From c8e28256650d9b49b46baf7ab5897518498173e8 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 3 Feb 2022 19:34:11 +0200 Subject: [PATCH 001/179] wip issue 1362 --- Core/package-lock.json | 46 +++++++++++++++++++++++++----------------- Core/package.json | 1 + 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/Core/package-lock.json b/Core/package-lock.json index 6e74a8ab6..bda5ff0da 100644 --- a/Core/package-lock.json +++ b/Core/package-lock.json @@ -10,6 +10,7 @@ "license": "SEE LICENSE IN ", "dependencies": { "encoding-japanese": "^1.0.30", + "openpgp": "5.1.0", "sanitize-html": "2.6.1", "zxcvbn": "4.4.2" }, @@ -832,7 +833,6 @@ "version": "5.4.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", - "dev": true, "dependencies": { "bn.js": "^4.0.0", "inherits": "^2.0.1", @@ -843,8 +843,7 @@ "node_modules/asn1.js/node_modules/bn.js": { "version": "4.12.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" }, "node_modules/assert": { "version": "1.5.0", @@ -4459,8 +4458,7 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/interpret": { "version": "2.2.0", @@ -5228,8 +5226,7 @@ "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" }, "node_modules/minimalistic-crypto-utils": { "version": "1.0.1", @@ -5605,6 +5602,17 @@ "wrappy": "1" } }, + "node_modules/openpgp": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/openpgp/-/openpgp-5.1.0.tgz", + "integrity": "sha512-keCno6QPMXWwfjrOOtT8fwZ5XgCcB7vZH80xb44SbJ49qQ11Efl2fFfqHpaie7jTQFjRKxgT8hSFPXJUjogNPw==", + "dependencies": { + "asn1.js": "^5.0.0" + }, + "engines": { + "node": ">= 8.0.0" + } + }, "node_modules/os-browserify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", @@ -6528,8 +6536,7 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/sanitize-html": { "version": "2.6.1", @@ -9150,7 +9157,6 @@ "version": "5.4.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", - "dev": true, "requires": { "bn.js": "^4.0.0", "inherits": "^2.0.1", @@ -9161,8 +9167,7 @@ "bn.js": { "version": "4.12.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" } } }, @@ -12143,8 +12148,7 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "interpret": { "version": "2.2.0", @@ -12736,8 +12740,7 @@ "minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" }, "minimalistic-crypto-utils": { "version": "1.0.1", @@ -13054,6 +13057,14 @@ "wrappy": "1" } }, + "openpgp": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/openpgp/-/openpgp-5.1.0.tgz", + "integrity": "sha512-keCno6QPMXWwfjrOOtT8fwZ5XgCcB7vZH80xb44SbJ49qQ11Efl2fFfqHpaie7jTQFjRKxgT8hSFPXJUjogNPw==", + "requires": { + "asn1.js": "^5.0.0" + } + }, "os-browserify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", @@ -13756,8 +13767,7 @@ "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "sanitize-html": { "version": "2.6.1", diff --git a/Core/package.json b/Core/package.json index c9f58f3f4..bfdcd2f91 100644 --- a/Core/package.json +++ b/Core/package.json @@ -4,6 +4,7 @@ "description": "TypeScript core for FlowCrypt iOS internal use", "dependencies": { "encoding-japanese": "^1.0.30", + "openpgp": "5.1.0", "sanitize-html": "2.6.1", "zxcvbn": "4.4.2" }, From 045c253653e3b0aa74861a5303998aeedb3d2558 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 3 Feb 2022 19:40:14 +0200 Subject: [PATCH 002/179] update local copy --- Core/source/core/types/openpgp.d.ts | 1903 +- Core/source/lib/openpgp.js | 77928 +++++++++++++------------- 2 files changed, 40133 insertions(+), 39698 deletions(-) diff --git a/Core/source/core/types/openpgp.d.ts b/Core/source/core/types/openpgp.d.ts index 6b0926394..c1b7bc831 100644 --- a/Core/source/core/types/openpgp.d.ts +++ b/Core/source/core/types/openpgp.d.ts @@ -1,1131 +1,886 @@ -// Type definitions for openpgpjs -// Project: http://openpgpjs.org/ -// Definitions by: Guillaume Lacasa -// Errietta Kostala -// FlowCrypt Limited -// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +/** + * Type definitions for OpenPGP.js http://openpgpjs.org/ + * + * Contributors: + * - FlowCrypt a. s. + * - Guillaume Lacasa + * - Errietta Kostala + */ + +/* ############## v5 KEY #################### */ +// The Key and PublicKey types can be used interchangably since TS cannot detect the difference, as they have the same class properties. +// The declared readKey(s) return type is Key instead of a PublicKey since it seems more obvious that a Key can be cast to a PrivateKey. +export function readKey(options: { armoredKey: string, config?: PartialConfig }): Promise; +export function readKey(options: { binaryKey: Uint8Array, config?: PartialConfig }): Promise; +export function readKeys(options: { armoredKeys: string, config?: PartialConfig }): Promise; +export function readKeys(options: { binaryKeys: Uint8Array, config?: PartialConfig }): Promise; +export function readPrivateKey(options: { armoredKey: string, config?: PartialConfig }): Promise; +export function readPrivateKey(options: { binaryKey: Uint8Array, config?: PartialConfig }): Promise; +export function readPrivateKeys(options: { armoredKeys: string, config?: PartialConfig }): Promise; +export function readPrivateKeys(options: { binaryKeys: Uint8Array, config?: PartialConfig }): Promise; +export function generateKey(options: KeyOptions & { format?: 'armored' }): Promise & { revocationCertificate: string }>; +export function generateKey(options: KeyOptions & { format: 'binary' }): Promise & { revocationCertificate: string }>; +export function generateKey(options: KeyOptions & { format: 'object' }): Promise; +export function decryptKey(options: { privateKey: PrivateKey; passphrase?: MaybeArray; config?: PartialConfig }): Promise; +export function encryptKey(options: { privateKey: PrivateKey; passphrase?: MaybeArray; config?: PartialConfig }): Promise; +export function reformatKey(options: { privateKey: PrivateKey; userIDs?: MaybeArray; passphrase?: string; keyExpirationTime?: number; date?: Date, format?: 'armored', config?: PartialConfig }): Promise & { revocationCertificate: string }>; +export function reformatKey(options: { privateKey: PrivateKey; userIDs?: MaybeArray; passphrase?: string; keyExpirationTime?: number; date?: Date, format: 'binary', config?: PartialConfig }): Promise & { revocationCertificate: string }>; +export function reformatKey(options: { privateKey: PrivateKey; userIDs?: MaybeArray; passphrase?: string; keyExpirationTime?: number; date?: Date, format: 'object', config?: PartialConfig }): Promise; +export function revokeKey(options: { key: PrivateKey, reasonForRevocation?: ReasonForRevocation, date?: Date, format?: 'armored', config?: PartialConfig }): Promise>; +export function revokeKey(options: { key: PrivateKey, reasonForRevocation?: ReasonForRevocation, date?: Date, format: 'binary', config?: PartialConfig }): Promise>; +export function revokeKey(options: { key: PrivateKey, reasonForRevocation?: ReasonForRevocation, date?: Date, format: 'object', config?: PartialConfig }): Promise; +export function revokeKey(options: { key: PrivateKey, revocationCertificate: string, date?: Date, format?: 'armored', config?: PartialConfig }): Promise>; +export function revokeKey(options: { key: PrivateKey, revocationCertificate: string, date?: Date, format: 'binary', config?: PartialConfig }): Promise>; +export function revokeKey(options: { key: PrivateKey, revocationCertificate: string, date?: Date, format: 'object', config?: PartialConfig }): Promise; +export function revokeKey(options: { key: PublicKey, revocationCertificate: string, date?: Date, format?: 'armored', config?: PartialConfig }): Promise<{ publicKey: string, privateKey: null }>; +export function revokeKey(options: { key: PublicKey, revocationCertificate: string, date?: Date, format: 'binary', config?: PartialConfig }): Promise<{ publicKey: Uint8Array, privateKey: null }>; +export function revokeKey(options: { key: PublicKey, revocationCertificate: string, date?: Date, format: 'object', config?: PartialConfig }): Promise<{ publicKey: PublicKey, privateKey: null }>; + +export abstract class Key { + public readonly keyPacket: PublicKeyPacket | SecretKeyPacket; + public subkeys: Subkey[]; // do not add/replace users directly + public users: User[]; // do not add/replace subkeys directly + public revocationSignatures: SignaturePacket[]; + public write(): Uint8Array; + public armor(config?: Config): string; + public getExpirationTime(userID?: UserID, config?: Config): Promise; + public getKeyIDs(): KeyID[]; + public getPrimaryUser(date?: Date, userID?: UserID, config?: Config): Promise; // throws on error + public getUserIDs(): string[]; + public isPrivate(): this is PrivateKey; + public toPublic(): PublicKey; + // NB: the order of the `update` declarations matters, since PublicKey includes PrivateKey + public update(sourceKey: PrivateKey, date?: Date, config?: Config): Promise; + public update(sourceKey: PublicKey, date?: Date, config?: Config): Promise; + public signPrimaryUser(privateKeys: PrivateKey[], date?: Date, userID?: UserID, config?: Config): Promise + public signAllUsers(privateKeys: PrivateKey[], date?: Date, config?: Config): Promise + public verifyPrimaryKey(date?: Date, userID?: UserID, config?: Config): Promise; // throws on error + public verifyPrimaryUser(publicKeys: PublicKey[], date?: Date, userIDs?: UserID, config?: Config): Promise<{ keyID: KeyID, valid: boolean | null }[]>; + public verifyAllUsers(publicKeys: PublicKey[], date?: Date, config?: Config): Promise<{ userID: string, keyID: KeyID, valid: boolean | null }[]>; + public isRevoked(signature: SignaturePacket, key?: AnyKeyPacket, date?: Date, config?: Config): Promise; + public getRevocationCertificate(date?: Date, config?: Config): Promise | undefined>; + public getEncryptionKey(keyID?: KeyID, date?: Date | null, userID?: UserID, config?: Config): Promise; + public getSigningKey(keyID?: KeyID, date?: Date | null, userID?: UserID, config?: Config): Promise; + public getKeys(keyID?: KeyID): (this | Subkey)[]; + public getSubkeys(keyID?: KeyID): Subkey[]; + public getFingerprint(): string; + public getCreationTime(): Date; + public getAlgorithmInfo(): AlgorithmInfo; + public getKeyID(): KeyID; + public toPacketList(): PacketList; +} -/* tslint:disable:only-arrow-functions variable-name max-line-length no-null-keyword ban-types */ +type AllowedKeyPackets = PublicKeyPacket | PublicSubkeyPacket | SecretKeyPacket | SecretSubkeyPacket | UserIDPacket | UserAttributePacket | SignaturePacket; +export class PublicKey extends Key { + constructor(packetlist: PacketList); +} -declare namespace OpenPGP { +export class PrivateKey extends PublicKey { + constructor(packetlist: PacketList); + public revoke(reason?: ReasonForRevocation, date?: Date, config?: Config): Promise; + public isDecrypted(): boolean; + public addSubkey(options: SubkeyOptions): Promise; + public getDecryptionKeys(keyID?: KeyID, date?: Date | null, userID?: UserID, config?: Config): Promise + public update(sourceKey: PublicKey, date?: Date, config?: Config): Promise; +} - type DataPacketType = 'utf8' | 'binary' | 'text' | 'mime'; +export class Subkey { + constructor(subkeyPacket: SecretSubkeyPacket | PublicSubkeyPacket, mainKey: PublicKey); + public readonly keyPacket: SecretSubkeyPacket | PublicSubkeyPacket; + public readonly mainKey: PublicKey; + public bindingSignatures: SignaturePacket[]; + public revocationSignatures: SignaturePacket[]; + public verify(date?: Date, config?: Config): Promise; + public isDecrypted(): boolean; + public getFingerprint(): string; + public getCreationTime(): Date; + public getAlgorithmInfo(): AlgorithmInfo; + public getKeyID(): KeyID; +} - export interface UserId { - name?: string; - email?: string; - } +export interface User { + userID: UserIDPacket | null; + userAttribute: UserAttributePacket | null; + selfCertifications: SignaturePacket[]; + otherCertifications: SignaturePacket[]; + revocationSignatures: SignaturePacket[]; +} - export interface SessionKey { - data: Uint8Array; - algorithm: string; - } +export interface PrimaryUser { + index: number; + user: User; +} - interface BaseStream { } - interface WebStream extends BaseStream { // copied+simplified version of ReadableStream from lib.dom.d.ts - readonly locked: boolean; cancel(reason?: any): Promise; getReader: Function; pipeThrough: Function; pipeTo: Function; tee: Function; - } - interface NodeStream extends BaseStream { // copied+simplified version of ReadableStream from @types/node/index.d.ts - readable: boolean; read(size?: number): string | Uint8Array; setEncoding(encoding: string): this; pause(): this; resume(): this; - isPaused(): boolean; pipe: Function; unpipe: Function; unshift(chunk: string | Uint8Array): void; wrap: Function; - } - type Stream = WebStream | NodeStream; +type AlgorithmInfo = { + algorithm: enums.publicKeyNames; + bits?: number; + curve?: EllipticCurveName; +}; - /** - * EncryptArmorOptions or EncryptBinaryOptions will be used based on armor option (boolean), defaults to armoring - */ - interface BaseEncryptOptions { - /** message to be encrypted as created by openpgp.message.fromText or openpgp.message.fromBinary */ - message: message.Message; - /** (optional) array of keys or single key, used to encrypt the message */ - publicKeys?: key.Key | key.Key[]; - /** (optional) private keys for signing. If omitted message will not be signed */ - privateKeys?: key.Key | key.Key[]; - /** (optional) array of passwords or a single password to encrypt the message */ - passwords?: string | string[]; - /** (optional) session key in the form: { data:Uint8Array, algorithm:String } */ - sessionKey?: SessionKey; - /** (optional) which compression algorithm to compress the message with, defaults to what is specified in config */ - compression?: enums.compression; - /** (optional) whether to return data as a stream. Defaults to the type of stream `message` was created from, if any. */ - streaming?: 'web' | 'node' | false; - /** (optional) if the signature should be detached (if true, signature will be added to returned object) */ - detached?: boolean; - /** (optional) a detached signature to add to the encrypted message */ - signature?: signature.Signature; - /** (optional) if the unencrypted session key should be added to returned object */ - returnSessionKey?: boolean; - /** (optional) encrypt as of a certain date */ - date?: Date; - /** (optional) use a key ID of 0 instead of the public key IDs */ - wildcard?: boolean; - /** (optional) user ID to sign with, e.g. { name:'Steve Sender', email:'steve@openpgp.org' } */ - fromUserId?: UserId; - /** (optional) user ID to encrypt for, e.g. { name:'Robert Receiver', email:'robert@openpgp.org' } */ - toUserId?: UserId; - } +/* ############## v5 SIG #################### */ - export type EncryptOptions = BaseEncryptOptions | EncryptArmorOptions | EncryptBinaryOptions; +export function readSignature(options: { armoredSignature: string, config?: PartialConfig }): Promise; +export function readSignature(options: { binarySignature: Uint8Array, config?: PartialConfig }): Promise; - export interface EncryptArmorOptions extends BaseEncryptOptions { - /** if the return values should be ascii armored or the message/signature objects */ - armor: true; - } +export class Signature { + public readonly packets: PacketList; + constructor(packetlist: PacketList); + public write(): MaybeStream; + public armor(config?: Config): string; + public getSigningKeyIDs(): Array; +} - export interface EncryptBinaryOptions extends BaseEncryptOptions { - /** if the return values should be ascii armored or the message/signature objects */ - armor: false; - } +interface VerificationResult { + keyID: KeyID; + verified: Promise; // throws on invalid signature + signature: Promise; +} - export namespace packet { - - export class List extends Array { - [index: number]: PACKET_TYPE; - length: number; - read(bytes: Uint8Array): void; - write(): Uint8Array; - push(...packet: PACKET_TYPE[]): number; - pop(): PACKET_TYPE; - filter(callback: (packet: PACKET_TYPE, i: number, self: List) => void): List; - filterByTag(...args: enums.packet[]): List; - forEach(callback: (packet: PACKET_TYPE, i: number, self: List) => void): void; - map(callback: (packet: PACKET_TYPE, i: number, self: List) => RETURN_TYPE): List; - // some() - // every() - // findPacket() - // indexOfTag() - // slice() - // concat() - // fromStructuredClone() - } - - function fromStructuredClone(packetClone: object): AnyPacket; - - function newPacketFromTag(tag: enums.packetNames): AnyPacket; - - class BasePacket { - tag: enums.packet; - read(bytes: Uint8Array): void; - write(): Uint8Array; - } - - class BaseKeyPacket extends BasePacket { - // fingerprint: Uint8Array|null; - not included because not recommended to use. Use getFingerprint() or getFingerprintBytes() - algorithm: enums.publicKey; - created: Date; - getBitSize(): number; - getAlgorithmInfo(): key.AlgorithmInfo; - getFingerprint(): string; - getFingerprintBytes(): Uint8Array | null; - getCreationTime(): Date; - getKeyId(): Keyid; - - version: number; - expirationTimeV3: number | null; - keyExpirationTime: number | null; - } - - class BasePrimaryKeyPacket extends BaseKeyPacket { - } - - export class Compressed extends BasePacket { - tag: enums.packet.compressed; - } - - export class SymEncryptedIntegrityProtected extends BasePacket { - tag: enums.packet.symEncryptedIntegrityProtected; - } - - export class SymEncryptedAEADProtected extends BasePacket { - tag: enums.packet.symEncryptedAEADProtected; - } - - export class PublicKeyEncryptedSessionKey extends BasePacket { - tag: enums.packet.publicKeyEncryptedSessionKey; - } - - export class SymEncryptedSessionKey extends BasePacket { - tag: enums.packet.symEncryptedSessionKey; - } - - export class Literal extends BasePacket { - tag: enums.packet.literal; - } - - export class PublicKey extends BasePrimaryKeyPacket { - tag: enums.packet.publicKey; - isDecrypted(): null; - } - - export class SymmetricallyEncrypted extends BasePacket { - tag: enums.packet.symmetricallyEncrypted; - } - - export class Marker extends BasePacket { - tag: enums.packet.marker; - } - - export class PublicSubkey extends BaseKeyPacket { - tag: enums.packet.publicSubkey; - isDecrypted(): null; - } - - export class UserAttribute extends BasePacket { - tag: enums.packet.userAttribute; - } - - export class OnePassSignature extends BasePacket { - tag: enums.packet.onePassSignature; - correspondingSig?: Promise; - } - - export class SecretKey extends BasePrimaryKeyPacket { - tag: enums.packet.secretKey; - isDecrypted(): boolean; - encrypt(passphrase: string): Promise; - decrypt(passphrase: string): Promise; - // encrypted: null | unknown[]; // Encrypted secret-key data, not meant for public use - s2k: { type: string } | null; - } - - export class Userid extends BasePacket { - tag: enums.packet.userid; - userid: string; - } - - export class SecretSubkey extends BaseKeyPacket { - tag: enums.packet.secretSubkey; - isDecrypted(): boolean; - encrypt(passphrase: string): Promise; - decrypt(passphrase: string): Promise; - // encrypted: null | unknown[]; // Encrypted secret-key data, not meant for public use - s2k: { type: string } | null; - } - - export class Signature extends BasePacket { - tag: enums.packet.signature; - version: number; - signatureType: null | number; - hashAlgorithm: null | number; - publicKeyAlgorithm: null | number; - signatureData: null | Uint8Array; - unhashedSubpackets: null | Uint8Array; - signedHashValue: null | Uint8Array; - created: Date; - signatureExpirationTime: null | number; - signatureNeverExpires: boolean; - exportable: null | boolean; - trustLevel: null | number; - trustAmount: null | number; - regularExpression: null | number; - revocable: null | boolean; - keyExpirationTime: null | number; - keyNeverExpires: null | boolean; - preferredSymmetricAlgorithms: null | number[]; - revocationKeyClass: null | number; - revocationKeyAlgorithm: null | number; - revocationKeyFingerprint: null | Uint8Array; - issuerKeyId: Keyid; - notation: null | { [name: string]: string }; - preferredHashAlgorithms: null | number[]; - preferredCompressionAlgorithms: null | number[]; - keyServerPreferences: null | number[]; - preferredKeyServer: null | string; - isPrimaryUserID: null | boolean; - policyURI: null | string; - keyFlags: null | number[]; - signersUserId: null | string; - reasonForRevocationFlag: null | number; - reasonForRevocationString: null | string; - features: null | number[]; - signatureTargetPublicKeyAlgorithm: null | number; - signatureTargetHashAlgorithm: null | number; - signatureTargetHash: null | string; - embeddedSignature: null | Signature; - issuerKeyVersion: null | number; - issuerFingerprint: null | Uint8Array; - preferredAeadAlgorithms: null | Uint8Array; - verified: null | boolean; - revoked: null | boolean; - sign(key: SecretKey | SecretSubkey, data: Uint8Array): true; - isExpired(date?: Date): boolean; - getExpirationTime(): Date | typeof Infinity; - } - - export class Trust extends BasePacket { - tag: enums.packet.trust; - } - - export type AnyPacket = Compressed | SymEncryptedIntegrityProtected | SymEncryptedAEADProtected | PublicKeyEncryptedSessionKey | SymEncryptedSessionKey | Literal - | PublicKey | SymmetricallyEncrypted | Marker | PublicSubkey | UserAttribute | OnePassSignature | SecretKey | Userid | SecretSubkey | Signature | Trust; - export type AnySecretPacket = SecretKey | SecretSubkey; - export type AnyKeyPacket = PublicKey | SecretKey | PublicSubkey | SecretSubkey; - } +/* ############## v5 CLEARTEXT #################### */ - export interface EncryptArmorResult { - data: string; - signature?: string; - } +export function readCleartextMessage(options: { cleartextMessage: string, config?: PartialConfig }): Promise; - export interface EncryptBinaryResult { - message: message.Message; - signature?: signature.Signature; - } +export function createCleartextMessage(options: { text: string }): Promise; - export type EncryptResult = EncryptArmorResult | EncryptBinaryResult; +/** Class that represents an OpenPGP cleartext signed message. + */ +export class CleartextMessage { + /** Returns ASCII armored text of cleartext signed message + */ + armor(config?: Config): string; - export interface SignArmorResult { - data: string | Stream; - signature: string | Stream; - } + /** Returns the key IDs of the keys that signed the cleartext message + */ + getSigningKeyIDs(): KeyID[]; - export interface SignBinaryResult { - message: message.Message | cleartext.CleartextMessage; - signature: signature.Signature; - } + /** Get cleartext + */ + getText(): string; - export type SignResult = SignArmorResult | SignBinaryResult; - - export interface DecryptOptions { - /** the message object with the encrypted data */ - message: message.Message; - /** (optional) private keys with decrypted secret key data or session key */ - privateKeys?: key.Key | key.Key[]; - /** (optional) passwords to decrypt the message */ - passwords?: string | string[]; - /** (optional) session keys in the form: { data:Uint8Array, algorithm:String } */ - sessionKeys?: SessionKey | SessionKey[]; - /** (optional) array of public keys or single key, to verify signatures */ - publicKeys?: key.Key | key.Key[]; - /** (optional) whether to return data as a string(Stream) or Uint8Array(Stream). If 'utf8' (the default), also normalize newlines. */ - format?: string; - /** (optional) whether to return data as a stream. Defaults to the type of stream `message` was created from, if any. */ - streaming?: 'web' | 'node' | false; - /** (optional) detached signature for verification */ - signature?: signature.Signature; - } + /** Sign the cleartext message + * + * @param privateKeys private keys with decrypted secret key data for signing + */ + sign(privateKeys: PrivateKey[], signature?: Signature, signingKeyIDs?: KeyID[], date?: Date, userIDs?: UserID[], config?: Config): void; - export interface SignOptions { - message: cleartext.CleartextMessage | message.Message; - privateKeys?: key.Key | key.Key[]; - armor?: boolean; - streaming?: 'web' | 'node' | false; - dataType?: DataPacketType; - detached?: boolean; - date?: Date; - fromUserId?: UserId; - } + /** Verify signatures of cleartext signed message + * @param keys array of keys to verify signatures + */ + verify(keys: PublicKey[], date?: Date, config?: Config): Promise; +} - export interface KeyContainer { - key: key.Key; - } +/* ############## v5 MSG #################### */ +export function generateSessionKey(options: { encryptionKeys: MaybeArray, date?: Date, encryptionUserIDs?: MaybeArray, config?: PartialConfig }): Promise; +export function encryptSessionKey(options: SessionKey & { + encryptionKeys?: MaybeArray, passwords?: MaybeArray, format?: 'armored', wildcard?: boolean, encryptionKeyIDs?: MaybeArray, date?: Date, encryptionUserIDs?: MaybeArray, config?: PartialConfig +}) : Promise; +export function encryptSessionKey(options: SessionKey & { + encryptionKeys?: MaybeArray, passwords?: MaybeArray, format: 'binary', wildcard?: boolean, encryptionKeyIDs?: MaybeArray, date?: Date, encryptionUserIDs?: MaybeArray, config?: PartialConfig +}) : Promise; +export function encryptSessionKey(options: SessionKey & { + encryptionKeys?: MaybeArray, passwords?: MaybeArray, format: 'object', wildcard?: boolean, encryptionKeyIDs?: MaybeArray, date?: Date, encryptionUserIDs?: MaybeArray, config?: PartialConfig +}) : Promise>; +export function decryptSessionKeys>(options: { message: Message, decryptionKeys?: MaybeArray, passwords?: MaybeArray, date?: Date, config?: PartialConfig }): Promise; + +export function readMessage>(options: { armoredMessage: T, config?: PartialConfig }): Promise>; +export function readMessage>(options: { binaryMessage: T, config?: PartialConfig }): Promise>; + +export function createMessage>(options: { text: T, filename?: string, date?: Date, format?: enums.literalFormatNames }): Promise>; +export function createMessage>(options: { binary: T, filename?: string, date?: Date, format?: enums.literalFormatNames }): Promise>; + +export function encrypt>(options: EncryptOptions & { message: Message, format?: 'armored' }): Promise< + T extends WebStream ? WebStream : + T extends NodeStream ? NodeStream : + string +>; +export function encrypt>(options: EncryptOptions & { message: Message, format: 'binary' }): Promise< + T extends WebStream ? WebStream : + T extends NodeStream ? NodeStream : + Uint8Array +>; +export function encrypt>(options: EncryptOptions & { message: Message, format: 'object' }): Promise>; + +export function sign>(options: SignOptions & { message: Message, format?: 'armored' }): Promise< + T extends WebStream ? WebStream : + T extends NodeStream ? NodeStream : + string +>; +export function sign>(options: SignOptions & { message: Message, format: 'binary' }): Promise< + T extends WebStream ? WebStream : + T extends NodeStream ? NodeStream : + Uint8Array +>; +export function sign>(options: SignOptions & { message: Message, format: 'object' }): Promise>; +export function sign(options: SignOptions & { message: CleartextMessage, format?: 'armored' }): Promise; +export function sign(options: SignOptions & { message: CleartextMessage, format: 'object' }): Promise; + +export function decrypt>(options: DecryptOptions & { message: Message, format: 'binary' }): Promise ? WebStream : + T extends NodeStream ? NodeStream : + Uint8Array +}>; +export function decrypt>(options: DecryptOptions & { message: Message }): Promise ? WebStream : + T extends NodeStream ? NodeStream : + string +}>; + +export function verify>(options: VerifyOptions & { message: Message, format: 'binary' }): Promise ? WebStream : + T extends NodeStream ? NodeStream : + Uint8Array +}>; +export function verify>(options: VerifyOptions & { message: Message }): Promise ? WebStream : + T extends NodeStream ? NodeStream : + string +}>; + +/** Class that represents an OpenPGP message. Can be an encrypted message, signed message, compressed message or literal message + */ +export class Message> { + + public readonly packets: PacketList; + constructor(packetlist: PacketList); + + /** Returns binary representation of message + */ + public write(): MaybeStream; - export interface KeyPair extends KeyContainer { - privateKeyArmored: string; - publicKeyArmored: string; - } + /** Returns ASCII armored text of message + */ + public armor(config?: Config): string; - export interface KeyOptions { - userIds: UserId[]; // generating a key with no user defined results in error - passphrase?: string; - numBits?: number; - keyExpirationTime?: number; - curve?: key.EllipticCurveName; - date?: Date; - subkeys?: KeyOptions[]; - } + /** Decrypt the message + @param decryptionKeys array of private keys with decrypted secret data + */ + public decrypt(decryptionKeys?: PrivateKey[], passwords?: string[], sessionKeys?: SessionKey[], date?: Date, config?: Config): Promise>>; - /** - * Intended for internal use with openpgp.key.generate() - * It's recommended that users choose openpgp.generateKey() that requires KeyOptions instead - */ - export interface FullKeyOptions { - userIds: UserId[]; - passphrase?: string; - numBits?: number; - keyExpirationTime?: number; - curve?: key.EllipticCurveName; - date?: Date; - subkeys: KeyOptions[]; // required unline KeyOptions.subkeys - } + /** Encrypt the message + @param encryptionKeys array of public keys, used to encrypt the message + */ + public encrypt(encryptionKeys?: PublicKey[], passwords?: string[], sessionKeys?: SessionKey[], wildcard?: boolean, encryptionKeyIDs?: KeyID[], date?: Date, userIDs?: UserID[], config?: Config): Promise>>; - export interface Keyid { - bytes: string; - } + /** Returns the key IDs of the keys to which the session key is encrypted + */ + public getEncryptionKeyIDs(): KeyID[]; - export interface DecryptMessageResult { - data: Uint8Array | string; - signatures: signature.Signature[]; - filename: string; - } + /** Get literal data that is the body of the message + */ + public getLiteralData(): MaybeStream | null; - export interface OpenPGPWorker { - randomCallback(): void; - configure(config: any): void; - seedRandom(buffer: ArrayBuffer): void; - delegate(id: number, method: string, options: any): void; - response(event: any): void; - } + /** Returns the key IDs of the keys that signed the message + */ + public getSigningKeyIDs(): KeyID[]; - export interface WorkerOptions { - path?: string; - n?: number; - workers?: OpenPGPWorker[]; - config?: any; - } + /** Get literal data as text + */ + public getText(): MaybeStream | null; - export class AsyncProxy { - constructor(options: WorkerOptions); - getId(): number; - seedRandom(workerId: number, size: number): Promise; - terminate(): void; - delegate(method: string, options: any): void; + public getFilename(): string | null; - workers: OpenPGPWorker[]; - } + /** Sign the message (the literal data packet of the message) + @param signingKeys private keys with decrypted secret key data for signing + */ + public sign(signingKeys: PrivateKey[], signature?: Signature, signingKeyIDs?: KeyID[], date?: Date, userIDs?: UserID[], config?: Config): Promise>; - /** - * Set the path for the web worker script and create an instance of the async proxy - * @param {String} path relative path to the worker scripts, default: 'openpgp.worker.js' - * @param {Number} n number of workers to initialize - * @param {Array} workers alternative to path parameter: web workers initialized with 'openpgp.worker.js' + /** Unwrap compressed message */ - export function initWorker(options: WorkerOptions): boolean; + public unwrapCompressed(): Message; - /** - * Returns a reference to the async proxy if the worker was initialized with openpgp.initWorker() - * @returns {module:worker/async_proxy.AsyncProxy|null} the async proxy or null if not initialized - */ - export function getWorker(): AsyncProxy; + /** Verify message signatures + @param verificationKeys array of public keys to verify signatures + */ + public verify(verificationKeys: PublicKey[], date?: Date, config?: Config): Promise; /** - * Cleanup the current instance of the web worker. + * Append signature to unencrypted message object + * @param {String|Uint8Array} detachedSignature - The detached ASCII-armored or Uint8Array PGP signature */ - export function destroyWorker(): void; + public appendSignature(detachedSignature: string | Uint8Array, config?: Config): Promise; +} - /** - * Encrypts message text/data with public keys, passwords or both at once. At least either public keys or passwords - * must be specified. If private keys are specified, those will be used to sign the message. - * @param {EncryptOptions} options See `EncryptOptions` - * @returns {Promise} Promise of `EncryptResult` (and optionally signed message) in the form: - * {data: ASCII armored message if 'armor' is true; - * message: full Message object if 'armor' is false, signature: detached signature if 'detached' is true} - * @async - * @static - */ - export function encrypt(options: EncryptBinaryOptions): Promise; - export function encrypt(options: EncryptArmorOptions | BaseEncryptOptions): Promise; - /** - * Signs a cleartext message. - * @param {String | Uint8Array} data cleartext input to be signed - * @param {utf8|binary|text|mime} dataType (optional) data packet type - * @param {Key|Array} privateKeys array of keys or single key with decrypted secret key data to sign cleartext - * @param {Boolean} armor (optional) if the return value should be ascii armored or the message object - * @param {Boolean} detached (optional) if the return value should contain a detached signature - * @param {Date} date (optional) override the creation date signature - * @param {Object} fromUserId (optional) user ID to sign with, e.g. { name:'Steve Sender', email:'steve@openpgp.org' } - * @returns {Promise} signed cleartext in the form: - * {data: ASCII armored message if 'armor' is true; - * message: full Message object if 'armor' is false, signature: detached signature if 'detached' is true} - * @async - * @static - */ - export function sign(options: SignOptions): Promise; +/* ############## v5 CONFIG #################### */ + +interface Config { + preferredHashAlgorithm: enums.hash; + preferredSymmetricAlgorithm: enums.symmetric; + preferredCompressionAlgorithm: enums.compression; + showVersion: boolean; + showComment: boolean; + deflateLevel: number; + aeadProtect: boolean; + allowUnauthenticatedMessages: boolean; + allowUnauthenticatedStream: boolean; + checksumRequired: boolean; + minRSABits: number; + passwordCollisionCheck: boolean; + revocationsExpire: boolean; + ignoreUnsupportedPackets: boolean; + ignoreMalformedPackets: boolean; + versionString: string; + commentString: string; + allowInsecureDecryptionWithSigningKeys: boolean; + constantTimePKCS1Decryption: boolean; + constantTimePKCS1DecryptionSupportedSymmetricAlgorithms: Set; + v5Keys: boolean; + preferredAEADAlgorithm: enums.aead; + aeadChunkSizeByte: number; + s2kIterationCountByte: number; + minBytesForWebCrypto: number; + maxUserIDLength: number; + knownNotations: string[]; + useIndutnyElliptic: boolean; + rejectHashAlgorithms: Set; + rejectMessageHashAlgorithms: Set; + rejectPublicKeyAlgorithms: Set; + rejectCurves: Set; +} +export var config: Config; - /** - * Decrypts a message with the user's private key, a session key or a password. Either a private key; - * a session key or a password must be specified. - * @param {DecryptOptions} options see `DecryptOptions` - * @returns {Promise} Promise of `DecryptMessageResult` and verified message in the form: - * { data:Uint8Array|String, filename:String, signatures:[{ keyid:String, valid:Boolean }] } - * @async - * @static - */ - export function decrypt(options: DecryptOptions): Promise; +// PartialConfig has the same properties as Config, but declared as optional. +// This interface is relevant for top-level functions, which accept a subset of configuration options +interface PartialConfig extends Partial {} - /** - * Generates a new OpenPGP key pair. Supports RSA and ECC keys. Primary and subkey will be of same type. - * @param {Array} userIds array of user IDs e.g. [{ name:'Phil Zimmermann', email:'phil@openpgp.org' }] - * @param {String} passphrase (optional) The passphrase used to encrypt the resulting private key - * @param {Number} numBits (optional) number of bits for RSA keys: 2048 or 4096. - * @param {Number} keyExpirationTime (optional) The number of seconds after the key creation time that the key expires - * @param {String} curve (optional) elliptic curve for ECC keys: - * curve25519, p256, p384, p521, secp256k1; - * brainpoolP256r1, brainpoolP384r1, or brainpoolP512r1. - * @param {Date} date (optional) override the creation date of the key and the key signatures - * @param {Array} subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}] - * sign parameter defaults to false, and indicates whether the subkey should sign rather than encrypt - * @returns {Promise} The generated key object in the form: - * { key:Key, privateKeyArmored:String, publicKeyArmored:String } - * @async - * @static - */ - export function generateKey(options: KeyOptions): Promise; +/* ############## v5 PACKET #################### */ - /** - * Reformats signature packets for a key and rewraps key object. - * @param {Key} privateKey private key to reformat - * @param {Array} userIds array of user IDs e.g. [{ name:'Phil Zimmermann', email:'phil@openpgp.org' }] - * @param {String} passphrase (optional) The passphrase used to encrypt the resulting private key - * @param {Number} keyExpirationTime (optional) The number of seconds after the key creation time that the key expires - * @returns {Promise} The generated key object in the form: - * { key:Key, privateKeyArmored:String, publicKeyArmored:String } - * @async - * @static - */ - export function reformatKey(options: { - privateKey: key.Key; - userIds?: (string | UserId)[]; - passphrase?: string; - keyExpirationTime?: number; - }): Promise; +declare abstract class BasePacket { + static readonly tag: enums.packet; + public read(bytes: Uint8Array): void; + public write(): Uint8Array; +} - /** - * Unlock a private key with your passphrase. - * @param {Key} privateKey the private key that is to be decrypted - * @param {String|Array} passphrase the user's passphrase(s) chosen during key generation - * @returns {Promise} the unlocked key object in the form: { key:Key } - * @async - */ - export function decryptKey(options: { - privateKey: key.Key; - passphrase?: string | string[]; - }): Promise; - - export function encryptKey(options: { - privateKey: key.Key; - passphrase?: string - }): Promise; - - export namespace armor { - /** Armor an OpenPGP binary packet block - * @param messagetype type of the message - * @param body - * @param partindex - * @param parttotal - */ - function armor(messagetype: enums.armor, body: object, partindex: number, parttotal: number): string; - - /** DeArmor an OpenPGP armored message; verify the checksum and return the encoded bytes - * - * @param text OpenPGP armored message - */ - function dearmor(text: string): object; - } +/** + * The relationship between the KeyPacket classes is modeled by considering the following: + * - A Secret (Sub)Key Packet can always be used when a Public one is expected. + * - A Subkey Packet cannot always be used when a Primary Key Packet is expected (and vice versa). + */ +declare abstract class BasePublicKeyPacket extends BasePacket { + public algorithm: enums.publicKey; + public created: Date; + public version: number; + public getAlgorithmInfo(): AlgorithmInfo; + public getFingerprint(): string; + public getFingerprintBytes(): Uint8Array | null; + public hasSameFingerprintAs(other: BasePublicKeyPacket): boolean; + public getCreationTime(): Date; + public getKeyID(): KeyID; + public isDecrypted(): boolean; + public publicParams: object; + // `isSubkey` is a dummy method to ensure that Subkey packets are not accepted as Key one, and vice versa. + // The key class hierarchy is already modelled to cover this, but the concrete key packet classes + // have compatible structure and TS can't detect the difference. + protected isSubkey(): boolean; +} - export namespace cleartext { - /** Class that represents an OpenPGP cleartext signed message. - */ - interface CleartextMessage { - /** Returns ASCII armored text of cleartext signed message - */ - armor(): string; - - /** Returns the key IDs of the keys that signed the cleartext message - */ - getSigningKeyIds(): Array; - - /** Get cleartext - */ - getText(): string; - - /** Sign the cleartext message - * - * @param privateKeys private keys with decrypted secret key data for signing - */ - sign(privateKeys: Array): void; - - /** Verify signatures of cleartext signed message - * @param keys array of keys to verify signatures - */ - verify(keys: key.Key[], date?: Date, streaming?: boolean): Promise; - } - - /** - * reads an OpenPGP cleartext signed message and returns a CleartextMessage object - * @param armoredText text to be parsed - * @returns new cleartext message object - * @async - * @static - */ - function readArmored(armoredText: string): Promise; - - function fromText(text: string): CleartextMessage; - } +export class PublicKeyPacket extends BasePublicKeyPacket { + static readonly tag: enums.packet.publicKey; + protected isSubkey(): false; +} - export namespace config { - let prefer_hash_algorithm: enums.hash; - let encryption_cipher: enums.symmetric; - let compression: enums.compression; - let show_version: boolean; - let show_comment: boolean; - let integrity_protect: boolean; - let debug: boolean; - let deflate_level: number; - let aead_protect: boolean; - let ignore_mdc_error: boolean; - let checksum_required: boolean; - let rsa_blinding: boolean; - let password_collision_check: boolean; - let revocations_expire: boolean; - let use_native: boolean; - let zero_copy: boolean; - let tolerant: boolean; - let versionstring: string; - let commentstring: string; - let keyserver: string; - let node_store: string; - } +export class PublicSubkeyPacket extends BasePublicKeyPacket { + static readonly tag: enums.packet.publicSubkey; + protected isSubkey(): true; +} - export namespace crypto { - interface Mpi { - data: number; - read(input: string): number; - write(): string; - } - - /** Generating a session key for the specified symmetric algorithm - * @param algo Algorithm to use - */ - function generateSessionKey(algo: enums.symmetric): string; - - /** generate random byte prefix as string for the specified algorithm - * @param algo Algorithm to use - */ - function getPrefixRandom(algo: enums.symmetric): string; - - /** Returns the number of integers comprising the private key of an algorithm - * @param algo The public key algorithm - */ - function getPrivateMpiCount(algo: enums.symmetric): number; - - /** Decrypts data using the specified public key multiprecision integers of the private key, the specified secretMPIs of the private key and the specified algorithm. - @param algo Algorithm to be used - @param publicMPIs Algorithm dependent multiprecision integers of the public key part of the private key - @param secretMPIs Algorithm dependent multiprecision integers of the private key used - @param data Data to be encrypted as MPI - */ - function publicKeyDecrypt(algo: enums.publicKey, publicMPIs: Array, secretMPIs: Array, data: Mpi): Mpi; - - /** Encrypts data using the specified public key multiprecision integers and the specified algorithm. - @param algo Algorithm to be used - @param publicMPIs Algorithm dependent multiprecision integers - @param data Data to be encrypted as MPI - */ - function publicKeyEncrypt(algo: enums.publicKey, publicMPIs: Array, data: Mpi): Array; - - namespace cfb { - /** This function decrypts a given plaintext using the specified blockcipher to decrypt a message - @param cipherfn the algorithm cipher class to decrypt data in one block_size encryption - @param key binary string representation of key to be used to decrypt the ciphertext. This will be passed to the cipherfn - @param ciphertext to be decrypted provided as a string - @param resync a boolean value specifying if a resync of the IV should be used or not. The encrypteddatapacket uses the "old" style with a resync. Decryption within an encryptedintegrityprotecteddata packet is not resyncing the IV. - */ - function decrypt(cipherfn: string, key: string, ciphertext: string, resync: boolean): string; - - /** This function encrypts a given with the specified prefixrandom using the specified blockcipher to encrypt a message - @param prefixrandom random bytes of block_size length provided as a string to be used in prefixing the data - @param cipherfn the algorithm cipher class to encrypt data in one block_size encryption - @param plaintext data to be encrypted provided as a string - @param key binary string representation of key to be used to encrypt the plaintext. This will be passed to the cipherfn - @param resync a boolean value specifying if a resync of the IV should be used or not. The encrypteddatapacket uses the "old" style with a resync. Encryption within an encryptedintegrityprotecteddata packet is not resyncing the IV. - */ - function encrypt(prefixrandom: string, cipherfn: string, plaintext: string, key: string, resync: boolean): string; - - /** Decrypts the prefixed data for the Modification Detection Code (MDC) computation - @param cipherfn cipherfn.encrypt Cipher function to use - @param key binary string representation of key to be used to check the mdc This will be passed to the cipherfn - @param ciphertext The encrypted data - */ - function mdc(cipherfn: object, key: string, ciphertext: string): string; - } - - namespace hash { - /** Create a hash on the specified data using the specified algorithm - @param algo Hash algorithm type - @param data Data to be hashed - */ - function digest(algo: enums.hash, data: Uint8Array): Promise; - - /** Returns the hash size in bytes of the specified hash algorithm type - @param algo Hash algorithm type - */ - function getHashByteLength(algo: enums.hash): number; - } - - namespace random { - /** Retrieve secure random byte string of the specified length - @param length Length in bytes to generate - */ - function getRandomBytes(length: number): Promise; - } - - namespace signature { - /** Create a signature on data using the specified algorithm - @param hash_algo hash Algorithm to use - @param algo Asymmetric cipher algorithm to use - @param publicMPIs Public key multiprecision integers of the private key - @param secretMPIs Private key multiprecision integers which is used to sign the data - @param data Data to be signed - */ - function sign(hash_algo: enums.hash, algo: enums.publicKey, publicMPIs: Array, secretMPIs: Array, data: string): Mpi; - - /** - @param algo public Key algorithm - @param hash_algo Hash algorithm - @param msg_MPIs Signature multiprecision integers - @param publickey_MPIs Public key multiprecision integers - @param data Data on where the signature was computed on - */ - function verify(algo: enums.publicKey, hash_algo: enums.hash, msg_MPIs: Array, publickey_MPIs: Array, data: string): boolean; - } - } +declare abstract class BaseSecretKeyPacket extends BasePublicKeyPacket { + public privateParams: object | null; + public encrypt(passphrase: string, config?: Config): Promise; // throws on error + public decrypt(passphrase: string): Promise; // throws on error + public validate(): Promise; // throws on error + public isDummy(): boolean; + public makeDummy(config?: Config): void; +} - export namespace enums { - - function read(type: typeof armor, e: armor): armorNames | string | any; - function read(type: typeof compression, e: compression): compressionNames | string | any; - function read(type: typeof hash, e: hash): hashNames | string | any; - function read(type: typeof packet, e: packet): packetNames | string | any; - function read(type: typeof publicKey, e: publicKey): publicKeyNames | string | any; - function read(type: typeof symmetric, e: symmetric): symmetricNames | string | any; - function read(type: typeof keyStatus, e: keyStatus): keyStatusNames | string | any; - function read(type: typeof keyFlags, e: keyFlags): keyFlagsNames | string | any; - - export type armorNames = 'multipart_section' | 'multipart_last' | 'signed' | 'message' | 'public_key' | 'private_key'; - enum armor { - multipart_section = 0, - multipart_last = 1, - signed = 2, - message = 3, - public_key = 4, - private_key = 5, - signature = 6, - } - - enum reasonForRevocation { - no_reason = 0, // No reason specified (key revocations or cert revocations) - key_superseded = 1, // Key is superseded (key revocations) - key_compromised = 2, // Key material has been compromised (key revocations) - key_retired = 3, // Key is retired and no longer used (key revocations) - userid_invalid = 32, // User ID information is no longer valid (cert revocations) - } - - export type compressionNames = 'uncompressed' | 'zip' | 'zlib' | 'bzip2'; - enum compression { - uncompressed = 0, - zip = 1, - zlib = 2, - bzip2 = 3, - } - - export type hashNames = 'md5' | 'sha1' | 'ripemd' | 'sha256' | 'sha384' | 'sha512' | 'sha224'; - enum hash { - md5 = 1, - sha1 = 2, - ripemd = 3, - sha256 = 8, - sha384 = 9, - sha512 = 10, - sha224 = 11, - } - - export type packetNames = 'publicKeyEncryptedSessionKey' | 'signature' | 'symEncryptedSessionKey' | 'onePassSignature' | 'secretKey' | 'publicKey' - | 'secretSubkey' | 'compressed' | 'symmetricallyEncrypted' | 'marker' | 'literal' | 'trust' | 'userid' | 'publicSubkey' | 'userAttribute' - | 'symEncryptedIntegrityProtected' | 'modificationDetectionCode' | 'symEncryptedAEADProtected'; - enum packet { - publicKeyEncryptedSessionKey = 1, - signature = 2, - symEncryptedSessionKey = 3, - onePassSignature = 4, - secretKey = 5, - publicKey = 6, - secretSubkey = 7, - compressed = 8, - symmetricallyEncrypted = 9, - marker = 10, - literal = 11, - trust = 12, - userid = 13, - publicSubkey = 14, - userAttribute = 17, - symEncryptedIntegrityProtected = 18, - modificationDetectionCode = 19, - symEncryptedAEADProtected = 20, - } - - export type publicKeyNames = 'rsa_encrypt_sign' | 'rsa_encrypt' | 'rsa_sign' | 'elgamal' | 'dsa' | 'ecdh' | 'ecdsa' | 'eddsa' | 'aedh' | 'aedsa'; - enum publicKey { - rsa_encrypt_sign = 1, - rsa_encrypt = 2, - rsa_sign = 3, - elgamal = 16, - dsa = 17, - ecdh = 18, - ecdsa = 19, - eddsa = 22, - aedh = 23, - aedsa = 24, - } - - export type symmetricNames = 'plaintext' | 'idea' | 'tripledes' | 'cast5' | 'blowfish' | 'aes128' | 'aes192' | 'aes256' | 'twofish'; - enum symmetric { - plaintext = 0, - idea = 1, - tripledes = 2, - cast5 = 3, - blowfish = 4, - aes128 = 7, - aes192 = 8, - aes256 = 9, - twofish = 10, - } - - export type keyStatusNames = 'invalid' | 'expired' | 'revoked' | 'valid' | 'no_self_cert'; - enum keyStatus { - invalid = 0, - expired = 1, - revoked = 2, - valid = 3, - no_self_cert = 4, - } - - export type keyFlagsNames = 'certify_keys' | 'sign_data' | 'encrypt_communication' | 'encrypt_storage' | 'split_private_key' | 'authentication' - | 'shared_private_key'; - enum keyFlags { - certify_keys = 1, - sign_data = 2, - encrypt_communication = 4, - encrypt_storage = 8, - split_private_key = 16, - authentication = 32, - shared_private_key = 128, - } +export class SecretKeyPacket extends BaseSecretKeyPacket { + static readonly tag: enums.packet.secretKey; + protected isSubkey(): false; +} - } +export class SecretSubkeyPacket extends BaseSecretKeyPacket { + static readonly tag: enums.packet.secretSubkey; + protected isSubkey(): true; +} - export namespace key { - - export type EllipticCurveName = 'curve25519' | 'p256' | 'p384' | 'p521' | 'secp256k1' | 'brainpoolP256r1' | 'brainpoolP384r1' | 'brainpoolP512r1'; - - /** Class that represents an OpenPGP key. Must contain a primary key. Can contain additional subkeys, signatures, user ids, user attributes. - */ - class Key { - constructor(packetlist: packet.List); - armor(): string; - decrypt(passphrase: string | string[], keyId?: Keyid): Promise; - encrypt(passphrase: string | string[]): Promise; - getExpirationTime(capability?: 'encrypt' | 'encrypt_sign' | 'sign' | null, keyId?: Keyid | null, userId?: UserId | null): Promise; // Returns null if `capabilities` is passed and the key does not have the specified capabilities or is revoked or invalid. - getKeyIds(): Keyid[]; - getPrimaryUser(): Promise; - getUserIds(): string[]; - isPrivate(): boolean; - isPublic(): boolean; - toPublic(): Key; - update(key: Key): void; - verifyPrimaryKey(): Promise; - isRevoked(): Promise; - revoke(reason: { flag?: enums.reasonForRevocation; string?: string; }, date?: Date): Promise; - getRevocationCertificate(): Promise | string | undefined>; - getEncryptionKey(keyid?: Keyid | null, date?: Date, userId?: UserId | null): Promise; - getSigningKey(): Promise; - getKeys(keyId?: Keyid): (Key | SubKey)[]; - // isDecrypted(): boolean; - isFullyEncrypted(): boolean; - isFullyDecrypted(): boolean; - isPacketDecrypted(keyId: Keyid): boolean; - getFingerprint(): string; - getCreationTime(): Date; - getAlgorithmInfo(): AlgorithmInfo; - getKeyId(): Keyid; - primaryKey: packet.PublicKey | packet.SecretKey; - subKeys: SubKey[]; - users: User[]; - revocationSignatures: packet.Signature[]; - keyPacket: packet.PublicKey | packet.SecretKey; - } - - class SubKey { - constructor(subKeyPacket: packet.SecretSubkey | packet.PublicSubkey); - subKey: packet.SecretSubkey | packet.PublicSubkey; - keyPacket: packet.SecretKey; - bindingSignatures: packet.Signature[]; - revocationSignatures: packet.Signature[]; - verify(primaryKey: packet.PublicKey | packet.SecretKey): Promise; - isDecrypted(): boolean; - getFingerprint(): string; - getCreationTime(): Date; - getAlgorithmInfo(): AlgorithmInfo; - getKeyId(): Keyid; - } - - export interface User { - userId: packet.Userid | null; - userAttribute: packet.UserAttribute | null; - selfCertifications: packet.Signature[]; - otherCertifications: packet.Signature[]; - revocationSignatures: packet.Signature[]; - } - - export interface PrimaryUser { - index: number; - user: User; - } - - interface KeyResult { - keys: Key[]; - err?: Error[]; - } - - type AlgorithmInfo = { - algorithm: enums.publicKeyNames; - bits: number; - }; - - /** Generates a new OpenPGP key. Currently only supports RSA keys. Primary and subkey will be of same type. - * @param options - */ - function generate(options: FullKeyOptions): Promise; - - /** Reads an OpenPGP armored text and returns one or multiple key objects - - @param armoredText text to be parsed - */ - function readArmored(armoredText: string): Promise; - - /** Reads an OpenPGP binary data and returns one or multiple key objects - - @param data to be parsed - */ - function read(data: Uint8Array): Promise; - } +export class CompressedDataPacket extends BasePacket { + static readonly tag: enums.packet.compressedData; + private compress(): void; + private decompress(config?: Config): void; +} - export namespace signature { - class Signature { - constructor(packetlist: packet.List); - armor(): string; - packets: packet.List; - } +export class SymEncryptedIntegrityProtectedDataPacket extends BasePacket { + static readonly tag: enums.packet.symEncryptedIntegrityProtectedData; +} - /** reads an OpenPGP armored signature and returns a signature object +export class AEADEncryptedDataPacket extends BasePacket { + static readonly tag: enums.packet.aeadEncryptedData; + private decrypt(sessionKeyAlgorithm: enums.symmetric, sessionKey: Uint8Array, config?: Config): void; + private encrypt(sessionKeyAlgorithm: enums.symmetric, sessionKey: Uint8Array, config?: Config): void; + private crypt(fn: Function, sessionKey: Uint8Array, data: MaybeStream): MaybeStream +} - @param armoredText text to be parsed - */ - function readArmored(armoredText: string): Promise; +export class PublicKeyEncryptedSessionKeyPacket extends BasePacket { + static readonly tag: enums.packet.publicKeyEncryptedSessionKey; + private decrypt(keyPacket: SecretKeyPacket): void; // throws on error + private encrypt(keyPacket: PublicKeyPacket): void; // throws on error +} - /** reads an OpenPGP signature as byte array and returns a signature object +export class SymEncryptedSessionKey extends BasePacket { + static readonly tag: enums.packet.symEncryptedSessionKey; + private decrypt(passphrase: string): Promise; + private encrypt(passphrase: string, config?: Config): Promise; +} - @param input binary signature - */ - function read(input: Uint8Array): Promise; - } +export class LiteralDataPacket extends BasePacket { + static readonly tag: enums.packet.literalData; + private getText(clone?: boolean): MaybeStream; + private getBytes(clone?: boolean): MaybeStream; + private setText(text: MaybeStream, format?: enums.literal); + private setBytes(bytes: MaybeStream, format: enums.literal); + private setFilename(filename: string); + private getFilename(): string; + private writeHeader(): Uint8Array; +} - export namespace message { - /** Class that represents an OpenPGP message. Can be an encrypted message, signed message, compressed message or literal message - */ - class Message { - constructor(packetlist: packet.List); - - /** Returns ASCII armored text of message - */ - armor(): string; - - /** Decrypt the message - @param privateKey private key with decrypted secret data - */ - decrypt(privateKeys?: key.Key[] | null, passwords?: string[] | null, sessionKeys?: SessionKey[] | null, streaming?: boolean): Promise; - - /** Encrypt the message - @param keys array of keys, used to encrypt the message - */ - encrypt(keys: key.Key[]): Promise; - - /** Returns the key IDs of the keys to which the session key is encrypted - */ - getEncryptionKeyIds(): Keyid[]; - - /** Get literal data that is the body of the message - */ - getLiteralData(): Uint8Array | null | Stream; - - /** Returns the key IDs of the keys that signed the message - */ - getSigningKeyIds(): Keyid[]; - - /** Get literal data as text - */ - getText(): string | null | Stream; - - getFilename(): string | null; - - /** Sign the message (the literal data packet of the message) - @param privateKey private keys with decrypted secret key data for signing - */ - sign(privateKey: key.Key[]): Promise; - - /** Unwrap compressed message - */ - unwrapCompressed(): Message; - - /** Verify message signatures - @param keys array of keys to verify signatures - */ - verify(keys: key.Key[], date?: Date, streaming?: boolean): Promise; - - /** - * Append signature to unencrypted message object - * @param {String|Uint8Array} detachedSignature The detached ASCII-armored or Uint8Array PGP signature - */ - appendSignature(detachedSignature: string | Uint8Array): Promise; - - packets: packet.List; - } - - class SessionKey { // todo - - } - - export interface Verification { - keyid: Keyid; - verified: Promise; - signature: Promise; - } - - /** creates new message object from binary data - @param bytes - */ - function fromBinary(bytes: Uint8Array | Stream, filename?: string, date?: Date, type?: DataPacketType): Message; - - /** creates new message object from text - @param text - */ - function fromText(text: string | Stream, filename?: string, date?: Date, type?: DataPacketType): Message; - - /** reads an OpenPGP armored message and returns a message object - - @param armoredText text to be parsed - */ - function readArmored(armoredText: string | Stream): Promise; - - /** - * reads an OpenPGP message as byte array and returns a message object - * @param {Uint8Array} input binary message - * @returns {Message} new message object - * @static - */ - function read(input: Uint8Array): Promise; - } +export class SymmetricallyEncryptedDataPacket extends BasePacket { + static readonly tag: enums.packet.symmetricallyEncryptedData; + private decrypt(sessionKeyAlgorithm: enums.symmetric, sessionKey: Uint8Array, config?: Config): void; + private encrypt(sessionKeyAlgorithm: enums.symmetric, sessionKey: Uint8Array, config?: Config): void; +} - export class HKP { - constructor(keyServerBaseUrl?: string); - lookup(options: { keyid?: string, query?: string }): Promise; - } +export class MarkerPacket extends BasePacket { + static readonly tag: enums.packet.marker; +} - /** - * todo - some of these are outdated - check OpenPGP.js api - */ - export namespace util { - /** Convert an array of integers(0.255) to a string - @param bin An array of (binary) integers to convert - */ - function bin2str(bin: Array): string; - - /** Calculates a 16bit sum of a string by adding each character codes modulus 65535 - @param text string to create a sum of - */ - function calc_checksum(text: string): number; - - /** Convert a string of utf8 bytes to a native javascript string - @param utf8 A valid squence of utf8 bytes - */ - function decode_utf8(utf8: string): string; - - /** Convert a native javascript string to a string of utf8 bytes - param str The string to convert - */ - function encode_utf8(str: string): string; - - /** Return the algorithm type as string - */ - function get_hashAlgorithmString(): string; - - /** Get native Web Cryptography api. The default configuration is to use the api when available. But it can also be deactivated with config.useWebCrypto - */ - function getWebCrypto(): object; - - /** Helper function to print a debug message. Debug messages are only printed if - @param str string of the debug message - */ - function print_debug(str: string): void; - - /** Helper function to print a debug message. Debug messages are only printed if - @param str string of the debug message - */ - function print_debug_hexstr_dump(str: string): void; - - /** Shifting a string to n bits right - @param value The string to shift - @param bitcount Amount of bits to shift (MUST be smaller than 9) - */ - function shiftRight(value: string, bitcount: number): string; - - /** - * Convert a string to an array of 8-bit integers - * @param {String} str String to convert - * @returns {Uint8Array} An array of 8-bit integers - */ - function str_to_Uint8Array(str: string): Uint8Array; - - /** - * Convert an array of 8-bit integers to a string - * @param {Uint8Array} bytes An array of 8-bit integers to convert - * @returns {String} String representation of the array - */ - function Uint8Array_to_str(bin: Uint8Array): string; - - /** - * Convert an array of 8-bit integers to a hex string - * @param {Uint8Array} bytes Array of 8-bit integers to convert - * @returns {String} Hexadecimal representation of the array - */ - function Uint8Array_to_hex(bytes: Uint8Array): string; - - /** - * Convert a hex string to an array of 8-bit integers - * @param {String} hex A hex string to convert - * @returns {Uint8Array} An array of 8-bit integers - */ - function hex_to_Uint8Array(hex: string): Uint8Array; - - /** - * Create hex string from a binary - * @param {String} str String to convert - * @returns {String} String containing the hexadecimal values - */ - function str_to_hex(str: string): string; - - /** - * Create binary string from a hex encoded string - * @param {String} str Hex string to convert - * @returns {String} - */ - function hex_to_str(hex: string): string; - - function parseUserId(userid: string): UserId; - - function formatUserId(userid: UserId): string; - - function normalizeDate(date: Date | null): Date | null; - } +export class UserAttributePacket extends BasePacket { + static readonly tag: enums.packet.userAttribute; + private equals(packet: UserAttributePacket): boolean; +} - export namespace stream { - function readToEnd(input: Stream | T, concat?: (list: T[]) => T): Promise; - // concat - // slice - // clone - // webToNode - // nodeToWeb - } +export class OnePassSignaturePacket extends BasePacket { + static readonly tag: enums.packet.onePassSignature; + public correspondingSig?: Promise; + private verify: SignaturePacket['verify']; +} + +export class UserIDPacket extends BasePacket { + static readonly tag: enums.packet.userID; + public readonly name: string; + public readonly comment: string; + public readonly email: string; + public readonly userID: string; + static fromObject(userID: UserID): UserIDPacket; +} + +export class SignaturePacket extends BasePacket { + static readonly tag: enums.packet.signature; + public version: number; + public signatureType: enums.signature | null; + public hashAlgorithm: enums.hash | null; + public publicKeyAlgorithm: enums.publicKey | null; + public signatureData: null | Uint8Array; + public unhashedSubpackets: null | Uint8Array; + public signedHashValue: null | Uint8Array; + public created: Date | null; + public signatureExpirationTime: null | number; + public signatureNeverExpires: boolean; + public exportable: null | boolean; + public trustLevel: null | number; + public trustAmount: null | number; + public regularExpression: null | number; + public revocable: null | boolean; + public keyExpirationTime: null | number; + public keyNeverExpires: null | boolean; + public preferredSymmetricAlgorithms: enums.symmetric[] | null; + public revocationKeyClass: null | number; + public revocationKeyAlgorithm: null | enums.publicKey; + public revocationKeyFingerprint: null | Uint8Array; + public issuerKeyID: KeyID; + public notation: null | { [name: string]: string }; + public preferredHashAlgorithms: enums.hash[] | null; + public preferredCompressionAlgorithms: enums.compression[] | null; + public keyServerPreferences: null | number[]; + public preferredKeyServer: null | string; + public isPrimaryUserID: null | boolean; + public policyURI: null | string; + public keyFlags: Uint8Array | null; + public signersUserID: null | string; + public reasonForRevocationFlag: null | enums.reasonForRevocation; + public reasonForRevocationString: null | string; + public features: Uint8Array | null; + public signatureTargetPublicKeyAlgorithm: enums.publicKey | null; + public signatureTargetHashAlgorithm: enums.hash | null; + public signatureTargetHash: null | string; + public embeddedSignature: null | SignaturePacket; + public issuerKeyVersion: null | number; + public issuerFingerprint: null | Uint8Array; + public preferredAEADAlgorithms: enums.aead[] | null; + public verified: null | boolean; + public revoked: null | boolean; + public sign(key: AnySecretKeyPacket, data: Uint8Array, date?: Date, detached?: boolean): Promise; + public verify(key: AnyKeyPacket, signatureType: enums.signature, data: Uint8Array, date?: Date, detached?: boolean, config?: Config): Promise; // throws on error + public isExpired(date?: Date): boolean; + public getExpirationTime(): Date | typeof Infinity; +} + +export class TrustPacket extends BasePacket { + static readonly tag: enums.packet.trust; +} +export type AnyPacket = BasePacket; +export type AnySecretKeyPacket = SecretKeyPacket | SecretSubkeyPacket; +export type AnyKeyPacket = BasePublicKeyPacket; + +type AllowedPackets = Map; // mapping to Packet classes (i.e. typeof LiteralDataPacket etc.) +export class PacketList extends Array { + static fromBinary(bytes: MaybeStream, allowedPackets: AllowedPackets, config?: Config): PacketList; // the packet types depend on`allowedPackets` + public read(bytes: MaybeStream, allowedPackets: AllowedPackets, config?: Config): void; + public write(): Uint8Array; + public filterByTag(...args: enums.packet[]): PacketList; + public indexOfTag(...tags: enums.packet[]): number[]; + public findPacket(tag: enums.packet): T | undefined; +} + +/* ############## v5 STREAM #################### */ + +type Data = Uint8Array | string; +interface BaseStream extends AsyncIterable { } +interface WebStream extends BaseStream { // copied+simplified version of ReadableStream from lib.dom.d.ts + readonly locked: boolean; getReader: Function; pipeThrough: Function; pipeTo: Function; tee: Function; + cancel(reason?: any): Promise; +} +interface NodeStream extends BaseStream { // copied+simplified version of ReadableStream from @types/node/index.d.ts + readable: boolean; pipe: Function; unpipe: Function; wrap: Function; + read(size?: number): string | Uint8Array; setEncoding(encoding: string): this; pause(): this; resume(): this; + isPaused(): boolean; unshift(chunk: string | Uint8Array): void; +} +type Stream = WebStream | NodeStream; +type MaybeStream = T | Stream; + +/* ############## v5 GENERAL #################### */ +type MaybeArray = T | Array; + +export interface UserID { name?: string; email?: string; comment?: string; } +export interface SessionKey { + data: Uint8Array; + algorithm: enums.symmetricNames; + aeadAlgorithm?: enums.aeadNames; +} + +export interface ReasonForRevocation { flag?: enums.reasonForRevocation, string?: string } + +interface EncryptOptions { + /** message to be encrypted as created by createMessage */ + message: Message>; + /** (optional) array of keys or single key, used to encrypt the message */ + encryptionKeys?: MaybeArray; + /** (optional) private keys for signing. If omitted message will not be signed */ + signingKeys?: MaybeArray; + /** (optional) array of passwords or a single password to encrypt the message */ + passwords?: MaybeArray; + /** (optional) session key */ + sessionKey?: SessionKey; + /** if the return values should be ascii armored or the message/signature objects */ + format?: 'armored' | 'binary' | 'object'; + /** (optional) if the signature should be detached (if true, signature will be added to returned object) */ + signature?: Signature; + /** (optional) encrypt as of a certain date */ + date?: Date; + /** (optional) use a key ID of 0 instead of the public key IDs */ + wildcard?: boolean; + /** (optional) Array of key IDs to use for signing. Each `signingKeyIDs[i]` corresponds to `signingKeys[i]` */ + signingKeyIDs?: MaybeArray; + /** (optional) Array of key IDs to use for encryption. Each `encryptionKeyIDs[i]` corresponds to `encryptionKeys[i]`*/ + encryptionKeyIDs?: MaybeArray; + /** (optional) Array of user IDs to sign with, e.g. { name:'Steve Sender', email:'steve@openpgp.org' } */ + signingUserIDs?: MaybeArray; + /** (optional) array of user IDs to encrypt for, e.g. { name:'Robert Receiver', email:'robert@openpgp.org' } */ + encryptionUserIDs?: MaybeArray; + config?: PartialConfig; +} + +interface DecryptOptions { + /** the message object with the encrypted data */ + message: Message>; + /** (optional) private keys with decrypted secret key data or session key */ + decryptionKeys?: MaybeArray; + /** (optional) passwords to decrypt the message */ + passwords?: MaybeArray; + /** (optional) session keys in the form: { data:Uint8Array, algorithm:String } */ + sessionKeys?: MaybeArray; + /** (optional) array of public keys or single key, to verify signatures */ + verificationKeys?: MaybeArray; + /** (optional) whether data decryption should fail if the message is not signed with the provided publicKeys */ + expectSigned?: boolean; + /** (optional) whether to return data as a string(Stream) or Uint8Array(Stream). If 'utf8' (the default), also normalize newlines. */ + format?: 'utf8' | 'binary'; + /** (optional) detached signature for verification */ + signature?: Signature; + /** (optional) use the given date for verification instead of the current time */ + date?: Date; + config?: PartialConfig; +} + +interface SignOptions { + message: CleartextMessage | Message>; + signingKeys?: MaybeArray; + format?: 'armored' | 'binary' | 'object'; + detached?: boolean; + signingKeyIDs?: MaybeArray; + date?: Date; + signingUserIDs?: MaybeArray; + config?: PartialConfig; +} + +interface VerifyOptions { + /** (cleartext) message object with signatures */ + message: CleartextMessage | Message>; + /** array of publicKeys or single key, to verify signatures */ + verificationKeys: MaybeArray; + /** (optional) whether verification should throw if the message is not signed with the provided publicKeys */ + expectSigned?: boolean; + /** (optional) whether to return data as a string(Stream) or Uint8Array(Stream). If 'utf8' (the default), also normalize newlines. */ + format?: 'utf8' | 'binary'; + /** (optional) detached signature for verification */ + signature?: Signature; + /** (optional) use the given date for verification instead of the current time */ + date?: Date; + config?: PartialConfig; +} + + +interface SerializedKeyPair { + privateKey: T; + publicKey: T; +} +interface KeyPair { + privateKey: PrivateKey; + publicKey: PublicKey; +} + +export type EllipticCurveName = 'ed25519' | 'curve25519' | 'p256' | 'p384' | 'p521' | 'secp256k1' | 'brainpoolP256r1' | 'brainpoolP384r1' | 'brainpoolP512r1'; + +interface KeyOptions { + userIDs: MaybeArray; + passphrase?: string; + type?: 'ecc' | 'rsa'; + curve?: EllipticCurveName; + rsaBits?: number; + keyExpirationTime?: number; + date?: Date; + subkeys?: SubkeyOptions[]; + format?: 'armored' | 'object' | 'binary'; + config?: PartialConfig; +} + +interface SubkeyOptions { + type?: 'ecc' | 'rsa'; + curve?: EllipticCurveName; + rsaBits?: number; + keyExpirationTime?: number; + date?: Date; + sign?: boolean; + config?: PartialConfig; +} + +declare class KeyID { + bytes: string; + equals(keyID: KeyID, matchWildcard?: boolean): boolean; + toHex(): string; + static fromID(hex: string): KeyID; +} + +interface DecryptMessageResult { + data: MaybeStream; + signatures: VerificationResult[]; + filename: string; +} + +interface VerifyMessageResult { + data: MaybeStream; + signatures: VerificationResult[]; +} + + +/** + * Armor an OpenPGP binary packet block + */ +export function armor(messagetype: enums.armor, body: object, partindex: number, parttotal: number, config?: Config): string; + +/** + * DeArmor an OpenPGP armored message; verify the checksum and return the encoded bytes + */ +export function unarmor(input: string, config?: Config): Promise<{ text: string, data: Stream, type: enums.armor }>; + +/* ############## v5 ENUMS #################### */ + +export namespace enums { + function read(type: typeof armor, e: armor): armorNames; + function read(type: typeof compression, e: compression): compressionNames; + function read(type: typeof hash, e: hash): hashNames; + function read(type: typeof packet, e: packet): packetNames; + function read(type: typeof publicKey, e: publicKey): publicKeyNames; + function read(type: typeof symmetric, e: symmetric): symmetricNames; + function read(type: typeof keyStatus, e: keyStatus): keyStatusNames; + function read(type: typeof keyFlags, e: keyFlags): keyFlagsNames; + + export type armorNames = 'multipartSection' | 'multipartLast' | 'signed' | 'message' | 'publicKey' | 'privateKey'; + enum armor { + multipartSection = 0, + multipartLast = 1, + signed = 2, + message = 3, + publicKey = 4, + privateKey = 5, + signature = 6, + } + + enum reasonForRevocation { + noReason = 0, // No reason specified (key revocations or cert revocations) + keySuperseded = 1, // Key is superseded (key revocations) + keyCompromised = 2, // Key material has been compromised (key revocations) + keyRetired = 3, // Key is retired and no longer used (key revocations) + userIDInvalid = 32, // User ID information is no longer valid (cert revocations) + } + + export type compressionNames = 'uncompressed' | 'zip' | 'zlib' | 'bzip2'; + enum compression { + uncompressed = 0, + zip = 1, + zlib = 2, + bzip2 = 3, + } + + export type hashNames = 'md5' | 'sha1' | 'ripemd' | 'sha256' | 'sha384' | 'sha512' | 'sha224'; + enum hash { + md5 = 1, + sha1 = 2, + ripemd = 3, + sha256 = 8, + sha384 = 9, + sha512 = 10, + sha224 = 11, + } + + export type packetNames = 'publicKeyEncryptedSessionKey' | 'signature' | 'symEncryptedSessionKey' | 'onePassSignature' | 'secretKey' | 'publicKey' + | 'secretSubkey' | 'compressed' | 'symmetricallyEncrypted' | 'marker' | 'literal' | 'trust' | 'userID' | 'publicSubkey' | 'userAttribute' + | 'symEncryptedIntegrityProtected' | 'modificationDetectionCode' | 'AEADEncryptedDataPacket'; + enum packet { + publicKeyEncryptedSessionKey = 1, + signature = 2, + symEncryptedSessionKey = 3, + onePassSignature = 4, + secretKey = 5, + publicKey = 6, + secretSubkey = 7, + compressedData = 8, + symmetricallyEncryptedData = 9, + marker = 10, + literalData = 11, + trust = 12, + userID = 13, + publicSubkey = 14, + userAttribute = 17, + symEncryptedIntegrityProtectedData = 18, + modificationDetectionCode = 19, + aeadEncryptedData = 20, + } + + export type publicKeyNames = 'rsaEncryptSign' | 'rsaEncrypt' | 'rsaSign' | 'elgamal' | 'dsa' | 'ecdh' | 'ecdsa' | 'eddsa' | 'aedh' | 'aedsa'; + enum publicKey { + rsaEncryptSign = 1, + rsaEncrypt = 2, + rsaSign = 3, + elgamal = 16, + dsa = 17, + ecdh = 18, + ecdsa = 19, + eddsa = 22, + aedh = 23, + aedsa = 24, + } + + enum curve { + p256 = 'p256', + p384 = 'p384', + p521 = 'p521', + ed25519 = 'ed25519', + curve25519 = 'curve25519', + secp256k1 = 'secp256k1', + brainpoolP256r1 = 'brainpoolP256r1', + brainpoolP384r1 = 'brainpoolP384r1', + brainpoolP512r1 = 'brainpoolP512r1' + } + + export type symmetricNames = 'plaintext' | 'idea' | 'tripledes' | 'cast5' | 'blowfish' | 'aes128' | 'aes192' | 'aes256' | 'twofish'; + enum symmetric { + plaintext = 0, + idea = 1, + tripledes = 2, + cast5 = 3, + blowfish = 4, + aes128 = 7, + aes192 = 8, + aes256 = 9, + twofish = 10, + } + + export type keyStatusNames = 'invalid' | 'expired' | 'revoked' | 'valid' | 'noSelfCert'; + enum keyStatus { + invalid = 0, + expired = 1, + revoked = 2, + valid = 3, + noSelfCert = 4, + } + + export type keyFlagsNames = 'certifyKeys' | 'signData' | 'encryptCommunication' | 'encryptStorage' | 'splitPrivateKey' | 'authentication' + | 'sharedPrivateKey'; + enum keyFlags { + certifyKeys = 1, + signData = 2, + encryptCommunication = 4, + encryptStorage = 8, + splitPrivateKey = 16, + authentication = 32, + sharedPrivateKey = 128, + } + + enum signature { + binary = 0, + text = 1, + standalone = 2, + certGeneric = 16, + certPersona = 17, + certCasual = 18, + certPositive = 19, + certRevocation = 48, + subkeyBinding = 24, + keyBinding = 25, + key = 31, + keyRevocation = 32, + subkeyRevocation = 40, + timestamp = 64, + thirdParty = 80 + } + + export type aeadNames = 'eax' | 'ocb' | 'gcm'; + enum aead { + eax = 1, + ocb = 2, + experimentalGCM = 100 // Private algorithm + } + + export type literalFormatNames = 'utf8' | 'binary' | 'text' | 'mime' + enum literal { + binary = 98, + text = 116, + utf8 = 117, + mime = 109 + } } diff --git a/Core/source/lib/openpgp.js b/Core/source/lib/openpgp.js index 8103dee04..2ec404742 100644 --- a/Core/source/lib/openpgp.js +++ b/Core/source/lib/openpgp.js @@ -1,22856 +1,11004 @@ -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.openpgp = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i `Symbol(${e})`;const r = "undefined" != typeof self ? self : "undefined" != typeof window ? window : "undefined" != typeof global ? global : void 0, - o = Number.isNaN || function (e) { - return e != e; - };function n(e) { - return "object" == typeof e && null !== e || "function" == typeof e; - }function i(e, t, r) { - Object.defineProperty(e, t, { value: r, writable: !0, enumerable: !0, configurable: !0 }); - }function a(e) { - return e.slice(); - }function s(e, t, r, o, n) { - new Uint8Array(e).set(new Uint8Array(r, o, n), t); - }function l(e) { - return !1 !== function (e) { - if ("number" != typeof e) return !1;if (o(e)) return !1;if (e < 0) return !1;return !0; - }(e) && e !== 1 / 0; - }function c(e, t, r) { - if ("function" != typeof e) throw new TypeError("Argument is not a function");return Function.prototype.apply.call(e, t, r); - }function u(e, t, r, o) { - const n = e[t];if (void 0 !== n) { - if ("function" != typeof n) throw new TypeError(`${n} is not a method`);switch (r) {case 0: - return () => f(n, e, o);case 1: - return t => { - const r = [t].concat(o);return f(n, e, r); - };} - }return () => Promise.resolve(); - }function d(e, t, r) { - const o = e[t];if (void 0 !== o) return c(o, e, r); - }function f(e, t, r) { - try { - return Promise.resolve(c(e, t, r)); - } catch (e) { - return Promise.reject(e); - } - }function _(e) { - return e; - }function h(e) { - if (e = Number(e), o(e) || e < 0) throw new RangeError("highWaterMark property of a queuing strategy must be non-negative and non-NaN");return e; - }function b(e) { - if (void 0 === e) return () => 1;if ("function" != typeof e) throw new TypeError("size property of a queuing strategy must be a function");return t => e(t); - }function m(e, t, r) { - return Promise.prototype.then.call(e, t, r); - }function y(e, t, r) { - let o, n;const i = new Promise((e, t) => { - o = e, n = t; - });void 0 === r && (r = e => { - throw e; - });return function (e, t, r) { - let o = !1;const n = e => { - !1 === o && (o = !0, r(e)); - };let i = 0, - a = 0;const s = e.length, - l = new Array(s);for (const r of e) { - const e = i;m(r, r => { - l[e] = r, ++a === s && t(l); - }, n), ++i; - } - }(e, e => { - try { - const r = t(e);o(r); - } catch (e) { - n(e); - } - }, e => { - try { - const t = r(e);o(t); - } catch (e) { - n(e); - } - }), i; - }function p(e) {}function w(e) { - e && e instanceof p.AssertionError && setTimeout(() => { - throw e; - }, 0); - }function g(e) { - const t = e._queue.shift();return e._queueTotalSize -= t.size, e._queueTotalSize < 0 && (e._queueTotalSize = 0), t.value; - }function S(e, t, r) { - if (!l(r = Number(r))) throw new RangeError("Size must be a finite, non-NaN, non-negative number.");e._queue.push({ value: t, size: r }), e._queueTotalSize += r; - }function v(e) { - e._queue = [], e._queueTotalSize = 0; - }p.AssertionError = function () {};const R = t("[[AbortSteps]]"), - P = t("[[ErrorSteps]]");class WritableStream { - constructor(e = {}, t = {}) { - q(this);const r = t.size;let o = t.highWaterMark;if (void 0 !== e.type) throw new RangeError("Invalid type is specified");const n = b(r);void 0 === o && (o = 1), function (e, t, r, o) { - const n = Object.create(WritableStreamDefaultController.prototype);const i = u(t, "write", 1, [n]), - a = u(t, "close", 0, []), - s = u(t, "abort", 1, []);$(e, n, function () { - return d(t, "start", [n]); - }, i, a, s, r, o); - }(this, e, o = h(o), n); - }get locked() { - if (!1 === E(this)) throw G("locked");return C(this); - }abort(e) { - return !1 === E(this) ? Promise.reject(G("abort")) : !0 === C(this) ? Promise.reject(new TypeError("Cannot abort a stream that already has a writer")) : j(this, e); - }getWriter() { - if (!1 === E(this)) throw G("getWriter");return T(this); - } - }function T(e) { - return new WritableStreamDefaultWriter(e); - }function q(e) { - e._state = "writable", e._storedError = void 0, e._writer = void 0, e._writableStreamController = void 0, e._writeRequests = [], e._inFlightWriteRequest = void 0, e._closeRequest = void 0, e._inFlightCloseRequest = void 0, e._pendingAbortRequest = void 0, e._backpressure = !1; - }function E(e) { - return !!n(e) && !!Object.prototype.hasOwnProperty.call(e, "_writableStreamController"); - }function C(e) { - return void 0 !== e._writer; - }function j(e, t) { - const r = e._state;if ("closed" === r || "errored" === r) return Promise.resolve(void 0);if (void 0 !== e._pendingAbortRequest) return e._pendingAbortRequest._promise;let o = !1;"erroring" === r && (o = !0, t = void 0);const n = new Promise((r, n) => { - e._pendingAbortRequest = { _promise: void 0, _resolve: r, _reject: n, _reason: t, _wasAlreadyErroring: o }; - });return e._pendingAbortRequest._promise = n, !1 === o && W(e, t), n; - }function A(e, t) { - "writable" !== e._state ? B(e) : W(e, t); - }function W(e, t) { - const r = e._writableStreamController;e._state = "erroring", e._storedError = t;const o = e._writer;void 0 !== o && D(o, t), !1 === function (e) { - if (void 0 === e._inFlightWriteRequest && void 0 === e._inFlightCloseRequest) return !1;return !0; - }(e) && !0 === r._started && B(e); - }function B(e) { - e._state = "errored", e._writableStreamController[P]();const t = e._storedError;for (const r of e._writeRequests) r._reject(t);if (e._writeRequests = [], void 0 === e._pendingAbortRequest) return void z(e);const r = e._pendingAbortRequest;if (e._pendingAbortRequest = void 0, !0 === r._wasAlreadyErroring) return r._reject(t), void z(e);e._writableStreamController[R](r._reason).then(() => { - r._resolve(), z(e); - }, t => { - r._reject(t), z(e); +/*! OpenPGP.js v5.1.0 - 2022-01-24 - this is LGPL licensed code, see LICENSE/our website https://openpgpjs.org/ for more information. */ +'use strict'; + +const globalThis = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + +Object.defineProperty(exports, '__esModule', { value: true }); + +var buffer = require('buffer'); +var stream$1 = require('stream'); +var crypto$3 = require('crypto'); +var zlib = require('zlib'); +var os = require('os'); +var util$1 = require('util'); +var asn1$2 = require('asn1.js'); + +function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } + +var buffer__default = /*#__PURE__*/_interopDefaultLegacy(buffer); +var stream__default = /*#__PURE__*/_interopDefaultLegacy(stream$1); +var crypto__default = /*#__PURE__*/_interopDefaultLegacy(crypto$3); +var zlib__default = /*#__PURE__*/_interopDefaultLegacy(zlib); +var os__default = /*#__PURE__*/_interopDefaultLegacy(os); +var util__default = /*#__PURE__*/_interopDefaultLegacy(util$1); +var asn1__default = /*#__PURE__*/_interopDefaultLegacy(asn1$2); + +const doneWritingPromise = Symbol('doneWritingPromise'); +const doneWritingResolve = Symbol('doneWritingResolve'); +const doneWritingReject = Symbol('doneWritingReject'); + +const readingIndex = Symbol('readingIndex'); + +class ArrayStream extends Array { + constructor() { + super(); + this[doneWritingPromise] = new Promise((resolve, reject) => { + this[doneWritingResolve] = resolve; + this[doneWritingReject] = reject; }); - }function O(e) { - return void 0 !== e._closeRequest || void 0 !== e._inFlightCloseRequest; - }function z(e) { - void 0 !== e._closeRequest && (e._closeRequest._reject(e._storedError), e._closeRequest = void 0);const t = e._writer;void 0 !== t && ee(t, e._storedError); - }function k(e, t) { - const r = e._writer;void 0 !== r && t !== e._backpressure && (!0 === t ? function (e) { - re(e); - }(r) : ae(r)), e._backpressure = t; - }class WritableStreamDefaultWriter { - constructor(e) { - if (!1 === E(e)) throw new TypeError("WritableStreamDefaultWriter can only be constructed with a WritableStream instance");if (!0 === C(e)) throw new TypeError("This stream has already been locked for exclusive writing by another writer");this._ownerWritableStream = e, e._writer = this;const t = e._state;if ("writable" === t) !1 === O(e) && !0 === e._backpressure ? re(this) : ne(this), X(this);else if ("erroring" === t) oe(this, e._storedError), X(this);else if ("closed" === t) ne(this), function (e) { - X(e), te(e); - }(this);else { - const t = e._storedError;oe(this, t), Z(this, t); - } - }get closed() { - return !1 === F(this) ? Promise.reject(J("closed")) : this._closedPromise; - }get desiredSize() { - if (!1 === F(this)) throw J("desiredSize");if (void 0 === this._ownerWritableStream) throw K("desiredSize");return function (e) { - const t = e._ownerWritableStream, - r = t._state;if ("errored" === r || "erroring" === r) return null;if ("closed" === r) return 0;return Q(t._writableStreamController); - }(this); - }get ready() { - return !1 === F(this) ? Promise.reject(J("ready")) : this._readyPromise; - }abort(e) { - return !1 === F(this) ? Promise.reject(J("abort")) : void 0 === this._ownerWritableStream ? Promise.reject(K("abort")) : function (e, t) { - return j(e._ownerWritableStream, t); - }(this, e); - }close() { - if (!1 === F(this)) return Promise.reject(J("close"));const e = this._ownerWritableStream;return void 0 === e ? Promise.reject(K("close")) : !0 === O(e) ? Promise.reject(new TypeError("cannot close an already-closing stream")) : L(this); - }releaseLock() { - if (!1 === F(this)) throw J("releaseLock");void 0 !== this._ownerWritableStream && M(this); - }write(e) { - return !1 === F(this) ? Promise.reject(J("write")) : void 0 === this._ownerWritableStream ? Promise.reject(K("write to")) : Y(this, e); - } - }function F(e) { - return !!n(e) && !!Object.prototype.hasOwnProperty.call(e, "_ownerWritableStream"); - }function L(e) { - const t = e._ownerWritableStream, - r = t._state;if ("closed" === r || "errored" === r) return Promise.reject(new TypeError(`The stream (in ${r} state) is not in the writable state and cannot be closed`));const o = new Promise((e, r) => { - const o = { _resolve: e, _reject: r };t._closeRequest = o; - });return !0 === t._backpressure && "writable" === r && ae(e), function (e) { - S(e, "close", 0), x(e); - }(t._writableStreamController), o; - }function I(e, t) { - "pending" === e._closedPromiseState ? ee(e, t) : function (e, t) { - Z(e, t); - }(e, t); - }function D(e, t) { - "pending" === e._readyPromiseState ? ie(e, t) : function (e, t) { - oe(e, t); - }(e, t); - }function M(e) { - const t = e._ownerWritableStream, - r = new TypeError("Writer was released and can no longer be used to monitor the stream's closedness");D(e, r), I(e, r), t._writer = void 0, e._ownerWritableStream = void 0; - }function Y(e, t) { - const r = e._ownerWritableStream, - o = r._writableStreamController, - n = function (e, t) { - try { - return e._strategySizeAlgorithm(t); - } catch (t) { - return H(e, t), 1; + this[doneWritingPromise].catch(() => {}); + } +} + +ArrayStream.prototype.getReader = function() { + if (this[readingIndex] === undefined) { + this[readingIndex] = 0; + } + return { + read: async () => { + await this[doneWritingPromise]; + if (this[readingIndex] === this.length) { + return { value: undefined, done: true }; } - }(o, t);if (r !== e._ownerWritableStream) return Promise.reject(K("write to"));const i = r._state;if ("errored" === i) return Promise.reject(r._storedError);if (!0 === O(r) || "closed" === i) return Promise.reject(new TypeError("The stream is closing or closed and cannot be written to"));if ("erroring" === i) return Promise.reject(r._storedError);const a = function (e) { - return new Promise((t, r) => { - const o = { _resolve: t, _reject: r };e._writeRequests.push(o); - }); - }(r);return function (e, t, r) { - const o = { chunk: t };try { - S(e, o, r); - } catch (t) { - return void H(e, t); - }const n = e._controlledWritableStream;if (!1 === O(n) && "writable" === n._state) { - const t = U(e);k(n, t); - }x(e); - }(o, t, n), a; - }class WritableStreamDefaultController { - constructor() { - throw new TypeError("WritableStreamDefaultController cannot be constructed explicitly"); - }error(e) { - if (!1 === function (e) { - if (!n(e)) return !1;if (!Object.prototype.hasOwnProperty.call(e, "_controlledWritableStream")) return !1;return !0; - }(this)) throw new TypeError("WritableStreamDefaultController.prototype.error can only be used on a WritableStreamDefaultController");"writable" === this._controlledWritableStream._state && V(this, e); - }[R](e) { - const t = this._abortAlgorithm(e);return N(this), t; - }[P]() { - v(this); - } - }function $(e, t, r, o, n, i, a, s) { - t._controlledWritableStream = e, e._writableStreamController = t, t._queue = void 0, t._queueTotalSize = void 0, v(t), t._started = !1, t._strategySizeAlgorithm = s, t._strategyHWM = a, t._writeAlgorithm = o, t._closeAlgorithm = n, t._abortAlgorithm = i;const l = U(t);k(e, l);const c = r();Promise.resolve(c).then(() => { - t._started = !0, x(t); - }, r => { - t._started = !0, A(e, r); - }).catch(w); - }function N(e) { - e._writeAlgorithm = void 0, e._closeAlgorithm = void 0, e._abortAlgorithm = void 0, e._strategySizeAlgorithm = void 0; - }function Q(e) { - return e._strategyHWM - e._queueTotalSize; - }function x(e) { - const t = e._controlledWritableStream;if (!1 === e._started) return;if (void 0 !== t._inFlightWriteRequest) return;const r = t._state;if ("closed" === r || "errored" === r) return;if ("erroring" === r) return void B(t);if (0 === e._queue.length) return;const o = function (e) { - return e._queue[0].value; - }(e);"close" === o ? function (e) { - const t = e._controlledWritableStream;(function (e) { - e._inFlightCloseRequest = e._closeRequest, e._closeRequest = void 0; - })(t), g(e);const r = e._closeAlgorithm();N(e), r.then(() => { - !function (e) { - e._inFlightCloseRequest._resolve(void 0), e._inFlightCloseRequest = void 0, "erroring" === e._state && (e._storedError = void 0, void 0 !== e._pendingAbortRequest && (e._pendingAbortRequest._resolve(), e._pendingAbortRequest = void 0)), e._state = "closed";const t = e._writer;void 0 !== t && te(t); - }(t); - }, e => { - !function (e, t) { - e._inFlightCloseRequest._reject(t), e._inFlightCloseRequest = void 0, void 0 !== e._pendingAbortRequest && (e._pendingAbortRequest._reject(t), e._pendingAbortRequest = void 0), A(e, t); - }(t, e); - }).catch(w); - }(e) : function (e, t) { - const r = e._controlledWritableStream;(function (e) { - e._inFlightWriteRequest = e._writeRequests.shift(); - })(r), e._writeAlgorithm(t).then(() => { - !function (e) { - e._inFlightWriteRequest._resolve(void 0), e._inFlightWriteRequest = void 0; - }(r);const t = r._state;if (g(e), !1 === O(r) && "writable" === t) { - const t = U(e);k(r, t); - }x(e); - }, t => { - "writable" === r._state && N(e), function (e, t) { - e._inFlightWriteRequest._reject(t), e._inFlightWriteRequest = void 0, A(e, t); - }(r, t); - }).catch(w); - }(e, o.chunk); - }function H(e, t) { - "writable" === e._controlledWritableStream._state && V(e, t); - }function U(e) { - return Q(e) <= 0; - }function V(e, t) { - const r = e._controlledWritableStream;N(e), W(r, t); - }function G(e) { - return new TypeError(`WritableStream.prototype.${e} can only be used on a WritableStream`); - }function J(e) { - return new TypeError(`WritableStreamDefaultWriter.prototype.${e} can only be used on a WritableStreamDefaultWriter`); - }function K(e) { - return new TypeError("Cannot " + e + " a stream using a released writer"); - }function X(e) { - e._closedPromise = new Promise((t, r) => { - e._closedPromise_resolve = t, e._closedPromise_reject = r, e._closedPromiseState = "pending"; - }); - }function Z(e, t) { - X(e), ee(e, t); - }function ee(e, t) { - e._closedPromise.catch(() => {}), e._closedPromise_reject(t), e._closedPromise_resolve = void 0, e._closedPromise_reject = void 0, e._closedPromiseState = "rejected"; - }function te(e) { - e._closedPromise_resolve(void 0), e._closedPromise_resolve = void 0, e._closedPromise_reject = void 0, e._closedPromiseState = "resolved"; - }function re(e) { - e._readyPromise = new Promise((t, r) => { - e._readyPromise_resolve = t, e._readyPromise_reject = r; - }), e._readyPromiseState = "pending"; - }function oe(e, t) { - re(e), ie(e, t); - }function ne(e) { - re(e), ae(e); - }function ie(e, t) { - e._readyPromise.catch(() => {}), e._readyPromise_reject(t), e._readyPromise_resolve = void 0, e._readyPromise_reject = void 0, e._readyPromiseState = "rejected"; - }function ae(e) { - e._readyPromise_resolve(void 0), e._readyPromise_resolve = void 0, e._readyPromise_reject = void 0, e._readyPromiseState = "fulfilled"; - }const se = Number.isInteger || function (e) { - return "number" == typeof e && isFinite(e) && Math.floor(e) === e; - }, - le = t("[[CancelSteps]]"), - ce = t("[[PullSteps]]");class ReadableStream { - constructor(e = {}, t = {}) { - fe(this);const r = t.size;let o = t.highWaterMark;const n = e.type;if ("bytes" === String(n)) { - if (void 0 !== r) throw new RangeError("The strategy for a byte stream cannot have a size function");void 0 === o && (o = 0), function (e, t, r) { - const o = Object.create(ReadableByteStreamController.prototype);const n = u(t, "pull", 0, [o]), - i = u(t, "cancel", 1, []);let a = t.autoAllocateChunkSize;if (void 0 !== a && (a = Number(a), !1 === se(a) || a <= 0)) throw new RangeError("autoAllocateChunkSize must be a positive integer");!function (e, t, r, o, n, i, a) { - t._controlledReadableByteStream = e, t._pullAgain = !1, t._pulling = !1, He(t), t._queue = t._queueTotalSize = void 0, v(t), t._closeRequested = !1, t._started = !1, t._strategyHWM = h(i), t._pullAlgorithm = o, t._cancelAlgorithm = n, t._autoAllocateChunkSize = a, t._pendingPullIntos = [], e._readableStreamController = t;const s = r();Promise.resolve(s).then(() => { - t._started = !0, xe(t); - }, e => { - nt(t, e); - }).catch(w); - }(e, o, function () { - return d(t, "start", [o]); - }, n, i, r, a); - }(this, e, o = h(o)); - } else { - if (void 0 !== n) throw new RangeError("Invalid type is specified");{ - const t = b(r);void 0 === o && (o = 1), function (e, t, r, o) { - const n = Object.create(ReadableStreamDefaultController.prototype);const i = u(t, "pull", 0, [n]), - a = u(t, "cancel", 1, []);$e(e, n, function () { - return d(t, "start", [n]); - }, i, a, r, o); - }(this, e, o = h(o), t); - } - } - }get locked() { - if (!1 === _e(this)) throw st("locked");return he(this); - }cancel(e) { - return !1 === _e(this) ? Promise.reject(st("cancel")) : !0 === he(this) ? Promise.reject(new TypeError("Cannot cancel a stream that already has a reader")) : pe(this, e); - }getReader({ mode: e } = {}) { - if (!1 === _e(this)) throw st("getReader");if (void 0 === e) return ue(this);if ("byob" === (e = String(e))) return function (e) { - return new ReadableStreamBYOBReader(e); - }(this);throw new RangeError("Invalid mode is specified"); - }pipeThrough({ writable: e, readable: t }, { preventClose: r, preventAbort: o, preventCancel: n, signal: i } = {}) { - if (!1 === _e(this)) throw st("pipeThrough");if (!1 === E(e)) throw new TypeError("writable argument to pipeThrough must be a WritableStream");if (!1 === _e(t)) throw new TypeError("readable argument to pipeThrough must be a ReadableStream");if (r = Boolean(r), o = Boolean(o), n = Boolean(n), void 0 !== i && !at(i)) throw new TypeError("ReadableStream.prototype.pipeThrough's signal option must be an AbortSignal");if (!0 === he(this)) throw new TypeError("ReadableStream.prototype.pipeThrough cannot be used on a locked ReadableStream");if (!0 === C(e)) throw new TypeError("ReadableStream.prototype.pipeThrough cannot be used on a locked WritableStream");return be(this, e, r, o, n, i).catch(() => {}), t; - }pipeTo(e, { preventClose: t, preventAbort: r, preventCancel: o, signal: n } = {}) { - return !1 === _e(this) ? Promise.reject(st("pipeTo")) : !1 === E(e) ? Promise.reject(new TypeError("ReadableStream.prototype.pipeTo's first argument must be a WritableStream")) : (t = Boolean(t), r = Boolean(r), o = Boolean(o), void 0 === n || at(n) ? !0 === he(this) ? Promise.reject(new TypeError("ReadableStream.prototype.pipeTo cannot be used on a locked ReadableStream")) : !0 === C(e) ? Promise.reject(new TypeError("ReadableStream.prototype.pipeTo cannot be used on a locked WritableStream")) : be(this, e, t, r, o, n) : Promise.reject(new TypeError("ReadableStream.prototype.pipeTo's signal option must be an AbortSignal"))); - }tee() { - if (!1 === _e(this)) throw st("tee");const e = function (e, t) { - const r = ue(e);let o, - n, - i, - s, - l, - c = !1, - u = !1, - d = !1;const f = new Promise(e => { - l = e; - });function _() { - return Be(r).then(e => { - const t = e.value, - r = e.done;if (!0 === r && !1 === c && (!1 === u && Le(i._readableStreamController), !1 === d && Le(s._readableStreamController), c = !0), !0 === c) return;const o = t, - n = t;!1 === u && Ie(i._readableStreamController, o), !1 === d && Ie(s._readableStreamController, n); - }); - }function h() {}return i = de(h, _, function (t) { - if (u = !0, o = t, !0 === d) { - const t = a([o, n]), - r = pe(e, t);l(r); - }return f; - }), s = de(h, _, function (t) { - if (d = !0, n = t, !0 === u) { - const t = a([o, n]), - r = pe(e, t);l(r); - }return f; - }), r._closedPromise.catch(e => { - !0 !== c && (De(i._readableStreamController, e), De(s._readableStreamController, e), c = !0); - }), [i, s]; - }(this);return a(e); - } - }function ue(e) { - return new ReadableStreamDefaultReader(e); - }function de(e, t, r, o = 1, n = () => 1) { - const i = Object.create(ReadableStream.prototype);return fe(i), $e(i, Object.create(ReadableStreamDefaultController.prototype), e, t, r, o, n), i; - }function fe(e) { - e._state = "readable", e._reader = void 0, e._storedError = void 0, e._disturbed = !1; - }function _e(e) { - return !!n(e) && !!Object.prototype.hasOwnProperty.call(e, "_readableStreamController"); - }function he(e) { - return void 0 !== e._reader; - }function be(e, t, r, o, n, i) { - const a = ue(e), - s = T(t);let l = !1, - c = Promise.resolve();return new Promise((u, d) => { - let f;if (void 0 !== i) { - if (f = () => { - const r = new DOMException("Aborted", "AbortError"), - i = [];!1 === o && i.push(() => "writable" === t._state ? j(t, r) : Promise.resolve()), !1 === n && i.push(() => "readable" === e._state ? pe(e, r) : Promise.resolve()), b(() => y(i.map(e => e()), e => e), !0, r); - }, !0 === i.aborted) return void f();i.addEventListener("abort", f); - }if (h(e, a._closedPromise, e => { - !1 === o ? b(() => j(t, e), !0, e) : m(!0, e); - }), h(t, s._closedPromise, t => { - !1 === n ? b(() => pe(e, t), !0, t) : m(!0, t); - }), function (e, t, r) { - "closed" === e._state ? r() : t.then(r).catch(w); - }(e, a._closedPromise, () => { - !1 === r ? b(() => function (e) { - const t = e._ownerWritableStream, - r = t._state;return !0 === O(t) || "closed" === r ? Promise.resolve() : "errored" === r ? Promise.reject(t._storedError) : L(e); - }(s)) : m(); - }), !0 === O(t) || "closed" === t._state) { - const t = new TypeError("the destination writable stream closed before all data could be piped to it");!1 === n ? b(() => pe(e, t), !0, t) : m(!0, t); - }function _() { - const e = c;return c.then(() => e !== c ? _() : void 0); - }function h(e, t, r) { - "errored" === e._state ? r(e._storedError) : t.catch(r).catch(w); - }function b(e, r, o) { - function n() { - e().then(() => p(r, o), e => p(!0, e)).catch(w); - }!0 !== l && (l = !0, "writable" === t._state && !1 === O(t) ? _().then(n) : n()); - }function m(e, r) { - !0 !== l && (l = !0, "writable" === t._state && !1 === O(t) ? _().then(() => p(e, r)).catch(w) : p(e, r)); - }function p(e, t) { - M(s), We(a), void 0 !== i && i.removeEventListener("abort", f), e ? d(t) : u(void 0); - }new Promise((e, t) => { - !function r(o) { - o ? e() : (!0 === l ? Promise.resolve(!0) : s._readyPromise.then(() => Be(a).then(({ value: e, done: t }) => !0 === t || (c = Y(s, e).catch(() => {}), !1)))).then(r, t); - }(!1); - }).catch(e => { - c = Promise.resolve(), w(e); - }); - }); - }function me(e, t) { - return new Promise((r, o) => { - const n = { _resolve: r, _reject: o, _forAuthorCode: t };e._reader._readIntoRequests.push(n); - }); - }function ye(e, t) { - return new Promise((r, o) => { - const n = { _resolve: r, _reject: o, _forAuthorCode: t };e._reader._readRequests.push(n); - }); - }function pe(e, t) { - if (e._disturbed = !0, "closed" === e._state) return Promise.resolve(void 0);if ("errored" === e._state) return Promise.reject(e._storedError);return we(e), e._readableStreamController[le](t).then(() => void 0); - }function we(e) { - e._state = "closed";const t = e._reader;if (void 0 !== t) { - if (Ce(t)) { - for (const _ref of t._readRequests) { - const e = _ref._resolve; - const r = _ref._forAuthorCode; - e(ge(void 0, !0, r)); - }t._readRequests = []; - }_t(t); - } - }function ge(e, t, r) { - let o = null;!0 === r && (o = Object.prototype);const n = Object.create(o);return Object.defineProperty(n, "value", { value: e, enumerable: !0, writable: !0, configurable: !0 }), Object.defineProperty(n, "done", { value: t, enumerable: !0, writable: !0, configurable: !0 }), n; - }function Se(e, t) { - e._state = "errored", e._storedError = t;const r = e._reader;if (void 0 !== r) { - if (Ce(r)) { - for (const e of r._readRequests) e._reject(t);r._readRequests = []; - } else { - for (const e of r._readIntoRequests) e._reject(t);r._readIntoRequests = []; - }ft(r, t); - } - }function ve(e, t, r) { - const o = e._reader._readRequests.shift();o._resolve(ge(t, r, o._forAuthorCode)); - }function Re(e) { - return e._reader._readIntoRequests.length; - }function Pe(e) { - return e._reader._readRequests.length; - }function Te(e) { - const t = e._reader;return void 0 !== t && !!Ee(t); - }function qe(e) { - const t = e._reader;return void 0 !== t && !!Ce(t); - }class ReadableStreamDefaultReader { - constructor(e) { - if (!1 === _e(e)) throw new TypeError("ReadableStreamDefaultReader can only be constructed with a ReadableStream instance");if (!0 === he(e)) throw new TypeError("This stream has already been locked for exclusive reading by another reader");je(this, e), this._readRequests = []; - }get closed() { - return Ce(this) ? this._closedPromise : Promise.reject(ct("closed")); - }cancel(e) { - return Ce(this) ? void 0 === this._ownerReadableStream ? Promise.reject(lt("cancel")) : Ae(this, e) : Promise.reject(ct("cancel")); - }read() { - return Ce(this) ? void 0 === this._ownerReadableStream ? Promise.reject(lt("read from")) : Be(this, !0) : Promise.reject(ct("read")); - }releaseLock() { - if (!Ce(this)) throw ct("releaseLock");if (void 0 !== this._ownerReadableStream) { - if (this._readRequests.length > 0) throw new TypeError("Tried to release a reader lock when that reader has pending read() calls un-settled");We(this); - } - } - }class ReadableStreamBYOBReader { - constructor(e) { - if (!_e(e)) throw new TypeError("ReadableStreamBYOBReader can only be constructed with a ReadableStream instance given a byte source");if (!1 === Ne(e._readableStreamController)) throw new TypeError("Cannot construct a ReadableStreamBYOBReader for a stream not constructed with a byte source");if (he(e)) throw new TypeError("This stream has already been locked for exclusive reading by another reader");je(this, e), this._readIntoRequests = []; - }get closed() { - return Ee(this) ? this._closedPromise : Promise.reject(ht("closed")); - }cancel(e) { - return Ee(this) ? void 0 === this._ownerReadableStream ? Promise.reject(lt("cancel")) : Ae(this, e) : Promise.reject(ht("cancel")); - }read(e) { - return Ee(this) ? void 0 === this._ownerReadableStream ? Promise.reject(lt("read from")) : ArrayBuffer.isView(e) ? (e.buffer, 0 === e.byteLength ? Promise.reject(new TypeError("view must have non-zero byteLength")) : function (e, t, r = !1) { - const o = e._ownerReadableStream;if (o._disturbed = !0, "errored" === o._state) return Promise.reject(o._storedError);return function (e, t, r) { - const o = e._controlledReadableByteStream;let n = 1;t.constructor !== DataView && (n = t.constructor.BYTES_PER_ELEMENT);const i = t.constructor, - a = { buffer: _(t.buffer), byteOffset: t.byteOffset, byteLength: t.byteLength, bytesFilled: 0, elementSize: n, ctor: i, readerType: "byob" };if (e._pendingPullIntos.length > 0) return e._pendingPullIntos.push(a), me(o, r);if ("closed" === o._state) { - const e = new i(a.buffer, a.byteOffset, 0);return Promise.resolve(ge(e, !0, r)); - }if (e._queueTotalSize > 0) { - if (!0 === Je(e, a)) { - const t = Ve(a);return Xe(e), Promise.resolve(ge(t, !1, r)); - }if (!0 === e._closeRequested) { - const t = new TypeError("Insufficient bytes to fill elements in the given buffer");return nt(e, t), Promise.reject(t); - } - }e._pendingPullIntos.push(a);const s = me(o, r);return xe(e), s; - }(o._readableStreamController, t, r); - }(this, e, !0)) : Promise.reject(new TypeError("view must be an array buffer view")) : Promise.reject(ht("read")); - }releaseLock() { - if (!Ee(this)) throw ht("releaseLock");if (void 0 !== this._ownerReadableStream) { - if (this._readIntoRequests.length > 0) throw new TypeError("Tried to release a reader lock when that reader has pending read() calls un-settled");We(this); - } - } - }function Ee(e) { - return !!n(e) && !!Object.prototype.hasOwnProperty.call(e, "_readIntoRequests"); - }function Ce(e) { - return !!n(e) && !!Object.prototype.hasOwnProperty.call(e, "_readRequests"); - }function je(e, t) { - e._ownerReadableStream = t, t._reader = e, "readable" === t._state ? ut(e) : "closed" === t._state ? function (e) { - ut(e), _t(e); - }(e) : dt(e, t._storedError); - }function Ae(e, t) { - return pe(e._ownerReadableStream, t); - }function We(e) { - "readable" === e._ownerReadableStream._state ? ft(e, new TypeError("Reader was released and can no longer be used to monitor the stream's closedness")) : function (e, t) { - dt(e, t); - }(e, new TypeError("Reader was released and can no longer be used to monitor the stream's closedness")), e._ownerReadableStream._reader = void 0, e._ownerReadableStream = void 0; - }function Be(e, t = !1) { - const r = e._ownerReadableStream;return r._disturbed = !0, "closed" === r._state ? Promise.resolve(ge(void 0, !0, t)) : "errored" === r._state ? Promise.reject(r._storedError) : r._readableStreamController[ce](t); - }class ReadableStreamDefaultController { - constructor() { - throw new TypeError(); - }get desiredSize() { - if (!1 === Oe(this)) throw bt("desiredSize");return Me(this); - }close() { - if (!1 === Oe(this)) throw bt("close");if (!1 === Ye(this)) throw new TypeError("The stream is not in a state that permits close");Le(this); - }enqueue(e) { - if (!1 === Oe(this)) throw bt("enqueue");if (!1 === Ye(this)) throw new TypeError("The stream is not in a state that permits enqueue");return Ie(this, e); - }error(e) { - if (!1 === Oe(this)) throw bt("error");De(this, e); - }[le](e) { - v(this);const t = this._cancelAlgorithm(e);return Fe(this), t; - }[ce](e) { - const t = this._controlledReadableStream;if (this._queue.length > 0) { - const r = g(this);return !0 === this._closeRequested && 0 === this._queue.length ? (Fe(this), we(t)) : ze(this), Promise.resolve(ge(r, !1, e)); - }const r = ye(t, e);return ze(this), r; - } - }function Oe(e) { - return !!n(e) && !!Object.prototype.hasOwnProperty.call(e, "_controlledReadableStream"); - }function ze(e) { - !1 !== ke(e) && (!0 !== e._pulling ? (e._pulling = !0, e._pullAlgorithm().then(() => { - if (e._pulling = !1, !0 === e._pullAgain) return e._pullAgain = !1, ze(e); - }, t => { - De(e, t); - }).catch(w)) : e._pullAgain = !0); - }function ke(e) { - const t = e._controlledReadableStream;return !1 !== Ye(e) && !1 !== e._started && (!0 === he(t) && Pe(t) > 0 || Me(e) > 0); - }function Fe(e) { - e._pullAlgorithm = void 0, e._cancelAlgorithm = void 0, e._strategySizeAlgorithm = void 0; - }function Le(e) { - const t = e._controlledReadableStream;e._closeRequested = !0, 0 === e._queue.length && (Fe(e), we(t)); - }function Ie(e, t) { - const r = e._controlledReadableStream;if (!0 === he(r) && Pe(r) > 0) ve(r, t, !1);else { - let r;try { - r = e._strategySizeAlgorithm(t); - } catch (t) { - throw De(e, t), t; - }try { - S(e, t, r); - } catch (t) { - throw De(e, t), t; - } - }ze(e); - }function De(e, t) { - const r = e._controlledReadableStream;"readable" === r._state && (v(e), Fe(e), Se(r, t)); - }function Me(e) { - const t = e._controlledReadableStream._state;return "errored" === t ? null : "closed" === t ? 0 : e._strategyHWM - e._queueTotalSize; - }function Ye(e) { - const t = e._controlledReadableStream._state;return !1 === e._closeRequested && "readable" === t; - }function $e(e, t, r, o, n, i, a) { - t._controlledReadableStream = e, t._queue = void 0, t._queueTotalSize = void 0, v(t), t._started = !1, t._closeRequested = !1, t._pullAgain = !1, t._pulling = !1, t._strategySizeAlgorithm = a, t._strategyHWM = i, t._pullAlgorithm = o, t._cancelAlgorithm = n, e._readableStreamController = t;const s = r();Promise.resolve(s).then(() => { - t._started = !0, ze(t); - }, e => { - De(t, e); - }).catch(w); - }class ReadableStreamBYOBRequest { - constructor() { - throw new TypeError("ReadableStreamBYOBRequest cannot be used directly"); - }get view() { - if (!1 === Qe(this)) throw mt("view");return this._view; - }respond(e) { - if (!1 === Qe(this)) throw mt("respond");if (void 0 === this._associatedReadableByteStreamController) throw new TypeError("This BYOB request has been invalidated");this._view.buffer, function (e, t) { - if (!1 === l(t = Number(t))) throw new RangeError("bytesWritten must be a finite");tt(e, t); - }(this._associatedReadableByteStreamController, e); - }respondWithNewView(e) { - if (!1 === Qe(this)) throw mt("respond");if (void 0 === this._associatedReadableByteStreamController) throw new TypeError("This BYOB request has been invalidated");if (!ArrayBuffer.isView(e)) throw new TypeError("You can only respond with array buffer views");e.buffer, function (e, t) { - const r = e._pendingPullIntos[0];if (r.byteOffset + r.bytesFilled !== t.byteOffset) throw new RangeError("The region specified by view does not match byobRequest");if (r.byteLength !== t.byteLength) throw new RangeError("The buffer of view has different capacity than byobRequest");r.buffer = t.buffer, tt(e, t.byteLength); - }(this._associatedReadableByteStreamController, e); - } - }class ReadableByteStreamController { - constructor() { - throw new TypeError("ReadableByteStreamController constructor cannot be used directly"); - }get byobRequest() { - if (!1 === Ne(this)) throw yt("byobRequest");if (void 0 === this._byobRequest && this._pendingPullIntos.length > 0) { - const e = this._pendingPullIntos[0], - t = new Uint8Array(e.buffer, e.byteOffset + e.bytesFilled, e.byteLength - e.bytesFilled), - r = Object.create(ReadableStreamBYOBRequest.prototype);!function (e, t, r) { - e._associatedReadableByteStreamController = t, e._view = r; - }(r, this, t), this._byobRequest = r; - }return this._byobRequest; - }get desiredSize() { - if (!1 === Ne(this)) throw yt("desiredSize");return it(this); - }close() { - if (!1 === Ne(this)) throw yt("close");if (!0 === this._closeRequested) throw new TypeError("The stream has already been closed; do not close it again!");const e = this._controlledReadableByteStream._state;if ("readable" !== e) throw new TypeError(`The stream (in ${e} state) is not in the readable state and cannot be closed`);!function (e) { - const t = e._controlledReadableByteStream;if (e._queueTotalSize > 0) return void (e._closeRequested = !0);if (e._pendingPullIntos.length > 0) { - const t = e._pendingPullIntos[0];if (t.bytesFilled > 0) { - const t = new TypeError("Insufficient bytes to fill elements in the given buffer");throw nt(e, t), t; - } - }ot(e), we(t); - }(this); - }enqueue(e) { - if (!1 === Ne(this)) throw yt("enqueue");if (!0 === this._closeRequested) throw new TypeError("stream is closed or draining");const t = this._controlledReadableByteStream._state;if ("readable" !== t) throw new TypeError(`The stream (in ${t} state) is not in the readable state and cannot be enqueued to`);if (!ArrayBuffer.isView(e)) throw new TypeError("You can only enqueue array buffer views when using a ReadableByteStreamController");e.buffer, function (e, t) { - const r = e._controlledReadableByteStream, - o = t.buffer, - n = t.byteOffset, - i = t.byteLength, - a = _(o);if (!0 === qe(r)) { - if (0 === Pe(r)) Ge(e, a, n, i);else { - const e = new Uint8Array(a, n, i);ve(r, e, !1); - } - } else !0 === Te(r) ? (Ge(e, a, n, i), et(e)) : Ge(e, a, n, i);xe(e); - }(this, e); - }error(e) { - if (!1 === Ne(this)) throw yt("error");nt(this, e); - }[le](e) { - if (this._pendingPullIntos.length > 0) { - this._pendingPullIntos[0].bytesFilled = 0; - }v(this);const t = this._cancelAlgorithm(e);return ot(this), t; - }[ce](e) { - const t = this._controlledReadableByteStream;if (this._queueTotalSize > 0) { - const t = this._queue.shift();let r;this._queueTotalSize -= t.byteLength, Xe(this);try { - r = new Uint8Array(t.buffer, t.byteOffset, t.byteLength); - } catch (e) { - return Promise.reject(e); - }return Promise.resolve(ge(r, !1, e)); - }const r = this._autoAllocateChunkSize;if (void 0 !== r) { - let e;try { - e = new ArrayBuffer(r); - } catch (e) { - return Promise.reject(e); - }const t = { buffer: e, byteOffset: 0, byteLength: r, bytesFilled: 0, elementSize: 1, ctor: Uint8Array, readerType: "default" };this._pendingPullIntos.push(t); - }const o = ye(t, e);return xe(this), o; - } - }function Ne(e) { - return !!n(e) && !!Object.prototype.hasOwnProperty.call(e, "_controlledReadableByteStream"); - }function Qe(e) { - return !!n(e) && !!Object.prototype.hasOwnProperty.call(e, "_associatedReadableByteStreamController"); - }function xe(e) { - !1 !== function (e) { - const t = e._controlledReadableByteStream;if ("readable" !== t._state) return !1;if (!0 === e._closeRequested) return !1;if (!1 === e._started) return !1;if (!0 === qe(t) && Pe(t) > 0) return !0;if (!0 === Te(t) && Re(t) > 0) return !0;if (it(e) > 0) return !0;return !1; - }(e) && (!0 !== e._pulling ? (e._pulling = !0, e._pullAlgorithm().then(() => { - e._pulling = !1, !0 === e._pullAgain && (e._pullAgain = !1, xe(e)); - }, t => { - nt(e, t); - }).catch(w)) : e._pullAgain = !0); - }function He(e) { - Ze(e), e._pendingPullIntos = []; - }function Ue(e, t) { - let r = !1;"closed" === e._state && (r = !0);const o = Ve(t);"default" === t.readerType ? ve(e, o, r) : function (e, t, r) { - const o = e._reader._readIntoRequests.shift();o._resolve(ge(t, r, o._forAuthorCode)); - }(e, o, r); - }function Ve(e) { - const t = e.bytesFilled, - r = e.elementSize;return new e.ctor(e.buffer, e.byteOffset, t / r); - }function Ge(e, t, r, o) { - e._queue.push({ buffer: t, byteOffset: r, byteLength: o }), e._queueTotalSize += o; - }function Je(e, t) { - const r = t.elementSize, - o = t.bytesFilled - t.bytesFilled % r, - n = Math.min(e._queueTotalSize, t.byteLength - t.bytesFilled), - i = t.bytesFilled + n, - a = i - i % r;let l = n, - c = !1;a > o && (l = a - t.bytesFilled, c = !0);const u = e._queue;for (; l > 0;) { - const r = u[0], - o = Math.min(l, r.byteLength), - n = t.byteOffset + t.bytesFilled;s(t.buffer, n, r.buffer, r.byteOffset, o), r.byteLength === o ? u.shift() : (r.byteOffset += o, r.byteLength -= o), e._queueTotalSize -= o, Ke(e, o, t), l -= o; - }return c; - }function Ke(e, t, r) { - Ze(e), r.bytesFilled += t; - }function Xe(e) { - 0 === e._queueTotalSize && !0 === e._closeRequested ? (ot(e), we(e._controlledReadableByteStream)) : xe(e); - }function Ze(e) { - void 0 !== e._byobRequest && (e._byobRequest._associatedReadableByteStreamController = void 0, e._byobRequest._view = void 0, e._byobRequest = void 0); - }function et(e) { - for (; e._pendingPullIntos.length > 0;) { - if (0 === e._queueTotalSize) return;const t = e._pendingPullIntos[0];!0 === Je(e, t) && (rt(e), Ue(e._controlledReadableByteStream, t)); - } - }function tt(e, t) { - const r = e._pendingPullIntos[0];if ("closed" === e._controlledReadableByteStream._state) { - if (0 !== t) throw new TypeError("bytesWritten must be 0 when calling respond() on a closed stream");!function (e, t) { - t.buffer = _(t.buffer);const r = e._controlledReadableByteStream;if (!0 === Te(r)) for (; Re(r) > 0;) Ue(r, rt(e)); - }(e, r); - } else !function (e, t, r) { - if (r.bytesFilled + t > r.byteLength) throw new RangeError("bytesWritten out of range");if (Ke(e, t, r), r.bytesFilled < r.elementSize) return;rt(e);const o = r.bytesFilled % r.elementSize;if (o > 0) { - const t = r.byteOffset + r.bytesFilled, - n = r.buffer.slice(t - o, t);Ge(e, n, 0, n.byteLength); - }r.buffer = _(r.buffer), r.bytesFilled -= o, Ue(e._controlledReadableByteStream, r), et(e); - }(e, t, r);xe(e); - }function rt(e) { - const t = e._pendingPullIntos.shift();return Ze(e), t; - }function ot(e) { - e._pullAlgorithm = void 0, e._cancelAlgorithm = void 0; - }function nt(e, t) { - const r = e._controlledReadableByteStream;"readable" === r._state && (He(e), v(e), ot(e), Se(r, t)); - }function it(e) { - const t = e._controlledReadableByteStream._state;return "errored" === t ? null : "closed" === t ? 0 : e._strategyHWM - e._queueTotalSize; - }function at(e) { - if ("object" != typeof e || null === e) return !1;const t = Object.getOwnPropertyDescriptor(AbortSignal.prototype, "aborted").get;try { - return t.call(e), !0; - } catch (e) { - return !1; - } - }function st(e) { - return new TypeError(`ReadableStream.prototype.${e} can only be used on a ReadableStream`); - }function lt(e) { - return new TypeError("Cannot " + e + " a stream using a released reader"); - }function ct(e) { - return new TypeError(`ReadableStreamDefaultReader.prototype.${e} can only be used on a ReadableStreamDefaultReader`); - }function ut(e) { - e._closedPromise = new Promise((t, r) => { - e._closedPromise_resolve = t, e._closedPromise_reject = r; - }); - }function dt(e, t) { - ut(e), ft(e, t); - }function ft(e, t) { - e._closedPromise.catch(() => {}), e._closedPromise_reject(t), e._closedPromise_resolve = void 0, e._closedPromise_reject = void 0; - }function _t(e) { - e._closedPromise_resolve(void 0), e._closedPromise_resolve = void 0, e._closedPromise_reject = void 0; - }function ht(e) { - return new TypeError(`ReadableStreamBYOBReader.prototype.${e} can only be used on a ReadableStreamBYOBReader`); - }function bt(e) { - return new TypeError(`ReadableStreamDefaultController.prototype.${e} can only be used on a ReadableStreamDefaultController`); - }function mt(e) { - return new TypeError(`ReadableStreamBYOBRequest.prototype.${e} can only be used on a ReadableStreamBYOBRequest`); - }function yt(e) { - return new TypeError(`ReadableByteStreamController.prototype.${e} can only be used on a ReadableByteStreamController`); - }class ByteLengthQueuingStrategy { - constructor({ highWaterMark: e }) { - i(this, "highWaterMark", e); - }size(e) { - return e.byteLength; - } - }class CountQueuingStrategy { - constructor({ highWaterMark: e }) { - i(this, "highWaterMark", e); - }size() { - return 1; - } - }class TransformStream { - constructor(e = {}, t = {}, r = {}) { - const o = t.size;let n = t.highWaterMark;const i = r.size;let a = r.highWaterMark;if (void 0 !== e.writableType) throw new RangeError("Invalid writable type specified");const s = b(o);if (void 0 === n && (n = 1), n = h(n), void 0 !== e.readableType) throw new RangeError("Invalid readable type specified");const l = b(i);let c;void 0 === a && (a = 0), a = h(a), function (e, t, r, o, n, i) { - function a() { - return t; - }e._writable = function (e, t, r, o, n = 1, i = () => 1) { - const a = Object.create(WritableStream.prototype);return q(a), $(a, Object.create(WritableStreamDefaultController.prototype), e, t, r, o, n, i), a; - }(a, function (t) { - return function (e, t) { - const r = e._transformStreamController;if (!0 === e._backpressure) { - const o = e._backpressureChangePromise;return o.then(() => { - const o = e._writable, - n = o._state;if ("erroring" === n) throw o._storedError;return Tt(r, t); - }); - }return Tt(r, t); - }(e, t); - }, function () { - return function (e) { - const t = e._readable, - r = e._transformStreamController, - o = r._flushAlgorithm();return Rt(r), o.then(() => { - if ("errored" === t._state) throw t._storedError;const e = t._readableStreamController;!0 === Ye(e) && Le(e); - }).catch(r => { - throw wt(e, r), t._storedError; - }); - }(e); - }, function (t) { - return function (e, t) { - return wt(e, t), Promise.resolve(); - }(e, t); - }, r, o), e._readable = de(a, function () { - return function (e) { - return St(e, !1), e._backpressureChangePromise; - }(e); - }, function (t) { - return gt(e, t), Promise.resolve(); - }, n, i), e._backpressure = void 0, e._backpressureChangePromise = void 0, e._backpressureChangePromise_resolve = void 0, St(e, !0), e._transformStreamController = void 0; - }(this, new Promise(e => { - c = e; - }), n, s, a, l), function (e, t) { - const r = Object.create(TransformStreamDefaultController.prototype);let o = e => { - try { - return Pt(r, e), Promise.resolve(); - } catch (e) { - return Promise.reject(e); - } - };const n = t.transform;if (void 0 !== n) { - if ("function" != typeof n) throw new TypeError("transform is not a method");o = e => f(n, t, [e, r]); - }const i = u(t, "flush", 0, [r]);!function (e, t, r, o) { - t._controlledTransformStream = e, e._transformStreamController = t, t._transformAlgorithm = r, t._flushAlgorithm = o; - }(e, r, o, i); - }(this, e);const _ = d(e, "start", [this._transformStreamController]);c(_); - }get readable() { - if (!1 === pt(this)) throw Et("readable");return this._readable; - }get writable() { - if (!1 === pt(this)) throw Et("writable");return this._writable; - } - }function pt(e) { - return !!n(e) && !!Object.prototype.hasOwnProperty.call(e, "_transformStreamController"); - }function wt(e, t) { - De(e._readable._readableStreamController, t), gt(e, t); - }function gt(e, t) { - Rt(e._transformStreamController), H(e._writable._writableStreamController, t), !0 === e._backpressure && St(e, !1); - }function St(e, t) { - void 0 !== e._backpressureChangePromise && e._backpressureChangePromise_resolve(), e._backpressureChangePromise = new Promise(t => { - e._backpressureChangePromise_resolve = t; - }), e._backpressure = t; - }class TransformStreamDefaultController { - constructor() { - throw new TypeError("TransformStreamDefaultController instances cannot be created directly"); - }get desiredSize() { - if (!1 === vt(this)) throw qt("desiredSize");return Me(this._controlledTransformStream._readable._readableStreamController); - }enqueue(e) { - if (!1 === vt(this)) throw qt("enqueue");Pt(this, e); - }error(e) { - if (!1 === vt(this)) throw qt("error");!function (e, t) { - wt(e._controlledTransformStream, t); - }(this, e); - }terminate() { - if (!1 === vt(this)) throw qt("terminate");!function (e) { - const t = e._controlledTransformStream, - r = t._readable._readableStreamController;!0 === Ye(r) && Le(r);const o = new TypeError("TransformStream terminated");gt(t, o); - }(this); - } - }function vt(e) { - return !!n(e) && !!Object.prototype.hasOwnProperty.call(e, "_controlledTransformStream"); - }function Rt(e) { - e._transformAlgorithm = void 0, e._flushAlgorithm = void 0; - }function Pt(e, t) { - const r = e._controlledTransformStream, - o = r._readable._readableStreamController;if (!1 === Ye(o)) throw new TypeError("Readable side is not in a state that permits enqueue");try { - Ie(o, t); - } catch (e) { - throw gt(r, e), r._readable._storedError; - }(function (e) { - return !0 !== ke(e); - })(o) !== r._backpressure && St(r, !0); - }function Tt(e, t) { - return e._transformAlgorithm(t).catch(t => { - throw wt(e._controlledTransformStream, t), t; - }); - }function qt(e) { - return new TypeError(`TransformStreamDefaultController.prototype.${e} can only be used on a TransformStreamDefaultController`); - }function Et(e) { - return new TypeError(`TransformStream.prototype.${e} can only be used on a TransformStream`); - }const Ct = { ReadableStream: ReadableStream, WritableStream: WritableStream, ByteLengthQueuingStrategy: ByteLengthQueuingStrategy, CountQueuingStrategy: CountQueuingStrategy, TransformStream: TransformStream };void 0 !== r && Object.assign(r, Ct), e.ReadableStream = ReadableStream, e.WritableStream = WritableStream, e.ByteLengthQueuingStrategy = ByteLengthQueuingStrategy, e.CountQueuingStrategy = CountQueuingStrategy, e.TransformStream = TransformStream, Object.defineProperty(e, "__esModule", { value: !0 }); -}); + return { value: this[this[readingIndex]++], done: false }; + } + }; +}; +ArrayStream.prototype.readToEnd = async function(join) { + await this[doneWritingPromise]; + const result = join(this.slice(this[readingIndex])); + this.length = 0; + return result; +}; -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],2:[function(require,module,exports){ -"use strict"; +ArrayStream.prototype.clone = function() { + const clone = new ArrayStream(); + clone[doneWritingPromise] = this[doneWritingPromise].then(() => { + clone.push(...this); + }); + return clone; +}; -Object.defineProperty(exports, "__esModule", { - value: true -}); /** - * @file {@link http://asmjs.org Asm.js} implementation of the {@link https://en.wikipedia.org/wiki/Advanced_Encryption_Standard Advanced Encryption Standard}. - * @author Artem S Vybornov - * @license MIT + * Check whether data is an ArrayStream + * @param {Any} input data to check + * @returns {boolean} */ -var AES_asm = exports.AES_asm = function () { - "use strict"; +function isArrayStream(input) { + return input && input.getReader && Array.isArray(input); +} - /** - * Galois Field stuff init flag - */ +/** + * A wrapper class over the native WritableStreamDefaultWriter. + * It also lets you "write data to" array streams instead of streams. + * @class + */ +function Writer(input) { + if (!isArrayStream(input)) { + const writer = input.getWriter(); + const releaseLock = writer.releaseLock; + writer.releaseLock = () => { + writer.closed.catch(function() {}); + releaseLock.call(writer); + }; + return writer; + } + this.stream = input; +} - var ginit_done = false; +/** + * Write a chunk of data. + * @returns {Promise} + * @async + */ +Writer.prototype.write = async function(chunk) { + this.stream.push(chunk); +}; - /** - * Galois Field exponentiation and logarithm tables for 3 (the generator) - */ - var gexp3, glog3; +/** + * Close the stream. + * @returns {Promise} + * @async + */ +Writer.prototype.close = async function() { + this.stream[doneWritingResolve](); +}; - /** - * Init Galois Field tables - */ - function ginit() { - gexp3 = [], glog3 = []; +/** + * Error the stream. + * @returns {Promise} + * @async + */ +Writer.prototype.abort = async function(reason) { + this.stream[doneWritingReject](reason); + return reason; +}; - var a = 1, - c, - d; - for (c = 0; c < 255; c++) { - gexp3[c] = a; +/** + * Release the writer's lock. + * @returns {undefined} + * @async + */ +Writer.prototype.releaseLock = function() {}; - // Multiply by three - d = a & 0x80, a <<= 1, a &= 255; - if (d === 0x80) a ^= 0x1b; - a ^= gexp3[c]; +const isNode = typeof globalThis.process === 'object' && + typeof globalThis.process.versions === 'object'; - // Set the log table value - glog3[gexp3[c]] = c; - } - gexp3[255] = gexp3[0]; - glog3[0] = 0; +const NodeReadableStream = isNode && stream__default['default'].Readable; - ginit_done = true; +/** + * Check whether data is a Stream, and if so of which type + * @param {Any} input data to check + * @returns {'web'|'ponyfill'|'node'|'array'|'web-like'|false} + */ +function isStream(input) { + if (isArrayStream(input)) { + return 'array'; } - - /** - * Galois Field multiplication - * @param {number} a - * @param {number} b - * @return {number} - */ - function gmul(a, b) { - var c = gexp3[(glog3[a] + glog3[b]) % 255]; - if (a === 0 || b === 0) c = 0; - return c; + if (globalThis.ReadableStream && globalThis.ReadableStream.prototype.isPrototypeOf(input)) { + return 'web'; } - - /** - * Galois Field reciprocal - * @param {number} a - * @return {number} - */ - function ginv(a) { - var i = gexp3[255 - glog3[a]]; - if (a === 0) i = 0; - return i; + if (ReadableStream && ReadableStream.prototype.isPrototypeOf(input)) { + return 'ponyfill'; } + if (NodeReadableStream && NodeReadableStream.prototype.isPrototypeOf(input)) { + return 'node'; + } + if (input && input.getReader) { + return 'web-like'; + } + return false; +} - /** - * AES stuff init flag - */ - var aes_init_done = false; - - /** - * Encryption, Decryption, S-Box and KeyTransform tables - * - * @type {number[]} - */ - var aes_sbox; - - /** - * @type {number[]} - */ - var aes_sinv; +/** + * Check whether data is a Uint8Array + * @param {Any} input data to check + * @returns {Boolean} + */ +function isUint8Array(input) { + return Uint8Array.prototype.isPrototypeOf(input); +} - /** - * @type {number[][]} - */ - var aes_enc; +/** + * Concat Uint8Arrays + * @param {Array} Array of Uint8Arrays to concatenate + * @returns {Uint8array} Concatenated array + */ +function concatUint8Array(arrays) { + if (arrays.length === 1) return arrays[0]; - /** - * @type {number[][]} - */ - var aes_dec; + let totalLength = 0; + for (let i = 0; i < arrays.length; i++) { + if (!isUint8Array(arrays[i])) { + throw new Error('concatUint8Array: Data must be in the form of a Uint8Array'); + } - /** - * Init AES tables - */ - function aes_init() { - if (!ginit_done) ginit(); + totalLength += arrays[i].length; + } - // Calculates AES S-Box value - function _s(a) { - var c, s, x; - s = x = ginv(a); - for (c = 0; c < 4; c++) { - s = (s << 1 | s >>> 7) & 255; - x ^= s; - } - x ^= 99; - return x; - } + const result = new Uint8Array(totalLength); + let pos = 0; + arrays.forEach(function (element) { + result.set(element, pos); + pos += element.length; + }); - // Tables - aes_sbox = [], aes_sinv = [], aes_enc = [[], [], [], []], aes_dec = [[], [], [], []]; + return result; +} - for (var i = 0; i < 256; i++) { - var s = _s(i); +const NodeBuffer = isNode && buffer__default['default'].Buffer; +const NodeReadableStream$1 = isNode && stream__default['default'].Readable; - // S-Box and its inverse - aes_sbox[i] = s; - aes_sinv[s] = i; +/** + * Web / node stream conversion functions + * From https://github.com/gwicke/node-web-streams + */ - // Ecryption and Decryption tables - aes_enc[0][i] = gmul(2, s) << 24 | s << 16 | s << 8 | gmul(3, s); - aes_dec[0][s] = gmul(14, i) << 24 | gmul(9, i) << 16 | gmul(13, i) << 8 | gmul(11, i); - // Rotate tables - for (var t = 1; t < 4; t++) { - aes_enc[t][i] = aes_enc[t - 1][i] >>> 8 | aes_enc[t - 1][i] << 24; - aes_dec[t][s] = aes_dec[t - 1][s] >>> 8 | aes_dec[t - 1][s] << 24; - } - } +let nodeToWeb; +let webToNode; - aes_init_done = true; - } +if (NodeReadableStream$1) { /** - * Asm.js module constructor. - * - *

- * Heap buffer layout by offset: - *

-   * 0x0000   encryption key schedule
-   * 0x0400   decryption key schedule
-   * 0x0800   sbox
-   * 0x0c00   inv sbox
-   * 0x1000   encryption tables
-   * 0x2000   decryption tables
-   * 0x3000   reserved (future GCM multiplication lookup table)
-   * 0x4000   data
-   * 
- * Don't touch anything before 0x400. - *

- * - * @alias AES_asm - * @class - * @param foreign - ignored - * @param buffer - heap buffer to link with + * Convert a Node Readable Stream to a Web ReadableStream + * @param {Readable} nodeStream + * @returns {ReadableStream} */ - var wrapper = function wrapper(foreign, buffer) { - // Init AES stuff for the first time - if (!aes_init_done) aes_init(); - - // Fill up AES tables - var heap = new Uint32Array(buffer); - heap.set(aes_sbox, 0x0800 >> 2); - heap.set(aes_sinv, 0x0c00 >> 2); - for (var i = 0; i < 4; i++) { - heap.set(aes_enc[i], 0x1000 + 0x400 * i >> 2); - heap.set(aes_dec[i], 0x2000 + 0x400 * i >> 2); - } + nodeToWeb = function(nodeStream) { + let canceled = false; + return new ReadableStream({ + start(controller) { + nodeStream.pause(); + nodeStream.on('data', chunk => { + if (canceled) { + return; + } + if (NodeBuffer.isBuffer(chunk)) { + chunk = new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength); + } + controller.enqueue(chunk); + nodeStream.pause(); + }); + nodeStream.on('end', () => { + if (canceled) { + return; + } + controller.close(); + }); + nodeStream.on('error', e => controller.error(e)); + }, + pull() { + nodeStream.resume(); + }, + cancel(reason) { + canceled = true; + nodeStream.destroy(reason); + } + }); + }; - /** - * Calculate AES key schedules. - * @instance - * @memberof AES_asm - * @param {number} ks - key size, 4/6/8 (for 128/192/256-bit key correspondingly) - * @param {number} k0 - key vector components - * @param {number} k1 - key vector components - * @param {number} k2 - key vector components - * @param {number} k3 - key vector components - * @param {number} k4 - key vector components - * @param {number} k5 - key vector components - * @param {number} k6 - key vector components - * @param {number} k7 - key vector components - */ - function set_key(ks, k0, k1, k2, k3, k4, k5, k6, k7) { - var ekeys = heap.subarray(0x000, 60), - dkeys = heap.subarray(0x100, 0x100 + 60); - // Encryption key schedule - ekeys.set([k0, k1, k2, k3, k4, k5, k6, k7]); - for (var i = ks, rcon = 1; i < 4 * ks + 28; i++) { - var k = ekeys[i - 1]; - if (i % ks === 0 || ks === 8 && i % ks === 4) { - k = aes_sbox[k >>> 24] << 24 ^ aes_sbox[k >>> 16 & 255] << 16 ^ aes_sbox[k >>> 8 & 255] << 8 ^ aes_sbox[k & 255]; - } - if (i % ks === 0) { - k = k << 8 ^ k >>> 24 ^ rcon << 24; - rcon = rcon << 1 ^ (rcon & 0x80 ? 0x1b : 0); - } - ekeys[i] = ekeys[i - ks] ^ k; - } + class NodeReadable extends NodeReadableStream$1 { + constructor(webStream, options) { + super(options); + this._reader = getReader(webStream); + } - // Decryption key schedule - for (var j = 0; j < i; j += 4) { - for (var jj = 0; jj < 4; jj++) { - var k = ekeys[i - (4 + j) + (4 - jj) % 4]; - if (j < 4 || j >= i - 4) { - dkeys[j + jj] = k; - } else { - dkeys[j + jj] = aes_dec[0][aes_sbox[k >>> 24]] ^ aes_dec[1][aes_sbox[k >>> 16 & 255]] ^ aes_dec[2][aes_sbox[k >>> 8 & 255]] ^ aes_dec[3][aes_sbox[k & 255]]; + async _read(size) { + try { + while (true) { + const { done, value } = await this._reader.read(); + if (done) { + this.push(null); + break; + } + if (!this.push(value) || this._cancelling) { + this._reading = false; + break; } } + } catch(e) { + this.emit('error', e); } - - // Set rounds number - asm.set_rounds(ks + 5); } - // create library object with necessary properties - var stdlib = { Uint8Array: Uint8Array, Uint32Array: Uint32Array }; - - var asm = function (stdlib, foreign, buffer) { - "use asm"; + _destroy(reason) { + this._reader.cancel(reason); + } + } - var S0 = 0, - S1 = 0, - S2 = 0, - S3 = 0, - I0 = 0, - I1 = 0, - I2 = 0, - I3 = 0, - N0 = 0, - N1 = 0, - N2 = 0, - N3 = 0, - M0 = 0, - M1 = 0, - M2 = 0, - M3 = 0, - H0 = 0, - H1 = 0, - H2 = 0, - H3 = 0, - R = 0; + /** + * Convert a Web ReadableStream to a Node Readable Stream + * @param {ReadableStream} webStream + * @param {Object} options + * @returns {Readable} + */ + webToNode = function(webStream, options) { + return new NodeReadable(webStream, options); + }; - var HEAP = new stdlib.Uint32Array(buffer), - DATA = new stdlib.Uint8Array(buffer); +} - /** - * AES core - * @param {number} k - precomputed key schedule offset - * @param {number} s - precomputed sbox table offset - * @param {number} t - precomputed round table offset - * @param {number} r - number of inner rounds to perform - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _core(k, s, t, r, x0, x1, x2, x3) { - k = k | 0; - s = s | 0; - t = t | 0; - r = r | 0; - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; +const doneReadingSet = new WeakSet(); +const externalBuffer = Symbol('externalBuffer'); - var t1 = 0, - t2 = 0, - t3 = 0, - y0 = 0, - y1 = 0, - y2 = 0, - y3 = 0, - i = 0; +/** + * A wrapper class over the native ReadableStreamDefaultReader. + * This additionally implements pushing back data on the stream, which + * lets us implement peeking and a host of convenience functions. + * It also lets you read data other than streams, such as a Uint8Array. + * @class + */ +function Reader(input) { + this.stream = input; + if (input[externalBuffer]) { + this[externalBuffer] = input[externalBuffer].slice(); + } + if (isArrayStream(input)) { + const reader = input.getReader(); + this._read = reader.read.bind(reader); + this._releaseLock = () => {}; + this._cancel = () => {}; + return; + } + let streamType = isStream(input); + if (streamType === 'node') { + input = nodeToWeb(input); + } + if (streamType) { + const reader = input.getReader(); + this._read = reader.read.bind(reader); + this._releaseLock = () => { + reader.closed.catch(function() {}); + reader.releaseLock(); + }; + this._cancel = reader.cancel.bind(reader); + return; + } + let doneReading = false; + this._read = async () => { + if (doneReading || doneReadingSet.has(input)) { + return { value: undefined, done: true }; + } + doneReading = true; + return { value: input, done: false }; + }; + this._releaseLock = () => { + if (doneReading) { + try { + doneReadingSet.add(input); + } catch(e) {} + } + }; +} - t1 = t | 0x400, t2 = t | 0x800, t3 = t | 0xc00; +/** + * Read a chunk of data. + * @returns {Promise} Either { done: false, value: Uint8Array | String } or { done: true, value: undefined } + * @async + */ +Reader.prototype.read = async function() { + if (this[externalBuffer] && this[externalBuffer].length) { + const value = this[externalBuffer].shift(); + return { done: false, value }; + } + return this._read(); +}; - // round 0 - x0 = x0 ^ HEAP[(k | 0) >> 2], x1 = x1 ^ HEAP[(k | 4) >> 2], x2 = x2 ^ HEAP[(k | 8) >> 2], x3 = x3 ^ HEAP[(k | 12) >> 2]; +/** + * Allow others to read the stream. + */ +Reader.prototype.releaseLock = function() { + if (this[externalBuffer]) { + this.stream[externalBuffer] = this[externalBuffer]; + } + this._releaseLock(); +}; - // round 1..r - for (i = 16; (i | 0) <= r << 4; i = i + 16 | 0) { - y0 = HEAP[(t | x0 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x1 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x2 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x3 << 2 & 1020) >> 2] ^ HEAP[(k | i | 0) >> 2], y1 = HEAP[(t | x1 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x2 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x3 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x0 << 2 & 1020) >> 2] ^ HEAP[(k | i | 4) >> 2], y2 = HEAP[(t | x2 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x3 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x0 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x1 << 2 & 1020) >> 2] ^ HEAP[(k | i | 8) >> 2], y3 = HEAP[(t | x3 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x0 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x1 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x2 << 2 & 1020) >> 2] ^ HEAP[(k | i | 12) >> 2]; - x0 = y0, x1 = y1, x2 = y2, x3 = y3; - } +/** + * Cancel the stream. + */ +Reader.prototype.cancel = function(reason) { + return this._cancel(reason); +}; - // final round - S0 = HEAP[(s | x0 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x1 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x2 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x3 << 2 & 1020) >> 2] ^ HEAP[(k | i | 0) >> 2], S1 = HEAP[(s | x1 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x2 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x3 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x0 << 2 & 1020) >> 2] ^ HEAP[(k | i | 4) >> 2], S2 = HEAP[(s | x2 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x3 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x0 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x1 << 2 & 1020) >> 2] ^ HEAP[(k | i | 8) >> 2], S3 = HEAP[(s | x3 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x0 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x1 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x2 << 2 & 1020) >> 2] ^ HEAP[(k | i | 12) >> 2]; - } +/** + * Read up to and including the first \n character. + * @returns {Promise} + * @async + */ +Reader.prototype.readLine = async function() { + let buffer = []; + let returnVal; + while (!returnVal) { + let { done, value } = await this.read(); + value += ''; + if (done) { + if (buffer.length) return concat(buffer); + return; + } + const lineEndIndex = value.indexOf('\n') + 1; + if (lineEndIndex) { + returnVal = concat(buffer.concat(value.substr(0, lineEndIndex))); + buffer = []; + } + if (lineEndIndex !== value.length) { + buffer.push(value.substr(lineEndIndex)); + } + } + this.unshift(...buffer); + return returnVal; +}; - /** - * ECB mode encryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _ecb_enc(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; +/** + * Read a single byte/character. + * @returns {Promise} + * @async + */ +Reader.prototype.readByte = async function() { + const { done, value } = await this.read(); + if (done) return; + const byte = value[0]; + this.unshift(slice(value, 1)); + return byte; +}; - _core(0x0000, 0x0800, 0x1000, R, x0, x1, x2, x3); - } +/** + * Read a specific amount of bytes/characters, unless the stream ends before that amount. + * @returns {Promise} + * @async + */ +Reader.prototype.readBytes = async function(length) { + const buffer = []; + let bufferLength = 0; + while (true) { + const { done, value } = await this.read(); + if (done) { + if (buffer.length) return concat(buffer); + return; + } + buffer.push(value); + bufferLength += value.length; + if (bufferLength >= length) { + const bufferConcat = concat(buffer); + this.unshift(slice(bufferConcat, length)); + return slice(bufferConcat, 0, length); + } + } +}; - /** - * ECB mode decryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _ecb_dec(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - var t = 0; +/** + * Peek (look ahead) a specific amount of bytes/characters, unless the stream ends before that amount. + * @returns {Promise} + * @async + */ +Reader.prototype.peekBytes = async function(length) { + const bytes = await this.readBytes(length); + this.unshift(bytes); + return bytes; +}; - _core(0x0400, 0x0c00, 0x2000, R, x0, x3, x2, x1); +/** + * Push data to the front of the stream. + * Data must have been read in the last call to read*. + * @param {...(Uint8Array|String|Undefined)} values + */ +Reader.prototype.unshift = function(...values) { + if (!this[externalBuffer]) { + this[externalBuffer] = []; + } + if ( + values.length === 1 && isUint8Array(values[0]) && + this[externalBuffer].length && values[0].length && + this[externalBuffer][0].byteOffset >= values[0].length + ) { + this[externalBuffer][0] = new Uint8Array( + this[externalBuffer][0].buffer, + this[externalBuffer][0].byteOffset - values[0].length, + this[externalBuffer][0].byteLength + values[0].length + ); + return; + } + this[externalBuffer].unshift(...values.filter(value => value && value.length)); +}; - t = S1, S1 = S3, S3 = t; - } +/** + * Read the stream to the end and return its contents, concatenated by the join function (defaults to streams.concat). + * @param {Function} join + * @returns {Promise} the return value of join() + * @async + */ +Reader.prototype.readToEnd = async function(join=concat) { + const result = []; + while (true) { + const { done, value } = await this.read(); + if (done) break; + result.push(value); + } + return join(result); +}; - /** - * CBC mode encryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _cbc_enc(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; +let { ReadableStream, WritableStream, TransformStream } = globalThis; - _core(0x0000, 0x0800, 0x1000, R, I0 ^ x0, I1 ^ x1, I2 ^ x2, I3 ^ x3); +let toPonyfillReadable, toNativeReadable; - I0 = S0, I1 = S1, I2 = S2, I3 = S3; - } +async function loadStreamsPonyfill() { + if (TransformStream) { + return; + } - /** - * CBC mode decryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _cbc_dec(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; + const [ponyfill, adapter] = await Promise.all([ + Promise.resolve().then(function () { return ponyfill_es6; }), + Promise.resolve().then(function () { return webStreamsAdapter; }) + ]); - var t = 0; + ({ ReadableStream, WritableStream, TransformStream } = ponyfill); - _core(0x0400, 0x0c00, 0x2000, R, x0, x3, x2, x1); + const { createReadableStreamWrapper } = adapter; - t = S1, S1 = S3, S3 = t; + if (globalThis.ReadableStream && ReadableStream !== globalThis.ReadableStream) { + toPonyfillReadable = createReadableStreamWrapper(ReadableStream); + toNativeReadable = createReadableStreamWrapper(globalThis.ReadableStream); + } +} - S0 = S0 ^ I0, S1 = S1 ^ I1, S2 = S2 ^ I2, S3 = S3 ^ I3; +const NodeBuffer$1 = isNode && buffer__default['default'].Buffer; - I0 = x0, I1 = x1, I2 = x2, I3 = x3; - } +/** + * Convert data to Stream + * @param {ReadableStream|Uint8array|String} input data to convert + * @returns {ReadableStream} Converted data + */ +function toStream(input) { + let streamType = isStream(input); + if (streamType === 'node') { + return nodeToWeb(input); + } + if (streamType === 'web' && toPonyfillReadable) { + return toPonyfillReadable(input); + } + if (streamType) { + return input; + } + return new ReadableStream({ + start(controller) { + controller.enqueue(input); + controller.close(); + } + }); +} - /** - * CFB mode encryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _cfb_enc(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; +/** + * Convert data to ArrayStream + * @param {Object} input data to convert + * @returns {ArrayStream} Converted data + */ +function toArrayStream(input) { + if (isStream(input)) { + return input; + } + const stream = new ArrayStream(); + (async () => { + const writer = getWriter(stream); + await writer.write(input); + await writer.close(); + })(); + return stream; +} - _core(0x0000, 0x0800, 0x1000, R, I0, I1, I2, I3); +/** + * Concat a list of Uint8Arrays, Strings or Streams + * The caller should not mix Uint8Arrays with Strings, but may mix Streams with non-Streams. + * @param {Array} Array of Uint8Arrays/Strings/Streams to concatenate + * @returns {Uint8array|String|ReadableStream} Concatenated array + */ +function concat(list) { + if (list.some(stream => isStream(stream) && !isArrayStream(stream))) { + return concatStream(list); + } + if (list.some(stream => isArrayStream(stream))) { + return concatArrayStream(list); + } + if (typeof list[0] === 'string') { + return list.join(''); + } + if (NodeBuffer$1 && NodeBuffer$1.isBuffer(list[0])) { + return NodeBuffer$1.concat(list); + } + return concatUint8Array(list); +} - I0 = S0 = S0 ^ x0, I1 = S1 = S1 ^ x1, I2 = S2 = S2 ^ x2, I3 = S3 = S3 ^ x3; - } +/** + * Concat a list of Streams + * @param {Array} list Array of Uint8Arrays/Strings/Streams to concatenate + * @returns {ReadableStream} Concatenated list + */ +function concatStream(list) { + list = list.map(toStream); + const transform = transformWithCancel(async function(reason) { + await Promise.all(transforms.map(stream => cancel(stream, reason))); + }); + let prev = Promise.resolve(); + const transforms = list.map((stream, i) => transformPair(stream, (readable, writable) => { + prev = prev.then(() => pipe(readable, transform.writable, { + preventClose: i !== list.length - 1 + })); + return prev; + })); + return transform.readable; +} - /** - * CFB mode decryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _cfb_dec(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; +/** + * Concat a list of ArrayStreams + * @param {Array} list Array of Uint8Arrays/Strings/ArrayStreams to concatenate + * @returns {ArrayStream} Concatenated streams + */ +function concatArrayStream(list) { + const result = new ArrayStream(); + let prev = Promise.resolve(); + list.forEach((stream, i) => { + prev = prev.then(() => pipe(stream, result, { + preventClose: i !== list.length - 1 + })); + return prev; + }); + return result; +} - _core(0x0000, 0x0800, 0x1000, R, I0, I1, I2, I3); +/** + * Get a Reader + * @param {ReadableStream|Uint8array|String} input + * @returns {Reader} + */ +function getReader(input) { + return new Reader(input); +} - S0 = S0 ^ x0, S1 = S1 ^ x1, S2 = S2 ^ x2, S3 = S3 ^ x3; +/** + * Get a Writer + * @param {WritableStream} input + * @returns {Writer} + */ +function getWriter(input) { + return new Writer(input); +} - I0 = x0, I1 = x1, I2 = x2, I3 = x3; +/** + * Pipe a readable stream to a writable stream. Don't throw on input stream errors, but forward them to the output stream. + * @param {ReadableStream|Uint8array|String} input + * @param {WritableStream} target + * @param {Object} (optional) options + * @returns {Promise} Promise indicating when piping has finished (input stream closed or errored) + * @async + */ +async function pipe(input, target, { + preventClose = false, + preventAbort = false, + preventCancel = false +} = {}) { + if (isStream(input) && !isArrayStream(input)) { + input = toStream(input); + try { + if (input[externalBuffer]) { + const writer = getWriter(target); + for (let i = 0; i < input[externalBuffer].length; i++) { + await writer.ready; + await writer.write(input[externalBuffer][i]); + } + writer.releaseLock(); } - - /** - * OFB mode encryption / decryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _ofb(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core(0x0000, 0x0800, 0x1000, R, I0, I1, I2, I3); - - I0 = S0, I1 = S1, I2 = S2, I3 = S3; - - S0 = S0 ^ x0, S1 = S1 ^ x1, S2 = S2 ^ x2, S3 = S3 ^ x3; + await input.pipeTo(target, { + preventClose, + preventAbort, + preventCancel + }); + } catch(e) {} + return; + } + input = toArrayStream(input); + const reader = getReader(input); + const writer = getWriter(target); + try { + while (true) { + await writer.ready; + const { done, value } = await reader.read(); + if (done) { + if (!preventClose) await writer.close(); + break; } + await writer.write(value); + } + } catch (e) { + if (!preventAbort) await writer.abort(e); + } finally { + reader.releaseLock(); + writer.releaseLock(); + } +} - /** - * CTR mode encryption / decryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _ctr(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core(0x0000, 0x0800, 0x1000, R, N0, N1, N2, N3); - - N3 = ~M3 & N3 | M3 & N3 + 1; - N2 = ~M2 & N2 | M2 & N2 + ((N3 | 0) == 0); - N1 = ~M1 & N1 | M1 & N1 + ((N2 | 0) == 0); - N0 = ~M0 & N0 | M0 & N0 + ((N1 | 0) == 0); - - S0 = S0 ^ x0; - S1 = S1 ^ x1; - S2 = S2 ^ x2; - S3 = S3 ^ x3; - } +/** + * Pipe a readable stream through a transform stream. + * @param {ReadableStream|Uint8array|String} input + * @param {Object} (optional) options + * @returns {ReadableStream} transformed stream + */ +function transformRaw(input, options) { + const transformStream = new TransformStream(options); + pipe(input, transformStream.writable); + return transformStream.readable; +} - /** - * GCM mode MAC calculation - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _gcm_mac(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - var y0 = 0, - y1 = 0, - y2 = 0, - y3 = 0, - z0 = 0, - z1 = 0, - z2 = 0, - z3 = 0, - i = 0, - c = 0; - - x0 = x0 ^ I0, x1 = x1 ^ I1, x2 = x2 ^ I2, x3 = x3 ^ I3; - - y0 = H0 | 0, y1 = H1 | 0, y2 = H2 | 0, y3 = H3 | 0; - - for (; (i | 0) < 128; i = i + 1 | 0) { - if (y0 >>> 31) { - z0 = z0 ^ x0, z1 = z1 ^ x1, z2 = z2 ^ x2, z3 = z3 ^ x3; - } - - y0 = y0 << 1 | y1 >>> 31, y1 = y1 << 1 | y2 >>> 31, y2 = y2 << 1 | y3 >>> 31, y3 = y3 << 1; - - c = x3 & 1; - - x3 = x3 >>> 1 | x2 << 31, x2 = x2 >>> 1 | x1 << 31, x1 = x1 >>> 1 | x0 << 31, x0 = x0 >>> 1; - - if (c) x0 = x0 ^ 0xe1000000; +/** + * Create a cancelable TransformStream. + * @param {Function} cancel + * @returns {TransformStream} + */ +function transformWithCancel(cancel) { + let pulled = false; + let backpressureChangePromiseResolve; + let outputController; + return { + readable: new ReadableStream({ + start(controller) { + outputController = controller; + }, + pull() { + if (backpressureChangePromiseResolve) { + backpressureChangePromiseResolve(); + } else { + pulled = true; } + }, + cancel + }, {highWaterMark: 0}), + writable: new WritableStream({ + write: async function(chunk) { + outputController.enqueue(chunk); + if (!pulled) { + await new Promise(resolve => { + backpressureChangePromiseResolve = resolve; + }); + backpressureChangePromiseResolve = null; + } else { + pulled = false; + } + }, + close: outputController.close.bind(outputController), + abort: outputController.error.bind(outputController) + }) + }; +} - I0 = z0, I1 = z1, I2 = z2, I3 = z3; - } - - /** - * Set the internal rounds number. - * @instance - * @memberof AES_asm - * @param {number} r - number if inner AES rounds - */ - function set_rounds(r) { - r = r | 0; - R = r; +/** + * Transform a stream using helper functions which are called on each chunk, and on stream close, respectively. + * @param {ReadableStream|Uint8array|String} input + * @param {Function} process + * @param {Function} finish + * @returns {ReadableStream|Uint8array|String} + */ +function transform(input, process = () => undefined, finish = () => undefined) { + if (isArrayStream(input)) { + const output = new ArrayStream(); + (async () => { + const data = await readToEnd(input); + const result1 = process(data); + const result2 = finish(); + let result; + if (result1 !== undefined && result2 !== undefined) result = concat([result1, result2]); + else result = result1 !== undefined ? result1 : result2; + const writer = getWriter(output); + await writer.write(result); + await writer.close(); + })(); + return output; + } + if (isStream(input)) { + return transformRaw(input, { + async transform(value, controller) { + try { + const result = await process(value); + if (result !== undefined) controller.enqueue(result); + } catch(e) { + controller.error(e); + } + }, + async flush(controller) { + try { + const result = await finish(); + if (result !== undefined) controller.enqueue(result); + } catch(e) { + controller.error(e); + } } + }); + } + const result1 = process(input); + const result2 = finish(); + if (result1 !== undefined && result2 !== undefined) return concat([result1, result2]); + return result1 !== undefined ? result1 : result2; +} - /** - * Populate the internal state of the module. - * @instance - * @memberof AES_asm - * @param {number} s0 - state vector - * @param {number} s1 - state vector - * @param {number} s2 - state vector - * @param {number} s3 - state vector - */ - function set_state(s0, s1, s2, s3) { - s0 = s0 | 0; - s1 = s1 | 0; - s2 = s2 | 0; - s3 = s3 | 0; - - S0 = s0, S1 = s1, S2 = s2, S3 = s3; +/** + * Transform a stream using a helper function which is passed a readable and a writable stream. + * This function also maintains the possibility to cancel the input stream, + * and does so on cancelation of the output stream, despite cancelation + * normally being impossible when the input stream is being read from. + * @param {ReadableStream|Uint8array|String} input + * @param {Function} fn + * @returns {ReadableStream} + */ +function transformPair(input, fn) { + if (isStream(input) && !isArrayStream(input)) { + let incomingTransformController; + const incoming = new TransformStream({ + start(controller) { + incomingTransformController = controller; } + }); - /** - * Populate the internal iv of the module. - * @instance - * @memberof AES_asm - * @param {number} i0 - iv vector - * @param {number} i1 - iv vector - * @param {number} i2 - iv vector - * @param {number} i3 - iv vector - */ - function set_iv(i0, i1, i2, i3) { - i0 = i0 | 0; - i1 = i1 | 0; - i2 = i2 | 0; - i3 = i3 | 0; + const pipeDonePromise = pipe(input, incoming.writable); - I0 = i0, I1 = i1, I2 = i2, I3 = i3; - } + const outgoing = transformWithCancel(async function() { + incomingTransformController.error(new Error('Readable side was canceled.')); + await pipeDonePromise; + await new Promise(setTimeout); + }); + fn(incoming.readable, outgoing.writable); + return outgoing.readable; + } + input = toArrayStream(input); + const output = new ArrayStream(); + fn(input, output); + return output; +} - /** - * Set nonce for CTR-family modes. - * @instance - * @memberof AES_asm - * @param {number} n0 - nonce vector - * @param {number} n1 - nonce vector - * @param {number} n2 - nonce vector - * @param {number} n3 - nonce vector - */ - function set_nonce(n0, n1, n2, n3) { - n0 = n0 | 0; - n1 = n1 | 0; - n2 = n2 | 0; - n3 = n3 | 0; +/** + * Parse a stream using a helper function which is passed a Reader. + * The reader additionally has a remainder() method which returns a + * stream pointing to the remainder of input, and is linked to input + * for cancelation. + * @param {ReadableStream|Uint8array|String} input + * @param {Function} fn + * @returns {Any} the return value of fn() + */ +function parse(input, fn) { + let returnValue; + const transformed = transformPair(input, (readable, writable) => { + const reader = getReader(readable); + reader.remainder = () => { + reader.releaseLock(); + pipe(readable, writable); + return transformed; + }; + returnValue = fn(reader); + }); + return returnValue; +} - N0 = n0, N1 = n1, N2 = n2, N3 = n3; - } +/** + * Tee a Stream for reading it twice. The input stream can no longer be read after tee()ing. + * Reading either of the two returned streams will pull from the input stream. + * The input stream will only be canceled if both of the returned streams are canceled. + * @param {ReadableStream|Uint8array|String} input + * @returns {Array} array containing two copies of input + */ +function tee(input) { + if (isArrayStream(input)) { + throw new Error('ArrayStream cannot be tee()d, use clone() instead'); + } + if (isStream(input)) { + const teed = toStream(input).tee(); + teed[0][externalBuffer] = teed[1][externalBuffer] = input[externalBuffer]; + return teed; + } + return [slice(input), slice(input)]; +} - /** - * Set counter mask for CTR-family modes. - * @instance - * @memberof AES_asm - * @param {number} m0 - counter mask vector - * @param {number} m1 - counter mask vector - * @param {number} m2 - counter mask vector - * @param {number} m3 - counter mask vector - */ - function set_mask(m0, m1, m2, m3) { - m0 = m0 | 0; - m1 = m1 | 0; - m2 = m2 | 0; - m3 = m3 | 0; +/** + * Clone a Stream for reading it twice. The input stream can still be read after clone()ing. + * Reading from the clone will pull from the input stream. + * The input stream will only be canceled if both the clone and the input stream are canceled. + * @param {ReadableStream|Uint8array|String} input + * @returns {ReadableStream|Uint8array|String} cloned input + */ +function clone(input) { + if (isArrayStream(input)) { + return input.clone(); + } + if (isStream(input)) { + const teed = tee(input); + overwrite(input, teed[0]); + return teed[1]; + } + return slice(input); +} - M0 = m0, M1 = m1, M2 = m2, M3 = m3; +/** + * Clone a Stream for reading it twice. Data will arrive at the same rate as the input stream is being read. + * Reading from the clone will NOT pull from the input stream. Data only arrives when reading the input stream. + * The input stream will NOT be canceled if the clone is canceled, only if the input stream are canceled. + * If the input stream is canceled, the clone will be errored. + * @param {ReadableStream|Uint8array|String} input + * @returns {ReadableStream|Uint8array|String} cloned input + */ +function passiveClone(input) { + if (isArrayStream(input)) { + return clone(input); + } + if (isStream(input)) { + return new ReadableStream({ + start(controller) { + const transformed = transformPair(input, async (readable, writable) => { + const reader = getReader(readable); + const writer = getWriter(writable); + try { + while (true) { + await writer.ready; + const { done, value } = await reader.read(); + if (done) { + try { controller.close(); } catch(e) {} + await writer.close(); + return; + } + try { controller.enqueue(value); } catch(e) {} + await writer.write(value); + } + } catch(e) { + controller.error(e); + await writer.abort(e); + } + }); + overwrite(input, transformed); } + }); + } + return slice(input); +} - /** - * Set counter for CTR-family modes. - * @instance - * @memberof AES_asm - * @param {number} c0 - counter vector - * @param {number} c1 - counter vector - * @param {number} c2 - counter vector - * @param {number} c3 - counter vector - */ - function set_counter(c0, c1, c2, c3) { - c0 = c0 | 0; - c1 = c1 | 0; - c2 = c2 | 0; - c3 = c3 | 0; +/** + * Modify a stream object to point to a different stream object. + * This is used internally by clone() and passiveClone() to provide an abstraction over tee(). + * @param {ReadableStream} input + * @param {ReadableStream} clone + */ +function overwrite(input, clone) { + // Overwrite input.getReader, input.locked, etc to point to clone + Object.entries(Object.getOwnPropertyDescriptors(input.constructor.prototype)).forEach(([name, descriptor]) => { + if (name === 'constructor') { + return; + } + if (descriptor.value) { + descriptor.value = descriptor.value.bind(clone); + } else { + descriptor.get = descriptor.get.bind(clone); + } + Object.defineProperty(input, name, descriptor); + }); +} - N3 = ~M3 & N3 | M3 & c3, N2 = ~M2 & N2 | M2 & c2, N1 = ~M1 & N1 | M1 & c1, N0 = ~M0 & N0 | M0 & c0; - } +/** + * Return a stream pointing to a part of the input stream. + * @param {ReadableStream|Uint8array|String} input + * @returns {ReadableStream|Uint8array|String} clone + */ +function slice(input, begin=0, end=Infinity) { + if (isArrayStream(input)) { + throw new Error('Not implemented'); + } + if (isStream(input)) { + if (begin >= 0 && end >= 0) { + let bytesRead = 0; + return transformRaw(input, { + transform(value, controller) { + if (bytesRead < end) { + if (bytesRead + value.length >= begin) { + controller.enqueue(slice(value, Math.max(begin - bytesRead, 0), end - bytesRead)); + } + bytesRead += value.length; + } else { + controller.terminate(); + } + } + }); + } + if (begin < 0 && (end < 0 || end === Infinity)) { + let lastBytes = []; + return transform(input, value => { + if (value.length >= -begin) lastBytes = [value]; + else lastBytes.push(value); + }, () => slice(concat(lastBytes), begin, end)); + } + if (begin === 0 && end < 0) { + let lastBytes; + return transform(input, value => { + const returnValue = lastBytes ? concat([lastBytes, value]) : value; + if (returnValue.length >= -end) { + lastBytes = slice(returnValue, end); + return slice(returnValue, begin, end); + } else { + lastBytes = returnValue; + } + }); + } + console.warn(`stream.slice(input, ${begin}, ${end}) not implemented efficiently.`); + return fromAsync(async () => slice(await readToEnd(input), begin, end)); + } + if (input[externalBuffer]) { + input = concat(input[externalBuffer].concat([input])); + } + if (isUint8Array(input) && !(NodeBuffer$1 && NodeBuffer$1.isBuffer(input))) { + if (end === Infinity) end = input.length; + return input.subarray(begin, end); + } + return input.slice(begin, end); +} - /** - * Store the internal state vector into the heap. - * @instance - * @memberof AES_asm - * @param {number} pos - offset where to put the data - * @return {number} The number of bytes have been written into the heap, always 16. - */ - function get_state(pos) { - pos = pos | 0; +/** + * Read a stream to the end and return its contents, concatenated by the join function (defaults to concat). + * @param {ReadableStream|Uint8array|String} input + * @param {Function} join + * @returns {Promise} the return value of join() + * @async + */ +async function readToEnd(input, join=concat) { + if (isArrayStream(input)) { + return input.readToEnd(join); + } + if (isStream(input)) { + return getReader(input).readToEnd(join); + } + return input; +} - if (pos & 15) return -1; +/** + * Cancel a stream. + * @param {ReadableStream|Uint8array|String} input + * @param {Any} reason + * @returns {Promise} indicates when the stream has been canceled + * @async + */ +async function cancel(input, reason) { + if (isStream(input)) { + if (input.cancel) { + return input.cancel(reason); + } + if (input.destroy) { + input.destroy(reason); + await new Promise(setTimeout); + return reason; + } + } +} + +/** + * Convert an async function to an ArrayStream. When the function returns, its return value is written to the stream. + * @param {Function} fn + * @returns {ArrayStream} + */ +function fromAsync(fn) { + const arrayStream = new ArrayStream(); + (async () => { + const writer = getWriter(arrayStream); + try { + await writer.write(await fn()); + await writer.close(); + } catch (e) { + await writer.abort(e); + } + })(); + return arrayStream; +} - DATA[pos | 0] = S0 >>> 24, DATA[pos | 1] = S0 >>> 16 & 255, DATA[pos | 2] = S0 >>> 8 & 255, DATA[pos | 3] = S0 & 255, DATA[pos | 4] = S1 >>> 24, DATA[pos | 5] = S1 >>> 16 & 255, DATA[pos | 6] = S1 >>> 8 & 255, DATA[pos | 7] = S1 & 255, DATA[pos | 8] = S2 >>> 24, DATA[pos | 9] = S2 >>> 16 & 255, DATA[pos | 10] = S2 >>> 8 & 255, DATA[pos | 11] = S2 & 255, DATA[pos | 12] = S3 >>> 24, DATA[pos | 13] = S3 >>> 16 & 255, DATA[pos | 14] = S3 >>> 8 & 255, DATA[pos | 15] = S3 & 255; +/* eslint-disable new-cap */ - return 16; +/** + * @fileoverview + * BigInteger implementation of basic operations + * that wraps the native BigInt library. + * Operations are not constant time, + * but we try and limit timing leakage where we can + * @module biginteger/native + * @private + */ + +/** + * @private + */ +class BigInteger { + /** + * Get a BigInteger (input must be big endian for strings and arrays) + * @param {Number|String|Uint8Array} n - Value to convert + * @throws {Error} on null or undefined input + */ + constructor(n) { + if (n === undefined) { + throw new Error('Invalid BigInteger input'); + } + + if (n instanceof Uint8Array) { + const bytes = n; + const hex = new Array(bytes.length); + for (let i = 0; i < bytes.length; i++) { + const hexByte = bytes[i].toString(16); + hex[i] = (bytes[i] <= 0xF) ? ('0' + hexByte) : hexByte; } + this.value = BigInt('0x0' + hex.join('')); + } else { + this.value = BigInt(n); + } + } - /** - * Store the internal iv vector into the heap. - * @instance - * @memberof AES_asm - * @param {number} pos - offset where to put the data - * @return {number} The number of bytes have been written into the heap, always 16. - */ - function get_iv(pos) { - pos = pos | 0; + clone() { + return new BigInteger(this.value); + } - if (pos & 15) return -1; + /** + * BigInteger increment in place + */ + iinc() { + this.value++; + return this; + } - DATA[pos | 0] = I0 >>> 24, DATA[pos | 1] = I0 >>> 16 & 255, DATA[pos | 2] = I0 >>> 8 & 255, DATA[pos | 3] = I0 & 255, DATA[pos | 4] = I1 >>> 24, DATA[pos | 5] = I1 >>> 16 & 255, DATA[pos | 6] = I1 >>> 8 & 255, DATA[pos | 7] = I1 & 255, DATA[pos | 8] = I2 >>> 24, DATA[pos | 9] = I2 >>> 16 & 255, DATA[pos | 10] = I2 >>> 8 & 255, DATA[pos | 11] = I2 & 255, DATA[pos | 12] = I3 >>> 24, DATA[pos | 13] = I3 >>> 16 & 255, DATA[pos | 14] = I3 >>> 8 & 255, DATA[pos | 15] = I3 & 255; + /** + * BigInteger increment + * @returns {BigInteger} this + 1. + */ + inc() { + return this.clone().iinc(); + } - return 16; - } + /** + * BigInteger decrement in place + */ + idec() { + this.value--; + return this; + } - /** - * GCM initialization. - * @instance - * @memberof AES_asm - */ - function gcm_init() { - _ecb_enc(0, 0, 0, 0); - H0 = S0, H1 = S1, H2 = S2, H3 = S3; - } + /** + * BigInteger decrement + * @returns {BigInteger} this - 1. + */ + dec() { + return this.clone().idec(); + } - /** - * Perform ciphering operation on the supplied data. - * @instance - * @memberof AES_asm - * @param {number} mode - block cipher mode (see {@link AES_asm} mode constants) - * @param {number} pos - offset of the data being processed - * @param {number} len - length of the data being processed - * @return {number} Actual amount of data have been processed. - */ - function cipher(mode, pos, len) { - mode = mode | 0; - pos = pos | 0; - len = len | 0; + /** + * BigInteger addition in place + * @param {BigInteger} x - Value to add + */ + iadd(x) { + this.value += x.value; + return this; + } - var ret = 0; + /** + * BigInteger addition + * @param {BigInteger} x - Value to add + * @returns {BigInteger} this + x. + */ + add(x) { + return this.clone().iadd(x); + } - if (pos & 15) return -1; + /** + * BigInteger subtraction in place + * @param {BigInteger} x - Value to subtract + */ + isub(x) { + this.value -= x.value; + return this; + } - while ((len | 0) >= 16) { - _cipher_modes[mode & 7](DATA[pos | 0] << 24 | DATA[pos | 1] << 16 | DATA[pos | 2] << 8 | DATA[pos | 3], DATA[pos | 4] << 24 | DATA[pos | 5] << 16 | DATA[pos | 6] << 8 | DATA[pos | 7], DATA[pos | 8] << 24 | DATA[pos | 9] << 16 | DATA[pos | 10] << 8 | DATA[pos | 11], DATA[pos | 12] << 24 | DATA[pos | 13] << 16 | DATA[pos | 14] << 8 | DATA[pos | 15]); + /** + * BigInteger subtraction + * @param {BigInteger} x - Value to subtract + * @returns {BigInteger} this - x. + */ + sub(x) { + return this.clone().isub(x); + } - DATA[pos | 0] = S0 >>> 24, DATA[pos | 1] = S0 >>> 16 & 255, DATA[pos | 2] = S0 >>> 8 & 255, DATA[pos | 3] = S0 & 255, DATA[pos | 4] = S1 >>> 24, DATA[pos | 5] = S1 >>> 16 & 255, DATA[pos | 6] = S1 >>> 8 & 255, DATA[pos | 7] = S1 & 255, DATA[pos | 8] = S2 >>> 24, DATA[pos | 9] = S2 >>> 16 & 255, DATA[pos | 10] = S2 >>> 8 & 255, DATA[pos | 11] = S2 & 255, DATA[pos | 12] = S3 >>> 24, DATA[pos | 13] = S3 >>> 16 & 255, DATA[pos | 14] = S3 >>> 8 & 255, DATA[pos | 15] = S3 & 255; + /** + * BigInteger multiplication in place + * @param {BigInteger} x - Value to multiply + */ + imul(x) { + this.value *= x.value; + return this; + } - ret = ret + 16 | 0, pos = pos + 16 | 0, len = len - 16 | 0; - } + /** + * BigInteger multiplication + * @param {BigInteger} x - Value to multiply + * @returns {BigInteger} this * x. + */ + mul(x) { + return this.clone().imul(x); + } - return ret | 0; - } + /** + * Compute value modulo m, in place + * @param {BigInteger} m - Modulo + */ + imod(m) { + this.value %= m.value; + if (this.isNegative()) { + this.iadd(m); + } + return this; + } - /** - * Calculates MAC of the supplied data. - * @instance - * @memberof AES_asm - * @param {number} mode - block cipher mode (see {@link AES_asm} mode constants) - * @param {number} pos - offset of the data being processed - * @param {number} len - length of the data being processed - * @return {number} Actual amount of data have been processed. - */ - function mac(mode, pos, len) { - mode = mode | 0; - pos = pos | 0; - len = len | 0; + /** + * Compute value modulo m + * @param {BigInteger} m - Modulo + * @returns {BigInteger} this mod m. + */ + mod(m) { + return this.clone().imod(m); + } - var ret = 0; + /** + * Compute modular exponentiation using square and multiply + * @param {BigInteger} e - Exponent + * @param {BigInteger} n - Modulo + * @returns {BigInteger} this ** e mod n. + */ + modExp(e, n) { + if (n.isZero()) throw Error('Modulo cannot be zero'); + if (n.isOne()) return new BigInteger(0); + if (e.isNegative()) throw Error('Unsopported negative exponent'); - if (pos & 15) return -1; + let exp = e.value; + let x = this.value; - while ((len | 0) >= 16) { - _mac_modes[mode & 1](DATA[pos | 0] << 24 | DATA[pos | 1] << 16 | DATA[pos | 2] << 8 | DATA[pos | 3], DATA[pos | 4] << 24 | DATA[pos | 5] << 16 | DATA[pos | 6] << 8 | DATA[pos | 7], DATA[pos | 8] << 24 | DATA[pos | 9] << 16 | DATA[pos | 10] << 8 | DATA[pos | 11], DATA[pos | 12] << 24 | DATA[pos | 13] << 16 | DATA[pos | 14] << 8 | DATA[pos | 15]); + x %= n.value; + let r = BigInt(1); + while (exp > BigInt(0)) { + const lsb = exp & BigInt(1); + exp >>= BigInt(1); // e / 2 + // Always compute multiplication step, to reduce timing leakage + const rx = (r * x) % n.value; + // Update r only if lsb is 1 (odd exponent) + r = lsb ? rx : r; + x = (x * x) % n.value; // Square + } + return new BigInteger(r); + } - ret = ret + 16 | 0, pos = pos + 16 | 0, len = len - 16 | 0; - } - return ret | 0; - } + /** + * Compute the inverse of this value modulo n + * Note: this and and n must be relatively prime + * @param {BigInteger} n - Modulo + * @returns {BigInteger} x such that this*x = 1 mod n + * @throws {Error} if the inverse does not exist + */ + modInv(n) { + const { gcd, x } = this._egcd(n); + if (!gcd.isOne()) { + throw new Error('Inverse does not exist'); + } + return x.add(n).mod(n); + } - /** - * AES cipher modes table (virual methods) - */ - var _cipher_modes = [_ecb_enc, _ecb_dec, _cbc_enc, _cbc_dec, _cfb_enc, _cfb_dec, _ofb, _ctr]; + /** + * Extended Eucleadian algorithm (http://anh.cs.luc.edu/331/notes/xgcd.pdf) + * Given a = this and b, compute (x, y) such that ax + by = gdc(a, b) + * @param {BigInteger} b - Second operand + * @returns {{ gcd, x, y: BigInteger }} + */ + _egcd(b) { + let x = BigInt(0); + let y = BigInt(1); + let xPrev = BigInt(1); + let yPrev = BigInt(0); - /** - * AES MAC modes table (virual methods) - */ - var _mac_modes = [_cbc_enc, _gcm_mac]; + let a = this.value; + b = b.value; - /** - * Asm.js module exports - */ - return { - set_rounds: set_rounds, - set_state: set_state, - set_iv: set_iv, - set_nonce: set_nonce, - set_mask: set_mask, - set_counter: set_counter, - get_state: get_state, - get_iv: get_iv, - gcm_init: gcm_init, - cipher: cipher, - mac: mac - }; - }(stdlib, foreign, buffer); + while (b !== BigInt(0)) { + const q = a / b; + let tmp = x; + x = xPrev - q * x; + xPrev = tmp; - asm.set_key = set_key; + tmp = y; + y = yPrev - q * y; + yPrev = tmp; - return asm; - }; + tmp = b; + b = a % b; + a = tmp; + } + + return { + x: new BigInteger(xPrev), + y: new BigInteger(yPrev), + gcd: new BigInteger(a) + }; + } /** - * AES enciphering mode constants - * @enum {number} - * @const + * Compute greatest common divisor between this and n + * @param {BigInteger} b - Operand + * @returns {BigInteger} gcd */ - wrapper.ENC = { - ECB: 0, - CBC: 2, - CFB: 4, - OFB: 6, - CTR: 7 - }, + gcd(b) { + let a = this.value; + b = b.value; + while (b !== BigInt(0)) { + const tmp = b; + b = a % b; + a = tmp; + } + return new BigInteger(a); + } /** - * AES deciphering mode constants - * @enum {number} - * @const + * Shift this to the left by x, in place + * @param {BigInteger} x - Shift value */ - wrapper.DEC = { - ECB: 1, - CBC: 3, - CFB: 5, - OFB: 6, - CTR: 7 - }, + ileftShift(x) { + this.value <<= x.value; + return this; + } /** - * AES MAC mode constants - * @enum {number} - * @const + * Shift this to the left by x + * @param {BigInteger} x - Shift value + * @returns {BigInteger} this << x. */ - wrapper.MAC = { - CBC: 0, - GCM: 1 - }; + leftShift(x) { + return this.clone().ileftShift(x); + } /** - * Heap data offset - * @type {number} - * @const + * Shift this to the right by x, in place + * @param {BigInteger} x - Shift value */ - wrapper.HEAP_DATA = 0x4000; + irightShift(x) { + this.value >>= x.value; + return this; + } - return wrapper; -}(); + /** + * Shift this to the right by x + * @param {BigInteger} x - Shift value + * @returns {BigInteger} this >> x. + */ + rightShift(x) { + return this.clone().irightShift(x); + } -},{}],3:[function(require,module,exports){ -'use strict'; + /** + * Whether this value is equal to x + * @param {BigInteger} x + * @returns {Boolean} + */ + equal(x) { + return this.value === x.value; + } -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.AES = undefined; + /** + * Whether this value is less than x + * @param {BigInteger} x + * @returns {Boolean} + */ + lt(x) { + return this.value < x.value; + } -var _aes = require('./aes.asm'); + /** + * Whether this value is less than or equal to x + * @param {BigInteger} x + * @returns {Boolean} + */ + lte(x) { + return this.value <= x.value; + } -var _utils = require('../other/utils'); + /** + * Whether this value is greater than x + * @param {BigInteger} x + * @returns {Boolean} + */ + gt(x) { + return this.value > x.value; + } -var _errors = require('../other/errors'); + /** + * Whether this value is greater than or equal to x + * @param {BigInteger} x + * @returns {Boolean} + */ + gte(x) { + return this.value >= x.value; + } -var heap_pool = []; -var asm_pool = []; -var AES = /** @class */function () { - function AES(key, iv, padding, mode) { - if (padding === void 0) { - padding = true; - } - this.pos = 0; - this.len = 0; - this.mode = mode; - // The AES object state - this.pos = 0; - this.len = 0; - this.key = key; - this.iv = iv; - this.padding = padding; - // The AES "worker" - this.acquire_asm(); - } - AES.prototype.acquire_asm = function () { - if (this.heap === undefined && this.asm === undefined) { - this.heap = heap_pool.pop() || (0, _utils._heap_init)().subarray(_aes.AES_asm.HEAP_DATA); - this.asm = asm_pool.pop() || (0, _aes.AES_asm)(null, this.heap.buffer); - this.reset(this.key, this.iv); - } - }; - AES.prototype.release_asm = function () { - heap_pool.push(this.heap); - ; - asm_pool.push(this.asm); - this.heap = undefined; - this.asm = undefined; - }; - AES.prototype.reset = function (key, iv) { - // Key - var keylen = key.length; - if (keylen !== 16 && keylen !== 24 && keylen !== 32) throw new _errors.IllegalArgumentError('illegal key size'); - var keyview = new DataView(key.buffer, key.byteOffset, key.byteLength); - this.asm.set_key(keylen >> 2, keyview.getUint32(0), keyview.getUint32(4), keyview.getUint32(8), keyview.getUint32(12), keylen > 16 ? keyview.getUint32(16) : 0, keylen > 16 ? keyview.getUint32(20) : 0, keylen > 24 ? keyview.getUint32(24) : 0, keylen > 24 ? keyview.getUint32(28) : 0); - // IV - if (iv !== undefined) { - if (iv.length !== 16) throw new _errors.IllegalArgumentError('illegal iv size'); - var ivview = new DataView(iv.buffer, iv.byteOffset, iv.byteLength); - this.asm.set_iv(ivview.getUint32(0), ivview.getUint32(4), ivview.getUint32(8), ivview.getUint32(12)); - } else { - this.asm.set_iv(0, 0, 0, 0); - } - }; - AES.prototype.AES_Encrypt_process = function (data) { - if (!(0, _utils.is_bytes)(data)) throw new TypeError("data isn't of expected type"); - this.acquire_asm(); - var asm = this.asm; - var heap = this.heap; - var amode = _aes.AES_asm.ENC[this.mode]; - var hpos = _aes.AES_asm.HEAP_DATA; - var pos = this.pos; - var len = this.len; - var dpos = 0; - var dlen = data.length || 0; - var rpos = 0; - var rlen = len + dlen & -16; - var wlen = 0; - var result = new Uint8Array(rlen); - while (dlen > 0) { - wlen = (0, _utils._heap_write)(heap, pos + len, data, dpos, dlen); - len += wlen; - dpos += wlen; - dlen -= wlen; - wlen = asm.cipher(amode, hpos + pos, len); - if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos); - rpos += wlen; - if (wlen < len) { - pos += wlen; - len -= wlen; - } else { - pos = 0; - len = 0; - } - } - this.pos = pos; - this.len = len; - return result; - }; - AES.prototype.AES_Encrypt_finish = function () { - this.acquire_asm(); - var asm = this.asm; - var heap = this.heap; - var amode = _aes.AES_asm.ENC[this.mode]; - var hpos = _aes.AES_asm.HEAP_DATA; - var pos = this.pos; - var len = this.len; - var plen = 16 - len % 16; - var rlen = len; - if (this.hasOwnProperty('padding')) { - if (this.padding) { - for (var p = 0; p < plen; ++p) { - heap[pos + len + p] = plen; - } - len += plen; - rlen = len; - } else if (len % 16) { - throw new _errors.IllegalArgumentError('data length must be a multiple of the block size'); - } - } else { - len += plen; - } - var result = new Uint8Array(rlen); - if (len) asm.cipher(amode, hpos + pos, len); - if (rlen) result.set(heap.subarray(pos, pos + rlen)); - this.pos = 0; - this.len = 0; - this.release_asm(); - return result; - }; - AES.prototype.AES_Decrypt_process = function (data) { - if (!(0, _utils.is_bytes)(data)) throw new TypeError("data isn't of expected type"); - this.acquire_asm(); - var asm = this.asm; - var heap = this.heap; - var amode = _aes.AES_asm.DEC[this.mode]; - var hpos = _aes.AES_asm.HEAP_DATA; - var pos = this.pos; - var len = this.len; - var dpos = 0; - var dlen = data.length || 0; - var rpos = 0; - var rlen = len + dlen & -16; - var plen = 0; - var wlen = 0; - if (this.padding) { - plen = len + dlen - rlen || 16; - rlen -= plen; - } - var result = new Uint8Array(rlen); - while (dlen > 0) { - wlen = (0, _utils._heap_write)(heap, pos + len, data, dpos, dlen); - len += wlen; - dpos += wlen; - dlen -= wlen; - wlen = asm.cipher(amode, hpos + pos, len - (!dlen ? plen : 0)); - if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos); - rpos += wlen; - if (wlen < len) { - pos += wlen; - len -= wlen; - } else { - pos = 0; - len = 0; - } - } - this.pos = pos; - this.len = len; - return result; - }; - AES.prototype.AES_Decrypt_finish = function () { - this.acquire_asm(); - var asm = this.asm; - var heap = this.heap; - var amode = _aes.AES_asm.DEC[this.mode]; - var hpos = _aes.AES_asm.HEAP_DATA; - var pos = this.pos; - var len = this.len; - var rlen = len; - if (len > 0) { - if (len % 16) { - if (this.hasOwnProperty('padding')) { - throw new _errors.IllegalArgumentError('data length must be a multiple of the block size'); - } else { - len += 16 - len % 16; - } - } - asm.cipher(amode, hpos + pos, len); - if (this.hasOwnProperty('padding') && this.padding) { - var pad = heap[pos + rlen - 1]; - if (pad < 1 || pad > 16 || pad > rlen) throw new _errors.SecurityError('bad padding'); - var pcheck = 0; - for (var i = pad; i > 1; i--) pcheck |= pad ^ heap[pos + rlen - i]; - if (pcheck) throw new _errors.SecurityError('bad padding'); - rlen -= pad; - } - } - var result = new Uint8Array(rlen); - if (rlen > 0) { - result.set(heap.subarray(pos, pos + rlen)); - } - this.pos = 0; - this.len = 0; - this.release_asm(); - return result; - }; - return AES; -}(); -exports.AES = AES; + isZero() { + return this.value === BigInt(0); + } -},{"../other/errors":14,"../other/utils":15,"./aes.asm":2}],4:[function(require,module,exports){ -'use strict'; + isOne() { + return this.value === BigInt(1); + } -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.AES_CBC = undefined; + isNegative() { + return this.value < BigInt(0); + } -var _aes = require('./aes'); + isEven() { + return !(this.value & BigInt(1)); + } -var _utils = require('../other/utils'); + abs() { + const res = this.clone(); + if (this.isNegative()) { + res.value = -res.value; + } + return res; + } -var __extends = undefined && undefined.__extends || function () { - var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) { - d.__proto__ = b; - } || function (d, b) { - for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; - }; - return function (d, b) { - extendStatics(d, b); - function __() { - this.constructor = d; - } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -}(); + /** + * Get this value as a string + * @returns {String} this value. + */ + toString() { + return this.value.toString(); + } -var AES_CBC = /** @class */function (_super) { - __extends(AES_CBC, _super); - function AES_CBC(key, iv, padding) { - if (padding === void 0) { - padding = true; - } - return _super.call(this, key, iv, padding, 'CBC') || this; + /** + * Get this value as an exact Number (max 53 bits) + * Fails if this value is too large + * @returns {Number} + */ + toNumber() { + const number = Number(this.value); + if (number > Number.MAX_SAFE_INTEGER) { + // We throw and error to conform with the bn.js implementation + throw new Error('Number can only safely store up to 53 bits'); } - AES_CBC.encrypt = function (data, key, padding, iv) { - if (padding === void 0) { - padding = true; - } - return new AES_CBC(key, iv, padding).encrypt(data); - }; - AES_CBC.decrypt = function (data, key, padding, iv) { - if (padding === void 0) { - padding = true; - } - return new AES_CBC(key, iv, padding).decrypt(data); - }; - AES_CBC.prototype.encrypt = function (data) { - var r1 = this.AES_Encrypt_process(data); - var r2 = this.AES_Encrypt_finish(); - return (0, _utils.joinBytes)(r1, r2); - }; - AES_CBC.prototype.decrypt = function (data) { - var r1 = this.AES_Decrypt_process(data); - var r2 = this.AES_Decrypt_finish(); - return (0, _utils.joinBytes)(r1, r2); - }; - return AES_CBC; -}(_aes.AES); -exports.AES_CBC = AES_CBC; + return number; + } -},{"../other/utils":15,"./aes":3}],5:[function(require,module,exports){ -'use strict'; + /** + * Get value of i-th bit + * @param {Number} i - Bit index + * @returns {Number} Bit value. + */ + getBit(i) { + const bit = (this.value >> BigInt(i)) & BigInt(1); + return (bit === BigInt(0)) ? 0 : 1; + } -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.AES_CFB = undefined; + /** + * Compute bit length + * @returns {Number} Bit length. + */ + bitLength() { + const zero = new BigInteger(0); + const one = new BigInteger(1); + const negOne = new BigInteger(-1); -var _aes = require('./aes'); + // -1n >> -1n is -1n + // 1n >> 1n is 0n + const target = this.isNegative() ? negOne : zero; + let bitlen = 1; + const tmp = this.clone(); + while (!tmp.irightShift(one).equal(target)) { + bitlen++; + } + return bitlen; + } -var _utils = require('../other/utils'); + /** + * Compute byte length + * @returns {Number} Byte length. + */ + byteLength() { + const zero = new BigInteger(0); + const negOne = new BigInteger(-1); -var __extends = undefined && undefined.__extends || function () { - var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) { - d.__proto__ = b; - } || function (d, b) { - for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; - }; - return function (d, b) { - extendStatics(d, b); - function __() { - this.constructor = d; - } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -}(); + const target = this.isNegative() ? negOne : zero; + const eight = new BigInteger(8); + let len = 1; + const tmp = this.clone(); + while (!tmp.irightShift(eight).equal(target)) { + len++; + } + return len; + } -var AES_CFB = /** @class */function (_super) { - __extends(AES_CFB, _super); - function AES_CFB(key, iv) { - var _this = _super.call(this, key, iv, true, 'CFB') || this; - delete _this.padding; - return _this; + /** + * Get Uint8Array representation of this number + * @param {String} endian - Endianess of output array (defaults to 'be') + * @param {Number} length - Of output array + * @returns {Uint8Array} + */ + toUint8Array(endian = 'be', length) { + // we get and parse the hex string (https://coolaj86.com/articles/convert-js-bigints-to-typedarrays/) + // this is faster than shift+mod iterations + let hex = this.value.toString(16); + if (hex.length % 2 === 1) { + hex = '0' + hex; + } + + const rawLength = hex.length / 2; + const bytes = new Uint8Array(length || rawLength); + // parse hex + const offset = length ? (length - rawLength) : 0; + let i = 0; + while (i < rawLength) { + bytes[i + offset] = parseInt(hex.slice(2 * i, 2 * i + 2), 16); + i++; } - AES_CFB.encrypt = function (data, key, iv) { - return new AES_CFB(key, iv).encrypt(data); - }; - AES_CFB.decrypt = function (data, key, iv) { - return new AES_CFB(key, iv).decrypt(data); - }; - AES_CFB.prototype.encrypt = function (data) { - var r1 = this.AES_Encrypt_process(data); - var r2 = this.AES_Encrypt_finish(); - return (0, _utils.joinBytes)(r1, r2); - }; - AES_CFB.prototype.decrypt = function (data) { - var r1 = this.AES_Decrypt_process(data); - var r2 = this.AES_Decrypt_finish(); - return (0, _utils.joinBytes)(r1, r2); - }; - return AES_CFB; -}(_aes.AES); -exports.AES_CFB = AES_CFB; -},{"../other/utils":15,"./aes":3}],6:[function(require,module,exports){ -'use strict'; + if (endian !== 'be') { + bytes.reverse(); + } -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.AES_CTR = undefined; + return bytes; + } +} -var _aes = require('./aes'); +async function getBigInteger() { + if (util.detectBigInt()) { + return BigInteger; + } else { + const { default: BigInteger } = await Promise.resolve().then(function () { return bn_interface; }); + return BigInteger; + } +} -var _errors = require('../other/errors'); +const debugMode = (() => { + try { + return process.env.NODE_ENV === 'development'; // eslint-disable-line no-process-env + } catch (e) {} + return false; +})(); -var _utils = require('../other/utils'); +const util = { + isString: function(data) { + return typeof data === 'string' || String.prototype.isPrototypeOf(data); + }, -var __extends = undefined && undefined.__extends || function () { - var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) { - d.__proto__ = b; - } || function (d, b) { - for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; - }; - return function (d, b) { - extendStatics(d, b); - function __() { - this.constructor = d; - } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -}(); + isArray: function(data) { + return Array.prototype.isPrototypeOf(data); + }, -var AES_CTR = /** @class */function (_super) { - __extends(AES_CTR, _super); - function AES_CTR(key, nonce) { - var _this = _super.call(this, key, undefined, false, 'CTR') || this; - delete _this.padding; - _this.AES_CTR_set_options(nonce); - return _this; - } - AES_CTR.encrypt = function (data, key, nonce) { - return new AES_CTR(key, nonce).encrypt(data); - }; - AES_CTR.decrypt = function (data, key, nonce) { - return new AES_CTR(key, nonce).encrypt(data); - }; - AES_CTR.prototype.encrypt = function (data) { - var r1 = this.AES_Encrypt_process(data); - var r2 = this.AES_Encrypt_finish(); - return (0, _utils.joinBytes)(r1, r2); - }; - AES_CTR.prototype.decrypt = function (data) { - var r1 = this.AES_Encrypt_process(data); - var r2 = this.AES_Encrypt_finish(); - return (0, _utils.joinBytes)(r1, r2); - }; - AES_CTR.prototype.AES_CTR_set_options = function (nonce, counter, size) { - if (size !== undefined) { - if (size < 8 || size > 48) throw new _errors.IllegalArgumentError('illegal counter size'); - var mask = Math.pow(2, size) - 1; - this.asm.set_mask(0, 0, mask / 0x100000000 | 0, mask | 0); - } else { - size = 48; - this.asm.set_mask(0, 0, 0xffff, 0xffffffff); - } - if (nonce !== undefined) { - var len = nonce.length; - if (!len || len > 16) throw new _errors.IllegalArgumentError('illegal nonce size'); - var view = new DataView(new ArrayBuffer(16)); - new Uint8Array(view.buffer).set(nonce); - this.asm.set_nonce(view.getUint32(0), view.getUint32(4), view.getUint32(8), view.getUint32(12)); - } else { - throw new Error('nonce is required'); - } - if (counter !== undefined) { - if (counter < 0 || counter >= Math.pow(2, size)) throw new _errors.IllegalArgumentError('illegal counter value'); - this.asm.set_counter(0, 0, counter / 0x100000000 | 0, counter | 0); - } - }; - return AES_CTR; -}(_aes.AES); -exports.AES_CTR = AES_CTR; + isUint8Array: isUint8Array, -},{"../other/errors":14,"../other/utils":15,"./aes":3}],7:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.AES_ECB = undefined; + isStream: isStream, -var _aes = require('./aes'); + readNumber: function (bytes) { + let n = 0; + for (let i = 0; i < bytes.length; i++) { + n += (256 ** i) * bytes[bytes.length - 1 - i]; + } + return n; + }, -var _utils = require('../other/utils'); + writeNumber: function (n, bytes) { + const b = new Uint8Array(bytes); + for (let i = 0; i < bytes; i++) { + b[i] = (n >> (8 * (bytes - i - 1))) & 0xFF; + } -var __extends = undefined && undefined.__extends || function () { - var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) { - d.__proto__ = b; - } || function (d, b) { - for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; - }; - return function (d, b) { - extendStatics(d, b); - function __() { - this.constructor = d; - } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -}(); + return b; + }, -var AES_ECB = /** @class */function (_super) { - __extends(AES_ECB, _super); - function AES_ECB(key, padding) { - if (padding === void 0) { - padding = false; - } - return _super.call(this, key, undefined, padding, 'ECB') || this; - } - AES_ECB.encrypt = function (data, key, padding) { - if (padding === void 0) { - padding = false; - } - return new AES_ECB(key, padding).encrypt(data); - }; - AES_ECB.decrypt = function (data, key, padding) { - if (padding === void 0) { - padding = false; - } - return new AES_ECB(key, padding).decrypt(data); - }; - AES_ECB.prototype.encrypt = function (data) { - var r1 = this.AES_Encrypt_process(data); - var r2 = this.AES_Encrypt_finish(); - return (0, _utils.joinBytes)(r1, r2); - }; - AES_ECB.prototype.decrypt = function (data) { - var r1 = this.AES_Decrypt_process(data); - var r2 = this.AES_Decrypt_finish(); - return (0, _utils.joinBytes)(r1, r2); - }; - return AES_ECB; -}(_aes.AES); -exports.AES_ECB = AES_ECB; + readDate: function (bytes) { + const n = util.readNumber(bytes); + const d = new Date(n * 1000); + return d; + }, -},{"../other/utils":15,"./aes":3}],8:[function(require,module,exports){ -'use strict'; + writeDate: function (time) { + const numeric = Math.floor(time.getTime() / 1000); -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.AES_GCM = undefined; + return util.writeNumber(numeric, 4); + }, -var _errors = require('../other/errors'); + normalizeDate: function (time = Date.now()) { + return time === null || time === Infinity ? time : new Date(Math.floor(+time / 1000) * 1000); + }, -var _utils = require('../other/utils'); + /** + * Read one MPI from bytes in input + * @param {Uint8Array} bytes - Input data to parse + * @returns {Uint8Array} Parsed MPI. + */ + readMPI: function (bytes) { + const bits = (bytes[0] << 8) | bytes[1]; + const bytelen = (bits + 7) >>> 3; + return bytes.subarray(2, 2 + bytelen); + }, -var _aes = require('./aes'); + /** + * Left-pad Uint8Array to length by adding 0x0 bytes + * @param {Uint8Array} bytes - Data to pad + * @param {Number} length - Padded length + * @returns {Uint8Array} Padded bytes. + */ + leftPad(bytes, length) { + const padded = new Uint8Array(length); + const offset = length - bytes.length; + padded.set(bytes, offset); + return padded; + }, -var _aes2 = require('./aes.asm'); + /** + * Convert a Uint8Array to an MPI-formatted Uint8Array. + * @param {Uint8Array} bin - An array of 8-bit integers to convert + * @returns {Uint8Array} MPI-formatted Uint8Array. + */ + uint8ArrayToMPI: function (bin) { + const bitSize = util.uint8ArrayBitLength(bin); + if (bitSize === 0) { + throw new Error('Zero MPI'); + } + const stripped = bin.subarray(bin.length - Math.ceil(bitSize / 8)); + const prefix = new Uint8Array([(bitSize & 0xFF00) >> 8, bitSize & 0xFF]); + return util.concatUint8Array([prefix, stripped]); + }, -var __extends = undefined && undefined.__extends || function () { - var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) { - d.__proto__ = b; - } || function (d, b) { - for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; - }; - return function (d, b) { - extendStatics(d, b); - function __() { - this.constructor = d; - } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -}(); + /** + * Return bit length of the input data + * @param {Uint8Array} bin input data (big endian) + * @returns bit length + */ + uint8ArrayBitLength: function (bin) { + let i; // index of leading non-zero byte + for (i = 0; i < bin.length; i++) if (bin[i] !== 0) break; + if (i === bin.length) { + return 0; + } + const stripped = bin.subarray(i); + return (stripped.length - 1) * 8 + util.nbits(stripped[0]); + }, -var _AES_GCM_data_maxLength = 68719476704; // 2^36 - 2^5 -var AES_GCM = /** @class */function (_super) { - __extends(AES_GCM, _super); - function AES_GCM(key, nonce, adata, tagSize) { - if (tagSize === void 0) { - tagSize = 16; - } - var _this = _super.call(this, key, undefined, false, 'CTR') || this; - _this.tagSize = tagSize; - _this.gamma0 = 0; - _this.counter = 1; - // Init GCM - _this.asm.gcm_init(); - // Tag size - if (_this.tagSize < 4 || _this.tagSize > 16) throw new _errors.IllegalArgumentError('illegal tagSize value'); - // Nonce - var noncelen = nonce.length || 0; - var noncebuf = new Uint8Array(16); - if (noncelen !== 12) { - _this._gcm_mac_process(nonce); - _this.heap[0] = 0; - _this.heap[1] = 0; - _this.heap[2] = 0; - _this.heap[3] = 0; - _this.heap[4] = 0; - _this.heap[5] = 0; - _this.heap[6] = 0; - _this.heap[7] = 0; - _this.heap[8] = 0; - _this.heap[9] = 0; - _this.heap[10] = 0; - _this.heap[11] = noncelen >>> 29; - _this.heap[12] = noncelen >>> 21 & 255; - _this.heap[13] = noncelen >>> 13 & 255; - _this.heap[14] = noncelen >>> 5 & 255; - _this.heap[15] = noncelen << 3 & 255; - _this.asm.mac(_aes2.AES_asm.MAC.GCM, _aes2.AES_asm.HEAP_DATA, 16); - _this.asm.get_iv(_aes2.AES_asm.HEAP_DATA); - _this.asm.set_iv(0, 0, 0, 0); - noncebuf.set(_this.heap.subarray(0, 16)); - } else { - noncebuf.set(nonce); - noncebuf[15] = 1; - } - var nonceview = new DataView(noncebuf.buffer); - _this.gamma0 = nonceview.getUint32(12); - _this.asm.set_nonce(nonceview.getUint32(0), nonceview.getUint32(4), nonceview.getUint32(8), 0); - _this.asm.set_mask(0, 0, 0, 0xffffffff); - // Associated data - if (adata !== undefined) { - if (adata.length > _AES_GCM_data_maxLength) throw new _errors.IllegalArgumentError('illegal adata length'); - if (adata.length) { - _this.adata = adata; - _this._gcm_mac_process(adata); - } else { - _this.adata = undefined; - } - } else { - _this.adata = undefined; - } - // Counter - if (_this.counter < 1 || _this.counter > 0xffffffff) throw new RangeError('counter must be a positive 32-bit integer'); - _this.asm.set_counter(0, 0, 0, _this.gamma0 + _this.counter | 0); - return _this; + /** + * Convert a hex string to an array of 8-bit integers + * @param {String} hex - A hex string to convert + * @returns {Uint8Array} An array of 8-bit integers. + */ + hexToUint8Array: function (hex) { + const result = new Uint8Array(hex.length >> 1); + for (let k = 0; k < hex.length >> 1; k++) { + result[k] = parseInt(hex.substr(k << 1, 2), 16); } - AES_GCM.encrypt = function (cleartext, key, nonce, adata, tagsize) { - return new AES_GCM(key, nonce, adata, tagsize).encrypt(cleartext); - }; - AES_GCM.decrypt = function (ciphertext, key, nonce, adata, tagsize) { - return new AES_GCM(key, nonce, adata, tagsize).decrypt(ciphertext); - }; - AES_GCM.prototype.encrypt = function (data) { - return this.AES_GCM_encrypt(data); - }; - AES_GCM.prototype.decrypt = function (data) { - return this.AES_GCM_decrypt(data); - }; - AES_GCM.prototype.AES_GCM_Encrypt_process = function (data) { - var dpos = 0; - var dlen = data.length || 0; - var asm = this.asm; - var heap = this.heap; - var counter = this.counter; - var pos = this.pos; - var len = this.len; - var rpos = 0; - var rlen = len + dlen & -16; - var wlen = 0; - if ((counter - 1 << 4) + len + dlen > _AES_GCM_data_maxLength) throw new RangeError('counter overflow'); - var result = new Uint8Array(rlen); - while (dlen > 0) { - wlen = (0, _utils._heap_write)(heap, pos + len, data, dpos, dlen); - len += wlen; - dpos += wlen; - dlen -= wlen; - wlen = asm.cipher(_aes2.AES_asm.ENC.CTR, _aes2.AES_asm.HEAP_DATA + pos, len); - wlen = asm.mac(_aes2.AES_asm.MAC.GCM, _aes2.AES_asm.HEAP_DATA + pos, wlen); - if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos); - counter += wlen >>> 4; - rpos += wlen; - if (wlen < len) { - pos += wlen; - len -= wlen; - } else { - pos = 0; - len = 0; - } - } - this.counter = counter; - this.pos = pos; - this.len = len; - return result; - }; - AES_GCM.prototype.AES_GCM_Encrypt_finish = function () { - var asm = this.asm; - var heap = this.heap; - var counter = this.counter; - var tagSize = this.tagSize; - var adata = this.adata; - var pos = this.pos; - var len = this.len; - var result = new Uint8Array(len + tagSize); - asm.cipher(_aes2.AES_asm.ENC.CTR, _aes2.AES_asm.HEAP_DATA + pos, len + 15 & -16); - if (len) result.set(heap.subarray(pos, pos + len)); - var i = len; - for (; i & 15; i++) heap[pos + i] = 0; - asm.mac(_aes2.AES_asm.MAC.GCM, _aes2.AES_asm.HEAP_DATA + pos, i); - var alen = adata !== undefined ? adata.length : 0; - var clen = (counter - 1 << 4) + len; - heap[0] = 0; - heap[1] = 0; - heap[2] = 0; - heap[3] = alen >>> 29; - heap[4] = alen >>> 21; - heap[5] = alen >>> 13 & 255; - heap[6] = alen >>> 5 & 255; - heap[7] = alen << 3 & 255; - heap[8] = heap[9] = heap[10] = 0; - heap[11] = clen >>> 29; - heap[12] = clen >>> 21 & 255; - heap[13] = clen >>> 13 & 255; - heap[14] = clen >>> 5 & 255; - heap[15] = clen << 3 & 255; - asm.mac(_aes2.AES_asm.MAC.GCM, _aes2.AES_asm.HEAP_DATA, 16); - asm.get_iv(_aes2.AES_asm.HEAP_DATA); - asm.set_counter(0, 0, 0, this.gamma0); - asm.cipher(_aes2.AES_asm.ENC.CTR, _aes2.AES_asm.HEAP_DATA, 16); - result.set(heap.subarray(0, tagSize), len); - this.counter = 1; - this.pos = 0; - this.len = 0; - return result; - }; - AES_GCM.prototype.AES_GCM_Decrypt_process = function (data) { - var dpos = 0; - var dlen = data.length || 0; - var asm = this.asm; - var heap = this.heap; - var counter = this.counter; - var tagSize = this.tagSize; - var pos = this.pos; - var len = this.len; - var rpos = 0; - var rlen = len + dlen > tagSize ? len + dlen - tagSize & -16 : 0; - var tlen = len + dlen - rlen; - var wlen = 0; - if ((counter - 1 << 4) + len + dlen > _AES_GCM_data_maxLength) throw new RangeError('counter overflow'); - var result = new Uint8Array(rlen); - while (dlen > tlen) { - wlen = (0, _utils._heap_write)(heap, pos + len, data, dpos, dlen - tlen); - len += wlen; - dpos += wlen; - dlen -= wlen; - wlen = asm.mac(_aes2.AES_asm.MAC.GCM, _aes2.AES_asm.HEAP_DATA + pos, wlen); - wlen = asm.cipher(_aes2.AES_asm.DEC.CTR, _aes2.AES_asm.HEAP_DATA + pos, wlen); - if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos); - counter += wlen >>> 4; - rpos += wlen; - pos = 0; - len = 0; - } - if (dlen > 0) { - len += (0, _utils._heap_write)(heap, 0, data, dpos, dlen); - } - this.counter = counter; - this.pos = pos; - this.len = len; - return result; - }; - AES_GCM.prototype.AES_GCM_Decrypt_finish = function () { - var asm = this.asm; - var heap = this.heap; - var tagSize = this.tagSize; - var adata = this.adata; - var counter = this.counter; - var pos = this.pos; - var len = this.len; - var rlen = len - tagSize; - if (len < tagSize) throw new _errors.IllegalStateError('authentication tag not found'); - var result = new Uint8Array(rlen); - var atag = new Uint8Array(heap.subarray(pos + rlen, pos + len)); - var i = rlen; - for (; i & 15; i++) heap[pos + i] = 0; - asm.mac(_aes2.AES_asm.MAC.GCM, _aes2.AES_asm.HEAP_DATA + pos, i); - asm.cipher(_aes2.AES_asm.DEC.CTR, _aes2.AES_asm.HEAP_DATA + pos, i); - if (rlen) result.set(heap.subarray(pos, pos + rlen)); - var alen = adata !== undefined ? adata.length : 0; - var clen = (counter - 1 << 4) + len - tagSize; - heap[0] = 0; - heap[1] = 0; - heap[2] = 0; - heap[3] = alen >>> 29; - heap[4] = alen >>> 21; - heap[5] = alen >>> 13 & 255; - heap[6] = alen >>> 5 & 255; - heap[7] = alen << 3 & 255; - heap[8] = heap[9] = heap[10] = 0; - heap[11] = clen >>> 29; - heap[12] = clen >>> 21 & 255; - heap[13] = clen >>> 13 & 255; - heap[14] = clen >>> 5 & 255; - heap[15] = clen << 3 & 255; - asm.mac(_aes2.AES_asm.MAC.GCM, _aes2.AES_asm.HEAP_DATA, 16); - asm.get_iv(_aes2.AES_asm.HEAP_DATA); - asm.set_counter(0, 0, 0, this.gamma0); - asm.cipher(_aes2.AES_asm.ENC.CTR, _aes2.AES_asm.HEAP_DATA, 16); - var acheck = 0; - for (var i_1 = 0; i_1 < tagSize; ++i_1) acheck |= atag[i_1] ^ heap[i_1]; - if (acheck) throw new _errors.SecurityError('data integrity check failed'); - this.counter = 1; - this.pos = 0; - this.len = 0; - return result; - }; - AES_GCM.prototype.AES_GCM_decrypt = function (data) { - var result1 = this.AES_GCM_Decrypt_process(data); - var result2 = this.AES_GCM_Decrypt_finish(); - var result = new Uint8Array(result1.length + result2.length); - if (result1.length) result.set(result1); - if (result2.length) result.set(result2, result1.length); - return result; - }; - AES_GCM.prototype.AES_GCM_encrypt = function (data) { - var result1 = this.AES_GCM_Encrypt_process(data); - var result2 = this.AES_GCM_Encrypt_finish(); - var result = new Uint8Array(result1.length + result2.length); - if (result1.length) result.set(result1); - if (result2.length) result.set(result2, result1.length); - return result; - }; - AES_GCM.prototype._gcm_mac_process = function (data) { - var heap = this.heap; - var asm = this.asm; - var dpos = 0; - var dlen = data.length || 0; - var wlen = 0; - while (dlen > 0) { - wlen = (0, _utils._heap_write)(heap, 0, data, dpos, dlen); - dpos += wlen; - dlen -= wlen; - while (wlen & 15) heap[wlen++] = 0; - asm.mac(_aes2.AES_asm.MAC.GCM, _aes2.AES_asm.HEAP_DATA, wlen); - } - }; - return AES_GCM; -}(_aes.AES); -exports.AES_GCM = AES_GCM; + return result; + }, -},{"../other/errors":14,"../other/utils":15,"./aes":3,"./aes.asm":2}],9:[function(require,module,exports){ -'use strict'; + /** + * Convert an array of 8-bit integers to a hex string + * @param {Uint8Array} bytes - Array of 8-bit integers to convert + * @returns {String} Hexadecimal representation of the array. + */ + uint8ArrayToHex: function (bytes) { + const r = []; + const e = bytes.length; + let c = 0; + let h; + while (c < e) { + h = bytes[c++].toString(16); + while (h.length < 2) { + h = '0' + h; + } + r.push('' + h); + } + return r.join(''); + }, -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.Hash = undefined; + /** + * Convert a string to an array of 8-bit integers + * @param {String} str - String to convert + * @returns {Uint8Array} An array of 8-bit integers. + */ + stringToUint8Array: function (str) { + return transform(str, str => { + if (!util.isString(str)) { + throw new Error('stringToUint8Array: Data must be in the form of a string'); + } -var _utils = require('../other/utils'); + const result = new Uint8Array(str.length); + for (let i = 0; i < str.length; i++) { + result[i] = str.charCodeAt(i); + } + return result; + }); + }, -var _errors = require('../other/errors'); + /** + * Convert an array of 8-bit integers to a string + * @param {Uint8Array} bytes - An array of 8-bit integers to convert + * @returns {String} String representation of the array. + */ + uint8ArrayToString: function (bytes) { + bytes = new Uint8Array(bytes); + const result = []; + const bs = 1 << 14; + const j = bytes.length; -var Hash = /** @class */function () { - function Hash() { - this.pos = 0; - this.len = 0; - this.acquire_asm(); + for (let i = 0; i < j; i += bs) { + result.push(String.fromCharCode.apply(String, bytes.subarray(i, i + bs < j ? i + bs : j))); } - Hash.prototype.acquire_asm = function () { - if (this.heap === undefined && this.asm === undefined) { - this.heap = this.constructor.heap_pool.pop() || (0, _utils._heap_init)(); - this.asm = this.constructor.asm_pool.pop() || this.constructor.asm_function({ Uint8Array: Uint8Array }, null, this.heap.buffer); - this.reset(); - } - }; - Hash.prototype.release_asm = function () { - this.constructor.heap_pool.push(this.heap); - ; - this.constructor.asm_pool.push(this.asm); - this.heap = undefined; - this.asm = undefined; - }; - Hash.prototype.reset = function () { - this.acquire_asm(); - this.result = null; - this.pos = 0; - this.len = 0; - this.asm.reset(); - return this; - }; - Hash.prototype.process = function (data) { - if (this.result !== null) throw new _errors.IllegalStateError('state must be reset before processing new data'); - this.acquire_asm(); - var asm = this.asm; - var heap = this.heap; - var hpos = this.pos; - var hlen = this.len; - var dpos = 0; - var dlen = data.length; - var wlen = 0; - while (dlen > 0) { - wlen = (0, _utils._heap_write)(heap, hpos + hlen, data, dpos, dlen); - hlen += wlen; - dpos += wlen; - dlen -= wlen; - wlen = asm.process(hpos, hlen); - hpos += wlen; - hlen -= wlen; - if (!hlen) hpos = 0; - } - this.pos = hpos; - this.len = hlen; - return this; - }; - Hash.prototype.finish = function () { - if (this.result !== null) throw new _errors.IllegalStateError('state must be reset before processing new data'); - this.acquire_asm(); - this.asm.finish(this.pos, this.len, 0); - this.result = new Uint8Array(this.HASH_SIZE); - this.result.set(this.heap.subarray(0, this.HASH_SIZE)); - this.pos = 0; - this.len = 0; - this.release_asm(); - return this; - }; - return Hash; -}(); -exports.Hash = Hash; + return result.join(''); + }, -},{"../other/errors":14,"../other/utils":15}],10:[function(require,module,exports){ -"use strict"; + /** + * Convert a native javascript string to a Uint8Array of utf8 bytes + * @param {String|ReadableStream} str - The string to convert + * @returns {Uint8Array|ReadableStream} A valid squence of utf8 bytes. + */ + encodeUTF8: function (str) { + const encoder = new TextEncoder('utf-8'); + // eslint-disable-next-line no-inner-declarations + function process(value, lastChunk = false) { + return encoder.encode(value, { stream: !lastChunk }); + } + return transform(str, process, () => process('', true)); + }, -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.sha1_asm = sha1_asm; -function sha1_asm(stdlib, foreign, buffer) { - "use asm"; - - // SHA256 state - - var H0 = 0, - H1 = 0, - H2 = 0, - H3 = 0, - H4 = 0, - TOTAL0 = 0, - TOTAL1 = 0; + /** + * Convert a Uint8Array of utf8 bytes to a native javascript string + * @param {Uint8Array|ReadableStream} utf8 - A valid squence of utf8 bytes + * @returns {String|ReadableStream} A native javascript string. + */ + decodeUTF8: function (utf8) { + const decoder = new TextDecoder('utf-8'); + // eslint-disable-next-line no-inner-declarations + function process(value, lastChunk = false) { + return decoder.decode(value, { stream: !lastChunk }); + } + return transform(utf8, process, () => process(new Uint8Array(), true)); + }, - // HMAC state - var I0 = 0, - I1 = 0, - I2 = 0, - I3 = 0, - I4 = 0, - O0 = 0, - O1 = 0, - O2 = 0, - O3 = 0, - O4 = 0; + /** + * Concat a list of Uint8Arrays, Strings or Streams + * The caller must not mix Uint8Arrays with Strings, but may mix Streams with non-Streams. + * @param {Array} Array - Of Uint8Arrays/Strings/Streams to concatenate + * @returns {Uint8Array|String|ReadableStream} Concatenated array. + */ + concat: concat, - // I/O buffer - var HEAP = new stdlib.Uint8Array(buffer); + /** + * Concat Uint8Arrays + * @param {Array} Array - Of Uint8Arrays to concatenate + * @returns {Uint8Array} Concatenated array. + */ + concatUint8Array: concatUint8Array, - function _core(w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15) { - w0 = w0 | 0; - w1 = w1 | 0; - w2 = w2 | 0; - w3 = w3 | 0; - w4 = w4 | 0; - w5 = w5 | 0; - w6 = w6 | 0; - w7 = w7 | 0; - w8 = w8 | 0; - w9 = w9 | 0; - w10 = w10 | 0; - w11 = w11 | 0; - w12 = w12 | 0; - w13 = w13 | 0; - w14 = w14 | 0; - w15 = w15 | 0; - - var a = 0, - b = 0, - c = 0, - d = 0, - e = 0, - n = 0, - t = 0, - w16 = 0, - w17 = 0, - w18 = 0, - w19 = 0, - w20 = 0, - w21 = 0, - w22 = 0, - w23 = 0, - w24 = 0, - w25 = 0, - w26 = 0, - w27 = 0, - w28 = 0, - w29 = 0, - w30 = 0, - w31 = 0, - w32 = 0, - w33 = 0, - w34 = 0, - w35 = 0, - w36 = 0, - w37 = 0, - w38 = 0, - w39 = 0, - w40 = 0, - w41 = 0, - w42 = 0, - w43 = 0, - w44 = 0, - w45 = 0, - w46 = 0, - w47 = 0, - w48 = 0, - w49 = 0, - w50 = 0, - w51 = 0, - w52 = 0, - w53 = 0, - w54 = 0, - w55 = 0, - w56 = 0, - w57 = 0, - w58 = 0, - w59 = 0, - w60 = 0, - w61 = 0, - w62 = 0, - w63 = 0, - w64 = 0, - w65 = 0, - w66 = 0, - w67 = 0, - w68 = 0, - w69 = 0, - w70 = 0, - w71 = 0, - w72 = 0, - w73 = 0, - w74 = 0, - w75 = 0, - w76 = 0, - w77 = 0, - w78 = 0, - w79 = 0; + /** + * Check Uint8Array equality + * @param {Uint8Array} array1 - First array + * @param {Uint8Array} array2 - Second array + * @returns {Boolean} Equality. + */ + equalsUint8Array: function (array1, array2) { + if (!util.isUint8Array(array1) || !util.isUint8Array(array2)) { + throw new Error('Data must be in the form of a Uint8Array'); + } - a = H0; - b = H1; - c = H2; - d = H3; - e = H4; + if (array1.length !== array2.length) { + return false; + } - // 0 - t = w0 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + for (let i = 0; i < array1.length; i++) { + if (array1[i] !== array2[i]) { + return false; + } + } + return true; + }, - // 1 - t = w1 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** + * Calculates a 16bit sum of a Uint8Array by adding each character + * codes modulus 65535 + * @param {Uint8Array} Uint8Array - To create a sum of + * @returns {Uint8Array} 2 bytes containing the sum of all charcodes % 65535. + */ + writeChecksum: function (text) { + let s = 0; + for (let i = 0; i < text.length; i++) { + s = (s + text[i]) & 0xFFFF; + } + return util.writeNumber(s, 2); + }, - // 2 - t = w2 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** + * Helper function to print a debug message. Debug + * messages are only printed if + * @param {String} str - String of the debug message + */ + printDebug: function (str) { + if (debugMode) { + console.log(str); + } + }, - // 3 - t = w3 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** + * Helper function to print a debug error. Debug + * messages are only printed if + * @param {String} str - String of the debug message + */ + printDebugError: function (error) { + if (debugMode) { + console.error(error); + } + }, - // 4 - t = w4 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + // returns bit length of the integer x + nbits: function (x) { + let r = 1; + let t = x >>> 16; + if (t !== 0) { + x = t; + r += 16; + } + t = x >> 8; + if (t !== 0) { + x = t; + r += 8; + } + t = x >> 4; + if (t !== 0) { + x = t; + r += 4; + } + t = x >> 2; + if (t !== 0) { + x = t; + r += 2; + } + t = x >> 1; + if (t !== 0) { + x = t; + r += 1; + } + return r; + }, - // 5 - t = w5 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** + * If S[1] == 0, then double(S) == (S[2..128] || 0); + * otherwise, double(S) == (S[2..128] || 0) xor + * (zeros(120) || 10000111). + * + * Both OCB and EAX (through CMAC) require this function to be constant-time. + * + * @param {Uint8Array} data + */ + double: function(data) { + const doubleVar = new Uint8Array(data.length); + const last = data.length - 1; + for (let i = 0; i < last; i++) { + doubleVar[i] = (data[i] << 1) ^ (data[i + 1] >> 7); + } + doubleVar[last] = (data[last] << 1) ^ ((data[0] >> 7) * 0x87); + return doubleVar; + }, - // 6 - t = w6 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** + * Shift a Uint8Array to the right by n bits + * @param {Uint8Array} array - The array to shift + * @param {Integer} bits - Amount of bits to shift (MUST be smaller + * than 8) + * @returns {String} Resulting array. + */ + shiftRight: function (array, bits) { + if (bits) { + for (let i = array.length - 1; i >= 0; i--) { + array[i] >>= bits; + if (i > 0) { + array[i] |= (array[i - 1] << (8 - bits)); + } + } + } + return array; + }, - // 7 - t = w7 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** + * Get native Web Cryptography api, only the current version of the spec. + * @returns {Object} The SubtleCrypto api or 'undefined'. + */ + getWebCrypto: function() { + return typeof globalThis !== 'undefined' && globalThis.crypto && globalThis.crypto.subtle; + }, - // 8 - t = w8 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** + * Detect Node.js runtime. + */ + detectNode: function() { + return typeof globalThis.process === 'object' && + typeof globalThis.process.versions === 'object'; + }, - // 9 - t = w9 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** + * Detect native BigInt support + */ + detectBigInt: () => typeof BigInt !== 'undefined', - // 10 - t = w10 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** + * Get BigInteger class + * It wraps the native BigInt type if it's available + * Otherwise it relies on bn.js + * @returns {BigInteger} + * @async + */ + getBigInteger, - // 11 - t = w11 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** + * Get native Node.js crypto api. + * @returns {Object} The crypto module or 'undefined'. + */ + getNodeCrypto: function() { + return crypto__default['default']; + }, - // 12 - t = w12 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + getNodeZlib: function() { + return zlib__default['default']; + }, - // 13 - t = w13 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** + * Get native Node.js Buffer constructor. This should be used since + * Buffer is not available under browserify. + * @returns {Function} The Buffer constructor or 'undefined'. + */ + getNodeBuffer: function() { + return (buffer__default['default'] || {}).Buffer; + }, - // 14 - t = w14 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + getHardwareConcurrency: function() { + if (util.detectNode()) { + const os = os__default['default']; + return os.cpus().length; + } - // 15 - t = w15 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + return navigator.hardwareConcurrency || 1; + }, - // 16 - n = w13 ^ w8 ^ w2 ^ w0; - w16 = n << 1 | n >>> 31; - t = w16 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + isEmailAddress: function(data) { + if (!util.isString(data)) { + return false; + } + const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+([a-zA-Z]{2,}|xn--[a-zA-Z\-0-9]+)))$/; + return re.test(data); + }, - // 17 - n = w14 ^ w9 ^ w3 ^ w1; - w17 = n << 1 | n >>> 31; - t = w17 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** + * Normalize line endings to + * Support any encoding where CR=0x0D, LF=0x0A + */ + canonicalizeEOL: function(data) { + const CR = 13; + const LF = 10; + let carryOverCR = false; - // 18 - n = w15 ^ w10 ^ w4 ^ w2; - w18 = n << 1 | n >>> 31; - t = w18 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + return transform(data, bytes => { + if (carryOverCR) { + bytes = util.concatUint8Array([new Uint8Array([CR]), bytes]); + } - // 19 - n = w16 ^ w11 ^ w5 ^ w3; - w19 = n << 1 | n >>> 31; - t = w19 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + if (bytes[bytes.length - 1] === CR) { + carryOverCR = true; + bytes = bytes.subarray(0, -1); + } else { + carryOverCR = false; + } - // 20 - n = w17 ^ w12 ^ w6 ^ w4; - w20 = n << 1 | n >>> 31; - t = w20 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + let index; + const indices = []; + for (let i = 0; ; i = index) { + index = bytes.indexOf(LF, i) + 1; + if (index) { + if (bytes[index - 2] !== CR) indices.push(index); + } else { + break; + } + } + if (!indices.length) { + return bytes; + } - // 21 - n = w18 ^ w13 ^ w7 ^ w5; - w21 = n << 1 | n >>> 31; - t = w21 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + const normalized = new Uint8Array(bytes.length + indices.length); + let j = 0; + for (let i = 0; i < indices.length; i++) { + const sub = bytes.subarray(indices[i - 1] || 0, indices[i]); + normalized.set(sub, j); + j += sub.length; + normalized[j - 1] = CR; + normalized[j] = LF; + j++; + } + normalized.set(bytes.subarray(indices[indices.length - 1] || 0), j); + return normalized; + }, () => (carryOverCR ? new Uint8Array([CR]) : undefined)); + }, - // 22 - n = w19 ^ w14 ^ w8 ^ w6; - w22 = n << 1 | n >>> 31; - t = w22 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** + * Convert line endings from canonicalized to native + * Support any encoding where CR=0x0D, LF=0x0A + */ + nativeEOL: function(data) { + const CR = 13; + const LF = 10; + let carryOverCR = false; + + return transform(data, bytes => { + if (carryOverCR && bytes[0] !== LF) { + bytes = util.concatUint8Array([new Uint8Array([CR]), bytes]); + } else { + bytes = new Uint8Array(bytes); // Don't mutate passed bytes + } - // 23 - n = w20 ^ w15 ^ w9 ^ w7; - w23 = n << 1 | n >>> 31; - t = w23 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + if (bytes[bytes.length - 1] === CR) { + carryOverCR = true; + bytes = bytes.subarray(0, -1); + } else { + carryOverCR = false; + } - // 24 - n = w21 ^ w16 ^ w10 ^ w8; - w24 = n << 1 | n >>> 31; - t = w24 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + let index; + let j = 0; + for (let i = 0; i !== bytes.length; i = index) { + index = bytes.indexOf(CR, i) + 1; + if (!index) index = bytes.length; + const last = index - (bytes[index] === LF ? 1 : 0); + if (i) bytes.copyWithin(j, i, last); + j += last - i; + } + return bytes.subarray(0, j); + }, () => (carryOverCR ? new Uint8Array([CR]) : undefined)); + }, - // 25 - n = w22 ^ w17 ^ w11 ^ w9; - w25 = n << 1 | n >>> 31; - t = w25 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** + * Remove trailing spaces and tabs from each line + */ + removeTrailingSpaces: function(text) { + return text.split('\n').map(line => { + let i = line.length - 1; + for (; i >= 0 && (line[i] === ' ' || line[i] === '\t'); i--); + return line.substr(0, i + 1); + }).join('\n'); + }, - // 26 - n = w23 ^ w18 ^ w12 ^ w10; - w26 = n << 1 | n >>> 31; - t = w26 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + wrapError: function(message, error) { + if (!error) { + return new Error(message); + } - // 27 - n = w24 ^ w19 ^ w13 ^ w11; - w27 = n << 1 | n >>> 31; - t = w27 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + // update error message + try { + error.message = message + ': ' + error.message; + } catch (e) {} - // 28 - n = w25 ^ w20 ^ w14 ^ w12; - w28 = n << 1 | n >>> 31; - t = w28 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + return error; + }, - // 29 - n = w26 ^ w21 ^ w15 ^ w13; - w29 = n << 1 | n >>> 31; - t = w29 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** + * Map allowed packet tags to corresponding classes + * Meant to be used to format `allowedPacket` for Packetlist.read + * @param {Array} allowedClasses + * @returns {Object} map from enum.packet to corresponding *Packet class + */ + constructAllowedPackets: function(allowedClasses) { + const map = {}; + allowedClasses.forEach(PacketClass => { + if (!PacketClass.tag) { + throw new Error('Invalid input: expected a packet class'); + } + map[PacketClass.tag] = PacketClass; + }); + return map; + }, - // 30 - n = w27 ^ w22 ^ w16 ^ w14; - w30 = n << 1 | n >>> 31; - t = w30 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** + * Return a Promise that will resolve as soon as one of the promises in input resolves + * or will reject if all input promises all rejected + * (similar to Promise.any, but with slightly different error handling) + * @param {Array} promises + * @return {Promise} Promise resolving to the result of the fastest fulfilled promise + * or rejected with the Error of the last resolved Promise (if all promises are rejected) + */ + anyPromise: function(promises) { + return new Promise(async (resolve, reject) => { + let exception; + await Promise.all(promises.map(async promise => { + try { + resolve(await promise); + } catch (e) { + exception = e; + } + })); + reject(exception); + }); + }, - // 31 - n = w28 ^ w23 ^ w17 ^ w15; - w31 = n << 1 | n >>> 31; - t = w31 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** + * Return either `a` or `b` based on `cond`, in algorithmic constant time. + * @param {Boolean} cond + * @param {Uint8Array} a + * @param {Uint8Array} b + * @returns `a` if `cond` is true, `b` otherwise + */ + selectUint8Array: function(cond, a, b) { + const length = Math.max(a.length, b.length); + const result = new Uint8Array(length); + let end = 0; + for (let i = 0; i < result.length; i++) { + result[i] = (a[i] & (256 - cond)) | (b[i] & (255 + cond)); + end += (cond & i < a.length) | ((1 - cond) & i < b.length); + } + return result.subarray(0, end); + }, + /** + * Return either `a` or `b` based on `cond`, in algorithmic constant time. + * NB: it only supports `a, b` with values between 0-255. + * @param {Boolean} cond + * @param {Uint8} a + * @param {Uint8} b + * @returns `a` if `cond` is true, `b` otherwise + */ + selectUint8: function(cond, a, b) { + return (a & (256 - cond)) | (b & (255 + cond)); + } +}; - // 32 - n = w29 ^ w24 ^ w18 ^ w16; - w32 = n << 1 | n >>> 31; - t = w32 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 33 - n = w30 ^ w25 ^ w19 ^ w17; - w33 = n << 1 | n >>> 31; - t = w33 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 34 - n = w31 ^ w26 ^ w20 ^ w18; - w34 = n << 1 | n >>> 31; - t = w34 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 35 - n = w32 ^ w27 ^ w21 ^ w19; - w35 = n << 1 | n >>> 31; - t = w35 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; +/* OpenPGP radix-64/base64 string encoding/decoding + * Copyright 2005 Herbert Hanewinkel, www.haneWIN.de + * version 1.0, check www.haneWIN.de for the latest version + * + * This software is provided as-is, without express or implied warranty. + * Permission to use, copy, modify, distribute or sell this software, with or + * without fee, for any purpose and by any individual or organization, is hereby + * granted, provided that the above copyright notice and this paragraph appear + * in all copies. Distribution as a part of an application or binary must + * include the above copyright notice in the documentation and/or other materials + * provided with the application or distribution. + */ - // 36 - n = w33 ^ w28 ^ w22 ^ w20; - w36 = n << 1 | n >>> 31; - t = w36 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; +const Buffer = util.getNodeBuffer(); - // 37 - n = w34 ^ w29 ^ w23 ^ w21; - w37 = n << 1 | n >>> 31; - t = w37 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; +let encodeChunk; +let decodeChunk; +if (Buffer) { + encodeChunk = buf => Buffer.from(buf).toString('base64'); + decodeChunk = str => { + const b = Buffer.from(str, 'base64'); + return new Uint8Array(b.buffer, b.byteOffset, b.byteLength); + }; +} else { + encodeChunk = buf => btoa(util.uint8ArrayToString(buf)); + decodeChunk = str => util.stringToUint8Array(atob(str)); +} - // 38 - n = w35 ^ w30 ^ w24 ^ w22; - w38 = n << 1 | n >>> 31; - t = w38 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; +/** + * Convert binary array to radix-64 + * @param {Uint8Array | ReadableStream} data - Uint8Array to convert + * @returns {String | ReadableStream} Radix-64 version of input string. + * @static + */ +function encode(data) { + let buf = new Uint8Array(); + return transform(data, value => { + buf = util.concatUint8Array([buf, value]); + const r = []; + const bytesPerLine = 45; // 60 chars per line * (3 bytes / 4 chars of base64). + const lines = Math.floor(buf.length / bytesPerLine); + const bytes = lines * bytesPerLine; + const encoded = encodeChunk(buf.subarray(0, bytes)); + for (let i = 0; i < lines; i++) { + r.push(encoded.substr(i * 60, 60)); + r.push('\n'); + } + buf = buf.subarray(bytes); + return r.join(''); + }, () => (buf.length ? encodeChunk(buf) + '\n' : '')); +} - // 39 - n = w36 ^ w31 ^ w25 ^ w23; - w39 = n << 1 | n >>> 31; - t = w39 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; +/** + * Convert radix-64 to binary array + * @param {String | ReadableStream} data - Radix-64 string to convert + * @returns {Uint8Array | ReadableStream} Binary array version of input string. + * @static + */ +function decode(data) { + let buf = ''; + return transform(data, value => { + buf += value; - // 40 - n = w37 ^ w32 ^ w26 ^ w24; - w40 = n << 1 | n >>> 31; - t = w40 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + // Count how many whitespace characters there are in buf + let spaces = 0; + const spacechars = [' ', '\t', '\r', '\n']; + for (let i = 0; i < spacechars.length; i++) { + const spacechar = spacechars[i]; + for (let pos = buf.indexOf(spacechar); pos !== -1; pos = buf.indexOf(spacechar, pos + 1)) { + spaces++; + } + } - // 41 - n = w38 ^ w33 ^ w27 ^ w25; - w41 = n << 1 | n >>> 31; - t = w41 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + // Backtrack until we have 4n non-whitespace characters + // that we can safely base64-decode + let length = buf.length; + for (; length > 0 && (length - spaces) % 4 !== 0; length--) { + if (spacechars.includes(buf[length])) spaces--; + } - // 42 - n = w39 ^ w34 ^ w28 ^ w26; - w42 = n << 1 | n >>> 31; - t = w42 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + const decoded = decodeChunk(buf.substr(0, length)); + buf = buf.substr(length); + return decoded; + }, () => decodeChunk(buf)); +} - // 43 - n = w40 ^ w35 ^ w29 ^ w27; - w43 = n << 1 | n >>> 31; - t = w43 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; +/** + * Convert a Base-64 encoded string an array of 8-bit integer + * + * Note: accepts both Radix-64 and URL-safe strings + * @param {String} base64 - Base-64 encoded string to convert + * @returns {Uint8Array} An array of 8-bit integers. + */ +function b64ToUint8Array(base64) { + return decode(base64.replace(/-/g, '+').replace(/_/g, '/')); +} - // 44 - n = w41 ^ w36 ^ w30 ^ w28; - w44 = n << 1 | n >>> 31; - t = w44 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; +/** + * Convert an array of 8-bit integer to a Base-64 encoded string + * @param {Uint8Array} bytes - An array of 8-bit integers to convert + * @param {bool} url - If true, output is URL-safe + * @returns {String} Base-64 encoded string. + */ +function uint8ArrayToB64(bytes, url) { + let encoded = encode(bytes).replace(/[\r\n]/g, ''); + if (url) { + encoded = encoded.replace(/[+]/g, '-').replace(/[/]/g, '_').replace(/[=]/g, ''); + } + return encoded; +} - // 45 - n = w42 ^ w37 ^ w31 ^ w29; - w45 = n << 1 | n >>> 31; - t = w45 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; +/** + * @module enums + */ - // 46 - n = w43 ^ w38 ^ w32 ^ w30; - w46 = n << 1 | n >>> 31; - t = w46 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; +const byValue = Symbol('byValue'); - // 47 - n = w44 ^ w39 ^ w33 ^ w31; - w47 = n << 1 | n >>> 31; - t = w47 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; +var enums = { - // 48 - n = w45 ^ w40 ^ w34 ^ w32; - w48 = n << 1 | n >>> 31; - t = w48 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** Maps curve names under various standards to one + * @see {@link https://wiki.gnupg.org/ECC|ECC - GnuPG wiki} + * @enum {String} + * @readonly + */ + curve: { + /** NIST P-256 Curve */ + 'p256': 'p256', + 'P-256': 'p256', + 'secp256r1': 'p256', + 'prime256v1': 'p256', + '1.2.840.10045.3.1.7': 'p256', + '2a8648ce3d030107': 'p256', + '2A8648CE3D030107': 'p256', - // 49 - n = w46 ^ w41 ^ w35 ^ w33; - w49 = n << 1 | n >>> 31; - t = w49 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** NIST P-384 Curve */ + 'p384': 'p384', + 'P-384': 'p384', + 'secp384r1': 'p384', + '1.3.132.0.34': 'p384', + '2b81040022': 'p384', + '2B81040022': 'p384', - // 50 - n = w47 ^ w42 ^ w36 ^ w34; - w50 = n << 1 | n >>> 31; - t = w50 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** NIST P-521 Curve */ + 'p521': 'p521', + 'P-521': 'p521', + 'secp521r1': 'p521', + '1.3.132.0.35': 'p521', + '2b81040023': 'p521', + '2B81040023': 'p521', - // 51 - n = w48 ^ w43 ^ w37 ^ w35; - w51 = n << 1 | n >>> 31; - t = w51 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** SECG SECP256k1 Curve */ + 'secp256k1': 'secp256k1', + '1.3.132.0.10': 'secp256k1', + '2b8104000a': 'secp256k1', + '2B8104000A': 'secp256k1', - // 52 - n = w49 ^ w44 ^ w38 ^ w36; - w52 = n << 1 | n >>> 31; - t = w52 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** Ed25519 */ + 'ED25519': 'ed25519', + 'ed25519': 'ed25519', + 'Ed25519': 'ed25519', + '1.3.6.1.4.1.11591.15.1': 'ed25519', + '2b06010401da470f01': 'ed25519', + '2B06010401DA470F01': 'ed25519', - // 53 - n = w50 ^ w45 ^ w39 ^ w37; - w53 = n << 1 | n >>> 31; - t = w53 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** Curve25519 */ + 'X25519': 'curve25519', + 'cv25519': 'curve25519', + 'curve25519': 'curve25519', + 'Curve25519': 'curve25519', + '1.3.6.1.4.1.3029.1.5.1': 'curve25519', + '2b060104019755010501': 'curve25519', + '2B060104019755010501': 'curve25519', - // 54 - n = w51 ^ w46 ^ w40 ^ w38; - w54 = n << 1 | n >>> 31; - t = w54 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** BrainpoolP256r1 Curve */ + 'brainpoolP256r1': 'brainpoolP256r1', + '1.3.36.3.3.2.8.1.1.7': 'brainpoolP256r1', + '2b2403030208010107': 'brainpoolP256r1', + '2B2403030208010107': 'brainpoolP256r1', - // 55 - n = w52 ^ w47 ^ w41 ^ w39; - w55 = n << 1 | n >>> 31; - t = w55 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** BrainpoolP384r1 Curve */ + 'brainpoolP384r1': 'brainpoolP384r1', + '1.3.36.3.3.2.8.1.1.11': 'brainpoolP384r1', + '2b240303020801010b': 'brainpoolP384r1', + '2B240303020801010B': 'brainpoolP384r1', - // 56 - n = w53 ^ w48 ^ w42 ^ w40; - w56 = n << 1 | n >>> 31; - t = w56 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** BrainpoolP512r1 Curve */ + 'brainpoolP512r1': 'brainpoolP512r1', + '1.3.36.3.3.2.8.1.1.13': 'brainpoolP512r1', + '2b240303020801010d': 'brainpoolP512r1', + '2B240303020801010D': 'brainpoolP512r1' + }, - // 57 - n = w54 ^ w49 ^ w43 ^ w41; - w57 = n << 1 | n >>> 31; - t = w57 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** A string to key specifier type + * @enum {Integer} + * @readonly + */ + s2k: { + simple: 0, + salted: 1, + iterated: 3, + gnu: 101 + }, - // 58 - n = w55 ^ w50 ^ w44 ^ w42; - w58 = n << 1 | n >>> 31; - t = w58 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-9.1|RFC4880bis-04, section 9.1} + * @enum {Integer} + * @readonly + */ + publicKey: { + /** RSA (Encrypt or Sign) [HAC] */ + rsaEncryptSign: 1, + /** RSA (Encrypt only) [HAC] */ + rsaEncrypt: 2, + /** RSA (Sign only) [HAC] */ + rsaSign: 3, + /** Elgamal (Encrypt only) [ELGAMAL] [HAC] */ + elgamal: 16, + /** DSA (Sign only) [FIPS186] [HAC] */ + dsa: 17, + /** ECDH (Encrypt only) [RFC6637] */ + ecdh: 18, + /** ECDSA (Sign only) [RFC6637] */ + ecdsa: 19, + /** EdDSA (Sign only) + * [{@link https://tools.ietf.org/html/draft-koch-eddsa-for-openpgp-04|Draft RFC}] */ + eddsa: 22, + /** Reserved for AEDH */ + aedh: 23, + /** Reserved for AEDSA */ + aedsa: 24 + }, - // 59 - n = w56 ^ w51 ^ w45 ^ w43; - w59 = n << 1 | n >>> 31; - t = w59 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC4880, section 9.2} + * @enum {Integer} + * @readonly + */ + symmetric: { + plaintext: 0, + /** Not implemented! */ + idea: 1, + tripledes: 2, + cast5: 3, + blowfish: 4, + aes128: 7, + aes192: 8, + aes256: 9, + twofish: 10 + }, - // 60 - n = w57 ^ w52 ^ w46 ^ w44; - w60 = n << 1 | n >>> 31; - t = w60 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** {@link https://tools.ietf.org/html/rfc4880#section-9.3|RFC4880, section 9.3} + * @enum {Integer} + * @readonly + */ + compression: { + uncompressed: 0, + /** RFC1951 */ + zip: 1, + /** RFC1950 */ + zlib: 2, + bzip2: 3 + }, - // 61 - n = w58 ^ w53 ^ w47 ^ w45; - w61 = n << 1 | n >>> 31; - t = w61 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC4880, section 9.4} + * @enum {Integer} + * @readonly + */ + hash: { + md5: 1, + sha1: 2, + ripemd: 3, + sha256: 8, + sha384: 9, + sha512: 10, + sha224: 11 + }, - // 62 - n = w59 ^ w54 ^ w48 ^ w46; - w62 = n << 1 | n >>> 31; - t = w62 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** A list of hash names as accepted by webCrypto functions. + * {@link https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest|Parameters, algo} + * @enum {String} + */ + webHash: { + 'SHA-1': 2, + 'SHA-256': 8, + 'SHA-384': 9, + 'SHA-512': 10 + }, - // 63 - n = w60 ^ w55 ^ w49 ^ w47; - w63 = n << 1 | n >>> 31; - t = w63 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-9.6|RFC4880bis-04, section 9.6} + * @enum {Integer} + * @readonly + */ + aead: { + eax: 1, + ocb: 2, + experimentalGCM: 100 // Private algorithm + }, - // 64 - n = w61 ^ w56 ^ w50 ^ w48; - w64 = n << 1 | n >>> 31; - t = w64 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** A list of packet types and numeric tags associated with them. + * @enum {Integer} + * @readonly + */ + packet: { + publicKeyEncryptedSessionKey: 1, + signature: 2, + symEncryptedSessionKey: 3, + onePassSignature: 4, + secretKey: 5, + publicKey: 6, + secretSubkey: 7, + compressedData: 8, + symmetricallyEncryptedData: 9, + marker: 10, + literalData: 11, + trust: 12, + userID: 13, + publicSubkey: 14, + userAttribute: 17, + symEncryptedIntegrityProtectedData: 18, + modificationDetectionCode: 19, + aeadEncryptedData: 20 // see IETF draft: https://tools.ietf.org/html/draft-ford-openpgp-format-00#section-2.1 + }, - // 65 - n = w62 ^ w57 ^ w51 ^ w49; - w65 = n << 1 | n >>> 31; - t = w65 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** Data types in the literal packet + * @enum {Integer} + * @readonly + */ + literal: { + /** Binary data 'b' */ + binary: 'b'.charCodeAt(), + /** Text data 't' */ + text: 't'.charCodeAt(), + /** Utf8 data 'u' */ + utf8: 'u'.charCodeAt(), + /** MIME message body part 'm' */ + mime: 'm'.charCodeAt() + }, - // 66 - n = w63 ^ w58 ^ w52 ^ w50; - w66 = n << 1 | n >>> 31; - t = w66 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - // 67 - n = w64 ^ w59 ^ w53 ^ w51; - w67 = n << 1 | n >>> 31; - t = w67 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 68 - n = w65 ^ w60 ^ w54 ^ w52; - w68 = n << 1 | n >>> 31; - t = w68 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 69 - n = w66 ^ w61 ^ w55 ^ w53; - w69 = n << 1 | n >>> 31; - t = w69 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 70 - n = w67 ^ w62 ^ w56 ^ w54; - w70 = n << 1 | n >>> 31; - t = w70 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 71 - n = w68 ^ w63 ^ w57 ^ w55; - w71 = n << 1 | n >>> 31; - t = w71 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 72 - n = w69 ^ w64 ^ w58 ^ w56; - w72 = n << 1 | n >>> 31; - t = w72 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 73 - n = w70 ^ w65 ^ w59 ^ w57; - w73 = n << 1 | n >>> 31; - t = w73 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 74 - n = w71 ^ w66 ^ w60 ^ w58; - w74 = n << 1 | n >>> 31; - t = w74 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 75 - n = w72 ^ w67 ^ w61 ^ w59; - w75 = n << 1 | n >>> 31; - t = w75 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 76 - n = w73 ^ w68 ^ w62 ^ w60; - w76 = n << 1 | n >>> 31; - t = w76 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** One pass signature packet type + * @enum {Integer} + * @readonly + */ + signature: { + /** 0x00: Signature of a binary document. */ + binary: 0, + /** 0x01: Signature of a canonical text document. + * + * Canonicalyzing the document by converting line endings. */ + text: 1, + /** 0x02: Standalone signature. + * + * This signature is a signature of only its own subpacket contents. + * It is calculated identically to a signature over a zero-lengh + * binary document. Note that it doesn't make sense to have a V3 + * standalone signature. */ + standalone: 2, + /** 0x10: Generic certification of a User ID and Public-Key packet. + * + * The issuer of this certification does not make any particular + * assertion as to how well the certifier has checked that the owner + * of the key is in fact the person described by the User ID. */ + certGeneric: 16, + /** 0x11: Persona certification of a User ID and Public-Key packet. + * + * The issuer of this certification has not done any verification of + * the claim that the owner of this key is the User ID specified. */ + certPersona: 17, + /** 0x12: Casual certification of a User ID and Public-Key packet. + * + * The issuer of this certification has done some casual + * verification of the claim of identity. */ + certCasual: 18, + /** 0x13: Positive certification of a User ID and Public-Key packet. + * + * The issuer of this certification has done substantial + * verification of the claim of identity. + * + * Most OpenPGP implementations make their "key signatures" as 0x10 + * certifications. Some implementations can issue 0x11-0x13 + * certifications, but few differentiate between the types. */ + certPositive: 19, + /** 0x30: Certification revocation signature + * + * This signature revokes an earlier User ID certification signature + * (signature class 0x10 through 0x13) or direct-key signature + * (0x1F). It should be issued by the same key that issued the + * revoked signature or an authorized revocation key. The signature + * is computed over the same data as the certificate that it + * revokes, and should have a later creation date than that + * certificate. */ + certRevocation: 48, + /** 0x18: Subkey Binding Signature + * + * This signature is a statement by the top-level signing key that + * indicates that it owns the subkey. This signature is calculated + * directly on the primary key and subkey, and not on any User ID or + * other packets. A signature that binds a signing subkey MUST have + * an Embedded Signature subpacket in this binding signature that + * contains a 0x19 signature made by the signing subkey on the + * primary key and subkey. */ + subkeyBinding: 24, + /** 0x19: Primary Key Binding Signature + * + * This signature is a statement by a signing subkey, indicating + * that it is owned by the primary key and subkey. This signature + * is calculated the same way as a 0x18 signature: directly on the + * primary key and subkey, and not on any User ID or other packets. + * + * When a signature is made over a key, the hash data starts with the + * octet 0x99, followed by a two-octet length of the key, and then body + * of the key packet. (Note that this is an old-style packet header for + * a key packet with two-octet length.) A subkey binding signature + * (type 0x18) or primary key binding signature (type 0x19) then hashes + * the subkey using the same format as the main key (also using 0x99 as + * the first octet). */ + keyBinding: 25, + /** 0x1F: Signature directly on a key + * + * This signature is calculated directly on a key. It binds the + * information in the Signature subpackets to the key, and is + * appropriate to be used for subpackets that provide information + * about the key, such as the Revocation Key subpacket. It is also + * appropriate for statements that non-self certifiers want to make + * about the key itself, rather than the binding between a key and a + * name. */ + key: 31, + /** 0x20: Key revocation signature + * + * The signature is calculated directly on the key being revoked. A + * revoked key is not to be used. Only revocation signatures by the + * key being revoked, or by an authorized revocation key, should be + * considered valid revocation signatures.a */ + keyRevocation: 32, + /** 0x28: Subkey revocation signature + * + * The signature is calculated directly on the subkey being revoked. + * A revoked subkey is not to be used. Only revocation signatures + * by the top-level signature key that is bound to this subkey, or + * by an authorized revocation key, should be considered valid + * revocation signatures. + * + * Key revocation signatures (types 0x20 and 0x28) + * hash only the key being revoked. */ + subkeyRevocation: 40, + /** 0x40: Timestamp signature. + * This signature is only meaningful for the timestamp contained in + * it. */ + timestamp: 64, + /** 0x50: Third-Party Confirmation signature. + * + * This signature is a signature over some other OpenPGP Signature + * packet(s). It is analogous to a notary seal on the signed data. + * A third-party signature SHOULD include Signature Target + * subpacket(s) to give easy identification. Note that we really do + * mean SHOULD. There are plausible uses for this (such as a blind + * party that only sees the signature, not the key or source + * document) that cannot include a target subpacket. */ + thirdParty: 80 + }, - // 77 - n = w74 ^ w69 ^ w63 ^ w61; - w77 = n << 1 | n >>> 31; - t = w77 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** Signature subpacket type + * @enum {Integer} + * @readonly + */ + signatureSubpacket: { + signatureCreationTime: 2, + signatureExpirationTime: 3, + exportableCertification: 4, + trustSignature: 5, + regularExpression: 6, + revocable: 7, + keyExpirationTime: 9, + placeholderBackwardsCompatibility: 10, + preferredSymmetricAlgorithms: 11, + revocationKey: 12, + issuer: 16, + notationData: 20, + preferredHashAlgorithms: 21, + preferredCompressionAlgorithms: 22, + keyServerPreferences: 23, + preferredKeyServer: 24, + primaryUserID: 25, + policyURI: 26, + keyFlags: 27, + signersUserID: 28, + reasonForRevocation: 29, + features: 30, + signatureTarget: 31, + embeddedSignature: 32, + issuerFingerprint: 33, + preferredAEADAlgorithms: 34 + }, - // 78 - n = w75 ^ w70 ^ w64 ^ w62; - w78 = n << 1 | n >>> 31; - t = w78 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** Key flags + * @enum {Integer} + * @readonly + */ + keyFlags: { + /** 0x01 - This key may be used to certify other keys. */ + certifyKeys: 1, + /** 0x02 - This key may be used to sign data. */ + signData: 2, + /** 0x04 - This key may be used to encrypt communications. */ + encryptCommunication: 4, + /** 0x08 - This key may be used to encrypt storage. */ + encryptStorage: 8, + /** 0x10 - The private component of this key may have been split + * by a secret-sharing mechanism. */ + splitPrivateKey: 16, + /** 0x20 - This key may be used for authentication. */ + authentication: 32, + /** 0x80 - The private component of this key may be in the + * possession of more than one person. */ + sharedPrivateKey: 128 + }, - // 79 - n = w76 ^ w71 ^ w65 ^ w63; - w79 = n << 1 | n >>> 31; - t = w79 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + /** Armor type + * @enum {Integer} + * @readonly + */ + armor: { + multipartSection: 0, + multipartLast: 1, + signed: 2, + message: 3, + publicKey: 4, + privateKey: 5, + signature: 6 + }, - H0 = H0 + a | 0; - H1 = H1 + b | 0; - H2 = H2 + c | 0; - H3 = H3 + d | 0; - H4 = H4 + e | 0; - } + /** {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.23|RFC4880, section 5.2.3.23} + * @enum {Integer} + * @readonly + */ + reasonForRevocation: { + /** No reason specified (key revocations or cert revocations) */ + noReason: 0, + /** Key is superseded (key revocations) */ + keySuperseded: 1, + /** Key material has been compromised (key revocations) */ + keyCompromised: 2, + /** Key is retired and no longer used (key revocations) */ + keyRetired: 3, + /** User ID information is no longer valid (cert revocations) */ + userIDInvalid: 32 + }, - function _core_heap(offset) { - offset = offset | 0; + /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.2.3.25|RFC4880bis-04, section 5.2.3.25} + * @enum {Integer} + * @readonly + */ + features: { + /** 0x01 - Modification Detection (packets 18 and 19) */ + modificationDetection: 1, + /** 0x02 - AEAD Encrypted Data Packet (packet 20) and version 5 + * Symmetric-Key Encrypted Session Key Packets (packet 3) */ + aead: 2, + /** 0x04 - Version 5 Public-Key Packet format and corresponding new + * fingerprint format */ + v5Keys: 4 + }, - _core(HEAP[offset | 0] << 24 | HEAP[offset | 1] << 16 | HEAP[offset | 2] << 8 | HEAP[offset | 3], HEAP[offset | 4] << 24 | HEAP[offset | 5] << 16 | HEAP[offset | 6] << 8 | HEAP[offset | 7], HEAP[offset | 8] << 24 | HEAP[offset | 9] << 16 | HEAP[offset | 10] << 8 | HEAP[offset | 11], HEAP[offset | 12] << 24 | HEAP[offset | 13] << 16 | HEAP[offset | 14] << 8 | HEAP[offset | 15], HEAP[offset | 16] << 24 | HEAP[offset | 17] << 16 | HEAP[offset | 18] << 8 | HEAP[offset | 19], HEAP[offset | 20] << 24 | HEAP[offset | 21] << 16 | HEAP[offset | 22] << 8 | HEAP[offset | 23], HEAP[offset | 24] << 24 | HEAP[offset | 25] << 16 | HEAP[offset | 26] << 8 | HEAP[offset | 27], HEAP[offset | 28] << 24 | HEAP[offset | 29] << 16 | HEAP[offset | 30] << 8 | HEAP[offset | 31], HEAP[offset | 32] << 24 | HEAP[offset | 33] << 16 | HEAP[offset | 34] << 8 | HEAP[offset | 35], HEAP[offset | 36] << 24 | HEAP[offset | 37] << 16 | HEAP[offset | 38] << 8 | HEAP[offset | 39], HEAP[offset | 40] << 24 | HEAP[offset | 41] << 16 | HEAP[offset | 42] << 8 | HEAP[offset | 43], HEAP[offset | 44] << 24 | HEAP[offset | 45] << 16 | HEAP[offset | 46] << 8 | HEAP[offset | 47], HEAP[offset | 48] << 24 | HEAP[offset | 49] << 16 | HEAP[offset | 50] << 8 | HEAP[offset | 51], HEAP[offset | 52] << 24 | HEAP[offset | 53] << 16 | HEAP[offset | 54] << 8 | HEAP[offset | 55], HEAP[offset | 56] << 24 | HEAP[offset | 57] << 16 | HEAP[offset | 58] << 8 | HEAP[offset | 59], HEAP[offset | 60] << 24 | HEAP[offset | 61] << 16 | HEAP[offset | 62] << 8 | HEAP[offset | 63]); + /** + * Asserts validity of given value and converts from string/integer to integer. + * @param {Object} type target enum type + * @param {String|Integer} e value to check and/or convert + * @returns {Integer} enum value if it exists + * @throws {Error} if the value is invalid + */ + write: function(type, e) { + if (typeof e === 'number') { + e = this.read(type, e); } - // offset — multiple of 32 - function _state_to_heap(output) { - output = output | 0; - - HEAP[output | 0] = H0 >>> 24; - HEAP[output | 1] = H0 >>> 16 & 255; - HEAP[output | 2] = H0 >>> 8 & 255; - HEAP[output | 3] = H0 & 255; - HEAP[output | 4] = H1 >>> 24; - HEAP[output | 5] = H1 >>> 16 & 255; - HEAP[output | 6] = H1 >>> 8 & 255; - HEAP[output | 7] = H1 & 255; - HEAP[output | 8] = H2 >>> 24; - HEAP[output | 9] = H2 >>> 16 & 255; - HEAP[output | 10] = H2 >>> 8 & 255; - HEAP[output | 11] = H2 & 255; - HEAP[output | 12] = H3 >>> 24; - HEAP[output | 13] = H3 >>> 16 & 255; - HEAP[output | 14] = H3 >>> 8 & 255; - HEAP[output | 15] = H3 & 255; - HEAP[output | 16] = H4 >>> 24; - HEAP[output | 17] = H4 >>> 16 & 255; - HEAP[output | 18] = H4 >>> 8 & 255; - HEAP[output | 19] = H4 & 255; - } - - function reset() { - H0 = 0x67452301; - H1 = 0xefcdab89; - H2 = 0x98badcfe; - H3 = 0x10325476; - H4 = 0xc3d2e1f0; - TOTAL0 = TOTAL1 = 0; + if (type[e] !== undefined) { + return type[e]; } - function init(h0, h1, h2, h3, h4, total0, total1) { - h0 = h0 | 0; - h1 = h1 | 0; - h2 = h2 | 0; - h3 = h3 | 0; - h4 = h4 | 0; - total0 = total0 | 0; - total1 = total1 | 0; + throw new Error('Invalid enum value.'); + }, - H0 = h0; - H1 = h1; - H2 = h2; - H3 = h3; - H4 = h4; - TOTAL0 = total0; - TOTAL1 = total1; + /** + * Converts enum integer value to the corresponding string, if it exists. + * @param {Object} type target enum type + * @param {Integer} e value to convert + * @returns {String} name of enum value if it exists + * @throws {Error} if the value is invalid + */ + read: function(type, e) { + if (!type[byValue]) { + type[byValue] = []; + Object.entries(type).forEach(([key, value]) => { + type[byValue][value] = key; + }); } - // offset — multiple of 64 - function process(offset, length) { - offset = offset | 0; - length = length | 0; - - var hashed = 0; - - if (offset & 63) return -1; - - while ((length | 0) >= 64) { - _core_heap(offset); - - offset = offset + 64 | 0; - length = length - 64 | 0; - - hashed = hashed + 64 | 0; - } - - TOTAL0 = TOTAL0 + hashed | 0; - if (TOTAL0 >>> 0 < hashed >>> 0) TOTAL1 = TOTAL1 + 1 | 0; - - return hashed | 0; + if (type[byValue][e] !== undefined) { + return type[byValue][e]; } - // offset — multiple of 64 - // output — multiple of 32 - function finish(offset, length, output) { - offset = offset | 0; - length = length | 0; - output = output | 0; - - var hashed = 0, - i = 0; - - if (offset & 63) return -1; + throw new Error('Invalid enum value.'); + } +}; - if (~output) if (output & 31) return -1; +// GPG4Browsers - An OpenPGP implementation in javascript - if ((length | 0) >= 64) { - hashed = process(offset, length) | 0; - if ((hashed | 0) == -1) return -1; - - offset = offset + hashed | 0; - length = length - hashed | 0; - } - - hashed = hashed + length | 0; - TOTAL0 = TOTAL0 + length | 0; - if (TOTAL0 >>> 0 < length >>> 0) TOTAL1 = TOTAL1 + 1 | 0; +var defaultConfig = { + /** + * @memberof module:config + * @property {Integer} preferredHashAlgorithm Default hash algorithm {@link module:enums.hash} + */ + preferredHashAlgorithm: enums.hash.sha256, + /** + * @memberof module:config + * @property {Integer} preferredSymmetricAlgorithm Default encryption cipher {@link module:enums.symmetric} + */ + preferredSymmetricAlgorithm: enums.symmetric.aes256, + /** + * @memberof module:config + * @property {Integer} compression Default compression algorithm {@link module:enums.compression} + */ + preferredCompressionAlgorithm: enums.compression.uncompressed, + /** + * @memberof module:config + * @property {Integer} deflateLevel Default zip/zlib compression level, between 1 and 9 + */ + deflateLevel: 6, - HEAP[offset | length] = 0x80; + /** + * Use Authenticated Encryption with Additional Data (AEAD) protection for symmetric encryption. + * Note: not all OpenPGP implementations are compatible with this option. + * **FUTURE OPENPGP.JS VERSIONS MAY BREAK COMPATIBILITY WHEN USING THIS OPTION** + * @see {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-07|RFC4880bis-07} + * @memberof module:config + * @property {Boolean} aeadProtect + */ + aeadProtect: false, + /** + * Default Authenticated Encryption with Additional Data (AEAD) encryption mode + * Only has an effect when aeadProtect is set to true. + * @memberof module:config + * @property {Integer} preferredAEADAlgorithm Default AEAD mode {@link module:enums.aead} + */ + preferredAEADAlgorithm: enums.aead.eax, + /** + * Chunk Size Byte for Authenticated Encryption with Additional Data (AEAD) mode + * Only has an effect when aeadProtect is set to true. + * Must be an integer value from 0 to 56. + * @memberof module:config + * @property {Integer} aeadChunkSizeByte + */ + aeadChunkSizeByte: 12, + /** + * Use V5 keys. + * Note: not all OpenPGP implementations are compatible with this option. + * **FUTURE OPENPGP.JS VERSIONS MAY BREAK COMPATIBILITY WHEN USING THIS OPTION** + * @memberof module:config + * @property {Boolean} v5Keys + */ + v5Keys: false, + /** + * {@link https://tools.ietf.org/html/rfc4880#section-3.7.1.3|RFC4880 3.7.1.3}: + * Iteration Count Byte for S2K (String to Key) + * @memberof module:config + * @property {Integer} s2kIterationCountByte + */ + s2kIterationCountByte: 224, + /** + * Allow decryption of messages without integrity protection. + * This is an **insecure** setting: + * - message modifications cannot be detected, thus processing the decrypted data is potentially unsafe. + * - it enables downgrade attacks against integrity-protected messages. + * @memberof module:config + * @property {Boolean} allowUnauthenticatedMessages + */ + allowUnauthenticatedMessages: false, + /** + * Allow streaming unauthenticated data before its integrity has been checked. + * This setting is **insecure** if the partially decrypted message is processed further or displayed to the user. + * @memberof module:config + * @property {Boolean} allowUnauthenticatedStream + */ + allowUnauthenticatedStream: false, + /** + * @memberof module:config + * @property {Boolean} checksumRequired Do not throw error when armor is missing a checksum + */ + checksumRequired: false, + /** + * Minimum RSA key size allowed for key generation and message signing, verification and encryption. + * The default is 2047 since due to a bug, previous versions of OpenPGP.js could generate 2047-bit keys instead of 2048-bit ones. + * @memberof module:config + * @property {Number} minRSABits + */ + minRSABits: 2047, + /** + * Work-around for rare GPG decryption bug when encrypting with multiple passwords. + * **Slower and slightly less secure** + * @memberof module:config + * @property {Boolean} passwordCollisionCheck + */ + passwordCollisionCheck: false, + /** + * @memberof module:config + * @property {Boolean} revocationsExpire If true, expired revocation signatures are ignored + */ + revocationsExpire: false, + /** + * Allow decryption using RSA keys without `encrypt` flag. + * This setting is potentially insecure, but it is needed to get around an old openpgpjs bug + * where key flags were ignored when selecting a key for encryption. + * @memberof module:config + * @property {Boolean} allowInsecureDecryptionWithSigningKeys + */ + allowInsecureDecryptionWithSigningKeys: false, + /** + * Allow verification of message signatures with keys whose validity at the time of signing cannot be determined. + * Instead, a verification key will also be consider valid as long as it is valid at the current time. + * This setting is potentially insecure, but it is needed to verify messages signed with keys that were later reformatted, + * and have self-signature's creation date that does not match the primary key creation date. + * @memberof module:config + * @property {Boolean} allowInsecureDecryptionWithSigningKeys + */ + allowInsecureVerificationWithReformattedKeys: false, - if ((length | 0) >= 56) { - for (i = length + 1 | 0; (i | 0) < 64; i = i + 1 | 0) HEAP[offset | i] = 0x00; - _core_heap(offset); + /** + * Enable constant-time decryption of RSA- and ElGamal-encrypted session keys, to hinder Bleichenbacher-like attacks (https://link.springer.com/chapter/10.1007/BFb0055716). + * This setting has measurable performance impact and it is only helpful in application scenarios where both of the following conditions apply: + * - new/incoming messages are automatically decrypted (without user interaction); + * - an attacker can determine how long it takes to decrypt each message (e.g. due to decryption errors being logged remotely). + * See also `constantTimePKCS1DecryptionSupportedSymmetricAlgorithms`. + * @memberof module:config + * @property {Boolean} constantTimePKCS1Decryption + */ + constantTimePKCS1Decryption: false, + /** + * This setting is only meaningful if `constantTimePKCS1Decryption` is enabled. + * Decryption of RSA- and ElGamal-encrypted session keys of symmetric algorithms different from the ones specified here will fail. + * However, the more algorithms are added, the slower the decryption procedure becomes. + * @memberof module:config + * @property {Set} constantTimePKCS1DecryptionSupportedSymmetricAlgorithms {@link module:enums.symmetric} + */ + constantTimePKCS1DecryptionSupportedSymmetricAlgorithms: new Set([enums.symmetric.aes128, enums.symmetric.aes192, enums.symmetric.aes256]), - length = 0; + /** + * @memberof module:config + * @property {Integer} minBytesForWebCrypto The minimum amount of bytes for which to use native WebCrypto APIs when available + */ + minBytesForWebCrypto: 1000, + /** + * @memberof module:config + * @property {Boolean} ignoreUnsupportedPackets Ignore unsupported/unrecognizable packets on parsing instead of throwing an error + */ + ignoreUnsupportedPackets: true, + /** + * @memberof module:config + * @property {Boolean} ignoreMalformedPackets Ignore malformed packets on parsing instead of throwing an error + */ + ignoreMalformedPackets: false, + /** + * @memberof module:config + * @property {Boolean} showVersion Whether to include {@link module:config/config.versionString} in armored messages + */ + showVersion: false, + /** + * @memberof module:config + * @property {Boolean} showComment Whether to include {@link module:config/config.commentString} in armored messages + */ + showComment: false, + /** + * @memberof module:config + * @property {String} versionString A version string to be included in armored messages + */ + versionString: 'OpenPGP.js 5.1.0', + /** + * @memberof module:config + * @property {String} commentString A comment string to be included in armored messages + */ + commentString: 'https://openpgpjs.org', - HEAP[offset | 0] = 0; - } + /** + * Max userID string length (used for parsing) + * @memberof module:config + * @property {Integer} maxUserIDLength + */ + maxUserIDLength: 1024 * 5, + /** + * Contains notatations that are considered "known". Known notations do not trigger + * validation error when the notation is marked as critical. + * @memberof module:config + * @property {Array} knownNotations + */ + knownNotations: ['preferred-email-encoding@pgp.com', 'pka-address@gnupg.org'], + /** + * Whether to use the indutny/elliptic library for curves (other than Curve25519) that are not supported by the available native crypto API. + * When false, certain standard curves will not be supported (depending on the platform). + * Note: the indutny/elliptic curve library is not designed to be constant time. + * @memberof module:config + * @property {Boolean} useIndutnyElliptic + */ + useIndutnyElliptic: true, + /** + * Reject insecure hash algorithms + * @memberof module:config + * @property {Set} rejectHashAlgorithms {@link module:enums.hash} + */ + rejectHashAlgorithms: new Set([enums.hash.md5, enums.hash.ripemd]), + /** + * Reject insecure message hash algorithms + * @memberof module:config + * @property {Set} rejectMessageHashAlgorithms {@link module:enums.hash} + */ + rejectMessageHashAlgorithms: new Set([enums.hash.md5, enums.hash.ripemd, enums.hash.sha1]), + /** + * Reject insecure public key algorithms for key generation and message encryption, signing or verification + * @memberof module:config + * @property {Set} rejectPublicKeyAlgorithms {@link module:enums.publicKey} + */ + rejectPublicKeyAlgorithms: new Set([enums.publicKey.elgamal, enums.publicKey.dsa]), + /** + * Reject non-standard curves for key generation, message encryption, signing or verification + * @memberof module:config + * @property {Set} rejectCurves {@link module:enums.curve} + */ + rejectCurves: new Set([enums.curve.brainpoolP256r1, enums.curve.brainpoolP384r1, enums.curve.brainpoolP512r1, enums.curve.secp256k1]) +}; - for (i = length + 1 | 0; (i | 0) < 59; i = i + 1 | 0) HEAP[offset | i] = 0; +// GPG4Browsers - An OpenPGP implementation in javascript - HEAP[offset | 56] = TOTAL1 >>> 21 & 255; - HEAP[offset | 57] = TOTAL1 >>> 13 & 255; - HEAP[offset | 58] = TOTAL1 >>> 5 & 255; - HEAP[offset | 59] = TOTAL1 << 3 & 255 | TOTAL0 >>> 29; - HEAP[offset | 60] = TOTAL0 >>> 21 & 255; - HEAP[offset | 61] = TOTAL0 >>> 13 & 255; - HEAP[offset | 62] = TOTAL0 >>> 5 & 255; - HEAP[offset | 63] = TOTAL0 << 3 & 255; - _core_heap(offset); +/** + * Finds out which Ascii Armoring type is used. Throws error if unknown type. + * @param {String} text - ascii armored text + * @returns {Integer} 0 = MESSAGE PART n of m. + * 1 = MESSAGE PART n + * 2 = SIGNED MESSAGE + * 3 = PGP MESSAGE + * 4 = PUBLIC KEY BLOCK + * 5 = PRIVATE KEY BLOCK + * 6 = SIGNATURE + * @private + */ +function getType(text) { + const reHeader = /^-----BEGIN PGP (MESSAGE, PART \d+\/\d+|MESSAGE, PART \d+|SIGNED MESSAGE|MESSAGE|PUBLIC KEY BLOCK|PRIVATE KEY BLOCK|SIGNATURE)-----$/m; - if (~output) _state_to_heap(output); + const header = text.match(reHeader); - return hashed | 0; - } + if (!header) { + throw new Error('Unknown ASCII armor type'); + } - function hmac_reset() { - H0 = I0; - H1 = I1; - H2 = I2; - H3 = I3; - H4 = I4; - TOTAL0 = 64; - TOTAL1 = 0; - } + // BEGIN PGP MESSAGE, PART X/Y + // Used for multi-part messages, where the armor is split amongst Y + // parts, and this is the Xth part out of Y. + if (/MESSAGE, PART \d+\/\d+/.test(header[1])) { + return enums.armor.multipartSection; + } else + // BEGIN PGP MESSAGE, PART X + // Used for multi-part messages, where this is the Xth part of an + // unspecified number of parts. Requires the MESSAGE-ID Armor + // Header to be used. + if (/MESSAGE, PART \d+/.test(header[1])) { + return enums.armor.multipartLast; + } else + // BEGIN PGP SIGNED MESSAGE + if (/SIGNED MESSAGE/.test(header[1])) { + return enums.armor.signed; + } else + // BEGIN PGP MESSAGE + // Used for signed, encrypted, or compressed files. + if (/MESSAGE/.test(header[1])) { + return enums.armor.message; + } else + // BEGIN PGP PUBLIC KEY BLOCK + // Used for armoring public keys. + if (/PUBLIC KEY BLOCK/.test(header[1])) { + return enums.armor.publicKey; + } else + // BEGIN PGP PRIVATE KEY BLOCK + // Used for armoring private keys. + if (/PRIVATE KEY BLOCK/.test(header[1])) { + return enums.armor.privateKey; + } else + // BEGIN PGP SIGNATURE + // Used for detached signatures, OpenPGP/MIME signatures, and + // cleartext signatures. Note that PGP 2.x uses BEGIN PGP MESSAGE + // for detached signatures. + if (/SIGNATURE/.test(header[1])) { + return enums.armor.signature; + } +} - function _hmac_opad() { - H0 = O0; - H1 = O1; - H2 = O2; - H3 = O3; - H4 = O4; - TOTAL0 = 64; - TOTAL1 = 0; - } +/** + * Add additional information to the armor version of an OpenPGP binary + * packet block. + * @author Alex + * @version 2011-12-16 + * @param {String} [customComment] - Additional comment to add to the armored string + * @returns {String} The header information. + * @private + */ +function addheader(customComment, config) { + let result = ''; + if (config.showVersion) { + result += 'Version: ' + config.versionString + '\n'; + } + if (config.showComment) { + result += 'Comment: ' + config.commentString + '\n'; + } + if (customComment) { + result += 'Comment: ' + customComment + '\n'; + } + result += '\n'; + return result; +} - function hmac_init(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15) { - p0 = p0 | 0; - p1 = p1 | 0; - p2 = p2 | 0; - p3 = p3 | 0; - p4 = p4 | 0; - p5 = p5 | 0; - p6 = p6 | 0; - p7 = p7 | 0; - p8 = p8 | 0; - p9 = p9 | 0; - p10 = p10 | 0; - p11 = p11 | 0; - p12 = p12 | 0; - p13 = p13 | 0; - p14 = p14 | 0; - p15 = p15 | 0; - // opad - reset(); - _core(p0 ^ 0x5c5c5c5c, p1 ^ 0x5c5c5c5c, p2 ^ 0x5c5c5c5c, p3 ^ 0x5c5c5c5c, p4 ^ 0x5c5c5c5c, p5 ^ 0x5c5c5c5c, p6 ^ 0x5c5c5c5c, p7 ^ 0x5c5c5c5c, p8 ^ 0x5c5c5c5c, p9 ^ 0x5c5c5c5c, p10 ^ 0x5c5c5c5c, p11 ^ 0x5c5c5c5c, p12 ^ 0x5c5c5c5c, p13 ^ 0x5c5c5c5c, p14 ^ 0x5c5c5c5c, p15 ^ 0x5c5c5c5c); - O0 = H0; - O1 = H1; - O2 = H2; - O3 = H3; - O4 = H4; +/** + * Calculates a checksum over the given data and returns it base64 encoded + * @param {String | ReadableStream} data - Data to create a CRC-24 checksum for + * @returns {String | ReadableStream} Base64 encoded checksum. + * @private + */ +function getCheckSum(data) { + const crc = createcrc24(data); + return encode(crc); +} - // ipad - reset(); - _core(p0 ^ 0x36363636, p1 ^ 0x36363636, p2 ^ 0x36363636, p3 ^ 0x36363636, p4 ^ 0x36363636, p5 ^ 0x36363636, p6 ^ 0x36363636, p7 ^ 0x36363636, p8 ^ 0x36363636, p9 ^ 0x36363636, p10 ^ 0x36363636, p11 ^ 0x36363636, p12 ^ 0x36363636, p13 ^ 0x36363636, p14 ^ 0x36363636, p15 ^ 0x36363636); - I0 = H0; - I1 = H1; - I2 = H2; - I3 = H3; - I4 = H4; +// https://create.stephan-brumme.com/crc32/#slicing-by-8-overview - TOTAL0 = 64; - TOTAL1 = 0; - } +const crc_table = [ + new Array(0xFF), + new Array(0xFF), + new Array(0xFF), + new Array(0xFF) +]; - // offset — multiple of 64 - // output — multiple of 32 - function hmac_finish(offset, length, output) { - offset = offset | 0; - length = length | 0; - output = output | 0; - - var t0 = 0, - t1 = 0, - t2 = 0, - t3 = 0, - t4 = 0, - hashed = 0; +for (let i = 0; i <= 0xFF; i++) { + let crc = i << 16; + for (let j = 0; j < 8; j++) { + crc = (crc << 1) ^ ((crc & 0x800000) !== 0 ? 0x864CFB : 0); + } + crc_table[0][i] = + ((crc & 0xFF0000) >> 16) | + (crc & 0x00FF00) | + ((crc & 0x0000FF) << 16); +} +for (let i = 0; i <= 0xFF; i++) { + crc_table[1][i] = (crc_table[0][i] >> 8) ^ crc_table[0][crc_table[0][i] & 0xFF]; +} +for (let i = 0; i <= 0xFF; i++) { + crc_table[2][i] = (crc_table[1][i] >> 8) ^ crc_table[0][crc_table[1][i] & 0xFF]; +} +for (let i = 0; i <= 0xFF; i++) { + crc_table[3][i] = (crc_table[2][i] >> 8) ^ crc_table[0][crc_table[2][i] & 0xFF]; +} - if (offset & 63) return -1; +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView#Endianness +const isLittleEndian = (function() { + const buffer = new ArrayBuffer(2); + new DataView(buffer).setInt16(0, 0xFF, true /* littleEndian */); + // Int16Array uses the platform's endianness. + return new Int16Array(buffer)[0] === 0xFF; +}()); - if (~output) if (output & 31) return -1; +/** + * Internal function to calculate a CRC-24 checksum over a given string (data) + * @param {String | ReadableStream} input - Data to create a CRC-24 checksum for + * @returns {Uint8Array | ReadableStream} The CRC-24 checksum. + * @private + */ +function createcrc24(input) { + let crc = 0xCE04B7; + return transform(input, value => { + const len32 = isLittleEndian ? Math.floor(value.length / 4) : 0; + const arr32 = new Uint32Array(value.buffer, value.byteOffset, len32); + for (let i = 0; i < len32; i++) { + crc ^= arr32[i]; + crc = + crc_table[0][(crc >> 24) & 0xFF] ^ + crc_table[1][(crc >> 16) & 0xFF] ^ + crc_table[2][(crc >> 8) & 0xFF] ^ + crc_table[3][(crc >> 0) & 0xFF]; + } + for (let i = len32 * 4; i < value.length; i++) { + crc = (crc >> 8) ^ crc_table[0][(crc & 0xFF) ^ value[i]]; + } + }, () => new Uint8Array([crc, crc >> 8, crc >> 16])); +} - hashed = finish(offset, length, -1) | 0; - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; +/** + * Verify armored headers. RFC4880, section 6.3: "OpenPGP should consider improperly formatted + * Armor Headers to be corruption of the ASCII Armor." + * @private + * @param {Array} headers - Armor headers + */ +function verifyHeaders(headers) { + for (let i = 0; i < headers.length; i++) { + if (!/^([^\s:]|[^\s:][^:]*[^\s:]): .+$/.test(headers[i])) { + throw new Error('Improperly formatted armor header: ' + headers[i]); + } + if (!/^(Version|Comment|MessageID|Hash|Charset): .+$/.test(headers[i])) { + util.printDebugError(new Error('Unknown header: ' + headers[i])); + } + } +} - _hmac_opad(); - _core(t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672); +/** + * Splits a message into two parts, the body and the checksum. This is an internal function + * @param {String} text - OpenPGP armored message part + * @returns {Object} An object with attribute "body" containing the body. + * and an attribute "checksum" containing the checksum. + * @private + */ +function splitChecksum(text) { + let body = text; + let checksum = ''; - if (~output) _state_to_heap(output); + const lastEquals = text.lastIndexOf('='); - return hashed | 0; - } + if (lastEquals >= 0 && lastEquals !== text.length - 1) { // '=' as the last char means no checksum + body = text.slice(0, lastEquals); + checksum = text.slice(lastEquals + 1).substr(0, 4); + } - // salt is assumed to be already processed - // offset — multiple of 64 - // output — multiple of 32 - function pbkdf2_generate_block(offset, length, block, count, output) { - offset = offset | 0; - length = length | 0; - block = block | 0; - count = count | 0; - output = output | 0; - - var h0 = 0, - h1 = 0, - h2 = 0, - h3 = 0, - h4 = 0, - t0 = 0, - t1 = 0, - t2 = 0, - t3 = 0, - t4 = 0; - - if (offset & 63) return -1; - - if (~output) if (output & 31) return -1; + return { body: body, checksum: checksum }; +} - // pad block number into heap - // FIXME probable OOB write - HEAP[offset + length | 0] = block >>> 24; - HEAP[offset + length + 1 | 0] = block >>> 16 & 255; - HEAP[offset + length + 2 | 0] = block >>> 8 & 255; - HEAP[offset + length + 3 | 0] = block & 255; - - // finish first iteration - hmac_finish(offset, length + 4 | 0, -1) | 0; - h0 = t0 = H0, h1 = t1 = H1, h2 = t2 = H2, h3 = t3 = H3, h4 = t4 = H4; - count = count - 1 | 0; - - // perform the rest iterations - while ((count | 0) > 0) { - hmac_reset(); - _core(t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672); - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; - - _hmac_opad(); - _core(t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672); - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; - - h0 = h0 ^ H0; - h1 = h1 ^ H1; - h2 = h2 ^ H2; - h3 = h3 ^ H3; - h4 = h4 ^ H4; +/** + * Dearmor an OpenPGP armored message; verify the checksum and return + * the encoded bytes + * @param {String} input - OpenPGP armored message + * @returns {Promise} An object with attribute "text" containing the message text, + * an attribute "data" containing a stream of bytes and "type" for the ASCII armor type + * @async + * @static + */ +function unarmor(input, config = defaultConfig) { + return new Promise(async (resolve, reject) => { + try { + const reSplit = /^-----[^-]+-----$/m; + const reEmptyLine = /^[ \f\r\t\u00a0\u2000-\u200a\u202f\u205f\u3000]*$/; - count = count - 1 | 0; + let type; + const headers = []; + let lastHeaders = headers; + let headersDone; + let text = []; + let textDone; + let checksum; + let data = decode(transformPair(input, async (readable, writable) => { + const reader = getReader(readable); + try { + while (true) { + let line = await reader.readLine(); + if (line === undefined) { + throw new Error('Misformed armored text'); + } + // remove trailing whitespace at end of lines + line = util.removeTrailingSpaces(line.replace(/[\r\n]/g, '')); + if (!type) { + if (reSplit.test(line)) { + type = getType(line); + } + } else if (!headersDone) { + if (reSplit.test(line)) { + reject(new Error('Mandatory blank line missing between armor headers and armor data')); + } + if (!reEmptyLine.test(line)) { + lastHeaders.push(line); + } else { + verifyHeaders(lastHeaders); + headersDone = true; + if (textDone || type !== 2) { + resolve({ text, data, headers, type }); + break; + } + } + } else if (!textDone && type === 2) { + if (!reSplit.test(line)) { + // Reverse dash-escaping for msg + text.push(line.replace(/^- /, '')); + } else { + text = text.join('\r\n'); + textDone = true; + verifyHeaders(lastHeaders); + lastHeaders = []; + headersDone = false; + } + } + } + } catch (e) { + reject(e); + return; } - - H0 = h0; - H1 = h1; - H2 = h2; - H3 = h3; - H4 = h4; - - if (~output) _state_to_heap(output); - - return 0; + const writer = getWriter(writable); + try { + while (true) { + await writer.ready; + const { done, value } = await reader.read(); + if (done) { + throw new Error('Misformed armored text'); + } + const line = value + ''; + if (line.indexOf('=') === -1 && line.indexOf('-') === -1) { + await writer.write(line); + } else { + let remainder = await reader.readToEnd(); + if (!remainder.length) remainder = ''; + remainder = line + remainder; + remainder = util.removeTrailingSpaces(remainder.replace(/\r/g, '')); + const parts = remainder.split(reSplit); + if (parts.length === 1) { + throw new Error('Misformed armored text'); + } + const split = splitChecksum(parts[0].slice(0, -1)); + checksum = split.checksum; + await writer.write(split.body); + break; + } + } + await writer.ready; + await writer.close(); + } catch (e) { + await writer.abort(e); + } + })); + data = transformPair(data, async (readable, writable) => { + const checksumVerified = readToEnd(getCheckSum(passiveClone(readable))); + checksumVerified.catch(() => {}); + await pipe(readable, writable, { + preventClose: true + }); + const writer = getWriter(writable); + try { + const checksumVerifiedString = (await checksumVerified).replace('\n', ''); + if (checksum !== checksumVerifiedString && (checksum || config.checksumRequired)) { + throw new Error('Ascii armor integrity check failed'); + } + await writer.ready; + await writer.close(); + } catch (e) { + await writer.abort(e); + } + }); + } catch (e) { + reject(e); } - - return { - // SHA1 - reset: reset, - init: init, - process: process, - finish: finish, - - // HMAC-SHA1 - hmac_reset: hmac_reset, - hmac_init: hmac_init, - hmac_finish: hmac_finish, - - // PBKDF2-HMAC-SHA1 - pbkdf2_generate_block: pbkdf2_generate_block - }; + }).then(async result => { + if (isArrayStream(result.data)) { + result.data = await readToEnd(result.data); + } + return result; + }); } -},{}],11:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.Sha1 = exports._sha1_hash_size = exports._sha1_block_size = undefined; - -var _sha = require('./sha1.asm'); -var _hash = require('../hash'); +/** + * Armor an OpenPGP binary packet block + * @param {module:enums.armor} messageType - Type of the message + * @param {Uint8Array | ReadableStream} body - The message body to armor + * @param {Integer} [partIndex] + * @param {Integer} [partTotal] + * @param {String} [customComment] - Additional comment to add to the armored string + * @returns {String | ReadableStream} Armored text. + * @static + */ +function armor(messageType, body, partIndex, partTotal, customComment, config = defaultConfig) { + let text; + let hash; + if (messageType === enums.armor.signed) { + text = body.text; + hash = body.hash; + body = body.data; + } + const bodyClone = passiveClone(body); + const result = []; + switch (messageType) { + case enums.armor.multipartSection: + result.push('-----BEGIN PGP MESSAGE, PART ' + partIndex + '/' + partTotal + '-----\n'); + result.push(addheader(customComment, config)); + result.push(encode(body)); + result.push('=', getCheckSum(bodyClone)); + result.push('-----END PGP MESSAGE, PART ' + partIndex + '/' + partTotal + '-----\n'); + break; + case enums.armor.multipartLast: + result.push('-----BEGIN PGP MESSAGE, PART ' + partIndex + '-----\n'); + result.push(addheader(customComment, config)); + result.push(encode(body)); + result.push('=', getCheckSum(bodyClone)); + result.push('-----END PGP MESSAGE, PART ' + partIndex + '-----\n'); + break; + case enums.armor.signed: + result.push('\n-----BEGIN PGP SIGNED MESSAGE-----\n'); + result.push('Hash: ' + hash + '\n\n'); + result.push(text.replace(/^-/mg, '- -')); + result.push('\n-----BEGIN PGP SIGNATURE-----\n'); + result.push(addheader(customComment, config)); + result.push(encode(body)); + result.push('=', getCheckSum(bodyClone)); + result.push('-----END PGP SIGNATURE-----\n'); + break; + case enums.armor.message: + result.push('-----BEGIN PGP MESSAGE-----\n'); + result.push(addheader(customComment, config)); + result.push(encode(body)); + result.push('=', getCheckSum(bodyClone)); + result.push('-----END PGP MESSAGE-----\n'); + break; + case enums.armor.publicKey: + result.push('-----BEGIN PGP PUBLIC KEY BLOCK-----\n'); + result.push(addheader(customComment, config)); + result.push(encode(body)); + result.push('=', getCheckSum(bodyClone)); + result.push('-----END PGP PUBLIC KEY BLOCK-----\n'); + break; + case enums.armor.privateKey: + result.push('-----BEGIN PGP PRIVATE KEY BLOCK-----\n'); + result.push(addheader(customComment, config)); + result.push(encode(body)); + result.push('=', getCheckSum(bodyClone)); + result.push('-----END PGP PRIVATE KEY BLOCK-----\n'); + break; + case enums.armor.signature: + result.push('-----BEGIN PGP SIGNATURE-----\n'); + result.push(addheader(customComment, config)); + result.push(encode(body)); + result.push('=', getCheckSum(bodyClone)); + result.push('-----END PGP SIGNATURE-----\n'); + break; + } -var __extends = undefined && undefined.__extends || function () { - var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) { - d.__proto__ = b; - } || function (d, b) { - for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; - }; - return function (d, b) { - extendStatics(d, b); - function __() { - this.constructor = d; - } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -}(); -var _sha1_block_size = exports._sha1_block_size = 64; -var _sha1_hash_size = exports._sha1_hash_size = 20; -var Sha1 = /** @class */function (_super) { - __extends(Sha1, _super); - function Sha1() { - var _this = _super !== null && _super.apply(this, arguments) || this; - _this.NAME = 'sha1'; - _this.BLOCK_SIZE = _sha1_block_size; - _this.HASH_SIZE = _sha1_hash_size; - return _this; - } - Sha1.bytes = function (data) { - return new Sha1().process(data).finish().result; - }; - Sha1.NAME = 'sha1'; - Sha1.heap_pool = []; - Sha1.asm_pool = []; - Sha1.asm_function = _sha.sha1_asm; - return Sha1; -}(_hash.Hash); -exports.Sha1 = Sha1; - -},{"../hash":9,"./sha1.asm":10}],12:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.sha256_asm = sha256_asm; -function sha256_asm(stdlib, foreign, buffer) { - "use asm"; + return util.concat(result); +} - // SHA256 state +// GPG4Browsers - An OpenPGP implementation in javascript - var H0 = 0, - H1 = 0, - H2 = 0, - H3 = 0, - H4 = 0, - H5 = 0, - H6 = 0, - H7 = 0, - TOTAL0 = 0, - TOTAL1 = 0; +/** + * Implementation of type key id + * + * {@link https://tools.ietf.org/html/rfc4880#section-3.3|RFC4880 3.3}: + * A Key ID is an eight-octet scalar that identifies a key. + * Implementations SHOULD NOT assume that Key IDs are unique. The + * section "Enhanced Key Formats" below describes how Key IDs are + * formed. + */ +class KeyID { + constructor() { + this.bytes = ''; + } - // HMAC state - var I0 = 0, - I1 = 0, - I2 = 0, - I3 = 0, - I4 = 0, - I5 = 0, - I6 = 0, - I7 = 0, - O0 = 0, - O1 = 0, - O2 = 0, - O3 = 0, - O4 = 0, - O5 = 0, - O6 = 0, - O7 = 0; + /** + * Parsing method for a key id + * @param {Uint8Array} bytes - Input to read the key id from + */ + read(bytes) { + this.bytes = util.uint8ArrayToString(bytes.subarray(0, 8)); + } - // I/O buffer - var HEAP = new stdlib.Uint8Array(buffer); + /** + * Serializes the Key ID + * @returns {Uint8Array} Key ID as a Uint8Array. + */ + write() { + return util.stringToUint8Array(this.bytes); + } - function _core(w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15) { - w0 = w0 | 0; - w1 = w1 | 0; - w2 = w2 | 0; - w3 = w3 | 0; - w4 = w4 | 0; - w5 = w5 | 0; - w6 = w6 | 0; - w7 = w7 | 0; - w8 = w8 | 0; - w9 = w9 | 0; - w10 = w10 | 0; - w11 = w11 | 0; - w12 = w12 | 0; - w13 = w13 | 0; - w14 = w14 | 0; - w15 = w15 | 0; - - var a = 0, - b = 0, - c = 0, - d = 0, - e = 0, - f = 0, - g = 0, - h = 0; + /** + * Returns the Key ID represented as a hexadecimal string + * @returns {String} Key ID as a hexadecimal string. + */ + toHex() { + return util.uint8ArrayToHex(util.stringToUint8Array(this.bytes)); + } - a = H0; - b = H1; - c = H2; - d = H3; - e = H4; - f = H5; - g = H6; - h = H7; + /** + * Checks equality of Key ID's + * @param {KeyID} keyID + * @param {Boolean} matchWildcard - Indicates whether to check if either keyID is a wildcard + */ + equals(keyID, matchWildcard = false) { + return (matchWildcard && (keyID.isWildcard() || this.isWildcard())) || this.bytes === keyID.bytes; + } - // 0 - h = w0 + h + (e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7) + (g ^ e & (f ^ g)) + 0x428a2f98 | 0; - d = d + h | 0; - h = h + (a & b ^ c & (a ^ b)) + (a >>> 2 ^ a >>> 13 ^ a >>> 22 ^ a << 30 ^ a << 19 ^ a << 10) | 0; + /** + * Checks to see if the Key ID is unset + * @returns {Boolean} True if the Key ID is null. + */ + isNull() { + return this.bytes === ''; + } - // 1 - g = w1 + g + (d >>> 6 ^ d >>> 11 ^ d >>> 25 ^ d << 26 ^ d << 21 ^ d << 7) + (f ^ d & (e ^ f)) + 0x71374491 | 0; - c = c + g | 0; - g = g + (h & a ^ b & (h ^ a)) + (h >>> 2 ^ h >>> 13 ^ h >>> 22 ^ h << 30 ^ h << 19 ^ h << 10) | 0; + /** + * Checks to see if the Key ID is a "wildcard" Key ID (all zeros) + * @returns {Boolean} True if this is a wildcard Key ID. + */ + isWildcard() { + return /^0+$/.test(this.toHex()); + } - // 2 - f = w2 + f + (c >>> 6 ^ c >>> 11 ^ c >>> 25 ^ c << 26 ^ c << 21 ^ c << 7) + (e ^ c & (d ^ e)) + 0xb5c0fbcf | 0; - b = b + f | 0; - f = f + (g & h ^ a & (g ^ h)) + (g >>> 2 ^ g >>> 13 ^ g >>> 22 ^ g << 30 ^ g << 19 ^ g << 10) | 0; + static mapToHex(keyID) { + return keyID.toHex(); + } - // 3 - e = w3 + e + (b >>> 6 ^ b >>> 11 ^ b >>> 25 ^ b << 26 ^ b << 21 ^ b << 7) + (d ^ b & (c ^ d)) + 0xe9b5dba5 | 0; - a = a + e | 0; - e = e + (f & g ^ h & (f ^ g)) + (f >>> 2 ^ f >>> 13 ^ f >>> 22 ^ f << 30 ^ f << 19 ^ f << 10) | 0; + static fromID(hex) { + const keyID = new KeyID(); + keyID.read(util.hexToUint8Array(hex)); + return keyID; + } - // 4 - d = w4 + d + (a >>> 6 ^ a >>> 11 ^ a >>> 25 ^ a << 26 ^ a << 21 ^ a << 7) + (c ^ a & (b ^ c)) + 0x3956c25b | 0; - h = h + d | 0; - d = d + (e & f ^ g & (e ^ f)) + (e >>> 2 ^ e >>> 13 ^ e >>> 22 ^ e << 30 ^ e << 19 ^ e << 10) | 0; + static wildcard() { + const keyID = new KeyID(); + keyID.read(new Uint8Array(8)); + return keyID; + } +} - // 5 - c = w5 + c + (h >>> 6 ^ h >>> 11 ^ h >>> 25 ^ h << 26 ^ h << 21 ^ h << 7) + (b ^ h & (a ^ b)) + 0x59f111f1 | 0; - g = g + c | 0; - c = c + (d & e ^ f & (d ^ e)) + (d >>> 2 ^ d >>> 13 ^ d >>> 22 ^ d << 30 ^ d << 19 ^ d << 10) | 0; +/** + * @file {@link http://asmjs.org Asm.js} implementation of the {@link https://en.wikipedia.org/wiki/Advanced_Encryption_Standard Advanced Encryption Standard}. + * @author Artem S Vybornov + * @license MIT + */ +var AES_asm = function () { - // 6 - b = w6 + b + (g >>> 6 ^ g >>> 11 ^ g >>> 25 ^ g << 26 ^ g << 21 ^ g << 7) + (a ^ g & (h ^ a)) + 0x923f82a4 | 0; - f = f + b | 0; - b = b + (c & d ^ e & (c ^ d)) + (c >>> 2 ^ c >>> 13 ^ c >>> 22 ^ c << 30 ^ c << 19 ^ c << 10) | 0; + /** + * Galois Field stuff init flag + */ + var ginit_done = false; - // 7 - a = w7 + a + (f >>> 6 ^ f >>> 11 ^ f >>> 25 ^ f << 26 ^ f << 21 ^ f << 7) + (h ^ f & (g ^ h)) + 0xab1c5ed5 | 0; - e = e + a | 0; - a = a + (b & c ^ d & (b ^ c)) + (b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10) | 0; + /** + * Galois Field exponentiation and logarithm tables for 3 (the generator) + */ + var gexp3, glog3; - // 8 - h = w8 + h + (e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7) + (g ^ e & (f ^ g)) + 0xd807aa98 | 0; - d = d + h | 0; - h = h + (a & b ^ c & (a ^ b)) + (a >>> 2 ^ a >>> 13 ^ a >>> 22 ^ a << 30 ^ a << 19 ^ a << 10) | 0; + /** + * Init Galois Field tables + */ + function ginit() { + gexp3 = [], + glog3 = []; - // 9 - g = w9 + g + (d >>> 6 ^ d >>> 11 ^ d >>> 25 ^ d << 26 ^ d << 21 ^ d << 7) + (f ^ d & (e ^ f)) + 0x12835b01 | 0; - c = c + g | 0; - g = g + (h & a ^ b & (h ^ a)) + (h >>> 2 ^ h >>> 13 ^ h >>> 22 ^ h << 30 ^ h << 19 ^ h << 10) | 0; + var a = 1, c, d; + for (c = 0; c < 255; c++) { + gexp3[c] = a; - // 10 - f = w10 + f + (c >>> 6 ^ c >>> 11 ^ c >>> 25 ^ c << 26 ^ c << 21 ^ c << 7) + (e ^ c & (d ^ e)) + 0x243185be | 0; - b = b + f | 0; - f = f + (g & h ^ a & (g ^ h)) + (g >>> 2 ^ g >>> 13 ^ g >>> 22 ^ g << 30 ^ g << 19 ^ g << 10) | 0; + // Multiply by three + d = a & 0x80, a <<= 1, a &= 255; + if (d === 0x80) a ^= 0x1b; + a ^= gexp3[c]; - // 11 - e = w11 + e + (b >>> 6 ^ b >>> 11 ^ b >>> 25 ^ b << 26 ^ b << 21 ^ b << 7) + (d ^ b & (c ^ d)) + 0x550c7dc3 | 0; - a = a + e | 0; - e = e + (f & g ^ h & (f ^ g)) + (f >>> 2 ^ f >>> 13 ^ f >>> 22 ^ f << 30 ^ f << 19 ^ f << 10) | 0; + // Set the log table value + glog3[gexp3[c]] = c; + } + gexp3[255] = gexp3[0]; + glog3[0] = 0; - // 12 - d = w12 + d + (a >>> 6 ^ a >>> 11 ^ a >>> 25 ^ a << 26 ^ a << 21 ^ a << 7) + (c ^ a & (b ^ c)) + 0x72be5d74 | 0; - h = h + d | 0; - d = d + (e & f ^ g & (e ^ f)) + (e >>> 2 ^ e >>> 13 ^ e >>> 22 ^ e << 30 ^ e << 19 ^ e << 10) | 0; + ginit_done = true; + } - // 13 - c = w13 + c + (h >>> 6 ^ h >>> 11 ^ h >>> 25 ^ h << 26 ^ h << 21 ^ h << 7) + (b ^ h & (a ^ b)) + 0x80deb1fe | 0; - g = g + c | 0; - c = c + (d & e ^ f & (d ^ e)) + (d >>> 2 ^ d >>> 13 ^ d >>> 22 ^ d << 30 ^ d << 19 ^ d << 10) | 0; - - // 14 - b = w14 + b + (g >>> 6 ^ g >>> 11 ^ g >>> 25 ^ g << 26 ^ g << 21 ^ g << 7) + (a ^ g & (h ^ a)) + 0x9bdc06a7 | 0; - f = f + b | 0; - b = b + (c & d ^ e & (c ^ d)) + (c >>> 2 ^ c >>> 13 ^ c >>> 22 ^ c << 30 ^ c << 19 ^ c << 10) | 0; - - // 15 - a = w15 + a + (f >>> 6 ^ f >>> 11 ^ f >>> 25 ^ f << 26 ^ f << 21 ^ f << 7) + (h ^ f & (g ^ h)) + 0xc19bf174 | 0; - e = e + a | 0; - a = a + (b & c ^ d & (b ^ c)) + (b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10) | 0; + /** + * Galois Field multiplication + * @param {number} a + * @param {number} b + * @return {number} + */ + function gmul(a, b) { + var c = gexp3[(glog3[a] + glog3[b]) % 255]; + if (a === 0 || b === 0) c = 0; + return c; + } - // 16 - w0 = (w1 >>> 7 ^ w1 >>> 18 ^ w1 >>> 3 ^ w1 << 25 ^ w1 << 14) + (w14 >>> 17 ^ w14 >>> 19 ^ w14 >>> 10 ^ w14 << 15 ^ w14 << 13) + w0 + w9 | 0; - h = w0 + h + (e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7) + (g ^ e & (f ^ g)) + 0xe49b69c1 | 0; - d = d + h | 0; - h = h + (a & b ^ c & (a ^ b)) + (a >>> 2 ^ a >>> 13 ^ a >>> 22 ^ a << 30 ^ a << 19 ^ a << 10) | 0; + /** + * Galois Field reciprocal + * @param {number} a + * @return {number} + */ + function ginv(a) { + var i = gexp3[255 - glog3[a]]; + if (a === 0) i = 0; + return i; + } - // 17 - w1 = (w2 >>> 7 ^ w2 >>> 18 ^ w2 >>> 3 ^ w2 << 25 ^ w2 << 14) + (w15 >>> 17 ^ w15 >>> 19 ^ w15 >>> 10 ^ w15 << 15 ^ w15 << 13) + w1 + w10 | 0; - g = w1 + g + (d >>> 6 ^ d >>> 11 ^ d >>> 25 ^ d << 26 ^ d << 21 ^ d << 7) + (f ^ d & (e ^ f)) + 0xefbe4786 | 0; - c = c + g | 0; - g = g + (h & a ^ b & (h ^ a)) + (h >>> 2 ^ h >>> 13 ^ h >>> 22 ^ h << 30 ^ h << 19 ^ h << 10) | 0; + /** + * AES stuff init flag + */ + var aes_init_done = false; - // 18 - w2 = (w3 >>> 7 ^ w3 >>> 18 ^ w3 >>> 3 ^ w3 << 25 ^ w3 << 14) + (w0 >>> 17 ^ w0 >>> 19 ^ w0 >>> 10 ^ w0 << 15 ^ w0 << 13) + w2 + w11 | 0; - f = w2 + f + (c >>> 6 ^ c >>> 11 ^ c >>> 25 ^ c << 26 ^ c << 21 ^ c << 7) + (e ^ c & (d ^ e)) + 0x0fc19dc6 | 0; - b = b + f | 0; - f = f + (g & h ^ a & (g ^ h)) + (g >>> 2 ^ g >>> 13 ^ g >>> 22 ^ g << 30 ^ g << 19 ^ g << 10) | 0; + /** + * Encryption, Decryption, S-Box and KeyTransform tables + * + * @type {number[]} + */ + var aes_sbox; - // 19 - w3 = (w4 >>> 7 ^ w4 >>> 18 ^ w4 >>> 3 ^ w4 << 25 ^ w4 << 14) + (w1 >>> 17 ^ w1 >>> 19 ^ w1 >>> 10 ^ w1 << 15 ^ w1 << 13) + w3 + w12 | 0; - e = w3 + e + (b >>> 6 ^ b >>> 11 ^ b >>> 25 ^ b << 26 ^ b << 21 ^ b << 7) + (d ^ b & (c ^ d)) + 0x240ca1cc | 0; - a = a + e | 0; - e = e + (f & g ^ h & (f ^ g)) + (f >>> 2 ^ f >>> 13 ^ f >>> 22 ^ f << 30 ^ f << 19 ^ f << 10) | 0; + /** + * @type {number[]} + */ + var aes_sinv; - // 20 - w4 = (w5 >>> 7 ^ w5 >>> 18 ^ w5 >>> 3 ^ w5 << 25 ^ w5 << 14) + (w2 >>> 17 ^ w2 >>> 19 ^ w2 >>> 10 ^ w2 << 15 ^ w2 << 13) + w4 + w13 | 0; - d = w4 + d + (a >>> 6 ^ a >>> 11 ^ a >>> 25 ^ a << 26 ^ a << 21 ^ a << 7) + (c ^ a & (b ^ c)) + 0x2de92c6f | 0; - h = h + d | 0; - d = d + (e & f ^ g & (e ^ f)) + (e >>> 2 ^ e >>> 13 ^ e >>> 22 ^ e << 30 ^ e << 19 ^ e << 10) | 0; + /** + * @type {number[][]} + */ + var aes_enc; - // 21 - w5 = (w6 >>> 7 ^ w6 >>> 18 ^ w6 >>> 3 ^ w6 << 25 ^ w6 << 14) + (w3 >>> 17 ^ w3 >>> 19 ^ w3 >>> 10 ^ w3 << 15 ^ w3 << 13) + w5 + w14 | 0; - c = w5 + c + (h >>> 6 ^ h >>> 11 ^ h >>> 25 ^ h << 26 ^ h << 21 ^ h << 7) + (b ^ h & (a ^ b)) + 0x4a7484aa | 0; - g = g + c | 0; - c = c + (d & e ^ f & (d ^ e)) + (d >>> 2 ^ d >>> 13 ^ d >>> 22 ^ d << 30 ^ d << 19 ^ d << 10) | 0; + /** + * @type {number[][]} + */ + var aes_dec; - // 22 - w6 = (w7 >>> 7 ^ w7 >>> 18 ^ w7 >>> 3 ^ w7 << 25 ^ w7 << 14) + (w4 >>> 17 ^ w4 >>> 19 ^ w4 >>> 10 ^ w4 << 15 ^ w4 << 13) + w6 + w15 | 0; - b = w6 + b + (g >>> 6 ^ g >>> 11 ^ g >>> 25 ^ g << 26 ^ g << 21 ^ g << 7) + (a ^ g & (h ^ a)) + 0x5cb0a9dc | 0; - f = f + b | 0; - b = b + (c & d ^ e & (c ^ d)) + (c >>> 2 ^ c >>> 13 ^ c >>> 22 ^ c << 30 ^ c << 19 ^ c << 10) | 0; + /** + * Init AES tables + */ + function aes_init() { + if (!ginit_done) ginit(); - // 23 - w7 = (w8 >>> 7 ^ w8 >>> 18 ^ w8 >>> 3 ^ w8 << 25 ^ w8 << 14) + (w5 >>> 17 ^ w5 >>> 19 ^ w5 >>> 10 ^ w5 << 15 ^ w5 << 13) + w7 + w0 | 0; - a = w7 + a + (f >>> 6 ^ f >>> 11 ^ f >>> 25 ^ f << 26 ^ f << 21 ^ f << 7) + (h ^ f & (g ^ h)) + 0x76f988da | 0; - e = e + a | 0; - a = a + (b & c ^ d & (b ^ c)) + (b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10) | 0; + // Calculates AES S-Box value + function _s(a) { + var c, s, x; + s = x = ginv(a); + for (c = 0; c < 4; c++) { + s = ((s << 1) | (s >>> 7)) & 255; + x ^= s; + } + x ^= 99; + return x; + } - // 24 - w8 = (w9 >>> 7 ^ w9 >>> 18 ^ w9 >>> 3 ^ w9 << 25 ^ w9 << 14) + (w6 >>> 17 ^ w6 >>> 19 ^ w6 >>> 10 ^ w6 << 15 ^ w6 << 13) + w8 + w1 | 0; - h = w8 + h + (e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7) + (g ^ e & (f ^ g)) + 0x983e5152 | 0; - d = d + h | 0; - h = h + (a & b ^ c & (a ^ b)) + (a >>> 2 ^ a >>> 13 ^ a >>> 22 ^ a << 30 ^ a << 19 ^ a << 10) | 0; + // Tables + aes_sbox = [], + aes_sinv = [], + aes_enc = [[], [], [], []], + aes_dec = [[], [], [], []]; - // 25 - w9 = (w10 >>> 7 ^ w10 >>> 18 ^ w10 >>> 3 ^ w10 << 25 ^ w10 << 14) + (w7 >>> 17 ^ w7 >>> 19 ^ w7 >>> 10 ^ w7 << 15 ^ w7 << 13) + w9 + w2 | 0; - g = w9 + g + (d >>> 6 ^ d >>> 11 ^ d >>> 25 ^ d << 26 ^ d << 21 ^ d << 7) + (f ^ d & (e ^ f)) + 0xa831c66d | 0; - c = c + g | 0; - g = g + (h & a ^ b & (h ^ a)) + (h >>> 2 ^ h >>> 13 ^ h >>> 22 ^ h << 30 ^ h << 19 ^ h << 10) | 0; + for (var i = 0; i < 256; i++) { + var s = _s(i); - // 26 - w10 = (w11 >>> 7 ^ w11 >>> 18 ^ w11 >>> 3 ^ w11 << 25 ^ w11 << 14) + (w8 >>> 17 ^ w8 >>> 19 ^ w8 >>> 10 ^ w8 << 15 ^ w8 << 13) + w10 + w3 | 0; - f = w10 + f + (c >>> 6 ^ c >>> 11 ^ c >>> 25 ^ c << 26 ^ c << 21 ^ c << 7) + (e ^ c & (d ^ e)) + 0xb00327c8 | 0; - b = b + f | 0; - f = f + (g & h ^ a & (g ^ h)) + (g >>> 2 ^ g >>> 13 ^ g >>> 22 ^ g << 30 ^ g << 19 ^ g << 10) | 0; + // S-Box and its inverse + aes_sbox[i] = s; + aes_sinv[s] = i; - // 27 - w11 = (w12 >>> 7 ^ w12 >>> 18 ^ w12 >>> 3 ^ w12 << 25 ^ w12 << 14) + (w9 >>> 17 ^ w9 >>> 19 ^ w9 >>> 10 ^ w9 << 15 ^ w9 << 13) + w11 + w4 | 0; - e = w11 + e + (b >>> 6 ^ b >>> 11 ^ b >>> 25 ^ b << 26 ^ b << 21 ^ b << 7) + (d ^ b & (c ^ d)) + 0xbf597fc7 | 0; - a = a + e | 0; - e = e + (f & g ^ h & (f ^ g)) + (f >>> 2 ^ f >>> 13 ^ f >>> 22 ^ f << 30 ^ f << 19 ^ f << 10) | 0; + // Ecryption and Decryption tables + aes_enc[0][i] = (gmul(2, s) << 24) | (s << 16) | (s << 8) | gmul(3, s); + aes_dec[0][s] = (gmul(14, i) << 24) | (gmul(9, i) << 16) | (gmul(13, i) << 8) | gmul(11, i); + // Rotate tables + for (var t = 1; t < 4; t++) { + aes_enc[t][i] = (aes_enc[t - 1][i] >>> 8) | (aes_enc[t - 1][i] << 24); + aes_dec[t][s] = (aes_dec[t - 1][s] >>> 8) | (aes_dec[t - 1][s] << 24); + } + } - // 28 - w12 = (w13 >>> 7 ^ w13 >>> 18 ^ w13 >>> 3 ^ w13 << 25 ^ w13 << 14) + (w10 >>> 17 ^ w10 >>> 19 ^ w10 >>> 10 ^ w10 << 15 ^ w10 << 13) + w12 + w5 | 0; - d = w12 + d + (a >>> 6 ^ a >>> 11 ^ a >>> 25 ^ a << 26 ^ a << 21 ^ a << 7) + (c ^ a & (b ^ c)) + 0xc6e00bf3 | 0; - h = h + d | 0; - d = d + (e & f ^ g & (e ^ f)) + (e >>> 2 ^ e >>> 13 ^ e >>> 22 ^ e << 30 ^ e << 19 ^ e << 10) | 0; + aes_init_done = true; + } - // 29 - w13 = (w14 >>> 7 ^ w14 >>> 18 ^ w14 >>> 3 ^ w14 << 25 ^ w14 << 14) + (w11 >>> 17 ^ w11 >>> 19 ^ w11 >>> 10 ^ w11 << 15 ^ w11 << 13) + w13 + w6 | 0; - c = w13 + c + (h >>> 6 ^ h >>> 11 ^ h >>> 25 ^ h << 26 ^ h << 21 ^ h << 7) + (b ^ h & (a ^ b)) + 0xd5a79147 | 0; - g = g + c | 0; - c = c + (d & e ^ f & (d ^ e)) + (d >>> 2 ^ d >>> 13 ^ d >>> 22 ^ d << 30 ^ d << 19 ^ d << 10) | 0; + /** + * Asm.js module constructor. + * + *

+ * Heap buffer layout by offset: + *

+   * 0x0000   encryption key schedule
+   * 0x0400   decryption key schedule
+   * 0x0800   sbox
+   * 0x0c00   inv sbox
+   * 0x1000   encryption tables
+   * 0x2000   decryption tables
+   * 0x3000   reserved (future GCM multiplication lookup table)
+   * 0x4000   data
+   * 
+ * Don't touch anything before 0x400. + *

+ * + * @alias AES_asm + * @class + * @param foreign - ignored + * @param buffer - heap buffer to link with + */ + var wrapper = function (foreign, buffer) { + // Init AES stuff for the first time + if (!aes_init_done) aes_init(); - // 30 - w14 = (w15 >>> 7 ^ w15 >>> 18 ^ w15 >>> 3 ^ w15 << 25 ^ w15 << 14) + (w12 >>> 17 ^ w12 >>> 19 ^ w12 >>> 10 ^ w12 << 15 ^ w12 << 13) + w14 + w7 | 0; - b = w14 + b + (g >>> 6 ^ g >>> 11 ^ g >>> 25 ^ g << 26 ^ g << 21 ^ g << 7) + (a ^ g & (h ^ a)) + 0x06ca6351 | 0; - f = f + b | 0; - b = b + (c & d ^ e & (c ^ d)) + (c >>> 2 ^ c >>> 13 ^ c >>> 22 ^ c << 30 ^ c << 19 ^ c << 10) | 0; + // Fill up AES tables + var heap = new Uint32Array(buffer); + heap.set(aes_sbox, 0x0800 >> 2); + heap.set(aes_sinv, 0x0c00 >> 2); + for (var i = 0; i < 4; i++) { + heap.set(aes_enc[i], (0x1000 + 0x400 * i) >> 2); + heap.set(aes_dec[i], (0x2000 + 0x400 * i) >> 2); + } - // 31 - w15 = (w0 >>> 7 ^ w0 >>> 18 ^ w0 >>> 3 ^ w0 << 25 ^ w0 << 14) + (w13 >>> 17 ^ w13 >>> 19 ^ w13 >>> 10 ^ w13 << 15 ^ w13 << 13) + w15 + w8 | 0; - a = w15 + a + (f >>> 6 ^ f >>> 11 ^ f >>> 25 ^ f << 26 ^ f << 21 ^ f << 7) + (h ^ f & (g ^ h)) + 0x14292967 | 0; - e = e + a | 0; - a = a + (b & c ^ d & (b ^ c)) + (b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10) | 0; + /** + * Calculate AES key schedules. + * @instance + * @memberof AES_asm + * @param {number} ks - key size, 4/6/8 (for 128/192/256-bit key correspondingly) + * @param {number} k0 - key vector components + * @param {number} k1 - key vector components + * @param {number} k2 - key vector components + * @param {number} k3 - key vector components + * @param {number} k4 - key vector components + * @param {number} k5 - key vector components + * @param {number} k6 - key vector components + * @param {number} k7 - key vector components + */ + function set_key(ks, k0, k1, k2, k3, k4, k5, k6, k7) { + var ekeys = heap.subarray(0x000, 60), + dkeys = heap.subarray(0x100, 0x100 + 60); - // 32 - w0 = (w1 >>> 7 ^ w1 >>> 18 ^ w1 >>> 3 ^ w1 << 25 ^ w1 << 14) + (w14 >>> 17 ^ w14 >>> 19 ^ w14 >>> 10 ^ w14 << 15 ^ w14 << 13) + w0 + w9 | 0; - h = w0 + h + (e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7) + (g ^ e & (f ^ g)) + 0x27b70a85 | 0; - d = d + h | 0; - h = h + (a & b ^ c & (a ^ b)) + (a >>> 2 ^ a >>> 13 ^ a >>> 22 ^ a << 30 ^ a << 19 ^ a << 10) | 0; + // Encryption key schedule + ekeys.set([k0, k1, k2, k3, k4, k5, k6, k7]); + for (var i = ks, rcon = 1; i < 4 * ks + 28; i++) { + var k = ekeys[i - 1]; + if ((i % ks === 0) || (ks === 8 && i % ks === 4)) { + k = aes_sbox[k >>> 24] << 24 ^ aes_sbox[k >>> 16 & 255] << 16 ^ aes_sbox[k >>> 8 & 255] << 8 ^ aes_sbox[k & 255]; + } + if (i % ks === 0) { + k = (k << 8) ^ (k >>> 24) ^ (rcon << 24); + rcon = (rcon << 1) ^ ((rcon & 0x80) ? 0x1b : 0); + } + ekeys[i] = ekeys[i - ks] ^ k; + } - // 33 - w1 = (w2 >>> 7 ^ w2 >>> 18 ^ w2 >>> 3 ^ w2 << 25 ^ w2 << 14) + (w15 >>> 17 ^ w15 >>> 19 ^ w15 >>> 10 ^ w15 << 15 ^ w15 << 13) + w1 + w10 | 0; - g = w1 + g + (d >>> 6 ^ d >>> 11 ^ d >>> 25 ^ d << 26 ^ d << 21 ^ d << 7) + (f ^ d & (e ^ f)) + 0x2e1b2138 | 0; - c = c + g | 0; - g = g + (h & a ^ b & (h ^ a)) + (h >>> 2 ^ h >>> 13 ^ h >>> 22 ^ h << 30 ^ h << 19 ^ h << 10) | 0; + // Decryption key schedule + for (var j = 0; j < i; j += 4) { + for (var jj = 0; jj < 4; jj++) { + var k = ekeys[i - (4 + j) + (4 - jj) % 4]; + if (j < 4 || j >= i - 4) { + dkeys[j + jj] = k; + } else { + dkeys[j + jj] = aes_dec[0][aes_sbox[k >>> 24]] + ^ aes_dec[1][aes_sbox[k >>> 16 & 255]] + ^ aes_dec[2][aes_sbox[k >>> 8 & 255]] + ^ aes_dec[3][aes_sbox[k & 255]]; + } + } + } - // 34 - w2 = (w3 >>> 7 ^ w3 >>> 18 ^ w3 >>> 3 ^ w3 << 25 ^ w3 << 14) + (w0 >>> 17 ^ w0 >>> 19 ^ w0 >>> 10 ^ w0 << 15 ^ w0 << 13) + w2 + w11 | 0; - f = w2 + f + (c >>> 6 ^ c >>> 11 ^ c >>> 25 ^ c << 26 ^ c << 21 ^ c << 7) + (e ^ c & (d ^ e)) + 0x4d2c6dfc | 0; - b = b + f | 0; - f = f + (g & h ^ a & (g ^ h)) + (g >>> 2 ^ g >>> 13 ^ g >>> 22 ^ g << 30 ^ g << 19 ^ g << 10) | 0; + // Set rounds number + asm.set_rounds(ks + 5); + } - // 35 - w3 = (w4 >>> 7 ^ w4 >>> 18 ^ w4 >>> 3 ^ w4 << 25 ^ w4 << 14) + (w1 >>> 17 ^ w1 >>> 19 ^ w1 >>> 10 ^ w1 << 15 ^ w1 << 13) + w3 + w12 | 0; - e = w3 + e + (b >>> 6 ^ b >>> 11 ^ b >>> 25 ^ b << 26 ^ b << 21 ^ b << 7) + (d ^ b & (c ^ d)) + 0x53380d13 | 0; - a = a + e | 0; - e = e + (f & g ^ h & (f ^ g)) + (f >>> 2 ^ f >>> 13 ^ f >>> 22 ^ f << 30 ^ f << 19 ^ f << 10) | 0; + // create library object with necessary properties + var stdlib = {Uint8Array: Uint8Array, Uint32Array: Uint32Array}; - // 36 - w4 = (w5 >>> 7 ^ w5 >>> 18 ^ w5 >>> 3 ^ w5 << 25 ^ w5 << 14) + (w2 >>> 17 ^ w2 >>> 19 ^ w2 >>> 10 ^ w2 << 15 ^ w2 << 13) + w4 + w13 | 0; - d = w4 + d + (a >>> 6 ^ a >>> 11 ^ a >>> 25 ^ a << 26 ^ a << 21 ^ a << 7) + (c ^ a & (b ^ c)) + 0x650a7354 | 0; - h = h + d | 0; - d = d + (e & f ^ g & (e ^ f)) + (e >>> 2 ^ e >>> 13 ^ e >>> 22 ^ e << 30 ^ e << 19 ^ e << 10) | 0; + var asm = function (stdlib, foreign, buffer) { + "use asm"; - // 37 - w5 = (w6 >>> 7 ^ w6 >>> 18 ^ w6 >>> 3 ^ w6 << 25 ^ w6 << 14) + (w3 >>> 17 ^ w3 >>> 19 ^ w3 >>> 10 ^ w3 << 15 ^ w3 << 13) + w5 + w14 | 0; - c = w5 + c + (h >>> 6 ^ h >>> 11 ^ h >>> 25 ^ h << 26 ^ h << 21 ^ h << 7) + (b ^ h & (a ^ b)) + 0x766a0abb | 0; - g = g + c | 0; - c = c + (d & e ^ f & (d ^ e)) + (d >>> 2 ^ d >>> 13 ^ d >>> 22 ^ d << 30 ^ d << 19 ^ d << 10) | 0; + var S0 = 0, S1 = 0, S2 = 0, S3 = 0, + I0 = 0, I1 = 0, I2 = 0, I3 = 0, + N0 = 0, N1 = 0, N2 = 0, N3 = 0, + M0 = 0, M1 = 0, M2 = 0, M3 = 0, + H0 = 0, H1 = 0, H2 = 0, H3 = 0, + R = 0; - // 38 - w6 = (w7 >>> 7 ^ w7 >>> 18 ^ w7 >>> 3 ^ w7 << 25 ^ w7 << 14) + (w4 >>> 17 ^ w4 >>> 19 ^ w4 >>> 10 ^ w4 << 15 ^ w4 << 13) + w6 + w15 | 0; - b = w6 + b + (g >>> 6 ^ g >>> 11 ^ g >>> 25 ^ g << 26 ^ g << 21 ^ g << 7) + (a ^ g & (h ^ a)) + 0x81c2c92e | 0; - f = f + b | 0; - b = b + (c & d ^ e & (c ^ d)) + (c >>> 2 ^ c >>> 13 ^ c >>> 22 ^ c << 30 ^ c << 19 ^ c << 10) | 0; + var HEAP = new stdlib.Uint32Array(buffer), + DATA = new stdlib.Uint8Array(buffer); - // 39 - w7 = (w8 >>> 7 ^ w8 >>> 18 ^ w8 >>> 3 ^ w8 << 25 ^ w8 << 14) + (w5 >>> 17 ^ w5 >>> 19 ^ w5 >>> 10 ^ w5 << 15 ^ w5 << 13) + w7 + w0 | 0; - a = w7 + a + (f >>> 6 ^ f >>> 11 ^ f >>> 25 ^ f << 26 ^ f << 21 ^ f << 7) + (h ^ f & (g ^ h)) + 0x92722c85 | 0; - e = e + a | 0; - a = a + (b & c ^ d & (b ^ c)) + (b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10) | 0; + /** + * AES core + * @param {number} k - precomputed key schedule offset + * @param {number} s - precomputed sbox table offset + * @param {number} t - precomputed round table offset + * @param {number} r - number of inner rounds to perform + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _core(k, s, t, r, x0, x1, x2, x3) { + k = k | 0; + s = s | 0; + t = t | 0; + r = r | 0; + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; - // 40 - w8 = (w9 >>> 7 ^ w9 >>> 18 ^ w9 >>> 3 ^ w9 << 25 ^ w9 << 14) + (w6 >>> 17 ^ w6 >>> 19 ^ w6 >>> 10 ^ w6 << 15 ^ w6 << 13) + w8 + w1 | 0; - h = w8 + h + (e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7) + (g ^ e & (f ^ g)) + 0xa2bfe8a1 | 0; - d = d + h | 0; - h = h + (a & b ^ c & (a ^ b)) + (a >>> 2 ^ a >>> 13 ^ a >>> 22 ^ a << 30 ^ a << 19 ^ a << 10) | 0; + var t1 = 0, t2 = 0, t3 = 0, + y0 = 0, y1 = 0, y2 = 0, y3 = 0, + i = 0; - // 41 - w9 = (w10 >>> 7 ^ w10 >>> 18 ^ w10 >>> 3 ^ w10 << 25 ^ w10 << 14) + (w7 >>> 17 ^ w7 >>> 19 ^ w7 >>> 10 ^ w7 << 15 ^ w7 << 13) + w9 + w2 | 0; - g = w9 + g + (d >>> 6 ^ d >>> 11 ^ d >>> 25 ^ d << 26 ^ d << 21 ^ d << 7) + (f ^ d & (e ^ f)) + 0xa81a664b | 0; - c = c + g | 0; - g = g + (h & a ^ b & (h ^ a)) + (h >>> 2 ^ h >>> 13 ^ h >>> 22 ^ h << 30 ^ h << 19 ^ h << 10) | 0; + t1 = t | 0x400, t2 = t | 0x800, t3 = t | 0xc00; - // 42 - w10 = (w11 >>> 7 ^ w11 >>> 18 ^ w11 >>> 3 ^ w11 << 25 ^ w11 << 14) + (w8 >>> 17 ^ w8 >>> 19 ^ w8 >>> 10 ^ w8 << 15 ^ w8 << 13) + w10 + w3 | 0; - f = w10 + f + (c >>> 6 ^ c >>> 11 ^ c >>> 25 ^ c << 26 ^ c << 21 ^ c << 7) + (e ^ c & (d ^ e)) + 0xc24b8b70 | 0; - b = b + f | 0; - f = f + (g & h ^ a & (g ^ h)) + (g >>> 2 ^ g >>> 13 ^ g >>> 22 ^ g << 30 ^ g << 19 ^ g << 10) | 0; + // round 0 + x0 = x0 ^ HEAP[(k | 0) >> 2], + x1 = x1 ^ HEAP[(k | 4) >> 2], + x2 = x2 ^ HEAP[(k | 8) >> 2], + x3 = x3 ^ HEAP[(k | 12) >> 2]; - // 43 - w11 = (w12 >>> 7 ^ w12 >>> 18 ^ w12 >>> 3 ^ w12 << 25 ^ w12 << 14) + (w9 >>> 17 ^ w9 >>> 19 ^ w9 >>> 10 ^ w9 << 15 ^ w9 << 13) + w11 + w4 | 0; - e = w11 + e + (b >>> 6 ^ b >>> 11 ^ b >>> 25 ^ b << 26 ^ b << 21 ^ b << 7) + (d ^ b & (c ^ d)) + 0xc76c51a3 | 0; - a = a + e | 0; - e = e + (f & g ^ h & (f ^ g)) + (f >>> 2 ^ f >>> 13 ^ f >>> 22 ^ f << 30 ^ f << 19 ^ f << 10) | 0; + // round 1..r + for (i = 16; (i | 0) <= (r << 4); i = (i + 16) | 0) { + y0 = HEAP[(t | x0 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x1 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x2 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x3 << 2 & 1020) >> 2] ^ HEAP[(k | i | 0) >> 2], + y1 = HEAP[(t | x1 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x2 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x3 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x0 << 2 & 1020) >> 2] ^ HEAP[(k | i | 4) >> 2], + y2 = HEAP[(t | x2 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x3 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x0 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x1 << 2 & 1020) >> 2] ^ HEAP[(k | i | 8) >> 2], + y3 = HEAP[(t | x3 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x0 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x1 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x2 << 2 & 1020) >> 2] ^ HEAP[(k | i | 12) >> 2]; + x0 = y0, x1 = y1, x2 = y2, x3 = y3; + } - // 44 - w12 = (w13 >>> 7 ^ w13 >>> 18 ^ w13 >>> 3 ^ w13 << 25 ^ w13 << 14) + (w10 >>> 17 ^ w10 >>> 19 ^ w10 >>> 10 ^ w10 << 15 ^ w10 << 13) + w12 + w5 | 0; - d = w12 + d + (a >>> 6 ^ a >>> 11 ^ a >>> 25 ^ a << 26 ^ a << 21 ^ a << 7) + (c ^ a & (b ^ c)) + 0xd192e819 | 0; - h = h + d | 0; - d = d + (e & f ^ g & (e ^ f)) + (e >>> 2 ^ e >>> 13 ^ e >>> 22 ^ e << 30 ^ e << 19 ^ e << 10) | 0; + // final round + S0 = HEAP[(s | x0 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x1 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x2 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x3 << 2 & 1020) >> 2] ^ HEAP[(k | i | 0) >> 2], + S1 = HEAP[(s | x1 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x2 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x3 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x0 << 2 & 1020) >> 2] ^ HEAP[(k | i | 4) >> 2], + S2 = HEAP[(s | x2 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x3 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x0 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x1 << 2 & 1020) >> 2] ^ HEAP[(k | i | 8) >> 2], + S3 = HEAP[(s | x3 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x0 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x1 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x2 << 2 & 1020) >> 2] ^ HEAP[(k | i | 12) >> 2]; + } - // 45 - w13 = (w14 >>> 7 ^ w14 >>> 18 ^ w14 >>> 3 ^ w14 << 25 ^ w14 << 14) + (w11 >>> 17 ^ w11 >>> 19 ^ w11 >>> 10 ^ w11 << 15 ^ w11 << 13) + w13 + w6 | 0; - c = w13 + c + (h >>> 6 ^ h >>> 11 ^ h >>> 25 ^ h << 26 ^ h << 21 ^ h << 7) + (b ^ h & (a ^ b)) + 0xd6990624 | 0; - g = g + c | 0; - c = c + (d & e ^ f & (d ^ e)) + (d >>> 2 ^ d >>> 13 ^ d >>> 22 ^ d << 30 ^ d << 19 ^ d << 10) | 0; + /** + * ECB mode encryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _ecb_enc(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; - // 46 - w14 = (w15 >>> 7 ^ w15 >>> 18 ^ w15 >>> 3 ^ w15 << 25 ^ w15 << 14) + (w12 >>> 17 ^ w12 >>> 19 ^ w12 >>> 10 ^ w12 << 15 ^ w12 << 13) + w14 + w7 | 0; - b = w14 + b + (g >>> 6 ^ g >>> 11 ^ g >>> 25 ^ g << 26 ^ g << 21 ^ g << 7) + (a ^ g & (h ^ a)) + 0xf40e3585 | 0; - f = f + b | 0; - b = b + (c & d ^ e & (c ^ d)) + (c >>> 2 ^ c >>> 13 ^ c >>> 22 ^ c << 30 ^ c << 19 ^ c << 10) | 0; + _core( + 0x0000, 0x0800, 0x1000, + R, + x0, + x1, + x2, + x3 + ); + } - // 47 - w15 = (w0 >>> 7 ^ w0 >>> 18 ^ w0 >>> 3 ^ w0 << 25 ^ w0 << 14) + (w13 >>> 17 ^ w13 >>> 19 ^ w13 >>> 10 ^ w13 << 15 ^ w13 << 13) + w15 + w8 | 0; - a = w15 + a + (f >>> 6 ^ f >>> 11 ^ f >>> 25 ^ f << 26 ^ f << 21 ^ f << 7) + (h ^ f & (g ^ h)) + 0x106aa070 | 0; - e = e + a | 0; - a = a + (b & c ^ d & (b ^ c)) + (b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10) | 0; + /** + * ECB mode decryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _ecb_dec(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; - // 48 - w0 = (w1 >>> 7 ^ w1 >>> 18 ^ w1 >>> 3 ^ w1 << 25 ^ w1 << 14) + (w14 >>> 17 ^ w14 >>> 19 ^ w14 >>> 10 ^ w14 << 15 ^ w14 << 13) + w0 + w9 | 0; - h = w0 + h + (e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7) + (g ^ e & (f ^ g)) + 0x19a4c116 | 0; - d = d + h | 0; - h = h + (a & b ^ c & (a ^ b)) + (a >>> 2 ^ a >>> 13 ^ a >>> 22 ^ a << 30 ^ a << 19 ^ a << 10) | 0; + var t = 0; - // 49 - w1 = (w2 >>> 7 ^ w2 >>> 18 ^ w2 >>> 3 ^ w2 << 25 ^ w2 << 14) + (w15 >>> 17 ^ w15 >>> 19 ^ w15 >>> 10 ^ w15 << 15 ^ w15 << 13) + w1 + w10 | 0; - g = w1 + g + (d >>> 6 ^ d >>> 11 ^ d >>> 25 ^ d << 26 ^ d << 21 ^ d << 7) + (f ^ d & (e ^ f)) + 0x1e376c08 | 0; - c = c + g | 0; - g = g + (h & a ^ b & (h ^ a)) + (h >>> 2 ^ h >>> 13 ^ h >>> 22 ^ h << 30 ^ h << 19 ^ h << 10) | 0; + _core( + 0x0400, 0x0c00, 0x2000, + R, + x0, + x3, + x2, + x1 + ); - // 50 - w2 = (w3 >>> 7 ^ w3 >>> 18 ^ w3 >>> 3 ^ w3 << 25 ^ w3 << 14) + (w0 >>> 17 ^ w0 >>> 19 ^ w0 >>> 10 ^ w0 << 15 ^ w0 << 13) + w2 + w11 | 0; - f = w2 + f + (c >>> 6 ^ c >>> 11 ^ c >>> 25 ^ c << 26 ^ c << 21 ^ c << 7) + (e ^ c & (d ^ e)) + 0x2748774c | 0; - b = b + f | 0; - f = f + (g & h ^ a & (g ^ h)) + (g >>> 2 ^ g >>> 13 ^ g >>> 22 ^ g << 30 ^ g << 19 ^ g << 10) | 0; + t = S1, S1 = S3, S3 = t; + } - // 51 - w3 = (w4 >>> 7 ^ w4 >>> 18 ^ w4 >>> 3 ^ w4 << 25 ^ w4 << 14) + (w1 >>> 17 ^ w1 >>> 19 ^ w1 >>> 10 ^ w1 << 15 ^ w1 << 13) + w3 + w12 | 0; - e = w3 + e + (b >>> 6 ^ b >>> 11 ^ b >>> 25 ^ b << 26 ^ b << 21 ^ b << 7) + (d ^ b & (c ^ d)) + 0x34b0bcb5 | 0; - a = a + e | 0; - e = e + (f & g ^ h & (f ^ g)) + (f >>> 2 ^ f >>> 13 ^ f >>> 22 ^ f << 30 ^ f << 19 ^ f << 10) | 0; - // 52 - w4 = (w5 >>> 7 ^ w5 >>> 18 ^ w5 >>> 3 ^ w5 << 25 ^ w5 << 14) + (w2 >>> 17 ^ w2 >>> 19 ^ w2 >>> 10 ^ w2 << 15 ^ w2 << 13) + w4 + w13 | 0; - d = w4 + d + (a >>> 6 ^ a >>> 11 ^ a >>> 25 ^ a << 26 ^ a << 21 ^ a << 7) + (c ^ a & (b ^ c)) + 0x391c0cb3 | 0; - h = h + d | 0; - d = d + (e & f ^ g & (e ^ f)) + (e >>> 2 ^ e >>> 13 ^ e >>> 22 ^ e << 30 ^ e << 19 ^ e << 10) | 0; + /** + * CBC mode encryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _cbc_enc(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; - // 53 - w5 = (w6 >>> 7 ^ w6 >>> 18 ^ w6 >>> 3 ^ w6 << 25 ^ w6 << 14) + (w3 >>> 17 ^ w3 >>> 19 ^ w3 >>> 10 ^ w3 << 15 ^ w3 << 13) + w5 + w14 | 0; - c = w5 + c + (h >>> 6 ^ h >>> 11 ^ h >>> 25 ^ h << 26 ^ h << 21 ^ h << 7) + (b ^ h & (a ^ b)) + 0x4ed8aa4a | 0; - g = g + c | 0; - c = c + (d & e ^ f & (d ^ e)) + (d >>> 2 ^ d >>> 13 ^ d >>> 22 ^ d << 30 ^ d << 19 ^ d << 10) | 0; + _core( + 0x0000, 0x0800, 0x1000, + R, + I0 ^ x0, + I1 ^ x1, + I2 ^ x2, + I3 ^ x3 + ); - // 54 - w6 = (w7 >>> 7 ^ w7 >>> 18 ^ w7 >>> 3 ^ w7 << 25 ^ w7 << 14) + (w4 >>> 17 ^ w4 >>> 19 ^ w4 >>> 10 ^ w4 << 15 ^ w4 << 13) + w6 + w15 | 0; - b = w6 + b + (g >>> 6 ^ g >>> 11 ^ g >>> 25 ^ g << 26 ^ g << 21 ^ g << 7) + (a ^ g & (h ^ a)) + 0x5b9cca4f | 0; - f = f + b | 0; - b = b + (c & d ^ e & (c ^ d)) + (c >>> 2 ^ c >>> 13 ^ c >>> 22 ^ c << 30 ^ c << 19 ^ c << 10) | 0; + I0 = S0, + I1 = S1, + I2 = S2, + I3 = S3; + } - // 55 - w7 = (w8 >>> 7 ^ w8 >>> 18 ^ w8 >>> 3 ^ w8 << 25 ^ w8 << 14) + (w5 >>> 17 ^ w5 >>> 19 ^ w5 >>> 10 ^ w5 << 15 ^ w5 << 13) + w7 + w0 | 0; - a = w7 + a + (f >>> 6 ^ f >>> 11 ^ f >>> 25 ^ f << 26 ^ f << 21 ^ f << 7) + (h ^ f & (g ^ h)) + 0x682e6ff3 | 0; - e = e + a | 0; - a = a + (b & c ^ d & (b ^ c)) + (b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10) | 0; + /** + * CBC mode decryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _cbc_dec(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; - // 56 - w8 = (w9 >>> 7 ^ w9 >>> 18 ^ w9 >>> 3 ^ w9 << 25 ^ w9 << 14) + (w6 >>> 17 ^ w6 >>> 19 ^ w6 >>> 10 ^ w6 << 15 ^ w6 << 13) + w8 + w1 | 0; - h = w8 + h + (e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7) + (g ^ e & (f ^ g)) + 0x748f82ee | 0; - d = d + h | 0; - h = h + (a & b ^ c & (a ^ b)) + (a >>> 2 ^ a >>> 13 ^ a >>> 22 ^ a << 30 ^ a << 19 ^ a << 10) | 0; + var t = 0; - // 57 - w9 = (w10 >>> 7 ^ w10 >>> 18 ^ w10 >>> 3 ^ w10 << 25 ^ w10 << 14) + (w7 >>> 17 ^ w7 >>> 19 ^ w7 >>> 10 ^ w7 << 15 ^ w7 << 13) + w9 + w2 | 0; - g = w9 + g + (d >>> 6 ^ d >>> 11 ^ d >>> 25 ^ d << 26 ^ d << 21 ^ d << 7) + (f ^ d & (e ^ f)) + 0x78a5636f | 0; - c = c + g | 0; - g = g + (h & a ^ b & (h ^ a)) + (h >>> 2 ^ h >>> 13 ^ h >>> 22 ^ h << 30 ^ h << 19 ^ h << 10) | 0; + _core( + 0x0400, 0x0c00, 0x2000, + R, + x0, + x3, + x2, + x1 + ); - // 58 - w10 = (w11 >>> 7 ^ w11 >>> 18 ^ w11 >>> 3 ^ w11 << 25 ^ w11 << 14) + (w8 >>> 17 ^ w8 >>> 19 ^ w8 >>> 10 ^ w8 << 15 ^ w8 << 13) + w10 + w3 | 0; - f = w10 + f + (c >>> 6 ^ c >>> 11 ^ c >>> 25 ^ c << 26 ^ c << 21 ^ c << 7) + (e ^ c & (d ^ e)) + 0x84c87814 | 0; - b = b + f | 0; - f = f + (g & h ^ a & (g ^ h)) + (g >>> 2 ^ g >>> 13 ^ g >>> 22 ^ g << 30 ^ g << 19 ^ g << 10) | 0; + t = S1, S1 = S3, S3 = t; - // 59 - w11 = (w12 >>> 7 ^ w12 >>> 18 ^ w12 >>> 3 ^ w12 << 25 ^ w12 << 14) + (w9 >>> 17 ^ w9 >>> 19 ^ w9 >>> 10 ^ w9 << 15 ^ w9 << 13) + w11 + w4 | 0; - e = w11 + e + (b >>> 6 ^ b >>> 11 ^ b >>> 25 ^ b << 26 ^ b << 21 ^ b << 7) + (d ^ b & (c ^ d)) + 0x8cc70208 | 0; - a = a + e | 0; - e = e + (f & g ^ h & (f ^ g)) + (f >>> 2 ^ f >>> 13 ^ f >>> 22 ^ f << 30 ^ f << 19 ^ f << 10) | 0; + S0 = S0 ^ I0, + S1 = S1 ^ I1, + S2 = S2 ^ I2, + S3 = S3 ^ I3; - // 60 - w12 = (w13 >>> 7 ^ w13 >>> 18 ^ w13 >>> 3 ^ w13 << 25 ^ w13 << 14) + (w10 >>> 17 ^ w10 >>> 19 ^ w10 >>> 10 ^ w10 << 15 ^ w10 << 13) + w12 + w5 | 0; - d = w12 + d + (a >>> 6 ^ a >>> 11 ^ a >>> 25 ^ a << 26 ^ a << 21 ^ a << 7) + (c ^ a & (b ^ c)) + 0x90befffa | 0; - h = h + d | 0; - d = d + (e & f ^ g & (e ^ f)) + (e >>> 2 ^ e >>> 13 ^ e >>> 22 ^ e << 30 ^ e << 19 ^ e << 10) | 0; + I0 = x0, + I1 = x1, + I2 = x2, + I3 = x3; + } - // 61 - w13 = (w14 >>> 7 ^ w14 >>> 18 ^ w14 >>> 3 ^ w14 << 25 ^ w14 << 14) + (w11 >>> 17 ^ w11 >>> 19 ^ w11 >>> 10 ^ w11 << 15 ^ w11 << 13) + w13 + w6 | 0; - c = w13 + c + (h >>> 6 ^ h >>> 11 ^ h >>> 25 ^ h << 26 ^ h << 21 ^ h << 7) + (b ^ h & (a ^ b)) + 0xa4506ceb | 0; - g = g + c | 0; - c = c + (d & e ^ f & (d ^ e)) + (d >>> 2 ^ d >>> 13 ^ d >>> 22 ^ d << 30 ^ d << 19 ^ d << 10) | 0; + /** + * CFB mode encryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _cfb_enc(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; - // 62 - w14 = (w15 >>> 7 ^ w15 >>> 18 ^ w15 >>> 3 ^ w15 << 25 ^ w15 << 14) + (w12 >>> 17 ^ w12 >>> 19 ^ w12 >>> 10 ^ w12 << 15 ^ w12 << 13) + w14 + w7 | 0; - b = w14 + b + (g >>> 6 ^ g >>> 11 ^ g >>> 25 ^ g << 26 ^ g << 21 ^ g << 7) + (a ^ g & (h ^ a)) + 0xbef9a3f7 | 0; - f = f + b | 0; - b = b + (c & d ^ e & (c ^ d)) + (c >>> 2 ^ c >>> 13 ^ c >>> 22 ^ c << 30 ^ c << 19 ^ c << 10) | 0; + _core( + 0x0000, 0x0800, 0x1000, + R, + I0, + I1, + I2, + I3 + ); - // 63 - w15 = (w0 >>> 7 ^ w0 >>> 18 ^ w0 >>> 3 ^ w0 << 25 ^ w0 << 14) + (w13 >>> 17 ^ w13 >>> 19 ^ w13 >>> 10 ^ w13 << 15 ^ w13 << 13) + w15 + w8 | 0; - a = w15 + a + (f >>> 6 ^ f >>> 11 ^ f >>> 25 ^ f << 26 ^ f << 21 ^ f << 7) + (h ^ f & (g ^ h)) + 0xc67178f2 | 0; - e = e + a | 0; - a = a + (b & c ^ d & (b ^ c)) + (b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10) | 0; + I0 = S0 = S0 ^ x0, + I1 = S1 = S1 ^ x1, + I2 = S2 = S2 ^ x2, + I3 = S3 = S3 ^ x3; + } - H0 = H0 + a | 0; - H1 = H1 + b | 0; - H2 = H2 + c | 0; - H3 = H3 + d | 0; - H4 = H4 + e | 0; - H5 = H5 + f | 0; - H6 = H6 + g | 0; - H7 = H7 + h | 0; - } - function _core_heap(offset) { - offset = offset | 0; + /** + * CFB mode decryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _cfb_dec(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; - _core(HEAP[offset | 0] << 24 | HEAP[offset | 1] << 16 | HEAP[offset | 2] << 8 | HEAP[offset | 3], HEAP[offset | 4] << 24 | HEAP[offset | 5] << 16 | HEAP[offset | 6] << 8 | HEAP[offset | 7], HEAP[offset | 8] << 24 | HEAP[offset | 9] << 16 | HEAP[offset | 10] << 8 | HEAP[offset | 11], HEAP[offset | 12] << 24 | HEAP[offset | 13] << 16 | HEAP[offset | 14] << 8 | HEAP[offset | 15], HEAP[offset | 16] << 24 | HEAP[offset | 17] << 16 | HEAP[offset | 18] << 8 | HEAP[offset | 19], HEAP[offset | 20] << 24 | HEAP[offset | 21] << 16 | HEAP[offset | 22] << 8 | HEAP[offset | 23], HEAP[offset | 24] << 24 | HEAP[offset | 25] << 16 | HEAP[offset | 26] << 8 | HEAP[offset | 27], HEAP[offset | 28] << 24 | HEAP[offset | 29] << 16 | HEAP[offset | 30] << 8 | HEAP[offset | 31], HEAP[offset | 32] << 24 | HEAP[offset | 33] << 16 | HEAP[offset | 34] << 8 | HEAP[offset | 35], HEAP[offset | 36] << 24 | HEAP[offset | 37] << 16 | HEAP[offset | 38] << 8 | HEAP[offset | 39], HEAP[offset | 40] << 24 | HEAP[offset | 41] << 16 | HEAP[offset | 42] << 8 | HEAP[offset | 43], HEAP[offset | 44] << 24 | HEAP[offset | 45] << 16 | HEAP[offset | 46] << 8 | HEAP[offset | 47], HEAP[offset | 48] << 24 | HEAP[offset | 49] << 16 | HEAP[offset | 50] << 8 | HEAP[offset | 51], HEAP[offset | 52] << 24 | HEAP[offset | 53] << 16 | HEAP[offset | 54] << 8 | HEAP[offset | 55], HEAP[offset | 56] << 24 | HEAP[offset | 57] << 16 | HEAP[offset | 58] << 8 | HEAP[offset | 59], HEAP[offset | 60] << 24 | HEAP[offset | 61] << 16 | HEAP[offset | 62] << 8 | HEAP[offset | 63]); - } + _core( + 0x0000, 0x0800, 0x1000, + R, + I0, + I1, + I2, + I3 + ); - // offset — multiple of 32 - function _state_to_heap(output) { - output = output | 0; - - HEAP[output | 0] = H0 >>> 24; - HEAP[output | 1] = H0 >>> 16 & 255; - HEAP[output | 2] = H0 >>> 8 & 255; - HEAP[output | 3] = H0 & 255; - HEAP[output | 4] = H1 >>> 24; - HEAP[output | 5] = H1 >>> 16 & 255; - HEAP[output | 6] = H1 >>> 8 & 255; - HEAP[output | 7] = H1 & 255; - HEAP[output | 8] = H2 >>> 24; - HEAP[output | 9] = H2 >>> 16 & 255; - HEAP[output | 10] = H2 >>> 8 & 255; - HEAP[output | 11] = H2 & 255; - HEAP[output | 12] = H3 >>> 24; - HEAP[output | 13] = H3 >>> 16 & 255; - HEAP[output | 14] = H3 >>> 8 & 255; - HEAP[output | 15] = H3 & 255; - HEAP[output | 16] = H4 >>> 24; - HEAP[output | 17] = H4 >>> 16 & 255; - HEAP[output | 18] = H4 >>> 8 & 255; - HEAP[output | 19] = H4 & 255; - HEAP[output | 20] = H5 >>> 24; - HEAP[output | 21] = H5 >>> 16 & 255; - HEAP[output | 22] = H5 >>> 8 & 255; - HEAP[output | 23] = H5 & 255; - HEAP[output | 24] = H6 >>> 24; - HEAP[output | 25] = H6 >>> 16 & 255; - HEAP[output | 26] = H6 >>> 8 & 255; - HEAP[output | 27] = H6 & 255; - HEAP[output | 28] = H7 >>> 24; - HEAP[output | 29] = H7 >>> 16 & 255; - HEAP[output | 30] = H7 >>> 8 & 255; - HEAP[output | 31] = H7 & 255; - } - - function reset() { - H0 = 0x6a09e667; - H1 = 0xbb67ae85; - H2 = 0x3c6ef372; - H3 = 0xa54ff53a; - H4 = 0x510e527f; - H5 = 0x9b05688c; - H6 = 0x1f83d9ab; - H7 = 0x5be0cd19; - TOTAL0 = TOTAL1 = 0; - } + S0 = S0 ^ x0, + S1 = S1 ^ x1, + S2 = S2 ^ x2, + S3 = S3 ^ x3; - function init(h0, h1, h2, h3, h4, h5, h6, h7, total0, total1) { - h0 = h0 | 0; - h1 = h1 | 0; - h2 = h2 | 0; - h3 = h3 | 0; - h4 = h4 | 0; - h5 = h5 | 0; - h6 = h6 | 0; - h7 = h7 | 0; - total0 = total0 | 0; - total1 = total1 | 0; + I0 = x0, + I1 = x1, + I2 = x2, + I3 = x3; + } - H0 = h0; - H1 = h1; - H2 = h2; - H3 = h3; - H4 = h4; - H5 = h5; - H6 = h6; - H7 = h7; - TOTAL0 = total0; - TOTAL1 = total1; - } + /** + * OFB mode encryption / decryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _ofb(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; - // offset — multiple of 64 - function process(offset, length) { - offset = offset | 0; - length = length | 0; + _core( + 0x0000, 0x0800, 0x1000, + R, + I0, + I1, + I2, + I3 + ); - var hashed = 0; + I0 = S0, + I1 = S1, + I2 = S2, + I3 = S3; - if (offset & 63) return -1; + S0 = S0 ^ x0, + S1 = S1 ^ x1, + S2 = S2 ^ x2, + S3 = S3 ^ x3; + } - while ((length | 0) >= 64) { - _core_heap(offset); + /** + * CTR mode encryption / decryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _ctr(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; - offset = offset + 64 | 0; - length = length - 64 | 0; + _core( + 0x0000, 0x0800, 0x1000, + R, + N0, + N1, + N2, + N3 + ); - hashed = hashed + 64 | 0; - } + N3 = (~M3 & N3) | M3 & (N3 + 1); + N2 = (~M2 & N2) | M2 & (N2 + ((N3 | 0) == 0)); + N1 = (~M1 & N1) | M1 & (N1 + ((N2 | 0) == 0)); + N0 = (~M0 & N0) | M0 & (N0 + ((N1 | 0) == 0)); - TOTAL0 = TOTAL0 + hashed | 0; - if (TOTAL0 >>> 0 < hashed >>> 0) TOTAL1 = TOTAL1 + 1 | 0; + S0 = S0 ^ x0; + S1 = S1 ^ x1; + S2 = S2 ^ x2; + S3 = S3 ^ x3; + } - return hashed | 0; - } + /** + * GCM mode MAC calculation + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _gcm_mac(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; - // offset — multiple of 64 - // output — multiple of 32 - function finish(offset, length, output) { - offset = offset | 0; - length = length | 0; - output = output | 0; + var y0 = 0, y1 = 0, y2 = 0, y3 = 0, + z0 = 0, z1 = 0, z2 = 0, z3 = 0, + i = 0, c = 0; - var hashed = 0, - i = 0; + x0 = x0 ^ I0, + x1 = x1 ^ I1, + x2 = x2 ^ I2, + x3 = x3 ^ I3; - if (offset & 63) return -1; + y0 = H0 | 0, + y1 = H1 | 0, + y2 = H2 | 0, + y3 = H3 | 0; - if (~output) if (output & 31) return -1; + for (; (i | 0) < 128; i = (i + 1) | 0) { + if (y0 >>> 31) { + z0 = z0 ^ x0, + z1 = z1 ^ x1, + z2 = z2 ^ x2, + z3 = z3 ^ x3; + } - if ((length | 0) >= 64) { - hashed = process(offset, length) | 0; - if ((hashed | 0) == -1) return -1; + y0 = (y0 << 1) | (y1 >>> 31), + y1 = (y1 << 1) | (y2 >>> 31), + y2 = (y2 << 1) | (y3 >>> 31), + y3 = (y3 << 1); - offset = offset + hashed | 0; - length = length - hashed | 0; - } + c = x3 & 1; - hashed = hashed + length | 0; - TOTAL0 = TOTAL0 + length | 0; - if (TOTAL0 >>> 0 < length >>> 0) TOTAL1 = TOTAL1 + 1 | 0; + x3 = (x3 >>> 1) | (x2 << 31), + x2 = (x2 >>> 1) | (x1 << 31), + x1 = (x1 >>> 1) | (x0 << 31), + x0 = (x0 >>> 1); - HEAP[offset | length] = 0x80; + if (c) x0 = x0 ^ 0xe1000000; + } - if ((length | 0) >= 56) { - for (i = length + 1 | 0; (i | 0) < 64; i = i + 1 | 0) HEAP[offset | i] = 0x00; + I0 = z0, + I1 = z1, + I2 = z2, + I3 = z3; + } - _core_heap(offset); + /** + * Set the internal rounds number. + * @instance + * @memberof AES_asm + * @param {number} r - number if inner AES rounds + */ + function set_rounds(r) { + r = r | 0; + R = r; + } - length = 0; + /** + * Populate the internal state of the module. + * @instance + * @memberof AES_asm + * @param {number} s0 - state vector + * @param {number} s1 - state vector + * @param {number} s2 - state vector + * @param {number} s3 - state vector + */ + function set_state(s0, s1, s2, s3) { + s0 = s0 | 0; + s1 = s1 | 0; + s2 = s2 | 0; + s3 = s3 | 0; - HEAP[offset | 0] = 0; - } + S0 = s0, + S1 = s1, + S2 = s2, + S3 = s3; + } - for (i = length + 1 | 0; (i | 0) < 59; i = i + 1 | 0) HEAP[offset | i] = 0; + /** + * Populate the internal iv of the module. + * @instance + * @memberof AES_asm + * @param {number} i0 - iv vector + * @param {number} i1 - iv vector + * @param {number} i2 - iv vector + * @param {number} i3 - iv vector + */ + function set_iv(i0, i1, i2, i3) { + i0 = i0 | 0; + i1 = i1 | 0; + i2 = i2 | 0; + i3 = i3 | 0; - HEAP[offset | 56] = TOTAL1 >>> 21 & 255; - HEAP[offset | 57] = TOTAL1 >>> 13 & 255; - HEAP[offset | 58] = TOTAL1 >>> 5 & 255; - HEAP[offset | 59] = TOTAL1 << 3 & 255 | TOTAL0 >>> 29; - HEAP[offset | 60] = TOTAL0 >>> 21 & 255; - HEAP[offset | 61] = TOTAL0 >>> 13 & 255; - HEAP[offset | 62] = TOTAL0 >>> 5 & 255; - HEAP[offset | 63] = TOTAL0 << 3 & 255; - _core_heap(offset); + I0 = i0, + I1 = i1, + I2 = i2, + I3 = i3; + } - if (~output) _state_to_heap(output); + /** + * Set nonce for CTR-family modes. + * @instance + * @memberof AES_asm + * @param {number} n0 - nonce vector + * @param {number} n1 - nonce vector + * @param {number} n2 - nonce vector + * @param {number} n3 - nonce vector + */ + function set_nonce(n0, n1, n2, n3) { + n0 = n0 | 0; + n1 = n1 | 0; + n2 = n2 | 0; + n3 = n3 | 0; - return hashed | 0; - } + N0 = n0, + N1 = n1, + N2 = n2, + N3 = n3; + } - function hmac_reset() { - H0 = I0; - H1 = I1; - H2 = I2; - H3 = I3; - H4 = I4; - H5 = I5; - H6 = I6; - H7 = I7; - TOTAL0 = 64; - TOTAL1 = 0; - } + /** + * Set counter mask for CTR-family modes. + * @instance + * @memberof AES_asm + * @param {number} m0 - counter mask vector + * @param {number} m1 - counter mask vector + * @param {number} m2 - counter mask vector + * @param {number} m3 - counter mask vector + */ + function set_mask(m0, m1, m2, m3) { + m0 = m0 | 0; + m1 = m1 | 0; + m2 = m2 | 0; + m3 = m3 | 0; - function _hmac_opad() { - H0 = O0; - H1 = O1; - H2 = O2; - H3 = O3; - H4 = O4; - H5 = O5; - H6 = O6; - H7 = O7; - TOTAL0 = 64; - TOTAL1 = 0; - } + M0 = m0, + M1 = m1, + M2 = m2, + M3 = m3; + } - function hmac_init(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15) { - p0 = p0 | 0; - p1 = p1 | 0; - p2 = p2 | 0; - p3 = p3 | 0; - p4 = p4 | 0; - p5 = p5 | 0; - p6 = p6 | 0; - p7 = p7 | 0; - p8 = p8 | 0; - p9 = p9 | 0; - p10 = p10 | 0; - p11 = p11 | 0; - p12 = p12 | 0; - p13 = p13 | 0; - p14 = p14 | 0; - p15 = p15 | 0; + /** + * Set counter for CTR-family modes. + * @instance + * @memberof AES_asm + * @param {number} c0 - counter vector + * @param {number} c1 - counter vector + * @param {number} c2 - counter vector + * @param {number} c3 - counter vector + */ + function set_counter(c0, c1, c2, c3) { + c0 = c0 | 0; + c1 = c1 | 0; + c2 = c2 | 0; + c3 = c3 | 0; - // opad - reset(); - _core(p0 ^ 0x5c5c5c5c, p1 ^ 0x5c5c5c5c, p2 ^ 0x5c5c5c5c, p3 ^ 0x5c5c5c5c, p4 ^ 0x5c5c5c5c, p5 ^ 0x5c5c5c5c, p6 ^ 0x5c5c5c5c, p7 ^ 0x5c5c5c5c, p8 ^ 0x5c5c5c5c, p9 ^ 0x5c5c5c5c, p10 ^ 0x5c5c5c5c, p11 ^ 0x5c5c5c5c, p12 ^ 0x5c5c5c5c, p13 ^ 0x5c5c5c5c, p14 ^ 0x5c5c5c5c, p15 ^ 0x5c5c5c5c); - O0 = H0; - O1 = H1; - O2 = H2; - O3 = H3; - O4 = H4; - O5 = H5; - O6 = H6; - O7 = H7; + N3 = (~M3 & N3) | M3 & c3, + N2 = (~M2 & N2) | M2 & c2, + N1 = (~M1 & N1) | M1 & c1, + N0 = (~M0 & N0) | M0 & c0; + } - // ipad - reset(); - _core(p0 ^ 0x36363636, p1 ^ 0x36363636, p2 ^ 0x36363636, p3 ^ 0x36363636, p4 ^ 0x36363636, p5 ^ 0x36363636, p6 ^ 0x36363636, p7 ^ 0x36363636, p8 ^ 0x36363636, p9 ^ 0x36363636, p10 ^ 0x36363636, p11 ^ 0x36363636, p12 ^ 0x36363636, p13 ^ 0x36363636, p14 ^ 0x36363636, p15 ^ 0x36363636); - I0 = H0; - I1 = H1; - I2 = H2; - I3 = H3; - I4 = H4; - I5 = H5; - I6 = H6; - I7 = H7; + /** + * Store the internal state vector into the heap. + * @instance + * @memberof AES_asm + * @param {number} pos - offset where to put the data + * @return {number} The number of bytes have been written into the heap, always 16. + */ + function get_state(pos) { + pos = pos | 0; - TOTAL0 = 64; - TOTAL1 = 0; - } + if (pos & 15) return -1; - // offset — multiple of 64 - // output — multiple of 32 - function hmac_finish(offset, length, output) { - offset = offset | 0; - length = length | 0; - output = output | 0; - - var t0 = 0, - t1 = 0, - t2 = 0, - t3 = 0, - t4 = 0, - t5 = 0, - t6 = 0, - t7 = 0, - hashed = 0; + DATA[pos | 0] = S0 >>> 24, + DATA[pos | 1] = S0 >>> 16 & 255, + DATA[pos | 2] = S0 >>> 8 & 255, + DATA[pos | 3] = S0 & 255, + DATA[pos | 4] = S1 >>> 24, + DATA[pos | 5] = S1 >>> 16 & 255, + DATA[pos | 6] = S1 >>> 8 & 255, + DATA[pos | 7] = S1 & 255, + DATA[pos | 8] = S2 >>> 24, + DATA[pos | 9] = S2 >>> 16 & 255, + DATA[pos | 10] = S2 >>> 8 & 255, + DATA[pos | 11] = S2 & 255, + DATA[pos | 12] = S3 >>> 24, + DATA[pos | 13] = S3 >>> 16 & 255, + DATA[pos | 14] = S3 >>> 8 & 255, + DATA[pos | 15] = S3 & 255; - if (offset & 63) return -1; + return 16; + } - if (~output) if (output & 31) return -1; + /** + * Store the internal iv vector into the heap. + * @instance + * @memberof AES_asm + * @param {number} pos - offset where to put the data + * @return {number} The number of bytes have been written into the heap, always 16. + */ + function get_iv(pos) { + pos = pos | 0; - hashed = finish(offset, length, -1) | 0; - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; + if (pos & 15) return -1; - _hmac_opad(); - _core(t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768); + DATA[pos | 0] = I0 >>> 24, + DATA[pos | 1] = I0 >>> 16 & 255, + DATA[pos | 2] = I0 >>> 8 & 255, + DATA[pos | 3] = I0 & 255, + DATA[pos | 4] = I1 >>> 24, + DATA[pos | 5] = I1 >>> 16 & 255, + DATA[pos | 6] = I1 >>> 8 & 255, + DATA[pos | 7] = I1 & 255, + DATA[pos | 8] = I2 >>> 24, + DATA[pos | 9] = I2 >>> 16 & 255, + DATA[pos | 10] = I2 >>> 8 & 255, + DATA[pos | 11] = I2 & 255, + DATA[pos | 12] = I3 >>> 24, + DATA[pos | 13] = I3 >>> 16 & 255, + DATA[pos | 14] = I3 >>> 8 & 255, + DATA[pos | 15] = I3 & 255; - if (~output) _state_to_heap(output); + return 16; + } - return hashed | 0; - } + /** + * GCM initialization. + * @instance + * @memberof AES_asm + */ + function gcm_init() { + _ecb_enc(0, 0, 0, 0); + H0 = S0, + H1 = S1, + H2 = S2, + H3 = S3; + } - // salt is assumed to be already processed - // offset — multiple of 64 - // output — multiple of 32 - function pbkdf2_generate_block(offset, length, block, count, output) { - offset = offset | 0; - length = length | 0; - block = block | 0; - count = count | 0; - output = output | 0; - - var h0 = 0, - h1 = 0, - h2 = 0, - h3 = 0, - h4 = 0, - h5 = 0, - h6 = 0, - h7 = 0, - t0 = 0, - t1 = 0, - t2 = 0, - t3 = 0, - t4 = 0, - t5 = 0, - t6 = 0, - t7 = 0; - - if (offset & 63) return -1; - - if (~output) if (output & 31) return -1; + /** + * Perform ciphering operation on the supplied data. + * @instance + * @memberof AES_asm + * @param {number} mode - block cipher mode (see {@link AES_asm} mode constants) + * @param {number} pos - offset of the data being processed + * @param {number} len - length of the data being processed + * @return {number} Actual amount of data have been processed. + */ + function cipher(mode, pos, len) { + mode = mode | 0; + pos = pos | 0; + len = len | 0; - // pad block number into heap - // FIXME probable OOB write - HEAP[offset + length | 0] = block >>> 24; - HEAP[offset + length + 1 | 0] = block >>> 16 & 255; - HEAP[offset + length + 2 | 0] = block >>> 8 & 255; - HEAP[offset + length + 3 | 0] = block & 255; + var ret = 0; - // finish first iteration - hmac_finish(offset, length + 4 | 0, -1) | 0; - h0 = t0 = H0, h1 = t1 = H1, h2 = t2 = H2, h3 = t3 = H3, h4 = t4 = H4, h5 = t5 = H5, h6 = t6 = H6, h7 = t7 = H7; - count = count - 1 | 0; + if (pos & 15) return -1; - // perform the rest iterations - while ((count | 0) > 0) { - hmac_reset(); - _core(t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768); - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; + while ((len | 0) >= 16) { + _cipher_modes[mode & 7]( + DATA[pos | 0] << 24 | DATA[pos | 1] << 16 | DATA[pos | 2] << 8 | DATA[pos | 3], + DATA[pos | 4] << 24 | DATA[pos | 5] << 16 | DATA[pos | 6] << 8 | DATA[pos | 7], + DATA[pos | 8] << 24 | DATA[pos | 9] << 16 | DATA[pos | 10] << 8 | DATA[pos | 11], + DATA[pos | 12] << 24 | DATA[pos | 13] << 16 | DATA[pos | 14] << 8 | DATA[pos | 15] + ); + + DATA[pos | 0] = S0 >>> 24, + DATA[pos | 1] = S0 >>> 16 & 255, + DATA[pos | 2] = S0 >>> 8 & 255, + DATA[pos | 3] = S0 & 255, + DATA[pos | 4] = S1 >>> 24, + DATA[pos | 5] = S1 >>> 16 & 255, + DATA[pos | 6] = S1 >>> 8 & 255, + DATA[pos | 7] = S1 & 255, + DATA[pos | 8] = S2 >>> 24, + DATA[pos | 9] = S2 >>> 16 & 255, + DATA[pos | 10] = S2 >>> 8 & 255, + DATA[pos | 11] = S2 & 255, + DATA[pos | 12] = S3 >>> 24, + DATA[pos | 13] = S3 >>> 16 & 255, + DATA[pos | 14] = S3 >>> 8 & 255, + DATA[pos | 15] = S3 & 255; + + ret = (ret + 16) | 0, + pos = (pos + 16) | 0, + len = (len - 16) | 0; + } - _hmac_opad(); - _core(t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768); - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; + return ret | 0; + } - h0 = h0 ^ H0; - h1 = h1 ^ H1; - h2 = h2 ^ H2; - h3 = h3 ^ H3; - h4 = h4 ^ H4; - h5 = h5 ^ H5; - h6 = h6 ^ H6; - h7 = h7 ^ H7; + /** + * Calculates MAC of the supplied data. + * @instance + * @memberof AES_asm + * @param {number} mode - block cipher mode (see {@link AES_asm} mode constants) + * @param {number} pos - offset of the data being processed + * @param {number} len - length of the data being processed + * @return {number} Actual amount of data have been processed. + */ + function mac(mode, pos, len) { + mode = mode | 0; + pos = pos | 0; + len = len | 0; - count = count - 1 | 0; - } + var ret = 0; - H0 = h0; - H1 = h1; - H2 = h2; - H3 = h3; - H4 = h4; - H5 = h5; - H6 = h6; - H7 = h7; + if (pos & 15) return -1; - if (~output) _state_to_heap(output); + while ((len | 0) >= 16) { + _mac_modes[mode & 1]( + DATA[pos | 0] << 24 | DATA[pos | 1] << 16 | DATA[pos | 2] << 8 | DATA[pos | 3], + DATA[pos | 4] << 24 | DATA[pos | 5] << 16 | DATA[pos | 6] << 8 | DATA[pos | 7], + DATA[pos | 8] << 24 | DATA[pos | 9] << 16 | DATA[pos | 10] << 8 | DATA[pos | 11], + DATA[pos | 12] << 24 | DATA[pos | 13] << 16 | DATA[pos | 14] << 8 | DATA[pos | 15] + ); - return 0; - } + ret = (ret + 16) | 0, + pos = (pos + 16) | 0, + len = (len - 16) | 0; + } - return { - // SHA256 - reset: reset, - init: init, - process: process, - finish: finish, - - // HMAC-SHA256 - hmac_reset: hmac_reset, - hmac_init: hmac_init, - hmac_finish: hmac_finish, - - // PBKDF2-HMAC-SHA256 - pbkdf2_generate_block: pbkdf2_generate_block - }; -} + return ret | 0; + } -},{}],13:[function(require,module,exports){ -'use strict'; + /** + * AES cipher modes table (virual methods) + */ + var _cipher_modes = [_ecb_enc, _ecb_dec, _cbc_enc, _cbc_dec, _cfb_enc, _cfb_dec, _ofb, _ctr]; -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.Sha256 = exports._sha256_hash_size = exports._sha256_block_size = undefined; + /** + * AES MAC modes table (virual methods) + */ + var _mac_modes = [_cbc_enc, _gcm_mac]; -var _sha = require('./sha256.asm'); + /** + * Asm.js module exports + */ + return { + set_rounds: set_rounds, + set_state: set_state, + set_iv: set_iv, + set_nonce: set_nonce, + set_mask: set_mask, + set_counter: set_counter, + get_state: get_state, + get_iv: get_iv, + gcm_init: gcm_init, + cipher: cipher, + mac: mac, + }; + }(stdlib, foreign, buffer); -var _hash = require('../hash'); + asm.set_key = set_key; -var __extends = undefined && undefined.__extends || function () { - var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) { - d.__proto__ = b; - } || function (d, b) { - for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; - }; - return function (d, b) { - extendStatics(d, b); - function __() { - this.constructor = d; - } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -}(); -var _sha256_block_size = exports._sha256_block_size = 64; -var _sha256_hash_size = exports._sha256_hash_size = 32; -var Sha256 = /** @class */function (_super) { - __extends(Sha256, _super); - function Sha256() { - var _this = _super !== null && _super.apply(this, arguments) || this; - _this.NAME = 'sha256'; - _this.BLOCK_SIZE = _sha256_block_size; - _this.HASH_SIZE = _sha256_hash_size; - return _this; - } - Sha256.bytes = function (data) { - return new Sha256().process(data).finish().result; - }; - Sha256.NAME = 'sha256'; - Sha256.heap_pool = []; - Sha256.asm_pool = []; - Sha256.asm_function = _sha.sha256_asm; - return Sha256; -}(_hash.Hash); -exports.Sha256 = Sha256; - -},{"../hash":9,"./sha256.asm":12}],14:[function(require,module,exports){ -'use strict'; + return asm; + }; -Object.defineProperty(exports, "__esModule", { - value: true -}); -var __extends = undefined && undefined.__extends || function () { - var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) { - d.__proto__ = b; - } || function (d, b) { - for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; - }; - return function (d, b) { - extendStatics(d, b); - function __() { - this.constructor = d; - } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -}(); -var IllegalStateError = /** @class */function (_super) { - __extends(IllegalStateError, _super); - function IllegalStateError() { - var args = []; - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - var _this = _super.apply(this, args) || this; - Object.create(Error.prototype, { name: { value: 'IllegalStateError' } }); - return _this; - } - return IllegalStateError; -}(Error); -exports.IllegalStateError = IllegalStateError; + /** + * AES enciphering mode constants + * @enum {number} + * @const + */ + wrapper.ENC = { + ECB: 0, + CBC: 2, + CFB: 4, + OFB: 6, + CTR: 7, + }, -var IllegalArgumentError = /** @class */function (_super) { - __extends(IllegalArgumentError, _super); - function IllegalArgumentError() { - var args = []; - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - var _this = _super.apply(this, args) || this; - Object.create(Error.prototype, { name: { value: 'IllegalArgumentError' } }); - return _this; - } - return IllegalArgumentError; -}(Error); -exports.IllegalArgumentError = IllegalArgumentError; + /** + * AES deciphering mode constants + * @enum {number} + * @const + */ + wrapper.DEC = { + ECB: 1, + CBC: 3, + CFB: 5, + OFB: 6, + CTR: 7, + }, -var SecurityError = /** @class */function (_super) { - __extends(SecurityError, _super); - function SecurityError() { - var args = []; - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - var _this = _super.apply(this, args) || this; - Object.create(Error.prototype, { name: { value: 'SecurityError' } }); - return _this; - } - return SecurityError; -}(Error); -exports.SecurityError = SecurityError; + /** + * AES MAC mode constants + * @enum {number} + * @const + */ + wrapper.MAC = { + CBC: 0, + GCM: 1, + }; -},{}],15:[function(require,module,exports){ -'use strict'; + /** + * Heap data offset + * @type {number} + * @const + */ + wrapper.HEAP_DATA = 0x4000; + + return wrapper; +}(); -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.string_to_bytes = string_to_bytes; -exports.hex_to_bytes = hex_to_bytes; -exports.base64_to_bytes = base64_to_bytes; -exports.bytes_to_string = bytes_to_string; -exports.bytes_to_hex = bytes_to_hex; -exports.bytes_to_base64 = bytes_to_base64; -exports.pow2_ceil = pow2_ceil; -exports.is_number = is_number; -exports.is_string = is_string; -exports.is_buffer = is_buffer; -exports.is_bytes = is_bytes; -exports.is_typed_array = is_typed_array; -exports._heap_init = _heap_init; -exports._heap_write = _heap_write; -exports.joinBytes = joinBytes; -var local_atob = typeof atob === 'undefined' ? function (str) { - return require('buffer').Buffer.from(str, 'base64').toString('binary'); -} : atob; -var local_btoa = typeof btoa === 'undefined' ? function (str) { - return require('buffer').Buffer.from(str, 'binary').toString('base64'); -} : btoa; -function string_to_bytes(str, utf8) { - if (utf8 === void 0) { - utf8 = false; - } - var len = str.length, - bytes = new Uint8Array(utf8 ? 4 * len : len); - for (var i = 0, j = 0; i < len; i++) { - var c = str.charCodeAt(i); - if (utf8 && 0xd800 <= c && c <= 0xdbff) { - if (++i >= len) throw new Error('Malformed string, low surrogate expected at position ' + i); - c = (c ^ 0xd800) << 10 | 0x10000 | str.charCodeAt(i) ^ 0xdc00; - } else if (!utf8 && c >>> 8) { - throw new Error('Wide characters are not allowed.'); - } - if (!utf8 || c <= 0x7f) { - bytes[j++] = c; - } else if (c <= 0x7ff) { - bytes[j++] = 0xc0 | c >> 6; - bytes[j++] = 0x80 | c & 0x3f; - } else if (c <= 0xffff) { - bytes[j++] = 0xe0 | c >> 12; - bytes[j++] = 0x80 | c >> 6 & 0x3f; - bytes[j++] = 0x80 | c & 0x3f; - } else { - bytes[j++] = 0xf0 | c >> 18; - bytes[j++] = 0x80 | c >> 12 & 0x3f; - bytes[j++] = 0x80 | c >> 6 & 0x3f; - bytes[j++] = 0x80 | c & 0x3f; - } - } - return bytes.subarray(0, j); -} -function hex_to_bytes(str) { - var len = str.length; - if (len & 1) { - str = '0' + str; - len++; - } - var bytes = new Uint8Array(len >> 1); - for (var i = 0; i < len; i += 2) { - bytes[i >> 1] = parseInt(str.substr(i, 2), 16); - } - return bytes; -} -function base64_to_bytes(str) { - return string_to_bytes(local_atob(str)); -} -function bytes_to_string(bytes, utf8) { - if (utf8 === void 0) { - utf8 = false; - } - var len = bytes.length, - chars = new Array(len); - for (var i = 0, j = 0; i < len; i++) { - var b = bytes[i]; - if (!utf8 || b < 128) { - chars[j++] = b; - } else if (b >= 192 && b < 224 && i + 1 < len) { - chars[j++] = (b & 0x1f) << 6 | bytes[++i] & 0x3f; - } else if (b >= 224 && b < 240 && i + 2 < len) { - chars[j++] = (b & 0xf) << 12 | (bytes[++i] & 0x3f) << 6 | bytes[++i] & 0x3f; - } else if (b >= 240 && b < 248 && i + 3 < len) { - var c = (b & 7) << 18 | (bytes[++i] & 0x3f) << 12 | (bytes[++i] & 0x3f) << 6 | bytes[++i] & 0x3f; - if (c <= 0xffff) { - chars[j++] = c; - } else { - c ^= 0x10000; - chars[j++] = 0xd800 | c >> 10; - chars[j++] = 0xdc00 | c & 0x3ff; - } - } else { - throw new Error('Malformed UTF8 character at byte offset ' + i); - } - } - var str = '', - bs = 16384; - for (var i = 0; i < j; i += bs) { - str += String.fromCharCode.apply(String, chars.slice(i, i + bs <= j ? i + bs : j)); - } - return str; -} -function bytes_to_hex(arr) { - var str = ''; - for (var i = 0; i < arr.length; i++) { - var h = (arr[i] & 0xff).toString(16); - if (h.length < 2) str += '0'; - str += h; - } - return str; -} -function bytes_to_base64(arr) { - return local_btoa(bytes_to_string(arr)); -} -function pow2_ceil(a) { - a -= 1; - a |= a >>> 1; - a |= a >>> 2; - a |= a >>> 4; - a |= a >>> 8; - a |= a >>> 16; - a += 1; - return a; -} -function is_number(a) { - return typeof a === 'number'; -} -function is_string(a) { - return typeof a === 'string'; -} -function is_buffer(a) { - return a instanceof ArrayBuffer; -} function is_bytes(a) { return a instanceof Uint8Array; } -function is_typed_array(a) { - return a instanceof Int8Array || a instanceof Uint8Array || a instanceof Int16Array || a instanceof Uint16Array || a instanceof Int32Array || a instanceof Uint32Array || a instanceof Float32Array || a instanceof Float64Array; -} function _heap_init(heap, heapSize) { - var size = heap ? heap.byteLength : heapSize || 65536; - if (size & 0xfff || size <= 0) throw new Error('heap size must be a positive integer and a multiple of 4096'); + const size = heap ? heap.byteLength : heapSize || 65536; + if (size & 0xfff || size <= 0) + throw new Error('heap size must be a positive integer and a multiple of 4096'); heap = heap || new Uint8Array(new ArrayBuffer(size)); return heap; } function _heap_write(heap, hpos, data, dpos, dlen) { - var hlen = heap.length - hpos; - var wlen = hlen < dlen ? hlen : dlen; + const hlen = heap.length - hpos; + const wlen = hlen < dlen ? hlen : dlen; heap.set(data.subarray(dpos, dpos + wlen), hpos); return wlen; } -function joinBytes() { - var arg = []; - for (var _i = 0; _i < arguments.length; _i++) { - arg[_i] = arguments[_i]; - } - var totalLenght = arg.reduce(function (sum, curr) { - return sum + curr.length; - }, 0); - var ret = new Uint8Array(totalLenght); - var cursor = 0; - for (var i = 0; i < arg.length; i++) { +function joinBytes(...arg) { + const totalLenght = arg.reduce((sum, curr) => sum + curr.length, 0); + const ret = new Uint8Array(totalLenght); + let cursor = 0; + for (let i = 0; i < arg.length; i++) { ret.set(arg[i], cursor); cursor += arg[i].length; } return ret; } -},{"buffer":"buffer"}],16:[function(require,module,exports){ -(function (module, exports) { - 'use strict'; - - // Utils - function assert (val, msg) { - if (!val) throw new Error(msg || 'Assertion failed'); - } - - // Could use `inherits` module, but don't want to move from single file - // architecture yet. - function inherits (ctor, superCtor) { - ctor.super_ = superCtor; - var TempCtor = function () {}; - TempCtor.prototype = superCtor.prototype; - ctor.prototype = new TempCtor(); - ctor.prototype.constructor = ctor; - } - - // BN - - function BN (number, base, endian) { - if (BN.isBN(number)) { - return number; +class IllegalStateError extends Error { + constructor(...args) { + super(...args); } +} +class IllegalArgumentError extends Error { + constructor(...args) { + super(...args); + } +} +class SecurityError extends Error { + constructor(...args) { + super(...args); + } +} - this.negative = 0; - this.words = null; - this.length = 0; - - // Reduction context - this.red = null; - - if (number !== null) { - if (base === 'le' || base === 'be') { - endian = base; - base = 10; - } - - this._init(number || 0, base || 10, endian || 'be'); +const heap_pool = []; +const asm_pool = []; +class AES { + constructor(key, iv, padding = true, mode, heap, asm) { + this.pos = 0; + this.len = 0; + this.mode = mode; + // The AES object state + this.pos = 0; + this.len = 0; + this.key = key; + this.iv = iv; + this.padding = padding; + // The AES "worker" + this.acquire_asm(heap, asm); } - } - if (typeof module === 'object') { - module.exports = BN; - } else { - exports.BN = BN; - } - - BN.BN = BN; - BN.wordSize = 26; - - var Buffer; - try { - Buffer = require('buffer').Buffer; - } catch (e) { - } - - BN.isBN = function isBN (num) { - if (num instanceof BN) { - return true; + acquire_asm(heap, asm) { + if (this.heap === undefined || this.asm === undefined) { + this.heap = heap || heap_pool.pop() || _heap_init().subarray(AES_asm.HEAP_DATA); + this.asm = asm || asm_pool.pop() || new AES_asm(null, this.heap.buffer); + this.reset(this.key, this.iv); + } + return { heap: this.heap, asm: this.asm }; } - - return num !== null && typeof num === 'object' && - num.constructor.wordSize === BN.wordSize && Array.isArray(num.words); - }; - - BN.max = function max (left, right) { - if (left.cmp(right) > 0) return left; - return right; - }; - - BN.min = function min (left, right) { - if (left.cmp(right) < 0) return left; - return right; - }; - - BN.prototype._init = function init (number, base, endian) { - if (typeof number === 'number') { - return this._initNumber(number, base, endian); + release_asm() { + if (this.heap !== undefined && this.asm !== undefined) { + heap_pool.push(this.heap); + asm_pool.push(this.asm); + } + this.heap = undefined; + this.asm = undefined; } - - if (typeof number === 'object') { - return this._initArray(number, base, endian); + reset(key, iv) { + const { asm } = this.acquire_asm(); + // Key + const keylen = key.length; + if (keylen !== 16 && keylen !== 24 && keylen !== 32) + throw new IllegalArgumentError('illegal key size'); + const keyview = new DataView(key.buffer, key.byteOffset, key.byteLength); + asm.set_key(keylen >> 2, keyview.getUint32(0), keyview.getUint32(4), keyview.getUint32(8), keyview.getUint32(12), keylen > 16 ? keyview.getUint32(16) : 0, keylen > 16 ? keyview.getUint32(20) : 0, keylen > 24 ? keyview.getUint32(24) : 0, keylen > 24 ? keyview.getUint32(28) : 0); + // IV + if (iv !== undefined) { + if (iv.length !== 16) + throw new IllegalArgumentError('illegal iv size'); + let ivview = new DataView(iv.buffer, iv.byteOffset, iv.byteLength); + asm.set_iv(ivview.getUint32(0), ivview.getUint32(4), ivview.getUint32(8), ivview.getUint32(12)); + } + else { + asm.set_iv(0, 0, 0, 0); + } + } + AES_Encrypt_process(data) { + if (!is_bytes(data)) + throw new TypeError("data isn't of expected type"); + let { heap, asm } = this.acquire_asm(); + let amode = AES_asm.ENC[this.mode]; + let hpos = AES_asm.HEAP_DATA; + let pos = this.pos; + let len = this.len; + let dpos = 0; + let dlen = data.length || 0; + let rpos = 0; + let rlen = (len + dlen) & -16; + let wlen = 0; + let result = new Uint8Array(rlen); + while (dlen > 0) { + wlen = _heap_write(heap, pos + len, data, dpos, dlen); + len += wlen; + dpos += wlen; + dlen -= wlen; + wlen = asm.cipher(amode, hpos + pos, len); + if (wlen) + result.set(heap.subarray(pos, pos + wlen), rpos); + rpos += wlen; + if (wlen < len) { + pos += wlen; + len -= wlen; + } + else { + pos = 0; + len = 0; + } + } + this.pos = pos; + this.len = len; + return result; } - - if (base === 'hex') { - base = 16; + AES_Encrypt_finish() { + let { heap, asm } = this.acquire_asm(); + let amode = AES_asm.ENC[this.mode]; + let hpos = AES_asm.HEAP_DATA; + let pos = this.pos; + let len = this.len; + let plen = 16 - (len % 16); + let rlen = len; + if (this.hasOwnProperty('padding')) { + if (this.padding) { + for (let p = 0; p < plen; ++p) { + heap[pos + len + p] = plen; + } + len += plen; + rlen = len; + } + else if (len % 16) { + throw new IllegalArgumentError('data length must be a multiple of the block size'); + } + } + else { + len += plen; + } + const result = new Uint8Array(rlen); + if (len) + asm.cipher(amode, hpos + pos, len); + if (rlen) + result.set(heap.subarray(pos, pos + rlen)); + this.pos = 0; + this.len = 0; + this.release_asm(); + return result; } - assert(base === (base | 0) && base >= 2 && base <= 36); - - number = number.toString().replace(/\s+/g, ''); - var start = 0; - if (number[0] === '-') { - start++; + AES_Decrypt_process(data) { + if (!is_bytes(data)) + throw new TypeError("data isn't of expected type"); + let { heap, asm } = this.acquire_asm(); + let amode = AES_asm.DEC[this.mode]; + let hpos = AES_asm.HEAP_DATA; + let pos = this.pos; + let len = this.len; + let dpos = 0; + let dlen = data.length || 0; + let rpos = 0; + let rlen = (len + dlen) & -16; + let plen = 0; + let wlen = 0; + if (this.padding) { + plen = len + dlen - rlen || 16; + rlen -= plen; + } + const result = new Uint8Array(rlen); + while (dlen > 0) { + wlen = _heap_write(heap, pos + len, data, dpos, dlen); + len += wlen; + dpos += wlen; + dlen -= wlen; + wlen = asm.cipher(amode, hpos + pos, len - (!dlen ? plen : 0)); + if (wlen) + result.set(heap.subarray(pos, pos + wlen), rpos); + rpos += wlen; + if (wlen < len) { + pos += wlen; + len -= wlen; + } + else { + pos = 0; + len = 0; + } + } + this.pos = pos; + this.len = len; + return result; } - - if (base === 16) { - this._parseHex(number, start); - } else { - this._parseBase(number, base, start); + AES_Decrypt_finish() { + let { heap, asm } = this.acquire_asm(); + let amode = AES_asm.DEC[this.mode]; + let hpos = AES_asm.HEAP_DATA; + let pos = this.pos; + let len = this.len; + let rlen = len; + if (len > 0) { + if (len % 16) { + if (this.hasOwnProperty('padding')) { + throw new IllegalArgumentError('data length must be a multiple of the block size'); + } + else { + len += 16 - (len % 16); + } + } + asm.cipher(amode, hpos + pos, len); + if (this.hasOwnProperty('padding') && this.padding) { + let pad = heap[pos + rlen - 1]; + if (pad < 1 || pad > 16 || pad > rlen) + throw new SecurityError('bad padding'); + let pcheck = 0; + for (let i = pad; i > 1; i--) + pcheck |= pad ^ heap[pos + rlen - i]; + if (pcheck) + throw new SecurityError('bad padding'); + rlen -= pad; + } + } + const result = new Uint8Array(rlen); + if (rlen > 0) { + result.set(heap.subarray(pos, pos + rlen)); + } + this.pos = 0; + this.len = 0; + this.release_asm(); + return result; } +} - if (number[0] === '-') { - this.negative = 1; +class AES_ECB { + static encrypt(data, key, padding = false) { + return new AES_ECB(key, padding).encrypt(data); } - - this.strip(); - - if (endian !== 'le') return; - - this._initArray(this.toArray(), base, endian); - }; - - BN.prototype._initNumber = function _initNumber (number, base, endian) { - if (number < 0) { - this.negative = 1; - number = -number; + static decrypt(data, key, padding = false) { + return new AES_ECB(key, padding).decrypt(data); } - if (number < 0x4000000) { - this.words = [ number & 0x3ffffff ]; - this.length = 1; - } else if (number < 0x10000000000000) { - this.words = [ - number & 0x3ffffff, - (number / 0x4000000) & 0x3ffffff - ]; - this.length = 2; - } else { - assert(number < 0x20000000000000); // 2 ^ 53 (unsafe) - this.words = [ - number & 0x3ffffff, - (number / 0x4000000) & 0x3ffffff, - 1 - ]; - this.length = 3; + constructor(key, padding = false, aes) { + this.aes = aes ? aes : new AES(key, undefined, padding, 'ECB'); } - - if (endian !== 'le') return; - - // Reverse the bytes - this._initArray(this.toArray(), base, endian); - }; - - BN.prototype._initArray = function _initArray (number, base, endian) { - // Perhaps a Uint8Array - assert(typeof number.length === 'number'); - if (number.length <= 0) { - this.words = [ 0 ]; - this.length = 1; - return this; + encrypt(data) { + const r1 = this.aes.AES_Encrypt_process(data); + const r2 = this.aes.AES_Encrypt_finish(); + return joinBytes(r1, r2); } - - this.length = Math.ceil(number.length / 3); - this.words = new Array(this.length); - for (var i = 0; i < this.length; i++) { - this.words[i] = 0; + decrypt(data) { + const r1 = this.aes.AES_Decrypt_process(data); + const r2 = this.aes.AES_Decrypt_finish(); + return joinBytes(r1, r2); } +} - var j, w; - var off = 0; - if (endian === 'be') { - for (i = number.length - 1, j = 0; i >= 0; i -= 3) { - w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16); - this.words[j] |= (w << off) & 0x3ffffff; - this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; - off += 24; - if (off >= 26) { - off -= 26; - j++; - } - } - } else if (endian === 'le') { - for (i = 0, j = 0; i < number.length; i += 3) { - w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16); - this.words[j] |= (w << off) & 0x3ffffff; - this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; - off += 24; - if (off >= 26) { - off -= 26; - j++; - } - } - } - return this.strip(); - }; +/** + * Javascript AES implementation. + * This is used as fallback if the native Crypto APIs are not available. + */ +function aes(length) { + const C = function(key) { + const aesECB = new AES_ECB(key); - function parseHex (str, start, end) { - var r = 0; - var len = Math.min(str.length, end); - for (var i = start; i < len; i++) { - var c = str.charCodeAt(i) - 48; + this.encrypt = function(block) { + return aesECB.encrypt(block); + }; - r <<= 4; + this.decrypt = function(block) { + return aesECB.decrypt(block); + }; + }; - // 'a' - 'f' - if (c >= 49 && c <= 54) { - r |= c - 49 + 0xa; + C.blockSize = C.prototype.blockSize = 16; + C.keySize = C.prototype.keySize = length / 8; - // 'A' - 'F' - } else if (c >= 17 && c <= 22) { - r |= c - 17 + 0xa; + return C; +} - // '0' - '9' - } else { - r |= c & 0xf; - } - } - return r; - } - - BN.prototype._parseHex = function _parseHex (number, start) { - // Create possibly bigger array to ensure that it fits the number - this.length = Math.ceil((number.length - start) / 6); - this.words = new Array(this.length); - for (var i = 0; i < this.length; i++) { - this.words[i] = 0; - } - - var j, w; - // Scan 24-bit chunks and add them to the number - var off = 0; - for (i = number.length - 6, j = 0; i >= start; i -= 6) { - w = parseHex(number, i, i + 6); - this.words[j] |= (w << off) & 0x3ffffff; - // NOTE: `0x3fffff` is intentional here, 26bits max shift + 24bit hex limb - this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; - off += 24; - if (off >= 26) { - off -= 26; - j++; - } - } - if (i + 6 !== start) { - w = parseHex(number, start, i + 6); - this.words[j] |= (w << off) & 0x3ffffff; - this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; - } - this.strip(); - }; +//Paul Tero, July 2001 +//http://www.tero.co.uk/des/ +// +//Optimised for performance with large blocks by Michael Hayworth, November 2001 +//http://www.netdealing.com +// +// Modified by Recurity Labs GmbH - function parseBase (str, start, end, mul) { - var r = 0; - var len = Math.min(str.length, end); - for (var i = start; i < len; i++) { - var c = str.charCodeAt(i) - 48; +//THIS SOFTWARE IS PROVIDED "AS IS" AND +//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +//IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +//ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +//FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +//DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +//OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +//HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +//OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +//SUCH DAMAGE. - r *= mul; +//des +//this takes the key, the message, and whether to encrypt or decrypt - // 'a' - if (c >= 49) { - r += c - 49 + 0xa; +function des(keys, message, encrypt, mode, iv, padding) { + //declaring this locally speeds things up a bit + const spfunction1 = [ + 0x1010400, 0, 0x10000, 0x1010404, 0x1010004, 0x10404, 0x4, 0x10000, 0x400, 0x1010400, + 0x1010404, 0x400, 0x1000404, 0x1010004, 0x1000000, 0x4, 0x404, 0x1000400, 0x1000400, 0x10400, 0x10400, 0x1010000, + 0x1010000, 0x1000404, 0x10004, 0x1000004, 0x1000004, 0x10004, 0, 0x404, 0x10404, 0x1000000, 0x10000, 0x1010404, 0x4, + 0x1010000, 0x1010400, 0x1000000, 0x1000000, 0x400, 0x1010004, 0x10000, 0x10400, 0x1000004, 0x400, 0x4, 0x1000404, + 0x10404, 0x1010404, 0x10004, 0x1010000, 0x1000404, 0x1000004, 0x404, 0x10404, 0x1010400, 0x404, 0x1000400, + 0x1000400, 0, 0x10004, 0x10400, 0, 0x1010004 + ]; + const spfunction2 = [ + -0x7fef7fe0, -0x7fff8000, 0x8000, 0x108020, 0x100000, 0x20, -0x7fefffe0, -0x7fff7fe0, + -0x7fffffe0, -0x7fef7fe0, -0x7fef8000, -0x80000000, -0x7fff8000, 0x100000, 0x20, -0x7fefffe0, 0x108000, 0x100020, + -0x7fff7fe0, 0, -0x80000000, 0x8000, 0x108020, -0x7ff00000, 0x100020, -0x7fffffe0, 0, 0x108000, 0x8020, -0x7fef8000, + -0x7ff00000, 0x8020, 0, 0x108020, -0x7fefffe0, 0x100000, -0x7fff7fe0, -0x7ff00000, -0x7fef8000, 0x8000, -0x7ff00000, + -0x7fff8000, 0x20, -0x7fef7fe0, 0x108020, 0x20, 0x8000, -0x80000000, 0x8020, -0x7fef8000, 0x100000, -0x7fffffe0, + 0x100020, -0x7fff7fe0, -0x7fffffe0, 0x100020, 0x108000, 0, -0x7fff8000, 0x8020, -0x80000000, -0x7fefffe0, + -0x7fef7fe0, 0x108000 + ]; + const spfunction3 = [ + 0x208, 0x8020200, 0, 0x8020008, 0x8000200, 0, 0x20208, 0x8000200, 0x20008, 0x8000008, + 0x8000008, 0x20000, 0x8020208, 0x20008, 0x8020000, 0x208, 0x8000000, 0x8, 0x8020200, 0x200, 0x20200, 0x8020000, + 0x8020008, 0x20208, 0x8000208, 0x20200, 0x20000, 0x8000208, 0x8, 0x8020208, 0x200, 0x8000000, 0x8020200, 0x8000000, + 0x20008, 0x208, 0x20000, 0x8020200, 0x8000200, 0, 0x200, 0x20008, 0x8020208, 0x8000200, 0x8000008, 0x200, 0, + 0x8020008, 0x8000208, 0x20000, 0x8000000, 0x8020208, 0x8, 0x20208, 0x20200, 0x8000008, 0x8020000, 0x8000208, 0x208, + 0x8020000, 0x20208, 0x8, 0x8020008, 0x20200 + ]; + const spfunction4 = [ + 0x802001, 0x2081, 0x2081, 0x80, 0x802080, 0x800081, 0x800001, 0x2001, 0, 0x802000, + 0x802000, 0x802081, 0x81, 0, 0x800080, 0x800001, 0x1, 0x2000, 0x800000, 0x802001, 0x80, 0x800000, 0x2001, 0x2080, + 0x800081, 0x1, 0x2080, 0x800080, 0x2000, 0x802080, 0x802081, 0x81, 0x800080, 0x800001, 0x802000, 0x802081, 0x81, 0, + 0, 0x802000, 0x2080, 0x800080, 0x800081, 0x1, 0x802001, 0x2081, 0x2081, 0x80, 0x802081, 0x81, 0x1, 0x2000, 0x800001, + 0x2001, 0x802080, 0x800081, 0x2001, 0x2080, 0x800000, 0x802001, 0x80, 0x800000, 0x2000, 0x802080 + ]; + const spfunction5 = [ + 0x100, 0x2080100, 0x2080000, 0x42000100, 0x80000, 0x100, 0x40000000, 0x2080000, + 0x40080100, 0x80000, 0x2000100, 0x40080100, 0x42000100, 0x42080000, 0x80100, 0x40000000, 0x2000000, 0x40080000, + 0x40080000, 0, 0x40000100, 0x42080100, 0x42080100, 0x2000100, 0x42080000, 0x40000100, 0, 0x42000000, 0x2080100, + 0x2000000, 0x42000000, 0x80100, 0x80000, 0x42000100, 0x100, 0x2000000, 0x40000000, 0x2080000, 0x42000100, + 0x40080100, 0x2000100, 0x40000000, 0x42080000, 0x2080100, 0x40080100, 0x100, 0x2000000, 0x42080000, 0x42080100, + 0x80100, 0x42000000, 0x42080100, 0x2080000, 0, 0x40080000, 0x42000000, 0x80100, 0x2000100, 0x40000100, 0x80000, 0, + 0x40080000, 0x2080100, 0x40000100 + ]; + const spfunction6 = [ + 0x20000010, 0x20400000, 0x4000, 0x20404010, 0x20400000, 0x10, 0x20404010, 0x400000, + 0x20004000, 0x404010, 0x400000, 0x20000010, 0x400010, 0x20004000, 0x20000000, 0x4010, 0, 0x400010, 0x20004010, + 0x4000, 0x404000, 0x20004010, 0x10, 0x20400010, 0x20400010, 0, 0x404010, 0x20404000, 0x4010, 0x404000, 0x20404000, + 0x20000000, 0x20004000, 0x10, 0x20400010, 0x404000, 0x20404010, 0x400000, 0x4010, 0x20000010, 0x400000, 0x20004000, + 0x20000000, 0x4010, 0x20000010, 0x20404010, 0x404000, 0x20400000, 0x404010, 0x20404000, 0, 0x20400010, 0x10, 0x4000, + 0x20400000, 0x404010, 0x4000, 0x400010, 0x20004010, 0, 0x20404000, 0x20000000, 0x400010, 0x20004010 + ]; + const spfunction7 = [ + 0x200000, 0x4200002, 0x4000802, 0, 0x800, 0x4000802, 0x200802, 0x4200800, 0x4200802, + 0x200000, 0, 0x4000002, 0x2, 0x4000000, 0x4200002, 0x802, 0x4000800, 0x200802, 0x200002, 0x4000800, 0x4000002, + 0x4200000, 0x4200800, 0x200002, 0x4200000, 0x800, 0x802, 0x4200802, 0x200800, 0x2, 0x4000000, 0x200800, 0x4000000, + 0x200800, 0x200000, 0x4000802, 0x4000802, 0x4200002, 0x4200002, 0x2, 0x200002, 0x4000000, 0x4000800, 0x200000, + 0x4200800, 0x802, 0x200802, 0x4200800, 0x802, 0x4000002, 0x4200802, 0x4200000, 0x200800, 0, 0x2, 0x4200802, 0, + 0x200802, 0x4200000, 0x800, 0x4000002, 0x4000800, 0x800, 0x200002 + ]; + const spfunction8 = [ + 0x10001040, 0x1000, 0x40000, 0x10041040, 0x10000000, 0x10001040, 0x40, 0x10000000, + 0x40040, 0x10040000, 0x10041040, 0x41000, 0x10041000, 0x41040, 0x1000, 0x40, 0x10040000, 0x10000040, 0x10001000, + 0x1040, 0x41000, 0x40040, 0x10040040, 0x10041000, 0x1040, 0, 0, 0x10040040, 0x10000040, 0x10001000, 0x41040, + 0x40000, 0x41040, 0x40000, 0x10041000, 0x1000, 0x40, 0x10040040, 0x1000, 0x41040, 0x10001000, 0x40, 0x10000040, + 0x10040000, 0x10040040, 0x10000000, 0x40000, 0x10001040, 0, 0x10041040, 0x40040, 0x10000040, 0x10040000, 0x10001000, + 0x10001040, 0, 0x10041040, 0x41000, 0x41000, 0x1040, 0x1040, 0x40040, 0x10000000, 0x10041000 + ]; - // 'A' - } else if (c >= 17) { - r += c - 17 + 0xa; + //create the 16 or 48 subkeys we will need + let m = 0; + let i; + let j; + let temp; + let right1; + let right2; + let left; + let right; + let looping; + let cbcleft; + let cbcleft2; + let cbcright; + let cbcright2; + let endloop; + let loopinc; + let len = message.length; - // '0' - '9' - } else { - r += c; - } - } - return r; + //set up the loops for single and triple des + const iterations = keys.length === 32 ? 3 : 9; //single or triple des + if (iterations === 3) { + looping = encrypt ? [0, 32, 2] : [30, -2, -2]; + } else { + looping = encrypt ? [0, 32, 2, 62, 30, -2, 64, 96, 2] : [94, 62, -2, 32, 64, 2, 30, -2, -2]; } - BN.prototype._parseBase = function _parseBase (number, base, start) { - // Initialize as zero - this.words = [ 0 ]; - this.length = 1; + //pad the message depending on the padding parameter + //only add padding if encrypting - note that you need to use the same padding option for both encrypt and decrypt + if (encrypt) { + message = desAddPadding(message, padding); + len = message.length; + } - // Find length of limb in base - for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) { - limbLen++; - } - limbLen--; - limbPow = (limbPow / base) | 0; + //store the result here + let result = new Uint8Array(len); + let k = 0; - var total = number.length - start; - var mod = total % limbLen; - var end = Math.min(total, total - mod) + start; + if (mode === 1) { //CBC mode + cbcleft = (iv[m++] << 24) | (iv[m++] << 16) | (iv[m++] << 8) | iv[m++]; + cbcright = (iv[m++] << 24) | (iv[m++] << 16) | (iv[m++] << 8) | iv[m++]; + m = 0; + } - var word = 0; - for (var i = start; i < end; i += limbLen) { - word = parseBase(number, i, i + limbLen, base); + //loop through each 64 bit chunk of the message + while (m < len) { + left = (message[m++] << 24) | (message[m++] << 16) | (message[m++] << 8) | message[m++]; + right = (message[m++] << 24) | (message[m++] << 16) | (message[m++] << 8) | message[m++]; - this.imuln(limbPow); - if (this.words[0] + word < 0x4000000) { - this.words[0] += word; + //for Cipher Block Chaining mode, xor the message with the previous result + if (mode === 1) { + if (encrypt) { + left ^= cbcleft; + right ^= cbcright; } else { - this._iaddn(word); + cbcleft2 = cbcleft; + cbcright2 = cbcright; + cbcleft = left; + cbcright = right; } } - if (mod !== 0) { - var pow = 1; - word = parseBase(number, i, number.length, base); + //first each 64 but chunk of the message must be permuted according to IP + temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; + right ^= temp; + left ^= (temp << 4); + temp = ((left >>> 16) ^ right) & 0x0000ffff; + right ^= temp; + left ^= (temp << 16); + temp = ((right >>> 2) ^ left) & 0x33333333; + left ^= temp; + right ^= (temp << 2); + temp = ((right >>> 8) ^ left) & 0x00ff00ff; + left ^= temp; + right ^= (temp << 8); + temp = ((left >>> 1) ^ right) & 0x55555555; + right ^= temp; + left ^= (temp << 1); - for (i = 0; i < mod; i++) { - pow *= base; - } + left = ((left << 1) | (left >>> 31)); + right = ((right << 1) | (right >>> 31)); - this.imuln(pow); - if (this.words[0] + word < 0x4000000) { - this.words[0] += word; - } else { - this._iaddn(word); + //do this either 1 or 3 times for each chunk of the message + for (j = 0; j < iterations; j += 3) { + endloop = looping[j + 1]; + loopinc = looping[j + 2]; + //now go through and perform the encryption or decryption + for (i = looping[j]; i !== endloop; i += loopinc) { //for efficiency + right1 = right ^ keys[i]; + right2 = ((right >>> 4) | (right << 28)) ^ keys[i + 1]; + //the result is attained by passing these bytes through the S selection functions + temp = left; + left = right; + right = temp ^ (spfunction2[(right1 >>> 24) & 0x3f] | spfunction4[(right1 >>> 16) & 0x3f] | spfunction6[(right1 >>> + 8) & 0x3f] | spfunction8[right1 & 0x3f] | spfunction1[(right2 >>> 24) & 0x3f] | spfunction3[(right2 >>> 16) & + 0x3f] | spfunction5[(right2 >>> 8) & 0x3f] | spfunction7[right2 & 0x3f]); } - } - }; + temp = left; + left = right; + right = temp; //unreverse left and right + } //for either 1 or 3 iterations - BN.prototype.copy = function copy (dest) { - dest.words = new Array(this.length); - for (var i = 0; i < this.length; i++) { - dest.words[i] = this.words[i]; - } - dest.length = this.length; - dest.negative = this.negative; - dest.red = this.red; - }; + //move then each one bit to the right + left = ((left >>> 1) | (left << 31)); + right = ((right >>> 1) | (right << 31)); - BN.prototype.clone = function clone () { - var r = new BN(null); - this.copy(r); - return r; - }; + //now perform IP-1, which is IP in the opposite direction + temp = ((left >>> 1) ^ right) & 0x55555555; + right ^= temp; + left ^= (temp << 1); + temp = ((right >>> 8) ^ left) & 0x00ff00ff; + left ^= temp; + right ^= (temp << 8); + temp = ((right >>> 2) ^ left) & 0x33333333; + left ^= temp; + right ^= (temp << 2); + temp = ((left >>> 16) ^ right) & 0x0000ffff; + right ^= temp; + left ^= (temp << 16); + temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; + right ^= temp; + left ^= (temp << 4); - BN.prototype._expand = function _expand (size) { - while (this.length < size) { - this.words[this.length++] = 0; + //for Cipher Block Chaining mode, xor the message with the previous result + if (mode === 1) { + if (encrypt) { + cbcleft = left; + cbcright = right; + } else { + left ^= cbcleft2; + right ^= cbcright2; + } } - return this; - }; - // Remove leading `0` from `this` - BN.prototype.strip = function strip () { - while (this.length > 1 && this.words[this.length - 1] === 0) { - this.length--; - } - return this._normSign(); - }; + result[k++] = (left >>> 24); + result[k++] = ((left >>> 16) & 0xff); + result[k++] = ((left >>> 8) & 0xff); + result[k++] = (left & 0xff); + result[k++] = (right >>> 24); + result[k++] = ((right >>> 16) & 0xff); + result[k++] = ((right >>> 8) & 0xff); + result[k++] = (right & 0xff); + } //for every 8 characters, or 64 bits in the message - BN.prototype._normSign = function _normSign () { - // -0 = 0 - if (this.length === 1 && this.words[0] === 0) { - this.negative = 0; - } - return this; - }; + //only remove padding if decrypting - note that you need to use the same padding option for both encrypt and decrypt + if (!encrypt) { + result = desRemovePadding(result, padding); + } - BN.prototype.inspect = function inspect () { - return (this.red ? ''; - }; + return result; +} //end of des - /* - var zeros = []; - var groupSizes = []; - var groupBases = []; +//desCreateKeys +//this takes as input a 64 bit key (even though only 56 bits are used) +//as an array of 2 integers, and returns 16 48 bit keys - var s = ''; - var i = -1; - while (++i < BN.wordSize) { - zeros[i] = s; - s += '0'; - } - groupSizes[0] = 0; - groupSizes[1] = 0; - groupBases[0] = 0; - groupBases[1] = 0; - var base = 2 - 1; - while (++base < 36 + 1) { - var groupSize = 0; - var groupBase = 1; - while (groupBase < (1 << BN.wordSize) / base) { - groupBase *= base; - groupSize += 1; - } - groupSizes[base] = groupSize; - groupBases[base] = groupBase; - } - - */ - - var zeros = [ - '', - '0', - '00', - '000', - '0000', - '00000', - '000000', - '0000000', - '00000000', - '000000000', - '0000000000', - '00000000000', - '000000000000', - '0000000000000', - '00000000000000', - '000000000000000', - '0000000000000000', - '00000000000000000', - '000000000000000000', - '0000000000000000000', - '00000000000000000000', - '000000000000000000000', - '0000000000000000000000', - '00000000000000000000000', - '000000000000000000000000', - '0000000000000000000000000' +function desCreateKeys(key) { + //declaring this locally speeds things up a bit + const pc2bytes0 = [ + 0, 0x4, 0x20000000, 0x20000004, 0x10000, 0x10004, 0x20010000, 0x20010004, 0x200, 0x204, + 0x20000200, 0x20000204, 0x10200, 0x10204, 0x20010200, 0x20010204 ]; - - var groupSizes = [ - 0, 0, - 25, 16, 12, 11, 10, 9, 8, - 8, 7, 7, 7, 7, 6, 6, - 6, 6, 6, 6, 6, 5, 5, - 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5 + const pc2bytes1 = [ + 0, 0x1, 0x100000, 0x100001, 0x4000000, 0x4000001, 0x4100000, 0x4100001, 0x100, 0x101, 0x100100, + 0x100101, 0x4000100, 0x4000101, 0x4100100, 0x4100101 ]; - - var groupBases = [ - 0, 0, - 33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216, - 43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625, - 16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632, - 6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149, - 24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176 + const pc2bytes2 = [ + 0, 0x8, 0x800, 0x808, 0x1000000, 0x1000008, 0x1000800, 0x1000808, 0, 0x8, 0x800, 0x808, + 0x1000000, 0x1000008, 0x1000800, 0x1000808 + ]; + const pc2bytes3 = [ + 0, 0x200000, 0x8000000, 0x8200000, 0x2000, 0x202000, 0x8002000, 0x8202000, 0x20000, 0x220000, + 0x8020000, 0x8220000, 0x22000, 0x222000, 0x8022000, 0x8222000 + ]; + const pc2bytes4 = [ + 0, 0x40000, 0x10, 0x40010, 0, 0x40000, 0x10, 0x40010, 0x1000, 0x41000, 0x1010, 0x41010, 0x1000, + 0x41000, 0x1010, 0x41010 + ]; + const pc2bytes5 = [ + 0, 0x400, 0x20, 0x420, 0, 0x400, 0x20, 0x420, 0x2000000, 0x2000400, 0x2000020, 0x2000420, + 0x2000000, 0x2000400, 0x2000020, 0x2000420 + ]; + const pc2bytes6 = [ + 0, 0x10000000, 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002, 0, 0x10000000, + 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002 + ]; + const pc2bytes7 = [ + 0, 0x10000, 0x800, 0x10800, 0x20000000, 0x20010000, 0x20000800, 0x20010800, 0x20000, 0x30000, + 0x20800, 0x30800, 0x20020000, 0x20030000, 0x20020800, 0x20030800 + ]; + const pc2bytes8 = [ + 0, 0x40000, 0, 0x40000, 0x2, 0x40002, 0x2, 0x40002, 0x2000000, 0x2040000, 0x2000000, 0x2040000, + 0x2000002, 0x2040002, 0x2000002, 0x2040002 + ]; + const pc2bytes9 = [ + 0, 0x10000000, 0x8, 0x10000008, 0, 0x10000000, 0x8, 0x10000008, 0x400, 0x10000400, 0x408, + 0x10000408, 0x400, 0x10000400, 0x408, 0x10000408 + ]; + const pc2bytes10 = [ + 0, 0x20, 0, 0x20, 0x100000, 0x100020, 0x100000, 0x100020, 0x2000, 0x2020, 0x2000, 0x2020, + 0x102000, 0x102020, 0x102000, 0x102020 + ]; + const pc2bytes11 = [ + 0, 0x1000000, 0x200, 0x1000200, 0x200000, 0x1200000, 0x200200, 0x1200200, 0x4000000, 0x5000000, + 0x4000200, 0x5000200, 0x4200000, 0x5200000, 0x4200200, 0x5200200 ]; + const pc2bytes12 = [ + 0, 0x1000, 0x8000000, 0x8001000, 0x80000, 0x81000, 0x8080000, 0x8081000, 0x10, 0x1010, + 0x8000010, 0x8001010, 0x80010, 0x81010, 0x8080010, 0x8081010 + ]; + const pc2bytes13 = [0, 0x4, 0x100, 0x104, 0, 0x4, 0x100, 0x104, 0x1, 0x5, 0x101, 0x105, 0x1, 0x5, 0x101, 0x105]; - BN.prototype.toString = function toString (base, padding) { - base = base || 10; - padding = padding | 0 || 1; + //how many iterations (1 for des, 3 for triple des) + const iterations = key.length > 8 ? 3 : 1; //changed by Paul 16/6/2007 to use Triple DES for 9+ byte keys + //stores the return keys + const keys = new Array(32 * iterations); + //now define the left shifts which need to be done + const shifts = [0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0]; + //other variables + let lefttemp; + let righttemp; + let m = 0; + let n = 0; + let temp; - var out; - if (base === 16 || base === 'hex') { - out = ''; - var off = 0; - var carry = 0; - for (var i = 0; i < this.length; i++) { - var w = this.words[i]; - var word = (((w << off) | carry) & 0xffffff).toString(16); - carry = (w >>> (24 - off)) & 0xffffff; - if (carry !== 0 || i !== this.length - 1) { - out = zeros[6 - word.length] + word + out; - } else { - out = word + out; - } - off += 2; - if (off >= 26) { - off -= 26; - i--; - } - } - if (carry !== 0) { - out = carry.toString(16) + out; - } - while (out.length % padding !== 0) { - out = '0' + out; - } - if (this.negative !== 0) { - out = '-' + out; - } - return out; - } + for (let j = 0; j < iterations; j++) { //either 1 or 3 iterations + let left = (key[m++] << 24) | (key[m++] << 16) | (key[m++] << 8) | key[m++]; + let right = (key[m++] << 24) | (key[m++] << 16) | (key[m++] << 8) | key[m++]; - if (base === (base | 0) && base >= 2 && base <= 36) { - // var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base)); - var groupSize = groupSizes[base]; - // var groupBase = Math.pow(base, groupSize); - var groupBase = groupBases[base]; - out = ''; - var c = this.clone(); - c.negative = 0; - while (!c.isZero()) { - var r = c.modn(groupBase).toString(base); - c = c.idivn(groupBase); + temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; + right ^= temp; + left ^= (temp << 4); + temp = ((right >>> -16) ^ left) & 0x0000ffff; + left ^= temp; + right ^= (temp << -16); + temp = ((left >>> 2) ^ right) & 0x33333333; + right ^= temp; + left ^= (temp << 2); + temp = ((right >>> -16) ^ left) & 0x0000ffff; + left ^= temp; + right ^= (temp << -16); + temp = ((left >>> 1) ^ right) & 0x55555555; + right ^= temp; + left ^= (temp << 1); + temp = ((right >>> 8) ^ left) & 0x00ff00ff; + left ^= temp; + right ^= (temp << 8); + temp = ((left >>> 1) ^ right) & 0x55555555; + right ^= temp; + left ^= (temp << 1); - if (!c.isZero()) { - out = zeros[groupSize - r.length] + r + out; - } else { - out = r + out; - } - } - if (this.isZero()) { - out = '0' + out; - } - while (out.length % padding !== 0) { - out = '0' + out; - } - if (this.negative !== 0) { - out = '-' + out; - } - return out; - } + //the right side needs to be shifted and to get the last four bits of the left side + temp = (left << 8) | ((right >>> 20) & 0x000000f0); + //left needs to be put upside down + left = (right << 24) | ((right << 8) & 0xff0000) | ((right >>> 8) & 0xff00) | ((right >>> 24) & 0xf0); + right = temp; - assert(false, 'Base should be between 2 and 36'); - }; + //now go through and perform these shifts on the left and right keys + for (let i = 0; i < shifts.length; i++) { + //shift the keys either one or two bits to the left + if (shifts[i]) { + left = (left << 2) | (left >>> 26); + right = (right << 2) | (right >>> 26); + } else { + left = (left << 1) | (left >>> 27); + right = (right << 1) | (right >>> 27); + } + left &= -0xf; + right &= -0xf; - BN.prototype.toNumber = function toNumber () { - var ret = this.words[0]; - if (this.length === 2) { - ret += this.words[1] * 0x4000000; - } else if (this.length === 3 && this.words[2] === 0x01) { - // NOTE: at this stage it is known that the top bit is set - ret += 0x10000000000000 + (this.words[1] * 0x4000000); - } else if (this.length > 2) { - assert(false, 'Number can only safely store up to 53 bits'); + //now apply PC-2, in such a way that E is easier when encrypting or decrypting + //this conversion will look like PC-2 except only the last 6 bits of each byte are used + //rather than 48 consecutive bits and the order of lines will be according to + //how the S selection functions will be applied: S2, S4, S6, S8, S1, S3, S5, S7 + lefttemp = pc2bytes0[left >>> 28] | pc2bytes1[(left >>> 24) & 0xf] | pc2bytes2[(left >>> 20) & 0xf] | pc2bytes3[( + left >>> 16) & 0xf] | pc2bytes4[(left >>> 12) & 0xf] | pc2bytes5[(left >>> 8) & 0xf] | pc2bytes6[(left >>> 4) & + 0xf]; + righttemp = pc2bytes7[right >>> 28] | pc2bytes8[(right >>> 24) & 0xf] | pc2bytes9[(right >>> 20) & 0xf] | + pc2bytes10[(right >>> 16) & 0xf] | pc2bytes11[(right >>> 12) & 0xf] | pc2bytes12[(right >>> 8) & 0xf] | + pc2bytes13[(right >>> 4) & 0xf]; + temp = ((righttemp >>> 16) ^ lefttemp) & 0x0000ffff; + keys[n++] = lefttemp ^ temp; + keys[n++] = righttemp ^ (temp << 16); } - return (this.negative !== 0) ? -ret : ret; - }; + } //for each iterations + //return the keys we've created + return keys; +} //end of desCreateKeys - BN.prototype.toJSON = function toJSON () { - return this.toString(16); - }; - BN.prototype.toBuffer = function toBuffer (endian, length) { - assert(typeof Buffer !== 'undefined'); - return this.toArrayLike(Buffer, endian, length); - }; +function desAddPadding(message, padding) { + const padLength = 8 - (message.length % 8); - BN.prototype.toArray = function toArray (endian, length) { - return this.toArrayLike(Array, endian, length); - }; + let pad; + if (padding === 2 && (padLength < 8)) { //pad the message with spaces + pad = ' '.charCodeAt(0); + } else if (padding === 1) { //PKCS7 padding + pad = padLength; + } else if (!padding && (padLength < 8)) { //pad the message out with null bytes + pad = 0; + } else if (padLength === 8) { + return message; + } else { + throw new Error('des: invalid padding'); + } - BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) { - var byteLength = this.byteLength(); - var reqLength = length || Math.max(1, byteLength); - assert(byteLength <= reqLength, 'byte array longer than desired length'); - assert(reqLength > 0, 'Requested array length <= 0'); + const paddedMessage = new Uint8Array(message.length + padLength); + for (let i = 0; i < message.length; i++) { + paddedMessage[i] = message[i]; + } + for (let j = 0; j < padLength; j++) { + paddedMessage[message.length + j] = pad; + } - this.strip(); - var littleEndian = endian === 'le'; - var res = new ArrayType(reqLength); + return paddedMessage; +} - var b, i; - var q = this.clone(); - if (!littleEndian) { - // Assume big-endian - for (i = 0; i < reqLength - byteLength; i++) { - res[i] = 0; - } +function desRemovePadding(message, padding) { + let padLength = null; + let pad; + if (padding === 2) { // space padded + pad = ' '.charCodeAt(0); + } else if (padding === 1) { // PKCS7 + padLength = message[message.length - 1]; + } else if (!padding) { // null padding + pad = 0; + } else { + throw new Error('des: invalid padding'); + } - for (i = 0; !q.isZero(); i++) { - b = q.andln(0xff); - q.iushrn(8); + if (!padLength) { + padLength = 1; + while (message[message.length - padLength] === pad) { + padLength++; + } + padLength--; + } - res[reqLength - i - 1] = b; - } - } else { - for (i = 0; !q.isZero(); i++) { - b = q.andln(0xff); - q.iushrn(8); + return message.subarray(0, message.length - padLength); +} - res[i] = b; - } +// added by Recurity Labs - for (; i < reqLength; i++) { - res[i] = 0; - } - } +function TripleDES(key) { + this.key = []; - return res; + for (let i = 0; i < 3; i++) { + this.key.push(new Uint8Array(key.subarray(i * 8, (i * 8) + 8))); + } + + this.encrypt = function(block) { + return des( + desCreateKeys(this.key[2]), + des( + desCreateKeys(this.key[1]), + des( + desCreateKeys(this.key[0]), + block, true, 0, null, null + ), + false, 0, null, null + ), true, 0, null, null + ); }; +} - if (Math.clz32) { - BN.prototype._countBits = function _countBits (w) { - return 32 - Math.clz32(w); - }; - } else { - BN.prototype._countBits = function _countBits (w) { - var t = w; - var r = 0; - if (t >= 0x1000) { - r += 13; - t >>>= 13; - } - if (t >= 0x40) { - r += 7; - t >>>= 7; - } - if (t >= 0x8) { - r += 4; - t >>>= 4; - } - if (t >= 0x02) { - r += 2; - t >>>= 2; - } - return r + t; - }; - } +TripleDES.keySize = TripleDES.prototype.keySize = 24; +TripleDES.blockSize = TripleDES.prototype.blockSize = 8; - BN.prototype._zeroBits = function _zeroBits (w) { - // Short-cut - if (w === 0) return 26; +// This is "original" DES - var t = w; - var r = 0; - if ((t & 0x1fff) === 0) { - r += 13; - t >>>= 13; - } - if ((t & 0x7f) === 0) { - r += 7; - t >>>= 7; - } - if ((t & 0xf) === 0) { - r += 4; - t >>>= 4; - } - if ((t & 0x3) === 0) { - r += 2; - t >>>= 2; - } - if ((t & 0x1) === 0) { - r++; - } - return r; - }; +function DES(key) { + this.key = key; - // Return number of used bits in a BN - BN.prototype.bitLength = function bitLength () { - var w = this.words[this.length - 1]; - var hi = this._countBits(w); - return (this.length - 1) * 26 + hi; + this.encrypt = function(block, padding) { + const keys = desCreateKeys(this.key); + return des(keys, block, true, 0, null, padding); }; - function toBitArray (num) { - var w = new Array(num.bitLength()); + this.decrypt = function(block, padding) { + const keys = desCreateKeys(this.key); + return des(keys, block, false, 0, null, padding); + }; +} - for (var bit = 0; bit < w.length; bit++) { - var off = (bit / 26) | 0; - var wbit = bit % 26; +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. - w[bit] = (num.words[off] & (1 << wbit)) >>> wbit; - } +// Copyright 2010 pjacobs@xeekr.com . All rights reserved. - return w; - } +// Modified by Recurity Labs GmbH - // Number of trailing zero bits - BN.prototype.zeroBits = function zeroBits () { - if (this.isZero()) return 0; +// fixed/modified by Herbert Hanewinkel, www.haneWIN.de +// check www.haneWIN.de for the latest version - var r = 0; - for (var i = 0; i < this.length; i++) { - var b = this._zeroBits(this.words[i]); - r += b; - if (b !== 26) break; - } - return r; - }; +// cast5.js is a Javascript implementation of CAST-128, as defined in RFC 2144. +// CAST-128 is a common OpenPGP cipher. - BN.prototype.byteLength = function byteLength () { - return Math.ceil(this.bitLength() / 8); - }; - BN.prototype.toTwos = function toTwos (width) { - if (this.negative !== 0) { - return this.abs().inotn(width).iaddn(1); - } - return this.clone(); - }; +// CAST5 constructor - BN.prototype.fromTwos = function fromTwos (width) { - if (this.testn(width - 1)) { - return this.notn(width).iaddn(1).ineg(); - } - return this.clone(); - }; +function OpenPGPSymEncCAST5() { + this.BlockSize = 8; + this.KeySize = 16; - BN.prototype.isNeg = function isNeg () { - return this.negative !== 0; - }; + this.setKey = function(key) { + this.masking = new Array(16); + this.rotate = new Array(16); - // Return negative clone of `this` - BN.prototype.neg = function neg () { - return this.clone().ineg(); - }; + this.reset(); - BN.prototype.ineg = function ineg () { - if (!this.isZero()) { - this.negative ^= 1; + if (key.length === this.KeySize) { + this.keySchedule(key); + } else { + throw new Error('CAST-128: keys must be 16 bytes'); } - - return this; + return true; }; - // Or `num` with `this` in-place - BN.prototype.iuor = function iuor (num) { - while (this.length < num.length) { - this.words[this.length++] = 0; - } - - for (var i = 0; i < num.length; i++) { - this.words[i] = this.words[i] | num.words[i]; + this.reset = function() { + for (let i = 0; i < 16; i++) { + this.masking[i] = 0; + this.rotate[i] = 0; } - - return this.strip(); }; - BN.prototype.ior = function ior (num) { - assert((this.negative | num.negative) === 0); - return this.iuor(num); + this.getBlockSize = function() { + return this.BlockSize; }; - // Or `num` with `this` - BN.prototype.or = function or (num) { - if (this.length > num.length) return this.clone().ior(num); - return num.clone().ior(this); - }; + this.encrypt = function(src) { + const dst = new Array(src.length); - BN.prototype.uor = function uor (num) { - if (this.length > num.length) return this.clone().iuor(num); - return num.clone().iuor(this); - }; + for (let i = 0; i < src.length; i += 8) { + let l = (src[i] << 24) | (src[i + 1] << 16) | (src[i + 2] << 8) | src[i + 3]; + let r = (src[i + 4] << 24) | (src[i + 5] << 16) | (src[i + 6] << 8) | src[i + 7]; + let t; - // And `num` with `this` in-place - BN.prototype.iuand = function iuand (num) { - // b = min-length(num, this) - var b; - if (this.length > num.length) { - b = num; - } else { - b = this; - } + t = r; + r = l ^ f1(r, this.masking[0], this.rotate[0]); + l = t; + t = r; + r = l ^ f2(r, this.masking[1], this.rotate[1]); + l = t; + t = r; + r = l ^ f3(r, this.masking[2], this.rotate[2]); + l = t; + t = r; + r = l ^ f1(r, this.masking[3], this.rotate[3]); + l = t; - for (var i = 0; i < b.length; i++) { - this.words[i] = this.words[i] & num.words[i]; - } + t = r; + r = l ^ f2(r, this.masking[4], this.rotate[4]); + l = t; + t = r; + r = l ^ f3(r, this.masking[5], this.rotate[5]); + l = t; + t = r; + r = l ^ f1(r, this.masking[6], this.rotate[6]); + l = t; + t = r; + r = l ^ f2(r, this.masking[7], this.rotate[7]); + l = t; - this.length = b.length; + t = r; + r = l ^ f3(r, this.masking[8], this.rotate[8]); + l = t; + t = r; + r = l ^ f1(r, this.masking[9], this.rotate[9]); + l = t; + t = r; + r = l ^ f2(r, this.masking[10], this.rotate[10]); + l = t; + t = r; + r = l ^ f3(r, this.masking[11], this.rotate[11]); + l = t; - return this.strip(); - }; + t = r; + r = l ^ f1(r, this.masking[12], this.rotate[12]); + l = t; + t = r; + r = l ^ f2(r, this.masking[13], this.rotate[13]); + l = t; + t = r; + r = l ^ f3(r, this.masking[14], this.rotate[14]); + l = t; + t = r; + r = l ^ f1(r, this.masking[15], this.rotate[15]); + l = t; - BN.prototype.iand = function iand (num) { - assert((this.negative | num.negative) === 0); - return this.iuand(num); - }; + dst[i] = (r >>> 24) & 255; + dst[i + 1] = (r >>> 16) & 255; + dst[i + 2] = (r >>> 8) & 255; + dst[i + 3] = r & 255; + dst[i + 4] = (l >>> 24) & 255; + dst[i + 5] = (l >>> 16) & 255; + dst[i + 6] = (l >>> 8) & 255; + dst[i + 7] = l & 255; + } - // And `num` with `this` - BN.prototype.and = function and (num) { - if (this.length > num.length) return this.clone().iand(num); - return num.clone().iand(this); + return dst; }; - BN.prototype.uand = function uand (num) { - if (this.length > num.length) return this.clone().iuand(num); - return num.clone().iuand(this); - }; + this.decrypt = function(src) { + const dst = new Array(src.length); - // Xor `num` with `this` in-place - BN.prototype.iuxor = function iuxor (num) { - // a.length > b.length - var a; - var b; - if (this.length > num.length) { - a = this; - b = num; - } else { - a = num; - b = this; - } + for (let i = 0; i < src.length; i += 8) { + let l = (src[i] << 24) | (src[i + 1] << 16) | (src[i + 2] << 8) | src[i + 3]; + let r = (src[i + 4] << 24) | (src[i + 5] << 16) | (src[i + 6] << 8) | src[i + 7]; + let t; - for (var i = 0; i < b.length; i++) { - this.words[i] = a.words[i] ^ b.words[i]; - } + t = r; + r = l ^ f1(r, this.masking[15], this.rotate[15]); + l = t; + t = r; + r = l ^ f3(r, this.masking[14], this.rotate[14]); + l = t; + t = r; + r = l ^ f2(r, this.masking[13], this.rotate[13]); + l = t; + t = r; + r = l ^ f1(r, this.masking[12], this.rotate[12]); + l = t; - if (this !== a) { - for (; i < a.length; i++) { - this.words[i] = a.words[i]; - } - } + t = r; + r = l ^ f3(r, this.masking[11], this.rotate[11]); + l = t; + t = r; + r = l ^ f2(r, this.masking[10], this.rotate[10]); + l = t; + t = r; + r = l ^ f1(r, this.masking[9], this.rotate[9]); + l = t; + t = r; + r = l ^ f3(r, this.masking[8], this.rotate[8]); + l = t; - this.length = a.length; + t = r; + r = l ^ f2(r, this.masking[7], this.rotate[7]); + l = t; + t = r; + r = l ^ f1(r, this.masking[6], this.rotate[6]); + l = t; + t = r; + r = l ^ f3(r, this.masking[5], this.rotate[5]); + l = t; + t = r; + r = l ^ f2(r, this.masking[4], this.rotate[4]); + l = t; - return this.strip(); - }; + t = r; + r = l ^ f1(r, this.masking[3], this.rotate[3]); + l = t; + t = r; + r = l ^ f3(r, this.masking[2], this.rotate[2]); + l = t; + t = r; + r = l ^ f2(r, this.masking[1], this.rotate[1]); + l = t; + t = r; + r = l ^ f1(r, this.masking[0], this.rotate[0]); + l = t; - BN.prototype.ixor = function ixor (num) { - assert((this.negative | num.negative) === 0); - return this.iuxor(num); - }; + dst[i] = (r >>> 24) & 255; + dst[i + 1] = (r >>> 16) & 255; + dst[i + 2] = (r >>> 8) & 255; + dst[i + 3] = r & 255; + dst[i + 4] = (l >>> 24) & 255; + dst[i + 5] = (l >> 16) & 255; + dst[i + 6] = (l >> 8) & 255; + dst[i + 7] = l & 255; + } - // Xor `num` with `this` - BN.prototype.xor = function xor (num) { - if (this.length > num.length) return this.clone().ixor(num); - return num.clone().ixor(this); + return dst; }; + const scheduleA = new Array(4); - BN.prototype.uxor = function uxor (num) { - if (this.length > num.length) return this.clone().iuxor(num); - return num.clone().iuxor(this); - }; + scheduleA[0] = new Array(4); + scheduleA[0][0] = [4, 0, 0xd, 0xf, 0xc, 0xe, 0x8]; + scheduleA[0][1] = [5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa]; + scheduleA[0][2] = [6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9]; + scheduleA[0][3] = [7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb]; - // Not ``this`` with ``width`` bitwidth - BN.prototype.inotn = function inotn (width) { - assert(typeof width === 'number' && width >= 0); + scheduleA[1] = new Array(4); + scheduleA[1][0] = [0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0]; + scheduleA[1][1] = [1, 4, 0, 2, 1, 3, 16 + 2]; + scheduleA[1][2] = [2, 5, 7, 6, 5, 4, 16 + 1]; + scheduleA[1][3] = [3, 7, 0xa, 9, 0xb, 8, 16 + 3]; - var bytesNeeded = Math.ceil(width / 26) | 0; - var bitsLeft = width % 26; + scheduleA[2] = new Array(4); + scheduleA[2][0] = [4, 0, 0xd, 0xf, 0xc, 0xe, 8]; + scheduleA[2][1] = [5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa]; + scheduleA[2][2] = [6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9]; + scheduleA[2][3] = [7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb]; - // Extend the buffer with leading zeroes - this._expand(bytesNeeded); - if (bitsLeft > 0) { - bytesNeeded--; - } + scheduleA[3] = new Array(4); + scheduleA[3][0] = [0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0]; + scheduleA[3][1] = [1, 4, 0, 2, 1, 3, 16 + 2]; + scheduleA[3][2] = [2, 5, 7, 6, 5, 4, 16 + 1]; + scheduleA[3][3] = [3, 7, 0xa, 9, 0xb, 8, 16 + 3]; - // Handle complete words - for (var i = 0; i < bytesNeeded; i++) { - this.words[i] = ~this.words[i] & 0x3ffffff; - } + const scheduleB = new Array(4); - // Handle the residue - if (bitsLeft > 0) { - this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft)); - } + scheduleB[0] = new Array(4); + scheduleB[0][0] = [16 + 8, 16 + 9, 16 + 7, 16 + 6, 16 + 2]; + scheduleB[0][1] = [16 + 0xa, 16 + 0xb, 16 + 5, 16 + 4, 16 + 6]; + scheduleB[0][2] = [16 + 0xc, 16 + 0xd, 16 + 3, 16 + 2, 16 + 9]; + scheduleB[0][3] = [16 + 0xe, 16 + 0xf, 16 + 1, 16 + 0, 16 + 0xc]; - // And remove leading zeroes - return this.strip(); - }; + scheduleB[1] = new Array(4); + scheduleB[1][0] = [3, 2, 0xc, 0xd, 8]; + scheduleB[1][1] = [1, 0, 0xe, 0xf, 0xd]; + scheduleB[1][2] = [7, 6, 8, 9, 3]; + scheduleB[1][3] = [5, 4, 0xa, 0xb, 7]; - BN.prototype.notn = function notn (width) { - return this.clone().inotn(width); - }; - // Set `bit` of `this` - BN.prototype.setn = function setn (bit, val) { - assert(typeof bit === 'number' && bit >= 0); + scheduleB[2] = new Array(4); + scheduleB[2][0] = [16 + 3, 16 + 2, 16 + 0xc, 16 + 0xd, 16 + 9]; + scheduleB[2][1] = [16 + 1, 16 + 0, 16 + 0xe, 16 + 0xf, 16 + 0xc]; + scheduleB[2][2] = [16 + 7, 16 + 6, 16 + 8, 16 + 9, 16 + 2]; + scheduleB[2][3] = [16 + 5, 16 + 4, 16 + 0xa, 16 + 0xb, 16 + 6]; - var off = (bit / 26) | 0; - var wbit = bit % 26; - this._expand(off + 1); + scheduleB[3] = new Array(4); + scheduleB[3][0] = [8, 9, 7, 6, 3]; + scheduleB[3][1] = [0xa, 0xb, 5, 4, 7]; + scheduleB[3][2] = [0xc, 0xd, 3, 2, 8]; + scheduleB[3][3] = [0xe, 0xf, 1, 0, 0xd]; - if (val) { - this.words[off] = this.words[off] | (1 << wbit); - } else { - this.words[off] = this.words[off] & ~(1 << wbit); - } + // changed 'in' to 'inn' (in javascript 'in' is a reserved word) + this.keySchedule = function(inn) { + const t = new Array(8); + const k = new Array(32); - return this.strip(); - }; + let j; - // Add `num` to `this` in-place - BN.prototype.iadd = function iadd (num) { - var r; + for (let i = 0; i < 4; i++) { + j = i * 4; + t[i] = (inn[j] << 24) | (inn[j + 1] << 16) | (inn[j + 2] << 8) | inn[j + 3]; + } - // negative + positive - if (this.negative !== 0 && num.negative === 0) { - this.negative = 0; - r = this.isub(num); - this.negative ^= 1; - return this._normSign(); + const x = [6, 7, 4, 5]; + let ki = 0; + let w; - // positive + negative - } else if (this.negative === 0 && num.negative !== 0) { - num.negative = 0; - r = this.isub(num); - num.negative = 1; - return r._normSign(); - } + for (let half = 0; half < 2; half++) { + for (let round = 0; round < 4; round++) { + for (j = 0; j < 4; j++) { + const a = scheduleA[round][j]; + w = t[a[1]]; - // a.length > b.length - var a, b; - if (this.length > num.length) { - a = this; - b = num; - } else { - a = num; - b = this; - } + w ^= sBox[4][(t[a[2] >>> 2] >>> (24 - 8 * (a[2] & 3))) & 0xff]; + w ^= sBox[5][(t[a[3] >>> 2] >>> (24 - 8 * (a[3] & 3))) & 0xff]; + w ^= sBox[6][(t[a[4] >>> 2] >>> (24 - 8 * (a[4] & 3))) & 0xff]; + w ^= sBox[7][(t[a[5] >>> 2] >>> (24 - 8 * (a[5] & 3))) & 0xff]; + w ^= sBox[x[j]][(t[a[6] >>> 2] >>> (24 - 8 * (a[6] & 3))) & 0xff]; + t[a[0]] = w; + } - var carry = 0; - for (var i = 0; i < b.length; i++) { - r = (a.words[i] | 0) + (b.words[i] | 0) + carry; - this.words[i] = r & 0x3ffffff; - carry = r >>> 26; - } - for (; carry !== 0 && i < a.length; i++) { - r = (a.words[i] | 0) + carry; - this.words[i] = r & 0x3ffffff; - carry = r >>> 26; - } + for (j = 0; j < 4; j++) { + const b = scheduleB[round][j]; + w = sBox[4][(t[b[0] >>> 2] >>> (24 - 8 * (b[0] & 3))) & 0xff]; - this.length = a.length; - if (carry !== 0) { - this.words[this.length] = carry; - this.length++; - // Copy the rest of the words - } else if (a !== this) { - for (; i < a.length; i++) { - this.words[i] = a.words[i]; + w ^= sBox[5][(t[b[1] >>> 2] >>> (24 - 8 * (b[1] & 3))) & 0xff]; + w ^= sBox[6][(t[b[2] >>> 2] >>> (24 - 8 * (b[2] & 3))) & 0xff]; + w ^= sBox[7][(t[b[3] >>> 2] >>> (24 - 8 * (b[3] & 3))) & 0xff]; + w ^= sBox[4 + j][(t[b[4] >>> 2] >>> (24 - 8 * (b[4] & 3))) & 0xff]; + k[ki] = w; + ki++; + } } } - return this; + for (let i = 0; i < 16; i++) { + this.masking[i] = k[i]; + this.rotate[i] = k[16 + i] & 0x1f; + } }; - // Add `num` to `this` - BN.prototype.add = function add (num) { - var res; - if (num.negative !== 0 && this.negative === 0) { - num.negative = 0; - res = this.sub(num); - num.negative ^= 1; - return res; - } else if (num.negative === 0 && this.negative !== 0) { - this.negative = 0; - res = num.sub(this); - this.negative = 1; - return res; - } + // These are the three 'f' functions. See RFC 2144, section 2.2. - if (this.length > num.length) return this.clone().iadd(num); + function f1(d, m, r) { + const t = m + d; + const I = (t << r) | (t >>> (32 - r)); + return ((sBox[0][I >>> 24] ^ sBox[1][(I >>> 16) & 255]) - sBox[2][(I >>> 8) & 255]) + sBox[3][I & 255]; + } - return num.clone().iadd(this); - }; + function f2(d, m, r) { + const t = m ^ d; + const I = (t << r) | (t >>> (32 - r)); + return ((sBox[0][I >>> 24] - sBox[1][(I >>> 16) & 255]) + sBox[2][(I >>> 8) & 255]) ^ sBox[3][I & 255]; + } - // Subtract `num` from `this` in-place - BN.prototype.isub = function isub (num) { - // this - (-num) = this + num - if (num.negative !== 0) { - num.negative = 0; - var r = this.iadd(num); - num.negative = 1; - return r._normSign(); + function f3(d, m, r) { + const t = m - d; + const I = (t << r) | (t >>> (32 - r)); + return ((sBox[0][I >>> 24] + sBox[1][(I >>> 16) & 255]) ^ sBox[2][(I >>> 8) & 255]) - sBox[3][I & 255]; + } - // -this - num = -(this + num) - } else if (this.negative !== 0) { - this.negative = 0; - this.iadd(num); - this.negative = 1; - return this._normSign(); - } + const sBox = new Array(8); + sBox[0] = [ + 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949, + 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, + 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, + 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0, + 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, + 0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935, + 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d, + 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, + 0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe, + 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3, + 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, + 0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291, + 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779, + 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, + 0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, + 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d, + 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, + 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, + 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c, + 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, + 0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d, + 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96, + 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, + 0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, + 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, + 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, + 0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, + 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872, + 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, + 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, + 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9, + 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf + ]; - // At this point both numbers are positive - var cmp = this.cmp(num); + sBox[1] = [ + 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651, + 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, + 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, + 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806, + 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, + 0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359, + 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b, + 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, + 0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34, + 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb, + 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, + 0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860, + 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b, + 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, + 0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, + 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, + 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, + 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, + 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f, + 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, + 0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6, + 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58, + 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, + 0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, + 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6, + 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, + 0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6, + 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f, + 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, + 0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, + 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9, + 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1 + ]; - // Optimization - zeroify - if (cmp === 0) { - this.negative = 0; - this.length = 1; - this.words[0] = 0; - return this; - } + sBox[2] = [ + 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90, + 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, + 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, + 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240, + 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, + 0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, + 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71, + 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, + 0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, + 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15, + 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, + 0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176, + 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148, + 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, + 0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, + 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e, + 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, + 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, + 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a, + 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, + 0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, + 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5, + 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, + 0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536, + 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, + 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, + 0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69, + 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, + 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, + 0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, + 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a, + 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783 + ]; - // a > b - var a, b; - if (cmp > 0) { - a = this; - b = num; - } else { - a = num; - b = this; - } + sBox[3] = [ + 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1, + 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, + 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, + 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121, + 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, + 0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, + 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb, + 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, + 0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d, + 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6, + 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, + 0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003, + 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, + 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, + 0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, + 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a, + 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, + 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, + 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26, + 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, + 0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7, + 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417, + 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, + 0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2, + 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, + 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, + 0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, + 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, + 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, + 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, + 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282, + 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2 + ]; - var carry = 0; - for (var i = 0; i < b.length; i++) { - r = (a.words[i] | 0) - (b.words[i] | 0) + carry; - carry = r >> 26; - this.words[i] = r & 0x3ffffff; - } - for (; carry !== 0 && i < a.length; i++) { - r = (a.words[i] | 0) + carry; - carry = r >> 26; - this.words[i] = r & 0x3ffffff; - } + sBox[4] = [ + 0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f, + 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, + 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, + 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02, + 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, + 0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7, + 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9, + 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, + 0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774, + 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655, + 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, + 0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910, + 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1, + 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, + 0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, + 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f, + 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, + 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, + 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3, + 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, + 0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4, + 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2, + 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, + 0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5, + 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, + 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, + 0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801, + 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, + 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, + 0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, + 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8, + 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4 + ]; - // Copy rest of the words - if (carry === 0 && i < a.length && a !== this) { - for (; i < a.length; i++) { - this.words[i] = a.words[i]; - } - } + sBox[5] = [ + 0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac, + 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, + 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, + 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98, + 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, + 0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3, + 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd, + 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, + 0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9, + 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54, + 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, + 0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc, + 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf, + 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, + 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, + 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289, + 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, + 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, + 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b, + 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, + 0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13, + 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976, + 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, + 0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891, + 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da, + 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, + 0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084, + 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25, + 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, + 0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, + 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd, + 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f + ]; - this.length = Math.max(this.length, i); + sBox[6] = [ + 0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f, + 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, + 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, + 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19, + 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, + 0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516, + 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88, + 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, + 0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756, + 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, + 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, + 0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688, + 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28, + 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, + 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, + 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, + 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, + 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, + 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566, + 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, + 0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962, + 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e, + 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, + 0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c, + 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, + 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, + 0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be, + 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767, + 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, + 0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, + 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c, + 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3 + ]; - if (a !== this) { - this.negative = 1; - } + sBox[7] = [ + 0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5, + 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, + 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, + 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d, + 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, + 0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862, + 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc, + 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, + 0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e, + 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039, + 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, + 0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42, + 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5, + 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, + 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, + 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c, + 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, + 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, + 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70, + 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, + 0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c, + 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3, + 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, + 0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101, + 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f, + 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, + 0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a, + 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c, + 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, + 0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, + 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82, + 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e + ]; +} - return this.strip(); - }; +function CAST5(key) { + this.cast5 = new OpenPGPSymEncCAST5(); + this.cast5.setKey(key); - // Subtract `num` from `this` - BN.prototype.sub = function sub (num) { - return this.clone().isub(num); + this.encrypt = function(block) { + return this.cast5.encrypt(block); }; +} - function smallMulTo (self, num, out) { - out.negative = num.negative ^ self.negative; - var len = (self.length + num.length) | 0; - out.length = len; - len = (len - 1) | 0; +CAST5.blockSize = CAST5.prototype.blockSize = 8; +CAST5.keySize = CAST5.prototype.keySize = 16; - // Peel one iteration (compiler can't do it, because of code complexity) - var a = self.words[0] | 0; - var b = num.words[0] | 0; - var r = a * b; +/* eslint-disable no-mixed-operators, no-fallthrough */ - var lo = r & 0x3ffffff; - var carry = (r / 0x4000000) | 0; - out.words[0] = lo; - for (var k = 1; k < len; k++) { - // Sum all words with the same `i + j = k` and accumulate `ncarry`, - // note that ncarry could be >= 0x3ffffff - var ncarry = carry >>> 26; - var rword = carry & 0x3ffffff; - var maxJ = Math.min(k, num.length - 1); - for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { - var i = (k - j) | 0; - a = self.words[i] | 0; - b = num.words[j] | 0; - r = a * b + rword; - ncarry += (r / 0x4000000) | 0; - rword = r & 0x3ffffff; +/* Modified by Recurity Labs GmbH + * + * Cipher.js + * A block-cipher algorithm implementation on JavaScript + * See Cipher.readme.txt for further information. + * + * Copyright(c) 2009 Atsushi Oka [ http://oka.nu/ ] + * This script file is distributed under the LGPL + * + * ACKNOWLEDGMENT + * + * The main subroutines are written by Michiel van Everdingen. + * + * Michiel van Everdingen + * http://home.versatel.nl/MAvanEverdingen/index.html + * + * All rights for these routines are reserved to Michiel van Everdingen. + * + */ + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//Math +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +const MAXINT = 0xFFFFFFFF; + +function rotw(w, n) { + return (w << n | w >>> (32 - n)) & MAXINT; +} + +function getW(a, i) { + return a[i] | a[i + 1] << 8 | a[i + 2] << 16 | a[i + 3] << 24; +} + +function setW(a, i, w) { + a.splice(i, 4, w & 0xFF, (w >>> 8) & 0xFF, (w >>> 16) & 0xFF, (w >>> 24) & 0xFF); +} + +function getB(x, n) { + return (x >>> (n * 8)) & 0xFF; +} + +// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Twofish +// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +function createTwofish() { + // + let keyBytes = null; + let dataBytes = null; + let dataOffset = -1; + // var dataLength = -1; + // var idx2 = -1; + // + + let tfsKey = []; + let tfsM = [ + [], + [], + [], + [] + ]; + + function tfsInit(key) { + keyBytes = key; + let i; + let a; + let b; + let c; + let d; + const meKey = []; + const moKey = []; + const inKey = []; + let kLen; + const sKey = []; + let f01; + let f5b; + let fef; + + const q0 = [ + [8, 1, 7, 13, 6, 15, 3, 2, 0, 11, 5, 9, 14, 12, 10, 4], + [2, 8, 11, 13, 15, 7, 6, 14, 3, 1, 9, 4, 0, 10, 12, 5] + ]; + const q1 = [ + [14, 12, 11, 8, 1, 2, 3, 5, 15, 4, 10, 6, 7, 0, 9, 13], + [1, 14, 2, 11, 4, 12, 3, 7, 6, 13, 10, 5, 15, 9, 0, 8] + ]; + const q2 = [ + [11, 10, 5, 14, 6, 13, 9, 0, 12, 8, 15, 3, 2, 4, 7, 1], + [4, 12, 7, 5, 1, 6, 9, 10, 0, 14, 13, 8, 2, 11, 3, 15] + ]; + const q3 = [ + [13, 7, 15, 4, 1, 2, 6, 14, 9, 11, 3, 0, 8, 5, 12, 10], + [11, 9, 5, 1, 12, 3, 13, 14, 6, 4, 7, 15, 2, 0, 8, 10] + ]; + const ror4 = [0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15]; + const ashx = [0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 5, 14, 7]; + const q = [ + [], + [] + ]; + const m = [ + [], + [], + [], + [] + ]; + + function ffm5b(x) { + return x ^ (x >> 2) ^ [0, 90, 180, 238][x & 3]; + } + + function ffmEf(x) { + return x ^ (x >> 1) ^ (x >> 2) ^ [0, 238, 180, 90][x & 3]; + } + + function mdsRem(p, q) { + let i; + let t; + let u; + for (i = 0; i < 8; i++) { + t = q >>> 24; + q = ((q << 8) & MAXINT) | p >>> 24; + p = (p << 8) & MAXINT; + u = t << 1; + if (t & 128) { + u ^= 333; + } + q ^= t ^ (u << 16); + u ^= t >>> 1; + if (t & 1) { + u ^= 166; + } + q ^= u << 24 | u << 8; } - out.words[k] = rword | 0; - carry = ncarry | 0; + return q; } - if (carry !== 0) { - out.words[k] = carry | 0; - } else { - out.length--; + + function qp(n, x) { + const a = x >> 4; + const b = x & 15; + const c = q0[n][a ^ b]; + const d = q1[n][ror4[b] ^ ashx[a]]; + return q3[n][ror4[d] ^ ashx[c]] << 4 | q2[n][c ^ d]; } - return out.strip(); - } + function hFun(x, key) { + let a = getB(x, 0); + let b = getB(x, 1); + let c = getB(x, 2); + let d = getB(x, 3); + switch (kLen) { + case 4: + a = q[1][a] ^ getB(key[3], 0); + b = q[0][b] ^ getB(key[3], 1); + c = q[0][c] ^ getB(key[3], 2); + d = q[1][d] ^ getB(key[3], 3); + case 3: + a = q[1][a] ^ getB(key[2], 0); + b = q[1][b] ^ getB(key[2], 1); + c = q[0][c] ^ getB(key[2], 2); + d = q[0][d] ^ getB(key[2], 3); + case 2: + a = q[0][q[0][a] ^ getB(key[1], 0)] ^ getB(key[0], 0); + b = q[0][q[1][b] ^ getB(key[1], 1)] ^ getB(key[0], 1); + c = q[1][q[0][c] ^ getB(key[1], 2)] ^ getB(key[0], 2); + d = q[1][q[1][d] ^ getB(key[1], 3)] ^ getB(key[0], 3); + } + return m[0][a] ^ m[1][b] ^ m[2][c] ^ m[3][d]; + } - // TODO(indutny): it may be reasonable to omit it for users who don't need - // to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit - // multiplication (like elliptic secp256k1). - var comb10MulTo = function comb10MulTo (self, num, out) { - var a = self.words; - var b = num.words; - var o = out.words; - var c = 0; - var lo; - var mid; - var hi; - var a0 = a[0] | 0; - var al0 = a0 & 0x1fff; - var ah0 = a0 >>> 13; - var a1 = a[1] | 0; - var al1 = a1 & 0x1fff; - var ah1 = a1 >>> 13; - var a2 = a[2] | 0; - var al2 = a2 & 0x1fff; - var ah2 = a2 >>> 13; - var a3 = a[3] | 0; - var al3 = a3 & 0x1fff; - var ah3 = a3 >>> 13; - var a4 = a[4] | 0; - var al4 = a4 & 0x1fff; - var ah4 = a4 >>> 13; - var a5 = a[5] | 0; - var al5 = a5 & 0x1fff; - var ah5 = a5 >>> 13; - var a6 = a[6] | 0; - var al6 = a6 & 0x1fff; - var ah6 = a6 >>> 13; - var a7 = a[7] | 0; - var al7 = a7 & 0x1fff; - var ah7 = a7 >>> 13; - var a8 = a[8] | 0; - var al8 = a8 & 0x1fff; - var ah8 = a8 >>> 13; - var a9 = a[9] | 0; - var al9 = a9 & 0x1fff; - var ah9 = a9 >>> 13; - var b0 = b[0] | 0; - var bl0 = b0 & 0x1fff; - var bh0 = b0 >>> 13; - var b1 = b[1] | 0; - var bl1 = b1 & 0x1fff; - var bh1 = b1 >>> 13; - var b2 = b[2] | 0; - var bl2 = b2 & 0x1fff; - var bh2 = b2 >>> 13; - var b3 = b[3] | 0; - var bl3 = b3 & 0x1fff; - var bh3 = b3 >>> 13; - var b4 = b[4] | 0; - var bl4 = b4 & 0x1fff; - var bh4 = b4 >>> 13; - var b5 = b[5] | 0; - var bl5 = b5 & 0x1fff; - var bh5 = b5 >>> 13; - var b6 = b[6] | 0; - var bl6 = b6 & 0x1fff; - var bh6 = b6 >>> 13; - var b7 = b[7] | 0; - var bl7 = b7 & 0x1fff; - var bh7 = b7 >>> 13; - var b8 = b[8] | 0; - var bl8 = b8 & 0x1fff; - var bh8 = b8 >>> 13; - var b9 = b[9] | 0; - var bl9 = b9 & 0x1fff; - var bh9 = b9 >>> 13; + keyBytes = keyBytes.slice(0, 32); + i = keyBytes.length; + while (i !== 16 && i !== 24 && i !== 32) { + keyBytes[i++] = 0; + } - out.negative = self.negative ^ num.negative; - out.length = 19; - /* k = 0 */ - lo = Math.imul(al0, bl0); - mid = Math.imul(al0, bh0); - mid = (mid + Math.imul(ah0, bl0)) | 0; - hi = Math.imul(ah0, bh0); - var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0; - w0 &= 0x3ffffff; - /* k = 1 */ - lo = Math.imul(al1, bl0); - mid = Math.imul(al1, bh0); - mid = (mid + Math.imul(ah1, bl0)) | 0; - hi = Math.imul(ah1, bh0); - lo = (lo + Math.imul(al0, bl1)) | 0; - mid = (mid + Math.imul(al0, bh1)) | 0; - mid = (mid + Math.imul(ah0, bl1)) | 0; - hi = (hi + Math.imul(ah0, bh1)) | 0; - var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0; - w1 &= 0x3ffffff; - /* k = 2 */ - lo = Math.imul(al2, bl0); - mid = Math.imul(al2, bh0); - mid = (mid + Math.imul(ah2, bl0)) | 0; - hi = Math.imul(ah2, bh0); - lo = (lo + Math.imul(al1, bl1)) | 0; - mid = (mid + Math.imul(al1, bh1)) | 0; - mid = (mid + Math.imul(ah1, bl1)) | 0; - hi = (hi + Math.imul(ah1, bh1)) | 0; - lo = (lo + Math.imul(al0, bl2)) | 0; - mid = (mid + Math.imul(al0, bh2)) | 0; - mid = (mid + Math.imul(ah0, bl2)) | 0; - hi = (hi + Math.imul(ah0, bh2)) | 0; - var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0; - w2 &= 0x3ffffff; - /* k = 3 */ - lo = Math.imul(al3, bl0); - mid = Math.imul(al3, bh0); - mid = (mid + Math.imul(ah3, bl0)) | 0; - hi = Math.imul(ah3, bh0); - lo = (lo + Math.imul(al2, bl1)) | 0; - mid = (mid + Math.imul(al2, bh1)) | 0; - mid = (mid + Math.imul(ah2, bl1)) | 0; - hi = (hi + Math.imul(ah2, bh1)) | 0; - lo = (lo + Math.imul(al1, bl2)) | 0; - mid = (mid + Math.imul(al1, bh2)) | 0; - mid = (mid + Math.imul(ah1, bl2)) | 0; - hi = (hi + Math.imul(ah1, bh2)) | 0; - lo = (lo + Math.imul(al0, bl3)) | 0; - mid = (mid + Math.imul(al0, bh3)) | 0; - mid = (mid + Math.imul(ah0, bl3)) | 0; - hi = (hi + Math.imul(ah0, bh3)) | 0; - var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0; - w3 &= 0x3ffffff; - /* k = 4 */ - lo = Math.imul(al4, bl0); - mid = Math.imul(al4, bh0); - mid = (mid + Math.imul(ah4, bl0)) | 0; - hi = Math.imul(ah4, bh0); - lo = (lo + Math.imul(al3, bl1)) | 0; - mid = (mid + Math.imul(al3, bh1)) | 0; - mid = (mid + Math.imul(ah3, bl1)) | 0; - hi = (hi + Math.imul(ah3, bh1)) | 0; - lo = (lo + Math.imul(al2, bl2)) | 0; - mid = (mid + Math.imul(al2, bh2)) | 0; - mid = (mid + Math.imul(ah2, bl2)) | 0; - hi = (hi + Math.imul(ah2, bh2)) | 0; - lo = (lo + Math.imul(al1, bl3)) | 0; - mid = (mid + Math.imul(al1, bh3)) | 0; - mid = (mid + Math.imul(ah1, bl3)) | 0; - hi = (hi + Math.imul(ah1, bh3)) | 0; - lo = (lo + Math.imul(al0, bl4)) | 0; - mid = (mid + Math.imul(al0, bh4)) | 0; - mid = (mid + Math.imul(ah0, bl4)) | 0; - hi = (hi + Math.imul(ah0, bh4)) | 0; - var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0; - w4 &= 0x3ffffff; - /* k = 5 */ - lo = Math.imul(al5, bl0); - mid = Math.imul(al5, bh0); - mid = (mid + Math.imul(ah5, bl0)) | 0; - hi = Math.imul(ah5, bh0); - lo = (lo + Math.imul(al4, bl1)) | 0; - mid = (mid + Math.imul(al4, bh1)) | 0; - mid = (mid + Math.imul(ah4, bl1)) | 0; - hi = (hi + Math.imul(ah4, bh1)) | 0; - lo = (lo + Math.imul(al3, bl2)) | 0; - mid = (mid + Math.imul(al3, bh2)) | 0; - mid = (mid + Math.imul(ah3, bl2)) | 0; - hi = (hi + Math.imul(ah3, bh2)) | 0; - lo = (lo + Math.imul(al2, bl3)) | 0; - mid = (mid + Math.imul(al2, bh3)) | 0; - mid = (mid + Math.imul(ah2, bl3)) | 0; - hi = (hi + Math.imul(ah2, bh3)) | 0; - lo = (lo + Math.imul(al1, bl4)) | 0; - mid = (mid + Math.imul(al1, bh4)) | 0; - mid = (mid + Math.imul(ah1, bl4)) | 0; - hi = (hi + Math.imul(ah1, bh4)) | 0; - lo = (lo + Math.imul(al0, bl5)) | 0; - mid = (mid + Math.imul(al0, bh5)) | 0; - mid = (mid + Math.imul(ah0, bl5)) | 0; - hi = (hi + Math.imul(ah0, bh5)) | 0; - var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0; - w5 &= 0x3ffffff; - /* k = 6 */ - lo = Math.imul(al6, bl0); - mid = Math.imul(al6, bh0); - mid = (mid + Math.imul(ah6, bl0)) | 0; - hi = Math.imul(ah6, bh0); - lo = (lo + Math.imul(al5, bl1)) | 0; - mid = (mid + Math.imul(al5, bh1)) | 0; - mid = (mid + Math.imul(ah5, bl1)) | 0; - hi = (hi + Math.imul(ah5, bh1)) | 0; - lo = (lo + Math.imul(al4, bl2)) | 0; - mid = (mid + Math.imul(al4, bh2)) | 0; - mid = (mid + Math.imul(ah4, bl2)) | 0; - hi = (hi + Math.imul(ah4, bh2)) | 0; - lo = (lo + Math.imul(al3, bl3)) | 0; - mid = (mid + Math.imul(al3, bh3)) | 0; - mid = (mid + Math.imul(ah3, bl3)) | 0; - hi = (hi + Math.imul(ah3, bh3)) | 0; - lo = (lo + Math.imul(al2, bl4)) | 0; - mid = (mid + Math.imul(al2, bh4)) | 0; - mid = (mid + Math.imul(ah2, bl4)) | 0; - hi = (hi + Math.imul(ah2, bh4)) | 0; - lo = (lo + Math.imul(al1, bl5)) | 0; - mid = (mid + Math.imul(al1, bh5)) | 0; - mid = (mid + Math.imul(ah1, bl5)) | 0; - hi = (hi + Math.imul(ah1, bh5)) | 0; - lo = (lo + Math.imul(al0, bl6)) | 0; - mid = (mid + Math.imul(al0, bh6)) | 0; - mid = (mid + Math.imul(ah0, bl6)) | 0; - hi = (hi + Math.imul(ah0, bh6)) | 0; - var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0; - w6 &= 0x3ffffff; - /* k = 7 */ - lo = Math.imul(al7, bl0); - mid = Math.imul(al7, bh0); - mid = (mid + Math.imul(ah7, bl0)) | 0; - hi = Math.imul(ah7, bh0); - lo = (lo + Math.imul(al6, bl1)) | 0; - mid = (mid + Math.imul(al6, bh1)) | 0; - mid = (mid + Math.imul(ah6, bl1)) | 0; - hi = (hi + Math.imul(ah6, bh1)) | 0; - lo = (lo + Math.imul(al5, bl2)) | 0; - mid = (mid + Math.imul(al5, bh2)) | 0; - mid = (mid + Math.imul(ah5, bl2)) | 0; - hi = (hi + Math.imul(ah5, bh2)) | 0; - lo = (lo + Math.imul(al4, bl3)) | 0; - mid = (mid + Math.imul(al4, bh3)) | 0; - mid = (mid + Math.imul(ah4, bl3)) | 0; - hi = (hi + Math.imul(ah4, bh3)) | 0; - lo = (lo + Math.imul(al3, bl4)) | 0; - mid = (mid + Math.imul(al3, bh4)) | 0; - mid = (mid + Math.imul(ah3, bl4)) | 0; - hi = (hi + Math.imul(ah3, bh4)) | 0; - lo = (lo + Math.imul(al2, bl5)) | 0; - mid = (mid + Math.imul(al2, bh5)) | 0; - mid = (mid + Math.imul(ah2, bl5)) | 0; - hi = (hi + Math.imul(ah2, bh5)) | 0; - lo = (lo + Math.imul(al1, bl6)) | 0; - mid = (mid + Math.imul(al1, bh6)) | 0; - mid = (mid + Math.imul(ah1, bl6)) | 0; - hi = (hi + Math.imul(ah1, bh6)) | 0; - lo = (lo + Math.imul(al0, bl7)) | 0; - mid = (mid + Math.imul(al0, bh7)) | 0; - mid = (mid + Math.imul(ah0, bl7)) | 0; - hi = (hi + Math.imul(ah0, bh7)) | 0; - var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0; - w7 &= 0x3ffffff; - /* k = 8 */ - lo = Math.imul(al8, bl0); - mid = Math.imul(al8, bh0); - mid = (mid + Math.imul(ah8, bl0)) | 0; - hi = Math.imul(ah8, bh0); - lo = (lo + Math.imul(al7, bl1)) | 0; - mid = (mid + Math.imul(al7, bh1)) | 0; - mid = (mid + Math.imul(ah7, bl1)) | 0; - hi = (hi + Math.imul(ah7, bh1)) | 0; - lo = (lo + Math.imul(al6, bl2)) | 0; - mid = (mid + Math.imul(al6, bh2)) | 0; - mid = (mid + Math.imul(ah6, bl2)) | 0; - hi = (hi + Math.imul(ah6, bh2)) | 0; - lo = (lo + Math.imul(al5, bl3)) | 0; - mid = (mid + Math.imul(al5, bh3)) | 0; - mid = (mid + Math.imul(ah5, bl3)) | 0; - hi = (hi + Math.imul(ah5, bh3)) | 0; - lo = (lo + Math.imul(al4, bl4)) | 0; - mid = (mid + Math.imul(al4, bh4)) | 0; - mid = (mid + Math.imul(ah4, bl4)) | 0; - hi = (hi + Math.imul(ah4, bh4)) | 0; - lo = (lo + Math.imul(al3, bl5)) | 0; - mid = (mid + Math.imul(al3, bh5)) | 0; - mid = (mid + Math.imul(ah3, bl5)) | 0; - hi = (hi + Math.imul(ah3, bh5)) | 0; - lo = (lo + Math.imul(al2, bl6)) | 0; - mid = (mid + Math.imul(al2, bh6)) | 0; - mid = (mid + Math.imul(ah2, bl6)) | 0; - hi = (hi + Math.imul(ah2, bh6)) | 0; - lo = (lo + Math.imul(al1, bl7)) | 0; - mid = (mid + Math.imul(al1, bh7)) | 0; - mid = (mid + Math.imul(ah1, bl7)) | 0; - hi = (hi + Math.imul(ah1, bh7)) | 0; - lo = (lo + Math.imul(al0, bl8)) | 0; - mid = (mid + Math.imul(al0, bh8)) | 0; - mid = (mid + Math.imul(ah0, bl8)) | 0; - hi = (hi + Math.imul(ah0, bh8)) | 0; - var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0; - w8 &= 0x3ffffff; - /* k = 9 */ - lo = Math.imul(al9, bl0); - mid = Math.imul(al9, bh0); - mid = (mid + Math.imul(ah9, bl0)) | 0; - hi = Math.imul(ah9, bh0); - lo = (lo + Math.imul(al8, bl1)) | 0; - mid = (mid + Math.imul(al8, bh1)) | 0; - mid = (mid + Math.imul(ah8, bl1)) | 0; - hi = (hi + Math.imul(ah8, bh1)) | 0; - lo = (lo + Math.imul(al7, bl2)) | 0; - mid = (mid + Math.imul(al7, bh2)) | 0; - mid = (mid + Math.imul(ah7, bl2)) | 0; - hi = (hi + Math.imul(ah7, bh2)) | 0; - lo = (lo + Math.imul(al6, bl3)) | 0; - mid = (mid + Math.imul(al6, bh3)) | 0; - mid = (mid + Math.imul(ah6, bl3)) | 0; - hi = (hi + Math.imul(ah6, bh3)) | 0; - lo = (lo + Math.imul(al5, bl4)) | 0; - mid = (mid + Math.imul(al5, bh4)) | 0; - mid = (mid + Math.imul(ah5, bl4)) | 0; - hi = (hi + Math.imul(ah5, bh4)) | 0; - lo = (lo + Math.imul(al4, bl5)) | 0; - mid = (mid + Math.imul(al4, bh5)) | 0; - mid = (mid + Math.imul(ah4, bl5)) | 0; - hi = (hi + Math.imul(ah4, bh5)) | 0; - lo = (lo + Math.imul(al3, bl6)) | 0; - mid = (mid + Math.imul(al3, bh6)) | 0; - mid = (mid + Math.imul(ah3, bl6)) | 0; - hi = (hi + Math.imul(ah3, bh6)) | 0; - lo = (lo + Math.imul(al2, bl7)) | 0; - mid = (mid + Math.imul(al2, bh7)) | 0; - mid = (mid + Math.imul(ah2, bl7)) | 0; - hi = (hi + Math.imul(ah2, bh7)) | 0; - lo = (lo + Math.imul(al1, bl8)) | 0; - mid = (mid + Math.imul(al1, bh8)) | 0; - mid = (mid + Math.imul(ah1, bl8)) | 0; - hi = (hi + Math.imul(ah1, bh8)) | 0; - lo = (lo + Math.imul(al0, bl9)) | 0; - mid = (mid + Math.imul(al0, bh9)) | 0; - mid = (mid + Math.imul(ah0, bl9)) | 0; - hi = (hi + Math.imul(ah0, bh9)) | 0; - var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0; - w9 &= 0x3ffffff; - /* k = 10 */ - lo = Math.imul(al9, bl1); - mid = Math.imul(al9, bh1); - mid = (mid + Math.imul(ah9, bl1)) | 0; - hi = Math.imul(ah9, bh1); - lo = (lo + Math.imul(al8, bl2)) | 0; - mid = (mid + Math.imul(al8, bh2)) | 0; - mid = (mid + Math.imul(ah8, bl2)) | 0; - hi = (hi + Math.imul(ah8, bh2)) | 0; - lo = (lo + Math.imul(al7, bl3)) | 0; - mid = (mid + Math.imul(al7, bh3)) | 0; - mid = (mid + Math.imul(ah7, bl3)) | 0; - hi = (hi + Math.imul(ah7, bh3)) | 0; - lo = (lo + Math.imul(al6, bl4)) | 0; - mid = (mid + Math.imul(al6, bh4)) | 0; - mid = (mid + Math.imul(ah6, bl4)) | 0; - hi = (hi + Math.imul(ah6, bh4)) | 0; - lo = (lo + Math.imul(al5, bl5)) | 0; - mid = (mid + Math.imul(al5, bh5)) | 0; - mid = (mid + Math.imul(ah5, bl5)) | 0; - hi = (hi + Math.imul(ah5, bh5)) | 0; - lo = (lo + Math.imul(al4, bl6)) | 0; - mid = (mid + Math.imul(al4, bh6)) | 0; - mid = (mid + Math.imul(ah4, bl6)) | 0; - hi = (hi + Math.imul(ah4, bh6)) | 0; - lo = (lo + Math.imul(al3, bl7)) | 0; - mid = (mid + Math.imul(al3, bh7)) | 0; - mid = (mid + Math.imul(ah3, bl7)) | 0; - hi = (hi + Math.imul(ah3, bh7)) | 0; - lo = (lo + Math.imul(al2, bl8)) | 0; - mid = (mid + Math.imul(al2, bh8)) | 0; - mid = (mid + Math.imul(ah2, bl8)) | 0; - hi = (hi + Math.imul(ah2, bh8)) | 0; - lo = (lo + Math.imul(al1, bl9)) | 0; - mid = (mid + Math.imul(al1, bh9)) | 0; - mid = (mid + Math.imul(ah1, bl9)) | 0; - hi = (hi + Math.imul(ah1, bh9)) | 0; - var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0; - w10 &= 0x3ffffff; - /* k = 11 */ - lo = Math.imul(al9, bl2); - mid = Math.imul(al9, bh2); - mid = (mid + Math.imul(ah9, bl2)) | 0; - hi = Math.imul(ah9, bh2); - lo = (lo + Math.imul(al8, bl3)) | 0; - mid = (mid + Math.imul(al8, bh3)) | 0; - mid = (mid + Math.imul(ah8, bl3)) | 0; - hi = (hi + Math.imul(ah8, bh3)) | 0; - lo = (lo + Math.imul(al7, bl4)) | 0; - mid = (mid + Math.imul(al7, bh4)) | 0; - mid = (mid + Math.imul(ah7, bl4)) | 0; - hi = (hi + Math.imul(ah7, bh4)) | 0; - lo = (lo + Math.imul(al6, bl5)) | 0; - mid = (mid + Math.imul(al6, bh5)) | 0; - mid = (mid + Math.imul(ah6, bl5)) | 0; - hi = (hi + Math.imul(ah6, bh5)) | 0; - lo = (lo + Math.imul(al5, bl6)) | 0; - mid = (mid + Math.imul(al5, bh6)) | 0; - mid = (mid + Math.imul(ah5, bl6)) | 0; - hi = (hi + Math.imul(ah5, bh6)) | 0; - lo = (lo + Math.imul(al4, bl7)) | 0; - mid = (mid + Math.imul(al4, bh7)) | 0; - mid = (mid + Math.imul(ah4, bl7)) | 0; - hi = (hi + Math.imul(ah4, bh7)) | 0; - lo = (lo + Math.imul(al3, bl8)) | 0; - mid = (mid + Math.imul(al3, bh8)) | 0; - mid = (mid + Math.imul(ah3, bl8)) | 0; - hi = (hi + Math.imul(ah3, bh8)) | 0; - lo = (lo + Math.imul(al2, bl9)) | 0; - mid = (mid + Math.imul(al2, bh9)) | 0; - mid = (mid + Math.imul(ah2, bl9)) | 0; - hi = (hi + Math.imul(ah2, bh9)) | 0; - var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0; - w11 &= 0x3ffffff; - /* k = 12 */ - lo = Math.imul(al9, bl3); - mid = Math.imul(al9, bh3); - mid = (mid + Math.imul(ah9, bl3)) | 0; - hi = Math.imul(ah9, bh3); - lo = (lo + Math.imul(al8, bl4)) | 0; - mid = (mid + Math.imul(al8, bh4)) | 0; - mid = (mid + Math.imul(ah8, bl4)) | 0; - hi = (hi + Math.imul(ah8, bh4)) | 0; - lo = (lo + Math.imul(al7, bl5)) | 0; - mid = (mid + Math.imul(al7, bh5)) | 0; - mid = (mid + Math.imul(ah7, bl5)) | 0; - hi = (hi + Math.imul(ah7, bh5)) | 0; - lo = (lo + Math.imul(al6, bl6)) | 0; - mid = (mid + Math.imul(al6, bh6)) | 0; - mid = (mid + Math.imul(ah6, bl6)) | 0; - hi = (hi + Math.imul(ah6, bh6)) | 0; - lo = (lo + Math.imul(al5, bl7)) | 0; - mid = (mid + Math.imul(al5, bh7)) | 0; - mid = (mid + Math.imul(ah5, bl7)) | 0; - hi = (hi + Math.imul(ah5, bh7)) | 0; - lo = (lo + Math.imul(al4, bl8)) | 0; - mid = (mid + Math.imul(al4, bh8)) | 0; - mid = (mid + Math.imul(ah4, bl8)) | 0; - hi = (hi + Math.imul(ah4, bh8)) | 0; - lo = (lo + Math.imul(al3, bl9)) | 0; - mid = (mid + Math.imul(al3, bh9)) | 0; - mid = (mid + Math.imul(ah3, bl9)) | 0; - hi = (hi + Math.imul(ah3, bh9)) | 0; - var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0; - w12 &= 0x3ffffff; - /* k = 13 */ - lo = Math.imul(al9, bl4); - mid = Math.imul(al9, bh4); - mid = (mid + Math.imul(ah9, bl4)) | 0; - hi = Math.imul(ah9, bh4); - lo = (lo + Math.imul(al8, bl5)) | 0; - mid = (mid + Math.imul(al8, bh5)) | 0; - mid = (mid + Math.imul(ah8, bl5)) | 0; - hi = (hi + Math.imul(ah8, bh5)) | 0; - lo = (lo + Math.imul(al7, bl6)) | 0; - mid = (mid + Math.imul(al7, bh6)) | 0; - mid = (mid + Math.imul(ah7, bl6)) | 0; - hi = (hi + Math.imul(ah7, bh6)) | 0; - lo = (lo + Math.imul(al6, bl7)) | 0; - mid = (mid + Math.imul(al6, bh7)) | 0; - mid = (mid + Math.imul(ah6, bl7)) | 0; - hi = (hi + Math.imul(ah6, bh7)) | 0; - lo = (lo + Math.imul(al5, bl8)) | 0; - mid = (mid + Math.imul(al5, bh8)) | 0; - mid = (mid + Math.imul(ah5, bl8)) | 0; - hi = (hi + Math.imul(ah5, bh8)) | 0; - lo = (lo + Math.imul(al4, bl9)) | 0; - mid = (mid + Math.imul(al4, bh9)) | 0; - mid = (mid + Math.imul(ah4, bl9)) | 0; - hi = (hi + Math.imul(ah4, bh9)) | 0; - var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0; - w13 &= 0x3ffffff; - /* k = 14 */ - lo = Math.imul(al9, bl5); - mid = Math.imul(al9, bh5); - mid = (mid + Math.imul(ah9, bl5)) | 0; - hi = Math.imul(ah9, bh5); - lo = (lo + Math.imul(al8, bl6)) | 0; - mid = (mid + Math.imul(al8, bh6)) | 0; - mid = (mid + Math.imul(ah8, bl6)) | 0; - hi = (hi + Math.imul(ah8, bh6)) | 0; - lo = (lo + Math.imul(al7, bl7)) | 0; - mid = (mid + Math.imul(al7, bh7)) | 0; - mid = (mid + Math.imul(ah7, bl7)) | 0; - hi = (hi + Math.imul(ah7, bh7)) | 0; - lo = (lo + Math.imul(al6, bl8)) | 0; - mid = (mid + Math.imul(al6, bh8)) | 0; - mid = (mid + Math.imul(ah6, bl8)) | 0; - hi = (hi + Math.imul(ah6, bh8)) | 0; - lo = (lo + Math.imul(al5, bl9)) | 0; - mid = (mid + Math.imul(al5, bh9)) | 0; - mid = (mid + Math.imul(ah5, bl9)) | 0; - hi = (hi + Math.imul(ah5, bh9)) | 0; - var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0; - w14 &= 0x3ffffff; - /* k = 15 */ - lo = Math.imul(al9, bl6); - mid = Math.imul(al9, bh6); - mid = (mid + Math.imul(ah9, bl6)) | 0; - hi = Math.imul(ah9, bh6); - lo = (lo + Math.imul(al8, bl7)) | 0; - mid = (mid + Math.imul(al8, bh7)) | 0; - mid = (mid + Math.imul(ah8, bl7)) | 0; - hi = (hi + Math.imul(ah8, bh7)) | 0; - lo = (lo + Math.imul(al7, bl8)) | 0; - mid = (mid + Math.imul(al7, bh8)) | 0; - mid = (mid + Math.imul(ah7, bl8)) | 0; - hi = (hi + Math.imul(ah7, bh8)) | 0; - lo = (lo + Math.imul(al6, bl9)) | 0; - mid = (mid + Math.imul(al6, bh9)) | 0; - mid = (mid + Math.imul(ah6, bl9)) | 0; - hi = (hi + Math.imul(ah6, bh9)) | 0; - var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0; - w15 &= 0x3ffffff; - /* k = 16 */ - lo = Math.imul(al9, bl7); - mid = Math.imul(al9, bh7); - mid = (mid + Math.imul(ah9, bl7)) | 0; - hi = Math.imul(ah9, bh7); - lo = (lo + Math.imul(al8, bl8)) | 0; - mid = (mid + Math.imul(al8, bh8)) | 0; - mid = (mid + Math.imul(ah8, bl8)) | 0; - hi = (hi + Math.imul(ah8, bh8)) | 0; - lo = (lo + Math.imul(al7, bl9)) | 0; - mid = (mid + Math.imul(al7, bh9)) | 0; - mid = (mid + Math.imul(ah7, bl9)) | 0; - hi = (hi + Math.imul(ah7, bh9)) | 0; - var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0; - w16 &= 0x3ffffff; - /* k = 17 */ - lo = Math.imul(al9, bl8); - mid = Math.imul(al9, bh8); - mid = (mid + Math.imul(ah9, bl8)) | 0; - hi = Math.imul(ah9, bh8); - lo = (lo + Math.imul(al8, bl9)) | 0; - mid = (mid + Math.imul(al8, bh9)) | 0; - mid = (mid + Math.imul(ah8, bl9)) | 0; - hi = (hi + Math.imul(ah8, bh9)) | 0; - var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0; - w17 &= 0x3ffffff; - /* k = 18 */ - lo = Math.imul(al9, bl9); - mid = Math.imul(al9, bh9); - mid = (mid + Math.imul(ah9, bl9)) | 0; - hi = Math.imul(ah9, bh9); - var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0; - w18 &= 0x3ffffff; - o[0] = w0; - o[1] = w1; - o[2] = w2; - o[3] = w3; - o[4] = w4; - o[5] = w5; - o[6] = w6; - o[7] = w7; - o[8] = w8; - o[9] = w9; - o[10] = w10; - o[11] = w11; - o[12] = w12; - o[13] = w13; - o[14] = w14; - o[15] = w15; - o[16] = w16; - o[17] = w17; - o[18] = w18; - if (c !== 0) { - o[19] = c; - out.length++; - } - return out; - }; - - // Polyfill comb - if (!Math.imul) { - comb10MulTo = smallMulTo; - } - - function bigMulTo (self, num, out) { - out.negative = num.negative ^ self.negative; - out.length = self.length + num.length; - - var carry = 0; - var hncarry = 0; - for (var k = 0; k < out.length - 1; k++) { - // Sum all words with the same `i + j = k` and accumulate `ncarry`, - // note that ncarry could be >= 0x3ffffff - var ncarry = hncarry; - hncarry = 0; - var rword = carry & 0x3ffffff; - var maxJ = Math.min(k, num.length - 1); - for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { - var i = k - j; - var a = self.words[i] | 0; - var b = num.words[j] | 0; - var r = a * b; - - var lo = r & 0x3ffffff; - ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0; - lo = (lo + rword) | 0; - rword = lo & 0x3ffffff; - ncarry = (ncarry + (lo >>> 26)) | 0; - - hncarry += ncarry >>> 26; - ncarry &= 0x3ffffff; - } - out.words[k] = rword; - carry = ncarry; - ncarry = hncarry; - } - if (carry !== 0) { - out.words[k] = carry; - } else { - out.length--; - } - - return out.strip(); - } - - function jumboMulTo (self, num, out) { - var fftm = new FFTM(); - return fftm.mulp(self, num, out); - } - - BN.prototype.mulTo = function mulTo (num, out) { - var res; - var len = this.length + num.length; - if (this.length === 10 && num.length === 10) { - res = comb10MulTo(this, num, out); - } else if (len < 63) { - res = smallMulTo(this, num, out); - } else if (len < 1024) { - res = bigMulTo(this, num, out); - } else { - res = jumboMulTo(this, num, out); - } - - return res; - }; - - // Cooley-Tukey algorithm for FFT - // slightly revisited to rely on looping instead of recursion - - function FFTM (x, y) { - this.x = x; - this.y = y; - } - - FFTM.prototype.makeRBT = function makeRBT (N) { - var t = new Array(N); - var l = BN.prototype._countBits(N) - 1; - for (var i = 0; i < N; i++) { - t[i] = this.revBin(i, l, N); - } - - return t; - }; - - // Returns binary-reversed representation of `x` - FFTM.prototype.revBin = function revBin (x, l, N) { - if (x === 0 || x === N - 1) return x; - - var rb = 0; - for (var i = 0; i < l; i++) { - rb |= (x & 1) << (l - i - 1); - x >>= 1; - } - - return rb; - }; - - // Performs "tweedling" phase, therefore 'emulating' - // behaviour of the recursive algorithm - FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) { - for (var i = 0; i < N; i++) { - rtws[i] = rws[rbt[i]]; - itws[i] = iws[rbt[i]]; - } - }; - - FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) { - this.permute(rbt, rws, iws, rtws, itws, N); - - for (var s = 1; s < N; s <<= 1) { - var l = s << 1; - - var rtwdf = Math.cos(2 * Math.PI / l); - var itwdf = Math.sin(2 * Math.PI / l); - - for (var p = 0; p < N; p += l) { - var rtwdf_ = rtwdf; - var itwdf_ = itwdf; - - for (var j = 0; j < s; j++) { - var re = rtws[p + j]; - var ie = itws[p + j]; - - var ro = rtws[p + j + s]; - var io = itws[p + j + s]; - - var rx = rtwdf_ * ro - itwdf_ * io; - - io = rtwdf_ * io + itwdf_ * ro; - ro = rx; - - rtws[p + j] = re + ro; - itws[p + j] = ie + io; - - rtws[p + j + s] = re - ro; - itws[p + j + s] = ie - io; - - /* jshint maxdepth : false */ - if (j !== l) { - rx = rtwdf * rtwdf_ - itwdf * itwdf_; - - itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_; - rtwdf_ = rx; - } - } - } - } - }; - - FFTM.prototype.guessLen13b = function guessLen13b (n, m) { - var N = Math.max(m, n) | 1; - var odd = N & 1; - var i = 0; - for (N = N / 2 | 0; N; N = N >>> 1) { - i++; - } - - return 1 << i + 1 + odd; - }; - - FFTM.prototype.conjugate = function conjugate (rws, iws, N) { - if (N <= 1) return; - - for (var i = 0; i < N / 2; i++) { - var t = rws[i]; - - rws[i] = rws[N - i - 1]; - rws[N - i - 1] = t; - - t = iws[i]; - - iws[i] = -iws[N - i - 1]; - iws[N - i - 1] = -t; - } - }; - - FFTM.prototype.normalize13b = function normalize13b (ws, N) { - var carry = 0; - for (var i = 0; i < N / 2; i++) { - var w = Math.round(ws[2 * i + 1] / N) * 0x2000 + - Math.round(ws[2 * i] / N) + - carry; - - ws[i] = w & 0x3ffffff; - - if (w < 0x4000000) { - carry = 0; - } else { - carry = w / 0x4000000 | 0; - } - } - - return ws; - }; - - FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) { - var carry = 0; - for (var i = 0; i < len; i++) { - carry = carry + (ws[i] | 0); - - rws[2 * i] = carry & 0x1fff; carry = carry >>> 13; - rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13; - } - - // Pad with zeroes - for (i = 2 * len; i < N; ++i) { - rws[i] = 0; - } - - assert(carry === 0); - assert((carry & ~0x1fff) === 0); - }; - - FFTM.prototype.stub = function stub (N) { - var ph = new Array(N); - for (var i = 0; i < N; i++) { - ph[i] = 0; - } - - return ph; - }; - - FFTM.prototype.mulp = function mulp (x, y, out) { - var N = 2 * this.guessLen13b(x.length, y.length); - - var rbt = this.makeRBT(N); - - var _ = this.stub(N); - - var rws = new Array(N); - var rwst = new Array(N); - var iwst = new Array(N); - - var nrws = new Array(N); - var nrwst = new Array(N); - var niwst = new Array(N); - - var rmws = out.words; - rmws.length = N; - - this.convert13b(x.words, x.length, rws, N); - this.convert13b(y.words, y.length, nrws, N); - - this.transform(rws, _, rwst, iwst, N, rbt); - this.transform(nrws, _, nrwst, niwst, N, rbt); - - for (var i = 0; i < N; i++) { - var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i]; - iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i]; - rwst[i] = rx; - } - - this.conjugate(rwst, iwst, N); - this.transform(rwst, iwst, rmws, _, N, rbt); - this.conjugate(rmws, _, N); - this.normalize13b(rmws, N); - - out.negative = x.negative ^ y.negative; - out.length = x.length + y.length; - return out.strip(); - }; - - // Multiply `this` by `num` - BN.prototype.mul = function mul (num) { - var out = new BN(null); - out.words = new Array(this.length + num.length); - return this.mulTo(num, out); - }; - - // Multiply employing FFT - BN.prototype.mulf = function mulf (num) { - var out = new BN(null); - out.words = new Array(this.length + num.length); - return jumboMulTo(this, num, out); - }; - - // In-place Multiplication - BN.prototype.imul = function imul (num) { - return this.clone().mulTo(num, this); - }; - - BN.prototype.imuln = function imuln (num) { - assert(typeof num === 'number'); - assert(num < 0x4000000); - - // Carry - var carry = 0; - for (var i = 0; i < this.length; i++) { - var w = (this.words[i] | 0) * num; - var lo = (w & 0x3ffffff) + (carry & 0x3ffffff); - carry >>= 26; - carry += (w / 0x4000000) | 0; - // NOTE: lo is 27bit maximum - carry += lo >>> 26; - this.words[i] = lo & 0x3ffffff; - } - - if (carry !== 0) { - this.words[i] = carry; - this.length++; - } - - return this; - }; - - BN.prototype.muln = function muln (num) { - return this.clone().imuln(num); - }; - - // `this` * `this` - BN.prototype.sqr = function sqr () { - return this.mul(this); - }; - - // `this` * `this` in-place - BN.prototype.isqr = function isqr () { - return this.imul(this.clone()); - }; - - // Math.pow(`this`, `num`) - BN.prototype.pow = function pow (num) { - var w = toBitArray(num); - if (w.length === 0) return new BN(1); - - // Skip leading zeroes - var res = this; - for (var i = 0; i < w.length; i++, res = res.sqr()) { - if (w[i] !== 0) break; - } - - if (++i < w.length) { - for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) { - if (w[i] === 0) continue; - - res = res.mul(q); - } - } - - return res; - }; - - // Shift-left in-place - BN.prototype.iushln = function iushln (bits) { - assert(typeof bits === 'number' && bits >= 0); - var r = bits % 26; - var s = (bits - r) / 26; - var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r); - var i; - - if (r !== 0) { - var carry = 0; - - for (i = 0; i < this.length; i++) { - var newCarry = this.words[i] & carryMask; - var c = ((this.words[i] | 0) - newCarry) << r; - this.words[i] = c | carry; - carry = newCarry >>> (26 - r); - } - - if (carry) { - this.words[i] = carry; - this.length++; - } - } - - if (s !== 0) { - for (i = this.length - 1; i >= 0; i--) { - this.words[i + s] = this.words[i]; - } - - for (i = 0; i < s; i++) { - this.words[i] = 0; - } - - this.length += s; - } - - return this.strip(); - }; - - BN.prototype.ishln = function ishln (bits) { - // TODO(indutny): implement me - assert(this.negative === 0); - return this.iushln(bits); - }; - - // Shift-right in-place - // NOTE: `hint` is a lowest bit before trailing zeroes - // NOTE: if `extended` is present - it will be filled with destroyed bits - BN.prototype.iushrn = function iushrn (bits, hint, extended) { - assert(typeof bits === 'number' && bits >= 0); - var h; - if (hint) { - h = (hint - (hint % 26)) / 26; - } else { - h = 0; - } - - var r = bits % 26; - var s = Math.min((bits - r) / 26, this.length); - var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); - var maskedWords = extended; - - h -= s; - h = Math.max(0, h); - - // Extended mode, copy masked part - if (maskedWords) { - for (var i = 0; i < s; i++) { - maskedWords.words[i] = this.words[i]; - } - maskedWords.length = s; - } - - if (s === 0) { - // No-op, we should not move anything at all - } else if (this.length > s) { - this.length -= s; - for (i = 0; i < this.length; i++) { - this.words[i] = this.words[i + s]; - } - } else { - this.words[0] = 0; - this.length = 1; - } - - var carry = 0; - for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) { - var word = this.words[i] | 0; - this.words[i] = (carry << (26 - r)) | (word >>> r); - carry = word & mask; - } - - // Push carried bits as a mask - if (maskedWords && carry !== 0) { - maskedWords.words[maskedWords.length++] = carry; - } - - if (this.length === 0) { - this.words[0] = 0; - this.length = 1; - } - - return this.strip(); - }; - - BN.prototype.ishrn = function ishrn (bits, hint, extended) { - // TODO(indutny): implement me - assert(this.negative === 0); - return this.iushrn(bits, hint, extended); - }; - - // Shift-left - BN.prototype.shln = function shln (bits) { - return this.clone().ishln(bits); - }; - - BN.prototype.ushln = function ushln (bits) { - return this.clone().iushln(bits); - }; - - // Shift-right - BN.prototype.shrn = function shrn (bits) { - return this.clone().ishrn(bits); - }; - - BN.prototype.ushrn = function ushrn (bits) { - return this.clone().iushrn(bits); - }; - - // Test if n bit is set - BN.prototype.testn = function testn (bit) { - assert(typeof bit === 'number' && bit >= 0); - var r = bit % 26; - var s = (bit - r) / 26; - var q = 1 << r; - - // Fast case: bit is much higher than all existing words - if (this.length <= s) return false; - - // Check bit and return - var w = this.words[s]; - - return !!(w & q); - }; - - // Return only lowers bits of number (in-place) - BN.prototype.imaskn = function imaskn (bits) { - assert(typeof bits === 'number' && bits >= 0); - var r = bits % 26; - var s = (bits - r) / 26; - - assert(this.negative === 0, 'imaskn works only with positive numbers'); - - if (this.length <= s) { - return this; - } - - if (r !== 0) { - s++; - } - this.length = Math.min(s, this.length); - - if (r !== 0) { - var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); - this.words[this.length - 1] &= mask; - } - - return this.strip(); - }; - - // Return only lowers bits of number - BN.prototype.maskn = function maskn (bits) { - return this.clone().imaskn(bits); - }; - - // Add plain number `num` to `this` - BN.prototype.iaddn = function iaddn (num) { - assert(typeof num === 'number'); - assert(num < 0x4000000); - if (num < 0) return this.isubn(-num); - - // Possible sign change - if (this.negative !== 0) { - if (this.length === 1 && (this.words[0] | 0) < num) { - this.words[0] = num - (this.words[0] | 0); - this.negative = 0; - return this; - } - - this.negative = 0; - this.isubn(num); - this.negative = 1; - return this; - } - - // Add without checks - return this._iaddn(num); - }; - - BN.prototype._iaddn = function _iaddn (num) { - this.words[0] += num; - - // Carry - for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) { - this.words[i] -= 0x4000000; - if (i === this.length - 1) { - this.words[i + 1] = 1; - } else { - this.words[i + 1]++; - } - } - this.length = Math.max(this.length, i + 1); - - return this; - }; - - // Subtract plain number `num` from `this` - BN.prototype.isubn = function isubn (num) { - assert(typeof num === 'number'); - assert(num < 0x4000000); - if (num < 0) return this.iaddn(-num); - - if (this.negative !== 0) { - this.negative = 0; - this.iaddn(num); - this.negative = 1; - return this; - } - - this.words[0] -= num; - - if (this.length === 1 && this.words[0] < 0) { - this.words[0] = -this.words[0]; - this.negative = 1; - } else { - // Carry - for (var i = 0; i < this.length && this.words[i] < 0; i++) { - this.words[i] += 0x4000000; - this.words[i + 1] -= 1; - } - } - - return this.strip(); - }; - - BN.prototype.addn = function addn (num) { - return this.clone().iaddn(num); - }; - - BN.prototype.subn = function subn (num) { - return this.clone().isubn(num); - }; - - BN.prototype.iabs = function iabs () { - this.negative = 0; - - return this; - }; - - BN.prototype.abs = function abs () { - return this.clone().iabs(); - }; - - BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) { - var len = num.length + shift; - var i; - - this._expand(len); - - var w; - var carry = 0; - for (i = 0; i < num.length; i++) { - w = (this.words[i + shift] | 0) + carry; - var right = (num.words[i] | 0) * mul; - w -= right & 0x3ffffff; - carry = (w >> 26) - ((right / 0x4000000) | 0); - this.words[i + shift] = w & 0x3ffffff; - } - for (; i < this.length - shift; i++) { - w = (this.words[i + shift] | 0) + carry; - carry = w >> 26; - this.words[i + shift] = w & 0x3ffffff; - } - - if (carry === 0) return this.strip(); - - // Subtraction overflow - assert(carry === -1); - carry = 0; - for (i = 0; i < this.length; i++) { - w = -(this.words[i] | 0) + carry; - carry = w >> 26; - this.words[i] = w & 0x3ffffff; - } - this.negative = 1; - - return this.strip(); - }; - - BN.prototype._wordDiv = function _wordDiv (num, mode) { - var shift = this.length - num.length; - - var a = this.clone(); - var b = num; - - // Normalize - var bhi = b.words[b.length - 1] | 0; - var bhiBits = this._countBits(bhi); - shift = 26 - bhiBits; - if (shift !== 0) { - b = b.ushln(shift); - a.iushln(shift); - bhi = b.words[b.length - 1] | 0; - } - - // Initialize quotient - var m = a.length - b.length; - var q; - - if (mode !== 'mod') { - q = new BN(null); - q.length = m + 1; - q.words = new Array(q.length); - for (var i = 0; i < q.length; i++) { - q.words[i] = 0; - } - } - - var diff = a.clone()._ishlnsubmul(b, 1, m); - if (diff.negative === 0) { - a = diff; - if (q) { - q.words[m] = 1; - } - } - - for (var j = m - 1; j >= 0; j--) { - var qj = (a.words[b.length + j] | 0) * 0x4000000 + - (a.words[b.length + j - 1] | 0); - - // NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max - // (0x7ffffff) - qj = Math.min((qj / bhi) | 0, 0x3ffffff); - - a._ishlnsubmul(b, qj, j); - while (a.negative !== 0) { - qj--; - a.negative = 0; - a._ishlnsubmul(b, 1, j); - if (!a.isZero()) { - a.negative ^= 1; - } - } - if (q) { - q.words[j] = qj; - } - } - if (q) { - q.strip(); - } - a.strip(); - - // Denormalize - if (mode !== 'div' && shift !== 0) { - a.iushrn(shift); - } - - return { - div: q || null, - mod: a - }; - }; - - // NOTE: 1) `mode` can be set to `mod` to request mod only, - // to `div` to request div only, or be absent to - // request both div & mod - // 2) `positive` is true if unsigned mod is requested - BN.prototype.divmod = function divmod (num, mode, positive) { - assert(!num.isZero()); - - if (this.isZero()) { - return { - div: new BN(0), - mod: new BN(0) - }; - } - - var div, mod, res; - if (this.negative !== 0 && num.negative === 0) { - res = this.neg().divmod(num, mode); - - if (mode !== 'mod') { - div = res.div.neg(); - } - - if (mode !== 'div') { - mod = res.mod.neg(); - if (positive && mod.negative !== 0) { - mod.iadd(num); - } - } - - return { - div: div, - mod: mod - }; - } - - if (this.negative === 0 && num.negative !== 0) { - res = this.divmod(num.neg(), mode); - - if (mode !== 'mod') { - div = res.div.neg(); - } - - return { - div: div, - mod: res.mod - }; - } - - if ((this.negative & num.negative) !== 0) { - res = this.neg().divmod(num.neg(), mode); - - if (mode !== 'div') { - mod = res.mod.neg(); - if (positive && mod.negative !== 0) { - mod.isub(num); - } - } - - return { - div: res.div, - mod: mod - }; - } - - // Both numbers are positive at this point - - // Strip both numbers to approximate shift value - if (num.length > this.length || this.cmp(num) < 0) { - return { - div: new BN(0), - mod: this - }; - } - - // Very short reduction - if (num.length === 1) { - if (mode === 'div') { - return { - div: this.divn(num.words[0]), - mod: null - }; - } - - if (mode === 'mod') { - return { - div: null, - mod: new BN(this.modn(num.words[0])) - }; - } - - return { - div: this.divn(num.words[0]), - mod: new BN(this.modn(num.words[0])) - }; - } - - return this._wordDiv(num, mode); - }; - - // Find `this` / `num` - BN.prototype.div = function div (num) { - return this.divmod(num, 'div', false).div; - }; - - // Find `this` % `num` - BN.prototype.mod = function mod (num) { - return this.divmod(num, 'mod', false).mod; - }; - - BN.prototype.umod = function umod (num) { - return this.divmod(num, 'mod', true).mod; - }; - - // Find Round(`this` / `num`) - BN.prototype.divRound = function divRound (num) { - var dm = this.divmod(num); - - // Fast case - exact division - if (dm.mod.isZero()) return dm.div; - - var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod; - - var half = num.ushrn(1); - var r2 = num.andln(1); - var cmp = mod.cmp(half); - - // Round down - if (cmp < 0 || r2 === 1 && cmp === 0) return dm.div; - - // Round up - return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1); - }; - - BN.prototype.modn = function modn (num) { - assert(num <= 0x3ffffff); - var p = (1 << 26) % num; - - var acc = 0; - for (var i = this.length - 1; i >= 0; i--) { - acc = (p * acc + (this.words[i] | 0)) % num; - } - - return acc; - }; - - // In-place division by number - BN.prototype.idivn = function idivn (num) { - assert(num <= 0x3ffffff); - - var carry = 0; - for (var i = this.length - 1; i >= 0; i--) { - var w = (this.words[i] | 0) + carry * 0x4000000; - this.words[i] = (w / num) | 0; - carry = w % num; - } - - return this.strip(); - }; - - BN.prototype.divn = function divn (num) { - return this.clone().idivn(num); - }; - - BN.prototype.egcd = function egcd (p) { - assert(p.negative === 0); - assert(!p.isZero()); - - var x = this; - var y = p.clone(); - - if (x.negative !== 0) { - x = x.umod(p); - } else { - x = x.clone(); - } - - // A * x + B * y = x - var A = new BN(1); - var B = new BN(0); - - // C * x + D * y = y - var C = new BN(0); - var D = new BN(1); - - var g = 0; - - while (x.isEven() && y.isEven()) { - x.iushrn(1); - y.iushrn(1); - ++g; - } - - var yp = y.clone(); - var xp = x.clone(); - - while (!x.isZero()) { - for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1); - if (i > 0) { - x.iushrn(i); - while (i-- > 0) { - if (A.isOdd() || B.isOdd()) { - A.iadd(yp); - B.isub(xp); - } - - A.iushrn(1); - B.iushrn(1); - } - } - - for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); - if (j > 0) { - y.iushrn(j); - while (j-- > 0) { - if (C.isOdd() || D.isOdd()) { - C.iadd(yp); - D.isub(xp); - } - - C.iushrn(1); - D.iushrn(1); - } - } - - if (x.cmp(y) >= 0) { - x.isub(y); - A.isub(C); - B.isub(D); - } else { - y.isub(x); - C.isub(A); - D.isub(B); - } - } - - return { - a: C, - b: D, - gcd: y.iushln(g) - }; - }; - - // This is reduced incarnation of the binary EEA - // above, designated to invert members of the - // _prime_ fields F(p) at a maximal speed - BN.prototype._invmp = function _invmp (p) { - assert(p.negative === 0); - assert(!p.isZero()); - - var a = this; - var b = p.clone(); - - if (a.negative !== 0) { - a = a.umod(p); - } else { - a = a.clone(); - } - - var x1 = new BN(1); - var x2 = new BN(0); - - var delta = b.clone(); - - while (a.cmpn(1) > 0 && b.cmpn(1) > 0) { - for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1); - if (i > 0) { - a.iushrn(i); - while (i-- > 0) { - if (x1.isOdd()) { - x1.iadd(delta); - } - - x1.iushrn(1); - } - } - - for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); - if (j > 0) { - b.iushrn(j); - while (j-- > 0) { - if (x2.isOdd()) { - x2.iadd(delta); - } - - x2.iushrn(1); - } - } - - if (a.cmp(b) >= 0) { - a.isub(b); - x1.isub(x2); - } else { - b.isub(a); - x2.isub(x1); - } - } - - var res; - if (a.cmpn(1) === 0) { - res = x1; - } else { - res = x2; - } - - if (res.cmpn(0) < 0) { - res.iadd(p); - } - - return res; - }; - - BN.prototype.gcd = function gcd (num) { - if (this.isZero()) return num.abs(); - if (num.isZero()) return this.abs(); - - var a = this.clone(); - var b = num.clone(); - a.negative = 0; - b.negative = 0; - - // Remove common factor of two - for (var shift = 0; a.isEven() && b.isEven(); shift++) { - a.iushrn(1); - b.iushrn(1); - } - - do { - while (a.isEven()) { - a.iushrn(1); - } - while (b.isEven()) { - b.iushrn(1); - } - - var r = a.cmp(b); - if (r < 0) { - // Swap `a` and `b` to make `a` always bigger than `b` - var t = a; - a = b; - b = t; - } else if (r === 0 || b.cmpn(1) === 0) { - break; - } - - a.isub(b); - } while (true); - - return b.iushln(shift); - }; - - // Invert number in the field F(num) - BN.prototype.invm = function invm (num) { - return this.egcd(num).a.umod(num); - }; - - BN.prototype.isEven = function isEven () { - return (this.words[0] & 1) === 0; - }; - - BN.prototype.isOdd = function isOdd () { - return (this.words[0] & 1) === 1; - }; - - // And first word and num - BN.prototype.andln = function andln (num) { - return this.words[0] & num; - }; - - // Increment at the bit position in-line - BN.prototype.bincn = function bincn (bit) { - assert(typeof bit === 'number'); - var r = bit % 26; - var s = (bit - r) / 26; - var q = 1 << r; - - // Fast case: bit is much higher than all existing words - if (this.length <= s) { - this._expand(s + 1); - this.words[s] |= q; - return this; - } - - // Add bit and propagate, if needed - var carry = q; - for (var i = s; carry !== 0 && i < this.length; i++) { - var w = this.words[i] | 0; - w += carry; - carry = w >>> 26; - w &= 0x3ffffff; - this.words[i] = w; - } - if (carry !== 0) { - this.words[i] = carry; - this.length++; - } - return this; - }; - - BN.prototype.isZero = function isZero () { - return this.length === 1 && this.words[0] === 0; - }; - - BN.prototype.cmpn = function cmpn (num) { - var negative = num < 0; - - if (this.negative !== 0 && !negative) return -1; - if (this.negative === 0 && negative) return 1; - - this.strip(); - - var res; - if (this.length > 1) { - res = 1; - } else { - if (negative) { - num = -num; - } - - assert(num <= 0x3ffffff, 'Number is too big'); - - var w = this.words[0] | 0; - res = w === num ? 0 : w < num ? -1 : 1; - } - if (this.negative !== 0) return -res | 0; - return res; - }; - - // Compare two numbers and return: - // 1 - if `this` > `num` - // 0 - if `this` == `num` - // -1 - if `this` < `num` - BN.prototype.cmp = function cmp (num) { - if (this.negative !== 0 && num.negative === 0) return -1; - if (this.negative === 0 && num.negative !== 0) return 1; - - var res = this.ucmp(num); - if (this.negative !== 0) return -res | 0; - return res; - }; - - // Unsigned comparison - BN.prototype.ucmp = function ucmp (num) { - // At this point both numbers have the same sign - if (this.length > num.length) return 1; - if (this.length < num.length) return -1; - - var res = 0; - for (var i = this.length - 1; i >= 0; i--) { - var a = this.words[i] | 0; - var b = num.words[i] | 0; - - if (a === b) continue; - if (a < b) { - res = -1; - } else if (a > b) { - res = 1; - } - break; - } - return res; - }; - - BN.prototype.gtn = function gtn (num) { - return this.cmpn(num) === 1; - }; - - BN.prototype.gt = function gt (num) { - return this.cmp(num) === 1; - }; - - BN.prototype.gten = function gten (num) { - return this.cmpn(num) >= 0; - }; - - BN.prototype.gte = function gte (num) { - return this.cmp(num) >= 0; - }; - - BN.prototype.ltn = function ltn (num) { - return this.cmpn(num) === -1; - }; - - BN.prototype.lt = function lt (num) { - return this.cmp(num) === -1; - }; - - BN.prototype.lten = function lten (num) { - return this.cmpn(num) <= 0; - }; - - BN.prototype.lte = function lte (num) { - return this.cmp(num) <= 0; - }; - - BN.prototype.eqn = function eqn (num) { - return this.cmpn(num) === 0; - }; - - BN.prototype.eq = function eq (num) { - return this.cmp(num) === 0; - }; - - // - // A reduce context, could be using montgomery or something better, depending - // on the `m` itself. - // - BN.red = function red (num) { - return new Red(num); - }; - - BN.prototype.toRed = function toRed (ctx) { - assert(!this.red, 'Already a number in reduction context'); - assert(this.negative === 0, 'red works only with positives'); - return ctx.convertTo(this)._forceRed(ctx); - }; - - BN.prototype.fromRed = function fromRed () { - assert(this.red, 'fromRed works only with numbers in reduction context'); - return this.red.convertFrom(this); - }; - - BN.prototype._forceRed = function _forceRed (ctx) { - this.red = ctx; - return this; - }; - - BN.prototype.forceRed = function forceRed (ctx) { - assert(!this.red, 'Already a number in reduction context'); - return this._forceRed(ctx); - }; - - BN.prototype.redAdd = function redAdd (num) { - assert(this.red, 'redAdd works only with red numbers'); - return this.red.add(this, num); - }; - - BN.prototype.redIAdd = function redIAdd (num) { - assert(this.red, 'redIAdd works only with red numbers'); - return this.red.iadd(this, num); - }; - - BN.prototype.redSub = function redSub (num) { - assert(this.red, 'redSub works only with red numbers'); - return this.red.sub(this, num); - }; - - BN.prototype.redISub = function redISub (num) { - assert(this.red, 'redISub works only with red numbers'); - return this.red.isub(this, num); - }; - - BN.prototype.redShl = function redShl (num) { - assert(this.red, 'redShl works only with red numbers'); - return this.red.shl(this, num); - }; - - BN.prototype.redMul = function redMul (num) { - assert(this.red, 'redMul works only with red numbers'); - this.red._verify2(this, num); - return this.red.mul(this, num); - }; - - BN.prototype.redIMul = function redIMul (num) { - assert(this.red, 'redMul works only with red numbers'); - this.red._verify2(this, num); - return this.red.imul(this, num); - }; - - BN.prototype.redSqr = function redSqr () { - assert(this.red, 'redSqr works only with red numbers'); - this.red._verify1(this); - return this.red.sqr(this); - }; - - BN.prototype.redISqr = function redISqr () { - assert(this.red, 'redISqr works only with red numbers'); - this.red._verify1(this); - return this.red.isqr(this); - }; - - // Square root over p - BN.prototype.redSqrt = function redSqrt () { - assert(this.red, 'redSqrt works only with red numbers'); - this.red._verify1(this); - return this.red.sqrt(this); - }; - - BN.prototype.redInvm = function redInvm () { - assert(this.red, 'redInvm works only with red numbers'); - this.red._verify1(this); - return this.red.invm(this); - }; - - // Return negative clone of `this` % `red modulo` - BN.prototype.redNeg = function redNeg () { - assert(this.red, 'redNeg works only with red numbers'); - this.red._verify1(this); - return this.red.neg(this); - }; - - BN.prototype.redPow = function redPow (num) { - assert(this.red && !num.red, 'redPow(normalNum)'); - this.red._verify1(this); - return this.red.pow(this, num); - }; - - // Prime numbers with efficient reduction - var primes = { - k256: null, - p224: null, - p192: null, - p25519: null - }; - - // Pseudo-Mersenne prime - function MPrime (name, p) { - // P = 2 ^ N - K - this.name = name; - this.p = new BN(p, 16); - this.n = this.p.bitLength(); - this.k = new BN(1).iushln(this.n).isub(this.p); - - this.tmp = this._tmp(); - } - - MPrime.prototype._tmp = function _tmp () { - var tmp = new BN(null); - tmp.words = new Array(Math.ceil(this.n / 13)); - return tmp; - }; - - MPrime.prototype.ireduce = function ireduce (num) { - // Assumes that `num` is less than `P^2` - // num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P) - var r = num; - var rlen; - - do { - this.split(r, this.tmp); - r = this.imulK(r); - r = r.iadd(this.tmp); - rlen = r.bitLength(); - } while (rlen > this.n); - - var cmp = rlen < this.n ? -1 : r.ucmp(this.p); - if (cmp === 0) { - r.words[0] = 0; - r.length = 1; - } else if (cmp > 0) { - r.isub(this.p); - } else { - r.strip(); - } - - return r; - }; - - MPrime.prototype.split = function split (input, out) { - input.iushrn(this.n, 0, out); - }; - - MPrime.prototype.imulK = function imulK (num) { - return num.imul(this.k); - }; - - function K256 () { - MPrime.call( - this, - 'k256', - 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f'); - } - inherits(K256, MPrime); - - K256.prototype.split = function split (input, output) { - // 256 = 9 * 26 + 22 - var mask = 0x3fffff; - - var outLen = Math.min(input.length, 9); - for (var i = 0; i < outLen; i++) { - output.words[i] = input.words[i]; - } - output.length = outLen; - - if (input.length <= 9) { - input.words[0] = 0; - input.length = 1; - return; - } - - // Shift by 9 limbs - var prev = input.words[9]; - output.words[output.length++] = prev & mask; - - for (i = 10; i < input.length; i++) { - var next = input.words[i] | 0; - input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22); - prev = next; - } - prev >>>= 22; - input.words[i - 10] = prev; - if (prev === 0 && input.length > 10) { - input.length -= 10; - } else { - input.length -= 9; - } - }; - - K256.prototype.imulK = function imulK (num) { - // K = 0x1000003d1 = [ 0x40, 0x3d1 ] - num.words[num.length] = 0; - num.words[num.length + 1] = 0; - num.length += 2; - - // bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390 - var lo = 0; - for (var i = 0; i < num.length; i++) { - var w = num.words[i] | 0; - lo += w * 0x3d1; - num.words[i] = lo & 0x3ffffff; - lo = w * 0x40 + ((lo / 0x4000000) | 0); - } - - // Fast length reduction - if (num.words[num.length - 1] === 0) { - num.length--; - if (num.words[num.length - 1] === 0) { - num.length--; - } - } - return num; - }; - - function P224 () { - MPrime.call( - this, - 'p224', - 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001'); - } - inherits(P224, MPrime); - - function P192 () { - MPrime.call( - this, - 'p192', - 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff'); - } - inherits(P192, MPrime); - - function P25519 () { - // 2 ^ 255 - 19 - MPrime.call( - this, - '25519', - '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed'); - } - inherits(P25519, MPrime); - - P25519.prototype.imulK = function imulK (num) { - // K = 0x13 - var carry = 0; - for (var i = 0; i < num.length; i++) { - var hi = (num.words[i] | 0) * 0x13 + carry; - var lo = hi & 0x3ffffff; - hi >>>= 26; - - num.words[i] = lo; - carry = hi; - } - if (carry !== 0) { - num.words[num.length++] = carry; - } - return num; - }; - - // Exported mostly for testing purposes, use plain name instead - BN._prime = function prime (name) { - // Cached version of prime - if (primes[name]) return primes[name]; - - var prime; - if (name === 'k256') { - prime = new K256(); - } else if (name === 'p224') { - prime = new P224(); - } else if (name === 'p192') { - prime = new P192(); - } else if (name === 'p25519') { - prime = new P25519(); - } else { - throw new Error('Unknown prime ' + name); - } - primes[name] = prime; - - return prime; - }; - - // - // Base reduction engine - // - function Red (m) { - if (typeof m === 'string') { - var prime = BN._prime(m); - this.m = prime.p; - this.prime = prime; - } else { - assert(m.gtn(1), 'modulus must be greater than 1'); - this.m = m; - this.prime = null; - } - } - - Red.prototype._verify1 = function _verify1 (a) { - assert(a.negative === 0, 'red works only with positives'); - assert(a.red, 'red works only with red numbers'); - }; - - Red.prototype._verify2 = function _verify2 (a, b) { - assert((a.negative | b.negative) === 0, 'red works only with positives'); - assert(a.red && a.red === b.red, - 'red works only with red numbers'); - }; - - Red.prototype.imod = function imod (a) { - if (this.prime) return this.prime.ireduce(a)._forceRed(this); - return a.umod(this.m)._forceRed(this); - }; - - Red.prototype.neg = function neg (a) { - if (a.isZero()) { - return a.clone(); - } - - return this.m.sub(a)._forceRed(this); - }; - - Red.prototype.add = function add (a, b) { - this._verify2(a, b); - - var res = a.add(b); - if (res.cmp(this.m) >= 0) { - res.isub(this.m); - } - return res._forceRed(this); - }; - - Red.prototype.iadd = function iadd (a, b) { - this._verify2(a, b); - - var res = a.iadd(b); - if (res.cmp(this.m) >= 0) { - res.isub(this.m); - } - return res; - }; - - Red.prototype.sub = function sub (a, b) { - this._verify2(a, b); - - var res = a.sub(b); - if (res.cmpn(0) < 0) { - res.iadd(this.m); - } - return res._forceRed(this); - }; - - Red.prototype.isub = function isub (a, b) { - this._verify2(a, b); - - var res = a.isub(b); - if (res.cmpn(0) < 0) { - res.iadd(this.m); - } - return res; - }; - - Red.prototype.shl = function shl (a, num) { - this._verify1(a); - return this.imod(a.ushln(num)); - }; - - Red.prototype.imul = function imul (a, b) { - this._verify2(a, b); - return this.imod(a.imul(b)); - }; - - Red.prototype.mul = function mul (a, b) { - this._verify2(a, b); - return this.imod(a.mul(b)); - }; - - Red.prototype.isqr = function isqr (a) { - return this.imul(a, a.clone()); - }; - - Red.prototype.sqr = function sqr (a) { - return this.mul(a, a); - }; - - Red.prototype.sqrt = function sqrt (a) { - if (a.isZero()) return a.clone(); - - var mod3 = this.m.andln(3); - assert(mod3 % 2 === 1); - - // Fast case - if (mod3 === 3) { - var pow = this.m.add(new BN(1)).iushrn(2); - return this.pow(a, pow); - } - - // Tonelli-Shanks algorithm (Totally unoptimized and slow) - // - // Find Q and S, that Q * 2 ^ S = (P - 1) - var q = this.m.subn(1); - var s = 0; - while (!q.isZero() && q.andln(1) === 0) { - s++; - q.iushrn(1); - } - assert(!q.isZero()); - - var one = new BN(1).toRed(this); - var nOne = one.redNeg(); - - // Find quadratic non-residue - // NOTE: Max is such because of generalized Riemann hypothesis. - var lpow = this.m.subn(1).iushrn(1); - var z = this.m.bitLength(); - z = new BN(2 * z * z).toRed(this); - - while (this.pow(z, lpow).cmp(nOne) !== 0) { - z.redIAdd(nOne); - } - - var c = this.pow(z, q); - var r = this.pow(a, q.addn(1).iushrn(1)); - var t = this.pow(a, q); - var m = s; - while (t.cmp(one) !== 0) { - var tmp = t; - for (var i = 0; tmp.cmp(one) !== 0; i++) { - tmp = tmp.redSqr(); - } - assert(i < m); - var b = this.pow(c, new BN(1).iushln(m - i - 1)); - - r = r.redMul(b); - c = b.redSqr(); - t = t.redMul(c); - m = i; - } - - return r; - }; - - Red.prototype.invm = function invm (a) { - var inv = a._invmp(this.m); - if (inv.negative !== 0) { - inv.negative = 0; - return this.imod(inv).redNeg(); - } else { - return this.imod(inv); - } - }; - - Red.prototype.pow = function pow (a, num) { - if (num.isZero()) return new BN(1).toRed(this); - if (num.cmpn(1) === 0) return a.clone(); - - var windowSize = 4; - var wnd = new Array(1 << windowSize); - wnd[0] = new BN(1).toRed(this); - wnd[1] = a; - for (var i = 2; i < wnd.length; i++) { - wnd[i] = this.mul(wnd[i - 1], a); - } - - var res = wnd[0]; - var current = 0; - var currentLen = 0; - var start = num.bitLength() % 26; - if (start === 0) { - start = 26; - } - - for (i = num.length - 1; i >= 0; i--) { - var word = num.words[i]; - for (var j = start - 1; j >= 0; j--) { - var bit = (word >> j) & 1; - if (res !== wnd[0]) { - res = this.sqr(res); - } - - if (bit === 0 && current === 0) { - currentLen = 0; - continue; - } - - current <<= 1; - current |= bit; - currentLen++; - if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue; - - res = this.mul(res, wnd[current]); - currentLen = 0; - current = 0; - } - start = 26; - } - - return res; - }; - - Red.prototype.convertTo = function convertTo (num) { - var r = num.umod(this.m); - - return r === num ? r.clone() : r; - }; - - Red.prototype.convertFrom = function convertFrom (num) { - var res = num.clone(); - res.red = null; - return res; - }; - - // - // Montgomery method engine - // - - BN.mont = function mont (num) { - return new Mont(num); - }; - - function Mont (m) { - Red.call(this, m); - - this.shift = this.m.bitLength(); - if (this.shift % 26 !== 0) { - this.shift += 26 - (this.shift % 26); - } - - this.r = new BN(1).iushln(this.shift); - this.r2 = this.imod(this.r.sqr()); - this.rinv = this.r._invmp(this.m); - - this.minv = this.rinv.mul(this.r).isubn(1).div(this.m); - this.minv = this.minv.umod(this.r); - this.minv = this.r.sub(this.minv); - } - inherits(Mont, Red); - - Mont.prototype.convertTo = function convertTo (num) { - return this.imod(num.ushln(this.shift)); - }; - - Mont.prototype.convertFrom = function convertFrom (num) { - var r = this.imod(num.mul(this.rinv)); - r.red = null; - return r; - }; - - Mont.prototype.imul = function imul (a, b) { - if (a.isZero() || b.isZero()) { - a.words[0] = 0; - a.length = 1; - return a; - } - - var t = a.imul(b); - var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); - var u = t.isub(c).iushrn(this.shift); - var res = u; - - if (u.cmp(this.m) >= 0) { - res = u.isub(this.m); - } else if (u.cmpn(0) < 0) { - res = u.iadd(this.m); - } - - return res._forceRed(this); - }; - - Mont.prototype.mul = function mul (a, b) { - if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this); - - var t = a.mul(b); - var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); - var u = t.isub(c).iushrn(this.shift); - var res = u; - if (u.cmp(this.m) >= 0) { - res = u.isub(this.m); - } else if (u.cmpn(0) < 0) { - res = u.iadd(this.m); - } - - return res._forceRed(this); - }; - - Mont.prototype.invm = function invm (a) { - // (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R - var res = this.imod(a._invmp(this.m).mul(this.r2)); - return res._forceRed(this); - }; -})(typeof module === 'undefined' || module, this); - -},{"buffer":"buffer"}],17:[function(require,module,exports){ -var r; - -module.exports = function rand(len) { - if (!r) - r = new Rand(null); - - return r.generate(len); -}; - -function Rand(rand) { - this.rand = rand; -} -module.exports.Rand = Rand; - -Rand.prototype.generate = function generate(len) { - return this._rand(len); -}; - -// Emulate crypto API using randy -Rand.prototype._rand = function _rand(n) { - if (this.rand.getBytes) - return this.rand.getBytes(n); - - var res = new Uint8Array(n); - for (var i = 0; i < res.length; i++) - res[i] = this.rand.getByte(); - return res; -}; - -if (typeof self === 'object') { - if (self.crypto && self.crypto.getRandomValues) { - // Modern browsers - Rand.prototype._rand = function _rand(n) { - var arr = new Uint8Array(n); - self.crypto.getRandomValues(arr); - return arr; - }; - } else if (self.msCrypto && self.msCrypto.getRandomValues) { - // IE - Rand.prototype._rand = function _rand(n) { - var arr = new Uint8Array(n); - self.msCrypto.getRandomValues(arr); - return arr; - }; - - // Safari's WebWorkers do not have `crypto` - } else if (typeof window === 'object') { - // Old junk - Rand.prototype._rand = function() { - throw new Error('Not implemented yet'); - }; - } -} else { - // Node.js or Web worker with no crypto support - try { - var crypto = require('crypto'); - if (typeof crypto.randomBytes !== 'function') - throw new Error('Not supported'); - - Rand.prototype._rand = function _rand(n) { - return crypto.randomBytes(n); - }; - } catch (e) { - } -} - -},{"crypto":"crypto"}],18:[function(require,module,exports){ -'use strict'; - -var elliptic = exports; - -elliptic.utils = require('./elliptic/utils'); -elliptic.rand = require('brorand'); -elliptic.curve = require('./elliptic/curve'); -elliptic.curves = require('./elliptic/curves'); - -// Protocols -elliptic.ec = require('./elliptic/ec'); -elliptic.eddsa = require('./elliptic/eddsa'); - -},{"./elliptic/curve":21,"./elliptic/curves":24,"./elliptic/ec":25,"./elliptic/eddsa":28,"./elliptic/utils":32,"brorand":17}],19:[function(require,module,exports){ -'use strict'; - -var BN = require('bn.js'); -var elliptic = require('../../elliptic'); -var utils = elliptic.utils; -var getNAF = utils.getNAF; -var getJSF = utils.getJSF; -var assert = utils.assert; - -function BaseCurve(type, conf) { - this.type = type; - this.p = new BN(conf.p, 16); - - // Use Montgomery, when there is no fast reduction for the prime - this.red = conf.prime ? BN.red(conf.prime) : BN.mont(this.p); - - // Useful for many curves - this.zero = new BN(0).toRed(this.red); - this.one = new BN(1).toRed(this.red); - this.two = new BN(2).toRed(this.red); - - // Curve configuration, optional - this.n = conf.n && new BN(conf.n, 16); - this.g = conf.g && this.pointFromJSON(conf.g, conf.gRed); - - // Temporary arrays - this._wnafT1 = new Array(4); - this._wnafT2 = new Array(4); - this._wnafT3 = new Array(4); - this._wnafT4 = new Array(4); - - // Generalized Greg Maxwell's trick - var adjustCount = this.n && this.p.div(this.n); - if (!adjustCount || adjustCount.cmpn(100) > 0) { - this.redN = null; - } else { - this._maxwellTrick = true; - this.redN = this.n.toRed(this.red); - } -} -module.exports = BaseCurve; - -BaseCurve.prototype.point = function point() { - throw new Error('Not implemented'); -}; - -BaseCurve.prototype.validate = function validate() { - throw new Error('Not implemented'); -}; - -BaseCurve.prototype._fixedNafMul = function _fixedNafMul(p, k) { - assert(p.precomputed); - var doubles = p._getDoubles(); - - var naf = getNAF(k, 1); - var I = (1 << (doubles.step + 1)) - (doubles.step % 2 === 0 ? 2 : 1); - I /= 3; - - // Translate into more windowed form - var repr = []; - for (var j = 0; j < naf.length; j += doubles.step) { - var nafW = 0; - for (var k = j + doubles.step - 1; k >= j; k--) - nafW = (nafW << 1) + naf[k]; - repr.push(nafW); - } - - var a = this.jpoint(null, null, null); - var b = this.jpoint(null, null, null); - for (var i = I; i > 0; i--) { - for (var j = 0; j < repr.length; j++) { - var nafW = repr[j]; - if (nafW === i) - b = b.mixedAdd(doubles.points[j]); - else if (nafW === -i) - b = b.mixedAdd(doubles.points[j].neg()); - } - a = a.add(b); - } - return a.toP(); -}; - -BaseCurve.prototype._wnafMul = function _wnafMul(p, k) { - var w = 4; - - // Precompute window - var nafPoints = p._getNAFPoints(w); - w = nafPoints.wnd; - var wnd = nafPoints.points; - - // Get NAF form - var naf = getNAF(k, w); - - // Add `this`*(N+1) for every w-NAF index - var acc = this.jpoint(null, null, null); - for (var i = naf.length - 1; i >= 0; i--) { - // Count zeroes - for (var k = 0; i >= 0 && naf[i] === 0; i--) - k++; - if (i >= 0) - k++; - acc = acc.dblp(k); - - if (i < 0) - break; - var z = naf[i]; - assert(z !== 0); - if (p.type === 'affine') { - // J +- P - if (z > 0) - acc = acc.mixedAdd(wnd[(z - 1) >> 1]); - else - acc = acc.mixedAdd(wnd[(-z - 1) >> 1].neg()); - } else { - // J +- J - if (z > 0) - acc = acc.add(wnd[(z - 1) >> 1]); - else - acc = acc.add(wnd[(-z - 1) >> 1].neg()); - } - } - return p.type === 'affine' ? acc.toP() : acc; -}; - -BaseCurve.prototype._wnafMulAdd = function _wnafMulAdd(defW, - points, - coeffs, - len, - jacobianResult) { - var wndWidth = this._wnafT1; - var wnd = this._wnafT2; - var naf = this._wnafT3; - - // Fill all arrays - var max = 0; - for (var i = 0; i < len; i++) { - var p = points[i]; - var nafPoints = p._getNAFPoints(defW); - wndWidth[i] = nafPoints.wnd; - wnd[i] = nafPoints.points; - } - - // Comb small window NAFs - for (var i = len - 1; i >= 1; i -= 2) { - var a = i - 1; - var b = i; - if (wndWidth[a] !== 1 || wndWidth[b] !== 1) { - naf[a] = getNAF(coeffs[a], wndWidth[a]); - naf[b] = getNAF(coeffs[b], wndWidth[b]); - max = Math.max(naf[a].length, max); - max = Math.max(naf[b].length, max); - continue; - } - - var comb = [ - points[a], /* 1 */ - null, /* 3 */ - null, /* 5 */ - points[b] /* 7 */ - ]; - - // Try to avoid Projective points, if possible - if (points[a].y.cmp(points[b].y) === 0) { - comb[1] = points[a].add(points[b]); - comb[2] = points[a].toJ().mixedAdd(points[b].neg()); - } else if (points[a].y.cmp(points[b].y.redNeg()) === 0) { - comb[1] = points[a].toJ().mixedAdd(points[b]); - comb[2] = points[a].add(points[b].neg()); - } else { - comb[1] = points[a].toJ().mixedAdd(points[b]); - comb[2] = points[a].toJ().mixedAdd(points[b].neg()); - } - - var index = [ - -3, /* -1 -1 */ - -1, /* -1 0 */ - -5, /* -1 1 */ - -7, /* 0 -1 */ - 0, /* 0 0 */ - 7, /* 0 1 */ - 5, /* 1 -1 */ - 1, /* 1 0 */ - 3 /* 1 1 */ - ]; - - var jsf = getJSF(coeffs[a], coeffs[b]); - max = Math.max(jsf[0].length, max); - naf[a] = new Array(max); - naf[b] = new Array(max); - for (var j = 0; j < max; j++) { - var ja = jsf[0][j] | 0; - var jb = jsf[1][j] | 0; - - naf[a][j] = index[(ja + 1) * 3 + (jb + 1)]; - naf[b][j] = 0; - wnd[a] = comb; - } - } - - var acc = this.jpoint(null, null, null); - var tmp = this._wnafT4; - for (var i = max; i >= 0; i--) { - var k = 0; - - while (i >= 0) { - var zero = true; - for (var j = 0; j < len; j++) { - tmp[j] = naf[j][i] | 0; - if (tmp[j] !== 0) - zero = false; - } - if (!zero) - break; - k++; - i--; - } - if (i >= 0) - k++; - acc = acc.dblp(k); - if (i < 0) - break; - - for (var j = 0; j < len; j++) { - var z = tmp[j]; - var p; - if (z === 0) - continue; - else if (z > 0) - p = wnd[j][(z - 1) >> 1]; - else if (z < 0) - p = wnd[j][(-z - 1) >> 1].neg(); - - if (p.type === 'affine') - acc = acc.mixedAdd(p); - else - acc = acc.add(p); - } - } - // Zeroify references - for (var i = 0; i < len; i++) - wnd[i] = null; - - if (jacobianResult) - return acc; - else - return acc.toP(); -}; - -function BasePoint(curve, type) { - this.curve = curve; - this.type = type; - this.precomputed = null; -} -BaseCurve.BasePoint = BasePoint; - -BasePoint.prototype.eq = function eq(/*other*/) { - throw new Error('Not implemented'); -}; - -BasePoint.prototype.validate = function validate() { - return this.curve.validate(this); -}; - -BaseCurve.prototype.decodePoint = function decodePoint(bytes, enc) { - bytes = utils.toArray(bytes, enc); - - var len = this.p.byteLength(); - - // uncompressed, hybrid-odd, hybrid-even - if ((bytes[0] === 0x04 || bytes[0] === 0x06 || bytes[0] === 0x07) && - bytes.length - 1 === 2 * len) { - if (bytes[0] === 0x06) - assert(bytes[bytes.length - 1] % 2 === 0); - else if (bytes[0] === 0x07) - assert(bytes[bytes.length - 1] % 2 === 1); - - var res = this.point(bytes.slice(1, 1 + len), - bytes.slice(1 + len, 1 + 2 * len)); - - return res; - } else if ((bytes[0] === 0x02 || bytes[0] === 0x03) && - bytes.length - 1 === len) { - return this.pointFromX(bytes.slice(1, 1 + len), bytes[0] === 0x03); - } - throw new Error('Unknown point format'); -}; - -BasePoint.prototype.encodeCompressed = function encodeCompressed(enc) { - return this.encode(enc, true); -}; - -BasePoint.prototype._encode = function _encode(compact) { - var len = this.curve.p.byteLength(); - var x = this.getX().toArray('be', len); - - if (compact) - return [ this.getY().isEven() ? 0x02 : 0x03 ].concat(x); - - return [ 0x04 ].concat(x, this.getY().toArray('be', len)) ; -}; - -BasePoint.prototype.encode = function encode(enc, compact) { - return utils.encode(this._encode(compact), enc); -}; - -BasePoint.prototype.precompute = function precompute(power) { - if (this.precomputed) - return this; - - var precomputed = { - doubles: null, - naf: null, - beta: null - }; - precomputed.naf = this._getNAFPoints(8); - precomputed.doubles = this._getDoubles(4, power); - precomputed.beta = this._getBeta(); - this.precomputed = precomputed; - - return this; -}; - -BasePoint.prototype._hasDoubles = function _hasDoubles(k) { - if (!this.precomputed) - return false; - - var doubles = this.precomputed.doubles; - if (!doubles) - return false; - - return doubles.points.length >= Math.ceil((k.bitLength() + 1) / doubles.step); -}; - -BasePoint.prototype._getDoubles = function _getDoubles(step, power) { - if (this.precomputed && this.precomputed.doubles) - return this.precomputed.doubles; - - var doubles = [ this ]; - var acc = this; - for (var i = 0; i < power; i += step) { - for (var j = 0; j < step; j++) - acc = acc.dbl(); - doubles.push(acc); - } - return { - step: step, - points: doubles - }; -}; - -BasePoint.prototype._getNAFPoints = function _getNAFPoints(wnd) { - if (this.precomputed && this.precomputed.naf) - return this.precomputed.naf; - - var res = [ this ]; - var max = (1 << wnd) - 1; - var dbl = max === 1 ? null : this.dbl(); - for (var i = 1; i < max; i++) - res[i] = res[i - 1].add(dbl); - return { - wnd: wnd, - points: res - }; -}; - -BasePoint.prototype._getBeta = function _getBeta() { - return null; -}; - -BasePoint.prototype.dblp = function dblp(k) { - var r = this; - for (var i = 0; i < k; i++) - r = r.dbl(); - return r; -}; - -},{"../../elliptic":18,"bn.js":16}],20:[function(require,module,exports){ -'use strict'; - -var curve = require('../curve'); -var elliptic = require('../../elliptic'); -var BN = require('bn.js'); -var inherits = require('inherits'); -var Base = curve.base; - -var assert = elliptic.utils.assert; - -function EdwardsCurve(conf) { - // NOTE: Important as we are creating point in Base.call() - this.twisted = (conf.a | 0) !== 1; - this.mOneA = this.twisted && (conf.a | 0) === -1; - this.extended = this.mOneA; - - Base.call(this, 'edwards', conf); - - this.a = new BN(conf.a, 16).umod(this.red.m); - this.a = this.a.toRed(this.red); - this.c = new BN(conf.c, 16).toRed(this.red); - this.c2 = this.c.redSqr(); - this.d = new BN(conf.d, 16).toRed(this.red); - this.dd = this.d.redAdd(this.d); - - assert(!this.twisted || this.c.fromRed().cmpn(1) === 0); - this.oneC = (conf.c | 0) === 1; -} -inherits(EdwardsCurve, Base); -module.exports = EdwardsCurve; - -EdwardsCurve.prototype._mulA = function _mulA(num) { - if (this.mOneA) - return num.redNeg(); - else - return this.a.redMul(num); -}; - -EdwardsCurve.prototype._mulC = function _mulC(num) { - if (this.oneC) - return num; - else - return this.c.redMul(num); -}; - -// Just for compatibility with Short curve -EdwardsCurve.prototype.jpoint = function jpoint(x, y, z, t) { - return this.point(x, y, z, t); -}; - -EdwardsCurve.prototype.pointFromX = function pointFromX(x, odd) { - x = new BN(x, 16); - if (!x.red) - x = x.toRed(this.red); - - var x2 = x.redSqr(); - var rhs = this.c2.redSub(this.a.redMul(x2)); - var lhs = this.one.redSub(this.c2.redMul(this.d).redMul(x2)); - - var y2 = rhs.redMul(lhs.redInvm()); - var y = y2.redSqrt(); - if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) - throw new Error('invalid point'); - - var isOdd = y.fromRed().isOdd(); - if (odd && !isOdd || !odd && isOdd) - y = y.redNeg(); - - return this.point(x, y); -}; - -EdwardsCurve.prototype.pointFromY = function pointFromY(y, odd) { - y = new BN(y, 16); - if (!y.red) - y = y.toRed(this.red); - - // x^2 = (y^2 - c^2) / (c^2 d y^2 - a) - var y2 = y.redSqr(); - var lhs = y2.redSub(this.c2); - var rhs = y2.redMul(this.d).redMul(this.c2).redSub(this.a); - var x2 = lhs.redMul(rhs.redInvm()); - - if (x2.cmp(this.zero) === 0) { - if (odd) - throw new Error('invalid point'); - else - return this.point(this.zero, y); - } - - var x = x2.redSqrt(); - if (x.redSqr().redSub(x2).cmp(this.zero) !== 0) - throw new Error('invalid point'); - - if (x.fromRed().isOdd() !== odd) - x = x.redNeg(); - - return this.point(x, y); -}; - -EdwardsCurve.prototype.validate = function validate(point) { - if (point.isInfinity()) - return true; - - // Curve: A * X^2 + Y^2 = C^2 * (1 + D * X^2 * Y^2) - point.normalize(); - - var x2 = point.x.redSqr(); - var y2 = point.y.redSqr(); - var lhs = x2.redMul(this.a).redAdd(y2); - var rhs = this.c2.redMul(this.one.redAdd(this.d.redMul(x2).redMul(y2))); - - return lhs.cmp(rhs) === 0; -}; - -function Point(curve, x, y, z, t) { - Base.BasePoint.call(this, curve, 'projective'); - if (x === null && y === null && z === null) { - this.x = this.curve.zero; - this.y = this.curve.one; - this.z = this.curve.one; - this.t = this.curve.zero; - this.zOne = true; - } else { - this.x = new BN(x, 16); - this.y = new BN(y, 16); - this.z = z ? new BN(z, 16) : this.curve.one; - this.t = t && new BN(t, 16); - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.y.red) - this.y = this.y.toRed(this.curve.red); - if (!this.z.red) - this.z = this.z.toRed(this.curve.red); - if (this.t && !this.t.red) - this.t = this.t.toRed(this.curve.red); - this.zOne = this.z === this.curve.one; - - // Use extended coordinates - if (this.curve.extended && !this.t) { - this.t = this.x.redMul(this.y); - if (!this.zOne) - this.t = this.t.redMul(this.z.redInvm()); - } - } -} -inherits(Point, Base.BasePoint); - -EdwardsCurve.prototype.pointFromJSON = function pointFromJSON(obj) { - return Point.fromJSON(this, obj); -}; - -EdwardsCurve.prototype.point = function point(x, y, z, t) { - return new Point(this, x, y, z, t); -}; - -Point.fromJSON = function fromJSON(curve, obj) { - return new Point(curve, obj[0], obj[1], obj[2]); -}; - -Point.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; -}; - -Point.prototype.isInfinity = function isInfinity() { - // XXX This code assumes that zero is always zero in red - return this.x.cmpn(0) === 0 && - (this.y.cmp(this.z) === 0 || - (this.zOne && this.y.cmp(this.curve.c) === 0)); -}; - -Point.prototype._extDbl = function _extDbl() { - // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html - // #doubling-dbl-2008-hwcd - // 4M + 4S - - // A = X1^2 - var a = this.x.redSqr(); - // B = Y1^2 - var b = this.y.redSqr(); - // C = 2 * Z1^2 - var c = this.z.redSqr(); - c = c.redIAdd(c); - // D = a * A - var d = this.curve._mulA(a); - // E = (X1 + Y1)^2 - A - B - var e = this.x.redAdd(this.y).redSqr().redISub(a).redISub(b); - // G = D + B - var g = d.redAdd(b); - // F = G - C - var f = g.redSub(c); - // H = D - B - var h = d.redSub(b); - // X3 = E * F - var nx = e.redMul(f); - // Y3 = G * H - var ny = g.redMul(h); - // T3 = E * H - var nt = e.redMul(h); - // Z3 = F * G - var nz = f.redMul(g); - return this.curve.point(nx, ny, nz, nt); -}; - -Point.prototype._projDbl = function _projDbl() { - // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html - // #doubling-dbl-2008-bbjlp - // #doubling-dbl-2007-bl - // and others - // Generally 3M + 4S or 2M + 4S - - // B = (X1 + Y1)^2 - var b = this.x.redAdd(this.y).redSqr(); - // C = X1^2 - var c = this.x.redSqr(); - // D = Y1^2 - var d = this.y.redSqr(); - - var nx; - var ny; - var nz; - if (this.curve.twisted) { - // E = a * C - var e = this.curve._mulA(c); - // F = E + D - var f = e.redAdd(d); - if (this.zOne) { - // X3 = (B - C - D) * (F - 2) - nx = b.redSub(c).redSub(d).redMul(f.redSub(this.curve.two)); - // Y3 = F * (E - D) - ny = f.redMul(e.redSub(d)); - // Z3 = F^2 - 2 * F - nz = f.redSqr().redSub(f).redSub(f); - } else { - // H = Z1^2 - var h = this.z.redSqr(); - // J = F - 2 * H - var j = f.redSub(h).redISub(h); - // X3 = (B-C-D)*J - nx = b.redSub(c).redISub(d).redMul(j); - // Y3 = F * (E - D) - ny = f.redMul(e.redSub(d)); - // Z3 = F * J - nz = f.redMul(j); - } - } else { - // E = C + D - var e = c.redAdd(d); - // H = (c * Z1)^2 - var h = this.curve._mulC(this.z).redSqr(); - // J = E - 2 * H - var j = e.redSub(h).redSub(h); - // X3 = c * (B - E) * J - nx = this.curve._mulC(b.redISub(e)).redMul(j); - // Y3 = c * E * (C - D) - ny = this.curve._mulC(e).redMul(c.redISub(d)); - // Z3 = E * J - nz = e.redMul(j); - } - return this.curve.point(nx, ny, nz); -}; - -Point.prototype.dbl = function dbl() { - if (this.isInfinity()) - return this; - - // Double in extended coordinates - if (this.curve.extended) - return this._extDbl(); - else - return this._projDbl(); -}; - -Point.prototype._extAdd = function _extAdd(p) { - // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html - // #addition-add-2008-hwcd-3 - // 8M - - // A = (Y1 - X1) * (Y2 - X2) - var a = this.y.redSub(this.x).redMul(p.y.redSub(p.x)); - // B = (Y1 + X1) * (Y2 + X2) - var b = this.y.redAdd(this.x).redMul(p.y.redAdd(p.x)); - // C = T1 * k * T2 - var c = this.t.redMul(this.curve.dd).redMul(p.t); - // D = Z1 * 2 * Z2 - var d = this.z.redMul(p.z.redAdd(p.z)); - // E = B - A - var e = b.redSub(a); - // F = D - C - var f = d.redSub(c); - // G = D + C - var g = d.redAdd(c); - // H = B + A - var h = b.redAdd(a); - // X3 = E * F - var nx = e.redMul(f); - // Y3 = G * H - var ny = g.redMul(h); - // T3 = E * H - var nt = e.redMul(h); - // Z3 = F * G - var nz = f.redMul(g); - return this.curve.point(nx, ny, nz, nt); -}; - -Point.prototype._projAdd = function _projAdd(p) { - // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html - // #addition-add-2008-bbjlp - // #addition-add-2007-bl - // 10M + 1S - - // A = Z1 * Z2 - var a = this.z.redMul(p.z); - // B = A^2 - var b = a.redSqr(); - // C = X1 * X2 - var c = this.x.redMul(p.x); - // D = Y1 * Y2 - var d = this.y.redMul(p.y); - // E = d * C * D - var e = this.curve.d.redMul(c).redMul(d); - // F = B - E - var f = b.redSub(e); - // G = B + E - var g = b.redAdd(e); - // X3 = A * F * ((X1 + Y1) * (X2 + Y2) - C - D) - var tmp = this.x.redAdd(this.y).redMul(p.x.redAdd(p.y)).redISub(c).redISub(d); - var nx = a.redMul(f).redMul(tmp); - var ny; - var nz; - if (this.curve.twisted) { - // Y3 = A * G * (D - a * C) - ny = a.redMul(g).redMul(d.redSub(this.curve._mulA(c))); - // Z3 = F * G - nz = f.redMul(g); - } else { - // Y3 = A * G * (D - C) - ny = a.redMul(g).redMul(d.redSub(c)); - // Z3 = c * F * G - nz = this.curve._mulC(f).redMul(g); - } - return this.curve.point(nx, ny, nz); -}; - -Point.prototype.add = function add(p) { - if (this.isInfinity()) - return p; - if (p.isInfinity()) - return this; - - if (this.curve.extended) - return this._extAdd(p); - else - return this._projAdd(p); -}; - -Point.prototype.mul = function mul(k) { - if (this._hasDoubles(k)) - return this.curve._fixedNafMul(this, k); - else - return this.curve._wnafMul(this, k); -}; - -Point.prototype.mulAdd = function mulAdd(k1, p, k2) { - return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, false); -}; - -Point.prototype.jmulAdd = function jmulAdd(k1, p, k2) { - return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, true); -}; - -Point.prototype.normalize = function normalize() { - if (this.zOne) - return this; - - // Normalize coordinates - var zi = this.z.redInvm(); - this.x = this.x.redMul(zi); - this.y = this.y.redMul(zi); - if (this.t) - this.t = this.t.redMul(zi); - this.z = this.curve.one; - this.zOne = true; - return this; -}; - -Point.prototype.neg = function neg() { - return this.curve.point(this.x.redNeg(), - this.y, - this.z, - this.t && this.t.redNeg()); -}; - -Point.prototype.getX = function getX() { - this.normalize(); - return this.x.fromRed(); -}; - -Point.prototype.getY = function getY() { - this.normalize(); - return this.y.fromRed(); -}; - -Point.prototype.eq = function eq(other) { - return this === other || - this.getX().cmp(other.getX()) === 0 && - this.getY().cmp(other.getY()) === 0; -}; - -Point.prototype.eqXToP = function eqXToP(x) { - var rx = x.toRed(this.curve.red).redMul(this.z); - if (this.x.cmp(rx) === 0) - return true; - - var xc = x.clone(); - var t = this.curve.redN.redMul(this.z); - for (;;) { - xc.iadd(this.curve.n); - if (xc.cmp(this.curve.p) >= 0) - return false; - - rx.redIAdd(t); - if (this.x.cmp(rx) === 0) - return true; - } -}; - -// Compatibility with BaseCurve -Point.prototype.toP = Point.prototype.normalize; -Point.prototype.mixedAdd = Point.prototype.add; - -},{"../../elliptic":18,"../curve":21,"bn.js":16,"inherits":47}],21:[function(require,module,exports){ -'use strict'; - -var curve = exports; - -curve.base = require('./base'); -curve.short = require('./short'); -curve.mont = require('./mont'); -curve.edwards = require('./edwards'); - -},{"./base":19,"./edwards":20,"./mont":22,"./short":23}],22:[function(require,module,exports){ -'use strict'; - -var curve = require('../curve'); -var BN = require('bn.js'); -var inherits = require('inherits'); -var Base = curve.base; - -var elliptic = require('../../elliptic'); -var utils = elliptic.utils; - -function MontCurve(conf) { - Base.call(this, 'mont', conf); - - this.a = new BN(conf.a, 16).toRed(this.red); - this.b = new BN(conf.b, 16).toRed(this.red); - this.i4 = new BN(4).toRed(this.red).redInvm(); - this.two = new BN(2).toRed(this.red); - // Note: this implementation is according to the original paper - // by P. Montgomery, NOT the one by D. J. Bernstein. - this.a24 = this.i4.redMul(this.a.redAdd(this.two)); -} -inherits(MontCurve, Base); -module.exports = MontCurve; - -MontCurve.prototype.validate = function validate(point) { - var x = point.normalize().x; - var x2 = x.redSqr(); - var rhs = x2.redMul(x).redAdd(x2.redMul(this.a)).redAdd(x); - var y = rhs.redSqrt(); - - return y.redSqr().cmp(rhs) === 0; -}; - -function Point(curve, x, z) { - Base.BasePoint.call(this, curve, 'projective'); - if (x === null && z === null) { - this.x = this.curve.one; - this.z = this.curve.zero; - } else { - this.x = new BN(x, 16); - this.z = new BN(z, 16); - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.z.red) - this.z = this.z.toRed(this.curve.red); - } -} -inherits(Point, Base.BasePoint); - -MontCurve.prototype.decodePoint = function decodePoint(bytes, enc) { - var bytes = utils.toArray(bytes, enc); - - // TODO Curve448 - // Montgomery curve points must be represented in the compressed format - // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B - if (bytes.length === 33 && bytes[0] === 0x40) - bytes = bytes.slice(1, 33).reverse(); // point must be little-endian - if (bytes.length !== 32) - throw new Error('Unknown point compression format'); - return this.point(bytes, 1); -}; - -MontCurve.prototype.point = function point(x, z) { - return new Point(this, x, z); -}; - -MontCurve.prototype.pointFromJSON = function pointFromJSON(obj) { - return Point.fromJSON(this, obj); -}; - -Point.prototype.precompute = function precompute() { - // No-op -}; - -Point.prototype._encode = function _encode(compact) { - var len = this.curve.p.byteLength(); - - // Note: the output should always be little-endian - // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B - if (compact) { - return [ 0x40 ].concat(this.getX().toArray('le', len)); - } else { - return this.getX().toArray('be', len); - } -}; - -Point.fromJSON = function fromJSON(curve, obj) { - return new Point(curve, obj[0], obj[1] || curve.one); -}; - -Point.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; -}; - -Point.prototype.isInfinity = function isInfinity() { - // XXX This code assumes that zero is always zero in red - return this.z.cmpn(0) === 0; -}; - -Point.prototype.dbl = function dbl() { - // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#doubling-dbl-1987-m-3 - // 2M + 2S + 4A - - // A = X1 + Z1 - var a = this.x.redAdd(this.z); - // AA = A^2 - var aa = a.redSqr(); - // B = X1 - Z1 - var b = this.x.redSub(this.z); - // BB = B^2 - var bb = b.redSqr(); - // C = AA - BB - var c = aa.redSub(bb); - // X3 = AA * BB - var nx = aa.redMul(bb); - // Z3 = C * (BB + A24 * C) - var nz = c.redMul(bb.redAdd(this.curve.a24.redMul(c))); - return this.curve.point(nx, nz); -}; - -Point.prototype.add = function add() { - throw new Error('Not supported on Montgomery curve'); -}; - -Point.prototype.diffAdd = function diffAdd(p, diff) { - // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#diffadd-dadd-1987-m-3 - // 4M + 2S + 6A - - // A = X2 + Z2 - var a = this.x.redAdd(this.z); - // B = X2 - Z2 - var b = this.x.redSub(this.z); - // C = X3 + Z3 - var c = p.x.redAdd(p.z); - // D = X3 - Z3 - var d = p.x.redSub(p.z); - // DA = D * A - var da = d.redMul(a); - // CB = C * B - var cb = c.redMul(b); - // X5 = Z1 * (DA + CB)^2 - var nx = diff.z.redMul(da.redAdd(cb).redSqr()); - // Z5 = X1 * (DA - CB)^2 - var nz = diff.x.redMul(da.redISub(cb).redSqr()); - return this.curve.point(nx, nz); -}; - -Point.prototype.mul = function mul(k) { - k = new BN(k, 16); - - var t = k.clone(); - var a = this; // (N / 2) * Q + Q - var b = this.curve.point(null, null); // (N / 2) * Q - var c = this; // Q - - for (var bits = []; t.cmpn(0) !== 0; t.iushrn(1)) - bits.push(t.andln(1)); - - for (var i = bits.length - 1; i >= 0; i--) { - if (bits[i] === 0) { - // N * Q + Q = ((N / 2) * Q + Q)) + (N / 2) * Q - a = a.diffAdd(b, c); - // N * Q = 2 * ((N / 2) * Q + Q)) - b = b.dbl(); - } else { - // N * Q = ((N / 2) * Q + Q) + ((N / 2) * Q) - b = a.diffAdd(b, c); - // N * Q + Q = 2 * ((N / 2) * Q + Q) - a = a.dbl(); - } - } - return b; -}; - -Point.prototype.mulAdd = function mulAdd() { - throw new Error('Not supported on Montgomery curve'); -}; - -Point.prototype.jumlAdd = function jumlAdd() { - throw new Error('Not supported on Montgomery curve'); -}; - -Point.prototype.eq = function eq(other) { - return this.getX().cmp(other.getX()) === 0; -}; - -Point.prototype.normalize = function normalize() { - this.x = this.x.redMul(this.z.redInvm()); - this.z = this.curve.one; - return this; -}; - -Point.prototype.getX = function getX() { - // Normalize coordinates - this.normalize(); - - return this.x.fromRed(); -}; - -},{"../../elliptic":18,"../curve":21,"bn.js":16,"inherits":47}],23:[function(require,module,exports){ -'use strict'; - -var curve = require('../curve'); -var elliptic = require('../../elliptic'); -var BN = require('bn.js'); -var inherits = require('inherits'); -var Base = curve.base; - -var assert = elliptic.utils.assert; - -function ShortCurve(conf) { - Base.call(this, 'short', conf); - - this.a = new BN(conf.a, 16).toRed(this.red); - this.b = new BN(conf.b, 16).toRed(this.red); - this.tinv = this.two.redInvm(); - - this.zeroA = this.a.fromRed().cmpn(0) === 0; - this.threeA = this.a.fromRed().sub(this.p).cmpn(-3) === 0; - - // If the curve is endomorphic, precalculate beta and lambda - this.endo = this._getEndomorphism(conf); - this._endoWnafT1 = new Array(4); - this._endoWnafT2 = new Array(4); -} -inherits(ShortCurve, Base); -module.exports = ShortCurve; - -ShortCurve.prototype._getEndomorphism = function _getEndomorphism(conf) { - // No efficient endomorphism - if (!this.zeroA || !this.g || !this.n || this.p.modn(3) !== 1) - return; - - // Compute beta and lambda, that lambda * P = (beta * Px; Py) - var beta; - var lambda; - if (conf.beta) { - beta = new BN(conf.beta, 16).toRed(this.red); - } else { - var betas = this._getEndoRoots(this.p); - // Choose the smallest beta - beta = betas[0].cmp(betas[1]) < 0 ? betas[0] : betas[1]; - beta = beta.toRed(this.red); - } - if (conf.lambda) { - lambda = new BN(conf.lambda, 16); - } else { - // Choose the lambda that is matching selected beta - var lambdas = this._getEndoRoots(this.n); - if (this.g.mul(lambdas[0]).x.cmp(this.g.x.redMul(beta)) === 0) { - lambda = lambdas[0]; - } else { - lambda = lambdas[1]; - assert(this.g.mul(lambda).x.cmp(this.g.x.redMul(beta)) === 0); - } - } - - // Get basis vectors, used for balanced length-two representation - var basis; - if (conf.basis) { - basis = conf.basis.map(function(vec) { - return { - a: new BN(vec.a, 16), - b: new BN(vec.b, 16) - }; - }); - } else { - basis = this._getEndoBasis(lambda); - } - - return { - beta: beta, - lambda: lambda, - basis: basis - }; -}; - -ShortCurve.prototype._getEndoRoots = function _getEndoRoots(num) { - // Find roots of for x^2 + x + 1 in F - // Root = (-1 +- Sqrt(-3)) / 2 - // - var red = num === this.p ? this.red : BN.mont(num); - var tinv = new BN(2).toRed(red).redInvm(); - var ntinv = tinv.redNeg(); - - var s = new BN(3).toRed(red).redNeg().redSqrt().redMul(tinv); - - var l1 = ntinv.redAdd(s).fromRed(); - var l2 = ntinv.redSub(s).fromRed(); - return [ l1, l2 ]; -}; - -ShortCurve.prototype._getEndoBasis = function _getEndoBasis(lambda) { - // aprxSqrt >= sqrt(this.n) - var aprxSqrt = this.n.ushrn(Math.floor(this.n.bitLength() / 2)); - - // 3.74 - // Run EGCD, until r(L + 1) < aprxSqrt - var u = lambda; - var v = this.n.clone(); - var x1 = new BN(1); - var y1 = new BN(0); - var x2 = new BN(0); - var y2 = new BN(1); - - // NOTE: all vectors are roots of: a + b * lambda = 0 (mod n) - var a0; - var b0; - // First vector - var a1; - var b1; - // Second vector - var a2; - var b2; - - var prevR; - var i = 0; - var r; - var x; - while (u.cmpn(0) !== 0) { - var q = v.div(u); - r = v.sub(q.mul(u)); - x = x2.sub(q.mul(x1)); - var y = y2.sub(q.mul(y1)); - - if (!a1 && r.cmp(aprxSqrt) < 0) { - a0 = prevR.neg(); - b0 = x1; - a1 = r.neg(); - b1 = x; - } else if (a1 && ++i === 2) { - break; - } - prevR = r; - - v = u; - u = r; - x2 = x1; - x1 = x; - y2 = y1; - y1 = y; - } - a2 = r.neg(); - b2 = x; - - var len1 = a1.sqr().add(b1.sqr()); - var len2 = a2.sqr().add(b2.sqr()); - if (len2.cmp(len1) >= 0) { - a2 = a0; - b2 = b0; - } - - // Normalize signs - if (a1.negative) { - a1 = a1.neg(); - b1 = b1.neg(); - } - if (a2.negative) { - a2 = a2.neg(); - b2 = b2.neg(); - } - - return [ - { a: a1, b: b1 }, - { a: a2, b: b2 } - ]; -}; - -ShortCurve.prototype._endoSplit = function _endoSplit(k) { - var basis = this.endo.basis; - var v1 = basis[0]; - var v2 = basis[1]; - - var c1 = v2.b.mul(k).divRound(this.n); - var c2 = v1.b.neg().mul(k).divRound(this.n); - - var p1 = c1.mul(v1.a); - var p2 = c2.mul(v2.a); - var q1 = c1.mul(v1.b); - var q2 = c2.mul(v2.b); - - // Calculate answer - var k1 = k.sub(p1).sub(p2); - var k2 = q1.add(q2).neg(); - return { k1: k1, k2: k2 }; -}; - -ShortCurve.prototype.pointFromX = function pointFromX(x, odd) { - x = new BN(x, 16); - if (!x.red) - x = x.toRed(this.red); - - var y2 = x.redSqr().redMul(x).redIAdd(x.redMul(this.a)).redIAdd(this.b); - var y = y2.redSqrt(); - if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) - throw new Error('invalid point'); - - // XXX Is there any way to tell if the number is odd without converting it - // to non-red form? - var isOdd = y.fromRed().isOdd(); - if (odd && !isOdd || !odd && isOdd) - y = y.redNeg(); - - return this.point(x, y); -}; - -ShortCurve.prototype.validate = function validate(point) { - if (point.inf) - return true; - - var x = point.x; - var y = point.y; - - var ax = this.a.redMul(x); - var rhs = x.redSqr().redMul(x).redIAdd(ax).redIAdd(this.b); - return y.redSqr().redISub(rhs).cmpn(0) === 0; -}; - -ShortCurve.prototype._endoWnafMulAdd = - function _endoWnafMulAdd(points, coeffs, jacobianResult) { - var npoints = this._endoWnafT1; - var ncoeffs = this._endoWnafT2; - for (var i = 0; i < points.length; i++) { - var split = this._endoSplit(coeffs[i]); - var p = points[i]; - var beta = p._getBeta(); - - if (split.k1.negative) { - split.k1.ineg(); - p = p.neg(true); - } - if (split.k2.negative) { - split.k2.ineg(); - beta = beta.neg(true); - } - - npoints[i * 2] = p; - npoints[i * 2 + 1] = beta; - ncoeffs[i * 2] = split.k1; - ncoeffs[i * 2 + 1] = split.k2; - } - var res = this._wnafMulAdd(1, npoints, ncoeffs, i * 2, jacobianResult); - - // Clean-up references to points and coefficients - for (var j = 0; j < i * 2; j++) { - npoints[j] = null; - ncoeffs[j] = null; - } - return res; -}; - -function Point(curve, x, y, isRed) { - Base.BasePoint.call(this, curve, 'affine'); - if (x === null && y === null) { - this.x = null; - this.y = null; - this.inf = true; - } else { - this.x = new BN(x, 16); - this.y = new BN(y, 16); - // Force redgomery representation when loading from JSON - if (isRed) { - this.x.forceRed(this.curve.red); - this.y.forceRed(this.curve.red); - } - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.y.red) - this.y = this.y.toRed(this.curve.red); - this.inf = false; - } -} -inherits(Point, Base.BasePoint); - -ShortCurve.prototype.point = function point(x, y, isRed) { - return new Point(this, x, y, isRed); -}; - -ShortCurve.prototype.pointFromJSON = function pointFromJSON(obj, red) { - return Point.fromJSON(this, obj, red); -}; - -Point.prototype._getBeta = function _getBeta() { - if (!this.curve.endo) - return; - - var pre = this.precomputed; - if (pre && pre.beta) - return pre.beta; - - var beta = this.curve.point(this.x.redMul(this.curve.endo.beta), this.y); - if (pre) { - var curve = this.curve; - var endoMul = function(p) { - return curve.point(p.x.redMul(curve.endo.beta), p.y); - }; - pre.beta = beta; - beta.precomputed = { - beta: null, - naf: pre.naf && { - wnd: pre.naf.wnd, - points: pre.naf.points.map(endoMul) - }, - doubles: pre.doubles && { - step: pre.doubles.step, - points: pre.doubles.points.map(endoMul) - } - }; - } - return beta; -}; - -Point.prototype.toJSON = function toJSON() { - if (!this.precomputed) - return [ this.x, this.y ]; - - return [ this.x, this.y, this.precomputed && { - doubles: this.precomputed.doubles && { - step: this.precomputed.doubles.step, - points: this.precomputed.doubles.points.slice(1) - }, - naf: this.precomputed.naf && { - wnd: this.precomputed.naf.wnd, - points: this.precomputed.naf.points.slice(1) - } - } ]; -}; - -Point.fromJSON = function fromJSON(curve, obj, red) { - if (typeof obj === 'string') - obj = JSON.parse(obj); - var res = curve.point(obj[0], obj[1], red); - if (!obj[2]) - return res; - - function obj2point(obj) { - return curve.point(obj[0], obj[1], red); - } - - var pre = obj[2]; - res.precomputed = { - beta: null, - doubles: pre.doubles && { - step: pre.doubles.step, - points: [ res ].concat(pre.doubles.points.map(obj2point)) - }, - naf: pre.naf && { - wnd: pre.naf.wnd, - points: [ res ].concat(pre.naf.points.map(obj2point)) - } - }; - return res; -}; - -Point.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; -}; - -Point.prototype.isInfinity = function isInfinity() { - return this.inf; -}; - -Point.prototype.add = function add(p) { - // O + P = P - if (this.inf) - return p; - - // P + O = P - if (p.inf) - return this; - - // P + P = 2P - if (this.eq(p)) - return this.dbl(); - - // P + (-P) = O - if (this.neg().eq(p)) - return this.curve.point(null, null); - - // P + Q = O - if (this.x.cmp(p.x) === 0) - return this.curve.point(null, null); - - var c = this.y.redSub(p.y); - if (c.cmpn(0) !== 0) - c = c.redMul(this.x.redSub(p.x).redInvm()); - var nx = c.redSqr().redISub(this.x).redISub(p.x); - var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); - return this.curve.point(nx, ny); -}; - -Point.prototype.dbl = function dbl() { - if (this.inf) - return this; - - // 2P = O - var ys1 = this.y.redAdd(this.y); - if (ys1.cmpn(0) === 0) - return this.curve.point(null, null); - - var a = this.curve.a; - - var x2 = this.x.redSqr(); - var dyinv = ys1.redInvm(); - var c = x2.redAdd(x2).redIAdd(x2).redIAdd(a).redMul(dyinv); - - var nx = c.redSqr().redISub(this.x.redAdd(this.x)); - var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); - return this.curve.point(nx, ny); -}; - -Point.prototype.getX = function getX() { - return this.x.fromRed(); -}; - -Point.prototype.getY = function getY() { - return this.y.fromRed(); -}; - -Point.prototype.mul = function mul(k) { - k = new BN(k, 16); - - if (this._hasDoubles(k)) - return this.curve._fixedNafMul(this, k); - else if (this.curve.endo) - return this.curve._endoWnafMulAdd([ this ], [ k ]); - else - return this.curve._wnafMul(this, k); -}; - -Point.prototype.mulAdd = function mulAdd(k1, p2, k2) { - var points = [ this, p2 ]; - var coeffs = [ k1, k2 ]; - if (this.curve.endo) - return this.curve._endoWnafMulAdd(points, coeffs); - else - return this.curve._wnafMulAdd(1, points, coeffs, 2); -}; - -Point.prototype.jmulAdd = function jmulAdd(k1, p2, k2) { - var points = [ this, p2 ]; - var coeffs = [ k1, k2 ]; - if (this.curve.endo) - return this.curve._endoWnafMulAdd(points, coeffs, true); - else - return this.curve._wnafMulAdd(1, points, coeffs, 2, true); -}; - -Point.prototype.eq = function eq(p) { - return this === p || - this.inf === p.inf && - (this.inf || this.x.cmp(p.x) === 0 && this.y.cmp(p.y) === 0); -}; - -Point.prototype.neg = function neg(_precompute) { - if (this.inf) - return this; - - var res = this.curve.point(this.x, this.y.redNeg()); - if (_precompute && this.precomputed) { - var pre = this.precomputed; - var negate = function(p) { - return p.neg(); - }; - res.precomputed = { - naf: pre.naf && { - wnd: pre.naf.wnd, - points: pre.naf.points.map(negate) - }, - doubles: pre.doubles && { - step: pre.doubles.step, - points: pre.doubles.points.map(negate) - } - }; - } - return res; -}; - -Point.prototype.toJ = function toJ() { - if (this.inf) - return this.curve.jpoint(null, null, null); - - var res = this.curve.jpoint(this.x, this.y, this.curve.one); - return res; -}; - -function JPoint(curve, x, y, z) { - Base.BasePoint.call(this, curve, 'jacobian'); - if (x === null && y === null && z === null) { - this.x = this.curve.one; - this.y = this.curve.one; - this.z = new BN(0); - } else { - this.x = new BN(x, 16); - this.y = new BN(y, 16); - this.z = new BN(z, 16); - } - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.y.red) - this.y = this.y.toRed(this.curve.red); - if (!this.z.red) - this.z = this.z.toRed(this.curve.red); - - this.zOne = this.z === this.curve.one; -} -inherits(JPoint, Base.BasePoint); - -ShortCurve.prototype.jpoint = function jpoint(x, y, z) { - return new JPoint(this, x, y, z); -}; - -JPoint.prototype.toP = function toP() { - if (this.isInfinity()) - return this.curve.point(null, null); - - var zinv = this.z.redInvm(); - var zinv2 = zinv.redSqr(); - var ax = this.x.redMul(zinv2); - var ay = this.y.redMul(zinv2).redMul(zinv); - - return this.curve.point(ax, ay); -}; - -JPoint.prototype.neg = function neg() { - return this.curve.jpoint(this.x, this.y.redNeg(), this.z); -}; - -JPoint.prototype.add = function add(p) { - // O + P = P - if (this.isInfinity()) - return p; - - // P + O = P - if (p.isInfinity()) - return this; - - // 12M + 4S + 7A - var pz2 = p.z.redSqr(); - var z2 = this.z.redSqr(); - var u1 = this.x.redMul(pz2); - var u2 = p.x.redMul(z2); - var s1 = this.y.redMul(pz2.redMul(p.z)); - var s2 = p.y.redMul(z2.redMul(this.z)); - - var h = u1.redSub(u2); - var r = s1.redSub(s2); - if (h.cmpn(0) === 0) { - if (r.cmpn(0) !== 0) - return this.curve.jpoint(null, null, null); - else - return this.dbl(); - } - - var h2 = h.redSqr(); - var h3 = h2.redMul(h); - var v = u1.redMul(h2); - - var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); - var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); - var nz = this.z.redMul(p.z).redMul(h); - - return this.curve.jpoint(nx, ny, nz); -}; - -JPoint.prototype.mixedAdd = function mixedAdd(p) { - // O + P = P - if (this.isInfinity()) - return p.toJ(); - - // P + O = P - if (p.isInfinity()) - return this; - - // 8M + 3S + 7A - var z2 = this.z.redSqr(); - var u1 = this.x; - var u2 = p.x.redMul(z2); - var s1 = this.y; - var s2 = p.y.redMul(z2).redMul(this.z); - - var h = u1.redSub(u2); - var r = s1.redSub(s2); - if (h.cmpn(0) === 0) { - if (r.cmpn(0) !== 0) - return this.curve.jpoint(null, null, null); - else - return this.dbl(); - } - - var h2 = h.redSqr(); - var h3 = h2.redMul(h); - var v = u1.redMul(h2); - - var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); - var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); - var nz = this.z.redMul(h); - - return this.curve.jpoint(nx, ny, nz); -}; - -JPoint.prototype.dblp = function dblp(pow) { - if (pow === 0) - return this; - if (this.isInfinity()) - return this; - if (!pow) - return this.dbl(); - - if (this.curve.zeroA || this.curve.threeA) { - var r = this; - for (var i = 0; i < pow; i++) - r = r.dbl(); - return r; - } - - // 1M + 2S + 1A + N * (4S + 5M + 8A) - // N = 1 => 6M + 6S + 9A - var a = this.curve.a; - var tinv = this.curve.tinv; - - var jx = this.x; - var jy = this.y; - var jz = this.z; - var jz4 = jz.redSqr().redSqr(); - - // Reuse results - var jyd = jy.redAdd(jy); - for (var i = 0; i < pow; i++) { - var jx2 = jx.redSqr(); - var jyd2 = jyd.redSqr(); - var jyd4 = jyd2.redSqr(); - var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); - - var t1 = jx.redMul(jyd2); - var nx = c.redSqr().redISub(t1.redAdd(t1)); - var t2 = t1.redISub(nx); - var dny = c.redMul(t2); - dny = dny.redIAdd(dny).redISub(jyd4); - var nz = jyd.redMul(jz); - if (i + 1 < pow) - jz4 = jz4.redMul(jyd4); - - jx = nx; - jz = nz; - jyd = dny; - } - - return this.curve.jpoint(jx, jyd.redMul(tinv), jz); -}; - -JPoint.prototype.dbl = function dbl() { - if (this.isInfinity()) - return this; - - if (this.curve.zeroA) - return this._zeroDbl(); - else if (this.curve.threeA) - return this._threeDbl(); - else - return this._dbl(); -}; - -JPoint.prototype._zeroDbl = function _zeroDbl() { - var nx; - var ny; - var nz; - // Z = 1 - if (this.zOne) { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html - // #doubling-mdbl-2007-bl - // 1M + 5S + 14A - - // XX = X1^2 - var xx = this.x.redSqr(); - // YY = Y1^2 - var yy = this.y.redSqr(); - // YYYY = YY^2 - var yyyy = yy.redSqr(); - // S = 2 * ((X1 + YY)^2 - XX - YYYY) - var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); - s = s.redIAdd(s); - // M = 3 * XX + a; a = 0 - var m = xx.redAdd(xx).redIAdd(xx); - // T = M ^ 2 - 2*S - var t = m.redSqr().redISub(s).redISub(s); - - // 8 * YYYY - var yyyy8 = yyyy.redIAdd(yyyy); - yyyy8 = yyyy8.redIAdd(yyyy8); - yyyy8 = yyyy8.redIAdd(yyyy8); - - // X3 = T - nx = t; - // Y3 = M * (S - T) - 8 * YYYY - ny = m.redMul(s.redISub(t)).redISub(yyyy8); - // Z3 = 2*Y1 - nz = this.y.redAdd(this.y); - } else { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html - // #doubling-dbl-2009-l - // 2M + 5S + 13A - - // A = X1^2 - var a = this.x.redSqr(); - // B = Y1^2 - var b = this.y.redSqr(); - // C = B^2 - var c = b.redSqr(); - // D = 2 * ((X1 + B)^2 - A - C) - var d = this.x.redAdd(b).redSqr().redISub(a).redISub(c); - d = d.redIAdd(d); - // E = 3 * A - var e = a.redAdd(a).redIAdd(a); - // F = E^2 - var f = e.redSqr(); - - // 8 * C - var c8 = c.redIAdd(c); - c8 = c8.redIAdd(c8); - c8 = c8.redIAdd(c8); - - // X3 = F - 2 * D - nx = f.redISub(d).redISub(d); - // Y3 = E * (D - X3) - 8 * C - ny = e.redMul(d.redISub(nx)).redISub(c8); - // Z3 = 2 * Y1 * Z1 - nz = this.y.redMul(this.z); - nz = nz.redIAdd(nz); - } - - return this.curve.jpoint(nx, ny, nz); -}; - -JPoint.prototype._threeDbl = function _threeDbl() { - var nx; - var ny; - var nz; - // Z = 1 - if (this.zOne) { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html - // #doubling-mdbl-2007-bl - // 1M + 5S + 15A - - // XX = X1^2 - var xx = this.x.redSqr(); - // YY = Y1^2 - var yy = this.y.redSqr(); - // YYYY = YY^2 - var yyyy = yy.redSqr(); - // S = 2 * ((X1 + YY)^2 - XX - YYYY) - var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); - s = s.redIAdd(s); - // M = 3 * XX + a - var m = xx.redAdd(xx).redIAdd(xx).redIAdd(this.curve.a); - // T = M^2 - 2 * S - var t = m.redSqr().redISub(s).redISub(s); - // X3 = T - nx = t; - // Y3 = M * (S - T) - 8 * YYYY - var yyyy8 = yyyy.redIAdd(yyyy); - yyyy8 = yyyy8.redIAdd(yyyy8); - yyyy8 = yyyy8.redIAdd(yyyy8); - ny = m.redMul(s.redISub(t)).redISub(yyyy8); - // Z3 = 2 * Y1 - nz = this.y.redAdd(this.y); - } else { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b - // 3M + 5S - - // delta = Z1^2 - var delta = this.z.redSqr(); - // gamma = Y1^2 - var gamma = this.y.redSqr(); - // beta = X1 * gamma - var beta = this.x.redMul(gamma); - // alpha = 3 * (X1 - delta) * (X1 + delta) - var alpha = this.x.redSub(delta).redMul(this.x.redAdd(delta)); - alpha = alpha.redAdd(alpha).redIAdd(alpha); - // X3 = alpha^2 - 8 * beta - var beta4 = beta.redIAdd(beta); - beta4 = beta4.redIAdd(beta4); - var beta8 = beta4.redAdd(beta4); - nx = alpha.redSqr().redISub(beta8); - // Z3 = (Y1 + Z1)^2 - gamma - delta - nz = this.y.redAdd(this.z).redSqr().redISub(gamma).redISub(delta); - // Y3 = alpha * (4 * beta - X3) - 8 * gamma^2 - var ggamma8 = gamma.redSqr(); - ggamma8 = ggamma8.redIAdd(ggamma8); - ggamma8 = ggamma8.redIAdd(ggamma8); - ggamma8 = ggamma8.redIAdd(ggamma8); - ny = alpha.redMul(beta4.redISub(nx)).redISub(ggamma8); - } - - return this.curve.jpoint(nx, ny, nz); -}; - -JPoint.prototype._dbl = function _dbl() { - var a = this.curve.a; - - // 4M + 6S + 10A - var jx = this.x; - var jy = this.y; - var jz = this.z; - var jz4 = jz.redSqr().redSqr(); - - var jx2 = jx.redSqr(); - var jy2 = jy.redSqr(); - - var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); - - var jxd4 = jx.redAdd(jx); - jxd4 = jxd4.redIAdd(jxd4); - var t1 = jxd4.redMul(jy2); - var nx = c.redSqr().redISub(t1.redAdd(t1)); - var t2 = t1.redISub(nx); - - var jyd8 = jy2.redSqr(); - jyd8 = jyd8.redIAdd(jyd8); - jyd8 = jyd8.redIAdd(jyd8); - jyd8 = jyd8.redIAdd(jyd8); - var ny = c.redMul(t2).redISub(jyd8); - var nz = jy.redAdd(jy).redMul(jz); - - return this.curve.jpoint(nx, ny, nz); -}; - -JPoint.prototype.trpl = function trpl() { - if (!this.curve.zeroA) - return this.dbl().add(this); - - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#tripling-tpl-2007-bl - // 5M + 10S + ... - - // XX = X1^2 - var xx = this.x.redSqr(); - // YY = Y1^2 - var yy = this.y.redSqr(); - // ZZ = Z1^2 - var zz = this.z.redSqr(); - // YYYY = YY^2 - var yyyy = yy.redSqr(); - // M = 3 * XX + a * ZZ2; a = 0 - var m = xx.redAdd(xx).redIAdd(xx); - // MM = M^2 - var mm = m.redSqr(); - // E = 6 * ((X1 + YY)^2 - XX - YYYY) - MM - var e = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); - e = e.redIAdd(e); - e = e.redAdd(e).redIAdd(e); - e = e.redISub(mm); - // EE = E^2 - var ee = e.redSqr(); - // T = 16*YYYY - var t = yyyy.redIAdd(yyyy); - t = t.redIAdd(t); - t = t.redIAdd(t); - t = t.redIAdd(t); - // U = (M + E)^2 - MM - EE - T - var u = m.redIAdd(e).redSqr().redISub(mm).redISub(ee).redISub(t); - // X3 = 4 * (X1 * EE - 4 * YY * U) - var yyu4 = yy.redMul(u); - yyu4 = yyu4.redIAdd(yyu4); - yyu4 = yyu4.redIAdd(yyu4); - var nx = this.x.redMul(ee).redISub(yyu4); - nx = nx.redIAdd(nx); - nx = nx.redIAdd(nx); - // Y3 = 8 * Y1 * (U * (T - U) - E * EE) - var ny = this.y.redMul(u.redMul(t.redISub(u)).redISub(e.redMul(ee))); - ny = ny.redIAdd(ny); - ny = ny.redIAdd(ny); - ny = ny.redIAdd(ny); - // Z3 = (Z1 + E)^2 - ZZ - EE - var nz = this.z.redAdd(e).redSqr().redISub(zz).redISub(ee); - - return this.curve.jpoint(nx, ny, nz); -}; - -JPoint.prototype.mul = function mul(k, kbase) { - k = new BN(k, kbase); - - return this.curve._wnafMul(this, k); -}; - -JPoint.prototype.eq = function eq(p) { - if (p.type === 'affine') - return this.eq(p.toJ()); - - if (this === p) - return true; - - // x1 * z2^2 == x2 * z1^2 - var z2 = this.z.redSqr(); - var pz2 = p.z.redSqr(); - if (this.x.redMul(pz2).redISub(p.x.redMul(z2)).cmpn(0) !== 0) - return false; - - // y1 * z2^3 == y2 * z1^3 - var z3 = z2.redMul(this.z); - var pz3 = pz2.redMul(p.z); - return this.y.redMul(pz3).redISub(p.y.redMul(z3)).cmpn(0) === 0; -}; - -JPoint.prototype.eqXToP = function eqXToP(x) { - var zs = this.z.redSqr(); - var rx = x.toRed(this.curve.red).redMul(zs); - if (this.x.cmp(rx) === 0) - return true; - - var xc = x.clone(); - var t = this.curve.redN.redMul(zs); - for (;;) { - xc.iadd(this.curve.n); - if (xc.cmp(this.curve.p) >= 0) - return false; - - rx.redIAdd(t); - if (this.x.cmp(rx) === 0) - return true; - } -}; - -JPoint.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; -}; - -JPoint.prototype.isInfinity = function isInfinity() { - // XXX This code assumes that zero is always zero in red - return this.z.cmpn(0) === 0; -}; - -},{"../../elliptic":18,"../curve":21,"bn.js":16,"inherits":47}],24:[function(require,module,exports){ -'use strict'; - -var curves = exports; - -var hash = require('hash.js'); -var elliptic = require('../elliptic'); - -var assert = elliptic.utils.assert; - -function PresetCurve(options) { - if (options.type === 'short') - this.curve = new elliptic.curve.short(options); - else if (options.type === 'edwards') - this.curve = new elliptic.curve.edwards(options); - else if (options.type === 'mont') - this.curve = new elliptic.curve.mont(options); - else throw new Error('Unknown curve type.'); - this.g = this.curve.g; - this.n = this.curve.n; - this.hash = options.hash; - - assert(this.g.validate(), 'Invalid curve'); - assert(this.g.mul(this.n).isInfinity(), 'Invalid curve, n*G != O'); -} -curves.PresetCurve = PresetCurve; - -function defineCurve(name, options) { - Object.defineProperty(curves, name, { - configurable: true, - enumerable: true, - get: function() { - var curve = new PresetCurve(options); - Object.defineProperty(curves, name, { - configurable: true, - enumerable: true, - value: curve - }); - return curve; - } - }); -} - -defineCurve('p192', { - type: 'short', - prime: 'p192', - p: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff', - a: 'ffffffff ffffffff ffffffff fffffffe ffffffff fffffffc', - b: '64210519 e59c80e7 0fa7e9ab 72243049 feb8deec c146b9b1', - n: 'ffffffff ffffffff ffffffff 99def836 146bc9b1 b4d22831', - hash: hash.sha256, - gRed: false, - g: [ - '188da80e b03090f6 7cbf20eb 43a18800 f4ff0afd 82ff1012', - '07192b95 ffc8da78 631011ed 6b24cdd5 73f977a1 1e794811' - ] -}); - -defineCurve('p224', { - type: 'short', - prime: 'p224', - p: 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001', - a: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff fffffffe', - b: 'b4050a85 0c04b3ab f5413256 5044b0b7 d7bfd8ba 270b3943 2355ffb4', - n: 'ffffffff ffffffff ffffffff ffff16a2 e0b8f03e 13dd2945 5c5c2a3d', - hash: hash.sha256, - gRed: false, - g: [ - 'b70e0cbd 6bb4bf7f 321390b9 4a03c1d3 56c21122 343280d6 115c1d21', - 'bd376388 b5f723fb 4c22dfe6 cd4375a0 5a074764 44d58199 85007e34' - ] -}); - -defineCurve('p256', { - type: 'short', - prime: null, - p: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff', - a: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff fffffffc', - b: '5ac635d8 aa3a93e7 b3ebbd55 769886bc 651d06b0 cc53b0f6 3bce3c3e 27d2604b', - n: 'ffffffff 00000000 ffffffff ffffffff bce6faad a7179e84 f3b9cac2 fc632551', - hash: hash.sha256, - gRed: false, - g: [ - '6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296', - '4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5' - ] -}); - -defineCurve('p384', { - type: 'short', - prime: null, - p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'fffffffe ffffffff 00000000 00000000 ffffffff', - a: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'fffffffe ffffffff 00000000 00000000 fffffffc', - b: 'b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112 0314088f ' + - '5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef', - n: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff c7634d81 ' + - 'f4372ddf 581a0db2 48b0a77a ecec196a ccc52973', - hash: hash.sha384, - gRed: false, - g: [ - 'aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98 59f741e0 82542a38 ' + - '5502f25d bf55296c 3a545e38 72760ab7', - '3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c e9da3113 b5f0b8c0 ' + - '0a60b1ce 1d7e819d 7a431d7c 90ea0e5f' - ] -}); - -defineCurve('p521', { - type: 'short', - prime: null, - p: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff ffffffff', - a: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff fffffffc', - b: '00000051 953eb961 8e1c9a1f 929a21a0 b68540ee a2da725b ' + - '99b315f3 b8b48991 8ef109e1 56193951 ec7e937b 1652c0bd ' + - '3bb1bf07 3573df88 3d2c34f1 ef451fd4 6b503f00', - n: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff fffffffa 51868783 bf2f966b 7fcc0148 ' + - 'f709a5d0 3bb5c9b8 899c47ae bb6fb71e 91386409', - hash: hash.sha512, - gRed: false, - g: [ - '000000c6 858e06b7 0404e9cd 9e3ecb66 2395b442 9c648139 ' + - '053fb521 f828af60 6b4d3dba a14b5e77 efe75928 fe1dc127 ' + - 'a2ffa8de 3348b3c1 856a429b f97e7e31 c2e5bd66', - '00000118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd9 98f54449 ' + - '579b4468 17afbd17 273e662c 97ee7299 5ef42640 c550b901 ' + - '3fad0761 353c7086 a272c240 88be9476 9fd16650' - ] -}); - -// https://tools.ietf.org/html/rfc7748#section-4.1 -defineCurve('curve25519', { - type: 'mont', - prime: 'p25519', - p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', - a: '76d06', - b: '1', - n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', - cofactor: '8', - hash: hash.sha256, - gRed: false, - g: [ - '9' - ] -}); - -defineCurve('ed25519', { - type: 'edwards', - prime: 'p25519', - p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', - a: '-1', - c: '1', - // -121665 * (121666^(-1)) (mod P) - d: '52036cee2b6ffe73 8cc740797779e898 00700a4d4141d8ab 75eb4dca135978a3', - n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', - cofactor: '8', - hash: hash.sha256, - gRed: false, - g: [ - '216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a', - // 4/5 - '6666666666666666666666666666666666666666666666666666666666666658' - ] -}); - -// https://tools.ietf.org/html/rfc5639#section-3.4 -defineCurve('brainpoolP256r1', { - type: 'short', - prime: null, - p: 'A9FB57DB A1EEA9BC 3E660A90 9D838D72 6E3BF623 D5262028 2013481D 1F6E5377', - a: '7D5A0975 FC2C3057 EEF67530 417AFFE7 FB8055C1 26DC5C6C E94A4B44 F330B5D9', - b: '26DC5C6C E94A4B44 F330B5D9 BBD77CBF 95841629 5CF7E1CE 6BCCDC18 FF8C07B6', - n: 'A9FB57DB A1EEA9BC 3E660A90 9D838D71 8C397AA3 B561A6F7 901E0E82 974856A7', - hash: hash.sha256, // or 384, or 512 - gRed: false, - g: [ - '8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262', - '547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997' - ] -}); - -// https://tools.ietf.org/html/rfc5639#section-3.6 -defineCurve('brainpoolP384r1', { - type: 'short', - prime: null, - p: '8CB91E82 A3386D28 0F5D6F7E 50E641DF 152F7109 ED5456B4 12B1DA19 7FB71123' + - 'ACD3A729 901D1A71 87470013 3107EC53', - a: '7BC382C6 3D8C150C 3C72080A CE05AFA0 C2BEA28E 4FB22787 139165EF BA91F90F' + - '8AA5814A 503AD4EB 04A8C7DD 22CE2826', - b: '04A8C7DD 22CE2826 8B39B554 16F0447C 2FB77DE1 07DCD2A6 2E880EA5 3EEB62D5' + - '7CB43902 95DBC994 3AB78696 FA504C11', - n: '8CB91E82 A3386D28 0F5D6F7E 50E641DF 152F7109 ED5456B3 1F166E6C AC0425A7' + - 'CF3AB6AF 6B7FC310 3B883202 E9046565', - hash: hash.sha384, // or 512 - gRed: false, - g: [ - '1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10' + - 'E8E826E03436D646AAEF87B2E247D4AF1E', - '8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129' + - '280E4646217791811142820341263C5315' - ] -}); - -// https://tools.ietf.org/html/rfc5639#section-3.7 -defineCurve('brainpoolP512r1', { - type: 'short', - prime: null, - p: 'AADD9DB8 DBE9C48B 3FD4E6AE 33C9FC07 CB308DB3 B3C9D20E D6639CCA 70330871' + - '7D4D9B00 9BC66842 AECDA12A E6A380E6 2881FF2F 2D82C685 28AA6056 583A48F3', - a: '7830A331 8B603B89 E2327145 AC234CC5 94CBDD8D 3DF91610 A83441CA EA9863BC' + - '2DED5D5A A8253AA1 0A2EF1C9 8B9AC8B5 7F1117A7 2BF2C7B9 E7C1AC4D 77FC94CA', - b: '3DF91610 A83441CA EA9863BC 2DED5D5A A8253AA1 0A2EF1C9 8B9AC8B5 7F1117A7' + - '2BF2C7B9 E7C1AC4D 77FC94CA DC083E67 984050B7 5EBAE5DD 2809BD63 8016F723', - n: 'AADD9DB8 DBE9C48B 3FD4E6AE 33C9FC07 CB308DB3 B3C9D20E D6639CCA 70330870' + - '553E5C41 4CA92619 41866119 7FAC1047 1DB1D381 085DDADD B5879682 9CA90069', - hash: hash.sha512, - gRed: false, - g: [ - '81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D009' + - '8EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822', - '7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F81' + - '11B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892' - ] -}); - -// https://en.bitcoin.it/wiki/Secp256k1 -var pre; -try { - pre = require('./precomputed/secp256k1'); -} catch (e) { - pre = undefined; -} - -defineCurve('secp256k1', { - type: 'short', - prime: 'k256', - p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f', - a: '0', - b: '7', - n: 'ffffffff ffffffff ffffffff fffffffe baaedce6 af48a03b bfd25e8c d0364141', - h: '1', - hash: hash.sha256, - - // Precomputed endomorphism - beta: '7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee', - lambda: '5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72', - basis: [ - { - a: '3086d221a7d46bcde86c90e49284eb15', - b: '-e4437ed6010e88286f547fa90abfe4c3' - }, - { - a: '114ca50f7a8e2f3f657c1108d9d44cfd8', - b: '3086d221a7d46bcde86c90e49284eb15' - } - ], - - gRed: false, - g: [ - '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', - '483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', - pre - ] -}); - -},{"../elliptic":18,"./precomputed/secp256k1":31,"hash.js":34}],25:[function(require,module,exports){ -'use strict'; - -var BN = require('bn.js'); -var HmacDRBG = require('hmac-drbg'); -var elliptic = require('../../elliptic'); -var utils = elliptic.utils; -var assert = utils.assert; - -var KeyPair = require('./key'); -var Signature = require('./signature'); - -function EC(options) { - if (!(this instanceof EC)) - return new EC(options); - - // Shortcut `elliptic.ec(curve-name)` - if (typeof options === 'string') { - assert(elliptic.curves.hasOwnProperty(options), 'Unknown curve ' + options); - - options = elliptic.curves[options]; - } - - // Shortcut for `elliptic.ec(elliptic.curves.curveName)` - if (options instanceof elliptic.curves.PresetCurve) - options = { curve: options }; - - this.curve = options.curve.curve; - this.n = this.curve.n; - this.nh = this.n.ushrn(1); - this.g = this.curve.g; - - // Point on curve - this.g = options.curve.g; - this.g.precompute(options.curve.n.bitLength() + 1); - - // Hash function for DRBG - this.hash = options.hash || options.curve.hash; -} -module.exports = EC; - -EC.prototype.keyPair = function keyPair(options) { - return new KeyPair(this, options); -}; - -EC.prototype.keyFromPrivate = function keyFromPrivate(priv, enc) { - return KeyPair.fromPrivate(this, priv, enc); -}; - -EC.prototype.keyFromPublic = function keyFromPublic(pub, enc) { - return KeyPair.fromPublic(this, pub, enc); -}; - -EC.prototype.genKeyPair = function genKeyPair(options) { - if (!options) - options = {}; - - // Instantiate Hmac_DRBG - var drbg = new HmacDRBG({ - hash: this.hash, - pers: options.pers, - persEnc: options.persEnc || 'utf8', - entropy: options.entropy || elliptic.rand(this.hash.hmacStrength), - entropyEnc: options.entropy && options.entropyEnc || 'utf8', - nonce: this.n.toArray() - }); - - // Key generation for curve25519 is simpler - if (this.curve.type === 'mont') { - var priv = new BN(drbg.generate(32)); - return this.keyFromPrivate(priv); - } - - var bytes = this.n.byteLength(); - var ns2 = this.n.sub(new BN(2)); - do { - var priv = new BN(drbg.generate(bytes)); - if (priv.cmp(ns2) > 0) - continue; - - priv.iaddn(1); - return this.keyFromPrivate(priv); - } while (true); -}; - -EC.prototype._truncateToN = function truncateToN(msg, truncOnly) { - var delta = msg.byteLength() * 8 - this.n.bitLength(); - if (delta > 0) - msg = msg.ushrn(delta); - if (!truncOnly && msg.cmp(this.n) >= 0) - return msg.sub(this.n); - else - return msg; -}; - -EC.prototype.sign = function sign(msg, key, enc, options) { - if (typeof enc === 'object') { - options = enc; - enc = null; - } - if (!options) - options = {}; - - key = this.keyFromPrivate(key, enc); - msg = this._truncateToN(new BN(msg, 16)); - - // Zero-extend key to provide enough entropy - var bytes = this.n.byteLength(); - var bkey = key.getPrivate().toArray('be', bytes); - - // Zero-extend nonce to have the same byte size as N - var nonce = msg.toArray('be', bytes); - - // Instantiate Hmac_DRBG - var drbg = new HmacDRBG({ - hash: this.hash, - entropy: bkey, - nonce: nonce, - pers: options.pers, - persEnc: options.persEnc || 'utf8' - }); - - // Number of bytes to generate - var ns1 = this.n.sub(new BN(1)); - - for (var iter = 0; true; iter++) { - var k = options.k ? - options.k(iter) : - new BN(drbg.generate(this.n.byteLength())); - k = this._truncateToN(k, true); - if (k.cmpn(1) <= 0 || k.cmp(ns1) >= 0) - continue; - - var kp = this.g.mul(k); - if (kp.isInfinity()) - continue; - - var kpX = kp.getX(); - var r = kpX.umod(this.n); - if (r.cmpn(0) === 0) - continue; - - var s = k.invm(this.n).mul(r.mul(key.getPrivate()).iadd(msg)); - s = s.umod(this.n); - if (s.cmpn(0) === 0) - continue; - - var recoveryParam = (kp.getY().isOdd() ? 1 : 0) | - (kpX.cmp(r) !== 0 ? 2 : 0); - - // Use complement of `s`, if it is > `n / 2` - if (options.canonical && s.cmp(this.nh) > 0) { - s = this.n.sub(s); - recoveryParam ^= 1; - } - - return new Signature({ r: r, s: s, recoveryParam: recoveryParam }); - } -}; - -EC.prototype.verify = function verify(msg, signature, key, enc) { - msg = this._truncateToN(new BN(msg, 16)); - key = this.keyFromPublic(key, enc); - signature = new Signature(signature, 'hex'); - - // Perform primitive values validation - var r = signature.r; - var s = signature.s; - if (r.cmpn(1) < 0 || r.cmp(this.n) >= 0) - return false; - if (s.cmpn(1) < 0 || s.cmp(this.n) >= 0) - return false; - - // Validate signature - var sinv = s.invm(this.n); - var u1 = sinv.mul(msg).umod(this.n); - var u2 = sinv.mul(r).umod(this.n); - - if (!this.curve._maxwellTrick) { - var p = this.g.mulAdd(u1, key.getPublic(), u2); - if (p.isInfinity()) - return false; - - return p.getX().umod(this.n).cmp(r) === 0; - } - - // NOTE: Greg Maxwell's trick, inspired by: - // https://git.io/vad3K - - var p = this.g.jmulAdd(u1, key.getPublic(), u2); - if (p.isInfinity()) - return false; - - // Compare `p.x` of Jacobian point with `r`, - // this will do `p.x == r * p.z^2` instead of multiplying `p.x` by the - // inverse of `p.z^2` - return p.eqXToP(r); -}; - -EC.prototype.recoverPubKey = function(msg, signature, j, enc) { - assert((3 & j) === j, 'The recovery param is more than two bits'); - signature = new Signature(signature, enc); - - var n = this.n; - var e = new BN(msg); - var r = signature.r; - var s = signature.s; - - // A set LSB signifies that the y-coordinate is odd - var isYOdd = j & 1; - var isSecondKey = j >> 1; - if (r.cmp(this.curve.p.umod(this.curve.n)) >= 0 && isSecondKey) - throw new Error('Unable to find sencond key candinate'); - - // 1.1. Let x = r + jn. - if (isSecondKey) - r = this.curve.pointFromX(r.add(this.curve.n), isYOdd); - else - r = this.curve.pointFromX(r, isYOdd); - - var rInv = signature.r.invm(n); - var s1 = n.sub(e).mul(rInv).umod(n); - var s2 = s.mul(rInv).umod(n); - - // 1.6.1 Compute Q = r^-1 (sR - eG) - // Q = r^-1 (sR + -eG) - return this.g.mulAdd(s1, r, s2); -}; - -EC.prototype.getKeyRecoveryParam = function(e, signature, Q, enc) { - signature = new Signature(signature, enc); - if (signature.recoveryParam !== null) - return signature.recoveryParam; - - for (var i = 0; i < 4; i++) { - var Qprime; - try { - Qprime = this.recoverPubKey(e, signature, i); - } catch (e) { - continue; - } - - if (Qprime.eq(Q)) - return i; - } - throw new Error('Unable to find valid recovery factor'); -}; - -},{"../../elliptic":18,"./key":26,"./signature":27,"bn.js":16,"hmac-drbg":46}],26:[function(require,module,exports){ -'use strict'; - -var BN = require('bn.js'); -var elliptic = require('../../elliptic'); -var utils = elliptic.utils; -var assert = utils.assert; - -function KeyPair(ec, options) { - this.ec = ec; - this.priv = null; - this.pub = null; - - // KeyPair(ec, { priv: ..., pub: ... }) - if (options.priv) - this._importPrivate(options.priv, options.privEnc); - if (options.pub) - this._importPublic(options.pub, options.pubEnc); -} -module.exports = KeyPair; - -KeyPair.fromPublic = function fromPublic(ec, pub, enc) { - if (pub instanceof KeyPair) - return pub; - - return new KeyPair(ec, { - pub: pub, - pubEnc: enc - }); -}; - -KeyPair.fromPrivate = function fromPrivate(ec, priv, enc) { - if (priv instanceof KeyPair) - return priv; - - return new KeyPair(ec, { - priv: priv, - privEnc: enc - }); -}; - -// TODO: should not validate for X25519 -KeyPair.prototype.validate = function validate() { - var pub = this.getPublic(); - - if (pub.isInfinity()) - return { result: false, reason: 'Invalid public key' }; - if (!pub.validate()) - return { result: false, reason: 'Public key is not a point' }; - if (!pub.mul(this.ec.curve.n).isInfinity()) - return { result: false, reason: 'Public key * N != O' }; - - return { result: true, reason: null }; -}; - -KeyPair.prototype.getPublic = function getPublic(enc, compact) { - if (!this.pub) - this.pub = this.ec.g.mul(this.priv); - - if (!enc) - return this.pub; - - return this.pub.encode(enc, compact); -}; - -KeyPair.prototype.getPrivate = function getPrivate(enc) { - if (enc === 'hex') - return this.priv.toString(16, 2); - else - return this.priv; -}; - -KeyPair.prototype._importPrivate = function _importPrivate(key, enc) { - this.priv = new BN(key, enc || 16); - - // For Curve25519/Curve448 we have a specific procedure. - // TODO Curve448 - if (this.ec.curve.type === 'mont') { - var one = this.ec.curve.one; - var mask = one.ushln(255 - 3).sub(one).ushln(3); - this.priv = this.priv.or(one.ushln(255 - 1)); - this.priv = this.priv.and(mask); - } else - // Ensure that the priv won't be bigger than n, otherwise we may fail - // in fixed multiplication method - this.priv = this.priv.umod(this.ec.curve.n); -}; - -KeyPair.prototype._importPublic = function _importPublic(key, enc) { - if (key.x || key.y) { - // Montgomery points only have an `x` coordinate. - // Weierstrass/Edwards points on the other hand have both `x` and - // `y` coordinates. - if (this.ec.curve.type === 'mont') { - assert(key.x, 'Need x coordinate'); - } else if (this.ec.curve.type === 'short' || - this.ec.curve.type === 'edwards') { - assert(key.x && key.y, 'Need both x and y coordinate'); - } - this.pub = this.ec.curve.point(key.x, key.y); - return; - } - this.pub = this.ec.curve.decodePoint(key, enc); -}; - -// ECDH -KeyPair.prototype.derive = function derive(pub) { - return pub.mul(this.priv).getX(); -}; - -// ECDSA -KeyPair.prototype.sign = function sign(msg, enc, options) { - return this.ec.sign(msg, this, enc, options); -}; - -KeyPair.prototype.verify = function verify(msg, signature) { - return this.ec.verify(msg, signature, this); -}; - -KeyPair.prototype.inspect = function inspect() { - return ''; -}; - -},{"../../elliptic":18,"bn.js":16}],27:[function(require,module,exports){ -'use strict'; - -var BN = require('bn.js'); - -var elliptic = require('../../elliptic'); -var utils = elliptic.utils; -var assert = utils.assert; - -function Signature(options, enc) { - if (options instanceof Signature) - return options; - - if (this._importDER(options, enc)) - return; - - assert(options.r && options.s, 'Signature without r or s'); - this.r = new BN(options.r, 16); - this.s = new BN(options.s, 16); - if (options.recoveryParam === undefined) - this.recoveryParam = null; - else - this.recoveryParam = options.recoveryParam; -} -module.exports = Signature; - -function Position() { - this.place = 0; -} - -function getLength(buf, p) { - var initial = buf[p.place++]; - if (!(initial & 0x80)) { - return initial; - } - var octetLen = initial & 0xf; - var val = 0; - for (var i = 0, off = p.place; i < octetLen; i++, off++) { - val <<= 8; - val |= buf[off]; - } - p.place = off; - return val; -} - -function rmPadding(buf) { - var i = 0; - var len = buf.length - 1; - while (!buf[i] && !(buf[i + 1] & 0x80) && i < len) { - i++; - } - if (i === 0) { - return buf; - } - return buf.slice(i); -} - -Signature.prototype._importDER = function _importDER(data, enc) { - data = utils.toArray(data, enc); - var p = new Position(); - if (data[p.place++] !== 0x30) { - return false; - } - var len = getLength(data, p); - if ((len + p.place) !== data.length) { - return false; - } - if (data[p.place++] !== 0x02) { - return false; - } - var rlen = getLength(data, p); - var r = data.slice(p.place, rlen + p.place); - p.place += rlen; - if (data[p.place++] !== 0x02) { - return false; - } - var slen = getLength(data, p); - if (data.length !== slen + p.place) { - return false; - } - var s = data.slice(p.place, slen + p.place); - if (r[0] === 0 && (r[1] & 0x80)) { - r = r.slice(1); - } - if (s[0] === 0 && (s[1] & 0x80)) { - s = s.slice(1); - } - - this.r = new BN(r); - this.s = new BN(s); - this.recoveryParam = null; - - return true; -}; - -function constructLength(arr, len) { - if (len < 0x80) { - arr.push(len); - return; - } - var octets = 1 + (Math.log(len) / Math.LN2 >>> 3); - arr.push(octets | 0x80); - while (--octets) { - arr.push((len >>> (octets << 3)) & 0xff); - } - arr.push(len); -} - -Signature.prototype.toDER = function toDER(enc) { - var r = this.r.toArray(); - var s = this.s.toArray(); - - // Pad values - if (r[0] & 0x80) - r = [ 0 ].concat(r); - // Pad values - if (s[0] & 0x80) - s = [ 0 ].concat(s); - - r = rmPadding(r); - s = rmPadding(s); - - while (!s[0] && !(s[1] & 0x80)) { - s = s.slice(1); - } - var arr = [ 0x02 ]; - constructLength(arr, r.length); - arr = arr.concat(r); - arr.push(0x02); - constructLength(arr, s.length); - var backHalf = arr.concat(s); - var res = [ 0x30 ]; - constructLength(res, backHalf.length); - res = res.concat(backHalf); - return utils.encode(res, enc); -}; - -},{"../../elliptic":18,"bn.js":16}],28:[function(require,module,exports){ -'use strict'; - -var hash = require('hash.js'); -var HmacDRBG = require('hmac-drbg'); -var elliptic = require('../../elliptic'); -var utils = elliptic.utils; -var assert = utils.assert; -var parseBytes = utils.parseBytes; -var KeyPair = require('./key'); -var Signature = require('./signature'); - -function EDDSA(curve) { - assert(curve === 'ed25519', 'only tested with ed25519 so far'); - - if (!(this instanceof EDDSA)) - return new EDDSA(curve); - - var curve = elliptic.curves[curve].curve; - this.curve = curve; - this.g = curve.g; - this.g.precompute(curve.n.bitLength() + 1); - - this.pointClass = curve.point().constructor; - this.encodingLength = Math.ceil(curve.n.bitLength() / 8); - this.hash = hash.sha512; -} - -module.exports = EDDSA; - -/** -* @param {Array|String} message - message bytes -* @param {Array|String|KeyPair} secret - secret bytes or a keypair -* @returns {Signature} - signature -*/ -EDDSA.prototype.sign = function sign(message, secret) { - message = parseBytes(message); - var key = this.keyFromSecret(secret); - var r = this.hashInt(key.messagePrefix(), message); - var R = this.g.mul(r); - var Rencoded = this.encodePoint(R); - var s_ = this.hashInt(Rencoded, key.pubBytes(), message) - .mul(key.priv()); - var S = r.add(s_).umod(this.curve.n); - return this.makeSignature({ R: R, S: S, Rencoded: Rencoded }); -}; - -/** -* @param {Array} message - message bytes -* @param {Array|String|Signature} sig - sig bytes -* @param {Array|String|Point|KeyPair} pub - public key -* @returns {Boolean} - true if public key matches sig of message -*/ -EDDSA.prototype.verify = function verify(message, sig, pub) { - message = parseBytes(message); - sig = this.makeSignature(sig); - var key = this.keyFromPublic(pub); - var h = this.hashInt(sig.Rencoded(), key.pubBytes(), message); - var SG = this.g.mul(sig.S()); - var RplusAh = sig.R().add(key.pub().mul(h)); - return RplusAh.eq(SG); -}; - -EDDSA.prototype.hashInt = function hashInt() { - var hash = this.hash(); - for (var i = 0; i < arguments.length; i++) - hash.update(arguments[i]); - return utils.intFromLE(hash.digest()).umod(this.curve.n); -}; - -EDDSA.prototype.keyPair = function keyPair(options) { - return new KeyPair(this, options); -}; - -EDDSA.prototype.keyFromPublic = function keyFromPublic(pub) { - return KeyPair.fromPublic(this, pub); -}; - -EDDSA.prototype.keyFromSecret = function keyFromSecret(secret) { - return KeyPair.fromSecret(this, secret); -}; - -EDDSA.prototype.genKeyPair = function genKeyPair(options) { - if (!options) - options = {}; - - // Instantiate Hmac_DRBG - var drbg = new HmacDRBG({ - hash: this.hash, - pers: options.pers, - persEnc: options.persEnc || 'utf8', - entropy: options.entropy || elliptic.rand(this.hash.hmacStrength), - entropyEnc: options.entropy && options.entropyEnc || 'utf8', - nonce: this.curve.n.toArray() - }); - - return this.keyFromSecret(drbg.generate(32)); -}; - -EDDSA.prototype.makeSignature = function makeSignature(sig) { - if (sig instanceof Signature) - return sig; - return new Signature(this, sig); -}; - -/** -* * https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03#section-5.2 -* -* EDDSA defines methods for encoding and decoding points and integers. These are -* helper convenience methods, that pass along to utility functions implied -* parameters. -* -*/ -EDDSA.prototype.encodePoint = function encodePoint(point) { - var enc = point.getY().toArray('le', this.encodingLength); - enc[this.encodingLength - 1] |= point.getX().isOdd() ? 0x80 : 0; - return enc; -}; - -EDDSA.prototype.decodePoint = function decodePoint(bytes) { - bytes = utils.parseBytes(bytes); - - var lastIx = bytes.length - 1; - var normed = bytes.slice(0, lastIx).concat(bytes[lastIx] & ~0x80); - var xIsOdd = (bytes[lastIx] & 0x80) !== 0; - - var y = utils.intFromLE(normed); - return this.curve.pointFromY(y, xIsOdd); -}; - -EDDSA.prototype.encodeInt = function encodeInt(num) { - return num.toArray('le', this.encodingLength); -}; - -EDDSA.prototype.decodeInt = function decodeInt(bytes) { - return utils.intFromLE(bytes); -}; - -EDDSA.prototype.isPoint = function isPoint(val) { - return val instanceof this.pointClass; -}; - -},{"../../elliptic":18,"./key":29,"./signature":30,"hash.js":34,"hmac-drbg":46}],29:[function(require,module,exports){ -'use strict'; - -var elliptic = require('../../elliptic'); -var utils = elliptic.utils; -var assert = utils.assert; -var parseBytes = utils.parseBytes; -var cachedProperty = utils.cachedProperty; - -/** -* @param {EDDSA} eddsa - instance -* @param {Object} params - public/private key parameters -* -* @param {Array} [params.secret] - secret seed bytes -* @param {Point} [params.pub] - public key point (aka `A` in eddsa terms) -* @param {Array} [params.pub] - public key point encoded as bytes -* -*/ -function KeyPair(eddsa, params) { - this.eddsa = eddsa; - if (params.hasOwnProperty('secret')) - this._secret = parseBytes(params.secret); - if (eddsa.isPoint(params.pub)) - this._pub = params.pub; - else { - this._pubBytes = parseBytes(params.pub); - if (this._pubBytes && this._pubBytes.length === 33 && - this._pubBytes[0] === 0x40) - this._pubBytes = this._pubBytes.slice(1, 33); - if (this._pubBytes && this._pubBytes.length !== 32) - throw new Error('Unknown point compression format'); - } -} - -KeyPair.fromPublic = function fromPublic(eddsa, pub) { - if (pub instanceof KeyPair) - return pub; - return new KeyPair(eddsa, { pub: pub }); -}; - -KeyPair.fromSecret = function fromSecret(eddsa, secret) { - if (secret instanceof KeyPair) - return secret; - return new KeyPair(eddsa, { secret: secret }); -}; - -KeyPair.prototype.secret = function secret() { - return this._secret; -}; - -cachedProperty(KeyPair, 'pubBytes', function pubBytes() { - return this.eddsa.encodePoint(this.pub()); -}); - -cachedProperty(KeyPair, 'pub', function pub() { - if (this._pubBytes) - return this.eddsa.decodePoint(this._pubBytes); - return this.eddsa.g.mul(this.priv()); -}); - -cachedProperty(KeyPair, 'privBytes', function privBytes() { - var eddsa = this.eddsa; - var hash = this.hash(); - var lastIx = eddsa.encodingLength - 1; - - // https://tools.ietf.org/html/rfc8032#section-5.1.5 - var a = hash.slice(0, eddsa.encodingLength); - a[0] &= 248; - a[lastIx] &= 127; - a[lastIx] |= 64; - - return a; -}); - -cachedProperty(KeyPair, 'priv', function priv() { - return this.eddsa.decodeInt(this.privBytes()); -}); - -cachedProperty(KeyPair, 'hash', function hash() { - return this.eddsa.hash().update(this.secret()).digest(); -}); - -cachedProperty(KeyPair, 'messagePrefix', function messagePrefix() { - return this.hash().slice(this.eddsa.encodingLength); -}); - -KeyPair.prototype.sign = function sign(message) { - assert(this._secret, 'KeyPair can only verify'); - return this.eddsa.sign(message, this); -}; - -KeyPair.prototype.verify = function verify(message, sig) { - return this.eddsa.verify(message, sig, this); -}; - -KeyPair.prototype.getSecret = function getSecret(enc) { - assert(this._secret, 'KeyPair is public only'); - return utils.encode(this.secret(), enc); -}; - -KeyPair.prototype.getPublic = function getPublic(enc, compact) { - return utils.encode((compact ? [ 0x40 ] : []).concat(this.pubBytes()), enc); -}; - -module.exports = KeyPair; - -},{"../../elliptic":18}],30:[function(require,module,exports){ -'use strict'; - -var BN = require('bn.js'); -var elliptic = require('../../elliptic'); -var utils = elliptic.utils; -var assert = utils.assert; -var cachedProperty = utils.cachedProperty; -var parseBytes = utils.parseBytes; - -/** -* @param {EDDSA} eddsa - eddsa instance -* @param {Array|Object} sig - -* @param {Array|Point} [sig.R] - R point as Point or bytes -* @param {Array|bn} [sig.S] - S scalar as bn or bytes -* @param {Array} [sig.Rencoded] - R point encoded -* @param {Array} [sig.Sencoded] - S scalar encoded -*/ -function Signature(eddsa, sig) { - this.eddsa = eddsa; - - if (typeof sig !== 'object') - sig = parseBytes(sig); - - if (Array.isArray(sig)) { - sig = { - R: sig.slice(0, eddsa.encodingLength), - S: sig.slice(eddsa.encodingLength) - }; - } - - assert(sig.R && sig.S, 'Signature without R or S'); - - if (eddsa.isPoint(sig.R)) - this._R = sig.R; - if (sig.S instanceof BN) - this._S = sig.S; - - this._Rencoded = Array.isArray(sig.R) ? sig.R : sig.Rencoded; - this._Sencoded = Array.isArray(sig.S) ? sig.S : sig.Sencoded; -} - -cachedProperty(Signature, 'S', function S() { - return this.eddsa.decodeInt(this.Sencoded()); -}); - -cachedProperty(Signature, 'R', function R() { - return this.eddsa.decodePoint(this.Rencoded()); -}); - -cachedProperty(Signature, 'Rencoded', function Rencoded() { - return this.eddsa.encodePoint(this.R()); -}); - -cachedProperty(Signature, 'Sencoded', function Sencoded() { - return this.eddsa.encodeInt(this.S()); -}); - -Signature.prototype.toBytes = function toBytes() { - return this.Rencoded().concat(this.Sencoded()); -}; - -Signature.prototype.toHex = function toHex() { - return utils.encode(this.toBytes(), 'hex').toUpperCase(); -}; - -module.exports = Signature; - -},{"../../elliptic":18,"bn.js":16}],31:[function(require,module,exports){ -module.exports = { - doubles: { - step: 4, - points: [ - [ - 'e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a', - 'f7e3507399e595929db99f34f57937101296891e44d23f0be1f32cce69616821' - ], - [ - '8282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508', - '11f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf' - ], - [ - '175e159f728b865a72f99cc6c6fc846de0b93833fd2222ed73fce5b551e5b739', - 'd3506e0d9e3c79eba4ef97a51ff71f5eacb5955add24345c6efa6ffee9fed695' - ], - [ - '363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640', - '4e273adfc732221953b445397f3363145b9a89008199ecb62003c7f3bee9de9' - ], - [ - '8b4b5f165df3c2be8c6244b5b745638843e4a781a15bcd1b69f79a55dffdf80c', - '4aad0a6f68d308b4b3fbd7813ab0da04f9e336546162ee56b3eff0c65fd4fd36' - ], - [ - '723cbaa6e5db996d6bf771c00bd548c7b700dbffa6c0e77bcb6115925232fcda', - '96e867b5595cc498a921137488824d6e2660a0653779494801dc069d9eb39f5f' - ], - [ - 'eebfa4d493bebf98ba5feec812c2d3b50947961237a919839a533eca0e7dd7fa', - '5d9a8ca3970ef0f269ee7edaf178089d9ae4cdc3a711f712ddfd4fdae1de8999' - ], - [ - '100f44da696e71672791d0a09b7bde459f1215a29b3c03bfefd7835b39a48db0', - 'cdd9e13192a00b772ec8f3300c090666b7ff4a18ff5195ac0fbd5cd62bc65a09' - ], - [ - 'e1031be262c7ed1b1dc9227a4a04c017a77f8d4464f3b3852c8acde6e534fd2d', - '9d7061928940405e6bb6a4176597535af292dd419e1ced79a44f18f29456a00d' - ], - [ - 'feea6cae46d55b530ac2839f143bd7ec5cf8b266a41d6af52d5e688d9094696d', - 'e57c6b6c97dce1bab06e4e12bf3ecd5c981c8957cc41442d3155debf18090088' - ], - [ - 'da67a91d91049cdcb367be4be6ffca3cfeed657d808583de33fa978bc1ec6cb1', - '9bacaa35481642bc41f463f7ec9780e5dec7adc508f740a17e9ea8e27a68be1d' - ], - [ - '53904faa0b334cdda6e000935ef22151ec08d0f7bb11069f57545ccc1a37b7c0', - '5bc087d0bc80106d88c9eccac20d3c1c13999981e14434699dcb096b022771c8' - ], - [ - '8e7bcd0bd35983a7719cca7764ca906779b53a043a9b8bcaeff959f43ad86047', - '10b7770b2a3da4b3940310420ca9514579e88e2e47fd68b3ea10047e8460372a' - ], - [ - '385eed34c1cdff21e6d0818689b81bde71a7f4f18397e6690a841e1599c43862', - '283bebc3e8ea23f56701de19e9ebf4576b304eec2086dc8cc0458fe5542e5453' - ], - [ - '6f9d9b803ecf191637c73a4413dfa180fddf84a5947fbc9c606ed86c3fac3a7', - '7c80c68e603059ba69b8e2a30e45c4d47ea4dd2f5c281002d86890603a842160' - ], - [ - '3322d401243c4e2582a2147c104d6ecbf774d163db0f5e5313b7e0e742d0e6bd', - '56e70797e9664ef5bfb019bc4ddaf9b72805f63ea2873af624f3a2e96c28b2a0' - ], - [ - '85672c7d2de0b7da2bd1770d89665868741b3f9af7643397721d74d28134ab83', - '7c481b9b5b43b2eb6374049bfa62c2e5e77f17fcc5298f44c8e3094f790313a6' - ], - [ - '948bf809b1988a46b06c9f1919413b10f9226c60f668832ffd959af60c82a0a', - '53a562856dcb6646dc6b74c5d1c3418c6d4dff08c97cd2bed4cb7f88d8c8e589' - ], - [ - '6260ce7f461801c34f067ce0f02873a8f1b0e44dfc69752accecd819f38fd8e8', - 'bc2da82b6fa5b571a7f09049776a1ef7ecd292238051c198c1a84e95b2b4ae17' - ], - [ - 'e5037de0afc1d8d43d8348414bbf4103043ec8f575bfdc432953cc8d2037fa2d', - '4571534baa94d3b5f9f98d09fb990bddbd5f5b03ec481f10e0e5dc841d755bda' - ], - [ - 'e06372b0f4a207adf5ea905e8f1771b4e7e8dbd1c6a6c5b725866a0ae4fce725', - '7a908974bce18cfe12a27bb2ad5a488cd7484a7787104870b27034f94eee31dd' - ], - [ - '213c7a715cd5d45358d0bbf9dc0ce02204b10bdde2a3f58540ad6908d0559754', - '4b6dad0b5ae462507013ad06245ba190bb4850f5f36a7eeddff2c27534b458f2' - ], - [ - '4e7c272a7af4b34e8dbb9352a5419a87e2838c70adc62cddf0cc3a3b08fbd53c', - '17749c766c9d0b18e16fd09f6def681b530b9614bff7dd33e0b3941817dcaae6' - ], - [ - 'fea74e3dbe778b1b10f238ad61686aa5c76e3db2be43057632427e2840fb27b6', - '6e0568db9b0b13297cf674deccb6af93126b596b973f7b77701d3db7f23cb96f' - ], - [ - '76e64113f677cf0e10a2570d599968d31544e179b760432952c02a4417bdde39', - 'c90ddf8dee4e95cf577066d70681f0d35e2a33d2b56d2032b4b1752d1901ac01' - ], - [ - 'c738c56b03b2abe1e8281baa743f8f9a8f7cc643df26cbee3ab150242bcbb891', - '893fb578951ad2537f718f2eacbfbbbb82314eef7880cfe917e735d9699a84c3' - ], - [ - 'd895626548b65b81e264c7637c972877d1d72e5f3a925014372e9f6588f6c14b', - 'febfaa38f2bc7eae728ec60818c340eb03428d632bb067e179363ed75d7d991f' - ], - [ - 'b8da94032a957518eb0f6433571e8761ceffc73693e84edd49150a564f676e03', - '2804dfa44805a1e4d7c99cc9762808b092cc584d95ff3b511488e4e74efdf6e7' - ], - [ - 'e80fea14441fb33a7d8adab9475d7fab2019effb5156a792f1a11778e3c0df5d', - 'eed1de7f638e00771e89768ca3ca94472d155e80af322ea9fcb4291b6ac9ec78' - ], - [ - 'a301697bdfcd704313ba48e51d567543f2a182031efd6915ddc07bbcc4e16070', - '7370f91cfb67e4f5081809fa25d40f9b1735dbf7c0a11a130c0d1a041e177ea1' - ], - [ - '90ad85b389d6b936463f9d0512678de208cc330b11307fffab7ac63e3fb04ed4', - 'e507a3620a38261affdcbd9427222b839aefabe1582894d991d4d48cb6ef150' - ], - [ - '8f68b9d2f63b5f339239c1ad981f162ee88c5678723ea3351b7b444c9ec4c0da', - '662a9f2dba063986de1d90c2b6be215dbbea2cfe95510bfdf23cbf79501fff82' - ], - [ - 'e4f3fb0176af85d65ff99ff9198c36091f48e86503681e3e6686fd5053231e11', - '1e63633ad0ef4f1c1661a6d0ea02b7286cc7e74ec951d1c9822c38576feb73bc' - ], - [ - '8c00fa9b18ebf331eb961537a45a4266c7034f2f0d4e1d0716fb6eae20eae29e', - 'efa47267fea521a1a9dc343a3736c974c2fadafa81e36c54e7d2a4c66702414b' - ], - [ - 'e7a26ce69dd4829f3e10cec0a9e98ed3143d084f308b92c0997fddfc60cb3e41', - '2a758e300fa7984b471b006a1aafbb18d0a6b2c0420e83e20e8a9421cf2cfd51' - ], - [ - 'b6459e0ee3662ec8d23540c223bcbdc571cbcb967d79424f3cf29eb3de6b80ef', - '67c876d06f3e06de1dadf16e5661db3c4b3ae6d48e35b2ff30bf0b61a71ba45' - ], - [ - 'd68a80c8280bb840793234aa118f06231d6f1fc67e73c5a5deda0f5b496943e8', - 'db8ba9fff4b586d00c4b1f9177b0e28b5b0e7b8f7845295a294c84266b133120' - ], - [ - '324aed7df65c804252dc0270907a30b09612aeb973449cea4095980fc28d3d5d', - '648a365774b61f2ff130c0c35aec1f4f19213b0c7e332843967224af96ab7c84' - ], - [ - '4df9c14919cde61f6d51dfdbe5fee5dceec4143ba8d1ca888e8bd373fd054c96', - '35ec51092d8728050974c23a1d85d4b5d506cdc288490192ebac06cad10d5d' - ], - [ - '9c3919a84a474870faed8a9c1cc66021523489054d7f0308cbfc99c8ac1f98cd', - 'ddb84f0f4a4ddd57584f044bf260e641905326f76c64c8e6be7e5e03d4fc599d' - ], - [ - '6057170b1dd12fdf8de05f281d8e06bb91e1493a8b91d4cc5a21382120a959e5', - '9a1af0b26a6a4807add9a2daf71df262465152bc3ee24c65e899be932385a2a8' - ], - [ - 'a576df8e23a08411421439a4518da31880cef0fba7d4df12b1a6973eecb94266', - '40a6bf20e76640b2c92b97afe58cd82c432e10a7f514d9f3ee8be11ae1b28ec8' - ], - [ - '7778a78c28dec3e30a05fe9629de8c38bb30d1f5cf9a3a208f763889be58ad71', - '34626d9ab5a5b22ff7098e12f2ff580087b38411ff24ac563b513fc1fd9f43ac' - ], - [ - '928955ee637a84463729fd30e7afd2ed5f96274e5ad7e5cb09eda9c06d903ac', - 'c25621003d3f42a827b78a13093a95eeac3d26efa8a8d83fc5180e935bcd091f' - ], - [ - '85d0fef3ec6db109399064f3a0e3b2855645b4a907ad354527aae75163d82751', - '1f03648413a38c0be29d496e582cf5663e8751e96877331582c237a24eb1f962' - ], - [ - 'ff2b0dce97eece97c1c9b6041798b85dfdfb6d8882da20308f5404824526087e', - '493d13fef524ba188af4c4dc54d07936c7b7ed6fb90e2ceb2c951e01f0c29907' - ], - [ - '827fbbe4b1e880ea9ed2b2e6301b212b57f1ee148cd6dd28780e5e2cf856e241', - 'c60f9c923c727b0b71bef2c67d1d12687ff7a63186903166d605b68baec293ec' - ], - [ - 'eaa649f21f51bdbae7be4ae34ce6e5217a58fdce7f47f9aa7f3b58fa2120e2b3', - 'be3279ed5bbbb03ac69a80f89879aa5a01a6b965f13f7e59d47a5305ba5ad93d' - ], - [ - 'e4a42d43c5cf169d9391df6decf42ee541b6d8f0c9a137401e23632dda34d24f', - '4d9f92e716d1c73526fc99ccfb8ad34ce886eedfa8d8e4f13a7f7131deba9414' - ], - [ - '1ec80fef360cbdd954160fadab352b6b92b53576a88fea4947173b9d4300bf19', - 'aeefe93756b5340d2f3a4958a7abbf5e0146e77f6295a07b671cdc1cc107cefd' - ], - [ - '146a778c04670c2f91b00af4680dfa8bce3490717d58ba889ddb5928366642be', - 'b318e0ec3354028add669827f9d4b2870aaa971d2f7e5ed1d0b297483d83efd0' - ], - [ - 'fa50c0f61d22e5f07e3acebb1aa07b128d0012209a28b9776d76a8793180eef9', - '6b84c6922397eba9b72cd2872281a68a5e683293a57a213b38cd8d7d3f4f2811' - ], - [ - 'da1d61d0ca721a11b1a5bf6b7d88e8421a288ab5d5bba5220e53d32b5f067ec2', - '8157f55a7c99306c79c0766161c91e2966a73899d279b48a655fba0f1ad836f1' - ], - [ - 'a8e282ff0c9706907215ff98e8fd416615311de0446f1e062a73b0610d064e13', - '7f97355b8db81c09abfb7f3c5b2515888b679a3e50dd6bd6cef7c73111f4cc0c' - ], - [ - '174a53b9c9a285872d39e56e6913cab15d59b1fa512508c022f382de8319497c', - 'ccc9dc37abfc9c1657b4155f2c47f9e6646b3a1d8cb9854383da13ac079afa73' - ], - [ - '959396981943785c3d3e57edf5018cdbe039e730e4918b3d884fdff09475b7ba', - '2e7e552888c331dd8ba0386a4b9cd6849c653f64c8709385e9b8abf87524f2fd' - ], - [ - 'd2a63a50ae401e56d645a1153b109a8fcca0a43d561fba2dbb51340c9d82b151', - 'e82d86fb6443fcb7565aee58b2948220a70f750af484ca52d4142174dcf89405' - ], - [ - '64587e2335471eb890ee7896d7cfdc866bacbdbd3839317b3436f9b45617e073', - 'd99fcdd5bf6902e2ae96dd6447c299a185b90a39133aeab358299e5e9faf6589' - ], - [ - '8481bde0e4e4d885b3a546d3e549de042f0aa6cea250e7fd358d6c86dd45e458', - '38ee7b8cba5404dd84a25bf39cecb2ca900a79c42b262e556d64b1b59779057e' - ], - [ - '13464a57a78102aa62b6979ae817f4637ffcfed3c4b1ce30bcd6303f6caf666b', - '69be159004614580ef7e433453ccb0ca48f300a81d0942e13f495a907f6ecc27' - ], - [ - 'bc4a9df5b713fe2e9aef430bcc1dc97a0cd9ccede2f28588cada3a0d2d83f366', - 'd3a81ca6e785c06383937adf4b798caa6e8a9fbfa547b16d758d666581f33c1' - ], - [ - '8c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa', - '40a30463a3305193378fedf31f7cc0eb7ae784f0451cb9459e71dc73cbef9482' - ], - [ - '8ea9666139527a8c1dd94ce4f071fd23c8b350c5a4bb33748c4ba111faccae0', - '620efabbc8ee2782e24e7c0cfb95c5d735b783be9cf0f8e955af34a30e62b945' - ], - [ - 'dd3625faef5ba06074669716bbd3788d89bdde815959968092f76cc4eb9a9787', - '7a188fa3520e30d461da2501045731ca941461982883395937f68d00c644a573' - ], - [ - 'f710d79d9eb962297e4f6232b40e8f7feb2bc63814614d692c12de752408221e', - 'ea98e67232d3b3295d3b535532115ccac8612c721851617526ae47a9c77bfc82' - ] - ] - }, - naf: { - wnd: 7, - points: [ - [ - 'f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9', - '388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672' - ], - [ - '2f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4', - 'd8ac222636e5e3d6d4dba9dda6c9c426f788271bab0d6840dca87d3aa6ac62d6' - ], - [ - '5cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc', - '6aebca40ba255960a3178d6d861a54dba813d0b813fde7b5a5082628087264da' - ], - [ - 'acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe', - 'cc338921b0a7d9fd64380971763b61e9add888a4375f8e0f05cc262ac64f9c37' - ], - [ - '774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb', - 'd984a032eb6b5e190243dd56d7b7b365372db1e2dff9d6a8301d74c9c953c61b' - ], - [ - 'f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8', - 'ab0902e8d880a89758212eb65cdaf473a1a06da521fa91f29b5cb52db03ed81' - ], - [ - 'd7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e', - '581e2872a86c72a683842ec228cc6defea40af2bd896d3a5c504dc9ff6a26b58' - ], - [ - 'defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34', - '4211ab0694635168e997b0ead2a93daeced1f4a04a95c0f6cfb199f69e56eb77' - ], - [ - '2b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c', - '85e89bc037945d93b343083b5a1c86131a01f60c50269763b570c854e5c09b7a' - ], - [ - '352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5', - '321eb4075348f534d59c18259dda3e1f4a1b3b2e71b1039c67bd3d8bcf81998c' - ], - [ - '2fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f', - '2de1068295dd865b64569335bd5dd80181d70ecfc882648423ba76b532b7d67' - ], - [ - '9248279b09b4d68dab21a9b066edda83263c3d84e09572e269ca0cd7f5453714', - '73016f7bf234aade5d1aa71bdea2b1ff3fc0de2a887912ffe54a32ce97cb3402' - ], - [ - 'daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729', - 'a69dce4a7d6c98e8d4a1aca87ef8d7003f83c230f3afa726ab40e52290be1c55' - ], - [ - 'c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db', - '2119a460ce326cdc76c45926c982fdac0e106e861edf61c5a039063f0e0e6482' - ], - [ - '6a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4', - 'e022cf42c2bd4a708b3f5126f16a24ad8b33ba48d0423b6efd5e6348100d8a82' - ], - [ - '1697ffa6fd9de627c077e3d2fe541084ce13300b0bec1146f95ae57f0d0bd6a5', - 'b9c398f186806f5d27561506e4557433a2cf15009e498ae7adee9d63d01b2396' - ], - [ - '605bdb019981718b986d0f07e834cb0d9deb8360ffb7f61df982345ef27a7479', - '2972d2de4f8d20681a78d93ec96fe23c26bfae84fb14db43b01e1e9056b8c49' - ], - [ - '62d14dab4150bf497402fdc45a215e10dcb01c354959b10cfe31c7e9d87ff33d', - '80fc06bd8cc5b01098088a1950eed0db01aa132967ab472235f5642483b25eaf' - ], - [ - '80c60ad0040f27dade5b4b06c408e56b2c50e9f56b9b8b425e555c2f86308b6f', - '1c38303f1cc5c30f26e66bad7fe72f70a65eed4cbe7024eb1aa01f56430bd57a' - ], - [ - '7a9375ad6167ad54aa74c6348cc54d344cc5dc9487d847049d5eabb0fa03c8fb', - 'd0e3fa9eca8726909559e0d79269046bdc59ea10c70ce2b02d499ec224dc7f7' - ], - [ - 'd528ecd9b696b54c907a9ed045447a79bb408ec39b68df504bb51f459bc3ffc9', - 'eecf41253136e5f99966f21881fd656ebc4345405c520dbc063465b521409933' - ], - [ - '49370a4b5f43412ea25f514e8ecdad05266115e4a7ecb1387231808f8b45963', - '758f3f41afd6ed428b3081b0512fd62a54c3f3afbb5b6764b653052a12949c9a' - ], - [ - '77f230936ee88cbbd73df930d64702ef881d811e0e1498e2f1c13eb1fc345d74', - '958ef42a7886b6400a08266e9ba1b37896c95330d97077cbbe8eb3c7671c60d6' - ], - [ - 'f2dac991cc4ce4b9ea44887e5c7c0bce58c80074ab9d4dbaeb28531b7739f530', - 'e0dedc9b3b2f8dad4da1f32dec2531df9eb5fbeb0598e4fd1a117dba703a3c37' - ], - [ - '463b3d9f662621fb1b4be8fbbe2520125a216cdfc9dae3debcba4850c690d45b', - '5ed430d78c296c3543114306dd8622d7c622e27c970a1de31cb377b01af7307e' - ], - [ - 'f16f804244e46e2a09232d4aff3b59976b98fac14328a2d1a32496b49998f247', - 'cedabd9b82203f7e13d206fcdf4e33d92a6c53c26e5cce26d6579962c4e31df6' - ], - [ - 'caf754272dc84563b0352b7a14311af55d245315ace27c65369e15f7151d41d1', - 'cb474660ef35f5f2a41b643fa5e460575f4fa9b7962232a5c32f908318a04476' - ], - [ - '2600ca4b282cb986f85d0f1709979d8b44a09c07cb86d7c124497bc86f082120', - '4119b88753c15bd6a693b03fcddbb45d5ac6be74ab5f0ef44b0be9475a7e4b40' - ], - [ - '7635ca72d7e8432c338ec53cd12220bc01c48685e24f7dc8c602a7746998e435', - '91b649609489d613d1d5e590f78e6d74ecfc061d57048bad9e76f302c5b9c61' - ], - [ - '754e3239f325570cdbbf4a87deee8a66b7f2b33479d468fbc1a50743bf56cc18', - '673fb86e5bda30fb3cd0ed304ea49a023ee33d0197a695d0c5d98093c536683' - ], - [ - 'e3e6bd1071a1e96aff57859c82d570f0330800661d1c952f9fe2694691d9b9e8', - '59c9e0bba394e76f40c0aa58379a3cb6a5a2283993e90c4167002af4920e37f5' - ], - [ - '186b483d056a033826ae73d88f732985c4ccb1f32ba35f4b4cc47fdcf04aa6eb', - '3b952d32c67cf77e2e17446e204180ab21fb8090895138b4a4a797f86e80888b' - ], - [ - 'df9d70a6b9876ce544c98561f4be4f725442e6d2b737d9c91a8321724ce0963f', - '55eb2dafd84d6ccd5f862b785dc39d4ab157222720ef9da217b8c45cf2ba2417' - ], - [ - '5edd5cc23c51e87a497ca815d5dce0f8ab52554f849ed8995de64c5f34ce7143', - 'efae9c8dbc14130661e8cec030c89ad0c13c66c0d17a2905cdc706ab7399a868' - ], - [ - '290798c2b6476830da12fe02287e9e777aa3fba1c355b17a722d362f84614fba', - 'e38da76dcd440621988d00bcf79af25d5b29c094db2a23146d003afd41943e7a' - ], - [ - 'af3c423a95d9f5b3054754efa150ac39cd29552fe360257362dfdecef4053b45', - 'f98a3fd831eb2b749a93b0e6f35cfb40c8cd5aa667a15581bc2feded498fd9c6' - ], - [ - '766dbb24d134e745cccaa28c99bf274906bb66b26dcf98df8d2fed50d884249a', - '744b1152eacbe5e38dcc887980da38b897584a65fa06cedd2c924f97cbac5996' - ], - [ - '59dbf46f8c94759ba21277c33784f41645f7b44f6c596a58ce92e666191abe3e', - 'c534ad44175fbc300f4ea6ce648309a042ce739a7919798cd85e216c4a307f6e' - ], - [ - 'f13ada95103c4537305e691e74e9a4a8dd647e711a95e73cb62dc6018cfd87b8', - 'e13817b44ee14de663bf4bc808341f326949e21a6a75c2570778419bdaf5733d' - ], - [ - '7754b4fa0e8aced06d4167a2c59cca4cda1869c06ebadfb6488550015a88522c', - '30e93e864e669d82224b967c3020b8fa8d1e4e350b6cbcc537a48b57841163a2' - ], - [ - '948dcadf5990e048aa3874d46abef9d701858f95de8041d2a6828c99e2262519', - 'e491a42537f6e597d5d28a3224b1bc25df9154efbd2ef1d2cbba2cae5347d57e' - ], - [ - '7962414450c76c1689c7b48f8202ec37fb224cf5ac0bfa1570328a8a3d7c77ab', - '100b610ec4ffb4760d5c1fc133ef6f6b12507a051f04ac5760afa5b29db83437' - ], - [ - '3514087834964b54b15b160644d915485a16977225b8847bb0dd085137ec47ca', - 'ef0afbb2056205448e1652c48e8127fc6039e77c15c2378b7e7d15a0de293311' - ], - [ - 'd3cc30ad6b483e4bc79ce2c9dd8bc54993e947eb8df787b442943d3f7b527eaf', - '8b378a22d827278d89c5e9be8f9508ae3c2ad46290358630afb34db04eede0a4' - ], - [ - '1624d84780732860ce1c78fcbfefe08b2b29823db913f6493975ba0ff4847610', - '68651cf9b6da903e0914448c6cd9d4ca896878f5282be4c8cc06e2a404078575' - ], - [ - '733ce80da955a8a26902c95633e62a985192474b5af207da6df7b4fd5fc61cd4', - 'f5435a2bd2badf7d485a4d8b8db9fcce3e1ef8e0201e4578c54673bc1dc5ea1d' - ], - [ - '15d9441254945064cf1a1c33bbd3b49f8966c5092171e699ef258dfab81c045c', - 'd56eb30b69463e7234f5137b73b84177434800bacebfc685fc37bbe9efe4070d' - ], - [ - 'a1d0fcf2ec9de675b612136e5ce70d271c21417c9d2b8aaaac138599d0717940', - 'edd77f50bcb5a3cab2e90737309667f2641462a54070f3d519212d39c197a629' - ], - [ - 'e22fbe15c0af8ccc5780c0735f84dbe9a790badee8245c06c7ca37331cb36980', - 'a855babad5cd60c88b430a69f53a1a7a38289154964799be43d06d77d31da06' - ], - [ - '311091dd9860e8e20ee13473c1155f5f69635e394704eaa74009452246cfa9b3', - '66db656f87d1f04fffd1f04788c06830871ec5a64feee685bd80f0b1286d8374' - ], - [ - '34c1fd04d301be89b31c0442d3e6ac24883928b45a9340781867d4232ec2dbdf', - '9414685e97b1b5954bd46f730174136d57f1ceeb487443dc5321857ba73abee' - ], - [ - 'f219ea5d6b54701c1c14de5b557eb42a8d13f3abbcd08affcc2a5e6b049b8d63', - '4cb95957e83d40b0f73af4544cccf6b1f4b08d3c07b27fb8d8c2962a400766d1' - ], - [ - 'd7b8740f74a8fbaab1f683db8f45de26543a5490bca627087236912469a0b448', - 'fa77968128d9c92ee1010f337ad4717eff15db5ed3c049b3411e0315eaa4593b' - ], - [ - '32d31c222f8f6f0ef86f7c98d3a3335ead5bcd32abdd94289fe4d3091aa824bf', - '5f3032f5892156e39ccd3d7915b9e1da2e6dac9e6f26e961118d14b8462e1661' - ], - [ - '7461f371914ab32671045a155d9831ea8793d77cd59592c4340f86cbc18347b5', - '8ec0ba238b96bec0cbdddcae0aa442542eee1ff50c986ea6b39847b3cc092ff6' - ], - [ - 'ee079adb1df1860074356a25aa38206a6d716b2c3e67453d287698bad7b2b2d6', - '8dc2412aafe3be5c4c5f37e0ecc5f9f6a446989af04c4e25ebaac479ec1c8c1e' - ], - [ - '16ec93e447ec83f0467b18302ee620f7e65de331874c9dc72bfd8616ba9da6b5', - '5e4631150e62fb40d0e8c2a7ca5804a39d58186a50e497139626778e25b0674d' - ], - [ - 'eaa5f980c245f6f038978290afa70b6bd8855897f98b6aa485b96065d537bd99', - 'f65f5d3e292c2e0819a528391c994624d784869d7e6ea67fb18041024edc07dc' - ], - [ - '78c9407544ac132692ee1910a02439958ae04877151342ea96c4b6b35a49f51', - 'f3e0319169eb9b85d5404795539a5e68fa1fbd583c064d2462b675f194a3ddb4' - ], - [ - '494f4be219a1a77016dcd838431aea0001cdc8ae7a6fc688726578d9702857a5', - '42242a969283a5f339ba7f075e36ba2af925ce30d767ed6e55f4b031880d562c' - ], - [ - 'a598a8030da6d86c6bc7f2f5144ea549d28211ea58faa70ebf4c1e665c1fe9b5', - '204b5d6f84822c307e4b4a7140737aec23fc63b65b35f86a10026dbd2d864e6b' - ], - [ - 'c41916365abb2b5d09192f5f2dbeafec208f020f12570a184dbadc3e58595997', - '4f14351d0087efa49d245b328984989d5caf9450f34bfc0ed16e96b58fa9913' - ], - [ - '841d6063a586fa475a724604da03bc5b92a2e0d2e0a36acfe4c73a5514742881', - '73867f59c0659e81904f9a1c7543698e62562d6744c169ce7a36de01a8d6154' - ], - [ - '5e95bb399a6971d376026947f89bde2f282b33810928be4ded112ac4d70e20d5', - '39f23f366809085beebfc71181313775a99c9aed7d8ba38b161384c746012865' - ], - [ - '36e4641a53948fd476c39f8a99fd974e5ec07564b5315d8bf99471bca0ef2f66', - 'd2424b1b1abe4eb8164227b085c9aa9456ea13493fd563e06fd51cf5694c78fc' - ], - [ - '336581ea7bfbbb290c191a2f507a41cf5643842170e914faeab27c2c579f726', - 'ead12168595fe1be99252129b6e56b3391f7ab1410cd1e0ef3dcdcabd2fda224' - ], - [ - '8ab89816dadfd6b6a1f2634fcf00ec8403781025ed6890c4849742706bd43ede', - '6fdcef09f2f6d0a044e654aef624136f503d459c3e89845858a47a9129cdd24e' - ], - [ - '1e33f1a746c9c5778133344d9299fcaa20b0938e8acff2544bb40284b8c5fb94', - '60660257dd11b3aa9c8ed618d24edff2306d320f1d03010e33a7d2057f3b3b6' - ], - [ - '85b7c1dcb3cec1b7ee7f30ded79dd20a0ed1f4cc18cbcfcfa410361fd8f08f31', - '3d98a9cdd026dd43f39048f25a8847f4fcafad1895d7a633c6fed3c35e999511' - ], - [ - '29df9fbd8d9e46509275f4b125d6d45d7fbe9a3b878a7af872a2800661ac5f51', - 'b4c4fe99c775a606e2d8862179139ffda61dc861c019e55cd2876eb2a27d84b' - ], - [ - 'a0b1cae06b0a847a3fea6e671aaf8adfdfe58ca2f768105c8082b2e449fce252', - 'ae434102edde0958ec4b19d917a6a28e6b72da1834aff0e650f049503a296cf2' - ], - [ - '4e8ceafb9b3e9a136dc7ff67e840295b499dfb3b2133e4ba113f2e4c0e121e5', - 'cf2174118c8b6d7a4b48f6d534ce5c79422c086a63460502b827ce62a326683c' - ], - [ - 'd24a44e047e19b6f5afb81c7ca2f69080a5076689a010919f42725c2b789a33b', - '6fb8d5591b466f8fc63db50f1c0f1c69013f996887b8244d2cdec417afea8fa3' - ], - [ - 'ea01606a7a6c9cdd249fdfcfacb99584001edd28abbab77b5104e98e8e3b35d4', - '322af4908c7312b0cfbfe369f7a7b3cdb7d4494bc2823700cfd652188a3ea98d' - ], - [ - 'af8addbf2b661c8a6c6328655eb96651252007d8c5ea31be4ad196de8ce2131f', - '6749e67c029b85f52a034eafd096836b2520818680e26ac8f3dfbcdb71749700' - ], - [ - 'e3ae1974566ca06cc516d47e0fb165a674a3dabcfca15e722f0e3450f45889', - '2aeabe7e4531510116217f07bf4d07300de97e4874f81f533420a72eeb0bd6a4' - ], - [ - '591ee355313d99721cf6993ffed1e3e301993ff3ed258802075ea8ced397e246', - 'b0ea558a113c30bea60fc4775460c7901ff0b053d25ca2bdeee98f1a4be5d196' - ], - [ - '11396d55fda54c49f19aa97318d8da61fa8584e47b084945077cf03255b52984', - '998c74a8cd45ac01289d5833a7beb4744ff536b01b257be4c5767bea93ea57a4' - ], - [ - '3c5d2a1ba39c5a1790000738c9e0c40b8dcdfd5468754b6405540157e017aa7a', - 'b2284279995a34e2f9d4de7396fc18b80f9b8b9fdd270f6661f79ca4c81bd257' - ], - [ - 'cc8704b8a60a0defa3a99a7299f2e9c3fbc395afb04ac078425ef8a1793cc030', - 'bdd46039feed17881d1e0862db347f8cf395b74fc4bcdc4e940b74e3ac1f1b13' - ], - [ - 'c533e4f7ea8555aacd9777ac5cad29b97dd4defccc53ee7ea204119b2889b197', - '6f0a256bc5efdf429a2fb6242f1a43a2d9b925bb4a4b3a26bb8e0f45eb596096' - ], - [ - 'c14f8f2ccb27d6f109f6d08d03cc96a69ba8c34eec07bbcf566d48e33da6593', - 'c359d6923bb398f7fd4473e16fe1c28475b740dd098075e6c0e8649113dc3a38' - ], - [ - 'a6cbc3046bc6a450bac24789fa17115a4c9739ed75f8f21ce441f72e0b90e6ef', - '21ae7f4680e889bb130619e2c0f95a360ceb573c70603139862afd617fa9b9f' - ], - [ - '347d6d9a02c48927ebfb86c1359b1caf130a3c0267d11ce6344b39f99d43cc38', - '60ea7f61a353524d1c987f6ecec92f086d565ab687870cb12689ff1e31c74448' - ], - [ - 'da6545d2181db8d983f7dcb375ef5866d47c67b1bf31c8cf855ef7437b72656a', - '49b96715ab6878a79e78f07ce5680c5d6673051b4935bd897fea824b77dc208a' - ], - [ - 'c40747cc9d012cb1a13b8148309c6de7ec25d6945d657146b9d5994b8feb1111', - '5ca560753be2a12fc6de6caf2cb489565db936156b9514e1bb5e83037e0fa2d4' - ], - [ - '4e42c8ec82c99798ccf3a610be870e78338c7f713348bd34c8203ef4037f3502', - '7571d74ee5e0fb92a7a8b33a07783341a5492144cc54bcc40a94473693606437' - ], - [ - '3775ab7089bc6af823aba2e1af70b236d251cadb0c86743287522a1b3b0dedea', - 'be52d107bcfa09d8bcb9736a828cfa7fac8db17bf7a76a2c42ad961409018cf7' - ], - [ - 'cee31cbf7e34ec379d94fb814d3d775ad954595d1314ba8846959e3e82f74e26', - '8fd64a14c06b589c26b947ae2bcf6bfa0149ef0be14ed4d80f448a01c43b1c6d' - ], - [ - 'b4f9eaea09b6917619f6ea6a4eb5464efddb58fd45b1ebefcdc1a01d08b47986', - '39e5c9925b5a54b07433a4f18c61726f8bb131c012ca542eb24a8ac07200682a' - ], - [ - 'd4263dfc3d2df923a0179a48966d30ce84e2515afc3dccc1b77907792ebcc60e', - '62dfaf07a0f78feb30e30d6295853ce189e127760ad6cf7fae164e122a208d54' - ], - [ - '48457524820fa65a4f8d35eb6930857c0032acc0a4a2de422233eeda897612c4', - '25a748ab367979d98733c38a1fa1c2e7dc6cc07db2d60a9ae7a76aaa49bd0f77' - ], - [ - 'dfeeef1881101f2cb11644f3a2afdfc2045e19919152923f367a1767c11cceda', - 'ecfb7056cf1de042f9420bab396793c0c390bde74b4bbdff16a83ae09a9a7517' - ], - [ - '6d7ef6b17543f8373c573f44e1f389835d89bcbc6062ced36c82df83b8fae859', - 'cd450ec335438986dfefa10c57fea9bcc521a0959b2d80bbf74b190dca712d10' - ], - [ - 'e75605d59102a5a2684500d3b991f2e3f3c88b93225547035af25af66e04541f', - 'f5c54754a8f71ee540b9b48728473e314f729ac5308b06938360990e2bfad125' - ], - [ - 'eb98660f4c4dfaa06a2be453d5020bc99a0c2e60abe388457dd43fefb1ed620c', - '6cb9a8876d9cb8520609af3add26cd20a0a7cd8a9411131ce85f44100099223e' - ], - [ - '13e87b027d8514d35939f2e6892b19922154596941888336dc3563e3b8dba942', - 'fef5a3c68059a6dec5d624114bf1e91aac2b9da568d6abeb2570d55646b8adf1' - ], - [ - 'ee163026e9fd6fe017c38f06a5be6fc125424b371ce2708e7bf4491691e5764a', - '1acb250f255dd61c43d94ccc670d0f58f49ae3fa15b96623e5430da0ad6c62b2' - ], - [ - 'b268f5ef9ad51e4d78de3a750c2dc89b1e626d43505867999932e5db33af3d80', - '5f310d4b3c99b9ebb19f77d41c1dee018cf0d34fd4191614003e945a1216e423' - ], - [ - 'ff07f3118a9df035e9fad85eb6c7bfe42b02f01ca99ceea3bf7ffdba93c4750d', - '438136d603e858a3a5c440c38eccbaddc1d2942114e2eddd4740d098ced1f0d8' - ], - [ - '8d8b9855c7c052a34146fd20ffb658bea4b9f69e0d825ebec16e8c3ce2b526a1', - 'cdb559eedc2d79f926baf44fb84ea4d44bcf50fee51d7ceb30e2e7f463036758' - ], - [ - '52db0b5384dfbf05bfa9d472d7ae26dfe4b851ceca91b1eba54263180da32b63', - 'c3b997d050ee5d423ebaf66a6db9f57b3180c902875679de924b69d84a7b375' - ], - [ - 'e62f9490d3d51da6395efd24e80919cc7d0f29c3f3fa48c6fff543becbd43352', - '6d89ad7ba4876b0b22c2ca280c682862f342c8591f1daf5170e07bfd9ccafa7d' - ], - [ - '7f30ea2476b399b4957509c88f77d0191afa2ff5cb7b14fd6d8e7d65aaab1193', - 'ca5ef7d4b231c94c3b15389a5f6311e9daff7bb67b103e9880ef4bff637acaec' - ], - [ - '5098ff1e1d9f14fb46a210fada6c903fef0fb7b4a1dd1d9ac60a0361800b7a00', - '9731141d81fc8f8084d37c6e7542006b3ee1b40d60dfe5362a5b132fd17ddc0' - ], - [ - '32b78c7de9ee512a72895be6b9cbefa6e2f3c4ccce445c96b9f2c81e2778ad58', - 'ee1849f513df71e32efc3896ee28260c73bb80547ae2275ba497237794c8753c' - ], - [ - 'e2cb74fddc8e9fbcd076eef2a7c72b0ce37d50f08269dfc074b581550547a4f7', - 'd3aa2ed71c9dd2247a62df062736eb0baddea9e36122d2be8641abcb005cc4a4' - ], - [ - '8438447566d4d7bedadc299496ab357426009a35f235cb141be0d99cd10ae3a8', - 'c4e1020916980a4da5d01ac5e6ad330734ef0d7906631c4f2390426b2edd791f' - ], - [ - '4162d488b89402039b584c6fc6c308870587d9c46f660b878ab65c82c711d67e', - '67163e903236289f776f22c25fb8a3afc1732f2b84b4e95dbda47ae5a0852649' - ], - [ - '3fad3fa84caf0f34f0f89bfd2dcf54fc175d767aec3e50684f3ba4a4bf5f683d', - 'cd1bc7cb6cc407bb2f0ca647c718a730cf71872e7d0d2a53fa20efcdfe61826' - ], - [ - '674f2600a3007a00568c1a7ce05d0816c1fb84bf1370798f1c69532faeb1a86b', - '299d21f9413f33b3edf43b257004580b70db57da0b182259e09eecc69e0d38a5' - ], - [ - 'd32f4da54ade74abb81b815ad1fb3b263d82d6c692714bcff87d29bd5ee9f08f', - 'f9429e738b8e53b968e99016c059707782e14f4535359d582fc416910b3eea87' - ], - [ - '30e4e670435385556e593657135845d36fbb6931f72b08cb1ed954f1e3ce3ff6', - '462f9bce619898638499350113bbc9b10a878d35da70740dc695a559eb88db7b' - ], - [ - 'be2062003c51cc3004682904330e4dee7f3dcd10b01e580bf1971b04d4cad297', - '62188bc49d61e5428573d48a74e1c655b1c61090905682a0d5558ed72dccb9bc' - ], - [ - '93144423ace3451ed29e0fb9ac2af211cb6e84a601df5993c419859fff5df04a', - '7c10dfb164c3425f5c71a3f9d7992038f1065224f72bb9d1d902a6d13037b47c' - ], - [ - 'b015f8044f5fcbdcf21ca26d6c34fb8197829205c7b7d2a7cb66418c157b112c', - 'ab8c1e086d04e813744a655b2df8d5f83b3cdc6faa3088c1d3aea1454e3a1d5f' - ], - [ - 'd5e9e1da649d97d89e4868117a465a3a4f8a18de57a140d36b3f2af341a21b52', - '4cb04437f391ed73111a13cc1d4dd0db1693465c2240480d8955e8592f27447a' - ], - [ - 'd3ae41047dd7ca065dbf8ed77b992439983005cd72e16d6f996a5316d36966bb', - 'bd1aeb21ad22ebb22a10f0303417c6d964f8cdd7df0aca614b10dc14d125ac46' - ], - [ - '463e2763d885f958fc66cdd22800f0a487197d0a82e377b49f80af87c897b065', - 'bfefacdb0e5d0fd7df3a311a94de062b26b80c61fbc97508b79992671ef7ca7f' - ], - [ - '7985fdfd127c0567c6f53ec1bb63ec3158e597c40bfe747c83cddfc910641917', - '603c12daf3d9862ef2b25fe1de289aed24ed291e0ec6708703a5bd567f32ed03' - ], - [ - '74a1ad6b5f76e39db2dd249410eac7f99e74c59cb83d2d0ed5ff1543da7703e9', - 'cc6157ef18c9c63cd6193d83631bbea0093e0968942e8c33d5737fd790e0db08' - ], - [ - '30682a50703375f602d416664ba19b7fc9bab42c72747463a71d0896b22f6da3', - '553e04f6b018b4fa6c8f39e7f311d3176290d0e0f19ca73f17714d9977a22ff8' - ], - [ - '9e2158f0d7c0d5f26c3791efefa79597654e7a2b2464f52b1ee6c1347769ef57', - '712fcdd1b9053f09003a3481fa7762e9ffd7c8ef35a38509e2fbf2629008373' - ], - [ - '176e26989a43c9cfeba4029c202538c28172e566e3c4fce7322857f3be327d66', - 'ed8cc9d04b29eb877d270b4878dc43c19aefd31f4eee09ee7b47834c1fa4b1c3' - ], - [ - '75d46efea3771e6e68abb89a13ad747ecf1892393dfc4f1b7004788c50374da8', - '9852390a99507679fd0b86fd2b39a868d7efc22151346e1a3ca4726586a6bed8' - ], - [ - '809a20c67d64900ffb698c4c825f6d5f2310fb0451c869345b7319f645605721', - '9e994980d9917e22b76b061927fa04143d096ccc54963e6a5ebfa5f3f8e286c1' - ], - [ - '1b38903a43f7f114ed4500b4eac7083fdefece1cf29c63528d563446f972c180', - '4036edc931a60ae889353f77fd53de4a2708b26b6f5da72ad3394119daf408f9' - ] - ] - } -}; - -},{}],32:[function(require,module,exports){ -'use strict'; - -var utils = exports; -var BN = require('bn.js'); -var minAssert = require('minimalistic-assert'); -var minUtils = require('minimalistic-crypto-utils'); - -utils.assert = minAssert; -utils.toArray = minUtils.toArray; -utils.zero2 = minUtils.zero2; -utils.toHex = minUtils.toHex; -utils.encode = minUtils.encode; - -// Represent num in a w-NAF form -function getNAF(num, w) { - var naf = []; - var ws = 1 << (w + 1); - var k = num.clone(); - while (k.cmpn(1) >= 0) { - var z; - if (k.isOdd()) { - var mod = k.andln(ws - 1); - if (mod > (ws >> 1) - 1) - z = (ws >> 1) - mod; - else - z = mod; - k.isubn(z); - } else { - z = 0; - } - naf.push(z); - - // Optimization, shift by word if possible - var shift = (k.cmpn(0) !== 0 && k.andln(ws - 1) === 0) ? (w + 1) : 1; - for (var i = 1; i < shift; i++) - naf.push(0); - k.iushrn(shift); - } - - return naf; -} -utils.getNAF = getNAF; - -// Represent k1, k2 in a Joint Sparse Form -function getJSF(k1, k2) { - var jsf = [ - [], - [] - ]; - - k1 = k1.clone(); - k2 = k2.clone(); - var d1 = 0; - var d2 = 0; - while (k1.cmpn(-d1) > 0 || k2.cmpn(-d2) > 0) { - - // First phase - var m14 = (k1.andln(3) + d1) & 3; - var m24 = (k2.andln(3) + d2) & 3; - if (m14 === 3) - m14 = -1; - if (m24 === 3) - m24 = -1; - var u1; - if ((m14 & 1) === 0) { - u1 = 0; - } else { - var m8 = (k1.andln(7) + d1) & 7; - if ((m8 === 3 || m8 === 5) && m24 === 2) - u1 = -m14; - else - u1 = m14; - } - jsf[0].push(u1); - - var u2; - if ((m24 & 1) === 0) { - u2 = 0; - } else { - var m8 = (k2.andln(7) + d2) & 7; - if ((m8 === 3 || m8 === 5) && m14 === 2) - u2 = -m24; - else - u2 = m24; - } - jsf[1].push(u2); - - // Second phase - if (2 * d1 === u1 + 1) - d1 = 1 - d1; - if (2 * d2 === u2 + 1) - d2 = 1 - d2; - k1.iushrn(1); - k2.iushrn(1); - } - - return jsf; -} -utils.getJSF = getJSF; - -function cachedProperty(obj, name, computer) { - var key = '_' + name; - obj.prototype[name] = function cachedProperty() { - return this[key] !== undefined ? this[key] : - this[key] = computer.call(this); - }; -} -utils.cachedProperty = cachedProperty; - -function parseBytes(bytes) { - return typeof bytes === 'string' ? utils.toArray(bytes, 'hex') : - bytes; -} -utils.parseBytes = parseBytes; - -function intFromLE(bytes) { - return new BN(bytes, 'hex', 'le'); -} -utils.intFromLE = intFromLE; - - -},{"bn.js":16,"minimalistic-assert":48,"minimalistic-crypto-utils":49}],33:[function(require,module,exports){ -"use strict"; - -// email-addresses.js - RFC 5322 email address parser -// v 3.0.3 -// -// http://tools.ietf.org/html/rfc5322 -// -// This library does not validate email addresses. -// emailAddresses attempts to parse addresses using the (fairly liberal) -// grammar specified in RFC 5322. -// -// email-addresses returns { -// ast: , -// addresses: [{ -// node: , -// name: , -// address: , -// local: , -// domain: -// }, ...] -// } -// -// emailAddresses.parseOneAddress and emailAddresses.parseAddressList -// work as you might expect. Try it out. -// -// Many thanks to Dominic Sayers and his documentation on the is_email function, -// http://code.google.com/p/isemail/ , which helped greatly in writing this parser. - -(function (global) { - "use strict"; - - function parse5322(opts) { - - // tokenizing functions - - function inStr() { - return pos < len; - } - function curTok() { - return parseString[pos]; - } - function getPos() { - return pos; - } - function setPos(i) { - pos = i; - } - function nextTok() { - pos += 1; - } - function initialize() { - pos = 0; - len = parseString.length; - } - - // parser helper functions - - function o(name, value) { - return { - name: name, - tokens: value || "", - semantic: value || "", - children: [] - }; - } - - function wrap(name, ast) { - var n; - if (ast === null) { - return null; - } - n = o(name); - n.tokens = ast.tokens; - n.semantic = ast.semantic; - n.children.push(ast); - return n; - } - - function add(parent, child) { - if (child !== null) { - parent.tokens += child.tokens; - parent.semantic += child.semantic; - } - parent.children.push(child); - return parent; - } - - function compareToken(fxnCompare) { - var tok; - if (!inStr()) { - return null; - } - tok = curTok(); - if (fxnCompare(tok)) { - nextTok(); - return o('token', tok); - } - return null; - } - - function literal(lit) { - return function literalFunc() { - return wrap('literal', compareToken(function (tok) { - return tok === lit; - })); - }; - } - - function and() { - var args = arguments; - return function andFunc() { - var i, s, result, start; - start = getPos(); - s = o('and'); - for (i = 0; i < args.length; i += 1) { - result = args[i](); - if (result === null) { - setPos(start); - return null; - } - add(s, result); - } - return s; - }; - } - - function or() { - var args = arguments; - return function orFunc() { - var i, result, start; - start = getPos(); - for (i = 0; i < args.length; i += 1) { - result = args[i](); - if (result !== null) { - return result; - } - setPos(start); - } - return null; - }; - } - - function opt(prod) { - return function optFunc() { - var result, start; - start = getPos(); - result = prod(); - if (result !== null) { - return result; - } else { - setPos(start); - return o('opt'); - } - }; - } - - function invis(prod) { - return function invisFunc() { - var result = prod(); - if (result !== null) { - result.semantic = ""; - } - return result; - }; - } - - function colwsp(prod) { - return function collapseSemanticWhitespace() { - var result = prod(); - if (result !== null && result.semantic.length > 0) { - result.semantic = " "; - } - return result; - }; - } - - function star(prod, minimum) { - return function starFunc() { - var s, result, count, start, min; - start = getPos(); - s = o('star'); - count = 0; - min = minimum === undefined ? 0 : minimum; - while ((result = prod()) !== null) { - count = count + 1; - add(s, result); - } - if (count >= min) { - return s; - } else { - setPos(start); - return null; - } - }; - } - - // One expects names to get normalized like this: - // " First Last " -> "First Last" - // "First Last" -> "First Last" - // "First Last" -> "First Last" - function collapseWhitespace(s) { - return s.replace(/([ \t]|\r\n)+/g, ' ').replace(/^\s*/, '').replace(/\s*$/, ''); - } - - // UTF-8 pseudo-production (RFC 6532) - // RFC 6532 extends RFC 5322 productions to include UTF-8 - // using the following productions: - // UTF8-non-ascii = UTF8-2 / UTF8-3 / UTF8-4 - // UTF8-2 = - // UTF8-3 = - // UTF8-4 = - // - // For reference, the extended RFC 5322 productions are: - // VCHAR =/ UTF8-non-ascii - // ctext =/ UTF8-non-ascii - // atext =/ UTF8-non-ascii - // qtext =/ UTF8-non-ascii - // dtext =/ UTF8-non-ascii - function isUTF8NonAscii(tok) { - // In JavaScript, we just deal directly with Unicode code points, - // so we aren't checking individual bytes for UTF-8 encoding. - // Just check that the character is non-ascii. - return tok.charCodeAt(0) >= 128; - } - - // common productions (RFC 5234) - // http://tools.ietf.org/html/rfc5234 - // B.1. Core Rules - - // CR = %x0D - // ; carriage return - function cr() { - return wrap('cr', literal('\r')()); - } - - // CRLF = CR LF - // ; Internet standard newline - function crlf() { - return wrap('crlf', and(cr, lf)()); - } - - // DQUOTE = %x22 - // ; " (Double Quote) - function dquote() { - return wrap('dquote', literal('"')()); - } - - // HTAB = %x09 - // ; horizontal tab - function htab() { - return wrap('htab', literal('\t')()); - } - - // LF = %x0A - // ; linefeed - function lf() { - return wrap('lf', literal('\n')()); - } - - // SP = %x20 - function sp() { - return wrap('sp', literal(' ')()); - } - - // VCHAR = %x21-7E - // ; visible (printing) characters - function vchar() { - return wrap('vchar', compareToken(function vcharFunc(tok) { - var code = tok.charCodeAt(0); - var accept = 0x21 <= code && code <= 0x7E; - if (opts.rfc6532) { - accept = accept || isUTF8NonAscii(tok); - } - return accept; - })); - } - - // WSP = SP / HTAB - // ; white space - function wsp() { - return wrap('wsp', or(sp, htab)()); - } - - // email productions (RFC 5322) - // http://tools.ietf.org/html/rfc5322 - // 3.2.1. Quoted characters - - // quoted-pair = ("\" (VCHAR / WSP)) / obs-qp - function quotedPair() { - var qp = wrap('quoted-pair', or(and(literal('\\'), or(vchar, wsp)), obsQP)()); - if (qp === null) { - return null; - } - // a quoted pair will be two characters, and the "\" character - // should be semantically "invisible" (RFC 5322 3.2.1) - qp.semantic = qp.semantic[1]; - return qp; - } - - // 3.2.2. Folding White Space and Comments - - // FWS = ([*WSP CRLF] 1*WSP) / obs-FWS - function fws() { - return wrap('fws', or(obsFws, and(opt(and(star(wsp), invis(crlf))), star(wsp, 1)))()); - } - - // ctext = %d33-39 / ; Printable US-ASCII - // %d42-91 / ; characters not including - // %d93-126 / ; "(", ")", or "\" - // obs-ctext - function ctext() { - return wrap('ctext', or(function ctextFunc1() { - return compareToken(function ctextFunc2(tok) { - var code = tok.charCodeAt(0); - var accept = 33 <= code && code <= 39 || 42 <= code && code <= 91 || 93 <= code && code <= 126; - if (opts.rfc6532) { - accept = accept || isUTF8NonAscii(tok); - } - return accept; - }); - }, obsCtext)()); - } - - // ccontent = ctext / quoted-pair / comment - function ccontent() { - return wrap('ccontent', or(ctext, quotedPair, comment)()); - } - - // comment = "(" *([FWS] ccontent) [FWS] ")" - function comment() { - return wrap('comment', and(literal('('), star(and(opt(fws), ccontent)), opt(fws), literal(')'))()); - } - - // CFWS = (1*([FWS] comment) [FWS]) / FWS - function cfws() { - return wrap('cfws', or(and(star(and(opt(fws), comment), 1), opt(fws)), fws)()); - } - - // 3.2.3. Atom - - //atext = ALPHA / DIGIT / ; Printable US-ASCII - // "!" / "#" / ; characters not including - // "$" / "%" / ; specials. Used for atoms. - // "&" / "'" / - // "*" / "+" / - // "-" / "/" / - // "=" / "?" / - // "^" / "_" / - // "`" / "{" / - // "|" / "}" / - // "~" - function atext() { - return wrap('atext', compareToken(function atextFunc(tok) { - var accept = 'a' <= tok && tok <= 'z' || 'A' <= tok && tok <= 'Z' || '0' <= tok && tok <= '9' || ['!', '#', '$', '%', '&', '\'', '*', '+', '-', '/', '=', '?', '^', '_', '`', '{', '|', '}', '~'].indexOf(tok) >= 0; - if (opts.rfc6532) { - accept = accept || isUTF8NonAscii(tok); - } - return accept; - })); - } - - // atom = [CFWS] 1*atext [CFWS] - function atom() { - return wrap('atom', and(colwsp(opt(cfws)), star(atext, 1), colwsp(opt(cfws)))()); - } - - // dot-atom-text = 1*atext *("." 1*atext) - function dotAtomText() { - var s, maybeText; - s = wrap('dot-atom-text', star(atext, 1)()); - if (s === null) { - return s; - } - maybeText = star(and(literal('.'), star(atext, 1)))(); - if (maybeText !== null) { - add(s, maybeText); - } - return s; - } - - // dot-atom = [CFWS] dot-atom-text [CFWS] - function dotAtom() { - return wrap('dot-atom', and(invis(opt(cfws)), dotAtomText, invis(opt(cfws)))()); - } - - // 3.2.4. Quoted Strings - - // qtext = %d33 / ; Printable US-ASCII - // %d35-91 / ; characters not including - // %d93-126 / ; "\" or the quote character - // obs-qtext - function qtext() { - return wrap('qtext', or(function qtextFunc1() { - return compareToken(function qtextFunc2(tok) { - var code = tok.charCodeAt(0); - var accept = 33 === code || 35 <= code && code <= 91 || 93 <= code && code <= 126; - if (opts.rfc6532) { - accept = accept || isUTF8NonAscii(tok); - } - return accept; - }); - }, obsQtext)()); - } - - // qcontent = qtext / quoted-pair - function qcontent() { - return wrap('qcontent', or(qtext, quotedPair)()); - } - - // quoted-string = [CFWS] - // DQUOTE *([FWS] qcontent) [FWS] DQUOTE - // [CFWS] - function quotedString() { - return wrap('quoted-string', and(invis(opt(cfws)), invis(dquote), star(and(opt(colwsp(fws)), qcontent)), opt(invis(fws)), invis(dquote), invis(opt(cfws)))()); - } - - // 3.2.5 Miscellaneous Tokens - - // word = atom / quoted-string - function word() { - return wrap('word', or(atom, quotedString)()); - } - - // phrase = 1*word / obs-phrase - function phrase() { - return wrap('phrase', or(obsPhrase, star(word, 1))()); - } - - // 3.4. Address Specification - // address = mailbox / group - function address() { - return wrap('address', or(mailbox, group)()); - } - - // mailbox = name-addr / addr-spec - function mailbox() { - return wrap('mailbox', or(nameAddr, addrSpec)()); - } - - // name-addr = [display-name] angle-addr - function nameAddr() { - return wrap('name-addr', and(opt(displayName), angleAddr)()); - } - - // angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / - // obs-angle-addr - function angleAddr() { - return wrap('angle-addr', or(and(invis(opt(cfws)), literal('<'), addrSpec, literal('>'), invis(opt(cfws))), obsAngleAddr)()); - } - - // group = display-name ":" [group-list] ";" [CFWS] - function group() { - return wrap('group', and(displayName, literal(':'), opt(groupList), literal(';'), invis(opt(cfws)))()); - } - - // display-name = phrase - function displayName() { - return wrap('display-name', function phraseFixedSemantic() { - var result = phrase(); - if (result !== null) { - result.semantic = collapseWhitespace(result.semantic); - } - return result; - }()); - } - - // mailbox-list = (mailbox *("," mailbox)) / obs-mbox-list - function mailboxList() { - return wrap('mailbox-list', or(and(mailbox, star(and(literal(','), mailbox))), obsMboxList)()); - } - - // address-list = (address *("," address)) / obs-addr-list - function addressList() { - return wrap('address-list', or(and(address, star(and(literal(','), address))), obsAddrList)()); - } - - // group-list = mailbox-list / CFWS / obs-group-list - function groupList() { - return wrap('group-list', or(mailboxList, invis(cfws), obsGroupList)()); - } - - // 3.4.1 Addr-Spec Specification - - // local-part = dot-atom / quoted-string / obs-local-part - function localPart() { - // note: quoted-string, dotAtom are proper subsets of obs-local-part - // so we really just have to look for obsLocalPart, if we don't care about the exact parse tree - return wrap('local-part', or(obsLocalPart, dotAtom, quotedString)()); - } - - // dtext = %d33-90 / ; Printable US-ASCII - // %d94-126 / ; characters not including - // obs-dtext ; "[", "]", or "\" - function dtext() { - return wrap('dtext', or(function dtextFunc1() { - return compareToken(function dtextFunc2(tok) { - var code = tok.charCodeAt(0); - var accept = 33 <= code && code <= 90 || 94 <= code && code <= 126; - if (opts.rfc6532) { - accept = accept || isUTF8NonAscii(tok); - } - return accept; - }); - }, obsDtext)()); - } - - // domain-literal = [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS] - function domainLiteral() { - return wrap('domain-literal', and(invis(opt(cfws)), literal('['), star(and(opt(fws), dtext)), opt(fws), literal(']'), invis(opt(cfws)))()); - } - - // domain = dot-atom / domain-literal / obs-domain - function domain() { - return wrap('domain', function domainCheckTLD() { - var result = or(obsDomain, dotAtom, domainLiteral)(); - if (opts.rejectTLD) { - if (result && result.semantic && result.semantic.indexOf('.') < 0) { - return null; - } - } - // strip all whitespace from domains - if (result) { - result.semantic = result.semantic.replace(/\s+/g, ''); - } - return result; - }()); - } - - // addr-spec = local-part "@" domain - function addrSpec() { - return wrap('addr-spec', and(localPart, literal('@'), domain)()); - } - - // 3.6.2 Originator Fields - // Below we only parse the field body, not the name of the field - // like "From:", "Sender:", or "Reply-To:". Other libraries that - // parse email headers can parse those and defer to these productions - // for the "RFC 5322" part. - - // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields - // from = "From:" (mailbox-list / address-list) CRLF - function fromSpec() { - return wrap('from', or(mailboxList, addressList)()); - } - - // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields - // sender = "Sender:" (mailbox / address) CRLF - function senderSpec() { - return wrap('sender', or(mailbox, address)()); - } - - // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields - // reply-to = "Reply-To:" address-list CRLF - function replyToSpec() { - return wrap('reply-to', addressList()); - } - - // 4.1. Miscellaneous Obsolete Tokens - - // obs-NO-WS-CTL = %d1-8 / ; US-ASCII control - // %d11 / ; characters that do not - // %d12 / ; include the carriage - // %d14-31 / ; return, line feed, and - // %d127 ; white space characters - function obsNoWsCtl() { - return opts.strict ? null : wrap('obs-NO-WS-CTL', compareToken(function (tok) { - var code = tok.charCodeAt(0); - return 1 <= code && code <= 8 || 11 === code || 12 === code || 14 <= code && code <= 31 || 127 === code; - })); - } - - // obs-ctext = obs-NO-WS-CTL - function obsCtext() { - return opts.strict ? null : wrap('obs-ctext', obsNoWsCtl()); - } - - // obs-qtext = obs-NO-WS-CTL - function obsQtext() { - return opts.strict ? null : wrap('obs-qtext', obsNoWsCtl()); - } - - // obs-qp = "\" (%d0 / obs-NO-WS-CTL / LF / CR) - function obsQP() { - return opts.strict ? null : wrap('obs-qp', and(literal('\\'), or(literal('\0'), obsNoWsCtl, lf, cr))()); - } - - // obs-phrase = word *(word / "." / CFWS) - function obsPhrase() { - return opts.strict ? null : wrap('obs-phrase', and(word, star(or(word, literal('.'), literal('@'), colwsp(cfws))))()); - } - - // 4.2. Obsolete Folding White Space - - // NOTE: read the errata http://www.rfc-editor.org/errata_search.php?rfc=5322&eid=1908 - // obs-FWS = 1*([CRLF] WSP) - function obsFws() { - return opts.strict ? null : wrap('obs-FWS', star(and(invis(opt(crlf)), wsp), 1)()); - } - - // 4.4. Obsolete Addressing - - // obs-angle-addr = [CFWS] "<" obs-route addr-spec ">" [CFWS] - function obsAngleAddr() { - return opts.strict ? null : wrap('obs-angle-addr', and(invis(opt(cfws)), literal('<'), obsRoute, addrSpec, literal('>'), invis(opt(cfws)))()); - } - - // obs-route = obs-domain-list ":" - function obsRoute() { - return opts.strict ? null : wrap('obs-route', and(obsDomainList, literal(':'))()); - } - - // obs-domain-list = *(CFWS / ",") "@" domain - // *("," [CFWS] ["@" domain]) - function obsDomainList() { - return opts.strict ? null : wrap('obs-domain-list', and(star(or(invis(cfws), literal(','))), literal('@'), domain, star(and(literal(','), invis(opt(cfws)), opt(and(literal('@'), domain)))))()); - } - - // obs-mbox-list = *([CFWS] ",") mailbox *("," [mailbox / CFWS]) - function obsMboxList() { - return opts.strict ? null : wrap('obs-mbox-list', and(star(and(invis(opt(cfws)), literal(','))), mailbox, star(and(literal(','), opt(and(mailbox, invis(cfws))))))()); - } - - // obs-addr-list = *([CFWS] ",") address *("," [address / CFWS]) - function obsAddrList() { - return opts.strict ? null : wrap('obs-addr-list', and(star(and(invis(opt(cfws)), literal(','))), address, star(and(literal(','), opt(and(address, invis(cfws))))))()); - } - - // obs-group-list = 1*([CFWS] ",") [CFWS] - function obsGroupList() { - return opts.strict ? null : wrap('obs-group-list', and(star(and(invis(opt(cfws)), literal(',')), 1), invis(opt(cfws)))()); - } - - // obs-local-part = word *("." word) - function obsLocalPart() { - return opts.strict ? null : wrap('obs-local-part', and(word, star(and(literal('.'), word)))()); - } - - // obs-domain = atom *("." atom) - function obsDomain() { - return opts.strict ? null : wrap('obs-domain', and(atom, star(and(literal('.'), atom)))()); - } - - // obs-dtext = obs-NO-WS-CTL / quoted-pair - function obsDtext() { - return opts.strict ? null : wrap('obs-dtext', or(obsNoWsCtl, quotedPair)()); - } - - ///////////////////////////////////////////////////// - - // ast analysis - - function findNode(name, root) { - var i, stack, node; - if (root === null || root === undefined) { - return null; - } - stack = [root]; - while (stack.length > 0) { - node = stack.pop(); - if (node.name === name) { - return node; - } - for (i = node.children.length - 1; i >= 0; i -= 1) { - stack.push(node.children[i]); - } - } - return null; - } - - function findAllNodes(name, root) { - var i, stack, node, result; - if (root === null || root === undefined) { - return null; - } - stack = [root]; - result = []; - while (stack.length > 0) { - node = stack.pop(); - if (node.name === name) { - result.push(node); - } - for (i = node.children.length - 1; i >= 0; i -= 1) { - stack.push(node.children[i]); - } - } - return result; - } - - function findAllNodesNoChildren(names, root) { - var i, stack, node, result, namesLookup; - if (root === null || root === undefined) { - return null; - } - stack = [root]; - result = []; - namesLookup = {}; - for (i = 0; i < names.length; i += 1) { - namesLookup[names[i]] = true; - } - - while (stack.length > 0) { - node = stack.pop(); - if (node.name in namesLookup) { - result.push(node); - // don't look at children (hence findAllNodesNoChildren) - } else { - for (i = node.children.length - 1; i >= 0; i -= 1) { - stack.push(node.children[i]); - } - } - } - return result; - } - - function giveResult(ast) { - var addresses, groupsAndMailboxes, i, groupOrMailbox, result; - if (ast === null) { - return null; - } - addresses = []; - - // An address is a 'group' (i.e. a list of mailboxes) or a 'mailbox'. - groupsAndMailboxes = findAllNodesNoChildren(['group', 'mailbox'], ast); - for (i = 0; i < groupsAndMailboxes.length; i += 1) { - groupOrMailbox = groupsAndMailboxes[i]; - if (groupOrMailbox.name === 'group') { - addresses.push(giveResultGroup(groupOrMailbox)); - } else if (groupOrMailbox.name === 'mailbox') { - addresses.push(giveResultMailbox(groupOrMailbox)); - } - } - - result = { - ast: ast, - addresses: addresses - }; - if (opts.simple) { - result = simplifyResult(result); - } - if (opts.oneResult) { - return oneResult(result); - } - if (opts.simple) { - return result && result.addresses; - } else { - return result; - } - } - - function giveResultGroup(group) { - var i; - var groupName = findNode('display-name', group); - var groupResultMailboxes = []; - var mailboxes = findAllNodesNoChildren(['mailbox'], group); - for (i = 0; i < mailboxes.length; i += 1) { - groupResultMailboxes.push(giveResultMailbox(mailboxes[i])); - } - return { - node: group, - parts: { - name: groupName - }, - type: group.name, // 'group' - name: grabSemantic(groupName), - addresses: groupResultMailboxes - }; - } - - function giveResultMailbox(mailbox) { - var name = findNode('display-name', mailbox); - var aspec = findNode('addr-spec', mailbox); - var comments = findAllNodesNoChildren(['comment'], mailbox); - - var local = findNode('local-part', aspec); - var domain = findNode('domain', aspec); - return { - node: mailbox, - parts: { - name: name, - address: aspec, - local: local, - domain: domain, - comments: comments - }, - type: mailbox.name, // 'mailbox' - name: grabSemantic(name), - address: grabSemantic(aspec), - local: grabSemantic(local), - domain: grabSemantic(domain), - comments: concatComments(comments), - groupName: grabSemantic(mailbox.groupName) - }; - } - - function grabSemantic(n) { - return n !== null && n !== undefined ? n.semantic : null; - } - - function simplifyResult(result) { - var i; - if (result && result.addresses) { - for (i = 0; i < result.addresses.length; i += 1) { - delete result.addresses[i].node; - } - } - return result; - } - - function concatComments(comments) { - let result = ''; - if (comments) { - for (let i = 0; i < comments.length; i += 1) { - result += grabSemantic(comments[i]); - } - } - return result; - } - - function oneResult(result) { - if (!result) { - return null; - } - if (!opts.partial && result.addresses.length > 1) { - return null; - } - return result.addresses && result.addresses[0]; - } - - ///////////////////////////////////////////////////// - - var parseString, pos, len, parsed, startProduction; - - opts = handleOpts(opts, {}); - if (opts === null) { - return null; - } - - parseString = opts.input; - - startProduction = { - 'address': address, - 'address-list': addressList, - 'angle-addr': angleAddr, - 'from': fromSpec, - 'group': group, - 'mailbox': mailbox, - 'mailbox-list': mailboxList, - 'reply-to': replyToSpec, - 'sender': senderSpec - }[opts.startAt] || addressList; - - if (!opts.strict) { - initialize(); - opts.strict = true; - parsed = startProduction(parseString); - if (opts.partial || !inStr()) { - return giveResult(parsed); - } - opts.strict = false; - } - - initialize(); - parsed = startProduction(parseString); - if (!opts.partial && inStr()) { - return null; - } - return giveResult(parsed); - } - - function parseOneAddressSimple(opts) { - return parse5322(handleOpts(opts, { - oneResult: true, - rfc6532: true, - simple: true, - startAt: 'address-list' - })); - } - - function parseAddressListSimple(opts) { - return parse5322(handleOpts(opts, { - rfc6532: true, - simple: true, - startAt: 'address-list' - })); - } - - function parseFromSimple(opts) { - return parse5322(handleOpts(opts, { - rfc6532: true, - simple: true, - startAt: 'from' - })); - } - - function parseSenderSimple(opts) { - return parse5322(handleOpts(opts, { - oneResult: true, - rfc6532: true, - simple: true, - startAt: 'sender' - })); - } - - function parseReplyToSimple(opts) { - return parse5322(handleOpts(opts, { - rfc6532: true, - simple: true, - startAt: 'reply-to' - })); - } - - function handleOpts(opts, defs) { - function isString(str) { - return Object.prototype.toString.call(str) === '[object String]'; - } - - function isObject(o) { - return o === Object(o); - } - - function isNullUndef(o) { - return o === null || o === undefined; - } - - var defaults, o; - - if (isString(opts)) { - opts = { input: opts }; - } else if (!isObject(opts)) { - return null; - } - - if (!isString(opts.input)) { - return null; - } - if (!defs) { - return null; - } - - defaults = { - oneResult: false, - partial: false, - rejectTLD: false, - rfc6532: false, - simple: false, - startAt: 'address-list', - strict: false - }; - - for (o in defaults) { - if (isNullUndef(opts[o])) { - opts[o] = !isNullUndef(defs[o]) ? defs[o] : defaults[o]; - } - } - return opts; - } - - parse5322.parseOneAddress = parseOneAddressSimple; - parse5322.parseAddressList = parseAddressListSimple; - parse5322.parseFrom = parseFromSimple; - parse5322.parseSender = parseSenderSimple; - parse5322.parseReplyTo = parseReplyToSimple; - - if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { - module.exports = parse5322; - } else { - global.emailAddresses = parse5322; - } -})(undefined); - -},{}],34:[function(require,module,exports){ -var hash = exports; - -hash.utils = require('./hash/utils'); -hash.common = require('./hash/common'); -hash.sha = require('./hash/sha'); -hash.ripemd = require('./hash/ripemd'); -hash.hmac = require('./hash/hmac'); - -// Proxy hash functions to the main object -hash.sha1 = hash.sha.sha1; -hash.sha256 = hash.sha.sha256; -hash.sha224 = hash.sha.sha224; -hash.sha384 = hash.sha.sha384; -hash.sha512 = hash.sha.sha512; -hash.ripemd160 = hash.ripemd.ripemd160; - -},{"./hash/common":35,"./hash/hmac":36,"./hash/ripemd":37,"./hash/sha":38,"./hash/utils":45}],35:[function(require,module,exports){ -'use strict'; - -var utils = require('./utils'); -var assert = require('minimalistic-assert'); - -function BlockHash() { - this.pending = null; - this.pendingTotal = 0; - this.blockSize = this.constructor.blockSize; - this.outSize = this.constructor.outSize; - this.hmacStrength = this.constructor.hmacStrength; - this.padLength = this.constructor.padLength / 8; - this.endian = 'big'; - - this._delta8 = this.blockSize / 8; - this._delta32 = this.blockSize / 32; -} -exports.BlockHash = BlockHash; - -BlockHash.prototype.update = function update(msg, enc) { - // Convert message to array, pad it, and join into 32bit blocks - msg = utils.toArray(msg, enc); - if (!this.pending) - this.pending = msg; - else - this.pending = this.pending.concat(msg); - this.pendingTotal += msg.length; - - // Enough data, try updating - if (this.pending.length >= this._delta8) { - msg = this.pending; - - // Process pending data in blocks - var r = msg.length % this._delta8; - this.pending = msg.slice(msg.length - r, msg.length); - if (this.pending.length === 0) - this.pending = null; - - msg = utils.join32(msg, 0, msg.length - r, this.endian); - for (var i = 0; i < msg.length; i += this._delta32) - this._update(msg, i, i + this._delta32); - } - - return this; -}; - -BlockHash.prototype.digest = function digest(enc) { - this.update(this._pad()); - assert(this.pending === null); - - return this._digest(enc); -}; - -BlockHash.prototype._pad = function pad() { - var len = this.pendingTotal; - var bytes = this._delta8; - var k = bytes - ((len + this.padLength) % bytes); - var res = new Array(k + this.padLength); - res[0] = 0x80; - for (var i = 1; i < k; i++) - res[i] = 0; - - // Append length - len <<= 3; - if (this.endian === 'big') { - for (var t = 8; t < this.padLength; t++) - res[i++] = 0; - - res[i++] = 0; - res[i++] = 0; - res[i++] = 0; - res[i++] = 0; - res[i++] = (len >>> 24) & 0xff; - res[i++] = (len >>> 16) & 0xff; - res[i++] = (len >>> 8) & 0xff; - res[i++] = len & 0xff; - } else { - res[i++] = len & 0xff; - res[i++] = (len >>> 8) & 0xff; - res[i++] = (len >>> 16) & 0xff; - res[i++] = (len >>> 24) & 0xff; - res[i++] = 0; - res[i++] = 0; - res[i++] = 0; - res[i++] = 0; - - for (t = 8; t < this.padLength; t++) - res[i++] = 0; - } - - return res; -}; - -},{"./utils":45,"minimalistic-assert":48}],36:[function(require,module,exports){ -'use strict'; - -var utils = require('./utils'); -var assert = require('minimalistic-assert'); - -function Hmac(hash, key, enc) { - if (!(this instanceof Hmac)) - return new Hmac(hash, key, enc); - this.Hash = hash; - this.blockSize = hash.blockSize / 8; - this.outSize = hash.outSize / 8; - this.inner = null; - this.outer = null; - - this._init(utils.toArray(key, enc)); -} -module.exports = Hmac; - -Hmac.prototype._init = function init(key) { - // Shorten key, if needed - if (key.length > this.blockSize) - key = new this.Hash().update(key).digest(); - assert(key.length <= this.blockSize); - - // Add padding to key - for (var i = key.length; i < this.blockSize; i++) - key.push(0); - - for (i = 0; i < key.length; i++) - key[i] ^= 0x36; - this.inner = new this.Hash().update(key); - - // 0x36 ^ 0x5c = 0x6a - for (i = 0; i < key.length; i++) - key[i] ^= 0x6a; - this.outer = new this.Hash().update(key); -}; - -Hmac.prototype.update = function update(msg, enc) { - this.inner.update(msg, enc); - return this; -}; - -Hmac.prototype.digest = function digest(enc) { - this.outer.update(this.inner.digest()); - return this.outer.digest(enc); -}; - -},{"./utils":45,"minimalistic-assert":48}],37:[function(require,module,exports){ -'use strict'; - -var utils = require('./utils'); -var common = require('./common'); - -var rotl32 = utils.rotl32; -var sum32 = utils.sum32; -var sum32_3 = utils.sum32_3; -var sum32_4 = utils.sum32_4; -var BlockHash = common.BlockHash; - -function RIPEMD160() { - if (!(this instanceof RIPEMD160)) - return new RIPEMD160(); - - BlockHash.call(this); - - this.h = [ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 ]; - this.endian = 'little'; -} -utils.inherits(RIPEMD160, BlockHash); -exports.ripemd160 = RIPEMD160; - -RIPEMD160.blockSize = 512; -RIPEMD160.outSize = 160; -RIPEMD160.hmacStrength = 192; -RIPEMD160.padLength = 64; - -RIPEMD160.prototype._update = function update(msg, start) { - var A = this.h[0]; - var B = this.h[1]; - var C = this.h[2]; - var D = this.h[3]; - var E = this.h[4]; - var Ah = A; - var Bh = B; - var Ch = C; - var Dh = D; - var Eh = E; - for (var j = 0; j < 80; j++) { - var T = sum32( - rotl32( - sum32_4(A, f(j, B, C, D), msg[r[j] + start], K(j)), - s[j]), - E); - A = E; - E = D; - D = rotl32(C, 10); - C = B; - B = T; - T = sum32( - rotl32( - sum32_4(Ah, f(79 - j, Bh, Ch, Dh), msg[rh[j] + start], Kh(j)), - sh[j]), - Eh); - Ah = Eh; - Eh = Dh; - Dh = rotl32(Ch, 10); - Ch = Bh; - Bh = T; - } - T = sum32_3(this.h[1], C, Dh); - this.h[1] = sum32_3(this.h[2], D, Eh); - this.h[2] = sum32_3(this.h[3], E, Ah); - this.h[3] = sum32_3(this.h[4], A, Bh); - this.h[4] = sum32_3(this.h[0], B, Ch); - this.h[0] = T; -}; - -RIPEMD160.prototype._digest = function digest(enc) { - if (enc === 'hex') - return utils.toHex32(this.h, 'little'); - else - return utils.split32(this.h, 'little'); -}; - -function f(j, x, y, z) { - if (j <= 15) - return x ^ y ^ z; - else if (j <= 31) - return (x & y) | ((~x) & z); - else if (j <= 47) - return (x | (~y)) ^ z; - else if (j <= 63) - return (x & z) | (y & (~z)); - else - return x ^ (y | (~z)); -} - -function K(j) { - if (j <= 15) - return 0x00000000; - else if (j <= 31) - return 0x5a827999; - else if (j <= 47) - return 0x6ed9eba1; - else if (j <= 63) - return 0x8f1bbcdc; - else - return 0xa953fd4e; -} - -function Kh(j) { - if (j <= 15) - return 0x50a28be6; - else if (j <= 31) - return 0x5c4dd124; - else if (j <= 47) - return 0x6d703ef3; - else if (j <= 63) - return 0x7a6d76e9; - else - return 0x00000000; -} - -var r = [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, - 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, - 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, - 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 -]; - -var rh = [ - 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, - 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, - 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, - 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, - 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 -]; - -var s = [ - 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, - 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, - 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, - 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, - 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 -]; - -var sh = [ - 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, - 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, - 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, - 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, - 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 -]; - -},{"./common":35,"./utils":45}],38:[function(require,module,exports){ -'use strict'; - -exports.sha1 = require('./sha/1'); -exports.sha224 = require('./sha/224'); -exports.sha256 = require('./sha/256'); -exports.sha384 = require('./sha/384'); -exports.sha512 = require('./sha/512'); - -},{"./sha/1":39,"./sha/224":40,"./sha/256":41,"./sha/384":42,"./sha/512":43}],39:[function(require,module,exports){ -'use strict'; - -var utils = require('../utils'); -var common = require('../common'); -var shaCommon = require('./common'); - -var rotl32 = utils.rotl32; -var sum32 = utils.sum32; -var sum32_5 = utils.sum32_5; -var ft_1 = shaCommon.ft_1; -var BlockHash = common.BlockHash; - -var sha1_K = [ - 0x5A827999, 0x6ED9EBA1, - 0x8F1BBCDC, 0xCA62C1D6 -]; - -function SHA1() { - if (!(this instanceof SHA1)) - return new SHA1(); - - BlockHash.call(this); - this.h = [ - 0x67452301, 0xefcdab89, 0x98badcfe, - 0x10325476, 0xc3d2e1f0 ]; - this.W = new Array(80); -} - -utils.inherits(SHA1, BlockHash); -module.exports = SHA1; - -SHA1.blockSize = 512; -SHA1.outSize = 160; -SHA1.hmacStrength = 80; -SHA1.padLength = 64; - -SHA1.prototype._update = function _update(msg, start) { - var W = this.W; - - for (var i = 0; i < 16; i++) - W[i] = msg[start + i]; - - for(; i < W.length; i++) - W[i] = rotl32(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1); - - var a = this.h[0]; - var b = this.h[1]; - var c = this.h[2]; - var d = this.h[3]; - var e = this.h[4]; - - for (i = 0; i < W.length; i++) { - var s = ~~(i / 20); - var t = sum32_5(rotl32(a, 5), ft_1(s, b, c, d), e, W[i], sha1_K[s]); - e = d; - d = c; - c = rotl32(b, 30); - b = a; - a = t; - } - - this.h[0] = sum32(this.h[0], a); - this.h[1] = sum32(this.h[1], b); - this.h[2] = sum32(this.h[2], c); - this.h[3] = sum32(this.h[3], d); - this.h[4] = sum32(this.h[4], e); -}; - -SHA1.prototype._digest = function digest(enc) { - if (enc === 'hex') - return utils.toHex32(this.h, 'big'); - else - return utils.split32(this.h, 'big'); -}; - -},{"../common":35,"../utils":45,"./common":44}],40:[function(require,module,exports){ -'use strict'; - -var utils = require('../utils'); -var SHA256 = require('./256'); - -function SHA224() { - if (!(this instanceof SHA224)) - return new SHA224(); - - SHA256.call(this); - this.h = [ - 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, - 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 ]; -} -utils.inherits(SHA224, SHA256); -module.exports = SHA224; - -SHA224.blockSize = 512; -SHA224.outSize = 224; -SHA224.hmacStrength = 192; -SHA224.padLength = 64; - -SHA224.prototype._digest = function digest(enc) { - // Just truncate output - if (enc === 'hex') - return utils.toHex32(this.h.slice(0, 7), 'big'); - else - return utils.split32(this.h.slice(0, 7), 'big'); -}; - - -},{"../utils":45,"./256":41}],41:[function(require,module,exports){ -'use strict'; - -var utils = require('../utils'); -var common = require('../common'); -var shaCommon = require('./common'); -var assert = require('minimalistic-assert'); - -var sum32 = utils.sum32; -var sum32_4 = utils.sum32_4; -var sum32_5 = utils.sum32_5; -var ch32 = shaCommon.ch32; -var maj32 = shaCommon.maj32; -var s0_256 = shaCommon.s0_256; -var s1_256 = shaCommon.s1_256; -var g0_256 = shaCommon.g0_256; -var g1_256 = shaCommon.g1_256; - -var BlockHash = common.BlockHash; - -var sha256_K = [ - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -]; - -function SHA256() { - if (!(this instanceof SHA256)) - return new SHA256(); - - BlockHash.call(this); - this.h = [ - 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, - 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 - ]; - this.k = sha256_K; - this.W = new Array(64); -} -utils.inherits(SHA256, BlockHash); -module.exports = SHA256; - -SHA256.blockSize = 512; -SHA256.outSize = 256; -SHA256.hmacStrength = 192; -SHA256.padLength = 64; - -SHA256.prototype._update = function _update(msg, start) { - var W = this.W; - - for (var i = 0; i < 16; i++) - W[i] = msg[start + i]; - for (; i < W.length; i++) - W[i] = sum32_4(g1_256(W[i - 2]), W[i - 7], g0_256(W[i - 15]), W[i - 16]); - - var a = this.h[0]; - var b = this.h[1]; - var c = this.h[2]; - var d = this.h[3]; - var e = this.h[4]; - var f = this.h[5]; - var g = this.h[6]; - var h = this.h[7]; - - assert(this.k.length === W.length); - for (i = 0; i < W.length; i++) { - var T1 = sum32_5(h, s1_256(e), ch32(e, f, g), this.k[i], W[i]); - var T2 = sum32(s0_256(a), maj32(a, b, c)); - h = g; - g = f; - f = e; - e = sum32(d, T1); - d = c; - c = b; - b = a; - a = sum32(T1, T2); - } - - this.h[0] = sum32(this.h[0], a); - this.h[1] = sum32(this.h[1], b); - this.h[2] = sum32(this.h[2], c); - this.h[3] = sum32(this.h[3], d); - this.h[4] = sum32(this.h[4], e); - this.h[5] = sum32(this.h[5], f); - this.h[6] = sum32(this.h[6], g); - this.h[7] = sum32(this.h[7], h); -}; - -SHA256.prototype._digest = function digest(enc) { - if (enc === 'hex') - return utils.toHex32(this.h, 'big'); - else - return utils.split32(this.h, 'big'); -}; - -},{"../common":35,"../utils":45,"./common":44,"minimalistic-assert":48}],42:[function(require,module,exports){ -'use strict'; - -var utils = require('../utils'); - -var SHA512 = require('./512'); - -function SHA384() { - if (!(this instanceof SHA384)) - return new SHA384(); - - SHA512.call(this); - this.h = [ - 0xcbbb9d5d, 0xc1059ed8, - 0x629a292a, 0x367cd507, - 0x9159015a, 0x3070dd17, - 0x152fecd8, 0xf70e5939, - 0x67332667, 0xffc00b31, - 0x8eb44a87, 0x68581511, - 0xdb0c2e0d, 0x64f98fa7, - 0x47b5481d, 0xbefa4fa4 ]; -} -utils.inherits(SHA384, SHA512); -module.exports = SHA384; - -SHA384.blockSize = 1024; -SHA384.outSize = 384; -SHA384.hmacStrength = 192; -SHA384.padLength = 128; - -SHA384.prototype._digest = function digest(enc) { - if (enc === 'hex') - return utils.toHex32(this.h.slice(0, 12), 'big'); - else - return utils.split32(this.h.slice(0, 12), 'big'); -}; - -},{"../utils":45,"./512":43}],43:[function(require,module,exports){ -'use strict'; - -var utils = require('../utils'); -var common = require('../common'); -var assert = require('minimalistic-assert'); - -var rotr64_hi = utils.rotr64_hi; -var rotr64_lo = utils.rotr64_lo; -var shr64_hi = utils.shr64_hi; -var shr64_lo = utils.shr64_lo; -var sum64 = utils.sum64; -var sum64_hi = utils.sum64_hi; -var sum64_lo = utils.sum64_lo; -var sum64_4_hi = utils.sum64_4_hi; -var sum64_4_lo = utils.sum64_4_lo; -var sum64_5_hi = utils.sum64_5_hi; -var sum64_5_lo = utils.sum64_5_lo; - -var BlockHash = common.BlockHash; - -var sha512_K = [ - 0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd, - 0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc, - 0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019, - 0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118, - 0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe, - 0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2, - 0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1, - 0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694, - 0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3, - 0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65, - 0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483, - 0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5, - 0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210, - 0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4, - 0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725, - 0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70, - 0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926, - 0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df, - 0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8, - 0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b, - 0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001, - 0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30, - 0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910, - 0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8, - 0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53, - 0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8, - 0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb, - 0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3, - 0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60, - 0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec, - 0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9, - 0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b, - 0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207, - 0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178, - 0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6, - 0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b, - 0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493, - 0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c, - 0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a, - 0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817 -]; - -function SHA512() { - if (!(this instanceof SHA512)) - return new SHA512(); - - BlockHash.call(this); - this.h = [ - 0x6a09e667, 0xf3bcc908, - 0xbb67ae85, 0x84caa73b, - 0x3c6ef372, 0xfe94f82b, - 0xa54ff53a, 0x5f1d36f1, - 0x510e527f, 0xade682d1, - 0x9b05688c, 0x2b3e6c1f, - 0x1f83d9ab, 0xfb41bd6b, - 0x5be0cd19, 0x137e2179 ]; - this.k = sha512_K; - this.W = new Array(160); -} -utils.inherits(SHA512, BlockHash); -module.exports = SHA512; - -SHA512.blockSize = 1024; -SHA512.outSize = 512; -SHA512.hmacStrength = 192; -SHA512.padLength = 128; - -SHA512.prototype._prepareBlock = function _prepareBlock(msg, start) { - var W = this.W; - - // 32 x 32bit words - for (var i = 0; i < 32; i++) - W[i] = msg[start + i]; - for (; i < W.length; i += 2) { - var c0_hi = g1_512_hi(W[i - 4], W[i - 3]); // i - 2 - var c0_lo = g1_512_lo(W[i - 4], W[i - 3]); - var c1_hi = W[i - 14]; // i - 7 - var c1_lo = W[i - 13]; - var c2_hi = g0_512_hi(W[i - 30], W[i - 29]); // i - 15 - var c2_lo = g0_512_lo(W[i - 30], W[i - 29]); - var c3_hi = W[i - 32]; // i - 16 - var c3_lo = W[i - 31]; - - W[i] = sum64_4_hi( - c0_hi, c0_lo, - c1_hi, c1_lo, - c2_hi, c2_lo, - c3_hi, c3_lo); - W[i + 1] = sum64_4_lo( - c0_hi, c0_lo, - c1_hi, c1_lo, - c2_hi, c2_lo, - c3_hi, c3_lo); - } -}; - -SHA512.prototype._update = function _update(msg, start) { - this._prepareBlock(msg, start); - - var W = this.W; - - var ah = this.h[0]; - var al = this.h[1]; - var bh = this.h[2]; - var bl = this.h[3]; - var ch = this.h[4]; - var cl = this.h[5]; - var dh = this.h[6]; - var dl = this.h[7]; - var eh = this.h[8]; - var el = this.h[9]; - var fh = this.h[10]; - var fl = this.h[11]; - var gh = this.h[12]; - var gl = this.h[13]; - var hh = this.h[14]; - var hl = this.h[15]; - - assert(this.k.length === W.length); - for (var i = 0; i < W.length; i += 2) { - var c0_hi = hh; - var c0_lo = hl; - var c1_hi = s1_512_hi(eh, el); - var c1_lo = s1_512_lo(eh, el); - var c2_hi = ch64_hi(eh, el, fh, fl, gh, gl); - var c2_lo = ch64_lo(eh, el, fh, fl, gh, gl); - var c3_hi = this.k[i]; - var c3_lo = this.k[i + 1]; - var c4_hi = W[i]; - var c4_lo = W[i + 1]; - - var T1_hi = sum64_5_hi( - c0_hi, c0_lo, - c1_hi, c1_lo, - c2_hi, c2_lo, - c3_hi, c3_lo, - c4_hi, c4_lo); - var T1_lo = sum64_5_lo( - c0_hi, c0_lo, - c1_hi, c1_lo, - c2_hi, c2_lo, - c3_hi, c3_lo, - c4_hi, c4_lo); - - c0_hi = s0_512_hi(ah, al); - c0_lo = s0_512_lo(ah, al); - c1_hi = maj64_hi(ah, al, bh, bl, ch, cl); - c1_lo = maj64_lo(ah, al, bh, bl, ch, cl); - - var T2_hi = sum64_hi(c0_hi, c0_lo, c1_hi, c1_lo); - var T2_lo = sum64_lo(c0_hi, c0_lo, c1_hi, c1_lo); - - hh = gh; - hl = gl; - - gh = fh; - gl = fl; - - fh = eh; - fl = el; - - eh = sum64_hi(dh, dl, T1_hi, T1_lo); - el = sum64_lo(dl, dl, T1_hi, T1_lo); - - dh = ch; - dl = cl; - - ch = bh; - cl = bl; - - bh = ah; - bl = al; - - ah = sum64_hi(T1_hi, T1_lo, T2_hi, T2_lo); - al = sum64_lo(T1_hi, T1_lo, T2_hi, T2_lo); - } - - sum64(this.h, 0, ah, al); - sum64(this.h, 2, bh, bl); - sum64(this.h, 4, ch, cl); - sum64(this.h, 6, dh, dl); - sum64(this.h, 8, eh, el); - sum64(this.h, 10, fh, fl); - sum64(this.h, 12, gh, gl); - sum64(this.h, 14, hh, hl); -}; - -SHA512.prototype._digest = function digest(enc) { - if (enc === 'hex') - return utils.toHex32(this.h, 'big'); - else - return utils.split32(this.h, 'big'); -}; - -function ch64_hi(xh, xl, yh, yl, zh) { - var r = (xh & yh) ^ ((~xh) & zh); - if (r < 0) - r += 0x100000000; - return r; -} - -function ch64_lo(xh, xl, yh, yl, zh, zl) { - var r = (xl & yl) ^ ((~xl) & zl); - if (r < 0) - r += 0x100000000; - return r; -} - -function maj64_hi(xh, xl, yh, yl, zh) { - var r = (xh & yh) ^ (xh & zh) ^ (yh & zh); - if (r < 0) - r += 0x100000000; - return r; -} - -function maj64_lo(xh, xl, yh, yl, zh, zl) { - var r = (xl & yl) ^ (xl & zl) ^ (yl & zl); - if (r < 0) - r += 0x100000000; - return r; -} - -function s0_512_hi(xh, xl) { - var c0_hi = rotr64_hi(xh, xl, 28); - var c1_hi = rotr64_hi(xl, xh, 2); // 34 - var c2_hi = rotr64_hi(xl, xh, 7); // 39 - - var r = c0_hi ^ c1_hi ^ c2_hi; - if (r < 0) - r += 0x100000000; - return r; -} - -function s0_512_lo(xh, xl) { - var c0_lo = rotr64_lo(xh, xl, 28); - var c1_lo = rotr64_lo(xl, xh, 2); // 34 - var c2_lo = rotr64_lo(xl, xh, 7); // 39 - - var r = c0_lo ^ c1_lo ^ c2_lo; - if (r < 0) - r += 0x100000000; - return r; -} - -function s1_512_hi(xh, xl) { - var c0_hi = rotr64_hi(xh, xl, 14); - var c1_hi = rotr64_hi(xh, xl, 18); - var c2_hi = rotr64_hi(xl, xh, 9); // 41 - - var r = c0_hi ^ c1_hi ^ c2_hi; - if (r < 0) - r += 0x100000000; - return r; -} - -function s1_512_lo(xh, xl) { - var c0_lo = rotr64_lo(xh, xl, 14); - var c1_lo = rotr64_lo(xh, xl, 18); - var c2_lo = rotr64_lo(xl, xh, 9); // 41 - - var r = c0_lo ^ c1_lo ^ c2_lo; - if (r < 0) - r += 0x100000000; - return r; -} - -function g0_512_hi(xh, xl) { - var c0_hi = rotr64_hi(xh, xl, 1); - var c1_hi = rotr64_hi(xh, xl, 8); - var c2_hi = shr64_hi(xh, xl, 7); - - var r = c0_hi ^ c1_hi ^ c2_hi; - if (r < 0) - r += 0x100000000; - return r; -} - -function g0_512_lo(xh, xl) { - var c0_lo = rotr64_lo(xh, xl, 1); - var c1_lo = rotr64_lo(xh, xl, 8); - var c2_lo = shr64_lo(xh, xl, 7); - - var r = c0_lo ^ c1_lo ^ c2_lo; - if (r < 0) - r += 0x100000000; - return r; -} - -function g1_512_hi(xh, xl) { - var c0_hi = rotr64_hi(xh, xl, 19); - var c1_hi = rotr64_hi(xl, xh, 29); // 61 - var c2_hi = shr64_hi(xh, xl, 6); - - var r = c0_hi ^ c1_hi ^ c2_hi; - if (r < 0) - r += 0x100000000; - return r; -} - -function g1_512_lo(xh, xl) { - var c0_lo = rotr64_lo(xh, xl, 19); - var c1_lo = rotr64_lo(xl, xh, 29); // 61 - var c2_lo = shr64_lo(xh, xl, 6); - - var r = c0_lo ^ c1_lo ^ c2_lo; - if (r < 0) - r += 0x100000000; - return r; -} - -},{"../common":35,"../utils":45,"minimalistic-assert":48}],44:[function(require,module,exports){ -'use strict'; - -var utils = require('../utils'); -var rotr32 = utils.rotr32; - -function ft_1(s, x, y, z) { - if (s === 0) - return ch32(x, y, z); - if (s === 1 || s === 3) - return p32(x, y, z); - if (s === 2) - return maj32(x, y, z); -} -exports.ft_1 = ft_1; - -function ch32(x, y, z) { - return (x & y) ^ ((~x) & z); -} -exports.ch32 = ch32; - -function maj32(x, y, z) { - return (x & y) ^ (x & z) ^ (y & z); -} -exports.maj32 = maj32; - -function p32(x, y, z) { - return x ^ y ^ z; -} -exports.p32 = p32; - -function s0_256(x) { - return rotr32(x, 2) ^ rotr32(x, 13) ^ rotr32(x, 22); -} -exports.s0_256 = s0_256; - -function s1_256(x) { - return rotr32(x, 6) ^ rotr32(x, 11) ^ rotr32(x, 25); -} -exports.s1_256 = s1_256; - -function g0_256(x) { - return rotr32(x, 7) ^ rotr32(x, 18) ^ (x >>> 3); -} -exports.g0_256 = g0_256; - -function g1_256(x) { - return rotr32(x, 17) ^ rotr32(x, 19) ^ (x >>> 10); -} -exports.g1_256 = g1_256; - -},{"../utils":45}],45:[function(require,module,exports){ -'use strict'; - -var assert = require('minimalistic-assert'); -var inherits = require('inherits'); - -exports.inherits = inherits; - -function toArray(msg, enc) { - if (Array.isArray(msg)) - return msg.slice(); - if (!msg) - return []; - var res = []; - if (typeof msg === 'string') { - if (!enc) { - for (var i = 0; i < msg.length; i++) { - var c = msg.charCodeAt(i); - var hi = c >> 8; - var lo = c & 0xff; - if (hi) - res.push(hi, lo); - else - res.push(lo); - } - } else if (enc === 'hex') { - msg = msg.replace(/[^a-z0-9]+/ig, ''); - if (msg.length % 2 !== 0) - msg = '0' + msg; - for (i = 0; i < msg.length; i += 2) - res.push(parseInt(msg[i] + msg[i + 1], 16)); - } - } else { - for (i = 0; i < msg.length; i++) - res[i] = msg[i] | 0; - } - return res; -} -exports.toArray = toArray; - -function toHex(msg) { - var res = ''; - for (var i = 0; i < msg.length; i++) - res += zero2(msg[i].toString(16)); - return res; -} -exports.toHex = toHex; - -function htonl(w) { - var res = (w >>> 24) | - ((w >>> 8) & 0xff00) | - ((w << 8) & 0xff0000) | - ((w & 0xff) << 24); - return res >>> 0; -} -exports.htonl = htonl; - -function toHex32(msg, endian) { - var res = ''; - for (var i = 0; i < msg.length; i++) { - var w = msg[i]; - if (endian === 'little') - w = htonl(w); - res += zero8(w.toString(16)); - } - return res; -} -exports.toHex32 = toHex32; - -function zero2(word) { - if (word.length === 1) - return '0' + word; - else - return word; -} -exports.zero2 = zero2; - -function zero8(word) { - if (word.length === 7) - return '0' + word; - else if (word.length === 6) - return '00' + word; - else if (word.length === 5) - return '000' + word; - else if (word.length === 4) - return '0000' + word; - else if (word.length === 3) - return '00000' + word; - else if (word.length === 2) - return '000000' + word; - else if (word.length === 1) - return '0000000' + word; - else - return word; -} -exports.zero8 = zero8; - -function join32(msg, start, end, endian) { - var len = end - start; - assert(len % 4 === 0); - var res = new Array(len / 4); - for (var i = 0, k = start; i < res.length; i++, k += 4) { - var w; - if (endian === 'big') - w = (msg[k] << 24) | (msg[k + 1] << 16) | (msg[k + 2] << 8) | msg[k + 3]; - else - w = (msg[k + 3] << 24) | (msg[k + 2] << 16) | (msg[k + 1] << 8) | msg[k]; - res[i] = w >>> 0; - } - return res; -} -exports.join32 = join32; - -function split32(msg, endian) { - var res = new Array(msg.length * 4); - for (var i = 0, k = 0; i < msg.length; i++, k += 4) { - var m = msg[i]; - if (endian === 'big') { - res[k] = m >>> 24; - res[k + 1] = (m >>> 16) & 0xff; - res[k + 2] = (m >>> 8) & 0xff; - res[k + 3] = m & 0xff; - } else { - res[k + 3] = m >>> 24; - res[k + 2] = (m >>> 16) & 0xff; - res[k + 1] = (m >>> 8) & 0xff; - res[k] = m & 0xff; - } - } - return res; -} -exports.split32 = split32; - -function rotr32(w, b) { - return (w >>> b) | (w << (32 - b)); -} -exports.rotr32 = rotr32; - -function rotl32(w, b) { - return (w << b) | (w >>> (32 - b)); -} -exports.rotl32 = rotl32; - -function sum32(a, b) { - return (a + b) >>> 0; -} -exports.sum32 = sum32; - -function sum32_3(a, b, c) { - return (a + b + c) >>> 0; -} -exports.sum32_3 = sum32_3; - -function sum32_4(a, b, c, d) { - return (a + b + c + d) >>> 0; -} -exports.sum32_4 = sum32_4; - -function sum32_5(a, b, c, d, e) { - return (a + b + c + d + e) >>> 0; -} -exports.sum32_5 = sum32_5; - -function sum64(buf, pos, ah, al) { - var bh = buf[pos]; - var bl = buf[pos + 1]; - - var lo = (al + bl) >>> 0; - var hi = (lo < al ? 1 : 0) + ah + bh; - buf[pos] = hi >>> 0; - buf[pos + 1] = lo; -} -exports.sum64 = sum64; - -function sum64_hi(ah, al, bh, bl) { - var lo = (al + bl) >>> 0; - var hi = (lo < al ? 1 : 0) + ah + bh; - return hi >>> 0; -} -exports.sum64_hi = sum64_hi; - -function sum64_lo(ah, al, bh, bl) { - var lo = al + bl; - return lo >>> 0; -} -exports.sum64_lo = sum64_lo; - -function sum64_4_hi(ah, al, bh, bl, ch, cl, dh, dl) { - var carry = 0; - var lo = al; - lo = (lo + bl) >>> 0; - carry += lo < al ? 1 : 0; - lo = (lo + cl) >>> 0; - carry += lo < cl ? 1 : 0; - lo = (lo + dl) >>> 0; - carry += lo < dl ? 1 : 0; - - var hi = ah + bh + ch + dh + carry; - return hi >>> 0; -} -exports.sum64_4_hi = sum64_4_hi; - -function sum64_4_lo(ah, al, bh, bl, ch, cl, dh, dl) { - var lo = al + bl + cl + dl; - return lo >>> 0; -} -exports.sum64_4_lo = sum64_4_lo; - -function sum64_5_hi(ah, al, bh, bl, ch, cl, dh, dl, eh, el) { - var carry = 0; - var lo = al; - lo = (lo + bl) >>> 0; - carry += lo < al ? 1 : 0; - lo = (lo + cl) >>> 0; - carry += lo < cl ? 1 : 0; - lo = (lo + dl) >>> 0; - carry += lo < dl ? 1 : 0; - lo = (lo + el) >>> 0; - carry += lo < el ? 1 : 0; - - var hi = ah + bh + ch + dh + eh + carry; - return hi >>> 0; -} -exports.sum64_5_hi = sum64_5_hi; - -function sum64_5_lo(ah, al, bh, bl, ch, cl, dh, dl, eh, el) { - var lo = al + bl + cl + dl + el; - - return lo >>> 0; -} -exports.sum64_5_lo = sum64_5_lo; - -function rotr64_hi(ah, al, num) { - var r = (al << (32 - num)) | (ah >>> num); - return r >>> 0; -} -exports.rotr64_hi = rotr64_hi; - -function rotr64_lo(ah, al, num) { - var r = (ah << (32 - num)) | (al >>> num); - return r >>> 0; -} -exports.rotr64_lo = rotr64_lo; - -function shr64_hi(ah, al, num) { - return ah >>> num; -} -exports.shr64_hi = shr64_hi; - -function shr64_lo(ah, al, num) { - var r = (ah << (32 - num)) | (al >>> num); - return r >>> 0; -} -exports.shr64_lo = shr64_lo; - -},{"inherits":47,"minimalistic-assert":48}],46:[function(require,module,exports){ -'use strict'; - -var hash = require('hash.js'); -var utils = require('minimalistic-crypto-utils'); -var assert = require('minimalistic-assert'); - -function HmacDRBG(options) { - if (!(this instanceof HmacDRBG)) - return new HmacDRBG(options); - this.hash = options.hash; - this.predResist = !!options.predResist; - - this.outLen = this.hash.outSize; - this.minEntropy = options.minEntropy || this.hash.hmacStrength; - - this._reseed = null; - this.reseedInterval = null; - this.K = null; - this.V = null; - - var entropy = utils.toArray(options.entropy, options.entropyEnc || 'hex'); - var nonce = utils.toArray(options.nonce, options.nonceEnc || 'hex'); - var pers = utils.toArray(options.pers, options.persEnc || 'hex'); - assert(entropy.length >= (this.minEntropy / 8), - 'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits'); - this._init(entropy, nonce, pers); -} -module.exports = HmacDRBG; - -HmacDRBG.prototype._init = function init(entropy, nonce, pers) { - var seed = entropy.concat(nonce).concat(pers); - - this.K = new Array(this.outLen / 8); - this.V = new Array(this.outLen / 8); - for (var i = 0; i < this.V.length; i++) { - this.K[i] = 0x00; - this.V[i] = 0x01; - } - - this._update(seed); - this._reseed = 1; - this.reseedInterval = 0x1000000000000; // 2^48 -}; - -HmacDRBG.prototype._hmac = function hmac() { - return new hash.hmac(this.hash, this.K); -}; - -HmacDRBG.prototype._update = function update(seed) { - var kmac = this._hmac() - .update(this.V) - .update([ 0x00 ]); - if (seed) - kmac = kmac.update(seed); - this.K = kmac.digest(); - this.V = this._hmac().update(this.V).digest(); - if (!seed) - return; - - this.K = this._hmac() - .update(this.V) - .update([ 0x01 ]) - .update(seed) - .digest(); - this.V = this._hmac().update(this.V).digest(); -}; - -HmacDRBG.prototype.reseed = function reseed(entropy, entropyEnc, add, addEnc) { - // Optional entropy enc - if (typeof entropyEnc !== 'string') { - addEnc = add; - add = entropyEnc; - entropyEnc = null; - } - - entropy = utils.toArray(entropy, entropyEnc); - add = utils.toArray(add, addEnc); - - assert(entropy.length >= (this.minEntropy / 8), - 'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits'); - - this._update(entropy.concat(add || [])); - this._reseed = 1; -}; - -HmacDRBG.prototype.generate = function generate(len, enc, add, addEnc) { - if (this._reseed > this.reseedInterval) - throw new Error('Reseed is required'); - - // Optional encoding - if (typeof enc !== 'string') { - addEnc = add; - add = enc; - enc = null; - } - - // Optional additional data - if (add) { - add = utils.toArray(add, addEnc || 'hex'); - this._update(add); - } - - var temp = []; - while (temp.length < len) { - this.V = this._hmac().update(this.V).digest(); - temp = temp.concat(this.V); - } - - var res = temp.slice(0, len); - this._update(add); - this._reseed++; - return utils.encode(res, enc); -}; - -},{"hash.js":34,"minimalistic-assert":48,"minimalistic-crypto-utils":49}],47:[function(require,module,exports){ -if (typeof Object.create === 'function') { - // implementation from standard node.js 'util' module - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }); - }; -} else { - // old school shim for old browsers - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - var TempCtor = function () {} - TempCtor.prototype = superCtor.prototype - ctor.prototype = new TempCtor() - ctor.prototype.constructor = ctor - } -} - -},{}],48:[function(require,module,exports){ -module.exports = assert; - -function assert(val, msg) { - if (!val) - throw new Error(msg || 'Assertion failed'); -} - -assert.equal = function assertEqual(l, r, msg) { - if (l != r) - throw new Error(msg || ('Assertion failed: ' + l + ' != ' + r)); -}; - -},{}],49:[function(require,module,exports){ -'use strict'; - -var utils = exports; - -function toArray(msg, enc) { - if (Array.isArray(msg)) - return msg.slice(); - if (!msg) - return []; - var res = []; - if (typeof msg !== 'string') { - for (var i = 0; i < msg.length; i++) - res[i] = msg[i] | 0; - return res; - } - if (enc === 'hex') { - msg = msg.replace(/[^a-z0-9]+/ig, ''); - if (msg.length % 2 !== 0) - msg = '0' + msg; - for (var i = 0; i < msg.length; i += 2) - res.push(parseInt(msg[i] + msg[i + 1], 16)); - } else { - for (var i = 0; i < msg.length; i++) { - var c = msg.charCodeAt(i); - var hi = c >> 8; - var lo = c & 0xff; - if (hi) - res.push(hi, lo); - else - res.push(lo); - } - } - return res; -} -utils.toArray = toArray; - -function zero2(word) { - if (word.length === 1) - return '0' + word; - else - return word; -} -utils.zero2 = zero2; - -function toHex(msg) { - var res = ''; - for (var i = 0; i < msg.length; i++) - res += zero2(msg[i].toString(16)); - return res; -} -utils.toHex = toHex; - -utils.encode = function encode(arr, enc) { - if (enc === 'hex') - return toHex(arr); - else - return arr; -}; - -},{}],50:[function(require,module,exports){ -// Top level file is just a mixin of submodules & constants -'use strict'; - -var assign = require('./lib/utils/common').assign; - -var deflate = require('./lib/deflate'); -var inflate = require('./lib/inflate'); -var constants = require('./lib/zlib/constants'); - -var pako = {}; - -assign(pako, deflate, inflate, constants); - -module.exports = pako; - -},{"./lib/deflate":51,"./lib/inflate":52,"./lib/utils/common":53,"./lib/zlib/constants":56}],51:[function(require,module,exports){ -'use strict'; - - -var zlib_deflate = require('./zlib/deflate'); -var utils = require('./utils/common'); -var strings = require('./utils/strings'); -var msg = require('./zlib/messages'); -var ZStream = require('./zlib/zstream'); - -var toString = Object.prototype.toString; - -/* Public constants ==========================================================*/ -/* ===========================================================================*/ - -var Z_NO_FLUSH = 0; -var Z_FINISH = 4; - -var Z_OK = 0; -var Z_STREAM_END = 1; -var Z_SYNC_FLUSH = 2; - -var Z_DEFAULT_COMPRESSION = -1; - -var Z_DEFAULT_STRATEGY = 0; - -var Z_DEFLATED = 8; - -/* ===========================================================================*/ - - -/** - * class Deflate - * - * Generic JS-style wrapper for zlib calls. If you don't need - * streaming behaviour - use more simple functions: [[deflate]], - * [[deflateRaw]] and [[gzip]]. - **/ - -/* internal - * Deflate.chunks -> Array - * - * Chunks of output data, if [[Deflate#onData]] not overridden. - **/ - -/** - * Deflate.result -> Uint8Array|Array - * - * Compressed result, generated by default [[Deflate#onData]] - * and [[Deflate#onEnd]] handlers. Filled after you push last chunk - * (call [[Deflate#push]] with `Z_FINISH` / `true` param) or if you - * push a chunk with explicit flush (call [[Deflate#push]] with - * `Z_SYNC_FLUSH` param). - **/ - -/** - * Deflate.err -> Number - * - * Error code after deflate finished. 0 (Z_OK) on success. - * You will not need it in real life, because deflate errors - * are possible only on wrong options or bad `onData` / `onEnd` - * custom handlers. - **/ - -/** - * Deflate.msg -> String - * - * Error message, if [[Deflate.err]] != 0 - **/ - - -/** - * new Deflate(options) - * - options (Object): zlib deflate options. - * - * Creates new deflator instance with specified params. Throws exception - * on bad params. Supported options: - * - * - `level` - * - `windowBits` - * - `memLevel` - * - `strategy` - * - `dictionary` - * - * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) - * for more information on these. - * - * Additional options, for internal needs: - * - * - `chunkSize` - size of generated data chunks (16K by default) - * - `raw` (Boolean) - do raw deflate - * - `gzip` (Boolean) - create gzip wrapper - * - `to` (String) - if equal to 'string', then result will be "binary string" - * (each char code [0..255]) - * - `header` (Object) - custom header for gzip - * - `text` (Boolean) - true if compressed data believed to be text - * - `time` (Number) - modification time, unix timestamp - * - `os` (Number) - operation system code - * - `extra` (Array) - array of bytes with extra data (max 65536) - * - `name` (String) - file name (binary string) - * - `comment` (String) - comment (binary string) - * - `hcrc` (Boolean) - true if header crc should be added - * - * ##### Example: - * - * ```javascript - * var pako = require('pako') - * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9]) - * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]); - * - * var deflate = new pako.Deflate({ level: 3}); - * - * deflate.push(chunk1, false); - * deflate.push(chunk2, true); // true -> last chunk - * - * if (deflate.err) { throw new Error(deflate.err); } - * - * console.log(deflate.result); - * ``` - **/ -function Deflate(options) { - if (!(this instanceof Deflate)) return new Deflate(options); - - this.options = utils.assign({ - level: Z_DEFAULT_COMPRESSION, - method: Z_DEFLATED, - chunkSize: 16384, - windowBits: 15, - memLevel: 8, - strategy: Z_DEFAULT_STRATEGY, - to: '' - }, options || {}); - - var opt = this.options; - - if (opt.raw && (opt.windowBits > 0)) { - opt.windowBits = -opt.windowBits; - } - - else if (opt.gzip && (opt.windowBits > 0) && (opt.windowBits < 16)) { - opt.windowBits += 16; - } - - this.err = 0; // error code, if happens (0 = Z_OK) - this.msg = ''; // error message - this.ended = false; // used to avoid multiple onEnd() calls - this.chunks = []; // chunks of compressed data - - this.strm = new ZStream(); - this.strm.avail_out = 0; - - var status = zlib_deflate.deflateInit2( - this.strm, - opt.level, - opt.method, - opt.windowBits, - opt.memLevel, - opt.strategy - ); - - if (status !== Z_OK) { - throw new Error(msg[status]); - } - - if (opt.header) { - zlib_deflate.deflateSetHeader(this.strm, opt.header); - } - - if (opt.dictionary) { - var dict; - // Convert data if needed - if (typeof opt.dictionary === 'string') { - // If we need to compress text, change encoding to utf8. - dict = strings.string2buf(opt.dictionary); - } else if (toString.call(opt.dictionary) === '[object ArrayBuffer]') { - dict = new Uint8Array(opt.dictionary); - } else { - dict = opt.dictionary; - } - - status = zlib_deflate.deflateSetDictionary(this.strm, dict); - - if (status !== Z_OK) { - throw new Error(msg[status]); - } - - this._dict_set = true; - } -} - -/** - * Deflate#push(data[, mode]) -> Boolean - * - data (Uint8Array|Array|ArrayBuffer|String): input data. Strings will be - * converted to utf8 byte sequence. - * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. - * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH. - * - * Sends input data to deflate pipe, generating [[Deflate#onData]] calls with - * new compressed chunks. Returns `true` on success. The last data block must have - * mode Z_FINISH (or `true`). That will flush internal pending buffers and call - * [[Deflate#onEnd]]. For interim explicit flushes (without ending the stream) you - * can use mode Z_SYNC_FLUSH, keeping the compression context. - * - * On fail call [[Deflate#onEnd]] with error code and return false. - * - * We strongly recommend to use `Uint8Array` on input for best speed (output - * array format is detected automatically). Also, don't skip last param and always - * use the same type in your code (boolean or number). That will improve JS speed. - * - * For regular `Array`-s make sure all elements are [0..255]. - * - * ##### Example - * - * ```javascript - * push(chunk, false); // push one of data chunks - * ... - * push(chunk, true); // push last chunk - * ``` - **/ -Deflate.prototype.push = function (data, mode) { - var strm = this.strm; - var chunkSize = this.options.chunkSize; - var status, _mode; - - if (this.ended) { return false; } - - _mode = (mode === ~~mode) ? mode : ((mode === true) ? Z_FINISH : Z_NO_FLUSH); - - // Convert data if needed - if (typeof data === 'string') { - // If we need to compress text, change encoding to utf8. - strm.input = strings.string2buf(data); - } else if (toString.call(data) === '[object ArrayBuffer]') { - strm.input = new Uint8Array(data); - } else { - strm.input = data; - } - - strm.next_in = 0; - strm.avail_in = strm.input.length; - - do { - if (strm.avail_out === 0) { - strm.output = new utils.Buf8(chunkSize); - strm.next_out = 0; - strm.avail_out = chunkSize; - } - status = zlib_deflate.deflate(strm, _mode); /* no bad return value */ - - if (status !== Z_STREAM_END && status !== Z_OK) { - this.onEnd(status); - this.ended = true; - return false; - } - if (strm.avail_out === 0 || (strm.avail_in === 0 && (_mode === Z_FINISH || _mode === Z_SYNC_FLUSH))) { - if (this.options.to === 'string') { - this.onData(strings.buf2binstring(utils.shrinkBuf(strm.output, strm.next_out))); - } else { - this.onData(utils.shrinkBuf(strm.output, strm.next_out)); - } - } - } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== Z_STREAM_END); - - // Finalize on the last chunk. - if (_mode === Z_FINISH) { - status = zlib_deflate.deflateEnd(this.strm); - this.onEnd(status); - this.ended = true; - return status === Z_OK; - } - - // callback interim results if Z_SYNC_FLUSH. - if (_mode === Z_SYNC_FLUSH) { - this.onEnd(Z_OK); - strm.avail_out = 0; - return true; - } - - return true; -}; - - -/** - * Deflate#onData(chunk) -> Void - * - chunk (Uint8Array|Array|String): output data. Type of array depends - * on js engine support. When string output requested, each chunk - * will be string. - * - * By default, stores data blocks in `chunks[]` property and glue - * those in `onEnd`. Override this handler, if you need another behaviour. - **/ -Deflate.prototype.onData = function (chunk) { - this.chunks.push(chunk); -}; - - -/** - * Deflate#onEnd(status) -> Void - * - status (Number): deflate status. 0 (Z_OK) on success, - * other if not. - * - * Called once after you tell deflate that the input stream is - * complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH) - * or if an error happened. By default - join collected chunks, - * free memory and fill `results` / `err` properties. - **/ -Deflate.prototype.onEnd = function (status) { - // On success - join - if (status === Z_OK) { - if (this.options.to === 'string') { - this.result = this.chunks.join(''); - } else { - this.result = utils.flattenChunks(this.chunks); - } - } - this.chunks = []; - this.err = status; - this.msg = this.strm.msg; -}; - - -/** - * deflate(data[, options]) -> Uint8Array|Array|String - * - data (Uint8Array|Array|String): input data to compress. - * - options (Object): zlib deflate options. - * - * Compress `data` with deflate algorithm and `options`. - * - * Supported options are: - * - * - level - * - windowBits - * - memLevel - * - strategy - * - dictionary - * - * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) - * for more information on these. - * - * Sugar (options): - * - * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify - * negative windowBits implicitly. - * - `to` (String) - if equal to 'string', then result will be "binary string" - * (each char code [0..255]) - * - * ##### Example: - * - * ```javascript - * var pako = require('pako') - * , data = Uint8Array([1,2,3,4,5,6,7,8,9]); - * - * console.log(pako.deflate(data)); - * ``` - **/ -function deflate(input, options) { - var deflator = new Deflate(options); - - deflator.push(input, true); - - // That will never happens, if you don't cheat with options :) - if (deflator.err) { throw deflator.msg || msg[deflator.err]; } - - return deflator.result; -} - - -/** - * deflateRaw(data[, options]) -> Uint8Array|Array|String - * - data (Uint8Array|Array|String): input data to compress. - * - options (Object): zlib deflate options. - * - * The same as [[deflate]], but creates raw data, without wrapper - * (header and adler32 crc). - **/ -function deflateRaw(input, options) { - options = options || {}; - options.raw = true; - return deflate(input, options); -} - - -/** - * gzip(data[, options]) -> Uint8Array|Array|String - * - data (Uint8Array|Array|String): input data to compress. - * - options (Object): zlib deflate options. - * - * The same as [[deflate]], but create gzip wrapper instead of - * deflate one. - **/ -function gzip(input, options) { - options = options || {}; - options.gzip = true; - return deflate(input, options); -} - - -exports.Deflate = Deflate; -exports.deflate = deflate; -exports.deflateRaw = deflateRaw; -exports.gzip = gzip; - -},{"./utils/common":53,"./utils/strings":54,"./zlib/deflate":58,"./zlib/messages":63,"./zlib/zstream":65}],52:[function(require,module,exports){ -'use strict'; - - -var zlib_inflate = require('./zlib/inflate'); -var utils = require('./utils/common'); -var strings = require('./utils/strings'); -var c = require('./zlib/constants'); -var msg = require('./zlib/messages'); -var ZStream = require('./zlib/zstream'); -var GZheader = require('./zlib/gzheader'); - -var toString = Object.prototype.toString; - -/** - * class Inflate - * - * Generic JS-style wrapper for zlib calls. If you don't need - * streaming behaviour - use more simple functions: [[inflate]] - * and [[inflateRaw]]. - **/ - -/* internal - * inflate.chunks -> Array - * - * Chunks of output data, if [[Inflate#onData]] not overridden. - **/ - -/** - * Inflate.result -> Uint8Array|Array|String - * - * Uncompressed result, generated by default [[Inflate#onData]] - * and [[Inflate#onEnd]] handlers. Filled after you push last chunk - * (call [[Inflate#push]] with `Z_FINISH` / `true` param) or if you - * push a chunk with explicit flush (call [[Inflate#push]] with - * `Z_SYNC_FLUSH` param). - **/ - -/** - * Inflate.err -> Number - * - * Error code after inflate finished. 0 (Z_OK) on success. - * Should be checked if broken data possible. - **/ - -/** - * Inflate.msg -> String - * - * Error message, if [[Inflate.err]] != 0 - **/ - - -/** - * new Inflate(options) - * - options (Object): zlib inflate options. - * - * Creates new inflator instance with specified params. Throws exception - * on bad params. Supported options: - * - * - `windowBits` - * - `dictionary` - * - * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) - * for more information on these. - * - * Additional options, for internal needs: - * - * - `chunkSize` - size of generated data chunks (16K by default) - * - `raw` (Boolean) - do raw inflate - * - `to` (String) - if equal to 'string', then result will be converted - * from utf8 to utf16 (javascript) string. When string output requested, - * chunk length can differ from `chunkSize`, depending on content. - * - * By default, when no options set, autodetect deflate/gzip data format via - * wrapper header. - * - * ##### Example: - * - * ```javascript - * var pako = require('pako') - * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9]) - * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]); - * - * var inflate = new pako.Inflate({ level: 3}); - * - * inflate.push(chunk1, false); - * inflate.push(chunk2, true); // true -> last chunk - * - * if (inflate.err) { throw new Error(inflate.err); } - * - * console.log(inflate.result); - * ``` - **/ -function Inflate(options) { - if (!(this instanceof Inflate)) return new Inflate(options); - - this.options = utils.assign({ - chunkSize: 16384, - windowBits: 0, - to: '' - }, options || {}); - - var opt = this.options; - - // Force window size for `raw` data, if not set directly, - // because we have no header for autodetect. - if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) { - opt.windowBits = -opt.windowBits; - if (opt.windowBits === 0) { opt.windowBits = -15; } - } - - // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate - if ((opt.windowBits >= 0) && (opt.windowBits < 16) && - !(options && options.windowBits)) { - opt.windowBits += 32; - } - - // Gzip header has no info about windows size, we can do autodetect only - // for deflate. So, if window size not set, force it to max when gzip possible - if ((opt.windowBits > 15) && (opt.windowBits < 48)) { - // bit 3 (16) -> gzipped data - // bit 4 (32) -> autodetect gzip/deflate - if ((opt.windowBits & 15) === 0) { - opt.windowBits |= 15; - } - } - - this.err = 0; // error code, if happens (0 = Z_OK) - this.msg = ''; // error message - this.ended = false; // used to avoid multiple onEnd() calls - this.chunks = []; // chunks of compressed data - - this.strm = new ZStream(); - this.strm.avail_out = 0; - - var status = zlib_inflate.inflateInit2( - this.strm, - opt.windowBits - ); - - if (status !== c.Z_OK) { - throw new Error(msg[status]); - } - - this.header = new GZheader(); - - zlib_inflate.inflateGetHeader(this.strm, this.header); -} - -/** - * Inflate#push(data[, mode]) -> Boolean - * - data (Uint8Array|Array|ArrayBuffer|String): input data - * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. - * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH. - * - * Sends input data to inflate pipe, generating [[Inflate#onData]] calls with - * new output chunks. Returns `true` on success. The last data block must have - * mode Z_FINISH (or `true`). That will flush internal pending buffers and call - * [[Inflate#onEnd]]. For interim explicit flushes (without ending the stream) you - * can use mode Z_SYNC_FLUSH, keeping the decompression context. - * - * On fail call [[Inflate#onEnd]] with error code and return false. - * - * We strongly recommend to use `Uint8Array` on input for best speed (output - * format is detected automatically). Also, don't skip last param and always - * use the same type in your code (boolean or number). That will improve JS speed. - * - * For regular `Array`-s make sure all elements are [0..255]. - * - * ##### Example - * - * ```javascript - * push(chunk, false); // push one of data chunks - * ... - * push(chunk, true); // push last chunk - * ``` - **/ -Inflate.prototype.push = function (data, mode) { - var strm = this.strm; - var chunkSize = this.options.chunkSize; - var dictionary = this.options.dictionary; - var status, _mode; - var next_out_utf8, tail, utf8str; - var dict; - - // Flag to properly process Z_BUF_ERROR on testing inflate call - // when we check that all output data was flushed. - var allowBufError = false; - - if (this.ended) { return false; } - _mode = (mode === ~~mode) ? mode : ((mode === true) ? c.Z_FINISH : c.Z_NO_FLUSH); - - // Convert data if needed - if (typeof data === 'string') { - // Only binary strings can be decompressed on practice - strm.input = strings.binstring2buf(data); - } else if (toString.call(data) === '[object ArrayBuffer]') { - strm.input = new Uint8Array(data); - } else { - strm.input = data; - } - - strm.next_in = 0; - strm.avail_in = strm.input.length; - - do { - if (strm.avail_out === 0) { - strm.output = new utils.Buf8(chunkSize); - strm.next_out = 0; - strm.avail_out = chunkSize; - } - - status = zlib_inflate.inflate(strm, c.Z_NO_FLUSH); /* no bad return value */ - - if (status === c.Z_NEED_DICT && dictionary) { - // Convert data if needed - if (typeof dictionary === 'string') { - dict = strings.string2buf(dictionary); - } else if (toString.call(dictionary) === '[object ArrayBuffer]') { - dict = new Uint8Array(dictionary); - } else { - dict = dictionary; - } - - status = zlib_inflate.inflateSetDictionary(this.strm, dict); - - } - - if (status === c.Z_BUF_ERROR && allowBufError === true) { - status = c.Z_OK; - allowBufError = false; - } - - if (status !== c.Z_STREAM_END && status !== c.Z_OK) { - this.onEnd(status); - this.ended = true; - return false; - } - - if (strm.next_out) { - if (strm.avail_out === 0 || status === c.Z_STREAM_END || (strm.avail_in === 0 && (_mode === c.Z_FINISH || _mode === c.Z_SYNC_FLUSH))) { - - if (this.options.to === 'string') { - - next_out_utf8 = strings.utf8border(strm.output, strm.next_out); - - tail = strm.next_out - next_out_utf8; - utf8str = strings.buf2string(strm.output, next_out_utf8); - - // move tail - strm.next_out = tail; - strm.avail_out = chunkSize - tail; - if (tail) { utils.arraySet(strm.output, strm.output, next_out_utf8, tail, 0); } - - this.onData(utf8str); - - } else { - this.onData(utils.shrinkBuf(strm.output, strm.next_out)); - } - } - } - - // When no more input data, we should check that internal inflate buffers - // are flushed. The only way to do it when avail_out = 0 - run one more - // inflate pass. But if output data not exists, inflate return Z_BUF_ERROR. - // Here we set flag to process this error properly. - // - // NOTE. Deflate does not return error in this case and does not needs such - // logic. - if (strm.avail_in === 0 && strm.avail_out === 0) { - allowBufError = true; - } - - } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== c.Z_STREAM_END); - - if (status === c.Z_STREAM_END) { - _mode = c.Z_FINISH; - } - - // Finalize on the last chunk. - if (_mode === c.Z_FINISH) { - status = zlib_inflate.inflateEnd(this.strm); - this.onEnd(status); - this.ended = true; - return status === c.Z_OK; - } - - // callback interim results if Z_SYNC_FLUSH. - if (_mode === c.Z_SYNC_FLUSH) { - this.onEnd(c.Z_OK); - strm.avail_out = 0; - return true; - } - - return true; -}; - - -/** - * Inflate#onData(chunk) -> Void - * - chunk (Uint8Array|Array|String): output data. Type of array depends - * on js engine support. When string output requested, each chunk - * will be string. - * - * By default, stores data blocks in `chunks[]` property and glue - * those in `onEnd`. Override this handler, if you need another behaviour. - **/ -Inflate.prototype.onData = function (chunk) { - this.chunks.push(chunk); -}; - - -/** - * Inflate#onEnd(status) -> Void - * - status (Number): inflate status. 0 (Z_OK) on success, - * other if not. - * - * Called either after you tell inflate that the input stream is - * complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH) - * or if an error happened. By default - join collected chunks, - * free memory and fill `results` / `err` properties. - **/ -Inflate.prototype.onEnd = function (status) { - // On success - join - if (status === c.Z_OK) { - if (this.options.to === 'string') { - // Glue & convert here, until we teach pako to send - // utf8 aligned strings to onData - this.result = this.chunks.join(''); - } else { - this.result = utils.flattenChunks(this.chunks); - } - } - this.chunks = []; - this.err = status; - this.msg = this.strm.msg; -}; - - -/** - * inflate(data[, options]) -> Uint8Array|Array|String - * - data (Uint8Array|Array|String): input data to decompress. - * - options (Object): zlib inflate options. - * - * Decompress `data` with inflate/ungzip and `options`. Autodetect - * format via wrapper header by default. That's why we don't provide - * separate `ungzip` method. - * - * Supported options are: - * - * - windowBits - * - * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) - * for more information. - * - * Sugar (options): - * - * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify - * negative windowBits implicitly. - * - `to` (String) - if equal to 'string', then result will be converted - * from utf8 to utf16 (javascript) string. When string output requested, - * chunk length can differ from `chunkSize`, depending on content. - * - * - * ##### Example: - * - * ```javascript - * var pako = require('pako') - * , input = pako.deflate([1,2,3,4,5,6,7,8,9]) - * , output; - * - * try { - * output = pako.inflate(input); - * } catch (err) - * console.log(err); - * } - * ``` - **/ -function inflate(input, options) { - var inflator = new Inflate(options); - - inflator.push(input, true); - - // That will never happens, if you don't cheat with options :) - if (inflator.err) { throw inflator.msg || msg[inflator.err]; } - - return inflator.result; -} - - -/** - * inflateRaw(data[, options]) -> Uint8Array|Array|String - * - data (Uint8Array|Array|String): input data to decompress. - * - options (Object): zlib inflate options. - * - * The same as [[inflate]], but creates raw data, without wrapper - * (header and adler32 crc). - **/ -function inflateRaw(input, options) { - options = options || {}; - options.raw = true; - return inflate(input, options); -} - - -/** - * ungzip(data[, options]) -> Uint8Array|Array|String - * - data (Uint8Array|Array|String): input data to decompress. - * - options (Object): zlib inflate options. - * - * Just shortcut to [[inflate]], because it autodetects format - * by header.content. Done for convenience. - **/ - - -exports.Inflate = Inflate; -exports.inflate = inflate; -exports.inflateRaw = inflateRaw; -exports.ungzip = inflate; - -},{"./utils/common":53,"./utils/strings":54,"./zlib/constants":56,"./zlib/gzheader":59,"./zlib/inflate":61,"./zlib/messages":63,"./zlib/zstream":65}],53:[function(require,module,exports){ -'use strict'; - - -var TYPED_OK = (typeof Uint8Array !== 'undefined') && - (typeof Uint16Array !== 'undefined') && - (typeof Int32Array !== 'undefined'); - -function _has(obj, key) { - return Object.prototype.hasOwnProperty.call(obj, key); -} - -exports.assign = function (obj /*from1, from2, from3, ...*/) { - var sources = Array.prototype.slice.call(arguments, 1); - while (sources.length) { - var source = sources.shift(); - if (!source) { continue; } - - if (typeof source !== 'object') { - throw new TypeError(source + 'must be non-object'); - } - - for (var p in source) { - if (_has(source, p)) { - obj[p] = source[p]; - } - } - } - - return obj; -}; - - -// reduce buffer size, avoiding mem copy -exports.shrinkBuf = function (buf, size) { - if (buf.length === size) { return buf; } - if (buf.subarray) { return buf.subarray(0, size); } - buf.length = size; - return buf; -}; - - -var fnTyped = { - arraySet: function (dest, src, src_offs, len, dest_offs) { - if (src.subarray && dest.subarray) { - dest.set(src.subarray(src_offs, src_offs + len), dest_offs); - return; - } - // Fallback to ordinary array - for (var i = 0; i < len; i++) { - dest[dest_offs + i] = src[src_offs + i]; - } - }, - // Join array of chunks to single array. - flattenChunks: function (chunks) { - var i, l, len, pos, chunk, result; - - // calculate data length - len = 0; - for (i = 0, l = chunks.length; i < l; i++) { - len += chunks[i].length; - } - - // join chunks - result = new Uint8Array(len); - pos = 0; - for (i = 0, l = chunks.length; i < l; i++) { - chunk = chunks[i]; - result.set(chunk, pos); - pos += chunk.length; - } - - return result; - } -}; - -var fnUntyped = { - arraySet: function (dest, src, src_offs, len, dest_offs) { - for (var i = 0; i < len; i++) { - dest[dest_offs + i] = src[src_offs + i]; - } - }, - // Join array of chunks to single array. - flattenChunks: function (chunks) { - return [].concat.apply([], chunks); - } -}; - - -// Enable/Disable typed arrays use, for testing -// -exports.setTyped = function (on) { - if (on) { - exports.Buf8 = Uint8Array; - exports.Buf16 = Uint16Array; - exports.Buf32 = Int32Array; - exports.assign(exports, fnTyped); - } else { - exports.Buf8 = Array; - exports.Buf16 = Array; - exports.Buf32 = Array; - exports.assign(exports, fnUntyped); - } -}; - -exports.setTyped(TYPED_OK); - -},{}],54:[function(require,module,exports){ -// String encode/decode helpers -'use strict'; - - -var utils = require('./common'); - - -// Quick check if we can use fast array to bin string conversion -// -// - apply(Array) can fail on Android 2.2 -// - apply(Uint8Array) can fail on iOS 5.1 Safari -// -var STR_APPLY_OK = true; -var STR_APPLY_UIA_OK = true; - -try { String.fromCharCode.apply(null, [ 0 ]); } catch (__) { STR_APPLY_OK = false; } -try { String.fromCharCode.apply(null, new Uint8Array(1)); } catch (__) { STR_APPLY_UIA_OK = false; } - - -// Table with utf8 lengths (calculated by first byte of sequence) -// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS, -// because max possible codepoint is 0x10ffff -var _utf8len = new utils.Buf8(256); -for (var q = 0; q < 256; q++) { - _utf8len[q] = (q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1); -} -_utf8len[254] = _utf8len[254] = 1; // Invalid sequence start - - -// convert string to array (typed, when possible) -exports.string2buf = function (str) { - var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0; - - // count binary size - for (m_pos = 0; m_pos < str_len; m_pos++) { - c = str.charCodeAt(m_pos); - if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) { - c2 = str.charCodeAt(m_pos + 1); - if ((c2 & 0xfc00) === 0xdc00) { - c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); - m_pos++; - } - } - buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4; - } - - // allocate buffer - buf = new utils.Buf8(buf_len); - - // convert - for (i = 0, m_pos = 0; i < buf_len; m_pos++) { - c = str.charCodeAt(m_pos); - if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) { - c2 = str.charCodeAt(m_pos + 1); - if ((c2 & 0xfc00) === 0xdc00) { - c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); - m_pos++; - } - } - if (c < 0x80) { - /* one byte */ - buf[i++] = c; - } else if (c < 0x800) { - /* two bytes */ - buf[i++] = 0xC0 | (c >>> 6); - buf[i++] = 0x80 | (c & 0x3f); - } else if (c < 0x10000) { - /* three bytes */ - buf[i++] = 0xE0 | (c >>> 12); - buf[i++] = 0x80 | (c >>> 6 & 0x3f); - buf[i++] = 0x80 | (c & 0x3f); - } else { - /* four bytes */ - buf[i++] = 0xf0 | (c >>> 18); - buf[i++] = 0x80 | (c >>> 12 & 0x3f); - buf[i++] = 0x80 | (c >>> 6 & 0x3f); - buf[i++] = 0x80 | (c & 0x3f); - } - } - - return buf; -}; - -// Helper (used in 2 places) -function buf2binstring(buf, len) { - // use fallback for big arrays to avoid stack overflow - if (len < 65537) { - if ((buf.subarray && STR_APPLY_UIA_OK) || (!buf.subarray && STR_APPLY_OK)) { - return String.fromCharCode.apply(null, utils.shrinkBuf(buf, len)); - } - } - - var result = ''; - for (var i = 0; i < len; i++) { - result += String.fromCharCode(buf[i]); - } - return result; -} - - -// Convert byte array to binary string -exports.buf2binstring = function (buf) { - return buf2binstring(buf, buf.length); -}; - - -// Convert binary string (typed, when possible) -exports.binstring2buf = function (str) { - var buf = new utils.Buf8(str.length); - for (var i = 0, len = buf.length; i < len; i++) { - buf[i] = str.charCodeAt(i); - } - return buf; -}; - - -// convert array to string -exports.buf2string = function (buf, max) { - var i, out, c, c_len; - var len = max || buf.length; - - // Reserve max possible length (2 words per char) - // NB: by unknown reasons, Array is significantly faster for - // String.fromCharCode.apply than Uint16Array. - var utf16buf = new Array(len * 2); - - for (out = 0, i = 0; i < len;) { - c = buf[i++]; - // quick process ascii - if (c < 0x80) { utf16buf[out++] = c; continue; } - - c_len = _utf8len[c]; - // skip 5 & 6 byte codes - if (c_len > 4) { utf16buf[out++] = 0xfffd; i += c_len - 1; continue; } - - // apply mask on first byte - c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07; - // join the rest - while (c_len > 1 && i < len) { - c = (c << 6) | (buf[i++] & 0x3f); - c_len--; - } - - // terminated by end of string? - if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; } - - if (c < 0x10000) { - utf16buf[out++] = c; - } else { - c -= 0x10000; - utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff); - utf16buf[out++] = 0xdc00 | (c & 0x3ff); - } - } - - return buf2binstring(utf16buf, out); -}; - - -// Calculate max possible position in utf8 buffer, -// that will not break sequence. If that's not possible -// - (very small limits) return max size as is. -// -// buf[] - utf8 bytes array -// max - length limit (mandatory); -exports.utf8border = function (buf, max) { - var pos; - - max = max || buf.length; - if (max > buf.length) { max = buf.length; } - - // go back from last position, until start of sequence found - pos = max - 1; - while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; } - - // Very small and broken sequence, - // return max, because we should return something anyway. - if (pos < 0) { return max; } - - // If we came to start of buffer - that means buffer is too small, - // return max too. - if (pos === 0) { return max; } - - return (pos + _utf8len[buf[pos]] > max) ? pos : max; -}; - -},{"./common":53}],55:[function(require,module,exports){ -'use strict'; - -// Note: adler32 takes 12% for level 0 and 2% for level 6. -// It isn't worth it to make additional optimizations as in original. -// Small size is preferable. - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -function adler32(adler, buf, len, pos) { - var s1 = (adler & 0xffff) |0, - s2 = ((adler >>> 16) & 0xffff) |0, - n = 0; - - while (len !== 0) { - // Set limit ~ twice less than 5552, to keep - // s2 in 31-bits, because we force signed ints. - // in other case %= will fail. - n = len > 2000 ? 2000 : len; - len -= n; - - do { - s1 = (s1 + buf[pos++]) |0; - s2 = (s2 + s1) |0; - } while (--n); - - s1 %= 65521; - s2 %= 65521; - } - - return (s1 | (s2 << 16)) |0; -} - - -module.exports = adler32; - -},{}],56:[function(require,module,exports){ -'use strict'; - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -module.exports = { - - /* Allowed flush values; see deflate() and inflate() below for details */ - Z_NO_FLUSH: 0, - Z_PARTIAL_FLUSH: 1, - Z_SYNC_FLUSH: 2, - Z_FULL_FLUSH: 3, - Z_FINISH: 4, - Z_BLOCK: 5, - Z_TREES: 6, - - /* Return codes for the compression/decompression functions. Negative values - * are errors, positive values are used for special but normal events. - */ - Z_OK: 0, - Z_STREAM_END: 1, - Z_NEED_DICT: 2, - Z_ERRNO: -1, - Z_STREAM_ERROR: -2, - Z_DATA_ERROR: -3, - //Z_MEM_ERROR: -4, - Z_BUF_ERROR: -5, - //Z_VERSION_ERROR: -6, - - /* compression levels */ - Z_NO_COMPRESSION: 0, - Z_BEST_SPEED: 1, - Z_BEST_COMPRESSION: 9, - Z_DEFAULT_COMPRESSION: -1, - - - Z_FILTERED: 1, - Z_HUFFMAN_ONLY: 2, - Z_RLE: 3, - Z_FIXED: 4, - Z_DEFAULT_STRATEGY: 0, - - /* Possible values of the data_type field (though see inflate()) */ - Z_BINARY: 0, - Z_TEXT: 1, - //Z_ASCII: 1, // = Z_TEXT (deprecated) - Z_UNKNOWN: 2, - - /* The deflate compression method */ - Z_DEFLATED: 8 - //Z_NULL: null // Use -1 or null inline, depending on var type -}; - -},{}],57:[function(require,module,exports){ -'use strict'; - -// Note: we can't get significant speed boost here. -// So write code to minimize size - no pregenerated tables -// and array tools dependencies. - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -// Use ordinary array, since untyped makes no boost here -function makeTable() { - var c, table = []; - - for (var n = 0; n < 256; n++) { - c = n; - for (var k = 0; k < 8; k++) { - c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); - } - table[n] = c; - } - - return table; -} - -// Create table on load. Just 255 signed longs. Not a problem. -var crcTable = makeTable(); - - -function crc32(crc, buf, len, pos) { - var t = crcTable, - end = pos + len; - - crc ^= -1; - - for (var i = pos; i < end; i++) { - crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF]; - } - - return (crc ^ (-1)); // >>> 0; -} - - -module.exports = crc32; - -},{}],58:[function(require,module,exports){ -'use strict'; - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -var utils = require('../utils/common'); -var trees = require('./trees'); -var adler32 = require('./adler32'); -var crc32 = require('./crc32'); -var msg = require('./messages'); - -/* Public constants ==========================================================*/ -/* ===========================================================================*/ - - -/* Allowed flush values; see deflate() and inflate() below for details */ -var Z_NO_FLUSH = 0; -var Z_PARTIAL_FLUSH = 1; -//var Z_SYNC_FLUSH = 2; -var Z_FULL_FLUSH = 3; -var Z_FINISH = 4; -var Z_BLOCK = 5; -//var Z_TREES = 6; - - -/* Return codes for the compression/decompression functions. Negative values - * are errors, positive values are used for special but normal events. - */ -var Z_OK = 0; -var Z_STREAM_END = 1; -//var Z_NEED_DICT = 2; -//var Z_ERRNO = -1; -var Z_STREAM_ERROR = -2; -var Z_DATA_ERROR = -3; -//var Z_MEM_ERROR = -4; -var Z_BUF_ERROR = -5; -//var Z_VERSION_ERROR = -6; - - -/* compression levels */ -//var Z_NO_COMPRESSION = 0; -//var Z_BEST_SPEED = 1; -//var Z_BEST_COMPRESSION = 9; -var Z_DEFAULT_COMPRESSION = -1; - - -var Z_FILTERED = 1; -var Z_HUFFMAN_ONLY = 2; -var Z_RLE = 3; -var Z_FIXED = 4; -var Z_DEFAULT_STRATEGY = 0; - -/* Possible values of the data_type field (though see inflate()) */ -//var Z_BINARY = 0; -//var Z_TEXT = 1; -//var Z_ASCII = 1; // = Z_TEXT -var Z_UNKNOWN = 2; - - -/* The deflate compression method */ -var Z_DEFLATED = 8; - -/*============================================================================*/ - - -var MAX_MEM_LEVEL = 9; -/* Maximum value for memLevel in deflateInit2 */ -var MAX_WBITS = 15; -/* 32K LZ77 window */ -var DEF_MEM_LEVEL = 8; - - -var LENGTH_CODES = 29; -/* number of length codes, not counting the special END_BLOCK code */ -var LITERALS = 256; -/* number of literal bytes 0..255 */ -var L_CODES = LITERALS + 1 + LENGTH_CODES; -/* number of Literal or Length codes, including the END_BLOCK code */ -var D_CODES = 30; -/* number of distance codes */ -var BL_CODES = 19; -/* number of codes used to transfer the bit lengths */ -var HEAP_SIZE = 2 * L_CODES + 1; -/* maximum heap size */ -var MAX_BITS = 15; -/* All codes must not exceed MAX_BITS bits */ - -var MIN_MATCH = 3; -var MAX_MATCH = 258; -var MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1); - -var PRESET_DICT = 0x20; - -var INIT_STATE = 42; -var EXTRA_STATE = 69; -var NAME_STATE = 73; -var COMMENT_STATE = 91; -var HCRC_STATE = 103; -var BUSY_STATE = 113; -var FINISH_STATE = 666; - -var BS_NEED_MORE = 1; /* block not completed, need more input or more output */ -var BS_BLOCK_DONE = 2; /* block flush performed */ -var BS_FINISH_STARTED = 3; /* finish started, need only more output at next deflate */ -var BS_FINISH_DONE = 4; /* finish done, accept no more input or output */ - -var OS_CODE = 0x03; // Unix :) . Don't detect, use this default. - -function err(strm, errorCode) { - strm.msg = msg[errorCode]; - return errorCode; -} - -function rank(f) { - return ((f) << 1) - ((f) > 4 ? 9 : 0); -} - -function zero(buf) { var len = buf.length; while (--len >= 0) { buf[len] = 0; } } - - -/* ========================================================================= - * Flush as much pending output as possible. All deflate() output goes - * through this function so some applications may wish to modify it - * to avoid allocating a large strm->output buffer and copying into it. - * (See also read_buf()). - */ -function flush_pending(strm) { - var s = strm.state; - - //_tr_flush_bits(s); - var len = s.pending; - if (len > strm.avail_out) { - len = strm.avail_out; - } - if (len === 0) { return; } - - utils.arraySet(strm.output, s.pending_buf, s.pending_out, len, strm.next_out); - strm.next_out += len; - s.pending_out += len; - strm.total_out += len; - strm.avail_out -= len; - s.pending -= len; - if (s.pending === 0) { - s.pending_out = 0; - } -} - - -function flush_block_only(s, last) { - trees._tr_flush_block(s, (s.block_start >= 0 ? s.block_start : -1), s.strstart - s.block_start, last); - s.block_start = s.strstart; - flush_pending(s.strm); -} - - -function put_byte(s, b) { - s.pending_buf[s.pending++] = b; -} - - -/* ========================================================================= - * Put a short in the pending buffer. The 16-bit value is put in MSB order. - * IN assertion: the stream state is correct and there is enough room in - * pending_buf. - */ -function putShortMSB(s, b) { -// put_byte(s, (Byte)(b >> 8)); -// put_byte(s, (Byte)(b & 0xff)); - s.pending_buf[s.pending++] = (b >>> 8) & 0xff; - s.pending_buf[s.pending++] = b & 0xff; -} - - -/* =========================================================================== - * Read a new buffer from the current input stream, update the adler32 - * and total number of bytes read. All deflate() input goes through - * this function so some applications may wish to modify it to avoid - * allocating a large strm->input buffer and copying from it. - * (See also flush_pending()). - */ -function read_buf(strm, buf, start, size) { - var len = strm.avail_in; - - if (len > size) { len = size; } - if (len === 0) { return 0; } - - strm.avail_in -= len; - - // zmemcpy(buf, strm->next_in, len); - utils.arraySet(buf, strm.input, strm.next_in, len, start); - if (strm.state.wrap === 1) { - strm.adler = adler32(strm.adler, buf, len, start); - } - - else if (strm.state.wrap === 2) { - strm.adler = crc32(strm.adler, buf, len, start); - } - - strm.next_in += len; - strm.total_in += len; - - return len; -} - - -/* =========================================================================== - * Set match_start to the longest match starting at the given string and - * return its length. Matches shorter or equal to prev_length are discarded, - * in which case the result is equal to prev_length and match_start is - * garbage. - * IN assertions: cur_match is the head of the hash chain for the current - * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 - * OUT assertion: the match length is not greater than s->lookahead. - */ -function longest_match(s, cur_match) { - var chain_length = s.max_chain_length; /* max hash chain length */ - var scan = s.strstart; /* current string */ - var match; /* matched string */ - var len; /* length of current match */ - var best_len = s.prev_length; /* best match length so far */ - var nice_match = s.nice_match; /* stop if match long enough */ - var limit = (s.strstart > (s.w_size - MIN_LOOKAHEAD)) ? - s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0/*NIL*/; - - var _win = s.window; // shortcut - - var wmask = s.w_mask; - var prev = s.prev; - - /* Stop when cur_match becomes <= limit. To simplify the code, - * we prevent matches with the string of window index 0. - */ - - var strend = s.strstart + MAX_MATCH; - var scan_end1 = _win[scan + best_len - 1]; - var scan_end = _win[scan + best_len]; - - /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - * It is easy to get rid of this optimization if necessary. - */ - // Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - - /* Do not waste too much time if we already have a good match: */ - if (s.prev_length >= s.good_match) { - chain_length >>= 2; - } - /* Do not look for matches beyond the end of the input. This is necessary - * to make deflate deterministic. - */ - if (nice_match > s.lookahead) { nice_match = s.lookahead; } - - // Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); - - do { - // Assert(cur_match < s->strstart, "no future"); - match = cur_match; - - /* Skip to next match if the match length cannot increase - * or if the match length is less than 2. Note that the checks below - * for insufficient lookahead only occur occasionally for performance - * reasons. Therefore uninitialized memory will be accessed, and - * conditional jumps will be made that depend on those values. - * However the length of the match is limited to the lookahead, so - * the output of deflate is not affected by the uninitialized values. - */ - - if (_win[match + best_len] !== scan_end || - _win[match + best_len - 1] !== scan_end1 || - _win[match] !== _win[scan] || - _win[++match] !== _win[scan + 1]) { - continue; - } - - /* The check at best_len-1 can be removed because it will be made - * again later. (This heuristic is not always a win.) - * It is not necessary to compare scan[2] and match[2] since they - * are always equal when the other bytes match, given that - * the hash keys are equal and that HASH_BITS >= 8. - */ - scan += 2; - match++; - // Assert(*scan == *match, "match[2]?"); - - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. - */ - do { - /*jshint noempty:false*/ - } while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - scan < strend); - - // Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - - len = MAX_MATCH - (strend - scan); - scan = strend - MAX_MATCH; - - if (len > best_len) { - s.match_start = cur_match; - best_len = len; - if (len >= nice_match) { - break; - } - scan_end1 = _win[scan + best_len - 1]; - scan_end = _win[scan + best_len]; - } - } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0); - - if (best_len <= s.lookahead) { - return best_len; - } - return s.lookahead; -} - - -/* =========================================================================== - * Fill the window when the lookahead becomes insufficient. - * Updates strstart and lookahead. - * - * IN assertion: lookahead < MIN_LOOKAHEAD - * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD - * At least one byte has been read, or avail_in == 0; reads are - * performed for at least two bytes (required for the zip translate_eol - * option -- not supported here). - */ -function fill_window(s) { - var _w_size = s.w_size; - var p, n, m, more, str; - - //Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); - - do { - more = s.window_size - s.lookahead - s.strstart; - - // JS ints have 32 bit, block below not needed - /* Deal with !@#$% 64K limit: */ - //if (sizeof(int) <= 2) { - // if (more == 0 && s->strstart == 0 && s->lookahead == 0) { - // more = wsize; - // - // } else if (more == (unsigned)(-1)) { - // /* Very unlikely, but possible on 16 bit machine if - // * strstart == 0 && lookahead == 1 (input done a byte at time) - // */ - // more--; - // } - //} - - - /* If the window is almost full and there is insufficient lookahead, - * move the upper half to the lower one to make room in the upper half. - */ - if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) { - - utils.arraySet(s.window, s.window, _w_size, _w_size, 0); - s.match_start -= _w_size; - s.strstart -= _w_size; - /* we now have strstart >= MAX_DIST */ - s.block_start -= _w_size; - - /* Slide the hash table (could be avoided with 32 bit values - at the expense of memory usage). We slide even when level == 0 - to keep the hash table consistent if we switch back to level > 0 - later. (Using level 0 permanently is not an optimal usage of - zlib, so we don't care about this pathological case.) - */ - - n = s.hash_size; - p = n; - do { - m = s.head[--p]; - s.head[p] = (m >= _w_size ? m - _w_size : 0); - } while (--n); - - n = _w_size; - p = n; - do { - m = s.prev[--p]; - s.prev[p] = (m >= _w_size ? m - _w_size : 0); - /* If n is not on any hash chain, prev[n] is garbage but - * its value will never be used. - */ - } while (--n); - - more += _w_size; - } - if (s.strm.avail_in === 0) { - break; - } - - /* If there was no sliding: - * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && - * more == window_size - lookahead - strstart - * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) - * => more >= window_size - 2*WSIZE + 2 - * In the BIG_MEM or MMAP case (not yet supported), - * window_size == input_size + MIN_LOOKAHEAD && - * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. - * Otherwise, window_size == 2*WSIZE so more >= 2. - * If there was sliding, more >= WSIZE. So in all cases, more >= 2. - */ - //Assert(more >= 2, "more < 2"); - n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more); - s.lookahead += n; - - /* Initialize the hash value now that we have some input: */ - if (s.lookahead + s.insert >= MIN_MATCH) { - str = s.strstart - s.insert; - s.ins_h = s.window[str]; - - /* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + 1]) & s.hash_mask; -//#if MIN_MATCH != 3 -// Call update_hash() MIN_MATCH-3 more times -//#endif - while (s.insert) { - /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH - 1]) & s.hash_mask; - - s.prev[str & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = str; - str++; - s.insert--; - if (s.lookahead + s.insert < MIN_MATCH) { - break; - } - } - } - /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, - * but this is not important since only literal bytes will be emitted. - */ - - } while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0); - - /* If the WIN_INIT bytes after the end of the current data have never been - * written, then zero those bytes in order to avoid memory check reports of - * the use of uninitialized (or uninitialised as Julian writes) bytes by - * the longest match routines. Update the high water mark for the next - * time through here. WIN_INIT is set to MAX_MATCH since the longest match - * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. - */ -// if (s.high_water < s.window_size) { -// var curr = s.strstart + s.lookahead; -// var init = 0; -// -// if (s.high_water < curr) { -// /* Previous high water mark below current data -- zero WIN_INIT -// * bytes or up to end of window, whichever is less. -// */ -// init = s.window_size - curr; -// if (init > WIN_INIT) -// init = WIN_INIT; -// zmemzero(s->window + curr, (unsigned)init); -// s->high_water = curr + init; -// } -// else if (s->high_water < (ulg)curr + WIN_INIT) { -// /* High water mark at or above current data, but below current data -// * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up -// * to end of window, whichever is less. -// */ -// init = (ulg)curr + WIN_INIT - s->high_water; -// if (init > s->window_size - s->high_water) -// init = s->window_size - s->high_water; -// zmemzero(s->window + s->high_water, (unsigned)init); -// s->high_water += init; -// } -// } -// -// Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, -// "not enough room for search"); -} - -/* =========================================================================== - * Copy without compression as much as possible from the input stream, return - * the current block state. - * This function does not insert new strings in the dictionary since - * uncompressible data is probably not useful. This function is used - * only for the level=0 compression option. - * NOTE: this function should be optimized to avoid extra copying from - * window to pending_buf. - */ -function deflate_stored(s, flush) { - /* Stored blocks are limited to 0xffff bytes, pending_buf is limited - * to pending_buf_size, and each stored block has a 5 byte header: - */ - var max_block_size = 0xffff; - - if (max_block_size > s.pending_buf_size - 5) { - max_block_size = s.pending_buf_size - 5; - } - - /* Copy as much as possible from input to output: */ - for (;;) { - /* Fill the window as much as possible: */ - if (s.lookahead <= 1) { - - //Assert(s->strstart < s->w_size+MAX_DIST(s) || - // s->block_start >= (long)s->w_size, "slide too late"); -// if (!(s.strstart < s.w_size + (s.w_size - MIN_LOOKAHEAD) || -// s.block_start >= s.w_size)) { -// throw new Error("slide too late"); -// } - - fill_window(s); - if (s.lookahead === 0 && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - - if (s.lookahead === 0) { - break; - } - /* flush the current block */ - } - //Assert(s->block_start >= 0L, "block gone"); -// if (s.block_start < 0) throw new Error("block gone"); - - s.strstart += s.lookahead; - s.lookahead = 0; - - /* Emit a stored block if pending_buf will be full: */ - var max_start = s.block_start + max_block_size; - - if (s.strstart === 0 || s.strstart >= max_start) { - /* strstart == 0 is possible when wraparound on 16-bit machine */ - s.lookahead = s.strstart - max_start; - s.strstart = max_start; - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - - - } - /* Flush if we may have to slide, otherwise block_start may become - * negative and the data will be gone: - */ - if (s.strstart - s.block_start >= (s.w_size - MIN_LOOKAHEAD)) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } - - s.insert = 0; - - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - - if (s.strstart > s.block_start) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - - return BS_NEED_MORE; -} - -/* =========================================================================== - * Compress as much as possible from the input stream, return the current - * block state. - * This function does not perform lazy evaluation of matches and inserts - * new strings in the dictionary only for unmatched strings or for short - * matches. It is used only for the fast compression options. - */ -function deflate_fast(s, flush) { - var hash_head; /* head of the hash chain */ - var bflush; /* set if current block must be flushed */ - - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s.lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - if (s.lookahead === 0) { - break; /* flush the current block */ - } - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - hash_head = 0/*NIL*/; - if (s.lookahead >= MIN_MATCH) { - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - } - - /* Find the longest match, discarding those <= prev_length. - * At this point we have always match_length < MIN_MATCH - */ - if (hash_head !== 0/*NIL*/ && ((s.strstart - hash_head) <= (s.w_size - MIN_LOOKAHEAD))) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - s.match_length = longest_match(s, hash_head); - /* longest_match() sets match_start */ - } - if (s.match_length >= MIN_MATCH) { - // check_match(s, s.strstart, s.match_start, s.match_length); // for debug only - - /*** _tr_tally_dist(s, s.strstart - s.match_start, - s.match_length - MIN_MATCH, bflush); ***/ - bflush = trees._tr_tally(s, s.strstart - s.match_start, s.match_length - MIN_MATCH); - - s.lookahead -= s.match_length; - - /* Insert new strings in the hash table only if the match length - * is not too large. This saves time but degrades compression. - */ - if (s.match_length <= s.max_lazy_match/*max_insert_length*/ && s.lookahead >= MIN_MATCH) { - s.match_length--; /* string at strstart already in table */ - do { - s.strstart++; - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - /* strstart never exceeds WSIZE-MAX_MATCH, so there are - * always MIN_MATCH bytes ahead. - */ - } while (--s.match_length !== 0); - s.strstart++; - } else - { - s.strstart += s.match_length; - s.match_length = 0; - s.ins_h = s.window[s.strstart]; - /* UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]); */ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + 1]) & s.hash_mask; - -//#if MIN_MATCH != 3 -// Call UPDATE_HASH() MIN_MATCH-3 more times -//#endif - /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not - * matter since it will be recomputed at next deflate call. - */ - } - } else { - /* No match, output a literal byte */ - //Tracevv((stderr,"%c", s.window[s.strstart])); - /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ - bflush = trees._tr_tally(s, 0, s.window[s.strstart]); - - s.lookahead--; - s.strstart++; - } - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } - s.insert = ((s.strstart < (MIN_MATCH - 1)) ? s.strstart : MIN_MATCH - 1); - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - return BS_BLOCK_DONE; -} - -/* =========================================================================== - * Same as above, but achieves better compression. We use a lazy - * evaluation for matches: a match is finally adopted only if there is - * no better match at the next window position. - */ -function deflate_slow(s, flush) { - var hash_head; /* head of hash chain */ - var bflush; /* set if current block must be flushed */ - - var max_insert; - - /* Process the input block. */ - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s.lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - if (s.lookahead === 0) { break; } /* flush the current block */ - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - hash_head = 0/*NIL*/; - if (s.lookahead >= MIN_MATCH) { - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - } - - /* Find the longest match, discarding those <= prev_length. - */ - s.prev_length = s.match_length; - s.prev_match = s.match_start; - s.match_length = MIN_MATCH - 1; - - if (hash_head !== 0/*NIL*/ && s.prev_length < s.max_lazy_match && - s.strstart - hash_head <= (s.w_size - MIN_LOOKAHEAD)/*MAX_DIST(s)*/) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - s.match_length = longest_match(s, hash_head); - /* longest_match() sets match_start */ - - if (s.match_length <= 5 && - (s.strategy === Z_FILTERED || (s.match_length === MIN_MATCH && s.strstart - s.match_start > 4096/*TOO_FAR*/))) { - - /* If prev_match is also MIN_MATCH, match_start is garbage - * but we will ignore the current match anyway. - */ - s.match_length = MIN_MATCH - 1; - } - } - /* If there was a match at the previous step and the current - * match is not better, output the previous match: - */ - if (s.prev_length >= MIN_MATCH && s.match_length <= s.prev_length) { - max_insert = s.strstart + s.lookahead - MIN_MATCH; - /* Do not insert strings in hash table beyond this. */ - - //check_match(s, s.strstart-1, s.prev_match, s.prev_length); - - /***_tr_tally_dist(s, s.strstart - 1 - s.prev_match, - s.prev_length - MIN_MATCH, bflush);***/ - bflush = trees._tr_tally(s, s.strstart - 1 - s.prev_match, s.prev_length - MIN_MATCH); - /* Insert in hash table all strings up to the end of the match. - * strstart-1 and strstart are already inserted. If there is not - * enough lookahead, the last two strings are not inserted in - * the hash table. - */ - s.lookahead -= s.prev_length - 1; - s.prev_length -= 2; - do { - if (++s.strstart <= max_insert) { - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - } - } while (--s.prev_length !== 0); - s.match_available = 0; - s.match_length = MIN_MATCH - 1; - s.strstart++; - - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - - } else if (s.match_available) { - /* If there was no match at the previous position, output a - * single literal. If there was a match but the current match - * is longer, truncate the previous match to a single literal. - */ - //Tracevv((stderr,"%c", s->window[s->strstart-1])); - /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ - bflush = trees._tr_tally(s, 0, s.window[s.strstart - 1]); - - if (bflush) { - /*** FLUSH_BLOCK_ONLY(s, 0) ***/ - flush_block_only(s, false); - /***/ - } - s.strstart++; - s.lookahead--; - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - } else { - /* There is no previous match to compare with, wait for - * the next step to decide. - */ - s.match_available = 1; - s.strstart++; - s.lookahead--; - } - } - //Assert (flush != Z_NO_FLUSH, "no flush?"); - if (s.match_available) { - //Tracevv((stderr,"%c", s->window[s->strstart-1])); - /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ - bflush = trees._tr_tally(s, 0, s.window[s.strstart - 1]); - - s.match_available = 0; - } - s.insert = s.strstart < MIN_MATCH - 1 ? s.strstart : MIN_MATCH - 1; - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - - return BS_BLOCK_DONE; -} - - -/* =========================================================================== - * For Z_RLE, simply look for runs of bytes, generate matches only of distance - * one. Do not maintain a hash table. (It will be regenerated if this run of - * deflate switches away from Z_RLE.) - */ -function deflate_rle(s, flush) { - var bflush; /* set if current block must be flushed */ - var prev; /* byte at distance one to match */ - var scan, strend; /* scan goes up to strend for length of run */ - - var _win = s.window; - - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the longest run, plus one for the unrolled loop. - */ - if (s.lookahead <= MAX_MATCH) { - fill_window(s); - if (s.lookahead <= MAX_MATCH && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - if (s.lookahead === 0) { break; } /* flush the current block */ - } - - /* See how many times the previous byte repeats */ - s.match_length = 0; - if (s.lookahead >= MIN_MATCH && s.strstart > 0) { - scan = s.strstart - 1; - prev = _win[scan]; - if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) { - strend = s.strstart + MAX_MATCH; - do { - /*jshint noempty:false*/ - } while (prev === _win[++scan] && prev === _win[++scan] && - prev === _win[++scan] && prev === _win[++scan] && - prev === _win[++scan] && prev === _win[++scan] && - prev === _win[++scan] && prev === _win[++scan] && - scan < strend); - s.match_length = MAX_MATCH - (strend - scan); - if (s.match_length > s.lookahead) { - s.match_length = s.lookahead; - } - } - //Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); - } - - /* Emit match if have run of MIN_MATCH or longer, else emit literal */ - if (s.match_length >= MIN_MATCH) { - //check_match(s, s.strstart, s.strstart - 1, s.match_length); - - /*** _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ***/ - bflush = trees._tr_tally(s, 1, s.match_length - MIN_MATCH); - - s.lookahead -= s.match_length; - s.strstart += s.match_length; - s.match_length = 0; - } else { - /* No match, output a literal byte */ - //Tracevv((stderr,"%c", s->window[s->strstart])); - /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ - bflush = trees._tr_tally(s, 0, s.window[s.strstart]); - - s.lookahead--; - s.strstart++; - } - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } - s.insert = 0; - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - return BS_BLOCK_DONE; -} - -/* =========================================================================== - * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. - * (It will be regenerated if this run of deflate switches away from Huffman.) - */ -function deflate_huff(s, flush) { - var bflush; /* set if current block must be flushed */ - - for (;;) { - /* Make sure that we have a literal to write. */ - if (s.lookahead === 0) { - fill_window(s); - if (s.lookahead === 0) { - if (flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - break; /* flush the current block */ - } - } - - /* Output a literal byte */ - s.match_length = 0; - //Tracevv((stderr,"%c", s->window[s->strstart])); - /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ - bflush = trees._tr_tally(s, 0, s.window[s.strstart]); - s.lookahead--; - s.strstart++; - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } - s.insert = 0; - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - return BS_BLOCK_DONE; -} - -/* Values for max_lazy_match, good_match and max_chain_length, depending on - * the desired pack level (0..9). The values given below have been tuned to - * exclude worst case performance for pathological files. Better values may be - * found for specific files. - */ -function Config(good_length, max_lazy, nice_length, max_chain, func) { - this.good_length = good_length; - this.max_lazy = max_lazy; - this.nice_length = nice_length; - this.max_chain = max_chain; - this.func = func; -} - -var configuration_table; - -configuration_table = [ - /* good lazy nice chain */ - new Config(0, 0, 0, 0, deflate_stored), /* 0 store only */ - new Config(4, 4, 8, 4, deflate_fast), /* 1 max speed, no lazy matches */ - new Config(4, 5, 16, 8, deflate_fast), /* 2 */ - new Config(4, 6, 32, 32, deflate_fast), /* 3 */ - - new Config(4, 4, 16, 16, deflate_slow), /* 4 lazy matches */ - new Config(8, 16, 32, 32, deflate_slow), /* 5 */ - new Config(8, 16, 128, 128, deflate_slow), /* 6 */ - new Config(8, 32, 128, 256, deflate_slow), /* 7 */ - new Config(32, 128, 258, 1024, deflate_slow), /* 8 */ - new Config(32, 258, 258, 4096, deflate_slow) /* 9 max compression */ -]; - - -/* =========================================================================== - * Initialize the "longest match" routines for a new zlib stream - */ -function lm_init(s) { - s.window_size = 2 * s.w_size; - - /*** CLEAR_HASH(s); ***/ - zero(s.head); // Fill with NIL (= 0); - - /* Set the default configuration parameters: - */ - s.max_lazy_match = configuration_table[s.level].max_lazy; - s.good_match = configuration_table[s.level].good_length; - s.nice_match = configuration_table[s.level].nice_length; - s.max_chain_length = configuration_table[s.level].max_chain; - - s.strstart = 0; - s.block_start = 0; - s.lookahead = 0; - s.insert = 0; - s.match_length = s.prev_length = MIN_MATCH - 1; - s.match_available = 0; - s.ins_h = 0; -} - - -function DeflateState() { - this.strm = null; /* pointer back to this zlib stream */ - this.status = 0; /* as the name implies */ - this.pending_buf = null; /* output still pending */ - this.pending_buf_size = 0; /* size of pending_buf */ - this.pending_out = 0; /* next pending byte to output to the stream */ - this.pending = 0; /* nb of bytes in the pending buffer */ - this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ - this.gzhead = null; /* gzip header information to write */ - this.gzindex = 0; /* where in extra, name, or comment */ - this.method = Z_DEFLATED; /* can only be DEFLATED */ - this.last_flush = -1; /* value of flush param for previous deflate call */ - - this.w_size = 0; /* LZ77 window size (32K by default) */ - this.w_bits = 0; /* log2(w_size) (8..16) */ - this.w_mask = 0; /* w_size - 1 */ - - this.window = null; - /* Sliding window. Input bytes are read into the second half of the window, - * and move to the first half later to keep a dictionary of at least wSize - * bytes. With this organization, matches are limited to a distance of - * wSize-MAX_MATCH bytes, but this ensures that IO is always - * performed with a length multiple of the block size. - */ - - this.window_size = 0; - /* Actual size of window: 2*wSize, except when the user input buffer - * is directly used as sliding window. - */ - - this.prev = null; - /* Link to older string with same hash index. To limit the size of this - * array to 64K, this link is maintained only for the last 32K strings. - * An index in this array is thus a window index modulo 32K. - */ - - this.head = null; /* Heads of the hash chains or NIL. */ - - this.ins_h = 0; /* hash index of string to be inserted */ - this.hash_size = 0; /* number of elements in hash table */ - this.hash_bits = 0; /* log2(hash_size) */ - this.hash_mask = 0; /* hash_size-1 */ - - this.hash_shift = 0; - /* Number of bits by which ins_h must be shifted at each input - * step. It must be such that after MIN_MATCH steps, the oldest - * byte no longer takes part in the hash key, that is: - * hash_shift * MIN_MATCH >= hash_bits - */ - - this.block_start = 0; - /* Window position at the beginning of the current output block. Gets - * negative when the window is moved backwards. - */ - - this.match_length = 0; /* length of best match */ - this.prev_match = 0; /* previous match */ - this.match_available = 0; /* set if previous match exists */ - this.strstart = 0; /* start of string to insert */ - this.match_start = 0; /* start of matching string */ - this.lookahead = 0; /* number of valid bytes ahead in window */ - - this.prev_length = 0; - /* Length of the best match at previous step. Matches not greater than this - * are discarded. This is used in the lazy match evaluation. - */ - - this.max_chain_length = 0; - /* To speed up deflation, hash chains are never searched beyond this - * length. A higher limit improves compression ratio but degrades the - * speed. - */ - - this.max_lazy_match = 0; - /* Attempt to find a better match only when the current match is strictly - * smaller than this value. This mechanism is used only for compression - * levels >= 4. - */ - // That's alias to max_lazy_match, don't use directly - //this.max_insert_length = 0; - /* Insert new strings in the hash table only if the match length is not - * greater than this length. This saves time but degrades compression. - * max_insert_length is used only for compression levels <= 3. - */ - - this.level = 0; /* compression level (1..9) */ - this.strategy = 0; /* favor or force Huffman coding*/ - - this.good_match = 0; - /* Use a faster search when the previous match is longer than this */ - - this.nice_match = 0; /* Stop searching when current match exceeds this */ - - /* used by trees.c: */ - - /* Didn't use ct_data typedef below to suppress compiler warning */ - - // struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ - // struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ - // struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ - - // Use flat array of DOUBLE size, with interleaved fata, - // because JS does not support effective - this.dyn_ltree = new utils.Buf16(HEAP_SIZE * 2); - this.dyn_dtree = new utils.Buf16((2 * D_CODES + 1) * 2); - this.bl_tree = new utils.Buf16((2 * BL_CODES + 1) * 2); - zero(this.dyn_ltree); - zero(this.dyn_dtree); - zero(this.bl_tree); - - this.l_desc = null; /* desc. for literal tree */ - this.d_desc = null; /* desc. for distance tree */ - this.bl_desc = null; /* desc. for bit length tree */ - - //ush bl_count[MAX_BITS+1]; - this.bl_count = new utils.Buf16(MAX_BITS + 1); - /* number of codes at each bit length for an optimal tree */ - - //int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ - this.heap = new utils.Buf16(2 * L_CODES + 1); /* heap used to build the Huffman trees */ - zero(this.heap); - - this.heap_len = 0; /* number of elements in the heap */ - this.heap_max = 0; /* element of largest frequency */ - /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. - * The same heap array is used to build all trees. - */ - - this.depth = new utils.Buf16(2 * L_CODES + 1); //uch depth[2*L_CODES+1]; - zero(this.depth); - /* Depth of each subtree used as tie breaker for trees of equal frequency - */ - - this.l_buf = 0; /* buffer index for literals or lengths */ - - this.lit_bufsize = 0; - /* Size of match buffer for literals/lengths. There are 4 reasons for - * limiting lit_bufsize to 64K: - * - frequencies can be kept in 16 bit counters - * - if compression is not successful for the first block, all input - * data is still in the window so we can still emit a stored block even - * when input comes from standard input. (This can also be done for - * all blocks if lit_bufsize is not greater than 32K.) - * - if compression is not successful for a file smaller than 64K, we can - * even emit a stored file instead of a stored block (saving 5 bytes). - * This is applicable only for zip (not gzip or zlib). - * - creating new Huffman trees less frequently may not provide fast - * adaptation to changes in the input data statistics. (Take for - * example a binary file with poorly compressible code followed by - * a highly compressible string table.) Smaller buffer sizes give - * fast adaptation but have of course the overhead of transmitting - * trees more frequently. - * - I can't count above 4 - */ - - this.last_lit = 0; /* running index in l_buf */ - - this.d_buf = 0; - /* Buffer index for distances. To simplify the code, d_buf and l_buf have - * the same number of elements. To use different lengths, an extra flag - * array would be necessary. - */ - - this.opt_len = 0; /* bit length of current block with optimal trees */ - this.static_len = 0; /* bit length of current block with static trees */ - this.matches = 0; /* number of string matches in current block */ - this.insert = 0; /* bytes at end of window left to insert */ - - - this.bi_buf = 0; - /* Output buffer. bits are inserted starting at the bottom (least - * significant bits). - */ - this.bi_valid = 0; - /* Number of valid bits in bi_buf. All bits above the last valid bit - * are always zero. - */ - - // Used for window memory init. We safely ignore it for JS. That makes - // sense only for pointers and memory check tools. - //this.high_water = 0; - /* High water mark offset in window for initialized bytes -- bytes above - * this are set to zero in order to avoid memory check warnings when - * longest match routines access bytes past the input. This is then - * updated to the new high water mark. - */ -} - - -function deflateResetKeep(strm) { - var s; - - if (!strm || !strm.state) { - return err(strm, Z_STREAM_ERROR); - } - - strm.total_in = strm.total_out = 0; - strm.data_type = Z_UNKNOWN; - - s = strm.state; - s.pending = 0; - s.pending_out = 0; - - if (s.wrap < 0) { - s.wrap = -s.wrap; - /* was made negative by deflate(..., Z_FINISH); */ - } - s.status = (s.wrap ? INIT_STATE : BUSY_STATE); - strm.adler = (s.wrap === 2) ? - 0 // crc32(0, Z_NULL, 0) - : - 1; // adler32(0, Z_NULL, 0) - s.last_flush = Z_NO_FLUSH; - trees._tr_init(s); - return Z_OK; -} - - -function deflateReset(strm) { - var ret = deflateResetKeep(strm); - if (ret === Z_OK) { - lm_init(strm.state); - } - return ret; -} - - -function deflateSetHeader(strm, head) { - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - if (strm.state.wrap !== 2) { return Z_STREAM_ERROR; } - strm.state.gzhead = head; - return Z_OK; -} - - -function deflateInit2(strm, level, method, windowBits, memLevel, strategy) { - if (!strm) { // === Z_NULL - return Z_STREAM_ERROR; - } - var wrap = 1; - - if (level === Z_DEFAULT_COMPRESSION) { - level = 6; - } - - if (windowBits < 0) { /* suppress zlib wrapper */ - wrap = 0; - windowBits = -windowBits; - } - - else if (windowBits > 15) { - wrap = 2; /* write gzip wrapper instead */ - windowBits -= 16; - } - - - if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method !== Z_DEFLATED || - windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || - strategy < 0 || strategy > Z_FIXED) { - return err(strm, Z_STREAM_ERROR); - } - - - if (windowBits === 8) { - windowBits = 9; - } - /* until 256-byte window bug fixed */ - - var s = new DeflateState(); - - strm.state = s; - s.strm = strm; - - s.wrap = wrap; - s.gzhead = null; - s.w_bits = windowBits; - s.w_size = 1 << s.w_bits; - s.w_mask = s.w_size - 1; - - s.hash_bits = memLevel + 7; - s.hash_size = 1 << s.hash_bits; - s.hash_mask = s.hash_size - 1; - s.hash_shift = ~~((s.hash_bits + MIN_MATCH - 1) / MIN_MATCH); - - s.window = new utils.Buf8(s.w_size * 2); - s.head = new utils.Buf16(s.hash_size); - s.prev = new utils.Buf16(s.w_size); - - // Don't need mem init magic for JS. - //s.high_water = 0; /* nothing written to s->window yet */ - - s.lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ - - s.pending_buf_size = s.lit_bufsize * 4; - - //overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); - //s->pending_buf = (uchf *) overlay; - s.pending_buf = new utils.Buf8(s.pending_buf_size); - - // It is offset from `s.pending_buf` (size is `s.lit_bufsize * 2`) - //s->d_buf = overlay + s->lit_bufsize/sizeof(ush); - s.d_buf = 1 * s.lit_bufsize; - - //s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; - s.l_buf = (1 + 2) * s.lit_bufsize; - - s.level = level; - s.strategy = strategy; - s.method = method; - - return deflateReset(strm); -} - -function deflateInit(strm, level) { - return deflateInit2(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); -} - - -function deflate(strm, flush) { - var old_flush, s; - var beg, val; // for gzip header write only - - if (!strm || !strm.state || - flush > Z_BLOCK || flush < 0) { - return strm ? err(strm, Z_STREAM_ERROR) : Z_STREAM_ERROR; - } - - s = strm.state; - - if (!strm.output || - (!strm.input && strm.avail_in !== 0) || - (s.status === FINISH_STATE && flush !== Z_FINISH)) { - return err(strm, (strm.avail_out === 0) ? Z_BUF_ERROR : Z_STREAM_ERROR); - } - - s.strm = strm; /* just in case */ - old_flush = s.last_flush; - s.last_flush = flush; - - /* Write the header */ - if (s.status === INIT_STATE) { - - if (s.wrap === 2) { // GZIP header - strm.adler = 0; //crc32(0L, Z_NULL, 0); - put_byte(s, 31); - put_byte(s, 139); - put_byte(s, 8); - if (!s.gzhead) { // s->gzhead == Z_NULL - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, s.level === 9 ? 2 : - (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? - 4 : 0)); - put_byte(s, OS_CODE); - s.status = BUSY_STATE; - } - else { - put_byte(s, (s.gzhead.text ? 1 : 0) + - (s.gzhead.hcrc ? 2 : 0) + - (!s.gzhead.extra ? 0 : 4) + - (!s.gzhead.name ? 0 : 8) + - (!s.gzhead.comment ? 0 : 16) - ); - put_byte(s, s.gzhead.time & 0xff); - put_byte(s, (s.gzhead.time >> 8) & 0xff); - put_byte(s, (s.gzhead.time >> 16) & 0xff); - put_byte(s, (s.gzhead.time >> 24) & 0xff); - put_byte(s, s.level === 9 ? 2 : - (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? - 4 : 0)); - put_byte(s, s.gzhead.os & 0xff); - if (s.gzhead.extra && s.gzhead.extra.length) { - put_byte(s, s.gzhead.extra.length & 0xff); - put_byte(s, (s.gzhead.extra.length >> 8) & 0xff); - } - if (s.gzhead.hcrc) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending, 0); - } - s.gzindex = 0; - s.status = EXTRA_STATE; - } - } - else // DEFLATE header - { - var header = (Z_DEFLATED + ((s.w_bits - 8) << 4)) << 8; - var level_flags = -1; - - if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) { - level_flags = 0; - } else if (s.level < 6) { - level_flags = 1; - } else if (s.level === 6) { - level_flags = 2; - } else { - level_flags = 3; - } - header |= (level_flags << 6); - if (s.strstart !== 0) { header |= PRESET_DICT; } - header += 31 - (header % 31); - - s.status = BUSY_STATE; - putShortMSB(s, header); - - /* Save the adler32 of the preset dictionary: */ - if (s.strstart !== 0) { - putShortMSB(s, strm.adler >>> 16); - putShortMSB(s, strm.adler & 0xffff); - } - strm.adler = 1; // adler32(0L, Z_NULL, 0); - } - } - -//#ifdef GZIP - if (s.status === EXTRA_STATE) { - if (s.gzhead.extra/* != Z_NULL*/) { - beg = s.pending; /* start of bytes to update crc */ - - while (s.gzindex < (s.gzhead.extra.length & 0xffff)) { - if (s.pending === s.pending_buf_size) { - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - flush_pending(strm); - beg = s.pending; - if (s.pending === s.pending_buf_size) { - break; - } - } - put_byte(s, s.gzhead.extra[s.gzindex] & 0xff); - s.gzindex++; - } - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - if (s.gzindex === s.gzhead.extra.length) { - s.gzindex = 0; - s.status = NAME_STATE; - } - } - else { - s.status = NAME_STATE; - } - } - if (s.status === NAME_STATE) { - if (s.gzhead.name/* != Z_NULL*/) { - beg = s.pending; /* start of bytes to update crc */ - //int val; - - do { - if (s.pending === s.pending_buf_size) { - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - flush_pending(strm); - beg = s.pending; - if (s.pending === s.pending_buf_size) { - val = 1; - break; - } - } - // JS specific: little magic to add zero terminator to end of string - if (s.gzindex < s.gzhead.name.length) { - val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff; - } else { - val = 0; - } - put_byte(s, val); - } while (val !== 0); - - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - if (val === 0) { - s.gzindex = 0; - s.status = COMMENT_STATE; - } - } - else { - s.status = COMMENT_STATE; - } - } - if (s.status === COMMENT_STATE) { - if (s.gzhead.comment/* != Z_NULL*/) { - beg = s.pending; /* start of bytes to update crc */ - //int val; - - do { - if (s.pending === s.pending_buf_size) { - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - flush_pending(strm); - beg = s.pending; - if (s.pending === s.pending_buf_size) { - val = 1; - break; - } - } - // JS specific: little magic to add zero terminator to end of string - if (s.gzindex < s.gzhead.comment.length) { - val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff; - } else { - val = 0; - } - put_byte(s, val); - } while (val !== 0); - - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - if (val === 0) { - s.status = HCRC_STATE; - } - } - else { - s.status = HCRC_STATE; - } - } - if (s.status === HCRC_STATE) { - if (s.gzhead.hcrc) { - if (s.pending + 2 > s.pending_buf_size) { - flush_pending(strm); - } - if (s.pending + 2 <= s.pending_buf_size) { - put_byte(s, strm.adler & 0xff); - put_byte(s, (strm.adler >> 8) & 0xff); - strm.adler = 0; //crc32(0L, Z_NULL, 0); - s.status = BUSY_STATE; - } - } - else { - s.status = BUSY_STATE; - } - } -//#endif - - /* Flush as much pending output as possible */ - if (s.pending !== 0) { - flush_pending(strm); - if (strm.avail_out === 0) { - /* Since avail_out is 0, deflate will be called again with - * more output space, but possibly with both pending and - * avail_in equal to zero. There won't be anything to do, - * but this is not an error situation so make sure we - * return OK instead of BUF_ERROR at next call of deflate: - */ - s.last_flush = -1; - return Z_OK; - } - - /* Make sure there is something to do and avoid duplicate consecutive - * flushes. For repeated and useless calls with Z_FINISH, we keep - * returning Z_STREAM_END instead of Z_BUF_ERROR. - */ - } else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) && - flush !== Z_FINISH) { - return err(strm, Z_BUF_ERROR); - } - - /* User must not provide more input after the first FINISH: */ - if (s.status === FINISH_STATE && strm.avail_in !== 0) { - return err(strm, Z_BUF_ERROR); - } - - /* Start a new block or continue the current one. - */ - if (strm.avail_in !== 0 || s.lookahead !== 0 || - (flush !== Z_NO_FLUSH && s.status !== FINISH_STATE)) { - var bstate = (s.strategy === Z_HUFFMAN_ONLY) ? deflate_huff(s, flush) : - (s.strategy === Z_RLE ? deflate_rle(s, flush) : - configuration_table[s.level].func(s, flush)); - - if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) { - s.status = FINISH_STATE; - } - if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) { - if (strm.avail_out === 0) { - s.last_flush = -1; - /* avoid BUF_ERROR next call, see above */ - } - return Z_OK; - /* If flush != Z_NO_FLUSH && avail_out == 0, the next call - * of deflate should use the same flush parameter to make sure - * that the flush is complete. So we don't have to output an - * empty block here, this will be done at next call. This also - * ensures that for a very small output buffer, we emit at most - * one empty block. - */ - } - if (bstate === BS_BLOCK_DONE) { - if (flush === Z_PARTIAL_FLUSH) { - trees._tr_align(s); - } - else if (flush !== Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ - - trees._tr_stored_block(s, 0, 0, false); - /* For a full flush, this empty block will be recognized - * as a special marker by inflate_sync(). - */ - if (flush === Z_FULL_FLUSH) { - /*** CLEAR_HASH(s); ***/ /* forget history */ - zero(s.head); // Fill with NIL (= 0); - - if (s.lookahead === 0) { - s.strstart = 0; - s.block_start = 0; - s.insert = 0; - } - } - } - flush_pending(strm); - if (strm.avail_out === 0) { - s.last_flush = -1; /* avoid BUF_ERROR at next call, see above */ - return Z_OK; - } - } - } - //Assert(strm->avail_out > 0, "bug2"); - //if (strm.avail_out <= 0) { throw new Error("bug2");} - - if (flush !== Z_FINISH) { return Z_OK; } - if (s.wrap <= 0) { return Z_STREAM_END; } - - /* Write the trailer */ - if (s.wrap === 2) { - put_byte(s, strm.adler & 0xff); - put_byte(s, (strm.adler >> 8) & 0xff); - put_byte(s, (strm.adler >> 16) & 0xff); - put_byte(s, (strm.adler >> 24) & 0xff); - put_byte(s, strm.total_in & 0xff); - put_byte(s, (strm.total_in >> 8) & 0xff); - put_byte(s, (strm.total_in >> 16) & 0xff); - put_byte(s, (strm.total_in >> 24) & 0xff); - } - else - { - putShortMSB(s, strm.adler >>> 16); - putShortMSB(s, strm.adler & 0xffff); - } - - flush_pending(strm); - /* If avail_out is zero, the application will call deflate again - * to flush the rest. - */ - if (s.wrap > 0) { s.wrap = -s.wrap; } - /* write the trailer only once! */ - return s.pending !== 0 ? Z_OK : Z_STREAM_END; -} - -function deflateEnd(strm) { - var status; - - if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) { - return Z_STREAM_ERROR; - } - - status = strm.state.status; - if (status !== INIT_STATE && - status !== EXTRA_STATE && - status !== NAME_STATE && - status !== COMMENT_STATE && - status !== HCRC_STATE && - status !== BUSY_STATE && - status !== FINISH_STATE - ) { - return err(strm, Z_STREAM_ERROR); - } - - strm.state = null; - - return status === BUSY_STATE ? err(strm, Z_DATA_ERROR) : Z_OK; -} - - -/* ========================================================================= - * Initializes the compression dictionary from the given byte - * sequence without producing any compressed output. - */ -function deflateSetDictionary(strm, dictionary) { - var dictLength = dictionary.length; - - var s; - var str, n; - var wrap; - var avail; - var next; - var input; - var tmpDict; - - if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) { - return Z_STREAM_ERROR; - } - - s = strm.state; - wrap = s.wrap; - - if (wrap === 2 || (wrap === 1 && s.status !== INIT_STATE) || s.lookahead) { - return Z_STREAM_ERROR; - } - - /* when using zlib wrappers, compute Adler-32 for provided dictionary */ - if (wrap === 1) { - /* adler32(strm->adler, dictionary, dictLength); */ - strm.adler = adler32(strm.adler, dictionary, dictLength, 0); - } - - s.wrap = 0; /* avoid computing Adler-32 in read_buf */ - - /* if dictionary would fill window, just replace the history */ - if (dictLength >= s.w_size) { - if (wrap === 0) { /* already empty otherwise */ - /*** CLEAR_HASH(s); ***/ - zero(s.head); // Fill with NIL (= 0); - s.strstart = 0; - s.block_start = 0; - s.insert = 0; - } - /* use the tail */ - // dictionary = dictionary.slice(dictLength - s.w_size); - tmpDict = new utils.Buf8(s.w_size); - utils.arraySet(tmpDict, dictionary, dictLength - s.w_size, s.w_size, 0); - dictionary = tmpDict; - dictLength = s.w_size; - } - /* insert dictionary into window and hash */ - avail = strm.avail_in; - next = strm.next_in; - input = strm.input; - strm.avail_in = dictLength; - strm.next_in = 0; - strm.input = dictionary; - fill_window(s); - while (s.lookahead >= MIN_MATCH) { - str = s.strstart; - n = s.lookahead - (MIN_MATCH - 1); - do { - /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH - 1]) & s.hash_mask; - - s.prev[str & s.w_mask] = s.head[s.ins_h]; - - s.head[s.ins_h] = str; - str++; - } while (--n); - s.strstart = str; - s.lookahead = MIN_MATCH - 1; - fill_window(s); - } - s.strstart += s.lookahead; - s.block_start = s.strstart; - s.insert = s.lookahead; - s.lookahead = 0; - s.match_length = s.prev_length = MIN_MATCH - 1; - s.match_available = 0; - strm.next_in = next; - strm.input = input; - strm.avail_in = avail; - s.wrap = wrap; - return Z_OK; -} - - -exports.deflateInit = deflateInit; -exports.deflateInit2 = deflateInit2; -exports.deflateReset = deflateReset; -exports.deflateResetKeep = deflateResetKeep; -exports.deflateSetHeader = deflateSetHeader; -exports.deflate = deflate; -exports.deflateEnd = deflateEnd; -exports.deflateSetDictionary = deflateSetDictionary; -exports.deflateInfo = 'pako deflate (from Nodeca project)'; - -/* Not implemented -exports.deflateBound = deflateBound; -exports.deflateCopy = deflateCopy; -exports.deflateParams = deflateParams; -exports.deflatePending = deflatePending; -exports.deflatePrime = deflatePrime; -exports.deflateTune = deflateTune; -*/ - -},{"../utils/common":53,"./adler32":55,"./crc32":57,"./messages":63,"./trees":64}],59:[function(require,module,exports){ -'use strict'; - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -function GZheader() { - /* true if compressed data believed to be text */ - this.text = 0; - /* modification time */ - this.time = 0; - /* extra flags (not used when writing a gzip file) */ - this.xflags = 0; - /* operating system */ - this.os = 0; - /* pointer to extra field or Z_NULL if none */ - this.extra = null; - /* extra field length (valid if extra != Z_NULL) */ - this.extra_len = 0; // Actually, we don't need it in JS, - // but leave for few code modifications - - // - // Setup limits is not necessary because in js we should not preallocate memory - // for inflate use constant limit in 65536 bytes - // - - /* space at extra (only when reading header) */ - // this.extra_max = 0; - /* pointer to zero-terminated file name or Z_NULL */ - this.name = ''; - /* space at name (only when reading header) */ - // this.name_max = 0; - /* pointer to zero-terminated comment or Z_NULL */ - this.comment = ''; - /* space at comment (only when reading header) */ - // this.comm_max = 0; - /* true if there was or will be a header crc */ - this.hcrc = 0; - /* true when done reading gzip header (not used when writing a gzip file) */ - this.done = false; -} - -module.exports = GZheader; - -},{}],60:[function(require,module,exports){ -'use strict'; - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -// See state defs from inflate.js -var BAD = 30; /* got a data error -- remain here until reset */ -var TYPE = 12; /* i: waiting for type bits, including last-flag bit */ - -/* - Decode literal, length, and distance codes and write out the resulting - literal and match bytes until either not enough input or output is - available, an end-of-block is encountered, or a data error is encountered. - When large enough input and output buffers are supplied to inflate(), for - example, a 16K input buffer and a 64K output buffer, more than 95% of the - inflate execution time is spent in this routine. - - Entry assumptions: - - state.mode === LEN - strm.avail_in >= 6 - strm.avail_out >= 258 - start >= strm.avail_out - state.bits < 8 - - On return, state.mode is one of: - - LEN -- ran out of enough output space or enough available input - TYPE -- reached end of block code, inflate() to interpret next block - BAD -- error in block data - - Notes: - - - The maximum input bits used by a length/distance pair is 15 bits for the - length code, 5 bits for the length extra, 15 bits for the distance code, - and 13 bits for the distance extra. This totals 48 bits, or six bytes. - Therefore if strm.avail_in >= 6, then there is enough input to avoid - checking for available input while decoding. - - - The maximum bytes that a single length/distance pair can output is 258 - bytes, which is the maximum length that can be coded. inflate_fast() - requires strm.avail_out >= 258 for each loop to avoid checking for - output space. - */ -module.exports = function inflate_fast(strm, start) { - var state; - var _in; /* local strm.input */ - var last; /* have enough input while in < last */ - var _out; /* local strm.output */ - var beg; /* inflate()'s initial strm.output */ - var end; /* while out < end, enough space available */ -//#ifdef INFLATE_STRICT - var dmax; /* maximum distance from zlib header */ -//#endif - var wsize; /* window size or zero if not using window */ - var whave; /* valid bytes in the window */ - var wnext; /* window write index */ - // Use `s_window` instead `window`, avoid conflict with instrumentation tools - var s_window; /* allocated sliding window, if wsize != 0 */ - var hold; /* local strm.hold */ - var bits; /* local strm.bits */ - var lcode; /* local strm.lencode */ - var dcode; /* local strm.distcode */ - var lmask; /* mask for first level of length codes */ - var dmask; /* mask for first level of distance codes */ - var here; /* retrieved table entry */ - var op; /* code bits, operation, extra bits, or */ - /* window position, window bytes to copy */ - var len; /* match length, unused bytes */ - var dist; /* match distance */ - var from; /* where to copy match from */ - var from_source; - - - var input, output; // JS specific, because we have no pointers - - /* copy state to local variables */ - state = strm.state; - //here = state.here; - _in = strm.next_in; - input = strm.input; - last = _in + (strm.avail_in - 5); - _out = strm.next_out; - output = strm.output; - beg = _out - (start - strm.avail_out); - end = _out + (strm.avail_out - 257); -//#ifdef INFLATE_STRICT - dmax = state.dmax; -//#endif - wsize = state.wsize; - whave = state.whave; - wnext = state.wnext; - s_window = state.window; - hold = state.hold; - bits = state.bits; - lcode = state.lencode; - dcode = state.distcode; - lmask = (1 << state.lenbits) - 1; - dmask = (1 << state.distbits) - 1; - - - /* decode literals and length/distances until end-of-block or not enough - input data or output space */ - - top: - do { - if (bits < 15) { - hold += input[_in++] << bits; - bits += 8; - hold += input[_in++] << bits; - bits += 8; - } - - here = lcode[hold & lmask]; - - dolen: - for (;;) { // Goto emulation - op = here >>> 24/*here.bits*/; - hold >>>= op; - bits -= op; - op = (here >>> 16) & 0xff/*here.op*/; - if (op === 0) { /* literal */ - //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - // "inflate: literal '%c'\n" : - // "inflate: literal 0x%02x\n", here.val)); - output[_out++] = here & 0xffff/*here.val*/; - } - else if (op & 16) { /* length base */ - len = here & 0xffff/*here.val*/; - op &= 15; /* number of extra bits */ - if (op) { - if (bits < op) { - hold += input[_in++] << bits; - bits += 8; - } - len += hold & ((1 << op) - 1); - hold >>>= op; - bits -= op; - } - //Tracevv((stderr, "inflate: length %u\n", len)); - if (bits < 15) { - hold += input[_in++] << bits; - bits += 8; - hold += input[_in++] << bits; - bits += 8; - } - here = dcode[hold & dmask]; - - dodist: - for (;;) { // goto emulation - op = here >>> 24/*here.bits*/; - hold >>>= op; - bits -= op; - op = (here >>> 16) & 0xff/*here.op*/; - - if (op & 16) { /* distance base */ - dist = here & 0xffff/*here.val*/; - op &= 15; /* number of extra bits */ - if (bits < op) { - hold += input[_in++] << bits; - bits += 8; - if (bits < op) { - hold += input[_in++] << bits; - bits += 8; - } - } - dist += hold & ((1 << op) - 1); -//#ifdef INFLATE_STRICT - if (dist > dmax) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD; - break top; - } -//#endif - hold >>>= op; - bits -= op; - //Tracevv((stderr, "inflate: distance %u\n", dist)); - op = _out - beg; /* max distance in output */ - if (dist > op) { /* see if copy from window */ - op = dist - op; /* distance back in window */ - if (op > whave) { - if (state.sane) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD; - break top; - } - -// (!) This block is disabled in zlib defaults, -// don't enable it for binary compatibility -//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR -// if (len <= op - whave) { -// do { -// output[_out++] = 0; -// } while (--len); -// continue top; -// } -// len -= op - whave; -// do { -// output[_out++] = 0; -// } while (--op > whave); -// if (op === 0) { -// from = _out - dist; -// do { -// output[_out++] = output[from++]; -// } while (--len); -// continue top; -// } -//#endif - } - from = 0; // window index - from_source = s_window; - if (wnext === 0) { /* very common case */ - from += wsize - op; - if (op < len) { /* some from window */ - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = _out - dist; /* rest from output */ - from_source = output; - } - } - else if (wnext < op) { /* wrap around window */ - from += wsize + wnext - op; - op -= wnext; - if (op < len) { /* some from end of window */ - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = 0; - if (wnext < len) { /* some from start of window */ - op = wnext; - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = _out - dist; /* rest from output */ - from_source = output; - } - } - } - else { /* contiguous in window */ - from += wnext - op; - if (op < len) { /* some from window */ - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = _out - dist; /* rest from output */ - from_source = output; - } - } - while (len > 2) { - output[_out++] = from_source[from++]; - output[_out++] = from_source[from++]; - output[_out++] = from_source[from++]; - len -= 3; - } - if (len) { - output[_out++] = from_source[from++]; - if (len > 1) { - output[_out++] = from_source[from++]; - } - } - } - else { - from = _out - dist; /* copy direct from output */ - do { /* minimum length is three */ - output[_out++] = output[from++]; - output[_out++] = output[from++]; - output[_out++] = output[from++]; - len -= 3; - } while (len > 2); - if (len) { - output[_out++] = output[from++]; - if (len > 1) { - output[_out++] = output[from++]; - } - } - } - } - else if ((op & 64) === 0) { /* 2nd level distance code */ - here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))]; - continue dodist; - } - else { - strm.msg = 'invalid distance code'; - state.mode = BAD; - break top; - } - - break; // need to emulate goto via "continue" - } - } - else if ((op & 64) === 0) { /* 2nd level length code */ - here = lcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))]; - continue dolen; - } - else if (op & 32) { /* end-of-block */ - //Tracevv((stderr, "inflate: end of block\n")); - state.mode = TYPE; - break top; - } - else { - strm.msg = 'invalid literal/length code'; - state.mode = BAD; - break top; - } - - break; // need to emulate goto via "continue" + for (i = 0; i < keyBytes.length; i += 4) { + inKey[i >> 2] = getW(keyBytes, i); + } + for (i = 0; i < 256; i++) { + q[0][i] = qp(0, i); + q[1][i] = qp(1, i); + } + for (i = 0; i < 256; i++) { + f01 = q[1][i]; + f5b = ffm5b(f01); + fef = ffmEf(f01); + m[0][i] = f01 + (f5b << 8) + (fef << 16) + (fef << 24); + m[2][i] = f5b + (fef << 8) + (f01 << 16) + (fef << 24); + f01 = q[0][i]; + f5b = ffm5b(f01); + fef = ffmEf(f01); + m[1][i] = fef + (fef << 8) + (f5b << 16) + (f01 << 24); + m[3][i] = f5b + (f01 << 8) + (fef << 16) + (f5b << 24); } - } while (_in < last && _out < end); - - /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ - len = bits >> 3; - _in -= len; - bits -= len << 3; - hold &= (1 << bits) - 1; - - /* update state and return */ - strm.next_in = _in; - strm.next_out = _out; - strm.avail_in = (_in < last ? 5 + (last - _in) : 5 - (_in - last)); - strm.avail_out = (_out < end ? 257 + (end - _out) : 257 - (_out - end)); - state.hold = hold; - state.bits = bits; - return; -}; - -},{}],61:[function(require,module,exports){ -'use strict'; - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -var utils = require('../utils/common'); -var adler32 = require('./adler32'); -var crc32 = require('./crc32'); -var inflate_fast = require('./inffast'); -var inflate_table = require('./inftrees'); - -var CODES = 0; -var LENS = 1; -var DISTS = 2; - -/* Public constants ==========================================================*/ -/* ===========================================================================*/ - - -/* Allowed flush values; see deflate() and inflate() below for details */ -//var Z_NO_FLUSH = 0; -//var Z_PARTIAL_FLUSH = 1; -//var Z_SYNC_FLUSH = 2; -//var Z_FULL_FLUSH = 3; -var Z_FINISH = 4; -var Z_BLOCK = 5; -var Z_TREES = 6; - - -/* Return codes for the compression/decompression functions. Negative values - * are errors, positive values are used for special but normal events. - */ -var Z_OK = 0; -var Z_STREAM_END = 1; -var Z_NEED_DICT = 2; -//var Z_ERRNO = -1; -var Z_STREAM_ERROR = -2; -var Z_DATA_ERROR = -3; -var Z_MEM_ERROR = -4; -var Z_BUF_ERROR = -5; -//var Z_VERSION_ERROR = -6; - -/* The deflate compression method */ -var Z_DEFLATED = 8; - - -/* STATES ====================================================================*/ -/* ===========================================================================*/ - - -var HEAD = 1; /* i: waiting for magic header */ -var FLAGS = 2; /* i: waiting for method and flags (gzip) */ -var TIME = 3; /* i: waiting for modification time (gzip) */ -var OS = 4; /* i: waiting for extra flags and operating system (gzip) */ -var EXLEN = 5; /* i: waiting for extra length (gzip) */ -var EXTRA = 6; /* i: waiting for extra bytes (gzip) */ -var NAME = 7; /* i: waiting for end of file name (gzip) */ -var COMMENT = 8; /* i: waiting for end of comment (gzip) */ -var HCRC = 9; /* i: waiting for header crc (gzip) */ -var DICTID = 10; /* i: waiting for dictionary check value */ -var DICT = 11; /* waiting for inflateSetDictionary() call */ -var TYPE = 12; /* i: waiting for type bits, including last-flag bit */ -var TYPEDO = 13; /* i: same, but skip check to exit inflate on new block */ -var STORED = 14; /* i: waiting for stored size (length and complement) */ -var COPY_ = 15; /* i/o: same as COPY below, but only first time in */ -var COPY = 16; /* i/o: waiting for input or output to copy stored block */ -var TABLE = 17; /* i: waiting for dynamic block table lengths */ -var LENLENS = 18; /* i: waiting for code length code lengths */ -var CODELENS = 19; /* i: waiting for length/lit and distance code lengths */ -var LEN_ = 20; /* i: same as LEN below, but only first time in */ -var LEN = 21; /* i: waiting for length/lit/eob code */ -var LENEXT = 22; /* i: waiting for length extra bits */ -var DIST = 23; /* i: waiting for distance code */ -var DISTEXT = 24; /* i: waiting for distance extra bits */ -var MATCH = 25; /* o: waiting for output space to copy string */ -var LIT = 26; /* o: waiting for output space to write literal */ -var CHECK = 27; /* i: waiting for 32-bit check value */ -var LENGTH = 28; /* i: waiting for 32-bit length (gzip) */ -var DONE = 29; /* finished check, done -- remain here until reset */ -var BAD = 30; /* got a data error -- remain here until reset */ -var MEM = 31; /* got an inflate() memory error -- remain here until reset */ -var SYNC = 32; /* looking for synchronization bytes to restart inflate() */ - -/* ===========================================================================*/ - - - -var ENOUGH_LENS = 852; -var ENOUGH_DISTS = 592; -//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); - -var MAX_WBITS = 15; -/* 32K LZ77 window */ -var DEF_WBITS = MAX_WBITS; - - -function zswap32(q) { - return (((q >>> 24) & 0xff) + - ((q >>> 8) & 0xff00) + - ((q & 0xff00) << 8) + - ((q & 0xff) << 24)); -} - - -function InflateState() { - this.mode = 0; /* current inflate mode */ - this.last = false; /* true if processing last block */ - this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ - this.havedict = false; /* true if dictionary provided */ - this.flags = 0; /* gzip header method and flags (0 if zlib) */ - this.dmax = 0; /* zlib header max distance (INFLATE_STRICT) */ - this.check = 0; /* protected copy of check value */ - this.total = 0; /* protected copy of output count */ - // TODO: may be {} - this.head = null; /* where to save gzip header information */ - - /* sliding window */ - this.wbits = 0; /* log base 2 of requested window size */ - this.wsize = 0; /* window size or zero if not using window */ - this.whave = 0; /* valid bytes in the window */ - this.wnext = 0; /* window write index */ - this.window = null; /* allocated sliding window, if needed */ - - /* bit accumulator */ - this.hold = 0; /* input bit accumulator */ - this.bits = 0; /* number of bits in "in" */ - - /* for string and stored block copying */ - this.length = 0; /* literal or length of data to copy */ - this.offset = 0; /* distance back to copy string from */ - - /* for table and code decoding */ - this.extra = 0; /* extra bits needed */ - - /* fixed and dynamic code tables */ - this.lencode = null; /* starting table for length/literal codes */ - this.distcode = null; /* starting table for distance codes */ - this.lenbits = 0; /* index bits for lencode */ - this.distbits = 0; /* index bits for distcode */ - - /* dynamic table building */ - this.ncode = 0; /* number of code length code lengths */ - this.nlen = 0; /* number of length code lengths */ - this.ndist = 0; /* number of distance code lengths */ - this.have = 0; /* number of code lengths in lens[] */ - this.next = null; /* next available space in codes[] */ - - this.lens = new utils.Buf16(320); /* temporary storage for code lengths */ - this.work = new utils.Buf16(288); /* work area for code table building */ - - /* - because we don't have pointers in js, we use lencode and distcode directly - as buffers so we don't need codes - */ - //this.codes = new utils.Buf32(ENOUGH); /* space for code tables */ - this.lendyn = null; /* dynamic table for length/literal codes (JS specific) */ - this.distdyn = null; /* dynamic table for distance codes (JS specific) */ - this.sane = 0; /* if false, allow invalid distance too far */ - this.back = 0; /* bits back of last unprocessed length/lit */ - this.was = 0; /* initial length of match */ -} - -function inflateResetKeep(strm) { - var state; - - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - strm.total_in = strm.total_out = state.total = 0; - strm.msg = ''; /*Z_NULL*/ - if (state.wrap) { /* to support ill-conceived Java test suite */ - strm.adler = state.wrap & 1; - } - state.mode = HEAD; - state.last = 0; - state.havedict = 0; - state.dmax = 32768; - state.head = null/*Z_NULL*/; - state.hold = 0; - state.bits = 0; - //state.lencode = state.distcode = state.next = state.codes; - state.lencode = state.lendyn = new utils.Buf32(ENOUGH_LENS); - state.distcode = state.distdyn = new utils.Buf32(ENOUGH_DISTS); - - state.sane = 1; - state.back = -1; - //Tracev((stderr, "inflate: reset\n")); - return Z_OK; -} - -function inflateReset(strm) { - var state; - - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - state.wsize = 0; - state.whave = 0; - state.wnext = 0; - return inflateResetKeep(strm); - -} - -function inflateReset2(strm, windowBits) { - var wrap; - var state; - - /* get the state */ - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - /* extract wrap request from windowBits parameter */ - if (windowBits < 0) { - wrap = 0; - windowBits = -windowBits; - } - else { - wrap = (windowBits >> 4) + 1; - if (windowBits < 48) { - windowBits &= 15; + kLen = inKey.length / 2; + for (i = 0; i < kLen; i++) { + a = inKey[i + i]; + meKey[i] = a; + b = inKey[i + i + 1]; + moKey[i] = b; + sKey[kLen - i - 1] = mdsRem(a, b); + } + for (i = 0; i < 40; i += 2) { + a = 0x1010101 * i; + b = a + 0x1010101; + a = hFun(a, meKey); + b = rotw(hFun(b, moKey), 8); + tfsKey[i] = (a + b) & MAXINT; + tfsKey[i + 1] = rotw(a + 2 * b, 9); + } + for (i = 0; i < 256; i++) { + a = b = c = d = i; + switch (kLen) { + case 4: + a = q[1][a] ^ getB(sKey[3], 0); + b = q[0][b] ^ getB(sKey[3], 1); + c = q[0][c] ^ getB(sKey[3], 2); + d = q[1][d] ^ getB(sKey[3], 3); + case 3: + a = q[1][a] ^ getB(sKey[2], 0); + b = q[1][b] ^ getB(sKey[2], 1); + c = q[0][c] ^ getB(sKey[2], 2); + d = q[0][d] ^ getB(sKey[2], 3); + case 2: + tfsM[0][i] = m[0][q[0][q[0][a] ^ getB(sKey[1], 0)] ^ getB(sKey[0], 0)]; + tfsM[1][i] = m[1][q[0][q[1][b] ^ getB(sKey[1], 1)] ^ getB(sKey[0], 1)]; + tfsM[2][i] = m[2][q[1][q[0][c] ^ getB(sKey[1], 2)] ^ getB(sKey[0], 2)]; + tfsM[3][i] = m[3][q[1][q[1][d] ^ getB(sKey[1], 3)] ^ getB(sKey[0], 3)]; + } } } - /* set number of window bits, free window if different */ - if (windowBits && (windowBits < 8 || windowBits > 15)) { - return Z_STREAM_ERROR; - } - if (state.window !== null && state.wbits !== windowBits) { - state.window = null; + function tfsG0(x) { + return tfsM[0][getB(x, 0)] ^ tfsM[1][getB(x, 1)] ^ tfsM[2][getB(x, 2)] ^ tfsM[3][getB(x, 3)]; } - /* update state and reset the rest of it */ - state.wrap = wrap; - state.wbits = windowBits; - return inflateReset(strm); -} - -function inflateInit2(strm, windowBits) { - var ret; - var state; - - if (!strm) { return Z_STREAM_ERROR; } - //strm.msg = Z_NULL; /* in case we return an error */ - - state = new InflateState(); - - //if (state === Z_NULL) return Z_MEM_ERROR; - //Tracev((stderr, "inflate: allocated\n")); - strm.state = state; - state.window = null/*Z_NULL*/; - ret = inflateReset2(strm, windowBits); - if (ret !== Z_OK) { - strm.state = null/*Z_NULL*/; + function tfsG1(x) { + return tfsM[0][getB(x, 3)] ^ tfsM[1][getB(x, 0)] ^ tfsM[2][getB(x, 1)] ^ tfsM[3][getB(x, 2)]; } - return ret; -} - -function inflateInit(strm) { - return inflateInit2(strm, DEF_WBITS); -} - - -/* - Return state with length and distance decoding tables and index sizes set to - fixed code decoding. Normally this returns fixed tables from inffixed.h. - If BUILDFIXED is defined, then instead this routine builds the tables the - first time it's called, and returns those tables the first time and - thereafter. This reduces the size of the code by about 2K bytes, in - exchange for a little execution time. However, BUILDFIXED should not be - used for threaded applications, since the rewriting of the tables and virgin - may not be thread-safe. - */ -var virgin = true; -var lenfix, distfix; // We have no pointers in JS, so keep tables separate - -function fixedtables(state) { - /* build fixed huffman tables if first call (may not be thread safe) */ - if (virgin) { - var sym; - - lenfix = new utils.Buf32(512); - distfix = new utils.Buf32(32); - - /* literal/length table */ - sym = 0; - while (sym < 144) { state.lens[sym++] = 8; } - while (sym < 256) { state.lens[sym++] = 9; } - while (sym < 280) { state.lens[sym++] = 7; } - while (sym < 288) { state.lens[sym++] = 8; } - - inflate_table(LENS, state.lens, 0, 288, lenfix, 0, state.work, { bits: 9 }); - - /* distance table */ - sym = 0; - while (sym < 32) { state.lens[sym++] = 5; } - - inflate_table(DISTS, state.lens, 0, 32, distfix, 0, state.work, { bits: 5 }); - - /* do this just once */ - virgin = false; + function tfsFrnd(r, blk) { + let a = tfsG0(blk[0]); + let b = tfsG1(blk[1]); + blk[2] = rotw(blk[2] ^ (a + b + tfsKey[4 * r + 8]) & MAXINT, 31); + blk[3] = rotw(blk[3], 1) ^ (a + 2 * b + tfsKey[4 * r + 9]) & MAXINT; + a = tfsG0(blk[2]); + b = tfsG1(blk[3]); + blk[0] = rotw(blk[0] ^ (a + b + tfsKey[4 * r + 10]) & MAXINT, 31); + blk[1] = rotw(blk[1], 1) ^ (a + 2 * b + tfsKey[4 * r + 11]) & MAXINT; } - state.lencode = lenfix; - state.lenbits = 9; - state.distcode = distfix; - state.distbits = 5; -} - - -/* - Update the window with the last wsize (normally 32K) bytes written before - returning. If window does not exist yet, create it. This is only called - when a window is already in use, or when output has been written during this - inflate call, but the end of the deflate stream has not been reached yet. - It is also called to create a window for dictionary data when a dictionary - is loaded. - - Providing output buffers larger than 32K to inflate() should provide a speed - advantage, since only the last 32K of output is copied to the sliding window - upon return from inflate(), and since all distances after the first 32K of - output will fall in the output data, making match copies simpler and faster. - The advantage may be dependent on the size of the processor's data caches. - */ -function updatewindow(strm, src, end, copy) { - var dist; - var state = strm.state; - - /* if it hasn't been done already, allocate space for the window */ - if (state.window === null) { - state.wsize = 1 << state.wbits; - state.wnext = 0; - state.whave = 0; - - state.window = new utils.Buf8(state.wsize); + function tfsIrnd(i, blk) { + let a = tfsG0(blk[0]); + let b = tfsG1(blk[1]); + blk[2] = rotw(blk[2], 1) ^ (a + b + tfsKey[4 * i + 10]) & MAXINT; + blk[3] = rotw(blk[3] ^ (a + 2 * b + tfsKey[4 * i + 11]) & MAXINT, 31); + a = tfsG0(blk[2]); + b = tfsG1(blk[3]); + blk[0] = rotw(blk[0], 1) ^ (a + b + tfsKey[4 * i + 8]) & MAXINT; + blk[1] = rotw(blk[1] ^ (a + 2 * b + tfsKey[4 * i + 9]) & MAXINT, 31); } - /* copy state->wsize or less output bytes into the circular window */ - if (copy >= state.wsize) { - utils.arraySet(state.window, src, end - state.wsize, state.wsize, 0); - state.wnext = 0; - state.whave = state.wsize; + function tfsClose() { + tfsKey = []; + tfsM = [ + [], + [], + [], + [] + ]; } - else { - dist = state.wsize - state.wnext; - if (dist > copy) { - dist = copy; - } - //zmemcpy(state->window + state->wnext, end - copy, dist); - utils.arraySet(state.window, src, end - copy, dist, state.wnext); - copy -= dist; - if (copy) { - //zmemcpy(state->window, end - copy, copy); - utils.arraySet(state.window, src, end - copy, copy, 0); - state.wnext = copy; - state.whave = state.wsize; + + function tfsEncrypt(data, offset) { + dataBytes = data; + dataOffset = offset; + const blk = [getW(dataBytes, dataOffset) ^ tfsKey[0], + getW(dataBytes, dataOffset + 4) ^ tfsKey[1], + getW(dataBytes, dataOffset + 8) ^ tfsKey[2], + getW(dataBytes, dataOffset + 12) ^ tfsKey[3]]; + for (let j = 0; j < 8; j++) { + tfsFrnd(j, blk); } - else { - state.wnext += dist; - if (state.wnext === state.wsize) { state.wnext = 0; } - if (state.whave < state.wsize) { state.whave += dist; } + setW(dataBytes, dataOffset, blk[2] ^ tfsKey[4]); + setW(dataBytes, dataOffset + 4, blk[3] ^ tfsKey[5]); + setW(dataBytes, dataOffset + 8, blk[0] ^ tfsKey[6]); + setW(dataBytes, dataOffset + 12, blk[1] ^ tfsKey[7]); + dataOffset += 16; + return dataBytes; + } + + function tfsDecrypt(data, offset) { + dataBytes = data; + dataOffset = offset; + const blk = [getW(dataBytes, dataOffset) ^ tfsKey[4], + getW(dataBytes, dataOffset + 4) ^ tfsKey[5], + getW(dataBytes, dataOffset + 8) ^ tfsKey[6], + getW(dataBytes, dataOffset + 12) ^ tfsKey[7]]; + for (let j = 7; j >= 0; j--) { + tfsIrnd(j, blk); } + setW(dataBytes, dataOffset, blk[2] ^ tfsKey[0]); + setW(dataBytes, dataOffset + 4, blk[3] ^ tfsKey[1]); + setW(dataBytes, dataOffset + 8, blk[0] ^ tfsKey[2]); + setW(dataBytes, dataOffset + 12, blk[1] ^ tfsKey[3]); + dataOffset += 16; } - return 0; -} -function inflate(strm, flush) { - var state; - var input, output; // input/output buffers - var next; /* next input INDEX */ - var put; /* next output INDEX */ - var have, left; /* available input and output */ - var hold; /* bit buffer */ - var bits; /* bits in bit buffer */ - var _in, _out; /* save starting available input and output */ - var copy; /* number of stored or match bytes to copy */ - var from; /* where to copy match bytes from */ - var from_source; - var here = 0; /* current decoding table entry */ - var here_bits, here_op, here_val; // paked "here" denormalized (JS specific) - //var last; /* parent table entry */ - var last_bits, last_op, last_val; // paked "last" denormalized (JS specific) - var len; /* length to copy for repeats, bits to drop */ - var ret; /* return code */ - var hbuf = new utils.Buf8(4); /* buffer for gzip header crc calculation */ - var opts; + // added by Recurity Labs - var n; // temporary var for NEED_BITS + function tfsFinal() { + return dataBytes; + } - var order = /* permutation of code lengths */ - [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ]; + return { + name: 'twofish', + blocksize: 128 / 8, + open: tfsInit, + close: tfsClose, + encrypt: tfsEncrypt, + decrypt: tfsDecrypt, + // added by Recurity Labs + finalize: tfsFinal + }; +} +// added by Recurity Labs - if (!strm || !strm.state || !strm.output || - (!strm.input && strm.avail_in !== 0)) { - return Z_STREAM_ERROR; - } +function TF(key) { + this.tf = createTwofish(); + this.tf.open(Array.from(key), 0); - state = strm.state; - if (state.mode === TYPE) { state.mode = TYPEDO; } /* skip check */ + this.encrypt = function(block) { + return this.tf.encrypt(Array.from(block), 0); + }; +} +TF.keySize = TF.prototype.keySize = 32; +TF.blockSize = TF.prototype.blockSize = 16; - //--- LOAD() --- - put = strm.next_out; - output = strm.output; - left = strm.avail_out; - next = strm.next_in; - input = strm.input; - have = strm.avail_in; - hold = state.hold; - bits = state.bits; - //--- +/* Modified by Recurity Labs GmbH + * + * Originally written by nklein software (nklein.com) + */ + +/* + * Javascript implementation based on Bruce Schneier's reference implementation. + * + * + * The constructor doesn't do much of anything. It's just here + * so we can start defining properties and methods and such. + */ +function Blowfish() {} - _in = have; - _out = left; - ret = Z_OK; +/* + * Declare the block size so that protocols know what size + * Initialization Vector (IV) they will need. + */ +Blowfish.prototype.BLOCKSIZE = 8; - inf_leave: // goto emulation - for (;;) { - switch (state.mode) { - case HEAD: - if (state.wrap === 0) { - state.mode = TYPEDO; - break; - } - //=== NEEDBITS(16); - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if ((state.wrap & 2) && hold === 0x8b1f) { /* gzip header */ - state.check = 0/*crc32(0L, Z_NULL, 0)*/; - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// +/* + * These are the default SBOXES. + */ +Blowfish.prototype.SBOXES = [ + [ + 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, + 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, + 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658, + 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, + 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, + 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, + 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6, + 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, + 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, + 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, + 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, + 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, + 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, + 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, + 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, + 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, + 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, + 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, + 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, + 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, + 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, + 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, + 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, + 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, + 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, + 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, + 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8, + 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, + 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, + 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, + 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, + 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, + 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, + 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, + 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, + 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, + 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, + 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, + 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, + 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, + 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, + 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, + 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a + ], + [ + 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, + 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, + 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, + 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, + 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, + 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, + 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, + 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, + 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, + 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, + 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, + 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, + 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, + 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, + 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, + 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, + 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, + 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, + 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, + 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, + 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, + 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, + 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, + 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, + 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, + 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, + 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, + 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, + 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, + 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, + 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, + 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, + 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, + 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, + 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, + 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, + 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, + 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, + 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, + 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, + 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, + 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, + 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7 + ], + [ + 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, + 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, + 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, + 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, + 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, + 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, + 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, + 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, + 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, + 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, + 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, + 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, + 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, + 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, + 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, + 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, + 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, + 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, + 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74, + 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, + 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, + 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, + 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, + 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, + 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, + 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, + 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, + 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, + 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, + 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, + 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, + 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, + 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, + 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, + 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, + 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, + 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, + 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, + 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, + 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, + 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, + 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, + 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0 + ], + [ + 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, + 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, + 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, + 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, + 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, + 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, + 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, + 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, + 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, + 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, + 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, + 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, + 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, + 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, + 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5, + 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, + 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, + 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, + 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd, + 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, + 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, + 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, + 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc, + 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, + 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, + 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, + 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, + 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, + 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, + 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, + 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, + 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, + 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, + 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, + 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623, + 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, + 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, + 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, + 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3, + 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, + 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, + 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, + 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 + ] +]; - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = FLAGS; - break; - } - state.flags = 0; /* expect zlib header */ - if (state.head) { - state.head.done = false; - } - if (!(state.wrap & 1) || /* check if zlib header allowed */ - (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) { - strm.msg = 'incorrect header check'; - state.mode = BAD; - break; - } - if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) { - strm.msg = 'unknown compression method'; - state.mode = BAD; - break; - } - //--- DROPBITS(4) ---// - hold >>>= 4; - bits -= 4; - //---// - len = (hold & 0x0f)/*BITS(4)*/ + 8; - if (state.wbits === 0) { - state.wbits = len; - } - else if (len > state.wbits) { - strm.msg = 'invalid window size'; - state.mode = BAD; - break; - } - state.dmax = 1 << len; - //Tracev((stderr, "inflate: zlib header ok\n")); - strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; - state.mode = hold & 0x200 ? DICTID : TYPE; - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - break; - case FLAGS: - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.flags = hold; - if ((state.flags & 0xff) !== Z_DEFLATED) { - strm.msg = 'unknown compression method'; - state.mode = BAD; - break; - } - if (state.flags & 0xe000) { - strm.msg = 'unknown header flags set'; - state.mode = BAD; - break; - } - if (state.head) { - state.head.text = ((hold >> 8) & 1); - } - if (state.flags & 0x0200) { - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = TIME; - /* falls through */ - case TIME: - //=== NEEDBITS(32); */ - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (state.head) { - state.head.time = hold; - } - if (state.flags & 0x0200) { - //=== CRC4(state.check, hold) - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - hbuf[2] = (hold >>> 16) & 0xff; - hbuf[3] = (hold >>> 24) & 0xff; - state.check = crc32(state.check, hbuf, 4, 0); - //=== - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = OS; - /* falls through */ - case OS: - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (state.head) { - state.head.xflags = (hold & 0xff); - state.head.os = (hold >> 8); - } - if (state.flags & 0x0200) { - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = EXLEN; - /* falls through */ - case EXLEN: - if (state.flags & 0x0400) { - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.length = hold; - if (state.head) { - state.head.extra_len = hold; - } - if (state.flags & 0x0200) { - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - } - else if (state.head) { - state.head.extra = null/*Z_NULL*/; - } - state.mode = EXTRA; - /* falls through */ - case EXTRA: - if (state.flags & 0x0400) { - copy = state.length; - if (copy > have) { copy = have; } - if (copy) { - if (state.head) { - len = state.head.extra_len - state.length; - if (!state.head.extra) { - // Use untyped array for more convenient processing later - state.head.extra = new Array(state.head.extra_len); - } - utils.arraySet( - state.head.extra, - input, - next, - // extra field is limited to 65536 bytes - // - no need for additional size check - copy, - /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/ - len - ); - //zmemcpy(state.head.extra + len, next, - // len + copy > state.head.extra_max ? - // state.head.extra_max - len : copy); - } - if (state.flags & 0x0200) { - state.check = crc32(state.check, input, copy, next); - } - have -= copy; - next += copy; - state.length -= copy; - } - if (state.length) { break inf_leave; } - } - state.length = 0; - state.mode = NAME; - /* falls through */ - case NAME: - if (state.flags & 0x0800) { - if (have === 0) { break inf_leave; } - copy = 0; - do { - // TODO: 2 or 1 bytes? - len = input[next + copy++]; - /* use constant limit because in js we should not preallocate memory */ - if (state.head && len && - (state.length < 65536 /*state.head.name_max*/)) { - state.head.name += String.fromCharCode(len); - } - } while (len && copy < have); +//* +//* This is the default PARRAY +//* +Blowfish.prototype.PARRAY = [ + 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, + 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, + 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b +]; + +//* +//* This is the number of rounds the cipher will go +//* +Blowfish.prototype.NN = 16; - if (state.flags & 0x0200) { - state.check = crc32(state.check, input, copy, next); - } - have -= copy; - next += copy; - if (len) { break inf_leave; } - } - else if (state.head) { - state.head.name = null; - } - state.length = 0; - state.mode = COMMENT; - /* falls through */ - case COMMENT: - if (state.flags & 0x1000) { - if (have === 0) { break inf_leave; } - copy = 0; - do { - len = input[next + copy++]; - /* use constant limit because in js we should not preallocate memory */ - if (state.head && len && - (state.length < 65536 /*state.head.comm_max*/)) { - state.head.comment += String.fromCharCode(len); - } - } while (len && copy < have); - if (state.flags & 0x0200) { - state.check = crc32(state.check, input, copy, next); - } - have -= copy; - next += copy; - if (len) { break inf_leave; } - } - else if (state.head) { - state.head.comment = null; - } - state.mode = HCRC; - /* falls through */ - case HCRC: - if (state.flags & 0x0200) { - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (hold !== (state.check & 0xffff)) { - strm.msg = 'header crc mismatch'; - state.mode = BAD; - break; - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - } - if (state.head) { - state.head.hcrc = ((state.flags >> 9) & 1); - state.head.done = true; - } - strm.adler = state.check = 0; - state.mode = TYPE; - break; - case DICTID: - //=== NEEDBITS(32); */ - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - strm.adler = state.check = zswap32(hold); - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = DICT; - /* falls through */ - case DICT: - if (state.havedict === 0) { - //--- RESTORE() --- - strm.next_out = put; - strm.avail_out = left; - strm.next_in = next; - strm.avail_in = have; - state.hold = hold; - state.bits = bits; - //--- - return Z_NEED_DICT; - } - strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; - state.mode = TYPE; - /* falls through */ - case TYPE: - if (flush === Z_BLOCK || flush === Z_TREES) { break inf_leave; } - /* falls through */ - case TYPEDO: - if (state.last) { - //--- BYTEBITS() ---// - hold >>>= bits & 7; - bits -= bits & 7; - //---// - state.mode = CHECK; - break; - } - //=== NEEDBITS(3); */ - while (bits < 3) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.last = (hold & 0x01)/*BITS(1)*/; - //--- DROPBITS(1) ---// - hold >>>= 1; - bits -= 1; - //---// +//* +//* This function is needed to get rid of problems +//* with the high-bit getting set. If we don't do +//* this, then sometimes ( aa & 0x00FFFFFFFF ) is not +//* equal to ( bb & 0x00FFFFFFFF ) even when they +//* agree bit-for-bit for the first 32 bits. +//* +Blowfish.prototype._clean = function(xx) { + if (xx < 0) { + const yy = xx & 0x7FFFFFFF; + xx = yy + 0x80000000; + } + return xx; +}; + +//* +//* This is the mixing function that uses the sboxes +//* +Blowfish.prototype._F = function(xx) { + let yy; + + const dd = xx & 0x00FF; + xx >>>= 8; + const cc = xx & 0x00FF; + xx >>>= 8; + const bb = xx & 0x00FF; + xx >>>= 8; + const aa = xx & 0x00FF; + + yy = this.sboxes[0][aa] + this.sboxes[1][bb]; + yy ^= this.sboxes[2][cc]; + yy += this.sboxes[3][dd]; + + return yy; +}; + +//* +//* This method takes an array with two values, left and right +//* and does NN rounds of Blowfish on them. +//* +Blowfish.prototype._encryptBlock = function(vals) { + let dataL = vals[0]; + let dataR = vals[1]; + + let ii; + + for (ii = 0; ii < this.NN; ++ii) { + dataL ^= this.parray[ii]; + dataR = this._F(dataL) ^ dataR; + + const tmp = dataL; + dataL = dataR; + dataR = tmp; + } + + dataL ^= this.parray[this.NN + 0]; + dataR ^= this.parray[this.NN + 1]; + + vals[0] = this._clean(dataR); + vals[1] = this._clean(dataL); +}; + +//* +//* This method takes a vector of numbers and turns them +//* into long words so that they can be processed by the +//* real algorithm. +//* +//* Maybe I should make the real algorithm above take a vector +//* instead. That will involve more looping, but it won't require +//* the F() method to deconstruct the vector. +//* +Blowfish.prototype.encryptBlock = function(vector) { + let ii; + const vals = [0, 0]; + const off = this.BLOCKSIZE / 2; + for (ii = 0; ii < this.BLOCKSIZE / 2; ++ii) { + vals[0] = (vals[0] << 8) | (vector[ii + 0] & 0x00FF); + vals[1] = (vals[1] << 8) | (vector[ii + off] & 0x00FF); + } + + this._encryptBlock(vals); + + const ret = []; + for (ii = 0; ii < this.BLOCKSIZE / 2; ++ii) { + ret[ii + 0] = ((vals[0] >>> (24 - 8 * (ii))) & 0x00FF); + ret[ii + off] = ((vals[1] >>> (24 - 8 * (ii))) & 0x00FF); + // vals[ 0 ] = ( vals[ 0 ] >>> 8 ); + // vals[ 1 ] = ( vals[ 1 ] >>> 8 ); + } + + return ret; +}; + +//* +//* This method takes an array with two values, left and right +//* and undoes NN rounds of Blowfish on them. +//* +Blowfish.prototype._decryptBlock = function(vals) { + let dataL = vals[0]; + let dataR = vals[1]; + + let ii; + + for (ii = this.NN + 1; ii > 1; --ii) { + dataL ^= this.parray[ii]; + dataR = this._F(dataL) ^ dataR; + + const tmp = dataL; + dataL = dataR; + dataR = tmp; + } + + dataL ^= this.parray[1]; + dataR ^= this.parray[0]; + + vals[0] = this._clean(dataR); + vals[1] = this._clean(dataL); +}; + +//* +//* This method takes a key array and initializes the +//* sboxes and parray for this encryption. +//* +Blowfish.prototype.init = function(key) { + let ii; + let jj = 0; + + this.parray = []; + for (ii = 0; ii < this.NN + 2; ++ii) { + let data = 0x00000000; + for (let kk = 0; kk < 4; ++kk) { + data = (data << 8) | (key[jj] & 0x00FF); + if (++jj >= key.length) { + jj = 0; + } + } + this.parray[ii] = this.PARRAY[ii] ^ data; + } + + this.sboxes = []; + for (ii = 0; ii < 4; ++ii) { + this.sboxes[ii] = []; + for (jj = 0; jj < 256; ++jj) { + this.sboxes[ii][jj] = this.SBOXES[ii][jj]; + } + } + + const vals = [0x00000000, 0x00000000]; + + for (ii = 0; ii < this.NN + 2; ii += 2) { + this._encryptBlock(vals); + this.parray[ii + 0] = vals[0]; + this.parray[ii + 1] = vals[1]; + } - switch ((hold & 0x03)/*BITS(2)*/) { - case 0: /* stored block */ - //Tracev((stderr, "inflate: stored block%s\n", - // state.last ? " (last)" : "")); - state.mode = STORED; - break; - case 1: /* fixed block */ - fixedtables(state); - //Tracev((stderr, "inflate: fixed codes block%s\n", - // state.last ? " (last)" : "")); - state.mode = LEN_; /* decode codes */ - if (flush === Z_TREES) { - //--- DROPBITS(2) ---// - hold >>>= 2; - bits -= 2; - //---// - break inf_leave; - } - break; - case 2: /* dynamic block */ - //Tracev((stderr, "inflate: dynamic codes block%s\n", - // state.last ? " (last)" : "")); - state.mode = TABLE; - break; - case 3: - strm.msg = 'invalid block type'; - state.mode = BAD; - } - //--- DROPBITS(2) ---// - hold >>>= 2; - bits -= 2; - //---// - break; - case STORED: - //--- BYTEBITS() ---// /* go to byte boundary */ - hold >>>= bits & 7; - bits -= bits & 7; - //---// - //=== NEEDBITS(32); */ - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) { - strm.msg = 'invalid stored block lengths'; - state.mode = BAD; - break; - } - state.length = hold & 0xffff; - //Tracev((stderr, "inflate: stored length %u\n", - // state.length)); - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = COPY_; - if (flush === Z_TREES) { break inf_leave; } - /* falls through */ - case COPY_: - state.mode = COPY; - /* falls through */ - case COPY: - copy = state.length; - if (copy) { - if (copy > have) { copy = have; } - if (copy > left) { copy = left; } - if (copy === 0) { break inf_leave; } - //--- zmemcpy(put, next, copy); --- - utils.arraySet(output, input, next, copy, put); - //---// - have -= copy; - next += copy; - left -= copy; - put += copy; - state.length -= copy; - break; - } - //Tracev((stderr, "inflate: stored end\n")); - state.mode = TYPE; - break; - case TABLE: - //=== NEEDBITS(14); */ - while (bits < 14) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257; - //--- DROPBITS(5) ---// - hold >>>= 5; - bits -= 5; - //---// - state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1; - //--- DROPBITS(5) ---// - hold >>>= 5; - bits -= 5; - //---// - state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4; - //--- DROPBITS(4) ---// - hold >>>= 4; - bits -= 4; - //---// -//#ifndef PKZIP_BUG_WORKAROUND - if (state.nlen > 286 || state.ndist > 30) { - strm.msg = 'too many length or distance symbols'; - state.mode = BAD; - break; - } -//#endif - //Tracev((stderr, "inflate: table sizes ok\n")); - state.have = 0; - state.mode = LENLENS; - /* falls through */ - case LENLENS: - while (state.have < state.ncode) { - //=== NEEDBITS(3); - while (bits < 3) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.lens[order[state.have++]] = (hold & 0x07);//BITS(3); - //--- DROPBITS(3) ---// - hold >>>= 3; - bits -= 3; - //---// - } - while (state.have < 19) { - state.lens[order[state.have++]] = 0; - } - // We have separate tables & no pointers. 2 commented lines below not needed. - //state.next = state.codes; - //state.lencode = state.next; - // Switch to use dynamic table - state.lencode = state.lendyn; - state.lenbits = 7; + for (ii = 0; ii < 4; ++ii) { + for (jj = 0; jj < 256; jj += 2) { + this._encryptBlock(vals); + this.sboxes[ii][jj + 0] = vals[0]; + this.sboxes[ii][jj + 1] = vals[1]; + } + } +}; + +// added by Recurity Labs +function BF(key) { + this.bf = new Blowfish(); + this.bf.init(key); + + this.encrypt = function(block) { + return this.bf.encryptBlock(block); + }; +} + +BF.keySize = BF.prototype.keySize = 16; +BF.blockSize = BF.prototype.blockSize = 8; + +/** + * @fileoverview Symmetric cryptography functions + * @module crypto/cipher + * @private + */ + +/** + * AES-128 encryption and decryption (ID 7) + * @function + * @param {String} key - 128-bit key + * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} + * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} + * @returns {Object} + */ +const aes128 = aes(128); +/** + * AES-128 Block Cipher (ID 8) + * @function + * @param {String} key - 192-bit key + * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} + * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} + * @returns {Object} + */ +const aes192 = aes(192); +/** + * AES-128 Block Cipher (ID 9) + * @function + * @param {String} key - 256-bit key + * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} + * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} + * @returns {Object} + */ +const aes256 = aes(256); +// Not in OpenPGP specifications +const des$1 = DES; +/** + * Triple DES Block Cipher (ID 2) + * @function + * @param {String} key - 192-bit key + * @see {@link https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-67r2.pdf|NIST SP 800-67} + * @returns {Object} + */ +const tripledes = TripleDES; +/** + * CAST-128 Block Cipher (ID 3) + * @function + * @param {String} key - 128-bit key + * @see {@link https://tools.ietf.org/html/rfc2144|The CAST-128 Encryption Algorithm} + * @returns {Object} + */ +const cast5 = CAST5; +/** + * Twofish Block Cipher (ID 10) + * @function + * @param {String} key - 256-bit key + * @see {@link https://tools.ietf.org/html/rfc4880#ref-TWOFISH|TWOFISH} + * @returns {Object} + */ +const twofish = TF; +/** + * Blowfish Block Cipher (ID 4) + * @function + * @param {String} key - 128-bit key + * @see {@link https://tools.ietf.org/html/rfc4880#ref-BLOWFISH|BLOWFISH} + * @returns {Object} + */ +const blowfish = BF; +/** + * Not implemented + * @function + * @throws {Error} + */ +const idea = function() { + throw new Error('IDEA symmetric-key algorithm not implemented'); +}; + +var cipher = /*#__PURE__*/Object.freeze({ + __proto__: null, + aes128: aes128, + aes192: aes192, + aes256: aes256, + des: des$1, + tripledes: tripledes, + cast5: cast5, + twofish: twofish, + blowfish: blowfish, + idea: idea +}); + +var sha1_asm = function ( stdlib, foreign, buffer ) { + "use asm"; + + // SHA256 state + var H0 = 0, H1 = 0, H2 = 0, H3 = 0, H4 = 0, + TOTAL0 = 0, TOTAL1 = 0; + + // HMAC state + var I0 = 0, I1 = 0, I2 = 0, I3 = 0, I4 = 0, + O0 = 0, O1 = 0, O2 = 0, O3 = 0, O4 = 0; + + // I/O buffer + var HEAP = new stdlib.Uint8Array(buffer); + + function _core ( w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15 ) { + w0 = w0|0; + w1 = w1|0; + w2 = w2|0; + w3 = w3|0; + w4 = w4|0; + w5 = w5|0; + w6 = w6|0; + w7 = w7|0; + w8 = w8|0; + w9 = w9|0; + w10 = w10|0; + w11 = w11|0; + w12 = w12|0; + w13 = w13|0; + w14 = w14|0; + w15 = w15|0; + + var a = 0, b = 0, c = 0, d = 0, e = 0, n = 0, t = 0, + w16 = 0, w17 = 0, w18 = 0, w19 = 0, + w20 = 0, w21 = 0, w22 = 0, w23 = 0, w24 = 0, w25 = 0, w26 = 0, w27 = 0, w28 = 0, w29 = 0, + w30 = 0, w31 = 0, w32 = 0, w33 = 0, w34 = 0, w35 = 0, w36 = 0, w37 = 0, w38 = 0, w39 = 0, + w40 = 0, w41 = 0, w42 = 0, w43 = 0, w44 = 0, w45 = 0, w46 = 0, w47 = 0, w48 = 0, w49 = 0, + w50 = 0, w51 = 0, w52 = 0, w53 = 0, w54 = 0, w55 = 0, w56 = 0, w57 = 0, w58 = 0, w59 = 0, + w60 = 0, w61 = 0, w62 = 0, w63 = 0, w64 = 0, w65 = 0, w66 = 0, w67 = 0, w68 = 0, w69 = 0, + w70 = 0, w71 = 0, w72 = 0, w73 = 0, w74 = 0, w75 = 0, w76 = 0, w77 = 0, w78 = 0, w79 = 0; + + a = H0; + b = H1; + c = H2; + d = H3; + e = H4; + + // 0 + t = ( w0 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 1 + t = ( w1 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 2 + t = ( w2 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 3 + t = ( w3 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 4 + t = ( w4 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 5 + t = ( w5 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 6 + t = ( w6 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 7 + t = ( w7 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 8 + t = ( w8 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 9 + t = ( w9 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 10 + t = ( w10 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 11 + t = ( w11 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 12 + t = ( w12 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 13 + t = ( w13 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 14 + t = ( w14 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 15 + t = ( w15 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 16 + n = w13 ^ w8 ^ w2 ^ w0; + w16 = (n << 1) | (n >>> 31); + t = (w16 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 17 + n = w14 ^ w9 ^ w3 ^ w1; + w17 = (n << 1) | (n >>> 31); + t = (w17 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 18 + n = w15 ^ w10 ^ w4 ^ w2; + w18 = (n << 1) | (n >>> 31); + t = (w18 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 19 + n = w16 ^ w11 ^ w5 ^ w3; + w19 = (n << 1) | (n >>> 31); + t = (w19 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 20 + n = w17 ^ w12 ^ w6 ^ w4; + w20 = (n << 1) | (n >>> 31); + t = (w20 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 21 + n = w18 ^ w13 ^ w7 ^ w5; + w21 = (n << 1) | (n >>> 31); + t = (w21 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - opts = { bits: state.lenbits }; - ret = inflate_table(CODES, state.lens, 0, 19, state.lencode, 0, state.work, opts); - state.lenbits = opts.bits; + // 22 + n = w19 ^ w14 ^ w8 ^ w6; + w22 = (n << 1) | (n >>> 31); + t = (w22 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - if (ret) { - strm.msg = 'invalid code lengths set'; - state.mode = BAD; - break; - } - //Tracev((stderr, "inflate: code lengths ok\n")); - state.have = 0; - state.mode = CODELENS; - /* falls through */ - case CODELENS: - while (state.have < state.nlen + state.ndist) { - for (;;) { - here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/ - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; + // 23 + n = w20 ^ w15 ^ w9 ^ w7; + w23 = (n << 1) | (n >>> 31); + t = (w23 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - if ((here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - if (here_val < 16) { - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - state.lens[state.have++] = here_val; - } - else { - if (here_val === 16) { - //=== NEEDBITS(here.bits + 2); - n = here_bits + 2; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - if (state.have === 0) { - strm.msg = 'invalid bit length repeat'; - state.mode = BAD; - break; - } - len = state.lens[state.have - 1]; - copy = 3 + (hold & 0x03);//BITS(2); - //--- DROPBITS(2) ---// - hold >>>= 2; - bits -= 2; - //---// - } - else if (here_val === 17) { - //=== NEEDBITS(here.bits + 3); - n = here_bits + 3; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - len = 0; - copy = 3 + (hold & 0x07);//BITS(3); - //--- DROPBITS(3) ---// - hold >>>= 3; - bits -= 3; - //---// - } - else { - //=== NEEDBITS(here.bits + 7); - n = here_bits + 7; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - len = 0; - copy = 11 + (hold & 0x7f);//BITS(7); - //--- DROPBITS(7) ---// - hold >>>= 7; - bits -= 7; - //---// - } - if (state.have + copy > state.nlen + state.ndist) { - strm.msg = 'invalid bit length repeat'; - state.mode = BAD; - break; - } - while (copy--) { - state.lens[state.have++] = len; - } - } - } + // 24 + n = w21 ^ w16 ^ w10 ^ w8; + w24 = (n << 1) | (n >>> 31); + t = (w24 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - /* handle error breaks in while */ - if (state.mode === BAD) { break; } + // 25 + n = w22 ^ w17 ^ w11 ^ w9; + w25 = (n << 1) | (n >>> 31); + t = (w25 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - /* check for end-of-block code (better have one) */ - if (state.lens[256] === 0) { - strm.msg = 'invalid code -- missing end-of-block'; - state.mode = BAD; - break; - } + // 26 + n = w23 ^ w18 ^ w12 ^ w10; + w26 = (n << 1) | (n >>> 31); + t = (w26 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - /* build code tables -- note: do not change the lenbits or distbits - values here (9 and 6) without reading the comments in inftrees.h - concerning the ENOUGH constants, which depend on those values */ - state.lenbits = 9; + // 27 + n = w24 ^ w19 ^ w13 ^ w11; + w27 = (n << 1) | (n >>> 31); + t = (w27 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - opts = { bits: state.lenbits }; - ret = inflate_table(LENS, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts); - // We have separate tables & no pointers. 2 commented lines below not needed. - // state.next_index = opts.table_index; - state.lenbits = opts.bits; - // state.lencode = state.next; + // 28 + n = w25 ^ w20 ^ w14 ^ w12; + w28 = (n << 1) | (n >>> 31); + t = (w28 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - if (ret) { - strm.msg = 'invalid literal/lengths set'; - state.mode = BAD; - break; - } + // 29 + n = w26 ^ w21 ^ w15 ^ w13; + w29 = (n << 1) | (n >>> 31); + t = (w29 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - state.distbits = 6; - //state.distcode.copy(state.codes); - // Switch to use dynamic table - state.distcode = state.distdyn; - opts = { bits: state.distbits }; - ret = inflate_table(DISTS, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts); - // We have separate tables & no pointers. 2 commented lines below not needed. - // state.next_index = opts.table_index; - state.distbits = opts.bits; - // state.distcode = state.next; + // 30 + n = w27 ^ w22 ^ w16 ^ w14; + w30 = (n << 1) | (n >>> 31); + t = (w30 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - if (ret) { - strm.msg = 'invalid distances set'; - state.mode = BAD; - break; - } - //Tracev((stderr, 'inflate: codes ok\n')); - state.mode = LEN_; - if (flush === Z_TREES) { break inf_leave; } - /* falls through */ - case LEN_: - state.mode = LEN; - /* falls through */ - case LEN: - if (have >= 6 && left >= 258) { - //--- RESTORE() --- - strm.next_out = put; - strm.avail_out = left; - strm.next_in = next; - strm.avail_in = have; - state.hold = hold; - state.bits = bits; - //--- - inflate_fast(strm, _out); - //--- LOAD() --- - put = strm.next_out; - output = strm.output; - left = strm.avail_out; - next = strm.next_in; - input = strm.input; - have = strm.avail_in; - hold = state.hold; - bits = state.bits; - //--- + // 31 + n = w28 ^ w23 ^ w17 ^ w15; + w31 = (n << 1) | (n >>> 31); + t = (w31 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 32 + n = w29 ^ w24 ^ w18 ^ w16; + w32 = (n << 1) | (n >>> 31); + t = (w32 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 33 + n = w30 ^ w25 ^ w19 ^ w17; + w33 = (n << 1) | (n >>> 31); + t = (w33 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 34 + n = w31 ^ w26 ^ w20 ^ w18; + w34 = (n << 1) | (n >>> 31); + t = (w34 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 35 + n = w32 ^ w27 ^ w21 ^ w19; + w35 = (n << 1) | (n >>> 31); + t = (w35 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 36 + n = w33 ^ w28 ^ w22 ^ w20; + w36 = (n << 1) | (n >>> 31); + t = (w36 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 37 + n = w34 ^ w29 ^ w23 ^ w21; + w37 = (n << 1) | (n >>> 31); + t = (w37 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 38 + n = w35 ^ w30 ^ w24 ^ w22; + w38 = (n << 1) | (n >>> 31); + t = (w38 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 39 + n = w36 ^ w31 ^ w25 ^ w23; + w39 = (n << 1) | (n >>> 31); + t = (w39 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 40 + n = w37 ^ w32 ^ w26 ^ w24; + w40 = (n << 1) | (n >>> 31); + t = (w40 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 41 + n = w38 ^ w33 ^ w27 ^ w25; + w41 = (n << 1) | (n >>> 31); + t = (w41 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 42 + n = w39 ^ w34 ^ w28 ^ w26; + w42 = (n << 1) | (n >>> 31); + t = (w42 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 43 + n = w40 ^ w35 ^ w29 ^ w27; + w43 = (n << 1) | (n >>> 31); + t = (w43 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 44 + n = w41 ^ w36 ^ w30 ^ w28; + w44 = (n << 1) | (n >>> 31); + t = (w44 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 45 + n = w42 ^ w37 ^ w31 ^ w29; + w45 = (n << 1) | (n >>> 31); + t = (w45 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 46 + n = w43 ^ w38 ^ w32 ^ w30; + w46 = (n << 1) | (n >>> 31); + t = (w46 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 47 + n = w44 ^ w39 ^ w33 ^ w31; + w47 = (n << 1) | (n >>> 31); + t = (w47 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 48 + n = w45 ^ w40 ^ w34 ^ w32; + w48 = (n << 1) | (n >>> 31); + t = (w48 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 49 + n = w46 ^ w41 ^ w35 ^ w33; + w49 = (n << 1) | (n >>> 31); + t = (w49 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 50 + n = w47 ^ w42 ^ w36 ^ w34; + w50 = (n << 1) | (n >>> 31); + t = (w50 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 51 + n = w48 ^ w43 ^ w37 ^ w35; + w51 = (n << 1) | (n >>> 31); + t = (w51 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 52 + n = w49 ^ w44 ^ w38 ^ w36; + w52 = (n << 1) | (n >>> 31); + t = (w52 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 53 + n = w50 ^ w45 ^ w39 ^ w37; + w53 = (n << 1) | (n >>> 31); + t = (w53 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - if (state.mode === TYPE) { - state.back = -1; - } - break; - } - state.back = 0; - for (;;) { - here = state.lencode[hold & ((1 << state.lenbits) - 1)]; /*BITS(state.lenbits)*/ - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; + // 54 + n = w51 ^ w46 ^ w40 ^ w38; + w54 = (n << 1) | (n >>> 31); + t = (w54 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - if (here_bits <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - if (here_op && (here_op & 0xf0) === 0) { - last_bits = here_bits; - last_op = here_op; - last_val = here_val; - for (;;) { - here = state.lencode[last_val + - ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; + // 55 + n = w52 ^ w47 ^ w41 ^ w39; + w55 = (n << 1) | (n >>> 31); + t = (w55 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - if ((last_bits + here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - //--- DROPBITS(last.bits) ---// - hold >>>= last_bits; - bits -= last_bits; - //---// - state.back += last_bits; - } - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - state.back += here_bits; - state.length = here_val; - if (here_op === 0) { - //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - // "inflate: literal '%c'\n" : - // "inflate: literal 0x%02x\n", here.val)); - state.mode = LIT; - break; - } - if (here_op & 32) { - //Tracevv((stderr, "inflate: end of block\n")); - state.back = -1; - state.mode = TYPE; - break; - } - if (here_op & 64) { - strm.msg = 'invalid literal/length code'; - state.mode = BAD; - break; - } - state.extra = here_op & 15; - state.mode = LENEXT; - /* falls through */ - case LENEXT: - if (state.extra) { - //=== NEEDBITS(state.extra); - n = state.extra; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.length += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; - //--- DROPBITS(state.extra) ---// - hold >>>= state.extra; - bits -= state.extra; - //---// - state.back += state.extra; - } - //Tracevv((stderr, "inflate: length %u\n", state.length)); - state.was = state.length; - state.mode = DIST; - /* falls through */ - case DIST: - for (;;) { - here = state.distcode[hold & ((1 << state.distbits) - 1)];/*BITS(state.distbits)*/ - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; + // 56 + n = w53 ^ w48 ^ w42 ^ w40; + w56 = (n << 1) | (n >>> 31); + t = (w56 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - if ((here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - if ((here_op & 0xf0) === 0) { - last_bits = here_bits; - last_op = here_op; - last_val = here_val; - for (;;) { - here = state.distcode[last_val + - ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; + // 57 + n = w54 ^ w49 ^ w43 ^ w41; + w57 = (n << 1) | (n >>> 31); + t = (w57 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - if ((last_bits + here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - //--- DROPBITS(last.bits) ---// - hold >>>= last_bits; - bits -= last_bits; - //---// - state.back += last_bits; - } - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - state.back += here_bits; - if (here_op & 64) { - strm.msg = 'invalid distance code'; - state.mode = BAD; - break; - } - state.offset = here_val; - state.extra = (here_op) & 15; - state.mode = DISTEXT; - /* falls through */ - case DISTEXT: - if (state.extra) { - //=== NEEDBITS(state.extra); - n = state.extra; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.offset += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; - //--- DROPBITS(state.extra) ---// - hold >>>= state.extra; - bits -= state.extra; - //---// - state.back += state.extra; - } -//#ifdef INFLATE_STRICT - if (state.offset > state.dmax) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD; - break; - } -//#endif - //Tracevv((stderr, "inflate: distance %u\n", state.offset)); - state.mode = MATCH; - /* falls through */ - case MATCH: - if (left === 0) { break inf_leave; } - copy = _out - left; - if (state.offset > copy) { /* copy from window */ - copy = state.offset - copy; - if (copy > state.whave) { - if (state.sane) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD; - break; - } -// (!) This block is disabled in zlib defaults, -// don't enable it for binary compatibility -//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR -// Trace((stderr, "inflate.c too far\n")); -// copy -= state.whave; -// if (copy > state.length) { copy = state.length; } -// if (copy > left) { copy = left; } -// left -= copy; -// state.length -= copy; -// do { -// output[put++] = 0; -// } while (--copy); -// if (state.length === 0) { state.mode = LEN; } -// break; -//#endif - } - if (copy > state.wnext) { - copy -= state.wnext; - from = state.wsize - copy; - } - else { - from = state.wnext - copy; - } - if (copy > state.length) { copy = state.length; } - from_source = state.window; - } - else { /* copy from output */ - from_source = output; - from = put - state.offset; - copy = state.length; - } - if (copy > left) { copy = left; } - left -= copy; - state.length -= copy; - do { - output[put++] = from_source[from++]; - } while (--copy); - if (state.length === 0) { state.mode = LEN; } - break; - case LIT: - if (left === 0) { break inf_leave; } - output[put++] = state.length; - left--; - state.mode = LEN; - break; - case CHECK: - if (state.wrap) { - //=== NEEDBITS(32); - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - // Use '|' instead of '+' to make sure that result is signed - hold |= input[next++] << bits; - bits += 8; - } - //===// - _out -= left; - strm.total_out += _out; - state.total += _out; - if (_out) { - strm.adler = state.check = - /*UPDATE(state.check, put - _out, _out);*/ - (state.flags ? crc32(state.check, output, _out, put - _out) : adler32(state.check, output, _out, put - _out)); + // 58 + n = w55 ^ w50 ^ w44 ^ w42; + w58 = (n << 1) | (n >>> 31); + t = (w58 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 59 + n = w56 ^ w51 ^ w45 ^ w43; + w59 = (n << 1) | (n >>> 31); + t = (w59 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 60 + n = w57 ^ w52 ^ w46 ^ w44; + w60 = (n << 1) | (n >>> 31); + t = (w60 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - } - _out = left; - // NB: crc32 stored as signed 32-bit int, zswap32 returns signed too - if ((state.flags ? hold : zswap32(hold)) !== state.check) { - strm.msg = 'incorrect data check'; - state.mode = BAD; - break; - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - //Tracev((stderr, "inflate: check matches trailer\n")); - } - state.mode = LENGTH; - /* falls through */ - case LENGTH: - if (state.wrap && state.flags) { - //=== NEEDBITS(32); - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (hold !== (state.total & 0xffffffff)) { - strm.msg = 'incorrect length check'; - state.mode = BAD; - break; - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - //Tracev((stderr, "inflate: length matches trailer\n")); - } - state.mode = DONE; - /* falls through */ - case DONE: - ret = Z_STREAM_END; - break inf_leave; - case BAD: - ret = Z_DATA_ERROR; - break inf_leave; - case MEM: - return Z_MEM_ERROR; - case SYNC: - /* falls through */ - default: - return Z_STREAM_ERROR; + // 61 + n = w58 ^ w53 ^ w47 ^ w45; + w61 = (n << 1) | (n >>> 31); + t = (w61 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 62 + n = w59 ^ w54 ^ w48 ^ w46; + w62 = (n << 1) | (n >>> 31); + t = (w62 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 63 + n = w60 ^ w55 ^ w49 ^ w47; + w63 = (n << 1) | (n >>> 31); + t = (w63 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 64 + n = w61 ^ w56 ^ w50 ^ w48; + w64 = (n << 1) | (n >>> 31); + t = (w64 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 65 + n = w62 ^ w57 ^ w51 ^ w49; + w65 = (n << 1) | (n >>> 31); + t = (w65 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 66 + n = w63 ^ w58 ^ w52 ^ w50; + w66 = (n << 1) | (n >>> 31); + t = (w66 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 67 + n = w64 ^ w59 ^ w53 ^ w51; + w67 = (n << 1) | (n >>> 31); + t = (w67 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 68 + n = w65 ^ w60 ^ w54 ^ w52; + w68 = (n << 1) | (n >>> 31); + t = (w68 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 69 + n = w66 ^ w61 ^ w55 ^ w53; + w69 = (n << 1) | (n >>> 31); + t = (w69 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 70 + n = w67 ^ w62 ^ w56 ^ w54; + w70 = (n << 1) | (n >>> 31); + t = (w70 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 71 + n = w68 ^ w63 ^ w57 ^ w55; + w71 = (n << 1) | (n >>> 31); + t = (w71 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 72 + n = w69 ^ w64 ^ w58 ^ w56; + w72 = (n << 1) | (n >>> 31); + t = (w72 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 73 + n = w70 ^ w65 ^ w59 ^ w57; + w73 = (n << 1) | (n >>> 31); + t = (w73 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 74 + n = w71 ^ w66 ^ w60 ^ w58; + w74 = (n << 1) | (n >>> 31); + t = (w74 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 75 + n = w72 ^ w67 ^ w61 ^ w59; + w75 = (n << 1) | (n >>> 31); + t = (w75 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 76 + n = w73 ^ w68 ^ w62 ^ w60; + w76 = (n << 1) | (n >>> 31); + t = (w76 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 77 + n = w74 ^ w69 ^ w63 ^ w61; + w77 = (n << 1) | (n >>> 31); + t = (w77 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 78 + n = w75 ^ w70 ^ w64 ^ w62; + w78 = (n << 1) | (n >>> 31); + t = (w78 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 79 + n = w76 ^ w71 ^ w65 ^ w63; + w79 = (n << 1) | (n >>> 31); + t = (w79 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + H0 = ( H0 + a )|0; + H1 = ( H1 + b )|0; + H2 = ( H2 + c )|0; + H3 = ( H3 + d )|0; + H4 = ( H4 + e )|0; + + } + + function _core_heap ( offset ) { + offset = offset|0; + + _core( + HEAP[offset|0]<<24 | HEAP[offset|1]<<16 | HEAP[offset|2]<<8 | HEAP[offset|3], + HEAP[offset|4]<<24 | HEAP[offset|5]<<16 | HEAP[offset|6]<<8 | HEAP[offset|7], + HEAP[offset|8]<<24 | HEAP[offset|9]<<16 | HEAP[offset|10]<<8 | HEAP[offset|11], + HEAP[offset|12]<<24 | HEAP[offset|13]<<16 | HEAP[offset|14]<<8 | HEAP[offset|15], + HEAP[offset|16]<<24 | HEAP[offset|17]<<16 | HEAP[offset|18]<<8 | HEAP[offset|19], + HEAP[offset|20]<<24 | HEAP[offset|21]<<16 | HEAP[offset|22]<<8 | HEAP[offset|23], + HEAP[offset|24]<<24 | HEAP[offset|25]<<16 | HEAP[offset|26]<<8 | HEAP[offset|27], + HEAP[offset|28]<<24 | HEAP[offset|29]<<16 | HEAP[offset|30]<<8 | HEAP[offset|31], + HEAP[offset|32]<<24 | HEAP[offset|33]<<16 | HEAP[offset|34]<<8 | HEAP[offset|35], + HEAP[offset|36]<<24 | HEAP[offset|37]<<16 | HEAP[offset|38]<<8 | HEAP[offset|39], + HEAP[offset|40]<<24 | HEAP[offset|41]<<16 | HEAP[offset|42]<<8 | HEAP[offset|43], + HEAP[offset|44]<<24 | HEAP[offset|45]<<16 | HEAP[offset|46]<<8 | HEAP[offset|47], + HEAP[offset|48]<<24 | HEAP[offset|49]<<16 | HEAP[offset|50]<<8 | HEAP[offset|51], + HEAP[offset|52]<<24 | HEAP[offset|53]<<16 | HEAP[offset|54]<<8 | HEAP[offset|55], + HEAP[offset|56]<<24 | HEAP[offset|57]<<16 | HEAP[offset|58]<<8 | HEAP[offset|59], + HEAP[offset|60]<<24 | HEAP[offset|61]<<16 | HEAP[offset|62]<<8 | HEAP[offset|63] + ); } - } - // inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave" + // offset — multiple of 32 + function _state_to_heap ( output ) { + output = output|0; + + HEAP[output|0] = H0>>>24; + HEAP[output|1] = H0>>>16&255; + HEAP[output|2] = H0>>>8&255; + HEAP[output|3] = H0&255; + HEAP[output|4] = H1>>>24; + HEAP[output|5] = H1>>>16&255; + HEAP[output|6] = H1>>>8&255; + HEAP[output|7] = H1&255; + HEAP[output|8] = H2>>>24; + HEAP[output|9] = H2>>>16&255; + HEAP[output|10] = H2>>>8&255; + HEAP[output|11] = H2&255; + HEAP[output|12] = H3>>>24; + HEAP[output|13] = H3>>>16&255; + HEAP[output|14] = H3>>>8&255; + HEAP[output|15] = H3&255; + HEAP[output|16] = H4>>>24; + HEAP[output|17] = H4>>>16&255; + HEAP[output|18] = H4>>>8&255; + HEAP[output|19] = H4&255; + } + + function reset () { + H0 = 0x67452301; + H1 = 0xefcdab89; + H2 = 0x98badcfe; + H3 = 0x10325476; + H4 = 0xc3d2e1f0; + TOTAL0 = TOTAL1 = 0; + } - /* - Return from inflate(), updating the total counts and the check value. - If there was no progress during the inflate() call, return a buffer - error. Call updatewindow() to create and/or update the window state. - Note: a memory error from inflate() is non-recoverable. - */ + function init ( h0, h1, h2, h3, h4, total0, total1 ) { + h0 = h0|0; + h1 = h1|0; + h2 = h2|0; + h3 = h3|0; + h4 = h4|0; + total0 = total0|0; + total1 = total1|0; - //--- RESTORE() --- - strm.next_out = put; - strm.avail_out = left; - strm.next_in = next; - strm.avail_in = have; - state.hold = hold; - state.bits = bits; - //--- + H0 = h0; + H1 = h1; + H2 = h2; + H3 = h3; + H4 = h4; + TOTAL0 = total0; + TOTAL1 = total1; + } - if (state.wsize || (_out !== strm.avail_out && state.mode < BAD && - (state.mode < CHECK || flush !== Z_FINISH))) { - if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) { - state.mode = MEM; - return Z_MEM_ERROR; + // offset — multiple of 64 + function process ( offset, length ) { + offset = offset|0; + length = length|0; + + var hashed = 0; + + if ( offset & 63 ) + return -1; + + while ( (length|0) >= 64 ) { + _core_heap(offset); + + offset = ( offset + 64 )|0; + length = ( length - 64 )|0; + + hashed = ( hashed + 64 )|0; + } + + TOTAL0 = ( TOTAL0 + hashed )|0; + if ( TOTAL0>>>0 < hashed>>>0 ) TOTAL1 = ( TOTAL1 + 1 )|0; + + return hashed|0; } - } - _in -= strm.avail_in; - _out -= strm.avail_out; - strm.total_in += _in; - strm.total_out += _out; - state.total += _out; - if (state.wrap && _out) { - strm.adler = state.check = /*UPDATE(state.check, strm.next_out - _out, _out);*/ - (state.flags ? crc32(state.check, output, _out, strm.next_out - _out) : adler32(state.check, output, _out, strm.next_out - _out)); - } - strm.data_type = state.bits + (state.last ? 64 : 0) + - (state.mode === TYPE ? 128 : 0) + - (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0); - if (((_in === 0 && _out === 0) || flush === Z_FINISH) && ret === Z_OK) { - ret = Z_BUF_ERROR; - } - return ret; -} -function inflateEnd(strm) { + // offset — multiple of 64 + // output — multiple of 32 + function finish ( offset, length, output ) { + offset = offset|0; + length = length|0; + output = output|0; - if (!strm || !strm.state /*|| strm->zfree == (free_func)0*/) { - return Z_STREAM_ERROR; - } + var hashed = 0, + i = 0; - var state = strm.state; - if (state.window) { - state.window = null; - } - strm.state = null; - return Z_OK; -} + if ( offset & 63 ) + return -1; -function inflateGetHeader(strm, head) { - var state; + if ( ~output ) + if ( output & 31 ) + return -1; - /* check state */ - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR; } + if ( (length|0) >= 64 ) { + hashed = process( offset, length )|0; + if ( (hashed|0) == -1 ) + return -1; - /* save header structure */ - state.head = head; - head.done = false; - return Z_OK; -} + offset = ( offset + hashed )|0; + length = ( length - hashed )|0; + } -function inflateSetDictionary(strm, dictionary) { - var dictLength = dictionary.length; + hashed = ( hashed + length )|0; + TOTAL0 = ( TOTAL0 + length )|0; + if ( TOTAL0>>>0 < length>>>0 ) TOTAL1 = (TOTAL1 + 1)|0; - var state; - var dictid; - var ret; + HEAP[offset|length] = 0x80; - /* check state */ - if (!strm /* == Z_NULL */ || !strm.state /* == Z_NULL */) { return Z_STREAM_ERROR; } - state = strm.state; + if ( (length|0) >= 56 ) { + for ( i = (length+1)|0; (i|0) < 64; i = (i+1)|0 ) + HEAP[offset|i] = 0x00; + _core_heap(offset); - if (state.wrap !== 0 && state.mode !== DICT) { - return Z_STREAM_ERROR; - } + length = 0; - /* check for correct dictionary identifier */ - if (state.mode === DICT) { - dictid = 1; /* adler32(0, null, 0)*/ - /* dictid = adler32(dictid, dictionary, dictLength); */ - dictid = adler32(dictid, dictionary, dictLength, 0); - if (dictid !== state.check) { - return Z_DATA_ERROR; + HEAP[offset|0] = 0; + } + + for ( i = (length+1)|0; (i|0) < 59; i = (i+1)|0 ) + HEAP[offset|i] = 0; + + HEAP[offset|56] = TOTAL1>>>21&255; + HEAP[offset|57] = TOTAL1>>>13&255; + HEAP[offset|58] = TOTAL1>>>5&255; + HEAP[offset|59] = TOTAL1<<3&255 | TOTAL0>>>29; + HEAP[offset|60] = TOTAL0>>>21&255; + HEAP[offset|61] = TOTAL0>>>13&255; + HEAP[offset|62] = TOTAL0>>>5&255; + HEAP[offset|63] = TOTAL0<<3&255; + _core_heap(offset); + + if ( ~output ) + _state_to_heap(output); + + return hashed|0; + } + + function hmac_reset () { + H0 = I0; + H1 = I1; + H2 = I2; + H3 = I3; + H4 = I4; + TOTAL0 = 64; + TOTAL1 = 0; + } + + function _hmac_opad () { + H0 = O0; + H1 = O1; + H2 = O2; + H3 = O3; + H4 = O4; + TOTAL0 = 64; + TOTAL1 = 0; + } + + function hmac_init ( p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15 ) { + p0 = p0|0; + p1 = p1|0; + p2 = p2|0; + p3 = p3|0; + p4 = p4|0; + p5 = p5|0; + p6 = p6|0; + p7 = p7|0; + p8 = p8|0; + p9 = p9|0; + p10 = p10|0; + p11 = p11|0; + p12 = p12|0; + p13 = p13|0; + p14 = p14|0; + p15 = p15|0; + + // opad + reset(); + _core( + p0 ^ 0x5c5c5c5c, + p1 ^ 0x5c5c5c5c, + p2 ^ 0x5c5c5c5c, + p3 ^ 0x5c5c5c5c, + p4 ^ 0x5c5c5c5c, + p5 ^ 0x5c5c5c5c, + p6 ^ 0x5c5c5c5c, + p7 ^ 0x5c5c5c5c, + p8 ^ 0x5c5c5c5c, + p9 ^ 0x5c5c5c5c, + p10 ^ 0x5c5c5c5c, + p11 ^ 0x5c5c5c5c, + p12 ^ 0x5c5c5c5c, + p13 ^ 0x5c5c5c5c, + p14 ^ 0x5c5c5c5c, + p15 ^ 0x5c5c5c5c + ); + O0 = H0; + O1 = H1; + O2 = H2; + O3 = H3; + O4 = H4; + + // ipad + reset(); + _core( + p0 ^ 0x36363636, + p1 ^ 0x36363636, + p2 ^ 0x36363636, + p3 ^ 0x36363636, + p4 ^ 0x36363636, + p5 ^ 0x36363636, + p6 ^ 0x36363636, + p7 ^ 0x36363636, + p8 ^ 0x36363636, + p9 ^ 0x36363636, + p10 ^ 0x36363636, + p11 ^ 0x36363636, + p12 ^ 0x36363636, + p13 ^ 0x36363636, + p14 ^ 0x36363636, + p15 ^ 0x36363636 + ); + I0 = H0; + I1 = H1; + I2 = H2; + I3 = H3; + I4 = H4; + + TOTAL0 = 64; + TOTAL1 = 0; } - } - /* copy dictionary to window using updatewindow(), which will amend the - existing dictionary if appropriate */ - ret = updatewindow(strm, dictionary, dictLength, dictLength); - if (ret) { - state.mode = MEM; - return Z_MEM_ERROR; - } - state.havedict = 1; - // Tracev((stderr, "inflate: dictionary set\n")); - return Z_OK; -} -exports.inflateReset = inflateReset; -exports.inflateReset2 = inflateReset2; -exports.inflateResetKeep = inflateResetKeep; -exports.inflateInit = inflateInit; -exports.inflateInit2 = inflateInit2; -exports.inflate = inflate; -exports.inflateEnd = inflateEnd; -exports.inflateGetHeader = inflateGetHeader; -exports.inflateSetDictionary = inflateSetDictionary; -exports.inflateInfo = 'pako inflate (from Nodeca project)'; + // offset — multiple of 64 + // output — multiple of 32 + function hmac_finish ( offset, length, output ) { + offset = offset|0; + length = length|0; + output = output|0; -/* Not implemented -exports.inflateCopy = inflateCopy; -exports.inflateGetDictionary = inflateGetDictionary; -exports.inflateMark = inflateMark; -exports.inflatePrime = inflatePrime; -exports.inflateSync = inflateSync; -exports.inflateSyncPoint = inflateSyncPoint; -exports.inflateUndermine = inflateUndermine; -*/ + var t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, hashed = 0; -},{"../utils/common":53,"./adler32":55,"./crc32":57,"./inffast":60,"./inftrees":62}],62:[function(require,module,exports){ -'use strict'; + if ( offset & 63 ) + return -1; -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. + if ( ~output ) + if ( output & 31 ) + return -1; -var utils = require('../utils/common'); + hashed = finish( offset, length, -1 )|0; + t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; -var MAXBITS = 15; -var ENOUGH_LENS = 852; -var ENOUGH_DISTS = 592; -//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); + _hmac_opad(); + _core( t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672 ); -var CODES = 0; -var LENS = 1; -var DISTS = 2; + if ( ~output ) + _state_to_heap(output); -var lbase = [ /* Length codes 257..285 base */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 -]; + return hashed|0; + } -var lext = [ /* Length codes 257..285 extra */ - 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78 -]; + // salt is assumed to be already processed + // offset — multiple of 64 + // output — multiple of 32 + function pbkdf2_generate_block ( offset, length, block, count, output ) { + offset = offset|0; + length = length|0; + block = block|0; + count = count|0; + output = output|0; -var dbase = [ /* Distance codes 0..29 base */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577, 0, 0 -]; + var h0 = 0, h1 = 0, h2 = 0, h3 = 0, h4 = 0, + t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0; -var dext = [ /* Distance codes 0..29 extra */ - 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, - 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, - 28, 28, 29, 29, 64, 64 -]; + if ( offset & 63 ) + return -1; -module.exports = function inflate_table(type, lens, lens_index, codes, table, table_index, work, opts) -{ - var bits = opts.bits; - //here = opts.here; /* table entry for duplication */ - - var len = 0; /* a code's length in bits */ - var sym = 0; /* index of code symbols */ - var min = 0, max = 0; /* minimum and maximum code lengths */ - var root = 0; /* number of index bits for root table */ - var curr = 0; /* number of index bits for current table */ - var drop = 0; /* code bits to drop for sub-table */ - var left = 0; /* number of prefix codes available */ - var used = 0; /* code entries in table used */ - var huff = 0; /* Huffman code */ - var incr; /* for incrementing code, index */ - var fill; /* index for replicating entries */ - var low; /* low bits for current root entry */ - var mask; /* mask for low root bits */ - var next; /* next available space in table */ - var base = null; /* base value table to use */ - var base_index = 0; -// var shoextra; /* extra bits table to use */ - var end; /* use base and extra for symbol > end */ - var count = new utils.Buf16(MAXBITS + 1); //[MAXBITS+1]; /* number of codes of each length */ - var offs = new utils.Buf16(MAXBITS + 1); //[MAXBITS+1]; /* offsets in table for each length */ - var extra = null; - var extra_index = 0; - - var here_bits, here_op, here_val; + if ( ~output ) + if ( output & 31 ) + return -1; - /* - Process a set of code lengths to create a canonical Huffman code. The - code lengths are lens[0..codes-1]. Each length corresponds to the - symbols 0..codes-1. The Huffman code is generated by first sorting the - symbols by length from short to long, and retaining the symbol order - for codes with equal lengths. Then the code starts with all zero bits - for the first code of the shortest length, and the codes are integer - increments for the same length, and zeros are appended as the length - increases. For the deflate format, these bits are stored backwards - from their more natural integer increment ordering, and so when the - decoding tables are built in the large loop below, the integer codes - are incremented backwards. + // pad block number into heap + // FIXME probable OOB write + HEAP[(offset+length)|0] = block>>>24; + HEAP[(offset+length+1)|0] = block>>>16&255; + HEAP[(offset+length+2)|0] = block>>>8&255; + HEAP[(offset+length+3)|0] = block&255; - This routine assumes, but does not check, that all of the entries in - lens[] are in the range 0..MAXBITS. The caller must assure this. - 1..MAXBITS is interpreted as that code length. zero means that that - symbol does not occur in this code. + // finish first iteration + hmac_finish( offset, (length+4)|0, -1 )|0; + h0 = t0 = H0, h1 = t1 = H1, h2 = t2 = H2, h3 = t3 = H3, h4 = t4 = H4; + count = (count-1)|0; - The codes are sorted by computing a count of codes for each length, - creating from that a table of starting indices for each length in the - sorted table, and then entering the symbols in order in the sorted - table. The sorted table is work[], with that space being provided by - the caller. + // perform the rest iterations + while ( (count|0) > 0 ) { + hmac_reset(); + _core( t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672 ); + t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; - The length counts are used for other purposes as well, i.e. finding - the minimum and maximum length codes, determining if there are any - codes at all, checking for a valid set of lengths, and looking ahead - at length counts to determine sub-table sizes when building the - decoding tables. - */ + _hmac_opad(); + _core( t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672 ); + t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; - /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ - for (len = 0; len <= MAXBITS; len++) { - count[len] = 0; - } - for (sym = 0; sym < codes; sym++) { - count[lens[lens_index + sym]]++; - } + h0 = h0 ^ H0; + h1 = h1 ^ H1; + h2 = h2 ^ H2; + h3 = h3 ^ H3; + h4 = h4 ^ H4; - /* bound code lengths, force root to be within code lengths */ - root = bits; - for (max = MAXBITS; max >= 1; max--) { - if (count[max] !== 0) { break; } - } - if (root > max) { - root = max; - } - if (max === 0) { /* no symbols to code at all */ - //table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */ - //table.bits[opts.table_index] = 1; //here.bits = (var char)1; - //table.val[opts.table_index++] = 0; //here.val = (var short)0; - table[table_index++] = (1 << 24) | (64 << 16) | 0; + count = (count-1)|0; + } + H0 = h0; + H1 = h1; + H2 = h2; + H3 = h3; + H4 = h4; - //table.op[opts.table_index] = 64; - //table.bits[opts.table_index] = 1; - //table.val[opts.table_index++] = 0; - table[table_index++] = (1 << 24) | (64 << 16) | 0; + if ( ~output ) + _state_to_heap(output); - opts.bits = 1; - return 0; /* no symbols, but wait for decoding to report error */ - } - for (min = 1; min < max; min++) { - if (count[min] !== 0) { break; } - } - if (root < min) { - root = min; - } + return 0; + } - /* check for an over-subscribed or incomplete set of lengths */ - left = 1; - for (len = 1; len <= MAXBITS; len++) { - left <<= 1; - left -= count[len]; - if (left < 0) { - return -1; - } /* over-subscribed */ - } - if (left > 0 && (type === CODES || max !== 1)) { - return -1; /* incomplete set */ - } + return { + // SHA1 + reset: reset, + init: init, + process: process, + finish: finish, - /* generate offsets into symbol table for each length for sorting */ - offs[1] = 0; - for (len = 1; len < MAXBITS; len++) { - offs[len + 1] = offs[len] + count[len]; - } + // HMAC-SHA1 + hmac_reset: hmac_reset, + hmac_init: hmac_init, + hmac_finish: hmac_finish, - /* sort symbols by length, by symbol order within each length */ - for (sym = 0; sym < codes; sym++) { - if (lens[lens_index + sym] !== 0) { - work[offs[lens[lens_index + sym]]++] = sym; + // PBKDF2-HMAC-SHA1 + pbkdf2_generate_block: pbkdf2_generate_block } - } +}; - /* - Create and fill in decoding tables. In this loop, the table being - filled is at next and has curr index bits. The code being used is huff - with length len. That code is converted to an index by dropping drop - bits off of the bottom. For codes where len is less than drop + curr, - those top drop + curr - len bits are incremented through all values to - fill the table with replicated entries. +class Hash { + constructor() { + this.pos = 0; + this.len = 0; + } + reset() { + const { asm } = this.acquire_asm(); + this.result = null; + this.pos = 0; + this.len = 0; + asm.reset(); + return this; + } + process(data) { + if (this.result !== null) + throw new IllegalStateError('state must be reset before processing new data'); + const { asm, heap } = this.acquire_asm(); + let hpos = this.pos; + let hlen = this.len; + let dpos = 0; + let dlen = data.length; + let wlen = 0; + while (dlen > 0) { + wlen = _heap_write(heap, hpos + hlen, data, dpos, dlen); + hlen += wlen; + dpos += wlen; + dlen -= wlen; + wlen = asm.process(hpos, hlen); + hpos += wlen; + hlen -= wlen; + if (!hlen) + hpos = 0; + } + this.pos = hpos; + this.len = hlen; + return this; + } + finish() { + if (this.result !== null) + throw new IllegalStateError('state must be reset before processing new data'); + const { asm, heap } = this.acquire_asm(); + asm.finish(this.pos, this.len, 0); + this.result = new Uint8Array(this.HASH_SIZE); + this.result.set(heap.subarray(0, this.HASH_SIZE)); + this.pos = 0; + this.len = 0; + this.release_asm(); + return this; + } +} - root is the number of index bits for the root table. When len exceeds - root, sub-tables are created pointed to by the root entry with an index - of the low root bits of huff. This is saved in low to check for when a - new sub-table should be started. drop is zero when the root table is - being filled, and drop is root when sub-tables are being filled. +const _sha1_block_size = 64; +const _sha1_hash_size = 20; +const heap_pool$1 = []; +const asm_pool$1 = []; +class Sha1 extends Hash { + constructor() { + super(); + this.NAME = 'sha1'; + this.BLOCK_SIZE = _sha1_block_size; + this.HASH_SIZE = _sha1_hash_size; + this.acquire_asm(); + } + acquire_asm() { + if (this.heap === undefined || this.asm === undefined) { + this.heap = heap_pool$1.pop() || _heap_init(); + this.asm = asm_pool$1.pop() || sha1_asm({ Uint8Array: Uint8Array }, null, this.heap.buffer); + this.reset(); + } + return { heap: this.heap, asm: this.asm }; + } + release_asm() { + if (this.heap !== undefined && this.asm !== undefined) { + heap_pool$1.push(this.heap); + asm_pool$1.push(this.asm); + } + this.heap = undefined; + this.asm = undefined; + } + static bytes(data) { + return new Sha1().process(data).finish().result; + } +} +Sha1.NAME = 'sha1'; +Sha1.heap_pool = []; +Sha1.asm_pool = []; +Sha1.asm_function = sha1_asm; - When a new sub-table is needed, it is necessary to look ahead in the - code lengths to determine what size sub-table is needed. The length - counts are used for this, and so count[] is decremented as codes are - entered in the tables. +var sha256_asm = function ( stdlib, foreign, buffer ) { + "use asm"; - used keeps track of how many table entries have been allocated from the - provided *table space. It is checked for LENS and DIST tables against - the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in - the initial root table size constants. See the comments in inftrees.h - for more information. + // SHA256 state + var H0 = 0, H1 = 0, H2 = 0, H3 = 0, H4 = 0, H5 = 0, H6 = 0, H7 = 0, + TOTAL0 = 0, TOTAL1 = 0; - sym increments through all symbols, and the loop terminates when - all codes of length max, i.e. all codes, have been processed. This - routine permits incomplete codes, so another loop after this one fills - in the rest of the decoding tables with invalid code markers. - */ + // HMAC state + var I0 = 0, I1 = 0, I2 = 0, I3 = 0, I4 = 0, I5 = 0, I6 = 0, I7 = 0, + O0 = 0, O1 = 0, O2 = 0, O3 = 0, O4 = 0, O5 = 0, O6 = 0, O7 = 0; - /* set up for code type */ - // poor man optimization - use if-else instead of switch, - // to avoid deopts in old v8 - if (type === CODES) { - base = extra = work; /* dummy value--not used */ - end = 19; - - } else if (type === LENS) { - base = lbase; - base_index -= 257; - extra = lext; - extra_index -= 257; - end = 256; - - } else { /* DISTS */ - base = dbase; - extra = dext; - end = -1; - } - - /* initialize opts for loop */ - huff = 0; /* starting code */ - sym = 0; /* starting code symbol */ - len = min; /* starting code length */ - next = table_index; /* current table to fill in */ - curr = root; /* current table index bits */ - drop = 0; /* current bits to drop from code for index */ - low = -1; /* trigger new sub-table when len > root */ - used = 1 << root; /* use root table entries */ - mask = used - 1; /* mask for comparing low */ - - /* check available table space */ - if ((type === LENS && used > ENOUGH_LENS) || - (type === DISTS && used > ENOUGH_DISTS)) { - return 1; - } + // I/O buffer + var HEAP = new stdlib.Uint8Array(buffer); - /* process all codes and make table entries */ - for (;;) { - /* create table entry */ - here_bits = len - drop; - if (work[sym] < end) { - here_op = 0; - here_val = work[sym]; - } - else if (work[sym] > end) { - here_op = extra[extra_index + work[sym]]; - here_val = base[base_index + work[sym]]; - } - else { - here_op = 32 + 64; /* end of block */ - here_val = 0; - } + function _core ( w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15 ) { + w0 = w0|0; + w1 = w1|0; + w2 = w2|0; + w3 = w3|0; + w4 = w4|0; + w5 = w5|0; + w6 = w6|0; + w7 = w7|0; + w8 = w8|0; + w9 = w9|0; + w10 = w10|0; + w11 = w11|0; + w12 = w12|0; + w13 = w13|0; + w14 = w14|0; + w15 = w15|0; + + var a = 0, b = 0, c = 0, d = 0, e = 0, f = 0, g = 0, h = 0; - /* replicate for those indices with low len bits equal to huff */ - incr = 1 << (len - drop); - fill = 1 << curr; - min = fill; /* save offset to next table */ - do { - fill -= incr; - table[next + (huff >> drop) + fill] = (here_bits << 24) | (here_op << 16) | here_val |0; - } while (fill !== 0); - - /* backwards increment the len-bit code huff */ - incr = 1 << (len - 1); - while (huff & incr) { - incr >>= 1; - } - if (incr !== 0) { - huff &= incr - 1; - huff += incr; - } else { - huff = 0; - } + a = H0; + b = H1; + c = H2; + d = H3; + e = H4; + f = H5; + g = H6; + h = H7; + + // 0 + h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x428a2f98 )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - /* go to next symbol, update count, len */ - sym++; - if (--count[len] === 0) { - if (len === max) { break; } - len = lens[lens_index + work[sym]]; - } + // 1 + g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x71374491 )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - /* create new sub-table if needed */ - if (len > root && (huff & mask) !== low) { - /* if first time, transition to sub-tables */ - if (drop === 0) { - drop = root; - } + // 2 + f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0xb5c0fbcf )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - /* increment past last table */ - next += min; /* here min is 1 << curr */ + // 3 + e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0xe9b5dba5 )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - /* determine length of next table */ - curr = len - drop; - left = 1 << curr; - while (curr + drop < max) { - left -= count[curr + drop]; - if (left <= 0) { break; } - curr++; - left <<= 1; - } + // 4 + d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x3956c25b )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - /* check for enough space */ - used += 1 << curr; - if ((type === LENS && used > ENOUGH_LENS) || - (type === DISTS && used > ENOUGH_DISTS)) { - return 1; - } + // 5 + c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x59f111f1 )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - /* point entry in root table to sub-table */ - low = huff & mask; - /*table.op[low] = curr; - table.bits[low] = root; - table.val[low] = next - opts.table_index;*/ - table[low] = (root << 24) | (curr << 16) | (next - table_index) |0; - } - } + // 6 + b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x923f82a4 )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - /* fill in remaining table entry if code is incomplete (guaranteed to have - at most one remaining entry, since if the code is incomplete, the - maximum code length that was allowed to get this far is one bit) */ - if (huff !== 0) { - //table.op[next + huff] = 64; /* invalid code marker */ - //table.bits[next + huff] = len - drop; - //table.val[next + huff] = 0; - table[next + huff] = ((len - drop) << 24) | (64 << 16) |0; - } + // 7 + a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0xab1c5ed5 )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - /* set return parameters */ - //opts.table_index += used; - opts.bits = root; - return 0; -}; + // 8 + h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0xd807aa98 )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; -},{"../utils/common":53}],63:[function(require,module,exports){ -'use strict'; + // 9 + g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x12835b01 )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. + // 10 + f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x243185be )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; + + // 11 + e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x550c7dc3 )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; + + // 12 + d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x72be5d74 )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; + + // 13 + c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x80deb1fe )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; + + // 14 + b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x9bdc06a7 )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; -module.exports = { - 2: 'need dictionary', /* Z_NEED_DICT 2 */ - 1: 'stream end', /* Z_STREAM_END 1 */ - 0: '', /* Z_OK 0 */ - '-1': 'file error', /* Z_ERRNO (-1) */ - '-2': 'stream error', /* Z_STREAM_ERROR (-2) */ - '-3': 'data error', /* Z_DATA_ERROR (-3) */ - '-4': 'insufficient memory', /* Z_MEM_ERROR (-4) */ - '-5': 'buffer error', /* Z_BUF_ERROR (-5) */ - '-6': 'incompatible version' /* Z_VERSION_ERROR (-6) */ -}; + // 15 + a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0xc19bf174 )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; -},{}],64:[function(require,module,exports){ -'use strict'; + // 16 + w0 = ( ( w1>>>7 ^ w1>>>18 ^ w1>>>3 ^ w1<<25 ^ w1<<14 ) + ( w14>>>17 ^ w14>>>19 ^ w14>>>10 ^ w14<<15 ^ w14<<13 ) + w0 + w9 )|0; + h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0xe49b69c1 )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. + // 17 + w1 = ( ( w2>>>7 ^ w2>>>18 ^ w2>>>3 ^ w2<<25 ^ w2<<14 ) + ( w15>>>17 ^ w15>>>19 ^ w15>>>10 ^ w15<<15 ^ w15<<13 ) + w1 + w10 )|0; + g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0xefbe4786 )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; -var utils = require('../utils/common'); + // 18 + w2 = ( ( w3>>>7 ^ w3>>>18 ^ w3>>>3 ^ w3<<25 ^ w3<<14 ) + ( w0>>>17 ^ w0>>>19 ^ w0>>>10 ^ w0<<15 ^ w0<<13 ) + w2 + w11 )|0; + f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x0fc19dc6 )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; -/* Public constants ==========================================================*/ -/* ===========================================================================*/ + // 19 + w3 = ( ( w4>>>7 ^ w4>>>18 ^ w4>>>3 ^ w4<<25 ^ w4<<14 ) + ( w1>>>17 ^ w1>>>19 ^ w1>>>10 ^ w1<<15 ^ w1<<13 ) + w3 + w12 )|0; + e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x240ca1cc )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; + // 20 + w4 = ( ( w5>>>7 ^ w5>>>18 ^ w5>>>3 ^ w5<<25 ^ w5<<14 ) + ( w2>>>17 ^ w2>>>19 ^ w2>>>10 ^ w2<<15 ^ w2<<13 ) + w4 + w13 )|0; + d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x2de92c6f )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; -//var Z_FILTERED = 1; -//var Z_HUFFMAN_ONLY = 2; -//var Z_RLE = 3; -var Z_FIXED = 4; -//var Z_DEFAULT_STRATEGY = 0; + // 21 + w5 = ( ( w6>>>7 ^ w6>>>18 ^ w6>>>3 ^ w6<<25 ^ w6<<14 ) + ( w3>>>17 ^ w3>>>19 ^ w3>>>10 ^ w3<<15 ^ w3<<13 ) + w5 + w14 )|0; + c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x4a7484aa )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; -/* Possible values of the data_type field (though see inflate()) */ -var Z_BINARY = 0; -var Z_TEXT = 1; -//var Z_ASCII = 1; // = Z_TEXT -var Z_UNKNOWN = 2; + // 22 + w6 = ( ( w7>>>7 ^ w7>>>18 ^ w7>>>3 ^ w7<<25 ^ w7<<14 ) + ( w4>>>17 ^ w4>>>19 ^ w4>>>10 ^ w4<<15 ^ w4<<13 ) + w6 + w15 )|0; + b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x5cb0a9dc )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; -/*============================================================================*/ + // 23 + w7 = ( ( w8>>>7 ^ w8>>>18 ^ w8>>>3 ^ w8<<25 ^ w8<<14 ) + ( w5>>>17 ^ w5>>>19 ^ w5>>>10 ^ w5<<15 ^ w5<<13 ) + w7 + w0 )|0; + a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x76f988da )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; + // 24 + w8 = ( ( w9>>>7 ^ w9>>>18 ^ w9>>>3 ^ w9<<25 ^ w9<<14 ) + ( w6>>>17 ^ w6>>>19 ^ w6>>>10 ^ w6<<15 ^ w6<<13 ) + w8 + w1 )|0; + h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x983e5152 )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; -function zero(buf) { var len = buf.length; while (--len >= 0) { buf[len] = 0; } } + // 25 + w9 = ( ( w10>>>7 ^ w10>>>18 ^ w10>>>3 ^ w10<<25 ^ w10<<14 ) + ( w7>>>17 ^ w7>>>19 ^ w7>>>10 ^ w7<<15 ^ w7<<13 ) + w9 + w2 )|0; + g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0xa831c66d )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; -// From zutil.h + // 26 + w10 = ( ( w11>>>7 ^ w11>>>18 ^ w11>>>3 ^ w11<<25 ^ w11<<14 ) + ( w8>>>17 ^ w8>>>19 ^ w8>>>10 ^ w8<<15 ^ w8<<13 ) + w10 + w3 )|0; + f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0xb00327c8 )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; -var STORED_BLOCK = 0; -var STATIC_TREES = 1; -var DYN_TREES = 2; -/* The three kinds of block type */ + // 27 + w11 = ( ( w12>>>7 ^ w12>>>18 ^ w12>>>3 ^ w12<<25 ^ w12<<14 ) + ( w9>>>17 ^ w9>>>19 ^ w9>>>10 ^ w9<<15 ^ w9<<13 ) + w11 + w4 )|0; + e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0xbf597fc7 )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; -var MIN_MATCH = 3; -var MAX_MATCH = 258; -/* The minimum and maximum match lengths */ + // 28 + w12 = ( ( w13>>>7 ^ w13>>>18 ^ w13>>>3 ^ w13<<25 ^ w13<<14 ) + ( w10>>>17 ^ w10>>>19 ^ w10>>>10 ^ w10<<15 ^ w10<<13 ) + w12 + w5 )|0; + d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0xc6e00bf3 )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; -// From deflate.h -/* =========================================================================== - * Internal compression state. - */ + // 29 + w13 = ( ( w14>>>7 ^ w14>>>18 ^ w14>>>3 ^ w14<<25 ^ w14<<14 ) + ( w11>>>17 ^ w11>>>19 ^ w11>>>10 ^ w11<<15 ^ w11<<13 ) + w13 + w6 )|0; + c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0xd5a79147 )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; -var LENGTH_CODES = 29; -/* number of length codes, not counting the special END_BLOCK code */ + // 30 + w14 = ( ( w15>>>7 ^ w15>>>18 ^ w15>>>3 ^ w15<<25 ^ w15<<14 ) + ( w12>>>17 ^ w12>>>19 ^ w12>>>10 ^ w12<<15 ^ w12<<13 ) + w14 + w7 )|0; + b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x06ca6351 )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; -var LITERALS = 256; -/* number of literal bytes 0..255 */ + // 31 + w15 = ( ( w0>>>7 ^ w0>>>18 ^ w0>>>3 ^ w0<<25 ^ w0<<14 ) + ( w13>>>17 ^ w13>>>19 ^ w13>>>10 ^ w13<<15 ^ w13<<13 ) + w15 + w8 )|0; + a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x14292967 )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; -var L_CODES = LITERALS + 1 + LENGTH_CODES; -/* number of Literal or Length codes, including the END_BLOCK code */ + // 32 + w0 = ( ( w1>>>7 ^ w1>>>18 ^ w1>>>3 ^ w1<<25 ^ w1<<14 ) + ( w14>>>17 ^ w14>>>19 ^ w14>>>10 ^ w14<<15 ^ w14<<13 ) + w0 + w9 )|0; + h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x27b70a85 )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; -var D_CODES = 30; -/* number of distance codes */ + // 33 + w1 = ( ( w2>>>7 ^ w2>>>18 ^ w2>>>3 ^ w2<<25 ^ w2<<14 ) + ( w15>>>17 ^ w15>>>19 ^ w15>>>10 ^ w15<<15 ^ w15<<13 ) + w1 + w10 )|0; + g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x2e1b2138 )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; -var BL_CODES = 19; -/* number of codes used to transfer the bit lengths */ + // 34 + w2 = ( ( w3>>>7 ^ w3>>>18 ^ w3>>>3 ^ w3<<25 ^ w3<<14 ) + ( w0>>>17 ^ w0>>>19 ^ w0>>>10 ^ w0<<15 ^ w0<<13 ) + w2 + w11 )|0; + f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x4d2c6dfc )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; -var HEAP_SIZE = 2 * L_CODES + 1; -/* maximum heap size */ + // 35 + w3 = ( ( w4>>>7 ^ w4>>>18 ^ w4>>>3 ^ w4<<25 ^ w4<<14 ) + ( w1>>>17 ^ w1>>>19 ^ w1>>>10 ^ w1<<15 ^ w1<<13 ) + w3 + w12 )|0; + e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x53380d13 )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; -var MAX_BITS = 15; -/* All codes must not exceed MAX_BITS bits */ + // 36 + w4 = ( ( w5>>>7 ^ w5>>>18 ^ w5>>>3 ^ w5<<25 ^ w5<<14 ) + ( w2>>>17 ^ w2>>>19 ^ w2>>>10 ^ w2<<15 ^ w2<<13 ) + w4 + w13 )|0; + d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x650a7354 )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; -var Buf_size = 16; -/* size of bit buffer in bi_buf */ + // 37 + w5 = ( ( w6>>>7 ^ w6>>>18 ^ w6>>>3 ^ w6<<25 ^ w6<<14 ) + ( w3>>>17 ^ w3>>>19 ^ w3>>>10 ^ w3<<15 ^ w3<<13 ) + w5 + w14 )|0; + c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x766a0abb )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; + // 38 + w6 = ( ( w7>>>7 ^ w7>>>18 ^ w7>>>3 ^ w7<<25 ^ w7<<14 ) + ( w4>>>17 ^ w4>>>19 ^ w4>>>10 ^ w4<<15 ^ w4<<13 ) + w6 + w15 )|0; + b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x81c2c92e )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; -/* =========================================================================== - * Constants - */ + // 39 + w7 = ( ( w8>>>7 ^ w8>>>18 ^ w8>>>3 ^ w8<<25 ^ w8<<14 ) + ( w5>>>17 ^ w5>>>19 ^ w5>>>10 ^ w5<<15 ^ w5<<13 ) + w7 + w0 )|0; + a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x92722c85 )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; -var MAX_BL_BITS = 7; -/* Bit length codes must not exceed MAX_BL_BITS bits */ + // 40 + w8 = ( ( w9>>>7 ^ w9>>>18 ^ w9>>>3 ^ w9<<25 ^ w9<<14 ) + ( w6>>>17 ^ w6>>>19 ^ w6>>>10 ^ w6<<15 ^ w6<<13 ) + w8 + w1 )|0; + h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0xa2bfe8a1 )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; -var END_BLOCK = 256; -/* end of block literal code */ + // 41 + w9 = ( ( w10>>>7 ^ w10>>>18 ^ w10>>>3 ^ w10<<25 ^ w10<<14 ) + ( w7>>>17 ^ w7>>>19 ^ w7>>>10 ^ w7<<15 ^ w7<<13 ) + w9 + w2 )|0; + g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0xa81a664b )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; -var REP_3_6 = 16; -/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + // 42 + w10 = ( ( w11>>>7 ^ w11>>>18 ^ w11>>>3 ^ w11<<25 ^ w11<<14 ) + ( w8>>>17 ^ w8>>>19 ^ w8>>>10 ^ w8<<15 ^ w8<<13 ) + w10 + w3 )|0; + f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0xc24b8b70 )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; -var REPZ_3_10 = 17; -/* repeat a zero length 3-10 times (3 bits of repeat count) */ + // 43 + w11 = ( ( w12>>>7 ^ w12>>>18 ^ w12>>>3 ^ w12<<25 ^ w12<<14 ) + ( w9>>>17 ^ w9>>>19 ^ w9>>>10 ^ w9<<15 ^ w9<<13 ) + w11 + w4 )|0; + e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0xc76c51a3 )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; -var REPZ_11_138 = 18; -/* repeat a zero length 11-138 times (7 bits of repeat count) */ + // 44 + w12 = ( ( w13>>>7 ^ w13>>>18 ^ w13>>>3 ^ w13<<25 ^ w13<<14 ) + ( w10>>>17 ^ w10>>>19 ^ w10>>>10 ^ w10<<15 ^ w10<<13 ) + w12 + w5 )|0; + d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0xd192e819 )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; -/* eslint-disable comma-spacing,array-bracket-spacing */ -var extra_lbits = /* extra bits for each length code */ - [0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0]; + // 45 + w13 = ( ( w14>>>7 ^ w14>>>18 ^ w14>>>3 ^ w14<<25 ^ w14<<14 ) + ( w11>>>17 ^ w11>>>19 ^ w11>>>10 ^ w11<<15 ^ w11<<13 ) + w13 + w6 )|0; + c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0xd6990624 )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; -var extra_dbits = /* extra bits for each distance code */ - [0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13]; + // 46 + w14 = ( ( w15>>>7 ^ w15>>>18 ^ w15>>>3 ^ w15<<25 ^ w15<<14 ) + ( w12>>>17 ^ w12>>>19 ^ w12>>>10 ^ w12<<15 ^ w12<<13 ) + w14 + w7 )|0; + b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0xf40e3585 )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; -var extra_blbits = /* extra bits for each bit length code */ - [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7]; + // 47 + w15 = ( ( w0>>>7 ^ w0>>>18 ^ w0>>>3 ^ w0<<25 ^ w0<<14 ) + ( w13>>>17 ^ w13>>>19 ^ w13>>>10 ^ w13<<15 ^ w13<<13 ) + w15 + w8 )|0; + a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x106aa070 )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; -var bl_order = - [16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]; -/* eslint-enable comma-spacing,array-bracket-spacing */ + // 48 + w0 = ( ( w1>>>7 ^ w1>>>18 ^ w1>>>3 ^ w1<<25 ^ w1<<14 ) + ( w14>>>17 ^ w14>>>19 ^ w14>>>10 ^ w14<<15 ^ w14<<13 ) + w0 + w9 )|0; + h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x19a4c116 )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; -/* The lengths of the bit length codes are sent in order of decreasing - * probability, to avoid transmitting the lengths for unused bit length codes. - */ + // 49 + w1 = ( ( w2>>>7 ^ w2>>>18 ^ w2>>>3 ^ w2<<25 ^ w2<<14 ) + ( w15>>>17 ^ w15>>>19 ^ w15>>>10 ^ w15<<15 ^ w15<<13 ) + w1 + w10 )|0; + g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x1e376c08 )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; -/* =========================================================================== - * Local data. These are initialized only once. - */ + // 50 + w2 = ( ( w3>>>7 ^ w3>>>18 ^ w3>>>3 ^ w3<<25 ^ w3<<14 ) + ( w0>>>17 ^ w0>>>19 ^ w0>>>10 ^ w0<<15 ^ w0<<13 ) + w2 + w11 )|0; + f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x2748774c )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; -// We pre-fill arrays with 0 to avoid uninitialized gaps + // 51 + w3 = ( ( w4>>>7 ^ w4>>>18 ^ w4>>>3 ^ w4<<25 ^ w4<<14 ) + ( w1>>>17 ^ w1>>>19 ^ w1>>>10 ^ w1<<15 ^ w1<<13 ) + w3 + w12 )|0; + e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x34b0bcb5 )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; -var DIST_CODE_LEN = 512; /* see definition of array dist_code below */ + // 52 + w4 = ( ( w5>>>7 ^ w5>>>18 ^ w5>>>3 ^ w5<<25 ^ w5<<14 ) + ( w2>>>17 ^ w2>>>19 ^ w2>>>10 ^ w2<<15 ^ w2<<13 ) + w4 + w13 )|0; + d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x391c0cb3 )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; -// !!!! Use flat array instead of structure, Freq = i*2, Len = i*2+1 -var static_ltree = new Array((L_CODES + 2) * 2); -zero(static_ltree); -/* The static literal tree. Since the bit lengths are imposed, there is no - * need for the L_CODES extra codes used during heap construction. However - * The codes 286 and 287 are needed to build a canonical tree (see _tr_init - * below). - */ + // 53 + w5 = ( ( w6>>>7 ^ w6>>>18 ^ w6>>>3 ^ w6<<25 ^ w6<<14 ) + ( w3>>>17 ^ w3>>>19 ^ w3>>>10 ^ w3<<15 ^ w3<<13 ) + w5 + w14 )|0; + c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x4ed8aa4a )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; -var static_dtree = new Array(D_CODES * 2); -zero(static_dtree); -/* The static distance tree. (Actually a trivial tree since all codes use - * 5 bits.) - */ + // 54 + w6 = ( ( w7>>>7 ^ w7>>>18 ^ w7>>>3 ^ w7<<25 ^ w7<<14 ) + ( w4>>>17 ^ w4>>>19 ^ w4>>>10 ^ w4<<15 ^ w4<<13 ) + w6 + w15 )|0; + b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x5b9cca4f )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; -var _dist_code = new Array(DIST_CODE_LEN); -zero(_dist_code); -/* Distance codes. The first 256 values correspond to the distances - * 3 .. 258, the last 256 values correspond to the top 8 bits of - * the 15 bit distances. - */ + // 55 + w7 = ( ( w8>>>7 ^ w8>>>18 ^ w8>>>3 ^ w8<<25 ^ w8<<14 ) + ( w5>>>17 ^ w5>>>19 ^ w5>>>10 ^ w5<<15 ^ w5<<13 ) + w7 + w0 )|0; + a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x682e6ff3 )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; -var _length_code = new Array(MAX_MATCH - MIN_MATCH + 1); -zero(_length_code); -/* length code for each normalized match length (0 == MIN_MATCH) */ + // 56 + w8 = ( ( w9>>>7 ^ w9>>>18 ^ w9>>>3 ^ w9<<25 ^ w9<<14 ) + ( w6>>>17 ^ w6>>>19 ^ w6>>>10 ^ w6<<15 ^ w6<<13 ) + w8 + w1 )|0; + h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x748f82ee )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; -var base_length = new Array(LENGTH_CODES); -zero(base_length); -/* First normalized length for each code (0 = MIN_MATCH) */ + // 57 + w9 = ( ( w10>>>7 ^ w10>>>18 ^ w10>>>3 ^ w10<<25 ^ w10<<14 ) + ( w7>>>17 ^ w7>>>19 ^ w7>>>10 ^ w7<<15 ^ w7<<13 ) + w9 + w2 )|0; + g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x78a5636f )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; -var base_dist = new Array(D_CODES); -zero(base_dist); -/* First normalized distance for each code (0 = distance of 1) */ + // 58 + w10 = ( ( w11>>>7 ^ w11>>>18 ^ w11>>>3 ^ w11<<25 ^ w11<<14 ) + ( w8>>>17 ^ w8>>>19 ^ w8>>>10 ^ w8<<15 ^ w8<<13 ) + w10 + w3 )|0; + f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x84c87814 )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; + + // 59 + w11 = ( ( w12>>>7 ^ w12>>>18 ^ w12>>>3 ^ w12<<25 ^ w12<<14 ) + ( w9>>>17 ^ w9>>>19 ^ w9>>>10 ^ w9<<15 ^ w9<<13 ) + w11 + w4 )|0; + e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x8cc70208 )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; + // 60 + w12 = ( ( w13>>>7 ^ w13>>>18 ^ w13>>>3 ^ w13<<25 ^ w13<<14 ) + ( w10>>>17 ^ w10>>>19 ^ w10>>>10 ^ w10<<15 ^ w10<<13 ) + w12 + w5 )|0; + d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x90befffa )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; -function StaticTreeDesc(static_tree, extra_bits, extra_base, elems, max_length) { + // 61 + w13 = ( ( w14>>>7 ^ w14>>>18 ^ w14>>>3 ^ w14<<25 ^ w14<<14 ) + ( w11>>>17 ^ w11>>>19 ^ w11>>>10 ^ w11<<15 ^ w11<<13 ) + w13 + w6 )|0; + c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0xa4506ceb )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - this.static_tree = static_tree; /* static tree or NULL */ - this.extra_bits = extra_bits; /* extra bits for each code or NULL */ - this.extra_base = extra_base; /* base index for extra_bits */ - this.elems = elems; /* max number of elements in the tree */ - this.max_length = max_length; /* max bit length for the codes */ + // 62 + w14 = ( ( w15>>>7 ^ w15>>>18 ^ w15>>>3 ^ w15<<25 ^ w15<<14 ) + ( w12>>>17 ^ w12>>>19 ^ w12>>>10 ^ w12<<15 ^ w12<<13 ) + w14 + w7 )|0; + b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0xbef9a3f7 )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - // show if `static_tree` has data or dummy - needed for monomorphic objects - this.has_stree = static_tree && static_tree.length; -} + // 63 + w15 = ( ( w0>>>7 ^ w0>>>18 ^ w0>>>3 ^ w0<<25 ^ w0<<14 ) + ( w13>>>17 ^ w13>>>19 ^ w13>>>10 ^ w13<<15 ^ w13<<13 ) + w15 + w8 )|0; + a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0xc67178f2 )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; + + H0 = ( H0 + a )|0; + H1 = ( H1 + b )|0; + H2 = ( H2 + c )|0; + H3 = ( H3 + d )|0; + H4 = ( H4 + e )|0; + H5 = ( H5 + f )|0; + H6 = ( H6 + g )|0; + H7 = ( H7 + h )|0; + } + + function _core_heap ( offset ) { + offset = offset|0; + + _core( + HEAP[offset|0]<<24 | HEAP[offset|1]<<16 | HEAP[offset|2]<<8 | HEAP[offset|3], + HEAP[offset|4]<<24 | HEAP[offset|5]<<16 | HEAP[offset|6]<<8 | HEAP[offset|7], + HEAP[offset|8]<<24 | HEAP[offset|9]<<16 | HEAP[offset|10]<<8 | HEAP[offset|11], + HEAP[offset|12]<<24 | HEAP[offset|13]<<16 | HEAP[offset|14]<<8 | HEAP[offset|15], + HEAP[offset|16]<<24 | HEAP[offset|17]<<16 | HEAP[offset|18]<<8 | HEAP[offset|19], + HEAP[offset|20]<<24 | HEAP[offset|21]<<16 | HEAP[offset|22]<<8 | HEAP[offset|23], + HEAP[offset|24]<<24 | HEAP[offset|25]<<16 | HEAP[offset|26]<<8 | HEAP[offset|27], + HEAP[offset|28]<<24 | HEAP[offset|29]<<16 | HEAP[offset|30]<<8 | HEAP[offset|31], + HEAP[offset|32]<<24 | HEAP[offset|33]<<16 | HEAP[offset|34]<<8 | HEAP[offset|35], + HEAP[offset|36]<<24 | HEAP[offset|37]<<16 | HEAP[offset|38]<<8 | HEAP[offset|39], + HEAP[offset|40]<<24 | HEAP[offset|41]<<16 | HEAP[offset|42]<<8 | HEAP[offset|43], + HEAP[offset|44]<<24 | HEAP[offset|45]<<16 | HEAP[offset|46]<<8 | HEAP[offset|47], + HEAP[offset|48]<<24 | HEAP[offset|49]<<16 | HEAP[offset|50]<<8 | HEAP[offset|51], + HEAP[offset|52]<<24 | HEAP[offset|53]<<16 | HEAP[offset|54]<<8 | HEAP[offset|55], + HEAP[offset|56]<<24 | HEAP[offset|57]<<16 | HEAP[offset|58]<<8 | HEAP[offset|59], + HEAP[offset|60]<<24 | HEAP[offset|61]<<16 | HEAP[offset|62]<<8 | HEAP[offset|63] + ); + } + // offset — multiple of 32 + function _state_to_heap ( output ) { + output = output|0; + + HEAP[output|0] = H0>>>24; + HEAP[output|1] = H0>>>16&255; + HEAP[output|2] = H0>>>8&255; + HEAP[output|3] = H0&255; + HEAP[output|4] = H1>>>24; + HEAP[output|5] = H1>>>16&255; + HEAP[output|6] = H1>>>8&255; + HEAP[output|7] = H1&255; + HEAP[output|8] = H2>>>24; + HEAP[output|9] = H2>>>16&255; + HEAP[output|10] = H2>>>8&255; + HEAP[output|11] = H2&255; + HEAP[output|12] = H3>>>24; + HEAP[output|13] = H3>>>16&255; + HEAP[output|14] = H3>>>8&255; + HEAP[output|15] = H3&255; + HEAP[output|16] = H4>>>24; + HEAP[output|17] = H4>>>16&255; + HEAP[output|18] = H4>>>8&255; + HEAP[output|19] = H4&255; + HEAP[output|20] = H5>>>24; + HEAP[output|21] = H5>>>16&255; + HEAP[output|22] = H5>>>8&255; + HEAP[output|23] = H5&255; + HEAP[output|24] = H6>>>24; + HEAP[output|25] = H6>>>16&255; + HEAP[output|26] = H6>>>8&255; + HEAP[output|27] = H6&255; + HEAP[output|28] = H7>>>24; + HEAP[output|29] = H7>>>16&255; + HEAP[output|30] = H7>>>8&255; + HEAP[output|31] = H7&255; + } + + function reset () { + H0 = 0x6a09e667; + H1 = 0xbb67ae85; + H2 = 0x3c6ef372; + H3 = 0xa54ff53a; + H4 = 0x510e527f; + H5 = 0x9b05688c; + H6 = 0x1f83d9ab; + H7 = 0x5be0cd19; + TOTAL0 = TOTAL1 = 0; + } -var static_l_desc; -var static_d_desc; -var static_bl_desc; + function init ( h0, h1, h2, h3, h4, h5, h6, h7, total0, total1 ) { + h0 = h0|0; + h1 = h1|0; + h2 = h2|0; + h3 = h3|0; + h4 = h4|0; + h5 = h5|0; + h6 = h6|0; + h7 = h7|0; + total0 = total0|0; + total1 = total1|0; + H0 = h0; + H1 = h1; + H2 = h2; + H3 = h3; + H4 = h4; + H5 = h5; + H6 = h6; + H7 = h7; + TOTAL0 = total0; + TOTAL1 = total1; + } -function TreeDesc(dyn_tree, stat_desc) { - this.dyn_tree = dyn_tree; /* the dynamic tree */ - this.max_code = 0; /* largest code with non zero frequency */ - this.stat_desc = stat_desc; /* the corresponding static tree */ -} + // offset — multiple of 64 + function process ( offset, length ) { + offset = offset|0; + length = length|0; + var hashed = 0; + if ( offset & 63 ) + return -1; -function d_code(dist) { - return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)]; -} + while ( (length|0) >= 64 ) { + _core_heap(offset); + offset = ( offset + 64 )|0; + length = ( length - 64 )|0; -/* =========================================================================== - * Output a short LSB first on the stream. - * IN assertion: there is enough room in pendingBuf. - */ -function put_short(s, w) { -// put_byte(s, (uch)((w) & 0xff)); -// put_byte(s, (uch)((ush)(w) >> 8)); - s.pending_buf[s.pending++] = (w) & 0xff; - s.pending_buf[s.pending++] = (w >>> 8) & 0xff; -} + hashed = ( hashed + 64 )|0; + } + TOTAL0 = ( TOTAL0 + hashed )|0; + if ( TOTAL0>>>0 < hashed>>>0 ) TOTAL1 = ( TOTAL1 + 1 )|0; -/* =========================================================================== - * Send a value on a given number of bits. - * IN assertion: length <= 16 and value fits in length bits. - */ -function send_bits(s, value, length) { - if (s.bi_valid > (Buf_size - length)) { - s.bi_buf |= (value << s.bi_valid) & 0xffff; - put_short(s, s.bi_buf); - s.bi_buf = value >> (Buf_size - s.bi_valid); - s.bi_valid += length - Buf_size; - } else { - s.bi_buf |= (value << s.bi_valid) & 0xffff; - s.bi_valid += length; - } -} + return hashed|0; + } + // offset — multiple of 64 + // output — multiple of 32 + function finish ( offset, length, output ) { + offset = offset|0; + length = length|0; + output = output|0; -function send_code(s, c, tree) { - send_bits(s, tree[c * 2]/*.Code*/, tree[c * 2 + 1]/*.Len*/); -} + var hashed = 0, + i = 0; + if ( offset & 63 ) + return -1; -/* =========================================================================== - * Reverse the first len bits of a code, using straightforward code (a faster - * method would use a table) - * IN assertion: 1 <= len <= 15 - */ -function bi_reverse(code, len) { - var res = 0; - do { - res |= code & 1; - code >>>= 1; - res <<= 1; - } while (--len > 0); - return res >>> 1; -} + if ( ~output ) + if ( output & 31 ) + return -1; + if ( (length|0) >= 64 ) { + hashed = process( offset, length )|0; + if ( (hashed|0) == -1 ) + return -1; -/* =========================================================================== - * Flush the bit buffer, keeping at most 7 bits in it. - */ -function bi_flush(s) { - if (s.bi_valid === 16) { - put_short(s, s.bi_buf); - s.bi_buf = 0; - s.bi_valid = 0; + offset = ( offset + hashed )|0; + length = ( length - hashed )|0; + } - } else if (s.bi_valid >= 8) { - s.pending_buf[s.pending++] = s.bi_buf & 0xff; - s.bi_buf >>= 8; - s.bi_valid -= 8; - } -} + hashed = ( hashed + length )|0; + TOTAL0 = ( TOTAL0 + length )|0; + if ( TOTAL0>>>0 < length>>>0 ) TOTAL1 = ( TOTAL1 + 1 )|0; + HEAP[offset|length] = 0x80; -/* =========================================================================== - * Compute the optimal bit lengths for a tree and update the total bit length - * for the current block. - * IN assertion: the fields freq and dad are set, heap[heap_max] and - * above are the tree nodes sorted by increasing frequency. - * OUT assertions: the field len is set to the optimal bit length, the - * array bl_count contains the frequencies for each bit length. - * The length opt_len is updated; static_len is also updated if stree is - * not null. - */ -function gen_bitlen(s, desc) -// deflate_state *s; -// tree_desc *desc; /* the tree descriptor */ -{ - var tree = desc.dyn_tree; - var max_code = desc.max_code; - var stree = desc.stat_desc.static_tree; - var has_stree = desc.stat_desc.has_stree; - var extra = desc.stat_desc.extra_bits; - var base = desc.stat_desc.extra_base; - var max_length = desc.stat_desc.max_length; - var h; /* heap index */ - var n, m; /* iterate over the tree elements */ - var bits; /* bit length */ - var xbits; /* extra bits */ - var f; /* frequency */ - var overflow = 0; /* number of elements with bit length too large */ - - for (bits = 0; bits <= MAX_BITS; bits++) { - s.bl_count[bits] = 0; - } - - /* In a first pass, compute the optimal bit lengths (which may - * overflow in the case of the bit length tree). - */ - tree[s.heap[s.heap_max] * 2 + 1]/*.Len*/ = 0; /* root of the heap */ + if ( (length|0) >= 56 ) { + for ( i = (length+1)|0; (i|0) < 64; i = (i+1)|0 ) + HEAP[offset|i] = 0x00; + + _core_heap(offset); + + length = 0; + + HEAP[offset|0] = 0; + } + + for ( i = (length+1)|0; (i|0) < 59; i = (i+1)|0 ) + HEAP[offset|i] = 0; + + HEAP[offset|56] = TOTAL1>>>21&255; + HEAP[offset|57] = TOTAL1>>>13&255; + HEAP[offset|58] = TOTAL1>>>5&255; + HEAP[offset|59] = TOTAL1<<3&255 | TOTAL0>>>29; + HEAP[offset|60] = TOTAL0>>>21&255; + HEAP[offset|61] = TOTAL0>>>13&255; + HEAP[offset|62] = TOTAL0>>>5&255; + HEAP[offset|63] = TOTAL0<<3&255; + _core_heap(offset); + + if ( ~output ) + _state_to_heap(output); - for (h = s.heap_max + 1; h < HEAP_SIZE; h++) { - n = s.heap[h]; - bits = tree[tree[n * 2 + 1]/*.Dad*/ * 2 + 1]/*.Len*/ + 1; - if (bits > max_length) { - bits = max_length; - overflow++; + return hashed|0; } - tree[n * 2 + 1]/*.Len*/ = bits; - /* We overwrite tree[n].Dad which is no longer needed */ - if (n > max_code) { continue; } /* not a leaf node */ + function hmac_reset () { + H0 = I0; + H1 = I1; + H2 = I2; + H3 = I3; + H4 = I4; + H5 = I5; + H6 = I6; + H7 = I7; + TOTAL0 = 64; + TOTAL1 = 0; + } + + function _hmac_opad () { + H0 = O0; + H1 = O1; + H2 = O2; + H3 = O3; + H4 = O4; + H5 = O5; + H6 = O6; + H7 = O7; + TOTAL0 = 64; + TOTAL1 = 0; + } + + function hmac_init ( p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15 ) { + p0 = p0|0; + p1 = p1|0; + p2 = p2|0; + p3 = p3|0; + p4 = p4|0; + p5 = p5|0; + p6 = p6|0; + p7 = p7|0; + p8 = p8|0; + p9 = p9|0; + p10 = p10|0; + p11 = p11|0; + p12 = p12|0; + p13 = p13|0; + p14 = p14|0; + p15 = p15|0; + + // opad + reset(); + _core( + p0 ^ 0x5c5c5c5c, + p1 ^ 0x5c5c5c5c, + p2 ^ 0x5c5c5c5c, + p3 ^ 0x5c5c5c5c, + p4 ^ 0x5c5c5c5c, + p5 ^ 0x5c5c5c5c, + p6 ^ 0x5c5c5c5c, + p7 ^ 0x5c5c5c5c, + p8 ^ 0x5c5c5c5c, + p9 ^ 0x5c5c5c5c, + p10 ^ 0x5c5c5c5c, + p11 ^ 0x5c5c5c5c, + p12 ^ 0x5c5c5c5c, + p13 ^ 0x5c5c5c5c, + p14 ^ 0x5c5c5c5c, + p15 ^ 0x5c5c5c5c + ); + O0 = H0; + O1 = H1; + O2 = H2; + O3 = H3; + O4 = H4; + O5 = H5; + O6 = H6; + O7 = H7; + + // ipad + reset(); + _core( + p0 ^ 0x36363636, + p1 ^ 0x36363636, + p2 ^ 0x36363636, + p3 ^ 0x36363636, + p4 ^ 0x36363636, + p5 ^ 0x36363636, + p6 ^ 0x36363636, + p7 ^ 0x36363636, + p8 ^ 0x36363636, + p9 ^ 0x36363636, + p10 ^ 0x36363636, + p11 ^ 0x36363636, + p12 ^ 0x36363636, + p13 ^ 0x36363636, + p14 ^ 0x36363636, + p15 ^ 0x36363636 + ); + I0 = H0; + I1 = H1; + I2 = H2; + I3 = H3; + I4 = H4; + I5 = H5; + I6 = H6; + I7 = H7; - s.bl_count[bits]++; - xbits = 0; - if (n >= base) { - xbits = extra[n - base]; - } - f = tree[n * 2]/*.Freq*/; - s.opt_len += f * (bits + xbits); - if (has_stree) { - s.static_len += f * (stree[n * 2 + 1]/*.Len*/ + xbits); + TOTAL0 = 64; + TOTAL1 = 0; } - } - if (overflow === 0) { return; } - // Trace((stderr,"\nbit length overflow\n")); - /* This happens for example on obj2 and pic of the Calgary corpus */ + // offset — multiple of 64 + // output — multiple of 32 + function hmac_finish ( offset, length, output ) { + offset = offset|0; + length = length|0; + output = output|0; - /* Find the first bit length which could increase: */ - do { - bits = max_length - 1; - while (s.bl_count[bits] === 0) { bits--; } - s.bl_count[bits]--; /* move one leaf down the tree */ - s.bl_count[bits + 1] += 2; /* move one overflow item as its brother */ - s.bl_count[max_length]--; - /* The brother of the overflow item also moves one step up, - * but this does not affect bl_count[max_length] - */ - overflow -= 2; - } while (overflow > 0); + var t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0, + hashed = 0; - /* Now recompute all bit lengths, scanning in increasing frequency. - * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all - * lengths instead of fixing only the wrong ones. This idea is taken - * from 'ar' written by Haruhiko Okumura.) - */ - for (bits = max_length; bits !== 0; bits--) { - n = s.bl_count[bits]; - while (n !== 0) { - m = s.heap[--h]; - if (m > max_code) { continue; } - if (tree[m * 2 + 1]/*.Len*/ !== bits) { - // Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); - s.opt_len += (bits - tree[m * 2 + 1]/*.Len*/) * tree[m * 2]/*.Freq*/; - tree[m * 2 + 1]/*.Len*/ = bits; - } - n--; - } - } -} + if ( offset & 63 ) + return -1; + if ( ~output ) + if ( output & 31 ) + return -1; -/* =========================================================================== - * Generate the codes for a given tree and bit counts (which need not be - * optimal). - * IN assertion: the array bl_count contains the bit length statistics for - * the given tree and the field len is set for all tree elements. - * OUT assertion: the field code is set for all tree elements of non - * zero code length. - */ -function gen_codes(tree, max_code, bl_count) -// ct_data *tree; /* the tree to decorate */ -// int max_code; /* largest code with non zero frequency */ -// ushf *bl_count; /* number of codes at each bit length */ -{ - var next_code = new Array(MAX_BITS + 1); /* next code value for each bit length */ - var code = 0; /* running code value */ - var bits; /* bit index */ - var n; /* code index */ + hashed = finish( offset, length, -1 )|0; + t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; - /* The distribution counts are first used to generate the code values - * without bit reversal. - */ - for (bits = 1; bits <= MAX_BITS; bits++) { - next_code[bits] = code = (code + bl_count[bits - 1]) << 1; - } - /* Check that the bit counts in bl_count are consistent. The last code - * must be all ones. - */ - //Assert (code + bl_count[MAX_BITS]-1 == (1< length code (0..28) */ - length = 0; - for (code = 0; code < LENGTH_CODES - 1; code++) { - base_length[code] = length; - for (n = 0; n < (1 << extra_lbits[code]); n++) { - _length_code[length++] = code; - } - } - //Assert (length == 256, "tr_static_init: length != 256"); - /* Note that the length 255 (match length 258) can be represented - * in two different ways: code 284 + 5 bits or code 285, so we - * overwrite length_code[255] to use the best encoding: - */ - _length_code[length - 1] = code; + if ( offset & 63 ) + return -1; - /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ - dist = 0; - for (code = 0; code < 16; code++) { - base_dist[code] = dist; - for (n = 0; n < (1 << extra_dbits[code]); n++) { - _dist_code[dist++] = code; - } - } - //Assert (dist == 256, "tr_static_init: dist != 256"); - dist >>= 7; /* from now on, all distances are divided by 128 */ - for (; code < D_CODES; code++) { - base_dist[code] = dist << 7; - for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) { - _dist_code[256 + dist++] = code; - } - } - //Assert (dist == 256, "tr_static_init: 256+dist != 512"); + if ( ~output ) + if ( output & 31 ) + return -1; - /* Construct the codes of the static literal tree */ - for (bits = 0; bits <= MAX_BITS; bits++) { - bl_count[bits] = 0; - } + // pad block number into heap + // FIXME probable OOB write + HEAP[(offset+length)|0] = block>>>24; + HEAP[(offset+length+1)|0] = block>>>16&255; + HEAP[(offset+length+2)|0] = block>>>8&255; + HEAP[(offset+length+3)|0] = block&255; - n = 0; - while (n <= 143) { - static_ltree[n * 2 + 1]/*.Len*/ = 8; - n++; - bl_count[8]++; - } - while (n <= 255) { - static_ltree[n * 2 + 1]/*.Len*/ = 9; - n++; - bl_count[9]++; - } - while (n <= 279) { - static_ltree[n * 2 + 1]/*.Len*/ = 7; - n++; - bl_count[7]++; - } - while (n <= 287) { - static_ltree[n * 2 + 1]/*.Len*/ = 8; - n++; - bl_count[8]++; - } - /* Codes 286 and 287 do not exist, but we must include them in the - * tree construction to get a canonical Huffman tree (longest code - * all ones) - */ - gen_codes(static_ltree, L_CODES + 1, bl_count); + // finish first iteration + hmac_finish( offset, (length+4)|0, -1 )|0; + h0 = t0 = H0, h1 = t1 = H1, h2 = t2 = H2, h3 = t3 = H3, h4 = t4 = H4, h5 = t5 = H5, h6 = t6 = H6, h7 = t7 = H7; + count = (count-1)|0; - /* The static distance tree is trivial: */ - for (n = 0; n < D_CODES; n++) { - static_dtree[n * 2 + 1]/*.Len*/ = 5; - static_dtree[n * 2]/*.Code*/ = bi_reverse(n, 5); - } + // perform the rest iterations + while ( (count|0) > 0 ) { + hmac_reset(); + _core( t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768 ); + t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; - // Now data ready and we can init static trees - static_l_desc = new StaticTreeDesc(static_ltree, extra_lbits, LITERALS + 1, L_CODES, MAX_BITS); - static_d_desc = new StaticTreeDesc(static_dtree, extra_dbits, 0, D_CODES, MAX_BITS); - static_bl_desc = new StaticTreeDesc(new Array(0), extra_blbits, 0, BL_CODES, MAX_BL_BITS); + _hmac_opad(); + _core( t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768 ); + t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; - //static_init_done = true; -} + h0 = h0 ^ H0; + h1 = h1 ^ H1; + h2 = h2 ^ H2; + h3 = h3 ^ H3; + h4 = h4 ^ H4; + h5 = h5 ^ H5; + h6 = h6 ^ H6; + h7 = h7 ^ H7; + count = (count-1)|0; + } -/* =========================================================================== - * Initialize a new block. - */ -function init_block(s) { - var n; /* iterates over tree elements */ + H0 = h0; + H1 = h1; + H2 = h2; + H3 = h3; + H4 = h4; + H5 = h5; + H6 = h6; + H7 = h7; - /* Initialize the trees. */ - for (n = 0; n < L_CODES; n++) { s.dyn_ltree[n * 2]/*.Freq*/ = 0; } - for (n = 0; n < D_CODES; n++) { s.dyn_dtree[n * 2]/*.Freq*/ = 0; } - for (n = 0; n < BL_CODES; n++) { s.bl_tree[n * 2]/*.Freq*/ = 0; } + if ( ~output ) + _state_to_heap(output); - s.dyn_ltree[END_BLOCK * 2]/*.Freq*/ = 1; - s.opt_len = s.static_len = 0; - s.last_lit = s.matches = 0; -} + return 0; + } + return { + // SHA256 + reset: reset, + init: init, + process: process, + finish: finish, -/* =========================================================================== - * Flush the bit buffer and align the output on a byte boundary - */ -function bi_windup(s) -{ - if (s.bi_valid > 8) { - put_short(s, s.bi_buf); - } else if (s.bi_valid > 0) { - //put_byte(s, (Byte)s->bi_buf); - s.pending_buf[s.pending++] = s.bi_buf; - } - s.bi_buf = 0; - s.bi_valid = 0; -} + // HMAC-SHA256 + hmac_reset: hmac_reset, + hmac_init: hmac_init, + hmac_finish: hmac_finish, -/* =========================================================================== - * Copy a stored block, storing first the length and its - * one's complement if requested. - */ -function copy_block(s, buf, len, header) -//DeflateState *s; -//charf *buf; /* the input data */ -//unsigned len; /* its length */ -//int header; /* true if block header must be written */ -{ - bi_windup(s); /* align on byte boundary */ + // PBKDF2-HMAC-SHA256 + pbkdf2_generate_block: pbkdf2_generate_block + } +}; - if (header) { - put_short(s, len); - put_short(s, ~len); - } -// while (len--) { -// put_byte(s, *buf++); -// } - utils.arraySet(s.pending_buf, s.window, buf, len, s.pending); - s.pending += len; +const _sha256_block_size = 64; +const _sha256_hash_size = 32; +const heap_pool$2 = []; +const asm_pool$2 = []; +class Sha256 extends Hash { + constructor() { + super(); + this.NAME = 'sha256'; + this.BLOCK_SIZE = _sha256_block_size; + this.HASH_SIZE = _sha256_hash_size; + this.acquire_asm(); + } + acquire_asm() { + if (this.heap === undefined || this.asm === undefined) { + this.heap = heap_pool$2.pop() || _heap_init(); + this.asm = asm_pool$2.pop() || sha256_asm({ Uint8Array: Uint8Array }, null, this.heap.buffer); + this.reset(); + } + return { heap: this.heap, asm: this.asm }; + } + release_asm() { + if (this.heap !== undefined && this.asm !== undefined) { + heap_pool$2.push(this.heap); + asm_pool$2.push(this.asm); + } + this.heap = undefined; + this.asm = undefined; + } + static bytes(data) { + return new Sha256().process(data).finish().result; + } } +Sha256.NAME = 'sha256'; -/* =========================================================================== - * Compares to subtrees, using the tree depth as tie breaker when - * the subtrees have equal frequency. This minimizes the worst case length. - */ -function smaller(tree, n, m, depth) { - var _n2 = n * 2; - var _m2 = m * 2; - return (tree[_n2]/*.Freq*/ < tree[_m2]/*.Freq*/ || - (tree[_n2]/*.Freq*/ === tree[_m2]/*.Freq*/ && depth[n] <= depth[m])); +var minimalisticAssert = assert; + +function assert(val, msg) { + if (!val) + throw new Error(msg || 'Assertion failed'); } -/* =========================================================================== - * Restore the heap property by moving down the tree starting at node k, - * exchanging a node with the smallest of its two sons if necessary, stopping - * when the heap property is re-established (each father smaller than its - * two sons). - */ -function pqdownheap(s, tree, k) -// deflate_state *s; -// ct_data *tree; /* the tree to restore */ -// int k; /* node to move down */ -{ - var v = s.heap[k]; - var j = k << 1; /* left son of k */ - while (j <= s.heap_len) { - /* Set j to the smallest of the two sons: */ - if (j < s.heap_len && - smaller(tree, s.heap[j + 1], s.heap[j], s.depth)) { - j++; - } - /* Exit if v is smaller than both sons */ - if (smaller(tree, v, s.heap[j], s.depth)) { break; } +assert.equal = function assertEqual(l, r, msg) { + if (l != r) + throw new Error(msg || ('Assertion failed: ' + l + ' != ' + r)); +}; - /* Exchange v with the smallest son */ - s.heap[k] = s.heap[j]; - k = j; +var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; - /* And continue down the tree, setting j to the left son of k */ - j <<= 1; - } - s.heap[k] = v; +function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; } +function commonjsRequire () { + throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs'); +} -// inlined manually -// var SMALLEST = 1; +var inherits_browser = createCommonjsModule(function (module) { +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor; + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor; + var TempCtor = function () {}; + TempCtor.prototype = superCtor.prototype; + ctor.prototype = new TempCtor(); + ctor.prototype.constructor = ctor; + }; +} +}); -/* =========================================================================== - * Send the block data compressed using the given Huffman trees - */ -function compress_block(s, ltree, dtree) -// deflate_state *s; -// const ct_data *ltree; /* literal tree */ -// const ct_data *dtree; /* distance tree */ -{ - var dist; /* distance of matched string */ - var lc; /* match length or unmatched char (if dist == 0) */ - var lx = 0; /* running index in l_buf */ - var code; /* the code to send */ - var extra; /* number of extra bits to send */ +var inherits = createCommonjsModule(function (module) { +try { + var util = util__default['default']; + if (typeof util.inherits !== 'function') throw ''; + module.exports = util.inherits; +} catch (e) { + module.exports = inherits_browser; +} +}); - if (s.last_lit !== 0) { - do { - dist = (s.pending_buf[s.d_buf + lx * 2] << 8) | (s.pending_buf[s.d_buf + lx * 2 + 1]); - lc = s.pending_buf[s.l_buf + lx]; - lx++; +var inherits_1 = inherits; - if (dist === 0) { - send_code(s, lc, ltree); /* send a literal byte */ - //Tracecv(isgraph(lc), (stderr," '%c' ", lc)); - } else { - /* Here, lc is the match length - MIN_MATCH */ - code = _length_code[lc]; - send_code(s, code + LITERALS + 1, ltree); /* send the length code */ - extra = extra_lbits[code]; - if (extra !== 0) { - lc -= base_length[code]; - send_bits(s, lc, extra); /* send the extra length bits */ - } - dist--; /* dist is now the match distance - 1 */ - code = d_code(dist); - //Assert (code < D_CODES, "bad d_code"); +function toArray(msg, enc) { + if (Array.isArray(msg)) + return msg.slice(); + if (!msg) + return []; + var res = []; + if (typeof msg === 'string') { + if (!enc) { + for (var i = 0; i < msg.length; i++) { + var c = msg.charCodeAt(i); + var hi = c >> 8; + var lo = c & 0xff; + if (hi) + res.push(hi, lo); + else + res.push(lo); + } + } else if (enc === 'hex') { + msg = msg.replace(/[^a-z0-9]+/ig, ''); + if (msg.length % 2 !== 0) + msg = '0' + msg; + for (i = 0; i < msg.length; i += 2) + res.push(parseInt(msg[i] + msg[i + 1], 16)); + } + } else { + for (i = 0; i < msg.length; i++) + res[i] = msg[i] | 0; + } + return res; +} +var toArray_1 = toArray; - send_code(s, code, dtree); /* send the distance code */ - extra = extra_dbits[code]; - if (extra !== 0) { - dist -= base_dist[code]; - send_bits(s, dist, extra); /* send the extra distance bits */ - } - } /* literal or match pair ? */ +function toHex(msg) { + var res = ''; + for (var i = 0; i < msg.length; i++) + res += zero2(msg[i].toString(16)); + return res; +} +var toHex_1 = toHex; - /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ - //Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, - // "pendingBuf overflow"); +function htonl(w) { + var res = (w >>> 24) | + ((w >>> 8) & 0xff00) | + ((w << 8) & 0xff0000) | + ((w & 0xff) << 24); + return res >>> 0; +} +var htonl_1 = htonl; - } while (lx < s.last_lit); +function toHex32(msg, endian) { + var res = ''; + for (var i = 0; i < msg.length; i++) { + var w = msg[i]; + if (endian === 'little') + w = htonl(w); + res += zero8(w.toString(16)); } - - send_code(s, END_BLOCK, ltree); + return res; } +var toHex32_1 = toHex32; +function zero2(word) { + if (word.length === 1) + return '0' + word; + else + return word; +} +var zero2_1 = zero2; -/* =========================================================================== - * Construct one Huffman tree and assigns the code bit strings and lengths. - * Update the total bit length for the current block. - * IN assertion: the field freq is set for all tree elements. - * OUT assertions: the fields len and code are set to the optimal bit length - * and corresponding code. The length opt_len is updated; static_len is - * also updated if stree is not null. The field max_code is set. - */ -function build_tree(s, desc) -// deflate_state *s; -// tree_desc *desc; /* the tree descriptor */ -{ - var tree = desc.dyn_tree; - var stree = desc.stat_desc.static_tree; - var has_stree = desc.stat_desc.has_stree; - var elems = desc.stat_desc.elems; - var n, m; /* iterate over heap elements */ - var max_code = -1; /* largest code with non zero frequency */ - var node; /* new node being created */ - - /* Construct the initial heap, with least frequent element in - * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. - * heap[0] is not used. - */ - s.heap_len = 0; - s.heap_max = HEAP_SIZE; - - for (n = 0; n < elems; n++) { - if (tree[n * 2]/*.Freq*/ !== 0) { - s.heap[++s.heap_len] = max_code = n; - s.depth[n] = 0; +function zero8(word) { + if (word.length === 7) + return '0' + word; + else if (word.length === 6) + return '00' + word; + else if (word.length === 5) + return '000' + word; + else if (word.length === 4) + return '0000' + word; + else if (word.length === 3) + return '00000' + word; + else if (word.length === 2) + return '000000' + word; + else if (word.length === 1) + return '0000000' + word; + else + return word; +} +var zero8_1 = zero8; - } else { - tree[n * 2 + 1]/*.Len*/ = 0; - } +function join32(msg, start, end, endian) { + var len = end - start; + minimalisticAssert(len % 4 === 0); + var res = new Array(len / 4); + for (var i = 0, k = start; i < res.length; i++, k += 4) { + var w; + if (endian === 'big') + w = (msg[k] << 24) | (msg[k + 1] << 16) | (msg[k + 2] << 8) | msg[k + 3]; + else + w = (msg[k + 3] << 24) | (msg[k + 2] << 16) | (msg[k + 1] << 8) | msg[k]; + res[i] = w >>> 0; } + return res; +} +var join32_1 = join32; - /* The pkzip format requires that at least one distance code exists, - * and that at least one bit should be sent even if there is only one - * possible code. So to avoid special checks later on we force at least - * two codes of non zero frequency. - */ - while (s.heap_len < 2) { - node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0); - tree[node * 2]/*.Freq*/ = 1; - s.depth[node] = 0; - s.opt_len--; - - if (has_stree) { - s.static_len -= stree[node * 2 + 1]/*.Len*/; +function split32(msg, endian) { + var res = new Array(msg.length * 4); + for (var i = 0, k = 0; i < msg.length; i++, k += 4) { + var m = msg[i]; + if (endian === 'big') { + res[k] = m >>> 24; + res[k + 1] = (m >>> 16) & 0xff; + res[k + 2] = (m >>> 8) & 0xff; + res[k + 3] = m & 0xff; + } else { + res[k + 3] = m >>> 24; + res[k + 2] = (m >>> 16) & 0xff; + res[k + 1] = (m >>> 8) & 0xff; + res[k] = m & 0xff; } - /* node is 0 or 1 so it does not have extra bits */ } - desc.max_code = max_code; - - /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, - * establish sub-heaps of increasing lengths: - */ - for (n = (s.heap_len >> 1/*int /2*/); n >= 1; n--) { pqdownheap(s, tree, n); } - - /* Construct the Huffman tree by repeatedly combining the least two - * frequent nodes. - */ - node = elems; /* next internal node of the tree */ - do { - //pqremove(s, tree, n); /* n = node of least frequency */ - /*** pqremove ***/ - n = s.heap[1/*SMALLEST*/]; - s.heap[1/*SMALLEST*/] = s.heap[s.heap_len--]; - pqdownheap(s, tree, 1/*SMALLEST*/); - /***/ + return res; +} +var split32_1 = split32; - m = s.heap[1/*SMALLEST*/]; /* m = node of next least frequency */ +function rotr32(w, b) { + return (w >>> b) | (w << (32 - b)); +} +var rotr32_1 = rotr32; - s.heap[--s.heap_max] = n; /* keep the nodes sorted by frequency */ - s.heap[--s.heap_max] = m; +function rotl32(w, b) { + return (w << b) | (w >>> (32 - b)); +} +var rotl32_1 = rotl32; - /* Create a new node father of n and m */ - tree[node * 2]/*.Freq*/ = tree[n * 2]/*.Freq*/ + tree[m * 2]/*.Freq*/; - s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1; - tree[n * 2 + 1]/*.Dad*/ = tree[m * 2 + 1]/*.Dad*/ = node; +function sum32(a, b) { + return (a + b) >>> 0; +} +var sum32_1 = sum32; - /* and insert the new node in the heap */ - s.heap[1/*SMALLEST*/] = node++; - pqdownheap(s, tree, 1/*SMALLEST*/); +function sum32_3(a, b, c) { + return (a + b + c) >>> 0; +} +var sum32_3_1 = sum32_3; - } while (s.heap_len >= 2); +function sum32_4(a, b, c, d) { + return (a + b + c + d) >>> 0; +} +var sum32_4_1 = sum32_4; - s.heap[--s.heap_max] = s.heap[1/*SMALLEST*/]; +function sum32_5(a, b, c, d, e) { + return (a + b + c + d + e) >>> 0; +} +var sum32_5_1 = sum32_5; - /* At this point, the fields freq and dad are set. We can now - * generate the bit lengths. - */ - gen_bitlen(s, desc); +function sum64(buf, pos, ah, al) { + var bh = buf[pos]; + var bl = buf[pos + 1]; - /* The field len is now set, we can generate the bit codes */ - gen_codes(tree, max_code, s.bl_count); + var lo = (al + bl) >>> 0; + var hi = (lo < al ? 1 : 0) + ah + bh; + buf[pos] = hi >>> 0; + buf[pos + 1] = lo; } +var sum64_1 = sum64; +function sum64_hi(ah, al, bh, bl) { + var lo = (al + bl) >>> 0; + var hi = (lo < al ? 1 : 0) + ah + bh; + return hi >>> 0; +} +var sum64_hi_1 = sum64_hi; -/* =========================================================================== - * Scan a literal or distance tree to determine the frequencies of the codes - * in the bit length tree. - */ -function scan_tree(s, tree, max_code) -// deflate_state *s; -// ct_data *tree; /* the tree to be scanned */ -// int max_code; /* and its largest code of non zero frequency */ -{ - var n; /* iterates over all tree elements */ - var prevlen = -1; /* last emitted length */ - var curlen; /* length of current code */ - - var nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */ +function sum64_lo(ah, al, bh, bl) { + var lo = al + bl; + return lo >>> 0; +} +var sum64_lo_1 = sum64_lo; - var count = 0; /* repeat count of the current code */ - var max_count = 7; /* max repeat count */ - var min_count = 4; /* min repeat count */ +function sum64_4_hi(ah, al, bh, bl, ch, cl, dh, dl) { + var carry = 0; + var lo = al; + lo = (lo + bl) >>> 0; + carry += lo < al ? 1 : 0; + lo = (lo + cl) >>> 0; + carry += lo < cl ? 1 : 0; + lo = (lo + dl) >>> 0; + carry += lo < dl ? 1 : 0; - if (nextlen === 0) { - max_count = 138; - min_count = 3; - } - tree[(max_code + 1) * 2 + 1]/*.Len*/ = 0xffff; /* guard */ + var hi = ah + bh + ch + dh + carry; + return hi >>> 0; +} +var sum64_4_hi_1 = sum64_4_hi; - for (n = 0; n <= max_code; n++) { - curlen = nextlen; - nextlen = tree[(n + 1) * 2 + 1]/*.Len*/; +function sum64_4_lo(ah, al, bh, bl, ch, cl, dh, dl) { + var lo = al + bl + cl + dl; + return lo >>> 0; +} +var sum64_4_lo_1 = sum64_4_lo; - if (++count < max_count && curlen === nextlen) { - continue; +function sum64_5_hi(ah, al, bh, bl, ch, cl, dh, dl, eh, el) { + var carry = 0; + var lo = al; + lo = (lo + bl) >>> 0; + carry += lo < al ? 1 : 0; + lo = (lo + cl) >>> 0; + carry += lo < cl ? 1 : 0; + lo = (lo + dl) >>> 0; + carry += lo < dl ? 1 : 0; + lo = (lo + el) >>> 0; + carry += lo < el ? 1 : 0; - } else if (count < min_count) { - s.bl_tree[curlen * 2]/*.Freq*/ += count; + var hi = ah + bh + ch + dh + eh + carry; + return hi >>> 0; +} +var sum64_5_hi_1 = sum64_5_hi; - } else if (curlen !== 0) { +function sum64_5_lo(ah, al, bh, bl, ch, cl, dh, dl, eh, el) { + var lo = al + bl + cl + dl + el; - if (curlen !== prevlen) { s.bl_tree[curlen * 2]/*.Freq*/++; } - s.bl_tree[REP_3_6 * 2]/*.Freq*/++; + return lo >>> 0; +} +var sum64_5_lo_1 = sum64_5_lo; - } else if (count <= 10) { - s.bl_tree[REPZ_3_10 * 2]/*.Freq*/++; +function rotr64_hi(ah, al, num) { + var r = (al << (32 - num)) | (ah >>> num); + return r >>> 0; +} +var rotr64_hi_1 = rotr64_hi; - } else { - s.bl_tree[REPZ_11_138 * 2]/*.Freq*/++; - } +function rotr64_lo(ah, al, num) { + var r = (ah << (32 - num)) | (al >>> num); + return r >>> 0; +} +var rotr64_lo_1 = rotr64_lo; - count = 0; - prevlen = curlen; +function shr64_hi(ah, al, num) { + return ah >>> num; +} +var shr64_hi_1 = shr64_hi; - if (nextlen === 0) { - max_count = 138; - min_count = 3; +function shr64_lo(ah, al, num) { + var r = (ah << (32 - num)) | (al >>> num); + return r >>> 0; +} +var shr64_lo_1 = shr64_lo; + +var utils = { + inherits: inherits_1, + toArray: toArray_1, + toHex: toHex_1, + htonl: htonl_1, + toHex32: toHex32_1, + zero2: zero2_1, + zero8: zero8_1, + join32: join32_1, + split32: split32_1, + rotr32: rotr32_1, + rotl32: rotl32_1, + sum32: sum32_1, + sum32_3: sum32_3_1, + sum32_4: sum32_4_1, + sum32_5: sum32_5_1, + sum64: sum64_1, + sum64_hi: sum64_hi_1, + sum64_lo: sum64_lo_1, + sum64_4_hi: sum64_4_hi_1, + sum64_4_lo: sum64_4_lo_1, + sum64_5_hi: sum64_5_hi_1, + sum64_5_lo: sum64_5_lo_1, + rotr64_hi: rotr64_hi_1, + rotr64_lo: rotr64_lo_1, + shr64_hi: shr64_hi_1, + shr64_lo: shr64_lo_1 +}; - } else if (curlen === nextlen) { - max_count = 6; - min_count = 3; +function BlockHash() { + this.pending = null; + this.pendingTotal = 0; + this.blockSize = this.constructor.blockSize; + this.outSize = this.constructor.outSize; + this.hmacStrength = this.constructor.hmacStrength; + this.padLength = this.constructor.padLength / 8; + this.endian = 'big'; - } else { - max_count = 7; - min_count = 4; - } - } + this._delta8 = this.blockSize / 8; + this._delta32 = this.blockSize / 32; } +var BlockHash_1 = BlockHash; +BlockHash.prototype.update = function update(msg, enc) { + // Convert message to array, pad it, and join into 32bit blocks + msg = utils.toArray(msg, enc); + if (!this.pending) + this.pending = msg; + else + this.pending = this.pending.concat(msg); + this.pendingTotal += msg.length; -/* =========================================================================== - * Send a literal or distance tree in compressed form, using the codes in - * bl_tree. - */ -function send_tree(s, tree, max_code) -// deflate_state *s; -// ct_data *tree; /* the tree to be scanned */ -// int max_code; /* and its largest code of non zero frequency */ -{ - var n; /* iterates over all tree elements */ - var prevlen = -1; /* last emitted length */ - var curlen; /* length of current code */ - - var nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */ + // Enough data, try updating + if (this.pending.length >= this._delta8) { + msg = this.pending; - var count = 0; /* repeat count of the current code */ - var max_count = 7; /* max repeat count */ - var min_count = 4; /* min repeat count */ + // Process pending data in blocks + var r = msg.length % this._delta8; + this.pending = msg.slice(msg.length - r, msg.length); + if (this.pending.length === 0) + this.pending = null; - /* tree[max_code+1].Len = -1; */ /* guard already set */ - if (nextlen === 0) { - max_count = 138; - min_count = 3; + msg = utils.join32(msg, 0, msg.length - r, this.endian); + for (var i = 0; i < msg.length; i += this._delta32) + this._update(msg, i, i + this._delta32); } - for (n = 0; n <= max_code; n++) { - curlen = nextlen; - nextlen = tree[(n + 1) * 2 + 1]/*.Len*/; - - if (++count < max_count && curlen === nextlen) { - continue; - - } else if (count < min_count) { - do { send_code(s, curlen, s.bl_tree); } while (--count !== 0); + return this; +}; - } else if (curlen !== 0) { - if (curlen !== prevlen) { - send_code(s, curlen, s.bl_tree); - count--; - } - //Assert(count >= 3 && count <= 6, " 3_6?"); - send_code(s, REP_3_6, s.bl_tree); - send_bits(s, count - 3, 2); +BlockHash.prototype.digest = function digest(enc) { + this.update(this._pad()); + minimalisticAssert(this.pending === null); - } else if (count <= 10) { - send_code(s, REPZ_3_10, s.bl_tree); - send_bits(s, count - 3, 3); + return this._digest(enc); +}; - } else { - send_code(s, REPZ_11_138, s.bl_tree); - send_bits(s, count - 11, 7); - } +BlockHash.prototype._pad = function pad() { + var len = this.pendingTotal; + var bytes = this._delta8; + var k = bytes - ((len + this.padLength) % bytes); + var res = new Array(k + this.padLength); + res[0] = 0x80; + for (var i = 1; i < k; i++) + res[i] = 0; - count = 0; - prevlen = curlen; - if (nextlen === 0) { - max_count = 138; - min_count = 3; + // Append length + len <<= 3; + if (this.endian === 'big') { + for (var t = 8; t < this.padLength; t++) + res[i++] = 0; - } else if (curlen === nextlen) { - max_count = 6; - min_count = 3; + res[i++] = 0; + res[i++] = 0; + res[i++] = 0; + res[i++] = 0; + res[i++] = (len >>> 24) & 0xff; + res[i++] = (len >>> 16) & 0xff; + res[i++] = (len >>> 8) & 0xff; + res[i++] = len & 0xff; + } else { + res[i++] = len & 0xff; + res[i++] = (len >>> 8) & 0xff; + res[i++] = (len >>> 16) & 0xff; + res[i++] = (len >>> 24) & 0xff; + res[i++] = 0; + res[i++] = 0; + res[i++] = 0; + res[i++] = 0; - } else { - max_count = 7; - min_count = 4; - } + for (t = 8; t < this.padLength; t++) + res[i++] = 0; } -} + return res; +}; -/* =========================================================================== - * Construct the Huffman tree for the bit lengths and return the index in - * bl_order of the last bit length code to send. - */ -function build_bl_tree(s) { - var max_blindex; /* index of last bit length code of non zero freq */ +var common = { + BlockHash: BlockHash_1 +}; - /* Determine the bit length frequencies for literal and distance trees */ - scan_tree(s, s.dyn_ltree, s.l_desc.max_code); - scan_tree(s, s.dyn_dtree, s.d_desc.max_code); +var rotr32$1 = utils.rotr32; - /* Build the bit length tree: */ - build_tree(s, s.bl_desc); - /* opt_len now includes the length of the tree representations, except - * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. - */ +function ft_1(s, x, y, z) { + if (s === 0) + return ch32(x, y, z); + if (s === 1 || s === 3) + return p32(x, y, z); + if (s === 2) + return maj32(x, y, z); +} +var ft_1_1 = ft_1; - /* Determine the number of bit length codes to send. The pkzip format - * requires that at least 4 bit length codes be sent. (appnote.txt says - * 3 but the actual value used is 4.) - */ - for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) { - if (s.bl_tree[bl_order[max_blindex] * 2 + 1]/*.Len*/ !== 0) { - break; - } - } - /* Update opt_len to include the bit length tree and counts */ - s.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4; - //Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", - // s->opt_len, s->static_len)); +function ch32(x, y, z) { + return (x & y) ^ ((~x) & z); +} +var ch32_1 = ch32; - return max_blindex; +function maj32(x, y, z) { + return (x & y) ^ (x & z) ^ (y & z); } +var maj32_1 = maj32; +function p32(x, y, z) { + return x ^ y ^ z; +} +var p32_1 = p32; -/* =========================================================================== - * Send the header for a block using dynamic Huffman trees: the counts, the - * lengths of the bit length codes, the literal tree and the distance tree. - * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. - */ -function send_all_trees(s, lcodes, dcodes, blcodes) -// deflate_state *s; -// int lcodes, dcodes, blcodes; /* number of codes for each tree */ -{ - var rank; /* index in bl_order */ - - //Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); - //Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, - // "too many codes"); - //Tracev((stderr, "\nbl counts: ")); - send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */ - send_bits(s, dcodes - 1, 5); - send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */ - for (rank = 0; rank < blcodes; rank++) { - //Tracev((stderr, "\nbl code %2d ", bl_order[rank])); - send_bits(s, s.bl_tree[bl_order[rank] * 2 + 1]/*.Len*/, 3); - } - //Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); +function s0_256(x) { + return rotr32$1(x, 2) ^ rotr32$1(x, 13) ^ rotr32$1(x, 22); +} +var s0_256_1 = s0_256; - send_tree(s, s.dyn_ltree, lcodes - 1); /* literal tree */ - //Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); +function s1_256(x) { + return rotr32$1(x, 6) ^ rotr32$1(x, 11) ^ rotr32$1(x, 25); +} +var s1_256_1 = s1_256; - send_tree(s, s.dyn_dtree, dcodes - 1); /* distance tree */ - //Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +function g0_256(x) { + return rotr32$1(x, 7) ^ rotr32$1(x, 18) ^ (x >>> 3); } +var g0_256_1 = g0_256; +function g1_256(x) { + return rotr32$1(x, 17) ^ rotr32$1(x, 19) ^ (x >>> 10); +} +var g1_256_1 = g1_256; -/* =========================================================================== - * Check if the data type is TEXT or BINARY, using the following algorithm: - * - TEXT if the two conditions below are satisfied: - * a) There are no non-portable control characters belonging to the - * "black list" (0..6, 14..25, 28..31). - * b) There is at least one printable character belonging to the - * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). - * - BINARY otherwise. - * - The following partially-portable control characters form a - * "gray list" that is ignored in this detection algorithm: - * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). - * IN assertion: the fields Freq of dyn_ltree are set. - */ -function detect_data_type(s) { - /* black_mask is the bit mask of black-listed bytes - * set bits 0..6, 14..25, and 28..31 - * 0xf3ffc07f = binary 11110011111111111100000001111111 - */ - var black_mask = 0xf3ffc07f; - var n; +var common$1 = { + ft_1: ft_1_1, + ch32: ch32_1, + maj32: maj32_1, + p32: p32_1, + s0_256: s0_256_1, + s1_256: s1_256_1, + g0_256: g0_256_1, + g1_256: g1_256_1 +}; - /* Check for non-textual ("black-listed") bytes. */ - for (n = 0; n <= 31; n++, black_mask >>>= 1) { - if ((black_mask & 1) && (s.dyn_ltree[n * 2]/*.Freq*/ !== 0)) { - return Z_BINARY; - } - } +var sum32$1 = utils.sum32; +var sum32_4$1 = utils.sum32_4; +var sum32_5$1 = utils.sum32_5; +var ch32$1 = common$1.ch32; +var maj32$1 = common$1.maj32; +var s0_256$1 = common$1.s0_256; +var s1_256$1 = common$1.s1_256; +var g0_256$1 = common$1.g0_256; +var g1_256$1 = common$1.g1_256; - /* Check for textual ("white-listed") bytes. */ - if (s.dyn_ltree[9 * 2]/*.Freq*/ !== 0 || s.dyn_ltree[10 * 2]/*.Freq*/ !== 0 || - s.dyn_ltree[13 * 2]/*.Freq*/ !== 0) { - return Z_TEXT; - } - for (n = 32; n < LITERALS; n++) { - if (s.dyn_ltree[n * 2]/*.Freq*/ !== 0) { - return Z_TEXT; - } - } +var BlockHash$1 = common.BlockHash; - /* There are no "black-listed" or "white-listed" bytes: - * this stream either is empty or has tolerated ("gray-listed") bytes only. - */ - return Z_BINARY; +var sha256_K = [ + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +]; + +function SHA256() { + if (!(this instanceof SHA256)) + return new SHA256(); + + BlockHash$1.call(this); + this.h = [ + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 + ]; + this.k = sha256_K; + this.W = new Array(64); } +utils.inherits(SHA256, BlockHash$1); +var _256 = SHA256; +SHA256.blockSize = 512; +SHA256.outSize = 256; +SHA256.hmacStrength = 192; +SHA256.padLength = 64; -var static_init_done = false; +SHA256.prototype._update = function _update(msg, start) { + var W = this.W; -/* =========================================================================== - * Initialize the tree data structures for a new zlib stream. - */ -function _tr_init(s) -{ + for (var i = 0; i < 16; i++) + W[i] = msg[start + i]; + for (; i < W.length; i++) + W[i] = sum32_4$1(g1_256$1(W[i - 2]), W[i - 7], g0_256$1(W[i - 15]), W[i - 16]); + + var a = this.h[0]; + var b = this.h[1]; + var c = this.h[2]; + var d = this.h[3]; + var e = this.h[4]; + var f = this.h[5]; + var g = this.h[6]; + var h = this.h[7]; - if (!static_init_done) { - tr_static_init(); - static_init_done = true; + minimalisticAssert(this.k.length === W.length); + for (i = 0; i < W.length; i++) { + var T1 = sum32_5$1(h, s1_256$1(e), ch32$1(e, f, g), this.k[i], W[i]); + var T2 = sum32$1(s0_256$1(a), maj32$1(a, b, c)); + h = g; + g = f; + f = e; + e = sum32$1(d, T1); + d = c; + c = b; + b = a; + a = sum32$1(T1, T2); } - s.l_desc = new TreeDesc(s.dyn_ltree, static_l_desc); - s.d_desc = new TreeDesc(s.dyn_dtree, static_d_desc); - s.bl_desc = new TreeDesc(s.bl_tree, static_bl_desc); + this.h[0] = sum32$1(this.h[0], a); + this.h[1] = sum32$1(this.h[1], b); + this.h[2] = sum32$1(this.h[2], c); + this.h[3] = sum32$1(this.h[3], d); + this.h[4] = sum32$1(this.h[4], e); + this.h[5] = sum32$1(this.h[5], f); + this.h[6] = sum32$1(this.h[6], g); + this.h[7] = sum32$1(this.h[7], h); +}; + +SHA256.prototype._digest = function digest(enc) { + if (enc === 'hex') + return utils.toHex32(this.h, 'big'); + else + return utils.split32(this.h, 'big'); +}; - s.bi_buf = 0; - s.bi_valid = 0; +function SHA224() { + if (!(this instanceof SHA224)) + return new SHA224(); - /* Initialize the first block of the first file: */ - init_block(s); + _256.call(this); + this.h = [ + 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, + 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 ]; } +utils.inherits(SHA224, _256); +var _224 = SHA224; +SHA224.blockSize = 512; +SHA224.outSize = 224; +SHA224.hmacStrength = 192; +SHA224.padLength = 64; -/* =========================================================================== - * Send a stored block - */ -function _tr_stored_block(s, buf, stored_len, last) -//DeflateState *s; -//charf *buf; /* input block */ -//ulg stored_len; /* length of input block */ -//int last; /* one if this is the last block for a file */ -{ - send_bits(s, (STORED_BLOCK << 1) + (last ? 1 : 0), 3); /* send block type */ - copy_block(s, buf, stored_len, true); /* with header */ -} +SHA224.prototype._digest = function digest(enc) { + // Just truncate output + if (enc === 'hex') + return utils.toHex32(this.h.slice(0, 7), 'big'); + else + return utils.split32(this.h.slice(0, 7), 'big'); +}; +var rotr64_hi$1 = utils.rotr64_hi; +var rotr64_lo$1 = utils.rotr64_lo; +var shr64_hi$1 = utils.shr64_hi; +var shr64_lo$1 = utils.shr64_lo; +var sum64$1 = utils.sum64; +var sum64_hi$1 = utils.sum64_hi; +var sum64_lo$1 = utils.sum64_lo; +var sum64_4_hi$1 = utils.sum64_4_hi; +var sum64_4_lo$1 = utils.sum64_4_lo; +var sum64_5_hi$1 = utils.sum64_5_hi; +var sum64_5_lo$1 = utils.sum64_5_lo; -/* =========================================================================== - * Send one empty static block to give enough lookahead for inflate. - * This takes 10 bits, of which 7 may remain in the bit buffer. - */ -function _tr_align(s) { - send_bits(s, STATIC_TREES << 1, 3); - send_code(s, END_BLOCK, static_ltree); - bi_flush(s); -} +var BlockHash$2 = common.BlockHash; +var sha512_K = [ + 0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd, + 0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc, + 0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019, + 0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118, + 0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe, + 0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2, + 0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1, + 0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694, + 0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3, + 0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65, + 0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483, + 0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5, + 0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210, + 0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4, + 0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725, + 0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70, + 0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926, + 0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df, + 0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8, + 0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b, + 0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001, + 0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30, + 0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910, + 0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8, + 0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53, + 0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8, + 0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb, + 0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3, + 0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60, + 0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec, + 0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9, + 0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b, + 0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207, + 0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178, + 0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6, + 0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b, + 0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493, + 0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c, + 0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a, + 0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817 +]; -/* =========================================================================== - * Determine the best encoding for the current block: dynamic trees, static - * trees or store, and output the encoded block to the zip file. - */ -function _tr_flush_block(s, buf, stored_len, last) -//DeflateState *s; -//charf *buf; /* input block, or NULL if too old */ -//ulg stored_len; /* length of input block */ -//int last; /* one if this is the last block for a file */ -{ - var opt_lenb, static_lenb; /* opt_len and static_len in bytes */ - var max_blindex = 0; /* index of last bit length code of non zero freq */ +function SHA512() { + if (!(this instanceof SHA512)) + return new SHA512(); - /* Build the Huffman trees unless a stored block is forced */ - if (s.level > 0) { + BlockHash$2.call(this); + this.h = [ + 0x6a09e667, 0xf3bcc908, + 0xbb67ae85, 0x84caa73b, + 0x3c6ef372, 0xfe94f82b, + 0xa54ff53a, 0x5f1d36f1, + 0x510e527f, 0xade682d1, + 0x9b05688c, 0x2b3e6c1f, + 0x1f83d9ab, 0xfb41bd6b, + 0x5be0cd19, 0x137e2179 ]; + this.k = sha512_K; + this.W = new Array(160); +} +utils.inherits(SHA512, BlockHash$2); +var _512 = SHA512; - /* Check if the file is binary or text */ - if (s.strm.data_type === Z_UNKNOWN) { - s.strm.data_type = detect_data_type(s); - } +SHA512.blockSize = 1024; +SHA512.outSize = 512; +SHA512.hmacStrength = 192; +SHA512.padLength = 128; - /* Construct the literal and distance trees */ - build_tree(s, s.l_desc); - // Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, - // s->static_len)); +SHA512.prototype._prepareBlock = function _prepareBlock(msg, start) { + var W = this.W; - build_tree(s, s.d_desc); - // Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, - // s->static_len)); - /* At this point, opt_len and static_len are the total bit lengths of - * the compressed block data, excluding the tree representations. - */ + // 32 x 32bit words + for (var i = 0; i < 32; i++) + W[i] = msg[start + i]; + for (; i < W.length; i += 2) { + var c0_hi = g1_512_hi(W[i - 4], W[i - 3]); // i - 2 + var c0_lo = g1_512_lo(W[i - 4], W[i - 3]); + var c1_hi = W[i - 14]; // i - 7 + var c1_lo = W[i - 13]; + var c2_hi = g0_512_hi(W[i - 30], W[i - 29]); // i - 15 + var c2_lo = g0_512_lo(W[i - 30], W[i - 29]); + var c3_hi = W[i - 32]; // i - 16 + var c3_lo = W[i - 31]; - /* Build the bit length tree for the above two trees, and get the index - * in bl_order of the last bit length code to send. - */ - max_blindex = build_bl_tree(s); + W[i] = sum64_4_hi$1( + c0_hi, c0_lo, + c1_hi, c1_lo, + c2_hi, c2_lo, + c3_hi, c3_lo); + W[i + 1] = sum64_4_lo$1( + c0_hi, c0_lo, + c1_hi, c1_lo, + c2_hi, c2_lo, + c3_hi, c3_lo); + } +}; - /* Determine the best encoding. Compute the block lengths in bytes. */ - opt_lenb = (s.opt_len + 3 + 7) >>> 3; - static_lenb = (s.static_len + 3 + 7) >>> 3; +SHA512.prototype._update = function _update(msg, start) { + this._prepareBlock(msg, start); - // Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", - // opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, - // s->last_lit)); + var W = this.W; - if (static_lenb <= opt_lenb) { opt_lenb = static_lenb; } + var ah = this.h[0]; + var al = this.h[1]; + var bh = this.h[2]; + var bl = this.h[3]; + var ch = this.h[4]; + var cl = this.h[5]; + var dh = this.h[6]; + var dl = this.h[7]; + var eh = this.h[8]; + var el = this.h[9]; + var fh = this.h[10]; + var fl = this.h[11]; + var gh = this.h[12]; + var gl = this.h[13]; + var hh = this.h[14]; + var hl = this.h[15]; - } else { - // Assert(buf != (char*)0, "lost buf"); - opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ - } + minimalisticAssert(this.k.length === W.length); + for (var i = 0; i < W.length; i += 2) { + var c0_hi = hh; + var c0_lo = hl; + var c1_hi = s1_512_hi(eh, el); + var c1_lo = s1_512_lo(eh, el); + var c2_hi = ch64_hi(eh, el, fh, fl, gh); + var c2_lo = ch64_lo(eh, el, fh, fl, gh, gl); + var c3_hi = this.k[i]; + var c3_lo = this.k[i + 1]; + var c4_hi = W[i]; + var c4_lo = W[i + 1]; - if ((stored_len + 4 <= opt_lenb) && (buf !== -1)) { - /* 4: two words for the lengths */ + var T1_hi = sum64_5_hi$1( + c0_hi, c0_lo, + c1_hi, c1_lo, + c2_hi, c2_lo, + c3_hi, c3_lo, + c4_hi, c4_lo); + var T1_lo = sum64_5_lo$1( + c0_hi, c0_lo, + c1_hi, c1_lo, + c2_hi, c2_lo, + c3_hi, c3_lo, + c4_hi, c4_lo); - /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. - * Otherwise we can't have processed more than WSIZE input bytes since - * the last block flush, because compression would have been - * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to - * transform a block into a stored block. - */ - _tr_stored_block(s, buf, stored_len, last); + c0_hi = s0_512_hi(ah, al); + c0_lo = s0_512_lo(ah, al); + c1_hi = maj64_hi(ah, al, bh, bl, ch); + c1_lo = maj64_lo(ah, al, bh, bl, ch, cl); - } else if (s.strategy === Z_FIXED || static_lenb === opt_lenb) { + var T2_hi = sum64_hi$1(c0_hi, c0_lo, c1_hi, c1_lo); + var T2_lo = sum64_lo$1(c0_hi, c0_lo, c1_hi, c1_lo); - send_bits(s, (STATIC_TREES << 1) + (last ? 1 : 0), 3); - compress_block(s, static_ltree, static_dtree); + hh = gh; + hl = gl; - } else { - send_bits(s, (DYN_TREES << 1) + (last ? 1 : 0), 3); - send_all_trees(s, s.l_desc.max_code + 1, s.d_desc.max_code + 1, max_blindex + 1); - compress_block(s, s.dyn_ltree, s.dyn_dtree); - } - // Assert (s->compressed_len == s->bits_sent, "bad compressed size"); - /* The above check is made mod 2^32, for files larger than 512 MB - * and uLong implemented on 32 bits. - */ - init_block(s); + gh = fh; + gl = fl; - if (last) { - bi_windup(s); - } - // Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, - // s->compressed_len-7*last)); -} + fh = eh; + fl = el; -/* =========================================================================== - * Save the match info and tally the frequency counts. Return true if - * the current block must be flushed. - */ -function _tr_tally(s, dist, lc) -// deflate_state *s; -// unsigned dist; /* distance of matched string */ -// unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ -{ - //var out_length, in_length, dcode; + eh = sum64_hi$1(dh, dl, T1_hi, T1_lo); + el = sum64_lo$1(dl, dl, T1_hi, T1_lo); - s.pending_buf[s.d_buf + s.last_lit * 2] = (dist >>> 8) & 0xff; - s.pending_buf[s.d_buf + s.last_lit * 2 + 1] = dist & 0xff; + dh = ch; + dl = cl; - s.pending_buf[s.l_buf + s.last_lit] = lc & 0xff; - s.last_lit++; + ch = bh; + cl = bl; - if (dist === 0) { - /* lc is the unmatched char */ - s.dyn_ltree[lc * 2]/*.Freq*/++; - } else { - s.matches++; - /* Here, lc is the match length - MIN_MATCH */ - dist--; /* dist = match distance - 1 */ - //Assert((ush)dist < (ush)MAX_DIST(s) && - // (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && - // (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + bh = ah; + bl = al; - s.dyn_ltree[(_length_code[lc] + LITERALS + 1) * 2]/*.Freq*/++; - s.dyn_dtree[d_code(dist) * 2]/*.Freq*/++; + ah = sum64_hi$1(T1_hi, T1_lo, T2_hi, T2_lo); + al = sum64_lo$1(T1_hi, T1_lo, T2_hi, T2_lo); } -// (!) This block is disabled in zlib defaults, -// don't enable it for binary compatibility + sum64$1(this.h, 0, ah, al); + sum64$1(this.h, 2, bh, bl); + sum64$1(this.h, 4, ch, cl); + sum64$1(this.h, 6, dh, dl); + sum64$1(this.h, 8, eh, el); + sum64$1(this.h, 10, fh, fl); + sum64$1(this.h, 12, gh, gl); + sum64$1(this.h, 14, hh, hl); +}; -//#ifdef TRUNCATE_BLOCK -// /* Try to guess if it is profitable to stop the current block here */ -// if ((s.last_lit & 0x1fff) === 0 && s.level > 2) { -// /* Compute an upper bound for the compressed length */ -// out_length = s.last_lit*8; -// in_length = s.strstart - s.block_start; -// -// for (dcode = 0; dcode < D_CODES; dcode++) { -// out_length += s.dyn_dtree[dcode*2]/*.Freq*/ * (5 + extra_dbits[dcode]); -// } -// out_length >>>= 3; -// //Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", -// // s->last_lit, in_length, out_length, -// // 100L - out_length*100L/in_length)); -// if (s.matches < (s.last_lit>>1)/*int /2*/ && out_length < (in_length>>1)/*int /2*/) { -// return true; -// } -// } -//#endif +SHA512.prototype._digest = function digest(enc) { + if (enc === 'hex') + return utils.toHex32(this.h, 'big'); + else + return utils.split32(this.h, 'big'); +}; - return (s.last_lit === s.lit_bufsize - 1); - /* We avoid equality with lit_bufsize because of wraparound at 64K - * on 16 bit machines and because stored blocks are restricted to - * 64K-1 bytes. - */ +function ch64_hi(xh, xl, yh, yl, zh) { + var r = (xh & yh) ^ ((~xh) & zh); + if (r < 0) + r += 0x100000000; + return r; } -exports._tr_init = _tr_init; -exports._tr_stored_block = _tr_stored_block; -exports._tr_flush_block = _tr_flush_block; -exports._tr_tally = _tr_tally; -exports._tr_align = _tr_align; - -},{"../utils/common":53}],65:[function(require,module,exports){ -'use strict'; - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -function ZStream() { - /* next input byte */ - this.input = null; // JS specific, because we have no pointers - this.next_in = 0; - /* number of bytes available at input */ - this.avail_in = 0; - /* total number of input bytes read so far */ - this.total_in = 0; - /* next output byte should be put there */ - this.output = null; // JS specific, because we have no pointers - this.next_out = 0; - /* remaining free space at output */ - this.avail_out = 0; - /* total number of bytes output so far */ - this.total_out = 0; - /* last error message, NULL if no error */ - this.msg = ''/*Z_NULL*/; - /* not visible by applications */ - this.state = null; - /* best guess about the data type: binary or text */ - this.data_type = 2/*Z_UNKNOWN*/; - /* adler32 value of the uncompressed data */ - this.adler = 0; -} - -module.exports = ZStream; - -},{}],66:[function(require,module,exports){ -// shim for using process in browser -var process = module.exports = {}; - -// cached from whatever global is present so that test runners that stub it -// don't break things. But we need to wrap it in a try catch in case it is -// wrapped in strict mode code which doesn't define any globals. It's inside a -// function because try/catches deoptimize in certain engines. - -var cachedSetTimeout; -var cachedClearTimeout; - -function defaultSetTimout() { - throw new Error('setTimeout has not been defined'); -} -function defaultClearTimeout () { - throw new Error('clearTimeout has not been defined'); -} -(function () { - try { - if (typeof setTimeout === 'function') { - cachedSetTimeout = setTimeout; - } else { - cachedSetTimeout = defaultSetTimout; - } - } catch (e) { - cachedSetTimeout = defaultSetTimout; - } - try { - if (typeof clearTimeout === 'function') { - cachedClearTimeout = clearTimeout; - } else { - cachedClearTimeout = defaultClearTimeout; - } - } catch (e) { - cachedClearTimeout = defaultClearTimeout; - } -} ()) -function runTimeout(fun) { - if (cachedSetTimeout === setTimeout) { - //normal enviroments in sane situations - return setTimeout(fun, 0); - } - // if setTimeout wasn't available but was latter defined - if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { - cachedSetTimeout = setTimeout; - return setTimeout(fun, 0); - } - try { - // when when somebody has screwed with setTimeout but no I.E. maddness - return cachedSetTimeout(fun, 0); - } catch(e){ - try { - // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally - return cachedSetTimeout.call(null, fun, 0); - } catch(e){ - // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error - return cachedSetTimeout.call(this, fun, 0); - } - } - - +function ch64_lo(xh, xl, yh, yl, zh, zl) { + var r = (xl & yl) ^ ((~xl) & zl); + if (r < 0) + r += 0x100000000; + return r; } -function runClearTimeout(marker) { - if (cachedClearTimeout === clearTimeout) { - //normal enviroments in sane situations - return clearTimeout(marker); - } - // if clearTimeout wasn't available but was latter defined - if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { - cachedClearTimeout = clearTimeout; - return clearTimeout(marker); - } - try { - // when when somebody has screwed with setTimeout but no I.E. maddness - return cachedClearTimeout(marker); - } catch (e){ - try { - // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally - return cachedClearTimeout.call(null, marker); - } catch (e){ - // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. - // Some versions of I.E. have different rules for clearTimeout vs setTimeout - return cachedClearTimeout.call(this, marker); - } - } - +function maj64_hi(xh, xl, yh, yl, zh) { + var r = (xh & yh) ^ (xh & zh) ^ (yh & zh); + if (r < 0) + r += 0x100000000; + return r; +} +function maj64_lo(xh, xl, yh, yl, zh, zl) { + var r = (xl & yl) ^ (xl & zl) ^ (yl & zl); + if (r < 0) + r += 0x100000000; + return r; } -var queue = []; -var draining = false; -var currentQueue; -var queueIndex = -1; -function cleanUpNextTick() { - if (!draining || !currentQueue) { - return; - } - draining = false; - if (currentQueue.length) { - queue = currentQueue.concat(queue); - } else { - queueIndex = -1; - } - if (queue.length) { - drainQueue(); - } +function s0_512_hi(xh, xl) { + var c0_hi = rotr64_hi$1(xh, xl, 28); + var c1_hi = rotr64_hi$1(xl, xh, 2); // 34 + var c2_hi = rotr64_hi$1(xl, xh, 7); // 39 + + var r = c0_hi ^ c1_hi ^ c2_hi; + if (r < 0) + r += 0x100000000; + return r; } -function drainQueue() { - if (draining) { - return; - } - var timeout = runTimeout(cleanUpNextTick); - draining = true; +function s0_512_lo(xh, xl) { + var c0_lo = rotr64_lo$1(xh, xl, 28); + var c1_lo = rotr64_lo$1(xl, xh, 2); // 34 + var c2_lo = rotr64_lo$1(xl, xh, 7); // 39 - var len = queue.length; - while(len) { - currentQueue = queue; - queue = []; - while (++queueIndex < len) { - if (currentQueue) { - currentQueue[queueIndex].run(); - } - } - queueIndex = -1; - len = queue.length; - } - currentQueue = null; - draining = false; - runClearTimeout(timeout); + var r = c0_lo ^ c1_lo ^ c2_lo; + if (r < 0) + r += 0x100000000; + return r; } -process.nextTick = function (fun) { - var args = new Array(arguments.length - 1); - if (arguments.length > 1) { - for (var i = 1; i < arguments.length; i++) { - args[i - 1] = arguments[i]; - } - } - queue.push(new Item(fun, args)); - if (queue.length === 1 && !draining) { - runTimeout(drainQueue); - } -}; +function s1_512_hi(xh, xl) { + var c0_hi = rotr64_hi$1(xh, xl, 14); + var c1_hi = rotr64_hi$1(xh, xl, 18); + var c2_hi = rotr64_hi$1(xl, xh, 9); // 41 + + var r = c0_hi ^ c1_hi ^ c2_hi; + if (r < 0) + r += 0x100000000; + return r; +} + +function s1_512_lo(xh, xl) { + var c0_lo = rotr64_lo$1(xh, xl, 14); + var c1_lo = rotr64_lo$1(xh, xl, 18); + var c2_lo = rotr64_lo$1(xl, xh, 9); // 41 -// v8 likes predictible objects -function Item(fun, array) { - this.fun = fun; - this.array = array; + var r = c0_lo ^ c1_lo ^ c2_lo; + if (r < 0) + r += 0x100000000; + return r; } -Item.prototype.run = function () { - this.fun.apply(null, this.array); -}; -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; -process.version = ''; // empty string to avoid regexp issues -process.versions = {}; -function noop() {} +function g0_512_hi(xh, xl) { + var c0_hi = rotr64_hi$1(xh, xl, 1); + var c1_hi = rotr64_hi$1(xh, xl, 8); + var c2_hi = shr64_hi$1(xh, xl, 7); -process.on = noop; -process.addListener = noop; -process.once = noop; -process.off = noop; -process.removeListener = noop; -process.removeAllListeners = noop; -process.emit = noop; -process.prependListener = noop; -process.prependOnceListener = noop; + var r = c0_hi ^ c1_hi ^ c2_hi; + if (r < 0) + r += 0x100000000; + return r; +} -process.listeners = function (name) { return [] } +function g0_512_lo(xh, xl) { + var c0_lo = rotr64_lo$1(xh, xl, 1); + var c1_lo = rotr64_lo$1(xh, xl, 8); + var c2_lo = shr64_lo$1(xh, xl, 7); -process.binding = function (name) { - throw new Error('process.binding is not supported'); -}; + var r = c0_lo ^ c1_lo ^ c2_lo; + if (r < 0) + r += 0x100000000; + return r; +} -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); -}; -process.umask = function() { return 0; }; +function g1_512_hi(xh, xl) { + var c0_hi = rotr64_hi$1(xh, xl, 19); + var c1_hi = rotr64_hi$1(xl, xh, 29); // 61 + var c2_hi = shr64_hi$1(xh, xl, 6); -},{}],67:[function(require,module,exports){ -'use strict'; + var r = c0_hi ^ c1_hi ^ c2_hi; + if (r < 0) + r += 0x100000000; + return r; +} -/* -node-bzip - a pure-javascript Node.JS module for decoding bzip2 data +function g1_512_lo(xh, xl) { + var c0_lo = rotr64_lo$1(xh, xl, 19); + var c1_lo = rotr64_lo$1(xl, xh, 29); // 61 + var c2_lo = shr64_lo$1(xh, xl, 6); -Copyright (C) 2012 Eli Skeggs + var r = c0_lo ^ c1_lo ^ c2_lo; + if (r < 0) + r += 0x100000000; + return r; +} -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. +function SHA384() { + if (!(this instanceof SHA384)) + return new SHA384(); -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. + _512.call(this); + this.h = [ + 0xcbbb9d5d, 0xc1059ed8, + 0x629a292a, 0x367cd507, + 0x9159015a, 0x3070dd17, + 0x152fecd8, 0xf70e5939, + 0x67332667, 0xffc00b31, + 0x8eb44a87, 0x68581511, + 0xdb0c2e0d, 0x64f98fa7, + 0x47b5481d, 0xbefa4fa4 ]; +} +utils.inherits(SHA384, _512); +var _384 = SHA384; -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, see -http://www.gnu.org/licenses/lgpl-2.1.html +SHA384.blockSize = 1024; +SHA384.outSize = 384; +SHA384.hmacStrength = 192; +SHA384.padLength = 128; -Adapted from bzip2.js, copyright 2011 antimatter15 (antimatter15@gmail.com). +SHA384.prototype._digest = function digest(enc) { + if (enc === 'hex') + return utils.toHex32(this.h.slice(0, 12), 'big'); + else + return utils.split32(this.h.slice(0, 12), 'big'); +}; -Based on micro-bunzip by Rob Landley (rob@landley.net). +var rotl32$1 = utils.rotl32; +var sum32$2 = utils.sum32; +var sum32_3$1 = utils.sum32_3; +var sum32_4$2 = utils.sum32_4; +var BlockHash$3 = common.BlockHash; -Based on bzip2 decompression code by Julian R Seward (jseward@acm.org), -which also acknowledges contributions by Mike Burrows, David Wheeler, -Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten, -Robert Sedgewick, and Jon L. Bentley. -*/ +function RIPEMD160() { + if (!(this instanceof RIPEMD160)) + return new RIPEMD160(); -var BITMASK = [0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF]; + BlockHash$3.call(this); -// offset in bytes -var BitReader = function BitReader(stream) { - this.stream = stream; - this.bitOffset = 0; - this.curByte = 0; - this.hasByte = false; -}; + this.h = [ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 ]; + this.endian = 'little'; +} +utils.inherits(RIPEMD160, BlockHash$3); +var ripemd160 = RIPEMD160; -BitReader.prototype._ensureByte = function () { - if (!this.hasByte) { - this.curByte = this.stream.readByte(); - this.hasByte = true; - } -}; +RIPEMD160.blockSize = 512; +RIPEMD160.outSize = 160; +RIPEMD160.hmacStrength = 192; +RIPEMD160.padLength = 64; -// reads bits from the buffer -BitReader.prototype.read = function (bits) { - var result = 0; - while (bits > 0) { - this._ensureByte(); - var remaining = 8 - this.bitOffset; - // if we're in a byte - if (bits >= remaining) { - result <<= remaining; - result |= BITMASK[remaining] & this.curByte; - this.hasByte = false; - this.bitOffset = 0; - bits -= remaining; - } else { - result <<= bits; - var shift = remaining - bits; - result |= (this.curByte & BITMASK[bits] << shift) >> shift; - this.bitOffset += bits; - bits = 0; - } +RIPEMD160.prototype._update = function update(msg, start) { + var A = this.h[0]; + var B = this.h[1]; + var C = this.h[2]; + var D = this.h[3]; + var E = this.h[4]; + var Ah = A; + var Bh = B; + var Ch = C; + var Dh = D; + var Eh = E; + for (var j = 0; j < 80; j++) { + var T = sum32$2( + rotl32$1( + sum32_4$2(A, f(j, B, C, D), msg[r[j] + start], K(j)), + s[j]), + E); + A = E; + E = D; + D = rotl32$1(C, 10); + C = B; + B = T; + T = sum32$2( + rotl32$1( + sum32_4$2(Ah, f(79 - j, Bh, Ch, Dh), msg[rh[j] + start], Kh(j)), + sh[j]), + Eh); + Ah = Eh; + Eh = Dh; + Dh = rotl32$1(Ch, 10); + Ch = Bh; + Bh = T; } - return result; -}; - -// seek to an arbitrary point in the buffer (expressed in bits) -BitReader.prototype.seek = function (pos) { - var n_bit = pos % 8; - var n_byte = (pos - n_bit) / 8; - this.bitOffset = n_bit; - this.stream.seek(n_byte); - this.hasByte = false; + T = sum32_3$1(this.h[1], C, Dh); + this.h[1] = sum32_3$1(this.h[2], D, Eh); + this.h[2] = sum32_3$1(this.h[3], E, Ah); + this.h[3] = sum32_3$1(this.h[4], A, Bh); + this.h[4] = sum32_3$1(this.h[0], B, Ch); + this.h[0] = T; }; -// reads 6 bytes worth of data using the read method -BitReader.prototype.pi = function () { - var buf = new Uint8Array(6), - i; - for (i = 0; i < buf.length; i++) { - buf[i] = this.read(8); - } - return bufToHex(buf); +RIPEMD160.prototype._digest = function digest(enc) { + if (enc === 'hex') + return utils.toHex32(this.h, 'little'); + else + return utils.split32(this.h, 'little'); }; -function bufToHex(buf) { - return Array.prototype.map.call(buf, x => ('00' + x.toString(16)).slice(-2)).join(''); +function f(j, x, y, z) { + if (j <= 15) + return x ^ y ^ z; + else if (j <= 31) + return (x & y) | ((~x) & z); + else if (j <= 47) + return (x | (~y)) ^ z; + else if (j <= 63) + return (x & z) | (y & (~z)); + else + return x ^ (y | (~z)); } -module.exports = BitReader; - -},{}],68:[function(require,module,exports){ -"use strict"; - -/* CRC32, used in Bzip2 implementation. - * This is a port of CRC32.java from the jbzip2 implementation at - * https://code.google.com/p/jbzip2 - * which is: - * Copyright (c) 2011 Matthew Francis - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * This JavaScript implementation is: - * Copyright (c) 2013 C. Scott Ananian - * with the same licensing terms as Matthew Francis' original implementation. - */ -module.exports = function () { - - /** - * A static CRC lookup table - */ - var crc32Lookup = new Uint32Array([0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4]); - - var CRC32 = function CRC32() { - /** - * The current CRC - */ - var crc = 0xffffffff; - - /** - * @return The current CRC - */ - this.getCRC = function () { - return ~crc >>> 0; // return an unsigned value - }; - - /** - * Update the CRC with a single byte - * @param value The value to update the CRC with - */ - this.updateCRC = function (value) { - crc = crc << 8 ^ crc32Lookup[(crc >>> 24 ^ value) & 0xff]; - }; - - /** - * Update the CRC with a sequence of identical bytes - * @param value The value to update the CRC with - * @param count The number of bytes - */ - this.updateCRCRun = function (value, count) { - while (count-- > 0) { - crc = crc << 8 ^ crc32Lookup[(crc >>> 24 ^ value) & 0xff]; - } - }; - }; - return CRC32; -}(); +function K(j) { + if (j <= 15) + return 0x00000000; + else if (j <= 31) + return 0x5a827999; + else if (j <= 47) + return 0x6ed9eba1; + else if (j <= 63) + return 0x8f1bbcdc; + else + return 0xa953fd4e; +} -},{}],69:[function(require,module,exports){ -'use strict'; +function Kh(j) { + if (j <= 15) + return 0x50a28be6; + else if (j <= 31) + return 0x5c4dd124; + else if (j <= 47) + return 0x6d703ef3; + else if (j <= 63) + return 0x7a6d76e9; + else + return 0x00000000; +} -/* -seek-bzip - a pure-javascript module for seeking within bzip2 data +var r = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, + 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, + 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, + 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 +]; -Copyright (C) 2013 C. Scott Ananian -Copyright (C) 2012 Eli Skeggs -Copyright (C) 2011 Kevin Kwok +var rh = [ + 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, + 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, + 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, + 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, + 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 +]; -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. +var s = [ + 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, + 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, + 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, + 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, + 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 +]; -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. +var sh = [ + 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, + 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, + 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, + 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, + 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 +]; -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, see -http://www.gnu.org/licenses/lgpl-2.1.html +var ripemd = { + ripemd160: ripemd160 +}; -Adapted from node-bzip, copyright 2012 Eli Skeggs. -Adapted from bzip2.js, copyright 2011 Kevin Kwok (antimatter15@gmail.com). +/** + * A fast MD5 JavaScript implementation + * Copyright (c) 2012 Joseph Myers + * http://www.myersdaily.org/joseph/javascript/md5-text.html + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purposes and without + * fee is hereby granted provided that this copyright notice + * appears in all copies. + * + * Of course, this soft is provided "as is" without express or implied + * warranty of any kind. + */ -Based on micro-bunzip by Rob Landley (rob@landley.net). +// MD5 Digest +async function md5(entree) { + const digest = md51(util.uint8ArrayToString(entree)); + return util.hexToUint8Array(hex(digest)); +} -Based on bzip2 decompression code by Julian R Seward (jseward@acm.org), -which also acknowledges contributions by Mike Burrows, David Wheeler, -Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten, -Robert Sedgewick, and Jon L. Bentley. -*/ +function md5cycle(x, k) { + let a = x[0]; + let b = x[1]; + let c = x[2]; + let d = x[3]; -var BitReader = require('./bitreader'); -var Stream = require('./stream'); -var CRC32 = require('./crc32'); + a = ff(a, b, c, d, k[0], 7, -680876936); + d = ff(d, a, b, c, k[1], 12, -389564586); + c = ff(c, d, a, b, k[2], 17, 606105819); + b = ff(b, c, d, a, k[3], 22, -1044525330); + a = ff(a, b, c, d, k[4], 7, -176418897); + d = ff(d, a, b, c, k[5], 12, 1200080426); + c = ff(c, d, a, b, k[6], 17, -1473231341); + b = ff(b, c, d, a, k[7], 22, -45705983); + a = ff(a, b, c, d, k[8], 7, 1770035416); + d = ff(d, a, b, c, k[9], 12, -1958414417); + c = ff(c, d, a, b, k[10], 17, -42063); + b = ff(b, c, d, a, k[11], 22, -1990404162); + a = ff(a, b, c, d, k[12], 7, 1804603682); + d = ff(d, a, b, c, k[13], 12, -40341101); + c = ff(c, d, a, b, k[14], 17, -1502002290); + b = ff(b, c, d, a, k[15], 22, 1236535329); -var MAX_HUFCODE_BITS = 20; -var MAX_SYMBOLS = 258; -var SYMBOL_RUNA = 0; -var SYMBOL_RUNB = 1; -var MIN_GROUPS = 2; -var MAX_GROUPS = 6; -var GROUP_SIZE = 50; + a = gg(a, b, c, d, k[1], 5, -165796510); + d = gg(d, a, b, c, k[6], 9, -1069501632); + c = gg(c, d, a, b, k[11], 14, 643717713); + b = gg(b, c, d, a, k[0], 20, -373897302); + a = gg(a, b, c, d, k[5], 5, -701558691); + d = gg(d, a, b, c, k[10], 9, 38016083); + c = gg(c, d, a, b, k[15], 14, -660478335); + b = gg(b, c, d, a, k[4], 20, -405537848); + a = gg(a, b, c, d, k[9], 5, 568446438); + d = gg(d, a, b, c, k[14], 9, -1019803690); + c = gg(c, d, a, b, k[3], 14, -187363961); + b = gg(b, c, d, a, k[8], 20, 1163531501); + a = gg(a, b, c, d, k[13], 5, -1444681467); + d = gg(d, a, b, c, k[2], 9, -51403784); + c = gg(c, d, a, b, k[7], 14, 1735328473); + b = gg(b, c, d, a, k[12], 20, -1926607734); -var WHOLEPI = "314159265359"; -var SQRTPI = "177245385090"; + a = hh(a, b, c, d, k[5], 4, -378558); + d = hh(d, a, b, c, k[8], 11, -2022574463); + c = hh(c, d, a, b, k[11], 16, 1839030562); + b = hh(b, c, d, a, k[14], 23, -35309556); + a = hh(a, b, c, d, k[1], 4, -1530992060); + d = hh(d, a, b, c, k[4], 11, 1272893353); + c = hh(c, d, a, b, k[7], 16, -155497632); + b = hh(b, c, d, a, k[10], 23, -1094730640); + a = hh(a, b, c, d, k[13], 4, 681279174); + d = hh(d, a, b, c, k[0], 11, -358537222); + c = hh(c, d, a, b, k[3], 16, -722521979); + b = hh(b, c, d, a, k[6], 23, 76029189); + a = hh(a, b, c, d, k[9], 4, -640364487); + d = hh(d, a, b, c, k[12], 11, -421815835); + c = hh(c, d, a, b, k[15], 16, 530742520); + b = hh(b, c, d, a, k[2], 23, -995338651); -var mtf = function mtf(array, index) { - var src = array[index], - i; - for (i = index; i > 0; i--) { - array[i] = array[i - 1]; - } - array[0] = src; - return src; -}; + a = ii(a, b, c, d, k[0], 6, -198630844); + d = ii(d, a, b, c, k[7], 10, 1126891415); + c = ii(c, d, a, b, k[14], 15, -1416354905); + b = ii(b, c, d, a, k[5], 21, -57434055); + a = ii(a, b, c, d, k[12], 6, 1700485571); + d = ii(d, a, b, c, k[3], 10, -1894986606); + c = ii(c, d, a, b, k[10], 15, -1051523); + b = ii(b, c, d, a, k[1], 21, -2054922799); + a = ii(a, b, c, d, k[8], 6, 1873313359); + d = ii(d, a, b, c, k[15], 10, -30611744); + c = ii(c, d, a, b, k[6], 15, -1560198380); + b = ii(b, c, d, a, k[13], 21, 1309151649); + a = ii(a, b, c, d, k[4], 6, -145523070); + d = ii(d, a, b, c, k[11], 10, -1120210379); + c = ii(c, d, a, b, k[2], 15, 718787259); + b = ii(b, c, d, a, k[9], 21, -343485551); -var Err = { - OK: 0, - LAST_BLOCK: -1, - NOT_BZIP_DATA: -2, - UNEXPECTED_INPUT_EOF: -3, - UNEXPECTED_OUTPUT_EOF: -4, - DATA_ERROR: -5, - OUT_OF_MEMORY: -6, - OBSOLETE_INPUT: -7, - END_OF_BLOCK: -8 -}; -var ErrorMessages = {}; -ErrorMessages[Err.LAST_BLOCK] = "Bad file checksum"; -ErrorMessages[Err.NOT_BZIP_DATA] = "Not bzip data"; -ErrorMessages[Err.UNEXPECTED_INPUT_EOF] = "Unexpected input EOF"; -ErrorMessages[Err.UNEXPECTED_OUTPUT_EOF] = "Unexpected output EOF"; -ErrorMessages[Err.DATA_ERROR] = "Data error"; -ErrorMessages[Err.OUT_OF_MEMORY] = "Out of memory"; -ErrorMessages[Err.OBSOLETE_INPUT] = "Obsolete (pre 0.9.5) bzip format not supported."; + x[0] = add32(a, x[0]); + x[1] = add32(b, x[1]); + x[2] = add32(c, x[2]); + x[3] = add32(d, x[3]); +} -var _throw = function _throw(status, optDetail) { - var msg = ErrorMessages[status] || 'unknown error'; - if (optDetail) { - msg += ': ' + optDetail; - } - var e = new TypeError(msg); - e.errorCode = status; - throw e; -}; +function cmn(q, a, b, x, s, t) { + a = add32(add32(a, q), add32(x, t)); + return add32((a << s) | (a >>> (32 - s)), b); +} -var Bunzip = function Bunzip(inputStream, outputStream) { - this.writePos = this.writeCurrent = this.writeCount = 0; +function ff(a, b, c, d, x, s, t) { + return cmn((b & c) | ((~b) & d), a, b, x, s, t); +} - this._start_bunzip(inputStream, outputStream); -}; -Bunzip.prototype._init_block = function () { - var moreBlocks = this._get_next_block(); - if (!moreBlocks) { - this.writeCount = -1; - return false; /* no more blocks */ - } - this.blockCRC = new CRC32(); - return true; -}; -/* XXX micro-bunzip uses (inputStream, inputBuffer, len) as arguments */ -Bunzip.prototype._start_bunzip = function (inputStream, outputStream) { - /* Ensure that file starts with "BZh['1'-'9']." */ - var buf = new Uint8Array(4); - if (inputStream.read(buf, 0, 4) !== 4 || String.fromCharCode(buf[0], buf[1], buf[2]) !== 'BZh') _throw(Err.NOT_BZIP_DATA, 'bad magic'); +function gg(a, b, c, d, x, s, t) { + return cmn((b & d) | (c & (~d)), a, b, x, s, t); +} - var level = buf[3] - 0x30; - if (level < 1 || level > 9) _throw(Err.NOT_BZIP_DATA, 'level out of range'); +function hh(a, b, c, d, x, s, t) { + return cmn(b ^ c ^ d, a, b, x, s, t); +} - this.reader = new BitReader(inputStream); +function ii(a, b, c, d, x, s, t) { + return cmn(c ^ (b | (~d)), a, b, x, s, t); +} - /* Fourth byte (ascii '1'-'9'), indicates block size in units of 100k of - uncompressed data. Allocate intermediate buffer for block. */ - this.dbufSize = 100000 * level; - this.nextoutput = 0; - this.outputStream = outputStream; - this.streamCRC = 0; -}; -Bunzip.prototype._get_next_block = function () { - var i, j, k; - var reader = this.reader; - // this is get_next_block() function from micro-bunzip: - /* Read in header signature and CRC, then validate signature. - (last block signature means CRC is for whole file, return now) */ - var h = reader.pi(); - if (h === SQRTPI) { - // last block - return false; /* no more blocks */ +function md51(s) { + const n = s.length; + const state = [1732584193, -271733879, -1732584194, 271733878]; + let i; + for (i = 64; i <= s.length; i += 64) { + md5cycle(state, md5blk(s.substring(i - 64, i))); } - if (h !== WHOLEPI) _throw(Err.NOT_BZIP_DATA); - this.targetBlockCRC = reader.read(32) >>> 0; // (convert to unsigned) - this.streamCRC = (this.targetBlockCRC ^ (this.streamCRC << 1 | this.streamCRC >>> 31)) >>> 0; - /* We can add support for blockRandomised if anybody complains. There was - some code for this in busybox 1.0.0-pre3, but nobody ever noticed that - it didn't actually work. */ - if (reader.read(1)) _throw(Err.OBSOLETE_INPUT); - var origPointer = reader.read(24); - if (origPointer > this.dbufSize) _throw(Err.DATA_ERROR, 'initial position out of bounds'); - /* mapping table: if some byte values are never used (encoding things - like ascii text), the compression code removes the gaps to have fewer - symbols to deal with, and writes a sparse bitfield indicating which - values were present. We make a translation table to convert the symbols - back to the corresponding bytes. */ - var t = reader.read(16); - var symToByte = new Uint8Array(256), - symTotal = 0; - for (i = 0; i < 16; i++) { - if (t & 1 << 0xF - i) { - var o = i * 16; - k = reader.read(16); - for (j = 0; j < 16; j++) if (k & 1 << 0xF - j) symToByte[symTotal++] = o + j; + s = s.substring(i - 64); + const tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + for (i = 0; i < s.length; i++) { + tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3); + } + tail[i >> 2] |= 0x80 << ((i % 4) << 3); + if (i > 55) { + md5cycle(state, tail); + for (i = 0; i < 16; i++) { + tail[i] = 0; } } + tail[14] = n * 8; + md5cycle(state, tail); + return state; +} + +/* there needs to be support for Unicode here, + * unless we pretend that we can redefine the MD-5 + * algorithm for multi-byte characters (perhaps + * by adding every four 16-bit characters and + * shortening the sum to 32 bits). Otherwise + * I suggest performing MD-5 as if every character + * was two bytes--e.g., 0040 0025 = @%--but then + * how will an ordinary MD-5 sum be matched? + * There is no way to standardize text to something + * like UTF-8 before transformation; speed cost is + * utterly prohibitive. The JavaScript standard + * itself needs to look at this: it should start + * providing access to strings as preformed UTF-8 + * 8-bit unsigned value arrays. + */ +function md5blk(s) { /* I figured global was faster. */ + const md5blks = []; + let i; /* Andy King said do it this way. */ + for (i = 0; i < 64; i += 4) { + md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << + 24); + } + return md5blks; +} - /* How many different huffman coding groups does this block use? */ - var groupCount = reader.read(3); - if (groupCount < MIN_GROUPS || groupCount > MAX_GROUPS) _throw(Err.DATA_ERROR); - /* nSelectors: Every GROUP_SIZE many symbols we select a new huffman coding - group. Read in the group selector list, which is stored as MTF encoded - bit runs. (MTF=Move To Front, as each value is used it's moved to the - start of the list.) */ - var nSelectors = reader.read(15); - if (nSelectors === 0) _throw(Err.DATA_ERROR); - - var mtfSymbol = new Uint8Array(256); - for (i = 0; i < groupCount; i++) mtfSymbol[i] = i; +const hex_chr = '0123456789abcdef'.split(''); - var selectors = new Uint8Array(nSelectors); // was 32768... +function rhex(n) { + let s = ''; + let j = 0; + for (; j < 4; j++) { + s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F]; + } + return s; +} - for (i = 0; i < nSelectors; i++) { - /* Get next value */ - for (j = 0; reader.read(1); j++) if (j >= groupCount) _throw(Err.DATA_ERROR); - /* Decode MTF to get the next selector */ - selectors[i] = mtf(mtfSymbol, j); +function hex(x) { + for (let i = 0; i < x.length; i++) { + x[i] = rhex(x[i]); } + return x.join(''); +} - /* Read the huffman coding tables for each group, which code for symTotal - literal symbols, plus two run symbols (RUNA, RUNB) */ - var symCount = symTotal + 2; - var groups = [], - hufGroup; - for (j = 0; j < groupCount; j++) { - var length = new Uint8Array(symCount), - temp = new Uint16Array(MAX_HUFCODE_BITS + 1); - /* Read huffman code lengths for each symbol. They're stored in - a way similar to mtf; record a starting value for the first symbol, - and an offset from the previous value for everys symbol after that. */ - t = reader.read(5); // lengths - for (i = 0; i < symCount; i++) { - for (;;) { - if (t < 1 || t > MAX_HUFCODE_BITS) _throw(Err.DATA_ERROR); - /* If first bit is 0, stop. Else second bit indicates whether - to increment or decrement the value. */ - if (!reader.read(1)) break; - if (!reader.read(1)) t++;else t--; - } - length[i] = t; - } +/* this function is much faster, +so if possible we use it. Some IEs +are the only ones I know of that +need the idiotic second function, +generated by an if clause. */ - /* Find largest and smallest lengths in this group */ - var minLen, maxLen; - minLen = maxLen = length[0]; - for (i = 1; i < symCount; i++) { - if (length[i] > maxLen) maxLen = length[i];else if (length[i] < minLen) minLen = length[i]; - } +function add32(a, b) { + return (a + b) & 0xFFFFFFFF; +} - /* Calculate permute[], base[], and limit[] tables from length[]. - * - * permute[] is the lookup table for converting huffman coded symbols - * into decoded symbols. base[] is the amount to subtract from the - * value of a huffman symbol of a given length when using permute[]. - * - * limit[] indicates the largest numerical value a symbol with a given - * number of bits can have. This is how the huffman codes can vary in - * length: each code with a value>limit[length] needs another bit. - */ - hufGroup = {}; - groups.push(hufGroup); - hufGroup.permute = new Uint16Array(MAX_SYMBOLS); - hufGroup.limit = new Uint32Array(MAX_HUFCODE_BITS + 2); - hufGroup.base = new Uint32Array(MAX_HUFCODE_BITS + 1); - hufGroup.minLen = minLen; - hufGroup.maxLen = maxLen; - /* Calculate permute[]. Concurently, initialize temp[] and limit[]. */ - var pp = 0; - for (i = minLen; i <= maxLen; i++) { - temp[i] = hufGroup.limit[i] = 0; - for (t = 0; t < symCount; t++) if (length[t] === i) hufGroup.permute[pp++] = t; - } - /* Count symbols coded for at each bit length */ - for (i = 0; i < symCount; i++) temp[length[i]]++; - /* Calculate limit[] (the largest symbol-coding value at each bit - * length, which is (previous limit<<1)+symbols at this level), and - * base[] (number of symbols to ignore at each bit length, which is - * limit minus the cumulative count of symbols coded for already). */ - pp = t = 0; - for (i = minLen; i < maxLen; i++) { - pp += temp[i]; - /* We read the largest possible symbol size and then unget bits - after determining how many we need, and those extra bits could - be set to anything. (They're noise from future symbols.) At - each level we're really only interested in the first few bits, - so here we set all the trailing to-be-ignored bits to 1 so they - don't affect the value>limit[length] comparison. */ - hufGroup.limit[i] = pp - 1; - pp <<= 1; - t += temp[i]; - hufGroup.base[i + 1] = pp - t; - } - hufGroup.limit[maxLen + 1] = Number.MAX_VALUE; /* Sentinal value for reading next sym. */ - hufGroup.limit[maxLen] = pp + temp[maxLen] - 1; - hufGroup.base[minLen] = 0; - } - /* We've finished reading and digesting the block header. Now read this - block's huffman coded symbols from the file and undo the huffman coding - and run length encoding, saving the result into dbuf[dbufCount++]=uc */ +/** + * @fileoverview Provides an interface to hashing functions available in Node.js or external libraries. + * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} + * @see {@link https://github.com/indutny/hash.js|hash.js} + * @module crypto/hash + * @private + */ - /* Initialize symbol occurrence counters and symbol Move To Front table */ - var byteCount = new Uint32Array(256); - for (i = 0; i < 256; i++) mtfSymbol[i] = i; - /* Loop through compressed symbols. */ - var runPos = 0, - dbufCount = 0, - selector = 0, - uc; - var dbuf = this.dbuf = new Uint32Array(this.dbufSize); - symCount = 0; - for (;;) { - /* Determine which huffman coding group to use. */ - if (!symCount--) { - symCount = GROUP_SIZE - 1; - if (selector >= nSelectors) { - _throw(Err.DATA_ERROR); - } - hufGroup = groups[selectors[selector++]]; - } - /* Read next huffman-coded symbol. */ - i = hufGroup.minLen; - j = reader.read(i); - for (;; i++) { - if (i > hufGroup.maxLen) { - _throw(Err.DATA_ERROR); - } - if (j <= hufGroup.limit[i]) break; - j = j << 1 | reader.read(1); +const webCrypto = util.getWebCrypto(); +const nodeCrypto = util.getNodeCrypto(); + +function nodeHash(type) { + return async function (data) { + const shasum = nodeCrypto.createHash(type); + return transform(data, value => { + shasum.update(value); + }, () => new Uint8Array(shasum.digest())); + }; +} + +function hashjsHash(hash, webCryptoHash) { + return async function(data, config = defaultConfig) { + if (isArrayStream(data)) { + data = await readToEnd(data); } - /* Huffman decode value to get nextSym (with bounds checking) */ - j -= hufGroup.base[i]; - if (j < 0 || j >= MAX_SYMBOLS) { - _throw(Err.DATA_ERROR); + if (!util.isStream(data) && webCrypto && webCryptoHash && data.length >= config.minBytesForWebCrypto) { + return new Uint8Array(await webCrypto.digest(webCryptoHash, data)); } - var nextSym = hufGroup.permute[j]; - /* We have now decoded the symbol, which indicates either a new literal - byte, or a repeated run of the most recent literal byte. First, - check if nextSym indicates a repeated run, and if so loop collecting - how many times to repeat the last literal. */ - if (nextSym === SYMBOL_RUNA || nextSym === SYMBOL_RUNB) { - /* If this is the start of a new run, zero out counter */ - if (!runPos) { - runPos = 1; - t = 0; - } - /* Neat trick that saves 1 symbol: instead of or-ing 0 or 1 at - each bit position, add 1 or 2 instead. For example, - 1011 is 1<<0 + 1<<1 + 2<<2. 1010 is 2<<0 + 2<<1 + 1<<2. - You can make any bit pattern that way using 1 less symbol than - the basic or 0/1 method (except all bits 0, which would use no - symbols, but a run of length 0 doesn't mean anything in this - context). Thus space is saved. */ - if (nextSym === SYMBOL_RUNA) t += runPos;else t += 2 * runPos; - runPos <<= 1; - continue; + const hashInstance = hash(); + return transform(data, value => { + hashInstance.update(value); + }, () => new Uint8Array(hashInstance.digest())); + }; +} + +function asmcryptoHash(hash, webCryptoHash) { + return async function(data, config = defaultConfig) { + if (isArrayStream(data)) { + data = await readToEnd(data); } - /* When we hit the first non-run symbol after a run, we now know - how many times to repeat the last literal, so append that many - copies to our buffer of decoded symbols (dbuf) now. (The last - literal used is the one at the head of the mtfSymbol array.) */ - if (runPos) { - runPos = 0; - if (dbufCount + t > this.dbufSize) { - _throw(Err.DATA_ERROR); - } - uc = symToByte[mtfSymbol[0]]; - byteCount[uc] += t; - while (t--) dbuf[dbufCount++] = uc; + if (util.isStream(data)) { + const hashInstance = new hash(); + return transform(data, value => { + hashInstance.process(value); + }, () => hashInstance.finish().result); + } else if (webCrypto && webCryptoHash && data.length >= config.minBytesForWebCrypto) { + return new Uint8Array(await webCrypto.digest(webCryptoHash, data)); + } else { + return hash.bytes(data); } - /* Is this the terminating symbol? */ - if (nextSym > symTotal) break; - /* At this point, nextSym indicates a new literal character. Subtract - one to get the position in the MTF array at which this literal is - currently to be found. (Note that the result can't be -1 or 0, - because 0 and 1 are RUNA and RUNB. But another instance of the - first symbol in the mtf array, position 0, would have been handled - as part of a run above. Therefore 1 unused mtf position minus - 2 non-literal nextSym values equals -1.) */ - if (dbufCount >= this.dbufSize) { - _throw(Err.DATA_ERROR); + }; +} + +let hashFunctions; +if (nodeCrypto) { // Use Node native crypto for all hash functions + hashFunctions = { + md5: nodeHash('md5'), + sha1: nodeHash('sha1'), + sha224: nodeHash('sha224'), + sha256: nodeHash('sha256'), + sha384: nodeHash('sha384'), + sha512: nodeHash('sha512'), + ripemd: nodeHash('ripemd160') + }; +} else { // Use JS fallbacks + hashFunctions = { + md5: md5, + sha1: asmcryptoHash(Sha1, (!navigator.userAgent || navigator.userAgent.indexOf('Edge') === -1) && 'SHA-1'), + sha224: hashjsHash(_224), + sha256: asmcryptoHash(Sha256, 'SHA-256'), + sha384: hashjsHash(_384, 'SHA-384'), + sha512: hashjsHash(_512, 'SHA-512'), // asmcrypto sha512 is huge. + ripemd: hashjsHash(ripemd160) + }; +} + +var hash = { + + /** @see module:md5 */ + md5: hashFunctions.md5, + /** @see asmCrypto */ + sha1: hashFunctions.sha1, + /** @see hash.js */ + sha224: hashFunctions.sha224, + /** @see asmCrypto */ + sha256: hashFunctions.sha256, + /** @see hash.js */ + sha384: hashFunctions.sha384, + /** @see asmCrypto */ + sha512: hashFunctions.sha512, + /** @see hash.js */ + ripemd: hashFunctions.ripemd, + + /** + * Create a hash on the specified data using the specified algorithm + * @param {module:enums.hash} algo - Hash algorithm type (see {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}) + * @param {Uint8Array} data - Data to be hashed + * @returns {Promise} Hash value. + */ + digest: function(algo, data) { + switch (algo) { + case enums.hash.md5: + return this.md5(data); + case enums.hash.sha1: + return this.sha1(data); + case enums.hash.ripemd: + return this.ripemd(data); + case enums.hash.sha256: + return this.sha256(data); + case enums.hash.sha384: + return this.sha384(data); + case enums.hash.sha512: + return this.sha512(data); + case enums.hash.sha224: + return this.sha224(data); + default: + throw new Error('Invalid hash function.'); + } + }, + + /** + * Returns the hash size in bytes of the specified hash algorithm type + * @param {module:enums.hash} algo - Hash algorithm type (See {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}) + * @returns {Integer} Size in bytes of the resulting hash. + */ + getHashByteLength: function(algo) { + switch (algo) { + case enums.hash.md5: + return 16; + case enums.hash.sha1: + case enums.hash.ripemd: + return 20; + case enums.hash.sha256: + return 32; + case enums.hash.sha384: + return 48; + case enums.hash.sha512: + return 64; + case enums.hash.sha224: + return 28; + default: + throw new Error('Invalid hash algorithm.'); } - i = nextSym - 1; - uc = mtf(mtfSymbol, i); - uc = symToByte[uc]; - /* We have our literal byte. Save it into dbuf. */ - byteCount[uc]++; - dbuf[dbufCount++] = uc; - } - /* At this point, we've read all the huffman-coded symbols (and repeated - runs) for this block from the input stream, and decoded them into the - intermediate buffer. There are dbufCount many decoded bytes in dbuf[]. - Now undo the Burrows-Wheeler transform on dbuf. - See http://dogma.net/markn/articles/bwt/bwt.htm - */ - if (origPointer < 0 || origPointer >= dbufCount) { - _throw(Err.DATA_ERROR); - } - /* Turn byteCount into cumulative occurrence counts of 0 to n-1. */ - j = 0; - for (i = 0; i < 256; i++) { - k = j + byteCount[i]; - byteCount[i] = j; - j = k; } - /* Figure out what order dbuf would be in if we sorted it. */ - for (i = 0; i < dbufCount; i++) { - uc = dbuf[i] & 0xff; - dbuf[byteCount[uc]] |= i << 8; - byteCount[uc]++; +}; + +class AES_CFB { + static encrypt(data, key, iv) { + return new AES_CFB(key, iv).encrypt(data); + } + static decrypt(data, key, iv) { + return new AES_CFB(key, iv).decrypt(data); + } + constructor(key, iv, aes) { + this.aes = aes ? aes : new AES(key, iv, true, 'CFB'); + delete this.aes.padding; + } + encrypt(data) { + const r1 = this.aes.AES_Encrypt_process(data); + const r2 = this.aes.AES_Encrypt_finish(); + return joinBytes(r1, r2); + } + decrypt(data) { + const r1 = this.aes.AES_Decrypt_process(data); + const r2 = this.aes.AES_Decrypt_finish(); + return joinBytes(r1, r2); + } +} + +// Modified by ProtonTech AG + +const webCrypto$1 = util.getWebCrypto(); +const nodeCrypto$1 = util.getNodeCrypto(); + +const knownAlgos = nodeCrypto$1 ? nodeCrypto$1.getCiphers() : []; +const nodeAlgos = { + idea: knownAlgos.includes('idea-cfb') ? 'idea-cfb' : undefined, /* Unused, not implemented */ + tripledes: knownAlgos.includes('des-ede3-cfb') ? 'des-ede3-cfb' : undefined, + cast5: knownAlgos.includes('cast5-cfb') ? 'cast5-cfb' : undefined, + blowfish: knownAlgos.includes('bf-cfb') ? 'bf-cfb' : undefined, + aes128: knownAlgos.includes('aes-128-cfb') ? 'aes-128-cfb' : undefined, + aes192: knownAlgos.includes('aes-192-cfb') ? 'aes-192-cfb' : undefined, + aes256: knownAlgos.includes('aes-256-cfb') ? 'aes-256-cfb' : undefined + /* twofish is not implemented in OpenSSL */ +}; + +/** + * CFB encryption + * @param {enums.symmetric} algo - block cipher algorithm + * @param {Uint8Array} key + * @param {MaybeStream} plaintext + * @param {Uint8Array} iv + * @param {Object} config - full configuration, defaults to openpgp.config + * @returns MaybeStream + */ +async function encrypt(algo, key, plaintext, iv, config) { + const algoName = enums.read(enums.symmetric, algo); + if (util.getNodeCrypto() && nodeAlgos[algoName]) { // Node crypto library. + return nodeEncrypt(algo, key, plaintext, iv); } - /* Decode first byte by hand to initialize "previous" byte. Note that it - doesn't get output, and if the first three characters are identical - it doesn't qualify as a run (hence writeRunCountdown=5). */ - var pos = 0, - current = 0, - run = 0; - if (dbufCount) { - pos = dbuf[origPointer]; - current = pos & 0xff; - pos >>= 8; - run = -1; + if (algoName.substr(0, 3) === 'aes') { + return aesEncrypt(algo, key, plaintext, iv, config); } - this.writePos = pos; - this.writeCurrent = current; - this.writeCount = dbufCount; - this.writeRun = run; - return true; /* more blocks to come */ -}; -/* Undo burrows-wheeler transform on intermediate buffer to produce output. - If start_bunzip was initialized with out_fd=-1, then up to len bytes of - data are written to outbuf. Return value is number of bytes written or - error (all errors are negative numbers). If out_fd!=-1, outbuf and len - are ignored, data is written to out_fd and return is RETVAL_OK or error. -*/ -Bunzip.prototype._read_bunzip = function (outputBuffer, len) { - var copies, previous, outbyte; - /* james@jamestaylor.org: writeCount goes to -1 when the buffer is fully - decoded, which results in this returning RETVAL_LAST_BLOCK, also - equal to -1... Confusing, I'm returning 0 here to indicate no - bytes written into the buffer */ - if (this.writeCount < 0) { - return 0; + const cipherfn = new cipher[algoName](key); + const block_size = cipherfn.blockSize; + + const blockc = iv.slice(); + let pt = new Uint8Array(); + const process = chunk => { + if (chunk) { + pt = util.concatUint8Array([pt, chunk]); + } + const ciphertext = new Uint8Array(pt.length); + let i; + let j = 0; + while (chunk ? pt.length >= block_size : pt.length) { + const encblock = cipherfn.encrypt(blockc); + for (i = 0; i < block_size; i++) { + blockc[i] = pt[i] ^ encblock[i]; + ciphertext[j++] = blockc[i]; + } + pt = pt.subarray(block_size); + } + return ciphertext.subarray(0, j); + }; + return transform(plaintext, process, process); +} + +/** + * CFB decryption + * @param {enums.symmetric} algo - block cipher algorithm + * @param {Uint8Array} key + * @param {MaybeStream} ciphertext + * @param {Uint8Array} iv + * @returns MaybeStream + */ +async function decrypt(algo, key, ciphertext, iv) { + const algoName = enums.read(enums.symmetric, algo); + if (util.getNodeCrypto() && nodeAlgos[algoName]) { // Node crypto library. + return nodeDecrypt(algo, key, ciphertext, iv); + } + if (algoName.substr(0, 3) === 'aes') { + return aesDecrypt(algo, key, ciphertext, iv); } - var gotcount = 0; - var dbuf = this.dbuf, - pos = this.writePos, - current = this.writeCurrent; - var dbufCount = this.writeCount, - outputsize = this.outputsize; - var run = this.writeRun; + const cipherfn = new cipher[algoName](key); + const block_size = cipherfn.blockSize; - while (dbufCount) { - dbufCount--; - previous = current; - pos = dbuf[pos]; - current = pos & 0xff; - pos >>= 8; - if (run++ === 3) { - copies = current; - outbyte = previous; - current = -1; - } else { - copies = 1; - outbyte = current; + let blockp = iv; + let ct = new Uint8Array(); + const process = chunk => { + if (chunk) { + ct = util.concatUint8Array([ct, chunk]); } - this.blockCRC.updateCRCRun(outbyte, copies); - while (copies--) { - this.outputStream.writeByte(outbyte); - this.nextoutput++; + const plaintext = new Uint8Array(ct.length); + let i; + let j = 0; + while (chunk ? ct.length >= block_size : ct.length) { + const decblock = cipherfn.encrypt(blockp); + blockp = ct; + for (i = 0; i < block_size; i++) { + plaintext[j++] = blockp[i] ^ decblock[i]; + } + ct = ct.subarray(block_size); } - if (current != previous) run = 0; + return plaintext.subarray(0, j); + }; + return transform(ciphertext, process, process); +} + +function aesEncrypt(algo, key, pt, iv, config) { + if ( + util.getWebCrypto() && + key.length !== 24 && // Chrome doesn't support 192 bit keys, see https://www.chromium.org/blink/webcrypto#TOC-AES-support + !util.isStream(pt) && + pt.length >= 3000 * config.minBytesForWebCrypto // Default to a 3MB minimum. Chrome is pretty slow for small messages, see: https://bugs.chromium.org/p/chromium/issues/detail?id=701188#c2 + ) { // Web Crypto + return webEncrypt(algo, key, pt, iv); } - this.writeCount = dbufCount; - // check CRC - if (this.blockCRC.getCRC() !== this.targetBlockCRC) { - _throw(Err.DATA_ERROR, "Bad block CRC " + "(got " + this.blockCRC.getCRC().toString(16) + " expected " + this.targetBlockCRC.toString(16) + ")"); + // asm.js fallback + const cfb = new AES_CFB(key, iv); + return transform(pt, value => cfb.aes.AES_Encrypt_process(value), () => cfb.aes.AES_Encrypt_finish()); +} + +function aesDecrypt(algo, key, ct, iv) { + if (util.isStream(ct)) { + const cfb = new AES_CFB(key, iv); + return transform(ct, value => cfb.aes.AES_Decrypt_process(value), () => cfb.aes.AES_Decrypt_finish()); } - return this.nextoutput; -}; + return AES_CFB.decrypt(ct, key, iv); +} -var coerceInputStream = function coerceInputStream(input) { - if ('readByte' in input) { - return input; +function xorMut(a, b) { + for (let i = 0; i < a.length; i++) { + a[i] = a[i] ^ b[i]; } - var inputStream = new Stream(); - inputStream.pos = 0; - inputStream.readByte = function () { - return input[this.pos++]; - }; - inputStream.seek = function (pos) { - this.pos = pos; - }; - inputStream.eof = function () { - return this.pos >= input.length; - }; - return inputStream; -}; -var coerceOutputStream = function coerceOutputStream(output) { - var outputStream = new Stream(); - var resizeOk = true; - if (output) { - if (typeof output === 'number') { - outputStream.buffer = new Uint8Array(output); - resizeOk = false; - } else if ('writeByte' in output) { - return output; - } else { - outputStream.buffer = output; - resizeOk = false; +} + +async function webEncrypt(algo, key, pt, iv) { + const ALGO = 'AES-CBC'; + const _key = await webCrypto$1.importKey('raw', key, { name: ALGO }, false, ['encrypt']); + const { blockSize } = crypto.getCipher(algo); + const cbc_pt = util.concatUint8Array([new Uint8Array(blockSize), pt]); + const ct = new Uint8Array(await webCrypto$1.encrypt({ name: ALGO, iv }, _key, cbc_pt)).subarray(0, pt.length); + xorMut(ct, pt); + return ct; +} + +function nodeEncrypt(algo, key, pt, iv) { + const algoName = enums.read(enums.symmetric, algo); + const cipherObj = new nodeCrypto$1.createCipheriv(nodeAlgos[algoName], key, iv); + return transform(pt, value => new Uint8Array(cipherObj.update(value))); +} + +function nodeDecrypt(algo, key, ct, iv) { + const algoName = enums.read(enums.symmetric, algo); + const decipherObj = new nodeCrypto$1.createDecipheriv(nodeAlgos[algoName], key, iv); + return transform(ct, value => new Uint8Array(decipherObj.update(value))); +} + +var cfb = /*#__PURE__*/Object.freeze({ + __proto__: null, + encrypt: encrypt, + decrypt: decrypt +}); + +class AES_CTR { + static encrypt(data, key, nonce) { + return new AES_CTR(key, nonce).encrypt(data); } - } else { - outputStream.buffer = new Uint8Array(16384); - } - outputStream.pos = 0; - outputStream.writeByte = function (_byte) { - if (resizeOk && this.pos >= this.buffer.length) { - var newBuffer = new Uint8Array(this.buffer.length * 2); - newBuffer.set(this.buffer); - this.buffer = newBuffer; + static decrypt(data, key, nonce) { + return new AES_CTR(key, nonce).encrypt(data); } - this.buffer[this.pos++] = _byte; - }; - outputStream.getBuffer = function () { - // trim buffer - if (this.pos !== this.buffer.length) { - if (!resizeOk) throw new TypeError('outputsize does not match decoded input'); - var newBuffer = new Uint8Array(this.pos); - newBuffer.set(this.buffer.subarray(0, this.pos)); - this.buffer = newBuffer; + constructor(key, nonce, aes) { + this.aes = aes ? aes : new AES(key, undefined, false, 'CTR'); + delete this.aes.padding; + this.AES_CTR_set_options(nonce); } - return this.buffer; - }; - outputStream._coerced = true; - return outputStream; -}; - -/* Static helper functions */ -Bunzip.Err = Err; -// 'input' can be a stream or a buffer -// 'output' can be a stream or a buffer or a number (buffer size) -Bunzip.decode = function (input, output, multistream) { - // make a stream from a buffer, if necessary - var inputStream = coerceInputStream(input); - var outputStream = coerceOutputStream(output); + encrypt(data) { + const r1 = this.aes.AES_Encrypt_process(data); + const r2 = this.aes.AES_Encrypt_finish(); + return joinBytes(r1, r2); + } + decrypt(data) { + const r1 = this.aes.AES_Encrypt_process(data); + const r2 = this.aes.AES_Encrypt_finish(); + return joinBytes(r1, r2); + } + AES_CTR_set_options(nonce, counter, size) { + let { asm } = this.aes.acquire_asm(); + if (size !== undefined) { + if (size < 8 || size > 48) + throw new IllegalArgumentError('illegal counter size'); + let mask = Math.pow(2, size) - 1; + asm.set_mask(0, 0, (mask / 0x100000000) | 0, mask | 0); + } + else { + size = 48; + asm.set_mask(0, 0, 0xffff, 0xffffffff); + } + if (nonce !== undefined) { + let len = nonce.length; + if (!len || len > 16) + throw new IllegalArgumentError('illegal nonce size'); + let view = new DataView(new ArrayBuffer(16)); + new Uint8Array(view.buffer).set(nonce); + asm.set_nonce(view.getUint32(0), view.getUint32(4), view.getUint32(8), view.getUint32(12)); + } + else { + throw new Error('nonce is required'); + } + if (counter !== undefined) { + if (counter < 0 || counter >= Math.pow(2, size)) + throw new IllegalArgumentError('illegal counter value'); + asm.set_counter(0, 0, (counter / 0x100000000) | 0, counter | 0); + } + } +} - var bz = new Bunzip(inputStream, outputStream); - while (true) { - if ('eof' in inputStream && inputStream.eof()) break; - if (bz._init_block()) { - bz._read_bunzip(); - } else { - var targetStreamCRC = bz.reader.read(32) >>> 0; // (convert to unsigned) - if (targetStreamCRC !== bz.streamCRC) { - _throw(Err.DATA_ERROR, "Bad stream CRC " + "(got " + bz.streamCRC.toString(16) + " expected " + targetStreamCRC.toString(16) + ")"); - } - if (multistream && 'eof' in inputStream && !inputStream.eof()) { - // note that start_bunzip will also resync the bit reader to next byte - bz._start_bunzip(inputStream, outputStream); - } else break; +class AES_CBC { + static encrypt(data, key, padding = true, iv) { + return new AES_CBC(key, iv, padding).encrypt(data); + } + static decrypt(data, key, padding = true, iv) { + return new AES_CBC(key, iv, padding).decrypt(data); + } + constructor(key, iv, padding = true, aes) { + this.aes = aes ? aes : new AES(key, iv, padding, 'CBC'); } + encrypt(data) { + const r1 = this.aes.AES_Encrypt_process(data); + const r2 = this.aes.AES_Encrypt_finish(); + return joinBytes(r1, r2); + } + decrypt(data) { + const r1 = this.aes.AES_Decrypt_process(data); + const r2 = this.aes.AES_Decrypt_finish(); + return joinBytes(r1, r2); + } +} + +/** + * @fileoverview This module implements AES-CMAC on top of + * native AES-CBC using either the WebCrypto API or Node.js' crypto API. + * @module crypto/cmac + * @private + */ + +const webCrypto$2 = util.getWebCrypto(); +const nodeCrypto$2 = util.getNodeCrypto(); + + +/** + * This implementation of CMAC is based on the description of OMAC in + * http://web.cs.ucdavis.edu/~rogaway/papers/eax.pdf. As per that + * document: + * + * We have made a small modification to the OMAC algorithm as it was + * originally presented, changing one of its two constants. + * Specifically, the constant 4 at line 85 was the constant 1/2 (the + * multiplicative inverse of 2) in the original definition of OMAC [14]. + * The OMAC authors indicate that they will promulgate this modification + * [15], which slightly simplifies implementations. + */ + +const blockLength = 16; + + +/** + * xor `padding` into the end of `data`. This function implements "the + * operation xor→ [which] xors the shorter string into the end of longer + * one". Since data is always as least as long as padding, we can + * simplify the implementation. + * @param {Uint8Array} data + * @param {Uint8Array} padding + */ +function rightXORMut(data, padding) { + const offset = data.length - blockLength; + for (let i = 0; i < blockLength; i++) { + data[i + offset] ^= padding[i]; } - if ('getBuffer' in outputStream) return outputStream.getBuffer(); -}; -Bunzip.decodeBlock = function (input, pos, output) { - // make a stream from a buffer, if necessary - var inputStream = coerceInputStream(input); - var outputStream = coerceOutputStream(output); - var bz = new Bunzip(inputStream, outputStream); - bz.reader.seek(pos); - /* Fill the decode buffer for the block */ - var moreBlocks = bz._get_next_block(); - if (moreBlocks) { - /* Init the CRC for writing */ - bz.blockCRC = new CRC32(); + return data; +} + +function pad(data, padding, padding2) { + // if |M| in {n, 2n, 3n, ...} + if (data.length && data.length % blockLength === 0) { + // then return M xor→ B, + return rightXORMut(data, padding); + } + // else return (M || 10^(n−1−(|M| mod n))) xor→ P + const padded = new Uint8Array(data.length + (blockLength - data.length % blockLength)); + padded.set(data); + padded[data.length] = 0b10000000; + return rightXORMut(padded, padding2); +} + +const zeroBlock = new Uint8Array(blockLength); + +async function CMAC(key) { + const cbc = await CBC(key); + + // L ← E_K(0^n); B ← 2L; P ← 4L + const padding = util.double(await cbc(zeroBlock)); + const padding2 = util.double(padding); - /* Zero this so the current byte from before the seek is not written */ - bz.writeCopies = 0; + return async function(data) { + // return CBC_K(pad(M; B, P)) + return (await cbc(pad(data, padding, padding2))).subarray(-blockLength); + }; +} - /* Decompress the block and write to stdout */ - bz._read_bunzip(); - // XXX keep writing? +async function CBC(key) { + if (util.getWebCrypto() && key.length !== 24) { // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support + key = await webCrypto$2.importKey('raw', key, { name: 'AES-CBC', length: key.length * 8 }, false, ['encrypt']); + return async function(pt) { + const ct = await webCrypto$2.encrypt({ name: 'AES-CBC', iv: zeroBlock, length: blockLength * 8 }, key, pt); + return new Uint8Array(ct).subarray(0, ct.byteLength - blockLength); + }; } - if ('getBuffer' in outputStream) return outputStream.getBuffer(); -}; -/* Reads bzip2 file from stream or buffer `input`, and invoke - * `callback(position, size)` once for each bzip2 block, - * where position gives the starting position (in *bits*) - * and size gives uncompressed size of the block (in *bytes*). */ -Bunzip.table = function (input, callback, multistream) { - // make a stream from a buffer, if necessary - var inputStream = new Stream(); - inputStream.delegate = coerceInputStream(input); - inputStream.pos = 0; - inputStream.readByte = function () { - this.pos++; - return this.delegate.readByte(); - }; - if (inputStream.delegate.eof) { - inputStream.eof = inputStream.delegate.eof.bind(inputStream.delegate); + if (util.getNodeCrypto()) { // Node crypto library + return async function(pt) { + const en = new nodeCrypto$2.createCipheriv('aes-' + (key.length * 8) + '-cbc', key, zeroBlock); + const ct = en.update(pt); + return new Uint8Array(ct); + }; } - var outputStream = new Stream(); - outputStream.pos = 0; - outputStream.writeByte = function () { - this.pos++; + // asm.js fallback + return async function(pt) { + return AES_CBC.encrypt(pt, key, false, zeroBlock); }; +} - var bz = new Bunzip(inputStream, outputStream); - var blockSize = bz.dbufSize; - while (true) { - if ('eof' in inputStream && inputStream.eof()) break; - - var position = inputStream.pos * 8 + bz.reader.bitOffset; - if (bz.reader.hasByte) { - position -= 8; - } +// OpenPGP.js - An OpenPGP implementation in javascript - if (bz._init_block()) { - var start = outputStream.pos; - bz._read_bunzip(); - callback(position, outputStream.pos - start); - } else { - var crc = bz.reader.read(32); // (but we ignore the crc) - if (multistream && 'eof' in inputStream && !inputStream.eof()) { - // note that start_bunzip will also resync the bit reader to next byte - bz._start_bunzip(inputStream, outputStream); - console.assert(bz.dbufSize === blockSize, "shouldn't change block size within multistream file"); - } else break; - } - } -}; +const webCrypto$3 = util.getWebCrypto(); +const nodeCrypto$3 = util.getNodeCrypto(); +const Buffer$1 = util.getNodeBuffer(); -Bunzip.Stream = Stream; -module.exports = Bunzip; +const blockLength$1 = 16; +const ivLength = blockLength$1; +const tagLength = blockLength$1; -},{"./bitreader":67,"./crc32":68,"./stream":70}],70:[function(require,module,exports){ -"use strict"; +const zero = new Uint8Array(blockLength$1); +const one = new Uint8Array(blockLength$1); one[blockLength$1 - 1] = 1; +const two = new Uint8Array(blockLength$1); two[blockLength$1 - 1] = 2; -/* very simple input/output stream interface */ -var Stream = function Stream() {}; +async function OMAC(key) { + const cmac = await CMAC(key); + return function(t, message) { + return cmac(util.concatUint8Array([t, message])); + }; +} -// input streams ////////////// -/** Returns the next byte, or -1 for EOF. */ -Stream.prototype.readByte = function () { - throw new Error("abstract method readByte() not implemented"); -}; -/** Attempts to fill the buffer; returns number of bytes read, or - * -1 for EOF. */ -Stream.prototype.read = function (buffer, bufOffset, length) { - var bytesRead = 0; - while (bytesRead < length) { - var c = this.readByte(); - if (c < 0) { - // EOF - return bytesRead === 0 ? -1 : bytesRead; - } - buffer[bufOffset++] = c; - bytesRead++; +async function CTR(key) { + if ( + util.getWebCrypto() && + key.length !== 24 && // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support + (!navigator.userAgent || navigator.userAgent.indexOf('Edge') === -1) + ) { + key = await webCrypto$3.importKey('raw', key, { name: 'AES-CTR', length: key.length * 8 }, false, ['encrypt']); + return async function(pt, iv) { + const ct = await webCrypto$3.encrypt({ name: 'AES-CTR', counter: iv, length: blockLength$1 * 8 }, key, pt); + return new Uint8Array(ct); + }; } - return bytesRead; -}; -Stream.prototype.seek = function (new_pos) { - throw new Error("abstract method seek() not implemented"); -}; - -// output streams /////////// -Stream.prototype.writeByte = function (_byte) { - throw new Error("abstract method readByte() not implemented"); -}; -Stream.prototype.write = function (buffer, bufOffset, length) { - var i; - for (i = 0; i < length; i++) { - this.writeByte(buffer[bufOffset++]); + if (util.getNodeCrypto()) { // Node crypto library + return async function(pt, iv) { + const en = new nodeCrypto$3.createCipheriv('aes-' + (key.length * 8) + '-ctr', key, iv); + const ct = Buffer$1.concat([en.update(pt), en.final()]); + return new Uint8Array(ct); + }; } - return length; -}; -Stream.prototype.flush = function () {}; + // asm.js fallback + return async function(pt, iv) { + return AES_CTR.encrypt(pt, key, iv); + }; +} -module.exports = Stream; -},{}],71:[function(require,module,exports){ -'use strict'; +/** + * Class to en/decrypt using EAX mode. + * @param {enums.symmetric} cipher - The symmetric cipher algorithm to use + * @param {Uint8Array} key - The encryption key + */ +async function EAX(cipher, key) { + if (cipher !== enums.symmetric.aes128 && + cipher !== enums.symmetric.aes192 && + cipher !== enums.symmetric.aes256) { + throw new Error('EAX mode supports only AES cipher'); + } -// This is free and unencumbered software released into the public domain. -// See LICENSE.md for more information. + const [ + omac, + ctr + ] = await Promise.all([ + OMAC(key), + CTR(key) + ]); -// -// Utilities -// + return { + /** + * Encrypt plaintext input. + * @param {Uint8Array} plaintext - The cleartext input to be encrypted + * @param {Uint8Array} nonce - The nonce (16 bytes) + * @param {Uint8Array} adata - Associated data to sign + * @returns {Promise} The ciphertext output. + */ + encrypt: async function(plaintext, nonce, adata) { + const [ + omacNonce, + omacAdata + ] = await Promise.all([ + omac(zero, nonce), + omac(one, adata) + ]); + const ciphered = await ctr(plaintext, omacNonce); + const omacCiphered = await omac(two, ciphered); + const tag = omacCiphered; // Assumes that omac(*).length === tagLength. + for (let i = 0; i < tagLength; i++) { + tag[i] ^= omacAdata[i] ^ omacNonce[i]; + } + return util.concatUint8Array([ciphered, tag]); + }, -/** - * @param {number} a The number to test. - * @param {number} min The minimum value in the range, inclusive. - * @param {number} max The maximum value in the range, inclusive. - * @return {boolean} True if a >= min and a <= max. - */ -function inRange(a, min, max) { - return min <= a && a <= max; + /** + * Decrypt ciphertext input. + * @param {Uint8Array} ciphertext - The ciphertext input to be decrypted + * @param {Uint8Array} nonce - The nonce (16 bytes) + * @param {Uint8Array} adata - Associated data to verify + * @returns {Promise} The plaintext output. + */ + decrypt: async function(ciphertext, nonce, adata) { + if (ciphertext.length < tagLength) throw new Error('Invalid EAX ciphertext'); + const ciphered = ciphertext.subarray(0, -tagLength); + const ctTag = ciphertext.subarray(-tagLength); + const [ + omacNonce, + omacAdata, + omacCiphered + ] = await Promise.all([ + omac(zero, nonce), + omac(one, adata), + omac(two, ciphered) + ]); + const tag = omacCiphered; // Assumes that omac(*).length === tagLength. + for (let i = 0; i < tagLength; i++) { + tag[i] ^= omacAdata[i] ^ omacNonce[i]; + } + if (!util.equalsUint8Array(ctTag, tag)) throw new Error('Authentication tag mismatch'); + const plaintext = await ctr(ciphered, omacNonce); + return plaintext; + } + }; } -/** - * @param {*} o - * @return {Object} - */ -function ToDictionary(o) { - if (o === undefined) return {}; - if (o === Object(o)) return o; - throw TypeError('Could not convert argument to dictionary'); -} /** - * @param {string} string Input string of UTF-16 code units. - * @return {!Array.} Code points. + * Get EAX nonce as defined by {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.1|RFC4880bis-04, section 5.16.1}. + * @param {Uint8Array} iv - The initialization vector (16 bytes) + * @param {Uint8Array} chunkIndex - The chunk index (8 bytes) */ -function stringToCodePoints(string) { - // https://heycam.github.io/webidl/#dfn-obtain-unicode +EAX.getNonce = function(iv, chunkIndex) { + const nonce = iv.slice(); + for (let i = 0; i < chunkIndex.length; i++) { + nonce[8 + i] ^= chunkIndex[i]; + } + return nonce; +}; - // 1. Let S be the DOMString value. - var s = String(string); +EAX.blockLength = blockLength$1; +EAX.ivLength = ivLength; +EAX.tagLength = tagLength; - // 2. Let n be the length of S. - var n = s.length; +// OpenPGP.js - An OpenPGP implementation in javascript - // 3. Initialize i to 0. - var i = 0; +const blockLength$2 = 16; +const ivLength$1 = 15; - // 4. Initialize U to be an empty sequence of Unicode characters. - var u = []; +// https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.2: +// While OCB [RFC7253] allows the authentication tag length to be of any +// number up to 128 bits long, this document requires a fixed +// authentication tag length of 128 bits (16 octets) for simplicity. +const tagLength$1 = 16; - // 5. While i < n: - while (i < n) { - // 1. Let c be the code unit in S at index i. - var c = s.charCodeAt(i); +function ntz(n) { + let ntz = 0; + for (let i = 1; (n & i) === 0; i <<= 1) { + ntz++; + } + return ntz; +} - // 2. Depending on the value of c: +function xorMut$1(S, T) { + for (let i = 0; i < S.length; i++) { + S[i] ^= T[i]; + } + return S; +} - // c < 0xD800 or c > 0xDFFF - if (c < 0xD800 || c > 0xDFFF) { - // Append to U the Unicode character with code point c. - u.push(c); - } +function xor(S, T) { + return xorMut$1(S.slice(), T); +} - // 0xDC00 ≤ c ≤ 0xDFFF - else if (0xDC00 <= c && c <= 0xDFFF) { - // Append to U a U+FFFD REPLACEMENT CHARACTER. - u.push(0xFFFD); - } +const zeroBlock$1 = new Uint8Array(blockLength$2); +const one$1 = new Uint8Array([1]); - // 0xD800 ≤ c ≤ 0xDBFF - else if (0xD800 <= c && c <= 0xDBFF) { - // 1. If i = n−1, then append to U a U+FFFD REPLACEMENT - // CHARACTER. - if (i === n - 1) { - u.push(0xFFFD); - } - // 2. Otherwise, i < n−1: - else { - // 1. Let d be the code unit in S at index i+1. - var d = string.charCodeAt(i + 1); +/** + * Class to en/decrypt using OCB mode. + * @param {enums.symmetric} cipher - The symmetric cipher algorithm to use + * @param {Uint8Array} key - The encryption key + */ +async function OCB(cipher$1, key) { - // 2. If 0xDC00 ≤ d ≤ 0xDFFF, then: - if (0xDC00 <= d && d <= 0xDFFF) { - // 1. Let a be c & 0x3FF. - var a = c & 0x3FF; + let maxNtz = 0; + let encipher; + let decipher; + let mask; - // 2. Let b be d & 0x3FF. - var b = d & 0x3FF; + constructKeyVariables(cipher$1, key); - // 3. Append to U the Unicode character with code point - // 2^16+2^10*a+b. - u.push(0x10000 + (a << 10) + b); + function constructKeyVariables(cipher$1, key) { + const cipherName = enums.read(enums.symmetric, cipher$1); + const aes = new cipher[cipherName](key); + encipher = aes.encrypt.bind(aes); + decipher = aes.decrypt.bind(aes); - // 4. Set i to i+1. - i += 1; - } + const mask_x = encipher(zeroBlock$1); + const mask_$ = util.double(mask_x); + mask = []; + mask[0] = util.double(mask_$); - // 3. Otherwise, d < 0xDC00 or d > 0xDFFF. Append to U a - // U+FFFD REPLACEMENT CHARACTER. - else { - u.push(0xFFFD); - } - } - } - // 3. Set i to i+1. - i += 1; + mask.x = mask_x; + mask.$ = mask_$; } - // 6. Return U. - return u; -} - -/** - * @param {!Array.} code_points Array of code points. - * @return {string} string String of UTF-16 code units. - */ -function codePointsToString(code_points) { - var s = ''; - for (var i = 0; i < code_points.length; ++i) { - var cp = code_points[i]; - if (cp <= 0xFFFF) { - s += String.fromCharCode(cp); - } else { - cp -= 0x10000; - s += String.fromCharCode((cp >> 10) + 0xD800, - (cp & 0x3FF) + 0xDC00); + function extendKeyVariables(text, adata) { + const newMaxNtz = util.nbits(Math.max(text.length, adata.length) / blockLength$2 | 0) - 1; + for (let i = maxNtz + 1; i <= newMaxNtz; i++) { + mask[i] = util.double(mask[i - 1]); } + maxNtz = newMaxNtz; } - return s; -} + function hash(adata) { + if (!adata.length) { + // Fast path + return zeroBlock$1; + } -// -// Implementation of Encoding specification -// https://encoding.spec.whatwg.org/ -// + // + // Consider A as a sequence of 128-bit blocks + // + const m = adata.length / blockLength$2 | 0; -// -// 3. Terminology -// + const offset = new Uint8Array(blockLength$2); + const sum = new Uint8Array(blockLength$2); + for (let i = 0; i < m; i++) { + xorMut$1(offset, mask[ntz(i + 1)]); + xorMut$1(sum, encipher(xor(offset, adata))); + adata = adata.subarray(blockLength$2); + } -/** - * End-of-stream is a special token that signifies no more tokens - * are in the stream. - * @const - */ var end_of_stream = -1; + // + // Process any final partial block; compute final hash value + // + if (adata.length) { + xorMut$1(offset, mask.x); -/** - * A stream represents an ordered sequence of tokens. - * - * @constructor - * @param {!(Array.|Uint8Array)} tokens Array of tokens that provide the - * stream. - */ -function Stream(tokens) { - /** @type {!Array.} */ - this.tokens = [].slice.call(tokens); -} + const cipherInput = new Uint8Array(blockLength$2); + cipherInput.set(adata, 0); + cipherInput[adata.length] = 0b10000000; + xorMut$1(cipherInput, offset); -Stream.prototype = { - /** - * @return {boolean} True if end-of-stream has been hit. - */ - endOfStream: function() { - return !this.tokens.length; - }, + xorMut$1(sum, encipher(cipherInput)); + } - /** - * When a token is read from a stream, the first token in the - * stream must be returned and subsequently removed, and - * end-of-stream must be returned otherwise. - * - * @return {number} Get the next token from the stream, or - * end_of_stream. - */ - read: function() { - if (!this.tokens.length) - return end_of_stream; - return this.tokens.shift(); - }, + return sum; + } /** - * When one or more tokens are prepended to a stream, those tokens - * must be inserted, in given order, before the first token in the - * stream. - * - * @param {(number|!Array.)} token The token(s) to prepend to the stream. + * Encrypt/decrypt data. + * @param {encipher|decipher} fn - Encryption/decryption block cipher function + * @param {Uint8Array} text - The cleartext or ciphertext (without tag) input + * @param {Uint8Array} nonce - The nonce (15 bytes) + * @param {Uint8Array} adata - Associated data to sign + * @returns {Promise} The ciphertext or plaintext output, with tag appended in both cases. */ - prepend: function(token) { - if (Array.isArray(token)) { - var tokens = /**@type {!Array.}*/(token); - while (tokens.length) - this.tokens.unshift(tokens.pop()); - } else { - this.tokens.unshift(token); + function crypt(fn, text, nonce, adata) { + // + // Consider P as a sequence of 128-bit blocks + // + const m = text.length / blockLength$2 | 0; + + // + // Key-dependent variables + // + extendKeyVariables(text, adata); + + // + // Nonce-dependent and per-encryption variables + // + // Nonce = num2str(TAGLEN mod 128,7) || zeros(120-bitlen(N)) || 1 || N + // Note: We assume here that tagLength mod 16 == 0. + const paddedNonce = util.concatUint8Array([zeroBlock$1.subarray(0, ivLength$1 - nonce.length), one$1, nonce]); + // bottom = str2num(Nonce[123..128]) + const bottom = paddedNonce[blockLength$2 - 1] & 0b111111; + // Ktop = ENCIPHER(K, Nonce[1..122] || zeros(6)) + paddedNonce[blockLength$2 - 1] &= 0b11000000; + const kTop = encipher(paddedNonce); + // Stretch = Ktop || (Ktop[1..64] xor Ktop[9..72]) + const stretched = util.concatUint8Array([kTop, xor(kTop.subarray(0, 8), kTop.subarray(1, 9))]); + // Offset_0 = Stretch[1+bottom..128+bottom] + const offset = util.shiftRight(stretched.subarray(0 + (bottom >> 3), 17 + (bottom >> 3)), 8 - (bottom & 7)).subarray(1); + // Checksum_0 = zeros(128) + const checksum = new Uint8Array(blockLength$2); + + const ct = new Uint8Array(text.length + tagLength$1); + + // + // Process any whole blocks + // + let i; + let pos = 0; + for (i = 0; i < m; i++) { + // Offset_i = Offset_{i-1} xor L_{ntz(i)} + xorMut$1(offset, mask[ntz(i + 1)]); + // C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) + // P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i) + ct.set(xorMut$1(fn(xor(offset, text)), offset), pos); + // Checksum_i = Checksum_{i-1} xor P_i + xorMut$1(checksum, fn === encipher ? text : ct.subarray(pos)); + + text = text.subarray(blockLength$2); + pos += blockLength$2; } - }, - /** - * When one or more tokens are pushed to a stream, those tokens - * must be inserted, in given order, after the last token in the - * stream. - * - * @param {(number|!Array.)} token The tokens(s) to prepend to the stream. - */ - push: function(token) { - if (Array.isArray(token)) { - var tokens = /**@type {!Array.}*/(token); - while (tokens.length) - this.tokens.push(tokens.shift()); - } else { - this.tokens.push(token); + // + // Process any final partial block and compute raw tag + // + if (text.length) { + // Offset_* = Offset_m xor L_* + xorMut$1(offset, mask.x); + // Pad = ENCIPHER(K, Offset_*) + const padding = encipher(offset); + // C_* = P_* xor Pad[1..bitlen(P_*)] + ct.set(xor(text, padding), pos); + + // Checksum_* = Checksum_m xor (P_* || 1 || new Uint8Array(127-bitlen(P_*))) + const xorInput = new Uint8Array(blockLength$2); + xorInput.set(fn === encipher ? text : ct.subarray(pos, -tagLength$1), 0); + xorInput[text.length] = 0b10000000; + xorMut$1(checksum, xorInput); + pos += text.length; } - } -}; + // Tag = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) xor HASH(K,A) + const tag = xorMut$1(encipher(xorMut$1(xorMut$1(checksum, offset), mask.$)), hash(adata)); -// -// 4. Encodings -// + // + // Assemble ciphertext + // + // C = C_1 || C_2 || ... || C_m || C_* || Tag[1..TAGLEN] + ct.set(tag, pos); + return ct; + } -// 4.1 Encoders and decoders -/** @const */ -var finished = -1; + return { + /** + * Encrypt plaintext input. + * @param {Uint8Array} plaintext - The cleartext input to be encrypted + * @param {Uint8Array} nonce - The nonce (15 bytes) + * @param {Uint8Array} adata - Associated data to sign + * @returns {Promise} The ciphertext output. + */ + encrypt: async function(plaintext, nonce, adata) { + return crypt(encipher, plaintext, nonce, adata); + }, -/** - * @param {boolean} fatal If true, decoding errors raise an exception. - * @param {number=} opt_code_point Override the standard fallback code point. - * @return {number} The code point to insert on a decoding error. - */ -function decoderError(fatal, opt_code_point) { - if (fatal) - throw TypeError('Decoder error'); - return opt_code_point || 0xFFFD; -} + /** + * Decrypt ciphertext input. + * @param {Uint8Array} ciphertext - The ciphertext input to be decrypted + * @param {Uint8Array} nonce - The nonce (15 bytes) + * @param {Uint8Array} adata - Associated data to sign + * @returns {Promise} The ciphertext output. + */ + decrypt: async function(ciphertext, nonce, adata) { + if (ciphertext.length < tagLength$1) throw new Error('Invalid OCB ciphertext'); -// -// 7. API -// + const tag = ciphertext.subarray(-tagLength$1); + ciphertext = ciphertext.subarray(0, -tagLength$1); -/** @const */ var DEFAULT_ENCODING = 'utf-8'; + const crypted = crypt(decipher, ciphertext, nonce, adata); + // if (Tag[1..TAGLEN] == T) + if (util.equalsUint8Array(tag, crypted.subarray(-tagLength$1))) { + return crypted.subarray(0, -tagLength$1); + } + throw new Error('Authentication tag mismatch'); + } + }; +} -// 7.1 Interface TextDecoder /** - * @constructor - * @param {string=} encoding The label of the encoding; - * defaults to 'utf-8'. - * @param {Object=} options + * Get OCB nonce as defined by {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.2|RFC4880bis-04, section 5.16.2}. + * @param {Uint8Array} iv - The initialization vector (15 bytes) + * @param {Uint8Array} chunkIndex - The chunk index (8 bytes) */ -function TextDecoder(encoding, options) { - if (!(this instanceof TextDecoder)) { - return new TextDecoder(encoding, options); - } - encoding = encoding !== undefined ? String(encoding).toLowerCase() : DEFAULT_ENCODING; - if (encoding !== DEFAULT_ENCODING) { - throw new Error('Encoding not supported. Only utf-8 is supported'); +OCB.getNonce = function(iv, chunkIndex) { + const nonce = iv.slice(); + for (let i = 0; i < chunkIndex.length; i++) { + nonce[7 + i] ^= chunkIndex[i]; } - options = ToDictionary(options); - - /** @private @type {boolean} */ - this._streaming = false; - /** @private @type {boolean} */ - this._BOMseen = false; - /** @private @type {?Decoder} */ - this._decoder = null; - /** @private @type {boolean} */ - this._fatal = Boolean(options['fatal']); - /** @private @type {boolean} */ - this._ignoreBOM = Boolean(options['ignoreBOM']); + return nonce; +}; - Object.defineProperty(this, 'encoding', {value: 'utf-8'}); - Object.defineProperty(this, 'fatal', {value: this._fatal}); - Object.defineProperty(this, 'ignoreBOM', {value: this._ignoreBOM}); -} +OCB.blockLength = blockLength$2; +OCB.ivLength = ivLength$1; +OCB.tagLength = tagLength$1; -TextDecoder.prototype = { - /** - * @param {ArrayBufferView=} input The buffer of bytes to decode. - * @param {Object=} options - * @return {string} The decoded string. - */ - decode: function decode(input, options) { - var bytes; - if (typeof input === 'object' && input instanceof ArrayBuffer) { - bytes = new Uint8Array(input); - } else if (typeof input === 'object' && 'buffer' in input && - input.buffer instanceof ArrayBuffer) { - bytes = new Uint8Array(input.buffer, - input.byteOffset, - input.byteLength); - } else { - bytes = new Uint8Array(0); +const _AES_GCM_data_maxLength = 68719476704; // 2^36 - 2^5 +class AES_GCM { + constructor(key, nonce, adata, tagSize = 16, aes) { + this.tagSize = tagSize; + this.gamma0 = 0; + this.counter = 1; + this.aes = aes ? aes : new AES(key, undefined, false, 'CTR'); + let { asm, heap } = this.aes.acquire_asm(); + // Init GCM + asm.gcm_init(); + // Tag size + if (this.tagSize < 4 || this.tagSize > 16) + throw new IllegalArgumentError('illegal tagSize value'); + // Nonce + const noncelen = nonce.length || 0; + const noncebuf = new Uint8Array(16); + if (noncelen !== 12) { + this._gcm_mac_process(nonce); + heap[0] = 0; + heap[1] = 0; + heap[2] = 0; + heap[3] = 0; + heap[4] = 0; + heap[5] = 0; + heap[6] = 0; + heap[7] = 0; + heap[8] = 0; + heap[9] = 0; + heap[10] = 0; + heap[11] = noncelen >>> 29; + heap[12] = (noncelen >>> 21) & 255; + heap[13] = (noncelen >>> 13) & 255; + heap[14] = (noncelen >>> 5) & 255; + heap[15] = (noncelen << 3) & 255; + asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16); + asm.get_iv(AES_asm.HEAP_DATA); + asm.set_iv(0, 0, 0, 0); + noncebuf.set(heap.subarray(0, 16)); + } + else { + noncebuf.set(nonce); + noncebuf[15] = 1; + } + const nonceview = new DataView(noncebuf.buffer); + this.gamma0 = nonceview.getUint32(12); + asm.set_nonce(nonceview.getUint32(0), nonceview.getUint32(4), nonceview.getUint32(8), 0); + asm.set_mask(0, 0, 0, 0xffffffff); + // Associated data + if (adata !== undefined) { + if (adata.length > _AES_GCM_data_maxLength) + throw new IllegalArgumentError('illegal adata length'); + if (adata.length) { + this.adata = adata; + this._gcm_mac_process(adata); + } + else { + this.adata = undefined; + } + } + else { + this.adata = undefined; + } + // Counter + if (this.counter < 1 || this.counter > 0xffffffff) + throw new RangeError('counter must be a positive 32-bit integer'); + asm.set_counter(0, 0, 0, (this.gamma0 + this.counter) | 0); } - - options = ToDictionary(options); - - if (!this._streaming) { - this._decoder = new UTF8Decoder({fatal: this._fatal}); - this._BOMseen = false; + static encrypt(cleartext, key, nonce, adata, tagsize) { + return new AES_GCM(key, nonce, adata, tagsize).encrypt(cleartext); } - this._streaming = Boolean(options['stream']); - - var input_stream = new Stream(bytes); - - var code_points = []; - - /** @type {?(number|!Array.)} */ - var result; - - while (!input_stream.endOfStream()) { - result = this._decoder.handler(input_stream, input_stream.read()); - if (result === finished) - break; - if (result === null) - continue; - if (Array.isArray(result)) - code_points.push.apply(code_points, /**@type {!Array.}*/(result)); - else - code_points.push(result); + static decrypt(ciphertext, key, nonce, adata, tagsize) { + return new AES_GCM(key, nonce, adata, tagsize).decrypt(ciphertext); } - if (!this._streaming) { - do { - result = this._decoder.handler(input_stream, input_stream.read()); - if (result === finished) - break; - if (result === null) - continue; - if (Array.isArray(result)) - code_points.push.apply(code_points, /**@type {!Array.}*/(result)); - else - code_points.push(result); - } while (!input_stream.endOfStream()); - this._decoder = null; - } - - if (code_points.length) { - // If encoding is one of utf-8, utf-16be, and utf-16le, and - // ignore BOM flag and BOM seen flag are unset, run these - // subsubsteps: - if (['utf-8'].indexOf(this.encoding) !== -1 && - !this._ignoreBOM && !this._BOMseen) { - // If token is U+FEFF, set BOM seen flag. - if (code_points[0] === 0xFEFF) { - this._BOMseen = true; - code_points.shift(); - } else { - // Otherwise, if token is not end-of-stream, set BOM seen - // flag and append token to output. - this._BOMseen = true; + encrypt(data) { + return this.AES_GCM_encrypt(data); + } + decrypt(data) { + return this.AES_GCM_decrypt(data); + } + AES_GCM_Encrypt_process(data) { + let dpos = 0; + let dlen = data.length || 0; + let { asm, heap } = this.aes.acquire_asm(); + let counter = this.counter; + let pos = this.aes.pos; + let len = this.aes.len; + let rpos = 0; + let rlen = (len + dlen) & -16; + let wlen = 0; + if (((counter - 1) << 4) + len + dlen > _AES_GCM_data_maxLength) + throw new RangeError('counter overflow'); + const result = new Uint8Array(rlen); + while (dlen > 0) { + wlen = _heap_write(heap, pos + len, data, dpos, dlen); + len += wlen; + dpos += wlen; + dlen -= wlen; + wlen = asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, len); + wlen = asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, wlen); + if (wlen) + result.set(heap.subarray(pos, pos + wlen), rpos); + counter += wlen >>> 4; + rpos += wlen; + if (wlen < len) { + pos += wlen; + len -= wlen; + } + else { + pos = 0; + len = 0; + } } - } + this.counter = counter; + this.aes.pos = pos; + this.aes.len = len; + return result; + } + AES_GCM_Encrypt_finish() { + let { asm, heap } = this.aes.acquire_asm(); + let counter = this.counter; + let tagSize = this.tagSize; + let adata = this.adata; + let pos = this.aes.pos; + let len = this.aes.len; + const result = new Uint8Array(len + tagSize); + asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, (len + 15) & -16); + if (len) + result.set(heap.subarray(pos, pos + len)); + let i = len; + for (; i & 15; i++) + heap[pos + i] = 0; + asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, i); + const alen = adata !== undefined ? adata.length : 0; + const clen = ((counter - 1) << 4) + len; + heap[0] = 0; + heap[1] = 0; + heap[2] = 0; + heap[3] = alen >>> 29; + heap[4] = alen >>> 21; + heap[5] = (alen >>> 13) & 255; + heap[6] = (alen >>> 5) & 255; + heap[7] = (alen << 3) & 255; + heap[8] = heap[9] = heap[10] = 0; + heap[11] = clen >>> 29; + heap[12] = (clen >>> 21) & 255; + heap[13] = (clen >>> 13) & 255; + heap[14] = (clen >>> 5) & 255; + heap[15] = (clen << 3) & 255; + asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16); + asm.get_iv(AES_asm.HEAP_DATA); + asm.set_counter(0, 0, 0, this.gamma0); + asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16); + result.set(heap.subarray(0, tagSize), len); + this.counter = 1; + this.aes.pos = 0; + this.aes.len = 0; + return result; + } + AES_GCM_Decrypt_process(data) { + let dpos = 0; + let dlen = data.length || 0; + let { asm, heap } = this.aes.acquire_asm(); + let counter = this.counter; + let tagSize = this.tagSize; + let pos = this.aes.pos; + let len = this.aes.len; + let rpos = 0; + let rlen = len + dlen > tagSize ? (len + dlen - tagSize) & -16 : 0; + let tlen = len + dlen - rlen; + let wlen = 0; + if (((counter - 1) << 4) + len + dlen > _AES_GCM_data_maxLength) + throw new RangeError('counter overflow'); + const result = new Uint8Array(rlen); + while (dlen > tlen) { + wlen = _heap_write(heap, pos + len, data, dpos, dlen - tlen); + len += wlen; + dpos += wlen; + dlen -= wlen; + wlen = asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, wlen); + wlen = asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, wlen); + if (wlen) + result.set(heap.subarray(pos, pos + wlen), rpos); + counter += wlen >>> 4; + rpos += wlen; + pos = 0; + len = 0; + } + if (dlen > 0) { + len += _heap_write(heap, 0, data, dpos, dlen); + } + this.counter = counter; + this.aes.pos = pos; + this.aes.len = len; + return result; + } + AES_GCM_Decrypt_finish() { + let { asm, heap } = this.aes.acquire_asm(); + let tagSize = this.tagSize; + let adata = this.adata; + let counter = this.counter; + let pos = this.aes.pos; + let len = this.aes.len; + let rlen = len - tagSize; + if (len < tagSize) + throw new IllegalStateError('authentication tag not found'); + const result = new Uint8Array(rlen); + const atag = new Uint8Array(heap.subarray(pos + rlen, pos + len)); + let i = rlen; + for (; i & 15; i++) + heap[pos + i] = 0; + asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, i); + asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, i); + if (rlen) + result.set(heap.subarray(pos, pos + rlen)); + const alen = adata !== undefined ? adata.length : 0; + const clen = ((counter - 1) << 4) + len - tagSize; + heap[0] = 0; + heap[1] = 0; + heap[2] = 0; + heap[3] = alen >>> 29; + heap[4] = alen >>> 21; + heap[5] = (alen >>> 13) & 255; + heap[6] = (alen >>> 5) & 255; + heap[7] = (alen << 3) & 255; + heap[8] = heap[9] = heap[10] = 0; + heap[11] = clen >>> 29; + heap[12] = (clen >>> 21) & 255; + heap[13] = (clen >>> 13) & 255; + heap[14] = (clen >>> 5) & 255; + heap[15] = (clen << 3) & 255; + asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16); + asm.get_iv(AES_asm.HEAP_DATA); + asm.set_counter(0, 0, 0, this.gamma0); + asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16); + let acheck = 0; + for (let i = 0; i < tagSize; ++i) + acheck |= atag[i] ^ heap[i]; + if (acheck) + throw new SecurityError('data integrity check failed'); + this.counter = 1; + this.aes.pos = 0; + this.aes.len = 0; + return result; + } + AES_GCM_decrypt(data) { + const result1 = this.AES_GCM_Decrypt_process(data); + const result2 = this.AES_GCM_Decrypt_finish(); + const result = new Uint8Array(result1.length + result2.length); + if (result1.length) + result.set(result1); + if (result2.length) + result.set(result2, result1.length); + return result; + } + AES_GCM_encrypt(data) { + const result1 = this.AES_GCM_Encrypt_process(data); + const result2 = this.AES_GCM_Encrypt_finish(); + const result = new Uint8Array(result1.length + result2.length); + if (result1.length) + result.set(result1); + if (result2.length) + result.set(result2, result1.length); + return result; } + _gcm_mac_process(data) { + let { asm, heap } = this.aes.acquire_asm(); + let dpos = 0; + let dlen = data.length || 0; + let wlen = 0; + while (dlen > 0) { + wlen = _heap_write(heap, 0, data, dpos, dlen); + dpos += wlen; + dlen -= wlen; + while (wlen & 15) + heap[wlen++] = 0; + asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, wlen); + } + } +} - return codePointsToString(code_points); - } -}; +// OpenPGP.js - An OpenPGP implementation in javascript + +const webCrypto$4 = util.getWebCrypto(); +const nodeCrypto$4 = util.getNodeCrypto(); +const Buffer$2 = util.getNodeBuffer(); -// 7.2 Interface TextEncoder +const blockLength$3 = 16; +const ivLength$2 = 12; // size of the IV in bytes +const tagLength$2 = 16; // size of the tag in bytes +const ALGO = 'AES-GCM'; /** - * @constructor - * @param {string=} encoding The label of the encoding; - * defaults to 'utf-8'. - * @param {Object=} options + * Class to en/decrypt using GCM mode. + * @param {enums.symmetric} cipher - The symmetric cipher algorithm to use + * @param {Uint8Array} key - The encryption key */ -function TextEncoder(encoding, options) { - if (!(this instanceof TextEncoder)) - return new TextEncoder(encoding, options); - encoding = encoding !== undefined ? String(encoding).toLowerCase() : DEFAULT_ENCODING; - if (encoding !== DEFAULT_ENCODING) { - throw new Error('Encoding not supported. Only utf-8 is supported'); +async function GCM(cipher, key) { + if (cipher !== enums.symmetric.aes128 && + cipher !== enums.symmetric.aes192 && + cipher !== enums.symmetric.aes256) { + throw new Error('GCM mode supports only AES cipher'); } - options = ToDictionary(options); - - /** @private @type {boolean} */ - this._streaming = false; - /** @private @type {?Encoder} */ - this._encoder = null; - /** @private @type {{fatal: boolean}} */ - this._options = {fatal: Boolean(options['fatal'])}; - - Object.defineProperty(this, 'encoding', {value: 'utf-8'}); -} -TextEncoder.prototype = { - /** - * @param {string=} opt_string The string to encode. - * @param {Object=} options - * @return {Uint8Array} Encoded bytes, as a Uint8Array. - */ - encode: function encode(opt_string, options) { - opt_string = opt_string ? String(opt_string) : ''; - options = ToDictionary(options); + if (util.getWebCrypto() && key.length !== 24) { // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support + const _key = await webCrypto$4.importKey('raw', key, { name: ALGO }, false, ['encrypt', 'decrypt']); - // NOTE: This option is nonstandard. None of the encodings - // permitted for encoding (i.e. UTF-8, UTF-16) are stateful, - // so streaming is not necessary. - if (!this._streaming) - this._encoder = new UTF8Encoder(this._options); - this._streaming = Boolean(options['stream']); + return { + encrypt: async function(pt, iv, adata = new Uint8Array()) { + if ( + !pt.length || + // iOS does not support GCM-en/decrypting empty messages + // Also, synchronous en/decryption might be faster in this case. + (!adata.length && navigator.userAgent && navigator.userAgent.indexOf('Edge') !== -1) + // Edge does not support GCM-en/decrypting without ADATA + ) { + return AES_GCM.encrypt(pt, key, iv, adata); + } + const ct = await webCrypto$4.encrypt({ name: ALGO, iv, additionalData: adata, tagLength: tagLength$2 * 8 }, _key, pt); + return new Uint8Array(ct); + }, - var bytes = []; - var input_stream = new Stream(stringToCodePoints(opt_string)); - /** @type {?(number|!Array.)} */ - var result; - while (!input_stream.endOfStream()) { - result = this._encoder.handler(input_stream, input_stream.read()); - if (result === finished) - break; - if (Array.isArray(result)) - bytes.push.apply(bytes, /**@type {!Array.}*/(result)); - else - bytes.push(result); - } - if (!this._streaming) { - while (true) { - result = this._encoder.handler(input_stream, input_stream.read()); - if (result === finished) - break; - if (Array.isArray(result)) - bytes.push.apply(bytes, /**@type {!Array.}*/(result)); - else - bytes.push(result); + decrypt: async function(ct, iv, adata = new Uint8Array()) { + if ( + ct.length === tagLength$2 || + // iOS does not support GCM-en/decrypting empty messages + // Also, synchronous en/decryption might be faster in this case. + (!adata.length && navigator.userAgent && navigator.userAgent.indexOf('Edge') !== -1) + // Edge does not support GCM-en/decrypting without ADATA + ) { + return AES_GCM.decrypt(ct, key, iv, adata); + } + const pt = await webCrypto$4.decrypt({ name: ALGO, iv, additionalData: adata, tagLength: tagLength$2 * 8 }, _key, ct); + return new Uint8Array(pt); } - this._encoder = null; - } - return new Uint8Array(bytes); + }; } -}; -// -// 8. The encoding -// + if (util.getNodeCrypto()) { // Node crypto library + return { + encrypt: async function(pt, iv, adata = new Uint8Array()) { + const en = new nodeCrypto$4.createCipheriv('aes-' + (key.length * 8) + '-gcm', key, iv); + en.setAAD(adata); + const ct = Buffer$2.concat([en.update(pt), en.final(), en.getAuthTag()]); // append auth tag to ciphertext + return new Uint8Array(ct); + }, -// 8.1 utf-8 - -/** - * @constructor - * @implements {Decoder} - * @param {{fatal: boolean}} options - */ -function UTF8Decoder(options) { - var fatal = options.fatal; - - // utf-8's decoder's has an associated utf-8 code point, utf-8 - // bytes seen, and utf-8 bytes needed (all initially 0), a utf-8 - // lower boundary (initially 0x80), and a utf-8 upper boundary - // (initially 0xBF). - var /** @type {number} */ utf8_code_point = 0, - /** @type {number} */ utf8_bytes_seen = 0, - /** @type {number} */ utf8_bytes_needed = 0, - /** @type {number} */ utf8_lower_boundary = 0x80, - /** @type {number} */ utf8_upper_boundary = 0xBF; - - /** - * @param {Stream} stream The stream of bytes being decoded. - * @param {number} bite The next byte read from the stream. - * @return {?(number|!Array.)} The next code point(s) - * decoded, or null if not enough data exists in the input - * stream to decode a complete code point. - */ - this.handler = function(stream, bite) { - // 1. If byte is end-of-stream and utf-8 bytes needed is not 0, - // set utf-8 bytes needed to 0 and return error. - if (bite === end_of_stream && utf8_bytes_needed !== 0) { - utf8_bytes_needed = 0; - return decoderError(fatal); - } - - // 2. If byte is end-of-stream, return finished. - if (bite === end_of_stream) - return finished; - - // 3. If utf-8 bytes needed is 0, based on byte: - if (utf8_bytes_needed === 0) { - - // 0x00 to 0x7F - if (inRange(bite, 0x00, 0x7F)) { - // Return a code point whose value is byte. - return bite; - } - - // 0xC2 to 0xDF - if (inRange(bite, 0xC2, 0xDF)) { - // Set utf-8 bytes needed to 1 and utf-8 code point to byte - // − 0xC0. - utf8_bytes_needed = 1; - utf8_code_point = bite - 0xC0; - } - - // 0xE0 to 0xEF - else if (inRange(bite, 0xE0, 0xEF)) { - // 1. If byte is 0xE0, set utf-8 lower boundary to 0xA0. - if (bite === 0xE0) - utf8_lower_boundary = 0xA0; - // 2. If byte is 0xED, set utf-8 upper boundary to 0x9F. - if (bite === 0xED) - utf8_upper_boundary = 0x9F; - // 3. Set utf-8 bytes needed to 2 and utf-8 code point to - // byte − 0xE0. - utf8_bytes_needed = 2; - utf8_code_point = bite - 0xE0; - } - - // 0xF0 to 0xF4 - else if (inRange(bite, 0xF0, 0xF4)) { - // 1. If byte is 0xF0, set utf-8 lower boundary to 0x90. - if (bite === 0xF0) - utf8_lower_boundary = 0x90; - // 2. If byte is 0xF4, set utf-8 upper boundary to 0x8F. - if (bite === 0xF4) - utf8_upper_boundary = 0x8F; - // 3. Set utf-8 bytes needed to 3 and utf-8 code point to - // byte − 0xF0. - utf8_bytes_needed = 3; - utf8_code_point = bite - 0xF0; - } - - // Otherwise - else { - // Return error. - return decoderError(fatal); + decrypt: async function(ct, iv, adata = new Uint8Array()) { + const de = new nodeCrypto$4.createDecipheriv('aes-' + (key.length * 8) + '-gcm', key, iv); + de.setAAD(adata); + de.setAuthTag(ct.slice(ct.length - tagLength$2, ct.length)); // read auth tag at end of ciphertext + const pt = Buffer$2.concat([de.update(ct.slice(0, ct.length - tagLength$2)), de.final()]); + return new Uint8Array(pt); } + }; + } - // Then (byte is in the range 0xC2 to 0xF4) set utf-8 code - // point to utf-8 code point << (6 × utf-8 bytes needed) and - // return continue. - utf8_code_point = utf8_code_point << (6 * utf8_bytes_needed); - return null; - } - - // 4. If byte is not in the range utf-8 lower boundary to utf-8 - // upper boundary, run these substeps: - if (!inRange(bite, utf8_lower_boundary, utf8_upper_boundary)) { - - // 1. Set utf-8 code point, utf-8 bytes needed, and utf-8 - // bytes seen to 0, set utf-8 lower boundary to 0x80, and set - // utf-8 upper boundary to 0xBF. - utf8_code_point = utf8_bytes_needed = utf8_bytes_seen = 0; - utf8_lower_boundary = 0x80; - utf8_upper_boundary = 0xBF; - - // 2. Prepend byte to stream. - stream.prepend(bite); + return { + encrypt: async function(pt, iv, adata) { + return AES_GCM.encrypt(pt, key, iv, adata); + }, - // 3. Return error. - return decoderError(fatal); + decrypt: async function(ct, iv, adata) { + return AES_GCM.decrypt(ct, key, iv, adata); } - - // 5. Set utf-8 lower boundary to 0x80 and utf-8 upper boundary - // to 0xBF. - utf8_lower_boundary = 0x80; - utf8_upper_boundary = 0xBF; - - // 6. Increase utf-8 bytes seen by one and set utf-8 code point - // to utf-8 code point + (byte − 0x80) << (6 × (utf-8 bytes - // needed − utf-8 bytes seen)). - utf8_bytes_seen += 1; - utf8_code_point += (bite - 0x80) << (6 * (utf8_bytes_needed - utf8_bytes_seen)); - - // 7. If utf-8 bytes seen is not equal to utf-8 bytes needed, - // continue. - if (utf8_bytes_seen !== utf8_bytes_needed) - return null; - - // 8. Let code point be utf-8 code point. - var code_point = utf8_code_point; - - // 9. Set utf-8 code point, utf-8 bytes needed, and utf-8 bytes - // seen to 0. - utf8_code_point = utf8_bytes_needed = utf8_bytes_seen = 0; - - // 10. Return a code point whose value is code point. - return code_point; }; } + /** - * @constructor - * @implements {Encoder} - * @param {{fatal: boolean}} options + * Get GCM nonce. Note: this operation is not defined by the standard. + * A future version of the standard may define GCM mode differently, + * hopefully under a different ID (we use Private/Experimental algorithm + * ID 100) so that we can maintain backwards compatibility. + * @param {Uint8Array} iv - The initialization vector (12 bytes) + * @param {Uint8Array} chunkIndex - The chunk index (8 bytes) */ -function UTF8Encoder(options) { - var fatal = options.fatal; - /** - * @param {Stream} stream Input stream. - * @param {number} code_point Next code point read from the stream. - * @return {(number|!Array.)} Byte(s) to emit. - */ - this.handler = function(stream, code_point) { - // 1. If code point is end-of-stream, return finished. - if (code_point === end_of_stream) - return finished; - - // 2. If code point is in the range U+0000 to U+007F, return a - // byte whose value is code point. - if (inRange(code_point, 0x0000, 0x007f)) - return code_point; - - // 3. Set count and offset based on the range code point is in: - var count, offset; - // U+0080 to U+07FF: 1 and 0xC0 - if (inRange(code_point, 0x0080, 0x07FF)) { - count = 1; - offset = 0xC0; - } - // U+0800 to U+FFFF: 2 and 0xE0 - else if (inRange(code_point, 0x0800, 0xFFFF)) { - count = 2; - offset = 0xE0; - } - // U+10000 to U+10FFFF: 3 and 0xF0 - else if (inRange(code_point, 0x10000, 0x10FFFF)) { - count = 3; - offset = 0xF0; - } - - // 4.Let bytes be a byte sequence whose first byte is (code - // point >> (6 × count)) + offset. - var bytes = [(code_point >> (6 * count)) + offset]; - - // 5. Run these substeps while count is greater than 0: - while (count > 0) { - - // 1. Set temp to code point >> (6 × (count − 1)). - var temp = code_point >> (6 * (count - 1)); +GCM.getNonce = function(iv, chunkIndex) { + const nonce = iv.slice(); + for (let i = 0; i < chunkIndex.length; i++) { + nonce[4 + i] ^= chunkIndex[i]; + } + return nonce; +}; - // 2. Append to bytes 0x80 | (temp & 0x3F). - bytes.push(0x80 | (temp & 0x3F)); +GCM.blockLength = blockLength$3; +GCM.ivLength = ivLength$2; +GCM.tagLength = tagLength$2; - // 3. Decrease count by one. - count -= 1; - } +/** + * @fileoverview Cipher modes + * @module crypto/mode + * @private + */ - // 6. Return bytes bytes, in order. - return bytes; - }; -} +var mode = { + /** @see module:crypto/mode/cfb */ + cfb: cfb, + /** @see module:crypto/mode/gcm */ + gcm: GCM, + experimentalGCM: GCM, + /** @see module:crypto/mode/eax */ + eax: EAX, + /** @see module:crypto/mode/ocb */ + ocb: OCB +}; -exports.TextEncoder = TextEncoder; -exports.TextDecoder = TextDecoder; -},{}],72:[function(require,module,exports){ +var naclFastLight = createCommonjsModule(function (module) { /*jshint bitwise: false*/ (function(nacl) { -'use strict'; // Ported in 2014 by Dmitry Chestnykh and Devi Mandiri. // Public domain. @@ -23259,19608 +11407,32140 @@ function M(o, a, b) { t29 += v * b14; t30 += v * b15; - t0 += 38 * t16; - t1 += 38 * t17; - t2 += 38 * t18; - t3 += 38 * t19; - t4 += 38 * t20; - t5 += 38 * t21; - t6 += 38 * t22; - t7 += 38 * t23; - t8 += 38 * t24; - t9 += 38 * t25; - t10 += 38 * t26; - t11 += 38 * t27; - t12 += 38 * t28; - t13 += 38 * t29; - t14 += 38 * t30; - // t15 left as is + t0 += 38 * t16; + t1 += 38 * t17; + t2 += 38 * t18; + t3 += 38 * t19; + t4 += 38 * t20; + t5 += 38 * t21; + t6 += 38 * t22; + t7 += 38 * t23; + t8 += 38 * t24; + t9 += 38 * t25; + t10 += 38 * t26; + t11 += 38 * t27; + t12 += 38 * t28; + t13 += 38 * t29; + t14 += 38 * t30; + // t15 left as is + + // first car + c = 1; + v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536; + v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536; + v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536; + v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536; + v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536; + v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536; + v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536; + v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536; + v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536; + v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536; + v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536; + v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536; + v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536; + v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536; + v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536; + v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536; + t0 += c-1 + 37 * (c-1); + + // second car + c = 1; + v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536; + v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536; + v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536; + v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536; + v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536; + v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536; + v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536; + v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536; + v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536; + v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536; + v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536; + v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536; + v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536; + v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536; + v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536; + v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536; + t0 += c-1 + 37 * (c-1); + + o[ 0] = t0; + o[ 1] = t1; + o[ 2] = t2; + o[ 3] = t3; + o[ 4] = t4; + o[ 5] = t5; + o[ 6] = t6; + o[ 7] = t7; + o[ 8] = t8; + o[ 9] = t9; + o[10] = t10; + o[11] = t11; + o[12] = t12; + o[13] = t13; + o[14] = t14; + o[15] = t15; +} + +function S(o, a) { + M(o, a, a); +} + +function inv25519(o, i) { + var c = gf(); + var a; + for (a = 0; a < 16; a++) c[a] = i[a]; + for (a = 253; a >= 0; a--) { + S(c, c); + if(a !== 2 && a !== 4) M(c, c, i); + } + for (a = 0; a < 16; a++) o[a] = c[a]; +} + +function pow2523(o, i) { + var c = gf(); + var a; + for (a = 0; a < 16; a++) c[a] = i[a]; + for (a = 250; a >= 0; a--) { + S(c, c); + if(a !== 1) M(c, c, i); + } + for (a = 0; a < 16; a++) o[a] = c[a]; +} + +function crypto_scalarmult(q, n, p) { + var z = new Uint8Array(32); + var x = new Float64Array(80), r, i; + var a = gf(), b = gf(), c = gf(), + d = gf(), e = gf(), f = gf(); + for (i = 0; i < 31; i++) z[i] = n[i]; + z[31]=(n[31]&127)|64; + z[0]&=248; + unpack25519(x,p); + for (i = 0; i < 16; i++) { + b[i]=x[i]; + d[i]=a[i]=c[i]=0; + } + a[0]=d[0]=1; + for (i=254; i>=0; --i) { + r=(z[i>>>3]>>>(i&7))&1; + sel25519(a,b,r); + sel25519(c,d,r); + A(e,a,c); + Z(a,a,c); + A(c,b,d); + Z(b,b,d); + S(d,e); + S(f,a); + M(a,c,a); + M(c,b,e); + A(e,a,c); + Z(a,a,c); + S(b,a); + Z(c,d,f); + M(a,c,_121665); + A(a,a,d); + M(c,c,a); + M(a,d,f); + M(d,b,x); + S(b,e); + sel25519(a,b,r); + sel25519(c,d,r); + } + for (i = 0; i < 16; i++) { + x[i+16]=a[i]; + x[i+32]=c[i]; + x[i+48]=b[i]; + x[i+64]=d[i]; + } + var x32 = x.subarray(32); + var x16 = x.subarray(16); + inv25519(x32,x32); + M(x16,x16,x32); + pack25519(q,x16); + return 0; +} + +function crypto_scalarmult_base(q, n) { + return crypto_scalarmult(q, n, _9); +} + +function crypto_box_keypair(y, x) { + randombytes(x, 32); + return crypto_scalarmult_base(y, x); +} + +function add(p, q) { + var a = gf(), b = gf(), c = gf(), + d = gf(), e = gf(), f = gf(), + g = gf(), h = gf(), t = gf(); + + Z(a, p[1], p[0]); + Z(t, q[1], q[0]); + M(a, a, t); + A(b, p[0], p[1]); + A(t, q[0], q[1]); + M(b, b, t); + M(c, p[3], q[3]); + M(c, c, D2); + M(d, p[2], q[2]); + A(d, d, d); + Z(e, b, a); + Z(f, d, c); + A(g, d, c); + A(h, b, a); + + M(p[0], e, f); + M(p[1], h, g); + M(p[2], g, f); + M(p[3], e, h); +} + +function cswap(p, q, b) { + var i; + for (i = 0; i < 4; i++) { + sel25519(p[i], q[i], b); + } +} + +function pack(r, p) { + var tx = gf(), ty = gf(), zi = gf(); + inv25519(zi, p[2]); + M(tx, p[0], zi); + M(ty, p[1], zi); + pack25519(r, ty); + r[31] ^= par25519(tx) << 7; +} + +function scalarmult(p, q, s) { + var b, i; + set25519(p[0], gf0); + set25519(p[1], gf1); + set25519(p[2], gf1); + set25519(p[3], gf0); + for (i = 255; i >= 0; --i) { + b = (s[(i/8)|0] >> (i&7)) & 1; + cswap(p, q, b); + add(q, p); + add(p, p); + cswap(p, q, b); + } +} + +function scalarbase(p, s) { + var q = [gf(), gf(), gf(), gf()]; + set25519(q[0], X); + set25519(q[1], Y); + set25519(q[2], gf1); + M(q[3], X, Y); + scalarmult(p, q, s); +} + +function crypto_sign_keypair(pk, sk, seeded) { + var d; + var p = [gf(), gf(), gf(), gf()]; + var i; + + if (!seeded) randombytes(sk, 32); + d = nacl.hash(sk.subarray(0, 32)); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + scalarbase(p, d); + pack(pk, p); + + for (i = 0; i < 32; i++) sk[i+32] = pk[i]; + return 0; +} + +var L = new Float64Array([0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10]); + +function modL(r, x) { + var carry, i, j, k; + for (i = 63; i >= 32; --i) { + carry = 0; + for (j = i - 32, k = i - 12; j < k; ++j) { + x[j] += carry - 16 * x[i] * L[j - (i - 32)]; + carry = Math.floor((x[j] + 128) / 256); + x[j] -= carry * 256; + } + x[j] += carry; + x[i] = 0; + } + carry = 0; + for (j = 0; j < 32; j++) { + x[j] += carry - (x[31] >> 4) * L[j]; + carry = x[j] >> 8; + x[j] &= 255; + } + for (j = 0; j < 32; j++) x[j] -= carry * L[j]; + for (i = 0; i < 32; i++) { + x[i+1] += x[i] >> 8; + r[i] = x[i] & 255; + } +} + +function reduce(r) { + var x = new Float64Array(64), i; + for (i = 0; i < 64; i++) x[i] = r[i]; + for (i = 0; i < 64; i++) r[i] = 0; + modL(r, x); +} + +// Note: difference from C - smlen returned, not passed as argument. +function crypto_sign(sm, m, n, sk) { + var d, h, r; + var i, j, x = new Float64Array(64); + var p = [gf(), gf(), gf(), gf()]; + + d = nacl.hash(sk.subarray(0, 32)); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + var smlen = n + 64; + for (i = 0; i < n; i++) sm[64 + i] = m[i]; + for (i = 0; i < 32; i++) sm[32 + i] = d[32 + i]; + + r = nacl.hash(sm.subarray(32, smlen)); + reduce(r); + scalarbase(p, r); + pack(sm, p); + + for (i = 32; i < 64; i++) sm[i] = sk[i]; + h = nacl.hash(sm.subarray(0, smlen)); + reduce(h); + + for (i = 0; i < 64; i++) x[i] = 0; + for (i = 0; i < 32; i++) x[i] = r[i]; + for (i = 0; i < 32; i++) { + for (j = 0; j < 32; j++) { + x[i+j] += h[i] * d[j]; + } + } + + modL(sm.subarray(32), x); + return smlen; +} + +function unpackneg(r, p) { + var t = gf(), chk = gf(), num = gf(), + den = gf(), den2 = gf(), den4 = gf(), + den6 = gf(); + + set25519(r[2], gf1); + unpack25519(r[1], p); + S(num, r[1]); + M(den, num, D); + Z(num, num, r[2]); + A(den, r[2], den); + + S(den2, den); + S(den4, den2); + M(den6, den4, den2); + M(t, den6, num); + M(t, t, den); + + pow2523(t, t); + M(t, t, num); + M(t, t, den); + M(t, t, den); + M(r[0], t, den); + + S(chk, r[0]); + M(chk, chk, den); + if (neq25519(chk, num)) M(r[0], r[0], I); + + S(chk, r[0]); + M(chk, chk, den); + if (neq25519(chk, num)) return -1; + + if (par25519(r[0]) === (p[31]>>7)) Z(r[0], gf0, r[0]); + + M(r[3], r[0], r[1]); + return 0; +} + +function crypto_sign_open(m, sm, n, pk) { + var i; + var t = new Uint8Array(32), h; + var p = [gf(), gf(), gf(), gf()], + q = [gf(), gf(), gf(), gf()]; + + if (n < 64) return -1; + + if (unpackneg(q, pk)) return -1; + + for (i = 0; i < n; i++) m[i] = sm[i]; + for (i = 0; i < 32; i++) m[i+32] = pk[i]; + h = nacl.hash(m.subarray(0, n)); + reduce(h); + scalarmult(p, q, h); + + scalarbase(q, sm.subarray(32)); + add(p, q); + pack(t, p); + + n -= 64; + if (crypto_verify_32(sm, 0, t, 0)) { + for (i = 0; i < n; i++) m[i] = 0; + return -1; + } + + for (i = 0; i < n; i++) m[i] = sm[i + 64]; + return n; +} + +var crypto_scalarmult_BYTES = 32, + crypto_scalarmult_SCALARBYTES = 32, + crypto_box_PUBLICKEYBYTES = 32, + crypto_box_SECRETKEYBYTES = 32, + crypto_sign_BYTES = 64, + crypto_sign_PUBLICKEYBYTES = 32, + crypto_sign_SECRETKEYBYTES = 64, + crypto_sign_SEEDBYTES = 32; + +function checkArrayTypes() { + for (var i = 0; i < arguments.length; i++) { + if (!(arguments[i] instanceof Uint8Array)) + throw new TypeError('unexpected type, use Uint8Array'); + } +} + +function cleanup(arr) { + for (var i = 0; i < arr.length; i++) arr[i] = 0; +} + +nacl.scalarMult = function(n, p) { + checkArrayTypes(n, p); + if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error('bad n size'); + if (p.length !== crypto_scalarmult_BYTES) throw new Error('bad p size'); + var q = new Uint8Array(crypto_scalarmult_BYTES); + crypto_scalarmult(q, n, p); + return q; +}; + +nacl.box = {}; + +nacl.box.keyPair = function() { + var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); + var sk = new Uint8Array(crypto_box_SECRETKEYBYTES); + crypto_box_keypair(pk, sk); + return {publicKey: pk, secretKey: sk}; +}; + +nacl.box.keyPair.fromSecretKey = function(secretKey) { + checkArrayTypes(secretKey); + if (secretKey.length !== crypto_box_SECRETKEYBYTES) + throw new Error('bad secret key size'); + var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); + crypto_scalarmult_base(pk, secretKey); + return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; +}; + +nacl.sign = function(msg, secretKey) { + checkArrayTypes(msg, secretKey); + if (secretKey.length !== crypto_sign_SECRETKEYBYTES) + throw new Error('bad secret key size'); + var signedMsg = new Uint8Array(crypto_sign_BYTES+msg.length); + crypto_sign(signedMsg, msg, msg.length, secretKey); + return signedMsg; +}; + +nacl.sign.detached = function(msg, secretKey) { + var signedMsg = nacl.sign(msg, secretKey); + var sig = new Uint8Array(crypto_sign_BYTES); + for (var i = 0; i < sig.length; i++) sig[i] = signedMsg[i]; + return sig; +}; + +nacl.sign.detached.verify = function(msg, sig, publicKey) { + checkArrayTypes(msg, sig, publicKey); + if (sig.length !== crypto_sign_BYTES) + throw new Error('bad signature size'); + if (publicKey.length !== crypto_sign_PUBLICKEYBYTES) + throw new Error('bad public key size'); + var sm = new Uint8Array(crypto_sign_BYTES + msg.length); + var m = new Uint8Array(crypto_sign_BYTES + msg.length); + var i; + for (i = 0; i < crypto_sign_BYTES; i++) sm[i] = sig[i]; + for (i = 0; i < msg.length; i++) sm[i+crypto_sign_BYTES] = msg[i]; + return (crypto_sign_open(m, sm, sm.length, publicKey) >= 0); +}; + +nacl.sign.keyPair = function() { + var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); + var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); + crypto_sign_keypair(pk, sk); + return {publicKey: pk, secretKey: sk}; +}; + +nacl.sign.keyPair.fromSecretKey = function(secretKey) { + checkArrayTypes(secretKey); + if (secretKey.length !== crypto_sign_SECRETKEYBYTES) + throw new Error('bad secret key size'); + var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); + for (var i = 0; i < pk.length; i++) pk[i] = secretKey[32+i]; + return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; +}; + +nacl.sign.keyPair.fromSeed = function(seed) { + checkArrayTypes(seed); + if (seed.length !== crypto_sign_SEEDBYTES) + throw new Error('bad seed size'); + var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); + var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); + for (var i = 0; i < 32; i++) sk[i] = seed[i]; + crypto_sign_keypair(pk, sk, true); + return {publicKey: pk, secretKey: sk}; +}; + +nacl.setPRNG = function(fn) { + randombytes = fn; +}; + +(function() { + // Initialize PRNG if environment provides CSPRNG. + // If not, methods calling randombytes will throw. + var crypto = typeof self !== 'undefined' ? (self.crypto || self.msCrypto) : null; + if (crypto && crypto.getRandomValues) { + // Browsers. + var QUOTA = 65536; + nacl.setPRNG(function(x, n) { + var i, v = new Uint8Array(n); + for (i = 0; i < n; i += QUOTA) { + crypto.getRandomValues(v.subarray(i, i + Math.min(n - i, QUOTA))); + } + for (i = 0; i < n; i++) x[i] = v[i]; + cleanup(v); + }); + } else if (typeof commonjsRequire !== 'undefined') { + // Node.js. + crypto = crypto__default['default']; + if (crypto && crypto.randomBytes) { + nacl.setPRNG(function(x, n) { + var i, v = crypto.randomBytes(n); + for (i = 0; i < n; i++) x[i] = v[i]; + cleanup(v); + }); + } + } +})(); + +})(module.exports ? module.exports : (self.nacl = self.nacl || {})); +}); + +// GPG4Browsers - An OpenPGP implementation in javascript + +const nodeCrypto$5 = util.getNodeCrypto(); + +/** + * Buffer for secure random numbers + */ +class RandomBuffer { + constructor() { + this.buffer = null; + this.size = null; + this.callback = null; + } + + /** + * Initialize buffer + * @param {Integer} size - size of buffer + */ + init(size, callback) { + this.buffer = new Uint8Array(size); + this.size = 0; + this.callback = callback; + } + + /** + * Concat array of secure random numbers to buffer + * @param {Uint8Array} buf + */ + set(buf) { + if (!this.buffer) { + throw new Error('RandomBuffer is not initialized'); + } + if (!(buf instanceof Uint8Array)) { + throw new Error('Invalid type: buf not an Uint8Array'); + } + const freeSpace = this.buffer.length - this.size; + if (buf.length > freeSpace) { + buf = buf.subarray(0, freeSpace); + } + // set buf with offset old size of buffer + this.buffer.set(buf, this.size); + this.size += buf.length; + } + + /** + * Take numbers out of buffer and copy to array + * @param {Uint8Array} buf - The destination array + */ + async get(buf) { + if (!this.buffer) { + throw new Error('RandomBuffer is not initialized'); + } + if (!(buf instanceof Uint8Array)) { + throw new Error('Invalid type: buf not an Uint8Array'); + } + if (this.size < buf.length) { + if (!this.callback) { + throw new Error('Random number buffer depleted'); + } + // Wait for random bytes from main context, then try again + await this.callback(); + return this.get(buf); + } + for (let i = 0; i < buf.length; i++) { + buf[i] = this.buffer[--this.size]; + // clear buffer value + this.buffer[this.size] = 0; + } + } +} + +/** + * Retrieve secure random byte array of the specified length + * @param {Integer} length - Length in bytes to generate + * @returns {Promise} Random byte array. + * @async + */ +async function getRandomBytes(length) { + const buf = new Uint8Array(length); + if (typeof crypto !== 'undefined' && crypto.getRandomValues) { + crypto.getRandomValues(buf); + } else if (nodeCrypto$5) { + const bytes = nodeCrypto$5.randomBytes(buf.length); + buf.set(bytes); + } else if (randomBuffer.buffer) { + await randomBuffer.get(buf); + } else { + throw new Error('No secure random number generator available.'); + } + return buf; +} + +/** + * Create a secure random BigInteger that is greater than or equal to min and less than max. + * @param {module:BigInteger} min - Lower bound, included + * @param {module:BigInteger} max - Upper bound, excluded + * @returns {Promise} Random BigInteger. + * @async + */ +async function getRandomBigInteger(min, max) { + const BigInteger = await util.getBigInteger(); + + if (max.lt(min)) { + throw new Error('Illegal parameter value: max <= min'); + } + + const modulus = max.sub(min); + const bytes = modulus.byteLength(); + + // Using a while loop is necessary to avoid bias introduced by the mod operation. + // However, we request 64 extra random bits so that the bias is negligible. + // Section B.1.1 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf + const r = new BigInteger(await getRandomBytes(bytes + 8)); + return r.mod(modulus).add(min); +} + +const randomBuffer = new RandomBuffer(); + +var random = /*#__PURE__*/Object.freeze({ + __proto__: null, + getRandomBytes: getRandomBytes, + getRandomBigInteger: getRandomBigInteger, + randomBuffer: randomBuffer +}); + +// OpenPGP.js - An OpenPGP implementation in javascript + +/** + * Generate a probably prime random number + * @param {Integer} bits - Bit length of the prime + * @param {BigInteger} e - Optional RSA exponent to check against the prime + * @param {Integer} k - Optional number of iterations of Miller-Rabin test + * @returns BigInteger + * @async + */ +async function randomProbablePrime(bits, e, k) { + const BigInteger = await util.getBigInteger(); + const one = new BigInteger(1); + const min = one.leftShift(new BigInteger(bits - 1)); + const thirty = new BigInteger(30); + /* + * We can avoid any multiples of 3 and 5 by looking at n mod 30 + * n mod 30 = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 + * the next possible prime is mod 30: + * 1 7 7 7 7 7 7 11 11 11 11 13 13 17 17 17 17 19 19 23 23 23 23 29 29 29 29 29 29 1 + */ + const adds = [1, 6, 5, 4, 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, 3, 2, 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1, 2]; + + const n = await getRandomBigInteger(min, min.leftShift(one)); + let i = n.mod(thirty).toNumber(); + + do { + n.iadd(new BigInteger(adds[i])); + i = (i + adds[i]) % adds.length; + // If reached the maximum, go back to the minimum. + if (n.bitLength() > bits) { + n.imod(min.leftShift(one)).iadd(min); + i = n.mod(thirty).toNumber(); + } + } while (!await isProbablePrime(n, e, k)); + return n; +} + +/** + * Probabilistic primality testing + * @param {BigInteger} n - Number to test + * @param {BigInteger} e - Optional RSA exponent to check against the prime + * @param {Integer} k - Optional number of iterations of Miller-Rabin test + * @returns {boolean} + * @async + */ +async function isProbablePrime(n, e, k) { + if (e && !n.dec().gcd(e).isOne()) { + return false; + } + if (!await divisionTest(n)) { + return false; + } + if (!await fermat(n)) { + return false; + } + if (!await millerRabin(n, k)) { + return false; + } + // TODO implement the Lucas test + // See Section C.3.3 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf + return true; +} + +/** + * Tests whether n is probably prime or not using Fermat's test with b = 2. + * Fails if b^(n-1) mod n != 1. + * @param {BigInteger} n - Number to test + * @param {BigInteger} b - Optional Fermat test base + * @returns {boolean} + */ +async function fermat(n, b) { + const BigInteger = await util.getBigInteger(); + b = b || new BigInteger(2); + return b.modExp(n.dec(), n).isOne(); +} + +async function divisionTest(n) { + const BigInteger = await util.getBigInteger(); + return smallPrimes.every(m => { + return n.mod(new BigInteger(m)) !== 0; + }); +} + +// https://github.com/gpg/libgcrypt/blob/master/cipher/primegen.c +const smallPrimes = [ + 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, + 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, + 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, + 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, + 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, + 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, + 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, + 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, + 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, + 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, + 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, + 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, + 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, + 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, + 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, + 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, + 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, + 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, + 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, + 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, + 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, + 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, + 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, + 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, + 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, + 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, + 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, + 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, + 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, + 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, + 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, + 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, + 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, + 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, + 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, + 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, + 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, + 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, + 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, + 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, + 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, + 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, + 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, + 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, + 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, + 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, + 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, + 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, + 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, + 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, + 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, + 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, + 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, + 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, + 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, + 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, + 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, + 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, + 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, + 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, + 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, + 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, + 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, + 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, + 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, + 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, + 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, + 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, + 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, + 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, + 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457, + 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, + 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, + 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, + 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, + 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, + 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, + 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, + 4957, 4967, 4969, 4973, 4987, 4993, 4999 +]; + + +// Miller-Rabin - Miller Rabin algorithm for primality test +// Copyright Fedor Indutny, 2014. +// +// This software is licensed under the MIT License. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// Adapted on Jan 2018 from version 4.0.1 at https://github.com/indutny/miller-rabin + +// Sample syntax for Fixed-Base Miller-Rabin: +// millerRabin(n, k, () => new BN(small_primes[Math.random() * small_primes.length | 0])) + +/** + * Tests whether n is probably prime or not using the Miller-Rabin test. + * See HAC Remark 4.28. + * @param {BigInteger} n - Number to test + * @param {Integer} k - Optional number of iterations of Miller-Rabin test + * @param {Function} rand - Optional function to generate potential witnesses + * @returns {boolean} + * @async + */ +async function millerRabin(n, k, rand) { + const BigInteger = await util.getBigInteger(); + const len = n.bitLength(); + + if (!k) { + k = Math.max(1, (len / 48) | 0); + } + + const n1 = n.dec(); // n - 1 + + // Find d and s, (n - 1) = (2 ^ s) * d; + let s = 0; + while (!n1.getBit(s)) { s++; } + const d = n.rightShift(new BigInteger(s)); + + for (; k > 0; k--) { + const a = rand ? rand() : await getRandomBigInteger(new BigInteger(2), n1); + + let x = a.modExp(d, n); + if (x.isOne() || x.equal(n1)) { + continue; + } + + let i; + for (i = 1; i < s; i++) { + x = x.mul(x).mod(n); + + if (x.isOne()) { + return false; + } + if (x.equal(n1)) { + break; + } + } + + if (i === s) { + return false; + } + } + + return true; +} + +// GPG4Browsers - An OpenPGP implementation in javascript + +/** + * ASN1 object identifiers for hashes + * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.2} + */ +const hash_headers = []; +hash_headers[1] = [0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, + 0x10]; +hash_headers[2] = [0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14]; +hash_headers[3] = [0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14]; +hash_headers[8] = [0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, + 0x04, 0x20]; +hash_headers[9] = [0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, + 0x04, 0x30]; +hash_headers[10] = [0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, + 0x00, 0x04, 0x40]; +hash_headers[11] = [0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, + 0x00, 0x04, 0x1C]; + +/** + * Create padding with secure random data + * @private + * @param {Integer} length - Length of the padding in bytes + * @returns {Promise} Random padding. + * @async + */ +async function getPKCS1Padding(length) { + const result = new Uint8Array(length); + let count = 0; + while (count < length) { + const randomBytes = await getRandomBytes(length - count); + for (let i = 0; i < randomBytes.length; i++) { + if (randomBytes[i] !== 0) { + result[count++] = randomBytes[i]; + } + } + } + return result; +} + +/** + * Create a EME-PKCS1-v1_5 padded message + * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.1|RFC 4880 13.1.1} + * @param {Uint8Array} message - Message to be encoded + * @param {Integer} keyLength - The length in octets of the key modulus + * @returns {Promise} EME-PKCS1 padded message. + * @async + */ +async function emeEncode(message, keyLength) { + const mLength = message.length; + // length checking + if (mLength > keyLength - 11) { + throw new Error('Message too long'); + } + // Generate an octet string PS of length k - mLen - 3 consisting of + // pseudo-randomly generated nonzero octets + const PS = await getPKCS1Padding(keyLength - mLength - 3); + // Concatenate PS, the message M, and other padding to form an + // encoded message EM of length k octets as EM = 0x00 || 0x02 || PS || 0x00 || M. + const encoded = new Uint8Array(keyLength); + // 0x00 byte + encoded[1] = 2; + encoded.set(PS, 2); + // 0x00 bytes + encoded.set(message, keyLength - mLength); + return encoded; +} + +/** + * Decode a EME-PKCS1-v1_5 padded message + * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.2|RFC 4880 13.1.2} + * @param {Uint8Array} encoded - Encoded message bytes + * @param {Uint8Array} randomPayload - Data to return in case of decoding error (needed for constant-time processing) + * @returns {Uint8Array} decoded data or `randomPayload` (on error, if given) + * @throws {Error} on decoding failure, unless `randomPayload` is provided + */ +function emeDecode(encoded, randomPayload) { + // encoded format: 0x00 0x02 0x00 + let offset = 2; + let separatorNotFound = 1; + for (let j = offset; j < encoded.length; j++) { + separatorNotFound &= encoded[j] !== 0; + offset += separatorNotFound; + } + + const psLen = offset - 2; + const payload = encoded.subarray(offset + 1); // discard the 0x00 separator + const isValidPadding = encoded[0] === 0 & encoded[1] === 2 & psLen >= 8 & !separatorNotFound; + + if (randomPayload) { + return util.selectUint8Array(isValidPadding, payload, randomPayload); + } + + if (isValidPadding) { + return payload; + } + + throw new Error('Decryption error'); +} + +/** + * Create a EMSA-PKCS1-v1_5 padded message + * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.3|RFC 4880 13.1.3} + * @param {Integer} algo - Hash algorithm type used + * @param {Uint8Array} hashed - Message to be encoded + * @param {Integer} emLen - Intended length in octets of the encoded message + * @returns {Uint8Array} Encoded message. + */ +async function emsaEncode(algo, hashed, emLen) { + let i; + if (hashed.length !== hash.getHashByteLength(algo)) { + throw new Error('Invalid hash length'); + } + // produce an ASN.1 DER value for the hash function used. + // Let T be the full hash prefix + const hashPrefix = new Uint8Array(hash_headers[algo].length); + for (i = 0; i < hash_headers[algo].length; i++) { + hashPrefix[i] = hash_headers[algo][i]; + } + // and let tLen be the length in octets prefix and hashed data + const tLen = hashPrefix.length + hashed.length; + if (emLen < tLen + 11) { + throw new Error('Intended encoded message length too short'); + } + // an octet string PS consisting of emLen - tLen - 3 octets with hexadecimal value 0xFF + // The length of PS will be at least 8 octets + const PS = new Uint8Array(emLen - tLen - 3).fill(0xff); + + // Concatenate PS, the hash prefix, hashed data, and other padding to form the + // encoded message EM as EM = 0x00 || 0x01 || PS || 0x00 || prefix || hashed + const EM = new Uint8Array(emLen); + EM[1] = 0x01; + EM.set(PS, 2); + EM.set(hashPrefix, emLen - tLen); + EM.set(hashed, emLen - hashed.length); + return EM; +} + +var pkcs1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + emeEncode: emeEncode, + emeDecode: emeDecode, + emsaEncode: emsaEncode +}); + +const webCrypto$5 = util.getWebCrypto(); +const nodeCrypto$6 = util.getNodeCrypto(); +const asn1 = nodeCrypto$6 ? asn1__default['default'] : undefined; + +/* eslint-disable no-invalid-this */ +const RSAPrivateKey = util.detectNode() ? asn1.define('RSAPrivateKey', function () { + this.seq().obj( // used for native NodeJS crypto + this.key('version').int(), // 0 + this.key('modulus').int(), // n + this.key('publicExponent').int(), // e + this.key('privateExponent').int(), // d + this.key('prime1').int(), // p + this.key('prime2').int(), // q + this.key('exponent1').int(), // dp + this.key('exponent2').int(), // dq + this.key('coefficient').int() // u + ); +}) : undefined; + +const RSAPublicKey = util.detectNode() ? asn1.define('RSAPubliceKey', function () { + this.seq().obj( // used for native NodeJS crypto + this.key('modulus').int(), // n + this.key('publicExponent').int(), // e + ); +}) : undefined; +/* eslint-enable no-invalid-this */ + +/** Create signature + * @param {module:enums.hash} hashAlgo - Hash algorithm + * @param {Uint8Array} data - Message + * @param {Uint8Array} n - RSA public modulus + * @param {Uint8Array} e - RSA public exponent + * @param {Uint8Array} d - RSA private exponent + * @param {Uint8Array} p - RSA private prime p + * @param {Uint8Array} q - RSA private prime q + * @param {Uint8Array} u - RSA private coefficient + * @param {Uint8Array} hashed - Hashed message + * @returns {Promise} RSA Signature. + * @async + */ +async function sign(hashAlgo, data, n, e, d, p, q, u, hashed) { + if (data && !util.isStream(data)) { + if (util.getWebCrypto()) { + try { + return await webSign(enums.read(enums.webHash, hashAlgo), data, n, e, d, p, q, u); + } catch (err) { + util.printDebugError(err); + } + } else if (util.getNodeCrypto()) { + return nodeSign(hashAlgo, data, n, e, d, p, q, u); + } + } + return bnSign(hashAlgo, n, d, hashed); +} + +/** + * Verify signature + * @param {module:enums.hash} hashAlgo - Hash algorithm + * @param {Uint8Array} data - Message + * @param {Uint8Array} s - Signature + * @param {Uint8Array} n - RSA public modulus + * @param {Uint8Array} e - RSA public exponent + * @param {Uint8Array} hashed - Hashed message + * @returns {Boolean} + * @async + */ +async function verify(hashAlgo, data, s, n, e, hashed) { + if (data && !util.isStream(data)) { + if (util.getWebCrypto()) { + try { + return await webVerify(enums.read(enums.webHash, hashAlgo), data, s, n, e); + } catch (err) { + util.printDebugError(err); + } + } else if (util.getNodeCrypto()) { + return nodeVerify(hashAlgo, data, s, n, e); + } + } + return bnVerify(hashAlgo, s, n, e, hashed); +} + +/** + * Encrypt message + * @param {Uint8Array} data - Message + * @param {Uint8Array} n - RSA public modulus + * @param {Uint8Array} e - RSA public exponent + * @returns {Promise} RSA Ciphertext. + * @async + */ +async function encrypt$1(data, n, e) { + if (util.getNodeCrypto()) { + return nodeEncrypt$1(data, n, e); + } + return bnEncrypt(data, n, e); +} + +/** + * Decrypt RSA message + * @param {Uint8Array} m - Message + * @param {Uint8Array} n - RSA public modulus + * @param {Uint8Array} e - RSA public exponent + * @param {Uint8Array} d - RSA private exponent + * @param {Uint8Array} p - RSA private prime p + * @param {Uint8Array} q - RSA private prime q + * @param {Uint8Array} u - RSA private coefficient + * @param {Uint8Array} randomPayload - Data to return on decryption error, instead of throwing + * (needed for constant-time processing) + * @returns {Promise} RSA Plaintext. + * @throws {Error} on decryption error, unless `randomPayload` is given + * @async + */ +async function decrypt$1(data, n, e, d, p, q, u, randomPayload) { + if (util.getNodeCrypto()) { + return nodeDecrypt$1(data, n, e, d, p, q, u, randomPayload); + } + return bnDecrypt(data, n, e, d, p, q, u, randomPayload); +} + +/** + * Generate a new random private key B bits long with public exponent E. + * + * When possible, webCrypto or nodeCrypto is used. Otherwise, primes are generated using + * 40 rounds of the Miller-Rabin probabilistic random prime generation algorithm. + * @see module:crypto/public_key/prime + * @param {Integer} bits - RSA bit length + * @param {Integer} e - RSA public exponent + * @returns {{n, e, d, + * p, q ,u: Uint8Array}} RSA public modulus, RSA public exponent, RSA private exponent, + * RSA private prime p, RSA private prime q, u = p ** -1 mod q + * @async + */ +async function generate(bits, e) { + const BigInteger = await util.getBigInteger(); + + e = new BigInteger(e); + + // Native RSA keygen using Web Crypto + if (util.getWebCrypto()) { + const keyGenOpt = { + name: 'RSASSA-PKCS1-v1_5', + modulusLength: bits, // the specified keysize in bits + publicExponent: e.toUint8Array(), // take three bytes (max 65537) for exponent + hash: { + name: 'SHA-1' // not required for actual RSA keys, but for crypto api 'sign' and 'verify' + } + }; + const keyPair = await webCrypto$5.generateKey(keyGenOpt, true, ['sign', 'verify']); + + // export the generated keys as JsonWebKey (JWK) + // https://tools.ietf.org/html/draft-ietf-jose-json-web-key-33 + const jwk = await webCrypto$5.exportKey('jwk', keyPair.privateKey); + // map JWK parameters to corresponding OpenPGP names + return { + n: b64ToUint8Array(jwk.n), + e: e.toUint8Array(), + d: b64ToUint8Array(jwk.d), + // switch p and q + p: b64ToUint8Array(jwk.q), + q: b64ToUint8Array(jwk.p), + // Since p and q are switched in places, u is the inverse of jwk.q + u: b64ToUint8Array(jwk.qi) + }; + } else if (util.getNodeCrypto() && nodeCrypto$6.generateKeyPair && RSAPrivateKey) { + const opts = { + modulusLength: bits, + publicExponent: e.toNumber(), + publicKeyEncoding: { type: 'pkcs1', format: 'der' }, + privateKeyEncoding: { type: 'pkcs1', format: 'der' } + }; + const prv = await new Promise((resolve, reject) => nodeCrypto$6.generateKeyPair('rsa', opts, (err, _, der) => { + if (err) { + reject(err); + } else { + resolve(RSAPrivateKey.decode(der, 'der')); + } + })); + /** + * OpenPGP spec differs from DER spec, DER: `u = (inverse of q) mod p`, OpenPGP: `u = (inverse of p) mod q`. + * @link https://tools.ietf.org/html/rfc3447#section-3.2 + * @link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-08#section-5.6.1 + */ + return { + n: prv.modulus.toArrayLike(Uint8Array), + e: prv.publicExponent.toArrayLike(Uint8Array), + d: prv.privateExponent.toArrayLike(Uint8Array), + // switch p and q + p: prv.prime2.toArrayLike(Uint8Array), + q: prv.prime1.toArrayLike(Uint8Array), + // Since p and q are switched in places, we can keep u as defined by DER + u: prv.coefficient.toArrayLike(Uint8Array) + }; + } + + // RSA keygen fallback using 40 iterations of the Miller-Rabin test + // See https://stackoverflow.com/a/6330138 for justification + // Also see section C.3 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST + let p; + let q; + let n; + do { + q = await randomProbablePrime(bits - (bits >> 1), e, 40); + p = await randomProbablePrime(bits >> 1, e, 40); + n = p.mul(q); + } while (n.bitLength() !== bits); + + const phi = p.dec().imul(q.dec()); + + if (q.lt(p)) { + [p, q] = [q, p]; + } + + return { + n: n.toUint8Array(), + e: e.toUint8Array(), + d: e.modInv(phi).toUint8Array(), + p: p.toUint8Array(), + q: q.toUint8Array(), + // dp: d.mod(p.subn(1)), + // dq: d.mod(q.subn(1)), + u: p.modInv(q).toUint8Array() + }; +} + +/** + * Validate RSA parameters + * @param {Uint8Array} n - RSA public modulus + * @param {Uint8Array} e - RSA public exponent + * @param {Uint8Array} d - RSA private exponent + * @param {Uint8Array} p - RSA private prime p + * @param {Uint8Array} q - RSA private prime q + * @param {Uint8Array} u - RSA inverse of p w.r.t. q + * @returns {Promise} Whether params are valid. + * @async + */ +async function validateParams(n, e, d, p, q, u) { + const BigInteger = await util.getBigInteger(); + n = new BigInteger(n); + p = new BigInteger(p); + q = new BigInteger(q); + + // expect pq = n + if (!p.mul(q).equal(n)) { + return false; + } + + const two = new BigInteger(2); + // expect p*u = 1 mod q + u = new BigInteger(u); + if (!p.mul(u).mod(q).isOne()) { + return false; + } + + e = new BigInteger(e); + d = new BigInteger(d); + /** + * In RSA pkcs#1 the exponents (d, e) are inverses modulo lcm(p-1, q-1) + * We check that [de = 1 mod (p-1)] and [de = 1 mod (q-1)] + * By CRT on coprime factors of (p-1, q-1) it follows that [de = 1 mod lcm(p-1, q-1)] + * + * We blind the multiplication with r, and check that rde = r mod lcm(p-1, q-1) + */ + const nSizeOver3 = new BigInteger(Math.floor(n.bitLength() / 3)); + const r = await getRandomBigInteger(two, two.leftShift(nSizeOver3)); // r in [ 2, 2^{|n|/3} ) < p and q + const rde = r.mul(d).mul(e); + + const areInverses = rde.mod(p.dec()).equal(r) && rde.mod(q.dec()).equal(r); + if (!areInverses) { + return false; + } + + return true; +} + +async function bnSign(hashAlgo, n, d, hashed) { + const BigInteger = await util.getBigInteger(); + n = new BigInteger(n); + const m = new BigInteger(await emsaEncode(hashAlgo, hashed, n.byteLength())); + d = new BigInteger(d); + if (m.gte(n)) { + throw new Error('Message size cannot exceed modulus size'); + } + return m.modExp(d, n).toUint8Array('be', n.byteLength()); +} + +async function webSign(hashName, data, n, e, d, p, q, u) { + /** OpenPGP keys require that p < q, and Safari Web Crypto requires that p > q. + * We swap them in privateToJWK, so it usually works out, but nevertheless, + * not all OpenPGP keys are compatible with this requirement. + * OpenPGP.js used to generate RSA keys the wrong way around (p > q), and still + * does if the underlying Web Crypto does so (e.g. old MS Edge 50% of the time). + */ + const jwk = await privateToJWK(n, e, d, p, q, u); + const algo = { + name: 'RSASSA-PKCS1-v1_5', + hash: { name: hashName } + }; + const key = await webCrypto$5.importKey('jwk', jwk, algo, false, ['sign']); + // add hash field for ms edge support + return new Uint8Array(await webCrypto$5.sign({ 'name': 'RSASSA-PKCS1-v1_5', 'hash': hashName }, key, data)); +} + +async function nodeSign(hashAlgo, data, n, e, d, p, q, u) { + const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); + const pBNum = new BN(p); + const qBNum = new BN(q); + const dBNum = new BN(d); + const dq = dBNum.mod(qBNum.subn(1)); // d mod (q-1) + const dp = dBNum.mod(pBNum.subn(1)); // d mod (p-1) + const sign = nodeCrypto$6.createSign(enums.read(enums.hash, hashAlgo)); + sign.write(data); + sign.end(); + const keyObject = { + version: 0, + modulus: new BN(n), + publicExponent: new BN(e), + privateExponent: new BN(d), + // switch p and q + prime1: new BN(q), + prime2: new BN(p), + // switch dp and dq + exponent1: dq, + exponent2: dp, + coefficient: new BN(u) + }; + if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { //from version 11.6.0 Node supports der encoded key objects + const der = RSAPrivateKey.encode(keyObject, 'der'); + return new Uint8Array(sign.sign({ key: der, format: 'der', type: 'pkcs1' })); + } + const pem = RSAPrivateKey.encode(keyObject, 'pem', { + label: 'RSA PRIVATE KEY' + }); + return new Uint8Array(sign.sign(pem)); +} + +async function bnVerify(hashAlgo, s, n, e, hashed) { + const BigInteger = await util.getBigInteger(); + n = new BigInteger(n); + s = new BigInteger(s); + e = new BigInteger(e); + if (s.gte(n)) { + throw new Error('Signature size cannot exceed modulus size'); + } + const EM1 = s.modExp(e, n).toUint8Array('be', n.byteLength()); + const EM2 = await emsaEncode(hashAlgo, hashed, n.byteLength()); + return util.equalsUint8Array(EM1, EM2); +} + +async function webVerify(hashName, data, s, n, e) { + const jwk = publicToJWK(n, e); + const key = await webCrypto$5.importKey('jwk', jwk, { + name: 'RSASSA-PKCS1-v1_5', + hash: { name: hashName } + }, false, ['verify']); + // add hash field for ms edge support + return webCrypto$5.verify({ 'name': 'RSASSA-PKCS1-v1_5', 'hash': hashName }, key, s, data); +} + +async function nodeVerify(hashAlgo, data, s, n, e) { + const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); + + const verify = nodeCrypto$6.createVerify(enums.read(enums.hash, hashAlgo)); + verify.write(data); + verify.end(); + const keyObject = { + modulus: new BN(n), + publicExponent: new BN(e) + }; + let key; + if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { //from version 11.6.0 Node supports der encoded key objects + const der = RSAPublicKey.encode(keyObject, 'der'); + key = { key: der, format: 'der', type: 'pkcs1' }; + } else { + key = RSAPublicKey.encode(keyObject, 'pem', { + label: 'RSA PUBLIC KEY' + }); + } + try { + return await verify.verify(key, s); + } catch (err) { + return false; + } +} + +async function nodeEncrypt$1(data, n, e) { + const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); + + const keyObject = { + modulus: new BN(n), + publicExponent: new BN(e) + }; + let key; + if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { + const der = RSAPublicKey.encode(keyObject, 'der'); + key = { key: der, format: 'der', type: 'pkcs1', padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; + } else { + const pem = RSAPublicKey.encode(keyObject, 'pem', { + label: 'RSA PUBLIC KEY' + }); + key = { key: pem, padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; + } + return new Uint8Array(nodeCrypto$6.publicEncrypt(key, data)); +} + +async function bnEncrypt(data, n, e) { + const BigInteger = await util.getBigInteger(); + n = new BigInteger(n); + data = new BigInteger(await emeEncode(data, n.byteLength())); + e = new BigInteger(e); + if (data.gte(n)) { + throw new Error('Message size cannot exceed modulus size'); + } + return data.modExp(e, n).toUint8Array('be', n.byteLength()); +} + +async function nodeDecrypt$1(data, n, e, d, p, q, u, randomPayload) { + const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); + + const pBNum = new BN(p); + const qBNum = new BN(q); + const dBNum = new BN(d); + const dq = dBNum.mod(qBNum.subn(1)); // d mod (q-1) + const dp = dBNum.mod(pBNum.subn(1)); // d mod (p-1) + const keyObject = { + version: 0, + modulus: new BN(n), + publicExponent: new BN(e), + privateExponent: new BN(d), + // switch p and q + prime1: new BN(q), + prime2: new BN(p), + // switch dp and dq + exponent1: dq, + exponent2: dp, + coefficient: new BN(u) + }; + let key; + if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { + const der = RSAPrivateKey.encode(keyObject, 'der'); + key = { key: der, format: 'der' , type: 'pkcs1', padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; + } else { + const pem = RSAPrivateKey.encode(keyObject, 'pem', { + label: 'RSA PRIVATE KEY' + }); + key = { key: pem, padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; + } + try { + return new Uint8Array(nodeCrypto$6.privateDecrypt(key, data)); + } catch (err) { + if (randomPayload) { + return randomPayload; + } + throw new Error('Decryption error'); + } +} + +async function bnDecrypt(data, n, e, d, p, q, u, randomPayload) { + const BigInteger = await util.getBigInteger(); + data = new BigInteger(data); + n = new BigInteger(n); + e = new BigInteger(e); + d = new BigInteger(d); + p = new BigInteger(p); + q = new BigInteger(q); + u = new BigInteger(u); + if (data.gte(n)) { + throw new Error('Data too large.'); + } + const dq = d.mod(q.dec()); // d mod (q-1) + const dp = d.mod(p.dec()); // d mod (p-1) + + const unblinder = (await getRandomBigInteger(new BigInteger(2), n)).mod(n); + const blinder = unblinder.modInv(n).modExp(e, n); + data = data.mul(blinder).mod(n); + + + const mp = data.modExp(dp, p); // data**{d mod (q-1)} mod p + const mq = data.modExp(dq, q); // data**{d mod (p-1)} mod q + const h = u.mul(mq.sub(mp)).mod(q); // u * (mq-mp) mod q (operands already < q) + + let result = h.mul(p).add(mp); // result < n due to relations above + + result = result.mul(unblinder).mod(n); + + + return emeDecode(result.toUint8Array('be', n.byteLength()), randomPayload); +} + +/** Convert Openpgp private key params to jwk key according to + * @link https://tools.ietf.org/html/rfc7517 + * @param {String} hashAlgo + * @param {Uint8Array} n + * @param {Uint8Array} e + * @param {Uint8Array} d + * @param {Uint8Array} p + * @param {Uint8Array} q + * @param {Uint8Array} u + */ +async function privateToJWK(n, e, d, p, q, u) { + const BigInteger = await util.getBigInteger(); + const pNum = new BigInteger(p); + const qNum = new BigInteger(q); + const dNum = new BigInteger(d); + + let dq = dNum.mod(qNum.dec()); // d mod (q-1) + let dp = dNum.mod(pNum.dec()); // d mod (p-1) + dp = dp.toUint8Array(); + dq = dq.toUint8Array(); + return { + kty: 'RSA', + n: uint8ArrayToB64(n, true), + e: uint8ArrayToB64(e, true), + d: uint8ArrayToB64(d, true), + // switch p and q + p: uint8ArrayToB64(q, true), + q: uint8ArrayToB64(p, true), + // switch dp and dq + dp: uint8ArrayToB64(dq, true), + dq: uint8ArrayToB64(dp, true), + qi: uint8ArrayToB64(u, true), + ext: true + }; +} + +/** Convert Openpgp key public params to jwk key according to + * @link https://tools.ietf.org/html/rfc7517 + * @param {String} hashAlgo + * @param {Uint8Array} n + * @param {Uint8Array} e + */ +function publicToJWK(n, e) { + return { + kty: 'RSA', + n: uint8ArrayToB64(n, true), + e: uint8ArrayToB64(e, true), + ext: true + }; +} + +var rsa = /*#__PURE__*/Object.freeze({ + __proto__: null, + sign: sign, + verify: verify, + encrypt: encrypt$1, + decrypt: decrypt$1, + generate: generate, + validateParams: validateParams +}); + +// GPG4Browsers - An OpenPGP implementation in javascript + +/** + * ElGamal Encryption function + * Note that in OpenPGP, the message needs to be padded with PKCS#1 (same as RSA) + * @param {Uint8Array} data - To be padded and encrypted + * @param {Uint8Array} p + * @param {Uint8Array} g + * @param {Uint8Array} y + * @returns {Promise<{ c1: Uint8Array, c2: Uint8Array }>} + * @async + */ +async function encrypt$2(data, p, g, y) { + const BigInteger = await util.getBigInteger(); + p = new BigInteger(p); + g = new BigInteger(g); + y = new BigInteger(y); + + const padded = await emeEncode(data, p.byteLength()); + const m = new BigInteger(padded); + + // OpenPGP uses a "special" version of ElGamal where g is generator of the full group Z/pZ* + // hence g has order p-1, and to avoid that k = 0 mod p-1, we need to pick k in [1, p-2] + const k = await getRandomBigInteger(new BigInteger(1), p.dec()); + return { + c1: g.modExp(k, p).toUint8Array(), + c2: y.modExp(k, p).imul(m).imod(p).toUint8Array() + }; +} + +/** + * ElGamal Encryption function + * @param {Uint8Array} c1 + * @param {Uint8Array} c2 + * @param {Uint8Array} p + * @param {Uint8Array} x + * @param {Uint8Array} randomPayload - Data to return on unpadding error, instead of throwing + * (needed for constant-time processing) + * @returns {Promise} Unpadded message. + * @throws {Error} on decryption error, unless `randomPayload` is given + * @async + */ +async function decrypt$2(c1, c2, p, x, randomPayload) { + const BigInteger = await util.getBigInteger(); + c1 = new BigInteger(c1); + c2 = new BigInteger(c2); + p = new BigInteger(p); + x = new BigInteger(x); + + const padded = c1.modExp(x, p).modInv(p).imul(c2).imod(p); + return emeDecode(padded.toUint8Array('be', p.byteLength()), randomPayload); +} + +/** + * Validate ElGamal parameters + * @param {Uint8Array} p - ElGamal prime + * @param {Uint8Array} g - ElGamal group generator + * @param {Uint8Array} y - ElGamal public key + * @param {Uint8Array} x - ElGamal private exponent + * @returns {Promise} Whether params are valid. + * @async + */ +async function validateParams$1(p, g, y, x) { + const BigInteger = await util.getBigInteger(); + p = new BigInteger(p); + g = new BigInteger(g); + y = new BigInteger(y); + + const one = new BigInteger(1); + // Check that 1 < g < p + if (g.lte(one) || g.gte(p)) { + return false; + } + + // Expect p-1 to be large + const pSize = new BigInteger(p.bitLength()); + const n1023 = new BigInteger(1023); + if (pSize.lt(n1023)) { + return false; + } + + /** + * g should have order p-1 + * Check that g ** (p-1) = 1 mod p + */ + if (!g.modExp(p.dec(), p).isOne()) { + return false; + } + + /** + * Since p-1 is not prime, g might have a smaller order that divides p-1 + * We want to make sure that the order is large enough to hinder a small subgroup attack + * + * We just check g**i != 1 for all i up to a threshold + */ + let res = g; + const i = new BigInteger(1); + const threshold = new BigInteger(2).leftShift(new BigInteger(17)); // we want order > threshold + while (i.lt(threshold)) { + res = res.mul(g).imod(p); + if (res.isOne()) { + return false; + } + i.iinc(); + } + + /** + * Re-derive public key y' = g ** x mod p + * Expect y == y' + * + * Blinded exponentiation computes g**{r(p-1) + x} to compare to y + */ + x = new BigInteger(x); + const two = new BigInteger(2); + const r = await getRandomBigInteger(two.leftShift(pSize.dec()), two.leftShift(pSize)); // draw r of same size as p-1 + const rqx = p.dec().imul(r).iadd(x); + if (!y.equal(g.modExp(rqx, p))) { + return false; + } + + return true; +} + +var elgamal = /*#__PURE__*/Object.freeze({ + __proto__: null, + encrypt: encrypt$2, + decrypt: decrypt$2, + validateParams: validateParams$1 +}); + +// OpenPGP.js - An OpenPGP implementation in javascript + +class OID { + constructor(oid) { + if (oid instanceof OID) { + this.oid = oid.oid; + } else if (util.isArray(oid) || + util.isUint8Array(oid)) { + oid = new Uint8Array(oid); + if (oid[0] === 0x06) { // DER encoded oid byte array + if (oid[1] !== oid.length - 2) { + throw new Error('Length mismatch in DER encoded oid'); + } + oid = oid.subarray(2); + } + this.oid = oid; + } else { + this.oid = ''; + } + } + + /** + * Method to read an OID object + * @param {Uint8Array} input - Where to read the OID from + * @returns {Number} Number of read bytes. + */ + read(input) { + if (input.length >= 1) { + const length = input[0]; + if (input.length >= 1 + length) { + this.oid = input.subarray(1, 1 + length); + return 1 + this.oid.length; + } + } + throw new Error('Invalid oid'); + } + + /** + * Serialize an OID object + * @returns {Uint8Array} Array with the serialized value the OID. + */ + write() { + return util.concatUint8Array([new Uint8Array([this.oid.length]), this.oid]); + } + + /** + * Serialize an OID object as a hex string + * @returns {string} String with the hex value of the OID. + */ + toHex() { + return util.uint8ArrayToHex(this.oid); + } + + /** + * If a known curve object identifier, return the canonical name of the curve + * @returns {string} String with the canonical name of the curve. + */ + getName() { + const hex = this.toHex(); + if (enums.curve[hex]) { + return enums.write(enums.curve, hex); + } else { + throw new Error('Unknown curve object identifier.'); + } + } +} + +// OpenPGP.js - An OpenPGP implementation in javascript + +function keyFromPrivate(indutnyCurve, priv) { + const keyPair = indutnyCurve.keyPair({ priv: priv }); + return keyPair; +} + +function keyFromPublic(indutnyCurve, pub) { + const keyPair = indutnyCurve.keyPair({ pub: pub }); + if (keyPair.validate().result !== true) { + throw new Error('Invalid elliptic public key'); + } + return keyPair; +} + +async function getIndutnyCurve(name) { + if (!defaultConfig.useIndutnyElliptic) { + throw new Error('This curve is only supported in the full build of OpenPGP.js'); + } + const { default: elliptic } = await Promise.resolve().then(function () { return elliptic$1; }); + return new elliptic.ec(name); +} + +// OpenPGP.js - An OpenPGP implementation in javascript + +const webCrypto$6 = util.getWebCrypto(); +const nodeCrypto$7 = util.getNodeCrypto(); + +const webCurves = { + 'p256': 'P-256', + 'p384': 'P-384', + 'p521': 'P-521' +}; +const knownCurves = nodeCrypto$7 ? nodeCrypto$7.getCurves() : []; +const nodeCurves = nodeCrypto$7 ? { + secp256k1: knownCurves.includes('secp256k1') ? 'secp256k1' : undefined, + p256: knownCurves.includes('prime256v1') ? 'prime256v1' : undefined, + p384: knownCurves.includes('secp384r1') ? 'secp384r1' : undefined, + p521: knownCurves.includes('secp521r1') ? 'secp521r1' : undefined, + ed25519: knownCurves.includes('ED25519') ? 'ED25519' : undefined, + curve25519: knownCurves.includes('X25519') ? 'X25519' : undefined, + brainpoolP256r1: knownCurves.includes('brainpoolP256r1') ? 'brainpoolP256r1' : undefined, + brainpoolP384r1: knownCurves.includes('brainpoolP384r1') ? 'brainpoolP384r1' : undefined, + brainpoolP512r1: knownCurves.includes('brainpoolP512r1') ? 'brainpoolP512r1' : undefined +} : {}; + +const curves = { + p256: { + oid: [0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07], + keyType: enums.publicKey.ecdsa, + hash: enums.hash.sha256, + cipher: enums.symmetric.aes128, + node: nodeCurves.p256, + web: webCurves.p256, + payloadSize: 32, + sharedSize: 256 + }, + p384: { + oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22], + keyType: enums.publicKey.ecdsa, + hash: enums.hash.sha384, + cipher: enums.symmetric.aes192, + node: nodeCurves.p384, + web: webCurves.p384, + payloadSize: 48, + sharedSize: 384 + }, + p521: { + oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23], + keyType: enums.publicKey.ecdsa, + hash: enums.hash.sha512, + cipher: enums.symmetric.aes256, + node: nodeCurves.p521, + web: webCurves.p521, + payloadSize: 66, + sharedSize: 528 + }, + secp256k1: { + oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x0A], + keyType: enums.publicKey.ecdsa, + hash: enums.hash.sha256, + cipher: enums.symmetric.aes128, + node: nodeCurves.secp256k1, + payloadSize: 32 + }, + ed25519: { + oid: [0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01], + keyType: enums.publicKey.eddsa, + hash: enums.hash.sha512, + node: false, // nodeCurves.ed25519 TODO + payloadSize: 32 + }, + curve25519: { + oid: [0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01], + keyType: enums.publicKey.ecdh, + hash: enums.hash.sha256, + cipher: enums.symmetric.aes128, + node: false, // nodeCurves.curve25519 TODO + payloadSize: 32 + }, + brainpoolP256r1: { + oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07], + keyType: enums.publicKey.ecdsa, + hash: enums.hash.sha256, + cipher: enums.symmetric.aes128, + node: nodeCurves.brainpoolP256r1, + payloadSize: 32 + }, + brainpoolP384r1: { + oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B], + keyType: enums.publicKey.ecdsa, + hash: enums.hash.sha384, + cipher: enums.symmetric.aes192, + node: nodeCurves.brainpoolP384r1, + payloadSize: 48 + }, + brainpoolP512r1: { + oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D], + keyType: enums.publicKey.ecdsa, + hash: enums.hash.sha512, + cipher: enums.symmetric.aes256, + node: nodeCurves.brainpoolP512r1, + payloadSize: 64 + } +}; + +class Curve { + constructor(oidOrName, params) { + try { + if (util.isArray(oidOrName) || + util.isUint8Array(oidOrName)) { + // by oid byte array + oidOrName = new OID(oidOrName); + } + if (oidOrName instanceof OID) { + // by curve OID + oidOrName = oidOrName.getName(); + } + // by curve name or oid string + this.name = enums.write(enums.curve, oidOrName); + } catch (err) { + throw new Error('Not valid curve'); + } + params = params || curves[this.name]; + + this.keyType = params.keyType; + + this.oid = params.oid; + this.hash = params.hash; + this.cipher = params.cipher; + this.node = params.node && curves[this.name]; + this.web = params.web && curves[this.name]; + this.payloadSize = params.payloadSize; + if (this.web && util.getWebCrypto()) { + this.type = 'web'; + } else if (this.node && util.getNodeCrypto()) { + this.type = 'node'; + } else if (this.name === 'curve25519') { + this.type = 'curve25519'; + } else if (this.name === 'ed25519') { + this.type = 'ed25519'; + } + } + + async genKeyPair() { + let keyPair; + switch (this.type) { + case 'web': + try { + return await webGenKeyPair(this.name); + } catch (err) { + util.printDebugError('Browser did not support generating ec key ' + err.message); + break; + } + case 'node': + return nodeGenKeyPair(this.name); + case 'curve25519': { + const privateKey = await getRandomBytes(32); + privateKey[0] = (privateKey[0] & 127) | 64; + privateKey[31] &= 248; + const secretKey = privateKey.slice().reverse(); + keyPair = naclFastLight.box.keyPair.fromSecretKey(secretKey); + const publicKey = util.concatUint8Array([new Uint8Array([0x40]), keyPair.publicKey]); + return { publicKey, privateKey }; + } + case 'ed25519': { + const privateKey = await getRandomBytes(32); + const keyPair = naclFastLight.sign.keyPair.fromSeed(privateKey); + const publicKey = util.concatUint8Array([new Uint8Array([0x40]), keyPair.publicKey]); + return { publicKey, privateKey }; + } + } + const indutnyCurve = await getIndutnyCurve(this.name); + keyPair = await indutnyCurve.genKeyPair({ + entropy: util.uint8ArrayToString(await getRandomBytes(32)) + }); + return { publicKey: new Uint8Array(keyPair.getPublic('array', false)), privateKey: keyPair.getPrivate().toArrayLike(Uint8Array) }; + } +} + +async function generate$1(curve) { + const BigInteger = await util.getBigInteger(); + + curve = new Curve(curve); + const keyPair = await curve.genKeyPair(); + const Q = new BigInteger(keyPair.publicKey).toUint8Array(); + const secret = new BigInteger(keyPair.privateKey).toUint8Array('be', curve.payloadSize); + return { + oid: curve.oid, + Q, + secret, + hash: curve.hash, + cipher: curve.cipher + }; +} + +/** + * Get preferred hash algo to use with the given curve + * @param {module:type/oid} oid - curve oid + * @returns {enums.hash} hash algorithm + */ +function getPreferredHashAlgo(oid) { + return curves[enums.write(enums.curve, oid.toHex())].hash; +} + +/** + * Validate ECDH and ECDSA parameters + * Not suitable for EdDSA (different secret key format) + * @param {module:enums.publicKey} algo - EC algorithm, to filter supported curves + * @param {module:type/oid} oid - EC object identifier + * @param {Uint8Array} Q - EC public point + * @param {Uint8Array} d - EC secret scalar + * @returns {Promise} Whether params are valid. + * @async + */ +async function validateStandardParams(algo, oid, Q, d) { + const supportedCurves = { + p256: true, + p384: true, + p521: true, + secp256k1: true, + curve25519: algo === enums.publicKey.ecdh, + brainpoolP256r1: true, + brainpoolP384r1: true, + brainpoolP512r1: true + }; + + // Check whether the given curve is supported + const curveName = oid.getName(); + if (!supportedCurves[curveName]) { + return false; + } + + if (curveName === 'curve25519') { + d = d.slice().reverse(); + // Re-derive public point Q' + const { publicKey } = naclFastLight.box.keyPair.fromSecretKey(d); + + Q = new Uint8Array(Q); + const dG = new Uint8Array([0x40, ...publicKey]); // Add public key prefix + if (!util.equalsUint8Array(dG, Q)) { + return false; + } + + return true; + } + + const curve = await getIndutnyCurve(curveName); + try { + // Parse Q and check that it is on the curve but not at infinity + Q = keyFromPublic(curve, Q).getPublic(); + } catch (validationErrors) { + return false; + } + + /** + * Re-derive public point Q' = dG from private key + * Expect Q == Q' + */ + const dG = keyFromPrivate(curve, d).getPublic(); + if (!dG.eq(Q)) { + return false; + } + + return true; +} + +////////////////////////// +// // +// Helper functions // +// // +////////////////////////// + + +async function webGenKeyPair(name) { + // Note: keys generated with ECDSA and ECDH are structurally equivalent + const webCryptoKey = await webCrypto$6.generateKey({ name: 'ECDSA', namedCurve: webCurves[name] }, true, ['sign', 'verify']); + + const privateKey = await webCrypto$6.exportKey('jwk', webCryptoKey.privateKey); + const publicKey = await webCrypto$6.exportKey('jwk', webCryptoKey.publicKey); + + return { + publicKey: jwkToRawPublic(publicKey), + privateKey: b64ToUint8Array(privateKey.d) + }; +} + +async function nodeGenKeyPair(name) { + // Note: ECDSA and ECDH key generation is structurally equivalent + const ecdh = nodeCrypto$7.createECDH(nodeCurves[name]); + await ecdh.generateKeys(); + return { + publicKey: new Uint8Array(ecdh.getPublicKey()), + privateKey: new Uint8Array(ecdh.getPrivateKey()) + }; +} + +////////////////////////// +// // +// Helper functions // +// // +////////////////////////// + +/** + * @param {JsonWebKey} jwk - key for conversion + * + * @returns {Uint8Array} Raw public key. + */ +function jwkToRawPublic(jwk) { + const bufX = b64ToUint8Array(jwk.x); + const bufY = b64ToUint8Array(jwk.y); + const publicKey = new Uint8Array(bufX.length + bufY.length + 1); + publicKey[0] = 0x04; + publicKey.set(bufX, 1); + publicKey.set(bufY, bufX.length + 1); + return publicKey; +} + +/** + * @param {Integer} payloadSize - ec payload size + * @param {String} name - curve name + * @param {Uint8Array} publicKey - public key + * + * @returns {JsonWebKey} Public key in jwk format. + */ +function rawPublicToJWK(payloadSize, name, publicKey) { + const len = payloadSize; + const bufX = publicKey.slice(1, len + 1); + const bufY = publicKey.slice(len + 1, len * 2 + 1); + // https://www.rfc-editor.org/rfc/rfc7518.txt + const jwk = { + kty: 'EC', + crv: name, + x: uint8ArrayToB64(bufX, true), + y: uint8ArrayToB64(bufY, true), + ext: true + }; + return jwk; +} + +/** + * @param {Integer} payloadSize - ec payload size + * @param {String} name - curve name + * @param {Uint8Array} publicKey - public key + * @param {Uint8Array} privateKey - private key + * + * @returns {JsonWebKey} Private key in jwk format. + */ +function privateToJWK$1(payloadSize, name, publicKey, privateKey) { + const jwk = rawPublicToJWK(payloadSize, name, publicKey); + jwk.d = uint8ArrayToB64(privateKey, true); + return jwk; +} + +const webCrypto$7 = util.getWebCrypto(); +const nodeCrypto$8 = util.getNodeCrypto(); + +/** + * Sign a message using the provided key + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {module:enums.hash} hashAlgo - Hash algorithm used to sign + * @param {Uint8Array} message - Message to sign + * @param {Uint8Array} publicKey - Public key + * @param {Uint8Array} privateKey - Private key used to sign the message + * @param {Uint8Array} hashed - The hashed message + * @returns {Promise<{ + * r: Uint8Array, + * s: Uint8Array + * }>} Signature of the message + * @async + */ +async function sign$1(oid, hashAlgo, message, publicKey, privateKey, hashed) { + const curve = new Curve(oid); + if (message && !util.isStream(message)) { + const keyPair = { publicKey, privateKey }; + switch (curve.type) { + case 'web': { + // If browser doesn't support a curve, we'll catch it + try { + // Need to await to make sure browser succeeds + return await webSign$1(curve, hashAlgo, message, keyPair); + } catch (err) { + // We do not fallback if the error is related to key integrity + // Unfortunaley Safari does not support p521 and throws a DataError when using it + // So we need to always fallback for that curve + if (curve.name !== 'p521' && (err.name === 'DataError' || err.name === 'OperationError')) { + throw err; + } + util.printDebugError('Browser did not support signing: ' + err.message); + } + break; + } + case 'node': { + const signature = await nodeSign$1(curve, hashAlgo, message, keyPair); + return { + r: signature.r.toArrayLike(Uint8Array), + s: signature.s.toArrayLike(Uint8Array) + }; + } + } + } + return ellipticSign(curve, hashed, privateKey); +} + +/** + * Verifies if a signature is valid for a message + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {module:enums.hash} hashAlgo - Hash algorithm used in the signature + * @param {{r: Uint8Array, + s: Uint8Array}} signature Signature to verify + * @param {Uint8Array} message - Message to verify + * @param {Uint8Array} publicKey - Public key used to verify the message + * @param {Uint8Array} hashed - The hashed message + * @returns {Boolean} + * @async + */ +async function verify$1(oid, hashAlgo, signature, message, publicKey, hashed) { + const curve = new Curve(oid); + if (message && !util.isStream(message)) { + switch (curve.type) { + case 'web': + try { + // Need to await to make sure browser succeeds + return await webVerify$1(curve, hashAlgo, signature, message, publicKey); + } catch (err) { + // We do not fallback if the error is related to key integrity + // Unfortunately Safari does not support p521 and throws a DataError when using it + // So we need to always fallback for that curve + if (curve.name !== 'p521' && (err.name === 'DataError' || err.name === 'OperationError')) { + throw err; + } + util.printDebugError('Browser did not support verifying: ' + err.message); + } + break; + case 'node': + return nodeVerify$1(curve, hashAlgo, signature, message, publicKey); + } + } + const digest = (typeof hashAlgo === 'undefined') ? message : hashed; + return ellipticVerify(curve, signature, digest, publicKey); +} + +/** + * Validate ECDSA parameters + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {Uint8Array} Q - ECDSA public point + * @param {Uint8Array} d - ECDSA secret scalar + * @returns {Promise} Whether params are valid. + * @async + */ +async function validateParams$2(oid, Q, d) { + const curve = new Curve(oid); + // Reject curves x25519 and ed25519 + if (curve.keyType !== enums.publicKey.ecdsa) { + return false; + } + + // To speed up the validation, we try to use node- or webcrypto when available + // and sign + verify a random message + switch (curve.type) { + case 'web': + case 'node': { + const message = await getRandomBytes(8); + const hashAlgo = enums.hash.sha256; + const hashed = await hash.digest(hashAlgo, message); + try { + const signature = await sign$1(oid, hashAlgo, message, Q, d, hashed); + return await verify$1(oid, hashAlgo, signature, message, Q, hashed); + } catch (err) { + return false; + } + } + default: + return validateStandardParams(enums.publicKey.ecdsa, oid, Q, d); + } +} + + +////////////////////////// +// // +// Helper functions // +// // +////////////////////////// + +async function ellipticSign(curve, hashed, privateKey) { + const indutnyCurve = await getIndutnyCurve(curve.name); + const key = keyFromPrivate(indutnyCurve, privateKey); + const signature = key.sign(hashed); + return { + r: signature.r.toArrayLike(Uint8Array), + s: signature.s.toArrayLike(Uint8Array) + }; +} + +async function ellipticVerify(curve, signature, digest, publicKey) { + const indutnyCurve = await getIndutnyCurve(curve.name); + const key = keyFromPublic(indutnyCurve, publicKey); + return key.verify(digest, signature); +} + +async function webSign$1(curve, hashAlgo, message, keyPair) { + const len = curve.payloadSize; + const jwk = privateToJWK$1(curve.payloadSize, webCurves[curve.name], keyPair.publicKey, keyPair.privateKey); + const key = await webCrypto$7.importKey( + 'jwk', + jwk, + { + 'name': 'ECDSA', + 'namedCurve': webCurves[curve.name], + 'hash': { name: enums.read(enums.webHash, curve.hash) } + }, + false, + ['sign'] + ); + + const signature = new Uint8Array(await webCrypto$7.sign( + { + 'name': 'ECDSA', + 'namedCurve': webCurves[curve.name], + 'hash': { name: enums.read(enums.webHash, hashAlgo) } + }, + key, + message + )); + + return { + r: signature.slice(0, len), + s: signature.slice(len, len << 1) + }; +} + +async function webVerify$1(curve, hashAlgo, { r, s }, message, publicKey) { + const jwk = rawPublicToJWK(curve.payloadSize, webCurves[curve.name], publicKey); + const key = await webCrypto$7.importKey( + 'jwk', + jwk, + { + 'name': 'ECDSA', + 'namedCurve': webCurves[curve.name], + 'hash': { name: enums.read(enums.webHash, curve.hash) } + }, + false, + ['verify'] + ); + + const signature = util.concatUint8Array([r, s]).buffer; + + return webCrypto$7.verify( + { + 'name': 'ECDSA', + 'namedCurve': webCurves[curve.name], + 'hash': { name: enums.read(enums.webHash, hashAlgo) } + }, + key, + signature, + message + ); +} + +async function nodeSign$1(curve, hashAlgo, message, keyPair) { + const sign = nodeCrypto$8.createSign(enums.read(enums.hash, hashAlgo)); + sign.write(message); + sign.end(); + const key = ECPrivateKey.encode({ + version: 1, + parameters: curve.oid, + privateKey: Array.from(keyPair.privateKey), + publicKey: { unused: 0, data: Array.from(keyPair.publicKey) } + }, 'pem', { + label: 'EC PRIVATE KEY' + }); + + return ECDSASignature.decode(sign.sign(key), 'der'); +} + +async function nodeVerify$1(curve, hashAlgo, { r, s }, message, publicKey) { + const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); + + const verify = nodeCrypto$8.createVerify(enums.read(enums.hash, hashAlgo)); + verify.write(message); + verify.end(); + const key = SubjectPublicKeyInfo.encode({ + algorithm: { + algorithm: [1, 2, 840, 10045, 2, 1], + parameters: curve.oid + }, + subjectPublicKey: { unused: 0, data: Array.from(publicKey) } + }, 'pem', { + label: 'PUBLIC KEY' + }); + const signature = ECDSASignature.encode({ + r: new BN(r), s: new BN(s) + }, 'der'); + + try { + return verify.verify(key, signature); + } catch (err) { + return false; + } +} + +// Originally written by Owen Smith https://github.com/omsmith +// Adapted on Feb 2018 from https://github.com/Brightspace/node-jwk-to-pem/ + +/* eslint-disable no-invalid-this */ + +const asn1$1 = nodeCrypto$8 ? asn1__default['default'] : undefined; + +const ECDSASignature = nodeCrypto$8 ? + asn1$1.define('ECDSASignature', function() { + this.seq().obj( + this.key('r').int(), + this.key('s').int() + ); + }) : undefined; + +const ECPrivateKey = nodeCrypto$8 ? + asn1$1.define('ECPrivateKey', function() { + this.seq().obj( + this.key('version').int(), + this.key('privateKey').octstr(), + this.key('parameters').explicit(0).optional().any(), + this.key('publicKey').explicit(1).optional().bitstr() + ); + }) : undefined; + +const AlgorithmIdentifier = nodeCrypto$8 ? + asn1$1.define('AlgorithmIdentifier', function() { + this.seq().obj( + this.key('algorithm').objid(), + this.key('parameters').optional().any() + ); + }) : undefined; + +const SubjectPublicKeyInfo = nodeCrypto$8 ? + asn1$1.define('SubjectPublicKeyInfo', function() { + this.seq().obj( + this.key('algorithm').use(AlgorithmIdentifier), + this.key('subjectPublicKey').bitstr() + ); + }) : undefined; + +var ecdsa = /*#__PURE__*/Object.freeze({ + __proto__: null, + sign: sign$1, + verify: verify$1, + validateParams: validateParams$2 +}); + +// OpenPGP.js - An OpenPGP implementation in javascript + +naclFastLight.hash = bytes => new Uint8Array(_512().update(bytes).digest()); + +/** + * Sign a message using the provided key + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {module:enums.hash} hashAlgo - Hash algorithm used to sign (must be sha256 or stronger) + * @param {Uint8Array} message - Message to sign + * @param {Uint8Array} publicKey - Public key + * @param {Uint8Array} privateKey - Private key used to sign the message + * @param {Uint8Array} hashed - The hashed message + * @returns {Promise<{ + * r: Uint8Array, + * s: Uint8Array + * }>} Signature of the message + * @async + */ +async function sign$2(oid, hashAlgo, message, publicKey, privateKey, hashed) { + if (hash.getHashByteLength(hashAlgo) < hash.getHashByteLength(enums.hash.sha256)) { + // see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2 + throw new Error('Hash algorithm too weak: sha256 or stronger is required for EdDSA.'); + } + const secretKey = util.concatUint8Array([privateKey, publicKey.subarray(1)]); + const signature = naclFastLight.sign.detached(hashed, secretKey); + // EdDSA signature params are returned in little-endian format + return { + r: signature.subarray(0, 32), + s: signature.subarray(32) + }; +} + +/** + * Verifies if a signature is valid for a message + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {module:enums.hash} hashAlgo - Hash algorithm used in the signature + * @param {{r: Uint8Array, + s: Uint8Array}} signature Signature to verify the message + * @param {Uint8Array} m - Message to verify + * @param {Uint8Array} publicKey - Public key used to verify the message + * @param {Uint8Array} hashed - The hashed message + * @returns {Boolean} + * @async + */ +async function verify$2(oid, hashAlgo, { r, s }, m, publicKey, hashed) { + const signature = util.concatUint8Array([r, s]); + return naclFastLight.sign.detached.verify(hashed, signature, publicKey.subarray(1)); +} +/** + * Validate EdDSA parameters + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {Uint8Array} Q - EdDSA public point + * @param {Uint8Array} k - EdDSA secret seed + * @returns {Promise} Whether params are valid. + * @async + */ +async function validateParams$3(oid, Q, k) { + // Check whether the given curve is supported + if (oid.getName() !== 'ed25519') { + return false; + } + + /** + * Derive public point Q' = dG from private key + * and expect Q == Q' + */ + const { publicKey } = naclFastLight.sign.keyPair.fromSeed(k); + const dG = new Uint8Array([0x40, ...publicKey]); // Add public key prefix + return util.equalsUint8Array(Q, dG); +} + +var eddsa = /*#__PURE__*/Object.freeze({ + __proto__: null, + sign: sign$2, + verify: verify$2, + validateParams: validateParams$3 +}); + +// OpenPGP.js - An OpenPGP implementation in javascript + +/** + * AES key wrap + * @function + * @param {Uint8Array} key + * @param {Uint8Array} data + * @returns {Uint8Array} + */ +function wrap(key, data) { + const aes = new cipher['aes' + (key.length * 8)](key); + const IV = new Uint32Array([0xA6A6A6A6, 0xA6A6A6A6]); + const P = unpack(data); + let A = IV; + const R = P; + const n = P.length / 2; + const t = new Uint32Array([0, 0]); + let B = new Uint32Array(4); + for (let j = 0; j <= 5; ++j) { + for (let i = 0; i < n; ++i) { + t[1] = n * j + (1 + i); + // B = A + B[0] = A[0]; + B[1] = A[1]; + // B = A || R[i] + B[2] = R[2 * i]; + B[3] = R[2 * i + 1]; + // B = AES(K, B) + B = unpack(aes.encrypt(pack(B))); + // A = MSB(64, B) ^ t + A = B.subarray(0, 2); + A[0] ^= t[0]; + A[1] ^= t[1]; + // R[i] = LSB(64, B) + R[2 * i] = B[2]; + R[2 * i + 1] = B[3]; + } + } + return pack(A, R); +} + +/** + * AES key unwrap + * @function + * @param {String} key + * @param {String} data + * @returns {Uint8Array} + * @throws {Error} + */ +function unwrap(key, data) { + const aes = new cipher['aes' + (key.length * 8)](key); + const IV = new Uint32Array([0xA6A6A6A6, 0xA6A6A6A6]); + const C = unpack(data); + let A = C.subarray(0, 2); + const R = C.subarray(2); + const n = C.length / 2 - 1; + const t = new Uint32Array([0, 0]); + let B = new Uint32Array(4); + for (let j = 5; j >= 0; --j) { + for (let i = n - 1; i >= 0; --i) { + t[1] = n * j + (i + 1); + // B = A ^ t + B[0] = A[0] ^ t[0]; + B[1] = A[1] ^ t[1]; + // B = (A ^ t) || R[i] + B[2] = R[2 * i]; + B[3] = R[2 * i + 1]; + // B = AES-1(B) + B = unpack(aes.decrypt(pack(B))); + // A = MSB(64, B) + A = B.subarray(0, 2); + // R[i] = LSB(64, B) + R[2 * i] = B[2]; + R[2 * i + 1] = B[3]; + } + } + if (A[0] === IV[0] && A[1] === IV[1]) { + return pack(R); + } + throw new Error('Key Data Integrity failed'); +} + +function createArrayBuffer(data) { + if (util.isString(data)) { + const { length } = data; + const buffer = new ArrayBuffer(length); + const view = new Uint8Array(buffer); + for (let j = 0; j < length; ++j) { + view[j] = data.charCodeAt(j); + } + return buffer; + } + return new Uint8Array(data).buffer; +} + +function unpack(data) { + const { length } = data; + const buffer = createArrayBuffer(data); + const view = new DataView(buffer); + const arr = new Uint32Array(length / 4); + for (let i = 0; i < length / 4; ++i) { + arr[i] = view.getUint32(4 * i); + } + return arr; +} + +function pack() { + let length = 0; + for (let k = 0; k < arguments.length; ++k) { + length += 4 * arguments[k].length; + } + const buffer = new ArrayBuffer(length); + const view = new DataView(buffer); + let offset = 0; + for (let i = 0; i < arguments.length; ++i) { + for (let j = 0; j < arguments[i].length; ++j) { + view.setUint32(offset + 4 * j, arguments[i][j]); + } + offset += 4 * arguments[i].length; + } + return new Uint8Array(buffer); +} + +var aesKW = /*#__PURE__*/Object.freeze({ + __proto__: null, + wrap: wrap, + unwrap: unwrap +}); + +// OpenPGP.js - An OpenPGP implementation in javascript + +/** + * @fileoverview Functions to add and remove PKCS5 padding + * @see PublicKeyEncryptedSessionKeyPacket + * @module crypto/pkcs5 + * @private + */ + +/** + * Add pkcs5 padding to a message + * @param {Uint8Array} message - message to pad + * @returns {Uint8Array} Padded message. + */ +function encode$1(message) { + const c = 8 - (message.length % 8); + const padded = new Uint8Array(message.length + c).fill(c); + padded.set(message); + return padded; +} + +/** + * Remove pkcs5 padding from a message + * @param {Uint8Array} message - message to remove padding from + * @returns {Uint8Array} Message without padding. + */ +function decode$1(message) { + const len = message.length; + if (len > 0) { + const c = message[len - 1]; + if (c >= 1) { + const provided = message.subarray(len - c); + const computed = new Uint8Array(c).fill(c); + if (util.equalsUint8Array(provided, computed)) { + return message.subarray(0, len - c); + } + } + } + throw new Error('Invalid padding'); +} + +var pkcs5 = /*#__PURE__*/Object.freeze({ + __proto__: null, + encode: encode$1, + decode: decode$1 +}); + +// OpenPGP.js - An OpenPGP implementation in javascript + +class ECDHSymmetricKey { + constructor(data) { + if (typeof data === 'undefined') { + data = new Uint8Array([]); + } else if (util.isString(data)) { + data = util.stringToUint8Array(data); + } else { + data = new Uint8Array(data); + } + this.data = data; + } + + /** + * Read an ECDHSymmetricKey from an Uint8Array + * @param {Uint8Array} input - Where to read the encoded symmetric key from + * @returns {Number} Number of read bytes. + */ + read(input) { + if (input.length >= 1) { + const length = input[0]; + if (input.length >= 1 + length) { + this.data = input.subarray(1, 1 + length); + return 1 + this.data.length; + } + } + throw new Error('Invalid symmetric key'); + } + + /** + * Write an ECDHSymmetricKey as an Uint8Array + * @returns {Uint8Array} An array containing the value + */ + write() { + return util.concatUint8Array([new Uint8Array([this.data.length]), this.data]); + } +} + +// OpenPGP.js - An OpenPGP implementation in javascript +// Copyright (C) 2015-2016 Decentral +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * Implementation of type KDF parameters + * + * {@link https://tools.ietf.org/html/rfc6637#section-7|RFC 6637 7}: + * A key derivation function (KDF) is necessary to implement the EC + * encryption. The Concatenation Key Derivation Function (Approved + * Alternative 1) [NIST-SP800-56A] with the KDF hash function that is + * SHA2-256 [FIPS-180-3] or stronger is REQUIRED. + * @module type/kdf_params + * @private + */ + +class KDFParams { + /** + * @param {enums.hash} hash - Hash algorithm + * @param {enums.symmetric} cipher - Symmetric algorithm + */ + constructor(data) { + if (data) { + const { hash, cipher } = data; + this.hash = hash; + this.cipher = cipher; + } else { + this.hash = null; + this.cipher = null; + } + } + + /** + * Read KDFParams from an Uint8Array + * @param {Uint8Array} input - Where to read the KDFParams from + * @returns {Number} Number of read bytes. + */ + read(input) { + if (input.length < 4 || input[0] !== 3 || input[1] !== 1) { + throw new Error('Cannot read KDFParams'); + } + this.hash = input[2]; + this.cipher = input[3]; + return 4; + } + + /** + * Write KDFParams to an Uint8Array + * @returns {Uint8Array} Array with the KDFParams value + */ + write() { + return new Uint8Array([3, 1, this.hash, this.cipher]); + } +} + +// GPG4Browsers - An OpenPGP implementation in javascript + +/** + * Encrypts data using specified algorithm and public key parameters. + * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} for public key algorithms. + * @param {module:enums.publicKey} algo - Public key algorithm + * @param {Object} publicParams - Algorithm-specific public key parameters + * @param {Uint8Array} data - Data to be encrypted + * @param {Uint8Array} fingerprint - Recipient fingerprint + * @returns {Promise} Encrypted session key parameters. + * @async + */ +async function publicKeyEncrypt(algo, publicParams, data, fingerprint) { + switch (algo) { + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaEncryptSign: { + const { n, e } = publicParams; + const c = await publicKey.rsa.encrypt(data, n, e); + return { c }; + } + case enums.publicKey.elgamal: { + const { p, g, y } = publicParams; + return publicKey.elgamal.encrypt(data, p, g, y); + } + case enums.publicKey.ecdh: { + const { oid, Q, kdfParams } = publicParams; + const { publicKey: V, wrappedKey: C } = await publicKey.elliptic.ecdh.encrypt( + oid, kdfParams, data, Q, fingerprint); + return { V, C: new ECDHSymmetricKey(C) }; + } + default: + return []; + } +} + +/** + * Decrypts data using specified algorithm and private key parameters. + * See {@link https://tools.ietf.org/html/rfc4880#section-5.5.3|RFC 4880 5.5.3} + * @param {module:enums.publicKey} algo - Public key algorithm + * @param {Object} publicKeyParams - Algorithm-specific public key parameters + * @param {Object} privateKeyParams - Algorithm-specific private key parameters + * @param {Object} sessionKeyParams - Encrypted session key parameters + * @param {Uint8Array} fingerprint - Recipient fingerprint + * @param {Uint8Array} [randomPayload] - Data to return on decryption error, instead of throwing + * (needed for constant-time processing in RSA and ElGamal) + * @returns {Promise} Decrypted data. + * @throws {Error} on sensitive decryption error, unless `randomPayload` is given + * @async + */ +async function publicKeyDecrypt(algo, publicKeyParams, privateKeyParams, sessionKeyParams, fingerprint, randomPayload) { + switch (algo) { + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaEncrypt: { + const { c } = sessionKeyParams; + const { n, e } = publicKeyParams; + const { d, p, q, u } = privateKeyParams; + return publicKey.rsa.decrypt(c, n, e, d, p, q, u, randomPayload); + } + case enums.publicKey.elgamal: { + const { c1, c2 } = sessionKeyParams; + const p = publicKeyParams.p; + const x = privateKeyParams.x; + return publicKey.elgamal.decrypt(c1, c2, p, x, randomPayload); + } + case enums.publicKey.ecdh: { + const { oid, Q, kdfParams } = publicKeyParams; + const { d } = privateKeyParams; + const { V, C } = sessionKeyParams; + return publicKey.elliptic.ecdh.decrypt( + oid, kdfParams, V, C.data, Q, d, fingerprint); + } + default: + throw new Error('Invalid public key encryption algorithm.'); + } +} + +/** + * Parse public key material in binary form to get the key parameters + * @param {module:enums.publicKey} algo - The key algorithm + * @param {Uint8Array} bytes - The key material to parse + * @returns {{ read: Number, publicParams: Object }} Number of read bytes plus key parameters referenced by name. + */ +function parsePublicKeyParams(algo, bytes) { + let read = 0; + switch (algo) { + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaSign: { + const n = util.readMPI(bytes.subarray(read)); read += n.length + 2; + const e = util.readMPI(bytes.subarray(read)); read += e.length + 2; + return { read, publicParams: { n, e } }; + } + case enums.publicKey.dsa: { + const p = util.readMPI(bytes.subarray(read)); read += p.length + 2; + const q = util.readMPI(bytes.subarray(read)); read += q.length + 2; + const g = util.readMPI(bytes.subarray(read)); read += g.length + 2; + const y = util.readMPI(bytes.subarray(read)); read += y.length + 2; + return { read, publicParams: { p, q, g, y } }; + } + case enums.publicKey.elgamal: { + const p = util.readMPI(bytes.subarray(read)); read += p.length + 2; + const g = util.readMPI(bytes.subarray(read)); read += g.length + 2; + const y = util.readMPI(bytes.subarray(read)); read += y.length + 2; + return { read, publicParams: { p, g, y } }; + } + case enums.publicKey.ecdsa: { + const oid = new OID(); read += oid.read(bytes); + const Q = util.readMPI(bytes.subarray(read)); read += Q.length + 2; + return { read: read, publicParams: { oid, Q } }; + } + case enums.publicKey.eddsa: { + const oid = new OID(); read += oid.read(bytes); + let Q = util.readMPI(bytes.subarray(read)); read += Q.length + 2; + Q = util.leftPad(Q, 33); + return { read: read, publicParams: { oid, Q } }; + } + case enums.publicKey.ecdh: { + const oid = new OID(); read += oid.read(bytes); + const Q = util.readMPI(bytes.subarray(read)); read += Q.length + 2; + const kdfParams = new KDFParams(); read += kdfParams.read(bytes.subarray(read)); + return { read: read, publicParams: { oid, Q, kdfParams } }; + } + default: + throw new Error('Invalid public key encryption algorithm.'); + } +} + +/** + * Parse private key material in binary form to get the key parameters + * @param {module:enums.publicKey} algo - The key algorithm + * @param {Uint8Array} bytes - The key material to parse + * @param {Object} publicParams - (ECC only) public params, needed to format some private params + * @returns {{ read: Number, privateParams: Object }} Number of read bytes plus the key parameters referenced by name. + */ +function parsePrivateKeyParams(algo, bytes, publicParams) { + let read = 0; + switch (algo) { + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaSign: { + const d = util.readMPI(bytes.subarray(read)); read += d.length + 2; + const p = util.readMPI(bytes.subarray(read)); read += p.length + 2; + const q = util.readMPI(bytes.subarray(read)); read += q.length + 2; + const u = util.readMPI(bytes.subarray(read)); read += u.length + 2; + return { read, privateParams: { d, p, q, u } }; + } + case enums.publicKey.dsa: + case enums.publicKey.elgamal: { + const x = util.readMPI(bytes.subarray(read)); read += x.length + 2; + return { read, privateParams: { x } }; + } + case enums.publicKey.ecdsa: + case enums.publicKey.ecdh: { + const curve = new Curve(publicParams.oid); + let d = util.readMPI(bytes.subarray(read)); read += d.length + 2; + d = util.leftPad(d, curve.payloadSize); + return { read, privateParams: { d } }; + } + case enums.publicKey.eddsa: { + let seed = util.readMPI(bytes.subarray(read)); read += seed.length + 2; + seed = util.leftPad(seed, 32); + return { read, privateParams: { seed } }; + } + default: + throw new Error('Invalid public key encryption algorithm.'); + } +} + +/** Returns the types comprising the encrypted session key of an algorithm + * @param {module:enums.publicKey} algo - The key algorithm + * @param {Uint8Array} bytes - The key material to parse + * @returns {Object} The session key parameters referenced by name. + */ +function parseEncSessionKeyParams(algo, bytes) { + let read = 0; + switch (algo) { + // Algorithm-Specific Fields for RSA encrypted session keys: + // - MPI of RSA encrypted value m**e mod n. + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaEncryptSign: { + const c = util.readMPI(bytes.subarray(read)); + return { c }; + } + + // Algorithm-Specific Fields for Elgamal encrypted session keys: + // - MPI of Elgamal value g**k mod p + // - MPI of Elgamal value m * y**k mod p + case enums.publicKey.elgamal: { + const c1 = util.readMPI(bytes.subarray(read)); read += c1.length + 2; + const c2 = util.readMPI(bytes.subarray(read)); + return { c1, c2 }; + } + // Algorithm-Specific Fields for ECDH encrypted session keys: + // - MPI containing the ephemeral key used to establish the shared secret + // - ECDH Symmetric Key + case enums.publicKey.ecdh: { + const V = util.readMPI(bytes.subarray(read)); read += V.length + 2; + const C = new ECDHSymmetricKey(); C.read(bytes.subarray(read)); + return { V, C }; + } + default: + throw new Error('Invalid public key encryption algorithm.'); + } +} + +/** + * Convert params to MPI and serializes them in the proper order + * @param {module:enums.publicKey} algo - The public key algorithm + * @param {Object} params - The key parameters indexed by name + * @returns {Uint8Array} The array containing the MPIs. + */ +function serializeParams(algo, params) { + const orderedParams = Object.keys(params).map(name => { + const param = params[name]; + return util.isUint8Array(param) ? util.uint8ArrayToMPI(param) : param.write(); + }); + return util.concatUint8Array(orderedParams); +} + +/** + * Generate algorithm-specific key parameters + * @param {module:enums.publicKey} algo - The public key algorithm + * @param {Integer} bits - Bit length for RSA keys + * @param {module:type/oid} oid - Object identifier for ECC keys + * @returns {Promise<{ publicParams: {Object}, privateParams: {Object} }>} The parameters referenced by name. + * @async + */ +function generateParams(algo, bits, oid) { + switch (algo) { + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaSign: { + return publicKey.rsa.generate(bits, 65537).then(({ n, e, d, p, q, u }) => ({ + privateParams: { d, p, q, u }, + publicParams: { n, e } + })); + } + case enums.publicKey.ecdsa: + return publicKey.elliptic.generate(oid).then(({ oid, Q, secret }) => ({ + privateParams: { d: secret }, + publicParams: { oid: new OID(oid), Q } + })); + case enums.publicKey.eddsa: + return publicKey.elliptic.generate(oid).then(({ oid, Q, secret }) => ({ + privateParams: { seed: secret }, + publicParams: { oid: new OID(oid), Q } + })); + case enums.publicKey.ecdh: + return publicKey.elliptic.generate(oid).then(({ oid, Q, secret, hash, cipher }) => ({ + privateParams: { d: secret }, + publicParams: { + oid: new OID(oid), + Q, + kdfParams: new KDFParams({ hash, cipher }) + } + })); + case enums.publicKey.dsa: + case enums.publicKey.elgamal: + throw new Error('Unsupported algorithm for key generation.'); + default: + throw new Error('Invalid public key algorithm.'); + } +} + +/** + * Validate algorithm-specific key parameters + * @param {module:enums.publicKey} algo - The public key algorithm + * @param {Object} publicParams - Algorithm-specific public key parameters + * @param {Object} privateParams - Algorithm-specific private key parameters + * @returns {Promise} Whether the parameters are valid. + * @async + */ +async function validateParams$4(algo, publicParams, privateParams) { + if (!publicParams || !privateParams) { + throw new Error('Missing key parameters'); + } + switch (algo) { + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaSign: { + const { n, e } = publicParams; + const { d, p, q, u } = privateParams; + return publicKey.rsa.validateParams(n, e, d, p, q, u); + } + case enums.publicKey.dsa: { + const { p, q, g, y } = publicParams; + const { x } = privateParams; + return publicKey.dsa.validateParams(p, q, g, y, x); + } + case enums.publicKey.elgamal: { + const { p, g, y } = publicParams; + const { x } = privateParams; + return publicKey.elgamal.validateParams(p, g, y, x); + } + case enums.publicKey.ecdsa: + case enums.publicKey.ecdh: { + const algoModule = publicKey.elliptic[enums.read(enums.publicKey, algo)]; + const { oid, Q } = publicParams; + const { d } = privateParams; + return algoModule.validateParams(oid, Q, d); + } + case enums.publicKey.eddsa: { + const { oid, Q } = publicParams; + const { seed } = privateParams; + return publicKey.elliptic.eddsa.validateParams(oid, Q, seed); + } + default: + throw new Error('Invalid public key algorithm.'); + } +} + +/** + * Generates a random byte prefix for the specified algorithm + * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. + * @param {module:enums.symmetric} algo - Symmetric encryption algorithm + * @returns {Promise} Random bytes with length equal to the block size of the cipher, plus the last two bytes repeated. + * @async + */ +async function getPrefixRandom(algo) { + const { blockSize } = getCipher(algo); + const prefixrandom = await getRandomBytes(blockSize); + const repeat = new Uint8Array([prefixrandom[prefixrandom.length - 2], prefixrandom[prefixrandom.length - 1]]); + return util.concat([prefixrandom, repeat]); +} + +/** + * Generating a session key for the specified symmetric algorithm + * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. + * @param {module:enums.symmetric} algo - Symmetric encryption algorithm + * @returns {Promise} Random bytes as a string to be used as a key. + * @async + */ +function generateSessionKey(algo) { + const { keySize } = getCipher(algo); + return getRandomBytes(keySize); +} + +/** + * Get implementation of the given AEAD mode + * @param {enums.aead} algo + * @returns {Object} + * @throws {Error} on invalid algo + */ +function getAEADMode(algo) { + const algoName = enums.read(enums.aead, algo); + return mode[algoName]; +} + +/** + * Get implementation of the given cipher + * @param {enums.symmetric} algo + * @returns {Object} + * @throws {Error} on invalid algo + */ +function getCipher(algo) { + const algoName = enums.read(enums.symmetric, algo); + return cipher[algoName]; +} + +var crypto$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + publicKeyEncrypt: publicKeyEncrypt, + publicKeyDecrypt: publicKeyDecrypt, + parsePublicKeyParams: parsePublicKeyParams, + parsePrivateKeyParams: parsePrivateKeyParams, + parseEncSessionKeyParams: parseEncSessionKeyParams, + serializeParams: serializeParams, + generateParams: generateParams, + validateParams: validateParams$4, + getPrefixRandom: getPrefixRandom, + generateSessionKey: generateSessionKey, + getAEADMode: getAEADMode, + getCipher: getCipher +}); + +// OpenPGP.js - An OpenPGP implementation in javascript + +const webCrypto$8 = util.getWebCrypto(); +const nodeCrypto$9 = util.getNodeCrypto(); + +/** + * Validate ECDH parameters + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {Uint8Array} Q - ECDH public point + * @param {Uint8Array} d - ECDH secret scalar + * @returns {Promise} Whether params are valid. + * @async + */ +async function validateParams$5(oid, Q, d) { + return validateStandardParams(enums.publicKey.ecdh, oid, Q, d); +} + +// Build Param for ECDH algorithm (RFC 6637) +function buildEcdhParam(public_algo, oid, kdfParams, fingerprint) { + return util.concatUint8Array([ + oid.write(), + new Uint8Array([public_algo]), + kdfParams.write(), + util.stringToUint8Array('Anonymous Sender '), + fingerprint.subarray(0, 20) + ]); +} + +// Key Derivation Function (RFC 6637) +async function kdf(hashAlgo, X, length, param, stripLeading = false, stripTrailing = false) { + // Note: X is little endian for Curve25519, big-endian for all others. + // This is not ideal, but the RFC's are unclear + // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B + let i; + if (stripLeading) { + // Work around old go crypto bug + for (i = 0; i < X.length && X[i] === 0; i++); + X = X.subarray(i); + } + if (stripTrailing) { + // Work around old OpenPGP.js bug + for (i = X.length - 1; i >= 0 && X[i] === 0; i--); + X = X.subarray(0, i + 1); + } + const digest = await hash.digest(hashAlgo, util.concatUint8Array([ + new Uint8Array([0, 0, 0, 1]), + X, + param + ])); + return digest.subarray(0, length); +} + +/** + * Generate ECDHE ephemeral key and secret from public key + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} Q - Recipient public key + * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ +async function genPublicEphemeralKey(curve, Q) { + switch (curve.type) { + case 'curve25519': { + const d = await getRandomBytes(32); + const { secretKey, sharedKey } = await genPrivateEphemeralKey(curve, Q, null, d); + let { publicKey } = naclFastLight.box.keyPair.fromSecretKey(secretKey); + publicKey = util.concatUint8Array([new Uint8Array([0x40]), publicKey]); + return { publicKey, sharedKey }; // Note: sharedKey is little-endian here, unlike below + } + case 'web': + if (curve.web && util.getWebCrypto()) { + try { + return await webPublicEphemeralKey(curve, Q); + } catch (err) { + util.printDebugError(err); + } + } + break; + case 'node': + return nodePublicEphemeralKey(curve, Q); + } + return ellipticPublicEphemeralKey(curve, Q); +} + +/** + * Encrypt and wrap a session key + * + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {module:type/kdf_params} kdfParams - KDF params including cipher and algorithm to use + * @param {Uint8Array} data - Unpadded session key data + * @param {Uint8Array} Q - Recipient public key + * @param {Uint8Array} fingerprint - Recipient fingerprint + * @returns {Promise<{publicKey: Uint8Array, wrappedKey: Uint8Array}>} + * @async + */ +async function encrypt$3(oid, kdfParams, data, Q, fingerprint) { + const m = encode$1(data); + + const curve = new Curve(oid); + const { publicKey, sharedKey } = await genPublicEphemeralKey(curve, Q); + const param = buildEcdhParam(enums.publicKey.ecdh, oid, kdfParams, fingerprint); + const { keySize } = getCipher(kdfParams.cipher); + const Z = await kdf(kdfParams.hash, sharedKey, keySize, param); + const wrappedKey = wrap(Z, m); + return { publicKey, wrappedKey }; +} + +/** + * Generate ECDHE secret from private key and public part of ephemeral key + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} V - Public part of ephemeral key + * @param {Uint8Array} Q - Recipient public key + * @param {Uint8Array} d - Recipient private key + * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ +async function genPrivateEphemeralKey(curve, V, Q, d) { + if (d.length !== curve.payloadSize) { + const privateKey = new Uint8Array(curve.payloadSize); + privateKey.set(d, curve.payloadSize - d.length); + d = privateKey; + } + switch (curve.type) { + case 'curve25519': { + const secretKey = d.slice().reverse(); + const sharedKey = naclFastLight.scalarMult(secretKey, V.subarray(1)); + return { secretKey, sharedKey }; // Note: sharedKey is little-endian here, unlike below + } + case 'web': + if (curve.web && util.getWebCrypto()) { + try { + return await webPrivateEphemeralKey(curve, V, Q, d); + } catch (err) { + util.printDebugError(err); + } + } + break; + case 'node': + return nodePrivateEphemeralKey(curve, V, d); + } + return ellipticPrivateEphemeralKey(curve, V, d); +} + +/** + * Decrypt and unwrap the value derived from session key + * + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {module:type/kdf_params} kdfParams - KDF params including cipher and algorithm to use + * @param {Uint8Array} V - Public part of ephemeral key + * @param {Uint8Array} C - Encrypted and wrapped value derived from session key + * @param {Uint8Array} Q - Recipient public key + * @param {Uint8Array} d - Recipient private key + * @param {Uint8Array} fingerprint - Recipient fingerprint + * @returns {Promise} Value derived from session key. + * @async + */ +async function decrypt$3(oid, kdfParams, V, C, Q, d, fingerprint) { + const curve = new Curve(oid); + const { sharedKey } = await genPrivateEphemeralKey(curve, V, Q, d); + const param = buildEcdhParam(enums.publicKey.ecdh, oid, kdfParams, fingerprint); + const { keySize } = getCipher(kdfParams.cipher); + let err; + for (let i = 0; i < 3; i++) { + try { + // Work around old go crypto bug and old OpenPGP.js bug, respectively. + const Z = await kdf(kdfParams.hash, sharedKey, keySize, param, i === 1, i === 2); + return decode$1(unwrap(Z, C)); + } catch (e) { + err = e; + } + } + throw err; +} + +/** + * Generate ECDHE secret from private key and public part of ephemeral key using webCrypto + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} V - Public part of ephemeral key + * @param {Uint8Array} Q - Recipient public key + * @param {Uint8Array} d - Recipient private key + * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ +async function webPrivateEphemeralKey(curve, V, Q, d) { + const recipient = privateToJWK$1(curve.payloadSize, curve.web.web, Q, d); + let privateKey = webCrypto$8.importKey( + 'jwk', + recipient, + { + name: 'ECDH', + namedCurve: curve.web.web + }, + true, + ['deriveKey', 'deriveBits'] + ); + const jwk = rawPublicToJWK(curve.payloadSize, curve.web.web, V); + let sender = webCrypto$8.importKey( + 'jwk', + jwk, + { + name: 'ECDH', + namedCurve: curve.web.web + }, + true, + [] + ); + [privateKey, sender] = await Promise.all([privateKey, sender]); + let S = webCrypto$8.deriveBits( + { + name: 'ECDH', + namedCurve: curve.web.web, + public: sender + }, + privateKey, + curve.web.sharedSize + ); + let secret = webCrypto$8.exportKey( + 'jwk', + privateKey + ); + [S, secret] = await Promise.all([S, secret]); + const sharedKey = new Uint8Array(S); + const secretKey = b64ToUint8Array(secret.d); + return { secretKey, sharedKey }; +} + +/** + * Generate ECDHE ephemeral key and secret from public key using webCrypto + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} Q - Recipient public key + * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ +async function webPublicEphemeralKey(curve, Q) { + const jwk = rawPublicToJWK(curve.payloadSize, curve.web.web, Q); + let keyPair = webCrypto$8.generateKey( + { + name: 'ECDH', + namedCurve: curve.web.web + }, + true, + ['deriveKey', 'deriveBits'] + ); + let recipient = webCrypto$8.importKey( + 'jwk', + jwk, + { + name: 'ECDH', + namedCurve: curve.web.web + }, + false, + [] + ); + [keyPair, recipient] = await Promise.all([keyPair, recipient]); + let s = webCrypto$8.deriveBits( + { + name: 'ECDH', + namedCurve: curve.web.web, + public: recipient + }, + keyPair.privateKey, + curve.web.sharedSize + ); + let p = webCrypto$8.exportKey( + 'jwk', + keyPair.publicKey + ); + [s, p] = await Promise.all([s, p]); + const sharedKey = new Uint8Array(s); + const publicKey = new Uint8Array(jwkToRawPublic(p)); + return { publicKey, sharedKey }; +} + +/** + * Generate ECDHE secret from private key and public part of ephemeral key using indutny/elliptic + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} V - Public part of ephemeral key + * @param {Uint8Array} d - Recipient private key + * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ +async function ellipticPrivateEphemeralKey(curve, V, d) { + const indutnyCurve = await getIndutnyCurve(curve.name); + V = keyFromPublic(indutnyCurve, V); + d = keyFromPrivate(indutnyCurve, d); + const secretKey = new Uint8Array(d.getPrivate()); + const S = d.derive(V.getPublic()); + const len = indutnyCurve.curve.p.byteLength(); + const sharedKey = S.toArrayLike(Uint8Array, 'be', len); + return { secretKey, sharedKey }; +} + +/** + * Generate ECDHE ephemeral key and secret from public key using indutny/elliptic + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} Q - Recipient public key + * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ +async function ellipticPublicEphemeralKey(curve, Q) { + const indutnyCurve = await getIndutnyCurve(curve.name); + const v = await curve.genKeyPair(); + Q = keyFromPublic(indutnyCurve, Q); + const V = keyFromPrivate(indutnyCurve, v.privateKey); + const publicKey = v.publicKey; + const S = V.derive(Q.getPublic()); + const len = indutnyCurve.curve.p.byteLength(); + const sharedKey = S.toArrayLike(Uint8Array, 'be', len); + return { publicKey, sharedKey }; +} + +/** + * Generate ECDHE secret from private key and public part of ephemeral key using nodeCrypto + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} V - Public part of ephemeral key + * @param {Uint8Array} d - Recipient private key + * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ +async function nodePrivateEphemeralKey(curve, V, d) { + const recipient = nodeCrypto$9.createECDH(curve.node.node); + recipient.setPrivateKey(d); + const sharedKey = new Uint8Array(recipient.computeSecret(V)); + const secretKey = new Uint8Array(recipient.getPrivateKey()); + return { secretKey, sharedKey }; +} + +/** + * Generate ECDHE ephemeral key and secret from public key using nodeCrypto + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} Q - Recipient public key + * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ +async function nodePublicEphemeralKey(curve, Q) { + const sender = nodeCrypto$9.createECDH(curve.node.node); + sender.generateKeys(); + const sharedKey = new Uint8Array(sender.computeSecret(Q)); + const publicKey = new Uint8Array(sender.getPublicKey()); + return { publicKey, sharedKey }; +} + +var ecdh = /*#__PURE__*/Object.freeze({ + __proto__: null, + validateParams: validateParams$5, + encrypt: encrypt$3, + decrypt: decrypt$3 +}); + +// OpenPGP.js - An OpenPGP implementation in javascript + +var elliptic = /*#__PURE__*/Object.freeze({ + __proto__: null, + Curve: Curve, + ecdh: ecdh, + ecdsa: ecdsa, + eddsa: eddsa, + generate: generate$1, + getPreferredHashAlgo: getPreferredHashAlgo +}); + +// GPG4Browsers - An OpenPGP implementation in javascript + +/* + TODO regarding the hash function, read: + https://tools.ietf.org/html/rfc4880#section-13.6 + https://tools.ietf.org/html/rfc4880#section-14 +*/ + +/** + * DSA Sign function + * @param {Integer} hashAlgo + * @param {Uint8Array} hashed + * @param {Uint8Array} g + * @param {Uint8Array} p + * @param {Uint8Array} q + * @param {Uint8Array} x + * @returns {Promise<{ r: Uint8Array, s: Uint8Array }>} + * @async + */ +async function sign$3(hashAlgo, hashed, g, p, q, x) { + const BigInteger = await util.getBigInteger(); + const one = new BigInteger(1); + p = new BigInteger(p); + q = new BigInteger(q); + g = new BigInteger(g); + x = new BigInteger(x); + + let k; + let r; + let s; + let t; + g = g.mod(p); + x = x.mod(q); + // If the output size of the chosen hash is larger than the number of + // bits of q, the hash result is truncated to fit by taking the number + // of leftmost bits equal to the number of bits of q. This (possibly + // truncated) hash function result is treated as a number and used + // directly in the DSA signature algorithm. + const h = new BigInteger(hashed.subarray(0, q.byteLength())).mod(q); + // FIPS-186-4, section 4.6: + // The values of r and s shall be checked to determine if r = 0 or s = 0. + // If either r = 0 or s = 0, a new value of k shall be generated, and the + // signature shall be recalculated. It is extremely unlikely that r = 0 + // or s = 0 if signatures are generated properly. + while (true) { + // See Appendix B here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf + k = await getRandomBigInteger(one, q); // returns in [1, q-1] + r = g.modExp(k, p).imod(q); // (g**k mod p) mod q + if (r.isZero()) { + continue; + } + const xr = x.mul(r).imod(q); + t = h.add(xr).imod(q); // H(m) + x*r mod q + s = k.modInv(q).imul(t).imod(q); // k**-1 * (H(m) + x*r) mod q + if (s.isZero()) { + continue; + } + break; + } + return { + r: r.toUint8Array('be', q.byteLength()), + s: s.toUint8Array('be', q.byteLength()) + }; +} + +/** + * DSA Verify function + * @param {Integer} hashAlgo + * @param {Uint8Array} r + * @param {Uint8Array} s + * @param {Uint8Array} hashed + * @param {Uint8Array} g + * @param {Uint8Array} p + * @param {Uint8Array} q + * @param {Uint8Array} y + * @returns {boolean} + * @async + */ +async function verify$3(hashAlgo, r, s, hashed, g, p, q, y) { + const BigInteger = await util.getBigInteger(); + const zero = new BigInteger(0); + r = new BigInteger(r); + s = new BigInteger(s); + + p = new BigInteger(p); + q = new BigInteger(q); + g = new BigInteger(g); + y = new BigInteger(y); + + if (r.lte(zero) || r.gte(q) || + s.lte(zero) || s.gte(q)) { + util.printDebug('invalid DSA Signature'); + return false; + } + const h = new BigInteger(hashed.subarray(0, q.byteLength())).imod(q); + const w = s.modInv(q); // s**-1 mod q + if (w.isZero()) { + util.printDebug('invalid DSA Signature'); + return false; + } + + g = g.mod(p); + y = y.mod(p); + const u1 = h.mul(w).imod(q); // H(m) * w mod q + const u2 = r.mul(w).imod(q); // r * w mod q + const t1 = g.modExp(u1, p); // g**u1 mod p + const t2 = y.modExp(u2, p); // y**u2 mod p + const v = t1.mul(t2).imod(p).imod(q); // (g**u1 * y**u2 mod p) mod q + return v.equal(r); +} + +/** + * Validate DSA parameters + * @param {Uint8Array} p - DSA prime + * @param {Uint8Array} q - DSA group order + * @param {Uint8Array} g - DSA sub-group generator + * @param {Uint8Array} y - DSA public key + * @param {Uint8Array} x - DSA private key + * @returns {Promise} Whether params are valid. + * @async + */ +async function validateParams$6(p, q, g, y, x) { + const BigInteger = await util.getBigInteger(); + p = new BigInteger(p); + q = new BigInteger(q); + g = new BigInteger(g); + y = new BigInteger(y); + const one = new BigInteger(1); + // Check that 1 < g < p + if (g.lte(one) || g.gte(p)) { + return false; + } + + /** + * Check that subgroup order q divides p-1 + */ + if (!p.dec().mod(q).isZero()) { + return false; + } + + /** + * g has order q + * Check that g ** q = 1 mod p + */ + if (!g.modExp(q, p).isOne()) { + return false; + } + + /** + * Check q is large and probably prime (we mainly want to avoid small factors) + */ + const qSize = new BigInteger(q.bitLength()); + const n150 = new BigInteger(150); + if (qSize.lt(n150) || !(await isProbablePrime(q, null, 32))) { + return false; + } + + /** + * Re-derive public key y' = g ** x mod p + * Expect y == y' + * + * Blinded exponentiation computes g**{rq + x} to compare to y + */ + x = new BigInteger(x); + const two = new BigInteger(2); + const r = await getRandomBigInteger(two.leftShift(qSize.dec()), two.leftShift(qSize)); // draw r of same size as q + const rqx = q.mul(r).add(x); + if (!y.equal(g.modExp(rqx, p))) { + return false; + } + + return true; +} + +var dsa = /*#__PURE__*/Object.freeze({ + __proto__: null, + sign: sign$3, + verify: verify$3, + validateParams: validateParams$6 +}); + +/** + * @fileoverview Asymmetric cryptography functions + * @module crypto/public_key + * @private + */ + +var publicKey = { + /** @see module:crypto/public_key/rsa */ + rsa: rsa, + /** @see module:crypto/public_key/elgamal */ + elgamal: elgamal, + /** @see module:crypto/public_key/elliptic */ + elliptic: elliptic, + /** @see module:crypto/public_key/dsa */ + dsa: dsa, + /** @see tweetnacl */ + nacl: naclFastLight +}; + +/** + * @fileoverview Provides functions for asymmetric signing and signature verification + * @module crypto/signature + * @private + */ + +/** + * Parse signature in binary form to get the parameters. + * The returned values are only padded for EdDSA, since in the other cases their expected length + * depends on the key params, hence we delegate the padding to the signature verification function. + * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} + * See {@link https://tools.ietf.org/html/rfc4880#section-5.2.2|RFC 4880 5.2.2.} + * @param {module:enums.publicKey} algo - Public key algorithm + * @param {Uint8Array} signature - Data for which the signature was created + * @returns {Promise} True if signature is valid. + * @async + */ +function parseSignatureParams(algo, signature) { + let read = 0; + switch (algo) { + // Algorithm-Specific Fields for RSA signatures: + // - MPI of RSA signature value m**d mod n. + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaSign: { + const s = util.readMPI(signature.subarray(read)); + // The signature needs to be the same length as the public key modulo n. + // We pad s on signature verification, where we have access to n. + return { s }; + } + // Algorithm-Specific Fields for DSA or ECDSA signatures: + // - MPI of DSA or ECDSA value r. + // - MPI of DSA or ECDSA value s. + case enums.publicKey.dsa: + case enums.publicKey.ecdsa: + { + const r = util.readMPI(signature.subarray(read)); read += r.length + 2; + const s = util.readMPI(signature.subarray(read)); + return { r, s }; + } + // Algorithm-Specific Fields for EdDSA signatures: + // - MPI of an EC point r. + // - EdDSA value s, in MPI, in the little endian representation + case enums.publicKey.eddsa: { + // When parsing little-endian MPI data, we always need to left-pad it, as done with big-endian values: + // https://www.ietf.org/archive/id/draft-ietf-openpgp-rfc4880bis-10.html#section-3.2-9 + let r = util.readMPI(signature.subarray(read)); read += r.length + 2; + r = util.leftPad(r, 32); + let s = util.readMPI(signature.subarray(read)); + s = util.leftPad(s, 32); + return { r, s }; + } + default: + throw new Error('Invalid signature algorithm.'); + } +} + +/** + * Verifies the signature provided for data using specified algorithms and public key parameters. + * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} + * and {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4} + * for public key and hash algorithms. + * @param {module:enums.publicKey} algo - Public key algorithm + * @param {module:enums.hash} hashAlgo - Hash algorithm + * @param {Object} signature - Named algorithm-specific signature parameters + * @param {Object} publicParams - Algorithm-specific public key parameters + * @param {Uint8Array} data - Data for which the signature was created + * @param {Uint8Array} hashed - The hashed data + * @returns {Promise} True if signature is valid. + * @async + */ +async function verify$4(algo, hashAlgo, signature, publicParams, data, hashed) { + switch (algo) { + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaSign: { + const { n, e } = publicParams; + const s = util.leftPad(signature.s, n.length); // padding needed for webcrypto and node crypto + return publicKey.rsa.verify(hashAlgo, data, s, n, e, hashed); + } + case enums.publicKey.dsa: { + const { g, p, q, y } = publicParams; + const { r, s } = signature; // no need to pad, since we always handle them as BigIntegers + return publicKey.dsa.verify(hashAlgo, r, s, hashed, g, p, q, y); + } + case enums.publicKey.ecdsa: { + const { oid, Q } = publicParams; + const curveSize = new publicKey.elliptic.Curve(oid).payloadSize; + // padding needed for webcrypto + const r = util.leftPad(signature.r, curveSize); + const s = util.leftPad(signature.s, curveSize); + return publicKey.elliptic.ecdsa.verify(oid, hashAlgo, { r, s }, data, Q, hashed); + } + case enums.publicKey.eddsa: { + const { oid, Q } = publicParams; + // signature already padded on parsing + return publicKey.elliptic.eddsa.verify(oid, hashAlgo, signature, data, Q, hashed); + } + default: + throw new Error('Invalid signature algorithm.'); + } +} + +/** + * Creates a signature on data using specified algorithms and private key parameters. + * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} + * and {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4} + * for public key and hash algorithms. + * @param {module:enums.publicKey} algo - Public key algorithm + * @param {module:enums.hash} hashAlgo - Hash algorithm + * @param {Object} publicKeyParams - Algorithm-specific public and private key parameters + * @param {Object} privateKeyParams - Algorithm-specific public and private key parameters + * @param {Uint8Array} data - Data to be signed + * @param {Uint8Array} hashed - The hashed data + * @returns {Promise} Signature Object containing named signature parameters. + * @async + */ +async function sign$4(algo, hashAlgo, publicKeyParams, privateKeyParams, data, hashed) { + if (!publicKeyParams || !privateKeyParams) { + throw new Error('Missing key parameters'); + } + switch (algo) { + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaSign: { + const { n, e } = publicKeyParams; + const { d, p, q, u } = privateKeyParams; + const s = await publicKey.rsa.sign(hashAlgo, data, n, e, d, p, q, u, hashed); + return { s }; + } + case enums.publicKey.dsa: { + const { g, p, q } = publicKeyParams; + const { x } = privateKeyParams; + return publicKey.dsa.sign(hashAlgo, hashed, g, p, q, x); + } + case enums.publicKey.elgamal: { + throw new Error('Signing with Elgamal is not defined in the OpenPGP standard.'); + } + case enums.publicKey.ecdsa: { + const { oid, Q } = publicKeyParams; + const { d } = privateKeyParams; + return publicKey.elliptic.ecdsa.sign(oid, hashAlgo, data, Q, d, hashed); + } + case enums.publicKey.eddsa: { + const { oid, Q } = publicKeyParams; + const { seed } = privateKeyParams; + return publicKey.elliptic.eddsa.sign(oid, hashAlgo, data, Q, seed, hashed); + } + default: + throw new Error('Invalid signature algorithm.'); + } +} + +var signature = /*#__PURE__*/Object.freeze({ + __proto__: null, + parseSignatureParams: parseSignatureParams, + verify: verify$4, + sign: sign$4 +}); + +/** + * @fileoverview Provides access to all cryptographic primitives used in OpenPGP.js + * @see module:crypto/crypto + * @see module:crypto/signature + * @see module:crypto/public_key + * @see module:crypto/cipher + * @see module:crypto/random + * @see module:crypto/hash + * @module crypto + * @private + */ + +// TODO move cfb and gcm to cipher +const mod = { + /** @see module:crypto/cipher */ + cipher: cipher, + /** @see module:crypto/hash */ + hash: hash, + /** @see module:crypto/mode */ + mode: mode, + /** @see module:crypto/public_key */ + publicKey: publicKey, + /** @see module:crypto/signature */ + signature: signature, + /** @see module:crypto/random */ + random: random, + /** @see module:crypto/pkcs1 */ + pkcs1: pkcs1, + /** @see module:crypto/pkcs5 */ + pkcs5: pkcs5, + /** @see module:crypto/aes_kw */ + aesKW: aesKW +}; + +Object.assign(mod, crypto$1); + +var TYPED_OK = typeof Uint8Array !== "undefined" && + typeof Uint16Array !== "undefined" && + typeof Int32Array !== "undefined"; + + +// reduce buffer size, avoiding mem copy +function shrinkBuf(buf, size) { + if (buf.length === size) { + return buf; + } + if (buf.subarray) { + return buf.subarray(0, size); + } + buf.length = size; + return buf; +} + + +const fnTyped = { + arraySet: function (dest, src, src_offs, len, dest_offs) { + if (src.subarray && dest.subarray) { + dest.set(src.subarray(src_offs, src_offs + len), dest_offs); + return; + } + // Fallback to ordinary array + for (let i = 0; i < len; i++) { + dest[dest_offs + i] = src[src_offs + i]; + } + }, + // Join array of chunks to single array. + flattenChunks: function (chunks) { + let i, l, len, pos, chunk; + + // calculate data length + len = 0; + for (i = 0, l = chunks.length; i < l; i++) { + len += chunks[i].length; + } + + // join chunks + const result = new Uint8Array(len); + pos = 0; + for (i = 0, l = chunks.length; i < l; i++) { + chunk = chunks[i]; + result.set(chunk, pos); + pos += chunk.length; + } + + return result; + } +}; + +const fnUntyped = { + arraySet: function (dest, src, src_offs, len, dest_offs) { + for (let i = 0; i < len; i++) { + dest[dest_offs + i] = src[src_offs + i]; + } + }, + // Join array of chunks to single array. + flattenChunks: function (chunks) { + return [].concat.apply([], chunks); + } +}; + + +// Enable/Disable typed arrays use, for testing +// + +let Buf8 = TYPED_OK ? Uint8Array : Array; +let Buf16 = TYPED_OK ? Uint16Array : Array; +let Buf32 = TYPED_OK ? Int32Array : Array; +let flattenChunks = TYPED_OK ? fnTyped.flattenChunks : fnUntyped.flattenChunks; +let arraySet = TYPED_OK ? fnTyped.arraySet : fnUntyped.arraySet; + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +/* Allowed flush values; see deflate() and inflate() below for details */ +const Z_NO_FLUSH = 0; +const Z_PARTIAL_FLUSH = 1; +const Z_SYNC_FLUSH = 2; +const Z_FULL_FLUSH = 3; +const Z_FINISH = 4; +const Z_BLOCK = 5; +const Z_TREES = 6; + +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ +const Z_OK = 0; +const Z_STREAM_END = 1; +const Z_NEED_DICT = 2; +const Z_STREAM_ERROR = -2; +const Z_DATA_ERROR = -3; +//export const Z_MEM_ERROR = -4; +const Z_BUF_ERROR = -5; +const Z_DEFAULT_COMPRESSION = -1; + + +const Z_FILTERED = 1; +const Z_HUFFMAN_ONLY = 2; +const Z_RLE = 3; +const Z_FIXED = 4; +const Z_DEFAULT_STRATEGY = 0; + +/* Possible values of the data_type field (though see inflate()) */ +const Z_BINARY = 0; +const Z_TEXT = 1; +//export const Z_ASCII = 1; // = Z_TEXT (deprecated) +const Z_UNKNOWN = 2; + +/* The deflate compression method */ +const Z_DEFLATED = 8; +//export const Z_NULL = null // Use -1 or null inline, depending on var type + +/*============================================================================*/ + + +function zero$1(buf) { + let len = buf.length; while (--len >= 0) { + buf[len] = 0; + } +} + +// From zutil.h + +const STORED_BLOCK = 0; +const STATIC_TREES = 1; +const DYN_TREES = 2; +/* The three kinds of block type */ + +const MIN_MATCH = 3; +const MAX_MATCH = 258; +/* The minimum and maximum match lengths */ + +// From deflate.h +/* =========================================================================== + * Internal compression state. + */ + +const LENGTH_CODES = 29; +/* number of length codes, not counting the special END_BLOCK code */ + +const LITERALS = 256; +/* number of literal bytes 0..255 */ + +const L_CODES = LITERALS + 1 + LENGTH_CODES; +/* number of Literal or Length codes, including the END_BLOCK code */ + +const D_CODES = 30; +/* number of distance codes */ + +const BL_CODES = 19; +/* number of codes used to transfer the bit lengths */ + +const HEAP_SIZE = 2 * L_CODES + 1; +/* maximum heap size */ + +const MAX_BITS = 15; +/* All codes must not exceed MAX_BITS bits */ + +const Buf_size = 16; +/* size of bit buffer in bi_buf */ + + +/* =========================================================================== + * Constants + */ + +const MAX_BL_BITS = 7; +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +const END_BLOCK = 256; +/* end of block literal code */ + +const REP_3_6 = 16; +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +const REPZ_3_10 = 17; +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +const REPZ_11_138 = 18; +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +/* eslint-disable comma-spacing,array-bracket-spacing */ +const extra_lbits = /* extra bits for each length code */ + [0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0]; + +const extra_dbits = /* extra bits for each distance code */ + [0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13]; + +const extra_blbits = /* extra bits for each bit length code */ + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7]; + +const bl_order = + [16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]; +/* eslint-enable comma-spacing,array-bracket-spacing */ + +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +// We pre-fill arrays with 0 to avoid uninitialized gaps + +const DIST_CODE_LEN = 512; /* see definition of array dist_code below */ + +// !!!! Use flat array instead of structure, Freq = i*2, Len = i*2+1 +const static_ltree = new Array((L_CODES + 2) * 2); +zero$1(static_ltree); +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +const static_dtree = new Array(D_CODES * 2); +zero$1(static_dtree); +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +const _dist_code = new Array(DIST_CODE_LEN); +zero$1(_dist_code); +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +const _length_code = new Array(MAX_MATCH - MIN_MATCH + 1); +zero$1(_length_code); +/* length code for each normalized match length (0 == MIN_MATCH) */ + +const base_length = new Array(LENGTH_CODES); +zero$1(base_length); +/* First normalized length for each code (0 = MIN_MATCH) */ + +const base_dist = new Array(D_CODES); +zero$1(base_dist); +/* First normalized distance for each code (0 = distance of 1) */ + + +function StaticTreeDesc(static_tree, extra_bits, extra_base, elems, max_length) { + + this.static_tree = static_tree; /* static tree or NULL */ + this.extra_bits = extra_bits; /* extra bits for each code or NULL */ + this.extra_base = extra_base; /* base index for extra_bits */ + this.elems = elems; /* max number of elements in the tree */ + this.max_length = max_length; /* max bit length for the codes */ + + // show if `static_tree` has data or dummy - needed for monomorphic objects + this.has_stree = static_tree && static_tree.length; +} + + +let static_l_desc; +let static_d_desc; +let static_bl_desc; + + +function TreeDesc(dyn_tree, stat_desc) { + this.dyn_tree = dyn_tree; /* the dynamic tree */ + this.max_code = 0; /* largest code with non zero frequency */ + this.stat_desc = stat_desc; /* the corresponding static tree */ +} + + + +function d_code(dist) { + return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)]; +} + + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +function put_short(s, w) { +// put_byte(s, (uch)((w) & 0xff)); +// put_byte(s, (uch)((ush)(w) >> 8)); + s.pending_buf[s.pending++] = w & 0xff; + s.pending_buf[s.pending++] = w >>> 8 & 0xff; +} + + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +function send_bits(s, value, length) { + if (s.bi_valid > Buf_size - length) { + s.bi_buf |= value << s.bi_valid & 0xffff; + put_short(s, s.bi_buf); + s.bi_buf = value >> Buf_size - s.bi_valid; + s.bi_valid += length - Buf_size; + } else { + s.bi_buf |= value << s.bi_valid & 0xffff; + s.bi_valid += length; + } +} + + +function send_code(s, c, tree) { + send_bits(s, tree[c * 2]/*.Code*/, tree[c * 2 + 1]/*.Len*/); +} + + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +function bi_reverse(code, len) { + let res = 0; + do { + res |= code & 1; + code >>>= 1; + res <<= 1; + } while (--len > 0); + return res >>> 1; +} + + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +function bi_flush(s) { + if (s.bi_valid === 16) { + put_short(s, s.bi_buf); + s.bi_buf = 0; + s.bi_valid = 0; + + } else if (s.bi_valid >= 8) { + s.pending_buf[s.pending++] = s.bi_buf & 0xff; + s.bi_buf >>= 8; + s.bi_valid -= 8; + } +} + + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +function gen_bitlen(s, desc) +// deflate_state *s; +// tree_desc *desc; /* the tree descriptor */ +{ + const tree = desc.dyn_tree; + const max_code = desc.max_code; + const stree = desc.stat_desc.static_tree; + const has_stree = desc.stat_desc.has_stree; + const extra = desc.stat_desc.extra_bits; + const base = desc.stat_desc.extra_base; + const max_length = desc.stat_desc.max_length; + let h; /* heap index */ + let n, m; /* iterate over the tree elements */ + let bits; /* bit length */ + let xbits; /* extra bits */ + let f; /* frequency */ + let overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) { + s.bl_count[bits] = 0; + } + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s.heap[s.heap_max] * 2 + 1]/*.Len*/ = 0; /* root of the heap */ + + for (h = s.heap_max + 1; h < HEAP_SIZE; h++) { + n = s.heap[h]; + bits = tree[tree[n * 2 + 1]/*.Dad*/ * 2 + 1]/*.Len*/ + 1; + if (bits > max_length) { + bits = max_length; + overflow++; + } + tree[n * 2 + 1]/*.Len*/ = bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) { + continue; + } /* not a leaf node */ + + s.bl_count[bits]++; + xbits = 0; + if (n >= base) { + xbits = extra[n - base]; + } + f = tree[n * 2]/*.Freq*/; + s.opt_len += f * (bits + xbits); + if (has_stree) { + s.static_len += f * (stree[n * 2 + 1]/*.Len*/ + xbits); + } + } + if (overflow === 0) { + return; + } + + // Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length - 1; + while (s.bl_count[bits] === 0) { + bits--; + } + s.bl_count[bits]--; /* move one leaf down the tree */ + s.bl_count[bits + 1] += 2; /* move one overflow item as its brother */ + s.bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits !== 0; bits--) { + n = s.bl_count[bits]; + while (n !== 0) { + m = s.heap[--h]; + if (m > max_code) { + continue; + } + if (tree[m * 2 + 1]/*.Len*/ !== bits) { + // Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s.opt_len += (bits - tree[m * 2 + 1]/*.Len*/) * tree[m * 2]/*.Freq*/; + tree[m * 2 + 1]/*.Len*/ = bits; + } + n--; + } + } +} + + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +function gen_codes(tree, max_code, bl_count) +// ct_data *tree; /* the tree to decorate */ +// int max_code; /* largest code with non zero frequency */ +// ushf *bl_count; /* number of codes at each bit length */ +{ + const next_code = new Array(MAX_BITS + 1); /* next code value for each bit length */ + let code = 0; /* running code value */ + let bits; /* bit index */ + let n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = code + bl_count[bits - 1] << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + //Assert (code + bl_count[MAX_BITS]-1 == (1< length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES - 1; code++) { + base_length[code] = length; + for (n = 0; n < 1 << extra_lbits[code]; n++) { + _length_code[length++] = code; + } + } + //Assert (length == 256, "tr_static_init: length != 256"); + /* Note that the length 255 (match length 258) can be represented + * in two different ways: code 284 + 5 bits or code 285, so we + * overwrite length_code[255] to use the best encoding: + */ + _length_code[length - 1] = code; + + /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ + dist = 0; + for (code = 0; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < 1 << extra_dbits[code]; n++) { + _dist_code[dist++] = code; + } + } + //Assert (dist == 256, "tr_static_init: dist != 256"); + dist >>= 7; /* from now on, all distances are divided by 128 */ + for (; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < 1 << extra_dbits[code] - 7; n++) { + _dist_code[256 + dist++] = code; + } + } + //Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) { + bl_count[bits] = 0; + } + + n = 0; + while (n <= 143) { + static_ltree[n * 2 + 1]/*.Len*/ = 8; + n++; + bl_count[8]++; + } + while (n <= 255) { + static_ltree[n * 2 + 1]/*.Len*/ = 9; + n++; + bl_count[9]++; + } + while (n <= 279) { + static_ltree[n * 2 + 1]/*.Len*/ = 7; + n++; + bl_count[7]++; + } + while (n <= 287) { + static_ltree[n * 2 + 1]/*.Len*/ = 8; + n++; + bl_count[8]++; + } + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes(static_ltree, L_CODES + 1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n * 2 + 1]/*.Len*/ = 5; + static_dtree[n * 2]/*.Code*/ = bi_reverse(n, 5); + } + + // Now data ready and we can init static trees + static_l_desc = new StaticTreeDesc(static_ltree, extra_lbits, LITERALS + 1, L_CODES, MAX_BITS); + static_d_desc = new StaticTreeDesc(static_dtree, extra_dbits, 0, D_CODES, MAX_BITS); + static_bl_desc = new StaticTreeDesc(new Array(0), extra_blbits, 0, BL_CODES, MAX_BL_BITS); + + //static_init_done = true; +} + + +/* =========================================================================== + * Initialize a new block. + */ +function init_block(s) { + let n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) { + s.dyn_ltree[n * 2]/*.Freq*/ = 0; + } + for (n = 0; n < D_CODES; n++) { + s.dyn_dtree[n * 2]/*.Freq*/ = 0; + } + for (n = 0; n < BL_CODES; n++) { + s.bl_tree[n * 2]/*.Freq*/ = 0; + } + + s.dyn_ltree[END_BLOCK * 2]/*.Freq*/ = 1; + s.opt_len = s.static_len = 0; + s.last_lit = s.matches = 0; +} + + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +function bi_windup(s) { + if (s.bi_valid > 8) { + put_short(s, s.bi_buf); + } else if (s.bi_valid > 0) { + //put_byte(s, (Byte)s->bi_buf); + s.pending_buf[s.pending++] = s.bi_buf; + } + s.bi_buf = 0; + s.bi_valid = 0; +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +function copy_block(s, buf, len, header) +//DeflateState *s; +//charf *buf; /* the input data */ +//unsigned len; /* its length */ +//int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + + if (header) { + put_short(s, len); + put_short(s, ~len); + } + // while (len--) { + // put_byte(s, *buf++); + // } + arraySet(s.pending_buf, s.window, buf, len, s.pending); + s.pending += len; +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +function smaller(tree, n, m, depth) { + const _n2 = n * 2; + const _m2 = m * 2; + return tree[_n2]/*.Freq*/ < tree[_m2]/*.Freq*/ || + tree[_n2]/*.Freq*/ === tree[_m2]/*.Freq*/ && depth[n] <= depth[m]; +} + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +function pqdownheap(s, tree, k) +// deflate_state *s; +// ct_data *tree; /* the tree to restore */ +// int k; /* node to move down */ +{ + const v = s.heap[k]; + let j = k << 1; /* left son of k */ + while (j <= s.heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s.heap_len && + smaller(tree, s.heap[j + 1], s.heap[j], s.depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s.heap[j], s.depth)) { + break; + } + + /* Exchange v with the smallest son */ + s.heap[k] = s.heap[j]; + k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s.heap[k] = v; +} + + +// inlined manually +// var SMALLEST = 1; + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +function compress_block(s, ltree, dtree) +// deflate_state *s; +// const ct_data *ltree; /* literal tree */ +// const ct_data *dtree; /* distance tree */ +{ + let dist; /* distance of matched string */ + let lc; /* match length or unmatched char (if dist == 0) */ + let lx = 0; /* running index in l_buf */ + let code; /* the code to send */ + let extra; /* number of extra bits to send */ + + if (s.last_lit !== 0) { + do { + dist = s.pending_buf[s.d_buf + lx * 2] << 8 | s.pending_buf[s.d_buf + lx * 2 + 1]; + lc = s.pending_buf[s.l_buf + lx]; + lx++; + + if (dist === 0) { + send_code(s, lc, ltree); /* send a literal byte */ + //Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code + LITERALS + 1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra !== 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + //Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra !== 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + //Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + // "pendingBuf overflow"); + + } while (lx < s.last_lit); + } + + send_code(s, END_BLOCK, ltree); +} + + +/* =========================================================================== + * Construct one Huffman tree and assigns the code bit strings and lengths. + * Update the total bit length for the current block. + * IN assertion: the field freq is set for all tree elements. + * OUT assertions: the fields len and code are set to the optimal bit length + * and corresponding code. The length opt_len is updated; static_len is + * also updated if stree is not null. The field max_code is set. + */ +function build_tree(s, desc) +// deflate_state *s; +// tree_desc *desc; /* the tree descriptor */ +{ + const tree = desc.dyn_tree; + const stree = desc.stat_desc.static_tree; + const has_stree = desc.stat_desc.has_stree; + const elems = desc.stat_desc.elems; + let n, m; /* iterate over heap elements */ + let max_code = -1; /* largest code with non zero frequency */ + let node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s.heap_len = 0; + s.heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n * 2]/*.Freq*/ !== 0) { + s.heap[++s.heap_len] = max_code = n; + s.depth[n] = 0; + + } else { + tree[n * 2 + 1]/*.Len*/ = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s.heap_len < 2) { + node = s.heap[++s.heap_len] = max_code < 2 ? ++max_code : 0; + tree[node * 2]/*.Freq*/ = 1; + s.depth[node] = 0; + s.opt_len--; + + if (has_stree) { + s.static_len -= stree[node * 2 + 1]/*.Len*/; + } + /* node is 0 or 1 so it does not have extra bits */ + } + desc.max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s.heap_len >> 1/*int /2*/; n >= 1; n--) { + pqdownheap(s, tree, n); + } + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + //pqremove(s, tree, n); /* n = node of least frequency */ + /*** pqremove ***/ + n = s.heap[1/*SMALLEST*/]; + s.heap[1/*SMALLEST*/] = s.heap[s.heap_len--]; + pqdownheap(s, tree, 1/*SMALLEST*/); + /***/ + + m = s.heap[1/*SMALLEST*/]; /* m = node of next least frequency */ + + s.heap[--s.heap_max] = n; /* keep the nodes sorted by frequency */ + s.heap[--s.heap_max] = m; + + /* Create a new node father of n and m */ + tree[node * 2]/*.Freq*/ = tree[n * 2]/*.Freq*/ + tree[m * 2]/*.Freq*/; + s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1; + tree[n * 2 + 1]/*.Dad*/ = tree[m * 2 + 1]/*.Dad*/ = node; + + /* and insert the new node in the heap */ + s.heap[1/*SMALLEST*/] = node++; + pqdownheap(s, tree, 1/*SMALLEST*/); + + } while (s.heap_len >= 2); + + s.heap[--s.heap_max] = s.heap[1/*SMALLEST*/]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes(tree, max_code, s.bl_count); +} + + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +function scan_tree(s, tree, max_code) +// deflate_state *s; +// ct_data *tree; /* the tree to be scanned */ +// int max_code; /* and its largest code of non zero frequency */ +{ + let n; /* iterates over all tree elements */ + let prevlen = -1; /* last emitted length */ + let curlen; /* length of current code */ + + let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */ + + let count = 0; /* repeat count of the current code */ + let max_count = 7; /* max repeat count */ + let min_count = 4; /* min repeat count */ + + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } + tree[(max_code + 1) * 2 + 1]/*.Len*/ = 0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[(n + 1) * 2 + 1]/*.Len*/; + + if (++count < max_count && curlen === nextlen) { + continue; + + } else if (count < min_count) { + s.bl_tree[curlen * 2]/*.Freq*/ += count; + + } else if (curlen !== 0) { + + if (curlen !== prevlen) { + s.bl_tree[curlen * 2]/*.Freq*/++; + } + s.bl_tree[REP_3_6 * 2]/*.Freq*/++; + + } else if (count <= 10) { + s.bl_tree[REPZ_3_10 * 2]/*.Freq*/++; + + } else { + s.bl_tree[REPZ_11_138 * 2]/*.Freq*/++; + } + + count = 0; + prevlen = curlen; + + if (nextlen === 0) { + max_count = 138; + min_count = 3; + + } else if (curlen === nextlen) { + max_count = 6; + min_count = 3; + + } else { + max_count = 7; + min_count = 4; + } + } +} + + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +function send_tree(s, tree, max_code) +// deflate_state *s; +// ct_data *tree; /* the tree to be scanned */ +// int max_code; /* and its largest code of non zero frequency */ +{ + let n; /* iterates over all tree elements */ + let prevlen = -1; /* last emitted length */ + let curlen; /* length of current code */ + + let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */ + + let count = 0; /* repeat count of the current code */ + let max_count = 7; /* max repeat count */ + let min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[(n + 1) * 2 + 1]/*.Len*/; + + if (++count < max_count && curlen === nextlen) { + continue; + + } else if (count < min_count) { + do { + send_code(s, curlen, s.bl_tree); + } while (--count !== 0); + + } else if (curlen !== 0) { + if (curlen !== prevlen) { + send_code(s, curlen, s.bl_tree); + count--; + } + //Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s.bl_tree); + send_bits(s, count - 3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s.bl_tree); + send_bits(s, count - 3, 3); + + } else { + send_code(s, REPZ_11_138, s.bl_tree); + send_bits(s, count - 11, 7); + } + + count = 0; + prevlen = curlen; + if (nextlen === 0) { + max_count = 138; + min_count = 3; + + } else if (curlen === nextlen) { + max_count = 6; + min_count = 3; + + } else { + max_count = 7; + min_count = 4; + } + } +} + + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +function build_bl_tree(s) { + let max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, s.dyn_ltree, s.l_desc.max_code); + scan_tree(s, s.dyn_dtree, s.d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, s.bl_desc); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) { + if (s.bl_tree[bl_order[max_blindex] * 2 + 1]/*.Len*/ !== 0) { + break; + } + } + /* Update opt_len to include the bit length tree and counts */ + s.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4; + //Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + // s->opt_len, s->static_len)); + + return max_blindex; +} + + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +function send_all_trees(s, lcodes, dcodes, blcodes) +// deflate_state *s; +// int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + let rank; /* index in bl_order */ + + //Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + //Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + // "too many codes"); + //Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes - 1, 5); + send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + //Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s.bl_tree[bl_order[rank] * 2 + 1]/*.Len*/, 3); + } + //Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, s.dyn_ltree, lcodes - 1); /* literal tree */ + //Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, s.dyn_dtree, dcodes - 1); /* distance tree */ + //Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + + +/* =========================================================================== + * Check if the data type is TEXT or BINARY, using the following algorithm: + * - TEXT if the two conditions below are satisfied: + * a) There are no non-portable control characters belonging to the + * "black list" (0..6, 14..25, 28..31). + * b) There is at least one printable character belonging to the + * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). + * - BINARY otherwise. + * - The following partially-portable control characters form a + * "gray list" that is ignored in this detection algorithm: + * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). + * IN assertion: the fields Freq of dyn_ltree are set. + */ +function detect_data_type(s) { + /* black_mask is the bit mask of black-listed bytes + * set bits 0..6, 14..25, and 28..31 + * 0xf3ffc07f = binary 11110011111111111100000001111111 + */ + let black_mask = 0xf3ffc07f; + let n; + + /* Check for non-textual ("black-listed") bytes. */ + for (n = 0; n <= 31; n++, black_mask >>>= 1) { + if (black_mask & 1 && s.dyn_ltree[n * 2]/*.Freq*/ !== 0) { + return Z_BINARY; + } + } + + /* Check for textual ("white-listed") bytes. */ + if (s.dyn_ltree[9 * 2]/*.Freq*/ !== 0 || s.dyn_ltree[10 * 2]/*.Freq*/ !== 0 || + s.dyn_ltree[13 * 2]/*.Freq*/ !== 0) { + return Z_TEXT; + } + for (n = 32; n < LITERALS; n++) { + if (s.dyn_ltree[n * 2]/*.Freq*/ !== 0) { + return Z_TEXT; + } + } + + /* There are no "black-listed" or "white-listed" bytes: + * this stream either is empty or has tolerated ("gray-listed") bytes only. + */ + return Z_BINARY; +} + + +let static_init_done = false; + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +function _tr_init(s) { + + if (!static_init_done) { + tr_static_init(); + static_init_done = true; + } + + s.l_desc = new TreeDesc(s.dyn_ltree, static_l_desc); + s.d_desc = new TreeDesc(s.dyn_dtree, static_d_desc); + s.bl_desc = new TreeDesc(s.bl_tree, static_bl_desc); + + s.bi_buf = 0; + s.bi_valid = 0; + + /* Initialize the first block of the first file: */ + init_block(s); +} + + +/* =========================================================================== + * Send a stored block + */ +function _tr_stored_block(s, buf, stored_len, last) +//DeflateState *s; +//charf *buf; /* input block */ +//ulg stored_len; /* length of input block */ +//int last; /* one if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK << 1) + (last ? 1 : 0), 3); /* send block type */ + copy_block(s, buf, stored_len, true); /* with header */ +} + + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + */ +function _tr_align(s) { + send_bits(s, STATIC_TREES << 1, 3); + send_code(s, END_BLOCK, static_ltree); + bi_flush(s); +} + + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +function _tr_flush_block(s, buf, stored_len, last) +//DeflateState *s; +//charf *buf; /* input block, or NULL if too old */ +//ulg stored_len; /* length of input block */ +//int last; /* one if this is the last block for a file */ +{ + let opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + let max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s.level > 0) { + + /* Check if the file is binary or text */ + if (s.strm.data_type === Z_UNKNOWN) { + s.strm.data_type = detect_data_type(s); + } + + /* Construct the literal and distance trees */ + build_tree(s, s.l_desc); + // Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + // s->static_len)); + + build_tree(s, s.d_desc); + // Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + // s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = s.opt_len + 3 + 7 >>> 3; + static_lenb = s.static_len + 3 + 7 >>> 3; + + // Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + // opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + // s->last_lit)); + + if (static_lenb <= opt_lenb) { + opt_lenb = static_lenb; + } + + } else { + // Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + + if (stored_len + 4 <= opt_lenb && buf !== -1) { + /* 4: two words for the lengths */ + + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, last); + + } else if (s.strategy === Z_FIXED || static_lenb === opt_lenb) { + + send_bits(s, (STATIC_TREES << 1) + (last ? 1 : 0), 3); + compress_block(s, static_ltree, static_dtree); + + } else { + send_bits(s, (DYN_TREES << 1) + (last ? 1 : 0), 3); + send_all_trees(s, s.l_desc.max_code + 1, s.d_desc.max_code + 1, max_blindex + 1); + compress_block(s, s.dyn_ltree, s.dyn_dtree); + } + // Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (last) { + bi_windup(s); + } + // Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + // s->compressed_len-7*last)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +function _tr_tally(s, dist, lc) +// deflate_state *s; +// unsigned dist; /* distance of matched string */ +// unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + //var out_length, in_length, dcode; + + s.pending_buf[s.d_buf + s.last_lit * 2] = dist >>> 8 & 0xff; + s.pending_buf[s.d_buf + s.last_lit * 2 + 1] = dist & 0xff; + + s.pending_buf[s.l_buf + s.last_lit] = lc & 0xff; + s.last_lit++; + + if (dist === 0) { + /* lc is the unmatched char */ + s.dyn_ltree[lc * 2]/*.Freq*/++; + } else { + s.matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + //Assert((ush)dist < (ush)MAX_DIST(s) && + // (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + // (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s.dyn_ltree[(_length_code[lc] + LITERALS + 1) * 2]/*.Freq*/++; + s.dyn_dtree[d_code(dist) * 2]/*.Freq*/++; + } + + // (!) This block is disabled in zlib defaults, + // don't enable it for binary compatibility + + //#ifdef TRUNCATE_BLOCK + // /* Try to guess if it is profitable to stop the current block here */ + // if ((s.last_lit & 0x1fff) === 0 && s.level > 2) { + // /* Compute an upper bound for the compressed length */ + // out_length = s.last_lit*8; + // in_length = s.strstart - s.block_start; + // + // for (dcode = 0; dcode < D_CODES; dcode++) { + // out_length += s.dyn_dtree[dcode*2]/*.Freq*/ * (5 + extra_dbits[dcode]); + // } + // out_length >>>= 3; + // //Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + // // s->last_lit, in_length, out_length, + // // 100L - out_length*100L/in_length)); + // if (s.matches < (s.last_lit>>1)/*int /2*/ && out_length < (in_length>>1)/*int /2*/) { + // return true; + // } + // } + //#endif + + return s.last_lit === s.lit_bufsize - 1; + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +// Note: adler32 takes 12% for level 0 and 2% for level 6. +// It isn't worth it to make additional optimizations as in original. +// Small size is preferable. + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +function adler32(adler, buf, len, pos) { + let s1 = adler & 0xffff |0, + s2 = adler >>> 16 & 0xffff |0, + n = 0; + + while (len !== 0) { + // Set limit ~ twice less than 5552, to keep + // s2 in 31-bits, because we force signed ints. + // in other case %= will fail. + n = len > 2000 ? 2000 : len; + len -= n; + + do { + s1 = s1 + buf[pos++] |0; + s2 = s2 + s1 |0; + } while (--n); + + s1 %= 65521; + s2 %= 65521; + } + + return s1 | s2 << 16 |0; +} + +// Note: we can't get significant speed boost here. +// So write code to minimize size - no pregenerated tables +// and array tools dependencies. + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +// Use ordinary array, since untyped makes no boost here +function makeTable() { + let c; + const table = []; + + for (let n = 0; n < 256; n++) { + c = n; + for (let k = 0; k < 8; k++) { + c = c & 1 ? 0xEDB88320 ^ c >>> 1 : c >>> 1; + } + table[n] = c; + } + + return table; +} + +// Create table on load. Just 255 signed longs. Not a problem. +const crcTable = makeTable(); + + +function crc32(crc, buf, len, pos) { + const t = crcTable, + end = pos + len; + + crc ^= -1; + + for (let i = pos; i < end; i++) { + crc = crc >>> 8 ^ t[(crc ^ buf[i]) & 0xFF]; + } + + return crc ^ -1; // >>> 0; +} + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +var msg = { + 2: "need dictionary", /* Z_NEED_DICT 2 */ + 1: "stream end", /* Z_STREAM_END 1 */ + 0: "", /* Z_OK 0 */ + "-1": "file error", /* Z_ERRNO (-1) */ + "-2": "stream error", /* Z_STREAM_ERROR (-2) */ + "-3": "data error", /* Z_DATA_ERROR (-3) */ + "-4": "insufficient memory", /* Z_MEM_ERROR (-4) */ + "-5": "buffer error", /* Z_BUF_ERROR (-5) */ + "-6": "incompatible version" /* Z_VERSION_ERROR (-6) */ +}; + +/*============================================================================*/ + + +const MAX_MEM_LEVEL = 9; + + +const LENGTH_CODES$1 = 29; +/* number of length codes, not counting the special END_BLOCK code */ +const LITERALS$1 = 256; +/* number of literal bytes 0..255 */ +const L_CODES$1 = LITERALS$1 + 1 + LENGTH_CODES$1; +/* number of Literal or Length codes, including the END_BLOCK code */ +const D_CODES$1 = 30; +/* number of distance codes */ +const BL_CODES$1 = 19; +/* number of codes used to transfer the bit lengths */ +const HEAP_SIZE$1 = 2 * L_CODES$1 + 1; +/* maximum heap size */ +const MAX_BITS$1 = 15; +/* All codes must not exceed MAX_BITS bits */ + +const MIN_MATCH$1 = 3; +const MAX_MATCH$1 = 258; +const MIN_LOOKAHEAD = (MAX_MATCH$1 + MIN_MATCH$1 + 1); + +const PRESET_DICT = 0x20; + +const INIT_STATE = 42; +const EXTRA_STATE = 69; +const NAME_STATE = 73; +const COMMENT_STATE = 91; +const HCRC_STATE = 103; +const BUSY_STATE = 113; +const FINISH_STATE = 666; + +const BS_NEED_MORE = 1; /* block not completed, need more input or more output */ +const BS_BLOCK_DONE = 2; /* block flush performed */ +const BS_FINISH_STARTED = 3; /* finish started, need only more output at next deflate */ +const BS_FINISH_DONE = 4; /* finish done, accept no more input or output */ + +const OS_CODE = 0x03; // Unix :) . Don't detect, use this default. + +function err(strm, errorCode) { + strm.msg = msg[errorCode]; + return errorCode; +} + +function rank(f) { + return ((f) << 1) - ((f) > 4 ? 9 : 0); +} + +function zero$2(buf) { let len = buf.length; while (--len >= 0) { buf[len] = 0; } } + + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->output buffer and copying into it. + * (See also read_buf()). + */ +function flush_pending(strm) { + const s = strm.state; + + //_tr_flush_bits(s); + let len = s.pending; + if (len > strm.avail_out) { + len = strm.avail_out; + } + if (len === 0) { return; } + + arraySet(strm.output, s.pending_buf, s.pending_out, len, strm.next_out); + strm.next_out += len; + s.pending_out += len; + strm.total_out += len; + strm.avail_out -= len; + s.pending -= len; + if (s.pending === 0) { + s.pending_out = 0; + } +} + + +function flush_block_only(s, last) { + _tr_flush_block(s, (s.block_start >= 0 ? s.block_start : -1), s.strstart - s.block_start, last); + s.block_start = s.strstart; + flush_pending(s.strm); +} + + +function put_byte(s, b) { + s.pending_buf[s.pending++] = b; +} + + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +function putShortMSB(s, b) { + // put_byte(s, (Byte)(b >> 8)); + // put_byte(s, (Byte)(b & 0xff)); + s.pending_buf[s.pending++] = (b >>> 8) & 0xff; + s.pending_buf[s.pending++] = b & 0xff; +} + + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->input buffer and copying from it. + * (See also flush_pending()). + */ +function read_buf(strm, buf, start, size) { + let len = strm.avail_in; + + if (len > size) { len = size; } + if (len === 0) { return 0; } + + strm.avail_in -= len; - // first car - c = 1; - v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536; - v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536; - v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536; - v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536; - v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536; - v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536; - v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536; - v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536; - v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536; - v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536; - v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536; - v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536; - v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536; - v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536; - v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536; - v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536; - t0 += c-1 + 37 * (c-1); + // zmemcpy(buf, strm->next_in, len); + arraySet(buf, strm.input, strm.next_in, len, start); + if (strm.state.wrap === 1) { + strm.adler = adler32(strm.adler, buf, len, start); + } - // second car - c = 1; - v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536; - v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536; - v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536; - v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536; - v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536; - v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536; - v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536; - v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536; - v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536; - v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536; - v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536; - v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536; - v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536; - v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536; - v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536; - v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536; - t0 += c-1 + 37 * (c-1); + else if (strm.state.wrap === 2) { + strm.adler = crc32(strm.adler, buf, len, start); + } + + strm.next_in += len; + strm.total_in += len; + + return len; +} + + +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +function longest_match(s, cur_match) { + let chain_length = s.max_chain_length; /* max hash chain length */ + let scan = s.strstart; /* current string */ + let match; /* matched string */ + let len; /* length of current match */ + let best_len = s.prev_length; /* best match length so far */ + let nice_match = s.nice_match; /* stop if match long enough */ + const limit = (s.strstart > (s.w_size - MIN_LOOKAHEAD)) ? + s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0/*NIL*/; + + const _win = s.window; // shortcut + + const wmask = s.w_mask; + const prev = s.prev; + + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + + const strend = s.strstart + MAX_MATCH$1; + let scan_end1 = _win[scan + best_len - 1]; + let scan_end = _win[scan + best_len]; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + // Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s.prev_length >= s.good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if (nice_match > s.lookahead) { nice_match = s.lookahead; } + + // Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + // Assert(cur_match < s->strstart, "no future"); + match = cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2. Note that the checks below + * for insufficient lookahead only occur occasionally for performance + * reasons. Therefore uninitialized memory will be accessed, and + * conditional jumps will be made that depend on those values. + * However the length of the match is limited to the lookahead, so + * the output of deflate is not affected by the uninitialized values. + */ + + if (_win[match + best_len] !== scan_end || + _win[match + best_len - 1] !== scan_end1 || + _win[match] !== _win[scan] || + _win[++match] !== _win[scan + 1]) { + continue; + } + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2; + match++; + // Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + /*jshint noempty:false*/ + } while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + scan < strend); + + // Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH$1 - (strend - scan); + scan = strend - MAX_MATCH$1; + + if (len > best_len) { + s.match_start = cur_match; + best_len = len; + if (len >= nice_match) { + break; + } + scan_end1 = _win[scan + best_len - 1]; + scan_end = _win[scan + best_len]; + } + } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0); + + if (best_len <= s.lookahead) { + return best_len; + } + return s.lookahead; +} + + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +function fill_window(s) { + const _w_size = s.w_size; + let p, n, m, more, str; + + //Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); + + do { + more = s.window_size - s.lookahead - s.strstart; + + // JS ints have 32 bit, block below not needed + /* Deal with !@#$% 64K limit: */ + //if (sizeof(int) <= 2) { + // if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + // more = wsize; + // + // } else if (more == (unsigned)(-1)) { + // /* Very unlikely, but possible on 16 bit machine if + // * strstart == 0 && lookahead == 1 (input done a byte at time) + // */ + // more--; + // } + //} + + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) { + + arraySet(s.window, s.window, _w_size, _w_size, 0); + s.match_start -= _w_size; + s.strstart -= _w_size; + /* we now have strstart >= MAX_DIST */ + s.block_start -= _w_size; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + + n = s.hash_size; + p = n; + do { + m = s.head[--p]; + s.head[p] = (m >= _w_size ? m - _w_size : 0); + } while (--n); + + n = _w_size; + p = n; + do { + m = s.prev[--p]; + s.prev[p] = (m >= _w_size ? m - _w_size : 0); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); + + more += _w_size; + } + if (s.strm.avail_in === 0) { + break; + } + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + //Assert(more >= 2, "more < 2"); + n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more); + s.lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s.lookahead + s.insert >= MIN_MATCH$1) { + str = s.strstart - s.insert; + s.ins_h = s.window[str]; + + /* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + 1]) & s.hash_mask; + //#if MIN_MATCH != 3 + // Call update_hash() MIN_MATCH-3 more times + //#endif + while (s.insert) { + /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH$1 - 1]) & s.hash_mask; + + s.prev[str & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = str; + str++; + s.insert--; + if (s.lookahead + s.insert < MIN_MATCH$1) { + break; + } + } + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ - o[ 0] = t0; - o[ 1] = t1; - o[ 2] = t2; - o[ 3] = t3; - o[ 4] = t4; - o[ 5] = t5; - o[ 6] = t6; - o[ 7] = t7; - o[ 8] = t8; - o[ 9] = t9; - o[10] = t10; - o[11] = t11; - o[12] = t12; - o[13] = t13; - o[14] = t14; - o[15] = t15; -} + } while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0); -function S(o, a) { - M(o, a, a); + /* If the WIN_INIT bytes after the end of the current data have never been + * written, then zero those bytes in order to avoid memory check reports of + * the use of uninitialized (or uninitialised as Julian writes) bytes by + * the longest match routines. Update the high water mark for the next + * time through here. WIN_INIT is set to MAX_MATCH since the longest match + * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. + */ + // if (s.high_water < s.window_size) { + // var curr = s.strstart + s.lookahead; + // var init = 0; + // + // if (s.high_water < curr) { + // /* Previous high water mark below current data -- zero WIN_INIT + // * bytes or up to end of window, whichever is less. + // */ + // init = s.window_size - curr; + // if (init > WIN_INIT) + // init = WIN_INIT; + // zmemzero(s->window + curr, (unsigned)init); + // s->high_water = curr + init; + // } + // else if (s->high_water < (ulg)curr + WIN_INIT) { + // /* High water mark at or above current data, but below current data + // * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up + // * to end of window, whichever is less. + // */ + // init = (ulg)curr + WIN_INIT - s->high_water; + // if (init > s->window_size - s->high_water) + // init = s->window_size - s->high_water; + // zmemzero(s->window + s->high_water, (unsigned)init); + // s->high_water += init; + // } + // } + // + // Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, + // "not enough room for search"); } -function inv25519(o, i) { - var c = gf(); - var a; - for (a = 0; a < 16; a++) c[a] = i[a]; - for (a = 253; a >= 0; a--) { - S(c, c); - if(a !== 2 && a !== 4) M(c, c, i); - } - for (a = 0; a < 16; a++) o[a] = c[a]; -} +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +function deflate_stored(s, flush) { + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + let max_block_size = 0xffff; -function pow2523(o, i) { - var c = gf(); - var a; - for (a = 0; a < 16; a++) c[a] = i[a]; - for (a = 250; a >= 0; a--) { - S(c, c); - if(a !== 1) M(c, c, i); + if (max_block_size > s.pending_buf_size - 5) { + max_block_size = s.pending_buf_size - 5; } - for (a = 0; a < 16; a++) o[a] = c[a]; -} -function crypto_scalarmult(q, n, p) { - var z = new Uint8Array(32); - var x = new Float64Array(80), r, i; - var a = gf(), b = gf(), c = gf(), - d = gf(), e = gf(), f = gf(); - for (i = 0; i < 31; i++) z[i] = n[i]; - z[31]=(n[31]&127)|64; - z[0]&=248; - unpack25519(x,p); - for (i = 0; i < 16; i++) { - b[i]=x[i]; - d[i]=a[i]=c[i]=0; + /* Copy as much as possible from input to output: */ + for (; ;) { + /* Fill the window as much as possible: */ + if (s.lookahead <= 1) { + + //Assert(s->strstart < s->w_size+MAX_DIST(s) || + // s->block_start >= (long)s->w_size, "slide too late"); + // if (!(s.strstart < s.w_size + (s.w_size - MIN_LOOKAHEAD) || + // s.block_start >= s.w_size)) { + // throw new Error("slide too late"); + // } + + fill_window(s); + if (s.lookahead === 0 && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + + if (s.lookahead === 0) { + break; + } + /* flush the current block */ + } + //Assert(s->block_start >= 0L, "block gone"); + // if (s.block_start < 0) throw new Error("block gone"); + + s.strstart += s.lookahead; + s.lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + const max_start = s.block_start + max_block_size; + + if (s.strstart === 0 || s.strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s.lookahead = s.strstart - max_start; + s.strstart = max_start; + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + + + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s.strstart - s.block_start >= (s.w_size - MIN_LOOKAHEAD)) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } } - a[0]=d[0]=1; - for (i=254; i>=0; --i) { - r=(z[i>>>3]>>>(i&7))&1; - sel25519(a,b,r); - sel25519(c,d,r); - A(e,a,c); - Z(a,a,c); - A(c,b,d); - Z(b,b,d); - S(d,e); - S(f,a); - M(a,c,a); - M(c,b,e); - A(e,a,c); - Z(a,a,c); - S(b,a); - Z(c,d,f); - M(a,c,_121665); - A(a,a,d); - M(c,c,a); - M(a,d,f); - M(d,b,x); - S(b,e); - sel25519(a,b,r); - sel25519(c,d,r); + + s.insert = 0; + + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; } - for (i = 0; i < 16; i++) { - x[i+16]=a[i]; - x[i+32]=c[i]; - x[i+48]=b[i]; - x[i+64]=d[i]; + + if (s.strstart > s.block_start) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ } - var x32 = x.subarray(32); - var x16 = x.subarray(16); - inv25519(x32,x32); - M(x16,x16,x32); - pack25519(q,x16); - return 0; -} -function crypto_scalarmult_base(q, n) { - return crypto_scalarmult(q, n, _9); + return BS_NEED_MORE; } -function crypto_box_keypair(y, x) { - randombytes(x, 32); - return crypto_scalarmult_base(y, x); -} +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +function deflate_fast(s, flush) { + let hash_head; /* head of the hash chain */ + let bflush; /* set if current block must be flushed */ -function add(p, q) { - var a = gf(), b = gf(), c = gf(), - d = gf(), e = gf(), f = gf(), - g = gf(), h = gf(), t = gf(); + for (; ;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s.lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { + break; /* flush the current block */ + } + } - Z(a, p[1], p[0]); - Z(t, q[1], q[0]); - M(a, a, t); - A(b, p[0], p[1]); - A(t, q[0], q[1]); - M(b, b, t); - M(c, p[3], q[3]); - M(c, c, D2); - M(d, p[2], q[2]); - A(d, d, d); - Z(e, b, a); - Z(f, d, c); - A(g, d, c); - A(h, b, a); + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = 0/*NIL*/; + if (s.lookahead >= MIN_MATCH$1) { + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head !== 0/*NIL*/ && ((s.strstart - hash_head) <= (s.w_size - MIN_LOOKAHEAD))) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s.match_length = longest_match(s, hash_head); + /* longest_match() sets match_start */ + } + if (s.match_length >= MIN_MATCH$1) { + // check_match(s, s.strstart, s.match_start, s.match_length); // for debug only - M(p[0], e, f); - M(p[1], h, g); - M(p[2], g, f); - M(p[3], e, h); -} + /*** _tr_tally_dist(s, s.strstart - s.match_start, + s.match_length - MIN_MATCH, bflush); ***/ + bflush = _tr_tally(s, s.strstart - s.match_start, s.match_length - MIN_MATCH$1); -function cswap(p, q, b) { - var i; - for (i = 0; i < 4; i++) { - sel25519(p[i], q[i], b); - } -} + s.lookahead -= s.match_length; -function pack(r, p) { - var tx = gf(), ty = gf(), zi = gf(); - inv25519(zi, p[2]); - M(tx, p[0], zi); - M(ty, p[1], zi); - pack25519(r, ty); - r[31] ^= par25519(tx) << 7; -} + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ + if (s.match_length <= s.max_lazy_match/*max_insert_length*/ && s.lookahead >= MIN_MATCH$1) { + s.match_length--; /* string at strstart already in table */ + do { + s.strstart++; + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s.match_length !== 0); + s.strstart++; + } else { + s.strstart += s.match_length; + s.match_length = 0; + s.ins_h = s.window[s.strstart]; + /* UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]); */ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + 1]) & s.hash_mask; -function scalarmult(p, q, s) { - var b, i; - set25519(p[0], gf0); - set25519(p[1], gf1); - set25519(p[2], gf1); - set25519(p[3], gf0); - for (i = 255; i >= 0; --i) { - b = (s[(i/8)|0] >> (i&7)) & 1; - cswap(p, q, b); - add(q, p); - add(p, p); - cswap(p, q, b); + //#if MIN_MATCH != 3 + // Call UPDATE_HASH() MIN_MATCH-3 more times + //#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + //Tracevv((stderr,"%c", s.window[s.strstart])); + /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ + bflush = _tr_tally(s, 0, s.window[s.strstart]); + + s.lookahead--; + s.strstart++; + } + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + s.insert = ((s.strstart < (MIN_MATCH$1 - 1)) ? s.strstart : MIN_MATCH$1 - 1); + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ } + return BS_BLOCK_DONE; } -function scalarbase(p, s) { - var q = [gf(), gf(), gf(), gf()]; - set25519(q[0], X); - set25519(q[1], Y); - set25519(q[2], gf1); - M(q[3], X, Y); - scalarmult(p, q, s); -} +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +function deflate_slow(s, flush) { + let hash_head; /* head of hash chain */ + let bflush; /* set if current block must be flushed */ -function crypto_sign_keypair(pk, sk, seeded) { - var d; - var p = [gf(), gf(), gf(), gf()]; - var i; + let max_insert; - if (!seeded) randombytes(sk, 32); - d = nacl.hash(sk.subarray(0, 32)); - d[0] &= 248; - d[31] &= 127; - d[31] |= 64; + /* Process the input block. */ + for (; ;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s.lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { break; } /* flush the current block */ + } - scalarbase(p, d); - pack(pk, p); + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = 0/*NIL*/; + if (s.lookahead >= MIN_MATCH$1) { + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + } - for (i = 0; i < 32; i++) sk[i+32] = pk[i]; - return 0; -} + /* Find the longest match, discarding those <= prev_length. + */ + s.prev_length = s.match_length; + s.prev_match = s.match_start; + s.match_length = MIN_MATCH$1 - 1; -var L = new Float64Array([0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10]); + if (hash_head !== 0/*NIL*/ && s.prev_length < s.max_lazy_match && + s.strstart - hash_head <= (s.w_size - MIN_LOOKAHEAD)/*MAX_DIST(s)*/) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s.match_length = longest_match(s, hash_head); + /* longest_match() sets match_start */ -function modL(r, x) { - var carry, i, j, k; - for (i = 63; i >= 32; --i) { - carry = 0; - for (j = i - 32, k = i - 12; j < k; ++j) { - x[j] += carry - 16 * x[i] * L[j - (i - 32)]; - carry = (x[j] + 128) >> 8; - x[j] -= carry * 256; - } - x[j] += carry; - x[i] = 0; - } - carry = 0; - for (j = 0; j < 32; j++) { - x[j] += carry - (x[31] >> 4) * L[j]; - carry = x[j] >> 8; - x[j] &= 255; - } - for (j = 0; j < 32; j++) x[j] -= carry * L[j]; - for (i = 0; i < 32; i++) { - x[i+1] += x[i] >> 8; - r[i] = x[i] & 255; - } -} + if (s.match_length <= 5 && + (s.strategy === Z_FILTERED || (s.match_length === MIN_MATCH$1 && s.strstart - s.match_start > 4096/*TOO_FAR*/))) { -function reduce(r) { - var x = new Float64Array(64), i; - for (i = 0; i < 64; i++) x[i] = r[i]; - for (i = 0; i < 64; i++) r[i] = 0; - modL(r, x); -} + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s.match_length = MIN_MATCH$1 - 1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s.prev_length >= MIN_MATCH$1 && s.match_length <= s.prev_length) { + max_insert = s.strstart + s.lookahead - MIN_MATCH$1; + /* Do not insert strings in hash table beyond this. */ -// Note: difference from C - smlen returned, not passed as argument. -function crypto_sign(sm, m, n, sk) { - var d, h, r; - var i, j, x = new Float64Array(64); - var p = [gf(), gf(), gf(), gf()]; + //check_match(s, s.strstart-1, s.prev_match, s.prev_length); - d = nacl.hash(sk.subarray(0, 32)); - d[0] &= 248; - d[31] &= 127; - d[31] |= 64; + /***_tr_tally_dist(s, s.strstart - 1 - s.prev_match, + s.prev_length - MIN_MATCH, bflush);***/ + bflush = _tr_tally(s, s.strstart - 1 - s.prev_match, s.prev_length - MIN_MATCH$1); + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s.lookahead -= s.prev_length - 1; + s.prev_length -= 2; + do { + if (++s.strstart <= max_insert) { + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + } + } while (--s.prev_length !== 0); + s.match_available = 0; + s.match_length = MIN_MATCH$1 - 1; + s.strstart++; - var smlen = n + 64; - for (i = 0; i < n; i++) sm[64 + i] = m[i]; - for (i = 0; i < 32; i++) sm[32 + i] = d[32 + i]; + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } - r = nacl.hash(sm.subarray(32, smlen)); - reduce(r); - scalarbase(p, r); - pack(sm, p); + } else if (s.match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + //Tracevv((stderr,"%c", s->window[s->strstart-1])); + /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ + bflush = _tr_tally(s, 0, s.window[s.strstart - 1]); - for (i = 32; i < 64; i++) sm[i] = sk[i]; - h = nacl.hash(sm.subarray(0, smlen)); - reduce(h); + if (bflush) { + /*** FLUSH_BLOCK_ONLY(s, 0) ***/ + flush_block_only(s, false); + /***/ + } + s.strstart++; + s.lookahead--; + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s.match_available = 1; + s.strstart++; + s.lookahead--; + } + } + //Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s.match_available) { + //Tracevv((stderr,"%c", s->window[s->strstart-1])); + /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ + bflush = _tr_tally(s, 0, s.window[s.strstart - 1]); - for (i = 0; i < 64; i++) x[i] = 0; - for (i = 0; i < 32; i++) x[i] = r[i]; - for (i = 0; i < 32; i++) { - for (j = 0; j < 32; j++) { - x[i+j] += h[i] * d[j]; + s.match_available = 0; + } + s.insert = s.strstart < MIN_MATCH$1 - 1 ? s.strstart : MIN_MATCH$1 - 1; + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; } + /***/ } - modL(sm.subarray(32), x); - return smlen; + return BS_BLOCK_DONE; } -function unpackneg(r, p) { - var t = gf(), chk = gf(), num = gf(), - den = gf(), den2 = gf(), den4 = gf(), - den6 = gf(); - - set25519(r[2], gf1); - unpack25519(r[1], p); - S(num, r[1]); - M(den, num, D); - Z(num, num, r[2]); - A(den, r[2], den); - - S(den2, den); - S(den4, den2); - M(den6, den4, den2); - M(t, den6, num); - M(t, t, den); - - pow2523(t, t); - M(t, t, num); - M(t, t, den); - M(t, t, den); - M(r[0], t, den); - - S(chk, r[0]); - M(chk, chk, den); - if (neq25519(chk, num)) M(r[0], r[0], I); - - S(chk, r[0]); - M(chk, chk, den); - if (neq25519(chk, num)) return -1; - if (par25519(r[0]) === (p[31]>>7)) Z(r[0], gf0, r[0]); +/* =========================================================================== + * For Z_RLE, simply look for runs of bytes, generate matches only of distance + * one. Do not maintain a hash table. (It will be regenerated if this run of + * deflate switches away from Z_RLE.) + */ +function deflate_rle(s, flush) { + let bflush; /* set if current block must be flushed */ + let prev; /* byte at distance one to match */ + let scan, strend; /* scan goes up to strend for length of run */ - M(r[3], r[0], r[1]); - return 0; -} + const _win = s.window; -function crypto_sign_open(m, sm, n, pk) { - var i, mlen; - var t = new Uint8Array(32), h; - var p = [gf(), gf(), gf(), gf()], - q = [gf(), gf(), gf(), gf()]; + for (; ;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the longest run, plus one for the unrolled loop. + */ + if (s.lookahead <= MAX_MATCH$1) { + fill_window(s); + if (s.lookahead <= MAX_MATCH$1 && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { break; } /* flush the current block */ + } - mlen = -1; - if (n < 64) return -1; + /* See how many times the previous byte repeats */ + s.match_length = 0; + if (s.lookahead >= MIN_MATCH$1 && s.strstart > 0) { + scan = s.strstart - 1; + prev = _win[scan]; + if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) { + strend = s.strstart + MAX_MATCH$1; + do { + /*jshint noempty:false*/ + } while (prev === _win[++scan] && prev === _win[++scan] && + prev === _win[++scan] && prev === _win[++scan] && + prev === _win[++scan] && prev === _win[++scan] && + prev === _win[++scan] && prev === _win[++scan] && + scan < strend); + s.match_length = MAX_MATCH$1 - (strend - scan); + if (s.match_length > s.lookahead) { + s.match_length = s.lookahead; + } + } + //Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); + } - if (unpackneg(q, pk)) return -1; + /* Emit match if have run of MIN_MATCH or longer, else emit literal */ + if (s.match_length >= MIN_MATCH$1) { + //check_match(s, s.strstart, s.strstart - 1, s.match_length); - for (i = 0; i < n; i++) m[i] = sm[i]; - for (i = 0; i < 32; i++) m[i+32] = pk[i]; - h = nacl.hash(m.subarray(0, n)); - reduce(h); - scalarmult(p, q, h); + /*** _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ***/ + bflush = _tr_tally(s, 1, s.match_length - MIN_MATCH$1); - scalarbase(q, sm.subarray(32)); - add(p, q); - pack(t, p); + s.lookahead -= s.match_length; + s.strstart += s.match_length; + s.match_length = 0; + } else { + /* No match, output a literal byte */ + //Tracevv((stderr,"%c", s->window[s->strstart])); + /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ + bflush = _tr_tally(s, 0, s.window[s.strstart]); - n -= 64; - if (crypto_verify_32(sm, 0, t, 0)) { - for (i = 0; i < n; i++) m[i] = 0; - return -1; + s.lookahead--; + s.strstart++; + } + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } } - - for (i = 0; i < n; i++) m[i] = sm[i + 64]; - mlen = n; - return mlen; + s.insert = 0; + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + return BS_BLOCK_DONE; } -var crypto_scalarmult_BYTES = 32, - crypto_scalarmult_SCALARBYTES = 32, - crypto_box_PUBLICKEYBYTES = 32, - crypto_box_SECRETKEYBYTES = 32, - crypto_sign_BYTES = 64, - crypto_sign_PUBLICKEYBYTES = 32, - crypto_sign_SECRETKEYBYTES = 64, - crypto_sign_SEEDBYTES = 32; +/* =========================================================================== + * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. + * (It will be regenerated if this run of deflate switches away from Huffman.) + */ +function deflate_huff(s, flush) { + let bflush; /* set if current block must be flushed */ -function checkArrayTypes() { - for (var i = 0; i < arguments.length; i++) { - if (!(arguments[i] instanceof Uint8Array)) - throw new TypeError('unexpected type, use Uint8Array'); + for (; ;) { + /* Make sure that we have a literal to write. */ + if (s.lookahead === 0) { + fill_window(s); + if (s.lookahead === 0) { + if (flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + break; /* flush the current block */ + } + } + + /* Output a literal byte */ + s.match_length = 0; + //Tracevv((stderr,"%c", s->window[s->strstart])); + /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ + bflush = _tr_tally(s, 0, s.window[s.strstart]); + s.lookahead--; + s.strstart++; + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + s.insert = 0; + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ } + return BS_BLOCK_DONE; } -function cleanup(arr) { - for (var i = 0; i < arr.length; i++) arr[i] = 0; +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +class Config { + constructor(good_length, max_lazy, nice_length, max_chain, func) { + this.good_length = good_length; + this.max_lazy = max_lazy; + this.nice_length = nice_length; + this.max_chain = max_chain; + this.func = func; + } } +const configuration_table = [ + /* good lazy nice chain */ + new Config(0, 0, 0, 0, deflate_stored), /* 0 store only */ + new Config(4, 4, 8, 4, deflate_fast), /* 1 max speed, no lazy matches */ + new Config(4, 5, 16, 8, deflate_fast), /* 2 */ + new Config(4, 6, 32, 32, deflate_fast), /* 3 */ -nacl.scalarMult = function(n, p) { - checkArrayTypes(n, p); - if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error('bad n size'); - if (p.length !== crypto_scalarmult_BYTES) throw new Error('bad p size'); - var q = new Uint8Array(crypto_scalarmult_BYTES); - crypto_scalarmult(q, n, p); - return q; -}; - -nacl.box = {}; - -nacl.box.keyPair = function() { - var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); - var sk = new Uint8Array(crypto_box_SECRETKEYBYTES); - crypto_box_keypair(pk, sk); - return {publicKey: pk, secretKey: sk}; -}; + new Config(4, 4, 16, 16, deflate_slow), /* 4 lazy matches */ + new Config(8, 16, 32, 32, deflate_slow), /* 5 */ + new Config(8, 16, 128, 128, deflate_slow), /* 6 */ + new Config(8, 32, 128, 256, deflate_slow), /* 7 */ + new Config(32, 128, 258, 1024, deflate_slow), /* 8 */ + new Config(32, 258, 258, 4096, deflate_slow) /* 9 max compression */ +]; -nacl.box.keyPair.fromSecretKey = function(secretKey) { - checkArrayTypes(secretKey); - if (secretKey.length !== crypto_box_SECRETKEYBYTES) - throw new Error('bad secret key size'); - var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); - crypto_scalarmult_base(pk, secretKey); - return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; -}; -nacl.sign = function(msg, secretKey) { - checkArrayTypes(msg, secretKey); - if (secretKey.length !== crypto_sign_SECRETKEYBYTES) - throw new Error('bad secret key size'); - var signedMsg = new Uint8Array(crypto_sign_BYTES+msg.length); - crypto_sign(signedMsg, msg, msg.length, secretKey); - return signedMsg; -}; +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +function lm_init(s) { + s.window_size = 2 * s.w_size; -nacl.sign.detached = function(msg, secretKey) { - var signedMsg = nacl.sign(msg, secretKey); - var sig = new Uint8Array(crypto_sign_BYTES); - for (var i = 0; i < sig.length; i++) sig[i] = signedMsg[i]; - return sig; -}; + /*** CLEAR_HASH(s); ***/ + zero$2(s.head); // Fill with NIL (= 0); -nacl.sign.detached.verify = function(msg, sig, publicKey) { - checkArrayTypes(msg, sig, publicKey); - if (sig.length !== crypto_sign_BYTES) - throw new Error('bad signature size'); - if (publicKey.length !== crypto_sign_PUBLICKEYBYTES) - throw new Error('bad public key size'); - var sm = new Uint8Array(crypto_sign_BYTES + msg.length); - var m = new Uint8Array(crypto_sign_BYTES + msg.length); - var i; - for (i = 0; i < crypto_sign_BYTES; i++) sm[i] = sig[i]; - for (i = 0; i < msg.length; i++) sm[i+crypto_sign_BYTES] = msg[i]; - return (crypto_sign_open(m, sm, sm.length, publicKey) >= 0); -}; + /* Set the default configuration parameters: + */ + s.max_lazy_match = configuration_table[s.level].max_lazy; + s.good_match = configuration_table[s.level].good_length; + s.nice_match = configuration_table[s.level].nice_length; + s.max_chain_length = configuration_table[s.level].max_chain; -nacl.sign.keyPair = function() { - var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); - var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); - crypto_sign_keypair(pk, sk); - return {publicKey: pk, secretKey: sk}; -}; + s.strstart = 0; + s.block_start = 0; + s.lookahead = 0; + s.insert = 0; + s.match_length = s.prev_length = MIN_MATCH$1 - 1; + s.match_available = 0; + s.ins_h = 0; +} -nacl.sign.keyPair.fromSecretKey = function(secretKey) { - checkArrayTypes(secretKey); - if (secretKey.length !== crypto_sign_SECRETKEYBYTES) - throw new Error('bad secret key size'); - var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); - for (var i = 0; i < pk.length; i++) pk[i] = secretKey[32+i]; - return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; -}; +class DeflateState { + constructor() { + this.strm = null; /* pointer back to this zlib stream */ + this.status = 0; /* as the name implies */ + this.pending_buf = null; /* output still pending */ + this.pending_buf_size = 0; /* size of pending_buf */ + this.pending_out = 0; /* next pending byte to output to the stream */ + this.pending = 0; /* nb of bytes in the pending buffer */ + this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ + this.gzhead = null; /* gzip header information to write */ + this.gzindex = 0; /* where in extra, name, or comment */ + this.method = Z_DEFLATED; /* can only be DEFLATED */ + this.last_flush = -1; /* value of flush param for previous deflate call */ + + this.w_size = 0; /* LZ77 window size (32K by default) */ + this.w_bits = 0; /* log2(w_size) (8..16) */ + this.w_mask = 0; /* w_size - 1 */ + + this.window = null; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. + */ -nacl.sign.keyPair.fromSeed = function(seed) { - checkArrayTypes(seed); - if (seed.length !== crypto_sign_SEEDBYTES) - throw new Error('bad seed size'); - var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); - var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); - for (var i = 0; i < 32; i++) sk[i] = seed[i]; - crypto_sign_keypair(pk, sk, true); - return {publicKey: pk, secretKey: sk}; -}; + this.window_size = 0; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ -nacl.setPRNG = function(fn) { - randombytes = fn; -}; + this.prev = null; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ -(function() { - // Initialize PRNG if environment provides CSPRNG. - // If not, methods calling randombytes will throw. - var crypto = typeof self !== 'undefined' ? (self.crypto || self.msCrypto) : null; - if (crypto && crypto.getRandomValues) { - // Browsers. - var QUOTA = 65536; - nacl.setPRNG(function(x, n) { - var i, v = new Uint8Array(n); - for (i = 0; i < n; i += QUOTA) { - crypto.getRandomValues(v.subarray(i, i + Math.min(n - i, QUOTA))); - } - for (i = 0; i < n; i++) x[i] = v[i]; - cleanup(v); - }); - } else if (typeof require !== 'undefined') { - // Node.js. - crypto = require('crypto'); - if (crypto && crypto.randomBytes) { - nacl.setPRNG(function(x, n) { - var i, v = crypto.randomBytes(n); - for (i = 0; i < n; i++) x[i] = v[i]; - cleanup(v); - }); - } - } -})(); + this.head = null; /* Heads of the hash chains or NIL. */ -})(typeof module !== 'undefined' && module.exports ? module.exports : (self.nacl = self.nacl || {})); + this.ins_h = 0; /* hash index of string to be inserted */ + this.hash_size = 0; /* number of elements in hash table */ + this.hash_bits = 0; /* log2(hash_size) */ + this.hash_mask = 0; /* hash_size-1 */ -},{"crypto":"crypto"}],73:[function(require,module,exports){ -'use strict'; + this.hash_shift = 0; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.webToNode = exports.nodeToWeb = undefined; + this.block_start = 0; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ -var _util = require('./util'); + this.match_length = 0; /* length of best match */ + this.prev_match = 0; /* previous match */ + this.match_available = 0; /* set if previous match exists */ + this.strstart = 0; /* start of string to insert */ + this.match_start = 0; /* start of matching string */ + this.lookahead = 0; /* number of valid bytes ahead in window */ -var _streams = require('./streams'); + this.prev_length = 0; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ -var _streams2 = _interopRequireDefault(_streams); + this.max_chain_length = 0; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + this.max_lazy_match = 0; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ + // That's alias to max_lazy_match, don't use directly + //this.max_insert_length = 0; + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ -const NodeReadableStream = _util.isNode && require('stream').Readable; + this.level = 0; /* compression level (1..9) */ + this.strategy = 0; /* favor or force Huffman coding*/ -/** - * Web / node stream conversion functions - * From https://github.com/gwicke/node-web-streams - */ + this.good_match = 0; + /* Use a faster search when the previous match is longer than this */ -let nodeToWeb; -let webToNode; + this.nice_match = 0; /* Stop searching when current match exceeds this */ -if (NodeReadableStream) { + /* used by trees.c: */ - /** - * Convert a Node Readable Stream to a Web ReadableStream - * @param {Readable} nodeStream - * @returns {ReadableStream} - */ - exports.nodeToWeb = nodeToWeb = function nodeToWeb(nodeStream) { - return new ReadableStream({ - start(controller) { - nodeStream.pause(); - nodeStream.on('data', chunk => { - controller.enqueue(chunk); - nodeStream.pause(); - }); - nodeStream.on('end', () => controller.close()); - nodeStream.on('error', e => controller.error(e)); - }, - pull() { - nodeStream.resume(); - }, - cancel(reason) { - nodeStream.pause(); - if (nodeStream.cancel) { - return nodeStream.cancel(reason); - } - } - }); - }; + /* Didn't use ct_data typedef below to suppress compiler warning */ - class NodeReadable extends NodeReadableStream { - constructor(webStream, options) { - super(options); - this._webStream = webStream; - this._reader = _streams2.default.getReader(webStream); - this._reading = false; - this._doneReadingPromise = Promise.resolve(); - this._cancelling = false; - } + // struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + // struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + // struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ - _read(size) { - if (this._reading || this._cancelling) { - return; - } - this._reading = true; - const doRead = async () => { - try { - while (true) { - var _ref = await this._reader.read(); + // Use flat array of DOUBLE size, with interleaved fata, + // because JS does not support effective + this.dyn_ltree = new Buf16(HEAP_SIZE$1 * 2); + this.dyn_dtree = new Buf16((2 * D_CODES$1 + 1) * 2); + this.bl_tree = new Buf16((2 * BL_CODES$1 + 1) * 2); + zero$2(this.dyn_ltree); + zero$2(this.dyn_dtree); + zero$2(this.bl_tree); - const done = _ref.done, - value = _ref.value; + this.l_desc = null; /* desc. for literal tree */ + this.d_desc = null; /* desc. for distance tree */ + this.bl_desc = null; /* desc. for bit length tree */ - if (done) { - this.push(null); - break; - } - if (!this.push(value) || this._cancelling) { - this._reading = false; - break; - } - } - } catch (e) { - this.emit('error', e); - } - }; - this._doneReadingPromise = doRead(); - } + //ush bl_count[MAX_BITS+1]; + this.bl_count = new Buf16(MAX_BITS$1 + 1); + /* number of codes at each bit length for an optimal tree */ - async cancel(reason) { - this._cancelling = true; - await this._doneReadingPromise; - this._reader.releaseLock(); - return this._webStream.cancel(reason); - } - } + //int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + this.heap = new Buf16(2 * L_CODES$1 + 1); /* heap used to build the Huffman trees */ + zero$2(this.heap); - /** - * Convert a Web ReadableStream to a Node Readable Stream - * @param {ReadableStream} webStream - * @returns {Readable} - */ - exports.webToNode = webToNode = function webToNode(webStream) { - return new NodeReadable(webStream); - }; -} + this.heap_len = 0; /* number of elements in the heap */ + this.heap_max = 0; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ -exports.nodeToWeb = nodeToWeb; -exports.webToNode = webToNode; + this.depth = new Buf16(2 * L_CODES$1 + 1); //uch depth[2*L_CODES+1]; + zero$2(this.depth); + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ -},{"./streams":75,"./util":76,"stream":"stream"}],74:[function(require,module,exports){ -'use strict'; + this.l_buf = 0; /* buffer index for literals or lengths */ + + this.lit_bufsize = 0; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.externalBuffer = exports.Reader = undefined; + this.last_lit = 0; /* running index in l_buf */ -var _streams = require('./streams'); + this.d_buf = 0; + /* Buffer index for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ -var _streams2 = _interopRequireDefault(_streams); + this.opt_len = 0; /* bit length of current block with optimal trees */ + this.static_len = 0; /* bit length of current block with static trees */ + this.matches = 0; /* number of string matches in current block */ + this.insert = 0; /* bytes at end of window left to insert */ -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -const doneReadingSet = new WeakSet(); -const externalBuffer = Symbol('externalBuffer'); + this.bi_buf = 0; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + this.bi_valid = 0; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ -/** - * A wrapper class over the native ReadableStreamDefaultReader. - * This additionally implements pushing back data on the stream, which - * lets us implement peeking and a host of convenience functions. - * It also lets you read data other than streams, such as a Uint8Array. - * @class - */ -function Reader(input) { - this.stream = input; - if (input[externalBuffer]) { - this[externalBuffer] = input[externalBuffer].slice(); - } - let streamType = _streams2.default.isStream(input); - if (streamType === 'node') { - input = _streams2.default.nodeToWeb(input); - } - if (streamType) { - const reader = input.getReader(); - this._read = reader.read.bind(reader); - this._releaseLock = () => { - reader.closed.catch(function () {}); - reader.releaseLock(); - }; - return; + // Used for window memory init. We safely ignore it for JS. That makes + // sense only for pointers and memory check tools. + //this.high_water = 0; + /* High water mark offset in window for initialized bytes -- bytes above + * this are set to zero in order to avoid memory check warnings when + * longest match routines access bytes past the input. This is then + * updated to the new high water mark. + */ } - let doneReading = false; - this._read = async () => { - if (doneReading || doneReadingSet.has(input)) { - return { value: undefined, done: true }; - } - doneReading = true; - return { value: input, done: false }; - }; - this._releaseLock = () => { - if (doneReading) { - try { - doneReadingSet.add(input); - } catch (e) {} - } - }; } -/** - * Read a chunk of data. - * @returns {Promise} Either { done: false, value: Uint8Array | String } or { done: true, value: undefined } - * @async - */ -Reader.prototype.read = async function () { - if (this[externalBuffer] && this[externalBuffer].length) { - const value = this[externalBuffer].shift(); - return { done: false, value }; +function deflateResetKeep(strm) { + let s; + + if (!strm || !strm.state) { + return err(strm, Z_STREAM_ERROR); } - return this._read(); -}; -/** - * Allow others to read the stream. - */ -Reader.prototype.releaseLock = function () { - if (this[externalBuffer]) { - this.stream[externalBuffer] = this[externalBuffer]; + strm.total_in = strm.total_out = 0; + strm.data_type = Z_UNKNOWN; + + s = strm.state; + s.pending = 0; + s.pending_out = 0; + + if (s.wrap < 0) { + s.wrap = -s.wrap; + /* was made negative by deflate(..., Z_FINISH); */ + } + s.status = (s.wrap ? INIT_STATE : BUSY_STATE); + strm.adler = (s.wrap === 2) ? + 0 // crc32(0, Z_NULL, 0) + : + 1; // adler32(0, Z_NULL, 0) + s.last_flush = Z_NO_FLUSH; + _tr_init(s); + return Z_OK; +} + + +function deflateReset(strm) { + const ret = deflateResetKeep(strm); + if (ret === Z_OK) { + lm_init(strm.state); } - this._releaseLock(); -}; + return ret; +} -/** - * Read up to and including the first \n character. - * @returns {Promise} - * @async - */ -Reader.prototype.readLine = async function () { - let buffer = []; - let returnVal; - while (!returnVal) { - var _ref = await this.read(); - let done = _ref.done, - value = _ref.value; +function deflateSetHeader(strm, head) { + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + if (strm.state.wrap !== 2) { return Z_STREAM_ERROR; } + strm.state.gzhead = head; + return Z_OK; +} - value += ''; - if (done) { - if (buffer.length) return _streams2.default.concat(buffer); - return; - } - const lineEndIndex = value.indexOf('\n') + 1; - if (lineEndIndex) { - returnVal = _streams2.default.concat(buffer.concat(value.substr(0, lineEndIndex))); - buffer = []; - } - if (lineEndIndex !== value.length) { - buffer.push(value.substr(lineEndIndex)); - } - } - this.unshift(...buffer); - return returnVal; -}; -/** - * Read a single byte/character. - * @returns {Promise} - * @async - */ -Reader.prototype.readByte = async function () { - var _ref2 = await this.read(); +function deflateInit2(strm, level, method, windowBits, memLevel, strategy) { + if (!strm) { // === Z_NULL + return Z_STREAM_ERROR; + } + let wrap = 1; - const done = _ref2.done, - value = _ref2.value; + if (level === Z_DEFAULT_COMPRESSION) { + level = 6; + } - if (done) return; - const byte = value[0]; - this.unshift(_streams2.default.slice(value, 1)); - return byte; -}; + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } -/** - * Read a specific amount of bytes/characters, unless the stream ends before that amount. - * @returns {Promise} - * @async - */ -Reader.prototype.readBytes = async function (length) { - const buffer = []; - let bufferLength = 0; - while (true) { - var _ref3 = await this.read(); + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } - const done = _ref3.done, - value = _ref3.value; - if (done) { - if (buffer.length) return _streams2.default.concat(buffer); - return; - } - buffer.push(value); - bufferLength += value.length; - if (bufferLength >= length) { - const bufferConcat = _streams2.default.concat(buffer); - this.unshift(_streams2.default.slice(bufferConcat, length)); - return _streams2.default.slice(bufferConcat, 0, length); - } + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method !== Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_FIXED) { + return err(strm, Z_STREAM_ERROR); } -}; -/** - * Peek (look ahead) a specific amount of bytes/characters, unless the stream ends before that amount. - * @returns {Promise} - * @async - */ -Reader.prototype.peekBytes = async function (length) { - const bytes = await this.readBytes(length); - this.unshift(bytes); - return bytes; -}; -/** - * Push data to the front of the stream. - * @param {...(Uint8Array|String|Undefined)} values - */ -Reader.prototype.unshift = function (...values) { - if (!this[externalBuffer]) { - this[externalBuffer] = []; + if (windowBits === 8) { + windowBits = 9; } - this[externalBuffer].unshift(...values.filter(value => value && value.length)); -}; + /* until 256-byte window bug fixed */ -/** - * Read the stream to the end and return its contents, concatenated by the join function (defaults to streams.concat). - * @param {Function} join - * @returns {Promise} the return value of join() - * @async - */ -Reader.prototype.readToEnd = async function (join = _streams2.default.concat) { - const result = []; - while (true) { - var _ref4 = await this.read(); + const s = new DeflateState(); - const done = _ref4.done, - value = _ref4.value; + strm.state = s; + s.strm = strm; - if (done) break; - result.push(value); - } - return join(result); -}; + s.wrap = wrap; + s.gzhead = null; + s.w_bits = windowBits; + s.w_size = 1 << s.w_bits; + s.w_mask = s.w_size - 1; + + s.hash_bits = memLevel + 7; + s.hash_size = 1 << s.hash_bits; + s.hash_mask = s.hash_size - 1; + s.hash_shift = ~~((s.hash_bits + MIN_MATCH$1 - 1) / MIN_MATCH$1); + s.window = new Buf8(s.w_size * 2); + s.head = new Buf16(s.hash_size); + s.prev = new Buf16(s.w_size); -exports.Reader = Reader; -exports.externalBuffer = externalBuffer; + // Don't need mem init magic for JS. + //s.high_water = 0; /* nothing written to s->window yet */ -},{"./streams":75}],75:[function(require,module,exports){ -(function (process){ -'use strict'; + s.lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ -Object.defineProperty(exports, "__esModule", { - value: true -}); + s.pending_buf_size = s.lit_bufsize * 4; -var _util = require('./util'); + //overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + //s->pending_buf = (uchf *) overlay; + s.pending_buf = new Buf8(s.pending_buf_size); -var _nodeConversions = require('./node-conversions'); + // It is offset from `s.pending_buf` (size is `s.lit_bufsize * 2`) + //s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s.d_buf = 1 * s.lit_bufsize; -var _reader = require('./reader'); + //s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + s.l_buf = (1 + 2) * s.lit_bufsize; -const NodeBuffer = _util.isNode && require('buffer').Buffer; + s.level = level; + s.strategy = strategy; + s.method = method; -/** - * Convert data to Stream - * @param {ReadableStream|Uint8array|String} input data to convert - * @returns {ReadableStream} Converted data - */ -function toStream(input) { - let streamType = (0, _util.isStream)(input); - if (streamType === 'node') { - return (0, _nodeConversions.nodeToWeb)(input); - } else if (streamType) { - return input; - } - return new ReadableStream({ - start(controller) { - controller.enqueue(input); - controller.close(); - } - }); + return deflateReset(strm); } -/** - * Concat a list of Uint8Arrays, Strings or Streams - * The caller should not mix Uint8Arrays with Strings, but may mix Streams with non-Streams. - * @param {Array} Array of Uint8Arrays/Strings/Streams to concatenate - * @returns {Uint8array|String|ReadableStream} Concatenated array - */ -function concat(list) { - if (list.some(_util.isStream)) { - return concatStream(list); - } - if (typeof list[0] === 'string') { - return list.join(''); + +function deflate(strm, flush) { + let old_flush, s; + let beg, val; // for gzip header write only + + if (!strm || !strm.state || + flush > Z_BLOCK || flush < 0) { + return strm ? err(strm, Z_STREAM_ERROR) : Z_STREAM_ERROR; } - if (NodeBuffer && NodeBuffer.isBuffer(list[0])) { - return NodeBuffer.concat(list); + + s = strm.state; + + if (!strm.output || + (!strm.input && strm.avail_in !== 0) || + (s.status === FINISH_STATE && flush !== Z_FINISH)) { + return err(strm, (strm.avail_out === 0) ? Z_BUF_ERROR : Z_STREAM_ERROR); } - return (0, _util.concatUint8Array)(list); -} -/** - * Concat a list of Streams - * @param {Array} list Array of Uint8Arrays/Strings/Streams to concatenate - * @returns {ReadableStream} Concatenated list - */ -function concatStream(list) { - list = list.map(toStream); - const transform = transformWithCancel(async function (reason) { - await Promise.all(transforms.map(stream => cancel(stream, reason))); - }); - let prev = Promise.resolve(); - const transforms = list.map((stream, i) => transformPair(stream, (readable, writable) => { - prev = prev.then(() => pipe(readable, transform.writable, { - preventClose: i !== list.length - 1 - })); - return prev; - })); - return transform.readable; -} + s.strm = strm; /* just in case */ + old_flush = s.last_flush; + s.last_flush = flush; -/** - * Get a Reader - * @param {ReadableStream|Uint8array|String} input - * @returns {Reader} - */ -function getReader(input) { - return new _reader.Reader(input); -} + /* Write the header */ + if (s.status === INIT_STATE) { + + if (s.wrap === 2) { // GZIP header + strm.adler = 0; //crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (!s.gzhead) { // s->gzhead == Z_NULL + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s.level === 9 ? 2 : + (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s.status = BUSY_STATE; + } + else { + put_byte(s, (s.gzhead.text ? 1 : 0) + + (s.gzhead.hcrc ? 2 : 0) + + (!s.gzhead.extra ? 0 : 4) + + (!s.gzhead.name ? 0 : 8) + + (!s.gzhead.comment ? 0 : 16) + ); + put_byte(s, s.gzhead.time & 0xff); + put_byte(s, (s.gzhead.time >> 8) & 0xff); + put_byte(s, (s.gzhead.time >> 16) & 0xff); + put_byte(s, (s.gzhead.time >> 24) & 0xff); + put_byte(s, s.level === 9 ? 2 : + (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? + 4 : 0)); + put_byte(s, s.gzhead.os & 0xff); + if (s.gzhead.extra && s.gzhead.extra.length) { + put_byte(s, s.gzhead.extra.length & 0xff); + put_byte(s, (s.gzhead.extra.length >> 8) & 0xff); + } + if (s.gzhead.hcrc) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending, 0); + } + s.gzindex = 0; + s.status = EXTRA_STATE; + } + } + else // DEFLATE header + { + let header = (Z_DEFLATED + ((s.w_bits - 8) << 4)) << 8; + let level_flags = -1; + + if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) { + level_flags = 0; + } else if (s.level < 6) { + level_flags = 1; + } else if (s.level === 6) { + level_flags = 2; + } else { + level_flags = 3; + } + header |= (level_flags << 6); + if (s.strstart !== 0) { header |= PRESET_DICT; } + header += 31 - (header % 31); -/** - * Get a Writer - * @param {WritableStream} input - * @returns {WritableStreamDefaultWriter} - */ -function getWriter(input) { - const writer = input.getWriter(); - const releaseLock = writer.releaseLock; - writer.releaseLock = () => { - writer.closed.catch(function () {}); - releaseLock.call(writer); - }; - return writer; -} + s.status = BUSY_STATE; + putShortMSB(s, header); -/** - * Pipe a readable stream to a writable stream. Don't throw on input stream errors, but forward them to the output stream. - * @param {ReadableStream|Uint8array|String} input - * @param {WritableStream} target - * @param {Object} (optional) options - * @returns {Promise} Promise indicating when piping has finished (input stream closed or errored) - * @async - */ -async function pipe(input, target, options) { - input = toStream(input); - try { - if (input[_reader.externalBuffer]) { - const writer = getWriter(target); - for (let i = 0; i < input[_reader.externalBuffer].length; i++) { - await writer.ready; - await writer.write(input[_reader.externalBuffer][i]); + /* Save the adler32 of the preset dictionary: */ + if (s.strstart !== 0) { + putShortMSB(s, strm.adler >>> 16); + putShortMSB(s, strm.adler & 0xffff); } - writer.releaseLock(); + strm.adler = 1; // adler32(0L, Z_NULL, 0); } - return await input.pipeTo(target, options); - } catch (e) {} -} + } -/** - * Pipe a readable stream through a transform stream. - * @param {ReadableStream|Uint8array|String} input - * @param {Object} (optional) options - * @returns {ReadableStream} transformed stream - */ -function transformRaw(input, options) { - const transformStream = new TransformStream(options); - pipe(input, transformStream.writable); - return transformStream.readable; -} + //#ifdef GZIP + if (s.status === EXTRA_STATE) { + if (s.gzhead.extra/* != Z_NULL*/) { + beg = s.pending; /* start of bytes to update crc */ -/** - * Create a cancelable TransformStream. - * @param {Function} cancel - * @returns {TransformStream} - */ -function transformWithCancel(cancel) { - let pulled = false; - let backpressureChangePromiseResolve; - let outputController; - return { - readable: new ReadableStream({ - start(controller) { - outputController = controller; - }, - pull() { - if (backpressureChangePromiseResolve) { - backpressureChangePromiseResolve(); - } else { - pulled = true; - } - }, - cancel - }, { highWaterMark: 0 }), - writable: new WritableStream({ - write: async function write(chunk) { - outputController.enqueue(chunk); - if (!pulled) { - await new Promise(resolve => { - backpressureChangePromiseResolve = resolve; - }); - backpressureChangePromiseResolve = null; - } else { - pulled = false; + while (s.gzindex < (s.gzhead.extra.length & 0xffff)) { + if (s.pending === s.pending_buf_size) { + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + flush_pending(strm); + beg = s.pending; + if (s.pending === s.pending_buf_size) { + break; + } } - }, - close: outputController.close.bind(outputController), - abort: outputController.error.bind(outputController) - }) - }; -} + put_byte(s, s.gzhead.extra[s.gzindex] & 0xff); + s.gzindex++; + } + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + if (s.gzindex === s.gzhead.extra.length) { + s.gzindex = 0; + s.status = NAME_STATE; + } + } + else { + s.status = NAME_STATE; + } + } + if (s.status === NAME_STATE) { + if (s.gzhead.name/* != Z_NULL*/) { + beg = s.pending; /* start of bytes to update crc */ + //int val; -/** - * Transform a stream using helper functions which are called on each chunk, and on stream close, respectively. - * @param {ReadableStream|Uint8array|String} input - * @param {Function} process - * @param {Function} finish - * @returns {ReadableStream|Uint8array|String} - */ -function transform(input, process = () => undefined, finish = () => undefined) { - if ((0, _util.isStream)(input)) { - return transformRaw(input, { - async transform(value, controller) { - try { - const result = await process(value); - if (result !== undefined) controller.enqueue(result); - } catch (e) { - controller.error(e); + do { + if (s.pending === s.pending_buf_size) { + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + flush_pending(strm); + beg = s.pending; + if (s.pending === s.pending_buf_size) { + val = 1; + break; + } } - }, - async flush(controller) { - try { - const result = await finish(); - if (result !== undefined) controller.enqueue(result); - } catch (e) { - controller.error(e); + // JS specific: little magic to add zero terminator to end of string + if (s.gzindex < s.gzhead.name.length) { + val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff; + } else { + val = 0; } - } - }); - } - const result1 = process(input); - const result2 = finish(); - if (result1 !== undefined && result2 !== undefined) return concat([result1, result2]); - return result1 !== undefined ? result1 : result2; -} + put_byte(s, val); + } while (val !== 0); -/** - * Transform a stream using a helper function which is passed a readable and a writable stream. - * This function also maintains the possibility to cancel the input stream, - * and does so on cancelation of the output stream, despite cancelation - * normally being impossible when the input stream is being read from. - * @param {ReadableStream|Uint8array|String} input - * @param {Function} fn - * @returns {ReadableStream} - */ -function transformPair(input, fn) { - let incomingTransformController; - const incoming = new TransformStream({ - start(controller) { - incomingTransformController = controller; + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + if (val === 0) { + s.gzindex = 0; + s.status = COMMENT_STATE; + } } - }); - - const pipeDonePromise = pipe(input, incoming.writable); - - const outgoing = transformWithCancel(async function () { - incomingTransformController.error(new Error('Readable side was canceled.')); - await pipeDonePromise; - await new Promise(setTimeout); - }); - fn(incoming.readable, outgoing.writable); - return outgoing.readable; -} + else { + s.status = COMMENT_STATE; + } + } + if (s.status === COMMENT_STATE) { + if (s.gzhead.comment/* != Z_NULL*/) { + beg = s.pending; /* start of bytes to update crc */ + //int val; -/** - * Parse a stream using a helper function which is passed a Reader. - * The reader additionally has a remainder() method which returns a - * stream pointing to the remainder of input, and is linked to input - * for cancelation. - * @param {ReadableStream|Uint8array|String} input - * @param {Function} fn - * @returns {Any} the return value of fn() - */ -function parse(input, fn) { - let returnValue; - const transformed = transformPair(input, (readable, writable) => { - const reader = getReader(readable); - reader.remainder = () => { - reader.releaseLock(); - pipe(readable, writable); - return transformed; - }; - returnValue = fn(reader); - }); - return returnValue; -} + do { + if (s.pending === s.pending_buf_size) { + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + flush_pending(strm); + beg = s.pending; + if (s.pending === s.pending_buf_size) { + val = 1; + break; + } + } + // JS specific: little magic to add zero terminator to end of string + if (s.gzindex < s.gzhead.comment.length) { + val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff; + } else { + val = 0; + } + put_byte(s, val); + } while (val !== 0); -/** - * Tee a Stream for reading it twice. The input stream can no longer be read after tee()ing. - * Reading either of the two returned streams will pull from the input stream. - * The input stream will only be canceled if both of the returned streams are canceled. - * @param {ReadableStream|Uint8array|String} input - * @returns {Array} array containing two copies of input - */ -function tee(input) { - if ((0, _util.isStream)(input)) { - const teed = toStream(input).tee(); - teed[0][_reader.externalBuffer] = teed[1][_reader.externalBuffer] = input[_reader.externalBuffer]; - return teed; + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + if (val === 0) { + s.status = HCRC_STATE; + } + } + else { + s.status = HCRC_STATE; + } } - return [slice(input), slice(input)]; -} - -/** - * Clone a Stream for reading it twice. The input stream can still be read after clone()ing. - * Reading from the clone will pull from the input stream. - * The input stream will only be canceled if both the clone and the input stream are canceled. - * @param {ReadableStream|Uint8array|String} input - * @returns {ReadableStream|Uint8array|String} cloned input - */ -function clone(input) { - if ((0, _util.isStream)(input)) { - const teed = tee(input); - overwrite(input, teed[0]); - return teed[1]; + if (s.status === HCRC_STATE) { + if (s.gzhead.hcrc) { + if (s.pending + 2 > s.pending_buf_size) { + flush_pending(strm); + } + if (s.pending + 2 <= s.pending_buf_size) { + put_byte(s, strm.adler & 0xff); + put_byte(s, (strm.adler >> 8) & 0xff); + strm.adler = 0; //crc32(0L, Z_NULL, 0); + s.status = BUSY_STATE; + } + } + else { + s.status = BUSY_STATE; + } } - return slice(input); -} + //#endif -/** - * Clone a Stream for reading it twice. Data will arrive at the same rate as the input stream is being read. - * Reading from the clone will NOT pull from the input stream. Data only arrives when reading the input stream. - * The input stream will NOT be canceled if the clone is canceled, only if the input stream are canceled. - * If the input stream is canceled, the clone will be errored. - * @param {ReadableStream|Uint8array|String} input - * @returns {ReadableStream|Uint8array|String} cloned input - */ -function passiveClone(input) { - if ((0, _util.isStream)(input)) { - return new ReadableStream({ - start(controller) { - const transformed = transformPair(input, async (readable, writable) => { - const reader = getReader(readable); - const writer = getWriter(writable); - try { - while (true) { - await writer.ready; - - var _ref = await reader.read(); + /* Flush as much pending output as possible */ + if (s.pending !== 0) { + flush_pending(strm); + if (strm.avail_out === 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s.last_flush = -1; + return Z_OK; + } - const done = _ref.done, - value = _ref.value; + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) && + flush !== Z_FINISH) { + return err(strm, Z_BUF_ERROR); + } - if (done) { - try { - controller.close(); - } catch (e) {} - await writer.close(); - return; - } - try { - controller.enqueue(value); - } catch (e) {} - await writer.write(value); - } - } catch (e) { - controller.error(e); - await writer.abort(e); - } - }); - overwrite(input, transformed); - } - }); + /* User must not provide more input after the first FINISH: */ + if (s.status === FINISH_STATE && strm.avail_in !== 0) { + return err(strm, Z_BUF_ERROR); } - return slice(input); -} -/** - * Modify a stream object to point to a different stream object. - * This is used internally by clone() and passiveClone() to provide an abstraction over tee(). - * @param {ReadableStream} input - * @param {ReadableStream} clone - */ -function overwrite(input, clone) { - // Overwrite input.getReader, input.locked, etc to point to clone - Object.entries(Object.getOwnPropertyDescriptors(ReadableStream.prototype)).forEach(([name, descriptor]) => { - if (name === 'constructor') { - return; + /* Start a new block or continue the current one. + */ + if (strm.avail_in !== 0 || s.lookahead !== 0 || + (flush !== Z_NO_FLUSH && s.status !== FINISH_STATE)) { + var bstate = (s.strategy === Z_HUFFMAN_ONLY) ? deflate_huff(s, flush) : + (s.strategy === Z_RLE ? deflate_rle(s, flush) : + configuration_table[s.level].func(s, flush)); + + if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) { + s.status = FINISH_STATE; } - if (descriptor.value) { - descriptor.value = descriptor.value.bind(clone); - } else { - descriptor.get = descriptor.get.bind(clone); + if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) { + if (strm.avail_out === 0) { + s.last_flush = -1; + /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ } - Object.defineProperty(input, name, descriptor); - }); -} + if (bstate === BS_BLOCK_DONE) { + if (flush === Z_PARTIAL_FLUSH) { + _tr_align(s); + } + else if (flush !== Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ -/** - * Return a stream pointing to a part of the input stream. - * @param {ReadableStream|Uint8array|String} input - * @returns {ReadableStream|Uint8array|String} clone - */ -function slice(input, begin = 0, end = Infinity) { - if ((0, _util.isStream)(input)) { - if (begin >= 0 && end >= 0) { - let bytesRead = 0; - return transformRaw(input, { - transform(value, controller) { - if (bytesRead < end) { - if (bytesRead + value.length >= begin) { - controller.enqueue(slice(value, Math.max(begin - bytesRead, 0), end - bytesRead)); - } - bytesRead += value.length; - } else { - controller.terminate(); + _tr_stored_block(s, 0, 0, false); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush === Z_FULL_FLUSH) { + /*** CLEAR_HASH(s); ***/ /* forget history */ + zero$2(s.head); // Fill with NIL (= 0); + + if (s.lookahead === 0) { + s.strstart = 0; + s.block_start = 0; + s.insert = 0; } } - }); - } - if (begin < 0 && (end < 0 || end === Infinity)) { - let lastBytes = []; - return transform(input, value => { - if (value.length >= -begin) lastBytes = [value];else lastBytes.push(value); - }, () => slice(concat(lastBytes), begin, end)); - } - if (begin === 0 && end < 0) { - let lastBytes; - return transform(input, value => { - const returnValue = lastBytes ? concat([lastBytes, value]) : value; - if (returnValue.length >= -end) { - lastBytes = slice(returnValue, end); - return slice(returnValue, begin, end); - } else { - lastBytes = returnValue; - } - }); + } + flush_pending(strm); + if (strm.avail_out === 0) { + s.last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } } - console.warn(`stream.slice(input, ${begin}, ${end}) not implemented efficiently.`); - return fromAsync(async () => slice((await readToEnd(input)), begin, end)); } - if (input[_reader.externalBuffer]) { - input = concat(input[_reader.externalBuffer].concat([input])); + //Assert(strm->avail_out > 0, "bug2"); + //if (strm.avail_out <= 0) { throw new Error("bug2");} + + if (flush !== Z_FINISH) { return Z_OK; } + if (s.wrap <= 0) { return Z_STREAM_END; } + + /* Write the trailer */ + if (s.wrap === 2) { + put_byte(s, strm.adler & 0xff); + put_byte(s, (strm.adler >> 8) & 0xff); + put_byte(s, (strm.adler >> 16) & 0xff); + put_byte(s, (strm.adler >> 24) & 0xff); + put_byte(s, strm.total_in & 0xff); + put_byte(s, (strm.total_in >> 8) & 0xff); + put_byte(s, (strm.total_in >> 16) & 0xff); + put_byte(s, (strm.total_in >> 24) & 0xff); } - if ((0, _util.isUint8Array)(input) && !(NodeBuffer && NodeBuffer.isBuffer(input))) { - if (end === Infinity) end = input.length; - return input.subarray(begin, end); + else { + putShortMSB(s, strm.adler >>> 16); + putShortMSB(s, strm.adler & 0xffff); } - return input.slice(begin, end); -} -/** - * Read a stream to the end and return its contents, concatenated by the concat function (defaults to concat). - * @param {ReadableStream|Uint8array|String} input - * @param {Function} concat - * @returns {Promise} the return value of concat() - * @async - */ -async function readToEnd(input, concat) { - if ((0, _util.isStream)(input)) { - return getReader(input).readToEnd(concat); - } - return input; + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s.wrap > 0) { s.wrap = -s.wrap; } + /* write the trailer only once! */ + return s.pending !== 0 ? Z_OK : Z_STREAM_END; } -/** - * Cancel a stream. - * @param {ReadableStream|Uint8array|String} input - * @param {Any} reason - * @returns {Promise} indicates when the stream has been canceled - * @async - */ -async function cancel(input, reason) { - if ((0, _util.isStream)(input) && input.cancel) { - return input.cancel(reason); - } -} +function deflateEnd(strm) { + let status; -/** - * Convert an async function to a Stream. When the function returns, its return value is enqueued to the stream. - * @param {Function} fn - * @returns {ReadableStream} - */ -function fromAsync(fn) { - return new ReadableStream({ - pull: async controller => { - try { - controller.enqueue((await fn())); - controller.close(); - } catch (e) { - controller.error(e); - } - } - }); -} + if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) { + return Z_STREAM_ERROR; + } -exports.default = { isStream: _util.isStream, isUint8Array: _util.isUint8Array, toStream, concatUint8Array: _util.concatUint8Array, concatStream, concat, getReader, getWriter, pipe, transformRaw, transform, transformPair, parse, clone, passiveClone, slice, readToEnd, cancel, fromAsync, nodeToWeb: _nodeConversions.nodeToWeb, webToNode: _nodeConversions.webToNode }; + status = strm.state.status; + if (status !== INIT_STATE && + status !== EXTRA_STATE && + status !== NAME_STATE && + status !== COMMENT_STATE && + status !== HCRC_STATE && + status !== BUSY_STATE && + status !== FINISH_STATE + ) { + return err(strm, Z_STREAM_ERROR); + } -}).call(this,require('_process')) -},{"./node-conversions":73,"./reader":74,"./util":76,"_process":66,"buffer":"buffer"}],76:[function(require,module,exports){ -(function (global){ -'use strict'; + strm.state = null; -Object.defineProperty(exports, "__esModule", { - value: true -}); -const isNode = typeof global.process === 'object' && typeof global.process.versions === 'object'; + return status === BUSY_STATE ? err(strm, Z_DATA_ERROR) : Z_OK; +} -const NodeReadableStream = isNode && require('stream').Readable; -/** - * Check whether data is a Stream, and if so of which type - * @param {Any} input data to check - * @returns {'web'|'node'|false} +/* ========================================================================= + * Initializes the compression dictionary from the given byte + * sequence without producing any compressed output. */ -function isStream(input) { - if (ReadableStream.prototype.isPrototypeOf(input)) { - return 'web'; +function deflateSetDictionary(strm, dictionary) { + let dictLength = dictionary.length; + + let s; + let str, n; + let wrap; + let avail; + let next; + let input; + let tmpDict; + + if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) { + return Z_STREAM_ERROR; } - if (NodeReadableStream && NodeReadableStream.prototype.isPrototypeOf(input)) { - return 'node'; + + s = strm.state; + wrap = s.wrap; + + if (wrap === 2 || (wrap === 1 && s.status !== INIT_STATE) || s.lookahead) { + return Z_STREAM_ERROR; } - return false; -} -/** - * Check whether data is a Uint8Array - * @param {Any} input data to check - * @returns {Boolean} - */ -function isUint8Array(input) { - return Uint8Array.prototype.isPrototypeOf(input); -} + /* when using zlib wrappers, compute Adler-32 for provided dictionary */ + if (wrap === 1) { + /* adler32(strm->adler, dictionary, dictLength); */ + strm.adler = adler32(strm.adler, dictionary, dictLength, 0); + } -/** - * Concat Uint8Arrays - * @param {Array} Array of Uint8Arrays to concatenate - * @returns {Uint8array} Concatenated array - */ -function concatUint8Array(arrays) { - if (arrays.length === 1) return arrays[0]; + s.wrap = 0; /* avoid computing Adler-32 in read_buf */ - let totalLength = 0; - for (let i = 0; i < arrays.length; i++) { - if (!isUint8Array(arrays[i])) { - throw new Error('concatUint8Array: Data must be in the form of a Uint8Array'); + /* if dictionary would fill window, just replace the history */ + if (dictLength >= s.w_size) { + if (wrap === 0) { /* already empty otherwise */ + /*** CLEAR_HASH(s); ***/ + zero$2(s.head); // Fill with NIL (= 0); + s.strstart = 0; + s.block_start = 0; + s.insert = 0; } + /* use the tail */ + // dictionary = dictionary.slice(dictLength - s.w_size); + tmpDict = new Buf8(s.w_size); + arraySet(tmpDict, dictionary, dictLength - s.w_size, s.w_size, 0); + dictionary = tmpDict; + dictLength = s.w_size; + } + /* insert dictionary into window and hash */ + avail = strm.avail_in; + next = strm.next_in; + input = strm.input; + strm.avail_in = dictLength; + strm.next_in = 0; + strm.input = dictionary; + fill_window(s); + while (s.lookahead >= MIN_MATCH$1) { + str = s.strstart; + n = s.lookahead - (MIN_MATCH$1 - 1); + do { + /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH$1 - 1]) & s.hash_mask; - totalLength += arrays[i].length; + s.prev[str & s.w_mask] = s.head[s.ins_h]; + + s.head[s.ins_h] = str; + str++; + } while (--n); + s.strstart = str; + s.lookahead = MIN_MATCH$1 - 1; + fill_window(s); } + s.strstart += s.lookahead; + s.block_start = s.strstart; + s.insert = s.lookahead; + s.lookahead = 0; + s.match_length = s.prev_length = MIN_MATCH$1 - 1; + s.match_available = 0; + strm.next_in = next; + strm.input = input; + strm.avail_in = avail; + s.wrap = wrap; + return Z_OK; +} - const result = new Uint8Array(totalLength); - let pos = 0; - arrays.forEach(function (element) { - result.set(element, pos); - pos += element.length; - }); +/* Not implemented +exports.deflateBound = deflateBound; +exports.deflateCopy = deflateCopy; +exports.deflateParams = deflateParams; +exports.deflatePending = deflatePending; +exports.deflatePrime = deflatePrime; +exports.deflateTune = deflateTune; +*/ - return result; +// String encode/decode helpers + +try { + String.fromCharCode.apply(null, [ 0 ]); +} catch (__) { +} +try { + String.fromCharCode.apply(null, new Uint8Array(1)); +} catch (__) { } -exports.isNode = isNode; -exports.isStream = isStream; -exports.isUint8Array = isUint8Array; -exports.concatUint8Array = concatUint8Array; -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"stream":"stream"}],77:[function(require,module,exports){ -'use strict'; +// Table with utf8 lengths (calculated by first byte of sequence) +// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS, +// because max possible codepoint is 0x10ffff +const _utf8len = new Buf8(256); +for (let q = 0; q < 256; q++) { + _utf8len[q] = q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1; +} +_utf8len[254] = _utf8len[254] = 1; // Invalid sequence start -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.CleartextMessage = CleartextMessage; -exports.readArmored = readArmored; -exports.fromText = fromText; -var _armor = require('./encoding/armor'); +// convert string to array (typed, when possible) +function string2buf (str) { + let c, c2, m_pos, i, buf_len = 0; + const str_len = str.length; + + // count binary size + for (m_pos = 0; m_pos < str_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && m_pos + 1 < str_len) { + c2 = str.charCodeAt(m_pos + 1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + (c - 0xd800 << 10) + (c2 - 0xdc00); + m_pos++; + } + } + buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4; + } + + // allocate buffer + const buf = new Buf8(buf_len); -var _armor2 = _interopRequireDefault(_armor); + // convert + for (i = 0, m_pos = 0; i < buf_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && m_pos + 1 < str_len) { + c2 = str.charCodeAt(m_pos + 1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + (c - 0xd800 << 10) + (c2 - 0xdc00); + m_pos++; + } + } + if (c < 0x80) { + /* one byte */ + buf[i++] = c; + } else if (c < 0x800) { + /* two bytes */ + buf[i++] = 0xC0 | c >>> 6; + buf[i++] = 0x80 | c & 0x3f; + } else if (c < 0x10000) { + /* three bytes */ + buf[i++] = 0xE0 | c >>> 12; + buf[i++] = 0x80 | c >>> 6 & 0x3f; + buf[i++] = 0x80 | c & 0x3f; + } else { + /* four bytes */ + buf[i++] = 0xf0 | c >>> 18; + buf[i++] = 0x80 | c >>> 12 & 0x3f; + buf[i++] = 0x80 | c >>> 6 & 0x3f; + buf[i++] = 0x80 | c & 0x3f; + } + } -var _enums = require('./enums'); + return buf; +} -var _enums2 = _interopRequireDefault(_enums); -var _util = require('./util'); +// Convert binary string (typed, when possible) +function binstring2buf (str) { + const buf = new Buf8(str.length); + for (let i = 0, len = buf.length; i < len; i++) { + buf[i] = str.charCodeAt(i); + } + return buf; +} -var _util2 = _interopRequireDefault(_util); +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. -var _packet = require('./packet'); +class ZStream { + constructor() { + /* next input byte */ + this.input = null; // JS specific, because we have no pointers + this.next_in = 0; + /* number of bytes available at input */ + this.avail_in = 0; + /* total number of input bytes read so far */ + this.total_in = 0; + /* next output byte should be put there */ + this.output = null; // JS specific, because we have no pointers + this.next_out = 0; + /* remaining free space at output */ + this.avail_out = 0; + /* total number of bytes output so far */ + this.total_out = 0; + /* last error message, NULL if no error */ + this.msg = ''/*Z_NULL*/; + /* not visible by applications */ + this.state = null; + /* best guess about the data type: binary or text */ + this.data_type = 2/*Z_UNKNOWN*/; + /* adler32 value of the uncompressed data */ + this.adler = 0; + } +} -var _packet2 = _interopRequireDefault(_packet); +/* ===========================================================================*/ -var _signature = require('./signature'); -var _message = require('./message'); +/** + * class Deflate + * + * Generic JS-style wrapper for zlib calls. If you don't need + * streaming behaviour - use more simple functions: [[deflate]], + * [[deflateRaw]] and [[gzip]]. + **/ -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +/* internal + * Deflate.chunks -> Array + * + * Chunks of output data, if [[Deflate#onData]] not overridden. + **/ /** - * @class - * @classdesc Class that represents an OpenPGP cleartext signed message. - * See {@link https://tools.ietf.org/html/rfc4880#section-7} - * @param {String} text The cleartext of the signed message - * @param {module:signature.Signature} signature The detached signature or an empty signature for unsigned messages - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Deflate.result -> Uint8Array|Array + * + * Compressed result, generated by default [[Deflate#onData]] + * and [[Deflate#onEnd]] handlers. Filled after you push last chunk + * (call [[Deflate#push]] with `Z_FINISH` / `true` param) or if you + * push a chunk with explicit flush (call [[Deflate#push]] with + * `Z_SYNC_FLUSH` param). + **/ /** - * @requires encoding/armor - * @requires enums - * @requires util - * @requires packet - * @requires signature - * @module cleartext - */ + * Deflate.err -> Number + * + * Error code after deflate finished. 0 (Z_OK) on success. + * You will not need it in real life, because deflate errors + * are possible only on wrong options or bad `onData` / `onEnd` + * custom handlers. + **/ + +/** + * Deflate.msg -> String + * + * Error message, if [[Deflate.err]] != 0 + **/ + + +/** + * new Deflate(options) + * - options (Object): zlib deflate options. + * + * Creates new deflator instance with specified params. Throws exception + * on bad params. Supported options: + * + * - `level` + * - `windowBits` + * - `memLevel` + * - `strategy` + * - `dictionary` + * + * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) + * for more information on these. + * + * Additional options, for internal needs: + * + * - `chunkSize` - size of generated data chunks (16K by default) + * - `raw` (Boolean) - do raw deflate + * - `gzip` (Boolean) - create gzip wrapper + * - `to` (String) - if equal to 'string', then result will be "binary string" + * (each char code [0..255]) + * - `header` (Object) - custom header for gzip + * - `text` (Boolean) - true if compressed data believed to be text + * - `time` (Number) - modification time, unix timestamp + * - `os` (Number) - operation system code + * - `extra` (Array) - array of bytes with extra data (max 65536) + * - `name` (String) - file name (binary string) + * - `comment` (String) - comment (binary string) + * - `hcrc` (Boolean) - true if header crc should be added + * + * ##### Example: + * + * ```javascript + * var pako = require('pako') + * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9]) + * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]); + * + * var deflate = new pako.Deflate({ level: 3}); + * + * deflate.push(chunk1, false); + * deflate.push(chunk2, true); // true -> last chunk + * + * if (deflate.err) { throw new Error(deflate.err); } + * + * console.log(deflate.result); + * ``` + **/ -function CleartextMessage(text, signature) { - if (!(this instanceof CleartextMessage)) { - return new CleartextMessage(text, signature); - } - // normalize EOL to canonical form - this.text = _util2.default.canonicalizeEOL(_util2.default.removeTrailingSpaces(text)); - if (signature && !(signature instanceof _signature.Signature)) { - throw new Error('Invalid signature input'); - } - this.signature = signature || new _signature.Signature(new _packet2.default.List()); -} +class Deflate { + constructor(options) { + this.options = { + level: Z_DEFAULT_COMPRESSION, + method: Z_DEFLATED, + chunkSize: 16384, + windowBits: 15, + memLevel: 8, + strategy: Z_DEFAULT_STRATEGY, + ...(options || {}) + }; -/** - * Returns the key IDs of the keys that signed the cleartext message - * @returns {Array} array of keyid objects - */ -CleartextMessage.prototype.getSigningKeyIds = function () { - const keyIds = []; - const signatureList = this.signature.packets; - signatureList.forEach(function (packet) { - keyIds.push(packet.issuerKeyId); - }); - return keyIds; -}; + const opt = this.options; -/** - * Sign the cleartext message - * @param {Array} privateKeys private keys with decrypted secret key data for signing - * @param {Signature} signature (optional) any existing detached signature - * @param {Date} date (optional) The creation time of the signature that should be created - * @param {Array} userIds (optional) user IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] - * @returns {Promise} new cleartext message with signed content - * @async - */ -CleartextMessage.prototype.sign = async function (privateKeys, signature = null, date = new Date(), userIds = []) { - return new CleartextMessage(this.text, (await this.signDetached(privateKeys, signature, date, userIds))); -}; + if (opt.raw && (opt.windowBits > 0)) { + opt.windowBits = -opt.windowBits; + } -/** - * Sign the cleartext message - * @param {Array} privateKeys private keys with decrypted secret key data for signing - * @param {Signature} signature (optional) any existing detached signature - * @param {Date} date (optional) The creation time of the signature that should be created - * @param {Array} userIds (optional) user IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] - * @returns {Promise} new detached signature of message content - * @async - */ -CleartextMessage.prototype.signDetached = async function (privateKeys, signature = null, date = new Date(), userIds = []) { - const literalDataPacket = new _packet2.default.Literal(); - literalDataPacket.setText(this.text); + else if (opt.gzip && (opt.windowBits > 0) && (opt.windowBits < 16)) { + opt.windowBits += 16; + } - return new _signature.Signature((await (0, _message.createSignaturePackets)(literalDataPacket, privateKeys, signature, date, userIds, true))); -}; + this.err = 0; // error code, if happens (0 = Z_OK) + this.msg = ''; // error message + this.ended = false; // used to avoid multiple onEnd() calls + this.chunks = []; // chunks of compressed data -/** - * Verify signatures of cleartext signed message - * @param {Array} keys array of keys to verify signatures - * @param {Date} date (optional) Verify the signature against the given date, i.e. check signature creation time < date < expiration time - * @returns {Promise>} list of signer's keyid and validity of signature - * @async - */ -CleartextMessage.prototype.verify = function (keys, date = new Date()) { - return this.verifyDetached(this.signature, keys, date); -}; + this.strm = new ZStream(); + this.strm.avail_out = 0; -/** - * Verify signatures of cleartext signed message - * @param {Array} keys array of keys to verify signatures - * @param {Date} date (optional) Verify the signature against the given date, i.e. check signature creation time < date < expiration time - * @returns {Promise>} list of signer's keyid and validity of signature - * @async - */ -CleartextMessage.prototype.verifyDetached = function (signature, keys, date = new Date()) { - const signatureList = signature.packets; - const literalDataPacket = new _packet2.default.Literal(); - // we assume that cleartext signature is generated based on UTF8 cleartext - literalDataPacket.setText(this.text); - return (0, _message.createVerificationObjects)(signatureList, [literalDataPacket], keys, date, true); -}; + var status = deflateInit2( + this.strm, + opt.level, + opt.method, + opt.windowBits, + opt.memLevel, + opt.strategy + ); -/** - * Get cleartext - * @returns {String} cleartext of message - */ -CleartextMessage.prototype.getText = function () { - // normalize end of line to \n - return _util2.default.nativeEOL(this.text); -}; + if (status !== Z_OK) { + throw new Error(msg[status]); + } -/** - * Returns ASCII armored text of cleartext signed message - * @returns {String | ReadableStream} ASCII armor - */ -CleartextMessage.prototype.armor = function () { - let hashes = this.signature.packets.map(function (packet) { - return _enums2.default.read(_enums2.default.hash, packet.hashAlgorithm).toUpperCase(); - }); - hashes = hashes.filter(function (item, i, ar) { - return ar.indexOf(item) === i; - }); - const body = { - hash: hashes.join(), - text: this.text, - data: this.signature.packets.write() - }; - return _armor2.default.encode(_enums2.default.armor.signed, body); -}; + if (opt.header) { + deflateSetHeader(this.strm, opt.header); + } -/** - * reads an OpenPGP cleartext signed message and returns a CleartextMessage object - * @param {String | ReadableStream} armoredText text to be parsed - * @returns {module:cleartext.CleartextMessage} new cleartext message object - * @async - * @static - */ -async function readArmored(armoredText) { - const input = await _armor2.default.decode(armoredText); - if (input.type !== _enums2.default.armor.signed) { - throw new Error('No cleartext signed message.'); - } - const packetlist = new _packet2.default.List(); - await packetlist.read(input.data); - verifyHeaders(input.headers, packetlist); - const signature = new _signature.Signature(packetlist); - return new CleartextMessage(input.text, signature); -} + if (opt.dictionary) { + let dict; + // Convert data if needed + if (typeof opt.dictionary === 'string') { + // If we need to compress text, change encoding to utf8. + dict = string2buf(opt.dictionary); + } else if (opt.dictionary instanceof ArrayBuffer) { + dict = new Uint8Array(opt.dictionary); + } else { + dict = opt.dictionary; + } -/** - * Compare hash algorithm specified in the armor header with signatures - * @param {Array} headers Armor headers - * @param {module:packet.List} packetlist The packetlist with signature packets - * @private - */ -function verifyHeaders(headers, packetlist) { - const checkHashAlgos = function checkHashAlgos(hashAlgos) { - const check = packet => algo => packet.hashAlgorithm === algo; + status = deflateSetDictionary(this.strm, dict); - for (let i = 0; i < packetlist.length; i++) { - if (packetlist[i].tag === _enums2.default.packet.signature && !hashAlgos.some(check(packetlist[i]))) { - return false; + if (status !== Z_OK) { + throw new Error(msg[status]); } - } - return true; - }; - let oneHeader = null; - let hashAlgos = []; - headers.forEach(function (header) { - oneHeader = header.match(/Hash: (.+)/); // get header value - if (oneHeader) { - oneHeader = oneHeader[1].replace(/\s/g, ''); // remove whitespace - oneHeader = oneHeader.split(','); - oneHeader = oneHeader.map(function (hash) { - hash = hash.toLowerCase(); - try { - return _enums2.default.write(_enums2.default.hash, hash); - } catch (e) { - throw new Error('Unknown hash algorithm in armor header: ' + hash); - } - }); - hashAlgos = hashAlgos.concat(oneHeader); - } else { - throw new Error('Only "Hash" header allowed in cleartext signed message'); + this._dict_set = true; } - }); - - if (!hashAlgos.length && !checkHashAlgos([_enums2.default.hash.md5])) { - throw new Error('If no "Hash" header in cleartext signed message, then only MD5 signatures allowed'); - } else if (hashAlgos.length && !checkHashAlgos(hashAlgos)) { - throw new Error('Hash algorithm mismatch in armor header and signature'); } -} -/** - * Creates a new CleartextMessage object from text - * @param {String} text - * @static - */ -function fromText(text) { - return new CleartextMessage(text); -} + /** + * Deflate#push(data[, mode]) -> Boolean + * - data (Uint8Array|Array|ArrayBuffer|String): input data. Strings will be + * converted to utf8 byte sequence. + * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. + * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH. + * + * Sends input data to deflate pipe, generating [[Deflate#onData]] calls with + * new compressed chunks. Returns `true` on success. The last data block must have + * mode Z_FINISH (or `true`). That will flush internal pending buffers and call + * [[Deflate#onEnd]]. For interim explicit flushes (without ending the stream) you + * can use mode Z_SYNC_FLUSH, keeping the compression context. + * + * On fail call [[Deflate#onEnd]] with error code and return false. + * + * We strongly recommend to use `Uint8Array` on input for best speed (output + * array format is detected automatically). Also, don't skip last param and always + * use the same type in your code (boolean or number). That will improve JS speed. + * + * For regular `Array`-s make sure all elements are [0..255]. + * + * ##### Example + * + * ```javascript + * push(chunk, false); // push one of data chunks + * ... + * push(chunk, true); // push last chunk + * ``` + **/ + push(data, mode) { + const { strm, options: { chunkSize } } = this; + var status, _mode; -},{"./encoding/armor":111,"./enums":113,"./message":120,"./packet":125,"./signature":145,"./util":152}],78:[function(require,module,exports){ -"use strict"; + if (this.ended) { return false; } -Object.defineProperty(exports, "__esModule", { - value: true -}); + _mode = (mode === ~~mode) ? mode : ((mode === true) ? Z_FINISH : Z_NO_FLUSH); + + // Convert data if needed + if (typeof data === 'string') { + // If we need to compress text, change encoding to utf8. + strm.input = string2buf(data); + } else if (data instanceof ArrayBuffer) { + strm.input = new Uint8Array(data); + } else { + strm.input = data; + } -var _enums = require("../enums"); + strm.next_in = 0; + strm.avail_in = strm.input.length; -var _enums2 = _interopRequireDefault(_enums); + do { + if (strm.avail_out === 0) { + strm.output = new Buf8(chunkSize); + strm.next_out = 0; + strm.avail_out = chunkSize; + } + status = deflate(strm, _mode); /* no bad return value */ -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + if (status !== Z_STREAM_END && status !== Z_OK) { + this.onEnd(status); + this.ended = true; + return false; + } + if (strm.avail_out === 0 || (strm.avail_in === 0 && (_mode === Z_FINISH || _mode === Z_SYNC_FLUSH))) { + this.onData(shrinkBuf(strm.output, strm.next_out)); + } + } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== Z_STREAM_END); -exports.default = { - /** - * @memberof module:config - * @property {Integer} prefer_hash_algorithm Default hash algorithm {@link module:enums.hash} - */ - prefer_hash_algorithm: _enums2.default.hash.sha256, - /** - * @memberof module:config - * @property {Integer} encryption_cipher Default encryption cipher {@link module:enums.symmetric} - */ - encryption_cipher: _enums2.default.symmetric.aes256, - /** - * @memberof module:config - * @property {Integer} compression Default compression algorithm {@link module:enums.compression} - */ - compression: _enums2.default.compression.uncompressed, - /** - * @memberof module:config - * @property {Integer} deflate_level Default zip/zlib compression level, between 1 and 9 - */ - deflate_level: 6, + // Finalize on the last chunk. + if (_mode === Z_FINISH) { + status = deflateEnd(this.strm); + this.onEnd(status); + this.ended = true; + return status === Z_OK; + } - /** - * Use Authenticated Encryption with Additional Data (AEAD) protection for symmetric encryption. - * **NOT INTEROPERABLE WITH OTHER OPENPGP IMPLEMENTATIONS** - * **FUTURE OPENPGP.JS VERSIONS MAY BREAK COMPATIBILITY WHEN USING THIS OPTION** - * @see {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-07|RFC4880bis-07} - * @memberof module:config - * @property {Boolean} aead_protect - */ - aead_protect: false, - /** - * Default Authenticated Encryption with Additional Data (AEAD) encryption mode - * Only has an effect when aead_protect is set to true. - * @memberof module:config - * @property {Integer} aead_mode Default AEAD mode {@link module:enums.aead} - */ - aead_mode: _enums2.default.aead.eax, - /** - * Chunk Size Byte for Authenticated Encryption with Additional Data (AEAD) mode - * Only has an effect when aead_protect is set to true. - * Must be an integer value from 0 to 56. - * @memberof module:config - * @property {Integer} aead_chunk_size_byte - */ - aead_chunk_size_byte: 12, - /** - * Use V5 keys. - * **NOT INTEROPERABLE WITH OTHER OPENPGP IMPLEMENTATIONS** - * **FUTURE OPENPGP.JS VERSIONS MAY BREAK COMPATIBILITY WHEN USING THIS OPTION** - * @memberof module:config - * @property {Boolean} v5_keys - */ - v5_keys: false, - /** - * {@link https://tools.ietf.org/html/rfc4880#section-3.7.1.3|RFC4880 3.7.1.3}: - * Iteration Count Byte for S2K (String to Key) - * @memberof module:config - * @property {Integer} s2k_iteration_count_byte - */ - s2k_iteration_count_byte: 224, - /** Use integrity protection for symmetric encryption - * @memberof module:config - * @property {Boolean} integrity_protect - */ - integrity_protect: true, - /** - * @memberof module:config - * @property {Boolean} ignore_mdc_error Fail on decrypt if message is not integrity protected - */ - ignore_mdc_error: false, - /** - * @memberof module:config - * @property {Boolean} allow_unauthenticated_stream Stream unauthenticated data before integrity has been checked - */ - allow_unauthenticated_stream: false, - /** - * @memberof module:config - * @property {Boolean} checksum_required Do not throw error when armor is missing a checksum - */ - checksum_required: false, - /** - * @memberof module:config - * @property {Boolean} rsa_blinding - */ - rsa_blinding: true, - /** - * Work-around for rare GPG decryption bug when encrypting with multiple passwords. - * **Slower and slightly less secure** - * @memberof module:config - * @property {Boolean} password_collision_check - */ - password_collision_check: false, - /** - * @memberof module:config - * @property {Boolean} revocations_expire If true, expired revocation signatures are ignored - */ - revocations_expire: false, + // callback interim results if Z_SYNC_FLUSH. + if (_mode === Z_SYNC_FLUSH) { + this.onEnd(Z_OK); + strm.avail_out = 0; + return true; + } + return true; + }; /** - * @memberof module:config - * @property {Boolean} use_native Use native Node.js crypto/zlib and WebCrypto APIs when available - */ - use_native: true, - /** - * @memberof module:config - * @property {Integer} min_bytes_for_web_crypto The minimum amount of bytes for which to use native WebCrypto APIs when available - */ - min_bytes_for_web_crypto: 1000, - /** - * @memberof module:config - * @property {Boolean} Use transferable objects between the Web Worker and main thread - */ - zero_copy: false, - /** - * @memberof module:config - * @property {Boolean} debug If enabled, debug messages will be printed - */ - debug: false, - /** - * @memberof module:config - * @property {Boolean} tolerant Ignore unsupported/unrecognizable packets instead of throwing an error - */ - tolerant: true, + * Deflate#onData(chunk) -> Void + * - chunk (Uint8Array|Array|String): output data. Type of array depends + * on js engine support. When string output requested, each chunk + * will be string. + * + * By default, stores data blocks in `chunks[]` property and glue + * those in `onEnd`. Override this handler, if you need another behaviour. + **/ + onData(chunk) { + this.chunks.push(chunk); + }; /** - * @memberof module:config - * @property {Boolean} show_version Whether to include {@link module:config/config.versionstring} in armored messages - */ - show_version: true, - /** - * @memberof module:config - * @property {Boolean} show_comment Whether to include {@link module:config/config.commentstring} in armored messages - */ - show_comment: true, - /** - * @memberof module:config - * @property {String} versionstring A version string to be included in armored messages - */ - versionstring: "OpenPGP.js v4.6.0", - /** - * @memberof module:config - * @property {String} commentstring A comment string to be included in armored messages - */ - commentstring: "https://openpgpjs.org", + * Deflate#onEnd(status) -> Void + * - status (Number): deflate status. 0 (Z_OK) on success, + * other if not. + * + * Called once after you tell deflate that the input stream is + * complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH) + * or if an error happened. By default - join collected chunks, + * free memory and fill `results` / `err` properties. + **/ + onEnd(status) { + // On success - join + if (status === Z_OK) { + this.result = flattenChunks(this.chunks); + } + this.chunks = []; + this.err = status; + this.msg = this.strm.msg; + }; +} - /** - * @memberof module:config - * @property {String} keyserver - */ - keyserver: "https://keyserver.ubuntu.com", - /** - * @memberof module:config - * @property {String} node_store - */ - node_store: "./openpgp.store", - /** - * Max userid string length (used for parsing) - * @memberof module:config - * @property {Integer} max_userid_length - */ - max_userid_length: 1024 * 5, - /** - * Contains notatations that are considered "known". Known notations do not trigger - * validation error when the notation is marked as critical. - * @memberof module:config - * @property {Array} known_notations - */ - known_notations: ["preferred-email-encoding@pgp.com", "pka-address@gnupg.org"] -}; // GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin // -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. // -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: // -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. -/** - * Global configuration values. - * @requires enums +// See state defs from inflate.js +const BAD = 30; /* got a data error -- remain here until reset */ +const TYPE = 12; /* i: waiting for type bits, including last-flag bit */ + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state.mode === LEN + strm.avail_in >= 6 + strm.avail_out >= 258 + start >= strm.avail_out + state.bits < 8 + + On return, state.mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm.avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm.avail_out >= 258 for each loop to avoid checking for + output space. */ +function inflate_fast(strm, start) { + let _in; /* local strm.input */ + let _out; /* local strm.output */ + // Use `s_window` instead `window`, avoid conflict with instrumentation tools + let hold; /* local strm.hold */ + let bits; /* local strm.bits */ + let here; /* retrieved table entry */ + let op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + let len; /* match length, unused bytes */ + let dist; /* match distance */ + let from; /* where to copy match from */ + let from_source; + + + + /* copy state to local variables */ + const state = strm.state; + //here = state.here; + _in = strm.next_in; + const input = strm.input; + const last = _in + (strm.avail_in - 5); + _out = strm.next_out; + const output = strm.output; + const beg = _out - (start - strm.avail_out); + const end = _out + (strm.avail_out - 257); + //#ifdef INFLATE_STRICT + const dmax = state.dmax; + //#endif + const wsize = state.wsize; + const whave = state.whave; + const wnext = state.wnext; + const s_window = state.window; + hold = state.hold; + bits = state.bits; + const lcode = state.lencode; + const dcode = state.distcode; + const lmask = (1 << state.lenbits) - 1; + const dmask = (1 << state.distbits) - 1; + + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ -},{"../enums":113}],79:[function(require,module,exports){ -'use strict'; + top: + do { + if (bits < 15) { + hold += input[_in++] << bits; + bits += 8; + hold += input[_in++] << bits; + bits += 8; + } -Object.defineProperty(exports, "__esModule", { - value: true -}); + here = lcode[hold & lmask]; -var _config = require('./config.js'); + dolen: + for (;;) { // Goto emulation + op = here >>> 24/*here.bits*/; + hold >>>= op; + bits -= op; + op = here >>> 16 & 0xff/*here.op*/; + if (op === 0) { /* literal */ + //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + // "inflate: literal '%c'\n" : + // "inflate: literal 0x%02x\n", here.val)); + output[_out++] = here & 0xffff/*here.val*/; + } else if (op & 16) { /* length base */ + len = here & 0xffff/*here.val*/; + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + } + len += hold & (1 << op) - 1; + hold >>>= op; + bits -= op; + } + //Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += input[_in++] << bits; + bits += 8; + hold += input[_in++] << bits; + bits += 8; + } + here = dcode[hold & dmask]; + + dodist: + for (;;) { // goto emulation + op = here >>> 24/*here.bits*/; + hold >>>= op; + bits -= op; + op = here >>> 16 & 0xff/*here.op*/; + + if (op & 16) { /* distance base */ + dist = here & 0xffff/*here.val*/; + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + } + } + dist += hold & (1 << op) - 1; + //#ifdef INFLATE_STRICT + if (dist > dmax) { + strm.msg = "invalid distance too far back"; + state.mode = BAD; + break top; + } + //#endif + hold >>>= op; + bits -= op; + //Tracevv((stderr, "inflate: distance %u\n", dist)); + op = _out - beg; /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state.sane) { + strm.msg = "invalid distance too far back"; + state.mode = BAD; + break top; + } + + // (!) This block is disabled in zlib defaults, + // don't enable it for binary compatibility + //#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + // if (len <= op - whave) { + // do { + // output[_out++] = 0; + // } while (--len); + // continue top; + // } + // len -= op - whave; + // do { + // output[_out++] = 0; + // } while (--op > whave); + // if (op === 0) { + // from = _out - dist; + // do { + // output[_out++] = output[from++]; + // } while (--len); + // continue top; + // } + //#endif + } + from = 0; // window index + from_source = s_window; + if (wnext === 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } else if (wnext < op) { /* wrap around window */ + from += wsize + wnext - op; + op -= wnext; + if (op < len) { /* some from end of window */ + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = 0; + if (wnext < len) { /* some from start of window */ + op = wnext; + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } + } else { /* contiguous in window */ + from += wnext - op; + if (op < len) { /* some from window */ + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } + while (len > 2) { + output[_out++] = from_source[from++]; + output[_out++] = from_source[from++]; + output[_out++] = from_source[from++]; + len -= 3; + } + if (len) { + output[_out++] = from_source[from++]; + if (len > 1) { + output[_out++] = from_source[from++]; + } + } + } else { + from = _out - dist; /* copy direct from output */ + do { /* minimum length is three */ + output[_out++] = output[from++]; + output[_out++] = output[from++]; + output[_out++] = output[from++]; + len -= 3; + } while (len > 2); + if (len) { + output[_out++] = output[from++]; + if (len > 1) { + output[_out++] = output[from++]; + } + } + } + } else if ((op & 64) === 0) { /* 2nd level distance code */ + here = dcode[(here & 0xffff)/*here.val*/ + (hold & (1 << op) - 1)]; + continue dodist; + } else { + strm.msg = "invalid distance code"; + state.mode = BAD; + break top; + } -Object.defineProperty(exports, 'default', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_config).default; - } -}); + break; // need to emulate goto via "continue" + } + } else if ((op & 64) === 0) { /* 2nd level length code */ + here = lcode[(here & 0xffff)/*here.val*/ + (hold & (1 << op) - 1)]; + continue dolen; + } else if (op & 32) { /* end-of-block */ + //Tracevv((stderr, "inflate: end of block\n")); + state.mode = TYPE; + break top; + } else { + strm.msg = "invalid literal/length code"; + state.mode = BAD; + break top; + } -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + break; // need to emulate goto via "continue" + } + } while (_in < last && _out < end); -},{"./config.js":78}],80:[function(require,module,exports){ -'use strict'; + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + _in -= len; + bits -= len << 3; + hold &= (1 << bits) - 1; -Object.defineProperty(exports, "__esModule", { - value: true -}); + /* update state and return */ + strm.next_in = _in; + strm.next_out = _out; + strm.avail_in = _in < last ? 5 + (last - _in) : 5 - (_in - last); + strm.avail_out = _out < end ? 257 + (end - _out) : 257 - (_out - end); + state.hold = hold; + state.bits = bits; + return; +} -var _cipher = require('./cipher'); +const MAXBITS = 15; +const ENOUGH_LENS = 852; +const ENOUGH_DISTS = 592; +//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); -var _cipher2 = _interopRequireDefault(_cipher); +const CODES = 0; +const LENS = 1; +const DISTS = 2; -var _util = require('../util'); +const lbase = [ /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 +]; -var _util2 = _interopRequireDefault(_util); +const lext = [ /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78 +]; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +const dbase = [ /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0 +]; -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2015-2016 Decentral -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +const dext = [ /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64 +]; -/** - * @fileoverview Implementation of RFC 3394 AES Key Wrap & Key Unwrap funcions - * @see module:crypto/public_key/elliptic/ecdh - * @requires crypto/cipher - * @requires util - * @module crypto/aes_kw - */ +function inflate_table(type, lens, lens_index, codes, table, table_index, work, opts) { + const bits = opts.bits; + //here = opts.here; /* table entry for duplication */ + + let len = 0; /* a code's length in bits */ + let sym = 0; /* index of code symbols */ + let min = 0, max = 0; /* minimum and maximum code lengths */ + let root = 0; /* number of index bits for root table */ + let curr = 0; /* number of index bits for current table */ + let drop = 0; /* code bits to drop for sub-table */ + let left = 0; /* number of prefix codes available */ + let used = 0; /* code entries in table used */ + let huff = 0; /* Huffman code */ + let incr; /* for incrementing code, index */ + let fill; /* index for replicating entries */ + let low; /* low bits for current root entry */ + let next; /* next available space in table */ + let base = null; /* base value table to use */ + let base_index = 0; + // var shoextra; /* extra bits table to use */ + let end; /* use base and extra for symbol > end */ + const count = new Buf16(MAXBITS + 1); //[MAXBITS+1]; /* number of codes of each length */ + const offs = new Buf16(MAXBITS + 1); //[MAXBITS+1]; /* offsets in table for each length */ + let extra = null; + let extra_index = 0; + + let here_bits, here_op, here_val; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. -function wrap(key, data) { - const aes = new _cipher2.default["aes" + key.length * 8](key); - const IV = new Uint32Array([0xA6A6A6A6, 0xA6A6A6A6]); - const P = unpack(data); - let A = IV; - const R = P; - const n = P.length / 2; - const t = new Uint32Array([0, 0]); - let B = new Uint32Array(4); - for (let j = 0; j <= 5; ++j) { - for (let i = 0; i < n; ++i) { - t[1] = n * j + (1 + i); - // B = A - B[0] = A[0]; - B[1] = A[1]; - // B = A || R[i] - B[2] = R[2 * i]; - B[3] = R[2 * i + 1]; - // B = AES(K, B) - B = unpack(aes.encrypt(pack(B))); - // A = MSB(64, B) ^ t - A = B.subarray(0, 2); - A[0] ^= t[0]; - A[1] ^= t[1]; - // R[i] = LSB(64, B) - R[2 * i] = B[2]; - R[2 * i + 1] = B[3]; + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) { + count[len] = 0; + } + for (sym = 0; sym < codes; sym++) { + count[lens[lens_index + sym]]++; } - } - return pack(A, R); -} -function unwrap(key, data) { - const aes = new _cipher2.default["aes" + key.length * 8](key); - const IV = new Uint32Array([0xA6A6A6A6, 0xA6A6A6A6]); - const C = unpack(data); - let A = C.subarray(0, 2); - const R = C.subarray(2); - const n = C.length / 2 - 1; - const t = new Uint32Array([0, 0]); - let B = new Uint32Array(4); - for (let j = 5; j >= 0; --j) { - for (let i = n - 1; i >= 0; --i) { - t[1] = n * j + (i + 1); - // B = A ^ t - B[0] = A[0] ^ t[0]; - B[1] = A[1] ^ t[1]; - // B = (A ^ t) || R[i] - B[2] = R[2 * i]; - B[3] = R[2 * i + 1]; - // B = AES-1(B) - B = unpack(aes.decrypt(pack(B))); - // A = MSB(64, B) - A = B.subarray(0, 2); - // R[i] = LSB(64, B) - R[2 * i] = B[2]; - R[2 * i + 1] = B[3]; + /* bound code lengths, force root to be within code lengths */ + root = bits; + for (max = MAXBITS; max >= 1; max--) { + if (count[max] !== 0) { + break; + } } - } - if (A[0] === IV[0] && A[1] === IV[1]) { - return pack(R); - } - throw new Error("Key Data Integrity failed"); -} + if (root > max) { + root = max; + } + if (max === 0) { /* no symbols to code at all */ + //table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */ + //table.bits[opts.table_index] = 1; //here.bits = (var char)1; + //table.val[opts.table_index++] = 0; //here.val = (var short)0; + table[table_index++] = 1 << 24 | 64 << 16 | 0; + + + //table.op[opts.table_index] = 64; + //table.bits[opts.table_index] = 1; + //table.val[opts.table_index++] = 0; + table[table_index++] = 1 << 24 | 64 << 16 | 0; + + opts.bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min < max; min++) { + if (count[min] !== 0) { + break; + } + } + if (root < min) { + root = min; + } + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) { + return -1; + } /* over-subscribed */ + } + if (left > 0 && (type === CODES || max !== 1)) { + return -1; /* incomplete set */ + } + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) { + offs[len + 1] = offs[len] + count[len]; + } + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) { + if (lens[lens_index + sym] !== 0) { + work[offs[lens[lens_index + sym]]++] = sym; + } + } + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftrees.h + for more information. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + // poor man optimization - use if-else instead of switch, + // to avoid deopts in old v8 + if (type === CODES) { + base = extra = work; /* dummy value--not used */ + end = 19; + + } else if (type === LENS) { + base = lbase; + base_index -= 257; + extra = lext; + extra_index -= 257; + end = 256; + + } else { /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize opts for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = table_index; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = -1; /* trigger new sub-table when len > root */ + used = 1 << root; /* use root table entries */ + const mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if (type === LENS && used > ENOUGH_LENS || + type === DISTS && used > ENOUGH_DISTS) { + return 1; + } + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + here_bits = len - drop; + if (work[sym] < end) { + here_op = 0; + here_val = work[sym]; + } else if (work[sym] > end) { + here_op = extra[extra_index + work[sym]]; + here_val = base[base_index + work[sym]]; + } else { + here_op = 32 + 64; /* end of block */ + here_val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1 << len - drop; + fill = 1 << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + table[next + (huff >> drop) + fill] = here_bits << 24 | here_op << 16 | here_val |0; + } while (fill !== 0); + + /* backwards increment the len-bit code huff */ + incr = 1 << len - 1; + while (huff & incr) { + incr >>= 1; + } + if (incr !== 0) { + huff &= incr - 1; + huff += incr; + } else { + huff = 0; + } -function createArrayBuffer(data) { - if (_util2.default.isString(data)) { - const length = data.length; + /* go to next symbol, update count, len */ + sym++; + if (--count[len] === 0) { + if (len === max) { + break; + } + len = lens[lens_index + work[sym]]; + } - const buffer = new ArrayBuffer(length); - const view = new Uint8Array(buffer); - for (let j = 0; j < length; ++j) { - view[j] = data.charCodeAt(j); - } - return buffer; - } - return new Uint8Array(data).buffer; -} + /* create new sub-table if needed */ + if (len > root && (huff & mask) !== low) { + /* if first time, transition to sub-tables */ + if (drop === 0) { + drop = root; + } -function unpack(data) { - const length = data.length; + /* increment past last table */ + next += min; /* here min is 1 << curr */ - const buffer = createArrayBuffer(data); - const view = new DataView(buffer); - const arr = new Uint32Array(length / 4); - for (let i = 0; i < length / 4; ++i) { - arr[i] = view.getUint32(4 * i); - } - return arr; -} + /* determine length of next table */ + curr = len - drop; + left = 1 << curr; + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) { + break; + } + curr++; + left <<= 1; + } -function pack() { - let length = 0; - for (let k = 0; k < arguments.length; ++k) { - length += 4 * arguments[k].length; - } - const buffer = new ArrayBuffer(length); - const view = new DataView(buffer); - let offset = 0; - for (let i = 0; i < arguments.length; ++i) { - for (let j = 0; j < arguments[i].length; ++j) { - view.setUint32(offset + 4 * j, arguments[i][j]); + /* check for enough space */ + used += 1 << curr; + if (type === LENS && used > ENOUGH_LENS || + type === DISTS && used > ENOUGH_DISTS) { + return 1; + } + + /* point entry in root table to sub-table */ + low = huff & mask; + /*table.op[low] = curr; + table.bits[low] = root; + table.val[low] = next - opts.table_index;*/ + table[low] = root << 24 | curr << 16 | next - table_index |0; + } } - offset += 4 * arguments[i].length; - } - return new Uint8Array(buffer); + + /* fill in remaining table entry if code is incomplete (guaranteed to have + at most one remaining entry, since if the code is incomplete, the + maximum code length that was allowed to get this far is one bit) */ + if (huff !== 0) { + //table.op[next + huff] = 64; /* invalid code marker */ + //table.bits[next + huff] = len - drop; + //table.val[next + huff] = 0; + table[next + huff] = len - drop << 24 | 64 << 16 |0; + } + + /* set return parameters */ + //opts.table_index += used; + opts.bits = root; + return 0; } -exports.default = { - /** - * AES key wrap - * @function - * @param {String} key - * @param {String} data - * @returns {Uint8Array} - */ - wrap, - /** - * AES key unwrap - * @function - * @param {String} key - * @param {String} data - * @returns {Uint8Array} - * @throws {Error} - */ - unwrap -}; +const CODES$1 = 0; +const LENS$1 = 1; +const DISTS$1 = 2; -},{"../util":152,"./cipher":86}],81:[function(require,module,exports){ -'use strict'; +/* STATES ====================================================================*/ +/* ===========================================================================*/ -Object.defineProperty(exports, "__esModule", { - value: true -}); -var _cfb = require('asmcrypto.js/dist_es5/aes/cfb'); +const HEAD = 1; /* i: waiting for magic header */ +const FLAGS = 2; /* i: waiting for method and flags (gzip) */ +const TIME = 3; /* i: waiting for modification time (gzip) */ +const OS = 4; /* i: waiting for extra flags and operating system (gzip) */ +const EXLEN = 5; /* i: waiting for extra length (gzip) */ +const EXTRA = 6; /* i: waiting for extra bytes (gzip) */ +const NAME = 7; /* i: waiting for end of file name (gzip) */ +const COMMENT = 8; /* i: waiting for end of comment (gzip) */ +const HCRC = 9; /* i: waiting for header crc (gzip) */ +const DICTID = 10; /* i: waiting for dictionary check value */ +const DICT = 11; /* waiting for inflateSetDictionary() call */ +const TYPE$1 = 12; /* i: waiting for type bits, including last-flag bit */ +const TYPEDO = 13; /* i: same, but skip check to exit inflate on new block */ +const STORED = 14; /* i: waiting for stored size (length and complement) */ +const COPY_ = 15; /* i/o: same as COPY below, but only first time in */ +const COPY = 16; /* i/o: waiting for input or output to copy stored block */ +const TABLE = 17; /* i: waiting for dynamic block table lengths */ +const LENLENS = 18; /* i: waiting for code length code lengths */ +const CODELENS = 19; /* i: waiting for length/lit and distance code lengths */ +const LEN_ = 20; /* i: same as LEN below, but only first time in */ +const LEN = 21; /* i: waiting for length/lit/eob code */ +const LENEXT = 22; /* i: waiting for length extra bits */ +const DIST = 23; /* i: waiting for distance code */ +const DISTEXT = 24; /* i: waiting for distance extra bits */ +const MATCH = 25; /* o: waiting for output space to copy string */ +const LIT = 26; /* o: waiting for output space to write literal */ +const CHECK = 27; /* i: waiting for 32-bit check value */ +const LENGTH = 28; /* i: waiting for 32-bit length (gzip) */ +const DONE = 29; /* finished check, done -- remain here until reset */ +const BAD$1 = 30; /* got a data error -- remain here until reset */ +//const MEM = 31; /* got an inflate() memory error -- remain here until reset */ +const SYNC = 32; /* looking for synchronization bytes to restart inflate() */ -var _webStreamTools = require('web-stream-tools'); +/* ===========================================================================*/ -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); -var _cipher = require('./cipher'); -var _cipher2 = _interopRequireDefault(_cipher); +const ENOUGH_LENS$1 = 852; +const ENOUGH_DISTS$1 = 592; -var _config = require('../config'); -var _config2 = _interopRequireDefault(_config); +function zswap32(q) { + return (((q >>> 24) & 0xff) + + ((q >>> 8) & 0xff00) + + ((q & 0xff00) << 8) + + ((q & 0xff) << 24)); +} -var _util = require('../util'); -var _util2 = _interopRequireDefault(_util); +class InflateState { + constructor() { + this.mode = 0; /* current inflate mode */ + this.last = false; /* true if processing last block */ + this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ + this.havedict = false; /* true if dictionary provided */ + this.flags = 0; /* gzip header method and flags (0 if zlib) */ + this.dmax = 0; /* zlib header max distance (INFLATE_STRICT) */ + this.check = 0; /* protected copy of check value */ + this.total = 0; /* protected copy of output count */ + // TODO: may be {} + this.head = null; /* where to save gzip header information */ + + /* sliding window */ + this.wbits = 0; /* log base 2 of requested window size */ + this.wsize = 0; /* window size or zero if not using window */ + this.whave = 0; /* valid bytes in the window */ + this.wnext = 0; /* window write index */ + this.window = null; /* allocated sliding window, if needed */ + + /* bit accumulator */ + this.hold = 0; /* input bit accumulator */ + this.bits = 0; /* number of bits in "in" */ + + /* for string and stored block copying */ + this.length = 0; /* literal or length of data to copy */ + this.offset = 0; /* distance back to copy string from */ + + /* for table and code decoding */ + this.extra = 0; /* extra bits needed */ + + /* fixed and dynamic code tables */ + this.lencode = null; /* starting table for length/literal codes */ + this.distcode = null; /* starting table for distance codes */ + this.lenbits = 0; /* index bits for lencode */ + this.distbits = 0; /* index bits for distcode */ + + /* dynamic table building */ + this.ncode = 0; /* number of code length code lengths */ + this.nlen = 0; /* number of length code lengths */ + this.ndist = 0; /* number of distance code lengths */ + this.have = 0; /* number of code lengths in lens[] */ + this.next = null; /* next available space in codes[] */ + + this.lens = new Buf16(320); /* temporary storage for code lengths */ + this.work = new Buf16(288); /* work area for code table building */ + + /* + because we don't have pointers in js, we use lencode and distcode directly + as buffers so we don't need codes + */ + //this.codes = new utils.Buf32(ENOUGH); /* space for code tables */ + this.lendyn = null; /* dynamic table for length/literal codes (JS specific) */ + this.distdyn = null; /* dynamic table for distance codes (JS specific) */ + this.sane = 0; /* if false, allow invalid distance too far */ + this.back = 0; /* bits back of last unprocessed length/lit */ + this.was = 0; /* initial length of match */ + } +} -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +function inflateResetKeep(strm) { + let state; -const webCrypto = _util2.default.getWebCrypto(); // Modified by ProtonTech AG + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + strm.total_in = strm.total_out = state.total = 0; + strm.msg = ''; /*Z_NULL*/ + if (state.wrap) { /* to support ill-conceived Java test suite */ + strm.adler = state.wrap & 1; + } + state.mode = HEAD; + state.last = 0; + state.havedict = 0; + state.dmax = 32768; + state.head = null/*Z_NULL*/; + state.hold = 0; + state.bits = 0; + //state.lencode = state.distcode = state.next = state.codes; + state.lencode = state.lendyn = new Buf32(ENOUGH_LENS$1); + state.distcode = state.distdyn = new Buf32(ENOUGH_DISTS$1); -// Modified by Recurity Labs GmbH + state.sane = 1; + state.back = -1; + //Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} -// modified version of https://www.hanewin.net/encrypt/PGdecode.js: +function inflateReset(strm) { + let state; -/* OpenPGP encryption using RSA/AES - * Copyright 2005-2006 Herbert Hanewinkel, www.haneWIN.de - * version 2.0, check www.haneWIN.de for the latest version + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + state.wsize = 0; + state.whave = 0; + state.wnext = 0; + return inflateResetKeep(strm); - * This software is provided as-is, without express or implied warranty. - * Permission to use, copy, modify, distribute or sell this software, with or - * without fee, for any purpose and by any individual or organization, is hereby - * granted, provided that the above copyright notice and this paragraph appear - * in all copies. Distribution as a part of an application or binary must - * include the above copyright notice in the documentation and/or other - * materials provided with the application or distribution. - */ +} -/** - * @requires web-stream-tools - * @requires crypto/cipher - * @requires util - * @module crypto/cfb - */ +function inflateReset2(strm, windowBits) { + let wrap; + let state; -const nodeCrypto = _util2.default.getNodeCrypto(); -const Buffer = _util2.default.getNodeBuffer(); + /* get the state */ + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; -exports.default = { - encrypt: function encrypt(algo, key, plaintext, iv) { - if (algo.substr(0, 3) === 'aes') { - return aesEncrypt(algo, key, plaintext, iv); + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } + else { + wrap = (windowBits >> 4) + 1; + if (windowBits < 48) { + windowBits &= 15; } + } + + /* set number of window bits, free window if different */ + if (windowBits && (windowBits < 8 || windowBits > 15)) { + return Z_STREAM_ERROR; + } + if (state.window !== null && state.wbits !== windowBits) { + state.window = null; + } - const cipherfn = new _cipher2.default[algo](key); - const block_size = cipherfn.blockSize; + /* update state and reset the rest of it */ + state.wrap = wrap; + state.wbits = windowBits; + return inflateReset(strm); +} - let blocki = new Uint8Array(block_size); - const blockc = iv; - let pos = 0; - const ciphertext = new Uint8Array(plaintext.length); - let i; - let j = 0; +function inflateInit2(strm, windowBits) { + let ret; + let state; - while (plaintext.length > block_size * pos) { - const encblock = cipherfn.encrypt(blockc); - blocki = plaintext.subarray(pos * block_size, pos * block_size + block_size); - for (i = 0; i < blocki.length; i++) { - blockc[i] = blocki[i] ^ encblock[i]; - ciphertext[j++] = blockc[i]; - } - pos++; - } - return ciphertext; - }, + if (!strm) { return Z_STREAM_ERROR; } + //strm.msg = Z_NULL; /* in case we return an error */ - decrypt: async function decrypt(algo, key, ciphertext, iv) { - if (algo.substr(0, 3) === 'aes') { - return aesDecrypt(algo, key, ciphertext, iv); - } + state = new InflateState(); - ciphertext = await _webStreamTools2.default.readToEnd(ciphertext); + //if (state === Z_NULL) return Z_MEM_ERROR; + //Tracev((stderr, "inflate: allocated\n")); + strm.state = state; + state.window = null/*Z_NULL*/; + ret = inflateReset2(strm, windowBits); + if (ret !== Z_OK) { + strm.state = null/*Z_NULL*/; + } + return ret; +} - const cipherfn = new _cipher2.default[algo](key); - const block_size = cipherfn.blockSize; - let blockp = iv; - let pos = 0; - const plaintext = new Uint8Array(ciphertext.length); - const offset = 0; - let i; - let j = 0; +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +let virgin = true; - while (ciphertext.length > block_size * pos) { - const decblock = cipherfn.encrypt(blockp); - blockp = ciphertext.subarray(pos * block_size + offset, pos * block_size + block_size + offset); - for (i = 0; i < blockp.length; i++) { - plaintext[j++] = blockp[i] ^ decblock[i]; - } - pos++; - } +let lenfix, distfix; // We have no pointers in JS, so keep tables separate - return plaintext; - } -}; +function fixedtables(state) { + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + let sym; + lenfix = new Buf32(512); + distfix = new Buf32(32); -function aesEncrypt(algo, key, pt, iv) { - if (_util2.default.getWebCrypto() && key.length !== 24 && // Chrome doesn't support 192 bit keys, see https://www.chromium.org/blink/webcrypto#TOC-AES-support - !_util2.default.isStream(pt) && pt.length >= 3000 * _config2.default.min_bytes_for_web_crypto // Default to a 3MB minimum. Chrome is pretty slow for small messages, see: https://bugs.chromium.org/p/chromium/issues/detail?id=701188#c2 - ) { - // Web Crypto - return webEncrypt(algo, key, pt, iv); - } - if (nodeCrypto) { - // Node crypto library. - return nodeEncrypt(algo, key, pt, iv); - } // asm.js fallback - const cfb = new _cfb.AES_CFB(key, iv); - return _webStreamTools2.default.transform(pt, value => cfb.AES_Encrypt_process(value), () => cfb.AES_Encrypt_finish()); -} + /* literal/length table */ + sym = 0; + while (sym < 144) { state.lens[sym++] = 8; } + while (sym < 256) { state.lens[sym++] = 9; } + while (sym < 280) { state.lens[sym++] = 7; } + while (sym < 288) { state.lens[sym++] = 8; } -function aesDecrypt(algo, key, ct, iv) { - if (nodeCrypto) { - // Node crypto library. - return nodeDecrypt(algo, key, ct, iv); - } - if (_util2.default.isStream(ct)) { - const cfb = new _cfb.AES_CFB(key, iv); - return _webStreamTools2.default.transform(ct, value => cfb.AES_Decrypt_process(value), () => cfb.AES_Decrypt_finish()); - } - return _cfb.AES_CFB.decrypt(ct, key, iv); -} + inflate_table(LENS$1, state.lens, 0, 288, lenfix, 0, state.work, { bits: 9 }); -function xorMut(a, b) { - for (let i = 0; i < a.length; i++) { - a[i] = a[i] ^ b[i]; + /* distance table */ + sym = 0; + while (sym < 32) { state.lens[sym++] = 5; } + + inflate_table(DISTS$1, state.lens, 0, 32, distfix, 0, state.work, { bits: 5 }); + + /* do this just once */ + virgin = false; } + + state.lencode = lenfix; + state.lenbits = 9; + state.distcode = distfix; + state.distbits = 5; } -async function webEncrypt(algo, key, pt, iv) { - const ALGO = 'AES-CBC'; - const _key = await webCrypto.importKey('raw', key, { name: ALGO }, false, ['encrypt']); - const blockSize = _cipher2.default[algo].blockSize; - const cbc_pt = _util2.default.concatUint8Array([new Uint8Array(blockSize), pt]); - const ct = new Uint8Array((await webCrypto.encrypt({ name: ALGO, iv }, _key, cbc_pt))).subarray(0, pt.length); - xorMut(ct, pt); - return ct; -} +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. -function nodeEncrypt(algo, key, pt, iv) { - key = new Buffer(key); - iv = new Buffer(iv); - const cipherObj = new nodeCrypto.createCipheriv('aes-' + algo.substr(3, 3) + '-cfb', key, iv); - return _webStreamTools2.default.transform(pt, value => new Uint8Array(cipherObj.update(new Buffer(value)))); -} + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +function updatewindow(strm, src, end, copy) { + let dist; + const state = strm.state; -function nodeDecrypt(algo, key, ct, iv) { - key = new Buffer(key); - iv = new Buffer(iv); - const decipherObj = new nodeCrypto.createDecipheriv('aes-' + algo.substr(3, 3) + '-cfb', key, iv); - return _webStreamTools2.default.transform(ct, value => new Uint8Array(decipherObj.update(new Buffer(value)))); + /* if it hasn't been done already, allocate space for the window */ + if (state.window === null) { + state.wsize = 1 << state.wbits; + state.wnext = 0; + state.whave = 0; + + state.window = new Buf8(state.wsize); + } + + /* copy state->wsize or less output bytes into the circular window */ + if (copy >= state.wsize) { + arraySet(state.window, src, end - state.wsize, state.wsize, 0); + state.wnext = 0; + state.whave = state.wsize; + } + else { + dist = state.wsize - state.wnext; + if (dist > copy) { + dist = copy; + } + //zmemcpy(state->window + state->wnext, end - copy, dist); + arraySet(state.window, src, end - copy, dist, state.wnext); + copy -= dist; + if (copy) { + //zmemcpy(state->window, end - copy, copy); + arraySet(state.window, src, end - copy, copy, 0); + state.wnext = copy; + state.whave = state.wsize; + } + else { + state.wnext += dist; + if (state.wnext === state.wsize) { state.wnext = 0; } + if (state.whave < state.wsize) { state.whave += dist; } + } + } + return 0; } -},{"../config":79,"../util":152,"./cipher":86,"asmcrypto.js/dist_es5/aes/cfb":5,"web-stream-tools":75}],82:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); +function inflate(strm, flush) { + let state; + let input, output; // input/output buffers + let next; /* next input INDEX */ + let put; /* next output INDEX */ + let have, left; /* available input and output */ + let hold; /* bit buffer */ + let bits; /* bits in bit buffer */ + let _in, _out; /* save starting available input and output */ + let copy; /* number of stored or match bytes to copy */ + let from; /* where to copy match bytes from */ + let from_source; + let here = 0; /* current decoding table entry */ + let here_bits, here_op, here_val; // paked "here" denormalized (JS specific) + //var last; /* parent table entry */ + let last_bits, last_op, last_val; // paked "last" denormalized (JS specific) + let len; /* length to copy for repeats, bits to drop */ + let ret; /* return code */ + let hbuf = new Buf8(4); /* buffer for gzip header crc calculation */ + let opts; -var _ecb = require('asmcrypto.js/dist_es5/aes/ecb'); + let n; // temporary var for NEED_BITS -// TODO use webCrypto or nodeCrypto when possible. -function aes(length) { - const C = function C(key) { - const aes_ecb = new _ecb.AES_ECB(key); + const order = /* permutation of code lengths */ + [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ]; - this.encrypt = function (block) { - return aes_ecb.encrypt(block); - }; - this.decrypt = function (block) { - return aes_ecb.decrypt(block); - }; - }; + if (!strm || !strm.state || !strm.output || + (!strm.input && strm.avail_in !== 0)) { + return Z_STREAM_ERROR; + } - C.blockSize = C.prototype.blockSize = 16; - C.keySize = C.prototype.keySize = length / 8; + state = strm.state; + if (state.mode === TYPE$1) { state.mode = TYPEDO; } /* skip check */ - return C; -} /** - * @requires asmcrypto.js - */ -exports.default = aes; + //--- LOAD() --- + put = strm.next_out; + output = strm.output; + left = strm.avail_out; + next = strm.next_in; + input = strm.input; + have = strm.avail_in; + hold = state.hold; + bits = state.bits; + //--- -},{"asmcrypto.js/dist_es5/aes/ecb":7}],83:[function(require,module,exports){ -"use strict"; + _in = have; + _out = left; + ret = Z_OK; -Object.defineProperty(exports, "__esModule", { - value: true -}); -/* Modified by Recurity Labs GmbH - * - * Originally written by nklein software (nklein.com) - */ + inf_leave: // goto emulation + for (;;) { + switch (state.mode) { + case HEAD: + if (state.wrap === 0) { + state.mode = TYPEDO; + break; + } + //=== NEEDBITS(16); + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if ((state.wrap & 2) && hold === 0x8b1f) { /* gzip header */ + state.check = 0/*crc32(0L, Z_NULL, 0)*/; + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// -/* - * Javascript implementation based on Bruce Schneier's reference implementation. - * - * - * The constructor doesn't do much of anything. It's just here - * so we can start defining properties and methods and such. - */ -function Blowfish() {} + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = FLAGS; + break; + } + state.flags = 0; /* expect zlib header */ + if (state.head) { + state.head.done = false; + } + if (!(state.wrap & 1) || /* check if zlib header allowed */ + (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) { + strm.msg = 'incorrect header check'; + state.mode = BAD$1; + break; + } + if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) { + strm.msg = 'unknown compression method'; + state.mode = BAD$1; + break; + } + //--- DROPBITS(4) ---// + hold >>>= 4; + bits -= 4; + //---// + len = (hold & 0x0f)/*BITS(4)*/ + 8; + if (state.wbits === 0) { + state.wbits = len; + } + else if (len > state.wbits) { + strm.msg = 'invalid window size'; + state.mode = BAD$1; + break; + } + state.dmax = 1 << len; + //Tracev((stderr, "inflate: zlib header ok\n")); + strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; + state.mode = hold & 0x200 ? DICTID : TYPE$1; + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + break; + case FLAGS: + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.flags = hold; + if ((state.flags & 0xff) !== Z_DEFLATED) { + strm.msg = 'unknown compression method'; + state.mode = BAD$1; + break; + } + if (state.flags & 0xe000) { + strm.msg = 'unknown header flags set'; + state.mode = BAD$1; + break; + } + if (state.head) { + state.head.text = ((hold >> 8) & 1); + } + if (state.flags & 0x0200) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = TIME; + /* falls through */ + case TIME: + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (state.head) { + state.head.time = hold; + } + if (state.flags & 0x0200) { + //=== CRC4(state.check, hold) + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + hbuf[2] = (hold >>> 16) & 0xff; + hbuf[3] = (hold >>> 24) & 0xff; + state.check = crc32(state.check, hbuf, 4, 0); + //=== + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = OS; + /* falls through */ + case OS: + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (state.head) { + state.head.xflags = (hold & 0xff); + state.head.os = (hold >> 8); + } + if (state.flags & 0x0200) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = EXLEN; + /* falls through */ + case EXLEN: + if (state.flags & 0x0400) { + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.length = hold; + if (state.head) { + state.head.extra_len = hold; + } + if (state.flags & 0x0200) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + } + else if (state.head) { + state.head.extra = null/*Z_NULL*/; + } + state.mode = EXTRA; + /* falls through */ + case EXTRA: + if (state.flags & 0x0400) { + copy = state.length; + if (copy > have) { copy = have; } + if (copy) { + if (state.head) { + len = state.head.extra_len - state.length; + if (!state.head.extra) { + // Use untyped array for more convenient processing later + state.head.extra = new Array(state.head.extra_len); + } + arraySet( + state.head.extra, + input, + next, + // extra field is limited to 65536 bytes + // - no need for additional size check + copy, + /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/ + len + ); + //zmemcpy(state.head.extra + len, next, + // len + copy > state.head.extra_max ? + // state.head.extra_max - len : copy); + } + if (state.flags & 0x0200) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + state.length -= copy; + } + if (state.length) { break inf_leave; } + } + state.length = 0; + state.mode = NAME; + /* falls through */ + case NAME: + if (state.flags & 0x0800) { + if (have === 0) { break inf_leave; } + copy = 0; + do { + // TODO: 2 or 1 bytes? + len = input[next + copy++]; + /* use constant limit because in js we should not preallocate memory */ + if (state.head && len && + (state.length < 65536 /*state.head.name_max*/)) { + state.head.name += String.fromCharCode(len); + } + } while (len && copy < have); -/* - * Declare the block size so that protocols know what size - * Initialization Vector (IV) they will need. - */ -Blowfish.prototype.BLOCKSIZE = 8; + if (state.flags & 0x0200) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + if (len) { break inf_leave; } + } + else if (state.head) { + state.head.name = null; + } + state.length = 0; + state.mode = COMMENT; + /* falls through */ + case COMMENT: + if (state.flags & 0x1000) { + if (have === 0) { break inf_leave; } + copy = 0; + do { + len = input[next + copy++]; + /* use constant limit because in js we should not preallocate memory */ + if (state.head && len && + (state.length < 65536 /*state.head.comm_max*/)) { + state.head.comment += String.fromCharCode(len); + } + } while (len && copy < have); + if (state.flags & 0x0200) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + if (len) { break inf_leave; } + } + else if (state.head) { + state.head.comment = null; + } + state.mode = HCRC; + /* falls through */ + case HCRC: + if (state.flags & 0x0200) { + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (hold !== (state.check & 0xffff)) { + strm.msg = 'header crc mismatch'; + state.mode = BAD$1; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + } + if (state.head) { + state.head.hcrc = ((state.flags >> 9) & 1); + state.head.done = true; + } + strm.adler = state.check = 0; + state.mode = TYPE$1; + break; + case DICTID: + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + strm.adler = state.check = zswap32(hold); + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = DICT; + /* falls through */ + case DICT: + if (state.havedict === 0) { + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + return Z_NEED_DICT; + } + strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; + state.mode = TYPE$1; + /* falls through */ + case TYPE$1: + if (flush === Z_BLOCK || flush === Z_TREES) { break inf_leave; } + /* falls through */ + case TYPEDO: + if (state.last) { + //--- BYTEBITS() ---// + hold >>>= bits & 7; + bits -= bits & 7; + //---// + state.mode = CHECK; + break; + } + //=== NEEDBITS(3); */ + while (bits < 3) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.last = (hold & 0x01)/*BITS(1)*/; + //--- DROPBITS(1) ---// + hold >>>= 1; + bits -= 1; + //---// -/* - * These are the default SBOXES. - */ -Blowfish.prototype.SBOXES = [[0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a], [0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7], [0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0], [0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6]]; + switch ((hold & 0x03)/*BITS(2)*/) { + case 0: /* stored block */ + //Tracev((stderr, "inflate: stored block%s\n", + // state.last ? " (last)" : "")); + state.mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + //Tracev((stderr, "inflate: fixed codes block%s\n", + // state.last ? " (last)" : "")); + state.mode = LEN_; /* decode codes */ + if (flush === Z_TREES) { + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + break inf_leave; + } + break; + case 2: /* dynamic block */ + //Tracev((stderr, "inflate: dynamic codes block%s\n", + // state.last ? " (last)" : "")); + state.mode = TABLE; + break; + case 3: + strm.msg = 'invalid block type'; + state.mode = BAD$1; + } + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + break; + case STORED: + //--- BYTEBITS() ---// /* go to byte boundary */ + hold >>>= bits & 7; + bits -= bits & 7; + //---// + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) { + strm.msg = 'invalid stored block lengths'; + state.mode = BAD$1; + break; + } + state.length = hold & 0xffff; + //Tracev((stderr, "inflate: stored length %u\n", + // state.length)); + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = COPY_; + if (flush === Z_TREES) { break inf_leave; } + /* falls through */ + case COPY_: + state.mode = COPY; + /* falls through */ + case COPY: + copy = state.length; + if (copy) { + if (copy > have) { copy = have; } + if (copy > left) { copy = left; } + if (copy === 0) { break inf_leave; } + //--- zmemcpy(put, next, copy); --- + arraySet(output, input, next, copy, put); + //---// + have -= copy; + next += copy; + left -= copy; + put += copy; + state.length -= copy; + break; + } + //Tracev((stderr, "inflate: stored end\n")); + state.mode = TYPE$1; + break; + case TABLE: + //=== NEEDBITS(14); */ + while (bits < 14) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257; + //--- DROPBITS(5) ---// + hold >>>= 5; + bits -= 5; + //---// + state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1; + //--- DROPBITS(5) ---// + hold >>>= 5; + bits -= 5; + //---// + state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4; + //--- DROPBITS(4) ---// + hold >>>= 4; + bits -= 4; + //---// +//#ifndef PKZIP_BUG_WORKAROUND + if (state.nlen > 286 || state.ndist > 30) { + strm.msg = 'too many length or distance symbols'; + state.mode = BAD$1; + break; + } +//#endif + //Tracev((stderr, "inflate: table sizes ok\n")); + state.have = 0; + state.mode = LENLENS; + /* falls through */ + case LENLENS: + while (state.have < state.ncode) { + //=== NEEDBITS(3); + while (bits < 3) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.lens[order[state.have++]] = (hold & 0x07);//BITS(3); + //--- DROPBITS(3) ---// + hold >>>= 3; + bits -= 3; + //---// + } + while (state.have < 19) { + state.lens[order[state.have++]] = 0; + } + // We have separate tables & no pointers. 2 commented lines below not needed. + //state.next = state.codes; + //state.lencode = state.next; + // Switch to use dynamic table + state.lencode = state.lendyn; + state.lenbits = 7; -//* -//* This is the default PARRAY -//* -Blowfish.prototype.PARRAY = [0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b]; + opts = { bits: state.lenbits }; + ret = inflate_table(CODES$1, state.lens, 0, 19, state.lencode, 0, state.work, opts); + state.lenbits = opts.bits; -//* -//* This is the number of rounds the cipher will go -//* -Blowfish.prototype.NN = 16; + if (ret) { + strm.msg = 'invalid code lengths set'; + state.mode = BAD$1; + break; + } + //Tracev((stderr, "inflate: code lengths ok\n")); + state.have = 0; + state.mode = CODELENS; + /* falls through */ + case CODELENS: + while (state.have < state.nlen + state.ndist) { + for (;;) { + here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; -//* -//* This function is needed to get rid of problems -//* with the high-bit getting set. If we don't do -//* this, then sometimes ( aa & 0x00FFFFFFFF ) is not -//* equal to ( bb & 0x00FFFFFFFF ) even when they -//* agree bit-for-bit for the first 32 bits. -//* -Blowfish.prototype._clean = function (xx) { - if (xx < 0) { - const yy = xx & 0x7FFFFFFF; - xx = yy + 0x80000000; - } - return xx; -}; + if ((here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if (here_val < 16) { + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.lens[state.have++] = here_val; + } + else { + if (here_val === 16) { + //=== NEEDBITS(here.bits + 2); + n = here_bits + 2; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + if (state.have === 0) { + strm.msg = 'invalid bit length repeat'; + state.mode = BAD$1; + break; + } + len = state.lens[state.have - 1]; + copy = 3 + (hold & 0x03);//BITS(2); + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + } + else if (here_val === 17) { + //=== NEEDBITS(here.bits + 3); + n = here_bits + 3; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + len = 0; + copy = 3 + (hold & 0x07);//BITS(3); + //--- DROPBITS(3) ---// + hold >>>= 3; + bits -= 3; + //---// + } + else { + //=== NEEDBITS(here.bits + 7); + n = here_bits + 7; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + len = 0; + copy = 11 + (hold & 0x7f);//BITS(7); + //--- DROPBITS(7) ---// + hold >>>= 7; + bits -= 7; + //---// + } + if (state.have + copy > state.nlen + state.ndist) { + strm.msg = 'invalid bit length repeat'; + state.mode = BAD$1; + break; + } + while (copy--) { + state.lens[state.have++] = len; + } + } + } -//* -//* This is the mixing function that uses the sboxes -//* -Blowfish.prototype._F = function (xx) { - let yy; + /* handle error breaks in while */ + if (state.mode === BAD$1) { break; } - const dd = xx & 0x00FF; - xx >>>= 8; - const cc = xx & 0x00FF; - xx >>>= 8; - const bb = xx & 0x00FF; - xx >>>= 8; - const aa = xx & 0x00FF; + /* check for end-of-block code (better have one) */ + if (state.lens[256] === 0) { + strm.msg = 'invalid code -- missing end-of-block'; + state.mode = BAD$1; + break; + } - yy = this.sboxes[0][aa] + this.sboxes[1][bb]; - yy ^= this.sboxes[2][cc]; - yy += this.sboxes[3][dd]; + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state.lenbits = 9; - return yy; -}; + opts = { bits: state.lenbits }; + ret = inflate_table(LENS$1, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts); + // We have separate tables & no pointers. 2 commented lines below not needed. + // state.next_index = opts.table_index; + state.lenbits = opts.bits; + // state.lencode = state.next; -//* -//* This method takes an array with two values, left and right -//* and does NN rounds of Blowfish on them. -//* -Blowfish.prototype._encrypt_block = function (vals) { - let dataL = vals[0]; - let dataR = vals[1]; + if (ret) { + strm.msg = 'invalid literal/lengths set'; + state.mode = BAD$1; + break; + } - let ii; + state.distbits = 6; + //state.distcode.copy(state.codes); + // Switch to use dynamic table + state.distcode = state.distdyn; + opts = { bits: state.distbits }; + ret = inflate_table(DISTS$1, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts); + // We have separate tables & no pointers. 2 commented lines below not needed. + // state.next_index = opts.table_index; + state.distbits = opts.bits; + // state.distcode = state.next; - for (ii = 0; ii < this.NN; ++ii) { - dataL ^= this.parray[ii]; - dataR = this._F(dataL) ^ dataR; + if (ret) { + strm.msg = 'invalid distances set'; + state.mode = BAD$1; + break; + } + //Tracev((stderr, 'inflate: codes ok\n')); + state.mode = LEN_; + if (flush === Z_TREES) { break inf_leave; } + /* falls through */ + case LEN_: + state.mode = LEN; + /* falls through */ + case LEN: + if (have >= 6 && left >= 258) { + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + inflate_fast(strm, _out); + //--- LOAD() --- + put = strm.next_out; + output = strm.output; + left = strm.avail_out; + next = strm.next_in; + input = strm.input; + have = strm.avail_in; + hold = state.hold; + bits = state.bits; + //--- - const tmp = dataL; - dataL = dataR; - dataR = tmp; - } + if (state.mode === TYPE$1) { + state.back = -1; + } + break; + } + state.back = 0; + for (;;) { + here = state.lencode[hold & ((1 << state.lenbits) - 1)]; /*BITS(state.lenbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; - dataL ^= this.parray[this.NN + 0]; - dataR ^= this.parray[this.NN + 1]; + if (here_bits <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if (here_op && (here_op & 0xf0) === 0) { + last_bits = here_bits; + last_op = here_op; + last_val = here_val; + for (;;) { + here = state.lencode[last_val + + ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; - vals[0] = this._clean(dataR); - vals[1] = this._clean(dataL); -}; + if ((last_bits + here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + //--- DROPBITS(last.bits) ---// + hold >>>= last_bits; + bits -= last_bits; + //---// + state.back += last_bits; + } + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.back += here_bits; + state.length = here_val; + if (here_op === 0) { + //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + // "inflate: literal '%c'\n" : + // "inflate: literal 0x%02x\n", here.val)); + state.mode = LIT; + break; + } + if (here_op & 32) { + //Tracevv((stderr, "inflate: end of block\n")); + state.back = -1; + state.mode = TYPE$1; + break; + } + if (here_op & 64) { + strm.msg = 'invalid literal/length code'; + state.mode = BAD$1; + break; + } + state.extra = here_op & 15; + state.mode = LENEXT; + /* falls through */ + case LENEXT: + if (state.extra) { + //=== NEEDBITS(state.extra); + n = state.extra; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.length += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; + //--- DROPBITS(state.extra) ---// + hold >>>= state.extra; + bits -= state.extra; + //---// + state.back += state.extra; + } + //Tracevv((stderr, "inflate: length %u\n", state.length)); + state.was = state.length; + state.mode = DIST; + /* falls through */ + case DIST: + for (;;) { + here = state.distcode[hold & ((1 << state.distbits) - 1)];/*BITS(state.distbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; -//* -//* This method takes a vector of numbers and turns them -//* into long words so that they can be processed by the -//* real algorithm. -//* -//* Maybe I should make the real algorithm above take a vector -//* instead. That will involve more looping, but it won't require -//* the F() method to deconstruct the vector. -//* -Blowfish.prototype.encrypt_block = function (vector) { - let ii; - const vals = [0, 0]; - const off = this.BLOCKSIZE / 2; - for (ii = 0; ii < this.BLOCKSIZE / 2; ++ii) { - vals[0] = vals[0] << 8 | vector[ii + 0] & 0x00FF; - vals[1] = vals[1] << 8 | vector[ii + off] & 0x00FF; - } + if ((here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if ((here_op & 0xf0) === 0) { + last_bits = here_bits; + last_op = here_op; + last_val = here_val; + for (;;) { + here = state.distcode[last_val + + ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; - this._encrypt_block(vals); + if ((last_bits + here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + //--- DROPBITS(last.bits) ---// + hold >>>= last_bits; + bits -= last_bits; + //---// + state.back += last_bits; + } + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.back += here_bits; + if (here_op & 64) { + strm.msg = 'invalid distance code'; + state.mode = BAD$1; + break; + } + state.offset = here_val; + state.extra = (here_op) & 15; + state.mode = DISTEXT; + /* falls through */ + case DISTEXT: + if (state.extra) { + //=== NEEDBITS(state.extra); + n = state.extra; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.offset += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; + //--- DROPBITS(state.extra) ---// + hold >>>= state.extra; + bits -= state.extra; + //---// + state.back += state.extra; + } +//#ifdef INFLATE_STRICT + if (state.offset > state.dmax) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD$1; + break; + } +//#endif + //Tracevv((stderr, "inflate: distance %u\n", state.offset)); + state.mode = MATCH; + /* falls through */ + case MATCH: + if (left === 0) { break inf_leave; } + copy = _out - left; + if (state.offset > copy) { /* copy from window */ + copy = state.offset - copy; + if (copy > state.whave) { + if (state.sane) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD$1; + break; + } +// (!) This block is disabled in zlib defaults, +// don't enable it for binary compatibility +//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR +// Trace((stderr, "inflate.c too far\n")); +// copy -= state.whave; +// if (copy > state.length) { copy = state.length; } +// if (copy > left) { copy = left; } +// left -= copy; +// state.length -= copy; +// do { +// output[put++] = 0; +// } while (--copy); +// if (state.length === 0) { state.mode = LEN; } +// break; +//#endif + } + if (copy > state.wnext) { + copy -= state.wnext; + from = state.wsize - copy; + } + else { + from = state.wnext - copy; + } + if (copy > state.length) { copy = state.length; } + from_source = state.window; + } + else { /* copy from output */ + from_source = output; + from = put - state.offset; + copy = state.length; + } + if (copy > left) { copy = left; } + left -= copy; + state.length -= copy; + do { + output[put++] = from_source[from++]; + } while (--copy); + if (state.length === 0) { state.mode = LEN; } + break; + case LIT: + if (left === 0) { break inf_leave; } + output[put++] = state.length; + left--; + state.mode = LEN; + break; + case CHECK: + if (state.wrap) { + //=== NEEDBITS(32); + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + // Use '|' instead of '+' to make sure that result is signed + hold |= input[next++] << bits; + bits += 8; + } + //===// + _out -= left; + strm.total_out += _out; + state.total += _out; + if (_out) { + strm.adler = state.check = + /*UPDATE(state.check, put - _out, _out);*/ + (state.flags ? crc32(state.check, output, _out, put - _out) : adler32(state.check, output, _out, put - _out)); - const ret = []; - for (ii = 0; ii < this.BLOCKSIZE / 2; ++ii) { - ret[ii + 0] = vals[0] >>> 24 - 8 * ii & 0x00FF; - ret[ii + off] = vals[1] >>> 24 - 8 * ii & 0x00FF; - // vals[ 0 ] = ( vals[ 0 ] >>> 8 ); - // vals[ 1 ] = ( vals[ 1 ] >>> 8 ); + } + _out = left; + // NB: crc32 stored as signed 32-bit int, zswap32 returns signed too + if ((state.flags ? hold : zswap32(hold)) !== state.check) { + strm.msg = 'incorrect data check'; + state.mode = BAD$1; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + //Tracev((stderr, "inflate: check matches trailer\n")); + } + state.mode = LENGTH; + /* falls through */ + case LENGTH: + if (state.wrap && state.flags) { + //=== NEEDBITS(32); + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (hold !== (state.total & 0xffffffff)) { + strm.msg = 'incorrect length check'; + state.mode = BAD$1; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + //Tracev((stderr, "inflate: length matches trailer\n")); + } + state.mode = DONE; + /* falls through */ + case DONE: + ret = Z_STREAM_END; + break inf_leave; + case BAD$1: + ret = Z_DATA_ERROR; + break inf_leave; + // case MEM: + // return Z_MEM_ERROR; + case SYNC: + /* falls through */ + default: + return Z_STREAM_ERROR; + } } - return ret; -}; - -//* -//* This method takes an array with two values, left and right -//* and undoes NN rounds of Blowfish on them. -//* -Blowfish.prototype._decrypt_block = function (vals) { - let dataL = vals[0]; - let dataR = vals[1]; + // inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave" - let ii; + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ - for (ii = this.NN + 1; ii > 1; --ii) { - dataL ^= this.parray[ii]; - dataR = this._F(dataL) ^ dataR; + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- - const tmp = dataL; - dataL = dataR; - dataR = tmp; + if (state.wsize || (_out !== strm.avail_out && state.mode < BAD$1 && + (state.mode < CHECK || flush !== Z_FINISH))) { + if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) ; } - - dataL ^= this.parray[1]; - dataR ^= this.parray[0]; - - vals[0] = this._clean(dataR); - vals[1] = this._clean(dataL); -}; - -//* -//* This method takes a key array and initializes the -//* sboxes and parray for this encryption. -//* -Blowfish.prototype.init = function (key) { - let ii; - let jj = 0; - - this.parray = []; - for (ii = 0; ii < this.NN + 2; ++ii) { - let data = 0x00000000; - for (let kk = 0; kk < 4; ++kk) { - data = data << 8 | key[jj] & 0x00FF; - if (++jj >= key.length) { - jj = 0; - } - } - this.parray[ii] = this.PARRAY[ii] ^ data; + _in -= strm.avail_in; + _out -= strm.avail_out; + strm.total_in += _in; + strm.total_out += _out; + state.total += _out; + if (state.wrap && _out) { + strm.adler = state.check = /*UPDATE(state.check, strm.next_out - _out, _out);*/ + (state.flags ? crc32(state.check, output, _out, strm.next_out - _out) : adler32(state.check, output, _out, strm.next_out - _out)); } - - this.sboxes = []; - for (ii = 0; ii < 4; ++ii) { - this.sboxes[ii] = []; - for (jj = 0; jj < 256; ++jj) { - this.sboxes[ii][jj] = this.SBOXES[ii][jj]; - } + strm.data_type = state.bits + (state.last ? 64 : 0) + + (state.mode === TYPE$1 ? 128 : 0) + + (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0); + if (((_in === 0 && _out === 0) || flush === Z_FINISH) && ret === Z_OK) { + ret = Z_BUF_ERROR; } + return ret; +} - const vals = [0x00000000, 0x00000000]; +function inflateEnd(strm) { - for (ii = 0; ii < this.NN + 2; ii += 2) { - this._encrypt_block(vals); - this.parray[ii + 0] = vals[0]; - this.parray[ii + 1] = vals[1]; + if (!strm || !strm.state /*|| strm->zfree == (free_func)0*/) { + return Z_STREAM_ERROR; } - for (ii = 0; ii < 4; ++ii) { - for (jj = 0; jj < 256; jj += 2) { - this._encrypt_block(vals); - this.sboxes[ii][jj + 0] = vals[0]; - this.sboxes[ii][jj + 1] = vals[1]; - } + const state = strm.state; + if (state.window) { + state.window = null; } -}; - -// added by Recurity Labs -function BF(key) { - this.bf = new Blowfish(); - this.bf.init(key); - - this.encrypt = function (block) { - return this.bf.encrypt_block(block); - }; + strm.state = null; + return Z_OK; } -BF.keySize = BF.prototype.keySize = 16; -BF.blockSize = BF.prototype.blockSize = 16; - -exports.default = BF; - -},{}],84:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Copyright 2010 pjacobs@xeekr.com . All rights reserved. - -// Modified by Recurity Labs GmbH - -// fixed/modified by Herbert Hanewinkel, www.haneWIN.de -// check www.haneWIN.de for the latest version - -// cast5.js is a Javascript implementation of CAST-128, as defined in RFC 2144. -// CAST-128 is a common OpenPGP cipher. +function inflateGetHeader(strm, head) { + let state; + /* check state */ + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR; } -// CAST5 constructor + /* save header structure */ + state.head = head; + head.done = false; + return Z_OK; +} -function OpenpgpSymencCast5() { - this.BlockSize = 8; - this.KeySize = 16; +function inflateSetDictionary(strm, dictionary) { + const dictLength = dictionary.length; - this.setKey = function (key) { - this.masking = new Array(16); - this.rotate = new Array(16); + let state; + let dictid; - this.reset(); + /* check state */ + if (!strm /* == Z_NULL */ || !strm.state /* == Z_NULL */) { return Z_STREAM_ERROR; } + state = strm.state; - if (key.length === this.KeySize) { - this.keySchedule(key); - } else { - throw new Error('CAST-128: keys must be 16 bytes'); - } - return true; - }; + if (state.wrap !== 0 && state.mode !== DICT) { + return Z_STREAM_ERROR; + } - this.reset = function () { - for (let i = 0; i < 16; i++) { - this.masking[i] = 0; - this.rotate[i] = 0; + /* check for correct dictionary identifier */ + if (state.mode === DICT) { + dictid = 1; /* adler32(0, null, 0)*/ + /* dictid = adler32(dictid, dictionary, dictLength); */ + dictid = adler32(dictid, dictionary, dictLength, 0); + if (dictid !== state.check) { + return Z_DATA_ERROR; } - }; - - this.getBlockSize = function () { - return this.BlockSize; - }; - - this.encrypt = function (src) { - const dst = new Array(src.length); + } + /* copy dictionary to window using updatewindow(), which will amend the + existing dictionary if appropriate */ + updatewindow(strm, dictionary, dictLength, dictLength); + // if (ret) { + // state.mode = MEM; + // return Z_MEM_ERROR; + // } + state.havedict = 1; + // Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} - for (let i = 0; i < src.length; i += 8) { - let l = src[i] << 24 | src[i + 1] << 16 | src[i + 2] << 8 | src[i + 3]; - let r = src[i + 4] << 24 | src[i + 5] << 16 | src[i + 6] << 8 | src[i + 7]; - let t; +/* Not implemented +exports.inflateCopy = inflateCopy; +exports.inflateGetDictionary = inflateGetDictionary; +exports.inflateMark = inflateMark; +exports.inflatePrime = inflatePrime; +exports.inflateSync = inflateSync; +exports.inflateSyncPoint = inflateSyncPoint; +exports.inflateUndermine = inflateUndermine; +*/ - t = r; - r = l ^ f1(r, this.masking[0], this.rotate[0]); - l = t; - t = r; - r = l ^ f2(r, this.masking[1], this.rotate[1]); - l = t; - t = r; - r = l ^ f3(r, this.masking[2], this.rotate[2]); - l = t; - t = r; - r = l ^ f1(r, this.masking[3], this.rotate[3]); - l = t; +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. - t = r; - r = l ^ f2(r, this.masking[4], this.rotate[4]); - l = t; - t = r; - r = l ^ f3(r, this.masking[5], this.rotate[5]); - l = t; - t = r; - r = l ^ f1(r, this.masking[6], this.rotate[6]); - l = t; - t = r; - r = l ^ f2(r, this.masking[7], this.rotate[7]); - l = t; +class GZheader { + constructor() { + /* true if compressed data believed to be text */ + this.text = 0; + /* modification time */ + this.time = 0; + /* extra flags (not used when writing a gzip file) */ + this.xflags = 0; + /* operating system */ + this.os = 0; + /* pointer to extra field or Z_NULL if none */ + this.extra = null; + /* extra field length (valid if extra != Z_NULL) */ + this.extra_len = 0; // Actually, we don't need it in JS, + // but leave for few code modifications - t = r; - r = l ^ f3(r, this.masking[8], this.rotate[8]); - l = t; - t = r; - r = l ^ f1(r, this.masking[9], this.rotate[9]); - l = t; - t = r; - r = l ^ f2(r, this.masking[10], this.rotate[10]); - l = t; - t = r; - r = l ^ f3(r, this.masking[11], this.rotate[11]); - l = t; + // + // Setup limits is not necessary because in js we should not preallocate memory + // for inflate use constant limit in 65536 bytes + // - t = r; - r = l ^ f1(r, this.masking[12], this.rotate[12]); - l = t; - t = r; - r = l ^ f2(r, this.masking[13], this.rotate[13]); - l = t; - t = r; - r = l ^ f3(r, this.masking[14], this.rotate[14]); - l = t; - t = r; - r = l ^ f1(r, this.masking[15], this.rotate[15]); - l = t; + /* space at extra (only when reading header) */ + // this.extra_max = 0; + /* pointer to zero-terminated file name or Z_NULL */ + this.name = ''; + /* space at name (only when reading header) */ + // this.name_max = 0; + /* pointer to zero-terminated comment or Z_NULL */ + this.comment = ''; + /* space at comment (only when reading header) */ + // this.comm_max = 0; + /* true if there was or will be a header crc */ + this.hcrc = 0; + /* true when done reading gzip header (not used when writing a gzip file) */ + this.done = false; + } +} - dst[i] = r >>> 24 & 255; - dst[i + 1] = r >>> 16 & 255; - dst[i + 2] = r >>> 8 & 255; - dst[i + 3] = r & 255; - dst[i + 4] = l >>> 24 & 255; - dst[i + 5] = l >>> 16 & 255; - dst[i + 6] = l >>> 8 & 255; - dst[i + 7] = l & 255; - } +/** + * class Inflate + * + * Generic JS-style wrapper for zlib calls. If you don't need + * streaming behaviour - use more simple functions: [[inflate]] + * and [[inflateRaw]]. + **/ - return dst; - }; +/* internal + * inflate.chunks -> Array + * + * Chunks of output data, if [[Inflate#onData]] not overridden. + **/ - this.decrypt = function (src) { - const dst = new Array(src.length); +/** + * Inflate.result -> Uint8Array|Array|String + * + * Uncompressed result, generated by default [[Inflate#onData]] + * and [[Inflate#onEnd]] handlers. Filled after you push last chunk + * (call [[Inflate#push]] with `Z_FINISH` / `true` param) or if you + * push a chunk with explicit flush (call [[Inflate#push]] with + * `Z_SYNC_FLUSH` param). + **/ - for (let i = 0; i < src.length; i += 8) { - let l = src[i] << 24 | src[i + 1] << 16 | src[i + 2] << 8 | src[i + 3]; - let r = src[i + 4] << 24 | src[i + 5] << 16 | src[i + 6] << 8 | src[i + 7]; - let t; +/** + * Inflate.err -> Number + * + * Error code after inflate finished. 0 (Z_OK) on success. + * Should be checked if broken data possible. + **/ - t = r; - r = l ^ f1(r, this.masking[15], this.rotate[15]); - l = t; - t = r; - r = l ^ f3(r, this.masking[14], this.rotate[14]); - l = t; - t = r; - r = l ^ f2(r, this.masking[13], this.rotate[13]); - l = t; - t = r; - r = l ^ f1(r, this.masking[12], this.rotate[12]); - l = t; +/** + * Inflate.msg -> String + * + * Error message, if [[Inflate.err]] != 0 + **/ - t = r; - r = l ^ f3(r, this.masking[11], this.rotate[11]); - l = t; - t = r; - r = l ^ f2(r, this.masking[10], this.rotate[10]); - l = t; - t = r; - r = l ^ f1(r, this.masking[9], this.rotate[9]); - l = t; - t = r; - r = l ^ f3(r, this.masking[8], this.rotate[8]); - l = t; - t = r; - r = l ^ f2(r, this.masking[7], this.rotate[7]); - l = t; - t = r; - r = l ^ f1(r, this.masking[6], this.rotate[6]); - l = t; - t = r; - r = l ^ f3(r, this.masking[5], this.rotate[5]); - l = t; - t = r; - r = l ^ f2(r, this.masking[4], this.rotate[4]); - l = t; +/** + * new Inflate(options) + * - options (Object): zlib inflate options. + * + * Creates new inflator instance with specified params. Throws exception + * on bad params. Supported options: + * + * - `windowBits` + * - `dictionary` + * + * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) + * for more information on these. + * + * Additional options, for internal needs: + * + * - `chunkSize` - size of generated data chunks (16K by default) + * - `raw` (Boolean) - do raw inflate + * - `to` (String) - if equal to 'string', then result will be converted + * from utf8 to utf16 (javascript) string. When string output requested, + * chunk length can differ from `chunkSize`, depending on content. + * + * By default, when no options set, autodetect deflate/gzip data format via + * wrapper header. + * + * ##### Example: + * + * ```javascript + * var pako = require('pako') + * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9]) + * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]); + * + * var inflate = new pako.Inflate({ level: 3}); + * + * inflate.push(chunk1, false); + * inflate.push(chunk2, true); // true -> last chunk + * + * if (inflate.err) { throw new Error(inflate.err); } + * + * console.log(inflate.result); + * ``` + **/ +class Inflate { + constructor(options) { + this.options = { + chunkSize: 16384, + windowBits: 0, + ...(options || {}) + }; - t = r; - r = l ^ f1(r, this.masking[3], this.rotate[3]); - l = t; - t = r; - r = l ^ f3(r, this.masking[2], this.rotate[2]); - l = t; - t = r; - r = l ^ f2(r, this.masking[1], this.rotate[1]); - l = t; - t = r; - r = l ^ f1(r, this.masking[0], this.rotate[0]); - l = t; + const opt = this.options; - dst[i] = r >>> 24 & 255; - dst[i + 1] = r >>> 16 & 255; - dst[i + 2] = r >>> 8 & 255; - dst[i + 3] = r & 255; - dst[i + 4] = l >>> 24 & 255; - dst[i + 5] = l >> 16 & 255; - dst[i + 6] = l >> 8 & 255; - dst[i + 7] = l & 255; + // Force window size for `raw` data, if not set directly, + // because we have no header for autodetect. + if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) { + opt.windowBits = -opt.windowBits; + if (opt.windowBits === 0) { opt.windowBits = -15; } } - return dst; - }; - const scheduleA = new Array(4); + // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate + if ((opt.windowBits >= 0) && (opt.windowBits < 16) && + !(options && options.windowBits)) { + opt.windowBits += 32; + } - scheduleA[0] = new Array(4); - scheduleA[0][0] = [4, 0, 0xd, 0xf, 0xc, 0xe, 0x8]; - scheduleA[0][1] = [5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa]; - scheduleA[0][2] = [6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9]; - scheduleA[0][3] = [7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb]; + // Gzip header has no info about windows size, we can do autodetect only + // for deflate. So, if window size not set, force it to max when gzip possible + if ((opt.windowBits > 15) && (opt.windowBits < 48)) { + // bit 3 (16) -> gzipped data + // bit 4 (32) -> autodetect gzip/deflate + if ((opt.windowBits & 15) === 0) { + opt.windowBits |= 15; + } + } - scheduleA[1] = new Array(4); - scheduleA[1][0] = [0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0]; - scheduleA[1][1] = [1, 4, 0, 2, 1, 3, 16 + 2]; - scheduleA[1][2] = [2, 5, 7, 6, 5, 4, 16 + 1]; - scheduleA[1][3] = [3, 7, 0xa, 9, 0xb, 8, 16 + 3]; + this.err = 0; // error code, if happens (0 = Z_OK) + this.msg = ''; // error message + this.ended = false; // used to avoid multiple onEnd() calls + this.chunks = []; // chunks of compressed data - scheduleA[2] = new Array(4); - scheduleA[2][0] = [4, 0, 0xd, 0xf, 0xc, 0xe, 8]; - scheduleA[2][1] = [5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa]; - scheduleA[2][2] = [6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9]; - scheduleA[2][3] = [7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb]; + this.strm = new ZStream(); + this.strm.avail_out = 0; - scheduleA[3] = new Array(4); - scheduleA[3][0] = [0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0]; - scheduleA[3][1] = [1, 4, 0, 2, 1, 3, 16 + 2]; - scheduleA[3][2] = [2, 5, 7, 6, 5, 4, 16 + 1]; - scheduleA[3][3] = [3, 7, 0xa, 9, 0xb, 8, 16 + 3]; + let status = inflateInit2( + this.strm, + opt.windowBits + ); - const scheduleB = new Array(4); + if (status !== Z_OK) { + throw new Error(msg[status]); + } - scheduleB[0] = new Array(4); - scheduleB[0][0] = [16 + 8, 16 + 9, 16 + 7, 16 + 6, 16 + 2]; - scheduleB[0][1] = [16 + 0xa, 16 + 0xb, 16 + 5, 16 + 4, 16 + 6]; - scheduleB[0][2] = [16 + 0xc, 16 + 0xd, 16 + 3, 16 + 2, 16 + 9]; - scheduleB[0][3] = [16 + 0xe, 16 + 0xf, 16 + 1, 16 + 0, 16 + 0xc]; + this.header = new GZheader(); - scheduleB[1] = new Array(4); - scheduleB[1][0] = [3, 2, 0xc, 0xd, 8]; - scheduleB[1][1] = [1, 0, 0xe, 0xf, 0xd]; - scheduleB[1][2] = [7, 6, 8, 9, 3]; - scheduleB[1][3] = [5, 4, 0xa, 0xb, 7]; + inflateGetHeader(this.strm, this.header); + + // Setup dictionary + if (opt.dictionary) { + // Convert data if needed + if (typeof opt.dictionary === 'string') { + opt.dictionary = string2buf(opt.dictionary); + } else if (opt.dictionary instanceof ArrayBuffer) { + opt.dictionary = new Uint8Array(opt.dictionary); + } + if (opt.raw) { //In raw mode we need to set the dictionary early + status = inflateSetDictionary(this.strm, opt.dictionary); + if (status !== Z_OK) { + throw new Error(msg[status]); + } + } + } + } + /** + * Inflate#push(data[, mode]) -> Boolean + * - data (Uint8Array|Array|ArrayBuffer|String): input data + * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. + * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH. + * + * Sends input data to inflate pipe, generating [[Inflate#onData]] calls with + * new output chunks. Returns `true` on success. The last data block must have + * mode Z_FINISH (or `true`). That will flush internal pending buffers and call + * [[Inflate#onEnd]]. For interim explicit flushes (without ending the stream) you + * can use mode Z_SYNC_FLUSH, keeping the decompression context. + * + * On fail call [[Inflate#onEnd]] with error code and return false. + * + * We strongly recommend to use `Uint8Array` on input for best speed (output + * format is detected automatically). Also, don't skip last param and always + * use the same type in your code (boolean or number). That will improve JS speed. + * + * For regular `Array`-s make sure all elements are [0..255]. + * + * ##### Example + * + * ```javascript + * push(chunk, false); // push one of data chunks + * ... + * push(chunk, true); // push last chunk + * ``` + **/ + push(data, mode) { + const { strm, options: { chunkSize, dictionary } } = this; + let status, _mode; - scheduleB[2] = new Array(4); - scheduleB[2][0] = [16 + 3, 16 + 2, 16 + 0xc, 16 + 0xd, 16 + 9]; - scheduleB[2][1] = [16 + 1, 16 + 0, 16 + 0xe, 16 + 0xf, 16 + 0xc]; - scheduleB[2][2] = [16 + 7, 16 + 6, 16 + 8, 16 + 9, 16 + 2]; - scheduleB[2][3] = [16 + 5, 16 + 4, 16 + 0xa, 16 + 0xb, 16 + 6]; + // Flag to properly process Z_BUF_ERROR on testing inflate call + // when we check that all output data was flushed. + let allowBufError = false; - scheduleB[3] = new Array(4); - scheduleB[3][0] = [8, 9, 7, 6, 3]; - scheduleB[3][1] = [0xa, 0xb, 5, 4, 7]; - scheduleB[3][2] = [0xc, 0xd, 3, 2, 8]; - scheduleB[3][3] = [0xe, 0xf, 1, 0, 0xd]; + if (this.ended) { return false; } + _mode = (mode === ~~mode) ? mode : ((mode === true) ? Z_FINISH : Z_NO_FLUSH); - // changed 'in' to 'inn' (in javascript 'in' is a reserved word) - this.keySchedule = function (inn) { - const t = new Array(8); - const k = new Array(32); + // Convert data if needed + if (typeof data === 'string') { + // Only binary strings can be decompressed on practice + strm.input = binstring2buf(data); + } else if (data instanceof ArrayBuffer) { + strm.input = new Uint8Array(data); + } else { + strm.input = data; + } - let j; + strm.next_in = 0; + strm.avail_in = strm.input.length; - for (let i = 0; i < 4; i++) { - j = i * 4; - t[i] = inn[j] << 24 | inn[j + 1] << 16 | inn[j + 2] << 8 | inn[j + 3]; - } + do { + if (strm.avail_out === 0) { + strm.output = new Buf8(chunkSize); + strm.next_out = 0; + strm.avail_out = chunkSize; + } - const x = [6, 7, 4, 5]; - let ki = 0; - let w; + status = inflate(strm, Z_NO_FLUSH); /* no bad return value */ - for (let half = 0; half < 2; half++) { - for (let round = 0; round < 4; round++) { - for (j = 0; j < 4; j++) { - const a = scheduleA[round][j]; - w = t[a[1]]; + if (status === Z_NEED_DICT && dictionary) { + status = inflateSetDictionary(this.strm, dictionary); + } - w ^= sBox[4][t[a[2] >>> 2] >>> 24 - 8 * (a[2] & 3) & 0xff]; - w ^= sBox[5][t[a[3] >>> 2] >>> 24 - 8 * (a[3] & 3) & 0xff]; - w ^= sBox[6][t[a[4] >>> 2] >>> 24 - 8 * (a[4] & 3) & 0xff]; - w ^= sBox[7][t[a[5] >>> 2] >>> 24 - 8 * (a[5] & 3) & 0xff]; - w ^= sBox[x[j]][t[a[6] >>> 2] >>> 24 - 8 * (a[6] & 3) & 0xff]; - t[a[0]] = w; - } + if (status === Z_BUF_ERROR && allowBufError === true) { + status = Z_OK; + allowBufError = false; + } - for (j = 0; j < 4; j++) { - const b = scheduleB[round][j]; - w = sBox[4][t[b[0] >>> 2] >>> 24 - 8 * (b[0] & 3) & 0xff]; + if (status !== Z_STREAM_END && status !== Z_OK) { + this.onEnd(status); + this.ended = true; + return false; + } - w ^= sBox[5][t[b[1] >>> 2] >>> 24 - 8 * (b[1] & 3) & 0xff]; - w ^= sBox[6][t[b[2] >>> 2] >>> 24 - 8 * (b[2] & 3) & 0xff]; - w ^= sBox[7][t[b[3] >>> 2] >>> 24 - 8 * (b[3] & 3) & 0xff]; - w ^= sBox[4 + j][t[b[4] >>> 2] >>> 24 - 8 * (b[4] & 3) & 0xff]; - k[ki] = w; - ki++; + if (strm.next_out) { + if (strm.avail_out === 0 || status === Z_STREAM_END || (strm.avail_in === 0 && (_mode === Z_FINISH || _mode === Z_SYNC_FLUSH))) { + this.onData(shrinkBuf(strm.output, strm.next_out)); } } + + // When no more input data, we should check that internal inflate buffers + // are flushed. The only way to do it when avail_out = 0 - run one more + // inflate pass. But if output data not exists, inflate return Z_BUF_ERROR. + // Here we set flag to process this error properly. + // + // NOTE. Deflate does not return error in this case and does not needs such + // logic. + if (strm.avail_in === 0 && strm.avail_out === 0) { + allowBufError = true; + } + + } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== Z_STREAM_END); + + if (status === Z_STREAM_END) { + _mode = Z_FINISH; } - for (let i = 0; i < 16; i++) { - this.masking[i] = k[i]; - this.rotate[i] = k[16 + i] & 0x1f; + // Finalize on the last chunk. + if (_mode === Z_FINISH) { + status = inflateEnd(this.strm); + this.onEnd(status); + this.ended = true; + return status === Z_OK; + } + + // callback interim results if Z_SYNC_FLUSH. + if (_mode === Z_SYNC_FLUSH) { + this.onEnd(Z_OK); + strm.avail_out = 0; + return true; } + + return true; }; - // These are the three 'f' functions. See RFC 2144, section 2.2. + /** + * Inflate#onData(chunk) -> Void + * - chunk (Uint8Array|Array|String): output data. Type of array depends + * on js engine support. When string output requested, each chunk + * will be string. + * + * By default, stores data blocks in `chunks[]` property and glue + * those in `onEnd`. Override this handler, if you need another behaviour. + **/ + onData(chunk) { + this.chunks.push(chunk); + }; - function f1(d, m, r) { - const t = m + d; - const I = t << r | t >>> 32 - r; - return (sBox[0][I >>> 24] ^ sBox[1][I >>> 16 & 255]) - sBox[2][I >>> 8 & 255] + sBox[3][I & 255]; - } - function f2(d, m, r) { - const t = m ^ d; - const I = t << r | t >>> 32 - r; - return sBox[0][I >>> 24] - sBox[1][I >>> 16 & 255] + sBox[2][I >>> 8 & 255] ^ sBox[3][I & 255]; - } - function f3(d, m, r) { - const t = m - d; - const I = t << r | t >>> 32 - r; - return (sBox[0][I >>> 24] + sBox[1][I >>> 16 & 255] ^ sBox[2][I >>> 8 & 255]) - sBox[3][I & 255]; - } + /** + * Inflate#onEnd(status) -> Void + * - status (Number): inflate status. 0 (Z_OK) on success, + * other if not. + * + * Called either after you tell inflate that the input stream is + * complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH) + * or if an error happened. By default - join collected chunks, + * free memory and fill `results` / `err` properties. + **/ + onEnd(status) { + // On success - join + if (status === Z_OK) { + this.result = flattenChunks(this.chunks); + } + this.chunks = []; + this.err = status; + this.msg = this.strm.msg; + }; +} - const sBox = new Array(8); - sBox[0] = [0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949, 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0, 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, 0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935, 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d, 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, 0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe, 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3, 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, 0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291, 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779, 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, 0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d, 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c, 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, 0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d, 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96, 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, 0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, 0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872, 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9, 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf]; +/* +node-bzip - a pure-javascript Node.JS module for decoding bzip2 data - sBox[1] = [0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651, 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806, 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, 0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359, 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b, 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, 0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34, 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb, 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, 0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860, 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b, 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, 0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f, 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, 0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6, 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58, 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, 0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6, 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, 0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6, 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f, 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, 0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9, 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1]; +Copyright (C) 2012 Eli Skeggs - sBox[2] = [0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90, 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240, 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, 0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71, 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, 0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15, 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, 0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176, 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148, 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, 0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e, 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a, 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, 0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5, 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, 0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536, 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, 0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69, 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, 0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a, 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783]; +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. - sBox[3] = [0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1, 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121, 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, 0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb, 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, 0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d, 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6, 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, 0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003, 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, 0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a, 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26, 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, 0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7, 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417, 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, 0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2, 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, 0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282, 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2]; +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. - sBox[4] = [0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f, 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02, 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, 0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7, 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9, 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, 0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774, 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655, 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, 0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910, 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1, 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, 0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f, 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3, 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, 0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4, 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2, 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, 0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5, 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, 0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801, 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, 0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8, 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4]; +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, see +http://www.gnu.org/licenses/lgpl-2.1.html - sBox[5] = [0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac, 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98, 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, 0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3, 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd, 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, 0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9, 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54, 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, 0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc, 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf, 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289, 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b, 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, 0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13, 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976, 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, 0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891, 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da, 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, 0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084, 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25, 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, 0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd, 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f]; +Adapted from bzip2.js, copyright 2011 antimatter15 (antimatter15@gmail.com). - sBox[6] = [0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f, 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19, 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, 0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516, 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88, 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, 0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756, 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, 0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688, 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28, 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566, 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, 0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962, 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e, 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, 0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c, 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, 0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be, 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767, 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, 0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c, 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3]; +Based on micro-bunzip by Rob Landley (rob@landley.net). - sBox[7] = [0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5, 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d, 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, 0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862, 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc, 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, 0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e, 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039, 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, 0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42, 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5, 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c, 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70, 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, 0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c, 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3, 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, 0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101, 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f, 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, 0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a, 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c, 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, 0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82, 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e]; -} +Based on bzip2 decompression code by Julian R Seward (jseward@acm.org), +which also acknowledges contributions by Mike Burrows, David Wheeler, +Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten, +Robert Sedgewick, and Jon L. Bentley. +*/ -function Cast5(key) { - this.cast5 = new OpenpgpSymencCast5(); - this.cast5.setKey(key); +var BITMASK = [0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF]; - this.encrypt = function (block) { - return this.cast5.encrypt(block); - }; +// offset in bytes +var BitReader = function(stream) { + this.stream = stream; + this.bitOffset = 0; + this.curByte = 0; + this.hasByte = false; +}; + +BitReader.prototype._ensureByte = function() { + if (!this.hasByte) { + this.curByte = this.stream.readByte(); + this.hasByte = true; + } +}; + +// reads bits from the buffer +BitReader.prototype.read = function(bits) { + var result = 0; + while (bits > 0) { + this._ensureByte(); + var remaining = 8 - this.bitOffset; + // if we're in a byte + if (bits >= remaining) { + result <<= remaining; + result |= BITMASK[remaining] & this.curByte; + this.hasByte = false; + this.bitOffset = 0; + bits -= remaining; + } else { + result <<= bits; + var shift = remaining - bits; + result |= (this.curByte & (BITMASK[bits] << shift)) >> shift; + this.bitOffset += bits; + bits = 0; + } + } + return result; +}; + +// seek to an arbitrary point in the buffer (expressed in bits) +BitReader.prototype.seek = function(pos) { + var n_bit = pos % 8; + var n_byte = (pos - n_bit) / 8; + this.bitOffset = n_bit; + this.stream.seek(n_byte); + this.hasByte = false; +}; + +// reads 6 bytes worth of data using the read method +BitReader.prototype.pi = function() { + var buf = new Uint8Array(6), i; + for (i = 0; i < buf.length; i++) { + buf[i] = this.read(8); + } + return bufToHex(buf); +}; + +function bufToHex(buf) { + return Array.prototype.map.call(buf, x => ('00' + x.toString(16)).slice(-2)).join(''); } -Cast5.blockSize = Cast5.prototype.blockSize = 8; -Cast5.keySize = Cast5.prototype.keySize = 16; +var bitreader = BitReader; -exports.default = Cast5; +/* very simple input/output stream interface */ +var Stream = function() { +}; -},{}],85:[function(require,module,exports){ -"use strict"; +// input streams ////////////// +/** Returns the next byte, or -1 for EOF. */ +Stream.prototype.readByte = function() { + throw new Error("abstract method readByte() not implemented"); +}; +/** Attempts to fill the buffer; returns number of bytes read, or + * -1 for EOF. */ +Stream.prototype.read = function(buffer, bufOffset, length) { + var bytesRead = 0; + while (bytesRead < length) { + var c = this.readByte(); + if (c < 0) { // EOF + return (bytesRead===0) ? -1 : bytesRead; + } + buffer[bufOffset++] = c; + bytesRead++; + } + return bytesRead; +}; +Stream.prototype.seek = function(new_pos) { + throw new Error("abstract method seek() not implemented"); +}; -Object.defineProperty(exports, "__esModule", { - value: true -}); -//Paul Tero, July 2001 -//http://www.tero.co.uk/des/ -// -//Optimised for performance with large blocks by Michael Hayworth, November 2001 -//http://www.netdealing.com -// -// Modified by Recurity Labs GmbH +// output streams /////////// +Stream.prototype.writeByte = function(_byte) { + throw new Error("abstract method readByte() not implemented"); +}; +Stream.prototype.write = function(buffer, bufOffset, length) { + var i; + for (i=0; i>> 0; // return an unsigned value + }; + + /** + * Update the CRC with a single byte + * @param value The value to update the CRC with + */ + this.updateCRC = function(value) { + crc = (crc << 8) ^ crc32Lookup[((crc >>> 24) ^ value) & 0xff]; + }; + + /** + * Update the CRC with a sequence of identical bytes + * @param value The value to update the CRC with + * @param count The number of bytes + */ + this.updateCRCRun = function(value, count) { + while (count-- > 0) { + crc = (crc << 8) ^ crc32Lookup[((crc >>> 24) ^ value) & 0xff]; + } + }; + }; + return CRC32; +})(); -//des -//this takes the key, the message, and whether to encrypt or decrypt +/* +seek-bzip - a pure-javascript module for seeking within bzip2 data -function des(keys, message, encrypt, mode, iv, padding) { - //declaring this locally speeds things up a bit - const spfunction1 = [0x1010400, 0, 0x10000, 0x1010404, 0x1010004, 0x10404, 0x4, 0x10000, 0x400, 0x1010400, 0x1010404, 0x400, 0x1000404, 0x1010004, 0x1000000, 0x4, 0x404, 0x1000400, 0x1000400, 0x10400, 0x10400, 0x1010000, 0x1010000, 0x1000404, 0x10004, 0x1000004, 0x1000004, 0x10004, 0, 0x404, 0x10404, 0x1000000, 0x10000, 0x1010404, 0x4, 0x1010000, 0x1010400, 0x1000000, 0x1000000, 0x400, 0x1010004, 0x10000, 0x10400, 0x1000004, 0x400, 0x4, 0x1000404, 0x10404, 0x1010404, 0x10004, 0x1010000, 0x1000404, 0x1000004, 0x404, 0x10404, 0x1010400, 0x404, 0x1000400, 0x1000400, 0, 0x10004, 0x10400, 0, 0x1010004]; - const spfunction2 = [-0x7fef7fe0, -0x7fff8000, 0x8000, 0x108020, 0x100000, 0x20, -0x7fefffe0, -0x7fff7fe0, -0x7fffffe0, -0x7fef7fe0, -0x7fef8000, -0x80000000, -0x7fff8000, 0x100000, 0x20, -0x7fefffe0, 0x108000, 0x100020, -0x7fff7fe0, 0, -0x80000000, 0x8000, 0x108020, -0x7ff00000, 0x100020, -0x7fffffe0, 0, 0x108000, 0x8020, -0x7fef8000, -0x7ff00000, 0x8020, 0, 0x108020, -0x7fefffe0, 0x100000, -0x7fff7fe0, -0x7ff00000, -0x7fef8000, 0x8000, -0x7ff00000, -0x7fff8000, 0x20, -0x7fef7fe0, 0x108020, 0x20, 0x8000, -0x80000000, 0x8020, -0x7fef8000, 0x100000, -0x7fffffe0, 0x100020, -0x7fff7fe0, -0x7fffffe0, 0x100020, 0x108000, 0, -0x7fff8000, 0x8020, -0x80000000, -0x7fefffe0, -0x7fef7fe0, 0x108000]; - const spfunction3 = [0x208, 0x8020200, 0, 0x8020008, 0x8000200, 0, 0x20208, 0x8000200, 0x20008, 0x8000008, 0x8000008, 0x20000, 0x8020208, 0x20008, 0x8020000, 0x208, 0x8000000, 0x8, 0x8020200, 0x200, 0x20200, 0x8020000, 0x8020008, 0x20208, 0x8000208, 0x20200, 0x20000, 0x8000208, 0x8, 0x8020208, 0x200, 0x8000000, 0x8020200, 0x8000000, 0x20008, 0x208, 0x20000, 0x8020200, 0x8000200, 0, 0x200, 0x20008, 0x8020208, 0x8000200, 0x8000008, 0x200, 0, 0x8020008, 0x8000208, 0x20000, 0x8000000, 0x8020208, 0x8, 0x20208, 0x20200, 0x8000008, 0x8020000, 0x8000208, 0x208, 0x8020000, 0x20208, 0x8, 0x8020008, 0x20200]; - const spfunction4 = [0x802001, 0x2081, 0x2081, 0x80, 0x802080, 0x800081, 0x800001, 0x2001, 0, 0x802000, 0x802000, 0x802081, 0x81, 0, 0x800080, 0x800001, 0x1, 0x2000, 0x800000, 0x802001, 0x80, 0x800000, 0x2001, 0x2080, 0x800081, 0x1, 0x2080, 0x800080, 0x2000, 0x802080, 0x802081, 0x81, 0x800080, 0x800001, 0x802000, 0x802081, 0x81, 0, 0, 0x802000, 0x2080, 0x800080, 0x800081, 0x1, 0x802001, 0x2081, 0x2081, 0x80, 0x802081, 0x81, 0x1, 0x2000, 0x800001, 0x2001, 0x802080, 0x800081, 0x2001, 0x2080, 0x800000, 0x802001, 0x80, 0x800000, 0x2000, 0x802080]; - const spfunction5 = [0x100, 0x2080100, 0x2080000, 0x42000100, 0x80000, 0x100, 0x40000000, 0x2080000, 0x40080100, 0x80000, 0x2000100, 0x40080100, 0x42000100, 0x42080000, 0x80100, 0x40000000, 0x2000000, 0x40080000, 0x40080000, 0, 0x40000100, 0x42080100, 0x42080100, 0x2000100, 0x42080000, 0x40000100, 0, 0x42000000, 0x2080100, 0x2000000, 0x42000000, 0x80100, 0x80000, 0x42000100, 0x100, 0x2000000, 0x40000000, 0x2080000, 0x42000100, 0x40080100, 0x2000100, 0x40000000, 0x42080000, 0x2080100, 0x40080100, 0x100, 0x2000000, 0x42080000, 0x42080100, 0x80100, 0x42000000, 0x42080100, 0x2080000, 0, 0x40080000, 0x42000000, 0x80100, 0x2000100, 0x40000100, 0x80000, 0, 0x40080000, 0x2080100, 0x40000100]; - const spfunction6 = [0x20000010, 0x20400000, 0x4000, 0x20404010, 0x20400000, 0x10, 0x20404010, 0x400000, 0x20004000, 0x404010, 0x400000, 0x20000010, 0x400010, 0x20004000, 0x20000000, 0x4010, 0, 0x400010, 0x20004010, 0x4000, 0x404000, 0x20004010, 0x10, 0x20400010, 0x20400010, 0, 0x404010, 0x20404000, 0x4010, 0x404000, 0x20404000, 0x20000000, 0x20004000, 0x10, 0x20400010, 0x404000, 0x20404010, 0x400000, 0x4010, 0x20000010, 0x400000, 0x20004000, 0x20000000, 0x4010, 0x20000010, 0x20404010, 0x404000, 0x20400000, 0x404010, 0x20404000, 0, 0x20400010, 0x10, 0x4000, 0x20400000, 0x404010, 0x4000, 0x400010, 0x20004010, 0, 0x20404000, 0x20000000, 0x400010, 0x20004010]; - const spfunction7 = [0x200000, 0x4200002, 0x4000802, 0, 0x800, 0x4000802, 0x200802, 0x4200800, 0x4200802, 0x200000, 0, 0x4000002, 0x2, 0x4000000, 0x4200002, 0x802, 0x4000800, 0x200802, 0x200002, 0x4000800, 0x4000002, 0x4200000, 0x4200800, 0x200002, 0x4200000, 0x800, 0x802, 0x4200802, 0x200800, 0x2, 0x4000000, 0x200800, 0x4000000, 0x200800, 0x200000, 0x4000802, 0x4000802, 0x4200002, 0x4200002, 0x2, 0x200002, 0x4000000, 0x4000800, 0x200000, 0x4200800, 0x802, 0x200802, 0x4200800, 0x802, 0x4000002, 0x4200802, 0x4200000, 0x200800, 0, 0x2, 0x4200802, 0, 0x200802, 0x4200000, 0x800, 0x4000002, 0x4000800, 0x800, 0x200002]; - const spfunction8 = [0x10001040, 0x1000, 0x40000, 0x10041040, 0x10000000, 0x10001040, 0x40, 0x10000000, 0x40040, 0x10040000, 0x10041040, 0x41000, 0x10041000, 0x41040, 0x1000, 0x40, 0x10040000, 0x10000040, 0x10001000, 0x1040, 0x41000, 0x40040, 0x10040040, 0x10041000, 0x1040, 0, 0, 0x10040040, 0x10000040, 0x10001000, 0x41040, 0x40000, 0x41040, 0x40000, 0x10041000, 0x1000, 0x40, 0x10040040, 0x1000, 0x41040, 0x10001000, 0x40, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x40000, 0x10001040, 0, 0x10041040, 0x40040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0, 0x10041040, 0x41000, 0x41000, 0x1040, 0x1040, 0x40040, 0x10000000, 0x10041000]; +Copyright (C) 2013 C. Scott Ananian +Copyright (C) 2012 Eli Skeggs +Copyright (C) 2011 Kevin Kwok - //create the 16 or 48 subkeys we will need - let m = 0; - let i; - let j; - let temp; - let right1; - let right2; - let left; - let right; - let looping; - let cbcleft; - let cbcleft2; - let cbcright; - let cbcright2; - let endloop; - let loopinc; - let len = message.length; +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. - //set up the loops for single and triple des - const iterations = keys.length === 32 ? 3 : 9; //single or triple des - if (iterations === 3) { - looping = encrypt ? [0, 32, 2] : [30, -2, -2]; - } else { - looping = encrypt ? [0, 32, 2, 62, 30, -2, 64, 96, 2] : [94, 62, -2, 32, 64, 2, 30, -2, -2]; - } +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. - //pad the message depending on the padding parameter - //only add padding if encrypting - note that you need to use the same padding option for both encrypt and decrypt - if (encrypt) { - message = des_addPadding(message, padding); - len = message.length; - } +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, see +http://www.gnu.org/licenses/lgpl-2.1.html - //store the result here - let result = new Uint8Array(len); - let k = 0; +Adapted from node-bzip, copyright 2012 Eli Skeggs. +Adapted from bzip2.js, copyright 2011 Kevin Kwok (antimatter15@gmail.com). - if (mode === 1) { - //CBC mode - cbcleft = iv[m++] << 24 | iv[m++] << 16 | iv[m++] << 8 | iv[m++]; - cbcright = iv[m++] << 24 | iv[m++] << 16 | iv[m++] << 8 | iv[m++]; - m = 0; - } +Based on micro-bunzip by Rob Landley (rob@landley.net). - //loop through each 64 bit chunk of the message - while (m < len) { - left = message[m++] << 24 | message[m++] << 16 | message[m++] << 8 | message[m++]; - right = message[m++] << 24 | message[m++] << 16 | message[m++] << 8 | message[m++]; +Based on bzip2 decompression code by Julian R Seward (jseward@acm.org), +which also acknowledges contributions by Mike Burrows, David Wheeler, +Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten, +Robert Sedgewick, and Jon L. Bentley. +*/ - //for Cipher Block Chaining mode, xor the message with the previous result - if (mode === 1) { - if (encrypt) { - left ^= cbcleft; - right ^= cbcright; - } else { - cbcleft2 = cbcleft; - cbcright2 = cbcright; - cbcleft = left; - cbcright = right; - } - } - //first each 64 but chunk of the message must be permuted according to IP - temp = (left >>> 4 ^ right) & 0x0f0f0f0f; - right ^= temp; - left ^= temp << 4; - temp = (left >>> 16 ^ right) & 0x0000ffff; - right ^= temp; - left ^= temp << 16; - temp = (right >>> 2 ^ left) & 0x33333333; - left ^= temp; - right ^= temp << 2; - temp = (right >>> 8 ^ left) & 0x00ff00ff; - left ^= temp; - right ^= temp << 8; - temp = (left >>> 1 ^ right) & 0x55555555; - right ^= temp; - left ^= temp << 1; - left = left << 1 | left >>> 31; - right = right << 1 | right >>> 31; - //do this either 1 or 3 times for each chunk of the message - for (j = 0; j < iterations; j += 3) { - endloop = looping[j + 1]; - loopinc = looping[j + 2]; - //now go through and perform the encryption or decryption - for (i = looping[j]; i !== endloop; i += loopinc) { - //for efficiency - right1 = right ^ keys[i]; - right2 = (right >>> 4 | right << 28) ^ keys[i + 1]; - //the result is attained by passing these bytes through the S selection functions - temp = left; - left = right; - right = temp ^ (spfunction2[right1 >>> 24 & 0x3f] | spfunction4[right1 >>> 16 & 0x3f] | spfunction6[right1 >>> 8 & 0x3f] | spfunction8[right1 & 0x3f] | spfunction1[right2 >>> 24 & 0x3f] | spfunction3[right2 >>> 16 & 0x3f] | spfunction5[right2 >>> 8 & 0x3f] | spfunction7[right2 & 0x3f]); - } - temp = left; - left = right; - right = temp; //unreverse left and right - } //for either 1 or 3 iterations - //move then each one bit to the right - left = left >>> 1 | left << 31; - right = right >>> 1 | right << 31; +var MAX_HUFCODE_BITS = 20; +var MAX_SYMBOLS = 258; +var SYMBOL_RUNA = 0; +var SYMBOL_RUNB = 1; +var MIN_GROUPS = 2; +var MAX_GROUPS = 6; +var GROUP_SIZE = 50; - //now perform IP-1, which is IP in the opposite direction - temp = (left >>> 1 ^ right) & 0x55555555; - right ^= temp; - left ^= temp << 1; - temp = (right >>> 8 ^ left) & 0x00ff00ff; - left ^= temp; - right ^= temp << 8; - temp = (right >>> 2 ^ left) & 0x33333333; - left ^= temp; - right ^= temp << 2; - temp = (left >>> 16 ^ right) & 0x0000ffff; - right ^= temp; - left ^= temp << 16; - temp = (left >>> 4 ^ right) & 0x0f0f0f0f; - right ^= temp; - left ^= temp << 4; +var WHOLEPI = "314159265359"; +var SQRTPI = "177245385090"; - //for Cipher Block Chaining mode, xor the message with the previous result - if (mode === 1) { - if (encrypt) { - cbcleft = left; - cbcright = right; - } else { - left ^= cbcleft2; - right ^= cbcright2; - } - } +var mtf = function(array, index) { + var src = array[index], i; + for (i = index; i > 0; i--) { + array[i] = array[i-1]; + } + array[0] = src; + return src; +}; - result[k++] = left >>> 24; - result[k++] = left >>> 16 & 0xff; - result[k++] = left >>> 8 & 0xff; - result[k++] = left & 0xff; - result[k++] = right >>> 24; - result[k++] = right >>> 16 & 0xff; - result[k++] = right >>> 8 & 0xff; - result[k++] = right & 0xff; - } //for every 8 characters, or 64 bits in the message +var Err = { + OK: 0, + LAST_BLOCK: -1, + NOT_BZIP_DATA: -2, + UNEXPECTED_INPUT_EOF: -3, + UNEXPECTED_OUTPUT_EOF: -4, + DATA_ERROR: -5, + OUT_OF_MEMORY: -6, + OBSOLETE_INPUT: -7, + END_OF_BLOCK: -8 +}; +var ErrorMessages = {}; +ErrorMessages[Err.LAST_BLOCK] = "Bad file checksum"; +ErrorMessages[Err.NOT_BZIP_DATA] = "Not bzip data"; +ErrorMessages[Err.UNEXPECTED_INPUT_EOF] = "Unexpected input EOF"; +ErrorMessages[Err.UNEXPECTED_OUTPUT_EOF] = "Unexpected output EOF"; +ErrorMessages[Err.DATA_ERROR] = "Data error"; +ErrorMessages[Err.OUT_OF_MEMORY] = "Out of memory"; +ErrorMessages[Err.OBSOLETE_INPUT] = "Obsolete (pre 0.9.5) bzip format not supported."; - //only remove padding if decrypting - note that you need to use the same padding option for both encrypt and decrypt - if (!encrypt) { - result = des_removePadding(result, padding); - } +var _throw = function(status, optDetail) { + var msg = ErrorMessages[status] || 'unknown error'; + if (optDetail) { msg += ': '+optDetail; } + var e = new TypeError(msg); + e.errorCode = status; + throw e; +}; - return result; -} //end of des +var Bunzip = function(inputStream, outputStream) { + this.writePos = this.writeCurrent = this.writeCount = 0; + this._start_bunzip(inputStream, outputStream); +}; +Bunzip.prototype._init_block = function() { + var moreBlocks = this._get_next_block(); + if ( !moreBlocks ) { + this.writeCount = -1; + return false; /* no more blocks */ + } + this.blockCRC = new crc32$1(); + return true; +}; +/* XXX micro-bunzip uses (inputStream, inputBuffer, len) as arguments */ +Bunzip.prototype._start_bunzip = function(inputStream, outputStream) { + /* Ensure that file starts with "BZh['1'-'9']." */ + var buf = new Uint8Array(4); + if (inputStream.read(buf, 0, 4) !== 4 || + String.fromCharCode(buf[0], buf[1], buf[2]) !== 'BZh') + _throw(Err.NOT_BZIP_DATA, 'bad magic'); -//des_createKeys -//this takes as input a 64 bit key (even though only 56 bits are used) -//as an array of 2 integers, and returns 16 48 bit keys + var level = buf[3] - 0x30; + if (level < 1 || level > 9) + _throw(Err.NOT_BZIP_DATA, 'level out of range'); -function des_createKeys(key) { - //declaring this locally speeds things up a bit - const pc2bytes0 = [0, 0x4, 0x20000000, 0x20000004, 0x10000, 0x10004, 0x20010000, 0x20010004, 0x200, 0x204, 0x20000200, 0x20000204, 0x10200, 0x10204, 0x20010200, 0x20010204]; - const pc2bytes1 = [0, 0x1, 0x100000, 0x100001, 0x4000000, 0x4000001, 0x4100000, 0x4100001, 0x100, 0x101, 0x100100, 0x100101, 0x4000100, 0x4000101, 0x4100100, 0x4100101]; - const pc2bytes2 = [0, 0x8, 0x800, 0x808, 0x1000000, 0x1000008, 0x1000800, 0x1000808, 0, 0x8, 0x800, 0x808, 0x1000000, 0x1000008, 0x1000800, 0x1000808]; - const pc2bytes3 = [0, 0x200000, 0x8000000, 0x8200000, 0x2000, 0x202000, 0x8002000, 0x8202000, 0x20000, 0x220000, 0x8020000, 0x8220000, 0x22000, 0x222000, 0x8022000, 0x8222000]; - const pc2bytes4 = [0, 0x40000, 0x10, 0x40010, 0, 0x40000, 0x10, 0x40010, 0x1000, 0x41000, 0x1010, 0x41010, 0x1000, 0x41000, 0x1010, 0x41010]; - const pc2bytes5 = [0, 0x400, 0x20, 0x420, 0, 0x400, 0x20, 0x420, 0x2000000, 0x2000400, 0x2000020, 0x2000420, 0x2000000, 0x2000400, 0x2000020, 0x2000420]; - const pc2bytes6 = [0, 0x10000000, 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002, 0, 0x10000000, 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002]; - const pc2bytes7 = [0, 0x10000, 0x800, 0x10800, 0x20000000, 0x20010000, 0x20000800, 0x20010800, 0x20000, 0x30000, 0x20800, 0x30800, 0x20020000, 0x20030000, 0x20020800, 0x20030800]; - const pc2bytes8 = [0, 0x40000, 0, 0x40000, 0x2, 0x40002, 0x2, 0x40002, 0x2000000, 0x2040000, 0x2000000, 0x2040000, 0x2000002, 0x2040002, 0x2000002, 0x2040002]; - const pc2bytes9 = [0, 0x10000000, 0x8, 0x10000008, 0, 0x10000000, 0x8, 0x10000008, 0x400, 0x10000400, 0x408, 0x10000408, 0x400, 0x10000400, 0x408, 0x10000408]; - const pc2bytes10 = [0, 0x20, 0, 0x20, 0x100000, 0x100020, 0x100000, 0x100020, 0x2000, 0x2020, 0x2000, 0x2020, 0x102000, 0x102020, 0x102000, 0x102020]; - const pc2bytes11 = [0, 0x1000000, 0x200, 0x1000200, 0x200000, 0x1200000, 0x200200, 0x1200200, 0x4000000, 0x5000000, 0x4000200, 0x5000200, 0x4200000, 0x5200000, 0x4200200, 0x5200200]; - const pc2bytes12 = [0, 0x1000, 0x8000000, 0x8001000, 0x80000, 0x81000, 0x8080000, 0x8081000, 0x10, 0x1010, 0x8000010, 0x8001010, 0x80010, 0x81010, 0x8080010, 0x8081010]; - const pc2bytes13 = [0, 0x4, 0x100, 0x104, 0, 0x4, 0x100, 0x104, 0x1, 0x5, 0x101, 0x105, 0x1, 0x5, 0x101, 0x105]; + this.reader = new bitreader(inputStream); - //how many iterations (1 for des, 3 for triple des) - const iterations = key.length > 8 ? 3 : 1; //changed by Paul 16/6/2007 to use Triple DES for 9+ byte keys - //stores the return keys - const keys = new Array(32 * iterations); - //now define the left shifts which need to be done - const shifts = [0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0]; - //other variables - let lefttemp; - let righttemp; - let m = 0; - let n = 0; - let temp; + /* Fourth byte (ascii '1'-'9'), indicates block size in units of 100k of + uncompressed data. Allocate intermediate buffer for block. */ + this.dbufSize = 100000 * level; + this.nextoutput = 0; + this.outputStream = outputStream; + this.streamCRC = 0; +}; +Bunzip.prototype._get_next_block = function() { + var i, j, k; + var reader = this.reader; + // this is get_next_block() function from micro-bunzip: + /* Read in header signature and CRC, then validate signature. + (last block signature means CRC is for whole file, return now) */ + var h = reader.pi(); + if (h === SQRTPI) { // last block + return false; /* no more blocks */ + } + if (h !== WHOLEPI) + _throw(Err.NOT_BZIP_DATA); + this.targetBlockCRC = reader.read(32) >>> 0; // (convert to unsigned) + this.streamCRC = (this.targetBlockCRC ^ + ((this.streamCRC << 1) | (this.streamCRC>>>31))) >>> 0; + /* We can add support for blockRandomised if anybody complains. There was + some code for this in busybox 1.0.0-pre3, but nobody ever noticed that + it didn't actually work. */ + if (reader.read(1)) + _throw(Err.OBSOLETE_INPUT); + var origPointer = reader.read(24); + if (origPointer > this.dbufSize) + _throw(Err.DATA_ERROR, 'initial position out of bounds'); + /* mapping table: if some byte values are never used (encoding things + like ascii text), the compression code removes the gaps to have fewer + symbols to deal with, and writes a sparse bitfield indicating which + values were present. We make a translation table to convert the symbols + back to the corresponding bytes. */ + var t = reader.read(16); + var symToByte = new Uint8Array(256), symTotal = 0; + for (i = 0; i < 16; i++) { + if (t & (1 << (0xF - i))) { + var o = i * 16; + k = reader.read(16); + for (j = 0; j < 16; j++) + if (k & (1 << (0xF - j))) + symToByte[symTotal++] = o + j; + } + } + + /* How many different huffman coding groups does this block use? */ + var groupCount = reader.read(3); + if (groupCount < MIN_GROUPS || groupCount > MAX_GROUPS) + _throw(Err.DATA_ERROR); + /* nSelectors: Every GROUP_SIZE many symbols we select a new huffman coding + group. Read in the group selector list, which is stored as MTF encoded + bit runs. (MTF=Move To Front, as each value is used it's moved to the + start of the list.) */ + var nSelectors = reader.read(15); + if (nSelectors === 0) + _throw(Err.DATA_ERROR); - for (let j = 0; j < iterations; j++) { - //either 1 or 3 iterations - let left = key[m++] << 24 | key[m++] << 16 | key[m++] << 8 | key[m++]; - let right = key[m++] << 24 | key[m++] << 16 | key[m++] << 8 | key[m++]; + var mtfSymbol = new Uint8Array(256); + for (i = 0; i < groupCount; i++) + mtfSymbol[i] = i; - temp = (left >>> 4 ^ right) & 0x0f0f0f0f; - right ^= temp; - left ^= temp << 4; - temp = (right >>> -16 ^ left) & 0x0000ffff; - left ^= temp; - right ^= temp << -16; - temp = (left >>> 2 ^ right) & 0x33333333; - right ^= temp; - left ^= temp << 2; - temp = (right >>> -16 ^ left) & 0x0000ffff; - left ^= temp; - right ^= temp << -16; - temp = (left >>> 1 ^ right) & 0x55555555; - right ^= temp; - left ^= temp << 1; - temp = (right >>> 8 ^ left) & 0x00ff00ff; - left ^= temp; - right ^= temp << 8; - temp = (left >>> 1 ^ right) & 0x55555555; - right ^= temp; - left ^= temp << 1; + var selectors = new Uint8Array(nSelectors); // was 32768... - //the right side needs to be shifted and to get the last four bits of the left side - temp = left << 8 | right >>> 20 & 0x000000f0; - //left needs to be put upside down - left = right << 24 | right << 8 & 0xff0000 | right >>> 8 & 0xff00 | right >>> 24 & 0xf0; - right = temp; + for (i = 0; i < nSelectors; i++) { + /* Get next value */ + for (j = 0; reader.read(1); j++) + if (j >= groupCount) _throw(Err.DATA_ERROR); + /* Decode MTF to get the next selector */ + selectors[i] = mtf(mtfSymbol, j); + } - //now go through and perform these shifts on the left and right keys - for (let i = 0; i < shifts.length; i++) { - //shift the keys either one or two bits to the left - if (shifts[i]) { - left = left << 2 | left >>> 26; - right = right << 2 | right >>> 26; - } else { - left = left << 1 | left >>> 27; - right = right << 1 | right >>> 27; + /* Read the huffman coding tables for each group, which code for symTotal + literal symbols, plus two run symbols (RUNA, RUNB) */ + var symCount = symTotal + 2; + var groups = [], hufGroup; + for (j = 0; j < groupCount; j++) { + var length = new Uint8Array(symCount), temp = new Uint16Array(MAX_HUFCODE_BITS + 1); + /* Read huffman code lengths for each symbol. They're stored in + a way similar to mtf; record a starting value for the first symbol, + and an offset from the previous value for everys symbol after that. */ + t = reader.read(5); // lengths + for (i = 0; i < symCount; i++) { + for (;;) { + if (t < 1 || t > MAX_HUFCODE_BITS) _throw(Err.DATA_ERROR); + /* If first bit is 0, stop. Else second bit indicates whether + to increment or decrement the value. */ + if(!reader.read(1)) + break; + if(!reader.read(1)) + t++; + else + t--; } - left &= -0xf; - right &= -0xf; - - //now apply PC-2, in such a way that E is easier when encrypting or decrypting - //this conversion will look like PC-2 except only the last 6 bits of each byte are used - //rather than 48 consecutive bits and the order of lines will be according to - //how the S selection functions will be applied: S2, S4, S6, S8, S1, S3, S5, S7 - lefttemp = pc2bytes0[left >>> 28] | pc2bytes1[left >>> 24 & 0xf] | pc2bytes2[left >>> 20 & 0xf] | pc2bytes3[left >>> 16 & 0xf] | pc2bytes4[left >>> 12 & 0xf] | pc2bytes5[left >>> 8 & 0xf] | pc2bytes6[left >>> 4 & 0xf]; - righttemp = pc2bytes7[right >>> 28] | pc2bytes8[right >>> 24 & 0xf] | pc2bytes9[right >>> 20 & 0xf] | pc2bytes10[right >>> 16 & 0xf] | pc2bytes11[right >>> 12 & 0xf] | pc2bytes12[right >>> 8 & 0xf] | pc2bytes13[right >>> 4 & 0xf]; - temp = (righttemp >>> 16 ^ lefttemp) & 0x0000ffff; - keys[n++] = lefttemp ^ temp; - keys[n++] = righttemp ^ temp << 16; + length[i] = t; } - } //for each iterations - //return the keys we've created - return keys; -} //end of des_createKeys + /* Find largest and smallest lengths in this group */ + var minLen, maxLen; + minLen = maxLen = length[0]; + for (i = 1; i < symCount; i++) { + if (length[i] > maxLen) + maxLen = length[i]; + else if (length[i] < minLen) + minLen = length[i]; + } -function des_addPadding(message, padding) { - const padLength = 8 - message.length % 8; - - let pad; - if (padding === 2 && padLength < 8) { - //pad the message with spaces - pad = " ".charCodeAt(0); - } else if (padding === 1) { - //PKCS7 padding - pad = padLength; - } else if (!padding && padLength < 8) { - //pad the message out with null bytes - pad = 0; - } else if (padLength === 8) { - return message; - } else { - throw new Error('des: invalid padding'); + /* Calculate permute[], base[], and limit[] tables from length[]. + * + * permute[] is the lookup table for converting huffman coded symbols + * into decoded symbols. base[] is the amount to subtract from the + * value of a huffman symbol of a given length when using permute[]. + * + * limit[] indicates the largest numerical value a symbol with a given + * number of bits can have. This is how the huffman codes can vary in + * length: each code with a value>limit[length] needs another bit. + */ + hufGroup = {}; + groups.push(hufGroup); + hufGroup.permute = new Uint16Array(MAX_SYMBOLS); + hufGroup.limit = new Uint32Array(MAX_HUFCODE_BITS + 2); + hufGroup.base = new Uint32Array(MAX_HUFCODE_BITS + 1); + hufGroup.minLen = minLen; + hufGroup.maxLen = maxLen; + /* Calculate permute[]. Concurently, initialize temp[] and limit[]. */ + var pp = 0; + for (i = minLen; i <= maxLen; i++) { + temp[i] = hufGroup.limit[i] = 0; + for (t = 0; t < symCount; t++) + if (length[t] === i) + hufGroup.permute[pp++] = t; + } + /* Count symbols coded for at each bit length */ + for (i = 0; i < symCount; i++) + temp[length[i]]++; + /* Calculate limit[] (the largest symbol-coding value at each bit + * length, which is (previous limit<<1)+symbols at this level), and + * base[] (number of symbols to ignore at each bit length, which is + * limit minus the cumulative count of symbols coded for already). */ + pp = t = 0; + for (i = minLen; i < maxLen; i++) { + pp += temp[i]; + /* We read the largest possible symbol size and then unget bits + after determining how many we need, and those extra bits could + be set to anything. (They're noise from future symbols.) At + each level we're really only interested in the first few bits, + so here we set all the trailing to-be-ignored bits to 1 so they + don't affect the value>limit[length] comparison. */ + hufGroup.limit[i] = pp - 1; + pp <<= 1; + t += temp[i]; + hufGroup.base[i + 1] = pp - t; + } + hufGroup.limit[maxLen + 1] = Number.MAX_VALUE; /* Sentinal value for reading next sym. */ + hufGroup.limit[maxLen] = pp + temp[maxLen] - 1; + hufGroup.base[minLen] = 0; } + /* We've finished reading and digesting the block header. Now read this + block's huffman coded symbols from the file and undo the huffman coding + and run length encoding, saving the result into dbuf[dbufCount++]=uc */ - const paddedMessage = new Uint8Array(message.length + padLength); - for (let i = 0; i < message.length; i++) { - paddedMessage[i] = message[i]; + /* Initialize symbol occurrence counters and symbol Move To Front table */ + var byteCount = new Uint32Array(256); + for (i = 0; i < 256; i++) + mtfSymbol[i] = i; + /* Loop through compressed symbols. */ + var runPos = 0, dbufCount = 0, selector = 0, uc; + var dbuf = this.dbuf = new Uint32Array(this.dbufSize); + symCount = 0; + for (;;) { + /* Determine which huffman coding group to use. */ + if (!(symCount--)) { + symCount = GROUP_SIZE - 1; + if (selector >= nSelectors) { _throw(Err.DATA_ERROR); } + hufGroup = groups[selectors[selector++]]; + } + /* Read next huffman-coded symbol. */ + i = hufGroup.minLen; + j = reader.read(i); + for (;;i++) { + if (i > hufGroup.maxLen) { _throw(Err.DATA_ERROR); } + if (j <= hufGroup.limit[i]) + break; + j = (j << 1) | reader.read(1); + } + /* Huffman decode value to get nextSym (with bounds checking) */ + j -= hufGroup.base[i]; + if (j < 0 || j >= MAX_SYMBOLS) { _throw(Err.DATA_ERROR); } + var nextSym = hufGroup.permute[j]; + /* We have now decoded the symbol, which indicates either a new literal + byte, or a repeated run of the most recent literal byte. First, + check if nextSym indicates a repeated run, and if so loop collecting + how many times to repeat the last literal. */ + if (nextSym === SYMBOL_RUNA || nextSym === SYMBOL_RUNB) { + /* If this is the start of a new run, zero out counter */ + if (!runPos){ + runPos = 1; + t = 0; + } + /* Neat trick that saves 1 symbol: instead of or-ing 0 or 1 at + each bit position, add 1 or 2 instead. For example, + 1011 is 1<<0 + 1<<1 + 2<<2. 1010 is 2<<0 + 2<<1 + 1<<2. + You can make any bit pattern that way using 1 less symbol than + the basic or 0/1 method (except all bits 0, which would use no + symbols, but a run of length 0 doesn't mean anything in this + context). Thus space is saved. */ + if (nextSym === SYMBOL_RUNA) + t += runPos; + else + t += 2 * runPos; + runPos <<= 1; + continue; + } + /* When we hit the first non-run symbol after a run, we now know + how many times to repeat the last literal, so append that many + copies to our buffer of decoded symbols (dbuf) now. (The last + literal used is the one at the head of the mtfSymbol array.) */ + if (runPos){ + runPos = 0; + if (dbufCount + t > this.dbufSize) { _throw(Err.DATA_ERROR); } + uc = symToByte[mtfSymbol[0]]; + byteCount[uc] += t; + while (t--) + dbuf[dbufCount++] = uc; + } + /* Is this the terminating symbol? */ + if (nextSym > symTotal) + break; + /* At this point, nextSym indicates a new literal character. Subtract + one to get the position in the MTF array at which this literal is + currently to be found. (Note that the result can't be -1 or 0, + because 0 and 1 are RUNA and RUNB. But another instance of the + first symbol in the mtf array, position 0, would have been handled + as part of a run above. Therefore 1 unused mtf position minus + 2 non-literal nextSym values equals -1.) */ + if (dbufCount >= this.dbufSize) { _throw(Err.DATA_ERROR); } + i = nextSym - 1; + uc = mtf(mtfSymbol, i); + uc = symToByte[uc]; + /* We have our literal byte. Save it into dbuf. */ + byteCount[uc]++; + dbuf[dbufCount++] = uc; } - for (let j = 0; j < padLength; j++) { - paddedMessage[message.length + j] = pad; + /* At this point, we've read all the huffman-coded symbols (and repeated + runs) for this block from the input stream, and decoded them into the + intermediate buffer. There are dbufCount many decoded bytes in dbuf[]. + Now undo the Burrows-Wheeler transform on dbuf. + See http://dogma.net/markn/articles/bwt/bwt.htm + */ + if (origPointer < 0 || origPointer >= dbufCount) { _throw(Err.DATA_ERROR); } + /* Turn byteCount into cumulative occurrence counts of 0 to n-1. */ + j = 0; + for (i = 0; i < 256; i++) { + k = j + byteCount[i]; + byteCount[i] = j; + j = k; } - - return paddedMessage; -} - -function des_removePadding(message, padding) { - let padLength = null; - let pad; - if (padding === 2) { - // space padded - pad = " ".charCodeAt(0); - } else if (padding === 1) { - // PKCS7 - padLength = message[message.length - 1]; - } else if (!padding) { - // null padding - pad = 0; - } else { - throw new Error('des: invalid padding'); + /* Figure out what order dbuf would be in if we sorted it. */ + for (i = 0; i < dbufCount; i++) { + uc = dbuf[i] & 0xff; + dbuf[byteCount[uc]] |= (i << 8); + byteCount[uc]++; } - - if (!padLength) { - padLength = 1; - while (message[message.length - padLength] === pad) { - padLength++; - } - padLength--; + /* Decode first byte by hand to initialize "previous" byte. Note that it + doesn't get output, and if the first three characters are identical + it doesn't qualify as a run (hence writeRunCountdown=5). */ + var pos = 0, current = 0, run = 0; + if (dbufCount) { + pos = dbuf[origPointer]; + current = (pos & 0xff); + pos >>= 8; + run = -1; } + this.writePos = pos; + this.writeCurrent = current; + this.writeCount = dbufCount; + this.writeRun = run; - return message.subarray(0, message.length - padLength); -} - -// added by Recurity Labs - -function TripleDES(key) { - this.key = []; + return true; /* more blocks to come */ +}; +/* Undo burrows-wheeler transform on intermediate buffer to produce output. + If start_bunzip was initialized with out_fd=-1, then up to len bytes of + data are written to outbuf. Return value is number of bytes written or + error (all errors are negative numbers). If out_fd!=-1, outbuf and len + are ignored, data is written to out_fd and return is RETVAL_OK or error. +*/ +Bunzip.prototype._read_bunzip = function(outputBuffer, len) { + var copies, previous, outbyte; + /* james@jamestaylor.org: writeCount goes to -1 when the buffer is fully + decoded, which results in this returning RETVAL_LAST_BLOCK, also + equal to -1... Confusing, I'm returning 0 here to indicate no + bytes written into the buffer */ + if (this.writeCount < 0) { return 0; } + var dbuf = this.dbuf, pos = this.writePos, current = this.writeCurrent; + var dbufCount = this.writeCount; this.outputsize; + var run = this.writeRun; - for (let i = 0; i < 3; i++) { - this.key.push(new Uint8Array(key.subarray(i * 8, i * 8 + 8))); + while (dbufCount) { + dbufCount--; + previous = current; + pos = dbuf[pos]; + current = pos & 0xff; + pos >>= 8; + if (run++ === 3){ + copies = current; + outbyte = previous; + current = -1; + } else { + copies = 1; + outbyte = current; + } + this.blockCRC.updateCRCRun(outbyte, copies); + while (copies--) { + this.outputStream.writeByte(outbyte); + this.nextoutput++; + } + if (current != previous) + run = 0; } + this.writeCount = dbufCount; + // check CRC + if (this.blockCRC.getCRC() !== this.targetBlockCRC) { + _throw(Err.DATA_ERROR, "Bad block CRC "+ + "(got "+this.blockCRC.getCRC().toString(16)+ + " expected "+this.targetBlockCRC.toString(16)+")"); + } + return this.nextoutput; +}; - this.encrypt = function (block) { - return des(des_createKeys(this.key[2]), des(des_createKeys(this.key[1]), des(des_createKeys(this.key[0]), block, true, 0, null, null), false, 0, null, null), true, 0, null, null); - }; -} - -TripleDES.keySize = TripleDES.prototype.keySize = 24; -TripleDES.blockSize = TripleDES.prototype.blockSize = 8; - -// This is "original" DES - -function DES(key) { - this.key = key; - - this.encrypt = function (block, padding) { - const keys = des_createKeys(this.key); - return des(keys, block, true, 0, null, padding); +var coerceInputStream = function(input) { + if ('readByte' in input) { return input; } + var inputStream = new stream(); + inputStream.pos = 0; + inputStream.readByte = function() { return input[this.pos++]; }; + inputStream.seek = function(pos) { this.pos = pos; }; + inputStream.eof = function() { return this.pos >= input.length; }; + return inputStream; +}; +var coerceOutputStream = function(output) { + var outputStream = new stream(); + var resizeOk = true; + if (output) { + if (typeof(output)==='number') { + outputStream.buffer = new Uint8Array(output); + resizeOk = false; + } else if ('writeByte' in output) { + return output; + } else { + outputStream.buffer = output; + resizeOk = false; + } + } else { + outputStream.buffer = new Uint8Array(16384); + } + outputStream.pos = 0; + outputStream.writeByte = function(_byte) { + if (resizeOk && this.pos >= this.buffer.length) { + var newBuffer = new Uint8Array(this.buffer.length*2); + newBuffer.set(this.buffer); + this.buffer = newBuffer; + } + this.buffer[this.pos++] = _byte; }; - - this.decrypt = function (block, padding) { - const keys = des_createKeys(this.key); - return des(keys, block, false, 0, null, padding); + outputStream.getBuffer = function() { + // trim buffer + if (this.pos !== this.buffer.length) { + if (!resizeOk) + throw new TypeError('outputsize does not match decoded input'); + var newBuffer = new Uint8Array(this.pos); + newBuffer.set(this.buffer.subarray(0, this.pos)); + this.buffer = newBuffer; + } + return this.buffer; }; -} - -exports.default = { DES, TripleDES }; - -},{}],86:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _aes = require('./aes'); - -var _aes2 = _interopRequireDefault(_aes); - -var _des = require('./des.js'); - -var _des2 = _interopRequireDefault(_des); - -var _cast = require('./cast5'); + outputStream._coerced = true; + return outputStream; +}; -var _cast2 = _interopRequireDefault(_cast); +/* Static helper functions */ +// 'input' can be a stream or a buffer +// 'output' can be a stream or a buffer or a number (buffer size) +const decode$2 = function(input, output, multistream) { + // make a stream from a buffer, if necessary + var inputStream = coerceInputStream(input); + var outputStream = coerceOutputStream(output); -var _twofish = require('./twofish'); + var bz = new Bunzip(inputStream, outputStream); + while (true) { + if ('eof' in inputStream && inputStream.eof()) break; + if (bz._init_block()) { + bz._read_bunzip(); + } else { + var targetStreamCRC = bz.reader.read(32) >>> 0; // (convert to unsigned) + if (targetStreamCRC !== bz.streamCRC) { + _throw(Err.DATA_ERROR, "Bad stream CRC "+ + "(got "+bz.streamCRC.toString(16)+ + " expected "+targetStreamCRC.toString(16)+")"); + } + if (multistream && + 'eof' in inputStream && + !inputStream.eof()) { + // note that start_bunzip will also resync the bit reader to next byte + bz._start_bunzip(inputStream, outputStream); + } else break; + } + } + if ('getBuffer' in outputStream) + return outputStream.getBuffer(); +}; +const decodeBlock = function(input, pos, output) { + // make a stream from a buffer, if necessary + var inputStream = coerceInputStream(input); + var outputStream = coerceOutputStream(output); + var bz = new Bunzip(inputStream, outputStream); + bz.reader.seek(pos); + /* Fill the decode buffer for the block */ + var moreBlocks = bz._get_next_block(); + if (moreBlocks) { + /* Init the CRC for writing */ + bz.blockCRC = new crc32$1(); -var _twofish2 = _interopRequireDefault(_twofish); + /* Zero this so the current byte from before the seek is not written */ + bz.writeCopies = 0; -var _blowfish = require('./blowfish'); + /* Decompress the block and write to stdout */ + bz._read_bunzip(); + // XXX keep writing? + } + if ('getBuffer' in outputStream) + return outputStream.getBuffer(); +}; +/* Reads bzip2 file from stream or buffer `input`, and invoke + * `callback(position, size)` once for each bzip2 block, + * where position gives the starting position (in *bits*) + * and size gives uncompressed size of the block (in *bytes*). */ +const table = function(input, callback, multistream) { + // make a stream from a buffer, if necessary + var inputStream = new stream(); + inputStream.delegate = coerceInputStream(input); + inputStream.pos = 0; + inputStream.readByte = function() { + this.pos++; + return this.delegate.readByte(); + }; + if (inputStream.delegate.eof) { + inputStream.eof = inputStream.delegate.eof.bind(inputStream.delegate); + } + var outputStream = new stream(); + outputStream.pos = 0; + outputStream.writeByte = function() { this.pos++; }; -var _blowfish2 = _interopRequireDefault(_blowfish); + var bz = new Bunzip(inputStream, outputStream); + var blockSize = bz.dbufSize; + while (true) { + if ('eof' in inputStream && inputStream.eof()) break; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + var position = inputStream.pos*8 + bz.reader.bitOffset; + if (bz.reader.hasByte) { position -= 8; } -exports.default = { - /** - * AES-128 encryption and decryption (ID 7) - * @function - * @param {String} key 128-bit key - * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} - * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} - * @returns {Object} - * @requires asmcrypto.js - */ - aes128: (0, _aes2.default)(128), - /** - * AES-128 Block Cipher (ID 8) - * @function - * @param {String} key 192-bit key - * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} - * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} - * @returns {Object} - * @requires asmcrypto.js - */ - aes192: (0, _aes2.default)(192), - /** - * AES-128 Block Cipher (ID 9) - * @function - * @param {String} key 256-bit key - * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} - * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} - * @returns {Object} - * @requires asmcrypto.js - */ - aes256: (0, _aes2.default)(256), - // Not in OpenPGP specifications - des: _des2.default.DES, - /** - * Triple DES Block Cipher (ID 2) - * @function - * @param {String} key 192-bit key - * @see {@link https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-67r2.pdf|NIST SP 800-67} - * @returns {Object} - */ - tripledes: _des2.default.TripleDES, - '3des': _des2.default.TripleDES, - /** - * CAST-128 Block Cipher (ID 3) - * @function - * @param {String} key 128-bit key - * @see {@link https://tools.ietf.org/html/rfc2144|The CAST-128 Encryption Algorithm} - * @returns {Object} - */ - cast5: _cast2.default, - /** - * Twofish Block Cipher (ID 10) - * @function - * @param {String} key 256-bit key - * @see {@link https://tools.ietf.org/html/rfc4880#ref-TWOFISH|TWOFISH} - * @returns {Object} - */ - twofish: _twofish2.default, - /** - * Blowfish Block Cipher (ID 4) - * @function - * @param {String} key 128-bit key - * @see {@link https://tools.ietf.org/html/rfc4880#ref-BLOWFISH|BLOWFISH} - * @returns {Object} - */ - blowfish: _blowfish2.default, - /** - * Not implemented - * @function - * @throws {Error} - */ - idea: function idea() { - throw new Error('IDEA symmetric-key algorithm not implemented'); + if (bz._init_block()) { + var start = outputStream.pos; + bz._read_bunzip(); + callback(position, outputStream.pos - start); + } else { + bz.reader.read(32); // (but we ignore the crc) + if (multistream && + 'eof' in inputStream && + !inputStream.eof()) { + // note that start_bunzip will also resync the bit reader to next byte + bz._start_bunzip(inputStream, outputStream); + console.assert(bz.dbufSize === blockSize, + "shouldn't change block size within multistream file"); + } else break; + } } -}; /** - * @fileoverview Symmetric cryptography functions - * @requires crypto/cipher/aes - * @requires crypto/cipher/des - * @requires crypto/cipher/cast5 - * @requires crypto/cipher/twofish - * @requires crypto/cipher/blowfish - * @module crypto/cipher - */ +}; -},{"./aes":82,"./blowfish":83,"./cast5":84,"./des.js":85,"./twofish":87}],87:[function(require,module,exports){ -"use strict"; +var lib = { + Bunzip, + Stream: stream, + Err, + decode: decode$2, + decodeBlock, + table +}; +var lib_4 = lib.decode; -Object.defineProperty(exports, "__esModule", { - value: true -}); -/* eslint-disable no-mixed-operators, no-fallthrough */ +// GPG4Browsers - An OpenPGP implementation in javascript -/* Modified by Recurity Labs GmbH - * - * Cipher.js - * A block-cipher algorithm implementation on JavaScript - * See Cipher.readme.txt for further information. - * - * Copyright(c) 2009 Atsushi Oka [ http://oka.nu/ ] - * This script file is distributed under the LGPL - * - * ACKNOWLEDGMENT - * - * The main subroutines are written by Michiel van Everdingen. - * - * Michiel van Everdingen - * http://home.versatel.nl/MAvanEverdingen/index.html - * - * All rights for these routines are reserved to Michiel van Everdingen. +/** + * Implementation of the Literal Data Packet (Tag 11) * + * {@link https://tools.ietf.org/html/rfc4880#section-5.9|RFC4880 5.9}: + * A Literal Data packet contains the body of a message; data that is not to be + * further interpreted. */ +class LiteralDataPacket { + static get tag() { + return enums.packet.literalData; + } -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//Math -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -const MAXINT = 0xFFFFFFFF; - -function rotw(w, n) { - return (w << n | w >>> 32 - n) & MAXINT; -} - -function getW(a, i) { - return a[i] | a[i + 1] << 8 | a[i + 2] << 16 | a[i + 3] << 24; -} - -function setW(a, i, w) { - a.splice(i, 4, w & 0xFF, w >>> 8 & 0xFF, w >>> 16 & 0xFF, w >>> 24 & 0xFF); -} - -function getB(x, n) { - return x >>> n * 8 & 0xFF; -} - -// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Twofish -// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -function createTwofish() { - // - let keyBytes = null; - let dataBytes = null; - let dataOffset = -1; - // var dataLength = -1; - // var idx2 = -1; - // - - let tfsKey = []; - let tfsM = [[], [], [], []]; - - function tfsInit(key) { - keyBytes = key; - let i; - let a; - let b; - let c; - let d; - const meKey = []; - const moKey = []; - const inKey = []; - let kLen; - const sKey = []; - let f01; - let f5b; - let fef; - - const q0 = [[8, 1, 7, 13, 6, 15, 3, 2, 0, 11, 5, 9, 14, 12, 10, 4], [2, 8, 11, 13, 15, 7, 6, 14, 3, 1, 9, 4, 0, 10, 12, 5]]; - const q1 = [[14, 12, 11, 8, 1, 2, 3, 5, 15, 4, 10, 6, 7, 0, 9, 13], [1, 14, 2, 11, 4, 12, 3, 7, 6, 13, 10, 5, 15, 9, 0, 8]]; - const q2 = [[11, 10, 5, 14, 6, 13, 9, 0, 12, 8, 15, 3, 2, 4, 7, 1], [4, 12, 7, 5, 1, 6, 9, 10, 0, 14, 13, 8, 2, 11, 3, 15]]; - const q3 = [[13, 7, 15, 4, 1, 2, 6, 14, 9, 11, 3, 0, 8, 5, 12, 10], [11, 9, 5, 1, 12, 3, 13, 14, 6, 4, 7, 15, 2, 0, 8, 10]]; - const ror4 = [0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15]; - const ashx = [0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 5, 14, 7]; - const q = [[], []]; - const m = [[], [], [], []]; - - function ffm5b(x) { - return x ^ x >> 2 ^ [0, 90, 180, 238][x & 3]; - } - - function ffmEf(x) { - return x ^ x >> 1 ^ x >> 2 ^ [0, 238, 180, 90][x & 3]; - } - - function mdsRem(p, q) { - let i; - let t; - let u; - for (i = 0; i < 8; i++) { - t = q >>> 24; - q = q << 8 & MAXINT | p >>> 24; - p = p << 8 & MAXINT; - u = t << 1; - if (t & 128) { - u ^= 333; - } - q ^= t ^ u << 16; - u ^= t >>> 1; - if (t & 1) { - u ^= 166; - } - q ^= u << 24 | u << 8; - } - return q; - } - - function qp(n, x) { - const a = x >> 4; - const b = x & 15; - const c = q0[n][a ^ b]; - const d = q1[n][ror4[b] ^ ashx[a]]; - return q3[n][ror4[d] ^ ashx[c]] << 4 | q2[n][c ^ d]; - } + /** + * @param {Date} date - The creation date of the literal package + */ + constructor(date = new Date()) { + this.format = enums.literal.utf8; // default format for literal data packets + this.date = util.normalizeDate(date); + this.text = null; // textual data representation + this.data = null; // literal data representation + this.filename = ''; + } - function hFun(x, key) { - let a = getB(x, 0); - let b = getB(x, 1); - let c = getB(x, 2); - let d = getB(x, 3); - switch (kLen) { - case 4: - a = q[1][a] ^ getB(key[3], 0); - b = q[0][b] ^ getB(key[3], 1); - c = q[0][c] ^ getB(key[3], 2); - d = q[1][d] ^ getB(key[3], 3); - case 3: - a = q[1][a] ^ getB(key[2], 0); - b = q[1][b] ^ getB(key[2], 1); - c = q[0][c] ^ getB(key[2], 2); - d = q[0][d] ^ getB(key[2], 3); - case 2: - a = q[0][q[0][a] ^ getB(key[1], 0)] ^ getB(key[0], 0); - b = q[0][q[1][b] ^ getB(key[1], 1)] ^ getB(key[0], 1); - c = q[1][q[0][c] ^ getB(key[1], 2)] ^ getB(key[0], 2); - d = q[1][q[1][d] ^ getB(key[1], 3)] ^ getB(key[0], 3); - } - return m[0][a] ^ m[1][b] ^ m[2][c] ^ m[3][d]; - } + /** + * Set the packet data to a javascript native string, end of line + * will be normalized to \r\n and by default text is converted to UTF8 + * @param {String | ReadableStream} text - Any native javascript string + * @param {enums.literal} [format] - The format of the string of bytes + */ + setText(text, format = enums.literal.utf8) { + this.format = format; + this.text = text; + this.data = null; + } - keyBytes = keyBytes.slice(0, 32); - i = keyBytes.length; - while (i !== 16 && i !== 24 && i !== 32) { - keyBytes[i++] = 0; + /** + * Returns literal data packets as native JavaScript string + * with normalized end of line to \n + * @param {Boolean} [clone] - Whether to return a clone so that getBytes/getText can be called again + * @returns {String | ReadableStream} Literal data as text. + */ + getText(clone = false) { + if (this.text === null || util.isStream(this.text)) { // Assume that this.text has been read + this.text = util.decodeUTF8(util.nativeEOL(this.getBytes(clone))); } + return this.text; + } - for (i = 0; i < keyBytes.length; i += 4) { - inKey[i >> 2] = getW(keyBytes, i); - } - for (i = 0; i < 256; i++) { - q[0][i] = qp(0, i); - q[1][i] = qp(1, i); - } - for (i = 0; i < 256; i++) { - f01 = q[1][i]; - f5b = ffm5b(f01); - fef = ffmEf(f01); - m[0][i] = f01 + (f5b << 8) + (fef << 16) + (fef << 24); - m[2][i] = f5b + (fef << 8) + (f01 << 16) + (fef << 24); - f01 = q[0][i]; - f5b = ffm5b(f01); - fef = ffmEf(f01); - m[1][i] = fef + (fef << 8) + (f5b << 16) + (f01 << 24); - m[3][i] = f5b + (f01 << 8) + (fef << 16) + (f5b << 24); - } + /** + * Set the packet data to value represented by the provided string of bytes. + * @param {Uint8Array | ReadableStream} bytes - The string of bytes + * @param {enums.literal} format - The format of the string of bytes + */ + setBytes(bytes, format) { + this.format = format; + this.data = bytes; + this.text = null; + } - kLen = inKey.length / 2; - for (i = 0; i < kLen; i++) { - a = inKey[i + i]; - meKey[i] = a; - b = inKey[i + i + 1]; - moKey[i] = b; - sKey[kLen - i - 1] = mdsRem(a, b); - } - for (i = 0; i < 40; i += 2) { - a = 0x1010101 * i; - b = a + 0x1010101; - a = hFun(a, meKey); - b = rotw(hFun(b, moKey), 8); - tfsKey[i] = a + b & MAXINT; - tfsKey[i + 1] = rotw(a + 2 * b, 9); + + /** + * Get the byte sequence representing the literal packet data + * @param {Boolean} [clone] - Whether to return a clone so that getBytes/getText can be called again + * @returns {Uint8Array | ReadableStream} A sequence of bytes. + */ + getBytes(clone = false) { + if (this.data === null) { + // encode UTF8 and normalize EOL to \r\n + this.data = util.canonicalizeEOL(util.encodeUTF8(this.text)); } - for (i = 0; i < 256; i++) { - a = b = c = d = i; - switch (kLen) { - case 4: - a = q[1][a] ^ getB(sKey[3], 0); - b = q[0][b] ^ getB(sKey[3], 1); - c = q[0][c] ^ getB(sKey[3], 2); - d = q[1][d] ^ getB(sKey[3], 3); - case 3: - a = q[1][a] ^ getB(sKey[2], 0); - b = q[1][b] ^ getB(sKey[2], 1); - c = q[0][c] ^ getB(sKey[2], 2); - d = q[0][d] ^ getB(sKey[2], 3); - case 2: - tfsM[0][i] = m[0][q[0][q[0][a] ^ getB(sKey[1], 0)] ^ getB(sKey[0], 0)]; - tfsM[1][i] = m[1][q[0][q[1][b] ^ getB(sKey[1], 1)] ^ getB(sKey[0], 1)]; - tfsM[2][i] = m[2][q[1][q[0][c] ^ getB(sKey[1], 2)] ^ getB(sKey[0], 2)]; - tfsM[3][i] = m[3][q[1][q[1][d] ^ getB(sKey[1], 3)] ^ getB(sKey[0], 3)]; - } + if (clone) { + return passiveClone(this.data); } + return this.data; } - function tfsG0(x) { - return tfsM[0][getB(x, 0)] ^ tfsM[1][getB(x, 1)] ^ tfsM[2][getB(x, 2)] ^ tfsM[3][getB(x, 3)]; - } - function tfsG1(x) { - return tfsM[0][getB(x, 3)] ^ tfsM[1][getB(x, 0)] ^ tfsM[2][getB(x, 1)] ^ tfsM[3][getB(x, 2)]; + /** + * Sets the filename of the literal packet data + * @param {String} filename - Any native javascript string + */ + setFilename(filename) { + this.filename = filename; } - function tfsFrnd(r, blk) { - let a = tfsG0(blk[0]); - let b = tfsG1(blk[1]); - blk[2] = rotw(blk[2] ^ a + b + tfsKey[4 * r + 8] & MAXINT, 31); - blk[3] = rotw(blk[3], 1) ^ a + 2 * b + tfsKey[4 * r + 9] & MAXINT; - a = tfsG0(blk[2]); - b = tfsG1(blk[3]); - blk[0] = rotw(blk[0] ^ a + b + tfsKey[4 * r + 10] & MAXINT, 31); - blk[1] = rotw(blk[1], 1) ^ a + 2 * b + tfsKey[4 * r + 11] & MAXINT; - } - function tfsIrnd(i, blk) { - let a = tfsG0(blk[0]); - let b = tfsG1(blk[1]); - blk[2] = rotw(blk[2], 1) ^ a + b + tfsKey[4 * i + 10] & MAXINT; - blk[3] = rotw(blk[3] ^ a + 2 * b + tfsKey[4 * i + 11] & MAXINT, 31); - a = tfsG0(blk[2]); - b = tfsG1(blk[3]); - blk[0] = rotw(blk[0], 1) ^ a + b + tfsKey[4 * i + 8] & MAXINT; - blk[1] = rotw(blk[1] ^ a + 2 * b + tfsKey[4 * i + 9] & MAXINT, 31); + /** + * Get the filename of the literal packet data + * @returns {String} Filename. + */ + getFilename() { + return this.filename; } - function tfsClose() { - tfsKey = []; - tfsM = [[], [], [], []]; + /** + * Parsing function for a literal data packet (tag 11). + * + * @param {Uint8Array | ReadableStream} input - Payload of a tag 11 packet + * @returns {Promise} Object representation. + * @async + */ + async read(bytes) { + await parse(bytes, async reader => { + // - A one-octet field that describes how the data is formatted. + const format = await reader.readByte(); // enums.literal + + const filename_len = await reader.readByte(); + this.filename = util.decodeUTF8(await reader.readBytes(filename_len)); + + this.date = util.readDate(await reader.readBytes(4)); + + let data = reader.remainder(); + if (isArrayStream(data)) data = await readToEnd(data); + this.setBytes(data, format); + }); } - function tfsEncrypt(data, offset) { - dataBytes = data; - dataOffset = offset; - const blk = [getW(dataBytes, dataOffset) ^ tfsKey[0], getW(dataBytes, dataOffset + 4) ^ tfsKey[1], getW(dataBytes, dataOffset + 8) ^ tfsKey[2], getW(dataBytes, dataOffset + 12) ^ tfsKey[3]]; - for (let j = 0; j < 8; j++) { - tfsFrnd(j, blk); - } - setW(dataBytes, dataOffset, blk[2] ^ tfsKey[4]); - setW(dataBytes, dataOffset + 4, blk[3] ^ tfsKey[5]); - setW(dataBytes, dataOffset + 8, blk[0] ^ tfsKey[6]); - setW(dataBytes, dataOffset + 12, blk[1] ^ tfsKey[7]); - dataOffset += 16; - return dataBytes; + /** + * Creates a Uint8Array representation of the packet, excluding the data + * + * @returns {Uint8Array} Uint8Array representation of the packet. + */ + writeHeader() { + const filename = util.encodeUTF8(this.filename); + const filename_length = new Uint8Array([filename.length]); + + const format = new Uint8Array([this.format]); + const date = util.writeDate(this.date); + + return util.concatUint8Array([format, filename_length, filename, date]); } - function tfsDecrypt(data, offset) { - dataBytes = data; - dataOffset = offset; - const blk = [getW(dataBytes, dataOffset) ^ tfsKey[4], getW(dataBytes, dataOffset + 4) ^ tfsKey[5], getW(dataBytes, dataOffset + 8) ^ tfsKey[6], getW(dataBytes, dataOffset + 12) ^ tfsKey[7]]; - for (let j = 7; j >= 0; j--) { - tfsIrnd(j, blk); - } - setW(dataBytes, dataOffset, blk[2] ^ tfsKey[0]); - setW(dataBytes, dataOffset + 4, blk[3] ^ tfsKey[1]); - setW(dataBytes, dataOffset + 8, blk[0] ^ tfsKey[2]); - setW(dataBytes, dataOffset + 12, blk[1] ^ tfsKey[3]); - dataOffset += 16; + /** + * Creates a Uint8Array representation of the packet + * + * @returns {Uint8Array | ReadableStream} Uint8Array representation of the packet. + */ + write() { + const header = this.writeHeader(); + const data = this.getBytes(); + + return util.concat([header, data]); } +} - // added by Recurity Labs +// GPG4Browsers - An OpenPGP implementation in javascript - function tfsFinal() { - return dataBytes; +function readSimpleLength(bytes) { + let len = 0; + let offset; + const type = bytes[0]; + + + if (type < 192) { + [len] = bytes; + offset = 1; + } else if (type < 255) { + len = ((bytes[0] - 192) << 8) + (bytes[1]) + 192; + offset = 2; + } else if (type === 255) { + len = util.readNumber(bytes.subarray(1, 1 + 4)); + offset = 5; } return { - name: "twofish", - blocksize: 128 / 8, - open: tfsInit, - close: tfsClose, - encrypt: tfsEncrypt, - decrypt: tfsDecrypt, - // added by Recurity Labs - finalize: tfsFinal + len: len, + offset: offset }; } -// added by Recurity Labs +/** + * Encodes a given integer of length to the openpgp length specifier to a + * string + * + * @param {Integer} length - The length to encode + * @returns {Uint8Array} String with openpgp length representation. + */ +function writeSimpleLength(length) { + if (length < 192) { + return new Uint8Array([length]); + } else if (length > 191 && length < 8384) { + /* + * let a = (total data packet length) - 192 let bc = two octet + * representation of a let d = b + 192 + */ + return new Uint8Array([((length - 192) >> 8) + 192, (length - 192) & 0xFF]); + } + return util.concatUint8Array([new Uint8Array([255]), util.writeNumber(length, 4)]); +} -function TF(key) { - this.tf = createTwofish(); - this.tf.open(Array.from(key), 0); +function writePartialLength(power) { + if (power < 0 || power > 30) { + throw new Error('Partial Length power must be between 1 and 30'); + } + return new Uint8Array([224 + power]); +} - this.encrypt = function (block) { - return this.tf.encrypt(Array.from(block), 0); - }; +function writeTag(tag_type) { + /* we're only generating v4 packet headers here */ + return new Uint8Array([0xC0 | tag_type]); } -TF.keySize = TF.prototype.keySize = 32; -TF.blockSize = TF.prototype.blockSize = 16; +/** + * Writes a packet header version 4 with the given tag_type and length to a + * string + * + * @param {Integer} tag_type - Tag type + * @param {Integer} length - Length of the payload + * @returns {String} String of the header. + */ +function writeHeader(tag_type, length) { + /* we're only generating v4 packet headers here */ + return util.concatUint8Array([writeTag(tag_type), writeSimpleLength(length)]); +} -exports.default = TF; +/** + * Whether the packet type supports partial lengths per RFC4880 + * @param {Integer} tag - Tag type + * @returns {Boolean} String of the header. + */ +function supportsStreaming(tag) { + return [ + enums.packet.literalData, + enums.packet.compressedData, + enums.packet.symmetricallyEncryptedData, + enums.packet.symEncryptedIntegrityProtectedData, + enums.packet.aeadEncryptedData + ].includes(tag); +} -},{}],88:[function(require,module,exports){ -'use strict'; +/** + * Generic static Packet Parser function + * + * @param {Uint8Array | ReadableStream} input - Input stream as string + * @param {Function} callback - Function to call with the parsed packet + * @returns {Boolean} Returns false if the stream was empty and parsing is done, and true otherwise. + */ +async function readPackets(input, callback) { + const reader = getReader(input); + let writer; + let callbackReturned; + try { + const peekedBytes = await reader.peekBytes(2); + // some sanity checks + if (!peekedBytes || peekedBytes.length < 2 || (peekedBytes[0] & 0x80) === 0) { + throw new Error('Error during parsing. This message / key probably does not conform to a valid OpenPGP format.'); + } + const headerByte = await reader.readByte(); + let tag = -1; + let format = -1; + let packetLength; -Object.defineProperty(exports, "__esModule", { - value: true -}); + format = 0; // 0 = old format; 1 = new format + if ((headerByte & 0x40) !== 0) { + format = 1; + } + + let packetLengthType; + if (format) { + // new format header + tag = headerByte & 0x3F; // bit 5-0 + } else { + // old format header + tag = (headerByte & 0x3F) >> 2; // bit 5-2 + packetLengthType = headerByte & 0x03; // bit 1-0 + } + + const packetSupportsStreaming = supportsStreaming(tag); + let packet = null; + if (packetSupportsStreaming) { + if (util.isStream(input) === 'array') { + const arrayStream = new ArrayStream(); + writer = getWriter(arrayStream); + packet = arrayStream; + } else { + const transform = new TransformStream(); + writer = getWriter(transform.writable); + packet = transform.readable; + } + callbackReturned = callback({ tag, packet }); + } else { + packet = []; + } + + let wasPartialLength; + do { + if (!format) { + // 4.2.1. Old Format Packet Lengths + switch (packetLengthType) { + case 0: + // The packet has a one-octet length. The header is 2 octets + // long. + packetLength = await reader.readByte(); + break; + case 1: + // The packet has a two-octet length. The header is 3 octets + // long. + packetLength = (await reader.readByte() << 8) | await reader.readByte(); + break; + case 2: + // The packet has a four-octet length. The header is 5 + // octets long. + packetLength = (await reader.readByte() << 24) | (await reader.readByte() << 16) | (await reader.readByte() << + 8) | await reader.readByte(); + break; + default: + // 3 - The packet is of indeterminate length. The header is 1 + // octet long, and the implementation must determine how long + // the packet is. If the packet is in a file, this means that + // the packet extends until the end of the file. In general, + // an implementation SHOULD NOT use indeterminate-length + // packets except where the end of the data will be clear + // from the context, and even then it is better to use a + // definite length, or a new format header. The new format + // headers described below have a mechanism for precisely + // encoding data of indeterminate length. + packetLength = Infinity; + break; + } + } else { // 4.2.2. New Format Packet Lengths + // 4.2.2.1. One-Octet Lengths + const lengthByte = await reader.readByte(); + wasPartialLength = false; + if (lengthByte < 192) { + packetLength = lengthByte; + // 4.2.2.2. Two-Octet Lengths + } else if (lengthByte >= 192 && lengthByte < 224) { + packetLength = ((lengthByte - 192) << 8) + (await reader.readByte()) + 192; + // 4.2.2.4. Partial Body Lengths + } else if (lengthByte > 223 && lengthByte < 255) { + packetLength = 1 << (lengthByte & 0x1F); + wasPartialLength = true; + if (!packetSupportsStreaming) { + throw new TypeError('This packet type does not support partial lengths.'); + } + // 4.2.2.3. Five-Octet Lengths + } else { + packetLength = (await reader.readByte() << 24) | (await reader.readByte() << 16) | (await reader.readByte() << + 8) | await reader.readByte(); + } + } + if (packetLength > 0) { + let bytesRead = 0; + while (true) { + if (writer) await writer.ready; + const { done, value } = await reader.read(); + if (done) { + if (packetLength === Infinity) break; + throw new Error('Unexpected end of packet'); + } + const chunk = packetLength === Infinity ? value : value.subarray(0, packetLength - bytesRead); + if (writer) await writer.write(chunk); + else packet.push(chunk); + bytesRead += value.length; + if (bytesRead >= packetLength) { + reader.unshift(value.subarray(packetLength - bytesRead + value.length)); + break; + } + } + } + } while (wasPartialLength); + + // If this was not a packet that "supports streaming", we peek to check + // whether it is the last packet in the message. We peek 2 bytes instead + // of 1 because the beginning of this function also peeks 2 bytes, and we + // want to cut a `subarray` of the correct length into `web-stream-tools`' + // `externalBuffer` as a tiny optimization here. + // + // If it *was* a streaming packet (i.e. the data packets), we peek at the + // entire remainder of the stream, in order to forward errors in the + // remainder of the stream to the packet data. (Note that this means we + // read/peek at all signature packets before closing the literal data + // packet, for example.) This forwards MDC errors to the literal data + // stream, for example, so that they don't get lost / forgotten on + // decryptedMessage.packets.stream, which we never look at. + // + // An example of what we do when stream-parsing a message containing + // [ one-pass signature packet, literal data packet, signature packet ]: + // 1. Read the one-pass signature packet + // 2. Peek 2 bytes of the literal data packet + // 3. Parse the one-pass signature packet + // + // 4. Read the literal data packet, simultaneously stream-parsing it + // 5. Peek until the end of the message + // 6. Finish parsing the literal data packet + // + // 7. Read the signature packet again (we already peeked at it in step 5) + // 8. Peek at the end of the stream again (`peekBytes` returns undefined) + // 9. Parse the signature packet + // + // Note that this means that if there's an error in the very end of the + // stream, such as an MDC error, we throw in step 5 instead of in step 8 + // (or never), which is the point of this exercise. + const nextPacket = await reader.peekBytes(packetSupportsStreaming ? Infinity : 2); + if (writer) { + await writer.ready; + await writer.close(); + } else { + packet = util.concatUint8Array(packet); + await callback({ tag, packet }); + } + return !nextPacket || !nextPacket.length; + } catch (e) { + if (writer) { + await writer.abort(e); + return true; + } else { + throw e; + } + } finally { + if (writer) { + await callbackReturned; + } + reader.releaseLock(); + } +} -var _cbc = require('asmcrypto.js/dist_es5/aes/cbc'); +class UnsupportedError extends Error { + constructor(...params) { + super(...params); -var _util = require('../util'); + if (Error.captureStackTrace) { + Error.captureStackTrace(this, UnsupportedError); + } -var _util2 = _interopRequireDefault(_util); + this.name = 'UnsupportedError'; + } +} -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +// GPG4Browsers - An OpenPGP implementation in javascript -/** - * @fileoverview This module implements AES-CMAC on top of - * native AES-CBC using either the WebCrypto API or Node.js' crypto API. - * @requires asmcrypto.js - * @requires util - * @module crypto/cmac - */ +// Symbol to store cryptographic validity of the signature, to avoid recomputing multiple times on verification. +const verified = Symbol('verified'); -const webCrypto = _util2.default.getWebCrypto(); -const nodeCrypto = _util2.default.getNodeCrypto(); -const Buffer = _util2.default.getNodeBuffer(); +// GPG puts the Issuer and Signature subpackets in the unhashed area. +// Tampering with those invalidates the signature, so we still trust them and parse them. +// All other unhashed subpackets are ignored. +const allowedUnhashedSubpackets = new Set([ + enums.signatureSubpacket.issuer, + enums.signatureSubpacket.issuerFingerprint, + enums.signatureSubpacket.embeddedSignature +]); /** - * This implementation of CMAC is based on the description of OMAC in - * http://web.cs.ucdavis.edu/~rogaway/papers/eax.pdf. As per that - * document: + * Implementation of the Signature Packet (Tag 2) * - * We have made a small modification to the OMAC algorithm as it was - * originally presented, changing one of its two constants. - * Specifically, the constant 4 at line 85 was the constant 1/2 (the - * multiplicative inverse of 2) in the original definition of OMAC [14]. - * The OMAC authors indicate that they will promulgate this modification - * [15], which slightly simplifies implementations. + * {@link https://tools.ietf.org/html/rfc4880#section-5.2|RFC4480 5.2}: + * A Signature packet describes a binding between some public key and + * some data. The most common signatures are a signature of a file or a + * block of text, and a signature that is a certification of a User ID. */ +class SignaturePacket { + static get tag() { + return enums.packet.signature; + } + + constructor() { + this.version = null; + /** @type {enums.signature} */ + this.signatureType = null; + /** @type {enums.hash} */ + this.hashAlgorithm = null; + /** @type {enums.publicKey} */ + this.publicKeyAlgorithm = null; + + this.signatureData = null; + this.unhashedSubpackets = []; + this.signedHashValue = null; + + this.created = null; + this.signatureExpirationTime = null; + this.signatureNeverExpires = true; + this.exportable = null; + this.trustLevel = null; + this.trustAmount = null; + this.regularExpression = null; + this.revocable = null; + this.keyExpirationTime = null; + this.keyNeverExpires = null; + this.preferredSymmetricAlgorithms = null; + this.revocationKeyClass = null; + this.revocationKeyAlgorithm = null; + this.revocationKeyFingerprint = null; + this.issuerKeyID = new KeyID(); + this.rawNotations = []; + this.notations = {}; + this.preferredHashAlgorithms = null; + this.preferredCompressionAlgorithms = null; + this.keyServerPreferences = null; + this.preferredKeyServer = null; + this.isPrimaryUserID = null; + this.policyURI = null; + this.keyFlags = null; + this.signersUserID = null; + this.reasonForRevocationFlag = null; + this.reasonForRevocationString = null; + this.features = null; + this.signatureTargetPublicKeyAlgorithm = null; + this.signatureTargetHashAlgorithm = null; + this.signatureTargetHash = null; + this.embeddedSignature = null; + this.issuerKeyVersion = null; + this.issuerFingerprint = null; + this.preferredAEADAlgorithms = null; + + this.revoked = null; + this[verified] = null; + } -const blockLength = 16; + /** + * parsing function for a signature packet (tag 2). + * @param {String} bytes - Payload of a tag 2 packet + * @returns {SignaturePacket} Object representation. + */ + read(bytes) { + let i = 0; + this.version = bytes[i++]; -/** - * xor `padding` into the end of `data`. This function implements "the - * operation xor→ [which] xors the shorter string into the end of longer - * one". Since data is always as least as long as padding, we can - * simplify the implementation. - * @param {Uint8Array} data - * @param {Uint8Array} padding - */ -function rightXorMut(data, padding) { - const offset = data.length - blockLength; - for (let i = 0; i < blockLength; i++) { - data[i + offset] ^= padding[i]; + if (this.version !== 4 && this.version !== 5) { + throw new UnsupportedError(`Version ${this.version} of the signature packet is unsupported.`); + } + + this.signatureType = bytes[i++]; + this.publicKeyAlgorithm = bytes[i++]; + this.hashAlgorithm = bytes[i++]; + + // hashed subpackets + i += this.readSubPackets(bytes.subarray(i, bytes.length), true); + if (!this.created) { + throw new Error('Missing signature creation time subpacket.'); + } + + // A V4 signature hashes the packet body + // starting from its first field, the version number, through the end + // of the hashed subpacket data. Thus, the fields hashed are the + // signature version, the signature type, the public-key algorithm, the + // hash algorithm, the hashed subpacket length, and the hashed + // subpacket body. + this.signatureData = bytes.subarray(0, i); + + // unhashed subpackets + i += this.readSubPackets(bytes.subarray(i, bytes.length), false); + + // Two-octet field holding left 16 bits of signed hash value. + this.signedHashValue = bytes.subarray(i, i + 2); + i += 2; + + this.params = mod.signature.parseSignatureParams(this.publicKeyAlgorithm, bytes.subarray(i, bytes.length)); } - return data; -} -function pad(data, padding, padding2) { - // if |M| in {n, 2n, 3n, ...} - if (data.length && data.length % blockLength === 0) { - // then return M xor→ B, - return rightXorMut(data, padding); + /** + * @returns {Uint8Array | ReadableStream} + */ + writeParams() { + if (this.params instanceof Promise) { + return fromAsync( + async () => mod.serializeParams(this.publicKeyAlgorithm, await this.params) + ); + } + return mod.serializeParams(this.publicKeyAlgorithm, this.params); } - // else return (M || 10^(n−1−(|M| mod n))) xor→ P - const padded = new Uint8Array(data.length + (blockLength - data.length % blockLength)); - padded.set(data); - padded[data.length] = 0b10000000; - return rightXorMut(padded, padding2); -} -const zeroBlock = new Uint8Array(blockLength); + write() { + const arr = []; + arr.push(this.signatureData); + arr.push(this.writeUnhashedSubPackets()); + arr.push(this.signedHashValue); + arr.push(this.writeParams()); + return util.concat(arr); + } -exports.default = async function CMAC(key) { - const cbc = await CBC(key); + /** + * Signs provided data. This needs to be done prior to serialization. + * @param {SecretKeyPacket} key - Private key used to sign the message. + * @param {Object} data - Contains packets to be signed. + * @param {Date} [date] - The signature creation time. + * @param {Boolean} [detached] - Whether to create a detached signature + * @throws {Error} if signing failed + * @async + */ + async sign(key, data, date = new Date(), detached = false) { + if (key.version === 5) { + this.version = 5; + } else { + this.version = 4; + } + const arr = [new Uint8Array([this.version, this.signatureType, this.publicKeyAlgorithm, this.hashAlgorithm])]; - // L ← E_K(0^n); B ← 2L; P ← 4L - const padding = _util2.default.double((await cbc(zeroBlock))); - const padding2 = _util2.default.double(padding); + this.created = util.normalizeDate(date); + this.issuerKeyVersion = key.version; + this.issuerFingerprint = key.getFingerprintBytes(); + this.issuerKeyID = key.getKeyID(); - return async function (data) { - // return CBC_K(pad(M; B, P)) - return (await cbc(pad(data, padding, padding2))).subarray(-blockLength); - }; -}; + // Add hashed subpackets + arr.push(this.writeHashedSubPackets()); -async function CBC(key) { - if (_util2.default.getWebCrypto() && key.length !== 24) { - // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support - key = await webCrypto.importKey('raw', key, { name: 'AES-CBC', length: key.length * 8 }, false, ['encrypt']); - return async function (pt) { - const ct = await webCrypto.encrypt({ name: 'AES-CBC', iv: zeroBlock, length: blockLength * 8 }, key, pt); - return new Uint8Array(ct).subarray(0, ct.byteLength - blockLength); - }; - } - if (_util2.default.getNodeCrypto()) { - // Node crypto library - key = new Buffer(key); - return async function (pt) { - pt = new Buffer(pt); - const en = new nodeCrypto.createCipheriv('aes-' + key.length * 8 + '-cbc', key, zeroBlock); - const ct = en.update(pt); - return new Uint8Array(ct); - }; + this.signatureData = util.concat(arr); + + const toHash = this.toHash(this.signatureType, data, detached); + const hash = await this.hash(this.signatureType, data, toHash, detached); + + this.signedHashValue = slice(clone(hash), 0, 2); + const signed = async () => mod.signature.sign( + this.publicKeyAlgorithm, this.hashAlgorithm, key.publicParams, key.privateParams, toHash, await readToEnd(hash) + ); + if (util.isStream(hash)) { + this.params = signed(); + } else { + this.params = await signed(); + + // Store the fact that this signature is valid, e.g. for when we call `await + // getLatestValidSignature(this.revocationSignatures, key, data)` later. + // Note that this only holds up if the key and data passed to verify are the + // same as the ones passed to sign. + this[verified] = true; + } } - // asm.js fallback - return async function (pt) { - return _cbc.AES_CBC.encrypt(pt, key, false, zeroBlock); - }; -} -},{"../util":152,"asmcrypto.js/dist_es5/aes/cbc":4}],89:[function(require,module,exports){ -'use strict'; + /** + * Creates Uint8Array of bytes of all subpacket data except Issuer and Embedded Signature subpackets + * @returns {Uint8Array} Subpacket data. + */ + writeHashedSubPackets() { + const sub = enums.signatureSubpacket; + const arr = []; + let bytes; + if (this.created === null) { + throw new Error('Missing signature creation time'); + } + arr.push(writeSubPacket(sub.signatureCreationTime, util.writeDate(this.created))); + if (this.signatureExpirationTime !== null) { + arr.push(writeSubPacket(sub.signatureExpirationTime, util.writeNumber(this.signatureExpirationTime, 4))); + } + if (this.exportable !== null) { + arr.push(writeSubPacket(sub.exportableCertification, new Uint8Array([this.exportable ? 1 : 0]))); + } + if (this.trustLevel !== null) { + bytes = new Uint8Array([this.trustLevel, this.trustAmount]); + arr.push(writeSubPacket(sub.trustSignature, bytes)); + } + if (this.regularExpression !== null) { + arr.push(writeSubPacket(sub.regularExpression, this.regularExpression)); + } + if (this.revocable !== null) { + arr.push(writeSubPacket(sub.revocable, new Uint8Array([this.revocable ? 1 : 0]))); + } + if (this.keyExpirationTime !== null) { + arr.push(writeSubPacket(sub.keyExpirationTime, util.writeNumber(this.keyExpirationTime, 4))); + } + if (this.preferredSymmetricAlgorithms !== null) { + bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredSymmetricAlgorithms)); + arr.push(writeSubPacket(sub.preferredSymmetricAlgorithms, bytes)); + } + if (this.revocationKeyClass !== null) { + bytes = new Uint8Array([this.revocationKeyClass, this.revocationKeyAlgorithm]); + bytes = util.concat([bytes, this.revocationKeyFingerprint]); + arr.push(writeSubPacket(sub.revocationKey, bytes)); + } + this.rawNotations.forEach(([{ name, value, humanReadable }]) => { + bytes = [new Uint8Array([humanReadable ? 0x80 : 0, 0, 0, 0])]; + // 2 octets of name length + bytes.push(util.writeNumber(name.length, 2)); + // 2 octets of value length + bytes.push(util.writeNumber(value.length, 2)); + bytes.push(util.stringToUint8Array(name)); + bytes.push(value); + bytes = util.concat(bytes); + arr.push(writeSubPacket(sub.notationData, bytes)); + }); + if (this.preferredHashAlgorithms !== null) { + bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredHashAlgorithms)); + arr.push(writeSubPacket(sub.preferredHashAlgorithms, bytes)); + } + if (this.preferredCompressionAlgorithms !== null) { + bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredCompressionAlgorithms)); + arr.push(writeSubPacket(sub.preferredCompressionAlgorithms, bytes)); + } + if (this.keyServerPreferences !== null) { + bytes = util.stringToUint8Array(util.uint8ArrayToString(this.keyServerPreferences)); + arr.push(writeSubPacket(sub.keyServerPreferences, bytes)); + } + if (this.preferredKeyServer !== null) { + arr.push(writeSubPacket(sub.preferredKeyServer, util.stringToUint8Array(this.preferredKeyServer))); + } + if (this.isPrimaryUserID !== null) { + arr.push(writeSubPacket(sub.primaryUserID, new Uint8Array([this.isPrimaryUserID ? 1 : 0]))); + } + if (this.policyURI !== null) { + arr.push(writeSubPacket(sub.policyURI, util.stringToUint8Array(this.policyURI))); + } + if (this.keyFlags !== null) { + bytes = util.stringToUint8Array(util.uint8ArrayToString(this.keyFlags)); + arr.push(writeSubPacket(sub.keyFlags, bytes)); + } + if (this.signersUserID !== null) { + arr.push(writeSubPacket(sub.signersUserID, util.stringToUint8Array(this.signersUserID))); + } + if (this.reasonForRevocationFlag !== null) { + bytes = util.stringToUint8Array(String.fromCharCode(this.reasonForRevocationFlag) + this.reasonForRevocationString); + arr.push(writeSubPacket(sub.reasonForRevocation, bytes)); + } + if (this.features !== null) { + bytes = util.stringToUint8Array(util.uint8ArrayToString(this.features)); + arr.push(writeSubPacket(sub.features, bytes)); + } + if (this.signatureTargetPublicKeyAlgorithm !== null) { + bytes = [new Uint8Array([this.signatureTargetPublicKeyAlgorithm, this.signatureTargetHashAlgorithm])]; + bytes.push(util.stringToUint8Array(this.signatureTargetHash)); + bytes = util.concat(bytes); + arr.push(writeSubPacket(sub.signatureTarget, bytes)); + } + if (this.preferredAEADAlgorithms !== null) { + bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredAEADAlgorithms)); + arr.push(writeSubPacket(sub.preferredAEADAlgorithms, bytes)); + } -Object.defineProperty(exports, "__esModule", { - value: true -}); + const result = util.concat(arr); + const length = util.writeNumber(result.length, 2); -var _bn = require('bn.js'); + return util.concat([length, result]); + } -var _bn2 = _interopRequireDefault(_bn); + /** + * Creates Uint8Array of bytes of Issuer and Embedded Signature subpackets + * @returns {Uint8Array} Subpacket data. + */ + writeUnhashedSubPackets() { + const sub = enums.signatureSubpacket; + const arr = []; + let bytes; + if (!this.issuerKeyID.isNull() && this.issuerKeyVersion !== 5) { + // If the version of [the] key is greater than 4, this subpacket + // MUST NOT be included in the signature. + arr.push(writeSubPacket(sub.issuer, this.issuerKeyID.write())); + } + if (this.embeddedSignature !== null) { + arr.push(writeSubPacket(sub.embeddedSignature, this.embeddedSignature.write())); + } + if (this.issuerFingerprint !== null) { + bytes = [new Uint8Array([this.issuerKeyVersion]), this.issuerFingerprint]; + bytes = util.concat(bytes); + arr.push(writeSubPacket(sub.issuerFingerprint, bytes)); + } + this.unhashedSubpackets.forEach(data => { + arr.push(writeSimpleLength(data.length)); + arr.push(data); + }); -var _public_key = require('./public_key'); + const result = util.concat(arr); + const length = util.writeNumber(result.length, 2); -var _public_key2 = _interopRequireDefault(_public_key); + return util.concat([length, result]); + } -var _cipher = require('./cipher'); + // V4 signature sub packets + readSubPacket(bytes, hashed = true) { + let mypos = 0; -var _cipher2 = _interopRequireDefault(_cipher); + // The leftmost bit denotes a "critical" packet + const critical = bytes[mypos] & 0x80; + const type = bytes[mypos] & 0x7F; -var _random = require('./random'); + if (!hashed && !allowedUnhashedSubpackets.has(type)) { + this.unhashedSubpackets.push(bytes.subarray(mypos, bytes.length)); + return; + } -var _random2 = _interopRequireDefault(_random); + mypos++; -var _ecdh_symkey = require('../type/ecdh_symkey'); + // subpacket type + switch (type) { + case enums.signatureSubpacket.signatureCreationTime: + // Signature Creation Time + this.created = util.readDate(bytes.subarray(mypos, bytes.length)); + break; + case enums.signatureSubpacket.signatureExpirationTime: { + // Signature Expiration Time in seconds + const seconds = util.readNumber(bytes.subarray(mypos, bytes.length)); -var _ecdh_symkey2 = _interopRequireDefault(_ecdh_symkey); + this.signatureNeverExpires = seconds === 0; + this.signatureExpirationTime = seconds; -var _kdf_params = require('../type/kdf_params'); + break; + } + case enums.signatureSubpacket.exportableCertification: + // Exportable Certification + this.exportable = bytes[mypos++] === 1; + break; + case enums.signatureSubpacket.trustSignature: + // Trust Signature + this.trustLevel = bytes[mypos++]; + this.trustAmount = bytes[mypos++]; + break; + case enums.signatureSubpacket.regularExpression: + // Regular Expression + this.regularExpression = bytes[mypos]; + break; + case enums.signatureSubpacket.revocable: + // Revocable + this.revocable = bytes[mypos++] === 1; + break; + case enums.signatureSubpacket.keyExpirationTime: { + // Key Expiration Time in seconds + const seconds = util.readNumber(bytes.subarray(mypos, bytes.length)); -var _kdf_params2 = _interopRequireDefault(_kdf_params); + this.keyExpirationTime = seconds; + this.keyNeverExpires = seconds === 0; -var _mpi = require('../type/mpi'); + break; + } + case enums.signatureSubpacket.preferredSymmetricAlgorithms: + // Preferred Symmetric Algorithms + this.preferredSymmetricAlgorithms = [...bytes.subarray(mypos, bytes.length)]; + break; + case enums.signatureSubpacket.revocationKey: + // Revocation Key + // (1 octet of class, 1 octet of public-key algorithm ID, 20 + // octets of + // fingerprint) + this.revocationKeyClass = bytes[mypos++]; + this.revocationKeyAlgorithm = bytes[mypos++]; + this.revocationKeyFingerprint = bytes.subarray(mypos, mypos + 20); + break; -var _mpi2 = _interopRequireDefault(_mpi); + case enums.signatureSubpacket.issuer: + // Issuer + this.issuerKeyID.read(bytes.subarray(mypos, bytes.length)); + break; -var _oid = require('../type/oid'); + case enums.signatureSubpacket.notationData: { + // Notation Data + const humanReadable = !!(bytes[mypos] & 0x80); -var _oid2 = _interopRequireDefault(_oid); + // We extract key/value tuple from the byte stream. + mypos += 4; + const m = util.readNumber(bytes.subarray(mypos, mypos + 2)); + mypos += 2; + const n = util.readNumber(bytes.subarray(mypos, mypos + 2)); + mypos += 2; -var _enums = require('../enums'); + const name = util.uint8ArrayToString(bytes.subarray(mypos, mypos + m)); + const value = bytes.subarray(mypos + m, mypos + m + n); -var _enums2 = _interopRequireDefault(_enums); + this.rawNotations.push({ name, humanReadable, value, critical }); -var _util = require('../util'); + if (humanReadable) { + this.notations[name] = util.uint8ArrayToString(value); + } + break; + } + case enums.signatureSubpacket.preferredHashAlgorithms: + // Preferred Hash Algorithms + this.preferredHashAlgorithms = [...bytes.subarray(mypos, bytes.length)]; + break; + case enums.signatureSubpacket.preferredCompressionAlgorithms: + // Preferred Compression Algorithms + this.preferredCompressionAlgorithms = [...bytes.subarray(mypos, bytes.length)]; + break; + case enums.signatureSubpacket.keyServerPreferences: + // Key Server Preferences + this.keyServerPreferences = [...bytes.subarray(mypos, bytes.length)]; + break; + case enums.signatureSubpacket.preferredKeyServer: + // Preferred Key Server + this.preferredKeyServer = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); + break; + case enums.signatureSubpacket.primaryUserID: + // Primary User ID + this.isPrimaryUserID = bytes[mypos++] !== 0; + break; + case enums.signatureSubpacket.policyURI: + // Policy URI + this.policyURI = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); + break; + case enums.signatureSubpacket.keyFlags: + // Key Flags + this.keyFlags = [...bytes.subarray(mypos, bytes.length)]; + break; + case enums.signatureSubpacket.signersUserID: + // Signer's User ID + this.signersUserID = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); + break; + case enums.signatureSubpacket.reasonForRevocation: + // Reason for Revocation + this.reasonForRevocationFlag = bytes[mypos++]; + this.reasonForRevocationString = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); + break; + case enums.signatureSubpacket.features: + // Features + this.features = [...bytes.subarray(mypos, bytes.length)]; + break; + case enums.signatureSubpacket.signatureTarget: { + // Signature Target + // (1 octet public-key algorithm, 1 octet hash algorithm, N octets hash) + this.signatureTargetPublicKeyAlgorithm = bytes[mypos++]; + this.signatureTargetHashAlgorithm = bytes[mypos++]; -var _util2 = _interopRequireDefault(_util); + const len = mod.getHashByteLength(this.signatureTargetHashAlgorithm); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + this.signatureTargetHash = util.uint8ArrayToString(bytes.subarray(mypos, mypos + len)); + break; + } + case enums.signatureSubpacket.embeddedSignature: + // Embedded Signature + this.embeddedSignature = new SignaturePacket(); + this.embeddedSignature.read(bytes.subarray(mypos, bytes.length)); + break; + case enums.signatureSubpacket.issuerFingerprint: + // Issuer Fingerprint + this.issuerKeyVersion = bytes[mypos++]; + this.issuerFingerprint = bytes.subarray(mypos, bytes.length); + if (this.issuerKeyVersion === 5) { + this.issuerKeyID.read(this.issuerFingerprint); + } else { + this.issuerKeyID.read(this.issuerFingerprint.subarray(-8)); + } + break; + case enums.signatureSubpacket.preferredAEADAlgorithms: + // Preferred AEAD Algorithms + this.preferredAEADAlgorithms = [...bytes.subarray(mypos, bytes.length)]; + break; + default: { + const err = new Error(`Unknown signature subpacket type ${type}`); + if (critical) { + throw err; + } else { + util.printDebug(err); + } + } + } + } -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + readSubPackets(bytes, trusted = true, config) { + // Two-octet scalar octet count for following subpacket data. + const subpacketLength = util.readNumber(bytes.subarray(0, 2)); -// The GPG4Browsers crypto interface + let i = 2; -/** - * @fileoverview Provides functions for asymmetric encryption and decryption as - * well as key generation and parameter handling for all public-key cryptosystems. - * @requires bn.js - * @requires crypto/public_key - * @requires crypto/cipher - * @requires crypto/random - * @requires type/ecdh_symkey - * @requires type/kdf_params - * @requires type/mpi - * @requires type/oid - * @requires enums - * @requires util - * @module crypto/crypto - */ + // subpacket data set (zero or more subpackets) + while (i < 2 + subpacketLength) { + const len = readSimpleLength(bytes.subarray(i, bytes.length)); + i += len.offset; -function constructParams(types, data) { - return types.map(function (type, i) { - if (data && data[i]) { - return new type(data[i]); + this.readSubPacket(bytes.subarray(i, i + len.len), trusted, config); + + i += len.len; } - return new type(); - }); -} -exports.default = { - /** - * Encrypts data using specified algorithm and public key parameters. - * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} for public key algorithms. - * @param {module:enums.publicKey} algo Public key algorithm - * @param {Array} pub_params Algorithm-specific public key parameters - * @param {module:type/mpi} data Data to be encrypted as MPI - * @param {String} fingerprint Recipient fingerprint - * @returns {Array} encrypted session key parameters - * @async - */ - publicKeyEncrypt: async function publicKeyEncrypt(algo, pub_params, data, fingerprint) { - const types = this.getEncSessionKeyParamTypes(algo); - switch (algo) { - case _enums2.default.publicKey.rsa_encrypt: - case _enums2.default.publicKey.rsa_encrypt_sign: - { - const m = data.toBN(); - const n = pub_params[0].toBN(); - const e = pub_params[1].toBN(); - const res = await _public_key2.default.rsa.encrypt(m, n, e); - return constructParams(types, [res]); - } - case _enums2.default.publicKey.elgamal: - { - const m = data.toBN(); - const p = pub_params[0].toBN(); - const g = pub_params[1].toBN(); - const y = pub_params[2].toBN(); - const res = await _public_key2.default.elgamal.encrypt(m, p, g, y); - return constructParams(types, [res.c1, res.c2]); - } - case _enums2.default.publicKey.ecdh: - { - const oid = pub_params[0]; - const Q = pub_params[1].toUint8Array(); - const kdf_params = pub_params[2]; - - var _ref = await _public_key2.default.elliptic.ecdh.encrypt(oid, kdf_params.cipher, kdf_params.hash, data, Q, fingerprint); - - const V = _ref.publicKey, - C = _ref.wrappedKey; - - return constructParams(types, [new _bn2.default(V), C]); + return i; + } + + // Produces data to produce signature on + toSign(type, data) { + const t = enums.signature; + + switch (type) { + case t.binary: + if (data.text !== null) { + return util.encodeUTF8(data.getText(true)); + } + return data.getBytes(true); + + case t.text: { + const bytes = data.getBytes(true); + // normalize EOL to \r\n + return util.canonicalizeEOL(bytes); + } + case t.standalone: + return new Uint8Array(0); + + case t.certGeneric: + case t.certPersona: + case t.certCasual: + case t.certPositive: + case t.certRevocation: { + let packet; + let tag; + + if (data.userID) { + tag = 0xB4; + packet = data.userID; + } else if (data.userAttribute) { + tag = 0xD1; + packet = data.userAttribute; + } else { + throw new Error('Either a userID or userAttribute packet needs to be ' + + 'supplied for certification.'); } + + const bytes = packet.write(); + + return util.concat([this.toSign(t.key, data), + new Uint8Array([tag]), + util.writeNumber(bytes.length, 4), + bytes]); + } + case t.subkeyBinding: + case t.subkeyRevocation: + case t.keyBinding: + return util.concat([this.toSign(t.key, data), this.toSign(t.key, { + key: data.bind + })]); + + case t.key: + if (data.key === undefined) { + throw new Error('Key packet is required for this signature.'); + } + return data.key.writeForHash(this.version); + + case t.keyRevocation: + return this.toSign(t.key, data); + case t.timestamp: + return new Uint8Array(0); + case t.thirdParty: + throw new Error('Not implemented'); default: - return []; + throw new Error('Unknown signature type.'); } - }, + } + + calculateTrailer(data, detached) { + let length = 0; + return transform(clone(this.signatureData), value => { + length += value.length; + }, () => { + const arr = []; + if (this.version === 5 && (this.signatureType === enums.signature.binary || this.signatureType === enums.signature.text)) { + if (detached) { + arr.push(new Uint8Array(6)); + } else { + arr.push(data.writeHeader()); + } + } + arr.push(new Uint8Array([this.version, 0xFF])); + if (this.version === 5) { + arr.push(new Uint8Array(4)); + } + arr.push(util.writeNumber(length, 4)); + // For v5, this should really be writeNumber(length, 8) rather than the + // hardcoded 4 zero bytes above + return util.concat(arr); + }); + } + + toHash(signatureType, data, detached = false) { + const bytes = this.toSign(signatureType, data); + + return util.concat([bytes, this.signatureData, this.calculateTrailer(data, detached)]); + } + + async hash(signatureType, data, toHash, detached = false) { + if (!toHash) toHash = this.toHash(signatureType, data, detached); + return mod.hash.digest(this.hashAlgorithm, toHash); + } /** - * Decrypts data using specified algorithm and private key parameters. - * See {@link https://tools.ietf.org/html/rfc4880#section-5.5.3|RFC 4880 5.5.3} - * @param {module:enums.publicKey} algo Public key algorithm - * @param {Array} key_params Algorithm-specific public, private key parameters - * @param {Array} - data_params encrypted session key parameters - * @param {String} fingerprint Recipient fingerprint - * @returns {BN} A BN containing the decrypted data + * verifies the signature packet. Note: not all signature types are implemented + * @param {PublicSubkeyPacket|PublicKeyPacket| + * SecretSubkeyPacket|SecretKeyPacket} key - the public key to verify the signature + * @param {module:enums.signature} signatureType - Expected signature type + * @param {String|Object} data - Data which on the signature applies + * @param {Date} [date] - Use the given date instead of the current time to check for signature validity and expiration + * @param {Boolean} [detached] - Whether to verify a detached signature + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if signature validation failed * @async */ - publicKeyDecrypt: async function publicKeyDecrypt(algo, key_params, data_params, fingerprint) { - switch (algo) { - case _enums2.default.publicKey.rsa_encrypt_sign: - case _enums2.default.publicKey.rsa_encrypt: - { - const c = data_params[0].toBN(); - const n = key_params[0].toBN(); // n = pq - const e = key_params[1].toBN(); - const d = key_params[2].toBN(); // de = 1 mod (p-1)(q-1) - const p = key_params[3].toBN(); - const q = key_params[4].toBN(); - const u = key_params[5].toBN(); // p^-1 mod q - return _public_key2.default.rsa.decrypt(c, n, e, d, p, q, u); - } - case _enums2.default.publicKey.elgamal: - { - const c1 = data_params[0].toBN(); - const c2 = data_params[1].toBN(); - const p = key_params[0].toBN(); - const x = key_params[3].toBN(); - return _public_key2.default.elgamal.decrypt(c1, c2, p, x); - } - case _enums2.default.publicKey.ecdh: - { - const oid = key_params[0]; - const kdf_params = key_params[2]; - const V = data_params[0].toUint8Array(); - const C = data_params[1].data; - const Q = key_params[1].toUint8Array(); - const d = key_params[3].toUint8Array(); - return _public_key2.default.elliptic.ecdh.decrypt(oid, kdf_params.cipher, kdf_params.hash, V, C, Q, d, fingerprint); - } - default: - throw new Error('Invalid public key encryption algorithm.'); - } - }, + async verify(key, signatureType, data, date = new Date(), detached = false, config = defaultConfig) { + if (!this.issuerKeyID.equals(key.getKeyID())) { + throw new Error('Signature was not issued by the given public key'); + } + if (this.publicKeyAlgorithm !== key.algorithm) { + throw new Error('Public key algorithm used to sign signature does not match issuer key algorithm.'); + } + + const isMessageSignature = signatureType === enums.signature.binary || signatureType === enums.signature.text; + // Cryptographic validity is cached after one successful verification. + // However, for message signatures, we always re-verify, since the passed `data` can change + const skipVerify = this[verified] && !isMessageSignature; + if (!skipVerify) { + let toHash; + let hash; + if (this.hashed) { + hash = await this.hashed; + } else { + toHash = this.toHash(signatureType, data, detached); + hash = await this.hash(signatureType, data, toHash); + } + hash = await readToEnd(hash); + if (this.signedHashValue[0] !== hash[0] || + this.signedHashValue[1] !== hash[1]) { + throw new Error('Signed digest did not match'); + } - /** Returns the types comprising the private key of an algorithm - * @param {String} algo The public key algorithm - * @returns {Array} The array of types - */ - getPrivKeyParamTypes: function getPrivKeyParamTypes(algo) { - switch (algo) { - // Algorithm-Specific Fields for RSA secret keys: - // - multiprecision integer (MPI) of RSA secret exponent d. - // - MPI of RSA secret prime value p. - // - MPI of RSA secret prime value q (p < q). - // - MPI of u, the multiplicative inverse of p, mod q. - case _enums2.default.publicKey.rsa_encrypt: - case _enums2.default.publicKey.rsa_encrypt_sign: - case _enums2.default.publicKey.rsa_sign: - return [_mpi2.default, _mpi2.default, _mpi2.default, _mpi2.default]; - // Algorithm-Specific Fields for Elgamal secret keys: - // - MPI of Elgamal secret exponent x. - case _enums2.default.publicKey.elgamal: - return [_mpi2.default]; - // Algorithm-Specific Fields for DSA secret keys: - // - MPI of DSA secret exponent x. - case _enums2.default.publicKey.dsa: - return [_mpi2.default]; - // Algorithm-Specific Fields for ECDSA or ECDH secret keys: - // - MPI of an integer representing the secret key. - case _enums2.default.publicKey.ecdh: - case _enums2.default.publicKey.ecdsa: - case _enums2.default.publicKey.eddsa: - return [_mpi2.default]; - default: - throw new Error('Invalid public key encryption algorithm.'); - } - }, + this.params = await this.params; - /** Returns the types comprising the public key of an algorithm - * @param {String} algo The public key algorithm - * @returns {Array} The array of types - */ - getPubKeyParamTypes: function getPubKeyParamTypes(algo) { - switch (algo) { - // Algorithm-Specific Fields for RSA public keys: - // - a multiprecision integer (MPI) of RSA public modulus n; - // - an MPI of RSA public encryption exponent e. - case _enums2.default.publicKey.rsa_encrypt: - case _enums2.default.publicKey.rsa_encrypt_sign: - case _enums2.default.publicKey.rsa_sign: - return [_mpi2.default, _mpi2.default]; - // Algorithm-Specific Fields for Elgamal public keys: - // - MPI of Elgamal prime p; - // - MPI of Elgamal group generator g; - // - MPI of Elgamal public key value y (= g**x mod p where x is secret). - case _enums2.default.publicKey.elgamal: - return [_mpi2.default, _mpi2.default, _mpi2.default]; - // Algorithm-Specific Fields for DSA public keys: - // - MPI of DSA prime p; - // - MPI of DSA group order q (q is a prime divisor of p-1); - // - MPI of DSA group generator g; - // - MPI of DSA public-key value y (= g**x mod p where x is secret). - case _enums2.default.publicKey.dsa: - return [_mpi2.default, _mpi2.default, _mpi2.default, _mpi2.default]; - // Algorithm-Specific Fields for ECDSA/EdDSA public keys: - // - OID of curve; - // - MPI of EC point representing public key. - case _enums2.default.publicKey.ecdsa: - case _enums2.default.publicKey.eddsa: - return [_oid2.default, _mpi2.default]; - // Algorithm-Specific Fields for ECDH public keys: - // - OID of curve; - // - MPI of EC point representing public key. - // - KDF: variable-length field containing KDF parameters. - case _enums2.default.publicKey.ecdh: - return [_oid2.default, _mpi2.default, _kdf_params2.default]; - default: - throw new Error('Invalid public key encryption algorithm.'); - } - }, + this[verified] = await mod.signature.verify( + this.publicKeyAlgorithm, this.hashAlgorithm, this.params, key.publicParams, + toHash, hash + ); - /** Returns the types comprising the encrypted session key of an algorithm - * @param {String} algo The public key algorithm - * @returns {Array} The array of types - */ - getEncSessionKeyParamTypes: function getEncSessionKeyParamTypes(algo) { - switch (algo) { - // Algorithm-Specific Fields for RSA encrypted session keys: - // - MPI of RSA encrypted value m**e mod n. - case _enums2.default.publicKey.rsa_encrypt: - case _enums2.default.publicKey.rsa_encrypt_sign: - return [_mpi2.default]; - - // Algorithm-Specific Fields for Elgamal encrypted session keys: - // - MPI of Elgamal value g**k mod p - // - MPI of Elgamal value m * y**k mod p - case _enums2.default.publicKey.elgamal: - return [_mpi2.default, _mpi2.default]; - // Algorithm-Specific Fields for ECDH encrypted session keys: - // - MPI containing the ephemeral key used to establish the shared secret - // - ECDH Symmetric Key - case _enums2.default.publicKey.ecdh: - return [_mpi2.default, _ecdh_symkey2.default]; - default: - throw new Error('Invalid public key encryption algorithm.'); + if (!this[verified]) { + throw new Error('Signature verification failed'); + } } - }, - /** Generate algorithm-specific key parameters - * @param {String} algo The public key algorithm - * @param {Integer} bits Bit length for RSA keys - * @param {module:type/oid} oid Object identifier for ECC keys - * @returns {Array} The array of parameters - * @async - */ - generateParams: function generateParams(algo, bits, oid) { - const types = [].concat(this.getPubKeyParamTypes(algo), this.getPrivKeyParamTypes(algo)); - switch (algo) { - case _enums2.default.publicKey.rsa_encrypt: - case _enums2.default.publicKey.rsa_encrypt_sign: - case _enums2.default.publicKey.rsa_sign: - { - return _public_key2.default.rsa.generate(bits, "10001").then(function (keyObject) { - return constructParams(types, [keyObject.n, keyObject.e, keyObject.d, keyObject.p, keyObject.q, keyObject.u]); - }); - } - case _enums2.default.publicKey.dsa: - case _enums2.default.publicKey.elgamal: - throw new Error('Unsupported algorithm for key generation.'); - case _enums2.default.publicKey.ecdsa: - case _enums2.default.publicKey.eddsa: - return _public_key2.default.elliptic.generate(oid).then(function (keyObject) { - return constructParams(types, [keyObject.oid, keyObject.Q, keyObject.d]); - }); - case _enums2.default.publicKey.ecdh: - return _public_key2.default.elliptic.generate(oid).then(function (keyObject) { - return constructParams(types, [keyObject.oid, keyObject.Q, [keyObject.hash, keyObject.cipher], keyObject.d]); - }); - default: - throw new Error('Invalid public key algorithm.'); + const normDate = util.normalizeDate(date); + if (normDate && this.created > normDate) { + throw new Error('Signature creation time is in the future'); } - }, + if (normDate && normDate >= this.getExpirationTime()) { + throw new Error('Signature is expired'); + } + if (config.rejectHashAlgorithms.has(this.hashAlgorithm)) { + throw new Error('Insecure hash algorithm: ' + enums.read(enums.hash, this.hashAlgorithm).toUpperCase()); + } + if (config.rejectMessageHashAlgorithms.has(this.hashAlgorithm) && + [enums.signature.binary, enums.signature.text].includes(this.signatureType)) { + throw new Error('Insecure message hash algorithm: ' + enums.read(enums.hash, this.hashAlgorithm).toUpperCase()); + } + this.rawNotations.forEach(({ name, critical }) => { + if (critical && (config.knownNotations.indexOf(name) < 0)) { + throw new Error(`Unknown critical notation: ${name}`); + } + }); + if (this.revocationKeyClass !== null) { + throw new Error('This key is intended to be revoked with an authorized key, which OpenPGP.js does not support.'); + } + } /** - * Generates a random byte prefix for the specified algorithm - * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. - * @param {module:enums.symmetric} algo Symmetric encryption algorithm - * @returns {Uint8Array} Random bytes with length equal to the block size of the cipher, plus the last two bytes repeated. - * @async + * Verifies signature expiration date + * @param {Date} [date] - Use the given date for verification instead of the current time + * @returns {Boolean} True if expired. */ - getPrefixRandom: async function getPrefixRandom(algo) { - const prefixrandom = await _random2.default.getRandomBytes(_cipher2.default[algo].blockSize); - const repeat = new Uint8Array([prefixrandom[prefixrandom.length - 2], prefixrandom[prefixrandom.length - 1]]); - return _util2.default.concat([prefixrandom, repeat]); - }, + isExpired(date = new Date()) { + const normDate = util.normalizeDate(date); + if (normDate !== null) { + return !(this.created <= normDate && normDate < this.getExpirationTime()); + } + return false; + } /** - * Generating a session key for the specified symmetric algorithm - * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. - * @param {module:enums.symmetric} algo Symmetric encryption algorithm - * @returns {Uint8Array} Random bytes as a string to be used as a key - * @async + * Returns the expiration time of the signature or Infinity if signature does not expire + * @returns {Date | Infinity} Expiration time. */ - generateSessionKey: function generateSessionKey(algo) { - return _random2.default.getRandomBytes(_cipher2.default[algo].keySize); - }, - - constructParams: constructParams -}; - -},{"../enums":113,"../type/ecdh_symkey":146,"../type/kdf_params":147,"../type/mpi":149,"../type/oid":150,"../util":152,"./cipher":86,"./public_key":106,"./random":109,"bn.js":16}],90:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); // OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2018 ProtonTech AG -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + getExpirationTime() { + return this.signatureNeverExpires ? Infinity : new Date(this.created.getTime() + this.signatureExpirationTime * 1000); + } +} /** - * @fileoverview This module implements AES-EAX en/decryption on top of - * native AES-CTR using either the WebCrypto API or Node.js' crypto API. - * @requires asmcrypto.js - * @requires crypto/cmac - * @requires util - * @module crypto/eax + * Creates a string representation of a sub signature packet + * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.1|RFC4880 5.2.3.1} + * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.2|RFC4880 5.2.3.2} + * @param {Integer} type - Subpacket signature type. + * @param {String} data - Data to be included + * @returns {String} A string-representation of a sub signature packet. + * @private */ +function writeSubPacket(type, data) { + const arr = []; + arr.push(writeSimpleLength(data.length + 1)); + arr.push(new Uint8Array([type])); + arr.push(data); + return util.concat(arr); +} + +// GPG4Browsers - An OpenPGP implementation in javascript -var _ctr = require('asmcrypto.js/dist_es5/aes/ctr'); +const VERSION = 3; -var _cmac = require('./cmac'); +/** + * Implementation of the One-Pass Signature Packets (Tag 4) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.4|RFC4880 5.4}: + * The One-Pass Signature packet precedes the signed data and contains + * enough information to allow the receiver to begin calculating any + * hashes needed to verify the signature. It allows the Signature + * packet to be placed at the end of the message, so that the signer + * can compute the entire signed message in one pass. + */ +class OnePassSignaturePacket { + static get tag() { + return enums.packet.onePassSignature; + } -var _cmac2 = _interopRequireDefault(_cmac); + constructor() { + /** A one-octet version number. The current version is 3. */ + this.version = null; + /** + * A one-octet signature type. + * Signature types are described in + * {@link https://tools.ietf.org/html/rfc4880#section-5.2.1|RFC4880 Section 5.2.1}. + * @type {enums.signature} -var _util = require('../util'); + */ + this.signatureType = null; + /** + * A one-octet number describing the hash algorithm used. + * @see {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC4880 9.4} + * @type {enums.hash} + */ + this.hashAlgorithm = null; + /** + * A one-octet number describing the public-key algorithm used. + * @see {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC4880 9.1} + * @type {enums.publicKey} + */ + this.publicKeyAlgorithm = null; + /** An eight-octet number holding the Key ID of the signing key. */ + this.issuerKeyID = null; + /** + * A one-octet number holding a flag showing whether the signature is nested. + * A zero value indicates that the next packet is another One-Pass Signature packet + * that describes another signature to be applied to the same message data. + */ + this.flags = null; + } -var _util2 = _interopRequireDefault(_util); + /** + * parsing function for a one-pass signature packet (tag 4). + * @param {Uint8Array} bytes - Payload of a tag 4 packet + * @returns {OnePassSignaturePacket} Object representation. + */ + read(bytes) { + let mypos = 0; + // A one-octet version number. The current version is 3. + this.version = bytes[mypos++]; + if (this.version !== VERSION) { + throw new UnsupportedError(`Version ${this.version} of the one-pass signature packet is unsupported.`); + } + + // A one-octet signature type. Signature types are described in + // Section 5.2.1. + this.signatureType = bytes[mypos++]; + + // A one-octet number describing the hash algorithm used. + this.hashAlgorithm = bytes[mypos++]; + + // A one-octet number describing the public-key algorithm used. + this.publicKeyAlgorithm = bytes[mypos++]; + + // An eight-octet number holding the Key ID of the signing key. + this.issuerKeyID = new KeyID(); + this.issuerKeyID.read(bytes.subarray(mypos, mypos + 8)); + mypos += 8; + + // A one-octet number holding a flag showing whether the signature + // is nested. A zero value indicates that the next packet is + // another One-Pass Signature packet that describes another + // signature to be applied to the same message data. + this.flags = bytes[mypos++]; + return this; + } -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + /** + * creates a string representation of a one-pass signature packet + * @returns {Uint8Array} A Uint8Array representation of a one-pass signature packet. + */ + write() { + const start = new Uint8Array([VERSION, this.signatureType, this.hashAlgorithm, this.publicKeyAlgorithm]); -const webCrypto = _util2.default.getWebCrypto(); -const nodeCrypto = _util2.default.getNodeCrypto(); -const Buffer = _util2.default.getNodeBuffer(); + const end = new Uint8Array([this.flags]); -const blockLength = 16; -const ivLength = blockLength; -const tagLength = blockLength; + return util.concatUint8Array([start, this.issuerKeyID.write(), end]); + } -const zero = new Uint8Array(blockLength); -const one = new Uint8Array(blockLength);one[blockLength - 1] = 1; -const two = new Uint8Array(blockLength);two[blockLength - 1] = 2; + calculateTrailer(...args) { + return fromAsync(async () => SignaturePacket.prototype.calculateTrailer.apply(await this.correspondingSig, args)); + } -async function OMAC(key) { - const cmac = await (0, _cmac2.default)(key); - return function (t, message) { - return cmac(_util2.default.concatUint8Array([t, message])); - }; + async verify() { + const correspondingSig = await this.correspondingSig; + if (!correspondingSig || correspondingSig.constructor.tag !== enums.packet.signature) { + throw new Error('Corresponding signature packet missing'); + } + if ( + correspondingSig.signatureType !== this.signatureType || + correspondingSig.hashAlgorithm !== this.hashAlgorithm || + correspondingSig.publicKeyAlgorithm !== this.publicKeyAlgorithm || + !correspondingSig.issuerKeyID.equals(this.issuerKeyID) + ) { + throw new Error('Corresponding signature packet does not match one-pass signature packet'); + } + correspondingSig.hashed = this.hashed; + return correspondingSig.verify.apply(correspondingSig, arguments); + } } -async function CTR(key) { - if (_util2.default.getWebCrypto() && key.length !== 24 && // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support - navigator.userAgent.indexOf('Edge') === -1) { - key = await webCrypto.importKey('raw', key, { name: 'AES-CTR', length: key.length * 8 }, false, ['encrypt']); - return async function (pt, iv) { - const ct = await webCrypto.encrypt({ name: 'AES-CTR', counter: iv, length: blockLength * 8 }, key, pt); - return new Uint8Array(ct); - }; - } - if (_util2.default.getNodeCrypto()) { - // Node crypto library - key = new Buffer(key); - return async function (pt, iv) { - pt = new Buffer(pt); - iv = new Buffer(iv); - const en = new nodeCrypto.createCipheriv('aes-' + key.length * 8 + '-ctr', key, iv); - const ct = Buffer.concat([en.update(pt), en.final()]); - return new Uint8Array(ct); - }; +OnePassSignaturePacket.prototype.hash = SignaturePacket.prototype.hash; +OnePassSignaturePacket.prototype.toHash = SignaturePacket.prototype.toHash; +OnePassSignaturePacket.prototype.toSign = SignaturePacket.prototype.toSign; + +/** + * Instantiate a new packet given its tag + * @function newPacketFromTag + * @param {module:enums.packet} tag - Property value from {@link module:enums.packet} + * @param {Object} allowedPackets - mapping where keys are allowed packet tags, pointing to their Packet class + * @returns {Object} New packet object with type based on tag + * @throws {Error|UnsupportedError} for disallowed or unknown packets + */ +function newPacketFromTag(tag, allowedPackets) { + if (!allowedPackets[tag]) { + // distinguish between disallowed packets and unknown ones + let packetType; + try { + packetType = enums.read(enums.packet, tag); + } catch (e) { + throw new UnsupportedError(`Unknown packet type with tag: ${tag}`); + } + throw new Error(`Packet not allowed in this context: ${packetType}`); } - // asm.js fallback - return async function (pt, iv) { - return _ctr.AES_CTR.encrypt(pt, key, iv); - }; + return new allowedPackets[tag](); } /** - * Class to en/decrypt using EAX mode. - * @param {String} cipher The symmetric cipher algorithm to use e.g. 'aes128' - * @param {Uint8Array} key The encryption key + * This class represents a list of openpgp packets. + * Take care when iterating over it - the packets themselves + * are stored as numerical indices. + * @extends Array */ -async function EAX(cipher, key) { - if (cipher.substr(0, 3) !== 'aes') { - throw new Error('EAX mode supports only AES cipher'); +class PacketList extends Array { + /** + * Parses the given binary data and returns a list of packets. + * Equivalent to calling `read` on an empty PacketList instance. + * @param {Uint8Array | ReadableStream} bytes - binary data to parse + * @param {Object} allowedPackets - mapping where keys are allowed packet tags, pointing to their Packet class + * @param {Object} [config] - full configuration, defaults to openpgp.config + * @returns {PacketList} parsed list of packets + * @throws on parsing errors + * @async + */ + static async fromBinary(bytes, allowedPackets, config = defaultConfig) { + const packets = new PacketList(); + await packets.read(bytes, allowedPackets, config); + return packets; } - var _ref = await Promise.all([OMAC(key), CTR(key)]), - _ref2 = _slicedToArray(_ref, 2); - - const omac = _ref2[0], - ctr = _ref2[1]; - - - return { - /** - * Encrypt plaintext input. - * @param {Uint8Array} plaintext The cleartext input to be encrypted - * @param {Uint8Array} nonce The nonce (16 bytes) - * @param {Uint8Array} adata Associated data to sign - * @returns {Promise} The ciphertext output - */ - encrypt: async function encrypt(plaintext, nonce, adata) { - var _ref3 = await Promise.all([omac(zero, nonce), omac(one, adata)]), - _ref4 = _slicedToArray(_ref3, 2); - - const omacNonce = _ref4[0], - omacAdata = _ref4[1]; - - const ciphered = await ctr(plaintext, omacNonce); - const omacCiphered = await omac(two, ciphered); - const tag = omacCiphered; // Assumes that omac(*).length === tagLength. - for (let i = 0; i < tagLength; i++) { - tag[i] ^= omacAdata[i] ^ omacNonce[i]; + /** + * Reads a stream of binary data and interprets it as a list of packets. + * @param {Uint8Array | ReadableStream} bytes - binary data to parse + * @param {Object} allowedPackets - mapping where keys are allowed packet tags, pointing to their Packet class + * @param {Object} [config] - full configuration, defaults to openpgp.config + * @throws on parsing errors + * @async + */ + async read(bytes, allowedPackets, config = defaultConfig) { + this.stream = transformPair(bytes, async (readable, writable) => { + const writer = getWriter(writable); + try { + while (true) { + await writer.ready; + const done = await readPackets(readable, async parsed => { + try { + if (parsed.tag === enums.packet.marker || parsed.tag === enums.packet.trust) { + // According to the spec, these packet types should be ignored and not cause parsing errors, even if not esplicitly allowed: + // - Marker packets MUST be ignored when received: https://github.com/openpgpjs/openpgpjs/issues/1145 + // - Trust packets SHOULD be ignored outside of keyrings (unsupported): https://datatracker.ietf.org/doc/html/rfc4880#section-5.10 + return; + } + const packet = newPacketFromTag(parsed.tag, allowedPackets); + packet.packets = new PacketList(); + packet.fromStream = util.isStream(parsed.packet); + await packet.read(parsed.packet, config); + await writer.write(packet); + } catch (e) { + const throwUnsupportedError = !config.ignoreUnsupportedPackets && e instanceof UnsupportedError; + const throwMalformedError = !config.ignoreMalformedPackets && !(e instanceof UnsupportedError); + if (throwUnsupportedError || throwMalformedError || supportsStreaming(parsed.tag)) { + // The packets that support streaming are the ones that contain message data. + // Those are also the ones we want to be more strict about and throw on parse errors + // (since we likely cannot process the message without these packets anyway). + await writer.abort(e); + } + util.printDebugError(e); + } + }); + if (done) { + await writer.ready; + await writer.close(); + return; + } + } + } catch (e) { + await writer.abort(e); } - return _util2.default.concatUint8Array([ciphered, tag]); - }, - - /** - * Decrypt ciphertext input. - * @param {Uint8Array} ciphertext The ciphertext input to be decrypted - * @param {Uint8Array} nonce The nonce (16 bytes) - * @param {Uint8Array} adata Associated data to verify - * @returns {Promise} The plaintext output - */ - decrypt: async function decrypt(ciphertext, nonce, adata) { - if (ciphertext.length < tagLength) throw new Error('Invalid EAX ciphertext'); - const ciphered = ciphertext.subarray(0, -tagLength); - const ctTag = ciphertext.subarray(-tagLength); + }); - var _ref5 = await Promise.all([omac(zero, nonce), omac(one, adata), omac(two, ciphered)]), - _ref6 = _slicedToArray(_ref5, 3); + // Wait until first few packets have been read + const reader = getReader(this.stream); + while (true) { + const { done, value } = await reader.read(); + if (!done) { + this.push(value); + } else { + this.stream = null; + } + if (done || supportsStreaming(value.constructor.tag)) { + break; + } + } + reader.releaseLock(); + } - const omacNonce = _ref6[0], - omacAdata = _ref6[1], - omacCiphered = _ref6[2]; + /** + * Creates a binary representation of openpgp objects contained within the + * class instance. + * @returns {Uint8Array} A Uint8Array containing valid openpgp packets. + */ + write() { + const arr = []; - const tag = omacCiphered; // Assumes that omac(*).length === tagLength. - for (let i = 0; i < tagLength; i++) { - tag[i] ^= omacAdata[i] ^ omacNonce[i]; + for (let i = 0; i < this.length; i++) { + const packetbytes = this[i].write(); + if (util.isStream(packetbytes) && supportsStreaming(this[i].constructor.tag)) { + let buffer = []; + let bufferLength = 0; + const minLength = 512; + arr.push(writeTag(this[i].constructor.tag)); + arr.push(transform(packetbytes, value => { + buffer.push(value); + bufferLength += value.length; + if (bufferLength >= minLength) { + const powerOf2 = Math.min(Math.log(bufferLength) / Math.LN2 | 0, 30); + const chunkSize = 2 ** powerOf2; + const bufferConcat = util.concat([writePartialLength(powerOf2)].concat(buffer)); + buffer = [bufferConcat.subarray(1 + chunkSize)]; + bufferLength = buffer[0].length; + return bufferConcat.subarray(0, 1 + chunkSize); + } + }, () => util.concat([writeSimpleLength(bufferLength)].concat(buffer)))); + } else { + if (util.isStream(packetbytes)) { + let length = 0; + arr.push(transform(clone(packetbytes), value => { + length += value.length; + }, () => writeHeader(this[i].constructor.tag, length))); + } else { + arr.push(writeHeader(this[i].constructor.tag, packetbytes.length)); + } + arr.push(packetbytes); } - if (!_util2.default.equalsUint8Array(ctTag, tag)) throw new Error('Authentication tag mismatch'); - const plaintext = await ctr(ciphered, omacNonce); - return plaintext; } - }; -} -/** - * Get EAX nonce as defined by {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.1|RFC4880bis-04, section 5.16.1}. - * @param {Uint8Array} iv The initialization vector (16 bytes) - * @param {Uint8Array} chunkIndex The chunk index (8 bytes) - */ -EAX.getNonce = function (iv, chunkIndex) { - const nonce = iv.slice(); - for (let i = 0; i < chunkIndex.length; i++) { - nonce[8 + i] ^= chunkIndex[i]; + return util.concat(arr); } - return nonce; -}; - -EAX.blockLength = blockLength; -EAX.ivLength = ivLength; -EAX.tagLength = tagLength; - -exports.default = EAX; -},{"../util":152,"./cmac":88,"asmcrypto.js/dist_es5/aes/ctr":6}],91:[function(require,module,exports){ -'use strict'; + /** + * Creates a new PacketList with all packets matching the given tag(s) + * @param {...module:enums.packet} tags - packet tags to look for + * @returns {PacketList} + */ + filterByTag(...tags) { + const filtered = new PacketList(); -Object.defineProperty(exports, "__esModule", { - value: true -}); + const handle = tag => packetType => tag === packetType; -var _gcm = require('asmcrypto.js/dist_es5/aes/gcm'); + for (let i = 0; i < this.length; i++) { + if (tags.some(handle(this[i].constructor.tag))) { + filtered.push(this[i]); + } + } -var _util = require('../util'); + return filtered; + } -var _util2 = _interopRequireDefault(_util); + /** + * Traverses packet list and returns first packet with matching tag + * @param {module:enums.packet} tag - The packet tag + * @returns {Packet|undefined} + */ + findPacket(tag) { + return this.find(packet => packet.constructor.tag === tag); + } -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + /** + * Find indices of packets with the given tag(s) + * @param {...module:enums.packet} tags - packet tags to look for + * @returns {Integer[]} packet indices + */ + indexOfTag(...tags) { + const tagIndex = []; + const that = this; -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2016 Tankred Hase -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + const handle = tag => packetType => tag === packetType; -/** - * @fileoverview This module wraps native AES-GCM en/decryption for both - * the WebCrypto api as well as node.js' crypto api. - * @requires asmcrypto.js - * @requires util - * @module crypto/gcm - */ + for (let i = 0; i < this.length; i++) { + if (tags.some(handle(that[i].constructor.tag))) { + tagIndex.push(i); + } + } + return tagIndex; + } +} -const webCrypto = _util2.default.getWebCrypto(); // no GCM support in IE11, Safari 9 -const nodeCrypto = _util2.default.getNodeCrypto(); -const Buffer = _util2.default.getNodeBuffer(); +// GPG4Browsers - An OpenPGP implementation in javascript -const blockLength = 16; -const ivLength = 12; // size of the IV in bytes -const tagLength = 16; // size of the tag in bytes -const ALGO = 'AES-GCM'; +// A Compressed Data packet can contain the following packet types +const allowedPackets = /*#__PURE__*/ util.constructAllowedPackets([ + LiteralDataPacket, + OnePassSignaturePacket, + SignaturePacket +]); /** - * Class to en/decrypt using GCM mode. - * @param {String} cipher The symmetric cipher algorithm to use e.g. 'aes128' - * @param {Uint8Array} key The encryption key + * Implementation of the Compressed Data Packet (Tag 8) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.6|RFC4880 5.6}: + * The Compressed Data packet contains compressed data. Typically, + * this packet is found as the contents of an encrypted packet, or following + * a Signature or One-Pass Signature packet, and contains a literal data packet. */ -async function GCM(cipher, key) { - if (cipher.substr(0, 3) !== 'aes') { - throw new Error('GCM mode supports only AES cipher'); +class CompressedDataPacket { + static get tag() { + return enums.packet.compressedData; } - if (_util2.default.getWebCrypto() && key.length !== 24) { - // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support - const _key = await webCrypto.importKey('raw', key, { name: ALGO }, false, ['encrypt', 'decrypt']); + /** + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + constructor(config = defaultConfig) { + /** + * List of packets + * @type {PacketList} + */ + this.packets = null; + /** + * Compression algorithm + * @type {enums.compression} + */ + this.algorithm = config.preferredCompressionAlgorithm; - return { - encrypt: async function encrypt(pt, iv, adata = new Uint8Array()) { - if (!pt.length || - // iOS does not support GCM-en/decrypting empty messages - // Also, synchronous en/decryption might be faster in this case. - !adata.length && navigator.userAgent.indexOf('Edge') !== -1 - // Edge does not support GCM-en/decrypting without ADATA - ) { - return _gcm.AES_GCM.encrypt(pt, key, iv, adata); - } - const ct = await webCrypto.encrypt({ name: ALGO, iv, additionalData: adata, tagLength: tagLength * 8 }, _key, pt); - return new Uint8Array(ct); - }, + /** + * Compressed packet data + * @type {Uint8Array | ReadableStream} + */ + this.compressed = null; - decrypt: async function decrypt(ct, iv, adata = new Uint8Array()) { - if (ct.length === tagLength || - // iOS does not support GCM-en/decrypting empty messages - // Also, synchronous en/decryption might be faster in this case. - !adata.length && navigator.userAgent.indexOf('Edge') !== -1 - // Edge does not support GCM-en/decrypting without ADATA - ) { - return _gcm.AES_GCM.decrypt(ct, key, iv, adata); - } - const pt = await webCrypto.decrypt({ name: ALGO, iv, additionalData: adata, tagLength: tagLength * 8 }, _key, ct); - return new Uint8Array(pt); - } - }; + /** + * zip/zlib compression level, between 1 and 9 + */ + this.deflateLevel = config.deflateLevel; } - if (_util2.default.getNodeCrypto()) { - // Node crypto library - key = new Buffer(key); + /** + * Parsing function for the packet. + * @param {Uint8Array | ReadableStream} bytes - Payload of a tag 8 packet + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + async read(bytes, config = defaultConfig) { + await parse(bytes, async reader => { + + // One octet that gives the algorithm used to compress the packet. + this.algorithm = await reader.readByte(); - return { - encrypt: async function encrypt(pt, iv, adata = new Uint8Array()) { - pt = new Buffer(pt); - iv = new Buffer(iv); - adata = new Buffer(adata); - const en = new nodeCrypto.createCipheriv('aes-' + key.length * 8 + '-gcm', key, iv); - en.setAAD(adata); - const ct = Buffer.concat([en.update(pt), en.final(), en.getAuthTag()]); // append auth tag to ciphertext - return new Uint8Array(ct); - }, + // Compressed data, which makes up the remainder of the packet. + this.compressed = reader.remainder(); - decrypt: async function decrypt(ct, iv, adata = new Uint8Array()) { - ct = new Buffer(ct); - iv = new Buffer(iv); - adata = new Buffer(adata); - const de = new nodeCrypto.createDecipheriv('aes-' + key.length * 8 + '-gcm', key, iv); - de.setAAD(adata); - de.setAuthTag(ct.slice(ct.length - tagLength, ct.length)); // read auth tag at end of ciphertext - const pt = Buffer.concat([de.update(ct.slice(0, ct.length - tagLength)), de.final()]); - return new Uint8Array(pt); - } - }; + await this.decompress(config); + }); } - return { - encrypt: async function encrypt(pt, iv, adata) { - return _gcm.AES_GCM.encrypt(pt, key, iv, adata); - }, - decrypt: async function decrypt(ct, iv, adata) { - return _gcm.AES_GCM.decrypt(ct, key, iv, adata); + /** + * Return the compressed packet. + * @returns {Uint8Array | ReadableStream} Binary compressed packet. + */ + write() { + if (this.compressed === null) { + this.compress(); } - }; -} -/** - * Get GCM nonce. Note: this operation is not defined by the standard. - * A future version of the standard may define GCM mode differently, - * hopefully under a different ID (we use Private/Experimental algorithm - * ID 100) so that we can maintain backwards compatibility. - * @param {Uint8Array} iv The initialization vector (12 bytes) - * @param {Uint8Array} chunkIndex The chunk index (8 bytes) - */ -GCM.getNonce = function (iv, chunkIndex) { - const nonce = iv.slice(); - for (let i = 0; i < chunkIndex.length; i++) { - nonce[4 + i] ^= chunkIndex[i]; + return util.concat([new Uint8Array([this.algorithm]), this.compressed]); } - return nonce; -}; - -GCM.blockLength = blockLength; -GCM.ivLength = ivLength; -GCM.tagLength = tagLength; - -exports.default = GCM; - -},{"../util":152,"asmcrypto.js/dist_es5/aes/gcm":8}],92:[function(require,module,exports){ -'use strict'; -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _sha = require('asmcrypto.js/dist_es5/hash/sha1/sha1'); -var _sha2 = require('asmcrypto.js/dist_es5/hash/sha256/sha256'); - -var _ = require('hash.js/lib/hash/sha/224'); + /** + * Decompression method for decompressing the compressed data + * read by read_packet + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + async decompress(config = defaultConfig) { + const compressionName = enums.read(enums.compression, this.algorithm); + const decompressionFn = decompress_fns[compressionName]; + if (!decompressionFn) { + throw new Error(`${compressionName} decompression not supported`); + } -var _2 = _interopRequireDefault(_); + this.packets = await PacketList.fromBinary(decompressionFn(this.compressed), allowedPackets, config); + } -var _3 = require('hash.js/lib/hash/sha/384'); + /** + * Compress the packet data (member decompressedData) + */ + compress() { + const compressionName = enums.read(enums.compression, this.algorithm); + const compressionFn = compress_fns[compressionName]; + if (!compressionFn) { + throw new Error(`${compressionName} compression not supported`); + } -var _4 = _interopRequireDefault(_3); + this.compressed = compressionFn(this.packets.write(), this.deflateLevel); + } +} -var _5 = require('hash.js/lib/hash/sha/512'); +////////////////////////// +// // +// Helper functions // +// // +////////////////////////// -var _6 = _interopRequireDefault(_5); -var _ripemd = require('hash.js/lib/hash/ripemd'); +const nodeZlib = util.getNodeZlib(); -var _webStreamTools = require('web-stream-tools'); +function uncompressed(data) { + return data; +} -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); +function node_zlib(func, create, options = {}) { + return function (data) { + if (!util.isStream(data) || isArrayStream(data)) { + return fromAsync(() => readToEnd(data).then(data => { + return new Promise((resolve, reject) => { + func(data, options, (err, result) => { + if (err) return reject(err); + resolve(result); + }); + }); + })); + } + return nodeToWeb(webToNode(data).pipe(create(options))); + }; +} -var _md = require('./md5'); +function pako_zlib(constructor, options = {}) { + return function(data) { + const obj = new constructor(options); + return transform(data, value => { + if (value.length) { + obj.push(value, Z_SYNC_FLUSH); + return obj.result; + } + }, () => { + if (constructor === Deflate) { + obj.push([], Z_FINISH); + return obj.result; + } + }); + }; +} -var _md2 = _interopRequireDefault(_md); +function bzip2(func) { + return function(data) { + return fromAsync(async () => func(await readToEnd(data))); + }; +} -var _config = require('../../config'); +const compress_fns = nodeZlib ? { + zip: /*#__PURE__*/ (compressed, level) => node_zlib(nodeZlib.deflateRaw, nodeZlib.createDeflateRaw, { level })(compressed), + zlib: /*#__PURE__*/ (compressed, level) => node_zlib(nodeZlib.deflate, nodeZlib.createDeflate, { level })(compressed) +} : { + zip: /*#__PURE__*/ (compressed, level) => pako_zlib(Deflate, { raw: true, level })(compressed), + zlib: /*#__PURE__*/ (compressed, level) => pako_zlib(Deflate, { level })(compressed) +}; -var _config2 = _interopRequireDefault(_config); +const decompress_fns = nodeZlib ? { + uncompressed: uncompressed, + zip: /*#__PURE__*/ node_zlib(nodeZlib.inflateRaw, nodeZlib.createInflateRaw), + zlib: /*#__PURE__*/ node_zlib(nodeZlib.inflate, nodeZlib.createInflate), + bzip2: /*#__PURE__*/ bzip2(lib_4) +} : { + uncompressed: uncompressed, + zip: /*#__PURE__*/ pako_zlib(Inflate, { raw: true }), + zlib: /*#__PURE__*/ pako_zlib(Inflate), + bzip2: /*#__PURE__*/ bzip2(lib_4) +}; -var _util = require('../../util'); +// GPG4Browsers - An OpenPGP implementation in javascript -var _util2 = _interopRequireDefault(_util); +// A SEIP packet can contain the following packet types +const allowedPackets$1 = /*#__PURE__*/ util.constructAllowedPackets([ + LiteralDataPacket, + CompressedDataPacket, + OnePassSignaturePacket, + SignaturePacket +]); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +const VERSION$1 = 1; // A one-octet version number of the data packet. /** - * @fileoverview Provides an interface to hashing functions available in Node.js or external libraries. - * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} - * @see {@link https://github.com/indutny/hash.js|hash.js} - * @requires asmcrypto.js - * @requires hash.js - * @requires web-stream-tools - * @requires crypto/hash/md5 - * @requires config - * @requires util - * @module crypto/hash + * Implementation of the Sym. Encrypted Integrity Protected Data Packet (Tag 18) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.13|RFC4880 5.13}: + * The Symmetrically Encrypted Integrity Protected Data packet is + * a variant of the Symmetrically Encrypted Data packet. It is a new feature + * created for OpenPGP that addresses the problem of detecting a modification to + * encrypted data. It is used in combination with a Modification Detection Code + * packet. */ +class SymEncryptedIntegrityProtectedDataPacket { + static get tag() { + return enums.packet.symEncryptedIntegrityProtectedData; + } -const webCrypto = _util2.default.getWebCrypto(); -const nodeCrypto = _util2.default.getNodeCrypto(); -const Buffer = _util2.default.getNodeBuffer(); + constructor() { + this.version = VERSION$1; + this.encrypted = null; + this.packets = null; + } -function node_hash(type) { - return async function (data) { - const shasum = nodeCrypto.createHash(type); - return _webStreamTools2.default.transform(data, value => { - shasum.update(new Buffer(value)); - }, () => new Uint8Array(shasum.digest())); - }; -} + async read(bytes) { + await parse(bytes, async reader => { + const version = await reader.readByte(); + // - A one-octet version number. The only currently defined value is 1. + if (version !== VERSION$1) { + throw new UnsupportedError(`Version ${version} of the SEIP packet is unsupported.`); + } -function hashjs_hash(hash, webCryptoHash) { - return async function (data) { - if (!_util2.default.isStream(data) && webCrypto && webCryptoHash && data.length >= _config2.default.min_bytes_for_web_crypto) { - return new Uint8Array((await webCrypto.digest(webCryptoHash, data))); - } - const hashInstance = hash(); - return _webStreamTools2.default.transform(data, value => { - hashInstance.update(value); - }, () => new Uint8Array(hashInstance.digest())); - }; -} + // - Encrypted data, the output of the selected symmetric-key cipher + // operating in Cipher Feedback mode with shift amount equal to the + // block size of the cipher (CFB-n where n is the block size). + this.encrypted = reader.remainder(); + }); + } -function asmcrypto_hash(hash, webCryptoHash) { - return async function (data) { - if (_util2.default.isStream(data)) { - const hashInstance = new hash(); - return _webStreamTools2.default.transform(data, value => { - hashInstance.process(value); - }, () => hashInstance.finish().result); - } else if (webCrypto && webCryptoHash && data.length >= _config2.default.min_bytes_for_web_crypto) { - return new Uint8Array((await webCrypto.digest(webCryptoHash, data))); - } else { - return hash.bytes(data); - } - }; -} + write() { + return util.concat([new Uint8Array([VERSION$1]), this.encrypted]); + } -let hash_fns; -if (nodeCrypto) { - // Use Node native crypto for all hash functions - hash_fns = { - md5: node_hash('md5'), - sha1: node_hash('sha1'), - sha224: node_hash('sha224'), - sha256: node_hash('sha256'), - sha384: node_hash('sha384'), - sha512: node_hash('sha512'), - ripemd: node_hash('ripemd160') - }; -} else { - // Use JS fallbacks - hash_fns = { - md5: _md2.default, - sha1: asmcrypto_hash(_sha.Sha1, navigator.userAgent.indexOf('Edge') === -1 && 'SHA-1'), - sha224: hashjs_hash(_2.default), - sha256: asmcrypto_hash(_sha2.Sha256, 'SHA-256'), - sha384: hashjs_hash(_4.default, 'SHA-384'), - sha512: hashjs_hash(_6.default, 'SHA-512'), // asmcrypto sha512 is huge. - ripemd: hashjs_hash(_ripemd.ripemd160) - }; -} + /** + * Encrypt the payload in the packet. + * @param {enums.symmetric} sessionKeyAlgorithm - The symmetric encryption algorithm to use + * @param {Uint8Array} key - The key of cipher blocksize length to be used + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} + * @throws {Error} on encryption failure + * @async + */ + async encrypt(sessionKeyAlgorithm, key, config = defaultConfig) { + const { blockSize } = mod.getCipher(sessionKeyAlgorithm); -exports.default = { + let bytes = this.packets.write(); + if (isArrayStream(bytes)) bytes = await readToEnd(bytes); + const prefix = await mod.getPrefixRandom(sessionKeyAlgorithm); + const mdc = new Uint8Array([0xD3, 0x14]); // modification detection code packet - /** @see module:md5 */ - md5: hash_fns.md5, - /** @see asmCrypto */ - sha1: hash_fns.sha1, - /** @see hash.js */ - sha224: hash_fns.sha224, - /** @see asmCrypto */ - sha256: hash_fns.sha256, - /** @see hash.js */ - sha384: hash_fns.sha384, - /** @see asmCrypto */ - sha512: hash_fns.sha512, - /** @see hash.js */ - ripemd: hash_fns.ripemd, + const tohash = util.concat([prefix, bytes, mdc]); + const hash = await mod.hash.sha1(passiveClone(tohash)); + const plaintext = util.concat([tohash, hash]); - /** - * Create a hash on the specified data using the specified algorithm - * @param {module:enums.hash} algo Hash algorithm type (see {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}) - * @param {Uint8Array} data Data to be hashed - * @returns {Promise} hash value - */ - digest: function digest(algo, data) { - switch (algo) { - case 1: - // - MD5 [HAC] - return this.md5(data); - case 2: - // - SHA-1 [FIPS180] - return this.sha1(data); - case 3: - // - RIPE-MD/160 [HAC] - return this.ripemd(data); - case 8: - // - SHA256 [FIPS180] - return this.sha256(data); - case 9: - // - SHA384 [FIPS180] - return this.sha384(data); - case 10: - // - SHA512 [FIPS180] - return this.sha512(data); - case 11: - // - SHA224 [FIPS180] - return this.sha224(data); - default: - throw new Error('Invalid hash function.'); - } - }, + this.encrypted = await mod.mode.cfb.encrypt(sessionKeyAlgorithm, key, plaintext, new Uint8Array(blockSize), config); + return true; + } /** - * Returns the hash size in bytes of the specified hash algorithm type - * @param {module:enums.hash} algo Hash algorithm type (See {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}) - * @returns {Integer} Size in bytes of the resulting hash + * Decrypts the encrypted data contained in the packet. + * @param {enums.symmetric} sessionKeyAlgorithm - The selected symmetric encryption algorithm to be used + * @param {Uint8Array} key - The key of cipher blocksize length to be used + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} + * @throws {Error} on decryption failure + * @async */ - getHashByteLength: function getHashByteLength(algo) { - switch (algo) { - case 1: - // - MD5 [HAC] - return 16; - case 2: // - SHA-1 [FIPS180] - case 3: - // - RIPE-MD/160 [HAC] - return 20; - case 8: - // - SHA256 [FIPS180] - return 32; - case 9: - // - SHA384 [FIPS180] - return 48; - case 10: - // - SHA512 [FIPS180] - return 64; - case 11: - // - SHA224 [FIPS180] - return 28; - default: - throw new Error('Invalid hash algorithm.'); + async decrypt(sessionKeyAlgorithm, key, config = defaultConfig) { + const { blockSize } = mod.getCipher(sessionKeyAlgorithm); + let encrypted = clone(this.encrypted); + if (isArrayStream(encrypted)) encrypted = await readToEnd(encrypted); + const decrypted = await mod.mode.cfb.decrypt(sessionKeyAlgorithm, key, encrypted, new Uint8Array(blockSize)); + + // there must be a modification detection code packet as the + // last packet and everything gets hashed except the hash itself + const realHash = slice(passiveClone(decrypted), -20); + const tohash = slice(decrypted, 0, -20); + const verifyHash = Promise.all([ + readToEnd(await mod.hash.sha1(passiveClone(tohash))), + readToEnd(realHash) + ]).then(([hash, mdc]) => { + if (!util.equalsUint8Array(hash, mdc)) { + throw new Error('Modification detected.'); + } + return new Uint8Array(); + }); + const bytes = slice(tohash, blockSize + 2); // Remove random prefix + let packetbytes = slice(bytes, 0, -2); // Remove MDC packet + packetbytes = concat([packetbytes, fromAsync(() => verifyHash)]); + if (!util.isStream(encrypted) || !config.allowUnauthenticatedStream) { + packetbytes = await readToEnd(packetbytes); } + this.packets = await PacketList.fromBinary(packetbytes, allowedPackets$1, config); + return true; } -}; +} -},{"../../config":79,"../../util":152,"./md5":93,"asmcrypto.js/dist_es5/hash/sha1/sha1":11,"asmcrypto.js/dist_es5/hash/sha256/sha256":13,"hash.js/lib/hash/ripemd":37,"hash.js/lib/hash/sha/224":40,"hash.js/lib/hash/sha/384":42,"hash.js/lib/hash/sha/512":43,"web-stream-tools":75}],93:[function(require,module,exports){ -'use strict'; +// OpenPGP.js - An OpenPGP implementation in javascript -Object.defineProperty(exports, "__esModule", { - value: true -}); +// An AEAD-encrypted Data packet can contain the following packet types +const allowedPackets$2 = /*#__PURE__*/ util.constructAllowedPackets([ + LiteralDataPacket, + CompressedDataPacket, + OnePassSignaturePacket, + SignaturePacket +]); -var _util = require('../../util'); +const VERSION$2 = 1; // A one-octet version number of the data packet. -var _util2 = _interopRequireDefault(_util); +/** + * Implementation of the Symmetrically Encrypted Authenticated Encryption with + * Additional Data (AEAD) Protected Data Packet + * + * {@link https://tools.ietf.org/html/draft-ford-openpgp-format-00#section-2.1}: + * AEAD Protected Data Packet + */ +class AEADEncryptedDataPacket { + static get tag() { + return enums.packet.aeadEncryptedData; + } -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + constructor() { + this.version = VERSION$2; + /** @type {enums.symmetric} */ + this.cipherAlgorithm = null; + /** @type {enums.aead} */ + this.aeadAlgorithm = enums.aead.eax; + this.chunkSizeByte = null; + this.iv = null; + this.encrypted = null; + this.packets = null; + } -// MD5 Digest -async function md5(entree) { - const digest = md51(_util2.default.Uint8Array_to_str(entree)); - return _util2.default.hex_to_Uint8Array(hex(digest)); -} /** - * A fast MD5 JavaScript implementation - * Copyright (c) 2012 Joseph Myers - * http://www.myersdaily.org/joseph/javascript/md5-text.html - * - * Permission to use, copy, modify, and distribute this software - * and its documentation for any purposes and without - * fee is hereby granted provided that this copyright notice - * appears in all copies. - * - * Of course, this soft is provided "as is" without express or implied - * warranty of any kind. + /** + * Parse an encrypted payload of bytes in the order: version, IV, ciphertext (see specification) + * @param {Uint8Array | ReadableStream} bytes + * @throws {Error} on parsing failure */ + async read(bytes) { + await parse(bytes, async reader => { + const version = await reader.readByte(); + if (version !== VERSION$2) { // The only currently defined value is 1. + throw new UnsupportedError(`Version ${version} of the AEAD-encrypted data packet is not supported.`); + } + this.cipherAlgorithm = await reader.readByte(); + this.aeadAlgorithm = await reader.readByte(); + this.chunkSizeByte = await reader.readByte(); + + const mode = mod.getAEADMode(this.aeadAlgorithm); + this.iv = await reader.readBytes(mode.ivLength); + this.encrypted = reader.remainder(); + }); + } -/** - * @requires util - */ + /** + * Write the encrypted payload of bytes in the order: version, IV, ciphertext (see specification) + * @returns {Uint8Array | ReadableStream} The encrypted payload. + */ + write() { + return util.concat([new Uint8Array([this.version, this.cipherAlgorithm, this.aeadAlgorithm, this.chunkSizeByte]), this.iv, this.encrypted]); + } -function md5cycle(x, k) { - let a = x[0]; - let b = x[1]; - let c = x[2]; - let d = x[3]; + /** + * Decrypt the encrypted payload. + * @param {enums.symmetric} sessionKeyAlgorithm - The session key's cipher algorithm + * @param {Uint8Array} key - The session key used to encrypt the payload + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if decryption was not successful + * @async + */ + async decrypt(sessionKeyAlgorithm, key, config = defaultConfig) { + this.packets = await PacketList.fromBinary( + await this.crypt('decrypt', key, clone(this.encrypted)), + allowedPackets$2, + config + ); + } - a = ff(a, b, c, d, k[0], 7, -680876936); - d = ff(d, a, b, c, k[1], 12, -389564586); - c = ff(c, d, a, b, k[2], 17, 606105819); - b = ff(b, c, d, a, k[3], 22, -1044525330); - a = ff(a, b, c, d, k[4], 7, -176418897); - d = ff(d, a, b, c, k[5], 12, 1200080426); - c = ff(c, d, a, b, k[6], 17, -1473231341); - b = ff(b, c, d, a, k[7], 22, -45705983); - a = ff(a, b, c, d, k[8], 7, 1770035416); - d = ff(d, a, b, c, k[9], 12, -1958414417); - c = ff(c, d, a, b, k[10], 17, -42063); - b = ff(b, c, d, a, k[11], 22, -1990404162); - a = ff(a, b, c, d, k[12], 7, 1804603682); - d = ff(d, a, b, c, k[13], 12, -40341101); - c = ff(c, d, a, b, k[14], 17, -1502002290); - b = ff(b, c, d, a, k[15], 22, 1236535329); + /** + * Encrypt the packet payload. + * @param {enums.symmetric} sessionKeyAlgorithm - The session key's cipher algorithm + * @param {Uint8Array} key - The session key used to encrypt the payload + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if encryption was not successful + * @async + */ + async encrypt(sessionKeyAlgorithm, key, config = defaultConfig) { + this.cipherAlgorithm = sessionKeyAlgorithm; - a = gg(a, b, c, d, k[1], 5, -165796510); - d = gg(d, a, b, c, k[6], 9, -1069501632); - c = gg(c, d, a, b, k[11], 14, 643717713); - b = gg(b, c, d, a, k[0], 20, -373897302); - a = gg(a, b, c, d, k[5], 5, -701558691); - d = gg(d, a, b, c, k[10], 9, 38016083); - c = gg(c, d, a, b, k[15], 14, -660478335); - b = gg(b, c, d, a, k[4], 20, -405537848); - a = gg(a, b, c, d, k[9], 5, 568446438); - d = gg(d, a, b, c, k[14], 9, -1019803690); - c = gg(c, d, a, b, k[3], 14, -187363961); - b = gg(b, c, d, a, k[8], 20, 1163531501); - a = gg(a, b, c, d, k[13], 5, -1444681467); - d = gg(d, a, b, c, k[2], 9, -51403784); - c = gg(c, d, a, b, k[7], 14, 1735328473); - b = gg(b, c, d, a, k[12], 20, -1926607734); + const { ivLength } = mod.getAEADMode(this.aeadAlgorithm); + this.iv = await mod.random.getRandomBytes(ivLength); // generate new random IV + this.chunkSizeByte = config.aeadChunkSizeByte; + const data = this.packets.write(); + this.encrypted = await this.crypt('encrypt', key, data); + } - a = hh(a, b, c, d, k[5], 4, -378558); - d = hh(d, a, b, c, k[8], 11, -2022574463); - c = hh(c, d, a, b, k[11], 16, 1839030562); - b = hh(b, c, d, a, k[14], 23, -35309556); - a = hh(a, b, c, d, k[1], 4, -1530992060); - d = hh(d, a, b, c, k[4], 11, 1272893353); - c = hh(c, d, a, b, k[7], 16, -155497632); - b = hh(b, c, d, a, k[10], 23, -1094730640); - a = hh(a, b, c, d, k[13], 4, 681279174); - d = hh(d, a, b, c, k[0], 11, -358537222); - c = hh(c, d, a, b, k[3], 16, -722521979); - b = hh(b, c, d, a, k[6], 23, 76029189); - a = hh(a, b, c, d, k[9], 4, -640364487); - d = hh(d, a, b, c, k[12], 11, -421815835); - c = hh(c, d, a, b, k[15], 16, 530742520); - b = hh(b, c, d, a, k[2], 23, -995338651); + /** + * En/decrypt the payload. + * @param {encrypt|decrypt} fn - Whether to encrypt or decrypt + * @param {Uint8Array} key - The session key used to en/decrypt the payload + * @param {Uint8Array | ReadableStream} data - The data to en/decrypt + * @returns {Promise>} + * @async + */ + async crypt(fn, key, data) { + const mode = mod.getAEADMode(this.aeadAlgorithm); + const modeInstance = await mode(this.cipherAlgorithm, key); + const tagLengthIfDecrypting = fn === 'decrypt' ? mode.tagLength : 0; + const tagLengthIfEncrypting = fn === 'encrypt' ? mode.tagLength : 0; + const chunkSize = 2 ** (this.chunkSizeByte + 6) + tagLengthIfDecrypting; // ((uint64_t)1 << (c + 6)) + const adataBuffer = new ArrayBuffer(21); + const adataArray = new Uint8Array(adataBuffer, 0, 13); + const adataTagArray = new Uint8Array(adataBuffer); + const adataView = new DataView(adataBuffer); + const chunkIndexArray = new Uint8Array(adataBuffer, 5, 8); + adataArray.set([0xC0 | AEADEncryptedDataPacket.tag, this.version, this.cipherAlgorithm, this.aeadAlgorithm, this.chunkSizeByte], 0); + let chunkIndex = 0; + let latestPromise = Promise.resolve(); + let cryptedBytes = 0; + let queuedBytes = 0; + const iv = this.iv; + return transformPair(data, async (readable, writable) => { + if (util.isStream(readable) !== 'array') { + const buffer = new TransformStream({}, { + highWaterMark: util.getHardwareConcurrency() * 2 ** (this.chunkSizeByte + 6), + size: array => array.length + }); + pipe(buffer.readable, writable); + writable = buffer.writable; + } + const reader = getReader(readable); + const writer = getWriter(writable); + try { + while (true) { + let chunk = await reader.readBytes(chunkSize + tagLengthIfDecrypting) || new Uint8Array(); + const finalChunk = chunk.subarray(chunk.length - tagLengthIfDecrypting); + chunk = chunk.subarray(0, chunk.length - tagLengthIfDecrypting); + let cryptedPromise; + let done; + if (!chunkIndex || chunk.length) { + reader.unshift(finalChunk); + cryptedPromise = modeInstance[fn](chunk, mode.getNonce(iv, chunkIndexArray), adataArray); + queuedBytes += chunk.length - tagLengthIfDecrypting + tagLengthIfEncrypting; + } else { + // After the last chunk, we either encrypt a final, empty + // data chunk to get the final authentication tag or + // validate that final authentication tag. + adataView.setInt32(13 + 4, cryptedBytes); // Should be setInt64(13, ...) + cryptedPromise = modeInstance[fn](finalChunk, mode.getNonce(iv, chunkIndexArray), adataTagArray); + queuedBytes += tagLengthIfEncrypting; + done = true; + } + cryptedBytes += chunk.length - tagLengthIfDecrypting; + // eslint-disable-next-line no-loop-func + latestPromise = latestPromise.then(() => cryptedPromise).then(async crypted => { + await writer.ready; + await writer.write(crypted); + queuedBytes -= crypted.length; + }).catch(err => writer.abort(err)); + if (done || queuedBytes > writer.desiredSize) { + await latestPromise; // Respect backpressure + } + if (!done) { + adataView.setInt32(5 + 4, ++chunkIndex); // Should be setInt64(5, ...) + } else { + await writer.close(); + break; + } + } + } catch (e) { + await writer.abort(e); + } + }); + } +} - a = ii(a, b, c, d, k[0], 6, -198630844); - d = ii(d, a, b, c, k[7], 10, 1126891415); - c = ii(c, d, a, b, k[14], 15, -1416354905); - b = ii(b, c, d, a, k[5], 21, -57434055); - a = ii(a, b, c, d, k[12], 6, 1700485571); - d = ii(d, a, b, c, k[3], 10, -1894986606); - c = ii(c, d, a, b, k[10], 15, -1051523); - b = ii(b, c, d, a, k[1], 21, -2054922799); - a = ii(a, b, c, d, k[8], 6, 1873313359); - d = ii(d, a, b, c, k[15], 10, -30611744); - c = ii(c, d, a, b, k[6], 15, -1560198380); - b = ii(b, c, d, a, k[13], 21, 1309151649); - a = ii(a, b, c, d, k[4], 6, -145523070); - d = ii(d, a, b, c, k[11], 10, -1120210379); - c = ii(c, d, a, b, k[2], 15, 718787259); - b = ii(b, c, d, a, k[9], 21, -343485551); +// GPG4Browsers - An OpenPGP implementation in javascript - x[0] = add32(a, x[0]); - x[1] = add32(b, x[1]); - x[2] = add32(c, x[2]); - x[3] = add32(d, x[3]); -} +const VERSION$3 = 3; + +/** + * Public-Key Encrypted Session Key Packets (Tag 1) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.1|RFC4880 5.1}: + * A Public-Key Encrypted Session Key packet holds the session key + * used to encrypt a message. Zero or more Public-Key Encrypted Session Key + * packets and/or Symmetric-Key Encrypted Session Key packets may precede a + * Symmetrically Encrypted Data Packet, which holds an encrypted message. The + * message is encrypted with the session key, and the session key is itself + * encrypted and stored in the Encrypted Session Key packet(s). The + * Symmetrically Encrypted Data Packet is preceded by one Public-Key Encrypted + * Session Key packet for each OpenPGP key to which the message is encrypted. + * The recipient of the message finds a session key that is encrypted to their + * public key, decrypts the session key, and then uses the session key to + * decrypt the message. + */ +class PublicKeyEncryptedSessionKeyPacket { + static get tag() { + return enums.packet.publicKeyEncryptedSessionKey; + } -function cmn(q, a, b, x, s, t) { - a = add32(add32(a, q), add32(x, t)); - return add32(a << s | a >>> 32 - s, b); -} + constructor() { + this.version = 3; -function ff(a, b, c, d, x, s, t) { - return cmn(b & c | ~b & d, a, b, x, s, t); -} + this.publicKeyID = new KeyID(); + this.publicKeyAlgorithm = null; -function gg(a, b, c, d, x, s, t) { - return cmn(b & d | c & ~d, a, b, x, s, t); -} + this.sessionKey = null; + /** + * Algorithm to encrypt the message with + * @type {enums.symmetric} + */ + this.sessionKeyAlgorithm = null; -function hh(a, b, c, d, x, s, t) { - return cmn(b ^ c ^ d, a, b, x, s, t); -} + /** @type {Object} */ + this.encrypted = {}; + } -function ii(a, b, c, d, x, s, t) { - return cmn(c ^ (b | ~d), a, b, x, s, t); -} + /** + * Parsing function for a publickey encrypted session key packet (tag 1). + * + * @param {Uint8Array} bytes - Payload of a tag 1 packet + */ + read(bytes) { + this.version = bytes[0]; + if (this.version !== VERSION$3) { + throw new UnsupportedError(`Version ${this.version} of the PKESK packet is unsupported.`); + } + this.publicKeyID.read(bytes.subarray(1, bytes.length)); + this.publicKeyAlgorithm = bytes[9]; + this.encrypted = mod.parseEncSessionKeyParams(this.publicKeyAlgorithm, bytes.subarray(10)); + } -function md51(s) { - const n = s.length; - const state = [1732584193, -271733879, -1732584194, 271733878]; - let i; - for (i = 64; i <= s.length; i += 64) { - md5cycle(state, md5blk(s.substring(i - 64, i))); + /** + * Create a binary representation of a tag 1 packet + * + * @returns {Uint8Array} The Uint8Array representation. + */ + write() { + const arr = [ + new Uint8Array([this.version]), + this.publicKeyID.write(), + new Uint8Array([this.publicKeyAlgorithm]), + mod.serializeParams(this.publicKeyAlgorithm, this.encrypted) + ]; + + return util.concatUint8Array(arr); } - s = s.substring(i - 64); - const tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; - for (i = 0; i < s.length; i++) { - tail[i >> 2] |= s.charCodeAt(i) << (i % 4 << 3); + + /** + * Encrypt session key packet + * @param {PublicKeyPacket} key - Public key + * @throws {Error} if encryption failed + * @async + */ + async encrypt(key) { + const data = util.concatUint8Array([ + new Uint8Array([enums.write(enums.symmetric, this.sessionKeyAlgorithm)]), + this.sessionKey, + util.writeChecksum(this.sessionKey) + ]); + const algo = enums.write(enums.publicKey, this.publicKeyAlgorithm); + this.encrypted = await mod.publicKeyEncrypt( + algo, key.publicParams, data, key.getFingerprintBytes()); } - tail[i >> 2] |= 0x80 << (i % 4 << 3); - if (i > 55) { - md5cycle(state, tail); - for (i = 0; i < 16; i++) { - tail[i] = 0; + + /** + * Decrypts the session key (only for public key encrypted session key packets (tag 1) + * @param {SecretKeyPacket} key - decrypted private key + * @param {Object} [randomSessionKey] - Bogus session key to use in case of sensitive decryption error, or if the decrypted session key is of a different type/size. + * This is needed for constant-time processing. Expected object of the form: { sessionKey: Uint8Array, sessionKeyAlgorithm: enums.symmetric } + * @throws {Error} if decryption failed, unless `randomSessionKey` is given + * @async + */ + async decrypt(key, randomSessionKey) { + // check that session key algo matches the secret key algo + if (this.publicKeyAlgorithm !== key.algorithm) { + throw new Error('Decryption error'); + } + + const randomPayload = randomSessionKey ? util.concatUint8Array([ + new Uint8Array([randomSessionKey.sessionKeyAlgorithm]), + randomSessionKey.sessionKey, + util.writeChecksum(randomSessionKey.sessionKey) + ]) : null; + const decoded = await mod.publicKeyDecrypt(this.publicKeyAlgorithm, key.publicParams, key.privateParams, this.encrypted, key.getFingerprintBytes(), randomPayload); + const symmetricAlgoByte = decoded[0]; + const sessionKey = decoded.subarray(1, decoded.length - 2); + const checksum = decoded.subarray(decoded.length - 2); + const computedChecksum = util.writeChecksum(sessionKey); + const isValidChecksum = computedChecksum[0] === checksum[0] & computedChecksum[1] === checksum[1]; + + if (randomSessionKey) { + // We must not leak info about the validity of the decrypted checksum or cipher algo. + // The decrypted session key must be of the same algo and size as the random session key, otherwise we discard it and use the random data. + const isValidPayload = isValidChecksum & symmetricAlgoByte === randomSessionKey.sessionKeyAlgorithm & sessionKey.length === randomSessionKey.sessionKey.length; + this.sessionKeyAlgorithm = util.selectUint8(isValidPayload, symmetricAlgoByte, randomSessionKey.sessionKeyAlgorithm); + this.sessionKey = util.selectUint8Array(isValidPayload, sessionKey, randomSessionKey.sessionKey); + + } else { + const isValidPayload = isValidChecksum && enums.read(enums.symmetric, symmetricAlgoByte); + if (isValidPayload) { + this.sessionKey = sessionKey; + this.sessionKeyAlgorithm = symmetricAlgoByte; + } else { + throw new Error('Decryption error'); + } } } - tail[14] = n * 8; - md5cycle(state, tail); - return state; } -/* there needs to be support for Unicode here, - * unless we pretend that we can redefine the MD-5 - * algorithm for multi-byte characters (perhaps - * by adding every four 16-bit characters and - * shortening the sum to 32 bits). Otherwise - * I suggest performing MD-5 as if every character - * was two bytes--e.g., 0040 0025 = @%--but then - * how will an ordinary MD-5 sum be matched? - * There is no way to standardize text to something - * like UTF-8 before transformation; speed cost is - * utterly prohibitive. The JavaScript standard - * itself needs to look at this: it should start - * providing access to strings as preformed UTF-8 - * 8-bit unsigned value arrays. - */ -function md5blk(s) { - /* I figured global was faster. */ - const md5blks = []; - let i; /* Andy King said do it this way. */ - for (i = 0; i < 64; i += 4) { - md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24); +// GPG4Browsers - An OpenPGP implementation in javascript + +class S2K { + /** + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + constructor(config = defaultConfig) { + /** + * Hash function identifier, or 0 for gnu-dummy keys + * @type {module:enums.hash | 0} + */ + this.algorithm = enums.hash.sha256; + /** + * enums.s2k identifier or 'gnu-dummy' + * @type {String} + */ + this.type = 'iterated'; + /** @type {Integer} */ + this.c = config.s2kIterationCountByte; + /** Eight bytes of salt in a binary string. + * @type {Uint8Array} + */ + this.salt = null; } - return md5blks; -} -const hex_chr = '0123456789abcdef'.split(''); + getCount() { + // Exponent bias, defined in RFC4880 + const expbias = 6; -function rhex(n) { - let s = ''; - let j = 0; - for (; j < 4; j++) { - s += hex_chr[n >> j * 8 + 4 & 0x0F] + hex_chr[n >> j * 8 & 0x0F]; + return (16 + (this.c & 15)) << ((this.c >> 4) + expbias); } - return s; -} -function hex(x) { - for (let i = 0; i < x.length; i++) { - x[i] = rhex(x[i]); + /** + * Parsing function for a string-to-key specifier ({@link https://tools.ietf.org/html/rfc4880#section-3.7|RFC 4880 3.7}). + * @param {Uint8Array} bytes - Payload of string-to-key specifier + * @returns {Integer} Actual length of the object. + */ + read(bytes) { + let i = 0; + this.type = enums.read(enums.s2k, bytes[i++]); + this.algorithm = bytes[i++]; + + switch (this.type) { + case 'simple': + break; + + case 'salted': + this.salt = bytes.subarray(i, i + 8); + i += 8; + break; + + case 'iterated': + this.salt = bytes.subarray(i, i + 8); + i += 8; + + // Octet 10: count, a one-octet, coded value + this.c = bytes[i++]; + break; + + case 'gnu': + if (util.uint8ArrayToString(bytes.subarray(i, i + 3)) === 'GNU') { + i += 3; // GNU + const gnuExtType = 1000 + bytes[i++]; + if (gnuExtType === 1001) { + this.type = 'gnu-dummy'; + // GnuPG extension mode 1001 -- don't write secret key at all + } else { + throw new Error('Unknown s2k gnu protection mode.'); + } + } else { + throw new Error('Unknown s2k type.'); + } + break; + + default: + throw new Error('Unknown s2k type.'); + } + + return i; } - return x.join(''); -} -/* this function is much faster, -so if possible we use it. Some IEs -are the only ones I know of that -need the idiotic second function, -generated by an if clause. */ + /** + * Serializes s2k information + * @returns {Uint8Array} Binary representation of s2k. + */ + write() { + if (this.type === 'gnu-dummy') { + return new Uint8Array([101, 0, ...util.stringToUint8Array('GNU'), 1]); + } + const arr = [new Uint8Array([enums.write(enums.s2k, this.type), this.algorithm])]; -function add32(a, b) { - return a + b & 0xFFFFFFFF; -} + switch (this.type) { + case 'simple': + break; + case 'salted': + arr.push(this.salt); + break; + case 'iterated': + arr.push(this.salt); + arr.push(new Uint8Array([this.c])); + break; + case 'gnu': + throw new Error('GNU s2k type not supported.'); + default: + throw new Error('Unknown s2k type.'); + } -exports.default = md5; + return util.concatUint8Array(arr); + } -},{"../../util":152}],94:[function(require,module,exports){ -'use strict'; + /** + * Produces a key using the specified passphrase and the defined + * hashAlgorithm + * @param {String} passphrase - Passphrase containing user input + * @returns {Promise} Produced key with a length corresponding to. + * hashAlgorithm hash length + * @async + */ + async produceKey(passphrase, numBytes) { + passphrase = util.encodeUTF8(passphrase); -Object.defineProperty(exports, "__esModule", { - value: true -}); + const arr = []; + let rlength = 0; + + let prefixlen = 0; + while (rlength < numBytes) { + let toHash; + switch (this.type) { + case 'simple': + toHash = util.concatUint8Array([new Uint8Array(prefixlen), passphrase]); + break; + case 'salted': + toHash = util.concatUint8Array([new Uint8Array(prefixlen), this.salt, passphrase]); + break; + case 'iterated': { + const data = util.concatUint8Array([this.salt, passphrase]); + let datalen = data.length; + const count = Math.max(this.getCount(), datalen); + toHash = new Uint8Array(prefixlen + count); + toHash.set(data, prefixlen); + for (let pos = prefixlen + datalen; pos < count; pos += datalen, datalen *= 2) { + toHash.copyWithin(pos, prefixlen, pos); + } + break; + } + case 'gnu': + throw new Error('GNU s2k type not supported.'); + default: + throw new Error('Unknown s2k type.'); + } + const result = await mod.hash.digest(this.algorithm, toHash); + arr.push(result); + rlength += result.length; + prefixlen++; + } + + return util.concatUint8Array(arr).subarray(0, numBytes); + } +} + +// GPG4Browsers - An OpenPGP implementation in javascript + +/** + * Symmetric-Key Encrypted Session Key Packets (Tag 3) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.3|RFC4880 5.3}: + * The Symmetric-Key Encrypted Session Key packet holds the + * symmetric-key encryption of a session key used to encrypt a message. + * Zero or more Public-Key Encrypted Session Key packets and/or + * Symmetric-Key Encrypted Session Key packets may precede a + * Symmetrically Encrypted Data packet that holds an encrypted message. + * The message is encrypted with a session key, and the session key is + * itself encrypted and stored in the Encrypted Session Key packet or + * the Symmetric-Key Encrypted Session Key packet. + */ +class SymEncryptedSessionKeyPacket { + static get tag() { + return enums.packet.symEncryptedSessionKey; + } -var _cipher = require('./cipher'); + /** + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + constructor(config = defaultConfig) { + this.version = config.aeadProtect ? 5 : 4; + this.sessionKey = null; + /** + * Algorithm to encrypt the session key with + * @type {enums.symmetric} + */ + this.sessionKeyEncryptionAlgorithm = null; + /** + * Algorithm to encrypt the message with + * @type {enums.symmetric} + */ + this.sessionKeyAlgorithm = enums.symmetric.aes256; + /** + * AEAD mode to encrypt the session key with (if AEAD protection is enabled) + * @type {enums.aead} + */ + this.aeadAlgorithm = enums.write(enums.aead, config.preferredAEADAlgorithm); + this.encrypted = null; + this.s2k = null; + this.iv = null; + } -var _cipher2 = _interopRequireDefault(_cipher); + /** + * Parsing function for a symmetric encrypted session key packet (tag 3). + * + * @param {Uint8Array} bytes - Payload of a tag 3 packet + */ + read(bytes) { + let offset = 0; -var _hash = require('./hash'); + // A one-octet version number. The only currently defined version is 4. + this.version = bytes[offset++]; + if (this.version !== 4 && this.version !== 5) { + throw new UnsupportedError(`Version ${this.version} of the SKESK packet is unsupported.`); + } -var _hash2 = _interopRequireDefault(_hash); + // A one-octet number describing the symmetric algorithm used. + const algo = bytes[offset++]; -var _cfb = require('./cfb'); + if (this.version === 5) { + // A one-octet AEAD algorithm. + this.aeadAlgorithm = bytes[offset++]; + } -var _cfb2 = _interopRequireDefault(_cfb); + // A string-to-key (S2K) specifier, length as defined above. + this.s2k = new S2K(); + offset += this.s2k.read(bytes.subarray(offset, bytes.length)); -var _gcm = require('./gcm'); + if (this.version === 5) { + const mode = mod.getAEADMode(this.aeadAlgorithm); -var _gcm2 = _interopRequireDefault(_gcm); + // A starting initialization vector of size specified by the AEAD + // algorithm. + this.iv = bytes.subarray(offset, offset += mode.ivLength); + } -var _eax = require('./eax'); + // The encrypted session key itself, which is decrypted with the + // string-to-key object. This is optional in version 4. + if (this.version === 5 || offset < bytes.length) { + this.encrypted = bytes.subarray(offset, bytes.length); + this.sessionKeyEncryptionAlgorithm = algo; + } else { + this.sessionKeyAlgorithm = algo; + } + } -var _eax2 = _interopRequireDefault(_eax); + /** + * Create a binary representation of a tag 3 packet + * + * @returns {Uint8Array} The Uint8Array representation. + */ + write() { + const algo = this.encrypted === null ? + this.sessionKeyAlgorithm : + this.sessionKeyEncryptionAlgorithm; -var _ocb = require('./ocb'); + let bytes; -var _ocb2 = _interopRequireDefault(_ocb); + if (this.version === 5) { + bytes = util.concatUint8Array([new Uint8Array([this.version, algo, this.aeadAlgorithm]), this.s2k.write(), this.iv, this.encrypted]); + } else { + bytes = util.concatUint8Array([new Uint8Array([this.version, algo]), this.s2k.write()]); -var _public_key = require('./public_key'); + if (this.encrypted !== null) { + bytes = util.concatUint8Array([bytes, this.encrypted]); + } + } -var _public_key2 = _interopRequireDefault(_public_key); + return bytes; + } -var _signature = require('./signature'); + /** + * Decrypts the session key with the given passphrase + * @param {String} passphrase - The passphrase in string form + * @throws {Error} if decryption was not successful + * @async + */ + async decrypt(passphrase) { + const algo = this.sessionKeyEncryptionAlgorithm !== null ? + this.sessionKeyEncryptionAlgorithm : + this.sessionKeyAlgorithm; -var _signature2 = _interopRequireDefault(_signature); + const { blockSize, keySize } = mod.getCipher(algo); + const key = await this.s2k.produceKey(passphrase, keySize); -var _random = require('./random'); + if (this.version === 5) { + const mode = mod.getAEADMode(this.aeadAlgorithm); + const adata = new Uint8Array([0xC0 | SymEncryptedSessionKeyPacket.tag, this.version, this.sessionKeyEncryptionAlgorithm, this.aeadAlgorithm]); + const modeInstance = await mode(algo, key); + this.sessionKey = await modeInstance.decrypt(this.encrypted, this.iv, adata); + } else if (this.encrypted !== null) { + const decrypted = await mod.mode.cfb.decrypt(algo, key, this.encrypted, new Uint8Array(blockSize)); + + this.sessionKeyAlgorithm = enums.write(enums.symmetric, decrypted[0]); + this.sessionKey = decrypted.subarray(1, decrypted.length); + } else { + this.sessionKey = key; + } + } -var _random2 = _interopRequireDefault(_random); + /** + * Encrypts the session key with the given passphrase + * @param {String} passphrase - The passphrase in string form + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if encryption was not successful + * @async + */ + async encrypt(passphrase, config = defaultConfig) { + const algo = this.sessionKeyEncryptionAlgorithm !== null ? + this.sessionKeyEncryptionAlgorithm : + this.sessionKeyAlgorithm; -var _pkcs = require('./pkcs1'); + this.sessionKeyEncryptionAlgorithm = algo; -var _pkcs2 = _interopRequireDefault(_pkcs); + this.s2k = new S2K(config); + this.s2k.salt = await mod.random.getRandomBytes(8); -var _pkcs3 = require('./pkcs5'); + const { blockSize, keySize } = mod.getCipher(algo); + const encryptionKey = await this.s2k.produceKey(passphrase, keySize); -var _pkcs4 = _interopRequireDefault(_pkcs3); + if (this.sessionKey === null) { + this.sessionKey = await mod.generateSessionKey(this.sessionKeyAlgorithm); + } -var _crypto = require('./crypto'); + if (this.version === 5) { + const mode = mod.getAEADMode(this.aeadAlgorithm); + this.iv = await mod.random.getRandomBytes(mode.ivLength); // generate new random IV + const associatedData = new Uint8Array([0xC0 | SymEncryptedSessionKeyPacket.tag, this.version, this.sessionKeyEncryptionAlgorithm, this.aeadAlgorithm]); + const modeInstance = await mode(algo, encryptionKey); + this.encrypted = await modeInstance.encrypt(this.sessionKey, this.iv, associatedData); + } else { + const toEncrypt = util.concatUint8Array([ + new Uint8Array([this.sessionKeyAlgorithm]), + this.sessionKey + ]); + this.encrypted = await mod.mode.cfb.encrypt(algo, encryptionKey, toEncrypt, new Uint8Array(blockSize), config); + } + } +} -var _crypto2 = _interopRequireDefault(_crypto); +// GPG4Browsers - An OpenPGP implementation in javascript -var _aes_kw = require('./aes_kw'); +/** + * Implementation of the Key Material Packet (Tag 5,6,7,14) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.5|RFC4480 5.5}: + * A key material packet contains all the information about a public or + * private key. There are four variants of this packet type, and two + * major versions. + * + * A Public-Key packet starts a series of packets that forms an OpenPGP + * key (sometimes called an OpenPGP certificate). + */ +class PublicKeyPacket { + static get tag() { + return enums.packet.publicKey; + } -var _aes_kw2 = _interopRequireDefault(_aes_kw); + /** + * @param {Date} [date] - Creation date + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + constructor(date = new Date(), config = defaultConfig) { + /** + * Packet version + * @type {Integer} + */ + this.version = config.v5Keys ? 5 : 4; + /** + * Key creation date. + * @type {Date} + */ + this.created = util.normalizeDate(date); + /** + * Public key algorithm. + * @type {enums.publicKey} + */ + this.algorithm = null; + /** + * Algorithm specific public params + * @type {Object} + */ + this.publicParams = null; + /** + * Time until expiration in days (V3 only) + * @type {Integer} + */ + this.expirationTimeV3 = 0; + /** + * Fingerprint bytes + * @type {Uint8Array} + */ + this.fingerprint = null; + /** + * KeyID + * @type {module:type/keyid~KeyID} + */ + this.keyID = null; + } -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + /** + * Create a PublicKeyPacket from a SecretKeyPacket + * @param {SecretKeyPacket} secretKeyPacket - key packet to convert + * @returns {PublicKeyPacket} public key packet + * @static + */ + static fromSecretKeyPacket(secretKeyPacket) { + const keyPacket = new PublicKeyPacket(); + const { version, created, algorithm, publicParams, keyID, fingerprint } = secretKeyPacket; + keyPacket.version = version; + keyPacket.created = created; + keyPacket.algorithm = algorithm; + keyPacket.publicParams = publicParams; + keyPacket.keyID = keyID; + keyPacket.fingerprint = fingerprint; + return keyPacket; + } -// TODO move cfb and gcm to cipher -const mod = { - /** @see module:crypto/cipher */ - cipher: _cipher2.default, - /** @see module:crypto/hash */ - hash: _hash2.default, - /** @see module:crypto/cfb */ - cfb: _cfb2.default, - /** @see module:crypto/gcm */ - gcm: _gcm2.default, - experimental_gcm: _gcm2.default, - /** @see module:crypto/eax */ - eax: _eax2.default, - /** @see module:crypto/ocb */ - ocb: _ocb2.default, - /** @see module:crypto/public_key */ - publicKey: _public_key2.default, - /** @see module:crypto/signature */ - signature: _signature2.default, - /** @see module:crypto/random */ - random: _random2.default, - /** @see module:crypto/pkcs1 */ - pkcs1: _pkcs2.default, - /** @see module:crypto/pkcs5 */ - pkcs5: _pkcs4.default, - /** @see module:crypto/aes_kw */ - aes_kw: _aes_kw2.default -}; /** - * @fileoverview Provides access to all cryptographic primitives used in OpenPGP.js - * @see module:crypto/crypto - * @see module:crypto/signature - * @see module:crypto/public_key - * @see module:crypto/cipher - * @see module:crypto/random - * @see module:crypto/hash - * @module crypto - */ + /** + * Internal Parser for public keys as specified in {@link https://tools.ietf.org/html/rfc4880#section-5.5.2|RFC 4880 section 5.5.2 Public-Key Packet Formats} + * @param {Uint8Array} bytes - Input array to read the packet from + * @returns {Object} This object with attributes set by the parser + * @async + */ + async read(bytes) { + let pos = 0; + // A one-octet version number (3, 4 or 5). + this.version = bytes[pos++]; -Object.assign(mod, _crypto2.default); + if (this.version === 4 || this.version === 5) { + // - A four-octet number denoting the time that the key was created. + this.created = util.readDate(bytes.subarray(pos, pos + 4)); + pos += 4; -exports.default = mod; + // - A one-octet number denoting the public-key algorithm of this key. + this.algorithm = bytes[pos++]; -},{"./aes_kw":80,"./cfb":81,"./cipher":86,"./crypto":89,"./eax":90,"./gcm":91,"./hash":92,"./ocb":95,"./pkcs1":96,"./pkcs5":97,"./public_key":106,"./random":109,"./signature":110}],95:[function(require,module,exports){ -'use strict'; + if (this.version === 5) { + // - A four-octet scalar octet count for the following key material. + pos += 4; + } -Object.defineProperty(exports, "__esModule", { - value: true -}); + // - A series of values comprising the key material. + try { + const { read, publicParams } = mod.parsePublicKeyParams(this.algorithm, bytes.subarray(pos)); + this.publicParams = publicParams; + pos += read; + } catch (err) { + throw new Error('Error reading MPIs'); + } -var _cipher = require('./cipher'); + // we set the fingerprint and keyID already to make it possible to put together the key packets directly in the Key constructor + await this.computeFingerprintAndKeyID(); + return pos; + } + throw new UnsupportedError(`Version ${this.version} of the key packet is unsupported.`); + } -var _cipher2 = _interopRequireDefault(_cipher); + /** + * Creates an OpenPGP public key packet for the given key. + * @returns {Uint8Array} Bytes encoding the public key OpenPGP packet. + */ + write() { + const arr = []; + // Version + arr.push(new Uint8Array([this.version])); + arr.push(util.writeDate(this.created)); + // A one-octet number denoting the public-key algorithm of this key + arr.push(new Uint8Array([this.algorithm])); -var _util = require('../util'); + const params = mod.serializeParams(this.algorithm, this.publicParams); + if (this.version === 5) { + // A four-octet scalar octet count for the following key material + arr.push(util.writeNumber(params.length, 4)); + } + // Algorithm-specific params + arr.push(params); + return util.concatUint8Array(arr); + } -var _util2 = _interopRequireDefault(_util); + /** + * Write packet in order to be hashed; either for a signature or a fingerprint + * @param {Integer} version - target version of signature or key + */ + writeForHash(version) { + const bytes = this.writePublicKey(); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + if (version === 5) { + return util.concatUint8Array([new Uint8Array([0x9A]), util.writeNumber(bytes.length, 4), bytes]); + } + return util.concatUint8Array([new Uint8Array([0x99]), util.writeNumber(bytes.length, 2), bytes]); + } -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2018 ProtonTech AG -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + /** + * Check whether secret-key data is available in decrypted form. Returns null for public keys. + * @returns {Boolean|null} + */ + isDecrypted() { + return null; + } -/** - * @fileoverview This module implements AES-OCB en/decryption. - * @requires crypto/cipher - * @requires util - * @module crypto/ocb - */ + /** + * Returns the creation time of the key + * @returns {Date} + */ + getCreationTime() { + return this.created; + } -const blockLength = 16; -const ivLength = 15; + /** + * Return the key ID of the key + * @returns {module:type/keyid~KeyID} The 8-byte key ID + */ + getKeyID() { + return this.keyID; + } -// https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.2: -// While OCB [RFC7253] allows the authentication tag length to be of any -// number up to 128 bits long, this document requires a fixed -// authentication tag length of 128 bits (16 octets) for simplicity. -const tagLength = 16; + /** + * Computes and set the key ID and fingerprint of the key + * @async + */ + async computeFingerprintAndKeyID() { + await this.computeFingerprint(); + this.keyID = new KeyID(); -function ntz(n) { - let ntz = 0; - for (let i = 1; (n & i) === 0; i <<= 1) { - ntz++; + if (this.version === 5) { + this.keyID.read(this.fingerprint.subarray(0, 8)); + } else if (this.version === 4) { + this.keyID.read(this.fingerprint.subarray(12, 20)); + } else { + throw new Error('Unsupported key version'); + } } - return ntz; -} -function xorMut(S, T) { - for (let i = 0; i < S.length; i++) { - S[i] ^= T[i]; + /** + * Computes and set the fingerprint of the key + */ + async computeFingerprint() { + const toHash = this.writeForHash(this.version); + + if (this.version === 5) { + this.fingerprint = await mod.hash.sha256(toHash); + } else if (this.version === 4) { + this.fingerprint = await mod.hash.sha1(toHash); + } else { + throw new Error('Unsupported key version'); + } } - return S; -} -function xor(S, T) { - return xorMut(S.slice(), T); + /** + * Returns the fingerprint of the key, as an array of bytes + * @returns {Uint8Array} A Uint8Array containing the fingerprint + */ + getFingerprintBytes() { + return this.fingerprint; + } + + /** + * Calculates and returns the fingerprint of the key, as a string + * @returns {String} A string containing the fingerprint in lowercase hex + */ + getFingerprint() { + return util.uint8ArrayToHex(this.getFingerprintBytes()); + } + + /** + * Calculates whether two keys have the same fingerprint without actually calculating the fingerprint + * @returns {Boolean} Whether the two keys have the same version and public key data. + */ + hasSameFingerprintAs(other) { + return this.version === other.version && util.equalsUint8Array(this.writePublicKey(), other.writePublicKey()); + } + + /** + * Returns algorithm information + * @returns {Object} An object of the form {algorithm: String, bits:int, curve:String}. + */ + getAlgorithmInfo() { + const result = {}; + result.algorithm = enums.read(enums.publicKey, this.algorithm); + // RSA, DSA or ElGamal public modulo + const modulo = this.publicParams.n || this.publicParams.p; + if (modulo) { + result.bits = util.uint8ArrayBitLength(modulo); + } else { + result.curve = this.publicParams.oid.getName(); + } + return result; + } } -const zeroBlock = new Uint8Array(blockLength); -const one = new Uint8Array([1]); +/** + * Alias of read() + * @see PublicKeyPacket#read + */ +PublicKeyPacket.prototype.readPublicKey = PublicKeyPacket.prototype.read; /** - * Class to en/decrypt using OCB mode. - * @param {String} cipher The symmetric cipher algorithm to use e.g. 'aes128' - * @param {Uint8Array} key The encryption key + * Alias of write() + * @see PublicKeyPacket#write */ -async function OCB(cipher, key) { +PublicKeyPacket.prototype.writePublicKey = PublicKeyPacket.prototype.write; - let maxNtz = 0; - let encipher; - let decipher; - let mask; +// GPG4Browsers - An OpenPGP implementation in javascript - constructKeyVariables(cipher, key); +// A SE packet can contain the following packet types +const allowedPackets$3 = /*#__PURE__*/ util.constructAllowedPackets([ + LiteralDataPacket, + CompressedDataPacket, + OnePassSignaturePacket, + SignaturePacket +]); - function constructKeyVariables(cipher, key) { - const aes = new _cipher2.default[cipher](key); - encipher = aes.encrypt.bind(aes); - decipher = aes.decrypt.bind(aes); +/** + * Implementation of the Symmetrically Encrypted Data Packet (Tag 9) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.7|RFC4880 5.7}: + * The Symmetrically Encrypted Data packet contains data encrypted with a + * symmetric-key algorithm. When it has been decrypted, it contains other + * packets (usually a literal data packet or compressed data packet, but in + * theory other Symmetrically Encrypted Data packets or sequences of packets + * that form whole OpenPGP messages). + */ +class SymmetricallyEncryptedDataPacket { + static get tag() { + return enums.packet.symmetricallyEncryptedData; + } - const mask_x = encipher(zeroBlock); - const mask_$ = _util2.default.double(mask_x); - mask = []; - mask[0] = _util2.default.double(mask_$); + constructor() { + /** + * Encrypted secret-key data + */ + this.encrypted = null; + /** + * Decrypted packets contained within. + * @type {PacketList} + */ + this.packets = null; + } - mask.x = mask_x; - mask.$ = mask_$; + read(bytes) { + this.encrypted = bytes; } - function extendKeyVariables(text, adata) { - const newMaxNtz = _util2.default.nbits(Math.max(text.length, adata.length) / blockLength | 0) - 1; - for (let i = maxNtz + 1; i <= newMaxNtz; i++) { - mask[i] = _util2.default.double(mask[i - 1]); - } - maxNtz = newMaxNtz; + write() { + return this.encrypted; } - function hash(adata) { - if (!adata.length) { - // Fast path - return zeroBlock; + /** + * Decrypt the symmetrically-encrypted packet data + * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. + * @param {module:enums.symmetric} sessionKeyAlgorithm - Symmetric key algorithm to use + * @param {Uint8Array} key - The key of cipher blocksize length to be used + * @param {Object} [config] - Full configuration, defaults to openpgp.config + + * @throws {Error} if decryption was not successful + * @async + */ + async decrypt(sessionKeyAlgorithm, key, config = defaultConfig) { + // If MDC errors are not being ignored, all missing MDC packets in symmetrically encrypted data should throw an error + if (!config.allowUnauthenticatedMessages) { + throw new Error('Message is not authenticated.'); } - // - // Consider A as a sequence of 128-bit blocks - // - const m = adata.length / blockLength | 0; + const { blockSize } = mod.getCipher(sessionKeyAlgorithm); + const encrypted = await readToEnd(clone(this.encrypted)); + const decrypted = await mod.mode.cfb.decrypt(sessionKeyAlgorithm, key, + encrypted.subarray(blockSize + 2), + encrypted.subarray(2, blockSize + 2) + ); - const offset = new Uint8Array(blockLength); - const sum = new Uint8Array(blockLength); - for (let i = 0; i < m; i++) { - xorMut(offset, mask[ntz(i + 1)]); - xorMut(sum, encipher(xor(offset, adata))); - adata = adata.subarray(blockLength); - } + this.packets = await PacketList.fromBinary(decrypted, allowedPackets$3, config); + } - // - // Process any final partial block; compute final hash value - // - if (adata.length) { - xorMut(offset, mask.x); + /** + * Encrypt the symmetrically-encrypted packet data + * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. + * @param {module:enums.symmetric} sessionKeyAlgorithm - Symmetric key algorithm to use + * @param {Uint8Array} key - The key of cipher blocksize length to be used + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if encryption was not successful + * @async + */ + async encrypt(sessionKeyAlgorithm, key, config = defaultConfig) { + const data = this.packets.write(); + const { blockSize } = mod.getCipher(sessionKeyAlgorithm); - const cipherInput = new Uint8Array(blockLength); - cipherInput.set(adata, 0); - cipherInput[adata.length] = 0b10000000; - xorMut(cipherInput, offset); + const prefix = await mod.getPrefixRandom(sessionKeyAlgorithm); + const FRE = await mod.mode.cfb.encrypt(sessionKeyAlgorithm, key, prefix, new Uint8Array(blockSize), config); + const ciphertext = await mod.mode.cfb.encrypt(sessionKeyAlgorithm, key, data, FRE.subarray(2), config); + this.encrypted = util.concat([FRE, ciphertext]); + } +} - xorMut(sum, encipher(cipherInput)); - } +// GPG4Browsers - An OpenPGP implementation in javascript - return sum; +/** + * Implementation of the strange "Marker packet" (Tag 10) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.8|RFC4880 5.8}: + * An experimental version of PGP used this packet as the Literal + * packet, but no released version of PGP generated Literal packets with this + * tag. With PGP 5.x, this packet has been reassigned and is reserved for use as + * the Marker packet. + * + * The body of this packet consists of: + * The three octets 0x50, 0x47, 0x50 (which spell "PGP" in UTF-8). + * + * Such a packet MUST be ignored when received. It may be placed at the + * beginning of a message that uses features not available in PGP + * version 2.6 in order to cause that version to report that newer + * software is necessary to process the message. + */ +class MarkerPacket { + static get tag() { + return enums.packet.marker; } /** - * Encrypt/decrypt data. - * @param {encipher|decipher} fn Encryption/decryption block cipher function - * @param {Uint8Array} text The cleartext or ciphertext (without tag) input - * @param {Uint8Array} nonce The nonce (15 bytes) - * @param {Uint8Array} adata Associated data to sign - * @returns {Promise} The ciphertext or plaintext output, with tag appended in both cases + * Parsing function for a marker data packet (tag 10). + * @param {Uint8Array} bytes - Payload of a tag 10 packet + * @returns {Boolean} whether the packet payload contains "PGP" */ - function crypt(fn, text, nonce, adata) { - // - // Consider P as a sequence of 128-bit blocks - // - const m = text.length / blockLength | 0; + read(bytes) { + if (bytes[0] === 0x50 && // P + bytes[1] === 0x47 && // G + bytes[2] === 0x50) { // P + return true; + } + return false; + } - // - // Key-dependent variables - // - extendKeyVariables(text, adata); + write() { + return new Uint8Array([0x50, 0x47, 0x50]); + } +} - // - // Nonce-dependent and per-encryption variables - // - // Nonce = num2str(TAGLEN mod 128,7) || zeros(120-bitlen(N)) || 1 || N - // Note: We assume here that tagLength mod 16 == 0. - const paddedNonce = _util2.default.concatUint8Array([zeroBlock.subarray(0, ivLength - nonce.length), one, nonce]); - // bottom = str2num(Nonce[123..128]) - const bottom = paddedNonce[blockLength - 1] & 0b111111; - // Ktop = ENCIPHER(K, Nonce[1..122] || zeros(6)) - paddedNonce[blockLength - 1] &= 0b11000000; - const kTop = encipher(paddedNonce); - // Stretch = Ktop || (Ktop[1..64] xor Ktop[9..72]) - const stretched = _util2.default.concatUint8Array([kTop, xor(kTop.subarray(0, 8), kTop.subarray(1, 9))]); - // Offset_0 = Stretch[1+bottom..128+bottom] - const offset = _util2.default.shiftRight(stretched.subarray(0 + (bottom >> 3), 17 + (bottom >> 3)), 8 - (bottom & 7)).subarray(1); - // Checksum_0 = zeros(128) - const checksum = new Uint8Array(blockLength); +// GPG4Browsers - An OpenPGP implementation in javascript - const ct = new Uint8Array(text.length + tagLength); +/** + * A Public-Subkey packet (tag 14) has exactly the same format as a + * Public-Key packet, but denotes a subkey. One or more subkeys may be + * associated with a top-level key. By convention, the top-level key + * provides signature services, and the subkeys provide encryption + * services. + * @extends PublicKeyPacket + */ +class PublicSubkeyPacket extends PublicKeyPacket { + static get tag() { + return enums.packet.publicSubkey; + } - // - // Process any whole blocks - // - let i; - let pos = 0; - for (i = 0; i < m; i++) { - // Offset_i = Offset_{i-1} xor L_{ntz(i)} - xorMut(offset, mask[ntz(i + 1)]); - // C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) - // P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i) - ct.set(xorMut(fn(xor(offset, text)), offset), pos); - // Checksum_i = Checksum_{i-1} xor P_i - xorMut(checksum, fn === encipher ? text : ct.subarray(pos)); + /** + * @param {Date} [date] - Creation date + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + // eslint-disable-next-line no-useless-constructor + constructor(date, config) { + super(date, config); + } - text = text.subarray(blockLength); - pos += blockLength; - } + /** + * Create a PublicSubkeyPacket from a SecretSubkeyPacket + * @param {SecretSubkeyPacket} secretSubkeyPacket - subkey packet to convert + * @returns {SecretSubkeyPacket} public key packet + * @static + */ + static fromSecretSubkeyPacket(secretSubkeyPacket) { + const keyPacket = new PublicSubkeyPacket(); + const { version, created, algorithm, publicParams, keyID, fingerprint } = secretSubkeyPacket; + keyPacket.version = version; + keyPacket.created = created; + keyPacket.algorithm = algorithm; + keyPacket.publicParams = publicParams; + keyPacket.keyID = keyID; + keyPacket.fingerprint = fingerprint; + return keyPacket; + } +} - // - // Process any final partial block and compute raw tag - // - if (text.length) { - // Offset_* = Offset_m xor L_* - xorMut(offset, mask.x); - // Pad = ENCIPHER(K, Offset_*) - const padding = encipher(offset); - // C_* = P_* xor Pad[1..bitlen(P_*)] - ct.set(xor(text, padding), pos); +// GPG4Browsers - An OpenPGP implementation in javascript - // Checksum_* = Checksum_m xor (P_* || 1 || new Uint8Array(127-bitlen(P_*))) - const xorInput = new Uint8Array(blockLength); - xorInput.set(fn === encipher ? text : ct.subarray(pos, -tagLength), 0); - xorInput[text.length] = 0b10000000; - xorMut(checksum, xorInput); - pos += text.length; - } - // Tag = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) xor HASH(K,A) - const tag = xorMut(encipher(xorMut(xorMut(checksum, offset), mask.$)), hash(adata)); +/** + * Implementation of the User Attribute Packet (Tag 17) + * + * The User Attribute packet is a variation of the User ID packet. It + * is capable of storing more types of data than the User ID packet, + * which is limited to text. Like the User ID packet, a User Attribute + * packet may be certified by the key owner ("self-signed") or any other + * key owner who cares to certify it. Except as noted, a User Attribute + * packet may be used anywhere that a User ID packet may be used. + * + * While User Attribute packets are not a required part of the OpenPGP + * standard, implementations SHOULD provide at least enough + * compatibility to properly handle a certification signature on the + * User Attribute packet. A simple way to do this is by treating the + * User Attribute packet as a User ID packet with opaque contents, but + * an implementation may use any method desired. + */ +class UserAttributePacket { + static get tag() { + return enums.packet.userAttribute; + } - // - // Assemble ciphertext - // - // C = C_1 || C_2 || ... || C_m || C_* || Tag[1..TAGLEN] - ct.set(tag, pos); - return ct; + constructor() { + this.attributes = []; } - return { - /** - * Encrypt plaintext input. - * @param {Uint8Array} plaintext The cleartext input to be encrypted - * @param {Uint8Array} nonce The nonce (15 bytes) - * @param {Uint8Array} adata Associated data to sign - * @returns {Promise} The ciphertext output - */ - encrypt: async function encrypt(plaintext, nonce, adata) { - return crypt(encipher, plaintext, nonce, adata); - }, + /** + * parsing function for a user attribute packet (tag 17). + * @param {Uint8Array} input - Payload of a tag 17 packet + */ + read(bytes) { + let i = 0; + while (i < bytes.length) { + const len = readSimpleLength(bytes.subarray(i, bytes.length)); + i += len.offset; - /** - * Decrypt ciphertext input. - * @param {Uint8Array} ciphertext The ciphertext input to be decrypted - * @param {Uint8Array} nonce The nonce (15 bytes) - * @param {Uint8Array} adata Associated data to sign - * @returns {Promise} The ciphertext output - */ - decrypt: async function decrypt(ciphertext, nonce, adata) { - if (ciphertext.length < tagLength) throw new Error('Invalid OCB ciphertext'); + this.attributes.push(util.uint8ArrayToString(bytes.subarray(i, i + len.len))); + i += len.len; + } + } - const tag = ciphertext.subarray(-tagLength); - ciphertext = ciphertext.subarray(0, -tagLength); + /** + * Creates a binary representation of the user attribute packet + * @returns {Uint8Array} String representation. + */ + write() { + const arr = []; + for (let i = 0; i < this.attributes.length; i++) { + arr.push(writeSimpleLength(this.attributes[i].length)); + arr.push(util.stringToUint8Array(this.attributes[i])); + } + return util.concatUint8Array(arr); + } - const crypted = crypt(decipher, ciphertext, nonce, adata); - // if (Tag[1..TAGLEN] == T) - if (_util2.default.equalsUint8Array(tag, crypted.subarray(-tagLength))) { - return crypted.subarray(0, -tagLength); - } - throw new Error('Authentication tag mismatch'); + /** + * Compare for equality + * @param {UserAttributePacket} usrAttr + * @returns {Boolean} True if equal. + */ + equals(usrAttr) { + if (!usrAttr || !(usrAttr instanceof UserAttributePacket)) { + return false; } - }; + return this.attributes.every(function(attr, index) { + return attr === usrAttr.attributes[index]; + }); + } } +// GPG4Browsers - An OpenPGP implementation in javascript + /** - * Get OCB nonce as defined by {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.2|RFC4880bis-04, section 5.16.2}. - * @param {Uint8Array} iv The initialization vector (15 bytes) - * @param {Uint8Array} chunkIndex The chunk index (8 bytes) + * A Secret-Key packet contains all the information that is found in a + * Public-Key packet, including the public-key material, but also + * includes the secret-key material after all the public-key fields. + * @extends PublicKeyPacket */ -OCB.getNonce = function (iv, chunkIndex) { - const nonce = iv.slice(); - for (let i = 0; i < chunkIndex.length; i++) { - nonce[7 + i] ^= chunkIndex[i]; +class SecretKeyPacket extends PublicKeyPacket { + static get tag() { + return enums.packet.secretKey; } - return nonce; -}; - -OCB.blockLength = blockLength; -OCB.ivLength = ivLength; -OCB.tagLength = tagLength; - -exports.default = OCB; - -},{"../util":152,"./cipher":86}],96:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -var _random = require('./random'); + /** + * @param {Date} [date] - Creation date + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + constructor(date = new Date(), config = defaultConfig) { + super(date, config); + /** + * Secret-key data + */ + this.keyMaterial = null; + /** + * Indicates whether secret-key data is encrypted. `this.isEncrypted === false` means data is available in decrypted form. + */ + this.isEncrypted = null; + /** + * S2K usage + * @type {enums.symmetric} + */ + this.s2kUsage = 0; + /** + * S2K object + * @type {type/s2k} + */ + this.s2k = null; + /** + * Symmetric algorithm to encrypt the key with + * @type {enums.symmetric} + */ + this.symmetric = null; + /** + * AEAD algorithm to encrypt the key with (if AEAD protection is enabled) + * @type {enums.aead} + */ + this.aead = null; + /** + * Decrypted private parameters, referenced by name + * @type {Object} + */ + this.privateParams = null; + } -var _random2 = _interopRequireDefault(_random); + // 5.5.3. Secret-Key Packet Formats -var _hash = require('./hash'); + /** + * Internal parser for private keys as specified in + * {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.5.3|RFC4880bis-04 section 5.5.3} + * @param {Uint8Array} bytes - Input string to read the packet from + * @async + */ + async read(bytes) { + // - A Public-Key or Public-Subkey packet, as described above. + let i = await this.readPublicKey(bytes); + + // - One octet indicating string-to-key usage conventions. Zero + // indicates that the secret-key data is not encrypted. 255 or 254 + // indicates that a string-to-key specifier is being given. Any + // other value is a symmetric-key encryption algorithm identifier. + this.s2kUsage = bytes[i++]; + + // - Only for a version 5 packet, a one-octet scalar octet count of + // the next 4 optional fields. + if (this.version === 5) { + i++; + } -var _hash2 = _interopRequireDefault(_hash); + // - [Optional] If string-to-key usage octet was 255, 254, or 253, a + // one-octet symmetric encryption algorithm. + if (this.s2kUsage === 255 || this.s2kUsage === 254 || this.s2kUsage === 253) { + this.symmetric = bytes[i++]; -var _util = require('../util'); + // - [Optional] If string-to-key usage octet was 253, a one-octet + // AEAD algorithm. + if (this.s2kUsage === 253) { + this.aead = bytes[i++]; + } -var _util2 = _interopRequireDefault(_util); + // - [Optional] If string-to-key usage octet was 255, 254, or 253, a + // string-to-key specifier. The length of the string-to-key + // specifier is implied by its type, as described above. + this.s2k = new S2K(); + i += this.s2k.read(bytes.subarray(i, bytes.length)); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + if (this.s2k.type === 'gnu-dummy') { + return; + } + } else if (this.s2kUsage) { + this.symmetric = this.s2kUsage; + } -/** @namespace */ -const eme = {}; -/** @namespace */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + // - [Optional] If secret data is encrypted (string-to-key usage octet + // not zero), an Initial Vector (IV) of the same length as the + // cipher's block size. + if (this.s2kUsage) { + this.iv = bytes.subarray( + i, + i + mod.getCipher(this.symmetric).blockSize + ); -/** - * @fileoverview Provides EME-PKCS1-v1_5 encoding and decoding and EMSA-PKCS1-v1_5 encoding function - * @see module:crypto/public_key/rsa - * @see module:crypto/public_key/elliptic/ecdh - * @see module:packet.PublicKeyEncryptedSessionKey - * @requires crypto/random - * @requires crypto/hash - * @requires util - * @module crypto/pkcs1 - */ + i += this.iv.length; + } -const emsa = {}; + // - Only for a version 5 packet, a four-octet scalar octet count for + // the following key material. + if (this.version === 5) { + i += 4; + } -/** - * ASN1 object identifiers for hashes - * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.2} - */ -const hash_headers = []; -hash_headers[1] = [0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10]; -hash_headers[2] = [0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14]; -hash_headers[3] = [0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14]; -hash_headers[8] = [0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20]; -hash_headers[9] = [0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30]; -hash_headers[10] = [0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40]; -hash_headers[11] = [0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1C]; + // - Plain or encrypted multiprecision integers comprising the secret + // key data. These algorithm-specific fields are as described + // below. + this.keyMaterial = bytes.subarray(i); + this.isEncrypted = !!this.s2kUsage; -/** - * Create padding with secure random data - * @private - * @param {Integer} length Length of the padding in bytes - * @returns {String} Padding as string - * @async - */ -async function getPkcs1Padding(length) { - let result = ''; - while (result.length < length) { - const randomBytes = await _random2.default.getRandomBytes(length - result.length); - for (let i = 0; i < randomBytes.length; i++) { - if (randomBytes[i] !== 0) { - result += String.fromCharCode(randomBytes[i]); + if (!this.isEncrypted) { + const cleartext = this.keyMaterial.subarray(0, -2); + if (!util.equalsUint8Array(util.writeChecksum(cleartext), this.keyMaterial.subarray(-2))) { + throw new Error('Key checksum mismatch'); + } + try { + const { privateParams } = mod.parsePrivateKeyParams(this.algorithm, cleartext, this.publicParams); + this.privateParams = privateParams; + } catch (err) { + throw new Error('Error reading MPIs'); } } } - return result; -} - -/** - * Create a EME-PKCS1-v1_5 padded message - * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.1|RFC 4880 13.1.1} - * @param {String} M message to be encoded - * @param {Integer} k the length in octets of the key modulus - * @returns {Promise} EME-PKCS1 padded message - * @async - */ -eme.encode = async function (M, k) { - const mLen = M.length; - // length checking - if (mLen > k - 11) { - throw new Error('Message too long'); - } - // Generate an octet string PS of length k - mLen - 3 consisting of - // pseudo-randomly generated nonzero octets - const PS = await getPkcs1Padding(k - mLen - 3); - // Concatenate PS, the message M, and other padding to form an - // encoded message EM of length k octets as EM = 0x00 || 0x02 || PS || 0x00 || M. - return String.fromCharCode(0) + String.fromCharCode(2) + PS + String.fromCharCode(0) + M; -}; - -/** - * Decode a EME-PKCS1-v1_5 padded message - * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.2|RFC 4880 13.1.2} - * @param {String} EM encoded message, an octet string - * @returns {String} message, an octet string - */ -eme.decode = function (EM) { - // leading zeros truncated by bn.js - if (EM.charCodeAt(0) !== 0) { - EM = String.fromCharCode(0) + EM; - } - const firstOct = EM.charCodeAt(0); - const secondOct = EM.charCodeAt(1); - let i = 2; - while (EM.charCodeAt(i) !== 0 && i < EM.length) { - i++; - } - const psLen = i - 2; - const separator = EM.charCodeAt(i++); - if (firstOct === 0 && secondOct === 2 && psLen >= 8 && separator === 0) { - return EM.substr(i); - } - throw new Error('Decryption error'); -}; - -/** - * Create a EMSA-PKCS1-v1_5 padded message - * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.3|RFC 4880 13.1.3} - * @param {Integer} algo Hash algorithm type used - * @param {Uint8Array} hashed message to be encoded - * @param {Integer} emLen intended length in octets of the encoded message - * @returns {String} encoded message - */ -emsa.encode = async function (algo, hashed, emLen) { - let i; - const H = _util2.default.Uint8Array_to_str(hashed); - if (H.length !== _hash2.default.getHashByteLength(algo)) { - throw new Error('Invalid hash length'); - } - // produce an ASN.1 DER value for the hash function used. - // Let T be the full hash prefix - let T = ''; - for (i = 0; i < hash_headers[algo].length; i++) { - T += String.fromCharCode(hash_headers[algo][i]); - } - // add hash value to prefix - T += H; - // and let tLen be the length in octets of T - const tLen = T.length; - if (emLen < tLen + 11) { - throw new Error('Intended encoded message length too short'); - } - // an octet string PS consisting of emLen - tLen - 3 octets with hexadecimal value 0xFF - // The length of PS will be at least 8 octets - let PS = ''; - for (i = 0; i < emLen - tLen - 3; i++) { - PS += String.fromCharCode(0xff); - } - // Concatenate PS, the hash prefix T, and other padding to form the - // encoded message EM as EM = 0x00 || 0x01 || PS || 0x00 || T. - const EM = String.fromCharCode(0x00) + String.fromCharCode(0x01) + PS + String.fromCharCode(0x00) + T; - return _util2.default.str_to_hex(EM); -}; -exports.default = { eme, emsa }; + /** + * Creates an OpenPGP key packet for the given key. + * @returns {Uint8Array} A string of bytes containing the secret key OpenPGP packet. + */ + write() { + const arr = [this.writePublicKey()]; -},{"../util":152,"./hash":92,"./random":109}],97:[function(require,module,exports){ -'use strict'; + arr.push(new Uint8Array([this.s2kUsage])); -Object.defineProperty(exports, "__esModule", { - value: true -}); -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2015-2016 Decentral -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + const optionalFieldsArr = []; + // - [Optional] If string-to-key usage octet was 255, 254, or 253, a + // one- octet symmetric encryption algorithm. + if (this.s2kUsage === 255 || this.s2kUsage === 254 || this.s2kUsage === 253) { + optionalFieldsArr.push(this.symmetric); -/** - * @fileoverview Functions to add and remove PKCS5 padding - * @see module:packet.PublicKeyEncryptedSessionKey - * @module crypto/pkcs5 - */ + // - [Optional] If string-to-key usage octet was 253, a one-octet + // AEAD algorithm. + if (this.s2kUsage === 253) { + optionalFieldsArr.push(this.aead); + } -/** - * Add pkcs5 padding to a text. - * @param {String} msg Text to add padding - * @returns {String} Text with padding added - */ -function encode(msg) { - const c = 8 - msg.length % 8; - const padding = String.fromCharCode(c).repeat(c); - return msg + padding; -} + // - [Optional] If string-to-key usage octet was 255, 254, or 253, a + // string-to-key specifier. The length of the string-to-key + // specifier is implied by its type, as described above. + optionalFieldsArr.push(...this.s2k.write()); + } -/** - * Remove pkcs5 padding from a string. - * @param {String} msg Text to remove padding from - * @returns {String} Text with padding removed - */ -function decode(msg) { - const len = msg.length; - if (len > 0) { - const c = msg.charCodeAt(len - 1); - if (c >= 1 && c <= 8) { - const provided = msg.substr(len - c); - const computed = String.fromCharCode(c).repeat(c); - if (provided === computed) { - return msg.substr(0, len - c); - } + // - [Optional] If secret data is encrypted (string-to-key usage octet + // not zero), an Initial Vector (IV) of the same length as the + // cipher's block size. + if (this.s2kUsage && this.s2k.type !== 'gnu-dummy') { + optionalFieldsArr.push(...this.iv); } - } - throw new Error('Invalid padding'); -} -exports.default = { encode, decode }; + if (this.version === 5) { + arr.push(new Uint8Array([optionalFieldsArr.length])); + } + arr.push(new Uint8Array(optionalFieldsArr)); -},{}],98:[function(require,module,exports){ -'use strict'; + if (!this.isDummy()) { + if (!this.s2kUsage) { + this.keyMaterial = mod.serializeParams(this.algorithm, this.privateParams); + } -Object.defineProperty(exports, "__esModule", { - value: true -}); + if (this.version === 5) { + arr.push(util.writeNumber(this.keyMaterial.length, 4)); + } + arr.push(this.keyMaterial); -var _bn = require('bn.js'); + if (!this.s2kUsage) { + arr.push(util.writeChecksum(this.keyMaterial)); + } + } -var _bn2 = _interopRequireDefault(_bn); + return util.concatUint8Array(arr); + } -var _random = require('../random'); + /** + * Check whether secret-key data is available in decrypted form. + * Returns false for gnu-dummy keys and null for public keys. + * @returns {Boolean|null} + */ + isDecrypted() { + return this.isEncrypted === false; + } -var _random2 = _interopRequireDefault(_random); + /** + * Check whether this is a gnu-dummy key + * @returns {Boolean} + */ + isDummy() { + return !!(this.s2k && this.s2k.type === 'gnu-dummy'); + } -var _util = require('../../util'); + /** + * Remove private key material, converting the key to a dummy one. + * The resulting key cannot be used for signing/decrypting but can still verify signatures. + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + makeDummy(config = defaultConfig) { + if (this.isDummy()) { + return; + } + if (this.isDecrypted()) { + this.clearPrivateParams(); + } + this.isEncrypted = null; + this.keyMaterial = null; + this.s2k = new S2K(config); + this.s2k.algorithm = 0; + this.s2k.c = 0; + this.s2k.type = 'gnu-dummy'; + this.s2kUsage = 254; + this.symmetric = enums.symmetric.aes256; + } -var _util2 = _interopRequireDefault(_util); + /** + * Encrypt the payload. By default, we use aes256 and iterated, salted string + * to key specifier. If the key is in a decrypted state (isEncrypted === false) + * and the passphrase is empty or undefined, the key will be set as not encrypted. + * This can be used to remove passphrase protection after calling decrypt(). + * @param {String} passphrase + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if encryption was not successful + * @async + */ + async encrypt(passphrase, config = defaultConfig) { + if (this.isDummy()) { + return; + } -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + if (!this.isDecrypted()) { + throw new Error('Key packet is already encrypted'); + } -const one = new _bn2.default(1); // GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + if (this.isDecrypted() && !passphrase) { + this.s2kUsage = 0; + return; + } else if (!passphrase) { + throw new Error('The key must be decrypted before removing passphrase protection.'); + } -/** - * @fileoverview A Digital signature algorithm implementation - * @requires bn.js - * @requires crypto/random - * @requires util - * @module crypto/public_key/dsa - */ + this.s2k = new S2K(config); + this.s2k.salt = await mod.random.getRandomBytes(8); + const cleartext = mod.serializeParams(this.algorithm, this.privateParams); + this.symmetric = enums.symmetric.aes256; + const key = await produceEncryptionKey(this.s2k, passphrase, this.symmetric); -const zero = new _bn2.default(0); + const { blockSize } = mod.getCipher(this.symmetric); + this.iv = await mod.random.getRandomBytes(blockSize); -/* - TODO regarding the hash function, read: - https://tools.ietf.org/html/rfc4880#section-13.6 - https://tools.ietf.org/html/rfc4880#section-14 -*/ + if (config.aeadProtect) { + this.s2kUsage = 253; + this.aead = enums.aead.eax; + const mode = mod.getAEADMode(this.aead); + const modeInstance = await mode(this.symmetric, key); + this.keyMaterial = await modeInstance.encrypt(cleartext, this.iv.subarray(0, mode.ivLength), new Uint8Array()); + } else { + this.s2kUsage = 254; + this.keyMaterial = await mod.mode.cfb.encrypt(this.symmetric, key, util.concatUint8Array([ + cleartext, + await mod.hash.sha1(cleartext, config) + ]), this.iv, config); + } + } -exports.default = { /** - * DSA Sign function - * @param {Integer} hash_algo - * @param {Uint8Array} hashed - * @param {BN} g - * @param {BN} p - * @param {BN} q - * @param {BN} x - * @returns {{ r: BN, s: BN }} + * Decrypts the private key params which are needed to use the key. + * Successful decryption does not imply key integrity, call validate() to confirm that. + * {@link SecretKeyPacket.isDecrypted} should be false, as + * otherwise calls to this function will throw an error. + * @param {String} passphrase - The passphrase for this private key as string + * @throws {Error} if the key is already decrypted, or if decryption was not successful * @async */ - sign: async function sign(hash_algo, hashed, g, p, q, x) { - let k; - let r; - let s; - let t; - const redp = new _bn2.default.red(p); - const redq = new _bn2.default.red(q); - const gred = g.toRed(redp); - const xred = x.toRed(redq); - // If the output size of the chosen hash is larger than the number of - // bits of q, the hash result is truncated to fit by taking the number - // of leftmost bits equal to the number of bits of q. This (possibly - // truncated) hash function result is treated as a number and used - // directly in the DSA signature algorithm. - const h = new _bn2.default(hashed.subarray(0, q.byteLength())).toRed(redq); - // FIPS-186-4, section 4.6: - // The values of r and s shall be checked to determine if r = 0 or s = 0. - // If either r = 0 or s = 0, a new value of k shall be generated, and the - // signature shall be recalculated. It is extremely unlikely that r = 0 - // or s = 0 if signatures are generated properly. - while (true) { - // See Appendix B here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - k = await _random2.default.getRandomBN(one, q); // returns in [1, q-1] - r = gred.redPow(k).fromRed().toRed(redq); // (g**k mod p) mod q - if (zero.cmp(r) === 0) { - continue; + async decrypt(passphrase) { + if (this.isDummy()) { + return false; + } + + if (this.isDecrypted()) { + throw new Error('Key packet is already decrypted.'); + } + + let key; + if (this.s2kUsage === 254 || this.s2kUsage === 253) { + key = await produceEncryptionKey(this.s2k, passphrase, this.symmetric); + } else if (this.s2kUsage === 255) { + throw new Error('Encrypted private key is authenticated using an insecure two-byte hash'); + } else { + throw new Error('Private key is encrypted using an insecure S2K function: unsalted MD5'); + } + + let cleartext; + if (this.s2kUsage === 253) { + const mode = mod.getAEADMode(this.aead); + const modeInstance = await mode(this.symmetric, key); + try { + cleartext = await modeInstance.decrypt(this.keyMaterial, this.iv.subarray(0, mode.ivLength), new Uint8Array()); + } catch (err) { + if (err.message === 'Authentication tag mismatch') { + throw new Error('Incorrect key passphrase: ' + err.message); + } + throw err; } - t = h.redAdd(xred.redMul(r)); // H(m) + x*r mod q - s = k.toRed(redq).redInvm().redMul(t); // k**-1 * (H(m) + x*r) mod q - if (zero.cmp(s) === 0) { - continue; + } else { + const cleartextWithHash = await mod.mode.cfb.decrypt(this.symmetric, key, this.keyMaterial, this.iv); + + cleartext = cleartextWithHash.subarray(0, -20); + const hash = await mod.hash.sha1(cleartext); + + if (!util.equalsUint8Array(hash, cleartextWithHash.subarray(-20))) { + throw new Error('Incorrect key passphrase'); } - break; } - return { - r: r.toArrayLike(Uint8Array, 'be', q.byteLength()), - s: s.toArrayLike(Uint8Array, 'be', q.byteLength()) - }; - }, + + try { + const { privateParams } = mod.parsePrivateKeyParams(this.algorithm, cleartext, this.publicParams); + this.privateParams = privateParams; + } catch (err) { + throw new Error('Error reading MPIs'); + } + this.isEncrypted = false; + this.keyMaterial = null; + this.s2kUsage = 0; + } /** - * DSA Verify function - * @param {Integer} hash_algo - * @param {BN} r - * @param {BN} s - * @param {Uint8Array} hashed - * @param {BN} g - * @param {BN} p - * @param {BN} q - * @param {BN} y - * @returns BN + * Checks that the key parameters are consistent + * @throws {Error} if validation was not successful * @async */ - verify: async function verify(hash_algo, r, s, hashed, g, p, q, y) { - if (zero.ucmp(r) >= 0 || r.ucmp(q) >= 0 || zero.ucmp(s) >= 0 || s.ucmp(q) >= 0) { - _util2.default.print_debug("invalid DSA Signature"); - return null; - } - const redp = new _bn2.default.red(p); - const redq = new _bn2.default.red(q); - const h = new _bn2.default(hashed.subarray(0, q.byteLength())); - const w = s.toRed(redq).redInvm(); // s**-1 mod q - if (zero.cmp(w) === 0) { - _util2.default.print_debug("invalid DSA Signature"); - return null; + async validate() { + if (this.isDummy()) { + return; } - const u1 = h.toRed(redq).redMul(w); // H(m) * w mod q - const u2 = r.toRed(redq).redMul(w); // r * w mod q - const t1 = g.toRed(redp).redPow(u1.fromRed()); // g**u1 mod p - const t2 = y.toRed(redp).redPow(u2.fromRed()); // y**u2 mod p - const v = t1.redMul(t2).fromRed().mod(q); // (g**u1 * y**u2 mod p) mod q - return v.cmp(r) === 0; - } -}; - -},{"../../util":152,"../random":109,"bn.js":16}],99:[function(require,module,exports){ -'use strict'; -Object.defineProperty(exports, "__esModule", { - value: true -}); + if (!this.isDecrypted()) { + throw new Error('Key is not decrypted'); + } -var _bn = require('bn.js'); + let validParams; + try { + // this can throw if some parameters are undefined + validParams = await mod.validateParams(this.algorithm, this.publicParams, this.privateParams); + } catch (_) { + validParams = false; + } + if (!validParams) { + throw new Error('Key is invalid'); + } + } -var _bn2 = _interopRequireDefault(_bn); + async generate(bits, curve) { + const { privateParams, publicParams } = await mod.generateParams(this.algorithm, bits, curve); + this.privateParams = privateParams; + this.publicParams = publicParams; + this.isEncrypted = false; + } -var _random = require('../random'); + /** + * Clear private key parameters + */ + clearPrivateParams() { + if (this.isDummy()) { + return; + } -var _random2 = _interopRequireDefault(_random); + Object.keys(this.privateParams).forEach(name => { + const param = this.privateParams[name]; + param.fill(0); + delete this.privateParams[name]; + }); + this.privateParams = null; + this.isEncrypted = true; + } +} -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +async function produceEncryptionKey(s2k, passphrase, algorithm) { + const { keySize } = mod.getCipher(algorithm); + return s2k.produceKey(passphrase, keySize); +} -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH +var emailAddresses = createCommonjsModule(function (module) { +// email-addresses.js - RFC 5322 email address parser +// v 3.1.0 // -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. +// http://tools.ietf.org/html/rfc5322 // -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. +// This library does not validate email addresses. +// emailAddresses attempts to parse addresses using the (fairly liberal) +// grammar specified in RFC 5322. // -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @fileoverview ElGamal implementation - * @requires bn.js - * @requires crypto/random - * @module crypto/public_key/elgamal - */ +// email-addresses returns { +// ast: , +// addresses: [{ +// node: , +// name: , +// address: , +// local: , +// domain: +// }, ...] +// } +// +// emailAddresses.parseOneAddress and emailAddresses.parseAddressList +// work as you might expect. Try it out. +// +// Many thanks to Dominic Sayers and his documentation on the is_email function, +// http://code.google.com/p/isemail/ , which helped greatly in writing this parser. -const zero = new _bn2.default(0); +(function (global) { -exports.default = { - /** - * ElGamal Encryption function - * @param {BN} m - * @param {BN} p - * @param {BN} g - * @param {BN} y - * @returns {{ c1: BN, c2: BN }} - * @async - */ - encrypt: async function encrypt(m, p, g, y) { - const redp = new _bn2.default.red(p); - const mred = m.toRed(redp); - const gred = g.toRed(redp); - const yred = y.toRed(redp); - // See Section 11.5 here: https://crypto.stanford.edu/~dabo/cryptobook/BonehShoup_0_4.pdf - const k = await _random2.default.getRandomBN(zero, p); // returns in [0, p-1] - return { - c1: gred.redPow(k).fromRed(), - c2: yred.redPow(k).redMul(mred).fromRed() - }; - }, +function parse5322(opts) { - /** - * ElGamal Encryption function - * @param {BN} c1 - * @param {BN} c2 - * @param {BN} p - * @param {BN} x - * @returns BN - * @async - */ - decrypt: async function decrypt(c1, c2, p, x) { - const redp = new _bn2.default.red(p); - const c1red = c1.toRed(redp); - const c2red = c2.toRed(redp); - return c1red.redPow(x).redInvm().redMul(c2red).fromRed(); - } -}; + // tokenizing functions -},{"../random":109,"bn.js":16}],100:[function(require,module,exports){ -'use strict'; + function inStr() { return pos < len; } + function curTok() { return parseString[pos]; } + function getPos() { return pos; } + function setPos(i) { pos = i; } + function nextTok() { pos += 1; } + function initialize() { + pos = 0; + len = parseString.length; + } -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getPreferredHashAlgo = exports.generate = exports.nodeCurves = exports.webCurves = exports.curves = undefined; + // parser helper functions -var _bn = require('bn.js'); + function o(name, value) { + return { + name: name, + tokens: value || "", + semantic: value || "", + children: [] + }; + } -var _bn2 = _interopRequireDefault(_bn); + function wrap(name, ast) { + var n; + if (ast === null) { return null; } + n = o(name); + n.tokens = ast.tokens; + n.semantic = ast.semantic; + n.children.push(ast); + return n; + } -var _elliptic = require('elliptic'); + function add(parent, child) { + if (child !== null) { + parent.tokens += child.tokens; + parent.semantic += child.semantic; + } + parent.children.push(child); + return parent; + } -var _key = require('./key'); + function compareToken(fxnCompare) { + var tok; + if (!inStr()) { return null; } + tok = curTok(); + if (fxnCompare(tok)) { + nextTok(); + return o('token', tok); + } + return null; + } -var _key2 = _interopRequireDefault(_key); + function literal(lit) { + return function literalFunc() { + return wrap('literal', compareToken(function (tok) { + return tok === lit; + })); + }; + } -var _random = require('../../random'); + function and() { + var args = arguments; + return function andFunc() { + var i, s, result, start; + start = getPos(); + s = o('and'); + for (i = 0; i < args.length; i += 1) { + result = args[i](); + if (result === null) { + setPos(start); + return null; + } + add(s, result); + } + return s; + }; + } -var _random2 = _interopRequireDefault(_random); + function or() { + var args = arguments; + return function orFunc() { + var i, result, start; + start = getPos(); + for (i = 0; i < args.length; i += 1) { + result = args[i](); + if (result !== null) { + return result; + } + setPos(start); + } + return null; + }; + } -var _enums = require('../../../enums'); + function opt(prod) { + return function optFunc() { + var result, start; + start = getPos(); + result = prod(); + if (result !== null) { + return result; + } + else { + setPos(start); + return o('opt'); + } + }; + } -var _enums2 = _interopRequireDefault(_enums); + function invis(prod) { + return function invisFunc() { + var result = prod(); + if (result !== null) { + result.semantic = ""; + } + return result; + }; + } -var _util = require('../../../util'); + function colwsp(prod) { + return function collapseSemanticWhitespace() { + var result = prod(); + if (result !== null && result.semantic.length > 0) { + result.semantic = " "; + } + return result; + }; + } -var _util2 = _interopRequireDefault(_util); + function star(prod, minimum) { + return function starFunc() { + var s, result, count, start, min; + start = getPos(); + s = o('star'); + count = 0; + min = minimum === undefined ? 0 : minimum; + while ((result = prod()) !== null) { + count = count + 1; + add(s, result); + } + if (count >= min) { + return s; + } + else { + setPos(start); + return null; + } + }; + } -var _oid = require('../../../type/oid'); + // One expects names to get normalized like this: + // " First Last " -> "First Last" + // "First Last" -> "First Last" + // "First Last" -> "First Last" + function collapseWhitespace(s) { + return s.replace(/([ \t]|\r\n)+/g, ' ').replace(/^\s*/, '').replace(/\s*$/, ''); + } -var _oid2 = _interopRequireDefault(_oid); + // UTF-8 pseudo-production (RFC 6532) + // RFC 6532 extends RFC 5322 productions to include UTF-8 + // using the following productions: + // UTF8-non-ascii = UTF8-2 / UTF8-3 / UTF8-4 + // UTF8-2 = + // UTF8-3 = + // UTF8-4 = + // + // For reference, the extended RFC 5322 productions are: + // VCHAR =/ UTF8-non-ascii + // ctext =/ UTF8-non-ascii + // atext =/ UTF8-non-ascii + // qtext =/ UTF8-non-ascii + // dtext =/ UTF8-non-ascii + function isUTF8NonAscii(tok) { + // In JavaScript, we just deal directly with Unicode code points, + // so we aren't checking individual bytes for UTF-8 encoding. + // Just check that the character is non-ascii. + return tok.charCodeAt(0) >= 128; + } + + + // common productions (RFC 5234) + // http://tools.ietf.org/html/rfc5234 + // B.1. Core Rules + + // CR = %x0D + // ; carriage return + function cr() { return wrap('cr', literal('\r')()); } + + // CRLF = CR LF + // ; Internet standard newline + function crlf() { return wrap('crlf', and(cr, lf)()); } + + // DQUOTE = %x22 + // ; " (Double Quote) + function dquote() { return wrap('dquote', literal('"')()); } + + // HTAB = %x09 + // ; horizontal tab + function htab() { return wrap('htab', literal('\t')()); } + + // LF = %x0A + // ; linefeed + function lf() { return wrap('lf', literal('\n')()); } + + // SP = %x20 + function sp() { return wrap('sp', literal(' ')()); } + + // VCHAR = %x21-7E + // ; visible (printing) characters + function vchar() { + return wrap('vchar', compareToken(function vcharFunc(tok) { + var code = tok.charCodeAt(0); + var accept = (0x21 <= code && code <= 0x7E); + if (opts.rfc6532) { + accept = accept || isUTF8NonAscii(tok); + } + return accept; + })); + } -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + // WSP = SP / HTAB + // ; white space + function wsp() { return wrap('wsp', or(sp, htab)()); } + + + // email productions (RFC 5322) + // http://tools.ietf.org/html/rfc5322 + // 3.2.1. Quoted characters + + // quoted-pair = ("\" (VCHAR / WSP)) / obs-qp + function quotedPair() { + var qp = wrap('quoted-pair', + or( + and(literal('\\'), or(vchar, wsp)), + obsQP + )()); + if (qp === null) { return null; } + // a quoted pair will be two characters, and the "\" character + // should be semantically "invisible" (RFC 5322 3.2.1) + qp.semantic = qp.semantic[1]; + return qp; + } + + // 3.2.2. Folding White Space and Comments + + // FWS = ([*WSP CRLF] 1*WSP) / obs-FWS + function fws() { + return wrap('fws', or( + obsFws, + and( + opt(and( + star(wsp), + invis(crlf) + )), + star(wsp, 1) + ) + )()); + } + + // ctext = %d33-39 / ; Printable US-ASCII + // %d42-91 / ; characters not including + // %d93-126 / ; "(", ")", or "\" + // obs-ctext + function ctext() { + return wrap('ctext', or( + function ctextFunc1() { + return compareToken(function ctextFunc2(tok) { + var code = tok.charCodeAt(0); + var accept = + (33 <= code && code <= 39) || + (42 <= code && code <= 91) || + (93 <= code && code <= 126); + if (opts.rfc6532) { + accept = accept || isUTF8NonAscii(tok); + } + return accept; + }); + }, + obsCtext + )()); + } + + // ccontent = ctext / quoted-pair / comment + function ccontent() { + return wrap('ccontent', or(ctext, quotedPair, comment)()); + } + + // comment = "(" *([FWS] ccontent) [FWS] ")" + function comment() { + return wrap('comment', and( + literal('('), + star(and(opt(fws), ccontent)), + opt(fws), + literal(')') + )()); + } + + // CFWS = (1*([FWS] comment) [FWS]) / FWS + function cfws() { + return wrap('cfws', or( + and( + star( + and(opt(fws), comment), + 1 + ), + opt(fws) + ), + fws + )()); + } + + // 3.2.3. Atom + + //atext = ALPHA / DIGIT / ; Printable US-ASCII + // "!" / "#" / ; characters not including + // "$" / "%" / ; specials. Used for atoms. + // "&" / "'" / + // "*" / "+" / + // "-" / "/" / + // "=" / "?" / + // "^" / "_" / + // "`" / "{" / + // "|" / "}" / + // "~" + function atext() { + return wrap('atext', compareToken(function atextFunc(tok) { + var accept = + ('a' <= tok && tok <= 'z') || + ('A' <= tok && tok <= 'Z') || + ('0' <= tok && tok <= '9') || + (['!', '#', '$', '%', '&', '\'', '*', '+', '-', '/', + '=', '?', '^', '_', '`', '{', '|', '}', '~'].indexOf(tok) >= 0); + if (opts.rfc6532) { + accept = accept || isUTF8NonAscii(tok); + } + return accept; + })); + } -const webCrypto = _util2.default.getWebCrypto(); // OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2015-2016 Decentral -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + // atom = [CFWS] 1*atext [CFWS] + function atom() { + return wrap('atom', and(colwsp(opt(cfws)), star(atext, 1), colwsp(opt(cfws)))()); + } -/** - * @fileoverview Wrapper of an instance of an Elliptic Curve - * @requires bn.js - * @requires elliptic - * @requires crypto/public_key/elliptic/key - * @requires crypto/random - * @requires enums - * @requires util - * @requires type/oid - * @module crypto/public_key/elliptic/curve - */ + // dot-atom-text = 1*atext *("." 1*atext) + function dotAtomText() { + var s, maybeText; + s = wrap('dot-atom-text', star(atext, 1)()); + if (s === null) { return s; } + maybeText = star(and(literal('.'), star(atext, 1)))(); + if (maybeText !== null) { + add(s, maybeText); + } + return s; + } -const nodeCrypto = _util2.default.getNodeCrypto(); + // dot-atom = [CFWS] dot-atom-text [CFWS] + function dotAtom() { + return wrap('dot-atom', and(invis(opt(cfws)), dotAtomText, invis(opt(cfws)))()); + } -const webCurves = { - 'p256': 'P-256', - 'p384': 'P-384', - 'p521': 'P-521' -}; -const knownCurves = nodeCrypto ? nodeCrypto.getCurves() : []; -const nodeCurves = nodeCrypto ? { - secp256k1: knownCurves.includes('secp256k1') ? 'secp256k1' : undefined, - p256: knownCurves.includes('prime256v1') ? 'prime256v1' : undefined, - p384: knownCurves.includes('secp384r1') ? 'secp384r1' : undefined, - p521: knownCurves.includes('secp521r1') ? 'secp521r1' : undefined, - ed25519: knownCurves.includes('ED25519') ? 'ED25519' : undefined, - curve25519: knownCurves.includes('X25519') ? 'X25519' : undefined, - brainpoolP256r1: knownCurves.includes('brainpoolP256r1') ? 'brainpoolP256r1' : undefined, - brainpoolP384r1: knownCurves.includes('brainpoolP384r1') ? 'brainpoolP384r1' : undefined, - brainpoolP512r1: knownCurves.includes('brainpoolP512r1') ? 'brainpoolP512r1' : undefined -} : {}; + // 3.2.4. Quoted Strings -const curves = { - p256: { - oid: [0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07], - keyType: _enums2.default.publicKey.ecdsa, - hash: _enums2.default.hash.sha256, - cipher: _enums2.default.symmetric.aes128, - node: nodeCurves.p256, - web: webCurves.p256, - payloadSize: 32, - sharedSize: 256 - }, - p384: { - oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22], - keyType: _enums2.default.publicKey.ecdsa, - hash: _enums2.default.hash.sha384, - cipher: _enums2.default.symmetric.aes192, - node: nodeCurves.p384, - web: webCurves.p384, - payloadSize: 48, - sharedSize: 384 - }, - p521: { - oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23], - keyType: _enums2.default.publicKey.ecdsa, - hash: _enums2.default.hash.sha512, - cipher: _enums2.default.symmetric.aes256, - node: nodeCurves.p521, - web: webCurves.p521, - payloadSize: 66, - sharedSize: 528 - }, - secp256k1: { - oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x0A], - keyType: _enums2.default.publicKey.ecdsa, - hash: _enums2.default.hash.sha256, - cipher: _enums2.default.symmetric.aes128, - node: nodeCurves.secp256k1 - }, - ed25519: { - oid: [0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01], - keyType: _enums2.default.publicKey.eddsa, - hash: _enums2.default.hash.sha512, - node: false // nodeCurves.ed25519 TODO - }, - curve25519: { - oid: [0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01], - keyType: _enums2.default.publicKey.ecdsa, - hash: _enums2.default.hash.sha256, - cipher: _enums2.default.symmetric.aes128, - node: false // nodeCurves.curve25519 TODO - }, - brainpoolP256r1: { - oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07], - keyType: _enums2.default.publicKey.ecdsa, - hash: _enums2.default.hash.sha256, - cipher: _enums2.default.symmetric.aes128, - node: nodeCurves.brainpoolP256r1 - }, - brainpoolP384r1: { - oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B], - keyType: _enums2.default.publicKey.ecdsa, - hash: _enums2.default.hash.sha384, - cipher: _enums2.default.symmetric.aes192, - node: nodeCurves.brainpoolP384r1 - }, - brainpoolP512r1: { - oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D], - keyType: _enums2.default.publicKey.ecdsa, - hash: _enums2.default.hash.sha512, - cipher: _enums2.default.symmetric.aes256, - node: nodeCurves.brainpoolP512r1 - } -}; + // qtext = %d33 / ; Printable US-ASCII + // %d35-91 / ; characters not including + // %d93-126 / ; "\" or the quote character + // obs-qtext + function qtext() { + return wrap('qtext', or( + function qtextFunc1() { + return compareToken(function qtextFunc2(tok) { + var code = tok.charCodeAt(0); + var accept = + (33 === code) || + (35 <= code && code <= 91) || + (93 <= code && code <= 126); + if (opts.rfc6532) { + accept = accept || isUTF8NonAscii(tok); + } + return accept; + }); + }, + obsQtext + )()); + } -/** - * @constructor - */ -function Curve(oid_or_name, params) { - try { - if (_util2.default.isArray(oid_or_name) || _util2.default.isUint8Array(oid_or_name)) { - // by oid byte array - oid_or_name = new _oid2.default(oid_or_name); + // qcontent = qtext / quoted-pair + function qcontent() { + return wrap('qcontent', or(qtext, quotedPair)()); } - if (oid_or_name instanceof _oid2.default) { - // by curve OID - oid_or_name = oid_or_name.getName(); + + // quoted-string = [CFWS] + // DQUOTE *([FWS] qcontent) [FWS] DQUOTE + // [CFWS] + function quotedString() { + return wrap('quoted-string', and( + invis(opt(cfws)), + invis(dquote), star(and(opt(colwsp(fws)), qcontent)), opt(invis(fws)), invis(dquote), + invis(opt(cfws)) + )()); } - // by curve name or oid string - this.name = _enums2.default.write(_enums2.default.curve, oid_or_name); - } catch (err) { - throw new Error('Not valid curve'); - } - params = params || curves[this.name]; - this.keyType = params.keyType; - switch (this.keyType) { - case _enums2.default.publicKey.ecdsa: - this.curve = new _elliptic.ec(this.name); - break; - case _enums2.default.publicKey.eddsa: - this.curve = new _elliptic.eddsa(this.name); - break; - default: - throw new Error('Unknown elliptic key type;'); - } + // 3.2.5 Miscellaneous Tokens - this.oid = params.oid; - this.hash = params.hash; - this.cipher = params.cipher; - this.node = params.node && curves[this.name]; - this.web = params.web && curves[this.name]; - this.payloadSize = params.payloadSize; -} + // word = atom / quoted-string + function word() { + return wrap('word', or(atom, quotedString)()); + } -Curve.prototype.keyFromPrivate = function (priv) { - // Not for ed25519 - return new _key2.default(this, { priv: priv }); -}; + // phrase = 1*word / obs-phrase + function phrase() { + return wrap('phrase', or(obsPhrase, star(word, 1))()); + } -Curve.prototype.keyFromPublic = function (pub) { - const keyPair = new _key2.default(this, { pub: pub }); - if (this.keyType === _enums2.default.publicKey.ecdsa && keyPair.keyPair.validate().result !== true) { - throw new Error('Invalid elliptic public key'); - } - return keyPair; -}; + // 3.4. Address Specification + // address = mailbox / group + function address() { + return wrap('address', or(mailbox, group)()); + } -Curve.prototype.genKeyPair = async function () { - let keyPair; - if (this.web && _util2.default.getWebCrypto()) { - // If browser doesn't support a curve, we'll catch it - try { - keyPair = await webGenKeyPair(this.name); - } catch (err) { - _util2.default.print_debug("Browser did not support signing: " + err.message); + // mailbox = name-addr / addr-spec + function mailbox() { + return wrap('mailbox', or(nameAddr, addrSpec)()); } - } else if (this.node && _util2.default.getNodeCrypto()) { - keyPair = await nodeGenKeyPair(this.name); - } - if (!keyPair || !keyPair.priv) { - // elliptic fallback - const r = await this.curve.genKeyPair({ - entropy: _util2.default.Uint8Array_to_str((await _random2.default.getRandomBytes(32))) - }); - const compact = this.curve.curve.type === 'edwards' || this.curve.curve.type === 'mont'; - if (this.keyType === _enums2.default.publicKey.eddsa) { - keyPair = { secret: r.getSecret() }; - } else { - keyPair = { pub: r.getPublic('array', compact), priv: r.getPrivate().toArray() }; + // name-addr = [display-name] angle-addr + function nameAddr() { + return wrap('name-addr', and(opt(displayName), angleAddr)()); } - } - return new _key2.default(this, keyPair); -}; -async function generate(curve) { - curve = new Curve(curve); - const keyPair = await curve.genKeyPair(); - return { - oid: curve.oid, - Q: new _bn2.default(keyPair.getPublic()), - d: new _bn2.default(keyPair.getPrivate()), - hash: curve.hash, - cipher: curve.cipher - }; -} + // angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / + // obs-angle-addr + function angleAddr() { + return wrap('angle-addr', or( + and( + invis(opt(cfws)), + literal('<'), + addrSpec, + literal('>'), + invis(opt(cfws)) + ), + obsAngleAddr + )()); + } -function getPreferredHashAlgo(oid) { - return curves[_enums2.default.write(_enums2.default.curve, oid.toHex())].hash; -} + // group = display-name ":" [group-list] ";" [CFWS] + function group() { + return wrap('group', and( + displayName, + literal(':'), + opt(groupList), + literal(';'), + invis(opt(cfws)) + )()); + } -exports.default = Curve; -exports.curves = curves; -exports.webCurves = webCurves; -exports.nodeCurves = nodeCurves; -exports.generate = generate; -exports.getPreferredHashAlgo = getPreferredHashAlgo; + // display-name = phrase + function displayName() { + return wrap('display-name', function phraseFixedSemantic() { + var result = phrase(); + if (result !== null) { + result.semantic = collapseWhitespace(result.semantic); + } + return result; + }()); + } + + // mailbox-list = (mailbox *("," mailbox)) / obs-mbox-list + function mailboxList() { + return wrap('mailbox-list', or( + and( + mailbox, + star(and(literal(','), mailbox)) + ), + obsMboxList + )()); + } + + // address-list = (address *("," address)) / obs-addr-list + function addressList() { + return wrap('address-list', or( + and( + address, + star(and(literal(','), address)) + ), + obsAddrList + )()); + } + + // group-list = mailbox-list / CFWS / obs-group-list + function groupList() { + return wrap('group-list', or( + mailboxList, + invis(cfws), + obsGroupList + )()); + } + + // 3.4.1 Addr-Spec Specification + + // local-part = dot-atom / quoted-string / obs-local-part + function localPart() { + // note: quoted-string, dotAtom are proper subsets of obs-local-part + // so we really just have to look for obsLocalPart, if we don't care about the exact parse tree + return wrap('local-part', or(obsLocalPart, dotAtom, quotedString)()); + } + + // dtext = %d33-90 / ; Printable US-ASCII + // %d94-126 / ; characters not including + // obs-dtext ; "[", "]", or "\" + function dtext() { + return wrap('dtext', or( + function dtextFunc1() { + return compareToken(function dtextFunc2(tok) { + var code = tok.charCodeAt(0); + var accept = + (33 <= code && code <= 90) || + (94 <= code && code <= 126); + if (opts.rfc6532) { + accept = accept || isUTF8NonAscii(tok); + } + return accept; + }); + }, + obsDtext + )() + ); + } + + // domain-literal = [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS] + function domainLiteral() { + return wrap('domain-literal', and( + invis(opt(cfws)), + literal('['), + star(and(opt(fws), dtext)), + opt(fws), + literal(']'), + invis(opt(cfws)) + )()); + } + + // domain = dot-atom / domain-literal / obs-domain + function domain() { + return wrap('domain', function domainCheckTLD() { + var result = or(obsDomain, dotAtom, domainLiteral)(); + if (opts.rejectTLD) { + if (result && result.semantic && result.semantic.indexOf('.') < 0) { + return null; + } + } + // strip all whitespace from domains + if (result) { + result.semantic = result.semantic.replace(/\s+/g, ''); + } + return result; + }()); + } + + // addr-spec = local-part "@" domain + function addrSpec() { + return wrap('addr-spec', and( + localPart, literal('@'), domain + )()); + } + + // 3.6.2 Originator Fields + // Below we only parse the field body, not the name of the field + // like "From:", "Sender:", or "Reply-To:". Other libraries that + // parse email headers can parse those and defer to these productions + // for the "RFC 5322" part. + + // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields + // from = "From:" (mailbox-list / address-list) CRLF + function fromSpec() { + return wrap('from', or( + mailboxList, + addressList + )()); + } + + // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields + // sender = "Sender:" (mailbox / address) CRLF + function senderSpec() { + return wrap('sender', or( + mailbox, + address + )()); + } + + // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields + // reply-to = "Reply-To:" address-list CRLF + function replyToSpec() { + return wrap('reply-to', addressList()); + } + + // 4.1. Miscellaneous Obsolete Tokens + + // obs-NO-WS-CTL = %d1-8 / ; US-ASCII control + // %d11 / ; characters that do not + // %d12 / ; include the carriage + // %d14-31 / ; return, line feed, and + // %d127 ; white space characters + function obsNoWsCtl() { + return opts.strict ? null : wrap('obs-NO-WS-CTL', compareToken(function (tok) { + var code = tok.charCodeAt(0); + return ((1 <= code && code <= 8) || + (11 === code || 12 === code) || + (14 <= code && code <= 31) || + (127 === code)); + })); + } -////////////////////////// -// // -// Helper functions // -// // -////////////////////////// + // obs-ctext = obs-NO-WS-CTL + function obsCtext() { return opts.strict ? null : wrap('obs-ctext', obsNoWsCtl()); } + + // obs-qtext = obs-NO-WS-CTL + function obsQtext() { return opts.strict ? null : wrap('obs-qtext', obsNoWsCtl()); } + + // obs-qp = "\" (%d0 / obs-NO-WS-CTL / LF / CR) + function obsQP() { + return opts.strict ? null : wrap('obs-qp', and( + literal('\\'), + or(literal('\0'), obsNoWsCtl, lf, cr) + )()); + } + + // obs-phrase = word *(word / "." / CFWS) + function obsPhrase() { + if (opts.strict ) return null; + return opts.atInDisplayName ? wrap('obs-phrase', and( + word, + star(or(word, literal('.'), literal('@'), colwsp(cfws))) + )()) : + wrap('obs-phrase', and( + word, + star(or(word, literal('.'), colwsp(cfws))) + )()); + } + + // 4.2. Obsolete Folding White Space + + // NOTE: read the errata http://www.rfc-editor.org/errata_search.php?rfc=5322&eid=1908 + // obs-FWS = 1*([CRLF] WSP) + function obsFws() { + return opts.strict ? null : wrap('obs-FWS', star( + and(invis(opt(crlf)), wsp), + 1 + )()); + } + + // 4.4. Obsolete Addressing + + // obs-angle-addr = [CFWS] "<" obs-route addr-spec ">" [CFWS] + function obsAngleAddr() { + return opts.strict ? null : wrap('obs-angle-addr', and( + invis(opt(cfws)), + literal('<'), + obsRoute, + addrSpec, + literal('>'), + invis(opt(cfws)) + )()); + } + + // obs-route = obs-domain-list ":" + function obsRoute() { + return opts.strict ? null : wrap('obs-route', and( + obsDomainList, + literal(':') + )()); + } + + // obs-domain-list = *(CFWS / ",") "@" domain + // *("," [CFWS] ["@" domain]) + function obsDomainList() { + return opts.strict ? null : wrap('obs-domain-list', and( + star(or(invis(cfws), literal(','))), + literal('@'), + domain, + star(and( + literal(','), + invis(opt(cfws)), + opt(and(literal('@'), domain)) + )) + )()); + } + + // obs-mbox-list = *([CFWS] ",") mailbox *("," [mailbox / CFWS]) + function obsMboxList() { + return opts.strict ? null : wrap('obs-mbox-list', and( + star(and( + invis(opt(cfws)), + literal(',') + )), + mailbox, + star(and( + literal(','), + opt(and( + mailbox, + invis(cfws) + )) + )) + )()); + } + + // obs-addr-list = *([CFWS] ",") address *("," [address / CFWS]) + function obsAddrList() { + return opts.strict ? null : wrap('obs-addr-list', and( + star(and( + invis(opt(cfws)), + literal(',') + )), + address, + star(and( + literal(','), + opt(and( + address, + invis(cfws) + )) + )) + )()); + } + + // obs-group-list = 1*([CFWS] ",") [CFWS] + function obsGroupList() { + return opts.strict ? null : wrap('obs-group-list', and( + star(and( + invis(opt(cfws)), + literal(',') + ), 1), + invis(opt(cfws)) + )()); + } + + // obs-local-part = word *("." word) + function obsLocalPart() { + return opts.strict ? null : wrap('obs-local-part', and(word, star(and(literal('.'), word)))()); + } + + // obs-domain = atom *("." atom) + function obsDomain() { + return opts.strict ? null : wrap('obs-domain', and(atom, star(and(literal('.'), atom)))()); + } + + // obs-dtext = obs-NO-WS-CTL / quoted-pair + function obsDtext() { + return opts.strict ? null : wrap('obs-dtext', or(obsNoWsCtl, quotedPair)()); + } + + ///////////////////////////////////////////////////// + + // ast analysis + + function findNode(name, root) { + var i, stack, node; + if (root === null || root === undefined) { return null; } + stack = [root]; + while (stack.length > 0) { + node = stack.pop(); + if (node.name === name) { + return node; + } + for (i = node.children.length - 1; i >= 0; i -= 1) { + stack.push(node.children[i]); + } + } + return null; + } + function findAllNodes(name, root) { + var i, stack, node, result; + if (root === null || root === undefined) { return null; } + stack = [root]; + result = []; + while (stack.length > 0) { + node = stack.pop(); + if (node.name === name) { + result.push(node); + } + for (i = node.children.length - 1; i >= 0; i -= 1) { + stack.push(node.children[i]); + } + } + return result; + } -async function webGenKeyPair(name) { - // Note: keys generated with ECDSA and ECDH are structurally equivalent - const webCryptoKey = await webCrypto.generateKey({ name: "ECDSA", namedCurve: webCurves[name] }, true, ["sign", "verify"]); + function findAllNodesNoChildren(names, root) { + var i, stack, node, result, namesLookup; + if (root === null || root === undefined) { return null; } + stack = [root]; + result = []; + namesLookup = {}; + for (i = 0; i < names.length; i += 1) { + namesLookup[names[i]] = true; + } - const privateKey = await webCrypto.exportKey("jwk", webCryptoKey.privateKey); - const publicKey = await webCrypto.exportKey("jwk", webCryptoKey.publicKey); + while (stack.length > 0) { + node = stack.pop(); + if (node.name in namesLookup) { + result.push(node); + // don't look at children (hence findAllNodesNoChildren) + } else { + for (i = node.children.length - 1; i >= 0; i -= 1) { + stack.push(node.children[i]); + } + } + } + return result; + } - return { - pub: { - x: _util2.default.b64_to_Uint8Array(publicKey.x, true), - y: _util2.default.b64_to_Uint8Array(publicKey.y, true) - }, - priv: _util2.default.b64_to_Uint8Array(privateKey.d, true) - }; -} + function giveResult(ast) { + var addresses, groupsAndMailboxes, i, groupOrMailbox, result; + if (ast === null) { + return null; + } + addresses = []; -async function nodeGenKeyPair(name) { - // Note: ECDSA and ECDH key generation is structurally equivalent - const ecdh = nodeCrypto.createECDH(nodeCurves[name]); - await ecdh.generateKeys(); + // An address is a 'group' (i.e. a list of mailboxes) or a 'mailbox'. + groupsAndMailboxes = findAllNodesNoChildren(['group', 'mailbox'], ast); + for (i = 0; i < groupsAndMailboxes.length; i += 1) { + groupOrMailbox = groupsAndMailboxes[i]; + if (groupOrMailbox.name === 'group') { + addresses.push(giveResultGroup(groupOrMailbox)); + } else if (groupOrMailbox.name === 'mailbox') { + addresses.push(giveResultMailbox(groupOrMailbox)); + } + } - return { - pub: ecdh.getPublicKey().toJSON().data, - priv: ecdh.getPrivateKey().toJSON().data - }; -} + result = { + ast: ast, + addresses: addresses, + }; + if (opts.simple) { + result = simplifyResult(result); + } + if (opts.oneResult) { + return oneResult(result); + } + if (opts.simple) { + return result && result.addresses; + } else { + return result; + } + } -},{"../../../enums":113,"../../../type/oid":150,"../../../util":152,"../../random":109,"./key":105,"bn.js":16,"elliptic":18}],101:[function(require,module,exports){ -'use strict'; + function giveResultGroup(group) { + var i; + var groupName = findNode('display-name', group); + var groupResultMailboxes = []; + var mailboxes = findAllNodesNoChildren(['mailbox'], group); + for (i = 0; i < mailboxes.length; i += 1) { + groupResultMailboxes.push(giveResultMailbox(mailboxes[i])); + } + return { + node: group, + parts: { + name: groupName, + }, + type: group.name, // 'group' + name: grabSemantic(groupName), + addresses: groupResultMailboxes, + }; + } -Object.defineProperty(exports, "__esModule", { - value: true -}); + function giveResultMailbox(mailbox) { + var name = findNode('display-name', mailbox); + var aspec = findNode('addr-spec', mailbox); + var cfws = findAllNodes('cfws', mailbox); + var comments = findAllNodesNoChildren(['comment'], mailbox); -var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); // OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2015-2016 Decentral -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -/** - * @fileoverview Key encryption and decryption for RFC 6637 ECDH - * @requires bn.js - * @requires tweetnacl - * @requires crypto/public_key/elliptic/curve - * @requires crypto/aes_kw - * @requires crypto/cipher - * @requires crypto/hash - * @requires type/kdf_params - * @requires enums - * @requires util - * @module crypto/public_key/elliptic/ecdh - */ + var local = findNode('local-part', aspec); + var domain = findNode('domain', aspec); + return { + node: mailbox, + parts: { + name: name, + address: aspec, + local: local, + domain: domain, + comments: cfws + }, + type: mailbox.name, // 'mailbox' + name: grabSemantic(name), + address: grabSemantic(aspec), + local: grabSemantic(local), + domain: grabSemantic(domain), + comments: concatComments(comments), + groupName: grabSemantic(mailbox.groupName), + }; + } -var _bn = require('bn.js'); + function grabSemantic(n) { + return n !== null && n !== undefined ? n.semantic : null; + } -var _bn2 = _interopRequireDefault(_bn); + function simplifyResult(result) { + var i; + if (result && result.addresses) { + for (i = 0; i < result.addresses.length; i += 1) { + delete result.addresses[i].node; + } + } + return result; + } -var _naclFastLight = require('tweetnacl/nacl-fast-light.js'); + function concatComments(comments) { + var result = ''; + if (comments) { + for (var i = 0; i < comments.length; i += 1) { + result += grabSemantic(comments[i]); + } + } + return result; + } -var _naclFastLight2 = _interopRequireDefault(_naclFastLight); + function oneResult(result) { + if (!result) { return null; } + if (!opts.partial && result.addresses.length > 1) { return null; } + return result.addresses && result.addresses[0]; + } -var _curves = require('./curves'); + ///////////////////////////////////////////////////// -var _curves2 = _interopRequireDefault(_curves); + var parseString, pos, len, parsed, startProduction; -var _aes_kw = require('../../aes_kw'); + opts = handleOpts(opts, {}); + if (opts === null) { return null; } -var _aes_kw2 = _interopRequireDefault(_aes_kw); + parseString = opts.input; -var _cipher = require('../../cipher'); + startProduction = { + 'address': address, + 'address-list': addressList, + 'angle-addr': angleAddr, + 'from': fromSpec, + 'group': group, + 'mailbox': mailbox, + 'mailbox-list': mailboxList, + 'reply-to': replyToSpec, + 'sender': senderSpec, + }[opts.startAt] || addressList; -var _cipher2 = _interopRequireDefault(_cipher); + if (!opts.strict) { + initialize(); + opts.strict = true; + parsed = startProduction(parseString); + if (opts.partial || !inStr()) { + return giveResult(parsed); + } + opts.strict = false; + } -var _hash = require('../../hash'); + initialize(); + parsed = startProduction(parseString); + if (!opts.partial && inStr()) { return null; } + return giveResult(parsed); +} -var _hash2 = _interopRequireDefault(_hash); +function parseOneAddressSimple(opts) { + return parse5322(handleOpts(opts, { + oneResult: true, + rfc6532: true, + simple: true, + startAt: 'address-list', + })); +} -var _kdf_params = require('../../../type/kdf_params'); +function parseAddressListSimple(opts) { + return parse5322(handleOpts(opts, { + rfc6532: true, + simple: true, + startAt: 'address-list', + })); +} -var _kdf_params2 = _interopRequireDefault(_kdf_params); +function parseFromSimple(opts) { + return parse5322(handleOpts(opts, { + rfc6532: true, + simple: true, + startAt: 'from', + })); +} -var _enums = require('../../../enums'); +function parseSenderSimple(opts) { + return parse5322(handleOpts(opts, { + oneResult: true, + rfc6532: true, + simple: true, + startAt: 'sender', + })); +} -var _enums2 = _interopRequireDefault(_enums); +function parseReplyToSimple(opts) { + return parse5322(handleOpts(opts, { + rfc6532: true, + simple: true, + startAt: 'reply-to', + })); +} -var _util = require('../../../util'); +function handleOpts(opts, defs) { + function isString(str) { + return Object.prototype.toString.call(str) === '[object String]'; + } -var _util2 = _interopRequireDefault(_util); + function isObject(o) { + return o === Object(o); + } -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + function isNullUndef(o) { + return o === null || o === undefined; + } -const webCrypto = _util2.default.getWebCrypto(); -const nodeCrypto = _util2.default.getNodeCrypto(); + var defaults, o; -// Build Param for ECDH algorithm (RFC 6637) -function buildEcdhParam(public_algo, oid, cipher_algo, hash_algo, fingerprint) { - const kdf_params = new _kdf_params2.default([hash_algo, cipher_algo]); - return _util2.default.concatUint8Array([oid.write(), new Uint8Array([public_algo]), kdf_params.write(), _util2.default.str_to_Uint8Array("Anonymous Sender "), fingerprint.subarray(0, 20)]); + if (isString(opts)) { + opts = { input: opts }; + } else if (!isObject(opts)) { + return null; + } + + if (!isString(opts.input)) { return null; } + if (!defs) { return null; } + + defaults = { + oneResult: false, + partial: false, + rejectTLD: false, + rfc6532: false, + simple: false, + startAt: 'address-list', + strict: false, + atInDisplayName: false + }; + + for (o in defaults) { + if (isNullUndef(opts[o])) { + opts[o] = !isNullUndef(defs[o]) ? defs[o] : defaults[o]; + } + } + return opts; } -// Key Derivation Function (RFC 6637) -async function kdf(hash_algo, X, length, param, stripLeading = false, stripTrailing = false) { - // Note: X is little endian for Curve25519, big-endian for all others. - // This is not ideal, but the RFC's are unclear - // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B - let i; - if (stripLeading) { - // Work around old go crypto bug - for (i = 0; i < X.length && X[i] === 0; i++); - X = X.subarray(i); - } - if (stripTrailing) { - // Work around old OpenPGP.js bug - for (i = X.length - 1; i >= 0 && X[i] === 0; i--); - X = X.subarray(0, i + 1); - } - const digest = await _hash2.default.digest(hash_algo, _util2.default.concatUint8Array([new Uint8Array([0, 0, 0, 1]), X, param])); - return digest.subarray(0, length); +parse5322.parseOneAddress = parseOneAddressSimple; +parse5322.parseAddressList = parseAddressListSimple; +parse5322.parseFrom = parseFromSimple; +parse5322.parseSender = parseSenderSimple; +parse5322.parseReplyTo = parseReplyToSimple; + +{ + module.exports = parse5322; } +}()); +}); + +// GPG4Browsers - An OpenPGP implementation in javascript + /** - * Generate ECDHE ephemeral key and secret from public key + * Implementation of the User ID Packet (Tag 13) * - * @param {Curve} curve Elliptic curve object - * @param {Uint8Array} Q Recipient public key - * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} - * @async + * A User ID packet consists of UTF-8 text that is intended to represent + * the name and email address of the key holder. By convention, it + * includes an RFC 2822 [RFC2822] mail name-addr, but there are no + * restrictions on its content. The packet length in the header + * specifies the length of the User ID. */ -async function genPublicEphemeralKey(curve, Q) { - switch (curve.name) { - case 'curve25519': - { - var _nacl$box$keyPair = _naclFastLight2.default.box.keyPair(); +class UserIDPacket { + static get tag() { + return enums.packet.userID; + } - const d = _nacl$box$keyPair.secretKey; + constructor() { + /** A string containing the user id. Usually in the form + * John Doe + * @type {String} + */ + this.userID = ''; - var _ref = await genPrivateEphemeralKey(curve, Q, null, d); + this.name = ''; + this.email = ''; + this.comment = ''; + } - const secretKey = _ref.secretKey, - sharedKey = _ref.sharedKey; + /** + * Create UserIDPacket instance from object + * @param {Object} userID - Object specifying userID name, email and comment + * @returns {UserIDPacket} + * @static + */ + static fromObject(userID) { + if (util.isString(userID) || + (userID.name && !util.isString(userID.name)) || + (userID.email && !util.isEmailAddress(userID.email)) || + (userID.comment && !util.isString(userID.comment))) { + throw new Error('Invalid user ID format'); + } + const packet = new UserIDPacket(); + Object.assign(packet, userID); + const components = []; + if (packet.name) components.push(packet.name); + if (packet.comment) components.push(`(${packet.comment})`); + if (packet.email) components.push(`<${packet.email}>`); + packet.userID = components.join(' '); + return packet; + } - var _nacl$box$keyPair$fro = _naclFastLight2.default.box.keyPair.fromSecretKey(secretKey); + /** + * Parsing function for a user id packet (tag 13). + * @param {Uint8Array} input - Payload of a tag 13 packet + */ + read(bytes, config = defaultConfig) { + const userID = util.decodeUTF8(bytes); + if (userID.length > config.maxUserIDLength) { + throw new Error('User ID string is too long'); + } + try { + const { name, address: email, comments } = emailAddresses.parseOneAddress({ input: userID, atInDisplayName: true }); + this.comment = comments.replace(/^\(|\)$/g, ''); + this.name = name; + this.email = email; + } catch (e) {} + this.userID = userID; + } - let publicKey = _nacl$box$keyPair$fro.publicKey; + /** + * Creates a binary representation of the user id packet + * @returns {Uint8Array} Binary representation. + */ + write() { + return util.encodeUTF8(this.userID); + } - publicKey = _util2.default.concatUint8Array([new Uint8Array([0x40]), publicKey]); - return { publicKey, sharedKey }; // Note: sharedKey is little-endian here, unlike below - } - case 'p256': - case 'p384': - case 'p521': - { - if (curve.web && _util2.default.getWebCrypto()) { - try { - return await webPublicEphemeralKey(curve, Q); - } catch (err) { - _util2.default.print_debug_error(err); - } - } - } + equals(otherUserID) { + return otherUserID && otherUserID.userID === this.userID; + } +} + +// GPG4Browsers - An OpenPGP implementation in javascript + +/** + * A Secret-Subkey packet (tag 7) is the subkey analog of the Secret + * Key packet and has exactly the same format. + * @extends SecretKeyPacket + */ +class SecretSubkeyPacket extends SecretKeyPacket { + static get tag() { + return enums.packet.secretSubkey; + } + + /** + * @param {Date} [date] - Creation date + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + constructor(date = new Date(), config = defaultConfig) { + super(date, config); + } +} + +/** + * Implementation of the Trust Packet (Tag 12) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.10|RFC4880 5.10}: + * The Trust packet is used only within keyrings and is not normally + * exported. Trust packets contain data that record the user's + * specifications of which key holders are trustworthy introducers, + * along with other information that implementing software uses for + * trust information. The format of Trust packets is defined by a given + * implementation. + * + * Trust packets SHOULD NOT be emitted to output streams that are + * transferred to other users, and they SHOULD be ignored on any input + * other than local keyring files. + */ +class TrustPacket { + static get tag() { + return enums.packet.trust; + } + + /** + * Parsing function for a trust packet (tag 12). + * Currently not implemented as we ignore trust packets + */ + read() { + throw new UnsupportedError('Trust packets are not supported'); } - if (curve.node && nodeCrypto) { - return nodePublicEphemeralKey(curve, Q); + + write() { + throw new UnsupportedError('Trust packets are not supported'); } - return ellipticPublicEphemeralKey(curve, Q); } +// GPG4Browsers - An OpenPGP implementation in javascript + +// A Signature can contain the following packets +const allowedPackets$4 = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); + /** - * Encrypt and wrap a session key - * - * @param {module:type/oid} oid Elliptic curve object identifier - * @param {module:enums.symmetric} cipher_algo Symmetric cipher to use - * @param {module:enums.hash} hash_algo Hash algorithm to use - * @param {module:type/mpi} m Value derived from session key (RFC 6637) - * @param {Uint8Array} Q Recipient public key - * @param {String} fingerprint Recipient fingerprint - * @returns {Promise<{publicKey: Uint8Array, wrappedKey: Uint8Array}>} - * @async + * Class that represents an OpenPGP signature. */ -async function encrypt(oid, cipher_algo, hash_algo, m, Q, fingerprint) { - const curve = new _curves2.default(oid); +class Signature { + /** + * @param {PacketList} packetlist - The signature packets + */ + constructor(packetlist) { + this.packets = packetlist || new PacketList(); + } - var _ref2 = await genPublicEphemeralKey(curve, Q); + /** + * Returns binary encoded signature + * @returns {ReadableStream} Binary signature. + */ + write() { + return this.packets.write(); + } - const publicKey = _ref2.publicKey, - sharedKey = _ref2.sharedKey; + /** + * Returns ASCII armored text of signature + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {ReadableStream} ASCII armor. + */ + armor(config = defaultConfig) { + return armor(enums.armor.signature, this.write(), undefined, undefined, undefined, config); + } - const param = buildEcdhParam(_enums2.default.publicKey.ecdh, oid, cipher_algo, hash_algo, fingerprint); - cipher_algo = _enums2.default.read(_enums2.default.symmetric, cipher_algo); - const Z = await kdf(hash_algo, sharedKey, _cipher2.default[cipher_algo].keySize, param); - const wrappedKey = _aes_kw2.default.wrap(Z, m.toString()); - return { publicKey, wrappedKey }; + /** + * Returns an array of KeyIDs of all of the issuers who created this signature + * @returns {Array} The Key IDs of the signing keys + */ + getSigningKeyIDs() { + return this.packets.map(packet => packet.issuerKeyID); + } } /** - * Generate ECDHE secret from private key and public part of ephemeral key - * - * @param {Curve} curve Elliptic curve object - * @param {Uint8Array} V Public part of ephemeral key - * @param {Uint8Array} Q Recipient public key - * @param {Uint8Array} d Recipient private key - * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} + * reads an (optionally armored) OpenPGP signature and returns a signature object + * @param {Object} options + * @param {String} [options.armoredSignature] - Armored signature to be parsed + * @param {Uint8Array} [options.binarySignature] - Binary signature to be parsed + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} New signature object. * @async + * @static */ -async function genPrivateEphemeralKey(curve, V, Q, d) { - switch (curve.name) { - case 'curve25519': - { - const one = new _bn2.default(1); - const mask = one.ushln(255 - 3).sub(one).ushln(3); - let secretKey = new _bn2.default(d); - secretKey = secretKey.or(one.ushln(255 - 1)); - secretKey = secretKey.and(mask); - secretKey = secretKey.toArrayLike(Uint8Array, 'le', 32); - const sharedKey = _naclFastLight2.default.scalarMult(secretKey, V.subarray(1)); - return { secretKey, sharedKey }; // Note: sharedKey is little-endian here, unlike below - } - case 'p256': - case 'p384': - case 'p521': - { - if (curve.web && _util2.default.getWebCrypto()) { - try { - return await webPrivateEphemeralKey(curve, V, Q, d); - } catch (err) { - _util2.default.print_debug_error(err); - } - } - } +async function readSignature({ armoredSignature, binarySignature, config, ...rest }) { + config = { ...defaultConfig, ...config }; + let input = armoredSignature || binarySignature; + if (!input) { + throw new Error('readSignature: must pass options object containing `armoredSignature` or `binarySignature`'); } - if (curve.node && nodeCrypto) { - return nodePrivateEphemeralKey(curve, V, d); + if (armoredSignature && !util.isString(armoredSignature)) { + throw new Error('readSignature: options.armoredSignature must be a string'); } - return ellipticPrivateEphemeralKey(curve, V, d); -} - -/** - * Decrypt and unwrap the value derived from session key - * - * @param {module:type/oid} oid Elliptic curve object identifier - * @param {module:enums.symmetric} cipher_algo Symmetric cipher to use - * @param {module:enums.hash} hash_algo Hash algorithm to use - * @param {Uint8Array} V Public part of ephemeral key - * @param {Uint8Array} C Encrypted and wrapped value derived from session key - * @param {Uint8Array} Q Recipient public key - * @param {Uint8Array} d Recipient private key - * @param {String} fingerprint Recipient fingerprint - * @returns {Promise} Value derived from session key - * @async - */ -async function decrypt(oid, cipher_algo, hash_algo, V, C, Q, d, fingerprint) { - const curve = new _curves2.default(oid); - - var _ref3 = await genPrivateEphemeralKey(curve, V, Q, d); - - const sharedKey = _ref3.sharedKey; + if (binarySignature && !util.isUint8Array(binarySignature)) { + throw new Error('readSignature: options.binarySignature must be a Uint8Array'); + } + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - const param = buildEcdhParam(_enums2.default.publicKey.ecdh, oid, cipher_algo, hash_algo, fingerprint); - cipher_algo = _enums2.default.read(_enums2.default.symmetric, cipher_algo); - let err; - for (let i = 0; i < 3; i++) { - try { - // Work around old go crypto bug and old OpenPGP.js bug, respectively. - const Z = await kdf(hash_algo, sharedKey, _cipher2.default[cipher_algo].keySize, param, i === 1, i === 2); - return new _bn2.default(_aes_kw2.default.unwrap(Z, C)); - } catch (e) { - err = e; + if (armoredSignature) { + const { type, data } = await unarmor(input, config); + if (type !== enums.armor.signature) { + throw new Error('Armored text not of type signature'); } + input = data; } - throw err; + const packetlist = await PacketList.fromBinary(input, allowedPackets$4, config); + return new Signature(packetlist); } /** - * Generate ECDHE secret from private key and public part of ephemeral key using webCrypto - * - * @param {Curve} curve Elliptic curve object - * @param {Uint8Array} V Public part of ephemeral key - * @param {Uint8Array} Q Recipient public key - * @param {Uint8Array} d Recipient private key - * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} - * @async + * @fileoverview Provides helpers methods for key module + * @module key/helper + * @private */ -async function webPrivateEphemeralKey(curve, V, Q, d) { - const recipient = privateToJwk(curve.payloadSize, curve.web.web, d, Q); - let privateKey = webCrypto.importKey("jwk", recipient, { - name: "ECDH", - namedCurve: curve.web.web - }, true, ["deriveKey", "deriveBits"]); - const jwk = rawPublicToJwk(curve.payloadSize, curve.web.web, V); - let sender = webCrypto.importKey("jwk", jwk, { - name: "ECDH", - namedCurve: curve.web.web - }, true, []); - - var _ref4 = await Promise.all([privateKey, sender]); - - var _ref5 = _slicedToArray(_ref4, 2); - - privateKey = _ref5[0]; - sender = _ref5[1]; - - let S = webCrypto.deriveBits({ - name: "ECDH", - namedCurve: curve.web.web, - public: sender - }, privateKey, curve.web.sharedSize); - let secret = webCrypto.exportKey("jwk", privateKey); - - var _ref6 = await Promise.all([S, secret]); - - var _ref7 = _slicedToArray(_ref6, 2); - S = _ref7[0]; - secret = _ref7[1]; +async function generateSecretSubkey(options, config) { + const secretSubkeyPacket = new SecretSubkeyPacket(options.date, config); + secretSubkeyPacket.packets = null; + secretSubkeyPacket.algorithm = enums.write(enums.publicKey, options.algorithm); + await secretSubkeyPacket.generate(options.rsaBits, options.curve); + await secretSubkeyPacket.computeFingerprintAndKeyID(); + return secretSubkeyPacket; +} - const sharedKey = new Uint8Array(S); - const secretKey = _util2.default.b64_to_Uint8Array(secret.d, true); - return { secretKey, sharedKey }; +async function generateSecretKey(options, config) { + const secretKeyPacket = new SecretKeyPacket(options.date, config); + secretKeyPacket.packets = null; + secretKeyPacket.algorithm = enums.write(enums.publicKey, options.algorithm); + await secretKeyPacket.generate(options.rsaBits, options.curve, options.config); + await secretKeyPacket.computeFingerprintAndKeyID(); + return secretKeyPacket; } /** - * Generate ECDHE ephemeral key and secret from public key using webCrypto - * - * @param {Curve} curve Elliptic curve object - * @param {Uint8Array} Q Recipient public key - * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} + * Returns the valid and non-expired signature that has the latest creation date, while ignoring signatures created in the future. + * @param {Array} signatures - List of signatures + * @param {PublicKeyPacket|PublicSubkeyPacket} publicKey - Public key packet to verify the signature + * @param {Date} date - Use the given date instead of the current time + * @param {Object} config - full configuration + * @returns {Promise} The latest valid signature. * @async */ -async function webPublicEphemeralKey(curve, Q) { - const jwk = rawPublicToJwk(curve.payloadSize, curve.web.web, Q); - let keyPair = webCrypto.generateKey({ - name: "ECDH", - namedCurve: curve.web.web - }, true, ["deriveKey", "deriveBits"]); - let recipient = webCrypto.importKey("jwk", jwk, { - name: "ECDH", - namedCurve: curve.web.web - }, false, []); - - var _ref8 = await Promise.all([keyPair, recipient]); - - var _ref9 = _slicedToArray(_ref8, 2); - - keyPair = _ref9[0]; - recipient = _ref9[1]; - - let s = webCrypto.deriveBits({ - name: "ECDH", - namedCurve: curve.web.web, - public: recipient - }, keyPair.privateKey, curve.web.sharedSize); - let p = webCrypto.exportKey("jwk", keyPair.publicKey); - - var _ref10 = await Promise.all([s, p]); - - var _ref11 = _slicedToArray(_ref10, 2); +async function getLatestValidSignature(signatures, publicKey, signatureType, dataToVerify, date = new Date(), config) { + let latestValid; + let exception; + for (let i = signatures.length - 1; i >= 0; i--) { + try { + if ( + (!latestValid || signatures[i].created >= latestValid.created) + ) { + await signatures[i].verify(publicKey, signatureType, dataToVerify, date, undefined, config); + latestValid = signatures[i]; + } + } catch (e) { + exception = e; + } + } + if (!latestValid) { + throw util.wrapError( + `Could not find valid ${enums.read(enums.signature, signatureType)} signature in key ${publicKey.getKeyID().toHex()}` + .replace('certGeneric ', 'self-') + .replace(/([a-z])([A-Z])/g, (_, $1, $2) => $1 + ' ' + $2.toLowerCase()) + , exception); + } + return latestValid; +} - s = _ref11[0]; - p = _ref11[1]; +function isDataExpired(keyPacket, signature, date = new Date()) { + const normDate = util.normalizeDate(date); + if (normDate !== null) { + const expirationTime = getKeyExpirationTime(keyPacket, signature); + return !(keyPacket.created <= normDate && normDate < expirationTime); + } + return false; +} - const sharedKey = new Uint8Array(s); - const publicKey = new Uint8Array(jwkToRawPublic(p)); - return { publicKey, sharedKey }; +/** + * Create Binding signature to the key according to the {@link https://tools.ietf.org/html/rfc4880#section-5.2.1} + * @param {SecretSubkeyPacket} subkey - Subkey key packet + * @param {SecretKeyPacket} primaryKey - Primary key packet + * @param {Object} options + * @param {Object} config - Full configuration + */ +async function createBindingSignature(subkey, primaryKey, options, config) { + const dataToSign = {}; + dataToSign.key = primaryKey; + dataToSign.bind = subkey; + const subkeySignaturePacket = new SignaturePacket(); + subkeySignaturePacket.signatureType = enums.signature.subkeyBinding; + subkeySignaturePacket.publicKeyAlgorithm = primaryKey.algorithm; + subkeySignaturePacket.hashAlgorithm = await getPreferredHashAlgo$1(null, subkey, undefined, undefined, config); + if (options.sign) { + subkeySignaturePacket.keyFlags = [enums.keyFlags.signData]; + subkeySignaturePacket.embeddedSignature = await createSignaturePacket(dataToSign, null, subkey, { + signatureType: enums.signature.keyBinding + }, options.date, undefined, undefined, config); + } else { + subkeySignaturePacket.keyFlags = [enums.keyFlags.encryptCommunication | enums.keyFlags.encryptStorage]; + } + if (options.keyExpirationTime > 0) { + subkeySignaturePacket.keyExpirationTime = options.keyExpirationTime; + subkeySignaturePacket.keyNeverExpires = false; + } + await subkeySignaturePacket.sign(primaryKey, dataToSign, options.date); + return subkeySignaturePacket; } /** - * Generate ECDHE secret from private key and public part of ephemeral key using indutny/elliptic - * - * @param {Curve} curve Elliptic curve object - * @param {Uint8Array} V Public part of ephemeral key - * @param {Uint8Array} d Recipient private key - * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} + * Returns the preferred signature hash algorithm of a key + * @param {Key} [key] - The key to get preferences from + * @param {SecretKeyPacket|SecretSubkeyPacket} keyPacket - key packet used for signing + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} [userID] - User ID + * @param {Object} config - full configuration + * @returns {Promise} * @async */ -async function ellipticPrivateEphemeralKey(curve, V, d) { - V = curve.keyFromPublic(V); - d = curve.keyFromPrivate(d); - const secretKey = new Uint8Array(d.getPrivate()); - const S = d.derive(V); - const len = curve.curve.curve.p.byteLength(); - const sharedKey = S.toArrayLike(Uint8Array, 'be', len); - return { secretKey, sharedKey }; +async function getPreferredHashAlgo$1(key, keyPacket, date = new Date(), userID = {}, config) { + let hashAlgo = config.preferredHashAlgorithm; + let prefAlgo = hashAlgo; + if (key) { + const primaryUser = await key.getPrimaryUser(date, userID, config); + if (primaryUser.selfCertification.preferredHashAlgorithms) { + [prefAlgo] = primaryUser.selfCertification.preferredHashAlgorithms; + hashAlgo = mod.hash.getHashByteLength(hashAlgo) <= mod.hash.getHashByteLength(prefAlgo) ? + prefAlgo : hashAlgo; + } + } + switch (Object.getPrototypeOf(keyPacket)) { + case SecretKeyPacket.prototype: + case PublicKeyPacket.prototype: + case SecretSubkeyPacket.prototype: + case PublicSubkeyPacket.prototype: + switch (keyPacket.algorithm) { + case enums.publicKey.ecdh: + case enums.publicKey.ecdsa: + case enums.publicKey.eddsa: + prefAlgo = mod.publicKey.elliptic.getPreferredHashAlgo(keyPacket.publicParams.oid); + } + } + return mod.hash.getHashByteLength(hashAlgo) <= mod.hash.getHashByteLength(prefAlgo) ? + prefAlgo : hashAlgo; } /** - * Generate ECDHE ephemeral key and secret from public key using indutny/elliptic - * - * @param {Curve} curve Elliptic curve object - * @param {Uint8Array} Q Recipient public key - * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} + * Returns the preferred symmetric/aead/compression algorithm for a set of keys + * @param {'symmetric'|'aead'|'compression'} type - Type of preference to return + * @param {Array} [keys] - Set of keys + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Array} [userIDs] - User IDs + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} Preferred algorithm * @async */ -async function ellipticPublicEphemeralKey(curve, Q) { - const v = await curve.genKeyPair(); - Q = curve.keyFromPublic(Q); - const publicKey = new Uint8Array(v.getPublic()); - const S = v.derive(Q); - const len = curve.curve.curve.p.byteLength(); - const sharedKey = S.toArrayLike(Uint8Array, 'be', len); - return { publicKey, sharedKey }; +async function getPreferredAlgo(type, keys = [], date = new Date(), userIDs = [], config = defaultConfig) { + const defaultAlgo = { // these are all must-implement in rfc4880bis + 'symmetric': enums.symmetric.aes128, + 'aead': enums.aead.eax, + 'compression': enums.compression.uncompressed + }[type]; + const preferredSenderAlgo = { + 'symmetric': config.preferredSymmetricAlgorithm, + 'aead': config.preferredAEADAlgorithm, + 'compression': config.preferredCompressionAlgorithm + }[type]; + const prefPropertyName = { + 'symmetric': 'preferredSymmetricAlgorithms', + 'aead': 'preferredAEADAlgorithms', + 'compression': 'preferredCompressionAlgorithms' + }[type]; + + // if preferredSenderAlgo appears in the prefs of all recipients, we pick it + // otherwise we use the default algo + // if no keys are available, preferredSenderAlgo is returned + const senderAlgoSupport = await Promise.all(keys.map(async function(key, i) { + const primaryUser = await key.getPrimaryUser(date, userIDs[i], config); + const recipientPrefs = primaryUser.selfCertification[prefPropertyName]; + return !!recipientPrefs && recipientPrefs.indexOf(preferredSenderAlgo) >= 0; + })); + return senderAlgoSupport.every(Boolean) ? preferredSenderAlgo : defaultAlgo; } /** - * Generate ECDHE secret from private key and public part of ephemeral key using nodeCrypto - * - * @param {Curve} curve Elliptic curve object - * @param {Uint8Array} V Public part of ephemeral key - * @param {Uint8Array} d Recipient private key - * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ -async function nodePrivateEphemeralKey(curve, V, d) { - const recipient = nodeCrypto.createECDH(curve.node.node); - recipient.setPrivateKey(d); - const sharedKey = new Uint8Array(recipient.computeSecret(V)); - const secretKey = new Uint8Array(recipient.getPrivateKey()); - return { secretKey, sharedKey }; + * Create signature packet + * @param {Object} dataToSign - Contains packets to be signed + * @param {PrivateKey} privateKey - key to get preferences from + * @param {SecretKeyPacket| + * SecretSubkeyPacket} signingKeyPacket secret key packet for signing + * @param {Object} [signatureProperties] - Properties to write on the signature packet before signing + * @param {Date} [date] - Override the creationtime of the signature + * @param {Object} [userID] - User ID + * @param {Object} [detached] - Whether to create a detached signature packet + * @param {Object} config - full configuration + * @returns {Promise} Signature packet. + */ +async function createSignaturePacket(dataToSign, privateKey, signingKeyPacket, signatureProperties, date, userID, detached = false, config) { + if (signingKeyPacket.isDummy()) { + throw new Error('Cannot sign with a gnu-dummy key.'); + } + if (!signingKeyPacket.isDecrypted()) { + throw new Error('Signing key is not decrypted.'); + } + const signaturePacket = new SignaturePacket(); + Object.assign(signaturePacket, signatureProperties); + signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm; + signaturePacket.hashAlgorithm = await getPreferredHashAlgo$1(privateKey, signingKeyPacket, date, userID, config); + await signaturePacket.sign(signingKeyPacket, dataToSign, date, detached); + return signaturePacket; } /** - * Generate ECDHE ephemeral key and secret from public key using nodeCrypto - * - * @param {Curve} curve Elliptic curve object - * @param {Uint8Array} Q Recipient public key - * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} - * @async + * Merges signatures from source[attr] to dest[attr] + * @param {Object} source + * @param {Object} dest + * @param {String} attr + * @param {Date} [date] - date to use for signature expiration check, instead of the current time + * @param {Function} [checkFn] - signature only merged if true */ -async function nodePublicEphemeralKey(curve, Q) { - const sender = nodeCrypto.createECDH(curve.node.node); - sender.generateKeys(); - const sharedKey = new Uint8Array(sender.computeSecret(Q)); - const publicKey = new Uint8Array(sender.getPublicKey()); - return { publicKey, sharedKey }; +async function mergeSignatures(source, dest, attr, date = new Date(), checkFn) { + source = source[attr]; + if (source) { + if (!dest[attr].length) { + dest[attr] = source; + } else { + await Promise.all(source.map(async function(sourceSig) { + if (!sourceSig.isExpired(date) && (!checkFn || await checkFn(sourceSig)) && + !dest[attr].some(function(destSig) { + return util.equalsUint8Array(destSig.writeParams(), sourceSig.writeParams()); + })) { + dest[attr].push(sourceSig); + } + })); + } + } } /** - * @param {Integer} payloadSize ec payload size - * @param {String} name curve name - * @param {Uint8Array} publicKey public key - * @returns {JsonWebKey} public key in jwk format + * Checks if a given certificate or binding signature is revoked + * @param {SecretKeyPacket| + * PublicKeyPacket} primaryKey The primary key packet + * @param {Object} dataToVerify - The data to check + * @param {Array} revocations - The revocation signatures to check + * @param {SignaturePacket} signature - The certificate or signature to check + * @param {PublicSubkeyPacket| + * SecretSubkeyPacket| + * PublicKeyPacket| + * SecretKeyPacket} key, optional The key packet to verify the signature, instead of the primary key + * @param {Date} date - Use the given date instead of the current time + * @param {Object} config - Full configuration + * @returns {Promise} True if the signature revokes the data. + * @async */ -function rawPublicToJwk(payloadSize, name, publicKey) { - const len = payloadSize; - const bufX = publicKey.slice(1, len + 1); - const bufY = publicKey.slice(len + 1, len * 2 + 1); - // https://www.rfc-editor.org/rfc/rfc7518.txt - const jwKey = { - kty: "EC", - crv: name, - x: _util2.default.Uint8Array_to_b64(bufX, true), - y: _util2.default.Uint8Array_to_b64(bufY, true), - ext: true - }; - return jwKey; +async function isDataRevoked(primaryKey, signatureType, dataToVerify, revocations, signature, key, date = new Date(), config) { + key = key || primaryKey; + const revocationKeyIDs = []; + await Promise.all(revocations.map(async function(revocationSignature) { + try { + if ( + // Note: a third-party revocation signature could legitimately revoke a + // self-signature if the signature has an authorized revocation key. + // However, we don't support passing authorized revocation keys, nor + // verifying such revocation signatures. Instead, we indicate an error + // when parsing a key with an authorized revocation key, and ignore + // third-party revocation signatures here. (It could also be revoking a + // third-party key certification, which should only affect + // `verifyAllCertifications`.) + !signature || revocationSignature.issuerKeyID.equals(signature.issuerKeyID) + ) { + await revocationSignature.verify( + key, signatureType, dataToVerify, config.revocationsExpire ? date : null, false, config + ); + + // TODO get an identifier of the revoked object instead + revocationKeyIDs.push(revocationSignature.issuerKeyID); + } + } catch (e) {} + })); + // TODO further verify that this is the signature that should be revoked + if (signature) { + signature.revoked = revocationKeyIDs.some(keyID => keyID.equals(signature.issuerKeyID)) ? true : + signature.revoked || false; + return signature.revoked; + } + return revocationKeyIDs.length > 0; } /** - * @param {Integer} payloadSize ec payload size - * @param {String} name curve name - * @param {Uint8Array} publicKey public key - * @param {Uint8Array} privateKey private key - * @returns {JsonWebKey} private key in jwk format + * Returns key expiration time based on the given certification signature. + * The expiration time of the signature is ignored. + * @param {PublicSubkeyPacket|PublicKeyPacket} keyPacket - key to check + * @param {SignaturePacket} signature - signature to process + * @returns {Date|Infinity} expiration time or infinity if the key does not expire */ -function privateToJwk(payloadSize, name, privateKey, publicKey) { - const jwk = rawPublicToJwk(payloadSize, name, publicKey); - jwk.d = _util2.default.Uint8Array_to_b64(privateKey, true); - return jwk; +function getKeyExpirationTime(keyPacket, signature) { + let expirationTime; + // check V4 expiration time + if (signature.keyNeverExpires === false) { + expirationTime = keyPacket.created.getTime() + signature.keyExpirationTime * 1000; + } + return expirationTime ? new Date(expirationTime) : Infinity; } /** - * @param {JsonWebKey} jwk key for conversion - * @returns {Uint8Array} raw public key + * Returns whether aead is supported by all keys in the set + * @param {Array} keys - Set of keys + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Array} [userIDs] - User IDs + * @param {Object} config - full configuration + * @returns {Promise} + * @async */ -function jwkToRawPublic(jwk) { - const bufX = _util2.default.b64_to_Uint8Array(jwk.x); - const bufY = _util2.default.b64_to_Uint8Array(jwk.y); - const publicKey = new Uint8Array(bufX.length + bufY.length + 1); - publicKey[0] = 0x04; - publicKey.set(bufX, 1); - publicKey.set(bufY, bufX.length + 1); - return publicKey; +async function isAEADSupported(keys, date = new Date(), userIDs = [], config = defaultConfig) { + let supported = true; + // TODO replace when Promise.some or Promise.any are implemented + await Promise.all(keys.map(async function(key, i) { + const primaryUser = await key.getPrimaryUser(date, userIDs[i], config); + if (!primaryUser.selfCertification.features || + !(primaryUser.selfCertification.features[0] & enums.features.aead)) { + supported = false; + } + })); + return supported; } -exports.default = { encrypt, decrypt, genPublicEphemeralKey, genPrivateEphemeralKey, buildEcdhParam, kdf, webPublicEphemeralKey, webPrivateEphemeralKey, ellipticPublicEphemeralKey, ellipticPrivateEphemeralKey, nodePublicEphemeralKey, nodePrivateEphemeralKey }; +function sanitizeKeyOptions(options, subkeyDefaults = {}) { + options.type = options.type || subkeyDefaults.type; + options.curve = options.curve || subkeyDefaults.curve; + options.rsaBits = options.rsaBits || subkeyDefaults.rsaBits; + options.keyExpirationTime = options.keyExpirationTime !== undefined ? options.keyExpirationTime : subkeyDefaults.keyExpirationTime; + options.passphrase = util.isString(options.passphrase) ? options.passphrase : subkeyDefaults.passphrase; + options.date = options.date || subkeyDefaults.date; -},{"../../../enums":113,"../../../type/kdf_params":147,"../../../util":152,"../../aes_kw":80,"../../cipher":86,"../../hash":92,"./curves":100,"bn.js":16,"tweetnacl/nacl-fast-light.js":72}],102:[function(require,module,exports){ -'use strict'; + options.sign = options.sign || false; -Object.defineProperty(exports, "__esModule", { - value: true -}); + switch (options.type) { + case 'ecc': + try { + options.curve = enums.write(enums.curve, options.curve); + } catch (e) { + throw new Error('Invalid curve'); + } + if (options.curve === enums.curve.ed25519 || options.curve === enums.curve.curve25519) { + options.curve = options.sign ? enums.curve.ed25519 : enums.curve.curve25519; + } + if (options.sign) { + options.algorithm = options.curve === enums.curve.ed25519 ? enums.publicKey.eddsa : enums.publicKey.ecdsa; + } else { + options.algorithm = enums.publicKey.ecdh; + } + break; + case 'rsa': + options.algorithm = enums.publicKey.rsaEncryptSign; + break; + default: + throw new Error(`Unsupported key type ${options.type}`); + } + return options; +} -var _curves = require('./curves'); +function isValidSigningKeyPacket(keyPacket, signature) { + const keyAlgo = keyPacket.algorithm; + return keyAlgo !== enums.publicKey.rsaEncrypt && + keyAlgo !== enums.publicKey.elgamal && + keyAlgo !== enums.publicKey.ecdh && + (!signature.keyFlags || + (signature.keyFlags[0] & enums.keyFlags.signData) !== 0); +} -var _curves2 = _interopRequireDefault(_curves); +function isValidEncryptionKeyPacket(keyPacket, signature) { + const keyAlgo = keyPacket.algorithm; + return keyAlgo !== enums.publicKey.dsa && + keyAlgo !== enums.publicKey.rsaSign && + keyAlgo !== enums.publicKey.ecdsa && + keyAlgo !== enums.publicKey.eddsa && + (!signature.keyFlags || + (signature.keyFlags[0] & enums.keyFlags.encryptCommunication) !== 0 || + (signature.keyFlags[0] & enums.keyFlags.encryptStorage) !== 0); +} -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +function isValidDecryptionKeyPacket(signature, config) { + if (config.allowInsecureDecryptionWithSigningKeys) { + // This is only relevant for RSA keys, all other signing algorithms cannot decrypt + return true; + } -/** - * Sign a message using the provided key - * @param {module:type/oid} oid Elliptic curve object identifier - * @param {module:enums.hash} hash_algo Hash algorithm used to sign - * @param {Uint8Array} m Message to sign - * @param {Uint8Array} d Private key used to sign the message - * @param {Uint8Array} hashed The hashed message - * @returns {{r: Uint8Array, - * s: Uint8Array}} Signature of the message - * @async - */ -async function sign(oid, hash_algo, m, d, hashed) { - const curve = new _curves2.default(oid); - const key = curve.keyFromPrivate(d); - const signature = await key.sign(m, hash_algo, hashed); - return { - r: signature.r.toArrayLike(Uint8Array), - s: signature.s.toArrayLike(Uint8Array) - }; + return !signature.keyFlags || + (signature.keyFlags[0] & enums.keyFlags.encryptCommunication) !== 0 || + (signature.keyFlags[0] & enums.keyFlags.encryptStorage) !== 0; } /** - * Verifies if a signature is valid for a message - * @param {module:type/oid} oid Elliptic curve object identifier - * @param {module:enums.hash} hash_algo Hash algorithm used in the signature - * @param {{r: Uint8Array, - s: Uint8Array}} signature Signature to verify - * @param {Uint8Array} m Message to verify - * @param {Uint8Array} Q Public key used to verify the message - * @param {Uint8Array} hashed The hashed message - * @returns {Boolean} - * @async - */ -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2015-2016 Decentral -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @fileoverview Implementation of ECDSA following RFC6637 for Openpgpjs - * @requires crypto/public_key/elliptic/curve - * @module crypto/public_key/elliptic/ecdsa + * Check key against blacklisted algorithms and minimum strength requirements. + * @param {SecretKeyPacket|PublicKeyPacket| + * SecretSubkeyPacket|PublicSubkeyPacket} keyPacket + * @param {Config} config + * @throws {Error} if the key packet does not meet the requirements */ - -async function verify(oid, hash_algo, signature, m, Q, hashed) { - const curve = new _curves2.default(oid); - const key = curve.keyFromPublic(Q); - return key.verify(m, signature, hash_algo, hashed); +function checkKeyRequirements(keyPacket, config) { + const keyAlgo = enums.write(enums.publicKey, keyPacket.algorithm); + const algoInfo = keyPacket.getAlgorithmInfo(); + if (config.rejectPublicKeyAlgorithms.has(keyAlgo)) { + throw new Error(`${algoInfo.algorithm} keys are considered too weak.`); + } + switch (keyAlgo) { + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaSign: + case enums.publicKey.rsaEncrypt: + if (algoInfo.bits < config.minRSABits) { + throw new Error(`RSA keys shorter than ${config.minRSABits} bits are considered too weak.`); + } + break; + case enums.publicKey.ecdsa: + case enums.publicKey.eddsa: + case enums.publicKey.ecdh: + if (config.rejectCurves.has(algoInfo.curve)) { + throw new Error(`Support for ${algoInfo.algorithm} keys using curve ${algoInfo.curve} is disabled.`); + } + break; + } } -exports.default = { sign, verify }; - -},{"./curves":100}],103:[function(require,module,exports){ -'use strict'; +/** + * @module key/User + * @private + */ -Object.defineProperty(exports, "__esModule", { - value: true -}); +/** + * Class that represents an user ID or attribute packet and the relevant signatures. + * @param {UserIDPacket|UserAttributePacket} userPacket - packet containing the user info + * @param {Key} mainKey - reference to main Key object containing the primary key and subkeys that the user is associated with + */ +class User { + constructor(userPacket, mainKey) { + this.userID = userPacket.constructor.tag === enums.packet.userID ? userPacket : null; + this.userAttribute = userPacket.constructor.tag === enums.packet.userAttribute ? userPacket : null; + this.selfCertifications = []; + this.otherCertifications = []; + this.revocationSignatures = []; + this.mainKey = mainKey; + } -var _ = require('hash.js/lib/hash/sha/512'); + /** + * Transforms structured user data to packetlist + * @returns {PacketList} + */ + toPacketList() { + const packetlist = new PacketList(); + packetlist.push(this.userID || this.userAttribute); + packetlist.push(...this.revocationSignatures); + packetlist.push(...this.selfCertifications); + packetlist.push(...this.otherCertifications); + return packetlist; + } -var _2 = _interopRequireDefault(_); + /** + * Shallow clone + * @returns {User} + */ + clone() { + const user = new User(this.userID || this.userAttribute, this.mainKey); + user.selfCertifications = [...this.selfCertifications]; + user.otherCertifications = [...this.otherCertifications]; + user.revocationSignatures = [...this.revocationSignatures]; + return user; + } -var _naclFastLight = require('tweetnacl/nacl-fast-light.js'); + /** + * Generate third-party certifications over this user and its primary key + * @param {Array} signingKeys - Decrypted private keys for signing + * @param {Date} [date] - Date to use as creation date of the certificate, instead of the current time + * @param {Object} config - Full configuration + * @returns {Promise} New user with new certifications. + * @async + */ + async certify(signingKeys, date, config) { + const primaryKey = this.mainKey.keyPacket; + const dataToSign = { + userID: this.userID, + userAttribute: this.userAttribute, + key: primaryKey + }; + const user = new User(dataToSign.userID || dataToSign.userAttribute, this.mainKey); + user.otherCertifications = await Promise.all(signingKeys.map(async function(privateKey) { + if (!privateKey.isPrivate()) { + throw new Error('Need private key for signing'); + } + if (privateKey.hasSameFingerprintAs(primaryKey)) { + throw new Error("The user's own key can only be used for self-certifications"); + } + const signingKey = await privateKey.getSigningKey(undefined, date, undefined, config); + return createSignaturePacket(dataToSign, privateKey, signingKey.keyPacket, { + // Most OpenPGP implementations use generic certification (0x10) + signatureType: enums.signature.certGeneric, + keyFlags: [enums.keyFlags.certifyKeys | enums.keyFlags.signData] + }, date, undefined, undefined, config); + })); + await user.update(this, date, config); + return user; + } -var _naclFastLight2 = _interopRequireDefault(_naclFastLight); + /** + * Checks if a given certificate of the user is revoked + * @param {SignaturePacket} certificate - The certificate to verify + * @param {PublicSubkeyPacket| + * SecretSubkeyPacket| + * PublicKeyPacket| + * SecretKeyPacket} [keyPacket] The key packet to verify the signature, instead of the primary key + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} config - Full configuration + * @returns {Promise} True if the certificate is revoked. + * @async + */ + async isRevoked(certificate, keyPacket, date = new Date(), config) { + const primaryKey = this.mainKey.keyPacket; + return isDataRevoked(primaryKey, enums.signature.certRevocation, { + key: primaryKey, + userID: this.userID, + userAttribute: this.userAttribute + }, this.revocationSignatures, certificate, keyPacket, date, config); + } -var _util = require('../../../util'); + /** + * Verifies the user certificate. + * @param {SignaturePacket} certificate - A certificate of this user + * @param {Array} verificationKeys - Array of keys to verify certificate signatures + * @param {Date} [date] - Use the given date instead of the current time + * @param {Object} config - Full configuration + * @returns {Promise} true if the certificate could be verified, or null if the verification keys do not correspond to the certificate + * @throws if the user certificate is invalid. + * @async + */ + async verifyCertificate(certificate, verificationKeys, date = new Date(), config) { + const that = this; + const primaryKey = this.mainKey.keyPacket; + const dataToVerify = { + userID: this.userID, + userAttribute: this.userAttribute, + key: primaryKey + }; + const { issuerKeyID } = certificate; + const issuerKeys = verificationKeys.filter(key => key.getKeys(issuerKeyID).length > 0); + if (issuerKeys.length === 0) { + return null; + } + await Promise.all(issuerKeys.map(async key => { + const signingKey = await key.getSigningKey(issuerKeyID, certificate.created, undefined, config); + if (certificate.revoked || await that.isRevoked(certificate, signingKey.keyPacket, date, config)) { + throw new Error('User certificate is revoked'); + } + try { + await certificate.verify(signingKey.keyPacket, enums.signature.certGeneric, dataToVerify, date, undefined, config); + } catch (e) { + throw util.wrapError('User certificate is invalid', e); + } + })); + return true; + } -var _util2 = _interopRequireDefault(_util); + /** + * Verifies all user certificates + * @param {Array} verificationKeys - Array of keys to verify certificate signatures + * @param {Date} [date] - Use the given date instead of the current time + * @param {Object} config - Full configuration + * @returns {Promise>} List of signer's keyID and validity of signature. + * Signature validity is null if the verification keys do not correspond to the certificate. + * @async + */ + async verifyAllCertifications(verificationKeys, date = new Date(), config) { + const that = this; + const certifications = this.selfCertifications.concat(this.otherCertifications); + return Promise.all(certifications.map(async certification => ({ + keyID: certification.issuerKeyID, + valid: await that.verifyCertificate(certification, verificationKeys, date, config).catch(() => false) + }))); + } -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + /** + * Verify User. Checks for existence of self signatures, revocation signatures + * and validity of self signature. + * @param {Date} date - Use the given date instead of the current time + * @param {Object} config - Full configuration + * @returns {Promise} Status of user. + * @throws {Error} if there are no valid self signatures. + * @async + */ + async verify(date = new Date(), config) { + if (!this.selfCertifications.length) { + throw new Error('No self-certifications found'); + } + const that = this; + const primaryKey = this.mainKey.keyPacket; + const dataToVerify = { + userID: this.userID, + userAttribute: this.userAttribute, + key: primaryKey + }; + // TODO replace when Promise.some or Promise.any are implemented + let exception; + for (let i = this.selfCertifications.length - 1; i >= 0; i--) { + try { + const selfCertification = this.selfCertifications[i]; + if (selfCertification.revoked || await that.isRevoked(selfCertification, undefined, date, config)) { + throw new Error('Self-certification is revoked'); + } + try { + await selfCertification.verify(primaryKey, enums.signature.certGeneric, dataToVerify, date, undefined, config); + } catch (e) { + throw util.wrapError('Self-certification is invalid', e); + } + return true; + } catch (e) { + exception = e; + } + } + throw exception; + } -_naclFastLight2.default.hash = bytes => new Uint8Array((0, _2.default)().update(bytes).digest()); + /** + * Update user with new components from specified user + * @param {User} sourceUser - Source user to merge + * @param {Date} date - Date to verify the validity of signatures + * @param {Object} config - Full configuration + * @returns {Promise} + * @async + */ + async update(sourceUser, date, config) { + const primaryKey = this.mainKey.keyPacket; + const dataToVerify = { + userID: this.userID, + userAttribute: this.userAttribute, + key: primaryKey + }; + // self signatures + await mergeSignatures(sourceUser, this, 'selfCertifications', date, async function(srcSelfSig) { + try { + await srcSelfSig.verify(primaryKey, enums.signature.certGeneric, dataToVerify, date, false, config); + return true; + } catch (e) { + return false; + } + }); + // other signatures + await mergeSignatures(sourceUser, this, 'otherCertifications', date); + // revocation signatures + await mergeSignatures(sourceUser, this, 'revocationSignatures', date, function(srcRevSig) { + return isDataRevoked(primaryKey, enums.signature.certRevocation, dataToVerify, [srcRevSig], undefined, undefined, date, config); + }); + } +} /** - * Sign a message using the provided key - * @param {module:type/oid} oid Elliptic curve object identifier - * @param {module:enums.hash} hash_algo Hash algorithm used to sign - * @param {Uint8Array} m Message to sign - * @param {Uint8Array} d Private key used to sign - * @param {Uint8Array} hashed The hashed message - * @returns {{R: Uint8Array, - * S: Uint8Array}} Signature of the message - * @async + * @module key/Subkey + * @private */ -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2018 Proton Technologies AG -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /** - * @fileoverview Implementation of EdDSA following RFC4880bis-03 for OpenPGP - * @requires hash.js - * @requires tweetnacl - * @requires crypto/public_key/elliptic/curve - * @requires util - * @module crypto/public_key/elliptic/eddsa + * Class that represents a subkey packet and the relevant signatures. + * @borrows PublicSubkeyPacket#getKeyID as Subkey#getKeyID + * @borrows PublicSubkeyPacket#getFingerprint as Subkey#getFingerprint + * @borrows PublicSubkeyPacket#hasSameFingerprintAs as Subkey#hasSameFingerprintAs + * @borrows PublicSubkeyPacket#getAlgorithmInfo as Subkey#getAlgorithmInfo + * @borrows PublicSubkeyPacket#getCreationTime as Subkey#getCreationTime + * @borrows PublicSubkeyPacket#isDecrypted as Subkey#isDecrypted */ +class Subkey { + /** + * @param {SecretSubkeyPacket|PublicSubkeyPacket} subkeyPacket - subkey packet to hold in the Subkey + * @param {Key} mainKey - reference to main Key object, containing the primary key packet corresponding to the subkey + */ + constructor(subkeyPacket, mainKey) { + this.keyPacket = subkeyPacket; + this.bindingSignatures = []; + this.revocationSignatures = []; + this.mainKey = mainKey; + } -async function sign(oid, hash_algo, m, d, hashed) { - var _nacl$sign$keyPair$fr = _naclFastLight2.default.sign.keyPair.fromSeed(d); + /** + * Transforms structured subkey data to packetlist + * @returns {PacketList} + */ + toPacketList() { + const packetlist = new PacketList(); + packetlist.push(this.keyPacket); + packetlist.push(...this.revocationSignatures); + packetlist.push(...this.bindingSignatures); + return packetlist; + } - const secretKey = _nacl$sign$keyPair$fr.secretKey; + /** + * Shallow clone + * @return {Subkey} + */ + clone() { + const subkey = new Subkey(this.keyPacket, this.mainKey); + subkey.bindingSignatures = [...this.bindingSignatures]; + subkey.revocationSignatures = [...this.revocationSignatures]; + return subkey; + } - const signature = _naclFastLight2.default.sign.detached(hashed, secretKey); - // EdDSA signature params are returned in little-endian format - return { - R: signature.subarray(0, 32), - S: signature.subarray(32) - }; -} + /** + * Checks if a binding signature of a subkey is revoked + * @param {SignaturePacket} signature - The binding signature to verify + * @param {PublicSubkeyPacket| + * SecretSubkeyPacket| + * PublicKeyPacket| + * SecretKeyPacket} key, optional The key to verify the signature + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} True if the binding signature is revoked. + * @async + */ + async isRevoked(signature, key, date = new Date(), config = defaultConfig) { + const primaryKey = this.mainKey.keyPacket; + return isDataRevoked( + primaryKey, enums.signature.subkeyRevocation, { + key: primaryKey, + bind: this.keyPacket + }, this.revocationSignatures, signature, key, date, config + ); + } -/** - * Verifies if a signature is valid for a message - * @param {module:type/oid} oid Elliptic curve object identifier - * @param {module:enums.hash} hash_algo Hash algorithm used in the signature - * @param {{R: Uint8Array, - S: Uint8Array}} signature Signature to verify the message - * @param {Uint8Array} m Message to verify - * @param {Uint8Array} publicKey Public key used to verify the message - * @param {Uint8Array} hashed The hashed message - * @returns {Boolean} - * @async - */ -async function verify(oid, hash_algo, { R, S }, m, publicKey, hashed) { - const signature = _util2.default.concatUint8Array([R, S]); - return _naclFastLight2.default.sign.detached.verify(hashed, signature, publicKey.subarray(1)); -} + /** + * Verify subkey. Checks for revocation signatures, expiration time + * and valid binding signature. + * @param {Date} date - Use the given date instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} + * @throws {Error} if the subkey is invalid. + * @async + */ + async verify(date = new Date(), config = defaultConfig) { + const primaryKey = this.mainKey.keyPacket; + const dataToVerify = { key: primaryKey, bind: this.keyPacket }; + // check subkey binding signatures + const bindingSignature = await getLatestValidSignature(this.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); + // check binding signature is not revoked + if (bindingSignature.revoked || await this.isRevoked(bindingSignature, null, date, config)) { + throw new Error('Subkey is revoked'); + } + // check for expiration time + if (isDataExpired(this.keyPacket, bindingSignature, date)) { + throw new Error('Subkey is expired'); + } + return bindingSignature; + } -exports.default = { sign, verify }; + /** + * Returns the expiration time of the subkey or Infinity if key does not expire. + * Returns null if the subkey is invalid. + * @param {Date} date - Use the given date instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} + * @async + */ + async getExpirationTime(date = new Date(), config = defaultConfig) { + const primaryKey = this.mainKey.keyPacket; + const dataToVerify = { key: primaryKey, bind: this.keyPacket }; + let bindingSignature; + try { + bindingSignature = await getLatestValidSignature(this.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); + } catch (e) { + return null; + } + const keyExpiry = getKeyExpirationTime(this.keyPacket, bindingSignature); + const sigExpiry = bindingSignature.getExpirationTime(); + return keyExpiry < sigExpiry ? keyExpiry : sigExpiry; + } -},{"../../../util":152,"hash.js/lib/hash/sha/512":43,"tweetnacl/nacl-fast-light.js":72}],104:[function(require,module,exports){ -'use strict'; + /** + * Update subkey with new components from specified subkey + * @param {Subkey} subkey - Source subkey to merge + * @param {Date} [date] - Date to verify validity of signatures + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if update failed + * @async + */ + async update(subkey, date = new Date(), config = defaultConfig) { + const primaryKey = this.mainKey.keyPacket; + if (!this.hasSameFingerprintAs(subkey)) { + throw new Error('Subkey update method: fingerprints of subkeys not equal'); + } + // key packet + if (this.keyPacket.constructor.tag === enums.packet.publicSubkey && + subkey.keyPacket.constructor.tag === enums.packet.secretSubkey) { + this.keyPacket = subkey.keyPacket; + } + // update missing binding signatures + const that = this; + const dataToVerify = { key: primaryKey, bind: that.keyPacket }; + await mergeSignatures(subkey, this, 'bindingSignatures', date, async function(srcBindSig) { + for (let i = 0; i < that.bindingSignatures.length; i++) { + if (that.bindingSignatures[i].issuerKeyID.equals(srcBindSig.issuerKeyID)) { + if (srcBindSig.created > that.bindingSignatures[i].created) { + that.bindingSignatures[i] = srcBindSig; + } + return false; + } + } + try { + await srcBindSig.verify(primaryKey, enums.signature.subkeyBinding, dataToVerify, date, undefined, config); + return true; + } catch (e) { + return false; + } + }); + // revocation signatures + await mergeSignatures(subkey, this, 'revocationSignatures', date, function(srcRevSig) { + return isDataRevoked(primaryKey, enums.signature.subkeyRevocation, dataToVerify, [srcRevSig], undefined, undefined, date, config); + }); + } + + /** + * Revokes the subkey + * @param {SecretKeyPacket} primaryKey - decrypted private primary key for revocation + * @param {Object} reasonForRevocation - optional, object indicating the reason for revocation + * @param {module:enums.reasonForRevocation} reasonForRevocation.flag optional, flag indicating the reason for revocation + * @param {String} reasonForRevocation.string optional, string explaining the reason for revocation + * @param {Date} date - optional, override the creationtime of the revocation signature + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New subkey with revocation signature. + * @async + */ + async revoke( + primaryKey, + { + flag: reasonForRevocationFlag = enums.reasonForRevocation.noReason, + string: reasonForRevocationString = '' + } = {}, + date = new Date(), + config = defaultConfig + ) { + const dataToSign = { key: primaryKey, bind: this.keyPacket }; + const subkey = new Subkey(this.keyPacket, this.mainKey); + subkey.revocationSignatures.push(await createSignaturePacket(dataToSign, null, primaryKey, { + signatureType: enums.signature.subkeyRevocation, + reasonForRevocationFlag: enums.write(enums.reasonForRevocation, reasonForRevocationFlag), + reasonForRevocationString + }, date, undefined, false, config)); + await subkey.update(this); + return subkey; + } -Object.defineProperty(exports, "__esModule", { - value: true + hasSameFingerprintAs(other) { + return this.keyPacket.hasSameFingerprintAs(other.keyPacket || other); + } +} + +['getKeyID', 'getFingerprint', 'getAlgorithmInfo', 'getCreationTime', 'isDecrypted'].forEach(name => { + Subkey.prototype[name] = + function() { + return this.keyPacket[name](); + }; }); -var _curves = require('./curves'); +// GPG4Browsers - An OpenPGP implementation in javascript + +// A key revocation certificate can contain the following packets +const allowedRevocationPackets = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); + +/** + * Abstract class that represents an OpenPGP key. Must contain a primary key. + * Can contain additional subkeys, signatures, user ids, user attributes. + * @borrows PublicKeyPacket#getKeyID as Key#getKeyID + * @borrows PublicKeyPacket#getFingerprint as Key#getFingerprint + * @borrows PublicKeyPacket#hasSameFingerprintAs as Key#hasSameFingerprintAs + * @borrows PublicKeyPacket#getAlgorithmInfo as Key#getAlgorithmInfo + * @borrows PublicKeyPacket#getCreationTime as Key#getCreationTime + */ +class Key { + /** + * Transforms packetlist to structured key data + * @param {PacketList} packetlist - The packets that form a key + * @param {Set} disallowedPackets - disallowed packet tags + */ + packetListToStructure(packetlist, disallowedPackets = new Set()) { + let user; + let primaryKeyID; + let subkey; + for (const packet of packetlist) { + const tag = packet.constructor.tag; + if (disallowedPackets.has(tag)) { + throw new Error(`Unexpected packet type: ${tag}`); + } + switch (tag) { + case enums.packet.publicKey: + case enums.packet.secretKey: + if (this.keyPacket) { + throw new Error('Key block contains multiple keys'); + } + this.keyPacket = packet; + primaryKeyID = this.getKeyID(); + if (!primaryKeyID) { + throw new Error('Missing Key ID'); + } + break; + case enums.packet.userID: + case enums.packet.userAttribute: + user = new User(packet, this); + this.users.push(user); + break; + case enums.packet.publicSubkey: + case enums.packet.secretSubkey: + user = null; + subkey = new Subkey(packet, this); + this.subkeys.push(subkey); + break; + case enums.packet.signature: + switch (packet.signatureType) { + case enums.signature.certGeneric: + case enums.signature.certPersona: + case enums.signature.certCasual: + case enums.signature.certPositive: + if (!user) { + util.printDebug('Dropping certification signatures without preceding user packet'); + continue; + } + if (packet.issuerKeyID.equals(primaryKeyID)) { + user.selfCertifications.push(packet); + } else { + user.otherCertifications.push(packet); + } + break; + case enums.signature.certRevocation: + if (user) { + user.revocationSignatures.push(packet); + } else { + this.directSignatures.push(packet); + } + break; + case enums.signature.key: + this.directSignatures.push(packet); + break; + case enums.signature.subkeyBinding: + if (!subkey) { + util.printDebug('Dropping subkey binding signature without preceding subkey packet'); + continue; + } + subkey.bindingSignatures.push(packet); + break; + case enums.signature.keyRevocation: + this.revocationSignatures.push(packet); + break; + case enums.signature.subkeyRevocation: + if (!subkey) { + util.printDebug('Dropping subkey revocation signature without preceding subkey packet'); + continue; + } + subkey.revocationSignatures.push(packet); + break; + } + break; + } + } + } + + /** + * Transforms structured key data to packetlist + * @returns {PacketList} The packets that form a key. + */ + toPacketList() { + const packetlist = new PacketList(); + packetlist.push(this.keyPacket); + packetlist.push(...this.revocationSignatures); + packetlist.push(...this.directSignatures); + this.users.map(user => packetlist.push(...user.toPacketList())); + this.subkeys.map(subkey => packetlist.push(...subkey.toPacketList())); + return packetlist; + } + + /** + * Clones the key object + * @param {Boolean} [deep=false] Whether to return a deep clone + * @returns {Promise} Clone of the key. + */ + clone(deep = false) { + const key = new this.constructor(this.toPacketList()); + if (deep) { + key.getKeys().forEach(k => { + // shallow clone the key packets + k.keyPacket = Object.create( + Object.getPrototypeOf(k.keyPacket), + Object.getOwnPropertyDescriptors(k.keyPacket) + ); + if (!k.keyPacket.isDecrypted()) return; + // deep clone the private params, which are cleared during encryption + const privateParams = {}; + Object.keys(k.keyPacket.privateParams).forEach(name => { + privateParams[name] = new Uint8Array(k.keyPacket.privateParams[name]); + }); + k.keyPacket.privateParams = privateParams; + }); + } + return key; + } -var _curves2 = _interopRequireDefault(_curves); + /** + * Returns an array containing all public or private subkeys matching keyID; + * If no keyID is given, returns all subkeys. + * @param {type/keyID} [keyID] - key ID to look for + * @returns {Array} array of subkeys + */ + getSubkeys(keyID = null) { + const subkeys = this.subkeys.filter(subkey => ( + !keyID || subkey.getKeyID().equals(keyID, true) + )); + return subkeys; + } -var _ecdsa = require('./ecdsa'); + /** + * Returns an array containing all public or private keys matching keyID. + * If no keyID is given, returns all keys, starting with the primary key. + * @param {type/keyid~KeyID} [keyID] - key ID to look for + * @returns {Array} array of keys + */ + getKeys(keyID = null) { + const keys = []; + if (!keyID || this.getKeyID().equals(keyID, true)) { + keys.push(this); + } + return keys.concat(this.getSubkeys(keyID)); + } -var _ecdsa2 = _interopRequireDefault(_ecdsa); + /** + * Returns key IDs of all keys + * @returns {Array} + */ + getKeyIDs() { + return this.getKeys().map(key => key.getKeyID()); + } -var _eddsa = require('./eddsa'); + /** + * Returns userIDs + * @returns {Array} Array of userIDs. + */ + getUserIDs() { + return this.users.map(user => { + return user.userID ? user.userID.userID : null; + }).filter(userID => userID !== null); + } -var _eddsa2 = _interopRequireDefault(_eddsa); + /** + * Returns binary encoded key + * @returns {Uint8Array} Binary key. + */ + write() { + return this.toPacketList().write(); + } -var _ecdh = require('./ecdh'); + /** + * Returns last created key or key by given keyID that is available for signing and verification + * @param {module:type/keyid~KeyID} [keyID] - key ID of a specific key to retrieve + * @param {Date} [date] - use the fiven date date to to check key validity instead of the current date + * @param {Object} [userID] - filter keys for the given user ID + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} signing key + * @throws if no valid signing key was found + * @async + */ + async getSigningKey(keyID = null, date = new Date(), userID = {}, config = defaultConfig) { + await this.verifyPrimaryKey(date, userID, config); + const primaryKey = this.keyPacket; + const subkeys = this.subkeys.slice().sort((a, b) => b.keyPacket.created - a.keyPacket.created); + let exception; + for (const subkey of subkeys) { + if (!keyID || subkey.getKeyID().equals(keyID)) { + try { + await subkey.verify(date, config); + const dataToVerify = { key: primaryKey, bind: subkey.keyPacket }; + const bindingSignature = await getLatestValidSignature( + subkey.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config + ); + if (!isValidSigningKeyPacket(subkey.keyPacket, bindingSignature)) { + continue; + } + if (!bindingSignature.embeddedSignature) { + throw new Error('Missing embedded signature'); + } + // verify embedded signature + await getLatestValidSignature( + [bindingSignature.embeddedSignature], subkey.keyPacket, enums.signature.keyBinding, dataToVerify, date, config + ); + checkKeyRequirements(subkey.keyPacket, config); + return subkey; + } catch (e) { + exception = e; + } + } + } -var _ecdh2 = _interopRequireDefault(_ecdh); + try { + const primaryUser = await this.getPrimaryUser(date, userID, config); + if ((!keyID || primaryKey.getKeyID().equals(keyID)) && + isValidSigningKeyPacket(primaryKey, primaryUser.selfCertification, config)) { + checkKeyRequirements(primaryKey, config); + return this; + } + } catch (e) { + exception = e; + } + throw util.wrapError('Could not find valid signing key packet in key ' + this.getKeyID().toHex(), exception); + } -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + /** + * Returns last created key or key by given keyID that is available for encryption or decryption + * @param {module:type/keyid~KeyID} [keyID] - key ID of a specific key to retrieve + * @param {Date} [date] - use the fiven date date to to check key validity instead of the current date + * @param {Object} [userID] - filter keys for the given user ID + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} encryption key + * @throws if no valid encryption key was found + * @async + */ + async getEncryptionKey(keyID, date = new Date(), userID = {}, config = defaultConfig) { + await this.verifyPrimaryKey(date, userID, config); + const primaryKey = this.keyPacket; + // V4: by convention subkeys are preferred for encryption service + const subkeys = this.subkeys.slice().sort((a, b) => b.keyPacket.created - a.keyPacket.created); + let exception; + for (const subkey of subkeys) { + if (!keyID || subkey.getKeyID().equals(keyID)) { + try { + await subkey.verify(date, config); + const dataToVerify = { key: primaryKey, bind: subkey.keyPacket }; + const bindingSignature = await getLatestValidSignature(subkey.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); + if (isValidEncryptionKeyPacket(subkey.keyPacket, bindingSignature)) { + checkKeyRequirements(subkey.keyPacket, config); + return subkey; + } + } catch (e) { + exception = e; + } + } + } -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2015-2016 Decentral -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + try { + // if no valid subkey for encryption, evaluate primary key + const primaryUser = await this.getPrimaryUser(date, userID, config); + if ((!keyID || primaryKey.getKeyID().equals(keyID)) && + isValidEncryptionKeyPacket(primaryKey, primaryUser.selfCertification)) { + checkKeyRequirements(primaryKey, config); + return this; + } + } catch (e) { + exception = e; + } + throw util.wrapError('Could not find valid encryption key packet in key ' + this.getKeyID().toHex(), exception); + } -/** - * @fileoverview Functions to access Elliptic Curve Cryptography - * @see module:crypto/public_key/elliptic/curve - * @see module:crypto/public_key/elliptic/ecdh - * @see module:crypto/public_key/elliptic/ecdsa - * @see module:crypto/public_key/elliptic/eddsa - * @module crypto/public_key/elliptic - */ + /** + * Checks if a signature on a key is revoked + * @param {SignaturePacket} signature - The signature to verify + * @param {PublicSubkeyPacket| + * SecretSubkeyPacket| + * PublicKeyPacket| + * SecretKeyPacket} key, optional The key to verify the signature + * @param {Date} [date] - Use the given date for verification, instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} True if the certificate is revoked. + * @async + */ + async isRevoked(signature, key, date = new Date(), config = defaultConfig) { + return isDataRevoked( + this.keyPacket, enums.signature.keyRevocation, { key: this.keyPacket }, this.revocationSignatures, signature, key, date, config + ); + } -exports.default = { - Curve: _curves2.default, ecdh: _ecdh2.default, ecdsa: _ecdsa2.default, eddsa: _eddsa2.default, generate: _curves.generate, getPreferredHashAlgo: _curves.getPreferredHashAlgo -}; + /** + * Verify primary key. Checks for revocation signatures, expiration time + * and valid self signature. Throws if the primary key is invalid. + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} [userID] - User ID + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} If key verification failed + * @async + */ + async verifyPrimaryKey(date = new Date(), userID = {}, config = defaultConfig) { + const primaryKey = this.keyPacket; + // check for key revocation signatures + if (await this.isRevoked(null, null, date, config)) { + throw new Error('Primary key is revoked'); + } + // check for valid, unrevoked, unexpired self signature + const { selfCertification } = await this.getPrimaryUser(date, userID, config); + // check for expiration time in binding signatures + if (isDataExpired(primaryKey, selfCertification, date)) { + throw new Error('Primary key is expired'); + } + // check for expiration time in direct signatures + const directSignature = await getLatestValidSignature( + this.directSignatures, primaryKey, enums.signature.key, { key: primaryKey }, date, config + ).catch(() => {}); // invalid signatures are discarded, to avoid breaking the key -},{"./curves":100,"./ecdh":101,"./ecdsa":102,"./eddsa":103}],105:[function(require,module,exports){ -'use strict'; + if (directSignature && isDataExpired(primaryKey, directSignature, date)) { + throw new Error('Primary key is expired'); + } + } -Object.defineProperty(exports, "__esModule", { - value: true -}); + /** + * Returns the expiration date of the primary key, considering self-certifications and direct-key signatures. + * Returns `Infinity` if the key doesn't expire, or `null` if the key is revoked or invalid. + * @param {Object} [userID] - User ID to consider instead of the primary user + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} + * @async + */ + async getExpirationTime(userID, config = defaultConfig) { + let primaryKeyExpiry; + try { + const { selfCertification } = await this.getPrimaryUser(null, userID, config); + const selfSigKeyExpiry = getKeyExpirationTime(this.keyPacket, selfCertification); + const selfSigExpiry = selfCertification.getExpirationTime(); + const directSignature = await getLatestValidSignature( + this.directSignatures, this.keyPacket, enums.signature.key, { key: this.keyPacket }, null, config + ).catch(() => {}); + if (directSignature) { + const directSigKeyExpiry = getKeyExpirationTime(this.keyPacket, directSignature); + // We do not support the edge case where the direct signature expires, since it would invalidate the corresponding key expiration, + // causing a discountinous validy period for the key + primaryKeyExpiry = Math.min(selfSigKeyExpiry, selfSigExpiry, directSigKeyExpiry); + } else { + primaryKeyExpiry = selfSigKeyExpiry < selfSigExpiry ? selfSigKeyExpiry : selfSigExpiry; + } + } catch (e) { + primaryKeyExpiry = null; + } -var _bn = require('bn.js'); + return util.normalizeDate(primaryKeyExpiry); + } + + + /** + * Returns primary user and most significant (latest valid) self signature + * - if multiple primary users exist, returns the one with the latest self signature + * - otherwise, returns the user with the latest self signature + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} [userID] - User ID to get instead of the primary user, if it exists + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise<{ + * user: User, + * selfCertification: SignaturePacket + * }>} The primary user and the self signature + * @async + */ + async getPrimaryUser(date = new Date(), userID = {}, config = defaultConfig) { + const primaryKey = this.keyPacket; + const users = []; + let exception; + for (let i = 0; i < this.users.length; i++) { + try { + const user = this.users[i]; + if (!user.userID) { + continue; + } + if ( + (userID.name !== undefined && user.userID.name !== userID.name) || + (userID.email !== undefined && user.userID.email !== userID.email) || + (userID.comment !== undefined && user.userID.comment !== userID.comment) + ) { + throw new Error('Could not find user that matches that user ID'); + } + const dataToVerify = { userID: user.userID, key: primaryKey }; + const selfCertification = await getLatestValidSignature(user.selfCertifications, primaryKey, enums.signature.certGeneric, dataToVerify, date, config); + users.push({ index: i, user, selfCertification }); + } catch (e) { + exception = e; + } + } + if (!users.length) { + throw exception || new Error('Could not find primary user'); + } + await Promise.all(users.map(async function (a) { + return a.user.revoked || a.user.isRevoked(a.selfCertification, null, date, config); + })); + // sort by primary user flag and signature creation time + const primaryUser = users.sort(function(a, b) { + const A = a.selfCertification; + const B = b.selfCertification; + return B.revoked - A.revoked || A.isPrimaryUserID - B.isPrimaryUserID || A.created - B.created; + }).pop(); + const { user, selfCertification: cert } = primaryUser; + if (cert.revoked || await user.isRevoked(cert, null, date, config)) { + throw new Error('Primary user is revoked'); + } + return primaryUser; + } -var _bn2 = _interopRequireDefault(_bn); + /** + * Update key with new components from specified key with same key ID: + * users, subkeys, certificates are merged into the destination key, + * duplicates and expired signatures are ignored. + * + * If the source key is a private key and the destination key is public, + * a private key is returned. + * @param {Key} sourceKey - Source key to merge + * @param {Date} [date] - Date to verify validity of signatures and keys + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} updated key + * @async + */ + async update(sourceKey, date = new Date(), config = defaultConfig) { + if (!this.hasSameFingerprintAs(sourceKey)) { + throw new Error('Primary key fingerprints must be equal to update the key'); + } + if (!this.isPrivate() && sourceKey.isPrivate()) { + // check for equal subkey packets + const equal = (this.subkeys.length === sourceKey.subkeys.length) && + (this.subkeys.every(destSubkey => { + return sourceKey.subkeys.some(srcSubkey => { + return destSubkey.hasSameFingerprintAs(srcSubkey); + }); + })); + if (!equal) { + throw new Error('Cannot update public key with private key if subkeys mismatch'); + } -var _webStreamTools = require('web-stream-tools'); + return sourceKey.update(this, config); + } + // from here on, either: + // - destination key is private, source key is public + // - the keys are of the same type + // hence we don't need to convert the destination key type + const updatedKey = this.clone(); + // revocation signatures + await mergeSignatures(sourceKey, updatedKey, 'revocationSignatures', date, srcRevSig => { + return isDataRevoked(updatedKey.keyPacket, enums.signature.keyRevocation, updatedKey, [srcRevSig], null, sourceKey.keyPacket, date, config); + }); + // direct signatures + await mergeSignatures(sourceKey, updatedKey, 'directSignatures', date); + // update users + await Promise.all(sourceKey.users.map(async srcUser => { + // multiple users with the same ID/attribute are not explicitly disallowed by the spec + // hence we support them, just in case + const usersToUpdate = updatedKey.users.filter(dstUser => ( + (srcUser.userID && srcUser.userID.equals(dstUser.userID)) || + (srcUser.userAttribute && srcUser.userAttribute.equals(dstUser.userAttribute)) + )); + if (usersToUpdate.length > 0) { + await Promise.all( + usersToUpdate.map(userToUpdate => userToUpdate.update(srcUser, date, config)) + ); + } else { + const newUser = srcUser.clone(); + newUser.mainKey = updatedKey; + updatedKey.users.push(newUser); + } + })); + // update subkeys + await Promise.all(sourceKey.subkeys.map(async srcSubkey => { + // multiple subkeys with same fingerprint might be preset + const subkeysToUpdate = updatedKey.subkeys.filter(dstSubkey => ( + dstSubkey.hasSameFingerprintAs(srcSubkey) + )); + if (subkeysToUpdate.length > 0) { + await Promise.all( + subkeysToUpdate.map(subkeyToUpdate => subkeyToUpdate.update(srcSubkey, date, config)) + ); + } else { + const newSubkey = srcSubkey.clone(); + newSubkey.mainKey = updatedKey; + updatedKey.subkeys.push(newSubkey); + } + })); -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); + return updatedKey; + } -var _curves = require('./curves'); + /** + * Get revocation certificate from a revoked key. + * (To get a revocation certificate for an unrevoked key, call revoke() first.) + * @param {Date} date - Use the given date instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} Armored revocation certificate. + * @async + */ + async getRevocationCertificate(date = new Date(), config = defaultConfig) { + const dataToVerify = { key: this.keyPacket }; + const revocationSignature = await getLatestValidSignature(this.revocationSignatures, this.keyPacket, enums.signature.keyRevocation, dataToVerify, date, config); + const packetlist = new PacketList(); + packetlist.push(revocationSignature); + return armor(enums.armor.publicKey, packetlist.write(), null, null, 'This is a revocation certificate'); + } -var _util = require('../../../util'); + /** + * Applies a revocation certificate to a key + * This adds the first signature packet in the armored text to the key, + * if it is a valid revocation signature. + * @param {String} revocationCertificate - armored revocation certificate + * @param {Date} [date] - Date to verify the certificate + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} Revoked key. + * @async + */ + async applyRevocationCertificate(revocationCertificate, date = new Date(), config = defaultConfig) { + const input = await unarmor(revocationCertificate, config); + const packetlist = await PacketList.fromBinary(input.data, allowedRevocationPackets, config); + const revocationSignature = packetlist.findPacket(enums.packet.signature); + if (!revocationSignature || revocationSignature.signatureType !== enums.signature.keyRevocation) { + throw new Error('Could not find revocation signature packet'); + } + if (!revocationSignature.issuerKeyID.equals(this.getKeyID())) { + throw new Error('Revocation signature does not match key'); + } + try { + await revocationSignature.verify(this.keyPacket, enums.signature.keyRevocation, { key: this.keyPacket }, date, undefined, config); + } catch (e) { + throw util.wrapError('Could not verify revocation signature', e); + } + const key = this.clone(); + key.revocationSignatures.push(revocationSignature); + return key; + } -var _util2 = _interopRequireDefault(_util); + /** + * Signs primary user of key + * @param {Array} privateKeys - decrypted private keys for signing + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} [userID] - User ID to get instead of the primary user, if it exists + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} Key with new certificate signature. + * @async + */ + async signPrimaryUser(privateKeys, date, userID, config = defaultConfig) { + const { index, user } = await this.getPrimaryUser(date, userID, config); + const userSign = await user.certify(privateKeys, date, config); + const key = this.clone(); + key.users[index] = userSign; + return key; + } -var _enums = require('../../../enums'); + /** + * Signs all users of key + * @param {Array} privateKeys - decrypted private keys for signing + * @param {Date} [date] - Use the given date for signing, instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} Key with new certificate signature. + * @async + */ + async signAllUsers(privateKeys, date = new Date(), config = defaultConfig) { + const key = this.clone(); + key.users = await Promise.all(this.users.map(function(user) { + return user.certify(privateKeys, date, config); + })); + return key; + } -var _enums2 = _interopRequireDefault(_enums); + /** + * Verifies primary user of key + * - if no arguments are given, verifies the self certificates; + * - otherwise, verifies all certificates signed with given keys. + * @param {Array} [verificationKeys] - array of keys to verify certificate signatures, instead of the primary key + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} [userID] - User ID to get instead of the primary user, if it exists + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise>} List of signer's keyID and validity of signature. + * Signature validity is null if the verification keys do not correspond to the certificate. + * @async + */ + async verifyPrimaryUser(verificationKeys, date = new Date(), userID, config = defaultConfig) { + const primaryKey = this.keyPacket; + const { user } = await this.getPrimaryUser(date, userID, config); + const results = verificationKeys ? + await user.verifyAllCertifications(verificationKeys, date, config) : + [{ keyID: primaryKey.getKeyID(), valid: await user.verify(date, config).catch(() => false) }]; + return results; + } -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + /** + * Verifies all users of key + * - if no arguments are given, verifies the self certificates; + * - otherwise, verifies all certificates signed with given keys. + * @param {Array} [verificationKeys] - array of keys to verify certificate signatures + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise>} List of userID, signer's keyID and validity of signature. + * Signature validity is null if the verification keys do not correspond to the certificate. + * @async + */ + async verifyAllUsers(verificationKeys, date = new Date(), config = defaultConfig) { + const primaryKey = this.keyPacket; + const results = []; + await Promise.all(this.users.map(async user => { + const signatures = verificationKeys ? + await user.verifyAllCertifications(verificationKeys, date, config) : + [{ keyID: primaryKey.getKeyID(), valid: await user.verify(date, config).catch(() => false) }]; + + results.push(...signatures.map( + signature => ({ + userID: user.userID.userID, + keyID: signature.keyID, + valid: signature.valid + })) + ); + })); + return results; + } +} -const webCrypto = _util2.default.getWebCrypto(); // OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2015-2016 Decentral -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +['getKeyID', 'getFingerprint', 'getAlgorithmInfo', 'getCreationTime', 'hasSameFingerprintAs'].forEach(name => { + Key.prototype[name] = + Subkey.prototype[name]; +}); /** - * @fileoverview Wrapper for a KeyPair of an Elliptic Curve - * @requires bn.js - * @requires web-stream-tools - * @requires crypto/public_key/elliptic/curves - * @requires util - * @requires enums - * @requires asn1.js - * @module crypto/public_key/elliptic/key + * Creates a PublicKey or PrivateKey depending on the packetlist in input + * @param {PacketList} - packets to parse + * @return {Key} parsed key + * @throws if no key packet was found */ +function createKey(packetlist) { + for (const packet of packetlist) { + switch (packet.constructor.tag) { + case enums.packet.secretKey: + return new PrivateKey(packetlist); + case enums.packet.publicKey: + return new PublicKey(packetlist); + } + } + throw new Error('No key packet found'); +} -const nodeCrypto = _util2.default.getNodeCrypto(); +// This library is free software; you can redistribute it and/or /** - * @constructor + * Class that represents an OpenPGP Public Key */ -function KeyPair(curve, options) { - this.curve = curve; - this.keyType = curve.curve.type === 'edwards' ? _enums2.default.publicKey.eddsa : _enums2.default.publicKey.ecdsa; - this.keyPair = this.curve.curve.keyPair(options); -} - -KeyPair.prototype.sign = async function (message, hash_algo, hashed) { - if (message && !message.locked) { - message = await _webStreamTools2.default.readToEnd(message); - if (this.curve.web && _util2.default.getWebCrypto()) { - // If browser doesn't support a curve, we'll catch it - try { - // need to await to make sure browser succeeds - const signature = await webSign(this.curve, hash_algo, message, this.keyPair); - return signature; - } catch (err) { - _util2.default.print_debug("Browser did not support signing: " + err.message); +class PublicKey extends Key { + /** + * @param {PacketList} packetlist - The packets that form this key + */ + constructor(packetlist) { + super(); + this.keyPacket = null; + this.revocationSignatures = []; + this.directSignatures = []; + this.users = []; + this.subkeys = []; + if (packetlist) { + this.packetListToStructure(packetlist, new Set([enums.packet.secretKey, enums.packet.secretSubkey])); + if (!this.keyPacket) { + throw new Error('Invalid key: missing public-key packet'); } - } else if (this.curve.node && _util2.default.getNodeCrypto()) { - return nodeSign(this.curve, hash_algo, message, this.keyPair); } } - const digest = typeof hash_algo === 'undefined' ? message : hashed; - return this.keyPair.sign(digest); -}; -KeyPair.prototype.verify = async function (message, signature, hash_algo, hashed) { - if (message && !message.locked) { - message = await _webStreamTools2.default.readToEnd(message); - if (this.curve.web && _util2.default.getWebCrypto()) { - // If browser doesn't support a curve, we'll catch it - try { - // need to await to make sure browser succeeds - const result = await webVerify(this.curve, hash_algo, signature, message, this.keyPair.getPublic()); - return result; - } catch (err) { - _util2.default.print_debug("Browser did not support signing: " + err.message); - } - } else if (this.curve.node && _util2.default.getNodeCrypto()) { - return nodeVerify(this.curve, hash_algo, signature, message, this.keyPair.getPublic()); - } + /** + * Returns true if this is a private key + * @returns {false} + */ + isPrivate() { + return false; } - const digest = typeof hash_algo === 'undefined' ? message : hashed; - return this.keyPair.verify(digest, signature); -}; -KeyPair.prototype.derive = function (pub) { - if (this.keyType === _enums2.default.publicKey.eddsa) { - throw new Error('Key can only be used for EdDSA'); + /** + * Returns key as public key (shallow copy) + * @returns {PublicKey} New public Key + */ + toPublic() { + return this; } - return this.keyPair.derive(pub.keyPair.getPublic()); -}; -KeyPair.prototype.getPublic = function () { - const compact = this.curve.curve.curve.type === 'edwards' || this.curve.curve.curve.type === 'mont'; - return this.keyPair.getPublic('array', compact); -}; + /** + * Returns ASCII armored text of key + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {ReadableStream} ASCII armor. + */ + armor(config = defaultConfig) { + return armor(enums.armor.publicKey, this.toPacketList().write(), undefined, undefined, undefined, config); + } +} -KeyPair.prototype.getPrivate = function () { - if (this.curve.keyType === _enums2.default.publicKey.eddsa) { - return this.keyPair.getSecret(); +/** + * Class that represents an OpenPGP Private key + */ +class PrivateKey extends PublicKey { + /** + * @param {PacketList} packetlist - The packets that form this key + */ + constructor(packetlist) { + super(); + this.packetListToStructure(packetlist, new Set([enums.packet.publicKey, enums.packet.publicSubkey])); + if (!this.keyPacket) { + throw new Error('Invalid key: missing private-key packet'); + } } - return this.keyPair.getPrivate().toArray(); -}; -exports.default = KeyPair; + /** + * Returns true if this is a private key + * @returns {Boolean} + */ + isPrivate() { + return true; + } -////////////////////////// -// // -// Helper functions // -// // -////////////////////////// + /** + * Returns key as public key (shallow copy) + * @returns {PublicKey} New public Key + */ + toPublic() { + const packetlist = new PacketList(); + const keyPackets = this.toPacketList(); + for (const keyPacket of keyPackets) { + switch (keyPacket.constructor.tag) { + case enums.packet.secretKey: { + const pubKeyPacket = PublicKeyPacket.fromSecretKeyPacket(keyPacket); + packetlist.push(pubKeyPacket); + break; + } + case enums.packet.secretSubkey: { + const pubSubkeyPacket = PublicSubkeyPacket.fromSecretSubkeyPacket(keyPacket); + packetlist.push(pubSubkeyPacket); + break; + } + default: + packetlist.push(keyPacket); + } + } + return new PublicKey(packetlist); + } + /** + * Returns ASCII armored text of key + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {ReadableStream} ASCII armor. + */ + armor(config = defaultConfig) { + return armor(enums.armor.privateKey, this.toPacketList().write(), undefined, undefined, undefined, config); + } -async function webSign(curve, hash_algo, message, keyPair) { - const len = curve.payloadSize; - const key = await webCrypto.importKey("jwk", { - "kty": "EC", - "crv": _curves.webCurves[curve.name], - "x": _util2.default.Uint8Array_to_b64(new Uint8Array(keyPair.getPublic().getX().toArray('be', len)), true), - "y": _util2.default.Uint8Array_to_b64(new Uint8Array(keyPair.getPublic().getY().toArray('be', len)), true), - "d": _util2.default.Uint8Array_to_b64(new Uint8Array(keyPair.getPrivate().toArray('be', len)), true), - "use": "sig", - "kid": "ECDSA Private Key" - }, { - "name": "ECDSA", - "namedCurve": _curves.webCurves[curve.name], - "hash": { name: _enums2.default.read(_enums2.default.webHash, curve.hash) } - }, false, ["sign"]); - - const signature = new Uint8Array((await webCrypto.sign({ - "name": 'ECDSA', - "namedCurve": _curves.webCurves[curve.name], - "hash": { name: _enums2.default.read(_enums2.default.webHash, hash_algo) } - }, key, message))); + /** + * Returns all keys that are available for decryption, matching the keyID when given + * This is useful to retrieve keys for session key decryption + * @param {module:type/keyid~KeyID} keyID, optional + * @param {Date} date, optional + * @param {String} userID, optional + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise>} Array of decryption keys. + * @async + */ + async getDecryptionKeys(keyID, date = new Date(), userID = {}, config = defaultConfig) { + const primaryKey = this.keyPacket; + const keys = []; + for (let i = 0; i < this.subkeys.length; i++) { + if (!keyID || this.subkeys[i].getKeyID().equals(keyID, true)) { + try { + const dataToVerify = { key: primaryKey, bind: this.subkeys[i].keyPacket }; + const bindingSignature = await getLatestValidSignature(this.subkeys[i].bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); + if (isValidDecryptionKeyPacket(bindingSignature, config)) { + keys.push(this.subkeys[i]); + } + } catch (e) {} + } + } - return { - r: new _bn2.default(signature.slice(0, len)), - s: new _bn2.default(signature.slice(len, len << 1)) - }; -} + // evaluate primary key + const primaryUser = await this.getPrimaryUser(date, userID, config); + if ((!keyID || primaryKey.getKeyID().equals(keyID, true)) && + isValidDecryptionKeyPacket(primaryUser.selfCertification, config)) { + keys.push(this); + } -async function webVerify(curve, hash_algo, { r, s }, message, publicKey) { - const len = curve.payloadSize; - const key = await webCrypto.importKey("jwk", { - "kty": "EC", - "crv": _curves.webCurves[curve.name], - "x": _util2.default.Uint8Array_to_b64(new Uint8Array(publicKey.getX().toArray('be', len)), true), - "y": _util2.default.Uint8Array_to_b64(new Uint8Array(publicKey.getY().toArray('be', len)), true), - "use": "sig", - "kid": "ECDSA Public Key" - }, { - "name": "ECDSA", - "namedCurve": _curves.webCurves[curve.name], - "hash": { name: _enums2.default.read(_enums2.default.webHash, curve.hash) } - }, false, ["verify"]); - - const signature = _util2.default.concatUint8Array([new Uint8Array(len - r.length), r, new Uint8Array(len - s.length), s]).buffer; - - return webCrypto.verify({ - "name": 'ECDSA', - "namedCurve": _curves.webCurves[curve.name], - "hash": { name: _enums2.default.read(_enums2.default.webHash, hash_algo) } - }, key, signature, message); -} - -async function nodeSign(curve, hash_algo, message, keyPair) { - const sign = nodeCrypto.createSign(_enums2.default.read(_enums2.default.hash, hash_algo)); - sign.write(message); - sign.end(); + return keys; + } - const key = ECPrivateKey.encode({ - version: 1, - parameters: curve.oid, - privateKey: keyPair.getPrivate().toArray(), - publicKey: { unused: 0, data: keyPair.getPublic().encode() } - }, 'pem', { - label: 'EC PRIVATE KEY' - }); + /** + * Returns true if the primary key or any subkey is decrypted. + * A dummy key is considered encrypted. + */ + isDecrypted() { + return this.getKeys().some(({ keyPacket }) => keyPacket.isDecrypted()); + } - return ECDSASignature.decode(sign.sign(key), 'der'); -} + /** + * Check whether the private and public primary key parameters correspond + * Together with verification of binding signatures, this guarantees key integrity + * In case of gnu-dummy primary key, it is enough to validate any signing subkeys + * otherwise all encryption subkeys are validated + * If only gnu-dummy keys are found, we cannot properly validate so we throw an error + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if validation was not successful and the key cannot be trusted + * @async + */ + async validate(config = defaultConfig) { + if (!this.isPrivate()) { + throw new Error('Cannot validate a public key'); + } -async function nodeVerify(curve, hash_algo, { r, s }, message, publicKey) { - const verify = nodeCrypto.createVerify(_enums2.default.read(_enums2.default.hash, hash_algo)); - verify.write(message); - verify.end(); + let signingKeyPacket; + if (!this.keyPacket.isDummy()) { + signingKeyPacket = this.keyPacket; + } else { + /** + * It is enough to validate any signing keys + * since its binding signatures are also checked + */ + const signingKey = await this.getSigningKey(null, null, undefined, { ...config, rejectPublicKeyAlgorithms: new Set(), minRSABits: 0 }); + // This could again be a dummy key + if (signingKey && !signingKey.keyPacket.isDummy()) { + signingKeyPacket = signingKey.keyPacket; + } + } - const key = SubjectPublicKeyInfo.encode({ - algorithm: { - algorithm: [1, 2, 840, 10045, 2, 1], - parameters: curve.oid - }, - subjectPublicKey: { unused: 0, data: publicKey.encode() } - }, 'pem', { - label: 'PUBLIC KEY' - }); + if (signingKeyPacket) { + return signingKeyPacket.validate(); + } else { + const keys = this.getKeys(); + const allDummies = keys.map(key => key.keyPacket.isDummy()).every(Boolean); + if (allDummies) { + throw new Error('Cannot validate an all-gnu-dummy key'); + } - const signature = ECDSASignature.encode({ - r: new _bn2.default(r), s: new _bn2.default(s) - }, 'der'); + return Promise.all(keys.map(async key => key.keyPacket.validate())); + } + } - try { - return verify.verify(key, signature); - } catch (err) { - return false; + /** + * Clear private key parameters + */ + clearPrivateParams() { + this.getKeys().forEach(({ keyPacket }) => { + if (keyPacket.isDecrypted()) { + keyPacket.clearPrivateParams(); + } + }); } -} -// Originally written by Owen Smith https://github.com/omsmith -// Adapted on Feb 2018 from https://github.com/Brightspace/node-jwk-to-pem/ + /** + * Revokes the key + * @param {Object} reasonForRevocation - optional, object indicating the reason for revocation + * @param {module:enums.reasonForRevocation} reasonForRevocation.flag optional, flag indicating the reason for revocation + * @param {String} reasonForRevocation.string optional, string explaining the reason for revocation + * @param {Date} date - optional, override the creationtime of the revocation signature + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New key with revocation signature. + * @async + */ + async revoke( + { + flag: reasonForRevocationFlag = enums.reasonForRevocation.noReason, + string: reasonForRevocationString = '' + } = {}, + date = new Date(), + config = defaultConfig + ) { + if (!this.isPrivate()) { + throw new Error('Need private key for revoking'); + } + const dataToSign = { key: this.keyPacket }; + const key = this.clone(); + key.revocationSignatures.push(await createSignaturePacket(dataToSign, null, this.keyPacket, { + signatureType: enums.signature.keyRevocation, + reasonForRevocationFlag: enums.write(enums.reasonForRevocation, reasonForRevocationFlag), + reasonForRevocationString + }, date, undefined, undefined, config)); + return key; + } -/* eslint-disable no-invalid-this */ -const asn1 = nodeCrypto ? require('asn1.js') : undefined; + /** + * Generates a new OpenPGP subkey, and returns a clone of the Key object with the new subkey added. + * Supports RSA and ECC keys. Defaults to the algorithm and bit size/curve of the primary key. DSA primary keys default to RSA subkeys. + * @param {ecc|rsa} options.type The subkey algorithm: ECC or RSA + * @param {String} options.curve (optional) Elliptic curve for ECC keys + * @param {Integer} options.rsaBits (optional) Number of bits for RSA subkeys + * @param {Number} options.keyExpirationTime (optional) Number of seconds from the key creation time after which the key expires + * @param {Date} options.date (optional) Override the creation date of the key and the key signatures + * @param {Boolean} options.sign (optional) Indicates whether the subkey should sign rather than encrypt. Defaults to false + * @param {Object} options.config (optional) custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} + * @async + */ + async addSubkey(options = {}) { + const config = { ...defaultConfig, ...options.config }; + if (options.passphrase) { + throw new Error('Subkey could not be encrypted here, please encrypt whole key'); + } + if (options.rsaBits < config.minRSABits) { + throw new Error(`rsaBits should be at least ${config.minRSABits}, got: ${options.rsaBits}`); + } + const secretKeyPacket = this.keyPacket; + if (secretKeyPacket.isDummy()) { + throw new Error('Cannot add subkey to gnu-dummy primary key'); + } + if (!secretKeyPacket.isDecrypted()) { + throw new Error('Key is not decrypted'); + } + const defaultOptions = secretKeyPacket.getAlgorithmInfo(); + defaultOptions.type = defaultOptions.curve ? 'ecc' : 'rsa'; // DSA keys default to RSA + defaultOptions.rsaBits = defaultOptions.bits || 4096; + defaultOptions.curve = defaultOptions.curve || 'curve25519'; + options = sanitizeKeyOptions(options, defaultOptions); + const keyPacket = await generateSecretSubkey(options); + checkKeyRequirements(keyPacket, config); + const bindingSignature = await createBindingSignature(keyPacket, secretKeyPacket, options, config); + const packetList = this.toPacketList(); + packetList.push(keyPacket, bindingSignature); + return new PrivateKey(packetList); + } +} -const ECDSASignature = nodeCrypto ? asn1.define('ECDSASignature', function () { - this.seq().obj(this.key('r').int(), this.key('s').int()); -}) : undefined; +// OpenPGP.js - An OpenPGP implementation in javascript -const ECPrivateKey = nodeCrypto ? asn1.define('ECPrivateKey', function () { - this.seq().obj(this.key('version').int(), this.key('privateKey').octstr(), this.key('parameters').explicit(0).optional().any(), this.key('publicKey').explicit(1).optional().bitstr()); -}) : undefined; +// A Key can contain the following packets +const allowedKeyPackets = /*#__PURE__*/ util.constructAllowedPackets([ + PublicKeyPacket, + PublicSubkeyPacket, + SecretKeyPacket, + SecretSubkeyPacket, + UserIDPacket, + UserAttributePacket, + SignaturePacket +]); -const AlgorithmIdentifier = nodeCrypto ? asn1.define('AlgorithmIdentifier', function () { - this.seq().obj(this.key('algorithm').objid(), this.key('parameters').optional().any()); -}) : undefined; +/** + * Generates a new OpenPGP key. Supports RSA and ECC keys. + * By default, primary and subkeys will be of same type. + * @param {ecc|rsa} options.type The primary key algorithm type: ECC or RSA + * @param {String} options.curve Elliptic curve for ECC keys + * @param {Integer} options.rsaBits Number of bits for RSA keys + * @param {Array} options.userIDs User IDs as strings or objects: 'Jo Doe ' or { name:'Jo Doe', email:'info@jo.com' } + * @param {String} options.passphrase Passphrase used to encrypt the resulting private key + * @param {Number} options.keyExpirationTime (optional) Number of seconds from the key creation time after which the key expires + * @param {Date} options.date Creation date of the key and the key signatures + * @param {Object} config - Full configuration + * @param {Array} options.subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}] + * sign parameter defaults to false, and indicates whether the subkey should sign rather than encrypt + * @returns {Promise<{{ key: PrivateKey, revocationCertificate: String }}>} + * @async + * @static + * @private + */ +async function generate$2(options, config) { + options.sign = true; // primary key is always a signing key + options = sanitizeKeyOptions(options); + options.subkeys = options.subkeys.map((subkey, index) => sanitizeKeyOptions(options.subkeys[index], options)); + let promises = [generateSecretKey(options, config)]; + promises = promises.concat(options.subkeys.map(options => generateSecretSubkey(options, config))); + const packets = await Promise.all(promises); -const SubjectPublicKeyInfo = nodeCrypto ? asn1.define('SubjectPublicKeyInfo', function () { - this.seq().obj(this.key('algorithm').use(AlgorithmIdentifier), this.key('subjectPublicKey').bitstr()); -}) : undefined; + const key = await wrapKeyObject(packets[0], packets.slice(1), options, config); + const revocationCertificate = await key.getRevocationCertificate(options.date, config); + key.revocationSignatures = []; + return { key, revocationCertificate }; +} -},{"../../../enums":113,"../../../util":152,"./curves":100,"asn1.js":"asn1.js","bn.js":16,"web-stream-tools":75}],106:[function(require,module,exports){ -'use strict'; +/** + * Reformats and signs an OpenPGP key with a given User ID. Currently only supports RSA keys. + * @param {PrivateKey} options.privateKey The private key to reformat + * @param {Array} options.userIDs User IDs as strings or objects: 'Jo Doe ' or { name:'Jo Doe', email:'info@jo.com' } + * @param {String} options.passphrase Passphrase used to encrypt the resulting private key + * @param {Number} options.keyExpirationTime Number of seconds from the key creation time after which the key expires + * @param {Date} options.date Override the creation date of the key signatures + * @param {Array} options.subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}] + * @param {Object} config - Full configuration + * + * @returns {Promise<{{ key: PrivateKey, revocationCertificate: String }}>} + * @async + * @static + * @private + */ +async function reformat(options, config) { + options = sanitize(options); + const { privateKey } = options; -Object.defineProperty(exports, "__esModule", { - value: true -}); + if (!privateKey.isPrivate()) { + throw new Error('Cannot reformat a public key'); + } -var _naclFastLight = require('tweetnacl/nacl-fast-light.js'); + if (privateKey.keyPacket.isDummy()) { + throw new Error('Cannot reformat a gnu-dummy primary key'); + } -var _naclFastLight2 = _interopRequireDefault(_naclFastLight); + const isDecrypted = privateKey.getKeys().every(({ keyPacket }) => keyPacket.isDecrypted()); + if (!isDecrypted) { + throw new Error('Key is not decrypted'); + } -var _rsa = require('./rsa'); + const secretKeyPacket = privateKey.keyPacket; -var _rsa2 = _interopRequireDefault(_rsa); + if (!options.subkeys) { + options.subkeys = await Promise.all(privateKey.subkeys.map(async subkey => { + const secretSubkeyPacket = subkey.keyPacket; + const dataToVerify = { key: secretKeyPacket, bind: secretSubkeyPacket }; + const bindingSignature = await ( + getLatestValidSignature(subkey.bindingSignatures, secretKeyPacket, enums.signature.subkeyBinding, dataToVerify, null, config) + ).catch(() => ({})); + return { + sign: bindingSignature.keyFlags && (bindingSignature.keyFlags[0] & enums.keyFlags.signData) + }; + })); + } -var _elgamal = require('./elgamal'); + const secretSubkeyPackets = privateKey.subkeys.map(subkey => subkey.keyPacket); + if (options.subkeys.length !== secretSubkeyPackets.length) { + throw new Error('Number of subkey options does not match number of subkeys'); + } -var _elgamal2 = _interopRequireDefault(_elgamal); + options.subkeys = options.subkeys.map(subkeyOptions => sanitize(subkeyOptions, options)); -var _elliptic = require('./elliptic'); + const key = await wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options, config); + const revocationCertificate = await key.getRevocationCertificate(options.date, config); + key.revocationSignatures = []; + return { key, revocationCertificate }; -var _elliptic2 = _interopRequireDefault(_elliptic); + function sanitize(options, subkeyDefaults = {}) { + options.keyExpirationTime = options.keyExpirationTime || subkeyDefaults.keyExpirationTime; + options.passphrase = util.isString(options.passphrase) ? options.passphrase : subkeyDefaults.passphrase; + options.date = options.date || subkeyDefaults.date; -var _dsa = require('./dsa'); + return options; + } +} -var _dsa2 = _interopRequireDefault(_dsa); +/** + * Construct PrivateKey object from the given key packets, add certification signatures and set passphrase protection + * The new key includes a revocation certificate that must be removed before returning the key, otherwise the key is considered revoked. + * @param {SecretKeyPacket} secretKeyPacket + * @param {SecretSubkeyPacket} secretSubkeyPackets + * @param {Object} options + * @param {Object} config - Full configuration + * @returns {PrivateKey} + */ +async function wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options, config) { + // set passphrase protection + if (options.passphrase) { + await secretKeyPacket.encrypt(options.passphrase, config); + } -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + await Promise.all(secretSubkeyPackets.map(async function(secretSubkeyPacket, index) { + const subkeyPassphrase = options.subkeys[index].passphrase; + if (subkeyPassphrase) { + await secretSubkeyPacket.encrypt(subkeyPassphrase, config); + } + })); -exports.default = { - /** @see module:crypto/public_key/rsa */ - rsa: _rsa2.default, - /** @see module:crypto/public_key/elgamal */ - elgamal: _elgamal2.default, - /** @see module:crypto/public_key/elliptic */ - elliptic: _elliptic2.default, - /** @see module:crypto/public_key/dsa */ - dsa: _dsa2.default, - /** @see tweetnacl */ - nacl: _naclFastLight2.default -}; /** - * @fileoverview Asymmetric cryptography functions - * @requires tweetnacl - * @requires crypto/public_key/dsa - * @requires crypto/public_key/elgamal - * @requires crypto/public_key/elliptic - * @requires crypto/public_key/rsa - * @module crypto/public_key - */ + const packetlist = new PacketList(); + packetlist.push(secretKeyPacket); -},{"./dsa":98,"./elgamal":99,"./elliptic":104,"./rsa":108,"tweetnacl/nacl-fast-light.js":72}],107:[function(require,module,exports){ -'use strict'; + await Promise.all(options.userIDs.map(async function(userID, index) { + function createPreferredAlgos(algos, preferredAlgo) { + return [preferredAlgo, ...algos.filter(algo => algo !== preferredAlgo)]; + } -Object.defineProperty(exports, "__esModule", { - value: true -}); + const userIDPacket = UserIDPacket.fromObject(userID); + const dataToSign = {}; + dataToSign.userID = userIDPacket; + dataToSign.key = secretKeyPacket; + const signaturePacket = new SignaturePacket(); + signaturePacket.signatureType = enums.signature.certGeneric; + signaturePacket.publicKeyAlgorithm = secretKeyPacket.algorithm; + signaturePacket.hashAlgorithm = await getPreferredHashAlgo$1(null, secretKeyPacket, undefined, undefined, config); + signaturePacket.keyFlags = [enums.keyFlags.certifyKeys | enums.keyFlags.signData]; + signaturePacket.preferredSymmetricAlgorithms = createPreferredAlgos([ + // prefer aes256, aes128, then aes192 (no WebCrypto support: https://www.chromium.org/blink/webcrypto#TOC-AES-support) + enums.symmetric.aes256, + enums.symmetric.aes128, + enums.symmetric.aes192 + ], config.preferredSymmetricAlgorithm); + if (config.aeadProtect) { + signaturePacket.preferredAEADAlgorithms = createPreferredAlgos([ + enums.aead.eax, + enums.aead.ocb + ], config.preferredAEADAlgorithm); + } + signaturePacket.preferredHashAlgorithms = createPreferredAlgos([ + // prefer fast asm.js implementations (SHA-256) + enums.hash.sha256, + enums.hash.sha512 + ], config.preferredHashAlgorithm); + signaturePacket.preferredCompressionAlgorithms = createPreferredAlgos([ + enums.compression.zlib, + enums.compression.zip, + enums.compression.uncompressed + ], config.preferredCompressionAlgorithm); + if (index === 0) { + signaturePacket.isPrimaryUserID = true; + } + // integrity protection always enabled + signaturePacket.features = [0]; + signaturePacket.features[0] |= enums.features.modificationDetection; + if (config.aeadProtect) { + signaturePacket.features[0] |= enums.features.aead; + } + if (config.v5Keys) { + signaturePacket.features[0] |= enums.features.v5Keys; + } + if (options.keyExpirationTime > 0) { + signaturePacket.keyExpirationTime = options.keyExpirationTime; + signaturePacket.keyNeverExpires = false; + } + await signaturePacket.sign(secretKeyPacket, dataToSign, options.date); -var _bn = require('bn.js'); + return { userIDPacket, signaturePacket }; + })).then(list => { + list.forEach(({ userIDPacket, signaturePacket }) => { + packetlist.push(userIDPacket); + packetlist.push(signaturePacket); + }); + }); -var _bn2 = _interopRequireDefault(_bn); + await Promise.all(secretSubkeyPackets.map(async function(secretSubkeyPacket, index) { + const subkeyOptions = options.subkeys[index]; + const subkeySignaturePacket = await createBindingSignature(secretSubkeyPacket, secretKeyPacket, subkeyOptions, config); + return { secretSubkeyPacket, subkeySignaturePacket }; + })).then(packets => { + packets.forEach(({ secretSubkeyPacket, subkeySignaturePacket }) => { + packetlist.push(secretSubkeyPacket); + packetlist.push(subkeySignaturePacket); + }); + }); -var _random = require('../random'); + // Add revocation signature packet for creating a revocation certificate. + // This packet should be removed before returning the key. + const dataToSign = { key: secretKeyPacket }; + packetlist.push(await createSignaturePacket(dataToSign, null, secretKeyPacket, { + signatureType: enums.signature.keyRevocation, + reasonForRevocationFlag: enums.reasonForRevocation.noReason, + reasonForRevocationString: '' + }, options.date, undefined, undefined, config)); -var _random2 = _interopRequireDefault(_random); + if (options.passphrase) { + secretKeyPacket.clearPrivateParams(); + } -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + await Promise.all(secretSubkeyPackets.map(async function(secretSubkeyPacket, index) { + const subkeyPassphrase = options.subkeys[index].passphrase; + if (subkeyPassphrase) { + secretSubkeyPacket.clearPrivateParams(); + } + })); -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2018 Proton Technologies AG -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + return new PrivateKey(packetlist); +} /** - * @fileoverview Algorithms for probabilistic random prime generation - * @requires bn.js - * @requires crypto/random - * @module crypto/public_key/prime + * Reads an (optionally armored) OpenPGP key and returns a key object + * @param {Object} options + * @param {String} [options.armoredKey] - Armored key to be parsed + * @param {Uint8Array} [options.binaryKey] - Binary key to be parsed + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} Key object. + * @async + * @static */ +async function readKey({ armoredKey, binaryKey, config, ...rest }) { + config = { ...defaultConfig, ...config }; + if (!armoredKey && !binaryKey) { + throw new Error('readKey: must pass options object containing `armoredKey` or `binaryKey`'); + } + if (armoredKey && !util.isString(armoredKey)) { + throw new Error('readKey: options.armoredKey must be a string'); + } + if (binaryKey && !util.isUint8Array(binaryKey)) { + throw new Error('readKey: options.binaryKey must be a Uint8Array'); + } + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); -exports.default = { - randomProbablePrime, isProbablePrime, fermat, millerRabin, divisionTest -}; + let input; + if (armoredKey) { + const { type, data } = await unarmor(armoredKey, config); + if (!(type === enums.armor.publicKey || type === enums.armor.privateKey)) { + throw new Error('Armored text not of type key'); + } + input = data; + } else { + input = binaryKey; + } + const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); + return createKey(packetlist); +} /** - * Probabilistic random number generator - * @param {Integer} bits Bit length of the prime - * @param {BN} e Optional RSA exponent to check against the prime - * @param {Integer} k Optional number of iterations of Miller-Rabin test - * @returns BN + * Reads an (optionally armored) OpenPGP private key and returns a PrivateKey object + * @param {Object} options + * @param {String} [options.armoredKey] - Armored key to be parsed + * @param {Uint8Array} [options.binaryKey] - Binary key to be parsed + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} Key object. * @async + * @static */ +async function readPrivateKey({ armoredKey, binaryKey, config, ...rest }) { + config = { ...defaultConfig, ...config }; + if (!armoredKey && !binaryKey) { + throw new Error('readPrivateKey: must pass options object containing `armoredKey` or `binaryKey`'); + } + if (armoredKey && !util.isString(armoredKey)) { + throw new Error('readPrivateKey: options.armoredKey must be a string'); + } + if (binaryKey && !util.isUint8Array(binaryKey)) { + throw new Error('readPrivateKey: options.binaryKey must be a Uint8Array'); + } + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); -async function randomProbablePrime(bits, e, k) { - const min = new _bn2.default(1).shln(bits - 1); - const thirty = new _bn2.default(30); - /* - * We can avoid any multiples of 3 and 5 by looking at n mod 30 - * n mod 30 = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 - * the next possible prime is mod 30: - * 1 7 7 7 7 7 7 11 11 11 11 13 13 17 17 17 17 19 19 23 23 23 23 29 29 29 29 29 29 1 - */ - const adds = [1, 6, 5, 4, 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, 3, 2, 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1, 2]; - - let n = await _random2.default.getRandomBN(min, min.shln(1)); - let i = n.mod(thirty).toNumber(); - - do { - n.iaddn(adds[i]); - i = (i + adds[i]) % adds.length; - // If reached the maximum, go back to the minimum. - if (n.bitLength() > bits) { - n = n.mod(min.shln(1)).iadd(min); - i = n.mod(thirty).toNumber(); + let input; + if (armoredKey) { + const { type, data } = await unarmor(armoredKey, config); + if (!(type === enums.armor.privateKey)) { + throw new Error('Armored text not of type private key'); } - } while (!(await isProbablePrime(n, e, k))); - return n; + input = data; + } else { + input = binaryKey; + } + const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); + return new PrivateKey(packetlist); } /** - * Probabilistic primality testing - * @param {BN} n Number to test - * @param {BN} e Optional RSA exponent to check against the prime - * @param {Integer} k Optional number of iterations of Miller-Rabin test - * @returns {boolean} + * Reads an (optionally armored) OpenPGP key block and returns a list of key objects + * @param {Object} options + * @param {String} [options.armoredKeys] - Armored keys to be parsed + * @param {Uint8Array} [options.binaryKeys] - Binary keys to be parsed + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise>} Key objects. * @async + * @static */ -async function isProbablePrime(n, e, k) { - if (e && !n.subn(1).gcd(e).eqn(1)) { - return false; +async function readKeys({ armoredKeys, binaryKeys, config, ...rest }) { + config = { ...defaultConfig, ...config }; + let input = armoredKeys || binaryKeys; + if (!input) { + throw new Error('readKeys: must pass options object containing `armoredKeys` or `binaryKeys`'); } - if (!divisionTest(n)) { - return false; + if (armoredKeys && !util.isString(armoredKeys)) { + throw new Error('readKeys: options.armoredKeys must be a string'); } - if (!fermat(n)) { - return false; + if (binaryKeys && !util.isUint8Array(binaryKeys)) { + throw new Error('readKeys: options.binaryKeys must be a Uint8Array'); } - if (!(await millerRabin(n, k))) { - return false; + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + if (armoredKeys) { + const { type, data } = await unarmor(armoredKeys, config); + if (type !== enums.armor.publicKey && type !== enums.armor.privateKey) { + throw new Error('Armored text not of type key'); + } + input = data; } - // TODO implement the Lucas test - // See Section C.3.3 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - return true; + const keys = []; + const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); + const keyIndex = packetlist.indexOfTag(enums.packet.publicKey, enums.packet.secretKey); + if (keyIndex.length === 0) { + throw new Error('No key packet found'); + } + for (let i = 0; i < keyIndex.length; i++) { + const oneKeyList = packetlist.slice(keyIndex[i], keyIndex[i + 1]); + const newKey = createKey(oneKeyList); + keys.push(newKey); + } + return keys; } /** - * Tests whether n is probably prime or not using Fermat's test with b = 2. - * Fails if b^(n-1) mod n === 1. - * @param {BN} n Number to test - * @param {Integer} b Optional Fermat test base - * @returns {boolean} + * Reads an (optionally armored) OpenPGP private key block and returns a list of PrivateKey objects + * @param {Object} options + * @param {String} [options.armoredKeys] - Armored keys to be parsed + * @param {Uint8Array} [options.binaryKeys] - Binary keys to be parsed + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise>} Key objects. + * @async + * @static */ -function fermat(n, b) { - b = b || new _bn2.default(2); - return b.toRed(_bn2.default.mont(n)).redPow(n.subn(1)).fromRed().cmpn(1) === 0; +async function readPrivateKeys({ armoredKeys, binaryKeys, config }) { + config = { ...defaultConfig, ...config }; + let input = armoredKeys || binaryKeys; + if (!input) { + throw new Error('readPrivateKeys: must pass options object containing `armoredKeys` or `binaryKeys`'); + } + if (armoredKeys && !util.isString(armoredKeys)) { + throw new Error('readPrivateKeys: options.armoredKeys must be a string'); + } + if (binaryKeys && !util.isUint8Array(binaryKeys)) { + throw new Error('readPrivateKeys: options.binaryKeys must be a Uint8Array'); + } + if (armoredKeys) { + const { type, data } = await unarmor(armoredKeys, config); + if (type !== enums.armor.privateKey) { + throw new Error('Armored text not of type private key'); + } + input = data; + } + const keys = []; + const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); + const keyIndex = packetlist.indexOfTag(enums.packet.secretKey); + if (keyIndex.length === 0) { + throw new Error('No secret key packet found'); + } + for (let i = 0; i < keyIndex.length; i++) { + const oneKeyList = packetlist.slice(keyIndex[i], keyIndex[i + 1]); + const newKey = new PrivateKey(oneKeyList); + keys.push(newKey); + } + return keys; } -function divisionTest(n) { - return small_primes.every(m => { - return n.modn(m) !== 0; - }); -} +// GPG4Browsers - An OpenPGP implementation in javascript -// https://github.com/gpg/libgcrypt/blob/master/cipher/primegen.c -const small_primes = [7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999]; +// A Message can contain the following packets +const allowedMessagePackets = /*#__PURE__*/ util.constructAllowedPackets([ + LiteralDataPacket, + CompressedDataPacket, + AEADEncryptedDataPacket, + SymEncryptedIntegrityProtectedDataPacket, + SymmetricallyEncryptedDataPacket, + PublicKeyEncryptedSessionKeyPacket, + SymEncryptedSessionKeyPacket, + OnePassSignaturePacket, + SignaturePacket +]); +// A SKESK packet can contain the following packets +const allowedSymSessionKeyPackets = /*#__PURE__*/ util.constructAllowedPackets([SymEncryptedSessionKeyPacket]); +// A detached signature can contain the following packets +const allowedDetachedSignaturePackets = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); + +/** + * Class that represents an OpenPGP message. + * Can be an encrypted message, signed message, compressed message or literal message + * See {@link https://tools.ietf.org/html/rfc4880#section-11.3} + */ +class Message { + /** + * @param {PacketList} packetlist - The packets that form this message + */ + constructor(packetlist) { + this.packets = packetlist || new PacketList(); + } -// Miller-Rabin - Miller Rabin algorithm for primality test -// Copyright Fedor Indutny, 2014. -// -// This software is licensed under the MIT License. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. + /** + * Returns the key IDs of the keys to which the session key is encrypted + * @returns {Array} Array of keyID objects. + */ + getEncryptionKeyIDs() { + const keyIDs = []; + const pkESKeyPacketlist = this.packets.filterByTag(enums.packet.publicKeyEncryptedSessionKey); + pkESKeyPacketlist.forEach(function(packet) { + keyIDs.push(packet.publicKeyID); + }); + return keyIDs; + } -// Adapted on Jan 2018 from version 4.0.1 at https://github.com/indutny/miller-rabin + /** + * Returns the key IDs of the keys that signed the message + * @returns {Array} Array of keyID objects. + */ + getSigningKeyIDs() { + const msg = this.unwrapCompressed(); + // search for one pass signatures + const onePassSigList = msg.packets.filterByTag(enums.packet.onePassSignature); + if (onePassSigList.length > 0) { + return onePassSigList.map(packet => packet.issuerKeyID); + } + // if nothing found look for signature packets + const signatureList = msg.packets.filterByTag(enums.packet.signature); + return signatureList.map(packet => packet.issuerKeyID); + } -// Sample syntax for Fixed-Base Miller-Rabin: -// millerRabin(n, k, () => new BN(small_primes[Math.random() * small_primes.length | 0])) + /** + * Decrypt the message. Either a private key, a session key, or a password must be specified. + * @param {Array} [decryptionKeys] - Private keys with decrypted secret data + * @param {Array} [passwords] - Passwords used to decrypt + * @param {Array} [sessionKeys] - Session keys in the form: { data:Uint8Array, algorithm:String, [aeadAlgorithm:String] } + * @param {Date} [date] - Use the given date for key verification instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New message with decrypted content. + * @async + */ + async decrypt(decryptionKeys, passwords, sessionKeys, date = new Date(), config = defaultConfig) { + const sessionKeyObjects = sessionKeys || await this.decryptSessionKeys(decryptionKeys, passwords, date, config); + + const symEncryptedPacketlist = this.packets.filterByTag( + enums.packet.symmetricallyEncryptedData, + enums.packet.symEncryptedIntegrityProtectedData, + enums.packet.aeadEncryptedData + ); + + if (symEncryptedPacketlist.length === 0) { + return this; + } + + const symEncryptedPacket = symEncryptedPacketlist[0]; + let exception = null; + const decryptedPromise = Promise.all(sessionKeyObjects.map(async ({ algorithm: algorithmName, data }) => { + if (!util.isUint8Array(data) || !util.isString(algorithmName)) { + throw new Error('Invalid session key for decryption.'); + } + + try { + const algo = enums.write(enums.symmetric, algorithmName); + await symEncryptedPacket.decrypt(algo, data, config); + } catch (e) { + util.printDebugError(e); + exception = e; + } + })); + // We don't await stream.cancel here because it only returns when the other copy is canceled too. + cancel(symEncryptedPacket.encrypted); // Don't keep copy of encrypted data in memory. + symEncryptedPacket.encrypted = null; + await decryptedPromise; + + if (!symEncryptedPacket.packets || !symEncryptedPacket.packets.length) { + throw exception || new Error('Decryption failed.'); + } + + const resultMsg = new Message(symEncryptedPacket.packets); + symEncryptedPacket.packets = new PacketList(); // remove packets after decryption + + return resultMsg; + } + + /** + * Decrypt encrypted session keys either with private keys or passwords. + * @param {Array} [decryptionKeys] - Private keys with decrypted secret data + * @param {Array} [passwords] - Passwords used to decrypt + * @param {Date} [date] - Use the given date for key verification, instead of current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise>} array of object with potential sessionKey, algorithm pairs + * @async + */ + async decryptSessionKeys(decryptionKeys, passwords, date = new Date(), config = defaultConfig) { + let decryptedSessionKeyPackets = []; + + let exception; + if (passwords) { + const skeskPackets = this.packets.filterByTag(enums.packet.symEncryptedSessionKey); + if (skeskPackets.length === 0) { + throw new Error('No symmetrically encrypted session key packet found.'); + } + await Promise.all(passwords.map(async function(password, i) { + let packets; + if (i) { + packets = await PacketList.fromBinary(skeskPackets.write(), allowedSymSessionKeyPackets, config); + } else { + packets = skeskPackets; + } + await Promise.all(packets.map(async function(skeskPacket) { + try { + await skeskPacket.decrypt(password); + decryptedSessionKeyPackets.push(skeskPacket); + } catch (err) { + util.printDebugError(err); + } + })); + })); + } else if (decryptionKeys) { + const pkeskPackets = this.packets.filterByTag(enums.packet.publicKeyEncryptedSessionKey); + if (pkeskPackets.length === 0) { + throw new Error('No public key encrypted session key packet found.'); + } + await Promise.all(pkeskPackets.map(async function(pkeskPacket) { + await Promise.all(decryptionKeys.map(async function(decryptionKey) { + let algos = [ + enums.symmetric.aes256, // Old OpenPGP.js default fallback + enums.symmetric.aes128, // RFC4880bis fallback + enums.symmetric.tripledes, // RFC4880 fallback + enums.symmetric.cast5 // Golang OpenPGP fallback + ]; + try { + const primaryUser = await decryptionKey.getPrimaryUser(date, undefined, config); // TODO: Pass userID from somewhere. + if (primaryUser.selfCertification.preferredSymmetricAlgorithms) { + algos = algos.concat(primaryUser.selfCertification.preferredSymmetricAlgorithms); + } + } catch (e) {} + + // do not check key expiration to allow decryption of old messages + const decryptionKeyPackets = (await decryptionKey.getDecryptionKeys(pkeskPacket.publicKeyID, null, undefined, config)).map(key => key.keyPacket); + await Promise.all(decryptionKeyPackets.map(async function(decryptionKeyPacket) { + if (!decryptionKeyPacket || decryptionKeyPacket.isDummy()) { + return; + } + if (!decryptionKeyPacket.isDecrypted()) { + throw new Error('Decryption key is not decrypted.'); + } + + // To hinder CCA attacks against PKCS1, we carry out a constant-time decryption flow if the `constantTimePKCS1Decryption` config option is set. + const doConstantTimeDecryption = config.constantTimePKCS1Decryption && ( + pkeskPacket.publicKeyAlgorithm === enums.publicKey.rsaEncrypt || + pkeskPacket.publicKeyAlgorithm === enums.publicKey.rsaEncryptSign || + pkeskPacket.publicKeyAlgorithm === enums.publicKey.rsaSign || + pkeskPacket.publicKeyAlgorithm === enums.publicKey.elgamal + ); + + if (doConstantTimeDecryption) { + // The goal is to not reveal whether PKESK decryption (specifically the PKCS1 decoding step) failed, hence, we always proceed to decrypt the message, + // either with the successfully decrypted session key, or with a randomly generated one. + // Since the SEIP/AEAD's symmetric algorithm and key size are stored in the encrypted portion of the PKESK, and the execution flow cannot depend on + // the decrypted payload, we always assume the message to be encrypted with one of the symmetric algorithms specified in `config.constantTimePKCS1DecryptionSupportedSymmetricAlgorithms`: + // - If the PKESK decryption succeeds, and the session key cipher is in the supported set, then we try to decrypt the data with the decrypted session key as well as with the + // randomly generated keys of the remaining key types. + // - If the PKESK decryptions fails, or if it succeeds but support for the cipher is not enabled, then we discard the session key and try to decrypt the data using only the randomly + // generated session keys. + // NB: as a result, if the data is encrypted with a non-suported cipher, decryption will always fail. + + const serialisedPKESK = pkeskPacket.write(); // make copies to be able to decrypt the PKESK packet multiple times + await Promise.all(Array.from(config.constantTimePKCS1DecryptionSupportedSymmetricAlgorithms).map(async sessionKeyAlgorithm => { + const pkeskPacketCopy = new PublicKeyEncryptedSessionKeyPacket(); + pkeskPacketCopy.read(serialisedPKESK); + const randomSessionKey = { + sessionKeyAlgorithm, + sessionKey: await mod.generateSessionKey(sessionKeyAlgorithm) + }; + try { + await pkeskPacketCopy.decrypt(decryptionKeyPacket, randomSessionKey); + decryptedSessionKeyPackets.push(pkeskPacketCopy); + } catch (err) { + // `decrypt` can still throw some non-security-sensitive errors + util.printDebugError(err); + exception = err; + } + })); + + } else { + try { + await pkeskPacket.decrypt(decryptionKeyPacket); + if (!algos.includes(enums.write(enums.symmetric, pkeskPacket.sessionKeyAlgorithm))) { + throw new Error('A non-preferred symmetric algorithm was used.'); + } + decryptedSessionKeyPackets.push(pkeskPacket); + } catch (err) { + util.printDebugError(err); + exception = err; + } + } + })); + })); + cancel(pkeskPacket.encrypted); // Don't keep copy of encrypted data in memory. + pkeskPacket.encrypted = null; + })); + } else { + throw new Error('No key or password specified.'); + } -/** - * Tests whether n is probably prime or not using the Miller-Rabin test. - * See HAC Remark 4.28. - * @param {BN} n Number to test - * @param {Integer} k Optional number of iterations of Miller-Rabin test - * @param {Function} rand Optional function to generate potential witnesses - * @returns {boolean} - * @async - */ -async function millerRabin(n, k, rand) { - const len = n.bitLength(); - const red = _bn2.default.mont(n); - const rone = new _bn2.default(1).toRed(red); + if (decryptedSessionKeyPackets.length > 0) { + // Return only unique session keys + if (decryptedSessionKeyPackets.length > 1) { + const seen = new Set(); + decryptedSessionKeyPackets = decryptedSessionKeyPackets.filter(item => { + const k = item.sessionKeyAlgorithm + util.uint8ArrayToString(item.sessionKey); + if (seen.has(k)) { + return false; + } + seen.add(k); + return true; + }); + } - if (!k) { - k = Math.max(1, len / 48 | 0); + return decryptedSessionKeyPackets.map(packet => ({ + data: packet.sessionKey, + algorithm: enums.read(enums.symmetric, packet.sessionKeyAlgorithm) + })); + } + throw exception || new Error('Session key decryption failed.'); } - const n1 = n.subn(1); - const rn1 = n1.toRed(red); - - // Find d and s, (n - 1) = (2 ^ s) * d; - let s = 0; - while (!n1.testn(s)) { - s++; + /** + * Get literal data that is the body of the message + * @returns {(Uint8Array|null)} Literal body of the message as Uint8Array. + */ + getLiteralData() { + const msg = this.unwrapCompressed(); + const literal = msg.packets.findPacket(enums.packet.literalData); + return (literal && literal.getBytes()) || null; } - const d = n.shrn(s); - for (; k > 0; k--) { - const a = rand ? rand() : await _random2.default.getRandomBN(new _bn2.default(2), n1); + /** + * Get filename from literal data packet + * @returns {(String|null)} Filename of literal data packet as string. + */ + getFilename() { + const msg = this.unwrapCompressed(); + const literal = msg.packets.findPacket(enums.packet.literalData); + return (literal && literal.getFilename()) || null; + } - let x = a.toRed(red).redPow(d); - if (x.eq(rone) || x.eq(rn1)) { - continue; + /** + * Get literal data as text + * @returns {(String|null)} Literal body of the message interpreted as text. + */ + getText() { + const msg = this.unwrapCompressed(); + const literal = msg.packets.findPacket(enums.packet.literalData); + if (literal) { + return literal.getText(); } + return null; + } - let i; - for (i = 1; i < s; i++) { - x = x.redSqr(); + /** + * Generate a new session key object, taking the algorithm preferences of the passed encryption keys into account, if any. + * @param {Array} [encryptionKeys] - Public key(s) to select algorithm preferences for + * @param {Date} [date] - Date to select algorithm preferences at + * @param {Array} [userIDs] - User IDs to select algorithm preferences for + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise<{ data: Uint8Array, algorithm: String, aeadAlgorithm: undefined|String }>} Object with session key data and algorithms. + * @async + */ + static async generateSessionKey(encryptionKeys = [], date = new Date(), userIDs = [], config = defaultConfig) { + const algo = await getPreferredAlgo('symmetric', encryptionKeys, date, userIDs, config); + const algorithmName = enums.read(enums.symmetric, algo); + const aeadAlgorithmName = config.aeadProtect && await isAEADSupported(encryptionKeys, date, userIDs, config) ? + enums.read(enums.aead, await getPreferredAlgo('aead', encryptionKeys, date, userIDs, config)) : + undefined; - if (x.eq(rone)) { - return false; - } - if (x.eq(rn1)) { - break; - } - } + const sessionKeyData = await mod.generateSessionKey(algo); + return { data: sessionKeyData, algorithm: algorithmName, aeadAlgorithm: aeadAlgorithmName }; + } - if (i === s) { - return false; + /** + * Encrypt the message either with public keys, passwords, or both at once. + * @param {Array} [encryptionKeys] - Public key(s) for message encryption + * @param {Array} [passwords] - Password(s) for message encryption + * @param {Object} [sessionKey] - Session key in the form: { data:Uint8Array, algorithm:String, [aeadAlgorithm:String] } + * @param {Boolean} [wildcard] - Use a key ID of 0 instead of the public key IDs + * @param {Array} [encryptionKeyIDs] - Array of key IDs to use for encryption. Each encryptionKeyIDs[i] corresponds to keys[i] + * @param {Date} [date] - Override the creation date of the literal package + * @param {Array} [userIDs] - User IDs to encrypt for, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }] + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New message with encrypted content. + * @async + */ + async encrypt(encryptionKeys, passwords, sessionKey, wildcard = false, encryptionKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { + if (sessionKey) { + if (!util.isUint8Array(sessionKey.data) || !util.isString(sessionKey.algorithm)) { + throw new Error('Invalid session key for encryption.'); + } + } else if (encryptionKeys && encryptionKeys.length) { + sessionKey = await Message.generateSessionKey(encryptionKeys, date, userIDs, config); + } else if (passwords && passwords.length) { + sessionKey = await Message.generateSessionKey(undefined, undefined, undefined, config); + } else { + throw new Error('No keys, passwords, or session key provided.'); } - } - return true; -} + const { data: sessionKeyData, algorithm: algorithmName, aeadAlgorithm: aeadAlgorithmName } = sessionKey; -},{"../random":109,"bn.js":16}],108:[function(require,module,exports){ -'use strict'; + const msg = await Message.encryptSessionKey(sessionKeyData, algorithmName, aeadAlgorithmName, encryptionKeys, passwords, wildcard, encryptionKeyIDs, date, userIDs, config); -Object.defineProperty(exports, "__esModule", { - value: true -}); + let symEncryptedPacket; + if (aeadAlgorithmName) { + symEncryptedPacket = new AEADEncryptedDataPacket(); + symEncryptedPacket.aeadAlgorithm = enums.write(enums.aead, aeadAlgorithmName); + } else { + symEncryptedPacket = new SymEncryptedIntegrityProtectedDataPacket(); + } + symEncryptedPacket.packets = this.packets; -var _bn = require('bn.js'); + const algorithm = enums.write(enums.symmetric, algorithmName); + await symEncryptedPacket.encrypt(algorithm, sessionKeyData, config); -var _bn2 = _interopRequireDefault(_bn); + msg.packets.push(symEncryptedPacket); + symEncryptedPacket.packets = new PacketList(); // remove packets after encryption + return msg; + } -var _prime = require('./prime'); + /** + * Encrypt a session key either with public keys, passwords, or both at once. + * @param {Uint8Array} sessionKey - session key for encryption + * @param {String} algorithmName - session key algorithm + * @param {String} [aeadAlgorithmName] - AEAD algorithm, e.g. 'eax' or 'ocb' + * @param {Array} [encryptionKeys] - Public key(s) for message encryption + * @param {Array} [passwords] - For message encryption + * @param {Boolean} [wildcard] - Use a key ID of 0 instead of the public key IDs + * @param {Array} [encryptionKeyIDs] - Array of key IDs to use for encryption. Each encryptionKeyIDs[i] corresponds to encryptionKeys[i] + * @param {Date} [date] - Override the date + * @param {Array} [userIDs] - User IDs to encrypt for, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }] + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New message with encrypted content. + * @async + */ + static async encryptSessionKey(sessionKey, algorithmName, aeadAlgorithmName, encryptionKeys, passwords, wildcard = false, encryptionKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { + const packetlist = new PacketList(); + const algorithm = enums.write(enums.symmetric, algorithmName); + const aeadAlgorithm = aeadAlgorithmName && enums.write(enums.aead, aeadAlgorithmName); + + if (encryptionKeys) { + const results = await Promise.all(encryptionKeys.map(async function(primaryKey, i) { + const encryptionKey = await primaryKey.getEncryptionKey(encryptionKeyIDs[i], date, userIDs, config); + const pkESKeyPacket = new PublicKeyEncryptedSessionKeyPacket(); + pkESKeyPacket.publicKeyID = wildcard ? KeyID.wildcard() : encryptionKey.getKeyID(); + pkESKeyPacket.publicKeyAlgorithm = encryptionKey.keyPacket.algorithm; + pkESKeyPacket.sessionKey = sessionKey; + pkESKeyPacket.sessionKeyAlgorithm = algorithm; + await pkESKeyPacket.encrypt(encryptionKey.keyPacket); + delete pkESKeyPacket.sessionKey; // delete plaintext session key after encryption + return pkESKeyPacket; + })); + packetlist.push(...results); + } + if (passwords) { + const testDecrypt = async function(keyPacket, password) { + try { + await keyPacket.decrypt(password); + return 1; + } catch (e) { + return 0; + } + }; -var _prime2 = _interopRequireDefault(_prime); + const sum = (accumulator, currentValue) => accumulator + currentValue; -var _random = require('../random'); + const encryptPassword = async function(sessionKey, algorithm, aeadAlgorithm, password) { + const symEncryptedSessionKeyPacket = new SymEncryptedSessionKeyPacket(config); + symEncryptedSessionKeyPacket.sessionKey = sessionKey; + symEncryptedSessionKeyPacket.sessionKeyAlgorithm = algorithm; + if (aeadAlgorithm) { + symEncryptedSessionKeyPacket.aeadAlgorithm = aeadAlgorithm; + } + await symEncryptedSessionKeyPacket.encrypt(password, config); -var _random2 = _interopRequireDefault(_random); + if (config.passwordCollisionCheck) { + const results = await Promise.all(passwords.map(pwd => testDecrypt(symEncryptedSessionKeyPacket, pwd))); + if (results.reduce(sum) !== 1) { + return encryptPassword(sessionKey, algorithm, password); + } + } -var _config = require('../../config'); + delete symEncryptedSessionKeyPacket.sessionKey; // delete plaintext session key after encryption + return symEncryptedSessionKeyPacket; + }; -var _config2 = _interopRequireDefault(_config); + const results = await Promise.all(passwords.map(pwd => encryptPassword(sessionKey, algorithm, aeadAlgorithm, pwd))); + packetlist.push(...results); + } -var _util = require('../../util'); + return new Message(packetlist); + } -var _util2 = _interopRequireDefault(_util); + /** + * Sign the message (the literal data packet of the message) + * @param {Array} signingKeys - private keys with decrypted secret key data for signing + * @param {Signature} [signature] - Any existing detached signature to add to the message + * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] + * @param {Date} [date] - Override the creation time of the signature + * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New message with signed content. + * @async + */ + async sign(signingKeys = [], signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { + const packetlist = new PacketList(); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + const literalDataPacket = this.packets.findPacket(enums.packet.literalData); + if (!literalDataPacket) { + throw new Error('No literal data packet to sign.'); + } -// Helper for IE11 KeyOperation objects -function promisifyIE11Op(keyObj, err) { - if (typeof keyObj.then !== 'function') { - // IE11 KeyOperation - return new Promise(function (resolve, reject) { - keyObj.onerror = function () { - reject(new Error(err)); - }; - keyObj.oncomplete = function (e) { - resolve(e.target.result); - }; + let i; + let existingSigPacketlist; + // If data packet was created from Uint8Array, use binary, otherwise use text + const signatureType = literalDataPacket.text === null ? + enums.signature.binary : enums.signature.text; + + if (signature) { + existingSigPacketlist = signature.packets.filterByTag(enums.packet.signature); + for (i = existingSigPacketlist.length - 1; i >= 0; i--) { + const signaturePacket = existingSigPacketlist[i]; + const onePassSig = new OnePassSignaturePacket(); + onePassSig.signatureType = signaturePacket.signatureType; + onePassSig.hashAlgorithm = signaturePacket.hashAlgorithm; + onePassSig.publicKeyAlgorithm = signaturePacket.publicKeyAlgorithm; + onePassSig.issuerKeyID = signaturePacket.issuerKeyID; + if (!signingKeys.length && i === 0) { + onePassSig.flags = 1; + } + packetlist.push(onePassSig); + } + } + + await Promise.all(Array.from(signingKeys).reverse().map(async function (primaryKey, i) { + if (!primaryKey.isPrivate()) { + throw new Error('Need private key for signing'); + } + const signingKeyID = signingKeyIDs[signingKeys.length - 1 - i]; + const signingKey = await primaryKey.getSigningKey(signingKeyID, date, userIDs, config); + const onePassSig = new OnePassSignaturePacket(); + onePassSig.signatureType = signatureType; + onePassSig.hashAlgorithm = await getPreferredHashAlgo$1(primaryKey, signingKey.keyPacket, date, userIDs, config); + onePassSig.publicKeyAlgorithm = signingKey.keyPacket.algorithm; + onePassSig.issuerKeyID = signingKey.getKeyID(); + if (i === signingKeys.length - 1) { + onePassSig.flags = 1; + } + return onePassSig; + })).then(onePassSignatureList => { + onePassSignatureList.forEach(onePassSig => packetlist.push(onePassSig)); }); - } - return keyObj; -} // GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -/** - * @fileoverview RSA implementation - * @requires bn.js - * @requires crypto/public_key/prime - * @requires crypto/random - * @requires config - * @requires util - * @module crypto/public_key/rsa - */ + packetlist.push(literalDataPacket); + packetlist.push(...(await createSignaturePackets(literalDataPacket, signingKeys, signature, signingKeyIDs, date, userIDs, false, config))); -exports.default = { - /** Create signature - * @param {BN} m message - * @param {BN} n RSA public modulus - * @param {BN} e RSA public exponent - * @param {BN} d RSA private exponent - * @returns {BN} RSA Signature - * @async + return new Message(packetlist); + } + + /** + * Compresses the message (the literal and -if signed- signature data packets of the message) + * @param {module:enums.compression} algo - compression algorithm + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Message} New message with compressed content. */ - sign: async function sign(m, n, e, d) { - if (n.cmp(m) <= 0) { - throw new Error('Message size cannot exceed modulus size'); + compress(algo, config = defaultConfig) { + if (algo === enums.compression.uncompressed) { + return this; } - const nred = new _bn2.default.red(n); - return m.toRed(nred).redPow(d).toArrayLike(Uint8Array, 'be', n.byteLength()); - }, + + const compressed = new CompressedDataPacket(config); + compressed.algorithm = algo; + compressed.packets = this.packets; + + const packetList = new PacketList(); + packetList.push(compressed); + + return new Message(packetList); + } /** - * Verify signature - * @param {BN} s signature - * @param {BN} n RSA public modulus - * @param {BN} e RSA public exponent - * @returns {BN} + * Create a detached signature for the message (the literal data packet of the message) + * @param {Array} signingKeys - private keys with decrypted secret key data for signing + * @param {Signature} [signature] - Any existing detached signature + * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] + * @param {Date} [date] - Override the creation time of the signature + * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New detached signature of message content. * @async */ - verify: async function verify(s, n, e) { - if (n.cmp(s) <= 0) { - throw new Error('Signature size cannot exceed modulus size'); + async signDetached(signingKeys = [], signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { + const literalDataPacket = this.packets.findPacket(enums.packet.literalData); + if (!literalDataPacket) { + throw new Error('No literal data packet to sign.'); } - const nred = new _bn2.default.red(n); - return s.toRed(nred).redPow(e).toArrayLike(Uint8Array, 'be', n.byteLength()); - }, + return new Signature(await createSignaturePackets(literalDataPacket, signingKeys, signature, signingKeyIDs, date, userIDs, true, config)); + } /** - * Encrypt message - * @param {BN} m message - * @param {BN} n RSA public modulus - * @param {BN} e RSA public exponent - * @returns {BN} RSA Ciphertext + * Verify message signatures + * @param {Array} verificationKeys - Array of public keys to verify signatures + * @param {Date} [date] - Verify the signature against the given date, i.e. check signature creation time < date < expiration time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise, + * verified: Promise + * }>>} List of signer's keyID and validity of signatures. * @async */ - encrypt: async function encrypt(m, n, e) { - if (n.cmp(m) <= 0) { - throw new Error('Message size cannot exceed modulus size'); + async verify(verificationKeys, date = new Date(), config = defaultConfig) { + const msg = this.unwrapCompressed(); + const literalDataList = msg.packets.filterByTag(enums.packet.literalData); + if (literalDataList.length !== 1) { + throw new Error('Can only verify message with one literal data packet.'); + } + if (isArrayStream(msg.packets.stream)) { + msg.packets.push(...await readToEnd(msg.packets.stream, _ => _ || [])); + } + const onePassSigList = msg.packets.filterByTag(enums.packet.onePassSignature).reverse(); + const signatureList = msg.packets.filterByTag(enums.packet.signature); + if (onePassSigList.length && !signatureList.length && util.isStream(msg.packets.stream) && !isArrayStream(msg.packets.stream)) { + await Promise.all(onePassSigList.map(async onePassSig => { + onePassSig.correspondingSig = new Promise((resolve, reject) => { + onePassSig.correspondingSigResolve = resolve; + onePassSig.correspondingSigReject = reject; + }); + onePassSig.signatureData = fromAsync(async () => (await onePassSig.correspondingSig).signatureData); + onePassSig.hashed = readToEnd(await onePassSig.hash(onePassSig.signatureType, literalDataList[0], undefined, false)); + onePassSig.hashed.catch(() => {}); + })); + msg.packets.stream = transformPair(msg.packets.stream, async (readable, writable) => { + const reader = getReader(readable); + const writer = getWriter(writable); + try { + for (let i = 0; i < onePassSigList.length; i++) { + const { value: signature } = await reader.read(); + onePassSigList[i].correspondingSigResolve(signature); + } + await reader.readToEnd(); + await writer.ready; + await writer.close(); + } catch (e) { + onePassSigList.forEach(onePassSig => { + onePassSig.correspondingSigReject(e); + }); + await writer.abort(e); + } + }); + return createVerificationObjects(onePassSigList, literalDataList, verificationKeys, date, false, config); } - const nred = new _bn2.default.red(n); - return m.toRed(nred).redPow(e).toArrayLike(Uint8Array, 'be', n.byteLength()); - }, + return createVerificationObjects(signatureList, literalDataList, verificationKeys, date, false, config); + } /** - * Decrypt RSA message - * @param {BN} m message - * @param {BN} n RSA public modulus - * @param {BN} e RSA public exponent - * @param {BN} d RSA private exponent - * @param {BN} p RSA private prime p - * @param {BN} q RSA private prime q - * @param {BN} u RSA private inverse of prime q - * @returns {BN} RSA Plaintext + * Verify detached message signature + * @param {Array} verificationKeys - Array of public keys to verify signatures + * @param {Signature} signature + * @param {Date} date - Verify the signature against the given date, i.e. check signature creation time < date < expiration time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise, + * verified: Promise + * }>>} List of signer's keyID and validity of signature. * @async */ - decrypt: async function decrypt(m, n, e, d, p, q, u) { - if (n.cmp(m) <= 0) { - throw new Error('Data too large.'); + verifyDetached(signature, verificationKeys, date = new Date(), config = defaultConfig) { + const msg = this.unwrapCompressed(); + const literalDataList = msg.packets.filterByTag(enums.packet.literalData); + if (literalDataList.length !== 1) { + throw new Error('Can only verify message with one literal data packet.'); } - const dq = d.mod(q.subn(1)); // d mod (q-1) - const dp = d.mod(p.subn(1)); // d mod (p-1) - const pred = new _bn2.default.red(p); - const qred = new _bn2.default.red(q); - const nred = new _bn2.default.red(n); + const signatureList = signature.packets; + return createVerificationObjects(signatureList, literalDataList, verificationKeys, date, true, config); + } - let blinder; - let unblinder; - if (_config2.default.rsa_blinding) { - unblinder = (await _random2.default.getRandomBN(new _bn2.default(2), n)).toRed(nred); - blinder = unblinder.redInvm().redPow(e); - m = m.toRed(nred).redMul(blinder).fromRed(); + /** + * Unwrap compressed message + * @returns {Message} Message Content of compressed message. + */ + unwrapCompressed() { + const compressed = this.packets.filterByTag(enums.packet.compressedData); + if (compressed.length) { + return new Message(compressed[0].packets); } + return this; + } - const mp = m.toRed(pred).redPow(dp); - const mq = m.toRed(qred).redPow(dq); - const t = mq.redSub(mp.fromRed().toRed(qred)); - const h = u.toRed(qred).redMul(t).fromRed(); - - let result = h.mul(p).add(mp).toRed(nred); - - if (_config2.default.rsa_blinding) { - result = result.redMul(unblinder); - } + /** + * Append signature to unencrypted message object + * @param {String|Uint8Array} detachedSignature - The detached ASCII-armored or Uint8Array PGP signature + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + async appendSignature(detachedSignature, config = defaultConfig) { + await this.packets.read( + util.isUint8Array(detachedSignature) ? detachedSignature : (await unarmor(detachedSignature)).data, + allowedDetachedSignaturePackets, + config + ); + } - return result.toArrayLike(Uint8Array, 'be', n.byteLength()); - }, + /** + * Returns binary encoded message + * @returns {ReadableStream} Binary message. + */ + write() { + return this.packets.write(); + } /** - * Generate a new random private key B bits long with public exponent E. - * - * When possible, webCrypto is used. Otherwise, primes are generated using - * 40 rounds of the Miller-Rabin probabilistic random prime generation algorithm. - * @see module:crypto/public_key/prime - * @param {Integer} B RSA bit length - * @param {String} E RSA public exponent in hex string - * @returns {{n: BN, e: BN, d: BN, - * p: BN, q: BN, u: BN}} RSA public modulus, RSA public exponent, RSA private exponent, - * RSA private prime p, RSA private prime q, u = q ** -1 mod p - * @async + * Returns ASCII armored text of message + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {ReadableStream} ASCII armor. */ - generate: async function generate(B, E) { - let key; - E = new _bn2.default(E, 16); - const webCrypto = _util2.default.getWebCryptoAll(); - - // Native RSA keygen using Web Crypto - if (webCrypto) { - let keyPair; - let keyGenOpt; - if (window.crypto && window.crypto.subtle || window.msCrypto) { - // current standard spec - keyGenOpt = { - name: 'RSASSA-PKCS1-v1_5', - modulusLength: B, // the specified keysize in bits - publicExponent: E.toArrayLike(Uint8Array), // take three bytes (max 65537) for exponent - hash: { - name: 'SHA-1' // not required for actual RSA keys, but for crypto api 'sign' and 'verify' - } - }; - keyPair = webCrypto.generateKey(keyGenOpt, true, ['sign', 'verify']); - keyPair = await promisifyIE11Op(keyPair, 'Error generating RSA key pair.'); - } else if (window.crypto && window.crypto.webkitSubtle) { - // outdated spec implemented by old Webkit - keyGenOpt = { - name: 'RSA-OAEP', - modulusLength: B, // the specified keysize in bits - publicExponent: E.toArrayLike(Uint8Array), // take three bytes (max 65537) for exponent - hash: { - name: 'SHA-1' // not required for actual RSA keys, but for crypto api 'sign' and 'verify' - } - }; - keyPair = await webCrypto.generateKey(keyGenOpt, true, ['encrypt', 'decrypt']); - } else { - throw new Error('Unknown WebCrypto implementation'); - } + armor(config = defaultConfig) { + return armor(enums.armor.message, this.write(), null, null, null, config); + } +} - // export the generated keys as JsonWebKey (JWK) - // https://tools.ietf.org/html/draft-ietf-jose-json-web-key-33 - let jwk = webCrypto.exportKey('jwk', keyPair.privateKey); - jwk = await promisifyIE11Op(jwk, 'Error exporting RSA key pair.'); +/** + * Create signature packets for the message + * @param {LiteralDataPacket} literalDataPacket - the literal data packet to sign + * @param {Array} [signingKeys] - private keys with decrypted secret key data for signing + * @param {Signature} [signature] - Any existing detached signature to append + * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] + * @param {Date} [date] - Override the creationtime of the signature + * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] + * @param {Boolean} [detached] - Whether to create detached signature packets + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} List of signature packets. + * @async + * @private + */ +async function createSignaturePackets(literalDataPacket, signingKeys, signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], detached = false, config = defaultConfig) { + const packetlist = new PacketList(); - // parse raw ArrayBuffer bytes to jwk/json (WebKit/Safari/IE11 quirk) - if (jwk instanceof ArrayBuffer) { - jwk = JSON.parse(String.fromCharCode.apply(null, new Uint8Array(jwk))); - } + // If data packet was created from Uint8Array, use binary, otherwise use text + const signatureType = literalDataPacket.text === null ? + enums.signature.binary : enums.signature.text; - // map JWK parameters to BN - key = {}; - key.n = new _bn2.default(_util2.default.b64_to_Uint8Array(jwk.n)); - key.e = E; - key.d = new _bn2.default(_util2.default.b64_to_Uint8Array(jwk.d)); - key.p = new _bn2.default(_util2.default.b64_to_Uint8Array(jwk.p)); - key.q = new _bn2.default(_util2.default.b64_to_Uint8Array(jwk.q)); - key.u = key.p.invm(key.q); - return key; + await Promise.all(signingKeys.map(async (primaryKey, i) => { + const userID = userIDs[i]; + if (!primaryKey.isPrivate()) { + throw new Error('Need private key for signing'); } + const signingKey = await primaryKey.getSigningKey(signingKeyIDs[i], date, userID, config); + return createSignaturePacket(literalDataPacket, primaryKey, signingKey.keyPacket, { signatureType }, date, userID, detached, config); + })).then(signatureList => { + packetlist.push(...signatureList); + }); + + if (signature) { + const existingSigPacketlist = signature.packets.filterByTag(enums.packet.signature); + packetlist.push(...existingSigPacketlist); + } + return packetlist; +} - // RSA keygen fallback using 40 iterations of the Miller-Rabin test - // See https://stackoverflow.com/a/6330138 for justification - // Also see section C.3 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST - let p = await _prime2.default.randomProbablePrime(B - (B >> 1), E, 40); - let q = await _prime2.default.randomProbablePrime(B >> 1, E, 40); +/** + * Create object containing signer's keyID and validity of signature + * @param {SignaturePacket} signature - Signature packet + * @param {Array} literalDataList - Array of literal data packets + * @param {Array} verificationKeys - Array of public keys to verify signatures + * @param {Date} [date] - Check signature validity with respect to the given date + * @param {Boolean} [detached] - Whether to verify detached signature packets + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise<{ + * keyID: module:type/keyid~KeyID, + * signature: Promise, + * verified: Promise + * }>} signer's keyID and validity of signature + * @async + * @private + */ +async function createVerificationObject(signature, literalDataList, verificationKeys, date = new Date(), detached = false, config = defaultConfig) { + let primaryKey; + let unverifiedSigningKey; - if (p.cmp(q) < 0) { - var _ref = [q, p]; - p = _ref[0]; - q = _ref[1]; + for (const key of verificationKeys) { + const issuerKeys = key.getKeys(signature.issuerKeyID); + if (issuerKeys.length > 0) { + primaryKey = key; + unverifiedSigningKey = issuerKeys[0]; + break; } + } - const phi = p.subn(1).mul(q.subn(1)); - return { - n: p.mul(q), - e: E, - d: E.invm(phi), - p: p, - q: q, - // dp: d.mod(p.subn(1)), - // dq: d.mod(q.subn(1)), - u: p.invm(q) - }; - }, + const isOnePassSignature = signature instanceof OnePassSignaturePacket; + const signaturePacketPromise = isOnePassSignature ? signature.correspondingSig : signature; - prime: _prime2.default -}; + const verifiedSig = { + keyID: signature.issuerKeyID, + verified: (async () => { + if (!unverifiedSigningKey) { + throw new Error(`Could not find signing key with key ID ${signature.issuerKeyID.toHex()}`); + } -},{"../../config":79,"../../util":152,"../random":109,"./prime":107,"bn.js":16}],109:[function(require,module,exports){ -'use strict'; + await signature.verify(unverifiedSigningKey.keyPacket, signature.signatureType, literalDataList[0], date, detached, config); + const signaturePacket = await signaturePacketPromise; + if (unverifiedSigningKey.getCreationTime() > signaturePacket.created) { + throw new Error('Key is newer than the signature'); + } + // We pass the signature creation time to check whether the key was expired at the time of signing. + // We check this after signature verification because for streamed one-pass signatures, the creation time is not available before + try { + await primaryKey.getSigningKey(unverifiedSigningKey.getKeyID(), signaturePacket.created, undefined, config); + } catch (e) { + // If a key was reformatted then the self-signatures of the signing key might be in the future compared to the message signature, + // making the key invalid at the time of signing. + // However, if the key is valid at the given `date`, we still allow using it provided the relevant `config` setting is enabled. + // Note: we do not support the edge case of a key that was reformatted and it has expired. + if (config.allowInsecureVerificationWithReformattedKeys && e.message.match(/Signature creation time is in the future/)) { + await primaryKey.getSigningKey(unverifiedSigningKey.getKeyID(), date, undefined, config); + } else { + throw e; + } + } + return true; + })(), + signature: (async () => { + const signaturePacket = await signaturePacketPromise; + const packetlist = new PacketList(); + signaturePacket && packetlist.push(signaturePacket); + return new Signature(packetlist); + })() + }; -Object.defineProperty(exports, "__esModule", { - value: true -}); + // Mark potential promise rejections as "handled". This is needed because in + // some cases, we reject them before the user has a reasonable chance to + // handle them (e.g. `await readToEnd(result.data); await result.verified` and + // the data stream errors). + verifiedSig.signature.catch(() => {}); + verifiedSig.verified.catch(() => {}); -var _bn = require('bn.js'); + return verifiedSig; +} -var _bn2 = _interopRequireDefault(_bn); +/** + * Create list of objects containing signer's keyID and validity of signature + * @param {Array} signatureList - Array of signature packets + * @param {Array} literalDataList - Array of literal data packets + * @param {Array} verificationKeys - Array of public keys to verify signatures + * @param {Date} date - Verify the signature against the given date, + * i.e. check signature creation time < date < expiration time + * @param {Boolean} [detached] - Whether to verify detached signature packets + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise, + * verified: Promise + * }>>} list of signer's keyID and validity of signatures (one entry per signature packet in input) + * @async + * @private + */ +async function createVerificationObjects(signatureList, literalDataList, verificationKeys, date = new Date(), detached = false, config = defaultConfig) { + return Promise.all(signatureList.filter(function(signature) { + return ['text', 'binary'].includes(enums.read(enums.signature, signature.signatureType)); + }).map(async function(signature) { + return createVerificationObject(signature, literalDataList, verificationKeys, date, detached, config); + })); +} -var _util = require('../util'); +/** + * Reads an (optionally armored) OpenPGP message and returns a Message object + * @param {Object} options + * @param {String | ReadableStream} [options.armoredMessage] - Armored message to be parsed + * @param {Uint8Array | ReadableStream} [options.binaryMessage] - Binary to be parsed + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} New message object. + * @async + * @static + */ +async function readMessage({ armoredMessage, binaryMessage, config, ...rest }) { + config = { ...defaultConfig, ...config }; + let input = armoredMessage || binaryMessage; + if (!input) { + throw new Error('readMessage: must pass options object containing `armoredMessage` or `binaryMessage`'); + } + if (armoredMessage && !util.isString(armoredMessage) && !util.isStream(armoredMessage)) { + throw new Error('readMessage: options.armoredMessage must be a string or stream'); + } + if (binaryMessage && !util.isUint8Array(binaryMessage) && !util.isStream(binaryMessage)) { + throw new Error('readMessage: options.binaryMessage must be a Uint8Array or stream'); + } + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); -var _util2 = _interopRequireDefault(_util); + const streamType = util.isStream(input); + if (streamType) { + await loadStreamsPonyfill(); + input = toStream(input); + } + if (armoredMessage) { + const { type, data } = await unarmor(input, config); + if (type !== enums.armor.message) { + throw new Error('Armored text not of type message'); + } + input = data; + } + const packetlist = await PacketList.fromBinary(input, allowedMessagePackets, config); + const message = new Message(packetlist); + message.fromStream = streamType; + return message; +} -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +/** + * Creates new message object from text or binary data. + * @param {Object} options + * @param {String | ReadableStream} [options.text] - The text message contents + * @param {Uint8Array | ReadableStream} [options.binary] - The binary message contents + * @param {String} [options.filename=""] - Name of the file (if any) + * @param {Date} [options.date=current date] - Date of the message, or modification date of the file + * @param {'utf8'|'binary'|'text'|'mime'} [options.format='utf8' if text is passed, 'binary' otherwise] - Data packet type + * @returns {Promise} New message object. + * @async + * @static + */ +async function createMessage({ text, binary, filename, date = new Date(), format = text !== undefined ? 'utf8' : 'binary', ...rest }) { + let input = text !== undefined ? text : binary; + if (input === undefined) { + throw new Error('createMessage: must pass options object containing `text` or `binary`'); + } + if (text && !util.isString(text) && !util.isStream(text)) { + throw new Error('createMessage: options.text must be a string or stream'); + } + if (binary && !util.isUint8Array(binary) && !util.isStream(binary)) { + throw new Error('createMessage: options.binary must be a Uint8Array or stream'); + } + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); -// Do not use util.getNodeCrypto because we need this regardless of use_native setting -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + const streamType = util.isStream(input); + if (streamType) { + await loadStreamsPonyfill(); + input = toStream(input); + } + const literalDataPacket = new LiteralDataPacket(date); + if (text !== undefined) { + literalDataPacket.setText(input, enums.write(enums.literal, format)); + } else { + literalDataPacket.setBytes(input, enums.write(enums.literal, format)); + } + if (filename !== undefined) { + literalDataPacket.setFilename(filename); + } + const literalDataPacketlist = new PacketList(); + literalDataPacketlist.push(literalDataPacket); + const message = new Message(literalDataPacketlist); + message.fromStream = streamType; + return message; +} + +// GPG4Browsers - An OpenPGP implementation in javascript -// The GPG4Browsers crypto interface +// A Cleartext message can contain the following packets +const allowedPackets$5 = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); /** - * @fileoverview Provides tools for retrieving secure randomness from browsers or Node.js - * @requires bn.js - * @requires util - * @module crypto/random + * Class that represents an OpenPGP cleartext signed message. + * See {@link https://tools.ietf.org/html/rfc4880#section-7} */ +class CleartextMessage { + /** + * @param {String} text - The cleartext of the signed message + * @param {Signature} signature - The detached signature or an empty signature for unsigned messages + */ + constructor(text, signature) { + // normalize EOL to canonical form + this.text = util.removeTrailingSpaces(text).replace(/\r?\n/g, '\r\n'); + if (signature && !(signature instanceof Signature)) { + throw new Error('Invalid signature input'); + } + this.signature = signature || new Signature(new PacketList()); + } -const nodeCrypto = _util2.default.detectNode() && require('crypto'); + /** + * Returns the key IDs of the keys that signed the cleartext message + * @returns {Array} Array of keyID objects. + */ + getSigningKeyIDs() { + const keyIDs = []; + const signatureList = this.signature.packets; + signatureList.forEach(function(packet) { + keyIDs.push(packet.issuerKeyID); + }); + return keyIDs; + } -exports.default = { /** - * Retrieve secure random byte array of the specified length - * @param {Integer} length Length in bytes to generate - * @returns {Uint8Array} Random byte array + * Sign the cleartext message + * @param {Array} privateKeys - private keys with decrypted secret key data for signing + * @param {Signature} [signature] - Any existing detached signature + * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to privateKeys[i] + * @param {Date} [date] - The creation time of the signature that should be created + * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New cleartext message with signed content. * @async */ - getRandomBytes: async function getRandomBytes(length) { - const buf = new Uint8Array(length); - if (typeof window !== 'undefined' && window.crypto && window.crypto.getRandomValues) { - window.crypto.getRandomValues(buf); - } else if (typeof window !== 'undefined' && typeof window.msCrypto === 'object' && typeof window.msCrypto.getRandomValues === 'function') { - window.msCrypto.getRandomValues(buf); - } else if (nodeCrypto) { - const bytes = nodeCrypto.randomBytes(buf.length); - buf.set(bytes); - } else if (this.randomBuffer.buffer) { - await this.randomBuffer.get(buf); - } else { - throw new Error('No secure random number generator available.'); - } - return buf; - }, + async sign(privateKeys, signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { + const literalDataPacket = new LiteralDataPacket(); + literalDataPacket.setText(this.text); + const newSignature = new Signature(await createSignaturePackets(literalDataPacket, privateKeys, signature, signingKeyIDs, date, userIDs, true, config)); + return new CleartextMessage(this.text, newSignature); + } /** - * Create a secure random MPI that is greater than or equal to min and less than max. - * @param {module:type/mpi} min Lower bound, included - * @param {module:type/mpi} max Upper bound, excluded - * @returns {module:BN} Random MPI + * Verify signatures of cleartext signed message + * @param {Array} keys - Array of keys to verify signatures + * @param {Date} [date] - Verify the signature against the given date, i.e. check signature creation time < date < expiration time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise, + * verified: Promise + * }>>} List of signer's keyID and validity of signature. * @async */ - getRandomBN: async function getRandomBN(min, max) { - if (max.cmp(min) <= 0) { - throw new Error('Illegal parameter value: max <= min'); - } - - const modulus = max.sub(min); - const bytes = modulus.byteLength(); + verify(keys, date = new Date(), config = defaultConfig) { + const signatureList = this.signature.packets; + const literalDataPacket = new LiteralDataPacket(); + // we assume that cleartext signature is generated based on UTF8 cleartext + literalDataPacket.setText(this.text); + return createVerificationObjects(signatureList, [literalDataPacket], keys, date, true, config); + } - // Using a while loop is necessary to avoid bias introduced by the mod operation. - // However, we request 64 extra random bits so that the bias is negligible. - // Section B.1.1 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - const r = new _bn2.default((await this.getRandomBytes(bytes + 8))); - return r.mod(modulus).add(min); - }, + /** + * Get cleartext + * @returns {String} Cleartext of message. + */ + getText() { + // normalize end of line to \n + return this.text.replace(/\r\n/g, '\n'); + } - randomBuffer: new RandomBuffer() -}; + /** + * Returns ASCII armored text of cleartext signed message + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {String | ReadableStream} ASCII armor. + */ + armor(config = defaultConfig) { + let hashes = this.signature.packets.map(function(packet) { + return enums.read(enums.hash, packet.hashAlgorithm).toUpperCase(); + }); + hashes = hashes.filter(function(item, i, ar) { return ar.indexOf(item) === i; }); + const body = { + hash: hashes.join(), + text: this.text, + data: this.signature.packets.write() + }; + return armor(enums.armor.signed, body, undefined, undefined, undefined, config); + } +} /** - * Buffer for secure random numbers + * Reads an OpenPGP cleartext signed message and returns a CleartextMessage object + * @param {Object} options + * @param {String} options.cleartextMessage - Text to be parsed + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} New cleartext message object. + * @async + * @static */ +async function readCleartextMessage({ cleartextMessage, config, ...rest }) { + config = { ...defaultConfig, ...config }; + if (!cleartextMessage) { + throw new Error('readCleartextMessage: must pass options object containing `cleartextMessage`'); + } + if (!util.isString(cleartextMessage)) { + throw new Error('readCleartextMessage: options.cleartextMessage must be a string'); + } + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); -function RandomBuffer() { - this.buffer = null; - this.size = null; - this.callback = null; + const input = await unarmor(cleartextMessage); + if (input.type !== enums.armor.signed) { + throw new Error('No cleartext signed message.'); + } + const packetlist = await PacketList.fromBinary(input.data, allowedPackets$5, config); + verifyHeaders$1(input.headers, packetlist); + const signature = new Signature(packetlist); + return new CleartextMessage(input.text, signature); } /** - * Initialize buffer - * @param {Integer} size size of buffer + * Compare hash algorithm specified in the armor header with signatures + * @param {Array} headers - Armor headers + * @param {PacketList} packetlist - The packetlist with signature packets + * @private */ -RandomBuffer.prototype.init = function (size, callback) { - this.buffer = new Uint8Array(size); - this.size = 0; - this.callback = callback; -}; +function verifyHeaders$1(headers, packetlist) { + const checkHashAlgos = function(hashAlgos) { + const check = packet => algo => packet.hashAlgorithm === algo; -/** - * Concat array of secure random numbers to buffer - * @param {Uint8Array} buf - */ -RandomBuffer.prototype.set = function (buf) { - if (!this.buffer) { - throw new Error('RandomBuffer is not initialized'); - } - if (!(buf instanceof Uint8Array)) { - throw new Error('Invalid type: buf not an Uint8Array'); - } - const freeSpace = this.buffer.length - this.size; - if (buf.length > freeSpace) { - buf = buf.subarray(0, freeSpace); + for (let i = 0; i < packetlist.length; i++) { + if (packetlist[i].constructor.tag === enums.packet.signature && !hashAlgos.some(check(packetlist[i]))) { + return false; + } + } + return true; + }; + + let oneHeader = null; + let hashAlgos = []; + headers.forEach(function(header) { + oneHeader = header.match(/Hash: (.+)/); // get header value + if (oneHeader) { + oneHeader = oneHeader[1].replace(/\s/g, ''); // remove whitespace + oneHeader = oneHeader.split(','); + oneHeader = oneHeader.map(function(hash) { + hash = hash.toLowerCase(); + try { + return enums.write(enums.hash, hash); + } catch (e) { + throw new Error('Unknown hash algorithm in armor header: ' + hash); + } + }); + hashAlgos = hashAlgos.concat(oneHeader); + } else { + throw new Error('Only "Hash" header allowed in cleartext signed message'); + } + }); + + if (!hashAlgos.length && !checkHashAlgos([enums.hash.md5])) { + throw new Error('If no "Hash" header in cleartext signed message, then only MD5 signatures allowed'); + } else if (hashAlgos.length && !checkHashAlgos(hashAlgos)) { + throw new Error('Hash algorithm mismatch in armor header and signature'); } - // set buf with offset old size of buffer - this.buffer.set(buf, this.size); - this.size += buf.length; -}; +} /** - * Take numbers out of buffer and copy to array - * @param {Uint8Array} buf the destination array + * Creates a new CleartextMessage object from text + * @param {Object} options + * @param {String} options.text + * @static + * @async */ -RandomBuffer.prototype.get = async function (buf) { - if (!this.buffer) { - throw new Error('RandomBuffer is not initialized'); - } - if (!(buf instanceof Uint8Array)) { - throw new Error('Invalid type: buf not an Uint8Array'); - } - if (this.size < buf.length) { - if (!this.callback) { - throw new Error('Random number buffer depleted'); - } - // Wait for random bytes from main context, then try again - await this.callback(); - return this.get(buf); +async function createCleartextMessage({ text, ...rest }) { + if (!text) { + throw new Error('createCleartextMessage: must pass options object containing `text`'); } - for (let i = 0; i < buf.length; i++) { - buf[i] = this.buffer[--this.size]; - // clear buffer value - this.buffer[this.size] = 0; + if (!util.isString(text)) { + throw new Error('createCleartextMessage: options.text must be a string'); } -}; - -},{"../util":152,"bn.js":16,"crypto":"crypto"}],110:[function(require,module,exports){ -'use strict'; + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); -Object.defineProperty(exports, "__esModule", { - value: true -}); + return new CleartextMessage(text); +} -var _bn = require('bn.js'); +// OpenPGP.js - An OpenPGP implementation in javascript -var _bn2 = _interopRequireDefault(_bn); -var _crypto = require('./crypto'); +////////////////////// +// // +// Key handling // +// // +////////////////////// -var _crypto2 = _interopRequireDefault(_crypto); -var _public_key = require('./public_key'); +/** + * Generates a new OpenPGP key pair. Supports RSA and ECC keys. By default, primary and subkeys will be of same type. + * The generated primary key will have signing capabilities. By default, one subkey with encryption capabilities is also generated. + * @param {Object} options + * @param {Object|Array} options.userIDs - User IDs as objects: `{ name: 'Jo Doe', email: 'info@jo.com' }` + * @param {'ecc'|'rsa'} [options.type='ecc'] - The primary key algorithm type: ECC (default) or RSA + * @param {String} [options.passphrase=(not protected)] - The passphrase used to encrypt the generated private key. If omitted, the key won't be encrypted. + * @param {Number} [options.rsaBits=4096] - Number of bits for RSA keys + * @param {String} [options.curve='curve25519'] - Elliptic curve for ECC keys: + * curve25519 (default), p256, p384, p521, secp256k1, + * brainpoolP256r1, brainpoolP384r1, or brainpoolP512r1 + * @param {Date} [options.date=current date] - Override the creation date of the key and the key signatures + * @param {Number} [options.keyExpirationTime=0 (never expires)] - Number of seconds from the key creation time after which the key expires + * @param {Array} [options.subkeys=a single encryption subkey] - Options for each subkey e.g. `[{sign: true, passphrase: '123'}]` + * default to main key options, except for `sign` parameter that defaults to false, and indicates whether the subkey should sign rather than encrypt + * @param {'armored'|'binary'|'object'} [options.format='armored'] - format of the output keys + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} The generated key object in the form: + * { privateKey:PrivateKey|Uint8Array|String, publicKey:PublicKey|Uint8Array|String, revocationCertificate:String } + * @async + * @static + */ +async function generateKey({ userIDs = [], passphrase = '', type = 'ecc', rsaBits = 4096, curve = 'curve25519', keyExpirationTime = 0, date = new Date(), subkeys = [{}], format = 'armored', config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + userIDs = toArray$1(userIDs); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); -var _public_key2 = _interopRequireDefault(_public_key); + if (userIDs.length === 0) { + throw new Error('UserIDs are required for key generation'); + } + if (type === 'rsa' && rsaBits < config.minRSABits) { + throw new Error(`rsaBits should be at least ${config.minRSABits}, got: ${rsaBits}`); + } -var _pkcs = require('./pkcs1'); + const options = { userIDs, passphrase, type, rsaBits, curve, keyExpirationTime, date, subkeys }; -var _pkcs2 = _interopRequireDefault(_pkcs); + try { + const { key, revocationCertificate } = await generate$2(options, config); + key.getKeys().forEach(({ keyPacket }) => checkKeyRequirements(keyPacket, config)); -var _enums = require('../enums'); + return { + privateKey: formatObject(key, format, config), + publicKey: formatObject(key.toPublic(), format, config), + revocationCertificate + }; + } catch (err) { + throw util.wrapError('Error generating keypair', err); + } +} -var _enums2 = _interopRequireDefault(_enums); +/** + * Reformats signature packets for a key and rewraps key object. + * @param {Object} options + * @param {PrivateKey} options.privateKey - Private key to reformat + * @param {Object|Array} options.userIDs - User IDs as objects: `{ name: 'Jo Doe', email: 'info@jo.com' }` + * @param {String} [options.passphrase=(not protected)] - The passphrase used to encrypt the reformatted private key. If omitted, the key won't be encrypted. + * @param {Number} [options.keyExpirationTime=0 (never expires)] - Number of seconds from the key creation time after which the key expires + * @param {Date} [options.date] - Override the creation date of the key signatures. If the key was previously used to sign messages, it is recommended + * to set the same date as the key creation time to ensure that old message signatures will still be verifiable using the reformatted key. + * @param {'armored'|'binary'|'object'} [options.format='armored'] - format of the output keys + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} The generated key object in the form: + * { privateKey:PrivateKey|Uint8Array|String, publicKey:PublicKey|Uint8Array|String, revocationCertificate:String } + * @async + * @static + */ +async function reformatKey({ privateKey, userIDs = [], passphrase = '', keyExpirationTime = 0, date, format = 'armored', config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + userIDs = toArray$1(userIDs); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); -var _util = require('../util'); + if (userIDs.length === 0) { + throw new Error('UserIDs are required for key reformat'); + } + const options = { privateKey, userIDs, passphrase, keyExpirationTime, date }; -var _util2 = _interopRequireDefault(_util); + try { + const { key: reformattedKey, revocationCertificate } = await reformat(options, config); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + return { + privateKey: formatObject(reformattedKey, format, config), + publicKey: formatObject(reformattedKey.toPublic(), format, config), + revocationCertificate + }; + } catch (err) { + throw util.wrapError('Error reformatting keypair', err); + } +} /** - * @fileoverview Provides functions for asymmetric signing and signature verification - * @requires bn.js - * @requires crypto/crypto - * @requires crypto/public_key - * @requires crypto/pkcs1 - * @requires enums - * @requires util - * @module crypto/signature -*/ - -exports.default = { - /** - * Verifies the signature provided for data using specified algorithms and public key parameters. - * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} - * and {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4} - * for public key and hash algorithms. - * @param {module:enums.publicKey} algo Public key algorithm - * @param {module:enums.hash} hash_algo Hash algorithm - * @param {Array} msg_MPIs Algorithm-specific signature parameters - * @param {Array} pub_MPIs Algorithm-specific public key parameters - * @param {Uint8Array} data Data for which the signature was created - * @param {Uint8Array} hashed The hashed data - * @returns {Boolean} True if signature is valid - * @async - */ - verify: async function verify(algo, hash_algo, msg_MPIs, pub_MPIs, data, hashed) { - const types = _crypto2.default.getPubKeyParamTypes(algo); - if (pub_MPIs.length < types.length) { - throw new Error('Missing public key parameters'); - } - switch (algo) { - case _enums2.default.publicKey.rsa_encrypt_sign: - case _enums2.default.publicKey.rsa_encrypt: - case _enums2.default.publicKey.rsa_sign: - { - const m = msg_MPIs[0].toBN(); - const n = pub_MPIs[0].toBN(); - const e = pub_MPIs[1].toBN(); - const EM = await _public_key2.default.rsa.verify(m, n, e); - const EM2 = await _pkcs2.default.emsa.encode(hash_algo, hashed, n.byteLength()); - return _util2.default.Uint8Array_to_hex(EM) === EM2; - } - case _enums2.default.publicKey.dsa: - { - const r = msg_MPIs[0].toBN(); - const s = msg_MPIs[1].toBN(); - const p = pub_MPIs[0].toBN(); - const q = pub_MPIs[1].toBN(); - const g = pub_MPIs[2].toBN(); - const y = pub_MPIs[3].toBN(); - return _public_key2.default.dsa.verify(hash_algo, r, s, hashed, g, p, q, y); - } - case _enums2.default.publicKey.ecdsa: - { - const oid = pub_MPIs[0]; - const signature = { r: msg_MPIs[0].toUint8Array(), s: msg_MPIs[1].toUint8Array() }; - const Q = pub_MPIs[1].toUint8Array(); - return _public_key2.default.elliptic.ecdsa.verify(oid, hash_algo, signature, data, Q, hashed); - } - case _enums2.default.publicKey.eddsa: - { - const oid = pub_MPIs[0]; - // EdDSA signature params are expected in little-endian format - const signature = { - R: msg_MPIs[0].toUint8Array('le', 32), - S: msg_MPIs[1].toUint8Array('le', 32) - }; - const Q = pub_MPIs[1].toUint8Array('be', 33); - return _public_key2.default.elliptic.eddsa.verify(oid, hash_algo, signature, data, Q, hashed); - } - default: - throw new Error('Invalid signature algorithm.'); - } - }, + * Revokes a key. Requires either a private key or a revocation certificate. + * If a revocation certificate is passed, the reasonForRevocation parameter will be ignored. + * @param {Object} options + * @param {Key} options.key - Public or private key to revoke + * @param {String} [options.revocationCertificate] - Revocation certificate to revoke the key with + * @param {Object} [options.reasonForRevocation] - Object indicating the reason for revocation + * @param {module:enums.reasonForRevocation} [options.reasonForRevocation.flag=[noReason]{@link module:enums.reasonForRevocation}] - Flag indicating the reason for revocation + * @param {String} [options.reasonForRevocation.string=""] - String explaining the reason for revocation + * @param {Date} [options.date] - Use the given date instead of the current time to verify validity of revocation certificate (if provided), or as creation time of the revocation signature + * @param {'armored'|'binary'|'object'} [options.format='armored'] - format of the output key(s) + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} The revoked key in the form: + * { privateKey:PrivateKey|Uint8Array|String, publicKey:PublicKey|Uint8Array|String } if private key is passed, or + * { privateKey: null, publicKey:PublicKey|Uint8Array|String } otherwise + * @async + * @static + */ +async function revokeKey({ key, revocationCertificate, reasonForRevocation, date = new Date(), format = 'armored', config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - /** - * Creates a signature on data using specified algorithms and private key parameters. - * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} - * and {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4} - * for public key and hash algorithms. - * @param {module:enums.publicKey} algo Public key algorithm - * @param {module:enums.hash} hash_algo Hash algorithm - * @param {Array} key_params Algorithm-specific public and private key parameters - * @param {Uint8Array} data Data to be signed - * @param {Uint8Array} hashed The hashed data - * @returns {Uint8Array} Signature - * @async - */ - sign: async function sign(algo, hash_algo, key_params, data, hashed) { - const types = [].concat(_crypto2.default.getPubKeyParamTypes(algo), _crypto2.default.getPrivKeyParamTypes(algo)); - if (key_params.length < types.length) { - throw new Error('Missing private key parameters'); - } - switch (algo) { - case _enums2.default.publicKey.rsa_encrypt_sign: - case _enums2.default.publicKey.rsa_encrypt: - case _enums2.default.publicKey.rsa_sign: - { - const n = key_params[0].toBN(); - const e = key_params[1].toBN(); - const d = key_params[2].toBN(); - const m = new _bn2.default((await _pkcs2.default.emsa.encode(hash_algo, hashed, n.byteLength())), 16); - const signature = await _public_key2.default.rsa.sign(m, n, e, d); - return _util2.default.Uint8Array_to_MPI(signature); - } - case _enums2.default.publicKey.dsa: - { - const p = key_params[0].toBN(); - const q = key_params[1].toBN(); - const g = key_params[2].toBN(); - const x = key_params[4].toBN(); - const signature = await _public_key2.default.dsa.sign(hash_algo, hashed, g, p, q, x); - return _util2.default.concatUint8Array([_util2.default.Uint8Array_to_MPI(signature.r), _util2.default.Uint8Array_to_MPI(signature.s)]); - } - case _enums2.default.publicKey.elgamal: - { - throw new Error('Signing with Elgamal is not defined in the OpenPGP standard.'); - } - case _enums2.default.publicKey.ecdsa: - { - const oid = key_params[0]; - const d = key_params[2].toUint8Array(); - const signature = await _public_key2.default.elliptic.ecdsa.sign(oid, hash_algo, data, d, hashed); - return _util2.default.concatUint8Array([_util2.default.Uint8Array_to_MPI(signature.r), _util2.default.Uint8Array_to_MPI(signature.s)]); - } - case _enums2.default.publicKey.eddsa: - { - const oid = key_params[0]; - const d = key_params[2].toUint8Array('be', 32); - const signature = await _public_key2.default.elliptic.eddsa.sign(oid, hash_algo, data, d, hashed); - return _util2.default.concatUint8Array([_util2.default.Uint8Array_to_MPI(signature.R), _util2.default.Uint8Array_to_MPI(signature.S)]); - } - default: - throw new Error('Invalid signature algorithm.'); - } + try { + const revokedKey = revocationCertificate ? + await key.applyRevocationCertificate(revocationCertificate, date, config) : + await key.revoke(reasonForRevocation, date, config); + + return revokedKey.isPrivate() ? { + privateKey: formatObject(revokedKey, format, config), + publicKey: formatObject(revokedKey.toPublic(), format, config) + } : { + privateKey: null, + publicKey: formatObject(revokedKey, format, config) + }; + } catch (err) { + throw util.wrapError('Error revoking key', err); } -}; - -},{"../enums":113,"../util":152,"./crypto":89,"./pkcs1":96,"./public_key":106,"bn.js":16}],111:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); +} -var _webStreamTools = require('web-stream-tools'); +/** + * Unlock a private key with the given passphrase. + * This method does not change the original key. + * @param {Object} options + * @param {PrivateKey} options.privateKey - The private key to decrypt + * @param {String|Array} options.passphrase - The user's passphrase(s) + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} The unlocked key object. + * @async + */ +async function decryptKey({ privateKey, passphrase, config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); + if (!privateKey.isPrivate()) { + throw new Error('Cannot decrypt a public key'); + } + const clonedPrivateKey = privateKey.clone(true); + const passphrases = util.isArray(passphrase) ? passphrase : [passphrase]; -var _base = require('./base64.js'); + try { + await Promise.all(clonedPrivateKey.getKeys().map(key => ( + // try to decrypt each key with any of the given passphrases + util.anyPromise(passphrases.map(passphrase => key.keyPacket.decrypt(passphrase))) + ))); -var _base2 = _interopRequireDefault(_base); + await clonedPrivateKey.validate(config); + return clonedPrivateKey; + } catch (err) { + clonedPrivateKey.clearPrivateParams(); + throw util.wrapError('Error decrypting private key', err); + } +} -var _enums = require('../enums.js'); +/** + * Lock a private key with the given passphrase. + * This method does not change the original key. + * @param {Object} options + * @param {PrivateKey} options.privateKey - The private key to encrypt + * @param {String|Array} options.passphrase - If multiple passphrases, they should be in the same order as the packets each should encrypt + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} The locked key object. + * @async + */ +async function encryptKey({ privateKey, passphrase, config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); -var _enums2 = _interopRequireDefault(_enums); + if (!privateKey.isPrivate()) { + throw new Error('Cannot encrypt a public key'); + } + const clonedPrivateKey = privateKey.clone(true); -var _config = require('../config'); + const keys = clonedPrivateKey.getKeys(); + const passphrases = util.isArray(passphrase) ? passphrase : new Array(keys.length).fill(passphrase); + if (passphrases.length !== keys.length) { + throw new Error('Invalid number of passphrases given for key encryption'); + } -var _config2 = _interopRequireDefault(_config); + try { + await Promise.all(keys.map(async (key, i) => { + const { keyPacket } = key; + await keyPacket.encrypt(passphrases[i], config); + keyPacket.clearPrivateParams(); + })); + return clonedPrivateKey; + } catch (err) { + clonedPrivateKey.clearPrivateParams(); + throw util.wrapError('Error encrypting private key', err); + } +} -var _util = require('../util'); -var _util2 = _interopRequireDefault(_util); +/////////////////////////////////////////// +// // +// Message encryption and decryption // +// // +/////////////////////////////////////////// -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** - * Finds out which Ascii Armoring type is used. Throws error if unknown type. - * @private - * @param {String} text [String] ascii armored text - * @returns {Integer} 0 = MESSAGE PART n of m - * 1 = MESSAGE PART n - * 2 = SIGNED MESSAGE - * 3 = PGP MESSAGE - * 4 = PUBLIC KEY BLOCK - * 5 = PRIVATE KEY BLOCK - * 6 = SIGNATURE + * Encrypts a message using public keys, passwords or both at once. At least one of `encryptionKeys` or `passwords` + * must be specified. If signing keys are specified, those will be used to sign the message. + * @param {Object} options + * @param {Message} options.message - Message to be encrypted as created by {@link createMessage} + * @param {PublicKey|PublicKey[]} [options.encryptionKeys] - Array of keys or single key, used to encrypt the message + * @param {PrivateKey|PrivateKey[]} [options.signingKeys] - Private keys for signing. If omitted message will not be signed + * @param {String|String[]} [options.passwords] - Array of passwords or a single password to encrypt the message + * @param {Object} [options.sessionKey] - Session key in the form: `{ data:Uint8Array, algorithm:String }` + * @param {'armored'|'binary'|'object'} [options.format='armored'] - Format of the returned message + * @param {Signature} [options.signature] - A detached signature to add to the encrypted message + * @param {Boolean} [options.wildcard=false] - Use a key ID of 0 instead of the public key IDs + * @param {KeyID|KeyID[]} [options.signingKeyIDs=latest-created valid signing (sub)keys] - Array of key IDs to use for signing. Each `signingKeyIDs[i]` corresponds to `signingKeys[i]` + * @param {KeyID|KeyID[]} [options.encryptionKeyIDs=latest-created valid encryption (sub)keys] - Array of key IDs to use for encryption. Each `encryptionKeyIDs[i]` corresponds to `encryptionKeys[i]` + * @param {Date} [options.date=current date] - Override the creation date of the message signature + * @param {Object|Object[]} [options.signingUserIDs=primary user IDs] - Array of user IDs to sign with, one per key in `signingKeys`, e.g. `[{ name: 'Steve Sender', email: 'steve@openpgp.org' }]` + * @param {Object|Object[]} [options.encryptionUserIDs=primary user IDs] - Array of user IDs to encrypt for, one per key in `encryptionKeys`, e.g. `[{ name: 'Robert Receiver', email: 'robert@openpgp.org' }]` + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise|MaybeStream>} Encrypted message (string if `armor` was true, the default; Uint8Array if `armor` was false). + * @async + * @static */ -function getType(text) { - const reHeader = /^-----BEGIN PGP (MESSAGE, PART \d+\/\d+|MESSAGE, PART \d+|SIGNED MESSAGE|MESSAGE|PUBLIC KEY BLOCK|PRIVATE KEY BLOCK|SIGNATURE)-----$/m; - - const header = text.match(reHeader); - - if (!header) { - throw new Error('Unknown ASCII armor type'); +async function encrypt$4({ message, encryptionKeys, signingKeys, passwords, sessionKey, format = 'armored', signature = null, wildcard = false, signingKeyIDs = [], encryptionKeyIDs = [], date = new Date(), signingUserIDs = [], encryptionUserIDs = [], config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + checkMessage(message); checkOutputMessageFormat(format); + encryptionKeys = toArray$1(encryptionKeys); signingKeys = toArray$1(signingKeys); passwords = toArray$1(passwords); + signingKeyIDs = toArray$1(signingKeyIDs); encryptionKeyIDs = toArray$1(encryptionKeyIDs); signingUserIDs = toArray$1(signingUserIDs); encryptionUserIDs = toArray$1(encryptionUserIDs); + if (rest.detached) { + throw new Error("The `detached` option has been removed from openpgp.encrypt, separately call openpgp.sign instead. Don't forget to remove the `privateKeys` option as well."); } + if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.encrypt, pass `encryptionKeys` instead'); + if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.encrypt, pass `signingKeys` instead'); + if (rest.armor !== undefined) throw new Error('The `armor` option has been removed from openpgp.encrypt, pass `format` instead.'); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - // BEGIN PGP MESSAGE, PART X/Y - // Used for multi-part messages, where the armor is split amongst Y - // parts, and this is the Xth part out of Y. - if (/MESSAGE, PART \d+\/\d+/.test(header[1])) { - return _enums2.default.armor.multipart_section; - } else - // BEGIN PGP MESSAGE, PART X - // Used for multi-part messages, where this is the Xth part of an - // unspecified number of parts. Requires the MESSAGE-ID Armor - // Header to be used. - if (/MESSAGE, PART \d+/.test(header[1])) { - return _enums2.default.armor.multipart_last; - } else - // BEGIN PGP SIGNED MESSAGE - if (/SIGNED MESSAGE/.test(header[1])) { - return _enums2.default.armor.signed; - } else - // BEGIN PGP MESSAGE - // Used for signed, encrypted, or compressed files. - if (/MESSAGE/.test(header[1])) { - return _enums2.default.armor.message; - } else - // BEGIN PGP PUBLIC KEY BLOCK - // Used for armoring public keys. - if (/PUBLIC KEY BLOCK/.test(header[1])) { - return _enums2.default.armor.public_key; - } else - // BEGIN PGP PRIVATE KEY BLOCK - // Used for armoring private keys. - if (/PRIVATE KEY BLOCK/.test(header[1])) { - return _enums2.default.armor.private_key; - } else - // BEGIN PGP SIGNATURE - // Used for detached signatures, OpenPGP/MIME signatures, and - // cleartext signatures. Note that PGP 2.x uses BEGIN PGP MESSAGE - // for detached signatures. - if (/SIGNATURE/.test(header[1])) { - return _enums2.default.armor.signature; - } + if (!signingKeys) { + signingKeys = []; + } + const streaming = message.fromStream; + try { + if (signingKeys.length || signature) { // sign the message only if signing keys or signature is specified + message = await message.sign(signingKeys, signature, signingKeyIDs, date, signingUserIDs, config); + } + message = message.compress( + await getPreferredAlgo('compression', encryptionKeys, date, encryptionUserIDs, config), + config + ); + message = await message.encrypt(encryptionKeys, passwords, sessionKey, wildcard, encryptionKeyIDs, date, encryptionUserIDs, config); + if (format === 'object') return message; + // serialize data + const armor = format === 'armored'; + const data = armor ? message.armor(config) : message.write(); + return convertStream(data, streaming, armor ? 'utf8' : 'binary'); + } catch (err) { + throw util.wrapError('Error encrypting message', err); + } } /** - * Add additional information to the armor version of an OpenPGP binary - * packet block. - * @author Alex - * @version 2011-12-16 - * @param {String} customComment (optional) additional comment to add to the armored string - * @returns {String} The header information + * Decrypts a message with the user's private key, a session key or a password. + * One of `decryptionKeys`, `sessionkeys` or `passwords` must be specified (passing a combination of these options is not supported). + * @param {Object} options + * @param {Message} options.message - The message object with the encrypted data + * @param {PrivateKey|PrivateKey[]} [options.decryptionKeys] - Private keys with decrypted secret key data or session key + * @param {String|String[]} [options.passwords] - Passwords to decrypt the message + * @param {Object|Object[]} [options.sessionKeys] - Session keys in the form: { data:Uint8Array, algorithm:String } + * @param {PublicKey|PublicKey[]} [options.verificationKeys] - Array of public keys or single key, to verify signatures + * @param {Boolean} [options.expectSigned=false] - If true, data decryption fails if the message is not signed with the provided publicKeys + * @param {'utf8'|'binary'} [options.format='utf8'] - Whether to return data as a string(Stream) or Uint8Array(Stream). If 'utf8' (the default), also normalize newlines. + * @param {Signature} [options.signature] - Detached signature for verification + * @param {Date} [options.date=current date] - Use the given date for verification instead of the current time + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} Object containing decrypted and verified message in the form: + * + * { + * data: MaybeStream, (if format was 'utf8', the default) + * data: MaybeStream, (if format was 'binary') + * filename: String, + * signatures: [ + * { + * keyID: module:type/keyid~KeyID, + * verified: Promise, + * signature: Promise + * }, ... + * ] + * } + * + * where `signatures` contains a separate entry for each signature packet found in the input message. + * @async + * @static */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +async function decrypt$4({ message, decryptionKeys, passwords, sessionKeys, verificationKeys, expectSigned = false, format = 'utf8', signature = null, date = new Date(), config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + checkMessage(message); verificationKeys = toArray$1(verificationKeys); decryptionKeys = toArray$1(decryptionKeys); passwords = toArray$1(passwords); sessionKeys = toArray$1(sessionKeys); + if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.decrypt, pass `decryptionKeys` instead'); + if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.decrypt, pass `verificationKeys` instead'); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); -/** - * @requires web-stream-tools - * @requires encoding/base64 - * @requires enums - * @requires config - * @requires util - * @module encoding/armor - */ + try { + const decrypted = await message.decrypt(decryptionKeys, passwords, sessionKeys, date, config); + if (!verificationKeys) { + verificationKeys = []; + } -function addheader(customComment) { - let result = ""; - if (_config2.default.show_version) { - result += "Version: " + _config2.default.versionstring + '\r\n'; - } - if (_config2.default.show_comment) { - result += "Comment: " + _config2.default.commentstring + '\r\n'; - } - if (customComment) { - result += "Comment: " + customComment + '\r\n'; + const result = {}; + result.signatures = signature ? await decrypted.verifyDetached(signature, verificationKeys, date, config) : await decrypted.verify(verificationKeys, date, config); + result.data = format === 'binary' ? decrypted.getLiteralData() : decrypted.getText(); + result.filename = decrypted.getFilename(); + linkStreams(result, message); + if (expectSigned) { + if (verificationKeys.length === 0) { + throw new Error('Verification keys are required to verify message signatures'); + } + if (result.signatures.length === 0) { + throw new Error('Message is not signed'); + } + result.data = concat([ + result.data, + fromAsync(async () => { + await util.anyPromise(result.signatures.map(sig => sig.verified)); + }) + ]); + } + result.data = await convertStream(result.data, message.fromStream, format); + return result; + } catch (err) { + throw util.wrapError('Error decrypting message', err); } - result += '\r\n'; - return result; } + +////////////////////////////////////////// +// // +// Message signing and verification // +// // +////////////////////////////////////////// + + /** - * Calculates a checksum over the given data and returns it base64 encoded - * @param {String | ReadableStream} data Data to create a CRC-24 checksum for - * @returns {String | ReadableStream} Base64 encoded checksum + * Signs a message. + * @param {Object} options + * @param {CleartextMessage|Message} options.message - (cleartext) message to be signed + * @param {PrivateKey|PrivateKey[]} options.signingKeys - Array of keys or single key with decrypted secret key data to sign cleartext + * @param {'armored'|'binary'|'object'} [options.format='armored'] - Format of the returned message + * @param {Boolean} [options.detached=false] - If the return value should contain a detached signature + * @param {KeyID|KeyID[]} [options.signingKeyIDs=latest-created valid signing (sub)keys] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] + * @param {Date} [options.date=current date] - Override the creation date of the signature + * @param {Object|Object[]} [options.signingUserIDs=primary user IDs] - Array of user IDs to sign with, one per key in `signingKeys`, e.g. `[{ name: 'Steve Sender', email: 'steve@openpgp.org' }]` + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise>} Signed message (string if `armor` was true, the default; Uint8Array if `armor` was false). + * @async + * @static */ -function getCheckSum(data) { - const crc = createcrc24(data); - return _base2.default.encode(crc); -} +async function sign$5({ message, signingKeys, format = 'armored', detached = false, signingKeyIDs = [], date = new Date(), signingUserIDs = [], config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + checkCleartextOrMessage(message); checkOutputMessageFormat(format); + signingKeys = toArray$1(signingKeys); signingKeyIDs = toArray$1(signingKeyIDs); signingUserIDs = toArray$1(signingUserIDs); -const crc_table = [0x00000000, 0x00864cfb, 0x018ad50d, 0x010c99f6, 0x0393e6e1, 0x0315aa1a, 0x021933ec, 0x029f7f17, 0x07a18139, 0x0727cdc2, 0x062b5434, 0x06ad18cf, 0x043267d8, 0x04b42b23, 0x05b8b2d5, 0x053efe2e, 0x0fc54e89, 0x0f430272, 0x0e4f9b84, 0x0ec9d77f, 0x0c56a868, 0x0cd0e493, 0x0ddc7d65, 0x0d5a319e, 0x0864cfb0, 0x08e2834b, 0x09ee1abd, 0x09685646, 0x0bf72951, 0x0b7165aa, 0x0a7dfc5c, 0x0afbb0a7, 0x1f0cd1e9, 0x1f8a9d12, 0x1e8604e4, 0x1e00481f, 0x1c9f3708, 0x1c197bf3, 0x1d15e205, 0x1d93aefe, 0x18ad50d0, 0x182b1c2b, 0x192785dd, 0x19a1c926, 0x1b3eb631, 0x1bb8faca, 0x1ab4633c, 0x1a322fc7, 0x10c99f60, 0x104fd39b, 0x11434a6d, 0x11c50696, 0x135a7981, 0x13dc357a, 0x12d0ac8c, 0x1256e077, 0x17681e59, 0x17ee52a2, 0x16e2cb54, 0x166487af, 0x14fbf8b8, 0x147db443, 0x15712db5, 0x15f7614e, 0x3e19a3d2, 0x3e9fef29, 0x3f9376df, 0x3f153a24, 0x3d8a4533, 0x3d0c09c8, 0x3c00903e, 0x3c86dcc5, 0x39b822eb, 0x393e6e10, 0x3832f7e6, 0x38b4bb1d, 0x3a2bc40a, 0x3aad88f1, 0x3ba11107, 0x3b275dfc, 0x31dced5b, 0x315aa1a0, 0x30563856, 0x30d074ad, 0x324f0bba, 0x32c94741, 0x33c5deb7, 0x3343924c, 0x367d6c62, 0x36fb2099, 0x37f7b96f, 0x3771f594, 0x35ee8a83, 0x3568c678, 0x34645f8e, 0x34e21375, 0x2115723b, 0x21933ec0, 0x209fa736, 0x2019ebcd, 0x228694da, 0x2200d821, 0x230c41d7, 0x238a0d2c, 0x26b4f302, 0x2632bff9, 0x273e260f, 0x27b86af4, 0x252715e3, 0x25a15918, 0x24adc0ee, 0x242b8c15, 0x2ed03cb2, 0x2e567049, 0x2f5ae9bf, 0x2fdca544, 0x2d43da53, 0x2dc596a8, 0x2cc90f5e, 0x2c4f43a5, 0x2971bd8b, 0x29f7f170, 0x28fb6886, 0x287d247d, 0x2ae25b6a, 0x2a641791, 0x2b688e67, 0x2beec29c, 0x7c3347a4, 0x7cb50b5f, 0x7db992a9, 0x7d3fde52, 0x7fa0a145, 0x7f26edbe, 0x7e2a7448, 0x7eac38b3, 0x7b92c69d, 0x7b148a66, 0x7a181390, 0x7a9e5f6b, 0x7801207c, 0x78876c87, 0x798bf571, 0x790db98a, 0x73f6092d, 0x737045d6, 0x727cdc20, 0x72fa90db, 0x7065efcc, 0x70e3a337, 0x71ef3ac1, 0x7169763a, 0x74578814, 0x74d1c4ef, 0x75dd5d19, 0x755b11e2, 0x77c46ef5, 0x7742220e, 0x764ebbf8, 0x76c8f703, 0x633f964d, 0x63b9dab6, 0x62b54340, 0x62330fbb, 0x60ac70ac, 0x602a3c57, 0x6126a5a1, 0x61a0e95a, 0x649e1774, 0x64185b8f, 0x6514c279, 0x65928e82, 0x670df195, 0x678bbd6e, 0x66872498, 0x66016863, 0x6cfad8c4, 0x6c7c943f, 0x6d700dc9, 0x6df64132, 0x6f693e25, 0x6fef72de, 0x6ee3eb28, 0x6e65a7d3, 0x6b5b59fd, 0x6bdd1506, 0x6ad18cf0, 0x6a57c00b, 0x68c8bf1c, 0x684ef3e7, 0x69426a11, 0x69c426ea, 0x422ae476, 0x42aca88d, 0x43a0317b, 0x43267d80, 0x41b90297, 0x413f4e6c, 0x4033d79a, 0x40b59b61, 0x458b654f, 0x450d29b4, 0x4401b042, 0x4487fcb9, 0x461883ae, 0x469ecf55, 0x479256a3, 0x47141a58, 0x4defaaff, 0x4d69e604, 0x4c657ff2, 0x4ce33309, 0x4e7c4c1e, 0x4efa00e5, 0x4ff69913, 0x4f70d5e8, 0x4a4e2bc6, 0x4ac8673d, 0x4bc4fecb, 0x4b42b230, 0x49ddcd27, 0x495b81dc, 0x4857182a, 0x48d154d1, 0x5d26359f, 0x5da07964, 0x5cace092, 0x5c2aac69, 0x5eb5d37e, 0x5e339f85, 0x5f3f0673, 0x5fb94a88, 0x5a87b4a6, 0x5a01f85d, 0x5b0d61ab, 0x5b8b2d50, 0x59145247, 0x59921ebc, 0x589e874a, 0x5818cbb1, 0x52e37b16, 0x526537ed, 0x5369ae1b, 0x53efe2e0, 0x51709df7, 0x51f6d10c, 0x50fa48fa, 0x507c0401, 0x5542fa2f, 0x55c4b6d4, 0x54c82f22, 0x544e63d9, 0x56d11cce, 0x56575035, 0x575bc9c3, 0x57dd8538]; + if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.sign, pass `signingKeys` instead'); + if (rest.armor !== undefined) throw new Error('The `armor` option has been removed from openpgp.sign, pass `format` instead.'); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); -/** - * Internal function to calculate a CRC-24 checksum over a given string (data) - * @param {String | ReadableStream} data Data to create a CRC-24 checksum for - * @returns {Uint8Array | ReadableStream} The CRC-24 checksum - */ -function createcrc24(input) { - let crc = 0xB704CE; - return _webStreamTools2.default.transform(input, value => { - for (let index = 0; index < value.length; index++) { - crc = crc << 8 ^ crc_table[(crc >> 16 ^ value[index]) & 0xff]; - } - }, () => new Uint8Array([crc >> 16, crc >> 8, crc])); -} + if (message instanceof CleartextMessage && format === 'binary') throw new Error('Cannot return signed cleartext message in binary format'); + if (message instanceof CleartextMessage && detached) throw new Error('Cannot detach-sign a cleartext message'); -/** - * Verify armored headers. RFC4880, section 6.3: "OpenPGP should consider improperly formatted - * Armor Headers to be corruption of the ASCII Armor." - * @private - * @param {Array} headers Armor headers - */ -function verifyHeaders(headers) { - for (let i = 0; i < headers.length; i++) { - if (!/^([^\s:]|[^\s:][^:]*[^\s:]): .+$/.test(headers[i])) { - throw new Error('Improperly formatted armor header: ' + headers[i]); + if (!signingKeys || signingKeys.length === 0) { + throw new Error('No signing keys provided'); + } + + try { + let signature; + if (detached) { + signature = await message.signDetached(signingKeys, undefined, signingKeyIDs, date, signingUserIDs, config); + } else { + signature = await message.sign(signingKeys, undefined, signingKeyIDs, date, signingUserIDs, config); } - if (!/^(Version|Comment|MessageID|Hash|Charset): .+$/.test(headers[i])) { - _util2.default.print_debug_error(new Error('Unknown header: ' + headers[i])); + if (format === 'object') return signature; + + const armor = format === 'armored'; + signature = armor ? signature.armor(config) : signature.write(); + if (detached) { + signature = transformPair(message.packets.write(), async (readable, writable) => { + await Promise.all([ + pipe(signature, writable), + readToEnd(readable).catch(() => {}) + ]); + }); } + return convertStream(signature, message.fromStream, armor ? 'utf8' : 'binary'); + } catch (err) { + throw util.wrapError('Error signing message', err); } } /** - * Splits a message into two parts, the body and the checksum. This is an internal function - * @param {String} text OpenPGP armored message part - * @returns {Object} An object with attribute "body" containing the body - * and an attribute "checksum" containing the checksum. + * Verifies signatures of cleartext signed message + * @param {Object} options + * @param {CleartextMessage|Message} options.message - (cleartext) message object with signatures + * @param {PublicKey|PublicKey[]} options.verificationKeys - Array of publicKeys or single key, to verify signatures + * @param {Boolean} [options.expectSigned=false] - If true, verification throws if the message is not signed with the provided publicKeys + * @param {'utf8'|'binary'} [options.format='utf8'] - Whether to return data as a string(Stream) or Uint8Array(Stream). If 'utf8' (the default), also normalize newlines. + * @param {Signature} [options.signature] - Detached signature for verification + * @param {Date} [options.date=current date] - Use the given date for verification instead of the current time + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} Object containing verified message in the form: + * + * { + * data: MaybeStream, (if `message` was a CleartextMessage) + * data: MaybeStream, (if `message` was a Message) + * signatures: [ + * { + * keyID: module:type/keyid~KeyID, + * verified: Promise, + * signature: Promise + * }, ... + * ] + * } + * + * where `signatures` contains a separate entry for each signature packet found in the input message. + * @async + * @static */ -function splitChecksum(text) { - let body = text; - let checksum = ""; +async function verify$5({ message, verificationKeys, expectSigned = false, format = 'utf8', signature = null, date = new Date(), config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + checkCleartextOrMessage(message); verificationKeys = toArray$1(verificationKeys); + if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.verify, pass `verificationKeys` instead'); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - const lastEquals = text.lastIndexOf("="); + if (message instanceof CleartextMessage && format === 'binary') throw new Error("Can't return cleartext message data as binary"); + if (message instanceof CleartextMessage && signature) throw new Error("Can't verify detached cleartext signature"); - if (lastEquals >= 0 && lastEquals !== text.length - 1) { - // '=' as the last char means no checksum - body = text.slice(0, lastEquals); - checksum = text.slice(lastEquals + 1).substr(0, 4); + try { + const result = {}; + if (signature) { + result.signatures = await message.verifyDetached(signature, verificationKeys, date, config); + } else { + result.signatures = await message.verify(verificationKeys, date, config); + } + result.data = format === 'binary' ? message.getLiteralData() : message.getText(); + if (message.fromStream) linkStreams(result, message); + if (expectSigned) { + if (result.signatures.length === 0) { + throw new Error('Message is not signed'); + } + result.data = concat([ + result.data, + fromAsync(async () => { + await util.anyPromise(result.signatures.map(sig => sig.verified)); + }) + ]); + } + result.data = await convertStream(result.data, message.fromStream, format); + return result; + } catch (err) { + throw util.wrapError('Error verifying signed message', err); } - - return { body: body, checksum: checksum }; } + +/////////////////////////////////////////////// +// // +// Session key encryption and decryption // +// // +/////////////////////////////////////////////// + /** - * DeArmor an OpenPGP armored message; verify the checksum and return - * the encoded bytes - * @param {String} text OpenPGP armored message - * @returns {Promise} An object with attribute "text" containing the message text, - * an attribute "data" containing a stream of bytes and "type" for the ASCII armor type + * Generate a new session key object, taking the algorithm preferences of the passed public keys into account. + * @param {Object} options + * @param {PublicKey|PublicKey[]} options.encryptionKeys - Array of public keys or single key used to select algorithm preferences for + * @param {Date} [options.date=current date] - Date to select algorithm preferences at + * @param {Object|Object[]} [options.encryptionUserIDs=primary user IDs] - User IDs to select algorithm preferences for + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise<{ data: Uint8Array, algorithm: String }>} Object with session key data and algorithm. * @async * @static */ -function dearmor(input) { - return new Promise(async (resolve, reject) => { - try { - const reSplit = /^-----[^-]+-----$/m; - const reEmptyLine = /^[ \f\r\t\u00a0\u2000-\u200a\u202f\u205f\u3000]*$/; - - let type; - const headers = []; - let lastHeaders = headers; - let headersDone; - let text = []; - let textDone; - let checksum; - let data = _base2.default.decode(_webStreamTools2.default.transformPair(input, async (readable, writable) => { - const reader = _webStreamTools2.default.getReader(readable); - try { - while (true) { - let line = await reader.readLine(); - if (line === undefined) { - throw new Error('Misformed armored text'); - } - // remove trailing whitespace at end of lines - line = _util2.default.removeTrailingSpaces(line.replace(/[\r\n]/g, '')); - if (!type) { - if (reSplit.test(line)) { - type = getType(line); - } - } else if (!headersDone) { - if (reSplit.test(line)) { - reject(new Error('Mandatory blank line missing between armor headers and armor data')); - } - if (!reEmptyLine.test(line)) { - lastHeaders.push(line); - } else { - verifyHeaders(lastHeaders); - headersDone = true; - if (textDone || type !== 2) { - resolve({ text, data, headers, type }); - break; - } - } - } else if (!textDone && type === 2) { - if (!reSplit.test(line)) { - // Reverse dash-escaping for msg - text.push(line.replace(/^- /, '')); - } else { - text = text.join('\r\n'); - textDone = true; - verifyHeaders(lastHeaders); - lastHeaders = []; - headersDone = false; - } - } - } - } catch (e) { - reject(e); - return; - } - const writer = _webStreamTools2.default.getWriter(writable); - try { - while (true) { - await writer.ready; +async function generateSessionKey$1({ encryptionKeys, date = new Date(), encryptionUserIDs = [], config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + encryptionKeys = toArray$1(encryptionKeys); encryptionUserIDs = toArray$1(encryptionUserIDs); + if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.generateSessionKey, pass `encryptionKeys` instead'); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - var _ref = await reader.read(); - - const done = _ref.done, - value = _ref.value; + try { + const sessionKeys = await Message.generateSessionKey(encryptionKeys, date, encryptionUserIDs, config); + return sessionKeys; + } catch (err) { + throw util.wrapError('Error generating session key', err); + } +} + +/** + * Encrypt a symmetric session key with public keys, passwords, or both at once. + * At least one of `encryptionKeys` or `passwords` must be specified. + * @param {Object} options + * @param {Uint8Array} options.data - The session key to be encrypted e.g. 16 random bytes (for aes128) + * @param {String} options.algorithm - Algorithm of the symmetric session key e.g. 'aes128' or 'aes256' + * @param {String} [options.aeadAlgorithm] - AEAD algorithm, e.g. 'eax' or 'ocb' + * @param {PublicKey|PublicKey[]} [options.encryptionKeys] - Array of public keys or single key, used to encrypt the key + * @param {String|String[]} [options.passwords] - Passwords for the message + * @param {'armored'|'binary'} [options.format='armored'] - Format of the returned value + * @param {Boolean} [options.wildcard=false] - Use a key ID of 0 instead of the public key IDs + * @param {KeyID|KeyID[]} [options.encryptionKeyIDs=latest-created valid encryption (sub)keys] - Array of key IDs to use for encryption. Each encryptionKeyIDs[i] corresponds to encryptionKeys[i] + * @param {Date} [options.date=current date] - Override the date + * @param {Object|Object[]} [options.encryptionUserIDs=primary user IDs] - Array of user IDs to encrypt for, one per key in `encryptionKeys`, e.g. `[{ name: 'Phil Zimmermann', email: 'phil@openpgp.org' }]` + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} Encrypted session keys (string if `armor` was true, the default; Uint8Array if `armor` was false). + * @async + * @static + */ +async function encryptSessionKey({ data, algorithm, aeadAlgorithm, encryptionKeys, passwords, format = 'armored', wildcard = false, encryptionKeyIDs = [], date = new Date(), encryptionUserIDs = [], config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + checkBinary(data); checkString(algorithm, 'algorithm'); checkOutputMessageFormat(format); + encryptionKeys = toArray$1(encryptionKeys); passwords = toArray$1(passwords); encryptionKeyIDs = toArray$1(encryptionKeyIDs); encryptionUserIDs = toArray$1(encryptionUserIDs); + if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.encryptSessionKey, pass `encryptionKeys` instead'); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - if (done) { - throw new Error('Misformed armored text'); - } - const line = value + ''; - if (line.indexOf('=') === -1 && line.indexOf('-') === -1) { - await writer.write(line); - } else { - let remainder = await reader.readToEnd(); - if (!remainder.length) remainder = ''; - remainder = line + remainder; - remainder = _util2.default.removeTrailingSpaces(remainder.replace(/\r/g, '')); - const parts = remainder.split(reSplit); - if (parts.length === 1) { - throw new Error('Misformed armored text'); - } - const split = splitChecksum(parts[0].slice(0, -1)); - checksum = split.checksum; - await writer.write(split.body); - break; - } - } - await writer.ready; - await writer.close(); - } catch (e) { - await writer.abort(e); - } - })); - data = _webStreamTools2.default.transformPair(data, async (readable, writable) => { - const checksumVerified = getCheckSum(_webStreamTools2.default.passiveClone(readable)); - await _webStreamTools2.default.pipe(readable, writable, { - preventClose: true - }); - const writer = _webStreamTools2.default.getWriter(writable); - try { - const checksumVerifiedString = await _webStreamTools2.default.readToEnd(checksumVerified); - if (checksum !== checksumVerifiedString && (checksum || _config2.default.checksum_required)) { - throw new Error("Ascii armor integrity check on message failed: '" + checksum + "' should be '" + checksumVerifiedString + "'"); - } - await writer.ready; - await writer.close(); - } catch (e) { - await writer.abort(e); - } - }); - } catch (e) { - reject(e); - } - }); + try { + const message = await Message.encryptSessionKey(data, algorithm, aeadAlgorithm, encryptionKeys, passwords, wildcard, encryptionKeyIDs, date, encryptionUserIDs, config); + return formatObject(message, format, config); + } catch (err) { + throw util.wrapError('Error encrypting session key', err); + } } /** - * Armor an OpenPGP binary packet block - * @param {Integer} messagetype type of the message - * @param body - * @param {Integer} partindex - * @param {Integer} parttotal - * @param {String} customComment (optional) additional comment to add to the armored string - * @returns {String | ReadableStream} Armored text + * Decrypt symmetric session keys using private keys or passwords (not both). + * One of `decryptionKeys` or `passwords` must be specified. + * @param {Object} options + * @param {Message} options.message - A message object containing the encrypted session key packets + * @param {PrivateKey|PrivateKey[]} [options.decryptionKeys] - Private keys with decrypted secret key data + * @param {String|String[]} [options.passwords] - Passwords to decrypt the session key + * @param {Date} [options.date] - Date to use for key verification instead of the current time + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} Array of decrypted session key, algorithm pairs in the form: + * { data:Uint8Array, algorithm:String } + * @throws if no session key could be found or decrypted + * @async * @static */ -function armor(messagetype, body, partindex, parttotal, customComment) { - let text; - let hash; - if (messagetype === _enums2.default.armor.signed) { - text = body.text; - hash = body.hash; - body = body.data; - } - const bodyClone = _webStreamTools2.default.passiveClone(body); - const result = []; - switch (messagetype) { - case _enums2.default.armor.multipart_section: - result.push("-----BEGIN PGP MESSAGE, PART " + partindex + "/" + parttotal + "-----\r\n"); - result.push(addheader(customComment)); - result.push(_base2.default.encode(body)); - result.push("\r\n=", getCheckSum(bodyClone), "\r\n"); - result.push("-----END PGP MESSAGE, PART " + partindex + "/" + parttotal + "-----\r\n"); - break; - case _enums2.default.armor.multipart_last: - result.push("-----BEGIN PGP MESSAGE, PART " + partindex + "-----\r\n"); - result.push(addheader(customComment)); - result.push(_base2.default.encode(body)); - result.push("\r\n=", getCheckSum(bodyClone), "\r\n"); - result.push("-----END PGP MESSAGE, PART " + partindex + "-----\r\n"); - break; - case _enums2.default.armor.signed: - result.push("\r\n-----BEGIN PGP SIGNED MESSAGE-----\r\n"); - result.push("Hash: " + hash + "\r\n\r\n"); - result.push(text.replace(/^-/mg, "- -")); - result.push("\r\n-----BEGIN PGP SIGNATURE-----\r\n"); - result.push(addheader(customComment)); - result.push(_base2.default.encode(body)); - result.push("\r\n=", getCheckSum(bodyClone), "\r\n"); - result.push("-----END PGP SIGNATURE-----\r\n"); - break; - case _enums2.default.armor.message: - result.push("-----BEGIN PGP MESSAGE-----\r\n"); - result.push(addheader(customComment)); - result.push(_base2.default.encode(body)); - result.push("\r\n=", getCheckSum(bodyClone), "\r\n"); - result.push("-----END PGP MESSAGE-----\r\n"); - break; - case _enums2.default.armor.public_key: - result.push("-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n"); - result.push(addheader(customComment)); - result.push(_base2.default.encode(body)); - result.push("\r\n=", getCheckSum(bodyClone), "\r\n"); - result.push("-----END PGP PUBLIC KEY BLOCK-----\r\n"); - break; - case _enums2.default.armor.private_key: - result.push("-----BEGIN PGP PRIVATE KEY BLOCK-----\r\n"); - result.push(addheader(customComment)); - result.push(_base2.default.encode(body)); - result.push("\r\n=", getCheckSum(bodyClone), "\r\n"); - result.push("-----END PGP PRIVATE KEY BLOCK-----\r\n"); - break; - case _enums2.default.armor.signature: - result.push("-----BEGIN PGP SIGNATURE-----\r\n"); - result.push(addheader(customComment)); - result.push(_base2.default.encode(body)); - result.push("\r\n=", getCheckSum(bodyClone), "\r\n"); - result.push("-----END PGP SIGNATURE-----\r\n"); - break; - } +async function decryptSessionKeys({ message, decryptionKeys, passwords, date = new Date(), config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + checkMessage(message); decryptionKeys = toArray$1(decryptionKeys); passwords = toArray$1(passwords); + if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.decryptSessionKeys, pass `decryptionKeys` instead'); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - return _util2.default.concat(result); + try { + const sessionKeys = await message.decryptSessionKeys(decryptionKeys, passwords, date, config); + return sessionKeys; + } catch (err) { + throw util.wrapError('Error decrypting session keys', err); + } } -exports.default = { - encode: armor, - decode: dearmor -}; -},{"../config":79,"../enums.js":113,"../util":152,"./base64.js":112,"web-stream-tools":75}],112:[function(require,module,exports){ -'use strict'; +////////////////////////// +// // +// Helper functions // +// // +////////////////////////// -Object.defineProperty(exports, "__esModule", { - value: true -}); -var _webStreamTools = require('web-stream-tools'); +/** + * Input validation + * @private + */ +function checkString(data, name) { + if (!util.isString(data)) { + throw new Error('Parameter [' + (name || 'data') + '] must be of type String'); + } +} +function checkBinary(data, name) { + if (!util.isUint8Array(data)) { + throw new Error('Parameter [' + (name || 'data') + '] must be of type Uint8Array'); + } +} +function checkMessage(message) { + if (!(message instanceof Message)) { + throw new Error('Parameter [message] needs to be of type Message'); + } +} +function checkCleartextOrMessage(message) { + if (!(message instanceof CleartextMessage) && !(message instanceof Message)) { + throw new Error('Parameter [message] needs to be of type Message or CleartextMessage'); + } +} +function checkOutputMessageFormat(format) { + if (format !== 'armored' && format !== 'binary' && format !== 'object') { + throw new Error(`Unsupported format ${format}`); + } +} +const defaultConfigPropsCount = Object.keys(defaultConfig).length; +function checkConfig(config) { + const inputConfigProps = Object.keys(config); + if (inputConfigProps.length !== defaultConfigPropsCount) { + for (const inputProp of inputConfigProps) { + if (defaultConfig[inputProp] === undefined) { + throw new Error(`Unknown config property: ${inputProp}`); + } + } + } +} -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); +/** + * Normalize parameter to an array if it is not undefined. + * @param {Object} param - the parameter to be normalized + * @returns {Array|undefined} The resulting array or undefined. + * @private + */ +function toArray$1(param) { + if (param && !util.isArray(param)) { + param = [param]; + } + return param; +} -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +/** + * Convert data to or from Stream + * @param {Object} data - the data to convert + * @param {'web'|'ponyfill'|'node'|false} streaming - Whether to return a ReadableStream, and of what type + * @param {'utf8'|'binary'} [encoding] - How to return data in Node Readable streams + * @returns {Promise} The data in the respective format. + * @async + * @private + */ +async function convertStream(data, streaming, encoding = 'utf8') { + const streamType = util.isStream(data); + if (streamType === 'array') { + return readToEnd(data); + } + if (streaming === 'node') { + data = webToNode(data); + if (encoding !== 'binary') data.setEncoding(encoding); + return data; + } + if (streaming === 'web' && streamType === 'ponyfill') { + return toNativeReadable(data); + } + return data; +} -const b64s = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; // Standard radix-64 -/* OpenPGP radix-64/base64 string encoding/decoding - * Copyright 2005 Herbert Hanewinkel, www.haneWIN.de - * version 1.0, check www.haneWIN.de for the latest version - * - * This software is provided as-is, without express or implied warranty. - * Permission to use, copy, modify, distribute or sell this software, with or - * without fee, for any purpose and by any individual or organization, is hereby - * granted, provided that the above copyright notice and this paragraph appear - * in all copies. Distribution as a part of an application or binary must - * include the above copyright notice in the documentation and/or other materials - * provided with the application or distribution. +/** + * Link result.data to the message stream for cancellation. + * Also, forward errors in the message to result.data. + * @param {Object} result - the data to convert + * @param {Message} message - message object + * @returns {Object} + * @private */ +function linkStreams(result, message) { + result.data = transformPair(message.packets.stream, async (readable, writable) => { + await pipe(result.data, writable, { + preventClose: true + }); + const writer = getWriter(writable); + try { + // Forward errors in the message stream to result.data. + await readToEnd(readable, _ => _); + await writer.close(); + } catch (e) { + await writer.abort(e); + } + }); +} /** - * @requires web-stream-tools - * @module encoding/base64 + * Convert the object to the given format + * @param {Key|Message} object + * @param {'armored'|'binary'|'object'} format + * @param {Object} config - Full configuration + * @returns {String|Uint8Array|Object} */ - -const b64u = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'; // URL-safe radix-64 - -const b64toByte = []; -for (let i = 0; i < b64s.length; i++) { - b64toByte[b64s.charCodeAt(i)] = i; +function formatObject(object, format, config) { + switch (format) { + case 'object': + return object; + case 'armored': + return object.armor(config); + case 'binary': + return object.write(); + default: + throw new Error(`Unsupported format ${format}`); + } } -b64toByte[b64u.charCodeAt(62)] = 62; -b64toByte[b64u.charCodeAt(63)] = 63; /** - * Convert binary array to radix-64 - * @param {Uint8Array | ReadableStream} t Uint8Array to convert - * @param {bool} u if true, output is URL-safe - * @returns {String | ReadableStream} radix-64 version of input string - * @static + * web-streams-polyfill v3.0.3 */ -function s2r(t, u = false) { - // TODO check btoa alternative - const b64 = u ? b64u : b64s; - let a; - let c; - - let l = 0; - let s = 0; +/// +const SymbolPolyfill = typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol' ? + Symbol : + description => `Symbol(${description})`; - return _webStreamTools2.default.transform(t, value => { - const r = []; - const tl = value.length; - for (let n = 0; n < tl; n++) { - if (l && l % 60 === 0 && !u) { - r.push("\r\n"); - } - c = value[n]; - if (s === 0) { - r.push(b64.charAt(c >> 2 & 63)); - a = (c & 3) << 4; - } else if (s === 1) { - r.push(b64.charAt(a | c >> 4 & 15)); - a = (c & 15) << 2; - } else if (s === 2) { - r.push(b64.charAt(a | c >> 6 & 3)); - l += 1; - if (l % 60 === 0 && !u) { - r.push("\r\n"); - } - r.push(b64.charAt(c & 63)); - } - l += 1; - s += 1; - if (s === 3) { - s = 0; - } +/// +function noop() { + return undefined; +} +function getGlobals() { + if (typeof self !== 'undefined') { + return self; } - return r.join(''); - }, () => { - const r = []; - if (s > 0) { - r.push(b64.charAt(a)); - l += 1; - if (l % 60 === 0 && !u) { - r.push("\r\n"); - } - if (!u) { - r.push('='); - l += 1; - } + else if (typeof window !== 'undefined') { + return window; } - if (s === 1 && !u) { - if (l % 60 === 0 && !u) { - r.push("\r\n"); - } - r.push('='); + else if (typeof global !== 'undefined') { + return global; } - return r.join(''); - }); + return undefined; } +const globals = getGlobals(); -/** - * Convert radix-64 to binary array - * @param {String | ReadableStream} t radix-64 string to convert - * @param {bool} u if true, input is interpreted as URL-safe - * @returns {Uint8Array | ReadableStream} binary array version of input string - * @static - */ -function r2s(t, u) { - // TODO check atob alternative - let c; - - let s = 0; - let a = 0; +function typeIsObject(x) { + return (typeof x === 'object' && x !== null) || typeof x === 'function'; +} +const rethrowAssertionErrorRejection = noop; - return _webStreamTools2.default.transform(t, value => { - const tl = value.length; - const r = new Uint8Array(Math.ceil(0.75 * tl)); - let index = 0; - for (let n = 0; n < tl; n++) { - c = b64toByte[value.charCodeAt(n)]; - if (c >= 0) { - if (s) { - r[index++] = a | c >> 6 - s & 255; - } - s = s + 2 & 7; - a = c << s & 255; - } +const originalPromise = Promise; +const originalPromiseThen = Promise.prototype.then; +const originalPromiseResolve = Promise.resolve.bind(originalPromise); +const originalPromiseReject = Promise.reject.bind(originalPromise); +function newPromise(executor) { + return new originalPromise(executor); +} +function promiseResolvedWith(value) { + return originalPromiseResolve(value); +} +function promiseRejectedWith(reason) { + return originalPromiseReject(reason); +} +function PerformPromiseThen(promise, onFulfilled, onRejected) { + // There doesn't appear to be any way to correctly emulate the behaviour from JavaScript, so this is just an + // approximation. + return originalPromiseThen.call(promise, onFulfilled, onRejected); +} +function uponPromise(promise, onFulfilled, onRejected) { + PerformPromiseThen(PerformPromiseThen(promise, onFulfilled, onRejected), undefined, rethrowAssertionErrorRejection); +} +function uponFulfillment(promise, onFulfilled) { + uponPromise(promise, onFulfilled); +} +function uponRejection(promise, onRejected) { + uponPromise(promise, undefined, onRejected); +} +function transformPromiseWith(promise, fulfillmentHandler, rejectionHandler) { + return PerformPromiseThen(promise, fulfillmentHandler, rejectionHandler); +} +function setPromiseIsHandledToTrue(promise) { + PerformPromiseThen(promise, undefined, rethrowAssertionErrorRejection); +} +const queueMicrotask = (() => { + const globalQueueMicrotask = globals && globals.queueMicrotask; + if (typeof globalQueueMicrotask === 'function') { + return globalQueueMicrotask; + } + const resolvedPromise = promiseResolvedWith(undefined); + return (fn) => PerformPromiseThen(resolvedPromise, fn); +})(); +function reflectCall(F, V, args) { + if (typeof F !== 'function') { + throw new TypeError('Argument is not a function'); + } + return Function.prototype.apply.call(F, V, args); +} +function promiseCall(F, V, args) { + try { + return promiseResolvedWith(reflectCall(F, V, args)); + } + catch (value) { + return promiseRejectedWith(value); } - return r.subarray(0, index); - }); } -exports.default = { - encode: s2r, - decode: r2s -}; - -},{"web-stream-tools":75}],113:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); +// Original from Chromium +// https://chromium.googlesource.com/chromium/src/+/0aee4434a4dba42a42abaea9bfbc0cd196a63bc1/third_party/blink/renderer/core/streams/SimpleQueue.js +const QUEUE_MAX_ARRAY_SIZE = 16384; /** - * @module enums + * Simple queue structure. + * + * Avoids scalability issues with using a packed array directly by using + * multiple arrays in a linked list and keeping the array size bounded. */ +class SimpleQueue { + constructor() { + this._cursor = 0; + this._size = 0; + // _front and _back are always defined. + this._front = { + _elements: [], + _next: undefined + }; + this._back = this._front; + // The cursor is used to avoid calling Array.shift(). + // It contains the index of the front element of the array inside the + // front-most node. It is always in the range [0, QUEUE_MAX_ARRAY_SIZE). + this._cursor = 0; + // When there is only one node, size === elements.length - cursor. + this._size = 0; + } + get length() { + return this._size; + } + // For exception safety, this method is structured in order: + // 1. Read state + // 2. Calculate required state mutations + // 3. Perform state mutations + push(element) { + const oldBack = this._back; + let newBack = oldBack; + if (oldBack._elements.length === QUEUE_MAX_ARRAY_SIZE - 1) { + newBack = { + _elements: [], + _next: undefined + }; + } + // push() is the mutation most likely to throw an exception, so it + // goes first. + oldBack._elements.push(element); + if (newBack !== oldBack) { + this._back = newBack; + oldBack._next = newBack; + } + ++this._size; + } + // Like push(), shift() follows the read -> calculate -> mutate pattern for + // exception safety. + shift() { // must not be called on an empty queue + const oldFront = this._front; + let newFront = oldFront; + const oldCursor = this._cursor; + let newCursor = oldCursor + 1; + const elements = oldFront._elements; + const element = elements[oldCursor]; + if (newCursor === QUEUE_MAX_ARRAY_SIZE) { + newFront = oldFront._next; + newCursor = 0; + } + // No mutations before this point. + --this._size; + this._cursor = newCursor; + if (oldFront !== newFront) { + this._front = newFront; + } + // Permit shifted element to be garbage collected. + elements[oldCursor] = undefined; + return element; + } + // The tricky thing about forEach() is that it can be called + // re-entrantly. The queue may be mutated inside the callback. It is easy to + // see that push() within the callback has no negative effects since the end + // of the queue is checked for on every iteration. If shift() is called + // repeatedly within the callback then the next iteration may return an + // element that has been removed. In this case the callback will be called + // with undefined values until we either "catch up" with elements that still + // exist or reach the back of the queue. + forEach(callback) { + let i = this._cursor; + let node = this._front; + let elements = node._elements; + while (i !== elements.length || node._next !== undefined) { + if (i === elements.length) { + node = node._next; + elements = node._elements; + i = 0; + if (elements.length === 0) { + break; + } + } + callback(elements[i]); + ++i; + } + } + // Return the element that would be returned if shift() was called now, + // without modifying the queue. + peek() { // must not be called on an empty queue + const front = this._front; + const cursor = this._cursor; + return front._elements[cursor]; + } +} -const byValue = Symbol('byValue'); - -exports.default = { - - /** Maps curve names under various standards to one - * @see {@link https://wiki.gnupg.org/ECC|ECC - GnuPG wiki} - * @enum {String} - * @readonly - */ - curve: { - /** NIST P-256 Curve */ - "p256": "p256", - "P-256": "p256", - "secp256r1": "p256", - "prime256v1": "p256", - "1.2.840.10045.3.1.7": "p256", - "2a8648ce3d030107": "p256", - "2A8648CE3D030107": "p256", - - /** NIST P-384 Curve */ - "p384": "p384", - "P-384": "p384", - "secp384r1": "p384", - "1.3.132.0.34": "p384", - "2b81040022": "p384", - "2B81040022": "p384", - - /** NIST P-521 Curve */ - "p521": "p521", - "P-521": "p521", - "secp521r1": "p521", - "1.3.132.0.35": "p521", - "2b81040023": "p521", - "2B81040023": "p521", - - /** SECG SECP256k1 Curve */ - "secp256k1": "secp256k1", - "1.3.132.0.10": "secp256k1", - "2b8104000a": "secp256k1", - "2B8104000A": "secp256k1", - - /** Ed25519 */ - "ED25519": "ed25519", - "ed25519": "ed25519", - "Ed25519": "ed25519", - "1.3.6.1.4.1.11591.15.1": "ed25519", - "2b06010401da470f01": "ed25519", - "2B06010401DA470F01": "ed25519", - - /** Curve25519 */ - "X25519": "curve25519", - "cv25519": "curve25519", - "curve25519": "curve25519", - "Curve25519": "curve25519", - "1.3.6.1.4.1.3029.1.5.1": "curve25519", - "2b060104019755010501": "curve25519", - "2B060104019755010501": "curve25519", - - /** BrainpoolP256r1 Curve */ - "brainpoolP256r1": "brainpoolP256r1", - "1.3.36.3.3.2.8.1.1.7": "brainpoolP256r1", - "2b2403030208010107": "brainpoolP256r1", - "2B2403030208010107": "brainpoolP256r1", - - /** BrainpoolP384r1 Curve */ - "brainpoolP384r1": "brainpoolP384r1", - "1.3.36.3.3.2.8.1.1.11": "brainpoolP384r1", - "2b240303020801010b": "brainpoolP384r1", - "2B240303020801010B": "brainpoolP384r1", - - /** BrainpoolP512r1 Curve */ - "brainpoolP512r1": "brainpoolP512r1", - "1.3.36.3.3.2.8.1.1.13": "brainpoolP512r1", - "2b240303020801010d": "brainpoolP512r1", - "2B240303020801010D": "brainpoolP512r1" - }, - - /** A string to key specifier type - * @enum {Integer} - * @readonly - */ - s2k: { - simple: 0, - salted: 1, - iterated: 3, - gnu: 101 - }, - - /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-9.1|RFC4880bis-04, section 9.1} - * @enum {Integer} - * @readonly - */ - publicKey: { - /** RSA (Encrypt or Sign) [HAC] */ - rsa_encrypt_sign: 1, - /** RSA (Encrypt only) [HAC] */ - rsa_encrypt: 2, - /** RSA (Sign only) [HAC] */ - rsa_sign: 3, - /** Elgamal (Encrypt only) [ELGAMAL] [HAC] */ - elgamal: 16, - /** DSA (Sign only) [FIPS186] [HAC] */ - dsa: 17, - /** ECDH (Encrypt only) [RFC6637] */ - ecdh: 18, - /** ECDSA (Sign only) [RFC6637] */ - ecdsa: 19, - /** EdDSA (Sign only) - * [{@link https://tools.ietf.org/html/draft-koch-eddsa-for-openpgp-04|Draft RFC}] */ - eddsa: 22, - /** Reserved for AEDH */ - aedh: 23, - /** Reserved for AEDSA */ - aedsa: 24 - }, - - /** {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC4880, section 9.2} - * @enum {Integer} - * @readonly - */ - symmetric: { - plaintext: 0, - /** Not implemented! */ - idea: 1, - '3des': 2, - tripledes: 2, - cast5: 3, - blowfish: 4, - aes128: 7, - aes192: 8, - aes256: 9, - twofish: 10 - }, - - /** {@link https://tools.ietf.org/html/rfc4880#section-9.3|RFC4880, section 9.3} - * @enum {Integer} - * @readonly - */ - compression: { - uncompressed: 0, - /** RFC1951 */ - zip: 1, - /** RFC1950 */ - zlib: 2, - bzip2: 3 - }, +function ReadableStreamReaderGenericInitialize(reader, stream) { + reader._ownerReadableStream = stream; + stream._reader = reader; + if (stream._state === 'readable') { + defaultReaderClosedPromiseInitialize(reader); + } + else if (stream._state === 'closed') { + defaultReaderClosedPromiseInitializeAsResolved(reader); + } + else { + defaultReaderClosedPromiseInitializeAsRejected(reader, stream._storedError); + } +} +// A client of ReadableStreamDefaultReader and ReadableStreamBYOBReader may use these functions directly to bypass state +// check. +function ReadableStreamReaderGenericCancel(reader, reason) { + const stream = reader._ownerReadableStream; + return ReadableStreamCancel(stream, reason); +} +function ReadableStreamReaderGenericRelease(reader) { + if (reader._ownerReadableStream._state === 'readable') { + defaultReaderClosedPromiseReject(reader, new TypeError(`Reader was released and can no longer be used to monitor the stream's closedness`)); + } + else { + defaultReaderClosedPromiseResetToRejected(reader, new TypeError(`Reader was released and can no longer be used to monitor the stream's closedness`)); + } + reader._ownerReadableStream._reader = undefined; + reader._ownerReadableStream = undefined; +} +// Helper functions for the readers. +function readerLockException(name) { + return new TypeError('Cannot ' + name + ' a stream using a released reader'); +} +// Helper functions for the ReadableStreamDefaultReader. +function defaultReaderClosedPromiseInitialize(reader) { + reader._closedPromise = newPromise((resolve, reject) => { + reader._closedPromise_resolve = resolve; + reader._closedPromise_reject = reject; + }); +} +function defaultReaderClosedPromiseInitializeAsRejected(reader, reason) { + defaultReaderClosedPromiseInitialize(reader); + defaultReaderClosedPromiseReject(reader, reason); +} +function defaultReaderClosedPromiseInitializeAsResolved(reader) { + defaultReaderClosedPromiseInitialize(reader); + defaultReaderClosedPromiseResolve(reader); +} +function defaultReaderClosedPromiseReject(reader, reason) { + if (reader._closedPromise_reject === undefined) { + return; + } + setPromiseIsHandledToTrue(reader._closedPromise); + reader._closedPromise_reject(reason); + reader._closedPromise_resolve = undefined; + reader._closedPromise_reject = undefined; +} +function defaultReaderClosedPromiseResetToRejected(reader, reason) { + defaultReaderClosedPromiseInitializeAsRejected(reader, reason); +} +function defaultReaderClosedPromiseResolve(reader) { + if (reader._closedPromise_resolve === undefined) { + return; + } + reader._closedPromise_resolve(undefined); + reader._closedPromise_resolve = undefined; + reader._closedPromise_reject = undefined; +} - /** {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC4880, section 9.4} - * @enum {Integer} - * @readonly - */ - hash: { - md5: 1, - sha1: 2, - ripemd: 3, - sha256: 8, - sha384: 9, - sha512: 10, - sha224: 11 - }, +const AbortSteps = SymbolPolyfill('[[AbortSteps]]'); +const ErrorSteps = SymbolPolyfill('[[ErrorSteps]]'); +const CancelSteps = SymbolPolyfill('[[CancelSteps]]'); +const PullSteps = SymbolPolyfill('[[PullSteps]]'); - /** A list of hash names as accepted by webCrypto functions. - * {@link https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest|Parameters, algo} - * @enum {String} - */ - webHash: { - 'SHA-1': 2, - 'SHA-256': 8, - 'SHA-384': 9, - 'SHA-512': 10 - }, +/// +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isFinite#Polyfill +const NumberIsFinite = Number.isFinite || function (x) { + return typeof x === 'number' && isFinite(x); +}; - /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-9.6|RFC4880bis-04, section 9.6} - * @enum {Integer} - * @readonly - */ - aead: { - eax: 1, - ocb: 2, - experimental_gcm: 100 // Private algorithm - }, +/// +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc#Polyfill +const MathTrunc = Math.trunc || function (v) { + return v < 0 ? Math.ceil(v) : Math.floor(v); +}; - /** A list of packet types and numeric tags associated with them. - * @enum {Integer} - * @readonly - */ - packet: { - publicKeyEncryptedSessionKey: 1, - signature: 2, - symEncryptedSessionKey: 3, - onePassSignature: 4, - secretKey: 5, - publicKey: 6, - secretSubkey: 7, - compressed: 8, - symmetricallyEncrypted: 9, - marker: 10, - literal: 11, - trust: 12, - userid: 13, - publicSubkey: 14, - userAttribute: 17, - symEncryptedIntegrityProtected: 18, - modificationDetectionCode: 19, - symEncryptedAEADProtected: 20 // see IETF draft: https://tools.ietf.org/html/draft-ford-openpgp-format-00#section-2.1 - }, +// https://heycam.github.io/webidl/#idl-dictionaries +function isDictionary(x) { + return typeof x === 'object' || typeof x === 'function'; +} +function assertDictionary(obj, context) { + if (obj !== undefined && !isDictionary(obj)) { + throw new TypeError(`${context} is not an object.`); + } +} +// https://heycam.github.io/webidl/#idl-callback-functions +function assertFunction(x, context) { + if (typeof x !== 'function') { + throw new TypeError(`${context} is not a function.`); + } +} +// https://heycam.github.io/webidl/#idl-object +function isObject(x) { + return (typeof x === 'object' && x !== null) || typeof x === 'function'; +} +function assertObject(x, context) { + if (!isObject(x)) { + throw new TypeError(`${context} is not an object.`); + } +} +function assertRequiredArgument(x, position, context) { + if (x === undefined) { + throw new TypeError(`Parameter ${position} is required in '${context}'.`); + } +} +function assertRequiredField(x, field, context) { + if (x === undefined) { + throw new TypeError(`${field} is required in '${context}'.`); + } +} +// https://heycam.github.io/webidl/#idl-unrestricted-double +function convertUnrestrictedDouble(value) { + return Number(value); +} +function censorNegativeZero(x) { + return x === 0 ? 0 : x; +} +function integerPart(x) { + return censorNegativeZero(MathTrunc(x)); +} +// https://heycam.github.io/webidl/#idl-unsigned-long-long +function convertUnsignedLongLongWithEnforceRange(value, context) { + const lowerBound = 0; + const upperBound = Number.MAX_SAFE_INTEGER; + let x = Number(value); + x = censorNegativeZero(x); + if (!NumberIsFinite(x)) { + throw new TypeError(`${context} is not a finite number`); + } + x = integerPart(x); + if (x < lowerBound || x > upperBound) { + throw new TypeError(`${context} is outside the accepted range of ${lowerBound} to ${upperBound}, inclusive`); + } + if (!NumberIsFinite(x) || x === 0) { + return 0; + } + // TODO Use BigInt if supported? + // let xBigInt = BigInt(integerPart(x)); + // xBigInt = BigInt.asUintN(64, xBigInt); + // return Number(xBigInt); + return x; +} - /** Data types in the literal packet - * @enum {Integer} - * @readonly - */ - literal: { - /** Binary data 'b' */ - binary: 'b'.charCodeAt(), - /** Text data 't' */ - text: 't'.charCodeAt(), - /** Utf8 data 'u' */ - utf8: 'u'.charCodeAt(), - /** MIME message body part 'm' */ - mime: 'm'.charCodeAt() - }, +function assertReadableStream(x, context) { + if (!IsReadableStream(x)) { + throw new TypeError(`${context} is not a ReadableStream.`); + } +} - /** One pass signature packet type - * @enum {Integer} - * @readonly - */ - signature: { - /** 0x00: Signature of a binary document. */ - binary: 0, - /** 0x01: Signature of a canonical text document. - * - * Canonicalyzing the document by converting line endings. */ - text: 1, - /** 0x02: Standalone signature. - * - * This signature is a signature of only its own subpacket contents. - * It is calculated identically to a signature over a zero-lengh - * binary document. Note that it doesn't make sense to have a V3 - * standalone signature. */ - standalone: 2, - /** 0x10: Generic certification of a User ID and Public-Key packet. - * - * The issuer of this certification does not make any particular - * assertion as to how well the certifier has checked that the owner - * of the key is in fact the person described by the User ID. */ - cert_generic: 16, - /** 0x11: Persona certification of a User ID and Public-Key packet. - * - * The issuer of this certification has not done any verification of - * the claim that the owner of this key is the User ID specified. */ - cert_persona: 17, - /** 0x12: Casual certification of a User ID and Public-Key packet. - * - * The issuer of this certification has done some casual - * verification of the claim of identity. */ - cert_casual: 18, - /** 0x13: Positive certification of a User ID and Public-Key packet. - * - * The issuer of this certification has done substantial - * verification of the claim of identity. - * - * Most OpenPGP implementations make their "key signatures" as 0x10 - * certifications. Some implementations can issue 0x11-0x13 - * certifications, but few differentiate between the types. */ - cert_positive: 19, - /** 0x30: Certification revocation signature - * - * This signature revokes an earlier User ID certification signature - * (signature class 0x10 through 0x13) or direct-key signature - * (0x1F). It should be issued by the same key that issued the - * revoked signature or an authorized revocation key. The signature - * is computed over the same data as the certificate that it - * revokes, and should have a later creation date than that - * certificate. */ - cert_revocation: 48, - /** 0x18: Subkey Binding Signature - * - * This signature is a statement by the top-level signing key that - * indicates that it owns the subkey. This signature is calculated - * directly on the primary key and subkey, and not on any User ID or - * other packets. A signature that binds a signing subkey MUST have - * an Embedded Signature subpacket in this binding signature that - * contains a 0x19 signature made by the signing subkey on the - * primary key and subkey. */ - subkey_binding: 24, - /** 0x19: Primary Key Binding Signature - * - * This signature is a statement by a signing subkey, indicating - * that it is owned by the primary key and subkey. This signature - * is calculated the same way as a 0x18 signature: directly on the - * primary key and subkey, and not on any User ID or other packets. - * - * When a signature is made over a key, the hash data starts with the - * octet 0x99, followed by a two-octet length of the key, and then body - * of the key packet. (Note that this is an old-style packet header for - * a key packet with two-octet length.) A subkey binding signature - * (type 0x18) or primary key binding signature (type 0x19) then hashes - * the subkey using the same format as the main key (also using 0x99 as - * the first octet). */ - key_binding: 25, - /** 0x1F: Signature directly on a key - * - * This signature is calculated directly on a key. It binds the - * information in the Signature subpackets to the key, and is - * appropriate to be used for subpackets that provide information - * about the key, such as the Revocation Key subpacket. It is also - * appropriate for statements that non-self certifiers want to make - * about the key itself, rather than the binding between a key and a - * name. */ - key: 31, - /** 0x20: Key revocation signature - * - * The signature is calculated directly on the key being revoked. A - * revoked key is not to be used. Only revocation signatures by the - * key being revoked, or by an authorized revocation key, should be - * considered valid revocation signatures.a */ - key_revocation: 32, - /** 0x28: Subkey revocation signature - * - * The signature is calculated directly on the subkey being revoked. - * A revoked subkey is not to be used. Only revocation signatures - * by the top-level signature key that is bound to this subkey, or - * by an authorized revocation key, should be considered valid - * revocation signatures. +// Abstract operations for the ReadableStream. +function AcquireReadableStreamDefaultReader(stream) { + return new ReadableStreamDefaultReader(stream); +} +// ReadableStream API exposed for controllers. +function ReadableStreamAddReadRequest(stream, readRequest) { + stream._reader._readRequests.push(readRequest); +} +function ReadableStreamFulfillReadRequest(stream, chunk, done) { + const reader = stream._reader; + const readRequest = reader._readRequests.shift(); + if (done) { + readRequest._closeSteps(); + } + else { + readRequest._chunkSteps(chunk); + } +} +function ReadableStreamGetNumReadRequests(stream) { + return stream._reader._readRequests.length; +} +function ReadableStreamHasDefaultReader(stream) { + const reader = stream._reader; + if (reader === undefined) { + return false; + } + if (!IsReadableStreamDefaultReader(reader)) { + return false; + } + return true; +} +/** + * A default reader vended by a {@link ReadableStream}. + * + * @public + */ +class ReadableStreamDefaultReader { + constructor(stream) { + assertRequiredArgument(stream, 1, 'ReadableStreamDefaultReader'); + assertReadableStream(stream, 'First parameter'); + if (IsReadableStreamLocked(stream)) { + throw new TypeError('This stream has already been locked for exclusive reading by another reader'); + } + ReadableStreamReaderGenericInitialize(this, stream); + this._readRequests = new SimpleQueue(); + } + /** + * Returns a promise that will be fulfilled when the stream becomes closed, + * or rejected if the stream ever errors or the reader's lock is released before the stream finishes closing. + */ + get closed() { + if (!IsReadableStreamDefaultReader(this)) { + return promiseRejectedWith(defaultReaderBrandCheckException('closed')); + } + return this._closedPromise; + } + /** + * If the reader is active, behaves the same as {@link ReadableStream.cancel | stream.cancel(reason)}. + */ + cancel(reason = undefined) { + if (!IsReadableStreamDefaultReader(this)) { + return promiseRejectedWith(defaultReaderBrandCheckException('cancel')); + } + if (this._ownerReadableStream === undefined) { + return promiseRejectedWith(readerLockException('cancel')); + } + return ReadableStreamReaderGenericCancel(this, reason); + } + /** + * Returns a promise that allows access to the next chunk from the stream's internal queue, if available. * - * Key revocation signatures (types 0x20 and 0x28) - * hash only the key being revoked. */ - subkey_revocation: 40, - /** 0x40: Timestamp signature. - * This signature is only meaningful for the timestamp contained in - * it. */ - timestamp: 64, - /** 0x50: Third-Party Confirmation signature. + * If reading a chunk causes the queue to become empty, more data will be pulled from the underlying source. + */ + read() { + if (!IsReadableStreamDefaultReader(this)) { + return promiseRejectedWith(defaultReaderBrandCheckException('read')); + } + if (this._ownerReadableStream === undefined) { + return promiseRejectedWith(readerLockException('read from')); + } + let resolvePromise; + let rejectPromise; + const promise = newPromise((resolve, reject) => { + resolvePromise = resolve; + rejectPromise = reject; + }); + const readRequest = { + _chunkSteps: chunk => resolvePromise({ value: chunk, done: false }), + _closeSteps: () => resolvePromise({ value: undefined, done: true }), + _errorSteps: e => rejectPromise(e) + }; + ReadableStreamDefaultReaderRead(this, readRequest); + return promise; + } + /** + * Releases the reader's lock on the corresponding stream. After the lock is released, the reader is no longer active. + * If the associated stream is errored when the lock is released, the reader will appear errored in the same way + * from now on; otherwise, the reader will appear closed. * - * This signature is a signature over some other OpenPGP Signature - * packet(s). It is analogous to a notary seal on the signed data. - * A third-party signature SHOULD include Signature Target - * subpacket(s) to give easy identification. Note that we really do - * mean SHOULD. There are plausible uses for this (such as a blind - * party that only sees the signature, not the key or source - * document) that cannot include a target subpacket. */ - third_party: 80 - }, - - /** Signature subpacket type - * @enum {Integer} - * @readonly - */ - signatureSubpacket: { - signature_creation_time: 2, - signature_expiration_time: 3, - exportable_certification: 4, - trust_signature: 5, - regular_expression: 6, - revocable: 7, - key_expiration_time: 9, - placeholder_backwards_compatibility: 10, - preferred_symmetric_algorithms: 11, - revocation_key: 12, - issuer: 16, - notation_data: 20, - preferred_hash_algorithms: 21, - preferred_compression_algorithms: 22, - key_server_preferences: 23, - preferred_key_server: 24, - primary_user_id: 25, - policy_uri: 26, - key_flags: 27, - signers_user_id: 28, - reason_for_revocation: 29, - features: 30, - signature_target: 31, - embedded_signature: 32, - issuer_fingerprint: 33, - preferred_aead_algorithms: 34 - }, + * A reader's lock cannot be released while it still has a pending read request, i.e., if a promise returned by + * the reader's {@link ReadableStreamDefaultReader.read | read()} method has not yet been settled. Attempting to + * do so will throw a `TypeError` and leave the reader locked to the stream. + */ + releaseLock() { + if (!IsReadableStreamDefaultReader(this)) { + throw defaultReaderBrandCheckException('releaseLock'); + } + if (this._ownerReadableStream === undefined) { + return; + } + if (this._readRequests.length > 0) { + throw new TypeError('Tried to release a reader lock when that reader has pending read() calls un-settled'); + } + ReadableStreamReaderGenericRelease(this); + } +} +Object.defineProperties(ReadableStreamDefaultReader.prototype, { + cancel: { enumerable: true }, + read: { enumerable: true }, + releaseLock: { enumerable: true }, + closed: { enumerable: true } +}); +if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(ReadableStreamDefaultReader.prototype, SymbolPolyfill.toStringTag, { + value: 'ReadableStreamDefaultReader', + configurable: true + }); +} +// Abstract operations for the readers. +function IsReadableStreamDefaultReader(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_readRequests')) { + return false; + } + return true; +} +function ReadableStreamDefaultReaderRead(reader, readRequest) { + const stream = reader._ownerReadableStream; + stream._disturbed = true; + if (stream._state === 'closed') { + readRequest._closeSteps(); + } + else if (stream._state === 'errored') { + readRequest._errorSteps(stream._storedError); + } + else { + stream._readableStreamController[PullSteps](readRequest); + } +} +// Helper functions for the ReadableStreamDefaultReader. +function defaultReaderBrandCheckException(name) { + return new TypeError(`ReadableStreamDefaultReader.prototype.${name} can only be used on a ReadableStreamDefaultReader`); +} - /** Key flags - * @enum {Integer} - * @readonly - */ - keyFlags: { - /** 0x01 - This key may be used to certify other keys. */ - certify_keys: 1, - /** 0x02 - This key may be used to sign data. */ - sign_data: 2, - /** 0x04 - This key may be used to encrypt communications. */ - encrypt_communication: 4, - /** 0x08 - This key may be used to encrypt storage. */ - encrypt_storage: 8, - /** 0x10 - The private component of this key may have been split - * by a secret-sharing mechanism. */ - split_private_key: 16, - /** 0x20 - This key may be used for authentication. */ - authentication: 32, - /** 0x80 - The private component of this key may be in the - * possession of more than one person. */ - shared_private_key: 128 - }, +/// +let AsyncIteratorPrototype; +if (typeof SymbolPolyfill.asyncIterator === 'symbol') { + // We're running inside a ES2018+ environment, but we're compiling to an older syntax. + // We cannot access %AsyncIteratorPrototype% without non-ES2018 syntax, but we can re-create it. + AsyncIteratorPrototype = { + // 25.1.3.1 %AsyncIteratorPrototype% [ @@asyncIterator ] ( ) + // https://tc39.github.io/ecma262/#sec-asynciteratorprototype-asynciterator + [SymbolPolyfill.asyncIterator]() { + return this; + } + }; + Object.defineProperty(AsyncIteratorPrototype, SymbolPolyfill.asyncIterator, { enumerable: false }); +} + +/// +class ReadableStreamAsyncIteratorImpl { + constructor(reader, preventCancel) { + this._ongoingPromise = undefined; + this._isFinished = false; + this._reader = reader; + this._preventCancel = preventCancel; + } + next() { + const nextSteps = () => this._nextSteps(); + this._ongoingPromise = this._ongoingPromise ? + transformPromiseWith(this._ongoingPromise, nextSteps, nextSteps) : + nextSteps(); + return this._ongoingPromise; + } + return(value) { + const returnSteps = () => this._returnSteps(value); + return this._ongoingPromise ? + transformPromiseWith(this._ongoingPromise, returnSteps, returnSteps) : + returnSteps(); + } + _nextSteps() { + if (this._isFinished) { + return Promise.resolve({ value: undefined, done: true }); + } + const reader = this._reader; + if (reader._ownerReadableStream === undefined) { + return promiseRejectedWith(readerLockException('iterate')); + } + let resolvePromise; + let rejectPromise; + const promise = newPromise((resolve, reject) => { + resolvePromise = resolve; + rejectPromise = reject; + }); + const readRequest = { + _chunkSteps: chunk => { + this._ongoingPromise = undefined; + // This needs to be delayed by one microtask, otherwise we stop pulling too early which breaks a test. + // FIXME Is this a bug in the specification, or in the test? + queueMicrotask(() => resolvePromise({ value: chunk, done: false })); + }, + _closeSteps: () => { + this._ongoingPromise = undefined; + this._isFinished = true; + ReadableStreamReaderGenericRelease(reader); + resolvePromise({ value: undefined, done: true }); + }, + _errorSteps: reason => { + this._ongoingPromise = undefined; + this._isFinished = true; + ReadableStreamReaderGenericRelease(reader); + rejectPromise(reason); + } + }; + ReadableStreamDefaultReaderRead(reader, readRequest); + return promise; + } + _returnSteps(value) { + if (this._isFinished) { + return Promise.resolve({ value, done: true }); + } + this._isFinished = true; + const reader = this._reader; + if (reader._ownerReadableStream === undefined) { + return promiseRejectedWith(readerLockException('finish iterating')); + } + if (!this._preventCancel) { + const result = ReadableStreamReaderGenericCancel(reader, value); + ReadableStreamReaderGenericRelease(reader); + return transformPromiseWith(result, () => ({ value, done: true })); + } + ReadableStreamReaderGenericRelease(reader); + return promiseResolvedWith({ value, done: true }); + } +} +const ReadableStreamAsyncIteratorPrototype = { + next() { + if (!IsReadableStreamAsyncIterator(this)) { + return promiseRejectedWith(streamAsyncIteratorBrandCheckException('next')); + } + return this._asyncIteratorImpl.next(); + }, + return(value) { + if (!IsReadableStreamAsyncIterator(this)) { + return promiseRejectedWith(streamAsyncIteratorBrandCheckException('return')); + } + return this._asyncIteratorImpl.return(value); + } +}; +if (AsyncIteratorPrototype !== undefined) { + Object.setPrototypeOf(ReadableStreamAsyncIteratorPrototype, AsyncIteratorPrototype); +} +// Abstract operations for the ReadableStream. +function AcquireReadableStreamAsyncIterator(stream, preventCancel) { + const reader = AcquireReadableStreamDefaultReader(stream); + const impl = new ReadableStreamAsyncIteratorImpl(reader, preventCancel); + const iterator = Object.create(ReadableStreamAsyncIteratorPrototype); + iterator._asyncIteratorImpl = impl; + return iterator; +} +function IsReadableStreamAsyncIterator(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_asyncIteratorImpl')) { + return false; + } + return true; +} +// Helper functions for the ReadableStream. +function streamAsyncIteratorBrandCheckException(name) { + return new TypeError(`ReadableStreamAsyncIterator.${name} can only be used on a ReadableSteamAsyncIterator`); +} - /** Key status - * @enum {Integer} - * @readonly - */ - keyStatus: { - invalid: 0, - expired: 1, - revoked: 2, - valid: 3, - no_self_cert: 4 - }, +/// +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN#Polyfill +const NumberIsNaN = Number.isNaN || function (x) { + // eslint-disable-next-line no-self-compare + return x !== x; +}; - /** Armor type - * @enum {Integer} - * @readonly - */ - armor: { - multipart_section: 0, - multipart_last: 1, - signed: 2, - message: 3, - public_key: 4, - private_key: 5, - signature: 6 - }, +function IsFiniteNonNegativeNumber(v) { + if (!IsNonNegativeNumber(v)) { + return false; + } + if (v === Infinity) { + return false; + } + return true; +} +function IsNonNegativeNumber(v) { + if (typeof v !== 'number') { + return false; + } + if (NumberIsNaN(v)) { + return false; + } + if (v < 0) { + return false; + } + return true; +} - /** {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.23|RFC4880, section 5.2.3.23} - * @enum {Integer} - * @readonly - */ - reasonForRevocation: { - /** No reason specified (key revocations or cert revocations) */ - no_reason: 0, - /** Key is superseded (key revocations) */ - key_superseded: 1, - /** Key material has been compromised (key revocations) */ - key_compromised: 2, - /** Key is retired and no longer used (key revocations) */ - key_retired: 3, - /** User ID information is no longer valid (cert revocations) */ - userid_invalid: 32 - }, +function DequeueValue(container) { + const pair = container._queue.shift(); + container._queueTotalSize -= pair.size; + if (container._queueTotalSize < 0) { + container._queueTotalSize = 0; + } + return pair.value; +} +function EnqueueValueWithSize(container, value, size) { + size = Number(size); + if (!IsFiniteNonNegativeNumber(size)) { + throw new RangeError('Size must be a finite, non-NaN, non-negative number.'); + } + container._queue.push({ value, size }); + container._queueTotalSize += size; +} +function PeekQueueValue(container) { + const pair = container._queue.peek(); + return pair.value; +} +function ResetQueue(container) { + container._queue = new SimpleQueue(); + container._queueTotalSize = 0; +} - /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.2.3.25|RFC4880bis-04, section 5.2.3.25} - * @enum {Integer} - * @readonly - */ - features: { - /** 0x01 - Modification Detection (packets 18 and 19) */ - modification_detection: 1, - /** 0x02 - AEAD Encrypted Data Packet (packet 20) and version 5 - * Symmetric-Key Encrypted Session Key Packets (packet 3) */ - aead: 2, - /** 0x04 - Version 5 Public-Key Packet format and corresponding new - * fingerprint format */ - v5_keys: 4 - }, +function CreateArrayFromList(elements) { + // We use arrays to represent lists, so this is basically a no-op. + // Do a slice though just in case we happen to depend on the unique-ness. + return elements.slice(); +} +function CopyDataBlockBytes(dest, destOffset, src, srcOffset, n) { + new Uint8Array(dest).set(new Uint8Array(src, srcOffset, n), destOffset); +} +// Not implemented correctly +function TransferArrayBuffer(O) { + return O; +} +// Not implemented correctly +function IsDetachedBuffer(O) { + return false; +} - /** Asserts validity and converts from string/integer to integer. */ - write: function write(type, e) { - if (typeof e === 'number') { - e = this.read(type, e); +/** + * A pull-into request in a {@link ReadableByteStreamController}. + * + * @public + */ +class ReadableStreamBYOBRequest { + constructor() { + throw new TypeError('Illegal constructor'); + } + /** + * Returns the view for writing in to, or `null` if the BYOB request has already been responded to. + */ + get view() { + if (!IsReadableStreamBYOBRequest(this)) { + throw byobRequestBrandCheckException('view'); + } + return this._view; + } + respond(bytesWritten) { + if (!IsReadableStreamBYOBRequest(this)) { + throw byobRequestBrandCheckException('respond'); + } + assertRequiredArgument(bytesWritten, 1, 'respond'); + bytesWritten = convertUnsignedLongLongWithEnforceRange(bytesWritten, 'First parameter'); + if (this._associatedReadableByteStreamController === undefined) { + throw new TypeError('This BYOB request has been invalidated'); + } + if (IsDetachedBuffer(this._view.buffer)) ; + ReadableByteStreamControllerRespond(this._associatedReadableByteStreamController, bytesWritten); + } + respondWithNewView(view) { + if (!IsReadableStreamBYOBRequest(this)) { + throw byobRequestBrandCheckException('respondWithNewView'); + } + assertRequiredArgument(view, 1, 'respondWithNewView'); + if (!ArrayBuffer.isView(view)) { + throw new TypeError('You can only respond with array buffer views'); + } + if (view.byteLength === 0) { + throw new TypeError('chunk must have non-zero byteLength'); + } + if (view.buffer.byteLength === 0) { + throw new TypeError(`chunk's buffer must have non-zero byteLength`); + } + if (this._associatedReadableByteStreamController === undefined) { + throw new TypeError('This BYOB request has been invalidated'); + } + ReadableByteStreamControllerRespondWithNewView(this._associatedReadableByteStreamController, view); + } +} +Object.defineProperties(ReadableStreamBYOBRequest.prototype, { + respond: { enumerable: true }, + respondWithNewView: { enumerable: true }, + view: { enumerable: true } +}); +if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(ReadableStreamBYOBRequest.prototype, SymbolPolyfill.toStringTag, { + value: 'ReadableStreamBYOBRequest', + configurable: true + }); +} +/** + * Allows control of a {@link ReadableStream | readable byte stream}'s state and internal queue. + * + * @public + */ +class ReadableByteStreamController { + constructor() { + throw new TypeError('Illegal constructor'); + } + /** + * Returns the current BYOB pull request, or `null` if there isn't one. + */ + get byobRequest() { + if (!IsReadableByteStreamController(this)) { + throw byteStreamControllerBrandCheckException('byobRequest'); + } + if (this._byobRequest === null && this._pendingPullIntos.length > 0) { + const firstDescriptor = this._pendingPullIntos.peek(); + const view = new Uint8Array(firstDescriptor.buffer, firstDescriptor.byteOffset + firstDescriptor.bytesFilled, firstDescriptor.byteLength - firstDescriptor.bytesFilled); + const byobRequest = Object.create(ReadableStreamBYOBRequest.prototype); + SetUpReadableStreamBYOBRequest(byobRequest, this, view); + this._byobRequest = byobRequest; + } + return this._byobRequest; + } + /** + * Returns the desired size to fill the controlled stream's internal queue. It can be negative, if the queue is + * over-full. An underlying byte source ought to use this information to determine when and how to apply backpressure. + */ + get desiredSize() { + if (!IsReadableByteStreamController(this)) { + throw byteStreamControllerBrandCheckException('desiredSize'); + } + return ReadableByteStreamControllerGetDesiredSize(this); + } + /** + * Closes the controlled readable stream. Consumers will still be able to read any previously-enqueued chunks from + * the stream, but once those are read, the stream will become closed. + */ + close() { + if (!IsReadableByteStreamController(this)) { + throw byteStreamControllerBrandCheckException('close'); + } + if (this._closeRequested) { + throw new TypeError('The stream has already been closed; do not close it again!'); + } + const state = this._controlledReadableByteStream._state; + if (state !== 'readable') { + throw new TypeError(`The stream (in ${state} state) is not in the readable state and cannot be closed`); + } + ReadableByteStreamControllerClose(this); + } + enqueue(chunk) { + if (!IsReadableByteStreamController(this)) { + throw byteStreamControllerBrandCheckException('enqueue'); + } + assertRequiredArgument(chunk, 1, 'enqueue'); + if (!ArrayBuffer.isView(chunk)) { + throw new TypeError('chunk must be an array buffer view'); + } + if (chunk.byteLength === 0) { + throw new TypeError('chunk must have non-zero byteLength'); + } + if (chunk.buffer.byteLength === 0) { + throw new TypeError(`chunk's buffer must have non-zero byteLength`); + } + if (this._closeRequested) { + throw new TypeError('stream is closed or draining'); + } + const state = this._controlledReadableByteStream._state; + if (state !== 'readable') { + throw new TypeError(`The stream (in ${state} state) is not in the readable state and cannot be enqueued to`); + } + ReadableByteStreamControllerEnqueue(this, chunk); + } + /** + * Errors the controlled readable stream, making all future interactions with it fail with the given error `e`. + */ + error(e = undefined) { + if (!IsReadableByteStreamController(this)) { + throw byteStreamControllerBrandCheckException('error'); + } + ReadableByteStreamControllerError(this, e); + } + /** @internal */ + [CancelSteps](reason) { + if (this._pendingPullIntos.length > 0) { + const firstDescriptor = this._pendingPullIntos.peek(); + firstDescriptor.bytesFilled = 0; + } + ResetQueue(this); + const result = this._cancelAlgorithm(reason); + ReadableByteStreamControllerClearAlgorithms(this); + return result; + } + /** @internal */ + [PullSteps](readRequest) { + const stream = this._controlledReadableByteStream; + if (this._queueTotalSize > 0) { + const entry = this._queue.shift(); + this._queueTotalSize -= entry.byteLength; + ReadableByteStreamControllerHandleQueueDrain(this); + const view = new Uint8Array(entry.buffer, entry.byteOffset, entry.byteLength); + readRequest._chunkSteps(view); + return; + } + const autoAllocateChunkSize = this._autoAllocateChunkSize; + if (autoAllocateChunkSize !== undefined) { + let buffer; + try { + buffer = new ArrayBuffer(autoAllocateChunkSize); + } + catch (bufferE) { + readRequest._errorSteps(bufferE); + return; + } + const pullIntoDescriptor = { + buffer, + byteOffset: 0, + byteLength: autoAllocateChunkSize, + bytesFilled: 0, + elementSize: 1, + viewConstructor: Uint8Array, + readerType: 'default' + }; + this._pendingPullIntos.push(pullIntoDescriptor); + } + ReadableStreamAddReadRequest(stream, readRequest); + ReadableByteStreamControllerCallPullIfNeeded(this); + } +} +Object.defineProperties(ReadableByteStreamController.prototype, { + close: { enumerable: true }, + enqueue: { enumerable: true }, + error: { enumerable: true }, + byobRequest: { enumerable: true }, + desiredSize: { enumerable: true } +}); +if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(ReadableByteStreamController.prototype, SymbolPolyfill.toStringTag, { + value: 'ReadableByteStreamController', + configurable: true + }); +} +// Abstract operations for the ReadableByteStreamController. +function IsReadableByteStreamController(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_controlledReadableByteStream')) { + return false; + } + return true; +} +function IsReadableStreamBYOBRequest(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_associatedReadableByteStreamController')) { + return false; + } + return true; +} +function ReadableByteStreamControllerCallPullIfNeeded(controller) { + const shouldPull = ReadableByteStreamControllerShouldCallPull(controller); + if (!shouldPull) { + return; + } + if (controller._pulling) { + controller._pullAgain = true; + return; + } + controller._pulling = true; + // TODO: Test controller argument + const pullPromise = controller._pullAlgorithm(); + uponPromise(pullPromise, () => { + controller._pulling = false; + if (controller._pullAgain) { + controller._pullAgain = false; + ReadableByteStreamControllerCallPullIfNeeded(controller); + } + }, e => { + ReadableByteStreamControllerError(controller, e); + }); +} +function ReadableByteStreamControllerClearPendingPullIntos(controller) { + ReadableByteStreamControllerInvalidateBYOBRequest(controller); + controller._pendingPullIntos = new SimpleQueue(); +} +function ReadableByteStreamControllerCommitPullIntoDescriptor(stream, pullIntoDescriptor) { + let done = false; + if (stream._state === 'closed') { + done = true; + } + const filledView = ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor); + if (pullIntoDescriptor.readerType === 'default') { + ReadableStreamFulfillReadRequest(stream, filledView, done); + } + else { + ReadableStreamFulfillReadIntoRequest(stream, filledView, done); + } +} +function ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor) { + const bytesFilled = pullIntoDescriptor.bytesFilled; + const elementSize = pullIntoDescriptor.elementSize; + return new pullIntoDescriptor.viewConstructor(pullIntoDescriptor.buffer, pullIntoDescriptor.byteOffset, bytesFilled / elementSize); +} +function ReadableByteStreamControllerEnqueueChunkToQueue(controller, buffer, byteOffset, byteLength) { + controller._queue.push({ buffer, byteOffset, byteLength }); + controller._queueTotalSize += byteLength; +} +function ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor) { + const elementSize = pullIntoDescriptor.elementSize; + const currentAlignedBytes = pullIntoDescriptor.bytesFilled - pullIntoDescriptor.bytesFilled % elementSize; + const maxBytesToCopy = Math.min(controller._queueTotalSize, pullIntoDescriptor.byteLength - pullIntoDescriptor.bytesFilled); + const maxBytesFilled = pullIntoDescriptor.bytesFilled + maxBytesToCopy; + const maxAlignedBytes = maxBytesFilled - maxBytesFilled % elementSize; + let totalBytesToCopyRemaining = maxBytesToCopy; + let ready = false; + if (maxAlignedBytes > currentAlignedBytes) { + totalBytesToCopyRemaining = maxAlignedBytes - pullIntoDescriptor.bytesFilled; + ready = true; + } + const queue = controller._queue; + while (totalBytesToCopyRemaining > 0) { + const headOfQueue = queue.peek(); + const bytesToCopy = Math.min(totalBytesToCopyRemaining, headOfQueue.byteLength); + const destStart = pullIntoDescriptor.byteOffset + pullIntoDescriptor.bytesFilled; + CopyDataBlockBytes(pullIntoDescriptor.buffer, destStart, headOfQueue.buffer, headOfQueue.byteOffset, bytesToCopy); + if (headOfQueue.byteLength === bytesToCopy) { + queue.shift(); + } + else { + headOfQueue.byteOffset += bytesToCopy; + headOfQueue.byteLength -= bytesToCopy; + } + controller._queueTotalSize -= bytesToCopy; + ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, bytesToCopy, pullIntoDescriptor); + totalBytesToCopyRemaining -= bytesToCopy; + } + return ready; +} +function ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, size, pullIntoDescriptor) { + ReadableByteStreamControllerInvalidateBYOBRequest(controller); + pullIntoDescriptor.bytesFilled += size; +} +function ReadableByteStreamControllerHandleQueueDrain(controller) { + if (controller._queueTotalSize === 0 && controller._closeRequested) { + ReadableByteStreamControllerClearAlgorithms(controller); + ReadableStreamClose(controller._controlledReadableByteStream); + } + else { + ReadableByteStreamControllerCallPullIfNeeded(controller); + } +} +function ReadableByteStreamControllerInvalidateBYOBRequest(controller) { + if (controller._byobRequest === null) { + return; + } + controller._byobRequest._associatedReadableByteStreamController = undefined; + controller._byobRequest._view = null; + controller._byobRequest = null; +} +function ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller) { + while (controller._pendingPullIntos.length > 0) { + if (controller._queueTotalSize === 0) { + return; + } + const pullIntoDescriptor = controller._pendingPullIntos.peek(); + if (ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor)) { + ReadableByteStreamControllerShiftPendingPullInto(controller); + ReadableByteStreamControllerCommitPullIntoDescriptor(controller._controlledReadableByteStream, pullIntoDescriptor); + } + } +} +function ReadableByteStreamControllerPullInto(controller, view, readIntoRequest) { + const stream = controller._controlledReadableByteStream; + let elementSize = 1; + if (view.constructor !== DataView) { + elementSize = view.constructor.BYTES_PER_ELEMENT; + } + const ctor = view.constructor; + const buffer = TransferArrayBuffer(view.buffer); + const pullIntoDescriptor = { + buffer, + byteOffset: view.byteOffset, + byteLength: view.byteLength, + bytesFilled: 0, + elementSize, + viewConstructor: ctor, + readerType: 'byob' + }; + if (controller._pendingPullIntos.length > 0) { + controller._pendingPullIntos.push(pullIntoDescriptor); + // No ReadableByteStreamControllerCallPullIfNeeded() call since: + // - No change happens on desiredSize + // - The source has already been notified of that there's at least 1 pending read(view) + ReadableStreamAddReadIntoRequest(stream, readIntoRequest); + return; + } + if (stream._state === 'closed') { + const emptyView = new ctor(pullIntoDescriptor.buffer, pullIntoDescriptor.byteOffset, 0); + readIntoRequest._closeSteps(emptyView); + return; + } + if (controller._queueTotalSize > 0) { + if (ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor)) { + const filledView = ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor); + ReadableByteStreamControllerHandleQueueDrain(controller); + readIntoRequest._chunkSteps(filledView); + return; + } + if (controller._closeRequested) { + const e = new TypeError('Insufficient bytes to fill elements in the given buffer'); + ReadableByteStreamControllerError(controller, e); + readIntoRequest._errorSteps(e); + return; + } + } + controller._pendingPullIntos.push(pullIntoDescriptor); + ReadableStreamAddReadIntoRequest(stream, readIntoRequest); + ReadableByteStreamControllerCallPullIfNeeded(controller); +} +function ReadableByteStreamControllerRespondInClosedState(controller, firstDescriptor) { + firstDescriptor.buffer = TransferArrayBuffer(firstDescriptor.buffer); + const stream = controller._controlledReadableByteStream; + if (ReadableStreamHasBYOBReader(stream)) { + while (ReadableStreamGetNumReadIntoRequests(stream) > 0) { + const pullIntoDescriptor = ReadableByteStreamControllerShiftPendingPullInto(controller); + ReadableByteStreamControllerCommitPullIntoDescriptor(stream, pullIntoDescriptor); + } + } +} +function ReadableByteStreamControllerRespondInReadableState(controller, bytesWritten, pullIntoDescriptor) { + if (pullIntoDescriptor.bytesFilled + bytesWritten > pullIntoDescriptor.byteLength) { + throw new RangeError('bytesWritten out of range'); + } + ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, bytesWritten, pullIntoDescriptor); + if (pullIntoDescriptor.bytesFilled < pullIntoDescriptor.elementSize) { + // TODO: Figure out whether we should detach the buffer or not here. + return; + } + ReadableByteStreamControllerShiftPendingPullInto(controller); + const remainderSize = pullIntoDescriptor.bytesFilled % pullIntoDescriptor.elementSize; + if (remainderSize > 0) { + const end = pullIntoDescriptor.byteOffset + pullIntoDescriptor.bytesFilled; + const remainder = pullIntoDescriptor.buffer.slice(end - remainderSize, end); + ReadableByteStreamControllerEnqueueChunkToQueue(controller, remainder, 0, remainder.byteLength); + } + pullIntoDescriptor.buffer = TransferArrayBuffer(pullIntoDescriptor.buffer); + pullIntoDescriptor.bytesFilled -= remainderSize; + ReadableByteStreamControllerCommitPullIntoDescriptor(controller._controlledReadableByteStream, pullIntoDescriptor); + ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller); +} +function ReadableByteStreamControllerRespondInternal(controller, bytesWritten) { + const firstDescriptor = controller._pendingPullIntos.peek(); + const state = controller._controlledReadableByteStream._state; + if (state === 'closed') { + if (bytesWritten !== 0) { + throw new TypeError('bytesWritten must be 0 when calling respond() on a closed stream'); + } + ReadableByteStreamControllerRespondInClosedState(controller, firstDescriptor); + } + else { + ReadableByteStreamControllerRespondInReadableState(controller, bytesWritten, firstDescriptor); + } + ReadableByteStreamControllerCallPullIfNeeded(controller); +} +function ReadableByteStreamControllerShiftPendingPullInto(controller) { + const descriptor = controller._pendingPullIntos.shift(); + ReadableByteStreamControllerInvalidateBYOBRequest(controller); + return descriptor; +} +function ReadableByteStreamControllerShouldCallPull(controller) { + const stream = controller._controlledReadableByteStream; + if (stream._state !== 'readable') { + return false; + } + if (controller._closeRequested) { + return false; + } + if (!controller._started) { + return false; + } + if (ReadableStreamHasDefaultReader(stream) && ReadableStreamGetNumReadRequests(stream) > 0) { + return true; + } + if (ReadableStreamHasBYOBReader(stream) && ReadableStreamGetNumReadIntoRequests(stream) > 0) { + return true; + } + const desiredSize = ReadableByteStreamControllerGetDesiredSize(controller); + if (desiredSize > 0) { + return true; + } + return false; +} +function ReadableByteStreamControllerClearAlgorithms(controller) { + controller._pullAlgorithm = undefined; + controller._cancelAlgorithm = undefined; +} +// A client of ReadableByteStreamController may use these functions directly to bypass state check. +function ReadableByteStreamControllerClose(controller) { + const stream = controller._controlledReadableByteStream; + if (controller._closeRequested || stream._state !== 'readable') { + return; + } + if (controller._queueTotalSize > 0) { + controller._closeRequested = true; + return; + } + if (controller._pendingPullIntos.length > 0) { + const firstPendingPullInto = controller._pendingPullIntos.peek(); + if (firstPendingPullInto.bytesFilled > 0) { + const e = new TypeError('Insufficient bytes to fill elements in the given buffer'); + ReadableByteStreamControllerError(controller, e); + throw e; + } + } + ReadableByteStreamControllerClearAlgorithms(controller); + ReadableStreamClose(stream); +} +function ReadableByteStreamControllerEnqueue(controller, chunk) { + const stream = controller._controlledReadableByteStream; + if (controller._closeRequested || stream._state !== 'readable') { + return; + } + const buffer = chunk.buffer; + const byteOffset = chunk.byteOffset; + const byteLength = chunk.byteLength; + const transferredBuffer = TransferArrayBuffer(buffer); + if (ReadableStreamHasDefaultReader(stream)) { + if (ReadableStreamGetNumReadRequests(stream) === 0) { + ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength); + } + else { + const transferredView = new Uint8Array(transferredBuffer, byteOffset, byteLength); + ReadableStreamFulfillReadRequest(stream, transferredView, false); + } + } + else if (ReadableStreamHasBYOBReader(stream)) { + // TODO: Ideally in this branch detaching should happen only if the buffer is not consumed fully. + ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength); + ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller); + } + else { + ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength); + } + ReadableByteStreamControllerCallPullIfNeeded(controller); +} +function ReadableByteStreamControllerError(controller, e) { + const stream = controller._controlledReadableByteStream; + if (stream._state !== 'readable') { + return; + } + ReadableByteStreamControllerClearPendingPullIntos(controller); + ResetQueue(controller); + ReadableByteStreamControllerClearAlgorithms(controller); + ReadableStreamError(stream, e); +} +function ReadableByteStreamControllerGetDesiredSize(controller) { + const state = controller._controlledReadableByteStream._state; + if (state === 'errored') { + return null; + } + if (state === 'closed') { + return 0; + } + return controller._strategyHWM - controller._queueTotalSize; +} +function ReadableByteStreamControllerRespond(controller, bytesWritten) { + bytesWritten = Number(bytesWritten); + if (!IsFiniteNonNegativeNumber(bytesWritten)) { + throw new RangeError('bytesWritten must be a finite'); + } + ReadableByteStreamControllerRespondInternal(controller, bytesWritten); +} +function ReadableByteStreamControllerRespondWithNewView(controller, view) { + const firstDescriptor = controller._pendingPullIntos.peek(); + if (firstDescriptor.byteOffset + firstDescriptor.bytesFilled !== view.byteOffset) { + throw new RangeError('The region specified by view does not match byobRequest'); + } + if (firstDescriptor.byteLength !== view.byteLength) { + throw new RangeError('The buffer of view has different capacity than byobRequest'); + } + firstDescriptor.buffer = view.buffer; + ReadableByteStreamControllerRespondInternal(controller, view.byteLength); +} +function SetUpReadableByteStreamController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, autoAllocateChunkSize) { + controller._controlledReadableByteStream = stream; + controller._pullAgain = false; + controller._pulling = false; + controller._byobRequest = null; + // Need to set the slots so that the assert doesn't fire. In the spec the slots already exist implicitly. + controller._queue = controller._queueTotalSize = undefined; + ResetQueue(controller); + controller._closeRequested = false; + controller._started = false; + controller._strategyHWM = highWaterMark; + controller._pullAlgorithm = pullAlgorithm; + controller._cancelAlgorithm = cancelAlgorithm; + controller._autoAllocateChunkSize = autoAllocateChunkSize; + controller._pendingPullIntos = new SimpleQueue(); + stream._readableStreamController = controller; + const startResult = startAlgorithm(); + uponPromise(promiseResolvedWith(startResult), () => { + controller._started = true; + ReadableByteStreamControllerCallPullIfNeeded(controller); + }, r => { + ReadableByteStreamControllerError(controller, r); + }); +} +function SetUpReadableByteStreamControllerFromUnderlyingSource(stream, underlyingByteSource, highWaterMark) { + const controller = Object.create(ReadableByteStreamController.prototype); + let startAlgorithm = () => undefined; + let pullAlgorithm = () => promiseResolvedWith(undefined); + let cancelAlgorithm = () => promiseResolvedWith(undefined); + if (underlyingByteSource.start !== undefined) { + startAlgorithm = () => underlyingByteSource.start(controller); + } + if (underlyingByteSource.pull !== undefined) { + pullAlgorithm = () => underlyingByteSource.pull(controller); + } + if (underlyingByteSource.cancel !== undefined) { + cancelAlgorithm = reason => underlyingByteSource.cancel(reason); + } + const autoAllocateChunkSize = underlyingByteSource.autoAllocateChunkSize; + if (autoAllocateChunkSize === 0) { + throw new TypeError('autoAllocateChunkSize must be greater than 0'); + } + SetUpReadableByteStreamController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, autoAllocateChunkSize); +} +function SetUpReadableStreamBYOBRequest(request, controller, view) { + request._associatedReadableByteStreamController = controller; + request._view = view; +} +// Helper functions for the ReadableStreamBYOBRequest. +function byobRequestBrandCheckException(name) { + return new TypeError(`ReadableStreamBYOBRequest.prototype.${name} can only be used on a ReadableStreamBYOBRequest`); +} +// Helper functions for the ReadableByteStreamController. +function byteStreamControllerBrandCheckException(name) { + return new TypeError(`ReadableByteStreamController.prototype.${name} can only be used on a ReadableByteStreamController`); +} + +// Abstract operations for the ReadableStream. +function AcquireReadableStreamBYOBReader(stream) { + return new ReadableStreamBYOBReader(stream); +} +// ReadableStream API exposed for controllers. +function ReadableStreamAddReadIntoRequest(stream, readIntoRequest) { + stream._reader._readIntoRequests.push(readIntoRequest); +} +function ReadableStreamFulfillReadIntoRequest(stream, chunk, done) { + const reader = stream._reader; + const readIntoRequest = reader._readIntoRequests.shift(); + if (done) { + readIntoRequest._closeSteps(chunk); + } + else { + readIntoRequest._chunkSteps(chunk); + } +} +function ReadableStreamGetNumReadIntoRequests(stream) { + return stream._reader._readIntoRequests.length; +} +function ReadableStreamHasBYOBReader(stream) { + const reader = stream._reader; + if (reader === undefined) { + return false; + } + if (!IsReadableStreamBYOBReader(reader)) { + return false; + } + return true; +} +/** + * A BYOB reader vended by a {@link ReadableStream}. + * + * @public + */ +class ReadableStreamBYOBReader { + constructor(stream) { + assertRequiredArgument(stream, 1, 'ReadableStreamBYOBReader'); + assertReadableStream(stream, 'First parameter'); + if (IsReadableStreamLocked(stream)) { + throw new TypeError('This stream has already been locked for exclusive reading by another reader'); + } + if (!IsReadableByteStreamController(stream._readableStreamController)) { + throw new TypeError('Cannot construct a ReadableStreamBYOBReader for a stream not constructed with a byte ' + + 'source'); + } + ReadableStreamReaderGenericInitialize(this, stream); + this._readIntoRequests = new SimpleQueue(); + } + /** + * Returns a promise that will be fulfilled when the stream becomes closed, or rejected if the stream ever errors or + * the reader's lock is released before the stream finishes closing. + */ + get closed() { + if (!IsReadableStreamBYOBReader(this)) { + return promiseRejectedWith(byobReaderBrandCheckException('closed')); + } + return this._closedPromise; + } + /** + * If the reader is active, behaves the same as {@link ReadableStream.cancel | stream.cancel(reason)}. + */ + cancel(reason = undefined) { + if (!IsReadableStreamBYOBReader(this)) { + return promiseRejectedWith(byobReaderBrandCheckException('cancel')); + } + if (this._ownerReadableStream === undefined) { + return promiseRejectedWith(readerLockException('cancel')); + } + return ReadableStreamReaderGenericCancel(this, reason); + } + /** + * Attempts to reads bytes into view, and returns a promise resolved with the result. + * + * If reading a chunk causes the queue to become empty, more data will be pulled from the underlying source. + */ + read(view) { + if (!IsReadableStreamBYOBReader(this)) { + return promiseRejectedWith(byobReaderBrandCheckException('read')); + } + if (!ArrayBuffer.isView(view)) { + return promiseRejectedWith(new TypeError('view must be an array buffer view')); + } + if (view.byteLength === 0) { + return promiseRejectedWith(new TypeError('view must have non-zero byteLength')); + } + if (view.buffer.byteLength === 0) { + return promiseRejectedWith(new TypeError(`view's buffer must have non-zero byteLength`)); + } + if (this._ownerReadableStream === undefined) { + return promiseRejectedWith(readerLockException('read from')); + } + let resolvePromise; + let rejectPromise; + const promise = newPromise((resolve, reject) => { + resolvePromise = resolve; + rejectPromise = reject; + }); + const readIntoRequest = { + _chunkSteps: chunk => resolvePromise({ value: chunk, done: false }), + _closeSteps: chunk => resolvePromise({ value: chunk, done: true }), + _errorSteps: e => rejectPromise(e) + }; + ReadableStreamBYOBReaderRead(this, view, readIntoRequest); + return promise; } - - if (type[e] !== undefined) { - return type[e]; + /** + * Releases the reader's lock on the corresponding stream. After the lock is released, the reader is no longer active. + * If the associated stream is errored when the lock is released, the reader will appear errored in the same way + * from now on; otherwise, the reader will appear closed. + * + * A reader's lock cannot be released while it still has a pending read request, i.e., if a promise returned by + * the reader's {@link ReadableStreamBYOBReader.read | read()} method has not yet been settled. Attempting to + * do so will throw a `TypeError` and leave the reader locked to the stream. + */ + releaseLock() { + if (!IsReadableStreamBYOBReader(this)) { + throw byobReaderBrandCheckException('releaseLock'); + } + if (this._ownerReadableStream === undefined) { + return; + } + if (this._readIntoRequests.length > 0) { + throw new TypeError('Tried to release a reader lock when that reader has pending read() calls un-settled'); + } + ReadableStreamReaderGenericRelease(this); } - - throw new Error('Invalid enum value.'); - }, - - /** Converts from an integer to string. */ - read: function read(type, e) { - if (!type[byValue]) { - type[byValue] = []; - Object.entries(type).forEach(([key, value]) => { - type[byValue][value] = key; - }); +} +Object.defineProperties(ReadableStreamBYOBReader.prototype, { + cancel: { enumerable: true }, + read: { enumerable: true }, + releaseLock: { enumerable: true }, + closed: { enumerable: true } +}); +if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(ReadableStreamBYOBReader.prototype, SymbolPolyfill.toStringTag, { + value: 'ReadableStreamBYOBReader', + configurable: true + }); +} +// Abstract operations for the readers. +function IsReadableStreamBYOBReader(x) { + if (!typeIsObject(x)) { + return false; } - - if (type[byValue][e] !== undefined) { - return type[byValue][e]; + if (!Object.prototype.hasOwnProperty.call(x, '_readIntoRequests')) { + return false; } + return true; +} +function ReadableStreamBYOBReaderRead(reader, view, readIntoRequest) { + const stream = reader._ownerReadableStream; + stream._disturbed = true; + if (stream._state === 'errored') { + readIntoRequest._errorSteps(stream._storedError); + } + else { + ReadableByteStreamControllerPullInto(stream._readableStreamController, view, readIntoRequest); + } +} +// Helper functions for the ReadableStreamBYOBReader. +function byobReaderBrandCheckException(name) { + return new TypeError(`ReadableStreamBYOBReader.prototype.${name} can only be used on a ReadableStreamBYOBReader`); +} - throw new Error('Invalid enum value.'); - } - -}; - -},{}],114:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _config = require('./config'); - -var _config2 = _interopRequireDefault(_config); +function ExtractHighWaterMark(strategy, defaultHWM) { + const { highWaterMark } = strategy; + if (highWaterMark === undefined) { + return defaultHWM; + } + if (NumberIsNaN(highWaterMark) || highWaterMark < 0) { + throw new RangeError('Invalid highWaterMark'); + } + return highWaterMark; +} +function ExtractSizeAlgorithm(strategy) { + const { size } = strategy; + if (!size) { + return () => 1; + } + return size; +} -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +function convertQueuingStrategy(init, context) { + assertDictionary(init, context); + const highWaterMark = init === null || init === void 0 ? void 0 : init.highWaterMark; + const size = init === null || init === void 0 ? void 0 : init.size; + return { + highWaterMark: highWaterMark === undefined ? undefined : convertUnrestrictedDouble(highWaterMark), + size: size === undefined ? undefined : convertQueuingStrategySize(size, `${context} has member 'size' that`) + }; +} +function convertQueuingStrategySize(fn, context) { + assertFunction(fn, context); + return chunk => convertUnrestrictedDouble(fn(chunk)); +} -/** - * Initialize the HKP client and configure it with the key server url and fetch function. - * @constructor - * @param {String} keyServerBaseUrl (optional) The HKP key server base url including - * the protocol to use, e.g. 'https://pgp.mit.edu'; defaults to - * openpgp.config.keyserver (https://keyserver.ubuntu.com) - */ -function HKP(keyServerBaseUrl) { - this._baseUrl = keyServerBaseUrl || _config2.default.keyserver; - this._fetch = typeof window !== 'undefined' ? window.fetch : require('node-fetch'); +function convertUnderlyingSink(original, context) { + assertDictionary(original, context); + const abort = original === null || original === void 0 ? void 0 : original.abort; + const close = original === null || original === void 0 ? void 0 : original.close; + const start = original === null || original === void 0 ? void 0 : original.start; + const type = original === null || original === void 0 ? void 0 : original.type; + const write = original === null || original === void 0 ? void 0 : original.write; + return { + abort: abort === undefined ? + undefined : + convertUnderlyingSinkAbortCallback(abort, original, `${context} has member 'abort' that`), + close: close === undefined ? + undefined : + convertUnderlyingSinkCloseCallback(close, original, `${context} has member 'close' that`), + start: start === undefined ? + undefined : + convertUnderlyingSinkStartCallback(start, original, `${context} has member 'start' that`), + write: write === undefined ? + undefined : + convertUnderlyingSinkWriteCallback(write, original, `${context} has member 'write' that`), + type + }; +} +function convertUnderlyingSinkAbortCallback(fn, original, context) { + assertFunction(fn, context); + return (reason) => promiseCall(fn, original, [reason]); +} +function convertUnderlyingSinkCloseCallback(fn, original, context) { + assertFunction(fn, context); + return () => promiseCall(fn, original, []); +} +function convertUnderlyingSinkStartCallback(fn, original, context) { + assertFunction(fn, context); + return (controller) => reflectCall(fn, original, [controller]); +} +function convertUnderlyingSinkWriteCallback(fn, original, context) { + assertFunction(fn, context); + return (chunk, controller) => promiseCall(fn, original, [chunk, controller]); } -/** - * Search for a public key on the key server either by key ID or part of the user ID. - * @param {String} options.keyID The long public key ID. - * @param {String} options.query This can be any part of the key user ID such as name - * or email address. - * @returns {Promise} The ascii armored public key. - * @async - */ -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2015 Tankred Hase -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +function assertWritableStream(x, context) { + if (!IsWritableStream(x)) { + throw new TypeError(`${context} is not a WritableStream.`); + } +} /** - * @fileoverview This class implements a client for the OpenPGP HTTP Keyserver Protocol (HKP) - * in order to lookup and upload keys on standard public key servers. - * @module hkp + * A writable stream represents a destination for data, into which you can write. + * + * @public */ - -HKP.prototype.lookup = function (options) { - let uri = this._baseUrl + '/pks/lookup?op=get&options=mr&search='; - const fetch = this._fetch; - - if (options.keyId) { - uri += '0x' + encodeURIComponent(options.keyId); - } else if (options.query) { - uri += encodeURIComponent(options.query); - } else { - throw new Error('You must provide a query parameter!'); - } - - return fetch(uri).then(function (response) { - if (response.status === 200) { - return response.text(); +class WritableStream$1 { + constructor(rawUnderlyingSink = {}, rawStrategy = {}) { + if (rawUnderlyingSink === undefined) { + rawUnderlyingSink = null; + } + else { + assertObject(rawUnderlyingSink, 'First parameter'); + } + const strategy = convertQueuingStrategy(rawStrategy, 'Second parameter'); + const underlyingSink = convertUnderlyingSink(rawUnderlyingSink, 'First parameter'); + InitializeWritableStream(this); + const type = underlyingSink.type; + if (type !== undefined) { + throw new RangeError('Invalid type is specified'); + } + const sizeAlgorithm = ExtractSizeAlgorithm(strategy); + const highWaterMark = ExtractHighWaterMark(strategy, 1); + SetUpWritableStreamDefaultControllerFromUnderlyingSink(this, underlyingSink, highWaterMark, sizeAlgorithm); } - }).then(function (publicKeyArmored) { - if (!publicKeyArmored || publicKeyArmored.indexOf('-----END PGP PUBLIC KEY BLOCK-----') < 0) { - return; + /** + * Returns whether or not the writable stream is locked to a writer. + */ + get locked() { + if (!IsWritableStream(this)) { + throw streamBrandCheckException$2('locked'); + } + return IsWritableStreamLocked(this); } - return publicKeyArmored.trim(); - }); -}; - -/** - * Upload a public key to the server. - * @param {String} publicKeyArmored An ascii armored public key to be uploaded. - * @returns {Promise} - * @async - */ -HKP.prototype.upload = function (publicKeyArmored) { - const uri = this._baseUrl + '/pks/add'; - const fetch = this._fetch; - - return fetch(uri, { - method: 'post', - headers: { - 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' - }, - body: 'keytext=' + encodeURIComponent(publicKeyArmored) - }); -}; - -exports.default = HKP; - -},{"./config":79,"node-fetch":"node-fetch"}],115:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.WKD = exports.HKP = exports.AsyncProxy = exports.Keyring = exports.crypto = exports.config = exports.enums = exports.armor = exports.stream = exports.OID = exports.KDFParams = exports.ECDHSymmetricKey = exports.Keyid = exports.S2K = exports.MPI = exports.packet = exports.util = exports.cleartext = exports.message = exports.signature = exports.key = exports.destroyWorker = exports.getWorker = exports.initWorker = exports.decryptSessionKeys = exports.encryptSessionKey = exports.decryptKey = exports.revokeKey = exports.reformatKey = exports.generateKey = exports.verify = exports.sign = exports.decrypt = exports.encrypt = undefined; - -var _openpgp = require('./openpgp'); - -Object.defineProperty(exports, 'encrypt', { - enumerable: true, - get: function get() { - return _openpgp.encrypt; - } -}); -Object.defineProperty(exports, 'decrypt', { - enumerable: true, - get: function get() { - return _openpgp.decrypt; - } -}); -Object.defineProperty(exports, 'sign', { - enumerable: true, - get: function get() { - return _openpgp.sign; - } -}); -Object.defineProperty(exports, 'verify', { - enumerable: true, - get: function get() { - return _openpgp.verify; - } -}); -Object.defineProperty(exports, 'generateKey', { - enumerable: true, - get: function get() { - return _openpgp.generateKey; - } -}); -Object.defineProperty(exports, 'reformatKey', { - enumerable: true, - get: function get() { - return _openpgp.reformatKey; - } -}); -Object.defineProperty(exports, 'revokeKey', { - enumerable: true, - get: function get() { - return _openpgp.revokeKey; - } -}); -Object.defineProperty(exports, 'decryptKey', { - enumerable: true, - get: function get() { - return _openpgp.decryptKey; - } -}); -Object.defineProperty(exports, 'encryptSessionKey', { - enumerable: true, - get: function get() { - return _openpgp.encryptSessionKey; - } -}); -Object.defineProperty(exports, 'decryptSessionKeys', { - enumerable: true, - get: function get() { - return _openpgp.decryptSessionKeys; - } -}); -Object.defineProperty(exports, 'initWorker', { - enumerable: true, - get: function get() { - return _openpgp.initWorker; - } -}); -Object.defineProperty(exports, 'getWorker', { - enumerable: true, - get: function get() { - return _openpgp.getWorker; - } -}); -Object.defineProperty(exports, 'destroyWorker', { - enumerable: true, - get: function get() { - return _openpgp.destroyWorker; - } -}); - -var _util = require('./util'); - -Object.defineProperty(exports, 'util', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_util).default; - } -}); - -var _packet = require('./packet'); - -Object.defineProperty(exports, 'packet', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_packet).default; - } -}); - -var _mpi = require('./type/mpi'); - -Object.defineProperty(exports, 'MPI', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_mpi).default; - } -}); - -var _s2k = require('./type/s2k'); - -Object.defineProperty(exports, 'S2K', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_s2k).default; - } -}); - -var _keyid = require('./type/keyid'); - -Object.defineProperty(exports, 'Keyid', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_keyid).default; - } -}); - -var _ecdh_symkey = require('./type/ecdh_symkey'); - -Object.defineProperty(exports, 'ECDHSymmetricKey', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_ecdh_symkey).default; - } -}); - -var _kdf_params = require('./type/kdf_params'); - -Object.defineProperty(exports, 'KDFParams', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_kdf_params).default; - } -}); - -var _oid = require('./type/oid'); - -Object.defineProperty(exports, 'OID', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_oid).default; - } -}); - -var _webStreamTools = require('web-stream-tools'); - -Object.defineProperty(exports, 'stream', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_webStreamTools).default; - } -}); - -var _armor = require('./encoding/armor'); - -Object.defineProperty(exports, 'armor', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_armor).default; - } -}); - -var _enums = require('./enums'); - -Object.defineProperty(exports, 'enums', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_enums).default; - } -}); - -var _config = require('./config/config'); - -Object.defineProperty(exports, 'config', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_config).default; - } -}); - -var _crypto = require('./crypto'); - -Object.defineProperty(exports, 'crypto', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_crypto).default; - } -}); - -var _keyring = require('./keyring'); - -Object.defineProperty(exports, 'Keyring', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_keyring).default; - } -}); - -var _async_proxy = require('./worker/async_proxy'); - -Object.defineProperty(exports, 'AsyncProxy', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_async_proxy).default; - } -}); - -var _hkp = require('./hkp'); - -Object.defineProperty(exports, 'HKP', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_hkp).default; - } -}); - -var _wkd = require('./wkd'); - -Object.defineProperty(exports, 'WKD', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_wkd).default; - } + /** + * Aborts the stream, signaling that the producer can no longer successfully write to the stream and it is to be + * immediately moved to an errored state, with any queued-up writes discarded. This will also execute any abort + * mechanism of the underlying sink. + * + * The returned promise will fulfill if the stream shuts down successfully, or reject if the underlying sink signaled + * that there was an error doing so. Additionally, it will reject with a `TypeError` (without attempting to cancel + * the stream) if the stream is currently locked. + */ + abort(reason = undefined) { + if (!IsWritableStream(this)) { + return promiseRejectedWith(streamBrandCheckException$2('abort')); + } + if (IsWritableStreamLocked(this)) { + return promiseRejectedWith(new TypeError('Cannot abort a stream that already has a writer')); + } + return WritableStreamAbort(this, reason); + } + /** + * Closes the stream. The underlying sink will finish processing any previously-written chunks, before invoking its + * close behavior. During this time any further attempts to write will fail (without erroring the stream). + * + * The method returns a promise that will fulfill if all remaining chunks are successfully written and the stream + * successfully closes, or rejects if an error is encountered during this process. Additionally, it will reject with + * a `TypeError` (without attempting to cancel the stream) if the stream is currently locked. + */ + close() { + if (!IsWritableStream(this)) { + return promiseRejectedWith(streamBrandCheckException$2('close')); + } + if (IsWritableStreamLocked(this)) { + return promiseRejectedWith(new TypeError('Cannot close a stream that already has a writer')); + } + if (WritableStreamCloseQueuedOrInFlight(this)) { + return promiseRejectedWith(new TypeError('Cannot close an already-closing stream')); + } + return WritableStreamClose(this); + } + /** + * Creates a {@link WritableStreamDefaultWriter | writer} and locks the stream to the new writer. While the stream + * is locked, no other writer can be acquired until this one is released. + * + * This functionality is especially useful for creating abstractions that desire the ability to write to a stream + * without interruption or interleaving. By getting a writer for the stream, you can ensure nobody else can write at + * the same time, which would cause the resulting written data to be unpredictable and probably useless. + */ + getWriter() { + if (!IsWritableStream(this)) { + throw streamBrandCheckException$2('getWriter'); + } + return AcquireWritableStreamDefaultWriter(this); + } +} +Object.defineProperties(WritableStream$1.prototype, { + abort: { enumerable: true }, + close: { enumerable: true }, + getWriter: { enumerable: true }, + locked: { enumerable: true } }); - -var openpgp = _interopRequireWildcard(_openpgp); - -var _key = require('./key'); - -var keyMod = _interopRequireWildcard(_key); - -var _signature = require('./signature'); - -var signatureMod = _interopRequireWildcard(_signature); - -var _message = require('./message'); - -var messageMod = _interopRequireWildcard(_message); - -var _cleartext = require('./cleartext'); - -var cleartextMod = _interopRequireWildcard(_cleartext); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -exports.default = openpgp; - +if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(WritableStream$1.prototype, SymbolPolyfill.toStringTag, { + value: 'WritableStream', + configurable: true + }); +} +// Abstract operations for the WritableStream. +function AcquireWritableStreamDefaultWriter(stream) { + return new WritableStreamDefaultWriter(stream); +} +// Throws if and only if startAlgorithm throws. +function CreateWritableStream(startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark = 1, sizeAlgorithm = () => 1) { + const stream = Object.create(WritableStream$1.prototype); + InitializeWritableStream(stream); + const controller = Object.create(WritableStreamDefaultController.prototype); + SetUpWritableStreamDefaultController(stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark, sizeAlgorithm); + return stream; +} +function InitializeWritableStream(stream) { + stream._state = 'writable'; + // The error that will be reported by new method calls once the state becomes errored. Only set when [[state]] is + // 'erroring' or 'errored'. May be set to an undefined value. + stream._storedError = undefined; + stream._writer = undefined; + // Initialize to undefined first because the constructor of the controller checks this + // variable to validate the caller. + stream._writableStreamController = undefined; + // This queue is placed here instead of the writer class in order to allow for passing a writer to the next data + // producer without waiting for the queued writes to finish. + stream._writeRequests = new SimpleQueue(); + // Write requests are removed from _writeRequests when write() is called on the underlying sink. This prevents + // them from being erroneously rejected on error. If a write() call is in-flight, the request is stored here. + stream._inFlightWriteRequest = undefined; + // The promise that was returned from writer.close(). Stored here because it may be fulfilled after the writer + // has been detached. + stream._closeRequest = undefined; + // Close request is removed from _closeRequest when close() is called on the underlying sink. This prevents it + // from being erroneously rejected on error. If a close() call is in-flight, the request is stored here. + stream._inFlightCloseRequest = undefined; + // The promise that was returned from writer.abort(). This may also be fulfilled after the writer has detached. + stream._pendingAbortRequest = undefined; + // The backpressure signal set by the controller. + stream._backpressure = false; +} +function IsWritableStream(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_writableStreamController')) { + return false; + } + return true; +} +function IsWritableStreamLocked(stream) { + if (stream._writer === undefined) { + return false; + } + return true; +} +function WritableStreamAbort(stream, reason) { + const state = stream._state; + if (state === 'closed' || state === 'errored') { + return promiseResolvedWith(undefined); + } + if (stream._pendingAbortRequest !== undefined) { + return stream._pendingAbortRequest._promise; + } + let wasAlreadyErroring = false; + if (state === 'erroring') { + wasAlreadyErroring = true; + // reason will not be used, so don't keep a reference to it. + reason = undefined; + } + const promise = newPromise((resolve, reject) => { + stream._pendingAbortRequest = { + _promise: undefined, + _resolve: resolve, + _reject: reject, + _reason: reason, + _wasAlreadyErroring: wasAlreadyErroring + }; + }); + stream._pendingAbortRequest._promise = promise; + if (!wasAlreadyErroring) { + WritableStreamStartErroring(stream, reason); + } + return promise; +} +function WritableStreamClose(stream) { + const state = stream._state; + if (state === 'closed' || state === 'errored') { + return promiseRejectedWith(new TypeError(`The stream (in ${state} state) is not in the writable state and cannot be closed`)); + } + const promise = newPromise((resolve, reject) => { + const closeRequest = { + _resolve: resolve, + _reject: reject + }; + stream._closeRequest = closeRequest; + }); + const writer = stream._writer; + if (writer !== undefined && stream._backpressure && state === 'writable') { + defaultWriterReadyPromiseResolve(writer); + } + WritableStreamDefaultControllerClose(stream._writableStreamController); + return promise; +} +// WritableStream API exposed for controllers. +function WritableStreamAddWriteRequest(stream) { + const promise = newPromise((resolve, reject) => { + const writeRequest = { + _resolve: resolve, + _reject: reject + }; + stream._writeRequests.push(writeRequest); + }); + return promise; +} +function WritableStreamDealWithRejection(stream, error) { + const state = stream._state; + if (state === 'writable') { + WritableStreamStartErroring(stream, error); + return; + } + WritableStreamFinishErroring(stream); +} +function WritableStreamStartErroring(stream, reason) { + const controller = stream._writableStreamController; + stream._state = 'erroring'; + stream._storedError = reason; + const writer = stream._writer; + if (writer !== undefined) { + WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, reason); + } + if (!WritableStreamHasOperationMarkedInFlight(stream) && controller._started) { + WritableStreamFinishErroring(stream); + } +} +function WritableStreamFinishErroring(stream) { + stream._state = 'errored'; + stream._writableStreamController[ErrorSteps](); + const storedError = stream._storedError; + stream._writeRequests.forEach(writeRequest => { + writeRequest._reject(storedError); + }); + stream._writeRequests = new SimpleQueue(); + if (stream._pendingAbortRequest === undefined) { + WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); + return; + } + const abortRequest = stream._pendingAbortRequest; + stream._pendingAbortRequest = undefined; + if (abortRequest._wasAlreadyErroring) { + abortRequest._reject(storedError); + WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); + return; + } + const promise = stream._writableStreamController[AbortSteps](abortRequest._reason); + uponPromise(promise, () => { + abortRequest._resolve(); + WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); + }, (reason) => { + abortRequest._reject(reason); + WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); + }); +} +function WritableStreamFinishInFlightWrite(stream) { + stream._inFlightWriteRequest._resolve(undefined); + stream._inFlightWriteRequest = undefined; +} +function WritableStreamFinishInFlightWriteWithError(stream, error) { + stream._inFlightWriteRequest._reject(error); + stream._inFlightWriteRequest = undefined; + WritableStreamDealWithRejection(stream, error); +} +function WritableStreamFinishInFlightClose(stream) { + stream._inFlightCloseRequest._resolve(undefined); + stream._inFlightCloseRequest = undefined; + const state = stream._state; + if (state === 'erroring') { + // The error was too late to do anything, so it is ignored. + stream._storedError = undefined; + if (stream._pendingAbortRequest !== undefined) { + stream._pendingAbortRequest._resolve(); + stream._pendingAbortRequest = undefined; + } + } + stream._state = 'closed'; + const writer = stream._writer; + if (writer !== undefined) { + defaultWriterClosedPromiseResolve(writer); + } +} +function WritableStreamFinishInFlightCloseWithError(stream, error) { + stream._inFlightCloseRequest._reject(error); + stream._inFlightCloseRequest = undefined; + // Never execute sink abort() after sink close(). + if (stream._pendingAbortRequest !== undefined) { + stream._pendingAbortRequest._reject(error); + stream._pendingAbortRequest = undefined; + } + WritableStreamDealWithRejection(stream, error); +} +// TODO(ricea): Fix alphabetical order. +function WritableStreamCloseQueuedOrInFlight(stream) { + if (stream._closeRequest === undefined && stream._inFlightCloseRequest === undefined) { + return false; + } + return true; +} +function WritableStreamHasOperationMarkedInFlight(stream) { + if (stream._inFlightWriteRequest === undefined && stream._inFlightCloseRequest === undefined) { + return false; + } + return true; +} +function WritableStreamMarkCloseRequestInFlight(stream) { + stream._inFlightCloseRequest = stream._closeRequest; + stream._closeRequest = undefined; +} +function WritableStreamMarkFirstWriteRequestInFlight(stream) { + stream._inFlightWriteRequest = stream._writeRequests.shift(); +} +function WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream) { + if (stream._closeRequest !== undefined) { + stream._closeRequest._reject(stream._storedError); + stream._closeRequest = undefined; + } + const writer = stream._writer; + if (writer !== undefined) { + defaultWriterClosedPromiseReject(writer, stream._storedError); + } +} +function WritableStreamUpdateBackpressure(stream, backpressure) { + const writer = stream._writer; + if (writer !== undefined && backpressure !== stream._backpressure) { + if (backpressure) { + defaultWriterReadyPromiseReset(writer); + } + else { + defaultWriterReadyPromiseResolve(writer); + } + } + stream._backpressure = backpressure; +} /** - * Export each high level api function separately. - * Usage: + * A default writer vended by a {@link WritableStream}. * - * import { encryptMessage } from 'openpgp.js' - * encryptMessage(keys, text) - */ -/* eslint-disable import/newline-after-import, import/first */ - + * @public + */ +class WritableStreamDefaultWriter { + constructor(stream) { + assertRequiredArgument(stream, 1, 'WritableStreamDefaultWriter'); + assertWritableStream(stream, 'First parameter'); + if (IsWritableStreamLocked(stream)) { + throw new TypeError('This stream has already been locked for exclusive writing by another writer'); + } + this._ownerWritableStream = stream; + stream._writer = this; + const state = stream._state; + if (state === 'writable') { + if (!WritableStreamCloseQueuedOrInFlight(stream) && stream._backpressure) { + defaultWriterReadyPromiseInitialize(this); + } + else { + defaultWriterReadyPromiseInitializeAsResolved(this); + } + defaultWriterClosedPromiseInitialize(this); + } + else if (state === 'erroring') { + defaultWriterReadyPromiseInitializeAsRejected(this, stream._storedError); + defaultWriterClosedPromiseInitialize(this); + } + else if (state === 'closed') { + defaultWriterReadyPromiseInitializeAsResolved(this); + defaultWriterClosedPromiseInitializeAsResolved(this); + } + else { + const storedError = stream._storedError; + defaultWriterReadyPromiseInitializeAsRejected(this, storedError); + defaultWriterClosedPromiseInitializeAsRejected(this, storedError); + } + } + /** + * Returns a promise that will be fulfilled when the stream becomes closed, or rejected if the stream ever errors or + * the writer’s lock is released before the stream finishes closing. + */ + get closed() { + if (!IsWritableStreamDefaultWriter(this)) { + return promiseRejectedWith(defaultWriterBrandCheckException('closed')); + } + return this._closedPromise; + } + /** + * Returns the desired size to fill the stream’s internal queue. It can be negative, if the queue is over-full. + * A producer can use this information to determine the right amount of data to write. + * + * It will be `null` if the stream cannot be successfully written to (due to either being errored, or having an abort + * queued up). It will return zero if the stream is closed. And the getter will throw an exception if invoked when + * the writer’s lock is released. + */ + get desiredSize() { + if (!IsWritableStreamDefaultWriter(this)) { + throw defaultWriterBrandCheckException('desiredSize'); + } + if (this._ownerWritableStream === undefined) { + throw defaultWriterLockException('desiredSize'); + } + return WritableStreamDefaultWriterGetDesiredSize(this); + } + /** + * Returns a promise that will be fulfilled when the desired size to fill the stream’s internal queue transitions + * from non-positive to positive, signaling that it is no longer applying backpressure. Once the desired size dips + * back to zero or below, the getter will return a new promise that stays pending until the next transition. + * + * If the stream becomes errored or aborted, or the writer’s lock is released, the returned promise will become + * rejected. + */ + get ready() { + if (!IsWritableStreamDefaultWriter(this)) { + return promiseRejectedWith(defaultWriterBrandCheckException('ready')); + } + return this._readyPromise; + } + /** + * If the reader is active, behaves the same as {@link WritableStream.abort | stream.abort(reason)}. + */ + abort(reason = undefined) { + if (!IsWritableStreamDefaultWriter(this)) { + return promiseRejectedWith(defaultWriterBrandCheckException('abort')); + } + if (this._ownerWritableStream === undefined) { + return promiseRejectedWith(defaultWriterLockException('abort')); + } + return WritableStreamDefaultWriterAbort(this, reason); + } + /** + * If the reader is active, behaves the same as {@link WritableStream.close | stream.close()}. + */ + close() { + if (!IsWritableStreamDefaultWriter(this)) { + return promiseRejectedWith(defaultWriterBrandCheckException('close')); + } + const stream = this._ownerWritableStream; + if (stream === undefined) { + return promiseRejectedWith(defaultWriterLockException('close')); + } + if (WritableStreamCloseQueuedOrInFlight(stream)) { + return promiseRejectedWith(new TypeError('Cannot close an already-closing stream')); + } + return WritableStreamDefaultWriterClose(this); + } + /** + * Releases the writer’s lock on the corresponding stream. After the lock is released, the writer is no longer active. + * If the associated stream is errored when the lock is released, the writer will appear errored in the same way from + * now on; otherwise, the writer will appear closed. + * + * Note that the lock can still be released even if some ongoing writes have not yet finished (i.e. even if the + * promises returned from previous calls to {@link WritableStreamDefaultWriter.write | write()} have not yet settled). + * It’s not necessary to hold the lock on the writer for the duration of the write; the lock instead simply prevents + * other producers from writing in an interleaved manner. + */ + releaseLock() { + if (!IsWritableStreamDefaultWriter(this)) { + throw defaultWriterBrandCheckException('releaseLock'); + } + const stream = this._ownerWritableStream; + if (stream === undefined) { + return; + } + WritableStreamDefaultWriterRelease(this); + } + write(chunk = undefined) { + if (!IsWritableStreamDefaultWriter(this)) { + return promiseRejectedWith(defaultWriterBrandCheckException('write')); + } + if (this._ownerWritableStream === undefined) { + return promiseRejectedWith(defaultWriterLockException('write to')); + } + return WritableStreamDefaultWriterWrite(this, chunk); + } +} +Object.defineProperties(WritableStreamDefaultWriter.prototype, { + abort: { enumerable: true }, + close: { enumerable: true }, + releaseLock: { enumerable: true }, + write: { enumerable: true }, + closed: { enumerable: true }, + desiredSize: { enumerable: true }, + ready: { enumerable: true } +}); +if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(WritableStreamDefaultWriter.prototype, SymbolPolyfill.toStringTag, { + value: 'WritableStreamDefaultWriter', + configurable: true + }); +} +// Abstract operations for the WritableStreamDefaultWriter. +function IsWritableStreamDefaultWriter(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_ownerWritableStream')) { + return false; + } + return true; +} +// A client of WritableStreamDefaultWriter may use these functions directly to bypass state check. +function WritableStreamDefaultWriterAbort(writer, reason) { + const stream = writer._ownerWritableStream; + return WritableStreamAbort(stream, reason); +} +function WritableStreamDefaultWriterClose(writer) { + const stream = writer._ownerWritableStream; + return WritableStreamClose(stream); +} +function WritableStreamDefaultWriterCloseWithErrorPropagation(writer) { + const stream = writer._ownerWritableStream; + const state = stream._state; + if (WritableStreamCloseQueuedOrInFlight(stream) || state === 'closed') { + return promiseResolvedWith(undefined); + } + if (state === 'errored') { + return promiseRejectedWith(stream._storedError); + } + return WritableStreamDefaultWriterClose(writer); +} +function WritableStreamDefaultWriterEnsureClosedPromiseRejected(writer, error) { + if (writer._closedPromiseState === 'pending') { + defaultWriterClosedPromiseReject(writer, error); + } + else { + defaultWriterClosedPromiseResetToRejected(writer, error); + } +} +function WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, error) { + if (writer._readyPromiseState === 'pending') { + defaultWriterReadyPromiseReject(writer, error); + } + else { + defaultWriterReadyPromiseResetToRejected(writer, error); + } +} +function WritableStreamDefaultWriterGetDesiredSize(writer) { + const stream = writer._ownerWritableStream; + const state = stream._state; + if (state === 'errored' || state === 'erroring') { + return null; + } + if (state === 'closed') { + return 0; + } + return WritableStreamDefaultControllerGetDesiredSize(stream._writableStreamController); +} +function WritableStreamDefaultWriterRelease(writer) { + const stream = writer._ownerWritableStream; + const releasedError = new TypeError(`Writer was released and can no longer be used to monitor the stream's closedness`); + WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, releasedError); + // The state transitions to "errored" before the sink abort() method runs, but the writer.closed promise is not + // rejected until afterwards. This means that simply testing state will not work. + WritableStreamDefaultWriterEnsureClosedPromiseRejected(writer, releasedError); + stream._writer = undefined; + writer._ownerWritableStream = undefined; +} +function WritableStreamDefaultWriterWrite(writer, chunk) { + const stream = writer._ownerWritableStream; + const controller = stream._writableStreamController; + const chunkSize = WritableStreamDefaultControllerGetChunkSize(controller, chunk); + if (stream !== writer._ownerWritableStream) { + return promiseRejectedWith(defaultWriterLockException('write to')); + } + const state = stream._state; + if (state === 'errored') { + return promiseRejectedWith(stream._storedError); + } + if (WritableStreamCloseQueuedOrInFlight(stream) || state === 'closed') { + return promiseRejectedWith(new TypeError('The stream is closing or closed and cannot be written to')); + } + if (state === 'erroring') { + return promiseRejectedWith(stream._storedError); + } + const promise = WritableStreamAddWriteRequest(stream); + WritableStreamDefaultControllerWrite(controller, chunk, chunkSize); + return promise; +} +const closeSentinel = {}; /** - * Export high level api as default. - * Usage: + * Allows control of a {@link WritableStream | writable stream}'s state and internal queue. * - * import openpgp from 'openpgp.js' - * openpgp.encryptMessage(keys, text) - */ - - -/** - * @see module:key - * @name module:openpgp.key - */ - -const key = exports.key = keyMod; - -/** - * @see module:signature - * @name module:openpgp.signature + * @public */ -const signature = exports.signature = signatureMod; - -/** - * @see module:message - * @name module:openpgp.message - */ -const message = exports.message = messageMod; - -/** - * @see module:cleartext - * @name module:openpgp.cleartext - */ -const cleartext = exports.cleartext = cleartextMod; - -/** - * @see module:util - * @name module:openpgp.util - */ - -},{"./cleartext":77,"./config/config":78,"./crypto":94,"./encoding/armor":111,"./enums":113,"./hkp":114,"./key":116,"./keyring":117,"./message":120,"./openpgp":121,"./packet":125,"./signature":145,"./type/ecdh_symkey":146,"./type/kdf_params":147,"./type/keyid":148,"./type/mpi":149,"./type/oid":150,"./type/s2k":151,"./util":152,"./wkd":153,"./worker/async_proxy":154,"web-stream-tools":75}],116:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true +class WritableStreamDefaultController { + constructor() { + throw new TypeError('Illegal constructor'); + } + /** + * Closes the controlled writable stream, making all future interactions with it fail with the given error `e`. + * + * This method is rarely used, since usually it suffices to return a rejected promise from one of the underlying + * sink's methods. However, it can be useful for suddenly shutting down a stream in response to an event outside the + * normal lifecycle of interactions with the underlying sink. + */ + error(e = undefined) { + if (!IsWritableStreamDefaultController(this)) { + throw new TypeError('WritableStreamDefaultController.prototype.error can only be used on a WritableStreamDefaultController'); + } + const state = this._controlledWritableStream._state; + if (state !== 'writable') { + // The stream is closed, errored or will be soon. The sink can't do anything useful if it gets an error here, so + // just treat it as a no-op. + return; + } + WritableStreamDefaultControllerError(this, e); + } + /** @internal */ + [AbortSteps](reason) { + const result = this._abortAlgorithm(reason); + WritableStreamDefaultControllerClearAlgorithms(this); + return result; + } + /** @internal */ + [ErrorSteps]() { + ResetQueue(this); + } +} +Object.defineProperties(WritableStreamDefaultController.prototype, { + error: { enumerable: true } }); +if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(WritableStreamDefaultController.prototype, SymbolPolyfill.toStringTag, { + value: 'WritableStreamDefaultController', + configurable: true + }); +} +// Abstract operations implementing interface required by the WritableStream. +function IsWritableStreamDefaultController(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_controlledWritableStream')) { + return false; + } + return true; +} +function SetUpWritableStreamDefaultController(stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark, sizeAlgorithm) { + controller._controlledWritableStream = stream; + stream._writableStreamController = controller; + // Need to set the slots so that the assert doesn't fire. In the spec the slots already exist implicitly. + controller._queue = undefined; + controller._queueTotalSize = undefined; + ResetQueue(controller); + controller._started = false; + controller._strategySizeAlgorithm = sizeAlgorithm; + controller._strategyHWM = highWaterMark; + controller._writeAlgorithm = writeAlgorithm; + controller._closeAlgorithm = closeAlgorithm; + controller._abortAlgorithm = abortAlgorithm; + const backpressure = WritableStreamDefaultControllerGetBackpressure(controller); + WritableStreamUpdateBackpressure(stream, backpressure); + const startResult = startAlgorithm(); + const startPromise = promiseResolvedWith(startResult); + uponPromise(startPromise, () => { + controller._started = true; + WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); + }, r => { + controller._started = true; + WritableStreamDealWithRejection(stream, r); + }); +} +function SetUpWritableStreamDefaultControllerFromUnderlyingSink(stream, underlyingSink, highWaterMark, sizeAlgorithm) { + const controller = Object.create(WritableStreamDefaultController.prototype); + let startAlgorithm = () => undefined; + let writeAlgorithm = () => promiseResolvedWith(undefined); + let closeAlgorithm = () => promiseResolvedWith(undefined); + let abortAlgorithm = () => promiseResolvedWith(undefined); + if (underlyingSink.start !== undefined) { + startAlgorithm = () => underlyingSink.start(controller); + } + if (underlyingSink.write !== undefined) { + writeAlgorithm = chunk => underlyingSink.write(chunk, controller); + } + if (underlyingSink.close !== undefined) { + closeAlgorithm = () => underlyingSink.close(); + } + if (underlyingSink.abort !== undefined) { + abortAlgorithm = reason => underlyingSink.abort(reason); + } + SetUpWritableStreamDefaultController(stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark, sizeAlgorithm); +} +// ClearAlgorithms may be called twice. Erroring the same stream in multiple ways will often result in redundant calls. +function WritableStreamDefaultControllerClearAlgorithms(controller) { + controller._writeAlgorithm = undefined; + controller._closeAlgorithm = undefined; + controller._abortAlgorithm = undefined; + controller._strategySizeAlgorithm = undefined; +} +function WritableStreamDefaultControllerClose(controller) { + EnqueueValueWithSize(controller, closeSentinel, 0); + WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); +} +function WritableStreamDefaultControllerGetChunkSize(controller, chunk) { + try { + return controller._strategySizeAlgorithm(chunk); + } + catch (chunkSizeE) { + WritableStreamDefaultControllerErrorIfNeeded(controller, chunkSizeE); + return 1; + } +} +function WritableStreamDefaultControllerGetDesiredSize(controller) { + return controller._strategyHWM - controller._queueTotalSize; +} +function WritableStreamDefaultControllerWrite(controller, chunk, chunkSize) { + try { + EnqueueValueWithSize(controller, chunk, chunkSize); + } + catch (enqueueE) { + WritableStreamDefaultControllerErrorIfNeeded(controller, enqueueE); + return; + } + const stream = controller._controlledWritableStream; + if (!WritableStreamCloseQueuedOrInFlight(stream) && stream._state === 'writable') { + const backpressure = WritableStreamDefaultControllerGetBackpressure(controller); + WritableStreamUpdateBackpressure(stream, backpressure); + } + WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); +} +// Abstract operations for the WritableStreamDefaultController. +function WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller) { + const stream = controller._controlledWritableStream; + if (!controller._started) { + return; + } + if (stream._inFlightWriteRequest !== undefined) { + return; + } + const state = stream._state; + if (state === 'erroring') { + WritableStreamFinishErroring(stream); + return; + } + if (controller._queue.length === 0) { + return; + } + const value = PeekQueueValue(controller); + if (value === closeSentinel) { + WritableStreamDefaultControllerProcessClose(controller); + } + else { + WritableStreamDefaultControllerProcessWrite(controller, value); + } +} +function WritableStreamDefaultControllerErrorIfNeeded(controller, error) { + if (controller._controlledWritableStream._state === 'writable') { + WritableStreamDefaultControllerError(controller, error); + } +} +function WritableStreamDefaultControllerProcessClose(controller) { + const stream = controller._controlledWritableStream; + WritableStreamMarkCloseRequestInFlight(stream); + DequeueValue(controller); + const sinkClosePromise = controller._closeAlgorithm(); + WritableStreamDefaultControllerClearAlgorithms(controller); + uponPromise(sinkClosePromise, () => { + WritableStreamFinishInFlightClose(stream); + }, reason => { + WritableStreamFinishInFlightCloseWithError(stream, reason); + }); +} +function WritableStreamDefaultControllerProcessWrite(controller, chunk) { + const stream = controller._controlledWritableStream; + WritableStreamMarkFirstWriteRequestInFlight(stream); + const sinkWritePromise = controller._writeAlgorithm(chunk); + uponPromise(sinkWritePromise, () => { + WritableStreamFinishInFlightWrite(stream); + const state = stream._state; + DequeueValue(controller); + if (!WritableStreamCloseQueuedOrInFlight(stream) && state === 'writable') { + const backpressure = WritableStreamDefaultControllerGetBackpressure(controller); + WritableStreamUpdateBackpressure(stream, backpressure); + } + WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); + }, reason => { + if (stream._state === 'writable') { + WritableStreamDefaultControllerClearAlgorithms(controller); + } + WritableStreamFinishInFlightWriteWithError(stream, reason); + }); +} +function WritableStreamDefaultControllerGetBackpressure(controller) { + const desiredSize = WritableStreamDefaultControllerGetDesiredSize(controller); + return desiredSize <= 0; +} +// A client of WritableStreamDefaultController may use these functions directly to bypass state check. +function WritableStreamDefaultControllerError(controller, error) { + const stream = controller._controlledWritableStream; + WritableStreamDefaultControllerClearAlgorithms(controller); + WritableStreamStartErroring(stream, error); +} +// Helper functions for the WritableStream. +function streamBrandCheckException$2(name) { + return new TypeError(`WritableStream.prototype.${name} can only be used on a WritableStream`); +} +// Helper functions for the WritableStreamDefaultWriter. +function defaultWriterBrandCheckException(name) { + return new TypeError(`WritableStreamDefaultWriter.prototype.${name} can only be used on a WritableStreamDefaultWriter`); +} +function defaultWriterLockException(name) { + return new TypeError('Cannot ' + name + ' a stream using a released writer'); +} +function defaultWriterClosedPromiseInitialize(writer) { + writer._closedPromise = newPromise((resolve, reject) => { + writer._closedPromise_resolve = resolve; + writer._closedPromise_reject = reject; + writer._closedPromiseState = 'pending'; + }); +} +function defaultWriterClosedPromiseInitializeAsRejected(writer, reason) { + defaultWriterClosedPromiseInitialize(writer); + defaultWriterClosedPromiseReject(writer, reason); +} +function defaultWriterClosedPromiseInitializeAsResolved(writer) { + defaultWriterClosedPromiseInitialize(writer); + defaultWriterClosedPromiseResolve(writer); +} +function defaultWriterClosedPromiseReject(writer, reason) { + if (writer._closedPromise_reject === undefined) { + return; + } + setPromiseIsHandledToTrue(writer._closedPromise); + writer._closedPromise_reject(reason); + writer._closedPromise_resolve = undefined; + writer._closedPromise_reject = undefined; + writer._closedPromiseState = 'rejected'; +} +function defaultWriterClosedPromiseResetToRejected(writer, reason) { + defaultWriterClosedPromiseInitializeAsRejected(writer, reason); +} +function defaultWriterClosedPromiseResolve(writer) { + if (writer._closedPromise_resolve === undefined) { + return; + } + writer._closedPromise_resolve(undefined); + writer._closedPromise_resolve = undefined; + writer._closedPromise_reject = undefined; + writer._closedPromiseState = 'resolved'; +} +function defaultWriterReadyPromiseInitialize(writer) { + writer._readyPromise = newPromise((resolve, reject) => { + writer._readyPromise_resolve = resolve; + writer._readyPromise_reject = reject; + }); + writer._readyPromiseState = 'pending'; +} +function defaultWriterReadyPromiseInitializeAsRejected(writer, reason) { + defaultWriterReadyPromiseInitialize(writer); + defaultWriterReadyPromiseReject(writer, reason); +} +function defaultWriterReadyPromiseInitializeAsResolved(writer) { + defaultWriterReadyPromiseInitialize(writer); + defaultWriterReadyPromiseResolve(writer); +} +function defaultWriterReadyPromiseReject(writer, reason) { + if (writer._readyPromise_reject === undefined) { + return; + } + setPromiseIsHandledToTrue(writer._readyPromise); + writer._readyPromise_reject(reason); + writer._readyPromise_resolve = undefined; + writer._readyPromise_reject = undefined; + writer._readyPromiseState = 'rejected'; +} +function defaultWriterReadyPromiseReset(writer) { + defaultWriterReadyPromiseInitialize(writer); +} +function defaultWriterReadyPromiseResetToRejected(writer, reason) { + defaultWriterReadyPromiseInitializeAsRejected(writer, reason); +} +function defaultWriterReadyPromiseResolve(writer) { + if (writer._readyPromise_resolve === undefined) { + return; + } + writer._readyPromise_resolve(undefined); + writer._readyPromise_resolve = undefined; + writer._readyPromise_reject = undefined; + writer._readyPromiseState = 'fulfilled'; +} -var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); // GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @requires encoding/armor - * @requires crypto - * @requires packet - * @requires config - * @requires enums - * @requires util - * @module key - */ - -exports.Key = Key; -exports.createSignaturePacket = createSignaturePacket; -exports.read = read; -exports.readArmored = readArmored; -exports.generate = generate; -exports.reformat = reformat; -exports.getPreferredHashAlgo = getPreferredHashAlgo; -exports.getPreferredAlgo = getPreferredAlgo; -exports.isAeadSupported = isAeadSupported; - -var _armor = require('./encoding/armor'); - -var _armor2 = _interopRequireDefault(_armor); - -var _crypto = require('./crypto'); - -var _crypto2 = _interopRequireDefault(_crypto); - -var _packet = require('./packet'); - -var _packet2 = _interopRequireDefault(_packet); - -var _config = require('./config'); - -var _config2 = _interopRequireDefault(_config); - -var _enums = require('./enums'); - -var _enums2 = _interopRequireDefault(_enums); - -var _util = require('./util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +function isAbortSignal(value) { + if (typeof value !== 'object' || value === null) { + return false; + } + try { + return typeof value.aborted === 'boolean'; + } + catch (_a) { + // AbortSignal.prototype.aborted throws if its brand check fails + return false; + } +} -/** - * @class - * @classdesc Class that represents an OpenPGP key. Must contain a primary key. - * Can contain additional subkeys, signatures, user ids, user attributes. - * @param {module:packet.List} packetlist The packets that form this key - * @borrows module:packet.PublicKey#getKeyId as Key#getKeyId - * @borrows module:packet.PublicKey#getFingerprint as Key#getFingerprint - * @borrows module:packet.PublicKey#hasSameFingerprintAs as Key#hasSameFingerprintAs - * @borrows module:packet.PublicKey#getAlgorithmInfo as Key#getAlgorithmInfo - * @borrows module:packet.PublicKey#getCreationTime as Key#getCreationTime - * @borrows module:packet.PublicKey#isDecrypted as Key#isDecrypted - */ -function Key(packetlist) { - if (!(this instanceof Key)) { - return new Key(packetlist); - } - // same data as in packetlist but in structured form - this.keyPacket = null; - this.revocationSignatures = []; - this.directSignatures = []; - this.users = []; - this.subKeys = []; - this.packetlist2structure(packetlist); - if (!this.keyPacket || !this.users.length) { - throw new Error('Invalid key: need at least key and user ID packet'); - } -} - -Object.defineProperty(Key.prototype, 'primaryKey', { - get() { - return this.keyPacket; - }, - configurable: true, - enumerable: true -}); +/// +const NativeDOMException = typeof DOMException !== 'undefined' ? DOMException : undefined; -/** - * Transforms packetlist to structured key data - * @param {module:packet.List} packetlist The packets that form a key - */ -Key.prototype.packetlist2structure = function (packetlist) { - let user; - let primaryKeyId; - let subKey; - for (let i = 0; i < packetlist.length; i++) { - switch (packetlist[i].tag) { - case _enums2.default.packet.publicKey: - case _enums2.default.packet.secretKey: - this.keyPacket = packetlist[i]; - primaryKeyId = this.getKeyId(); - break; - case _enums2.default.packet.userid: - case _enums2.default.packet.userAttribute: - user = new User(packetlist[i]); - this.users.push(user); - break; - case _enums2.default.packet.publicSubkey: - case _enums2.default.packet.secretSubkey: - user = null; - subKey = new SubKey(packetlist[i]); - this.subKeys.push(subKey); - break; - case _enums2.default.packet.signature: - switch (packetlist[i].signatureType) { - case _enums2.default.signature.cert_generic: - case _enums2.default.signature.cert_persona: - case _enums2.default.signature.cert_casual: - case _enums2.default.signature.cert_positive: - if (!user) { - _util2.default.print_debug('Dropping certification signatures without preceding user packet'); - continue; +/// +function isDOMExceptionConstructor(ctor) { + if (!(typeof ctor === 'function' || typeof ctor === 'object')) { + return false; + } + try { + new ctor(); + return true; + } + catch (_a) { + return false; + } +} +function createDOMExceptionPolyfill() { + // eslint-disable-next-line no-shadow + const ctor = function DOMException(message, name) { + this.message = message || ''; + this.name = name || 'Error'; + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + }; + ctor.prototype = Object.create(Error.prototype); + Object.defineProperty(ctor.prototype, 'constructor', { value: ctor, writable: true, configurable: true }); + return ctor; +} +// eslint-disable-next-line no-redeclare +const DOMException$1 = isDOMExceptionConstructor(NativeDOMException) ? NativeDOMException : createDOMExceptionPolyfill(); + +function ReadableStreamPipeTo(source, dest, preventClose, preventAbort, preventCancel, signal) { + const reader = AcquireReadableStreamDefaultReader(source); + const writer = AcquireWritableStreamDefaultWriter(dest); + source._disturbed = true; + let shuttingDown = false; + // This is used to keep track of the spec's requirement that we wait for ongoing writes during shutdown. + let currentWrite = promiseResolvedWith(undefined); + return newPromise((resolve, reject) => { + let abortAlgorithm; + if (signal !== undefined) { + abortAlgorithm = () => { + const error = new DOMException$1('Aborted', 'AbortError'); + const actions = []; + if (!preventAbort) { + actions.push(() => { + if (dest._state === 'writable') { + return WritableStreamAbort(dest, error); + } + return promiseResolvedWith(undefined); + }); + } + if (!preventCancel) { + actions.push(() => { + if (source._state === 'readable') { + return ReadableStreamCancel(source, error); + } + return promiseResolvedWith(undefined); + }); + } + shutdownWithAction(() => Promise.all(actions.map(action => action())), true, error); + }; + if (signal.aborted) { + abortAlgorithm(); + return; } - if (packetlist[i].issuerKeyId.equals(primaryKeyId)) { - checkRevocationKey(packetlist[i], primaryKeyId); - user.selfCertifications.push(packetlist[i]); - } else { - user.otherCertifications.push(packetlist[i]); + signal.addEventListener('abort', abortAlgorithm); + } + // Using reader and writer, read all chunks from this and write them to dest + // - Backpressure must be enforced + // - Shutdown must stop all activity + function pipeLoop() { + return newPromise((resolveLoop, rejectLoop) => { + function next(done) { + if (done) { + resolveLoop(); + } + else { + // Use `PerformPromiseThen` instead of `uponPromise` to avoid + // adding unnecessary `.catch(rethrowAssertionErrorRejection)` handlers + PerformPromiseThen(pipeStep(), next, rejectLoop); + } + } + next(false); + }); + } + function pipeStep() { + if (shuttingDown) { + return promiseResolvedWith(true); } - break; - case _enums2.default.signature.cert_revocation: - if (user) { - user.revocationSignatures.push(packetlist[i]); - } else { - this.directSignatures.push(packetlist[i]); + return PerformPromiseThen(writer._readyPromise, () => { + return newPromise((resolveRead, rejectRead) => { + ReadableStreamDefaultReaderRead(reader, { + _chunkSteps: chunk => { + currentWrite = PerformPromiseThen(WritableStreamDefaultWriterWrite(writer, chunk), undefined, noop); + resolveRead(false); + }, + _closeSteps: () => resolveRead(true), + _errorSteps: rejectRead + }); + }); + }); + } + // Errors must be propagated forward + isOrBecomesErrored(source, reader._closedPromise, storedError => { + if (!preventAbort) { + shutdownWithAction(() => WritableStreamAbort(dest, storedError), true, storedError); } - break; - case _enums2.default.signature.key: - checkRevocationKey(packetlist[i], primaryKeyId); - this.directSignatures.push(packetlist[i]); - break; - case _enums2.default.signature.subkey_binding: - if (!subKey) { - _util2.default.print_debug('Dropping subkey binding signature without preceding subkey packet'); - continue; + else { + shutdown(true, storedError); } - checkRevocationKey(packetlist[i], primaryKeyId); - subKey.bindingSignatures.push(packetlist[i]); - break; - case _enums2.default.signature.key_revocation: - this.revocationSignatures.push(packetlist[i]); - break; - case _enums2.default.signature.subkey_revocation: - if (!subKey) { - _util2.default.print_debug('Dropping subkey revocation signature without preceding subkey packet'); - continue; + }); + // Errors must be propagated backward + isOrBecomesErrored(dest, writer._closedPromise, storedError => { + if (!preventCancel) { + shutdownWithAction(() => ReadableStreamCancel(source, storedError), true, storedError); + } + else { + shutdown(true, storedError); + } + }); + // Closing must be propagated forward + isOrBecomesClosed(source, reader._closedPromise, () => { + if (!preventClose) { + shutdownWithAction(() => WritableStreamDefaultWriterCloseWithErrorPropagation(writer)); + } + else { + shutdown(); + } + }); + // Closing must be propagated backward + if (WritableStreamCloseQueuedOrInFlight(dest) || dest._state === 'closed') { + const destClosed = new TypeError('the destination writable stream closed before all data could be piped to it'); + if (!preventCancel) { + shutdownWithAction(() => ReadableStreamCancel(source, destClosed), true, destClosed); + } + else { + shutdown(true, destClosed); } - subKey.revocationSignatures.push(packetlist[i]); - break; } - break; - } - } -}; - -/** - * Transforms structured key data to packetlist - * @returns {module:packet.List} The packets that form a key - */ -Key.prototype.toPacketlist = function () { - const packetlist = new _packet2.default.List(); - packetlist.push(this.keyPacket); - packetlist.concat(this.revocationSignatures); - packetlist.concat(this.directSignatures); - this.users.map(user => packetlist.concat(user.toPacketlist())); - this.subKeys.map(subKey => packetlist.concat(subKey.toPacketlist())); - return packetlist; -}; + setPromiseIsHandledToTrue(pipeLoop()); + function waitForWritesToFinish() { + // Another write may have started while we were waiting on this currentWrite, so we have to be sure to wait + // for that too. + const oldCurrentWrite = currentWrite; + return PerformPromiseThen(currentWrite, () => oldCurrentWrite !== currentWrite ? waitForWritesToFinish() : undefined); + } + function isOrBecomesErrored(stream, promise, action) { + if (stream._state === 'errored') { + action(stream._storedError); + } + else { + uponRejection(promise, action); + } + } + function isOrBecomesClosed(stream, promise, action) { + if (stream._state === 'closed') { + action(); + } + else { + uponFulfillment(promise, action); + } + } + function shutdownWithAction(action, originalIsError, originalError) { + if (shuttingDown) { + return; + } + shuttingDown = true; + if (dest._state === 'writable' && !WritableStreamCloseQueuedOrInFlight(dest)) { + uponFulfillment(waitForWritesToFinish(), doTheRest); + } + else { + doTheRest(); + } + function doTheRest() { + uponPromise(action(), () => finalize(originalIsError, originalError), newError => finalize(true, newError)); + } + } + function shutdown(isError, error) { + if (shuttingDown) { + return; + } + shuttingDown = true; + if (dest._state === 'writable' && !WritableStreamCloseQueuedOrInFlight(dest)) { + uponFulfillment(waitForWritesToFinish(), () => finalize(isError, error)); + } + else { + finalize(isError, error); + } + } + function finalize(isError, error) { + WritableStreamDefaultWriterRelease(writer); + ReadableStreamReaderGenericRelease(reader); + if (signal !== undefined) { + signal.removeEventListener('abort', abortAlgorithm); + } + if (isError) { + reject(error); + } + else { + resolve(undefined); + } + } + }); +} /** - * Returns an array containing all public or private subkeys matching keyId; - * If keyId is not present, returns all subkeys. - * @param {type/keyid} keyId - * @returns {Array} + * Allows control of a {@link ReadableStream | readable stream}'s state and internal queue. + * + * @public */ -Key.prototype.getSubkeys = function (keyId = null) { - const subKeys = []; - this.subKeys.forEach(subKey => { - if (!keyId || subKey.getKeyId().equals(keyId, true)) { - subKeys.push(subKey); +class ReadableStreamDefaultController { + constructor() { + throw new TypeError('Illegal constructor'); } - }); - return subKeys; -}; - -/** - * Returns an array containing all public or private keys matching keyId. - * If keyId is not present, returns all keys starting with the primary key. - * @param {type/keyid} keyId - * @returns {Array} - */ -Key.prototype.getKeys = function (keyId = null) { - const keys = []; - if (!keyId || this.getKeyId().equals(keyId, true)) { - keys.push(this); - } - return keys.concat(this.getSubkeys(keyId)); -}; - -/** - * Returns key IDs of all keys - * @returns {Array} - */ -Key.prototype.getKeyIds = function () { - return this.getKeys().map(key => key.getKeyId()); -}; - -/** - * Returns userids - * @returns {Array} array of userids - */ -Key.prototype.getUserIds = function () { - return this.users.map(user => { - return user.userId ? user.userId.userid : null; - }).filter(userid => userid !== null); -}; - -/** - * Returns true if this is a public key - * @returns {Boolean} - */ -Key.prototype.isPublic = function () { - return this.keyPacket.tag === _enums2.default.packet.publicKey; -}; - -/** - * Returns true if this is a private key - * @returns {Boolean} - */ -Key.prototype.isPrivate = function () { - return this.keyPacket.tag === _enums2.default.packet.secretKey; -}; - -/** - * Returns key as public key (shallow copy) - * @returns {module:key.Key} new public Key - */ -Key.prototype.toPublic = function () { - const packetlist = new _packet2.default.List(); - const keyPackets = this.toPacketlist(); - let bytes; - let pubKeyPacket; - let pubSubkeyPacket; - for (let i = 0; i < keyPackets.length; i++) { - switch (keyPackets[i].tag) { - case _enums2.default.packet.secretKey: - bytes = keyPackets[i].writePublicKey(); - pubKeyPacket = new _packet2.default.PublicKey(); - pubKeyPacket.read(bytes); - packetlist.push(pubKeyPacket); - break; - case _enums2.default.packet.secretSubkey: - bytes = keyPackets[i].writePublicKey(); - pubSubkeyPacket = new _packet2.default.PublicSubkey(); - pubSubkeyPacket.read(bytes); - packetlist.push(pubSubkeyPacket); - break; - default: - packetlist.push(keyPackets[i]); + /** + * Returns the desired size to fill the controlled stream's internal queue. It can be negative, if the queue is + * over-full. An underlying source ought to use this information to determine when and how to apply backpressure. + */ + get desiredSize() { + if (!IsReadableStreamDefaultController(this)) { + throw defaultControllerBrandCheckException$1('desiredSize'); + } + return ReadableStreamDefaultControllerGetDesiredSize(this); } - } - return new Key(packetlist); -}; + /** + * Closes the controlled readable stream. Consumers will still be able to read any previously-enqueued chunks from + * the stream, but once those are read, the stream will become closed. + */ + close() { + if (!IsReadableStreamDefaultController(this)) { + throw defaultControllerBrandCheckException$1('close'); + } + if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(this)) { + throw new TypeError('The stream is not in a state that permits close'); + } + ReadableStreamDefaultControllerClose(this); + } + enqueue(chunk = undefined) { + if (!IsReadableStreamDefaultController(this)) { + throw defaultControllerBrandCheckException$1('enqueue'); + } + if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(this)) { + throw new TypeError('The stream is not in a state that permits enqueue'); + } + return ReadableStreamDefaultControllerEnqueue(this, chunk); + } + /** + * Errors the controlled readable stream, making all future interactions with it fail with the given error `e`. + */ + error(e = undefined) { + if (!IsReadableStreamDefaultController(this)) { + throw defaultControllerBrandCheckException$1('error'); + } + ReadableStreamDefaultControllerError(this, e); + } + /** @internal */ + [CancelSteps](reason) { + ResetQueue(this); + const result = this._cancelAlgorithm(reason); + ReadableStreamDefaultControllerClearAlgorithms(this); + return result; + } + /** @internal */ + [PullSteps](readRequest) { + const stream = this._controlledReadableStream; + if (this._queue.length > 0) { + const chunk = DequeueValue(this); + if (this._closeRequested && this._queue.length === 0) { + ReadableStreamDefaultControllerClearAlgorithms(this); + ReadableStreamClose(stream); + } + else { + ReadableStreamDefaultControllerCallPullIfNeeded(this); + } + readRequest._chunkSteps(chunk); + } + else { + ReadableStreamAddReadRequest(stream, readRequest); + ReadableStreamDefaultControllerCallPullIfNeeded(this); + } + } +} +Object.defineProperties(ReadableStreamDefaultController.prototype, { + close: { enumerable: true }, + enqueue: { enumerable: true }, + error: { enumerable: true }, + desiredSize: { enumerable: true } +}); +if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(ReadableStreamDefaultController.prototype, SymbolPolyfill.toStringTag, { + value: 'ReadableStreamDefaultController', + configurable: true + }); +} +// Abstract operations for the ReadableStreamDefaultController. +function IsReadableStreamDefaultController(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_controlledReadableStream')) { + return false; + } + return true; +} +function ReadableStreamDefaultControllerCallPullIfNeeded(controller) { + const shouldPull = ReadableStreamDefaultControllerShouldCallPull(controller); + if (!shouldPull) { + return; + } + if (controller._pulling) { + controller._pullAgain = true; + return; + } + controller._pulling = true; + const pullPromise = controller._pullAlgorithm(); + uponPromise(pullPromise, () => { + controller._pulling = false; + if (controller._pullAgain) { + controller._pullAgain = false; + ReadableStreamDefaultControllerCallPullIfNeeded(controller); + } + }, e => { + ReadableStreamDefaultControllerError(controller, e); + }); +} +function ReadableStreamDefaultControllerShouldCallPull(controller) { + const stream = controller._controlledReadableStream; + if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(controller)) { + return false; + } + if (!controller._started) { + return false; + } + if (IsReadableStreamLocked(stream) && ReadableStreamGetNumReadRequests(stream) > 0) { + return true; + } + const desiredSize = ReadableStreamDefaultControllerGetDesiredSize(controller); + if (desiredSize > 0) { + return true; + } + return false; +} +function ReadableStreamDefaultControllerClearAlgorithms(controller) { + controller._pullAlgorithm = undefined; + controller._cancelAlgorithm = undefined; + controller._strategySizeAlgorithm = undefined; +} +// A client of ReadableStreamDefaultController may use these functions directly to bypass state check. +function ReadableStreamDefaultControllerClose(controller) { + if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(controller)) { + return; + } + const stream = controller._controlledReadableStream; + controller._closeRequested = true; + if (controller._queue.length === 0) { + ReadableStreamDefaultControllerClearAlgorithms(controller); + ReadableStreamClose(stream); + } +} +function ReadableStreamDefaultControllerEnqueue(controller, chunk) { + if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(controller)) { + return; + } + const stream = controller._controlledReadableStream; + if (IsReadableStreamLocked(stream) && ReadableStreamGetNumReadRequests(stream) > 0) { + ReadableStreamFulfillReadRequest(stream, chunk, false); + } + else { + let chunkSize; + try { + chunkSize = controller._strategySizeAlgorithm(chunk); + } + catch (chunkSizeE) { + ReadableStreamDefaultControllerError(controller, chunkSizeE); + throw chunkSizeE; + } + try { + EnqueueValueWithSize(controller, chunk, chunkSize); + } + catch (enqueueE) { + ReadableStreamDefaultControllerError(controller, enqueueE); + throw enqueueE; + } + } + ReadableStreamDefaultControllerCallPullIfNeeded(controller); +} +function ReadableStreamDefaultControllerError(controller, e) { + const stream = controller._controlledReadableStream; + if (stream._state !== 'readable') { + return; + } + ResetQueue(controller); + ReadableStreamDefaultControllerClearAlgorithms(controller); + ReadableStreamError(stream, e); +} +function ReadableStreamDefaultControllerGetDesiredSize(controller) { + const state = controller._controlledReadableStream._state; + if (state === 'errored') { + return null; + } + if (state === 'closed') { + return 0; + } + return controller._strategyHWM - controller._queueTotalSize; +} +// This is used in the implementation of TransformStream. +function ReadableStreamDefaultControllerHasBackpressure(controller) { + if (ReadableStreamDefaultControllerShouldCallPull(controller)) { + return false; + } + return true; +} +function ReadableStreamDefaultControllerCanCloseOrEnqueue(controller) { + const state = controller._controlledReadableStream._state; + if (!controller._closeRequested && state === 'readable') { + return true; + } + return false; +} +function SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm) { + controller._controlledReadableStream = stream; + controller._queue = undefined; + controller._queueTotalSize = undefined; + ResetQueue(controller); + controller._started = false; + controller._closeRequested = false; + controller._pullAgain = false; + controller._pulling = false; + controller._strategySizeAlgorithm = sizeAlgorithm; + controller._strategyHWM = highWaterMark; + controller._pullAlgorithm = pullAlgorithm; + controller._cancelAlgorithm = cancelAlgorithm; + stream._readableStreamController = controller; + const startResult = startAlgorithm(); + uponPromise(promiseResolvedWith(startResult), () => { + controller._started = true; + ReadableStreamDefaultControllerCallPullIfNeeded(controller); + }, r => { + ReadableStreamDefaultControllerError(controller, r); + }); +} +function SetUpReadableStreamDefaultControllerFromUnderlyingSource(stream, underlyingSource, highWaterMark, sizeAlgorithm) { + const controller = Object.create(ReadableStreamDefaultController.prototype); + let startAlgorithm = () => undefined; + let pullAlgorithm = () => promiseResolvedWith(undefined); + let cancelAlgorithm = () => promiseResolvedWith(undefined); + if (underlyingSource.start !== undefined) { + startAlgorithm = () => underlyingSource.start(controller); + } + if (underlyingSource.pull !== undefined) { + pullAlgorithm = () => underlyingSource.pull(controller); + } + if (underlyingSource.cancel !== undefined) { + cancelAlgorithm = reason => underlyingSource.cancel(reason); + } + SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm); +} +// Helper functions for the ReadableStreamDefaultController. +function defaultControllerBrandCheckException$1(name) { + return new TypeError(`ReadableStreamDefaultController.prototype.${name} can only be used on a ReadableStreamDefaultController`); +} + +function ReadableStreamTee(stream, cloneForBranch2) { + const reader = AcquireReadableStreamDefaultReader(stream); + let reading = false; + let canceled1 = false; + let canceled2 = false; + let reason1; + let reason2; + let branch1; + let branch2; + let resolveCancelPromise; + const cancelPromise = newPromise(resolve => { + resolveCancelPromise = resolve; + }); + function pullAlgorithm() { + if (reading) { + return promiseResolvedWith(undefined); + } + reading = true; + const readRequest = { + _chunkSteps: value => { + // This needs to be delayed a microtask because it takes at least a microtask to detect errors (using + // reader._closedPromise below), and we want errors in stream to error both branches immediately. We cannot let + // successful synchronously-available reads get ahead of asynchronously-available errors. + queueMicrotask(() => { + reading = false; + const value1 = value; + const value2 = value; + // There is no way to access the cloning code right now in the reference implementation. + // If we add one then we'll need an implementation for serializable objects. + // if (!canceled2 && cloneForBranch2) { + // value2 = StructuredDeserialize(StructuredSerialize(value2)); + // } + if (!canceled1) { + ReadableStreamDefaultControllerEnqueue(branch1._readableStreamController, value1); + } + if (!canceled2) { + ReadableStreamDefaultControllerEnqueue(branch2._readableStreamController, value2); + } + }); + }, + _closeSteps: () => { + reading = false; + if (!canceled1) { + ReadableStreamDefaultControllerClose(branch1._readableStreamController); + } + if (!canceled2) { + ReadableStreamDefaultControllerClose(branch2._readableStreamController); + } + if (!canceled1 || !canceled2) { + resolveCancelPromise(undefined); + } + }, + _errorSteps: () => { + reading = false; + } + }; + ReadableStreamDefaultReaderRead(reader, readRequest); + return promiseResolvedWith(undefined); + } + function cancel1Algorithm(reason) { + canceled1 = true; + reason1 = reason; + if (canceled2) { + const compositeReason = CreateArrayFromList([reason1, reason2]); + const cancelResult = ReadableStreamCancel(stream, compositeReason); + resolveCancelPromise(cancelResult); + } + return cancelPromise; + } + function cancel2Algorithm(reason) { + canceled2 = true; + reason2 = reason; + if (canceled1) { + const compositeReason = CreateArrayFromList([reason1, reason2]); + const cancelResult = ReadableStreamCancel(stream, compositeReason); + resolveCancelPromise(cancelResult); + } + return cancelPromise; + } + function startAlgorithm() { + // do nothing + } + branch1 = CreateReadableStream(startAlgorithm, pullAlgorithm, cancel1Algorithm); + branch2 = CreateReadableStream(startAlgorithm, pullAlgorithm, cancel2Algorithm); + uponRejection(reader._closedPromise, (r) => { + ReadableStreamDefaultControllerError(branch1._readableStreamController, r); + ReadableStreamDefaultControllerError(branch2._readableStreamController, r); + if (!canceled1 || !canceled2) { + resolveCancelPromise(undefined); + } + }); + return [branch1, branch2]; +} -/** - * Returns ASCII armored text of key - * @returns {ReadableStream} ASCII armor - */ -Key.prototype.armor = function () { - const type = this.isPublic() ? _enums2.default.armor.public_key : _enums2.default.armor.private_key; - return _armor2.default.encode(type, this.toPacketlist().write()); -}; +function convertUnderlyingDefaultOrByteSource(source, context) { + assertDictionary(source, context); + const original = source; + const autoAllocateChunkSize = original === null || original === void 0 ? void 0 : original.autoAllocateChunkSize; + const cancel = original === null || original === void 0 ? void 0 : original.cancel; + const pull = original === null || original === void 0 ? void 0 : original.pull; + const start = original === null || original === void 0 ? void 0 : original.start; + const type = original === null || original === void 0 ? void 0 : original.type; + return { + autoAllocateChunkSize: autoAllocateChunkSize === undefined ? + undefined : + convertUnsignedLongLongWithEnforceRange(autoAllocateChunkSize, `${context} has member 'autoAllocateChunkSize' that`), + cancel: cancel === undefined ? + undefined : + convertUnderlyingSourceCancelCallback(cancel, original, `${context} has member 'cancel' that`), + pull: pull === undefined ? + undefined : + convertUnderlyingSourcePullCallback(pull, original, `${context} has member 'pull' that`), + start: start === undefined ? + undefined : + convertUnderlyingSourceStartCallback(start, original, `${context} has member 'start' that`), + type: type === undefined ? undefined : convertReadableStreamType(type, `${context} has member 'type' that`) + }; +} +function convertUnderlyingSourceCancelCallback(fn, original, context) { + assertFunction(fn, context); + return (reason) => promiseCall(fn, original, [reason]); +} +function convertUnderlyingSourcePullCallback(fn, original, context) { + assertFunction(fn, context); + return (controller) => promiseCall(fn, original, [controller]); +} +function convertUnderlyingSourceStartCallback(fn, original, context) { + assertFunction(fn, context); + return (controller) => reflectCall(fn, original, [controller]); +} +function convertReadableStreamType(type, context) { + type = `${type}`; + if (type !== 'bytes') { + throw new TypeError(`${context} '${type}' is not a valid enumeration value for ReadableStreamType`); + } + return type; +} -/** - * Returns the valid and non-expired signature that has the latest creation date, while ignoring signatures created in the future. - * @param {Array} signatures List of signatures - * @param {Date} date Use the given date instead of the current time - * @returns {Promise} The latest valid signature - * @async - */ -async function getLatestValidSignature(signatures, primaryKey, signatureType, dataToVerify, date = new Date()) { - let signature; - for (let i = signatures.length - 1; i >= 0; i--) { - if ((!signature || signatures[i].created >= signature.created) && - // check binding signature is not expired (ie, check for V4 expiration time) - !signatures[i].isExpired(date) && ( - // check binding signature is verified - signatures[i].verified || (await signatures[i].verify(primaryKey, signatureType, dataToVerify)))) { - signature = signatures[i]; +function convertReaderOptions(options, context) { + assertDictionary(options, context); + const mode = options === null || options === void 0 ? void 0 : options.mode; + return { + mode: mode === undefined ? undefined : convertReadableStreamReaderMode(mode, `${context} has member 'mode' that`) + }; +} +function convertReadableStreamReaderMode(mode, context) { + mode = `${mode}`; + if (mode !== 'byob') { + throw new TypeError(`${context} '${mode}' is not a valid enumeration value for ReadableStreamReaderMode`); } - } - return signature; + return mode; } -/** - * Returns last created key or key by given keyId that is available for signing and verification - * @param {module:type/keyid} keyId, optional - * @param {Date} date (optional) use the given date for verification instead of the current time - * @param {Object} userId, optional user ID - * @returns {Promise} key or null if no signing key has been found - * @async - */ -Key.prototype.getSigningKey = async function (keyId = null, date = new Date(), userId = {}) { - const primaryKey = this.keyPacket; - if ((await this.verifyPrimaryKey(date, userId)) === _enums2.default.keyStatus.valid) { - const subKeys = this.subKeys.slice().sort((a, b) => b.keyPacket.created - a.keyPacket.created); - for (let i = 0; i < subKeys.length; i++) { - if (!keyId || subKeys[i].getKeyId().equals(keyId)) { - if ((await subKeys[i].verify(primaryKey, date)) === _enums2.default.keyStatus.valid) { - const dataToVerify = { key: primaryKey, bind: subKeys[i].keyPacket }; - const bindingSignature = await getLatestValidSignature(subKeys[i].bindingSignatures, primaryKey, _enums2.default.signature.subkey_binding, dataToVerify, date); - if (bindingSignature && bindingSignature.embeddedSignature && isValidSigningKeyPacket(subKeys[i].keyPacket, bindingSignature) && (await getLatestValidSignature([bindingSignature.embeddedSignature], subKeys[i].keyPacket, _enums2.default.signature.key_binding, dataToVerify, date))) { - return subKeys[i]; - } - } - } +function convertIteratorOptions(options, context) { + assertDictionary(options, context); + const preventCancel = options === null || options === void 0 ? void 0 : options.preventCancel; + return { preventCancel: Boolean(preventCancel) }; +} + +function convertPipeOptions(options, context) { + assertDictionary(options, context); + const preventAbort = options === null || options === void 0 ? void 0 : options.preventAbort; + const preventCancel = options === null || options === void 0 ? void 0 : options.preventCancel; + const preventClose = options === null || options === void 0 ? void 0 : options.preventClose; + const signal = options === null || options === void 0 ? void 0 : options.signal; + if (signal !== undefined) { + assertAbortSignal(signal, `${context} has member 'signal' that`); } - const primaryUser = await this.getPrimaryUser(date, userId); - if (primaryUser && (!keyId || primaryKey.getKeyId().equals(keyId)) && isValidSigningKeyPacket(primaryKey, primaryUser.selfCertification)) { - return this; + return { + preventAbort: Boolean(preventAbort), + preventCancel: Boolean(preventCancel), + preventClose: Boolean(preventClose), + signal + }; +} +function assertAbortSignal(signal, context) { + if (!isAbortSignal(signal)) { + throw new TypeError(`${context} is not an AbortSignal.`); } - } - return null; +} - function isValidSigningKeyPacket(keyPacket, signature) { - if (!signature.verified || signature.revoked !== false) { - // Sanity check - throw new Error('Signature not verified'); - } - return keyPacket.algorithm !== _enums2.default.read(_enums2.default.publicKey, _enums2.default.publicKey.rsa_encrypt) && keyPacket.algorithm !== _enums2.default.read(_enums2.default.publicKey, _enums2.default.publicKey.elgamal) && keyPacket.algorithm !== _enums2.default.read(_enums2.default.publicKey, _enums2.default.publicKey.ecdh) && (!signature.keyFlags || (signature.keyFlags[0] & _enums2.default.keyFlags.sign_data) !== 0); - } -}; +function convertReadableWritablePair(pair, context) { + assertDictionary(pair, context); + const readable = pair === null || pair === void 0 ? void 0 : pair.readable; + assertRequiredField(readable, 'readable', 'ReadableWritablePair'); + assertReadableStream(readable, `${context} has member 'readable' that`); + const writable = pair === null || pair === void 0 ? void 0 : pair.writable; + assertRequiredField(writable, 'writable', 'ReadableWritablePair'); + assertWritableStream(writable, `${context} has member 'writable' that`); + return { readable, writable }; +} /** - * Returns last created key or key by given keyId that is available for encryption or decryption - * @param {module:type/keyid} keyId, optional - * @param {Date} date, optional - * @param {String} userId, optional - * @returns {Promise} key or null if no encryption key has been found - * @async - */ -Key.prototype.getEncryptionKey = async function (keyId, date = new Date(), userId = {}) { - const primaryKey = this.keyPacket; - if ((await this.verifyPrimaryKey(date, userId)) === _enums2.default.keyStatus.valid) { - // V4: by convention subkeys are preferred for encryption service - const subKeys = this.subKeys.slice().sort((a, b) => b.keyPacket.created - a.keyPacket.created); - for (let i = 0; i < subKeys.length; i++) { - if (!keyId || subKeys[i].getKeyId().equals(keyId)) { - if ((await subKeys[i].verify(primaryKey, date)) === _enums2.default.keyStatus.valid) { - const dataToVerify = { key: primaryKey, bind: subKeys[i].keyPacket }; - const bindingSignature = await getLatestValidSignature(subKeys[i].bindingSignatures, primaryKey, _enums2.default.signature.subkey_binding, dataToVerify, date); - if (bindingSignature && isValidEncryptionKeyPacket(subKeys[i].keyPacket, bindingSignature)) { - return subKeys[i]; - } + * A readable stream represents a source of data, from which you can read. + * + * @public + */ +class ReadableStream$1 { + constructor(rawUnderlyingSource = {}, rawStrategy = {}) { + if (rawUnderlyingSource === undefined) { + rawUnderlyingSource = null; + } + else { + assertObject(rawUnderlyingSource, 'First parameter'); + } + const strategy = convertQueuingStrategy(rawStrategy, 'Second parameter'); + const underlyingSource = convertUnderlyingDefaultOrByteSource(rawUnderlyingSource, 'First parameter'); + InitializeReadableStream(this); + if (underlyingSource.type === 'bytes') { + if (strategy.size !== undefined) { + throw new RangeError('The strategy for a byte stream cannot have a size function'); + } + const highWaterMark = ExtractHighWaterMark(strategy, 0); + SetUpReadableByteStreamControllerFromUnderlyingSource(this, underlyingSource, highWaterMark); + } + else { + const sizeAlgorithm = ExtractSizeAlgorithm(strategy); + const highWaterMark = ExtractHighWaterMark(strategy, 1); + SetUpReadableStreamDefaultControllerFromUnderlyingSource(this, underlyingSource, highWaterMark, sizeAlgorithm); } - } - } - // if no valid subkey for encryption, evaluate primary key - const primaryUser = await this.getPrimaryUser(date, userId); - if (primaryUser && (!keyId || primaryKey.getKeyId().equals(keyId)) && isValidEncryptionKeyPacket(primaryKey, primaryUser.selfCertification)) { - return this; } - } - return null; - - function isValidEncryptionKeyPacket(keyPacket, signature) { - if (!signature.verified || signature.revoked !== false) { - // Sanity check - throw new Error('Signature not verified'); + /** + * Whether or not the readable stream is locked to a {@link ReadableStreamDefaultReader | reader}. + */ + get locked() { + if (!IsReadableStream(this)) { + throw streamBrandCheckException$1('locked'); + } + return IsReadableStreamLocked(this); } - return keyPacket.algorithm !== _enums2.default.read(_enums2.default.publicKey, _enums2.default.publicKey.dsa) && keyPacket.algorithm !== _enums2.default.read(_enums2.default.publicKey, _enums2.default.publicKey.rsa_sign) && keyPacket.algorithm !== _enums2.default.read(_enums2.default.publicKey, _enums2.default.publicKey.ecdsa) && keyPacket.algorithm !== _enums2.default.read(_enums2.default.publicKey, _enums2.default.publicKey.eddsa) && (!signature.keyFlags || (signature.keyFlags[0] & _enums2.default.keyFlags.encrypt_communication) !== 0 || (signature.keyFlags[0] & _enums2.default.keyFlags.encrypt_storage) !== 0); - } -}; - -/** - * Encrypts all secret key and subkey packets matching keyId - * @param {String|Array} passphrases - if multiple passphrases, then should be in same order as packets each should encrypt - * @param {module:type/keyid} keyId - * @returns {Promise>} - * @async - */ -Key.prototype.encrypt = async function (passphrases, keyId = null) { - if (!this.isPrivate()) { - throw new Error("Nothing to encrypt in a public key"); - } - - const keys = this.getKeys(keyId); - passphrases = _util2.default.isArray(passphrases) ? passphrases : new Array(keys.length).fill(passphrases); - if (passphrases.length !== keys.length) { - throw new Error("Invalid number of passphrases for key"); - } - - return Promise.all(keys.map(async function (key, i) { - const keyPacket = key.keyPacket; - - await keyPacket.encrypt(passphrases[i]); - keyPacket.clearPrivateParams(); - return keyPacket; - })); -}; - -/** - * Decrypts all secret key and subkey packets matching keyId - * @param {String|Array} passphrases - * @param {module:type/keyid} keyId - * @returns {Promise} true if all matching key and subkey packets decrypted successfully - * @async - */ -Key.prototype.decrypt = async function (passphrases, keyId = null) { - if (!this.isPrivate()) { - throw new Error("Nothing to decrypt in a public key"); - } - passphrases = _util2.default.isArray(passphrases) ? passphrases : [passphrases]; - - const results = await Promise.all(this.getKeys(keyId).map(async function (key) { - let decrypted = false; - let error = null; - await Promise.all(passphrases.map(async function (passphrase) { - try { - await key.keyPacket.decrypt(passphrase); - decrypted = true; - } catch (e) { - error = e; - } - })); - if (!decrypted) { - throw error; + /** + * Cancels the stream, signaling a loss of interest in the stream by a consumer. + * + * The supplied `reason` argument will be given to the underlying source's {@link UnderlyingSource.cancel | cancel()} + * method, which might or might not use it. + */ + cancel(reason = undefined) { + if (!IsReadableStream(this)) { + return promiseRejectedWith(streamBrandCheckException$1('cancel')); + } + if (IsReadableStreamLocked(this)) { + return promiseRejectedWith(new TypeError('Cannot cancel a stream that already has a reader')); + } + return ReadableStreamCancel(this, reason); } - return decrypted; - })); - return results.every(result => result === true); -}; - -/** - * Checks if a signature on a key is revoked - * @param {module:packet.SecretKey| - * @param {module:packet.Signature} signature The signature to verify - * @param {module:packet.PublicSubkey| - * module:packet.SecretSubkey| - * module:packet.PublicKey| - * module:packet.SecretKey} key, optional The key to verify the signature - * @param {Date} date Use the given date instead of the current time - * @returns {Promise} True if the certificate is revoked - * @async - */ -Key.prototype.isRevoked = async function (signature, key, date = new Date()) { - return isDataRevoked(this.keyPacket, _enums2.default.signature.key_revocation, { key: this.keyPacket }, this.revocationSignatures, signature, key, date); -}; - -/** - * Verify primary key. Checks for revocation signatures, expiration time - * and valid self signature - * @param {Date} date (optional) use the given date for verification instead of the current time - * @param {Object} userId (optional) user ID - * @returns {Promise} The status of the primary key - * @async - */ -Key.prototype.verifyPrimaryKey = async function (date = new Date(), userId = {}) { - const primaryKey = this.keyPacket; - // check for key revocation signatures - if (await this.isRevoked(null, null, date)) { - return _enums2.default.keyStatus.revoked; - } - // check for at least one self signature. Self signature of user ID not mandatory - // See {@link https://tools.ietf.org/html/rfc4880#section-11.1} - if (!this.users.some(user => user.userId && user.selfCertifications.length)) { - return _enums2.default.keyStatus.no_self_cert; - } - // check for valid, unrevoked, unexpired self signature - - var _ref = (await this.getPrimaryUser(date, userId)) || {}; - - const user = _ref.user, - selfCertification = _ref.selfCertification; - - if (!user) { - return _enums2.default.keyStatus.invalid; - } - // check for expiration time - if (isDataExpired(primaryKey, selfCertification, date)) { - return _enums2.default.keyStatus.expired; - } - return _enums2.default.keyStatus.valid; -}; - -/** - * Returns the latest date when the key can be used for encrypting, signing, or both, depending on the `capabilities` paramater. - * When `capabilities` is null, defaults to returning the expiry date of the primary key. - * Returns null if `capabilities` is passed and the key does not have the specified capabilities or is revoked or invalid. - * Returns Infinity if the key doesn't expire. - * @param {encrypt|sign|encrypt_sign} capabilities, optional - * @param {module:type/keyid} keyId, optional - * @param {Object} userId, optional user ID - * @returns {Promise} - * @async - */ -Key.prototype.getExpirationTime = async function (capabilities, keyId, userId) { - const primaryUser = await this.getPrimaryUser(null, userId); - if (!primaryUser) { - throw new Error('Could not find primary user'); - } - const selfCert = primaryUser.selfCertification; - const keyExpiry = getExpirationTime(this.keyPacket, selfCert); - const sigExpiry = selfCert.getExpirationTime(); - let expiry = keyExpiry < sigExpiry ? keyExpiry : sigExpiry; - if (capabilities === 'encrypt' || capabilities === 'encrypt_sign') { - const encryptKey = (await this.getEncryptionKey(keyId, expiry, userId)) || (await this.getEncryptionKey(keyId, null, userId)); - if (!encryptKey) return null; - const encryptExpiry = await encryptKey.getExpirationTime(this.keyPacket); - if (encryptExpiry < expiry) expiry = encryptExpiry; - } - if (capabilities === 'sign' || capabilities === 'encrypt_sign') { - const signKey = (await this.getSigningKey(keyId, expiry, userId)) || (await this.getSigningKey(keyId, null, userId)); - if (!signKey) return null; - const signExpiry = await signKey.getExpirationTime(this.keyPacket); - if (signExpiry < expiry) expiry = signExpiry; - } - return expiry; -}; - -/** - * Returns primary user and most significant (latest valid) self signature - * - if multiple primary users exist, returns the one with the latest self signature - * - otherwise, returns the user with the latest self signature - * @param {Date} date (optional) use the given date for verification instead of the current time - * @param {Object} userId (optional) user ID to get instead of the primary user, if it exists - * @returns {Promise<{user: module:key.User, - * selfCertification: module:packet.Signature}>} The primary user and the self signature - * @async - */ -Key.prototype.getPrimaryUser = async function (date = new Date(), userId = {}) { - const primaryKey = this.keyPacket; - const users = []; - for (let i = 0; i < this.users.length; i++) { - const user = this.users[i]; - if (!user.userId || !((userId.name === undefined || user.userId.name === userId.name) && (userId.email === undefined || user.userId.email === userId.email) && (userId.comment === undefined || user.userId.comment === userId.comment))) continue; - const dataToVerify = { userId: user.userId, key: primaryKey }; - const selfCertification = await getLatestValidSignature(user.selfCertifications, primaryKey, _enums2.default.signature.cert_generic, dataToVerify, date); - if (!selfCertification) continue; - users.push({ index: i, user, selfCertification }); - } - if (!users.length) { - if (userId.name !== undefined || userId.email !== undefined || userId.comment !== undefined) { - throw new Error('Could not find user that matches that user ID'); + getReader(rawOptions = undefined) { + if (!IsReadableStream(this)) { + throw streamBrandCheckException$1('getReader'); + } + const options = convertReaderOptions(rawOptions, 'First parameter'); + if (options.mode === undefined) { + return AcquireReadableStreamDefaultReader(this); + } + return AcquireReadableStreamBYOBReader(this); } - return null; - } - await Promise.all(users.map(async function (a) { - return a.user.revoked || a.user.isRevoked(primaryKey, a.selfCertification, null, date); - })); - // sort by primary user flag and signature creation time - const primaryUser = users.sort(function (a, b) { - const A = a.selfCertification; - const B = b.selfCertification; - return B.revoked - A.revoked || A.isPrimaryUserID - B.isPrimaryUserID || A.created - B.created; - }).pop(); - const user = primaryUser.user, - cert = primaryUser.selfCertification; - - if (cert.revoked || (await user.isRevoked(primaryKey, cert, null, date))) { - return null; - } - return primaryUser; -}; - -/** - * Update key with new components from specified key with same key ID: - * users, subkeys, certificates are merged into the destination key, - * duplicates and expired signatures are ignored. - * - * If the specified key is a private key and the destination key is public, - * the destination key is transformed to a private key. - * @param {module:key.Key} key Source key to merge - * @returns {Promise} - * @async - */ -Key.prototype.update = async function (key) { - if ((await key.verifyPrimaryKey()) === _enums2.default.keyStatus.invalid) { - return; - } - if (!this.hasSameFingerprintAs(key)) { - throw new Error('Key update method: fingerprints of keys not equal'); - } - if (this.isPublic() && key.isPrivate()) { - // check for equal subkey packets - const equal = this.subKeys.length === key.subKeys.length && this.subKeys.every(destSubKey => { - return key.subKeys.some(srcSubKey => { - return destSubKey.hasSameFingerprintAs(srcSubKey); - }); - }); - if (!equal) { - throw new Error('Cannot update public key with private key if subkey mismatch'); + pipeThrough(rawTransform, rawOptions = {}) { + if (!IsReadableStream(this)) { + throw streamBrandCheckException$1('pipeThrough'); + } + assertRequiredArgument(rawTransform, 1, 'pipeThrough'); + const transform = convertReadableWritablePair(rawTransform, 'First parameter'); + const options = convertPipeOptions(rawOptions, 'Second parameter'); + if (IsReadableStreamLocked(this)) { + throw new TypeError('ReadableStream.prototype.pipeThrough cannot be used on a locked ReadableStream'); + } + if (IsWritableStreamLocked(transform.writable)) { + throw new TypeError('ReadableStream.prototype.pipeThrough cannot be used on a locked WritableStream'); + } + const promise = ReadableStreamPipeTo(this, transform.writable, options.preventClose, options.preventAbort, options.preventCancel, options.signal); + setPromiseIsHandledToTrue(promise); + return transform.readable; } - this.keyPacket = key.keyPacket; - } - // revocation signatures - await mergeSignatures(key, this, 'revocationSignatures', srcRevSig => { - return isDataRevoked(this.keyPacket, _enums2.default.signature.key_revocation, this, [srcRevSig], null, key.keyPacket); - }); - // direct signatures - await mergeSignatures(key, this, 'directSignatures'); - // TODO replace when Promise.some or Promise.any are implemented - // users - await Promise.all(key.users.map(async srcUser => { - let found = false; - await Promise.all(this.users.map(async dstUser => { - if (srcUser.userId && dstUser.userId && srcUser.userId.userid === dstUser.userId.userid || srcUser.userAttribute && srcUser.userAttribute.equals(dstUser.userAttribute)) { - await dstUser.update(srcUser, this.keyPacket); - found = true; - } - })); - if (!found) { - this.users.push(srcUser); + pipeTo(destination, rawOptions = {}) { + if (!IsReadableStream(this)) { + return promiseRejectedWith(streamBrandCheckException$1('pipeTo')); + } + if (destination === undefined) { + return promiseRejectedWith(`Parameter 1 is required in 'pipeTo'.`); + } + if (!IsWritableStream(destination)) { + return promiseRejectedWith(new TypeError(`ReadableStream.prototype.pipeTo's first argument must be a WritableStream`)); + } + let options; + try { + options = convertPipeOptions(rawOptions, 'Second parameter'); + } + catch (e) { + return promiseRejectedWith(e); + } + if (IsReadableStreamLocked(this)) { + return promiseRejectedWith(new TypeError('ReadableStream.prototype.pipeTo cannot be used on a locked ReadableStream')); + } + if (IsWritableStreamLocked(destination)) { + return promiseRejectedWith(new TypeError('ReadableStream.prototype.pipeTo cannot be used on a locked WritableStream')); + } + return ReadableStreamPipeTo(this, destination, options.preventClose, options.preventAbort, options.preventCancel, options.signal); } - })); - // TODO replace when Promise.some or Promise.any are implemented - // subkeys - await Promise.all(key.subKeys.map(async srcSubKey => { - let found = false; - await Promise.all(this.subKeys.map(async dstSubKey => { - if (dstSubKey.hasSameFingerprintAs(srcSubKey)) { - await dstSubKey.update(srcSubKey, this.keyPacket); - found = true; - } - })); - if (!found) { - this.subKeys.push(srcSubKey); + /** + * Tees this readable stream, returning a two-element array containing the two resulting branches as + * new {@link ReadableStream} instances. + * + * Teeing a stream will lock it, preventing any other consumer from acquiring a reader. + * To cancel the stream, cancel both of the resulting branches; a composite cancellation reason will then be + * propagated to the stream's underlying source. + * + * Note that the chunks seen in each branch will be the same object. If the chunks are not immutable, + * this could allow interference between the two branches. + */ + tee() { + if (!IsReadableStream(this)) { + throw streamBrandCheckException$1('tee'); + } + const branches = ReadableStreamTee(this); + return CreateArrayFromList(branches); } - })); -}; - -/** - * Merges signatures from source[attr] to dest[attr] - * @private - * @param {Object} source - * @param {Object} dest - * @param {String} attr - * @param {Function} checkFn optional, signature only merged if true - */ -async function mergeSignatures(source, dest, attr, checkFn) { - source = source[attr]; - if (source) { - if (!dest[attr].length) { - dest[attr] = source; - } else { - await Promise.all(source.map(async function (sourceSig) { - if (!sourceSig.isExpired() && (!checkFn || (await checkFn(sourceSig))) && !dest[attr].some(function (destSig) { - return _util2.default.equalsUint8Array(destSig.signature, sourceSig.signature); - })) { - dest[attr].push(sourceSig); + values(rawOptions = undefined) { + if (!IsReadableStream(this)) { + throw streamBrandCheckException$1('values'); } - })); + const options = convertIteratorOptions(rawOptions, 'First parameter'); + return AcquireReadableStreamAsyncIterator(this, options.preventCancel); } - } } - -/** - * Revokes the key - * @param {Object} reasonForRevocation optional, object indicating the reason for revocation - * @param {module:enums.reasonForRevocation} reasonForRevocation.flag optional, flag indicating the reason for revocation - * @param {String} reasonForRevocation.string optional, string explaining the reason for revocation - * @param {Date} date optional, override the creationtime of the revocation signature - * @returns {Promise} new key with revocation signature - * @async - */ -Key.prototype.revoke = async function ({ - flag: reasonForRevocationFlag = _enums2.default.reasonForRevocation.no_reason, - string: reasonForRevocationString = '' -} = {}, date = new Date()) { - if (this.isPublic()) { - throw new Error('Need private key for revoking'); - } - const dataToSign = { key: this.keyPacket }; - const key = new Key(this.toPacketlist()); - key.revocationSignatures.push((await createSignaturePacket(dataToSign, null, this.keyPacket, { - signatureType: _enums2.default.signature.key_revocation, - reasonForRevocationFlag: _enums2.default.write(_enums2.default.reasonForRevocation, reasonForRevocationFlag), - reasonForRevocationString - }, date))); - return key; -}; - -/** - * Get revocation certificate from a revoked key. - * (To get a revocation certificate for an unrevoked key, call revoke() first.) - * @returns {Promise} armored revocation certificate - * @async - */ -Key.prototype.getRevocationCertificate = async function () { - const dataToVerify = { key: this.keyPacket }; - const revocationSignature = await getLatestValidSignature(this.revocationSignatures, this.keyPacket, _enums2.default.signature.key_revocation, dataToVerify); - if (revocationSignature) { - const packetlist = new _packet2.default.List(); - packetlist.push(revocationSignature); - return _armor2.default.encode(_enums2.default.armor.public_key, packetlist.write(), null, null, 'This is a revocation certificate'); - } -}; - -/** - * Applies a revocation certificate to a key - * This adds the first signature packet in the armored text to the key, - * if it is a valid revocation signature. - * @param {String} revocationCertificate armored revocation certificate - * @returns {Promise} new revoked key - * @async - */ -Key.prototype.applyRevocationCertificate = async function (revocationCertificate) { - const input = await _armor2.default.decode(revocationCertificate); - const packetlist = new _packet2.default.List(); - await packetlist.read(input.data); - const revocationSignature = packetlist.findPacket(_enums2.default.packet.signature); - if (!revocationSignature || revocationSignature.signatureType !== _enums2.default.signature.key_revocation) { - throw new Error('Could not find revocation signature packet'); - } - if (!revocationSignature.issuerKeyId.equals(this.getKeyId())) { - throw new Error('Revocation signature does not match key'); - } - if (revocationSignature.isExpired()) { - throw new Error('Revocation signature is expired'); - } - if (!(await revocationSignature.verify(this.keyPacket, _enums2.default.signature.key_revocation, { key: this.keyPacket }))) { - throw new Error('Could not verify revocation signature'); - } - const key = new Key(this.toPacketlist()); - key.revocationSignatures.push(revocationSignature); - return key; -}; - -/** - * Signs primary user of key - * @param {Array} privateKey decrypted private keys for signing - * @param {Date} date (optional) use the given date for verification instead of the current time - * @param {Object} userId (optional) user ID to get instead of the primary user, if it exists - * @returns {Promise} new public key with new certificate signature - * @async - */ -Key.prototype.signPrimaryUser = async function (privateKeys, date, userId) { - var _ref2 = (await this.getPrimaryUser(date, userId)) || {}; - - const index = _ref2.index, - user = _ref2.user; - - if (!user) { - throw new Error('Could not find primary user'); - } - const userSign = await user.sign(this.keyPacket, privateKeys); - const key = new Key(this.toPacketlist()); - key.users[index] = userSign; - return key; -}; - -/** - * Signs all users of key - * @param {Array} privateKeys decrypted private keys for signing - * @returns {Promise} new public key with new certificate signature - * @async - */ -Key.prototype.signAllUsers = async function (privateKeys) { - const that = this; - const key = new Key(this.toPacketlist()); - key.users = await Promise.all(this.users.map(function (user) { - return user.sign(that.keyPacket, privateKeys); - })); - return key; -}; - -/** - * Verifies primary user of key - * - if no arguments are given, verifies the self certificates; - * - otherwise, verifies all certificates signed with given keys. - * @param {Array} keys array of keys to verify certificate signatures - * @param {Date} date (optional) use the given date for verification instead of the current time - * @param {Object} userId (optional) user ID to get instead of the primary user, if it exists - * @returns {Promise>} List of signer's keyid and validity of signature - * @async - */ -Key.prototype.verifyPrimaryUser = async function (keys, date, userId) { - const primaryKey = this.keyPacket; - - var _ref3 = (await this.getPrimaryUser(date, userId)) || {}; - - const user = _ref3.user; - - if (!user) { - throw new Error('Could not find primary user'); - } - const results = keys ? await user.verifyAllCertifications(primaryKey, keys) : [{ keyid: primaryKey.keyid, valid: (await user.verify(primaryKey)) === _enums2.default.keyStatus.valid }]; - return results; -}; - -/** - * Verifies all users of key - * - if no arguments are given, verifies the self certificates; - * - otherwise, verifies all certificates signed with given keys. - * @param {Array} keys array of keys to verify certificate signatures - * @returns {Promise>} list of userid, signer's keyid and validity of signature - * @async - */ -Key.prototype.verifyAllUsers = async function (keys) { - const results = []; - const primaryKey = this.keyPacket; - await Promise.all(this.users.map(async function (user) { - const signatures = keys ? await user.verifyAllCertifications(primaryKey, keys) : [{ keyid: primaryKey.keyid, valid: (await user.verify(primaryKey)) === _enums2.default.keyStatus.valid }]; - signatures.forEach(signature => { - results.push({ - userid: user.userId.userid, - keyid: signature.keyid, - valid: signature.valid - }); +Object.defineProperties(ReadableStream$1.prototype, { + cancel: { enumerable: true }, + getReader: { enumerable: true }, + pipeThrough: { enumerable: true }, + pipeTo: { enumerable: true }, + tee: { enumerable: true }, + values: { enumerable: true }, + locked: { enumerable: true } +}); +if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(ReadableStream$1.prototype, SymbolPolyfill.toStringTag, { + value: 'ReadableStream', + configurable: true }); - })); - return results; -}; - -/** - * @class - * @classdesc Class that represents an user ID or attribute packet and the relevant signatures. - */ -function User(userPacket) { - if (!(this instanceof User)) { - return new User(userPacket); - } - this.userId = userPacket.tag === _enums2.default.packet.userid ? userPacket : null; - this.userAttribute = userPacket.tag === _enums2.default.packet.userAttribute ? userPacket : null; - this.selfCertifications = []; - this.otherCertifications = []; - this.revocationSignatures = []; } - -/** - * Transforms structured user data to packetlist - * @returns {module:packet.List} - */ -User.prototype.toPacketlist = function () { - const packetlist = new _packet2.default.List(); - packetlist.push(this.userId || this.userAttribute); - packetlist.concat(this.revocationSignatures); - packetlist.concat(this.selfCertifications); - packetlist.concat(this.otherCertifications); - return packetlist; -}; - -/** - * Signs user - * @param {module:packet.SecretKey| - * module:packet.PublicKey} primaryKey The primary key packet - * @param {Array} privateKeys Decrypted private keys for signing - * @returns {Promise} New user with new certificate signatures - * @async - */ -User.prototype.sign = async function (primaryKey, privateKeys) { - const dataToSign = { - userId: this.userId, - userAttribute: this.userAttribute, - key: primaryKey - }; - const user = new User(dataToSign.userId || dataToSign.userAttribute); - user.otherCertifications = await Promise.all(privateKeys.map(async function (privateKey) { - if (privateKey.isPublic()) { - throw new Error('Need private key for signing'); +if (typeof SymbolPolyfill.asyncIterator === 'symbol') { + Object.defineProperty(ReadableStream$1.prototype, SymbolPolyfill.asyncIterator, { + value: ReadableStream$1.prototype.values, + writable: true, + configurable: true + }); +} +// Abstract operations for the ReadableStream. +// Throws if and only if startAlgorithm throws. +function CreateReadableStream(startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark = 1, sizeAlgorithm = () => 1) { + const stream = Object.create(ReadableStream$1.prototype); + InitializeReadableStream(stream); + const controller = Object.create(ReadableStreamDefaultController.prototype); + SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm); + return stream; +} +function InitializeReadableStream(stream) { + stream._state = 'readable'; + stream._reader = undefined; + stream._storedError = undefined; + stream._disturbed = false; +} +function IsReadableStream(x) { + if (!typeIsObject(x)) { + return false; } - if (privateKey.hasSameFingerprintAs(primaryKey)) { - throw new Error('Not implemented for self signing'); + if (!Object.prototype.hasOwnProperty.call(x, '_readableStreamController')) { + return false; } - const signingKey = await privateKey.getSigningKey(); - if (!signingKey) { - throw new Error('Could not find valid signing key packet in key ' + privateKey.getKeyId().toHex()); + return true; +} +function IsReadableStreamLocked(stream) { + if (stream._reader === undefined) { + return false; } - return createSignaturePacket(dataToSign, privateKey, signingKey.keyPacket, { - // Most OpenPGP implementations use generic certification (0x10) - signatureType: _enums2.default.signature.cert_generic, - keyFlags: [_enums2.default.keyFlags.certify_keys | _enums2.default.keyFlags.sign_data] - }); - })); - await user.update(this, primaryKey); - return user; -}; - -/** - * Checks if a given certificate of the user is revoked - * @param {module:packet.SecretKey| - * module:packet.PublicKey} primaryKey The primary key packet - * @param {module:packet.Signature} certificate The certificate to verify - * @param {module:packet.PublicSubkey| - * module:packet.SecretSubkey| - * module:packet.PublicKey| - * module:packet.SecretKey} key, optional The key to verify the signature - * @param {Date} date Use the given date instead of the current time - * @returns {Promise} True if the certificate is revoked - * @async - */ -User.prototype.isRevoked = async function (primaryKey, certificate, key, date = new Date()) { - return isDataRevoked(primaryKey, _enums2.default.signature.cert_revocation, { - key: primaryKey, - userId: this.userId, - userAttribute: this.userAttribute - }, this.revocationSignatures, certificate, key, date); -}; - -/** - * Create signature packet - * @param {Object} dataToSign Contains packets to be signed - * @param {module:packet.SecretKey| - * module:packet.SecretSubkey} signingKeyPacket secret key packet for signing - * @param {Object} signatureProperties (optional) properties to write on the signature packet before signing - * @param {Date} date (optional) override the creationtime of the signature - * @param {Object} userId (optional) user ID - * @param {Object} detached (optional) whether to create a detached signature packet - * @returns {module:packet/signature} signature packet - */ -async function createSignaturePacket(dataToSign, privateKey, signingKeyPacket, signatureProperties, date, userId, detached = false) { - if (!signingKeyPacket.isDecrypted()) { - throw new Error('Private key is not decrypted.'); - } - const signaturePacket = new _packet2.default.Signature(date); - Object.assign(signaturePacket, signatureProperties); - signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm; - signaturePacket.hashAlgorithm = await getPreferredHashAlgo(privateKey, signingKeyPacket, date, userId); - await signaturePacket.sign(signingKeyPacket, dataToSign, detached); - return signaturePacket; + return true; } - -/** - * Verifies the user certificate - * @param {module:packet.SecretKey| - * module:packet.PublicKey} primaryKey The primary key packet - * @param {module:packet.Signature} certificate A certificate of this user - * @param {Array} keys Array of keys to verify certificate signatures - * @param {Date} date Use the given date instead of the current time - * @returns {Promise} status of the certificate - * @async - */ -User.prototype.verifyCertificate = async function (primaryKey, certificate, keys, date = new Date()) { - const that = this; - const keyid = certificate.issuerKeyId; - const dataToVerify = { - userId: this.userId, - userAttribute: this.userAttribute, - key: primaryKey - }; - const results = await Promise.all(keys.map(async function (key) { - if (!key.getKeyIds().some(id => id.equals(keyid))) { - return; +// ReadableStream API exposed for controllers. +function ReadableStreamCancel(stream, reason) { + stream._disturbed = true; + if (stream._state === 'closed') { + return promiseResolvedWith(undefined); + } + if (stream._state === 'errored') { + return promiseRejectedWith(stream._storedError); + } + ReadableStreamClose(stream); + const sourceCancelPromise = stream._readableStreamController[CancelSteps](reason); + return transformPromiseWith(sourceCancelPromise, noop); +} +function ReadableStreamClose(stream) { + stream._state = 'closed'; + const reader = stream._reader; + if (reader === undefined) { + return; } - const signingKey = await key.getSigningKey(keyid, date); - if (certificate.revoked || (await that.isRevoked(primaryKey, certificate, signingKey.keyPacket, date))) { - return _enums2.default.keyStatus.revoked; + defaultReaderClosedPromiseResolve(reader); + if (IsReadableStreamDefaultReader(reader)) { + reader._readRequests.forEach(readRequest => { + readRequest._closeSteps(); + }); + reader._readRequests = new SimpleQueue(); } - if (!(certificate.verified || (await certificate.verify(signingKey.keyPacket, _enums2.default.signature.cert_generic, dataToVerify)))) { - return _enums2.default.keyStatus.invalid; +} +function ReadableStreamError(stream, e) { + stream._state = 'errored'; + stream._storedError = e; + const reader = stream._reader; + if (reader === undefined) { + return; } - if (certificate.isExpired(date)) { - return _enums2.default.keyStatus.expired; + defaultReaderClosedPromiseReject(reader, e); + if (IsReadableStreamDefaultReader(reader)) { + reader._readRequests.forEach(readRequest => { + readRequest._errorSteps(e); + }); + reader._readRequests = new SimpleQueue(); } - return _enums2.default.keyStatus.valid; - })); - return results.find(result => result !== undefined); -}; + else { + reader._readIntoRequests.forEach(readIntoRequest => { + readIntoRequest._errorSteps(e); + }); + reader._readIntoRequests = new SimpleQueue(); + } +} +// Helper functions for the ReadableStream. +function streamBrandCheckException$1(name) { + return new TypeError(`ReadableStream.prototype.${name} can only be used on a ReadableStream`); +} -/** - * Verifies all user certificates - * @param {module:packet.SecretKey| - * module:packet.PublicKey} primaryKey The primary key packet - * @param {Array} keys Array of keys to verify certificate signatures - * @param {Date} date Use the given date instead of the current time - * @returns {Promise>} List of signer's keyid and validity of signature - * @async - */ -User.prototype.verifyAllCertifications = async function (primaryKey, keys, date = new Date()) { - const that = this; - const certifications = this.selfCertifications.concat(this.otherCertifications); - return Promise.all(certifications.map(async function (certification) { - const status = await that.verifyCertificate(primaryKey, certification, keys, date); +function convertQueuingStrategyInit(init, context) { + assertDictionary(init, context); + const highWaterMark = init === null || init === void 0 ? void 0 : init.highWaterMark; + assertRequiredField(highWaterMark, 'highWaterMark', 'QueuingStrategyInit'); return { - keyid: certification.issuerKeyId, - valid: status === undefined ? null : status === _enums2.default.keyStatus.valid + highWaterMark: convertUnrestrictedDouble(highWaterMark) }; - })); -}; +} +const byteLengthSizeFunction = function size(chunk) { + return chunk.byteLength; +}; /** - * Verify User. Checks for existence of self signatures, revocation signatures - * and validity of self signature - * @param {module:packet.SecretKey| - * module:packet.PublicKey} primaryKey The primary key packet - * @param {Date} date Use the given date instead of the current time - * @returns {Promise} Status of user - * @async + * A queuing strategy that counts the number of bytes in each chunk. + * + * @public */ -User.prototype.verify = async function (primaryKey, date = new Date()) { - if (!this.selfCertifications.length) { - return _enums2.default.keyStatus.no_self_cert; - } - const that = this; - const dataToVerify = { - userId: this.userId, - userAttribute: this.userAttribute, - key: primaryKey - }; - // TODO replace when Promise.some or Promise.any are implemented - const results = [_enums2.default.keyStatus.invalid].concat((await Promise.all(this.selfCertifications.map(async function (selfCertification) { - if (selfCertification.revoked || (await that.isRevoked(primaryKey, selfCertification, undefined, date))) { - return _enums2.default.keyStatus.revoked; +class ByteLengthQueuingStrategy { + constructor(options) { + assertRequiredArgument(options, 1, 'ByteLengthQueuingStrategy'); + options = convertQueuingStrategyInit(options, 'First parameter'); + this._byteLengthQueuingStrategyHighWaterMark = options.highWaterMark; } - if (!(selfCertification.verified || (await selfCertification.verify(primaryKey, _enums2.default.signature.cert_generic, dataToVerify)))) { - return _enums2.default.keyStatus.invalid; + /** + * Returns the high water mark provided to the constructor. + */ + get highWaterMark() { + if (!IsByteLengthQueuingStrategy(this)) { + throw byteLengthBrandCheckException('highWaterMark'); + } + return this._byteLengthQueuingStrategyHighWaterMark; } - if (selfCertification.isExpired(date)) { - return _enums2.default.keyStatus.expired; + /** + * Measures the size of `chunk` by returning the value of its `byteLength` property. + */ + get size() { + if (!IsByteLengthQueuingStrategy(this)) { + throw byteLengthBrandCheckException('size'); + } + return byteLengthSizeFunction; } - return _enums2.default.keyStatus.valid; - })))); - return results.some(status => status === _enums2.default.keyStatus.valid) ? _enums2.default.keyStatus.valid : results.pop(); -}; - -/** - * Update user with new components from specified user - * @param {module:key.User} user Source user to merge - * @param {module:packet.SecretKey| - * module:packet.SecretSubkey} primaryKey primary key used for validation - * @returns {Promise} - * @async - */ -User.prototype.update = async function (user, primaryKey) { - const dataToVerify = { - userId: this.userId, - userAttribute: this.userAttribute, - key: primaryKey - }; - // self signatures - await mergeSignatures(user, this, 'selfCertifications', async function (srcSelfSig) { - return srcSelfSig.verified || srcSelfSig.verify(primaryKey, _enums2.default.signature.cert_generic, dataToVerify); - }); - // other signatures - await mergeSignatures(user, this, 'otherCertifications'); - // revocation signatures - await mergeSignatures(user, this, 'revocationSignatures', function (srcRevSig) { - return isDataRevoked(primaryKey, _enums2.default.signature.cert_revocation, dataToVerify, [srcRevSig]); - }); -}; - -/** - * @class - * @classdesc Class that represents a subkey packet and the relevant signatures. - * @borrows module:packet.PublicSubkey#getKeyId as SubKey#getKeyId - * @borrows module:packet.PublicSubkey#getFingerprint as SubKey#getFingerprint - * @borrows module:packet.PublicSubkey#hasSameFingerprintAs as SubKey#hasSameFingerprintAs - * @borrows module:packet.PublicSubkey#getAlgorithmInfo as SubKey#getAlgorithmInfo - * @borrows module:packet.PublicSubkey#getCreationTime as SubKey#getCreationTime - * @borrows module:packet.PublicSubkey#isDecrypted as SubKey#isDecrypted - */ -function SubKey(subKeyPacket) { - if (!(this instanceof SubKey)) { - return new SubKey(subKeyPacket); - } - this.keyPacket = subKeyPacket; - this.bindingSignatures = []; - this.revocationSignatures = []; } - -/** - * Transforms structured subkey data to packetlist - * @returns {module:packet.List} - */ -SubKey.prototype.toPacketlist = function () { - const packetlist = new _packet2.default.List(); - packetlist.push(this.keyPacket); - packetlist.concat(this.revocationSignatures); - packetlist.concat(this.bindingSignatures); - return packetlist; -}; - -/** - * Checks if a binding signature of a subkey is revoked - * @param {module:packet.SecretKey| - * module:packet.PublicKey} primaryKey The primary key packet - * @param {module:packet.Signature} signature The binding signature to verify - * @param {module:packet.PublicSubkey| - * module:packet.SecretSubkey| - * module:packet.PublicKey| - * module:packet.SecretKey} key, optional The key to verify the signature - * @param {Date} date Use the given date instead of the current time - * @returns {Promise} True if the binding signature is revoked - * @async - */ -SubKey.prototype.isRevoked = async function (primaryKey, signature, key, date = new Date()) { - return isDataRevoked(primaryKey, _enums2.default.signature.subkey_revocation, { - key: primaryKey, - bind: this.keyPacket - }, this.revocationSignatures, signature, key, date); -}; - -/** - * Verify subkey. Checks for revocation signatures, expiration time - * and valid binding signature - * @param {module:packet.SecretKey| - * module:packet.PublicKey} primaryKey The primary key packet - * @param {Date} date Use the given date instead of the current time - * @returns {Promise} The status of the subkey - * @async - */ -SubKey.prototype.verify = async function (primaryKey, date = new Date()) { - const that = this; - const dataToVerify = { key: primaryKey, bind: this.keyPacket }; - // check subkey binding signatures - const bindingSignature = await getLatestValidSignature(this.bindingSignatures, primaryKey, _enums2.default.signature.subkey_binding, dataToVerify, date); - // check binding signature is verified - if (!bindingSignature) { - return _enums2.default.keyStatus.invalid; - } - // check binding signature is not revoked - if (bindingSignature.revoked || (await that.isRevoked(primaryKey, bindingSignature, null, date))) { - return _enums2.default.keyStatus.revoked; - } - // check for expiration time - if (isDataExpired(this.keyPacket, bindingSignature, date)) { - return _enums2.default.keyStatus.expired; - } - return _enums2.default.keyStatus.valid; // binding signature passed all checks -}; - -/** - * Returns the expiration time of the subkey or Infinity if key does not expire - * Returns null if the subkey is invalid. - * @param {module:packet.SecretKey| - * module:packet.PublicKey} primaryKey The primary key packet - * @param {Date} date Use the given date instead of the current time - * @returns {Promise} - * @async - */ -SubKey.prototype.getExpirationTime = async function (primaryKey, date = new Date()) { - const dataToVerify = { key: primaryKey, bind: this.keyPacket }; - const bindingSignature = await getLatestValidSignature(this.bindingSignatures, primaryKey, _enums2.default.signature.subkey_binding, dataToVerify, date); - if (!bindingSignature) return null; - const keyExpiry = getExpirationTime(this.keyPacket, bindingSignature); - const sigExpiry = bindingSignature.getExpirationTime(); - return keyExpiry < sigExpiry ? keyExpiry : sigExpiry; -}; - -/** - * Update subkey with new components from specified subkey - * @param {module:key~SubKey} subKey Source subkey to merge - * @param {module:packet.SecretKey| - module:packet.SecretSubkey} primaryKey primary key used for validation - * @returns {Promise} - * @async - */ -SubKey.prototype.update = async function (subKey, primaryKey) { - if ((await subKey.verify(primaryKey)) === _enums2.default.keyStatus.invalid) { - return; - } - if (!this.hasSameFingerprintAs(subKey)) { - throw new Error('SubKey update method: fingerprints of subkeys not equal'); - } - // key packet - if (this.keyPacket.tag === _enums2.default.packet.publicSubkey && subKey.keyPacket.tag === _enums2.default.packet.secretSubkey) { - this.keyPacket = subKey.keyPacket; - } - // update missing binding signatures - const that = this; - const dataToVerify = { key: primaryKey, bind: that.keyPacket }; - await mergeSignatures(subKey, this, 'bindingSignatures', async function (srcBindSig) { - if (!(srcBindSig.verified || (await srcBindSig.verify(primaryKey, _enums2.default.signature.subkey_binding, dataToVerify)))) { - return false; +Object.defineProperties(ByteLengthQueuingStrategy.prototype, { + highWaterMark: { enumerable: true }, + size: { enumerable: true } +}); +if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(ByteLengthQueuingStrategy.prototype, SymbolPolyfill.toStringTag, { + value: 'ByteLengthQueuingStrategy', + configurable: true + }); +} +// Helper functions for the ByteLengthQueuingStrategy. +function byteLengthBrandCheckException(name) { + return new TypeError(`ByteLengthQueuingStrategy.prototype.${name} can only be used on a ByteLengthQueuingStrategy`); +} +function IsByteLengthQueuingStrategy(x) { + if (!typeIsObject(x)) { + return false; } - for (let i = 0; i < that.bindingSignatures.length; i++) { - if (that.bindingSignatures[i].issuerKeyId.equals(srcBindSig.issuerKeyId)) { - if (srcBindSig.created > that.bindingSignatures[i].created) { - that.bindingSignatures[i] = srcBindSig; - } + if (!Object.prototype.hasOwnProperty.call(x, '_byteLengthQueuingStrategyHighWaterMark')) { return false; - } } return true; - }); - // revocation signatures - await mergeSignatures(subKey, this, 'revocationSignatures', function (srcRevSig) { - return isDataRevoked(primaryKey, _enums2.default.signature.subkey_revocation, dataToVerify, [srcRevSig]); - }); -}; - -/** - * Revokes the subkey - * @param {module:packet.SecretKey} primaryKey decrypted private primary key for revocation - * @param {Object} reasonForRevocation optional, object indicating the reason for revocation - * @param {module:enums.reasonForRevocation} reasonForRevocation.flag optional, flag indicating the reason for revocation - * @param {String} reasonForRevocation.string optional, string explaining the reason for revocation - * @param {Date} date optional, override the creationtime of the revocation signature - * @returns {Promise} new subkey with revocation signature - * @async - */ -SubKey.prototype.revoke = async function (primaryKey, { - flag: reasonForRevocationFlag = _enums2.default.reasonForRevocation.no_reason, - string: reasonForRevocationString = '' -} = {}, date = new Date()) { - const dataToSign = { key: primaryKey, bind: this.keyPacket }; - const subKey = new SubKey(this.keyPacket); - subKey.revocationSignatures.push((await createSignaturePacket(dataToSign, null, primaryKey, { - signatureType: _enums2.default.signature.subkey_revocation, - reasonForRevocationFlag: _enums2.default.write(_enums2.default.reasonForRevocation, reasonForRevocationFlag), - reasonForRevocationString - }, date))); - await subKey.update(this, primaryKey); - return subKey; -}; - -['getKeyId', 'getFingerprint', 'getAlgorithmInfo', 'getCreationTime', 'isDecrypted'].forEach(name => { - Key.prototype[name] = SubKey.prototype[name] = function () { - return this.keyPacket[name](); - }; -}); +} -Key.prototype.hasSameFingerprintAs = SubKey.prototype.hasSameFingerprintAs = function (other) { - return this.keyPacket.hasSameFingerprintAs(other.keyPacket || other); +const countSizeFunction = function size() { + return 1; }; - /** - * Reads an unarmored OpenPGP key list and returns one or multiple key objects - * @param {Uint8Array} data to be parsed - * @returns {Promise<{keys: Array, - * err: (Array|null)}>} result object with key and error arrays - * @async - * @static + * A queuing strategy that counts the number of chunks. + * + * @public */ -async function read(data) { - const result = {}; - result.keys = []; - const err = []; - try { - const packetlist = new _packet2.default.List(); - await packetlist.read(data); - const keyIndex = packetlist.indexOfTag(_enums2.default.packet.publicKey, _enums2.default.packet.secretKey); - if (keyIndex.length === 0) { - throw new Error('No key packet found'); - } - for (let i = 0; i < keyIndex.length; i++) { - const oneKeyList = packetlist.slice(keyIndex[i], keyIndex[i + 1]); - try { - const newKey = new Key(oneKeyList); - result.keys.push(newKey); - } catch (e) { - err.push(e); - } +class CountQueuingStrategy { + constructor(options) { + assertRequiredArgument(options, 1, 'CountQueuingStrategy'); + options = convertQueuingStrategyInit(options, 'First parameter'); + this._countQueuingStrategyHighWaterMark = options.highWaterMark; + } + /** + * Returns the high water mark provided to the constructor. + */ + get highWaterMark() { + if (!IsCountQueuingStrategy(this)) { + throw countBrandCheckException('highWaterMark'); + } + return this._countQueuingStrategyHighWaterMark; + } + /** + * Measures the size of `chunk` by always returning 1. + * This ensures that the total queue size is a count of the number of chunks in the queue. + */ + get size() { + if (!IsCountQueuingStrategy(this)) { + throw countBrandCheckException('size'); + } + return countSizeFunction; } - } catch (e) { - err.push(e); - } - if (err.length) { - result.err = err; - } - return result; } - -/** - * Reads an OpenPGP armored text and returns one or multiple key objects - * @param {String | ReadableStream} armoredText text to be parsed - * @returns {Promise<{keys: Array, - * err: (Array|null)}>} result object with key and error arrays - * @async - * @static - */ -async function readArmored(armoredText) { - try { - const input = await _armor2.default.decode(armoredText); - if (!(input.type === _enums2.default.armor.public_key || input.type === _enums2.default.armor.private_key)) { - throw new Error('Armored text not of type key'); +Object.defineProperties(CountQueuingStrategy.prototype, { + highWaterMark: { enumerable: true }, + size: { enumerable: true } +}); +if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(CountQueuingStrategy.prototype, SymbolPolyfill.toStringTag, { + value: 'CountQueuingStrategy', + configurable: true + }); +} +// Helper functions for the CountQueuingStrategy. +function countBrandCheckException(name) { + return new TypeError(`CountQueuingStrategy.prototype.${name} can only be used on a CountQueuingStrategy`); +} +function IsCountQueuingStrategy(x) { + if (!typeIsObject(x)) { + return false; } - return read(input.data); - } catch (e) { - const result = { keys: [], err: [] }; - result.err.push(e); - return result; - } + if (!Object.prototype.hasOwnProperty.call(x, '_countQueuingStrategyHighWaterMark')) { + return false; + } + return true; } -/** - * Generates a new OpenPGP key. Supports RSA and ECC keys. - * Primary and subkey will be of same type. - * @param {module:enums.publicKey} [options.keyType=module:enums.publicKey.rsa_encrypt_sign] - * To indicate what type of key to make. - * RSA is 1. See {@link https://tools.ietf.org/html/rfc4880#section-9.1} - * @param {Integer} options.numBits number of bits for the key creation. - * @param {String|Array} options.userIds - * Assumes already in form of "User Name " - * If array is used, the first userId is set as primary user Id - * @param {String} options.passphrase The passphrase used to encrypt the resulting private key - * @param {Number} [options.keyExpirationTime=0] - * The number of seconds after the key creation time that the key expires - * @param {String} curve (optional) elliptic curve for ECC keys - * @param {Date} date Override the creation date of the key and the key signatures - * @param {Array} subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}] - * sign parameter defaults to false, and indicates whether the subkey should sign rather than encrypt - * @returns {Promise} - * @async - * @static - */ -async function generate(options) { - options.sign = true; // primary key is always a signing key - options = sanitizeKeyOptions(options); - options.subkeys = options.subkeys.map(function (subkey, index) { - return sanitizeKeyOptions(options.subkeys[index], options); - }); - - let promises = [generateSecretKey(options)]; - promises = promises.concat(options.subkeys.map(generateSecretSubkey)); - return Promise.all(promises).then(packets => wrapKeyObject(packets[0], packets.slice(1), options)); - - function sanitizeKeyOptions(options, subkeyDefaults = {}) { - options.curve = options.curve || subkeyDefaults.curve; - options.numBits = options.numBits || subkeyDefaults.numBits; - options.keyExpirationTime = options.keyExpirationTime !== undefined ? options.keyExpirationTime : subkeyDefaults.keyExpirationTime; - options.passphrase = _util2.default.isString(options.passphrase) ? options.passphrase : subkeyDefaults.passphrase; - options.date = options.date || subkeyDefaults.date; - - options.sign = options.sign || false; +function convertTransformer(original, context) { + assertDictionary(original, context); + const flush = original === null || original === void 0 ? void 0 : original.flush; + const readableType = original === null || original === void 0 ? void 0 : original.readableType; + const start = original === null || original === void 0 ? void 0 : original.start; + const transform = original === null || original === void 0 ? void 0 : original.transform; + const writableType = original === null || original === void 0 ? void 0 : original.writableType; + return { + flush: flush === undefined ? + undefined : + convertTransformerFlushCallback(flush, original, `${context} has member 'flush' that`), + readableType, + start: start === undefined ? + undefined : + convertTransformerStartCallback(start, original, `${context} has member 'start' that`), + transform: transform === undefined ? + undefined : + convertTransformerTransformCallback(transform, original, `${context} has member 'transform' that`), + writableType + }; +} +function convertTransformerFlushCallback(fn, original, context) { + assertFunction(fn, context); + return (controller) => promiseCall(fn, original, [controller]); +} +function convertTransformerStartCallback(fn, original, context) { + assertFunction(fn, context); + return (controller) => reflectCall(fn, original, [controller]); +} +function convertTransformerTransformCallback(fn, original, context) { + assertFunction(fn, context); + return (chunk, controller) => promiseCall(fn, original, [chunk, controller]); +} - if (options.curve) { - try { - options.curve = _enums2.default.write(_enums2.default.curve, options.curve); - } catch (e) { - throw new Error('Not valid curve.'); - } - if (options.curve === _enums2.default.curve.ed25519 || options.curve === _enums2.default.curve.curve25519) { - if (options.sign) { - options.algorithm = _enums2.default.publicKey.eddsa; - options.curve = _enums2.default.curve.ed25519; - } else { - options.algorithm = _enums2.default.publicKey.ecdh; - options.curve = _enums2.default.curve.curve25519; +// Class TransformStream +/** + * A transform stream consists of a pair of streams: a {@link WritableStream | writable stream}, + * known as its writable side, and a {@link ReadableStream | readable stream}, known as its readable side. + * In a manner specific to the transform stream in question, writes to the writable side result in new data being + * made available for reading from the readable side. + * + * @public + */ +class TransformStream$1 { + constructor(rawTransformer = {}, rawWritableStrategy = {}, rawReadableStrategy = {}) { + if (rawTransformer === undefined) { + rawTransformer = null; + } + const writableStrategy = convertQueuingStrategy(rawWritableStrategy, 'Second parameter'); + const readableStrategy = convertQueuingStrategy(rawReadableStrategy, 'Third parameter'); + const transformer = convertTransformer(rawTransformer, 'First parameter'); + if (transformer.readableType !== undefined) { + throw new RangeError('Invalid readableType specified'); + } + if (transformer.writableType !== undefined) { + throw new RangeError('Invalid writableType specified'); + } + const readableHighWaterMark = ExtractHighWaterMark(readableStrategy, 0); + const readableSizeAlgorithm = ExtractSizeAlgorithm(readableStrategy); + const writableHighWaterMark = ExtractHighWaterMark(writableStrategy, 1); + const writableSizeAlgorithm = ExtractSizeAlgorithm(writableStrategy); + let startPromise_resolve; + const startPromise = newPromise(resolve => { + startPromise_resolve = resolve; + }); + InitializeTransformStream(this, startPromise, writableHighWaterMark, writableSizeAlgorithm, readableHighWaterMark, readableSizeAlgorithm); + SetUpTransformStreamDefaultControllerFromTransformer(this, transformer); + if (transformer.start !== undefined) { + startPromise_resolve(transformer.start(this._transformStreamController)); } - } else { - if (options.sign) { - options.algorithm = _enums2.default.publicKey.ecdsa; - } else { - options.algorithm = _enums2.default.publicKey.ecdh; + else { + startPromise_resolve(undefined); } - } - } else if (options.numBits) { - options.algorithm = _enums2.default.publicKey.rsa_encrypt_sign; - } else { - throw new Error('Unrecognized key type'); } - return options; - } - - async function generateSecretKey(options) { - const secretKeyPacket = new _packet2.default.SecretKey(options.date); - secretKeyPacket.packets = null; - secretKeyPacket.algorithm = _enums2.default.read(_enums2.default.publicKey, options.algorithm); - await secretKeyPacket.generate(options.numBits, options.curve); - return secretKeyPacket; - } - - async function generateSecretSubkey(options) { - const secretSubkeyPacket = new _packet2.default.SecretSubkey(options.date); - secretSubkeyPacket.packets = null; - secretSubkeyPacket.algorithm = _enums2.default.read(_enums2.default.publicKey, options.algorithm); - await secretSubkeyPacket.generate(options.numBits, options.curve); - return secretSubkeyPacket; - } + /** + * The readable side of the transform stream. + */ + get readable() { + if (!IsTransformStream(this)) { + throw streamBrandCheckException('readable'); + } + return this._readable; + } + /** + * The writable side of the transform stream. + */ + get writable() { + if (!IsTransformStream(this)) { + throw streamBrandCheckException('writable'); + } + return this._writable; + } } - +Object.defineProperties(TransformStream$1.prototype, { + readable: { enumerable: true }, + writable: { enumerable: true } +}); +if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(TransformStream$1.prototype, SymbolPolyfill.toStringTag, { + value: 'TransformStream', + configurable: true + }); +} +function InitializeTransformStream(stream, startPromise, writableHighWaterMark, writableSizeAlgorithm, readableHighWaterMark, readableSizeAlgorithm) { + function startAlgorithm() { + return startPromise; + } + function writeAlgorithm(chunk) { + return TransformStreamDefaultSinkWriteAlgorithm(stream, chunk); + } + function abortAlgorithm(reason) { + return TransformStreamDefaultSinkAbortAlgorithm(stream, reason); + } + function closeAlgorithm() { + return TransformStreamDefaultSinkCloseAlgorithm(stream); + } + stream._writable = CreateWritableStream(startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, writableHighWaterMark, writableSizeAlgorithm); + function pullAlgorithm() { + return TransformStreamDefaultSourcePullAlgorithm(stream); + } + function cancelAlgorithm(reason) { + TransformStreamErrorWritableAndUnblockWrite(stream, reason); + return promiseResolvedWith(undefined); + } + stream._readable = CreateReadableStream(startAlgorithm, pullAlgorithm, cancelAlgorithm, readableHighWaterMark, readableSizeAlgorithm); + // The [[backpressure]] slot is set to undefined so that it can be initialised by TransformStreamSetBackpressure. + stream._backpressure = undefined; + stream._backpressureChangePromise = undefined; + stream._backpressureChangePromise_resolve = undefined; + TransformStreamSetBackpressure(stream, true); + stream._transformStreamController = undefined; +} +function IsTransformStream(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_transformStreamController')) { + return false; + } + return true; +} +// This is a no-op if both sides are already errored. +function TransformStreamError(stream, e) { + ReadableStreamDefaultControllerError(stream._readable._readableStreamController, e); + TransformStreamErrorWritableAndUnblockWrite(stream, e); +} +function TransformStreamErrorWritableAndUnblockWrite(stream, e) { + TransformStreamDefaultControllerClearAlgorithms(stream._transformStreamController); + WritableStreamDefaultControllerErrorIfNeeded(stream._writable._writableStreamController, e); + if (stream._backpressure) { + // Pretend that pull() was called to permit any pending write() calls to complete. TransformStreamSetBackpressure() + // cannot be called from enqueue() or pull() once the ReadableStream is errored, so this will will be the final time + // _backpressure is set. + TransformStreamSetBackpressure(stream, false); + } +} +function TransformStreamSetBackpressure(stream, backpressure) { + // Passes also when called during construction. + if (stream._backpressureChangePromise !== undefined) { + stream._backpressureChangePromise_resolve(); + } + stream._backpressureChangePromise = newPromise(resolve => { + stream._backpressureChangePromise_resolve = resolve; + }); + stream._backpressure = backpressure; +} +// Class TransformStreamDefaultController /** - * Reformats and signs an OpenPGP key with a given User ID. Currently only supports RSA keys. - * @param {module:key.Key} options.privateKey The private key to reformat - * @param {module:enums.publicKey} [options.keyType=module:enums.publicKey.rsa_encrypt_sign] - * @param {String|Array} options.userIds - * Assumes already in form of "User Name " - * If array is used, the first userId is set as primary user Id - * @param {String} options.passphrase The passphrase used to encrypt the resulting private key - * @param {Number} [options.keyExpirationTime=0] - * The number of seconds after the key creation time that the key expires - * @param {Date} date Override the creation date of the key and the key signatures - * @param {Array} subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}] + * Allows control of the {@link ReadableStream} and {@link WritableStream} of the associated {@link TransformStream}. * - * @returns {Promise} - * @async - * @static + * @public */ -async function reformat(options) { - options = sanitizeKeyOptions(options); - - try { - const isDecrypted = options.privateKey.getKeys().every(key => key.isDecrypted()); - if (!isDecrypted) { - await options.privateKey.decrypt(); +class TransformStreamDefaultController { + constructor() { + throw new TypeError('Illegal constructor'); } - } catch (err) { - throw new Error('Key not decrypted'); - } - - const packetlist = options.privateKey.toPacketlist(); - let secretKeyPacket; - const secretSubkeyPackets = []; - for (let i = 0; i < packetlist.length; i++) { - if (packetlist[i].tag === _enums2.default.packet.secretKey) { - secretKeyPacket = packetlist[i]; - } else if (packetlist[i].tag === _enums2.default.packet.secretSubkey) { - secretSubkeyPackets.push(packetlist[i]); + /** + * Returns the desired size to fill the readable side’s internal queue. It can be negative, if the queue is over-full. + */ + get desiredSize() { + if (!IsTransformStreamDefaultController(this)) { + throw defaultControllerBrandCheckException('desiredSize'); + } + const readableController = this._controlledTransformStream._readable._readableStreamController; + return ReadableStreamDefaultControllerGetDesiredSize(readableController); + } + enqueue(chunk = undefined) { + if (!IsTransformStreamDefaultController(this)) { + throw defaultControllerBrandCheckException('enqueue'); + } + TransformStreamDefaultControllerEnqueue(this, chunk); + } + /** + * Errors both the readable side and the writable side of the controlled transform stream, making all future + * interactions with it fail with the given error `e`. Any chunks queued for transformation will be discarded. + */ + error(reason = undefined) { + if (!IsTransformStreamDefaultController(this)) { + throw defaultControllerBrandCheckException('error'); + } + TransformStreamDefaultControllerError(this, reason); + } + /** + * Closes the readable side and errors the writable side of the controlled transform stream. This is useful when the + * transformer only needs to consume a portion of the chunks written to the writable side. + */ + terminate() { + if (!IsTransformStreamDefaultController(this)) { + throw defaultControllerBrandCheckException('terminate'); + } + TransformStreamDefaultControllerTerminate(this); } - } - if (!secretKeyPacket) { - throw new Error('Key does not contain a secret key packet'); - } - - if (!options.subkeys) { - options.subkeys = await Promise.all(secretSubkeyPackets.map(async secretSubkeyPacket => ({ - sign: (await options.privateKey.getSigningKey(secretSubkeyPacket.getKeyId(), null)) && !(await options.privateKey.getEncryptionKey(secretSubkeyPacket.getKeyId(), null)) - }))); - } - - if (options.subkeys.length !== secretSubkeyPackets.length) { - throw new Error('Number of subkey options does not match number of subkeys'); - } - - options.subkeys = options.subkeys.map(function (subkey, index) { - return sanitizeKeyOptions(options.subkeys[index], options); - }); - - return wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options); - - function sanitizeKeyOptions(options, subkeyDefaults = {}) { - options.keyExpirationTime = options.keyExpirationTime || subkeyDefaults.keyExpirationTime; - options.passphrase = _util2.default.isString(options.passphrase) ? options.passphrase : subkeyDefaults.passphrase; - options.date = options.date || subkeyDefaults.date; - - return options; - } } - -async function wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options) { - // set passphrase protection - if (options.passphrase) { - await secretKeyPacket.encrypt(options.passphrase); - } - - await Promise.all(secretSubkeyPackets.map(async function (secretSubkeyPacket, index) { - const subkeyPassphrase = options.subkeys[index].passphrase; - if (subkeyPassphrase) { - await secretSubkeyPacket.encrypt(subkeyPassphrase); +Object.defineProperties(TransformStreamDefaultController.prototype, { + enqueue: { enumerable: true }, + error: { enumerable: true }, + terminate: { enumerable: true }, + desiredSize: { enumerable: true } +}); +if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(TransformStreamDefaultController.prototype, SymbolPolyfill.toStringTag, { + value: 'TransformStreamDefaultController', + configurable: true + }); +} +// Transform Stream Default Controller Abstract Operations +function IsTransformStreamDefaultController(x) { + if (!typeIsObject(x)) { + return false; } - })); - - const packetlist = new _packet2.default.List(); - - packetlist.push(secretKeyPacket); - - await Promise.all(options.userIds.map(async function (userId, index) { - function createdPreferredAlgos(algos, configAlgo) { - if (configAlgo) { - // Not `uncompressed` / `plaintext` - const configIndex = algos.indexOf(configAlgo); - if (configIndex >= 1) { - // If it is included and not in first place, - algos.splice(configIndex, 1); // remove it. + if (!Object.prototype.hasOwnProperty.call(x, '_controlledTransformStream')) { + return false; + } + return true; +} +function SetUpTransformStreamDefaultController(stream, controller, transformAlgorithm, flushAlgorithm) { + controller._controlledTransformStream = stream; + stream._transformStreamController = controller; + controller._transformAlgorithm = transformAlgorithm; + controller._flushAlgorithm = flushAlgorithm; +} +function SetUpTransformStreamDefaultControllerFromTransformer(stream, transformer) { + const controller = Object.create(TransformStreamDefaultController.prototype); + let transformAlgorithm = (chunk) => { + try { + TransformStreamDefaultControllerEnqueue(controller, chunk); + return promiseResolvedWith(undefined); } - if (configIndex !== 0) { - // If it was included and not in first place, or wasn't included, - algos.unshift(configAlgo); // add it to the front. + catch (transformResultE) { + return promiseRejectedWith(transformResultE); } - } - return algos; + }; + let flushAlgorithm = () => promiseResolvedWith(undefined); + if (transformer.transform !== undefined) { + transformAlgorithm = chunk => transformer.transform(chunk, controller); } - - const userIdPacket = new _packet2.default.Userid(); - userIdPacket.format(userId); - - const dataToSign = {}; - dataToSign.userId = userIdPacket; - dataToSign.key = secretKeyPacket; - const signaturePacket = new _packet2.default.Signature(options.date); - signaturePacket.signatureType = _enums2.default.signature.cert_generic; - signaturePacket.publicKeyAlgorithm = secretKeyPacket.algorithm; - signaturePacket.hashAlgorithm = await getPreferredHashAlgo(null, secretKeyPacket); - signaturePacket.keyFlags = [_enums2.default.keyFlags.certify_keys | _enums2.default.keyFlags.sign_data]; - signaturePacket.preferredSymmetricAlgorithms = createdPreferredAlgos([ - // prefer aes256, aes128, then aes192 (no WebCrypto support: https://www.chromium.org/blink/webcrypto#TOC-AES-support) - _enums2.default.symmetric.aes256, _enums2.default.symmetric.aes128, _enums2.default.symmetric.aes192, _enums2.default.symmetric.cast5, _enums2.default.symmetric.tripledes], _config2.default.encryption_cipher); - if (_config2.default.aead_protect) { - signaturePacket.preferredAeadAlgorithms = createdPreferredAlgos([_enums2.default.aead.eax, _enums2.default.aead.ocb], _config2.default.aead_mode); - } - signaturePacket.preferredHashAlgorithms = createdPreferredAlgos([ - // prefer fast asm.js implementations (SHA-256). SHA-1 will not be secure much longer...move to bottom of list - _enums2.default.hash.sha256, _enums2.default.hash.sha512, _enums2.default.hash.sha1], _config2.default.prefer_hash_algorithm); - signaturePacket.preferredCompressionAlgorithms = createdPreferredAlgos([_enums2.default.compression.zlib, _enums2.default.compression.zip], _config2.default.compression); - if (index === 0) { - signaturePacket.isPrimaryUserID = true; + if (transformer.flush !== undefined) { + flushAlgorithm = () => transformer.flush(controller); } - if (_config2.default.integrity_protect) { - signaturePacket.features = [0]; - signaturePacket.features[0] |= _enums2.default.features.modification_detection; + SetUpTransformStreamDefaultController(stream, controller, transformAlgorithm, flushAlgorithm); +} +function TransformStreamDefaultControllerClearAlgorithms(controller) { + controller._transformAlgorithm = undefined; + controller._flushAlgorithm = undefined; +} +function TransformStreamDefaultControllerEnqueue(controller, chunk) { + const stream = controller._controlledTransformStream; + const readableController = stream._readable._readableStreamController; + if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(readableController)) { + throw new TypeError('Readable side is not in a state that permits enqueue'); } - if (_config2.default.aead_protect) { - signaturePacket.features || (signaturePacket.features = [0]); - signaturePacket.features[0] |= _enums2.default.features.aead; + // We throttle transform invocations based on the backpressure of the ReadableStream, but we still + // accept TransformStreamDefaultControllerEnqueue() calls. + try { + ReadableStreamDefaultControllerEnqueue(readableController, chunk); } - if (_config2.default.v5_keys) { - signaturePacket.features || (signaturePacket.features = [0]); - signaturePacket.features[0] |= _enums2.default.features.v5_keys; + catch (e) { + // This happens when readableStrategy.size() throws. + TransformStreamErrorWritableAndUnblockWrite(stream, e); + throw stream._readable._storedError; } - if (options.keyExpirationTime > 0) { - signaturePacket.keyExpirationTime = options.keyExpirationTime; - signaturePacket.keyNeverExpires = false; + const backpressure = ReadableStreamDefaultControllerHasBackpressure(readableController); + if (backpressure !== stream._backpressure) { + TransformStreamSetBackpressure(stream, true); } - await signaturePacket.sign(secretKeyPacket, dataToSign); - - return { userIdPacket, signaturePacket }; - })).then(list => { - list.forEach(({ userIdPacket, signaturePacket }) => { - packetlist.push(userIdPacket); - packetlist.push(signaturePacket); +} +function TransformStreamDefaultControllerError(controller, e) { + TransformStreamError(controller._controlledTransformStream, e); +} +function TransformStreamDefaultControllerPerformTransform(controller, chunk) { + const transformPromise = controller._transformAlgorithm(chunk); + return transformPromiseWith(transformPromise, undefined, r => { + TransformStreamError(controller._controlledTransformStream, r); + throw r; }); - }); - - await Promise.all(secretSubkeyPackets.map(async function (secretSubkeyPacket, index) { - const subkeyOptions = options.subkeys[index]; - const dataToSign = {}; - dataToSign.key = secretKeyPacket; - dataToSign.bind = secretSubkeyPacket; - const subkeySignaturePacket = new _packet2.default.Signature(subkeyOptions.date); - subkeySignaturePacket.signatureType = _enums2.default.signature.subkey_binding; - subkeySignaturePacket.publicKeyAlgorithm = secretKeyPacket.algorithm; - subkeySignaturePacket.hashAlgorithm = await getPreferredHashAlgo(null, secretSubkeyPacket); - if (subkeyOptions.sign) { - subkeySignaturePacket.keyFlags = [_enums2.default.keyFlags.sign_data]; - subkeySignaturePacket.embeddedSignature = await createSignaturePacket(dataToSign, null, secretSubkeyPacket, { - signatureType: _enums2.default.signature.key_binding - }, subkeyOptions.date); - } else { - subkeySignaturePacket.keyFlags = [_enums2.default.keyFlags.encrypt_communication | _enums2.default.keyFlags.encrypt_storage]; - } - if (subkeyOptions.keyExpirationTime > 0) { - subkeySignaturePacket.keyExpirationTime = subkeyOptions.keyExpirationTime; - subkeySignaturePacket.keyNeverExpires = false; +} +function TransformStreamDefaultControllerTerminate(controller) { + const stream = controller._controlledTransformStream; + const readableController = stream._readable._readableStreamController; + ReadableStreamDefaultControllerClose(readableController); + const error = new TypeError('TransformStream terminated'); + TransformStreamErrorWritableAndUnblockWrite(stream, error); +} +// TransformStreamDefaultSink Algorithms +function TransformStreamDefaultSinkWriteAlgorithm(stream, chunk) { + const controller = stream._transformStreamController; + if (stream._backpressure) { + const backpressureChangePromise = stream._backpressureChangePromise; + return transformPromiseWith(backpressureChangePromise, () => { + const writable = stream._writable; + const state = writable._state; + if (state === 'erroring') { + throw writable._storedError; + } + return TransformStreamDefaultControllerPerformTransform(controller, chunk); + }); } - await subkeySignaturePacket.sign(secretKeyPacket, dataToSign); - - return { secretSubkeyPacket, subkeySignaturePacket }; - })).then(packets => { - packets.forEach(({ secretSubkeyPacket, subkeySignaturePacket }) => { - packetlist.push(secretSubkeyPacket); - packetlist.push(subkeySignaturePacket); + return TransformStreamDefaultControllerPerformTransform(controller, chunk); +} +function TransformStreamDefaultSinkAbortAlgorithm(stream, reason) { + // abort() is not called synchronously, so it is possible for abort() to be called when the stream is already + // errored. + TransformStreamError(stream, reason); + return promiseResolvedWith(undefined); +} +function TransformStreamDefaultSinkCloseAlgorithm(stream) { + // stream._readable cannot change after construction, so caching it across a call to user code is safe. + const readable = stream._readable; + const controller = stream._transformStreamController; + const flushPromise = controller._flushAlgorithm(); + TransformStreamDefaultControllerClearAlgorithms(controller); + // Return a promise that is fulfilled with undefined on success. + return transformPromiseWith(flushPromise, () => { + if (readable._state === 'errored') { + throw readable._storedError; + } + ReadableStreamDefaultControllerClose(readable._readableStreamController); + }, r => { + TransformStreamError(stream, r); + throw readable._storedError; }); - }); +} +// TransformStreamDefaultSource Algorithms +function TransformStreamDefaultSourcePullAlgorithm(stream) { + // Invariant. Enforced by the promises returned by start() and pull(). + TransformStreamSetBackpressure(stream, false); + // Prevent the next pull() call until there is backpressure. + return stream._backpressureChangePromise; +} +// Helper functions for the TransformStreamDefaultController. +function defaultControllerBrandCheckException(name) { + return new TypeError(`TransformStreamDefaultController.prototype.${name} can only be used on a TransformStreamDefaultController`); +} +// Helper functions for the TransformStream. +function streamBrandCheckException(name) { + return new TypeError(`TransformStream.prototype.${name} can only be used on a TransformStream`); +} + +var ponyfill_es6 = /*#__PURE__*/Object.freeze({ + __proto__: null, + ByteLengthQueuingStrategy: ByteLengthQueuingStrategy, + CountQueuingStrategy: CountQueuingStrategy, + ReadableByteStreamController: ReadableByteStreamController, + ReadableStream: ReadableStream$1, + ReadableStreamBYOBReader: ReadableStreamBYOBReader, + ReadableStreamBYOBRequest: ReadableStreamBYOBRequest, + ReadableStreamDefaultController: ReadableStreamDefaultController, + ReadableStreamDefaultReader: ReadableStreamDefaultReader, + TransformStream: TransformStream$1, + TransformStreamDefaultController: TransformStreamDefaultController, + WritableStream: WritableStream$1, + WritableStreamDefaultController: WritableStreamDefaultController, + WritableStreamDefaultWriter: WritableStreamDefaultWriter +}); - // Add revocation signature packet for creating a revocation certificate. - // This packet should be removed before returning the key. - const dataToSign = { key: secretKeyPacket }; - packetlist.push((await createSignaturePacket(dataToSign, null, secretKeyPacket, { - signatureType: _enums2.default.signature.key_revocation, - reasonForRevocationFlag: _enums2.default.reasonForRevocation.no_reason, - reasonForRevocationString: '' - }, options.date))); +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. - // set passphrase protection - if (options.passphrase) { - secretKeyPacket.clearPrivateParams(); - } +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. - await Promise.all(secretSubkeyPackets.map(async function (secretSubkeyPacket, index) { - const subkeyPassphrase = options.subkeys[index].passphrase; - if (subkeyPassphrase) { - secretSubkeyPacket.clearPrivateParams(); - } - })); +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */ +/* global Reflect, Promise */ + +var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); +}; - return new Key(packetlist); +function __extends(d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } -/** - * Checks if a given certificate or binding signature is revoked - * @param {module:packet.SecretKey| - * module:packet.PublicKey} primaryKey The primary key packet - * @param {Object} dataToVerify The data to check - * @param {Array} revocations The revocation signatures to check - * @param {module:packet.Signature} signature The certificate or signature to check - * @param {module:packet.PublicSubkey| - * module:packet.SecretSubkey| - * module:packet.PublicKey| - * module:packet.SecretKey} key, optional The key packet to check the signature - * @param {Date} date Use the given date instead of the current time - * @returns {Promise} True if the signature revokes the data - * @async - */ -async function isDataRevoked(primaryKey, signatureType, dataToVerify, revocations, signature, key, date = new Date()) { - key = key || primaryKey; - const normDate = _util2.default.normalizeDate(date); - const revocationKeyIds = []; - await Promise.all(revocations.map(async function (revocationSignature) { - if ( - // Note: a third-party revocation signature could legitimately revoke a - // self-signature if the signature has an authorized revocation key. - // However, we don't support passing authorized revocation keys, nor - // verifying such revocation signatures. Instead, we indicate an error - // when parsing a key with an authorized revocation key, and ignore - // third-party revocation signatures here. (It could also be revoking a - // third-party key certification, which should only affect - // `verifyAllCertifications`.) - (!signature || revocationSignature.issuerKeyId.equals(signature.issuerKeyId)) && !(_config2.default.revocations_expire && revocationSignature.isExpired(normDate)) && (revocationSignature.verified || (await revocationSignature.verify(key, signatureType, dataToVerify)))) { - // TODO get an identifier of the revoked object instead - revocationKeyIds.push(revocationSignature.issuerKeyId); - return true; +function assert$1(test) { + if (!test) { + throw new TypeError('Assertion failed'); } - return false; - })); - // TODO further verify that this is the signature that should be revoked - if (signature) { - signature.revoked = revocationKeyIds.some(keyId => keyId.equals(signature.issuerKeyId)) ? true : signature.revoked || false; - return signature.revoked; - } - return revocationKeyIds.length > 0; } -function isDataExpired(keyPacket, signature, date = new Date()) { - const normDate = _util2.default.normalizeDate(date); - if (normDate !== null) { - const expirationTime = getExpirationTime(keyPacket, signature); - return !(keyPacket.created <= normDate && normDate <= expirationTime) || signature && signature.isExpired(date); - } - return false; +function noop$1() { + return; } - -function getExpirationTime(keyPacket, signature) { - let expirationTime; - // check V4 expiration time - if (signature.keyNeverExpires === false) { - expirationTime = keyPacket.created.getTime() + signature.keyExpirationTime * 1000; - } - return expirationTime ? new Date(expirationTime) : Infinity; +function typeIsObject$1(x) { + return (typeof x === 'object' && x !== null) || typeof x === 'function'; } -/** - * Check if signature has revocation key sub packet (not supported by OpenPGP.js) - * and throw error if found - * @param {module:packet.Signature} signature The certificate or signature to check - * @param {type/keyid} keyId Check only certificates or signatures from a certain issuer key ID - */ -function checkRevocationKey(signature, keyId) { - if (signature.revocationKeyClass !== null && signature.issuerKeyId.equals(keyId)) { - throw new Error('This key is intended to be revoked with an authorized key, which OpenPGP.js does not support.'); - } +function isStreamConstructor(ctor) { + if (typeof ctor !== 'function') { + return false; + } + var startCalled = false; + try { + new ctor({ + start: function () { + startCalled = true; + } + }); + } + catch (e) { + // ignore + } + return startCalled; } - -/** - * Returns the preferred signature hash algorithm of a key - * @param {module:key.Key} key (optional) the key to get preferences from - * @param {module:packet.SecretKey|module:packet.SecretSubkey} keyPacket key packet used for signing - * @param {Date} date (optional) use the given date for verification instead of the current time - * @param {Object} userId (optional) user ID - * @returns {Promise} - * @async - */ -async function getPreferredHashAlgo(key, keyPacket, date = new Date(), userId = {}) { - let hash_algo = _config2.default.prefer_hash_algorithm; - let pref_algo = hash_algo; - if (key instanceof Key) { - const primaryUser = await key.getPrimaryUser(date, userId); - if (primaryUser && primaryUser.selfCertification.preferredHashAlgorithms) { - var _primaryUser$selfCert = _slicedToArray(primaryUser.selfCertification.preferredHashAlgorithms, 1); - - pref_algo = _primaryUser$selfCert[0]; - - hash_algo = _crypto2.default.hash.getHashByteLength(hash_algo) <= _crypto2.default.hash.getHashByteLength(pref_algo) ? pref_algo : hash_algo; +function isReadableStream(readable) { + if (!typeIsObject$1(readable)) { + return false; } - } - switch (Object.getPrototypeOf(keyPacket)) { - case _packet2.default.SecretKey.prototype: - case _packet2.default.PublicKey.prototype: - case _packet2.default.SecretSubkey.prototype: - case _packet2.default.PublicSubkey.prototype: - switch (keyPacket.algorithm) { - case 'ecdh': - case 'ecdsa': - case 'eddsa': - pref_algo = _crypto2.default.publicKey.elliptic.getPreferredHashAlgo(keyPacket.params[0]); - } - } - return _crypto2.default.hash.getHashByteLength(hash_algo) <= _crypto2.default.hash.getHashByteLength(pref_algo) ? pref_algo : hash_algo; + if (typeof readable.getReader !== 'function') { + return false; + } + return true; } - -/** - * Returns the preferred symmetric/aead algorithm for a set of keys - * @param {symmetric|aead} type Type of preference to return - * @param {Array} keys Set of keys - * @param {Date} date (optional) use the given date for verification instead of the current time - * @param {Array} userIds (optional) user IDs - * @returns {Promise} Preferred symmetric algorithm - * @async - */ -async function getPreferredAlgo(type, keys, date = new Date(), userIds = []) { - const prefProperty = type === 'symmetric' ? 'preferredSymmetricAlgorithms' : 'preferredAeadAlgorithms'; - const defaultAlgo = type === 'symmetric' ? _enums2.default.symmetric.aes128 : _enums2.default.aead.eax; - const prioMap = {}; - await Promise.all(keys.map(async function (key, i) { - const primaryUser = await key.getPrimaryUser(date, userIds[i]); - if (!primaryUser || !primaryUser.selfCertification[prefProperty]) { - return defaultAlgo; - } - primaryUser.selfCertification[prefProperty].forEach(function (algo, index) { - const entry = prioMap[algo] || (prioMap[algo] = { prio: 0, count: 0, algo: algo }); - entry.prio += 64 >> index; - entry.count++; - }); - })); - let prefAlgo = { prio: 0, algo: defaultAlgo }; - Object.values(prioMap).forEach(({ prio, count, algo }) => { +function isReadableStreamConstructor(ctor) { + if (!isStreamConstructor(ctor)) { + return false; + } + if (!isReadableStream(new ctor())) { + return false; + } + return true; +} +function isWritableStream(writable) { + if (!typeIsObject$1(writable)) { + return false; + } + if (typeof writable.getWriter !== 'function') { + return false; + } + return true; +} +function isWritableStreamConstructor(ctor) { + if (!isStreamConstructor(ctor)) { + return false; + } + if (!isWritableStream(new ctor())) { + return false; + } + return true; +} +function isTransformStream(transform) { + if (!typeIsObject$1(transform)) { + return false; + } + if (!isReadableStream(transform.readable)) { + return false; + } + if (!isWritableStream(transform.writable)) { + return false; + } + return true; +} +function isTransformStreamConstructor(ctor) { + if (!isStreamConstructor(ctor)) { + return false; + } + if (!isTransformStream(new ctor())) { + return false; + } + return true; +} +function supportsByobReader(readable) { try { - if (algo !== _enums2.default[type].plaintext && algo !== _enums2.default[type].idea && // not implemented - _enums2.default.read(_enums2.default[type], algo) && // known algorithm - count === keys.length && // available for all keys - prio > prefAlgo.prio) { - prefAlgo = prioMap[algo]; - } - } catch (e) {} - }); - return prefAlgo.algo; + var reader = readable.getReader({ mode: 'byob' }); + reader.releaseLock(); + return true; + } + catch (_a) { + return false; + } } - -/** - * Returns whether aead is supported by all keys in the set - * @param {Array} keys Set of keys - * @param {Date} date (optional) use the given date for verification instead of the current time - * @param {Array} userIds (optional) user IDs - * @returns {Promise} - * @async - */ -async function isAeadSupported(keys, date = new Date(), userIds = []) { - let supported = true; - // TODO replace when Promise.some or Promise.any are implemented - await Promise.all(keys.map(async function (key, i) { - const primaryUser = await key.getPrimaryUser(date, userIds[i]); - if (!primaryUser || !primaryUser.selfCertification.features || !(primaryUser.selfCertification.features[0] & _enums2.default.features.aead)) { - supported = false; +function supportsByteSource(ctor) { + try { + new ctor({ type: 'bytes' }); + return true; + } + catch (_a) { + return false; } - })); - return supported; } -},{"./config":79,"./crypto":94,"./encoding/armor":111,"./enums":113,"./packet":125,"./util":152}],117:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _keyring = require('./keyring.js'); - -var _keyring2 = _interopRequireDefault(_keyring); - -var _localstore = require('./localstore.js'); - -var _localstore2 = _interopRequireDefault(_localstore); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * @fileoverview Functions dealing with storage of the keyring. - * @see module:keyring/keyring - * @see module:keyring/localstore - * @module keyring - */ -_keyring2.default.localstore = _localstore2.default; - -exports.default = _keyring2.default; - -},{"./keyring.js":118,"./localstore.js":119}],118:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _key = require('../key'); - -var _localstore = require('./localstore'); - -var _localstore2 = _interopRequireDefault(_localstore); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Initialization routine for the keyring. - * @constructor - * @param {keyring/localstore} [storeHandler] class implementing loadPublic(), loadPrivate(), storePublic(), and storePrivate() methods - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @fileoverview Provides the Keyring class - * @requires key - * @requires keyring/localstore - * @module keyring/keyring - */ - -function Keyring(storeHandler) { - this.storeHandler = storeHandler || new _localstore2.default(); +function createReadableStreamWrapper(ctor) { + assert$1(isReadableStreamConstructor(ctor)); + var byteSourceSupported = supportsByteSource(ctor); + return function (readable, _a) { + var _b = _a === void 0 ? {} : _a, type = _b.type; + type = parseReadableType(type); + if (type === 'bytes' && !byteSourceSupported) { + type = undefined; + } + if (readable.constructor === ctor) { + if (type !== 'bytes' || supportsByobReader(readable)) { + return readable; + } + } + if (type === 'bytes') { + var source = createWrappingReadableSource(readable, { type: type }); + return new ctor(source); + } + else { + var source = createWrappingReadableSource(readable); + return new ctor(source); + } + }; } - -/** - * Calls the storeHandler to load the keys - * @async - */ -Keyring.prototype.load = async function () { - this.publicKeys = new KeyArray((await this.storeHandler.loadPublic())); - this.privateKeys = new KeyArray((await this.storeHandler.loadPrivate())); -}; - -/** - * Calls the storeHandler to save the keys - * @async - */ -Keyring.prototype.store = async function () { - await Promise.all([this.storeHandler.storePublic(this.publicKeys.keys), this.storeHandler.storePrivate(this.privateKeys.keys)]); -}; - -/** - * Clear the keyring - erase all the keys - */ -Keyring.prototype.clear = function () { - this.publicKeys.keys = []; - this.privateKeys.keys = []; -}; - -/** - * Searches the keyring for keys having the specified key id - * @param {String} keyId provided as string of lowercase hex number - * withouth 0x prefix (can be 16-character key ID or fingerprint) - * @param {Boolean} deep if true search also in subkeys - * @returns {Array|null} keys found or null - */ -Keyring.prototype.getKeysForId = function (keyId, deep) { - let result = []; - result = result.concat(this.publicKeys.getForId(keyId, deep) || []); - result = result.concat(this.privateKeys.getForId(keyId, deep) || []); - return result.length ? result : null; -}; - -/** - * Removes keys having the specified key id from the keyring - * @param {String} keyId provided as string of lowercase hex number - * withouth 0x prefix (can be 16-character key ID or fingerprint) - * @returns {Array|null} keys found or null - */ -Keyring.prototype.removeKeysForId = function (keyId) { - let result = []; - result = result.concat(this.publicKeys.removeForId(keyId) || []); - result = result.concat(this.privateKeys.removeForId(keyId) || []); - return result.length ? result : null; -}; - -/** - * Get all public and private keys - * @returns {Array} all keys - */ -Keyring.prototype.getAllKeys = function () { - return this.publicKeys.keys.concat(this.privateKeys.keys); -}; - -/** - * Array of keys - * @param {Array} keys The keys to store in this array - */ -function KeyArray(keys) { - this.keys = keys; +function createWrappingReadableSource(readable, _a) { + var _b = _a === void 0 ? {} : _a, type = _b.type; + assert$1(isReadableStream(readable)); + assert$1(readable.locked === false); + type = parseReadableType(type); + var source; + if (type === 'bytes') { + source = new WrappingReadableByteStreamSource(readable); + } + else { + source = new WrappingReadableStreamDefaultSource(readable); + } + return source; } - -/** - * Searches all keys in the KeyArray matching the address or address part of the user ids - * @param {String} email email address to search for - * @returns {Array} The public keys associated with provided email address. - */ -KeyArray.prototype.getForAddress = function (email) { - const results = []; - for (let i = 0; i < this.keys.length; i++) { - if (emailCheck(email, this.keys[i])) { - results.push(this.keys[i]); +function parseReadableType(type) { + var typeString = String(type); + if (typeString === 'bytes') { + return typeString; } - } - return results; -}; - -/** - * Checks a key to see if it matches the specified email address - * @private - * @param {String} email email address to search for - * @param {module:key.Key} key The key to be checked. - * @returns {Boolean} True if the email address is defined in the specified key - */ -function emailCheck(email, key) { - email = email.toLowerCase(); - // escape email before using in regular expression - const emailEsc = email.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); - const emailRegex = new RegExp('<' + emailEsc + '>'); - const userIds = key.getUserIds(); - for (let i = 0; i < userIds.length; i++) { - const userId = userIds[i].toLowerCase(); - if (email === userId || emailRegex.test(userId)) { - return true; + else if (type === undefined) { + return type; + } + else { + throw new RangeError('Invalid type is specified'); } - } - return false; } +var AbstractWrappingReadableStreamSource = /** @class */ (function () { + function AbstractWrappingReadableStreamSource(underlyingStream) { + this._underlyingReader = undefined; + this._readerMode = undefined; + this._readableStreamController = undefined; + this._pendingRead = undefined; + this._underlyingStream = underlyingStream; + // always keep a reader attached to detect close/error + this._attachDefaultReader(); + } + AbstractWrappingReadableStreamSource.prototype.start = function (controller) { + this._readableStreamController = controller; + }; + AbstractWrappingReadableStreamSource.prototype.cancel = function (reason) { + assert$1(this._underlyingReader !== undefined); + return this._underlyingReader.cancel(reason); + }; + AbstractWrappingReadableStreamSource.prototype._attachDefaultReader = function () { + if (this._readerMode === "default" /* DEFAULT */) { + return; + } + this._detachReader(); + var reader = this._underlyingStream.getReader(); + this._readerMode = "default" /* DEFAULT */; + this._attachReader(reader); + }; + AbstractWrappingReadableStreamSource.prototype._attachReader = function (reader) { + var _this = this; + assert$1(this._underlyingReader === undefined); + this._underlyingReader = reader; + var closed = this._underlyingReader.closed; + if (!closed) { + return; + } + closed + .then(function () { return _this._finishPendingRead(); }) + .then(function () { + if (reader === _this._underlyingReader) { + _this._readableStreamController.close(); + } + }, function (reason) { + if (reader === _this._underlyingReader) { + _this._readableStreamController.error(reason); + } + }) + .catch(noop$1); + }; + AbstractWrappingReadableStreamSource.prototype._detachReader = function () { + if (this._underlyingReader === undefined) { + return; + } + this._underlyingReader.releaseLock(); + this._underlyingReader = undefined; + this._readerMode = undefined; + }; + AbstractWrappingReadableStreamSource.prototype._pullWithDefaultReader = function () { + var _this = this; + this._attachDefaultReader(); + // TODO Backpressure? + var read = this._underlyingReader.read() + .then(function (result) { + var controller = _this._readableStreamController; + if (result.done) { + _this._tryClose(); + } + else { + controller.enqueue(result.value); + } + }); + this._setPendingRead(read); + return read; + }; + AbstractWrappingReadableStreamSource.prototype._tryClose = function () { + try { + this._readableStreamController.close(); + } + catch (_a) { + // already errored or closed + } + }; + AbstractWrappingReadableStreamSource.prototype._setPendingRead = function (readPromise) { + var _this = this; + var pendingRead; + var finishRead = function () { + if (_this._pendingRead === pendingRead) { + _this._pendingRead = undefined; + } + }; + this._pendingRead = pendingRead = readPromise.then(finishRead, finishRead); + }; + AbstractWrappingReadableStreamSource.prototype._finishPendingRead = function () { + var _this = this; + if (!this._pendingRead) { + return undefined; + } + var afterRead = function () { return _this._finishPendingRead(); }; + return this._pendingRead.then(afterRead, afterRead); + }; + return AbstractWrappingReadableStreamSource; +}()); +var WrappingReadableStreamDefaultSource = /** @class */ (function (_super) { + __extends(WrappingReadableStreamDefaultSource, _super); + function WrappingReadableStreamDefaultSource() { + return _super !== null && _super.apply(this, arguments) || this; + } + WrappingReadableStreamDefaultSource.prototype.pull = function () { + return this._pullWithDefaultReader(); + }; + return WrappingReadableStreamDefaultSource; +}(AbstractWrappingReadableStreamSource)); +function toUint8Array(view) { + return new Uint8Array(view.buffer, view.byteOffset, view.byteLength); +} +function copyArrayBufferView(from, to) { + var fromArray = toUint8Array(from); + var toArray = toUint8Array(to); + toArray.set(fromArray, 0); +} +var WrappingReadableByteStreamSource = /** @class */ (function (_super) { + __extends(WrappingReadableByteStreamSource, _super); + function WrappingReadableByteStreamSource(underlyingStream) { + var _this = this; + var supportsByob = supportsByobReader(underlyingStream); + _this = _super.call(this, underlyingStream) || this; + _this._supportsByob = supportsByob; + return _this; + } + Object.defineProperty(WrappingReadableByteStreamSource.prototype, "type", { + get: function () { + return 'bytes'; + }, + enumerable: false, + configurable: true + }); + WrappingReadableByteStreamSource.prototype._attachByobReader = function () { + if (this._readerMode === "byob" /* BYOB */) { + return; + } + assert$1(this._supportsByob); + this._detachReader(); + var reader = this._underlyingStream.getReader({ mode: 'byob' }); + this._readerMode = "byob" /* BYOB */; + this._attachReader(reader); + }; + WrappingReadableByteStreamSource.prototype.pull = function () { + if (this._supportsByob) { + var byobRequest = this._readableStreamController.byobRequest; + if (byobRequest) { + return this._pullWithByobRequest(byobRequest); + } + } + return this._pullWithDefaultReader(); + }; + WrappingReadableByteStreamSource.prototype._pullWithByobRequest = function (byobRequest) { + var _this = this; + this._attachByobReader(); + // reader.read(view) detaches the input view, therefore we cannot pass byobRequest.view directly + // create a separate buffer to read into, then copy that to byobRequest.view + var buffer = new Uint8Array(byobRequest.view.byteLength); + // TODO Backpressure? + var read = this._underlyingReader.read(buffer) + .then(function (result) { + _this._readableStreamController; + if (result.done) { + _this._tryClose(); + byobRequest.respond(0); + } + else { + copyArrayBufferView(result.value, byobRequest.view); + byobRequest.respond(result.value.byteLength); + } + }); + this._setPendingRead(read); + return read; + }; + return WrappingReadableByteStreamSource; +}(AbstractWrappingReadableStreamSource)); -/** - * Checks a key to see if it matches the specified keyid - * @private - * @param {String} keyId provided as string of lowercase hex number - * withouth 0x prefix (can be 16-character key ID or fingerprint) - * @param {module:key.Key|module:key.SubKey} key The key to be checked - * @returns {Boolean} True if key has the specified keyid - */ -function keyIdCheck(keyId, key) { - if (keyId.length === 16) { - return keyId === key.getKeyId().toHex(); - } - return keyId === key.getFingerprint(); +function createWritableStreamWrapper(ctor) { + assert$1(isWritableStreamConstructor(ctor)); + return function (writable) { + if (writable.constructor === ctor) { + return writable; + } + var sink = createWrappingWritableSink(writable); + return new ctor(sink); + }; } +function createWrappingWritableSink(writable) { + assert$1(isWritableStream(writable)); + assert$1(writable.locked === false); + var writer = writable.getWriter(); + return new WrappingWritableStreamSink(writer); +} +var WrappingWritableStreamSink = /** @class */ (function () { + function WrappingWritableStreamSink(underlyingWriter) { + var _this = this; + this._writableStreamController = undefined; + this._pendingWrite = undefined; + this._state = "writable" /* WRITABLE */; + this._storedError = undefined; + this._underlyingWriter = underlyingWriter; + this._errorPromise = new Promise(function (resolve, reject) { + _this._errorPromiseReject = reject; + }); + this._errorPromise.catch(noop$1); + } + WrappingWritableStreamSink.prototype.start = function (controller) { + var _this = this; + this._writableStreamController = controller; + this._underlyingWriter.closed + .then(function () { + _this._state = "closed" /* CLOSED */; + }) + .catch(function (reason) { return _this._finishErroring(reason); }); + }; + WrappingWritableStreamSink.prototype.write = function (chunk) { + var _this = this; + var writer = this._underlyingWriter; + // Detect past errors + if (writer.desiredSize === null) { + return writer.ready; + } + var writeRequest = writer.write(chunk); + // Detect future errors + writeRequest.catch(function (reason) { return _this._finishErroring(reason); }); + writer.ready.catch(function (reason) { return _this._startErroring(reason); }); + // Reject write when errored + var write = Promise.race([writeRequest, this._errorPromise]); + this._setPendingWrite(write); + return write; + }; + WrappingWritableStreamSink.prototype.close = function () { + var _this = this; + if (this._pendingWrite === undefined) { + return this._underlyingWriter.close(); + } + return this._finishPendingWrite().then(function () { return _this.close(); }); + }; + WrappingWritableStreamSink.prototype.abort = function (reason) { + if (this._state === "errored" /* ERRORED */) { + return undefined; + } + var writer = this._underlyingWriter; + return writer.abort(reason); + }; + WrappingWritableStreamSink.prototype._setPendingWrite = function (writePromise) { + var _this = this; + var pendingWrite; + var finishWrite = function () { + if (_this._pendingWrite === pendingWrite) { + _this._pendingWrite = undefined; + } + }; + this._pendingWrite = pendingWrite = writePromise.then(finishWrite, finishWrite); + }; + WrappingWritableStreamSink.prototype._finishPendingWrite = function () { + var _this = this; + if (this._pendingWrite === undefined) { + return Promise.resolve(); + } + var afterWrite = function () { return _this._finishPendingWrite(); }; + return this._pendingWrite.then(afterWrite, afterWrite); + }; + WrappingWritableStreamSink.prototype._startErroring = function (reason) { + var _this = this; + if (this._state === "writable" /* WRITABLE */) { + this._state = "erroring" /* ERRORING */; + this._storedError = reason; + var afterWrite = function () { return _this._finishErroring(reason); }; + if (this._pendingWrite === undefined) { + afterWrite(); + } + else { + this._finishPendingWrite().then(afterWrite, afterWrite); + } + this._writableStreamController.error(reason); + } + }; + WrappingWritableStreamSink.prototype._finishErroring = function (reason) { + if (this._state === "writable" /* WRITABLE */) { + this._startErroring(reason); + } + if (this._state === "erroring" /* ERRORING */) { + this._state = "errored" /* ERRORED */; + this._errorPromiseReject(this._storedError); + } + }; + return WrappingWritableStreamSink; +}()); -/** - * Searches the KeyArray for a key having the specified key id - * @param {String} keyId provided as string of lowercase hex number - * withouth 0x prefix (can be 16-character key ID or fingerprint) - * @param {Boolean} deep if true search also in subkeys - * @returns {module:key.Key|null} key found or null - */ -KeyArray.prototype.getForId = function (keyId, deep) { - for (let i = 0; i < this.keys.length; i++) { - if (keyIdCheck(keyId, this.keys[i])) { - return this.keys[i]; - } - if (deep && this.keys[i].subKeys.length) { - for (let j = 0; j < this.keys[i].subKeys.length; j++) { - if (keyIdCheck(keyId, this.keys[i].subKeys[j])) { - return this.keys[i]; +function createTransformStreamWrapper(ctor) { + assert$1(isTransformStreamConstructor(ctor)); + return function (transform) { + if (transform.constructor === ctor) { + return transform; } - } + var transformer = createWrappingTransformer(transform); + return new ctor(transformer); + }; +} +function createWrappingTransformer(transform) { + assert$1(isTransformStream(transform)); + var readable = transform.readable, writable = transform.writable; + assert$1(readable.locked === false); + assert$1(writable.locked === false); + var reader = readable.getReader(); + var writer; + try { + writer = writable.getWriter(); } - } - return null; -}; - -/** - * Imports a key from an ascii armored message - * @param {String} armored message to read the keys/key from - * @returns {Promise|null>} array of error objects or null - * @async - */ -KeyArray.prototype.importKey = async function (armored) { - const imported = await (0, _key.readArmored)(armored); - for (let i = 0; i < imported.keys.length; i++) { - const key = imported.keys[i]; - // check if key already in key array - const keyidHex = key.getKeyId().toHex(); - const keyFound = this.getForId(keyidHex); - if (keyFound) { - await keyFound.update(key); - } else { - this.push(key); + catch (e) { + reader.releaseLock(); // do not leak reader + throw e; } - } - return imported.err ? imported.err : null; -}; - -/** - * Add key to KeyArray - * @param {module:key.Key} key The key that will be added to the keyring - * @returns {Number} The new length of the KeyArray - */ -KeyArray.prototype.push = function (key) { - return this.keys.push(key); -}; - -/** - * Removes a key with the specified keyid from the keyring - * @param {String} keyId provided as string of lowercase hex number - * withouth 0x prefix (can be 16-character key ID or fingerprint) - * @returns {module:key.Key|null} The key object which has been removed or null - */ -KeyArray.prototype.removeForId = function (keyId) { - for (let i = 0; i < this.keys.length; i++) { - if (keyIdCheck(keyId, this.keys[i])) { - return this.keys.splice(i, 1)[0]; + return new WrappingTransformStreamTransformer(reader, writer); +} +var WrappingTransformStreamTransformer = /** @class */ (function () { + function WrappingTransformStreamTransformer(reader, writer) { + var _this = this; + this._transformStreamController = undefined; + this._onRead = function (result) { + if (result.done) { + return; + } + _this._transformStreamController.enqueue(result.value); + return _this._reader.read().then(_this._onRead); + }; + this._onError = function (reason) { + _this._flushReject(reason); + _this._transformStreamController.error(reason); + _this._reader.cancel(reason).catch(noop$1); + _this._writer.abort(reason).catch(noop$1); + }; + this._onTerminate = function () { + _this._flushResolve(); + _this._transformStreamController.terminate(); + var error = new TypeError('TransformStream terminated'); + _this._writer.abort(error).catch(noop$1); + }; + this._reader = reader; + this._writer = writer; + this._flushPromise = new Promise(function (resolve, reject) { + _this._flushResolve = resolve; + _this._flushReject = reject; + }); } - } - return null; -}; - -exports.default = Keyring; - -},{"../key":116,"./localstore":119}],119:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true + WrappingTransformStreamTransformer.prototype.start = function (controller) { + this._transformStreamController = controller; + this._reader.read() + .then(this._onRead) + .then(this._onTerminate, this._onError); + var readerClosed = this._reader.closed; + if (readerClosed) { + readerClosed + .then(this._onTerminate, this._onError); + } + }; + WrappingTransformStreamTransformer.prototype.transform = function (chunk) { + return this._writer.write(chunk); + }; + WrappingTransformStreamTransformer.prototype.flush = function () { + var _this = this; + return this._writer.close() + .then(function () { return _this._flushPromise; }); + }; + return WrappingTransformStreamTransformer; +}()); + +var webStreamsAdapter = /*#__PURE__*/Object.freeze({ + __proto__: null, + createReadableStreamWrapper: createReadableStreamWrapper, + createTransformStreamWrapper: createTransformStreamWrapper, + createWrappingReadableSource: createWrappingReadableSource, + createWrappingTransformer: createWrappingTransformer, + createWrappingWritableSink: createWrappingWritableSink, + createWritableStreamWrapper: createWritableStreamWrapper }); -var _webStreamTools = require('web-stream-tools'); - -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); - -var _config = require('../config'); - -var _config2 = _interopRequireDefault(_config); - -var _key = require('../key'); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * The class that deals with storage of the keyring. - * Currently the only option is to use HTML5 local storage. - * @constructor - * @param {String} prefix prefix for itemnames in localstore - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +var bn = createCommonjsModule(function (module) { +(function (module, exports) { -/** - * @fileoverview Provides the LocalStore class - * @requires web-stream-tools - * @requires config - * @requires key - * @requires util - * @module keyring/localstore - */ + // Utils + function assert (val, msg) { + if (!val) throw new Error(msg || 'Assertion failed'); + } -function LocalStore(prefix) { - prefix = prefix || 'openpgp-'; - this.publicKeysItem = prefix + this.publicKeysItem; - this.privateKeysItem = prefix + this.privateKeysItem; - if (typeof window !== 'undefined' && window.localStorage) { - this.storage = window.localStorage; - } else { - this.storage = new (require('node-localstorage').LocalStorage)(_config2.default.node_store); + // Could use `inherits` module, but don't want to move from single file + // architecture yet. + function inherits (ctor, superCtor) { + ctor.super_ = superCtor; + var TempCtor = function () {}; + TempCtor.prototype = superCtor.prototype; + ctor.prototype = new TempCtor(); + ctor.prototype.constructor = ctor; } -} -/* - * Declare the localstore itemnames - */ -LocalStore.prototype.publicKeysItem = 'public-keys'; -LocalStore.prototype.privateKeysItem = 'private-keys'; + // BN -/** - * Load the public keys from HTML5 local storage. - * @returns {Array} array of keys retrieved from localstore - * @async - */ -LocalStore.prototype.loadPublic = async function () { - return loadKeys(this.storage, this.publicKeysItem); -}; + function BN (number, base, endian) { + if (BN.isBN(number)) { + return number; + } -/** - * Load the private keys from HTML5 local storage. - * @returns {Array} array of keys retrieved from localstore - * @async - */ -LocalStore.prototype.loadPrivate = async function () { - return loadKeys(this.storage, this.privateKeysItem); -}; + this.negative = 0; + this.words = null; + this.length = 0; -async function loadKeys(storage, itemname) { - const armoredKeys = JSON.parse(storage.getItem(itemname)); - const keys = []; - if (armoredKeys !== null && armoredKeys.length !== 0) { - let key; - for (let i = 0; i < armoredKeys.length; i++) { - key = await (0, _key.readArmored)(armoredKeys[i]); - if (!key.err) { - keys.push(key.keys[0]); - } else { - _util2.default.print_debug("Error reading armored key from keyring index: " + i); + // Reduction context + this.red = null; + + if (number !== null) { + if (base === 'le' || base === 'be') { + endian = base; + base = 10; } + + this._init(number || 0, base || 10, endian || 'be'); } } - return keys; -} - -/** - * Saves the current state of the public keys to HTML5 local storage. - * The key array gets stringified using JSON - * @param {Array} keys array of keys to save in localstore - * @async - */ -LocalStore.prototype.storePublic = async function (keys) { - await storeKeys(this.storage, this.publicKeysItem, keys); -}; - -/** - * Saves the current state of the private keys to HTML5 local storage. - * The key array gets stringified using JSON - * @param {Array} keys array of keys to save in localstore - * @async - */ -LocalStore.prototype.storePrivate = async function (keys) { - await storeKeys(this.storage, this.privateKeysItem, keys); -}; - -async function storeKeys(storage, itemname, keys) { - if (keys.length) { - const armoredKeys = await Promise.all(keys.map(key => _webStreamTools2.default.readToEnd(key.armor()))); - storage.setItem(itemname, JSON.stringify(armoredKeys)); + if (typeof module === 'object') { + module.exports = BN; } else { - storage.removeItem(itemname); + exports.BN = BN; } -} - -exports.default = LocalStore; - -},{"../config":79,"../key":116,"../util":152,"node-localstorage":"node-localstorage","web-stream-tools":75}],120:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.Message = Message; -exports.encryptSessionKey = encryptSessionKey; -exports.createSignaturePackets = createSignaturePackets; -exports.createVerificationObjects = createVerificationObjects; -exports.readArmored = readArmored; -exports.read = read; -exports.fromText = fromText; -exports.fromBinary = fromBinary; - -var _webStreamTools = require('web-stream-tools'); - -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); -var _armor = require('./encoding/armor'); + BN.BN = BN; + BN.wordSize = 26; -var _armor2 = _interopRequireDefault(_armor); + var Buffer; + try { + Buffer = buffer__default['default'].Buffer; + } catch (e) { + } -var _keyid = require('./type/keyid'); + BN.isBN = function isBN (num) { + if (num instanceof BN) { + return true; + } -var _keyid2 = _interopRequireDefault(_keyid); + return num !== null && typeof num === 'object' && + num.constructor.wordSize === BN.wordSize && Array.isArray(num.words); + }; -var _config = require('./config'); + BN.max = function max (left, right) { + if (left.cmp(right) > 0) return left; + return right; + }; -var _config2 = _interopRequireDefault(_config); + BN.min = function min (left, right) { + if (left.cmp(right) < 0) return left; + return right; + }; -var _crypto = require('./crypto'); + BN.prototype._init = function init (number, base, endian) { + if (typeof number === 'number') { + return this._initNumber(number, base, endian); + } -var _crypto2 = _interopRequireDefault(_crypto); + if (typeof number === 'object') { + return this._initArray(number, base, endian); + } -var _enums = require('./enums'); + if (base === 'hex') { + base = 16; + } + assert(base === (base | 0) && base >= 2 && base <= 36); -var _enums2 = _interopRequireDefault(_enums); + number = number.toString().replace(/\s+/g, ''); + var start = 0; + if (number[0] === '-') { + start++; + } -var _util = require('./util'); + if (base === 16) { + this._parseHex(number, start); + } else { + this._parseBase(number, base, start); + } -var _util2 = _interopRequireDefault(_util); + if (number[0] === '-') { + this.negative = 1; + } -var _packet = require('./packet'); + this.strip(); -var _packet2 = _interopRequireDefault(_packet); + if (endian !== 'le') return; -var _signature = require('./signature'); + this._initArray(this.toArray(), base, endian); + }; -var _key = require('./key'); + BN.prototype._initNumber = function _initNumber (number, base, endian) { + if (number < 0) { + this.negative = 1; + number = -number; + } + if (number < 0x4000000) { + this.words = [ number & 0x3ffffff ]; + this.length = 1; + } else if (number < 0x10000000000000) { + this.words = [ + number & 0x3ffffff, + (number / 0x4000000) & 0x3ffffff + ]; + this.length = 2; + } else { + assert(number < 0x20000000000000); // 2 ^ 53 (unsafe) + this.words = [ + number & 0x3ffffff, + (number / 0x4000000) & 0x3ffffff, + 1 + ]; + this.length = 3; + } -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + if (endian !== 'le') return; -/** - * @class - * @classdesc Class that represents an OpenPGP message. - * Can be an encrypted message, signed message, compressed message or literal message - * @param {module:packet.List} packetlist The packets that form this message - * See {@link https://tools.ietf.org/html/rfc4880#section-11.3} - */ + // Reverse the bytes + this._initArray(this.toArray(), base, endian); + }; -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + BN.prototype._initArray = function _initArray (number, base, endian) { + // Perhaps a Uint8Array + assert(typeof number.length === 'number'); + if (number.length <= 0) { + this.words = [ 0 ]; + this.length = 1; + return this; + } -/** - * @requires web-stream-tools - * @requires encoding/armor - * @requires type/keyid - * @requires config - * @requires crypto - * @requires enums - * @requires util - * @requires packet - * @requires signature - * @requires key - * @module message - */ + this.length = Math.ceil(number.length / 3); + this.words = new Array(this.length); + for (var i = 0; i < this.length; i++) { + this.words[i] = 0; + } -function Message(packetlist) { - if (!(this instanceof Message)) { - return new Message(packetlist); - } - this.packets = packetlist || new _packet2.default.List(); -} + var j, w; + var off = 0; + if (endian === 'be') { + for (i = number.length - 1, j = 0; i >= 0; i -= 3) { + w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16); + this.words[j] |= (w << off) & 0x3ffffff; + this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; + off += 24; + if (off >= 26) { + off -= 26; + j++; + } + } + } else if (endian === 'le') { + for (i = 0, j = 0; i < number.length; i += 3) { + w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16); + this.words[j] |= (w << off) & 0x3ffffff; + this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; + off += 24; + if (off >= 26) { + off -= 26; + j++; + } + } + } + return this.strip(); + }; -/** - * Returns the key IDs of the keys to which the session key is encrypted - * @returns {Array} array of keyid objects - */ -Message.prototype.getEncryptionKeyIds = function () { - const keyIds = []; - const pkESKeyPacketlist = this.packets.filterByTag(_enums2.default.packet.publicKeyEncryptedSessionKey); - pkESKeyPacketlist.forEach(function (packet) { - keyIds.push(packet.publicKeyId); - }); - return keyIds; -}; + function parseHex (str, start, end) { + var r = 0; + var len = Math.min(str.length, end); + for (var i = start; i < len; i++) { + var c = str.charCodeAt(i) - 48; -/** - * Returns the key IDs of the keys that signed the message - * @returns {Array} array of keyid objects - */ -Message.prototype.getSigningKeyIds = function () { - const keyIds = []; - const msg = this.unwrapCompressed(); - // search for one pass signatures - const onePassSigList = msg.packets.filterByTag(_enums2.default.packet.onePassSignature); - onePassSigList.forEach(function (packet) { - keyIds.push(packet.issuerKeyId); - }); - // if nothing found look for signature packets - if (!keyIds.length) { - const signatureList = msg.packets.filterByTag(_enums2.default.packet.signature); - signatureList.forEach(function (packet) { - keyIds.push(packet.issuerKeyId); - }); - } - return keyIds; -}; + r <<= 4; -/** - * Decrypt the message. Either a private key, a session key, or a password must be specified. - * @param {Array} privateKeys (optional) private keys with decrypted secret data - * @param {Array} passwords (optional) passwords used to decrypt - * @param {Array} sessionKeys (optional) session keys in the form: { data:Uint8Array, algorithm:String, [aeadAlgorithm:String] } - * @param {Boolean} streaming (optional) whether to process data as a stream - * @returns {Promise} new message with decrypted content - * @async - */ -Message.prototype.decrypt = async function (privateKeys, passwords, sessionKeys, streaming) { - const keyObjs = sessionKeys || (await this.decryptSessionKeys(privateKeys, passwords)); + // 'a' - 'f' + if (c >= 49 && c <= 54) { + r |= c - 49 + 0xa; - const symEncryptedPacketlist = this.packets.filterByTag(_enums2.default.packet.symmetricallyEncrypted, _enums2.default.packet.symEncryptedIntegrityProtected, _enums2.default.packet.symEncryptedAEADProtected); + // 'A' - 'F' + } else if (c >= 17 && c <= 22) { + r |= c - 17 + 0xa; - if (symEncryptedPacketlist.length === 0) { - return this; + // '0' - '9' + } else { + r |= c & 0xf; + } + } + return r; } - const symEncryptedPacket = symEncryptedPacketlist[0]; - let exception = null; - const decryptedPromise = Promise.all(keyObjs.map(async keyObj => { - if (!keyObj || !_util2.default.isUint8Array(keyObj.data) || !_util2.default.isString(keyObj.algorithm)) { - throw new Error('Invalid session key for decryption.'); + BN.prototype._parseHex = function _parseHex (number, start) { + // Create possibly bigger array to ensure that it fits the number + this.length = Math.ceil((number.length - start) / 6); + this.words = new Array(this.length); + for (var i = 0; i < this.length; i++) { + this.words[i] = 0; } - try { - await symEncryptedPacket.decrypt(keyObj.algorithm, keyObj.data, streaming); - } catch (e) { - _util2.default.print_debug_error(e); - exception = e; + var j, w; + // Scan 24-bit chunks and add them to the number + var off = 0; + for (i = number.length - 6, j = 0; i >= start; i -= 6) { + w = parseHex(number, i, i + 6); + this.words[j] |= (w << off) & 0x3ffffff; + // NOTE: `0x3fffff` is intentional here, 26bits max shift + 24bit hex limb + this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; + off += 24; + if (off >= 26) { + off -= 26; + j++; + } } - })); - // We don't await stream.cancel here because it only returns when the other copy is canceled too. - _webStreamTools2.default.cancel(symEncryptedPacket.encrypted); // Don't keep copy of encrypted data in memory. - symEncryptedPacket.encrypted = null; - await decryptedPromise; + if (i + 6 !== start) { + w = parseHex(number, start, i + 6); + this.words[j] |= (w << off) & 0x3ffffff; + this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; + } + this.strip(); + }; - if (!symEncryptedPacket.packets || !symEncryptedPacket.packets.length) { - throw exception || new Error('Decryption failed.'); - } + function parseBase (str, start, end, mul) { + var r = 0; + var len = Math.min(str.length, end); + for (var i = start; i < len; i++) { + var c = str.charCodeAt(i) - 48; - const resultMsg = new Message(symEncryptedPacket.packets); - symEncryptedPacket.packets = new _packet2.default.List(); // remove packets after decryption + r *= mul; - return resultMsg; -}; + // 'a' + if (c >= 49) { + r += c - 49 + 0xa; -/** - * Decrypt encrypted session keys either with private keys or passwords. - * @param {Array} privateKeys (optional) private keys with decrypted secret data - * @param {Array} passwords (optional) passwords used to decrypt - * @returns {Promise>} array of object with potential sessionKey, algorithm pairs - * @async - */ -Message.prototype.decryptSessionKeys = async function (privateKeys, passwords) { - let keyPackets = []; + // 'A' + } else if (c >= 17) { + r += c - 17 + 0xa; - let exception; - if (passwords) { - const symESKeyPacketlist = this.packets.filterByTag(_enums2.default.packet.symEncryptedSessionKey); - if (!symESKeyPacketlist) { - throw new Error('No symmetrically encrypted session key packet found.'); - } - await Promise.all(passwords.map(async function (password, i) { - let packets; - if (i) { - packets = new _packet2.default.List(); - await packets.read(symESKeyPacketlist.write()); + // '0' - '9' } else { - packets = symESKeyPacketlist; + r += c; } - await Promise.all(packets.map(async function (keyPacket) { - try { - await keyPacket.decrypt(password); - keyPackets.push(keyPacket); - } catch (err) { - _util2.default.print_debug_error(err); - } - })); - })); - } else if (privateKeys) { - const pkESKeyPacketlist = this.packets.filterByTag(_enums2.default.packet.publicKeyEncryptedSessionKey); - if (!pkESKeyPacketlist) { - throw new Error('No public key encrypted session key packet found.'); - } - await Promise.all(pkESKeyPacketlist.map(async function (keyPacket) { - await Promise.all(privateKeys.map(async function (privateKey) { - const primaryUser = await privateKey.getPrimaryUser(); // TODO: Pass userId from somewhere. - let algos = [_enums2.default.symmetric.aes256, // Old OpenPGP.js default fallback - _enums2.default.symmetric.aes128, // RFC4880bis fallback - _enums2.default.symmetric.tripledes, // RFC4880 fallback - _enums2.default.symmetric.cast5 // Golang OpenPGP fallback - ]; - if (primaryUser && primaryUser.selfCertification.preferredSymmetricAlgorithms) { - algos = algos.concat(primaryUser.selfCertification.preferredSymmetricAlgorithms); - } - - const privateKeyPackets = privateKey.getKeys(keyPacket.publicKeyId).map(key => key.keyPacket); - await Promise.all(privateKeyPackets.map(async function (privateKeyPacket) { - if (!privateKeyPacket) { - return; - } - if (!privateKeyPacket.isDecrypted()) { - throw new Error('Private key is not decrypted.'); - } - try { - await keyPacket.decrypt(privateKeyPacket); - if (!algos.includes(_enums2.default.write(_enums2.default.symmetric, keyPacket.sessionKeyAlgorithm))) { - throw new Error('A non-preferred symmetric algorithm was used.'); - } - keyPackets.push(keyPacket); - } catch (err) { - _util2.default.print_debug_error(err); - exception = err; - } - })); - })); - _webStreamTools2.default.cancel(keyPacket.encrypted); // Don't keep copy of encrypted data in memory. - keyPacket.encrypted = null; - })); - } else { - throw new Error('No key or password specified.'); - } - - if (keyPackets.length) { - // Return only unique session keys - if (keyPackets.length > 1) { - const seen = {}; - keyPackets = keyPackets.filter(function (item) { - const k = item.sessionKeyAlgorithm + _util2.default.Uint8Array_to_str(item.sessionKey); - if (seen.hasOwnProperty(k)) { - return false; - } - seen[k] = true; - return true; - }); } - - return keyPackets.map(packet => ({ data: packet.sessionKey, algorithm: packet.sessionKeyAlgorithm })); + return r; } - throw exception || new Error('Session key decryption failed.'); -}; - -/** - * Get literal data that is the body of the message - * @returns {(Uint8Array|null)} literal body of the message as Uint8Array - */ -Message.prototype.getLiteralData = function () { - const msg = this.unwrapCompressed(); - const literal = msg.packets.findPacket(_enums2.default.packet.literal); - return literal && literal.getBytes() || null; -}; -/** - * Get filename from literal data packet - * @returns {(String|null)} filename of literal data packet as string - */ -Message.prototype.getFilename = function () { - const msg = this.unwrapCompressed(); - const literal = msg.packets.findPacket(_enums2.default.packet.literal); - return literal && literal.getFilename() || null; -}; + BN.prototype._parseBase = function _parseBase (number, base, start) { + // Initialize as zero + this.words = [ 0 ]; + this.length = 1; -/** - * Get literal data as text - * @returns {(String|null)} literal body of the message interpreted as text - */ -Message.prototype.getText = function () { - const msg = this.unwrapCompressed(); - const literal = msg.packets.findPacket(_enums2.default.packet.literal); - if (literal) { - return literal.getText(); - } - return null; -}; + // Find length of limb in base + for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) { + limbLen++; + } + limbLen--; + limbPow = (limbPow / base) | 0; -/** - * Encrypt the message either with public keys, passwords, or both at once. - * @param {Array} keys (optional) public key(s) for message encryption - * @param {Array} passwords (optional) password(s) for message encryption - * @param {Object} sessionKey (optional) session key in the form: { data:Uint8Array, algorithm:String, [aeadAlgorithm:String] } - * @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs - * @param {Date} date (optional) override the creation date of the literal package - * @param {Array} userIds (optional) user IDs to encrypt for, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }] - * @param {Boolean} streaming (optional) whether to process data as a stream - * @returns {Promise} new message with encrypted content - * @async - */ -Message.prototype.encrypt = async function (keys, passwords, sessionKey, wildcard = false, date = new Date(), userIds = [], streaming) { - let symAlgo; - let aeadAlgo; - let symEncryptedPacket; - - if (sessionKey) { - if (!_util2.default.isUint8Array(sessionKey.data) || !_util2.default.isString(sessionKey.algorithm)) { - throw new Error('Invalid session key for encryption.'); - } - symAlgo = sessionKey.algorithm; - aeadAlgo = sessionKey.aeadAlgorithm; - sessionKey = sessionKey.data; - } else if (keys && keys.length) { - symAlgo = _enums2.default.read(_enums2.default.symmetric, (await (0, _key.getPreferredAlgo)('symmetric', keys, date, userIds))); - if (_config2.default.aead_protect && (await (0, _key.isAeadSupported)(keys, date, userIds))) { - aeadAlgo = _enums2.default.read(_enums2.default.aead, (await (0, _key.getPreferredAlgo)('aead', keys, date, userIds))); - } - } else if (passwords && passwords.length) { - symAlgo = _enums2.default.read(_enums2.default.symmetric, _config2.default.encryption_cipher); - aeadAlgo = _enums2.default.read(_enums2.default.aead, _config2.default.aead_mode); - } else { - throw new Error('No keys, passwords, or session key provided.'); - } + var total = number.length - start; + var mod = total % limbLen; + var end = Math.min(total, total - mod) + start; - if (!sessionKey) { - sessionKey = await _crypto2.default.generateSessionKey(symAlgo); - } + var word = 0; + for (var i = start; i < end; i += limbLen) { + word = parseBase(number, i, i + limbLen, base); - const msg = await encryptSessionKey(sessionKey, symAlgo, aeadAlgo, keys, passwords, wildcard, date, userIds); + this.imuln(limbPow); + if (this.words[0] + word < 0x4000000) { + this.words[0] += word; + } else { + this._iaddn(word); + } + } - if (_config2.default.aead_protect && aeadAlgo) { - symEncryptedPacket = new _packet2.default.SymEncryptedAEADProtected(); - symEncryptedPacket.aeadAlgorithm = aeadAlgo; - } else if (_config2.default.integrity_protect) { - symEncryptedPacket = new _packet2.default.SymEncryptedIntegrityProtected(); - } else { - symEncryptedPacket = new _packet2.default.SymmetricallyEncrypted(); - } - symEncryptedPacket.packets = this.packets; + if (mod !== 0) { + var pow = 1; + word = parseBase(number, i, number.length, base); - await symEncryptedPacket.encrypt(symAlgo, sessionKey, streaming); + for (i = 0; i < mod; i++) { + pow *= base; + } - msg.packets.push(symEncryptedPacket); - symEncryptedPacket.packets = new _packet2.default.List(); // remove packets after encryption - return { - message: msg, - sessionKey: { - data: sessionKey, - algorithm: symAlgo, - aeadAlgorithm: aeadAlgo + this.imuln(pow); + if (this.words[0] + word < 0x4000000) { + this.words[0] += word; + } else { + this._iaddn(word); + } } }; -}; -/** - * Encrypt a session key either with public keys, passwords, or both at once. - * @param {Uint8Array} sessionKey session key for encryption - * @param {String} symAlgo session key algorithm - * @param {String} aeadAlgo (optional) aead algorithm, e.g. 'eax' or 'ocb' - * @param {Array} publicKeys (optional) public key(s) for message encryption - * @param {Array} passwords (optional) for message encryption - * @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs - * @param {Date} date (optional) override the date - * @param {Array} userIds (optional) user IDs to encrypt for, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }] - * @returns {Promise} new message with encrypted content - * @async - */ -async function encryptSessionKey(sessionKey, symAlgo, aeadAlgo, publicKeys, passwords, wildcard = false, date = new Date(), userIds = []) { - const packetlist = new _packet2.default.List(); - - if (publicKeys) { - const results = await Promise.all(publicKeys.map(async function (publicKey) { - const encryptionKey = await publicKey.getEncryptionKey(undefined, date, userIds); - if (!encryptionKey) { - throw new Error('Could not find valid key packet for encryption in key ' + publicKey.getKeyId().toHex()); - } - const pkESKeyPacket = new _packet2.default.PublicKeyEncryptedSessionKey(); - pkESKeyPacket.publicKeyId = wildcard ? _keyid2.default.wildcard() : encryptionKey.getKeyId(); - pkESKeyPacket.publicKeyAlgorithm = encryptionKey.keyPacket.algorithm; - pkESKeyPacket.sessionKey = sessionKey; - pkESKeyPacket.sessionKeyAlgorithm = symAlgo; - await pkESKeyPacket.encrypt(encryptionKey.keyPacket); - delete pkESKeyPacket.sessionKey; // delete plaintext session key after encryption - return pkESKeyPacket; - })); - packetlist.concat(results); - } - if (passwords) { - const testDecrypt = async function testDecrypt(keyPacket, password) { - try { - await keyPacket.decrypt(password); - return 1; - } catch (e) { - return 0; - } - }; + BN.prototype.copy = function copy (dest) { + dest.words = new Array(this.length); + for (var i = 0; i < this.length; i++) { + dest.words[i] = this.words[i]; + } + dest.length = this.length; + dest.negative = this.negative; + dest.red = this.red; + }; - const sum = (accumulator, currentValue) => accumulator + currentValue; + BN.prototype.clone = function clone () { + var r = new BN(null); + this.copy(r); + return r; + }; - const encryptPassword = async function encryptPassword(sessionKey, symAlgo, aeadAlgo, password) { - const symEncryptedSessionKeyPacket = new _packet2.default.SymEncryptedSessionKey(); - symEncryptedSessionKeyPacket.sessionKey = sessionKey; - symEncryptedSessionKeyPacket.sessionKeyAlgorithm = symAlgo; - if (aeadAlgo) { - symEncryptedSessionKeyPacket.aeadAlgorithm = aeadAlgo; - } - await symEncryptedSessionKeyPacket.encrypt(password); + BN.prototype._expand = function _expand (size) { + while (this.length < size) { + this.words[this.length++] = 0; + } + return this; + }; - if (_config2.default.password_collision_check) { - const results = await Promise.all(passwords.map(pwd => testDecrypt(symEncryptedSessionKeyPacket, pwd))); - if (results.reduce(sum) !== 1) { - return encryptPassword(sessionKey, symAlgo, password); - } - } + // Remove leading `0` from `this` + BN.prototype.strip = function strip () { + while (this.length > 1 && this.words[this.length - 1] === 0) { + this.length--; + } + return this._normSign(); + }; - delete symEncryptedSessionKeyPacket.sessionKey; // delete plaintext session key after encryption - return symEncryptedSessionKeyPacket; - }; + BN.prototype._normSign = function _normSign () { + // -0 = 0 + if (this.length === 1 && this.words[0] === 0) { + this.negative = 0; + } + return this; + }; - const results = await Promise.all(passwords.map(pwd => encryptPassword(sessionKey, symAlgo, aeadAlgo, pwd))); - packetlist.concat(results); - } + BN.prototype.inspect = function inspect () { + return (this.red ? ''; + }; - return new Message(packetlist); -} + /* -/** - * Sign the message (the literal data packet of the message) - * @param {Array} privateKeys private keys with decrypted secret key data for signing - * @param {Signature} signature (optional) any existing detached signature to add to the message - * @param {Date} date (optional) override the creation time of the signature - * @param {Array} userIds (optional) user IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] - * @returns {Promise} new message with signed content - * @async - */ -Message.prototype.sign = async function (privateKeys = [], signature = null, date = new Date(), userIds = []) { - const packetlist = new _packet2.default.List(); + var zeros = []; + var groupSizes = []; + var groupBases = []; - const literalDataPacket = this.packets.findPacket(_enums2.default.packet.literal); - if (!literalDataPacket) { - throw new Error('No literal data packet to sign.'); + var s = ''; + var i = -1; + while (++i < BN.wordSize) { + zeros[i] = s; + s += '0'; } - - let i; - let existingSigPacketlist; - // If data packet was created from Uint8Array, use binary, otherwise use text - const signatureType = literalDataPacket.text === null ? _enums2.default.signature.binary : _enums2.default.signature.text; - - if (signature) { - existingSigPacketlist = signature.packets.filterByTag(_enums2.default.packet.signature); - for (i = existingSigPacketlist.length - 1; i >= 0; i--) { - const signaturePacket = existingSigPacketlist[i]; - const onePassSig = new _packet2.default.OnePassSignature(); - onePassSig.signatureType = signaturePacket.signatureType; - onePassSig.hashAlgorithm = signaturePacket.hashAlgorithm; - onePassSig.publicKeyAlgorithm = signaturePacket.publicKeyAlgorithm; - onePassSig.issuerKeyId = signaturePacket.issuerKeyId; - if (!privateKeys.length && i === 0) { - onePassSig.flags = 1; - } - packetlist.push(onePassSig); + groupSizes[0] = 0; + groupSizes[1] = 0; + groupBases[0] = 0; + groupBases[1] = 0; + var base = 2 - 1; + while (++base < 36 + 1) { + var groupSize = 0; + var groupBase = 1; + while (groupBase < (1 << BN.wordSize) / base) { + groupBase *= base; + groupSize += 1; } + groupSizes[base] = groupSize; + groupBases[base] = groupBase; } - await Promise.all(Array.from(privateKeys).reverse().map(async function (privateKey, i) { - if (privateKey.isPublic()) { - throw new Error('Need private key for signing'); - } - const signingKey = await privateKey.getSigningKey(undefined, date, userIds); - if (!signingKey) { - throw new Error('Could not find valid key packet for signing in key ' + privateKey.getKeyId().toHex()); - } - const onePassSig = new _packet2.default.OnePassSignature(); - onePassSig.signatureType = signatureType; - onePassSig.hashAlgorithm = await (0, _key.getPreferredHashAlgo)(privateKey, signingKey.keyPacket, date, userIds); - onePassSig.publicKeyAlgorithm = signingKey.keyPacket.algorithm; - onePassSig.issuerKeyId = signingKey.getKeyId(); - if (i === privateKeys.length - 1) { - onePassSig.flags = 1; - } - return onePassSig; - })).then(onePassSignatureList => { - onePassSignatureList.forEach(onePassSig => packetlist.push(onePassSig)); - }); - - packetlist.push(literalDataPacket); - packetlist.concat((await createSignaturePackets(literalDataPacket, privateKeys, signature, date, false))); + */ - return new Message(packetlist); -}; + var zeros = [ + '', + '0', + '00', + '000', + '0000', + '00000', + '000000', + '0000000', + '00000000', + '000000000', + '0000000000', + '00000000000', + '000000000000', + '0000000000000', + '00000000000000', + '000000000000000', + '0000000000000000', + '00000000000000000', + '000000000000000000', + '0000000000000000000', + '00000000000000000000', + '000000000000000000000', + '0000000000000000000000', + '00000000000000000000000', + '000000000000000000000000', + '0000000000000000000000000' + ]; -/** - * Compresses the message (the literal and -if signed- signature data packets of the message) - * @param {module:enums.compression} compression compression algorithm to be used - * @returns {module:message.Message} new message with compressed content - */ -Message.prototype.compress = function (compression) { - if (compression === _enums2.default.compression.uncompressed) { - return this; - } + var groupSizes = [ + 0, 0, + 25, 16, 12, 11, 10, 9, 8, + 8, 7, 7, 7, 7, 6, 6, + 6, 6, 6, 6, 6, 5, 5, + 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5 + ]; - const compressed = new _packet2.default.Compressed(); - compressed.packets = this.packets; - compressed.algorithm = _enums2.default.read(_enums2.default.compression, compression); + var groupBases = [ + 0, 0, + 33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216, + 43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625, + 16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632, + 6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149, + 24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176 + ]; - const packetList = new _packet2.default.List(); - packetList.push(compressed); + BN.prototype.toString = function toString (base, padding) { + base = base || 10; + padding = padding | 0 || 1; - return new Message(packetList); -}; + var out; + if (base === 16 || base === 'hex') { + out = ''; + var off = 0; + var carry = 0; + for (var i = 0; i < this.length; i++) { + var w = this.words[i]; + var word = (((w << off) | carry) & 0xffffff).toString(16); + carry = (w >>> (24 - off)) & 0xffffff; + if (carry !== 0 || i !== this.length - 1) { + out = zeros[6 - word.length] + word + out; + } else { + out = word + out; + } + off += 2; + if (off >= 26) { + off -= 26; + i--; + } + } + if (carry !== 0) { + out = carry.toString(16) + out; + } + while (out.length % padding !== 0) { + out = '0' + out; + } + if (this.negative !== 0) { + out = '-' + out; + } + return out; + } -/** - * Create a detached signature for the message (the literal data packet of the message) - * @param {Array} privateKeys private keys with decrypted secret key data for signing - * @param {Signature} signature (optional) any existing detached signature - * @param {Date} date (optional) override the creation time of the signature - * @param {Array} userIds (optional) user IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] - * @returns {Promise} new detached signature of message content - * @async - */ -Message.prototype.signDetached = async function (privateKeys = [], signature = null, date = new Date(), userIds = []) { - const literalDataPacket = this.packets.findPacket(_enums2.default.packet.literal); - if (!literalDataPacket) { - throw new Error('No literal data packet to sign.'); - } - return new _signature.Signature((await createSignaturePackets(literalDataPacket, privateKeys, signature, date, userIds, true))); -}; + if (base === (base | 0) && base >= 2 && base <= 36) { + // var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base)); + var groupSize = groupSizes[base]; + // var groupBase = Math.pow(base, groupSize); + var groupBase = groupBases[base]; + out = ''; + var c = this.clone(); + c.negative = 0; + while (!c.isZero()) { + var r = c.modn(groupBase).toString(base); + c = c.idivn(groupBase); -/** - * Create signature packets for the message - * @param {module:packet.Literal} literalDataPacket the literal data packet to sign - * @param {Array} privateKeys private keys with decrypted secret key data for signing - * @param {Signature} signature (optional) any existing detached signature to append - * @param {Date} date (optional) override the creationtime of the signature - * @param {Array} userIds (optional) user IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] - * @param {Boolean} detached (optional) whether to create detached signature packets - * @returns {Promise} list of signature packets - * @async - */ -async function createSignaturePackets(literalDataPacket, privateKeys, signature = null, date = new Date(), userIds = [], detached = false) { - const packetlist = new _packet2.default.List(); + if (!c.isZero()) { + out = zeros[groupSize - r.length] + r + out; + } else { + out = r + out; + } + } + if (this.isZero()) { + out = '0' + out; + } + while (out.length % padding !== 0) { + out = '0' + out; + } + if (this.negative !== 0) { + out = '-' + out; + } + return out; + } - // If data packet was created from Uint8Array, use binary, otherwise use text - const signatureType = literalDataPacket.text === null ? _enums2.default.signature.binary : _enums2.default.signature.text; + assert(false, 'Base should be between 2 and 36'); + }; - await Promise.all(privateKeys.map(async (privateKey, i) => { - const userId = userIds[i]; - if (privateKey.isPublic()) { - throw new Error('Need private key for signing'); - } - const signingKey = await privateKey.getSigningKey(undefined, date, userId); - if (!signingKey) { - throw new Error(`Could not find valid signing key packet in key ${privateKey.getKeyId().toHex()}`); + BN.prototype.toNumber = function toNumber () { + var ret = this.words[0]; + if (this.length === 2) { + ret += this.words[1] * 0x4000000; + } else if (this.length === 3 && this.words[2] === 0x01) { + // NOTE: at this stage it is known that the top bit is set + ret += 0x10000000000000 + (this.words[1] * 0x4000000); + } else if (this.length > 2) { + assert(false, 'Number can only safely store up to 53 bits'); } - return (0, _key.createSignaturePacket)(literalDataPacket, privateKey, signingKey.keyPacket, { signatureType }, date, userId, detached); - })).then(signatureList => { - signatureList.forEach(signaturePacket => packetlist.push(signaturePacket)); - }); - - if (signature) { - const existingSigPacketlist = signature.packets.filterByTag(_enums2.default.packet.signature); - packetlist.concat(existingSigPacketlist); - } - return packetlist; -} + return (this.negative !== 0) ? -ret : ret; + }; -/** - * Verify message signatures - * @param {Array} keys array of keys to verify signatures - * @param {Date} date (optional) Verify the signature against the given date, i.e. check signature creation time < date < expiration time - * @param {Boolean} streaming (optional) whether to process data as a stream - * @returns {Promise>} list of signer's keyid and validity of signature - * @async - */ -Message.prototype.verify = async function (keys, date = new Date(), streaming) { - const msg = this.unwrapCompressed(); - const literalDataList = msg.packets.filterByTag(_enums2.default.packet.literal); - if (literalDataList.length !== 1) { - throw new Error('Can only verify message with one literal data packet.'); - } - const onePassSigList = msg.packets.filterByTag(_enums2.default.packet.onePassSignature).reverse(); - const signatureList = msg.packets.filterByTag(_enums2.default.packet.signature); - if (onePassSigList.length && !signatureList.length && msg.packets.stream) { - await Promise.all(onePassSigList.map(async onePassSig => { - onePassSig.correspondingSig = new Promise((resolve, reject) => { - onePassSig.correspondingSigResolve = resolve; - onePassSig.correspondingSigReject = reject; - }); - onePassSig.signatureData = _webStreamTools2.default.fromAsync(async () => (await onePassSig.correspondingSig).signatureData); - onePassSig.hashed = await onePassSig.hash(onePassSig.signatureType, literalDataList[0], undefined, false, streaming); - })); - msg.packets.stream = _webStreamTools2.default.transformPair(msg.packets.stream, async (readable, writable) => { - const reader = _webStreamTools2.default.getReader(readable); - const writer = _webStreamTools2.default.getWriter(writable); - try { - for (let i = 0; i < onePassSigList.length; i++) { - var _ref = await reader.read(); + BN.prototype.toJSON = function toJSON () { + return this.toString(16); + }; - const signature = _ref.value; + BN.prototype.toBuffer = function toBuffer (endian, length) { + assert(typeof Buffer !== 'undefined'); + return this.toArrayLike(Buffer, endian, length); + }; - onePassSigList[i].correspondingSigResolve(signature); - } - await reader.readToEnd(); - await writer.ready; - await writer.close(); - } catch (e) { - onePassSigList.forEach(onePassSig => { - onePassSig.correspondingSigReject(e); - }); - await writer.abort(e); - } - }); - return createVerificationObjects(onePassSigList, literalDataList, keys, date, false); - } - return createVerificationObjects(signatureList, literalDataList, keys, date, false); -}; + BN.prototype.toArray = function toArray (endian, length) { + return this.toArrayLike(Array, endian, length); + }; -/** - * Verify detached message signature - * @param {Array} keys array of keys to verify signatures - * @param {Signature} signature - * @param {Date} date Verify the signature against the given date, i.e. check signature creation time < date < expiration time - * @returns {Promise>} list of signer's keyid and validity of signature - * @async - */ -Message.prototype.verifyDetached = function (signature, keys, date = new Date()) { - const msg = this.unwrapCompressed(); - const literalDataList = msg.packets.filterByTag(_enums2.default.packet.literal); - if (literalDataList.length !== 1) { - throw new Error('Can only verify message with one literal data packet.'); - } - const signatureList = signature.packets; - return createVerificationObjects(signatureList, literalDataList, keys, date, true); -}; + BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) { + var byteLength = this.byteLength(); + var reqLength = length || Math.max(1, byteLength); + assert(byteLength <= reqLength, 'byte array longer than desired length'); + assert(reqLength > 0, 'Requested array length <= 0'); -/** - * Create object containing signer's keyid and validity of signature - * @param {module:packet.Signature} signature signature packets - * @param {Array} literalDataList array of literal data packets - * @param {Array} keys array of keys to verify signatures - * @param {Date} date Verify the signature against the given date, - * i.e. check signature creation time < date < expiration time - * @param {Boolean} detached (optional) whether to verify detached signature packets - * @returns {Promise>} list of signer's keyid and validity of signature - * @async - */ -async function createVerificationObject(signature, literalDataList, keys, date = new Date(), detached = false) { - let primaryKey = null; - let signingKey = null; - await Promise.all(keys.map(async function (key) { - // Look for the unique key that matches issuerKeyId of signature - const result = await key.getSigningKey(signature.issuerKeyId, null); - if (result) { - primaryKey = key; - signingKey = result; - } - })); + this.strip(); + var littleEndian = endian === 'le'; + var res = new ArrayType(reqLength); - const signaturePacket = signature.correspondingSig || signature; - const verifiedSig = { - keyid: signature.issuerKeyId, - verified: (async () => { - if (!signingKey) { - return null; + var b, i; + var q = this.clone(); + if (!littleEndian) { + // Assume big-endian + for (i = 0; i < reqLength - byteLength; i++) { + res[i] = 0; } - const verified = await signature.verify(signingKey.keyPacket, signature.signatureType, literalDataList[0], detached); - const sig = await signaturePacket; - if (sig.isExpired(date) || !(sig.created >= signingKey.getCreationTime() && sig.created < (await (signingKey === primaryKey ? signingKey.getExpirationTime() : signingKey.getExpirationTime(primaryKey, date))))) { - return null; + + for (i = 0; !q.isZero(); i++) { + b = q.andln(0xff); + q.iushrn(8); + + res[reqLength - i - 1] = b; } - return verified; - })(), - signature: (async () => { - const sig = await signaturePacket; - const packetlist = new _packet2.default.List(); - packetlist.push(sig); - return new _signature.Signature(packetlist); - })() - }; + } else { + for (i = 0; !q.isZero(); i++) { + b = q.andln(0xff); + q.iushrn(8); - // Mark potential promise rejections as "handled". This is needed because in - // some cases, we reject them before the user has a reasonable chance to - // handle them (e.g. `await readToEnd(result.data); await result.verified` and - // the data stream errors). - verifiedSig.signature.catch(() => {}); - verifiedSig.verified.catch(() => {}); + res[i] = b; + } - return verifiedSig; -} + for (; i < reqLength; i++) { + res[i] = 0; + } + } -/** - * Create list of objects containing signer's keyid and validity of signature - * @param {Array} signatureList array of signature packets - * @param {Array} literalDataList array of literal data packets - * @param {Array} keys array of keys to verify signatures - * @param {Date} date Verify the signature against the given date, - * i.e. check signature creation time < date < expiration time - * @param {Boolean} detached (optional) whether to verify detached signature packets - * @returns {Promise>} list of signer's keyid and validity of signature - * @async - */ -async function createVerificationObjects(signatureList, literalDataList, keys, date = new Date(), detached = false) { - return Promise.all(signatureList.filter(function (signature) { - return ['text', 'binary'].includes(_enums2.default.read(_enums2.default.signature, signature.signatureType)); - }).map(async function (signature) { - return createVerificationObject(signature, literalDataList, keys, date, detached); - })); -} + return res; + }; -/** - * Unwrap compressed message - * @returns {module:message.Message} message Content of compressed message - */ -Message.prototype.unwrapCompressed = function () { - const compressed = this.packets.filterByTag(_enums2.default.packet.compressed); - if (compressed.length) { - return new Message(compressed[0].packets); + if (Math.clz32) { + BN.prototype._countBits = function _countBits (w) { + return 32 - Math.clz32(w); + }; + } else { + BN.prototype._countBits = function _countBits (w) { + var t = w; + var r = 0; + if (t >= 0x1000) { + r += 13; + t >>>= 13; + } + if (t >= 0x40) { + r += 7; + t >>>= 7; + } + if (t >= 0x8) { + r += 4; + t >>>= 4; + } + if (t >= 0x02) { + r += 2; + t >>>= 2; + } + return r + t; + }; } - return this; -}; -/** - * Append signature to unencrypted message object - * @param {String|Uint8Array} detachedSignature The detached ASCII-armored or Uint8Array PGP signature - */ -Message.prototype.appendSignature = async function (detachedSignature) { - await this.packets.read(_util2.default.isUint8Array(detachedSignature) ? detachedSignature : (await _armor2.default.decode(detachedSignature)).data); -}; + BN.prototype._zeroBits = function _zeroBits (w) { + // Short-cut + if (w === 0) return 26; -/** - * Returns ASCII armored text of message - * @returns {ReadableStream} ASCII armor - */ -Message.prototype.armor = function () { - return _armor2.default.encode(_enums2.default.armor.message, this.packets.write()); -}; + var t = w; + var r = 0; + if ((t & 0x1fff) === 0) { + r += 13; + t >>>= 13; + } + if ((t & 0x7f) === 0) { + r += 7; + t >>>= 7; + } + if ((t & 0xf) === 0) { + r += 4; + t >>>= 4; + } + if ((t & 0x3) === 0) { + r += 2; + t >>>= 2; + } + if ((t & 0x1) === 0) { + r++; + } + return r; + }; -/** - * reads an OpenPGP armored message and returns a message object - * @param {String | ReadableStream} armoredText text to be parsed - * @returns {Promise} new message object - * @async - * @static - */ -async function readArmored(armoredText) { - //TODO how do we want to handle bad text? Exception throwing - //TODO don't accept non-message armored texts - const streamType = _util2.default.isStream(armoredText); - if (streamType === 'node') { - armoredText = _webStreamTools2.default.nodeToWeb(armoredText); - } - const input = await _armor2.default.decode(armoredText); - return read(input.data, streamType); -} + // Return number of used bits in a BN + BN.prototype.bitLength = function bitLength () { + var w = this.words[this.length - 1]; + var hi = this._countBits(w); + return (this.length - 1) * 26 + hi; + }; -/** - * reads an OpenPGP message as byte array and returns a message object - * @param {Uint8Array | ReadableStream} input binary message - * @param {Boolean} fromStream whether the message was created from a Stream - * @returns {Promise} new message object - * @async - * @static - */ -async function read(input, fromStream = _util2.default.isStream(input)) { - const streamType = _util2.default.isStream(input); - if (streamType === 'node') { - input = _webStreamTools2.default.nodeToWeb(input); - } - const packetlist = new _packet2.default.List(); - await packetlist.read(input, fromStream); - const message = new Message(packetlist); - message.fromStream = fromStream; - return message; -} + function toBitArray (num) { + var w = new Array(num.bitLength()); -/** - * creates new message object from text - * @param {String | ReadableStream} text - * @param {String} filename (optional) - * @param {Date} date (optional) - * @param {utf8|binary|text|mime} type (optional) data packet type - * @returns {module:message.Message} new message object - * @static - */ -function fromText(text, filename, date = new Date(), type = 'utf8') { - const streamType = _util2.default.isStream(text); - if (streamType === 'node') { - text = _webStreamTools2.default.nodeToWeb(text); - } - const literalDataPacket = new _packet2.default.Literal(date); - // text will be converted to UTF8 - literalDataPacket.setText(text, type); - if (filename !== undefined) { - literalDataPacket.setFilename(filename); - } - const literalDataPacketlist = new _packet2.default.List(); - literalDataPacketlist.push(literalDataPacket); - const message = new Message(literalDataPacketlist); - message.fromStream = streamType; - return message; -} + for (var bit = 0; bit < w.length; bit++) { + var off = (bit / 26) | 0; + var wbit = bit % 26; -/** - * creates new message object from binary data - * @param {Uint8Array | ReadableStream} bytes - * @param {String} filename (optional) - * @param {Date} date (optional) - * @param {utf8|binary|text|mime} type (optional) data packet type - * @returns {module:message.Message} new message object - * @static - */ -function fromBinary(bytes, filename, date = new Date(), type = 'binary') { - const streamType = _util2.default.isStream(bytes); - if (!_util2.default.isUint8Array(bytes) && !streamType) { - throw new Error('Data must be in the form of a Uint8Array or Stream'); - } - if (streamType === 'node') { - bytes = _webStreamTools2.default.nodeToWeb(bytes); - } + w[bit] = (num.words[off] & (1 << wbit)) >>> wbit; + } - const literalDataPacket = new _packet2.default.Literal(date); - literalDataPacket.setBytes(bytes, type); - if (filename !== undefined) { - literalDataPacket.setFilename(filename); + return w; } - const literalDataPacketlist = new _packet2.default.List(); - literalDataPacketlist.push(literalDataPacket); - const message = new Message(literalDataPacketlist); - message.fromStream = streamType; - return message; -} - -},{"./config":79,"./crypto":94,"./encoding/armor":111,"./enums":113,"./key":116,"./packet":125,"./signature":145,"./type/keyid":148,"./util":152,"web-stream-tools":75}],121:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.initWorker = initWorker; -exports.getWorker = getWorker; -exports.destroyWorker = destroyWorker; -exports.generateKey = generateKey; -exports.reformatKey = reformatKey; -exports.revokeKey = revokeKey; -exports.decryptKey = decryptKey; -exports.encryptKey = encryptKey; -exports.encrypt = encrypt; -exports.decrypt = decrypt; -exports.sign = sign; -exports.verify = verify; -exports.encryptSessionKey = encryptSessionKey; -exports.decryptSessionKeys = decryptSessionKeys; -var _webStreamTools = require('web-stream-tools'); + // Number of trailing zero bits + BN.prototype.zeroBits = function zeroBits () { + if (this.isZero()) return 0; -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); + var r = 0; + for (var i = 0; i < this.length; i++) { + var b = this._zeroBits(this.words[i]); + r += b; + if (b !== 26) break; + } + return r; + }; -var _message = require('./message'); + BN.prototype.byteLength = function byteLength () { + return Math.ceil(this.bitLength() / 8); + }; -var messageLib = _interopRequireWildcard(_message); + BN.prototype.toTwos = function toTwos (width) { + if (this.negative !== 0) { + return this.abs().inotn(width).iaddn(1); + } + return this.clone(); + }; -var _cleartext = require('./cleartext'); + BN.prototype.fromTwos = function fromTwos (width) { + if (this.testn(width - 1)) { + return this.notn(width).iaddn(1).ineg(); + } + return this.clone(); + }; -var _key = require('./key'); + BN.prototype.isNeg = function isNeg () { + return this.negative !== 0; + }; -var _config = require('./config/config'); + // Return negative clone of `this` + BN.prototype.neg = function neg () { + return this.clone().ineg(); + }; -var _config2 = _interopRequireDefault(_config); + BN.prototype.ineg = function ineg () { + if (!this.isZero()) { + this.negative ^= 1; + } -var _enums = require('./enums'); + return this; + }; -var _enums2 = _interopRequireDefault(_enums); + // Or `num` with `this` in-place + BN.prototype.iuor = function iuor (num) { + while (this.length < num.length) { + this.words[this.length++] = 0; + } -require('./polyfills'); + for (var i = 0; i < num.length; i++) { + this.words[i] = this.words[i] | num.words[i]; + } -var _util = require('./util'); + return this.strip(); + }; -var _util2 = _interopRequireDefault(_util); + BN.prototype.ior = function ior (num) { + assert((this.negative | num.negative) === 0); + return this.iuor(num); + }; -var _async_proxy = require('./worker/async_proxy'); + // Or `num` with `this` + BN.prototype.or = function or (num) { + if (this.length > num.length) return this.clone().ior(num); + return num.clone().ior(this); + }; -var _async_proxy2 = _interopRequireDefault(_async_proxy); + BN.prototype.uor = function uor (num) { + if (this.length > num.length) return this.clone().iuor(num); + return num.clone().iuor(this); + }; -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + // And `num` with `this` in-place + BN.prototype.iuand = function iuand (num) { + // b = min-length(num, this) + var b; + if (this.length > num.length) { + b = num; + } else { + b = this; + } -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + for (var i = 0; i < b.length; i++) { + this.words[i] = this.words[i] & num.words[i]; + } -////////////////////////// -// // -// Web Worker setup // -// // -////////////////////////// + this.length = b.length; + return this.strip(); + }; -let asyncProxy; // instance of the asyncproxy + BN.prototype.iand = function iand (num) { + assert((this.negative | num.negative) === 0); + return this.iuand(num); + }; -/** - * Set the path for the web worker script and create an instance of the async proxy - * @param {String} path relative path to the worker scripts, default: 'openpgp.worker.js' - * @param {Number} n number of workers to initialize - * @param {Array} workers alternative to path parameter: web workers initialized with 'openpgp.worker.js' - * @returns {Promise} returns a promise that resolves to true if all workers have succesfully finished loading - * @async - */ -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2016 Tankred Hase -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + // And `num` with `this` + BN.prototype.and = function and (num) { + if (this.length > num.length) return this.clone().iand(num); + return num.clone().iand(this); + }; -/** - * @fileoverview The openpgp base module should provide all of the functionality - * to consume the openpgp.js library. All additional classes are documented - * for extending and developing on top of the base library. - * @requires web-stream-tools - * @requires message - * @requires cleartext - * @requires key - * @requires config - * @requires enums - * @requires util - * @requires polyfills - * @requires worker/async_proxy - * @module openpgp - */ + BN.prototype.uand = function uand (num) { + if (this.length > num.length) return this.clone().iuand(num); + return num.clone().iuand(this); + }; -// This file intentionally has two separate file overviews so that -// a reference to this module appears at the end of doc/index.html. + // Xor `num` with `this` in-place + BN.prototype.iuxor = function iuxor (num) { + // a.length > b.length + var a; + var b; + if (this.length > num.length) { + a = this; + b = num; + } else { + a = num; + b = this; + } -/** - * @fileoverview To view the full API documentation, start from - * {@link module:openpgp} - */ + for (var i = 0; i < b.length; i++) { + this.words[i] = a.words[i] ^ b.words[i]; + } -async function initWorker({ path = 'openpgp.worker.js', n = 1, workers = [] } = {}) { - if (workers.length || typeof window !== 'undefined' && window.Worker && window.MessageChannel) { - const proxy = new _async_proxy2.default({ path, n, workers, config: _config2.default }); - const loaded = await proxy.loaded(); - if (loaded) { - asyncProxy = proxy; - return true; + if (this !== a) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } } - } - return false; -} -/** - * Returns a reference to the async proxy if the worker was initialized with openpgp.initWorker() - * @returns {module:worker/async_proxy.AsyncProxy|null} the async proxy or null if not initialized - */ -function getWorker() { - return asyncProxy; -} + this.length = a.length; -/** - * Cleanup the current instance of the web worker. - */ -function destroyWorker() { - asyncProxy = undefined; -} + return this.strip(); + }; -////////////////////// -// // -// Key handling // -// // -////////////////////// + BN.prototype.ixor = function ixor (num) { + assert((this.negative | num.negative) === 0); + return this.iuxor(num); + }; + // Xor `num` with `this` + BN.prototype.xor = function xor (num) { + if (this.length > num.length) return this.clone().ixor(num); + return num.clone().ixor(this); + }; -/** - * Generates a new OpenPGP key pair. Supports RSA and ECC keys. Primary and subkey will be of same type. - * @param {Array} userIds array of user IDs e.g. [{ name:'Phil Zimmermann', email:'phil@openpgp.org' }] - * @param {String} passphrase (optional) The passphrase used to encrypt the resulting private key - * @param {Number} numBits (optional) number of bits for RSA keys: 2048 or 4096. - * @param {Number} keyExpirationTime (optional) The number of seconds after the key creation time that the key expires - * @param {String} curve (optional) elliptic curve for ECC keys: - * curve25519, p256, p384, p521, secp256k1, - * brainpoolP256r1, brainpoolP384r1, or brainpoolP512r1. - * @param {Date} date (optional) override the creation date of the key and the key signatures - * @param {Array} subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}] - * sign parameter defaults to false, and indicates whether the subkey should sign rather than encrypt - * @returns {Promise} The generated key object in the form: - * { key:Key, privateKeyArmored:String, publicKeyArmored:String, revocationCertificate:String } - * @async - * @static - */ + BN.prototype.uxor = function uxor (num) { + if (this.length > num.length) return this.clone().iuxor(num); + return num.clone().iuxor(this); + }; -function generateKey({ userIds = [], passphrase = "", numBits = 2048, keyExpirationTime = 0, curve = "", date = new Date(), subkeys = [{}] }) { - userIds = toArray(userIds); - const options = { userIds, passphrase, numBits, keyExpirationTime, curve, date, subkeys }; - if (_util2.default.getWebCryptoAll() && numBits < 2048) { - throw new Error('numBits should be 2048 or 4096, found: ' + numBits); - } + // Not ``this`` with ``width`` bitwidth + BN.prototype.inotn = function inotn (width) { + assert(typeof width === 'number' && width >= 0); - if (!_util2.default.getWebCryptoAll() && asyncProxy) { - // use web worker if web crypto apis are not supported - return asyncProxy.delegate('generateKey', options); - } + var bytesNeeded = Math.ceil(width / 26) | 0; + var bitsLeft = width % 26; - return (0, _key.generate)(options).then(async key => { - const revocationCertificate = await key.getRevocationCertificate(); - key.revocationSignatures = []; + // Extend the buffer with leading zeroes + this._expand(bytesNeeded); - return convertStreams({ + if (bitsLeft > 0) { + bytesNeeded--; + } - key: key, - privateKeyArmored: key.armor(), - publicKeyArmored: key.toPublic().armor(), - revocationCertificate: revocationCertificate + // Handle complete words + for (var i = 0; i < bytesNeeded; i++) { + this.words[i] = ~this.words[i] & 0x3ffffff; + } - }); - }).catch(onError.bind(null, 'Error generating keypair')); -} + // Handle the residue + if (bitsLeft > 0) { + this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft)); + } -/** - * Reformats signature packets for a key and rewraps key object. - * @param {Key} privateKey private key to reformat - * @param {Array} userIds array of user IDs e.g. [{ name:'Phil Zimmermann', email:'phil@openpgp.org' }] - * @param {String} passphrase (optional) The passphrase used to encrypt the resulting private key - * @param {Number} keyExpirationTime (optional) The number of seconds after the key creation time that the key expires - * @param {Boolean} revocationCertificate (optional) Whether the returned object should include a revocation certificate to revoke the public key - * @returns {Promise} The generated key object in the form: - * { key:Key, privateKeyArmored:String, publicKeyArmored:String, revocationCertificate:String } - * @async - * @static - */ -function reformatKey({ privateKey, userIds = [], passphrase = "", keyExpirationTime = 0, date, revocationCertificate = true }) { - userIds = toArray(userIds); - const options = { privateKey, userIds, passphrase, keyExpirationTime, date, revocationCertificate }; - if (asyncProxy) { - return asyncProxy.delegate('reformatKey', options); - } + // And remove leading zeroes + return this.strip(); + }; - options.revoked = options.revocationCertificate; + BN.prototype.notn = function notn (width) { + return this.clone().inotn(width); + }; - return (0, _key.reformat)(options).then(async key => { - const revocationCertificate = await key.getRevocationCertificate(); - key.revocationSignatures = []; + // Set `bit` of `this` + BN.prototype.setn = function setn (bit, val) { + assert(typeof bit === 'number' && bit >= 0); - return convertStreams({ + var off = (bit / 26) | 0; + var wbit = bit % 26; - key: key, - privateKeyArmored: key.armor(), - publicKeyArmored: key.toPublic().armor(), - revocationCertificate: revocationCertificate + this._expand(off + 1); - }); - }).catch(onError.bind(null, 'Error reformatting keypair')); -} + if (val) { + this.words[off] = this.words[off] | (1 << wbit); + } else { + this.words[off] = this.words[off] & ~(1 << wbit); + } -/** - * Revokes a key. Requires either a private key or a revocation certificate. - * If a revocation certificate is passed, the reasonForRevocation parameters will be ignored. - * @param {Key} key (optional) public or private key to revoke - * @param {String} revocationCertificate (optional) revocation certificate to revoke the key with - * @param {Object} reasonForRevocation (optional) object indicating the reason for revocation - * @param {module:enums.reasonForRevocation} reasonForRevocation.flag (optional) flag indicating the reason for revocation - * @param {String} reasonForRevocation.string (optional) string explaining the reason for revocation - * @returns {Promise} The revoked key object in the form: - * { privateKey:Key, privateKeyArmored:String, publicKey:Key, publicKeyArmored:String } - * (if private key is passed) or { publicKey:Key, publicKeyArmored:String } (otherwise) - * @static - */ -function revokeKey({ - key, revocationCertificate, reasonForRevocation -} = {}) { - const options = { - key, revocationCertificate, reasonForRevocation + return this.strip(); }; - if (!_util2.default.getWebCryptoAll() && asyncProxy) { - // use web worker if web crypto apis are not supported - return asyncProxy.delegate('revokeKey', options); - } + // Add `num` to `this` in-place + BN.prototype.iadd = function iadd (num) { + var r; - return Promise.resolve().then(() => { - if (revocationCertificate) { - return key.applyRevocationCertificate(revocationCertificate); - } else { - return key.revoke(reasonForRevocation); + // negative + positive + if (this.negative !== 0 && num.negative === 0) { + this.negative = 0; + r = this.isub(num); + this.negative ^= 1; + return this._normSign(); + + // positive + negative + } else if (this.negative === 0 && num.negative !== 0) { + num.negative = 0; + r = this.isub(num); + num.negative = 1; + return r._normSign(); } - }).then(async key => { - await convertStreams(key); - if (key.isPrivate()) { - const publicKey = key.toPublic(); - return { - privateKey: key, - privateKeyArmored: key.armor(), - publicKey: publicKey, - publicKeyArmored: publicKey.armor() - }; + + // a.length > b.length + var a, b; + if (this.length > num.length) { + a = this; + b = num; + } else { + a = num; + b = this; } - return { - publicKey: key, - publicKeyArmored: key.armor() - }; - }).catch(onError.bind(null, 'Error revoking key')); -} -/** - * Unlock a private key with your passphrase. - * @param {Key} privateKey the private key that is to be decrypted - * @param {String|Array} passphrase the user's passphrase(s) chosen during key generation - * @returns {Promise} the unlocked key object in the form: { key:Key } - * @async - */ -function decryptKey({ privateKey, passphrase }) { - if (asyncProxy) { - // use web worker if available - return asyncProxy.delegate('decryptKey', { privateKey, passphrase }); - } + var carry = 0; + for (var i = 0; i < b.length; i++) { + r = (a.words[i] | 0) + (b.words[i] | 0) + carry; + this.words[i] = r & 0x3ffffff; + carry = r >>> 26; + } + for (; carry !== 0 && i < a.length; i++) { + r = (a.words[i] | 0) + carry; + this.words[i] = r & 0x3ffffff; + carry = r >>> 26; + } - return Promise.resolve().then(async function () { - await privateKey.decrypt(passphrase); + this.length = a.length; + if (carry !== 0) { + this.words[this.length] = carry; + this.length++; + // Copy the rest of the words + } else if (a !== this) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } + } - return { - key: privateKey - }; - }).catch(onError.bind(null, 'Error decrypting private key')); -} + return this; + }; -/** - * Lock a private key with your passphrase. - * @param {Key} privateKey the private key that is to be decrypted - * @param {String|Array} passphrase the user's passphrase(s) chosen during key generation - * @returns {Promise} the locked key object in the form: { key:Key } - * @async - */ -function encryptKey({ privateKey, passphrase }) { - if (asyncProxy) { - // use web worker if available - return asyncProxy.delegate('encryptKey', { privateKey, passphrase }); - } + // Add `num` to `this` + BN.prototype.add = function add (num) { + var res; + if (num.negative !== 0 && this.negative === 0) { + num.negative = 0; + res = this.sub(num); + num.negative ^= 1; + return res; + } else if (num.negative === 0 && this.negative !== 0) { + this.negative = 0; + res = num.sub(this); + this.negative = 1; + return res; + } - return Promise.resolve().then(async function () { - await privateKey.encrypt(passphrase); + if (this.length > num.length) return this.clone().iadd(num); - return { - key: privateKey - }; - }).catch(onError.bind(null, 'Error decrypting private key')); -} + return num.clone().iadd(this); + }; -/////////////////////////////////////////// -// // -// Message encryption and decryption // -// // -/////////////////////////////////////////// + // Subtract `num` from `this` in-place + BN.prototype.isub = function isub (num) { + // this - (-num) = this + num + if (num.negative !== 0) { + num.negative = 0; + var r = this.iadd(num); + num.negative = 1; + return r._normSign(); + // -this - num = -(this + num) + } else if (this.negative !== 0) { + this.negative = 0; + this.iadd(num); + this.negative = 1; + return this._normSign(); + } -/** - * Encrypts message text/data with public keys, passwords or both at once. At least either public keys or passwords - * must be specified. If private keys are specified, those will be used to sign the message. - * @param {Message} message message to be encrypted as created by openpgp.message.fromText or openpgp.message.fromBinary - * @param {Key|Array} publicKeys (optional) array of keys or single key, used to encrypt the message - * @param {Key|Array} privateKeys (optional) private keys for signing. If omitted message will not be signed - * @param {String|Array} passwords (optional) array of passwords or a single password to encrypt the message - * @param {Object} sessionKey (optional) session key in the form: { data:Uint8Array, algorithm:String } - * @param {module:enums.compression} compression (optional) which compression algorithm to compress the message with, defaults to what is specified in config - * @param {Boolean} armor (optional) if the return values should be ascii armored or the message/signature objects - * @param {'web'|'node'|false} streaming (optional) whether to return data as a stream. Defaults to the type of stream `message` was created from, if any. - * @param {Boolean} detached (optional) if the signature should be detached (if true, signature will be added to returned object) - * @param {Signature} signature (optional) a detached signature to add to the encrypted message - * @param {Boolean} returnSessionKey (optional) if the unencrypted session key should be added to returned object - * @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs - * @param {Date} date (optional) override the creation date of the message signature - * @param {Array} fromUserIds (optional) array of user IDs to sign with, one per key in `privateKeys`, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] - * @param {Array} toUserIds (optional) array of user IDs to encrypt for, one per key in `publicKeys`, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }] - * @returns {Promise} Object containing encrypted (and optionally signed) message in the form: - * - * { - * data: String|ReadableStream|NodeStream, (if `armor` was true, the default) - * message: Message, (if `armor` was false) - * signature: String|ReadableStream|NodeStream, (if `detached` was true and `armor` was true) - * signature: Signature (if `detached` was true and `armor` was false) - * sessionKey: { data, algorithm, aeadAlgorithm } (if `returnSessionKey` was true) - * } - * @async - * @static - */ -function encrypt({ message, publicKeys, privateKeys, passwords, sessionKey, compression = _config2.default.compression, armor = true, streaming = message && message.fromStream, detached = false, signature = null, returnSessionKey = false, wildcard = false, date = new Date(), fromUserIds = [], toUserIds = [] }) { - checkMessage(message);publicKeys = toArray(publicKeys);privateKeys = toArray(privateKeys);passwords = toArray(passwords);fromUserIds = toArray(fromUserIds);toUserIds = toArray(toUserIds); + // At this point both numbers are positive + var cmp = this.cmp(num); - if (!nativeAEAD() && asyncProxy) { - // use web worker if web crypto apis are not supported - return asyncProxy.delegate('encrypt', { message, publicKeys, privateKeys, passwords, sessionKey, compression, armor, streaming, detached, signature, returnSessionKey, wildcard, date, fromUserIds, toUserIds }); - } - const result = {}; - return Promise.resolve().then(async function () { - if (!privateKeys) { - privateKeys = []; - } - if (privateKeys.length || signature) { - // sign the message only if private keys or signature is specified - if (detached) { - const detachedSignature = await message.signDetached(privateKeys, signature, date, fromUserIds); - result.signature = armor ? detachedSignature.armor() : detachedSignature; - } else { - message = await message.sign(privateKeys, signature, date, fromUserIds); - } + // Optimization - zeroify + if (cmp === 0) { + this.negative = 0; + this.length = 1; + this.words[0] = 0; + return this; } - message = message.compress(compression); - return message.encrypt(publicKeys, passwords, sessionKey, wildcard, date, toUserIds, streaming); - }).then(async encrypted => { - if (armor) { - result.data = encrypted.message.armor(); + + // a > b + var a, b; + if (cmp > 0) { + a = this; + b = num; } else { - result.message = encrypted.message; + a = num; + b = this; } - if (returnSessionKey) { - result.sessionKey = encrypted.sessionKey; + + var carry = 0; + for (var i = 0; i < b.length; i++) { + r = (a.words[i] | 0) - (b.words[i] | 0) + carry; + carry = r >> 26; + this.words[i] = r & 0x3ffffff; + } + for (; carry !== 0 && i < a.length; i++) { + r = (a.words[i] | 0) + carry; + carry = r >> 26; + this.words[i] = r & 0x3ffffff; } - return convertStreams(result, streaming, armor ? ['signature', 'data'] : []); - }).catch(onError.bind(null, 'Error encrypting message')); -} -/** - * Decrypts a message with the user's private key, a session key or a password. Either a private key, - * a session key or a password must be specified. - * @param {Message} message the message object with the encrypted data - * @param {Key|Array} privateKeys (optional) private keys with decrypted secret key data or session key - * @param {String|Array} passwords (optional) passwords to decrypt the message - * @param {Object|Array} sessionKeys (optional) session keys in the form: { data:Uint8Array, algorithm:String } - * @param {Key|Array} publicKeys (optional) array of public keys or single key, to verify signatures - * @param {'utf8'|'binary'} format (optional) whether to return data as a string(Stream) or Uint8Array(Stream). If 'utf8' (the default), also normalize newlines. - * @param {'web'|'node'|false} streaming (optional) whether to return data as a stream. Defaults to the type of stream `message` was created from, if any. - * @param {Signature} signature (optional) detached signature for verification - * @param {Date} date (optional) use the given date for verification instead of the current time - * @returns {Promise} Object containing decrypted and verified message in the form: - * - * { - * data: String|ReadableStream|NodeStream, (if format was 'utf8', the default) - * data: Uint8Array|ReadableStream|NodeStream, (if format was 'binary') - * filename: String, - * signatures: [ - * { - * keyid: module:type/keyid, - * verified: Promise, - * valid: Boolean (if streaming was false) - * }, ... - * ] - * } - * @async - * @static - */ -function decrypt({ message, privateKeys, passwords, sessionKeys, publicKeys, format = 'utf8', streaming = message && message.fromStream, signature = null, date = new Date() }) { - checkMessage(message);publicKeys = toArray(publicKeys);privateKeys = toArray(privateKeys);passwords = toArray(passwords);sessionKeys = toArray(sessionKeys); + // Copy rest of the words + if (carry === 0 && i < a.length && a !== this) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } + } - if (!nativeAEAD() && asyncProxy) { - // use web worker if web crypto apis are not supported - return asyncProxy.delegate('decrypt', { message, privateKeys, passwords, sessionKeys, publicKeys, format, streaming, signature, date }); - } + this.length = Math.max(this.length, i); - return message.decrypt(privateKeys, passwords, sessionKeys, streaming).then(async function (decrypted) { - if (!publicKeys) { - publicKeys = []; + if (a !== this) { + this.negative = 1; } - const result = {}; - result.signatures = signature ? await decrypted.verifyDetached(signature, publicKeys, date, streaming) : await decrypted.verify(publicKeys, date, streaming); - result.data = format === 'binary' ? decrypted.getLiteralData() : decrypted.getText(); - result.filename = decrypted.getFilename(); - if (streaming) linkStreams(result, message); - result.data = await convertStream(result.data, streaming); - if (!streaming) await prepareSignatures(result.signatures); - return result; - }).catch(onError.bind(null, 'Error decrypting message')); -} + return this.strip(); + }; -////////////////////////////////////////// -// // -// Message signing and verification // -// // -////////////////////////////////////////// + // Subtract `num` from `this` + BN.prototype.sub = function sub (num) { + return this.clone().isub(num); + }; + function smallMulTo (self, num, out) { + out.negative = num.negative ^ self.negative; + var len = (self.length + num.length) | 0; + out.length = len; + len = (len - 1) | 0; -/** - * Signs a cleartext message. - * @param {CleartextMessage|Message} message (cleartext) message to be signed - * @param {Key|Array} privateKeys array of keys or single key with decrypted secret key data to sign cleartext - * @param {Boolean} armor (optional) if the return value should be ascii armored or the message object - * @param {'web'|'node'|false} streaming (optional) whether to return data as a stream. Defaults to the type of stream `message` was created from, if any. - * @param {Boolean} detached (optional) if the return value should contain a detached signature - * @param {Date} date (optional) override the creation date of the signature - * @param {Array} fromUserIds (optional) array of user IDs to sign with, one per key in `privateKeys`, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] - * @returns {Promise} Object containing signed message in the form: - * - * { - * data: String|ReadableStream|NodeStream, (if `armor` was true, the default) - * message: Message (if `armor` was false) - * } - * - * Or, if `detached` was true: - * - * { - * signature: String|ReadableStream|NodeStream, (if `armor` was true, the default) - * signature: Signature (if `armor` was false) - * } - * @async - * @static - */ -function sign({ message, privateKeys, armor = true, streaming = message && message.fromStream, detached = false, date = new Date(), fromUserIds = [] }) { - checkCleartextOrMessage(message); - privateKeys = toArray(privateKeys);fromUserIds = toArray(fromUserIds); + // Peel one iteration (compiler can't do it, because of code complexity) + var a = self.words[0] | 0; + var b = num.words[0] | 0; + var r = a * b; - if (asyncProxy) { - // use web worker if available - return asyncProxy.delegate('sign', { - message, privateKeys, armor, streaming, detached, date, fromUserIds - }); - } + var lo = r & 0x3ffffff; + var carry = (r / 0x4000000) | 0; + out.words[0] = lo; - const result = {}; - return Promise.resolve().then(async function () { - if (detached) { - const signature = await message.signDetached(privateKeys, undefined, date, fromUserIds); - result.signature = armor ? signature.armor() : signature; - if (message.packets) { - result.signature = _webStreamTools2.default.transformPair(message.packets.write(), async (readable, writable) => { - await Promise.all([_webStreamTools2.default.pipe(result.signature, writable), _webStreamTools2.default.readToEnd(readable).catch(() => {})]); - }); + for (var k = 1; k < len; k++) { + // Sum all words with the same `i + j = k` and accumulate `ncarry`, + // note that ncarry could be >= 0x3ffffff + var ncarry = carry >>> 26; + var rword = carry & 0x3ffffff; + var maxJ = Math.min(k, num.length - 1); + for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { + var i = (k - j) | 0; + a = self.words[i] | 0; + b = num.words[j] | 0; + r = a * b + rword; + ncarry += (r / 0x4000000) | 0; + rword = r & 0x3ffffff; } + out.words[k] = rword | 0; + carry = ncarry | 0; + } + if (carry !== 0) { + out.words[k] = carry | 0; } else { - message = await message.sign(privateKeys, undefined, date, fromUserIds); - if (armor) { - result.data = message.armor(); - } else { - result.message = message; - } + out.length--; } - return convertStreams(result, streaming, armor ? ['signature', 'data'] : []); - }).catch(onError.bind(null, 'Error signing cleartext message')); -} - -/** - * Verifies signatures of cleartext signed message - * @param {Key|Array} publicKeys array of publicKeys or single key, to verify signatures - * @param {CleartextMessage|Message} message (cleartext) message object with signatures - * @param {'web'|'node'|false} streaming (optional) whether to return data as a stream. Defaults to the type of stream `message` was created from, if any. - * @param {Signature} signature (optional) detached signature for verification - * @param {Date} date (optional) use the given date for verification instead of the current time - * @returns {Promise} Object containing verified message in the form: - * - * { - * data: String|ReadableStream|NodeStream, (if `message` was a CleartextMessage) - * data: Uint8Array|ReadableStream|NodeStream, (if `message` was a Message) - * signatures: [ - * { - * keyid: module:type/keyid, - * verified: Promise, - * valid: Boolean (if `streaming` was false) - * }, ... - * ] - * } - * @async - * @static - */ -function verify({ message, publicKeys, streaming = message && message.fromStream, signature = null, date = new Date() }) { - checkCleartextOrMessage(message); - publicKeys = toArray(publicKeys); - - if (asyncProxy) { - // use web worker if available - return asyncProxy.delegate('verify', { message, publicKeys, streaming, signature, date }); - } - - return Promise.resolve().then(async function () { - const result = {}; - result.signatures = signature ? await message.verifyDetached(signature, publicKeys, date, streaming) : await message.verify(publicKeys, date, streaming); - result.data = message instanceof _cleartext.CleartextMessage ? message.getText() : message.getLiteralData(); - if (streaming) linkStreams(result, message); - result.data = await convertStream(result.data, streaming); - if (!streaming) await prepareSignatures(result.signatures); - return result; - }).catch(onError.bind(null, 'Error verifying cleartext signed message')); -} - -/////////////////////////////////////////////// -// // -// Session key encryption and decryption // -// // -/////////////////////////////////////////////// - - -/** - * Encrypt a symmetric session key with public keys, passwords, or both at once. At least either public keys - * or passwords must be specified. - * @param {Uint8Array} data the session key to be encrypted e.g. 16 random bytes (for aes128) - * @param {String} algorithm algorithm of the symmetric session key e.g. 'aes128' or 'aes256' - * @param {String} aeadAlgorithm (optional) aead algorithm, e.g. 'eax' or 'ocb' - * @param {Key|Array} publicKeys (optional) array of public keys or single key, used to encrypt the key - * @param {String|Array} passwords (optional) passwords for the message - * @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs - * @param {Date} date (optional) override the date - * @param {Array} toUserIds (optional) array of user IDs to encrypt for, one per key in `publicKeys`, e.g. [{ name:'Phil Zimmermann', email:'phil@openpgp.org' }] - * @returns {Promise} the encrypted session key packets contained in a message object - * @async - * @static - */ -function encryptSessionKey({ data, algorithm, aeadAlgorithm, publicKeys, passwords, wildcard = false, date = new Date(), toUserIds = [] }) { - checkBinary(data);checkString(algorithm, 'algorithm');publicKeys = toArray(publicKeys);passwords = toArray(passwords);toUserIds = toArray(toUserIds); - if (asyncProxy) { - // use web worker if available - return asyncProxy.delegate('encryptSessionKey', { data, algorithm, aeadAlgorithm, publicKeys, passwords, wildcard, date, toUserIds }); + return out.strip(); } - return Promise.resolve().then(async function () { - - return { message: await messageLib.encryptSessionKey(data, algorithm, aeadAlgorithm, publicKeys, passwords, wildcard, date, toUserIds) }; - }).catch(onError.bind(null, 'Error encrypting session key')); -} + // TODO(indutny): it may be reasonable to omit it for users who don't need + // to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit + // multiplication (like elliptic secp256k1). + var comb10MulTo = function comb10MulTo (self, num, out) { + var a = self.words; + var b = num.words; + var o = out.words; + var c = 0; + var lo; + var mid; + var hi; + var a0 = a[0] | 0; + var al0 = a0 & 0x1fff; + var ah0 = a0 >>> 13; + var a1 = a[1] | 0; + var al1 = a1 & 0x1fff; + var ah1 = a1 >>> 13; + var a2 = a[2] | 0; + var al2 = a2 & 0x1fff; + var ah2 = a2 >>> 13; + var a3 = a[3] | 0; + var al3 = a3 & 0x1fff; + var ah3 = a3 >>> 13; + var a4 = a[4] | 0; + var al4 = a4 & 0x1fff; + var ah4 = a4 >>> 13; + var a5 = a[5] | 0; + var al5 = a5 & 0x1fff; + var ah5 = a5 >>> 13; + var a6 = a[6] | 0; + var al6 = a6 & 0x1fff; + var ah6 = a6 >>> 13; + var a7 = a[7] | 0; + var al7 = a7 & 0x1fff; + var ah7 = a7 >>> 13; + var a8 = a[8] | 0; + var al8 = a8 & 0x1fff; + var ah8 = a8 >>> 13; + var a9 = a[9] | 0; + var al9 = a9 & 0x1fff; + var ah9 = a9 >>> 13; + var b0 = b[0] | 0; + var bl0 = b0 & 0x1fff; + var bh0 = b0 >>> 13; + var b1 = b[1] | 0; + var bl1 = b1 & 0x1fff; + var bh1 = b1 >>> 13; + var b2 = b[2] | 0; + var bl2 = b2 & 0x1fff; + var bh2 = b2 >>> 13; + var b3 = b[3] | 0; + var bl3 = b3 & 0x1fff; + var bh3 = b3 >>> 13; + var b4 = b[4] | 0; + var bl4 = b4 & 0x1fff; + var bh4 = b4 >>> 13; + var b5 = b[5] | 0; + var bl5 = b5 & 0x1fff; + var bh5 = b5 >>> 13; + var b6 = b[6] | 0; + var bl6 = b6 & 0x1fff; + var bh6 = b6 >>> 13; + var b7 = b[7] | 0; + var bl7 = b7 & 0x1fff; + var bh7 = b7 >>> 13; + var b8 = b[8] | 0; + var bl8 = b8 & 0x1fff; + var bh8 = b8 >>> 13; + var b9 = b[9] | 0; + var bl9 = b9 & 0x1fff; + var bh9 = b9 >>> 13; -/** - * Decrypt symmetric session keys with a private key or password. Either a private key or - * a password must be specified. - * @param {Message} message a message object containing the encrypted session key packets - * @param {Key|Array} privateKeys (optional) private keys with decrypted secret key data - * @param {String|Array} passwords (optional) passwords to decrypt the session key - * @returns {Promise} Array of decrypted session key, algorithm pairs in form: - * { data:Uint8Array, algorithm:String } - * or 'undefined' if no key packets found - * @async - * @static - */ -function decryptSessionKeys({ message, privateKeys, passwords }) { - checkMessage(message);privateKeys = toArray(privateKeys);passwords = toArray(passwords); + out.negative = self.negative ^ num.negative; + out.length = 19; + /* k = 0 */ + lo = Math.imul(al0, bl0); + mid = Math.imul(al0, bh0); + mid = (mid + Math.imul(ah0, bl0)) | 0; + hi = Math.imul(ah0, bh0); + var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0; + w0 &= 0x3ffffff; + /* k = 1 */ + lo = Math.imul(al1, bl0); + mid = Math.imul(al1, bh0); + mid = (mid + Math.imul(ah1, bl0)) | 0; + hi = Math.imul(ah1, bh0); + lo = (lo + Math.imul(al0, bl1)) | 0; + mid = (mid + Math.imul(al0, bh1)) | 0; + mid = (mid + Math.imul(ah0, bl1)) | 0; + hi = (hi + Math.imul(ah0, bh1)) | 0; + var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0; + w1 &= 0x3ffffff; + /* k = 2 */ + lo = Math.imul(al2, bl0); + mid = Math.imul(al2, bh0); + mid = (mid + Math.imul(ah2, bl0)) | 0; + hi = Math.imul(ah2, bh0); + lo = (lo + Math.imul(al1, bl1)) | 0; + mid = (mid + Math.imul(al1, bh1)) | 0; + mid = (mid + Math.imul(ah1, bl1)) | 0; + hi = (hi + Math.imul(ah1, bh1)) | 0; + lo = (lo + Math.imul(al0, bl2)) | 0; + mid = (mid + Math.imul(al0, bh2)) | 0; + mid = (mid + Math.imul(ah0, bl2)) | 0; + hi = (hi + Math.imul(ah0, bh2)) | 0; + var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0; + w2 &= 0x3ffffff; + /* k = 3 */ + lo = Math.imul(al3, bl0); + mid = Math.imul(al3, bh0); + mid = (mid + Math.imul(ah3, bl0)) | 0; + hi = Math.imul(ah3, bh0); + lo = (lo + Math.imul(al2, bl1)) | 0; + mid = (mid + Math.imul(al2, bh1)) | 0; + mid = (mid + Math.imul(ah2, bl1)) | 0; + hi = (hi + Math.imul(ah2, bh1)) | 0; + lo = (lo + Math.imul(al1, bl2)) | 0; + mid = (mid + Math.imul(al1, bh2)) | 0; + mid = (mid + Math.imul(ah1, bl2)) | 0; + hi = (hi + Math.imul(ah1, bh2)) | 0; + lo = (lo + Math.imul(al0, bl3)) | 0; + mid = (mid + Math.imul(al0, bh3)) | 0; + mid = (mid + Math.imul(ah0, bl3)) | 0; + hi = (hi + Math.imul(ah0, bh3)) | 0; + var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0; + w3 &= 0x3ffffff; + /* k = 4 */ + lo = Math.imul(al4, bl0); + mid = Math.imul(al4, bh0); + mid = (mid + Math.imul(ah4, bl0)) | 0; + hi = Math.imul(ah4, bh0); + lo = (lo + Math.imul(al3, bl1)) | 0; + mid = (mid + Math.imul(al3, bh1)) | 0; + mid = (mid + Math.imul(ah3, bl1)) | 0; + hi = (hi + Math.imul(ah3, bh1)) | 0; + lo = (lo + Math.imul(al2, bl2)) | 0; + mid = (mid + Math.imul(al2, bh2)) | 0; + mid = (mid + Math.imul(ah2, bl2)) | 0; + hi = (hi + Math.imul(ah2, bh2)) | 0; + lo = (lo + Math.imul(al1, bl3)) | 0; + mid = (mid + Math.imul(al1, bh3)) | 0; + mid = (mid + Math.imul(ah1, bl3)) | 0; + hi = (hi + Math.imul(ah1, bh3)) | 0; + lo = (lo + Math.imul(al0, bl4)) | 0; + mid = (mid + Math.imul(al0, bh4)) | 0; + mid = (mid + Math.imul(ah0, bl4)) | 0; + hi = (hi + Math.imul(ah0, bh4)) | 0; + var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0; + w4 &= 0x3ffffff; + /* k = 5 */ + lo = Math.imul(al5, bl0); + mid = Math.imul(al5, bh0); + mid = (mid + Math.imul(ah5, bl0)) | 0; + hi = Math.imul(ah5, bh0); + lo = (lo + Math.imul(al4, bl1)) | 0; + mid = (mid + Math.imul(al4, bh1)) | 0; + mid = (mid + Math.imul(ah4, bl1)) | 0; + hi = (hi + Math.imul(ah4, bh1)) | 0; + lo = (lo + Math.imul(al3, bl2)) | 0; + mid = (mid + Math.imul(al3, bh2)) | 0; + mid = (mid + Math.imul(ah3, bl2)) | 0; + hi = (hi + Math.imul(ah3, bh2)) | 0; + lo = (lo + Math.imul(al2, bl3)) | 0; + mid = (mid + Math.imul(al2, bh3)) | 0; + mid = (mid + Math.imul(ah2, bl3)) | 0; + hi = (hi + Math.imul(ah2, bh3)) | 0; + lo = (lo + Math.imul(al1, bl4)) | 0; + mid = (mid + Math.imul(al1, bh4)) | 0; + mid = (mid + Math.imul(ah1, bl4)) | 0; + hi = (hi + Math.imul(ah1, bh4)) | 0; + lo = (lo + Math.imul(al0, bl5)) | 0; + mid = (mid + Math.imul(al0, bh5)) | 0; + mid = (mid + Math.imul(ah0, bl5)) | 0; + hi = (hi + Math.imul(ah0, bh5)) | 0; + var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0; + w5 &= 0x3ffffff; + /* k = 6 */ + lo = Math.imul(al6, bl0); + mid = Math.imul(al6, bh0); + mid = (mid + Math.imul(ah6, bl0)) | 0; + hi = Math.imul(ah6, bh0); + lo = (lo + Math.imul(al5, bl1)) | 0; + mid = (mid + Math.imul(al5, bh1)) | 0; + mid = (mid + Math.imul(ah5, bl1)) | 0; + hi = (hi + Math.imul(ah5, bh1)) | 0; + lo = (lo + Math.imul(al4, bl2)) | 0; + mid = (mid + Math.imul(al4, bh2)) | 0; + mid = (mid + Math.imul(ah4, bl2)) | 0; + hi = (hi + Math.imul(ah4, bh2)) | 0; + lo = (lo + Math.imul(al3, bl3)) | 0; + mid = (mid + Math.imul(al3, bh3)) | 0; + mid = (mid + Math.imul(ah3, bl3)) | 0; + hi = (hi + Math.imul(ah3, bh3)) | 0; + lo = (lo + Math.imul(al2, bl4)) | 0; + mid = (mid + Math.imul(al2, bh4)) | 0; + mid = (mid + Math.imul(ah2, bl4)) | 0; + hi = (hi + Math.imul(ah2, bh4)) | 0; + lo = (lo + Math.imul(al1, bl5)) | 0; + mid = (mid + Math.imul(al1, bh5)) | 0; + mid = (mid + Math.imul(ah1, bl5)) | 0; + hi = (hi + Math.imul(ah1, bh5)) | 0; + lo = (lo + Math.imul(al0, bl6)) | 0; + mid = (mid + Math.imul(al0, bh6)) | 0; + mid = (mid + Math.imul(ah0, bl6)) | 0; + hi = (hi + Math.imul(ah0, bh6)) | 0; + var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0; + w6 &= 0x3ffffff; + /* k = 7 */ + lo = Math.imul(al7, bl0); + mid = Math.imul(al7, bh0); + mid = (mid + Math.imul(ah7, bl0)) | 0; + hi = Math.imul(ah7, bh0); + lo = (lo + Math.imul(al6, bl1)) | 0; + mid = (mid + Math.imul(al6, bh1)) | 0; + mid = (mid + Math.imul(ah6, bl1)) | 0; + hi = (hi + Math.imul(ah6, bh1)) | 0; + lo = (lo + Math.imul(al5, bl2)) | 0; + mid = (mid + Math.imul(al5, bh2)) | 0; + mid = (mid + Math.imul(ah5, bl2)) | 0; + hi = (hi + Math.imul(ah5, bh2)) | 0; + lo = (lo + Math.imul(al4, bl3)) | 0; + mid = (mid + Math.imul(al4, bh3)) | 0; + mid = (mid + Math.imul(ah4, bl3)) | 0; + hi = (hi + Math.imul(ah4, bh3)) | 0; + lo = (lo + Math.imul(al3, bl4)) | 0; + mid = (mid + Math.imul(al3, bh4)) | 0; + mid = (mid + Math.imul(ah3, bl4)) | 0; + hi = (hi + Math.imul(ah3, bh4)) | 0; + lo = (lo + Math.imul(al2, bl5)) | 0; + mid = (mid + Math.imul(al2, bh5)) | 0; + mid = (mid + Math.imul(ah2, bl5)) | 0; + hi = (hi + Math.imul(ah2, bh5)) | 0; + lo = (lo + Math.imul(al1, bl6)) | 0; + mid = (mid + Math.imul(al1, bh6)) | 0; + mid = (mid + Math.imul(ah1, bl6)) | 0; + hi = (hi + Math.imul(ah1, bh6)) | 0; + lo = (lo + Math.imul(al0, bl7)) | 0; + mid = (mid + Math.imul(al0, bh7)) | 0; + mid = (mid + Math.imul(ah0, bl7)) | 0; + hi = (hi + Math.imul(ah0, bh7)) | 0; + var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0; + w7 &= 0x3ffffff; + /* k = 8 */ + lo = Math.imul(al8, bl0); + mid = Math.imul(al8, bh0); + mid = (mid + Math.imul(ah8, bl0)) | 0; + hi = Math.imul(ah8, bh0); + lo = (lo + Math.imul(al7, bl1)) | 0; + mid = (mid + Math.imul(al7, bh1)) | 0; + mid = (mid + Math.imul(ah7, bl1)) | 0; + hi = (hi + Math.imul(ah7, bh1)) | 0; + lo = (lo + Math.imul(al6, bl2)) | 0; + mid = (mid + Math.imul(al6, bh2)) | 0; + mid = (mid + Math.imul(ah6, bl2)) | 0; + hi = (hi + Math.imul(ah6, bh2)) | 0; + lo = (lo + Math.imul(al5, bl3)) | 0; + mid = (mid + Math.imul(al5, bh3)) | 0; + mid = (mid + Math.imul(ah5, bl3)) | 0; + hi = (hi + Math.imul(ah5, bh3)) | 0; + lo = (lo + Math.imul(al4, bl4)) | 0; + mid = (mid + Math.imul(al4, bh4)) | 0; + mid = (mid + Math.imul(ah4, bl4)) | 0; + hi = (hi + Math.imul(ah4, bh4)) | 0; + lo = (lo + Math.imul(al3, bl5)) | 0; + mid = (mid + Math.imul(al3, bh5)) | 0; + mid = (mid + Math.imul(ah3, bl5)) | 0; + hi = (hi + Math.imul(ah3, bh5)) | 0; + lo = (lo + Math.imul(al2, bl6)) | 0; + mid = (mid + Math.imul(al2, bh6)) | 0; + mid = (mid + Math.imul(ah2, bl6)) | 0; + hi = (hi + Math.imul(ah2, bh6)) | 0; + lo = (lo + Math.imul(al1, bl7)) | 0; + mid = (mid + Math.imul(al1, bh7)) | 0; + mid = (mid + Math.imul(ah1, bl7)) | 0; + hi = (hi + Math.imul(ah1, bh7)) | 0; + lo = (lo + Math.imul(al0, bl8)) | 0; + mid = (mid + Math.imul(al0, bh8)) | 0; + mid = (mid + Math.imul(ah0, bl8)) | 0; + hi = (hi + Math.imul(ah0, bh8)) | 0; + var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0; + w8 &= 0x3ffffff; + /* k = 9 */ + lo = Math.imul(al9, bl0); + mid = Math.imul(al9, bh0); + mid = (mid + Math.imul(ah9, bl0)) | 0; + hi = Math.imul(ah9, bh0); + lo = (lo + Math.imul(al8, bl1)) | 0; + mid = (mid + Math.imul(al8, bh1)) | 0; + mid = (mid + Math.imul(ah8, bl1)) | 0; + hi = (hi + Math.imul(ah8, bh1)) | 0; + lo = (lo + Math.imul(al7, bl2)) | 0; + mid = (mid + Math.imul(al7, bh2)) | 0; + mid = (mid + Math.imul(ah7, bl2)) | 0; + hi = (hi + Math.imul(ah7, bh2)) | 0; + lo = (lo + Math.imul(al6, bl3)) | 0; + mid = (mid + Math.imul(al6, bh3)) | 0; + mid = (mid + Math.imul(ah6, bl3)) | 0; + hi = (hi + Math.imul(ah6, bh3)) | 0; + lo = (lo + Math.imul(al5, bl4)) | 0; + mid = (mid + Math.imul(al5, bh4)) | 0; + mid = (mid + Math.imul(ah5, bl4)) | 0; + hi = (hi + Math.imul(ah5, bh4)) | 0; + lo = (lo + Math.imul(al4, bl5)) | 0; + mid = (mid + Math.imul(al4, bh5)) | 0; + mid = (mid + Math.imul(ah4, bl5)) | 0; + hi = (hi + Math.imul(ah4, bh5)) | 0; + lo = (lo + Math.imul(al3, bl6)) | 0; + mid = (mid + Math.imul(al3, bh6)) | 0; + mid = (mid + Math.imul(ah3, bl6)) | 0; + hi = (hi + Math.imul(ah3, bh6)) | 0; + lo = (lo + Math.imul(al2, bl7)) | 0; + mid = (mid + Math.imul(al2, bh7)) | 0; + mid = (mid + Math.imul(ah2, bl7)) | 0; + hi = (hi + Math.imul(ah2, bh7)) | 0; + lo = (lo + Math.imul(al1, bl8)) | 0; + mid = (mid + Math.imul(al1, bh8)) | 0; + mid = (mid + Math.imul(ah1, bl8)) | 0; + hi = (hi + Math.imul(ah1, bh8)) | 0; + lo = (lo + Math.imul(al0, bl9)) | 0; + mid = (mid + Math.imul(al0, bh9)) | 0; + mid = (mid + Math.imul(ah0, bl9)) | 0; + hi = (hi + Math.imul(ah0, bh9)) | 0; + var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0; + w9 &= 0x3ffffff; + /* k = 10 */ + lo = Math.imul(al9, bl1); + mid = Math.imul(al9, bh1); + mid = (mid + Math.imul(ah9, bl1)) | 0; + hi = Math.imul(ah9, bh1); + lo = (lo + Math.imul(al8, bl2)) | 0; + mid = (mid + Math.imul(al8, bh2)) | 0; + mid = (mid + Math.imul(ah8, bl2)) | 0; + hi = (hi + Math.imul(ah8, bh2)) | 0; + lo = (lo + Math.imul(al7, bl3)) | 0; + mid = (mid + Math.imul(al7, bh3)) | 0; + mid = (mid + Math.imul(ah7, bl3)) | 0; + hi = (hi + Math.imul(ah7, bh3)) | 0; + lo = (lo + Math.imul(al6, bl4)) | 0; + mid = (mid + Math.imul(al6, bh4)) | 0; + mid = (mid + Math.imul(ah6, bl4)) | 0; + hi = (hi + Math.imul(ah6, bh4)) | 0; + lo = (lo + Math.imul(al5, bl5)) | 0; + mid = (mid + Math.imul(al5, bh5)) | 0; + mid = (mid + Math.imul(ah5, bl5)) | 0; + hi = (hi + Math.imul(ah5, bh5)) | 0; + lo = (lo + Math.imul(al4, bl6)) | 0; + mid = (mid + Math.imul(al4, bh6)) | 0; + mid = (mid + Math.imul(ah4, bl6)) | 0; + hi = (hi + Math.imul(ah4, bh6)) | 0; + lo = (lo + Math.imul(al3, bl7)) | 0; + mid = (mid + Math.imul(al3, bh7)) | 0; + mid = (mid + Math.imul(ah3, bl7)) | 0; + hi = (hi + Math.imul(ah3, bh7)) | 0; + lo = (lo + Math.imul(al2, bl8)) | 0; + mid = (mid + Math.imul(al2, bh8)) | 0; + mid = (mid + Math.imul(ah2, bl8)) | 0; + hi = (hi + Math.imul(ah2, bh8)) | 0; + lo = (lo + Math.imul(al1, bl9)) | 0; + mid = (mid + Math.imul(al1, bh9)) | 0; + mid = (mid + Math.imul(ah1, bl9)) | 0; + hi = (hi + Math.imul(ah1, bh9)) | 0; + var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0; + w10 &= 0x3ffffff; + /* k = 11 */ + lo = Math.imul(al9, bl2); + mid = Math.imul(al9, bh2); + mid = (mid + Math.imul(ah9, bl2)) | 0; + hi = Math.imul(ah9, bh2); + lo = (lo + Math.imul(al8, bl3)) | 0; + mid = (mid + Math.imul(al8, bh3)) | 0; + mid = (mid + Math.imul(ah8, bl3)) | 0; + hi = (hi + Math.imul(ah8, bh3)) | 0; + lo = (lo + Math.imul(al7, bl4)) | 0; + mid = (mid + Math.imul(al7, bh4)) | 0; + mid = (mid + Math.imul(ah7, bl4)) | 0; + hi = (hi + Math.imul(ah7, bh4)) | 0; + lo = (lo + Math.imul(al6, bl5)) | 0; + mid = (mid + Math.imul(al6, bh5)) | 0; + mid = (mid + Math.imul(ah6, bl5)) | 0; + hi = (hi + Math.imul(ah6, bh5)) | 0; + lo = (lo + Math.imul(al5, bl6)) | 0; + mid = (mid + Math.imul(al5, bh6)) | 0; + mid = (mid + Math.imul(ah5, bl6)) | 0; + hi = (hi + Math.imul(ah5, bh6)) | 0; + lo = (lo + Math.imul(al4, bl7)) | 0; + mid = (mid + Math.imul(al4, bh7)) | 0; + mid = (mid + Math.imul(ah4, bl7)) | 0; + hi = (hi + Math.imul(ah4, bh7)) | 0; + lo = (lo + Math.imul(al3, bl8)) | 0; + mid = (mid + Math.imul(al3, bh8)) | 0; + mid = (mid + Math.imul(ah3, bl8)) | 0; + hi = (hi + Math.imul(ah3, bh8)) | 0; + lo = (lo + Math.imul(al2, bl9)) | 0; + mid = (mid + Math.imul(al2, bh9)) | 0; + mid = (mid + Math.imul(ah2, bl9)) | 0; + hi = (hi + Math.imul(ah2, bh9)) | 0; + var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0; + w11 &= 0x3ffffff; + /* k = 12 */ + lo = Math.imul(al9, bl3); + mid = Math.imul(al9, bh3); + mid = (mid + Math.imul(ah9, bl3)) | 0; + hi = Math.imul(ah9, bh3); + lo = (lo + Math.imul(al8, bl4)) | 0; + mid = (mid + Math.imul(al8, bh4)) | 0; + mid = (mid + Math.imul(ah8, bl4)) | 0; + hi = (hi + Math.imul(ah8, bh4)) | 0; + lo = (lo + Math.imul(al7, bl5)) | 0; + mid = (mid + Math.imul(al7, bh5)) | 0; + mid = (mid + Math.imul(ah7, bl5)) | 0; + hi = (hi + Math.imul(ah7, bh5)) | 0; + lo = (lo + Math.imul(al6, bl6)) | 0; + mid = (mid + Math.imul(al6, bh6)) | 0; + mid = (mid + Math.imul(ah6, bl6)) | 0; + hi = (hi + Math.imul(ah6, bh6)) | 0; + lo = (lo + Math.imul(al5, bl7)) | 0; + mid = (mid + Math.imul(al5, bh7)) | 0; + mid = (mid + Math.imul(ah5, bl7)) | 0; + hi = (hi + Math.imul(ah5, bh7)) | 0; + lo = (lo + Math.imul(al4, bl8)) | 0; + mid = (mid + Math.imul(al4, bh8)) | 0; + mid = (mid + Math.imul(ah4, bl8)) | 0; + hi = (hi + Math.imul(ah4, bh8)) | 0; + lo = (lo + Math.imul(al3, bl9)) | 0; + mid = (mid + Math.imul(al3, bh9)) | 0; + mid = (mid + Math.imul(ah3, bl9)) | 0; + hi = (hi + Math.imul(ah3, bh9)) | 0; + var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0; + w12 &= 0x3ffffff; + /* k = 13 */ + lo = Math.imul(al9, bl4); + mid = Math.imul(al9, bh4); + mid = (mid + Math.imul(ah9, bl4)) | 0; + hi = Math.imul(ah9, bh4); + lo = (lo + Math.imul(al8, bl5)) | 0; + mid = (mid + Math.imul(al8, bh5)) | 0; + mid = (mid + Math.imul(ah8, bl5)) | 0; + hi = (hi + Math.imul(ah8, bh5)) | 0; + lo = (lo + Math.imul(al7, bl6)) | 0; + mid = (mid + Math.imul(al7, bh6)) | 0; + mid = (mid + Math.imul(ah7, bl6)) | 0; + hi = (hi + Math.imul(ah7, bh6)) | 0; + lo = (lo + Math.imul(al6, bl7)) | 0; + mid = (mid + Math.imul(al6, bh7)) | 0; + mid = (mid + Math.imul(ah6, bl7)) | 0; + hi = (hi + Math.imul(ah6, bh7)) | 0; + lo = (lo + Math.imul(al5, bl8)) | 0; + mid = (mid + Math.imul(al5, bh8)) | 0; + mid = (mid + Math.imul(ah5, bl8)) | 0; + hi = (hi + Math.imul(ah5, bh8)) | 0; + lo = (lo + Math.imul(al4, bl9)) | 0; + mid = (mid + Math.imul(al4, bh9)) | 0; + mid = (mid + Math.imul(ah4, bl9)) | 0; + hi = (hi + Math.imul(ah4, bh9)) | 0; + var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0; + w13 &= 0x3ffffff; + /* k = 14 */ + lo = Math.imul(al9, bl5); + mid = Math.imul(al9, bh5); + mid = (mid + Math.imul(ah9, bl5)) | 0; + hi = Math.imul(ah9, bh5); + lo = (lo + Math.imul(al8, bl6)) | 0; + mid = (mid + Math.imul(al8, bh6)) | 0; + mid = (mid + Math.imul(ah8, bl6)) | 0; + hi = (hi + Math.imul(ah8, bh6)) | 0; + lo = (lo + Math.imul(al7, bl7)) | 0; + mid = (mid + Math.imul(al7, bh7)) | 0; + mid = (mid + Math.imul(ah7, bl7)) | 0; + hi = (hi + Math.imul(ah7, bh7)) | 0; + lo = (lo + Math.imul(al6, bl8)) | 0; + mid = (mid + Math.imul(al6, bh8)) | 0; + mid = (mid + Math.imul(ah6, bl8)) | 0; + hi = (hi + Math.imul(ah6, bh8)) | 0; + lo = (lo + Math.imul(al5, bl9)) | 0; + mid = (mid + Math.imul(al5, bh9)) | 0; + mid = (mid + Math.imul(ah5, bl9)) | 0; + hi = (hi + Math.imul(ah5, bh9)) | 0; + var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0; + w14 &= 0x3ffffff; + /* k = 15 */ + lo = Math.imul(al9, bl6); + mid = Math.imul(al9, bh6); + mid = (mid + Math.imul(ah9, bl6)) | 0; + hi = Math.imul(ah9, bh6); + lo = (lo + Math.imul(al8, bl7)) | 0; + mid = (mid + Math.imul(al8, bh7)) | 0; + mid = (mid + Math.imul(ah8, bl7)) | 0; + hi = (hi + Math.imul(ah8, bh7)) | 0; + lo = (lo + Math.imul(al7, bl8)) | 0; + mid = (mid + Math.imul(al7, bh8)) | 0; + mid = (mid + Math.imul(ah7, bl8)) | 0; + hi = (hi + Math.imul(ah7, bh8)) | 0; + lo = (lo + Math.imul(al6, bl9)) | 0; + mid = (mid + Math.imul(al6, bh9)) | 0; + mid = (mid + Math.imul(ah6, bl9)) | 0; + hi = (hi + Math.imul(ah6, bh9)) | 0; + var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0; + w15 &= 0x3ffffff; + /* k = 16 */ + lo = Math.imul(al9, bl7); + mid = Math.imul(al9, bh7); + mid = (mid + Math.imul(ah9, bl7)) | 0; + hi = Math.imul(ah9, bh7); + lo = (lo + Math.imul(al8, bl8)) | 0; + mid = (mid + Math.imul(al8, bh8)) | 0; + mid = (mid + Math.imul(ah8, bl8)) | 0; + hi = (hi + Math.imul(ah8, bh8)) | 0; + lo = (lo + Math.imul(al7, bl9)) | 0; + mid = (mid + Math.imul(al7, bh9)) | 0; + mid = (mid + Math.imul(ah7, bl9)) | 0; + hi = (hi + Math.imul(ah7, bh9)) | 0; + var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0; + w16 &= 0x3ffffff; + /* k = 17 */ + lo = Math.imul(al9, bl8); + mid = Math.imul(al9, bh8); + mid = (mid + Math.imul(ah9, bl8)) | 0; + hi = Math.imul(ah9, bh8); + lo = (lo + Math.imul(al8, bl9)) | 0; + mid = (mid + Math.imul(al8, bh9)) | 0; + mid = (mid + Math.imul(ah8, bl9)) | 0; + hi = (hi + Math.imul(ah8, bh9)) | 0; + var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0; + w17 &= 0x3ffffff; + /* k = 18 */ + lo = Math.imul(al9, bl9); + mid = Math.imul(al9, bh9); + mid = (mid + Math.imul(ah9, bl9)) | 0; + hi = Math.imul(ah9, bh9); + var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0; + w18 &= 0x3ffffff; + o[0] = w0; + o[1] = w1; + o[2] = w2; + o[3] = w3; + o[4] = w4; + o[5] = w5; + o[6] = w6; + o[7] = w7; + o[8] = w8; + o[9] = w9; + o[10] = w10; + o[11] = w11; + o[12] = w12; + o[13] = w13; + o[14] = w14; + o[15] = w15; + o[16] = w16; + o[17] = w17; + o[18] = w18; + if (c !== 0) { + o[19] = c; + out.length++; + } + return out; + }; - if (asyncProxy) { - // use web worker if available - return asyncProxy.delegate('decryptSessionKeys', { message, privateKeys, passwords }); + // Polyfill comb + if (!Math.imul) { + comb10MulTo = smallMulTo; } - return Promise.resolve().then(async function () { - - return message.decryptSessionKeys(privateKeys, passwords); - }).catch(onError.bind(null, 'Error decrypting session keys')); -} - -////////////////////////// -// // -// Helper functions // -// // -////////////////////////// - - -/** - * Input validation - */ -function checkString(data, name) { - if (!_util2.default.isString(data)) { - throw new Error('Parameter [' + (name || 'data') + '] must be of type String'); - } -} -function checkBinary(data, name) { - if (!_util2.default.isUint8Array(data)) { - throw new Error('Parameter [' + (name || 'data') + '] must be of type Uint8Array'); - } -} -function checkMessage(message) { - if (!(message instanceof messageLib.Message)) { - throw new Error('Parameter [message] needs to be of type Message'); - } -} -function checkCleartextOrMessage(message) { - if (!(message instanceof _cleartext.CleartextMessage) && !(message instanceof messageLib.Message)) { - throw new Error('Parameter [message] needs to be of type Message or CleartextMessage'); - } -} + function bigMulTo (self, num, out) { + out.negative = num.negative ^ self.negative; + out.length = self.length + num.length; -/** - * Normalize parameter to an array if it is not undefined. - * @param {Object} param the parameter to be normalized - * @returns {Array|undefined} the resulting array or undefined - */ -function toArray(param) { - if (param && !_util2.default.isArray(param)) { - param = [param]; - } - return param; -} + var carry = 0; + var hncarry = 0; + for (var k = 0; k < out.length - 1; k++) { + // Sum all words with the same `i + j = k` and accumulate `ncarry`, + // note that ncarry could be >= 0x3ffffff + var ncarry = hncarry; + hncarry = 0; + var rword = carry & 0x3ffffff; + var maxJ = Math.min(k, num.length - 1); + for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { + var i = k - j; + var a = self.words[i] | 0; + var b = num.words[j] | 0; + var r = a * b; -/** - * Convert data to or from Stream - * @param {Object} data the data to convert - * @param {'web'|'node'|false} streaming (optional) whether to return a ReadableStream - * @returns {Object} the data in the respective format - */ -async function convertStream(data, streaming) { - if (!streaming && _util2.default.isStream(data)) { - return _webStreamTools2.default.readToEnd(data); - } - if (streaming && !_util2.default.isStream(data)) { - data = new ReadableStream({ - start(controller) { - controller.enqueue(data); - controller.close(); - } - }); - } - if (streaming === 'node') { - data = _webStreamTools2.default.webToNode(data); - } - return data; -} + var lo = r & 0x3ffffff; + ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0; + lo = (lo + rword) | 0; + rword = lo & 0x3ffffff; + ncarry = (ncarry + (lo >>> 26)) | 0; -/** - * Convert object properties from Stream - * @param {Object} obj the data to convert - * @param {'web'|'node'|false} streaming (optional) whether to return ReadableStreams - * @param {Array} keys (optional) which keys to return as streams, if possible - * @returns {Object} the data in the respective format - */ -async function convertStreams(obj, streaming, keys = []) { - if (Object.prototype.isPrototypeOf(obj) && !Uint8Array.prototype.isPrototypeOf(obj)) { - await Promise.all(Object.entries(obj).map(async ([key, value]) => { - // recursively search all children - if (_util2.default.isStream(value) || keys.includes(key)) { - obj[key] = await convertStream(value, streaming); - } else { - await convertStreams(obj[key], streaming); + hncarry += ncarry >>> 26; + ncarry &= 0x3ffffff; } - })); - } - return obj; -} - -/** - * Link result.data to the message stream for cancellation. - * @param {Object} result the data to convert - * @param {Message} message message object - * @returns {Object} - */ -function linkStreams(result, message) { - result.data = _webStreamTools2.default.transformPair(message.packets.stream, async (readable, writable) => { - await _webStreamTools2.default.pipe(result.data, writable); - }); -} - -/** - * Wait until signature objects have been verified - * @param {Object} signatures list of signatures - */ -async function prepareSignatures(signatures) { - await Promise.all(signatures.map(async signature => { - signature.signature = await signature.signature; - try { - signature.valid = await signature.verified; - } catch (e) { - signature.valid = null; - signature.error = e; - _util2.default.print_debug_error(e); + out.words[k] = rword; + carry = ncarry; + ncarry = hncarry; + } + if (carry !== 0) { + out.words[k] = carry; + } else { + out.length--; } - })); -} - -/** - * Global error handler that logs the stack trace and rethrows a high lvl error message. - * @param {String} message A human readable high level error Message - * @param {Error} error The internal error that caused the failure - */ -function onError(message, error) { - // log the stack trace - _util2.default.print_debug_error(error); - - // update error message - try { - error.message = message + ': ' + error.message; - } catch (e) {} - - throw error; -} - -/** - * Check for native AEAD support and configuration by the user. Only - * browsers that implement the current WebCrypto specification support - * native GCM. Native EAX is built on CTR and CBC, which current - * browsers support. OCB and CFB are not natively supported. - * @returns {Boolean} If authenticated encryption should be used - */ -function nativeAEAD() { - return _config2.default.aead_protect && (_config2.default.aead_mode === _enums2.default.aead.eax || _config2.default.aead_mode === _enums2.default.aead.experimental_gcm) && _util2.default.getWebCrypto(); -} - -},{"./cleartext":77,"./config/config":78,"./enums":113,"./key":116,"./message":120,"./polyfills":144,"./util":152,"./worker/async_proxy":154,"web-stream-tools":75}],122:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.Trust = exports.Signature = exports.SecretSubkey = exports.Userid = exports.SecretKey = exports.OnePassSignature = exports.UserAttribute = exports.PublicSubkey = exports.Marker = exports.SymmetricallyEncrypted = exports.PublicKey = exports.Literal = exports.SymEncryptedSessionKey = exports.PublicKeyEncryptedSessionKey = exports.SymEncryptedAEADProtected = exports.SymEncryptedIntegrityProtected = exports.Compressed = undefined; - -var _compressed = require('./compressed.js'); - -Object.defineProperty(exports, 'Compressed', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_compressed).default; - } -}); - -var _sym_encrypted_integrity_protected = require('./sym_encrypted_integrity_protected.js'); - -Object.defineProperty(exports, 'SymEncryptedIntegrityProtected', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_sym_encrypted_integrity_protected).default; - } -}); - -var _sym_encrypted_aead_protected = require('./sym_encrypted_aead_protected.js'); - -Object.defineProperty(exports, 'SymEncryptedAEADProtected', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_sym_encrypted_aead_protected).default; - } -}); - -var _public_key_encrypted_session_key = require('./public_key_encrypted_session_key.js'); - -Object.defineProperty(exports, 'PublicKeyEncryptedSessionKey', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_public_key_encrypted_session_key).default; - } -}); - -var _sym_encrypted_session_key = require('./sym_encrypted_session_key.js'); - -Object.defineProperty(exports, 'SymEncryptedSessionKey', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_sym_encrypted_session_key).default; - } -}); - -var _literal = require('./literal.js'); - -Object.defineProperty(exports, 'Literal', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_literal).default; - } -}); - -var _public_key = require('./public_key.js'); - -Object.defineProperty(exports, 'PublicKey', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_public_key).default; - } -}); - -var _symmetrically_encrypted = require('./symmetrically_encrypted.js'); - -Object.defineProperty(exports, 'SymmetricallyEncrypted', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_symmetrically_encrypted).default; - } -}); - -var _marker = require('./marker.js'); - -Object.defineProperty(exports, 'Marker', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_marker).default; - } -}); - -var _public_subkey = require('./public_subkey.js'); - -Object.defineProperty(exports, 'PublicSubkey', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_public_subkey).default; - } -}); - -var _user_attribute = require('./user_attribute.js'); - -Object.defineProperty(exports, 'UserAttribute', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_user_attribute).default; - } -}); - -var _one_pass_signature = require('./one_pass_signature.js'); - -Object.defineProperty(exports, 'OnePassSignature', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_one_pass_signature).default; - } -}); - -var _secret_key = require('./secret_key.js'); -Object.defineProperty(exports, 'SecretKey', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_secret_key).default; + return out.strip(); } -}); -var _userid = require('./userid.js'); - -Object.defineProperty(exports, 'Userid', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_userid).default; + function jumboMulTo (self, num, out) { + var fftm = new FFTM(); + return fftm.mulp(self, num, out); } -}); -var _secret_subkey = require('./secret_subkey.js'); + BN.prototype.mulTo = function mulTo (num, out) { + var res; + var len = this.length + num.length; + if (this.length === 10 && num.length === 10) { + res = comb10MulTo(this, num, out); + } else if (len < 63) { + res = smallMulTo(this, num, out); + } else if (len < 1024) { + res = bigMulTo(this, num, out); + } else { + res = jumboMulTo(this, num, out); + } -Object.defineProperty(exports, 'SecretSubkey', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_secret_subkey).default; - } -}); + return res; + }; -var _signature = require('./signature.js'); + // Cooley-Tukey algorithm for FFT + // slightly revisited to rely on looping instead of recursion -Object.defineProperty(exports, 'Signature', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_signature).default; + function FFTM (x, y) { + this.x = x; + this.y = y; } -}); -var _trust = require('./trust.js'); + FFTM.prototype.makeRBT = function makeRBT (N) { + var t = new Array(N); + var l = BN.prototype._countBits(N) - 1; + for (var i = 0; i < N; i++) { + t[i] = this.revBin(i, l, N); + } -Object.defineProperty(exports, 'Trust', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_trust).default; - } -}); -exports.newPacketFromTag = newPacketFromTag; -exports.fromStructuredClone = fromStructuredClone; + return t; + }; -var _enums = require('../enums.js'); + // Returns binary-reversed representation of `x` + FFTM.prototype.revBin = function revBin (x, l, N) { + if (x === 0 || x === N - 1) return x; -var _enums2 = _interopRequireDefault(_enums); + var rb = 0; + for (var i = 0; i < l; i++) { + rb |= (x & 1) << (l - i - 1); + x >>= 1; + } -var _all_packets = require('./all_packets.js'); + return rb; + }; -var packets = _interopRequireWildcard(_all_packets); + // Performs "tweedling" phase, therefore 'emulating' + // behaviour of the recursive algorithm + FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) { + for (var i = 0; i < N; i++) { + rtws[i] = rws[rbt[i]]; + itws[i] = iws[rbt[i]]; + } + }; -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) { + this.permute(rbt, rws, iws, rtws, itws, N); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + for (var s = 1; s < N; s <<= 1) { + var l = s << 1; -/** - * Allocate a new packet - * @function newPacketFromTag - * @memberof module:packet - * @param {String} tag property name from {@link module:enums.packet} - * @returns {Object} new packet object with type based on tag - */ -function newPacketFromTag(tag) { - return new packets[packetClassFromTagName(tag)](); -} + var rtwdf = Math.cos(2 * Math.PI / l); + var itwdf = Math.sin(2 * Math.PI / l); -/** - * Allocate a new packet from structured packet clone - * @see {@link https://w3c.github.io/html/infrastructure.html#safe-passing-of-structured-data} - * @function fromStructuredClone - * @memberof module:packet - * @param {Object} packetClone packet clone - * @returns {Object} new packet object with data from packet clone - */ -function fromStructuredClone(packetClone) { - const tagName = _enums2.default.read(_enums2.default.packet, packetClone.tag); - const packet = newPacketFromTag(tagName); - Object.assign(packet, packetClone); - if (packet.postCloneTypeFix) { - packet.postCloneTypeFix(); - } - return packet; -} + for (var p = 0; p < N; p += l) { + var rtwdf_ = rtwdf; + var itwdf_ = itwdf; -/** - * Convert tag name to class name - * @param {String} tag property name from {@link module:enums.packet} - * @returns {String} - * @private - */ -function packetClassFromTagName(tag) { - return tag.substr(0, 1).toUpperCase() + tag.substr(1); -} + for (var j = 0; j < s; j++) { + var re = rtws[p + j]; + var ie = itws[p + j]; -},{"../enums.js":113,"./all_packets.js":122,"./compressed.js":124,"./literal.js":126,"./marker.js":127,"./one_pass_signature.js":128,"./public_key.js":131,"./public_key_encrypted_session_key.js":132,"./public_subkey.js":133,"./secret_key.js":134,"./secret_subkey.js":135,"./signature.js":136,"./sym_encrypted_aead_protected.js":137,"./sym_encrypted_integrity_protected.js":138,"./sym_encrypted_session_key.js":139,"./symmetrically_encrypted.js":140,"./trust.js":141,"./user_attribute.js":142,"./userid.js":143}],123:[function(require,module,exports){ -'use strict'; + var ro = rtws[p + j + s]; + var io = itws[p + j + s]; -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.clonePackets = clonePackets; -exports.parseClonedPackets = parseClonedPackets; + var rx = rtwdf_ * ro - itwdf_ * io; -var _webStreamTools = require('web-stream-tools'); + io = rtwdf_ * io + itwdf_ * ro; + ro = rx; -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); + rtws[p + j] = re + ro; + itws[p + j] = ie + io; -var _key = require('../key'); + rtws[p + j + s] = re - ro; + itws[p + j + s] = ie - io; -var _message = require('../message'); + /* jshint maxdepth : false */ + if (j !== l) { + rx = rtwdf * rtwdf_ - itwdf * itwdf_; -var _cleartext = require('../cleartext'); + itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_; + rtwdf_ = rx; + } + } + } + } + }; -var _signature = require('../signature'); + FFTM.prototype.guessLen13b = function guessLen13b (n, m) { + var N = Math.max(m, n) | 1; + var odd = N & 1; + var i = 0; + for (N = N / 2 | 0; N; N = N >>> 1) { + i++; + } -var _packetlist = require('./packetlist'); + return 1 << i + 1 + odd; + }; -var _packetlist2 = _interopRequireDefault(_packetlist); + FFTM.prototype.conjugate = function conjugate (rws, iws, N) { + if (N <= 1) return; -var _keyid = require('../type/keyid'); + for (var i = 0; i < N / 2; i++) { + var t = rws[i]; -var _keyid2 = _interopRequireDefault(_keyid); + rws[i] = rws[N - i - 1]; + rws[N - i - 1] = t; -var _util = require('../util'); + t = iws[i]; -var _util2 = _interopRequireDefault(_util); + iws[i] = -iws[N - i - 1]; + iws[N - i - 1] = -t; + } + }; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + FFTM.prototype.normalize13b = function normalize13b (ws, N) { + var carry = 0; + for (var i = 0; i < N / 2; i++) { + var w = Math.round(ws[2 * i + 1] / N) * 0x2000 + + Math.round(ws[2 * i] / N) + + carry; -////////////////////////////// -// // -// List --> Clone // -// // -////////////////////////////// + ws[i] = w & 0x3ffffff; + if (w < 0x4000000) { + carry = 0; + } else { + carry = w / 0x4000000 | 0; + } + } -/** - * Create a packetlist from the correspoding object types. - * @param {Object} options the object passed to and from the web worker - * @returns {Object} a mutated version of the options optject - */ -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2015 Tankred Hase -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + return ws; + }; -/** - * @fileoverview This module implements packet list cloning required to - * pass certain object types between the web worker and main thread using - * the structured cloning algorithm. - * @module packet/clone - */ + FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) { + var carry = 0; + for (var i = 0; i < len; i++) { + carry = carry + (ws[i] | 0); -function clonePackets(options) { - if (options.publicKeys) { - options.publicKeys = options.publicKeys.map(key => key.toPacketlist()); - } - if (options.privateKeys) { - options.privateKeys = options.privateKeys.map(key => key.toPacketlist()); - } - if (options.privateKey) { - options.privateKey = options.privateKey.toPacketlist(); - } - if (options.key) { - options.key = options.key.toPacketlist(); - } - if (options.message) { - //could be either a Message or CleartextMessage object - if (options.message instanceof _message.Message) { - options.message = options.message.packets; - } else if (options.message instanceof _cleartext.CleartextMessage) { - options.message = { text: options.message.text, signature: options.message.signature.packets }; + rws[2 * i] = carry & 0x1fff; carry = carry >>> 13; + rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13; } - } - if (options.signature && options.signature instanceof _signature.Signature) { - options.signature = options.signature.packets; - } - if (options.signatures) { - options.signatures.forEach(verificationObjectToClone); - } - return options; -} -function verificationObjectToClone(verObject) { - const verified = verObject.verified; - verObject.verified = _webStreamTools2.default.fromAsync(() => verified); - if (verObject.signature instanceof Promise) { - const signature = verObject.signature; - verObject.signature = _webStreamTools2.default.fromAsync(async () => { - const packets = (await signature).packets; - try { - await verified; - delete packets[0].signature; - } catch (e) {} - return packets; - }); - } else { - verObject.signature = verObject.signature.packets; - } - if (verObject.error) { - verObject.error = verObject.error.message; - } - return verObject; -} + // Pad with zeroes + for (i = 2 * len; i < N; ++i) { + rws[i] = 0; + } -////////////////////////////// -// // -// Clone --> List // -// // -////////////////////////////// + assert(carry === 0); + assert((carry & ~0x1fff) === 0); + }; + FFTM.prototype.stub = function stub (N) { + var ph = new Array(N); + for (var i = 0; i < N; i++) { + ph[i] = 0; + } -/** - * Creates an object with the correct prototype from a corresponding packetlist. - * @param {Object} options the object passed to and from the web worker - * @param {String} method the public api function name to be delegated to the worker - * @returns {Object} a mutated version of the options optject - */ -function parseClonedPackets(options) { - if (options.publicKeys) { - options.publicKeys = options.publicKeys.map(packetlistCloneToKey); - } - if (options.privateKeys) { - options.privateKeys = options.privateKeys.map(packetlistCloneToKey); - } - if (options.privateKey) { - options.privateKey = packetlistCloneToKey(options.privateKey); - } - if (options.key) { - options.key = packetlistCloneToKey(options.key); - } - if (options.message && options.message.signature) { - options.message = packetlistCloneToCleartextMessage(options.message); - } else if (options.message) { - options.message = packetlistCloneToMessage(options.message); - } - if (options.signatures) { - options.signatures = options.signatures.map(packetlistCloneToSignatures); - } - if (options.signature) { - options.signature = packetlistCloneToSignature(options.signature); - } - return options; -} + return ph; + }; -function packetlistCloneToKey(clone) { - const packetlist = _packetlist2.default.fromStructuredClone(clone); - return new _key.Key(packetlist); -} + FFTM.prototype.mulp = function mulp (x, y, out) { + var N = 2 * this.guessLen13b(x.length, y.length); -function packetlistCloneToMessage(clone) { - const packetlist = _packetlist2.default.fromStructuredClone(clone); - return new _message.Message(packetlist); -} + var rbt = this.makeRBT(N); -function packetlistCloneToCleartextMessage(clone) { - const packetlist = _packetlist2.default.fromStructuredClone(clone.signature); - return new _cleartext.CleartextMessage(clone.text, new _signature.Signature(packetlist)); -} + var _ = this.stub(N); -//verification objects -function packetlistCloneToSignatures(clone) { - clone.keyid = _keyid2.default.fromClone(clone.keyid); - if (_util2.default.isStream(clone.signature)) { - clone.signature = _webStreamTools2.default.readToEnd(clone.signature, ([signature]) => new _signature.Signature(_packetlist2.default.fromStructuredClone(signature))); - clone.signature.catch(() => {}); - } else { - clone.signature = new _signature.Signature(_packetlist2.default.fromStructuredClone(clone.signature)); - } - clone.verified = _webStreamTools2.default.readToEnd(clone.verified, ([verified]) => verified); - clone.verified.catch(() => {}); - if (clone.error) { - clone.error = new Error(clone.error); - } - return clone; -} + var rws = new Array(N); + var rwst = new Array(N); + var iwst = new Array(N); -function packetlistCloneToSignature(clone) { - if (_util2.default.isString(clone) || _util2.default.isStream(clone)) { - //signature is armored - return clone; - } - const packetlist = _packetlist2.default.fromStructuredClone(clone); - return new _signature.Signature(packetlist); -} + var nrws = new Array(N); + var nrwst = new Array(N); + var niwst = new Array(N); -},{"../cleartext":77,"../key":116,"../message":120,"../signature":145,"../type/keyid":148,"../util":152,"./packetlist":130,"web-stream-tools":75}],124:[function(require,module,exports){ -'use strict'; + var rmws = out.words; + rmws.length = N; -Object.defineProperty(exports, "__esModule", { - value: true -}); + this.convert13b(x.words, x.length, rws, N); + this.convert13b(y.words, y.length, nrws, N); + + this.transform(rws, _, rwst, iwst, N, rbt); + this.transform(nrws, _, nrwst, niwst, N, rbt); -var _pako = require('pako'); + for (var i = 0; i < N; i++) { + var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i]; + iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i]; + rwst[i] = rx; + } + + this.conjugate(rwst, iwst, N); + this.transform(rwst, iwst, rmws, _, N, rbt); + this.conjugate(rmws, _, N); + this.normalize13b(rmws, N); -var _pako2 = _interopRequireDefault(_pako); + out.negative = x.negative ^ y.negative; + out.length = x.length + y.length; + return out.strip(); + }; -var _seekBzip = require('seek-bzip'); + // Multiply `this` by `num` + BN.prototype.mul = function mul (num) { + var out = new BN(null); + out.words = new Array(this.length + num.length); + return this.mulTo(num, out); + }; -var _seekBzip2 = _interopRequireDefault(_seekBzip); + // Multiply employing FFT + BN.prototype.mulf = function mulf (num) { + var out = new BN(null); + out.words = new Array(this.length + num.length); + return jumboMulTo(this, num, out); + }; -var _webStreamTools = require('web-stream-tools'); + // In-place Multiplication + BN.prototype.imul = function imul (num) { + return this.clone().mulTo(num, this); + }; -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); + BN.prototype.imuln = function imuln (num) { + assert(typeof num === 'number'); + assert(num < 0x4000000); -var _config = require('../config'); + // Carry + var carry = 0; + for (var i = 0; i < this.length; i++) { + var w = (this.words[i] | 0) * num; + var lo = (w & 0x3ffffff) + (carry & 0x3ffffff); + carry >>= 26; + carry += (w / 0x4000000) | 0; + // NOTE: lo is 27bit maximum + carry += lo >>> 26; + this.words[i] = lo & 0x3ffffff; + } -var _config2 = _interopRequireDefault(_config); + if (carry !== 0) { + this.words[i] = carry; + this.length++; + } -var _enums = require('../enums'); + return this; + }; -var _enums2 = _interopRequireDefault(_enums); + BN.prototype.muln = function muln (num) { + return this.clone().imuln(num); + }; -var _util = require('../util'); + // `this` * `this` + BN.prototype.sqr = function sqr () { + return this.mul(this); + }; -var _util2 = _interopRequireDefault(_util); + // `this` * `this` in-place + BN.prototype.isqr = function isqr () { + return this.imul(this.clone()); + }; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + // Math.pow(`this`, `num`) + BN.prototype.pow = function pow (num) { + var w = toBitArray(num); + if (w.length === 0) return new BN(1); -/** - * Implementation of the Compressed Data Packet (Tag 8) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.6|RFC4880 5.6}: - * The Compressed Data packet contains compressed data. Typically, - * this packet is found as the contents of an encrypted packet, or following - * a Signature or One-Pass Signature packet, and contains a literal data packet. - * @memberof module:packet - * @constructor - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + // Skip leading zeroes + var res = this; + for (var i = 0; i < w.length; i++, res = res.sqr()) { + if (w[i] !== 0) break; + } -/** - * @requires web-stream-tools - * @requires pako - * @requires config - * @requires enums - * @requires util - * @requires compression/bzip2 - */ + if (++i < w.length) { + for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) { + if (w[i] === 0) continue; -function Compressed() { - /** - * Packet type - * @type {module:enums.packet} - */ - this.tag = _enums2.default.packet.compressed; - /** - * List of packets - * @type {module:packet.List} - */ - this.packets = null; - /** - * Compression algorithm - * @type {compression} - */ - this.algorithm = 'zip'; + res = res.mul(q); + } + } - /** - * Compressed packet data - * @type {Uint8Array | ReadableStream} - */ - this.compressed = null; -} + return res; + }; -/** - * Parsing function for the packet. - * @param {Uint8Array | ReadableStream} bytes Payload of a tag 8 packet - */ -Compressed.prototype.read = async function (bytes, streaming) { - await _webStreamTools2.default.parse(bytes, async reader => { + // Shift-left in-place + BN.prototype.iushln = function iushln (bits) { + assert(typeof bits === 'number' && bits >= 0); + var r = bits % 26; + var s = (bits - r) / 26; + var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r); + var i; - // One octet that gives the algorithm used to compress the packet. - this.algorithm = _enums2.default.read(_enums2.default.compression, (await reader.readByte())); + if (r !== 0) { + var carry = 0; - // Compressed data, which makes up the remainder of the packet. - this.compressed = reader.remainder(); + for (i = 0; i < this.length; i++) { + var newCarry = this.words[i] & carryMask; + var c = ((this.words[i] | 0) - newCarry) << r; + this.words[i] = c | carry; + carry = newCarry >>> (26 - r); + } - await this.decompress(streaming); - }); -}; + if (carry) { + this.words[i] = carry; + this.length++; + } + } -/** - * Return the compressed packet. - * @returns {Uint8Array | ReadableStream} binary compressed packet - */ -Compressed.prototype.write = function () { - if (this.compressed === null) { - this.compress(); - } + if (s !== 0) { + for (i = this.length - 1; i >= 0; i--) { + this.words[i + s] = this.words[i]; + } - return _util2.default.concat([new Uint8Array([_enums2.default.write(_enums2.default.compression, this.algorithm)]), this.compressed]); -}; + for (i = 0; i < s; i++) { + this.words[i] = 0; + } -/** - * Decompression method for decompressing the compressed data - * read by read_packet - */ -Compressed.prototype.decompress = async function (streaming) { + this.length += s; + } - if (!decompress_fns[this.algorithm]) { - throw new Error(this.algorithm + ' decompression not supported'); - } + return this.strip(); + }; - await this.packets.read(decompress_fns[this.algorithm](this.compressed), streaming); -}; + BN.prototype.ishln = function ishln (bits) { + // TODO(indutny): implement me + assert(this.negative === 0); + return this.iushln(bits); + }; -/** - * Compress the packet data (member decompressedData) - */ -Compressed.prototype.compress = function () { + // Shift-right in-place + // NOTE: `hint` is a lowest bit before trailing zeroes + // NOTE: if `extended` is present - it will be filled with destroyed bits + BN.prototype.iushrn = function iushrn (bits, hint, extended) { + assert(typeof bits === 'number' && bits >= 0); + var h; + if (hint) { + h = (hint - (hint % 26)) / 26; + } else { + h = 0; + } - if (!compress_fns[this.algorithm]) { - throw new Error(this.algorithm + ' compression not supported'); - } + var r = bits % 26; + var s = Math.min((bits - r) / 26, this.length); + var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); + var maskedWords = extended; - this.compressed = compress_fns[this.algorithm](this.packets.write()); -}; + h -= s; + h = Math.max(0, h); -exports.default = Compressed; + // Extended mode, copy masked part + if (maskedWords) { + for (var i = 0; i < s; i++) { + maskedWords.words[i] = this.words[i]; + } + maskedWords.length = s; + } -////////////////////////// -// // -// Helper functions // -// // -////////////////////////// + if (s === 0) ; else if (this.length > s) { + this.length -= s; + for (i = 0; i < this.length; i++) { + this.words[i] = this.words[i + s]; + } + } else { + this.words[0] = 0; + this.length = 1; + } + var carry = 0; + for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) { + var word = this.words[i] | 0; + this.words[i] = (carry << (26 - r)) | (word >>> r); + carry = word & mask; + } -const nodeZlib = _util2.default.getNodeZlib(); + // Push carried bits as a mask + if (maskedWords && carry !== 0) { + maskedWords.words[maskedWords.length++] = carry; + } -function node_zlib(func, options = {}) { - return function (data) { - return _webStreamTools2.default.nodeToWeb(_webStreamTools2.default.webToNode(data).pipe(func(options))); - }; -} + if (this.length === 0) { + this.words[0] = 0; + this.length = 1; + } -function pako_zlib(constructor, options = {}) { - return function (data) { - const obj = new constructor(options); - return _webStreamTools2.default.transform(data, value => { - if (value.length) { - obj.push(value, _pako2.default.Z_SYNC_FLUSH); - return obj.result; - } - }, () => { - if (constructor === _pako2.default.Deflate) { - obj.push([], _pako2.default.Z_FINISH); - return obj.result; - } - }); + return this.strip(); }; -} -function bzip2(func) { - return function (data) { - return _webStreamTools2.default.fromAsync(async () => func((await _webStreamTools2.default.readToEnd(data)))); + BN.prototype.ishrn = function ishrn (bits, hint, extended) { + // TODO(indutny): implement me + assert(this.negative === 0); + return this.iushrn(bits, hint, extended); }; -} -let compress_fns; -let decompress_fns; -if (nodeZlib) { - // Use Node native zlib for DEFLATE compression/decompression - compress_fns = { - zip: node_zlib(nodeZlib.createDeflateRaw, { level: _config2.default.deflate_level }), - zlib: node_zlib(nodeZlib.createDeflate, { level: _config2.default.deflate_level }) + // Shift-left + BN.prototype.shln = function shln (bits) { + return this.clone().ishln(bits); }; - decompress_fns = { - zip: node_zlib(nodeZlib.createInflateRaw), - zlib: node_zlib(nodeZlib.createInflate), - bzip2: bzip2(_seekBzip2.default.decode) - }; -} else { - // Use JS fallbacks - compress_fns = { - zip: pako_zlib(_pako2.default.Deflate, { raw: true, level: _config2.default.deflate_level }), - zlib: pako_zlib(_pako2.default.Deflate, { level: _config2.default.deflate_level }) + BN.prototype.ushln = function ushln (bits) { + return this.clone().iushln(bits); }; - decompress_fns = { - zip: pako_zlib(_pako2.default.Inflate, { raw: true }), - zlib: pako_zlib(_pako2.default.Inflate), - bzip2: bzip2(_seekBzip2.default.decode) + // Shift-right + BN.prototype.shrn = function shrn (bits) { + return this.clone().ishrn(bits); }; -} -},{"../config":79,"../enums":113,"../util":152,"pako":50,"seek-bzip":69,"web-stream-tools":75}],125:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _all_packets = require('./all_packets'); - -var packets = _interopRequireWildcard(_all_packets); - -var _clone = require('./clone'); + BN.prototype.ushrn = function ushrn (bits) { + return this.clone().iushrn(bits); + }; -var clone = _interopRequireWildcard(_clone); + // Test if n bit is set + BN.prototype.testn = function testn (bit) { + assert(typeof bit === 'number' && bit >= 0); + var r = bit % 26; + var s = (bit - r) / 26; + var q = 1 << r; -var _packetlist = require('./packetlist'); + // Fast case: bit is much higher than all existing words + if (this.length <= s) return false; -var _packetlist2 = _interopRequireDefault(_packetlist); + // Check bit and return + var w = this.words[s]; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + return !!(w & q); + }; -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + // Return only lowers bits of number (in-place) + BN.prototype.imaskn = function imaskn (bits) { + assert(typeof bits === 'number' && bits >= 0); + var r = bits % 26; + var s = (bits - r) / 26; -const mod = { - List: _packetlist2.default, - clone -}; /** - * @fileoverview OpenPGP packet types - * @see module:packet/all_packets - * @see module:packet/clone - * @see module:packet.List - * @module packet - */ + assert(this.negative === 0, 'imaskn works only with positive numbers'); -Object.assign(mod, packets); + if (this.length <= s) { + return this; + } -exports.default = mod; + if (r !== 0) { + s++; + } + this.length = Math.min(s, this.length); -},{"./all_packets":122,"./clone":123,"./packetlist":130}],126:[function(require,module,exports){ -'use strict'; + if (r !== 0) { + var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); + this.words[this.length - 1] &= mask; + } -Object.defineProperty(exports, "__esModule", { - value: true -}); + return this.strip(); + }; -var _webStreamTools = require('web-stream-tools'); + // Return only lowers bits of number + BN.prototype.maskn = function maskn (bits) { + return this.clone().imaskn(bits); + }; -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); + // Add plain number `num` to `this` + BN.prototype.iaddn = function iaddn (num) { + assert(typeof num === 'number'); + assert(num < 0x4000000); + if (num < 0) return this.isubn(-num); -var _enums = require('../enums'); + // Possible sign change + if (this.negative !== 0) { + if (this.length === 1 && (this.words[0] | 0) < num) { + this.words[0] = num - (this.words[0] | 0); + this.negative = 0; + return this; + } -var _enums2 = _interopRequireDefault(_enums); + this.negative = 0; + this.isubn(num); + this.negative = 1; + return this; + } -var _util = require('../util'); + // Add without checks + return this._iaddn(num); + }; -var _util2 = _interopRequireDefault(_util); + BN.prototype._iaddn = function _iaddn (num) { + this.words[0] += num; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + // Carry + for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) { + this.words[i] -= 0x4000000; + if (i === this.length - 1) { + this.words[i + 1] = 1; + } else { + this.words[i + 1]++; + } + } + this.length = Math.max(this.length, i + 1); -/** - * Implementation of the Literal Data Packet (Tag 11) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.9|RFC4880 5.9}: - * A Literal Data packet contains the body of a message; data that is not to be - * further interpreted. - * @param {Date} date the creation date of the literal package - * @memberof module:packet - * @constructor - */ -function Literal(date = new Date()) { - this.tag = _enums2.default.packet.literal; - this.format = 'utf8'; // default format for literal data packets - this.date = _util2.default.normalizeDate(date); - this.text = null; // textual data representation - this.data = null; // literal data representation - this.filename = 'msg.txt'; -} + return this; + }; -/** - * Set the packet data to a javascript native string, end of line - * will be normalized to \r\n and by default text is converted to UTF8 - * @param {String | ReadableStream} text Any native javascript string - * @param {utf8|binary|text|mime} format (optional) The format of the string of bytes - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + // Subtract plain number `num` from `this` + BN.prototype.isubn = function isubn (num) { + assert(typeof num === 'number'); + assert(num < 0x4000000); + if (num < 0) return this.iaddn(-num); -/** - * @requires web-stream-tools - * @requires enums - * @requires util - */ + if (this.negative !== 0) { + this.negative = 0; + this.iaddn(num); + this.negative = 1; + return this; + } -Literal.prototype.setText = function (text, format = 'utf8') { - this.format = format; - this.text = text; - this.data = null; -}; + this.words[0] -= num; -/** - * Returns literal data packets as native JavaScript string - * with normalized end of line to \n - * @param {Boolean} clone (optional) Whether to return a clone so that getBytes/getText can be called again - * @returns {String | ReadableStream} literal data as text - */ -Literal.prototype.getText = function (clone = false) { - if (this.text === null || _util2.default.isStream(this.text)) { - // Assume that this.text has been read - this.text = _util2.default.nativeEOL(_util2.default.decode_utf8(this.getBytes(clone))); - } - return this.text; -}; + if (this.length === 1 && this.words[0] < 0) { + this.words[0] = -this.words[0]; + this.negative = 1; + } else { + // Carry + for (var i = 0; i < this.length && this.words[i] < 0; i++) { + this.words[i] += 0x4000000; + this.words[i + 1] -= 1; + } + } -/** - * Set the packet data to value represented by the provided string of bytes. - * @param {Uint8Array | ReadableStream} bytes The string of bytes - * @param {utf8|binary|text|mime} format The format of the string of bytes - */ -Literal.prototype.setBytes = function (bytes, format) { - this.format = format; - this.data = bytes; - this.text = null; -}; + return this.strip(); + }; -/** - * Get the byte sequence representing the literal packet data - * @param {Boolean} clone (optional) Whether to return a clone so that getBytes/getText can be called again - * @returns {Uint8Array | ReadableStream} A sequence of bytes - */ -Literal.prototype.getBytes = function (clone = false) { - if (this.data === null) { - // normalize EOL to \r\n and encode UTF8 - this.data = _util2.default.encode_utf8(_util2.default.canonicalizeEOL(this.text)); - } - if (clone) { - return _webStreamTools2.default.passiveClone(this.data); - } - return this.data; -}; + BN.prototype.addn = function addn (num) { + return this.clone().iaddn(num); + }; -/** - * Sets the filename of the literal packet data - * @param {String} filename Any native javascript string - */ -Literal.prototype.setFilename = function (filename) { - this.filename = filename; -}; + BN.prototype.subn = function subn (num) { + return this.clone().isubn(num); + }; -/** - * Get the filename of the literal packet data - * @returns {String} filename - */ -Literal.prototype.getFilename = function () { - return this.filename; -}; + BN.prototype.iabs = function iabs () { + this.negative = 0; -/** - * Parsing function for a literal data packet (tag 11). - * - * @param {Uint8Array | ReadableStream} input Payload of a tag 11 packet - * @returns {module:packet.Literal} object representation - */ -Literal.prototype.read = async function (bytes) { - await _webStreamTools2.default.parse(bytes, async reader => { - // - A one-octet field that describes how the data is formatted. - const format = _enums2.default.read(_enums2.default.literal, (await reader.readByte())); + return this; + }; - const filename_len = await reader.readByte(); - this.filename = _util2.default.decode_utf8((await reader.readBytes(filename_len))); + BN.prototype.abs = function abs () { + return this.clone().iabs(); + }; - this.date = _util2.default.readDate((await reader.readBytes(4))); + BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) { + var len = num.length + shift; + var i; - const data = reader.remainder(); + this._expand(len); - this.setBytes(data, format); - }); -}; + var w; + var carry = 0; + for (i = 0; i < num.length; i++) { + w = (this.words[i + shift] | 0) + carry; + var right = (num.words[i] | 0) * mul; + w -= right & 0x3ffffff; + carry = (w >> 26) - ((right / 0x4000000) | 0); + this.words[i + shift] = w & 0x3ffffff; + } + for (; i < this.length - shift; i++) { + w = (this.words[i + shift] | 0) + carry; + carry = w >> 26; + this.words[i + shift] = w & 0x3ffffff; + } -/** - * Creates a Uint8Array representation of the packet, excluding the data - * - * @returns {Uint8Array} Uint8Array representation of the packet - */ -Literal.prototype.writeHeader = function () { - const filename = _util2.default.encode_utf8(this.filename); - const filename_length = new Uint8Array([filename.length]); + if (carry === 0) return this.strip(); - const format = new Uint8Array([_enums2.default.write(_enums2.default.literal, this.format)]); - const date = _util2.default.writeDate(this.date); + // Subtraction overflow + assert(carry === -1); + carry = 0; + for (i = 0; i < this.length; i++) { + w = -(this.words[i] | 0) + carry; + carry = w >> 26; + this.words[i] = w & 0x3ffffff; + } + this.negative = 1; - return _util2.default.concatUint8Array([format, filename_length, filename, date]); -}; + return this.strip(); + }; -/** - * Creates a Uint8Array representation of the packet - * - * @returns {Uint8Array | ReadableStream} Uint8Array representation of the packet - */ -Literal.prototype.write = function () { - const header = this.writeHeader(); - const data = this.getBytes(); + BN.prototype._wordDiv = function _wordDiv (num, mode) { + var shift = this.length - num.length; - return _util2.default.concat([header, data]); -}; + var a = this.clone(); + var b = num; -exports.default = Literal; + // Normalize + var bhi = b.words[b.length - 1] | 0; + var bhiBits = this._countBits(bhi); + shift = 26 - bhiBits; + if (shift !== 0) { + b = b.ushln(shift); + a.iushln(shift); + bhi = b.words[b.length - 1] | 0; + } -},{"../enums":113,"../util":152,"web-stream-tools":75}],127:[function(require,module,exports){ -'use strict'; + // Initialize quotient + var m = a.length - b.length; + var q; -Object.defineProperty(exports, "__esModule", { - value: true -}); + if (mode !== 'mod') { + q = new BN(null); + q.length = m + 1; + q.words = new Array(q.length); + for (var i = 0; i < q.length; i++) { + q.words[i] = 0; + } + } -var _enums = require('../enums'); + var diff = a.clone()._ishlnsubmul(b, 1, m); + if (diff.negative === 0) { + a = diff; + if (q) { + q.words[m] = 1; + } + } -var _enums2 = _interopRequireDefault(_enums); + for (var j = m - 1; j >= 0; j--) { + var qj = (a.words[b.length + j] | 0) * 0x4000000 + + (a.words[b.length + j - 1] | 0); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + // NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max + // (0x7ffffff) + qj = Math.min((qj / bhi) | 0, 0x3ffffff); -/** - * Implementation of the strange "Marker packet" (Tag 10) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.8|RFC4880 5.8}: - * An experimental version of PGP used this packet as the Literal - * packet, but no released version of PGP generated Literal packets with this - * tag. With PGP 5.x, this packet has been reassigned and is reserved for use as - * the Marker packet. - * - * Such a packet MUST be ignored when received. - * @memberof module:packet - * @constructor - */ -function Marker() { - this.tag = _enums2.default.packet.marker; -} + a._ishlnsubmul(b, qj, j); + while (a.negative !== 0) { + qj--; + a.negative = 0; + a._ishlnsubmul(b, 1, j); + if (!a.isZero()) { + a.negative ^= 1; + } + } + if (q) { + q.words[j] = qj; + } + } + if (q) { + q.strip(); + } + a.strip(); -/** - * Parsing function for a literal data packet (tag 10). - * - * @param {String} input Payload of a tag 10 packet - * @param {Integer} position - * Position to start reading from the input string - * @param {Integer} len - * Length of the packet or the remaining length of - * input at position - * @returns {module:packet.Marker} Object representation - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + // Denormalize + if (mode !== 'div' && shift !== 0) { + a.iushrn(shift); + } -/** - * @requires enums - */ + return { + div: q || null, + mod: a + }; + }; -Marker.prototype.read = function (bytes) { - if (bytes[0] === 0x50 && // P - bytes[1] === 0x47 && // G - bytes[2] === 0x50) { - // P - return true; - } - // marker packet does not contain "PGP" - return false; -}; + // NOTE: 1) `mode` can be set to `mod` to request mod only, + // to `div` to request div only, or be absent to + // request both div & mod + // 2) `positive` is true if unsigned mod is requested + BN.prototype.divmod = function divmod (num, mode, positive) { + assert(!num.isZero()); -exports.default = Marker; + if (this.isZero()) { + return { + div: new BN(0), + mod: new BN(0) + }; + } -},{"../enums":113}],128:[function(require,module,exports){ -'use strict'; + var div, mod, res; + if (this.negative !== 0 && num.negative === 0) { + res = this.neg().divmod(num, mode); -Object.defineProperty(exports, "__esModule", { - value: true -}); + if (mode !== 'mod') { + div = res.div.neg(); + } -var _webStreamTools = require('web-stream-tools'); + if (mode !== 'div') { + mod = res.mod.neg(); + if (positive && mod.negative !== 0) { + mod.iadd(num); + } + } -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); + return { + div: div, + mod: mod + }; + } -var _signature = require('./signature'); + if (this.negative === 0 && num.negative !== 0) { + res = this.divmod(num.neg(), mode); -var _signature2 = _interopRequireDefault(_signature); + if (mode !== 'mod') { + div = res.div.neg(); + } -var _keyid = require('../type/keyid'); + return { + div: div, + mod: res.mod + }; + } -var _keyid2 = _interopRequireDefault(_keyid); + if ((this.negative & num.negative) !== 0) { + res = this.neg().divmod(num.neg(), mode); -var _enums = require('../enums'); + if (mode !== 'div') { + mod = res.mod.neg(); + if (positive && mod.negative !== 0) { + mod.isub(num); + } + } -var _enums2 = _interopRequireDefault(_enums); + return { + div: res.div, + mod: mod + }; + } -var _util = require('../util'); + // Both numbers are positive at this point -var _util2 = _interopRequireDefault(_util); + // Strip both numbers to approximate shift value + if (num.length > this.length || this.cmp(num) < 0) { + return { + div: new BN(0), + mod: this + }; + } -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + // Very short reduction + if (num.length === 1) { + if (mode === 'div') { + return { + div: this.divn(num.words[0]), + mod: null + }; + } -/** - * Implementation of the One-Pass Signature Packets (Tag 4) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.4|RFC4880 5.4}: - * The One-Pass Signature packet precedes the signed data and contains - * enough information to allow the receiver to begin calculating any - * hashes needed to verify the signature. It allows the Signature - * packet to be placed at the end of the message, so that the signer - * can compute the entire signed message in one pass. - * @memberof module:packet - * @constructor - */ -function OnePassSignature() { - /** - * Packet type - * @type {module:enums.packet} - */ - this.tag = _enums2.default.packet.onePassSignature; - /** A one-octet version number. The current version is 3. */ - this.version = null; - /** - * A one-octet signature type. - * Signature types are described in - * {@link https://tools.ietf.org/html/rfc4880#section-5.2.1|RFC4880 Section 5.2.1}. - */ - this.signatureType = null; - /** - * A one-octet number describing the hash algorithm used. - * @see {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC4880 9.4} - */ - this.hashAlgorithm = null; - /** - * A one-octet number describing the public-key algorithm used. - * @see {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC4880 9.1} - */ - this.publicKeyAlgorithm = null; - /** An eight-octet number holding the Key ID of the signing key. */ - this.issuerKeyId = null; - /** - * A one-octet number holding a flag showing whether the signature is nested. - * A zero value indicates that the next packet is another One-Pass Signature packet - * that describes another signature to be applied to the same message data. - */ - this.flags = null; -} + if (mode === 'mod') { + return { + div: null, + mod: new BN(this.modn(num.words[0])) + }; + } -/** - * parsing function for a one-pass signature packet (tag 4). - * @param {Uint8Array} bytes payload of a tag 4 packet - * @returns {module:packet.OnePassSignature} object representation - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + return { + div: this.divn(num.words[0]), + mod: new BN(this.modn(num.words[0])) + }; + } -/** - * @requires web-stream-tools - * @requires packet/signature - * @requires type/keyid - * @requires enums - * @requires util - */ + return this._wordDiv(num, mode); + }; -OnePassSignature.prototype.read = function (bytes) { - let mypos = 0; - // A one-octet version number. The current version is 3. - this.version = bytes[mypos++]; + // Find `this` / `num` + BN.prototype.div = function div (num) { + return this.divmod(num, 'div', false).div; + }; - // A one-octet signature type. Signature types are described in - // Section 5.2.1. - this.signatureType = bytes[mypos++]; + // Find `this` % `num` + BN.prototype.mod = function mod (num) { + return this.divmod(num, 'mod', false).mod; + }; - // A one-octet number describing the hash algorithm used. - this.hashAlgorithm = bytes[mypos++]; + BN.prototype.umod = function umod (num) { + return this.divmod(num, 'mod', true).mod; + }; - // A one-octet number describing the public-key algorithm used. - this.publicKeyAlgorithm = bytes[mypos++]; + // Find Round(`this` / `num`) + BN.prototype.divRound = function divRound (num) { + var dm = this.divmod(num); - // An eight-octet number holding the Key ID of the signing key. - this.issuerKeyId = new _keyid2.default(); - this.issuerKeyId.read(bytes.subarray(mypos, mypos + 8)); - mypos += 8; + // Fast case - exact division + if (dm.mod.isZero()) return dm.div; - // A one-octet number holding a flag showing whether the signature - // is nested. A zero value indicates that the next packet is - // another One-Pass Signature packet that describes another - // signature to be applied to the same message data. - this.flags = bytes[mypos++]; - return this; -}; + var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod; -/** - * creates a string representation of a one-pass signature packet - * @returns {Uint8Array} a Uint8Array representation of a one-pass signature packet - */ -OnePassSignature.prototype.write = function () { - const start = new Uint8Array([3, _enums2.default.write(_enums2.default.signature, this.signatureType), _enums2.default.write(_enums2.default.hash, this.hashAlgorithm), _enums2.default.write(_enums2.default.publicKey, this.publicKeyAlgorithm)]); + var half = num.ushrn(1); + var r2 = num.andln(1); + var cmp = mod.cmp(half); - const end = new Uint8Array([this.flags]); + // Round down + if (cmp < 0 || r2 === 1 && cmp === 0) return dm.div; - return _util2.default.concatUint8Array([start, this.issuerKeyId.write(), end]); -}; + // Round up + return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1); + }; -/** - * Fix custom types after cloning - */ -OnePassSignature.prototype.postCloneTypeFix = function () { - this.issuerKeyId = _keyid2.default.fromClone(this.issuerKeyId); -}; + BN.prototype.modn = function modn (num) { + assert(num <= 0x3ffffff); + var p = (1 << 26) % num; -OnePassSignature.prototype.hash = _signature2.default.prototype.hash; -OnePassSignature.prototype.toHash = _signature2.default.prototype.toHash; -OnePassSignature.prototype.toSign = _signature2.default.prototype.toSign; -OnePassSignature.prototype.calculateTrailer = function (...args) { - return _webStreamTools2.default.fromAsync(async () => (await this.correspondingSig).calculateTrailer(...args)); -}; + var acc = 0; + for (var i = this.length - 1; i >= 0; i--) { + acc = (p * acc + (this.words[i] | 0)) % num; + } -OnePassSignature.prototype.verify = async function () { - const correspondingSig = await this.correspondingSig; - if (!correspondingSig || correspondingSig.tag !== _enums2.default.packet.signature) { - throw new Error('Corresponding signature packet missing'); - } - if (correspondingSig.signatureType !== this.signatureType || correspondingSig.hashAlgorithm !== this.hashAlgorithm || correspondingSig.publicKeyAlgorithm !== this.publicKeyAlgorithm || !correspondingSig.issuerKeyId.equals(this.issuerKeyId)) { - throw new Error('Corresponding signature packet does not match one-pass signature packet'); - } - correspondingSig.hashed = this.hashed; - return correspondingSig.verify.apply(correspondingSig, arguments); -}; + return acc; + }; -exports.default = OnePassSignature; + // In-place division by number + BN.prototype.idivn = function idivn (num) { + assert(num <= 0x3ffffff); -},{"../enums":113,"../type/keyid":148,"../util":152,"./signature":136,"web-stream-tools":75}],129:[function(require,module,exports){ -'use strict'; + var carry = 0; + for (var i = this.length - 1; i >= 0; i--) { + var w = (this.words[i] | 0) + carry * 0x4000000; + this.words[i] = (w / num) | 0; + carry = w % num; + } -Object.defineProperty(exports, "__esModule", { - value: true -}); + return this.strip(); + }; -var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); // GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + BN.prototype.divn = function divn (num) { + return this.clone().idivn(num); + }; -/* eslint-disable callback-return */ + BN.prototype.egcd = function egcd (p) { + assert(p.negative === 0); + assert(!p.isZero()); -/** - * @fileoverview Functions for reading and writing packets - * @requires web-stream-tools - * @requires enums - * @requires util - * @module packet/packet - */ + var x = this; + var y = p.clone(); -var _webStreamTools = require('web-stream-tools'); + if (x.negative !== 0) { + x = x.umod(p); + } else { + x = x.clone(); + } -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); + // A * x + B * y = x + var A = new BN(1); + var B = new BN(0); -var _enums = require('../enums'); + // C * x + D * y = y + var C = new BN(0); + var D = new BN(1); -var _enums2 = _interopRequireDefault(_enums); + var g = 0; -var _util = require('../util'); + while (x.isEven() && y.isEven()) { + x.iushrn(1); + y.iushrn(1); + ++g; + } -var _util2 = _interopRequireDefault(_util); + var yp = y.clone(); + var xp = x.clone(); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + while (!x.isZero()) { + for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1); + if (i > 0) { + x.iushrn(i); + while (i-- > 0) { + if (A.isOdd() || B.isOdd()) { + A.iadd(yp); + B.isub(xp); + } -exports.default = { - readSimpleLength: function readSimpleLength(bytes) { - let len = 0; - let offset; - const type = bytes[0]; + A.iushrn(1); + B.iushrn(1); + } + } - if (type < 192) { - var _bytes = _slicedToArray(bytes, 1); + for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); + if (j > 0) { + y.iushrn(j); + while (j-- > 0) { + if (C.isOdd() || D.isOdd()) { + C.iadd(yp); + D.isub(xp); + } - len = _bytes[0]; + C.iushrn(1); + D.iushrn(1); + } + } - offset = 1; - } else if (type < 255) { - len = (bytes[0] - 192 << 8) + bytes[1] + 192; - offset = 2; - } else if (type === 255) { - len = _util2.default.readNumber(bytes.subarray(1, 1 + 4)); - offset = 5; + if (x.cmp(y) >= 0) { + x.isub(y); + A.isub(C); + B.isub(D); + } else { + y.isub(x); + C.isub(A); + D.isub(B); + } } return { - len: len, - offset: offset + a: C, + b: D, + gcd: y.iushln(g) }; - }, + }; - /** - * Encodes a given integer of length to the openpgp length specifier to a - * string - * - * @param {Integer} length The length to encode - * @returns {Uint8Array} String with openpgp length representation - */ - writeSimpleLength: function writeSimpleLength(length) { - if (length < 192) { - return new Uint8Array([length]); - } else if (length > 191 && length < 8384) { - /* - * let a = (total data packet length) - 192 let bc = two octet - * representation of a let d = b + 192 - */ - return new Uint8Array([(length - 192 >> 8) + 192, length - 192 & 0xFF]); - } - return _util2.default.concatUint8Array([new Uint8Array([255]), _util2.default.writeNumber(length, 4)]); - }, + // This is reduced incarnation of the binary EEA + // above, designated to invert members of the + // _prime_ fields F(p) at a maximal speed + BN.prototype._invmp = function _invmp (p) { + assert(p.negative === 0); + assert(!p.isZero()); + + var a = this; + var b = p.clone(); - writePartialLength: function writePartialLength(power) { - if (power < 0 || power > 30) { - throw new Error('Partial Length power must be between 1 and 30'); + if (a.negative !== 0) { + a = a.umod(p); + } else { + a = a.clone(); } - return new Uint8Array([224 + power]); - }, - writeTag: function writeTag(tag_type) { - /* we're only generating v4 packet headers here */ - return new Uint8Array([0xC0 | tag_type]); - }, + var x1 = new BN(1); + var x2 = new BN(0); - /** - * Writes a packet header version 4 with the given tag_type and length to a - * string - * - * @param {Integer} tag_type Tag type - * @param {Integer} length Length of the payload - * @returns {String} String of the header - */ - writeHeader: function writeHeader(tag_type, length) { - /* we're only generating v4 packet headers here */ - return _util2.default.concatUint8Array([this.writeTag(tag_type), this.writeSimpleLength(length)]); - }, + var delta = b.clone(); - /** - * Whether the packet type supports partial lengths per RFC4880 - * @param {Integer} tag_type Tag type - * @returns {Boolean} String of the header - */ - supportsStreaming: function supportsStreaming(tag_type) { - return [_enums2.default.packet.literal, _enums2.default.packet.compressed, _enums2.default.packet.symmetricallyEncrypted, _enums2.default.packet.symEncryptedIntegrityProtected, _enums2.default.packet.symEncryptedAEADProtected].includes(tag_type); - }, + while (a.cmpn(1) > 0 && b.cmpn(1) > 0) { + for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1); + if (i > 0) { + a.iushrn(i); + while (i-- > 0) { + if (x1.isOdd()) { + x1.iadd(delta); + } - /** - * Generic static Packet Parser function - * - * @param {Uint8Array | ReadableStream} input Input stream as string - * @param {Function} callback Function to call with the parsed packet - * @returns {Boolean} Returns false if the stream was empty and parsing is done, and true otherwise. - */ - read: async function read(input, streaming, callback) { - const reader = _webStreamTools2.default.getReader(input); - let writer; - let callbackReturned; - try { - const peekedBytes = await reader.peekBytes(2); - // some sanity checks - if (!peekedBytes || peekedBytes.length < 2 || (peekedBytes[0] & 0x80) === 0) { - throw new Error("Error during parsing. This message / key probably does not conform to a valid OpenPGP format."); + x1.iushrn(1); + } } - const headerByte = await reader.readByte(); - let tag = -1; - let format = -1; - let packet_length; - format = 0; // 0 = old format; 1 = new format - if ((headerByte & 0x40) !== 0) { - format = 1; + for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); + if (j > 0) { + b.iushrn(j); + while (j-- > 0) { + if (x2.isOdd()) { + x2.iadd(delta); + } + + x2.iushrn(1); + } } - let packet_length_type; - if (format) { - // new format header - tag = headerByte & 0x3F; // bit 5-0 + if (a.cmp(b) >= 0) { + a.isub(b); + x1.isub(x2); } else { - // old format header - tag = (headerByte & 0x3F) >> 2; // bit 5-2 - packet_length_type = headerByte & 0x03; // bit 1-0 + b.isub(a); + x2.isub(x1); } + } - const supportsStreaming = this.supportsStreaming(tag); - let packet = null; - if (streaming && supportsStreaming) { - const transform = new TransformStream(); - writer = _webStreamTools2.default.getWriter(transform.writable); - packet = transform.readable; - callbackReturned = callback({ tag, packet }); - } else { - packet = []; - } + var res; + if (a.cmpn(1) === 0) { + res = x1; + } else { + res = x2; + } - let wasPartialLength; - do { - if (!format) { - // 4.2.1. Old Format Packet Lengths - switch (packet_length_type) { - case 0: - // The packet has a one-octet length. The header is 2 octets - // long. - packet_length = await reader.readByte(); - break; - case 1: - // The packet has a two-octet length. The header is 3 octets - // long. - packet_length = (await reader.readByte()) << 8 | (await reader.readByte()); - break; - case 2: - // The packet has a four-octet length. The header is 5 - // octets long. - packet_length = (await reader.readByte()) << 24 | (await reader.readByte()) << 16 | (await reader.readByte()) << 8 | (await reader.readByte()); - break; - default: - // 3 - The packet is of indeterminate length. The header is 1 - // octet long, and the implementation must determine how long - // the packet is. If the packet is in a file, this means that - // the packet extends until the end of the file. In general, - // an implementation SHOULD NOT use indeterminate-length - // packets except where the end of the data will be clear - // from the context, and even then it is better to use a - // definite length, or a new format header. The new format - // headers described below have a mechanism for precisely - // encoding data of indeterminate length. - packet_length = Infinity; - break; - } - } else { - // 4.2.2. New Format Packet Lengths - // 4.2.2.1. One-Octet Lengths - const lengthByte = await reader.readByte(); - wasPartialLength = false; - if (lengthByte < 192) { - packet_length = lengthByte; - // 4.2.2.2. Two-Octet Lengths - } else if (lengthByte >= 192 && lengthByte < 224) { - packet_length = (lengthByte - 192 << 8) + (await reader.readByte()) + 192; - // 4.2.2.4. Partial Body Lengths - } else if (lengthByte > 223 && lengthByte < 255) { - packet_length = 1 << (lengthByte & 0x1F); - wasPartialLength = true; - if (!supportsStreaming) { - throw new TypeError('This packet type does not support partial lengths.'); - } - // 4.2.2.3. Five-Octet Lengths - } else { - packet_length = (await reader.readByte()) << 24 | (await reader.readByte()) << 16 | (await reader.readByte()) << 8 | (await reader.readByte()); - } - } - if (packet_length > 0) { - let bytesRead = 0; - while (true) { - if (writer) await writer.ready; + if (res.cmpn(0) < 0) { + res.iadd(p); + } - var _ref = await reader.read(); + return res; + }; - const done = _ref.done, - value = _ref.value; + BN.prototype.gcd = function gcd (num) { + if (this.isZero()) return num.abs(); + if (num.isZero()) return this.abs(); - if (done) { - if (packet_length === Infinity) break; - throw new Error('Unexpected end of packet'); - } - const chunk = packet_length === Infinity ? value : value.subarray(0, packet_length - bytesRead); - if (writer) await writer.write(chunk);else packet.push(chunk); - bytesRead += value.length; - if (bytesRead >= packet_length) { - reader.unshift(value.subarray(packet_length - bytesRead + value.length)); - break; - } - } - } - } while (wasPartialLength); + var a = this.clone(); + var b = num.clone(); + a.negative = 0; + b.negative = 0; - // If this was not a packet that "supports streaming", we peek to check - // whether it is the last packet in the message. We peek 2 bytes instead - // of 1 because the beginning of this function also peeks 2 bytes, and we - // want to cut a `subarray` of the correct length into `web-stream-tools`' - // `externalBuffer` as a tiny optimization here. - // - // If it *was* a streaming packet (i.e. the data packets), we peek at the - // entire remainder of the stream, in order to forward errors in the - // remainder of the stream to the packet data. (Note that this means we - // read/peek at all signature packets before closing the literal data - // packet, for example.) This forwards armor checksum errors to the - // encrypted data stream, for example, so that they don't get lost / - // forgotten on encryptedMessage.packets.stream, which we never look at. - // - // Note that subsequent packet parsing errors could still end up there if - // `config.tolerant` is set to false, or on malformed messages with - // multiple data packets, but usually it shouldn't happen. - // - // An example of what we do when stream-parsing a message containing - // [ one-pass signature packet, literal data packet, signature packet ]: - // 1. Read the one-pass signature packet - // 2. Peek 2 bytes of the literal data packet - // 3. Parse the one-pass signature packet - // - // 4. Read the literal data packet, simultaneously stream-parsing it - // 5. Peek until the end of the message - // 6. Finish parsing the literal data packet - // - // 7. Read the signature packet again (we already peeked at it in step 5) - // 8. Peek at the end of the stream again (`peekBytes` returns undefined) - // 9. Parse the signature packet - // - // Note that this means that if there's an error in the very end of the - // stream, such as an MDC error, we throw in step 5 instead of in step 8 - // (or never), which is the point of this exercise. - const nextPacket = await reader.peekBytes(supportsStreaming ? Infinity : 2); - if (writer) { - await writer.ready; - await writer.close(); - } else { - packet = _util2.default.concatUint8Array(packet); - await callback({ tag, packet }); + // Remove common factor of two + for (var shift = 0; a.isEven() && b.isEven(); shift++) { + a.iushrn(1); + b.iushrn(1); + } + + do { + while (a.isEven()) { + a.iushrn(1); } - return !nextPacket || !nextPacket.length; - } catch (e) { - if (writer) { - await writer.abort(e); - return true; - } else { - throw e; + while (b.isEven()) { + b.iushrn(1); } - } finally { - if (writer) { - await callbackReturned; + + var r = a.cmp(b); + if (r < 0) { + // Swap `a` and `b` to make `a` always bigger than `b` + var t = a; + a = b; + b = t; + } else if (r === 0 || b.cmpn(1) === 0) { + break; } - reader.releaseLock(); - } - } -}; -},{"../enums":113,"../util":152,"web-stream-tools":75}],130:[function(require,module,exports){ -'use strict'; + a.isub(b); + } while (true); -Object.defineProperty(exports, "__esModule", { - value: true -}); + return b.iushln(shift); + }; + + // Invert number in the field F(num) + BN.prototype.invm = function invm (num) { + return this.egcd(num).a.umod(num); + }; -var _webStreamTools = require('web-stream-tools'); + BN.prototype.isEven = function isEven () { + return (this.words[0] & 1) === 0; + }; -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); + BN.prototype.isOdd = function isOdd () { + return (this.words[0] & 1) === 1; + }; -var _all_packets = require('./all_packets'); + // And first word and num + BN.prototype.andln = function andln (num) { + return this.words[0] & num; + }; -var packets = _interopRequireWildcard(_all_packets); + // Increment at the bit position in-line + BN.prototype.bincn = function bincn (bit) { + assert(typeof bit === 'number'); + var r = bit % 26; + var s = (bit - r) / 26; + var q = 1 << r; -var _packet = require('./packet'); + // Fast case: bit is much higher than all existing words + if (this.length <= s) { + this._expand(s + 1); + this.words[s] |= q; + return this; + } -var _packet2 = _interopRequireDefault(_packet); + // Add bit and propagate, if needed + var carry = q; + for (var i = s; carry !== 0 && i < this.length; i++) { + var w = this.words[i] | 0; + w += carry; + carry = w >>> 26; + w &= 0x3ffffff; + this.words[i] = w; + } + if (carry !== 0) { + this.words[i] = carry; + this.length++; + } + return this; + }; -var _config = require('../config'); + BN.prototype.isZero = function isZero () { + return this.length === 1 && this.words[0] === 0; + }; -var _config2 = _interopRequireDefault(_config); + BN.prototype.cmpn = function cmpn (num) { + var negative = num < 0; -var _enums = require('../enums'); + if (this.negative !== 0 && !negative) return -1; + if (this.negative === 0 && negative) return 1; -var _enums2 = _interopRequireDefault(_enums); + this.strip(); -var _util = require('../util'); + var res; + if (this.length > 1) { + res = 1; + } else { + if (negative) { + num = -num; + } -var _util2 = _interopRequireDefault(_util); + assert(num <= 0x3ffffff, 'Number is too big'); -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + var w = this.words[0] | 0; + res = w === num ? 0 : w < num ? -1 : 1; + } + if (this.negative !== 0) return -res | 0; + return res; + }; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + // Compare two numbers and return: + // 1 - if `this` > `num` + // 0 - if `this` == `num` + // -1 - if `this` < `num` + BN.prototype.cmp = function cmp (num) { + if (this.negative !== 0 && num.negative === 0) return -1; + if (this.negative === 0 && num.negative !== 0) return 1; -/** - * This class represents a list of openpgp packets. - * Take care when iterating over it - the packets themselves - * are stored as numerical indices. - * @memberof module:packet - * @constructor - * @extends Array - */ -/* eslint-disable callback-return */ -/** - * @requires web-stream-tools - * @requires packet/all_packets - * @requires packet/packet - * @requires config - * @requires enums - * @requires util - */ + var res = this.ucmp(num); + if (this.negative !== 0) return -res | 0; + return res; + }; -function List() { - /** - * The number of packets contained within the list. - * @readonly - * @type {Integer} - */ - this.length = 0; -} + // Unsigned comparison + BN.prototype.ucmp = function ucmp (num) { + // At this point both numbers have the same sign + if (this.length > num.length) return 1; + if (this.length < num.length) return -1; -List.prototype = []; + var res = 0; + for (var i = this.length - 1; i >= 0; i--) { + var a = this.words[i] | 0; + var b = num.words[i] | 0; -/** - * Reads a stream of binary data and interprents it as a list of packets. - * @param {Uint8Array | ReadableStream} A Uint8Array of bytes. - */ -List.prototype.read = async function (bytes, streaming) { - this.stream = _webStreamTools2.default.transformPair(bytes, async (readable, writable) => { - const writer = _webStreamTools2.default.getWriter(writable); - try { - while (true) { - await writer.ready; - const done = await _packet2.default.read(readable, streaming, async parsed => { - try { - const tag = _enums2.default.read(_enums2.default.packet, parsed.tag); - const packet = packets.newPacketFromTag(tag); - packet.packets = new List(); - packet.fromStream = _util2.default.isStream(parsed.packet); - await packet.read(parsed.packet, streaming); - await writer.write(packet); - } catch (e) { - if (!_config2.default.tolerant || _packet2.default.supportsStreaming(parsed.tag)) { - // The packets that support streaming are the ones that contain - // message data. Those are also the ones we want to be more strict - // about and throw on parse errors for. - await writer.abort(e); - } - _util2.default.print_debug_error(e); - } - }); - if (done) { - await writer.ready; - await writer.close(); - return; - } + if (a === b) continue; + if (a < b) { + res = -1; + } else if (a > b) { + res = 1; } - } catch (e) { - await writer.abort(e); + break; } - }); + return res; + }; - // Wait until first few packets have been read - const reader = _webStreamTools2.default.getReader(this.stream); - while (true) { - var _ref = await reader.read(); + BN.prototype.gtn = function gtn (num) { + return this.cmpn(num) === 1; + }; - const done = _ref.done, - value = _ref.value; + BN.prototype.gt = function gt (num) { + return this.cmp(num) === 1; + }; - if (!done) { - this.push(value); - } else { - this.stream = null; - } - if (done || _packet2.default.supportsStreaming(value.tag)) { - break; - } - } - reader.releaseLock(); -}; + BN.prototype.gten = function gten (num) { + return this.cmpn(num) >= 0; + }; -/** - * Creates a binary representation of openpgp objects contained within the - * class instance. - * @returns {Uint8Array} A Uint8Array containing valid openpgp packets. - */ -List.prototype.write = function () { - const arr = []; + BN.prototype.gte = function gte (num) { + return this.cmp(num) >= 0; + }; - for (let i = 0; i < this.length; i++) { - const packetbytes = this[i].write(); - if (_util2.default.isStream(packetbytes) && _packet2.default.supportsStreaming(this[i].tag)) { - let buffer = []; - let bufferLength = 0; - const minLength = 512; - arr.push(_packet2.default.writeTag(this[i].tag)); - arr.push(_webStreamTools2.default.transform(packetbytes, value => { - buffer.push(value); - bufferLength += value.length; - if (bufferLength >= minLength) { - const powerOf2 = Math.min(Math.log(bufferLength) / Math.LN2 | 0, 30); - const chunkSize = 2 ** powerOf2; - const bufferConcat = _util2.default.concat([_packet2.default.writePartialLength(powerOf2)].concat(buffer)); - buffer = [bufferConcat.subarray(1 + chunkSize)]; - bufferLength = buffer[0].length; - return bufferConcat.subarray(0, 1 + chunkSize); - } - }, () => _util2.default.concat([_packet2.default.writeSimpleLength(bufferLength)].concat(buffer)))); - } else { - if (_util2.default.isStream(packetbytes)) { - let length = 0; - arr.push(_webStreamTools2.default.transform(_webStreamTools2.default.clone(packetbytes), value => { - length += value.length; - }, () => _packet2.default.writeHeader(this[i].tag, length))); - } else { - arr.push(_packet2.default.writeHeader(this[i].tag, packetbytes.length)); - } - arr.push(packetbytes); - } - } + BN.prototype.ltn = function ltn (num) { + return this.cmpn(num) === -1; + }; - return _util2.default.concat(arr); -}; + BN.prototype.lt = function lt (num) { + return this.cmp(num) === -1; + }; -/** - * Adds a packet to the list. This is the only supported method of doing so; - * writing to packetlist[i] directly will result in an error. - * @param {Object} packet Packet to push - */ -List.prototype.push = function (packet) { - if (!packet) { - return; - } + BN.prototype.lten = function lten (num) { + return this.cmpn(num) <= 0; + }; + + BN.prototype.lte = function lte (num) { + return this.cmp(num) <= 0; + }; + + BN.prototype.eqn = function eqn (num) { + return this.cmpn(num) === 0; + }; - packet.packets = packet.packets || new List(); + BN.prototype.eq = function eq (num) { + return this.cmp(num) === 0; + }; - this[this.length] = packet; - this.length++; -}; + // + // A reduce context, could be using montgomery or something better, depending + // on the `m` itself. + // + BN.red = function red (num) { + return new Red(num); + }; -/** - * Creates a new PacketList with all packets from the given types - */ -List.prototype.filterByTag = function (...args) { - const filtered = new List(); + BN.prototype.toRed = function toRed (ctx) { + assert(!this.red, 'Already a number in reduction context'); + assert(this.negative === 0, 'red works only with positives'); + return ctx.convertTo(this)._forceRed(ctx); + }; - const handle = tag => packetType => tag === packetType; + BN.prototype.fromRed = function fromRed () { + assert(this.red, 'fromRed works only with numbers in reduction context'); + return this.red.convertFrom(this); + }; - for (let i = 0; i < this.length; i++) { - if (args.some(handle(this[i].tag))) { - filtered.push(this[i]); - } - } + BN.prototype._forceRed = function _forceRed (ctx) { + this.red = ctx; + return this; + }; - return filtered; -}; + BN.prototype.forceRed = function forceRed (ctx) { + assert(!this.red, 'Already a number in reduction context'); + return this._forceRed(ctx); + }; -/** - * Traverses packet tree and returns first matching packet - * @param {module:enums.packet} type The packet type - * @returns {module:packet/packet|undefined} - */ -List.prototype.findPacket = function (type) { - return this.find(packet => packet.tag === type); -}; + BN.prototype.redAdd = function redAdd (num) { + assert(this.red, 'redAdd works only with red numbers'); + return this.red.add(this, num); + }; -/** - * Returns array of found indices by tag - */ -List.prototype.indexOfTag = function (...args) { - const tagIndex = []; - const that = this; + BN.prototype.redIAdd = function redIAdd (num) { + assert(this.red, 'redIAdd works only with red numbers'); + return this.red.iadd(this, num); + }; - const handle = tag => packetType => tag === packetType; + BN.prototype.redSub = function redSub (num) { + assert(this.red, 'redSub works only with red numbers'); + return this.red.sub(this, num); + }; - for (let i = 0; i < this.length; i++) { - if (args.some(handle(that[i].tag))) { - tagIndex.push(i); - } - } - return tagIndex; -}; + BN.prototype.redISub = function redISub (num) { + assert(this.red, 'redISub works only with red numbers'); + return this.red.isub(this, num); + }; -/** - * Concatenates packetlist or array of packets - */ -List.prototype.concat = function (packetlist) { - if (packetlist) { - for (let i = 0; i < packetlist.length; i++) { - this.push(packetlist[i]); - } - } - return this; -}; + BN.prototype.redShl = function redShl (num) { + assert(this.red, 'redShl works only with red numbers'); + return this.red.shl(this, num); + }; -/** - * Allocate a new packetlist from structured packetlist clone - * See {@link https://w3c.github.io/html/infrastructure.html#safe-passing-of-structured-data} - * @param {Object} packetClone packetlist clone - * @returns {Object} new packetlist object with data from packetlist clone - */ -List.fromStructuredClone = function (packetlistClone) { - const packetlist = new List(); - for (let i = 0; i < packetlistClone.length; i++) { - const packet = packets.fromStructuredClone(packetlistClone[i]); - packetlist.push(packet); - if (packet.embeddedSignature) { - packet.embeddedSignature = packets.fromStructuredClone(packet.embeddedSignature); - } - if (packet.packets.length !== 0) { - packet.packets = this.fromStructuredClone(packet.packets); - } else { - packet.packets = new List(); - } - } - if (packetlistClone.stream) { - packetlist.stream = _webStreamTools2.default.transform(packetlistClone.stream, packet => packets.fromStructuredClone(packet)); - } - return packetlist; -}; + BN.prototype.redMul = function redMul (num) { + assert(this.red, 'redMul works only with red numbers'); + this.red._verify2(this, num); + return this.red.mul(this, num); + }; -exports.default = List; + BN.prototype.redIMul = function redIMul (num) { + assert(this.red, 'redMul works only with red numbers'); + this.red._verify2(this, num); + return this.red.imul(this, num); + }; -},{"../config":79,"../enums":113,"../util":152,"./all_packets":122,"./packet":129,"web-stream-tools":75}],131:[function(require,module,exports){ -'use strict'; + BN.prototype.redSqr = function redSqr () { + assert(this.red, 'redSqr works only with red numbers'); + this.red._verify1(this); + return this.red.sqr(this); + }; -Object.defineProperty(exports, "__esModule", { - value: true -}); + BN.prototype.redISqr = function redISqr () { + assert(this.red, 'redISqr works only with red numbers'); + this.red._verify1(this); + return this.red.isqr(this); + }; -var _sha = require('asmcrypto.js/dist_es5/hash/sha1/sha1'); + // Square root over p + BN.prototype.redSqrt = function redSqrt () { + assert(this.red, 'redSqrt works only with red numbers'); + this.red._verify1(this); + return this.red.sqrt(this); + }; -var _sha2 = require('asmcrypto.js/dist_es5/hash/sha256/sha256'); + BN.prototype.redInvm = function redInvm () { + assert(this.red, 'redInvm works only with red numbers'); + this.red._verify1(this); + return this.red.invm(this); + }; -var _keyid = require('../type/keyid'); + // Return negative clone of `this` % `red modulo` + BN.prototype.redNeg = function redNeg () { + assert(this.red, 'redNeg works only with red numbers'); + this.red._verify1(this); + return this.red.neg(this); + }; -var _keyid2 = _interopRequireDefault(_keyid); + BN.prototype.redPow = function redPow (num) { + assert(this.red && !num.red, 'redPow(normalNum)'); + this.red._verify1(this); + return this.red.pow(this, num); + }; -var _mpi = require('../type/mpi'); + // Prime numbers with efficient reduction + var primes = { + k256: null, + p224: null, + p192: null, + p25519: null + }; -var _mpi2 = _interopRequireDefault(_mpi); + // Pseudo-Mersenne prime + function MPrime (name, p) { + // P = 2 ^ N - K + this.name = name; + this.p = new BN(p, 16); + this.n = this.p.bitLength(); + this.k = new BN(1).iushln(this.n).isub(this.p); -var _config = require('../config'); + this.tmp = this._tmp(); + } -var _config2 = _interopRequireDefault(_config); + MPrime.prototype._tmp = function _tmp () { + var tmp = new BN(null); + tmp.words = new Array(Math.ceil(this.n / 13)); + return tmp; + }; -var _crypto = require('../crypto'); + MPrime.prototype.ireduce = function ireduce (num) { + // Assumes that `num` is less than `P^2` + // num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P) + var r = num; + var rlen; -var _crypto2 = _interopRequireDefault(_crypto); + do { + this.split(r, this.tmp); + r = this.imulK(r); + r = r.iadd(this.tmp); + rlen = r.bitLength(); + } while (rlen > this.n); -var _enums = require('../enums'); + var cmp = rlen < this.n ? -1 : r.ucmp(this.p); + if (cmp === 0) { + r.words[0] = 0; + r.length = 1; + } else if (cmp > 0) { + r.isub(this.p); + } else { + r.strip(); + } -var _enums2 = _interopRequireDefault(_enums); + return r; + }; -var _util = require('../util'); + MPrime.prototype.split = function split (input, out) { + input.iushrn(this.n, 0, out); + }; -var _util2 = _interopRequireDefault(_util); + MPrime.prototype.imulK = function imulK (num) { + return num.imul(this.k); + }; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + function K256 () { + MPrime.call( + this, + 'k256', + 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f'); + } + inherits(K256, MPrime); -/** - * Implementation of the Key Material Packet (Tag 5,6,7,14) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.5|RFC4480 5.5}: - * A key material packet contains all the information about a public or - * private key. There are four variants of this packet type, and two - * major versions. - * - * A Public-Key packet starts a series of packets that forms an OpenPGP - * key (sometimes called an OpenPGP certificate). - * @memberof module:packet - * @constructor - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + K256.prototype.split = function split (input, output) { + // 256 = 9 * 26 + 22 + var mask = 0x3fffff; -/** - * @requires type/keyid - * @requires type/mpi - * @requires config - * @requires crypto - * @requires enums - * @requires util - */ + var outLen = Math.min(input.length, 9); + for (var i = 0; i < outLen; i++) { + output.words[i] = input.words[i]; + } + output.length = outLen; -function PublicKey(date = new Date()) { - /** - * Packet type - * @type {module:enums.packet} - */ - this.tag = _enums2.default.packet.publicKey; - /** - * Packet version - * @type {Integer} - */ - this.version = _config2.default.v5_keys ? 5 : 4; - /** - * Key creation date. - * @type {Date} - */ - this.created = _util2.default.normalizeDate(date); - /** - * Public key algorithm. - * @type {String} - */ - this.algorithm = null; - /** - * Algorithm specific params - * @type {Array} - */ - this.params = []; - /** - * Time until expiration in days (V3 only) - * @type {Integer} - */ - this.expirationTimeV3 = 0; - /** - * Fingerprint in lowercase hex - * @type {String} - */ - this.fingerprint = null; - /** - * Keyid - * @type {module:type/keyid} - */ - this.keyid = null; -} + if (input.length <= 9) { + input.words[0] = 0; + input.length = 1; + return; + } -/** - * Internal Parser for public keys as specified in {@link https://tools.ietf.org/html/rfc4880#section-5.5.2|RFC 4880 section 5.5.2 Public-Key Packet Formats} - * called by read_tag<num> - * @param {Uint8Array} bytes Input array to read the packet from - * @returns {Object} This object with attributes set by the parser - */ -PublicKey.prototype.read = function (bytes) { - let pos = 0; - // A one-octet version number (3, 4 or 5). - this.version = bytes[pos++]; + // Shift by 9 limbs + var prev = input.words[9]; + output.words[output.length++] = prev & mask; - if (this.version === 4 || this.version === 5) { - // - A four-octet number denoting the time that the key was created. - this.created = _util2.default.readDate(bytes.subarray(pos, pos + 4)); - pos += 4; + for (i = 10; i < input.length; i++) { + var next = input.words[i] | 0; + input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22); + prev = next; + } + prev >>>= 22; + input.words[i - 10] = prev; + if (prev === 0 && input.length > 10) { + input.length -= 10; + } else { + input.length -= 9; + } + }; - // - A one-octet number denoting the public-key algorithm of this key. - this.algorithm = _enums2.default.read(_enums2.default.publicKey, bytes[pos++]); - const algo = _enums2.default.write(_enums2.default.publicKey, this.algorithm); + K256.prototype.imulK = function imulK (num) { + // K = 0x1000003d1 = [ 0x40, 0x3d1 ] + num.words[num.length] = 0; + num.words[num.length + 1] = 0; + num.length += 2; - if (this.version === 5) { - // - A four-octet scalar octet count for the following key material. - pos += 4; + // bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390 + var lo = 0; + for (var i = 0; i < num.length; i++) { + var w = num.words[i] | 0; + lo += w * 0x3d1; + num.words[i] = lo & 0x3ffffff; + lo = w * 0x40 + ((lo / 0x4000000) | 0); } - // - A series of values comprising the key material. This is - // algorithm-specific and described in section XXXX. - const types = _crypto2.default.getPubKeyParamTypes(algo); - this.params = _crypto2.default.constructParams(types); - - for (let i = 0; i < types.length && pos < bytes.length; i++) { - pos += this.params[i].read(bytes.subarray(pos, bytes.length)); - if (pos > bytes.length) { - throw new Error('Error reading MPI @:' + pos); + // Fast length reduction + if (num.words[num.length - 1] === 0) { + num.length--; + if (num.words[num.length - 1] === 0) { + num.length--; } } + return num; + }; - return pos; + function P224 () { + MPrime.call( + this, + 'p224', + 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001'); } - throw new Error('Version ' + this.version + ' of the key packet is unsupported.'); -}; - -/** - * Alias of read() - * @see module:packet.PublicKey#read - */ -PublicKey.prototype.readPublicKey = PublicKey.prototype.read; - -/** - * Same as write_private_key, but has less information because of - * public key. - * @returns {Uint8Array} OpenPGP packet body contents, - */ -PublicKey.prototype.write = function () { - const arr = []; - // Version - arr.push(new Uint8Array([this.version])); - arr.push(_util2.default.writeDate(this.created)); - // A one-octet number denoting the public-key algorithm of this key - const algo = _enums2.default.write(_enums2.default.publicKey, this.algorithm); - arr.push(new Uint8Array([algo])); + inherits(P224, MPrime); - const paramCount = _crypto2.default.getPubKeyParamTypes(algo).length; - const params = _util2.default.concatUint8Array(this.params.slice(0, paramCount).map(param => param.write())); - if (this.version === 5) { - // A four-octet scalar octet count for the following key material - arr.push(_util2.default.writeNumber(params.length, 4)); + function P192 () { + MPrime.call( + this, + 'p192', + 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff'); } - // Algorithm-specific params - arr.push(params); - return _util2.default.concatUint8Array(arr); -}; - -/** - * Alias of write() - * @see module:packet.PublicKey#write - */ -PublicKey.prototype.writePublicKey = PublicKey.prototype.write; - -/** - * Write packet in order to be hashed; either for a signature or a fingerprint. - */ -PublicKey.prototype.writeForHash = function (version) { - const bytes = this.writePublicKey(); + inherits(P192, MPrime); - if (version === 5) { - return _util2.default.concatUint8Array([new Uint8Array([0x9A]), _util2.default.writeNumber(bytes.length, 4), bytes]); + function P25519 () { + // 2 ^ 255 - 19 + MPrime.call( + this, + '25519', + '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed'); } - return _util2.default.concatUint8Array([new Uint8Array([0x99]), _util2.default.writeNumber(bytes.length, 2), bytes]); -}; - -/** - * Check whether secret-key data is available in decrypted form. Returns null for public keys. - * @returns {Boolean|null} - */ -PublicKey.prototype.isDecrypted = function () { - return null; -}; - -/** - * Returns the creation time of the key - * @returns {Date} - */ -PublicKey.prototype.getCreationTime = function () { - return this.created; -}; + inherits(P25519, MPrime); -/** - * Calculates the key id of the key - * @returns {String} A 8 byte key id - */ -PublicKey.prototype.getKeyId = function () { - if (this.keyid) { - return this.keyid; - } - this.keyid = new _keyid2.default(); - if (this.version === 5) { - this.keyid.read(_util2.default.hex_to_Uint8Array(this.getFingerprint()).subarray(0, 8)); - } else if (this.version === 4) { - this.keyid.read(_util2.default.hex_to_Uint8Array(this.getFingerprint()).subarray(12, 20)); - } - return this.keyid; -}; + P25519.prototype.imulK = function imulK (num) { + // K = 0x13 + var carry = 0; + for (var i = 0; i < num.length; i++) { + var hi = (num.words[i] | 0) * 0x13 + carry; + var lo = hi & 0x3ffffff; + hi >>>= 26; -/** - * Calculates the fingerprint of the key - * @returns {Uint8Array} A Uint8Array containing the fingerprint - */ -PublicKey.prototype.getFingerprintBytes = function () { - if (this.fingerprint) { - return this.fingerprint; - } - const toHash = this.writeForHash(this.version); - if (this.version === 5) { - this.fingerprint = _sha2.Sha256.bytes(toHash); - } else if (this.version === 4) { - this.fingerprint = _sha.Sha1.bytes(toHash); - } - return this.fingerprint; -}; + num.words[i] = lo; + carry = hi; + } + if (carry !== 0) { + num.words[num.length++] = carry; + } + return num; + }; -/** - * Calculates the fingerprint of the key - * @returns {String} A string containing the fingerprint in lowercase hex - */ -PublicKey.prototype.getFingerprint = function () { - return _util2.default.Uint8Array_to_hex(this.getFingerprintBytes()); -}; + // Exported mostly for testing purposes, use plain name instead + BN._prime = function prime (name) { + // Cached version of prime + if (primes[name]) return primes[name]; -/** - * Calculates whether two keys have the same fingerprint without actually calculating the fingerprint - * @returns {Boolean} Whether the two keys have the same version and public key data - */ -PublicKey.prototype.hasSameFingerprintAs = function (other) { - return this.version === other.version && _util2.default.equalsUint8Array(this.writePublicKey(), other.writePublicKey()); -}; + var prime; + if (name === 'k256') { + prime = new K256(); + } else if (name === 'p224') { + prime = new P224(); + } else if (name === 'p192') { + prime = new P192(); + } else if (name === 'p25519') { + prime = new P25519(); + } else { + throw new Error('Unknown prime ' + name); + } + primes[name] = prime; -/** - * Returns algorithm information - * @returns {Object} An object of the form {algorithm: String, bits:int, curve:String} - */ -PublicKey.prototype.getAlgorithmInfo = function () { - const result = {}; - result.algorithm = this.algorithm; - if (this.params[0] instanceof _mpi2.default) { - result.bits = this.params[0].byteLength() * 8; - } else { - result.curve = this.params[0].getName(); - } - return result; -}; + return prime; + }; -/** - * Fix custom types after cloning - */ -PublicKey.prototype.postCloneTypeFix = function () { - const algo = _enums2.default.write(_enums2.default.publicKey, this.algorithm); - const types = _crypto2.default.getPubKeyParamTypes(algo); - for (let i = 0; i < types.length; i++) { - const param = this.params[i]; - this.params[i] = types[i].fromClone(param); - } - if (this.keyid) { - this.keyid = _keyid2.default.fromClone(this.keyid); + // + // Base reduction engine + // + function Red (m) { + if (typeof m === 'string') { + var prime = BN._prime(m); + this.m = prime.p; + this.prime = prime; + } else { + assert(m.gtn(1), 'modulus must be greater than 1'); + this.m = m; + this.prime = null; + } } -}; - -exports.default = PublicKey; - -},{"../config":79,"../crypto":94,"../enums":113,"../type/keyid":148,"../type/mpi":149,"../util":152,"asmcrypto.js/dist_es5/hash/sha1/sha1":11,"asmcrypto.js/dist_es5/hash/sha256/sha256":13}],132:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _keyid = require('../type/keyid'); -var _keyid2 = _interopRequireDefault(_keyid); - -var _mpi = require('../type/mpi'); - -var _mpi2 = _interopRequireDefault(_mpi); - -var _crypto = require('../crypto'); + Red.prototype._verify1 = function _verify1 (a) { + assert(a.negative === 0, 'red works only with positives'); + assert(a.red, 'red works only with red numbers'); + }; -var _crypto2 = _interopRequireDefault(_crypto); + Red.prototype._verify2 = function _verify2 (a, b) { + assert((a.negative | b.negative) === 0, 'red works only with positives'); + assert(a.red && a.red === b.red, + 'red works only with red numbers'); + }; -var _enums = require('../enums'); + Red.prototype.imod = function imod (a) { + if (this.prime) return this.prime.ireduce(a)._forceRed(this); + return a.umod(this.m)._forceRed(this); + }; -var _enums2 = _interopRequireDefault(_enums); + Red.prototype.neg = function neg (a) { + if (a.isZero()) { + return a.clone(); + } -var _util = require('../util'); + return this.m.sub(a)._forceRed(this); + }; -var _util2 = _interopRequireDefault(_util); + Red.prototype.add = function add (a, b) { + this._verify2(a, b); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + var res = a.add(b); + if (res.cmp(this.m) >= 0) { + res.isub(this.m); + } + return res._forceRed(this); + }; -/** - * Public-Key Encrypted Session Key Packets (Tag 1) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.1|RFC4880 5.1}: - * A Public-Key Encrypted Session Key packet holds the session key - * used to encrypt a message. Zero or more Public-Key Encrypted Session Key - * packets and/or Symmetric-Key Encrypted Session Key packets may precede a - * Symmetrically Encrypted Data Packet, which holds an encrypted message. The - * message is encrypted with the session key, and the session key is itself - * encrypted and stored in the Encrypted Session Key packet(s). The - * Symmetrically Encrypted Data Packet is preceded by one Public-Key Encrypted - * Session Key packet for each OpenPGP key to which the message is encrypted. - * The recipient of the message finds a session key that is encrypted to their - * public key, decrypts the session key, and then uses the session key to - * decrypt the message. - * @memberof module:packet - * @constructor - */ -function PublicKeyEncryptedSessionKey() { - this.tag = _enums2.default.packet.publicKeyEncryptedSessionKey; - this.version = 3; + Red.prototype.iadd = function iadd (a, b) { + this._verify2(a, b); - this.publicKeyId = new _keyid2.default(); - this.publicKeyAlgorithm = null; + var res = a.iadd(b); + if (res.cmp(this.m) >= 0) { + res.isub(this.m); + } + return res; + }; - this.sessionKey = null; - this.sessionKeyAlgorithm = null; + Red.prototype.sub = function sub (a, b) { + this._verify2(a, b); - /** @type {Array} */ - this.encrypted = []; -} + var res = a.sub(b); + if (res.cmpn(0) < 0) { + res.iadd(this.m); + } + return res._forceRed(this); + }; -/** - * Parsing function for a publickey encrypted session key packet (tag 1). - * - * @param {Uint8Array} input Payload of a tag 1 packet - * @param {Integer} position Position to start reading from the input string - * @param {Integer} len Length of the packet or the remaining length of - * input at position - * @returns {module:packet.PublicKeyEncryptedSessionKey} Object representation - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Red.prototype.isub = function isub (a, b) { + this._verify2(a, b); -/** - * @requires type/keyid - * @requires type/mpi - * @requires crypto - * @requires enums - * @requires util - */ + var res = a.isub(b); + if (res.cmpn(0) < 0) { + res.iadd(this.m); + } + return res; + }; -PublicKeyEncryptedSessionKey.prototype.read = function (bytes) { - this.version = bytes[0]; - this.publicKeyId.read(bytes.subarray(1, bytes.length)); - this.publicKeyAlgorithm = _enums2.default.read(_enums2.default.publicKey, bytes[9]); + Red.prototype.shl = function shl (a, num) { + this._verify1(a); + return this.imod(a.ushln(num)); + }; - let i = 10; + Red.prototype.imul = function imul (a, b) { + this._verify2(a, b); + return this.imod(a.imul(b)); + }; - const algo = _enums2.default.write(_enums2.default.publicKey, this.publicKeyAlgorithm); - const types = _crypto2.default.getEncSessionKeyParamTypes(algo); - this.encrypted = _crypto2.default.constructParams(types); + Red.prototype.mul = function mul (a, b) { + this._verify2(a, b); + return this.imod(a.mul(b)); + }; - for (let j = 0; j < types.length; j++) { - i += this.encrypted[j].read(bytes.subarray(i, bytes.length)); - } -}; + Red.prototype.isqr = function isqr (a) { + return this.imul(a, a.clone()); + }; -/** - * Create a string representation of a tag 1 packet - * - * @returns {Uint8Array} The Uint8Array representation - */ -PublicKeyEncryptedSessionKey.prototype.write = function () { - const arr = [new Uint8Array([this.version]), this.publicKeyId.write(), new Uint8Array([_enums2.default.write(_enums2.default.publicKey, this.publicKeyAlgorithm)])]; + Red.prototype.sqr = function sqr (a) { + return this.mul(a, a); + }; - for (let i = 0; i < this.encrypted.length; i++) { - arr.push(this.encrypted[i].write()); - } + Red.prototype.sqrt = function sqrt (a) { + if (a.isZero()) return a.clone(); - return _util2.default.concatUint8Array(arr); -}; + var mod3 = this.m.andln(3); + assert(mod3 % 2 === 1); -/** - * Encrypt session key packet - * @param {module:packet.PublicKey} key Public key - * @returns {Promise} - * @async - */ -PublicKeyEncryptedSessionKey.prototype.encrypt = async function (key) { - let data = String.fromCharCode(_enums2.default.write(_enums2.default.symmetric, this.sessionKeyAlgorithm)); + // Fast case + if (mod3 === 3) { + var pow = this.m.add(new BN(1)).iushrn(2); + return this.pow(a, pow); + } - data += _util2.default.Uint8Array_to_str(this.sessionKey); - data += _util2.default.Uint8Array_to_str(_util2.default.write_checksum(this.sessionKey)); + // Tonelli-Shanks algorithm (Totally unoptimized and slow) + // + // Find Q and S, that Q * 2 ^ S = (P - 1) + var q = this.m.subn(1); + var s = 0; + while (!q.isZero() && q.andln(1) === 0) { + s++; + q.iushrn(1); + } + assert(!q.isZero()); - let toEncrypt; - const algo = _enums2.default.write(_enums2.default.publicKey, this.publicKeyAlgorithm); - if (algo === _enums2.default.publicKey.ecdh) { - toEncrypt = new _mpi2.default(_crypto2.default.pkcs5.encode(data)); - } else { - toEncrypt = new _mpi2.default((await _crypto2.default.pkcs1.eme.encode(data, key.params[0].byteLength()))); - } + var one = new BN(1).toRed(this); + var nOne = one.redNeg(); - this.encrypted = await _crypto2.default.publicKeyEncrypt(algo, key.params, toEncrypt, key.getFingerprintBytes()); - return true; -}; + // Find quadratic non-residue + // NOTE: Max is such because of generalized Riemann hypothesis. + var lpow = this.m.subn(1).iushrn(1); + var z = this.m.bitLength(); + z = new BN(2 * z * z).toRed(this); -/** - * Decrypts the session key (only for public key encrypted session key - * packets (tag 1) - * - * @param {module:packet.SecretKey} key - * Private key with secret params unlocked - * @returns {Promise} - * @async - */ -PublicKeyEncryptedSessionKey.prototype.decrypt = async function (key) { - const algo = _enums2.default.write(_enums2.default.publicKey, this.publicKeyAlgorithm); - const result = new _mpi2.default((await _crypto2.default.publicKeyDecrypt(algo, key.params, this.encrypted, key.getFingerprintBytes()))); + while (this.pow(z, lpow).cmp(nOne) !== 0) { + z.redIAdd(nOne); + } - let checksum; - let decoded; - if (algo === _enums2.default.publicKey.ecdh) { - decoded = _crypto2.default.pkcs5.decode(result.toString()); - checksum = _util2.default.str_to_Uint8Array(decoded.substr(decoded.length - 2)); - } else { - decoded = _crypto2.default.pkcs1.eme.decode(result.toString()); - checksum = result.toUint8Array().slice(result.byteLength() - 2); - } + var c = this.pow(z, q); + var r = this.pow(a, q.addn(1).iushrn(1)); + var t = this.pow(a, q); + var m = s; + while (t.cmp(one) !== 0) { + var tmp = t; + for (var i = 0; tmp.cmp(one) !== 0; i++) { + tmp = tmp.redSqr(); + } + assert(i < m); + var b = this.pow(c, new BN(1).iushln(m - i - 1)); - key = _util2.default.str_to_Uint8Array(decoded.substring(1, decoded.length - 2)); + r = r.redMul(b); + c = b.redSqr(); + t = t.redMul(c); + m = i; + } - if (!_util2.default.equalsUint8Array(checksum, _util2.default.write_checksum(key))) { - throw new Error('Decryption error'); - } else { - this.sessionKey = key; - this.sessionKeyAlgorithm = _enums2.default.read(_enums2.default.symmetric, decoded.charCodeAt(0)); - } - return true; -}; + return r; + }; -/** - * Fix custom types after cloning - */ -PublicKeyEncryptedSessionKey.prototype.postCloneTypeFix = function () { - this.publicKeyId = _keyid2.default.fromClone(this.publicKeyId); - const algo = _enums2.default.write(_enums2.default.publicKey, this.publicKeyAlgorithm); - const types = _crypto2.default.getEncSessionKeyParamTypes(algo); - for (let i = 0; i < this.encrypted.length; i++) { - this.encrypted[i] = types[i].fromClone(this.encrypted[i]); - } -}; + Red.prototype.invm = function invm (a) { + var inv = a._invmp(this.m); + if (inv.negative !== 0) { + inv.negative = 0; + return this.imod(inv).redNeg(); + } else { + return this.imod(inv); + } + }; -exports.default = PublicKeyEncryptedSessionKey; + Red.prototype.pow = function pow (a, num) { + if (num.isZero()) return new BN(1).toRed(this); + if (num.cmpn(1) === 0) return a.clone(); -},{"../crypto":94,"../enums":113,"../type/keyid":148,"../type/mpi":149,"../util":152}],133:[function(require,module,exports){ -'use strict'; + var windowSize = 4; + var wnd = new Array(1 << windowSize); + wnd[0] = new BN(1).toRed(this); + wnd[1] = a; + for (var i = 2; i < wnd.length; i++) { + wnd[i] = this.mul(wnd[i - 1], a); + } -Object.defineProperty(exports, "__esModule", { - value: true -}); + var res = wnd[0]; + var current = 0; + var currentLen = 0; + var start = num.bitLength() % 26; + if (start === 0) { + start = 26; + } -var _public_key = require('./public_key'); + for (i = num.length - 1; i >= 0; i--) { + var word = num.words[i]; + for (var j = start - 1; j >= 0; j--) { + var bit = (word >> j) & 1; + if (res !== wnd[0]) { + res = this.sqr(res); + } -var _public_key2 = _interopRequireDefault(_public_key); + if (bit === 0 && current === 0) { + currentLen = 0; + continue; + } -var _enums = require('../enums'); + current <<= 1; + current |= bit; + currentLen++; + if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue; -var _enums2 = _interopRequireDefault(_enums); + res = this.mul(res, wnd[current]); + currentLen = 0; + current = 0; + } + start = 26; + } -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + return res; + }; -/** - * A Public-Subkey packet (tag 14) has exactly the same format as a - * Public-Key packet, but denotes a subkey. One or more subkeys may be - * associated with a top-level key. By convention, the top-level key - * provides signature services, and the subkeys provide encryption - * services. - * @memberof module:packet - * @constructor - * @extends module:packet.PublicKey - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Red.prototype.convertTo = function convertTo (num) { + var r = num.umod(this.m); -/** - * @requires packet/public_key - * @requires enums - */ + return r === num ? r.clone() : r; + }; -function PublicSubkey() { - _public_key2.default.call(this); - this.tag = _enums2.default.packet.publicSubkey; -} + Red.prototype.convertFrom = function convertFrom (num) { + var res = num.clone(); + res.red = null; + return res; + }; -PublicSubkey.prototype = new _public_key2.default(); -PublicSubkey.prototype.constructor = PublicSubkey; + // + // Montgomery method engine + // -exports.default = PublicSubkey; + BN.mont = function mont (num) { + return new Mont(num); + }; -},{"../enums":113,"./public_key":131}],134:[function(require,module,exports){ -'use strict'; + function Mont (m) { + Red.call(this, m); -Object.defineProperty(exports, "__esModule", { - value: true -}); + this.shift = this.m.bitLength(); + if (this.shift % 26 !== 0) { + this.shift += 26 - (this.shift % 26); + } -var _public_key = require('./public_key'); + this.r = new BN(1).iushln(this.shift); + this.r2 = this.imod(this.r.sqr()); + this.rinv = this.r._invmp(this.m); -var _public_key2 = _interopRequireDefault(_public_key); + this.minv = this.rinv.mul(this.r).isubn(1).div(this.m); + this.minv = this.minv.umod(this.r); + this.minv = this.r.sub(this.minv); + } + inherits(Mont, Red); -var _keyid = require('../type/keyid.js'); + Mont.prototype.convertTo = function convertTo (num) { + return this.imod(num.ushln(this.shift)); + }; -var _keyid2 = _interopRequireDefault(_keyid); + Mont.prototype.convertFrom = function convertFrom (num) { + var r = this.imod(num.mul(this.rinv)); + r.red = null; + return r; + }; -var _s2k = require('../type/s2k'); + Mont.prototype.imul = function imul (a, b) { + if (a.isZero() || b.isZero()) { + a.words[0] = 0; + a.length = 1; + return a; + } -var _s2k2 = _interopRequireDefault(_s2k); + var t = a.imul(b); + var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); + var u = t.isub(c).iushrn(this.shift); + var res = u; -var _crypto = require('../crypto'); + if (u.cmp(this.m) >= 0) { + res = u.isub(this.m); + } else if (u.cmpn(0) < 0) { + res = u.iadd(this.m); + } -var _crypto2 = _interopRequireDefault(_crypto); + return res._forceRed(this); + }; -var _enums = require('../enums'); + Mont.prototype.mul = function mul (a, b) { + if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this); -var _enums2 = _interopRequireDefault(_enums); + var t = a.mul(b); + var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); + var u = t.isub(c).iushrn(this.shift); + var res = u; + if (u.cmp(this.m) >= 0) { + res = u.isub(this.m); + } else if (u.cmpn(0) < 0) { + res = u.iadd(this.m); + } -var _util = require('../util'); + return res._forceRed(this); + }; -var _util2 = _interopRequireDefault(_util); + Mont.prototype.invm = function invm (a) { + // (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R + var res = this.imod(a._invmp(this.m).mul(this.r2)); + return res._forceRed(this); + }; +})(module, commonjsGlobal); +}); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +var bn$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + 'default': bn, + __moduleExports: bn +}); /** - * A Secret-Key packet contains all the information that is found in a - * Public-Key packet, including the public-key material, but also - * includes the secret-key material after all the public-key fields. - * @memberof module:packet - * @constructor - * @extends module:packet.PublicKey + * @fileoverview + * BigInteger implementation of basic operations + * Wrapper of bn.js library (wwww.github.com/indutny/bn.js) + * @module biginteger/bn + * @private */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /** - * @requires packet/public_key - * @requires type/keyid - * @requires type/s2k - * @requires crypto - * @requires enums - * @requires util + * @private */ +class BigInteger$1 { + /** + * Get a BigInteger (input must be big endian for strings and arrays) + * @param {Number|String|Uint8Array} n - Value to convert + * @throws {Error} on undefined input + */ + constructor(n) { + if (n === undefined) { + throw new Error('Invalid BigInteger input'); + } + + this.value = new bn(n); + } + + clone() { + const clone = new BigInteger$1(null); + this.value.copy(clone.value); + return clone; + } -function SecretKey(date = new Date()) { - _public_key2.default.call(this, date); /** - * Packet type - * @type {module:enums.packet} + * BigInteger increment in place */ - this.tag = _enums2.default.packet.secretKey; + iinc() { + this.value.iadd(new bn(1)); + return this; + } + /** - * Secret-key data + * BigInteger increment + * @returns {BigInteger} this + 1. */ - this.keyMaterial = null; + inc() { + return this.clone().iinc(); + } + /** - * Indicates whether secret-key data is encrypted. `this.isEncrypted === false` means data is available in decrypted form. + * BigInteger decrement in place */ - this.isEncrypted = null; + idec() { + this.value.isub(new bn(1)); + return this; + } + /** - * S2K usage - * @type {Integer} + * BigInteger decrement + * @returns {BigInteger} this - 1. */ - this.s2k_usage = 0; + dec() { + return this.clone().idec(); + } + + /** - * S2K object - * @type {type/s2k} + * BigInteger addition in place + * @param {BigInteger} x - Value to add */ - this.s2k = null; + iadd(x) { + this.value.iadd(x.value); + return this; + } + /** - * Symmetric algorithm - * @type {String} + * BigInteger addition + * @param {BigInteger} x - Value to add + * @returns {BigInteger} this + x. */ - this.symmetric = 'aes256'; + add(x) { + return this.clone().iadd(x); + } + /** - * AEAD algorithm - * @type {String} + * BigInteger subtraction in place + * @param {BigInteger} x - Value to subtract */ - this.aead = 'eax'; -} + isub(x) { + this.value.isub(x.value); + return this; + } -SecretKey.prototype = new _public_key2.default(); -SecretKey.prototype.constructor = SecretKey; + /** + * BigInteger subtraction + * @param {BigInteger} x - Value to subtract + * @returns {BigInteger} this - x. + */ + sub(x) { + return this.clone().isub(x); + } -// Helper function + /** + * BigInteger multiplication in place + * @param {BigInteger} x - Value to multiply + */ + imul(x) { + this.value.imul(x.value); + return this; + } -function parse_cleartext_params(cleartext, algorithm) { - const algo = _enums2.default.write(_enums2.default.publicKey, algorithm); - const types = _crypto2.default.getPrivKeyParamTypes(algo); - const params = _crypto2.default.constructParams(types); - let p = 0; + /** + * BigInteger multiplication + * @param {BigInteger} x - Value to multiply + * @returns {BigInteger} this * x. + */ + mul(x) { + return this.clone().imul(x); + } - for (let i = 0; i < types.length && p < cleartext.length; i++) { - p += params[i].read(cleartext.subarray(p, cleartext.length)); - if (p > cleartext.length) { - throw new Error('Error reading param @:' + p); - } + /** + * Compute value modulo m, in place + * @param {BigInteger} m - Modulo + */ + imod(m) { + this.value = this.value.umod(m.value); + return this; } - return params; -} + /** + * Compute value modulo m + * @param {BigInteger} m - Modulo + * @returns {BigInteger} this mod m. + */ + mod(m) { + return this.clone().imod(m); + } -function write_cleartext_params(params, algorithm) { - const arr = []; - const algo = _enums2.default.write(_enums2.default.publicKey, algorithm); - const numPublicParams = _crypto2.default.getPubKeyParamTypes(algo).length; + /** + * Compute modular exponentiation + * Much faster than this.exp(e).mod(n) + * @param {BigInteger} e - Exponent + * @param {BigInteger} n - Modulo + * @returns {BigInteger} this ** e mod n. + */ + modExp(e, n) { + // We use either Montgomery or normal reduction context + // Montgomery requires coprime n and R (montogmery multiplier) + // bn.js picks R as power of 2, so n must be odd + const nred = n.isEven() ? bn.red(n.value) : bn.mont(n.value); + const x = this.clone(); + x.value = x.value.toRed(nred).redPow(e.value).fromRed(); + return x; + } - for (let i = numPublicParams; i < params.length; i++) { - arr.push(params[i].write()); + /** + * Compute the inverse of this value modulo n + * Note: this and and n must be relatively prime + * @param {BigInteger} n - Modulo + * @returns {BigInteger} x such that this*x = 1 mod n + * @throws {Error} if the inverse does not exist + */ + modInv(n) { + // invm returns a wrong result if the inverse does not exist + if (!this.gcd(n).isOne()) { + throw new Error('Inverse does not exist'); + } + return new BigInteger$1(this.value.invm(n.value)); } - return _util2.default.concatUint8Array(arr); -} + /** + * Compute greatest common divisor between this and n + * @param {BigInteger} n - Operand + * @returns {BigInteger} gcd + */ + gcd(n) { + return new BigInteger$1(this.value.gcd(n.value)); + } -// 5.5.3. Secret-Key Packet Formats + /** + * Shift this to the left by x, in place + * @param {BigInteger} x - Shift value + */ + ileftShift(x) { + this.value.ishln(x.value.toNumber()); + return this; + } -/** - * Internal parser for private keys as specified in - * {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.5.3|RFC4880bis-04 section 5.5.3} - * @param {String} bytes Input string to read the packet from - */ -SecretKey.prototype.read = function (bytes) { - // - A Public-Key or Public-Subkey packet, as described above. - let i = this.readPublicKey(bytes); + /** + * Shift this to the left by x + * @param {BigInteger} x - Shift value + * @returns {BigInteger} this << x. + */ + leftShift(x) { + return this.clone().ileftShift(x); + } - // - One octet indicating string-to-key usage conventions. Zero - // indicates that the secret-key data is not encrypted. 255 or 254 - // indicates that a string-to-key specifier is being given. Any - // other value is a symmetric-key encryption algorithm identifier. - this.s2k_usage = bytes[i++]; + /** + * Shift this to the right by x, in place + * @param {BigInteger} x - Shift value + */ + irightShift(x) { + this.value.ishrn(x.value.toNumber()); + return this; + } - // - Only for a version 5 packet, a one-octet scalar octet count of - // the next 4 optional fields. - if (this.version === 5) { - i++; + /** + * Shift this to the right by x + * @param {BigInteger} x - Shift value + * @returns {BigInteger} this >> x. + */ + rightShift(x) { + return this.clone().irightShift(x); } - // - [Optional] If string-to-key usage octet was 255, 254, or 253, a - // one-octet symmetric encryption algorithm. - if (this.s2k_usage === 255 || this.s2k_usage === 254 || this.s2k_usage === 253) { - this.symmetric = bytes[i++]; - this.symmetric = _enums2.default.read(_enums2.default.symmetric, this.symmetric); + /** + * Whether this value is equal to x + * @param {BigInteger} x + * @returns {Boolean} + */ + equal(x) { + return this.value.eq(x.value); + } - // - [Optional] If string-to-key usage octet was 253, a one-octet - // AEAD algorithm. - if (this.s2k_usage === 253) { - this.aead = bytes[i++]; - this.aead = _enums2.default.read(_enums2.default.aead, this.aead); - } + /** + * Whether this value is less than x + * @param {BigInteger} x + * @returns {Boolean} + */ + lt(x) { + return this.value.lt(x.value); + } - // - [Optional] If string-to-key usage octet was 255, 254, or 253, a - // string-to-key specifier. The length of the string-to-key - // specifier is implied by its type, as described above. - this.s2k = new _s2k2.default(); - i += this.s2k.read(bytes.subarray(i, bytes.length)); + /** + * Whether this value is less than or equal to x + * @param {BigInteger} x + * @returns {Boolean} + */ + lte(x) { + return this.value.lte(x.value); + } - if (this.s2k.type === 'gnu-dummy') { - return; - } - } else if (this.s2k_usage) { - this.symmetric = this.s2k_usage; - this.symmetric = _enums2.default.read(_enums2.default.symmetric, this.symmetric); + /** + * Whether this value is greater than x + * @param {BigInteger} x + * @returns {Boolean} + */ + gt(x) { + return this.value.gt(x.value); } - // - [Optional] If secret data is encrypted (string-to-key usage octet - // not zero), an Initial Vector (IV) of the same length as the - // cipher's block size. - if (this.s2k_usage) { - this.iv = bytes.subarray(i, i + _crypto2.default.cipher[this.symmetric].blockSize); + /** + * Whether this value is greater than or equal to x + * @param {BigInteger} x + * @returns {Boolean} + */ + gte(x) { + return this.value.gte(x.value); + } - i += this.iv.length; + isZero() { + return this.value.isZero(); } - // - Only for a version 5 packet, a four-octet scalar octet count for - // the following key material. - if (this.version === 5) { - i += 4; + isOne() { + return this.value.eq(new bn(1)); } - // - Plain or encrypted multiprecision integers comprising the secret - // key data. These algorithm-specific fields are as described - // below. - this.keyMaterial = bytes.subarray(i); - this.isEncrypted = !!this.s2k_usage; + isNegative() { + return this.value.isNeg(); + } - if (!this.isEncrypted) { - const cleartext = this.keyMaterial.subarray(0, -2); - if (!_util2.default.equalsUint8Array(_util2.default.write_checksum(cleartext), this.keyMaterial.subarray(-2))) { - throw new Error('Key checksum mismatch'); - } - const privParams = parse_cleartext_params(cleartext, this.algorithm); - this.params = this.params.concat(privParams); + isEven() { + return this.value.isEven(); } -}; -/** - * Creates an OpenPGP key packet for the given key. - * @returns {String} A string of bytes containing the secret key OpenPGP packet - */ -SecretKey.prototype.write = function () { - const arr = [this.writePublicKey()]; + abs() { + const res = this.clone(); + res.value = res.value.abs(); + return res; + } - arr.push(new Uint8Array([this.s2k_usage])); + /** + * Get this value as a string + * @returns {String} this value. + */ + toString() { + return this.value.toString(); + } - const optionalFieldsArr = []; - // - [Optional] If string-to-key usage octet was 255, 254, or 253, a - // one- octet symmetric encryption algorithm. - if (this.s2k_usage === 255 || this.s2k_usage === 254 || this.s2k_usage === 253) { - optionalFieldsArr.push(_enums2.default.write(_enums2.default.symmetric, this.symmetric)); + /** + * Get this value as an exact Number (max 53 bits) + * Fails if this value is too large + * @returns {Number} + */ + toNumber() { + return this.value.toNumber(); + } - // - [Optional] If string-to-key usage octet was 253, a one-octet - // AEAD algorithm. - if (this.s2k_usage === 253) { - optionalFieldsArr.push(_enums2.default.write(_enums2.default.aead, this.aead)); - } + /** + * Get value of i-th bit + * @param {Number} i - Bit index + * @returns {Number} Bit value. + */ + getBit(i) { + return this.value.testn(i) ? 1 : 0; + } - // - [Optional] If string-to-key usage octet was 255, 254, or 253, a - // string-to-key specifier. The length of the string-to-key - // specifier is implied by its type, as described above. - optionalFieldsArr.push(...this.s2k.write()); + /** + * Compute bit length + * @returns {Number} Bit length. + */ + bitLength() { + return this.value.bitLength(); } - // - [Optional] If secret data is encrypted (string-to-key usage octet - // not zero), an Initial Vector (IV) of the same length as the - // cipher's block size. - if (this.s2k_usage && this.s2k.type !== 'gnu-dummy') { - optionalFieldsArr.push(...this.iv); + /** + * Compute byte length + * @returns {Number} Byte length. + */ + byteLength() { + return this.value.byteLength(); } - if (this.version === 5) { - arr.push(new Uint8Array([optionalFieldsArr.length])); + /** + * Get Uint8Array representation of this number + * @param {String} endian - Endianess of output array (defaults to 'be') + * @param {Number} length - Of output array + * @returns {Uint8Array} + */ + toUint8Array(endian = 'be', length) { + return this.value.toArrayLike(Uint8Array, endian, length); } - arr.push(new Uint8Array(optionalFieldsArr)); +} - if (!this.s2k || this.s2k.type !== 'gnu-dummy') { - if (!this.s2k_usage) { - const cleartextParams = write_cleartext_params(this.params, this.algorithm); - this.keyMaterial = _util2.default.concatUint8Array([cleartextParams, _util2.default.write_checksum(cleartextParams)]); - } +var bn_interface = /*#__PURE__*/Object.freeze({ + __proto__: null, + 'default': BigInteger$1 +}); - if (this.version === 5) { - arr.push(_util2.default.writeNumber(this.keyMaterial.length, 4)); +var utils_1 = createCommonjsModule(function (module, exports) { + +var utils = exports; + +function toArray(msg, enc) { + if (Array.isArray(msg)) + return msg.slice(); + if (!msg) + return []; + var res = []; + if (typeof msg !== 'string') { + for (var i = 0; i < msg.length; i++) + res[i] = msg[i] | 0; + return res; + } + if (enc === 'hex') { + msg = msg.replace(/[^a-z0-9]+/ig, ''); + if (msg.length % 2 !== 0) + msg = '0' + msg; + for (var i = 0; i < msg.length; i += 2) + res.push(parseInt(msg[i] + msg[i + 1], 16)); + } else { + for (var i = 0; i < msg.length; i++) { + var c = msg.charCodeAt(i); + var hi = c >> 8; + var lo = c & 0xff; + if (hi) + res.push(hi, lo); + else + res.push(lo); } - arr.push(this.keyMaterial); } + return res; +} +utils.toArray = toArray; - return _util2.default.concatUint8Array(arr); -}; +function zero2(word) { + if (word.length === 1) + return '0' + word; + else + return word; +} +utils.zero2 = zero2; -/** - * Check whether secret-key data is available in decrypted form. Returns null for public keys. - * @returns {Boolean|null} - */ -SecretKey.prototype.isDecrypted = function () { - return this.isEncrypted === false; +function toHex(msg) { + var res = ''; + for (var i = 0; i < msg.length; i++) + res += zero2(msg[i].toString(16)); + return res; +} +utils.toHex = toHex; + +utils.encode = function encode(arr, enc) { + if (enc === 'hex') + return toHex(arr); + else + return arr; }; +}); -/** - * Encrypt the payload. By default, we use aes256 and iterated, salted string - * to key specifier. If the key is in a decrypted state (isEncrypted === false) - * and the passphrase is empty or undefined, the key will be set as not encrypted. - * This can be used to remove passphrase protection after calling decrypt(). - * @param {String} passphrase - * @returns {Promise} - * @async - */ -SecretKey.prototype.encrypt = async function (passphrase) { - if (this.s2k && this.s2k.type === 'gnu-dummy') { - return false; - } +var utils_1$1 = createCommonjsModule(function (module, exports) { - if (this.isDecrypted() && !passphrase) { - this.s2k_usage = 0; - return false; - } else if (!passphrase) { - throw new Error('The key must be decrypted before removing passphrase protection.'); - } - - this.s2k = new _s2k2.default(); - this.s2k.salt = await _crypto2.default.random.getRandomBytes(8); - const cleartext = write_cleartext_params(this.params, this.algorithm); - const key = await produceEncryptionKey(this.s2k, passphrase, this.symmetric); - const blockLen = _crypto2.default.cipher[this.symmetric].blockSize; - this.iv = await _crypto2.default.random.getRandomBytes(blockLen); - - if (this.version === 5) { - this.s2k_usage = 253; - const mode = _crypto2.default[this.aead]; - const modeInstance = await mode(this.symmetric, key); - this.keyMaterial = await modeInstance.encrypt(cleartext, this.iv.subarray(0, mode.ivLength), new Uint8Array()); - } else { - this.s2k_usage = 254; - this.keyMaterial = _crypto2.default.cfb.encrypt(this.symmetric, key, _util2.default.concatUint8Array([cleartext, await _crypto2.default.hash.sha1(cleartext)]), this.iv); - } - return true; -}; +var utils = exports; -async function produceEncryptionKey(s2k, passphrase, algorithm) { - return s2k.produce_key(passphrase, _crypto2.default.cipher[algorithm].keySize); -} -/** - * Decrypts the private key params which are needed to use the key. - * {@link module:packet.SecretKey.isDecrypted} should be false, as - * otherwise calls to this function will throw an error. - * @param {String} passphrase The passphrase for this private key as string - * @returns {Promise} - * @async - */ -SecretKey.prototype.decrypt = async function (passphrase) { - if (this.s2k.type === 'gnu-dummy') { - this.isEncrypted = false; - return false; - } - if (this.isDecrypted()) { - throw new Error('Key packet is already decrypted.'); - } - let key; - if (this.s2k_usage === 255 || this.s2k_usage === 254 || this.s2k_usage === 253) { - key = await produceEncryptionKey(this.s2k, passphrase, this.symmetric); - } else { - key = await _crypto2.default.hash.md5(passphrase); - } +utils.assert = minimalisticAssert; +utils.toArray = utils_1.toArray; +utils.zero2 = utils_1.zero2; +utils.toHex = utils_1.toHex; +utils.encode = utils_1.encode; - let cleartext; - if (this.s2k_usage === 253) { - const mode = _crypto2.default[this.aead]; - try { - const modeInstance = await mode(this.symmetric, key); - cleartext = await modeInstance.decrypt(this.keyMaterial, this.iv.subarray(0, mode.ivLength), new Uint8Array()); - } catch (err) { - if (err.message === 'Authentication tag mismatch') { - throw new Error('Incorrect key passphrase: ' + err.message); - } - throw err; - } - } else { - const cleartextWithHash = await _crypto2.default.cfb.decrypt(this.symmetric, key, this.keyMaterial, this.iv); - - let hash; - let hashlen; - if (this.s2k_usage === 255) { - hashlen = 2; - cleartext = cleartextWithHash.subarray(0, -hashlen); - hash = _util2.default.write_checksum(cleartext); +// Represent num in a w-NAF form +function getNAF(num, w) { + var naf = []; + var ws = 1 << (w + 1); + var k = num.clone(); + while (k.cmpn(1) >= 0) { + var z; + if (k.isOdd()) { + var mod = k.andln(ws - 1); + if (mod > (ws >> 1) - 1) + z = (ws >> 1) - mod; + else + z = mod; + k.isubn(z); } else { - hashlen = 20; - cleartext = cleartextWithHash.subarray(0, -hashlen); - hash = await _crypto2.default.hash.sha1(cleartext); + z = 0; } + naf.push(z); - if (!_util2.default.equalsUint8Array(hash, cleartextWithHash.subarray(-hashlen))) { - throw new Error('Incorrect key passphrase'); - } + // Optimization, shift by word if possible + var shift = (k.cmpn(0) !== 0 && k.andln(ws - 1) === 0) ? (w + 1) : 1; + for (var i = 1; i < shift; i++) + naf.push(0); + k.iushrn(shift); } - const privParams = parse_cleartext_params(cleartext, this.algorithm); - this.params = this.params.concat(privParams); - this.isEncrypted = false; - this.keyMaterial = null; - this.s2k_usage = 0; + return naf; +} +utils.getNAF = getNAF; + +// Represent k1, k2 in a Joint Sparse Form +function getJSF(k1, k2) { + var jsf = [ + [], + [] + ]; - return true; -}; + k1 = k1.clone(); + k2 = k2.clone(); + var d1 = 0; + var d2 = 0; + while (k1.cmpn(-d1) > 0 || k2.cmpn(-d2) > 0) { -SecretKey.prototype.generate = async function (bits, curve) { - const algo = _enums2.default.write(_enums2.default.publicKey, this.algorithm); - this.params = await _crypto2.default.generateParams(algo, bits, curve); - this.isEncrypted = false; -}; + // First phase + var m14 = (k1.andln(3) + d1) & 3; + var m24 = (k2.andln(3) + d2) & 3; + if (m14 === 3) + m14 = -1; + if (m24 === 3) + m24 = -1; + var u1; + if ((m14 & 1) === 0) { + u1 = 0; + } else { + var m8 = (k1.andln(7) + d1) & 7; + if ((m8 === 3 || m8 === 5) && m24 === 2) + u1 = -m14; + else + u1 = m14; + } + jsf[0].push(u1); -/** - * Clear private params, return to initial state - */ -SecretKey.prototype.clearPrivateParams = function () { - if (this.s2k && this.s2k.type === 'gnu-dummy') { - this.isEncrypted = true; - return; - } + var u2; + if ((m24 & 1) === 0) { + u2 = 0; + } else { + var m8 = (k2.andln(7) + d2) & 7; + if ((m8 === 3 || m8 === 5) && m14 === 2) + u2 = -m24; + else + u2 = m24; + } + jsf[1].push(u2); - if (!this.keyMaterial) { - throw new Error('If secret key is not encrypted, clearing private params is irreversible.'); + // Second phase + if (2 * d1 === u1 + 1) + d1 = 1 - d1; + if (2 * d2 === u2 + 1) + d2 = 1 - d2; + k1.iushrn(1); + k2.iushrn(1); } - const algo = _enums2.default.write(_enums2.default.publicKey, this.algorithm); - this.params = this.params.slice(0, _crypto2.default.getPubKeyParamTypes(algo).length); - this.isEncrypted = true; -}; -/** - * Fix custom types after cloning - */ -SecretKey.prototype.postCloneTypeFix = function () { - const algo = _enums2.default.write(_enums2.default.publicKey, this.algorithm); - const types = [].concat(_crypto2.default.getPubKeyParamTypes(algo), _crypto2.default.getPrivKeyParamTypes(algo)); - for (let i = 0; i < this.params.length; i++) { - const param = this.params[i]; - this.params[i] = types[i].fromClone(param); - } - if (this.keyid) { - this.keyid = _keyid2.default.fromClone(this.keyid); - } -}; + return jsf; +} +utils.getJSF = getJSF; -exports.default = SecretKey; +function cachedProperty(obj, name, computer) { + var key = '_' + name; + obj.prototype[name] = function cachedProperty() { + return this[key] !== undefined ? this[key] : + this[key] = computer.call(this); + }; +} +utils.cachedProperty = cachedProperty; -},{"../crypto":94,"../enums":113,"../type/keyid.js":148,"../type/s2k":151,"../util":152,"./public_key":131}],135:[function(require,module,exports){ -'use strict'; +function parseBytes(bytes) { + return typeof bytes === 'string' ? utils.toArray(bytes, 'hex') : + bytes; +} +utils.parseBytes = parseBytes; -Object.defineProperty(exports, "__esModule", { - value: true +function intFromLE(bytes) { + return new bn(bytes, 'hex', 'le'); +} +utils.intFromLE = intFromLE; }); -var _secret_key = require('./secret_key'); - -var _secret_key2 = _interopRequireDefault(_secret_key); - -var _enums = require('../enums'); - -var _enums2 = _interopRequireDefault(_enums); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +var r$1; -/** - * A Secret-Subkey packet (tag 7) is the subkey analog of the Secret - * Key packet and has exactly the same format. - * @memberof module:packet - * @constructor - * @extends module:packet.SecretKey - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +var brorand = function rand(len) { + if (!r$1) + r$1 = new Rand(null); -/** - * @requires packet/secret_key - * @requires enums - */ + return r$1.generate(len); +}; -function SecretSubkey(date = new Date()) { - _secret_key2.default.call(this, date); - this.tag = _enums2.default.packet.secretSubkey; +function Rand(rand) { + this.rand = rand; } +var Rand_1 = Rand; -SecretSubkey.prototype = new _secret_key2.default(); -SecretSubkey.prototype.constructor = SecretSubkey; - -exports.default = SecretSubkey; - -},{"../enums":113,"./secret_key":134}],136:[function(require,module,exports){ -'use strict'; +Rand.prototype.generate = function generate(len) { + return this._rand(len); +}; -Object.defineProperty(exports, "__esModule", { - value: true -}); +// Emulate crypto API using randy +Rand.prototype._rand = function _rand(n) { + if (this.rand.getBytes) + return this.rand.getBytes(n); -var _webStreamTools = require('web-stream-tools'); + var res = new Uint8Array(n); + for (var i = 0; i < res.length; i++) + res[i] = this.rand.getByte(); + return res; +}; -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); +if (typeof self === 'object') { + if (self.crypto && self.crypto.getRandomValues) { + // Modern browsers + Rand.prototype._rand = function _rand(n) { + var arr = new Uint8Array(n); + self.crypto.getRandomValues(arr); + return arr; + }; + } else if (self.msCrypto && self.msCrypto.getRandomValues) { + // IE + Rand.prototype._rand = function _rand(n) { + var arr = new Uint8Array(n); + self.msCrypto.getRandomValues(arr); + return arr; + }; -var _packet = require('./packet'); + // Safari's WebWorkers do not have `crypto` + } else if (typeof window === 'object') { + // Old junk + Rand.prototype._rand = function() { + throw new Error('Not implemented yet'); + }; + } +} else { + // Node.js or Web worker with no crypto support + try { + var crypto$2 = crypto__default['default']; + if (typeof crypto$2.randomBytes !== 'function') + throw new Error('Not supported'); -var _packet2 = _interopRequireDefault(_packet); + Rand.prototype._rand = function _rand(n) { + return crypto$2.randomBytes(n); + }; + } catch (e) { + } +} +brorand.Rand = Rand_1; -var _keyid = require('../type/keyid.js'); +var getNAF = utils_1$1.getNAF; +var getJSF = utils_1$1.getJSF; +var assert$2 = utils_1$1.assert; -var _keyid2 = _interopRequireDefault(_keyid); +function BaseCurve(type, conf) { + this.type = type; + this.p = new bn(conf.p, 16); -var _mpi = require('../type/mpi.js'); + // Use Montgomery, when there is no fast reduction for the prime + this.red = conf.prime ? bn.red(conf.prime) : bn.mont(this.p); -var _mpi2 = _interopRequireDefault(_mpi); + // Useful for many curves + this.zero = new bn(0).toRed(this.red); + this.one = new bn(1).toRed(this.red); + this.two = new bn(2).toRed(this.red); -var _crypto = require('../crypto'); + // Curve configuration, optional + this.n = conf.n && new bn(conf.n, 16); + this.g = conf.g && this.pointFromJSON(conf.g, conf.gRed); -var _crypto2 = _interopRequireDefault(_crypto); + // Temporary arrays + this._wnafT1 = new Array(4); + this._wnafT2 = new Array(4); + this._wnafT3 = new Array(4); + this._wnafT4 = new Array(4); -var _enums = require('../enums'); + // Generalized Greg Maxwell's trick + var adjustCount = this.n && this.p.div(this.n); + if (!adjustCount || adjustCount.cmpn(100) > 0) { + this.redN = null; + } else { + this._maxwellTrick = true; + this.redN = this.n.toRed(this.red); + } +} +var base = BaseCurve; -var _enums2 = _interopRequireDefault(_enums); +BaseCurve.prototype.point = function point() { + throw new Error('Not implemented'); +}; -var _util = require('../util'); +BaseCurve.prototype.validate = function validate() { + throw new Error('Not implemented'); +}; -var _util2 = _interopRequireDefault(_util); +BaseCurve.prototype._fixedNafMul = function _fixedNafMul(p, k) { + assert$2(p.precomputed); + var doubles = p._getDoubles(); -var _config = require('../config'); + var naf = getNAF(k, 1); + var I = (1 << (doubles.step + 1)) - (doubles.step % 2 === 0 ? 2 : 1); + I /= 3; -var _config2 = _interopRequireDefault(_config); + // Translate into more windowed form + var repr = []; + for (var j = 0; j < naf.length; j += doubles.step) { + var nafW = 0; + for (var k = j + doubles.step - 1; k >= j; k--) + nafW = (nafW << 1) + naf[k]; + repr.push(nafW); + } -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + var a = this.jpoint(null, null, null); + var b = this.jpoint(null, null, null); + for (var i = I; i > 0; i--) { + for (var j = 0; j < repr.length; j++) { + var nafW = repr[j]; + if (nafW === i) + b = b.mixedAdd(doubles.points[j]); + else if (nafW === -i) + b = b.mixedAdd(doubles.points[j].neg()); + } + a = a.add(b); + } + return a.toP(); +}; -/** - * Implementation of the Signature Packet (Tag 2) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.2|RFC4480 5.2}: - * A Signature packet describes a binding between some public key and - * some data. The most common signatures are a signature of a file or a - * block of text, and a signature that is a certification of a User ID. - * @memberof module:packet - * @constructor - * @param {Date} date the creation date of the signature - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +BaseCurve.prototype._wnafMul = function _wnafMul(p, k) { + var w = 4; -/** - * @requires web-stream-tools - * @requires packet/packet - * @requires type/keyid - * @requires type/mpi - * @requires crypto - * @requires enums - * @requires util - */ - -function Signature(date = new Date()) { - this.tag = _enums2.default.packet.signature; - this.version = 4; // This is set to 5 below if we sign with a V5 key. - this.signatureType = null; - this.hashAlgorithm = null; - this.publicKeyAlgorithm = null; - - this.signatureData = null; - this.unhashedSubpackets = []; - this.signedHashValue = null; - - this.created = _util2.default.normalizeDate(date); - this.signatureExpirationTime = null; - this.signatureNeverExpires = true; - this.exportable = null; - this.trustLevel = null; - this.trustAmount = null; - this.regularExpression = null; - this.revocable = null; - this.keyExpirationTime = null; - this.keyNeverExpires = null; - this.preferredSymmetricAlgorithms = null; - this.revocationKeyClass = null; - this.revocationKeyAlgorithm = null; - this.revocationKeyFingerprint = null; - this.issuerKeyId = new _keyid2.default(); - this.notations = []; - this.preferredHashAlgorithms = null; - this.preferredCompressionAlgorithms = null; - this.keyServerPreferences = null; - this.preferredKeyServer = null; - this.isPrimaryUserID = null; - this.policyURI = null; - this.keyFlags = null; - this.signersUserId = null; - this.reasonForRevocationFlag = null; - this.reasonForRevocationString = null; - this.features = null; - this.signatureTargetPublicKeyAlgorithm = null; - this.signatureTargetHashAlgorithm = null; - this.signatureTargetHash = null; - this.embeddedSignature = null; - this.issuerKeyVersion = null; - this.issuerFingerprint = null; - this.preferredAeadAlgorithms = null; - - this.verified = null; - this.revoked = null; -} - -/** - * parsing function for a signature packet (tag 2). - * @param {String} bytes payload of a tag 2 packet - * @param {Integer} position position to start reading from the bytes string - * @param {Integer} len length of the packet or the remaining length of bytes at position - * @returns {module:packet.Signature} object representation - */ -Signature.prototype.read = function (bytes) { - let i = 0; - this.version = bytes[i++]; - - if (this.version !== 4 && this.version !== 5) { - throw new Error('Version ' + this.version + ' of the signature is unsupported.'); - } - - this.signatureType = bytes[i++]; - this.publicKeyAlgorithm = bytes[i++]; - this.hashAlgorithm = bytes[i++]; - - // hashed subpackets - i += this.read_sub_packets(bytes.subarray(i, bytes.length), true); - - // A V4 signature hashes the packet body - // starting from its first field, the version number, through the end - // of the hashed subpacket data. Thus, the fields hashed are the - // signature version, the signature type, the public-key algorithm, the - // hash algorithm, the hashed subpacket length, and the hashed - // subpacket body. - this.signatureData = bytes.subarray(0, i); - - // unhashed subpackets - i += this.read_sub_packets(bytes.subarray(i, bytes.length), false); - - // Two-octet field holding left 16 bits of signed hash value. - this.signedHashValue = bytes.subarray(i, i + 2); - i += 2; - - this.signature = bytes.subarray(i, bytes.length); -}; - -Signature.prototype.write = function () { - const arr = []; - arr.push(this.signatureData); - arr.push(this.write_unhashed_sub_packets()); - arr.push(this.signedHashValue); - arr.push(_webStreamTools2.default.clone(this.signature)); - return _util2.default.concat(arr); -}; + // Precompute window + var nafPoints = p._getNAFPoints(w); + w = nafPoints.wnd; + var wnd = nafPoints.points; -/** - * Signs provided data. This needs to be done prior to serialization. - * @param {module:packet.SecretKey} key private key used to sign the message. - * @param {Object} data Contains packets to be signed. - * @param {Boolean} detached (optional) whether to create a detached signature - * @returns {Promise} - * @async - */ -Signature.prototype.sign = async function (key, data, detached = false) { - const signatureType = _enums2.default.write(_enums2.default.signature, this.signatureType); - const publicKeyAlgorithm = _enums2.default.write(_enums2.default.publicKey, this.publicKeyAlgorithm); - const hashAlgorithm = _enums2.default.write(_enums2.default.hash, this.hashAlgorithm); + // Get NAF form + var naf = getNAF(k, w); - if (key.version === 5) { - this.version = 5; - } - const arr = [new Uint8Array([this.version, signatureType, publicKeyAlgorithm, hashAlgorithm])]; + // Add `this`*(N+1) for every w-NAF index + var acc = this.jpoint(null, null, null); + for (var i = naf.length - 1; i >= 0; i--) { + // Count zeroes + for (var k = 0; i >= 0 && naf[i] === 0; i--) + k++; + if (i >= 0) + k++; + acc = acc.dblp(k); - if (key.version === 5) { - // We could also generate this subpacket for version 4 keys, but for - // now we don't. - this.issuerKeyVersion = key.version; - this.issuerFingerprint = key.getFingerprintBytes(); + if (i < 0) + break; + var z = naf[i]; + assert$2(z !== 0); + if (p.type === 'affine') { + // J +- P + if (z > 0) + acc = acc.mixedAdd(wnd[(z - 1) >> 1]); + else + acc = acc.mixedAdd(wnd[(-z - 1) >> 1].neg()); + } else { + // J +- J + if (z > 0) + acc = acc.add(wnd[(z - 1) >> 1]); + else + acc = acc.add(wnd[(-z - 1) >> 1].neg()); + } } + return p.type === 'affine' ? acc.toP() : acc; +}; - this.issuerKeyId = key.getKeyId(); +BaseCurve.prototype._wnafMulAdd = function _wnafMulAdd(defW, + points, + coeffs, + len, + jacobianResult) { + var wndWidth = this._wnafT1; + var wnd = this._wnafT2; + var naf = this._wnafT3; - // Add hashed subpackets - arr.push(this.write_hashed_sub_packets()); + // Fill all arrays + var max = 0; + for (var i = 0; i < len; i++) { + var p = points[i]; + var nafPoints = p._getNAFPoints(defW); + wndWidth[i] = nafPoints.wnd; + wnd[i] = nafPoints.points; + } - this.signatureData = _util2.default.concat(arr); + // Comb small window NAFs + for (var i = len - 1; i >= 1; i -= 2) { + var a = i - 1; + var b = i; + if (wndWidth[a] !== 1 || wndWidth[b] !== 1) { + naf[a] = getNAF(coeffs[a], wndWidth[a]); + naf[b] = getNAF(coeffs[b], wndWidth[b]); + max = Math.max(naf[a].length, max); + max = Math.max(naf[b].length, max); + continue; + } - const toHash = this.toHash(signatureType, data, detached); - const hash = await this.hash(signatureType, data, toHash, detached); + var comb = [ + points[a], /* 1 */ + null, /* 3 */ + null, /* 5 */ + points[b] /* 7 */ + ]; - this.signedHashValue = _webStreamTools2.default.slice(_webStreamTools2.default.clone(hash), 0, 2); + // Try to avoid Projective points, if possible + if (points[a].y.cmp(points[b].y) === 0) { + comb[1] = points[a].add(points[b]); + comb[2] = points[a].toJ().mixedAdd(points[b].neg()); + } else if (points[a].y.cmp(points[b].y.redNeg()) === 0) { + comb[1] = points[a].toJ().mixedAdd(points[b]); + comb[2] = points[a].add(points[b].neg()); + } else { + comb[1] = points[a].toJ().mixedAdd(points[b]); + comb[2] = points[a].toJ().mixedAdd(points[b].neg()); + } - const params = key.params; - this.signature = _webStreamTools2.default.fromAsync(async () => _crypto2.default.signature.sign(publicKeyAlgorithm, hashAlgorithm, params, toHash, (await _webStreamTools2.default.readToEnd(hash)))); + var index = [ + -3, /* -1 -1 */ + -1, /* -1 0 */ + -5, /* -1 1 */ + -7, /* 0 -1 */ + 0, /* 0 0 */ + 7, /* 0 1 */ + 5, /* 1 -1 */ + 1, /* 1 0 */ + 3 /* 1 1 */ + ]; - // Store the fact that this signature is valid, e.g. for when we call `await - // getLatestValidSignature(this.revocationSignatures, key, data)` later. Note - // that this only holds up if the key and data passed to verify are the same - // as the ones passed to sign. - this.verified = true; - return true; -}; + var jsf = getJSF(coeffs[a], coeffs[b]); + max = Math.max(jsf[0].length, max); + naf[a] = new Array(max); + naf[b] = new Array(max); + for (var j = 0; j < max; j++) { + var ja = jsf[0][j] | 0; + var jb = jsf[1][j] | 0; -/** - * Creates Uint8Array of bytes of all subpacket data except Issuer and Embedded Signature subpackets - * @returns {Uint8Array} subpacket data - */ -Signature.prototype.write_hashed_sub_packets = function () { - const sub = _enums2.default.signatureSubpacket; - const arr = []; - let bytes; - if (this.created !== null) { - arr.push(write_sub_packet(sub.signature_creation_time, _util2.default.writeDate(this.created))); - } - if (this.signatureExpirationTime !== null) { - arr.push(write_sub_packet(sub.signature_expiration_time, _util2.default.writeNumber(this.signatureExpirationTime, 4))); - } - if (this.exportable !== null) { - arr.push(write_sub_packet(sub.exportable_certification, new Uint8Array([this.exportable ? 1 : 0]))); - } - if (this.trustLevel !== null) { - bytes = new Uint8Array([this.trustLevel, this.trustAmount]); - arr.push(write_sub_packet(sub.trust_signature, bytes)); - } - if (this.regularExpression !== null) { - arr.push(write_sub_packet(sub.regular_expression, this.regularExpression)); - } - if (this.revocable !== null) { - arr.push(write_sub_packet(sub.revocable, new Uint8Array([this.revocable ? 1 : 0]))); - } - if (this.keyExpirationTime !== null) { - arr.push(write_sub_packet(sub.key_expiration_time, _util2.default.writeNumber(this.keyExpirationTime, 4))); - } - if (this.preferredSymmetricAlgorithms !== null) { - bytes = _util2.default.str_to_Uint8Array(_util2.default.Uint8Array_to_str(this.preferredSymmetricAlgorithms)); - arr.push(write_sub_packet(sub.preferred_symmetric_algorithms, bytes)); - } - if (this.revocationKeyClass !== null) { - bytes = new Uint8Array([this.revocationKeyClass, this.revocationKeyAlgorithm]); - bytes = _util2.default.concat([bytes, this.revocationKeyFingerprint]); - arr.push(write_sub_packet(sub.revocation_key, bytes)); - } - this.notations.forEach(([name, value]) => { - bytes = [new Uint8Array([0x80, 0, 0, 0])]; - // 2 octets of name length - bytes.push(_util2.default.writeNumber(name.length, 2)); - // 2 octets of value length - bytes.push(_util2.default.writeNumber(value.length, 2)); - bytes.push(_util2.default.str_to_Uint8Array(name + value)); - bytes = _util2.default.concat(bytes); - arr.push(write_sub_packet(sub.notation_data, bytes)); - }); - if (this.preferredHashAlgorithms !== null) { - bytes = _util2.default.str_to_Uint8Array(_util2.default.Uint8Array_to_str(this.preferredHashAlgorithms)); - arr.push(write_sub_packet(sub.preferred_hash_algorithms, bytes)); - } - if (this.preferredCompressionAlgorithms !== null) { - bytes = _util2.default.str_to_Uint8Array(_util2.default.Uint8Array_to_str(this.preferredCompressionAlgorithms)); - arr.push(write_sub_packet(sub.preferred_compression_algorithms, bytes)); - } - if (this.keyServerPreferences !== null) { - bytes = _util2.default.str_to_Uint8Array(_util2.default.Uint8Array_to_str(this.keyServerPreferences)); - arr.push(write_sub_packet(sub.key_server_preferences, bytes)); - } - if (this.preferredKeyServer !== null) { - arr.push(write_sub_packet(sub.preferred_key_server, _util2.default.str_to_Uint8Array(this.preferredKeyServer))); - } - if (this.isPrimaryUserID !== null) { - arr.push(write_sub_packet(sub.primary_user_id, new Uint8Array([this.isPrimaryUserID ? 1 : 0]))); - } - if (this.policyURI !== null) { - arr.push(write_sub_packet(sub.policy_uri, _util2.default.str_to_Uint8Array(this.policyURI))); - } - if (this.keyFlags !== null) { - bytes = _util2.default.str_to_Uint8Array(_util2.default.Uint8Array_to_str(this.keyFlags)); - arr.push(write_sub_packet(sub.key_flags, bytes)); - } - if (this.signersUserId !== null) { - arr.push(write_sub_packet(sub.signers_user_id, _util2.default.str_to_Uint8Array(this.signersUserId))); - } - if (this.reasonForRevocationFlag !== null) { - bytes = _util2.default.str_to_Uint8Array(String.fromCharCode(this.reasonForRevocationFlag) + this.reasonForRevocationString); - arr.push(write_sub_packet(sub.reason_for_revocation, bytes)); - } - if (this.features !== null) { - bytes = _util2.default.str_to_Uint8Array(_util2.default.Uint8Array_to_str(this.features)); - arr.push(write_sub_packet(sub.features, bytes)); - } - if (this.signatureTargetPublicKeyAlgorithm !== null) { - bytes = [new Uint8Array([this.signatureTargetPublicKeyAlgorithm, this.signatureTargetHashAlgorithm])]; - bytes.push(_util2.default.str_to_Uint8Array(this.signatureTargetHash)); - bytes = _util2.default.concat(bytes); - arr.push(write_sub_packet(sub.signature_target, bytes)); - } - if (this.preferredAeadAlgorithms !== null) { - bytes = _util2.default.str_to_Uint8Array(_util2.default.Uint8Array_to_str(this.preferredAeadAlgorithms)); - arr.push(write_sub_packet(sub.preferred_aead_algorithms, bytes)); + naf[a][j] = index[(ja + 1) * 3 + (jb + 1)]; + naf[b][j] = 0; + wnd[a] = comb; + } } - const result = _util2.default.concat(arr); - const length = _util2.default.writeNumber(result.length, 2); + var acc = this.jpoint(null, null, null); + var tmp = this._wnafT4; + for (var i = max; i >= 0; i--) { + var k = 0; - return _util2.default.concat([length, result]); -}; + while (i >= 0) { + var zero = true; + for (var j = 0; j < len; j++) { + tmp[j] = naf[j][i] | 0; + if (tmp[j] !== 0) + zero = false; + } + if (!zero) + break; + k++; + i--; + } + if (i >= 0) + k++; + acc = acc.dblp(k); + if (i < 0) + break; -/** - * Creates Uint8Array of bytes of Issuer and Embedded Signature subpackets - * @returns {Uint8Array} subpacket data - */ -Signature.prototype.write_unhashed_sub_packets = function () { - const sub = _enums2.default.signatureSubpacket; - const arr = []; - let bytes; - if (!this.issuerKeyId.isNull() && this.issuerKeyVersion !== 5) { - // If the version of [the] key is greater than 4, this subpacket - // MUST NOT be included in the signature. - arr.push(write_sub_packet(sub.issuer, this.issuerKeyId.write())); - } - if (this.embeddedSignature !== null) { - arr.push(write_sub_packet(sub.embedded_signature, this.embeddedSignature.write())); - } - if (this.issuerFingerprint !== null) { - bytes = [new Uint8Array([this.issuerKeyVersion]), this.issuerFingerprint]; - bytes = _util2.default.concat(bytes); - arr.push(write_sub_packet(sub.issuer_fingerprint, bytes)); - } - this.unhashedSubpackets.forEach(data => { - arr.push(_packet2.default.writeSimpleLength(data.length)); - arr.push(data); - }); + for (var j = 0; j < len; j++) { + var z = tmp[j]; + var p; + if (z === 0) + continue; + else if (z > 0) + p = wnd[j][(z - 1) >> 1]; + else if (z < 0) + p = wnd[j][(-z - 1) >> 1].neg(); - const result = _util2.default.concat(arr); - const length = _util2.default.writeNumber(result.length, 2); + if (p.type === 'affine') + acc = acc.mixedAdd(p); + else + acc = acc.add(p); + } + } + // Zeroify references + for (var i = 0; i < len; i++) + wnd[i] = null; - return _util2.default.concat([length, result]); + if (jacobianResult) + return acc; + else + return acc.toP(); }; -/** - * Creates a string representation of a sub signature packet - * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.1|RFC4880 5.2.3.1} - * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.2|RFC4880 5.2.3.2} - * @param {Integer} type subpacket signature type. - * @param {String} data data to be included - * @returns {String} a string-representation of a sub signature packet - * @private - */ -function write_sub_packet(type, data) { - const arr = []; - arr.push(_packet2.default.writeSimpleLength(data.length + 1)); - arr.push(new Uint8Array([type])); - arr.push(data); - return _util2.default.concat(arr); +function BasePoint(curve, type) { + this.curve = curve; + this.type = type; + this.precomputed = null; } +BaseCurve.BasePoint = BasePoint; + +BasePoint.prototype.eq = function eq(/*other*/) { + throw new Error('Not implemented'); +}; -// V4 signature sub packets +BasePoint.prototype.validate = function validate() { + return this.curve.validate(this); +}; -Signature.prototype.read_sub_packet = function (bytes, trusted = true) { - let mypos = 0; +BaseCurve.prototype.decodePoint = function decodePoint(bytes, enc) { + bytes = utils_1$1.toArray(bytes, enc); - const read_array = (prop, bytes) => { - this[prop] = []; + var len = this.p.byteLength(); - for (let i = 0; i < bytes.length; i++) { - this[prop].push(bytes[i]); - } - }; + // uncompressed, hybrid-odd, hybrid-even + if ((bytes[0] === 0x04 || bytes[0] === 0x06 || bytes[0] === 0x07) && + bytes.length - 1 === 2 * len) { + if (bytes[0] === 0x06) + assert$2(bytes[bytes.length - 1] % 2 === 0); + else if (bytes[0] === 0x07) + assert$2(bytes[bytes.length - 1] % 2 === 1); - // The leftmost bit denotes a "critical" packet - const critical = bytes[mypos] & 0x80; - const type = bytes[mypos] & 0x7F; + var res = this.point(bytes.slice(1, 1 + len), + bytes.slice(1 + len, 1 + 2 * len)); - // GPG puts the Issuer and Signature subpackets in the unhashed area. - // Tampering with those invalidates the signature, so we can trust them. - // Ignore all other unhashed subpackets. - if (!trusted && ![_enums2.default.signatureSubpacket.issuer, _enums2.default.signatureSubpacket.issuer_fingerprint, _enums2.default.signatureSubpacket.embedded_signature].includes(type)) { - this.unhashedSubpackets.push(bytes.subarray(mypos, bytes.length)); - return; + return res; + } else if ((bytes[0] === 0x02 || bytes[0] === 0x03) && + bytes.length - 1 === len) { + return this.pointFromX(bytes.slice(1, 1 + len), bytes[0] === 0x03); } + throw new Error('Unknown point format'); +}; - mypos++; +BasePoint.prototype.encodeCompressed = function encodeCompressed(enc) { + return this.encode(enc, true); +}; - // subpacket type - switch (type) { - case 2: - // Signature Creation Time - this.created = _util2.default.readDate(bytes.subarray(mypos, bytes.length)); - break; - case 3: - { - // Signature Expiration Time in seconds - const seconds = _util2.default.readNumber(bytes.subarray(mypos, bytes.length)); +BasePoint.prototype._encode = function _encode(compact) { + var len = this.curve.p.byteLength(); + var x = this.getX().toArray('be', len); - this.signatureNeverExpires = seconds === 0; - this.signatureExpirationTime = seconds; + if (compact) + return [ this.getY().isEven() ? 0x02 : 0x03 ].concat(x); - break; - } - case 4: - // Exportable Certification - this.exportable = bytes[mypos++] === 1; - break; - case 5: - // Trust Signature - this.trustLevel = bytes[mypos++]; - this.trustAmount = bytes[mypos++]; - break; - case 6: - // Regular Expression - this.regularExpression = bytes[mypos]; - break; - case 7: - // Revocable - this.revocable = bytes[mypos++] === 1; - break; - case 9: - { - // Key Expiration Time in seconds - const seconds = _util2.default.readNumber(bytes.subarray(mypos, bytes.length)); + return [ 0x04 ].concat(x, this.getY().toArray('be', len)) ; +}; - this.keyExpirationTime = seconds; - this.keyNeverExpires = seconds === 0; +BasePoint.prototype.encode = function encode(enc, compact) { + return utils_1$1.encode(this._encode(compact), enc); +}; - break; - } - case 11: - // Preferred Symmetric Algorithms - read_array('preferredSymmetricAlgorithms', bytes.subarray(mypos, bytes.length)); - break; - case 12: - // Revocation Key - // (1 octet of class, 1 octet of public-key algorithm ID, 20 - // octets of - // fingerprint) - this.revocationKeyClass = bytes[mypos++]; - this.revocationKeyAlgorithm = bytes[mypos++]; - this.revocationKeyFingerprint = bytes.subarray(mypos, mypos + 20); - break; +BasePoint.prototype.precompute = function precompute(power) { + if (this.precomputed) + return this; - case 16: - // Issuer - this.issuerKeyId.read(bytes.subarray(mypos, bytes.length)); - break; + var precomputed = { + doubles: null, + naf: null, + beta: null + }; + precomputed.naf = this._getNAFPoints(8); + precomputed.doubles = this._getDoubles(4, power); + precomputed.beta = this._getBeta(); + this.precomputed = precomputed; - case 20: - // Notation Data - // We don't know how to handle anything but a text flagged data. - if (bytes[mypos] === 0x80) { - // We extract key/value tuple from the byte stream. - mypos += 4; - const m = _util2.default.readNumber(bytes.subarray(mypos, mypos + 2)); - mypos += 2; - const n = _util2.default.readNumber(bytes.subarray(mypos, mypos + 2)); - mypos += 2; + return this; +}; - const name = _util2.default.Uint8Array_to_str(bytes.subarray(mypos, mypos + m)); - const value = _util2.default.Uint8Array_to_str(bytes.subarray(mypos + m, mypos + m + n)); +BasePoint.prototype._hasDoubles = function _hasDoubles(k) { + if (!this.precomputed) + return false; - this.notations.push([name, value]); + var doubles = this.precomputed.doubles; + if (!doubles) + return false; - if (critical && _config2.default.known_notations.indexOf(name) === -1) { - throw new Error("Unknown critical notation: " + name); - } - } else { - _util2.default.print_debug("Unsupported notation flag " + bytes[mypos]); - } - break; - case 21: - // Preferred Hash Algorithms - read_array('preferredHashAlgorithms', bytes.subarray(mypos, bytes.length)); - break; - case 22: - // Preferred Compression Algorithms - read_array('preferredCompressionAlgorithms', bytes.subarray(mypos, bytes.length)); - break; - case 23: - // Key Server Preferences - read_array('keyServerPreferences', bytes.subarray(mypos, bytes.length)); - break; - case 24: - // Preferred Key Server - this.preferredKeyServer = _util2.default.Uint8Array_to_str(bytes.subarray(mypos, bytes.length)); - break; - case 25: - // Primary User ID - this.isPrimaryUserID = bytes[mypos++] !== 0; - break; - case 26: - // Policy URI - this.policyURI = _util2.default.Uint8Array_to_str(bytes.subarray(mypos, bytes.length)); - break; - case 27: - // Key Flags - read_array('keyFlags', bytes.subarray(mypos, bytes.length)); - break; - case 28: - // Signer's User ID - this.signersUserId = _util2.default.Uint8Array_to_str(bytes.subarray(mypos, bytes.length)); - break; - case 29: - // Reason for Revocation - this.reasonForRevocationFlag = bytes[mypos++]; - this.reasonForRevocationString = _util2.default.Uint8Array_to_str(bytes.subarray(mypos, bytes.length)); - break; - case 30: - // Features - read_array('features', bytes.subarray(mypos, bytes.length)); - break; - case 31: - { - // Signature Target - // (1 octet public-key algorithm, 1 octet hash algorithm, N octets hash) - this.signatureTargetPublicKeyAlgorithm = bytes[mypos++]; - this.signatureTargetHashAlgorithm = bytes[mypos++]; + return doubles.points.length >= Math.ceil((k.bitLength() + 1) / doubles.step); +}; - const len = _crypto2.default.getHashByteLength(this.signatureTargetHashAlgorithm); +BasePoint.prototype._getDoubles = function _getDoubles(step, power) { + if (this.precomputed && this.precomputed.doubles) + return this.precomputed.doubles; - this.signatureTargetHash = _util2.default.Uint8Array_to_str(bytes.subarray(mypos, mypos + len)); - break; - } - case 32: - // Embedded Signature - this.embeddedSignature = new Signature(); - this.embeddedSignature.read(bytes.subarray(mypos, bytes.length)); - break; - case 33: - // Issuer Fingerprint - this.issuerKeyVersion = bytes[mypos++]; - this.issuerFingerprint = bytes.subarray(mypos, bytes.length); - if (this.issuerKeyVersion === 5) { - this.issuerKeyId.read(this.issuerFingerprint); - } else { - this.issuerKeyId.read(this.issuerFingerprint.subarray(-8)); - } - break; - case 34: - // Preferred AEAD Algorithms - read_array.call(this, 'preferredAeadAlgorithms', bytes.subarray(mypos, bytes.length)); - break; - default: - { - const err = new Error("Unknown signature subpacket type " + type + " @:" + mypos); - if (critical) { - throw err; - } else { - _util2.default.print_debug(err); - } - } + var doubles = [ this ]; + var acc = this; + for (var i = 0; i < power; i += step) { + for (var j = 0; j < step; j++) + acc = acc.dbl(); + doubles.push(acc); } + return { + step: step, + points: doubles + }; }; -Signature.prototype.read_sub_packets = function (bytes, trusted = true) { - // Two-octet scalar octet count for following subpacket data. - const subpacket_length = _util2.default.readNumber(bytes.subarray(0, 2)); - - let i = 2; - - // subpacket data set (zero or more subpackets) - while (i < 2 + subpacket_length) { - const len = _packet2.default.readSimpleLength(bytes.subarray(i, bytes.length)); - i += len.offset; +BasePoint.prototype._getNAFPoints = function _getNAFPoints(wnd) { + if (this.precomputed && this.precomputed.naf) + return this.precomputed.naf; - this.read_sub_packet(bytes.subarray(i, i + len.len), trusted); + var res = [ this ]; + var max = (1 << wnd) - 1; + var dbl = max === 1 ? null : this.dbl(); + for (var i = 1; i < max; i++) + res[i] = res[i - 1].add(dbl); + return { + wnd: wnd, + points: res + }; +}; - i += len.len; - } +BasePoint.prototype._getBeta = function _getBeta() { + return null; +}; - return i; +BasePoint.prototype.dblp = function dblp(k) { + var r = this; + for (var i = 0; i < k; i++) + r = r.dbl(); + return r; }; -// Produces data to produce signature on -Signature.prototype.toSign = function (type, data) { - const t = _enums2.default.signature; +var assert$3 = utils_1$1.assert; - switch (type) { - case t.binary: - if (data.text !== null) { - return _util2.default.str_to_Uint8Array(data.getText(true)); - } - return data.getBytes(true); +function ShortCurve(conf) { + base.call(this, 'short', conf); - case t.text: - { - let text = data.getText(true); - // normalize EOL to \r\n - text = _util2.default.canonicalizeEOL(text); - // encode UTF8 - return _util2.default.encode_utf8(text); - } - case t.standalone: - return new Uint8Array(0); - - case t.cert_generic: - case t.cert_persona: - case t.cert_casual: - case t.cert_positive: - case t.cert_revocation: - { - let packet; - let tag; + this.a = new bn(conf.a, 16).toRed(this.red); + this.b = new bn(conf.b, 16).toRed(this.red); + this.tinv = this.two.redInvm(); - if (data.userId) { - tag = 0xB4; - packet = data.userId; - } else if (data.userAttribute) { - tag = 0xD1; - packet = data.userAttribute; - } else { - throw new Error('Either a userId or userAttribute packet needs to be ' + 'supplied for certification.'); - } + this.zeroA = this.a.fromRed().cmpn(0) === 0; + this.threeA = this.a.fromRed().sub(this.p).cmpn(-3) === 0; - const bytes = packet.write(); + // If the curve is endomorphic, precalculate beta and lambda + this.endo = this._getEndomorphism(conf); + this._endoWnafT1 = new Array(4); + this._endoWnafT2 = new Array(4); +} +inherits(ShortCurve, base); +var short_1 = ShortCurve; - return _util2.default.concat([this.toSign(t.key, data), new Uint8Array([tag]), _util2.default.writeNumber(bytes.length, 4), bytes]); - } - case t.subkey_binding: - case t.subkey_revocation: - case t.key_binding: - return _util2.default.concat([this.toSign(t.key, data), this.toSign(t.key, { - key: data.bind - })]); +ShortCurve.prototype._getEndomorphism = function _getEndomorphism(conf) { + // No efficient endomorphism + if (!this.zeroA || !this.g || !this.n || this.p.modn(3) !== 1) + return; - case t.key: - if (data.key === undefined) { - throw new Error('Key packet is required for this signature.'); - } - return data.key.writeForHash(this.version); + // Compute beta and lambda, that lambda * P = (beta * Px; Py) + var beta; + var lambda; + if (conf.beta) { + beta = new bn(conf.beta, 16).toRed(this.red); + } else { + var betas = this._getEndoRoots(this.p); + // Choose the smallest beta + beta = betas[0].cmp(betas[1]) < 0 ? betas[0] : betas[1]; + beta = beta.toRed(this.red); + } + if (conf.lambda) { + lambda = new bn(conf.lambda, 16); + } else { + // Choose the lambda that is matching selected beta + var lambdas = this._getEndoRoots(this.n); + if (this.g.mul(lambdas[0]).x.cmp(this.g.x.redMul(beta)) === 0) { + lambda = lambdas[0]; + } else { + lambda = lambdas[1]; + assert$3(this.g.mul(lambda).x.cmp(this.g.x.redMul(beta)) === 0); + } + } - case t.key_revocation: - return this.toSign(t.key, data); - case t.timestamp: - return new Uint8Array(0); - case t.third_party: - throw new Error('Not implemented'); - default: - throw new Error('Unknown signature type.'); + // Get basis vectors, used for balanced length-two representation + var basis; + if (conf.basis) { + basis = conf.basis.map(function(vec) { + return { + a: new bn(vec.a, 16), + b: new bn(vec.b, 16) + }; + }); + } else { + basis = this._getEndoBasis(lambda); } -}; -Signature.prototype.calculateTrailer = function (data, detached) { - let length = 0; - return _webStreamTools2.default.transform(_webStreamTools2.default.clone(this.signatureData), value => { - length += value.length; - }, () => { - const arr = []; - if (this.version === 5 && (this.signatureType === _enums2.default.signature.binary || this.signatureType === _enums2.default.signature.text)) { - if (detached) { - arr.push(new Uint8Array(6)); - } else { - arr.push(data.writeHeader()); - } - } - arr.push(new Uint8Array([this.version, 0xFF])); - if (this.version === 5) { - arr.push(new Uint8Array(4)); - } - arr.push(_util2.default.writeNumber(length, 4)); - // For v5, this should really be writeNumber(length, 8) rather than the - // hardcoded 4 zero bytes above - return _util2.default.concat(arr); - }); + return { + beta: beta, + lambda: lambda, + basis: basis + }; }; -Signature.prototype.toHash = function (signatureType, data, detached = false) { - const bytes = this.toSign(signatureType, data); +ShortCurve.prototype._getEndoRoots = function _getEndoRoots(num) { + // Find roots of for x^2 + x + 1 in F + // Root = (-1 +- Sqrt(-3)) / 2 + // + var red = num === this.p ? this.red : bn.mont(num); + var tinv = new bn(2).toRed(red).redInvm(); + var ntinv = tinv.redNeg(); - return _util2.default.concat([bytes, this.signatureData, this.calculateTrailer(data, detached)]); -}; + var s = new bn(3).toRed(red).redNeg().redSqrt().redMul(tinv); -Signature.prototype.hash = async function (signatureType, data, toHash, detached = false, streaming = true) { - const hashAlgorithm = _enums2.default.write(_enums2.default.hash, this.hashAlgorithm); - if (!toHash) toHash = this.toHash(signatureType, data, detached); - if (!streaming && _util2.default.isStream(toHash)) { - return _webStreamTools2.default.fromAsync(async () => this.hash(signatureType, data, (await _webStreamTools2.default.readToEnd(toHash)), detached)); - } - return _crypto2.default.hash.digest(hashAlgorithm, toHash); + var l1 = ntinv.redAdd(s).fromRed(); + var l2 = ntinv.redSub(s).fromRed(); + return [ l1, l2 ]; }; -/** - * verifys the signature packet. Note: not signature types are implemented - * @param {module:packet.PublicSubkey|module:packet.PublicKey| - * module:packet.SecretSubkey|module:packet.SecretKey} key the public key to verify the signature - * @param {module:enums.signature} signatureType expected signature type - * @param {String|Object} data data which on the signature applies - * @param {Boolean} detached (optional) whether to verify a detached signature - * @returns {Promise} True if message is verified, else false. - * @async - */ -Signature.prototype.verify = async function (key, signatureType, data, detached = false) { - const publicKeyAlgorithm = _enums2.default.write(_enums2.default.publicKey, this.publicKeyAlgorithm); - const hashAlgorithm = _enums2.default.write(_enums2.default.hash, this.hashAlgorithm); - - if (publicKeyAlgorithm !== _enums2.default.write(_enums2.default.publicKey, key.algorithm)) { - throw new Error('Public key algorithm used to sign signature does not match issuer key algorithm.'); - } +ShortCurve.prototype._getEndoBasis = function _getEndoBasis(lambda) { + // aprxSqrt >= sqrt(this.n) + var aprxSqrt = this.n.ushrn(Math.floor(this.n.bitLength() / 2)); - let toHash; - let hash; - if (this.hashed) { - hash = this.hashed; - } else { - toHash = this.toHash(signatureType, data, detached); - hash = await this.hash(signatureType, data, toHash); - } - hash = await _webStreamTools2.default.readToEnd(hash); + // 3.74 + // Run EGCD, until r(L + 1) < aprxSqrt + var u = lambda; + var v = this.n.clone(); + var x1 = new bn(1); + var y1 = new bn(0); + var x2 = new bn(0); + var y2 = new bn(1); - if (this.signedHashValue[0] !== hash[0] || this.signedHashValue[1] !== hash[1]) { - this.verified = false; - } else { - let mpicount = 0; - // Algorithm-Specific Fields for RSA signatures: - // - multiprecision number (MPI) of RSA signature value m**d mod n. - if (publicKeyAlgorithm > 0 && publicKeyAlgorithm < 4) { - mpicount = 1; + // NOTE: all vectors are roots of: a + b * lambda = 0 (mod n) + var a0; + var b0; + // First vector + var a1; + var b1; + // Second vector + var a2; + var b2; - // Algorithm-Specific Fields for DSA, ECDSA, and EdDSA signatures: - // - MPI of DSA value r. - // - MPI of DSA value s. - } else if (publicKeyAlgorithm === _enums2.default.publicKey.dsa || publicKeyAlgorithm === _enums2.default.publicKey.ecdsa || publicKeyAlgorithm === _enums2.default.publicKey.eddsa) { - mpicount = 2; - } + var prevR; + var i = 0; + var r; + var x; + while (u.cmpn(0) !== 0) { + var q = v.div(u); + r = v.sub(q.mul(u)); + x = x2.sub(q.mul(x1)); + var y = y2.sub(q.mul(y1)); - // EdDSA signature parameters are encoded in little-endian format - // https://tools.ietf.org/html/rfc8032#section-5.1.2 - const endian = publicKeyAlgorithm === _enums2.default.publicKey.eddsa ? 'le' : 'be'; - const mpi = []; - let i = 0; - this.signature = await _webStreamTools2.default.readToEnd(this.signature); - for (let j = 0; j < mpicount; j++) { - mpi[j] = new _mpi2.default(); - i += mpi[j].read(this.signature.subarray(i, this.signature.length), endian); + if (!a1 && r.cmp(aprxSqrt) < 0) { + a0 = prevR.neg(); + b0 = x1; + a1 = r.neg(); + b1 = x; + } else if (a1 && ++i === 2) { + break; } + prevR = r; - this.verified = await _crypto2.default.signature.verify(publicKeyAlgorithm, hashAlgorithm, mpi, key.params, toHash, hash); + v = u; + u = r; + x2 = x1; + x1 = x; + y2 = y1; + y1 = y; } - return this.verified; -}; + a2 = r.neg(); + b2 = x; -/** - * Verifies signature expiration date - * @param {Date} date (optional) use the given date for verification instead of the current time - * @returns {Boolean} true if expired - */ -Signature.prototype.isExpired = function (date = new Date()) { - const normDate = _util2.default.normalizeDate(date); - if (normDate !== null) { - const expirationTime = this.getExpirationTime(); - return !(this.created <= normDate && normDate <= expirationTime); + var len1 = a1.sqr().add(b1.sqr()); + var len2 = a2.sqr().add(b2.sqr()); + if (len2.cmp(len1) >= 0) { + a2 = a0; + b2 = b0; } - return false; -}; -/** - * Returns the expiration time of the signature or Infinity if signature does not expire - * @returns {Date} expiration time - */ -Signature.prototype.getExpirationTime = function () { - return !this.signatureNeverExpires ? new Date(this.created.getTime() + this.signatureExpirationTime * 1000) : Infinity; -}; + // Normalize signs + if (a1.negative) { + a1 = a1.neg(); + b1 = b1.neg(); + } + if (a2.negative) { + a2 = a2.neg(); + b2 = b2.neg(); + } -/** - * Fix custom types after cloning - */ -Signature.prototype.postCloneTypeFix = function () { - this.issuerKeyId = _keyid2.default.fromClone(this.issuerKeyId); + return [ + { a: a1, b: b1 }, + { a: a2, b: b2 } + ]; }; -exports.default = Signature; - -},{"../config":79,"../crypto":94,"../enums":113,"../type/keyid.js":148,"../type/mpi.js":149,"../util":152,"./packet":129,"web-stream-tools":75}],137:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _webStreamTools = require('web-stream-tools'); - -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); - -var _config = require('../config'); - -var _config2 = _interopRequireDefault(_config); - -var _crypto = require('../crypto'); - -var _crypto2 = _interopRequireDefault(_crypto); +ShortCurve.prototype._endoSplit = function _endoSplit(k) { + var basis = this.endo.basis; + var v1 = basis[0]; + var v2 = basis[1]; -var _enums = require('../enums'); + var c1 = v2.b.mul(k).divRound(this.n); + var c2 = v1.b.neg().mul(k).divRound(this.n); -var _enums2 = _interopRequireDefault(_enums); + var p1 = c1.mul(v1.a); + var p2 = c2.mul(v2.a); + var q1 = c1.mul(v1.b); + var q2 = c2.mul(v2.b); -var _util = require('../util'); + // Calculate answer + var k1 = k.sub(p1).sub(p2); + var k2 = q1.add(q2).neg(); + return { k1: k1, k2: k2 }; +}; -var _util2 = _interopRequireDefault(_util); +ShortCurve.prototype.pointFromX = function pointFromX(x, odd) { + x = new bn(x, 16); + if (!x.red) + x = x.toRed(this.red); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + var y2 = x.redSqr().redMul(x).redIAdd(x.redMul(this.a)).redIAdd(this.b); + var y = y2.redSqrt(); + if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) + throw new Error('invalid point'); -const VERSION = 1; // A one-octet version number of the data packet. + // XXX Is there any way to tell if the number is odd without converting it + // to non-red form? + var isOdd = y.fromRed().isOdd(); + if (odd && !isOdd || !odd && isOdd) + y = y.redNeg(); -/** - * Implementation of the Symmetrically Encrypted Authenticated Encryption with - * Additional Data (AEAD) Protected Data Packet - * - * {@link https://tools.ietf.org/html/draft-ford-openpgp-format-00#section-2.1}: - * AEAD Protected Data Packet - * @memberof module:packet - * @constructor - */ -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2016 Tankred Hase -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + return this.point(x, y); +}; -/** - * @requires web-stream-tools - * @requires config - * @requires crypto - * @requires enums - * @requires util - */ +ShortCurve.prototype.validate = function validate(point) { + if (point.inf) + return true; -function SymEncryptedAEADProtected() { - this.tag = _enums2.default.packet.symEncryptedAEADProtected; - this.version = VERSION; - this.cipherAlgo = null; - this.aeadAlgorithm = 'eax'; - this.aeadAlgo = null; - this.chunkSizeByte = null; - this.iv = null; - this.encrypted = null; - this.packets = null; -} + var x = point.x; + var y = point.y; -exports.default = SymEncryptedAEADProtected; + var ax = this.a.redMul(x); + var rhs = x.redSqr().redMul(x).redIAdd(ax).redIAdd(this.b); + return y.redSqr().redISub(rhs).cmpn(0) === 0; +}; -/** - * Parse an encrypted payload of bytes in the order: version, IV, ciphertext (see specification) - * @param {Uint8Array | ReadableStream} bytes - */ +ShortCurve.prototype._endoWnafMulAdd = + function _endoWnafMulAdd(points, coeffs, jacobianResult) { + var npoints = this._endoWnafT1; + var ncoeffs = this._endoWnafT2; + for (var i = 0; i < points.length; i++) { + var split = this._endoSplit(coeffs[i]); + var p = points[i]; + var beta = p._getBeta(); -SymEncryptedAEADProtected.prototype.read = async function (bytes) { - await _webStreamTools2.default.parse(bytes, async reader => { - if ((await reader.readByte()) !== VERSION) { - // The only currently defined value is 1. - throw new Error('Invalid packet version.'); + if (split.k1.negative) { + split.k1.ineg(); + p = p.neg(true); + } + if (split.k2.negative) { + split.k2.ineg(); + beta = beta.neg(true); } - this.cipherAlgo = await reader.readByte(); - this.aeadAlgo = await reader.readByte(); - this.chunkSizeByte = await reader.readByte(); - const mode = _crypto2.default[_enums2.default.read(_enums2.default.aead, this.aeadAlgo)]; - this.iv = await reader.readBytes(mode.ivLength); - this.encrypted = reader.remainder(); - }); -}; -/** - * Write the encrypted payload of bytes in the order: version, IV, ciphertext (see specification) - * @returns {Uint8Array | ReadableStream} The encrypted payload - */ -SymEncryptedAEADProtected.prototype.write = function () { - return _util2.default.concat([new Uint8Array([this.version, this.cipherAlgo, this.aeadAlgo, this.chunkSizeByte]), this.iv, this.encrypted]); + npoints[i * 2] = p; + npoints[i * 2 + 1] = beta; + ncoeffs[i * 2] = split.k1; + ncoeffs[i * 2 + 1] = split.k2; + } + var res = this._wnafMulAdd(1, npoints, ncoeffs, i * 2, jacobianResult); + + // Clean-up references to points and coefficients + for (var j = 0; j < i * 2; j++) { + npoints[j] = null; + ncoeffs[j] = null; + } + return res; }; -/** - * Decrypt the encrypted payload. - * @param {String} sessionKeyAlgorithm The session key's cipher algorithm e.g. 'aes128' - * @param {Uint8Array} key The session key used to encrypt the payload - * @param {Boolean} streaming Whether the top-level function will return a stream - * @returns {Boolean} - * @async - */ -SymEncryptedAEADProtected.prototype.decrypt = async function (sessionKeyAlgorithm, key, streaming) { - await this.packets.read((await this.crypt('decrypt', key, _webStreamTools2.default.clone(this.encrypted), streaming)), streaming); - return true; +function Point(curve, x, y, isRed) { + base.BasePoint.call(this, curve, 'affine'); + if (x === null && y === null) { + this.x = null; + this.y = null; + this.inf = true; + } else { + this.x = new bn(x, 16); + this.y = new bn(y, 16); + // Force redgomery representation when loading from JSON + if (isRed) { + this.x.forceRed(this.curve.red); + this.y.forceRed(this.curve.red); + } + if (!this.x.red) + this.x = this.x.toRed(this.curve.red); + if (!this.y.red) + this.y = this.y.toRed(this.curve.red); + this.inf = false; + } +} +inherits(Point, base.BasePoint); + +ShortCurve.prototype.point = function point(x, y, isRed) { + return new Point(this, x, y, isRed); }; -/** - * Encrypt the packet list payload. - * @param {String} sessionKeyAlgorithm The session key's cipher algorithm e.g. 'aes128' - * @param {Uint8Array} key The session key used to encrypt the payload - * @param {Boolean} streaming Whether the top-level function will return a stream - * @async - */ -SymEncryptedAEADProtected.prototype.encrypt = async function (sessionKeyAlgorithm, key, streaming) { - this.cipherAlgo = _enums2.default.write(_enums2.default.symmetric, sessionKeyAlgorithm); - this.aeadAlgo = _enums2.default.write(_enums2.default.aead, this.aeadAlgorithm); - const mode = _crypto2.default[_enums2.default.read(_enums2.default.aead, this.aeadAlgo)]; - this.iv = await _crypto2.default.random.getRandomBytes(mode.ivLength); // generate new random IV - this.chunkSizeByte = _config2.default.aead_chunk_size_byte; - const data = this.packets.write(); - this.encrypted = await this.crypt('encrypt', key, data, streaming); +ShortCurve.prototype.pointFromJSON = function pointFromJSON(obj, red) { + return Point.fromJSON(this, obj, red); }; -/** - * En/decrypt the payload. - * @param {encrypt|decrypt} fn Whether to encrypt or decrypt - * @param {Uint8Array} key The session key used to en/decrypt the payload - * @param {Uint8Array | ReadableStream} data The data to en/decrypt - * @param {Boolean} streaming Whether the top-level function will return a stream - * @returns {Uint8Array | ReadableStream} - * @async - */ -SymEncryptedAEADProtected.prototype.crypt = async function (fn, key, data, streaming) { - const cipher = _enums2.default.read(_enums2.default.symmetric, this.cipherAlgo); - const mode = _crypto2.default[_enums2.default.read(_enums2.default.aead, this.aeadAlgo)]; - const modeInstance = await mode(cipher, key); - const tagLengthIfDecrypting = fn === 'decrypt' ? mode.tagLength : 0; - const chunkSize = 2 ** (this.chunkSizeByte + 6) + tagLengthIfDecrypting; // ((uint64_t)1 << (c + 6)) - const adataBuffer = new ArrayBuffer(21); - const adataArray = new Uint8Array(adataBuffer, 0, 13); - const adataTagArray = new Uint8Array(adataBuffer); - const adataView = new DataView(adataBuffer); - const chunkIndexArray = new Uint8Array(adataBuffer, 5, 8); - adataArray.set([0xC0 | this.tag, this.version, this.cipherAlgo, this.aeadAlgo, this.chunkSizeByte], 0); - let chunkIndex = 0; - let latestPromise = Promise.resolve(); - let cryptedBytes = 0; - let queuedBytes = 0; - const iv = this.iv; - return _webStreamTools2.default.transformPair(data, async (readable, writable) => { - const reader = _webStreamTools2.default.getReader(readable); - const buffer = new TransformStream({}, { - highWaterMark: streaming ? _util2.default.getHardwareConcurrency() * 2 ** (_config2.default.aead_chunk_size_byte + 6) : Infinity, - size: array => array.length - }); - _webStreamTools2.default.pipe(buffer.readable, writable); - const writer = _webStreamTools2.default.getWriter(buffer.writable); - try { - while (true) { - let chunk = (await reader.readBytes(chunkSize + tagLengthIfDecrypting)) || new Uint8Array(); - const finalChunk = chunk.subarray(chunk.length - tagLengthIfDecrypting); - chunk = chunk.subarray(0, chunk.length - tagLengthIfDecrypting); - let cryptedPromise; - let done; - if (!chunkIndex || chunk.length) { - reader.unshift(finalChunk); - cryptedPromise = modeInstance[fn](chunk, mode.getNonce(iv, chunkIndexArray), adataArray); - } else { - // After the last chunk, we either encrypt a final, empty - // data chunk to get the final authentication tag or - // validate that final authentication tag. - adataView.setInt32(13 + 4, cryptedBytes); // Should be setInt64(13, ...) - cryptedPromise = modeInstance[fn](finalChunk, mode.getNonce(iv, chunkIndexArray), adataTagArray); - done = true; - } - cryptedBytes += chunk.length - tagLengthIfDecrypting; - queuedBytes += chunk.length - tagLengthIfDecrypting; - // eslint-disable-next-line no-loop-func - latestPromise = latestPromise.then(() => cryptedPromise).then(async crypted => { - await writer.ready; - await writer.write(crypted); - queuedBytes -= chunk.length; - }).catch(err => writer.abort(err)); - if (done || queuedBytes > writer.desiredSize) { - await latestPromise; // Respect backpressure - } - if (!done) { - adataView.setInt32(5 + 4, ++chunkIndex); // Should be setInt64(5, ...) - } else { - await writer.close(); - break; - } +Point.prototype._getBeta = function _getBeta() { + if (!this.curve.endo) + return; + + var pre = this.precomputed; + if (pre && pre.beta) + return pre.beta; + + var beta = this.curve.point(this.x.redMul(this.curve.endo.beta), this.y); + if (pre) { + var curve = this.curve; + var endoMul = function(p) { + return curve.point(p.x.redMul(curve.endo.beta), p.y); + }; + pre.beta = beta; + beta.precomputed = { + beta: null, + naf: pre.naf && { + wnd: pre.naf.wnd, + points: pre.naf.points.map(endoMul) + }, + doubles: pre.doubles && { + step: pre.doubles.step, + points: pre.doubles.points.map(endoMul) } - } catch (e) { - await writer.abort(e); + }; + } + return beta; +}; + +Point.prototype.toJSON = function toJSON() { + if (!this.precomputed) + return [ this.x, this.y ]; + + return [ this.x, this.y, this.precomputed && { + doubles: this.precomputed.doubles && { + step: this.precomputed.doubles.step, + points: this.precomputed.doubles.points.slice(1) + }, + naf: this.precomputed.naf && { + wnd: this.precomputed.naf.wnd, + points: this.precomputed.naf.points.slice(1) } - }); + } ]; }; -},{"../config":79,"../crypto":94,"../enums":113,"../util":152,"web-stream-tools":75}],138:[function(require,module,exports){ -'use strict'; +Point.fromJSON = function fromJSON(curve, obj, red) { + if (typeof obj === 'string') + obj = JSON.parse(obj); + var res = curve.point(obj[0], obj[1], red); + if (!obj[2]) + return res; -Object.defineProperty(exports, "__esModule", { - value: true -}); + function obj2point(obj) { + return curve.point(obj[0], obj[1], red); + } -var _webStreamTools = require('web-stream-tools'); + var pre = obj[2]; + res.precomputed = { + beta: null, + doubles: pre.doubles && { + step: pre.doubles.step, + points: [ res ].concat(pre.doubles.points.map(obj2point)) + }, + naf: pre.naf && { + wnd: pre.naf.wnd, + points: [ res ].concat(pre.naf.points.map(obj2point)) + } + }; + return res; +}; -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); +Point.prototype.inspect = function inspect() { + if (this.isInfinity()) + return ''; + return ''; +}; -var _config = require('../config'); +Point.prototype.isInfinity = function isInfinity() { + return this.inf; +}; -var _config2 = _interopRequireDefault(_config); +Point.prototype.add = function add(p) { + // O + P = P + if (this.inf) + return p; -var _crypto = require('../crypto'); + // P + O = P + if (p.inf) + return this; -var _crypto2 = _interopRequireDefault(_crypto); + // P + P = 2P + if (this.eq(p)) + return this.dbl(); -var _enums = require('../enums'); + // P + (-P) = O + if (this.neg().eq(p)) + return this.curve.point(null, null); -var _enums2 = _interopRequireDefault(_enums); + // P + Q = O + if (this.x.cmp(p.x) === 0) + return this.curve.point(null, null); -var _util = require('../util'); + var c = this.y.redSub(p.y); + if (c.cmpn(0) !== 0) + c = c.redMul(this.x.redSub(p.x).redInvm()); + var nx = c.redSqr().redISub(this.x).redISub(p.x); + var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); + return this.curve.point(nx, ny); +}; -var _util2 = _interopRequireDefault(_util); +Point.prototype.dbl = function dbl() { + if (this.inf) + return this; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + // 2P = O + var ys1 = this.y.redAdd(this.y); + if (ys1.cmpn(0) === 0) + return this.curve.point(null, null); -const VERSION = 1; // A one-octet version number of the data packet. + var a = this.curve.a; -/** - * Implementation of the Sym. Encrypted Integrity Protected Data Packet (Tag 18) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.13|RFC4880 5.13}: - * The Symmetrically Encrypted Integrity Protected Data packet is - * a variant of the Symmetrically Encrypted Data packet. It is a new feature - * created for OpenPGP that addresses the problem of detecting a modification to - * encrypted data. It is used in combination with a Modification Detection Code - * packet. - * @memberof module:packet - * @constructor - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + var x2 = this.x.redSqr(); + var dyinv = ys1.redInvm(); + var c = x2.redAdd(x2).redIAdd(x2).redIAdd(a).redMul(dyinv); -/** - * @requires asmcrypto.js - * @requires web-stream-tools - * @requires config - * @requires crypto - * @requires enums - * @requires util - */ + var nx = c.redSqr().redISub(this.x.redAdd(this.x)); + var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); + return this.curve.point(nx, ny); +}; -function SymEncryptedIntegrityProtected() { - this.tag = _enums2.default.packet.symEncryptedIntegrityProtected; - this.version = VERSION; - /** The encrypted payload. */ - this.encrypted = null; // string - /** - * If after decrypting the packet this is set to true, - * a modification has been detected and thus the contents - * should be discarded. - * @type {Boolean} - */ - this.modification = false; - this.packets = null; -} +Point.prototype.getX = function getX() { + return this.x.fromRed(); +}; -SymEncryptedIntegrityProtected.prototype.read = async function (bytes) { - await _webStreamTools2.default.parse(bytes, async reader => { +Point.prototype.getY = function getY() { + return this.y.fromRed(); +}; - // - A one-octet version number. The only currently defined value is 1. - if ((await reader.readByte()) !== VERSION) { - throw new Error('Invalid packet version.'); - } +Point.prototype.mul = function mul(k) { + k = new bn(k, 16); + if (this.isInfinity()) + return this; + else if (this._hasDoubles(k)) + return this.curve._fixedNafMul(this, k); + else if (this.curve.endo) + return this.curve._endoWnafMulAdd([ this ], [ k ]); + else + return this.curve._wnafMul(this, k); +}; - // - Encrypted data, the output of the selected symmetric-key cipher - // operating in Cipher Feedback mode with shift amount equal to the - // block size of the cipher (CFB-n where n is the block size). - this.encrypted = reader.remainder(); - }); +Point.prototype.mulAdd = function mulAdd(k1, p2, k2) { + var points = [ this, p2 ]; + var coeffs = [ k1, k2 ]; + if (this.curve.endo) + return this.curve._endoWnafMulAdd(points, coeffs); + else + return this.curve._wnafMulAdd(1, points, coeffs, 2); }; -SymEncryptedIntegrityProtected.prototype.write = function () { - return _util2.default.concat([new Uint8Array([VERSION]), this.encrypted]); +Point.prototype.jmulAdd = function jmulAdd(k1, p2, k2) { + var points = [ this, p2 ]; + var coeffs = [ k1, k2 ]; + if (this.curve.endo) + return this.curve._endoWnafMulAdd(points, coeffs, true); + else + return this.curve._wnafMulAdd(1, points, coeffs, 2, true); }; -/** - * Encrypt the payload in the packet. - * @param {String} sessionKeyAlgorithm The selected symmetric encryption algorithm to be used e.g. 'aes128' - * @param {Uint8Array} key The key of cipher blocksize length to be used - * @param {Boolean} streaming Whether to set this.encrypted to a stream - * @returns {Promise} - * @async - */ -SymEncryptedIntegrityProtected.prototype.encrypt = async function (sessionKeyAlgorithm, key, streaming) { - let bytes = this.packets.write(); - if (!streaming) bytes = await _webStreamTools2.default.readToEnd(bytes); - const prefix = await _crypto2.default.getPrefixRandom(sessionKeyAlgorithm); - const mdc = new Uint8Array([0xD3, 0x14]); // modification detection code packet - - const tohash = _util2.default.concat([prefix, bytes, mdc]); - const hash = await _crypto2.default.hash.sha1(_webStreamTools2.default.passiveClone(tohash)); - const plaintext = _util2.default.concat([tohash, hash]); - - this.encrypted = await _crypto2.default.cfb.encrypt(sessionKeyAlgorithm, key, plaintext, new Uint8Array(_crypto2.default.cipher[sessionKeyAlgorithm].blockSize)); - return true; +Point.prototype.eq = function eq(p) { + return this === p || + this.inf === p.inf && + (this.inf || this.x.cmp(p.x) === 0 && this.y.cmp(p.y) === 0); }; -/** - * Decrypts the encrypted data contained in the packet. - * @param {String} sessionKeyAlgorithm The selected symmetric encryption algorithm to be used e.g. 'aes128' - * @param {Uint8Array} key The key of cipher blocksize length to be used - * @param {Boolean} streaming Whether to read this.encrypted as a stream - * @returns {Promise} - * @async - */ -SymEncryptedIntegrityProtected.prototype.decrypt = async function (sessionKeyAlgorithm, key, streaming) { - let encrypted = _webStreamTools2.default.clone(this.encrypted); - if (!streaming) encrypted = await _webStreamTools2.default.readToEnd(encrypted); - const decrypted = await _crypto2.default.cfb.decrypt(sessionKeyAlgorithm, key, encrypted, new Uint8Array(_crypto2.default.cipher[sessionKeyAlgorithm].blockSize)); +Point.prototype.neg = function neg(_precompute) { + if (this.inf) + return this; - // there must be a modification detection code packet as the - // last packet and everything gets hashed except the hash itself - const realHash = _webStreamTools2.default.slice(_webStreamTools2.default.passiveClone(decrypted), -20); - const tohash = _webStreamTools2.default.slice(decrypted, 0, -20); - const verifyHash = Promise.all([_webStreamTools2.default.readToEnd((await _crypto2.default.hash.sha1(_webStreamTools2.default.passiveClone(tohash)))), _webStreamTools2.default.readToEnd(realHash)]).then(([hash, mdc]) => { - if (!_util2.default.equalsUint8Array(hash, mdc)) { - throw new Error('Modification detected.'); - } - return new Uint8Array(); - }); - const bytes = _webStreamTools2.default.slice(tohash, _crypto2.default.cipher[sessionKeyAlgorithm].blockSize + 2); // Remove random prefix - let packetbytes = _webStreamTools2.default.slice(bytes, 0, -2); // Remove MDC packet - packetbytes = _webStreamTools2.default.concat([packetbytes, _webStreamTools2.default.fromAsync(() => verifyHash)]); - if (!_util2.default.isStream(encrypted) || !_config2.default.allow_unauthenticated_stream) { - packetbytes = await _webStreamTools2.default.readToEnd(packetbytes); + var res = this.curve.point(this.x, this.y.redNeg()); + if (_precompute && this.precomputed) { + var pre = this.precomputed; + var negate = function(p) { + return p.neg(); + }; + res.precomputed = { + naf: pre.naf && { + wnd: pre.naf.wnd, + points: pre.naf.points.map(negate) + }, + doubles: pre.doubles && { + step: pre.doubles.step, + points: pre.doubles.points.map(negate) + } + }; } - await this.packets.read(packetbytes, streaming); - return true; + return res; }; -exports.default = SymEncryptedIntegrityProtected; - -},{"../config":79,"../crypto":94,"../enums":113,"../util":152,"web-stream-tools":75}],139:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _s2k = require('../type/s2k'); - -var _s2k2 = _interopRequireDefault(_s2k); - -var _config = require('../config'); - -var _config2 = _interopRequireDefault(_config); - -var _crypto = require('../crypto'); - -var _crypto2 = _interopRequireDefault(_crypto); - -var _enums = require('../enums'); - -var _enums2 = _interopRequireDefault(_enums); - -var _util = require('../util'); +Point.prototype.toJ = function toJ() { + if (this.inf) + return this.curve.jpoint(null, null, null); -var _util2 = _interopRequireDefault(_util); + var res = this.curve.jpoint(this.x, this.y, this.curve.one); + return res; +}; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +function JPoint(curve, x, y, z) { + base.BasePoint.call(this, curve, 'jacobian'); + if (x === null && y === null && z === null) { + this.x = this.curve.one; + this.y = this.curve.one; + this.z = new bn(0); + } else { + this.x = new bn(x, 16); + this.y = new bn(y, 16); + this.z = new bn(z, 16); + } + if (!this.x.red) + this.x = this.x.toRed(this.curve.red); + if (!this.y.red) + this.y = this.y.toRed(this.curve.red); + if (!this.z.red) + this.z = this.z.toRed(this.curve.red); -/** - * Public-Key Encrypted Session Key Packets (Tag 1) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.1|RFC4880 5.1}: - * A Public-Key Encrypted Session Key packet holds the session key - * used to encrypt a message. Zero or more Public-Key Encrypted Session Key - * packets and/or Symmetric-Key Encrypted Session Key packets may precede a - * Symmetrically Encrypted Data Packet, which holds an encrypted message. The - * message is encrypted with the session key, and the session key is itself - * encrypted and stored in the Encrypted Session Key packet(s). The - * Symmetrically Encrypted Data Packet is preceded by one Public-Key Encrypted - * Session Key packet for each OpenPGP key to which the message is encrypted. - * The recipient of the message finds a session key that is encrypted to their - * public key, decrypts the session key, and then uses the session key to - * decrypt the message. - * @memberof module:packet - * @constructor - */ -function SymEncryptedSessionKey() { - this.tag = _enums2.default.packet.symEncryptedSessionKey; - this.version = _config2.default.aead_protect ? 5 : 4; - this.sessionKey = null; - this.sessionKeyEncryptionAlgorithm = null; - this.sessionKeyAlgorithm = 'aes256'; - this.aeadAlgorithm = _enums2.default.read(_enums2.default.aead, _config2.default.aead_mode); - this.encrypted = null; - this.s2k = null; - this.iv = null; + this.zOne = this.z === this.curve.one; } +inherits(JPoint, base.BasePoint); -/** - * Parsing function for a symmetric encrypted session key packet (tag 3). - * - * @param {Uint8Array} input Payload of a tag 1 packet - * @param {Integer} position Position to start reading from the input string - * @param {Integer} len - * Length of the packet or the remaining length of - * input at position - * @returns {module:packet.SymEncryptedSessionKey} Object representation - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @requires type/s2k - * @requires config - * @requires crypto - * @requires enums - * @requires util - */ +ShortCurve.prototype.jpoint = function jpoint(x, y, z) { + return new JPoint(this, x, y, z); +}; -SymEncryptedSessionKey.prototype.read = function (bytes) { - let offset = 0; +JPoint.prototype.toP = function toP() { + if (this.isInfinity()) + return this.curve.point(null, null); - // A one-octet version number. The only currently defined version is 4. - this.version = bytes[offset++]; + var zinv = this.z.redInvm(); + var zinv2 = zinv.redSqr(); + var ax = this.x.redMul(zinv2); + var ay = this.y.redMul(zinv2).redMul(zinv); - // A one-octet number describing the symmetric algorithm used. - const algo = _enums2.default.read(_enums2.default.symmetric, bytes[offset++]); + return this.curve.point(ax, ay); +}; - if (this.version === 5) { - // A one-octet AEAD algorithm. - this.aeadAlgorithm = _enums2.default.read(_enums2.default.aead, bytes[offset++]); - } +JPoint.prototype.neg = function neg() { + return this.curve.jpoint(this.x, this.y.redNeg(), this.z); +}; - // A string-to-key (S2K) specifier, length as defined above. - this.s2k = new _s2k2.default(); - offset += this.s2k.read(bytes.subarray(offset, bytes.length)); +JPoint.prototype.add = function add(p) { + // O + P = P + if (this.isInfinity()) + return p; - if (this.version === 5) { - const mode = _crypto2.default[this.aeadAlgorithm]; + // P + O = P + if (p.isInfinity()) + return this; - // A starting initialization vector of size specified by the AEAD - // algorithm. - this.iv = bytes.subarray(offset, offset += mode.ivLength); - } + // 12M + 4S + 7A + var pz2 = p.z.redSqr(); + var z2 = this.z.redSqr(); + var u1 = this.x.redMul(pz2); + var u2 = p.x.redMul(z2); + var s1 = this.y.redMul(pz2.redMul(p.z)); + var s2 = p.y.redMul(z2.redMul(this.z)); - // The encrypted session key itself, which is decrypted with the - // string-to-key object. This is optional in version 4. - if (this.version === 5 || offset < bytes.length) { - this.encrypted = bytes.subarray(offset, bytes.length); - this.sessionKeyEncryptionAlgorithm = algo; - } else { - this.sessionKeyAlgorithm = algo; + var h = u1.redSub(u2); + var r = s1.redSub(s2); + if (h.cmpn(0) === 0) { + if (r.cmpn(0) !== 0) + return this.curve.jpoint(null, null, null); + else + return this.dbl(); } -}; - -SymEncryptedSessionKey.prototype.write = function () { - const algo = this.encrypted === null ? this.sessionKeyAlgorithm : this.sessionKeyEncryptionAlgorithm; - let bytes; - - if (this.version === 5) { - bytes = _util2.default.concatUint8Array([new Uint8Array([this.version, _enums2.default.write(_enums2.default.symmetric, algo), _enums2.default.write(_enums2.default.aead, this.aeadAlgorithm)]), this.s2k.write(), this.iv, this.encrypted]); - } else { - bytes = _util2.default.concatUint8Array([new Uint8Array([this.version, _enums2.default.write(_enums2.default.symmetric, algo)]), this.s2k.write()]); + var h2 = h.redSqr(); + var h3 = h2.redMul(h); + var v = u1.redMul(h2); - if (this.encrypted !== null) { - bytes = _util2.default.concatUint8Array([bytes, this.encrypted]); - } - } + var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); + var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); + var nz = this.z.redMul(p.z).redMul(h); - return bytes; + return this.curve.jpoint(nx, ny, nz); }; -/** - * Decrypts the session key - * @param {String} passphrase The passphrase in string form - * @returns {Promise} - * @async - */ -SymEncryptedSessionKey.prototype.decrypt = async function (passphrase) { - const algo = this.sessionKeyEncryptionAlgorithm !== null ? this.sessionKeyEncryptionAlgorithm : this.sessionKeyAlgorithm; +JPoint.prototype.mixedAdd = function mixedAdd(p) { + // O + P = P + if (this.isInfinity()) + return p.toJ(); - const length = _crypto2.default.cipher[algo].keySize; - const key = await this.s2k.produce_key(passphrase, length); + // P + O = P + if (p.isInfinity()) + return this; - if (this.version === 5) { - const mode = _crypto2.default[this.aeadAlgorithm]; - const adata = new Uint8Array([0xC0 | this.tag, this.version, _enums2.default.write(_enums2.default.symmetric, this.sessionKeyEncryptionAlgorithm), _enums2.default.write(_enums2.default.aead, this.aeadAlgorithm)]); - const modeInstance = await mode(algo, key); - this.sessionKey = await modeInstance.decrypt(this.encrypted, this.iv, adata); - } else if (this.encrypted !== null) { - const decrypted = await _crypto2.default.cfb.decrypt(algo, key, this.encrypted, new Uint8Array(_crypto2.default.cipher[algo].blockSize)); + // 8M + 3S + 7A + var z2 = this.z.redSqr(); + var u1 = this.x; + var u2 = p.x.redMul(z2); + var s1 = this.y; + var s2 = p.y.redMul(z2).redMul(this.z); - this.sessionKeyAlgorithm = _enums2.default.read(_enums2.default.symmetric, decrypted[0]); - this.sessionKey = decrypted.subarray(1, decrypted.length); - } else { - this.sessionKey = key; + var h = u1.redSub(u2); + var r = s1.redSub(s2); + if (h.cmpn(0) === 0) { + if (r.cmpn(0) !== 0) + return this.curve.jpoint(null, null, null); + else + return this.dbl(); } - return true; -}; - -/** - * Encrypts the session key - * @param {String} passphrase The passphrase in string form - * @returns {Promise} - * @async - */ -SymEncryptedSessionKey.prototype.encrypt = async function (passphrase) { - const algo = this.sessionKeyEncryptionAlgorithm !== null ? this.sessionKeyEncryptionAlgorithm : this.sessionKeyAlgorithm; - - this.sessionKeyEncryptionAlgorithm = algo; + var h2 = h.redSqr(); + var h3 = h2.redMul(h); + var v = u1.redMul(h2); - this.s2k = new _s2k2.default(); - this.s2k.salt = await _crypto2.default.random.getRandomBytes(8); + var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); + var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); + var nz = this.z.redMul(h); - const length = _crypto2.default.cipher[algo].keySize; - const key = await this.s2k.produce_key(passphrase, length); + return this.curve.jpoint(nx, ny, nz); +}; - if (this.sessionKey === null) { - this.sessionKey = await _crypto2.default.generateSessionKey(this.sessionKeyAlgorithm); - } +JPoint.prototype.dblp = function dblp(pow) { + if (pow === 0) + return this; + if (this.isInfinity()) + return this; + if (!pow) + return this.dbl(); - if (this.version === 5) { - const mode = _crypto2.default[this.aeadAlgorithm]; - this.iv = await _crypto2.default.random.getRandomBytes(mode.ivLength); // generate new random IV - const adata = new Uint8Array([0xC0 | this.tag, this.version, _enums2.default.write(_enums2.default.symmetric, this.sessionKeyEncryptionAlgorithm), _enums2.default.write(_enums2.default.aead, this.aeadAlgorithm)]); - const modeInstance = await mode(algo, key); - this.encrypted = await modeInstance.encrypt(this.sessionKey, this.iv, adata); - } else { - const algo_enum = new Uint8Array([_enums2.default.write(_enums2.default.symmetric, this.sessionKeyAlgorithm)]); - const private_key = _util2.default.concatUint8Array([algo_enum, this.sessionKey]); - this.encrypted = await _crypto2.default.cfb.encrypt(algo, key, private_key, new Uint8Array(_crypto2.default.cipher[algo].blockSize)); + if (this.curve.zeroA || this.curve.threeA) { + var r = this; + for (var i = 0; i < pow; i++) + r = r.dbl(); + return r; } - return true; -}; + // 1M + 2S + 1A + N * (4S + 5M + 8A) + // N = 1 => 6M + 6S + 9A + var a = this.curve.a; + var tinv = this.curve.tinv; -/** - * Fix custom types after cloning - */ -SymEncryptedSessionKey.prototype.postCloneTypeFix = function () { - this.s2k = _s2k2.default.fromClone(this.s2k); -}; + var jx = this.x; + var jy = this.y; + var jz = this.z; + var jz4 = jz.redSqr().redSqr(); -exports.default = SymEncryptedSessionKey; + // Reuse results + var jyd = jy.redAdd(jy); + for (var i = 0; i < pow; i++) { + var jx2 = jx.redSqr(); + var jyd2 = jyd.redSqr(); + var jyd4 = jyd2.redSqr(); + var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); -},{"../config":79,"../crypto":94,"../enums":113,"../type/s2k":151,"../util":152}],140:[function(require,module,exports){ -'use strict'; + var t1 = jx.redMul(jyd2); + var nx = c.redSqr().redISub(t1.redAdd(t1)); + var t2 = t1.redISub(nx); + var dny = c.redMul(t2); + dny = dny.redIAdd(dny).redISub(jyd4); + var nz = jyd.redMul(jz); + if (i + 1 < pow) + jz4 = jz4.redMul(jyd4); -Object.defineProperty(exports, "__esModule", { - value: true -}); + jx = nx; + jz = nz; + jyd = dny; + } -var _webStreamTools = require('web-stream-tools'); + return this.curve.jpoint(jx, jyd.redMul(tinv), jz); +}; -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); +JPoint.prototype.dbl = function dbl() { + if (this.isInfinity()) + return this; -var _config = require('../config'); + if (this.curve.zeroA) + return this._zeroDbl(); + else if (this.curve.threeA) + return this._threeDbl(); + else + return this._dbl(); +}; -var _config2 = _interopRequireDefault(_config); +JPoint.prototype._zeroDbl = function _zeroDbl() { + var nx; + var ny; + var nz; + // Z = 1 + if (this.zOne) { + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html + // #doubling-mdbl-2007-bl + // 1M + 5S + 14A -var _crypto = require('../crypto'); + // XX = X1^2 + var xx = this.x.redSqr(); + // YY = Y1^2 + var yy = this.y.redSqr(); + // YYYY = YY^2 + var yyyy = yy.redSqr(); + // S = 2 * ((X1 + YY)^2 - XX - YYYY) + var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); + s = s.redIAdd(s); + // M = 3 * XX + a; a = 0 + var m = xx.redAdd(xx).redIAdd(xx); + // T = M ^ 2 - 2*S + var t = m.redSqr().redISub(s).redISub(s); -var _crypto2 = _interopRequireDefault(_crypto); + // 8 * YYYY + var yyyy8 = yyyy.redIAdd(yyyy); + yyyy8 = yyyy8.redIAdd(yyyy8); + yyyy8 = yyyy8.redIAdd(yyyy8); -var _enums = require('../enums'); + // X3 = T + nx = t; + // Y3 = M * (S - T) - 8 * YYYY + ny = m.redMul(s.redISub(t)).redISub(yyyy8); + // Z3 = 2*Y1 + nz = this.y.redAdd(this.y); + } else { + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html + // #doubling-dbl-2009-l + // 2M + 5S + 13A -var _enums2 = _interopRequireDefault(_enums); + // A = X1^2 + var a = this.x.redSqr(); + // B = Y1^2 + var b = this.y.redSqr(); + // C = B^2 + var c = b.redSqr(); + // D = 2 * ((X1 + B)^2 - A - C) + var d = this.x.redAdd(b).redSqr().redISub(a).redISub(c); + d = d.redIAdd(d); + // E = 3 * A + var e = a.redAdd(a).redIAdd(a); + // F = E^2 + var f = e.redSqr(); -var _util = require('../util'); + // 8 * C + var c8 = c.redIAdd(c); + c8 = c8.redIAdd(c8); + c8 = c8.redIAdd(c8); -var _util2 = _interopRequireDefault(_util); + // X3 = F - 2 * D + nx = f.redISub(d).redISub(d); + // Y3 = E * (D - X3) - 8 * C + ny = e.redMul(d.redISub(nx)).redISub(c8); + // Z3 = 2 * Y1 * Z1 + nz = this.y.redMul(this.z); + nz = nz.redIAdd(nz); + } -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + return this.curve.jpoint(nx, ny, nz); +}; -/** - * Implementation of the Symmetrically Encrypted Data Packet (Tag 9) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.7|RFC4880 5.7}: - * The Symmetrically Encrypted Data packet contains data encrypted with a - * symmetric-key algorithm. When it has been decrypted, it contains other - * packets (usually a literal data packet or compressed data packet, but in - * theory other Symmetrically Encrypted Data packets or sequences of packets - * that form whole OpenPGP messages). - * @memberof module:packet - * @constructor - */ -function SymmetricallyEncrypted() { - /** - * Packet type - * @type {module:enums.packet} - */ - this.tag = _enums2.default.packet.symmetricallyEncrypted; - /** - * Encrypted secret-key data - */ - this.encrypted = null; - /** - * Decrypted packets contained within. - * @type {module:packet.List} - */ - this.packets = null; - /** - * When true, decrypt fails if message is not integrity protected - * @see module:config.ignore_mdc_error - */ - this.ignore_mdc_error = _config2.default.ignore_mdc_error; -} // GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +JPoint.prototype._threeDbl = function _threeDbl() { + var nx; + var ny; + var nz; + // Z = 1 + if (this.zOne) { + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html + // #doubling-mdbl-2007-bl + // 1M + 5S + 15A -/** - * @requires web-stream-tools - * @requires config - * @requires crypto - * @requires enums - * @requires util - */ + // XX = X1^2 + var xx = this.x.redSqr(); + // YY = Y1^2 + var yy = this.y.redSqr(); + // YYYY = YY^2 + var yyyy = yy.redSqr(); + // S = 2 * ((X1 + YY)^2 - XX - YYYY) + var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); + s = s.redIAdd(s); + // M = 3 * XX + a + var m = xx.redAdd(xx).redIAdd(xx).redIAdd(this.curve.a); + // T = M^2 - 2 * S + var t = m.redSqr().redISub(s).redISub(s); + // X3 = T + nx = t; + // Y3 = M * (S - T) - 8 * YYYY + var yyyy8 = yyyy.redIAdd(yyyy); + yyyy8 = yyyy8.redIAdd(yyyy8); + yyyy8 = yyyy8.redIAdd(yyyy8); + ny = m.redMul(s.redISub(t)).redISub(yyyy8); + // Z3 = 2 * Y1 + nz = this.y.redAdd(this.y); + } else { + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b + // 3M + 5S -SymmetricallyEncrypted.prototype.read = function (bytes) { - this.encrypted = bytes; -}; + // delta = Z1^2 + var delta = this.z.redSqr(); + // gamma = Y1^2 + var gamma = this.y.redSqr(); + // beta = X1 * gamma + var beta = this.x.redMul(gamma); + // alpha = 3 * (X1 - delta) * (X1 + delta) + var alpha = this.x.redSub(delta).redMul(this.x.redAdd(delta)); + alpha = alpha.redAdd(alpha).redIAdd(alpha); + // X3 = alpha^2 - 8 * beta + var beta4 = beta.redIAdd(beta); + beta4 = beta4.redIAdd(beta4); + var beta8 = beta4.redAdd(beta4); + nx = alpha.redSqr().redISub(beta8); + // Z3 = (Y1 + Z1)^2 - gamma - delta + nz = this.y.redAdd(this.z).redSqr().redISub(gamma).redISub(delta); + // Y3 = alpha * (4 * beta - X3) - 8 * gamma^2 + var ggamma8 = gamma.redSqr(); + ggamma8 = ggamma8.redIAdd(ggamma8); + ggamma8 = ggamma8.redIAdd(ggamma8); + ggamma8 = ggamma8.redIAdd(ggamma8); + ny = alpha.redMul(beta4.redISub(nx)).redISub(ggamma8); + } -SymmetricallyEncrypted.prototype.write = function () { - return this.encrypted; + return this.curve.jpoint(nx, ny, nz); }; -/** - * Decrypt the symmetrically-encrypted packet data - * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. - * @param {module:enums.symmetric} sessionKeyAlgorithm Symmetric key algorithm to use - * @param {Uint8Array} key The key of cipher blocksize length to be used - * @returns {Promise} - * @async - */ -SymmetricallyEncrypted.prototype.decrypt = async function (sessionKeyAlgorithm, key) { - // If MDC errors are not being ignored, all missing MDC packets in symmetrically encrypted data should throw an error - if (!this.ignore_mdc_error) { - throw new Error('Decryption failed due to missing MDC.'); - } +JPoint.prototype._dbl = function _dbl() { + var a = this.curve.a; - this.encrypted = await _webStreamTools2.default.readToEnd(this.encrypted); - const decrypted = await _crypto2.default.cfb.decrypt(sessionKeyAlgorithm, key, this.encrypted.subarray(_crypto2.default.cipher[sessionKeyAlgorithm].blockSize + 2), this.encrypted.subarray(2, _crypto2.default.cipher[sessionKeyAlgorithm].blockSize + 2)); + // 4M + 6S + 10A + var jx = this.x; + var jy = this.y; + var jz = this.z; + var jz4 = jz.redSqr().redSqr(); - await this.packets.read(decrypted); + var jx2 = jx.redSqr(); + var jy2 = jy.redSqr(); - return true; -}; + var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); -/** - * Encrypt the symmetrically-encrypted packet data - * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. - * @param {module:enums.symmetric} sessionKeyAlgorithm Symmetric key algorithm to use - * @param {Uint8Array} key The key of cipher blocksize length to be used - * @returns {Promise} - * @async - */ -SymmetricallyEncrypted.prototype.encrypt = async function (algo, key) { - const data = this.packets.write(); + var jxd4 = jx.redAdd(jx); + jxd4 = jxd4.redIAdd(jxd4); + var t1 = jxd4.redMul(jy2); + var nx = c.redSqr().redISub(t1.redAdd(t1)); + var t2 = t1.redISub(nx); - const prefix = await _crypto2.default.getPrefixRandom(algo); - const FRE = await _crypto2.default.cfb.encrypt(algo, key, prefix, new Uint8Array(_crypto2.default.cipher[algo].blockSize)); - const ciphertext = await _crypto2.default.cfb.encrypt(algo, key, data, FRE.subarray(2)); - this.encrypted = _util2.default.concat([FRE, ciphertext]); + var jyd8 = jy2.redSqr(); + jyd8 = jyd8.redIAdd(jyd8); + jyd8 = jyd8.redIAdd(jyd8); + jyd8 = jyd8.redIAdd(jyd8); + var ny = c.redMul(t2).redISub(jyd8); + var nz = jy.redAdd(jy).redMul(jz); - return true; + return this.curve.jpoint(nx, ny, nz); }; -exports.default = SymmetricallyEncrypted; +JPoint.prototype.trpl = function trpl() { + if (!this.curve.zeroA) + return this.dbl().add(this); -},{"../config":79,"../crypto":94,"../enums":113,"../util":152,"web-stream-tools":75}],141:[function(require,module,exports){ -'use strict'; + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#tripling-tpl-2007-bl + // 5M + 10S + ... -Object.defineProperty(exports, "__esModule", { - value: true -}); + // XX = X1^2 + var xx = this.x.redSqr(); + // YY = Y1^2 + var yy = this.y.redSqr(); + // ZZ = Z1^2 + var zz = this.z.redSqr(); + // YYYY = YY^2 + var yyyy = yy.redSqr(); + // M = 3 * XX + a * ZZ2; a = 0 + var m = xx.redAdd(xx).redIAdd(xx); + // MM = M^2 + var mm = m.redSqr(); + // E = 6 * ((X1 + YY)^2 - XX - YYYY) - MM + var e = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); + e = e.redIAdd(e); + e = e.redAdd(e).redIAdd(e); + e = e.redISub(mm); + // EE = E^2 + var ee = e.redSqr(); + // T = 16*YYYY + var t = yyyy.redIAdd(yyyy); + t = t.redIAdd(t); + t = t.redIAdd(t); + t = t.redIAdd(t); + // U = (M + E)^2 - MM - EE - T + var u = m.redIAdd(e).redSqr().redISub(mm).redISub(ee).redISub(t); + // X3 = 4 * (X1 * EE - 4 * YY * U) + var yyu4 = yy.redMul(u); + yyu4 = yyu4.redIAdd(yyu4); + yyu4 = yyu4.redIAdd(yyu4); + var nx = this.x.redMul(ee).redISub(yyu4); + nx = nx.redIAdd(nx); + nx = nx.redIAdd(nx); + // Y3 = 8 * Y1 * (U * (T - U) - E * EE) + var ny = this.y.redMul(u.redMul(t.redISub(u)).redISub(e.redMul(ee))); + ny = ny.redIAdd(ny); + ny = ny.redIAdd(ny); + ny = ny.redIAdd(ny); + // Z3 = (Z1 + E)^2 - ZZ - EE + var nz = this.z.redAdd(e).redSqr().redISub(zz).redISub(ee); -var _enums = require('../enums'); + return this.curve.jpoint(nx, ny, nz); +}; -var _enums2 = _interopRequireDefault(_enums); +JPoint.prototype.mul = function mul(k, kbase) { + k = new bn(k, kbase); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + return this.curve._wnafMul(this, k); +}; -/** - * Implementation of the Trust Packet (Tag 12) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.10|RFC4880 5.10}: - * The Trust packet is used only within keyrings and is not normally - * exported. Trust packets contain data that record the user's - * specifications of which key holders are trustworthy introducers, - * along with other information that implementing software uses for - * trust information. The format of Trust packets is defined by a given - * implementation. - * - * Trust packets SHOULD NOT be emitted to output streams that are - * transferred to other users, and they SHOULD be ignored on any input - * other than local keyring files. - * @memberof module:packet - * @constructor - */ -function Trust() { - this.tag = _enums2.default.packet.trust; -} +JPoint.prototype.eq = function eq(p) { + if (p.type === 'affine') + return this.eq(p.toJ()); -/** - * Parsing function for a trust packet (tag 12). - * Currently not implemented as we ignore trust packets - * @param {String} byptes payload of a tag 12 packet - */ -/** - * @requires enums - */ + if (this === p) + return true; -Trust.prototype.read = function () {}; // TODO + // x1 * z2^2 == x2 * z1^2 + var z2 = this.z.redSqr(); + var pz2 = p.z.redSqr(); + if (this.x.redMul(pz2).redISub(p.x.redMul(z2)).cmpn(0) !== 0) + return false; -exports.default = Trust; + // y1 * z2^3 == y2 * z1^3 + var z3 = z2.redMul(this.z); + var pz3 = pz2.redMul(p.z); + return this.y.redMul(pz3).redISub(p.y.redMul(z3)).cmpn(0) === 0; +}; -},{"../enums":113}],142:[function(require,module,exports){ -'use strict'; +JPoint.prototype.eqXToP = function eqXToP(x) { + var zs = this.z.redSqr(); + var rx = x.toRed(this.curve.red).redMul(zs); + if (this.x.cmp(rx) === 0) + return true; -Object.defineProperty(exports, "__esModule", { - value: true -}); + var xc = x.clone(); + var t = this.curve.redN.redMul(zs); + for (;;) { + xc.iadd(this.curve.n); + if (xc.cmp(this.curve.p) >= 0) + return false; -var _packet = require('./packet'); + rx.redIAdd(t); + if (this.x.cmp(rx) === 0) + return true; + } +}; -var _packet2 = _interopRequireDefault(_packet); +JPoint.prototype.inspect = function inspect() { + if (this.isInfinity()) + return ''; + return ''; +}; -var _enums = require('../enums'); +JPoint.prototype.isInfinity = function isInfinity() { + // XXX This code assumes that zero is always zero in red + return this.z.cmpn(0) === 0; +}; -var _enums2 = _interopRequireDefault(_enums); +function MontCurve(conf) { + base.call(this, 'mont', conf); -var _util = require('../util'); + this.a = new bn(conf.a, 16).toRed(this.red); + this.b = new bn(conf.b, 16).toRed(this.red); + this.i4 = new bn(4).toRed(this.red).redInvm(); + this.two = new bn(2).toRed(this.red); + // Note: this implementation is according to the original paper + // by P. Montgomery, NOT the one by D. J. Bernstein. + this.a24 = this.i4.redMul(this.a.redAdd(this.two)); +} +inherits(MontCurve, base); +var mont = MontCurve; -var _util2 = _interopRequireDefault(_util); +MontCurve.prototype.validate = function validate(point) { + var x = point.normalize().x; + var x2 = x.redSqr(); + var rhs = x2.redMul(x).redAdd(x2.redMul(this.a)).redAdd(x); + var y = rhs.redSqrt(); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + return y.redSqr().cmp(rhs) === 0; +}; -/** - * Implementation of the User Attribute Packet (Tag 17) - * - * The User Attribute packet is a variation of the User ID packet. It - * is capable of storing more types of data than the User ID packet, - * which is limited to text. Like the User ID packet, a User Attribute - * packet may be certified by the key owner ("self-signed") or any other - * key owner who cares to certify it. Except as noted, a User Attribute - * packet may be used anywhere that a User ID packet may be used. - * - * While User Attribute packets are not a required part of the OpenPGP - * standard, implementations SHOULD provide at least enough - * compatibility to properly handle a certification signature on the - * User Attribute packet. A simple way to do this is by treating the - * User Attribute packet as a User ID packet with opaque contents, but - * an implementation may use any method desired. - * @memberof module:packet - * @constructor - */ -function UserAttribute() { - this.tag = _enums2.default.packet.userAttribute; - this.attributes = []; +function Point$1(curve, x, z) { + base.BasePoint.call(this, curve, 'projective'); + if (x === null && z === null) { + this.x = this.curve.one; + this.z = this.curve.zero; + } else { + this.x = new bn(x, 16); + this.z = new bn(z, 16); + if (!this.x.red) + this.x = this.x.toRed(this.curve.red); + if (!this.z.red) + this.z = this.z.toRed(this.curve.red); + } } +inherits(Point$1, base.BasePoint); -/** - * parsing function for a user attribute packet (tag 17). - * @param {Uint8Array} input payload of a tag 17 packet - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +MontCurve.prototype.decodePoint = function decodePoint(bytes, enc) { + var bytes = utils_1$1.toArray(bytes, enc); -/** - * @requires packet - * @requires enums - * @requires util - */ + // TODO Curve448 + // Montgomery curve points must be represented in the compressed format + // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B + if (bytes.length === 33 && bytes[0] === 0x40) + bytes = bytes.slice(1, 33).reverse(); // point must be little-endian + if (bytes.length !== 32) + throw new Error('Unknown point compression format'); + return this.point(bytes, 1); +}; -UserAttribute.prototype.read = function (bytes) { - let i = 0; - while (i < bytes.length) { - const len = _packet2.default.readSimpleLength(bytes.subarray(i, bytes.length)); - i += len.offset; +MontCurve.prototype.point = function point(x, z) { + return new Point$1(this, x, z); +}; - this.attributes.push(_util2.default.Uint8Array_to_str(bytes.subarray(i, i + len.len))); - i += len.len; - } +MontCurve.prototype.pointFromJSON = function pointFromJSON(obj) { + return Point$1.fromJSON(this, obj); }; -/** - * Creates a binary representation of the user attribute packet - * @returns {Uint8Array} string representation - */ -UserAttribute.prototype.write = function () { - const arr = []; - for (let i = 0; i < this.attributes.length; i++) { - arr.push(_packet2.default.writeSimpleLength(this.attributes[i].length)); - arr.push(_util2.default.str_to_Uint8Array(this.attributes[i])); - } - return _util2.default.concatUint8Array(arr); +Point$1.prototype.precompute = function precompute() { + // No-op }; -/** - * Compare for equality - * @param {module:packet.UserAttribute} usrAttr - * @returns {Boolean} true if equal - */ -UserAttribute.prototype.equals = function (usrAttr) { - if (!usrAttr || !(usrAttr instanceof UserAttribute)) { - return false; +Point$1.prototype._encode = function _encode(compact) { + var len = this.curve.p.byteLength(); + + // Note: the output should always be little-endian + // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B + if (compact) { + return [ 0x40 ].concat(this.getX().toArray('le', len)); + } else { + return this.getX().toArray('be', len); } - return this.attributes.every(function (attr, index) { - return attr === usrAttr.attributes[index]; - }); }; -exports.default = UserAttribute; +Point$1.fromJSON = function fromJSON(curve, obj) { + return new Point$1(curve, obj[0], obj[1] || curve.one); +}; -},{"../enums":113,"../util":152,"./packet":129}],143:[function(require,module,exports){ -'use strict'; +Point$1.prototype.inspect = function inspect() { + if (this.isInfinity()) + return ''; + return ''; +}; -Object.defineProperty(exports, "__esModule", { - value: true -}); +Point$1.prototype.isInfinity = function isInfinity() { + // XXX This code assumes that zero is always zero in red + return this.z.cmpn(0) === 0; +}; + +Point$1.prototype.dbl = function dbl() { + // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#doubling-dbl-1987-m-3 + // 2M + 2S + 4A -var _enums = require('../enums'); + // A = X1 + Z1 + var a = this.x.redAdd(this.z); + // AA = A^2 + var aa = a.redSqr(); + // B = X1 - Z1 + var b = this.x.redSub(this.z); + // BB = B^2 + var bb = b.redSqr(); + // C = AA - BB + var c = aa.redSub(bb); + // X3 = AA * BB + var nx = aa.redMul(bb); + // Z3 = C * (BB + A24 * C) + var nz = c.redMul(bb.redAdd(this.curve.a24.redMul(c))); + return this.curve.point(nx, nz); +}; -var _enums2 = _interopRequireDefault(_enums); +Point$1.prototype.add = function add() { + throw new Error('Not supported on Montgomery curve'); +}; -var _util = require('../util'); +Point$1.prototype.diffAdd = function diffAdd(p, diff) { + // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#diffadd-dadd-1987-m-3 + // 4M + 2S + 6A -var _util2 = _interopRequireDefault(_util); + // A = X2 + Z2 + var a = this.x.redAdd(this.z); + // B = X2 - Z2 + var b = this.x.redSub(this.z); + // C = X3 + Z3 + var c = p.x.redAdd(p.z); + // D = X3 - Z3 + var d = p.x.redSub(p.z); + // DA = D * A + var da = d.redMul(a); + // CB = C * B + var cb = c.redMul(b); + // X5 = Z1 * (DA + CB)^2 + var nx = diff.z.redMul(da.redAdd(cb).redSqr()); + // Z5 = X1 * (DA - CB)^2 + var nz = diff.x.redMul(da.redISub(cb).redSqr()); + return this.curve.point(nx, nz); +}; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +Point$1.prototype.mul = function mul(k) { + k = new bn(k, 16); -/** - * Implementation of the User ID Packet (Tag 13) - * - * A User ID packet consists of UTF-8 text that is intended to represent - * the name and email address of the key holder. By convention, it - * includes an RFC 2822 [RFC2822] mail name-addr, but there are no - * restrictions on its content. The packet length in the header - * specifies the length of the User ID. - * @memberof module:packet - * @constructor - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + var t = k.clone(); + var a = this; // (N / 2) * Q + Q + var b = this.curve.point(null, null); // (N / 2) * Q + var c = this; // Q -/** - * @requires enums - * @requires util - */ + for (var bits = []; t.cmpn(0) !== 0; t.iushrn(1)) + bits.push(t.andln(1)); -function Userid() { - this.tag = _enums2.default.packet.userid; - /** A string containing the user id. Usually in the form - * John Doe - * @type {String} - */ - this.userid = ''; + for (var i = bits.length - 1; i >= 0; i--) { + if (bits[i] === 0) { + // N * Q + Q = ((N / 2) * Q + Q)) + (N / 2) * Q + a = a.diffAdd(b, c); + // N * Q = 2 * ((N / 2) * Q + Q)) + b = b.dbl(); + } else { + // N * Q = ((N / 2) * Q + Q) + ((N / 2) * Q) + b = a.diffAdd(b, c); + // N * Q + Q = 2 * ((N / 2) * Q + Q) + a = a.dbl(); + } + } + return b; +}; - this.name = ''; - this.email = ''; - this.comment = ''; -} +Point$1.prototype.mulAdd = function mulAdd() { + throw new Error('Not supported on Montgomery curve'); +}; -/** - * Parsing function for a user id packet (tag 13). - * @param {Uint8Array} input payload of a tag 13 packet - */ -Userid.prototype.read = function (bytes) { - this.parse(_util2.default.decode_utf8(bytes)); +Point$1.prototype.jumlAdd = function jumlAdd() { + throw new Error('Not supported on Montgomery curve'); }; -/** - * Parse userid string, e.g. 'John Doe ' - */ -Userid.prototype.parse = function (userid) { - try { - Object.assign(this, _util2.default.parseUserId(userid)); - } catch (e) {} - this.userid = userid; +Point$1.prototype.eq = function eq(other) { + return this.getX().cmp(other.getX()) === 0; }; -/** - * Creates a binary representation of the user id packet - * @returns {Uint8Array} binary representation - */ -Userid.prototype.write = function () { - return _util2.default.encode_utf8(this.userid); +Point$1.prototype.normalize = function normalize() { + this.x = this.x.redMul(this.z.redInvm()); + this.z = this.curve.one; + return this; }; -/** - * Set userid string from object, e.g. { name:'Phil Zimmermann', email:'phil@openpgp.org' } - */ -Userid.prototype.format = function (userid) { - if (_util2.default.isString(userid)) { - userid = _util2.default.parseUserId(userid); - } - Object.assign(this, userid); - this.userid = _util2.default.formatUserId(userid); +Point$1.prototype.getX = function getX() { + // Normalize coordinates + this.normalize(); + + return this.x.fromRed(); }; -exports.default = Userid; +var assert$4 = utils_1$1.assert; -},{"../enums":113,"../util":152}],144:[function(require,module,exports){ -(function (global){ -'use strict'; +function EdwardsCurve(conf) { + // NOTE: Important as we are creating point in Base.call() + this.twisted = (conf.a | 0) !== 1; + this.mOneA = this.twisted && (conf.a | 0) === -1; + this.extended = this.mOneA; -var _util = require('./util'); + base.call(this, 'edwards', conf); -var _util2 = _interopRequireDefault(_util); + this.a = new bn(conf.a, 16).umod(this.red.m); + this.a = this.a.toRed(this.red); + this.c = new bn(conf.c, 16).toRed(this.red); + this.c2 = this.c.redSqr(); + this.d = new bn(conf.d, 16).toRed(this.red); + this.dd = this.d.redAdd(this.d); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + assert$4(!this.twisted || this.c.fromRed().cmpn(1) === 0); + this.oneC = (conf.c | 0) === 1; +} +inherits(EdwardsCurve, base); +var edwards = EdwardsCurve; -if (typeof window !== 'undefined') { - /******************************************************************** - * NOTE: This list is duplicated in Gruntfile.js, * - * so that these polyfills are only included in the compat bundle. * - ********************************************************************/ +EdwardsCurve.prototype._mulA = function _mulA(num) { + if (this.mOneA) + return num.redNeg(); + else + return this.a.redMul(num); +}; - try { - if (typeof window.fetch === 'undefined') { - require('whatwg-fetch'); - } - if (typeof Array.prototype.fill === 'undefined') { - require('core-js/fn/array/fill'); - } - if (typeof Array.prototype.find === 'undefined') { - require('core-js/fn/array/find'); - } - if (typeof Array.prototype.includes === 'undefined') { - require('core-js/fn/array/includes'); - } - if (typeof Array.from === 'undefined') { - require('core-js/fn/array/from'); - } +EdwardsCurve.prototype._mulC = function _mulC(num) { + if (this.oneC) + return num; + else + return this.c.redMul(num); +}; - // No if-statement on Promise because of IE11. Otherwise Promise is undefined in the service worker. - require('core-js/fn/promise'); +// Just for compatibility with Short curve +EdwardsCurve.prototype.jpoint = function jpoint(x, y, z, t) { + return this.point(x, y, z, t); +}; - if (typeof Uint8Array.from === 'undefined') { - require('core-js/fn/typed/uint8-array'); - } - if (typeof String.prototype.repeat === 'undefined') { - require('core-js/fn/string/repeat'); - } - if (typeof Symbol === 'undefined') { - require('core-js/fn/symbol'); - } - if (typeof Object.assign === 'undefined') { - require('core-js/fn/object/assign'); - } - } catch (e) {} -} /** - * @fileoverview Old browser polyfills - * All are listed as dev dependencies because Node does not need them - * and for browser babel will take care of it - * @requires util - * @module polyfills - */ +EdwardsCurve.prototype.pointFromX = function pointFromX(x, odd) { + x = new bn(x, 16); + if (!x.red) + x = x.toRed(this.red); -if (typeof TransformStream === 'undefined') { - require('@mattiasbuelens/web-streams-polyfill/es6'); -} -if (typeof TextEncoder === 'undefined') { - const nodeUtil = _util2.default.nodeRequire('util') || {}; - global.TextEncoder = nodeUtil.TextEncoder; - global.TextDecoder = nodeUtil.TextDecoder; -} -if (typeof TextEncoder === 'undefined') { - const textEncoding = require('text-encoding-utf-8'); - global.TextEncoder = textEncoding.TextEncoder; - global.TextDecoder = textEncoding.TextDecoder; -} + var x2 = x.redSqr(); + var rhs = this.c2.redSub(this.a.redMul(x2)); + var lhs = this.one.redSub(this.c2.redMul(this.d).redMul(x2)); -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./util":152,"@mattiasbuelens/web-streams-polyfill/es6":1,"core-js/fn/array/fill":"core-js/fn/array/fill","core-js/fn/array/find":"core-js/fn/array/find","core-js/fn/array/from":"core-js/fn/array/from","core-js/fn/array/includes":"core-js/fn/array/includes","core-js/fn/object/assign":"core-js/fn/object/assign","core-js/fn/promise":"core-js/fn/promise","core-js/fn/string/repeat":"core-js/fn/string/repeat","core-js/fn/symbol":"core-js/fn/symbol","core-js/fn/typed/uint8-array":"core-js/fn/typed/uint8-array","text-encoding-utf-8":71,"whatwg-fetch":"whatwg-fetch"}],145:[function(require,module,exports){ -'use strict'; + var y2 = rhs.redMul(lhs.redInvm()); + var y = y2.redSqrt(); + if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) + throw new Error('invalid point'); -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.Signature = Signature; -exports.readArmored = readArmored; -exports.read = read; + var isOdd = y.fromRed().isOdd(); + if (odd && !isOdd || !odd && isOdd) + y = y.redNeg(); -var _armor = require('./encoding/armor'); + return this.point(x, y); +}; -var _armor2 = _interopRequireDefault(_armor); +EdwardsCurve.prototype.pointFromY = function pointFromY(y, odd) { + y = new bn(y, 16); + if (!y.red) + y = y.toRed(this.red); -var _packet = require('./packet'); + // x^2 = (y^2 - c^2) / (c^2 d y^2 - a) + var y2 = y.redSqr(); + var lhs = y2.redSub(this.c2); + var rhs = y2.redMul(this.d).redMul(this.c2).redSub(this.a); + var x2 = lhs.redMul(rhs.redInvm()); -var _packet2 = _interopRequireDefault(_packet); + if (x2.cmp(this.zero) === 0) { + if (odd) + throw new Error('invalid point'); + else + return this.point(this.zero, y); + } -var _enums = require('./enums'); + var x = x2.redSqrt(); + if (x.redSqr().redSub(x2).cmp(this.zero) !== 0) + throw new Error('invalid point'); -var _enums2 = _interopRequireDefault(_enums); + if (x.fromRed().isOdd() !== odd) + x = x.redNeg(); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + return this.point(x, y); +}; -/** - * @class - * @classdesc Class that represents an OpenPGP signature. - * @param {module:packet.List} packetlist The signature packets - */ -function Signature(packetlist) { - if (!(this instanceof Signature)) { - return new Signature(packetlist); - } - this.packets = packetlist || new _packet2.default.List(); -} +EdwardsCurve.prototype.validate = function validate(point) { + if (point.isInfinity()) + return true; -/** - * Returns ASCII armored text of signature - * @returns {ReadableStream} ASCII armor - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + // Curve: A * X^2 + Y^2 = C^2 * (1 + D * X^2 * Y^2) + point.normalize(); -/** - * @requires encoding/armor - * @requires packet - * @requires enums - * @module signature - */ + var x2 = point.x.redSqr(); + var y2 = point.y.redSqr(); + var lhs = x2.redMul(this.a).redAdd(y2); + var rhs = this.c2.redMul(this.one.redAdd(this.d.redMul(x2).redMul(y2))); -Signature.prototype.armor = function () { - return _armor2.default.encode(_enums2.default.armor.signature, this.packets.write()); + return lhs.cmp(rhs) === 0; }; -/** - * reads an OpenPGP armored signature and returns a signature object - * @param {String | ReadableStream} armoredText text to be parsed - * @returns {Signature} new signature object - * @async - * @static - */ -async function readArmored(armoredText) { - const input = await _armor2.default.decode(armoredText); - return read(input.data); -} +function Point$2(curve, x, y, z, t) { + base.BasePoint.call(this, curve, 'projective'); + if (x === null && y === null && z === null) { + this.x = this.curve.zero; + this.y = this.curve.one; + this.z = this.curve.one; + this.t = this.curve.zero; + this.zOne = true; + } else { + this.x = new bn(x, 16); + this.y = new bn(y, 16); + this.z = z ? new bn(z, 16) : this.curve.one; + this.t = t && new bn(t, 16); + if (!this.x.red) + this.x = this.x.toRed(this.curve.red); + if (!this.y.red) + this.y = this.y.toRed(this.curve.red); + if (!this.z.red) + this.z = this.z.toRed(this.curve.red); + if (this.t && !this.t.red) + this.t = this.t.toRed(this.curve.red); + this.zOne = this.z === this.curve.one; -/** - * reads an OpenPGP signature as byte array and returns a signature object - * @param {Uint8Array | ReadableStream} input binary signature - * @returns {Signature} new signature object - * @async - * @static - */ -async function read(input) { - const packetlist = new _packet2.default.List(); - await packetlist.read(input); - return new Signature(packetlist); + // Use extended coordinates + if (this.curve.extended && !this.t) { + this.t = this.x.redMul(this.y); + if (!this.zOne) + this.t = this.t.redMul(this.z.redInvm()); + } + } } +inherits(Point$2, base.BasePoint); -},{"./encoding/armor":111,"./enums":113,"./packet":125}],146:[function(require,module,exports){ -'use strict'; +EdwardsCurve.prototype.pointFromJSON = function pointFromJSON(obj) { + return Point$2.fromJSON(this, obj); +}; -Object.defineProperty(exports, "__esModule", { - value: true -}); +EdwardsCurve.prototype.point = function point(x, y, z, t) { + return new Point$2(this, x, y, z, t); +}; -var _util = require('../util'); +Point$2.fromJSON = function fromJSON(curve, obj) { + return new Point$2(curve, obj[0], obj[1], obj[2]); +}; -var _util2 = _interopRequireDefault(_util); +Point$2.prototype.inspect = function inspect() { + if (this.isInfinity()) + return ''; + return ''; +}; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +Point$2.prototype.isInfinity = function isInfinity() { + // XXX This code assumes that zero is always zero in red + return this.x.cmpn(0) === 0 && + (this.y.cmp(this.z) === 0 || + (this.zOne && this.y.cmp(this.curve.c) === 0)); +}; -/** - * @constructor - */ -function ECDHSymmetricKey(data) { - if (typeof data === 'undefined') { - data = new Uint8Array([]); - } else if (_util2.default.isString(data)) { - data = _util2.default.str_to_Uint8Array(data); - } else { - data = new Uint8Array(data); - } - this.data = data; -} +Point$2.prototype._extDbl = function _extDbl() { + // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html + // #doubling-dbl-2008-hwcd + // 4M + 4S -/** - * Read an ECDHSymmetricKey from an Uint8Array - * @param {Uint8Array} input Where to read the encoded symmetric key from - * @returns {Number} Number of read bytes - */ -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2015-2016 Decentral -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + // A = X1^2 + var a = this.x.redSqr(); + // B = Y1^2 + var b = this.y.redSqr(); + // C = 2 * Z1^2 + var c = this.z.redSqr(); + c = c.redIAdd(c); + // D = a * A + var d = this.curve._mulA(a); + // E = (X1 + Y1)^2 - A - B + var e = this.x.redAdd(this.y).redSqr().redISub(a).redISub(b); + // G = D + B + var g = d.redAdd(b); + // F = G - C + var f = g.redSub(c); + // H = D - B + var h = d.redSub(b); + // X3 = E * F + var nx = e.redMul(f); + // Y3 = G * H + var ny = g.redMul(h); + // T3 = E * H + var nt = e.redMul(h); + // Z3 = F * G + var nz = f.redMul(g); + return this.curve.point(nx, ny, nz, nt); +}; -/** - * Encoded symmetric key for ECDH - * - * @requires util - * @module type/ecdh_symkey - */ +Point$2.prototype._projDbl = function _projDbl() { + // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html + // #doubling-dbl-2008-bbjlp + // #doubling-dbl-2007-bl + // and others + // Generally 3M + 4S or 2M + 4S + + // B = (X1 + Y1)^2 + var b = this.x.redAdd(this.y).redSqr(); + // C = X1^2 + var c = this.x.redSqr(); + // D = Y1^2 + var d = this.y.redSqr(); -ECDHSymmetricKey.prototype.read = function (input) { - if (input.length >= 1) { - const length = input[0]; - if (input.length >= 1 + length) { - this.data = input.subarray(1, 1 + length); - return 1 + this.data.length; + var nx; + var ny; + var nz; + if (this.curve.twisted) { + // E = a * C + var e = this.curve._mulA(c); + // F = E + D + var f = e.redAdd(d); + if (this.zOne) { + // X3 = (B - C - D) * (F - 2) + nx = b.redSub(c).redSub(d).redMul(f.redSub(this.curve.two)); + // Y3 = F * (E - D) + ny = f.redMul(e.redSub(d)); + // Z3 = F^2 - 2 * F + nz = f.redSqr().redSub(f).redSub(f); + } else { + // H = Z1^2 + var h = this.z.redSqr(); + // J = F - 2 * H + var j = f.redSub(h).redISub(h); + // X3 = (B-C-D)*J + nx = b.redSub(c).redISub(d).redMul(j); + // Y3 = F * (E - D) + ny = f.redMul(e.redSub(d)); + // Z3 = F * J + nz = f.redMul(j); } + } else { + // E = C + D + var e = c.redAdd(d); + // H = (c * Z1)^2 + var h = this.curve._mulC(this.z).redSqr(); + // J = E - 2 * H + var j = e.redSub(h).redSub(h); + // X3 = c * (B - E) * J + nx = this.curve._mulC(b.redISub(e)).redMul(j); + // Y3 = c * E * (C - D) + ny = this.curve._mulC(e).redMul(c.redISub(d)); + // Z3 = E * J + nz = e.redMul(j); } - throw new Error('Invalid symmetric key'); + return this.curve.point(nx, ny, nz); }; -/** - * Write an ECDHSymmetricKey as an Uint8Array - * @returns {Uint8Array} An array containing the value - */ -ECDHSymmetricKey.prototype.write = function () { - return _util2.default.concatUint8Array([new Uint8Array([this.data.length]), this.data]); -}; +Point$2.prototype.dbl = function dbl() { + if (this.isInfinity()) + return this; -ECDHSymmetricKey.fromClone = function (clone) { - return new ECDHSymmetricKey(clone.data); + // Double in extended coordinates + if (this.curve.extended) + return this._extDbl(); + else + return this._projDbl(); }; -exports.default = ECDHSymmetricKey; - -},{"../util":152}],147:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _enums = require('../enums.js'); +Point$2.prototype._extAdd = function _extAdd(p) { + // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html + // #addition-add-2008-hwcd-3 + // 8M -var _enums2 = _interopRequireDefault(_enums); + // A = (Y1 - X1) * (Y2 - X2) + var a = this.y.redSub(this.x).redMul(p.y.redSub(p.x)); + // B = (Y1 + X1) * (Y2 + X2) + var b = this.y.redAdd(this.x).redMul(p.y.redAdd(p.x)); + // C = T1 * k * T2 + var c = this.t.redMul(this.curve.dd).redMul(p.t); + // D = Z1 * 2 * Z2 + var d = this.z.redMul(p.z.redAdd(p.z)); + // E = B - A + var e = b.redSub(a); + // F = D - C + var f = d.redSub(c); + // G = D + C + var g = d.redAdd(c); + // H = B + A + var h = b.redAdd(a); + // X3 = E * F + var nx = e.redMul(f); + // Y3 = G * H + var ny = g.redMul(h); + // T3 = E * H + var nt = e.redMul(h); + // Z3 = F * G + var nz = f.redMul(g); + return this.curve.point(nx, ny, nz, nt); +}; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +Point$2.prototype._projAdd = function _projAdd(p) { + // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html + // #addition-add-2008-bbjlp + // #addition-add-2007-bl + // 10M + 1S -/** - * @constructor - * @param {enums.hash} hash Hash algorithm - * @param {enums.symmetric} cipher Symmetric algorithm - */ -function KDFParams(data) { - if (data && data.length === 2) { - this.hash = data[0]; - this.cipher = data[1]; + // A = Z1 * Z2 + var a = this.z.redMul(p.z); + // B = A^2 + var b = a.redSqr(); + // C = X1 * X2 + var c = this.x.redMul(p.x); + // D = Y1 * Y2 + var d = this.y.redMul(p.y); + // E = d * C * D + var e = this.curve.d.redMul(c).redMul(d); + // F = B - E + var f = b.redSub(e); + // G = B + E + var g = b.redAdd(e); + // X3 = A * F * ((X1 + Y1) * (X2 + Y2) - C - D) + var tmp = this.x.redAdd(this.y).redMul(p.x.redAdd(p.y)).redISub(c).redISub(d); + var nx = a.redMul(f).redMul(tmp); + var ny; + var nz; + if (this.curve.twisted) { + // Y3 = A * G * (D - a * C) + ny = a.redMul(g).redMul(d.redSub(this.curve._mulA(c))); + // Z3 = F * G + nz = f.redMul(g); } else { - this.hash = _enums2.default.hash.sha1; - this.cipher = _enums2.default.symmetric.aes128; + // Y3 = A * G * (D - C) + ny = a.redMul(g).redMul(d.redSub(c)); + // Z3 = c * F * G + nz = this.curve._mulC(f).redMul(g); } -} - -/** - * Read KDFParams from an Uint8Array - * @param {Uint8Array} input Where to read the KDFParams from - * @returns {Number} Number of read bytes - */ -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2015-2016 Decentral -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + return this.curve.point(nx, ny, nz); +}; -/** - * Implementation of type KDF parameters - * - * {@link https://tools.ietf.org/html/rfc6637#section-7|RFC 6637 7}: - * A key derivation function (KDF) is necessary to implement the EC - * encryption. The Concatenation Key Derivation Function (Approved - * Alternative 1) [NIST-SP800-56A] with the KDF hash function that is - * SHA2-256 [FIPS-180-3] or stronger is REQUIRED. - * @requires enums - * @module type/kdf_params - */ +Point$2.prototype.add = function add(p) { + if (this.isInfinity()) + return p; + if (p.isInfinity()) + return this; -KDFParams.prototype.read = function (input) { - if (input.length < 4 || input[0] !== 3 || input[1] !== 1) { - throw new Error('Cannot read KDFParams'); - } - this.hash = input[2]; - this.cipher = input[3]; - return 4; + if (this.curve.extended) + return this._extAdd(p); + else + return this._projAdd(p); }; -/** - * Write KDFParams to an Uint8Array - * @returns {Uint8Array} Array with the KDFParams value - */ -KDFParams.prototype.write = function () { - return new Uint8Array([3, 1, this.hash, this.cipher]); +Point$2.prototype.mul = function mul(k) { + if (this._hasDoubles(k)) + return this.curve._fixedNafMul(this, k); + else + return this.curve._wnafMul(this, k); }; -KDFParams.fromClone = function (clone) { - return new KDFParams([clone.hash, clone.cipher]); +Point$2.prototype.mulAdd = function mulAdd(k1, p, k2) { + return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, false); }; -exports.default = KDFParams; +Point$2.prototype.jmulAdd = function jmulAdd(k1, p, k2) { + return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, true); +}; -},{"../enums.js":113}],148:[function(require,module,exports){ -'use strict'; +Point$2.prototype.normalize = function normalize() { + if (this.zOne) + return this; -Object.defineProperty(exports, "__esModule", { - value: true -}); + // Normalize coordinates + var zi = this.z.redInvm(); + this.x = this.x.redMul(zi); + this.y = this.y.redMul(zi); + if (this.t) + this.t = this.t.redMul(zi); + this.z = this.curve.one; + this.zOne = true; + return this; +}; -var _util = require('../util.js'); +Point$2.prototype.neg = function neg() { + return this.curve.point(this.x.redNeg(), + this.y, + this.z, + this.t && this.t.redNeg()); +}; -var _util2 = _interopRequireDefault(_util); +Point$2.prototype.getX = function getX() { + this.normalize(); + return this.x.fromRed(); +}; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +Point$2.prototype.getY = function getY() { + this.normalize(); + return this.y.fromRed(); +}; -/** - * @constructor - */ -function Keyid() { - this.bytes = ''; -} +Point$2.prototype.eq = function eq(other) { + return this === other || + this.getX().cmp(other.getX()) === 0 && + this.getY().cmp(other.getY()) === 0; +}; -/** - * Parsing method for a key id - * @param {Uint8Array} input Input to read the key id from - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +Point$2.prototype.eqXToP = function eqXToP(x) { + var rx = x.toRed(this.curve.red).redMul(this.z); + if (this.x.cmp(rx) === 0) + return true; -/** - * Implementation of type key id - * - * {@link https://tools.ietf.org/html/rfc4880#section-3.3|RFC4880 3.3}: - * A Key ID is an eight-octet scalar that identifies a key. - * Implementations SHOULD NOT assume that Key IDs are unique. The - * section "Enhanced Key Formats" below describes how Key IDs are - * formed. - * @requires util - * @module type/keyid - */ + var xc = x.clone(); + var t = this.curve.redN.redMul(this.z); + for (;;) { + xc.iadd(this.curve.n); + if (xc.cmp(this.curve.p) >= 0) + return false; -Keyid.prototype.read = function (bytes) { - this.bytes = _util2.default.Uint8Array_to_str(bytes.subarray(0, 8)); + rx.redIAdd(t); + if (this.x.cmp(rx) === 0) + return true; + } }; -Keyid.prototype.write = function () { - return _util2.default.str_to_Uint8Array(this.bytes); -}; +// Compatibility with BaseCurve +Point$2.prototype.toP = Point$2.prototype.normalize; +Point$2.prototype.mixedAdd = Point$2.prototype.add; -Keyid.prototype.toHex = function () { - return _util2.default.str_to_hex(this.bytes); -}; +var curve_1 = createCommonjsModule(function (module, exports) { -/** - * Checks equality of Key ID's - * @param {Keyid} keyid - * @param {Boolean} matchWildcard Indicates whether to check if either keyid is a wildcard - */ -Keyid.prototype.equals = function (keyid, matchWildcard = false) { - return matchWildcard && (keyid.isWildcard() || this.isWildcard()) || this.bytes === keyid.bytes; -}; +var curve = exports; -Keyid.prototype.isNull = function () { - return this.bytes === ''; -}; +curve.base = base; +curve.short = short_1; +curve.mont = mont; +curve.edwards = edwards; +}); -Keyid.prototype.isWildcard = function () { - return (/^0+$/.test(this.toHex()) - ); -}; +var rotl32$2 = utils.rotl32; +var sum32$3 = utils.sum32; +var sum32_5$2 = utils.sum32_5; +var ft_1$1 = common$1.ft_1; +var BlockHash$4 = common.BlockHash; + +var sha1_K = [ + 0x5A827999, 0x6ED9EBA1, + 0x8F1BBCDC, 0xCA62C1D6 +]; + +function SHA1() { + if (!(this instanceof SHA1)) + return new SHA1(); -Keyid.mapToHex = function (keyId) { - return keyId.toHex(); -}; + BlockHash$4.call(this); + this.h = [ + 0x67452301, 0xefcdab89, 0x98badcfe, + 0x10325476, 0xc3d2e1f0 ]; + this.W = new Array(80); +} -Keyid.fromClone = function (clone) { - const keyid = new Keyid(); - keyid.bytes = clone.bytes; - return keyid; -}; +utils.inherits(SHA1, BlockHash$4); +var _1 = SHA1; -Keyid.fromId = function (hex) { - const keyid = new Keyid(); - keyid.read(_util2.default.hex_to_Uint8Array(hex)); - return keyid; -}; +SHA1.blockSize = 512; +SHA1.outSize = 160; +SHA1.hmacStrength = 80; +SHA1.padLength = 64; -Keyid.wildcard = function () { - const keyid = new Keyid(); - keyid.read(new Uint8Array(8)); - return keyid; -}; +SHA1.prototype._update = function _update(msg, start) { + var W = this.W; -exports.default = Keyid; + for (var i = 0; i < 16; i++) + W[i] = msg[start + i]; -},{"../util.js":152}],149:[function(require,module,exports){ -'use strict'; + for(; i < W.length; i++) + W[i] = rotl32$2(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1); -Object.defineProperty(exports, "__esModule", { - value: true -}); + var a = this.h[0]; + var b = this.h[1]; + var c = this.h[2]; + var d = this.h[3]; + var e = this.h[4]; -var _bn = require('bn.js'); + for (i = 0; i < W.length; i++) { + var s = ~~(i / 20); + var t = sum32_5$2(rotl32$2(a, 5), ft_1$1(s, b, c, d), e, W[i], sha1_K[s]); + e = d; + d = c; + c = rotl32$2(b, 30); + b = a; + a = t; + } -var _bn2 = _interopRequireDefault(_bn); + this.h[0] = sum32$3(this.h[0], a); + this.h[1] = sum32$3(this.h[1], b); + this.h[2] = sum32$3(this.h[2], c); + this.h[3] = sum32$3(this.h[3], d); + this.h[4] = sum32$3(this.h[4], e); +}; -var _util = require('../util'); +SHA1.prototype._digest = function digest(enc) { + if (enc === 'hex') + return utils.toHex32(this.h, 'big'); + else + return utils.split32(this.h, 'big'); +}; -var _util2 = _interopRequireDefault(_util); +var sha1 = _1; +var sha224 = _224; +var sha256 = _256; +var sha384 = _384; +var sha512 = _512; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +var sha = { + sha1: sha1, + sha224: sha224, + sha256: sha256, + sha384: sha384, + sha512: sha512 +}; -/** - * @constructor - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +function Hmac(hash, key, enc) { + if (!(this instanceof Hmac)) + return new Hmac(hash, key, enc); + this.Hash = hash; + this.blockSize = hash.blockSize / 8; + this.outSize = hash.outSize / 8; + this.inner = null; + this.outer = null; -// Hint: We hold our MPIs as an array of octets in big endian format preceding a two -// octet scalar: MPI: [a,b,c,d,e,f] -// - MPI size: (a << 8) | b -// - MPI = c | d << 8 | e << ((MPI.length -2)*8) | f ((MPI.length -2)*8) - -/** - * Implementation of type MPI ({@link https://tools.ietf.org/html/rfc4880#section-3.2|RFC4880 3.2}) - * Multiprecision integers (also called MPIs) are unsigned integers used - * to hold large integers such as the ones used in cryptographic - * calculations. - * An MPI consists of two pieces: a two-octet scalar that is the length - * of the MPI in bits followed by a string of octets that contain the - * actual integer. - * @requires bn.js - * @requires util - * @module type/mpi - */ - -function MPI(data) { - /** An implementation dependent integer */ - if (data instanceof MPI) { - this.data = data.data; - } else if (_bn2.default.isBN(data)) { - this.fromBN(data); - } else if (_util2.default.isUint8Array(data)) { - this.fromUint8Array(data); - } else if (_util2.default.isString(data)) { - this.fromString(data); - } else { - this.data = null; - } + this._init(utils.toArray(key, enc)); } +var hmac = Hmac; -/** - * Parsing function for a MPI ({@link https://tools.ietf.org/html/rfc4880#section-3.2|RFC 4880 3.2}). - * @param {Uint8Array} input Payload of MPI data - * @param {String} endian Endianness of the data; 'be' for big-endian or 'le' for little-endian - * @returns {Integer} Length of data read - */ -MPI.prototype.read = function (bytes, endian = 'be') { - if (_util2.default.isString(bytes)) { - bytes = _util2.default.str_to_Uint8Array(bytes); - } - - const bits = bytes[0] << 8 | bytes[1]; - const bytelen = bits + 7 >>> 3; - const payload = bytes.subarray(2, 2 + bytelen); +Hmac.prototype._init = function init(key) { + // Shorten key, if needed + if (key.length > this.blockSize) + key = new this.Hash().update(key).digest(); + minimalisticAssert(key.length <= this.blockSize); - this.fromUint8Array(payload, endian); + // Add padding to key + for (var i = key.length; i < this.blockSize; i++) + key.push(0); - return 2 + bytelen; -}; + for (i = 0; i < key.length; i++) + key[i] ^= 0x36; + this.inner = new this.Hash().update(key); -/** - * Converts the mpi object to a bytes as specified in - * {@link https://tools.ietf.org/html/rfc4880#section-3.2|RFC4880 3.2} - * @param {String} endian Endianness of the payload; 'be' for big-endian or 'le' for little-endian - * @param {Integer} length Length of the data part of the MPI - * @returns {Uint8Aray} mpi Byte representation - */ -MPI.prototype.write = function (endian, length) { - return _util2.default.Uint8Array_to_MPI(this.toUint8Array(endian, length)); + // 0x36 ^ 0x5c = 0x6a + for (i = 0; i < key.length; i++) + key[i] ^= 0x6a; + this.outer = new this.Hash().update(key); }; -MPI.prototype.bitLength = function () { - return (this.data.length - 1) * 8 + _util2.default.nbits(this.data[0]); +Hmac.prototype.update = function update(msg, enc) { + this.inner.update(msg, enc); + return this; }; -MPI.prototype.byteLength = function () { - return this.data.length; +Hmac.prototype.digest = function digest(enc) { + this.outer.update(this.inner.digest()); + return this.outer.digest(enc); }; -MPI.prototype.toUint8Array = function (endian, length) { - endian = endian || 'be'; - length = length || this.data.length; - - const payload = new Uint8Array(length); - const start = length - this.data.length; - if (start < 0) { - throw new Error('Payload is too large.'); - } - - payload.set(this.data, start); - if (endian === 'le') { - payload.reverse(); - } +var hash_1 = createCommonjsModule(function (module, exports) { +var hash = exports; - return payload; -}; +hash.utils = utils; +hash.common = common; +hash.sha = sha; +hash.ripemd = ripemd; +hash.hmac = hmac; -MPI.prototype.fromUint8Array = function (bytes, endian = 'be') { - this.data = new Uint8Array(bytes.length); - this.data.set(bytes); +// Proxy hash functions to the main object +hash.sha1 = hash.sha.sha1; +hash.sha256 = hash.sha.sha256; +hash.sha224 = hash.sha.sha224; +hash.sha384 = hash.sha.sha384; +hash.sha512 = hash.sha.sha512; +hash.ripemd160 = hash.ripemd.ripemd160; +}); - if (endian === 'le') { - this.data.reverse(); +var secp256k1 = { + doubles: { + step: 4, + points: [ + [ + 'e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a', + 'f7e3507399e595929db99f34f57937101296891e44d23f0be1f32cce69616821' + ], + [ + '8282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508', + '11f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf' + ], + [ + '175e159f728b865a72f99cc6c6fc846de0b93833fd2222ed73fce5b551e5b739', + 'd3506e0d9e3c79eba4ef97a51ff71f5eacb5955add24345c6efa6ffee9fed695' + ], + [ + '363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640', + '4e273adfc732221953b445397f3363145b9a89008199ecb62003c7f3bee9de9' + ], + [ + '8b4b5f165df3c2be8c6244b5b745638843e4a781a15bcd1b69f79a55dffdf80c', + '4aad0a6f68d308b4b3fbd7813ab0da04f9e336546162ee56b3eff0c65fd4fd36' + ], + [ + '723cbaa6e5db996d6bf771c00bd548c7b700dbffa6c0e77bcb6115925232fcda', + '96e867b5595cc498a921137488824d6e2660a0653779494801dc069d9eb39f5f' + ], + [ + 'eebfa4d493bebf98ba5feec812c2d3b50947961237a919839a533eca0e7dd7fa', + '5d9a8ca3970ef0f269ee7edaf178089d9ae4cdc3a711f712ddfd4fdae1de8999' + ], + [ + '100f44da696e71672791d0a09b7bde459f1215a29b3c03bfefd7835b39a48db0', + 'cdd9e13192a00b772ec8f3300c090666b7ff4a18ff5195ac0fbd5cd62bc65a09' + ], + [ + 'e1031be262c7ed1b1dc9227a4a04c017a77f8d4464f3b3852c8acde6e534fd2d', + '9d7061928940405e6bb6a4176597535af292dd419e1ced79a44f18f29456a00d' + ], + [ + 'feea6cae46d55b530ac2839f143bd7ec5cf8b266a41d6af52d5e688d9094696d', + 'e57c6b6c97dce1bab06e4e12bf3ecd5c981c8957cc41442d3155debf18090088' + ], + [ + 'da67a91d91049cdcb367be4be6ffca3cfeed657d808583de33fa978bc1ec6cb1', + '9bacaa35481642bc41f463f7ec9780e5dec7adc508f740a17e9ea8e27a68be1d' + ], + [ + '53904faa0b334cdda6e000935ef22151ec08d0f7bb11069f57545ccc1a37b7c0', + '5bc087d0bc80106d88c9eccac20d3c1c13999981e14434699dcb096b022771c8' + ], + [ + '8e7bcd0bd35983a7719cca7764ca906779b53a043a9b8bcaeff959f43ad86047', + '10b7770b2a3da4b3940310420ca9514579e88e2e47fd68b3ea10047e8460372a' + ], + [ + '385eed34c1cdff21e6d0818689b81bde71a7f4f18397e6690a841e1599c43862', + '283bebc3e8ea23f56701de19e9ebf4576b304eec2086dc8cc0458fe5542e5453' + ], + [ + '6f9d9b803ecf191637c73a4413dfa180fddf84a5947fbc9c606ed86c3fac3a7', + '7c80c68e603059ba69b8e2a30e45c4d47ea4dd2f5c281002d86890603a842160' + ], + [ + '3322d401243c4e2582a2147c104d6ecbf774d163db0f5e5313b7e0e742d0e6bd', + '56e70797e9664ef5bfb019bc4ddaf9b72805f63ea2873af624f3a2e96c28b2a0' + ], + [ + '85672c7d2de0b7da2bd1770d89665868741b3f9af7643397721d74d28134ab83', + '7c481b9b5b43b2eb6374049bfa62c2e5e77f17fcc5298f44c8e3094f790313a6' + ], + [ + '948bf809b1988a46b06c9f1919413b10f9226c60f668832ffd959af60c82a0a', + '53a562856dcb6646dc6b74c5d1c3418c6d4dff08c97cd2bed4cb7f88d8c8e589' + ], + [ + '6260ce7f461801c34f067ce0f02873a8f1b0e44dfc69752accecd819f38fd8e8', + 'bc2da82b6fa5b571a7f09049776a1ef7ecd292238051c198c1a84e95b2b4ae17' + ], + [ + 'e5037de0afc1d8d43d8348414bbf4103043ec8f575bfdc432953cc8d2037fa2d', + '4571534baa94d3b5f9f98d09fb990bddbd5f5b03ec481f10e0e5dc841d755bda' + ], + [ + 'e06372b0f4a207adf5ea905e8f1771b4e7e8dbd1c6a6c5b725866a0ae4fce725', + '7a908974bce18cfe12a27bb2ad5a488cd7484a7787104870b27034f94eee31dd' + ], + [ + '213c7a715cd5d45358d0bbf9dc0ce02204b10bdde2a3f58540ad6908d0559754', + '4b6dad0b5ae462507013ad06245ba190bb4850f5f36a7eeddff2c27534b458f2' + ], + [ + '4e7c272a7af4b34e8dbb9352a5419a87e2838c70adc62cddf0cc3a3b08fbd53c', + '17749c766c9d0b18e16fd09f6def681b530b9614bff7dd33e0b3941817dcaae6' + ], + [ + 'fea74e3dbe778b1b10f238ad61686aa5c76e3db2be43057632427e2840fb27b6', + '6e0568db9b0b13297cf674deccb6af93126b596b973f7b77701d3db7f23cb96f' + ], + [ + '76e64113f677cf0e10a2570d599968d31544e179b760432952c02a4417bdde39', + 'c90ddf8dee4e95cf577066d70681f0d35e2a33d2b56d2032b4b1752d1901ac01' + ], + [ + 'c738c56b03b2abe1e8281baa743f8f9a8f7cc643df26cbee3ab150242bcbb891', + '893fb578951ad2537f718f2eacbfbbbb82314eef7880cfe917e735d9699a84c3' + ], + [ + 'd895626548b65b81e264c7637c972877d1d72e5f3a925014372e9f6588f6c14b', + 'febfaa38f2bc7eae728ec60818c340eb03428d632bb067e179363ed75d7d991f' + ], + [ + 'b8da94032a957518eb0f6433571e8761ceffc73693e84edd49150a564f676e03', + '2804dfa44805a1e4d7c99cc9762808b092cc584d95ff3b511488e4e74efdf6e7' + ], + [ + 'e80fea14441fb33a7d8adab9475d7fab2019effb5156a792f1a11778e3c0df5d', + 'eed1de7f638e00771e89768ca3ca94472d155e80af322ea9fcb4291b6ac9ec78' + ], + [ + 'a301697bdfcd704313ba48e51d567543f2a182031efd6915ddc07bbcc4e16070', + '7370f91cfb67e4f5081809fa25d40f9b1735dbf7c0a11a130c0d1a041e177ea1' + ], + [ + '90ad85b389d6b936463f9d0512678de208cc330b11307fffab7ac63e3fb04ed4', + 'e507a3620a38261affdcbd9427222b839aefabe1582894d991d4d48cb6ef150' + ], + [ + '8f68b9d2f63b5f339239c1ad981f162ee88c5678723ea3351b7b444c9ec4c0da', + '662a9f2dba063986de1d90c2b6be215dbbea2cfe95510bfdf23cbf79501fff82' + ], + [ + 'e4f3fb0176af85d65ff99ff9198c36091f48e86503681e3e6686fd5053231e11', + '1e63633ad0ef4f1c1661a6d0ea02b7286cc7e74ec951d1c9822c38576feb73bc' + ], + [ + '8c00fa9b18ebf331eb961537a45a4266c7034f2f0d4e1d0716fb6eae20eae29e', + 'efa47267fea521a1a9dc343a3736c974c2fadafa81e36c54e7d2a4c66702414b' + ], + [ + 'e7a26ce69dd4829f3e10cec0a9e98ed3143d084f308b92c0997fddfc60cb3e41', + '2a758e300fa7984b471b006a1aafbb18d0a6b2c0420e83e20e8a9421cf2cfd51' + ], + [ + 'b6459e0ee3662ec8d23540c223bcbdc571cbcb967d79424f3cf29eb3de6b80ef', + '67c876d06f3e06de1dadf16e5661db3c4b3ae6d48e35b2ff30bf0b61a71ba45' + ], + [ + 'd68a80c8280bb840793234aa118f06231d6f1fc67e73c5a5deda0f5b496943e8', + 'db8ba9fff4b586d00c4b1f9177b0e28b5b0e7b8f7845295a294c84266b133120' + ], + [ + '324aed7df65c804252dc0270907a30b09612aeb973449cea4095980fc28d3d5d', + '648a365774b61f2ff130c0c35aec1f4f19213b0c7e332843967224af96ab7c84' + ], + [ + '4df9c14919cde61f6d51dfdbe5fee5dceec4143ba8d1ca888e8bd373fd054c96', + '35ec51092d8728050974c23a1d85d4b5d506cdc288490192ebac06cad10d5d' + ], + [ + '9c3919a84a474870faed8a9c1cc66021523489054d7f0308cbfc99c8ac1f98cd', + 'ddb84f0f4a4ddd57584f044bf260e641905326f76c64c8e6be7e5e03d4fc599d' + ], + [ + '6057170b1dd12fdf8de05f281d8e06bb91e1493a8b91d4cc5a21382120a959e5', + '9a1af0b26a6a4807add9a2daf71df262465152bc3ee24c65e899be932385a2a8' + ], + [ + 'a576df8e23a08411421439a4518da31880cef0fba7d4df12b1a6973eecb94266', + '40a6bf20e76640b2c92b97afe58cd82c432e10a7f514d9f3ee8be11ae1b28ec8' + ], + [ + '7778a78c28dec3e30a05fe9629de8c38bb30d1f5cf9a3a208f763889be58ad71', + '34626d9ab5a5b22ff7098e12f2ff580087b38411ff24ac563b513fc1fd9f43ac' + ], + [ + '928955ee637a84463729fd30e7afd2ed5f96274e5ad7e5cb09eda9c06d903ac', + 'c25621003d3f42a827b78a13093a95eeac3d26efa8a8d83fc5180e935bcd091f' + ], + [ + '85d0fef3ec6db109399064f3a0e3b2855645b4a907ad354527aae75163d82751', + '1f03648413a38c0be29d496e582cf5663e8751e96877331582c237a24eb1f962' + ], + [ + 'ff2b0dce97eece97c1c9b6041798b85dfdfb6d8882da20308f5404824526087e', + '493d13fef524ba188af4c4dc54d07936c7b7ed6fb90e2ceb2c951e01f0c29907' + ], + [ + '827fbbe4b1e880ea9ed2b2e6301b212b57f1ee148cd6dd28780e5e2cf856e241', + 'c60f9c923c727b0b71bef2c67d1d12687ff7a63186903166d605b68baec293ec' + ], + [ + 'eaa649f21f51bdbae7be4ae34ce6e5217a58fdce7f47f9aa7f3b58fa2120e2b3', + 'be3279ed5bbbb03ac69a80f89879aa5a01a6b965f13f7e59d47a5305ba5ad93d' + ], + [ + 'e4a42d43c5cf169d9391df6decf42ee541b6d8f0c9a137401e23632dda34d24f', + '4d9f92e716d1c73526fc99ccfb8ad34ce886eedfa8d8e4f13a7f7131deba9414' + ], + [ + '1ec80fef360cbdd954160fadab352b6b92b53576a88fea4947173b9d4300bf19', + 'aeefe93756b5340d2f3a4958a7abbf5e0146e77f6295a07b671cdc1cc107cefd' + ], + [ + '146a778c04670c2f91b00af4680dfa8bce3490717d58ba889ddb5928366642be', + 'b318e0ec3354028add669827f9d4b2870aaa971d2f7e5ed1d0b297483d83efd0' + ], + [ + 'fa50c0f61d22e5f07e3acebb1aa07b128d0012209a28b9776d76a8793180eef9', + '6b84c6922397eba9b72cd2872281a68a5e683293a57a213b38cd8d7d3f4f2811' + ], + [ + 'da1d61d0ca721a11b1a5bf6b7d88e8421a288ab5d5bba5220e53d32b5f067ec2', + '8157f55a7c99306c79c0766161c91e2966a73899d279b48a655fba0f1ad836f1' + ], + [ + 'a8e282ff0c9706907215ff98e8fd416615311de0446f1e062a73b0610d064e13', + '7f97355b8db81c09abfb7f3c5b2515888b679a3e50dd6bd6cef7c73111f4cc0c' + ], + [ + '174a53b9c9a285872d39e56e6913cab15d59b1fa512508c022f382de8319497c', + 'ccc9dc37abfc9c1657b4155f2c47f9e6646b3a1d8cb9854383da13ac079afa73' + ], + [ + '959396981943785c3d3e57edf5018cdbe039e730e4918b3d884fdff09475b7ba', + '2e7e552888c331dd8ba0386a4b9cd6849c653f64c8709385e9b8abf87524f2fd' + ], + [ + 'd2a63a50ae401e56d645a1153b109a8fcca0a43d561fba2dbb51340c9d82b151', + 'e82d86fb6443fcb7565aee58b2948220a70f750af484ca52d4142174dcf89405' + ], + [ + '64587e2335471eb890ee7896d7cfdc866bacbdbd3839317b3436f9b45617e073', + 'd99fcdd5bf6902e2ae96dd6447c299a185b90a39133aeab358299e5e9faf6589' + ], + [ + '8481bde0e4e4d885b3a546d3e549de042f0aa6cea250e7fd358d6c86dd45e458', + '38ee7b8cba5404dd84a25bf39cecb2ca900a79c42b262e556d64b1b59779057e' + ], + [ + '13464a57a78102aa62b6979ae817f4637ffcfed3c4b1ce30bcd6303f6caf666b', + '69be159004614580ef7e433453ccb0ca48f300a81d0942e13f495a907f6ecc27' + ], + [ + 'bc4a9df5b713fe2e9aef430bcc1dc97a0cd9ccede2f28588cada3a0d2d83f366', + 'd3a81ca6e785c06383937adf4b798caa6e8a9fbfa547b16d758d666581f33c1' + ], + [ + '8c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa', + '40a30463a3305193378fedf31f7cc0eb7ae784f0451cb9459e71dc73cbef9482' + ], + [ + '8ea9666139527a8c1dd94ce4f071fd23c8b350c5a4bb33748c4ba111faccae0', + '620efabbc8ee2782e24e7c0cfb95c5d735b783be9cf0f8e955af34a30e62b945' + ], + [ + 'dd3625faef5ba06074669716bbd3788d89bdde815959968092f76cc4eb9a9787', + '7a188fa3520e30d461da2501045731ca941461982883395937f68d00c644a573' + ], + [ + 'f710d79d9eb962297e4f6232b40e8f7feb2bc63814614d692c12de752408221e', + 'ea98e67232d3b3295d3b535532115ccac8612c721851617526ae47a9c77bfc82' + ] + ] + }, + naf: { + wnd: 7, + points: [ + [ + 'f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9', + '388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672' + ], + [ + '2f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4', + 'd8ac222636e5e3d6d4dba9dda6c9c426f788271bab0d6840dca87d3aa6ac62d6' + ], + [ + '5cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc', + '6aebca40ba255960a3178d6d861a54dba813d0b813fde7b5a5082628087264da' + ], + [ + 'acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe', + 'cc338921b0a7d9fd64380971763b61e9add888a4375f8e0f05cc262ac64f9c37' + ], + [ + '774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb', + 'd984a032eb6b5e190243dd56d7b7b365372db1e2dff9d6a8301d74c9c953c61b' + ], + [ + 'f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8', + 'ab0902e8d880a89758212eb65cdaf473a1a06da521fa91f29b5cb52db03ed81' + ], + [ + 'd7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e', + '581e2872a86c72a683842ec228cc6defea40af2bd896d3a5c504dc9ff6a26b58' + ], + [ + 'defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34', + '4211ab0694635168e997b0ead2a93daeced1f4a04a95c0f6cfb199f69e56eb77' + ], + [ + '2b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c', + '85e89bc037945d93b343083b5a1c86131a01f60c50269763b570c854e5c09b7a' + ], + [ + '352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5', + '321eb4075348f534d59c18259dda3e1f4a1b3b2e71b1039c67bd3d8bcf81998c' + ], + [ + '2fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f', + '2de1068295dd865b64569335bd5dd80181d70ecfc882648423ba76b532b7d67' + ], + [ + '9248279b09b4d68dab21a9b066edda83263c3d84e09572e269ca0cd7f5453714', + '73016f7bf234aade5d1aa71bdea2b1ff3fc0de2a887912ffe54a32ce97cb3402' + ], + [ + 'daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729', + 'a69dce4a7d6c98e8d4a1aca87ef8d7003f83c230f3afa726ab40e52290be1c55' + ], + [ + 'c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db', + '2119a460ce326cdc76c45926c982fdac0e106e861edf61c5a039063f0e0e6482' + ], + [ + '6a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4', + 'e022cf42c2bd4a708b3f5126f16a24ad8b33ba48d0423b6efd5e6348100d8a82' + ], + [ + '1697ffa6fd9de627c077e3d2fe541084ce13300b0bec1146f95ae57f0d0bd6a5', + 'b9c398f186806f5d27561506e4557433a2cf15009e498ae7adee9d63d01b2396' + ], + [ + '605bdb019981718b986d0f07e834cb0d9deb8360ffb7f61df982345ef27a7479', + '2972d2de4f8d20681a78d93ec96fe23c26bfae84fb14db43b01e1e9056b8c49' + ], + [ + '62d14dab4150bf497402fdc45a215e10dcb01c354959b10cfe31c7e9d87ff33d', + '80fc06bd8cc5b01098088a1950eed0db01aa132967ab472235f5642483b25eaf' + ], + [ + '80c60ad0040f27dade5b4b06c408e56b2c50e9f56b9b8b425e555c2f86308b6f', + '1c38303f1cc5c30f26e66bad7fe72f70a65eed4cbe7024eb1aa01f56430bd57a' + ], + [ + '7a9375ad6167ad54aa74c6348cc54d344cc5dc9487d847049d5eabb0fa03c8fb', + 'd0e3fa9eca8726909559e0d79269046bdc59ea10c70ce2b02d499ec224dc7f7' + ], + [ + 'd528ecd9b696b54c907a9ed045447a79bb408ec39b68df504bb51f459bc3ffc9', + 'eecf41253136e5f99966f21881fd656ebc4345405c520dbc063465b521409933' + ], + [ + '49370a4b5f43412ea25f514e8ecdad05266115e4a7ecb1387231808f8b45963', + '758f3f41afd6ed428b3081b0512fd62a54c3f3afbb5b6764b653052a12949c9a' + ], + [ + '77f230936ee88cbbd73df930d64702ef881d811e0e1498e2f1c13eb1fc345d74', + '958ef42a7886b6400a08266e9ba1b37896c95330d97077cbbe8eb3c7671c60d6' + ], + [ + 'f2dac991cc4ce4b9ea44887e5c7c0bce58c80074ab9d4dbaeb28531b7739f530', + 'e0dedc9b3b2f8dad4da1f32dec2531df9eb5fbeb0598e4fd1a117dba703a3c37' + ], + [ + '463b3d9f662621fb1b4be8fbbe2520125a216cdfc9dae3debcba4850c690d45b', + '5ed430d78c296c3543114306dd8622d7c622e27c970a1de31cb377b01af7307e' + ], + [ + 'f16f804244e46e2a09232d4aff3b59976b98fac14328a2d1a32496b49998f247', + 'cedabd9b82203f7e13d206fcdf4e33d92a6c53c26e5cce26d6579962c4e31df6' + ], + [ + 'caf754272dc84563b0352b7a14311af55d245315ace27c65369e15f7151d41d1', + 'cb474660ef35f5f2a41b643fa5e460575f4fa9b7962232a5c32f908318a04476' + ], + [ + '2600ca4b282cb986f85d0f1709979d8b44a09c07cb86d7c124497bc86f082120', + '4119b88753c15bd6a693b03fcddbb45d5ac6be74ab5f0ef44b0be9475a7e4b40' + ], + [ + '7635ca72d7e8432c338ec53cd12220bc01c48685e24f7dc8c602a7746998e435', + '91b649609489d613d1d5e590f78e6d74ecfc061d57048bad9e76f302c5b9c61' + ], + [ + '754e3239f325570cdbbf4a87deee8a66b7f2b33479d468fbc1a50743bf56cc18', + '673fb86e5bda30fb3cd0ed304ea49a023ee33d0197a695d0c5d98093c536683' + ], + [ + 'e3e6bd1071a1e96aff57859c82d570f0330800661d1c952f9fe2694691d9b9e8', + '59c9e0bba394e76f40c0aa58379a3cb6a5a2283993e90c4167002af4920e37f5' + ], + [ + '186b483d056a033826ae73d88f732985c4ccb1f32ba35f4b4cc47fdcf04aa6eb', + '3b952d32c67cf77e2e17446e204180ab21fb8090895138b4a4a797f86e80888b' + ], + [ + 'df9d70a6b9876ce544c98561f4be4f725442e6d2b737d9c91a8321724ce0963f', + '55eb2dafd84d6ccd5f862b785dc39d4ab157222720ef9da217b8c45cf2ba2417' + ], + [ + '5edd5cc23c51e87a497ca815d5dce0f8ab52554f849ed8995de64c5f34ce7143', + 'efae9c8dbc14130661e8cec030c89ad0c13c66c0d17a2905cdc706ab7399a868' + ], + [ + '290798c2b6476830da12fe02287e9e777aa3fba1c355b17a722d362f84614fba', + 'e38da76dcd440621988d00bcf79af25d5b29c094db2a23146d003afd41943e7a' + ], + [ + 'af3c423a95d9f5b3054754efa150ac39cd29552fe360257362dfdecef4053b45', + 'f98a3fd831eb2b749a93b0e6f35cfb40c8cd5aa667a15581bc2feded498fd9c6' + ], + [ + '766dbb24d134e745cccaa28c99bf274906bb66b26dcf98df8d2fed50d884249a', + '744b1152eacbe5e38dcc887980da38b897584a65fa06cedd2c924f97cbac5996' + ], + [ + '59dbf46f8c94759ba21277c33784f41645f7b44f6c596a58ce92e666191abe3e', + 'c534ad44175fbc300f4ea6ce648309a042ce739a7919798cd85e216c4a307f6e' + ], + [ + 'f13ada95103c4537305e691e74e9a4a8dd647e711a95e73cb62dc6018cfd87b8', + 'e13817b44ee14de663bf4bc808341f326949e21a6a75c2570778419bdaf5733d' + ], + [ + '7754b4fa0e8aced06d4167a2c59cca4cda1869c06ebadfb6488550015a88522c', + '30e93e864e669d82224b967c3020b8fa8d1e4e350b6cbcc537a48b57841163a2' + ], + [ + '948dcadf5990e048aa3874d46abef9d701858f95de8041d2a6828c99e2262519', + 'e491a42537f6e597d5d28a3224b1bc25df9154efbd2ef1d2cbba2cae5347d57e' + ], + [ + '7962414450c76c1689c7b48f8202ec37fb224cf5ac0bfa1570328a8a3d7c77ab', + '100b610ec4ffb4760d5c1fc133ef6f6b12507a051f04ac5760afa5b29db83437' + ], + [ + '3514087834964b54b15b160644d915485a16977225b8847bb0dd085137ec47ca', + 'ef0afbb2056205448e1652c48e8127fc6039e77c15c2378b7e7d15a0de293311' + ], + [ + 'd3cc30ad6b483e4bc79ce2c9dd8bc54993e947eb8df787b442943d3f7b527eaf', + '8b378a22d827278d89c5e9be8f9508ae3c2ad46290358630afb34db04eede0a4' + ], + [ + '1624d84780732860ce1c78fcbfefe08b2b29823db913f6493975ba0ff4847610', + '68651cf9b6da903e0914448c6cd9d4ca896878f5282be4c8cc06e2a404078575' + ], + [ + '733ce80da955a8a26902c95633e62a985192474b5af207da6df7b4fd5fc61cd4', + 'f5435a2bd2badf7d485a4d8b8db9fcce3e1ef8e0201e4578c54673bc1dc5ea1d' + ], + [ + '15d9441254945064cf1a1c33bbd3b49f8966c5092171e699ef258dfab81c045c', + 'd56eb30b69463e7234f5137b73b84177434800bacebfc685fc37bbe9efe4070d' + ], + [ + 'a1d0fcf2ec9de675b612136e5ce70d271c21417c9d2b8aaaac138599d0717940', + 'edd77f50bcb5a3cab2e90737309667f2641462a54070f3d519212d39c197a629' + ], + [ + 'e22fbe15c0af8ccc5780c0735f84dbe9a790badee8245c06c7ca37331cb36980', + 'a855babad5cd60c88b430a69f53a1a7a38289154964799be43d06d77d31da06' + ], + [ + '311091dd9860e8e20ee13473c1155f5f69635e394704eaa74009452246cfa9b3', + '66db656f87d1f04fffd1f04788c06830871ec5a64feee685bd80f0b1286d8374' + ], + [ + '34c1fd04d301be89b31c0442d3e6ac24883928b45a9340781867d4232ec2dbdf', + '9414685e97b1b5954bd46f730174136d57f1ceeb487443dc5321857ba73abee' + ], + [ + 'f219ea5d6b54701c1c14de5b557eb42a8d13f3abbcd08affcc2a5e6b049b8d63', + '4cb95957e83d40b0f73af4544cccf6b1f4b08d3c07b27fb8d8c2962a400766d1' + ], + [ + 'd7b8740f74a8fbaab1f683db8f45de26543a5490bca627087236912469a0b448', + 'fa77968128d9c92ee1010f337ad4717eff15db5ed3c049b3411e0315eaa4593b' + ], + [ + '32d31c222f8f6f0ef86f7c98d3a3335ead5bcd32abdd94289fe4d3091aa824bf', + '5f3032f5892156e39ccd3d7915b9e1da2e6dac9e6f26e961118d14b8462e1661' + ], + [ + '7461f371914ab32671045a155d9831ea8793d77cd59592c4340f86cbc18347b5', + '8ec0ba238b96bec0cbdddcae0aa442542eee1ff50c986ea6b39847b3cc092ff6' + ], + [ + 'ee079adb1df1860074356a25aa38206a6d716b2c3e67453d287698bad7b2b2d6', + '8dc2412aafe3be5c4c5f37e0ecc5f9f6a446989af04c4e25ebaac479ec1c8c1e' + ], + [ + '16ec93e447ec83f0467b18302ee620f7e65de331874c9dc72bfd8616ba9da6b5', + '5e4631150e62fb40d0e8c2a7ca5804a39d58186a50e497139626778e25b0674d' + ], + [ + 'eaa5f980c245f6f038978290afa70b6bd8855897f98b6aa485b96065d537bd99', + 'f65f5d3e292c2e0819a528391c994624d784869d7e6ea67fb18041024edc07dc' + ], + [ + '78c9407544ac132692ee1910a02439958ae04877151342ea96c4b6b35a49f51', + 'f3e0319169eb9b85d5404795539a5e68fa1fbd583c064d2462b675f194a3ddb4' + ], + [ + '494f4be219a1a77016dcd838431aea0001cdc8ae7a6fc688726578d9702857a5', + '42242a969283a5f339ba7f075e36ba2af925ce30d767ed6e55f4b031880d562c' + ], + [ + 'a598a8030da6d86c6bc7f2f5144ea549d28211ea58faa70ebf4c1e665c1fe9b5', + '204b5d6f84822c307e4b4a7140737aec23fc63b65b35f86a10026dbd2d864e6b' + ], + [ + 'c41916365abb2b5d09192f5f2dbeafec208f020f12570a184dbadc3e58595997', + '4f14351d0087efa49d245b328984989d5caf9450f34bfc0ed16e96b58fa9913' + ], + [ + '841d6063a586fa475a724604da03bc5b92a2e0d2e0a36acfe4c73a5514742881', + '73867f59c0659e81904f9a1c7543698e62562d6744c169ce7a36de01a8d6154' + ], + [ + '5e95bb399a6971d376026947f89bde2f282b33810928be4ded112ac4d70e20d5', + '39f23f366809085beebfc71181313775a99c9aed7d8ba38b161384c746012865' + ], + [ + '36e4641a53948fd476c39f8a99fd974e5ec07564b5315d8bf99471bca0ef2f66', + 'd2424b1b1abe4eb8164227b085c9aa9456ea13493fd563e06fd51cf5694c78fc' + ], + [ + '336581ea7bfbbb290c191a2f507a41cf5643842170e914faeab27c2c579f726', + 'ead12168595fe1be99252129b6e56b3391f7ab1410cd1e0ef3dcdcabd2fda224' + ], + [ + '8ab89816dadfd6b6a1f2634fcf00ec8403781025ed6890c4849742706bd43ede', + '6fdcef09f2f6d0a044e654aef624136f503d459c3e89845858a47a9129cdd24e' + ], + [ + '1e33f1a746c9c5778133344d9299fcaa20b0938e8acff2544bb40284b8c5fb94', + '60660257dd11b3aa9c8ed618d24edff2306d320f1d03010e33a7d2057f3b3b6' + ], + [ + '85b7c1dcb3cec1b7ee7f30ded79dd20a0ed1f4cc18cbcfcfa410361fd8f08f31', + '3d98a9cdd026dd43f39048f25a8847f4fcafad1895d7a633c6fed3c35e999511' + ], + [ + '29df9fbd8d9e46509275f4b125d6d45d7fbe9a3b878a7af872a2800661ac5f51', + 'b4c4fe99c775a606e2d8862179139ffda61dc861c019e55cd2876eb2a27d84b' + ], + [ + 'a0b1cae06b0a847a3fea6e671aaf8adfdfe58ca2f768105c8082b2e449fce252', + 'ae434102edde0958ec4b19d917a6a28e6b72da1834aff0e650f049503a296cf2' + ], + [ + '4e8ceafb9b3e9a136dc7ff67e840295b499dfb3b2133e4ba113f2e4c0e121e5', + 'cf2174118c8b6d7a4b48f6d534ce5c79422c086a63460502b827ce62a326683c' + ], + [ + 'd24a44e047e19b6f5afb81c7ca2f69080a5076689a010919f42725c2b789a33b', + '6fb8d5591b466f8fc63db50f1c0f1c69013f996887b8244d2cdec417afea8fa3' + ], + [ + 'ea01606a7a6c9cdd249fdfcfacb99584001edd28abbab77b5104e98e8e3b35d4', + '322af4908c7312b0cfbfe369f7a7b3cdb7d4494bc2823700cfd652188a3ea98d' + ], + [ + 'af8addbf2b661c8a6c6328655eb96651252007d8c5ea31be4ad196de8ce2131f', + '6749e67c029b85f52a034eafd096836b2520818680e26ac8f3dfbcdb71749700' + ], + [ + 'e3ae1974566ca06cc516d47e0fb165a674a3dabcfca15e722f0e3450f45889', + '2aeabe7e4531510116217f07bf4d07300de97e4874f81f533420a72eeb0bd6a4' + ], + [ + '591ee355313d99721cf6993ffed1e3e301993ff3ed258802075ea8ced397e246', + 'b0ea558a113c30bea60fc4775460c7901ff0b053d25ca2bdeee98f1a4be5d196' + ], + [ + '11396d55fda54c49f19aa97318d8da61fa8584e47b084945077cf03255b52984', + '998c74a8cd45ac01289d5833a7beb4744ff536b01b257be4c5767bea93ea57a4' + ], + [ + '3c5d2a1ba39c5a1790000738c9e0c40b8dcdfd5468754b6405540157e017aa7a', + 'b2284279995a34e2f9d4de7396fc18b80f9b8b9fdd270f6661f79ca4c81bd257' + ], + [ + 'cc8704b8a60a0defa3a99a7299f2e9c3fbc395afb04ac078425ef8a1793cc030', + 'bdd46039feed17881d1e0862db347f8cf395b74fc4bcdc4e940b74e3ac1f1b13' + ], + [ + 'c533e4f7ea8555aacd9777ac5cad29b97dd4defccc53ee7ea204119b2889b197', + '6f0a256bc5efdf429a2fb6242f1a43a2d9b925bb4a4b3a26bb8e0f45eb596096' + ], + [ + 'c14f8f2ccb27d6f109f6d08d03cc96a69ba8c34eec07bbcf566d48e33da6593', + 'c359d6923bb398f7fd4473e16fe1c28475b740dd098075e6c0e8649113dc3a38' + ], + [ + 'a6cbc3046bc6a450bac24789fa17115a4c9739ed75f8f21ce441f72e0b90e6ef', + '21ae7f4680e889bb130619e2c0f95a360ceb573c70603139862afd617fa9b9f' + ], + [ + '347d6d9a02c48927ebfb86c1359b1caf130a3c0267d11ce6344b39f99d43cc38', + '60ea7f61a353524d1c987f6ecec92f086d565ab687870cb12689ff1e31c74448' + ], + [ + 'da6545d2181db8d983f7dcb375ef5866d47c67b1bf31c8cf855ef7437b72656a', + '49b96715ab6878a79e78f07ce5680c5d6673051b4935bd897fea824b77dc208a' + ], + [ + 'c40747cc9d012cb1a13b8148309c6de7ec25d6945d657146b9d5994b8feb1111', + '5ca560753be2a12fc6de6caf2cb489565db936156b9514e1bb5e83037e0fa2d4' + ], + [ + '4e42c8ec82c99798ccf3a610be870e78338c7f713348bd34c8203ef4037f3502', + '7571d74ee5e0fb92a7a8b33a07783341a5492144cc54bcc40a94473693606437' + ], + [ + '3775ab7089bc6af823aba2e1af70b236d251cadb0c86743287522a1b3b0dedea', + 'be52d107bcfa09d8bcb9736a828cfa7fac8db17bf7a76a2c42ad961409018cf7' + ], + [ + 'cee31cbf7e34ec379d94fb814d3d775ad954595d1314ba8846959e3e82f74e26', + '8fd64a14c06b589c26b947ae2bcf6bfa0149ef0be14ed4d80f448a01c43b1c6d' + ], + [ + 'b4f9eaea09b6917619f6ea6a4eb5464efddb58fd45b1ebefcdc1a01d08b47986', + '39e5c9925b5a54b07433a4f18c61726f8bb131c012ca542eb24a8ac07200682a' + ], + [ + 'd4263dfc3d2df923a0179a48966d30ce84e2515afc3dccc1b77907792ebcc60e', + '62dfaf07a0f78feb30e30d6295853ce189e127760ad6cf7fae164e122a208d54' + ], + [ + '48457524820fa65a4f8d35eb6930857c0032acc0a4a2de422233eeda897612c4', + '25a748ab367979d98733c38a1fa1c2e7dc6cc07db2d60a9ae7a76aaa49bd0f77' + ], + [ + 'dfeeef1881101f2cb11644f3a2afdfc2045e19919152923f367a1767c11cceda', + 'ecfb7056cf1de042f9420bab396793c0c390bde74b4bbdff16a83ae09a9a7517' + ], + [ + '6d7ef6b17543f8373c573f44e1f389835d89bcbc6062ced36c82df83b8fae859', + 'cd450ec335438986dfefa10c57fea9bcc521a0959b2d80bbf74b190dca712d10' + ], + [ + 'e75605d59102a5a2684500d3b991f2e3f3c88b93225547035af25af66e04541f', + 'f5c54754a8f71ee540b9b48728473e314f729ac5308b06938360990e2bfad125' + ], + [ + 'eb98660f4c4dfaa06a2be453d5020bc99a0c2e60abe388457dd43fefb1ed620c', + '6cb9a8876d9cb8520609af3add26cd20a0a7cd8a9411131ce85f44100099223e' + ], + [ + '13e87b027d8514d35939f2e6892b19922154596941888336dc3563e3b8dba942', + 'fef5a3c68059a6dec5d624114bf1e91aac2b9da568d6abeb2570d55646b8adf1' + ], + [ + 'ee163026e9fd6fe017c38f06a5be6fc125424b371ce2708e7bf4491691e5764a', + '1acb250f255dd61c43d94ccc670d0f58f49ae3fa15b96623e5430da0ad6c62b2' + ], + [ + 'b268f5ef9ad51e4d78de3a750c2dc89b1e626d43505867999932e5db33af3d80', + '5f310d4b3c99b9ebb19f77d41c1dee018cf0d34fd4191614003e945a1216e423' + ], + [ + 'ff07f3118a9df035e9fad85eb6c7bfe42b02f01ca99ceea3bf7ffdba93c4750d', + '438136d603e858a3a5c440c38eccbaddc1d2942114e2eddd4740d098ced1f0d8' + ], + [ + '8d8b9855c7c052a34146fd20ffb658bea4b9f69e0d825ebec16e8c3ce2b526a1', + 'cdb559eedc2d79f926baf44fb84ea4d44bcf50fee51d7ceb30e2e7f463036758' + ], + [ + '52db0b5384dfbf05bfa9d472d7ae26dfe4b851ceca91b1eba54263180da32b63', + 'c3b997d050ee5d423ebaf66a6db9f57b3180c902875679de924b69d84a7b375' + ], + [ + 'e62f9490d3d51da6395efd24e80919cc7d0f29c3f3fa48c6fff543becbd43352', + '6d89ad7ba4876b0b22c2ca280c682862f342c8591f1daf5170e07bfd9ccafa7d' + ], + [ + '7f30ea2476b399b4957509c88f77d0191afa2ff5cb7b14fd6d8e7d65aaab1193', + 'ca5ef7d4b231c94c3b15389a5f6311e9daff7bb67b103e9880ef4bff637acaec' + ], + [ + '5098ff1e1d9f14fb46a210fada6c903fef0fb7b4a1dd1d9ac60a0361800b7a00', + '9731141d81fc8f8084d37c6e7542006b3ee1b40d60dfe5362a5b132fd17ddc0' + ], + [ + '32b78c7de9ee512a72895be6b9cbefa6e2f3c4ccce445c96b9f2c81e2778ad58', + 'ee1849f513df71e32efc3896ee28260c73bb80547ae2275ba497237794c8753c' + ], + [ + 'e2cb74fddc8e9fbcd076eef2a7c72b0ce37d50f08269dfc074b581550547a4f7', + 'd3aa2ed71c9dd2247a62df062736eb0baddea9e36122d2be8641abcb005cc4a4' + ], + [ + '8438447566d4d7bedadc299496ab357426009a35f235cb141be0d99cd10ae3a8', + 'c4e1020916980a4da5d01ac5e6ad330734ef0d7906631c4f2390426b2edd791f' + ], + [ + '4162d488b89402039b584c6fc6c308870587d9c46f660b878ab65c82c711d67e', + '67163e903236289f776f22c25fb8a3afc1732f2b84b4e95dbda47ae5a0852649' + ], + [ + '3fad3fa84caf0f34f0f89bfd2dcf54fc175d767aec3e50684f3ba4a4bf5f683d', + 'cd1bc7cb6cc407bb2f0ca647c718a730cf71872e7d0d2a53fa20efcdfe61826' + ], + [ + '674f2600a3007a00568c1a7ce05d0816c1fb84bf1370798f1c69532faeb1a86b', + '299d21f9413f33b3edf43b257004580b70db57da0b182259e09eecc69e0d38a5' + ], + [ + 'd32f4da54ade74abb81b815ad1fb3b263d82d6c692714bcff87d29bd5ee9f08f', + 'f9429e738b8e53b968e99016c059707782e14f4535359d582fc416910b3eea87' + ], + [ + '30e4e670435385556e593657135845d36fbb6931f72b08cb1ed954f1e3ce3ff6', + '462f9bce619898638499350113bbc9b10a878d35da70740dc695a559eb88db7b' + ], + [ + 'be2062003c51cc3004682904330e4dee7f3dcd10b01e580bf1971b04d4cad297', + '62188bc49d61e5428573d48a74e1c655b1c61090905682a0d5558ed72dccb9bc' + ], + [ + '93144423ace3451ed29e0fb9ac2af211cb6e84a601df5993c419859fff5df04a', + '7c10dfb164c3425f5c71a3f9d7992038f1065224f72bb9d1d902a6d13037b47c' + ], + [ + 'b015f8044f5fcbdcf21ca26d6c34fb8197829205c7b7d2a7cb66418c157b112c', + 'ab8c1e086d04e813744a655b2df8d5f83b3cdc6faa3088c1d3aea1454e3a1d5f' + ], + [ + 'd5e9e1da649d97d89e4868117a465a3a4f8a18de57a140d36b3f2af341a21b52', + '4cb04437f391ed73111a13cc1d4dd0db1693465c2240480d8955e8592f27447a' + ], + [ + 'd3ae41047dd7ca065dbf8ed77b992439983005cd72e16d6f996a5316d36966bb', + 'bd1aeb21ad22ebb22a10f0303417c6d964f8cdd7df0aca614b10dc14d125ac46' + ], + [ + '463e2763d885f958fc66cdd22800f0a487197d0a82e377b49f80af87c897b065', + 'bfefacdb0e5d0fd7df3a311a94de062b26b80c61fbc97508b79992671ef7ca7f' + ], + [ + '7985fdfd127c0567c6f53ec1bb63ec3158e597c40bfe747c83cddfc910641917', + '603c12daf3d9862ef2b25fe1de289aed24ed291e0ec6708703a5bd567f32ed03' + ], + [ + '74a1ad6b5f76e39db2dd249410eac7f99e74c59cb83d2d0ed5ff1543da7703e9', + 'cc6157ef18c9c63cd6193d83631bbea0093e0968942e8c33d5737fd790e0db08' + ], + [ + '30682a50703375f602d416664ba19b7fc9bab42c72747463a71d0896b22f6da3', + '553e04f6b018b4fa6c8f39e7f311d3176290d0e0f19ca73f17714d9977a22ff8' + ], + [ + '9e2158f0d7c0d5f26c3791efefa79597654e7a2b2464f52b1ee6c1347769ef57', + '712fcdd1b9053f09003a3481fa7762e9ffd7c8ef35a38509e2fbf2629008373' + ], + [ + '176e26989a43c9cfeba4029c202538c28172e566e3c4fce7322857f3be327d66', + 'ed8cc9d04b29eb877d270b4878dc43c19aefd31f4eee09ee7b47834c1fa4b1c3' + ], + [ + '75d46efea3771e6e68abb89a13ad747ecf1892393dfc4f1b7004788c50374da8', + '9852390a99507679fd0b86fd2b39a868d7efc22151346e1a3ca4726586a6bed8' + ], + [ + '809a20c67d64900ffb698c4c825f6d5f2310fb0451c869345b7319f645605721', + '9e994980d9917e22b76b061927fa04143d096ccc54963e6a5ebfa5f3f8e286c1' + ], + [ + '1b38903a43f7f114ed4500b4eac7083fdefece1cf29c63528d563446f972c180', + '4036edc931a60ae889353f77fd53de4a2708b26b6f5da72ad3394119daf408f9' + ] + ] } }; -MPI.prototype.toString = function () { - return _util2.default.Uint8Array_to_str(this.toUint8Array()); -}; - -MPI.prototype.fromString = function (str, endian = 'be') { - this.fromUint8Array(_util2.default.str_to_Uint8Array(str), endian); -}; - -MPI.prototype.toBN = function () { - return new _bn2.default(this.toUint8Array()); -}; - -MPI.prototype.fromBN = function (bn) { - this.data = bn.toArrayLike(Uint8Array); -}; - -MPI.fromClone = function (clone) { - return new MPI(clone.data); -}; - -exports.default = MPI; +var curves_1 = createCommonjsModule(function (module, exports) { -},{"../util":152,"bn.js":16}],150:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); +var curves = exports; -var _util = require('../util'); -var _util2 = _interopRequireDefault(_util); -var _enums = require('../enums'); -var _enums2 = _interopRequireDefault(_enums); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +var assert = utils_1$1.assert; -/** - * @constructor - */ -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2015-2016 Decentral -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +function PresetCurve(options) { + if (options.type === 'short') + this.curve = new curve_1.short(options); + else if (options.type === 'edwards') + this.curve = new curve_1.edwards(options); + else if (options.type === 'mont') + this.curve = new curve_1.mont(options); + else throw new Error('Unknown curve type.'); + this.g = this.curve.g; + this.n = this.curve.n; + this.hash = options.hash; -/** - * Wrapper to an OID value - * - * {@link https://tools.ietf.org/html/rfc6637#section-11|RFC6637, section 11}: - * The sequence of octets in the third column is the result of applying - * the Distinguished Encoding Rules (DER) to the ASN.1 Object Identifier - * with subsequent truncation. The truncation removes the two fields of - * encoded Object Identifier. The first omitted field is one octet - * representing the Object Identifier tag, and the second omitted field - * is the length of the Object Identifier body. For example, the - * complete ASN.1 DER encoding for the NIST P-256 curve OID is "06 08 2A - * 86 48 CE 3D 03 01 07", from which the first entry in the table above - * is constructed by omitting the first two octets. Only the truncated - * sequence of octets is the valid representation of a curve OID. - * @requires util - * @requires enums - * @module type/oid - */ - -function OID(oid) { - if (oid instanceof OID) { - this.oid = oid.oid; - } else if (_util2.default.isArray(oid) || _util2.default.isUint8Array(oid)) { - oid = new Uint8Array(oid); - if (oid[0] === 0x06) { - // DER encoded oid byte array - if (oid[1] !== oid.length - 2) { - throw new Error('Length mismatch in DER encoded oid'); - } - oid = oid.subarray(2); - } - this.oid = oid; - } else { - this.oid = ''; - } + assert(this.g.validate(), 'Invalid curve'); + assert(this.g.mul(this.n).isInfinity(), 'Invalid curve, n*G != O'); } +curves.PresetCurve = PresetCurve; -/** - * Method to read an OID object - * @param {Uint8Array} input Where to read the OID from - * @returns {Number} Number of read bytes - */ -OID.prototype.read = function (input) { - if (input.length >= 1) { - const length = input[0]; - if (input.length >= 1 + length) { - this.oid = input.subarray(1, 1 + length); - return 1 + this.oid.length; +function defineCurve(name, options) { + Object.defineProperty(curves, name, { + configurable: true, + enumerable: true, + get: function() { + var curve = new PresetCurve(options); + Object.defineProperty(curves, name, { + configurable: true, + enumerable: true, + value: curve + }); + return curve; } - } - throw new Error('Invalid oid'); -}; - -/** - * Serialize an OID object - * @returns {Uint8Array} Array with the serialized value the OID - */ -OID.prototype.write = function () { - return _util2.default.concatUint8Array([new Uint8Array([this.oid.length]), this.oid]); -}; + }); +} -/** - * Serialize an OID object as a hex string - * @returns {string} String with the hex value of the OID - */ -OID.prototype.toHex = function () { - return _util2.default.Uint8Array_to_hex(this.oid); -}; +defineCurve('p192', { + type: 'short', + prime: 'p192', + p: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff', + a: 'ffffffff ffffffff ffffffff fffffffe ffffffff fffffffc', + b: '64210519 e59c80e7 0fa7e9ab 72243049 feb8deec c146b9b1', + n: 'ffffffff ffffffff ffffffff 99def836 146bc9b1 b4d22831', + hash: hash_1.sha256, + gRed: false, + g: [ + '188da80e b03090f6 7cbf20eb 43a18800 f4ff0afd 82ff1012', + '07192b95 ffc8da78 631011ed 6b24cdd5 73f977a1 1e794811' + ] +}); -/** - * If a known curve object identifier, return the canonical name of the curve - * @returns {string} String with the canonical name of the curve - */ -OID.prototype.getName = function () { - const hex = this.toHex(); - if (_enums2.default.curve[hex]) { - return _enums2.default.write(_enums2.default.curve, hex); - } else { - throw new Error('Unknown curve object identifier.'); - } -}; +defineCurve('p224', { + type: 'short', + prime: 'p224', + p: 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001', + a: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff fffffffe', + b: 'b4050a85 0c04b3ab f5413256 5044b0b7 d7bfd8ba 270b3943 2355ffb4', + n: 'ffffffff ffffffff ffffffff ffff16a2 e0b8f03e 13dd2945 5c5c2a3d', + hash: hash_1.sha256, + gRed: false, + g: [ + 'b70e0cbd 6bb4bf7f 321390b9 4a03c1d3 56c21122 343280d6 115c1d21', + 'bd376388 b5f723fb 4c22dfe6 cd4375a0 5a074764 44d58199 85007e34' + ] +}); -OID.fromClone = function (clone) { - return new OID(clone.oid); -}; +defineCurve('p256', { + type: 'short', + prime: null, + p: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff', + a: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff fffffffc', + b: '5ac635d8 aa3a93e7 b3ebbd55 769886bc 651d06b0 cc53b0f6 3bce3c3e 27d2604b', + n: 'ffffffff 00000000 ffffffff ffffffff bce6faad a7179e84 f3b9cac2 fc632551', + hash: hash_1.sha256, + gRed: false, + g: [ + '6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296', + '4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5' + ] +}); -exports.default = OID; +defineCurve('p384', { + type: 'short', + prime: null, + p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'fffffffe ffffffff 00000000 00000000 ffffffff', + a: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'fffffffe ffffffff 00000000 00000000 fffffffc', + b: 'b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112 0314088f ' + + '5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef', + n: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff c7634d81 ' + + 'f4372ddf 581a0db2 48b0a77a ecec196a ccc52973', + hash: hash_1.sha384, + gRed: false, + g: [ + 'aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98 59f741e0 82542a38 ' + + '5502f25d bf55296c 3a545e38 72760ab7', + '3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c e9da3113 b5f0b8c0 ' + + '0a60b1ce 1d7e819d 7a431d7c 90ea0e5f' + ] +}); -},{"../enums":113,"../util":152}],151:[function(require,module,exports){ -'use strict'; +defineCurve('p521', { + type: 'short', + prime: null, + p: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff ffffffff ffffffff ffffffff', + a: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff ffffffff ffffffff fffffffc', + b: '00000051 953eb961 8e1c9a1f 929a21a0 b68540ee a2da725b ' + + '99b315f3 b8b48991 8ef109e1 56193951 ec7e937b 1652c0bd ' + + '3bb1bf07 3573df88 3d2c34f1 ef451fd4 6b503f00', + n: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff fffffffa 51868783 bf2f966b 7fcc0148 ' + + 'f709a5d0 3bb5c9b8 899c47ae bb6fb71e 91386409', + hash: hash_1.sha512, + gRed: false, + g: [ + '000000c6 858e06b7 0404e9cd 9e3ecb66 2395b442 9c648139 ' + + '053fb521 f828af60 6b4d3dba a14b5e77 efe75928 fe1dc127 ' + + 'a2ffa8de 3348b3c1 856a429b f97e7e31 c2e5bd66', + '00000118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd9 98f54449 ' + + '579b4468 17afbd17 273e662c 97ee7299 5ef42640 c550b901 ' + + '3fad0761 353c7086 a272c240 88be9476 9fd16650' + ] +}); -Object.defineProperty(exports, "__esModule", { - value: true +// https://tools.ietf.org/html/rfc7748#section-4.1 +defineCurve('curve25519', { + type: 'mont', + prime: 'p25519', + p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', + a: '76d06', + b: '1', + n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', + cofactor: '8', + hash: hash_1.sha256, + gRed: false, + g: [ + '9' + ] }); -var _config = require('../config'); +defineCurve('ed25519', { + type: 'edwards', + prime: 'p25519', + p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', + a: '-1', + c: '1', + // -121665 * (121666^(-1)) (mod P) + d: '52036cee2b6ffe73 8cc740797779e898 00700a4d4141d8ab 75eb4dca135978a3', + n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', + cofactor: '8', + hash: hash_1.sha256, + gRed: false, + g: [ + '216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a', + // 4/5 + '6666666666666666666666666666666666666666666666666666666666666658' + ] +}); -var _config2 = _interopRequireDefault(_config); +// https://tools.ietf.org/html/rfc5639#section-3.4 +defineCurve('brainpoolP256r1', { + type: 'short', + prime: null, + p: 'A9FB57DB A1EEA9BC 3E660A90 9D838D72 6E3BF623 D5262028 2013481D 1F6E5377', + a: '7D5A0975 FC2C3057 EEF67530 417AFFE7 FB8055C1 26DC5C6C E94A4B44 F330B5D9', + b: '26DC5C6C E94A4B44 F330B5D9 BBD77CBF 95841629 5CF7E1CE 6BCCDC18 FF8C07B6', + n: 'A9FB57DB A1EEA9BC 3E660A90 9D838D71 8C397AA3 B561A6F7 901E0E82 974856A7', + hash: hash_1.sha256, // or 384, or 512 + gRed: false, + g: [ + '8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262', + '547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997' + ] +}); -var _crypto = require('../crypto'); +// https://tools.ietf.org/html/rfc5639#section-3.6 +defineCurve('brainpoolP384r1', { + type: 'short', + prime: null, + p: '8CB91E82 A3386D28 0F5D6F7E 50E641DF 152F7109 ED5456B4 12B1DA19 7FB71123' + + 'ACD3A729 901D1A71 87470013 3107EC53', + a: '7BC382C6 3D8C150C 3C72080A CE05AFA0 C2BEA28E 4FB22787 139165EF BA91F90F' + + '8AA5814A 503AD4EB 04A8C7DD 22CE2826', + b: '04A8C7DD 22CE2826 8B39B554 16F0447C 2FB77DE1 07DCD2A6 2E880EA5 3EEB62D5' + + '7CB43902 95DBC994 3AB78696 FA504C11', + n: '8CB91E82 A3386D28 0F5D6F7E 50E641DF 152F7109 ED5456B3 1F166E6C AC0425A7' + + 'CF3AB6AF 6B7FC310 3B883202 E9046565', + hash: hash_1.sha384, // or 512 + gRed: false, + g: [ + '1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10' + + 'E8E826E03436D646AAEF87B2E247D4AF1E', + '8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129' + + '280E4646217791811142820341263C5315' + ] +}); -var _crypto2 = _interopRequireDefault(_crypto); +// https://tools.ietf.org/html/rfc5639#section-3.7 +defineCurve('brainpoolP512r1', { + type: 'short', + prime: null, + p: 'AADD9DB8 DBE9C48B 3FD4E6AE 33C9FC07 CB308DB3 B3C9D20E D6639CCA 70330871' + + '7D4D9B00 9BC66842 AECDA12A E6A380E6 2881FF2F 2D82C685 28AA6056 583A48F3', + a: '7830A331 8B603B89 E2327145 AC234CC5 94CBDD8D 3DF91610 A83441CA EA9863BC' + + '2DED5D5A A8253AA1 0A2EF1C9 8B9AC8B5 7F1117A7 2BF2C7B9 E7C1AC4D 77FC94CA', + b: '3DF91610 A83441CA EA9863BC 2DED5D5A A8253AA1 0A2EF1C9 8B9AC8B5 7F1117A7' + + '2BF2C7B9 E7C1AC4D 77FC94CA DC083E67 984050B7 5EBAE5DD 2809BD63 8016F723', + n: 'AADD9DB8 DBE9C48B 3FD4E6AE 33C9FC07 CB308DB3 B3C9D20E D6639CCA 70330870' + + '553E5C41 4CA92619 41866119 7FAC1047 1DB1D381 085DDADD B5879682 9CA90069', + hash: hash_1.sha512, + gRed: false, + g: [ + '81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D009' + + '8EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822', + '7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F81' + + '11B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892' + ] +}); -var _enums = require('../enums.js'); +// https://en.bitcoin.it/wiki/Secp256k1 +var pre; +try { + pre = secp256k1; +} catch (e) { + pre = undefined; +} -var _enums2 = _interopRequireDefault(_enums); +defineCurve('secp256k1', { + type: 'short', + prime: 'k256', + p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f', + a: '0', + b: '7', + n: 'ffffffff ffffffff ffffffff fffffffe baaedce6 af48a03b bfd25e8c d0364141', + h: '1', + hash: hash_1.sha256, -var _util = require('../util.js'); + // Precomputed endomorphism + beta: '7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee', + lambda: '5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72', + basis: [ + { + a: '3086d221a7d46bcde86c90e49284eb15', + b: '-e4437ed6010e88286f547fa90abfe4c3' + }, + { + a: '114ca50f7a8e2f3f657c1108d9d44cfd8', + b: '3086d221a7d46bcde86c90e49284eb15' + } + ], -var _util2 = _interopRequireDefault(_util); + gRed: false, + g: [ + '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', + '483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', + pre + ] +}); +}); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +function HmacDRBG(options) { + if (!(this instanceof HmacDRBG)) + return new HmacDRBG(options); + this.hash = options.hash; + this.predResist = !!options.predResist; -/** - * @constructor - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + this.outLen = this.hash.outSize; + this.minEntropy = options.minEntropy || this.hash.hmacStrength; -/** - * Implementation of the String-to-key specifier - * - * {@link https://tools.ietf.org/html/rfc4880#section-3.7|RFC4880 3.7}: - * String-to-key (S2K) specifiers are used to convert passphrase strings - * into symmetric-key encryption/decryption keys. They are used in two - * places, currently: to encrypt the secret part of private keys in the - * private keyring, and to convert passphrases to encryption keys for - * symmetrically encrypted messages. - * @requires config - * @requires crypto - * @requires enums - * @requires util - * @module type/s2k - */ + this._reseed = null; + this.reseedInterval = null; + this.K = null; + this.V = null; -function S2K() { - /** @type {module:enums.hash} */ - this.algorithm = 'sha256'; - /** @type {module:enums.s2k} */ - this.type = 'iterated'; - /** @type {Integer} */ - this.c = _config2.default.s2k_iteration_count_byte; - /** Eight bytes of salt in a binary string. - * @type {String} - */ - this.salt = null; + var entropy = utils_1.toArray(options.entropy, options.entropyEnc || 'hex'); + var nonce = utils_1.toArray(options.nonce, options.nonceEnc || 'hex'); + var pers = utils_1.toArray(options.pers, options.persEnc || 'hex'); + minimalisticAssert(entropy.length >= (this.minEntropy / 8), + 'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits'); + this._init(entropy, nonce, pers); } +var hmacDrbg = HmacDRBG; -S2K.prototype.get_count = function () { - // Exponent bias, defined in RFC4880 - const expbias = 6; - - return 16 + (this.c & 15) << (this.c >> 4) + expbias; -}; +HmacDRBG.prototype._init = function init(entropy, nonce, pers) { + var seed = entropy.concat(nonce).concat(pers); -/** - * Parsing function for a string-to-key specifier ({@link https://tools.ietf.org/html/rfc4880#section-3.7|RFC 4880 3.7}). - * @param {String} input Payload of string-to-key specifier - * @returns {Integer} Actual length of the object - */ -S2K.prototype.read = function (bytes) { - let i = 0; - this.type = _enums2.default.read(_enums2.default.s2k, bytes[i++]); - this.algorithm = bytes[i++]; - if (this.type !== 'gnu') { - this.algorithm = _enums2.default.read(_enums2.default.hash, this.algorithm); + this.K = new Array(this.outLen / 8); + this.V = new Array(this.outLen / 8); + for (var i = 0; i < this.V.length; i++) { + this.K[i] = 0x00; + this.V[i] = 0x01; } - switch (this.type) { - case 'simple': - break; - - case 'salted': - this.salt = bytes.subarray(i, i + 8); - i += 8; - break; - - case 'iterated': - this.salt = bytes.subarray(i, i + 8); - i += 8; - - // Octet 10: count, a one-octet, coded value - this.c = bytes[i++]; - break; + this._update(seed); + this._reseed = 1; + this.reseedInterval = 0x1000000000000; // 2^48 +}; - case 'gnu': - if (_util2.default.Uint8Array_to_str(bytes.subarray(i, i + 3)) === "GNU") { - i += 3; // GNU - const gnuExtType = 1000 + bytes[i++]; - if (gnuExtType === 1001) { - this.type = 'gnu-dummy'; - // GnuPG extension mode 1001 -- don't write secret key at all - } else { - throw new Error("Unknown s2k gnu protection mode."); - } - } else { - throw new Error("Unknown s2k type."); - } - break; +HmacDRBG.prototype._hmac = function hmac() { + return new hash_1.hmac(this.hash, this.K); +}; - default: - throw new Error("Unknown s2k type."); - } +HmacDRBG.prototype._update = function update(seed) { + var kmac = this._hmac() + .update(this.V) + .update([ 0x00 ]); + if (seed) + kmac = kmac.update(seed); + this.K = kmac.digest(); + this.V = this._hmac().update(this.V).digest(); + if (!seed) + return; - return i; + this.K = this._hmac() + .update(this.V) + .update([ 0x01 ]) + .update(seed) + .digest(); + this.V = this._hmac().update(this.V).digest(); }; -/** - * Serializes s2k information - * @returns {Uint8Array} binary representation of s2k - */ -S2K.prototype.write = function () { - if (this.type === 'gnu-dummy') { - return new Uint8Array([101, 0, ..._util2.default.str_to_Uint8Array('GNU'), 1]); +HmacDRBG.prototype.reseed = function reseed(entropy, entropyEnc, add, addEnc) { + // Optional entropy enc + if (typeof entropyEnc !== 'string') { + addEnc = add; + add = entropyEnc; + entropyEnc = null; } - const arr = [new Uint8Array([_enums2.default.write(_enums2.default.s2k, this.type), _enums2.default.write(_enums2.default.hash, this.algorithm)])]; + entropy = utils_1.toArray(entropy, entropyEnc); + add = utils_1.toArray(add, addEnc); - switch (this.type) { - case 'simple': - break; - case 'salted': - arr.push(this.salt); - break; - case 'iterated': - arr.push(this.salt); - arr.push(new Uint8Array([this.c])); - break; - case 'gnu': - throw new Error("GNU s2k type not supported."); - default: - throw new Error("Unknown s2k type."); - } + minimalisticAssert(entropy.length >= (this.minEntropy / 8), + 'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits'); - return _util2.default.concatUint8Array(arr); + this._update(entropy.concat(add || [])); + this._reseed = 1; }; -/** - * Produces a key using the specified passphrase and the defined - * hashAlgorithm - * @param {String} passphrase Passphrase containing user input - * @returns {Uint8Array} Produced key with a length corresponding to - * hashAlgorithm hash length - */ -S2K.prototype.produce_key = async function (passphrase, numBytes) { - passphrase = _util2.default.encode_utf8(passphrase); - - async function round(prefix, s2k) { - const algorithm = _enums2.default.write(_enums2.default.hash, s2k.algorithm); - - switch (s2k.type) { - case 'simple': - return _crypto2.default.hash.digest(algorithm, _util2.default.concatUint8Array([prefix, passphrase])); - - case 'salted': - return _crypto2.default.hash.digest(algorithm, _util2.default.concatUint8Array([prefix, s2k.salt, passphrase])); - - case 'iterated': - { - const count = s2k.get_count(); - const data = _util2.default.concatUint8Array([s2k.salt, passphrase]); - const datalen = data.length; - const isp = new Uint8Array(prefix.length + count + datalen); - isp.set(prefix); - for (let pos = prefix.length; pos < count; pos += datalen) { - isp.set(data, pos); - } - return _crypto2.default.hash.digest(algorithm, isp.subarray(0, prefix.length + count)); - } - case 'gnu': - throw new Error("GNU s2k type not supported."); +HmacDRBG.prototype.generate = function generate(len, enc, add, addEnc) { + if (this._reseed > this.reseedInterval) + throw new Error('Reseed is required'); - default: - throw new Error("Unknown s2k type."); - } + // Optional encoding + if (typeof enc !== 'string') { + addEnc = add; + add = enc; + enc = null; } - const arr = []; - let rlength = 0; - const prefix = new Uint8Array(numBytes); - - for (let i = 0; i < numBytes; i++) { - prefix[i] = 0; + // Optional additional data + if (add) { + add = utils_1.toArray(add, addEnc || 'hex'); + this._update(add); } - let i = 0; - while (rlength < numBytes) { - const result = await round(prefix.subarray(0, i), this); - arr.push(result); - rlength += result.length; - i++; + var temp = []; + while (temp.length < len) { + this.V = this._hmac().update(this.V).digest(); + temp = temp.concat(this.V); } - return _util2.default.concatUint8Array(arr).subarray(0, numBytes); + var res = temp.slice(0, len); + this._update(add); + this._reseed++; + return utils_1.encode(res, enc); }; -S2K.fromClone = function (clone) { - const s2k = new S2K(); - s2k.algorithm = clone.algorithm; - s2k.type = clone.type; - s2k.c = clone.c; - s2k.salt = clone.salt; - return s2k; -}; +var assert$5 = utils_1$1.assert; -exports.default = S2K; +function KeyPair(ec, options) { + this.ec = ec; + this.priv = null; + this.pub = null; -},{"../config":79,"../crypto":94,"../enums.js":113,"../util.js":152}],152:[function(require,module,exports){ -(function (global){ -'use strict'; + // KeyPair(ec, { priv: ..., pub: ... }) + if (options.priv) + this._importPrivate(options.priv, options.privEnc); + if (options.pub) + this._importPublic(options.pub, options.pubEnc); +} +var key = KeyPair; -Object.defineProperty(exports, "__esModule", { - value: true -}); +KeyPair.fromPublic = function fromPublic(ec, pub, enc) { + if (pub instanceof KeyPair) + return pub; -var _emailAddresses = require('email-addresses'); + return new KeyPair(ec, { + pub: pub, + pubEnc: enc + }); +}; -var _emailAddresses2 = _interopRequireDefault(_emailAddresses); +KeyPair.fromPrivate = function fromPrivate(ec, priv, enc) { + if (priv instanceof KeyPair) + return priv; -var _webStreamTools = require('web-stream-tools'); + return new KeyPair(ec, { + priv: priv, + privEnc: enc + }); +}; -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); +// TODO: should not validate for X25519 +KeyPair.prototype.validate = function validate() { + var pub = this.getPublic(); -var _config = require('./config'); + if (pub.isInfinity()) + return { result: false, reason: 'Invalid public key' }; + if (!pub.validate()) + return { result: false, reason: 'Public key is not a point' }; + if (!pub.mul(this.ec.curve.n).isInfinity()) + return { result: false, reason: 'Public key * N != O' }; -var _config2 = _interopRequireDefault(_config); + return { result: true, reason: null }; +}; -var _util = require('./util'); +KeyPair.prototype.getPublic = function getPublic(enc, compact) { + if (!this.pub) + this.pub = this.ec.g.mul(this.priv); -var _util2 = _interopRequireDefault(_util); + if (!enc) + return this.pub; -var _base = require('./encoding/base64'); + return this.pub.encode(enc, compact); +}; -var _base2 = _interopRequireDefault(_base); +KeyPair.prototype.getPrivate = function getPrivate(enc) { + if (enc === 'hex') + return this.priv.toString(16, 2); + else + return this.priv; +}; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +KeyPair.prototype._importPrivate = function _importPrivate(key, enc) { + this.priv = new bn(key, enc || 16); -exports.default = { - isString: function isString(data) { - return typeof data === 'string' || String.prototype.isPrototypeOf(data); - }, + // For Curve25519/Curve448 we have a specific procedure. + // TODO Curve448 + if (this.ec.curve.type === 'mont') { + var one = this.ec.curve.one; + var mask = one.ushln(255 - 3).sub(one).ushln(3); + this.priv = this.priv.or(one.ushln(255 - 1)); + this.priv = this.priv.and(mask); + } else + // Ensure that the priv won't be bigger than n, otherwise we may fail + // in fixed multiplication method + this.priv = this.priv.umod(this.ec.curve.n); +}; - isArray: function isArray(data) { - return Array.prototype.isPrototypeOf(data); - }, +KeyPair.prototype._importPublic = function _importPublic(key, enc) { + if (key.x || key.y) { + // Montgomery points only have an `x` coordinate. + // Weierstrass/Edwards points on the other hand have both `x` and + // `y` coordinates. + if (this.ec.curve.type === 'mont') { + assert$5(key.x, 'Need x coordinate'); + } else if (this.ec.curve.type === 'short' || + this.ec.curve.type === 'edwards') { + assert$5(key.x && key.y, 'Need both x and y coordinate'); + } + this.pub = this.ec.curve.point(key.x, key.y); + return; + } + this.pub = this.ec.curve.decodePoint(key, enc); +}; - isUint8Array: _webStreamTools2.default.isUint8Array, +// ECDH +KeyPair.prototype.derive = function derive(pub) { + return pub.mul(this.priv).getX(); +}; - isStream: _webStreamTools2.default.isStream, +// ECDSA +KeyPair.prototype.sign = function sign(msg, enc, options) { + return this.ec.sign(msg, this, enc, options); +}; - /** - * Get transferable objects to pass buffers with zero copy (similar to "pass by reference" in C++) - * See: https://developer.mozilla.org/en-US/docs/Web/API/Worker/postMessage - * Also, convert ReadableStreams to MessagePorts - * @param {Object} obj the options object to be passed to the web worker - * @returns {Array} an array of binary data to be passed - */ - getTransferables: function getTransferables(obj, zero_copy) { - const transferables = []; - _util2.default.collectTransferables(obj, transferables, zero_copy); - return transferables.length ? transferables : undefined; - }, +KeyPair.prototype.verify = function verify(msg, signature) { + return this.ec.verify(msg, signature, this); +}; - collectTransferables: function collectTransferables(obj, collection, zero_copy) { - if (!obj) { - return; - } +KeyPair.prototype.inspect = function inspect() { + return ''; +}; - if (_util2.default.isUint8Array(obj)) { - if (zero_copy && collection.indexOf(obj.buffer) === -1 && !(navigator.userAgent.indexOf('Version/11.1') !== -1 || // Safari 11.1 - (navigator.userAgent.match(/Chrome\/(\d+)/) || [])[1] < 56 && navigator.userAgent.indexOf('Edge') === -1 // Chrome < 56 - )) { - collection.push(obj.buffer); - } - return; - } - if (Object.prototype.isPrototypeOf(obj)) { - Object.entries(obj).forEach(([key, value]) => { - // recursively search all children - if (_util2.default.isStream(value)) { - if (value.locked) { - obj[key] = null; - } else { - const transformed = _webStreamTools2.default.transformPair(value, async readable => { - const reader = _webStreamTools2.default.getReader(readable); - - var _ref = new MessageChannel(); - - const port1 = _ref.port1, - port2 = _ref.port2; - - port1.onmessage = async function ({ data: { action } }) { - if (action === 'read') { - try { - const result = await reader.read(); - port1.postMessage(result, _util2.default.getTransferables(result)); - } catch (e) { - port1.postMessage({ error: e.message }); - } - } else if (action === 'cancel') { - await transformed.cancel(); - port1.postMessage(); - } - }; - obj[key] = port2; - collection.push(port2); - }); - } - return; - } - if (Object.prototype.toString.call(value) === '[object MessagePort]') { - throw new Error("Can't transfer the same stream twice."); - } - _util2.default.collectTransferables(value, collection, zero_copy); - }); - } - }, +var assert$6 = utils_1$1.assert; - /** - * Convert MessagePorts back to ReadableStreams - * @param {Object} obj - * @returns {Object} - */ - restoreStreams: function restoreStreams(obj) { - if (Object.prototype.isPrototypeOf(obj) && !Uint8Array.prototype.isPrototypeOf(obj)) { - Object.entries(obj).forEach(([key, value]) => { - // recursively search all children - if (Object.prototype.toString.call(value) === '[object MessagePort]') { - obj[key] = new ReadableStream({ - pull(controller) { - return new Promise(resolve => { - value.onmessage = evt => { - var _evt$data = evt.data; - const done = _evt$data.done, - value = _evt$data.value, - error = _evt$data.error; - - if (error) { - controller.error(new Error(error)); - } else if (!done) { - controller.enqueue(value); - } else { - controller.close(); - } - resolve(); - }; - value.postMessage({ action: 'read' }); - }); - }, - cancel() { - return new Promise(resolve => { - value.onmessage = resolve; - value.postMessage({ action: 'cancel' }); - }); - } - }, { highWaterMark: 0 }); - return; - } - _util2.default.restoreStreams(value); - }); - } - return obj; - }, +function Signature$1(options, enc) { + if (options instanceof Signature$1) + return options; - readNumber: function readNumber(bytes) { - let n = 0; - for (let i = 0; i < bytes.length; i++) { - n += 256 ** i * bytes[bytes.length - 1 - i]; - } - return n; - }, + if (this._importDER(options, enc)) + return; - writeNumber: function writeNumber(n, bytes) { - const b = new Uint8Array(bytes); - for (let i = 0; i < bytes; i++) { - b[i] = n >> 8 * (bytes - i - 1) & 0xFF; - } + assert$6(options.r && options.s, 'Signature without r or s'); + this.r = new bn(options.r, 16); + this.s = new bn(options.s, 16); + if (options.recoveryParam === undefined) + this.recoveryParam = null; + else + this.recoveryParam = options.recoveryParam; +} +var signature$1 = Signature$1; - return b; - }, +function Position() { + this.place = 0; +} - readDate: function readDate(bytes) { - const n = _util2.default.readNumber(bytes); - const d = new Date(n * 1000); - return d; - }, +function getLength(buf, p) { + var initial = buf[p.place++]; + if (!(initial & 0x80)) { + return initial; + } + var octetLen = initial & 0xf; + var val = 0; + for (var i = 0, off = p.place; i < octetLen; i++, off++) { + val <<= 8; + val |= buf[off]; + } + p.place = off; + return val; +} - writeDate: function writeDate(time) { - const numeric = Math.floor(time.getTime() / 1000); +function rmPadding(buf) { + var i = 0; + var len = buf.length - 1; + while (!buf[i] && !(buf[i + 1] & 0x80) && i < len) { + i++; + } + if (i === 0) { + return buf; + } + return buf.slice(i); +} - return _util2.default.writeNumber(numeric, 4); - }, +Signature$1.prototype._importDER = function _importDER(data, enc) { + data = utils_1$1.toArray(data, enc); + var p = new Position(); + if (data[p.place++] !== 0x30) { + return false; + } + var len = getLength(data, p); + if ((len + p.place) !== data.length) { + return false; + } + if (data[p.place++] !== 0x02) { + return false; + } + var rlen = getLength(data, p); + var r = data.slice(p.place, rlen + p.place); + p.place += rlen; + if (data[p.place++] !== 0x02) { + return false; + } + var slen = getLength(data, p); + if (data.length !== slen + p.place) { + return false; + } + var s = data.slice(p.place, slen + p.place); + if (r[0] === 0 && (r[1] & 0x80)) { + r = r.slice(1); + } + if (s[0] === 0 && (s[1] & 0x80)) { + s = s.slice(1); + } - normalizeDate: function normalizeDate(time = Date.now()) { - return time === null || time === Infinity ? time : new Date(Math.floor(+time / 1000) * 1000); - }, + this.r = new bn(r); + this.s = new bn(s); + this.recoveryParam = null; - /** - * Create hex string from a binary - * @param {String} str String to convert - * @returns {String} String containing the hexadecimal values - */ - str_to_hex: function str_to_hex(str) { - if (str === null) { - return ""; - } - const r = []; - const e = str.length; - let c = 0; - let h; - while (c < e) { - h = str.charCodeAt(c++).toString(16); - while (h.length < 2) { - h = "0" + h; - } - r.push("" + h); - } - return r.join(''); - }, + return true; +}; + +function constructLength(arr, len) { + if (len < 0x80) { + arr.push(len); + return; + } + var octets = 1 + (Math.log(len) / Math.LN2 >>> 3); + arr.push(octets | 0x80); + while (--octets) { + arr.push((len >>> (octets << 3)) & 0xff); + } + arr.push(len); +} - /** - * Create binary string from a hex encoded string - * @param {String} str Hex string to convert - * @returns {String} - */ - hex_to_str: function hex_to_str(hex) { - let str = ''; - for (let i = 0; i < hex.length; i += 2) { - str += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); - } - return str; - }, +Signature$1.prototype.toDER = function toDER(enc) { + var r = this.r.toArray(); + var s = this.s.toArray(); - /** - * Convert a Uint8Array to an MPI-formatted Uint8Array. - * Note: the output is **not** an MPI object. - * @see {@link module:type/mpi/MPI.fromUint8Array} - * @see {@link module:type/mpi/MPI.toUint8Array} - * @param {Uint8Array} bin An array of 8-bit integers to convert - * @returns {Uint8Array} MPI-formatted Uint8Array - */ - Uint8Array_to_MPI: function Uint8Array_to_MPI(bin) { - const size = (bin.length - 1) * 8 + _util2.default.nbits(bin[0]); - const prefix = Uint8Array.from([(size & 0xFF00) >> 8, size & 0xFF]); - return _util2.default.concatUint8Array([prefix, bin]); - }, + // Pad values + if (r[0] & 0x80) + r = [ 0 ].concat(r); + // Pad values + if (s[0] & 0x80) + s = [ 0 ].concat(s); - /** - * Convert a Base-64 encoded string an array of 8-bit integer - * - * Note: accepts both Radix-64 and URL-safe strings - * @param {String} base64 Base-64 encoded string to convert - * @returns {Uint8Array} An array of 8-bit integers - */ - b64_to_Uint8Array: function b64_to_Uint8Array(base64) { - return _base2.default.decode(base64.replace(/-/g, '+').replace(/_/g, '/')); - }, + r = rmPadding(r); + s = rmPadding(s); - /** - * Convert an array of 8-bit integer to a Base-64 encoded string - * @param {Uint8Array} bytes An array of 8-bit integers to convert - * @param {bool} url If true, output is URL-safe - * @returns {String} Base-64 encoded string - */ - Uint8Array_to_b64: function Uint8Array_to_b64(bytes, url) { - return _base2.default.encode(bytes, url).replace(/(\n)/g, ''); - }, + while (!s[0] && !(s[1] & 0x80)) { + s = s.slice(1); + } + var arr = [ 0x02 ]; + constructLength(arr, r.length); + arr = arr.concat(r); + arr.push(0x02); + constructLength(arr, s.length); + var backHalf = arr.concat(s); + var res = [ 0x30 ]; + constructLength(res, backHalf.length); + res = res.concat(backHalf); + return utils_1$1.encode(res, enc); +}; - /** - * Convert a hex string to an array of 8-bit integers - * @param {String} hex A hex string to convert - * @returns {Uint8Array} An array of 8-bit integers - */ - hex_to_Uint8Array: function hex_to_Uint8Array(hex) { - const result = new Uint8Array(hex.length >> 1); - for (let k = 0; k < hex.length >> 1; k++) { - result[k] = parseInt(hex.substr(k << 1, 2), 16); - } - return result; - }, +var assert$7 = utils_1$1.assert; - /** - * Convert an array of 8-bit integers to a hex string - * @param {Uint8Array} bytes Array of 8-bit integers to convert - * @returns {String} Hexadecimal representation of the array - */ - Uint8Array_to_hex: function Uint8Array_to_hex(bytes) { - const r = []; - const e = bytes.length; - let c = 0; - let h; - while (c < e) { - h = bytes[c++].toString(16); - while (h.length < 2) { - h = "0" + h; - } - r.push("" + h); - } - return r.join(''); - }, - /** - * Convert a string to an array of 8-bit integers - * @param {String} str String to convert - * @returns {Uint8Array} An array of 8-bit integers - */ - str_to_Uint8Array: function str_to_Uint8Array(str) { - return _webStreamTools2.default.transform(str, str => { - if (!_util2.default.isString(str)) { - throw new Error('str_to_Uint8Array: Data must be in the form of a string'); - } - const result = new Uint8Array(str.length); - for (let i = 0; i < str.length; i++) { - result[i] = str.charCodeAt(i); - } - return result; - }); - }, - /** - * Convert an array of 8-bit integers to a string - * @param {Uint8Array} bytes An array of 8-bit integers to convert - * @returns {String} String representation of the array - */ - Uint8Array_to_str: function Uint8Array_to_str(bytes) { - bytes = new Uint8Array(bytes); - const result = []; - const bs = 1 << 14; - const j = bytes.length; +function EC(options) { + if (!(this instanceof EC)) + return new EC(options); - for (let i = 0; i < j; i += bs) { - result.push(String.fromCharCode.apply(String, bytes.subarray(i, i + bs < j ? i + bs : j))); - } - return result.join(''); - }, + // Shortcut `elliptic.ec(curve-name)` + if (typeof options === 'string') { + assert$7(curves_1.hasOwnProperty(options), 'Unknown curve ' + options); - /** - * Convert a native javascript string to a Uint8Array of utf8 bytes - * @param {String|ReadableStream} str The string to convert - * @returns {Uint8Array|ReadableStream} A valid squence of utf8 bytes - */ - encode_utf8: function encode_utf8(str) { - const encoder = new TextEncoder('utf-8'); - // eslint-disable-next-line no-inner-declarations - function process(value, lastChunk = false) { - return encoder.encode(value, { stream: !lastChunk }); - } - return _webStreamTools2.default.transform(str, process, () => process('', true)); - }, + options = curves_1[options]; + } - /** - * Convert a Uint8Array of utf8 bytes to a native javascript string - * @param {Uint8Array|ReadableStream} utf8 A valid squence of utf8 bytes - * @returns {String|ReadableStream} A native javascript string - */ - decode_utf8: function decode_utf8(utf8) { - const decoder = new TextDecoder('utf-8'); - // eslint-disable-next-line no-inner-declarations - function process(value, lastChunk = false) { - return decoder.decode(value, { stream: !lastChunk }); - } - return _webStreamTools2.default.transform(utf8, process, () => process(new Uint8Array(), true)); - }, + // Shortcut for `elliptic.ec(elliptic.curves.curveName)` + if (options instanceof curves_1.PresetCurve) + options = { curve: options }; - /** - * Concat a list of Uint8Arrays, Strings or Streams - * The caller must not mix Uint8Arrays with Strings, but may mix Streams with non-Streams. - * @param {Array} Array of Uint8Arrays/Strings/Streams to concatenate - * @returns {Uint8Array|String|ReadableStream} Concatenated array - */ - concat: _webStreamTools2.default.concat, + this.curve = options.curve.curve; + this.n = this.curve.n; + this.nh = this.n.ushrn(1); + this.g = this.curve.g; - /** - * Concat Uint8Arrays - * @param {Array} Array of Uint8Arrays to concatenate - * @returns {Uint8Array} Concatenated array - */ - concatUint8Array: _webStreamTools2.default.concatUint8Array, + // Point on curve + this.g = options.curve.g; + this.g.precompute(options.curve.n.bitLength() + 1); - /** - * Check Uint8Array equality - * @param {Uint8Array} first array - * @param {Uint8Array} second array - * @returns {Boolean} equality - */ - equalsUint8Array: function equalsUint8Array(array1, array2) { - if (!_util2.default.isUint8Array(array1) || !_util2.default.isUint8Array(array2)) { - throw new Error('Data must be in the form of a Uint8Array'); - } + // Hash function for DRBG + this.hash = options.hash || options.curve.hash; +} +var ec = EC; - if (array1.length !== array2.length) { - return false; - } +EC.prototype.keyPair = function keyPair(options) { + return new key(this, options); +}; - for (let i = 0; i < array1.length; i++) { - if (array1[i] !== array2[i]) { - return false; - } - } - return true; - }, +EC.prototype.keyFromPrivate = function keyFromPrivate(priv, enc) { + return key.fromPrivate(this, priv, enc); +}; - /** - * Calculates a 16bit sum of a Uint8Array by adding each character - * codes modulus 65535 - * @param {Uint8Array} Uint8Array to create a sum of - * @returns {Uint8Array} 2 bytes containing the sum of all charcodes % 65535 - */ - write_checksum: function write_checksum(text) { - let s = 0; - for (let i = 0; i < text.length; i++) { - s = s + text[i] & 0xFFFF; - } - return _util2.default.writeNumber(s, 2); - }, +EC.prototype.keyFromPublic = function keyFromPublic(pub, enc) { + return key.fromPublic(this, pub, enc); +}; - /** - * Helper function to print a debug message. Debug - * messages are only printed if - * @link module:config/config.debug is set to true. - * @param {String} str String of the debug message - */ - print_debug: function print_debug(str) { - if (_config2.default.debug) { - console.log(str); - } - }, +EC.prototype.genKeyPair = function genKeyPair(options) { + if (!options) + options = {}; - /** - * Helper function to print a debug message. Debug - * messages are only printed if - * @link module:config/config.debug is set to true. - * Different than print_debug because will call Uint8Array_to_hex iff necessary. - * @param {String} str String of the debug message - */ - print_debug_hexarray_dump: function print_debug_hexarray_dump(str, arrToHex) { - if (_config2.default.debug) { - str += ': ' + _util2.default.Uint8Array_to_hex(arrToHex); - console.log(str); - } - }, + // Instantiate Hmac_DRBG + var drbg = new hmacDrbg({ + hash: this.hash, + pers: options.pers, + persEnc: options.persEnc || 'utf8', + entropy: options.entropy || brorand(this.hash.hmacStrength), + entropyEnc: options.entropy && options.entropyEnc || 'utf8', + nonce: this.n.toArray() + }); - /** - * Helper function to print a debug message. Debug - * messages are only printed if - * @link module:config/config.debug is set to true. - * Different than print_debug because will call str_to_hex iff necessary. - * @param {String} str String of the debug message - */ - print_debug_hexstr_dump: function print_debug_hexstr_dump(str, strToHex) { - if (_config2.default.debug) { - str += _util2.default.str_to_hex(strToHex); - console.log(str); - } - }, + // Key generation for curve25519 is simpler + if (this.curve.type === 'mont') { + var priv = new bn(drbg.generate(32)); + return this.keyFromPrivate(priv); + } - /** - * Helper function to print a debug error. Debug - * messages are only printed if - * @link module:config/config.debug is set to true. - * @param {String} str String of the debug message - */ - print_debug_error: function print_debug_error(error) { - if (_config2.default.debug) { - console.error(error); - } - }, + var bytes = this.n.byteLength(); + var ns2 = this.n.sub(new bn(2)); + do { + var priv = new bn(drbg.generate(bytes)); + if (priv.cmp(ns2) > 0) + continue; - /** - * Read a stream to the end and print it to the console when it's closed. - * @param {String} str String of the debug message - * @param {ReadableStream|Uint8array|String} input Stream to print - * @param {Function} concat Function to concatenate chunks of the stream (defaults to util.concat). - */ - print_entire_stream: function print_entire_stream(str, input, concat) { - _webStreamTools2.default.readToEnd(_webStreamTools2.default.clone(input), concat).then(result => { - console.log(str + ': ', result); - }); - }, + priv.iaddn(1); + return this.keyFromPrivate(priv); + } while (true); +}; - // returns bit length of the integer x - nbits: function nbits(x) { - let r = 1; - let t = x >>> 16; - if (t !== 0) { - x = t; - r += 16; - } - t = x >> 8; - if (t !== 0) { - x = t; - r += 8; - } - t = x >> 4; - if (t !== 0) { - x = t; - r += 4; - } - t = x >> 2; - if (t !== 0) { - x = t; - r += 2; - } - t = x >> 1; - if (t !== 0) { - x = t; - r += 1; - } - return r; - }, +EC.prototype._truncateToN = function truncateToN(msg, truncOnly, bitSize) { + bitSize = bitSize || msg.byteLength() * 8; + var delta = bitSize - this.n.bitLength(); + if (delta > 0) + msg = msg.ushrn(delta); + if (!truncOnly && msg.cmp(this.n) >= 0) + return msg.sub(this.n); + else + return msg; +}; + +EC.prototype.truncateMsg = function truncateMSG(msg) { + // Bit size is only determined correctly for Uint8Arrays and hex strings + var bitSize; + if (msg instanceof Uint8Array) { + bitSize = msg.byteLength * 8; + msg = this._truncateToN(new bn(msg, 16), false, bitSize); + } else if (typeof msg === 'string') { + bitSize = msg.length * 4; + msg = this._truncateToN(new bn(msg, 16), false, bitSize); + } else { + msg = this._truncateToN(new bn(msg, 16)); + } + return msg; +}; + +EC.prototype.sign = function sign(msg, key, enc, options) { + if (typeof enc === 'object') { + options = enc; + enc = null; + } + if (!options) + options = {}; - /** - * If S[1] == 0, then double(S) == (S[2..128] || 0); - * otherwise, double(S) == (S[2..128] || 0) xor - * (zeros(120) || 10000111). - * - * Both OCB and EAX (through CMAC) require this function to be constant-time. - * - * @param {Uint8Array} data - */ - double: function double(data) { - const double_var = new Uint8Array(data.length); - const last = data.length - 1; - for (let i = 0; i < last; i++) { - double_var[i] = data[i] << 1 ^ data[i + 1] >> 7; - } - double_var[last] = data[last] << 1 ^ (data[0] >> 7) * 0x87; - return double_var; - }, + key = this.keyFromPrivate(key, enc); + msg = this.truncateMsg(msg); - /** - * Shift a Uint8Array to the right by n bits - * @param {Uint8Array} array The array to shift - * @param {Integer} bits Amount of bits to shift (MUST be smaller - * than 8) - * @returns {String} Resulting array. - */ - shiftRight: function shiftRight(array, bits) { - if (bits) { - for (let i = array.length - 1; i >= 0; i--) { - array[i] >>= bits; - if (i > 0) { - array[i] |= array[i - 1] << 8 - bits; - } - } - } - return array; - }, + // Zero-extend key to provide enough entropy + var bytes = this.n.byteLength(); + var bkey = key.getPrivate().toArray('be', bytes); - /** - * Get native Web Cryptography api, only the current version of the spec. - * The default configuration is to use the api when available. But it can - * be deactivated with config.use_native - * @returns {Object} The SubtleCrypto api or 'undefined' - */ - getWebCrypto: function getWebCrypto() { - if (!_config2.default.use_native) { - return; - } + // Zero-extend nonce to have the same byte size as N + var nonce = msg.toArray('be', bytes); - return typeof window !== 'undefined' && window.crypto && window.crypto.subtle; - }, + // Instantiate Hmac_DRBG + var drbg = new hmacDrbg({ + hash: this.hash, + entropy: bkey, + nonce: nonce, + pers: options.pers, + persEnc: options.persEnc || 'utf8' + }); - /** - * Get native Web Cryptography api for all browsers, including legacy - * implementations of the spec e.g IE11 and Safari 8/9. The default - * configuration is to use the api when available. But it can be deactivated - * with config.use_native - * @returns {Object} The SubtleCrypto api or 'undefined' - */ - getWebCryptoAll: function getWebCryptoAll() { - if (!_config2.default.use_native) { - return; - } + // Number of bytes to generate + var ns1 = this.n.sub(new bn(1)); - if (typeof window !== 'undefined') { - if (window.crypto) { - return window.crypto.subtle || window.crypto.webkitSubtle; - } - if (window.msCrypto) { - return window.msCrypto.subtle; - } - } - }, + for (var iter = 0; true; iter++) { + var k = options.k ? + options.k(iter) : + new bn(drbg.generate(this.n.byteLength())); + k = this._truncateToN(k, true); + if (k.cmpn(1) <= 0 || k.cmp(ns1) >= 0) + continue; - /** - * Detect Node.js runtime. - */ - detectNode: function detectNode() { - return typeof global.process === 'object' && typeof global.process.versions === 'object'; - }, + var kp = this.g.mul(k); + if (kp.isInfinity()) + continue; - /** - * Get native Node.js module - * @param {String} The module to require - * @returns {Object} The required module or 'undefined' - */ - nodeRequire: function nodeRequire(module) { - if (!_util2.default.detectNode()) { - return; - } + var kpX = kp.getX(); + var r = kpX.umod(this.n); + if (r.cmpn(0) === 0) + continue; - // Requiring the module dynamically allows us to access the native node module. - // otherwise, it gets replaced with the browserified version - // eslint-disable-next-line import/no-dynamic-require - return require(module); - }, + var s = k.invm(this.n).mul(r.mul(key.getPrivate()).iadd(msg)); + s = s.umod(this.n); + if (s.cmpn(0) === 0) + continue; - /** - * Get native Node.js crypto api. The default configuration is to use - * the api when available. But it can also be deactivated with config.use_native - * @returns {Object} The crypto module or 'undefined' - */ - getNodeCrypto: function getNodeCrypto() { - if (!_config2.default.use_native) { - return; + var recoveryParam = (kp.getY().isOdd() ? 1 : 0) | + (kpX.cmp(r) !== 0 ? 2 : 0); + + // Use complement of `s`, if it is > `n / 2` + if (options.canonical && s.cmp(this.nh) > 0) { + s = this.n.sub(s); + recoveryParam ^= 1; } - return _util2.default.nodeRequire('crypto'); - }, + return new signature$1({ r: r, s: s, recoveryParam: recoveryParam }); + } +}; - getNodeZlib: function getNodeZlib() { - if (!_config2.default.use_native) { - return; - } +EC.prototype.verify = function verify(msg, signature, key, enc) { + key = this.keyFromPublic(key, enc); + signature = new signature$1(signature, 'hex'); + // Fallback to the old code + var ret = this._verify(this.truncateMsg(msg), signature, key) || + this._verify(this._truncateToN(new bn(msg, 16)), signature, key); + return ret; +}; - return _util2.default.nodeRequire('zlib'); - }, +EC.prototype._verify = function _verify(msg, signature, key) { + // Perform primitive values validation + var r = signature.r; + var s = signature.s; + if (r.cmpn(1) < 0 || r.cmp(this.n) >= 0) + return false; + if (s.cmpn(1) < 0 || s.cmp(this.n) >= 0) + return false; - /** - * Get native Node.js Buffer constructor. This should be used since - * Buffer is not available under browserify. - * @returns {Function} The Buffer constructor or 'undefined' - */ - getNodeBuffer: function getNodeBuffer() { - return (_util2.default.nodeRequire('buffer') || {}).Buffer; - }, + // Validate signature + var sinv = s.invm(this.n); + var u1 = sinv.mul(msg).umod(this.n); + var u2 = sinv.mul(r).umod(this.n); - getNodeStream: function getNodeStream() { - return (_util2.default.nodeRequire('stream') || {}).Readable; - }, + if (!this.curve._maxwellTrick) { + var p = this.g.mulAdd(u1, key.getPublic(), u2); + if (p.isInfinity()) + return false; - getHardwareConcurrency: function getHardwareConcurrency() { - if (_util2.default.detectNode()) { - const os = _util2.default.nodeRequire('os'); - return os.cpus().length; - } + return p.getX().umod(this.n).cmp(r) === 0; + } - return navigator.hardwareConcurrency || 1; - }, + // NOTE: Greg Maxwell's trick, inspired by: + // https://git.io/vad3K - isEmailAddress: function isEmailAddress(data) { - if (!_util2.default.isString(data)) { - return false; - } - const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+([a-zA-Z]{2,}|xn--[a-zA-Z\-0-9]+)))$/; - return re.test(data); - }, + var p = this.g.jmulAdd(u1, key.getPublic(), u2); + if (p.isInfinity()) + return false; - /** - * Format user id for internal use. - */ - formatUserId: function formatUserId(id) { - // name, email address and comment can be empty but must be of the correct type - if (id.name && !_util2.default.isString(id.name) || id.email && !_util2.default.isEmailAddress(id.email) || id.comment && !_util2.default.isString(id.comment)) { - throw new Error('Invalid user id format'); - } - const components = []; - if (id.name) { - components.push(id.name); - } - if (id.comment) { - components.push(`(${id.comment})`); - } - if (id.email) { - components.push(`<${id.email}>`); - } - return components.join(' '); - }, + // Compare `p.x` of Jacobian point with `r`, + // this will do `p.x == r * p.z^2` instead of multiplying `p.x` by the + // inverse of `p.z^2` + return p.eqXToP(r); +}; - /** - * Parse user id. - */ - parseUserId: function parseUserId(userid) { - if (userid.length > _config2.default.max_userid_length) { - throw new Error('User id string is too long'); - } - try { - var _emailAddresses$parse = _emailAddresses2.default.parseOneAddress(userid); +EC.prototype.recoverPubKey = function(msg, signature, j, enc) { + assert$7((3 & j) === j, 'The recovery param is more than two bits'); + signature = new signature$1(signature, enc); - const name = _emailAddresses$parse.name, - email = _emailAddresses$parse.address, - comments = _emailAddresses$parse.comments; + var n = this.n; + var e = new bn(msg); + var r = signature.r; + var s = signature.s; - return { name, email, comment: comments.replace(/^\(|\)$/g, '') }; - } catch (e) { - throw new Error('Invalid user id format'); - } - }, + // A set LSB signifies that the y-coordinate is odd + var isYOdd = j & 1; + var isSecondKey = j >> 1; + if (r.cmp(this.curve.p.umod(this.curve.n)) >= 0 && isSecondKey) + throw new Error('Unable to find sencond key candinate'); - /** - * Normalize line endings to \r\n - */ - canonicalizeEOL: function canonicalizeEOL(text) { - return _webStreamTools2.default.transform(_util2.default.nativeEOL(text), value => value.replace(/\r/g, "\n").replace(/\n/g, "\r\n")); - }, + // 1.1. Let x = r + jn. + if (isSecondKey) + r = this.curve.pointFromX(r.add(this.curve.n), isYOdd); + else + r = this.curve.pointFromX(r, isYOdd); - /** - * Convert line endings from canonicalized \r\n to native \n - */ - nativeEOL: function nativeEOL(text) { - let lastChar = ''; - return _webStreamTools2.default.transform(text, value => { - value = lastChar + value; - if (value[value.length - 1] === '\r') { - lastChar = '\r'; - value = value.slice(0, -1); - } else { - lastChar = ''; - } - return value.replace(/\r\n/g, '\n'); - }, () => lastChar); - }, + var rInv = signature.r.invm(n); + var s1 = n.sub(e).mul(rInv).umod(n); + var s2 = s.mul(rInv).umod(n); - /** - * Remove trailing spaces and tabs from each line - */ - removeTrailingSpaces: function removeTrailingSpaces(text) { - return text.split('\n').map(line => { - let i = line.length - 1; - for (; i >= 0 && (line[i] === ' ' || line[i] === '\t'); i--); - return line.substr(0, i + 1); - }).join('\n'); - }, + // 1.6.1 Compute Q = r^-1 (sR - eG) + // Q = r^-1 (sR + -eG) + return this.g.mulAdd(s1, r, s2); +}; - /** - * Encode input buffer using Z-Base32 encoding. - * See: https://tools.ietf.org/html/rfc6189#section-5.1.6 - * - * @param {Uint8Array} data The binary data to encode - * @returns {String} Binary data encoded using Z-Base32 - */ - encodeZBase32: function encodeZBase32(data) { - if (data.length === 0) { - return ""; - } - const ALPHABET = "ybndrfg8ejkmcpqxot1uwisza345h769"; - const SHIFT = 5; - const MASK = 31; - let buffer = data[0]; - let index = 1; - let bitsLeft = 8; - let result = ''; - while (bitsLeft > 0 || index < data.length) { - if (bitsLeft < SHIFT) { - if (index < data.length) { - buffer <<= 8; - buffer |= data[index++] & 0xff; - bitsLeft += 8; - } else { - const pad = SHIFT - bitsLeft; - buffer <<= pad; - bitsLeft += pad; - } - } - bitsLeft -= SHIFT; - result += ALPHABET[MASK & buffer >> bitsLeft]; +EC.prototype.getKeyRecoveryParam = function(e, signature, Q, enc) { + signature = new signature$1(signature, enc); + if (signature.recoveryParam !== null) + return signature.recoveryParam; + + for (var i = 0; i < 4; i++) { + var Qprime; + try { + Qprime = this.recoverPubKey(e, signature, i); + } catch (e) { + continue; } - return result; + + if (Qprime.eq(Q)) + return i; } -}; // re-import module to access util functions -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + throw new Error('Unable to find valid recovery factor'); +}; + +var assert$8 = utils_1$1.assert; +var parseBytes = utils_1$1.parseBytes; +var cachedProperty = utils_1$1.cachedProperty; + +/** +* @param {EDDSA} eddsa - instance +* @param {Object} params - public/private key parameters +* +* @param {Array} [params.secret] - secret seed bytes +* @param {Point} [params.pub] - public key point (aka `A` in eddsa terms) +* @param {Array} [params.pub] - public key point encoded as bytes +* +*/ +function KeyPair$1(eddsa, params) { + this.eddsa = eddsa; + if (params.hasOwnProperty('secret')) + this._secret = parseBytes(params.secret); + if (eddsa.isPoint(params.pub)) + this._pub = params.pub; + else { + this._pubBytes = parseBytes(params.pub); + if (this._pubBytes && this._pubBytes.length === 33 && + this._pubBytes[0] === 0x40) + this._pubBytes = this._pubBytes.slice(1, 33); + if (this._pubBytes && this._pubBytes.length !== 32) + throw new Error('Unknown point compression format'); + } +} -/* eslint-disable no-console */ +KeyPair$1.fromPublic = function fromPublic(eddsa, pub) { + if (pub instanceof KeyPair$1) + return pub; + return new KeyPair$1(eddsa, { pub: pub }); +}; -/** - * This object contains utility functions - * @requires email-addresses - * @requires web-stream-tools - * @requires config - * @requires encoding/base64 - * @module util - */ +KeyPair$1.fromSecret = function fromSecret(eddsa, secret) { + if (secret instanceof KeyPair$1) + return secret; + return new KeyPair$1(eddsa, { secret: secret }); +}; -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./config":79,"./encoding/base64":112,"./util":152,"email-addresses":33,"web-stream-tools":75}],153:[function(require,module,exports){ -'use strict'; +KeyPair$1.prototype.secret = function secret() { + return this._secret; +}; -Object.defineProperty(exports, "__esModule", { - value: true +cachedProperty(KeyPair$1, 'pubBytes', function pubBytes() { + return this.eddsa.encodePoint(this.pub()); }); -var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); // OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2018 Wiktor Kwapisiewicz -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +cachedProperty(KeyPair$1, 'pub', function pub() { + if (this._pubBytes) + return this.eddsa.decodePoint(this._pubBytes); + return this.eddsa.g.mul(this.priv()); +}); -/** - * @fileoverview This class implements a client for the Web Key Directory (wkd) protocol - * in order to lookup keys on designated servers. - * See: https://datatracker.ietf.org/doc/draft-koch-openpgp-webkey-service/ - * @module wkd - */ +cachedProperty(KeyPair$1, 'privBytes', function privBytes() { + var eddsa = this.eddsa; + var hash = this.hash(); + var lastIx = eddsa.encodingLength - 1; + + // https://tools.ietf.org/html/rfc8032#section-5.1.5 + var a = hash.slice(0, eddsa.encodingLength); + a[0] &= 248; + a[lastIx] &= 127; + a[lastIx] |= 64; -var _util = require('./util'); + return a; +}); + +cachedProperty(KeyPair$1, 'priv', function priv() { + return this.eddsa.decodeInt(this.privBytes()); +}); -var _util2 = _interopRequireDefault(_util); +cachedProperty(KeyPair$1, 'hash', function hash() { + return this.eddsa.hash().update(this.secret()).digest(); +}); -var _crypto = require('./crypto'); +cachedProperty(KeyPair$1, 'messagePrefix', function messagePrefix() { + return this.hash().slice(this.eddsa.encodingLength); +}); -var _crypto2 = _interopRequireDefault(_crypto); +KeyPair$1.prototype.sign = function sign(message) { + assert$8(this._secret, 'KeyPair can only verify'); + return this.eddsa.sign(message, this); +}; -var _key = require('./key'); +KeyPair$1.prototype.verify = function verify(message, sig) { + return this.eddsa.verify(message, sig, this); +}; -var keyMod = _interopRequireWildcard(_key); +KeyPair$1.prototype.getSecret = function getSecret(enc) { + assert$8(this._secret, 'KeyPair is public only'); + return utils_1$1.encode(this.secret(), enc); +}; -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } +KeyPair$1.prototype.getPublic = function getPublic(enc, compact) { + return utils_1$1.encode((compact ? [ 0x40 ] : []).concat(this.pubBytes()), enc); +}; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +var key$1 = KeyPair$1; -/** - * Initialize the WKD client - * @constructor - */ -function WKD() { - this._fetch = typeof window !== 'undefined' ? window.fetch : require('node-fetch'); -} +var assert$9 = utils_1$1.assert; +var cachedProperty$1 = utils_1$1.cachedProperty; +var parseBytes$1 = utils_1$1.parseBytes; /** - * Search for a public key using Web Key Directory protocol. - * @param {String} options.email User's email. - * @param {Boolean} options.rawBytes Returns Uint8Array instead of parsed key. - * @returns {Promise, - * err: (Array|null)}>} The public key. - * @async - */ -WKD.prototype.lookup = async function (options) { - const fetch = this._fetch; +* @param {EDDSA} eddsa - eddsa instance +* @param {Array|Object} sig - +* @param {Array|Point} [sig.R] - R point as Point or bytes +* @param {Array|bn} [sig.S] - S scalar as bn or bytes +* @param {Array} [sig.Rencoded] - R point encoded +* @param {Array} [sig.Sencoded] - S scalar encoded +*/ +function Signature$2(eddsa, sig) { + this.eddsa = eddsa; - if (!options.email) { - throw new Error('You must provide an email parameter!'); - } + if (typeof sig !== 'object') + sig = parseBytes$1(sig); - if (!_util2.default.isEmailAddress(options.email)) { - throw new Error('Invalid e-mail address.'); + if (Array.isArray(sig)) { + sig = { + R: sig.slice(0, eddsa.encodingLength), + S: sig.slice(eddsa.encodingLength) + }; } - var _$exec = /(.*)@(.*)/.exec(options.email), - _$exec2 = _slicedToArray(_$exec, 3); - - const localPart = _$exec2[1], - domain = _$exec2[2]; + assert$9(sig.R && sig.S, 'Signature without R or S'); - const localEncoded = _util2.default.encodeZBase32((await _crypto2.default.hash.sha1(_util2.default.str_to_Uint8Array(localPart.toLowerCase())))); + if (eddsa.isPoint(sig.R)) + this._R = sig.R; + if (sig.S instanceof bn) + this._S = sig.S; - const url = `https://${domain}/.well-known/openpgpkey/hu/${localEncoded}`; + this._Rencoded = Array.isArray(sig.R) ? sig.R : sig.Rencoded; + this._Sencoded = Array.isArray(sig.S) ? sig.S : sig.Sencoded; +} - return fetch(url).then(function (response) { - if (response.status === 200) { - return response.arrayBuffer(); - } - }).then(function (publicKey) { - if (publicKey) { - const rawBytes = new Uint8Array(publicKey); - if (options.rawBytes) { - return rawBytes; - } - return keyMod.read(rawBytes); - } - }); -}; +cachedProperty$1(Signature$2, 'S', function S() { + return this.eddsa.decodeInt(this.Sencoded()); +}); -exports.default = WKD; +cachedProperty$1(Signature$2, 'R', function R() { + return this.eddsa.decodePoint(this.Rencoded()); +}); -},{"./crypto":94,"./key":116,"./util":152,"node-fetch":"node-fetch"}],154:[function(require,module,exports){ -'use strict'; +cachedProperty$1(Signature$2, 'Rencoded', function Rencoded() { + return this.eddsa.encodePoint(this.R()); +}); -Object.defineProperty(exports, "__esModule", { - value: true +cachedProperty$1(Signature$2, 'Sencoded', function Sencoded() { + return this.eddsa.encodeInt(this.S()); }); -var _util = require('../util.js'); +Signature$2.prototype.toBytes = function toBytes() { + return this.Rencoded().concat(this.Sencoded()); +}; + +Signature$2.prototype.toHex = function toHex() { + return utils_1$1.encode(this.toBytes(), 'hex').toUpperCase(); +}; + +var signature$2 = Signature$2; -var _util2 = _interopRequireDefault(_util); +var assert$a = utils_1$1.assert; +var parseBytes$2 = utils_1$1.parseBytes; -var _config = require('../config'); -var _config2 = _interopRequireDefault(_config); -var _crypto = require('../crypto'); +function EDDSA(curve) { + assert$a(curve === 'ed25519', 'only tested with ed25519 so far'); -var _crypto2 = _interopRequireDefault(_crypto); + if (!(this instanceof EDDSA)) + return new EDDSA(curve); -var _packet = require('../packet'); + var curve = curves_1[curve].curve; + this.curve = curve; + this.g = curve.g; + this.g.precompute(curve.n.bitLength() + 1); -var _packet2 = _interopRequireDefault(_packet); + this.pointClass = curve.point().constructor; + this.encodingLength = Math.ceil(curve.n.bitLength() / 8); + this.hash = hash_1.sha512; +} -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +var eddsa$1 = EDDSA; /** - * Initializes a new proxy and loads the web worker - * @param {String} path The path to the worker or 'openpgp.worker.js' by default - * @param {Number} n number of workers to initialize if path given - * @param {Object} config config The worker configuration - * @param {Array} worker alternative to path parameter: web worker initialized with 'openpgp.worker.js' - * @constructor - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* @param {Array|String} message - message bytes +* @param {Array|String|KeyPair} secret - secret bytes or a keypair +* @returns {Signature} - signature +*/ +EDDSA.prototype.sign = function sign(message, secret) { + message = parseBytes$2(message); + var key = this.keyFromSecret(secret); + var r = this.hashInt(key.messagePrefix(), message); + var R = this.g.mul(r); + var Rencoded = this.encodePoint(R); + var s_ = this.hashInt(Rencoded, key.pubBytes(), message) + .mul(key.priv()); + var S = r.add(s_).umod(this.curve.n); + return this.makeSignature({ R: R, S: S, Rencoded: Rencoded }); +}; /** - * @fileoverview Provides functions for maintaining browser workers - * @see module:openpgp.initWorker - * @see module:openpgp.getWorker - * @see module:openpgp.destroyWorker - * @see module:worker/worker - * @requires util - * @requires config - * @requires crypto - * @requires packet - * @module worker/async_proxy - */ +* @param {Array} message - message bytes +* @param {Array|String|Signature} sig - sig bytes +* @param {Array|String|Point|KeyPair} pub - public key +* @returns {Boolean} - true if public key matches sig of message +*/ +EDDSA.prototype.verify = function verify(message, sig, pub) { + message = parseBytes$2(message); + sig = this.makeSignature(sig); + var key = this.keyFromPublic(pub); + var h = this.hashInt(sig.Rencoded(), key.pubBytes(), message); + var SG = this.g.mul(sig.S()); + var RplusAh = sig.R().add(key.pub().mul(h)); + return RplusAh.eq(SG); +}; -function AsyncProxy({ path = 'openpgp.worker.js', n = 1, workers = [], config } = {}) { - /** - * Message handling - */ - const handleMessage = workerId => event => { - const msg = event.data; - switch (msg.event) { - case 'loaded': - this.workers[workerId].loadedResolve(true); - break; - case 'method-return': - if (msg.err) { - // fail - const err = new Error(msg.err); - // add worker stack - err.workerStack = msg.stack; - this.tasks[msg.id].reject(err); - } else { - // success - this.tasks[msg.id].resolve(msg.data); - } - delete this.tasks[msg.id]; - this.workers[workerId].requests--; - break; - case 'request-seed': - this.seedRandom(workerId, msg.amount); - break; - default: - throw new Error('Unknown Worker Event.'); - } - }; +EDDSA.prototype.hashInt = function hashInt() { + var hash = this.hash(); + for (var i = 0; i < arguments.length; i++) + hash.update(arguments[i]); + return utils_1$1.intFromLE(hash.digest()).umod(this.curve.n); +}; - if (workers.length) { - this.workers = workers; - } else { - this.workers = []; - while (this.workers.length < n) { - this.workers.push(new Worker(path)); - } - } +EDDSA.prototype.keyPair = function keyPair(options) { + return new key$1(this, options); +}; - let workerId = 0; - this.workers.forEach(worker => { - worker.loadedPromise = new Promise(resolve => { - worker.loadedResolve = resolve; - }); - worker.requests = 0; - worker.onmessage = handleMessage(workerId++); - worker.onerror = e => { - worker.loadedResolve(false); - console.error('Unhandled error in openpgp worker: ' + e.message + ' (' + e.filename + ':' + e.lineno + ')'); - return false; - }; +EDDSA.prototype.keyFromPublic = function keyFromPublic(pub) { + return key$1.fromPublic(this, pub); +}; - if (config) { - worker.postMessage({ event: 'configure', config }); - } +EDDSA.prototype.keyFromSecret = function keyFromSecret(secret) { + return key$1.fromSecret(this, secret); +}; + +EDDSA.prototype.genKeyPair = function genKeyPair(options) { + if (!options) + options = {}; + + // Instantiate Hmac_DRBG + var drbg = new hmacDrbg({ + hash: this.hash, + pers: options.pers, + persEnc: options.persEnc || 'utf8', + entropy: options.entropy || brorand(this.hash.hmacStrength), + entropyEnc: options.entropy && options.entropyEnc || 'utf8', + nonce: this.curve.n.toArray() }); - // Cannot rely on task order being maintained, use object keyed by request ID to track tasks - this.tasks = {}; - this.currentID = 0; -} + return this.keyFromSecret(drbg.generate(32)); +}; -/** - * Returns a promise that resolves when all workers have finished loading - * @returns {Promise} Resolves to true if all workers have loaded succesfully; false otherwise -*/ -AsyncProxy.prototype.loaded = async function () { - const loaded = await Promise.all(this.workers.map(worker => worker.loadedPromise)); - return loaded.every(Boolean); +EDDSA.prototype.makeSignature = function makeSignature(sig) { + if (sig instanceof signature$2) + return sig; + return new signature$2(this, sig); }; /** - * Get new request ID - * @returns {integer} New unique request ID +* * https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03#section-5.2 +* +* EDDSA defines methods for encoding and decoding points and integers. These are +* helper convenience methods, that pass along to utility functions implied +* parameters. +* */ -AsyncProxy.prototype.getID = function () { - return this.currentID++; +EDDSA.prototype.encodePoint = function encodePoint(point) { + var enc = point.getY().toArray('le', this.encodingLength); + enc[this.encodingLength - 1] |= point.getX().isOdd() ? 0x80 : 0; + return enc; }; -/** - * Send message to worker with random data - * @param {Integer} size Number of bytes to send - * @async - */ -AsyncProxy.prototype.seedRandom = async function (workerId, size) { - const buf = await _crypto2.default.random.getRandomBytes(size); - this.workers[workerId].postMessage({ event: 'seed-random', buf }, _util2.default.getTransferables(buf, true)); +EDDSA.prototype.decodePoint = function decodePoint(bytes) { + bytes = utils_1$1.parseBytes(bytes); + + var lastIx = bytes.length - 1; + var normed = bytes.slice(0, lastIx).concat(bytes[lastIx] & ~0x80); + var xIsOdd = (bytes[lastIx] & 0x80) !== 0; + + var y = utils_1$1.intFromLE(normed); + return this.curve.pointFromY(y, xIsOdd); }; -/** - * Terminates the workers - */ -AsyncProxy.prototype.terminate = function () { - this.workers.forEach(worker => { - worker.terminate(); - }); +EDDSA.prototype.encodeInt = function encodeInt(num) { + return num.toArray('le', this.encodingLength); }; -/** - * Generic proxy function that handles all commands from the public api. - * @param {String} method the public api function to be delegated to the worker thread - * @param {Object} options the api function's options - * @returns {Promise} see the corresponding public api functions for their return types - * @async - */ -AsyncProxy.prototype.delegate = function (method, options) { +EDDSA.prototype.decodeInt = function decodeInt(bytes) { + return utils_1$1.intFromLE(bytes); +}; - const id = this.getID(); - const requests = this.workers.map(worker => worker.requests); - const minRequests = Math.min(...requests); - let workerId = 0; - for (; workerId < this.workers.length; workerId++) { - if (this.workers[workerId].requests === minRequests) { - break; - } - } +EDDSA.prototype.isPoint = function isPoint(val) { + return val instanceof this.pointClass; +}; - return new Promise((_resolve, reject) => { - // clone packets (for web worker structured cloning algorithm) - this.workers[workerId].postMessage({ id: id, event: method, options: _packet2.default.clone.clonePackets(options) }, _util2.default.getTransferables(options, _config2.default.zero_copy)); - this.workers[workerId].requests++; +var elliptic_1 = createCommonjsModule(function (module, exports) { - // remember to handle parsing cloned packets from worker - this.tasks[id] = { resolve: data => _resolve(_packet2.default.clone.parseClonedPackets(_util2.default.restoreStreams(data), method)), reject }; - }); -}; +var elliptic = exports; -exports.default = AsyncProxy; +elliptic.utils = utils_1$1; +elliptic.rand = brorand; +elliptic.curve = curve_1; +elliptic.curves = curves_1; + +// Protocols +elliptic.ec = ec; +elliptic.eddsa = eddsa$1; +}); -},{"../config":79,"../crypto":94,"../packet":125,"../util.js":152}]},{},[115])(115) +var elliptic$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + 'default': elliptic_1, + __moduleExports: elliptic_1 }); + +exports.AEADEncryptedDataPacket = AEADEncryptedDataPacket; +exports.CleartextMessage = CleartextMessage; +exports.CompressedDataPacket = CompressedDataPacket; +exports.LiteralDataPacket = LiteralDataPacket; +exports.MarkerPacket = MarkerPacket; +exports.Message = Message; +exports.OnePassSignaturePacket = OnePassSignaturePacket; +exports.PacketList = PacketList; +exports.PrivateKey = PrivateKey; +exports.PublicKey = PublicKey; +exports.PublicKeyEncryptedSessionKeyPacket = PublicKeyEncryptedSessionKeyPacket; +exports.PublicKeyPacket = PublicKeyPacket; +exports.PublicSubkeyPacket = PublicSubkeyPacket; +exports.SecretKeyPacket = SecretKeyPacket; +exports.SecretSubkeyPacket = SecretSubkeyPacket; +exports.Signature = Signature; +exports.SignaturePacket = SignaturePacket; +exports.Subkey = Subkey; +exports.SymEncryptedIntegrityProtectedDataPacket = SymEncryptedIntegrityProtectedDataPacket; +exports.SymEncryptedSessionKeyPacket = SymEncryptedSessionKeyPacket; +exports.SymmetricallyEncryptedDataPacket = SymmetricallyEncryptedDataPacket; +exports.TrustPacket = TrustPacket; +exports.UserAttributePacket = UserAttributePacket; +exports.UserIDPacket = UserIDPacket; +exports.armor = armor; +exports.config = defaultConfig; +exports.createCleartextMessage = createCleartextMessage; +exports.createMessage = createMessage; +exports.decrypt = decrypt$4; +exports.decryptKey = decryptKey; +exports.decryptSessionKeys = decryptSessionKeys; +exports.encrypt = encrypt$4; +exports.encryptKey = encryptKey; +exports.encryptSessionKey = encryptSessionKey; +exports.enums = enums; +exports.generateKey = generateKey; +exports.generateSessionKey = generateSessionKey$1; +exports.readCleartextMessage = readCleartextMessage; +exports.readKey = readKey; +exports.readKeys = readKeys; +exports.readMessage = readMessage; +exports.readPrivateKey = readPrivateKey; +exports.readPrivateKeys = readPrivateKeys; +exports.readSignature = readSignature; +exports.reformatKey = reformatKey; +exports.revokeKey = revokeKey; +exports.sign = sign$5; +exports.unarmor = unarmor; +exports.verify = verify$5; From c091b3de6c79057ff819092f7e07d9965c46f7d8 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 3 Feb 2022 19:44:04 +0200 Subject: [PATCH 003/179] add old version for reference --- Core/source/core/types/openpgpv4.d.ts | 1131 + Core/source/lib/openpgpv4.js | 42866 ++++++++++++++++++++++++ 2 files changed, 43997 insertions(+) create mode 100644 Core/source/core/types/openpgpv4.d.ts create mode 100644 Core/source/lib/openpgpv4.js diff --git a/Core/source/core/types/openpgpv4.d.ts b/Core/source/core/types/openpgpv4.d.ts new file mode 100644 index 000000000..6b0926394 --- /dev/null +++ b/Core/source/core/types/openpgpv4.d.ts @@ -0,0 +1,1131 @@ +// Type definitions for openpgpjs +// Project: http://openpgpjs.org/ +// Definitions by: Guillaume Lacasa +// Errietta Kostala +// FlowCrypt Limited +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +/* tslint:disable:only-arrow-functions variable-name max-line-length no-null-keyword ban-types */ + +declare namespace OpenPGP { + + type DataPacketType = 'utf8' | 'binary' | 'text' | 'mime'; + + export interface UserId { + name?: string; + email?: string; + } + + export interface SessionKey { + data: Uint8Array; + algorithm: string; + } + + interface BaseStream { } + interface WebStream extends BaseStream { // copied+simplified version of ReadableStream from lib.dom.d.ts + readonly locked: boolean; cancel(reason?: any): Promise; getReader: Function; pipeThrough: Function; pipeTo: Function; tee: Function; + } + interface NodeStream extends BaseStream { // copied+simplified version of ReadableStream from @types/node/index.d.ts + readable: boolean; read(size?: number): string | Uint8Array; setEncoding(encoding: string): this; pause(): this; resume(): this; + isPaused(): boolean; pipe: Function; unpipe: Function; unshift(chunk: string | Uint8Array): void; wrap: Function; + } + type Stream = WebStream | NodeStream; + + /** + * EncryptArmorOptions or EncryptBinaryOptions will be used based on armor option (boolean), defaults to armoring + */ + interface BaseEncryptOptions { + /** message to be encrypted as created by openpgp.message.fromText or openpgp.message.fromBinary */ + message: message.Message; + /** (optional) array of keys or single key, used to encrypt the message */ + publicKeys?: key.Key | key.Key[]; + /** (optional) private keys for signing. If omitted message will not be signed */ + privateKeys?: key.Key | key.Key[]; + /** (optional) array of passwords or a single password to encrypt the message */ + passwords?: string | string[]; + /** (optional) session key in the form: { data:Uint8Array, algorithm:String } */ + sessionKey?: SessionKey; + /** (optional) which compression algorithm to compress the message with, defaults to what is specified in config */ + compression?: enums.compression; + /** (optional) whether to return data as a stream. Defaults to the type of stream `message` was created from, if any. */ + streaming?: 'web' | 'node' | false; + /** (optional) if the signature should be detached (if true, signature will be added to returned object) */ + detached?: boolean; + /** (optional) a detached signature to add to the encrypted message */ + signature?: signature.Signature; + /** (optional) if the unencrypted session key should be added to returned object */ + returnSessionKey?: boolean; + /** (optional) encrypt as of a certain date */ + date?: Date; + /** (optional) use a key ID of 0 instead of the public key IDs */ + wildcard?: boolean; + /** (optional) user ID to sign with, e.g. { name:'Steve Sender', email:'steve@openpgp.org' } */ + fromUserId?: UserId; + /** (optional) user ID to encrypt for, e.g. { name:'Robert Receiver', email:'robert@openpgp.org' } */ + toUserId?: UserId; + } + + export type EncryptOptions = BaseEncryptOptions | EncryptArmorOptions | EncryptBinaryOptions; + + export interface EncryptArmorOptions extends BaseEncryptOptions { + /** if the return values should be ascii armored or the message/signature objects */ + armor: true; + } + + export interface EncryptBinaryOptions extends BaseEncryptOptions { + /** if the return values should be ascii armored or the message/signature objects */ + armor: false; + } + + export namespace packet { + + export class List extends Array { + [index: number]: PACKET_TYPE; + length: number; + read(bytes: Uint8Array): void; + write(): Uint8Array; + push(...packet: PACKET_TYPE[]): number; + pop(): PACKET_TYPE; + filter(callback: (packet: PACKET_TYPE, i: number, self: List) => void): List; + filterByTag(...args: enums.packet[]): List; + forEach(callback: (packet: PACKET_TYPE, i: number, self: List) => void): void; + map(callback: (packet: PACKET_TYPE, i: number, self: List) => RETURN_TYPE): List; + // some() + // every() + // findPacket() + // indexOfTag() + // slice() + // concat() + // fromStructuredClone() + } + + function fromStructuredClone(packetClone: object): AnyPacket; + + function newPacketFromTag(tag: enums.packetNames): AnyPacket; + + class BasePacket { + tag: enums.packet; + read(bytes: Uint8Array): void; + write(): Uint8Array; + } + + class BaseKeyPacket extends BasePacket { + // fingerprint: Uint8Array|null; - not included because not recommended to use. Use getFingerprint() or getFingerprintBytes() + algorithm: enums.publicKey; + created: Date; + getBitSize(): number; + getAlgorithmInfo(): key.AlgorithmInfo; + getFingerprint(): string; + getFingerprintBytes(): Uint8Array | null; + getCreationTime(): Date; + getKeyId(): Keyid; + + version: number; + expirationTimeV3: number | null; + keyExpirationTime: number | null; + } + + class BasePrimaryKeyPacket extends BaseKeyPacket { + } + + export class Compressed extends BasePacket { + tag: enums.packet.compressed; + } + + export class SymEncryptedIntegrityProtected extends BasePacket { + tag: enums.packet.symEncryptedIntegrityProtected; + } + + export class SymEncryptedAEADProtected extends BasePacket { + tag: enums.packet.symEncryptedAEADProtected; + } + + export class PublicKeyEncryptedSessionKey extends BasePacket { + tag: enums.packet.publicKeyEncryptedSessionKey; + } + + export class SymEncryptedSessionKey extends BasePacket { + tag: enums.packet.symEncryptedSessionKey; + } + + export class Literal extends BasePacket { + tag: enums.packet.literal; + } + + export class PublicKey extends BasePrimaryKeyPacket { + tag: enums.packet.publicKey; + isDecrypted(): null; + } + + export class SymmetricallyEncrypted extends BasePacket { + tag: enums.packet.symmetricallyEncrypted; + } + + export class Marker extends BasePacket { + tag: enums.packet.marker; + } + + export class PublicSubkey extends BaseKeyPacket { + tag: enums.packet.publicSubkey; + isDecrypted(): null; + } + + export class UserAttribute extends BasePacket { + tag: enums.packet.userAttribute; + } + + export class OnePassSignature extends BasePacket { + tag: enums.packet.onePassSignature; + correspondingSig?: Promise; + } + + export class SecretKey extends BasePrimaryKeyPacket { + tag: enums.packet.secretKey; + isDecrypted(): boolean; + encrypt(passphrase: string): Promise; + decrypt(passphrase: string): Promise; + // encrypted: null | unknown[]; // Encrypted secret-key data, not meant for public use + s2k: { type: string } | null; + } + + export class Userid extends BasePacket { + tag: enums.packet.userid; + userid: string; + } + + export class SecretSubkey extends BaseKeyPacket { + tag: enums.packet.secretSubkey; + isDecrypted(): boolean; + encrypt(passphrase: string): Promise; + decrypt(passphrase: string): Promise; + // encrypted: null | unknown[]; // Encrypted secret-key data, not meant for public use + s2k: { type: string } | null; + } + + export class Signature extends BasePacket { + tag: enums.packet.signature; + version: number; + signatureType: null | number; + hashAlgorithm: null | number; + publicKeyAlgorithm: null | number; + signatureData: null | Uint8Array; + unhashedSubpackets: null | Uint8Array; + signedHashValue: null | Uint8Array; + created: Date; + signatureExpirationTime: null | number; + signatureNeverExpires: boolean; + exportable: null | boolean; + trustLevel: null | number; + trustAmount: null | number; + regularExpression: null | number; + revocable: null | boolean; + keyExpirationTime: null | number; + keyNeverExpires: null | boolean; + preferredSymmetricAlgorithms: null | number[]; + revocationKeyClass: null | number; + revocationKeyAlgorithm: null | number; + revocationKeyFingerprint: null | Uint8Array; + issuerKeyId: Keyid; + notation: null | { [name: string]: string }; + preferredHashAlgorithms: null | number[]; + preferredCompressionAlgorithms: null | number[]; + keyServerPreferences: null | number[]; + preferredKeyServer: null | string; + isPrimaryUserID: null | boolean; + policyURI: null | string; + keyFlags: null | number[]; + signersUserId: null | string; + reasonForRevocationFlag: null | number; + reasonForRevocationString: null | string; + features: null | number[]; + signatureTargetPublicKeyAlgorithm: null | number; + signatureTargetHashAlgorithm: null | number; + signatureTargetHash: null | string; + embeddedSignature: null | Signature; + issuerKeyVersion: null | number; + issuerFingerprint: null | Uint8Array; + preferredAeadAlgorithms: null | Uint8Array; + verified: null | boolean; + revoked: null | boolean; + sign(key: SecretKey | SecretSubkey, data: Uint8Array): true; + isExpired(date?: Date): boolean; + getExpirationTime(): Date | typeof Infinity; + } + + export class Trust extends BasePacket { + tag: enums.packet.trust; + } + + export type AnyPacket = Compressed | SymEncryptedIntegrityProtected | SymEncryptedAEADProtected | PublicKeyEncryptedSessionKey | SymEncryptedSessionKey | Literal + | PublicKey | SymmetricallyEncrypted | Marker | PublicSubkey | UserAttribute | OnePassSignature | SecretKey | Userid | SecretSubkey | Signature | Trust; + export type AnySecretPacket = SecretKey | SecretSubkey; + export type AnyKeyPacket = PublicKey | SecretKey | PublicSubkey | SecretSubkey; + } + + export interface EncryptArmorResult { + data: string; + signature?: string; + } + + export interface EncryptBinaryResult { + message: message.Message; + signature?: signature.Signature; + } + + export type EncryptResult = EncryptArmorResult | EncryptBinaryResult; + + export interface SignArmorResult { + data: string | Stream; + signature: string | Stream; + } + + export interface SignBinaryResult { + message: message.Message | cleartext.CleartextMessage; + signature: signature.Signature; + } + + export type SignResult = SignArmorResult | SignBinaryResult; + + export interface DecryptOptions { + /** the message object with the encrypted data */ + message: message.Message; + /** (optional) private keys with decrypted secret key data or session key */ + privateKeys?: key.Key | key.Key[]; + /** (optional) passwords to decrypt the message */ + passwords?: string | string[]; + /** (optional) session keys in the form: { data:Uint8Array, algorithm:String } */ + sessionKeys?: SessionKey | SessionKey[]; + /** (optional) array of public keys or single key, to verify signatures */ + publicKeys?: key.Key | key.Key[]; + /** (optional) whether to return data as a string(Stream) or Uint8Array(Stream). If 'utf8' (the default), also normalize newlines. */ + format?: string; + /** (optional) whether to return data as a stream. Defaults to the type of stream `message` was created from, if any. */ + streaming?: 'web' | 'node' | false; + /** (optional) detached signature for verification */ + signature?: signature.Signature; + } + + export interface SignOptions { + message: cleartext.CleartextMessage | message.Message; + privateKeys?: key.Key | key.Key[]; + armor?: boolean; + streaming?: 'web' | 'node' | false; + dataType?: DataPacketType; + detached?: boolean; + date?: Date; + fromUserId?: UserId; + } + + export interface KeyContainer { + key: key.Key; + } + + export interface KeyPair extends KeyContainer { + privateKeyArmored: string; + publicKeyArmored: string; + } + + export interface KeyOptions { + userIds: UserId[]; // generating a key with no user defined results in error + passphrase?: string; + numBits?: number; + keyExpirationTime?: number; + curve?: key.EllipticCurveName; + date?: Date; + subkeys?: KeyOptions[]; + } + + /** + * Intended for internal use with openpgp.key.generate() + * It's recommended that users choose openpgp.generateKey() that requires KeyOptions instead + */ + export interface FullKeyOptions { + userIds: UserId[]; + passphrase?: string; + numBits?: number; + keyExpirationTime?: number; + curve?: key.EllipticCurveName; + date?: Date; + subkeys: KeyOptions[]; // required unline KeyOptions.subkeys + } + + export interface Keyid { + bytes: string; + } + + export interface DecryptMessageResult { + data: Uint8Array | string; + signatures: signature.Signature[]; + filename: string; + } + + export interface OpenPGPWorker { + randomCallback(): void; + configure(config: any): void; + seedRandom(buffer: ArrayBuffer): void; + delegate(id: number, method: string, options: any): void; + response(event: any): void; + } + + export interface WorkerOptions { + path?: string; + n?: number; + workers?: OpenPGPWorker[]; + config?: any; + } + + export class AsyncProxy { + constructor(options: WorkerOptions); + getId(): number; + seedRandom(workerId: number, size: number): Promise; + terminate(): void; + delegate(method: string, options: any): void; + + workers: OpenPGPWorker[]; + } + + /** + * Set the path for the web worker script and create an instance of the async proxy + * @param {String} path relative path to the worker scripts, default: 'openpgp.worker.js' + * @param {Number} n number of workers to initialize + * @param {Array} workers alternative to path parameter: web workers initialized with 'openpgp.worker.js' + */ + export function initWorker(options: WorkerOptions): boolean; + + /** + * Returns a reference to the async proxy if the worker was initialized with openpgp.initWorker() + * @returns {module:worker/async_proxy.AsyncProxy|null} the async proxy or null if not initialized + */ + export function getWorker(): AsyncProxy; + + /** + * Cleanup the current instance of the web worker. + */ + export function destroyWorker(): void; + + /** + * Encrypts message text/data with public keys, passwords or both at once. At least either public keys or passwords + * must be specified. If private keys are specified, those will be used to sign the message. + * @param {EncryptOptions} options See `EncryptOptions` + * @returns {Promise} Promise of `EncryptResult` (and optionally signed message) in the form: + * {data: ASCII armored message if 'armor' is true; + * message: full Message object if 'armor' is false, signature: detached signature if 'detached' is true} + * @async + * @static + */ + export function encrypt(options: EncryptBinaryOptions): Promise; + export function encrypt(options: EncryptArmorOptions | BaseEncryptOptions): Promise; + + /** + * Signs a cleartext message. + * @param {String | Uint8Array} data cleartext input to be signed + * @param {utf8|binary|text|mime} dataType (optional) data packet type + * @param {Key|Array} privateKeys array of keys or single key with decrypted secret key data to sign cleartext + * @param {Boolean} armor (optional) if the return value should be ascii armored or the message object + * @param {Boolean} detached (optional) if the return value should contain a detached signature + * @param {Date} date (optional) override the creation date signature + * @param {Object} fromUserId (optional) user ID to sign with, e.g. { name:'Steve Sender', email:'steve@openpgp.org' } + * @returns {Promise} signed cleartext in the form: + * {data: ASCII armored message if 'armor' is true; + * message: full Message object if 'armor' is false, signature: detached signature if 'detached' is true} + * @async + * @static + */ + export function sign(options: SignOptions): Promise; + + /** + * Decrypts a message with the user's private key, a session key or a password. Either a private key; + * a session key or a password must be specified. + * @param {DecryptOptions} options see `DecryptOptions` + * @returns {Promise} Promise of `DecryptMessageResult` and verified message in the form: + * { data:Uint8Array|String, filename:String, signatures:[{ keyid:String, valid:Boolean }] } + * @async + * @static + */ + export function decrypt(options: DecryptOptions): Promise; + + /** + * Generates a new OpenPGP key pair. Supports RSA and ECC keys. Primary and subkey will be of same type. + * @param {Array} userIds array of user IDs e.g. [{ name:'Phil Zimmermann', email:'phil@openpgp.org' }] + * @param {String} passphrase (optional) The passphrase used to encrypt the resulting private key + * @param {Number} numBits (optional) number of bits for RSA keys: 2048 or 4096. + * @param {Number} keyExpirationTime (optional) The number of seconds after the key creation time that the key expires + * @param {String} curve (optional) elliptic curve for ECC keys: + * curve25519, p256, p384, p521, secp256k1; + * brainpoolP256r1, brainpoolP384r1, or brainpoolP512r1. + * @param {Date} date (optional) override the creation date of the key and the key signatures + * @param {Array} subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}] + * sign parameter defaults to false, and indicates whether the subkey should sign rather than encrypt + * @returns {Promise} The generated key object in the form: + * { key:Key, privateKeyArmored:String, publicKeyArmored:String } + * @async + * @static + */ + export function generateKey(options: KeyOptions): Promise; + + /** + * Reformats signature packets for a key and rewraps key object. + * @param {Key} privateKey private key to reformat + * @param {Array} userIds array of user IDs e.g. [{ name:'Phil Zimmermann', email:'phil@openpgp.org' }] + * @param {String} passphrase (optional) The passphrase used to encrypt the resulting private key + * @param {Number} keyExpirationTime (optional) The number of seconds after the key creation time that the key expires + * @returns {Promise} The generated key object in the form: + * { key:Key, privateKeyArmored:String, publicKeyArmored:String } + * @async + * @static + */ + export function reformatKey(options: { + privateKey: key.Key; + userIds?: (string | UserId)[]; + passphrase?: string; + keyExpirationTime?: number; + }): Promise; + + /** + * Unlock a private key with your passphrase. + * @param {Key} privateKey the private key that is to be decrypted + * @param {String|Array} passphrase the user's passphrase(s) chosen during key generation + * @returns {Promise} the unlocked key object in the form: { key:Key } + * @async + */ + export function decryptKey(options: { + privateKey: key.Key; + passphrase?: string | string[]; + }): Promise; + + export function encryptKey(options: { + privateKey: key.Key; + passphrase?: string + }): Promise; + + export namespace armor { + /** Armor an OpenPGP binary packet block + * @param messagetype type of the message + * @param body + * @param partindex + * @param parttotal + */ + function armor(messagetype: enums.armor, body: object, partindex: number, parttotal: number): string; + + /** DeArmor an OpenPGP armored message; verify the checksum and return the encoded bytes + * + * @param text OpenPGP armored message + */ + function dearmor(text: string): object; + } + + export namespace cleartext { + /** Class that represents an OpenPGP cleartext signed message. + */ + interface CleartextMessage { + /** Returns ASCII armored text of cleartext signed message + */ + armor(): string; + + /** Returns the key IDs of the keys that signed the cleartext message + */ + getSigningKeyIds(): Array; + + /** Get cleartext + */ + getText(): string; + + /** Sign the cleartext message + * + * @param privateKeys private keys with decrypted secret key data for signing + */ + sign(privateKeys: Array): void; + + /** Verify signatures of cleartext signed message + * @param keys array of keys to verify signatures + */ + verify(keys: key.Key[], date?: Date, streaming?: boolean): Promise; + } + + /** + * reads an OpenPGP cleartext signed message and returns a CleartextMessage object + * @param armoredText text to be parsed + * @returns new cleartext message object + * @async + * @static + */ + function readArmored(armoredText: string): Promise; + + function fromText(text: string): CleartextMessage; + } + + export namespace config { + let prefer_hash_algorithm: enums.hash; + let encryption_cipher: enums.symmetric; + let compression: enums.compression; + let show_version: boolean; + let show_comment: boolean; + let integrity_protect: boolean; + let debug: boolean; + let deflate_level: number; + let aead_protect: boolean; + let ignore_mdc_error: boolean; + let checksum_required: boolean; + let rsa_blinding: boolean; + let password_collision_check: boolean; + let revocations_expire: boolean; + let use_native: boolean; + let zero_copy: boolean; + let tolerant: boolean; + let versionstring: string; + let commentstring: string; + let keyserver: string; + let node_store: string; + } + + export namespace crypto { + interface Mpi { + data: number; + read(input: string): number; + write(): string; + } + + /** Generating a session key for the specified symmetric algorithm + * @param algo Algorithm to use + */ + function generateSessionKey(algo: enums.symmetric): string; + + /** generate random byte prefix as string for the specified algorithm + * @param algo Algorithm to use + */ + function getPrefixRandom(algo: enums.symmetric): string; + + /** Returns the number of integers comprising the private key of an algorithm + * @param algo The public key algorithm + */ + function getPrivateMpiCount(algo: enums.symmetric): number; + + /** Decrypts data using the specified public key multiprecision integers of the private key, the specified secretMPIs of the private key and the specified algorithm. + @param algo Algorithm to be used + @param publicMPIs Algorithm dependent multiprecision integers of the public key part of the private key + @param secretMPIs Algorithm dependent multiprecision integers of the private key used + @param data Data to be encrypted as MPI + */ + function publicKeyDecrypt(algo: enums.publicKey, publicMPIs: Array, secretMPIs: Array, data: Mpi): Mpi; + + /** Encrypts data using the specified public key multiprecision integers and the specified algorithm. + @param algo Algorithm to be used + @param publicMPIs Algorithm dependent multiprecision integers + @param data Data to be encrypted as MPI + */ + function publicKeyEncrypt(algo: enums.publicKey, publicMPIs: Array, data: Mpi): Array; + + namespace cfb { + /** This function decrypts a given plaintext using the specified blockcipher to decrypt a message + @param cipherfn the algorithm cipher class to decrypt data in one block_size encryption + @param key binary string representation of key to be used to decrypt the ciphertext. This will be passed to the cipherfn + @param ciphertext to be decrypted provided as a string + @param resync a boolean value specifying if a resync of the IV should be used or not. The encrypteddatapacket uses the "old" style with a resync. Decryption within an encryptedintegrityprotecteddata packet is not resyncing the IV. + */ + function decrypt(cipherfn: string, key: string, ciphertext: string, resync: boolean): string; + + /** This function encrypts a given with the specified prefixrandom using the specified blockcipher to encrypt a message + @param prefixrandom random bytes of block_size length provided as a string to be used in prefixing the data + @param cipherfn the algorithm cipher class to encrypt data in one block_size encryption + @param plaintext data to be encrypted provided as a string + @param key binary string representation of key to be used to encrypt the plaintext. This will be passed to the cipherfn + @param resync a boolean value specifying if a resync of the IV should be used or not. The encrypteddatapacket uses the "old" style with a resync. Encryption within an encryptedintegrityprotecteddata packet is not resyncing the IV. + */ + function encrypt(prefixrandom: string, cipherfn: string, plaintext: string, key: string, resync: boolean): string; + + /** Decrypts the prefixed data for the Modification Detection Code (MDC) computation + @param cipherfn cipherfn.encrypt Cipher function to use + @param key binary string representation of key to be used to check the mdc This will be passed to the cipherfn + @param ciphertext The encrypted data + */ + function mdc(cipherfn: object, key: string, ciphertext: string): string; + } + + namespace hash { + /** Create a hash on the specified data using the specified algorithm + @param algo Hash algorithm type + @param data Data to be hashed + */ + function digest(algo: enums.hash, data: Uint8Array): Promise; + + /** Returns the hash size in bytes of the specified hash algorithm type + @param algo Hash algorithm type + */ + function getHashByteLength(algo: enums.hash): number; + } + + namespace random { + /** Retrieve secure random byte string of the specified length + @param length Length in bytes to generate + */ + function getRandomBytes(length: number): Promise; + } + + namespace signature { + /** Create a signature on data using the specified algorithm + @param hash_algo hash Algorithm to use + @param algo Asymmetric cipher algorithm to use + @param publicMPIs Public key multiprecision integers of the private key + @param secretMPIs Private key multiprecision integers which is used to sign the data + @param data Data to be signed + */ + function sign(hash_algo: enums.hash, algo: enums.publicKey, publicMPIs: Array, secretMPIs: Array, data: string): Mpi; + + /** + @param algo public Key algorithm + @param hash_algo Hash algorithm + @param msg_MPIs Signature multiprecision integers + @param publickey_MPIs Public key multiprecision integers + @param data Data on where the signature was computed on + */ + function verify(algo: enums.publicKey, hash_algo: enums.hash, msg_MPIs: Array, publickey_MPIs: Array, data: string): boolean; + } + } + + export namespace enums { + + function read(type: typeof armor, e: armor): armorNames | string | any; + function read(type: typeof compression, e: compression): compressionNames | string | any; + function read(type: typeof hash, e: hash): hashNames | string | any; + function read(type: typeof packet, e: packet): packetNames | string | any; + function read(type: typeof publicKey, e: publicKey): publicKeyNames | string | any; + function read(type: typeof symmetric, e: symmetric): symmetricNames | string | any; + function read(type: typeof keyStatus, e: keyStatus): keyStatusNames | string | any; + function read(type: typeof keyFlags, e: keyFlags): keyFlagsNames | string | any; + + export type armorNames = 'multipart_section' | 'multipart_last' | 'signed' | 'message' | 'public_key' | 'private_key'; + enum armor { + multipart_section = 0, + multipart_last = 1, + signed = 2, + message = 3, + public_key = 4, + private_key = 5, + signature = 6, + } + + enum reasonForRevocation { + no_reason = 0, // No reason specified (key revocations or cert revocations) + key_superseded = 1, // Key is superseded (key revocations) + key_compromised = 2, // Key material has been compromised (key revocations) + key_retired = 3, // Key is retired and no longer used (key revocations) + userid_invalid = 32, // User ID information is no longer valid (cert revocations) + } + + export type compressionNames = 'uncompressed' | 'zip' | 'zlib' | 'bzip2'; + enum compression { + uncompressed = 0, + zip = 1, + zlib = 2, + bzip2 = 3, + } + + export type hashNames = 'md5' | 'sha1' | 'ripemd' | 'sha256' | 'sha384' | 'sha512' | 'sha224'; + enum hash { + md5 = 1, + sha1 = 2, + ripemd = 3, + sha256 = 8, + sha384 = 9, + sha512 = 10, + sha224 = 11, + } + + export type packetNames = 'publicKeyEncryptedSessionKey' | 'signature' | 'symEncryptedSessionKey' | 'onePassSignature' | 'secretKey' | 'publicKey' + | 'secretSubkey' | 'compressed' | 'symmetricallyEncrypted' | 'marker' | 'literal' | 'trust' | 'userid' | 'publicSubkey' | 'userAttribute' + | 'symEncryptedIntegrityProtected' | 'modificationDetectionCode' | 'symEncryptedAEADProtected'; + enum packet { + publicKeyEncryptedSessionKey = 1, + signature = 2, + symEncryptedSessionKey = 3, + onePassSignature = 4, + secretKey = 5, + publicKey = 6, + secretSubkey = 7, + compressed = 8, + symmetricallyEncrypted = 9, + marker = 10, + literal = 11, + trust = 12, + userid = 13, + publicSubkey = 14, + userAttribute = 17, + symEncryptedIntegrityProtected = 18, + modificationDetectionCode = 19, + symEncryptedAEADProtected = 20, + } + + export type publicKeyNames = 'rsa_encrypt_sign' | 'rsa_encrypt' | 'rsa_sign' | 'elgamal' | 'dsa' | 'ecdh' | 'ecdsa' | 'eddsa' | 'aedh' | 'aedsa'; + enum publicKey { + rsa_encrypt_sign = 1, + rsa_encrypt = 2, + rsa_sign = 3, + elgamal = 16, + dsa = 17, + ecdh = 18, + ecdsa = 19, + eddsa = 22, + aedh = 23, + aedsa = 24, + } + + export type symmetricNames = 'plaintext' | 'idea' | 'tripledes' | 'cast5' | 'blowfish' | 'aes128' | 'aes192' | 'aes256' | 'twofish'; + enum symmetric { + plaintext = 0, + idea = 1, + tripledes = 2, + cast5 = 3, + blowfish = 4, + aes128 = 7, + aes192 = 8, + aes256 = 9, + twofish = 10, + } + + export type keyStatusNames = 'invalid' | 'expired' | 'revoked' | 'valid' | 'no_self_cert'; + enum keyStatus { + invalid = 0, + expired = 1, + revoked = 2, + valid = 3, + no_self_cert = 4, + } + + export type keyFlagsNames = 'certify_keys' | 'sign_data' | 'encrypt_communication' | 'encrypt_storage' | 'split_private_key' | 'authentication' + | 'shared_private_key'; + enum keyFlags { + certify_keys = 1, + sign_data = 2, + encrypt_communication = 4, + encrypt_storage = 8, + split_private_key = 16, + authentication = 32, + shared_private_key = 128, + } + + } + + export namespace key { + + export type EllipticCurveName = 'curve25519' | 'p256' | 'p384' | 'p521' | 'secp256k1' | 'brainpoolP256r1' | 'brainpoolP384r1' | 'brainpoolP512r1'; + + /** Class that represents an OpenPGP key. Must contain a primary key. Can contain additional subkeys, signatures, user ids, user attributes. + */ + class Key { + constructor(packetlist: packet.List); + armor(): string; + decrypt(passphrase: string | string[], keyId?: Keyid): Promise; + encrypt(passphrase: string | string[]): Promise; + getExpirationTime(capability?: 'encrypt' | 'encrypt_sign' | 'sign' | null, keyId?: Keyid | null, userId?: UserId | null): Promise; // Returns null if `capabilities` is passed and the key does not have the specified capabilities or is revoked or invalid. + getKeyIds(): Keyid[]; + getPrimaryUser(): Promise; + getUserIds(): string[]; + isPrivate(): boolean; + isPublic(): boolean; + toPublic(): Key; + update(key: Key): void; + verifyPrimaryKey(): Promise; + isRevoked(): Promise; + revoke(reason: { flag?: enums.reasonForRevocation; string?: string; }, date?: Date): Promise; + getRevocationCertificate(): Promise | string | undefined>; + getEncryptionKey(keyid?: Keyid | null, date?: Date, userId?: UserId | null): Promise; + getSigningKey(): Promise; + getKeys(keyId?: Keyid): (Key | SubKey)[]; + // isDecrypted(): boolean; + isFullyEncrypted(): boolean; + isFullyDecrypted(): boolean; + isPacketDecrypted(keyId: Keyid): boolean; + getFingerprint(): string; + getCreationTime(): Date; + getAlgorithmInfo(): AlgorithmInfo; + getKeyId(): Keyid; + primaryKey: packet.PublicKey | packet.SecretKey; + subKeys: SubKey[]; + users: User[]; + revocationSignatures: packet.Signature[]; + keyPacket: packet.PublicKey | packet.SecretKey; + } + + class SubKey { + constructor(subKeyPacket: packet.SecretSubkey | packet.PublicSubkey); + subKey: packet.SecretSubkey | packet.PublicSubkey; + keyPacket: packet.SecretKey; + bindingSignatures: packet.Signature[]; + revocationSignatures: packet.Signature[]; + verify(primaryKey: packet.PublicKey | packet.SecretKey): Promise; + isDecrypted(): boolean; + getFingerprint(): string; + getCreationTime(): Date; + getAlgorithmInfo(): AlgorithmInfo; + getKeyId(): Keyid; + } + + export interface User { + userId: packet.Userid | null; + userAttribute: packet.UserAttribute | null; + selfCertifications: packet.Signature[]; + otherCertifications: packet.Signature[]; + revocationSignatures: packet.Signature[]; + } + + export interface PrimaryUser { + index: number; + user: User; + } + + interface KeyResult { + keys: Key[]; + err?: Error[]; + } + + type AlgorithmInfo = { + algorithm: enums.publicKeyNames; + bits: number; + }; + + /** Generates a new OpenPGP key. Currently only supports RSA keys. Primary and subkey will be of same type. + * @param options + */ + function generate(options: FullKeyOptions): Promise; + + /** Reads an OpenPGP armored text and returns one or multiple key objects + + @param armoredText text to be parsed + */ + function readArmored(armoredText: string): Promise; + + /** Reads an OpenPGP binary data and returns one or multiple key objects + + @param data to be parsed + */ + function read(data: Uint8Array): Promise; + } + + export namespace signature { + class Signature { + constructor(packetlist: packet.List); + armor(): string; + packets: packet.List; + } + + /** reads an OpenPGP armored signature and returns a signature object + + @param armoredText text to be parsed + */ + function readArmored(armoredText: string): Promise; + + /** reads an OpenPGP signature as byte array and returns a signature object + + @param input binary signature + */ + function read(input: Uint8Array): Promise; + } + + export namespace message { + /** Class that represents an OpenPGP message. Can be an encrypted message, signed message, compressed message or literal message + */ + class Message { + constructor(packetlist: packet.List); + + /** Returns ASCII armored text of message + */ + armor(): string; + + /** Decrypt the message + @param privateKey private key with decrypted secret data + */ + decrypt(privateKeys?: key.Key[] | null, passwords?: string[] | null, sessionKeys?: SessionKey[] | null, streaming?: boolean): Promise; + + /** Encrypt the message + @param keys array of keys, used to encrypt the message + */ + encrypt(keys: key.Key[]): Promise; + + /** Returns the key IDs of the keys to which the session key is encrypted + */ + getEncryptionKeyIds(): Keyid[]; + + /** Get literal data that is the body of the message + */ + getLiteralData(): Uint8Array | null | Stream; + + /** Returns the key IDs of the keys that signed the message + */ + getSigningKeyIds(): Keyid[]; + + /** Get literal data as text + */ + getText(): string | null | Stream; + + getFilename(): string | null; + + /** Sign the message (the literal data packet of the message) + @param privateKey private keys with decrypted secret key data for signing + */ + sign(privateKey: key.Key[]): Promise; + + /** Unwrap compressed message + */ + unwrapCompressed(): Message; + + /** Verify message signatures + @param keys array of keys to verify signatures + */ + verify(keys: key.Key[], date?: Date, streaming?: boolean): Promise; + + /** + * Append signature to unencrypted message object + * @param {String|Uint8Array} detachedSignature The detached ASCII-armored or Uint8Array PGP signature + */ + appendSignature(detachedSignature: string | Uint8Array): Promise; + + packets: packet.List; + } + + class SessionKey { // todo + + } + + export interface Verification { + keyid: Keyid; + verified: Promise; + signature: Promise; + } + + /** creates new message object from binary data + @param bytes + */ + function fromBinary(bytes: Uint8Array | Stream, filename?: string, date?: Date, type?: DataPacketType): Message; + + /** creates new message object from text + @param text + */ + function fromText(text: string | Stream, filename?: string, date?: Date, type?: DataPacketType): Message; + + /** reads an OpenPGP armored message and returns a message object + + @param armoredText text to be parsed + */ + function readArmored(armoredText: string | Stream): Promise; + + /** + * reads an OpenPGP message as byte array and returns a message object + * @param {Uint8Array} input binary message + * @returns {Message} new message object + * @static + */ + function read(input: Uint8Array): Promise; + } + + export class HKP { + constructor(keyServerBaseUrl?: string); + lookup(options: { keyid?: string, query?: string }): Promise; + } + + /** + * todo - some of these are outdated - check OpenPGP.js api + */ + export namespace util { + /** Convert an array of integers(0.255) to a string + @param bin An array of (binary) integers to convert + */ + function bin2str(bin: Array): string; + + /** Calculates a 16bit sum of a string by adding each character codes modulus 65535 + @param text string to create a sum of + */ + function calc_checksum(text: string): number; + + /** Convert a string of utf8 bytes to a native javascript string + @param utf8 A valid squence of utf8 bytes + */ + function decode_utf8(utf8: string): string; + + /** Convert a native javascript string to a string of utf8 bytes + param str The string to convert + */ + function encode_utf8(str: string): string; + + /** Return the algorithm type as string + */ + function get_hashAlgorithmString(): string; + + /** Get native Web Cryptography api. The default configuration is to use the api when available. But it can also be deactivated with config.useWebCrypto + */ + function getWebCrypto(): object; + + /** Helper function to print a debug message. Debug messages are only printed if + @param str string of the debug message + */ + function print_debug(str: string): void; + + /** Helper function to print a debug message. Debug messages are only printed if + @param str string of the debug message + */ + function print_debug_hexstr_dump(str: string): void; + + /** Shifting a string to n bits right + @param value The string to shift + @param bitcount Amount of bits to shift (MUST be smaller than 9) + */ + function shiftRight(value: string, bitcount: number): string; + + /** + * Convert a string to an array of 8-bit integers + * @param {String} str String to convert + * @returns {Uint8Array} An array of 8-bit integers + */ + function str_to_Uint8Array(str: string): Uint8Array; + + /** + * Convert an array of 8-bit integers to a string + * @param {Uint8Array} bytes An array of 8-bit integers to convert + * @returns {String} String representation of the array + */ + function Uint8Array_to_str(bin: Uint8Array): string; + + /** + * Convert an array of 8-bit integers to a hex string + * @param {Uint8Array} bytes Array of 8-bit integers to convert + * @returns {String} Hexadecimal representation of the array + */ + function Uint8Array_to_hex(bytes: Uint8Array): string; + + /** + * Convert a hex string to an array of 8-bit integers + * @param {String} hex A hex string to convert + * @returns {Uint8Array} An array of 8-bit integers + */ + function hex_to_Uint8Array(hex: string): Uint8Array; + + /** + * Create hex string from a binary + * @param {String} str String to convert + * @returns {String} String containing the hexadecimal values + */ + function str_to_hex(str: string): string; + + /** + * Create binary string from a hex encoded string + * @param {String} str Hex string to convert + * @returns {String} + */ + function hex_to_str(hex: string): string; + + function parseUserId(userid: string): UserId; + + function formatUserId(userid: UserId): string; + + function normalizeDate(date: Date | null): Date | null; + } + + export namespace stream { + function readToEnd(input: Stream | T, concat?: (list: T[]) => T): Promise; + // concat + // slice + // clone + // webToNode + // nodeToWeb + } + +} diff --git a/Core/source/lib/openpgpv4.js b/Core/source/lib/openpgpv4.js new file mode 100644 index 000000000..8103dee04 --- /dev/null +++ b/Core/source/lib/openpgpv4.js @@ -0,0 +1,42866 @@ +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.openpgp = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i `Symbol(${e})`;const r = "undefined" != typeof self ? self : "undefined" != typeof window ? window : "undefined" != typeof global ? global : void 0, + o = Number.isNaN || function (e) { + return e != e; + };function n(e) { + return "object" == typeof e && null !== e || "function" == typeof e; + }function i(e, t, r) { + Object.defineProperty(e, t, { value: r, writable: !0, enumerable: !0, configurable: !0 }); + }function a(e) { + return e.slice(); + }function s(e, t, r, o, n) { + new Uint8Array(e).set(new Uint8Array(r, o, n), t); + }function l(e) { + return !1 !== function (e) { + if ("number" != typeof e) return !1;if (o(e)) return !1;if (e < 0) return !1;return !0; + }(e) && e !== 1 / 0; + }function c(e, t, r) { + if ("function" != typeof e) throw new TypeError("Argument is not a function");return Function.prototype.apply.call(e, t, r); + }function u(e, t, r, o) { + const n = e[t];if (void 0 !== n) { + if ("function" != typeof n) throw new TypeError(`${n} is not a method`);switch (r) {case 0: + return () => f(n, e, o);case 1: + return t => { + const r = [t].concat(o);return f(n, e, r); + };} + }return () => Promise.resolve(); + }function d(e, t, r) { + const o = e[t];if (void 0 !== o) return c(o, e, r); + }function f(e, t, r) { + try { + return Promise.resolve(c(e, t, r)); + } catch (e) { + return Promise.reject(e); + } + }function _(e) { + return e; + }function h(e) { + if (e = Number(e), o(e) || e < 0) throw new RangeError("highWaterMark property of a queuing strategy must be non-negative and non-NaN");return e; + }function b(e) { + if (void 0 === e) return () => 1;if ("function" != typeof e) throw new TypeError("size property of a queuing strategy must be a function");return t => e(t); + }function m(e, t, r) { + return Promise.prototype.then.call(e, t, r); + }function y(e, t, r) { + let o, n;const i = new Promise((e, t) => { + o = e, n = t; + });void 0 === r && (r = e => { + throw e; + });return function (e, t, r) { + let o = !1;const n = e => { + !1 === o && (o = !0, r(e)); + };let i = 0, + a = 0;const s = e.length, + l = new Array(s);for (const r of e) { + const e = i;m(r, r => { + l[e] = r, ++a === s && t(l); + }, n), ++i; + } + }(e, e => { + try { + const r = t(e);o(r); + } catch (e) { + n(e); + } + }, e => { + try { + const t = r(e);o(t); + } catch (e) { + n(e); + } + }), i; + }function p(e) {}function w(e) { + e && e instanceof p.AssertionError && setTimeout(() => { + throw e; + }, 0); + }function g(e) { + const t = e._queue.shift();return e._queueTotalSize -= t.size, e._queueTotalSize < 0 && (e._queueTotalSize = 0), t.value; + }function S(e, t, r) { + if (!l(r = Number(r))) throw new RangeError("Size must be a finite, non-NaN, non-negative number.");e._queue.push({ value: t, size: r }), e._queueTotalSize += r; + }function v(e) { + e._queue = [], e._queueTotalSize = 0; + }p.AssertionError = function () {};const R = t("[[AbortSteps]]"), + P = t("[[ErrorSteps]]");class WritableStream { + constructor(e = {}, t = {}) { + q(this);const r = t.size;let o = t.highWaterMark;if (void 0 !== e.type) throw new RangeError("Invalid type is specified");const n = b(r);void 0 === o && (o = 1), function (e, t, r, o) { + const n = Object.create(WritableStreamDefaultController.prototype);const i = u(t, "write", 1, [n]), + a = u(t, "close", 0, []), + s = u(t, "abort", 1, []);$(e, n, function () { + return d(t, "start", [n]); + }, i, a, s, r, o); + }(this, e, o = h(o), n); + }get locked() { + if (!1 === E(this)) throw G("locked");return C(this); + }abort(e) { + return !1 === E(this) ? Promise.reject(G("abort")) : !0 === C(this) ? Promise.reject(new TypeError("Cannot abort a stream that already has a writer")) : j(this, e); + }getWriter() { + if (!1 === E(this)) throw G("getWriter");return T(this); + } + }function T(e) { + return new WritableStreamDefaultWriter(e); + }function q(e) { + e._state = "writable", e._storedError = void 0, e._writer = void 0, e._writableStreamController = void 0, e._writeRequests = [], e._inFlightWriteRequest = void 0, e._closeRequest = void 0, e._inFlightCloseRequest = void 0, e._pendingAbortRequest = void 0, e._backpressure = !1; + }function E(e) { + return !!n(e) && !!Object.prototype.hasOwnProperty.call(e, "_writableStreamController"); + }function C(e) { + return void 0 !== e._writer; + }function j(e, t) { + const r = e._state;if ("closed" === r || "errored" === r) return Promise.resolve(void 0);if (void 0 !== e._pendingAbortRequest) return e._pendingAbortRequest._promise;let o = !1;"erroring" === r && (o = !0, t = void 0);const n = new Promise((r, n) => { + e._pendingAbortRequest = { _promise: void 0, _resolve: r, _reject: n, _reason: t, _wasAlreadyErroring: o }; + });return e._pendingAbortRequest._promise = n, !1 === o && W(e, t), n; + }function A(e, t) { + "writable" !== e._state ? B(e) : W(e, t); + }function W(e, t) { + const r = e._writableStreamController;e._state = "erroring", e._storedError = t;const o = e._writer;void 0 !== o && D(o, t), !1 === function (e) { + if (void 0 === e._inFlightWriteRequest && void 0 === e._inFlightCloseRequest) return !1;return !0; + }(e) && !0 === r._started && B(e); + }function B(e) { + e._state = "errored", e._writableStreamController[P]();const t = e._storedError;for (const r of e._writeRequests) r._reject(t);if (e._writeRequests = [], void 0 === e._pendingAbortRequest) return void z(e);const r = e._pendingAbortRequest;if (e._pendingAbortRequest = void 0, !0 === r._wasAlreadyErroring) return r._reject(t), void z(e);e._writableStreamController[R](r._reason).then(() => { + r._resolve(), z(e); + }, t => { + r._reject(t), z(e); + }); + }function O(e) { + return void 0 !== e._closeRequest || void 0 !== e._inFlightCloseRequest; + }function z(e) { + void 0 !== e._closeRequest && (e._closeRequest._reject(e._storedError), e._closeRequest = void 0);const t = e._writer;void 0 !== t && ee(t, e._storedError); + }function k(e, t) { + const r = e._writer;void 0 !== r && t !== e._backpressure && (!0 === t ? function (e) { + re(e); + }(r) : ae(r)), e._backpressure = t; + }class WritableStreamDefaultWriter { + constructor(e) { + if (!1 === E(e)) throw new TypeError("WritableStreamDefaultWriter can only be constructed with a WritableStream instance");if (!0 === C(e)) throw new TypeError("This stream has already been locked for exclusive writing by another writer");this._ownerWritableStream = e, e._writer = this;const t = e._state;if ("writable" === t) !1 === O(e) && !0 === e._backpressure ? re(this) : ne(this), X(this);else if ("erroring" === t) oe(this, e._storedError), X(this);else if ("closed" === t) ne(this), function (e) { + X(e), te(e); + }(this);else { + const t = e._storedError;oe(this, t), Z(this, t); + } + }get closed() { + return !1 === F(this) ? Promise.reject(J("closed")) : this._closedPromise; + }get desiredSize() { + if (!1 === F(this)) throw J("desiredSize");if (void 0 === this._ownerWritableStream) throw K("desiredSize");return function (e) { + const t = e._ownerWritableStream, + r = t._state;if ("errored" === r || "erroring" === r) return null;if ("closed" === r) return 0;return Q(t._writableStreamController); + }(this); + }get ready() { + return !1 === F(this) ? Promise.reject(J("ready")) : this._readyPromise; + }abort(e) { + return !1 === F(this) ? Promise.reject(J("abort")) : void 0 === this._ownerWritableStream ? Promise.reject(K("abort")) : function (e, t) { + return j(e._ownerWritableStream, t); + }(this, e); + }close() { + if (!1 === F(this)) return Promise.reject(J("close"));const e = this._ownerWritableStream;return void 0 === e ? Promise.reject(K("close")) : !0 === O(e) ? Promise.reject(new TypeError("cannot close an already-closing stream")) : L(this); + }releaseLock() { + if (!1 === F(this)) throw J("releaseLock");void 0 !== this._ownerWritableStream && M(this); + }write(e) { + return !1 === F(this) ? Promise.reject(J("write")) : void 0 === this._ownerWritableStream ? Promise.reject(K("write to")) : Y(this, e); + } + }function F(e) { + return !!n(e) && !!Object.prototype.hasOwnProperty.call(e, "_ownerWritableStream"); + }function L(e) { + const t = e._ownerWritableStream, + r = t._state;if ("closed" === r || "errored" === r) return Promise.reject(new TypeError(`The stream (in ${r} state) is not in the writable state and cannot be closed`));const o = new Promise((e, r) => { + const o = { _resolve: e, _reject: r };t._closeRequest = o; + });return !0 === t._backpressure && "writable" === r && ae(e), function (e) { + S(e, "close", 0), x(e); + }(t._writableStreamController), o; + }function I(e, t) { + "pending" === e._closedPromiseState ? ee(e, t) : function (e, t) { + Z(e, t); + }(e, t); + }function D(e, t) { + "pending" === e._readyPromiseState ? ie(e, t) : function (e, t) { + oe(e, t); + }(e, t); + }function M(e) { + const t = e._ownerWritableStream, + r = new TypeError("Writer was released and can no longer be used to monitor the stream's closedness");D(e, r), I(e, r), t._writer = void 0, e._ownerWritableStream = void 0; + }function Y(e, t) { + const r = e._ownerWritableStream, + o = r._writableStreamController, + n = function (e, t) { + try { + return e._strategySizeAlgorithm(t); + } catch (t) { + return H(e, t), 1; + } + }(o, t);if (r !== e._ownerWritableStream) return Promise.reject(K("write to"));const i = r._state;if ("errored" === i) return Promise.reject(r._storedError);if (!0 === O(r) || "closed" === i) return Promise.reject(new TypeError("The stream is closing or closed and cannot be written to"));if ("erroring" === i) return Promise.reject(r._storedError);const a = function (e) { + return new Promise((t, r) => { + const o = { _resolve: t, _reject: r };e._writeRequests.push(o); + }); + }(r);return function (e, t, r) { + const o = { chunk: t };try { + S(e, o, r); + } catch (t) { + return void H(e, t); + }const n = e._controlledWritableStream;if (!1 === O(n) && "writable" === n._state) { + const t = U(e);k(n, t); + }x(e); + }(o, t, n), a; + }class WritableStreamDefaultController { + constructor() { + throw new TypeError("WritableStreamDefaultController cannot be constructed explicitly"); + }error(e) { + if (!1 === function (e) { + if (!n(e)) return !1;if (!Object.prototype.hasOwnProperty.call(e, "_controlledWritableStream")) return !1;return !0; + }(this)) throw new TypeError("WritableStreamDefaultController.prototype.error can only be used on a WritableStreamDefaultController");"writable" === this._controlledWritableStream._state && V(this, e); + }[R](e) { + const t = this._abortAlgorithm(e);return N(this), t; + }[P]() { + v(this); + } + }function $(e, t, r, o, n, i, a, s) { + t._controlledWritableStream = e, e._writableStreamController = t, t._queue = void 0, t._queueTotalSize = void 0, v(t), t._started = !1, t._strategySizeAlgorithm = s, t._strategyHWM = a, t._writeAlgorithm = o, t._closeAlgorithm = n, t._abortAlgorithm = i;const l = U(t);k(e, l);const c = r();Promise.resolve(c).then(() => { + t._started = !0, x(t); + }, r => { + t._started = !0, A(e, r); + }).catch(w); + }function N(e) { + e._writeAlgorithm = void 0, e._closeAlgorithm = void 0, e._abortAlgorithm = void 0, e._strategySizeAlgorithm = void 0; + }function Q(e) { + return e._strategyHWM - e._queueTotalSize; + }function x(e) { + const t = e._controlledWritableStream;if (!1 === e._started) return;if (void 0 !== t._inFlightWriteRequest) return;const r = t._state;if ("closed" === r || "errored" === r) return;if ("erroring" === r) return void B(t);if (0 === e._queue.length) return;const o = function (e) { + return e._queue[0].value; + }(e);"close" === o ? function (e) { + const t = e._controlledWritableStream;(function (e) { + e._inFlightCloseRequest = e._closeRequest, e._closeRequest = void 0; + })(t), g(e);const r = e._closeAlgorithm();N(e), r.then(() => { + !function (e) { + e._inFlightCloseRequest._resolve(void 0), e._inFlightCloseRequest = void 0, "erroring" === e._state && (e._storedError = void 0, void 0 !== e._pendingAbortRequest && (e._pendingAbortRequest._resolve(), e._pendingAbortRequest = void 0)), e._state = "closed";const t = e._writer;void 0 !== t && te(t); + }(t); + }, e => { + !function (e, t) { + e._inFlightCloseRequest._reject(t), e._inFlightCloseRequest = void 0, void 0 !== e._pendingAbortRequest && (e._pendingAbortRequest._reject(t), e._pendingAbortRequest = void 0), A(e, t); + }(t, e); + }).catch(w); + }(e) : function (e, t) { + const r = e._controlledWritableStream;(function (e) { + e._inFlightWriteRequest = e._writeRequests.shift(); + })(r), e._writeAlgorithm(t).then(() => { + !function (e) { + e._inFlightWriteRequest._resolve(void 0), e._inFlightWriteRequest = void 0; + }(r);const t = r._state;if (g(e), !1 === O(r) && "writable" === t) { + const t = U(e);k(r, t); + }x(e); + }, t => { + "writable" === r._state && N(e), function (e, t) { + e._inFlightWriteRequest._reject(t), e._inFlightWriteRequest = void 0, A(e, t); + }(r, t); + }).catch(w); + }(e, o.chunk); + }function H(e, t) { + "writable" === e._controlledWritableStream._state && V(e, t); + }function U(e) { + return Q(e) <= 0; + }function V(e, t) { + const r = e._controlledWritableStream;N(e), W(r, t); + }function G(e) { + return new TypeError(`WritableStream.prototype.${e} can only be used on a WritableStream`); + }function J(e) { + return new TypeError(`WritableStreamDefaultWriter.prototype.${e} can only be used on a WritableStreamDefaultWriter`); + }function K(e) { + return new TypeError("Cannot " + e + " a stream using a released writer"); + }function X(e) { + e._closedPromise = new Promise((t, r) => { + e._closedPromise_resolve = t, e._closedPromise_reject = r, e._closedPromiseState = "pending"; + }); + }function Z(e, t) { + X(e), ee(e, t); + }function ee(e, t) { + e._closedPromise.catch(() => {}), e._closedPromise_reject(t), e._closedPromise_resolve = void 0, e._closedPromise_reject = void 0, e._closedPromiseState = "rejected"; + }function te(e) { + e._closedPromise_resolve(void 0), e._closedPromise_resolve = void 0, e._closedPromise_reject = void 0, e._closedPromiseState = "resolved"; + }function re(e) { + e._readyPromise = new Promise((t, r) => { + e._readyPromise_resolve = t, e._readyPromise_reject = r; + }), e._readyPromiseState = "pending"; + }function oe(e, t) { + re(e), ie(e, t); + }function ne(e) { + re(e), ae(e); + }function ie(e, t) { + e._readyPromise.catch(() => {}), e._readyPromise_reject(t), e._readyPromise_resolve = void 0, e._readyPromise_reject = void 0, e._readyPromiseState = "rejected"; + }function ae(e) { + e._readyPromise_resolve(void 0), e._readyPromise_resolve = void 0, e._readyPromise_reject = void 0, e._readyPromiseState = "fulfilled"; + }const se = Number.isInteger || function (e) { + return "number" == typeof e && isFinite(e) && Math.floor(e) === e; + }, + le = t("[[CancelSteps]]"), + ce = t("[[PullSteps]]");class ReadableStream { + constructor(e = {}, t = {}) { + fe(this);const r = t.size;let o = t.highWaterMark;const n = e.type;if ("bytes" === String(n)) { + if (void 0 !== r) throw new RangeError("The strategy for a byte stream cannot have a size function");void 0 === o && (o = 0), function (e, t, r) { + const o = Object.create(ReadableByteStreamController.prototype);const n = u(t, "pull", 0, [o]), + i = u(t, "cancel", 1, []);let a = t.autoAllocateChunkSize;if (void 0 !== a && (a = Number(a), !1 === se(a) || a <= 0)) throw new RangeError("autoAllocateChunkSize must be a positive integer");!function (e, t, r, o, n, i, a) { + t._controlledReadableByteStream = e, t._pullAgain = !1, t._pulling = !1, He(t), t._queue = t._queueTotalSize = void 0, v(t), t._closeRequested = !1, t._started = !1, t._strategyHWM = h(i), t._pullAlgorithm = o, t._cancelAlgorithm = n, t._autoAllocateChunkSize = a, t._pendingPullIntos = [], e._readableStreamController = t;const s = r();Promise.resolve(s).then(() => { + t._started = !0, xe(t); + }, e => { + nt(t, e); + }).catch(w); + }(e, o, function () { + return d(t, "start", [o]); + }, n, i, r, a); + }(this, e, o = h(o)); + } else { + if (void 0 !== n) throw new RangeError("Invalid type is specified");{ + const t = b(r);void 0 === o && (o = 1), function (e, t, r, o) { + const n = Object.create(ReadableStreamDefaultController.prototype);const i = u(t, "pull", 0, [n]), + a = u(t, "cancel", 1, []);$e(e, n, function () { + return d(t, "start", [n]); + }, i, a, r, o); + }(this, e, o = h(o), t); + } + } + }get locked() { + if (!1 === _e(this)) throw st("locked");return he(this); + }cancel(e) { + return !1 === _e(this) ? Promise.reject(st("cancel")) : !0 === he(this) ? Promise.reject(new TypeError("Cannot cancel a stream that already has a reader")) : pe(this, e); + }getReader({ mode: e } = {}) { + if (!1 === _e(this)) throw st("getReader");if (void 0 === e) return ue(this);if ("byob" === (e = String(e))) return function (e) { + return new ReadableStreamBYOBReader(e); + }(this);throw new RangeError("Invalid mode is specified"); + }pipeThrough({ writable: e, readable: t }, { preventClose: r, preventAbort: o, preventCancel: n, signal: i } = {}) { + if (!1 === _e(this)) throw st("pipeThrough");if (!1 === E(e)) throw new TypeError("writable argument to pipeThrough must be a WritableStream");if (!1 === _e(t)) throw new TypeError("readable argument to pipeThrough must be a ReadableStream");if (r = Boolean(r), o = Boolean(o), n = Boolean(n), void 0 !== i && !at(i)) throw new TypeError("ReadableStream.prototype.pipeThrough's signal option must be an AbortSignal");if (!0 === he(this)) throw new TypeError("ReadableStream.prototype.pipeThrough cannot be used on a locked ReadableStream");if (!0 === C(e)) throw new TypeError("ReadableStream.prototype.pipeThrough cannot be used on a locked WritableStream");return be(this, e, r, o, n, i).catch(() => {}), t; + }pipeTo(e, { preventClose: t, preventAbort: r, preventCancel: o, signal: n } = {}) { + return !1 === _e(this) ? Promise.reject(st("pipeTo")) : !1 === E(e) ? Promise.reject(new TypeError("ReadableStream.prototype.pipeTo's first argument must be a WritableStream")) : (t = Boolean(t), r = Boolean(r), o = Boolean(o), void 0 === n || at(n) ? !0 === he(this) ? Promise.reject(new TypeError("ReadableStream.prototype.pipeTo cannot be used on a locked ReadableStream")) : !0 === C(e) ? Promise.reject(new TypeError("ReadableStream.prototype.pipeTo cannot be used on a locked WritableStream")) : be(this, e, t, r, o, n) : Promise.reject(new TypeError("ReadableStream.prototype.pipeTo's signal option must be an AbortSignal"))); + }tee() { + if (!1 === _e(this)) throw st("tee");const e = function (e, t) { + const r = ue(e);let o, + n, + i, + s, + l, + c = !1, + u = !1, + d = !1;const f = new Promise(e => { + l = e; + });function _() { + return Be(r).then(e => { + const t = e.value, + r = e.done;if (!0 === r && !1 === c && (!1 === u && Le(i._readableStreamController), !1 === d && Le(s._readableStreamController), c = !0), !0 === c) return;const o = t, + n = t;!1 === u && Ie(i._readableStreamController, o), !1 === d && Ie(s._readableStreamController, n); + }); + }function h() {}return i = de(h, _, function (t) { + if (u = !0, o = t, !0 === d) { + const t = a([o, n]), + r = pe(e, t);l(r); + }return f; + }), s = de(h, _, function (t) { + if (d = !0, n = t, !0 === u) { + const t = a([o, n]), + r = pe(e, t);l(r); + }return f; + }), r._closedPromise.catch(e => { + !0 !== c && (De(i._readableStreamController, e), De(s._readableStreamController, e), c = !0); + }), [i, s]; + }(this);return a(e); + } + }function ue(e) { + return new ReadableStreamDefaultReader(e); + }function de(e, t, r, o = 1, n = () => 1) { + const i = Object.create(ReadableStream.prototype);return fe(i), $e(i, Object.create(ReadableStreamDefaultController.prototype), e, t, r, o, n), i; + }function fe(e) { + e._state = "readable", e._reader = void 0, e._storedError = void 0, e._disturbed = !1; + }function _e(e) { + return !!n(e) && !!Object.prototype.hasOwnProperty.call(e, "_readableStreamController"); + }function he(e) { + return void 0 !== e._reader; + }function be(e, t, r, o, n, i) { + const a = ue(e), + s = T(t);let l = !1, + c = Promise.resolve();return new Promise((u, d) => { + let f;if (void 0 !== i) { + if (f = () => { + const r = new DOMException("Aborted", "AbortError"), + i = [];!1 === o && i.push(() => "writable" === t._state ? j(t, r) : Promise.resolve()), !1 === n && i.push(() => "readable" === e._state ? pe(e, r) : Promise.resolve()), b(() => y(i.map(e => e()), e => e), !0, r); + }, !0 === i.aborted) return void f();i.addEventListener("abort", f); + }if (h(e, a._closedPromise, e => { + !1 === o ? b(() => j(t, e), !0, e) : m(!0, e); + }), h(t, s._closedPromise, t => { + !1 === n ? b(() => pe(e, t), !0, t) : m(!0, t); + }), function (e, t, r) { + "closed" === e._state ? r() : t.then(r).catch(w); + }(e, a._closedPromise, () => { + !1 === r ? b(() => function (e) { + const t = e._ownerWritableStream, + r = t._state;return !0 === O(t) || "closed" === r ? Promise.resolve() : "errored" === r ? Promise.reject(t._storedError) : L(e); + }(s)) : m(); + }), !0 === O(t) || "closed" === t._state) { + const t = new TypeError("the destination writable stream closed before all data could be piped to it");!1 === n ? b(() => pe(e, t), !0, t) : m(!0, t); + }function _() { + const e = c;return c.then(() => e !== c ? _() : void 0); + }function h(e, t, r) { + "errored" === e._state ? r(e._storedError) : t.catch(r).catch(w); + }function b(e, r, o) { + function n() { + e().then(() => p(r, o), e => p(!0, e)).catch(w); + }!0 !== l && (l = !0, "writable" === t._state && !1 === O(t) ? _().then(n) : n()); + }function m(e, r) { + !0 !== l && (l = !0, "writable" === t._state && !1 === O(t) ? _().then(() => p(e, r)).catch(w) : p(e, r)); + }function p(e, t) { + M(s), We(a), void 0 !== i && i.removeEventListener("abort", f), e ? d(t) : u(void 0); + }new Promise((e, t) => { + !function r(o) { + o ? e() : (!0 === l ? Promise.resolve(!0) : s._readyPromise.then(() => Be(a).then(({ value: e, done: t }) => !0 === t || (c = Y(s, e).catch(() => {}), !1)))).then(r, t); + }(!1); + }).catch(e => { + c = Promise.resolve(), w(e); + }); + }); + }function me(e, t) { + return new Promise((r, o) => { + const n = { _resolve: r, _reject: o, _forAuthorCode: t };e._reader._readIntoRequests.push(n); + }); + }function ye(e, t) { + return new Promise((r, o) => { + const n = { _resolve: r, _reject: o, _forAuthorCode: t };e._reader._readRequests.push(n); + }); + }function pe(e, t) { + if (e._disturbed = !0, "closed" === e._state) return Promise.resolve(void 0);if ("errored" === e._state) return Promise.reject(e._storedError);return we(e), e._readableStreamController[le](t).then(() => void 0); + }function we(e) { + e._state = "closed";const t = e._reader;if (void 0 !== t) { + if (Ce(t)) { + for (const _ref of t._readRequests) { + const e = _ref._resolve; + const r = _ref._forAuthorCode; + e(ge(void 0, !0, r)); + }t._readRequests = []; + }_t(t); + } + }function ge(e, t, r) { + let o = null;!0 === r && (o = Object.prototype);const n = Object.create(o);return Object.defineProperty(n, "value", { value: e, enumerable: !0, writable: !0, configurable: !0 }), Object.defineProperty(n, "done", { value: t, enumerable: !0, writable: !0, configurable: !0 }), n; + }function Se(e, t) { + e._state = "errored", e._storedError = t;const r = e._reader;if (void 0 !== r) { + if (Ce(r)) { + for (const e of r._readRequests) e._reject(t);r._readRequests = []; + } else { + for (const e of r._readIntoRequests) e._reject(t);r._readIntoRequests = []; + }ft(r, t); + } + }function ve(e, t, r) { + const o = e._reader._readRequests.shift();o._resolve(ge(t, r, o._forAuthorCode)); + }function Re(e) { + return e._reader._readIntoRequests.length; + }function Pe(e) { + return e._reader._readRequests.length; + }function Te(e) { + const t = e._reader;return void 0 !== t && !!Ee(t); + }function qe(e) { + const t = e._reader;return void 0 !== t && !!Ce(t); + }class ReadableStreamDefaultReader { + constructor(e) { + if (!1 === _e(e)) throw new TypeError("ReadableStreamDefaultReader can only be constructed with a ReadableStream instance");if (!0 === he(e)) throw new TypeError("This stream has already been locked for exclusive reading by another reader");je(this, e), this._readRequests = []; + }get closed() { + return Ce(this) ? this._closedPromise : Promise.reject(ct("closed")); + }cancel(e) { + return Ce(this) ? void 0 === this._ownerReadableStream ? Promise.reject(lt("cancel")) : Ae(this, e) : Promise.reject(ct("cancel")); + }read() { + return Ce(this) ? void 0 === this._ownerReadableStream ? Promise.reject(lt("read from")) : Be(this, !0) : Promise.reject(ct("read")); + }releaseLock() { + if (!Ce(this)) throw ct("releaseLock");if (void 0 !== this._ownerReadableStream) { + if (this._readRequests.length > 0) throw new TypeError("Tried to release a reader lock when that reader has pending read() calls un-settled");We(this); + } + } + }class ReadableStreamBYOBReader { + constructor(e) { + if (!_e(e)) throw new TypeError("ReadableStreamBYOBReader can only be constructed with a ReadableStream instance given a byte source");if (!1 === Ne(e._readableStreamController)) throw new TypeError("Cannot construct a ReadableStreamBYOBReader for a stream not constructed with a byte source");if (he(e)) throw new TypeError("This stream has already been locked for exclusive reading by another reader");je(this, e), this._readIntoRequests = []; + }get closed() { + return Ee(this) ? this._closedPromise : Promise.reject(ht("closed")); + }cancel(e) { + return Ee(this) ? void 0 === this._ownerReadableStream ? Promise.reject(lt("cancel")) : Ae(this, e) : Promise.reject(ht("cancel")); + }read(e) { + return Ee(this) ? void 0 === this._ownerReadableStream ? Promise.reject(lt("read from")) : ArrayBuffer.isView(e) ? (e.buffer, 0 === e.byteLength ? Promise.reject(new TypeError("view must have non-zero byteLength")) : function (e, t, r = !1) { + const o = e._ownerReadableStream;if (o._disturbed = !0, "errored" === o._state) return Promise.reject(o._storedError);return function (e, t, r) { + const o = e._controlledReadableByteStream;let n = 1;t.constructor !== DataView && (n = t.constructor.BYTES_PER_ELEMENT);const i = t.constructor, + a = { buffer: _(t.buffer), byteOffset: t.byteOffset, byteLength: t.byteLength, bytesFilled: 0, elementSize: n, ctor: i, readerType: "byob" };if (e._pendingPullIntos.length > 0) return e._pendingPullIntos.push(a), me(o, r);if ("closed" === o._state) { + const e = new i(a.buffer, a.byteOffset, 0);return Promise.resolve(ge(e, !0, r)); + }if (e._queueTotalSize > 0) { + if (!0 === Je(e, a)) { + const t = Ve(a);return Xe(e), Promise.resolve(ge(t, !1, r)); + }if (!0 === e._closeRequested) { + const t = new TypeError("Insufficient bytes to fill elements in the given buffer");return nt(e, t), Promise.reject(t); + } + }e._pendingPullIntos.push(a);const s = me(o, r);return xe(e), s; + }(o._readableStreamController, t, r); + }(this, e, !0)) : Promise.reject(new TypeError("view must be an array buffer view")) : Promise.reject(ht("read")); + }releaseLock() { + if (!Ee(this)) throw ht("releaseLock");if (void 0 !== this._ownerReadableStream) { + if (this._readIntoRequests.length > 0) throw new TypeError("Tried to release a reader lock when that reader has pending read() calls un-settled");We(this); + } + } + }function Ee(e) { + return !!n(e) && !!Object.prototype.hasOwnProperty.call(e, "_readIntoRequests"); + }function Ce(e) { + return !!n(e) && !!Object.prototype.hasOwnProperty.call(e, "_readRequests"); + }function je(e, t) { + e._ownerReadableStream = t, t._reader = e, "readable" === t._state ? ut(e) : "closed" === t._state ? function (e) { + ut(e), _t(e); + }(e) : dt(e, t._storedError); + }function Ae(e, t) { + return pe(e._ownerReadableStream, t); + }function We(e) { + "readable" === e._ownerReadableStream._state ? ft(e, new TypeError("Reader was released and can no longer be used to monitor the stream's closedness")) : function (e, t) { + dt(e, t); + }(e, new TypeError("Reader was released and can no longer be used to monitor the stream's closedness")), e._ownerReadableStream._reader = void 0, e._ownerReadableStream = void 0; + }function Be(e, t = !1) { + const r = e._ownerReadableStream;return r._disturbed = !0, "closed" === r._state ? Promise.resolve(ge(void 0, !0, t)) : "errored" === r._state ? Promise.reject(r._storedError) : r._readableStreamController[ce](t); + }class ReadableStreamDefaultController { + constructor() { + throw new TypeError(); + }get desiredSize() { + if (!1 === Oe(this)) throw bt("desiredSize");return Me(this); + }close() { + if (!1 === Oe(this)) throw bt("close");if (!1 === Ye(this)) throw new TypeError("The stream is not in a state that permits close");Le(this); + }enqueue(e) { + if (!1 === Oe(this)) throw bt("enqueue");if (!1 === Ye(this)) throw new TypeError("The stream is not in a state that permits enqueue");return Ie(this, e); + }error(e) { + if (!1 === Oe(this)) throw bt("error");De(this, e); + }[le](e) { + v(this);const t = this._cancelAlgorithm(e);return Fe(this), t; + }[ce](e) { + const t = this._controlledReadableStream;if (this._queue.length > 0) { + const r = g(this);return !0 === this._closeRequested && 0 === this._queue.length ? (Fe(this), we(t)) : ze(this), Promise.resolve(ge(r, !1, e)); + }const r = ye(t, e);return ze(this), r; + } + }function Oe(e) { + return !!n(e) && !!Object.prototype.hasOwnProperty.call(e, "_controlledReadableStream"); + }function ze(e) { + !1 !== ke(e) && (!0 !== e._pulling ? (e._pulling = !0, e._pullAlgorithm().then(() => { + if (e._pulling = !1, !0 === e._pullAgain) return e._pullAgain = !1, ze(e); + }, t => { + De(e, t); + }).catch(w)) : e._pullAgain = !0); + }function ke(e) { + const t = e._controlledReadableStream;return !1 !== Ye(e) && !1 !== e._started && (!0 === he(t) && Pe(t) > 0 || Me(e) > 0); + }function Fe(e) { + e._pullAlgorithm = void 0, e._cancelAlgorithm = void 0, e._strategySizeAlgorithm = void 0; + }function Le(e) { + const t = e._controlledReadableStream;e._closeRequested = !0, 0 === e._queue.length && (Fe(e), we(t)); + }function Ie(e, t) { + const r = e._controlledReadableStream;if (!0 === he(r) && Pe(r) > 0) ve(r, t, !1);else { + let r;try { + r = e._strategySizeAlgorithm(t); + } catch (t) { + throw De(e, t), t; + }try { + S(e, t, r); + } catch (t) { + throw De(e, t), t; + } + }ze(e); + }function De(e, t) { + const r = e._controlledReadableStream;"readable" === r._state && (v(e), Fe(e), Se(r, t)); + }function Me(e) { + const t = e._controlledReadableStream._state;return "errored" === t ? null : "closed" === t ? 0 : e._strategyHWM - e._queueTotalSize; + }function Ye(e) { + const t = e._controlledReadableStream._state;return !1 === e._closeRequested && "readable" === t; + }function $e(e, t, r, o, n, i, a) { + t._controlledReadableStream = e, t._queue = void 0, t._queueTotalSize = void 0, v(t), t._started = !1, t._closeRequested = !1, t._pullAgain = !1, t._pulling = !1, t._strategySizeAlgorithm = a, t._strategyHWM = i, t._pullAlgorithm = o, t._cancelAlgorithm = n, e._readableStreamController = t;const s = r();Promise.resolve(s).then(() => { + t._started = !0, ze(t); + }, e => { + De(t, e); + }).catch(w); + }class ReadableStreamBYOBRequest { + constructor() { + throw new TypeError("ReadableStreamBYOBRequest cannot be used directly"); + }get view() { + if (!1 === Qe(this)) throw mt("view");return this._view; + }respond(e) { + if (!1 === Qe(this)) throw mt("respond");if (void 0 === this._associatedReadableByteStreamController) throw new TypeError("This BYOB request has been invalidated");this._view.buffer, function (e, t) { + if (!1 === l(t = Number(t))) throw new RangeError("bytesWritten must be a finite");tt(e, t); + }(this._associatedReadableByteStreamController, e); + }respondWithNewView(e) { + if (!1 === Qe(this)) throw mt("respond");if (void 0 === this._associatedReadableByteStreamController) throw new TypeError("This BYOB request has been invalidated");if (!ArrayBuffer.isView(e)) throw new TypeError("You can only respond with array buffer views");e.buffer, function (e, t) { + const r = e._pendingPullIntos[0];if (r.byteOffset + r.bytesFilled !== t.byteOffset) throw new RangeError("The region specified by view does not match byobRequest");if (r.byteLength !== t.byteLength) throw new RangeError("The buffer of view has different capacity than byobRequest");r.buffer = t.buffer, tt(e, t.byteLength); + }(this._associatedReadableByteStreamController, e); + } + }class ReadableByteStreamController { + constructor() { + throw new TypeError("ReadableByteStreamController constructor cannot be used directly"); + }get byobRequest() { + if (!1 === Ne(this)) throw yt("byobRequest");if (void 0 === this._byobRequest && this._pendingPullIntos.length > 0) { + const e = this._pendingPullIntos[0], + t = new Uint8Array(e.buffer, e.byteOffset + e.bytesFilled, e.byteLength - e.bytesFilled), + r = Object.create(ReadableStreamBYOBRequest.prototype);!function (e, t, r) { + e._associatedReadableByteStreamController = t, e._view = r; + }(r, this, t), this._byobRequest = r; + }return this._byobRequest; + }get desiredSize() { + if (!1 === Ne(this)) throw yt("desiredSize");return it(this); + }close() { + if (!1 === Ne(this)) throw yt("close");if (!0 === this._closeRequested) throw new TypeError("The stream has already been closed; do not close it again!");const e = this._controlledReadableByteStream._state;if ("readable" !== e) throw new TypeError(`The stream (in ${e} state) is not in the readable state and cannot be closed`);!function (e) { + const t = e._controlledReadableByteStream;if (e._queueTotalSize > 0) return void (e._closeRequested = !0);if (e._pendingPullIntos.length > 0) { + const t = e._pendingPullIntos[0];if (t.bytesFilled > 0) { + const t = new TypeError("Insufficient bytes to fill elements in the given buffer");throw nt(e, t), t; + } + }ot(e), we(t); + }(this); + }enqueue(e) { + if (!1 === Ne(this)) throw yt("enqueue");if (!0 === this._closeRequested) throw new TypeError("stream is closed or draining");const t = this._controlledReadableByteStream._state;if ("readable" !== t) throw new TypeError(`The stream (in ${t} state) is not in the readable state and cannot be enqueued to`);if (!ArrayBuffer.isView(e)) throw new TypeError("You can only enqueue array buffer views when using a ReadableByteStreamController");e.buffer, function (e, t) { + const r = e._controlledReadableByteStream, + o = t.buffer, + n = t.byteOffset, + i = t.byteLength, + a = _(o);if (!0 === qe(r)) { + if (0 === Pe(r)) Ge(e, a, n, i);else { + const e = new Uint8Array(a, n, i);ve(r, e, !1); + } + } else !0 === Te(r) ? (Ge(e, a, n, i), et(e)) : Ge(e, a, n, i);xe(e); + }(this, e); + }error(e) { + if (!1 === Ne(this)) throw yt("error");nt(this, e); + }[le](e) { + if (this._pendingPullIntos.length > 0) { + this._pendingPullIntos[0].bytesFilled = 0; + }v(this);const t = this._cancelAlgorithm(e);return ot(this), t; + }[ce](e) { + const t = this._controlledReadableByteStream;if (this._queueTotalSize > 0) { + const t = this._queue.shift();let r;this._queueTotalSize -= t.byteLength, Xe(this);try { + r = new Uint8Array(t.buffer, t.byteOffset, t.byteLength); + } catch (e) { + return Promise.reject(e); + }return Promise.resolve(ge(r, !1, e)); + }const r = this._autoAllocateChunkSize;if (void 0 !== r) { + let e;try { + e = new ArrayBuffer(r); + } catch (e) { + return Promise.reject(e); + }const t = { buffer: e, byteOffset: 0, byteLength: r, bytesFilled: 0, elementSize: 1, ctor: Uint8Array, readerType: "default" };this._pendingPullIntos.push(t); + }const o = ye(t, e);return xe(this), o; + } + }function Ne(e) { + return !!n(e) && !!Object.prototype.hasOwnProperty.call(e, "_controlledReadableByteStream"); + }function Qe(e) { + return !!n(e) && !!Object.prototype.hasOwnProperty.call(e, "_associatedReadableByteStreamController"); + }function xe(e) { + !1 !== function (e) { + const t = e._controlledReadableByteStream;if ("readable" !== t._state) return !1;if (!0 === e._closeRequested) return !1;if (!1 === e._started) return !1;if (!0 === qe(t) && Pe(t) > 0) return !0;if (!0 === Te(t) && Re(t) > 0) return !0;if (it(e) > 0) return !0;return !1; + }(e) && (!0 !== e._pulling ? (e._pulling = !0, e._pullAlgorithm().then(() => { + e._pulling = !1, !0 === e._pullAgain && (e._pullAgain = !1, xe(e)); + }, t => { + nt(e, t); + }).catch(w)) : e._pullAgain = !0); + }function He(e) { + Ze(e), e._pendingPullIntos = []; + }function Ue(e, t) { + let r = !1;"closed" === e._state && (r = !0);const o = Ve(t);"default" === t.readerType ? ve(e, o, r) : function (e, t, r) { + const o = e._reader._readIntoRequests.shift();o._resolve(ge(t, r, o._forAuthorCode)); + }(e, o, r); + }function Ve(e) { + const t = e.bytesFilled, + r = e.elementSize;return new e.ctor(e.buffer, e.byteOffset, t / r); + }function Ge(e, t, r, o) { + e._queue.push({ buffer: t, byteOffset: r, byteLength: o }), e._queueTotalSize += o; + }function Je(e, t) { + const r = t.elementSize, + o = t.bytesFilled - t.bytesFilled % r, + n = Math.min(e._queueTotalSize, t.byteLength - t.bytesFilled), + i = t.bytesFilled + n, + a = i - i % r;let l = n, + c = !1;a > o && (l = a - t.bytesFilled, c = !0);const u = e._queue;for (; l > 0;) { + const r = u[0], + o = Math.min(l, r.byteLength), + n = t.byteOffset + t.bytesFilled;s(t.buffer, n, r.buffer, r.byteOffset, o), r.byteLength === o ? u.shift() : (r.byteOffset += o, r.byteLength -= o), e._queueTotalSize -= o, Ke(e, o, t), l -= o; + }return c; + }function Ke(e, t, r) { + Ze(e), r.bytesFilled += t; + }function Xe(e) { + 0 === e._queueTotalSize && !0 === e._closeRequested ? (ot(e), we(e._controlledReadableByteStream)) : xe(e); + }function Ze(e) { + void 0 !== e._byobRequest && (e._byobRequest._associatedReadableByteStreamController = void 0, e._byobRequest._view = void 0, e._byobRequest = void 0); + }function et(e) { + for (; e._pendingPullIntos.length > 0;) { + if (0 === e._queueTotalSize) return;const t = e._pendingPullIntos[0];!0 === Je(e, t) && (rt(e), Ue(e._controlledReadableByteStream, t)); + } + }function tt(e, t) { + const r = e._pendingPullIntos[0];if ("closed" === e._controlledReadableByteStream._state) { + if (0 !== t) throw new TypeError("bytesWritten must be 0 when calling respond() on a closed stream");!function (e, t) { + t.buffer = _(t.buffer);const r = e._controlledReadableByteStream;if (!0 === Te(r)) for (; Re(r) > 0;) Ue(r, rt(e)); + }(e, r); + } else !function (e, t, r) { + if (r.bytesFilled + t > r.byteLength) throw new RangeError("bytesWritten out of range");if (Ke(e, t, r), r.bytesFilled < r.elementSize) return;rt(e);const o = r.bytesFilled % r.elementSize;if (o > 0) { + const t = r.byteOffset + r.bytesFilled, + n = r.buffer.slice(t - o, t);Ge(e, n, 0, n.byteLength); + }r.buffer = _(r.buffer), r.bytesFilled -= o, Ue(e._controlledReadableByteStream, r), et(e); + }(e, t, r);xe(e); + }function rt(e) { + const t = e._pendingPullIntos.shift();return Ze(e), t; + }function ot(e) { + e._pullAlgorithm = void 0, e._cancelAlgorithm = void 0; + }function nt(e, t) { + const r = e._controlledReadableByteStream;"readable" === r._state && (He(e), v(e), ot(e), Se(r, t)); + }function it(e) { + const t = e._controlledReadableByteStream._state;return "errored" === t ? null : "closed" === t ? 0 : e._strategyHWM - e._queueTotalSize; + }function at(e) { + if ("object" != typeof e || null === e) return !1;const t = Object.getOwnPropertyDescriptor(AbortSignal.prototype, "aborted").get;try { + return t.call(e), !0; + } catch (e) { + return !1; + } + }function st(e) { + return new TypeError(`ReadableStream.prototype.${e} can only be used on a ReadableStream`); + }function lt(e) { + return new TypeError("Cannot " + e + " a stream using a released reader"); + }function ct(e) { + return new TypeError(`ReadableStreamDefaultReader.prototype.${e} can only be used on a ReadableStreamDefaultReader`); + }function ut(e) { + e._closedPromise = new Promise((t, r) => { + e._closedPromise_resolve = t, e._closedPromise_reject = r; + }); + }function dt(e, t) { + ut(e), ft(e, t); + }function ft(e, t) { + e._closedPromise.catch(() => {}), e._closedPromise_reject(t), e._closedPromise_resolve = void 0, e._closedPromise_reject = void 0; + }function _t(e) { + e._closedPromise_resolve(void 0), e._closedPromise_resolve = void 0, e._closedPromise_reject = void 0; + }function ht(e) { + return new TypeError(`ReadableStreamBYOBReader.prototype.${e} can only be used on a ReadableStreamBYOBReader`); + }function bt(e) { + return new TypeError(`ReadableStreamDefaultController.prototype.${e} can only be used on a ReadableStreamDefaultController`); + }function mt(e) { + return new TypeError(`ReadableStreamBYOBRequest.prototype.${e} can only be used on a ReadableStreamBYOBRequest`); + }function yt(e) { + return new TypeError(`ReadableByteStreamController.prototype.${e} can only be used on a ReadableByteStreamController`); + }class ByteLengthQueuingStrategy { + constructor({ highWaterMark: e }) { + i(this, "highWaterMark", e); + }size(e) { + return e.byteLength; + } + }class CountQueuingStrategy { + constructor({ highWaterMark: e }) { + i(this, "highWaterMark", e); + }size() { + return 1; + } + }class TransformStream { + constructor(e = {}, t = {}, r = {}) { + const o = t.size;let n = t.highWaterMark;const i = r.size;let a = r.highWaterMark;if (void 0 !== e.writableType) throw new RangeError("Invalid writable type specified");const s = b(o);if (void 0 === n && (n = 1), n = h(n), void 0 !== e.readableType) throw new RangeError("Invalid readable type specified");const l = b(i);let c;void 0 === a && (a = 0), a = h(a), function (e, t, r, o, n, i) { + function a() { + return t; + }e._writable = function (e, t, r, o, n = 1, i = () => 1) { + const a = Object.create(WritableStream.prototype);return q(a), $(a, Object.create(WritableStreamDefaultController.prototype), e, t, r, o, n, i), a; + }(a, function (t) { + return function (e, t) { + const r = e._transformStreamController;if (!0 === e._backpressure) { + const o = e._backpressureChangePromise;return o.then(() => { + const o = e._writable, + n = o._state;if ("erroring" === n) throw o._storedError;return Tt(r, t); + }); + }return Tt(r, t); + }(e, t); + }, function () { + return function (e) { + const t = e._readable, + r = e._transformStreamController, + o = r._flushAlgorithm();return Rt(r), o.then(() => { + if ("errored" === t._state) throw t._storedError;const e = t._readableStreamController;!0 === Ye(e) && Le(e); + }).catch(r => { + throw wt(e, r), t._storedError; + }); + }(e); + }, function (t) { + return function (e, t) { + return wt(e, t), Promise.resolve(); + }(e, t); + }, r, o), e._readable = de(a, function () { + return function (e) { + return St(e, !1), e._backpressureChangePromise; + }(e); + }, function (t) { + return gt(e, t), Promise.resolve(); + }, n, i), e._backpressure = void 0, e._backpressureChangePromise = void 0, e._backpressureChangePromise_resolve = void 0, St(e, !0), e._transformStreamController = void 0; + }(this, new Promise(e => { + c = e; + }), n, s, a, l), function (e, t) { + const r = Object.create(TransformStreamDefaultController.prototype);let o = e => { + try { + return Pt(r, e), Promise.resolve(); + } catch (e) { + return Promise.reject(e); + } + };const n = t.transform;if (void 0 !== n) { + if ("function" != typeof n) throw new TypeError("transform is not a method");o = e => f(n, t, [e, r]); + }const i = u(t, "flush", 0, [r]);!function (e, t, r, o) { + t._controlledTransformStream = e, e._transformStreamController = t, t._transformAlgorithm = r, t._flushAlgorithm = o; + }(e, r, o, i); + }(this, e);const _ = d(e, "start", [this._transformStreamController]);c(_); + }get readable() { + if (!1 === pt(this)) throw Et("readable");return this._readable; + }get writable() { + if (!1 === pt(this)) throw Et("writable");return this._writable; + } + }function pt(e) { + return !!n(e) && !!Object.prototype.hasOwnProperty.call(e, "_transformStreamController"); + }function wt(e, t) { + De(e._readable._readableStreamController, t), gt(e, t); + }function gt(e, t) { + Rt(e._transformStreamController), H(e._writable._writableStreamController, t), !0 === e._backpressure && St(e, !1); + }function St(e, t) { + void 0 !== e._backpressureChangePromise && e._backpressureChangePromise_resolve(), e._backpressureChangePromise = new Promise(t => { + e._backpressureChangePromise_resolve = t; + }), e._backpressure = t; + }class TransformStreamDefaultController { + constructor() { + throw new TypeError("TransformStreamDefaultController instances cannot be created directly"); + }get desiredSize() { + if (!1 === vt(this)) throw qt("desiredSize");return Me(this._controlledTransformStream._readable._readableStreamController); + }enqueue(e) { + if (!1 === vt(this)) throw qt("enqueue");Pt(this, e); + }error(e) { + if (!1 === vt(this)) throw qt("error");!function (e, t) { + wt(e._controlledTransformStream, t); + }(this, e); + }terminate() { + if (!1 === vt(this)) throw qt("terminate");!function (e) { + const t = e._controlledTransformStream, + r = t._readable._readableStreamController;!0 === Ye(r) && Le(r);const o = new TypeError("TransformStream terminated");gt(t, o); + }(this); + } + }function vt(e) { + return !!n(e) && !!Object.prototype.hasOwnProperty.call(e, "_controlledTransformStream"); + }function Rt(e) { + e._transformAlgorithm = void 0, e._flushAlgorithm = void 0; + }function Pt(e, t) { + const r = e._controlledTransformStream, + o = r._readable._readableStreamController;if (!1 === Ye(o)) throw new TypeError("Readable side is not in a state that permits enqueue");try { + Ie(o, t); + } catch (e) { + throw gt(r, e), r._readable._storedError; + }(function (e) { + return !0 !== ke(e); + })(o) !== r._backpressure && St(r, !0); + }function Tt(e, t) { + return e._transformAlgorithm(t).catch(t => { + throw wt(e._controlledTransformStream, t), t; + }); + }function qt(e) { + return new TypeError(`TransformStreamDefaultController.prototype.${e} can only be used on a TransformStreamDefaultController`); + }function Et(e) { + return new TypeError(`TransformStream.prototype.${e} can only be used on a TransformStream`); + }const Ct = { ReadableStream: ReadableStream, WritableStream: WritableStream, ByteLengthQueuingStrategy: ByteLengthQueuingStrategy, CountQueuingStrategy: CountQueuingStrategy, TransformStream: TransformStream };void 0 !== r && Object.assign(r, Ct), e.ReadableStream = ReadableStream, e.WritableStream = WritableStream, e.ByteLengthQueuingStrategy = ByteLengthQueuingStrategy, e.CountQueuingStrategy = CountQueuingStrategy, e.TransformStream = TransformStream, Object.defineProperty(e, "__esModule", { value: !0 }); +}); + + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}],2:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +/** + * @file {@link http://asmjs.org Asm.js} implementation of the {@link https://en.wikipedia.org/wiki/Advanced_Encryption_Standard Advanced Encryption Standard}. + * @author Artem S Vybornov + * @license MIT + */ +var AES_asm = exports.AES_asm = function () { + "use strict"; + + /** + * Galois Field stuff init flag + */ + + var ginit_done = false; + + /** + * Galois Field exponentiation and logarithm tables for 3 (the generator) + */ + var gexp3, glog3; + + /** + * Init Galois Field tables + */ + function ginit() { + gexp3 = [], glog3 = []; + + var a = 1, + c, + d; + for (c = 0; c < 255; c++) { + gexp3[c] = a; + + // Multiply by three + d = a & 0x80, a <<= 1, a &= 255; + if (d === 0x80) a ^= 0x1b; + a ^= gexp3[c]; + + // Set the log table value + glog3[gexp3[c]] = c; + } + gexp3[255] = gexp3[0]; + glog3[0] = 0; + + ginit_done = true; + } + + /** + * Galois Field multiplication + * @param {number} a + * @param {number} b + * @return {number} + */ + function gmul(a, b) { + var c = gexp3[(glog3[a] + glog3[b]) % 255]; + if (a === 0 || b === 0) c = 0; + return c; + } + + /** + * Galois Field reciprocal + * @param {number} a + * @return {number} + */ + function ginv(a) { + var i = gexp3[255 - glog3[a]]; + if (a === 0) i = 0; + return i; + } + + /** + * AES stuff init flag + */ + var aes_init_done = false; + + /** + * Encryption, Decryption, S-Box and KeyTransform tables + * + * @type {number[]} + */ + var aes_sbox; + + /** + * @type {number[]} + */ + var aes_sinv; + + /** + * @type {number[][]} + */ + var aes_enc; + + /** + * @type {number[][]} + */ + var aes_dec; + + /** + * Init AES tables + */ + function aes_init() { + if (!ginit_done) ginit(); + + // Calculates AES S-Box value + function _s(a) { + var c, s, x; + s = x = ginv(a); + for (c = 0; c < 4; c++) { + s = (s << 1 | s >>> 7) & 255; + x ^= s; + } + x ^= 99; + return x; + } + + // Tables + aes_sbox = [], aes_sinv = [], aes_enc = [[], [], [], []], aes_dec = [[], [], [], []]; + + for (var i = 0; i < 256; i++) { + var s = _s(i); + + // S-Box and its inverse + aes_sbox[i] = s; + aes_sinv[s] = i; + + // Ecryption and Decryption tables + aes_enc[0][i] = gmul(2, s) << 24 | s << 16 | s << 8 | gmul(3, s); + aes_dec[0][s] = gmul(14, i) << 24 | gmul(9, i) << 16 | gmul(13, i) << 8 | gmul(11, i); + // Rotate tables + for (var t = 1; t < 4; t++) { + aes_enc[t][i] = aes_enc[t - 1][i] >>> 8 | aes_enc[t - 1][i] << 24; + aes_dec[t][s] = aes_dec[t - 1][s] >>> 8 | aes_dec[t - 1][s] << 24; + } + } + + aes_init_done = true; + } + + /** + * Asm.js module constructor. + * + *

+ * Heap buffer layout by offset: + *

+   * 0x0000   encryption key schedule
+   * 0x0400   decryption key schedule
+   * 0x0800   sbox
+   * 0x0c00   inv sbox
+   * 0x1000   encryption tables
+   * 0x2000   decryption tables
+   * 0x3000   reserved (future GCM multiplication lookup table)
+   * 0x4000   data
+   * 
+ * Don't touch anything before 0x400. + *

+ * + * @alias AES_asm + * @class + * @param foreign - ignored + * @param buffer - heap buffer to link with + */ + var wrapper = function wrapper(foreign, buffer) { + // Init AES stuff for the first time + if (!aes_init_done) aes_init(); + + // Fill up AES tables + var heap = new Uint32Array(buffer); + heap.set(aes_sbox, 0x0800 >> 2); + heap.set(aes_sinv, 0x0c00 >> 2); + for (var i = 0; i < 4; i++) { + heap.set(aes_enc[i], 0x1000 + 0x400 * i >> 2); + heap.set(aes_dec[i], 0x2000 + 0x400 * i >> 2); + } + + /** + * Calculate AES key schedules. + * @instance + * @memberof AES_asm + * @param {number} ks - key size, 4/6/8 (for 128/192/256-bit key correspondingly) + * @param {number} k0 - key vector components + * @param {number} k1 - key vector components + * @param {number} k2 - key vector components + * @param {number} k3 - key vector components + * @param {number} k4 - key vector components + * @param {number} k5 - key vector components + * @param {number} k6 - key vector components + * @param {number} k7 - key vector components + */ + function set_key(ks, k0, k1, k2, k3, k4, k5, k6, k7) { + var ekeys = heap.subarray(0x000, 60), + dkeys = heap.subarray(0x100, 0x100 + 60); + + // Encryption key schedule + ekeys.set([k0, k1, k2, k3, k4, k5, k6, k7]); + for (var i = ks, rcon = 1; i < 4 * ks + 28; i++) { + var k = ekeys[i - 1]; + if (i % ks === 0 || ks === 8 && i % ks === 4) { + k = aes_sbox[k >>> 24] << 24 ^ aes_sbox[k >>> 16 & 255] << 16 ^ aes_sbox[k >>> 8 & 255] << 8 ^ aes_sbox[k & 255]; + } + if (i % ks === 0) { + k = k << 8 ^ k >>> 24 ^ rcon << 24; + rcon = rcon << 1 ^ (rcon & 0x80 ? 0x1b : 0); + } + ekeys[i] = ekeys[i - ks] ^ k; + } + + // Decryption key schedule + for (var j = 0; j < i; j += 4) { + for (var jj = 0; jj < 4; jj++) { + var k = ekeys[i - (4 + j) + (4 - jj) % 4]; + if (j < 4 || j >= i - 4) { + dkeys[j + jj] = k; + } else { + dkeys[j + jj] = aes_dec[0][aes_sbox[k >>> 24]] ^ aes_dec[1][aes_sbox[k >>> 16 & 255]] ^ aes_dec[2][aes_sbox[k >>> 8 & 255]] ^ aes_dec[3][aes_sbox[k & 255]]; + } + } + } + + // Set rounds number + asm.set_rounds(ks + 5); + } + + // create library object with necessary properties + var stdlib = { Uint8Array: Uint8Array, Uint32Array: Uint32Array }; + + var asm = function (stdlib, foreign, buffer) { + "use asm"; + + var S0 = 0, + S1 = 0, + S2 = 0, + S3 = 0, + I0 = 0, + I1 = 0, + I2 = 0, + I3 = 0, + N0 = 0, + N1 = 0, + N2 = 0, + N3 = 0, + M0 = 0, + M1 = 0, + M2 = 0, + M3 = 0, + H0 = 0, + H1 = 0, + H2 = 0, + H3 = 0, + R = 0; + + var HEAP = new stdlib.Uint32Array(buffer), + DATA = new stdlib.Uint8Array(buffer); + + /** + * AES core + * @param {number} k - precomputed key schedule offset + * @param {number} s - precomputed sbox table offset + * @param {number} t - precomputed round table offset + * @param {number} r - number of inner rounds to perform + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _core(k, s, t, r, x0, x1, x2, x3) { + k = k | 0; + s = s | 0; + t = t | 0; + r = r | 0; + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + var t1 = 0, + t2 = 0, + t3 = 0, + y0 = 0, + y1 = 0, + y2 = 0, + y3 = 0, + i = 0; + + t1 = t | 0x400, t2 = t | 0x800, t3 = t | 0xc00; + + // round 0 + x0 = x0 ^ HEAP[(k | 0) >> 2], x1 = x1 ^ HEAP[(k | 4) >> 2], x2 = x2 ^ HEAP[(k | 8) >> 2], x3 = x3 ^ HEAP[(k | 12) >> 2]; + + // round 1..r + for (i = 16; (i | 0) <= r << 4; i = i + 16 | 0) { + y0 = HEAP[(t | x0 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x1 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x2 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x3 << 2 & 1020) >> 2] ^ HEAP[(k | i | 0) >> 2], y1 = HEAP[(t | x1 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x2 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x3 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x0 << 2 & 1020) >> 2] ^ HEAP[(k | i | 4) >> 2], y2 = HEAP[(t | x2 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x3 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x0 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x1 << 2 & 1020) >> 2] ^ HEAP[(k | i | 8) >> 2], y3 = HEAP[(t | x3 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x0 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x1 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x2 << 2 & 1020) >> 2] ^ HEAP[(k | i | 12) >> 2]; + x0 = y0, x1 = y1, x2 = y2, x3 = y3; + } + + // final round + S0 = HEAP[(s | x0 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x1 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x2 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x3 << 2 & 1020) >> 2] ^ HEAP[(k | i | 0) >> 2], S1 = HEAP[(s | x1 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x2 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x3 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x0 << 2 & 1020) >> 2] ^ HEAP[(k | i | 4) >> 2], S2 = HEAP[(s | x2 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x3 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x0 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x1 << 2 & 1020) >> 2] ^ HEAP[(k | i | 8) >> 2], S3 = HEAP[(s | x3 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x0 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x1 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x2 << 2 & 1020) >> 2] ^ HEAP[(k | i | 12) >> 2]; + } + + /** + * ECB mode encryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _ecb_enc(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + _core(0x0000, 0x0800, 0x1000, R, x0, x1, x2, x3); + } + + /** + * ECB mode decryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _ecb_dec(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + var t = 0; + + _core(0x0400, 0x0c00, 0x2000, R, x0, x3, x2, x1); + + t = S1, S1 = S3, S3 = t; + } + + /** + * CBC mode encryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _cbc_enc(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + _core(0x0000, 0x0800, 0x1000, R, I0 ^ x0, I1 ^ x1, I2 ^ x2, I3 ^ x3); + + I0 = S0, I1 = S1, I2 = S2, I3 = S3; + } + + /** + * CBC mode decryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _cbc_dec(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + var t = 0; + + _core(0x0400, 0x0c00, 0x2000, R, x0, x3, x2, x1); + + t = S1, S1 = S3, S3 = t; + + S0 = S0 ^ I0, S1 = S1 ^ I1, S2 = S2 ^ I2, S3 = S3 ^ I3; + + I0 = x0, I1 = x1, I2 = x2, I3 = x3; + } + + /** + * CFB mode encryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _cfb_enc(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + _core(0x0000, 0x0800, 0x1000, R, I0, I1, I2, I3); + + I0 = S0 = S0 ^ x0, I1 = S1 = S1 ^ x1, I2 = S2 = S2 ^ x2, I3 = S3 = S3 ^ x3; + } + + /** + * CFB mode decryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _cfb_dec(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + _core(0x0000, 0x0800, 0x1000, R, I0, I1, I2, I3); + + S0 = S0 ^ x0, S1 = S1 ^ x1, S2 = S2 ^ x2, S3 = S3 ^ x3; + + I0 = x0, I1 = x1, I2 = x2, I3 = x3; + } + + /** + * OFB mode encryption / decryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _ofb(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + _core(0x0000, 0x0800, 0x1000, R, I0, I1, I2, I3); + + I0 = S0, I1 = S1, I2 = S2, I3 = S3; + + S0 = S0 ^ x0, S1 = S1 ^ x1, S2 = S2 ^ x2, S3 = S3 ^ x3; + } + + /** + * CTR mode encryption / decryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _ctr(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + _core(0x0000, 0x0800, 0x1000, R, N0, N1, N2, N3); + + N3 = ~M3 & N3 | M3 & N3 + 1; + N2 = ~M2 & N2 | M2 & N2 + ((N3 | 0) == 0); + N1 = ~M1 & N1 | M1 & N1 + ((N2 | 0) == 0); + N0 = ~M0 & N0 | M0 & N0 + ((N1 | 0) == 0); + + S0 = S0 ^ x0; + S1 = S1 ^ x1; + S2 = S2 ^ x2; + S3 = S3 ^ x3; + } + + /** + * GCM mode MAC calculation + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _gcm_mac(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + var y0 = 0, + y1 = 0, + y2 = 0, + y3 = 0, + z0 = 0, + z1 = 0, + z2 = 0, + z3 = 0, + i = 0, + c = 0; + + x0 = x0 ^ I0, x1 = x1 ^ I1, x2 = x2 ^ I2, x3 = x3 ^ I3; + + y0 = H0 | 0, y1 = H1 | 0, y2 = H2 | 0, y3 = H3 | 0; + + for (; (i | 0) < 128; i = i + 1 | 0) { + if (y0 >>> 31) { + z0 = z0 ^ x0, z1 = z1 ^ x1, z2 = z2 ^ x2, z3 = z3 ^ x3; + } + + y0 = y0 << 1 | y1 >>> 31, y1 = y1 << 1 | y2 >>> 31, y2 = y2 << 1 | y3 >>> 31, y3 = y3 << 1; + + c = x3 & 1; + + x3 = x3 >>> 1 | x2 << 31, x2 = x2 >>> 1 | x1 << 31, x1 = x1 >>> 1 | x0 << 31, x0 = x0 >>> 1; + + if (c) x0 = x0 ^ 0xe1000000; + } + + I0 = z0, I1 = z1, I2 = z2, I3 = z3; + } + + /** + * Set the internal rounds number. + * @instance + * @memberof AES_asm + * @param {number} r - number if inner AES rounds + */ + function set_rounds(r) { + r = r | 0; + R = r; + } + + /** + * Populate the internal state of the module. + * @instance + * @memberof AES_asm + * @param {number} s0 - state vector + * @param {number} s1 - state vector + * @param {number} s2 - state vector + * @param {number} s3 - state vector + */ + function set_state(s0, s1, s2, s3) { + s0 = s0 | 0; + s1 = s1 | 0; + s2 = s2 | 0; + s3 = s3 | 0; + + S0 = s0, S1 = s1, S2 = s2, S3 = s3; + } + + /** + * Populate the internal iv of the module. + * @instance + * @memberof AES_asm + * @param {number} i0 - iv vector + * @param {number} i1 - iv vector + * @param {number} i2 - iv vector + * @param {number} i3 - iv vector + */ + function set_iv(i0, i1, i2, i3) { + i0 = i0 | 0; + i1 = i1 | 0; + i2 = i2 | 0; + i3 = i3 | 0; + + I0 = i0, I1 = i1, I2 = i2, I3 = i3; + } + + /** + * Set nonce for CTR-family modes. + * @instance + * @memberof AES_asm + * @param {number} n0 - nonce vector + * @param {number} n1 - nonce vector + * @param {number} n2 - nonce vector + * @param {number} n3 - nonce vector + */ + function set_nonce(n0, n1, n2, n3) { + n0 = n0 | 0; + n1 = n1 | 0; + n2 = n2 | 0; + n3 = n3 | 0; + + N0 = n0, N1 = n1, N2 = n2, N3 = n3; + } + + /** + * Set counter mask for CTR-family modes. + * @instance + * @memberof AES_asm + * @param {number} m0 - counter mask vector + * @param {number} m1 - counter mask vector + * @param {number} m2 - counter mask vector + * @param {number} m3 - counter mask vector + */ + function set_mask(m0, m1, m2, m3) { + m0 = m0 | 0; + m1 = m1 | 0; + m2 = m2 | 0; + m3 = m3 | 0; + + M0 = m0, M1 = m1, M2 = m2, M3 = m3; + } + + /** + * Set counter for CTR-family modes. + * @instance + * @memberof AES_asm + * @param {number} c0 - counter vector + * @param {number} c1 - counter vector + * @param {number} c2 - counter vector + * @param {number} c3 - counter vector + */ + function set_counter(c0, c1, c2, c3) { + c0 = c0 | 0; + c1 = c1 | 0; + c2 = c2 | 0; + c3 = c3 | 0; + + N3 = ~M3 & N3 | M3 & c3, N2 = ~M2 & N2 | M2 & c2, N1 = ~M1 & N1 | M1 & c1, N0 = ~M0 & N0 | M0 & c0; + } + + /** + * Store the internal state vector into the heap. + * @instance + * @memberof AES_asm + * @param {number} pos - offset where to put the data + * @return {number} The number of bytes have been written into the heap, always 16. + */ + function get_state(pos) { + pos = pos | 0; + + if (pos & 15) return -1; + + DATA[pos | 0] = S0 >>> 24, DATA[pos | 1] = S0 >>> 16 & 255, DATA[pos | 2] = S0 >>> 8 & 255, DATA[pos | 3] = S0 & 255, DATA[pos | 4] = S1 >>> 24, DATA[pos | 5] = S1 >>> 16 & 255, DATA[pos | 6] = S1 >>> 8 & 255, DATA[pos | 7] = S1 & 255, DATA[pos | 8] = S2 >>> 24, DATA[pos | 9] = S2 >>> 16 & 255, DATA[pos | 10] = S2 >>> 8 & 255, DATA[pos | 11] = S2 & 255, DATA[pos | 12] = S3 >>> 24, DATA[pos | 13] = S3 >>> 16 & 255, DATA[pos | 14] = S3 >>> 8 & 255, DATA[pos | 15] = S3 & 255; + + return 16; + } + + /** + * Store the internal iv vector into the heap. + * @instance + * @memberof AES_asm + * @param {number} pos - offset where to put the data + * @return {number} The number of bytes have been written into the heap, always 16. + */ + function get_iv(pos) { + pos = pos | 0; + + if (pos & 15) return -1; + + DATA[pos | 0] = I0 >>> 24, DATA[pos | 1] = I0 >>> 16 & 255, DATA[pos | 2] = I0 >>> 8 & 255, DATA[pos | 3] = I0 & 255, DATA[pos | 4] = I1 >>> 24, DATA[pos | 5] = I1 >>> 16 & 255, DATA[pos | 6] = I1 >>> 8 & 255, DATA[pos | 7] = I1 & 255, DATA[pos | 8] = I2 >>> 24, DATA[pos | 9] = I2 >>> 16 & 255, DATA[pos | 10] = I2 >>> 8 & 255, DATA[pos | 11] = I2 & 255, DATA[pos | 12] = I3 >>> 24, DATA[pos | 13] = I3 >>> 16 & 255, DATA[pos | 14] = I3 >>> 8 & 255, DATA[pos | 15] = I3 & 255; + + return 16; + } + + /** + * GCM initialization. + * @instance + * @memberof AES_asm + */ + function gcm_init() { + _ecb_enc(0, 0, 0, 0); + H0 = S0, H1 = S1, H2 = S2, H3 = S3; + } + + /** + * Perform ciphering operation on the supplied data. + * @instance + * @memberof AES_asm + * @param {number} mode - block cipher mode (see {@link AES_asm} mode constants) + * @param {number} pos - offset of the data being processed + * @param {number} len - length of the data being processed + * @return {number} Actual amount of data have been processed. + */ + function cipher(mode, pos, len) { + mode = mode | 0; + pos = pos | 0; + len = len | 0; + + var ret = 0; + + if (pos & 15) return -1; + + while ((len | 0) >= 16) { + _cipher_modes[mode & 7](DATA[pos | 0] << 24 | DATA[pos | 1] << 16 | DATA[pos | 2] << 8 | DATA[pos | 3], DATA[pos | 4] << 24 | DATA[pos | 5] << 16 | DATA[pos | 6] << 8 | DATA[pos | 7], DATA[pos | 8] << 24 | DATA[pos | 9] << 16 | DATA[pos | 10] << 8 | DATA[pos | 11], DATA[pos | 12] << 24 | DATA[pos | 13] << 16 | DATA[pos | 14] << 8 | DATA[pos | 15]); + + DATA[pos | 0] = S0 >>> 24, DATA[pos | 1] = S0 >>> 16 & 255, DATA[pos | 2] = S0 >>> 8 & 255, DATA[pos | 3] = S0 & 255, DATA[pos | 4] = S1 >>> 24, DATA[pos | 5] = S1 >>> 16 & 255, DATA[pos | 6] = S1 >>> 8 & 255, DATA[pos | 7] = S1 & 255, DATA[pos | 8] = S2 >>> 24, DATA[pos | 9] = S2 >>> 16 & 255, DATA[pos | 10] = S2 >>> 8 & 255, DATA[pos | 11] = S2 & 255, DATA[pos | 12] = S3 >>> 24, DATA[pos | 13] = S3 >>> 16 & 255, DATA[pos | 14] = S3 >>> 8 & 255, DATA[pos | 15] = S3 & 255; + + ret = ret + 16 | 0, pos = pos + 16 | 0, len = len - 16 | 0; + } + + return ret | 0; + } + + /** + * Calculates MAC of the supplied data. + * @instance + * @memberof AES_asm + * @param {number} mode - block cipher mode (see {@link AES_asm} mode constants) + * @param {number} pos - offset of the data being processed + * @param {number} len - length of the data being processed + * @return {number} Actual amount of data have been processed. + */ + function mac(mode, pos, len) { + mode = mode | 0; + pos = pos | 0; + len = len | 0; + + var ret = 0; + + if (pos & 15) return -1; + + while ((len | 0) >= 16) { + _mac_modes[mode & 1](DATA[pos | 0] << 24 | DATA[pos | 1] << 16 | DATA[pos | 2] << 8 | DATA[pos | 3], DATA[pos | 4] << 24 | DATA[pos | 5] << 16 | DATA[pos | 6] << 8 | DATA[pos | 7], DATA[pos | 8] << 24 | DATA[pos | 9] << 16 | DATA[pos | 10] << 8 | DATA[pos | 11], DATA[pos | 12] << 24 | DATA[pos | 13] << 16 | DATA[pos | 14] << 8 | DATA[pos | 15]); + + ret = ret + 16 | 0, pos = pos + 16 | 0, len = len - 16 | 0; + } + + return ret | 0; + } + + /** + * AES cipher modes table (virual methods) + */ + var _cipher_modes = [_ecb_enc, _ecb_dec, _cbc_enc, _cbc_dec, _cfb_enc, _cfb_dec, _ofb, _ctr]; + + /** + * AES MAC modes table (virual methods) + */ + var _mac_modes = [_cbc_enc, _gcm_mac]; + + /** + * Asm.js module exports + */ + return { + set_rounds: set_rounds, + set_state: set_state, + set_iv: set_iv, + set_nonce: set_nonce, + set_mask: set_mask, + set_counter: set_counter, + get_state: get_state, + get_iv: get_iv, + gcm_init: gcm_init, + cipher: cipher, + mac: mac + }; + }(stdlib, foreign, buffer); + + asm.set_key = set_key; + + return asm; + }; + + /** + * AES enciphering mode constants + * @enum {number} + * @const + */ + wrapper.ENC = { + ECB: 0, + CBC: 2, + CFB: 4, + OFB: 6, + CTR: 7 + }, + + /** + * AES deciphering mode constants + * @enum {number} + * @const + */ + wrapper.DEC = { + ECB: 1, + CBC: 3, + CFB: 5, + OFB: 6, + CTR: 7 + }, + + /** + * AES MAC mode constants + * @enum {number} + * @const + */ + wrapper.MAC = { + CBC: 0, + GCM: 1 + }; + + /** + * Heap data offset + * @type {number} + * @const + */ + wrapper.HEAP_DATA = 0x4000; + + return wrapper; +}(); + +},{}],3:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.AES = undefined; + +var _aes = require('./aes.asm'); + +var _utils = require('../other/utils'); + +var _errors = require('../other/errors'); + +var heap_pool = []; +var asm_pool = []; +var AES = /** @class */function () { + function AES(key, iv, padding, mode) { + if (padding === void 0) { + padding = true; + } + this.pos = 0; + this.len = 0; + this.mode = mode; + // The AES object state + this.pos = 0; + this.len = 0; + this.key = key; + this.iv = iv; + this.padding = padding; + // The AES "worker" + this.acquire_asm(); + } + AES.prototype.acquire_asm = function () { + if (this.heap === undefined && this.asm === undefined) { + this.heap = heap_pool.pop() || (0, _utils._heap_init)().subarray(_aes.AES_asm.HEAP_DATA); + this.asm = asm_pool.pop() || (0, _aes.AES_asm)(null, this.heap.buffer); + this.reset(this.key, this.iv); + } + }; + AES.prototype.release_asm = function () { + heap_pool.push(this.heap); + ; + asm_pool.push(this.asm); + this.heap = undefined; + this.asm = undefined; + }; + AES.prototype.reset = function (key, iv) { + // Key + var keylen = key.length; + if (keylen !== 16 && keylen !== 24 && keylen !== 32) throw new _errors.IllegalArgumentError('illegal key size'); + var keyview = new DataView(key.buffer, key.byteOffset, key.byteLength); + this.asm.set_key(keylen >> 2, keyview.getUint32(0), keyview.getUint32(4), keyview.getUint32(8), keyview.getUint32(12), keylen > 16 ? keyview.getUint32(16) : 0, keylen > 16 ? keyview.getUint32(20) : 0, keylen > 24 ? keyview.getUint32(24) : 0, keylen > 24 ? keyview.getUint32(28) : 0); + // IV + if (iv !== undefined) { + if (iv.length !== 16) throw new _errors.IllegalArgumentError('illegal iv size'); + var ivview = new DataView(iv.buffer, iv.byteOffset, iv.byteLength); + this.asm.set_iv(ivview.getUint32(0), ivview.getUint32(4), ivview.getUint32(8), ivview.getUint32(12)); + } else { + this.asm.set_iv(0, 0, 0, 0); + } + }; + AES.prototype.AES_Encrypt_process = function (data) { + if (!(0, _utils.is_bytes)(data)) throw new TypeError("data isn't of expected type"); + this.acquire_asm(); + var asm = this.asm; + var heap = this.heap; + var amode = _aes.AES_asm.ENC[this.mode]; + var hpos = _aes.AES_asm.HEAP_DATA; + var pos = this.pos; + var len = this.len; + var dpos = 0; + var dlen = data.length || 0; + var rpos = 0; + var rlen = len + dlen & -16; + var wlen = 0; + var result = new Uint8Array(rlen); + while (dlen > 0) { + wlen = (0, _utils._heap_write)(heap, pos + len, data, dpos, dlen); + len += wlen; + dpos += wlen; + dlen -= wlen; + wlen = asm.cipher(amode, hpos + pos, len); + if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos); + rpos += wlen; + if (wlen < len) { + pos += wlen; + len -= wlen; + } else { + pos = 0; + len = 0; + } + } + this.pos = pos; + this.len = len; + return result; + }; + AES.prototype.AES_Encrypt_finish = function () { + this.acquire_asm(); + var asm = this.asm; + var heap = this.heap; + var amode = _aes.AES_asm.ENC[this.mode]; + var hpos = _aes.AES_asm.HEAP_DATA; + var pos = this.pos; + var len = this.len; + var plen = 16 - len % 16; + var rlen = len; + if (this.hasOwnProperty('padding')) { + if (this.padding) { + for (var p = 0; p < plen; ++p) { + heap[pos + len + p] = plen; + } + len += plen; + rlen = len; + } else if (len % 16) { + throw new _errors.IllegalArgumentError('data length must be a multiple of the block size'); + } + } else { + len += plen; + } + var result = new Uint8Array(rlen); + if (len) asm.cipher(amode, hpos + pos, len); + if (rlen) result.set(heap.subarray(pos, pos + rlen)); + this.pos = 0; + this.len = 0; + this.release_asm(); + return result; + }; + AES.prototype.AES_Decrypt_process = function (data) { + if (!(0, _utils.is_bytes)(data)) throw new TypeError("data isn't of expected type"); + this.acquire_asm(); + var asm = this.asm; + var heap = this.heap; + var amode = _aes.AES_asm.DEC[this.mode]; + var hpos = _aes.AES_asm.HEAP_DATA; + var pos = this.pos; + var len = this.len; + var dpos = 0; + var dlen = data.length || 0; + var rpos = 0; + var rlen = len + dlen & -16; + var plen = 0; + var wlen = 0; + if (this.padding) { + plen = len + dlen - rlen || 16; + rlen -= plen; + } + var result = new Uint8Array(rlen); + while (dlen > 0) { + wlen = (0, _utils._heap_write)(heap, pos + len, data, dpos, dlen); + len += wlen; + dpos += wlen; + dlen -= wlen; + wlen = asm.cipher(amode, hpos + pos, len - (!dlen ? plen : 0)); + if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos); + rpos += wlen; + if (wlen < len) { + pos += wlen; + len -= wlen; + } else { + pos = 0; + len = 0; + } + } + this.pos = pos; + this.len = len; + return result; + }; + AES.prototype.AES_Decrypt_finish = function () { + this.acquire_asm(); + var asm = this.asm; + var heap = this.heap; + var amode = _aes.AES_asm.DEC[this.mode]; + var hpos = _aes.AES_asm.HEAP_DATA; + var pos = this.pos; + var len = this.len; + var rlen = len; + if (len > 0) { + if (len % 16) { + if (this.hasOwnProperty('padding')) { + throw new _errors.IllegalArgumentError('data length must be a multiple of the block size'); + } else { + len += 16 - len % 16; + } + } + asm.cipher(amode, hpos + pos, len); + if (this.hasOwnProperty('padding') && this.padding) { + var pad = heap[pos + rlen - 1]; + if (pad < 1 || pad > 16 || pad > rlen) throw new _errors.SecurityError('bad padding'); + var pcheck = 0; + for (var i = pad; i > 1; i--) pcheck |= pad ^ heap[pos + rlen - i]; + if (pcheck) throw new _errors.SecurityError('bad padding'); + rlen -= pad; + } + } + var result = new Uint8Array(rlen); + if (rlen > 0) { + result.set(heap.subarray(pos, pos + rlen)); + } + this.pos = 0; + this.len = 0; + this.release_asm(); + return result; + }; + return AES; +}(); +exports.AES = AES; + +},{"../other/errors":14,"../other/utils":15,"./aes.asm":2}],4:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.AES_CBC = undefined; + +var _aes = require('./aes'); + +var _utils = require('../other/utils'); + +var __extends = undefined && undefined.__extends || function () { + var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) { + d.__proto__ = b; + } || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + }; + return function (d, b) { + extendStatics(d, b); + function __() { + this.constructor = d; + } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +}(); + +var AES_CBC = /** @class */function (_super) { + __extends(AES_CBC, _super); + function AES_CBC(key, iv, padding) { + if (padding === void 0) { + padding = true; + } + return _super.call(this, key, iv, padding, 'CBC') || this; + } + AES_CBC.encrypt = function (data, key, padding, iv) { + if (padding === void 0) { + padding = true; + } + return new AES_CBC(key, iv, padding).encrypt(data); + }; + AES_CBC.decrypt = function (data, key, padding, iv) { + if (padding === void 0) { + padding = true; + } + return new AES_CBC(key, iv, padding).decrypt(data); + }; + AES_CBC.prototype.encrypt = function (data) { + var r1 = this.AES_Encrypt_process(data); + var r2 = this.AES_Encrypt_finish(); + return (0, _utils.joinBytes)(r1, r2); + }; + AES_CBC.prototype.decrypt = function (data) { + var r1 = this.AES_Decrypt_process(data); + var r2 = this.AES_Decrypt_finish(); + return (0, _utils.joinBytes)(r1, r2); + }; + return AES_CBC; +}(_aes.AES); +exports.AES_CBC = AES_CBC; + +},{"../other/utils":15,"./aes":3}],5:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.AES_CFB = undefined; + +var _aes = require('./aes'); + +var _utils = require('../other/utils'); + +var __extends = undefined && undefined.__extends || function () { + var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) { + d.__proto__ = b; + } || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + }; + return function (d, b) { + extendStatics(d, b); + function __() { + this.constructor = d; + } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +}(); + +var AES_CFB = /** @class */function (_super) { + __extends(AES_CFB, _super); + function AES_CFB(key, iv) { + var _this = _super.call(this, key, iv, true, 'CFB') || this; + delete _this.padding; + return _this; + } + AES_CFB.encrypt = function (data, key, iv) { + return new AES_CFB(key, iv).encrypt(data); + }; + AES_CFB.decrypt = function (data, key, iv) { + return new AES_CFB(key, iv).decrypt(data); + }; + AES_CFB.prototype.encrypt = function (data) { + var r1 = this.AES_Encrypt_process(data); + var r2 = this.AES_Encrypt_finish(); + return (0, _utils.joinBytes)(r1, r2); + }; + AES_CFB.prototype.decrypt = function (data) { + var r1 = this.AES_Decrypt_process(data); + var r2 = this.AES_Decrypt_finish(); + return (0, _utils.joinBytes)(r1, r2); + }; + return AES_CFB; +}(_aes.AES); +exports.AES_CFB = AES_CFB; + +},{"../other/utils":15,"./aes":3}],6:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.AES_CTR = undefined; + +var _aes = require('./aes'); + +var _errors = require('../other/errors'); + +var _utils = require('../other/utils'); + +var __extends = undefined && undefined.__extends || function () { + var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) { + d.__proto__ = b; + } || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + }; + return function (d, b) { + extendStatics(d, b); + function __() { + this.constructor = d; + } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +}(); + +var AES_CTR = /** @class */function (_super) { + __extends(AES_CTR, _super); + function AES_CTR(key, nonce) { + var _this = _super.call(this, key, undefined, false, 'CTR') || this; + delete _this.padding; + _this.AES_CTR_set_options(nonce); + return _this; + } + AES_CTR.encrypt = function (data, key, nonce) { + return new AES_CTR(key, nonce).encrypt(data); + }; + AES_CTR.decrypt = function (data, key, nonce) { + return new AES_CTR(key, nonce).encrypt(data); + }; + AES_CTR.prototype.encrypt = function (data) { + var r1 = this.AES_Encrypt_process(data); + var r2 = this.AES_Encrypt_finish(); + return (0, _utils.joinBytes)(r1, r2); + }; + AES_CTR.prototype.decrypt = function (data) { + var r1 = this.AES_Encrypt_process(data); + var r2 = this.AES_Encrypt_finish(); + return (0, _utils.joinBytes)(r1, r2); + }; + AES_CTR.prototype.AES_CTR_set_options = function (nonce, counter, size) { + if (size !== undefined) { + if (size < 8 || size > 48) throw new _errors.IllegalArgumentError('illegal counter size'); + var mask = Math.pow(2, size) - 1; + this.asm.set_mask(0, 0, mask / 0x100000000 | 0, mask | 0); + } else { + size = 48; + this.asm.set_mask(0, 0, 0xffff, 0xffffffff); + } + if (nonce !== undefined) { + var len = nonce.length; + if (!len || len > 16) throw new _errors.IllegalArgumentError('illegal nonce size'); + var view = new DataView(new ArrayBuffer(16)); + new Uint8Array(view.buffer).set(nonce); + this.asm.set_nonce(view.getUint32(0), view.getUint32(4), view.getUint32(8), view.getUint32(12)); + } else { + throw new Error('nonce is required'); + } + if (counter !== undefined) { + if (counter < 0 || counter >= Math.pow(2, size)) throw new _errors.IllegalArgumentError('illegal counter value'); + this.asm.set_counter(0, 0, counter / 0x100000000 | 0, counter | 0); + } + }; + return AES_CTR; +}(_aes.AES); +exports.AES_CTR = AES_CTR; + +},{"../other/errors":14,"../other/utils":15,"./aes":3}],7:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.AES_ECB = undefined; + +var _aes = require('./aes'); + +var _utils = require('../other/utils'); + +var __extends = undefined && undefined.__extends || function () { + var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) { + d.__proto__ = b; + } || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + }; + return function (d, b) { + extendStatics(d, b); + function __() { + this.constructor = d; + } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +}(); + +var AES_ECB = /** @class */function (_super) { + __extends(AES_ECB, _super); + function AES_ECB(key, padding) { + if (padding === void 0) { + padding = false; + } + return _super.call(this, key, undefined, padding, 'ECB') || this; + } + AES_ECB.encrypt = function (data, key, padding) { + if (padding === void 0) { + padding = false; + } + return new AES_ECB(key, padding).encrypt(data); + }; + AES_ECB.decrypt = function (data, key, padding) { + if (padding === void 0) { + padding = false; + } + return new AES_ECB(key, padding).decrypt(data); + }; + AES_ECB.prototype.encrypt = function (data) { + var r1 = this.AES_Encrypt_process(data); + var r2 = this.AES_Encrypt_finish(); + return (0, _utils.joinBytes)(r1, r2); + }; + AES_ECB.prototype.decrypt = function (data) { + var r1 = this.AES_Decrypt_process(data); + var r2 = this.AES_Decrypt_finish(); + return (0, _utils.joinBytes)(r1, r2); + }; + return AES_ECB; +}(_aes.AES); +exports.AES_ECB = AES_ECB; + +},{"../other/utils":15,"./aes":3}],8:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.AES_GCM = undefined; + +var _errors = require('../other/errors'); + +var _utils = require('../other/utils'); + +var _aes = require('./aes'); + +var _aes2 = require('./aes.asm'); + +var __extends = undefined && undefined.__extends || function () { + var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) { + d.__proto__ = b; + } || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + }; + return function (d, b) { + extendStatics(d, b); + function __() { + this.constructor = d; + } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +}(); + +var _AES_GCM_data_maxLength = 68719476704; // 2^36 - 2^5 +var AES_GCM = /** @class */function (_super) { + __extends(AES_GCM, _super); + function AES_GCM(key, nonce, adata, tagSize) { + if (tagSize === void 0) { + tagSize = 16; + } + var _this = _super.call(this, key, undefined, false, 'CTR') || this; + _this.tagSize = tagSize; + _this.gamma0 = 0; + _this.counter = 1; + // Init GCM + _this.asm.gcm_init(); + // Tag size + if (_this.tagSize < 4 || _this.tagSize > 16) throw new _errors.IllegalArgumentError('illegal tagSize value'); + // Nonce + var noncelen = nonce.length || 0; + var noncebuf = new Uint8Array(16); + if (noncelen !== 12) { + _this._gcm_mac_process(nonce); + _this.heap[0] = 0; + _this.heap[1] = 0; + _this.heap[2] = 0; + _this.heap[3] = 0; + _this.heap[4] = 0; + _this.heap[5] = 0; + _this.heap[6] = 0; + _this.heap[7] = 0; + _this.heap[8] = 0; + _this.heap[9] = 0; + _this.heap[10] = 0; + _this.heap[11] = noncelen >>> 29; + _this.heap[12] = noncelen >>> 21 & 255; + _this.heap[13] = noncelen >>> 13 & 255; + _this.heap[14] = noncelen >>> 5 & 255; + _this.heap[15] = noncelen << 3 & 255; + _this.asm.mac(_aes2.AES_asm.MAC.GCM, _aes2.AES_asm.HEAP_DATA, 16); + _this.asm.get_iv(_aes2.AES_asm.HEAP_DATA); + _this.asm.set_iv(0, 0, 0, 0); + noncebuf.set(_this.heap.subarray(0, 16)); + } else { + noncebuf.set(nonce); + noncebuf[15] = 1; + } + var nonceview = new DataView(noncebuf.buffer); + _this.gamma0 = nonceview.getUint32(12); + _this.asm.set_nonce(nonceview.getUint32(0), nonceview.getUint32(4), nonceview.getUint32(8), 0); + _this.asm.set_mask(0, 0, 0, 0xffffffff); + // Associated data + if (adata !== undefined) { + if (adata.length > _AES_GCM_data_maxLength) throw new _errors.IllegalArgumentError('illegal adata length'); + if (adata.length) { + _this.adata = adata; + _this._gcm_mac_process(adata); + } else { + _this.adata = undefined; + } + } else { + _this.adata = undefined; + } + // Counter + if (_this.counter < 1 || _this.counter > 0xffffffff) throw new RangeError('counter must be a positive 32-bit integer'); + _this.asm.set_counter(0, 0, 0, _this.gamma0 + _this.counter | 0); + return _this; + } + AES_GCM.encrypt = function (cleartext, key, nonce, adata, tagsize) { + return new AES_GCM(key, nonce, adata, tagsize).encrypt(cleartext); + }; + AES_GCM.decrypt = function (ciphertext, key, nonce, adata, tagsize) { + return new AES_GCM(key, nonce, adata, tagsize).decrypt(ciphertext); + }; + AES_GCM.prototype.encrypt = function (data) { + return this.AES_GCM_encrypt(data); + }; + AES_GCM.prototype.decrypt = function (data) { + return this.AES_GCM_decrypt(data); + }; + AES_GCM.prototype.AES_GCM_Encrypt_process = function (data) { + var dpos = 0; + var dlen = data.length || 0; + var asm = this.asm; + var heap = this.heap; + var counter = this.counter; + var pos = this.pos; + var len = this.len; + var rpos = 0; + var rlen = len + dlen & -16; + var wlen = 0; + if ((counter - 1 << 4) + len + dlen > _AES_GCM_data_maxLength) throw new RangeError('counter overflow'); + var result = new Uint8Array(rlen); + while (dlen > 0) { + wlen = (0, _utils._heap_write)(heap, pos + len, data, dpos, dlen); + len += wlen; + dpos += wlen; + dlen -= wlen; + wlen = asm.cipher(_aes2.AES_asm.ENC.CTR, _aes2.AES_asm.HEAP_DATA + pos, len); + wlen = asm.mac(_aes2.AES_asm.MAC.GCM, _aes2.AES_asm.HEAP_DATA + pos, wlen); + if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos); + counter += wlen >>> 4; + rpos += wlen; + if (wlen < len) { + pos += wlen; + len -= wlen; + } else { + pos = 0; + len = 0; + } + } + this.counter = counter; + this.pos = pos; + this.len = len; + return result; + }; + AES_GCM.prototype.AES_GCM_Encrypt_finish = function () { + var asm = this.asm; + var heap = this.heap; + var counter = this.counter; + var tagSize = this.tagSize; + var adata = this.adata; + var pos = this.pos; + var len = this.len; + var result = new Uint8Array(len + tagSize); + asm.cipher(_aes2.AES_asm.ENC.CTR, _aes2.AES_asm.HEAP_DATA + pos, len + 15 & -16); + if (len) result.set(heap.subarray(pos, pos + len)); + var i = len; + for (; i & 15; i++) heap[pos + i] = 0; + asm.mac(_aes2.AES_asm.MAC.GCM, _aes2.AES_asm.HEAP_DATA + pos, i); + var alen = adata !== undefined ? adata.length : 0; + var clen = (counter - 1 << 4) + len; + heap[0] = 0; + heap[1] = 0; + heap[2] = 0; + heap[3] = alen >>> 29; + heap[4] = alen >>> 21; + heap[5] = alen >>> 13 & 255; + heap[6] = alen >>> 5 & 255; + heap[7] = alen << 3 & 255; + heap[8] = heap[9] = heap[10] = 0; + heap[11] = clen >>> 29; + heap[12] = clen >>> 21 & 255; + heap[13] = clen >>> 13 & 255; + heap[14] = clen >>> 5 & 255; + heap[15] = clen << 3 & 255; + asm.mac(_aes2.AES_asm.MAC.GCM, _aes2.AES_asm.HEAP_DATA, 16); + asm.get_iv(_aes2.AES_asm.HEAP_DATA); + asm.set_counter(0, 0, 0, this.gamma0); + asm.cipher(_aes2.AES_asm.ENC.CTR, _aes2.AES_asm.HEAP_DATA, 16); + result.set(heap.subarray(0, tagSize), len); + this.counter = 1; + this.pos = 0; + this.len = 0; + return result; + }; + AES_GCM.prototype.AES_GCM_Decrypt_process = function (data) { + var dpos = 0; + var dlen = data.length || 0; + var asm = this.asm; + var heap = this.heap; + var counter = this.counter; + var tagSize = this.tagSize; + var pos = this.pos; + var len = this.len; + var rpos = 0; + var rlen = len + dlen > tagSize ? len + dlen - tagSize & -16 : 0; + var tlen = len + dlen - rlen; + var wlen = 0; + if ((counter - 1 << 4) + len + dlen > _AES_GCM_data_maxLength) throw new RangeError('counter overflow'); + var result = new Uint8Array(rlen); + while (dlen > tlen) { + wlen = (0, _utils._heap_write)(heap, pos + len, data, dpos, dlen - tlen); + len += wlen; + dpos += wlen; + dlen -= wlen; + wlen = asm.mac(_aes2.AES_asm.MAC.GCM, _aes2.AES_asm.HEAP_DATA + pos, wlen); + wlen = asm.cipher(_aes2.AES_asm.DEC.CTR, _aes2.AES_asm.HEAP_DATA + pos, wlen); + if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos); + counter += wlen >>> 4; + rpos += wlen; + pos = 0; + len = 0; + } + if (dlen > 0) { + len += (0, _utils._heap_write)(heap, 0, data, dpos, dlen); + } + this.counter = counter; + this.pos = pos; + this.len = len; + return result; + }; + AES_GCM.prototype.AES_GCM_Decrypt_finish = function () { + var asm = this.asm; + var heap = this.heap; + var tagSize = this.tagSize; + var adata = this.adata; + var counter = this.counter; + var pos = this.pos; + var len = this.len; + var rlen = len - tagSize; + if (len < tagSize) throw new _errors.IllegalStateError('authentication tag not found'); + var result = new Uint8Array(rlen); + var atag = new Uint8Array(heap.subarray(pos + rlen, pos + len)); + var i = rlen; + for (; i & 15; i++) heap[pos + i] = 0; + asm.mac(_aes2.AES_asm.MAC.GCM, _aes2.AES_asm.HEAP_DATA + pos, i); + asm.cipher(_aes2.AES_asm.DEC.CTR, _aes2.AES_asm.HEAP_DATA + pos, i); + if (rlen) result.set(heap.subarray(pos, pos + rlen)); + var alen = adata !== undefined ? adata.length : 0; + var clen = (counter - 1 << 4) + len - tagSize; + heap[0] = 0; + heap[1] = 0; + heap[2] = 0; + heap[3] = alen >>> 29; + heap[4] = alen >>> 21; + heap[5] = alen >>> 13 & 255; + heap[6] = alen >>> 5 & 255; + heap[7] = alen << 3 & 255; + heap[8] = heap[9] = heap[10] = 0; + heap[11] = clen >>> 29; + heap[12] = clen >>> 21 & 255; + heap[13] = clen >>> 13 & 255; + heap[14] = clen >>> 5 & 255; + heap[15] = clen << 3 & 255; + asm.mac(_aes2.AES_asm.MAC.GCM, _aes2.AES_asm.HEAP_DATA, 16); + asm.get_iv(_aes2.AES_asm.HEAP_DATA); + asm.set_counter(0, 0, 0, this.gamma0); + asm.cipher(_aes2.AES_asm.ENC.CTR, _aes2.AES_asm.HEAP_DATA, 16); + var acheck = 0; + for (var i_1 = 0; i_1 < tagSize; ++i_1) acheck |= atag[i_1] ^ heap[i_1]; + if (acheck) throw new _errors.SecurityError('data integrity check failed'); + this.counter = 1; + this.pos = 0; + this.len = 0; + return result; + }; + AES_GCM.prototype.AES_GCM_decrypt = function (data) { + var result1 = this.AES_GCM_Decrypt_process(data); + var result2 = this.AES_GCM_Decrypt_finish(); + var result = new Uint8Array(result1.length + result2.length); + if (result1.length) result.set(result1); + if (result2.length) result.set(result2, result1.length); + return result; + }; + AES_GCM.prototype.AES_GCM_encrypt = function (data) { + var result1 = this.AES_GCM_Encrypt_process(data); + var result2 = this.AES_GCM_Encrypt_finish(); + var result = new Uint8Array(result1.length + result2.length); + if (result1.length) result.set(result1); + if (result2.length) result.set(result2, result1.length); + return result; + }; + AES_GCM.prototype._gcm_mac_process = function (data) { + var heap = this.heap; + var asm = this.asm; + var dpos = 0; + var dlen = data.length || 0; + var wlen = 0; + while (dlen > 0) { + wlen = (0, _utils._heap_write)(heap, 0, data, dpos, dlen); + dpos += wlen; + dlen -= wlen; + while (wlen & 15) heap[wlen++] = 0; + asm.mac(_aes2.AES_asm.MAC.GCM, _aes2.AES_asm.HEAP_DATA, wlen); + } + }; + return AES_GCM; +}(_aes.AES); +exports.AES_GCM = AES_GCM; + +},{"../other/errors":14,"../other/utils":15,"./aes":3,"./aes.asm":2}],9:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Hash = undefined; + +var _utils = require('../other/utils'); + +var _errors = require('../other/errors'); + +var Hash = /** @class */function () { + function Hash() { + this.pos = 0; + this.len = 0; + this.acquire_asm(); + } + Hash.prototype.acquire_asm = function () { + if (this.heap === undefined && this.asm === undefined) { + this.heap = this.constructor.heap_pool.pop() || (0, _utils._heap_init)(); + this.asm = this.constructor.asm_pool.pop() || this.constructor.asm_function({ Uint8Array: Uint8Array }, null, this.heap.buffer); + this.reset(); + } + }; + Hash.prototype.release_asm = function () { + this.constructor.heap_pool.push(this.heap); + ; + this.constructor.asm_pool.push(this.asm); + this.heap = undefined; + this.asm = undefined; + }; + Hash.prototype.reset = function () { + this.acquire_asm(); + this.result = null; + this.pos = 0; + this.len = 0; + this.asm.reset(); + return this; + }; + Hash.prototype.process = function (data) { + if (this.result !== null) throw new _errors.IllegalStateError('state must be reset before processing new data'); + this.acquire_asm(); + var asm = this.asm; + var heap = this.heap; + var hpos = this.pos; + var hlen = this.len; + var dpos = 0; + var dlen = data.length; + var wlen = 0; + while (dlen > 0) { + wlen = (0, _utils._heap_write)(heap, hpos + hlen, data, dpos, dlen); + hlen += wlen; + dpos += wlen; + dlen -= wlen; + wlen = asm.process(hpos, hlen); + hpos += wlen; + hlen -= wlen; + if (!hlen) hpos = 0; + } + this.pos = hpos; + this.len = hlen; + return this; + }; + Hash.prototype.finish = function () { + if (this.result !== null) throw new _errors.IllegalStateError('state must be reset before processing new data'); + this.acquire_asm(); + this.asm.finish(this.pos, this.len, 0); + this.result = new Uint8Array(this.HASH_SIZE); + this.result.set(this.heap.subarray(0, this.HASH_SIZE)); + this.pos = 0; + this.len = 0; + this.release_asm(); + return this; + }; + return Hash; +}(); +exports.Hash = Hash; + +},{"../other/errors":14,"../other/utils":15}],10:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.sha1_asm = sha1_asm; +function sha1_asm(stdlib, foreign, buffer) { + "use asm"; + + // SHA256 state + + var H0 = 0, + H1 = 0, + H2 = 0, + H3 = 0, + H4 = 0, + TOTAL0 = 0, + TOTAL1 = 0; + + // HMAC state + var I0 = 0, + I1 = 0, + I2 = 0, + I3 = 0, + I4 = 0, + O0 = 0, + O1 = 0, + O2 = 0, + O3 = 0, + O4 = 0; + + // I/O buffer + var HEAP = new stdlib.Uint8Array(buffer); + + function _core(w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15) { + w0 = w0 | 0; + w1 = w1 | 0; + w2 = w2 | 0; + w3 = w3 | 0; + w4 = w4 | 0; + w5 = w5 | 0; + w6 = w6 | 0; + w7 = w7 | 0; + w8 = w8 | 0; + w9 = w9 | 0; + w10 = w10 | 0; + w11 = w11 | 0; + w12 = w12 | 0; + w13 = w13 | 0; + w14 = w14 | 0; + w15 = w15 | 0; + + var a = 0, + b = 0, + c = 0, + d = 0, + e = 0, + n = 0, + t = 0, + w16 = 0, + w17 = 0, + w18 = 0, + w19 = 0, + w20 = 0, + w21 = 0, + w22 = 0, + w23 = 0, + w24 = 0, + w25 = 0, + w26 = 0, + w27 = 0, + w28 = 0, + w29 = 0, + w30 = 0, + w31 = 0, + w32 = 0, + w33 = 0, + w34 = 0, + w35 = 0, + w36 = 0, + w37 = 0, + w38 = 0, + w39 = 0, + w40 = 0, + w41 = 0, + w42 = 0, + w43 = 0, + w44 = 0, + w45 = 0, + w46 = 0, + w47 = 0, + w48 = 0, + w49 = 0, + w50 = 0, + w51 = 0, + w52 = 0, + w53 = 0, + w54 = 0, + w55 = 0, + w56 = 0, + w57 = 0, + w58 = 0, + w59 = 0, + w60 = 0, + w61 = 0, + w62 = 0, + w63 = 0, + w64 = 0, + w65 = 0, + w66 = 0, + w67 = 0, + w68 = 0, + w69 = 0, + w70 = 0, + w71 = 0, + w72 = 0, + w73 = 0, + w74 = 0, + w75 = 0, + w76 = 0, + w77 = 0, + w78 = 0, + w79 = 0; + + a = H0; + b = H1; + c = H2; + d = H3; + e = H4; + + // 0 + t = w0 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 1 + t = w1 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 2 + t = w2 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 3 + t = w3 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 4 + t = w4 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 5 + t = w5 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 6 + t = w6 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 7 + t = w7 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 8 + t = w8 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 9 + t = w9 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 10 + t = w10 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 11 + t = w11 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 12 + t = w12 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 13 + t = w13 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 14 + t = w14 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 15 + t = w15 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 16 + n = w13 ^ w8 ^ w2 ^ w0; + w16 = n << 1 | n >>> 31; + t = w16 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 17 + n = w14 ^ w9 ^ w3 ^ w1; + w17 = n << 1 | n >>> 31; + t = w17 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 18 + n = w15 ^ w10 ^ w4 ^ w2; + w18 = n << 1 | n >>> 31; + t = w18 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 19 + n = w16 ^ w11 ^ w5 ^ w3; + w19 = n << 1 | n >>> 31; + t = w19 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 20 + n = w17 ^ w12 ^ w6 ^ w4; + w20 = n << 1 | n >>> 31; + t = w20 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 21 + n = w18 ^ w13 ^ w7 ^ w5; + w21 = n << 1 | n >>> 31; + t = w21 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 22 + n = w19 ^ w14 ^ w8 ^ w6; + w22 = n << 1 | n >>> 31; + t = w22 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 23 + n = w20 ^ w15 ^ w9 ^ w7; + w23 = n << 1 | n >>> 31; + t = w23 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 24 + n = w21 ^ w16 ^ w10 ^ w8; + w24 = n << 1 | n >>> 31; + t = w24 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 25 + n = w22 ^ w17 ^ w11 ^ w9; + w25 = n << 1 | n >>> 31; + t = w25 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 26 + n = w23 ^ w18 ^ w12 ^ w10; + w26 = n << 1 | n >>> 31; + t = w26 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 27 + n = w24 ^ w19 ^ w13 ^ w11; + w27 = n << 1 | n >>> 31; + t = w27 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 28 + n = w25 ^ w20 ^ w14 ^ w12; + w28 = n << 1 | n >>> 31; + t = w28 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 29 + n = w26 ^ w21 ^ w15 ^ w13; + w29 = n << 1 | n >>> 31; + t = w29 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 30 + n = w27 ^ w22 ^ w16 ^ w14; + w30 = n << 1 | n >>> 31; + t = w30 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 31 + n = w28 ^ w23 ^ w17 ^ w15; + w31 = n << 1 | n >>> 31; + t = w31 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 32 + n = w29 ^ w24 ^ w18 ^ w16; + w32 = n << 1 | n >>> 31; + t = w32 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 33 + n = w30 ^ w25 ^ w19 ^ w17; + w33 = n << 1 | n >>> 31; + t = w33 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 34 + n = w31 ^ w26 ^ w20 ^ w18; + w34 = n << 1 | n >>> 31; + t = w34 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 35 + n = w32 ^ w27 ^ w21 ^ w19; + w35 = n << 1 | n >>> 31; + t = w35 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 36 + n = w33 ^ w28 ^ w22 ^ w20; + w36 = n << 1 | n >>> 31; + t = w36 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 37 + n = w34 ^ w29 ^ w23 ^ w21; + w37 = n << 1 | n >>> 31; + t = w37 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 38 + n = w35 ^ w30 ^ w24 ^ w22; + w38 = n << 1 | n >>> 31; + t = w38 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 39 + n = w36 ^ w31 ^ w25 ^ w23; + w39 = n << 1 | n >>> 31; + t = w39 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 40 + n = w37 ^ w32 ^ w26 ^ w24; + w40 = n << 1 | n >>> 31; + t = w40 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 41 + n = w38 ^ w33 ^ w27 ^ w25; + w41 = n << 1 | n >>> 31; + t = w41 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 42 + n = w39 ^ w34 ^ w28 ^ w26; + w42 = n << 1 | n >>> 31; + t = w42 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 43 + n = w40 ^ w35 ^ w29 ^ w27; + w43 = n << 1 | n >>> 31; + t = w43 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 44 + n = w41 ^ w36 ^ w30 ^ w28; + w44 = n << 1 | n >>> 31; + t = w44 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 45 + n = w42 ^ w37 ^ w31 ^ w29; + w45 = n << 1 | n >>> 31; + t = w45 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 46 + n = w43 ^ w38 ^ w32 ^ w30; + w46 = n << 1 | n >>> 31; + t = w46 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 47 + n = w44 ^ w39 ^ w33 ^ w31; + w47 = n << 1 | n >>> 31; + t = w47 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 48 + n = w45 ^ w40 ^ w34 ^ w32; + w48 = n << 1 | n >>> 31; + t = w48 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 49 + n = w46 ^ w41 ^ w35 ^ w33; + w49 = n << 1 | n >>> 31; + t = w49 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 50 + n = w47 ^ w42 ^ w36 ^ w34; + w50 = n << 1 | n >>> 31; + t = w50 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 51 + n = w48 ^ w43 ^ w37 ^ w35; + w51 = n << 1 | n >>> 31; + t = w51 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 52 + n = w49 ^ w44 ^ w38 ^ w36; + w52 = n << 1 | n >>> 31; + t = w52 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 53 + n = w50 ^ w45 ^ w39 ^ w37; + w53 = n << 1 | n >>> 31; + t = w53 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 54 + n = w51 ^ w46 ^ w40 ^ w38; + w54 = n << 1 | n >>> 31; + t = w54 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 55 + n = w52 ^ w47 ^ w41 ^ w39; + w55 = n << 1 | n >>> 31; + t = w55 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 56 + n = w53 ^ w48 ^ w42 ^ w40; + w56 = n << 1 | n >>> 31; + t = w56 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 57 + n = w54 ^ w49 ^ w43 ^ w41; + w57 = n << 1 | n >>> 31; + t = w57 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 58 + n = w55 ^ w50 ^ w44 ^ w42; + w58 = n << 1 | n >>> 31; + t = w58 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 59 + n = w56 ^ w51 ^ w45 ^ w43; + w59 = n << 1 | n >>> 31; + t = w59 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 60 + n = w57 ^ w52 ^ w46 ^ w44; + w60 = n << 1 | n >>> 31; + t = w60 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 61 + n = w58 ^ w53 ^ w47 ^ w45; + w61 = n << 1 | n >>> 31; + t = w61 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 62 + n = w59 ^ w54 ^ w48 ^ w46; + w62 = n << 1 | n >>> 31; + t = w62 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 63 + n = w60 ^ w55 ^ w49 ^ w47; + w63 = n << 1 | n >>> 31; + t = w63 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 64 + n = w61 ^ w56 ^ w50 ^ w48; + w64 = n << 1 | n >>> 31; + t = w64 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 65 + n = w62 ^ w57 ^ w51 ^ w49; + w65 = n << 1 | n >>> 31; + t = w65 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 66 + n = w63 ^ w58 ^ w52 ^ w50; + w66 = n << 1 | n >>> 31; + t = w66 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 67 + n = w64 ^ w59 ^ w53 ^ w51; + w67 = n << 1 | n >>> 31; + t = w67 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 68 + n = w65 ^ w60 ^ w54 ^ w52; + w68 = n << 1 | n >>> 31; + t = w68 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 69 + n = w66 ^ w61 ^ w55 ^ w53; + w69 = n << 1 | n >>> 31; + t = w69 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 70 + n = w67 ^ w62 ^ w56 ^ w54; + w70 = n << 1 | n >>> 31; + t = w70 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 71 + n = w68 ^ w63 ^ w57 ^ w55; + w71 = n << 1 | n >>> 31; + t = w71 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 72 + n = w69 ^ w64 ^ w58 ^ w56; + w72 = n << 1 | n >>> 31; + t = w72 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 73 + n = w70 ^ w65 ^ w59 ^ w57; + w73 = n << 1 | n >>> 31; + t = w73 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 74 + n = w71 ^ w66 ^ w60 ^ w58; + w74 = n << 1 | n >>> 31; + t = w74 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 75 + n = w72 ^ w67 ^ w61 ^ w59; + w75 = n << 1 | n >>> 31; + t = w75 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 76 + n = w73 ^ w68 ^ w62 ^ w60; + w76 = n << 1 | n >>> 31; + t = w76 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 77 + n = w74 ^ w69 ^ w63 ^ w61; + w77 = n << 1 | n >>> 31; + t = w77 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 78 + n = w75 ^ w70 ^ w64 ^ w62; + w78 = n << 1 | n >>> 31; + t = w78 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + // 79 + n = w76 ^ w71 ^ w65 ^ w63; + w79 = n << 1 | n >>> 31; + t = w79 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; + e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; + + H0 = H0 + a | 0; + H1 = H1 + b | 0; + H2 = H2 + c | 0; + H3 = H3 + d | 0; + H4 = H4 + e | 0; + } + + function _core_heap(offset) { + offset = offset | 0; + + _core(HEAP[offset | 0] << 24 | HEAP[offset | 1] << 16 | HEAP[offset | 2] << 8 | HEAP[offset | 3], HEAP[offset | 4] << 24 | HEAP[offset | 5] << 16 | HEAP[offset | 6] << 8 | HEAP[offset | 7], HEAP[offset | 8] << 24 | HEAP[offset | 9] << 16 | HEAP[offset | 10] << 8 | HEAP[offset | 11], HEAP[offset | 12] << 24 | HEAP[offset | 13] << 16 | HEAP[offset | 14] << 8 | HEAP[offset | 15], HEAP[offset | 16] << 24 | HEAP[offset | 17] << 16 | HEAP[offset | 18] << 8 | HEAP[offset | 19], HEAP[offset | 20] << 24 | HEAP[offset | 21] << 16 | HEAP[offset | 22] << 8 | HEAP[offset | 23], HEAP[offset | 24] << 24 | HEAP[offset | 25] << 16 | HEAP[offset | 26] << 8 | HEAP[offset | 27], HEAP[offset | 28] << 24 | HEAP[offset | 29] << 16 | HEAP[offset | 30] << 8 | HEAP[offset | 31], HEAP[offset | 32] << 24 | HEAP[offset | 33] << 16 | HEAP[offset | 34] << 8 | HEAP[offset | 35], HEAP[offset | 36] << 24 | HEAP[offset | 37] << 16 | HEAP[offset | 38] << 8 | HEAP[offset | 39], HEAP[offset | 40] << 24 | HEAP[offset | 41] << 16 | HEAP[offset | 42] << 8 | HEAP[offset | 43], HEAP[offset | 44] << 24 | HEAP[offset | 45] << 16 | HEAP[offset | 46] << 8 | HEAP[offset | 47], HEAP[offset | 48] << 24 | HEAP[offset | 49] << 16 | HEAP[offset | 50] << 8 | HEAP[offset | 51], HEAP[offset | 52] << 24 | HEAP[offset | 53] << 16 | HEAP[offset | 54] << 8 | HEAP[offset | 55], HEAP[offset | 56] << 24 | HEAP[offset | 57] << 16 | HEAP[offset | 58] << 8 | HEAP[offset | 59], HEAP[offset | 60] << 24 | HEAP[offset | 61] << 16 | HEAP[offset | 62] << 8 | HEAP[offset | 63]); + } + + // offset — multiple of 32 + function _state_to_heap(output) { + output = output | 0; + + HEAP[output | 0] = H0 >>> 24; + HEAP[output | 1] = H0 >>> 16 & 255; + HEAP[output | 2] = H0 >>> 8 & 255; + HEAP[output | 3] = H0 & 255; + HEAP[output | 4] = H1 >>> 24; + HEAP[output | 5] = H1 >>> 16 & 255; + HEAP[output | 6] = H1 >>> 8 & 255; + HEAP[output | 7] = H1 & 255; + HEAP[output | 8] = H2 >>> 24; + HEAP[output | 9] = H2 >>> 16 & 255; + HEAP[output | 10] = H2 >>> 8 & 255; + HEAP[output | 11] = H2 & 255; + HEAP[output | 12] = H3 >>> 24; + HEAP[output | 13] = H3 >>> 16 & 255; + HEAP[output | 14] = H3 >>> 8 & 255; + HEAP[output | 15] = H3 & 255; + HEAP[output | 16] = H4 >>> 24; + HEAP[output | 17] = H4 >>> 16 & 255; + HEAP[output | 18] = H4 >>> 8 & 255; + HEAP[output | 19] = H4 & 255; + } + + function reset() { + H0 = 0x67452301; + H1 = 0xefcdab89; + H2 = 0x98badcfe; + H3 = 0x10325476; + H4 = 0xc3d2e1f0; + TOTAL0 = TOTAL1 = 0; + } + + function init(h0, h1, h2, h3, h4, total0, total1) { + h0 = h0 | 0; + h1 = h1 | 0; + h2 = h2 | 0; + h3 = h3 | 0; + h4 = h4 | 0; + total0 = total0 | 0; + total1 = total1 | 0; + + H0 = h0; + H1 = h1; + H2 = h2; + H3 = h3; + H4 = h4; + TOTAL0 = total0; + TOTAL1 = total1; + } + + // offset — multiple of 64 + function process(offset, length) { + offset = offset | 0; + length = length | 0; + + var hashed = 0; + + if (offset & 63) return -1; + + while ((length | 0) >= 64) { + _core_heap(offset); + + offset = offset + 64 | 0; + length = length - 64 | 0; + + hashed = hashed + 64 | 0; + } + + TOTAL0 = TOTAL0 + hashed | 0; + if (TOTAL0 >>> 0 < hashed >>> 0) TOTAL1 = TOTAL1 + 1 | 0; + + return hashed | 0; + } + + // offset — multiple of 64 + // output — multiple of 32 + function finish(offset, length, output) { + offset = offset | 0; + length = length | 0; + output = output | 0; + + var hashed = 0, + i = 0; + + if (offset & 63) return -1; + + if (~output) if (output & 31) return -1; + + if ((length | 0) >= 64) { + hashed = process(offset, length) | 0; + if ((hashed | 0) == -1) return -1; + + offset = offset + hashed | 0; + length = length - hashed | 0; + } + + hashed = hashed + length | 0; + TOTAL0 = TOTAL0 + length | 0; + if (TOTAL0 >>> 0 < length >>> 0) TOTAL1 = TOTAL1 + 1 | 0; + + HEAP[offset | length] = 0x80; + + if ((length | 0) >= 56) { + for (i = length + 1 | 0; (i | 0) < 64; i = i + 1 | 0) HEAP[offset | i] = 0x00; + _core_heap(offset); + + length = 0; + + HEAP[offset | 0] = 0; + } + + for (i = length + 1 | 0; (i | 0) < 59; i = i + 1 | 0) HEAP[offset | i] = 0; + + HEAP[offset | 56] = TOTAL1 >>> 21 & 255; + HEAP[offset | 57] = TOTAL1 >>> 13 & 255; + HEAP[offset | 58] = TOTAL1 >>> 5 & 255; + HEAP[offset | 59] = TOTAL1 << 3 & 255 | TOTAL0 >>> 29; + HEAP[offset | 60] = TOTAL0 >>> 21 & 255; + HEAP[offset | 61] = TOTAL0 >>> 13 & 255; + HEAP[offset | 62] = TOTAL0 >>> 5 & 255; + HEAP[offset | 63] = TOTAL0 << 3 & 255; + _core_heap(offset); + + if (~output) _state_to_heap(output); + + return hashed | 0; + } + + function hmac_reset() { + H0 = I0; + H1 = I1; + H2 = I2; + H3 = I3; + H4 = I4; + TOTAL0 = 64; + TOTAL1 = 0; + } + + function _hmac_opad() { + H0 = O0; + H1 = O1; + H2 = O2; + H3 = O3; + H4 = O4; + TOTAL0 = 64; + TOTAL1 = 0; + } + + function hmac_init(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15) { + p0 = p0 | 0; + p1 = p1 | 0; + p2 = p2 | 0; + p3 = p3 | 0; + p4 = p4 | 0; + p5 = p5 | 0; + p6 = p6 | 0; + p7 = p7 | 0; + p8 = p8 | 0; + p9 = p9 | 0; + p10 = p10 | 0; + p11 = p11 | 0; + p12 = p12 | 0; + p13 = p13 | 0; + p14 = p14 | 0; + p15 = p15 | 0; + + // opad + reset(); + _core(p0 ^ 0x5c5c5c5c, p1 ^ 0x5c5c5c5c, p2 ^ 0x5c5c5c5c, p3 ^ 0x5c5c5c5c, p4 ^ 0x5c5c5c5c, p5 ^ 0x5c5c5c5c, p6 ^ 0x5c5c5c5c, p7 ^ 0x5c5c5c5c, p8 ^ 0x5c5c5c5c, p9 ^ 0x5c5c5c5c, p10 ^ 0x5c5c5c5c, p11 ^ 0x5c5c5c5c, p12 ^ 0x5c5c5c5c, p13 ^ 0x5c5c5c5c, p14 ^ 0x5c5c5c5c, p15 ^ 0x5c5c5c5c); + O0 = H0; + O1 = H1; + O2 = H2; + O3 = H3; + O4 = H4; + + // ipad + reset(); + _core(p0 ^ 0x36363636, p1 ^ 0x36363636, p2 ^ 0x36363636, p3 ^ 0x36363636, p4 ^ 0x36363636, p5 ^ 0x36363636, p6 ^ 0x36363636, p7 ^ 0x36363636, p8 ^ 0x36363636, p9 ^ 0x36363636, p10 ^ 0x36363636, p11 ^ 0x36363636, p12 ^ 0x36363636, p13 ^ 0x36363636, p14 ^ 0x36363636, p15 ^ 0x36363636); + I0 = H0; + I1 = H1; + I2 = H2; + I3 = H3; + I4 = H4; + + TOTAL0 = 64; + TOTAL1 = 0; + } + + // offset — multiple of 64 + // output — multiple of 32 + function hmac_finish(offset, length, output) { + offset = offset | 0; + length = length | 0; + output = output | 0; + + var t0 = 0, + t1 = 0, + t2 = 0, + t3 = 0, + t4 = 0, + hashed = 0; + + if (offset & 63) return -1; + + if (~output) if (output & 31) return -1; + + hashed = finish(offset, length, -1) | 0; + t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; + + _hmac_opad(); + _core(t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672); + + if (~output) _state_to_heap(output); + + return hashed | 0; + } + + // salt is assumed to be already processed + // offset — multiple of 64 + // output — multiple of 32 + function pbkdf2_generate_block(offset, length, block, count, output) { + offset = offset | 0; + length = length | 0; + block = block | 0; + count = count | 0; + output = output | 0; + + var h0 = 0, + h1 = 0, + h2 = 0, + h3 = 0, + h4 = 0, + t0 = 0, + t1 = 0, + t2 = 0, + t3 = 0, + t4 = 0; + + if (offset & 63) return -1; + + if (~output) if (output & 31) return -1; + + // pad block number into heap + // FIXME probable OOB write + HEAP[offset + length | 0] = block >>> 24; + HEAP[offset + length + 1 | 0] = block >>> 16 & 255; + HEAP[offset + length + 2 | 0] = block >>> 8 & 255; + HEAP[offset + length + 3 | 0] = block & 255; + + // finish first iteration + hmac_finish(offset, length + 4 | 0, -1) | 0; + h0 = t0 = H0, h1 = t1 = H1, h2 = t2 = H2, h3 = t3 = H3, h4 = t4 = H4; + count = count - 1 | 0; + + // perform the rest iterations + while ((count | 0) > 0) { + hmac_reset(); + _core(t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672); + t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; + + _hmac_opad(); + _core(t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672); + t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; + + h0 = h0 ^ H0; + h1 = h1 ^ H1; + h2 = h2 ^ H2; + h3 = h3 ^ H3; + h4 = h4 ^ H4; + + count = count - 1 | 0; + } + + H0 = h0; + H1 = h1; + H2 = h2; + H3 = h3; + H4 = h4; + + if (~output) _state_to_heap(output); + + return 0; + } + + return { + // SHA1 + reset: reset, + init: init, + process: process, + finish: finish, + + // HMAC-SHA1 + hmac_reset: hmac_reset, + hmac_init: hmac_init, + hmac_finish: hmac_finish, + + // PBKDF2-HMAC-SHA1 + pbkdf2_generate_block: pbkdf2_generate_block + }; +} + +},{}],11:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Sha1 = exports._sha1_hash_size = exports._sha1_block_size = undefined; + +var _sha = require('./sha1.asm'); + +var _hash = require('../hash'); + +var __extends = undefined && undefined.__extends || function () { + var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) { + d.__proto__ = b; + } || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + }; + return function (d, b) { + extendStatics(d, b); + function __() { + this.constructor = d; + } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +}(); +var _sha1_block_size = exports._sha1_block_size = 64; +var _sha1_hash_size = exports._sha1_hash_size = 20; +var Sha1 = /** @class */function (_super) { + __extends(Sha1, _super); + function Sha1() { + var _this = _super !== null && _super.apply(this, arguments) || this; + _this.NAME = 'sha1'; + _this.BLOCK_SIZE = _sha1_block_size; + _this.HASH_SIZE = _sha1_hash_size; + return _this; + } + Sha1.bytes = function (data) { + return new Sha1().process(data).finish().result; + }; + Sha1.NAME = 'sha1'; + Sha1.heap_pool = []; + Sha1.asm_pool = []; + Sha1.asm_function = _sha.sha1_asm; + return Sha1; +}(_hash.Hash); +exports.Sha1 = Sha1; + +},{"../hash":9,"./sha1.asm":10}],12:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.sha256_asm = sha256_asm; +function sha256_asm(stdlib, foreign, buffer) { + "use asm"; + + // SHA256 state + + var H0 = 0, + H1 = 0, + H2 = 0, + H3 = 0, + H4 = 0, + H5 = 0, + H6 = 0, + H7 = 0, + TOTAL0 = 0, + TOTAL1 = 0; + + // HMAC state + var I0 = 0, + I1 = 0, + I2 = 0, + I3 = 0, + I4 = 0, + I5 = 0, + I6 = 0, + I7 = 0, + O0 = 0, + O1 = 0, + O2 = 0, + O3 = 0, + O4 = 0, + O5 = 0, + O6 = 0, + O7 = 0; + + // I/O buffer + var HEAP = new stdlib.Uint8Array(buffer); + + function _core(w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15) { + w0 = w0 | 0; + w1 = w1 | 0; + w2 = w2 | 0; + w3 = w3 | 0; + w4 = w4 | 0; + w5 = w5 | 0; + w6 = w6 | 0; + w7 = w7 | 0; + w8 = w8 | 0; + w9 = w9 | 0; + w10 = w10 | 0; + w11 = w11 | 0; + w12 = w12 | 0; + w13 = w13 | 0; + w14 = w14 | 0; + w15 = w15 | 0; + + var a = 0, + b = 0, + c = 0, + d = 0, + e = 0, + f = 0, + g = 0, + h = 0; + + a = H0; + b = H1; + c = H2; + d = H3; + e = H4; + f = H5; + g = H6; + h = H7; + + // 0 + h = w0 + h + (e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7) + (g ^ e & (f ^ g)) + 0x428a2f98 | 0; + d = d + h | 0; + h = h + (a & b ^ c & (a ^ b)) + (a >>> 2 ^ a >>> 13 ^ a >>> 22 ^ a << 30 ^ a << 19 ^ a << 10) | 0; + + // 1 + g = w1 + g + (d >>> 6 ^ d >>> 11 ^ d >>> 25 ^ d << 26 ^ d << 21 ^ d << 7) + (f ^ d & (e ^ f)) + 0x71374491 | 0; + c = c + g | 0; + g = g + (h & a ^ b & (h ^ a)) + (h >>> 2 ^ h >>> 13 ^ h >>> 22 ^ h << 30 ^ h << 19 ^ h << 10) | 0; + + // 2 + f = w2 + f + (c >>> 6 ^ c >>> 11 ^ c >>> 25 ^ c << 26 ^ c << 21 ^ c << 7) + (e ^ c & (d ^ e)) + 0xb5c0fbcf | 0; + b = b + f | 0; + f = f + (g & h ^ a & (g ^ h)) + (g >>> 2 ^ g >>> 13 ^ g >>> 22 ^ g << 30 ^ g << 19 ^ g << 10) | 0; + + // 3 + e = w3 + e + (b >>> 6 ^ b >>> 11 ^ b >>> 25 ^ b << 26 ^ b << 21 ^ b << 7) + (d ^ b & (c ^ d)) + 0xe9b5dba5 | 0; + a = a + e | 0; + e = e + (f & g ^ h & (f ^ g)) + (f >>> 2 ^ f >>> 13 ^ f >>> 22 ^ f << 30 ^ f << 19 ^ f << 10) | 0; + + // 4 + d = w4 + d + (a >>> 6 ^ a >>> 11 ^ a >>> 25 ^ a << 26 ^ a << 21 ^ a << 7) + (c ^ a & (b ^ c)) + 0x3956c25b | 0; + h = h + d | 0; + d = d + (e & f ^ g & (e ^ f)) + (e >>> 2 ^ e >>> 13 ^ e >>> 22 ^ e << 30 ^ e << 19 ^ e << 10) | 0; + + // 5 + c = w5 + c + (h >>> 6 ^ h >>> 11 ^ h >>> 25 ^ h << 26 ^ h << 21 ^ h << 7) + (b ^ h & (a ^ b)) + 0x59f111f1 | 0; + g = g + c | 0; + c = c + (d & e ^ f & (d ^ e)) + (d >>> 2 ^ d >>> 13 ^ d >>> 22 ^ d << 30 ^ d << 19 ^ d << 10) | 0; + + // 6 + b = w6 + b + (g >>> 6 ^ g >>> 11 ^ g >>> 25 ^ g << 26 ^ g << 21 ^ g << 7) + (a ^ g & (h ^ a)) + 0x923f82a4 | 0; + f = f + b | 0; + b = b + (c & d ^ e & (c ^ d)) + (c >>> 2 ^ c >>> 13 ^ c >>> 22 ^ c << 30 ^ c << 19 ^ c << 10) | 0; + + // 7 + a = w7 + a + (f >>> 6 ^ f >>> 11 ^ f >>> 25 ^ f << 26 ^ f << 21 ^ f << 7) + (h ^ f & (g ^ h)) + 0xab1c5ed5 | 0; + e = e + a | 0; + a = a + (b & c ^ d & (b ^ c)) + (b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10) | 0; + + // 8 + h = w8 + h + (e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7) + (g ^ e & (f ^ g)) + 0xd807aa98 | 0; + d = d + h | 0; + h = h + (a & b ^ c & (a ^ b)) + (a >>> 2 ^ a >>> 13 ^ a >>> 22 ^ a << 30 ^ a << 19 ^ a << 10) | 0; + + // 9 + g = w9 + g + (d >>> 6 ^ d >>> 11 ^ d >>> 25 ^ d << 26 ^ d << 21 ^ d << 7) + (f ^ d & (e ^ f)) + 0x12835b01 | 0; + c = c + g | 0; + g = g + (h & a ^ b & (h ^ a)) + (h >>> 2 ^ h >>> 13 ^ h >>> 22 ^ h << 30 ^ h << 19 ^ h << 10) | 0; + + // 10 + f = w10 + f + (c >>> 6 ^ c >>> 11 ^ c >>> 25 ^ c << 26 ^ c << 21 ^ c << 7) + (e ^ c & (d ^ e)) + 0x243185be | 0; + b = b + f | 0; + f = f + (g & h ^ a & (g ^ h)) + (g >>> 2 ^ g >>> 13 ^ g >>> 22 ^ g << 30 ^ g << 19 ^ g << 10) | 0; + + // 11 + e = w11 + e + (b >>> 6 ^ b >>> 11 ^ b >>> 25 ^ b << 26 ^ b << 21 ^ b << 7) + (d ^ b & (c ^ d)) + 0x550c7dc3 | 0; + a = a + e | 0; + e = e + (f & g ^ h & (f ^ g)) + (f >>> 2 ^ f >>> 13 ^ f >>> 22 ^ f << 30 ^ f << 19 ^ f << 10) | 0; + + // 12 + d = w12 + d + (a >>> 6 ^ a >>> 11 ^ a >>> 25 ^ a << 26 ^ a << 21 ^ a << 7) + (c ^ a & (b ^ c)) + 0x72be5d74 | 0; + h = h + d | 0; + d = d + (e & f ^ g & (e ^ f)) + (e >>> 2 ^ e >>> 13 ^ e >>> 22 ^ e << 30 ^ e << 19 ^ e << 10) | 0; + + // 13 + c = w13 + c + (h >>> 6 ^ h >>> 11 ^ h >>> 25 ^ h << 26 ^ h << 21 ^ h << 7) + (b ^ h & (a ^ b)) + 0x80deb1fe | 0; + g = g + c | 0; + c = c + (d & e ^ f & (d ^ e)) + (d >>> 2 ^ d >>> 13 ^ d >>> 22 ^ d << 30 ^ d << 19 ^ d << 10) | 0; + + // 14 + b = w14 + b + (g >>> 6 ^ g >>> 11 ^ g >>> 25 ^ g << 26 ^ g << 21 ^ g << 7) + (a ^ g & (h ^ a)) + 0x9bdc06a7 | 0; + f = f + b | 0; + b = b + (c & d ^ e & (c ^ d)) + (c >>> 2 ^ c >>> 13 ^ c >>> 22 ^ c << 30 ^ c << 19 ^ c << 10) | 0; + + // 15 + a = w15 + a + (f >>> 6 ^ f >>> 11 ^ f >>> 25 ^ f << 26 ^ f << 21 ^ f << 7) + (h ^ f & (g ^ h)) + 0xc19bf174 | 0; + e = e + a | 0; + a = a + (b & c ^ d & (b ^ c)) + (b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10) | 0; + + // 16 + w0 = (w1 >>> 7 ^ w1 >>> 18 ^ w1 >>> 3 ^ w1 << 25 ^ w1 << 14) + (w14 >>> 17 ^ w14 >>> 19 ^ w14 >>> 10 ^ w14 << 15 ^ w14 << 13) + w0 + w9 | 0; + h = w0 + h + (e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7) + (g ^ e & (f ^ g)) + 0xe49b69c1 | 0; + d = d + h | 0; + h = h + (a & b ^ c & (a ^ b)) + (a >>> 2 ^ a >>> 13 ^ a >>> 22 ^ a << 30 ^ a << 19 ^ a << 10) | 0; + + // 17 + w1 = (w2 >>> 7 ^ w2 >>> 18 ^ w2 >>> 3 ^ w2 << 25 ^ w2 << 14) + (w15 >>> 17 ^ w15 >>> 19 ^ w15 >>> 10 ^ w15 << 15 ^ w15 << 13) + w1 + w10 | 0; + g = w1 + g + (d >>> 6 ^ d >>> 11 ^ d >>> 25 ^ d << 26 ^ d << 21 ^ d << 7) + (f ^ d & (e ^ f)) + 0xefbe4786 | 0; + c = c + g | 0; + g = g + (h & a ^ b & (h ^ a)) + (h >>> 2 ^ h >>> 13 ^ h >>> 22 ^ h << 30 ^ h << 19 ^ h << 10) | 0; + + // 18 + w2 = (w3 >>> 7 ^ w3 >>> 18 ^ w3 >>> 3 ^ w3 << 25 ^ w3 << 14) + (w0 >>> 17 ^ w0 >>> 19 ^ w0 >>> 10 ^ w0 << 15 ^ w0 << 13) + w2 + w11 | 0; + f = w2 + f + (c >>> 6 ^ c >>> 11 ^ c >>> 25 ^ c << 26 ^ c << 21 ^ c << 7) + (e ^ c & (d ^ e)) + 0x0fc19dc6 | 0; + b = b + f | 0; + f = f + (g & h ^ a & (g ^ h)) + (g >>> 2 ^ g >>> 13 ^ g >>> 22 ^ g << 30 ^ g << 19 ^ g << 10) | 0; + + // 19 + w3 = (w4 >>> 7 ^ w4 >>> 18 ^ w4 >>> 3 ^ w4 << 25 ^ w4 << 14) + (w1 >>> 17 ^ w1 >>> 19 ^ w1 >>> 10 ^ w1 << 15 ^ w1 << 13) + w3 + w12 | 0; + e = w3 + e + (b >>> 6 ^ b >>> 11 ^ b >>> 25 ^ b << 26 ^ b << 21 ^ b << 7) + (d ^ b & (c ^ d)) + 0x240ca1cc | 0; + a = a + e | 0; + e = e + (f & g ^ h & (f ^ g)) + (f >>> 2 ^ f >>> 13 ^ f >>> 22 ^ f << 30 ^ f << 19 ^ f << 10) | 0; + + // 20 + w4 = (w5 >>> 7 ^ w5 >>> 18 ^ w5 >>> 3 ^ w5 << 25 ^ w5 << 14) + (w2 >>> 17 ^ w2 >>> 19 ^ w2 >>> 10 ^ w2 << 15 ^ w2 << 13) + w4 + w13 | 0; + d = w4 + d + (a >>> 6 ^ a >>> 11 ^ a >>> 25 ^ a << 26 ^ a << 21 ^ a << 7) + (c ^ a & (b ^ c)) + 0x2de92c6f | 0; + h = h + d | 0; + d = d + (e & f ^ g & (e ^ f)) + (e >>> 2 ^ e >>> 13 ^ e >>> 22 ^ e << 30 ^ e << 19 ^ e << 10) | 0; + + // 21 + w5 = (w6 >>> 7 ^ w6 >>> 18 ^ w6 >>> 3 ^ w6 << 25 ^ w6 << 14) + (w3 >>> 17 ^ w3 >>> 19 ^ w3 >>> 10 ^ w3 << 15 ^ w3 << 13) + w5 + w14 | 0; + c = w5 + c + (h >>> 6 ^ h >>> 11 ^ h >>> 25 ^ h << 26 ^ h << 21 ^ h << 7) + (b ^ h & (a ^ b)) + 0x4a7484aa | 0; + g = g + c | 0; + c = c + (d & e ^ f & (d ^ e)) + (d >>> 2 ^ d >>> 13 ^ d >>> 22 ^ d << 30 ^ d << 19 ^ d << 10) | 0; + + // 22 + w6 = (w7 >>> 7 ^ w7 >>> 18 ^ w7 >>> 3 ^ w7 << 25 ^ w7 << 14) + (w4 >>> 17 ^ w4 >>> 19 ^ w4 >>> 10 ^ w4 << 15 ^ w4 << 13) + w6 + w15 | 0; + b = w6 + b + (g >>> 6 ^ g >>> 11 ^ g >>> 25 ^ g << 26 ^ g << 21 ^ g << 7) + (a ^ g & (h ^ a)) + 0x5cb0a9dc | 0; + f = f + b | 0; + b = b + (c & d ^ e & (c ^ d)) + (c >>> 2 ^ c >>> 13 ^ c >>> 22 ^ c << 30 ^ c << 19 ^ c << 10) | 0; + + // 23 + w7 = (w8 >>> 7 ^ w8 >>> 18 ^ w8 >>> 3 ^ w8 << 25 ^ w8 << 14) + (w5 >>> 17 ^ w5 >>> 19 ^ w5 >>> 10 ^ w5 << 15 ^ w5 << 13) + w7 + w0 | 0; + a = w7 + a + (f >>> 6 ^ f >>> 11 ^ f >>> 25 ^ f << 26 ^ f << 21 ^ f << 7) + (h ^ f & (g ^ h)) + 0x76f988da | 0; + e = e + a | 0; + a = a + (b & c ^ d & (b ^ c)) + (b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10) | 0; + + // 24 + w8 = (w9 >>> 7 ^ w9 >>> 18 ^ w9 >>> 3 ^ w9 << 25 ^ w9 << 14) + (w6 >>> 17 ^ w6 >>> 19 ^ w6 >>> 10 ^ w6 << 15 ^ w6 << 13) + w8 + w1 | 0; + h = w8 + h + (e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7) + (g ^ e & (f ^ g)) + 0x983e5152 | 0; + d = d + h | 0; + h = h + (a & b ^ c & (a ^ b)) + (a >>> 2 ^ a >>> 13 ^ a >>> 22 ^ a << 30 ^ a << 19 ^ a << 10) | 0; + + // 25 + w9 = (w10 >>> 7 ^ w10 >>> 18 ^ w10 >>> 3 ^ w10 << 25 ^ w10 << 14) + (w7 >>> 17 ^ w7 >>> 19 ^ w7 >>> 10 ^ w7 << 15 ^ w7 << 13) + w9 + w2 | 0; + g = w9 + g + (d >>> 6 ^ d >>> 11 ^ d >>> 25 ^ d << 26 ^ d << 21 ^ d << 7) + (f ^ d & (e ^ f)) + 0xa831c66d | 0; + c = c + g | 0; + g = g + (h & a ^ b & (h ^ a)) + (h >>> 2 ^ h >>> 13 ^ h >>> 22 ^ h << 30 ^ h << 19 ^ h << 10) | 0; + + // 26 + w10 = (w11 >>> 7 ^ w11 >>> 18 ^ w11 >>> 3 ^ w11 << 25 ^ w11 << 14) + (w8 >>> 17 ^ w8 >>> 19 ^ w8 >>> 10 ^ w8 << 15 ^ w8 << 13) + w10 + w3 | 0; + f = w10 + f + (c >>> 6 ^ c >>> 11 ^ c >>> 25 ^ c << 26 ^ c << 21 ^ c << 7) + (e ^ c & (d ^ e)) + 0xb00327c8 | 0; + b = b + f | 0; + f = f + (g & h ^ a & (g ^ h)) + (g >>> 2 ^ g >>> 13 ^ g >>> 22 ^ g << 30 ^ g << 19 ^ g << 10) | 0; + + // 27 + w11 = (w12 >>> 7 ^ w12 >>> 18 ^ w12 >>> 3 ^ w12 << 25 ^ w12 << 14) + (w9 >>> 17 ^ w9 >>> 19 ^ w9 >>> 10 ^ w9 << 15 ^ w9 << 13) + w11 + w4 | 0; + e = w11 + e + (b >>> 6 ^ b >>> 11 ^ b >>> 25 ^ b << 26 ^ b << 21 ^ b << 7) + (d ^ b & (c ^ d)) + 0xbf597fc7 | 0; + a = a + e | 0; + e = e + (f & g ^ h & (f ^ g)) + (f >>> 2 ^ f >>> 13 ^ f >>> 22 ^ f << 30 ^ f << 19 ^ f << 10) | 0; + + // 28 + w12 = (w13 >>> 7 ^ w13 >>> 18 ^ w13 >>> 3 ^ w13 << 25 ^ w13 << 14) + (w10 >>> 17 ^ w10 >>> 19 ^ w10 >>> 10 ^ w10 << 15 ^ w10 << 13) + w12 + w5 | 0; + d = w12 + d + (a >>> 6 ^ a >>> 11 ^ a >>> 25 ^ a << 26 ^ a << 21 ^ a << 7) + (c ^ a & (b ^ c)) + 0xc6e00bf3 | 0; + h = h + d | 0; + d = d + (e & f ^ g & (e ^ f)) + (e >>> 2 ^ e >>> 13 ^ e >>> 22 ^ e << 30 ^ e << 19 ^ e << 10) | 0; + + // 29 + w13 = (w14 >>> 7 ^ w14 >>> 18 ^ w14 >>> 3 ^ w14 << 25 ^ w14 << 14) + (w11 >>> 17 ^ w11 >>> 19 ^ w11 >>> 10 ^ w11 << 15 ^ w11 << 13) + w13 + w6 | 0; + c = w13 + c + (h >>> 6 ^ h >>> 11 ^ h >>> 25 ^ h << 26 ^ h << 21 ^ h << 7) + (b ^ h & (a ^ b)) + 0xd5a79147 | 0; + g = g + c | 0; + c = c + (d & e ^ f & (d ^ e)) + (d >>> 2 ^ d >>> 13 ^ d >>> 22 ^ d << 30 ^ d << 19 ^ d << 10) | 0; + + // 30 + w14 = (w15 >>> 7 ^ w15 >>> 18 ^ w15 >>> 3 ^ w15 << 25 ^ w15 << 14) + (w12 >>> 17 ^ w12 >>> 19 ^ w12 >>> 10 ^ w12 << 15 ^ w12 << 13) + w14 + w7 | 0; + b = w14 + b + (g >>> 6 ^ g >>> 11 ^ g >>> 25 ^ g << 26 ^ g << 21 ^ g << 7) + (a ^ g & (h ^ a)) + 0x06ca6351 | 0; + f = f + b | 0; + b = b + (c & d ^ e & (c ^ d)) + (c >>> 2 ^ c >>> 13 ^ c >>> 22 ^ c << 30 ^ c << 19 ^ c << 10) | 0; + + // 31 + w15 = (w0 >>> 7 ^ w0 >>> 18 ^ w0 >>> 3 ^ w0 << 25 ^ w0 << 14) + (w13 >>> 17 ^ w13 >>> 19 ^ w13 >>> 10 ^ w13 << 15 ^ w13 << 13) + w15 + w8 | 0; + a = w15 + a + (f >>> 6 ^ f >>> 11 ^ f >>> 25 ^ f << 26 ^ f << 21 ^ f << 7) + (h ^ f & (g ^ h)) + 0x14292967 | 0; + e = e + a | 0; + a = a + (b & c ^ d & (b ^ c)) + (b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10) | 0; + + // 32 + w0 = (w1 >>> 7 ^ w1 >>> 18 ^ w1 >>> 3 ^ w1 << 25 ^ w1 << 14) + (w14 >>> 17 ^ w14 >>> 19 ^ w14 >>> 10 ^ w14 << 15 ^ w14 << 13) + w0 + w9 | 0; + h = w0 + h + (e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7) + (g ^ e & (f ^ g)) + 0x27b70a85 | 0; + d = d + h | 0; + h = h + (a & b ^ c & (a ^ b)) + (a >>> 2 ^ a >>> 13 ^ a >>> 22 ^ a << 30 ^ a << 19 ^ a << 10) | 0; + + // 33 + w1 = (w2 >>> 7 ^ w2 >>> 18 ^ w2 >>> 3 ^ w2 << 25 ^ w2 << 14) + (w15 >>> 17 ^ w15 >>> 19 ^ w15 >>> 10 ^ w15 << 15 ^ w15 << 13) + w1 + w10 | 0; + g = w1 + g + (d >>> 6 ^ d >>> 11 ^ d >>> 25 ^ d << 26 ^ d << 21 ^ d << 7) + (f ^ d & (e ^ f)) + 0x2e1b2138 | 0; + c = c + g | 0; + g = g + (h & a ^ b & (h ^ a)) + (h >>> 2 ^ h >>> 13 ^ h >>> 22 ^ h << 30 ^ h << 19 ^ h << 10) | 0; + + // 34 + w2 = (w3 >>> 7 ^ w3 >>> 18 ^ w3 >>> 3 ^ w3 << 25 ^ w3 << 14) + (w0 >>> 17 ^ w0 >>> 19 ^ w0 >>> 10 ^ w0 << 15 ^ w0 << 13) + w2 + w11 | 0; + f = w2 + f + (c >>> 6 ^ c >>> 11 ^ c >>> 25 ^ c << 26 ^ c << 21 ^ c << 7) + (e ^ c & (d ^ e)) + 0x4d2c6dfc | 0; + b = b + f | 0; + f = f + (g & h ^ a & (g ^ h)) + (g >>> 2 ^ g >>> 13 ^ g >>> 22 ^ g << 30 ^ g << 19 ^ g << 10) | 0; + + // 35 + w3 = (w4 >>> 7 ^ w4 >>> 18 ^ w4 >>> 3 ^ w4 << 25 ^ w4 << 14) + (w1 >>> 17 ^ w1 >>> 19 ^ w1 >>> 10 ^ w1 << 15 ^ w1 << 13) + w3 + w12 | 0; + e = w3 + e + (b >>> 6 ^ b >>> 11 ^ b >>> 25 ^ b << 26 ^ b << 21 ^ b << 7) + (d ^ b & (c ^ d)) + 0x53380d13 | 0; + a = a + e | 0; + e = e + (f & g ^ h & (f ^ g)) + (f >>> 2 ^ f >>> 13 ^ f >>> 22 ^ f << 30 ^ f << 19 ^ f << 10) | 0; + + // 36 + w4 = (w5 >>> 7 ^ w5 >>> 18 ^ w5 >>> 3 ^ w5 << 25 ^ w5 << 14) + (w2 >>> 17 ^ w2 >>> 19 ^ w2 >>> 10 ^ w2 << 15 ^ w2 << 13) + w4 + w13 | 0; + d = w4 + d + (a >>> 6 ^ a >>> 11 ^ a >>> 25 ^ a << 26 ^ a << 21 ^ a << 7) + (c ^ a & (b ^ c)) + 0x650a7354 | 0; + h = h + d | 0; + d = d + (e & f ^ g & (e ^ f)) + (e >>> 2 ^ e >>> 13 ^ e >>> 22 ^ e << 30 ^ e << 19 ^ e << 10) | 0; + + // 37 + w5 = (w6 >>> 7 ^ w6 >>> 18 ^ w6 >>> 3 ^ w6 << 25 ^ w6 << 14) + (w3 >>> 17 ^ w3 >>> 19 ^ w3 >>> 10 ^ w3 << 15 ^ w3 << 13) + w5 + w14 | 0; + c = w5 + c + (h >>> 6 ^ h >>> 11 ^ h >>> 25 ^ h << 26 ^ h << 21 ^ h << 7) + (b ^ h & (a ^ b)) + 0x766a0abb | 0; + g = g + c | 0; + c = c + (d & e ^ f & (d ^ e)) + (d >>> 2 ^ d >>> 13 ^ d >>> 22 ^ d << 30 ^ d << 19 ^ d << 10) | 0; + + // 38 + w6 = (w7 >>> 7 ^ w7 >>> 18 ^ w7 >>> 3 ^ w7 << 25 ^ w7 << 14) + (w4 >>> 17 ^ w4 >>> 19 ^ w4 >>> 10 ^ w4 << 15 ^ w4 << 13) + w6 + w15 | 0; + b = w6 + b + (g >>> 6 ^ g >>> 11 ^ g >>> 25 ^ g << 26 ^ g << 21 ^ g << 7) + (a ^ g & (h ^ a)) + 0x81c2c92e | 0; + f = f + b | 0; + b = b + (c & d ^ e & (c ^ d)) + (c >>> 2 ^ c >>> 13 ^ c >>> 22 ^ c << 30 ^ c << 19 ^ c << 10) | 0; + + // 39 + w7 = (w8 >>> 7 ^ w8 >>> 18 ^ w8 >>> 3 ^ w8 << 25 ^ w8 << 14) + (w5 >>> 17 ^ w5 >>> 19 ^ w5 >>> 10 ^ w5 << 15 ^ w5 << 13) + w7 + w0 | 0; + a = w7 + a + (f >>> 6 ^ f >>> 11 ^ f >>> 25 ^ f << 26 ^ f << 21 ^ f << 7) + (h ^ f & (g ^ h)) + 0x92722c85 | 0; + e = e + a | 0; + a = a + (b & c ^ d & (b ^ c)) + (b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10) | 0; + + // 40 + w8 = (w9 >>> 7 ^ w9 >>> 18 ^ w9 >>> 3 ^ w9 << 25 ^ w9 << 14) + (w6 >>> 17 ^ w6 >>> 19 ^ w6 >>> 10 ^ w6 << 15 ^ w6 << 13) + w8 + w1 | 0; + h = w8 + h + (e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7) + (g ^ e & (f ^ g)) + 0xa2bfe8a1 | 0; + d = d + h | 0; + h = h + (a & b ^ c & (a ^ b)) + (a >>> 2 ^ a >>> 13 ^ a >>> 22 ^ a << 30 ^ a << 19 ^ a << 10) | 0; + + // 41 + w9 = (w10 >>> 7 ^ w10 >>> 18 ^ w10 >>> 3 ^ w10 << 25 ^ w10 << 14) + (w7 >>> 17 ^ w7 >>> 19 ^ w7 >>> 10 ^ w7 << 15 ^ w7 << 13) + w9 + w2 | 0; + g = w9 + g + (d >>> 6 ^ d >>> 11 ^ d >>> 25 ^ d << 26 ^ d << 21 ^ d << 7) + (f ^ d & (e ^ f)) + 0xa81a664b | 0; + c = c + g | 0; + g = g + (h & a ^ b & (h ^ a)) + (h >>> 2 ^ h >>> 13 ^ h >>> 22 ^ h << 30 ^ h << 19 ^ h << 10) | 0; + + // 42 + w10 = (w11 >>> 7 ^ w11 >>> 18 ^ w11 >>> 3 ^ w11 << 25 ^ w11 << 14) + (w8 >>> 17 ^ w8 >>> 19 ^ w8 >>> 10 ^ w8 << 15 ^ w8 << 13) + w10 + w3 | 0; + f = w10 + f + (c >>> 6 ^ c >>> 11 ^ c >>> 25 ^ c << 26 ^ c << 21 ^ c << 7) + (e ^ c & (d ^ e)) + 0xc24b8b70 | 0; + b = b + f | 0; + f = f + (g & h ^ a & (g ^ h)) + (g >>> 2 ^ g >>> 13 ^ g >>> 22 ^ g << 30 ^ g << 19 ^ g << 10) | 0; + + // 43 + w11 = (w12 >>> 7 ^ w12 >>> 18 ^ w12 >>> 3 ^ w12 << 25 ^ w12 << 14) + (w9 >>> 17 ^ w9 >>> 19 ^ w9 >>> 10 ^ w9 << 15 ^ w9 << 13) + w11 + w4 | 0; + e = w11 + e + (b >>> 6 ^ b >>> 11 ^ b >>> 25 ^ b << 26 ^ b << 21 ^ b << 7) + (d ^ b & (c ^ d)) + 0xc76c51a3 | 0; + a = a + e | 0; + e = e + (f & g ^ h & (f ^ g)) + (f >>> 2 ^ f >>> 13 ^ f >>> 22 ^ f << 30 ^ f << 19 ^ f << 10) | 0; + + // 44 + w12 = (w13 >>> 7 ^ w13 >>> 18 ^ w13 >>> 3 ^ w13 << 25 ^ w13 << 14) + (w10 >>> 17 ^ w10 >>> 19 ^ w10 >>> 10 ^ w10 << 15 ^ w10 << 13) + w12 + w5 | 0; + d = w12 + d + (a >>> 6 ^ a >>> 11 ^ a >>> 25 ^ a << 26 ^ a << 21 ^ a << 7) + (c ^ a & (b ^ c)) + 0xd192e819 | 0; + h = h + d | 0; + d = d + (e & f ^ g & (e ^ f)) + (e >>> 2 ^ e >>> 13 ^ e >>> 22 ^ e << 30 ^ e << 19 ^ e << 10) | 0; + + // 45 + w13 = (w14 >>> 7 ^ w14 >>> 18 ^ w14 >>> 3 ^ w14 << 25 ^ w14 << 14) + (w11 >>> 17 ^ w11 >>> 19 ^ w11 >>> 10 ^ w11 << 15 ^ w11 << 13) + w13 + w6 | 0; + c = w13 + c + (h >>> 6 ^ h >>> 11 ^ h >>> 25 ^ h << 26 ^ h << 21 ^ h << 7) + (b ^ h & (a ^ b)) + 0xd6990624 | 0; + g = g + c | 0; + c = c + (d & e ^ f & (d ^ e)) + (d >>> 2 ^ d >>> 13 ^ d >>> 22 ^ d << 30 ^ d << 19 ^ d << 10) | 0; + + // 46 + w14 = (w15 >>> 7 ^ w15 >>> 18 ^ w15 >>> 3 ^ w15 << 25 ^ w15 << 14) + (w12 >>> 17 ^ w12 >>> 19 ^ w12 >>> 10 ^ w12 << 15 ^ w12 << 13) + w14 + w7 | 0; + b = w14 + b + (g >>> 6 ^ g >>> 11 ^ g >>> 25 ^ g << 26 ^ g << 21 ^ g << 7) + (a ^ g & (h ^ a)) + 0xf40e3585 | 0; + f = f + b | 0; + b = b + (c & d ^ e & (c ^ d)) + (c >>> 2 ^ c >>> 13 ^ c >>> 22 ^ c << 30 ^ c << 19 ^ c << 10) | 0; + + // 47 + w15 = (w0 >>> 7 ^ w0 >>> 18 ^ w0 >>> 3 ^ w0 << 25 ^ w0 << 14) + (w13 >>> 17 ^ w13 >>> 19 ^ w13 >>> 10 ^ w13 << 15 ^ w13 << 13) + w15 + w8 | 0; + a = w15 + a + (f >>> 6 ^ f >>> 11 ^ f >>> 25 ^ f << 26 ^ f << 21 ^ f << 7) + (h ^ f & (g ^ h)) + 0x106aa070 | 0; + e = e + a | 0; + a = a + (b & c ^ d & (b ^ c)) + (b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10) | 0; + + // 48 + w0 = (w1 >>> 7 ^ w1 >>> 18 ^ w1 >>> 3 ^ w1 << 25 ^ w1 << 14) + (w14 >>> 17 ^ w14 >>> 19 ^ w14 >>> 10 ^ w14 << 15 ^ w14 << 13) + w0 + w9 | 0; + h = w0 + h + (e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7) + (g ^ e & (f ^ g)) + 0x19a4c116 | 0; + d = d + h | 0; + h = h + (a & b ^ c & (a ^ b)) + (a >>> 2 ^ a >>> 13 ^ a >>> 22 ^ a << 30 ^ a << 19 ^ a << 10) | 0; + + // 49 + w1 = (w2 >>> 7 ^ w2 >>> 18 ^ w2 >>> 3 ^ w2 << 25 ^ w2 << 14) + (w15 >>> 17 ^ w15 >>> 19 ^ w15 >>> 10 ^ w15 << 15 ^ w15 << 13) + w1 + w10 | 0; + g = w1 + g + (d >>> 6 ^ d >>> 11 ^ d >>> 25 ^ d << 26 ^ d << 21 ^ d << 7) + (f ^ d & (e ^ f)) + 0x1e376c08 | 0; + c = c + g | 0; + g = g + (h & a ^ b & (h ^ a)) + (h >>> 2 ^ h >>> 13 ^ h >>> 22 ^ h << 30 ^ h << 19 ^ h << 10) | 0; + + // 50 + w2 = (w3 >>> 7 ^ w3 >>> 18 ^ w3 >>> 3 ^ w3 << 25 ^ w3 << 14) + (w0 >>> 17 ^ w0 >>> 19 ^ w0 >>> 10 ^ w0 << 15 ^ w0 << 13) + w2 + w11 | 0; + f = w2 + f + (c >>> 6 ^ c >>> 11 ^ c >>> 25 ^ c << 26 ^ c << 21 ^ c << 7) + (e ^ c & (d ^ e)) + 0x2748774c | 0; + b = b + f | 0; + f = f + (g & h ^ a & (g ^ h)) + (g >>> 2 ^ g >>> 13 ^ g >>> 22 ^ g << 30 ^ g << 19 ^ g << 10) | 0; + + // 51 + w3 = (w4 >>> 7 ^ w4 >>> 18 ^ w4 >>> 3 ^ w4 << 25 ^ w4 << 14) + (w1 >>> 17 ^ w1 >>> 19 ^ w1 >>> 10 ^ w1 << 15 ^ w1 << 13) + w3 + w12 | 0; + e = w3 + e + (b >>> 6 ^ b >>> 11 ^ b >>> 25 ^ b << 26 ^ b << 21 ^ b << 7) + (d ^ b & (c ^ d)) + 0x34b0bcb5 | 0; + a = a + e | 0; + e = e + (f & g ^ h & (f ^ g)) + (f >>> 2 ^ f >>> 13 ^ f >>> 22 ^ f << 30 ^ f << 19 ^ f << 10) | 0; + + // 52 + w4 = (w5 >>> 7 ^ w5 >>> 18 ^ w5 >>> 3 ^ w5 << 25 ^ w5 << 14) + (w2 >>> 17 ^ w2 >>> 19 ^ w2 >>> 10 ^ w2 << 15 ^ w2 << 13) + w4 + w13 | 0; + d = w4 + d + (a >>> 6 ^ a >>> 11 ^ a >>> 25 ^ a << 26 ^ a << 21 ^ a << 7) + (c ^ a & (b ^ c)) + 0x391c0cb3 | 0; + h = h + d | 0; + d = d + (e & f ^ g & (e ^ f)) + (e >>> 2 ^ e >>> 13 ^ e >>> 22 ^ e << 30 ^ e << 19 ^ e << 10) | 0; + + // 53 + w5 = (w6 >>> 7 ^ w6 >>> 18 ^ w6 >>> 3 ^ w6 << 25 ^ w6 << 14) + (w3 >>> 17 ^ w3 >>> 19 ^ w3 >>> 10 ^ w3 << 15 ^ w3 << 13) + w5 + w14 | 0; + c = w5 + c + (h >>> 6 ^ h >>> 11 ^ h >>> 25 ^ h << 26 ^ h << 21 ^ h << 7) + (b ^ h & (a ^ b)) + 0x4ed8aa4a | 0; + g = g + c | 0; + c = c + (d & e ^ f & (d ^ e)) + (d >>> 2 ^ d >>> 13 ^ d >>> 22 ^ d << 30 ^ d << 19 ^ d << 10) | 0; + + // 54 + w6 = (w7 >>> 7 ^ w7 >>> 18 ^ w7 >>> 3 ^ w7 << 25 ^ w7 << 14) + (w4 >>> 17 ^ w4 >>> 19 ^ w4 >>> 10 ^ w4 << 15 ^ w4 << 13) + w6 + w15 | 0; + b = w6 + b + (g >>> 6 ^ g >>> 11 ^ g >>> 25 ^ g << 26 ^ g << 21 ^ g << 7) + (a ^ g & (h ^ a)) + 0x5b9cca4f | 0; + f = f + b | 0; + b = b + (c & d ^ e & (c ^ d)) + (c >>> 2 ^ c >>> 13 ^ c >>> 22 ^ c << 30 ^ c << 19 ^ c << 10) | 0; + + // 55 + w7 = (w8 >>> 7 ^ w8 >>> 18 ^ w8 >>> 3 ^ w8 << 25 ^ w8 << 14) + (w5 >>> 17 ^ w5 >>> 19 ^ w5 >>> 10 ^ w5 << 15 ^ w5 << 13) + w7 + w0 | 0; + a = w7 + a + (f >>> 6 ^ f >>> 11 ^ f >>> 25 ^ f << 26 ^ f << 21 ^ f << 7) + (h ^ f & (g ^ h)) + 0x682e6ff3 | 0; + e = e + a | 0; + a = a + (b & c ^ d & (b ^ c)) + (b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10) | 0; + + // 56 + w8 = (w9 >>> 7 ^ w9 >>> 18 ^ w9 >>> 3 ^ w9 << 25 ^ w9 << 14) + (w6 >>> 17 ^ w6 >>> 19 ^ w6 >>> 10 ^ w6 << 15 ^ w6 << 13) + w8 + w1 | 0; + h = w8 + h + (e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7) + (g ^ e & (f ^ g)) + 0x748f82ee | 0; + d = d + h | 0; + h = h + (a & b ^ c & (a ^ b)) + (a >>> 2 ^ a >>> 13 ^ a >>> 22 ^ a << 30 ^ a << 19 ^ a << 10) | 0; + + // 57 + w9 = (w10 >>> 7 ^ w10 >>> 18 ^ w10 >>> 3 ^ w10 << 25 ^ w10 << 14) + (w7 >>> 17 ^ w7 >>> 19 ^ w7 >>> 10 ^ w7 << 15 ^ w7 << 13) + w9 + w2 | 0; + g = w9 + g + (d >>> 6 ^ d >>> 11 ^ d >>> 25 ^ d << 26 ^ d << 21 ^ d << 7) + (f ^ d & (e ^ f)) + 0x78a5636f | 0; + c = c + g | 0; + g = g + (h & a ^ b & (h ^ a)) + (h >>> 2 ^ h >>> 13 ^ h >>> 22 ^ h << 30 ^ h << 19 ^ h << 10) | 0; + + // 58 + w10 = (w11 >>> 7 ^ w11 >>> 18 ^ w11 >>> 3 ^ w11 << 25 ^ w11 << 14) + (w8 >>> 17 ^ w8 >>> 19 ^ w8 >>> 10 ^ w8 << 15 ^ w8 << 13) + w10 + w3 | 0; + f = w10 + f + (c >>> 6 ^ c >>> 11 ^ c >>> 25 ^ c << 26 ^ c << 21 ^ c << 7) + (e ^ c & (d ^ e)) + 0x84c87814 | 0; + b = b + f | 0; + f = f + (g & h ^ a & (g ^ h)) + (g >>> 2 ^ g >>> 13 ^ g >>> 22 ^ g << 30 ^ g << 19 ^ g << 10) | 0; + + // 59 + w11 = (w12 >>> 7 ^ w12 >>> 18 ^ w12 >>> 3 ^ w12 << 25 ^ w12 << 14) + (w9 >>> 17 ^ w9 >>> 19 ^ w9 >>> 10 ^ w9 << 15 ^ w9 << 13) + w11 + w4 | 0; + e = w11 + e + (b >>> 6 ^ b >>> 11 ^ b >>> 25 ^ b << 26 ^ b << 21 ^ b << 7) + (d ^ b & (c ^ d)) + 0x8cc70208 | 0; + a = a + e | 0; + e = e + (f & g ^ h & (f ^ g)) + (f >>> 2 ^ f >>> 13 ^ f >>> 22 ^ f << 30 ^ f << 19 ^ f << 10) | 0; + + // 60 + w12 = (w13 >>> 7 ^ w13 >>> 18 ^ w13 >>> 3 ^ w13 << 25 ^ w13 << 14) + (w10 >>> 17 ^ w10 >>> 19 ^ w10 >>> 10 ^ w10 << 15 ^ w10 << 13) + w12 + w5 | 0; + d = w12 + d + (a >>> 6 ^ a >>> 11 ^ a >>> 25 ^ a << 26 ^ a << 21 ^ a << 7) + (c ^ a & (b ^ c)) + 0x90befffa | 0; + h = h + d | 0; + d = d + (e & f ^ g & (e ^ f)) + (e >>> 2 ^ e >>> 13 ^ e >>> 22 ^ e << 30 ^ e << 19 ^ e << 10) | 0; + + // 61 + w13 = (w14 >>> 7 ^ w14 >>> 18 ^ w14 >>> 3 ^ w14 << 25 ^ w14 << 14) + (w11 >>> 17 ^ w11 >>> 19 ^ w11 >>> 10 ^ w11 << 15 ^ w11 << 13) + w13 + w6 | 0; + c = w13 + c + (h >>> 6 ^ h >>> 11 ^ h >>> 25 ^ h << 26 ^ h << 21 ^ h << 7) + (b ^ h & (a ^ b)) + 0xa4506ceb | 0; + g = g + c | 0; + c = c + (d & e ^ f & (d ^ e)) + (d >>> 2 ^ d >>> 13 ^ d >>> 22 ^ d << 30 ^ d << 19 ^ d << 10) | 0; + + // 62 + w14 = (w15 >>> 7 ^ w15 >>> 18 ^ w15 >>> 3 ^ w15 << 25 ^ w15 << 14) + (w12 >>> 17 ^ w12 >>> 19 ^ w12 >>> 10 ^ w12 << 15 ^ w12 << 13) + w14 + w7 | 0; + b = w14 + b + (g >>> 6 ^ g >>> 11 ^ g >>> 25 ^ g << 26 ^ g << 21 ^ g << 7) + (a ^ g & (h ^ a)) + 0xbef9a3f7 | 0; + f = f + b | 0; + b = b + (c & d ^ e & (c ^ d)) + (c >>> 2 ^ c >>> 13 ^ c >>> 22 ^ c << 30 ^ c << 19 ^ c << 10) | 0; + + // 63 + w15 = (w0 >>> 7 ^ w0 >>> 18 ^ w0 >>> 3 ^ w0 << 25 ^ w0 << 14) + (w13 >>> 17 ^ w13 >>> 19 ^ w13 >>> 10 ^ w13 << 15 ^ w13 << 13) + w15 + w8 | 0; + a = w15 + a + (f >>> 6 ^ f >>> 11 ^ f >>> 25 ^ f << 26 ^ f << 21 ^ f << 7) + (h ^ f & (g ^ h)) + 0xc67178f2 | 0; + e = e + a | 0; + a = a + (b & c ^ d & (b ^ c)) + (b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10) | 0; + + H0 = H0 + a | 0; + H1 = H1 + b | 0; + H2 = H2 + c | 0; + H3 = H3 + d | 0; + H4 = H4 + e | 0; + H5 = H5 + f | 0; + H6 = H6 + g | 0; + H7 = H7 + h | 0; + } + + function _core_heap(offset) { + offset = offset | 0; + + _core(HEAP[offset | 0] << 24 | HEAP[offset | 1] << 16 | HEAP[offset | 2] << 8 | HEAP[offset | 3], HEAP[offset | 4] << 24 | HEAP[offset | 5] << 16 | HEAP[offset | 6] << 8 | HEAP[offset | 7], HEAP[offset | 8] << 24 | HEAP[offset | 9] << 16 | HEAP[offset | 10] << 8 | HEAP[offset | 11], HEAP[offset | 12] << 24 | HEAP[offset | 13] << 16 | HEAP[offset | 14] << 8 | HEAP[offset | 15], HEAP[offset | 16] << 24 | HEAP[offset | 17] << 16 | HEAP[offset | 18] << 8 | HEAP[offset | 19], HEAP[offset | 20] << 24 | HEAP[offset | 21] << 16 | HEAP[offset | 22] << 8 | HEAP[offset | 23], HEAP[offset | 24] << 24 | HEAP[offset | 25] << 16 | HEAP[offset | 26] << 8 | HEAP[offset | 27], HEAP[offset | 28] << 24 | HEAP[offset | 29] << 16 | HEAP[offset | 30] << 8 | HEAP[offset | 31], HEAP[offset | 32] << 24 | HEAP[offset | 33] << 16 | HEAP[offset | 34] << 8 | HEAP[offset | 35], HEAP[offset | 36] << 24 | HEAP[offset | 37] << 16 | HEAP[offset | 38] << 8 | HEAP[offset | 39], HEAP[offset | 40] << 24 | HEAP[offset | 41] << 16 | HEAP[offset | 42] << 8 | HEAP[offset | 43], HEAP[offset | 44] << 24 | HEAP[offset | 45] << 16 | HEAP[offset | 46] << 8 | HEAP[offset | 47], HEAP[offset | 48] << 24 | HEAP[offset | 49] << 16 | HEAP[offset | 50] << 8 | HEAP[offset | 51], HEAP[offset | 52] << 24 | HEAP[offset | 53] << 16 | HEAP[offset | 54] << 8 | HEAP[offset | 55], HEAP[offset | 56] << 24 | HEAP[offset | 57] << 16 | HEAP[offset | 58] << 8 | HEAP[offset | 59], HEAP[offset | 60] << 24 | HEAP[offset | 61] << 16 | HEAP[offset | 62] << 8 | HEAP[offset | 63]); + } + + // offset — multiple of 32 + function _state_to_heap(output) { + output = output | 0; + + HEAP[output | 0] = H0 >>> 24; + HEAP[output | 1] = H0 >>> 16 & 255; + HEAP[output | 2] = H0 >>> 8 & 255; + HEAP[output | 3] = H0 & 255; + HEAP[output | 4] = H1 >>> 24; + HEAP[output | 5] = H1 >>> 16 & 255; + HEAP[output | 6] = H1 >>> 8 & 255; + HEAP[output | 7] = H1 & 255; + HEAP[output | 8] = H2 >>> 24; + HEAP[output | 9] = H2 >>> 16 & 255; + HEAP[output | 10] = H2 >>> 8 & 255; + HEAP[output | 11] = H2 & 255; + HEAP[output | 12] = H3 >>> 24; + HEAP[output | 13] = H3 >>> 16 & 255; + HEAP[output | 14] = H3 >>> 8 & 255; + HEAP[output | 15] = H3 & 255; + HEAP[output | 16] = H4 >>> 24; + HEAP[output | 17] = H4 >>> 16 & 255; + HEAP[output | 18] = H4 >>> 8 & 255; + HEAP[output | 19] = H4 & 255; + HEAP[output | 20] = H5 >>> 24; + HEAP[output | 21] = H5 >>> 16 & 255; + HEAP[output | 22] = H5 >>> 8 & 255; + HEAP[output | 23] = H5 & 255; + HEAP[output | 24] = H6 >>> 24; + HEAP[output | 25] = H6 >>> 16 & 255; + HEAP[output | 26] = H6 >>> 8 & 255; + HEAP[output | 27] = H6 & 255; + HEAP[output | 28] = H7 >>> 24; + HEAP[output | 29] = H7 >>> 16 & 255; + HEAP[output | 30] = H7 >>> 8 & 255; + HEAP[output | 31] = H7 & 255; + } + + function reset() { + H0 = 0x6a09e667; + H1 = 0xbb67ae85; + H2 = 0x3c6ef372; + H3 = 0xa54ff53a; + H4 = 0x510e527f; + H5 = 0x9b05688c; + H6 = 0x1f83d9ab; + H7 = 0x5be0cd19; + TOTAL0 = TOTAL1 = 0; + } + + function init(h0, h1, h2, h3, h4, h5, h6, h7, total0, total1) { + h0 = h0 | 0; + h1 = h1 | 0; + h2 = h2 | 0; + h3 = h3 | 0; + h4 = h4 | 0; + h5 = h5 | 0; + h6 = h6 | 0; + h7 = h7 | 0; + total0 = total0 | 0; + total1 = total1 | 0; + + H0 = h0; + H1 = h1; + H2 = h2; + H3 = h3; + H4 = h4; + H5 = h5; + H6 = h6; + H7 = h7; + TOTAL0 = total0; + TOTAL1 = total1; + } + + // offset — multiple of 64 + function process(offset, length) { + offset = offset | 0; + length = length | 0; + + var hashed = 0; + + if (offset & 63) return -1; + + while ((length | 0) >= 64) { + _core_heap(offset); + + offset = offset + 64 | 0; + length = length - 64 | 0; + + hashed = hashed + 64 | 0; + } + + TOTAL0 = TOTAL0 + hashed | 0; + if (TOTAL0 >>> 0 < hashed >>> 0) TOTAL1 = TOTAL1 + 1 | 0; + + return hashed | 0; + } + + // offset — multiple of 64 + // output — multiple of 32 + function finish(offset, length, output) { + offset = offset | 0; + length = length | 0; + output = output | 0; + + var hashed = 0, + i = 0; + + if (offset & 63) return -1; + + if (~output) if (output & 31) return -1; + + if ((length | 0) >= 64) { + hashed = process(offset, length) | 0; + if ((hashed | 0) == -1) return -1; + + offset = offset + hashed | 0; + length = length - hashed | 0; + } + + hashed = hashed + length | 0; + TOTAL0 = TOTAL0 + length | 0; + if (TOTAL0 >>> 0 < length >>> 0) TOTAL1 = TOTAL1 + 1 | 0; + + HEAP[offset | length] = 0x80; + + if ((length | 0) >= 56) { + for (i = length + 1 | 0; (i | 0) < 64; i = i + 1 | 0) HEAP[offset | i] = 0x00; + + _core_heap(offset); + + length = 0; + + HEAP[offset | 0] = 0; + } + + for (i = length + 1 | 0; (i | 0) < 59; i = i + 1 | 0) HEAP[offset | i] = 0; + + HEAP[offset | 56] = TOTAL1 >>> 21 & 255; + HEAP[offset | 57] = TOTAL1 >>> 13 & 255; + HEAP[offset | 58] = TOTAL1 >>> 5 & 255; + HEAP[offset | 59] = TOTAL1 << 3 & 255 | TOTAL0 >>> 29; + HEAP[offset | 60] = TOTAL0 >>> 21 & 255; + HEAP[offset | 61] = TOTAL0 >>> 13 & 255; + HEAP[offset | 62] = TOTAL0 >>> 5 & 255; + HEAP[offset | 63] = TOTAL0 << 3 & 255; + _core_heap(offset); + + if (~output) _state_to_heap(output); + + return hashed | 0; + } + + function hmac_reset() { + H0 = I0; + H1 = I1; + H2 = I2; + H3 = I3; + H4 = I4; + H5 = I5; + H6 = I6; + H7 = I7; + TOTAL0 = 64; + TOTAL1 = 0; + } + + function _hmac_opad() { + H0 = O0; + H1 = O1; + H2 = O2; + H3 = O3; + H4 = O4; + H5 = O5; + H6 = O6; + H7 = O7; + TOTAL0 = 64; + TOTAL1 = 0; + } + + function hmac_init(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15) { + p0 = p0 | 0; + p1 = p1 | 0; + p2 = p2 | 0; + p3 = p3 | 0; + p4 = p4 | 0; + p5 = p5 | 0; + p6 = p6 | 0; + p7 = p7 | 0; + p8 = p8 | 0; + p9 = p9 | 0; + p10 = p10 | 0; + p11 = p11 | 0; + p12 = p12 | 0; + p13 = p13 | 0; + p14 = p14 | 0; + p15 = p15 | 0; + + // opad + reset(); + _core(p0 ^ 0x5c5c5c5c, p1 ^ 0x5c5c5c5c, p2 ^ 0x5c5c5c5c, p3 ^ 0x5c5c5c5c, p4 ^ 0x5c5c5c5c, p5 ^ 0x5c5c5c5c, p6 ^ 0x5c5c5c5c, p7 ^ 0x5c5c5c5c, p8 ^ 0x5c5c5c5c, p9 ^ 0x5c5c5c5c, p10 ^ 0x5c5c5c5c, p11 ^ 0x5c5c5c5c, p12 ^ 0x5c5c5c5c, p13 ^ 0x5c5c5c5c, p14 ^ 0x5c5c5c5c, p15 ^ 0x5c5c5c5c); + O0 = H0; + O1 = H1; + O2 = H2; + O3 = H3; + O4 = H4; + O5 = H5; + O6 = H6; + O7 = H7; + + // ipad + reset(); + _core(p0 ^ 0x36363636, p1 ^ 0x36363636, p2 ^ 0x36363636, p3 ^ 0x36363636, p4 ^ 0x36363636, p5 ^ 0x36363636, p6 ^ 0x36363636, p7 ^ 0x36363636, p8 ^ 0x36363636, p9 ^ 0x36363636, p10 ^ 0x36363636, p11 ^ 0x36363636, p12 ^ 0x36363636, p13 ^ 0x36363636, p14 ^ 0x36363636, p15 ^ 0x36363636); + I0 = H0; + I1 = H1; + I2 = H2; + I3 = H3; + I4 = H4; + I5 = H5; + I6 = H6; + I7 = H7; + + TOTAL0 = 64; + TOTAL1 = 0; + } + + // offset — multiple of 64 + // output — multiple of 32 + function hmac_finish(offset, length, output) { + offset = offset | 0; + length = length | 0; + output = output | 0; + + var t0 = 0, + t1 = 0, + t2 = 0, + t3 = 0, + t4 = 0, + t5 = 0, + t6 = 0, + t7 = 0, + hashed = 0; + + if (offset & 63) return -1; + + if (~output) if (output & 31) return -1; + + hashed = finish(offset, length, -1) | 0; + t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; + + _hmac_opad(); + _core(t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768); + + if (~output) _state_to_heap(output); + + return hashed | 0; + } + + // salt is assumed to be already processed + // offset — multiple of 64 + // output — multiple of 32 + function pbkdf2_generate_block(offset, length, block, count, output) { + offset = offset | 0; + length = length | 0; + block = block | 0; + count = count | 0; + output = output | 0; + + var h0 = 0, + h1 = 0, + h2 = 0, + h3 = 0, + h4 = 0, + h5 = 0, + h6 = 0, + h7 = 0, + t0 = 0, + t1 = 0, + t2 = 0, + t3 = 0, + t4 = 0, + t5 = 0, + t6 = 0, + t7 = 0; + + if (offset & 63) return -1; + + if (~output) if (output & 31) return -1; + + // pad block number into heap + // FIXME probable OOB write + HEAP[offset + length | 0] = block >>> 24; + HEAP[offset + length + 1 | 0] = block >>> 16 & 255; + HEAP[offset + length + 2 | 0] = block >>> 8 & 255; + HEAP[offset + length + 3 | 0] = block & 255; + + // finish first iteration + hmac_finish(offset, length + 4 | 0, -1) | 0; + h0 = t0 = H0, h1 = t1 = H1, h2 = t2 = H2, h3 = t3 = H3, h4 = t4 = H4, h5 = t5 = H5, h6 = t6 = H6, h7 = t7 = H7; + count = count - 1 | 0; + + // perform the rest iterations + while ((count | 0) > 0) { + hmac_reset(); + _core(t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768); + t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; + + _hmac_opad(); + _core(t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768); + t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; + + h0 = h0 ^ H0; + h1 = h1 ^ H1; + h2 = h2 ^ H2; + h3 = h3 ^ H3; + h4 = h4 ^ H4; + h5 = h5 ^ H5; + h6 = h6 ^ H6; + h7 = h7 ^ H7; + + count = count - 1 | 0; + } + + H0 = h0; + H1 = h1; + H2 = h2; + H3 = h3; + H4 = h4; + H5 = h5; + H6 = h6; + H7 = h7; + + if (~output) _state_to_heap(output); + + return 0; + } + + return { + // SHA256 + reset: reset, + init: init, + process: process, + finish: finish, + + // HMAC-SHA256 + hmac_reset: hmac_reset, + hmac_init: hmac_init, + hmac_finish: hmac_finish, + + // PBKDF2-HMAC-SHA256 + pbkdf2_generate_block: pbkdf2_generate_block + }; +} + +},{}],13:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Sha256 = exports._sha256_hash_size = exports._sha256_block_size = undefined; + +var _sha = require('./sha256.asm'); + +var _hash = require('../hash'); + +var __extends = undefined && undefined.__extends || function () { + var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) { + d.__proto__ = b; + } || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + }; + return function (d, b) { + extendStatics(d, b); + function __() { + this.constructor = d; + } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +}(); +var _sha256_block_size = exports._sha256_block_size = 64; +var _sha256_hash_size = exports._sha256_hash_size = 32; +var Sha256 = /** @class */function (_super) { + __extends(Sha256, _super); + function Sha256() { + var _this = _super !== null && _super.apply(this, arguments) || this; + _this.NAME = 'sha256'; + _this.BLOCK_SIZE = _sha256_block_size; + _this.HASH_SIZE = _sha256_hash_size; + return _this; + } + Sha256.bytes = function (data) { + return new Sha256().process(data).finish().result; + }; + Sha256.NAME = 'sha256'; + Sha256.heap_pool = []; + Sha256.asm_pool = []; + Sha256.asm_function = _sha.sha256_asm; + return Sha256; +}(_hash.Hash); +exports.Sha256 = Sha256; + +},{"../hash":9,"./sha256.asm":12}],14:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +var __extends = undefined && undefined.__extends || function () { + var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) { + d.__proto__ = b; + } || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + }; + return function (d, b) { + extendStatics(d, b); + function __() { + this.constructor = d; + } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +}(); +var IllegalStateError = /** @class */function (_super) { + __extends(IllegalStateError, _super); + function IllegalStateError() { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + var _this = _super.apply(this, args) || this; + Object.create(Error.prototype, { name: { value: 'IllegalStateError' } }); + return _this; + } + return IllegalStateError; +}(Error); +exports.IllegalStateError = IllegalStateError; + +var IllegalArgumentError = /** @class */function (_super) { + __extends(IllegalArgumentError, _super); + function IllegalArgumentError() { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + var _this = _super.apply(this, args) || this; + Object.create(Error.prototype, { name: { value: 'IllegalArgumentError' } }); + return _this; + } + return IllegalArgumentError; +}(Error); +exports.IllegalArgumentError = IllegalArgumentError; + +var SecurityError = /** @class */function (_super) { + __extends(SecurityError, _super); + function SecurityError() { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + var _this = _super.apply(this, args) || this; + Object.create(Error.prototype, { name: { value: 'SecurityError' } }); + return _this; + } + return SecurityError; +}(Error); +exports.SecurityError = SecurityError; + +},{}],15:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.string_to_bytes = string_to_bytes; +exports.hex_to_bytes = hex_to_bytes; +exports.base64_to_bytes = base64_to_bytes; +exports.bytes_to_string = bytes_to_string; +exports.bytes_to_hex = bytes_to_hex; +exports.bytes_to_base64 = bytes_to_base64; +exports.pow2_ceil = pow2_ceil; +exports.is_number = is_number; +exports.is_string = is_string; +exports.is_buffer = is_buffer; +exports.is_bytes = is_bytes; +exports.is_typed_array = is_typed_array; +exports._heap_init = _heap_init; +exports._heap_write = _heap_write; +exports.joinBytes = joinBytes; +var local_atob = typeof atob === 'undefined' ? function (str) { + return require('buffer').Buffer.from(str, 'base64').toString('binary'); +} : atob; +var local_btoa = typeof btoa === 'undefined' ? function (str) { + return require('buffer').Buffer.from(str, 'binary').toString('base64'); +} : btoa; +function string_to_bytes(str, utf8) { + if (utf8 === void 0) { + utf8 = false; + } + var len = str.length, + bytes = new Uint8Array(utf8 ? 4 * len : len); + for (var i = 0, j = 0; i < len; i++) { + var c = str.charCodeAt(i); + if (utf8 && 0xd800 <= c && c <= 0xdbff) { + if (++i >= len) throw new Error('Malformed string, low surrogate expected at position ' + i); + c = (c ^ 0xd800) << 10 | 0x10000 | str.charCodeAt(i) ^ 0xdc00; + } else if (!utf8 && c >>> 8) { + throw new Error('Wide characters are not allowed.'); + } + if (!utf8 || c <= 0x7f) { + bytes[j++] = c; + } else if (c <= 0x7ff) { + bytes[j++] = 0xc0 | c >> 6; + bytes[j++] = 0x80 | c & 0x3f; + } else if (c <= 0xffff) { + bytes[j++] = 0xe0 | c >> 12; + bytes[j++] = 0x80 | c >> 6 & 0x3f; + bytes[j++] = 0x80 | c & 0x3f; + } else { + bytes[j++] = 0xf0 | c >> 18; + bytes[j++] = 0x80 | c >> 12 & 0x3f; + bytes[j++] = 0x80 | c >> 6 & 0x3f; + bytes[j++] = 0x80 | c & 0x3f; + } + } + return bytes.subarray(0, j); +} +function hex_to_bytes(str) { + var len = str.length; + if (len & 1) { + str = '0' + str; + len++; + } + var bytes = new Uint8Array(len >> 1); + for (var i = 0; i < len; i += 2) { + bytes[i >> 1] = parseInt(str.substr(i, 2), 16); + } + return bytes; +} +function base64_to_bytes(str) { + return string_to_bytes(local_atob(str)); +} +function bytes_to_string(bytes, utf8) { + if (utf8 === void 0) { + utf8 = false; + } + var len = bytes.length, + chars = new Array(len); + for (var i = 0, j = 0; i < len; i++) { + var b = bytes[i]; + if (!utf8 || b < 128) { + chars[j++] = b; + } else if (b >= 192 && b < 224 && i + 1 < len) { + chars[j++] = (b & 0x1f) << 6 | bytes[++i] & 0x3f; + } else if (b >= 224 && b < 240 && i + 2 < len) { + chars[j++] = (b & 0xf) << 12 | (bytes[++i] & 0x3f) << 6 | bytes[++i] & 0x3f; + } else if (b >= 240 && b < 248 && i + 3 < len) { + var c = (b & 7) << 18 | (bytes[++i] & 0x3f) << 12 | (bytes[++i] & 0x3f) << 6 | bytes[++i] & 0x3f; + if (c <= 0xffff) { + chars[j++] = c; + } else { + c ^= 0x10000; + chars[j++] = 0xd800 | c >> 10; + chars[j++] = 0xdc00 | c & 0x3ff; + } + } else { + throw new Error('Malformed UTF8 character at byte offset ' + i); + } + } + var str = '', + bs = 16384; + for (var i = 0; i < j; i += bs) { + str += String.fromCharCode.apply(String, chars.slice(i, i + bs <= j ? i + bs : j)); + } + return str; +} +function bytes_to_hex(arr) { + var str = ''; + for (var i = 0; i < arr.length; i++) { + var h = (arr[i] & 0xff).toString(16); + if (h.length < 2) str += '0'; + str += h; + } + return str; +} +function bytes_to_base64(arr) { + return local_btoa(bytes_to_string(arr)); +} +function pow2_ceil(a) { + a -= 1; + a |= a >>> 1; + a |= a >>> 2; + a |= a >>> 4; + a |= a >>> 8; + a |= a >>> 16; + a += 1; + return a; +} +function is_number(a) { + return typeof a === 'number'; +} +function is_string(a) { + return typeof a === 'string'; +} +function is_buffer(a) { + return a instanceof ArrayBuffer; +} +function is_bytes(a) { + return a instanceof Uint8Array; +} +function is_typed_array(a) { + return a instanceof Int8Array || a instanceof Uint8Array || a instanceof Int16Array || a instanceof Uint16Array || a instanceof Int32Array || a instanceof Uint32Array || a instanceof Float32Array || a instanceof Float64Array; +} +function _heap_init(heap, heapSize) { + var size = heap ? heap.byteLength : heapSize || 65536; + if (size & 0xfff || size <= 0) throw new Error('heap size must be a positive integer and a multiple of 4096'); + heap = heap || new Uint8Array(new ArrayBuffer(size)); + return heap; +} +function _heap_write(heap, hpos, data, dpos, dlen) { + var hlen = heap.length - hpos; + var wlen = hlen < dlen ? hlen : dlen; + heap.set(data.subarray(dpos, dpos + wlen), hpos); + return wlen; +} +function joinBytes() { + var arg = []; + for (var _i = 0; _i < arguments.length; _i++) { + arg[_i] = arguments[_i]; + } + var totalLenght = arg.reduce(function (sum, curr) { + return sum + curr.length; + }, 0); + var ret = new Uint8Array(totalLenght); + var cursor = 0; + for (var i = 0; i < arg.length; i++) { + ret.set(arg[i], cursor); + cursor += arg[i].length; + } + return ret; +} + +},{"buffer":"buffer"}],16:[function(require,module,exports){ +(function (module, exports) { + 'use strict'; + + // Utils + function assert (val, msg) { + if (!val) throw new Error(msg || 'Assertion failed'); + } + + // Could use `inherits` module, but don't want to move from single file + // architecture yet. + function inherits (ctor, superCtor) { + ctor.super_ = superCtor; + var TempCtor = function () {}; + TempCtor.prototype = superCtor.prototype; + ctor.prototype = new TempCtor(); + ctor.prototype.constructor = ctor; + } + + // BN + + function BN (number, base, endian) { + if (BN.isBN(number)) { + return number; + } + + this.negative = 0; + this.words = null; + this.length = 0; + + // Reduction context + this.red = null; + + if (number !== null) { + if (base === 'le' || base === 'be') { + endian = base; + base = 10; + } + + this._init(number || 0, base || 10, endian || 'be'); + } + } + if (typeof module === 'object') { + module.exports = BN; + } else { + exports.BN = BN; + } + + BN.BN = BN; + BN.wordSize = 26; + + var Buffer; + try { + Buffer = require('buffer').Buffer; + } catch (e) { + } + + BN.isBN = function isBN (num) { + if (num instanceof BN) { + return true; + } + + return num !== null && typeof num === 'object' && + num.constructor.wordSize === BN.wordSize && Array.isArray(num.words); + }; + + BN.max = function max (left, right) { + if (left.cmp(right) > 0) return left; + return right; + }; + + BN.min = function min (left, right) { + if (left.cmp(right) < 0) return left; + return right; + }; + + BN.prototype._init = function init (number, base, endian) { + if (typeof number === 'number') { + return this._initNumber(number, base, endian); + } + + if (typeof number === 'object') { + return this._initArray(number, base, endian); + } + + if (base === 'hex') { + base = 16; + } + assert(base === (base | 0) && base >= 2 && base <= 36); + + number = number.toString().replace(/\s+/g, ''); + var start = 0; + if (number[0] === '-') { + start++; + } + + if (base === 16) { + this._parseHex(number, start); + } else { + this._parseBase(number, base, start); + } + + if (number[0] === '-') { + this.negative = 1; + } + + this.strip(); + + if (endian !== 'le') return; + + this._initArray(this.toArray(), base, endian); + }; + + BN.prototype._initNumber = function _initNumber (number, base, endian) { + if (number < 0) { + this.negative = 1; + number = -number; + } + if (number < 0x4000000) { + this.words = [ number & 0x3ffffff ]; + this.length = 1; + } else if (number < 0x10000000000000) { + this.words = [ + number & 0x3ffffff, + (number / 0x4000000) & 0x3ffffff + ]; + this.length = 2; + } else { + assert(number < 0x20000000000000); // 2 ^ 53 (unsafe) + this.words = [ + number & 0x3ffffff, + (number / 0x4000000) & 0x3ffffff, + 1 + ]; + this.length = 3; + } + + if (endian !== 'le') return; + + // Reverse the bytes + this._initArray(this.toArray(), base, endian); + }; + + BN.prototype._initArray = function _initArray (number, base, endian) { + // Perhaps a Uint8Array + assert(typeof number.length === 'number'); + if (number.length <= 0) { + this.words = [ 0 ]; + this.length = 1; + return this; + } + + this.length = Math.ceil(number.length / 3); + this.words = new Array(this.length); + for (var i = 0; i < this.length; i++) { + this.words[i] = 0; + } + + var j, w; + var off = 0; + if (endian === 'be') { + for (i = number.length - 1, j = 0; i >= 0; i -= 3) { + w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16); + this.words[j] |= (w << off) & 0x3ffffff; + this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; + off += 24; + if (off >= 26) { + off -= 26; + j++; + } + } + } else if (endian === 'le') { + for (i = 0, j = 0; i < number.length; i += 3) { + w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16); + this.words[j] |= (w << off) & 0x3ffffff; + this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; + off += 24; + if (off >= 26) { + off -= 26; + j++; + } + } + } + return this.strip(); + }; + + function parseHex (str, start, end) { + var r = 0; + var len = Math.min(str.length, end); + for (var i = start; i < len; i++) { + var c = str.charCodeAt(i) - 48; + + r <<= 4; + + // 'a' - 'f' + if (c >= 49 && c <= 54) { + r |= c - 49 + 0xa; + + // 'A' - 'F' + } else if (c >= 17 && c <= 22) { + r |= c - 17 + 0xa; + + // '0' - '9' + } else { + r |= c & 0xf; + } + } + return r; + } + + BN.prototype._parseHex = function _parseHex (number, start) { + // Create possibly bigger array to ensure that it fits the number + this.length = Math.ceil((number.length - start) / 6); + this.words = new Array(this.length); + for (var i = 0; i < this.length; i++) { + this.words[i] = 0; + } + + var j, w; + // Scan 24-bit chunks and add them to the number + var off = 0; + for (i = number.length - 6, j = 0; i >= start; i -= 6) { + w = parseHex(number, i, i + 6); + this.words[j] |= (w << off) & 0x3ffffff; + // NOTE: `0x3fffff` is intentional here, 26bits max shift + 24bit hex limb + this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; + off += 24; + if (off >= 26) { + off -= 26; + j++; + } + } + if (i + 6 !== start) { + w = parseHex(number, start, i + 6); + this.words[j] |= (w << off) & 0x3ffffff; + this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; + } + this.strip(); + }; + + function parseBase (str, start, end, mul) { + var r = 0; + var len = Math.min(str.length, end); + for (var i = start; i < len; i++) { + var c = str.charCodeAt(i) - 48; + + r *= mul; + + // 'a' + if (c >= 49) { + r += c - 49 + 0xa; + + // 'A' + } else if (c >= 17) { + r += c - 17 + 0xa; + + // '0' - '9' + } else { + r += c; + } + } + return r; + } + + BN.prototype._parseBase = function _parseBase (number, base, start) { + // Initialize as zero + this.words = [ 0 ]; + this.length = 1; + + // Find length of limb in base + for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) { + limbLen++; + } + limbLen--; + limbPow = (limbPow / base) | 0; + + var total = number.length - start; + var mod = total % limbLen; + var end = Math.min(total, total - mod) + start; + + var word = 0; + for (var i = start; i < end; i += limbLen) { + word = parseBase(number, i, i + limbLen, base); + + this.imuln(limbPow); + if (this.words[0] + word < 0x4000000) { + this.words[0] += word; + } else { + this._iaddn(word); + } + } + + if (mod !== 0) { + var pow = 1; + word = parseBase(number, i, number.length, base); + + for (i = 0; i < mod; i++) { + pow *= base; + } + + this.imuln(pow); + if (this.words[0] + word < 0x4000000) { + this.words[0] += word; + } else { + this._iaddn(word); + } + } + }; + + BN.prototype.copy = function copy (dest) { + dest.words = new Array(this.length); + for (var i = 0; i < this.length; i++) { + dest.words[i] = this.words[i]; + } + dest.length = this.length; + dest.negative = this.negative; + dest.red = this.red; + }; + + BN.prototype.clone = function clone () { + var r = new BN(null); + this.copy(r); + return r; + }; + + BN.prototype._expand = function _expand (size) { + while (this.length < size) { + this.words[this.length++] = 0; + } + return this; + }; + + // Remove leading `0` from `this` + BN.prototype.strip = function strip () { + while (this.length > 1 && this.words[this.length - 1] === 0) { + this.length--; + } + return this._normSign(); + }; + + BN.prototype._normSign = function _normSign () { + // -0 = 0 + if (this.length === 1 && this.words[0] === 0) { + this.negative = 0; + } + return this; + }; + + BN.prototype.inspect = function inspect () { + return (this.red ? ''; + }; + + /* + + var zeros = []; + var groupSizes = []; + var groupBases = []; + + var s = ''; + var i = -1; + while (++i < BN.wordSize) { + zeros[i] = s; + s += '0'; + } + groupSizes[0] = 0; + groupSizes[1] = 0; + groupBases[0] = 0; + groupBases[1] = 0; + var base = 2 - 1; + while (++base < 36 + 1) { + var groupSize = 0; + var groupBase = 1; + while (groupBase < (1 << BN.wordSize) / base) { + groupBase *= base; + groupSize += 1; + } + groupSizes[base] = groupSize; + groupBases[base] = groupBase; + } + + */ + + var zeros = [ + '', + '0', + '00', + '000', + '0000', + '00000', + '000000', + '0000000', + '00000000', + '000000000', + '0000000000', + '00000000000', + '000000000000', + '0000000000000', + '00000000000000', + '000000000000000', + '0000000000000000', + '00000000000000000', + '000000000000000000', + '0000000000000000000', + '00000000000000000000', + '000000000000000000000', + '0000000000000000000000', + '00000000000000000000000', + '000000000000000000000000', + '0000000000000000000000000' + ]; + + var groupSizes = [ + 0, 0, + 25, 16, 12, 11, 10, 9, 8, + 8, 7, 7, 7, 7, 6, 6, + 6, 6, 6, 6, 6, 5, 5, + 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5 + ]; + + var groupBases = [ + 0, 0, + 33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216, + 43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625, + 16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632, + 6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149, + 24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176 + ]; + + BN.prototype.toString = function toString (base, padding) { + base = base || 10; + padding = padding | 0 || 1; + + var out; + if (base === 16 || base === 'hex') { + out = ''; + var off = 0; + var carry = 0; + for (var i = 0; i < this.length; i++) { + var w = this.words[i]; + var word = (((w << off) | carry) & 0xffffff).toString(16); + carry = (w >>> (24 - off)) & 0xffffff; + if (carry !== 0 || i !== this.length - 1) { + out = zeros[6 - word.length] + word + out; + } else { + out = word + out; + } + off += 2; + if (off >= 26) { + off -= 26; + i--; + } + } + if (carry !== 0) { + out = carry.toString(16) + out; + } + while (out.length % padding !== 0) { + out = '0' + out; + } + if (this.negative !== 0) { + out = '-' + out; + } + return out; + } + + if (base === (base | 0) && base >= 2 && base <= 36) { + // var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base)); + var groupSize = groupSizes[base]; + // var groupBase = Math.pow(base, groupSize); + var groupBase = groupBases[base]; + out = ''; + var c = this.clone(); + c.negative = 0; + while (!c.isZero()) { + var r = c.modn(groupBase).toString(base); + c = c.idivn(groupBase); + + if (!c.isZero()) { + out = zeros[groupSize - r.length] + r + out; + } else { + out = r + out; + } + } + if (this.isZero()) { + out = '0' + out; + } + while (out.length % padding !== 0) { + out = '0' + out; + } + if (this.negative !== 0) { + out = '-' + out; + } + return out; + } + + assert(false, 'Base should be between 2 and 36'); + }; + + BN.prototype.toNumber = function toNumber () { + var ret = this.words[0]; + if (this.length === 2) { + ret += this.words[1] * 0x4000000; + } else if (this.length === 3 && this.words[2] === 0x01) { + // NOTE: at this stage it is known that the top bit is set + ret += 0x10000000000000 + (this.words[1] * 0x4000000); + } else if (this.length > 2) { + assert(false, 'Number can only safely store up to 53 bits'); + } + return (this.negative !== 0) ? -ret : ret; + }; + + BN.prototype.toJSON = function toJSON () { + return this.toString(16); + }; + + BN.prototype.toBuffer = function toBuffer (endian, length) { + assert(typeof Buffer !== 'undefined'); + return this.toArrayLike(Buffer, endian, length); + }; + + BN.prototype.toArray = function toArray (endian, length) { + return this.toArrayLike(Array, endian, length); + }; + + BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) { + var byteLength = this.byteLength(); + var reqLength = length || Math.max(1, byteLength); + assert(byteLength <= reqLength, 'byte array longer than desired length'); + assert(reqLength > 0, 'Requested array length <= 0'); + + this.strip(); + var littleEndian = endian === 'le'; + var res = new ArrayType(reqLength); + + var b, i; + var q = this.clone(); + if (!littleEndian) { + // Assume big-endian + for (i = 0; i < reqLength - byteLength; i++) { + res[i] = 0; + } + + for (i = 0; !q.isZero(); i++) { + b = q.andln(0xff); + q.iushrn(8); + + res[reqLength - i - 1] = b; + } + } else { + for (i = 0; !q.isZero(); i++) { + b = q.andln(0xff); + q.iushrn(8); + + res[i] = b; + } + + for (; i < reqLength; i++) { + res[i] = 0; + } + } + + return res; + }; + + if (Math.clz32) { + BN.prototype._countBits = function _countBits (w) { + return 32 - Math.clz32(w); + }; + } else { + BN.prototype._countBits = function _countBits (w) { + var t = w; + var r = 0; + if (t >= 0x1000) { + r += 13; + t >>>= 13; + } + if (t >= 0x40) { + r += 7; + t >>>= 7; + } + if (t >= 0x8) { + r += 4; + t >>>= 4; + } + if (t >= 0x02) { + r += 2; + t >>>= 2; + } + return r + t; + }; + } + + BN.prototype._zeroBits = function _zeroBits (w) { + // Short-cut + if (w === 0) return 26; + + var t = w; + var r = 0; + if ((t & 0x1fff) === 0) { + r += 13; + t >>>= 13; + } + if ((t & 0x7f) === 0) { + r += 7; + t >>>= 7; + } + if ((t & 0xf) === 0) { + r += 4; + t >>>= 4; + } + if ((t & 0x3) === 0) { + r += 2; + t >>>= 2; + } + if ((t & 0x1) === 0) { + r++; + } + return r; + }; + + // Return number of used bits in a BN + BN.prototype.bitLength = function bitLength () { + var w = this.words[this.length - 1]; + var hi = this._countBits(w); + return (this.length - 1) * 26 + hi; + }; + + function toBitArray (num) { + var w = new Array(num.bitLength()); + + for (var bit = 0; bit < w.length; bit++) { + var off = (bit / 26) | 0; + var wbit = bit % 26; + + w[bit] = (num.words[off] & (1 << wbit)) >>> wbit; + } + + return w; + } + + // Number of trailing zero bits + BN.prototype.zeroBits = function zeroBits () { + if (this.isZero()) return 0; + + var r = 0; + for (var i = 0; i < this.length; i++) { + var b = this._zeroBits(this.words[i]); + r += b; + if (b !== 26) break; + } + return r; + }; + + BN.prototype.byteLength = function byteLength () { + return Math.ceil(this.bitLength() / 8); + }; + + BN.prototype.toTwos = function toTwos (width) { + if (this.negative !== 0) { + return this.abs().inotn(width).iaddn(1); + } + return this.clone(); + }; + + BN.prototype.fromTwos = function fromTwos (width) { + if (this.testn(width - 1)) { + return this.notn(width).iaddn(1).ineg(); + } + return this.clone(); + }; + + BN.prototype.isNeg = function isNeg () { + return this.negative !== 0; + }; + + // Return negative clone of `this` + BN.prototype.neg = function neg () { + return this.clone().ineg(); + }; + + BN.prototype.ineg = function ineg () { + if (!this.isZero()) { + this.negative ^= 1; + } + + return this; + }; + + // Or `num` with `this` in-place + BN.prototype.iuor = function iuor (num) { + while (this.length < num.length) { + this.words[this.length++] = 0; + } + + for (var i = 0; i < num.length; i++) { + this.words[i] = this.words[i] | num.words[i]; + } + + return this.strip(); + }; + + BN.prototype.ior = function ior (num) { + assert((this.negative | num.negative) === 0); + return this.iuor(num); + }; + + // Or `num` with `this` + BN.prototype.or = function or (num) { + if (this.length > num.length) return this.clone().ior(num); + return num.clone().ior(this); + }; + + BN.prototype.uor = function uor (num) { + if (this.length > num.length) return this.clone().iuor(num); + return num.clone().iuor(this); + }; + + // And `num` with `this` in-place + BN.prototype.iuand = function iuand (num) { + // b = min-length(num, this) + var b; + if (this.length > num.length) { + b = num; + } else { + b = this; + } + + for (var i = 0; i < b.length; i++) { + this.words[i] = this.words[i] & num.words[i]; + } + + this.length = b.length; + + return this.strip(); + }; + + BN.prototype.iand = function iand (num) { + assert((this.negative | num.negative) === 0); + return this.iuand(num); + }; + + // And `num` with `this` + BN.prototype.and = function and (num) { + if (this.length > num.length) return this.clone().iand(num); + return num.clone().iand(this); + }; + + BN.prototype.uand = function uand (num) { + if (this.length > num.length) return this.clone().iuand(num); + return num.clone().iuand(this); + }; + + // Xor `num` with `this` in-place + BN.prototype.iuxor = function iuxor (num) { + // a.length > b.length + var a; + var b; + if (this.length > num.length) { + a = this; + b = num; + } else { + a = num; + b = this; + } + + for (var i = 0; i < b.length; i++) { + this.words[i] = a.words[i] ^ b.words[i]; + } + + if (this !== a) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } + } + + this.length = a.length; + + return this.strip(); + }; + + BN.prototype.ixor = function ixor (num) { + assert((this.negative | num.negative) === 0); + return this.iuxor(num); + }; + + // Xor `num` with `this` + BN.prototype.xor = function xor (num) { + if (this.length > num.length) return this.clone().ixor(num); + return num.clone().ixor(this); + }; + + BN.prototype.uxor = function uxor (num) { + if (this.length > num.length) return this.clone().iuxor(num); + return num.clone().iuxor(this); + }; + + // Not ``this`` with ``width`` bitwidth + BN.prototype.inotn = function inotn (width) { + assert(typeof width === 'number' && width >= 0); + + var bytesNeeded = Math.ceil(width / 26) | 0; + var bitsLeft = width % 26; + + // Extend the buffer with leading zeroes + this._expand(bytesNeeded); + + if (bitsLeft > 0) { + bytesNeeded--; + } + + // Handle complete words + for (var i = 0; i < bytesNeeded; i++) { + this.words[i] = ~this.words[i] & 0x3ffffff; + } + + // Handle the residue + if (bitsLeft > 0) { + this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft)); + } + + // And remove leading zeroes + return this.strip(); + }; + + BN.prototype.notn = function notn (width) { + return this.clone().inotn(width); + }; + + // Set `bit` of `this` + BN.prototype.setn = function setn (bit, val) { + assert(typeof bit === 'number' && bit >= 0); + + var off = (bit / 26) | 0; + var wbit = bit % 26; + + this._expand(off + 1); + + if (val) { + this.words[off] = this.words[off] | (1 << wbit); + } else { + this.words[off] = this.words[off] & ~(1 << wbit); + } + + return this.strip(); + }; + + // Add `num` to `this` in-place + BN.prototype.iadd = function iadd (num) { + var r; + + // negative + positive + if (this.negative !== 0 && num.negative === 0) { + this.negative = 0; + r = this.isub(num); + this.negative ^= 1; + return this._normSign(); + + // positive + negative + } else if (this.negative === 0 && num.negative !== 0) { + num.negative = 0; + r = this.isub(num); + num.negative = 1; + return r._normSign(); + } + + // a.length > b.length + var a, b; + if (this.length > num.length) { + a = this; + b = num; + } else { + a = num; + b = this; + } + + var carry = 0; + for (var i = 0; i < b.length; i++) { + r = (a.words[i] | 0) + (b.words[i] | 0) + carry; + this.words[i] = r & 0x3ffffff; + carry = r >>> 26; + } + for (; carry !== 0 && i < a.length; i++) { + r = (a.words[i] | 0) + carry; + this.words[i] = r & 0x3ffffff; + carry = r >>> 26; + } + + this.length = a.length; + if (carry !== 0) { + this.words[this.length] = carry; + this.length++; + // Copy the rest of the words + } else if (a !== this) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } + } + + return this; + }; + + // Add `num` to `this` + BN.prototype.add = function add (num) { + var res; + if (num.negative !== 0 && this.negative === 0) { + num.negative = 0; + res = this.sub(num); + num.negative ^= 1; + return res; + } else if (num.negative === 0 && this.negative !== 0) { + this.negative = 0; + res = num.sub(this); + this.negative = 1; + return res; + } + + if (this.length > num.length) return this.clone().iadd(num); + + return num.clone().iadd(this); + }; + + // Subtract `num` from `this` in-place + BN.prototype.isub = function isub (num) { + // this - (-num) = this + num + if (num.negative !== 0) { + num.negative = 0; + var r = this.iadd(num); + num.negative = 1; + return r._normSign(); + + // -this - num = -(this + num) + } else if (this.negative !== 0) { + this.negative = 0; + this.iadd(num); + this.negative = 1; + return this._normSign(); + } + + // At this point both numbers are positive + var cmp = this.cmp(num); + + // Optimization - zeroify + if (cmp === 0) { + this.negative = 0; + this.length = 1; + this.words[0] = 0; + return this; + } + + // a > b + var a, b; + if (cmp > 0) { + a = this; + b = num; + } else { + a = num; + b = this; + } + + var carry = 0; + for (var i = 0; i < b.length; i++) { + r = (a.words[i] | 0) - (b.words[i] | 0) + carry; + carry = r >> 26; + this.words[i] = r & 0x3ffffff; + } + for (; carry !== 0 && i < a.length; i++) { + r = (a.words[i] | 0) + carry; + carry = r >> 26; + this.words[i] = r & 0x3ffffff; + } + + // Copy rest of the words + if (carry === 0 && i < a.length && a !== this) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } + } + + this.length = Math.max(this.length, i); + + if (a !== this) { + this.negative = 1; + } + + return this.strip(); + }; + + // Subtract `num` from `this` + BN.prototype.sub = function sub (num) { + return this.clone().isub(num); + }; + + function smallMulTo (self, num, out) { + out.negative = num.negative ^ self.negative; + var len = (self.length + num.length) | 0; + out.length = len; + len = (len - 1) | 0; + + // Peel one iteration (compiler can't do it, because of code complexity) + var a = self.words[0] | 0; + var b = num.words[0] | 0; + var r = a * b; + + var lo = r & 0x3ffffff; + var carry = (r / 0x4000000) | 0; + out.words[0] = lo; + + for (var k = 1; k < len; k++) { + // Sum all words with the same `i + j = k` and accumulate `ncarry`, + // note that ncarry could be >= 0x3ffffff + var ncarry = carry >>> 26; + var rword = carry & 0x3ffffff; + var maxJ = Math.min(k, num.length - 1); + for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { + var i = (k - j) | 0; + a = self.words[i] | 0; + b = num.words[j] | 0; + r = a * b + rword; + ncarry += (r / 0x4000000) | 0; + rword = r & 0x3ffffff; + } + out.words[k] = rword | 0; + carry = ncarry | 0; + } + if (carry !== 0) { + out.words[k] = carry | 0; + } else { + out.length--; + } + + return out.strip(); + } + + // TODO(indutny): it may be reasonable to omit it for users who don't need + // to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit + // multiplication (like elliptic secp256k1). + var comb10MulTo = function comb10MulTo (self, num, out) { + var a = self.words; + var b = num.words; + var o = out.words; + var c = 0; + var lo; + var mid; + var hi; + var a0 = a[0] | 0; + var al0 = a0 & 0x1fff; + var ah0 = a0 >>> 13; + var a1 = a[1] | 0; + var al1 = a1 & 0x1fff; + var ah1 = a1 >>> 13; + var a2 = a[2] | 0; + var al2 = a2 & 0x1fff; + var ah2 = a2 >>> 13; + var a3 = a[3] | 0; + var al3 = a3 & 0x1fff; + var ah3 = a3 >>> 13; + var a4 = a[4] | 0; + var al4 = a4 & 0x1fff; + var ah4 = a4 >>> 13; + var a5 = a[5] | 0; + var al5 = a5 & 0x1fff; + var ah5 = a5 >>> 13; + var a6 = a[6] | 0; + var al6 = a6 & 0x1fff; + var ah6 = a6 >>> 13; + var a7 = a[7] | 0; + var al7 = a7 & 0x1fff; + var ah7 = a7 >>> 13; + var a8 = a[8] | 0; + var al8 = a8 & 0x1fff; + var ah8 = a8 >>> 13; + var a9 = a[9] | 0; + var al9 = a9 & 0x1fff; + var ah9 = a9 >>> 13; + var b0 = b[0] | 0; + var bl0 = b0 & 0x1fff; + var bh0 = b0 >>> 13; + var b1 = b[1] | 0; + var bl1 = b1 & 0x1fff; + var bh1 = b1 >>> 13; + var b2 = b[2] | 0; + var bl2 = b2 & 0x1fff; + var bh2 = b2 >>> 13; + var b3 = b[3] | 0; + var bl3 = b3 & 0x1fff; + var bh3 = b3 >>> 13; + var b4 = b[4] | 0; + var bl4 = b4 & 0x1fff; + var bh4 = b4 >>> 13; + var b5 = b[5] | 0; + var bl5 = b5 & 0x1fff; + var bh5 = b5 >>> 13; + var b6 = b[6] | 0; + var bl6 = b6 & 0x1fff; + var bh6 = b6 >>> 13; + var b7 = b[7] | 0; + var bl7 = b7 & 0x1fff; + var bh7 = b7 >>> 13; + var b8 = b[8] | 0; + var bl8 = b8 & 0x1fff; + var bh8 = b8 >>> 13; + var b9 = b[9] | 0; + var bl9 = b9 & 0x1fff; + var bh9 = b9 >>> 13; + + out.negative = self.negative ^ num.negative; + out.length = 19; + /* k = 0 */ + lo = Math.imul(al0, bl0); + mid = Math.imul(al0, bh0); + mid = (mid + Math.imul(ah0, bl0)) | 0; + hi = Math.imul(ah0, bh0); + var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0; + w0 &= 0x3ffffff; + /* k = 1 */ + lo = Math.imul(al1, bl0); + mid = Math.imul(al1, bh0); + mid = (mid + Math.imul(ah1, bl0)) | 0; + hi = Math.imul(ah1, bh0); + lo = (lo + Math.imul(al0, bl1)) | 0; + mid = (mid + Math.imul(al0, bh1)) | 0; + mid = (mid + Math.imul(ah0, bl1)) | 0; + hi = (hi + Math.imul(ah0, bh1)) | 0; + var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0; + w1 &= 0x3ffffff; + /* k = 2 */ + lo = Math.imul(al2, bl0); + mid = Math.imul(al2, bh0); + mid = (mid + Math.imul(ah2, bl0)) | 0; + hi = Math.imul(ah2, bh0); + lo = (lo + Math.imul(al1, bl1)) | 0; + mid = (mid + Math.imul(al1, bh1)) | 0; + mid = (mid + Math.imul(ah1, bl1)) | 0; + hi = (hi + Math.imul(ah1, bh1)) | 0; + lo = (lo + Math.imul(al0, bl2)) | 0; + mid = (mid + Math.imul(al0, bh2)) | 0; + mid = (mid + Math.imul(ah0, bl2)) | 0; + hi = (hi + Math.imul(ah0, bh2)) | 0; + var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0; + w2 &= 0x3ffffff; + /* k = 3 */ + lo = Math.imul(al3, bl0); + mid = Math.imul(al3, bh0); + mid = (mid + Math.imul(ah3, bl0)) | 0; + hi = Math.imul(ah3, bh0); + lo = (lo + Math.imul(al2, bl1)) | 0; + mid = (mid + Math.imul(al2, bh1)) | 0; + mid = (mid + Math.imul(ah2, bl1)) | 0; + hi = (hi + Math.imul(ah2, bh1)) | 0; + lo = (lo + Math.imul(al1, bl2)) | 0; + mid = (mid + Math.imul(al1, bh2)) | 0; + mid = (mid + Math.imul(ah1, bl2)) | 0; + hi = (hi + Math.imul(ah1, bh2)) | 0; + lo = (lo + Math.imul(al0, bl3)) | 0; + mid = (mid + Math.imul(al0, bh3)) | 0; + mid = (mid + Math.imul(ah0, bl3)) | 0; + hi = (hi + Math.imul(ah0, bh3)) | 0; + var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0; + w3 &= 0x3ffffff; + /* k = 4 */ + lo = Math.imul(al4, bl0); + mid = Math.imul(al4, bh0); + mid = (mid + Math.imul(ah4, bl0)) | 0; + hi = Math.imul(ah4, bh0); + lo = (lo + Math.imul(al3, bl1)) | 0; + mid = (mid + Math.imul(al3, bh1)) | 0; + mid = (mid + Math.imul(ah3, bl1)) | 0; + hi = (hi + Math.imul(ah3, bh1)) | 0; + lo = (lo + Math.imul(al2, bl2)) | 0; + mid = (mid + Math.imul(al2, bh2)) | 0; + mid = (mid + Math.imul(ah2, bl2)) | 0; + hi = (hi + Math.imul(ah2, bh2)) | 0; + lo = (lo + Math.imul(al1, bl3)) | 0; + mid = (mid + Math.imul(al1, bh3)) | 0; + mid = (mid + Math.imul(ah1, bl3)) | 0; + hi = (hi + Math.imul(ah1, bh3)) | 0; + lo = (lo + Math.imul(al0, bl4)) | 0; + mid = (mid + Math.imul(al0, bh4)) | 0; + mid = (mid + Math.imul(ah0, bl4)) | 0; + hi = (hi + Math.imul(ah0, bh4)) | 0; + var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0; + w4 &= 0x3ffffff; + /* k = 5 */ + lo = Math.imul(al5, bl0); + mid = Math.imul(al5, bh0); + mid = (mid + Math.imul(ah5, bl0)) | 0; + hi = Math.imul(ah5, bh0); + lo = (lo + Math.imul(al4, bl1)) | 0; + mid = (mid + Math.imul(al4, bh1)) | 0; + mid = (mid + Math.imul(ah4, bl1)) | 0; + hi = (hi + Math.imul(ah4, bh1)) | 0; + lo = (lo + Math.imul(al3, bl2)) | 0; + mid = (mid + Math.imul(al3, bh2)) | 0; + mid = (mid + Math.imul(ah3, bl2)) | 0; + hi = (hi + Math.imul(ah3, bh2)) | 0; + lo = (lo + Math.imul(al2, bl3)) | 0; + mid = (mid + Math.imul(al2, bh3)) | 0; + mid = (mid + Math.imul(ah2, bl3)) | 0; + hi = (hi + Math.imul(ah2, bh3)) | 0; + lo = (lo + Math.imul(al1, bl4)) | 0; + mid = (mid + Math.imul(al1, bh4)) | 0; + mid = (mid + Math.imul(ah1, bl4)) | 0; + hi = (hi + Math.imul(ah1, bh4)) | 0; + lo = (lo + Math.imul(al0, bl5)) | 0; + mid = (mid + Math.imul(al0, bh5)) | 0; + mid = (mid + Math.imul(ah0, bl5)) | 0; + hi = (hi + Math.imul(ah0, bh5)) | 0; + var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0; + w5 &= 0x3ffffff; + /* k = 6 */ + lo = Math.imul(al6, bl0); + mid = Math.imul(al6, bh0); + mid = (mid + Math.imul(ah6, bl0)) | 0; + hi = Math.imul(ah6, bh0); + lo = (lo + Math.imul(al5, bl1)) | 0; + mid = (mid + Math.imul(al5, bh1)) | 0; + mid = (mid + Math.imul(ah5, bl1)) | 0; + hi = (hi + Math.imul(ah5, bh1)) | 0; + lo = (lo + Math.imul(al4, bl2)) | 0; + mid = (mid + Math.imul(al4, bh2)) | 0; + mid = (mid + Math.imul(ah4, bl2)) | 0; + hi = (hi + Math.imul(ah4, bh2)) | 0; + lo = (lo + Math.imul(al3, bl3)) | 0; + mid = (mid + Math.imul(al3, bh3)) | 0; + mid = (mid + Math.imul(ah3, bl3)) | 0; + hi = (hi + Math.imul(ah3, bh3)) | 0; + lo = (lo + Math.imul(al2, bl4)) | 0; + mid = (mid + Math.imul(al2, bh4)) | 0; + mid = (mid + Math.imul(ah2, bl4)) | 0; + hi = (hi + Math.imul(ah2, bh4)) | 0; + lo = (lo + Math.imul(al1, bl5)) | 0; + mid = (mid + Math.imul(al1, bh5)) | 0; + mid = (mid + Math.imul(ah1, bl5)) | 0; + hi = (hi + Math.imul(ah1, bh5)) | 0; + lo = (lo + Math.imul(al0, bl6)) | 0; + mid = (mid + Math.imul(al0, bh6)) | 0; + mid = (mid + Math.imul(ah0, bl6)) | 0; + hi = (hi + Math.imul(ah0, bh6)) | 0; + var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0; + w6 &= 0x3ffffff; + /* k = 7 */ + lo = Math.imul(al7, bl0); + mid = Math.imul(al7, bh0); + mid = (mid + Math.imul(ah7, bl0)) | 0; + hi = Math.imul(ah7, bh0); + lo = (lo + Math.imul(al6, bl1)) | 0; + mid = (mid + Math.imul(al6, bh1)) | 0; + mid = (mid + Math.imul(ah6, bl1)) | 0; + hi = (hi + Math.imul(ah6, bh1)) | 0; + lo = (lo + Math.imul(al5, bl2)) | 0; + mid = (mid + Math.imul(al5, bh2)) | 0; + mid = (mid + Math.imul(ah5, bl2)) | 0; + hi = (hi + Math.imul(ah5, bh2)) | 0; + lo = (lo + Math.imul(al4, bl3)) | 0; + mid = (mid + Math.imul(al4, bh3)) | 0; + mid = (mid + Math.imul(ah4, bl3)) | 0; + hi = (hi + Math.imul(ah4, bh3)) | 0; + lo = (lo + Math.imul(al3, bl4)) | 0; + mid = (mid + Math.imul(al3, bh4)) | 0; + mid = (mid + Math.imul(ah3, bl4)) | 0; + hi = (hi + Math.imul(ah3, bh4)) | 0; + lo = (lo + Math.imul(al2, bl5)) | 0; + mid = (mid + Math.imul(al2, bh5)) | 0; + mid = (mid + Math.imul(ah2, bl5)) | 0; + hi = (hi + Math.imul(ah2, bh5)) | 0; + lo = (lo + Math.imul(al1, bl6)) | 0; + mid = (mid + Math.imul(al1, bh6)) | 0; + mid = (mid + Math.imul(ah1, bl6)) | 0; + hi = (hi + Math.imul(ah1, bh6)) | 0; + lo = (lo + Math.imul(al0, bl7)) | 0; + mid = (mid + Math.imul(al0, bh7)) | 0; + mid = (mid + Math.imul(ah0, bl7)) | 0; + hi = (hi + Math.imul(ah0, bh7)) | 0; + var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0; + w7 &= 0x3ffffff; + /* k = 8 */ + lo = Math.imul(al8, bl0); + mid = Math.imul(al8, bh0); + mid = (mid + Math.imul(ah8, bl0)) | 0; + hi = Math.imul(ah8, bh0); + lo = (lo + Math.imul(al7, bl1)) | 0; + mid = (mid + Math.imul(al7, bh1)) | 0; + mid = (mid + Math.imul(ah7, bl1)) | 0; + hi = (hi + Math.imul(ah7, bh1)) | 0; + lo = (lo + Math.imul(al6, bl2)) | 0; + mid = (mid + Math.imul(al6, bh2)) | 0; + mid = (mid + Math.imul(ah6, bl2)) | 0; + hi = (hi + Math.imul(ah6, bh2)) | 0; + lo = (lo + Math.imul(al5, bl3)) | 0; + mid = (mid + Math.imul(al5, bh3)) | 0; + mid = (mid + Math.imul(ah5, bl3)) | 0; + hi = (hi + Math.imul(ah5, bh3)) | 0; + lo = (lo + Math.imul(al4, bl4)) | 0; + mid = (mid + Math.imul(al4, bh4)) | 0; + mid = (mid + Math.imul(ah4, bl4)) | 0; + hi = (hi + Math.imul(ah4, bh4)) | 0; + lo = (lo + Math.imul(al3, bl5)) | 0; + mid = (mid + Math.imul(al3, bh5)) | 0; + mid = (mid + Math.imul(ah3, bl5)) | 0; + hi = (hi + Math.imul(ah3, bh5)) | 0; + lo = (lo + Math.imul(al2, bl6)) | 0; + mid = (mid + Math.imul(al2, bh6)) | 0; + mid = (mid + Math.imul(ah2, bl6)) | 0; + hi = (hi + Math.imul(ah2, bh6)) | 0; + lo = (lo + Math.imul(al1, bl7)) | 0; + mid = (mid + Math.imul(al1, bh7)) | 0; + mid = (mid + Math.imul(ah1, bl7)) | 0; + hi = (hi + Math.imul(ah1, bh7)) | 0; + lo = (lo + Math.imul(al0, bl8)) | 0; + mid = (mid + Math.imul(al0, bh8)) | 0; + mid = (mid + Math.imul(ah0, bl8)) | 0; + hi = (hi + Math.imul(ah0, bh8)) | 0; + var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0; + w8 &= 0x3ffffff; + /* k = 9 */ + lo = Math.imul(al9, bl0); + mid = Math.imul(al9, bh0); + mid = (mid + Math.imul(ah9, bl0)) | 0; + hi = Math.imul(ah9, bh0); + lo = (lo + Math.imul(al8, bl1)) | 0; + mid = (mid + Math.imul(al8, bh1)) | 0; + mid = (mid + Math.imul(ah8, bl1)) | 0; + hi = (hi + Math.imul(ah8, bh1)) | 0; + lo = (lo + Math.imul(al7, bl2)) | 0; + mid = (mid + Math.imul(al7, bh2)) | 0; + mid = (mid + Math.imul(ah7, bl2)) | 0; + hi = (hi + Math.imul(ah7, bh2)) | 0; + lo = (lo + Math.imul(al6, bl3)) | 0; + mid = (mid + Math.imul(al6, bh3)) | 0; + mid = (mid + Math.imul(ah6, bl3)) | 0; + hi = (hi + Math.imul(ah6, bh3)) | 0; + lo = (lo + Math.imul(al5, bl4)) | 0; + mid = (mid + Math.imul(al5, bh4)) | 0; + mid = (mid + Math.imul(ah5, bl4)) | 0; + hi = (hi + Math.imul(ah5, bh4)) | 0; + lo = (lo + Math.imul(al4, bl5)) | 0; + mid = (mid + Math.imul(al4, bh5)) | 0; + mid = (mid + Math.imul(ah4, bl5)) | 0; + hi = (hi + Math.imul(ah4, bh5)) | 0; + lo = (lo + Math.imul(al3, bl6)) | 0; + mid = (mid + Math.imul(al3, bh6)) | 0; + mid = (mid + Math.imul(ah3, bl6)) | 0; + hi = (hi + Math.imul(ah3, bh6)) | 0; + lo = (lo + Math.imul(al2, bl7)) | 0; + mid = (mid + Math.imul(al2, bh7)) | 0; + mid = (mid + Math.imul(ah2, bl7)) | 0; + hi = (hi + Math.imul(ah2, bh7)) | 0; + lo = (lo + Math.imul(al1, bl8)) | 0; + mid = (mid + Math.imul(al1, bh8)) | 0; + mid = (mid + Math.imul(ah1, bl8)) | 0; + hi = (hi + Math.imul(ah1, bh8)) | 0; + lo = (lo + Math.imul(al0, bl9)) | 0; + mid = (mid + Math.imul(al0, bh9)) | 0; + mid = (mid + Math.imul(ah0, bl9)) | 0; + hi = (hi + Math.imul(ah0, bh9)) | 0; + var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0; + w9 &= 0x3ffffff; + /* k = 10 */ + lo = Math.imul(al9, bl1); + mid = Math.imul(al9, bh1); + mid = (mid + Math.imul(ah9, bl1)) | 0; + hi = Math.imul(ah9, bh1); + lo = (lo + Math.imul(al8, bl2)) | 0; + mid = (mid + Math.imul(al8, bh2)) | 0; + mid = (mid + Math.imul(ah8, bl2)) | 0; + hi = (hi + Math.imul(ah8, bh2)) | 0; + lo = (lo + Math.imul(al7, bl3)) | 0; + mid = (mid + Math.imul(al7, bh3)) | 0; + mid = (mid + Math.imul(ah7, bl3)) | 0; + hi = (hi + Math.imul(ah7, bh3)) | 0; + lo = (lo + Math.imul(al6, bl4)) | 0; + mid = (mid + Math.imul(al6, bh4)) | 0; + mid = (mid + Math.imul(ah6, bl4)) | 0; + hi = (hi + Math.imul(ah6, bh4)) | 0; + lo = (lo + Math.imul(al5, bl5)) | 0; + mid = (mid + Math.imul(al5, bh5)) | 0; + mid = (mid + Math.imul(ah5, bl5)) | 0; + hi = (hi + Math.imul(ah5, bh5)) | 0; + lo = (lo + Math.imul(al4, bl6)) | 0; + mid = (mid + Math.imul(al4, bh6)) | 0; + mid = (mid + Math.imul(ah4, bl6)) | 0; + hi = (hi + Math.imul(ah4, bh6)) | 0; + lo = (lo + Math.imul(al3, bl7)) | 0; + mid = (mid + Math.imul(al3, bh7)) | 0; + mid = (mid + Math.imul(ah3, bl7)) | 0; + hi = (hi + Math.imul(ah3, bh7)) | 0; + lo = (lo + Math.imul(al2, bl8)) | 0; + mid = (mid + Math.imul(al2, bh8)) | 0; + mid = (mid + Math.imul(ah2, bl8)) | 0; + hi = (hi + Math.imul(ah2, bh8)) | 0; + lo = (lo + Math.imul(al1, bl9)) | 0; + mid = (mid + Math.imul(al1, bh9)) | 0; + mid = (mid + Math.imul(ah1, bl9)) | 0; + hi = (hi + Math.imul(ah1, bh9)) | 0; + var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0; + w10 &= 0x3ffffff; + /* k = 11 */ + lo = Math.imul(al9, bl2); + mid = Math.imul(al9, bh2); + mid = (mid + Math.imul(ah9, bl2)) | 0; + hi = Math.imul(ah9, bh2); + lo = (lo + Math.imul(al8, bl3)) | 0; + mid = (mid + Math.imul(al8, bh3)) | 0; + mid = (mid + Math.imul(ah8, bl3)) | 0; + hi = (hi + Math.imul(ah8, bh3)) | 0; + lo = (lo + Math.imul(al7, bl4)) | 0; + mid = (mid + Math.imul(al7, bh4)) | 0; + mid = (mid + Math.imul(ah7, bl4)) | 0; + hi = (hi + Math.imul(ah7, bh4)) | 0; + lo = (lo + Math.imul(al6, bl5)) | 0; + mid = (mid + Math.imul(al6, bh5)) | 0; + mid = (mid + Math.imul(ah6, bl5)) | 0; + hi = (hi + Math.imul(ah6, bh5)) | 0; + lo = (lo + Math.imul(al5, bl6)) | 0; + mid = (mid + Math.imul(al5, bh6)) | 0; + mid = (mid + Math.imul(ah5, bl6)) | 0; + hi = (hi + Math.imul(ah5, bh6)) | 0; + lo = (lo + Math.imul(al4, bl7)) | 0; + mid = (mid + Math.imul(al4, bh7)) | 0; + mid = (mid + Math.imul(ah4, bl7)) | 0; + hi = (hi + Math.imul(ah4, bh7)) | 0; + lo = (lo + Math.imul(al3, bl8)) | 0; + mid = (mid + Math.imul(al3, bh8)) | 0; + mid = (mid + Math.imul(ah3, bl8)) | 0; + hi = (hi + Math.imul(ah3, bh8)) | 0; + lo = (lo + Math.imul(al2, bl9)) | 0; + mid = (mid + Math.imul(al2, bh9)) | 0; + mid = (mid + Math.imul(ah2, bl9)) | 0; + hi = (hi + Math.imul(ah2, bh9)) | 0; + var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0; + w11 &= 0x3ffffff; + /* k = 12 */ + lo = Math.imul(al9, bl3); + mid = Math.imul(al9, bh3); + mid = (mid + Math.imul(ah9, bl3)) | 0; + hi = Math.imul(ah9, bh3); + lo = (lo + Math.imul(al8, bl4)) | 0; + mid = (mid + Math.imul(al8, bh4)) | 0; + mid = (mid + Math.imul(ah8, bl4)) | 0; + hi = (hi + Math.imul(ah8, bh4)) | 0; + lo = (lo + Math.imul(al7, bl5)) | 0; + mid = (mid + Math.imul(al7, bh5)) | 0; + mid = (mid + Math.imul(ah7, bl5)) | 0; + hi = (hi + Math.imul(ah7, bh5)) | 0; + lo = (lo + Math.imul(al6, bl6)) | 0; + mid = (mid + Math.imul(al6, bh6)) | 0; + mid = (mid + Math.imul(ah6, bl6)) | 0; + hi = (hi + Math.imul(ah6, bh6)) | 0; + lo = (lo + Math.imul(al5, bl7)) | 0; + mid = (mid + Math.imul(al5, bh7)) | 0; + mid = (mid + Math.imul(ah5, bl7)) | 0; + hi = (hi + Math.imul(ah5, bh7)) | 0; + lo = (lo + Math.imul(al4, bl8)) | 0; + mid = (mid + Math.imul(al4, bh8)) | 0; + mid = (mid + Math.imul(ah4, bl8)) | 0; + hi = (hi + Math.imul(ah4, bh8)) | 0; + lo = (lo + Math.imul(al3, bl9)) | 0; + mid = (mid + Math.imul(al3, bh9)) | 0; + mid = (mid + Math.imul(ah3, bl9)) | 0; + hi = (hi + Math.imul(ah3, bh9)) | 0; + var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0; + w12 &= 0x3ffffff; + /* k = 13 */ + lo = Math.imul(al9, bl4); + mid = Math.imul(al9, bh4); + mid = (mid + Math.imul(ah9, bl4)) | 0; + hi = Math.imul(ah9, bh4); + lo = (lo + Math.imul(al8, bl5)) | 0; + mid = (mid + Math.imul(al8, bh5)) | 0; + mid = (mid + Math.imul(ah8, bl5)) | 0; + hi = (hi + Math.imul(ah8, bh5)) | 0; + lo = (lo + Math.imul(al7, bl6)) | 0; + mid = (mid + Math.imul(al7, bh6)) | 0; + mid = (mid + Math.imul(ah7, bl6)) | 0; + hi = (hi + Math.imul(ah7, bh6)) | 0; + lo = (lo + Math.imul(al6, bl7)) | 0; + mid = (mid + Math.imul(al6, bh7)) | 0; + mid = (mid + Math.imul(ah6, bl7)) | 0; + hi = (hi + Math.imul(ah6, bh7)) | 0; + lo = (lo + Math.imul(al5, bl8)) | 0; + mid = (mid + Math.imul(al5, bh8)) | 0; + mid = (mid + Math.imul(ah5, bl8)) | 0; + hi = (hi + Math.imul(ah5, bh8)) | 0; + lo = (lo + Math.imul(al4, bl9)) | 0; + mid = (mid + Math.imul(al4, bh9)) | 0; + mid = (mid + Math.imul(ah4, bl9)) | 0; + hi = (hi + Math.imul(ah4, bh9)) | 0; + var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0; + w13 &= 0x3ffffff; + /* k = 14 */ + lo = Math.imul(al9, bl5); + mid = Math.imul(al9, bh5); + mid = (mid + Math.imul(ah9, bl5)) | 0; + hi = Math.imul(ah9, bh5); + lo = (lo + Math.imul(al8, bl6)) | 0; + mid = (mid + Math.imul(al8, bh6)) | 0; + mid = (mid + Math.imul(ah8, bl6)) | 0; + hi = (hi + Math.imul(ah8, bh6)) | 0; + lo = (lo + Math.imul(al7, bl7)) | 0; + mid = (mid + Math.imul(al7, bh7)) | 0; + mid = (mid + Math.imul(ah7, bl7)) | 0; + hi = (hi + Math.imul(ah7, bh7)) | 0; + lo = (lo + Math.imul(al6, bl8)) | 0; + mid = (mid + Math.imul(al6, bh8)) | 0; + mid = (mid + Math.imul(ah6, bl8)) | 0; + hi = (hi + Math.imul(ah6, bh8)) | 0; + lo = (lo + Math.imul(al5, bl9)) | 0; + mid = (mid + Math.imul(al5, bh9)) | 0; + mid = (mid + Math.imul(ah5, bl9)) | 0; + hi = (hi + Math.imul(ah5, bh9)) | 0; + var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0; + w14 &= 0x3ffffff; + /* k = 15 */ + lo = Math.imul(al9, bl6); + mid = Math.imul(al9, bh6); + mid = (mid + Math.imul(ah9, bl6)) | 0; + hi = Math.imul(ah9, bh6); + lo = (lo + Math.imul(al8, bl7)) | 0; + mid = (mid + Math.imul(al8, bh7)) | 0; + mid = (mid + Math.imul(ah8, bl7)) | 0; + hi = (hi + Math.imul(ah8, bh7)) | 0; + lo = (lo + Math.imul(al7, bl8)) | 0; + mid = (mid + Math.imul(al7, bh8)) | 0; + mid = (mid + Math.imul(ah7, bl8)) | 0; + hi = (hi + Math.imul(ah7, bh8)) | 0; + lo = (lo + Math.imul(al6, bl9)) | 0; + mid = (mid + Math.imul(al6, bh9)) | 0; + mid = (mid + Math.imul(ah6, bl9)) | 0; + hi = (hi + Math.imul(ah6, bh9)) | 0; + var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0; + w15 &= 0x3ffffff; + /* k = 16 */ + lo = Math.imul(al9, bl7); + mid = Math.imul(al9, bh7); + mid = (mid + Math.imul(ah9, bl7)) | 0; + hi = Math.imul(ah9, bh7); + lo = (lo + Math.imul(al8, bl8)) | 0; + mid = (mid + Math.imul(al8, bh8)) | 0; + mid = (mid + Math.imul(ah8, bl8)) | 0; + hi = (hi + Math.imul(ah8, bh8)) | 0; + lo = (lo + Math.imul(al7, bl9)) | 0; + mid = (mid + Math.imul(al7, bh9)) | 0; + mid = (mid + Math.imul(ah7, bl9)) | 0; + hi = (hi + Math.imul(ah7, bh9)) | 0; + var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0; + w16 &= 0x3ffffff; + /* k = 17 */ + lo = Math.imul(al9, bl8); + mid = Math.imul(al9, bh8); + mid = (mid + Math.imul(ah9, bl8)) | 0; + hi = Math.imul(ah9, bh8); + lo = (lo + Math.imul(al8, bl9)) | 0; + mid = (mid + Math.imul(al8, bh9)) | 0; + mid = (mid + Math.imul(ah8, bl9)) | 0; + hi = (hi + Math.imul(ah8, bh9)) | 0; + var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0; + w17 &= 0x3ffffff; + /* k = 18 */ + lo = Math.imul(al9, bl9); + mid = Math.imul(al9, bh9); + mid = (mid + Math.imul(ah9, bl9)) | 0; + hi = Math.imul(ah9, bh9); + var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0; + w18 &= 0x3ffffff; + o[0] = w0; + o[1] = w1; + o[2] = w2; + o[3] = w3; + o[4] = w4; + o[5] = w5; + o[6] = w6; + o[7] = w7; + o[8] = w8; + o[9] = w9; + o[10] = w10; + o[11] = w11; + o[12] = w12; + o[13] = w13; + o[14] = w14; + o[15] = w15; + o[16] = w16; + o[17] = w17; + o[18] = w18; + if (c !== 0) { + o[19] = c; + out.length++; + } + return out; + }; + + // Polyfill comb + if (!Math.imul) { + comb10MulTo = smallMulTo; + } + + function bigMulTo (self, num, out) { + out.negative = num.negative ^ self.negative; + out.length = self.length + num.length; + + var carry = 0; + var hncarry = 0; + for (var k = 0; k < out.length - 1; k++) { + // Sum all words with the same `i + j = k` and accumulate `ncarry`, + // note that ncarry could be >= 0x3ffffff + var ncarry = hncarry; + hncarry = 0; + var rword = carry & 0x3ffffff; + var maxJ = Math.min(k, num.length - 1); + for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { + var i = k - j; + var a = self.words[i] | 0; + var b = num.words[j] | 0; + var r = a * b; + + var lo = r & 0x3ffffff; + ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0; + lo = (lo + rword) | 0; + rword = lo & 0x3ffffff; + ncarry = (ncarry + (lo >>> 26)) | 0; + + hncarry += ncarry >>> 26; + ncarry &= 0x3ffffff; + } + out.words[k] = rword; + carry = ncarry; + ncarry = hncarry; + } + if (carry !== 0) { + out.words[k] = carry; + } else { + out.length--; + } + + return out.strip(); + } + + function jumboMulTo (self, num, out) { + var fftm = new FFTM(); + return fftm.mulp(self, num, out); + } + + BN.prototype.mulTo = function mulTo (num, out) { + var res; + var len = this.length + num.length; + if (this.length === 10 && num.length === 10) { + res = comb10MulTo(this, num, out); + } else if (len < 63) { + res = smallMulTo(this, num, out); + } else if (len < 1024) { + res = bigMulTo(this, num, out); + } else { + res = jumboMulTo(this, num, out); + } + + return res; + }; + + // Cooley-Tukey algorithm for FFT + // slightly revisited to rely on looping instead of recursion + + function FFTM (x, y) { + this.x = x; + this.y = y; + } + + FFTM.prototype.makeRBT = function makeRBT (N) { + var t = new Array(N); + var l = BN.prototype._countBits(N) - 1; + for (var i = 0; i < N; i++) { + t[i] = this.revBin(i, l, N); + } + + return t; + }; + + // Returns binary-reversed representation of `x` + FFTM.prototype.revBin = function revBin (x, l, N) { + if (x === 0 || x === N - 1) return x; + + var rb = 0; + for (var i = 0; i < l; i++) { + rb |= (x & 1) << (l - i - 1); + x >>= 1; + } + + return rb; + }; + + // Performs "tweedling" phase, therefore 'emulating' + // behaviour of the recursive algorithm + FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) { + for (var i = 0; i < N; i++) { + rtws[i] = rws[rbt[i]]; + itws[i] = iws[rbt[i]]; + } + }; + + FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) { + this.permute(rbt, rws, iws, rtws, itws, N); + + for (var s = 1; s < N; s <<= 1) { + var l = s << 1; + + var rtwdf = Math.cos(2 * Math.PI / l); + var itwdf = Math.sin(2 * Math.PI / l); + + for (var p = 0; p < N; p += l) { + var rtwdf_ = rtwdf; + var itwdf_ = itwdf; + + for (var j = 0; j < s; j++) { + var re = rtws[p + j]; + var ie = itws[p + j]; + + var ro = rtws[p + j + s]; + var io = itws[p + j + s]; + + var rx = rtwdf_ * ro - itwdf_ * io; + + io = rtwdf_ * io + itwdf_ * ro; + ro = rx; + + rtws[p + j] = re + ro; + itws[p + j] = ie + io; + + rtws[p + j + s] = re - ro; + itws[p + j + s] = ie - io; + + /* jshint maxdepth : false */ + if (j !== l) { + rx = rtwdf * rtwdf_ - itwdf * itwdf_; + + itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_; + rtwdf_ = rx; + } + } + } + } + }; + + FFTM.prototype.guessLen13b = function guessLen13b (n, m) { + var N = Math.max(m, n) | 1; + var odd = N & 1; + var i = 0; + for (N = N / 2 | 0; N; N = N >>> 1) { + i++; + } + + return 1 << i + 1 + odd; + }; + + FFTM.prototype.conjugate = function conjugate (rws, iws, N) { + if (N <= 1) return; + + for (var i = 0; i < N / 2; i++) { + var t = rws[i]; + + rws[i] = rws[N - i - 1]; + rws[N - i - 1] = t; + + t = iws[i]; + + iws[i] = -iws[N - i - 1]; + iws[N - i - 1] = -t; + } + }; + + FFTM.prototype.normalize13b = function normalize13b (ws, N) { + var carry = 0; + for (var i = 0; i < N / 2; i++) { + var w = Math.round(ws[2 * i + 1] / N) * 0x2000 + + Math.round(ws[2 * i] / N) + + carry; + + ws[i] = w & 0x3ffffff; + + if (w < 0x4000000) { + carry = 0; + } else { + carry = w / 0x4000000 | 0; + } + } + + return ws; + }; + + FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) { + var carry = 0; + for (var i = 0; i < len; i++) { + carry = carry + (ws[i] | 0); + + rws[2 * i] = carry & 0x1fff; carry = carry >>> 13; + rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13; + } + + // Pad with zeroes + for (i = 2 * len; i < N; ++i) { + rws[i] = 0; + } + + assert(carry === 0); + assert((carry & ~0x1fff) === 0); + }; + + FFTM.prototype.stub = function stub (N) { + var ph = new Array(N); + for (var i = 0; i < N; i++) { + ph[i] = 0; + } + + return ph; + }; + + FFTM.prototype.mulp = function mulp (x, y, out) { + var N = 2 * this.guessLen13b(x.length, y.length); + + var rbt = this.makeRBT(N); + + var _ = this.stub(N); + + var rws = new Array(N); + var rwst = new Array(N); + var iwst = new Array(N); + + var nrws = new Array(N); + var nrwst = new Array(N); + var niwst = new Array(N); + + var rmws = out.words; + rmws.length = N; + + this.convert13b(x.words, x.length, rws, N); + this.convert13b(y.words, y.length, nrws, N); + + this.transform(rws, _, rwst, iwst, N, rbt); + this.transform(nrws, _, nrwst, niwst, N, rbt); + + for (var i = 0; i < N; i++) { + var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i]; + iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i]; + rwst[i] = rx; + } + + this.conjugate(rwst, iwst, N); + this.transform(rwst, iwst, rmws, _, N, rbt); + this.conjugate(rmws, _, N); + this.normalize13b(rmws, N); + + out.negative = x.negative ^ y.negative; + out.length = x.length + y.length; + return out.strip(); + }; + + // Multiply `this` by `num` + BN.prototype.mul = function mul (num) { + var out = new BN(null); + out.words = new Array(this.length + num.length); + return this.mulTo(num, out); + }; + + // Multiply employing FFT + BN.prototype.mulf = function mulf (num) { + var out = new BN(null); + out.words = new Array(this.length + num.length); + return jumboMulTo(this, num, out); + }; + + // In-place Multiplication + BN.prototype.imul = function imul (num) { + return this.clone().mulTo(num, this); + }; + + BN.prototype.imuln = function imuln (num) { + assert(typeof num === 'number'); + assert(num < 0x4000000); + + // Carry + var carry = 0; + for (var i = 0; i < this.length; i++) { + var w = (this.words[i] | 0) * num; + var lo = (w & 0x3ffffff) + (carry & 0x3ffffff); + carry >>= 26; + carry += (w / 0x4000000) | 0; + // NOTE: lo is 27bit maximum + carry += lo >>> 26; + this.words[i] = lo & 0x3ffffff; + } + + if (carry !== 0) { + this.words[i] = carry; + this.length++; + } + + return this; + }; + + BN.prototype.muln = function muln (num) { + return this.clone().imuln(num); + }; + + // `this` * `this` + BN.prototype.sqr = function sqr () { + return this.mul(this); + }; + + // `this` * `this` in-place + BN.prototype.isqr = function isqr () { + return this.imul(this.clone()); + }; + + // Math.pow(`this`, `num`) + BN.prototype.pow = function pow (num) { + var w = toBitArray(num); + if (w.length === 0) return new BN(1); + + // Skip leading zeroes + var res = this; + for (var i = 0; i < w.length; i++, res = res.sqr()) { + if (w[i] !== 0) break; + } + + if (++i < w.length) { + for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) { + if (w[i] === 0) continue; + + res = res.mul(q); + } + } + + return res; + }; + + // Shift-left in-place + BN.prototype.iushln = function iushln (bits) { + assert(typeof bits === 'number' && bits >= 0); + var r = bits % 26; + var s = (bits - r) / 26; + var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r); + var i; + + if (r !== 0) { + var carry = 0; + + for (i = 0; i < this.length; i++) { + var newCarry = this.words[i] & carryMask; + var c = ((this.words[i] | 0) - newCarry) << r; + this.words[i] = c | carry; + carry = newCarry >>> (26 - r); + } + + if (carry) { + this.words[i] = carry; + this.length++; + } + } + + if (s !== 0) { + for (i = this.length - 1; i >= 0; i--) { + this.words[i + s] = this.words[i]; + } + + for (i = 0; i < s; i++) { + this.words[i] = 0; + } + + this.length += s; + } + + return this.strip(); + }; + + BN.prototype.ishln = function ishln (bits) { + // TODO(indutny): implement me + assert(this.negative === 0); + return this.iushln(bits); + }; + + // Shift-right in-place + // NOTE: `hint` is a lowest bit before trailing zeroes + // NOTE: if `extended` is present - it will be filled with destroyed bits + BN.prototype.iushrn = function iushrn (bits, hint, extended) { + assert(typeof bits === 'number' && bits >= 0); + var h; + if (hint) { + h = (hint - (hint % 26)) / 26; + } else { + h = 0; + } + + var r = bits % 26; + var s = Math.min((bits - r) / 26, this.length); + var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); + var maskedWords = extended; + + h -= s; + h = Math.max(0, h); + + // Extended mode, copy masked part + if (maskedWords) { + for (var i = 0; i < s; i++) { + maskedWords.words[i] = this.words[i]; + } + maskedWords.length = s; + } + + if (s === 0) { + // No-op, we should not move anything at all + } else if (this.length > s) { + this.length -= s; + for (i = 0; i < this.length; i++) { + this.words[i] = this.words[i + s]; + } + } else { + this.words[0] = 0; + this.length = 1; + } + + var carry = 0; + for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) { + var word = this.words[i] | 0; + this.words[i] = (carry << (26 - r)) | (word >>> r); + carry = word & mask; + } + + // Push carried bits as a mask + if (maskedWords && carry !== 0) { + maskedWords.words[maskedWords.length++] = carry; + } + + if (this.length === 0) { + this.words[0] = 0; + this.length = 1; + } + + return this.strip(); + }; + + BN.prototype.ishrn = function ishrn (bits, hint, extended) { + // TODO(indutny): implement me + assert(this.negative === 0); + return this.iushrn(bits, hint, extended); + }; + + // Shift-left + BN.prototype.shln = function shln (bits) { + return this.clone().ishln(bits); + }; + + BN.prototype.ushln = function ushln (bits) { + return this.clone().iushln(bits); + }; + + // Shift-right + BN.prototype.shrn = function shrn (bits) { + return this.clone().ishrn(bits); + }; + + BN.prototype.ushrn = function ushrn (bits) { + return this.clone().iushrn(bits); + }; + + // Test if n bit is set + BN.prototype.testn = function testn (bit) { + assert(typeof bit === 'number' && bit >= 0); + var r = bit % 26; + var s = (bit - r) / 26; + var q = 1 << r; + + // Fast case: bit is much higher than all existing words + if (this.length <= s) return false; + + // Check bit and return + var w = this.words[s]; + + return !!(w & q); + }; + + // Return only lowers bits of number (in-place) + BN.prototype.imaskn = function imaskn (bits) { + assert(typeof bits === 'number' && bits >= 0); + var r = bits % 26; + var s = (bits - r) / 26; + + assert(this.negative === 0, 'imaskn works only with positive numbers'); + + if (this.length <= s) { + return this; + } + + if (r !== 0) { + s++; + } + this.length = Math.min(s, this.length); + + if (r !== 0) { + var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); + this.words[this.length - 1] &= mask; + } + + return this.strip(); + }; + + // Return only lowers bits of number + BN.prototype.maskn = function maskn (bits) { + return this.clone().imaskn(bits); + }; + + // Add plain number `num` to `this` + BN.prototype.iaddn = function iaddn (num) { + assert(typeof num === 'number'); + assert(num < 0x4000000); + if (num < 0) return this.isubn(-num); + + // Possible sign change + if (this.negative !== 0) { + if (this.length === 1 && (this.words[0] | 0) < num) { + this.words[0] = num - (this.words[0] | 0); + this.negative = 0; + return this; + } + + this.negative = 0; + this.isubn(num); + this.negative = 1; + return this; + } + + // Add without checks + return this._iaddn(num); + }; + + BN.prototype._iaddn = function _iaddn (num) { + this.words[0] += num; + + // Carry + for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) { + this.words[i] -= 0x4000000; + if (i === this.length - 1) { + this.words[i + 1] = 1; + } else { + this.words[i + 1]++; + } + } + this.length = Math.max(this.length, i + 1); + + return this; + }; + + // Subtract plain number `num` from `this` + BN.prototype.isubn = function isubn (num) { + assert(typeof num === 'number'); + assert(num < 0x4000000); + if (num < 0) return this.iaddn(-num); + + if (this.negative !== 0) { + this.negative = 0; + this.iaddn(num); + this.negative = 1; + return this; + } + + this.words[0] -= num; + + if (this.length === 1 && this.words[0] < 0) { + this.words[0] = -this.words[0]; + this.negative = 1; + } else { + // Carry + for (var i = 0; i < this.length && this.words[i] < 0; i++) { + this.words[i] += 0x4000000; + this.words[i + 1] -= 1; + } + } + + return this.strip(); + }; + + BN.prototype.addn = function addn (num) { + return this.clone().iaddn(num); + }; + + BN.prototype.subn = function subn (num) { + return this.clone().isubn(num); + }; + + BN.prototype.iabs = function iabs () { + this.negative = 0; + + return this; + }; + + BN.prototype.abs = function abs () { + return this.clone().iabs(); + }; + + BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) { + var len = num.length + shift; + var i; + + this._expand(len); + + var w; + var carry = 0; + for (i = 0; i < num.length; i++) { + w = (this.words[i + shift] | 0) + carry; + var right = (num.words[i] | 0) * mul; + w -= right & 0x3ffffff; + carry = (w >> 26) - ((right / 0x4000000) | 0); + this.words[i + shift] = w & 0x3ffffff; + } + for (; i < this.length - shift; i++) { + w = (this.words[i + shift] | 0) + carry; + carry = w >> 26; + this.words[i + shift] = w & 0x3ffffff; + } + + if (carry === 0) return this.strip(); + + // Subtraction overflow + assert(carry === -1); + carry = 0; + for (i = 0; i < this.length; i++) { + w = -(this.words[i] | 0) + carry; + carry = w >> 26; + this.words[i] = w & 0x3ffffff; + } + this.negative = 1; + + return this.strip(); + }; + + BN.prototype._wordDiv = function _wordDiv (num, mode) { + var shift = this.length - num.length; + + var a = this.clone(); + var b = num; + + // Normalize + var bhi = b.words[b.length - 1] | 0; + var bhiBits = this._countBits(bhi); + shift = 26 - bhiBits; + if (shift !== 0) { + b = b.ushln(shift); + a.iushln(shift); + bhi = b.words[b.length - 1] | 0; + } + + // Initialize quotient + var m = a.length - b.length; + var q; + + if (mode !== 'mod') { + q = new BN(null); + q.length = m + 1; + q.words = new Array(q.length); + for (var i = 0; i < q.length; i++) { + q.words[i] = 0; + } + } + + var diff = a.clone()._ishlnsubmul(b, 1, m); + if (diff.negative === 0) { + a = diff; + if (q) { + q.words[m] = 1; + } + } + + for (var j = m - 1; j >= 0; j--) { + var qj = (a.words[b.length + j] | 0) * 0x4000000 + + (a.words[b.length + j - 1] | 0); + + // NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max + // (0x7ffffff) + qj = Math.min((qj / bhi) | 0, 0x3ffffff); + + a._ishlnsubmul(b, qj, j); + while (a.negative !== 0) { + qj--; + a.negative = 0; + a._ishlnsubmul(b, 1, j); + if (!a.isZero()) { + a.negative ^= 1; + } + } + if (q) { + q.words[j] = qj; + } + } + if (q) { + q.strip(); + } + a.strip(); + + // Denormalize + if (mode !== 'div' && shift !== 0) { + a.iushrn(shift); + } + + return { + div: q || null, + mod: a + }; + }; + + // NOTE: 1) `mode` can be set to `mod` to request mod only, + // to `div` to request div only, or be absent to + // request both div & mod + // 2) `positive` is true if unsigned mod is requested + BN.prototype.divmod = function divmod (num, mode, positive) { + assert(!num.isZero()); + + if (this.isZero()) { + return { + div: new BN(0), + mod: new BN(0) + }; + } + + var div, mod, res; + if (this.negative !== 0 && num.negative === 0) { + res = this.neg().divmod(num, mode); + + if (mode !== 'mod') { + div = res.div.neg(); + } + + if (mode !== 'div') { + mod = res.mod.neg(); + if (positive && mod.negative !== 0) { + mod.iadd(num); + } + } + + return { + div: div, + mod: mod + }; + } + + if (this.negative === 0 && num.negative !== 0) { + res = this.divmod(num.neg(), mode); + + if (mode !== 'mod') { + div = res.div.neg(); + } + + return { + div: div, + mod: res.mod + }; + } + + if ((this.negative & num.negative) !== 0) { + res = this.neg().divmod(num.neg(), mode); + + if (mode !== 'div') { + mod = res.mod.neg(); + if (positive && mod.negative !== 0) { + mod.isub(num); + } + } + + return { + div: res.div, + mod: mod + }; + } + + // Both numbers are positive at this point + + // Strip both numbers to approximate shift value + if (num.length > this.length || this.cmp(num) < 0) { + return { + div: new BN(0), + mod: this + }; + } + + // Very short reduction + if (num.length === 1) { + if (mode === 'div') { + return { + div: this.divn(num.words[0]), + mod: null + }; + } + + if (mode === 'mod') { + return { + div: null, + mod: new BN(this.modn(num.words[0])) + }; + } + + return { + div: this.divn(num.words[0]), + mod: new BN(this.modn(num.words[0])) + }; + } + + return this._wordDiv(num, mode); + }; + + // Find `this` / `num` + BN.prototype.div = function div (num) { + return this.divmod(num, 'div', false).div; + }; + + // Find `this` % `num` + BN.prototype.mod = function mod (num) { + return this.divmod(num, 'mod', false).mod; + }; + + BN.prototype.umod = function umod (num) { + return this.divmod(num, 'mod', true).mod; + }; + + // Find Round(`this` / `num`) + BN.prototype.divRound = function divRound (num) { + var dm = this.divmod(num); + + // Fast case - exact division + if (dm.mod.isZero()) return dm.div; + + var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod; + + var half = num.ushrn(1); + var r2 = num.andln(1); + var cmp = mod.cmp(half); + + // Round down + if (cmp < 0 || r2 === 1 && cmp === 0) return dm.div; + + // Round up + return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1); + }; + + BN.prototype.modn = function modn (num) { + assert(num <= 0x3ffffff); + var p = (1 << 26) % num; + + var acc = 0; + for (var i = this.length - 1; i >= 0; i--) { + acc = (p * acc + (this.words[i] | 0)) % num; + } + + return acc; + }; + + // In-place division by number + BN.prototype.idivn = function idivn (num) { + assert(num <= 0x3ffffff); + + var carry = 0; + for (var i = this.length - 1; i >= 0; i--) { + var w = (this.words[i] | 0) + carry * 0x4000000; + this.words[i] = (w / num) | 0; + carry = w % num; + } + + return this.strip(); + }; + + BN.prototype.divn = function divn (num) { + return this.clone().idivn(num); + }; + + BN.prototype.egcd = function egcd (p) { + assert(p.negative === 0); + assert(!p.isZero()); + + var x = this; + var y = p.clone(); + + if (x.negative !== 0) { + x = x.umod(p); + } else { + x = x.clone(); + } + + // A * x + B * y = x + var A = new BN(1); + var B = new BN(0); + + // C * x + D * y = y + var C = new BN(0); + var D = new BN(1); + + var g = 0; + + while (x.isEven() && y.isEven()) { + x.iushrn(1); + y.iushrn(1); + ++g; + } + + var yp = y.clone(); + var xp = x.clone(); + + while (!x.isZero()) { + for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1); + if (i > 0) { + x.iushrn(i); + while (i-- > 0) { + if (A.isOdd() || B.isOdd()) { + A.iadd(yp); + B.isub(xp); + } + + A.iushrn(1); + B.iushrn(1); + } + } + + for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); + if (j > 0) { + y.iushrn(j); + while (j-- > 0) { + if (C.isOdd() || D.isOdd()) { + C.iadd(yp); + D.isub(xp); + } + + C.iushrn(1); + D.iushrn(1); + } + } + + if (x.cmp(y) >= 0) { + x.isub(y); + A.isub(C); + B.isub(D); + } else { + y.isub(x); + C.isub(A); + D.isub(B); + } + } + + return { + a: C, + b: D, + gcd: y.iushln(g) + }; + }; + + // This is reduced incarnation of the binary EEA + // above, designated to invert members of the + // _prime_ fields F(p) at a maximal speed + BN.prototype._invmp = function _invmp (p) { + assert(p.negative === 0); + assert(!p.isZero()); + + var a = this; + var b = p.clone(); + + if (a.negative !== 0) { + a = a.umod(p); + } else { + a = a.clone(); + } + + var x1 = new BN(1); + var x2 = new BN(0); + + var delta = b.clone(); + + while (a.cmpn(1) > 0 && b.cmpn(1) > 0) { + for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1); + if (i > 0) { + a.iushrn(i); + while (i-- > 0) { + if (x1.isOdd()) { + x1.iadd(delta); + } + + x1.iushrn(1); + } + } + + for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); + if (j > 0) { + b.iushrn(j); + while (j-- > 0) { + if (x2.isOdd()) { + x2.iadd(delta); + } + + x2.iushrn(1); + } + } + + if (a.cmp(b) >= 0) { + a.isub(b); + x1.isub(x2); + } else { + b.isub(a); + x2.isub(x1); + } + } + + var res; + if (a.cmpn(1) === 0) { + res = x1; + } else { + res = x2; + } + + if (res.cmpn(0) < 0) { + res.iadd(p); + } + + return res; + }; + + BN.prototype.gcd = function gcd (num) { + if (this.isZero()) return num.abs(); + if (num.isZero()) return this.abs(); + + var a = this.clone(); + var b = num.clone(); + a.negative = 0; + b.negative = 0; + + // Remove common factor of two + for (var shift = 0; a.isEven() && b.isEven(); shift++) { + a.iushrn(1); + b.iushrn(1); + } + + do { + while (a.isEven()) { + a.iushrn(1); + } + while (b.isEven()) { + b.iushrn(1); + } + + var r = a.cmp(b); + if (r < 0) { + // Swap `a` and `b` to make `a` always bigger than `b` + var t = a; + a = b; + b = t; + } else if (r === 0 || b.cmpn(1) === 0) { + break; + } + + a.isub(b); + } while (true); + + return b.iushln(shift); + }; + + // Invert number in the field F(num) + BN.prototype.invm = function invm (num) { + return this.egcd(num).a.umod(num); + }; + + BN.prototype.isEven = function isEven () { + return (this.words[0] & 1) === 0; + }; + + BN.prototype.isOdd = function isOdd () { + return (this.words[0] & 1) === 1; + }; + + // And first word and num + BN.prototype.andln = function andln (num) { + return this.words[0] & num; + }; + + // Increment at the bit position in-line + BN.prototype.bincn = function bincn (bit) { + assert(typeof bit === 'number'); + var r = bit % 26; + var s = (bit - r) / 26; + var q = 1 << r; + + // Fast case: bit is much higher than all existing words + if (this.length <= s) { + this._expand(s + 1); + this.words[s] |= q; + return this; + } + + // Add bit and propagate, if needed + var carry = q; + for (var i = s; carry !== 0 && i < this.length; i++) { + var w = this.words[i] | 0; + w += carry; + carry = w >>> 26; + w &= 0x3ffffff; + this.words[i] = w; + } + if (carry !== 0) { + this.words[i] = carry; + this.length++; + } + return this; + }; + + BN.prototype.isZero = function isZero () { + return this.length === 1 && this.words[0] === 0; + }; + + BN.prototype.cmpn = function cmpn (num) { + var negative = num < 0; + + if (this.negative !== 0 && !negative) return -1; + if (this.negative === 0 && negative) return 1; + + this.strip(); + + var res; + if (this.length > 1) { + res = 1; + } else { + if (negative) { + num = -num; + } + + assert(num <= 0x3ffffff, 'Number is too big'); + + var w = this.words[0] | 0; + res = w === num ? 0 : w < num ? -1 : 1; + } + if (this.negative !== 0) return -res | 0; + return res; + }; + + // Compare two numbers and return: + // 1 - if `this` > `num` + // 0 - if `this` == `num` + // -1 - if `this` < `num` + BN.prototype.cmp = function cmp (num) { + if (this.negative !== 0 && num.negative === 0) return -1; + if (this.negative === 0 && num.negative !== 0) return 1; + + var res = this.ucmp(num); + if (this.negative !== 0) return -res | 0; + return res; + }; + + // Unsigned comparison + BN.prototype.ucmp = function ucmp (num) { + // At this point both numbers have the same sign + if (this.length > num.length) return 1; + if (this.length < num.length) return -1; + + var res = 0; + for (var i = this.length - 1; i >= 0; i--) { + var a = this.words[i] | 0; + var b = num.words[i] | 0; + + if (a === b) continue; + if (a < b) { + res = -1; + } else if (a > b) { + res = 1; + } + break; + } + return res; + }; + + BN.prototype.gtn = function gtn (num) { + return this.cmpn(num) === 1; + }; + + BN.prototype.gt = function gt (num) { + return this.cmp(num) === 1; + }; + + BN.prototype.gten = function gten (num) { + return this.cmpn(num) >= 0; + }; + + BN.prototype.gte = function gte (num) { + return this.cmp(num) >= 0; + }; + + BN.prototype.ltn = function ltn (num) { + return this.cmpn(num) === -1; + }; + + BN.prototype.lt = function lt (num) { + return this.cmp(num) === -1; + }; + + BN.prototype.lten = function lten (num) { + return this.cmpn(num) <= 0; + }; + + BN.prototype.lte = function lte (num) { + return this.cmp(num) <= 0; + }; + + BN.prototype.eqn = function eqn (num) { + return this.cmpn(num) === 0; + }; + + BN.prototype.eq = function eq (num) { + return this.cmp(num) === 0; + }; + + // + // A reduce context, could be using montgomery or something better, depending + // on the `m` itself. + // + BN.red = function red (num) { + return new Red(num); + }; + + BN.prototype.toRed = function toRed (ctx) { + assert(!this.red, 'Already a number in reduction context'); + assert(this.negative === 0, 'red works only with positives'); + return ctx.convertTo(this)._forceRed(ctx); + }; + + BN.prototype.fromRed = function fromRed () { + assert(this.red, 'fromRed works only with numbers in reduction context'); + return this.red.convertFrom(this); + }; + + BN.prototype._forceRed = function _forceRed (ctx) { + this.red = ctx; + return this; + }; + + BN.prototype.forceRed = function forceRed (ctx) { + assert(!this.red, 'Already a number in reduction context'); + return this._forceRed(ctx); + }; + + BN.prototype.redAdd = function redAdd (num) { + assert(this.red, 'redAdd works only with red numbers'); + return this.red.add(this, num); + }; + + BN.prototype.redIAdd = function redIAdd (num) { + assert(this.red, 'redIAdd works only with red numbers'); + return this.red.iadd(this, num); + }; + + BN.prototype.redSub = function redSub (num) { + assert(this.red, 'redSub works only with red numbers'); + return this.red.sub(this, num); + }; + + BN.prototype.redISub = function redISub (num) { + assert(this.red, 'redISub works only with red numbers'); + return this.red.isub(this, num); + }; + + BN.prototype.redShl = function redShl (num) { + assert(this.red, 'redShl works only with red numbers'); + return this.red.shl(this, num); + }; + + BN.prototype.redMul = function redMul (num) { + assert(this.red, 'redMul works only with red numbers'); + this.red._verify2(this, num); + return this.red.mul(this, num); + }; + + BN.prototype.redIMul = function redIMul (num) { + assert(this.red, 'redMul works only with red numbers'); + this.red._verify2(this, num); + return this.red.imul(this, num); + }; + + BN.prototype.redSqr = function redSqr () { + assert(this.red, 'redSqr works only with red numbers'); + this.red._verify1(this); + return this.red.sqr(this); + }; + + BN.prototype.redISqr = function redISqr () { + assert(this.red, 'redISqr works only with red numbers'); + this.red._verify1(this); + return this.red.isqr(this); + }; + + // Square root over p + BN.prototype.redSqrt = function redSqrt () { + assert(this.red, 'redSqrt works only with red numbers'); + this.red._verify1(this); + return this.red.sqrt(this); + }; + + BN.prototype.redInvm = function redInvm () { + assert(this.red, 'redInvm works only with red numbers'); + this.red._verify1(this); + return this.red.invm(this); + }; + + // Return negative clone of `this` % `red modulo` + BN.prototype.redNeg = function redNeg () { + assert(this.red, 'redNeg works only with red numbers'); + this.red._verify1(this); + return this.red.neg(this); + }; + + BN.prototype.redPow = function redPow (num) { + assert(this.red && !num.red, 'redPow(normalNum)'); + this.red._verify1(this); + return this.red.pow(this, num); + }; + + // Prime numbers with efficient reduction + var primes = { + k256: null, + p224: null, + p192: null, + p25519: null + }; + + // Pseudo-Mersenne prime + function MPrime (name, p) { + // P = 2 ^ N - K + this.name = name; + this.p = new BN(p, 16); + this.n = this.p.bitLength(); + this.k = new BN(1).iushln(this.n).isub(this.p); + + this.tmp = this._tmp(); + } + + MPrime.prototype._tmp = function _tmp () { + var tmp = new BN(null); + tmp.words = new Array(Math.ceil(this.n / 13)); + return tmp; + }; + + MPrime.prototype.ireduce = function ireduce (num) { + // Assumes that `num` is less than `P^2` + // num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P) + var r = num; + var rlen; + + do { + this.split(r, this.tmp); + r = this.imulK(r); + r = r.iadd(this.tmp); + rlen = r.bitLength(); + } while (rlen > this.n); + + var cmp = rlen < this.n ? -1 : r.ucmp(this.p); + if (cmp === 0) { + r.words[0] = 0; + r.length = 1; + } else if (cmp > 0) { + r.isub(this.p); + } else { + r.strip(); + } + + return r; + }; + + MPrime.prototype.split = function split (input, out) { + input.iushrn(this.n, 0, out); + }; + + MPrime.prototype.imulK = function imulK (num) { + return num.imul(this.k); + }; + + function K256 () { + MPrime.call( + this, + 'k256', + 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f'); + } + inherits(K256, MPrime); + + K256.prototype.split = function split (input, output) { + // 256 = 9 * 26 + 22 + var mask = 0x3fffff; + + var outLen = Math.min(input.length, 9); + for (var i = 0; i < outLen; i++) { + output.words[i] = input.words[i]; + } + output.length = outLen; + + if (input.length <= 9) { + input.words[0] = 0; + input.length = 1; + return; + } + + // Shift by 9 limbs + var prev = input.words[9]; + output.words[output.length++] = prev & mask; + + for (i = 10; i < input.length; i++) { + var next = input.words[i] | 0; + input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22); + prev = next; + } + prev >>>= 22; + input.words[i - 10] = prev; + if (prev === 0 && input.length > 10) { + input.length -= 10; + } else { + input.length -= 9; + } + }; + + K256.prototype.imulK = function imulK (num) { + // K = 0x1000003d1 = [ 0x40, 0x3d1 ] + num.words[num.length] = 0; + num.words[num.length + 1] = 0; + num.length += 2; + + // bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390 + var lo = 0; + for (var i = 0; i < num.length; i++) { + var w = num.words[i] | 0; + lo += w * 0x3d1; + num.words[i] = lo & 0x3ffffff; + lo = w * 0x40 + ((lo / 0x4000000) | 0); + } + + // Fast length reduction + if (num.words[num.length - 1] === 0) { + num.length--; + if (num.words[num.length - 1] === 0) { + num.length--; + } + } + return num; + }; + + function P224 () { + MPrime.call( + this, + 'p224', + 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001'); + } + inherits(P224, MPrime); + + function P192 () { + MPrime.call( + this, + 'p192', + 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff'); + } + inherits(P192, MPrime); + + function P25519 () { + // 2 ^ 255 - 19 + MPrime.call( + this, + '25519', + '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed'); + } + inherits(P25519, MPrime); + + P25519.prototype.imulK = function imulK (num) { + // K = 0x13 + var carry = 0; + for (var i = 0; i < num.length; i++) { + var hi = (num.words[i] | 0) * 0x13 + carry; + var lo = hi & 0x3ffffff; + hi >>>= 26; + + num.words[i] = lo; + carry = hi; + } + if (carry !== 0) { + num.words[num.length++] = carry; + } + return num; + }; + + // Exported mostly for testing purposes, use plain name instead + BN._prime = function prime (name) { + // Cached version of prime + if (primes[name]) return primes[name]; + + var prime; + if (name === 'k256') { + prime = new K256(); + } else if (name === 'p224') { + prime = new P224(); + } else if (name === 'p192') { + prime = new P192(); + } else if (name === 'p25519') { + prime = new P25519(); + } else { + throw new Error('Unknown prime ' + name); + } + primes[name] = prime; + + return prime; + }; + + // + // Base reduction engine + // + function Red (m) { + if (typeof m === 'string') { + var prime = BN._prime(m); + this.m = prime.p; + this.prime = prime; + } else { + assert(m.gtn(1), 'modulus must be greater than 1'); + this.m = m; + this.prime = null; + } + } + + Red.prototype._verify1 = function _verify1 (a) { + assert(a.negative === 0, 'red works only with positives'); + assert(a.red, 'red works only with red numbers'); + }; + + Red.prototype._verify2 = function _verify2 (a, b) { + assert((a.negative | b.negative) === 0, 'red works only with positives'); + assert(a.red && a.red === b.red, + 'red works only with red numbers'); + }; + + Red.prototype.imod = function imod (a) { + if (this.prime) return this.prime.ireduce(a)._forceRed(this); + return a.umod(this.m)._forceRed(this); + }; + + Red.prototype.neg = function neg (a) { + if (a.isZero()) { + return a.clone(); + } + + return this.m.sub(a)._forceRed(this); + }; + + Red.prototype.add = function add (a, b) { + this._verify2(a, b); + + var res = a.add(b); + if (res.cmp(this.m) >= 0) { + res.isub(this.m); + } + return res._forceRed(this); + }; + + Red.prototype.iadd = function iadd (a, b) { + this._verify2(a, b); + + var res = a.iadd(b); + if (res.cmp(this.m) >= 0) { + res.isub(this.m); + } + return res; + }; + + Red.prototype.sub = function sub (a, b) { + this._verify2(a, b); + + var res = a.sub(b); + if (res.cmpn(0) < 0) { + res.iadd(this.m); + } + return res._forceRed(this); + }; + + Red.prototype.isub = function isub (a, b) { + this._verify2(a, b); + + var res = a.isub(b); + if (res.cmpn(0) < 0) { + res.iadd(this.m); + } + return res; + }; + + Red.prototype.shl = function shl (a, num) { + this._verify1(a); + return this.imod(a.ushln(num)); + }; + + Red.prototype.imul = function imul (a, b) { + this._verify2(a, b); + return this.imod(a.imul(b)); + }; + + Red.prototype.mul = function mul (a, b) { + this._verify2(a, b); + return this.imod(a.mul(b)); + }; + + Red.prototype.isqr = function isqr (a) { + return this.imul(a, a.clone()); + }; + + Red.prototype.sqr = function sqr (a) { + return this.mul(a, a); + }; + + Red.prototype.sqrt = function sqrt (a) { + if (a.isZero()) return a.clone(); + + var mod3 = this.m.andln(3); + assert(mod3 % 2 === 1); + + // Fast case + if (mod3 === 3) { + var pow = this.m.add(new BN(1)).iushrn(2); + return this.pow(a, pow); + } + + // Tonelli-Shanks algorithm (Totally unoptimized and slow) + // + // Find Q and S, that Q * 2 ^ S = (P - 1) + var q = this.m.subn(1); + var s = 0; + while (!q.isZero() && q.andln(1) === 0) { + s++; + q.iushrn(1); + } + assert(!q.isZero()); + + var one = new BN(1).toRed(this); + var nOne = one.redNeg(); + + // Find quadratic non-residue + // NOTE: Max is such because of generalized Riemann hypothesis. + var lpow = this.m.subn(1).iushrn(1); + var z = this.m.bitLength(); + z = new BN(2 * z * z).toRed(this); + + while (this.pow(z, lpow).cmp(nOne) !== 0) { + z.redIAdd(nOne); + } + + var c = this.pow(z, q); + var r = this.pow(a, q.addn(1).iushrn(1)); + var t = this.pow(a, q); + var m = s; + while (t.cmp(one) !== 0) { + var tmp = t; + for (var i = 0; tmp.cmp(one) !== 0; i++) { + tmp = tmp.redSqr(); + } + assert(i < m); + var b = this.pow(c, new BN(1).iushln(m - i - 1)); + + r = r.redMul(b); + c = b.redSqr(); + t = t.redMul(c); + m = i; + } + + return r; + }; + + Red.prototype.invm = function invm (a) { + var inv = a._invmp(this.m); + if (inv.negative !== 0) { + inv.negative = 0; + return this.imod(inv).redNeg(); + } else { + return this.imod(inv); + } + }; + + Red.prototype.pow = function pow (a, num) { + if (num.isZero()) return new BN(1).toRed(this); + if (num.cmpn(1) === 0) return a.clone(); + + var windowSize = 4; + var wnd = new Array(1 << windowSize); + wnd[0] = new BN(1).toRed(this); + wnd[1] = a; + for (var i = 2; i < wnd.length; i++) { + wnd[i] = this.mul(wnd[i - 1], a); + } + + var res = wnd[0]; + var current = 0; + var currentLen = 0; + var start = num.bitLength() % 26; + if (start === 0) { + start = 26; + } + + for (i = num.length - 1; i >= 0; i--) { + var word = num.words[i]; + for (var j = start - 1; j >= 0; j--) { + var bit = (word >> j) & 1; + if (res !== wnd[0]) { + res = this.sqr(res); + } + + if (bit === 0 && current === 0) { + currentLen = 0; + continue; + } + + current <<= 1; + current |= bit; + currentLen++; + if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue; + + res = this.mul(res, wnd[current]); + currentLen = 0; + current = 0; + } + start = 26; + } + + return res; + }; + + Red.prototype.convertTo = function convertTo (num) { + var r = num.umod(this.m); + + return r === num ? r.clone() : r; + }; + + Red.prototype.convertFrom = function convertFrom (num) { + var res = num.clone(); + res.red = null; + return res; + }; + + // + // Montgomery method engine + // + + BN.mont = function mont (num) { + return new Mont(num); + }; + + function Mont (m) { + Red.call(this, m); + + this.shift = this.m.bitLength(); + if (this.shift % 26 !== 0) { + this.shift += 26 - (this.shift % 26); + } + + this.r = new BN(1).iushln(this.shift); + this.r2 = this.imod(this.r.sqr()); + this.rinv = this.r._invmp(this.m); + + this.minv = this.rinv.mul(this.r).isubn(1).div(this.m); + this.minv = this.minv.umod(this.r); + this.minv = this.r.sub(this.minv); + } + inherits(Mont, Red); + + Mont.prototype.convertTo = function convertTo (num) { + return this.imod(num.ushln(this.shift)); + }; + + Mont.prototype.convertFrom = function convertFrom (num) { + var r = this.imod(num.mul(this.rinv)); + r.red = null; + return r; + }; + + Mont.prototype.imul = function imul (a, b) { + if (a.isZero() || b.isZero()) { + a.words[0] = 0; + a.length = 1; + return a; + } + + var t = a.imul(b); + var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); + var u = t.isub(c).iushrn(this.shift); + var res = u; + + if (u.cmp(this.m) >= 0) { + res = u.isub(this.m); + } else if (u.cmpn(0) < 0) { + res = u.iadd(this.m); + } + + return res._forceRed(this); + }; + + Mont.prototype.mul = function mul (a, b) { + if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this); + + var t = a.mul(b); + var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); + var u = t.isub(c).iushrn(this.shift); + var res = u; + if (u.cmp(this.m) >= 0) { + res = u.isub(this.m); + } else if (u.cmpn(0) < 0) { + res = u.iadd(this.m); + } + + return res._forceRed(this); + }; + + Mont.prototype.invm = function invm (a) { + // (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R + var res = this.imod(a._invmp(this.m).mul(this.r2)); + return res._forceRed(this); + }; +})(typeof module === 'undefined' || module, this); + +},{"buffer":"buffer"}],17:[function(require,module,exports){ +var r; + +module.exports = function rand(len) { + if (!r) + r = new Rand(null); + + return r.generate(len); +}; + +function Rand(rand) { + this.rand = rand; +} +module.exports.Rand = Rand; + +Rand.prototype.generate = function generate(len) { + return this._rand(len); +}; + +// Emulate crypto API using randy +Rand.prototype._rand = function _rand(n) { + if (this.rand.getBytes) + return this.rand.getBytes(n); + + var res = new Uint8Array(n); + for (var i = 0; i < res.length; i++) + res[i] = this.rand.getByte(); + return res; +}; + +if (typeof self === 'object') { + if (self.crypto && self.crypto.getRandomValues) { + // Modern browsers + Rand.prototype._rand = function _rand(n) { + var arr = new Uint8Array(n); + self.crypto.getRandomValues(arr); + return arr; + }; + } else if (self.msCrypto && self.msCrypto.getRandomValues) { + // IE + Rand.prototype._rand = function _rand(n) { + var arr = new Uint8Array(n); + self.msCrypto.getRandomValues(arr); + return arr; + }; + + // Safari's WebWorkers do not have `crypto` + } else if (typeof window === 'object') { + // Old junk + Rand.prototype._rand = function() { + throw new Error('Not implemented yet'); + }; + } +} else { + // Node.js or Web worker with no crypto support + try { + var crypto = require('crypto'); + if (typeof crypto.randomBytes !== 'function') + throw new Error('Not supported'); + + Rand.prototype._rand = function _rand(n) { + return crypto.randomBytes(n); + }; + } catch (e) { + } +} + +},{"crypto":"crypto"}],18:[function(require,module,exports){ +'use strict'; + +var elliptic = exports; + +elliptic.utils = require('./elliptic/utils'); +elliptic.rand = require('brorand'); +elliptic.curve = require('./elliptic/curve'); +elliptic.curves = require('./elliptic/curves'); + +// Protocols +elliptic.ec = require('./elliptic/ec'); +elliptic.eddsa = require('./elliptic/eddsa'); + +},{"./elliptic/curve":21,"./elliptic/curves":24,"./elliptic/ec":25,"./elliptic/eddsa":28,"./elliptic/utils":32,"brorand":17}],19:[function(require,module,exports){ +'use strict'; + +var BN = require('bn.js'); +var elliptic = require('../../elliptic'); +var utils = elliptic.utils; +var getNAF = utils.getNAF; +var getJSF = utils.getJSF; +var assert = utils.assert; + +function BaseCurve(type, conf) { + this.type = type; + this.p = new BN(conf.p, 16); + + // Use Montgomery, when there is no fast reduction for the prime + this.red = conf.prime ? BN.red(conf.prime) : BN.mont(this.p); + + // Useful for many curves + this.zero = new BN(0).toRed(this.red); + this.one = new BN(1).toRed(this.red); + this.two = new BN(2).toRed(this.red); + + // Curve configuration, optional + this.n = conf.n && new BN(conf.n, 16); + this.g = conf.g && this.pointFromJSON(conf.g, conf.gRed); + + // Temporary arrays + this._wnafT1 = new Array(4); + this._wnafT2 = new Array(4); + this._wnafT3 = new Array(4); + this._wnafT4 = new Array(4); + + // Generalized Greg Maxwell's trick + var adjustCount = this.n && this.p.div(this.n); + if (!adjustCount || adjustCount.cmpn(100) > 0) { + this.redN = null; + } else { + this._maxwellTrick = true; + this.redN = this.n.toRed(this.red); + } +} +module.exports = BaseCurve; + +BaseCurve.prototype.point = function point() { + throw new Error('Not implemented'); +}; + +BaseCurve.prototype.validate = function validate() { + throw new Error('Not implemented'); +}; + +BaseCurve.prototype._fixedNafMul = function _fixedNafMul(p, k) { + assert(p.precomputed); + var doubles = p._getDoubles(); + + var naf = getNAF(k, 1); + var I = (1 << (doubles.step + 1)) - (doubles.step % 2 === 0 ? 2 : 1); + I /= 3; + + // Translate into more windowed form + var repr = []; + for (var j = 0; j < naf.length; j += doubles.step) { + var nafW = 0; + for (var k = j + doubles.step - 1; k >= j; k--) + nafW = (nafW << 1) + naf[k]; + repr.push(nafW); + } + + var a = this.jpoint(null, null, null); + var b = this.jpoint(null, null, null); + for (var i = I; i > 0; i--) { + for (var j = 0; j < repr.length; j++) { + var nafW = repr[j]; + if (nafW === i) + b = b.mixedAdd(doubles.points[j]); + else if (nafW === -i) + b = b.mixedAdd(doubles.points[j].neg()); + } + a = a.add(b); + } + return a.toP(); +}; + +BaseCurve.prototype._wnafMul = function _wnafMul(p, k) { + var w = 4; + + // Precompute window + var nafPoints = p._getNAFPoints(w); + w = nafPoints.wnd; + var wnd = nafPoints.points; + + // Get NAF form + var naf = getNAF(k, w); + + // Add `this`*(N+1) for every w-NAF index + var acc = this.jpoint(null, null, null); + for (var i = naf.length - 1; i >= 0; i--) { + // Count zeroes + for (var k = 0; i >= 0 && naf[i] === 0; i--) + k++; + if (i >= 0) + k++; + acc = acc.dblp(k); + + if (i < 0) + break; + var z = naf[i]; + assert(z !== 0); + if (p.type === 'affine') { + // J +- P + if (z > 0) + acc = acc.mixedAdd(wnd[(z - 1) >> 1]); + else + acc = acc.mixedAdd(wnd[(-z - 1) >> 1].neg()); + } else { + // J +- J + if (z > 0) + acc = acc.add(wnd[(z - 1) >> 1]); + else + acc = acc.add(wnd[(-z - 1) >> 1].neg()); + } + } + return p.type === 'affine' ? acc.toP() : acc; +}; + +BaseCurve.prototype._wnafMulAdd = function _wnafMulAdd(defW, + points, + coeffs, + len, + jacobianResult) { + var wndWidth = this._wnafT1; + var wnd = this._wnafT2; + var naf = this._wnafT3; + + // Fill all arrays + var max = 0; + for (var i = 0; i < len; i++) { + var p = points[i]; + var nafPoints = p._getNAFPoints(defW); + wndWidth[i] = nafPoints.wnd; + wnd[i] = nafPoints.points; + } + + // Comb small window NAFs + for (var i = len - 1; i >= 1; i -= 2) { + var a = i - 1; + var b = i; + if (wndWidth[a] !== 1 || wndWidth[b] !== 1) { + naf[a] = getNAF(coeffs[a], wndWidth[a]); + naf[b] = getNAF(coeffs[b], wndWidth[b]); + max = Math.max(naf[a].length, max); + max = Math.max(naf[b].length, max); + continue; + } + + var comb = [ + points[a], /* 1 */ + null, /* 3 */ + null, /* 5 */ + points[b] /* 7 */ + ]; + + // Try to avoid Projective points, if possible + if (points[a].y.cmp(points[b].y) === 0) { + comb[1] = points[a].add(points[b]); + comb[2] = points[a].toJ().mixedAdd(points[b].neg()); + } else if (points[a].y.cmp(points[b].y.redNeg()) === 0) { + comb[1] = points[a].toJ().mixedAdd(points[b]); + comb[2] = points[a].add(points[b].neg()); + } else { + comb[1] = points[a].toJ().mixedAdd(points[b]); + comb[2] = points[a].toJ().mixedAdd(points[b].neg()); + } + + var index = [ + -3, /* -1 -1 */ + -1, /* -1 0 */ + -5, /* -1 1 */ + -7, /* 0 -1 */ + 0, /* 0 0 */ + 7, /* 0 1 */ + 5, /* 1 -1 */ + 1, /* 1 0 */ + 3 /* 1 1 */ + ]; + + var jsf = getJSF(coeffs[a], coeffs[b]); + max = Math.max(jsf[0].length, max); + naf[a] = new Array(max); + naf[b] = new Array(max); + for (var j = 0; j < max; j++) { + var ja = jsf[0][j] | 0; + var jb = jsf[1][j] | 0; + + naf[a][j] = index[(ja + 1) * 3 + (jb + 1)]; + naf[b][j] = 0; + wnd[a] = comb; + } + } + + var acc = this.jpoint(null, null, null); + var tmp = this._wnafT4; + for (var i = max; i >= 0; i--) { + var k = 0; + + while (i >= 0) { + var zero = true; + for (var j = 0; j < len; j++) { + tmp[j] = naf[j][i] | 0; + if (tmp[j] !== 0) + zero = false; + } + if (!zero) + break; + k++; + i--; + } + if (i >= 0) + k++; + acc = acc.dblp(k); + if (i < 0) + break; + + for (var j = 0; j < len; j++) { + var z = tmp[j]; + var p; + if (z === 0) + continue; + else if (z > 0) + p = wnd[j][(z - 1) >> 1]; + else if (z < 0) + p = wnd[j][(-z - 1) >> 1].neg(); + + if (p.type === 'affine') + acc = acc.mixedAdd(p); + else + acc = acc.add(p); + } + } + // Zeroify references + for (var i = 0; i < len; i++) + wnd[i] = null; + + if (jacobianResult) + return acc; + else + return acc.toP(); +}; + +function BasePoint(curve, type) { + this.curve = curve; + this.type = type; + this.precomputed = null; +} +BaseCurve.BasePoint = BasePoint; + +BasePoint.prototype.eq = function eq(/*other*/) { + throw new Error('Not implemented'); +}; + +BasePoint.prototype.validate = function validate() { + return this.curve.validate(this); +}; + +BaseCurve.prototype.decodePoint = function decodePoint(bytes, enc) { + bytes = utils.toArray(bytes, enc); + + var len = this.p.byteLength(); + + // uncompressed, hybrid-odd, hybrid-even + if ((bytes[0] === 0x04 || bytes[0] === 0x06 || bytes[0] === 0x07) && + bytes.length - 1 === 2 * len) { + if (bytes[0] === 0x06) + assert(bytes[bytes.length - 1] % 2 === 0); + else if (bytes[0] === 0x07) + assert(bytes[bytes.length - 1] % 2 === 1); + + var res = this.point(bytes.slice(1, 1 + len), + bytes.slice(1 + len, 1 + 2 * len)); + + return res; + } else if ((bytes[0] === 0x02 || bytes[0] === 0x03) && + bytes.length - 1 === len) { + return this.pointFromX(bytes.slice(1, 1 + len), bytes[0] === 0x03); + } + throw new Error('Unknown point format'); +}; + +BasePoint.prototype.encodeCompressed = function encodeCompressed(enc) { + return this.encode(enc, true); +}; + +BasePoint.prototype._encode = function _encode(compact) { + var len = this.curve.p.byteLength(); + var x = this.getX().toArray('be', len); + + if (compact) + return [ this.getY().isEven() ? 0x02 : 0x03 ].concat(x); + + return [ 0x04 ].concat(x, this.getY().toArray('be', len)) ; +}; + +BasePoint.prototype.encode = function encode(enc, compact) { + return utils.encode(this._encode(compact), enc); +}; + +BasePoint.prototype.precompute = function precompute(power) { + if (this.precomputed) + return this; + + var precomputed = { + doubles: null, + naf: null, + beta: null + }; + precomputed.naf = this._getNAFPoints(8); + precomputed.doubles = this._getDoubles(4, power); + precomputed.beta = this._getBeta(); + this.precomputed = precomputed; + + return this; +}; + +BasePoint.prototype._hasDoubles = function _hasDoubles(k) { + if (!this.precomputed) + return false; + + var doubles = this.precomputed.doubles; + if (!doubles) + return false; + + return doubles.points.length >= Math.ceil((k.bitLength() + 1) / doubles.step); +}; + +BasePoint.prototype._getDoubles = function _getDoubles(step, power) { + if (this.precomputed && this.precomputed.doubles) + return this.precomputed.doubles; + + var doubles = [ this ]; + var acc = this; + for (var i = 0; i < power; i += step) { + for (var j = 0; j < step; j++) + acc = acc.dbl(); + doubles.push(acc); + } + return { + step: step, + points: doubles + }; +}; + +BasePoint.prototype._getNAFPoints = function _getNAFPoints(wnd) { + if (this.precomputed && this.precomputed.naf) + return this.precomputed.naf; + + var res = [ this ]; + var max = (1 << wnd) - 1; + var dbl = max === 1 ? null : this.dbl(); + for (var i = 1; i < max; i++) + res[i] = res[i - 1].add(dbl); + return { + wnd: wnd, + points: res + }; +}; + +BasePoint.prototype._getBeta = function _getBeta() { + return null; +}; + +BasePoint.prototype.dblp = function dblp(k) { + var r = this; + for (var i = 0; i < k; i++) + r = r.dbl(); + return r; +}; + +},{"../../elliptic":18,"bn.js":16}],20:[function(require,module,exports){ +'use strict'; + +var curve = require('../curve'); +var elliptic = require('../../elliptic'); +var BN = require('bn.js'); +var inherits = require('inherits'); +var Base = curve.base; + +var assert = elliptic.utils.assert; + +function EdwardsCurve(conf) { + // NOTE: Important as we are creating point in Base.call() + this.twisted = (conf.a | 0) !== 1; + this.mOneA = this.twisted && (conf.a | 0) === -1; + this.extended = this.mOneA; + + Base.call(this, 'edwards', conf); + + this.a = new BN(conf.a, 16).umod(this.red.m); + this.a = this.a.toRed(this.red); + this.c = new BN(conf.c, 16).toRed(this.red); + this.c2 = this.c.redSqr(); + this.d = new BN(conf.d, 16).toRed(this.red); + this.dd = this.d.redAdd(this.d); + + assert(!this.twisted || this.c.fromRed().cmpn(1) === 0); + this.oneC = (conf.c | 0) === 1; +} +inherits(EdwardsCurve, Base); +module.exports = EdwardsCurve; + +EdwardsCurve.prototype._mulA = function _mulA(num) { + if (this.mOneA) + return num.redNeg(); + else + return this.a.redMul(num); +}; + +EdwardsCurve.prototype._mulC = function _mulC(num) { + if (this.oneC) + return num; + else + return this.c.redMul(num); +}; + +// Just for compatibility with Short curve +EdwardsCurve.prototype.jpoint = function jpoint(x, y, z, t) { + return this.point(x, y, z, t); +}; + +EdwardsCurve.prototype.pointFromX = function pointFromX(x, odd) { + x = new BN(x, 16); + if (!x.red) + x = x.toRed(this.red); + + var x2 = x.redSqr(); + var rhs = this.c2.redSub(this.a.redMul(x2)); + var lhs = this.one.redSub(this.c2.redMul(this.d).redMul(x2)); + + var y2 = rhs.redMul(lhs.redInvm()); + var y = y2.redSqrt(); + if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) + throw new Error('invalid point'); + + var isOdd = y.fromRed().isOdd(); + if (odd && !isOdd || !odd && isOdd) + y = y.redNeg(); + + return this.point(x, y); +}; + +EdwardsCurve.prototype.pointFromY = function pointFromY(y, odd) { + y = new BN(y, 16); + if (!y.red) + y = y.toRed(this.red); + + // x^2 = (y^2 - c^2) / (c^2 d y^2 - a) + var y2 = y.redSqr(); + var lhs = y2.redSub(this.c2); + var rhs = y2.redMul(this.d).redMul(this.c2).redSub(this.a); + var x2 = lhs.redMul(rhs.redInvm()); + + if (x2.cmp(this.zero) === 0) { + if (odd) + throw new Error('invalid point'); + else + return this.point(this.zero, y); + } + + var x = x2.redSqrt(); + if (x.redSqr().redSub(x2).cmp(this.zero) !== 0) + throw new Error('invalid point'); + + if (x.fromRed().isOdd() !== odd) + x = x.redNeg(); + + return this.point(x, y); +}; + +EdwardsCurve.prototype.validate = function validate(point) { + if (point.isInfinity()) + return true; + + // Curve: A * X^2 + Y^2 = C^2 * (1 + D * X^2 * Y^2) + point.normalize(); + + var x2 = point.x.redSqr(); + var y2 = point.y.redSqr(); + var lhs = x2.redMul(this.a).redAdd(y2); + var rhs = this.c2.redMul(this.one.redAdd(this.d.redMul(x2).redMul(y2))); + + return lhs.cmp(rhs) === 0; +}; + +function Point(curve, x, y, z, t) { + Base.BasePoint.call(this, curve, 'projective'); + if (x === null && y === null && z === null) { + this.x = this.curve.zero; + this.y = this.curve.one; + this.z = this.curve.one; + this.t = this.curve.zero; + this.zOne = true; + } else { + this.x = new BN(x, 16); + this.y = new BN(y, 16); + this.z = z ? new BN(z, 16) : this.curve.one; + this.t = t && new BN(t, 16); + if (!this.x.red) + this.x = this.x.toRed(this.curve.red); + if (!this.y.red) + this.y = this.y.toRed(this.curve.red); + if (!this.z.red) + this.z = this.z.toRed(this.curve.red); + if (this.t && !this.t.red) + this.t = this.t.toRed(this.curve.red); + this.zOne = this.z === this.curve.one; + + // Use extended coordinates + if (this.curve.extended && !this.t) { + this.t = this.x.redMul(this.y); + if (!this.zOne) + this.t = this.t.redMul(this.z.redInvm()); + } + } +} +inherits(Point, Base.BasePoint); + +EdwardsCurve.prototype.pointFromJSON = function pointFromJSON(obj) { + return Point.fromJSON(this, obj); +}; + +EdwardsCurve.prototype.point = function point(x, y, z, t) { + return new Point(this, x, y, z, t); +}; + +Point.fromJSON = function fromJSON(curve, obj) { + return new Point(curve, obj[0], obj[1], obj[2]); +}; + +Point.prototype.inspect = function inspect() { + if (this.isInfinity()) + return ''; + return ''; +}; + +Point.prototype.isInfinity = function isInfinity() { + // XXX This code assumes that zero is always zero in red + return this.x.cmpn(0) === 0 && + (this.y.cmp(this.z) === 0 || + (this.zOne && this.y.cmp(this.curve.c) === 0)); +}; + +Point.prototype._extDbl = function _extDbl() { + // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html + // #doubling-dbl-2008-hwcd + // 4M + 4S + + // A = X1^2 + var a = this.x.redSqr(); + // B = Y1^2 + var b = this.y.redSqr(); + // C = 2 * Z1^2 + var c = this.z.redSqr(); + c = c.redIAdd(c); + // D = a * A + var d = this.curve._mulA(a); + // E = (X1 + Y1)^2 - A - B + var e = this.x.redAdd(this.y).redSqr().redISub(a).redISub(b); + // G = D + B + var g = d.redAdd(b); + // F = G - C + var f = g.redSub(c); + // H = D - B + var h = d.redSub(b); + // X3 = E * F + var nx = e.redMul(f); + // Y3 = G * H + var ny = g.redMul(h); + // T3 = E * H + var nt = e.redMul(h); + // Z3 = F * G + var nz = f.redMul(g); + return this.curve.point(nx, ny, nz, nt); +}; + +Point.prototype._projDbl = function _projDbl() { + // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html + // #doubling-dbl-2008-bbjlp + // #doubling-dbl-2007-bl + // and others + // Generally 3M + 4S or 2M + 4S + + // B = (X1 + Y1)^2 + var b = this.x.redAdd(this.y).redSqr(); + // C = X1^2 + var c = this.x.redSqr(); + // D = Y1^2 + var d = this.y.redSqr(); + + var nx; + var ny; + var nz; + if (this.curve.twisted) { + // E = a * C + var e = this.curve._mulA(c); + // F = E + D + var f = e.redAdd(d); + if (this.zOne) { + // X3 = (B - C - D) * (F - 2) + nx = b.redSub(c).redSub(d).redMul(f.redSub(this.curve.two)); + // Y3 = F * (E - D) + ny = f.redMul(e.redSub(d)); + // Z3 = F^2 - 2 * F + nz = f.redSqr().redSub(f).redSub(f); + } else { + // H = Z1^2 + var h = this.z.redSqr(); + // J = F - 2 * H + var j = f.redSub(h).redISub(h); + // X3 = (B-C-D)*J + nx = b.redSub(c).redISub(d).redMul(j); + // Y3 = F * (E - D) + ny = f.redMul(e.redSub(d)); + // Z3 = F * J + nz = f.redMul(j); + } + } else { + // E = C + D + var e = c.redAdd(d); + // H = (c * Z1)^2 + var h = this.curve._mulC(this.z).redSqr(); + // J = E - 2 * H + var j = e.redSub(h).redSub(h); + // X3 = c * (B - E) * J + nx = this.curve._mulC(b.redISub(e)).redMul(j); + // Y3 = c * E * (C - D) + ny = this.curve._mulC(e).redMul(c.redISub(d)); + // Z3 = E * J + nz = e.redMul(j); + } + return this.curve.point(nx, ny, nz); +}; + +Point.prototype.dbl = function dbl() { + if (this.isInfinity()) + return this; + + // Double in extended coordinates + if (this.curve.extended) + return this._extDbl(); + else + return this._projDbl(); +}; + +Point.prototype._extAdd = function _extAdd(p) { + // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html + // #addition-add-2008-hwcd-3 + // 8M + + // A = (Y1 - X1) * (Y2 - X2) + var a = this.y.redSub(this.x).redMul(p.y.redSub(p.x)); + // B = (Y1 + X1) * (Y2 + X2) + var b = this.y.redAdd(this.x).redMul(p.y.redAdd(p.x)); + // C = T1 * k * T2 + var c = this.t.redMul(this.curve.dd).redMul(p.t); + // D = Z1 * 2 * Z2 + var d = this.z.redMul(p.z.redAdd(p.z)); + // E = B - A + var e = b.redSub(a); + // F = D - C + var f = d.redSub(c); + // G = D + C + var g = d.redAdd(c); + // H = B + A + var h = b.redAdd(a); + // X3 = E * F + var nx = e.redMul(f); + // Y3 = G * H + var ny = g.redMul(h); + // T3 = E * H + var nt = e.redMul(h); + // Z3 = F * G + var nz = f.redMul(g); + return this.curve.point(nx, ny, nz, nt); +}; + +Point.prototype._projAdd = function _projAdd(p) { + // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html + // #addition-add-2008-bbjlp + // #addition-add-2007-bl + // 10M + 1S + + // A = Z1 * Z2 + var a = this.z.redMul(p.z); + // B = A^2 + var b = a.redSqr(); + // C = X1 * X2 + var c = this.x.redMul(p.x); + // D = Y1 * Y2 + var d = this.y.redMul(p.y); + // E = d * C * D + var e = this.curve.d.redMul(c).redMul(d); + // F = B - E + var f = b.redSub(e); + // G = B + E + var g = b.redAdd(e); + // X3 = A * F * ((X1 + Y1) * (X2 + Y2) - C - D) + var tmp = this.x.redAdd(this.y).redMul(p.x.redAdd(p.y)).redISub(c).redISub(d); + var nx = a.redMul(f).redMul(tmp); + var ny; + var nz; + if (this.curve.twisted) { + // Y3 = A * G * (D - a * C) + ny = a.redMul(g).redMul(d.redSub(this.curve._mulA(c))); + // Z3 = F * G + nz = f.redMul(g); + } else { + // Y3 = A * G * (D - C) + ny = a.redMul(g).redMul(d.redSub(c)); + // Z3 = c * F * G + nz = this.curve._mulC(f).redMul(g); + } + return this.curve.point(nx, ny, nz); +}; + +Point.prototype.add = function add(p) { + if (this.isInfinity()) + return p; + if (p.isInfinity()) + return this; + + if (this.curve.extended) + return this._extAdd(p); + else + return this._projAdd(p); +}; + +Point.prototype.mul = function mul(k) { + if (this._hasDoubles(k)) + return this.curve._fixedNafMul(this, k); + else + return this.curve._wnafMul(this, k); +}; + +Point.prototype.mulAdd = function mulAdd(k1, p, k2) { + return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, false); +}; + +Point.prototype.jmulAdd = function jmulAdd(k1, p, k2) { + return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, true); +}; + +Point.prototype.normalize = function normalize() { + if (this.zOne) + return this; + + // Normalize coordinates + var zi = this.z.redInvm(); + this.x = this.x.redMul(zi); + this.y = this.y.redMul(zi); + if (this.t) + this.t = this.t.redMul(zi); + this.z = this.curve.one; + this.zOne = true; + return this; +}; + +Point.prototype.neg = function neg() { + return this.curve.point(this.x.redNeg(), + this.y, + this.z, + this.t && this.t.redNeg()); +}; + +Point.prototype.getX = function getX() { + this.normalize(); + return this.x.fromRed(); +}; + +Point.prototype.getY = function getY() { + this.normalize(); + return this.y.fromRed(); +}; + +Point.prototype.eq = function eq(other) { + return this === other || + this.getX().cmp(other.getX()) === 0 && + this.getY().cmp(other.getY()) === 0; +}; + +Point.prototype.eqXToP = function eqXToP(x) { + var rx = x.toRed(this.curve.red).redMul(this.z); + if (this.x.cmp(rx) === 0) + return true; + + var xc = x.clone(); + var t = this.curve.redN.redMul(this.z); + for (;;) { + xc.iadd(this.curve.n); + if (xc.cmp(this.curve.p) >= 0) + return false; + + rx.redIAdd(t); + if (this.x.cmp(rx) === 0) + return true; + } +}; + +// Compatibility with BaseCurve +Point.prototype.toP = Point.prototype.normalize; +Point.prototype.mixedAdd = Point.prototype.add; + +},{"../../elliptic":18,"../curve":21,"bn.js":16,"inherits":47}],21:[function(require,module,exports){ +'use strict'; + +var curve = exports; + +curve.base = require('./base'); +curve.short = require('./short'); +curve.mont = require('./mont'); +curve.edwards = require('./edwards'); + +},{"./base":19,"./edwards":20,"./mont":22,"./short":23}],22:[function(require,module,exports){ +'use strict'; + +var curve = require('../curve'); +var BN = require('bn.js'); +var inherits = require('inherits'); +var Base = curve.base; + +var elliptic = require('../../elliptic'); +var utils = elliptic.utils; + +function MontCurve(conf) { + Base.call(this, 'mont', conf); + + this.a = new BN(conf.a, 16).toRed(this.red); + this.b = new BN(conf.b, 16).toRed(this.red); + this.i4 = new BN(4).toRed(this.red).redInvm(); + this.two = new BN(2).toRed(this.red); + // Note: this implementation is according to the original paper + // by P. Montgomery, NOT the one by D. J. Bernstein. + this.a24 = this.i4.redMul(this.a.redAdd(this.two)); +} +inherits(MontCurve, Base); +module.exports = MontCurve; + +MontCurve.prototype.validate = function validate(point) { + var x = point.normalize().x; + var x2 = x.redSqr(); + var rhs = x2.redMul(x).redAdd(x2.redMul(this.a)).redAdd(x); + var y = rhs.redSqrt(); + + return y.redSqr().cmp(rhs) === 0; +}; + +function Point(curve, x, z) { + Base.BasePoint.call(this, curve, 'projective'); + if (x === null && z === null) { + this.x = this.curve.one; + this.z = this.curve.zero; + } else { + this.x = new BN(x, 16); + this.z = new BN(z, 16); + if (!this.x.red) + this.x = this.x.toRed(this.curve.red); + if (!this.z.red) + this.z = this.z.toRed(this.curve.red); + } +} +inherits(Point, Base.BasePoint); + +MontCurve.prototype.decodePoint = function decodePoint(bytes, enc) { + var bytes = utils.toArray(bytes, enc); + + // TODO Curve448 + // Montgomery curve points must be represented in the compressed format + // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B + if (bytes.length === 33 && bytes[0] === 0x40) + bytes = bytes.slice(1, 33).reverse(); // point must be little-endian + if (bytes.length !== 32) + throw new Error('Unknown point compression format'); + return this.point(bytes, 1); +}; + +MontCurve.prototype.point = function point(x, z) { + return new Point(this, x, z); +}; + +MontCurve.prototype.pointFromJSON = function pointFromJSON(obj) { + return Point.fromJSON(this, obj); +}; + +Point.prototype.precompute = function precompute() { + // No-op +}; + +Point.prototype._encode = function _encode(compact) { + var len = this.curve.p.byteLength(); + + // Note: the output should always be little-endian + // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B + if (compact) { + return [ 0x40 ].concat(this.getX().toArray('le', len)); + } else { + return this.getX().toArray('be', len); + } +}; + +Point.fromJSON = function fromJSON(curve, obj) { + return new Point(curve, obj[0], obj[1] || curve.one); +}; + +Point.prototype.inspect = function inspect() { + if (this.isInfinity()) + return ''; + return ''; +}; + +Point.prototype.isInfinity = function isInfinity() { + // XXX This code assumes that zero is always zero in red + return this.z.cmpn(0) === 0; +}; + +Point.prototype.dbl = function dbl() { + // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#doubling-dbl-1987-m-3 + // 2M + 2S + 4A + + // A = X1 + Z1 + var a = this.x.redAdd(this.z); + // AA = A^2 + var aa = a.redSqr(); + // B = X1 - Z1 + var b = this.x.redSub(this.z); + // BB = B^2 + var bb = b.redSqr(); + // C = AA - BB + var c = aa.redSub(bb); + // X3 = AA * BB + var nx = aa.redMul(bb); + // Z3 = C * (BB + A24 * C) + var nz = c.redMul(bb.redAdd(this.curve.a24.redMul(c))); + return this.curve.point(nx, nz); +}; + +Point.prototype.add = function add() { + throw new Error('Not supported on Montgomery curve'); +}; + +Point.prototype.diffAdd = function diffAdd(p, diff) { + // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#diffadd-dadd-1987-m-3 + // 4M + 2S + 6A + + // A = X2 + Z2 + var a = this.x.redAdd(this.z); + // B = X2 - Z2 + var b = this.x.redSub(this.z); + // C = X3 + Z3 + var c = p.x.redAdd(p.z); + // D = X3 - Z3 + var d = p.x.redSub(p.z); + // DA = D * A + var da = d.redMul(a); + // CB = C * B + var cb = c.redMul(b); + // X5 = Z1 * (DA + CB)^2 + var nx = diff.z.redMul(da.redAdd(cb).redSqr()); + // Z5 = X1 * (DA - CB)^2 + var nz = diff.x.redMul(da.redISub(cb).redSqr()); + return this.curve.point(nx, nz); +}; + +Point.prototype.mul = function mul(k) { + k = new BN(k, 16); + + var t = k.clone(); + var a = this; // (N / 2) * Q + Q + var b = this.curve.point(null, null); // (N / 2) * Q + var c = this; // Q + + for (var bits = []; t.cmpn(0) !== 0; t.iushrn(1)) + bits.push(t.andln(1)); + + for (var i = bits.length - 1; i >= 0; i--) { + if (bits[i] === 0) { + // N * Q + Q = ((N / 2) * Q + Q)) + (N / 2) * Q + a = a.diffAdd(b, c); + // N * Q = 2 * ((N / 2) * Q + Q)) + b = b.dbl(); + } else { + // N * Q = ((N / 2) * Q + Q) + ((N / 2) * Q) + b = a.diffAdd(b, c); + // N * Q + Q = 2 * ((N / 2) * Q + Q) + a = a.dbl(); + } + } + return b; +}; + +Point.prototype.mulAdd = function mulAdd() { + throw new Error('Not supported on Montgomery curve'); +}; + +Point.prototype.jumlAdd = function jumlAdd() { + throw new Error('Not supported on Montgomery curve'); +}; + +Point.prototype.eq = function eq(other) { + return this.getX().cmp(other.getX()) === 0; +}; + +Point.prototype.normalize = function normalize() { + this.x = this.x.redMul(this.z.redInvm()); + this.z = this.curve.one; + return this; +}; + +Point.prototype.getX = function getX() { + // Normalize coordinates + this.normalize(); + + return this.x.fromRed(); +}; + +},{"../../elliptic":18,"../curve":21,"bn.js":16,"inherits":47}],23:[function(require,module,exports){ +'use strict'; + +var curve = require('../curve'); +var elliptic = require('../../elliptic'); +var BN = require('bn.js'); +var inherits = require('inherits'); +var Base = curve.base; + +var assert = elliptic.utils.assert; + +function ShortCurve(conf) { + Base.call(this, 'short', conf); + + this.a = new BN(conf.a, 16).toRed(this.red); + this.b = new BN(conf.b, 16).toRed(this.red); + this.tinv = this.two.redInvm(); + + this.zeroA = this.a.fromRed().cmpn(0) === 0; + this.threeA = this.a.fromRed().sub(this.p).cmpn(-3) === 0; + + // If the curve is endomorphic, precalculate beta and lambda + this.endo = this._getEndomorphism(conf); + this._endoWnafT1 = new Array(4); + this._endoWnafT2 = new Array(4); +} +inherits(ShortCurve, Base); +module.exports = ShortCurve; + +ShortCurve.prototype._getEndomorphism = function _getEndomorphism(conf) { + // No efficient endomorphism + if (!this.zeroA || !this.g || !this.n || this.p.modn(3) !== 1) + return; + + // Compute beta and lambda, that lambda * P = (beta * Px; Py) + var beta; + var lambda; + if (conf.beta) { + beta = new BN(conf.beta, 16).toRed(this.red); + } else { + var betas = this._getEndoRoots(this.p); + // Choose the smallest beta + beta = betas[0].cmp(betas[1]) < 0 ? betas[0] : betas[1]; + beta = beta.toRed(this.red); + } + if (conf.lambda) { + lambda = new BN(conf.lambda, 16); + } else { + // Choose the lambda that is matching selected beta + var lambdas = this._getEndoRoots(this.n); + if (this.g.mul(lambdas[0]).x.cmp(this.g.x.redMul(beta)) === 0) { + lambda = lambdas[0]; + } else { + lambda = lambdas[1]; + assert(this.g.mul(lambda).x.cmp(this.g.x.redMul(beta)) === 0); + } + } + + // Get basis vectors, used for balanced length-two representation + var basis; + if (conf.basis) { + basis = conf.basis.map(function(vec) { + return { + a: new BN(vec.a, 16), + b: new BN(vec.b, 16) + }; + }); + } else { + basis = this._getEndoBasis(lambda); + } + + return { + beta: beta, + lambda: lambda, + basis: basis + }; +}; + +ShortCurve.prototype._getEndoRoots = function _getEndoRoots(num) { + // Find roots of for x^2 + x + 1 in F + // Root = (-1 +- Sqrt(-3)) / 2 + // + var red = num === this.p ? this.red : BN.mont(num); + var tinv = new BN(2).toRed(red).redInvm(); + var ntinv = tinv.redNeg(); + + var s = new BN(3).toRed(red).redNeg().redSqrt().redMul(tinv); + + var l1 = ntinv.redAdd(s).fromRed(); + var l2 = ntinv.redSub(s).fromRed(); + return [ l1, l2 ]; +}; + +ShortCurve.prototype._getEndoBasis = function _getEndoBasis(lambda) { + // aprxSqrt >= sqrt(this.n) + var aprxSqrt = this.n.ushrn(Math.floor(this.n.bitLength() / 2)); + + // 3.74 + // Run EGCD, until r(L + 1) < aprxSqrt + var u = lambda; + var v = this.n.clone(); + var x1 = new BN(1); + var y1 = new BN(0); + var x2 = new BN(0); + var y2 = new BN(1); + + // NOTE: all vectors are roots of: a + b * lambda = 0 (mod n) + var a0; + var b0; + // First vector + var a1; + var b1; + // Second vector + var a2; + var b2; + + var prevR; + var i = 0; + var r; + var x; + while (u.cmpn(0) !== 0) { + var q = v.div(u); + r = v.sub(q.mul(u)); + x = x2.sub(q.mul(x1)); + var y = y2.sub(q.mul(y1)); + + if (!a1 && r.cmp(aprxSqrt) < 0) { + a0 = prevR.neg(); + b0 = x1; + a1 = r.neg(); + b1 = x; + } else if (a1 && ++i === 2) { + break; + } + prevR = r; + + v = u; + u = r; + x2 = x1; + x1 = x; + y2 = y1; + y1 = y; + } + a2 = r.neg(); + b2 = x; + + var len1 = a1.sqr().add(b1.sqr()); + var len2 = a2.sqr().add(b2.sqr()); + if (len2.cmp(len1) >= 0) { + a2 = a0; + b2 = b0; + } + + // Normalize signs + if (a1.negative) { + a1 = a1.neg(); + b1 = b1.neg(); + } + if (a2.negative) { + a2 = a2.neg(); + b2 = b2.neg(); + } + + return [ + { a: a1, b: b1 }, + { a: a2, b: b2 } + ]; +}; + +ShortCurve.prototype._endoSplit = function _endoSplit(k) { + var basis = this.endo.basis; + var v1 = basis[0]; + var v2 = basis[1]; + + var c1 = v2.b.mul(k).divRound(this.n); + var c2 = v1.b.neg().mul(k).divRound(this.n); + + var p1 = c1.mul(v1.a); + var p2 = c2.mul(v2.a); + var q1 = c1.mul(v1.b); + var q2 = c2.mul(v2.b); + + // Calculate answer + var k1 = k.sub(p1).sub(p2); + var k2 = q1.add(q2).neg(); + return { k1: k1, k2: k2 }; +}; + +ShortCurve.prototype.pointFromX = function pointFromX(x, odd) { + x = new BN(x, 16); + if (!x.red) + x = x.toRed(this.red); + + var y2 = x.redSqr().redMul(x).redIAdd(x.redMul(this.a)).redIAdd(this.b); + var y = y2.redSqrt(); + if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) + throw new Error('invalid point'); + + // XXX Is there any way to tell if the number is odd without converting it + // to non-red form? + var isOdd = y.fromRed().isOdd(); + if (odd && !isOdd || !odd && isOdd) + y = y.redNeg(); + + return this.point(x, y); +}; + +ShortCurve.prototype.validate = function validate(point) { + if (point.inf) + return true; + + var x = point.x; + var y = point.y; + + var ax = this.a.redMul(x); + var rhs = x.redSqr().redMul(x).redIAdd(ax).redIAdd(this.b); + return y.redSqr().redISub(rhs).cmpn(0) === 0; +}; + +ShortCurve.prototype._endoWnafMulAdd = + function _endoWnafMulAdd(points, coeffs, jacobianResult) { + var npoints = this._endoWnafT1; + var ncoeffs = this._endoWnafT2; + for (var i = 0; i < points.length; i++) { + var split = this._endoSplit(coeffs[i]); + var p = points[i]; + var beta = p._getBeta(); + + if (split.k1.negative) { + split.k1.ineg(); + p = p.neg(true); + } + if (split.k2.negative) { + split.k2.ineg(); + beta = beta.neg(true); + } + + npoints[i * 2] = p; + npoints[i * 2 + 1] = beta; + ncoeffs[i * 2] = split.k1; + ncoeffs[i * 2 + 1] = split.k2; + } + var res = this._wnafMulAdd(1, npoints, ncoeffs, i * 2, jacobianResult); + + // Clean-up references to points and coefficients + for (var j = 0; j < i * 2; j++) { + npoints[j] = null; + ncoeffs[j] = null; + } + return res; +}; + +function Point(curve, x, y, isRed) { + Base.BasePoint.call(this, curve, 'affine'); + if (x === null && y === null) { + this.x = null; + this.y = null; + this.inf = true; + } else { + this.x = new BN(x, 16); + this.y = new BN(y, 16); + // Force redgomery representation when loading from JSON + if (isRed) { + this.x.forceRed(this.curve.red); + this.y.forceRed(this.curve.red); + } + if (!this.x.red) + this.x = this.x.toRed(this.curve.red); + if (!this.y.red) + this.y = this.y.toRed(this.curve.red); + this.inf = false; + } +} +inherits(Point, Base.BasePoint); + +ShortCurve.prototype.point = function point(x, y, isRed) { + return new Point(this, x, y, isRed); +}; + +ShortCurve.prototype.pointFromJSON = function pointFromJSON(obj, red) { + return Point.fromJSON(this, obj, red); +}; + +Point.prototype._getBeta = function _getBeta() { + if (!this.curve.endo) + return; + + var pre = this.precomputed; + if (pre && pre.beta) + return pre.beta; + + var beta = this.curve.point(this.x.redMul(this.curve.endo.beta), this.y); + if (pre) { + var curve = this.curve; + var endoMul = function(p) { + return curve.point(p.x.redMul(curve.endo.beta), p.y); + }; + pre.beta = beta; + beta.precomputed = { + beta: null, + naf: pre.naf && { + wnd: pre.naf.wnd, + points: pre.naf.points.map(endoMul) + }, + doubles: pre.doubles && { + step: pre.doubles.step, + points: pre.doubles.points.map(endoMul) + } + }; + } + return beta; +}; + +Point.prototype.toJSON = function toJSON() { + if (!this.precomputed) + return [ this.x, this.y ]; + + return [ this.x, this.y, this.precomputed && { + doubles: this.precomputed.doubles && { + step: this.precomputed.doubles.step, + points: this.precomputed.doubles.points.slice(1) + }, + naf: this.precomputed.naf && { + wnd: this.precomputed.naf.wnd, + points: this.precomputed.naf.points.slice(1) + } + } ]; +}; + +Point.fromJSON = function fromJSON(curve, obj, red) { + if (typeof obj === 'string') + obj = JSON.parse(obj); + var res = curve.point(obj[0], obj[1], red); + if (!obj[2]) + return res; + + function obj2point(obj) { + return curve.point(obj[0], obj[1], red); + } + + var pre = obj[2]; + res.precomputed = { + beta: null, + doubles: pre.doubles && { + step: pre.doubles.step, + points: [ res ].concat(pre.doubles.points.map(obj2point)) + }, + naf: pre.naf && { + wnd: pre.naf.wnd, + points: [ res ].concat(pre.naf.points.map(obj2point)) + } + }; + return res; +}; + +Point.prototype.inspect = function inspect() { + if (this.isInfinity()) + return ''; + return ''; +}; + +Point.prototype.isInfinity = function isInfinity() { + return this.inf; +}; + +Point.prototype.add = function add(p) { + // O + P = P + if (this.inf) + return p; + + // P + O = P + if (p.inf) + return this; + + // P + P = 2P + if (this.eq(p)) + return this.dbl(); + + // P + (-P) = O + if (this.neg().eq(p)) + return this.curve.point(null, null); + + // P + Q = O + if (this.x.cmp(p.x) === 0) + return this.curve.point(null, null); + + var c = this.y.redSub(p.y); + if (c.cmpn(0) !== 0) + c = c.redMul(this.x.redSub(p.x).redInvm()); + var nx = c.redSqr().redISub(this.x).redISub(p.x); + var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); + return this.curve.point(nx, ny); +}; + +Point.prototype.dbl = function dbl() { + if (this.inf) + return this; + + // 2P = O + var ys1 = this.y.redAdd(this.y); + if (ys1.cmpn(0) === 0) + return this.curve.point(null, null); + + var a = this.curve.a; + + var x2 = this.x.redSqr(); + var dyinv = ys1.redInvm(); + var c = x2.redAdd(x2).redIAdd(x2).redIAdd(a).redMul(dyinv); + + var nx = c.redSqr().redISub(this.x.redAdd(this.x)); + var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); + return this.curve.point(nx, ny); +}; + +Point.prototype.getX = function getX() { + return this.x.fromRed(); +}; + +Point.prototype.getY = function getY() { + return this.y.fromRed(); +}; + +Point.prototype.mul = function mul(k) { + k = new BN(k, 16); + + if (this._hasDoubles(k)) + return this.curve._fixedNafMul(this, k); + else if (this.curve.endo) + return this.curve._endoWnafMulAdd([ this ], [ k ]); + else + return this.curve._wnafMul(this, k); +}; + +Point.prototype.mulAdd = function mulAdd(k1, p2, k2) { + var points = [ this, p2 ]; + var coeffs = [ k1, k2 ]; + if (this.curve.endo) + return this.curve._endoWnafMulAdd(points, coeffs); + else + return this.curve._wnafMulAdd(1, points, coeffs, 2); +}; + +Point.prototype.jmulAdd = function jmulAdd(k1, p2, k2) { + var points = [ this, p2 ]; + var coeffs = [ k1, k2 ]; + if (this.curve.endo) + return this.curve._endoWnafMulAdd(points, coeffs, true); + else + return this.curve._wnafMulAdd(1, points, coeffs, 2, true); +}; + +Point.prototype.eq = function eq(p) { + return this === p || + this.inf === p.inf && + (this.inf || this.x.cmp(p.x) === 0 && this.y.cmp(p.y) === 0); +}; + +Point.prototype.neg = function neg(_precompute) { + if (this.inf) + return this; + + var res = this.curve.point(this.x, this.y.redNeg()); + if (_precompute && this.precomputed) { + var pre = this.precomputed; + var negate = function(p) { + return p.neg(); + }; + res.precomputed = { + naf: pre.naf && { + wnd: pre.naf.wnd, + points: pre.naf.points.map(negate) + }, + doubles: pre.doubles && { + step: pre.doubles.step, + points: pre.doubles.points.map(negate) + } + }; + } + return res; +}; + +Point.prototype.toJ = function toJ() { + if (this.inf) + return this.curve.jpoint(null, null, null); + + var res = this.curve.jpoint(this.x, this.y, this.curve.one); + return res; +}; + +function JPoint(curve, x, y, z) { + Base.BasePoint.call(this, curve, 'jacobian'); + if (x === null && y === null && z === null) { + this.x = this.curve.one; + this.y = this.curve.one; + this.z = new BN(0); + } else { + this.x = new BN(x, 16); + this.y = new BN(y, 16); + this.z = new BN(z, 16); + } + if (!this.x.red) + this.x = this.x.toRed(this.curve.red); + if (!this.y.red) + this.y = this.y.toRed(this.curve.red); + if (!this.z.red) + this.z = this.z.toRed(this.curve.red); + + this.zOne = this.z === this.curve.one; +} +inherits(JPoint, Base.BasePoint); + +ShortCurve.prototype.jpoint = function jpoint(x, y, z) { + return new JPoint(this, x, y, z); +}; + +JPoint.prototype.toP = function toP() { + if (this.isInfinity()) + return this.curve.point(null, null); + + var zinv = this.z.redInvm(); + var zinv2 = zinv.redSqr(); + var ax = this.x.redMul(zinv2); + var ay = this.y.redMul(zinv2).redMul(zinv); + + return this.curve.point(ax, ay); +}; + +JPoint.prototype.neg = function neg() { + return this.curve.jpoint(this.x, this.y.redNeg(), this.z); +}; + +JPoint.prototype.add = function add(p) { + // O + P = P + if (this.isInfinity()) + return p; + + // P + O = P + if (p.isInfinity()) + return this; + + // 12M + 4S + 7A + var pz2 = p.z.redSqr(); + var z2 = this.z.redSqr(); + var u1 = this.x.redMul(pz2); + var u2 = p.x.redMul(z2); + var s1 = this.y.redMul(pz2.redMul(p.z)); + var s2 = p.y.redMul(z2.redMul(this.z)); + + var h = u1.redSub(u2); + var r = s1.redSub(s2); + if (h.cmpn(0) === 0) { + if (r.cmpn(0) !== 0) + return this.curve.jpoint(null, null, null); + else + return this.dbl(); + } + + var h2 = h.redSqr(); + var h3 = h2.redMul(h); + var v = u1.redMul(h2); + + var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); + var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); + var nz = this.z.redMul(p.z).redMul(h); + + return this.curve.jpoint(nx, ny, nz); +}; + +JPoint.prototype.mixedAdd = function mixedAdd(p) { + // O + P = P + if (this.isInfinity()) + return p.toJ(); + + // P + O = P + if (p.isInfinity()) + return this; + + // 8M + 3S + 7A + var z2 = this.z.redSqr(); + var u1 = this.x; + var u2 = p.x.redMul(z2); + var s1 = this.y; + var s2 = p.y.redMul(z2).redMul(this.z); + + var h = u1.redSub(u2); + var r = s1.redSub(s2); + if (h.cmpn(0) === 0) { + if (r.cmpn(0) !== 0) + return this.curve.jpoint(null, null, null); + else + return this.dbl(); + } + + var h2 = h.redSqr(); + var h3 = h2.redMul(h); + var v = u1.redMul(h2); + + var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); + var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); + var nz = this.z.redMul(h); + + return this.curve.jpoint(nx, ny, nz); +}; + +JPoint.prototype.dblp = function dblp(pow) { + if (pow === 0) + return this; + if (this.isInfinity()) + return this; + if (!pow) + return this.dbl(); + + if (this.curve.zeroA || this.curve.threeA) { + var r = this; + for (var i = 0; i < pow; i++) + r = r.dbl(); + return r; + } + + // 1M + 2S + 1A + N * (4S + 5M + 8A) + // N = 1 => 6M + 6S + 9A + var a = this.curve.a; + var tinv = this.curve.tinv; + + var jx = this.x; + var jy = this.y; + var jz = this.z; + var jz4 = jz.redSqr().redSqr(); + + // Reuse results + var jyd = jy.redAdd(jy); + for (var i = 0; i < pow; i++) { + var jx2 = jx.redSqr(); + var jyd2 = jyd.redSqr(); + var jyd4 = jyd2.redSqr(); + var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); + + var t1 = jx.redMul(jyd2); + var nx = c.redSqr().redISub(t1.redAdd(t1)); + var t2 = t1.redISub(nx); + var dny = c.redMul(t2); + dny = dny.redIAdd(dny).redISub(jyd4); + var nz = jyd.redMul(jz); + if (i + 1 < pow) + jz4 = jz4.redMul(jyd4); + + jx = nx; + jz = nz; + jyd = dny; + } + + return this.curve.jpoint(jx, jyd.redMul(tinv), jz); +}; + +JPoint.prototype.dbl = function dbl() { + if (this.isInfinity()) + return this; + + if (this.curve.zeroA) + return this._zeroDbl(); + else if (this.curve.threeA) + return this._threeDbl(); + else + return this._dbl(); +}; + +JPoint.prototype._zeroDbl = function _zeroDbl() { + var nx; + var ny; + var nz; + // Z = 1 + if (this.zOne) { + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html + // #doubling-mdbl-2007-bl + // 1M + 5S + 14A + + // XX = X1^2 + var xx = this.x.redSqr(); + // YY = Y1^2 + var yy = this.y.redSqr(); + // YYYY = YY^2 + var yyyy = yy.redSqr(); + // S = 2 * ((X1 + YY)^2 - XX - YYYY) + var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); + s = s.redIAdd(s); + // M = 3 * XX + a; a = 0 + var m = xx.redAdd(xx).redIAdd(xx); + // T = M ^ 2 - 2*S + var t = m.redSqr().redISub(s).redISub(s); + + // 8 * YYYY + var yyyy8 = yyyy.redIAdd(yyyy); + yyyy8 = yyyy8.redIAdd(yyyy8); + yyyy8 = yyyy8.redIAdd(yyyy8); + + // X3 = T + nx = t; + // Y3 = M * (S - T) - 8 * YYYY + ny = m.redMul(s.redISub(t)).redISub(yyyy8); + // Z3 = 2*Y1 + nz = this.y.redAdd(this.y); + } else { + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html + // #doubling-dbl-2009-l + // 2M + 5S + 13A + + // A = X1^2 + var a = this.x.redSqr(); + // B = Y1^2 + var b = this.y.redSqr(); + // C = B^2 + var c = b.redSqr(); + // D = 2 * ((X1 + B)^2 - A - C) + var d = this.x.redAdd(b).redSqr().redISub(a).redISub(c); + d = d.redIAdd(d); + // E = 3 * A + var e = a.redAdd(a).redIAdd(a); + // F = E^2 + var f = e.redSqr(); + + // 8 * C + var c8 = c.redIAdd(c); + c8 = c8.redIAdd(c8); + c8 = c8.redIAdd(c8); + + // X3 = F - 2 * D + nx = f.redISub(d).redISub(d); + // Y3 = E * (D - X3) - 8 * C + ny = e.redMul(d.redISub(nx)).redISub(c8); + // Z3 = 2 * Y1 * Z1 + nz = this.y.redMul(this.z); + nz = nz.redIAdd(nz); + } + + return this.curve.jpoint(nx, ny, nz); +}; + +JPoint.prototype._threeDbl = function _threeDbl() { + var nx; + var ny; + var nz; + // Z = 1 + if (this.zOne) { + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html + // #doubling-mdbl-2007-bl + // 1M + 5S + 15A + + // XX = X1^2 + var xx = this.x.redSqr(); + // YY = Y1^2 + var yy = this.y.redSqr(); + // YYYY = YY^2 + var yyyy = yy.redSqr(); + // S = 2 * ((X1 + YY)^2 - XX - YYYY) + var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); + s = s.redIAdd(s); + // M = 3 * XX + a + var m = xx.redAdd(xx).redIAdd(xx).redIAdd(this.curve.a); + // T = M^2 - 2 * S + var t = m.redSqr().redISub(s).redISub(s); + // X3 = T + nx = t; + // Y3 = M * (S - T) - 8 * YYYY + var yyyy8 = yyyy.redIAdd(yyyy); + yyyy8 = yyyy8.redIAdd(yyyy8); + yyyy8 = yyyy8.redIAdd(yyyy8); + ny = m.redMul(s.redISub(t)).redISub(yyyy8); + // Z3 = 2 * Y1 + nz = this.y.redAdd(this.y); + } else { + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b + // 3M + 5S + + // delta = Z1^2 + var delta = this.z.redSqr(); + // gamma = Y1^2 + var gamma = this.y.redSqr(); + // beta = X1 * gamma + var beta = this.x.redMul(gamma); + // alpha = 3 * (X1 - delta) * (X1 + delta) + var alpha = this.x.redSub(delta).redMul(this.x.redAdd(delta)); + alpha = alpha.redAdd(alpha).redIAdd(alpha); + // X3 = alpha^2 - 8 * beta + var beta4 = beta.redIAdd(beta); + beta4 = beta4.redIAdd(beta4); + var beta8 = beta4.redAdd(beta4); + nx = alpha.redSqr().redISub(beta8); + // Z3 = (Y1 + Z1)^2 - gamma - delta + nz = this.y.redAdd(this.z).redSqr().redISub(gamma).redISub(delta); + // Y3 = alpha * (4 * beta - X3) - 8 * gamma^2 + var ggamma8 = gamma.redSqr(); + ggamma8 = ggamma8.redIAdd(ggamma8); + ggamma8 = ggamma8.redIAdd(ggamma8); + ggamma8 = ggamma8.redIAdd(ggamma8); + ny = alpha.redMul(beta4.redISub(nx)).redISub(ggamma8); + } + + return this.curve.jpoint(nx, ny, nz); +}; + +JPoint.prototype._dbl = function _dbl() { + var a = this.curve.a; + + // 4M + 6S + 10A + var jx = this.x; + var jy = this.y; + var jz = this.z; + var jz4 = jz.redSqr().redSqr(); + + var jx2 = jx.redSqr(); + var jy2 = jy.redSqr(); + + var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); + + var jxd4 = jx.redAdd(jx); + jxd4 = jxd4.redIAdd(jxd4); + var t1 = jxd4.redMul(jy2); + var nx = c.redSqr().redISub(t1.redAdd(t1)); + var t2 = t1.redISub(nx); + + var jyd8 = jy2.redSqr(); + jyd8 = jyd8.redIAdd(jyd8); + jyd8 = jyd8.redIAdd(jyd8); + jyd8 = jyd8.redIAdd(jyd8); + var ny = c.redMul(t2).redISub(jyd8); + var nz = jy.redAdd(jy).redMul(jz); + + return this.curve.jpoint(nx, ny, nz); +}; + +JPoint.prototype.trpl = function trpl() { + if (!this.curve.zeroA) + return this.dbl().add(this); + + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#tripling-tpl-2007-bl + // 5M + 10S + ... + + // XX = X1^2 + var xx = this.x.redSqr(); + // YY = Y1^2 + var yy = this.y.redSqr(); + // ZZ = Z1^2 + var zz = this.z.redSqr(); + // YYYY = YY^2 + var yyyy = yy.redSqr(); + // M = 3 * XX + a * ZZ2; a = 0 + var m = xx.redAdd(xx).redIAdd(xx); + // MM = M^2 + var mm = m.redSqr(); + // E = 6 * ((X1 + YY)^2 - XX - YYYY) - MM + var e = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); + e = e.redIAdd(e); + e = e.redAdd(e).redIAdd(e); + e = e.redISub(mm); + // EE = E^2 + var ee = e.redSqr(); + // T = 16*YYYY + var t = yyyy.redIAdd(yyyy); + t = t.redIAdd(t); + t = t.redIAdd(t); + t = t.redIAdd(t); + // U = (M + E)^2 - MM - EE - T + var u = m.redIAdd(e).redSqr().redISub(mm).redISub(ee).redISub(t); + // X3 = 4 * (X1 * EE - 4 * YY * U) + var yyu4 = yy.redMul(u); + yyu4 = yyu4.redIAdd(yyu4); + yyu4 = yyu4.redIAdd(yyu4); + var nx = this.x.redMul(ee).redISub(yyu4); + nx = nx.redIAdd(nx); + nx = nx.redIAdd(nx); + // Y3 = 8 * Y1 * (U * (T - U) - E * EE) + var ny = this.y.redMul(u.redMul(t.redISub(u)).redISub(e.redMul(ee))); + ny = ny.redIAdd(ny); + ny = ny.redIAdd(ny); + ny = ny.redIAdd(ny); + // Z3 = (Z1 + E)^2 - ZZ - EE + var nz = this.z.redAdd(e).redSqr().redISub(zz).redISub(ee); + + return this.curve.jpoint(nx, ny, nz); +}; + +JPoint.prototype.mul = function mul(k, kbase) { + k = new BN(k, kbase); + + return this.curve._wnafMul(this, k); +}; + +JPoint.prototype.eq = function eq(p) { + if (p.type === 'affine') + return this.eq(p.toJ()); + + if (this === p) + return true; + + // x1 * z2^2 == x2 * z1^2 + var z2 = this.z.redSqr(); + var pz2 = p.z.redSqr(); + if (this.x.redMul(pz2).redISub(p.x.redMul(z2)).cmpn(0) !== 0) + return false; + + // y1 * z2^3 == y2 * z1^3 + var z3 = z2.redMul(this.z); + var pz3 = pz2.redMul(p.z); + return this.y.redMul(pz3).redISub(p.y.redMul(z3)).cmpn(0) === 0; +}; + +JPoint.prototype.eqXToP = function eqXToP(x) { + var zs = this.z.redSqr(); + var rx = x.toRed(this.curve.red).redMul(zs); + if (this.x.cmp(rx) === 0) + return true; + + var xc = x.clone(); + var t = this.curve.redN.redMul(zs); + for (;;) { + xc.iadd(this.curve.n); + if (xc.cmp(this.curve.p) >= 0) + return false; + + rx.redIAdd(t); + if (this.x.cmp(rx) === 0) + return true; + } +}; + +JPoint.prototype.inspect = function inspect() { + if (this.isInfinity()) + return ''; + return ''; +}; + +JPoint.prototype.isInfinity = function isInfinity() { + // XXX This code assumes that zero is always zero in red + return this.z.cmpn(0) === 0; +}; + +},{"../../elliptic":18,"../curve":21,"bn.js":16,"inherits":47}],24:[function(require,module,exports){ +'use strict'; + +var curves = exports; + +var hash = require('hash.js'); +var elliptic = require('../elliptic'); + +var assert = elliptic.utils.assert; + +function PresetCurve(options) { + if (options.type === 'short') + this.curve = new elliptic.curve.short(options); + else if (options.type === 'edwards') + this.curve = new elliptic.curve.edwards(options); + else if (options.type === 'mont') + this.curve = new elliptic.curve.mont(options); + else throw new Error('Unknown curve type.'); + this.g = this.curve.g; + this.n = this.curve.n; + this.hash = options.hash; + + assert(this.g.validate(), 'Invalid curve'); + assert(this.g.mul(this.n).isInfinity(), 'Invalid curve, n*G != O'); +} +curves.PresetCurve = PresetCurve; + +function defineCurve(name, options) { + Object.defineProperty(curves, name, { + configurable: true, + enumerable: true, + get: function() { + var curve = new PresetCurve(options); + Object.defineProperty(curves, name, { + configurable: true, + enumerable: true, + value: curve + }); + return curve; + } + }); +} + +defineCurve('p192', { + type: 'short', + prime: 'p192', + p: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff', + a: 'ffffffff ffffffff ffffffff fffffffe ffffffff fffffffc', + b: '64210519 e59c80e7 0fa7e9ab 72243049 feb8deec c146b9b1', + n: 'ffffffff ffffffff ffffffff 99def836 146bc9b1 b4d22831', + hash: hash.sha256, + gRed: false, + g: [ + '188da80e b03090f6 7cbf20eb 43a18800 f4ff0afd 82ff1012', + '07192b95 ffc8da78 631011ed 6b24cdd5 73f977a1 1e794811' + ] +}); + +defineCurve('p224', { + type: 'short', + prime: 'p224', + p: 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001', + a: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff fffffffe', + b: 'b4050a85 0c04b3ab f5413256 5044b0b7 d7bfd8ba 270b3943 2355ffb4', + n: 'ffffffff ffffffff ffffffff ffff16a2 e0b8f03e 13dd2945 5c5c2a3d', + hash: hash.sha256, + gRed: false, + g: [ + 'b70e0cbd 6bb4bf7f 321390b9 4a03c1d3 56c21122 343280d6 115c1d21', + 'bd376388 b5f723fb 4c22dfe6 cd4375a0 5a074764 44d58199 85007e34' + ] +}); + +defineCurve('p256', { + type: 'short', + prime: null, + p: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff', + a: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff fffffffc', + b: '5ac635d8 aa3a93e7 b3ebbd55 769886bc 651d06b0 cc53b0f6 3bce3c3e 27d2604b', + n: 'ffffffff 00000000 ffffffff ffffffff bce6faad a7179e84 f3b9cac2 fc632551', + hash: hash.sha256, + gRed: false, + g: [ + '6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296', + '4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5' + ] +}); + +defineCurve('p384', { + type: 'short', + prime: null, + p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'fffffffe ffffffff 00000000 00000000 ffffffff', + a: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'fffffffe ffffffff 00000000 00000000 fffffffc', + b: 'b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112 0314088f ' + + '5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef', + n: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff c7634d81 ' + + 'f4372ddf 581a0db2 48b0a77a ecec196a ccc52973', + hash: hash.sha384, + gRed: false, + g: [ + 'aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98 59f741e0 82542a38 ' + + '5502f25d bf55296c 3a545e38 72760ab7', + '3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c e9da3113 b5f0b8c0 ' + + '0a60b1ce 1d7e819d 7a431d7c 90ea0e5f' + ] +}); + +defineCurve('p521', { + type: 'short', + prime: null, + p: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff ffffffff ffffffff ffffffff', + a: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff ffffffff ffffffff fffffffc', + b: '00000051 953eb961 8e1c9a1f 929a21a0 b68540ee a2da725b ' + + '99b315f3 b8b48991 8ef109e1 56193951 ec7e937b 1652c0bd ' + + '3bb1bf07 3573df88 3d2c34f1 ef451fd4 6b503f00', + n: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff fffffffa 51868783 bf2f966b 7fcc0148 ' + + 'f709a5d0 3bb5c9b8 899c47ae bb6fb71e 91386409', + hash: hash.sha512, + gRed: false, + g: [ + '000000c6 858e06b7 0404e9cd 9e3ecb66 2395b442 9c648139 ' + + '053fb521 f828af60 6b4d3dba a14b5e77 efe75928 fe1dc127 ' + + 'a2ffa8de 3348b3c1 856a429b f97e7e31 c2e5bd66', + '00000118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd9 98f54449 ' + + '579b4468 17afbd17 273e662c 97ee7299 5ef42640 c550b901 ' + + '3fad0761 353c7086 a272c240 88be9476 9fd16650' + ] +}); + +// https://tools.ietf.org/html/rfc7748#section-4.1 +defineCurve('curve25519', { + type: 'mont', + prime: 'p25519', + p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', + a: '76d06', + b: '1', + n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', + cofactor: '8', + hash: hash.sha256, + gRed: false, + g: [ + '9' + ] +}); + +defineCurve('ed25519', { + type: 'edwards', + prime: 'p25519', + p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', + a: '-1', + c: '1', + // -121665 * (121666^(-1)) (mod P) + d: '52036cee2b6ffe73 8cc740797779e898 00700a4d4141d8ab 75eb4dca135978a3', + n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', + cofactor: '8', + hash: hash.sha256, + gRed: false, + g: [ + '216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a', + // 4/5 + '6666666666666666666666666666666666666666666666666666666666666658' + ] +}); + +// https://tools.ietf.org/html/rfc5639#section-3.4 +defineCurve('brainpoolP256r1', { + type: 'short', + prime: null, + p: 'A9FB57DB A1EEA9BC 3E660A90 9D838D72 6E3BF623 D5262028 2013481D 1F6E5377', + a: '7D5A0975 FC2C3057 EEF67530 417AFFE7 FB8055C1 26DC5C6C E94A4B44 F330B5D9', + b: '26DC5C6C E94A4B44 F330B5D9 BBD77CBF 95841629 5CF7E1CE 6BCCDC18 FF8C07B6', + n: 'A9FB57DB A1EEA9BC 3E660A90 9D838D71 8C397AA3 B561A6F7 901E0E82 974856A7', + hash: hash.sha256, // or 384, or 512 + gRed: false, + g: [ + '8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262', + '547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997' + ] +}); + +// https://tools.ietf.org/html/rfc5639#section-3.6 +defineCurve('brainpoolP384r1', { + type: 'short', + prime: null, + p: '8CB91E82 A3386D28 0F5D6F7E 50E641DF 152F7109 ED5456B4 12B1DA19 7FB71123' + + 'ACD3A729 901D1A71 87470013 3107EC53', + a: '7BC382C6 3D8C150C 3C72080A CE05AFA0 C2BEA28E 4FB22787 139165EF BA91F90F' + + '8AA5814A 503AD4EB 04A8C7DD 22CE2826', + b: '04A8C7DD 22CE2826 8B39B554 16F0447C 2FB77DE1 07DCD2A6 2E880EA5 3EEB62D5' + + '7CB43902 95DBC994 3AB78696 FA504C11', + n: '8CB91E82 A3386D28 0F5D6F7E 50E641DF 152F7109 ED5456B3 1F166E6C AC0425A7' + + 'CF3AB6AF 6B7FC310 3B883202 E9046565', + hash: hash.sha384, // or 512 + gRed: false, + g: [ + '1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10' + + 'E8E826E03436D646AAEF87B2E247D4AF1E', + '8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129' + + '280E4646217791811142820341263C5315' + ] +}); + +// https://tools.ietf.org/html/rfc5639#section-3.7 +defineCurve('brainpoolP512r1', { + type: 'short', + prime: null, + p: 'AADD9DB8 DBE9C48B 3FD4E6AE 33C9FC07 CB308DB3 B3C9D20E D6639CCA 70330871' + + '7D4D9B00 9BC66842 AECDA12A E6A380E6 2881FF2F 2D82C685 28AA6056 583A48F3', + a: '7830A331 8B603B89 E2327145 AC234CC5 94CBDD8D 3DF91610 A83441CA EA9863BC' + + '2DED5D5A A8253AA1 0A2EF1C9 8B9AC8B5 7F1117A7 2BF2C7B9 E7C1AC4D 77FC94CA', + b: '3DF91610 A83441CA EA9863BC 2DED5D5A A8253AA1 0A2EF1C9 8B9AC8B5 7F1117A7' + + '2BF2C7B9 E7C1AC4D 77FC94CA DC083E67 984050B7 5EBAE5DD 2809BD63 8016F723', + n: 'AADD9DB8 DBE9C48B 3FD4E6AE 33C9FC07 CB308DB3 B3C9D20E D6639CCA 70330870' + + '553E5C41 4CA92619 41866119 7FAC1047 1DB1D381 085DDADD B5879682 9CA90069', + hash: hash.sha512, + gRed: false, + g: [ + '81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D009' + + '8EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822', + '7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F81' + + '11B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892' + ] +}); + +// https://en.bitcoin.it/wiki/Secp256k1 +var pre; +try { + pre = require('./precomputed/secp256k1'); +} catch (e) { + pre = undefined; +} + +defineCurve('secp256k1', { + type: 'short', + prime: 'k256', + p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f', + a: '0', + b: '7', + n: 'ffffffff ffffffff ffffffff fffffffe baaedce6 af48a03b bfd25e8c d0364141', + h: '1', + hash: hash.sha256, + + // Precomputed endomorphism + beta: '7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee', + lambda: '5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72', + basis: [ + { + a: '3086d221a7d46bcde86c90e49284eb15', + b: '-e4437ed6010e88286f547fa90abfe4c3' + }, + { + a: '114ca50f7a8e2f3f657c1108d9d44cfd8', + b: '3086d221a7d46bcde86c90e49284eb15' + } + ], + + gRed: false, + g: [ + '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', + '483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', + pre + ] +}); + +},{"../elliptic":18,"./precomputed/secp256k1":31,"hash.js":34}],25:[function(require,module,exports){ +'use strict'; + +var BN = require('bn.js'); +var HmacDRBG = require('hmac-drbg'); +var elliptic = require('../../elliptic'); +var utils = elliptic.utils; +var assert = utils.assert; + +var KeyPair = require('./key'); +var Signature = require('./signature'); + +function EC(options) { + if (!(this instanceof EC)) + return new EC(options); + + // Shortcut `elliptic.ec(curve-name)` + if (typeof options === 'string') { + assert(elliptic.curves.hasOwnProperty(options), 'Unknown curve ' + options); + + options = elliptic.curves[options]; + } + + // Shortcut for `elliptic.ec(elliptic.curves.curveName)` + if (options instanceof elliptic.curves.PresetCurve) + options = { curve: options }; + + this.curve = options.curve.curve; + this.n = this.curve.n; + this.nh = this.n.ushrn(1); + this.g = this.curve.g; + + // Point on curve + this.g = options.curve.g; + this.g.precompute(options.curve.n.bitLength() + 1); + + // Hash function for DRBG + this.hash = options.hash || options.curve.hash; +} +module.exports = EC; + +EC.prototype.keyPair = function keyPair(options) { + return new KeyPair(this, options); +}; + +EC.prototype.keyFromPrivate = function keyFromPrivate(priv, enc) { + return KeyPair.fromPrivate(this, priv, enc); +}; + +EC.prototype.keyFromPublic = function keyFromPublic(pub, enc) { + return KeyPair.fromPublic(this, pub, enc); +}; + +EC.prototype.genKeyPair = function genKeyPair(options) { + if (!options) + options = {}; + + // Instantiate Hmac_DRBG + var drbg = new HmacDRBG({ + hash: this.hash, + pers: options.pers, + persEnc: options.persEnc || 'utf8', + entropy: options.entropy || elliptic.rand(this.hash.hmacStrength), + entropyEnc: options.entropy && options.entropyEnc || 'utf8', + nonce: this.n.toArray() + }); + + // Key generation for curve25519 is simpler + if (this.curve.type === 'mont') { + var priv = new BN(drbg.generate(32)); + return this.keyFromPrivate(priv); + } + + var bytes = this.n.byteLength(); + var ns2 = this.n.sub(new BN(2)); + do { + var priv = new BN(drbg.generate(bytes)); + if (priv.cmp(ns2) > 0) + continue; + + priv.iaddn(1); + return this.keyFromPrivate(priv); + } while (true); +}; + +EC.prototype._truncateToN = function truncateToN(msg, truncOnly) { + var delta = msg.byteLength() * 8 - this.n.bitLength(); + if (delta > 0) + msg = msg.ushrn(delta); + if (!truncOnly && msg.cmp(this.n) >= 0) + return msg.sub(this.n); + else + return msg; +}; + +EC.prototype.sign = function sign(msg, key, enc, options) { + if (typeof enc === 'object') { + options = enc; + enc = null; + } + if (!options) + options = {}; + + key = this.keyFromPrivate(key, enc); + msg = this._truncateToN(new BN(msg, 16)); + + // Zero-extend key to provide enough entropy + var bytes = this.n.byteLength(); + var bkey = key.getPrivate().toArray('be', bytes); + + // Zero-extend nonce to have the same byte size as N + var nonce = msg.toArray('be', bytes); + + // Instantiate Hmac_DRBG + var drbg = new HmacDRBG({ + hash: this.hash, + entropy: bkey, + nonce: nonce, + pers: options.pers, + persEnc: options.persEnc || 'utf8' + }); + + // Number of bytes to generate + var ns1 = this.n.sub(new BN(1)); + + for (var iter = 0; true; iter++) { + var k = options.k ? + options.k(iter) : + new BN(drbg.generate(this.n.byteLength())); + k = this._truncateToN(k, true); + if (k.cmpn(1) <= 0 || k.cmp(ns1) >= 0) + continue; + + var kp = this.g.mul(k); + if (kp.isInfinity()) + continue; + + var kpX = kp.getX(); + var r = kpX.umod(this.n); + if (r.cmpn(0) === 0) + continue; + + var s = k.invm(this.n).mul(r.mul(key.getPrivate()).iadd(msg)); + s = s.umod(this.n); + if (s.cmpn(0) === 0) + continue; + + var recoveryParam = (kp.getY().isOdd() ? 1 : 0) | + (kpX.cmp(r) !== 0 ? 2 : 0); + + // Use complement of `s`, if it is > `n / 2` + if (options.canonical && s.cmp(this.nh) > 0) { + s = this.n.sub(s); + recoveryParam ^= 1; + } + + return new Signature({ r: r, s: s, recoveryParam: recoveryParam }); + } +}; + +EC.prototype.verify = function verify(msg, signature, key, enc) { + msg = this._truncateToN(new BN(msg, 16)); + key = this.keyFromPublic(key, enc); + signature = new Signature(signature, 'hex'); + + // Perform primitive values validation + var r = signature.r; + var s = signature.s; + if (r.cmpn(1) < 0 || r.cmp(this.n) >= 0) + return false; + if (s.cmpn(1) < 0 || s.cmp(this.n) >= 0) + return false; + + // Validate signature + var sinv = s.invm(this.n); + var u1 = sinv.mul(msg).umod(this.n); + var u2 = sinv.mul(r).umod(this.n); + + if (!this.curve._maxwellTrick) { + var p = this.g.mulAdd(u1, key.getPublic(), u2); + if (p.isInfinity()) + return false; + + return p.getX().umod(this.n).cmp(r) === 0; + } + + // NOTE: Greg Maxwell's trick, inspired by: + // https://git.io/vad3K + + var p = this.g.jmulAdd(u1, key.getPublic(), u2); + if (p.isInfinity()) + return false; + + // Compare `p.x` of Jacobian point with `r`, + // this will do `p.x == r * p.z^2` instead of multiplying `p.x` by the + // inverse of `p.z^2` + return p.eqXToP(r); +}; + +EC.prototype.recoverPubKey = function(msg, signature, j, enc) { + assert((3 & j) === j, 'The recovery param is more than two bits'); + signature = new Signature(signature, enc); + + var n = this.n; + var e = new BN(msg); + var r = signature.r; + var s = signature.s; + + // A set LSB signifies that the y-coordinate is odd + var isYOdd = j & 1; + var isSecondKey = j >> 1; + if (r.cmp(this.curve.p.umod(this.curve.n)) >= 0 && isSecondKey) + throw new Error('Unable to find sencond key candinate'); + + // 1.1. Let x = r + jn. + if (isSecondKey) + r = this.curve.pointFromX(r.add(this.curve.n), isYOdd); + else + r = this.curve.pointFromX(r, isYOdd); + + var rInv = signature.r.invm(n); + var s1 = n.sub(e).mul(rInv).umod(n); + var s2 = s.mul(rInv).umod(n); + + // 1.6.1 Compute Q = r^-1 (sR - eG) + // Q = r^-1 (sR + -eG) + return this.g.mulAdd(s1, r, s2); +}; + +EC.prototype.getKeyRecoveryParam = function(e, signature, Q, enc) { + signature = new Signature(signature, enc); + if (signature.recoveryParam !== null) + return signature.recoveryParam; + + for (var i = 0; i < 4; i++) { + var Qprime; + try { + Qprime = this.recoverPubKey(e, signature, i); + } catch (e) { + continue; + } + + if (Qprime.eq(Q)) + return i; + } + throw new Error('Unable to find valid recovery factor'); +}; + +},{"../../elliptic":18,"./key":26,"./signature":27,"bn.js":16,"hmac-drbg":46}],26:[function(require,module,exports){ +'use strict'; + +var BN = require('bn.js'); +var elliptic = require('../../elliptic'); +var utils = elliptic.utils; +var assert = utils.assert; + +function KeyPair(ec, options) { + this.ec = ec; + this.priv = null; + this.pub = null; + + // KeyPair(ec, { priv: ..., pub: ... }) + if (options.priv) + this._importPrivate(options.priv, options.privEnc); + if (options.pub) + this._importPublic(options.pub, options.pubEnc); +} +module.exports = KeyPair; + +KeyPair.fromPublic = function fromPublic(ec, pub, enc) { + if (pub instanceof KeyPair) + return pub; + + return new KeyPair(ec, { + pub: pub, + pubEnc: enc + }); +}; + +KeyPair.fromPrivate = function fromPrivate(ec, priv, enc) { + if (priv instanceof KeyPair) + return priv; + + return new KeyPair(ec, { + priv: priv, + privEnc: enc + }); +}; + +// TODO: should not validate for X25519 +KeyPair.prototype.validate = function validate() { + var pub = this.getPublic(); + + if (pub.isInfinity()) + return { result: false, reason: 'Invalid public key' }; + if (!pub.validate()) + return { result: false, reason: 'Public key is not a point' }; + if (!pub.mul(this.ec.curve.n).isInfinity()) + return { result: false, reason: 'Public key * N != O' }; + + return { result: true, reason: null }; +}; + +KeyPair.prototype.getPublic = function getPublic(enc, compact) { + if (!this.pub) + this.pub = this.ec.g.mul(this.priv); + + if (!enc) + return this.pub; + + return this.pub.encode(enc, compact); +}; + +KeyPair.prototype.getPrivate = function getPrivate(enc) { + if (enc === 'hex') + return this.priv.toString(16, 2); + else + return this.priv; +}; + +KeyPair.prototype._importPrivate = function _importPrivate(key, enc) { + this.priv = new BN(key, enc || 16); + + // For Curve25519/Curve448 we have a specific procedure. + // TODO Curve448 + if (this.ec.curve.type === 'mont') { + var one = this.ec.curve.one; + var mask = one.ushln(255 - 3).sub(one).ushln(3); + this.priv = this.priv.or(one.ushln(255 - 1)); + this.priv = this.priv.and(mask); + } else + // Ensure that the priv won't be bigger than n, otherwise we may fail + // in fixed multiplication method + this.priv = this.priv.umod(this.ec.curve.n); +}; + +KeyPair.prototype._importPublic = function _importPublic(key, enc) { + if (key.x || key.y) { + // Montgomery points only have an `x` coordinate. + // Weierstrass/Edwards points on the other hand have both `x` and + // `y` coordinates. + if (this.ec.curve.type === 'mont') { + assert(key.x, 'Need x coordinate'); + } else if (this.ec.curve.type === 'short' || + this.ec.curve.type === 'edwards') { + assert(key.x && key.y, 'Need both x and y coordinate'); + } + this.pub = this.ec.curve.point(key.x, key.y); + return; + } + this.pub = this.ec.curve.decodePoint(key, enc); +}; + +// ECDH +KeyPair.prototype.derive = function derive(pub) { + return pub.mul(this.priv).getX(); +}; + +// ECDSA +KeyPair.prototype.sign = function sign(msg, enc, options) { + return this.ec.sign(msg, this, enc, options); +}; + +KeyPair.prototype.verify = function verify(msg, signature) { + return this.ec.verify(msg, signature, this); +}; + +KeyPair.prototype.inspect = function inspect() { + return ''; +}; + +},{"../../elliptic":18,"bn.js":16}],27:[function(require,module,exports){ +'use strict'; + +var BN = require('bn.js'); + +var elliptic = require('../../elliptic'); +var utils = elliptic.utils; +var assert = utils.assert; + +function Signature(options, enc) { + if (options instanceof Signature) + return options; + + if (this._importDER(options, enc)) + return; + + assert(options.r && options.s, 'Signature without r or s'); + this.r = new BN(options.r, 16); + this.s = new BN(options.s, 16); + if (options.recoveryParam === undefined) + this.recoveryParam = null; + else + this.recoveryParam = options.recoveryParam; +} +module.exports = Signature; + +function Position() { + this.place = 0; +} + +function getLength(buf, p) { + var initial = buf[p.place++]; + if (!(initial & 0x80)) { + return initial; + } + var octetLen = initial & 0xf; + var val = 0; + for (var i = 0, off = p.place; i < octetLen; i++, off++) { + val <<= 8; + val |= buf[off]; + } + p.place = off; + return val; +} + +function rmPadding(buf) { + var i = 0; + var len = buf.length - 1; + while (!buf[i] && !(buf[i + 1] & 0x80) && i < len) { + i++; + } + if (i === 0) { + return buf; + } + return buf.slice(i); +} + +Signature.prototype._importDER = function _importDER(data, enc) { + data = utils.toArray(data, enc); + var p = new Position(); + if (data[p.place++] !== 0x30) { + return false; + } + var len = getLength(data, p); + if ((len + p.place) !== data.length) { + return false; + } + if (data[p.place++] !== 0x02) { + return false; + } + var rlen = getLength(data, p); + var r = data.slice(p.place, rlen + p.place); + p.place += rlen; + if (data[p.place++] !== 0x02) { + return false; + } + var slen = getLength(data, p); + if (data.length !== slen + p.place) { + return false; + } + var s = data.slice(p.place, slen + p.place); + if (r[0] === 0 && (r[1] & 0x80)) { + r = r.slice(1); + } + if (s[0] === 0 && (s[1] & 0x80)) { + s = s.slice(1); + } + + this.r = new BN(r); + this.s = new BN(s); + this.recoveryParam = null; + + return true; +}; + +function constructLength(arr, len) { + if (len < 0x80) { + arr.push(len); + return; + } + var octets = 1 + (Math.log(len) / Math.LN2 >>> 3); + arr.push(octets | 0x80); + while (--octets) { + arr.push((len >>> (octets << 3)) & 0xff); + } + arr.push(len); +} + +Signature.prototype.toDER = function toDER(enc) { + var r = this.r.toArray(); + var s = this.s.toArray(); + + // Pad values + if (r[0] & 0x80) + r = [ 0 ].concat(r); + // Pad values + if (s[0] & 0x80) + s = [ 0 ].concat(s); + + r = rmPadding(r); + s = rmPadding(s); + + while (!s[0] && !(s[1] & 0x80)) { + s = s.slice(1); + } + var arr = [ 0x02 ]; + constructLength(arr, r.length); + arr = arr.concat(r); + arr.push(0x02); + constructLength(arr, s.length); + var backHalf = arr.concat(s); + var res = [ 0x30 ]; + constructLength(res, backHalf.length); + res = res.concat(backHalf); + return utils.encode(res, enc); +}; + +},{"../../elliptic":18,"bn.js":16}],28:[function(require,module,exports){ +'use strict'; + +var hash = require('hash.js'); +var HmacDRBG = require('hmac-drbg'); +var elliptic = require('../../elliptic'); +var utils = elliptic.utils; +var assert = utils.assert; +var parseBytes = utils.parseBytes; +var KeyPair = require('./key'); +var Signature = require('./signature'); + +function EDDSA(curve) { + assert(curve === 'ed25519', 'only tested with ed25519 so far'); + + if (!(this instanceof EDDSA)) + return new EDDSA(curve); + + var curve = elliptic.curves[curve].curve; + this.curve = curve; + this.g = curve.g; + this.g.precompute(curve.n.bitLength() + 1); + + this.pointClass = curve.point().constructor; + this.encodingLength = Math.ceil(curve.n.bitLength() / 8); + this.hash = hash.sha512; +} + +module.exports = EDDSA; + +/** +* @param {Array|String} message - message bytes +* @param {Array|String|KeyPair} secret - secret bytes or a keypair +* @returns {Signature} - signature +*/ +EDDSA.prototype.sign = function sign(message, secret) { + message = parseBytes(message); + var key = this.keyFromSecret(secret); + var r = this.hashInt(key.messagePrefix(), message); + var R = this.g.mul(r); + var Rencoded = this.encodePoint(R); + var s_ = this.hashInt(Rencoded, key.pubBytes(), message) + .mul(key.priv()); + var S = r.add(s_).umod(this.curve.n); + return this.makeSignature({ R: R, S: S, Rencoded: Rencoded }); +}; + +/** +* @param {Array} message - message bytes +* @param {Array|String|Signature} sig - sig bytes +* @param {Array|String|Point|KeyPair} pub - public key +* @returns {Boolean} - true if public key matches sig of message +*/ +EDDSA.prototype.verify = function verify(message, sig, pub) { + message = parseBytes(message); + sig = this.makeSignature(sig); + var key = this.keyFromPublic(pub); + var h = this.hashInt(sig.Rencoded(), key.pubBytes(), message); + var SG = this.g.mul(sig.S()); + var RplusAh = sig.R().add(key.pub().mul(h)); + return RplusAh.eq(SG); +}; + +EDDSA.prototype.hashInt = function hashInt() { + var hash = this.hash(); + for (var i = 0; i < arguments.length; i++) + hash.update(arguments[i]); + return utils.intFromLE(hash.digest()).umod(this.curve.n); +}; + +EDDSA.prototype.keyPair = function keyPair(options) { + return new KeyPair(this, options); +}; + +EDDSA.prototype.keyFromPublic = function keyFromPublic(pub) { + return KeyPair.fromPublic(this, pub); +}; + +EDDSA.prototype.keyFromSecret = function keyFromSecret(secret) { + return KeyPair.fromSecret(this, secret); +}; + +EDDSA.prototype.genKeyPair = function genKeyPair(options) { + if (!options) + options = {}; + + // Instantiate Hmac_DRBG + var drbg = new HmacDRBG({ + hash: this.hash, + pers: options.pers, + persEnc: options.persEnc || 'utf8', + entropy: options.entropy || elliptic.rand(this.hash.hmacStrength), + entropyEnc: options.entropy && options.entropyEnc || 'utf8', + nonce: this.curve.n.toArray() + }); + + return this.keyFromSecret(drbg.generate(32)); +}; + +EDDSA.prototype.makeSignature = function makeSignature(sig) { + if (sig instanceof Signature) + return sig; + return new Signature(this, sig); +}; + +/** +* * https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03#section-5.2 +* +* EDDSA defines methods for encoding and decoding points and integers. These are +* helper convenience methods, that pass along to utility functions implied +* parameters. +* +*/ +EDDSA.prototype.encodePoint = function encodePoint(point) { + var enc = point.getY().toArray('le', this.encodingLength); + enc[this.encodingLength - 1] |= point.getX().isOdd() ? 0x80 : 0; + return enc; +}; + +EDDSA.prototype.decodePoint = function decodePoint(bytes) { + bytes = utils.parseBytes(bytes); + + var lastIx = bytes.length - 1; + var normed = bytes.slice(0, lastIx).concat(bytes[lastIx] & ~0x80); + var xIsOdd = (bytes[lastIx] & 0x80) !== 0; + + var y = utils.intFromLE(normed); + return this.curve.pointFromY(y, xIsOdd); +}; + +EDDSA.prototype.encodeInt = function encodeInt(num) { + return num.toArray('le', this.encodingLength); +}; + +EDDSA.prototype.decodeInt = function decodeInt(bytes) { + return utils.intFromLE(bytes); +}; + +EDDSA.prototype.isPoint = function isPoint(val) { + return val instanceof this.pointClass; +}; + +},{"../../elliptic":18,"./key":29,"./signature":30,"hash.js":34,"hmac-drbg":46}],29:[function(require,module,exports){ +'use strict'; + +var elliptic = require('../../elliptic'); +var utils = elliptic.utils; +var assert = utils.assert; +var parseBytes = utils.parseBytes; +var cachedProperty = utils.cachedProperty; + +/** +* @param {EDDSA} eddsa - instance +* @param {Object} params - public/private key parameters +* +* @param {Array} [params.secret] - secret seed bytes +* @param {Point} [params.pub] - public key point (aka `A` in eddsa terms) +* @param {Array} [params.pub] - public key point encoded as bytes +* +*/ +function KeyPair(eddsa, params) { + this.eddsa = eddsa; + if (params.hasOwnProperty('secret')) + this._secret = parseBytes(params.secret); + if (eddsa.isPoint(params.pub)) + this._pub = params.pub; + else { + this._pubBytes = parseBytes(params.pub); + if (this._pubBytes && this._pubBytes.length === 33 && + this._pubBytes[0] === 0x40) + this._pubBytes = this._pubBytes.slice(1, 33); + if (this._pubBytes && this._pubBytes.length !== 32) + throw new Error('Unknown point compression format'); + } +} + +KeyPair.fromPublic = function fromPublic(eddsa, pub) { + if (pub instanceof KeyPair) + return pub; + return new KeyPair(eddsa, { pub: pub }); +}; + +KeyPair.fromSecret = function fromSecret(eddsa, secret) { + if (secret instanceof KeyPair) + return secret; + return new KeyPair(eddsa, { secret: secret }); +}; + +KeyPair.prototype.secret = function secret() { + return this._secret; +}; + +cachedProperty(KeyPair, 'pubBytes', function pubBytes() { + return this.eddsa.encodePoint(this.pub()); +}); + +cachedProperty(KeyPair, 'pub', function pub() { + if (this._pubBytes) + return this.eddsa.decodePoint(this._pubBytes); + return this.eddsa.g.mul(this.priv()); +}); + +cachedProperty(KeyPair, 'privBytes', function privBytes() { + var eddsa = this.eddsa; + var hash = this.hash(); + var lastIx = eddsa.encodingLength - 1; + + // https://tools.ietf.org/html/rfc8032#section-5.1.5 + var a = hash.slice(0, eddsa.encodingLength); + a[0] &= 248; + a[lastIx] &= 127; + a[lastIx] |= 64; + + return a; +}); + +cachedProperty(KeyPair, 'priv', function priv() { + return this.eddsa.decodeInt(this.privBytes()); +}); + +cachedProperty(KeyPair, 'hash', function hash() { + return this.eddsa.hash().update(this.secret()).digest(); +}); + +cachedProperty(KeyPair, 'messagePrefix', function messagePrefix() { + return this.hash().slice(this.eddsa.encodingLength); +}); + +KeyPair.prototype.sign = function sign(message) { + assert(this._secret, 'KeyPair can only verify'); + return this.eddsa.sign(message, this); +}; + +KeyPair.prototype.verify = function verify(message, sig) { + return this.eddsa.verify(message, sig, this); +}; + +KeyPair.prototype.getSecret = function getSecret(enc) { + assert(this._secret, 'KeyPair is public only'); + return utils.encode(this.secret(), enc); +}; + +KeyPair.prototype.getPublic = function getPublic(enc, compact) { + return utils.encode((compact ? [ 0x40 ] : []).concat(this.pubBytes()), enc); +}; + +module.exports = KeyPair; + +},{"../../elliptic":18}],30:[function(require,module,exports){ +'use strict'; + +var BN = require('bn.js'); +var elliptic = require('../../elliptic'); +var utils = elliptic.utils; +var assert = utils.assert; +var cachedProperty = utils.cachedProperty; +var parseBytes = utils.parseBytes; + +/** +* @param {EDDSA} eddsa - eddsa instance +* @param {Array|Object} sig - +* @param {Array|Point} [sig.R] - R point as Point or bytes +* @param {Array|bn} [sig.S] - S scalar as bn or bytes +* @param {Array} [sig.Rencoded] - R point encoded +* @param {Array} [sig.Sencoded] - S scalar encoded +*/ +function Signature(eddsa, sig) { + this.eddsa = eddsa; + + if (typeof sig !== 'object') + sig = parseBytes(sig); + + if (Array.isArray(sig)) { + sig = { + R: sig.slice(0, eddsa.encodingLength), + S: sig.slice(eddsa.encodingLength) + }; + } + + assert(sig.R && sig.S, 'Signature without R or S'); + + if (eddsa.isPoint(sig.R)) + this._R = sig.R; + if (sig.S instanceof BN) + this._S = sig.S; + + this._Rencoded = Array.isArray(sig.R) ? sig.R : sig.Rencoded; + this._Sencoded = Array.isArray(sig.S) ? sig.S : sig.Sencoded; +} + +cachedProperty(Signature, 'S', function S() { + return this.eddsa.decodeInt(this.Sencoded()); +}); + +cachedProperty(Signature, 'R', function R() { + return this.eddsa.decodePoint(this.Rencoded()); +}); + +cachedProperty(Signature, 'Rencoded', function Rencoded() { + return this.eddsa.encodePoint(this.R()); +}); + +cachedProperty(Signature, 'Sencoded', function Sencoded() { + return this.eddsa.encodeInt(this.S()); +}); + +Signature.prototype.toBytes = function toBytes() { + return this.Rencoded().concat(this.Sencoded()); +}; + +Signature.prototype.toHex = function toHex() { + return utils.encode(this.toBytes(), 'hex').toUpperCase(); +}; + +module.exports = Signature; + +},{"../../elliptic":18,"bn.js":16}],31:[function(require,module,exports){ +module.exports = { + doubles: { + step: 4, + points: [ + [ + 'e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a', + 'f7e3507399e595929db99f34f57937101296891e44d23f0be1f32cce69616821' + ], + [ + '8282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508', + '11f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf' + ], + [ + '175e159f728b865a72f99cc6c6fc846de0b93833fd2222ed73fce5b551e5b739', + 'd3506e0d9e3c79eba4ef97a51ff71f5eacb5955add24345c6efa6ffee9fed695' + ], + [ + '363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640', + '4e273adfc732221953b445397f3363145b9a89008199ecb62003c7f3bee9de9' + ], + [ + '8b4b5f165df3c2be8c6244b5b745638843e4a781a15bcd1b69f79a55dffdf80c', + '4aad0a6f68d308b4b3fbd7813ab0da04f9e336546162ee56b3eff0c65fd4fd36' + ], + [ + '723cbaa6e5db996d6bf771c00bd548c7b700dbffa6c0e77bcb6115925232fcda', + '96e867b5595cc498a921137488824d6e2660a0653779494801dc069d9eb39f5f' + ], + [ + 'eebfa4d493bebf98ba5feec812c2d3b50947961237a919839a533eca0e7dd7fa', + '5d9a8ca3970ef0f269ee7edaf178089d9ae4cdc3a711f712ddfd4fdae1de8999' + ], + [ + '100f44da696e71672791d0a09b7bde459f1215a29b3c03bfefd7835b39a48db0', + 'cdd9e13192a00b772ec8f3300c090666b7ff4a18ff5195ac0fbd5cd62bc65a09' + ], + [ + 'e1031be262c7ed1b1dc9227a4a04c017a77f8d4464f3b3852c8acde6e534fd2d', + '9d7061928940405e6bb6a4176597535af292dd419e1ced79a44f18f29456a00d' + ], + [ + 'feea6cae46d55b530ac2839f143bd7ec5cf8b266a41d6af52d5e688d9094696d', + 'e57c6b6c97dce1bab06e4e12bf3ecd5c981c8957cc41442d3155debf18090088' + ], + [ + 'da67a91d91049cdcb367be4be6ffca3cfeed657d808583de33fa978bc1ec6cb1', + '9bacaa35481642bc41f463f7ec9780e5dec7adc508f740a17e9ea8e27a68be1d' + ], + [ + '53904faa0b334cdda6e000935ef22151ec08d0f7bb11069f57545ccc1a37b7c0', + '5bc087d0bc80106d88c9eccac20d3c1c13999981e14434699dcb096b022771c8' + ], + [ + '8e7bcd0bd35983a7719cca7764ca906779b53a043a9b8bcaeff959f43ad86047', + '10b7770b2a3da4b3940310420ca9514579e88e2e47fd68b3ea10047e8460372a' + ], + [ + '385eed34c1cdff21e6d0818689b81bde71a7f4f18397e6690a841e1599c43862', + '283bebc3e8ea23f56701de19e9ebf4576b304eec2086dc8cc0458fe5542e5453' + ], + [ + '6f9d9b803ecf191637c73a4413dfa180fddf84a5947fbc9c606ed86c3fac3a7', + '7c80c68e603059ba69b8e2a30e45c4d47ea4dd2f5c281002d86890603a842160' + ], + [ + '3322d401243c4e2582a2147c104d6ecbf774d163db0f5e5313b7e0e742d0e6bd', + '56e70797e9664ef5bfb019bc4ddaf9b72805f63ea2873af624f3a2e96c28b2a0' + ], + [ + '85672c7d2de0b7da2bd1770d89665868741b3f9af7643397721d74d28134ab83', + '7c481b9b5b43b2eb6374049bfa62c2e5e77f17fcc5298f44c8e3094f790313a6' + ], + [ + '948bf809b1988a46b06c9f1919413b10f9226c60f668832ffd959af60c82a0a', + '53a562856dcb6646dc6b74c5d1c3418c6d4dff08c97cd2bed4cb7f88d8c8e589' + ], + [ + '6260ce7f461801c34f067ce0f02873a8f1b0e44dfc69752accecd819f38fd8e8', + 'bc2da82b6fa5b571a7f09049776a1ef7ecd292238051c198c1a84e95b2b4ae17' + ], + [ + 'e5037de0afc1d8d43d8348414bbf4103043ec8f575bfdc432953cc8d2037fa2d', + '4571534baa94d3b5f9f98d09fb990bddbd5f5b03ec481f10e0e5dc841d755bda' + ], + [ + 'e06372b0f4a207adf5ea905e8f1771b4e7e8dbd1c6a6c5b725866a0ae4fce725', + '7a908974bce18cfe12a27bb2ad5a488cd7484a7787104870b27034f94eee31dd' + ], + [ + '213c7a715cd5d45358d0bbf9dc0ce02204b10bdde2a3f58540ad6908d0559754', + '4b6dad0b5ae462507013ad06245ba190bb4850f5f36a7eeddff2c27534b458f2' + ], + [ + '4e7c272a7af4b34e8dbb9352a5419a87e2838c70adc62cddf0cc3a3b08fbd53c', + '17749c766c9d0b18e16fd09f6def681b530b9614bff7dd33e0b3941817dcaae6' + ], + [ + 'fea74e3dbe778b1b10f238ad61686aa5c76e3db2be43057632427e2840fb27b6', + '6e0568db9b0b13297cf674deccb6af93126b596b973f7b77701d3db7f23cb96f' + ], + [ + '76e64113f677cf0e10a2570d599968d31544e179b760432952c02a4417bdde39', + 'c90ddf8dee4e95cf577066d70681f0d35e2a33d2b56d2032b4b1752d1901ac01' + ], + [ + 'c738c56b03b2abe1e8281baa743f8f9a8f7cc643df26cbee3ab150242bcbb891', + '893fb578951ad2537f718f2eacbfbbbb82314eef7880cfe917e735d9699a84c3' + ], + [ + 'd895626548b65b81e264c7637c972877d1d72e5f3a925014372e9f6588f6c14b', + 'febfaa38f2bc7eae728ec60818c340eb03428d632bb067e179363ed75d7d991f' + ], + [ + 'b8da94032a957518eb0f6433571e8761ceffc73693e84edd49150a564f676e03', + '2804dfa44805a1e4d7c99cc9762808b092cc584d95ff3b511488e4e74efdf6e7' + ], + [ + 'e80fea14441fb33a7d8adab9475d7fab2019effb5156a792f1a11778e3c0df5d', + 'eed1de7f638e00771e89768ca3ca94472d155e80af322ea9fcb4291b6ac9ec78' + ], + [ + 'a301697bdfcd704313ba48e51d567543f2a182031efd6915ddc07bbcc4e16070', + '7370f91cfb67e4f5081809fa25d40f9b1735dbf7c0a11a130c0d1a041e177ea1' + ], + [ + '90ad85b389d6b936463f9d0512678de208cc330b11307fffab7ac63e3fb04ed4', + 'e507a3620a38261affdcbd9427222b839aefabe1582894d991d4d48cb6ef150' + ], + [ + '8f68b9d2f63b5f339239c1ad981f162ee88c5678723ea3351b7b444c9ec4c0da', + '662a9f2dba063986de1d90c2b6be215dbbea2cfe95510bfdf23cbf79501fff82' + ], + [ + 'e4f3fb0176af85d65ff99ff9198c36091f48e86503681e3e6686fd5053231e11', + '1e63633ad0ef4f1c1661a6d0ea02b7286cc7e74ec951d1c9822c38576feb73bc' + ], + [ + '8c00fa9b18ebf331eb961537a45a4266c7034f2f0d4e1d0716fb6eae20eae29e', + 'efa47267fea521a1a9dc343a3736c974c2fadafa81e36c54e7d2a4c66702414b' + ], + [ + 'e7a26ce69dd4829f3e10cec0a9e98ed3143d084f308b92c0997fddfc60cb3e41', + '2a758e300fa7984b471b006a1aafbb18d0a6b2c0420e83e20e8a9421cf2cfd51' + ], + [ + 'b6459e0ee3662ec8d23540c223bcbdc571cbcb967d79424f3cf29eb3de6b80ef', + '67c876d06f3e06de1dadf16e5661db3c4b3ae6d48e35b2ff30bf0b61a71ba45' + ], + [ + 'd68a80c8280bb840793234aa118f06231d6f1fc67e73c5a5deda0f5b496943e8', + 'db8ba9fff4b586d00c4b1f9177b0e28b5b0e7b8f7845295a294c84266b133120' + ], + [ + '324aed7df65c804252dc0270907a30b09612aeb973449cea4095980fc28d3d5d', + '648a365774b61f2ff130c0c35aec1f4f19213b0c7e332843967224af96ab7c84' + ], + [ + '4df9c14919cde61f6d51dfdbe5fee5dceec4143ba8d1ca888e8bd373fd054c96', + '35ec51092d8728050974c23a1d85d4b5d506cdc288490192ebac06cad10d5d' + ], + [ + '9c3919a84a474870faed8a9c1cc66021523489054d7f0308cbfc99c8ac1f98cd', + 'ddb84f0f4a4ddd57584f044bf260e641905326f76c64c8e6be7e5e03d4fc599d' + ], + [ + '6057170b1dd12fdf8de05f281d8e06bb91e1493a8b91d4cc5a21382120a959e5', + '9a1af0b26a6a4807add9a2daf71df262465152bc3ee24c65e899be932385a2a8' + ], + [ + 'a576df8e23a08411421439a4518da31880cef0fba7d4df12b1a6973eecb94266', + '40a6bf20e76640b2c92b97afe58cd82c432e10a7f514d9f3ee8be11ae1b28ec8' + ], + [ + '7778a78c28dec3e30a05fe9629de8c38bb30d1f5cf9a3a208f763889be58ad71', + '34626d9ab5a5b22ff7098e12f2ff580087b38411ff24ac563b513fc1fd9f43ac' + ], + [ + '928955ee637a84463729fd30e7afd2ed5f96274e5ad7e5cb09eda9c06d903ac', + 'c25621003d3f42a827b78a13093a95eeac3d26efa8a8d83fc5180e935bcd091f' + ], + [ + '85d0fef3ec6db109399064f3a0e3b2855645b4a907ad354527aae75163d82751', + '1f03648413a38c0be29d496e582cf5663e8751e96877331582c237a24eb1f962' + ], + [ + 'ff2b0dce97eece97c1c9b6041798b85dfdfb6d8882da20308f5404824526087e', + '493d13fef524ba188af4c4dc54d07936c7b7ed6fb90e2ceb2c951e01f0c29907' + ], + [ + '827fbbe4b1e880ea9ed2b2e6301b212b57f1ee148cd6dd28780e5e2cf856e241', + 'c60f9c923c727b0b71bef2c67d1d12687ff7a63186903166d605b68baec293ec' + ], + [ + 'eaa649f21f51bdbae7be4ae34ce6e5217a58fdce7f47f9aa7f3b58fa2120e2b3', + 'be3279ed5bbbb03ac69a80f89879aa5a01a6b965f13f7e59d47a5305ba5ad93d' + ], + [ + 'e4a42d43c5cf169d9391df6decf42ee541b6d8f0c9a137401e23632dda34d24f', + '4d9f92e716d1c73526fc99ccfb8ad34ce886eedfa8d8e4f13a7f7131deba9414' + ], + [ + '1ec80fef360cbdd954160fadab352b6b92b53576a88fea4947173b9d4300bf19', + 'aeefe93756b5340d2f3a4958a7abbf5e0146e77f6295a07b671cdc1cc107cefd' + ], + [ + '146a778c04670c2f91b00af4680dfa8bce3490717d58ba889ddb5928366642be', + 'b318e0ec3354028add669827f9d4b2870aaa971d2f7e5ed1d0b297483d83efd0' + ], + [ + 'fa50c0f61d22e5f07e3acebb1aa07b128d0012209a28b9776d76a8793180eef9', + '6b84c6922397eba9b72cd2872281a68a5e683293a57a213b38cd8d7d3f4f2811' + ], + [ + 'da1d61d0ca721a11b1a5bf6b7d88e8421a288ab5d5bba5220e53d32b5f067ec2', + '8157f55a7c99306c79c0766161c91e2966a73899d279b48a655fba0f1ad836f1' + ], + [ + 'a8e282ff0c9706907215ff98e8fd416615311de0446f1e062a73b0610d064e13', + '7f97355b8db81c09abfb7f3c5b2515888b679a3e50dd6bd6cef7c73111f4cc0c' + ], + [ + '174a53b9c9a285872d39e56e6913cab15d59b1fa512508c022f382de8319497c', + 'ccc9dc37abfc9c1657b4155f2c47f9e6646b3a1d8cb9854383da13ac079afa73' + ], + [ + '959396981943785c3d3e57edf5018cdbe039e730e4918b3d884fdff09475b7ba', + '2e7e552888c331dd8ba0386a4b9cd6849c653f64c8709385e9b8abf87524f2fd' + ], + [ + 'd2a63a50ae401e56d645a1153b109a8fcca0a43d561fba2dbb51340c9d82b151', + 'e82d86fb6443fcb7565aee58b2948220a70f750af484ca52d4142174dcf89405' + ], + [ + '64587e2335471eb890ee7896d7cfdc866bacbdbd3839317b3436f9b45617e073', + 'd99fcdd5bf6902e2ae96dd6447c299a185b90a39133aeab358299e5e9faf6589' + ], + [ + '8481bde0e4e4d885b3a546d3e549de042f0aa6cea250e7fd358d6c86dd45e458', + '38ee7b8cba5404dd84a25bf39cecb2ca900a79c42b262e556d64b1b59779057e' + ], + [ + '13464a57a78102aa62b6979ae817f4637ffcfed3c4b1ce30bcd6303f6caf666b', + '69be159004614580ef7e433453ccb0ca48f300a81d0942e13f495a907f6ecc27' + ], + [ + 'bc4a9df5b713fe2e9aef430bcc1dc97a0cd9ccede2f28588cada3a0d2d83f366', + 'd3a81ca6e785c06383937adf4b798caa6e8a9fbfa547b16d758d666581f33c1' + ], + [ + '8c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa', + '40a30463a3305193378fedf31f7cc0eb7ae784f0451cb9459e71dc73cbef9482' + ], + [ + '8ea9666139527a8c1dd94ce4f071fd23c8b350c5a4bb33748c4ba111faccae0', + '620efabbc8ee2782e24e7c0cfb95c5d735b783be9cf0f8e955af34a30e62b945' + ], + [ + 'dd3625faef5ba06074669716bbd3788d89bdde815959968092f76cc4eb9a9787', + '7a188fa3520e30d461da2501045731ca941461982883395937f68d00c644a573' + ], + [ + 'f710d79d9eb962297e4f6232b40e8f7feb2bc63814614d692c12de752408221e', + 'ea98e67232d3b3295d3b535532115ccac8612c721851617526ae47a9c77bfc82' + ] + ] + }, + naf: { + wnd: 7, + points: [ + [ + 'f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9', + '388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672' + ], + [ + '2f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4', + 'd8ac222636e5e3d6d4dba9dda6c9c426f788271bab0d6840dca87d3aa6ac62d6' + ], + [ + '5cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc', + '6aebca40ba255960a3178d6d861a54dba813d0b813fde7b5a5082628087264da' + ], + [ + 'acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe', + 'cc338921b0a7d9fd64380971763b61e9add888a4375f8e0f05cc262ac64f9c37' + ], + [ + '774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb', + 'd984a032eb6b5e190243dd56d7b7b365372db1e2dff9d6a8301d74c9c953c61b' + ], + [ + 'f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8', + 'ab0902e8d880a89758212eb65cdaf473a1a06da521fa91f29b5cb52db03ed81' + ], + [ + 'd7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e', + '581e2872a86c72a683842ec228cc6defea40af2bd896d3a5c504dc9ff6a26b58' + ], + [ + 'defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34', + '4211ab0694635168e997b0ead2a93daeced1f4a04a95c0f6cfb199f69e56eb77' + ], + [ + '2b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c', + '85e89bc037945d93b343083b5a1c86131a01f60c50269763b570c854e5c09b7a' + ], + [ + '352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5', + '321eb4075348f534d59c18259dda3e1f4a1b3b2e71b1039c67bd3d8bcf81998c' + ], + [ + '2fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f', + '2de1068295dd865b64569335bd5dd80181d70ecfc882648423ba76b532b7d67' + ], + [ + '9248279b09b4d68dab21a9b066edda83263c3d84e09572e269ca0cd7f5453714', + '73016f7bf234aade5d1aa71bdea2b1ff3fc0de2a887912ffe54a32ce97cb3402' + ], + [ + 'daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729', + 'a69dce4a7d6c98e8d4a1aca87ef8d7003f83c230f3afa726ab40e52290be1c55' + ], + [ + 'c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db', + '2119a460ce326cdc76c45926c982fdac0e106e861edf61c5a039063f0e0e6482' + ], + [ + '6a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4', + 'e022cf42c2bd4a708b3f5126f16a24ad8b33ba48d0423b6efd5e6348100d8a82' + ], + [ + '1697ffa6fd9de627c077e3d2fe541084ce13300b0bec1146f95ae57f0d0bd6a5', + 'b9c398f186806f5d27561506e4557433a2cf15009e498ae7adee9d63d01b2396' + ], + [ + '605bdb019981718b986d0f07e834cb0d9deb8360ffb7f61df982345ef27a7479', + '2972d2de4f8d20681a78d93ec96fe23c26bfae84fb14db43b01e1e9056b8c49' + ], + [ + '62d14dab4150bf497402fdc45a215e10dcb01c354959b10cfe31c7e9d87ff33d', + '80fc06bd8cc5b01098088a1950eed0db01aa132967ab472235f5642483b25eaf' + ], + [ + '80c60ad0040f27dade5b4b06c408e56b2c50e9f56b9b8b425e555c2f86308b6f', + '1c38303f1cc5c30f26e66bad7fe72f70a65eed4cbe7024eb1aa01f56430bd57a' + ], + [ + '7a9375ad6167ad54aa74c6348cc54d344cc5dc9487d847049d5eabb0fa03c8fb', + 'd0e3fa9eca8726909559e0d79269046bdc59ea10c70ce2b02d499ec224dc7f7' + ], + [ + 'd528ecd9b696b54c907a9ed045447a79bb408ec39b68df504bb51f459bc3ffc9', + 'eecf41253136e5f99966f21881fd656ebc4345405c520dbc063465b521409933' + ], + [ + '49370a4b5f43412ea25f514e8ecdad05266115e4a7ecb1387231808f8b45963', + '758f3f41afd6ed428b3081b0512fd62a54c3f3afbb5b6764b653052a12949c9a' + ], + [ + '77f230936ee88cbbd73df930d64702ef881d811e0e1498e2f1c13eb1fc345d74', + '958ef42a7886b6400a08266e9ba1b37896c95330d97077cbbe8eb3c7671c60d6' + ], + [ + 'f2dac991cc4ce4b9ea44887e5c7c0bce58c80074ab9d4dbaeb28531b7739f530', + 'e0dedc9b3b2f8dad4da1f32dec2531df9eb5fbeb0598e4fd1a117dba703a3c37' + ], + [ + '463b3d9f662621fb1b4be8fbbe2520125a216cdfc9dae3debcba4850c690d45b', + '5ed430d78c296c3543114306dd8622d7c622e27c970a1de31cb377b01af7307e' + ], + [ + 'f16f804244e46e2a09232d4aff3b59976b98fac14328a2d1a32496b49998f247', + 'cedabd9b82203f7e13d206fcdf4e33d92a6c53c26e5cce26d6579962c4e31df6' + ], + [ + 'caf754272dc84563b0352b7a14311af55d245315ace27c65369e15f7151d41d1', + 'cb474660ef35f5f2a41b643fa5e460575f4fa9b7962232a5c32f908318a04476' + ], + [ + '2600ca4b282cb986f85d0f1709979d8b44a09c07cb86d7c124497bc86f082120', + '4119b88753c15bd6a693b03fcddbb45d5ac6be74ab5f0ef44b0be9475a7e4b40' + ], + [ + '7635ca72d7e8432c338ec53cd12220bc01c48685e24f7dc8c602a7746998e435', + '91b649609489d613d1d5e590f78e6d74ecfc061d57048bad9e76f302c5b9c61' + ], + [ + '754e3239f325570cdbbf4a87deee8a66b7f2b33479d468fbc1a50743bf56cc18', + '673fb86e5bda30fb3cd0ed304ea49a023ee33d0197a695d0c5d98093c536683' + ], + [ + 'e3e6bd1071a1e96aff57859c82d570f0330800661d1c952f9fe2694691d9b9e8', + '59c9e0bba394e76f40c0aa58379a3cb6a5a2283993e90c4167002af4920e37f5' + ], + [ + '186b483d056a033826ae73d88f732985c4ccb1f32ba35f4b4cc47fdcf04aa6eb', + '3b952d32c67cf77e2e17446e204180ab21fb8090895138b4a4a797f86e80888b' + ], + [ + 'df9d70a6b9876ce544c98561f4be4f725442e6d2b737d9c91a8321724ce0963f', + '55eb2dafd84d6ccd5f862b785dc39d4ab157222720ef9da217b8c45cf2ba2417' + ], + [ + '5edd5cc23c51e87a497ca815d5dce0f8ab52554f849ed8995de64c5f34ce7143', + 'efae9c8dbc14130661e8cec030c89ad0c13c66c0d17a2905cdc706ab7399a868' + ], + [ + '290798c2b6476830da12fe02287e9e777aa3fba1c355b17a722d362f84614fba', + 'e38da76dcd440621988d00bcf79af25d5b29c094db2a23146d003afd41943e7a' + ], + [ + 'af3c423a95d9f5b3054754efa150ac39cd29552fe360257362dfdecef4053b45', + 'f98a3fd831eb2b749a93b0e6f35cfb40c8cd5aa667a15581bc2feded498fd9c6' + ], + [ + '766dbb24d134e745cccaa28c99bf274906bb66b26dcf98df8d2fed50d884249a', + '744b1152eacbe5e38dcc887980da38b897584a65fa06cedd2c924f97cbac5996' + ], + [ + '59dbf46f8c94759ba21277c33784f41645f7b44f6c596a58ce92e666191abe3e', + 'c534ad44175fbc300f4ea6ce648309a042ce739a7919798cd85e216c4a307f6e' + ], + [ + 'f13ada95103c4537305e691e74e9a4a8dd647e711a95e73cb62dc6018cfd87b8', + 'e13817b44ee14de663bf4bc808341f326949e21a6a75c2570778419bdaf5733d' + ], + [ + '7754b4fa0e8aced06d4167a2c59cca4cda1869c06ebadfb6488550015a88522c', + '30e93e864e669d82224b967c3020b8fa8d1e4e350b6cbcc537a48b57841163a2' + ], + [ + '948dcadf5990e048aa3874d46abef9d701858f95de8041d2a6828c99e2262519', + 'e491a42537f6e597d5d28a3224b1bc25df9154efbd2ef1d2cbba2cae5347d57e' + ], + [ + '7962414450c76c1689c7b48f8202ec37fb224cf5ac0bfa1570328a8a3d7c77ab', + '100b610ec4ffb4760d5c1fc133ef6f6b12507a051f04ac5760afa5b29db83437' + ], + [ + '3514087834964b54b15b160644d915485a16977225b8847bb0dd085137ec47ca', + 'ef0afbb2056205448e1652c48e8127fc6039e77c15c2378b7e7d15a0de293311' + ], + [ + 'd3cc30ad6b483e4bc79ce2c9dd8bc54993e947eb8df787b442943d3f7b527eaf', + '8b378a22d827278d89c5e9be8f9508ae3c2ad46290358630afb34db04eede0a4' + ], + [ + '1624d84780732860ce1c78fcbfefe08b2b29823db913f6493975ba0ff4847610', + '68651cf9b6da903e0914448c6cd9d4ca896878f5282be4c8cc06e2a404078575' + ], + [ + '733ce80da955a8a26902c95633e62a985192474b5af207da6df7b4fd5fc61cd4', + 'f5435a2bd2badf7d485a4d8b8db9fcce3e1ef8e0201e4578c54673bc1dc5ea1d' + ], + [ + '15d9441254945064cf1a1c33bbd3b49f8966c5092171e699ef258dfab81c045c', + 'd56eb30b69463e7234f5137b73b84177434800bacebfc685fc37bbe9efe4070d' + ], + [ + 'a1d0fcf2ec9de675b612136e5ce70d271c21417c9d2b8aaaac138599d0717940', + 'edd77f50bcb5a3cab2e90737309667f2641462a54070f3d519212d39c197a629' + ], + [ + 'e22fbe15c0af8ccc5780c0735f84dbe9a790badee8245c06c7ca37331cb36980', + 'a855babad5cd60c88b430a69f53a1a7a38289154964799be43d06d77d31da06' + ], + [ + '311091dd9860e8e20ee13473c1155f5f69635e394704eaa74009452246cfa9b3', + '66db656f87d1f04fffd1f04788c06830871ec5a64feee685bd80f0b1286d8374' + ], + [ + '34c1fd04d301be89b31c0442d3e6ac24883928b45a9340781867d4232ec2dbdf', + '9414685e97b1b5954bd46f730174136d57f1ceeb487443dc5321857ba73abee' + ], + [ + 'f219ea5d6b54701c1c14de5b557eb42a8d13f3abbcd08affcc2a5e6b049b8d63', + '4cb95957e83d40b0f73af4544cccf6b1f4b08d3c07b27fb8d8c2962a400766d1' + ], + [ + 'd7b8740f74a8fbaab1f683db8f45de26543a5490bca627087236912469a0b448', + 'fa77968128d9c92ee1010f337ad4717eff15db5ed3c049b3411e0315eaa4593b' + ], + [ + '32d31c222f8f6f0ef86f7c98d3a3335ead5bcd32abdd94289fe4d3091aa824bf', + '5f3032f5892156e39ccd3d7915b9e1da2e6dac9e6f26e961118d14b8462e1661' + ], + [ + '7461f371914ab32671045a155d9831ea8793d77cd59592c4340f86cbc18347b5', + '8ec0ba238b96bec0cbdddcae0aa442542eee1ff50c986ea6b39847b3cc092ff6' + ], + [ + 'ee079adb1df1860074356a25aa38206a6d716b2c3e67453d287698bad7b2b2d6', + '8dc2412aafe3be5c4c5f37e0ecc5f9f6a446989af04c4e25ebaac479ec1c8c1e' + ], + [ + '16ec93e447ec83f0467b18302ee620f7e65de331874c9dc72bfd8616ba9da6b5', + '5e4631150e62fb40d0e8c2a7ca5804a39d58186a50e497139626778e25b0674d' + ], + [ + 'eaa5f980c245f6f038978290afa70b6bd8855897f98b6aa485b96065d537bd99', + 'f65f5d3e292c2e0819a528391c994624d784869d7e6ea67fb18041024edc07dc' + ], + [ + '78c9407544ac132692ee1910a02439958ae04877151342ea96c4b6b35a49f51', + 'f3e0319169eb9b85d5404795539a5e68fa1fbd583c064d2462b675f194a3ddb4' + ], + [ + '494f4be219a1a77016dcd838431aea0001cdc8ae7a6fc688726578d9702857a5', + '42242a969283a5f339ba7f075e36ba2af925ce30d767ed6e55f4b031880d562c' + ], + [ + 'a598a8030da6d86c6bc7f2f5144ea549d28211ea58faa70ebf4c1e665c1fe9b5', + '204b5d6f84822c307e4b4a7140737aec23fc63b65b35f86a10026dbd2d864e6b' + ], + [ + 'c41916365abb2b5d09192f5f2dbeafec208f020f12570a184dbadc3e58595997', + '4f14351d0087efa49d245b328984989d5caf9450f34bfc0ed16e96b58fa9913' + ], + [ + '841d6063a586fa475a724604da03bc5b92a2e0d2e0a36acfe4c73a5514742881', + '73867f59c0659e81904f9a1c7543698e62562d6744c169ce7a36de01a8d6154' + ], + [ + '5e95bb399a6971d376026947f89bde2f282b33810928be4ded112ac4d70e20d5', + '39f23f366809085beebfc71181313775a99c9aed7d8ba38b161384c746012865' + ], + [ + '36e4641a53948fd476c39f8a99fd974e5ec07564b5315d8bf99471bca0ef2f66', + 'd2424b1b1abe4eb8164227b085c9aa9456ea13493fd563e06fd51cf5694c78fc' + ], + [ + '336581ea7bfbbb290c191a2f507a41cf5643842170e914faeab27c2c579f726', + 'ead12168595fe1be99252129b6e56b3391f7ab1410cd1e0ef3dcdcabd2fda224' + ], + [ + '8ab89816dadfd6b6a1f2634fcf00ec8403781025ed6890c4849742706bd43ede', + '6fdcef09f2f6d0a044e654aef624136f503d459c3e89845858a47a9129cdd24e' + ], + [ + '1e33f1a746c9c5778133344d9299fcaa20b0938e8acff2544bb40284b8c5fb94', + '60660257dd11b3aa9c8ed618d24edff2306d320f1d03010e33a7d2057f3b3b6' + ], + [ + '85b7c1dcb3cec1b7ee7f30ded79dd20a0ed1f4cc18cbcfcfa410361fd8f08f31', + '3d98a9cdd026dd43f39048f25a8847f4fcafad1895d7a633c6fed3c35e999511' + ], + [ + '29df9fbd8d9e46509275f4b125d6d45d7fbe9a3b878a7af872a2800661ac5f51', + 'b4c4fe99c775a606e2d8862179139ffda61dc861c019e55cd2876eb2a27d84b' + ], + [ + 'a0b1cae06b0a847a3fea6e671aaf8adfdfe58ca2f768105c8082b2e449fce252', + 'ae434102edde0958ec4b19d917a6a28e6b72da1834aff0e650f049503a296cf2' + ], + [ + '4e8ceafb9b3e9a136dc7ff67e840295b499dfb3b2133e4ba113f2e4c0e121e5', + 'cf2174118c8b6d7a4b48f6d534ce5c79422c086a63460502b827ce62a326683c' + ], + [ + 'd24a44e047e19b6f5afb81c7ca2f69080a5076689a010919f42725c2b789a33b', + '6fb8d5591b466f8fc63db50f1c0f1c69013f996887b8244d2cdec417afea8fa3' + ], + [ + 'ea01606a7a6c9cdd249fdfcfacb99584001edd28abbab77b5104e98e8e3b35d4', + '322af4908c7312b0cfbfe369f7a7b3cdb7d4494bc2823700cfd652188a3ea98d' + ], + [ + 'af8addbf2b661c8a6c6328655eb96651252007d8c5ea31be4ad196de8ce2131f', + '6749e67c029b85f52a034eafd096836b2520818680e26ac8f3dfbcdb71749700' + ], + [ + 'e3ae1974566ca06cc516d47e0fb165a674a3dabcfca15e722f0e3450f45889', + '2aeabe7e4531510116217f07bf4d07300de97e4874f81f533420a72eeb0bd6a4' + ], + [ + '591ee355313d99721cf6993ffed1e3e301993ff3ed258802075ea8ced397e246', + 'b0ea558a113c30bea60fc4775460c7901ff0b053d25ca2bdeee98f1a4be5d196' + ], + [ + '11396d55fda54c49f19aa97318d8da61fa8584e47b084945077cf03255b52984', + '998c74a8cd45ac01289d5833a7beb4744ff536b01b257be4c5767bea93ea57a4' + ], + [ + '3c5d2a1ba39c5a1790000738c9e0c40b8dcdfd5468754b6405540157e017aa7a', + 'b2284279995a34e2f9d4de7396fc18b80f9b8b9fdd270f6661f79ca4c81bd257' + ], + [ + 'cc8704b8a60a0defa3a99a7299f2e9c3fbc395afb04ac078425ef8a1793cc030', + 'bdd46039feed17881d1e0862db347f8cf395b74fc4bcdc4e940b74e3ac1f1b13' + ], + [ + 'c533e4f7ea8555aacd9777ac5cad29b97dd4defccc53ee7ea204119b2889b197', + '6f0a256bc5efdf429a2fb6242f1a43a2d9b925bb4a4b3a26bb8e0f45eb596096' + ], + [ + 'c14f8f2ccb27d6f109f6d08d03cc96a69ba8c34eec07bbcf566d48e33da6593', + 'c359d6923bb398f7fd4473e16fe1c28475b740dd098075e6c0e8649113dc3a38' + ], + [ + 'a6cbc3046bc6a450bac24789fa17115a4c9739ed75f8f21ce441f72e0b90e6ef', + '21ae7f4680e889bb130619e2c0f95a360ceb573c70603139862afd617fa9b9f' + ], + [ + '347d6d9a02c48927ebfb86c1359b1caf130a3c0267d11ce6344b39f99d43cc38', + '60ea7f61a353524d1c987f6ecec92f086d565ab687870cb12689ff1e31c74448' + ], + [ + 'da6545d2181db8d983f7dcb375ef5866d47c67b1bf31c8cf855ef7437b72656a', + '49b96715ab6878a79e78f07ce5680c5d6673051b4935bd897fea824b77dc208a' + ], + [ + 'c40747cc9d012cb1a13b8148309c6de7ec25d6945d657146b9d5994b8feb1111', + '5ca560753be2a12fc6de6caf2cb489565db936156b9514e1bb5e83037e0fa2d4' + ], + [ + '4e42c8ec82c99798ccf3a610be870e78338c7f713348bd34c8203ef4037f3502', + '7571d74ee5e0fb92a7a8b33a07783341a5492144cc54bcc40a94473693606437' + ], + [ + '3775ab7089bc6af823aba2e1af70b236d251cadb0c86743287522a1b3b0dedea', + 'be52d107bcfa09d8bcb9736a828cfa7fac8db17bf7a76a2c42ad961409018cf7' + ], + [ + 'cee31cbf7e34ec379d94fb814d3d775ad954595d1314ba8846959e3e82f74e26', + '8fd64a14c06b589c26b947ae2bcf6bfa0149ef0be14ed4d80f448a01c43b1c6d' + ], + [ + 'b4f9eaea09b6917619f6ea6a4eb5464efddb58fd45b1ebefcdc1a01d08b47986', + '39e5c9925b5a54b07433a4f18c61726f8bb131c012ca542eb24a8ac07200682a' + ], + [ + 'd4263dfc3d2df923a0179a48966d30ce84e2515afc3dccc1b77907792ebcc60e', + '62dfaf07a0f78feb30e30d6295853ce189e127760ad6cf7fae164e122a208d54' + ], + [ + '48457524820fa65a4f8d35eb6930857c0032acc0a4a2de422233eeda897612c4', + '25a748ab367979d98733c38a1fa1c2e7dc6cc07db2d60a9ae7a76aaa49bd0f77' + ], + [ + 'dfeeef1881101f2cb11644f3a2afdfc2045e19919152923f367a1767c11cceda', + 'ecfb7056cf1de042f9420bab396793c0c390bde74b4bbdff16a83ae09a9a7517' + ], + [ + '6d7ef6b17543f8373c573f44e1f389835d89bcbc6062ced36c82df83b8fae859', + 'cd450ec335438986dfefa10c57fea9bcc521a0959b2d80bbf74b190dca712d10' + ], + [ + 'e75605d59102a5a2684500d3b991f2e3f3c88b93225547035af25af66e04541f', + 'f5c54754a8f71ee540b9b48728473e314f729ac5308b06938360990e2bfad125' + ], + [ + 'eb98660f4c4dfaa06a2be453d5020bc99a0c2e60abe388457dd43fefb1ed620c', + '6cb9a8876d9cb8520609af3add26cd20a0a7cd8a9411131ce85f44100099223e' + ], + [ + '13e87b027d8514d35939f2e6892b19922154596941888336dc3563e3b8dba942', + 'fef5a3c68059a6dec5d624114bf1e91aac2b9da568d6abeb2570d55646b8adf1' + ], + [ + 'ee163026e9fd6fe017c38f06a5be6fc125424b371ce2708e7bf4491691e5764a', + '1acb250f255dd61c43d94ccc670d0f58f49ae3fa15b96623e5430da0ad6c62b2' + ], + [ + 'b268f5ef9ad51e4d78de3a750c2dc89b1e626d43505867999932e5db33af3d80', + '5f310d4b3c99b9ebb19f77d41c1dee018cf0d34fd4191614003e945a1216e423' + ], + [ + 'ff07f3118a9df035e9fad85eb6c7bfe42b02f01ca99ceea3bf7ffdba93c4750d', + '438136d603e858a3a5c440c38eccbaddc1d2942114e2eddd4740d098ced1f0d8' + ], + [ + '8d8b9855c7c052a34146fd20ffb658bea4b9f69e0d825ebec16e8c3ce2b526a1', + 'cdb559eedc2d79f926baf44fb84ea4d44bcf50fee51d7ceb30e2e7f463036758' + ], + [ + '52db0b5384dfbf05bfa9d472d7ae26dfe4b851ceca91b1eba54263180da32b63', + 'c3b997d050ee5d423ebaf66a6db9f57b3180c902875679de924b69d84a7b375' + ], + [ + 'e62f9490d3d51da6395efd24e80919cc7d0f29c3f3fa48c6fff543becbd43352', + '6d89ad7ba4876b0b22c2ca280c682862f342c8591f1daf5170e07bfd9ccafa7d' + ], + [ + '7f30ea2476b399b4957509c88f77d0191afa2ff5cb7b14fd6d8e7d65aaab1193', + 'ca5ef7d4b231c94c3b15389a5f6311e9daff7bb67b103e9880ef4bff637acaec' + ], + [ + '5098ff1e1d9f14fb46a210fada6c903fef0fb7b4a1dd1d9ac60a0361800b7a00', + '9731141d81fc8f8084d37c6e7542006b3ee1b40d60dfe5362a5b132fd17ddc0' + ], + [ + '32b78c7de9ee512a72895be6b9cbefa6e2f3c4ccce445c96b9f2c81e2778ad58', + 'ee1849f513df71e32efc3896ee28260c73bb80547ae2275ba497237794c8753c' + ], + [ + 'e2cb74fddc8e9fbcd076eef2a7c72b0ce37d50f08269dfc074b581550547a4f7', + 'd3aa2ed71c9dd2247a62df062736eb0baddea9e36122d2be8641abcb005cc4a4' + ], + [ + '8438447566d4d7bedadc299496ab357426009a35f235cb141be0d99cd10ae3a8', + 'c4e1020916980a4da5d01ac5e6ad330734ef0d7906631c4f2390426b2edd791f' + ], + [ + '4162d488b89402039b584c6fc6c308870587d9c46f660b878ab65c82c711d67e', + '67163e903236289f776f22c25fb8a3afc1732f2b84b4e95dbda47ae5a0852649' + ], + [ + '3fad3fa84caf0f34f0f89bfd2dcf54fc175d767aec3e50684f3ba4a4bf5f683d', + 'cd1bc7cb6cc407bb2f0ca647c718a730cf71872e7d0d2a53fa20efcdfe61826' + ], + [ + '674f2600a3007a00568c1a7ce05d0816c1fb84bf1370798f1c69532faeb1a86b', + '299d21f9413f33b3edf43b257004580b70db57da0b182259e09eecc69e0d38a5' + ], + [ + 'd32f4da54ade74abb81b815ad1fb3b263d82d6c692714bcff87d29bd5ee9f08f', + 'f9429e738b8e53b968e99016c059707782e14f4535359d582fc416910b3eea87' + ], + [ + '30e4e670435385556e593657135845d36fbb6931f72b08cb1ed954f1e3ce3ff6', + '462f9bce619898638499350113bbc9b10a878d35da70740dc695a559eb88db7b' + ], + [ + 'be2062003c51cc3004682904330e4dee7f3dcd10b01e580bf1971b04d4cad297', + '62188bc49d61e5428573d48a74e1c655b1c61090905682a0d5558ed72dccb9bc' + ], + [ + '93144423ace3451ed29e0fb9ac2af211cb6e84a601df5993c419859fff5df04a', + '7c10dfb164c3425f5c71a3f9d7992038f1065224f72bb9d1d902a6d13037b47c' + ], + [ + 'b015f8044f5fcbdcf21ca26d6c34fb8197829205c7b7d2a7cb66418c157b112c', + 'ab8c1e086d04e813744a655b2df8d5f83b3cdc6faa3088c1d3aea1454e3a1d5f' + ], + [ + 'd5e9e1da649d97d89e4868117a465a3a4f8a18de57a140d36b3f2af341a21b52', + '4cb04437f391ed73111a13cc1d4dd0db1693465c2240480d8955e8592f27447a' + ], + [ + 'd3ae41047dd7ca065dbf8ed77b992439983005cd72e16d6f996a5316d36966bb', + 'bd1aeb21ad22ebb22a10f0303417c6d964f8cdd7df0aca614b10dc14d125ac46' + ], + [ + '463e2763d885f958fc66cdd22800f0a487197d0a82e377b49f80af87c897b065', + 'bfefacdb0e5d0fd7df3a311a94de062b26b80c61fbc97508b79992671ef7ca7f' + ], + [ + '7985fdfd127c0567c6f53ec1bb63ec3158e597c40bfe747c83cddfc910641917', + '603c12daf3d9862ef2b25fe1de289aed24ed291e0ec6708703a5bd567f32ed03' + ], + [ + '74a1ad6b5f76e39db2dd249410eac7f99e74c59cb83d2d0ed5ff1543da7703e9', + 'cc6157ef18c9c63cd6193d83631bbea0093e0968942e8c33d5737fd790e0db08' + ], + [ + '30682a50703375f602d416664ba19b7fc9bab42c72747463a71d0896b22f6da3', + '553e04f6b018b4fa6c8f39e7f311d3176290d0e0f19ca73f17714d9977a22ff8' + ], + [ + '9e2158f0d7c0d5f26c3791efefa79597654e7a2b2464f52b1ee6c1347769ef57', + '712fcdd1b9053f09003a3481fa7762e9ffd7c8ef35a38509e2fbf2629008373' + ], + [ + '176e26989a43c9cfeba4029c202538c28172e566e3c4fce7322857f3be327d66', + 'ed8cc9d04b29eb877d270b4878dc43c19aefd31f4eee09ee7b47834c1fa4b1c3' + ], + [ + '75d46efea3771e6e68abb89a13ad747ecf1892393dfc4f1b7004788c50374da8', + '9852390a99507679fd0b86fd2b39a868d7efc22151346e1a3ca4726586a6bed8' + ], + [ + '809a20c67d64900ffb698c4c825f6d5f2310fb0451c869345b7319f645605721', + '9e994980d9917e22b76b061927fa04143d096ccc54963e6a5ebfa5f3f8e286c1' + ], + [ + '1b38903a43f7f114ed4500b4eac7083fdefece1cf29c63528d563446f972c180', + '4036edc931a60ae889353f77fd53de4a2708b26b6f5da72ad3394119daf408f9' + ] + ] + } +}; + +},{}],32:[function(require,module,exports){ +'use strict'; + +var utils = exports; +var BN = require('bn.js'); +var minAssert = require('minimalistic-assert'); +var minUtils = require('minimalistic-crypto-utils'); + +utils.assert = minAssert; +utils.toArray = minUtils.toArray; +utils.zero2 = minUtils.zero2; +utils.toHex = minUtils.toHex; +utils.encode = minUtils.encode; + +// Represent num in a w-NAF form +function getNAF(num, w) { + var naf = []; + var ws = 1 << (w + 1); + var k = num.clone(); + while (k.cmpn(1) >= 0) { + var z; + if (k.isOdd()) { + var mod = k.andln(ws - 1); + if (mod > (ws >> 1) - 1) + z = (ws >> 1) - mod; + else + z = mod; + k.isubn(z); + } else { + z = 0; + } + naf.push(z); + + // Optimization, shift by word if possible + var shift = (k.cmpn(0) !== 0 && k.andln(ws - 1) === 0) ? (w + 1) : 1; + for (var i = 1; i < shift; i++) + naf.push(0); + k.iushrn(shift); + } + + return naf; +} +utils.getNAF = getNAF; + +// Represent k1, k2 in a Joint Sparse Form +function getJSF(k1, k2) { + var jsf = [ + [], + [] + ]; + + k1 = k1.clone(); + k2 = k2.clone(); + var d1 = 0; + var d2 = 0; + while (k1.cmpn(-d1) > 0 || k2.cmpn(-d2) > 0) { + + // First phase + var m14 = (k1.andln(3) + d1) & 3; + var m24 = (k2.andln(3) + d2) & 3; + if (m14 === 3) + m14 = -1; + if (m24 === 3) + m24 = -1; + var u1; + if ((m14 & 1) === 0) { + u1 = 0; + } else { + var m8 = (k1.andln(7) + d1) & 7; + if ((m8 === 3 || m8 === 5) && m24 === 2) + u1 = -m14; + else + u1 = m14; + } + jsf[0].push(u1); + + var u2; + if ((m24 & 1) === 0) { + u2 = 0; + } else { + var m8 = (k2.andln(7) + d2) & 7; + if ((m8 === 3 || m8 === 5) && m14 === 2) + u2 = -m24; + else + u2 = m24; + } + jsf[1].push(u2); + + // Second phase + if (2 * d1 === u1 + 1) + d1 = 1 - d1; + if (2 * d2 === u2 + 1) + d2 = 1 - d2; + k1.iushrn(1); + k2.iushrn(1); + } + + return jsf; +} +utils.getJSF = getJSF; + +function cachedProperty(obj, name, computer) { + var key = '_' + name; + obj.prototype[name] = function cachedProperty() { + return this[key] !== undefined ? this[key] : + this[key] = computer.call(this); + }; +} +utils.cachedProperty = cachedProperty; + +function parseBytes(bytes) { + return typeof bytes === 'string' ? utils.toArray(bytes, 'hex') : + bytes; +} +utils.parseBytes = parseBytes; + +function intFromLE(bytes) { + return new BN(bytes, 'hex', 'le'); +} +utils.intFromLE = intFromLE; + + +},{"bn.js":16,"minimalistic-assert":48,"minimalistic-crypto-utils":49}],33:[function(require,module,exports){ +"use strict"; + +// email-addresses.js - RFC 5322 email address parser +// v 3.0.3 +// +// http://tools.ietf.org/html/rfc5322 +// +// This library does not validate email addresses. +// emailAddresses attempts to parse addresses using the (fairly liberal) +// grammar specified in RFC 5322. +// +// email-addresses returns { +// ast: , +// addresses: [{ +// node: , +// name: , +// address: , +// local: , +// domain: +// }, ...] +// } +// +// emailAddresses.parseOneAddress and emailAddresses.parseAddressList +// work as you might expect. Try it out. +// +// Many thanks to Dominic Sayers and his documentation on the is_email function, +// http://code.google.com/p/isemail/ , which helped greatly in writing this parser. + +(function (global) { + "use strict"; + + function parse5322(opts) { + + // tokenizing functions + + function inStr() { + return pos < len; + } + function curTok() { + return parseString[pos]; + } + function getPos() { + return pos; + } + function setPos(i) { + pos = i; + } + function nextTok() { + pos += 1; + } + function initialize() { + pos = 0; + len = parseString.length; + } + + // parser helper functions + + function o(name, value) { + return { + name: name, + tokens: value || "", + semantic: value || "", + children: [] + }; + } + + function wrap(name, ast) { + var n; + if (ast === null) { + return null; + } + n = o(name); + n.tokens = ast.tokens; + n.semantic = ast.semantic; + n.children.push(ast); + return n; + } + + function add(parent, child) { + if (child !== null) { + parent.tokens += child.tokens; + parent.semantic += child.semantic; + } + parent.children.push(child); + return parent; + } + + function compareToken(fxnCompare) { + var tok; + if (!inStr()) { + return null; + } + tok = curTok(); + if (fxnCompare(tok)) { + nextTok(); + return o('token', tok); + } + return null; + } + + function literal(lit) { + return function literalFunc() { + return wrap('literal', compareToken(function (tok) { + return tok === lit; + })); + }; + } + + function and() { + var args = arguments; + return function andFunc() { + var i, s, result, start; + start = getPos(); + s = o('and'); + for (i = 0; i < args.length; i += 1) { + result = args[i](); + if (result === null) { + setPos(start); + return null; + } + add(s, result); + } + return s; + }; + } + + function or() { + var args = arguments; + return function orFunc() { + var i, result, start; + start = getPos(); + for (i = 0; i < args.length; i += 1) { + result = args[i](); + if (result !== null) { + return result; + } + setPos(start); + } + return null; + }; + } + + function opt(prod) { + return function optFunc() { + var result, start; + start = getPos(); + result = prod(); + if (result !== null) { + return result; + } else { + setPos(start); + return o('opt'); + } + }; + } + + function invis(prod) { + return function invisFunc() { + var result = prod(); + if (result !== null) { + result.semantic = ""; + } + return result; + }; + } + + function colwsp(prod) { + return function collapseSemanticWhitespace() { + var result = prod(); + if (result !== null && result.semantic.length > 0) { + result.semantic = " "; + } + return result; + }; + } + + function star(prod, minimum) { + return function starFunc() { + var s, result, count, start, min; + start = getPos(); + s = o('star'); + count = 0; + min = minimum === undefined ? 0 : minimum; + while ((result = prod()) !== null) { + count = count + 1; + add(s, result); + } + if (count >= min) { + return s; + } else { + setPos(start); + return null; + } + }; + } + + // One expects names to get normalized like this: + // " First Last " -> "First Last" + // "First Last" -> "First Last" + // "First Last" -> "First Last" + function collapseWhitespace(s) { + return s.replace(/([ \t]|\r\n)+/g, ' ').replace(/^\s*/, '').replace(/\s*$/, ''); + } + + // UTF-8 pseudo-production (RFC 6532) + // RFC 6532 extends RFC 5322 productions to include UTF-8 + // using the following productions: + // UTF8-non-ascii = UTF8-2 / UTF8-3 / UTF8-4 + // UTF8-2 = + // UTF8-3 = + // UTF8-4 = + // + // For reference, the extended RFC 5322 productions are: + // VCHAR =/ UTF8-non-ascii + // ctext =/ UTF8-non-ascii + // atext =/ UTF8-non-ascii + // qtext =/ UTF8-non-ascii + // dtext =/ UTF8-non-ascii + function isUTF8NonAscii(tok) { + // In JavaScript, we just deal directly with Unicode code points, + // so we aren't checking individual bytes for UTF-8 encoding. + // Just check that the character is non-ascii. + return tok.charCodeAt(0) >= 128; + } + + // common productions (RFC 5234) + // http://tools.ietf.org/html/rfc5234 + // B.1. Core Rules + + // CR = %x0D + // ; carriage return + function cr() { + return wrap('cr', literal('\r')()); + } + + // CRLF = CR LF + // ; Internet standard newline + function crlf() { + return wrap('crlf', and(cr, lf)()); + } + + // DQUOTE = %x22 + // ; " (Double Quote) + function dquote() { + return wrap('dquote', literal('"')()); + } + + // HTAB = %x09 + // ; horizontal tab + function htab() { + return wrap('htab', literal('\t')()); + } + + // LF = %x0A + // ; linefeed + function lf() { + return wrap('lf', literal('\n')()); + } + + // SP = %x20 + function sp() { + return wrap('sp', literal(' ')()); + } + + // VCHAR = %x21-7E + // ; visible (printing) characters + function vchar() { + return wrap('vchar', compareToken(function vcharFunc(tok) { + var code = tok.charCodeAt(0); + var accept = 0x21 <= code && code <= 0x7E; + if (opts.rfc6532) { + accept = accept || isUTF8NonAscii(tok); + } + return accept; + })); + } + + // WSP = SP / HTAB + // ; white space + function wsp() { + return wrap('wsp', or(sp, htab)()); + } + + // email productions (RFC 5322) + // http://tools.ietf.org/html/rfc5322 + // 3.2.1. Quoted characters + + // quoted-pair = ("\" (VCHAR / WSP)) / obs-qp + function quotedPair() { + var qp = wrap('quoted-pair', or(and(literal('\\'), or(vchar, wsp)), obsQP)()); + if (qp === null) { + return null; + } + // a quoted pair will be two characters, and the "\" character + // should be semantically "invisible" (RFC 5322 3.2.1) + qp.semantic = qp.semantic[1]; + return qp; + } + + // 3.2.2. Folding White Space and Comments + + // FWS = ([*WSP CRLF] 1*WSP) / obs-FWS + function fws() { + return wrap('fws', or(obsFws, and(opt(and(star(wsp), invis(crlf))), star(wsp, 1)))()); + } + + // ctext = %d33-39 / ; Printable US-ASCII + // %d42-91 / ; characters not including + // %d93-126 / ; "(", ")", or "\" + // obs-ctext + function ctext() { + return wrap('ctext', or(function ctextFunc1() { + return compareToken(function ctextFunc2(tok) { + var code = tok.charCodeAt(0); + var accept = 33 <= code && code <= 39 || 42 <= code && code <= 91 || 93 <= code && code <= 126; + if (opts.rfc6532) { + accept = accept || isUTF8NonAscii(tok); + } + return accept; + }); + }, obsCtext)()); + } + + // ccontent = ctext / quoted-pair / comment + function ccontent() { + return wrap('ccontent', or(ctext, quotedPair, comment)()); + } + + // comment = "(" *([FWS] ccontent) [FWS] ")" + function comment() { + return wrap('comment', and(literal('('), star(and(opt(fws), ccontent)), opt(fws), literal(')'))()); + } + + // CFWS = (1*([FWS] comment) [FWS]) / FWS + function cfws() { + return wrap('cfws', or(and(star(and(opt(fws), comment), 1), opt(fws)), fws)()); + } + + // 3.2.3. Atom + + //atext = ALPHA / DIGIT / ; Printable US-ASCII + // "!" / "#" / ; characters not including + // "$" / "%" / ; specials. Used for atoms. + // "&" / "'" / + // "*" / "+" / + // "-" / "/" / + // "=" / "?" / + // "^" / "_" / + // "`" / "{" / + // "|" / "}" / + // "~" + function atext() { + return wrap('atext', compareToken(function atextFunc(tok) { + var accept = 'a' <= tok && tok <= 'z' || 'A' <= tok && tok <= 'Z' || '0' <= tok && tok <= '9' || ['!', '#', '$', '%', '&', '\'', '*', '+', '-', '/', '=', '?', '^', '_', '`', '{', '|', '}', '~'].indexOf(tok) >= 0; + if (opts.rfc6532) { + accept = accept || isUTF8NonAscii(tok); + } + return accept; + })); + } + + // atom = [CFWS] 1*atext [CFWS] + function atom() { + return wrap('atom', and(colwsp(opt(cfws)), star(atext, 1), colwsp(opt(cfws)))()); + } + + // dot-atom-text = 1*atext *("." 1*atext) + function dotAtomText() { + var s, maybeText; + s = wrap('dot-atom-text', star(atext, 1)()); + if (s === null) { + return s; + } + maybeText = star(and(literal('.'), star(atext, 1)))(); + if (maybeText !== null) { + add(s, maybeText); + } + return s; + } + + // dot-atom = [CFWS] dot-atom-text [CFWS] + function dotAtom() { + return wrap('dot-atom', and(invis(opt(cfws)), dotAtomText, invis(opt(cfws)))()); + } + + // 3.2.4. Quoted Strings + + // qtext = %d33 / ; Printable US-ASCII + // %d35-91 / ; characters not including + // %d93-126 / ; "\" or the quote character + // obs-qtext + function qtext() { + return wrap('qtext', or(function qtextFunc1() { + return compareToken(function qtextFunc2(tok) { + var code = tok.charCodeAt(0); + var accept = 33 === code || 35 <= code && code <= 91 || 93 <= code && code <= 126; + if (opts.rfc6532) { + accept = accept || isUTF8NonAscii(tok); + } + return accept; + }); + }, obsQtext)()); + } + + // qcontent = qtext / quoted-pair + function qcontent() { + return wrap('qcontent', or(qtext, quotedPair)()); + } + + // quoted-string = [CFWS] + // DQUOTE *([FWS] qcontent) [FWS] DQUOTE + // [CFWS] + function quotedString() { + return wrap('quoted-string', and(invis(opt(cfws)), invis(dquote), star(and(opt(colwsp(fws)), qcontent)), opt(invis(fws)), invis(dquote), invis(opt(cfws)))()); + } + + // 3.2.5 Miscellaneous Tokens + + // word = atom / quoted-string + function word() { + return wrap('word', or(atom, quotedString)()); + } + + // phrase = 1*word / obs-phrase + function phrase() { + return wrap('phrase', or(obsPhrase, star(word, 1))()); + } + + // 3.4. Address Specification + // address = mailbox / group + function address() { + return wrap('address', or(mailbox, group)()); + } + + // mailbox = name-addr / addr-spec + function mailbox() { + return wrap('mailbox', or(nameAddr, addrSpec)()); + } + + // name-addr = [display-name] angle-addr + function nameAddr() { + return wrap('name-addr', and(opt(displayName), angleAddr)()); + } + + // angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / + // obs-angle-addr + function angleAddr() { + return wrap('angle-addr', or(and(invis(opt(cfws)), literal('<'), addrSpec, literal('>'), invis(opt(cfws))), obsAngleAddr)()); + } + + // group = display-name ":" [group-list] ";" [CFWS] + function group() { + return wrap('group', and(displayName, literal(':'), opt(groupList), literal(';'), invis(opt(cfws)))()); + } + + // display-name = phrase + function displayName() { + return wrap('display-name', function phraseFixedSemantic() { + var result = phrase(); + if (result !== null) { + result.semantic = collapseWhitespace(result.semantic); + } + return result; + }()); + } + + // mailbox-list = (mailbox *("," mailbox)) / obs-mbox-list + function mailboxList() { + return wrap('mailbox-list', or(and(mailbox, star(and(literal(','), mailbox))), obsMboxList)()); + } + + // address-list = (address *("," address)) / obs-addr-list + function addressList() { + return wrap('address-list', or(and(address, star(and(literal(','), address))), obsAddrList)()); + } + + // group-list = mailbox-list / CFWS / obs-group-list + function groupList() { + return wrap('group-list', or(mailboxList, invis(cfws), obsGroupList)()); + } + + // 3.4.1 Addr-Spec Specification + + // local-part = dot-atom / quoted-string / obs-local-part + function localPart() { + // note: quoted-string, dotAtom are proper subsets of obs-local-part + // so we really just have to look for obsLocalPart, if we don't care about the exact parse tree + return wrap('local-part', or(obsLocalPart, dotAtom, quotedString)()); + } + + // dtext = %d33-90 / ; Printable US-ASCII + // %d94-126 / ; characters not including + // obs-dtext ; "[", "]", or "\" + function dtext() { + return wrap('dtext', or(function dtextFunc1() { + return compareToken(function dtextFunc2(tok) { + var code = tok.charCodeAt(0); + var accept = 33 <= code && code <= 90 || 94 <= code && code <= 126; + if (opts.rfc6532) { + accept = accept || isUTF8NonAscii(tok); + } + return accept; + }); + }, obsDtext)()); + } + + // domain-literal = [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS] + function domainLiteral() { + return wrap('domain-literal', and(invis(opt(cfws)), literal('['), star(and(opt(fws), dtext)), opt(fws), literal(']'), invis(opt(cfws)))()); + } + + // domain = dot-atom / domain-literal / obs-domain + function domain() { + return wrap('domain', function domainCheckTLD() { + var result = or(obsDomain, dotAtom, domainLiteral)(); + if (opts.rejectTLD) { + if (result && result.semantic && result.semantic.indexOf('.') < 0) { + return null; + } + } + // strip all whitespace from domains + if (result) { + result.semantic = result.semantic.replace(/\s+/g, ''); + } + return result; + }()); + } + + // addr-spec = local-part "@" domain + function addrSpec() { + return wrap('addr-spec', and(localPart, literal('@'), domain)()); + } + + // 3.6.2 Originator Fields + // Below we only parse the field body, not the name of the field + // like "From:", "Sender:", or "Reply-To:". Other libraries that + // parse email headers can parse those and defer to these productions + // for the "RFC 5322" part. + + // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields + // from = "From:" (mailbox-list / address-list) CRLF + function fromSpec() { + return wrap('from', or(mailboxList, addressList)()); + } + + // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields + // sender = "Sender:" (mailbox / address) CRLF + function senderSpec() { + return wrap('sender', or(mailbox, address)()); + } + + // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields + // reply-to = "Reply-To:" address-list CRLF + function replyToSpec() { + return wrap('reply-to', addressList()); + } + + // 4.1. Miscellaneous Obsolete Tokens + + // obs-NO-WS-CTL = %d1-8 / ; US-ASCII control + // %d11 / ; characters that do not + // %d12 / ; include the carriage + // %d14-31 / ; return, line feed, and + // %d127 ; white space characters + function obsNoWsCtl() { + return opts.strict ? null : wrap('obs-NO-WS-CTL', compareToken(function (tok) { + var code = tok.charCodeAt(0); + return 1 <= code && code <= 8 || 11 === code || 12 === code || 14 <= code && code <= 31 || 127 === code; + })); + } + + // obs-ctext = obs-NO-WS-CTL + function obsCtext() { + return opts.strict ? null : wrap('obs-ctext', obsNoWsCtl()); + } + + // obs-qtext = obs-NO-WS-CTL + function obsQtext() { + return opts.strict ? null : wrap('obs-qtext', obsNoWsCtl()); + } + + // obs-qp = "\" (%d0 / obs-NO-WS-CTL / LF / CR) + function obsQP() { + return opts.strict ? null : wrap('obs-qp', and(literal('\\'), or(literal('\0'), obsNoWsCtl, lf, cr))()); + } + + // obs-phrase = word *(word / "." / CFWS) + function obsPhrase() { + return opts.strict ? null : wrap('obs-phrase', and(word, star(or(word, literal('.'), literal('@'), colwsp(cfws))))()); + } + + // 4.2. Obsolete Folding White Space + + // NOTE: read the errata http://www.rfc-editor.org/errata_search.php?rfc=5322&eid=1908 + // obs-FWS = 1*([CRLF] WSP) + function obsFws() { + return opts.strict ? null : wrap('obs-FWS', star(and(invis(opt(crlf)), wsp), 1)()); + } + + // 4.4. Obsolete Addressing + + // obs-angle-addr = [CFWS] "<" obs-route addr-spec ">" [CFWS] + function obsAngleAddr() { + return opts.strict ? null : wrap('obs-angle-addr', and(invis(opt(cfws)), literal('<'), obsRoute, addrSpec, literal('>'), invis(opt(cfws)))()); + } + + // obs-route = obs-domain-list ":" + function obsRoute() { + return opts.strict ? null : wrap('obs-route', and(obsDomainList, literal(':'))()); + } + + // obs-domain-list = *(CFWS / ",") "@" domain + // *("," [CFWS] ["@" domain]) + function obsDomainList() { + return opts.strict ? null : wrap('obs-domain-list', and(star(or(invis(cfws), literal(','))), literal('@'), domain, star(and(literal(','), invis(opt(cfws)), opt(and(literal('@'), domain)))))()); + } + + // obs-mbox-list = *([CFWS] ",") mailbox *("," [mailbox / CFWS]) + function obsMboxList() { + return opts.strict ? null : wrap('obs-mbox-list', and(star(and(invis(opt(cfws)), literal(','))), mailbox, star(and(literal(','), opt(and(mailbox, invis(cfws))))))()); + } + + // obs-addr-list = *([CFWS] ",") address *("," [address / CFWS]) + function obsAddrList() { + return opts.strict ? null : wrap('obs-addr-list', and(star(and(invis(opt(cfws)), literal(','))), address, star(and(literal(','), opt(and(address, invis(cfws))))))()); + } + + // obs-group-list = 1*([CFWS] ",") [CFWS] + function obsGroupList() { + return opts.strict ? null : wrap('obs-group-list', and(star(and(invis(opt(cfws)), literal(',')), 1), invis(opt(cfws)))()); + } + + // obs-local-part = word *("." word) + function obsLocalPart() { + return opts.strict ? null : wrap('obs-local-part', and(word, star(and(literal('.'), word)))()); + } + + // obs-domain = atom *("." atom) + function obsDomain() { + return opts.strict ? null : wrap('obs-domain', and(atom, star(and(literal('.'), atom)))()); + } + + // obs-dtext = obs-NO-WS-CTL / quoted-pair + function obsDtext() { + return opts.strict ? null : wrap('obs-dtext', or(obsNoWsCtl, quotedPair)()); + } + + ///////////////////////////////////////////////////// + + // ast analysis + + function findNode(name, root) { + var i, stack, node; + if (root === null || root === undefined) { + return null; + } + stack = [root]; + while (stack.length > 0) { + node = stack.pop(); + if (node.name === name) { + return node; + } + for (i = node.children.length - 1; i >= 0; i -= 1) { + stack.push(node.children[i]); + } + } + return null; + } + + function findAllNodes(name, root) { + var i, stack, node, result; + if (root === null || root === undefined) { + return null; + } + stack = [root]; + result = []; + while (stack.length > 0) { + node = stack.pop(); + if (node.name === name) { + result.push(node); + } + for (i = node.children.length - 1; i >= 0; i -= 1) { + stack.push(node.children[i]); + } + } + return result; + } + + function findAllNodesNoChildren(names, root) { + var i, stack, node, result, namesLookup; + if (root === null || root === undefined) { + return null; + } + stack = [root]; + result = []; + namesLookup = {}; + for (i = 0; i < names.length; i += 1) { + namesLookup[names[i]] = true; + } + + while (stack.length > 0) { + node = stack.pop(); + if (node.name in namesLookup) { + result.push(node); + // don't look at children (hence findAllNodesNoChildren) + } else { + for (i = node.children.length - 1; i >= 0; i -= 1) { + stack.push(node.children[i]); + } + } + } + return result; + } + + function giveResult(ast) { + var addresses, groupsAndMailboxes, i, groupOrMailbox, result; + if (ast === null) { + return null; + } + addresses = []; + + // An address is a 'group' (i.e. a list of mailboxes) or a 'mailbox'. + groupsAndMailboxes = findAllNodesNoChildren(['group', 'mailbox'], ast); + for (i = 0; i < groupsAndMailboxes.length; i += 1) { + groupOrMailbox = groupsAndMailboxes[i]; + if (groupOrMailbox.name === 'group') { + addresses.push(giveResultGroup(groupOrMailbox)); + } else if (groupOrMailbox.name === 'mailbox') { + addresses.push(giveResultMailbox(groupOrMailbox)); + } + } + + result = { + ast: ast, + addresses: addresses + }; + if (opts.simple) { + result = simplifyResult(result); + } + if (opts.oneResult) { + return oneResult(result); + } + if (opts.simple) { + return result && result.addresses; + } else { + return result; + } + } + + function giveResultGroup(group) { + var i; + var groupName = findNode('display-name', group); + var groupResultMailboxes = []; + var mailboxes = findAllNodesNoChildren(['mailbox'], group); + for (i = 0; i < mailboxes.length; i += 1) { + groupResultMailboxes.push(giveResultMailbox(mailboxes[i])); + } + return { + node: group, + parts: { + name: groupName + }, + type: group.name, // 'group' + name: grabSemantic(groupName), + addresses: groupResultMailboxes + }; + } + + function giveResultMailbox(mailbox) { + var name = findNode('display-name', mailbox); + var aspec = findNode('addr-spec', mailbox); + var comments = findAllNodesNoChildren(['comment'], mailbox); + + var local = findNode('local-part', aspec); + var domain = findNode('domain', aspec); + return { + node: mailbox, + parts: { + name: name, + address: aspec, + local: local, + domain: domain, + comments: comments + }, + type: mailbox.name, // 'mailbox' + name: grabSemantic(name), + address: grabSemantic(aspec), + local: grabSemantic(local), + domain: grabSemantic(domain), + comments: concatComments(comments), + groupName: grabSemantic(mailbox.groupName) + }; + } + + function grabSemantic(n) { + return n !== null && n !== undefined ? n.semantic : null; + } + + function simplifyResult(result) { + var i; + if (result && result.addresses) { + for (i = 0; i < result.addresses.length; i += 1) { + delete result.addresses[i].node; + } + } + return result; + } + + function concatComments(comments) { + let result = ''; + if (comments) { + for (let i = 0; i < comments.length; i += 1) { + result += grabSemantic(comments[i]); + } + } + return result; + } + + function oneResult(result) { + if (!result) { + return null; + } + if (!opts.partial && result.addresses.length > 1) { + return null; + } + return result.addresses && result.addresses[0]; + } + + ///////////////////////////////////////////////////// + + var parseString, pos, len, parsed, startProduction; + + opts = handleOpts(opts, {}); + if (opts === null) { + return null; + } + + parseString = opts.input; + + startProduction = { + 'address': address, + 'address-list': addressList, + 'angle-addr': angleAddr, + 'from': fromSpec, + 'group': group, + 'mailbox': mailbox, + 'mailbox-list': mailboxList, + 'reply-to': replyToSpec, + 'sender': senderSpec + }[opts.startAt] || addressList; + + if (!opts.strict) { + initialize(); + opts.strict = true; + parsed = startProduction(parseString); + if (opts.partial || !inStr()) { + return giveResult(parsed); + } + opts.strict = false; + } + + initialize(); + parsed = startProduction(parseString); + if (!opts.partial && inStr()) { + return null; + } + return giveResult(parsed); + } + + function parseOneAddressSimple(opts) { + return parse5322(handleOpts(opts, { + oneResult: true, + rfc6532: true, + simple: true, + startAt: 'address-list' + })); + } + + function parseAddressListSimple(opts) { + return parse5322(handleOpts(opts, { + rfc6532: true, + simple: true, + startAt: 'address-list' + })); + } + + function parseFromSimple(opts) { + return parse5322(handleOpts(opts, { + rfc6532: true, + simple: true, + startAt: 'from' + })); + } + + function parseSenderSimple(opts) { + return parse5322(handleOpts(opts, { + oneResult: true, + rfc6532: true, + simple: true, + startAt: 'sender' + })); + } + + function parseReplyToSimple(opts) { + return parse5322(handleOpts(opts, { + rfc6532: true, + simple: true, + startAt: 'reply-to' + })); + } + + function handleOpts(opts, defs) { + function isString(str) { + return Object.prototype.toString.call(str) === '[object String]'; + } + + function isObject(o) { + return o === Object(o); + } + + function isNullUndef(o) { + return o === null || o === undefined; + } + + var defaults, o; + + if (isString(opts)) { + opts = { input: opts }; + } else if (!isObject(opts)) { + return null; + } + + if (!isString(opts.input)) { + return null; + } + if (!defs) { + return null; + } + + defaults = { + oneResult: false, + partial: false, + rejectTLD: false, + rfc6532: false, + simple: false, + startAt: 'address-list', + strict: false + }; + + for (o in defaults) { + if (isNullUndef(opts[o])) { + opts[o] = !isNullUndef(defs[o]) ? defs[o] : defaults[o]; + } + } + return opts; + } + + parse5322.parseOneAddress = parseOneAddressSimple; + parse5322.parseAddressList = parseAddressListSimple; + parse5322.parseFrom = parseFromSimple; + parse5322.parseSender = parseSenderSimple; + parse5322.parseReplyTo = parseReplyToSimple; + + if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = parse5322; + } else { + global.emailAddresses = parse5322; + } +})(undefined); + +},{}],34:[function(require,module,exports){ +var hash = exports; + +hash.utils = require('./hash/utils'); +hash.common = require('./hash/common'); +hash.sha = require('./hash/sha'); +hash.ripemd = require('./hash/ripemd'); +hash.hmac = require('./hash/hmac'); + +// Proxy hash functions to the main object +hash.sha1 = hash.sha.sha1; +hash.sha256 = hash.sha.sha256; +hash.sha224 = hash.sha.sha224; +hash.sha384 = hash.sha.sha384; +hash.sha512 = hash.sha.sha512; +hash.ripemd160 = hash.ripemd.ripemd160; + +},{"./hash/common":35,"./hash/hmac":36,"./hash/ripemd":37,"./hash/sha":38,"./hash/utils":45}],35:[function(require,module,exports){ +'use strict'; + +var utils = require('./utils'); +var assert = require('minimalistic-assert'); + +function BlockHash() { + this.pending = null; + this.pendingTotal = 0; + this.blockSize = this.constructor.blockSize; + this.outSize = this.constructor.outSize; + this.hmacStrength = this.constructor.hmacStrength; + this.padLength = this.constructor.padLength / 8; + this.endian = 'big'; + + this._delta8 = this.blockSize / 8; + this._delta32 = this.blockSize / 32; +} +exports.BlockHash = BlockHash; + +BlockHash.prototype.update = function update(msg, enc) { + // Convert message to array, pad it, and join into 32bit blocks + msg = utils.toArray(msg, enc); + if (!this.pending) + this.pending = msg; + else + this.pending = this.pending.concat(msg); + this.pendingTotal += msg.length; + + // Enough data, try updating + if (this.pending.length >= this._delta8) { + msg = this.pending; + + // Process pending data in blocks + var r = msg.length % this._delta8; + this.pending = msg.slice(msg.length - r, msg.length); + if (this.pending.length === 0) + this.pending = null; + + msg = utils.join32(msg, 0, msg.length - r, this.endian); + for (var i = 0; i < msg.length; i += this._delta32) + this._update(msg, i, i + this._delta32); + } + + return this; +}; + +BlockHash.prototype.digest = function digest(enc) { + this.update(this._pad()); + assert(this.pending === null); + + return this._digest(enc); +}; + +BlockHash.prototype._pad = function pad() { + var len = this.pendingTotal; + var bytes = this._delta8; + var k = bytes - ((len + this.padLength) % bytes); + var res = new Array(k + this.padLength); + res[0] = 0x80; + for (var i = 1; i < k; i++) + res[i] = 0; + + // Append length + len <<= 3; + if (this.endian === 'big') { + for (var t = 8; t < this.padLength; t++) + res[i++] = 0; + + res[i++] = 0; + res[i++] = 0; + res[i++] = 0; + res[i++] = 0; + res[i++] = (len >>> 24) & 0xff; + res[i++] = (len >>> 16) & 0xff; + res[i++] = (len >>> 8) & 0xff; + res[i++] = len & 0xff; + } else { + res[i++] = len & 0xff; + res[i++] = (len >>> 8) & 0xff; + res[i++] = (len >>> 16) & 0xff; + res[i++] = (len >>> 24) & 0xff; + res[i++] = 0; + res[i++] = 0; + res[i++] = 0; + res[i++] = 0; + + for (t = 8; t < this.padLength; t++) + res[i++] = 0; + } + + return res; +}; + +},{"./utils":45,"minimalistic-assert":48}],36:[function(require,module,exports){ +'use strict'; + +var utils = require('./utils'); +var assert = require('minimalistic-assert'); + +function Hmac(hash, key, enc) { + if (!(this instanceof Hmac)) + return new Hmac(hash, key, enc); + this.Hash = hash; + this.blockSize = hash.blockSize / 8; + this.outSize = hash.outSize / 8; + this.inner = null; + this.outer = null; + + this._init(utils.toArray(key, enc)); +} +module.exports = Hmac; + +Hmac.prototype._init = function init(key) { + // Shorten key, if needed + if (key.length > this.blockSize) + key = new this.Hash().update(key).digest(); + assert(key.length <= this.blockSize); + + // Add padding to key + for (var i = key.length; i < this.blockSize; i++) + key.push(0); + + for (i = 0; i < key.length; i++) + key[i] ^= 0x36; + this.inner = new this.Hash().update(key); + + // 0x36 ^ 0x5c = 0x6a + for (i = 0; i < key.length; i++) + key[i] ^= 0x6a; + this.outer = new this.Hash().update(key); +}; + +Hmac.prototype.update = function update(msg, enc) { + this.inner.update(msg, enc); + return this; +}; + +Hmac.prototype.digest = function digest(enc) { + this.outer.update(this.inner.digest()); + return this.outer.digest(enc); +}; + +},{"./utils":45,"minimalistic-assert":48}],37:[function(require,module,exports){ +'use strict'; + +var utils = require('./utils'); +var common = require('./common'); + +var rotl32 = utils.rotl32; +var sum32 = utils.sum32; +var sum32_3 = utils.sum32_3; +var sum32_4 = utils.sum32_4; +var BlockHash = common.BlockHash; + +function RIPEMD160() { + if (!(this instanceof RIPEMD160)) + return new RIPEMD160(); + + BlockHash.call(this); + + this.h = [ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 ]; + this.endian = 'little'; +} +utils.inherits(RIPEMD160, BlockHash); +exports.ripemd160 = RIPEMD160; + +RIPEMD160.blockSize = 512; +RIPEMD160.outSize = 160; +RIPEMD160.hmacStrength = 192; +RIPEMD160.padLength = 64; + +RIPEMD160.prototype._update = function update(msg, start) { + var A = this.h[0]; + var B = this.h[1]; + var C = this.h[2]; + var D = this.h[3]; + var E = this.h[4]; + var Ah = A; + var Bh = B; + var Ch = C; + var Dh = D; + var Eh = E; + for (var j = 0; j < 80; j++) { + var T = sum32( + rotl32( + sum32_4(A, f(j, B, C, D), msg[r[j] + start], K(j)), + s[j]), + E); + A = E; + E = D; + D = rotl32(C, 10); + C = B; + B = T; + T = sum32( + rotl32( + sum32_4(Ah, f(79 - j, Bh, Ch, Dh), msg[rh[j] + start], Kh(j)), + sh[j]), + Eh); + Ah = Eh; + Eh = Dh; + Dh = rotl32(Ch, 10); + Ch = Bh; + Bh = T; + } + T = sum32_3(this.h[1], C, Dh); + this.h[1] = sum32_3(this.h[2], D, Eh); + this.h[2] = sum32_3(this.h[3], E, Ah); + this.h[3] = sum32_3(this.h[4], A, Bh); + this.h[4] = sum32_3(this.h[0], B, Ch); + this.h[0] = T; +}; + +RIPEMD160.prototype._digest = function digest(enc) { + if (enc === 'hex') + return utils.toHex32(this.h, 'little'); + else + return utils.split32(this.h, 'little'); +}; + +function f(j, x, y, z) { + if (j <= 15) + return x ^ y ^ z; + else if (j <= 31) + return (x & y) | ((~x) & z); + else if (j <= 47) + return (x | (~y)) ^ z; + else if (j <= 63) + return (x & z) | (y & (~z)); + else + return x ^ (y | (~z)); +} + +function K(j) { + if (j <= 15) + return 0x00000000; + else if (j <= 31) + return 0x5a827999; + else if (j <= 47) + return 0x6ed9eba1; + else if (j <= 63) + return 0x8f1bbcdc; + else + return 0xa953fd4e; +} + +function Kh(j) { + if (j <= 15) + return 0x50a28be6; + else if (j <= 31) + return 0x5c4dd124; + else if (j <= 47) + return 0x6d703ef3; + else if (j <= 63) + return 0x7a6d76e9; + else + return 0x00000000; +} + +var r = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, + 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, + 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, + 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 +]; + +var rh = [ + 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, + 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, + 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, + 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, + 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 +]; + +var s = [ + 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, + 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, + 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, + 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, + 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 +]; + +var sh = [ + 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, + 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, + 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, + 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, + 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 +]; + +},{"./common":35,"./utils":45}],38:[function(require,module,exports){ +'use strict'; + +exports.sha1 = require('./sha/1'); +exports.sha224 = require('./sha/224'); +exports.sha256 = require('./sha/256'); +exports.sha384 = require('./sha/384'); +exports.sha512 = require('./sha/512'); + +},{"./sha/1":39,"./sha/224":40,"./sha/256":41,"./sha/384":42,"./sha/512":43}],39:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var common = require('../common'); +var shaCommon = require('./common'); + +var rotl32 = utils.rotl32; +var sum32 = utils.sum32; +var sum32_5 = utils.sum32_5; +var ft_1 = shaCommon.ft_1; +var BlockHash = common.BlockHash; + +var sha1_K = [ + 0x5A827999, 0x6ED9EBA1, + 0x8F1BBCDC, 0xCA62C1D6 +]; + +function SHA1() { + if (!(this instanceof SHA1)) + return new SHA1(); + + BlockHash.call(this); + this.h = [ + 0x67452301, 0xefcdab89, 0x98badcfe, + 0x10325476, 0xc3d2e1f0 ]; + this.W = new Array(80); +} + +utils.inherits(SHA1, BlockHash); +module.exports = SHA1; + +SHA1.blockSize = 512; +SHA1.outSize = 160; +SHA1.hmacStrength = 80; +SHA1.padLength = 64; + +SHA1.prototype._update = function _update(msg, start) { + var W = this.W; + + for (var i = 0; i < 16; i++) + W[i] = msg[start + i]; + + for(; i < W.length; i++) + W[i] = rotl32(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1); + + var a = this.h[0]; + var b = this.h[1]; + var c = this.h[2]; + var d = this.h[3]; + var e = this.h[4]; + + for (i = 0; i < W.length; i++) { + var s = ~~(i / 20); + var t = sum32_5(rotl32(a, 5), ft_1(s, b, c, d), e, W[i], sha1_K[s]); + e = d; + d = c; + c = rotl32(b, 30); + b = a; + a = t; + } + + this.h[0] = sum32(this.h[0], a); + this.h[1] = sum32(this.h[1], b); + this.h[2] = sum32(this.h[2], c); + this.h[3] = sum32(this.h[3], d); + this.h[4] = sum32(this.h[4], e); +}; + +SHA1.prototype._digest = function digest(enc) { + if (enc === 'hex') + return utils.toHex32(this.h, 'big'); + else + return utils.split32(this.h, 'big'); +}; + +},{"../common":35,"../utils":45,"./common":44}],40:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var SHA256 = require('./256'); + +function SHA224() { + if (!(this instanceof SHA224)) + return new SHA224(); + + SHA256.call(this); + this.h = [ + 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, + 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 ]; +} +utils.inherits(SHA224, SHA256); +module.exports = SHA224; + +SHA224.blockSize = 512; +SHA224.outSize = 224; +SHA224.hmacStrength = 192; +SHA224.padLength = 64; + +SHA224.prototype._digest = function digest(enc) { + // Just truncate output + if (enc === 'hex') + return utils.toHex32(this.h.slice(0, 7), 'big'); + else + return utils.split32(this.h.slice(0, 7), 'big'); +}; + + +},{"../utils":45,"./256":41}],41:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var common = require('../common'); +var shaCommon = require('./common'); +var assert = require('minimalistic-assert'); + +var sum32 = utils.sum32; +var sum32_4 = utils.sum32_4; +var sum32_5 = utils.sum32_5; +var ch32 = shaCommon.ch32; +var maj32 = shaCommon.maj32; +var s0_256 = shaCommon.s0_256; +var s1_256 = shaCommon.s1_256; +var g0_256 = shaCommon.g0_256; +var g1_256 = shaCommon.g1_256; + +var BlockHash = common.BlockHash; + +var sha256_K = [ + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +]; + +function SHA256() { + if (!(this instanceof SHA256)) + return new SHA256(); + + BlockHash.call(this); + this.h = [ + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 + ]; + this.k = sha256_K; + this.W = new Array(64); +} +utils.inherits(SHA256, BlockHash); +module.exports = SHA256; + +SHA256.blockSize = 512; +SHA256.outSize = 256; +SHA256.hmacStrength = 192; +SHA256.padLength = 64; + +SHA256.prototype._update = function _update(msg, start) { + var W = this.W; + + for (var i = 0; i < 16; i++) + W[i] = msg[start + i]; + for (; i < W.length; i++) + W[i] = sum32_4(g1_256(W[i - 2]), W[i - 7], g0_256(W[i - 15]), W[i - 16]); + + var a = this.h[0]; + var b = this.h[1]; + var c = this.h[2]; + var d = this.h[3]; + var e = this.h[4]; + var f = this.h[5]; + var g = this.h[6]; + var h = this.h[7]; + + assert(this.k.length === W.length); + for (i = 0; i < W.length; i++) { + var T1 = sum32_5(h, s1_256(e), ch32(e, f, g), this.k[i], W[i]); + var T2 = sum32(s0_256(a), maj32(a, b, c)); + h = g; + g = f; + f = e; + e = sum32(d, T1); + d = c; + c = b; + b = a; + a = sum32(T1, T2); + } + + this.h[0] = sum32(this.h[0], a); + this.h[1] = sum32(this.h[1], b); + this.h[2] = sum32(this.h[2], c); + this.h[3] = sum32(this.h[3], d); + this.h[4] = sum32(this.h[4], e); + this.h[5] = sum32(this.h[5], f); + this.h[6] = sum32(this.h[6], g); + this.h[7] = sum32(this.h[7], h); +}; + +SHA256.prototype._digest = function digest(enc) { + if (enc === 'hex') + return utils.toHex32(this.h, 'big'); + else + return utils.split32(this.h, 'big'); +}; + +},{"../common":35,"../utils":45,"./common":44,"minimalistic-assert":48}],42:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); + +var SHA512 = require('./512'); + +function SHA384() { + if (!(this instanceof SHA384)) + return new SHA384(); + + SHA512.call(this); + this.h = [ + 0xcbbb9d5d, 0xc1059ed8, + 0x629a292a, 0x367cd507, + 0x9159015a, 0x3070dd17, + 0x152fecd8, 0xf70e5939, + 0x67332667, 0xffc00b31, + 0x8eb44a87, 0x68581511, + 0xdb0c2e0d, 0x64f98fa7, + 0x47b5481d, 0xbefa4fa4 ]; +} +utils.inherits(SHA384, SHA512); +module.exports = SHA384; + +SHA384.blockSize = 1024; +SHA384.outSize = 384; +SHA384.hmacStrength = 192; +SHA384.padLength = 128; + +SHA384.prototype._digest = function digest(enc) { + if (enc === 'hex') + return utils.toHex32(this.h.slice(0, 12), 'big'); + else + return utils.split32(this.h.slice(0, 12), 'big'); +}; + +},{"../utils":45,"./512":43}],43:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var common = require('../common'); +var assert = require('minimalistic-assert'); + +var rotr64_hi = utils.rotr64_hi; +var rotr64_lo = utils.rotr64_lo; +var shr64_hi = utils.shr64_hi; +var shr64_lo = utils.shr64_lo; +var sum64 = utils.sum64; +var sum64_hi = utils.sum64_hi; +var sum64_lo = utils.sum64_lo; +var sum64_4_hi = utils.sum64_4_hi; +var sum64_4_lo = utils.sum64_4_lo; +var sum64_5_hi = utils.sum64_5_hi; +var sum64_5_lo = utils.sum64_5_lo; + +var BlockHash = common.BlockHash; + +var sha512_K = [ + 0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd, + 0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc, + 0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019, + 0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118, + 0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe, + 0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2, + 0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1, + 0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694, + 0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3, + 0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65, + 0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483, + 0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5, + 0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210, + 0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4, + 0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725, + 0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70, + 0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926, + 0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df, + 0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8, + 0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b, + 0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001, + 0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30, + 0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910, + 0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8, + 0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53, + 0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8, + 0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb, + 0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3, + 0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60, + 0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec, + 0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9, + 0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b, + 0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207, + 0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178, + 0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6, + 0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b, + 0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493, + 0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c, + 0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a, + 0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817 +]; + +function SHA512() { + if (!(this instanceof SHA512)) + return new SHA512(); + + BlockHash.call(this); + this.h = [ + 0x6a09e667, 0xf3bcc908, + 0xbb67ae85, 0x84caa73b, + 0x3c6ef372, 0xfe94f82b, + 0xa54ff53a, 0x5f1d36f1, + 0x510e527f, 0xade682d1, + 0x9b05688c, 0x2b3e6c1f, + 0x1f83d9ab, 0xfb41bd6b, + 0x5be0cd19, 0x137e2179 ]; + this.k = sha512_K; + this.W = new Array(160); +} +utils.inherits(SHA512, BlockHash); +module.exports = SHA512; + +SHA512.blockSize = 1024; +SHA512.outSize = 512; +SHA512.hmacStrength = 192; +SHA512.padLength = 128; + +SHA512.prototype._prepareBlock = function _prepareBlock(msg, start) { + var W = this.W; + + // 32 x 32bit words + for (var i = 0; i < 32; i++) + W[i] = msg[start + i]; + for (; i < W.length; i += 2) { + var c0_hi = g1_512_hi(W[i - 4], W[i - 3]); // i - 2 + var c0_lo = g1_512_lo(W[i - 4], W[i - 3]); + var c1_hi = W[i - 14]; // i - 7 + var c1_lo = W[i - 13]; + var c2_hi = g0_512_hi(W[i - 30], W[i - 29]); // i - 15 + var c2_lo = g0_512_lo(W[i - 30], W[i - 29]); + var c3_hi = W[i - 32]; // i - 16 + var c3_lo = W[i - 31]; + + W[i] = sum64_4_hi( + c0_hi, c0_lo, + c1_hi, c1_lo, + c2_hi, c2_lo, + c3_hi, c3_lo); + W[i + 1] = sum64_4_lo( + c0_hi, c0_lo, + c1_hi, c1_lo, + c2_hi, c2_lo, + c3_hi, c3_lo); + } +}; + +SHA512.prototype._update = function _update(msg, start) { + this._prepareBlock(msg, start); + + var W = this.W; + + var ah = this.h[0]; + var al = this.h[1]; + var bh = this.h[2]; + var bl = this.h[3]; + var ch = this.h[4]; + var cl = this.h[5]; + var dh = this.h[6]; + var dl = this.h[7]; + var eh = this.h[8]; + var el = this.h[9]; + var fh = this.h[10]; + var fl = this.h[11]; + var gh = this.h[12]; + var gl = this.h[13]; + var hh = this.h[14]; + var hl = this.h[15]; + + assert(this.k.length === W.length); + for (var i = 0; i < W.length; i += 2) { + var c0_hi = hh; + var c0_lo = hl; + var c1_hi = s1_512_hi(eh, el); + var c1_lo = s1_512_lo(eh, el); + var c2_hi = ch64_hi(eh, el, fh, fl, gh, gl); + var c2_lo = ch64_lo(eh, el, fh, fl, gh, gl); + var c3_hi = this.k[i]; + var c3_lo = this.k[i + 1]; + var c4_hi = W[i]; + var c4_lo = W[i + 1]; + + var T1_hi = sum64_5_hi( + c0_hi, c0_lo, + c1_hi, c1_lo, + c2_hi, c2_lo, + c3_hi, c3_lo, + c4_hi, c4_lo); + var T1_lo = sum64_5_lo( + c0_hi, c0_lo, + c1_hi, c1_lo, + c2_hi, c2_lo, + c3_hi, c3_lo, + c4_hi, c4_lo); + + c0_hi = s0_512_hi(ah, al); + c0_lo = s0_512_lo(ah, al); + c1_hi = maj64_hi(ah, al, bh, bl, ch, cl); + c1_lo = maj64_lo(ah, al, bh, bl, ch, cl); + + var T2_hi = sum64_hi(c0_hi, c0_lo, c1_hi, c1_lo); + var T2_lo = sum64_lo(c0_hi, c0_lo, c1_hi, c1_lo); + + hh = gh; + hl = gl; + + gh = fh; + gl = fl; + + fh = eh; + fl = el; + + eh = sum64_hi(dh, dl, T1_hi, T1_lo); + el = sum64_lo(dl, dl, T1_hi, T1_lo); + + dh = ch; + dl = cl; + + ch = bh; + cl = bl; + + bh = ah; + bl = al; + + ah = sum64_hi(T1_hi, T1_lo, T2_hi, T2_lo); + al = sum64_lo(T1_hi, T1_lo, T2_hi, T2_lo); + } + + sum64(this.h, 0, ah, al); + sum64(this.h, 2, bh, bl); + sum64(this.h, 4, ch, cl); + sum64(this.h, 6, dh, dl); + sum64(this.h, 8, eh, el); + sum64(this.h, 10, fh, fl); + sum64(this.h, 12, gh, gl); + sum64(this.h, 14, hh, hl); +}; + +SHA512.prototype._digest = function digest(enc) { + if (enc === 'hex') + return utils.toHex32(this.h, 'big'); + else + return utils.split32(this.h, 'big'); +}; + +function ch64_hi(xh, xl, yh, yl, zh) { + var r = (xh & yh) ^ ((~xh) & zh); + if (r < 0) + r += 0x100000000; + return r; +} + +function ch64_lo(xh, xl, yh, yl, zh, zl) { + var r = (xl & yl) ^ ((~xl) & zl); + if (r < 0) + r += 0x100000000; + return r; +} + +function maj64_hi(xh, xl, yh, yl, zh) { + var r = (xh & yh) ^ (xh & zh) ^ (yh & zh); + if (r < 0) + r += 0x100000000; + return r; +} + +function maj64_lo(xh, xl, yh, yl, zh, zl) { + var r = (xl & yl) ^ (xl & zl) ^ (yl & zl); + if (r < 0) + r += 0x100000000; + return r; +} + +function s0_512_hi(xh, xl) { + var c0_hi = rotr64_hi(xh, xl, 28); + var c1_hi = rotr64_hi(xl, xh, 2); // 34 + var c2_hi = rotr64_hi(xl, xh, 7); // 39 + + var r = c0_hi ^ c1_hi ^ c2_hi; + if (r < 0) + r += 0x100000000; + return r; +} + +function s0_512_lo(xh, xl) { + var c0_lo = rotr64_lo(xh, xl, 28); + var c1_lo = rotr64_lo(xl, xh, 2); // 34 + var c2_lo = rotr64_lo(xl, xh, 7); // 39 + + var r = c0_lo ^ c1_lo ^ c2_lo; + if (r < 0) + r += 0x100000000; + return r; +} + +function s1_512_hi(xh, xl) { + var c0_hi = rotr64_hi(xh, xl, 14); + var c1_hi = rotr64_hi(xh, xl, 18); + var c2_hi = rotr64_hi(xl, xh, 9); // 41 + + var r = c0_hi ^ c1_hi ^ c2_hi; + if (r < 0) + r += 0x100000000; + return r; +} + +function s1_512_lo(xh, xl) { + var c0_lo = rotr64_lo(xh, xl, 14); + var c1_lo = rotr64_lo(xh, xl, 18); + var c2_lo = rotr64_lo(xl, xh, 9); // 41 + + var r = c0_lo ^ c1_lo ^ c2_lo; + if (r < 0) + r += 0x100000000; + return r; +} + +function g0_512_hi(xh, xl) { + var c0_hi = rotr64_hi(xh, xl, 1); + var c1_hi = rotr64_hi(xh, xl, 8); + var c2_hi = shr64_hi(xh, xl, 7); + + var r = c0_hi ^ c1_hi ^ c2_hi; + if (r < 0) + r += 0x100000000; + return r; +} + +function g0_512_lo(xh, xl) { + var c0_lo = rotr64_lo(xh, xl, 1); + var c1_lo = rotr64_lo(xh, xl, 8); + var c2_lo = shr64_lo(xh, xl, 7); + + var r = c0_lo ^ c1_lo ^ c2_lo; + if (r < 0) + r += 0x100000000; + return r; +} + +function g1_512_hi(xh, xl) { + var c0_hi = rotr64_hi(xh, xl, 19); + var c1_hi = rotr64_hi(xl, xh, 29); // 61 + var c2_hi = shr64_hi(xh, xl, 6); + + var r = c0_hi ^ c1_hi ^ c2_hi; + if (r < 0) + r += 0x100000000; + return r; +} + +function g1_512_lo(xh, xl) { + var c0_lo = rotr64_lo(xh, xl, 19); + var c1_lo = rotr64_lo(xl, xh, 29); // 61 + var c2_lo = shr64_lo(xh, xl, 6); + + var r = c0_lo ^ c1_lo ^ c2_lo; + if (r < 0) + r += 0x100000000; + return r; +} + +},{"../common":35,"../utils":45,"minimalistic-assert":48}],44:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var rotr32 = utils.rotr32; + +function ft_1(s, x, y, z) { + if (s === 0) + return ch32(x, y, z); + if (s === 1 || s === 3) + return p32(x, y, z); + if (s === 2) + return maj32(x, y, z); +} +exports.ft_1 = ft_1; + +function ch32(x, y, z) { + return (x & y) ^ ((~x) & z); +} +exports.ch32 = ch32; + +function maj32(x, y, z) { + return (x & y) ^ (x & z) ^ (y & z); +} +exports.maj32 = maj32; + +function p32(x, y, z) { + return x ^ y ^ z; +} +exports.p32 = p32; + +function s0_256(x) { + return rotr32(x, 2) ^ rotr32(x, 13) ^ rotr32(x, 22); +} +exports.s0_256 = s0_256; + +function s1_256(x) { + return rotr32(x, 6) ^ rotr32(x, 11) ^ rotr32(x, 25); +} +exports.s1_256 = s1_256; + +function g0_256(x) { + return rotr32(x, 7) ^ rotr32(x, 18) ^ (x >>> 3); +} +exports.g0_256 = g0_256; + +function g1_256(x) { + return rotr32(x, 17) ^ rotr32(x, 19) ^ (x >>> 10); +} +exports.g1_256 = g1_256; + +},{"../utils":45}],45:[function(require,module,exports){ +'use strict'; + +var assert = require('minimalistic-assert'); +var inherits = require('inherits'); + +exports.inherits = inherits; + +function toArray(msg, enc) { + if (Array.isArray(msg)) + return msg.slice(); + if (!msg) + return []; + var res = []; + if (typeof msg === 'string') { + if (!enc) { + for (var i = 0; i < msg.length; i++) { + var c = msg.charCodeAt(i); + var hi = c >> 8; + var lo = c & 0xff; + if (hi) + res.push(hi, lo); + else + res.push(lo); + } + } else if (enc === 'hex') { + msg = msg.replace(/[^a-z0-9]+/ig, ''); + if (msg.length % 2 !== 0) + msg = '0' + msg; + for (i = 0; i < msg.length; i += 2) + res.push(parseInt(msg[i] + msg[i + 1], 16)); + } + } else { + for (i = 0; i < msg.length; i++) + res[i] = msg[i] | 0; + } + return res; +} +exports.toArray = toArray; + +function toHex(msg) { + var res = ''; + for (var i = 0; i < msg.length; i++) + res += zero2(msg[i].toString(16)); + return res; +} +exports.toHex = toHex; + +function htonl(w) { + var res = (w >>> 24) | + ((w >>> 8) & 0xff00) | + ((w << 8) & 0xff0000) | + ((w & 0xff) << 24); + return res >>> 0; +} +exports.htonl = htonl; + +function toHex32(msg, endian) { + var res = ''; + for (var i = 0; i < msg.length; i++) { + var w = msg[i]; + if (endian === 'little') + w = htonl(w); + res += zero8(w.toString(16)); + } + return res; +} +exports.toHex32 = toHex32; + +function zero2(word) { + if (word.length === 1) + return '0' + word; + else + return word; +} +exports.zero2 = zero2; + +function zero8(word) { + if (word.length === 7) + return '0' + word; + else if (word.length === 6) + return '00' + word; + else if (word.length === 5) + return '000' + word; + else if (word.length === 4) + return '0000' + word; + else if (word.length === 3) + return '00000' + word; + else if (word.length === 2) + return '000000' + word; + else if (word.length === 1) + return '0000000' + word; + else + return word; +} +exports.zero8 = zero8; + +function join32(msg, start, end, endian) { + var len = end - start; + assert(len % 4 === 0); + var res = new Array(len / 4); + for (var i = 0, k = start; i < res.length; i++, k += 4) { + var w; + if (endian === 'big') + w = (msg[k] << 24) | (msg[k + 1] << 16) | (msg[k + 2] << 8) | msg[k + 3]; + else + w = (msg[k + 3] << 24) | (msg[k + 2] << 16) | (msg[k + 1] << 8) | msg[k]; + res[i] = w >>> 0; + } + return res; +} +exports.join32 = join32; + +function split32(msg, endian) { + var res = new Array(msg.length * 4); + for (var i = 0, k = 0; i < msg.length; i++, k += 4) { + var m = msg[i]; + if (endian === 'big') { + res[k] = m >>> 24; + res[k + 1] = (m >>> 16) & 0xff; + res[k + 2] = (m >>> 8) & 0xff; + res[k + 3] = m & 0xff; + } else { + res[k + 3] = m >>> 24; + res[k + 2] = (m >>> 16) & 0xff; + res[k + 1] = (m >>> 8) & 0xff; + res[k] = m & 0xff; + } + } + return res; +} +exports.split32 = split32; + +function rotr32(w, b) { + return (w >>> b) | (w << (32 - b)); +} +exports.rotr32 = rotr32; + +function rotl32(w, b) { + return (w << b) | (w >>> (32 - b)); +} +exports.rotl32 = rotl32; + +function sum32(a, b) { + return (a + b) >>> 0; +} +exports.sum32 = sum32; + +function sum32_3(a, b, c) { + return (a + b + c) >>> 0; +} +exports.sum32_3 = sum32_3; + +function sum32_4(a, b, c, d) { + return (a + b + c + d) >>> 0; +} +exports.sum32_4 = sum32_4; + +function sum32_5(a, b, c, d, e) { + return (a + b + c + d + e) >>> 0; +} +exports.sum32_5 = sum32_5; + +function sum64(buf, pos, ah, al) { + var bh = buf[pos]; + var bl = buf[pos + 1]; + + var lo = (al + bl) >>> 0; + var hi = (lo < al ? 1 : 0) + ah + bh; + buf[pos] = hi >>> 0; + buf[pos + 1] = lo; +} +exports.sum64 = sum64; + +function sum64_hi(ah, al, bh, bl) { + var lo = (al + bl) >>> 0; + var hi = (lo < al ? 1 : 0) + ah + bh; + return hi >>> 0; +} +exports.sum64_hi = sum64_hi; + +function sum64_lo(ah, al, bh, bl) { + var lo = al + bl; + return lo >>> 0; +} +exports.sum64_lo = sum64_lo; + +function sum64_4_hi(ah, al, bh, bl, ch, cl, dh, dl) { + var carry = 0; + var lo = al; + lo = (lo + bl) >>> 0; + carry += lo < al ? 1 : 0; + lo = (lo + cl) >>> 0; + carry += lo < cl ? 1 : 0; + lo = (lo + dl) >>> 0; + carry += lo < dl ? 1 : 0; + + var hi = ah + bh + ch + dh + carry; + return hi >>> 0; +} +exports.sum64_4_hi = sum64_4_hi; + +function sum64_4_lo(ah, al, bh, bl, ch, cl, dh, dl) { + var lo = al + bl + cl + dl; + return lo >>> 0; +} +exports.sum64_4_lo = sum64_4_lo; + +function sum64_5_hi(ah, al, bh, bl, ch, cl, dh, dl, eh, el) { + var carry = 0; + var lo = al; + lo = (lo + bl) >>> 0; + carry += lo < al ? 1 : 0; + lo = (lo + cl) >>> 0; + carry += lo < cl ? 1 : 0; + lo = (lo + dl) >>> 0; + carry += lo < dl ? 1 : 0; + lo = (lo + el) >>> 0; + carry += lo < el ? 1 : 0; + + var hi = ah + bh + ch + dh + eh + carry; + return hi >>> 0; +} +exports.sum64_5_hi = sum64_5_hi; + +function sum64_5_lo(ah, al, bh, bl, ch, cl, dh, dl, eh, el) { + var lo = al + bl + cl + dl + el; + + return lo >>> 0; +} +exports.sum64_5_lo = sum64_5_lo; + +function rotr64_hi(ah, al, num) { + var r = (al << (32 - num)) | (ah >>> num); + return r >>> 0; +} +exports.rotr64_hi = rotr64_hi; + +function rotr64_lo(ah, al, num) { + var r = (ah << (32 - num)) | (al >>> num); + return r >>> 0; +} +exports.rotr64_lo = rotr64_lo; + +function shr64_hi(ah, al, num) { + return ah >>> num; +} +exports.shr64_hi = shr64_hi; + +function shr64_lo(ah, al, num) { + var r = (ah << (32 - num)) | (al >>> num); + return r >>> 0; +} +exports.shr64_lo = shr64_lo; + +},{"inherits":47,"minimalistic-assert":48}],46:[function(require,module,exports){ +'use strict'; + +var hash = require('hash.js'); +var utils = require('minimalistic-crypto-utils'); +var assert = require('minimalistic-assert'); + +function HmacDRBG(options) { + if (!(this instanceof HmacDRBG)) + return new HmacDRBG(options); + this.hash = options.hash; + this.predResist = !!options.predResist; + + this.outLen = this.hash.outSize; + this.minEntropy = options.minEntropy || this.hash.hmacStrength; + + this._reseed = null; + this.reseedInterval = null; + this.K = null; + this.V = null; + + var entropy = utils.toArray(options.entropy, options.entropyEnc || 'hex'); + var nonce = utils.toArray(options.nonce, options.nonceEnc || 'hex'); + var pers = utils.toArray(options.pers, options.persEnc || 'hex'); + assert(entropy.length >= (this.minEntropy / 8), + 'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits'); + this._init(entropy, nonce, pers); +} +module.exports = HmacDRBG; + +HmacDRBG.prototype._init = function init(entropy, nonce, pers) { + var seed = entropy.concat(nonce).concat(pers); + + this.K = new Array(this.outLen / 8); + this.V = new Array(this.outLen / 8); + for (var i = 0; i < this.V.length; i++) { + this.K[i] = 0x00; + this.V[i] = 0x01; + } + + this._update(seed); + this._reseed = 1; + this.reseedInterval = 0x1000000000000; // 2^48 +}; + +HmacDRBG.prototype._hmac = function hmac() { + return new hash.hmac(this.hash, this.K); +}; + +HmacDRBG.prototype._update = function update(seed) { + var kmac = this._hmac() + .update(this.V) + .update([ 0x00 ]); + if (seed) + kmac = kmac.update(seed); + this.K = kmac.digest(); + this.V = this._hmac().update(this.V).digest(); + if (!seed) + return; + + this.K = this._hmac() + .update(this.V) + .update([ 0x01 ]) + .update(seed) + .digest(); + this.V = this._hmac().update(this.V).digest(); +}; + +HmacDRBG.prototype.reseed = function reseed(entropy, entropyEnc, add, addEnc) { + // Optional entropy enc + if (typeof entropyEnc !== 'string') { + addEnc = add; + add = entropyEnc; + entropyEnc = null; + } + + entropy = utils.toArray(entropy, entropyEnc); + add = utils.toArray(add, addEnc); + + assert(entropy.length >= (this.minEntropy / 8), + 'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits'); + + this._update(entropy.concat(add || [])); + this._reseed = 1; +}; + +HmacDRBG.prototype.generate = function generate(len, enc, add, addEnc) { + if (this._reseed > this.reseedInterval) + throw new Error('Reseed is required'); + + // Optional encoding + if (typeof enc !== 'string') { + addEnc = add; + add = enc; + enc = null; + } + + // Optional additional data + if (add) { + add = utils.toArray(add, addEnc || 'hex'); + this._update(add); + } + + var temp = []; + while (temp.length < len) { + this.V = this._hmac().update(this.V).digest(); + temp = temp.concat(this.V); + } + + var res = temp.slice(0, len); + this._update(add); + this._reseed++; + return utils.encode(res, enc); +}; + +},{"hash.js":34,"minimalistic-assert":48,"minimalistic-crypto-utils":49}],47:[function(require,module,exports){ +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } +} + +},{}],48:[function(require,module,exports){ +module.exports = assert; + +function assert(val, msg) { + if (!val) + throw new Error(msg || 'Assertion failed'); +} + +assert.equal = function assertEqual(l, r, msg) { + if (l != r) + throw new Error(msg || ('Assertion failed: ' + l + ' != ' + r)); +}; + +},{}],49:[function(require,module,exports){ +'use strict'; + +var utils = exports; + +function toArray(msg, enc) { + if (Array.isArray(msg)) + return msg.slice(); + if (!msg) + return []; + var res = []; + if (typeof msg !== 'string') { + for (var i = 0; i < msg.length; i++) + res[i] = msg[i] | 0; + return res; + } + if (enc === 'hex') { + msg = msg.replace(/[^a-z0-9]+/ig, ''); + if (msg.length % 2 !== 0) + msg = '0' + msg; + for (var i = 0; i < msg.length; i += 2) + res.push(parseInt(msg[i] + msg[i + 1], 16)); + } else { + for (var i = 0; i < msg.length; i++) { + var c = msg.charCodeAt(i); + var hi = c >> 8; + var lo = c & 0xff; + if (hi) + res.push(hi, lo); + else + res.push(lo); + } + } + return res; +} +utils.toArray = toArray; + +function zero2(word) { + if (word.length === 1) + return '0' + word; + else + return word; +} +utils.zero2 = zero2; + +function toHex(msg) { + var res = ''; + for (var i = 0; i < msg.length; i++) + res += zero2(msg[i].toString(16)); + return res; +} +utils.toHex = toHex; + +utils.encode = function encode(arr, enc) { + if (enc === 'hex') + return toHex(arr); + else + return arr; +}; + +},{}],50:[function(require,module,exports){ +// Top level file is just a mixin of submodules & constants +'use strict'; + +var assign = require('./lib/utils/common').assign; + +var deflate = require('./lib/deflate'); +var inflate = require('./lib/inflate'); +var constants = require('./lib/zlib/constants'); + +var pako = {}; + +assign(pako, deflate, inflate, constants); + +module.exports = pako; + +},{"./lib/deflate":51,"./lib/inflate":52,"./lib/utils/common":53,"./lib/zlib/constants":56}],51:[function(require,module,exports){ +'use strict'; + + +var zlib_deflate = require('./zlib/deflate'); +var utils = require('./utils/common'); +var strings = require('./utils/strings'); +var msg = require('./zlib/messages'); +var ZStream = require('./zlib/zstream'); + +var toString = Object.prototype.toString; + +/* Public constants ==========================================================*/ +/* ===========================================================================*/ + +var Z_NO_FLUSH = 0; +var Z_FINISH = 4; + +var Z_OK = 0; +var Z_STREAM_END = 1; +var Z_SYNC_FLUSH = 2; + +var Z_DEFAULT_COMPRESSION = -1; + +var Z_DEFAULT_STRATEGY = 0; + +var Z_DEFLATED = 8; + +/* ===========================================================================*/ + + +/** + * class Deflate + * + * Generic JS-style wrapper for zlib calls. If you don't need + * streaming behaviour - use more simple functions: [[deflate]], + * [[deflateRaw]] and [[gzip]]. + **/ + +/* internal + * Deflate.chunks -> Array + * + * Chunks of output data, if [[Deflate#onData]] not overridden. + **/ + +/** + * Deflate.result -> Uint8Array|Array + * + * Compressed result, generated by default [[Deflate#onData]] + * and [[Deflate#onEnd]] handlers. Filled after you push last chunk + * (call [[Deflate#push]] with `Z_FINISH` / `true` param) or if you + * push a chunk with explicit flush (call [[Deflate#push]] with + * `Z_SYNC_FLUSH` param). + **/ + +/** + * Deflate.err -> Number + * + * Error code after deflate finished. 0 (Z_OK) on success. + * You will not need it in real life, because deflate errors + * are possible only on wrong options or bad `onData` / `onEnd` + * custom handlers. + **/ + +/** + * Deflate.msg -> String + * + * Error message, if [[Deflate.err]] != 0 + **/ + + +/** + * new Deflate(options) + * - options (Object): zlib deflate options. + * + * Creates new deflator instance with specified params. Throws exception + * on bad params. Supported options: + * + * - `level` + * - `windowBits` + * - `memLevel` + * - `strategy` + * - `dictionary` + * + * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) + * for more information on these. + * + * Additional options, for internal needs: + * + * - `chunkSize` - size of generated data chunks (16K by default) + * - `raw` (Boolean) - do raw deflate + * - `gzip` (Boolean) - create gzip wrapper + * - `to` (String) - if equal to 'string', then result will be "binary string" + * (each char code [0..255]) + * - `header` (Object) - custom header for gzip + * - `text` (Boolean) - true if compressed data believed to be text + * - `time` (Number) - modification time, unix timestamp + * - `os` (Number) - operation system code + * - `extra` (Array) - array of bytes with extra data (max 65536) + * - `name` (String) - file name (binary string) + * - `comment` (String) - comment (binary string) + * - `hcrc` (Boolean) - true if header crc should be added + * + * ##### Example: + * + * ```javascript + * var pako = require('pako') + * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9]) + * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]); + * + * var deflate = new pako.Deflate({ level: 3}); + * + * deflate.push(chunk1, false); + * deflate.push(chunk2, true); // true -> last chunk + * + * if (deflate.err) { throw new Error(deflate.err); } + * + * console.log(deflate.result); + * ``` + **/ +function Deflate(options) { + if (!(this instanceof Deflate)) return new Deflate(options); + + this.options = utils.assign({ + level: Z_DEFAULT_COMPRESSION, + method: Z_DEFLATED, + chunkSize: 16384, + windowBits: 15, + memLevel: 8, + strategy: Z_DEFAULT_STRATEGY, + to: '' + }, options || {}); + + var opt = this.options; + + if (opt.raw && (opt.windowBits > 0)) { + opt.windowBits = -opt.windowBits; + } + + else if (opt.gzip && (opt.windowBits > 0) && (opt.windowBits < 16)) { + opt.windowBits += 16; + } + + this.err = 0; // error code, if happens (0 = Z_OK) + this.msg = ''; // error message + this.ended = false; // used to avoid multiple onEnd() calls + this.chunks = []; // chunks of compressed data + + this.strm = new ZStream(); + this.strm.avail_out = 0; + + var status = zlib_deflate.deflateInit2( + this.strm, + opt.level, + opt.method, + opt.windowBits, + opt.memLevel, + opt.strategy + ); + + if (status !== Z_OK) { + throw new Error(msg[status]); + } + + if (opt.header) { + zlib_deflate.deflateSetHeader(this.strm, opt.header); + } + + if (opt.dictionary) { + var dict; + // Convert data if needed + if (typeof opt.dictionary === 'string') { + // If we need to compress text, change encoding to utf8. + dict = strings.string2buf(opt.dictionary); + } else if (toString.call(opt.dictionary) === '[object ArrayBuffer]') { + dict = new Uint8Array(opt.dictionary); + } else { + dict = opt.dictionary; + } + + status = zlib_deflate.deflateSetDictionary(this.strm, dict); + + if (status !== Z_OK) { + throw new Error(msg[status]); + } + + this._dict_set = true; + } +} + +/** + * Deflate#push(data[, mode]) -> Boolean + * - data (Uint8Array|Array|ArrayBuffer|String): input data. Strings will be + * converted to utf8 byte sequence. + * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. + * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH. + * + * Sends input data to deflate pipe, generating [[Deflate#onData]] calls with + * new compressed chunks. Returns `true` on success. The last data block must have + * mode Z_FINISH (or `true`). That will flush internal pending buffers and call + * [[Deflate#onEnd]]. For interim explicit flushes (without ending the stream) you + * can use mode Z_SYNC_FLUSH, keeping the compression context. + * + * On fail call [[Deflate#onEnd]] with error code and return false. + * + * We strongly recommend to use `Uint8Array` on input for best speed (output + * array format is detected automatically). Also, don't skip last param and always + * use the same type in your code (boolean or number). That will improve JS speed. + * + * For regular `Array`-s make sure all elements are [0..255]. + * + * ##### Example + * + * ```javascript + * push(chunk, false); // push one of data chunks + * ... + * push(chunk, true); // push last chunk + * ``` + **/ +Deflate.prototype.push = function (data, mode) { + var strm = this.strm; + var chunkSize = this.options.chunkSize; + var status, _mode; + + if (this.ended) { return false; } + + _mode = (mode === ~~mode) ? mode : ((mode === true) ? Z_FINISH : Z_NO_FLUSH); + + // Convert data if needed + if (typeof data === 'string') { + // If we need to compress text, change encoding to utf8. + strm.input = strings.string2buf(data); + } else if (toString.call(data) === '[object ArrayBuffer]') { + strm.input = new Uint8Array(data); + } else { + strm.input = data; + } + + strm.next_in = 0; + strm.avail_in = strm.input.length; + + do { + if (strm.avail_out === 0) { + strm.output = new utils.Buf8(chunkSize); + strm.next_out = 0; + strm.avail_out = chunkSize; + } + status = zlib_deflate.deflate(strm, _mode); /* no bad return value */ + + if (status !== Z_STREAM_END && status !== Z_OK) { + this.onEnd(status); + this.ended = true; + return false; + } + if (strm.avail_out === 0 || (strm.avail_in === 0 && (_mode === Z_FINISH || _mode === Z_SYNC_FLUSH))) { + if (this.options.to === 'string') { + this.onData(strings.buf2binstring(utils.shrinkBuf(strm.output, strm.next_out))); + } else { + this.onData(utils.shrinkBuf(strm.output, strm.next_out)); + } + } + } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== Z_STREAM_END); + + // Finalize on the last chunk. + if (_mode === Z_FINISH) { + status = zlib_deflate.deflateEnd(this.strm); + this.onEnd(status); + this.ended = true; + return status === Z_OK; + } + + // callback interim results if Z_SYNC_FLUSH. + if (_mode === Z_SYNC_FLUSH) { + this.onEnd(Z_OK); + strm.avail_out = 0; + return true; + } + + return true; +}; + + +/** + * Deflate#onData(chunk) -> Void + * - chunk (Uint8Array|Array|String): output data. Type of array depends + * on js engine support. When string output requested, each chunk + * will be string. + * + * By default, stores data blocks in `chunks[]` property and glue + * those in `onEnd`. Override this handler, if you need another behaviour. + **/ +Deflate.prototype.onData = function (chunk) { + this.chunks.push(chunk); +}; + + +/** + * Deflate#onEnd(status) -> Void + * - status (Number): deflate status. 0 (Z_OK) on success, + * other if not. + * + * Called once after you tell deflate that the input stream is + * complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH) + * or if an error happened. By default - join collected chunks, + * free memory and fill `results` / `err` properties. + **/ +Deflate.prototype.onEnd = function (status) { + // On success - join + if (status === Z_OK) { + if (this.options.to === 'string') { + this.result = this.chunks.join(''); + } else { + this.result = utils.flattenChunks(this.chunks); + } + } + this.chunks = []; + this.err = status; + this.msg = this.strm.msg; +}; + + +/** + * deflate(data[, options]) -> Uint8Array|Array|String + * - data (Uint8Array|Array|String): input data to compress. + * - options (Object): zlib deflate options. + * + * Compress `data` with deflate algorithm and `options`. + * + * Supported options are: + * + * - level + * - windowBits + * - memLevel + * - strategy + * - dictionary + * + * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) + * for more information on these. + * + * Sugar (options): + * + * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify + * negative windowBits implicitly. + * - `to` (String) - if equal to 'string', then result will be "binary string" + * (each char code [0..255]) + * + * ##### Example: + * + * ```javascript + * var pako = require('pako') + * , data = Uint8Array([1,2,3,4,5,6,7,8,9]); + * + * console.log(pako.deflate(data)); + * ``` + **/ +function deflate(input, options) { + var deflator = new Deflate(options); + + deflator.push(input, true); + + // That will never happens, if you don't cheat with options :) + if (deflator.err) { throw deflator.msg || msg[deflator.err]; } + + return deflator.result; +} + + +/** + * deflateRaw(data[, options]) -> Uint8Array|Array|String + * - data (Uint8Array|Array|String): input data to compress. + * - options (Object): zlib deflate options. + * + * The same as [[deflate]], but creates raw data, without wrapper + * (header and adler32 crc). + **/ +function deflateRaw(input, options) { + options = options || {}; + options.raw = true; + return deflate(input, options); +} + + +/** + * gzip(data[, options]) -> Uint8Array|Array|String + * - data (Uint8Array|Array|String): input data to compress. + * - options (Object): zlib deflate options. + * + * The same as [[deflate]], but create gzip wrapper instead of + * deflate one. + **/ +function gzip(input, options) { + options = options || {}; + options.gzip = true; + return deflate(input, options); +} + + +exports.Deflate = Deflate; +exports.deflate = deflate; +exports.deflateRaw = deflateRaw; +exports.gzip = gzip; + +},{"./utils/common":53,"./utils/strings":54,"./zlib/deflate":58,"./zlib/messages":63,"./zlib/zstream":65}],52:[function(require,module,exports){ +'use strict'; + + +var zlib_inflate = require('./zlib/inflate'); +var utils = require('./utils/common'); +var strings = require('./utils/strings'); +var c = require('./zlib/constants'); +var msg = require('./zlib/messages'); +var ZStream = require('./zlib/zstream'); +var GZheader = require('./zlib/gzheader'); + +var toString = Object.prototype.toString; + +/** + * class Inflate + * + * Generic JS-style wrapper for zlib calls. If you don't need + * streaming behaviour - use more simple functions: [[inflate]] + * and [[inflateRaw]]. + **/ + +/* internal + * inflate.chunks -> Array + * + * Chunks of output data, if [[Inflate#onData]] not overridden. + **/ + +/** + * Inflate.result -> Uint8Array|Array|String + * + * Uncompressed result, generated by default [[Inflate#onData]] + * and [[Inflate#onEnd]] handlers. Filled after you push last chunk + * (call [[Inflate#push]] with `Z_FINISH` / `true` param) or if you + * push a chunk with explicit flush (call [[Inflate#push]] with + * `Z_SYNC_FLUSH` param). + **/ + +/** + * Inflate.err -> Number + * + * Error code after inflate finished. 0 (Z_OK) on success. + * Should be checked if broken data possible. + **/ + +/** + * Inflate.msg -> String + * + * Error message, if [[Inflate.err]] != 0 + **/ + + +/** + * new Inflate(options) + * - options (Object): zlib inflate options. + * + * Creates new inflator instance with specified params. Throws exception + * on bad params. Supported options: + * + * - `windowBits` + * - `dictionary` + * + * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) + * for more information on these. + * + * Additional options, for internal needs: + * + * - `chunkSize` - size of generated data chunks (16K by default) + * - `raw` (Boolean) - do raw inflate + * - `to` (String) - if equal to 'string', then result will be converted + * from utf8 to utf16 (javascript) string. When string output requested, + * chunk length can differ from `chunkSize`, depending on content. + * + * By default, when no options set, autodetect deflate/gzip data format via + * wrapper header. + * + * ##### Example: + * + * ```javascript + * var pako = require('pako') + * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9]) + * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]); + * + * var inflate = new pako.Inflate({ level: 3}); + * + * inflate.push(chunk1, false); + * inflate.push(chunk2, true); // true -> last chunk + * + * if (inflate.err) { throw new Error(inflate.err); } + * + * console.log(inflate.result); + * ``` + **/ +function Inflate(options) { + if (!(this instanceof Inflate)) return new Inflate(options); + + this.options = utils.assign({ + chunkSize: 16384, + windowBits: 0, + to: '' + }, options || {}); + + var opt = this.options; + + // Force window size for `raw` data, if not set directly, + // because we have no header for autodetect. + if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) { + opt.windowBits = -opt.windowBits; + if (opt.windowBits === 0) { opt.windowBits = -15; } + } + + // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate + if ((opt.windowBits >= 0) && (opt.windowBits < 16) && + !(options && options.windowBits)) { + opt.windowBits += 32; + } + + // Gzip header has no info about windows size, we can do autodetect only + // for deflate. So, if window size not set, force it to max when gzip possible + if ((opt.windowBits > 15) && (opt.windowBits < 48)) { + // bit 3 (16) -> gzipped data + // bit 4 (32) -> autodetect gzip/deflate + if ((opt.windowBits & 15) === 0) { + opt.windowBits |= 15; + } + } + + this.err = 0; // error code, if happens (0 = Z_OK) + this.msg = ''; // error message + this.ended = false; // used to avoid multiple onEnd() calls + this.chunks = []; // chunks of compressed data + + this.strm = new ZStream(); + this.strm.avail_out = 0; + + var status = zlib_inflate.inflateInit2( + this.strm, + opt.windowBits + ); + + if (status !== c.Z_OK) { + throw new Error(msg[status]); + } + + this.header = new GZheader(); + + zlib_inflate.inflateGetHeader(this.strm, this.header); +} + +/** + * Inflate#push(data[, mode]) -> Boolean + * - data (Uint8Array|Array|ArrayBuffer|String): input data + * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. + * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH. + * + * Sends input data to inflate pipe, generating [[Inflate#onData]] calls with + * new output chunks. Returns `true` on success. The last data block must have + * mode Z_FINISH (or `true`). That will flush internal pending buffers and call + * [[Inflate#onEnd]]. For interim explicit flushes (without ending the stream) you + * can use mode Z_SYNC_FLUSH, keeping the decompression context. + * + * On fail call [[Inflate#onEnd]] with error code and return false. + * + * We strongly recommend to use `Uint8Array` on input for best speed (output + * format is detected automatically). Also, don't skip last param and always + * use the same type in your code (boolean or number). That will improve JS speed. + * + * For regular `Array`-s make sure all elements are [0..255]. + * + * ##### Example + * + * ```javascript + * push(chunk, false); // push one of data chunks + * ... + * push(chunk, true); // push last chunk + * ``` + **/ +Inflate.prototype.push = function (data, mode) { + var strm = this.strm; + var chunkSize = this.options.chunkSize; + var dictionary = this.options.dictionary; + var status, _mode; + var next_out_utf8, tail, utf8str; + var dict; + + // Flag to properly process Z_BUF_ERROR on testing inflate call + // when we check that all output data was flushed. + var allowBufError = false; + + if (this.ended) { return false; } + _mode = (mode === ~~mode) ? mode : ((mode === true) ? c.Z_FINISH : c.Z_NO_FLUSH); + + // Convert data if needed + if (typeof data === 'string') { + // Only binary strings can be decompressed on practice + strm.input = strings.binstring2buf(data); + } else if (toString.call(data) === '[object ArrayBuffer]') { + strm.input = new Uint8Array(data); + } else { + strm.input = data; + } + + strm.next_in = 0; + strm.avail_in = strm.input.length; + + do { + if (strm.avail_out === 0) { + strm.output = new utils.Buf8(chunkSize); + strm.next_out = 0; + strm.avail_out = chunkSize; + } + + status = zlib_inflate.inflate(strm, c.Z_NO_FLUSH); /* no bad return value */ + + if (status === c.Z_NEED_DICT && dictionary) { + // Convert data if needed + if (typeof dictionary === 'string') { + dict = strings.string2buf(dictionary); + } else if (toString.call(dictionary) === '[object ArrayBuffer]') { + dict = new Uint8Array(dictionary); + } else { + dict = dictionary; + } + + status = zlib_inflate.inflateSetDictionary(this.strm, dict); + + } + + if (status === c.Z_BUF_ERROR && allowBufError === true) { + status = c.Z_OK; + allowBufError = false; + } + + if (status !== c.Z_STREAM_END && status !== c.Z_OK) { + this.onEnd(status); + this.ended = true; + return false; + } + + if (strm.next_out) { + if (strm.avail_out === 0 || status === c.Z_STREAM_END || (strm.avail_in === 0 && (_mode === c.Z_FINISH || _mode === c.Z_SYNC_FLUSH))) { + + if (this.options.to === 'string') { + + next_out_utf8 = strings.utf8border(strm.output, strm.next_out); + + tail = strm.next_out - next_out_utf8; + utf8str = strings.buf2string(strm.output, next_out_utf8); + + // move tail + strm.next_out = tail; + strm.avail_out = chunkSize - tail; + if (tail) { utils.arraySet(strm.output, strm.output, next_out_utf8, tail, 0); } + + this.onData(utf8str); + + } else { + this.onData(utils.shrinkBuf(strm.output, strm.next_out)); + } + } + } + + // When no more input data, we should check that internal inflate buffers + // are flushed. The only way to do it when avail_out = 0 - run one more + // inflate pass. But if output data not exists, inflate return Z_BUF_ERROR. + // Here we set flag to process this error properly. + // + // NOTE. Deflate does not return error in this case and does not needs such + // logic. + if (strm.avail_in === 0 && strm.avail_out === 0) { + allowBufError = true; + } + + } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== c.Z_STREAM_END); + + if (status === c.Z_STREAM_END) { + _mode = c.Z_FINISH; + } + + // Finalize on the last chunk. + if (_mode === c.Z_FINISH) { + status = zlib_inflate.inflateEnd(this.strm); + this.onEnd(status); + this.ended = true; + return status === c.Z_OK; + } + + // callback interim results if Z_SYNC_FLUSH. + if (_mode === c.Z_SYNC_FLUSH) { + this.onEnd(c.Z_OK); + strm.avail_out = 0; + return true; + } + + return true; +}; + + +/** + * Inflate#onData(chunk) -> Void + * - chunk (Uint8Array|Array|String): output data. Type of array depends + * on js engine support. When string output requested, each chunk + * will be string. + * + * By default, stores data blocks in `chunks[]` property and glue + * those in `onEnd`. Override this handler, if you need another behaviour. + **/ +Inflate.prototype.onData = function (chunk) { + this.chunks.push(chunk); +}; + + +/** + * Inflate#onEnd(status) -> Void + * - status (Number): inflate status. 0 (Z_OK) on success, + * other if not. + * + * Called either after you tell inflate that the input stream is + * complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH) + * or if an error happened. By default - join collected chunks, + * free memory and fill `results` / `err` properties. + **/ +Inflate.prototype.onEnd = function (status) { + // On success - join + if (status === c.Z_OK) { + if (this.options.to === 'string') { + // Glue & convert here, until we teach pako to send + // utf8 aligned strings to onData + this.result = this.chunks.join(''); + } else { + this.result = utils.flattenChunks(this.chunks); + } + } + this.chunks = []; + this.err = status; + this.msg = this.strm.msg; +}; + + +/** + * inflate(data[, options]) -> Uint8Array|Array|String + * - data (Uint8Array|Array|String): input data to decompress. + * - options (Object): zlib inflate options. + * + * Decompress `data` with inflate/ungzip and `options`. Autodetect + * format via wrapper header by default. That's why we don't provide + * separate `ungzip` method. + * + * Supported options are: + * + * - windowBits + * + * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) + * for more information. + * + * Sugar (options): + * + * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify + * negative windowBits implicitly. + * - `to` (String) - if equal to 'string', then result will be converted + * from utf8 to utf16 (javascript) string. When string output requested, + * chunk length can differ from `chunkSize`, depending on content. + * + * + * ##### Example: + * + * ```javascript + * var pako = require('pako') + * , input = pako.deflate([1,2,3,4,5,6,7,8,9]) + * , output; + * + * try { + * output = pako.inflate(input); + * } catch (err) + * console.log(err); + * } + * ``` + **/ +function inflate(input, options) { + var inflator = new Inflate(options); + + inflator.push(input, true); + + // That will never happens, if you don't cheat with options :) + if (inflator.err) { throw inflator.msg || msg[inflator.err]; } + + return inflator.result; +} + + +/** + * inflateRaw(data[, options]) -> Uint8Array|Array|String + * - data (Uint8Array|Array|String): input data to decompress. + * - options (Object): zlib inflate options. + * + * The same as [[inflate]], but creates raw data, without wrapper + * (header and adler32 crc). + **/ +function inflateRaw(input, options) { + options = options || {}; + options.raw = true; + return inflate(input, options); +} + + +/** + * ungzip(data[, options]) -> Uint8Array|Array|String + * - data (Uint8Array|Array|String): input data to decompress. + * - options (Object): zlib inflate options. + * + * Just shortcut to [[inflate]], because it autodetects format + * by header.content. Done for convenience. + **/ + + +exports.Inflate = Inflate; +exports.inflate = inflate; +exports.inflateRaw = inflateRaw; +exports.ungzip = inflate; + +},{"./utils/common":53,"./utils/strings":54,"./zlib/constants":56,"./zlib/gzheader":59,"./zlib/inflate":61,"./zlib/messages":63,"./zlib/zstream":65}],53:[function(require,module,exports){ +'use strict'; + + +var TYPED_OK = (typeof Uint8Array !== 'undefined') && + (typeof Uint16Array !== 'undefined') && + (typeof Int32Array !== 'undefined'); + +function _has(obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key); +} + +exports.assign = function (obj /*from1, from2, from3, ...*/) { + var sources = Array.prototype.slice.call(arguments, 1); + while (sources.length) { + var source = sources.shift(); + if (!source) { continue; } + + if (typeof source !== 'object') { + throw new TypeError(source + 'must be non-object'); + } + + for (var p in source) { + if (_has(source, p)) { + obj[p] = source[p]; + } + } + } + + return obj; +}; + + +// reduce buffer size, avoiding mem copy +exports.shrinkBuf = function (buf, size) { + if (buf.length === size) { return buf; } + if (buf.subarray) { return buf.subarray(0, size); } + buf.length = size; + return buf; +}; + + +var fnTyped = { + arraySet: function (dest, src, src_offs, len, dest_offs) { + if (src.subarray && dest.subarray) { + dest.set(src.subarray(src_offs, src_offs + len), dest_offs); + return; + } + // Fallback to ordinary array + for (var i = 0; i < len; i++) { + dest[dest_offs + i] = src[src_offs + i]; + } + }, + // Join array of chunks to single array. + flattenChunks: function (chunks) { + var i, l, len, pos, chunk, result; + + // calculate data length + len = 0; + for (i = 0, l = chunks.length; i < l; i++) { + len += chunks[i].length; + } + + // join chunks + result = new Uint8Array(len); + pos = 0; + for (i = 0, l = chunks.length; i < l; i++) { + chunk = chunks[i]; + result.set(chunk, pos); + pos += chunk.length; + } + + return result; + } +}; + +var fnUntyped = { + arraySet: function (dest, src, src_offs, len, dest_offs) { + for (var i = 0; i < len; i++) { + dest[dest_offs + i] = src[src_offs + i]; + } + }, + // Join array of chunks to single array. + flattenChunks: function (chunks) { + return [].concat.apply([], chunks); + } +}; + + +// Enable/Disable typed arrays use, for testing +// +exports.setTyped = function (on) { + if (on) { + exports.Buf8 = Uint8Array; + exports.Buf16 = Uint16Array; + exports.Buf32 = Int32Array; + exports.assign(exports, fnTyped); + } else { + exports.Buf8 = Array; + exports.Buf16 = Array; + exports.Buf32 = Array; + exports.assign(exports, fnUntyped); + } +}; + +exports.setTyped(TYPED_OK); + +},{}],54:[function(require,module,exports){ +// String encode/decode helpers +'use strict'; + + +var utils = require('./common'); + + +// Quick check if we can use fast array to bin string conversion +// +// - apply(Array) can fail on Android 2.2 +// - apply(Uint8Array) can fail on iOS 5.1 Safari +// +var STR_APPLY_OK = true; +var STR_APPLY_UIA_OK = true; + +try { String.fromCharCode.apply(null, [ 0 ]); } catch (__) { STR_APPLY_OK = false; } +try { String.fromCharCode.apply(null, new Uint8Array(1)); } catch (__) { STR_APPLY_UIA_OK = false; } + + +// Table with utf8 lengths (calculated by first byte of sequence) +// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS, +// because max possible codepoint is 0x10ffff +var _utf8len = new utils.Buf8(256); +for (var q = 0; q < 256; q++) { + _utf8len[q] = (q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1); +} +_utf8len[254] = _utf8len[254] = 1; // Invalid sequence start + + +// convert string to array (typed, when possible) +exports.string2buf = function (str) { + var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0; + + // count binary size + for (m_pos = 0; m_pos < str_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) { + c2 = str.charCodeAt(m_pos + 1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; + } + } + buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4; + } + + // allocate buffer + buf = new utils.Buf8(buf_len); + + // convert + for (i = 0, m_pos = 0; i < buf_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) { + c2 = str.charCodeAt(m_pos + 1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; + } + } + if (c < 0x80) { + /* one byte */ + buf[i++] = c; + } else if (c < 0x800) { + /* two bytes */ + buf[i++] = 0xC0 | (c >>> 6); + buf[i++] = 0x80 | (c & 0x3f); + } else if (c < 0x10000) { + /* three bytes */ + buf[i++] = 0xE0 | (c >>> 12); + buf[i++] = 0x80 | (c >>> 6 & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); + } else { + /* four bytes */ + buf[i++] = 0xf0 | (c >>> 18); + buf[i++] = 0x80 | (c >>> 12 & 0x3f); + buf[i++] = 0x80 | (c >>> 6 & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); + } + } + + return buf; +}; + +// Helper (used in 2 places) +function buf2binstring(buf, len) { + // use fallback for big arrays to avoid stack overflow + if (len < 65537) { + if ((buf.subarray && STR_APPLY_UIA_OK) || (!buf.subarray && STR_APPLY_OK)) { + return String.fromCharCode.apply(null, utils.shrinkBuf(buf, len)); + } + } + + var result = ''; + for (var i = 0; i < len; i++) { + result += String.fromCharCode(buf[i]); + } + return result; +} + + +// Convert byte array to binary string +exports.buf2binstring = function (buf) { + return buf2binstring(buf, buf.length); +}; + + +// Convert binary string (typed, when possible) +exports.binstring2buf = function (str) { + var buf = new utils.Buf8(str.length); + for (var i = 0, len = buf.length; i < len; i++) { + buf[i] = str.charCodeAt(i); + } + return buf; +}; + + +// convert array to string +exports.buf2string = function (buf, max) { + var i, out, c, c_len; + var len = max || buf.length; + + // Reserve max possible length (2 words per char) + // NB: by unknown reasons, Array is significantly faster for + // String.fromCharCode.apply than Uint16Array. + var utf16buf = new Array(len * 2); + + for (out = 0, i = 0; i < len;) { + c = buf[i++]; + // quick process ascii + if (c < 0x80) { utf16buf[out++] = c; continue; } + + c_len = _utf8len[c]; + // skip 5 & 6 byte codes + if (c_len > 4) { utf16buf[out++] = 0xfffd; i += c_len - 1; continue; } + + // apply mask on first byte + c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07; + // join the rest + while (c_len > 1 && i < len) { + c = (c << 6) | (buf[i++] & 0x3f); + c_len--; + } + + // terminated by end of string? + if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; } + + if (c < 0x10000) { + utf16buf[out++] = c; + } else { + c -= 0x10000; + utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff); + utf16buf[out++] = 0xdc00 | (c & 0x3ff); + } + } + + return buf2binstring(utf16buf, out); +}; + + +// Calculate max possible position in utf8 buffer, +// that will not break sequence. If that's not possible +// - (very small limits) return max size as is. +// +// buf[] - utf8 bytes array +// max - length limit (mandatory); +exports.utf8border = function (buf, max) { + var pos; + + max = max || buf.length; + if (max > buf.length) { max = buf.length; } + + // go back from last position, until start of sequence found + pos = max - 1; + while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; } + + // Very small and broken sequence, + // return max, because we should return something anyway. + if (pos < 0) { return max; } + + // If we came to start of buffer - that means buffer is too small, + // return max too. + if (pos === 0) { return max; } + + return (pos + _utf8len[buf[pos]] > max) ? pos : max; +}; + +},{"./common":53}],55:[function(require,module,exports){ +'use strict'; + +// Note: adler32 takes 12% for level 0 and 2% for level 6. +// It isn't worth it to make additional optimizations as in original. +// Small size is preferable. + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +function adler32(adler, buf, len, pos) { + var s1 = (adler & 0xffff) |0, + s2 = ((adler >>> 16) & 0xffff) |0, + n = 0; + + while (len !== 0) { + // Set limit ~ twice less than 5552, to keep + // s2 in 31-bits, because we force signed ints. + // in other case %= will fail. + n = len > 2000 ? 2000 : len; + len -= n; + + do { + s1 = (s1 + buf[pos++]) |0; + s2 = (s2 + s1) |0; + } while (--n); + + s1 %= 65521; + s2 %= 65521; + } + + return (s1 | (s2 << 16)) |0; +} + + +module.exports = adler32; + +},{}],56:[function(require,module,exports){ +'use strict'; + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +module.exports = { + + /* Allowed flush values; see deflate() and inflate() below for details */ + Z_NO_FLUSH: 0, + Z_PARTIAL_FLUSH: 1, + Z_SYNC_FLUSH: 2, + Z_FULL_FLUSH: 3, + Z_FINISH: 4, + Z_BLOCK: 5, + Z_TREES: 6, + + /* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + Z_OK: 0, + Z_STREAM_END: 1, + Z_NEED_DICT: 2, + Z_ERRNO: -1, + Z_STREAM_ERROR: -2, + Z_DATA_ERROR: -3, + //Z_MEM_ERROR: -4, + Z_BUF_ERROR: -5, + //Z_VERSION_ERROR: -6, + + /* compression levels */ + Z_NO_COMPRESSION: 0, + Z_BEST_SPEED: 1, + Z_BEST_COMPRESSION: 9, + Z_DEFAULT_COMPRESSION: -1, + + + Z_FILTERED: 1, + Z_HUFFMAN_ONLY: 2, + Z_RLE: 3, + Z_FIXED: 4, + Z_DEFAULT_STRATEGY: 0, + + /* Possible values of the data_type field (though see inflate()) */ + Z_BINARY: 0, + Z_TEXT: 1, + //Z_ASCII: 1, // = Z_TEXT (deprecated) + Z_UNKNOWN: 2, + + /* The deflate compression method */ + Z_DEFLATED: 8 + //Z_NULL: null // Use -1 or null inline, depending on var type +}; + +},{}],57:[function(require,module,exports){ +'use strict'; + +// Note: we can't get significant speed boost here. +// So write code to minimize size - no pregenerated tables +// and array tools dependencies. + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +// Use ordinary array, since untyped makes no boost here +function makeTable() { + var c, table = []; + + for (var n = 0; n < 256; n++) { + c = n; + for (var k = 0; k < 8; k++) { + c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); + } + table[n] = c; + } + + return table; +} + +// Create table on load. Just 255 signed longs. Not a problem. +var crcTable = makeTable(); + + +function crc32(crc, buf, len, pos) { + var t = crcTable, + end = pos + len; + + crc ^= -1; + + for (var i = pos; i < end; i++) { + crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF]; + } + + return (crc ^ (-1)); // >>> 0; +} + + +module.exports = crc32; + +},{}],58:[function(require,module,exports){ +'use strict'; + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +var utils = require('../utils/common'); +var trees = require('./trees'); +var adler32 = require('./adler32'); +var crc32 = require('./crc32'); +var msg = require('./messages'); + +/* Public constants ==========================================================*/ +/* ===========================================================================*/ + + +/* Allowed flush values; see deflate() and inflate() below for details */ +var Z_NO_FLUSH = 0; +var Z_PARTIAL_FLUSH = 1; +//var Z_SYNC_FLUSH = 2; +var Z_FULL_FLUSH = 3; +var Z_FINISH = 4; +var Z_BLOCK = 5; +//var Z_TREES = 6; + + +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ +var Z_OK = 0; +var Z_STREAM_END = 1; +//var Z_NEED_DICT = 2; +//var Z_ERRNO = -1; +var Z_STREAM_ERROR = -2; +var Z_DATA_ERROR = -3; +//var Z_MEM_ERROR = -4; +var Z_BUF_ERROR = -5; +//var Z_VERSION_ERROR = -6; + + +/* compression levels */ +//var Z_NO_COMPRESSION = 0; +//var Z_BEST_SPEED = 1; +//var Z_BEST_COMPRESSION = 9; +var Z_DEFAULT_COMPRESSION = -1; + + +var Z_FILTERED = 1; +var Z_HUFFMAN_ONLY = 2; +var Z_RLE = 3; +var Z_FIXED = 4; +var Z_DEFAULT_STRATEGY = 0; + +/* Possible values of the data_type field (though see inflate()) */ +//var Z_BINARY = 0; +//var Z_TEXT = 1; +//var Z_ASCII = 1; // = Z_TEXT +var Z_UNKNOWN = 2; + + +/* The deflate compression method */ +var Z_DEFLATED = 8; + +/*============================================================================*/ + + +var MAX_MEM_LEVEL = 9; +/* Maximum value for memLevel in deflateInit2 */ +var MAX_WBITS = 15; +/* 32K LZ77 window */ +var DEF_MEM_LEVEL = 8; + + +var LENGTH_CODES = 29; +/* number of length codes, not counting the special END_BLOCK code */ +var LITERALS = 256; +/* number of literal bytes 0..255 */ +var L_CODES = LITERALS + 1 + LENGTH_CODES; +/* number of Literal or Length codes, including the END_BLOCK code */ +var D_CODES = 30; +/* number of distance codes */ +var BL_CODES = 19; +/* number of codes used to transfer the bit lengths */ +var HEAP_SIZE = 2 * L_CODES + 1; +/* maximum heap size */ +var MAX_BITS = 15; +/* All codes must not exceed MAX_BITS bits */ + +var MIN_MATCH = 3; +var MAX_MATCH = 258; +var MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1); + +var PRESET_DICT = 0x20; + +var INIT_STATE = 42; +var EXTRA_STATE = 69; +var NAME_STATE = 73; +var COMMENT_STATE = 91; +var HCRC_STATE = 103; +var BUSY_STATE = 113; +var FINISH_STATE = 666; + +var BS_NEED_MORE = 1; /* block not completed, need more input or more output */ +var BS_BLOCK_DONE = 2; /* block flush performed */ +var BS_FINISH_STARTED = 3; /* finish started, need only more output at next deflate */ +var BS_FINISH_DONE = 4; /* finish done, accept no more input or output */ + +var OS_CODE = 0x03; // Unix :) . Don't detect, use this default. + +function err(strm, errorCode) { + strm.msg = msg[errorCode]; + return errorCode; +} + +function rank(f) { + return ((f) << 1) - ((f) > 4 ? 9 : 0); +} + +function zero(buf) { var len = buf.length; while (--len >= 0) { buf[len] = 0; } } + + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->output buffer and copying into it. + * (See also read_buf()). + */ +function flush_pending(strm) { + var s = strm.state; + + //_tr_flush_bits(s); + var len = s.pending; + if (len > strm.avail_out) { + len = strm.avail_out; + } + if (len === 0) { return; } + + utils.arraySet(strm.output, s.pending_buf, s.pending_out, len, strm.next_out); + strm.next_out += len; + s.pending_out += len; + strm.total_out += len; + strm.avail_out -= len; + s.pending -= len; + if (s.pending === 0) { + s.pending_out = 0; + } +} + + +function flush_block_only(s, last) { + trees._tr_flush_block(s, (s.block_start >= 0 ? s.block_start : -1), s.strstart - s.block_start, last); + s.block_start = s.strstart; + flush_pending(s.strm); +} + + +function put_byte(s, b) { + s.pending_buf[s.pending++] = b; +} + + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +function putShortMSB(s, b) { +// put_byte(s, (Byte)(b >> 8)); +// put_byte(s, (Byte)(b & 0xff)); + s.pending_buf[s.pending++] = (b >>> 8) & 0xff; + s.pending_buf[s.pending++] = b & 0xff; +} + + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->input buffer and copying from it. + * (See also flush_pending()). + */ +function read_buf(strm, buf, start, size) { + var len = strm.avail_in; + + if (len > size) { len = size; } + if (len === 0) { return 0; } + + strm.avail_in -= len; + + // zmemcpy(buf, strm->next_in, len); + utils.arraySet(buf, strm.input, strm.next_in, len, start); + if (strm.state.wrap === 1) { + strm.adler = adler32(strm.adler, buf, len, start); + } + + else if (strm.state.wrap === 2) { + strm.adler = crc32(strm.adler, buf, len, start); + } + + strm.next_in += len; + strm.total_in += len; + + return len; +} + + +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +function longest_match(s, cur_match) { + var chain_length = s.max_chain_length; /* max hash chain length */ + var scan = s.strstart; /* current string */ + var match; /* matched string */ + var len; /* length of current match */ + var best_len = s.prev_length; /* best match length so far */ + var nice_match = s.nice_match; /* stop if match long enough */ + var limit = (s.strstart > (s.w_size - MIN_LOOKAHEAD)) ? + s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0/*NIL*/; + + var _win = s.window; // shortcut + + var wmask = s.w_mask; + var prev = s.prev; + + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + + var strend = s.strstart + MAX_MATCH; + var scan_end1 = _win[scan + best_len - 1]; + var scan_end = _win[scan + best_len]; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + // Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s.prev_length >= s.good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if (nice_match > s.lookahead) { nice_match = s.lookahead; } + + // Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + // Assert(cur_match < s->strstart, "no future"); + match = cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2. Note that the checks below + * for insufficient lookahead only occur occasionally for performance + * reasons. Therefore uninitialized memory will be accessed, and + * conditional jumps will be made that depend on those values. + * However the length of the match is limited to the lookahead, so + * the output of deflate is not affected by the uninitialized values. + */ + + if (_win[match + best_len] !== scan_end || + _win[match + best_len - 1] !== scan_end1 || + _win[match] !== _win[scan] || + _win[++match] !== _win[scan + 1]) { + continue; + } + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2; + match++; + // Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + /*jshint noempty:false*/ + } while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + scan < strend); + + // Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (strend - scan); + scan = strend - MAX_MATCH; + + if (len > best_len) { + s.match_start = cur_match; + best_len = len; + if (len >= nice_match) { + break; + } + scan_end1 = _win[scan + best_len - 1]; + scan_end = _win[scan + best_len]; + } + } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0); + + if (best_len <= s.lookahead) { + return best_len; + } + return s.lookahead; +} + + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +function fill_window(s) { + var _w_size = s.w_size; + var p, n, m, more, str; + + //Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); + + do { + more = s.window_size - s.lookahead - s.strstart; + + // JS ints have 32 bit, block below not needed + /* Deal with !@#$% 64K limit: */ + //if (sizeof(int) <= 2) { + // if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + // more = wsize; + // + // } else if (more == (unsigned)(-1)) { + // /* Very unlikely, but possible on 16 bit machine if + // * strstart == 0 && lookahead == 1 (input done a byte at time) + // */ + // more--; + // } + //} + + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) { + + utils.arraySet(s.window, s.window, _w_size, _w_size, 0); + s.match_start -= _w_size; + s.strstart -= _w_size; + /* we now have strstart >= MAX_DIST */ + s.block_start -= _w_size; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + + n = s.hash_size; + p = n; + do { + m = s.head[--p]; + s.head[p] = (m >= _w_size ? m - _w_size : 0); + } while (--n); + + n = _w_size; + p = n; + do { + m = s.prev[--p]; + s.prev[p] = (m >= _w_size ? m - _w_size : 0); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); + + more += _w_size; + } + if (s.strm.avail_in === 0) { + break; + } + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + //Assert(more >= 2, "more < 2"); + n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more); + s.lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s.lookahead + s.insert >= MIN_MATCH) { + str = s.strstart - s.insert; + s.ins_h = s.window[str]; + + /* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + 1]) & s.hash_mask; +//#if MIN_MATCH != 3 +// Call update_hash() MIN_MATCH-3 more times +//#endif + while (s.insert) { + /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH - 1]) & s.hash_mask; + + s.prev[str & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = str; + str++; + s.insert--; + if (s.lookahead + s.insert < MIN_MATCH) { + break; + } + } + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0); + + /* If the WIN_INIT bytes after the end of the current data have never been + * written, then zero those bytes in order to avoid memory check reports of + * the use of uninitialized (or uninitialised as Julian writes) bytes by + * the longest match routines. Update the high water mark for the next + * time through here. WIN_INIT is set to MAX_MATCH since the longest match + * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. + */ +// if (s.high_water < s.window_size) { +// var curr = s.strstart + s.lookahead; +// var init = 0; +// +// if (s.high_water < curr) { +// /* Previous high water mark below current data -- zero WIN_INIT +// * bytes or up to end of window, whichever is less. +// */ +// init = s.window_size - curr; +// if (init > WIN_INIT) +// init = WIN_INIT; +// zmemzero(s->window + curr, (unsigned)init); +// s->high_water = curr + init; +// } +// else if (s->high_water < (ulg)curr + WIN_INIT) { +// /* High water mark at or above current data, but below current data +// * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up +// * to end of window, whichever is less. +// */ +// init = (ulg)curr + WIN_INIT - s->high_water; +// if (init > s->window_size - s->high_water) +// init = s->window_size - s->high_water; +// zmemzero(s->window + s->high_water, (unsigned)init); +// s->high_water += init; +// } +// } +// +// Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, +// "not enough room for search"); +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +function deflate_stored(s, flush) { + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + var max_block_size = 0xffff; + + if (max_block_size > s.pending_buf_size - 5) { + max_block_size = s.pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s.lookahead <= 1) { + + //Assert(s->strstart < s->w_size+MAX_DIST(s) || + // s->block_start >= (long)s->w_size, "slide too late"); +// if (!(s.strstart < s.w_size + (s.w_size - MIN_LOOKAHEAD) || +// s.block_start >= s.w_size)) { +// throw new Error("slide too late"); +// } + + fill_window(s); + if (s.lookahead === 0 && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + + if (s.lookahead === 0) { + break; + } + /* flush the current block */ + } + //Assert(s->block_start >= 0L, "block gone"); +// if (s.block_start < 0) throw new Error("block gone"); + + s.strstart += s.lookahead; + s.lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + var max_start = s.block_start + max_block_size; + + if (s.strstart === 0 || s.strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s.lookahead = s.strstart - max_start; + s.strstart = max_start; + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + + + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s.strstart - s.block_start >= (s.w_size - MIN_LOOKAHEAD)) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + + s.insert = 0; + + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + + if (s.strstart > s.block_start) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + + return BS_NEED_MORE; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +function deflate_fast(s, flush) { + var hash_head; /* head of the hash chain */ + var bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s.lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { + break; /* flush the current block */ + } + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = 0/*NIL*/; + if (s.lookahead >= MIN_MATCH) { + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head !== 0/*NIL*/ && ((s.strstart - hash_head) <= (s.w_size - MIN_LOOKAHEAD))) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s.match_length = longest_match(s, hash_head); + /* longest_match() sets match_start */ + } + if (s.match_length >= MIN_MATCH) { + // check_match(s, s.strstart, s.match_start, s.match_length); // for debug only + + /*** _tr_tally_dist(s, s.strstart - s.match_start, + s.match_length - MIN_MATCH, bflush); ***/ + bflush = trees._tr_tally(s, s.strstart - s.match_start, s.match_length - MIN_MATCH); + + s.lookahead -= s.match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ + if (s.match_length <= s.max_lazy_match/*max_insert_length*/ && s.lookahead >= MIN_MATCH) { + s.match_length--; /* string at strstart already in table */ + do { + s.strstart++; + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s.match_length !== 0); + s.strstart++; + } else + { + s.strstart += s.match_length; + s.match_length = 0; + s.ins_h = s.window[s.strstart]; + /* UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]); */ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + 1]) & s.hash_mask; + +//#if MIN_MATCH != 3 +// Call UPDATE_HASH() MIN_MATCH-3 more times +//#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + //Tracevv((stderr,"%c", s.window[s.strstart])); + /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ + bflush = trees._tr_tally(s, 0, s.window[s.strstart]); + + s.lookahead--; + s.strstart++; + } + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + s.insert = ((s.strstart < (MIN_MATCH - 1)) ? s.strstart : MIN_MATCH - 1); + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + return BS_BLOCK_DONE; +} + +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +function deflate_slow(s, flush) { + var hash_head; /* head of hash chain */ + var bflush; /* set if current block must be flushed */ + + var max_insert; + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s.lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { break; } /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = 0/*NIL*/; + if (s.lookahead >= MIN_MATCH) { + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + } + + /* Find the longest match, discarding those <= prev_length. + */ + s.prev_length = s.match_length; + s.prev_match = s.match_start; + s.match_length = MIN_MATCH - 1; + + if (hash_head !== 0/*NIL*/ && s.prev_length < s.max_lazy_match && + s.strstart - hash_head <= (s.w_size - MIN_LOOKAHEAD)/*MAX_DIST(s)*/) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s.match_length = longest_match(s, hash_head); + /* longest_match() sets match_start */ + + if (s.match_length <= 5 && + (s.strategy === Z_FILTERED || (s.match_length === MIN_MATCH && s.strstart - s.match_start > 4096/*TOO_FAR*/))) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s.match_length = MIN_MATCH - 1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s.prev_length >= MIN_MATCH && s.match_length <= s.prev_length) { + max_insert = s.strstart + s.lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + //check_match(s, s.strstart-1, s.prev_match, s.prev_length); + + /***_tr_tally_dist(s, s.strstart - 1 - s.prev_match, + s.prev_length - MIN_MATCH, bflush);***/ + bflush = trees._tr_tally(s, s.strstart - 1 - s.prev_match, s.prev_length - MIN_MATCH); + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s.lookahead -= s.prev_length - 1; + s.prev_length -= 2; + do { + if (++s.strstart <= max_insert) { + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + } + } while (--s.prev_length !== 0); + s.match_available = 0; + s.match_length = MIN_MATCH - 1; + s.strstart++; + + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + + } else if (s.match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + //Tracevv((stderr,"%c", s->window[s->strstart-1])); + /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ + bflush = trees._tr_tally(s, 0, s.window[s.strstart - 1]); + + if (bflush) { + /*** FLUSH_BLOCK_ONLY(s, 0) ***/ + flush_block_only(s, false); + /***/ + } + s.strstart++; + s.lookahead--; + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s.match_available = 1; + s.strstart++; + s.lookahead--; + } + } + //Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s.match_available) { + //Tracevv((stderr,"%c", s->window[s->strstart-1])); + /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ + bflush = trees._tr_tally(s, 0, s.window[s.strstart - 1]); + + s.match_available = 0; + } + s.insert = s.strstart < MIN_MATCH - 1 ? s.strstart : MIN_MATCH - 1; + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + + return BS_BLOCK_DONE; +} + + +/* =========================================================================== + * For Z_RLE, simply look for runs of bytes, generate matches only of distance + * one. Do not maintain a hash table. (It will be regenerated if this run of + * deflate switches away from Z_RLE.) + */ +function deflate_rle(s, flush) { + var bflush; /* set if current block must be flushed */ + var prev; /* byte at distance one to match */ + var scan, strend; /* scan goes up to strend for length of run */ + + var _win = s.window; + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the longest run, plus one for the unrolled loop. + */ + if (s.lookahead <= MAX_MATCH) { + fill_window(s); + if (s.lookahead <= MAX_MATCH && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { break; } /* flush the current block */ + } + + /* See how many times the previous byte repeats */ + s.match_length = 0; + if (s.lookahead >= MIN_MATCH && s.strstart > 0) { + scan = s.strstart - 1; + prev = _win[scan]; + if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) { + strend = s.strstart + MAX_MATCH; + do { + /*jshint noempty:false*/ + } while (prev === _win[++scan] && prev === _win[++scan] && + prev === _win[++scan] && prev === _win[++scan] && + prev === _win[++scan] && prev === _win[++scan] && + prev === _win[++scan] && prev === _win[++scan] && + scan < strend); + s.match_length = MAX_MATCH - (strend - scan); + if (s.match_length > s.lookahead) { + s.match_length = s.lookahead; + } + } + //Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); + } + + /* Emit match if have run of MIN_MATCH or longer, else emit literal */ + if (s.match_length >= MIN_MATCH) { + //check_match(s, s.strstart, s.strstart - 1, s.match_length); + + /*** _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ***/ + bflush = trees._tr_tally(s, 1, s.match_length - MIN_MATCH); + + s.lookahead -= s.match_length; + s.strstart += s.match_length; + s.match_length = 0; + } else { + /* No match, output a literal byte */ + //Tracevv((stderr,"%c", s->window[s->strstart])); + /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ + bflush = trees._tr_tally(s, 0, s.window[s.strstart]); + + s.lookahead--; + s.strstart++; + } + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + s.insert = 0; + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + return BS_BLOCK_DONE; +} + +/* =========================================================================== + * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. + * (It will be regenerated if this run of deflate switches away from Huffman.) + */ +function deflate_huff(s, flush) { + var bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we have a literal to write. */ + if (s.lookahead === 0) { + fill_window(s); + if (s.lookahead === 0) { + if (flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + break; /* flush the current block */ + } + } + + /* Output a literal byte */ + s.match_length = 0; + //Tracevv((stderr,"%c", s->window[s->strstart])); + /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ + bflush = trees._tr_tally(s, 0, s.window[s.strstart]); + s.lookahead--; + s.strstart++; + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + s.insert = 0; + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + return BS_BLOCK_DONE; +} + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +function Config(good_length, max_lazy, nice_length, max_chain, func) { + this.good_length = good_length; + this.max_lazy = max_lazy; + this.nice_length = nice_length; + this.max_chain = max_chain; + this.func = func; +} + +var configuration_table; + +configuration_table = [ + /* good lazy nice chain */ + new Config(0, 0, 0, 0, deflate_stored), /* 0 store only */ + new Config(4, 4, 8, 4, deflate_fast), /* 1 max speed, no lazy matches */ + new Config(4, 5, 16, 8, deflate_fast), /* 2 */ + new Config(4, 6, 32, 32, deflate_fast), /* 3 */ + + new Config(4, 4, 16, 16, deflate_slow), /* 4 lazy matches */ + new Config(8, 16, 32, 32, deflate_slow), /* 5 */ + new Config(8, 16, 128, 128, deflate_slow), /* 6 */ + new Config(8, 32, 128, 256, deflate_slow), /* 7 */ + new Config(32, 128, 258, 1024, deflate_slow), /* 8 */ + new Config(32, 258, 258, 4096, deflate_slow) /* 9 max compression */ +]; + + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +function lm_init(s) { + s.window_size = 2 * s.w_size; + + /*** CLEAR_HASH(s); ***/ + zero(s.head); // Fill with NIL (= 0); + + /* Set the default configuration parameters: + */ + s.max_lazy_match = configuration_table[s.level].max_lazy; + s.good_match = configuration_table[s.level].good_length; + s.nice_match = configuration_table[s.level].nice_length; + s.max_chain_length = configuration_table[s.level].max_chain; + + s.strstart = 0; + s.block_start = 0; + s.lookahead = 0; + s.insert = 0; + s.match_length = s.prev_length = MIN_MATCH - 1; + s.match_available = 0; + s.ins_h = 0; +} + + +function DeflateState() { + this.strm = null; /* pointer back to this zlib stream */ + this.status = 0; /* as the name implies */ + this.pending_buf = null; /* output still pending */ + this.pending_buf_size = 0; /* size of pending_buf */ + this.pending_out = 0; /* next pending byte to output to the stream */ + this.pending = 0; /* nb of bytes in the pending buffer */ + this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ + this.gzhead = null; /* gzip header information to write */ + this.gzindex = 0; /* where in extra, name, or comment */ + this.method = Z_DEFLATED; /* can only be DEFLATED */ + this.last_flush = -1; /* value of flush param for previous deflate call */ + + this.w_size = 0; /* LZ77 window size (32K by default) */ + this.w_bits = 0; /* log2(w_size) (8..16) */ + this.w_mask = 0; /* w_size - 1 */ + + this.window = null; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. + */ + + this.window_size = 0; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + this.prev = null; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + this.head = null; /* Heads of the hash chains or NIL. */ + + this.ins_h = 0; /* hash index of string to be inserted */ + this.hash_size = 0; /* number of elements in hash table */ + this.hash_bits = 0; /* log2(hash_size) */ + this.hash_mask = 0; /* hash_size-1 */ + + this.hash_shift = 0; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + this.block_start = 0; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + this.match_length = 0; /* length of best match */ + this.prev_match = 0; /* previous match */ + this.match_available = 0; /* set if previous match exists */ + this.strstart = 0; /* start of string to insert */ + this.match_start = 0; /* start of matching string */ + this.lookahead = 0; /* number of valid bytes ahead in window */ + + this.prev_length = 0; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + this.max_chain_length = 0; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + this.max_lazy_match = 0; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ + // That's alias to max_lazy_match, don't use directly + //this.max_insert_length = 0; + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + this.level = 0; /* compression level (1..9) */ + this.strategy = 0; /* favor or force Huffman coding*/ + + this.good_match = 0; + /* Use a faster search when the previous match is longer than this */ + + this.nice_match = 0; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + + /* Didn't use ct_data typedef below to suppress compiler warning */ + + // struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + // struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + // struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + // Use flat array of DOUBLE size, with interleaved fata, + // because JS does not support effective + this.dyn_ltree = new utils.Buf16(HEAP_SIZE * 2); + this.dyn_dtree = new utils.Buf16((2 * D_CODES + 1) * 2); + this.bl_tree = new utils.Buf16((2 * BL_CODES + 1) * 2); + zero(this.dyn_ltree); + zero(this.dyn_dtree); + zero(this.bl_tree); + + this.l_desc = null; /* desc. for literal tree */ + this.d_desc = null; /* desc. for distance tree */ + this.bl_desc = null; /* desc. for bit length tree */ + + //ush bl_count[MAX_BITS+1]; + this.bl_count = new utils.Buf16(MAX_BITS + 1); + /* number of codes at each bit length for an optimal tree */ + + //int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + this.heap = new utils.Buf16(2 * L_CODES + 1); /* heap used to build the Huffman trees */ + zero(this.heap); + + this.heap_len = 0; /* number of elements in the heap */ + this.heap_max = 0; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + this.depth = new utils.Buf16(2 * L_CODES + 1); //uch depth[2*L_CODES+1]; + zero(this.depth); + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + this.l_buf = 0; /* buffer index for literals or lengths */ + + this.lit_bufsize = 0; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + this.last_lit = 0; /* running index in l_buf */ + + this.d_buf = 0; + /* Buffer index for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + this.opt_len = 0; /* bit length of current block with optimal trees */ + this.static_len = 0; /* bit length of current block with static trees */ + this.matches = 0; /* number of string matches in current block */ + this.insert = 0; /* bytes at end of window left to insert */ + + + this.bi_buf = 0; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + this.bi_valid = 0; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + + // Used for window memory init. We safely ignore it for JS. That makes + // sense only for pointers and memory check tools. + //this.high_water = 0; + /* High water mark offset in window for initialized bytes -- bytes above + * this are set to zero in order to avoid memory check warnings when + * longest match routines access bytes past the input. This is then + * updated to the new high water mark. + */ +} + + +function deflateResetKeep(strm) { + var s; + + if (!strm || !strm.state) { + return err(strm, Z_STREAM_ERROR); + } + + strm.total_in = strm.total_out = 0; + strm.data_type = Z_UNKNOWN; + + s = strm.state; + s.pending = 0; + s.pending_out = 0; + + if (s.wrap < 0) { + s.wrap = -s.wrap; + /* was made negative by deflate(..., Z_FINISH); */ + } + s.status = (s.wrap ? INIT_STATE : BUSY_STATE); + strm.adler = (s.wrap === 2) ? + 0 // crc32(0, Z_NULL, 0) + : + 1; // adler32(0, Z_NULL, 0) + s.last_flush = Z_NO_FLUSH; + trees._tr_init(s); + return Z_OK; +} + + +function deflateReset(strm) { + var ret = deflateResetKeep(strm); + if (ret === Z_OK) { + lm_init(strm.state); + } + return ret; +} + + +function deflateSetHeader(strm, head) { + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + if (strm.state.wrap !== 2) { return Z_STREAM_ERROR; } + strm.state.gzhead = head; + return Z_OK; +} + + +function deflateInit2(strm, level, method, windowBits, memLevel, strategy) { + if (!strm) { // === Z_NULL + return Z_STREAM_ERROR; + } + var wrap = 1; + + if (level === Z_DEFAULT_COMPRESSION) { + level = 6; + } + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } + + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } + + + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method !== Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_FIXED) { + return err(strm, Z_STREAM_ERROR); + } + + + if (windowBits === 8) { + windowBits = 9; + } + /* until 256-byte window bug fixed */ + + var s = new DeflateState(); + + strm.state = s; + s.strm = strm; + + s.wrap = wrap; + s.gzhead = null; + s.w_bits = windowBits; + s.w_size = 1 << s.w_bits; + s.w_mask = s.w_size - 1; + + s.hash_bits = memLevel + 7; + s.hash_size = 1 << s.hash_bits; + s.hash_mask = s.hash_size - 1; + s.hash_shift = ~~((s.hash_bits + MIN_MATCH - 1) / MIN_MATCH); + + s.window = new utils.Buf8(s.w_size * 2); + s.head = new utils.Buf16(s.hash_size); + s.prev = new utils.Buf16(s.w_size); + + // Don't need mem init magic for JS. + //s.high_water = 0; /* nothing written to s->window yet */ + + s.lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + s.pending_buf_size = s.lit_bufsize * 4; + + //overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + //s->pending_buf = (uchf *) overlay; + s.pending_buf = new utils.Buf8(s.pending_buf_size); + + // It is offset from `s.pending_buf` (size is `s.lit_bufsize * 2`) + //s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s.d_buf = 1 * s.lit_bufsize; + + //s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + s.l_buf = (1 + 2) * s.lit_bufsize; + + s.level = level; + s.strategy = strategy; + s.method = method; + + return deflateReset(strm); +} + +function deflateInit(strm, level) { + return deflateInit2(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); +} + + +function deflate(strm, flush) { + var old_flush, s; + var beg, val; // for gzip header write only + + if (!strm || !strm.state || + flush > Z_BLOCK || flush < 0) { + return strm ? err(strm, Z_STREAM_ERROR) : Z_STREAM_ERROR; + } + + s = strm.state; + + if (!strm.output || + (!strm.input && strm.avail_in !== 0) || + (s.status === FINISH_STATE && flush !== Z_FINISH)) { + return err(strm, (strm.avail_out === 0) ? Z_BUF_ERROR : Z_STREAM_ERROR); + } + + s.strm = strm; /* just in case */ + old_flush = s.last_flush; + s.last_flush = flush; + + /* Write the header */ + if (s.status === INIT_STATE) { + + if (s.wrap === 2) { // GZIP header + strm.adler = 0; //crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (!s.gzhead) { // s->gzhead == Z_NULL + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s.level === 9 ? 2 : + (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s.status = BUSY_STATE; + } + else { + put_byte(s, (s.gzhead.text ? 1 : 0) + + (s.gzhead.hcrc ? 2 : 0) + + (!s.gzhead.extra ? 0 : 4) + + (!s.gzhead.name ? 0 : 8) + + (!s.gzhead.comment ? 0 : 16) + ); + put_byte(s, s.gzhead.time & 0xff); + put_byte(s, (s.gzhead.time >> 8) & 0xff); + put_byte(s, (s.gzhead.time >> 16) & 0xff); + put_byte(s, (s.gzhead.time >> 24) & 0xff); + put_byte(s, s.level === 9 ? 2 : + (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? + 4 : 0)); + put_byte(s, s.gzhead.os & 0xff); + if (s.gzhead.extra && s.gzhead.extra.length) { + put_byte(s, s.gzhead.extra.length & 0xff); + put_byte(s, (s.gzhead.extra.length >> 8) & 0xff); + } + if (s.gzhead.hcrc) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending, 0); + } + s.gzindex = 0; + s.status = EXTRA_STATE; + } + } + else // DEFLATE header + { + var header = (Z_DEFLATED + ((s.w_bits - 8) << 4)) << 8; + var level_flags = -1; + + if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) { + level_flags = 0; + } else if (s.level < 6) { + level_flags = 1; + } else if (s.level === 6) { + level_flags = 2; + } else { + level_flags = 3; + } + header |= (level_flags << 6); + if (s.strstart !== 0) { header |= PRESET_DICT; } + header += 31 - (header % 31); + + s.status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s.strstart !== 0) { + putShortMSB(s, strm.adler >>> 16); + putShortMSB(s, strm.adler & 0xffff); + } + strm.adler = 1; // adler32(0L, Z_NULL, 0); + } + } + +//#ifdef GZIP + if (s.status === EXTRA_STATE) { + if (s.gzhead.extra/* != Z_NULL*/) { + beg = s.pending; /* start of bytes to update crc */ + + while (s.gzindex < (s.gzhead.extra.length & 0xffff)) { + if (s.pending === s.pending_buf_size) { + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + flush_pending(strm); + beg = s.pending; + if (s.pending === s.pending_buf_size) { + break; + } + } + put_byte(s, s.gzhead.extra[s.gzindex] & 0xff); + s.gzindex++; + } + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + if (s.gzindex === s.gzhead.extra.length) { + s.gzindex = 0; + s.status = NAME_STATE; + } + } + else { + s.status = NAME_STATE; + } + } + if (s.status === NAME_STATE) { + if (s.gzhead.name/* != Z_NULL*/) { + beg = s.pending; /* start of bytes to update crc */ + //int val; + + do { + if (s.pending === s.pending_buf_size) { + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + flush_pending(strm); + beg = s.pending; + if (s.pending === s.pending_buf_size) { + val = 1; + break; + } + } + // JS specific: little magic to add zero terminator to end of string + if (s.gzindex < s.gzhead.name.length) { + val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff; + } else { + val = 0; + } + put_byte(s, val); + } while (val !== 0); + + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + if (val === 0) { + s.gzindex = 0; + s.status = COMMENT_STATE; + } + } + else { + s.status = COMMENT_STATE; + } + } + if (s.status === COMMENT_STATE) { + if (s.gzhead.comment/* != Z_NULL*/) { + beg = s.pending; /* start of bytes to update crc */ + //int val; + + do { + if (s.pending === s.pending_buf_size) { + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + flush_pending(strm); + beg = s.pending; + if (s.pending === s.pending_buf_size) { + val = 1; + break; + } + } + // JS specific: little magic to add zero terminator to end of string + if (s.gzindex < s.gzhead.comment.length) { + val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff; + } else { + val = 0; + } + put_byte(s, val); + } while (val !== 0); + + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + if (val === 0) { + s.status = HCRC_STATE; + } + } + else { + s.status = HCRC_STATE; + } + } + if (s.status === HCRC_STATE) { + if (s.gzhead.hcrc) { + if (s.pending + 2 > s.pending_buf_size) { + flush_pending(strm); + } + if (s.pending + 2 <= s.pending_buf_size) { + put_byte(s, strm.adler & 0xff); + put_byte(s, (strm.adler >> 8) & 0xff); + strm.adler = 0; //crc32(0L, Z_NULL, 0); + s.status = BUSY_STATE; + } + } + else { + s.status = BUSY_STATE; + } + } +//#endif + + /* Flush as much pending output as possible */ + if (s.pending !== 0) { + flush_pending(strm); + if (strm.avail_out === 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s.last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) && + flush !== Z_FINISH) { + return err(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s.status === FINISH_STATE && strm.avail_in !== 0) { + return err(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm.avail_in !== 0 || s.lookahead !== 0 || + (flush !== Z_NO_FLUSH && s.status !== FINISH_STATE)) { + var bstate = (s.strategy === Z_HUFFMAN_ONLY) ? deflate_huff(s, flush) : + (s.strategy === Z_RLE ? deflate_rle(s, flush) : + configuration_table[s.level].func(s, flush)); + + if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) { + s.status = FINISH_STATE; + } + if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) { + if (strm.avail_out === 0) { + s.last_flush = -1; + /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate === BS_BLOCK_DONE) { + if (flush === Z_PARTIAL_FLUSH) { + trees._tr_align(s); + } + else if (flush !== Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ + + trees._tr_stored_block(s, 0, 0, false); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush === Z_FULL_FLUSH) { + /*** CLEAR_HASH(s); ***/ /* forget history */ + zero(s.head); // Fill with NIL (= 0); + + if (s.lookahead === 0) { + s.strstart = 0; + s.block_start = 0; + s.insert = 0; + } + } + } + flush_pending(strm); + if (strm.avail_out === 0) { + s.last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + //Assert(strm->avail_out > 0, "bug2"); + //if (strm.avail_out <= 0) { throw new Error("bug2");} + + if (flush !== Z_FINISH) { return Z_OK; } + if (s.wrap <= 0) { return Z_STREAM_END; } + + /* Write the trailer */ + if (s.wrap === 2) { + put_byte(s, strm.adler & 0xff); + put_byte(s, (strm.adler >> 8) & 0xff); + put_byte(s, (strm.adler >> 16) & 0xff); + put_byte(s, (strm.adler >> 24) & 0xff); + put_byte(s, strm.total_in & 0xff); + put_byte(s, (strm.total_in >> 8) & 0xff); + put_byte(s, (strm.total_in >> 16) & 0xff); + put_byte(s, (strm.total_in >> 24) & 0xff); + } + else + { + putShortMSB(s, strm.adler >>> 16); + putShortMSB(s, strm.adler & 0xffff); + } + + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s.wrap > 0) { s.wrap = -s.wrap; } + /* write the trailer only once! */ + return s.pending !== 0 ? Z_OK : Z_STREAM_END; +} + +function deflateEnd(strm) { + var status; + + if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) { + return Z_STREAM_ERROR; + } + + status = strm.state.status; + if (status !== INIT_STATE && + status !== EXTRA_STATE && + status !== NAME_STATE && + status !== COMMENT_STATE && + status !== HCRC_STATE && + status !== BUSY_STATE && + status !== FINISH_STATE + ) { + return err(strm, Z_STREAM_ERROR); + } + + strm.state = null; + + return status === BUSY_STATE ? err(strm, Z_DATA_ERROR) : Z_OK; +} + + +/* ========================================================================= + * Initializes the compression dictionary from the given byte + * sequence without producing any compressed output. + */ +function deflateSetDictionary(strm, dictionary) { + var dictLength = dictionary.length; + + var s; + var str, n; + var wrap; + var avail; + var next; + var input; + var tmpDict; + + if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) { + return Z_STREAM_ERROR; + } + + s = strm.state; + wrap = s.wrap; + + if (wrap === 2 || (wrap === 1 && s.status !== INIT_STATE) || s.lookahead) { + return Z_STREAM_ERROR; + } + + /* when using zlib wrappers, compute Adler-32 for provided dictionary */ + if (wrap === 1) { + /* adler32(strm->adler, dictionary, dictLength); */ + strm.adler = adler32(strm.adler, dictionary, dictLength, 0); + } + + s.wrap = 0; /* avoid computing Adler-32 in read_buf */ + + /* if dictionary would fill window, just replace the history */ + if (dictLength >= s.w_size) { + if (wrap === 0) { /* already empty otherwise */ + /*** CLEAR_HASH(s); ***/ + zero(s.head); // Fill with NIL (= 0); + s.strstart = 0; + s.block_start = 0; + s.insert = 0; + } + /* use the tail */ + // dictionary = dictionary.slice(dictLength - s.w_size); + tmpDict = new utils.Buf8(s.w_size); + utils.arraySet(tmpDict, dictionary, dictLength - s.w_size, s.w_size, 0); + dictionary = tmpDict; + dictLength = s.w_size; + } + /* insert dictionary into window and hash */ + avail = strm.avail_in; + next = strm.next_in; + input = strm.input; + strm.avail_in = dictLength; + strm.next_in = 0; + strm.input = dictionary; + fill_window(s); + while (s.lookahead >= MIN_MATCH) { + str = s.strstart; + n = s.lookahead - (MIN_MATCH - 1); + do { + /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH - 1]) & s.hash_mask; + + s.prev[str & s.w_mask] = s.head[s.ins_h]; + + s.head[s.ins_h] = str; + str++; + } while (--n); + s.strstart = str; + s.lookahead = MIN_MATCH - 1; + fill_window(s); + } + s.strstart += s.lookahead; + s.block_start = s.strstart; + s.insert = s.lookahead; + s.lookahead = 0; + s.match_length = s.prev_length = MIN_MATCH - 1; + s.match_available = 0; + strm.next_in = next; + strm.input = input; + strm.avail_in = avail; + s.wrap = wrap; + return Z_OK; +} + + +exports.deflateInit = deflateInit; +exports.deflateInit2 = deflateInit2; +exports.deflateReset = deflateReset; +exports.deflateResetKeep = deflateResetKeep; +exports.deflateSetHeader = deflateSetHeader; +exports.deflate = deflate; +exports.deflateEnd = deflateEnd; +exports.deflateSetDictionary = deflateSetDictionary; +exports.deflateInfo = 'pako deflate (from Nodeca project)'; + +/* Not implemented +exports.deflateBound = deflateBound; +exports.deflateCopy = deflateCopy; +exports.deflateParams = deflateParams; +exports.deflatePending = deflatePending; +exports.deflatePrime = deflatePrime; +exports.deflateTune = deflateTune; +*/ + +},{"../utils/common":53,"./adler32":55,"./crc32":57,"./messages":63,"./trees":64}],59:[function(require,module,exports){ +'use strict'; + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +function GZheader() { + /* true if compressed data believed to be text */ + this.text = 0; + /* modification time */ + this.time = 0; + /* extra flags (not used when writing a gzip file) */ + this.xflags = 0; + /* operating system */ + this.os = 0; + /* pointer to extra field or Z_NULL if none */ + this.extra = null; + /* extra field length (valid if extra != Z_NULL) */ + this.extra_len = 0; // Actually, we don't need it in JS, + // but leave for few code modifications + + // + // Setup limits is not necessary because in js we should not preallocate memory + // for inflate use constant limit in 65536 bytes + // + + /* space at extra (only when reading header) */ + // this.extra_max = 0; + /* pointer to zero-terminated file name or Z_NULL */ + this.name = ''; + /* space at name (only when reading header) */ + // this.name_max = 0; + /* pointer to zero-terminated comment or Z_NULL */ + this.comment = ''; + /* space at comment (only when reading header) */ + // this.comm_max = 0; + /* true if there was or will be a header crc */ + this.hcrc = 0; + /* true when done reading gzip header (not used when writing a gzip file) */ + this.done = false; +} + +module.exports = GZheader; + +},{}],60:[function(require,module,exports){ +'use strict'; + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +// See state defs from inflate.js +var BAD = 30; /* got a data error -- remain here until reset */ +var TYPE = 12; /* i: waiting for type bits, including last-flag bit */ + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state.mode === LEN + strm.avail_in >= 6 + strm.avail_out >= 258 + start >= strm.avail_out + state.bits < 8 + + On return, state.mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm.avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm.avail_out >= 258 for each loop to avoid checking for + output space. + */ +module.exports = function inflate_fast(strm, start) { + var state; + var _in; /* local strm.input */ + var last; /* have enough input while in < last */ + var _out; /* local strm.output */ + var beg; /* inflate()'s initial strm.output */ + var end; /* while out < end, enough space available */ +//#ifdef INFLATE_STRICT + var dmax; /* maximum distance from zlib header */ +//#endif + var wsize; /* window size or zero if not using window */ + var whave; /* valid bytes in the window */ + var wnext; /* window write index */ + // Use `s_window` instead `window`, avoid conflict with instrumentation tools + var s_window; /* allocated sliding window, if wsize != 0 */ + var hold; /* local strm.hold */ + var bits; /* local strm.bits */ + var lcode; /* local strm.lencode */ + var dcode; /* local strm.distcode */ + var lmask; /* mask for first level of length codes */ + var dmask; /* mask for first level of distance codes */ + var here; /* retrieved table entry */ + var op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + var len; /* match length, unused bytes */ + var dist; /* match distance */ + var from; /* where to copy match from */ + var from_source; + + + var input, output; // JS specific, because we have no pointers + + /* copy state to local variables */ + state = strm.state; + //here = state.here; + _in = strm.next_in; + input = strm.input; + last = _in + (strm.avail_in - 5); + _out = strm.next_out; + output = strm.output; + beg = _out - (start - strm.avail_out); + end = _out + (strm.avail_out - 257); +//#ifdef INFLATE_STRICT + dmax = state.dmax; +//#endif + wsize = state.wsize; + whave = state.whave; + wnext = state.wnext; + s_window = state.window; + hold = state.hold; + bits = state.bits; + lcode = state.lencode; + dcode = state.distcode; + lmask = (1 << state.lenbits) - 1; + dmask = (1 << state.distbits) - 1; + + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + + top: + do { + if (bits < 15) { + hold += input[_in++] << bits; + bits += 8; + hold += input[_in++] << bits; + bits += 8; + } + + here = lcode[hold & lmask]; + + dolen: + for (;;) { // Goto emulation + op = here >>> 24/*here.bits*/; + hold >>>= op; + bits -= op; + op = (here >>> 16) & 0xff/*here.op*/; + if (op === 0) { /* literal */ + //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + // "inflate: literal '%c'\n" : + // "inflate: literal 0x%02x\n", here.val)); + output[_out++] = here & 0xffff/*here.val*/; + } + else if (op & 16) { /* length base */ + len = here & 0xffff/*here.val*/; + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + } + len += hold & ((1 << op) - 1); + hold >>>= op; + bits -= op; + } + //Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += input[_in++] << bits; + bits += 8; + hold += input[_in++] << bits; + bits += 8; + } + here = dcode[hold & dmask]; + + dodist: + for (;;) { // goto emulation + op = here >>> 24/*here.bits*/; + hold >>>= op; + bits -= op; + op = (here >>> 16) & 0xff/*here.op*/; + + if (op & 16) { /* distance base */ + dist = here & 0xffff/*here.val*/; + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + } + } + dist += hold & ((1 << op) - 1); +//#ifdef INFLATE_STRICT + if (dist > dmax) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD; + break top; + } +//#endif + hold >>>= op; + bits -= op; + //Tracevv((stderr, "inflate: distance %u\n", dist)); + op = _out - beg; /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state.sane) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD; + break top; + } + +// (!) This block is disabled in zlib defaults, +// don't enable it for binary compatibility +//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR +// if (len <= op - whave) { +// do { +// output[_out++] = 0; +// } while (--len); +// continue top; +// } +// len -= op - whave; +// do { +// output[_out++] = 0; +// } while (--op > whave); +// if (op === 0) { +// from = _out - dist; +// do { +// output[_out++] = output[from++]; +// } while (--len); +// continue top; +// } +//#endif + } + from = 0; // window index + from_source = s_window; + if (wnext === 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } + else if (wnext < op) { /* wrap around window */ + from += wsize + wnext - op; + op -= wnext; + if (op < len) { /* some from end of window */ + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = 0; + if (wnext < len) { /* some from start of window */ + op = wnext; + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } + } + else { /* contiguous in window */ + from += wnext - op; + if (op < len) { /* some from window */ + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } + while (len > 2) { + output[_out++] = from_source[from++]; + output[_out++] = from_source[from++]; + output[_out++] = from_source[from++]; + len -= 3; + } + if (len) { + output[_out++] = from_source[from++]; + if (len > 1) { + output[_out++] = from_source[from++]; + } + } + } + else { + from = _out - dist; /* copy direct from output */ + do { /* minimum length is three */ + output[_out++] = output[from++]; + output[_out++] = output[from++]; + output[_out++] = output[from++]; + len -= 3; + } while (len > 2); + if (len) { + output[_out++] = output[from++]; + if (len > 1) { + output[_out++] = output[from++]; + } + } + } + } + else if ((op & 64) === 0) { /* 2nd level distance code */ + here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))]; + continue dodist; + } + else { + strm.msg = 'invalid distance code'; + state.mode = BAD; + break top; + } + + break; // need to emulate goto via "continue" + } + } + else if ((op & 64) === 0) { /* 2nd level length code */ + here = lcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))]; + continue dolen; + } + else if (op & 32) { /* end-of-block */ + //Tracevv((stderr, "inflate: end of block\n")); + state.mode = TYPE; + break top; + } + else { + strm.msg = 'invalid literal/length code'; + state.mode = BAD; + break top; + } + + break; // need to emulate goto via "continue" + } + } while (_in < last && _out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + _in -= len; + bits -= len << 3; + hold &= (1 << bits) - 1; + + /* update state and return */ + strm.next_in = _in; + strm.next_out = _out; + strm.avail_in = (_in < last ? 5 + (last - _in) : 5 - (_in - last)); + strm.avail_out = (_out < end ? 257 + (end - _out) : 257 - (_out - end)); + state.hold = hold; + state.bits = bits; + return; +}; + +},{}],61:[function(require,module,exports){ +'use strict'; + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +var utils = require('../utils/common'); +var adler32 = require('./adler32'); +var crc32 = require('./crc32'); +var inflate_fast = require('./inffast'); +var inflate_table = require('./inftrees'); + +var CODES = 0; +var LENS = 1; +var DISTS = 2; + +/* Public constants ==========================================================*/ +/* ===========================================================================*/ + + +/* Allowed flush values; see deflate() and inflate() below for details */ +//var Z_NO_FLUSH = 0; +//var Z_PARTIAL_FLUSH = 1; +//var Z_SYNC_FLUSH = 2; +//var Z_FULL_FLUSH = 3; +var Z_FINISH = 4; +var Z_BLOCK = 5; +var Z_TREES = 6; + + +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ +var Z_OK = 0; +var Z_STREAM_END = 1; +var Z_NEED_DICT = 2; +//var Z_ERRNO = -1; +var Z_STREAM_ERROR = -2; +var Z_DATA_ERROR = -3; +var Z_MEM_ERROR = -4; +var Z_BUF_ERROR = -5; +//var Z_VERSION_ERROR = -6; + +/* The deflate compression method */ +var Z_DEFLATED = 8; + + +/* STATES ====================================================================*/ +/* ===========================================================================*/ + + +var HEAD = 1; /* i: waiting for magic header */ +var FLAGS = 2; /* i: waiting for method and flags (gzip) */ +var TIME = 3; /* i: waiting for modification time (gzip) */ +var OS = 4; /* i: waiting for extra flags and operating system (gzip) */ +var EXLEN = 5; /* i: waiting for extra length (gzip) */ +var EXTRA = 6; /* i: waiting for extra bytes (gzip) */ +var NAME = 7; /* i: waiting for end of file name (gzip) */ +var COMMENT = 8; /* i: waiting for end of comment (gzip) */ +var HCRC = 9; /* i: waiting for header crc (gzip) */ +var DICTID = 10; /* i: waiting for dictionary check value */ +var DICT = 11; /* waiting for inflateSetDictionary() call */ +var TYPE = 12; /* i: waiting for type bits, including last-flag bit */ +var TYPEDO = 13; /* i: same, but skip check to exit inflate on new block */ +var STORED = 14; /* i: waiting for stored size (length and complement) */ +var COPY_ = 15; /* i/o: same as COPY below, but only first time in */ +var COPY = 16; /* i/o: waiting for input or output to copy stored block */ +var TABLE = 17; /* i: waiting for dynamic block table lengths */ +var LENLENS = 18; /* i: waiting for code length code lengths */ +var CODELENS = 19; /* i: waiting for length/lit and distance code lengths */ +var LEN_ = 20; /* i: same as LEN below, but only first time in */ +var LEN = 21; /* i: waiting for length/lit/eob code */ +var LENEXT = 22; /* i: waiting for length extra bits */ +var DIST = 23; /* i: waiting for distance code */ +var DISTEXT = 24; /* i: waiting for distance extra bits */ +var MATCH = 25; /* o: waiting for output space to copy string */ +var LIT = 26; /* o: waiting for output space to write literal */ +var CHECK = 27; /* i: waiting for 32-bit check value */ +var LENGTH = 28; /* i: waiting for 32-bit length (gzip) */ +var DONE = 29; /* finished check, done -- remain here until reset */ +var BAD = 30; /* got a data error -- remain here until reset */ +var MEM = 31; /* got an inflate() memory error -- remain here until reset */ +var SYNC = 32; /* looking for synchronization bytes to restart inflate() */ + +/* ===========================================================================*/ + + + +var ENOUGH_LENS = 852; +var ENOUGH_DISTS = 592; +//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); + +var MAX_WBITS = 15; +/* 32K LZ77 window */ +var DEF_WBITS = MAX_WBITS; + + +function zswap32(q) { + return (((q >>> 24) & 0xff) + + ((q >>> 8) & 0xff00) + + ((q & 0xff00) << 8) + + ((q & 0xff) << 24)); +} + + +function InflateState() { + this.mode = 0; /* current inflate mode */ + this.last = false; /* true if processing last block */ + this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ + this.havedict = false; /* true if dictionary provided */ + this.flags = 0; /* gzip header method and flags (0 if zlib) */ + this.dmax = 0; /* zlib header max distance (INFLATE_STRICT) */ + this.check = 0; /* protected copy of check value */ + this.total = 0; /* protected copy of output count */ + // TODO: may be {} + this.head = null; /* where to save gzip header information */ + + /* sliding window */ + this.wbits = 0; /* log base 2 of requested window size */ + this.wsize = 0; /* window size or zero if not using window */ + this.whave = 0; /* valid bytes in the window */ + this.wnext = 0; /* window write index */ + this.window = null; /* allocated sliding window, if needed */ + + /* bit accumulator */ + this.hold = 0; /* input bit accumulator */ + this.bits = 0; /* number of bits in "in" */ + + /* for string and stored block copying */ + this.length = 0; /* literal or length of data to copy */ + this.offset = 0; /* distance back to copy string from */ + + /* for table and code decoding */ + this.extra = 0; /* extra bits needed */ + + /* fixed and dynamic code tables */ + this.lencode = null; /* starting table for length/literal codes */ + this.distcode = null; /* starting table for distance codes */ + this.lenbits = 0; /* index bits for lencode */ + this.distbits = 0; /* index bits for distcode */ + + /* dynamic table building */ + this.ncode = 0; /* number of code length code lengths */ + this.nlen = 0; /* number of length code lengths */ + this.ndist = 0; /* number of distance code lengths */ + this.have = 0; /* number of code lengths in lens[] */ + this.next = null; /* next available space in codes[] */ + + this.lens = new utils.Buf16(320); /* temporary storage for code lengths */ + this.work = new utils.Buf16(288); /* work area for code table building */ + + /* + because we don't have pointers in js, we use lencode and distcode directly + as buffers so we don't need codes + */ + //this.codes = new utils.Buf32(ENOUGH); /* space for code tables */ + this.lendyn = null; /* dynamic table for length/literal codes (JS specific) */ + this.distdyn = null; /* dynamic table for distance codes (JS specific) */ + this.sane = 0; /* if false, allow invalid distance too far */ + this.back = 0; /* bits back of last unprocessed length/lit */ + this.was = 0; /* initial length of match */ +} + +function inflateResetKeep(strm) { + var state; + + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + strm.total_in = strm.total_out = state.total = 0; + strm.msg = ''; /*Z_NULL*/ + if (state.wrap) { /* to support ill-conceived Java test suite */ + strm.adler = state.wrap & 1; + } + state.mode = HEAD; + state.last = 0; + state.havedict = 0; + state.dmax = 32768; + state.head = null/*Z_NULL*/; + state.hold = 0; + state.bits = 0; + //state.lencode = state.distcode = state.next = state.codes; + state.lencode = state.lendyn = new utils.Buf32(ENOUGH_LENS); + state.distcode = state.distdyn = new utils.Buf32(ENOUGH_DISTS); + + state.sane = 1; + state.back = -1; + //Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +function inflateReset(strm) { + var state; + + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + state.wsize = 0; + state.whave = 0; + state.wnext = 0; + return inflateResetKeep(strm); + +} + +function inflateReset2(strm, windowBits) { + var wrap; + var state; + + /* get the state */ + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } + else { + wrap = (windowBits >> 4) + 1; + if (windowBits < 48) { + windowBits &= 15; + } + } + + /* set number of window bits, free window if different */ + if (windowBits && (windowBits < 8 || windowBits > 15)) { + return Z_STREAM_ERROR; + } + if (state.window !== null && state.wbits !== windowBits) { + state.window = null; + } + + /* update state and reset the rest of it */ + state.wrap = wrap; + state.wbits = windowBits; + return inflateReset(strm); +} + +function inflateInit2(strm, windowBits) { + var ret; + var state; + + if (!strm) { return Z_STREAM_ERROR; } + //strm.msg = Z_NULL; /* in case we return an error */ + + state = new InflateState(); + + //if (state === Z_NULL) return Z_MEM_ERROR; + //Tracev((stderr, "inflate: allocated\n")); + strm.state = state; + state.window = null/*Z_NULL*/; + ret = inflateReset2(strm, windowBits); + if (ret !== Z_OK) { + strm.state = null/*Z_NULL*/; + } + return ret; +} + +function inflateInit(strm) { + return inflateInit2(strm, DEF_WBITS); +} + + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +var virgin = true; + +var lenfix, distfix; // We have no pointers in JS, so keep tables separate + +function fixedtables(state) { + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + var sym; + + lenfix = new utils.Buf32(512); + distfix = new utils.Buf32(32); + + /* literal/length table */ + sym = 0; + while (sym < 144) { state.lens[sym++] = 8; } + while (sym < 256) { state.lens[sym++] = 9; } + while (sym < 280) { state.lens[sym++] = 7; } + while (sym < 288) { state.lens[sym++] = 8; } + + inflate_table(LENS, state.lens, 0, 288, lenfix, 0, state.work, { bits: 9 }); + + /* distance table */ + sym = 0; + while (sym < 32) { state.lens[sym++] = 5; } + + inflate_table(DISTS, state.lens, 0, 32, distfix, 0, state.work, { bits: 5 }); + + /* do this just once */ + virgin = false; + } + + state.lencode = lenfix; + state.lenbits = 9; + state.distcode = distfix; + state.distbits = 5; +} + + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +function updatewindow(strm, src, end, copy) { + var dist; + var state = strm.state; + + /* if it hasn't been done already, allocate space for the window */ + if (state.window === null) { + state.wsize = 1 << state.wbits; + state.wnext = 0; + state.whave = 0; + + state.window = new utils.Buf8(state.wsize); + } + + /* copy state->wsize or less output bytes into the circular window */ + if (copy >= state.wsize) { + utils.arraySet(state.window, src, end - state.wsize, state.wsize, 0); + state.wnext = 0; + state.whave = state.wsize; + } + else { + dist = state.wsize - state.wnext; + if (dist > copy) { + dist = copy; + } + //zmemcpy(state->window + state->wnext, end - copy, dist); + utils.arraySet(state.window, src, end - copy, dist, state.wnext); + copy -= dist; + if (copy) { + //zmemcpy(state->window, end - copy, copy); + utils.arraySet(state.window, src, end - copy, copy, 0); + state.wnext = copy; + state.whave = state.wsize; + } + else { + state.wnext += dist; + if (state.wnext === state.wsize) { state.wnext = 0; } + if (state.whave < state.wsize) { state.whave += dist; } + } + } + return 0; +} + +function inflate(strm, flush) { + var state; + var input, output; // input/output buffers + var next; /* next input INDEX */ + var put; /* next output INDEX */ + var have, left; /* available input and output */ + var hold; /* bit buffer */ + var bits; /* bits in bit buffer */ + var _in, _out; /* save starting available input and output */ + var copy; /* number of stored or match bytes to copy */ + var from; /* where to copy match bytes from */ + var from_source; + var here = 0; /* current decoding table entry */ + var here_bits, here_op, here_val; // paked "here" denormalized (JS specific) + //var last; /* parent table entry */ + var last_bits, last_op, last_val; // paked "last" denormalized (JS specific) + var len; /* length to copy for repeats, bits to drop */ + var ret; /* return code */ + var hbuf = new utils.Buf8(4); /* buffer for gzip header crc calculation */ + var opts; + + var n; // temporary var for NEED_BITS + + var order = /* permutation of code lengths */ + [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ]; + + + if (!strm || !strm.state || !strm.output || + (!strm.input && strm.avail_in !== 0)) { + return Z_STREAM_ERROR; + } + + state = strm.state; + if (state.mode === TYPE) { state.mode = TYPEDO; } /* skip check */ + + + //--- LOAD() --- + put = strm.next_out; + output = strm.output; + left = strm.avail_out; + next = strm.next_in; + input = strm.input; + have = strm.avail_in; + hold = state.hold; + bits = state.bits; + //--- + + _in = have; + _out = left; + ret = Z_OK; + + inf_leave: // goto emulation + for (;;) { + switch (state.mode) { + case HEAD: + if (state.wrap === 0) { + state.mode = TYPEDO; + break; + } + //=== NEEDBITS(16); + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if ((state.wrap & 2) && hold === 0x8b1f) { /* gzip header */ + state.check = 0/*crc32(0L, Z_NULL, 0)*/; + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = FLAGS; + break; + } + state.flags = 0; /* expect zlib header */ + if (state.head) { + state.head.done = false; + } + if (!(state.wrap & 1) || /* check if zlib header allowed */ + (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) { + strm.msg = 'incorrect header check'; + state.mode = BAD; + break; + } + if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) { + strm.msg = 'unknown compression method'; + state.mode = BAD; + break; + } + //--- DROPBITS(4) ---// + hold >>>= 4; + bits -= 4; + //---// + len = (hold & 0x0f)/*BITS(4)*/ + 8; + if (state.wbits === 0) { + state.wbits = len; + } + else if (len > state.wbits) { + strm.msg = 'invalid window size'; + state.mode = BAD; + break; + } + state.dmax = 1 << len; + //Tracev((stderr, "inflate: zlib header ok\n")); + strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; + state.mode = hold & 0x200 ? DICTID : TYPE; + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + break; + case FLAGS: + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.flags = hold; + if ((state.flags & 0xff) !== Z_DEFLATED) { + strm.msg = 'unknown compression method'; + state.mode = BAD; + break; + } + if (state.flags & 0xe000) { + strm.msg = 'unknown header flags set'; + state.mode = BAD; + break; + } + if (state.head) { + state.head.text = ((hold >> 8) & 1); + } + if (state.flags & 0x0200) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = TIME; + /* falls through */ + case TIME: + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (state.head) { + state.head.time = hold; + } + if (state.flags & 0x0200) { + //=== CRC4(state.check, hold) + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + hbuf[2] = (hold >>> 16) & 0xff; + hbuf[3] = (hold >>> 24) & 0xff; + state.check = crc32(state.check, hbuf, 4, 0); + //=== + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = OS; + /* falls through */ + case OS: + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (state.head) { + state.head.xflags = (hold & 0xff); + state.head.os = (hold >> 8); + } + if (state.flags & 0x0200) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = EXLEN; + /* falls through */ + case EXLEN: + if (state.flags & 0x0400) { + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.length = hold; + if (state.head) { + state.head.extra_len = hold; + } + if (state.flags & 0x0200) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + } + else if (state.head) { + state.head.extra = null/*Z_NULL*/; + } + state.mode = EXTRA; + /* falls through */ + case EXTRA: + if (state.flags & 0x0400) { + copy = state.length; + if (copy > have) { copy = have; } + if (copy) { + if (state.head) { + len = state.head.extra_len - state.length; + if (!state.head.extra) { + // Use untyped array for more convenient processing later + state.head.extra = new Array(state.head.extra_len); + } + utils.arraySet( + state.head.extra, + input, + next, + // extra field is limited to 65536 bytes + // - no need for additional size check + copy, + /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/ + len + ); + //zmemcpy(state.head.extra + len, next, + // len + copy > state.head.extra_max ? + // state.head.extra_max - len : copy); + } + if (state.flags & 0x0200) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + state.length -= copy; + } + if (state.length) { break inf_leave; } + } + state.length = 0; + state.mode = NAME; + /* falls through */ + case NAME: + if (state.flags & 0x0800) { + if (have === 0) { break inf_leave; } + copy = 0; + do { + // TODO: 2 or 1 bytes? + len = input[next + copy++]; + /* use constant limit because in js we should not preallocate memory */ + if (state.head && len && + (state.length < 65536 /*state.head.name_max*/)) { + state.head.name += String.fromCharCode(len); + } + } while (len && copy < have); + + if (state.flags & 0x0200) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + if (len) { break inf_leave; } + } + else if (state.head) { + state.head.name = null; + } + state.length = 0; + state.mode = COMMENT; + /* falls through */ + case COMMENT: + if (state.flags & 0x1000) { + if (have === 0) { break inf_leave; } + copy = 0; + do { + len = input[next + copy++]; + /* use constant limit because in js we should not preallocate memory */ + if (state.head && len && + (state.length < 65536 /*state.head.comm_max*/)) { + state.head.comment += String.fromCharCode(len); + } + } while (len && copy < have); + if (state.flags & 0x0200) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + if (len) { break inf_leave; } + } + else if (state.head) { + state.head.comment = null; + } + state.mode = HCRC; + /* falls through */ + case HCRC: + if (state.flags & 0x0200) { + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (hold !== (state.check & 0xffff)) { + strm.msg = 'header crc mismatch'; + state.mode = BAD; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + } + if (state.head) { + state.head.hcrc = ((state.flags >> 9) & 1); + state.head.done = true; + } + strm.adler = state.check = 0; + state.mode = TYPE; + break; + case DICTID: + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + strm.adler = state.check = zswap32(hold); + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = DICT; + /* falls through */ + case DICT: + if (state.havedict === 0) { + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + return Z_NEED_DICT; + } + strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; + state.mode = TYPE; + /* falls through */ + case TYPE: + if (flush === Z_BLOCK || flush === Z_TREES) { break inf_leave; } + /* falls through */ + case TYPEDO: + if (state.last) { + //--- BYTEBITS() ---// + hold >>>= bits & 7; + bits -= bits & 7; + //---// + state.mode = CHECK; + break; + } + //=== NEEDBITS(3); */ + while (bits < 3) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.last = (hold & 0x01)/*BITS(1)*/; + //--- DROPBITS(1) ---// + hold >>>= 1; + bits -= 1; + //---// + + switch ((hold & 0x03)/*BITS(2)*/) { + case 0: /* stored block */ + //Tracev((stderr, "inflate: stored block%s\n", + // state.last ? " (last)" : "")); + state.mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + //Tracev((stderr, "inflate: fixed codes block%s\n", + // state.last ? " (last)" : "")); + state.mode = LEN_; /* decode codes */ + if (flush === Z_TREES) { + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + break inf_leave; + } + break; + case 2: /* dynamic block */ + //Tracev((stderr, "inflate: dynamic codes block%s\n", + // state.last ? " (last)" : "")); + state.mode = TABLE; + break; + case 3: + strm.msg = 'invalid block type'; + state.mode = BAD; + } + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + break; + case STORED: + //--- BYTEBITS() ---// /* go to byte boundary */ + hold >>>= bits & 7; + bits -= bits & 7; + //---// + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) { + strm.msg = 'invalid stored block lengths'; + state.mode = BAD; + break; + } + state.length = hold & 0xffff; + //Tracev((stderr, "inflate: stored length %u\n", + // state.length)); + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = COPY_; + if (flush === Z_TREES) { break inf_leave; } + /* falls through */ + case COPY_: + state.mode = COPY; + /* falls through */ + case COPY: + copy = state.length; + if (copy) { + if (copy > have) { copy = have; } + if (copy > left) { copy = left; } + if (copy === 0) { break inf_leave; } + //--- zmemcpy(put, next, copy); --- + utils.arraySet(output, input, next, copy, put); + //---// + have -= copy; + next += copy; + left -= copy; + put += copy; + state.length -= copy; + break; + } + //Tracev((stderr, "inflate: stored end\n")); + state.mode = TYPE; + break; + case TABLE: + //=== NEEDBITS(14); */ + while (bits < 14) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257; + //--- DROPBITS(5) ---// + hold >>>= 5; + bits -= 5; + //---// + state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1; + //--- DROPBITS(5) ---// + hold >>>= 5; + bits -= 5; + //---// + state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4; + //--- DROPBITS(4) ---// + hold >>>= 4; + bits -= 4; + //---// +//#ifndef PKZIP_BUG_WORKAROUND + if (state.nlen > 286 || state.ndist > 30) { + strm.msg = 'too many length or distance symbols'; + state.mode = BAD; + break; + } +//#endif + //Tracev((stderr, "inflate: table sizes ok\n")); + state.have = 0; + state.mode = LENLENS; + /* falls through */ + case LENLENS: + while (state.have < state.ncode) { + //=== NEEDBITS(3); + while (bits < 3) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.lens[order[state.have++]] = (hold & 0x07);//BITS(3); + //--- DROPBITS(3) ---// + hold >>>= 3; + bits -= 3; + //---// + } + while (state.have < 19) { + state.lens[order[state.have++]] = 0; + } + // We have separate tables & no pointers. 2 commented lines below not needed. + //state.next = state.codes; + //state.lencode = state.next; + // Switch to use dynamic table + state.lencode = state.lendyn; + state.lenbits = 7; + + opts = { bits: state.lenbits }; + ret = inflate_table(CODES, state.lens, 0, 19, state.lencode, 0, state.work, opts); + state.lenbits = opts.bits; + + if (ret) { + strm.msg = 'invalid code lengths set'; + state.mode = BAD; + break; + } + //Tracev((stderr, "inflate: code lengths ok\n")); + state.have = 0; + state.mode = CODELENS; + /* falls through */ + case CODELENS: + while (state.have < state.nlen + state.ndist) { + for (;;) { + here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if (here_val < 16) { + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.lens[state.have++] = here_val; + } + else { + if (here_val === 16) { + //=== NEEDBITS(here.bits + 2); + n = here_bits + 2; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + if (state.have === 0) { + strm.msg = 'invalid bit length repeat'; + state.mode = BAD; + break; + } + len = state.lens[state.have - 1]; + copy = 3 + (hold & 0x03);//BITS(2); + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + } + else if (here_val === 17) { + //=== NEEDBITS(here.bits + 3); + n = here_bits + 3; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + len = 0; + copy = 3 + (hold & 0x07);//BITS(3); + //--- DROPBITS(3) ---// + hold >>>= 3; + bits -= 3; + //---// + } + else { + //=== NEEDBITS(here.bits + 7); + n = here_bits + 7; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + len = 0; + copy = 11 + (hold & 0x7f);//BITS(7); + //--- DROPBITS(7) ---// + hold >>>= 7; + bits -= 7; + //---// + } + if (state.have + copy > state.nlen + state.ndist) { + strm.msg = 'invalid bit length repeat'; + state.mode = BAD; + break; + } + while (copy--) { + state.lens[state.have++] = len; + } + } + } + + /* handle error breaks in while */ + if (state.mode === BAD) { break; } + + /* check for end-of-block code (better have one) */ + if (state.lens[256] === 0) { + strm.msg = 'invalid code -- missing end-of-block'; + state.mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state.lenbits = 9; + + opts = { bits: state.lenbits }; + ret = inflate_table(LENS, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts); + // We have separate tables & no pointers. 2 commented lines below not needed. + // state.next_index = opts.table_index; + state.lenbits = opts.bits; + // state.lencode = state.next; + + if (ret) { + strm.msg = 'invalid literal/lengths set'; + state.mode = BAD; + break; + } + + state.distbits = 6; + //state.distcode.copy(state.codes); + // Switch to use dynamic table + state.distcode = state.distdyn; + opts = { bits: state.distbits }; + ret = inflate_table(DISTS, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts); + // We have separate tables & no pointers. 2 commented lines below not needed. + // state.next_index = opts.table_index; + state.distbits = opts.bits; + // state.distcode = state.next; + + if (ret) { + strm.msg = 'invalid distances set'; + state.mode = BAD; + break; + } + //Tracev((stderr, 'inflate: codes ok\n')); + state.mode = LEN_; + if (flush === Z_TREES) { break inf_leave; } + /* falls through */ + case LEN_: + state.mode = LEN; + /* falls through */ + case LEN: + if (have >= 6 && left >= 258) { + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + inflate_fast(strm, _out); + //--- LOAD() --- + put = strm.next_out; + output = strm.output; + left = strm.avail_out; + next = strm.next_in; + input = strm.input; + have = strm.avail_in; + hold = state.hold; + bits = state.bits; + //--- + + if (state.mode === TYPE) { + state.back = -1; + } + break; + } + state.back = 0; + for (;;) { + here = state.lencode[hold & ((1 << state.lenbits) - 1)]; /*BITS(state.lenbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if (here_bits <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if (here_op && (here_op & 0xf0) === 0) { + last_bits = here_bits; + last_op = here_op; + last_val = here_val; + for (;;) { + here = state.lencode[last_val + + ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((last_bits + here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + //--- DROPBITS(last.bits) ---// + hold >>>= last_bits; + bits -= last_bits; + //---// + state.back += last_bits; + } + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.back += here_bits; + state.length = here_val; + if (here_op === 0) { + //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + // "inflate: literal '%c'\n" : + // "inflate: literal 0x%02x\n", here.val)); + state.mode = LIT; + break; + } + if (here_op & 32) { + //Tracevv((stderr, "inflate: end of block\n")); + state.back = -1; + state.mode = TYPE; + break; + } + if (here_op & 64) { + strm.msg = 'invalid literal/length code'; + state.mode = BAD; + break; + } + state.extra = here_op & 15; + state.mode = LENEXT; + /* falls through */ + case LENEXT: + if (state.extra) { + //=== NEEDBITS(state.extra); + n = state.extra; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.length += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; + //--- DROPBITS(state.extra) ---// + hold >>>= state.extra; + bits -= state.extra; + //---// + state.back += state.extra; + } + //Tracevv((stderr, "inflate: length %u\n", state.length)); + state.was = state.length; + state.mode = DIST; + /* falls through */ + case DIST: + for (;;) { + here = state.distcode[hold & ((1 << state.distbits) - 1)];/*BITS(state.distbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if ((here_op & 0xf0) === 0) { + last_bits = here_bits; + last_op = here_op; + last_val = here_val; + for (;;) { + here = state.distcode[last_val + + ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((last_bits + here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + //--- DROPBITS(last.bits) ---// + hold >>>= last_bits; + bits -= last_bits; + //---// + state.back += last_bits; + } + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.back += here_bits; + if (here_op & 64) { + strm.msg = 'invalid distance code'; + state.mode = BAD; + break; + } + state.offset = here_val; + state.extra = (here_op) & 15; + state.mode = DISTEXT; + /* falls through */ + case DISTEXT: + if (state.extra) { + //=== NEEDBITS(state.extra); + n = state.extra; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.offset += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; + //--- DROPBITS(state.extra) ---// + hold >>>= state.extra; + bits -= state.extra; + //---// + state.back += state.extra; + } +//#ifdef INFLATE_STRICT + if (state.offset > state.dmax) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD; + break; + } +//#endif + //Tracevv((stderr, "inflate: distance %u\n", state.offset)); + state.mode = MATCH; + /* falls through */ + case MATCH: + if (left === 0) { break inf_leave; } + copy = _out - left; + if (state.offset > copy) { /* copy from window */ + copy = state.offset - copy; + if (copy > state.whave) { + if (state.sane) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD; + break; + } +// (!) This block is disabled in zlib defaults, +// don't enable it for binary compatibility +//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR +// Trace((stderr, "inflate.c too far\n")); +// copy -= state.whave; +// if (copy > state.length) { copy = state.length; } +// if (copy > left) { copy = left; } +// left -= copy; +// state.length -= copy; +// do { +// output[put++] = 0; +// } while (--copy); +// if (state.length === 0) { state.mode = LEN; } +// break; +//#endif + } + if (copy > state.wnext) { + copy -= state.wnext; + from = state.wsize - copy; + } + else { + from = state.wnext - copy; + } + if (copy > state.length) { copy = state.length; } + from_source = state.window; + } + else { /* copy from output */ + from_source = output; + from = put - state.offset; + copy = state.length; + } + if (copy > left) { copy = left; } + left -= copy; + state.length -= copy; + do { + output[put++] = from_source[from++]; + } while (--copy); + if (state.length === 0) { state.mode = LEN; } + break; + case LIT: + if (left === 0) { break inf_leave; } + output[put++] = state.length; + left--; + state.mode = LEN; + break; + case CHECK: + if (state.wrap) { + //=== NEEDBITS(32); + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + // Use '|' instead of '+' to make sure that result is signed + hold |= input[next++] << bits; + bits += 8; + } + //===// + _out -= left; + strm.total_out += _out; + state.total += _out; + if (_out) { + strm.adler = state.check = + /*UPDATE(state.check, put - _out, _out);*/ + (state.flags ? crc32(state.check, output, _out, put - _out) : adler32(state.check, output, _out, put - _out)); + + } + _out = left; + // NB: crc32 stored as signed 32-bit int, zswap32 returns signed too + if ((state.flags ? hold : zswap32(hold)) !== state.check) { + strm.msg = 'incorrect data check'; + state.mode = BAD; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + //Tracev((stderr, "inflate: check matches trailer\n")); + } + state.mode = LENGTH; + /* falls through */ + case LENGTH: + if (state.wrap && state.flags) { + //=== NEEDBITS(32); + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (hold !== (state.total & 0xffffffff)) { + strm.msg = 'incorrect length check'; + state.mode = BAD; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + //Tracev((stderr, "inflate: length matches trailer\n")); + } + state.mode = DONE; + /* falls through */ + case DONE: + ret = Z_STREAM_END; + break inf_leave; + case BAD: + ret = Z_DATA_ERROR; + break inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + /* falls through */ + default: + return Z_STREAM_ERROR; + } + } + + // inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave" + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + + if (state.wsize || (_out !== strm.avail_out && state.mode < BAD && + (state.mode < CHECK || flush !== Z_FINISH))) { + if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) { + state.mode = MEM; + return Z_MEM_ERROR; + } + } + _in -= strm.avail_in; + _out -= strm.avail_out; + strm.total_in += _in; + strm.total_out += _out; + state.total += _out; + if (state.wrap && _out) { + strm.adler = state.check = /*UPDATE(state.check, strm.next_out - _out, _out);*/ + (state.flags ? crc32(state.check, output, _out, strm.next_out - _out) : adler32(state.check, output, _out, strm.next_out - _out)); + } + strm.data_type = state.bits + (state.last ? 64 : 0) + + (state.mode === TYPE ? 128 : 0) + + (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0); + if (((_in === 0 && _out === 0) || flush === Z_FINISH) && ret === Z_OK) { + ret = Z_BUF_ERROR; + } + return ret; +} + +function inflateEnd(strm) { + + if (!strm || !strm.state /*|| strm->zfree == (free_func)0*/) { + return Z_STREAM_ERROR; + } + + var state = strm.state; + if (state.window) { + state.window = null; + } + strm.state = null; + return Z_OK; +} + +function inflateGetHeader(strm, head) { + var state; + + /* check state */ + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR; } + + /* save header structure */ + state.head = head; + head.done = false; + return Z_OK; +} + +function inflateSetDictionary(strm, dictionary) { + var dictLength = dictionary.length; + + var state; + var dictid; + var ret; + + /* check state */ + if (!strm /* == Z_NULL */ || !strm.state /* == Z_NULL */) { return Z_STREAM_ERROR; } + state = strm.state; + + if (state.wrap !== 0 && state.mode !== DICT) { + return Z_STREAM_ERROR; + } + + /* check for correct dictionary identifier */ + if (state.mode === DICT) { + dictid = 1; /* adler32(0, null, 0)*/ + /* dictid = adler32(dictid, dictionary, dictLength); */ + dictid = adler32(dictid, dictionary, dictLength, 0); + if (dictid !== state.check) { + return Z_DATA_ERROR; + } + } + /* copy dictionary to window using updatewindow(), which will amend the + existing dictionary if appropriate */ + ret = updatewindow(strm, dictionary, dictLength, dictLength); + if (ret) { + state.mode = MEM; + return Z_MEM_ERROR; + } + state.havedict = 1; + // Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +exports.inflateReset = inflateReset; +exports.inflateReset2 = inflateReset2; +exports.inflateResetKeep = inflateResetKeep; +exports.inflateInit = inflateInit; +exports.inflateInit2 = inflateInit2; +exports.inflate = inflate; +exports.inflateEnd = inflateEnd; +exports.inflateGetHeader = inflateGetHeader; +exports.inflateSetDictionary = inflateSetDictionary; +exports.inflateInfo = 'pako inflate (from Nodeca project)'; + +/* Not implemented +exports.inflateCopy = inflateCopy; +exports.inflateGetDictionary = inflateGetDictionary; +exports.inflateMark = inflateMark; +exports.inflatePrime = inflatePrime; +exports.inflateSync = inflateSync; +exports.inflateSyncPoint = inflateSyncPoint; +exports.inflateUndermine = inflateUndermine; +*/ + +},{"../utils/common":53,"./adler32":55,"./crc32":57,"./inffast":60,"./inftrees":62}],62:[function(require,module,exports){ +'use strict'; + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +var utils = require('../utils/common'); + +var MAXBITS = 15; +var ENOUGH_LENS = 852; +var ENOUGH_DISTS = 592; +//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); + +var CODES = 0; +var LENS = 1; +var DISTS = 2; + +var lbase = [ /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 +]; + +var lext = [ /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78 +]; + +var dbase = [ /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0 +]; + +var dext = [ /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64 +]; + +module.exports = function inflate_table(type, lens, lens_index, codes, table, table_index, work, opts) +{ + var bits = opts.bits; + //here = opts.here; /* table entry for duplication */ + + var len = 0; /* a code's length in bits */ + var sym = 0; /* index of code symbols */ + var min = 0, max = 0; /* minimum and maximum code lengths */ + var root = 0; /* number of index bits for root table */ + var curr = 0; /* number of index bits for current table */ + var drop = 0; /* code bits to drop for sub-table */ + var left = 0; /* number of prefix codes available */ + var used = 0; /* code entries in table used */ + var huff = 0; /* Huffman code */ + var incr; /* for incrementing code, index */ + var fill; /* index for replicating entries */ + var low; /* low bits for current root entry */ + var mask; /* mask for low root bits */ + var next; /* next available space in table */ + var base = null; /* base value table to use */ + var base_index = 0; +// var shoextra; /* extra bits table to use */ + var end; /* use base and extra for symbol > end */ + var count = new utils.Buf16(MAXBITS + 1); //[MAXBITS+1]; /* number of codes of each length */ + var offs = new utils.Buf16(MAXBITS + 1); //[MAXBITS+1]; /* offsets in table for each length */ + var extra = null; + var extra_index = 0; + + var here_bits, here_op, here_val; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) { + count[len] = 0; + } + for (sym = 0; sym < codes; sym++) { + count[lens[lens_index + sym]]++; + } + + /* bound code lengths, force root to be within code lengths */ + root = bits; + for (max = MAXBITS; max >= 1; max--) { + if (count[max] !== 0) { break; } + } + if (root > max) { + root = max; + } + if (max === 0) { /* no symbols to code at all */ + //table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */ + //table.bits[opts.table_index] = 1; //here.bits = (var char)1; + //table.val[opts.table_index++] = 0; //here.val = (var short)0; + table[table_index++] = (1 << 24) | (64 << 16) | 0; + + + //table.op[opts.table_index] = 64; + //table.bits[opts.table_index] = 1; + //table.val[opts.table_index++] = 0; + table[table_index++] = (1 << 24) | (64 << 16) | 0; + + opts.bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min < max; min++) { + if (count[min] !== 0) { break; } + } + if (root < min) { + root = min; + } + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) { + return -1; + } /* over-subscribed */ + } + if (left > 0 && (type === CODES || max !== 1)) { + return -1; /* incomplete set */ + } + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) { + offs[len + 1] = offs[len] + count[len]; + } + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) { + if (lens[lens_index + sym] !== 0) { + work[offs[lens[lens_index + sym]]++] = sym; + } + } + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftrees.h + for more information. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + // poor man optimization - use if-else instead of switch, + // to avoid deopts in old v8 + if (type === CODES) { + base = extra = work; /* dummy value--not used */ + end = 19; + + } else if (type === LENS) { + base = lbase; + base_index -= 257; + extra = lext; + extra_index -= 257; + end = 256; + + } else { /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize opts for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = table_index; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = -1; /* trigger new sub-table when len > root */ + used = 1 << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if ((type === LENS && used > ENOUGH_LENS) || + (type === DISTS && used > ENOUGH_DISTS)) { + return 1; + } + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + here_bits = len - drop; + if (work[sym] < end) { + here_op = 0; + here_val = work[sym]; + } + else if (work[sym] > end) { + here_op = extra[extra_index + work[sym]]; + here_val = base[base_index + work[sym]]; + } + else { + here_op = 32 + 64; /* end of block */ + here_val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1 << (len - drop); + fill = 1 << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + table[next + (huff >> drop) + fill] = (here_bits << 24) | (here_op << 16) | here_val |0; + } while (fill !== 0); + + /* backwards increment the len-bit code huff */ + incr = 1 << (len - 1); + while (huff & incr) { + incr >>= 1; + } + if (incr !== 0) { + huff &= incr - 1; + huff += incr; + } else { + huff = 0; + } + + /* go to next symbol, update count, len */ + sym++; + if (--count[len] === 0) { + if (len === max) { break; } + len = lens[lens_index + work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) !== low) { + /* if first time, transition to sub-tables */ + if (drop === 0) { + drop = root; + } + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = 1 << curr; + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) { break; } + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1 << curr; + if ((type === LENS && used > ENOUGH_LENS) || + (type === DISTS && used > ENOUGH_DISTS)) { + return 1; + } + + /* point entry in root table to sub-table */ + low = huff & mask; + /*table.op[low] = curr; + table.bits[low] = root; + table.val[low] = next - opts.table_index;*/ + table[low] = (root << 24) | (curr << 16) | (next - table_index) |0; + } + } + + /* fill in remaining table entry if code is incomplete (guaranteed to have + at most one remaining entry, since if the code is incomplete, the + maximum code length that was allowed to get this far is one bit) */ + if (huff !== 0) { + //table.op[next + huff] = 64; /* invalid code marker */ + //table.bits[next + huff] = len - drop; + //table.val[next + huff] = 0; + table[next + huff] = ((len - drop) << 24) | (64 << 16) |0; + } + + /* set return parameters */ + //opts.table_index += used; + opts.bits = root; + return 0; +}; + +},{"../utils/common":53}],63:[function(require,module,exports){ +'use strict'; + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +module.exports = { + 2: 'need dictionary', /* Z_NEED_DICT 2 */ + 1: 'stream end', /* Z_STREAM_END 1 */ + 0: '', /* Z_OK 0 */ + '-1': 'file error', /* Z_ERRNO (-1) */ + '-2': 'stream error', /* Z_STREAM_ERROR (-2) */ + '-3': 'data error', /* Z_DATA_ERROR (-3) */ + '-4': 'insufficient memory', /* Z_MEM_ERROR (-4) */ + '-5': 'buffer error', /* Z_BUF_ERROR (-5) */ + '-6': 'incompatible version' /* Z_VERSION_ERROR (-6) */ +}; + +},{}],64:[function(require,module,exports){ +'use strict'; + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +var utils = require('../utils/common'); + +/* Public constants ==========================================================*/ +/* ===========================================================================*/ + + +//var Z_FILTERED = 1; +//var Z_HUFFMAN_ONLY = 2; +//var Z_RLE = 3; +var Z_FIXED = 4; +//var Z_DEFAULT_STRATEGY = 0; + +/* Possible values of the data_type field (though see inflate()) */ +var Z_BINARY = 0; +var Z_TEXT = 1; +//var Z_ASCII = 1; // = Z_TEXT +var Z_UNKNOWN = 2; + +/*============================================================================*/ + + +function zero(buf) { var len = buf.length; while (--len >= 0) { buf[len] = 0; } } + +// From zutil.h + +var STORED_BLOCK = 0; +var STATIC_TREES = 1; +var DYN_TREES = 2; +/* The three kinds of block type */ + +var MIN_MATCH = 3; +var MAX_MATCH = 258; +/* The minimum and maximum match lengths */ + +// From deflate.h +/* =========================================================================== + * Internal compression state. + */ + +var LENGTH_CODES = 29; +/* number of length codes, not counting the special END_BLOCK code */ + +var LITERALS = 256; +/* number of literal bytes 0..255 */ + +var L_CODES = LITERALS + 1 + LENGTH_CODES; +/* number of Literal or Length codes, including the END_BLOCK code */ + +var D_CODES = 30; +/* number of distance codes */ + +var BL_CODES = 19; +/* number of codes used to transfer the bit lengths */ + +var HEAP_SIZE = 2 * L_CODES + 1; +/* maximum heap size */ + +var MAX_BITS = 15; +/* All codes must not exceed MAX_BITS bits */ + +var Buf_size = 16; +/* size of bit buffer in bi_buf */ + + +/* =========================================================================== + * Constants + */ + +var MAX_BL_BITS = 7; +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +var END_BLOCK = 256; +/* end of block literal code */ + +var REP_3_6 = 16; +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +var REPZ_3_10 = 17; +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +var REPZ_11_138 = 18; +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +/* eslint-disable comma-spacing,array-bracket-spacing */ +var extra_lbits = /* extra bits for each length code */ + [0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0]; + +var extra_dbits = /* extra bits for each distance code */ + [0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13]; + +var extra_blbits = /* extra bits for each bit length code */ + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7]; + +var bl_order = + [16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]; +/* eslint-enable comma-spacing,array-bracket-spacing */ + +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +// We pre-fill arrays with 0 to avoid uninitialized gaps + +var DIST_CODE_LEN = 512; /* see definition of array dist_code below */ + +// !!!! Use flat array instead of structure, Freq = i*2, Len = i*2+1 +var static_ltree = new Array((L_CODES + 2) * 2); +zero(static_ltree); +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +var static_dtree = new Array(D_CODES * 2); +zero(static_dtree); +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +var _dist_code = new Array(DIST_CODE_LEN); +zero(_dist_code); +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +var _length_code = new Array(MAX_MATCH - MIN_MATCH + 1); +zero(_length_code); +/* length code for each normalized match length (0 == MIN_MATCH) */ + +var base_length = new Array(LENGTH_CODES); +zero(base_length); +/* First normalized length for each code (0 = MIN_MATCH) */ + +var base_dist = new Array(D_CODES); +zero(base_dist); +/* First normalized distance for each code (0 = distance of 1) */ + + +function StaticTreeDesc(static_tree, extra_bits, extra_base, elems, max_length) { + + this.static_tree = static_tree; /* static tree or NULL */ + this.extra_bits = extra_bits; /* extra bits for each code or NULL */ + this.extra_base = extra_base; /* base index for extra_bits */ + this.elems = elems; /* max number of elements in the tree */ + this.max_length = max_length; /* max bit length for the codes */ + + // show if `static_tree` has data or dummy - needed for monomorphic objects + this.has_stree = static_tree && static_tree.length; +} + + +var static_l_desc; +var static_d_desc; +var static_bl_desc; + + +function TreeDesc(dyn_tree, stat_desc) { + this.dyn_tree = dyn_tree; /* the dynamic tree */ + this.max_code = 0; /* largest code with non zero frequency */ + this.stat_desc = stat_desc; /* the corresponding static tree */ +} + + + +function d_code(dist) { + return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)]; +} + + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +function put_short(s, w) { +// put_byte(s, (uch)((w) & 0xff)); +// put_byte(s, (uch)((ush)(w) >> 8)); + s.pending_buf[s.pending++] = (w) & 0xff; + s.pending_buf[s.pending++] = (w >>> 8) & 0xff; +} + + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +function send_bits(s, value, length) { + if (s.bi_valid > (Buf_size - length)) { + s.bi_buf |= (value << s.bi_valid) & 0xffff; + put_short(s, s.bi_buf); + s.bi_buf = value >> (Buf_size - s.bi_valid); + s.bi_valid += length - Buf_size; + } else { + s.bi_buf |= (value << s.bi_valid) & 0xffff; + s.bi_valid += length; + } +} + + +function send_code(s, c, tree) { + send_bits(s, tree[c * 2]/*.Code*/, tree[c * 2 + 1]/*.Len*/); +} + + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +function bi_reverse(code, len) { + var res = 0; + do { + res |= code & 1; + code >>>= 1; + res <<= 1; + } while (--len > 0); + return res >>> 1; +} + + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +function bi_flush(s) { + if (s.bi_valid === 16) { + put_short(s, s.bi_buf); + s.bi_buf = 0; + s.bi_valid = 0; + + } else if (s.bi_valid >= 8) { + s.pending_buf[s.pending++] = s.bi_buf & 0xff; + s.bi_buf >>= 8; + s.bi_valid -= 8; + } +} + + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +function gen_bitlen(s, desc) +// deflate_state *s; +// tree_desc *desc; /* the tree descriptor */ +{ + var tree = desc.dyn_tree; + var max_code = desc.max_code; + var stree = desc.stat_desc.static_tree; + var has_stree = desc.stat_desc.has_stree; + var extra = desc.stat_desc.extra_bits; + var base = desc.stat_desc.extra_base; + var max_length = desc.stat_desc.max_length; + var h; /* heap index */ + var n, m; /* iterate over the tree elements */ + var bits; /* bit length */ + var xbits; /* extra bits */ + var f; /* frequency */ + var overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) { + s.bl_count[bits] = 0; + } + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s.heap[s.heap_max] * 2 + 1]/*.Len*/ = 0; /* root of the heap */ + + for (h = s.heap_max + 1; h < HEAP_SIZE; h++) { + n = s.heap[h]; + bits = tree[tree[n * 2 + 1]/*.Dad*/ * 2 + 1]/*.Len*/ + 1; + if (bits > max_length) { + bits = max_length; + overflow++; + } + tree[n * 2 + 1]/*.Len*/ = bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) { continue; } /* not a leaf node */ + + s.bl_count[bits]++; + xbits = 0; + if (n >= base) { + xbits = extra[n - base]; + } + f = tree[n * 2]/*.Freq*/; + s.opt_len += f * (bits + xbits); + if (has_stree) { + s.static_len += f * (stree[n * 2 + 1]/*.Len*/ + xbits); + } + } + if (overflow === 0) { return; } + + // Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length - 1; + while (s.bl_count[bits] === 0) { bits--; } + s.bl_count[bits]--; /* move one leaf down the tree */ + s.bl_count[bits + 1] += 2; /* move one overflow item as its brother */ + s.bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits !== 0; bits--) { + n = s.bl_count[bits]; + while (n !== 0) { + m = s.heap[--h]; + if (m > max_code) { continue; } + if (tree[m * 2 + 1]/*.Len*/ !== bits) { + // Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s.opt_len += (bits - tree[m * 2 + 1]/*.Len*/) * tree[m * 2]/*.Freq*/; + tree[m * 2 + 1]/*.Len*/ = bits; + } + n--; + } + } +} + + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +function gen_codes(tree, max_code, bl_count) +// ct_data *tree; /* the tree to decorate */ +// int max_code; /* largest code with non zero frequency */ +// ushf *bl_count; /* number of codes at each bit length */ +{ + var next_code = new Array(MAX_BITS + 1); /* next code value for each bit length */ + var code = 0; /* running code value */ + var bits; /* bit index */ + var n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits - 1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + //Assert (code + bl_count[MAX_BITS]-1 == (1< length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES - 1; code++) { + base_length[code] = length; + for (n = 0; n < (1 << extra_lbits[code]); n++) { + _length_code[length++] = code; + } + } + //Assert (length == 256, "tr_static_init: length != 256"); + /* Note that the length 255 (match length 258) can be represented + * in two different ways: code 284 + 5 bits or code 285, so we + * overwrite length_code[255] to use the best encoding: + */ + _length_code[length - 1] = code; + + /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ + dist = 0; + for (code = 0; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1 << extra_dbits[code]); n++) { + _dist_code[dist++] = code; + } + } + //Assert (dist == 256, "tr_static_init: dist != 256"); + dist >>= 7; /* from now on, all distances are divided by 128 */ + for (; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) { + _dist_code[256 + dist++] = code; + } + } + //Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) { + bl_count[bits] = 0; + } + + n = 0; + while (n <= 143) { + static_ltree[n * 2 + 1]/*.Len*/ = 8; + n++; + bl_count[8]++; + } + while (n <= 255) { + static_ltree[n * 2 + 1]/*.Len*/ = 9; + n++; + bl_count[9]++; + } + while (n <= 279) { + static_ltree[n * 2 + 1]/*.Len*/ = 7; + n++; + bl_count[7]++; + } + while (n <= 287) { + static_ltree[n * 2 + 1]/*.Len*/ = 8; + n++; + bl_count[8]++; + } + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes(static_ltree, L_CODES + 1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n * 2 + 1]/*.Len*/ = 5; + static_dtree[n * 2]/*.Code*/ = bi_reverse(n, 5); + } + + // Now data ready and we can init static trees + static_l_desc = new StaticTreeDesc(static_ltree, extra_lbits, LITERALS + 1, L_CODES, MAX_BITS); + static_d_desc = new StaticTreeDesc(static_dtree, extra_dbits, 0, D_CODES, MAX_BITS); + static_bl_desc = new StaticTreeDesc(new Array(0), extra_blbits, 0, BL_CODES, MAX_BL_BITS); + + //static_init_done = true; +} + + +/* =========================================================================== + * Initialize a new block. + */ +function init_block(s) { + var n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) { s.dyn_ltree[n * 2]/*.Freq*/ = 0; } + for (n = 0; n < D_CODES; n++) { s.dyn_dtree[n * 2]/*.Freq*/ = 0; } + for (n = 0; n < BL_CODES; n++) { s.bl_tree[n * 2]/*.Freq*/ = 0; } + + s.dyn_ltree[END_BLOCK * 2]/*.Freq*/ = 1; + s.opt_len = s.static_len = 0; + s.last_lit = s.matches = 0; +} + + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +function bi_windup(s) +{ + if (s.bi_valid > 8) { + put_short(s, s.bi_buf); + } else if (s.bi_valid > 0) { + //put_byte(s, (Byte)s->bi_buf); + s.pending_buf[s.pending++] = s.bi_buf; + } + s.bi_buf = 0; + s.bi_valid = 0; +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +function copy_block(s, buf, len, header) +//DeflateState *s; +//charf *buf; /* the input data */ +//unsigned len; /* its length */ +//int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + + if (header) { + put_short(s, len); + put_short(s, ~len); + } +// while (len--) { +// put_byte(s, *buf++); +// } + utils.arraySet(s.pending_buf, s.window, buf, len, s.pending); + s.pending += len; +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +function smaller(tree, n, m, depth) { + var _n2 = n * 2; + var _m2 = m * 2; + return (tree[_n2]/*.Freq*/ < tree[_m2]/*.Freq*/ || + (tree[_n2]/*.Freq*/ === tree[_m2]/*.Freq*/ && depth[n] <= depth[m])); +} + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +function pqdownheap(s, tree, k) +// deflate_state *s; +// ct_data *tree; /* the tree to restore */ +// int k; /* node to move down */ +{ + var v = s.heap[k]; + var j = k << 1; /* left son of k */ + while (j <= s.heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s.heap_len && + smaller(tree, s.heap[j + 1], s.heap[j], s.depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s.heap[j], s.depth)) { break; } + + /* Exchange v with the smallest son */ + s.heap[k] = s.heap[j]; + k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s.heap[k] = v; +} + + +// inlined manually +// var SMALLEST = 1; + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +function compress_block(s, ltree, dtree) +// deflate_state *s; +// const ct_data *ltree; /* literal tree */ +// const ct_data *dtree; /* distance tree */ +{ + var dist; /* distance of matched string */ + var lc; /* match length or unmatched char (if dist == 0) */ + var lx = 0; /* running index in l_buf */ + var code; /* the code to send */ + var extra; /* number of extra bits to send */ + + if (s.last_lit !== 0) { + do { + dist = (s.pending_buf[s.d_buf + lx * 2] << 8) | (s.pending_buf[s.d_buf + lx * 2 + 1]); + lc = s.pending_buf[s.l_buf + lx]; + lx++; + + if (dist === 0) { + send_code(s, lc, ltree); /* send a literal byte */ + //Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code + LITERALS + 1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra !== 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + //Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra !== 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + //Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + // "pendingBuf overflow"); + + } while (lx < s.last_lit); + } + + send_code(s, END_BLOCK, ltree); +} + + +/* =========================================================================== + * Construct one Huffman tree and assigns the code bit strings and lengths. + * Update the total bit length for the current block. + * IN assertion: the field freq is set for all tree elements. + * OUT assertions: the fields len and code are set to the optimal bit length + * and corresponding code. The length opt_len is updated; static_len is + * also updated if stree is not null. The field max_code is set. + */ +function build_tree(s, desc) +// deflate_state *s; +// tree_desc *desc; /* the tree descriptor */ +{ + var tree = desc.dyn_tree; + var stree = desc.stat_desc.static_tree; + var has_stree = desc.stat_desc.has_stree; + var elems = desc.stat_desc.elems; + var n, m; /* iterate over heap elements */ + var max_code = -1; /* largest code with non zero frequency */ + var node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s.heap_len = 0; + s.heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n * 2]/*.Freq*/ !== 0) { + s.heap[++s.heap_len] = max_code = n; + s.depth[n] = 0; + + } else { + tree[n * 2 + 1]/*.Len*/ = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s.heap_len < 2) { + node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0); + tree[node * 2]/*.Freq*/ = 1; + s.depth[node] = 0; + s.opt_len--; + + if (has_stree) { + s.static_len -= stree[node * 2 + 1]/*.Len*/; + } + /* node is 0 or 1 so it does not have extra bits */ + } + desc.max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = (s.heap_len >> 1/*int /2*/); n >= 1; n--) { pqdownheap(s, tree, n); } + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + //pqremove(s, tree, n); /* n = node of least frequency */ + /*** pqremove ***/ + n = s.heap[1/*SMALLEST*/]; + s.heap[1/*SMALLEST*/] = s.heap[s.heap_len--]; + pqdownheap(s, tree, 1/*SMALLEST*/); + /***/ + + m = s.heap[1/*SMALLEST*/]; /* m = node of next least frequency */ + + s.heap[--s.heap_max] = n; /* keep the nodes sorted by frequency */ + s.heap[--s.heap_max] = m; + + /* Create a new node father of n and m */ + tree[node * 2]/*.Freq*/ = tree[n * 2]/*.Freq*/ + tree[m * 2]/*.Freq*/; + s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1; + tree[n * 2 + 1]/*.Dad*/ = tree[m * 2 + 1]/*.Dad*/ = node; + + /* and insert the new node in the heap */ + s.heap[1/*SMALLEST*/] = node++; + pqdownheap(s, tree, 1/*SMALLEST*/); + + } while (s.heap_len >= 2); + + s.heap[--s.heap_max] = s.heap[1/*SMALLEST*/]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes(tree, max_code, s.bl_count); +} + + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +function scan_tree(s, tree, max_code) +// deflate_state *s; +// ct_data *tree; /* the tree to be scanned */ +// int max_code; /* and its largest code of non zero frequency */ +{ + var n; /* iterates over all tree elements */ + var prevlen = -1; /* last emitted length */ + var curlen; /* length of current code */ + + var nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */ + + var count = 0; /* repeat count of the current code */ + var max_count = 7; /* max repeat count */ + var min_count = 4; /* min repeat count */ + + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } + tree[(max_code + 1) * 2 + 1]/*.Len*/ = 0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[(n + 1) * 2 + 1]/*.Len*/; + + if (++count < max_count && curlen === nextlen) { + continue; + + } else if (count < min_count) { + s.bl_tree[curlen * 2]/*.Freq*/ += count; + + } else if (curlen !== 0) { + + if (curlen !== prevlen) { s.bl_tree[curlen * 2]/*.Freq*/++; } + s.bl_tree[REP_3_6 * 2]/*.Freq*/++; + + } else if (count <= 10) { + s.bl_tree[REPZ_3_10 * 2]/*.Freq*/++; + + } else { + s.bl_tree[REPZ_11_138 * 2]/*.Freq*/++; + } + + count = 0; + prevlen = curlen; + + if (nextlen === 0) { + max_count = 138; + min_count = 3; + + } else if (curlen === nextlen) { + max_count = 6; + min_count = 3; + + } else { + max_count = 7; + min_count = 4; + } + } +} + + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +function send_tree(s, tree, max_code) +// deflate_state *s; +// ct_data *tree; /* the tree to be scanned */ +// int max_code; /* and its largest code of non zero frequency */ +{ + var n; /* iterates over all tree elements */ + var prevlen = -1; /* last emitted length */ + var curlen; /* length of current code */ + + var nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */ + + var count = 0; /* repeat count of the current code */ + var max_count = 7; /* max repeat count */ + var min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[(n + 1) * 2 + 1]/*.Len*/; + + if (++count < max_count && curlen === nextlen) { + continue; + + } else if (count < min_count) { + do { send_code(s, curlen, s.bl_tree); } while (--count !== 0); + + } else if (curlen !== 0) { + if (curlen !== prevlen) { + send_code(s, curlen, s.bl_tree); + count--; + } + //Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s.bl_tree); + send_bits(s, count - 3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s.bl_tree); + send_bits(s, count - 3, 3); + + } else { + send_code(s, REPZ_11_138, s.bl_tree); + send_bits(s, count - 11, 7); + } + + count = 0; + prevlen = curlen; + if (nextlen === 0) { + max_count = 138; + min_count = 3; + + } else if (curlen === nextlen) { + max_count = 6; + min_count = 3; + + } else { + max_count = 7; + min_count = 4; + } + } +} + + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +function build_bl_tree(s) { + var max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, s.dyn_ltree, s.l_desc.max_code); + scan_tree(s, s.dyn_dtree, s.d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, s.bl_desc); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) { + if (s.bl_tree[bl_order[max_blindex] * 2 + 1]/*.Len*/ !== 0) { + break; + } + } + /* Update opt_len to include the bit length tree and counts */ + s.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4; + //Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + // s->opt_len, s->static_len)); + + return max_blindex; +} + + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +function send_all_trees(s, lcodes, dcodes, blcodes) +// deflate_state *s; +// int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + var rank; /* index in bl_order */ + + //Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + //Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + // "too many codes"); + //Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes - 1, 5); + send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + //Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s.bl_tree[bl_order[rank] * 2 + 1]/*.Len*/, 3); + } + //Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, s.dyn_ltree, lcodes - 1); /* literal tree */ + //Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, s.dyn_dtree, dcodes - 1); /* distance tree */ + //Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + + +/* =========================================================================== + * Check if the data type is TEXT or BINARY, using the following algorithm: + * - TEXT if the two conditions below are satisfied: + * a) There are no non-portable control characters belonging to the + * "black list" (0..6, 14..25, 28..31). + * b) There is at least one printable character belonging to the + * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). + * - BINARY otherwise. + * - The following partially-portable control characters form a + * "gray list" that is ignored in this detection algorithm: + * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). + * IN assertion: the fields Freq of dyn_ltree are set. + */ +function detect_data_type(s) { + /* black_mask is the bit mask of black-listed bytes + * set bits 0..6, 14..25, and 28..31 + * 0xf3ffc07f = binary 11110011111111111100000001111111 + */ + var black_mask = 0xf3ffc07f; + var n; + + /* Check for non-textual ("black-listed") bytes. */ + for (n = 0; n <= 31; n++, black_mask >>>= 1) { + if ((black_mask & 1) && (s.dyn_ltree[n * 2]/*.Freq*/ !== 0)) { + return Z_BINARY; + } + } + + /* Check for textual ("white-listed") bytes. */ + if (s.dyn_ltree[9 * 2]/*.Freq*/ !== 0 || s.dyn_ltree[10 * 2]/*.Freq*/ !== 0 || + s.dyn_ltree[13 * 2]/*.Freq*/ !== 0) { + return Z_TEXT; + } + for (n = 32; n < LITERALS; n++) { + if (s.dyn_ltree[n * 2]/*.Freq*/ !== 0) { + return Z_TEXT; + } + } + + /* There are no "black-listed" or "white-listed" bytes: + * this stream either is empty or has tolerated ("gray-listed") bytes only. + */ + return Z_BINARY; +} + + +var static_init_done = false; + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +function _tr_init(s) +{ + + if (!static_init_done) { + tr_static_init(); + static_init_done = true; + } + + s.l_desc = new TreeDesc(s.dyn_ltree, static_l_desc); + s.d_desc = new TreeDesc(s.dyn_dtree, static_d_desc); + s.bl_desc = new TreeDesc(s.bl_tree, static_bl_desc); + + s.bi_buf = 0; + s.bi_valid = 0; + + /* Initialize the first block of the first file: */ + init_block(s); +} + + +/* =========================================================================== + * Send a stored block + */ +function _tr_stored_block(s, buf, stored_len, last) +//DeflateState *s; +//charf *buf; /* input block */ +//ulg stored_len; /* length of input block */ +//int last; /* one if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK << 1) + (last ? 1 : 0), 3); /* send block type */ + copy_block(s, buf, stored_len, true); /* with header */ +} + + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + */ +function _tr_align(s) { + send_bits(s, STATIC_TREES << 1, 3); + send_code(s, END_BLOCK, static_ltree); + bi_flush(s); +} + + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +function _tr_flush_block(s, buf, stored_len, last) +//DeflateState *s; +//charf *buf; /* input block, or NULL if too old */ +//ulg stored_len; /* length of input block */ +//int last; /* one if this is the last block for a file */ +{ + var opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + var max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s.level > 0) { + + /* Check if the file is binary or text */ + if (s.strm.data_type === Z_UNKNOWN) { + s.strm.data_type = detect_data_type(s); + } + + /* Construct the literal and distance trees */ + build_tree(s, s.l_desc); + // Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + // s->static_len)); + + build_tree(s, s.d_desc); + // Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + // s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s.opt_len + 3 + 7) >>> 3; + static_lenb = (s.static_len + 3 + 7) >>> 3; + + // Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + // opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + // s->last_lit)); + + if (static_lenb <= opt_lenb) { opt_lenb = static_lenb; } + + } else { + // Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + + if ((stored_len + 4 <= opt_lenb) && (buf !== -1)) { + /* 4: two words for the lengths */ + + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, last); + + } else if (s.strategy === Z_FIXED || static_lenb === opt_lenb) { + + send_bits(s, (STATIC_TREES << 1) + (last ? 1 : 0), 3); + compress_block(s, static_ltree, static_dtree); + + } else { + send_bits(s, (DYN_TREES << 1) + (last ? 1 : 0), 3); + send_all_trees(s, s.l_desc.max_code + 1, s.d_desc.max_code + 1, max_blindex + 1); + compress_block(s, s.dyn_ltree, s.dyn_dtree); + } + // Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (last) { + bi_windup(s); + } + // Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + // s->compressed_len-7*last)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +function _tr_tally(s, dist, lc) +// deflate_state *s; +// unsigned dist; /* distance of matched string */ +// unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + //var out_length, in_length, dcode; + + s.pending_buf[s.d_buf + s.last_lit * 2] = (dist >>> 8) & 0xff; + s.pending_buf[s.d_buf + s.last_lit * 2 + 1] = dist & 0xff; + + s.pending_buf[s.l_buf + s.last_lit] = lc & 0xff; + s.last_lit++; + + if (dist === 0) { + /* lc is the unmatched char */ + s.dyn_ltree[lc * 2]/*.Freq*/++; + } else { + s.matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + //Assert((ush)dist < (ush)MAX_DIST(s) && + // (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + // (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s.dyn_ltree[(_length_code[lc] + LITERALS + 1) * 2]/*.Freq*/++; + s.dyn_dtree[d_code(dist) * 2]/*.Freq*/++; + } + +// (!) This block is disabled in zlib defaults, +// don't enable it for binary compatibility + +//#ifdef TRUNCATE_BLOCK +// /* Try to guess if it is profitable to stop the current block here */ +// if ((s.last_lit & 0x1fff) === 0 && s.level > 2) { +// /* Compute an upper bound for the compressed length */ +// out_length = s.last_lit*8; +// in_length = s.strstart - s.block_start; +// +// for (dcode = 0; dcode < D_CODES; dcode++) { +// out_length += s.dyn_dtree[dcode*2]/*.Freq*/ * (5 + extra_dbits[dcode]); +// } +// out_length >>>= 3; +// //Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", +// // s->last_lit, in_length, out_length, +// // 100L - out_length*100L/in_length)); +// if (s.matches < (s.last_lit>>1)/*int /2*/ && out_length < (in_length>>1)/*int /2*/) { +// return true; +// } +// } +//#endif + + return (s.last_lit === s.lit_bufsize - 1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +exports._tr_init = _tr_init; +exports._tr_stored_block = _tr_stored_block; +exports._tr_flush_block = _tr_flush_block; +exports._tr_tally = _tr_tally; +exports._tr_align = _tr_align; + +},{"../utils/common":53}],65:[function(require,module,exports){ +'use strict'; + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +function ZStream() { + /* next input byte */ + this.input = null; // JS specific, because we have no pointers + this.next_in = 0; + /* number of bytes available at input */ + this.avail_in = 0; + /* total number of input bytes read so far */ + this.total_in = 0; + /* next output byte should be put there */ + this.output = null; // JS specific, because we have no pointers + this.next_out = 0; + /* remaining free space at output */ + this.avail_out = 0; + /* total number of bytes output so far */ + this.total_out = 0; + /* last error message, NULL if no error */ + this.msg = ''/*Z_NULL*/; + /* not visible by applications */ + this.state = null; + /* best guess about the data type: binary or text */ + this.data_type = 2/*Z_UNKNOWN*/; + /* adler32 value of the uncompressed data */ + this.adler = 0; +} + +module.exports = ZStream; + +},{}],66:[function(require,module,exports){ +// shim for using process in browser +var process = module.exports = {}; + +// cached from whatever global is present so that test runners that stub it +// don't break things. But we need to wrap it in a try catch in case it is +// wrapped in strict mode code which doesn't define any globals. It's inside a +// function because try/catches deoptimize in certain engines. + +var cachedSetTimeout; +var cachedClearTimeout; + +function defaultSetTimout() { + throw new Error('setTimeout has not been defined'); +} +function defaultClearTimeout () { + throw new Error('clearTimeout has not been defined'); +} +(function () { + try { + if (typeof setTimeout === 'function') { + cachedSetTimeout = setTimeout; + } else { + cachedSetTimeout = defaultSetTimout; + } + } catch (e) { + cachedSetTimeout = defaultSetTimout; + } + try { + if (typeof clearTimeout === 'function') { + cachedClearTimeout = clearTimeout; + } else { + cachedClearTimeout = defaultClearTimeout; + } + } catch (e) { + cachedClearTimeout = defaultClearTimeout; + } +} ()) +function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + //normal enviroments in sane situations + return setTimeout(fun, 0); + } + // if setTimeout wasn't available but was latter defined + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { + cachedSetTimeout = setTimeout; + return setTimeout(fun, 0); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedSetTimeout(fun, 0); + } catch(e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedSetTimeout.call(null, fun, 0); + } catch(e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error + return cachedSetTimeout.call(this, fun, 0); + } + } + + +} +function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + //normal enviroments in sane situations + return clearTimeout(marker); + } + // if clearTimeout wasn't available but was latter defined + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { + cachedClearTimeout = clearTimeout; + return clearTimeout(marker); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedClearTimeout(marker); + } catch (e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedClearTimeout.call(null, marker); + } catch (e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. + // Some versions of I.E. have different rules for clearTimeout vs setTimeout + return cachedClearTimeout.call(this, marker); + } + } + + + +} +var queue = []; +var draining = false; +var currentQueue; +var queueIndex = -1; + +function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } +} + +function drainQueue() { + if (draining) { + return; + } + var timeout = runTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + runClearTimeout(timeout); +} + +process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } +}; + +// v8 likes predictible objects +function Item(fun, array) { + this.fun = fun; + this.array = array; +} +Item.prototype.run = function () { + this.fun.apply(null, this.array); +}; +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; +process.version = ''; // empty string to avoid regexp issues +process.versions = {}; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; +process.prependListener = noop; +process.prependOnceListener = noop; + +process.listeners = function (name) { return [] } + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; +process.umask = function() { return 0; }; + +},{}],67:[function(require,module,exports){ +'use strict'; + +/* +node-bzip - a pure-javascript Node.JS module for decoding bzip2 data + +Copyright (C) 2012 Eli Skeggs + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, see +http://www.gnu.org/licenses/lgpl-2.1.html + +Adapted from bzip2.js, copyright 2011 antimatter15 (antimatter15@gmail.com). + +Based on micro-bunzip by Rob Landley (rob@landley.net). + +Based on bzip2 decompression code by Julian R Seward (jseward@acm.org), +which also acknowledges contributions by Mike Burrows, David Wheeler, +Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten, +Robert Sedgewick, and Jon L. Bentley. +*/ + +var BITMASK = [0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF]; + +// offset in bytes +var BitReader = function BitReader(stream) { + this.stream = stream; + this.bitOffset = 0; + this.curByte = 0; + this.hasByte = false; +}; + +BitReader.prototype._ensureByte = function () { + if (!this.hasByte) { + this.curByte = this.stream.readByte(); + this.hasByte = true; + } +}; + +// reads bits from the buffer +BitReader.prototype.read = function (bits) { + var result = 0; + while (bits > 0) { + this._ensureByte(); + var remaining = 8 - this.bitOffset; + // if we're in a byte + if (bits >= remaining) { + result <<= remaining; + result |= BITMASK[remaining] & this.curByte; + this.hasByte = false; + this.bitOffset = 0; + bits -= remaining; + } else { + result <<= bits; + var shift = remaining - bits; + result |= (this.curByte & BITMASK[bits] << shift) >> shift; + this.bitOffset += bits; + bits = 0; + } + } + return result; +}; + +// seek to an arbitrary point in the buffer (expressed in bits) +BitReader.prototype.seek = function (pos) { + var n_bit = pos % 8; + var n_byte = (pos - n_bit) / 8; + this.bitOffset = n_bit; + this.stream.seek(n_byte); + this.hasByte = false; +}; + +// reads 6 bytes worth of data using the read method +BitReader.prototype.pi = function () { + var buf = new Uint8Array(6), + i; + for (i = 0; i < buf.length; i++) { + buf[i] = this.read(8); + } + return bufToHex(buf); +}; + +function bufToHex(buf) { + return Array.prototype.map.call(buf, x => ('00' + x.toString(16)).slice(-2)).join(''); +} + +module.exports = BitReader; + +},{}],68:[function(require,module,exports){ +"use strict"; + +/* CRC32, used in Bzip2 implementation. + * This is a port of CRC32.java from the jbzip2 implementation at + * https://code.google.com/p/jbzip2 + * which is: + * Copyright (c) 2011 Matthew Francis + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * This JavaScript implementation is: + * Copyright (c) 2013 C. Scott Ananian + * with the same licensing terms as Matthew Francis' original implementation. + */ +module.exports = function () { + + /** + * A static CRC lookup table + */ + var crc32Lookup = new Uint32Array([0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4]); + + var CRC32 = function CRC32() { + /** + * The current CRC + */ + var crc = 0xffffffff; + + /** + * @return The current CRC + */ + this.getCRC = function () { + return ~crc >>> 0; // return an unsigned value + }; + + /** + * Update the CRC with a single byte + * @param value The value to update the CRC with + */ + this.updateCRC = function (value) { + crc = crc << 8 ^ crc32Lookup[(crc >>> 24 ^ value) & 0xff]; + }; + + /** + * Update the CRC with a sequence of identical bytes + * @param value The value to update the CRC with + * @param count The number of bytes + */ + this.updateCRCRun = function (value, count) { + while (count-- > 0) { + crc = crc << 8 ^ crc32Lookup[(crc >>> 24 ^ value) & 0xff]; + } + }; + }; + return CRC32; +}(); + +},{}],69:[function(require,module,exports){ +'use strict'; + +/* +seek-bzip - a pure-javascript module for seeking within bzip2 data + +Copyright (C) 2013 C. Scott Ananian +Copyright (C) 2012 Eli Skeggs +Copyright (C) 2011 Kevin Kwok + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, see +http://www.gnu.org/licenses/lgpl-2.1.html + +Adapted from node-bzip, copyright 2012 Eli Skeggs. +Adapted from bzip2.js, copyright 2011 Kevin Kwok (antimatter15@gmail.com). + +Based on micro-bunzip by Rob Landley (rob@landley.net). + +Based on bzip2 decompression code by Julian R Seward (jseward@acm.org), +which also acknowledges contributions by Mike Burrows, David Wheeler, +Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten, +Robert Sedgewick, and Jon L. Bentley. +*/ + +var BitReader = require('./bitreader'); +var Stream = require('./stream'); +var CRC32 = require('./crc32'); + +var MAX_HUFCODE_BITS = 20; +var MAX_SYMBOLS = 258; +var SYMBOL_RUNA = 0; +var SYMBOL_RUNB = 1; +var MIN_GROUPS = 2; +var MAX_GROUPS = 6; +var GROUP_SIZE = 50; + +var WHOLEPI = "314159265359"; +var SQRTPI = "177245385090"; + +var mtf = function mtf(array, index) { + var src = array[index], + i; + for (i = index; i > 0; i--) { + array[i] = array[i - 1]; + } + array[0] = src; + return src; +}; + +var Err = { + OK: 0, + LAST_BLOCK: -1, + NOT_BZIP_DATA: -2, + UNEXPECTED_INPUT_EOF: -3, + UNEXPECTED_OUTPUT_EOF: -4, + DATA_ERROR: -5, + OUT_OF_MEMORY: -6, + OBSOLETE_INPUT: -7, + END_OF_BLOCK: -8 +}; +var ErrorMessages = {}; +ErrorMessages[Err.LAST_BLOCK] = "Bad file checksum"; +ErrorMessages[Err.NOT_BZIP_DATA] = "Not bzip data"; +ErrorMessages[Err.UNEXPECTED_INPUT_EOF] = "Unexpected input EOF"; +ErrorMessages[Err.UNEXPECTED_OUTPUT_EOF] = "Unexpected output EOF"; +ErrorMessages[Err.DATA_ERROR] = "Data error"; +ErrorMessages[Err.OUT_OF_MEMORY] = "Out of memory"; +ErrorMessages[Err.OBSOLETE_INPUT] = "Obsolete (pre 0.9.5) bzip format not supported."; + +var _throw = function _throw(status, optDetail) { + var msg = ErrorMessages[status] || 'unknown error'; + if (optDetail) { + msg += ': ' + optDetail; + } + var e = new TypeError(msg); + e.errorCode = status; + throw e; +}; + +var Bunzip = function Bunzip(inputStream, outputStream) { + this.writePos = this.writeCurrent = this.writeCount = 0; + + this._start_bunzip(inputStream, outputStream); +}; +Bunzip.prototype._init_block = function () { + var moreBlocks = this._get_next_block(); + if (!moreBlocks) { + this.writeCount = -1; + return false; /* no more blocks */ + } + this.blockCRC = new CRC32(); + return true; +}; +/* XXX micro-bunzip uses (inputStream, inputBuffer, len) as arguments */ +Bunzip.prototype._start_bunzip = function (inputStream, outputStream) { + /* Ensure that file starts with "BZh['1'-'9']." */ + var buf = new Uint8Array(4); + if (inputStream.read(buf, 0, 4) !== 4 || String.fromCharCode(buf[0], buf[1], buf[2]) !== 'BZh') _throw(Err.NOT_BZIP_DATA, 'bad magic'); + + var level = buf[3] - 0x30; + if (level < 1 || level > 9) _throw(Err.NOT_BZIP_DATA, 'level out of range'); + + this.reader = new BitReader(inputStream); + + /* Fourth byte (ascii '1'-'9'), indicates block size in units of 100k of + uncompressed data. Allocate intermediate buffer for block. */ + this.dbufSize = 100000 * level; + this.nextoutput = 0; + this.outputStream = outputStream; + this.streamCRC = 0; +}; +Bunzip.prototype._get_next_block = function () { + var i, j, k; + var reader = this.reader; + // this is get_next_block() function from micro-bunzip: + /* Read in header signature and CRC, then validate signature. + (last block signature means CRC is for whole file, return now) */ + var h = reader.pi(); + if (h === SQRTPI) { + // last block + return false; /* no more blocks */ + } + if (h !== WHOLEPI) _throw(Err.NOT_BZIP_DATA); + this.targetBlockCRC = reader.read(32) >>> 0; // (convert to unsigned) + this.streamCRC = (this.targetBlockCRC ^ (this.streamCRC << 1 | this.streamCRC >>> 31)) >>> 0; + /* We can add support for blockRandomised if anybody complains. There was + some code for this in busybox 1.0.0-pre3, but nobody ever noticed that + it didn't actually work. */ + if (reader.read(1)) _throw(Err.OBSOLETE_INPUT); + var origPointer = reader.read(24); + if (origPointer > this.dbufSize) _throw(Err.DATA_ERROR, 'initial position out of bounds'); + /* mapping table: if some byte values are never used (encoding things + like ascii text), the compression code removes the gaps to have fewer + symbols to deal with, and writes a sparse bitfield indicating which + values were present. We make a translation table to convert the symbols + back to the corresponding bytes. */ + var t = reader.read(16); + var symToByte = new Uint8Array(256), + symTotal = 0; + for (i = 0; i < 16; i++) { + if (t & 1 << 0xF - i) { + var o = i * 16; + k = reader.read(16); + for (j = 0; j < 16; j++) if (k & 1 << 0xF - j) symToByte[symTotal++] = o + j; + } + } + + /* How many different huffman coding groups does this block use? */ + var groupCount = reader.read(3); + if (groupCount < MIN_GROUPS || groupCount > MAX_GROUPS) _throw(Err.DATA_ERROR); + /* nSelectors: Every GROUP_SIZE many symbols we select a new huffman coding + group. Read in the group selector list, which is stored as MTF encoded + bit runs. (MTF=Move To Front, as each value is used it's moved to the + start of the list.) */ + var nSelectors = reader.read(15); + if (nSelectors === 0) _throw(Err.DATA_ERROR); + + var mtfSymbol = new Uint8Array(256); + for (i = 0; i < groupCount; i++) mtfSymbol[i] = i; + + var selectors = new Uint8Array(nSelectors); // was 32768... + + for (i = 0; i < nSelectors; i++) { + /* Get next value */ + for (j = 0; reader.read(1); j++) if (j >= groupCount) _throw(Err.DATA_ERROR); + /* Decode MTF to get the next selector */ + selectors[i] = mtf(mtfSymbol, j); + } + + /* Read the huffman coding tables for each group, which code for symTotal + literal symbols, plus two run symbols (RUNA, RUNB) */ + var symCount = symTotal + 2; + var groups = [], + hufGroup; + for (j = 0; j < groupCount; j++) { + var length = new Uint8Array(symCount), + temp = new Uint16Array(MAX_HUFCODE_BITS + 1); + /* Read huffman code lengths for each symbol. They're stored in + a way similar to mtf; record a starting value for the first symbol, + and an offset from the previous value for everys symbol after that. */ + t = reader.read(5); // lengths + for (i = 0; i < symCount; i++) { + for (;;) { + if (t < 1 || t > MAX_HUFCODE_BITS) _throw(Err.DATA_ERROR); + /* If first bit is 0, stop. Else second bit indicates whether + to increment or decrement the value. */ + if (!reader.read(1)) break; + if (!reader.read(1)) t++;else t--; + } + length[i] = t; + } + + /* Find largest and smallest lengths in this group */ + var minLen, maxLen; + minLen = maxLen = length[0]; + for (i = 1; i < symCount; i++) { + if (length[i] > maxLen) maxLen = length[i];else if (length[i] < minLen) minLen = length[i]; + } + + /* Calculate permute[], base[], and limit[] tables from length[]. + * + * permute[] is the lookup table for converting huffman coded symbols + * into decoded symbols. base[] is the amount to subtract from the + * value of a huffman symbol of a given length when using permute[]. + * + * limit[] indicates the largest numerical value a symbol with a given + * number of bits can have. This is how the huffman codes can vary in + * length: each code with a value>limit[length] needs another bit. + */ + hufGroup = {}; + groups.push(hufGroup); + hufGroup.permute = new Uint16Array(MAX_SYMBOLS); + hufGroup.limit = new Uint32Array(MAX_HUFCODE_BITS + 2); + hufGroup.base = new Uint32Array(MAX_HUFCODE_BITS + 1); + hufGroup.minLen = minLen; + hufGroup.maxLen = maxLen; + /* Calculate permute[]. Concurently, initialize temp[] and limit[]. */ + var pp = 0; + for (i = minLen; i <= maxLen; i++) { + temp[i] = hufGroup.limit[i] = 0; + for (t = 0; t < symCount; t++) if (length[t] === i) hufGroup.permute[pp++] = t; + } + /* Count symbols coded for at each bit length */ + for (i = 0; i < symCount; i++) temp[length[i]]++; + /* Calculate limit[] (the largest symbol-coding value at each bit + * length, which is (previous limit<<1)+symbols at this level), and + * base[] (number of symbols to ignore at each bit length, which is + * limit minus the cumulative count of symbols coded for already). */ + pp = t = 0; + for (i = minLen; i < maxLen; i++) { + pp += temp[i]; + /* We read the largest possible symbol size and then unget bits + after determining how many we need, and those extra bits could + be set to anything. (They're noise from future symbols.) At + each level we're really only interested in the first few bits, + so here we set all the trailing to-be-ignored bits to 1 so they + don't affect the value>limit[length] comparison. */ + hufGroup.limit[i] = pp - 1; + pp <<= 1; + t += temp[i]; + hufGroup.base[i + 1] = pp - t; + } + hufGroup.limit[maxLen + 1] = Number.MAX_VALUE; /* Sentinal value for reading next sym. */ + hufGroup.limit[maxLen] = pp + temp[maxLen] - 1; + hufGroup.base[minLen] = 0; + } + /* We've finished reading and digesting the block header. Now read this + block's huffman coded symbols from the file and undo the huffman coding + and run length encoding, saving the result into dbuf[dbufCount++]=uc */ + + /* Initialize symbol occurrence counters and symbol Move To Front table */ + var byteCount = new Uint32Array(256); + for (i = 0; i < 256; i++) mtfSymbol[i] = i; + /* Loop through compressed symbols. */ + var runPos = 0, + dbufCount = 0, + selector = 0, + uc; + var dbuf = this.dbuf = new Uint32Array(this.dbufSize); + symCount = 0; + for (;;) { + /* Determine which huffman coding group to use. */ + if (!symCount--) { + symCount = GROUP_SIZE - 1; + if (selector >= nSelectors) { + _throw(Err.DATA_ERROR); + } + hufGroup = groups[selectors[selector++]]; + } + /* Read next huffman-coded symbol. */ + i = hufGroup.minLen; + j = reader.read(i); + for (;; i++) { + if (i > hufGroup.maxLen) { + _throw(Err.DATA_ERROR); + } + if (j <= hufGroup.limit[i]) break; + j = j << 1 | reader.read(1); + } + /* Huffman decode value to get nextSym (with bounds checking) */ + j -= hufGroup.base[i]; + if (j < 0 || j >= MAX_SYMBOLS) { + _throw(Err.DATA_ERROR); + } + var nextSym = hufGroup.permute[j]; + /* We have now decoded the symbol, which indicates either a new literal + byte, or a repeated run of the most recent literal byte. First, + check if nextSym indicates a repeated run, and if so loop collecting + how many times to repeat the last literal. */ + if (nextSym === SYMBOL_RUNA || nextSym === SYMBOL_RUNB) { + /* If this is the start of a new run, zero out counter */ + if (!runPos) { + runPos = 1; + t = 0; + } + /* Neat trick that saves 1 symbol: instead of or-ing 0 or 1 at + each bit position, add 1 or 2 instead. For example, + 1011 is 1<<0 + 1<<1 + 2<<2. 1010 is 2<<0 + 2<<1 + 1<<2. + You can make any bit pattern that way using 1 less symbol than + the basic or 0/1 method (except all bits 0, which would use no + symbols, but a run of length 0 doesn't mean anything in this + context). Thus space is saved. */ + if (nextSym === SYMBOL_RUNA) t += runPos;else t += 2 * runPos; + runPos <<= 1; + continue; + } + /* When we hit the first non-run symbol after a run, we now know + how many times to repeat the last literal, so append that many + copies to our buffer of decoded symbols (dbuf) now. (The last + literal used is the one at the head of the mtfSymbol array.) */ + if (runPos) { + runPos = 0; + if (dbufCount + t > this.dbufSize) { + _throw(Err.DATA_ERROR); + } + uc = symToByte[mtfSymbol[0]]; + byteCount[uc] += t; + while (t--) dbuf[dbufCount++] = uc; + } + /* Is this the terminating symbol? */ + if (nextSym > symTotal) break; + /* At this point, nextSym indicates a new literal character. Subtract + one to get the position in the MTF array at which this literal is + currently to be found. (Note that the result can't be -1 or 0, + because 0 and 1 are RUNA and RUNB. But another instance of the + first symbol in the mtf array, position 0, would have been handled + as part of a run above. Therefore 1 unused mtf position minus + 2 non-literal nextSym values equals -1.) */ + if (dbufCount >= this.dbufSize) { + _throw(Err.DATA_ERROR); + } + i = nextSym - 1; + uc = mtf(mtfSymbol, i); + uc = symToByte[uc]; + /* We have our literal byte. Save it into dbuf. */ + byteCount[uc]++; + dbuf[dbufCount++] = uc; + } + /* At this point, we've read all the huffman-coded symbols (and repeated + runs) for this block from the input stream, and decoded them into the + intermediate buffer. There are dbufCount many decoded bytes in dbuf[]. + Now undo the Burrows-Wheeler transform on dbuf. + See http://dogma.net/markn/articles/bwt/bwt.htm + */ + if (origPointer < 0 || origPointer >= dbufCount) { + _throw(Err.DATA_ERROR); + } + /* Turn byteCount into cumulative occurrence counts of 0 to n-1. */ + j = 0; + for (i = 0; i < 256; i++) { + k = j + byteCount[i]; + byteCount[i] = j; + j = k; + } + /* Figure out what order dbuf would be in if we sorted it. */ + for (i = 0; i < dbufCount; i++) { + uc = dbuf[i] & 0xff; + dbuf[byteCount[uc]] |= i << 8; + byteCount[uc]++; + } + /* Decode first byte by hand to initialize "previous" byte. Note that it + doesn't get output, and if the first three characters are identical + it doesn't qualify as a run (hence writeRunCountdown=5). */ + var pos = 0, + current = 0, + run = 0; + if (dbufCount) { + pos = dbuf[origPointer]; + current = pos & 0xff; + pos >>= 8; + run = -1; + } + this.writePos = pos; + this.writeCurrent = current; + this.writeCount = dbufCount; + this.writeRun = run; + + return true; /* more blocks to come */ +}; +/* Undo burrows-wheeler transform on intermediate buffer to produce output. + If start_bunzip was initialized with out_fd=-1, then up to len bytes of + data are written to outbuf. Return value is number of bytes written or + error (all errors are negative numbers). If out_fd!=-1, outbuf and len + are ignored, data is written to out_fd and return is RETVAL_OK or error. +*/ +Bunzip.prototype._read_bunzip = function (outputBuffer, len) { + var copies, previous, outbyte; + /* james@jamestaylor.org: writeCount goes to -1 when the buffer is fully + decoded, which results in this returning RETVAL_LAST_BLOCK, also + equal to -1... Confusing, I'm returning 0 here to indicate no + bytes written into the buffer */ + if (this.writeCount < 0) { + return 0; + } + + var gotcount = 0; + var dbuf = this.dbuf, + pos = this.writePos, + current = this.writeCurrent; + var dbufCount = this.writeCount, + outputsize = this.outputsize; + var run = this.writeRun; + + while (dbufCount) { + dbufCount--; + previous = current; + pos = dbuf[pos]; + current = pos & 0xff; + pos >>= 8; + if (run++ === 3) { + copies = current; + outbyte = previous; + current = -1; + } else { + copies = 1; + outbyte = current; + } + this.blockCRC.updateCRCRun(outbyte, copies); + while (copies--) { + this.outputStream.writeByte(outbyte); + this.nextoutput++; + } + if (current != previous) run = 0; + } + this.writeCount = dbufCount; + // check CRC + if (this.blockCRC.getCRC() !== this.targetBlockCRC) { + _throw(Err.DATA_ERROR, "Bad block CRC " + "(got " + this.blockCRC.getCRC().toString(16) + " expected " + this.targetBlockCRC.toString(16) + ")"); + } + return this.nextoutput; +}; + +var coerceInputStream = function coerceInputStream(input) { + if ('readByte' in input) { + return input; + } + var inputStream = new Stream(); + inputStream.pos = 0; + inputStream.readByte = function () { + return input[this.pos++]; + }; + inputStream.seek = function (pos) { + this.pos = pos; + }; + inputStream.eof = function () { + return this.pos >= input.length; + }; + return inputStream; +}; +var coerceOutputStream = function coerceOutputStream(output) { + var outputStream = new Stream(); + var resizeOk = true; + if (output) { + if (typeof output === 'number') { + outputStream.buffer = new Uint8Array(output); + resizeOk = false; + } else if ('writeByte' in output) { + return output; + } else { + outputStream.buffer = output; + resizeOk = false; + } + } else { + outputStream.buffer = new Uint8Array(16384); + } + outputStream.pos = 0; + outputStream.writeByte = function (_byte) { + if (resizeOk && this.pos >= this.buffer.length) { + var newBuffer = new Uint8Array(this.buffer.length * 2); + newBuffer.set(this.buffer); + this.buffer = newBuffer; + } + this.buffer[this.pos++] = _byte; + }; + outputStream.getBuffer = function () { + // trim buffer + if (this.pos !== this.buffer.length) { + if (!resizeOk) throw new TypeError('outputsize does not match decoded input'); + var newBuffer = new Uint8Array(this.pos); + newBuffer.set(this.buffer.subarray(0, this.pos)); + this.buffer = newBuffer; + } + return this.buffer; + }; + outputStream._coerced = true; + return outputStream; +}; + +/* Static helper functions */ +Bunzip.Err = Err; +// 'input' can be a stream or a buffer +// 'output' can be a stream or a buffer or a number (buffer size) +Bunzip.decode = function (input, output, multistream) { + // make a stream from a buffer, if necessary + var inputStream = coerceInputStream(input); + var outputStream = coerceOutputStream(output); + + var bz = new Bunzip(inputStream, outputStream); + while (true) { + if ('eof' in inputStream && inputStream.eof()) break; + if (bz._init_block()) { + bz._read_bunzip(); + } else { + var targetStreamCRC = bz.reader.read(32) >>> 0; // (convert to unsigned) + if (targetStreamCRC !== bz.streamCRC) { + _throw(Err.DATA_ERROR, "Bad stream CRC " + "(got " + bz.streamCRC.toString(16) + " expected " + targetStreamCRC.toString(16) + ")"); + } + if (multistream && 'eof' in inputStream && !inputStream.eof()) { + // note that start_bunzip will also resync the bit reader to next byte + bz._start_bunzip(inputStream, outputStream); + } else break; + } + } + if ('getBuffer' in outputStream) return outputStream.getBuffer(); +}; +Bunzip.decodeBlock = function (input, pos, output) { + // make a stream from a buffer, if necessary + var inputStream = coerceInputStream(input); + var outputStream = coerceOutputStream(output); + var bz = new Bunzip(inputStream, outputStream); + bz.reader.seek(pos); + /* Fill the decode buffer for the block */ + var moreBlocks = bz._get_next_block(); + if (moreBlocks) { + /* Init the CRC for writing */ + bz.blockCRC = new CRC32(); + + /* Zero this so the current byte from before the seek is not written */ + bz.writeCopies = 0; + + /* Decompress the block and write to stdout */ + bz._read_bunzip(); + // XXX keep writing? + } + if ('getBuffer' in outputStream) return outputStream.getBuffer(); +}; +/* Reads bzip2 file from stream or buffer `input`, and invoke + * `callback(position, size)` once for each bzip2 block, + * where position gives the starting position (in *bits*) + * and size gives uncompressed size of the block (in *bytes*). */ +Bunzip.table = function (input, callback, multistream) { + // make a stream from a buffer, if necessary + var inputStream = new Stream(); + inputStream.delegate = coerceInputStream(input); + inputStream.pos = 0; + inputStream.readByte = function () { + this.pos++; + return this.delegate.readByte(); + }; + if (inputStream.delegate.eof) { + inputStream.eof = inputStream.delegate.eof.bind(inputStream.delegate); + } + var outputStream = new Stream(); + outputStream.pos = 0; + outputStream.writeByte = function () { + this.pos++; + }; + + var bz = new Bunzip(inputStream, outputStream); + var blockSize = bz.dbufSize; + while (true) { + if ('eof' in inputStream && inputStream.eof()) break; + + var position = inputStream.pos * 8 + bz.reader.bitOffset; + if (bz.reader.hasByte) { + position -= 8; + } + + if (bz._init_block()) { + var start = outputStream.pos; + bz._read_bunzip(); + callback(position, outputStream.pos - start); + } else { + var crc = bz.reader.read(32); // (but we ignore the crc) + if (multistream && 'eof' in inputStream && !inputStream.eof()) { + // note that start_bunzip will also resync the bit reader to next byte + bz._start_bunzip(inputStream, outputStream); + console.assert(bz.dbufSize === blockSize, "shouldn't change block size within multistream file"); + } else break; + } + } +}; + +Bunzip.Stream = Stream; + +module.exports = Bunzip; + +},{"./bitreader":67,"./crc32":68,"./stream":70}],70:[function(require,module,exports){ +"use strict"; + +/* very simple input/output stream interface */ +var Stream = function Stream() {}; + +// input streams ////////////// +/** Returns the next byte, or -1 for EOF. */ +Stream.prototype.readByte = function () { + throw new Error("abstract method readByte() not implemented"); +}; +/** Attempts to fill the buffer; returns number of bytes read, or + * -1 for EOF. */ +Stream.prototype.read = function (buffer, bufOffset, length) { + var bytesRead = 0; + while (bytesRead < length) { + var c = this.readByte(); + if (c < 0) { + // EOF + return bytesRead === 0 ? -1 : bytesRead; + } + buffer[bufOffset++] = c; + bytesRead++; + } + return bytesRead; +}; +Stream.prototype.seek = function (new_pos) { + throw new Error("abstract method seek() not implemented"); +}; + +// output streams /////////// +Stream.prototype.writeByte = function (_byte) { + throw new Error("abstract method readByte() not implemented"); +}; +Stream.prototype.write = function (buffer, bufOffset, length) { + var i; + for (i = 0; i < length; i++) { + this.writeByte(buffer[bufOffset++]); + } + return length; +}; +Stream.prototype.flush = function () {}; + +module.exports = Stream; + +},{}],71:[function(require,module,exports){ +'use strict'; + +// This is free and unencumbered software released into the public domain. +// See LICENSE.md for more information. + +// +// Utilities +// + +/** + * @param {number} a The number to test. + * @param {number} min The minimum value in the range, inclusive. + * @param {number} max The maximum value in the range, inclusive. + * @return {boolean} True if a >= min and a <= max. + */ +function inRange(a, min, max) { + return min <= a && a <= max; +} + +/** + * @param {*} o + * @return {Object} + */ +function ToDictionary(o) { + if (o === undefined) return {}; + if (o === Object(o)) return o; + throw TypeError('Could not convert argument to dictionary'); +} + +/** + * @param {string} string Input string of UTF-16 code units. + * @return {!Array.} Code points. + */ +function stringToCodePoints(string) { + // https://heycam.github.io/webidl/#dfn-obtain-unicode + + // 1. Let S be the DOMString value. + var s = String(string); + + // 2. Let n be the length of S. + var n = s.length; + + // 3. Initialize i to 0. + var i = 0; + + // 4. Initialize U to be an empty sequence of Unicode characters. + var u = []; + + // 5. While i < n: + while (i < n) { + + // 1. Let c be the code unit in S at index i. + var c = s.charCodeAt(i); + + // 2. Depending on the value of c: + + // c < 0xD800 or c > 0xDFFF + if (c < 0xD800 || c > 0xDFFF) { + // Append to U the Unicode character with code point c. + u.push(c); + } + + // 0xDC00 ≤ c ≤ 0xDFFF + else if (0xDC00 <= c && c <= 0xDFFF) { + // Append to U a U+FFFD REPLACEMENT CHARACTER. + u.push(0xFFFD); + } + + // 0xD800 ≤ c ≤ 0xDBFF + else if (0xD800 <= c && c <= 0xDBFF) { + // 1. If i = n−1, then append to U a U+FFFD REPLACEMENT + // CHARACTER. + if (i === n - 1) { + u.push(0xFFFD); + } + // 2. Otherwise, i < n−1: + else { + // 1. Let d be the code unit in S at index i+1. + var d = string.charCodeAt(i + 1); + + // 2. If 0xDC00 ≤ d ≤ 0xDFFF, then: + if (0xDC00 <= d && d <= 0xDFFF) { + // 1. Let a be c & 0x3FF. + var a = c & 0x3FF; + + // 2. Let b be d & 0x3FF. + var b = d & 0x3FF; + + // 3. Append to U the Unicode character with code point + // 2^16+2^10*a+b. + u.push(0x10000 + (a << 10) + b); + + // 4. Set i to i+1. + i += 1; + } + + // 3. Otherwise, d < 0xDC00 or d > 0xDFFF. Append to U a + // U+FFFD REPLACEMENT CHARACTER. + else { + u.push(0xFFFD); + } + } + } + + // 3. Set i to i+1. + i += 1; + } + + // 6. Return U. + return u; +} + +/** + * @param {!Array.} code_points Array of code points. + * @return {string} string String of UTF-16 code units. + */ +function codePointsToString(code_points) { + var s = ''; + for (var i = 0; i < code_points.length; ++i) { + var cp = code_points[i]; + if (cp <= 0xFFFF) { + s += String.fromCharCode(cp); + } else { + cp -= 0x10000; + s += String.fromCharCode((cp >> 10) + 0xD800, + (cp & 0x3FF) + 0xDC00); + } + } + return s; +} + + +// +// Implementation of Encoding specification +// https://encoding.spec.whatwg.org/ +// + +// +// 3. Terminology +// + +/** + * End-of-stream is a special token that signifies no more tokens + * are in the stream. + * @const + */ var end_of_stream = -1; + +/** + * A stream represents an ordered sequence of tokens. + * + * @constructor + * @param {!(Array.|Uint8Array)} tokens Array of tokens that provide the + * stream. + */ +function Stream(tokens) { + /** @type {!Array.} */ + this.tokens = [].slice.call(tokens); +} + +Stream.prototype = { + /** + * @return {boolean} True if end-of-stream has been hit. + */ + endOfStream: function() { + return !this.tokens.length; + }, + + /** + * When a token is read from a stream, the first token in the + * stream must be returned and subsequently removed, and + * end-of-stream must be returned otherwise. + * + * @return {number} Get the next token from the stream, or + * end_of_stream. + */ + read: function() { + if (!this.tokens.length) + return end_of_stream; + return this.tokens.shift(); + }, + + /** + * When one or more tokens are prepended to a stream, those tokens + * must be inserted, in given order, before the first token in the + * stream. + * + * @param {(number|!Array.)} token The token(s) to prepend to the stream. + */ + prepend: function(token) { + if (Array.isArray(token)) { + var tokens = /**@type {!Array.}*/(token); + while (tokens.length) + this.tokens.unshift(tokens.pop()); + } else { + this.tokens.unshift(token); + } + }, + + /** + * When one or more tokens are pushed to a stream, those tokens + * must be inserted, in given order, after the last token in the + * stream. + * + * @param {(number|!Array.)} token The tokens(s) to prepend to the stream. + */ + push: function(token) { + if (Array.isArray(token)) { + var tokens = /**@type {!Array.}*/(token); + while (tokens.length) + this.tokens.push(tokens.shift()); + } else { + this.tokens.push(token); + } + } +}; + +// +// 4. Encodings +// + +// 4.1 Encoders and decoders + +/** @const */ +var finished = -1; + +/** + * @param {boolean} fatal If true, decoding errors raise an exception. + * @param {number=} opt_code_point Override the standard fallback code point. + * @return {number} The code point to insert on a decoding error. + */ +function decoderError(fatal, opt_code_point) { + if (fatal) + throw TypeError('Decoder error'); + return opt_code_point || 0xFFFD; +} + +// +// 7. API +// + +/** @const */ var DEFAULT_ENCODING = 'utf-8'; + +// 7.1 Interface TextDecoder + +/** + * @constructor + * @param {string=} encoding The label of the encoding; + * defaults to 'utf-8'. + * @param {Object=} options + */ +function TextDecoder(encoding, options) { + if (!(this instanceof TextDecoder)) { + return new TextDecoder(encoding, options); + } + encoding = encoding !== undefined ? String(encoding).toLowerCase() : DEFAULT_ENCODING; + if (encoding !== DEFAULT_ENCODING) { + throw new Error('Encoding not supported. Only utf-8 is supported'); + } + options = ToDictionary(options); + + /** @private @type {boolean} */ + this._streaming = false; + /** @private @type {boolean} */ + this._BOMseen = false; + /** @private @type {?Decoder} */ + this._decoder = null; + /** @private @type {boolean} */ + this._fatal = Boolean(options['fatal']); + /** @private @type {boolean} */ + this._ignoreBOM = Boolean(options['ignoreBOM']); + + Object.defineProperty(this, 'encoding', {value: 'utf-8'}); + Object.defineProperty(this, 'fatal', {value: this._fatal}); + Object.defineProperty(this, 'ignoreBOM', {value: this._ignoreBOM}); +} + +TextDecoder.prototype = { + /** + * @param {ArrayBufferView=} input The buffer of bytes to decode. + * @param {Object=} options + * @return {string} The decoded string. + */ + decode: function decode(input, options) { + var bytes; + if (typeof input === 'object' && input instanceof ArrayBuffer) { + bytes = new Uint8Array(input); + } else if (typeof input === 'object' && 'buffer' in input && + input.buffer instanceof ArrayBuffer) { + bytes = new Uint8Array(input.buffer, + input.byteOffset, + input.byteLength); + } else { + bytes = new Uint8Array(0); + } + + options = ToDictionary(options); + + if (!this._streaming) { + this._decoder = new UTF8Decoder({fatal: this._fatal}); + this._BOMseen = false; + } + this._streaming = Boolean(options['stream']); + + var input_stream = new Stream(bytes); + + var code_points = []; + + /** @type {?(number|!Array.)} */ + var result; + + while (!input_stream.endOfStream()) { + result = this._decoder.handler(input_stream, input_stream.read()); + if (result === finished) + break; + if (result === null) + continue; + if (Array.isArray(result)) + code_points.push.apply(code_points, /**@type {!Array.}*/(result)); + else + code_points.push(result); + } + if (!this._streaming) { + do { + result = this._decoder.handler(input_stream, input_stream.read()); + if (result === finished) + break; + if (result === null) + continue; + if (Array.isArray(result)) + code_points.push.apply(code_points, /**@type {!Array.}*/(result)); + else + code_points.push(result); + } while (!input_stream.endOfStream()); + this._decoder = null; + } + + if (code_points.length) { + // If encoding is one of utf-8, utf-16be, and utf-16le, and + // ignore BOM flag and BOM seen flag are unset, run these + // subsubsteps: + if (['utf-8'].indexOf(this.encoding) !== -1 && + !this._ignoreBOM && !this._BOMseen) { + // If token is U+FEFF, set BOM seen flag. + if (code_points[0] === 0xFEFF) { + this._BOMseen = true; + code_points.shift(); + } else { + // Otherwise, if token is not end-of-stream, set BOM seen + // flag and append token to output. + this._BOMseen = true; + } + } + } + + return codePointsToString(code_points); + } +}; + +// 7.2 Interface TextEncoder + +/** + * @constructor + * @param {string=} encoding The label of the encoding; + * defaults to 'utf-8'. + * @param {Object=} options + */ +function TextEncoder(encoding, options) { + if (!(this instanceof TextEncoder)) + return new TextEncoder(encoding, options); + encoding = encoding !== undefined ? String(encoding).toLowerCase() : DEFAULT_ENCODING; + if (encoding !== DEFAULT_ENCODING) { + throw new Error('Encoding not supported. Only utf-8 is supported'); + } + options = ToDictionary(options); + + /** @private @type {boolean} */ + this._streaming = false; + /** @private @type {?Encoder} */ + this._encoder = null; + /** @private @type {{fatal: boolean}} */ + this._options = {fatal: Boolean(options['fatal'])}; + + Object.defineProperty(this, 'encoding', {value: 'utf-8'}); +} + +TextEncoder.prototype = { + /** + * @param {string=} opt_string The string to encode. + * @param {Object=} options + * @return {Uint8Array} Encoded bytes, as a Uint8Array. + */ + encode: function encode(opt_string, options) { + opt_string = opt_string ? String(opt_string) : ''; + options = ToDictionary(options); + + // NOTE: This option is nonstandard. None of the encodings + // permitted for encoding (i.e. UTF-8, UTF-16) are stateful, + // so streaming is not necessary. + if (!this._streaming) + this._encoder = new UTF8Encoder(this._options); + this._streaming = Boolean(options['stream']); + + var bytes = []; + var input_stream = new Stream(stringToCodePoints(opt_string)); + /** @type {?(number|!Array.)} */ + var result; + while (!input_stream.endOfStream()) { + result = this._encoder.handler(input_stream, input_stream.read()); + if (result === finished) + break; + if (Array.isArray(result)) + bytes.push.apply(bytes, /**@type {!Array.}*/(result)); + else + bytes.push(result); + } + if (!this._streaming) { + while (true) { + result = this._encoder.handler(input_stream, input_stream.read()); + if (result === finished) + break; + if (Array.isArray(result)) + bytes.push.apply(bytes, /**@type {!Array.}*/(result)); + else + bytes.push(result); + } + this._encoder = null; + } + return new Uint8Array(bytes); + } +}; + +// +// 8. The encoding +// + +// 8.1 utf-8 + +/** + * @constructor + * @implements {Decoder} + * @param {{fatal: boolean}} options + */ +function UTF8Decoder(options) { + var fatal = options.fatal; + + // utf-8's decoder's has an associated utf-8 code point, utf-8 + // bytes seen, and utf-8 bytes needed (all initially 0), a utf-8 + // lower boundary (initially 0x80), and a utf-8 upper boundary + // (initially 0xBF). + var /** @type {number} */ utf8_code_point = 0, + /** @type {number} */ utf8_bytes_seen = 0, + /** @type {number} */ utf8_bytes_needed = 0, + /** @type {number} */ utf8_lower_boundary = 0x80, + /** @type {number} */ utf8_upper_boundary = 0xBF; + + /** + * @param {Stream} stream The stream of bytes being decoded. + * @param {number} bite The next byte read from the stream. + * @return {?(number|!Array.)} The next code point(s) + * decoded, or null if not enough data exists in the input + * stream to decode a complete code point. + */ + this.handler = function(stream, bite) { + // 1. If byte is end-of-stream and utf-8 bytes needed is not 0, + // set utf-8 bytes needed to 0 and return error. + if (bite === end_of_stream && utf8_bytes_needed !== 0) { + utf8_bytes_needed = 0; + return decoderError(fatal); + } + + // 2. If byte is end-of-stream, return finished. + if (bite === end_of_stream) + return finished; + + // 3. If utf-8 bytes needed is 0, based on byte: + if (utf8_bytes_needed === 0) { + + // 0x00 to 0x7F + if (inRange(bite, 0x00, 0x7F)) { + // Return a code point whose value is byte. + return bite; + } + + // 0xC2 to 0xDF + if (inRange(bite, 0xC2, 0xDF)) { + // Set utf-8 bytes needed to 1 and utf-8 code point to byte + // − 0xC0. + utf8_bytes_needed = 1; + utf8_code_point = bite - 0xC0; + } + + // 0xE0 to 0xEF + else if (inRange(bite, 0xE0, 0xEF)) { + // 1. If byte is 0xE0, set utf-8 lower boundary to 0xA0. + if (bite === 0xE0) + utf8_lower_boundary = 0xA0; + // 2. If byte is 0xED, set utf-8 upper boundary to 0x9F. + if (bite === 0xED) + utf8_upper_boundary = 0x9F; + // 3. Set utf-8 bytes needed to 2 and utf-8 code point to + // byte − 0xE0. + utf8_bytes_needed = 2; + utf8_code_point = bite - 0xE0; + } + + // 0xF0 to 0xF4 + else if (inRange(bite, 0xF0, 0xF4)) { + // 1. If byte is 0xF0, set utf-8 lower boundary to 0x90. + if (bite === 0xF0) + utf8_lower_boundary = 0x90; + // 2. If byte is 0xF4, set utf-8 upper boundary to 0x8F. + if (bite === 0xF4) + utf8_upper_boundary = 0x8F; + // 3. Set utf-8 bytes needed to 3 and utf-8 code point to + // byte − 0xF0. + utf8_bytes_needed = 3; + utf8_code_point = bite - 0xF0; + } + + // Otherwise + else { + // Return error. + return decoderError(fatal); + } + + // Then (byte is in the range 0xC2 to 0xF4) set utf-8 code + // point to utf-8 code point << (6 × utf-8 bytes needed) and + // return continue. + utf8_code_point = utf8_code_point << (6 * utf8_bytes_needed); + return null; + } + + // 4. If byte is not in the range utf-8 lower boundary to utf-8 + // upper boundary, run these substeps: + if (!inRange(bite, utf8_lower_boundary, utf8_upper_boundary)) { + + // 1. Set utf-8 code point, utf-8 bytes needed, and utf-8 + // bytes seen to 0, set utf-8 lower boundary to 0x80, and set + // utf-8 upper boundary to 0xBF. + utf8_code_point = utf8_bytes_needed = utf8_bytes_seen = 0; + utf8_lower_boundary = 0x80; + utf8_upper_boundary = 0xBF; + + // 2. Prepend byte to stream. + stream.prepend(bite); + + // 3. Return error. + return decoderError(fatal); + } + + // 5. Set utf-8 lower boundary to 0x80 and utf-8 upper boundary + // to 0xBF. + utf8_lower_boundary = 0x80; + utf8_upper_boundary = 0xBF; + + // 6. Increase utf-8 bytes seen by one and set utf-8 code point + // to utf-8 code point + (byte − 0x80) << (6 × (utf-8 bytes + // needed − utf-8 bytes seen)). + utf8_bytes_seen += 1; + utf8_code_point += (bite - 0x80) << (6 * (utf8_bytes_needed - utf8_bytes_seen)); + + // 7. If utf-8 bytes seen is not equal to utf-8 bytes needed, + // continue. + if (utf8_bytes_seen !== utf8_bytes_needed) + return null; + + // 8. Let code point be utf-8 code point. + var code_point = utf8_code_point; + + // 9. Set utf-8 code point, utf-8 bytes needed, and utf-8 bytes + // seen to 0. + utf8_code_point = utf8_bytes_needed = utf8_bytes_seen = 0; + + // 10. Return a code point whose value is code point. + return code_point; + }; +} + +/** + * @constructor + * @implements {Encoder} + * @param {{fatal: boolean}} options + */ +function UTF8Encoder(options) { + var fatal = options.fatal; + /** + * @param {Stream} stream Input stream. + * @param {number} code_point Next code point read from the stream. + * @return {(number|!Array.)} Byte(s) to emit. + */ + this.handler = function(stream, code_point) { + // 1. If code point is end-of-stream, return finished. + if (code_point === end_of_stream) + return finished; + + // 2. If code point is in the range U+0000 to U+007F, return a + // byte whose value is code point. + if (inRange(code_point, 0x0000, 0x007f)) + return code_point; + + // 3. Set count and offset based on the range code point is in: + var count, offset; + // U+0080 to U+07FF: 1 and 0xC0 + if (inRange(code_point, 0x0080, 0x07FF)) { + count = 1; + offset = 0xC0; + } + // U+0800 to U+FFFF: 2 and 0xE0 + else if (inRange(code_point, 0x0800, 0xFFFF)) { + count = 2; + offset = 0xE0; + } + // U+10000 to U+10FFFF: 3 and 0xF0 + else if (inRange(code_point, 0x10000, 0x10FFFF)) { + count = 3; + offset = 0xF0; + } + + // 4.Let bytes be a byte sequence whose first byte is (code + // point >> (6 × count)) + offset. + var bytes = [(code_point >> (6 * count)) + offset]; + + // 5. Run these substeps while count is greater than 0: + while (count > 0) { + + // 1. Set temp to code point >> (6 × (count − 1)). + var temp = code_point >> (6 * (count - 1)); + + // 2. Append to bytes 0x80 | (temp & 0x3F). + bytes.push(0x80 | (temp & 0x3F)); + + // 3. Decrease count by one. + count -= 1; + } + + // 6. Return bytes bytes, in order. + return bytes; + }; +} + +exports.TextEncoder = TextEncoder; +exports.TextDecoder = TextDecoder; +},{}],72:[function(require,module,exports){ +/*jshint bitwise: false*/ + +(function(nacl) { +'use strict'; + +// Ported in 2014 by Dmitry Chestnykh and Devi Mandiri. +// Public domain. +// +// Implementation derived from TweetNaCl version 20140427. +// See for details: http://tweetnacl.cr.yp.to/ + +var gf = function(init) { + var i, r = new Float64Array(16); + if (init) for (i = 0; i < init.length; i++) r[i] = init[i]; + return r; +}; + +// Pluggable, initialized in high-level API below. +var randombytes = function(/* x, n */) { throw new Error('no PRNG'); }; + +var _9 = new Uint8Array(32); _9[0] = 9; + +var gf0 = gf(), + gf1 = gf([1]), + _121665 = gf([0xdb41, 1]), + D = gf([0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203]), + D2 = gf([0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406]), + X = gf([0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169]), + Y = gf([0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666]), + I = gf([0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83]); + +function vn(x, xi, y, yi, n) { + var i,d = 0; + for (i = 0; i < n; i++) d |= x[xi+i]^y[yi+i]; + return (1 & ((d - 1) >>> 8)) - 1; +} + +function crypto_verify_32(x, xi, y, yi) { + return vn(x,xi,y,yi,32); +} + +function set25519(r, a) { + var i; + for (i = 0; i < 16; i++) r[i] = a[i]|0; +} + +function car25519(o) { + var i, v, c = 1; + for (i = 0; i < 16; i++) { + v = o[i] + c + 65535; + c = Math.floor(v / 65536); + o[i] = v - c * 65536; + } + o[0] += c-1 + 37 * (c-1); +} + +function sel25519(p, q, b) { + var t, c = ~(b-1); + for (var i = 0; i < 16; i++) { + t = c & (p[i] ^ q[i]); + p[i] ^= t; + q[i] ^= t; + } +} + +function pack25519(o, n) { + var i, j, b; + var m = gf(), t = gf(); + for (i = 0; i < 16; i++) t[i] = n[i]; + car25519(t); + car25519(t); + car25519(t); + for (j = 0; j < 2; j++) { + m[0] = t[0] - 0xffed; + for (i = 1; i < 15; i++) { + m[i] = t[i] - 0xffff - ((m[i-1]>>16) & 1); + m[i-1] &= 0xffff; + } + m[15] = t[15] - 0x7fff - ((m[14]>>16) & 1); + b = (m[15]>>16) & 1; + m[14] &= 0xffff; + sel25519(t, m, 1-b); + } + for (i = 0; i < 16; i++) { + o[2*i] = t[i] & 0xff; + o[2*i+1] = t[i]>>8; + } +} + +function neq25519(a, b) { + var c = new Uint8Array(32), d = new Uint8Array(32); + pack25519(c, a); + pack25519(d, b); + return crypto_verify_32(c, 0, d, 0); +} + +function par25519(a) { + var d = new Uint8Array(32); + pack25519(d, a); + return d[0] & 1; +} + +function unpack25519(o, n) { + var i; + for (i = 0; i < 16; i++) o[i] = n[2*i] + (n[2*i+1] << 8); + o[15] &= 0x7fff; +} + +function A(o, a, b) { + for (var i = 0; i < 16; i++) o[i] = a[i] + b[i]; +} + +function Z(o, a, b) { + for (var i = 0; i < 16; i++) o[i] = a[i] - b[i]; +} + +function M(o, a, b) { + var v, c, + t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0, + t8 = 0, t9 = 0, t10 = 0, t11 = 0, t12 = 0, t13 = 0, t14 = 0, t15 = 0, + t16 = 0, t17 = 0, t18 = 0, t19 = 0, t20 = 0, t21 = 0, t22 = 0, t23 = 0, + t24 = 0, t25 = 0, t26 = 0, t27 = 0, t28 = 0, t29 = 0, t30 = 0, + b0 = b[0], + b1 = b[1], + b2 = b[2], + b3 = b[3], + b4 = b[4], + b5 = b[5], + b6 = b[6], + b7 = b[7], + b8 = b[8], + b9 = b[9], + b10 = b[10], + b11 = b[11], + b12 = b[12], + b13 = b[13], + b14 = b[14], + b15 = b[15]; + + v = a[0]; + t0 += v * b0; + t1 += v * b1; + t2 += v * b2; + t3 += v * b3; + t4 += v * b4; + t5 += v * b5; + t6 += v * b6; + t7 += v * b7; + t8 += v * b8; + t9 += v * b9; + t10 += v * b10; + t11 += v * b11; + t12 += v * b12; + t13 += v * b13; + t14 += v * b14; + t15 += v * b15; + v = a[1]; + t1 += v * b0; + t2 += v * b1; + t3 += v * b2; + t4 += v * b3; + t5 += v * b4; + t6 += v * b5; + t7 += v * b6; + t8 += v * b7; + t9 += v * b8; + t10 += v * b9; + t11 += v * b10; + t12 += v * b11; + t13 += v * b12; + t14 += v * b13; + t15 += v * b14; + t16 += v * b15; + v = a[2]; + t2 += v * b0; + t3 += v * b1; + t4 += v * b2; + t5 += v * b3; + t6 += v * b4; + t7 += v * b5; + t8 += v * b6; + t9 += v * b7; + t10 += v * b8; + t11 += v * b9; + t12 += v * b10; + t13 += v * b11; + t14 += v * b12; + t15 += v * b13; + t16 += v * b14; + t17 += v * b15; + v = a[3]; + t3 += v * b0; + t4 += v * b1; + t5 += v * b2; + t6 += v * b3; + t7 += v * b4; + t8 += v * b5; + t9 += v * b6; + t10 += v * b7; + t11 += v * b8; + t12 += v * b9; + t13 += v * b10; + t14 += v * b11; + t15 += v * b12; + t16 += v * b13; + t17 += v * b14; + t18 += v * b15; + v = a[4]; + t4 += v * b0; + t5 += v * b1; + t6 += v * b2; + t7 += v * b3; + t8 += v * b4; + t9 += v * b5; + t10 += v * b6; + t11 += v * b7; + t12 += v * b8; + t13 += v * b9; + t14 += v * b10; + t15 += v * b11; + t16 += v * b12; + t17 += v * b13; + t18 += v * b14; + t19 += v * b15; + v = a[5]; + t5 += v * b0; + t6 += v * b1; + t7 += v * b2; + t8 += v * b3; + t9 += v * b4; + t10 += v * b5; + t11 += v * b6; + t12 += v * b7; + t13 += v * b8; + t14 += v * b9; + t15 += v * b10; + t16 += v * b11; + t17 += v * b12; + t18 += v * b13; + t19 += v * b14; + t20 += v * b15; + v = a[6]; + t6 += v * b0; + t7 += v * b1; + t8 += v * b2; + t9 += v * b3; + t10 += v * b4; + t11 += v * b5; + t12 += v * b6; + t13 += v * b7; + t14 += v * b8; + t15 += v * b9; + t16 += v * b10; + t17 += v * b11; + t18 += v * b12; + t19 += v * b13; + t20 += v * b14; + t21 += v * b15; + v = a[7]; + t7 += v * b0; + t8 += v * b1; + t9 += v * b2; + t10 += v * b3; + t11 += v * b4; + t12 += v * b5; + t13 += v * b6; + t14 += v * b7; + t15 += v * b8; + t16 += v * b9; + t17 += v * b10; + t18 += v * b11; + t19 += v * b12; + t20 += v * b13; + t21 += v * b14; + t22 += v * b15; + v = a[8]; + t8 += v * b0; + t9 += v * b1; + t10 += v * b2; + t11 += v * b3; + t12 += v * b4; + t13 += v * b5; + t14 += v * b6; + t15 += v * b7; + t16 += v * b8; + t17 += v * b9; + t18 += v * b10; + t19 += v * b11; + t20 += v * b12; + t21 += v * b13; + t22 += v * b14; + t23 += v * b15; + v = a[9]; + t9 += v * b0; + t10 += v * b1; + t11 += v * b2; + t12 += v * b3; + t13 += v * b4; + t14 += v * b5; + t15 += v * b6; + t16 += v * b7; + t17 += v * b8; + t18 += v * b9; + t19 += v * b10; + t20 += v * b11; + t21 += v * b12; + t22 += v * b13; + t23 += v * b14; + t24 += v * b15; + v = a[10]; + t10 += v * b0; + t11 += v * b1; + t12 += v * b2; + t13 += v * b3; + t14 += v * b4; + t15 += v * b5; + t16 += v * b6; + t17 += v * b7; + t18 += v * b8; + t19 += v * b9; + t20 += v * b10; + t21 += v * b11; + t22 += v * b12; + t23 += v * b13; + t24 += v * b14; + t25 += v * b15; + v = a[11]; + t11 += v * b0; + t12 += v * b1; + t13 += v * b2; + t14 += v * b3; + t15 += v * b4; + t16 += v * b5; + t17 += v * b6; + t18 += v * b7; + t19 += v * b8; + t20 += v * b9; + t21 += v * b10; + t22 += v * b11; + t23 += v * b12; + t24 += v * b13; + t25 += v * b14; + t26 += v * b15; + v = a[12]; + t12 += v * b0; + t13 += v * b1; + t14 += v * b2; + t15 += v * b3; + t16 += v * b4; + t17 += v * b5; + t18 += v * b6; + t19 += v * b7; + t20 += v * b8; + t21 += v * b9; + t22 += v * b10; + t23 += v * b11; + t24 += v * b12; + t25 += v * b13; + t26 += v * b14; + t27 += v * b15; + v = a[13]; + t13 += v * b0; + t14 += v * b1; + t15 += v * b2; + t16 += v * b3; + t17 += v * b4; + t18 += v * b5; + t19 += v * b6; + t20 += v * b7; + t21 += v * b8; + t22 += v * b9; + t23 += v * b10; + t24 += v * b11; + t25 += v * b12; + t26 += v * b13; + t27 += v * b14; + t28 += v * b15; + v = a[14]; + t14 += v * b0; + t15 += v * b1; + t16 += v * b2; + t17 += v * b3; + t18 += v * b4; + t19 += v * b5; + t20 += v * b6; + t21 += v * b7; + t22 += v * b8; + t23 += v * b9; + t24 += v * b10; + t25 += v * b11; + t26 += v * b12; + t27 += v * b13; + t28 += v * b14; + t29 += v * b15; + v = a[15]; + t15 += v * b0; + t16 += v * b1; + t17 += v * b2; + t18 += v * b3; + t19 += v * b4; + t20 += v * b5; + t21 += v * b6; + t22 += v * b7; + t23 += v * b8; + t24 += v * b9; + t25 += v * b10; + t26 += v * b11; + t27 += v * b12; + t28 += v * b13; + t29 += v * b14; + t30 += v * b15; + + t0 += 38 * t16; + t1 += 38 * t17; + t2 += 38 * t18; + t3 += 38 * t19; + t4 += 38 * t20; + t5 += 38 * t21; + t6 += 38 * t22; + t7 += 38 * t23; + t8 += 38 * t24; + t9 += 38 * t25; + t10 += 38 * t26; + t11 += 38 * t27; + t12 += 38 * t28; + t13 += 38 * t29; + t14 += 38 * t30; + // t15 left as is + + // first car + c = 1; + v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536; + v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536; + v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536; + v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536; + v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536; + v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536; + v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536; + v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536; + v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536; + v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536; + v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536; + v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536; + v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536; + v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536; + v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536; + v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536; + t0 += c-1 + 37 * (c-1); + + // second car + c = 1; + v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536; + v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536; + v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536; + v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536; + v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536; + v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536; + v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536; + v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536; + v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536; + v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536; + v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536; + v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536; + v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536; + v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536; + v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536; + v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536; + t0 += c-1 + 37 * (c-1); + + o[ 0] = t0; + o[ 1] = t1; + o[ 2] = t2; + o[ 3] = t3; + o[ 4] = t4; + o[ 5] = t5; + o[ 6] = t6; + o[ 7] = t7; + o[ 8] = t8; + o[ 9] = t9; + o[10] = t10; + o[11] = t11; + o[12] = t12; + o[13] = t13; + o[14] = t14; + o[15] = t15; +} + +function S(o, a) { + M(o, a, a); +} + +function inv25519(o, i) { + var c = gf(); + var a; + for (a = 0; a < 16; a++) c[a] = i[a]; + for (a = 253; a >= 0; a--) { + S(c, c); + if(a !== 2 && a !== 4) M(c, c, i); + } + for (a = 0; a < 16; a++) o[a] = c[a]; +} + +function pow2523(o, i) { + var c = gf(); + var a; + for (a = 0; a < 16; a++) c[a] = i[a]; + for (a = 250; a >= 0; a--) { + S(c, c); + if(a !== 1) M(c, c, i); + } + for (a = 0; a < 16; a++) o[a] = c[a]; +} + +function crypto_scalarmult(q, n, p) { + var z = new Uint8Array(32); + var x = new Float64Array(80), r, i; + var a = gf(), b = gf(), c = gf(), + d = gf(), e = gf(), f = gf(); + for (i = 0; i < 31; i++) z[i] = n[i]; + z[31]=(n[31]&127)|64; + z[0]&=248; + unpack25519(x,p); + for (i = 0; i < 16; i++) { + b[i]=x[i]; + d[i]=a[i]=c[i]=0; + } + a[0]=d[0]=1; + for (i=254; i>=0; --i) { + r=(z[i>>>3]>>>(i&7))&1; + sel25519(a,b,r); + sel25519(c,d,r); + A(e,a,c); + Z(a,a,c); + A(c,b,d); + Z(b,b,d); + S(d,e); + S(f,a); + M(a,c,a); + M(c,b,e); + A(e,a,c); + Z(a,a,c); + S(b,a); + Z(c,d,f); + M(a,c,_121665); + A(a,a,d); + M(c,c,a); + M(a,d,f); + M(d,b,x); + S(b,e); + sel25519(a,b,r); + sel25519(c,d,r); + } + for (i = 0; i < 16; i++) { + x[i+16]=a[i]; + x[i+32]=c[i]; + x[i+48]=b[i]; + x[i+64]=d[i]; + } + var x32 = x.subarray(32); + var x16 = x.subarray(16); + inv25519(x32,x32); + M(x16,x16,x32); + pack25519(q,x16); + return 0; +} + +function crypto_scalarmult_base(q, n) { + return crypto_scalarmult(q, n, _9); +} + +function crypto_box_keypair(y, x) { + randombytes(x, 32); + return crypto_scalarmult_base(y, x); +} + +function add(p, q) { + var a = gf(), b = gf(), c = gf(), + d = gf(), e = gf(), f = gf(), + g = gf(), h = gf(), t = gf(); + + Z(a, p[1], p[0]); + Z(t, q[1], q[0]); + M(a, a, t); + A(b, p[0], p[1]); + A(t, q[0], q[1]); + M(b, b, t); + M(c, p[3], q[3]); + M(c, c, D2); + M(d, p[2], q[2]); + A(d, d, d); + Z(e, b, a); + Z(f, d, c); + A(g, d, c); + A(h, b, a); + + M(p[0], e, f); + M(p[1], h, g); + M(p[2], g, f); + M(p[3], e, h); +} + +function cswap(p, q, b) { + var i; + for (i = 0; i < 4; i++) { + sel25519(p[i], q[i], b); + } +} + +function pack(r, p) { + var tx = gf(), ty = gf(), zi = gf(); + inv25519(zi, p[2]); + M(tx, p[0], zi); + M(ty, p[1], zi); + pack25519(r, ty); + r[31] ^= par25519(tx) << 7; +} + +function scalarmult(p, q, s) { + var b, i; + set25519(p[0], gf0); + set25519(p[1], gf1); + set25519(p[2], gf1); + set25519(p[3], gf0); + for (i = 255; i >= 0; --i) { + b = (s[(i/8)|0] >> (i&7)) & 1; + cswap(p, q, b); + add(q, p); + add(p, p); + cswap(p, q, b); + } +} + +function scalarbase(p, s) { + var q = [gf(), gf(), gf(), gf()]; + set25519(q[0], X); + set25519(q[1], Y); + set25519(q[2], gf1); + M(q[3], X, Y); + scalarmult(p, q, s); +} + +function crypto_sign_keypair(pk, sk, seeded) { + var d; + var p = [gf(), gf(), gf(), gf()]; + var i; + + if (!seeded) randombytes(sk, 32); + d = nacl.hash(sk.subarray(0, 32)); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + scalarbase(p, d); + pack(pk, p); + + for (i = 0; i < 32; i++) sk[i+32] = pk[i]; + return 0; +} + +var L = new Float64Array([0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10]); + +function modL(r, x) { + var carry, i, j, k; + for (i = 63; i >= 32; --i) { + carry = 0; + for (j = i - 32, k = i - 12; j < k; ++j) { + x[j] += carry - 16 * x[i] * L[j - (i - 32)]; + carry = (x[j] + 128) >> 8; + x[j] -= carry * 256; + } + x[j] += carry; + x[i] = 0; + } + carry = 0; + for (j = 0; j < 32; j++) { + x[j] += carry - (x[31] >> 4) * L[j]; + carry = x[j] >> 8; + x[j] &= 255; + } + for (j = 0; j < 32; j++) x[j] -= carry * L[j]; + for (i = 0; i < 32; i++) { + x[i+1] += x[i] >> 8; + r[i] = x[i] & 255; + } +} + +function reduce(r) { + var x = new Float64Array(64), i; + for (i = 0; i < 64; i++) x[i] = r[i]; + for (i = 0; i < 64; i++) r[i] = 0; + modL(r, x); +} + +// Note: difference from C - smlen returned, not passed as argument. +function crypto_sign(sm, m, n, sk) { + var d, h, r; + var i, j, x = new Float64Array(64); + var p = [gf(), gf(), gf(), gf()]; + + d = nacl.hash(sk.subarray(0, 32)); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + var smlen = n + 64; + for (i = 0; i < n; i++) sm[64 + i] = m[i]; + for (i = 0; i < 32; i++) sm[32 + i] = d[32 + i]; + + r = nacl.hash(sm.subarray(32, smlen)); + reduce(r); + scalarbase(p, r); + pack(sm, p); + + for (i = 32; i < 64; i++) sm[i] = sk[i]; + h = nacl.hash(sm.subarray(0, smlen)); + reduce(h); + + for (i = 0; i < 64; i++) x[i] = 0; + for (i = 0; i < 32; i++) x[i] = r[i]; + for (i = 0; i < 32; i++) { + for (j = 0; j < 32; j++) { + x[i+j] += h[i] * d[j]; + } + } + + modL(sm.subarray(32), x); + return smlen; +} + +function unpackneg(r, p) { + var t = gf(), chk = gf(), num = gf(), + den = gf(), den2 = gf(), den4 = gf(), + den6 = gf(); + + set25519(r[2], gf1); + unpack25519(r[1], p); + S(num, r[1]); + M(den, num, D); + Z(num, num, r[2]); + A(den, r[2], den); + + S(den2, den); + S(den4, den2); + M(den6, den4, den2); + M(t, den6, num); + M(t, t, den); + + pow2523(t, t); + M(t, t, num); + M(t, t, den); + M(t, t, den); + M(r[0], t, den); + + S(chk, r[0]); + M(chk, chk, den); + if (neq25519(chk, num)) M(r[0], r[0], I); + + S(chk, r[0]); + M(chk, chk, den); + if (neq25519(chk, num)) return -1; + + if (par25519(r[0]) === (p[31]>>7)) Z(r[0], gf0, r[0]); + + M(r[3], r[0], r[1]); + return 0; +} + +function crypto_sign_open(m, sm, n, pk) { + var i, mlen; + var t = new Uint8Array(32), h; + var p = [gf(), gf(), gf(), gf()], + q = [gf(), gf(), gf(), gf()]; + + mlen = -1; + if (n < 64) return -1; + + if (unpackneg(q, pk)) return -1; + + for (i = 0; i < n; i++) m[i] = sm[i]; + for (i = 0; i < 32; i++) m[i+32] = pk[i]; + h = nacl.hash(m.subarray(0, n)); + reduce(h); + scalarmult(p, q, h); + + scalarbase(q, sm.subarray(32)); + add(p, q); + pack(t, p); + + n -= 64; + if (crypto_verify_32(sm, 0, t, 0)) { + for (i = 0; i < n; i++) m[i] = 0; + return -1; + } + + for (i = 0; i < n; i++) m[i] = sm[i + 64]; + mlen = n; + return mlen; +} + +var crypto_scalarmult_BYTES = 32, + crypto_scalarmult_SCALARBYTES = 32, + crypto_box_PUBLICKEYBYTES = 32, + crypto_box_SECRETKEYBYTES = 32, + crypto_sign_BYTES = 64, + crypto_sign_PUBLICKEYBYTES = 32, + crypto_sign_SECRETKEYBYTES = 64, + crypto_sign_SEEDBYTES = 32; + +function checkArrayTypes() { + for (var i = 0; i < arguments.length; i++) { + if (!(arguments[i] instanceof Uint8Array)) + throw new TypeError('unexpected type, use Uint8Array'); + } +} + +function cleanup(arr) { + for (var i = 0; i < arr.length; i++) arr[i] = 0; +} + +nacl.scalarMult = function(n, p) { + checkArrayTypes(n, p); + if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error('bad n size'); + if (p.length !== crypto_scalarmult_BYTES) throw new Error('bad p size'); + var q = new Uint8Array(crypto_scalarmult_BYTES); + crypto_scalarmult(q, n, p); + return q; +}; + +nacl.box = {}; + +nacl.box.keyPair = function() { + var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); + var sk = new Uint8Array(crypto_box_SECRETKEYBYTES); + crypto_box_keypair(pk, sk); + return {publicKey: pk, secretKey: sk}; +}; + +nacl.box.keyPair.fromSecretKey = function(secretKey) { + checkArrayTypes(secretKey); + if (secretKey.length !== crypto_box_SECRETKEYBYTES) + throw new Error('bad secret key size'); + var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); + crypto_scalarmult_base(pk, secretKey); + return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; +}; + +nacl.sign = function(msg, secretKey) { + checkArrayTypes(msg, secretKey); + if (secretKey.length !== crypto_sign_SECRETKEYBYTES) + throw new Error('bad secret key size'); + var signedMsg = new Uint8Array(crypto_sign_BYTES+msg.length); + crypto_sign(signedMsg, msg, msg.length, secretKey); + return signedMsg; +}; + +nacl.sign.detached = function(msg, secretKey) { + var signedMsg = nacl.sign(msg, secretKey); + var sig = new Uint8Array(crypto_sign_BYTES); + for (var i = 0; i < sig.length; i++) sig[i] = signedMsg[i]; + return sig; +}; + +nacl.sign.detached.verify = function(msg, sig, publicKey) { + checkArrayTypes(msg, sig, publicKey); + if (sig.length !== crypto_sign_BYTES) + throw new Error('bad signature size'); + if (publicKey.length !== crypto_sign_PUBLICKEYBYTES) + throw new Error('bad public key size'); + var sm = new Uint8Array(crypto_sign_BYTES + msg.length); + var m = new Uint8Array(crypto_sign_BYTES + msg.length); + var i; + for (i = 0; i < crypto_sign_BYTES; i++) sm[i] = sig[i]; + for (i = 0; i < msg.length; i++) sm[i+crypto_sign_BYTES] = msg[i]; + return (crypto_sign_open(m, sm, sm.length, publicKey) >= 0); +}; + +nacl.sign.keyPair = function() { + var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); + var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); + crypto_sign_keypair(pk, sk); + return {publicKey: pk, secretKey: sk}; +}; + +nacl.sign.keyPair.fromSecretKey = function(secretKey) { + checkArrayTypes(secretKey); + if (secretKey.length !== crypto_sign_SECRETKEYBYTES) + throw new Error('bad secret key size'); + var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); + for (var i = 0; i < pk.length; i++) pk[i] = secretKey[32+i]; + return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; +}; + +nacl.sign.keyPair.fromSeed = function(seed) { + checkArrayTypes(seed); + if (seed.length !== crypto_sign_SEEDBYTES) + throw new Error('bad seed size'); + var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); + var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); + for (var i = 0; i < 32; i++) sk[i] = seed[i]; + crypto_sign_keypair(pk, sk, true); + return {publicKey: pk, secretKey: sk}; +}; + +nacl.setPRNG = function(fn) { + randombytes = fn; +}; + +(function() { + // Initialize PRNG if environment provides CSPRNG. + // If not, methods calling randombytes will throw. + var crypto = typeof self !== 'undefined' ? (self.crypto || self.msCrypto) : null; + if (crypto && crypto.getRandomValues) { + // Browsers. + var QUOTA = 65536; + nacl.setPRNG(function(x, n) { + var i, v = new Uint8Array(n); + for (i = 0; i < n; i += QUOTA) { + crypto.getRandomValues(v.subarray(i, i + Math.min(n - i, QUOTA))); + } + for (i = 0; i < n; i++) x[i] = v[i]; + cleanup(v); + }); + } else if (typeof require !== 'undefined') { + // Node.js. + crypto = require('crypto'); + if (crypto && crypto.randomBytes) { + nacl.setPRNG(function(x, n) { + var i, v = crypto.randomBytes(n); + for (i = 0; i < n; i++) x[i] = v[i]; + cleanup(v); + }); + } + } +})(); + +})(typeof module !== 'undefined' && module.exports ? module.exports : (self.nacl = self.nacl || {})); + +},{"crypto":"crypto"}],73:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.webToNode = exports.nodeToWeb = undefined; + +var _util = require('./util'); + +var _streams = require('./streams'); + +var _streams2 = _interopRequireDefault(_streams); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const NodeReadableStream = _util.isNode && require('stream').Readable; + +/** + * Web / node stream conversion functions + * From https://github.com/gwicke/node-web-streams + */ + +let nodeToWeb; +let webToNode; + +if (NodeReadableStream) { + + /** + * Convert a Node Readable Stream to a Web ReadableStream + * @param {Readable} nodeStream + * @returns {ReadableStream} + */ + exports.nodeToWeb = nodeToWeb = function nodeToWeb(nodeStream) { + return new ReadableStream({ + start(controller) { + nodeStream.pause(); + nodeStream.on('data', chunk => { + controller.enqueue(chunk); + nodeStream.pause(); + }); + nodeStream.on('end', () => controller.close()); + nodeStream.on('error', e => controller.error(e)); + }, + pull() { + nodeStream.resume(); + }, + cancel(reason) { + nodeStream.pause(); + if (nodeStream.cancel) { + return nodeStream.cancel(reason); + } + } + }); + }; + + class NodeReadable extends NodeReadableStream { + constructor(webStream, options) { + super(options); + this._webStream = webStream; + this._reader = _streams2.default.getReader(webStream); + this._reading = false; + this._doneReadingPromise = Promise.resolve(); + this._cancelling = false; + } + + _read(size) { + if (this._reading || this._cancelling) { + return; + } + this._reading = true; + const doRead = async () => { + try { + while (true) { + var _ref = await this._reader.read(); + + const done = _ref.done, + value = _ref.value; + + if (done) { + this.push(null); + break; + } + if (!this.push(value) || this._cancelling) { + this._reading = false; + break; + } + } + } catch (e) { + this.emit('error', e); + } + }; + this._doneReadingPromise = doRead(); + } + + async cancel(reason) { + this._cancelling = true; + await this._doneReadingPromise; + this._reader.releaseLock(); + return this._webStream.cancel(reason); + } + } + + /** + * Convert a Web ReadableStream to a Node Readable Stream + * @param {ReadableStream} webStream + * @returns {Readable} + */ + exports.webToNode = webToNode = function webToNode(webStream) { + return new NodeReadable(webStream); + }; +} + +exports.nodeToWeb = nodeToWeb; +exports.webToNode = webToNode; + +},{"./streams":75,"./util":76,"stream":"stream"}],74:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.externalBuffer = exports.Reader = undefined; + +var _streams = require('./streams'); + +var _streams2 = _interopRequireDefault(_streams); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const doneReadingSet = new WeakSet(); +const externalBuffer = Symbol('externalBuffer'); + +/** + * A wrapper class over the native ReadableStreamDefaultReader. + * This additionally implements pushing back data on the stream, which + * lets us implement peeking and a host of convenience functions. + * It also lets you read data other than streams, such as a Uint8Array. + * @class + */ +function Reader(input) { + this.stream = input; + if (input[externalBuffer]) { + this[externalBuffer] = input[externalBuffer].slice(); + } + let streamType = _streams2.default.isStream(input); + if (streamType === 'node') { + input = _streams2.default.nodeToWeb(input); + } + if (streamType) { + const reader = input.getReader(); + this._read = reader.read.bind(reader); + this._releaseLock = () => { + reader.closed.catch(function () {}); + reader.releaseLock(); + }; + return; + } + let doneReading = false; + this._read = async () => { + if (doneReading || doneReadingSet.has(input)) { + return { value: undefined, done: true }; + } + doneReading = true; + return { value: input, done: false }; + }; + this._releaseLock = () => { + if (doneReading) { + try { + doneReadingSet.add(input); + } catch (e) {} + } + }; +} + +/** + * Read a chunk of data. + * @returns {Promise} Either { done: false, value: Uint8Array | String } or { done: true, value: undefined } + * @async + */ +Reader.prototype.read = async function () { + if (this[externalBuffer] && this[externalBuffer].length) { + const value = this[externalBuffer].shift(); + return { done: false, value }; + } + return this._read(); +}; + +/** + * Allow others to read the stream. + */ +Reader.prototype.releaseLock = function () { + if (this[externalBuffer]) { + this.stream[externalBuffer] = this[externalBuffer]; + } + this._releaseLock(); +}; + +/** + * Read up to and including the first \n character. + * @returns {Promise} + * @async + */ +Reader.prototype.readLine = async function () { + let buffer = []; + let returnVal; + while (!returnVal) { + var _ref = await this.read(); + + let done = _ref.done, + value = _ref.value; + + value += ''; + if (done) { + if (buffer.length) return _streams2.default.concat(buffer); + return; + } + const lineEndIndex = value.indexOf('\n') + 1; + if (lineEndIndex) { + returnVal = _streams2.default.concat(buffer.concat(value.substr(0, lineEndIndex))); + buffer = []; + } + if (lineEndIndex !== value.length) { + buffer.push(value.substr(lineEndIndex)); + } + } + this.unshift(...buffer); + return returnVal; +}; + +/** + * Read a single byte/character. + * @returns {Promise} + * @async + */ +Reader.prototype.readByte = async function () { + var _ref2 = await this.read(); + + const done = _ref2.done, + value = _ref2.value; + + if (done) return; + const byte = value[0]; + this.unshift(_streams2.default.slice(value, 1)); + return byte; +}; + +/** + * Read a specific amount of bytes/characters, unless the stream ends before that amount. + * @returns {Promise} + * @async + */ +Reader.prototype.readBytes = async function (length) { + const buffer = []; + let bufferLength = 0; + while (true) { + var _ref3 = await this.read(); + + const done = _ref3.done, + value = _ref3.value; + + if (done) { + if (buffer.length) return _streams2.default.concat(buffer); + return; + } + buffer.push(value); + bufferLength += value.length; + if (bufferLength >= length) { + const bufferConcat = _streams2.default.concat(buffer); + this.unshift(_streams2.default.slice(bufferConcat, length)); + return _streams2.default.slice(bufferConcat, 0, length); + } + } +}; + +/** + * Peek (look ahead) a specific amount of bytes/characters, unless the stream ends before that amount. + * @returns {Promise} + * @async + */ +Reader.prototype.peekBytes = async function (length) { + const bytes = await this.readBytes(length); + this.unshift(bytes); + return bytes; +}; + +/** + * Push data to the front of the stream. + * @param {...(Uint8Array|String|Undefined)} values + */ +Reader.prototype.unshift = function (...values) { + if (!this[externalBuffer]) { + this[externalBuffer] = []; + } + this[externalBuffer].unshift(...values.filter(value => value && value.length)); +}; + +/** + * Read the stream to the end and return its contents, concatenated by the join function (defaults to streams.concat). + * @param {Function} join + * @returns {Promise} the return value of join() + * @async + */ +Reader.prototype.readToEnd = async function (join = _streams2.default.concat) { + const result = []; + while (true) { + var _ref4 = await this.read(); + + const done = _ref4.done, + value = _ref4.value; + + if (done) break; + result.push(value); + } + return join(result); +}; + +exports.Reader = Reader; +exports.externalBuffer = externalBuffer; + +},{"./streams":75}],75:[function(require,module,exports){ +(function (process){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _util = require('./util'); + +var _nodeConversions = require('./node-conversions'); + +var _reader = require('./reader'); + +const NodeBuffer = _util.isNode && require('buffer').Buffer; + +/** + * Convert data to Stream + * @param {ReadableStream|Uint8array|String} input data to convert + * @returns {ReadableStream} Converted data + */ +function toStream(input) { + let streamType = (0, _util.isStream)(input); + if (streamType === 'node') { + return (0, _nodeConversions.nodeToWeb)(input); + } else if (streamType) { + return input; + } + return new ReadableStream({ + start(controller) { + controller.enqueue(input); + controller.close(); + } + }); +} + +/** + * Concat a list of Uint8Arrays, Strings or Streams + * The caller should not mix Uint8Arrays with Strings, but may mix Streams with non-Streams. + * @param {Array} Array of Uint8Arrays/Strings/Streams to concatenate + * @returns {Uint8array|String|ReadableStream} Concatenated array + */ +function concat(list) { + if (list.some(_util.isStream)) { + return concatStream(list); + } + if (typeof list[0] === 'string') { + return list.join(''); + } + if (NodeBuffer && NodeBuffer.isBuffer(list[0])) { + return NodeBuffer.concat(list); + } + return (0, _util.concatUint8Array)(list); +} + +/** + * Concat a list of Streams + * @param {Array} list Array of Uint8Arrays/Strings/Streams to concatenate + * @returns {ReadableStream} Concatenated list + */ +function concatStream(list) { + list = list.map(toStream); + const transform = transformWithCancel(async function (reason) { + await Promise.all(transforms.map(stream => cancel(stream, reason))); + }); + let prev = Promise.resolve(); + const transforms = list.map((stream, i) => transformPair(stream, (readable, writable) => { + prev = prev.then(() => pipe(readable, transform.writable, { + preventClose: i !== list.length - 1 + })); + return prev; + })); + return transform.readable; +} + +/** + * Get a Reader + * @param {ReadableStream|Uint8array|String} input + * @returns {Reader} + */ +function getReader(input) { + return new _reader.Reader(input); +} + +/** + * Get a Writer + * @param {WritableStream} input + * @returns {WritableStreamDefaultWriter} + */ +function getWriter(input) { + const writer = input.getWriter(); + const releaseLock = writer.releaseLock; + writer.releaseLock = () => { + writer.closed.catch(function () {}); + releaseLock.call(writer); + }; + return writer; +} + +/** + * Pipe a readable stream to a writable stream. Don't throw on input stream errors, but forward them to the output stream. + * @param {ReadableStream|Uint8array|String} input + * @param {WritableStream} target + * @param {Object} (optional) options + * @returns {Promise} Promise indicating when piping has finished (input stream closed or errored) + * @async + */ +async function pipe(input, target, options) { + input = toStream(input); + try { + if (input[_reader.externalBuffer]) { + const writer = getWriter(target); + for (let i = 0; i < input[_reader.externalBuffer].length; i++) { + await writer.ready; + await writer.write(input[_reader.externalBuffer][i]); + } + writer.releaseLock(); + } + return await input.pipeTo(target, options); + } catch (e) {} +} + +/** + * Pipe a readable stream through a transform stream. + * @param {ReadableStream|Uint8array|String} input + * @param {Object} (optional) options + * @returns {ReadableStream} transformed stream + */ +function transformRaw(input, options) { + const transformStream = new TransformStream(options); + pipe(input, transformStream.writable); + return transformStream.readable; +} + +/** + * Create a cancelable TransformStream. + * @param {Function} cancel + * @returns {TransformStream} + */ +function transformWithCancel(cancel) { + let pulled = false; + let backpressureChangePromiseResolve; + let outputController; + return { + readable: new ReadableStream({ + start(controller) { + outputController = controller; + }, + pull() { + if (backpressureChangePromiseResolve) { + backpressureChangePromiseResolve(); + } else { + pulled = true; + } + }, + cancel + }, { highWaterMark: 0 }), + writable: new WritableStream({ + write: async function write(chunk) { + outputController.enqueue(chunk); + if (!pulled) { + await new Promise(resolve => { + backpressureChangePromiseResolve = resolve; + }); + backpressureChangePromiseResolve = null; + } else { + pulled = false; + } + }, + close: outputController.close.bind(outputController), + abort: outputController.error.bind(outputController) + }) + }; +} + +/** + * Transform a stream using helper functions which are called on each chunk, and on stream close, respectively. + * @param {ReadableStream|Uint8array|String} input + * @param {Function} process + * @param {Function} finish + * @returns {ReadableStream|Uint8array|String} + */ +function transform(input, process = () => undefined, finish = () => undefined) { + if ((0, _util.isStream)(input)) { + return transformRaw(input, { + async transform(value, controller) { + try { + const result = await process(value); + if (result !== undefined) controller.enqueue(result); + } catch (e) { + controller.error(e); + } + }, + async flush(controller) { + try { + const result = await finish(); + if (result !== undefined) controller.enqueue(result); + } catch (e) { + controller.error(e); + } + } + }); + } + const result1 = process(input); + const result2 = finish(); + if (result1 !== undefined && result2 !== undefined) return concat([result1, result2]); + return result1 !== undefined ? result1 : result2; +} + +/** + * Transform a stream using a helper function which is passed a readable and a writable stream. + * This function also maintains the possibility to cancel the input stream, + * and does so on cancelation of the output stream, despite cancelation + * normally being impossible when the input stream is being read from. + * @param {ReadableStream|Uint8array|String} input + * @param {Function} fn + * @returns {ReadableStream} + */ +function transformPair(input, fn) { + let incomingTransformController; + const incoming = new TransformStream({ + start(controller) { + incomingTransformController = controller; + } + }); + + const pipeDonePromise = pipe(input, incoming.writable); + + const outgoing = transformWithCancel(async function () { + incomingTransformController.error(new Error('Readable side was canceled.')); + await pipeDonePromise; + await new Promise(setTimeout); + }); + fn(incoming.readable, outgoing.writable); + return outgoing.readable; +} + +/** + * Parse a stream using a helper function which is passed a Reader. + * The reader additionally has a remainder() method which returns a + * stream pointing to the remainder of input, and is linked to input + * for cancelation. + * @param {ReadableStream|Uint8array|String} input + * @param {Function} fn + * @returns {Any} the return value of fn() + */ +function parse(input, fn) { + let returnValue; + const transformed = transformPair(input, (readable, writable) => { + const reader = getReader(readable); + reader.remainder = () => { + reader.releaseLock(); + pipe(readable, writable); + return transformed; + }; + returnValue = fn(reader); + }); + return returnValue; +} + +/** + * Tee a Stream for reading it twice. The input stream can no longer be read after tee()ing. + * Reading either of the two returned streams will pull from the input stream. + * The input stream will only be canceled if both of the returned streams are canceled. + * @param {ReadableStream|Uint8array|String} input + * @returns {Array} array containing two copies of input + */ +function tee(input) { + if ((0, _util.isStream)(input)) { + const teed = toStream(input).tee(); + teed[0][_reader.externalBuffer] = teed[1][_reader.externalBuffer] = input[_reader.externalBuffer]; + return teed; + } + return [slice(input), slice(input)]; +} + +/** + * Clone a Stream for reading it twice. The input stream can still be read after clone()ing. + * Reading from the clone will pull from the input stream. + * The input stream will only be canceled if both the clone and the input stream are canceled. + * @param {ReadableStream|Uint8array|String} input + * @returns {ReadableStream|Uint8array|String} cloned input + */ +function clone(input) { + if ((0, _util.isStream)(input)) { + const teed = tee(input); + overwrite(input, teed[0]); + return teed[1]; + } + return slice(input); +} + +/** + * Clone a Stream for reading it twice. Data will arrive at the same rate as the input stream is being read. + * Reading from the clone will NOT pull from the input stream. Data only arrives when reading the input stream. + * The input stream will NOT be canceled if the clone is canceled, only if the input stream are canceled. + * If the input stream is canceled, the clone will be errored. + * @param {ReadableStream|Uint8array|String} input + * @returns {ReadableStream|Uint8array|String} cloned input + */ +function passiveClone(input) { + if ((0, _util.isStream)(input)) { + return new ReadableStream({ + start(controller) { + const transformed = transformPair(input, async (readable, writable) => { + const reader = getReader(readable); + const writer = getWriter(writable); + try { + while (true) { + await writer.ready; + + var _ref = await reader.read(); + + const done = _ref.done, + value = _ref.value; + + if (done) { + try { + controller.close(); + } catch (e) {} + await writer.close(); + return; + } + try { + controller.enqueue(value); + } catch (e) {} + await writer.write(value); + } + } catch (e) { + controller.error(e); + await writer.abort(e); + } + }); + overwrite(input, transformed); + } + }); + } + return slice(input); +} + +/** + * Modify a stream object to point to a different stream object. + * This is used internally by clone() and passiveClone() to provide an abstraction over tee(). + * @param {ReadableStream} input + * @param {ReadableStream} clone + */ +function overwrite(input, clone) { + // Overwrite input.getReader, input.locked, etc to point to clone + Object.entries(Object.getOwnPropertyDescriptors(ReadableStream.prototype)).forEach(([name, descriptor]) => { + if (name === 'constructor') { + return; + } + if (descriptor.value) { + descriptor.value = descriptor.value.bind(clone); + } else { + descriptor.get = descriptor.get.bind(clone); + } + Object.defineProperty(input, name, descriptor); + }); +} + +/** + * Return a stream pointing to a part of the input stream. + * @param {ReadableStream|Uint8array|String} input + * @returns {ReadableStream|Uint8array|String} clone + */ +function slice(input, begin = 0, end = Infinity) { + if ((0, _util.isStream)(input)) { + if (begin >= 0 && end >= 0) { + let bytesRead = 0; + return transformRaw(input, { + transform(value, controller) { + if (bytesRead < end) { + if (bytesRead + value.length >= begin) { + controller.enqueue(slice(value, Math.max(begin - bytesRead, 0), end - bytesRead)); + } + bytesRead += value.length; + } else { + controller.terminate(); + } + } + }); + } + if (begin < 0 && (end < 0 || end === Infinity)) { + let lastBytes = []; + return transform(input, value => { + if (value.length >= -begin) lastBytes = [value];else lastBytes.push(value); + }, () => slice(concat(lastBytes), begin, end)); + } + if (begin === 0 && end < 0) { + let lastBytes; + return transform(input, value => { + const returnValue = lastBytes ? concat([lastBytes, value]) : value; + if (returnValue.length >= -end) { + lastBytes = slice(returnValue, end); + return slice(returnValue, begin, end); + } else { + lastBytes = returnValue; + } + }); + } + console.warn(`stream.slice(input, ${begin}, ${end}) not implemented efficiently.`); + return fromAsync(async () => slice((await readToEnd(input)), begin, end)); + } + if (input[_reader.externalBuffer]) { + input = concat(input[_reader.externalBuffer].concat([input])); + } + if ((0, _util.isUint8Array)(input) && !(NodeBuffer && NodeBuffer.isBuffer(input))) { + if (end === Infinity) end = input.length; + return input.subarray(begin, end); + } + return input.slice(begin, end); +} + +/** + * Read a stream to the end and return its contents, concatenated by the concat function (defaults to concat). + * @param {ReadableStream|Uint8array|String} input + * @param {Function} concat + * @returns {Promise} the return value of concat() + * @async + */ +async function readToEnd(input, concat) { + if ((0, _util.isStream)(input)) { + return getReader(input).readToEnd(concat); + } + return input; +} + +/** + * Cancel a stream. + * @param {ReadableStream|Uint8array|String} input + * @param {Any} reason + * @returns {Promise} indicates when the stream has been canceled + * @async + */ +async function cancel(input, reason) { + if ((0, _util.isStream)(input) && input.cancel) { + return input.cancel(reason); + } +} + +/** + * Convert an async function to a Stream. When the function returns, its return value is enqueued to the stream. + * @param {Function} fn + * @returns {ReadableStream} + */ +function fromAsync(fn) { + return new ReadableStream({ + pull: async controller => { + try { + controller.enqueue((await fn())); + controller.close(); + } catch (e) { + controller.error(e); + } + } + }); +} + +exports.default = { isStream: _util.isStream, isUint8Array: _util.isUint8Array, toStream, concatUint8Array: _util.concatUint8Array, concatStream, concat, getReader, getWriter, pipe, transformRaw, transform, transformPair, parse, clone, passiveClone, slice, readToEnd, cancel, fromAsync, nodeToWeb: _nodeConversions.nodeToWeb, webToNode: _nodeConversions.webToNode }; + +}).call(this,require('_process')) +},{"./node-conversions":73,"./reader":74,"./util":76,"_process":66,"buffer":"buffer"}],76:[function(require,module,exports){ +(function (global){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +const isNode = typeof global.process === 'object' && typeof global.process.versions === 'object'; + +const NodeReadableStream = isNode && require('stream').Readable; + +/** + * Check whether data is a Stream, and if so of which type + * @param {Any} input data to check + * @returns {'web'|'node'|false} + */ +function isStream(input) { + if (ReadableStream.prototype.isPrototypeOf(input)) { + return 'web'; + } + if (NodeReadableStream && NodeReadableStream.prototype.isPrototypeOf(input)) { + return 'node'; + } + return false; +} + +/** + * Check whether data is a Uint8Array + * @param {Any} input data to check + * @returns {Boolean} + */ +function isUint8Array(input) { + return Uint8Array.prototype.isPrototypeOf(input); +} + +/** + * Concat Uint8Arrays + * @param {Array} Array of Uint8Arrays to concatenate + * @returns {Uint8array} Concatenated array + */ +function concatUint8Array(arrays) { + if (arrays.length === 1) return arrays[0]; + + let totalLength = 0; + for (let i = 0; i < arrays.length; i++) { + if (!isUint8Array(arrays[i])) { + throw new Error('concatUint8Array: Data must be in the form of a Uint8Array'); + } + + totalLength += arrays[i].length; + } + + const result = new Uint8Array(totalLength); + let pos = 0; + arrays.forEach(function (element) { + result.set(element, pos); + pos += element.length; + }); + + return result; +} + +exports.isNode = isNode; +exports.isStream = isStream; +exports.isUint8Array = isUint8Array; +exports.concatUint8Array = concatUint8Array; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"stream":"stream"}],77:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.CleartextMessage = CleartextMessage; +exports.readArmored = readArmored; +exports.fromText = fromText; + +var _armor = require('./encoding/armor'); + +var _armor2 = _interopRequireDefault(_armor); + +var _enums = require('./enums'); + +var _enums2 = _interopRequireDefault(_enums); + +var _util = require('./util'); + +var _util2 = _interopRequireDefault(_util); + +var _packet = require('./packet'); + +var _packet2 = _interopRequireDefault(_packet); + +var _signature = require('./signature'); + +var _message = require('./message'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * @class + * @classdesc Class that represents an OpenPGP cleartext signed message. + * See {@link https://tools.ietf.org/html/rfc4880#section-7} + * @param {String} text The cleartext of the signed message + * @param {module:signature.Signature} signature The detached signature or an empty signature for unsigned messages + */ +// GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @requires encoding/armor + * @requires enums + * @requires util + * @requires packet + * @requires signature + * @module cleartext + */ + +function CleartextMessage(text, signature) { + if (!(this instanceof CleartextMessage)) { + return new CleartextMessage(text, signature); + } + // normalize EOL to canonical form + this.text = _util2.default.canonicalizeEOL(_util2.default.removeTrailingSpaces(text)); + if (signature && !(signature instanceof _signature.Signature)) { + throw new Error('Invalid signature input'); + } + this.signature = signature || new _signature.Signature(new _packet2.default.List()); +} + +/** + * Returns the key IDs of the keys that signed the cleartext message + * @returns {Array} array of keyid objects + */ +CleartextMessage.prototype.getSigningKeyIds = function () { + const keyIds = []; + const signatureList = this.signature.packets; + signatureList.forEach(function (packet) { + keyIds.push(packet.issuerKeyId); + }); + return keyIds; +}; + +/** + * Sign the cleartext message + * @param {Array} privateKeys private keys with decrypted secret key data for signing + * @param {Signature} signature (optional) any existing detached signature + * @param {Date} date (optional) The creation time of the signature that should be created + * @param {Array} userIds (optional) user IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] + * @returns {Promise} new cleartext message with signed content + * @async + */ +CleartextMessage.prototype.sign = async function (privateKeys, signature = null, date = new Date(), userIds = []) { + return new CleartextMessage(this.text, (await this.signDetached(privateKeys, signature, date, userIds))); +}; + +/** + * Sign the cleartext message + * @param {Array} privateKeys private keys with decrypted secret key data for signing + * @param {Signature} signature (optional) any existing detached signature + * @param {Date} date (optional) The creation time of the signature that should be created + * @param {Array} userIds (optional) user IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] + * @returns {Promise} new detached signature of message content + * @async + */ +CleartextMessage.prototype.signDetached = async function (privateKeys, signature = null, date = new Date(), userIds = []) { + const literalDataPacket = new _packet2.default.Literal(); + literalDataPacket.setText(this.text); + + return new _signature.Signature((await (0, _message.createSignaturePackets)(literalDataPacket, privateKeys, signature, date, userIds, true))); +}; + +/** + * Verify signatures of cleartext signed message + * @param {Array} keys array of keys to verify signatures + * @param {Date} date (optional) Verify the signature against the given date, i.e. check signature creation time < date < expiration time + * @returns {Promise>} list of signer's keyid and validity of signature + * @async + */ +CleartextMessage.prototype.verify = function (keys, date = new Date()) { + return this.verifyDetached(this.signature, keys, date); +}; + +/** + * Verify signatures of cleartext signed message + * @param {Array} keys array of keys to verify signatures + * @param {Date} date (optional) Verify the signature against the given date, i.e. check signature creation time < date < expiration time + * @returns {Promise>} list of signer's keyid and validity of signature + * @async + */ +CleartextMessage.prototype.verifyDetached = function (signature, keys, date = new Date()) { + const signatureList = signature.packets; + const literalDataPacket = new _packet2.default.Literal(); + // we assume that cleartext signature is generated based on UTF8 cleartext + literalDataPacket.setText(this.text); + return (0, _message.createVerificationObjects)(signatureList, [literalDataPacket], keys, date, true); +}; + +/** + * Get cleartext + * @returns {String} cleartext of message + */ +CleartextMessage.prototype.getText = function () { + // normalize end of line to \n + return _util2.default.nativeEOL(this.text); +}; + +/** + * Returns ASCII armored text of cleartext signed message + * @returns {String | ReadableStream} ASCII armor + */ +CleartextMessage.prototype.armor = function () { + let hashes = this.signature.packets.map(function (packet) { + return _enums2.default.read(_enums2.default.hash, packet.hashAlgorithm).toUpperCase(); + }); + hashes = hashes.filter(function (item, i, ar) { + return ar.indexOf(item) === i; + }); + const body = { + hash: hashes.join(), + text: this.text, + data: this.signature.packets.write() + }; + return _armor2.default.encode(_enums2.default.armor.signed, body); +}; + +/** + * reads an OpenPGP cleartext signed message and returns a CleartextMessage object + * @param {String | ReadableStream} armoredText text to be parsed + * @returns {module:cleartext.CleartextMessage} new cleartext message object + * @async + * @static + */ +async function readArmored(armoredText) { + const input = await _armor2.default.decode(armoredText); + if (input.type !== _enums2.default.armor.signed) { + throw new Error('No cleartext signed message.'); + } + const packetlist = new _packet2.default.List(); + await packetlist.read(input.data); + verifyHeaders(input.headers, packetlist); + const signature = new _signature.Signature(packetlist); + return new CleartextMessage(input.text, signature); +} + +/** + * Compare hash algorithm specified in the armor header with signatures + * @param {Array} headers Armor headers + * @param {module:packet.List} packetlist The packetlist with signature packets + * @private + */ +function verifyHeaders(headers, packetlist) { + const checkHashAlgos = function checkHashAlgos(hashAlgos) { + const check = packet => algo => packet.hashAlgorithm === algo; + + for (let i = 0; i < packetlist.length; i++) { + if (packetlist[i].tag === _enums2.default.packet.signature && !hashAlgos.some(check(packetlist[i]))) { + return false; + } + } + return true; + }; + + let oneHeader = null; + let hashAlgos = []; + headers.forEach(function (header) { + oneHeader = header.match(/Hash: (.+)/); // get header value + if (oneHeader) { + oneHeader = oneHeader[1].replace(/\s/g, ''); // remove whitespace + oneHeader = oneHeader.split(','); + oneHeader = oneHeader.map(function (hash) { + hash = hash.toLowerCase(); + try { + return _enums2.default.write(_enums2.default.hash, hash); + } catch (e) { + throw new Error('Unknown hash algorithm in armor header: ' + hash); + } + }); + hashAlgos = hashAlgos.concat(oneHeader); + } else { + throw new Error('Only "Hash" header allowed in cleartext signed message'); + } + }); + + if (!hashAlgos.length && !checkHashAlgos([_enums2.default.hash.md5])) { + throw new Error('If no "Hash" header in cleartext signed message, then only MD5 signatures allowed'); + } else if (hashAlgos.length && !checkHashAlgos(hashAlgos)) { + throw new Error('Hash algorithm mismatch in armor header and signature'); + } +} + +/** + * Creates a new CleartextMessage object from text + * @param {String} text + * @static + */ +function fromText(text) { + return new CleartextMessage(text); +} + +},{"./encoding/armor":111,"./enums":113,"./message":120,"./packet":125,"./signature":145,"./util":152}],78:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _enums = require("../enums"); + +var _enums2 = _interopRequireDefault(_enums); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = { + /** + * @memberof module:config + * @property {Integer} prefer_hash_algorithm Default hash algorithm {@link module:enums.hash} + */ + prefer_hash_algorithm: _enums2.default.hash.sha256, + /** + * @memberof module:config + * @property {Integer} encryption_cipher Default encryption cipher {@link module:enums.symmetric} + */ + encryption_cipher: _enums2.default.symmetric.aes256, + /** + * @memberof module:config + * @property {Integer} compression Default compression algorithm {@link module:enums.compression} + */ + compression: _enums2.default.compression.uncompressed, + /** + * @memberof module:config + * @property {Integer} deflate_level Default zip/zlib compression level, between 1 and 9 + */ + deflate_level: 6, + + /** + * Use Authenticated Encryption with Additional Data (AEAD) protection for symmetric encryption. + * **NOT INTEROPERABLE WITH OTHER OPENPGP IMPLEMENTATIONS** + * **FUTURE OPENPGP.JS VERSIONS MAY BREAK COMPATIBILITY WHEN USING THIS OPTION** + * @see {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-07|RFC4880bis-07} + * @memberof module:config + * @property {Boolean} aead_protect + */ + aead_protect: false, + /** + * Default Authenticated Encryption with Additional Data (AEAD) encryption mode + * Only has an effect when aead_protect is set to true. + * @memberof module:config + * @property {Integer} aead_mode Default AEAD mode {@link module:enums.aead} + */ + aead_mode: _enums2.default.aead.eax, + /** + * Chunk Size Byte for Authenticated Encryption with Additional Data (AEAD) mode + * Only has an effect when aead_protect is set to true. + * Must be an integer value from 0 to 56. + * @memberof module:config + * @property {Integer} aead_chunk_size_byte + */ + aead_chunk_size_byte: 12, + /** + * Use V5 keys. + * **NOT INTEROPERABLE WITH OTHER OPENPGP IMPLEMENTATIONS** + * **FUTURE OPENPGP.JS VERSIONS MAY BREAK COMPATIBILITY WHEN USING THIS OPTION** + * @memberof module:config + * @property {Boolean} v5_keys + */ + v5_keys: false, + /** + * {@link https://tools.ietf.org/html/rfc4880#section-3.7.1.3|RFC4880 3.7.1.3}: + * Iteration Count Byte for S2K (String to Key) + * @memberof module:config + * @property {Integer} s2k_iteration_count_byte + */ + s2k_iteration_count_byte: 224, + /** Use integrity protection for symmetric encryption + * @memberof module:config + * @property {Boolean} integrity_protect + */ + integrity_protect: true, + /** + * @memberof module:config + * @property {Boolean} ignore_mdc_error Fail on decrypt if message is not integrity protected + */ + ignore_mdc_error: false, + /** + * @memberof module:config + * @property {Boolean} allow_unauthenticated_stream Stream unauthenticated data before integrity has been checked + */ + allow_unauthenticated_stream: false, + /** + * @memberof module:config + * @property {Boolean} checksum_required Do not throw error when armor is missing a checksum + */ + checksum_required: false, + /** + * @memberof module:config + * @property {Boolean} rsa_blinding + */ + rsa_blinding: true, + /** + * Work-around for rare GPG decryption bug when encrypting with multiple passwords. + * **Slower and slightly less secure** + * @memberof module:config + * @property {Boolean} password_collision_check + */ + password_collision_check: false, + /** + * @memberof module:config + * @property {Boolean} revocations_expire If true, expired revocation signatures are ignored + */ + revocations_expire: false, + + /** + * @memberof module:config + * @property {Boolean} use_native Use native Node.js crypto/zlib and WebCrypto APIs when available + */ + use_native: true, + /** + * @memberof module:config + * @property {Integer} min_bytes_for_web_crypto The minimum amount of bytes for which to use native WebCrypto APIs when available + */ + min_bytes_for_web_crypto: 1000, + /** + * @memberof module:config + * @property {Boolean} Use transferable objects between the Web Worker and main thread + */ + zero_copy: false, + /** + * @memberof module:config + * @property {Boolean} debug If enabled, debug messages will be printed + */ + debug: false, + /** + * @memberof module:config + * @property {Boolean} tolerant Ignore unsupported/unrecognizable packets instead of throwing an error + */ + tolerant: true, + + /** + * @memberof module:config + * @property {Boolean} show_version Whether to include {@link module:config/config.versionstring} in armored messages + */ + show_version: true, + /** + * @memberof module:config + * @property {Boolean} show_comment Whether to include {@link module:config/config.commentstring} in armored messages + */ + show_comment: true, + /** + * @memberof module:config + * @property {String} versionstring A version string to be included in armored messages + */ + versionstring: "OpenPGP.js v4.6.0", + /** + * @memberof module:config + * @property {String} commentstring A comment string to be included in armored messages + */ + commentstring: "https://openpgpjs.org", + + /** + * @memberof module:config + * @property {String} keyserver + */ + keyserver: "https://keyserver.ubuntu.com", + /** + * @memberof module:config + * @property {String} node_store + */ + node_store: "./openpgp.store", + /** + * Max userid string length (used for parsing) + * @memberof module:config + * @property {Integer} max_userid_length + */ + max_userid_length: 1024 * 5, + /** + * Contains notatations that are considered "known". Known notations do not trigger + * validation error when the notation is marked as critical. + * @memberof module:config + * @property {Array} known_notations + */ + known_notations: ["preferred-email-encoding@pgp.com", "pka-address@gnupg.org"] +}; // GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * Global configuration values. + * @requires enums + */ + +},{"../enums":113}],79:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _config = require('./config.js'); + +Object.defineProperty(exports, 'default', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_config).default; + } +}); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +},{"./config.js":78}],80:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _cipher = require('./cipher'); + +var _cipher2 = _interopRequireDefault(_cipher); + +var _util = require('../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// OpenPGP.js - An OpenPGP implementation in javascript +// Copyright (C) 2015-2016 Decentral +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @fileoverview Implementation of RFC 3394 AES Key Wrap & Key Unwrap funcions + * @see module:crypto/public_key/elliptic/ecdh + * @requires crypto/cipher + * @requires util + * @module crypto/aes_kw + */ + +function wrap(key, data) { + const aes = new _cipher2.default["aes" + key.length * 8](key); + const IV = new Uint32Array([0xA6A6A6A6, 0xA6A6A6A6]); + const P = unpack(data); + let A = IV; + const R = P; + const n = P.length / 2; + const t = new Uint32Array([0, 0]); + let B = new Uint32Array(4); + for (let j = 0; j <= 5; ++j) { + for (let i = 0; i < n; ++i) { + t[1] = n * j + (1 + i); + // B = A + B[0] = A[0]; + B[1] = A[1]; + // B = A || R[i] + B[2] = R[2 * i]; + B[3] = R[2 * i + 1]; + // B = AES(K, B) + B = unpack(aes.encrypt(pack(B))); + // A = MSB(64, B) ^ t + A = B.subarray(0, 2); + A[0] ^= t[0]; + A[1] ^= t[1]; + // R[i] = LSB(64, B) + R[2 * i] = B[2]; + R[2 * i + 1] = B[3]; + } + } + return pack(A, R); +} + +function unwrap(key, data) { + const aes = new _cipher2.default["aes" + key.length * 8](key); + const IV = new Uint32Array([0xA6A6A6A6, 0xA6A6A6A6]); + const C = unpack(data); + let A = C.subarray(0, 2); + const R = C.subarray(2); + const n = C.length / 2 - 1; + const t = new Uint32Array([0, 0]); + let B = new Uint32Array(4); + for (let j = 5; j >= 0; --j) { + for (let i = n - 1; i >= 0; --i) { + t[1] = n * j + (i + 1); + // B = A ^ t + B[0] = A[0] ^ t[0]; + B[1] = A[1] ^ t[1]; + // B = (A ^ t) || R[i] + B[2] = R[2 * i]; + B[3] = R[2 * i + 1]; + // B = AES-1(B) + B = unpack(aes.decrypt(pack(B))); + // A = MSB(64, B) + A = B.subarray(0, 2); + // R[i] = LSB(64, B) + R[2 * i] = B[2]; + R[2 * i + 1] = B[3]; + } + } + if (A[0] === IV[0] && A[1] === IV[1]) { + return pack(R); + } + throw new Error("Key Data Integrity failed"); +} + +function createArrayBuffer(data) { + if (_util2.default.isString(data)) { + const length = data.length; + + const buffer = new ArrayBuffer(length); + const view = new Uint8Array(buffer); + for (let j = 0; j < length; ++j) { + view[j] = data.charCodeAt(j); + } + return buffer; + } + return new Uint8Array(data).buffer; +} + +function unpack(data) { + const length = data.length; + + const buffer = createArrayBuffer(data); + const view = new DataView(buffer); + const arr = new Uint32Array(length / 4); + for (let i = 0; i < length / 4; ++i) { + arr[i] = view.getUint32(4 * i); + } + return arr; +} + +function pack() { + let length = 0; + for (let k = 0; k < arguments.length; ++k) { + length += 4 * arguments[k].length; + } + const buffer = new ArrayBuffer(length); + const view = new DataView(buffer); + let offset = 0; + for (let i = 0; i < arguments.length; ++i) { + for (let j = 0; j < arguments[i].length; ++j) { + view.setUint32(offset + 4 * j, arguments[i][j]); + } + offset += 4 * arguments[i].length; + } + return new Uint8Array(buffer); +} + +exports.default = { + /** + * AES key wrap + * @function + * @param {String} key + * @param {String} data + * @returns {Uint8Array} + */ + wrap, + /** + * AES key unwrap + * @function + * @param {String} key + * @param {String} data + * @returns {Uint8Array} + * @throws {Error} + */ + unwrap +}; + +},{"../util":152,"./cipher":86}],81:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _cfb = require('asmcrypto.js/dist_es5/aes/cfb'); + +var _webStreamTools = require('web-stream-tools'); + +var _webStreamTools2 = _interopRequireDefault(_webStreamTools); + +var _cipher = require('./cipher'); + +var _cipher2 = _interopRequireDefault(_cipher); + +var _config = require('../config'); + +var _config2 = _interopRequireDefault(_config); + +var _util = require('../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const webCrypto = _util2.default.getWebCrypto(); // Modified by ProtonTech AG + +// Modified by Recurity Labs GmbH + +// modified version of https://www.hanewin.net/encrypt/PGdecode.js: + +/* OpenPGP encryption using RSA/AES + * Copyright 2005-2006 Herbert Hanewinkel, www.haneWIN.de + * version 2.0, check www.haneWIN.de for the latest version + + * This software is provided as-is, without express or implied warranty. + * Permission to use, copy, modify, distribute or sell this software, with or + * without fee, for any purpose and by any individual or organization, is hereby + * granted, provided that the above copyright notice and this paragraph appear + * in all copies. Distribution as a part of an application or binary must + * include the above copyright notice in the documentation and/or other + * materials provided with the application or distribution. + */ + +/** + * @requires web-stream-tools + * @requires crypto/cipher + * @requires util + * @module crypto/cfb + */ + +const nodeCrypto = _util2.default.getNodeCrypto(); +const Buffer = _util2.default.getNodeBuffer(); + +exports.default = { + encrypt: function encrypt(algo, key, plaintext, iv) { + if (algo.substr(0, 3) === 'aes') { + return aesEncrypt(algo, key, plaintext, iv); + } + + const cipherfn = new _cipher2.default[algo](key); + const block_size = cipherfn.blockSize; + + let blocki = new Uint8Array(block_size); + const blockc = iv; + let pos = 0; + const ciphertext = new Uint8Array(plaintext.length); + let i; + let j = 0; + + while (plaintext.length > block_size * pos) { + const encblock = cipherfn.encrypt(blockc); + blocki = plaintext.subarray(pos * block_size, pos * block_size + block_size); + for (i = 0; i < blocki.length; i++) { + blockc[i] = blocki[i] ^ encblock[i]; + ciphertext[j++] = blockc[i]; + } + pos++; + } + return ciphertext; + }, + + decrypt: async function decrypt(algo, key, ciphertext, iv) { + if (algo.substr(0, 3) === 'aes') { + return aesDecrypt(algo, key, ciphertext, iv); + } + + ciphertext = await _webStreamTools2.default.readToEnd(ciphertext); + + const cipherfn = new _cipher2.default[algo](key); + const block_size = cipherfn.blockSize; + + let blockp = iv; + let pos = 0; + const plaintext = new Uint8Array(ciphertext.length); + const offset = 0; + let i; + let j = 0; + + while (ciphertext.length > block_size * pos) { + const decblock = cipherfn.encrypt(blockp); + blockp = ciphertext.subarray(pos * block_size + offset, pos * block_size + block_size + offset); + for (i = 0; i < blockp.length; i++) { + plaintext[j++] = blockp[i] ^ decblock[i]; + } + pos++; + } + + return plaintext; + } +}; + + +function aesEncrypt(algo, key, pt, iv) { + if (_util2.default.getWebCrypto() && key.length !== 24 && // Chrome doesn't support 192 bit keys, see https://www.chromium.org/blink/webcrypto#TOC-AES-support + !_util2.default.isStream(pt) && pt.length >= 3000 * _config2.default.min_bytes_for_web_crypto // Default to a 3MB minimum. Chrome is pretty slow for small messages, see: https://bugs.chromium.org/p/chromium/issues/detail?id=701188#c2 + ) { + // Web Crypto + return webEncrypt(algo, key, pt, iv); + } + if (nodeCrypto) { + // Node crypto library. + return nodeEncrypt(algo, key, pt, iv); + } // asm.js fallback + const cfb = new _cfb.AES_CFB(key, iv); + return _webStreamTools2.default.transform(pt, value => cfb.AES_Encrypt_process(value), () => cfb.AES_Encrypt_finish()); +} + +function aesDecrypt(algo, key, ct, iv) { + if (nodeCrypto) { + // Node crypto library. + return nodeDecrypt(algo, key, ct, iv); + } + if (_util2.default.isStream(ct)) { + const cfb = new _cfb.AES_CFB(key, iv); + return _webStreamTools2.default.transform(ct, value => cfb.AES_Decrypt_process(value), () => cfb.AES_Decrypt_finish()); + } + return _cfb.AES_CFB.decrypt(ct, key, iv); +} + +function xorMut(a, b) { + for (let i = 0; i < a.length; i++) { + a[i] = a[i] ^ b[i]; + } +} + +async function webEncrypt(algo, key, pt, iv) { + const ALGO = 'AES-CBC'; + const _key = await webCrypto.importKey('raw', key, { name: ALGO }, false, ['encrypt']); + const blockSize = _cipher2.default[algo].blockSize; + + const cbc_pt = _util2.default.concatUint8Array([new Uint8Array(blockSize), pt]); + const ct = new Uint8Array((await webCrypto.encrypt({ name: ALGO, iv }, _key, cbc_pt))).subarray(0, pt.length); + xorMut(ct, pt); + return ct; +} + +function nodeEncrypt(algo, key, pt, iv) { + key = new Buffer(key); + iv = new Buffer(iv); + const cipherObj = new nodeCrypto.createCipheriv('aes-' + algo.substr(3, 3) + '-cfb', key, iv); + return _webStreamTools2.default.transform(pt, value => new Uint8Array(cipherObj.update(new Buffer(value)))); +} + +function nodeDecrypt(algo, key, ct, iv) { + key = new Buffer(key); + iv = new Buffer(iv); + const decipherObj = new nodeCrypto.createDecipheriv('aes-' + algo.substr(3, 3) + '-cfb', key, iv); + return _webStreamTools2.default.transform(ct, value => new Uint8Array(decipherObj.update(new Buffer(value)))); +} + +},{"../config":79,"../util":152,"./cipher":86,"asmcrypto.js/dist_es5/aes/cfb":5,"web-stream-tools":75}],82:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _ecb = require('asmcrypto.js/dist_es5/aes/ecb'); + +// TODO use webCrypto or nodeCrypto when possible. +function aes(length) { + const C = function C(key) { + const aes_ecb = new _ecb.AES_ECB(key); + + this.encrypt = function (block) { + return aes_ecb.encrypt(block); + }; + + this.decrypt = function (block) { + return aes_ecb.decrypt(block); + }; + }; + + C.blockSize = C.prototype.blockSize = 16; + C.keySize = C.prototype.keySize = length / 8; + + return C; +} /** + * @requires asmcrypto.js + */ + +exports.default = aes; + +},{"asmcrypto.js/dist_es5/aes/ecb":7}],83:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +/* Modified by Recurity Labs GmbH + * + * Originally written by nklein software (nklein.com) + */ + +/* + * Javascript implementation based on Bruce Schneier's reference implementation. + * + * + * The constructor doesn't do much of anything. It's just here + * so we can start defining properties and methods and such. + */ +function Blowfish() {} + +/* + * Declare the block size so that protocols know what size + * Initialization Vector (IV) they will need. + */ +Blowfish.prototype.BLOCKSIZE = 8; + +/* + * These are the default SBOXES. + */ +Blowfish.prototype.SBOXES = [[0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a], [0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7], [0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0], [0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6]]; + +//* +//* This is the default PARRAY +//* +Blowfish.prototype.PARRAY = [0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b]; + +//* +//* This is the number of rounds the cipher will go +//* +Blowfish.prototype.NN = 16; + +//* +//* This function is needed to get rid of problems +//* with the high-bit getting set. If we don't do +//* this, then sometimes ( aa & 0x00FFFFFFFF ) is not +//* equal to ( bb & 0x00FFFFFFFF ) even when they +//* agree bit-for-bit for the first 32 bits. +//* +Blowfish.prototype._clean = function (xx) { + if (xx < 0) { + const yy = xx & 0x7FFFFFFF; + xx = yy + 0x80000000; + } + return xx; +}; + +//* +//* This is the mixing function that uses the sboxes +//* +Blowfish.prototype._F = function (xx) { + let yy; + + const dd = xx & 0x00FF; + xx >>>= 8; + const cc = xx & 0x00FF; + xx >>>= 8; + const bb = xx & 0x00FF; + xx >>>= 8; + const aa = xx & 0x00FF; + + yy = this.sboxes[0][aa] + this.sboxes[1][bb]; + yy ^= this.sboxes[2][cc]; + yy += this.sboxes[3][dd]; + + return yy; +}; + +//* +//* This method takes an array with two values, left and right +//* and does NN rounds of Blowfish on them. +//* +Blowfish.prototype._encrypt_block = function (vals) { + let dataL = vals[0]; + let dataR = vals[1]; + + let ii; + + for (ii = 0; ii < this.NN; ++ii) { + dataL ^= this.parray[ii]; + dataR = this._F(dataL) ^ dataR; + + const tmp = dataL; + dataL = dataR; + dataR = tmp; + } + + dataL ^= this.parray[this.NN + 0]; + dataR ^= this.parray[this.NN + 1]; + + vals[0] = this._clean(dataR); + vals[1] = this._clean(dataL); +}; + +//* +//* This method takes a vector of numbers and turns them +//* into long words so that they can be processed by the +//* real algorithm. +//* +//* Maybe I should make the real algorithm above take a vector +//* instead. That will involve more looping, but it won't require +//* the F() method to deconstruct the vector. +//* +Blowfish.prototype.encrypt_block = function (vector) { + let ii; + const vals = [0, 0]; + const off = this.BLOCKSIZE / 2; + for (ii = 0; ii < this.BLOCKSIZE / 2; ++ii) { + vals[0] = vals[0] << 8 | vector[ii + 0] & 0x00FF; + vals[1] = vals[1] << 8 | vector[ii + off] & 0x00FF; + } + + this._encrypt_block(vals); + + const ret = []; + for (ii = 0; ii < this.BLOCKSIZE / 2; ++ii) { + ret[ii + 0] = vals[0] >>> 24 - 8 * ii & 0x00FF; + ret[ii + off] = vals[1] >>> 24 - 8 * ii & 0x00FF; + // vals[ 0 ] = ( vals[ 0 ] >>> 8 ); + // vals[ 1 ] = ( vals[ 1 ] >>> 8 ); + } + + return ret; +}; + +//* +//* This method takes an array with two values, left and right +//* and undoes NN rounds of Blowfish on them. +//* +Blowfish.prototype._decrypt_block = function (vals) { + let dataL = vals[0]; + let dataR = vals[1]; + + let ii; + + for (ii = this.NN + 1; ii > 1; --ii) { + dataL ^= this.parray[ii]; + dataR = this._F(dataL) ^ dataR; + + const tmp = dataL; + dataL = dataR; + dataR = tmp; + } + + dataL ^= this.parray[1]; + dataR ^= this.parray[0]; + + vals[0] = this._clean(dataR); + vals[1] = this._clean(dataL); +}; + +//* +//* This method takes a key array and initializes the +//* sboxes and parray for this encryption. +//* +Blowfish.prototype.init = function (key) { + let ii; + let jj = 0; + + this.parray = []; + for (ii = 0; ii < this.NN + 2; ++ii) { + let data = 0x00000000; + for (let kk = 0; kk < 4; ++kk) { + data = data << 8 | key[jj] & 0x00FF; + if (++jj >= key.length) { + jj = 0; + } + } + this.parray[ii] = this.PARRAY[ii] ^ data; + } + + this.sboxes = []; + for (ii = 0; ii < 4; ++ii) { + this.sboxes[ii] = []; + for (jj = 0; jj < 256; ++jj) { + this.sboxes[ii][jj] = this.SBOXES[ii][jj]; + } + } + + const vals = [0x00000000, 0x00000000]; + + for (ii = 0; ii < this.NN + 2; ii += 2) { + this._encrypt_block(vals); + this.parray[ii + 0] = vals[0]; + this.parray[ii + 1] = vals[1]; + } + + for (ii = 0; ii < 4; ++ii) { + for (jj = 0; jj < 256; jj += 2) { + this._encrypt_block(vals); + this.sboxes[ii][jj + 0] = vals[0]; + this.sboxes[ii][jj + 1] = vals[1]; + } + } +}; + +// added by Recurity Labs +function BF(key) { + this.bf = new Blowfish(); + this.bf.init(key); + + this.encrypt = function (block) { + return this.bf.encrypt_block(block); + }; +} + +BF.keySize = BF.prototype.keySize = 16; +BF.blockSize = BF.prototype.blockSize = 16; + +exports.default = BF; + +},{}],84:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Copyright 2010 pjacobs@xeekr.com . All rights reserved. + +// Modified by Recurity Labs GmbH + +// fixed/modified by Herbert Hanewinkel, www.haneWIN.de +// check www.haneWIN.de for the latest version + +// cast5.js is a Javascript implementation of CAST-128, as defined in RFC 2144. +// CAST-128 is a common OpenPGP cipher. + + +// CAST5 constructor + +function OpenpgpSymencCast5() { + this.BlockSize = 8; + this.KeySize = 16; + + this.setKey = function (key) { + this.masking = new Array(16); + this.rotate = new Array(16); + + this.reset(); + + if (key.length === this.KeySize) { + this.keySchedule(key); + } else { + throw new Error('CAST-128: keys must be 16 bytes'); + } + return true; + }; + + this.reset = function () { + for (let i = 0; i < 16; i++) { + this.masking[i] = 0; + this.rotate[i] = 0; + } + }; + + this.getBlockSize = function () { + return this.BlockSize; + }; + + this.encrypt = function (src) { + const dst = new Array(src.length); + + for (let i = 0; i < src.length; i += 8) { + let l = src[i] << 24 | src[i + 1] << 16 | src[i + 2] << 8 | src[i + 3]; + let r = src[i + 4] << 24 | src[i + 5] << 16 | src[i + 6] << 8 | src[i + 7]; + let t; + + t = r; + r = l ^ f1(r, this.masking[0], this.rotate[0]); + l = t; + t = r; + r = l ^ f2(r, this.masking[1], this.rotate[1]); + l = t; + t = r; + r = l ^ f3(r, this.masking[2], this.rotate[2]); + l = t; + t = r; + r = l ^ f1(r, this.masking[3], this.rotate[3]); + l = t; + + t = r; + r = l ^ f2(r, this.masking[4], this.rotate[4]); + l = t; + t = r; + r = l ^ f3(r, this.masking[5], this.rotate[5]); + l = t; + t = r; + r = l ^ f1(r, this.masking[6], this.rotate[6]); + l = t; + t = r; + r = l ^ f2(r, this.masking[7], this.rotate[7]); + l = t; + + t = r; + r = l ^ f3(r, this.masking[8], this.rotate[8]); + l = t; + t = r; + r = l ^ f1(r, this.masking[9], this.rotate[9]); + l = t; + t = r; + r = l ^ f2(r, this.masking[10], this.rotate[10]); + l = t; + t = r; + r = l ^ f3(r, this.masking[11], this.rotate[11]); + l = t; + + t = r; + r = l ^ f1(r, this.masking[12], this.rotate[12]); + l = t; + t = r; + r = l ^ f2(r, this.masking[13], this.rotate[13]); + l = t; + t = r; + r = l ^ f3(r, this.masking[14], this.rotate[14]); + l = t; + t = r; + r = l ^ f1(r, this.masking[15], this.rotate[15]); + l = t; + + dst[i] = r >>> 24 & 255; + dst[i + 1] = r >>> 16 & 255; + dst[i + 2] = r >>> 8 & 255; + dst[i + 3] = r & 255; + dst[i + 4] = l >>> 24 & 255; + dst[i + 5] = l >>> 16 & 255; + dst[i + 6] = l >>> 8 & 255; + dst[i + 7] = l & 255; + } + + return dst; + }; + + this.decrypt = function (src) { + const dst = new Array(src.length); + + for (let i = 0; i < src.length; i += 8) { + let l = src[i] << 24 | src[i + 1] << 16 | src[i + 2] << 8 | src[i + 3]; + let r = src[i + 4] << 24 | src[i + 5] << 16 | src[i + 6] << 8 | src[i + 7]; + let t; + + t = r; + r = l ^ f1(r, this.masking[15], this.rotate[15]); + l = t; + t = r; + r = l ^ f3(r, this.masking[14], this.rotate[14]); + l = t; + t = r; + r = l ^ f2(r, this.masking[13], this.rotate[13]); + l = t; + t = r; + r = l ^ f1(r, this.masking[12], this.rotate[12]); + l = t; + + t = r; + r = l ^ f3(r, this.masking[11], this.rotate[11]); + l = t; + t = r; + r = l ^ f2(r, this.masking[10], this.rotate[10]); + l = t; + t = r; + r = l ^ f1(r, this.masking[9], this.rotate[9]); + l = t; + t = r; + r = l ^ f3(r, this.masking[8], this.rotate[8]); + l = t; + + t = r; + r = l ^ f2(r, this.masking[7], this.rotate[7]); + l = t; + t = r; + r = l ^ f1(r, this.masking[6], this.rotate[6]); + l = t; + t = r; + r = l ^ f3(r, this.masking[5], this.rotate[5]); + l = t; + t = r; + r = l ^ f2(r, this.masking[4], this.rotate[4]); + l = t; + + t = r; + r = l ^ f1(r, this.masking[3], this.rotate[3]); + l = t; + t = r; + r = l ^ f3(r, this.masking[2], this.rotate[2]); + l = t; + t = r; + r = l ^ f2(r, this.masking[1], this.rotate[1]); + l = t; + t = r; + r = l ^ f1(r, this.masking[0], this.rotate[0]); + l = t; + + dst[i] = r >>> 24 & 255; + dst[i + 1] = r >>> 16 & 255; + dst[i + 2] = r >>> 8 & 255; + dst[i + 3] = r & 255; + dst[i + 4] = l >>> 24 & 255; + dst[i + 5] = l >> 16 & 255; + dst[i + 6] = l >> 8 & 255; + dst[i + 7] = l & 255; + } + + return dst; + }; + const scheduleA = new Array(4); + + scheduleA[0] = new Array(4); + scheduleA[0][0] = [4, 0, 0xd, 0xf, 0xc, 0xe, 0x8]; + scheduleA[0][1] = [5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa]; + scheduleA[0][2] = [6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9]; + scheduleA[0][3] = [7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb]; + + scheduleA[1] = new Array(4); + scheduleA[1][0] = [0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0]; + scheduleA[1][1] = [1, 4, 0, 2, 1, 3, 16 + 2]; + scheduleA[1][2] = [2, 5, 7, 6, 5, 4, 16 + 1]; + scheduleA[1][3] = [3, 7, 0xa, 9, 0xb, 8, 16 + 3]; + + scheduleA[2] = new Array(4); + scheduleA[2][0] = [4, 0, 0xd, 0xf, 0xc, 0xe, 8]; + scheduleA[2][1] = [5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa]; + scheduleA[2][2] = [6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9]; + scheduleA[2][3] = [7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb]; + + scheduleA[3] = new Array(4); + scheduleA[3][0] = [0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0]; + scheduleA[3][1] = [1, 4, 0, 2, 1, 3, 16 + 2]; + scheduleA[3][2] = [2, 5, 7, 6, 5, 4, 16 + 1]; + scheduleA[3][3] = [3, 7, 0xa, 9, 0xb, 8, 16 + 3]; + + const scheduleB = new Array(4); + + scheduleB[0] = new Array(4); + scheduleB[0][0] = [16 + 8, 16 + 9, 16 + 7, 16 + 6, 16 + 2]; + scheduleB[0][1] = [16 + 0xa, 16 + 0xb, 16 + 5, 16 + 4, 16 + 6]; + scheduleB[0][2] = [16 + 0xc, 16 + 0xd, 16 + 3, 16 + 2, 16 + 9]; + scheduleB[0][3] = [16 + 0xe, 16 + 0xf, 16 + 1, 16 + 0, 16 + 0xc]; + + scheduleB[1] = new Array(4); + scheduleB[1][0] = [3, 2, 0xc, 0xd, 8]; + scheduleB[1][1] = [1, 0, 0xe, 0xf, 0xd]; + scheduleB[1][2] = [7, 6, 8, 9, 3]; + scheduleB[1][3] = [5, 4, 0xa, 0xb, 7]; + + scheduleB[2] = new Array(4); + scheduleB[2][0] = [16 + 3, 16 + 2, 16 + 0xc, 16 + 0xd, 16 + 9]; + scheduleB[2][1] = [16 + 1, 16 + 0, 16 + 0xe, 16 + 0xf, 16 + 0xc]; + scheduleB[2][2] = [16 + 7, 16 + 6, 16 + 8, 16 + 9, 16 + 2]; + scheduleB[2][3] = [16 + 5, 16 + 4, 16 + 0xa, 16 + 0xb, 16 + 6]; + + scheduleB[3] = new Array(4); + scheduleB[3][0] = [8, 9, 7, 6, 3]; + scheduleB[3][1] = [0xa, 0xb, 5, 4, 7]; + scheduleB[3][2] = [0xc, 0xd, 3, 2, 8]; + scheduleB[3][3] = [0xe, 0xf, 1, 0, 0xd]; + + // changed 'in' to 'inn' (in javascript 'in' is a reserved word) + this.keySchedule = function (inn) { + const t = new Array(8); + const k = new Array(32); + + let j; + + for (let i = 0; i < 4; i++) { + j = i * 4; + t[i] = inn[j] << 24 | inn[j + 1] << 16 | inn[j + 2] << 8 | inn[j + 3]; + } + + const x = [6, 7, 4, 5]; + let ki = 0; + let w; + + for (let half = 0; half < 2; half++) { + for (let round = 0; round < 4; round++) { + for (j = 0; j < 4; j++) { + const a = scheduleA[round][j]; + w = t[a[1]]; + + w ^= sBox[4][t[a[2] >>> 2] >>> 24 - 8 * (a[2] & 3) & 0xff]; + w ^= sBox[5][t[a[3] >>> 2] >>> 24 - 8 * (a[3] & 3) & 0xff]; + w ^= sBox[6][t[a[4] >>> 2] >>> 24 - 8 * (a[4] & 3) & 0xff]; + w ^= sBox[7][t[a[5] >>> 2] >>> 24 - 8 * (a[5] & 3) & 0xff]; + w ^= sBox[x[j]][t[a[6] >>> 2] >>> 24 - 8 * (a[6] & 3) & 0xff]; + t[a[0]] = w; + } + + for (j = 0; j < 4; j++) { + const b = scheduleB[round][j]; + w = sBox[4][t[b[0] >>> 2] >>> 24 - 8 * (b[0] & 3) & 0xff]; + + w ^= sBox[5][t[b[1] >>> 2] >>> 24 - 8 * (b[1] & 3) & 0xff]; + w ^= sBox[6][t[b[2] >>> 2] >>> 24 - 8 * (b[2] & 3) & 0xff]; + w ^= sBox[7][t[b[3] >>> 2] >>> 24 - 8 * (b[3] & 3) & 0xff]; + w ^= sBox[4 + j][t[b[4] >>> 2] >>> 24 - 8 * (b[4] & 3) & 0xff]; + k[ki] = w; + ki++; + } + } + } + + for (let i = 0; i < 16; i++) { + this.masking[i] = k[i]; + this.rotate[i] = k[16 + i] & 0x1f; + } + }; + + // These are the three 'f' functions. See RFC 2144, section 2.2. + + function f1(d, m, r) { + const t = m + d; + const I = t << r | t >>> 32 - r; + return (sBox[0][I >>> 24] ^ sBox[1][I >>> 16 & 255]) - sBox[2][I >>> 8 & 255] + sBox[3][I & 255]; + } + + function f2(d, m, r) { + const t = m ^ d; + const I = t << r | t >>> 32 - r; + return sBox[0][I >>> 24] - sBox[1][I >>> 16 & 255] + sBox[2][I >>> 8 & 255] ^ sBox[3][I & 255]; + } + + function f3(d, m, r) { + const t = m - d; + const I = t << r | t >>> 32 - r; + return (sBox[0][I >>> 24] + sBox[1][I >>> 16 & 255] ^ sBox[2][I >>> 8 & 255]) - sBox[3][I & 255]; + } + + const sBox = new Array(8); + sBox[0] = [0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949, 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0, 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, 0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935, 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d, 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, 0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe, 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3, 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, 0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291, 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779, 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, 0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d, 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c, 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, 0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d, 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96, 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, 0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, 0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872, 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9, 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf]; + + sBox[1] = [0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651, 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806, 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, 0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359, 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b, 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, 0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34, 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb, 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, 0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860, 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b, 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, 0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f, 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, 0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6, 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58, 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, 0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6, 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, 0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6, 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f, 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, 0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9, 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1]; + + sBox[2] = [0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90, 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240, 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, 0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71, 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, 0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15, 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, 0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176, 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148, 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, 0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e, 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a, 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, 0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5, 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, 0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536, 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, 0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69, 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, 0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a, 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783]; + + sBox[3] = [0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1, 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121, 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, 0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb, 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, 0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d, 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6, 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, 0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003, 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, 0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a, 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26, 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, 0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7, 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417, 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, 0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2, 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, 0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282, 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2]; + + sBox[4] = [0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f, 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02, 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, 0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7, 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9, 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, 0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774, 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655, 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, 0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910, 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1, 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, 0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f, 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3, 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, 0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4, 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2, 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, 0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5, 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, 0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801, 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, 0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8, 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4]; + + sBox[5] = [0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac, 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98, 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, 0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3, 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd, 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, 0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9, 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54, 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, 0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc, 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf, 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289, 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b, 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, 0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13, 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976, 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, 0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891, 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da, 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, 0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084, 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25, 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, 0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd, 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f]; + + sBox[6] = [0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f, 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19, 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, 0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516, 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88, 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, 0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756, 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, 0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688, 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28, 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566, 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, 0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962, 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e, 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, 0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c, 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, 0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be, 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767, 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, 0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c, 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3]; + + sBox[7] = [0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5, 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d, 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, 0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862, 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc, 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, 0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e, 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039, 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, 0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42, 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5, 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c, 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70, 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, 0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c, 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3, 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, 0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101, 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f, 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, 0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a, 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c, 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, 0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82, 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e]; +} + +function Cast5(key) { + this.cast5 = new OpenpgpSymencCast5(); + this.cast5.setKey(key); + + this.encrypt = function (block) { + return this.cast5.encrypt(block); + }; +} + +Cast5.blockSize = Cast5.prototype.blockSize = 8; +Cast5.keySize = Cast5.prototype.keySize = 16; + +exports.default = Cast5; + +},{}],85:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +//Paul Tero, July 2001 +//http://www.tero.co.uk/des/ +// +//Optimised for performance with large blocks by Michael Hayworth, November 2001 +//http://www.netdealing.com +// +// Modified by Recurity Labs GmbH + +//THIS SOFTWARE IS PROVIDED "AS IS" AND +//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +//IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +//ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +//FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +//DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +//OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +//HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +//OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +//SUCH DAMAGE. + +//des +//this takes the key, the message, and whether to encrypt or decrypt + +function des(keys, message, encrypt, mode, iv, padding) { + //declaring this locally speeds things up a bit + const spfunction1 = [0x1010400, 0, 0x10000, 0x1010404, 0x1010004, 0x10404, 0x4, 0x10000, 0x400, 0x1010400, 0x1010404, 0x400, 0x1000404, 0x1010004, 0x1000000, 0x4, 0x404, 0x1000400, 0x1000400, 0x10400, 0x10400, 0x1010000, 0x1010000, 0x1000404, 0x10004, 0x1000004, 0x1000004, 0x10004, 0, 0x404, 0x10404, 0x1000000, 0x10000, 0x1010404, 0x4, 0x1010000, 0x1010400, 0x1000000, 0x1000000, 0x400, 0x1010004, 0x10000, 0x10400, 0x1000004, 0x400, 0x4, 0x1000404, 0x10404, 0x1010404, 0x10004, 0x1010000, 0x1000404, 0x1000004, 0x404, 0x10404, 0x1010400, 0x404, 0x1000400, 0x1000400, 0, 0x10004, 0x10400, 0, 0x1010004]; + const spfunction2 = [-0x7fef7fe0, -0x7fff8000, 0x8000, 0x108020, 0x100000, 0x20, -0x7fefffe0, -0x7fff7fe0, -0x7fffffe0, -0x7fef7fe0, -0x7fef8000, -0x80000000, -0x7fff8000, 0x100000, 0x20, -0x7fefffe0, 0x108000, 0x100020, -0x7fff7fe0, 0, -0x80000000, 0x8000, 0x108020, -0x7ff00000, 0x100020, -0x7fffffe0, 0, 0x108000, 0x8020, -0x7fef8000, -0x7ff00000, 0x8020, 0, 0x108020, -0x7fefffe0, 0x100000, -0x7fff7fe0, -0x7ff00000, -0x7fef8000, 0x8000, -0x7ff00000, -0x7fff8000, 0x20, -0x7fef7fe0, 0x108020, 0x20, 0x8000, -0x80000000, 0x8020, -0x7fef8000, 0x100000, -0x7fffffe0, 0x100020, -0x7fff7fe0, -0x7fffffe0, 0x100020, 0x108000, 0, -0x7fff8000, 0x8020, -0x80000000, -0x7fefffe0, -0x7fef7fe0, 0x108000]; + const spfunction3 = [0x208, 0x8020200, 0, 0x8020008, 0x8000200, 0, 0x20208, 0x8000200, 0x20008, 0x8000008, 0x8000008, 0x20000, 0x8020208, 0x20008, 0x8020000, 0x208, 0x8000000, 0x8, 0x8020200, 0x200, 0x20200, 0x8020000, 0x8020008, 0x20208, 0x8000208, 0x20200, 0x20000, 0x8000208, 0x8, 0x8020208, 0x200, 0x8000000, 0x8020200, 0x8000000, 0x20008, 0x208, 0x20000, 0x8020200, 0x8000200, 0, 0x200, 0x20008, 0x8020208, 0x8000200, 0x8000008, 0x200, 0, 0x8020008, 0x8000208, 0x20000, 0x8000000, 0x8020208, 0x8, 0x20208, 0x20200, 0x8000008, 0x8020000, 0x8000208, 0x208, 0x8020000, 0x20208, 0x8, 0x8020008, 0x20200]; + const spfunction4 = [0x802001, 0x2081, 0x2081, 0x80, 0x802080, 0x800081, 0x800001, 0x2001, 0, 0x802000, 0x802000, 0x802081, 0x81, 0, 0x800080, 0x800001, 0x1, 0x2000, 0x800000, 0x802001, 0x80, 0x800000, 0x2001, 0x2080, 0x800081, 0x1, 0x2080, 0x800080, 0x2000, 0x802080, 0x802081, 0x81, 0x800080, 0x800001, 0x802000, 0x802081, 0x81, 0, 0, 0x802000, 0x2080, 0x800080, 0x800081, 0x1, 0x802001, 0x2081, 0x2081, 0x80, 0x802081, 0x81, 0x1, 0x2000, 0x800001, 0x2001, 0x802080, 0x800081, 0x2001, 0x2080, 0x800000, 0x802001, 0x80, 0x800000, 0x2000, 0x802080]; + const spfunction5 = [0x100, 0x2080100, 0x2080000, 0x42000100, 0x80000, 0x100, 0x40000000, 0x2080000, 0x40080100, 0x80000, 0x2000100, 0x40080100, 0x42000100, 0x42080000, 0x80100, 0x40000000, 0x2000000, 0x40080000, 0x40080000, 0, 0x40000100, 0x42080100, 0x42080100, 0x2000100, 0x42080000, 0x40000100, 0, 0x42000000, 0x2080100, 0x2000000, 0x42000000, 0x80100, 0x80000, 0x42000100, 0x100, 0x2000000, 0x40000000, 0x2080000, 0x42000100, 0x40080100, 0x2000100, 0x40000000, 0x42080000, 0x2080100, 0x40080100, 0x100, 0x2000000, 0x42080000, 0x42080100, 0x80100, 0x42000000, 0x42080100, 0x2080000, 0, 0x40080000, 0x42000000, 0x80100, 0x2000100, 0x40000100, 0x80000, 0, 0x40080000, 0x2080100, 0x40000100]; + const spfunction6 = [0x20000010, 0x20400000, 0x4000, 0x20404010, 0x20400000, 0x10, 0x20404010, 0x400000, 0x20004000, 0x404010, 0x400000, 0x20000010, 0x400010, 0x20004000, 0x20000000, 0x4010, 0, 0x400010, 0x20004010, 0x4000, 0x404000, 0x20004010, 0x10, 0x20400010, 0x20400010, 0, 0x404010, 0x20404000, 0x4010, 0x404000, 0x20404000, 0x20000000, 0x20004000, 0x10, 0x20400010, 0x404000, 0x20404010, 0x400000, 0x4010, 0x20000010, 0x400000, 0x20004000, 0x20000000, 0x4010, 0x20000010, 0x20404010, 0x404000, 0x20400000, 0x404010, 0x20404000, 0, 0x20400010, 0x10, 0x4000, 0x20400000, 0x404010, 0x4000, 0x400010, 0x20004010, 0, 0x20404000, 0x20000000, 0x400010, 0x20004010]; + const spfunction7 = [0x200000, 0x4200002, 0x4000802, 0, 0x800, 0x4000802, 0x200802, 0x4200800, 0x4200802, 0x200000, 0, 0x4000002, 0x2, 0x4000000, 0x4200002, 0x802, 0x4000800, 0x200802, 0x200002, 0x4000800, 0x4000002, 0x4200000, 0x4200800, 0x200002, 0x4200000, 0x800, 0x802, 0x4200802, 0x200800, 0x2, 0x4000000, 0x200800, 0x4000000, 0x200800, 0x200000, 0x4000802, 0x4000802, 0x4200002, 0x4200002, 0x2, 0x200002, 0x4000000, 0x4000800, 0x200000, 0x4200800, 0x802, 0x200802, 0x4200800, 0x802, 0x4000002, 0x4200802, 0x4200000, 0x200800, 0, 0x2, 0x4200802, 0, 0x200802, 0x4200000, 0x800, 0x4000002, 0x4000800, 0x800, 0x200002]; + const spfunction8 = [0x10001040, 0x1000, 0x40000, 0x10041040, 0x10000000, 0x10001040, 0x40, 0x10000000, 0x40040, 0x10040000, 0x10041040, 0x41000, 0x10041000, 0x41040, 0x1000, 0x40, 0x10040000, 0x10000040, 0x10001000, 0x1040, 0x41000, 0x40040, 0x10040040, 0x10041000, 0x1040, 0, 0, 0x10040040, 0x10000040, 0x10001000, 0x41040, 0x40000, 0x41040, 0x40000, 0x10041000, 0x1000, 0x40, 0x10040040, 0x1000, 0x41040, 0x10001000, 0x40, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x40000, 0x10001040, 0, 0x10041040, 0x40040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0, 0x10041040, 0x41000, 0x41000, 0x1040, 0x1040, 0x40040, 0x10000000, 0x10041000]; + + //create the 16 or 48 subkeys we will need + let m = 0; + let i; + let j; + let temp; + let right1; + let right2; + let left; + let right; + let looping; + let cbcleft; + let cbcleft2; + let cbcright; + let cbcright2; + let endloop; + let loopinc; + let len = message.length; + + //set up the loops for single and triple des + const iterations = keys.length === 32 ? 3 : 9; //single or triple des + if (iterations === 3) { + looping = encrypt ? [0, 32, 2] : [30, -2, -2]; + } else { + looping = encrypt ? [0, 32, 2, 62, 30, -2, 64, 96, 2] : [94, 62, -2, 32, 64, 2, 30, -2, -2]; + } + + //pad the message depending on the padding parameter + //only add padding if encrypting - note that you need to use the same padding option for both encrypt and decrypt + if (encrypt) { + message = des_addPadding(message, padding); + len = message.length; + } + + //store the result here + let result = new Uint8Array(len); + let k = 0; + + if (mode === 1) { + //CBC mode + cbcleft = iv[m++] << 24 | iv[m++] << 16 | iv[m++] << 8 | iv[m++]; + cbcright = iv[m++] << 24 | iv[m++] << 16 | iv[m++] << 8 | iv[m++]; + m = 0; + } + + //loop through each 64 bit chunk of the message + while (m < len) { + left = message[m++] << 24 | message[m++] << 16 | message[m++] << 8 | message[m++]; + right = message[m++] << 24 | message[m++] << 16 | message[m++] << 8 | message[m++]; + + //for Cipher Block Chaining mode, xor the message with the previous result + if (mode === 1) { + if (encrypt) { + left ^= cbcleft; + right ^= cbcright; + } else { + cbcleft2 = cbcleft; + cbcright2 = cbcright; + cbcleft = left; + cbcright = right; + } + } + + //first each 64 but chunk of the message must be permuted according to IP + temp = (left >>> 4 ^ right) & 0x0f0f0f0f; + right ^= temp; + left ^= temp << 4; + temp = (left >>> 16 ^ right) & 0x0000ffff; + right ^= temp; + left ^= temp << 16; + temp = (right >>> 2 ^ left) & 0x33333333; + left ^= temp; + right ^= temp << 2; + temp = (right >>> 8 ^ left) & 0x00ff00ff; + left ^= temp; + right ^= temp << 8; + temp = (left >>> 1 ^ right) & 0x55555555; + right ^= temp; + left ^= temp << 1; + + left = left << 1 | left >>> 31; + right = right << 1 | right >>> 31; + + //do this either 1 or 3 times for each chunk of the message + for (j = 0; j < iterations; j += 3) { + endloop = looping[j + 1]; + loopinc = looping[j + 2]; + //now go through and perform the encryption or decryption + for (i = looping[j]; i !== endloop; i += loopinc) { + //for efficiency + right1 = right ^ keys[i]; + right2 = (right >>> 4 | right << 28) ^ keys[i + 1]; + //the result is attained by passing these bytes through the S selection functions + temp = left; + left = right; + right = temp ^ (spfunction2[right1 >>> 24 & 0x3f] | spfunction4[right1 >>> 16 & 0x3f] | spfunction6[right1 >>> 8 & 0x3f] | spfunction8[right1 & 0x3f] | spfunction1[right2 >>> 24 & 0x3f] | spfunction3[right2 >>> 16 & 0x3f] | spfunction5[right2 >>> 8 & 0x3f] | spfunction7[right2 & 0x3f]); + } + temp = left; + left = right; + right = temp; //unreverse left and right + } //for either 1 or 3 iterations + + //move then each one bit to the right + left = left >>> 1 | left << 31; + right = right >>> 1 | right << 31; + + //now perform IP-1, which is IP in the opposite direction + temp = (left >>> 1 ^ right) & 0x55555555; + right ^= temp; + left ^= temp << 1; + temp = (right >>> 8 ^ left) & 0x00ff00ff; + left ^= temp; + right ^= temp << 8; + temp = (right >>> 2 ^ left) & 0x33333333; + left ^= temp; + right ^= temp << 2; + temp = (left >>> 16 ^ right) & 0x0000ffff; + right ^= temp; + left ^= temp << 16; + temp = (left >>> 4 ^ right) & 0x0f0f0f0f; + right ^= temp; + left ^= temp << 4; + + //for Cipher Block Chaining mode, xor the message with the previous result + if (mode === 1) { + if (encrypt) { + cbcleft = left; + cbcright = right; + } else { + left ^= cbcleft2; + right ^= cbcright2; + } + } + + result[k++] = left >>> 24; + result[k++] = left >>> 16 & 0xff; + result[k++] = left >>> 8 & 0xff; + result[k++] = left & 0xff; + result[k++] = right >>> 24; + result[k++] = right >>> 16 & 0xff; + result[k++] = right >>> 8 & 0xff; + result[k++] = right & 0xff; + } //for every 8 characters, or 64 bits in the message + + //only remove padding if decrypting - note that you need to use the same padding option for both encrypt and decrypt + if (!encrypt) { + result = des_removePadding(result, padding); + } + + return result; +} //end of des + + +//des_createKeys +//this takes as input a 64 bit key (even though only 56 bits are used) +//as an array of 2 integers, and returns 16 48 bit keys + +function des_createKeys(key) { + //declaring this locally speeds things up a bit + const pc2bytes0 = [0, 0x4, 0x20000000, 0x20000004, 0x10000, 0x10004, 0x20010000, 0x20010004, 0x200, 0x204, 0x20000200, 0x20000204, 0x10200, 0x10204, 0x20010200, 0x20010204]; + const pc2bytes1 = [0, 0x1, 0x100000, 0x100001, 0x4000000, 0x4000001, 0x4100000, 0x4100001, 0x100, 0x101, 0x100100, 0x100101, 0x4000100, 0x4000101, 0x4100100, 0x4100101]; + const pc2bytes2 = [0, 0x8, 0x800, 0x808, 0x1000000, 0x1000008, 0x1000800, 0x1000808, 0, 0x8, 0x800, 0x808, 0x1000000, 0x1000008, 0x1000800, 0x1000808]; + const pc2bytes3 = [0, 0x200000, 0x8000000, 0x8200000, 0x2000, 0x202000, 0x8002000, 0x8202000, 0x20000, 0x220000, 0x8020000, 0x8220000, 0x22000, 0x222000, 0x8022000, 0x8222000]; + const pc2bytes4 = [0, 0x40000, 0x10, 0x40010, 0, 0x40000, 0x10, 0x40010, 0x1000, 0x41000, 0x1010, 0x41010, 0x1000, 0x41000, 0x1010, 0x41010]; + const pc2bytes5 = [0, 0x400, 0x20, 0x420, 0, 0x400, 0x20, 0x420, 0x2000000, 0x2000400, 0x2000020, 0x2000420, 0x2000000, 0x2000400, 0x2000020, 0x2000420]; + const pc2bytes6 = [0, 0x10000000, 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002, 0, 0x10000000, 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002]; + const pc2bytes7 = [0, 0x10000, 0x800, 0x10800, 0x20000000, 0x20010000, 0x20000800, 0x20010800, 0x20000, 0x30000, 0x20800, 0x30800, 0x20020000, 0x20030000, 0x20020800, 0x20030800]; + const pc2bytes8 = [0, 0x40000, 0, 0x40000, 0x2, 0x40002, 0x2, 0x40002, 0x2000000, 0x2040000, 0x2000000, 0x2040000, 0x2000002, 0x2040002, 0x2000002, 0x2040002]; + const pc2bytes9 = [0, 0x10000000, 0x8, 0x10000008, 0, 0x10000000, 0x8, 0x10000008, 0x400, 0x10000400, 0x408, 0x10000408, 0x400, 0x10000400, 0x408, 0x10000408]; + const pc2bytes10 = [0, 0x20, 0, 0x20, 0x100000, 0x100020, 0x100000, 0x100020, 0x2000, 0x2020, 0x2000, 0x2020, 0x102000, 0x102020, 0x102000, 0x102020]; + const pc2bytes11 = [0, 0x1000000, 0x200, 0x1000200, 0x200000, 0x1200000, 0x200200, 0x1200200, 0x4000000, 0x5000000, 0x4000200, 0x5000200, 0x4200000, 0x5200000, 0x4200200, 0x5200200]; + const pc2bytes12 = [0, 0x1000, 0x8000000, 0x8001000, 0x80000, 0x81000, 0x8080000, 0x8081000, 0x10, 0x1010, 0x8000010, 0x8001010, 0x80010, 0x81010, 0x8080010, 0x8081010]; + const pc2bytes13 = [0, 0x4, 0x100, 0x104, 0, 0x4, 0x100, 0x104, 0x1, 0x5, 0x101, 0x105, 0x1, 0x5, 0x101, 0x105]; + + //how many iterations (1 for des, 3 for triple des) + const iterations = key.length > 8 ? 3 : 1; //changed by Paul 16/6/2007 to use Triple DES for 9+ byte keys + //stores the return keys + const keys = new Array(32 * iterations); + //now define the left shifts which need to be done + const shifts = [0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0]; + //other variables + let lefttemp; + let righttemp; + let m = 0; + let n = 0; + let temp; + + for (let j = 0; j < iterations; j++) { + //either 1 or 3 iterations + let left = key[m++] << 24 | key[m++] << 16 | key[m++] << 8 | key[m++]; + let right = key[m++] << 24 | key[m++] << 16 | key[m++] << 8 | key[m++]; + + temp = (left >>> 4 ^ right) & 0x0f0f0f0f; + right ^= temp; + left ^= temp << 4; + temp = (right >>> -16 ^ left) & 0x0000ffff; + left ^= temp; + right ^= temp << -16; + temp = (left >>> 2 ^ right) & 0x33333333; + right ^= temp; + left ^= temp << 2; + temp = (right >>> -16 ^ left) & 0x0000ffff; + left ^= temp; + right ^= temp << -16; + temp = (left >>> 1 ^ right) & 0x55555555; + right ^= temp; + left ^= temp << 1; + temp = (right >>> 8 ^ left) & 0x00ff00ff; + left ^= temp; + right ^= temp << 8; + temp = (left >>> 1 ^ right) & 0x55555555; + right ^= temp; + left ^= temp << 1; + + //the right side needs to be shifted and to get the last four bits of the left side + temp = left << 8 | right >>> 20 & 0x000000f0; + //left needs to be put upside down + left = right << 24 | right << 8 & 0xff0000 | right >>> 8 & 0xff00 | right >>> 24 & 0xf0; + right = temp; + + //now go through and perform these shifts on the left and right keys + for (let i = 0; i < shifts.length; i++) { + //shift the keys either one or two bits to the left + if (shifts[i]) { + left = left << 2 | left >>> 26; + right = right << 2 | right >>> 26; + } else { + left = left << 1 | left >>> 27; + right = right << 1 | right >>> 27; + } + left &= -0xf; + right &= -0xf; + + //now apply PC-2, in such a way that E is easier when encrypting or decrypting + //this conversion will look like PC-2 except only the last 6 bits of each byte are used + //rather than 48 consecutive bits and the order of lines will be according to + //how the S selection functions will be applied: S2, S4, S6, S8, S1, S3, S5, S7 + lefttemp = pc2bytes0[left >>> 28] | pc2bytes1[left >>> 24 & 0xf] | pc2bytes2[left >>> 20 & 0xf] | pc2bytes3[left >>> 16 & 0xf] | pc2bytes4[left >>> 12 & 0xf] | pc2bytes5[left >>> 8 & 0xf] | pc2bytes6[left >>> 4 & 0xf]; + righttemp = pc2bytes7[right >>> 28] | pc2bytes8[right >>> 24 & 0xf] | pc2bytes9[right >>> 20 & 0xf] | pc2bytes10[right >>> 16 & 0xf] | pc2bytes11[right >>> 12 & 0xf] | pc2bytes12[right >>> 8 & 0xf] | pc2bytes13[right >>> 4 & 0xf]; + temp = (righttemp >>> 16 ^ lefttemp) & 0x0000ffff; + keys[n++] = lefttemp ^ temp; + keys[n++] = righttemp ^ temp << 16; + } + } //for each iterations + //return the keys we've created + return keys; +} //end of des_createKeys + + +function des_addPadding(message, padding) { + const padLength = 8 - message.length % 8; + + let pad; + if (padding === 2 && padLength < 8) { + //pad the message with spaces + pad = " ".charCodeAt(0); + } else if (padding === 1) { + //PKCS7 padding + pad = padLength; + } else if (!padding && padLength < 8) { + //pad the message out with null bytes + pad = 0; + } else if (padLength === 8) { + return message; + } else { + throw new Error('des: invalid padding'); + } + + const paddedMessage = new Uint8Array(message.length + padLength); + for (let i = 0; i < message.length; i++) { + paddedMessage[i] = message[i]; + } + for (let j = 0; j < padLength; j++) { + paddedMessage[message.length + j] = pad; + } + + return paddedMessage; +} + +function des_removePadding(message, padding) { + let padLength = null; + let pad; + if (padding === 2) { + // space padded + pad = " ".charCodeAt(0); + } else if (padding === 1) { + // PKCS7 + padLength = message[message.length - 1]; + } else if (!padding) { + // null padding + pad = 0; + } else { + throw new Error('des: invalid padding'); + } + + if (!padLength) { + padLength = 1; + while (message[message.length - padLength] === pad) { + padLength++; + } + padLength--; + } + + return message.subarray(0, message.length - padLength); +} + +// added by Recurity Labs + +function TripleDES(key) { + this.key = []; + + for (let i = 0; i < 3; i++) { + this.key.push(new Uint8Array(key.subarray(i * 8, i * 8 + 8))); + } + + this.encrypt = function (block) { + return des(des_createKeys(this.key[2]), des(des_createKeys(this.key[1]), des(des_createKeys(this.key[0]), block, true, 0, null, null), false, 0, null, null), true, 0, null, null); + }; +} + +TripleDES.keySize = TripleDES.prototype.keySize = 24; +TripleDES.blockSize = TripleDES.prototype.blockSize = 8; + +// This is "original" DES + +function DES(key) { + this.key = key; + + this.encrypt = function (block, padding) { + const keys = des_createKeys(this.key); + return des(keys, block, true, 0, null, padding); + }; + + this.decrypt = function (block, padding) { + const keys = des_createKeys(this.key); + return des(keys, block, false, 0, null, padding); + }; +} + +exports.default = { DES, TripleDES }; + +},{}],86:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _aes = require('./aes'); + +var _aes2 = _interopRequireDefault(_aes); + +var _des = require('./des.js'); + +var _des2 = _interopRequireDefault(_des); + +var _cast = require('./cast5'); + +var _cast2 = _interopRequireDefault(_cast); + +var _twofish = require('./twofish'); + +var _twofish2 = _interopRequireDefault(_twofish); + +var _blowfish = require('./blowfish'); + +var _blowfish2 = _interopRequireDefault(_blowfish); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = { + /** + * AES-128 encryption and decryption (ID 7) + * @function + * @param {String} key 128-bit key + * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} + * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} + * @returns {Object} + * @requires asmcrypto.js + */ + aes128: (0, _aes2.default)(128), + /** + * AES-128 Block Cipher (ID 8) + * @function + * @param {String} key 192-bit key + * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} + * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} + * @returns {Object} + * @requires asmcrypto.js + */ + aes192: (0, _aes2.default)(192), + /** + * AES-128 Block Cipher (ID 9) + * @function + * @param {String} key 256-bit key + * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} + * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} + * @returns {Object} + * @requires asmcrypto.js + */ + aes256: (0, _aes2.default)(256), + // Not in OpenPGP specifications + des: _des2.default.DES, + /** + * Triple DES Block Cipher (ID 2) + * @function + * @param {String} key 192-bit key + * @see {@link https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-67r2.pdf|NIST SP 800-67} + * @returns {Object} + */ + tripledes: _des2.default.TripleDES, + '3des': _des2.default.TripleDES, + /** + * CAST-128 Block Cipher (ID 3) + * @function + * @param {String} key 128-bit key + * @see {@link https://tools.ietf.org/html/rfc2144|The CAST-128 Encryption Algorithm} + * @returns {Object} + */ + cast5: _cast2.default, + /** + * Twofish Block Cipher (ID 10) + * @function + * @param {String} key 256-bit key + * @see {@link https://tools.ietf.org/html/rfc4880#ref-TWOFISH|TWOFISH} + * @returns {Object} + */ + twofish: _twofish2.default, + /** + * Blowfish Block Cipher (ID 4) + * @function + * @param {String} key 128-bit key + * @see {@link https://tools.ietf.org/html/rfc4880#ref-BLOWFISH|BLOWFISH} + * @returns {Object} + */ + blowfish: _blowfish2.default, + /** + * Not implemented + * @function + * @throws {Error} + */ + idea: function idea() { + throw new Error('IDEA symmetric-key algorithm not implemented'); + } +}; /** + * @fileoverview Symmetric cryptography functions + * @requires crypto/cipher/aes + * @requires crypto/cipher/des + * @requires crypto/cipher/cast5 + * @requires crypto/cipher/twofish + * @requires crypto/cipher/blowfish + * @module crypto/cipher + */ + +},{"./aes":82,"./blowfish":83,"./cast5":84,"./des.js":85,"./twofish":87}],87:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +/* eslint-disable no-mixed-operators, no-fallthrough */ + +/* Modified by Recurity Labs GmbH + * + * Cipher.js + * A block-cipher algorithm implementation on JavaScript + * See Cipher.readme.txt for further information. + * + * Copyright(c) 2009 Atsushi Oka [ http://oka.nu/ ] + * This script file is distributed under the LGPL + * + * ACKNOWLEDGMENT + * + * The main subroutines are written by Michiel van Everdingen. + * + * Michiel van Everdingen + * http://home.versatel.nl/MAvanEverdingen/index.html + * + * All rights for these routines are reserved to Michiel van Everdingen. + * + */ + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//Math +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +const MAXINT = 0xFFFFFFFF; + +function rotw(w, n) { + return (w << n | w >>> 32 - n) & MAXINT; +} + +function getW(a, i) { + return a[i] | a[i + 1] << 8 | a[i + 2] << 16 | a[i + 3] << 24; +} + +function setW(a, i, w) { + a.splice(i, 4, w & 0xFF, w >>> 8 & 0xFF, w >>> 16 & 0xFF, w >>> 24 & 0xFF); +} + +function getB(x, n) { + return x >>> n * 8 & 0xFF; +} + +// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Twofish +// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +function createTwofish() { + // + let keyBytes = null; + let dataBytes = null; + let dataOffset = -1; + // var dataLength = -1; + // var idx2 = -1; + // + + let tfsKey = []; + let tfsM = [[], [], [], []]; + + function tfsInit(key) { + keyBytes = key; + let i; + let a; + let b; + let c; + let d; + const meKey = []; + const moKey = []; + const inKey = []; + let kLen; + const sKey = []; + let f01; + let f5b; + let fef; + + const q0 = [[8, 1, 7, 13, 6, 15, 3, 2, 0, 11, 5, 9, 14, 12, 10, 4], [2, 8, 11, 13, 15, 7, 6, 14, 3, 1, 9, 4, 0, 10, 12, 5]]; + const q1 = [[14, 12, 11, 8, 1, 2, 3, 5, 15, 4, 10, 6, 7, 0, 9, 13], [1, 14, 2, 11, 4, 12, 3, 7, 6, 13, 10, 5, 15, 9, 0, 8]]; + const q2 = [[11, 10, 5, 14, 6, 13, 9, 0, 12, 8, 15, 3, 2, 4, 7, 1], [4, 12, 7, 5, 1, 6, 9, 10, 0, 14, 13, 8, 2, 11, 3, 15]]; + const q3 = [[13, 7, 15, 4, 1, 2, 6, 14, 9, 11, 3, 0, 8, 5, 12, 10], [11, 9, 5, 1, 12, 3, 13, 14, 6, 4, 7, 15, 2, 0, 8, 10]]; + const ror4 = [0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15]; + const ashx = [0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 5, 14, 7]; + const q = [[], []]; + const m = [[], [], [], []]; + + function ffm5b(x) { + return x ^ x >> 2 ^ [0, 90, 180, 238][x & 3]; + } + + function ffmEf(x) { + return x ^ x >> 1 ^ x >> 2 ^ [0, 238, 180, 90][x & 3]; + } + + function mdsRem(p, q) { + let i; + let t; + let u; + for (i = 0; i < 8; i++) { + t = q >>> 24; + q = q << 8 & MAXINT | p >>> 24; + p = p << 8 & MAXINT; + u = t << 1; + if (t & 128) { + u ^= 333; + } + q ^= t ^ u << 16; + u ^= t >>> 1; + if (t & 1) { + u ^= 166; + } + q ^= u << 24 | u << 8; + } + return q; + } + + function qp(n, x) { + const a = x >> 4; + const b = x & 15; + const c = q0[n][a ^ b]; + const d = q1[n][ror4[b] ^ ashx[a]]; + return q3[n][ror4[d] ^ ashx[c]] << 4 | q2[n][c ^ d]; + } + + function hFun(x, key) { + let a = getB(x, 0); + let b = getB(x, 1); + let c = getB(x, 2); + let d = getB(x, 3); + switch (kLen) { + case 4: + a = q[1][a] ^ getB(key[3], 0); + b = q[0][b] ^ getB(key[3], 1); + c = q[0][c] ^ getB(key[3], 2); + d = q[1][d] ^ getB(key[3], 3); + case 3: + a = q[1][a] ^ getB(key[2], 0); + b = q[1][b] ^ getB(key[2], 1); + c = q[0][c] ^ getB(key[2], 2); + d = q[0][d] ^ getB(key[2], 3); + case 2: + a = q[0][q[0][a] ^ getB(key[1], 0)] ^ getB(key[0], 0); + b = q[0][q[1][b] ^ getB(key[1], 1)] ^ getB(key[0], 1); + c = q[1][q[0][c] ^ getB(key[1], 2)] ^ getB(key[0], 2); + d = q[1][q[1][d] ^ getB(key[1], 3)] ^ getB(key[0], 3); + } + return m[0][a] ^ m[1][b] ^ m[2][c] ^ m[3][d]; + } + + keyBytes = keyBytes.slice(0, 32); + i = keyBytes.length; + while (i !== 16 && i !== 24 && i !== 32) { + keyBytes[i++] = 0; + } + + for (i = 0; i < keyBytes.length; i += 4) { + inKey[i >> 2] = getW(keyBytes, i); + } + for (i = 0; i < 256; i++) { + q[0][i] = qp(0, i); + q[1][i] = qp(1, i); + } + for (i = 0; i < 256; i++) { + f01 = q[1][i]; + f5b = ffm5b(f01); + fef = ffmEf(f01); + m[0][i] = f01 + (f5b << 8) + (fef << 16) + (fef << 24); + m[2][i] = f5b + (fef << 8) + (f01 << 16) + (fef << 24); + f01 = q[0][i]; + f5b = ffm5b(f01); + fef = ffmEf(f01); + m[1][i] = fef + (fef << 8) + (f5b << 16) + (f01 << 24); + m[3][i] = f5b + (f01 << 8) + (fef << 16) + (f5b << 24); + } + + kLen = inKey.length / 2; + for (i = 0; i < kLen; i++) { + a = inKey[i + i]; + meKey[i] = a; + b = inKey[i + i + 1]; + moKey[i] = b; + sKey[kLen - i - 1] = mdsRem(a, b); + } + for (i = 0; i < 40; i += 2) { + a = 0x1010101 * i; + b = a + 0x1010101; + a = hFun(a, meKey); + b = rotw(hFun(b, moKey), 8); + tfsKey[i] = a + b & MAXINT; + tfsKey[i + 1] = rotw(a + 2 * b, 9); + } + for (i = 0; i < 256; i++) { + a = b = c = d = i; + switch (kLen) { + case 4: + a = q[1][a] ^ getB(sKey[3], 0); + b = q[0][b] ^ getB(sKey[3], 1); + c = q[0][c] ^ getB(sKey[3], 2); + d = q[1][d] ^ getB(sKey[3], 3); + case 3: + a = q[1][a] ^ getB(sKey[2], 0); + b = q[1][b] ^ getB(sKey[2], 1); + c = q[0][c] ^ getB(sKey[2], 2); + d = q[0][d] ^ getB(sKey[2], 3); + case 2: + tfsM[0][i] = m[0][q[0][q[0][a] ^ getB(sKey[1], 0)] ^ getB(sKey[0], 0)]; + tfsM[1][i] = m[1][q[0][q[1][b] ^ getB(sKey[1], 1)] ^ getB(sKey[0], 1)]; + tfsM[2][i] = m[2][q[1][q[0][c] ^ getB(sKey[1], 2)] ^ getB(sKey[0], 2)]; + tfsM[3][i] = m[3][q[1][q[1][d] ^ getB(sKey[1], 3)] ^ getB(sKey[0], 3)]; + } + } + } + + function tfsG0(x) { + return tfsM[0][getB(x, 0)] ^ tfsM[1][getB(x, 1)] ^ tfsM[2][getB(x, 2)] ^ tfsM[3][getB(x, 3)]; + } + + function tfsG1(x) { + return tfsM[0][getB(x, 3)] ^ tfsM[1][getB(x, 0)] ^ tfsM[2][getB(x, 1)] ^ tfsM[3][getB(x, 2)]; + } + + function tfsFrnd(r, blk) { + let a = tfsG0(blk[0]); + let b = tfsG1(blk[1]); + blk[2] = rotw(blk[2] ^ a + b + tfsKey[4 * r + 8] & MAXINT, 31); + blk[3] = rotw(blk[3], 1) ^ a + 2 * b + tfsKey[4 * r + 9] & MAXINT; + a = tfsG0(blk[2]); + b = tfsG1(blk[3]); + blk[0] = rotw(blk[0] ^ a + b + tfsKey[4 * r + 10] & MAXINT, 31); + blk[1] = rotw(blk[1], 1) ^ a + 2 * b + tfsKey[4 * r + 11] & MAXINT; + } + + function tfsIrnd(i, blk) { + let a = tfsG0(blk[0]); + let b = tfsG1(blk[1]); + blk[2] = rotw(blk[2], 1) ^ a + b + tfsKey[4 * i + 10] & MAXINT; + blk[3] = rotw(blk[3] ^ a + 2 * b + tfsKey[4 * i + 11] & MAXINT, 31); + a = tfsG0(blk[2]); + b = tfsG1(blk[3]); + blk[0] = rotw(blk[0], 1) ^ a + b + tfsKey[4 * i + 8] & MAXINT; + blk[1] = rotw(blk[1] ^ a + 2 * b + tfsKey[4 * i + 9] & MAXINT, 31); + } + + function tfsClose() { + tfsKey = []; + tfsM = [[], [], [], []]; + } + + function tfsEncrypt(data, offset) { + dataBytes = data; + dataOffset = offset; + const blk = [getW(dataBytes, dataOffset) ^ tfsKey[0], getW(dataBytes, dataOffset + 4) ^ tfsKey[1], getW(dataBytes, dataOffset + 8) ^ tfsKey[2], getW(dataBytes, dataOffset + 12) ^ tfsKey[3]]; + for (let j = 0; j < 8; j++) { + tfsFrnd(j, blk); + } + setW(dataBytes, dataOffset, blk[2] ^ tfsKey[4]); + setW(dataBytes, dataOffset + 4, blk[3] ^ tfsKey[5]); + setW(dataBytes, dataOffset + 8, blk[0] ^ tfsKey[6]); + setW(dataBytes, dataOffset + 12, blk[1] ^ tfsKey[7]); + dataOffset += 16; + return dataBytes; + } + + function tfsDecrypt(data, offset) { + dataBytes = data; + dataOffset = offset; + const blk = [getW(dataBytes, dataOffset) ^ tfsKey[4], getW(dataBytes, dataOffset + 4) ^ tfsKey[5], getW(dataBytes, dataOffset + 8) ^ tfsKey[6], getW(dataBytes, dataOffset + 12) ^ tfsKey[7]]; + for (let j = 7; j >= 0; j--) { + tfsIrnd(j, blk); + } + setW(dataBytes, dataOffset, blk[2] ^ tfsKey[0]); + setW(dataBytes, dataOffset + 4, blk[3] ^ tfsKey[1]); + setW(dataBytes, dataOffset + 8, blk[0] ^ tfsKey[2]); + setW(dataBytes, dataOffset + 12, blk[1] ^ tfsKey[3]); + dataOffset += 16; + } + + // added by Recurity Labs + + function tfsFinal() { + return dataBytes; + } + + return { + name: "twofish", + blocksize: 128 / 8, + open: tfsInit, + close: tfsClose, + encrypt: tfsEncrypt, + decrypt: tfsDecrypt, + // added by Recurity Labs + finalize: tfsFinal + }; +} + +// added by Recurity Labs + +function TF(key) { + this.tf = createTwofish(); + this.tf.open(Array.from(key), 0); + + this.encrypt = function (block) { + return this.tf.encrypt(Array.from(block), 0); + }; +} + +TF.keySize = TF.prototype.keySize = 32; +TF.blockSize = TF.prototype.blockSize = 16; + +exports.default = TF; + +},{}],88:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _cbc = require('asmcrypto.js/dist_es5/aes/cbc'); + +var _util = require('../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * @fileoverview This module implements AES-CMAC on top of + * native AES-CBC using either the WebCrypto API or Node.js' crypto API. + * @requires asmcrypto.js + * @requires util + * @module crypto/cmac + */ + +const webCrypto = _util2.default.getWebCrypto(); +const nodeCrypto = _util2.default.getNodeCrypto(); +const Buffer = _util2.default.getNodeBuffer(); + +/** + * This implementation of CMAC is based on the description of OMAC in + * http://web.cs.ucdavis.edu/~rogaway/papers/eax.pdf. As per that + * document: + * + * We have made a small modification to the OMAC algorithm as it was + * originally presented, changing one of its two constants. + * Specifically, the constant 4 at line 85 was the constant 1/2 (the + * multiplicative inverse of 2) in the original definition of OMAC [14]. + * The OMAC authors indicate that they will promulgate this modification + * [15], which slightly simplifies implementations. + */ + +const blockLength = 16; + +/** + * xor `padding` into the end of `data`. This function implements "the + * operation xor→ [which] xors the shorter string into the end of longer + * one". Since data is always as least as long as padding, we can + * simplify the implementation. + * @param {Uint8Array} data + * @param {Uint8Array} padding + */ +function rightXorMut(data, padding) { + const offset = data.length - blockLength; + for (let i = 0; i < blockLength; i++) { + data[i + offset] ^= padding[i]; + } + return data; +} + +function pad(data, padding, padding2) { + // if |M| in {n, 2n, 3n, ...} + if (data.length && data.length % blockLength === 0) { + // then return M xor→ B, + return rightXorMut(data, padding); + } + // else return (M || 10^(n−1−(|M| mod n))) xor→ P + const padded = new Uint8Array(data.length + (blockLength - data.length % blockLength)); + padded.set(data); + padded[data.length] = 0b10000000; + return rightXorMut(padded, padding2); +} + +const zeroBlock = new Uint8Array(blockLength); + +exports.default = async function CMAC(key) { + const cbc = await CBC(key); + + // L ← E_K(0^n); B ← 2L; P ← 4L + const padding = _util2.default.double((await cbc(zeroBlock))); + const padding2 = _util2.default.double(padding); + + return async function (data) { + // return CBC_K(pad(M; B, P)) + return (await cbc(pad(data, padding, padding2))).subarray(-blockLength); + }; +}; + +async function CBC(key) { + if (_util2.default.getWebCrypto() && key.length !== 24) { + // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support + key = await webCrypto.importKey('raw', key, { name: 'AES-CBC', length: key.length * 8 }, false, ['encrypt']); + return async function (pt) { + const ct = await webCrypto.encrypt({ name: 'AES-CBC', iv: zeroBlock, length: blockLength * 8 }, key, pt); + return new Uint8Array(ct).subarray(0, ct.byteLength - blockLength); + }; + } + if (_util2.default.getNodeCrypto()) { + // Node crypto library + key = new Buffer(key); + return async function (pt) { + pt = new Buffer(pt); + const en = new nodeCrypto.createCipheriv('aes-' + key.length * 8 + '-cbc', key, zeroBlock); + const ct = en.update(pt); + return new Uint8Array(ct); + }; + } + // asm.js fallback + return async function (pt) { + return _cbc.AES_CBC.encrypt(pt, key, false, zeroBlock); + }; +} + +},{"../util":152,"asmcrypto.js/dist_es5/aes/cbc":4}],89:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _bn = require('bn.js'); + +var _bn2 = _interopRequireDefault(_bn); + +var _public_key = require('./public_key'); + +var _public_key2 = _interopRequireDefault(_public_key); + +var _cipher = require('./cipher'); + +var _cipher2 = _interopRequireDefault(_cipher); + +var _random = require('./random'); + +var _random2 = _interopRequireDefault(_random); + +var _ecdh_symkey = require('../type/ecdh_symkey'); + +var _ecdh_symkey2 = _interopRequireDefault(_ecdh_symkey); + +var _kdf_params = require('../type/kdf_params'); + +var _kdf_params2 = _interopRequireDefault(_kdf_params); + +var _mpi = require('../type/mpi'); + +var _mpi2 = _interopRequireDefault(_mpi); + +var _oid = require('../type/oid'); + +var _oid2 = _interopRequireDefault(_oid); + +var _enums = require('../enums'); + +var _enums2 = _interopRequireDefault(_enums); + +var _util = require('../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +// The GPG4Browsers crypto interface + +/** + * @fileoverview Provides functions for asymmetric encryption and decryption as + * well as key generation and parameter handling for all public-key cryptosystems. + * @requires bn.js + * @requires crypto/public_key + * @requires crypto/cipher + * @requires crypto/random + * @requires type/ecdh_symkey + * @requires type/kdf_params + * @requires type/mpi + * @requires type/oid + * @requires enums + * @requires util + * @module crypto/crypto + */ + +function constructParams(types, data) { + return types.map(function (type, i) { + if (data && data[i]) { + return new type(data[i]); + } + return new type(); + }); +} + +exports.default = { + /** + * Encrypts data using specified algorithm and public key parameters. + * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} for public key algorithms. + * @param {module:enums.publicKey} algo Public key algorithm + * @param {Array} pub_params Algorithm-specific public key parameters + * @param {module:type/mpi} data Data to be encrypted as MPI + * @param {String} fingerprint Recipient fingerprint + * @returns {Array} encrypted session key parameters + * @async + */ + publicKeyEncrypt: async function publicKeyEncrypt(algo, pub_params, data, fingerprint) { + const types = this.getEncSessionKeyParamTypes(algo); + switch (algo) { + case _enums2.default.publicKey.rsa_encrypt: + case _enums2.default.publicKey.rsa_encrypt_sign: + { + const m = data.toBN(); + const n = pub_params[0].toBN(); + const e = pub_params[1].toBN(); + const res = await _public_key2.default.rsa.encrypt(m, n, e); + return constructParams(types, [res]); + } + case _enums2.default.publicKey.elgamal: + { + const m = data.toBN(); + const p = pub_params[0].toBN(); + const g = pub_params[1].toBN(); + const y = pub_params[2].toBN(); + const res = await _public_key2.default.elgamal.encrypt(m, p, g, y); + return constructParams(types, [res.c1, res.c2]); + } + case _enums2.default.publicKey.ecdh: + { + const oid = pub_params[0]; + const Q = pub_params[1].toUint8Array(); + const kdf_params = pub_params[2]; + + var _ref = await _public_key2.default.elliptic.ecdh.encrypt(oid, kdf_params.cipher, kdf_params.hash, data, Q, fingerprint); + + const V = _ref.publicKey, + C = _ref.wrappedKey; + + return constructParams(types, [new _bn2.default(V), C]); + } + default: + return []; + } + }, + + /** + * Decrypts data using specified algorithm and private key parameters. + * See {@link https://tools.ietf.org/html/rfc4880#section-5.5.3|RFC 4880 5.5.3} + * @param {module:enums.publicKey} algo Public key algorithm + * @param {Array} key_params Algorithm-specific public, private key parameters + * @param {Array} + data_params encrypted session key parameters + * @param {String} fingerprint Recipient fingerprint + * @returns {BN} A BN containing the decrypted data + * @async + */ + publicKeyDecrypt: async function publicKeyDecrypt(algo, key_params, data_params, fingerprint) { + switch (algo) { + case _enums2.default.publicKey.rsa_encrypt_sign: + case _enums2.default.publicKey.rsa_encrypt: + { + const c = data_params[0].toBN(); + const n = key_params[0].toBN(); // n = pq + const e = key_params[1].toBN(); + const d = key_params[2].toBN(); // de = 1 mod (p-1)(q-1) + const p = key_params[3].toBN(); + const q = key_params[4].toBN(); + const u = key_params[5].toBN(); // p^-1 mod q + return _public_key2.default.rsa.decrypt(c, n, e, d, p, q, u); + } + case _enums2.default.publicKey.elgamal: + { + const c1 = data_params[0].toBN(); + const c2 = data_params[1].toBN(); + const p = key_params[0].toBN(); + const x = key_params[3].toBN(); + return _public_key2.default.elgamal.decrypt(c1, c2, p, x); + } + case _enums2.default.publicKey.ecdh: + { + const oid = key_params[0]; + const kdf_params = key_params[2]; + const V = data_params[0].toUint8Array(); + const C = data_params[1].data; + const Q = key_params[1].toUint8Array(); + const d = key_params[3].toUint8Array(); + return _public_key2.default.elliptic.ecdh.decrypt(oid, kdf_params.cipher, kdf_params.hash, V, C, Q, d, fingerprint); + } + default: + throw new Error('Invalid public key encryption algorithm.'); + } + }, + + /** Returns the types comprising the private key of an algorithm + * @param {String} algo The public key algorithm + * @returns {Array} The array of types + */ + getPrivKeyParamTypes: function getPrivKeyParamTypes(algo) { + switch (algo) { + // Algorithm-Specific Fields for RSA secret keys: + // - multiprecision integer (MPI) of RSA secret exponent d. + // - MPI of RSA secret prime value p. + // - MPI of RSA secret prime value q (p < q). + // - MPI of u, the multiplicative inverse of p, mod q. + case _enums2.default.publicKey.rsa_encrypt: + case _enums2.default.publicKey.rsa_encrypt_sign: + case _enums2.default.publicKey.rsa_sign: + return [_mpi2.default, _mpi2.default, _mpi2.default, _mpi2.default]; + // Algorithm-Specific Fields for Elgamal secret keys: + // - MPI of Elgamal secret exponent x. + case _enums2.default.publicKey.elgamal: + return [_mpi2.default]; + // Algorithm-Specific Fields for DSA secret keys: + // - MPI of DSA secret exponent x. + case _enums2.default.publicKey.dsa: + return [_mpi2.default]; + // Algorithm-Specific Fields for ECDSA or ECDH secret keys: + // - MPI of an integer representing the secret key. + case _enums2.default.publicKey.ecdh: + case _enums2.default.publicKey.ecdsa: + case _enums2.default.publicKey.eddsa: + return [_mpi2.default]; + default: + throw new Error('Invalid public key encryption algorithm.'); + } + }, + + /** Returns the types comprising the public key of an algorithm + * @param {String} algo The public key algorithm + * @returns {Array} The array of types + */ + getPubKeyParamTypes: function getPubKeyParamTypes(algo) { + switch (algo) { + // Algorithm-Specific Fields for RSA public keys: + // - a multiprecision integer (MPI) of RSA public modulus n; + // - an MPI of RSA public encryption exponent e. + case _enums2.default.publicKey.rsa_encrypt: + case _enums2.default.publicKey.rsa_encrypt_sign: + case _enums2.default.publicKey.rsa_sign: + return [_mpi2.default, _mpi2.default]; + // Algorithm-Specific Fields for Elgamal public keys: + // - MPI of Elgamal prime p; + // - MPI of Elgamal group generator g; + // - MPI of Elgamal public key value y (= g**x mod p where x is secret). + case _enums2.default.publicKey.elgamal: + return [_mpi2.default, _mpi2.default, _mpi2.default]; + // Algorithm-Specific Fields for DSA public keys: + // - MPI of DSA prime p; + // - MPI of DSA group order q (q is a prime divisor of p-1); + // - MPI of DSA group generator g; + // - MPI of DSA public-key value y (= g**x mod p where x is secret). + case _enums2.default.publicKey.dsa: + return [_mpi2.default, _mpi2.default, _mpi2.default, _mpi2.default]; + // Algorithm-Specific Fields for ECDSA/EdDSA public keys: + // - OID of curve; + // - MPI of EC point representing public key. + case _enums2.default.publicKey.ecdsa: + case _enums2.default.publicKey.eddsa: + return [_oid2.default, _mpi2.default]; + // Algorithm-Specific Fields for ECDH public keys: + // - OID of curve; + // - MPI of EC point representing public key. + // - KDF: variable-length field containing KDF parameters. + case _enums2.default.publicKey.ecdh: + return [_oid2.default, _mpi2.default, _kdf_params2.default]; + default: + throw new Error('Invalid public key encryption algorithm.'); + } + }, + + /** Returns the types comprising the encrypted session key of an algorithm + * @param {String} algo The public key algorithm + * @returns {Array} The array of types + */ + getEncSessionKeyParamTypes: function getEncSessionKeyParamTypes(algo) { + switch (algo) { + // Algorithm-Specific Fields for RSA encrypted session keys: + // - MPI of RSA encrypted value m**e mod n. + case _enums2.default.publicKey.rsa_encrypt: + case _enums2.default.publicKey.rsa_encrypt_sign: + return [_mpi2.default]; + + // Algorithm-Specific Fields for Elgamal encrypted session keys: + // - MPI of Elgamal value g**k mod p + // - MPI of Elgamal value m * y**k mod p + case _enums2.default.publicKey.elgamal: + return [_mpi2.default, _mpi2.default]; + // Algorithm-Specific Fields for ECDH encrypted session keys: + // - MPI containing the ephemeral key used to establish the shared secret + // - ECDH Symmetric Key + case _enums2.default.publicKey.ecdh: + return [_mpi2.default, _ecdh_symkey2.default]; + default: + throw new Error('Invalid public key encryption algorithm.'); + } + }, + + /** Generate algorithm-specific key parameters + * @param {String} algo The public key algorithm + * @param {Integer} bits Bit length for RSA keys + * @param {module:type/oid} oid Object identifier for ECC keys + * @returns {Array} The array of parameters + * @async + */ + generateParams: function generateParams(algo, bits, oid) { + const types = [].concat(this.getPubKeyParamTypes(algo), this.getPrivKeyParamTypes(algo)); + switch (algo) { + case _enums2.default.publicKey.rsa_encrypt: + case _enums2.default.publicKey.rsa_encrypt_sign: + case _enums2.default.publicKey.rsa_sign: + { + return _public_key2.default.rsa.generate(bits, "10001").then(function (keyObject) { + return constructParams(types, [keyObject.n, keyObject.e, keyObject.d, keyObject.p, keyObject.q, keyObject.u]); + }); + } + case _enums2.default.publicKey.dsa: + case _enums2.default.publicKey.elgamal: + throw new Error('Unsupported algorithm for key generation.'); + case _enums2.default.publicKey.ecdsa: + case _enums2.default.publicKey.eddsa: + return _public_key2.default.elliptic.generate(oid).then(function (keyObject) { + return constructParams(types, [keyObject.oid, keyObject.Q, keyObject.d]); + }); + case _enums2.default.publicKey.ecdh: + return _public_key2.default.elliptic.generate(oid).then(function (keyObject) { + return constructParams(types, [keyObject.oid, keyObject.Q, [keyObject.hash, keyObject.cipher], keyObject.d]); + }); + default: + throw new Error('Invalid public key algorithm.'); + } + }, + + /** + * Generates a random byte prefix for the specified algorithm + * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. + * @param {module:enums.symmetric} algo Symmetric encryption algorithm + * @returns {Uint8Array} Random bytes with length equal to the block size of the cipher, plus the last two bytes repeated. + * @async + */ + getPrefixRandom: async function getPrefixRandom(algo) { + const prefixrandom = await _random2.default.getRandomBytes(_cipher2.default[algo].blockSize); + const repeat = new Uint8Array([prefixrandom[prefixrandom.length - 2], prefixrandom[prefixrandom.length - 1]]); + return _util2.default.concat([prefixrandom, repeat]); + }, + + /** + * Generating a session key for the specified symmetric algorithm + * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. + * @param {module:enums.symmetric} algo Symmetric encryption algorithm + * @returns {Uint8Array} Random bytes as a string to be used as a key + * @async + */ + generateSessionKey: function generateSessionKey(algo) { + return _random2.default.getRandomBytes(_cipher2.default[algo].keySize); + }, + + constructParams: constructParams +}; + +},{"../enums":113,"../type/ecdh_symkey":146,"../type/kdf_params":147,"../type/mpi":149,"../type/oid":150,"../util":152,"./cipher":86,"./public_key":106,"./random":109,"bn.js":16}],90:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); // OpenPGP.js - An OpenPGP implementation in javascript +// Copyright (C) 2018 ProtonTech AG +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @fileoverview This module implements AES-EAX en/decryption on top of + * native AES-CTR using either the WebCrypto API or Node.js' crypto API. + * @requires asmcrypto.js + * @requires crypto/cmac + * @requires util + * @module crypto/eax + */ + +var _ctr = require('asmcrypto.js/dist_es5/aes/ctr'); + +var _cmac = require('./cmac'); + +var _cmac2 = _interopRequireDefault(_cmac); + +var _util = require('../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const webCrypto = _util2.default.getWebCrypto(); +const nodeCrypto = _util2.default.getNodeCrypto(); +const Buffer = _util2.default.getNodeBuffer(); + +const blockLength = 16; +const ivLength = blockLength; +const tagLength = blockLength; + +const zero = new Uint8Array(blockLength); +const one = new Uint8Array(blockLength);one[blockLength - 1] = 1; +const two = new Uint8Array(blockLength);two[blockLength - 1] = 2; + +async function OMAC(key) { + const cmac = await (0, _cmac2.default)(key); + return function (t, message) { + return cmac(_util2.default.concatUint8Array([t, message])); + }; +} + +async function CTR(key) { + if (_util2.default.getWebCrypto() && key.length !== 24 && // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support + navigator.userAgent.indexOf('Edge') === -1) { + key = await webCrypto.importKey('raw', key, { name: 'AES-CTR', length: key.length * 8 }, false, ['encrypt']); + return async function (pt, iv) { + const ct = await webCrypto.encrypt({ name: 'AES-CTR', counter: iv, length: blockLength * 8 }, key, pt); + return new Uint8Array(ct); + }; + } + if (_util2.default.getNodeCrypto()) { + // Node crypto library + key = new Buffer(key); + return async function (pt, iv) { + pt = new Buffer(pt); + iv = new Buffer(iv); + const en = new nodeCrypto.createCipheriv('aes-' + key.length * 8 + '-ctr', key, iv); + const ct = Buffer.concat([en.update(pt), en.final()]); + return new Uint8Array(ct); + }; + } + // asm.js fallback + return async function (pt, iv) { + return _ctr.AES_CTR.encrypt(pt, key, iv); + }; +} + +/** + * Class to en/decrypt using EAX mode. + * @param {String} cipher The symmetric cipher algorithm to use e.g. 'aes128' + * @param {Uint8Array} key The encryption key + */ +async function EAX(cipher, key) { + if (cipher.substr(0, 3) !== 'aes') { + throw new Error('EAX mode supports only AES cipher'); + } + + var _ref = await Promise.all([OMAC(key), CTR(key)]), + _ref2 = _slicedToArray(_ref, 2); + + const omac = _ref2[0], + ctr = _ref2[1]; + + + return { + /** + * Encrypt plaintext input. + * @param {Uint8Array} plaintext The cleartext input to be encrypted + * @param {Uint8Array} nonce The nonce (16 bytes) + * @param {Uint8Array} adata Associated data to sign + * @returns {Promise} The ciphertext output + */ + encrypt: async function encrypt(plaintext, nonce, adata) { + var _ref3 = await Promise.all([omac(zero, nonce), omac(one, adata)]), + _ref4 = _slicedToArray(_ref3, 2); + + const omacNonce = _ref4[0], + omacAdata = _ref4[1]; + + const ciphered = await ctr(plaintext, omacNonce); + const omacCiphered = await omac(two, ciphered); + const tag = omacCiphered; // Assumes that omac(*).length === tagLength. + for (let i = 0; i < tagLength; i++) { + tag[i] ^= omacAdata[i] ^ omacNonce[i]; + } + return _util2.default.concatUint8Array([ciphered, tag]); + }, + + /** + * Decrypt ciphertext input. + * @param {Uint8Array} ciphertext The ciphertext input to be decrypted + * @param {Uint8Array} nonce The nonce (16 bytes) + * @param {Uint8Array} adata Associated data to verify + * @returns {Promise} The plaintext output + */ + decrypt: async function decrypt(ciphertext, nonce, adata) { + if (ciphertext.length < tagLength) throw new Error('Invalid EAX ciphertext'); + const ciphered = ciphertext.subarray(0, -tagLength); + const ctTag = ciphertext.subarray(-tagLength); + + var _ref5 = await Promise.all([omac(zero, nonce), omac(one, adata), omac(two, ciphered)]), + _ref6 = _slicedToArray(_ref5, 3); + + const omacNonce = _ref6[0], + omacAdata = _ref6[1], + omacCiphered = _ref6[2]; + + const tag = omacCiphered; // Assumes that omac(*).length === tagLength. + for (let i = 0; i < tagLength; i++) { + tag[i] ^= omacAdata[i] ^ omacNonce[i]; + } + if (!_util2.default.equalsUint8Array(ctTag, tag)) throw new Error('Authentication tag mismatch'); + const plaintext = await ctr(ciphered, omacNonce); + return plaintext; + } + }; +} + +/** + * Get EAX nonce as defined by {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.1|RFC4880bis-04, section 5.16.1}. + * @param {Uint8Array} iv The initialization vector (16 bytes) + * @param {Uint8Array} chunkIndex The chunk index (8 bytes) + */ +EAX.getNonce = function (iv, chunkIndex) { + const nonce = iv.slice(); + for (let i = 0; i < chunkIndex.length; i++) { + nonce[8 + i] ^= chunkIndex[i]; + } + return nonce; +}; + +EAX.blockLength = blockLength; +EAX.ivLength = ivLength; +EAX.tagLength = tagLength; + +exports.default = EAX; + +},{"../util":152,"./cmac":88,"asmcrypto.js/dist_es5/aes/ctr":6}],91:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _gcm = require('asmcrypto.js/dist_es5/aes/gcm'); + +var _util = require('../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// OpenPGP.js - An OpenPGP implementation in javascript +// Copyright (C) 2016 Tankred Hase +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @fileoverview This module wraps native AES-GCM en/decryption for both + * the WebCrypto api as well as node.js' crypto api. + * @requires asmcrypto.js + * @requires util + * @module crypto/gcm + */ + +const webCrypto = _util2.default.getWebCrypto(); // no GCM support in IE11, Safari 9 +const nodeCrypto = _util2.default.getNodeCrypto(); +const Buffer = _util2.default.getNodeBuffer(); + +const blockLength = 16; +const ivLength = 12; // size of the IV in bytes +const tagLength = 16; // size of the tag in bytes +const ALGO = 'AES-GCM'; + +/** + * Class to en/decrypt using GCM mode. + * @param {String} cipher The symmetric cipher algorithm to use e.g. 'aes128' + * @param {Uint8Array} key The encryption key + */ +async function GCM(cipher, key) { + if (cipher.substr(0, 3) !== 'aes') { + throw new Error('GCM mode supports only AES cipher'); + } + + if (_util2.default.getWebCrypto() && key.length !== 24) { + // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support + const _key = await webCrypto.importKey('raw', key, { name: ALGO }, false, ['encrypt', 'decrypt']); + + return { + encrypt: async function encrypt(pt, iv, adata = new Uint8Array()) { + if (!pt.length || + // iOS does not support GCM-en/decrypting empty messages + // Also, synchronous en/decryption might be faster in this case. + !adata.length && navigator.userAgent.indexOf('Edge') !== -1 + // Edge does not support GCM-en/decrypting without ADATA + ) { + return _gcm.AES_GCM.encrypt(pt, key, iv, adata); + } + const ct = await webCrypto.encrypt({ name: ALGO, iv, additionalData: adata, tagLength: tagLength * 8 }, _key, pt); + return new Uint8Array(ct); + }, + + decrypt: async function decrypt(ct, iv, adata = new Uint8Array()) { + if (ct.length === tagLength || + // iOS does not support GCM-en/decrypting empty messages + // Also, synchronous en/decryption might be faster in this case. + !adata.length && navigator.userAgent.indexOf('Edge') !== -1 + // Edge does not support GCM-en/decrypting without ADATA + ) { + return _gcm.AES_GCM.decrypt(ct, key, iv, adata); + } + const pt = await webCrypto.decrypt({ name: ALGO, iv, additionalData: adata, tagLength: tagLength * 8 }, _key, ct); + return new Uint8Array(pt); + } + }; + } + + if (_util2.default.getNodeCrypto()) { + // Node crypto library + key = new Buffer(key); + + return { + encrypt: async function encrypt(pt, iv, adata = new Uint8Array()) { + pt = new Buffer(pt); + iv = new Buffer(iv); + adata = new Buffer(adata); + const en = new nodeCrypto.createCipheriv('aes-' + key.length * 8 + '-gcm', key, iv); + en.setAAD(adata); + const ct = Buffer.concat([en.update(pt), en.final(), en.getAuthTag()]); // append auth tag to ciphertext + return new Uint8Array(ct); + }, + + decrypt: async function decrypt(ct, iv, adata = new Uint8Array()) { + ct = new Buffer(ct); + iv = new Buffer(iv); + adata = new Buffer(adata); + const de = new nodeCrypto.createDecipheriv('aes-' + key.length * 8 + '-gcm', key, iv); + de.setAAD(adata); + de.setAuthTag(ct.slice(ct.length - tagLength, ct.length)); // read auth tag at end of ciphertext + const pt = Buffer.concat([de.update(ct.slice(0, ct.length - tagLength)), de.final()]); + return new Uint8Array(pt); + } + }; + } + + return { + encrypt: async function encrypt(pt, iv, adata) { + return _gcm.AES_GCM.encrypt(pt, key, iv, adata); + }, + + decrypt: async function decrypt(ct, iv, adata) { + return _gcm.AES_GCM.decrypt(ct, key, iv, adata); + } + }; +} + +/** + * Get GCM nonce. Note: this operation is not defined by the standard. + * A future version of the standard may define GCM mode differently, + * hopefully under a different ID (we use Private/Experimental algorithm + * ID 100) so that we can maintain backwards compatibility. + * @param {Uint8Array} iv The initialization vector (12 bytes) + * @param {Uint8Array} chunkIndex The chunk index (8 bytes) + */ +GCM.getNonce = function (iv, chunkIndex) { + const nonce = iv.slice(); + for (let i = 0; i < chunkIndex.length; i++) { + nonce[4 + i] ^= chunkIndex[i]; + } + return nonce; +}; + +GCM.blockLength = blockLength; +GCM.ivLength = ivLength; +GCM.tagLength = tagLength; + +exports.default = GCM; + +},{"../util":152,"asmcrypto.js/dist_es5/aes/gcm":8}],92:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _sha = require('asmcrypto.js/dist_es5/hash/sha1/sha1'); + +var _sha2 = require('asmcrypto.js/dist_es5/hash/sha256/sha256'); + +var _ = require('hash.js/lib/hash/sha/224'); + +var _2 = _interopRequireDefault(_); + +var _3 = require('hash.js/lib/hash/sha/384'); + +var _4 = _interopRequireDefault(_3); + +var _5 = require('hash.js/lib/hash/sha/512'); + +var _6 = _interopRequireDefault(_5); + +var _ripemd = require('hash.js/lib/hash/ripemd'); + +var _webStreamTools = require('web-stream-tools'); + +var _webStreamTools2 = _interopRequireDefault(_webStreamTools); + +var _md = require('./md5'); + +var _md2 = _interopRequireDefault(_md); + +var _config = require('../../config'); + +var _config2 = _interopRequireDefault(_config); + +var _util = require('../../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * @fileoverview Provides an interface to hashing functions available in Node.js or external libraries. + * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} + * @see {@link https://github.com/indutny/hash.js|hash.js} + * @requires asmcrypto.js + * @requires hash.js + * @requires web-stream-tools + * @requires crypto/hash/md5 + * @requires config + * @requires util + * @module crypto/hash + */ + +const webCrypto = _util2.default.getWebCrypto(); +const nodeCrypto = _util2.default.getNodeCrypto(); +const Buffer = _util2.default.getNodeBuffer(); + +function node_hash(type) { + return async function (data) { + const shasum = nodeCrypto.createHash(type); + return _webStreamTools2.default.transform(data, value => { + shasum.update(new Buffer(value)); + }, () => new Uint8Array(shasum.digest())); + }; +} + +function hashjs_hash(hash, webCryptoHash) { + return async function (data) { + if (!_util2.default.isStream(data) && webCrypto && webCryptoHash && data.length >= _config2.default.min_bytes_for_web_crypto) { + return new Uint8Array((await webCrypto.digest(webCryptoHash, data))); + } + const hashInstance = hash(); + return _webStreamTools2.default.transform(data, value => { + hashInstance.update(value); + }, () => new Uint8Array(hashInstance.digest())); + }; +} + +function asmcrypto_hash(hash, webCryptoHash) { + return async function (data) { + if (_util2.default.isStream(data)) { + const hashInstance = new hash(); + return _webStreamTools2.default.transform(data, value => { + hashInstance.process(value); + }, () => hashInstance.finish().result); + } else if (webCrypto && webCryptoHash && data.length >= _config2.default.min_bytes_for_web_crypto) { + return new Uint8Array((await webCrypto.digest(webCryptoHash, data))); + } else { + return hash.bytes(data); + } + }; +} + +let hash_fns; +if (nodeCrypto) { + // Use Node native crypto for all hash functions + hash_fns = { + md5: node_hash('md5'), + sha1: node_hash('sha1'), + sha224: node_hash('sha224'), + sha256: node_hash('sha256'), + sha384: node_hash('sha384'), + sha512: node_hash('sha512'), + ripemd: node_hash('ripemd160') + }; +} else { + // Use JS fallbacks + hash_fns = { + md5: _md2.default, + sha1: asmcrypto_hash(_sha.Sha1, navigator.userAgent.indexOf('Edge') === -1 && 'SHA-1'), + sha224: hashjs_hash(_2.default), + sha256: asmcrypto_hash(_sha2.Sha256, 'SHA-256'), + sha384: hashjs_hash(_4.default, 'SHA-384'), + sha512: hashjs_hash(_6.default, 'SHA-512'), // asmcrypto sha512 is huge. + ripemd: hashjs_hash(_ripemd.ripemd160) + }; +} + +exports.default = { + + /** @see module:md5 */ + md5: hash_fns.md5, + /** @see asmCrypto */ + sha1: hash_fns.sha1, + /** @see hash.js */ + sha224: hash_fns.sha224, + /** @see asmCrypto */ + sha256: hash_fns.sha256, + /** @see hash.js */ + sha384: hash_fns.sha384, + /** @see asmCrypto */ + sha512: hash_fns.sha512, + /** @see hash.js */ + ripemd: hash_fns.ripemd, + + /** + * Create a hash on the specified data using the specified algorithm + * @param {module:enums.hash} algo Hash algorithm type (see {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}) + * @param {Uint8Array} data Data to be hashed + * @returns {Promise} hash value + */ + digest: function digest(algo, data) { + switch (algo) { + case 1: + // - MD5 [HAC] + return this.md5(data); + case 2: + // - SHA-1 [FIPS180] + return this.sha1(data); + case 3: + // - RIPE-MD/160 [HAC] + return this.ripemd(data); + case 8: + // - SHA256 [FIPS180] + return this.sha256(data); + case 9: + // - SHA384 [FIPS180] + return this.sha384(data); + case 10: + // - SHA512 [FIPS180] + return this.sha512(data); + case 11: + // - SHA224 [FIPS180] + return this.sha224(data); + default: + throw new Error('Invalid hash function.'); + } + }, + + /** + * Returns the hash size in bytes of the specified hash algorithm type + * @param {module:enums.hash} algo Hash algorithm type (See {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}) + * @returns {Integer} Size in bytes of the resulting hash + */ + getHashByteLength: function getHashByteLength(algo) { + switch (algo) { + case 1: + // - MD5 [HAC] + return 16; + case 2: // - SHA-1 [FIPS180] + case 3: + // - RIPE-MD/160 [HAC] + return 20; + case 8: + // - SHA256 [FIPS180] + return 32; + case 9: + // - SHA384 [FIPS180] + return 48; + case 10: + // - SHA512 [FIPS180] + return 64; + case 11: + // - SHA224 [FIPS180] + return 28; + default: + throw new Error('Invalid hash algorithm.'); + } + } +}; + +},{"../../config":79,"../../util":152,"./md5":93,"asmcrypto.js/dist_es5/hash/sha1/sha1":11,"asmcrypto.js/dist_es5/hash/sha256/sha256":13,"hash.js/lib/hash/ripemd":37,"hash.js/lib/hash/sha/224":40,"hash.js/lib/hash/sha/384":42,"hash.js/lib/hash/sha/512":43,"web-stream-tools":75}],93:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _util = require('../../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// MD5 Digest +async function md5(entree) { + const digest = md51(_util2.default.Uint8Array_to_str(entree)); + return _util2.default.hex_to_Uint8Array(hex(digest)); +} /** + * A fast MD5 JavaScript implementation + * Copyright (c) 2012 Joseph Myers + * http://www.myersdaily.org/joseph/javascript/md5-text.html + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purposes and without + * fee is hereby granted provided that this copyright notice + * appears in all copies. + * + * Of course, this soft is provided "as is" without express or implied + * warranty of any kind. + */ + +/** + * @requires util + */ + +function md5cycle(x, k) { + let a = x[0]; + let b = x[1]; + let c = x[2]; + let d = x[3]; + + a = ff(a, b, c, d, k[0], 7, -680876936); + d = ff(d, a, b, c, k[1], 12, -389564586); + c = ff(c, d, a, b, k[2], 17, 606105819); + b = ff(b, c, d, a, k[3], 22, -1044525330); + a = ff(a, b, c, d, k[4], 7, -176418897); + d = ff(d, a, b, c, k[5], 12, 1200080426); + c = ff(c, d, a, b, k[6], 17, -1473231341); + b = ff(b, c, d, a, k[7], 22, -45705983); + a = ff(a, b, c, d, k[8], 7, 1770035416); + d = ff(d, a, b, c, k[9], 12, -1958414417); + c = ff(c, d, a, b, k[10], 17, -42063); + b = ff(b, c, d, a, k[11], 22, -1990404162); + a = ff(a, b, c, d, k[12], 7, 1804603682); + d = ff(d, a, b, c, k[13], 12, -40341101); + c = ff(c, d, a, b, k[14], 17, -1502002290); + b = ff(b, c, d, a, k[15], 22, 1236535329); + + a = gg(a, b, c, d, k[1], 5, -165796510); + d = gg(d, a, b, c, k[6], 9, -1069501632); + c = gg(c, d, a, b, k[11], 14, 643717713); + b = gg(b, c, d, a, k[0], 20, -373897302); + a = gg(a, b, c, d, k[5], 5, -701558691); + d = gg(d, a, b, c, k[10], 9, 38016083); + c = gg(c, d, a, b, k[15], 14, -660478335); + b = gg(b, c, d, a, k[4], 20, -405537848); + a = gg(a, b, c, d, k[9], 5, 568446438); + d = gg(d, a, b, c, k[14], 9, -1019803690); + c = gg(c, d, a, b, k[3], 14, -187363961); + b = gg(b, c, d, a, k[8], 20, 1163531501); + a = gg(a, b, c, d, k[13], 5, -1444681467); + d = gg(d, a, b, c, k[2], 9, -51403784); + c = gg(c, d, a, b, k[7], 14, 1735328473); + b = gg(b, c, d, a, k[12], 20, -1926607734); + + a = hh(a, b, c, d, k[5], 4, -378558); + d = hh(d, a, b, c, k[8], 11, -2022574463); + c = hh(c, d, a, b, k[11], 16, 1839030562); + b = hh(b, c, d, a, k[14], 23, -35309556); + a = hh(a, b, c, d, k[1], 4, -1530992060); + d = hh(d, a, b, c, k[4], 11, 1272893353); + c = hh(c, d, a, b, k[7], 16, -155497632); + b = hh(b, c, d, a, k[10], 23, -1094730640); + a = hh(a, b, c, d, k[13], 4, 681279174); + d = hh(d, a, b, c, k[0], 11, -358537222); + c = hh(c, d, a, b, k[3], 16, -722521979); + b = hh(b, c, d, a, k[6], 23, 76029189); + a = hh(a, b, c, d, k[9], 4, -640364487); + d = hh(d, a, b, c, k[12], 11, -421815835); + c = hh(c, d, a, b, k[15], 16, 530742520); + b = hh(b, c, d, a, k[2], 23, -995338651); + + a = ii(a, b, c, d, k[0], 6, -198630844); + d = ii(d, a, b, c, k[7], 10, 1126891415); + c = ii(c, d, a, b, k[14], 15, -1416354905); + b = ii(b, c, d, a, k[5], 21, -57434055); + a = ii(a, b, c, d, k[12], 6, 1700485571); + d = ii(d, a, b, c, k[3], 10, -1894986606); + c = ii(c, d, a, b, k[10], 15, -1051523); + b = ii(b, c, d, a, k[1], 21, -2054922799); + a = ii(a, b, c, d, k[8], 6, 1873313359); + d = ii(d, a, b, c, k[15], 10, -30611744); + c = ii(c, d, a, b, k[6], 15, -1560198380); + b = ii(b, c, d, a, k[13], 21, 1309151649); + a = ii(a, b, c, d, k[4], 6, -145523070); + d = ii(d, a, b, c, k[11], 10, -1120210379); + c = ii(c, d, a, b, k[2], 15, 718787259); + b = ii(b, c, d, a, k[9], 21, -343485551); + + x[0] = add32(a, x[0]); + x[1] = add32(b, x[1]); + x[2] = add32(c, x[2]); + x[3] = add32(d, x[3]); +} + +function cmn(q, a, b, x, s, t) { + a = add32(add32(a, q), add32(x, t)); + return add32(a << s | a >>> 32 - s, b); +} + +function ff(a, b, c, d, x, s, t) { + return cmn(b & c | ~b & d, a, b, x, s, t); +} + +function gg(a, b, c, d, x, s, t) { + return cmn(b & d | c & ~d, a, b, x, s, t); +} + +function hh(a, b, c, d, x, s, t) { + return cmn(b ^ c ^ d, a, b, x, s, t); +} + +function ii(a, b, c, d, x, s, t) { + return cmn(c ^ (b | ~d), a, b, x, s, t); +} + +function md51(s) { + const n = s.length; + const state = [1732584193, -271733879, -1732584194, 271733878]; + let i; + for (i = 64; i <= s.length; i += 64) { + md5cycle(state, md5blk(s.substring(i - 64, i))); + } + s = s.substring(i - 64); + const tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + for (i = 0; i < s.length; i++) { + tail[i >> 2] |= s.charCodeAt(i) << (i % 4 << 3); + } + tail[i >> 2] |= 0x80 << (i % 4 << 3); + if (i > 55) { + md5cycle(state, tail); + for (i = 0; i < 16; i++) { + tail[i] = 0; + } + } + tail[14] = n * 8; + md5cycle(state, tail); + return state; +} + +/* there needs to be support for Unicode here, + * unless we pretend that we can redefine the MD-5 + * algorithm for multi-byte characters (perhaps + * by adding every four 16-bit characters and + * shortening the sum to 32 bits). Otherwise + * I suggest performing MD-5 as if every character + * was two bytes--e.g., 0040 0025 = @%--but then + * how will an ordinary MD-5 sum be matched? + * There is no way to standardize text to something + * like UTF-8 before transformation; speed cost is + * utterly prohibitive. The JavaScript standard + * itself needs to look at this: it should start + * providing access to strings as preformed UTF-8 + * 8-bit unsigned value arrays. + */ +function md5blk(s) { + /* I figured global was faster. */ + const md5blks = []; + let i; /* Andy King said do it this way. */ + for (i = 0; i < 64; i += 4) { + md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24); + } + return md5blks; +} + +const hex_chr = '0123456789abcdef'.split(''); + +function rhex(n) { + let s = ''; + let j = 0; + for (; j < 4; j++) { + s += hex_chr[n >> j * 8 + 4 & 0x0F] + hex_chr[n >> j * 8 & 0x0F]; + } + return s; +} + +function hex(x) { + for (let i = 0; i < x.length; i++) { + x[i] = rhex(x[i]); + } + return x.join(''); +} + +/* this function is much faster, +so if possible we use it. Some IEs +are the only ones I know of that +need the idiotic second function, +generated by an if clause. */ + +function add32(a, b) { + return a + b & 0xFFFFFFFF; +} + +exports.default = md5; + +},{"../../util":152}],94:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _cipher = require('./cipher'); + +var _cipher2 = _interopRequireDefault(_cipher); + +var _hash = require('./hash'); + +var _hash2 = _interopRequireDefault(_hash); + +var _cfb = require('./cfb'); + +var _cfb2 = _interopRequireDefault(_cfb); + +var _gcm = require('./gcm'); + +var _gcm2 = _interopRequireDefault(_gcm); + +var _eax = require('./eax'); + +var _eax2 = _interopRequireDefault(_eax); + +var _ocb = require('./ocb'); + +var _ocb2 = _interopRequireDefault(_ocb); + +var _public_key = require('./public_key'); + +var _public_key2 = _interopRequireDefault(_public_key); + +var _signature = require('./signature'); + +var _signature2 = _interopRequireDefault(_signature); + +var _random = require('./random'); + +var _random2 = _interopRequireDefault(_random); + +var _pkcs = require('./pkcs1'); + +var _pkcs2 = _interopRequireDefault(_pkcs); + +var _pkcs3 = require('./pkcs5'); + +var _pkcs4 = _interopRequireDefault(_pkcs3); + +var _crypto = require('./crypto'); + +var _crypto2 = _interopRequireDefault(_crypto); + +var _aes_kw = require('./aes_kw'); + +var _aes_kw2 = _interopRequireDefault(_aes_kw); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// TODO move cfb and gcm to cipher +const mod = { + /** @see module:crypto/cipher */ + cipher: _cipher2.default, + /** @see module:crypto/hash */ + hash: _hash2.default, + /** @see module:crypto/cfb */ + cfb: _cfb2.default, + /** @see module:crypto/gcm */ + gcm: _gcm2.default, + experimental_gcm: _gcm2.default, + /** @see module:crypto/eax */ + eax: _eax2.default, + /** @see module:crypto/ocb */ + ocb: _ocb2.default, + /** @see module:crypto/public_key */ + publicKey: _public_key2.default, + /** @see module:crypto/signature */ + signature: _signature2.default, + /** @see module:crypto/random */ + random: _random2.default, + /** @see module:crypto/pkcs1 */ + pkcs1: _pkcs2.default, + /** @see module:crypto/pkcs5 */ + pkcs5: _pkcs4.default, + /** @see module:crypto/aes_kw */ + aes_kw: _aes_kw2.default +}; /** + * @fileoverview Provides access to all cryptographic primitives used in OpenPGP.js + * @see module:crypto/crypto + * @see module:crypto/signature + * @see module:crypto/public_key + * @see module:crypto/cipher + * @see module:crypto/random + * @see module:crypto/hash + * @module crypto + */ + +Object.assign(mod, _crypto2.default); + +exports.default = mod; + +},{"./aes_kw":80,"./cfb":81,"./cipher":86,"./crypto":89,"./eax":90,"./gcm":91,"./hash":92,"./ocb":95,"./pkcs1":96,"./pkcs5":97,"./public_key":106,"./random":109,"./signature":110}],95:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _cipher = require('./cipher'); + +var _cipher2 = _interopRequireDefault(_cipher); + +var _util = require('../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// OpenPGP.js - An OpenPGP implementation in javascript +// Copyright (C) 2018 ProtonTech AG +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @fileoverview This module implements AES-OCB en/decryption. + * @requires crypto/cipher + * @requires util + * @module crypto/ocb + */ + +const blockLength = 16; +const ivLength = 15; + +// https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.2: +// While OCB [RFC7253] allows the authentication tag length to be of any +// number up to 128 bits long, this document requires a fixed +// authentication tag length of 128 bits (16 octets) for simplicity. +const tagLength = 16; + +function ntz(n) { + let ntz = 0; + for (let i = 1; (n & i) === 0; i <<= 1) { + ntz++; + } + return ntz; +} + +function xorMut(S, T) { + for (let i = 0; i < S.length; i++) { + S[i] ^= T[i]; + } + return S; +} + +function xor(S, T) { + return xorMut(S.slice(), T); +} + +const zeroBlock = new Uint8Array(blockLength); +const one = new Uint8Array([1]); + +/** + * Class to en/decrypt using OCB mode. + * @param {String} cipher The symmetric cipher algorithm to use e.g. 'aes128' + * @param {Uint8Array} key The encryption key + */ +async function OCB(cipher, key) { + + let maxNtz = 0; + let encipher; + let decipher; + let mask; + + constructKeyVariables(cipher, key); + + function constructKeyVariables(cipher, key) { + const aes = new _cipher2.default[cipher](key); + encipher = aes.encrypt.bind(aes); + decipher = aes.decrypt.bind(aes); + + const mask_x = encipher(zeroBlock); + const mask_$ = _util2.default.double(mask_x); + mask = []; + mask[0] = _util2.default.double(mask_$); + + mask.x = mask_x; + mask.$ = mask_$; + } + + function extendKeyVariables(text, adata) { + const newMaxNtz = _util2.default.nbits(Math.max(text.length, adata.length) / blockLength | 0) - 1; + for (let i = maxNtz + 1; i <= newMaxNtz; i++) { + mask[i] = _util2.default.double(mask[i - 1]); + } + maxNtz = newMaxNtz; + } + + function hash(adata) { + if (!adata.length) { + // Fast path + return zeroBlock; + } + + // + // Consider A as a sequence of 128-bit blocks + // + const m = adata.length / blockLength | 0; + + const offset = new Uint8Array(blockLength); + const sum = new Uint8Array(blockLength); + for (let i = 0; i < m; i++) { + xorMut(offset, mask[ntz(i + 1)]); + xorMut(sum, encipher(xor(offset, adata))); + adata = adata.subarray(blockLength); + } + + // + // Process any final partial block; compute final hash value + // + if (adata.length) { + xorMut(offset, mask.x); + + const cipherInput = new Uint8Array(blockLength); + cipherInput.set(adata, 0); + cipherInput[adata.length] = 0b10000000; + xorMut(cipherInput, offset); + + xorMut(sum, encipher(cipherInput)); + } + + return sum; + } + + /** + * Encrypt/decrypt data. + * @param {encipher|decipher} fn Encryption/decryption block cipher function + * @param {Uint8Array} text The cleartext or ciphertext (without tag) input + * @param {Uint8Array} nonce The nonce (15 bytes) + * @param {Uint8Array} adata Associated data to sign + * @returns {Promise} The ciphertext or plaintext output, with tag appended in both cases + */ + function crypt(fn, text, nonce, adata) { + // + // Consider P as a sequence of 128-bit blocks + // + const m = text.length / blockLength | 0; + + // + // Key-dependent variables + // + extendKeyVariables(text, adata); + + // + // Nonce-dependent and per-encryption variables + // + // Nonce = num2str(TAGLEN mod 128,7) || zeros(120-bitlen(N)) || 1 || N + // Note: We assume here that tagLength mod 16 == 0. + const paddedNonce = _util2.default.concatUint8Array([zeroBlock.subarray(0, ivLength - nonce.length), one, nonce]); + // bottom = str2num(Nonce[123..128]) + const bottom = paddedNonce[blockLength - 1] & 0b111111; + // Ktop = ENCIPHER(K, Nonce[1..122] || zeros(6)) + paddedNonce[blockLength - 1] &= 0b11000000; + const kTop = encipher(paddedNonce); + // Stretch = Ktop || (Ktop[1..64] xor Ktop[9..72]) + const stretched = _util2.default.concatUint8Array([kTop, xor(kTop.subarray(0, 8), kTop.subarray(1, 9))]); + // Offset_0 = Stretch[1+bottom..128+bottom] + const offset = _util2.default.shiftRight(stretched.subarray(0 + (bottom >> 3), 17 + (bottom >> 3)), 8 - (bottom & 7)).subarray(1); + // Checksum_0 = zeros(128) + const checksum = new Uint8Array(blockLength); + + const ct = new Uint8Array(text.length + tagLength); + + // + // Process any whole blocks + // + let i; + let pos = 0; + for (i = 0; i < m; i++) { + // Offset_i = Offset_{i-1} xor L_{ntz(i)} + xorMut(offset, mask[ntz(i + 1)]); + // C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) + // P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i) + ct.set(xorMut(fn(xor(offset, text)), offset), pos); + // Checksum_i = Checksum_{i-1} xor P_i + xorMut(checksum, fn === encipher ? text : ct.subarray(pos)); + + text = text.subarray(blockLength); + pos += blockLength; + } + + // + // Process any final partial block and compute raw tag + // + if (text.length) { + // Offset_* = Offset_m xor L_* + xorMut(offset, mask.x); + // Pad = ENCIPHER(K, Offset_*) + const padding = encipher(offset); + // C_* = P_* xor Pad[1..bitlen(P_*)] + ct.set(xor(text, padding), pos); + + // Checksum_* = Checksum_m xor (P_* || 1 || new Uint8Array(127-bitlen(P_*))) + const xorInput = new Uint8Array(blockLength); + xorInput.set(fn === encipher ? text : ct.subarray(pos, -tagLength), 0); + xorInput[text.length] = 0b10000000; + xorMut(checksum, xorInput); + pos += text.length; + } + // Tag = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) xor HASH(K,A) + const tag = xorMut(encipher(xorMut(xorMut(checksum, offset), mask.$)), hash(adata)); + + // + // Assemble ciphertext + // + // C = C_1 || C_2 || ... || C_m || C_* || Tag[1..TAGLEN] + ct.set(tag, pos); + return ct; + } + + return { + /** + * Encrypt plaintext input. + * @param {Uint8Array} plaintext The cleartext input to be encrypted + * @param {Uint8Array} nonce The nonce (15 bytes) + * @param {Uint8Array} adata Associated data to sign + * @returns {Promise} The ciphertext output + */ + encrypt: async function encrypt(plaintext, nonce, adata) { + return crypt(encipher, plaintext, nonce, adata); + }, + + /** + * Decrypt ciphertext input. + * @param {Uint8Array} ciphertext The ciphertext input to be decrypted + * @param {Uint8Array} nonce The nonce (15 bytes) + * @param {Uint8Array} adata Associated data to sign + * @returns {Promise} The ciphertext output + */ + decrypt: async function decrypt(ciphertext, nonce, adata) { + if (ciphertext.length < tagLength) throw new Error('Invalid OCB ciphertext'); + + const tag = ciphertext.subarray(-tagLength); + ciphertext = ciphertext.subarray(0, -tagLength); + + const crypted = crypt(decipher, ciphertext, nonce, adata); + // if (Tag[1..TAGLEN] == T) + if (_util2.default.equalsUint8Array(tag, crypted.subarray(-tagLength))) { + return crypted.subarray(0, -tagLength); + } + throw new Error('Authentication tag mismatch'); + } + }; +} + +/** + * Get OCB nonce as defined by {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.2|RFC4880bis-04, section 5.16.2}. + * @param {Uint8Array} iv The initialization vector (15 bytes) + * @param {Uint8Array} chunkIndex The chunk index (8 bytes) + */ +OCB.getNonce = function (iv, chunkIndex) { + const nonce = iv.slice(); + for (let i = 0; i < chunkIndex.length; i++) { + nonce[7 + i] ^= chunkIndex[i]; + } + return nonce; +}; + +OCB.blockLength = blockLength; +OCB.ivLength = ivLength; +OCB.tagLength = tagLength; + +exports.default = OCB; + +},{"../util":152,"./cipher":86}],96:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _random = require('./random'); + +var _random2 = _interopRequireDefault(_random); + +var _hash = require('./hash'); + +var _hash2 = _interopRequireDefault(_hash); + +var _util = require('../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** @namespace */ +const eme = {}; +/** @namespace */ +// GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @fileoverview Provides EME-PKCS1-v1_5 encoding and decoding and EMSA-PKCS1-v1_5 encoding function + * @see module:crypto/public_key/rsa + * @see module:crypto/public_key/elliptic/ecdh + * @see module:packet.PublicKeyEncryptedSessionKey + * @requires crypto/random + * @requires crypto/hash + * @requires util + * @module crypto/pkcs1 + */ + +const emsa = {}; + +/** + * ASN1 object identifiers for hashes + * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.2} + */ +const hash_headers = []; +hash_headers[1] = [0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10]; +hash_headers[2] = [0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14]; +hash_headers[3] = [0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14]; +hash_headers[8] = [0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20]; +hash_headers[9] = [0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30]; +hash_headers[10] = [0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40]; +hash_headers[11] = [0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1C]; + +/** + * Create padding with secure random data + * @private + * @param {Integer} length Length of the padding in bytes + * @returns {String} Padding as string + * @async + */ +async function getPkcs1Padding(length) { + let result = ''; + while (result.length < length) { + const randomBytes = await _random2.default.getRandomBytes(length - result.length); + for (let i = 0; i < randomBytes.length; i++) { + if (randomBytes[i] !== 0) { + result += String.fromCharCode(randomBytes[i]); + } + } + } + return result; +} + +/** + * Create a EME-PKCS1-v1_5 padded message + * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.1|RFC 4880 13.1.1} + * @param {String} M message to be encoded + * @param {Integer} k the length in octets of the key modulus + * @returns {Promise} EME-PKCS1 padded message + * @async + */ +eme.encode = async function (M, k) { + const mLen = M.length; + // length checking + if (mLen > k - 11) { + throw new Error('Message too long'); + } + // Generate an octet string PS of length k - mLen - 3 consisting of + // pseudo-randomly generated nonzero octets + const PS = await getPkcs1Padding(k - mLen - 3); + // Concatenate PS, the message M, and other padding to form an + // encoded message EM of length k octets as EM = 0x00 || 0x02 || PS || 0x00 || M. + return String.fromCharCode(0) + String.fromCharCode(2) + PS + String.fromCharCode(0) + M; +}; + +/** + * Decode a EME-PKCS1-v1_5 padded message + * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.2|RFC 4880 13.1.2} + * @param {String} EM encoded message, an octet string + * @returns {String} message, an octet string + */ +eme.decode = function (EM) { + // leading zeros truncated by bn.js + if (EM.charCodeAt(0) !== 0) { + EM = String.fromCharCode(0) + EM; + } + const firstOct = EM.charCodeAt(0); + const secondOct = EM.charCodeAt(1); + let i = 2; + while (EM.charCodeAt(i) !== 0 && i < EM.length) { + i++; + } + const psLen = i - 2; + const separator = EM.charCodeAt(i++); + if (firstOct === 0 && secondOct === 2 && psLen >= 8 && separator === 0) { + return EM.substr(i); + } + throw new Error('Decryption error'); +}; + +/** + * Create a EMSA-PKCS1-v1_5 padded message + * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.3|RFC 4880 13.1.3} + * @param {Integer} algo Hash algorithm type used + * @param {Uint8Array} hashed message to be encoded + * @param {Integer} emLen intended length in octets of the encoded message + * @returns {String} encoded message + */ +emsa.encode = async function (algo, hashed, emLen) { + let i; + const H = _util2.default.Uint8Array_to_str(hashed); + if (H.length !== _hash2.default.getHashByteLength(algo)) { + throw new Error('Invalid hash length'); + } + // produce an ASN.1 DER value for the hash function used. + // Let T be the full hash prefix + let T = ''; + for (i = 0; i < hash_headers[algo].length; i++) { + T += String.fromCharCode(hash_headers[algo][i]); + } + // add hash value to prefix + T += H; + // and let tLen be the length in octets of T + const tLen = T.length; + if (emLen < tLen + 11) { + throw new Error('Intended encoded message length too short'); + } + // an octet string PS consisting of emLen - tLen - 3 octets with hexadecimal value 0xFF + // The length of PS will be at least 8 octets + let PS = ''; + for (i = 0; i < emLen - tLen - 3; i++) { + PS += String.fromCharCode(0xff); + } + // Concatenate PS, the hash prefix T, and other padding to form the + // encoded message EM as EM = 0x00 || 0x01 || PS || 0x00 || T. + const EM = String.fromCharCode(0x00) + String.fromCharCode(0x01) + PS + String.fromCharCode(0x00) + T; + return _util2.default.str_to_hex(EM); +}; + +exports.default = { eme, emsa }; + +},{"../util":152,"./hash":92,"./random":109}],97:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +// OpenPGP.js - An OpenPGP implementation in javascript +// Copyright (C) 2015-2016 Decentral +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @fileoverview Functions to add and remove PKCS5 padding + * @see module:packet.PublicKeyEncryptedSessionKey + * @module crypto/pkcs5 + */ + +/** + * Add pkcs5 padding to a text. + * @param {String} msg Text to add padding + * @returns {String} Text with padding added + */ +function encode(msg) { + const c = 8 - msg.length % 8; + const padding = String.fromCharCode(c).repeat(c); + return msg + padding; +} + +/** + * Remove pkcs5 padding from a string. + * @param {String} msg Text to remove padding from + * @returns {String} Text with padding removed + */ +function decode(msg) { + const len = msg.length; + if (len > 0) { + const c = msg.charCodeAt(len - 1); + if (c >= 1 && c <= 8) { + const provided = msg.substr(len - c); + const computed = String.fromCharCode(c).repeat(c); + if (provided === computed) { + return msg.substr(0, len - c); + } + } + } + throw new Error('Invalid padding'); +} + +exports.default = { encode, decode }; + +},{}],98:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _bn = require('bn.js'); + +var _bn2 = _interopRequireDefault(_bn); + +var _random = require('../random'); + +var _random2 = _interopRequireDefault(_random); + +var _util = require('../../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const one = new _bn2.default(1); // GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @fileoverview A Digital signature algorithm implementation + * @requires bn.js + * @requires crypto/random + * @requires util + * @module crypto/public_key/dsa + */ + +const zero = new _bn2.default(0); + +/* + TODO regarding the hash function, read: + https://tools.ietf.org/html/rfc4880#section-13.6 + https://tools.ietf.org/html/rfc4880#section-14 +*/ + +exports.default = { + /** + * DSA Sign function + * @param {Integer} hash_algo + * @param {Uint8Array} hashed + * @param {BN} g + * @param {BN} p + * @param {BN} q + * @param {BN} x + * @returns {{ r: BN, s: BN }} + * @async + */ + sign: async function sign(hash_algo, hashed, g, p, q, x) { + let k; + let r; + let s; + let t; + const redp = new _bn2.default.red(p); + const redq = new _bn2.default.red(q); + const gred = g.toRed(redp); + const xred = x.toRed(redq); + // If the output size of the chosen hash is larger than the number of + // bits of q, the hash result is truncated to fit by taking the number + // of leftmost bits equal to the number of bits of q. This (possibly + // truncated) hash function result is treated as a number and used + // directly in the DSA signature algorithm. + const h = new _bn2.default(hashed.subarray(0, q.byteLength())).toRed(redq); + // FIPS-186-4, section 4.6: + // The values of r and s shall be checked to determine if r = 0 or s = 0. + // If either r = 0 or s = 0, a new value of k shall be generated, and the + // signature shall be recalculated. It is extremely unlikely that r = 0 + // or s = 0 if signatures are generated properly. + while (true) { + // See Appendix B here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf + k = await _random2.default.getRandomBN(one, q); // returns in [1, q-1] + r = gred.redPow(k).fromRed().toRed(redq); // (g**k mod p) mod q + if (zero.cmp(r) === 0) { + continue; + } + t = h.redAdd(xred.redMul(r)); // H(m) + x*r mod q + s = k.toRed(redq).redInvm().redMul(t); // k**-1 * (H(m) + x*r) mod q + if (zero.cmp(s) === 0) { + continue; + } + break; + } + return { + r: r.toArrayLike(Uint8Array, 'be', q.byteLength()), + s: s.toArrayLike(Uint8Array, 'be', q.byteLength()) + }; + }, + + /** + * DSA Verify function + * @param {Integer} hash_algo + * @param {BN} r + * @param {BN} s + * @param {Uint8Array} hashed + * @param {BN} g + * @param {BN} p + * @param {BN} q + * @param {BN} y + * @returns BN + * @async + */ + verify: async function verify(hash_algo, r, s, hashed, g, p, q, y) { + if (zero.ucmp(r) >= 0 || r.ucmp(q) >= 0 || zero.ucmp(s) >= 0 || s.ucmp(q) >= 0) { + _util2.default.print_debug("invalid DSA Signature"); + return null; + } + const redp = new _bn2.default.red(p); + const redq = new _bn2.default.red(q); + const h = new _bn2.default(hashed.subarray(0, q.byteLength())); + const w = s.toRed(redq).redInvm(); // s**-1 mod q + if (zero.cmp(w) === 0) { + _util2.default.print_debug("invalid DSA Signature"); + return null; + } + const u1 = h.toRed(redq).redMul(w); // H(m) * w mod q + const u2 = r.toRed(redq).redMul(w); // r * w mod q + const t1 = g.toRed(redp).redPow(u1.fromRed()); // g**u1 mod p + const t2 = y.toRed(redp).redPow(u2.fromRed()); // y**u2 mod p + const v = t1.redMul(t2).fromRed().mod(q); // (g**u1 * y**u2 mod p) mod q + return v.cmp(r) === 0; + } +}; + +},{"../../util":152,"../random":109,"bn.js":16}],99:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _bn = require('bn.js'); + +var _bn2 = _interopRequireDefault(_bn); + +var _random = require('../random'); + +var _random2 = _interopRequireDefault(_random); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @fileoverview ElGamal implementation + * @requires bn.js + * @requires crypto/random + * @module crypto/public_key/elgamal + */ + +const zero = new _bn2.default(0); + +exports.default = { + /** + * ElGamal Encryption function + * @param {BN} m + * @param {BN} p + * @param {BN} g + * @param {BN} y + * @returns {{ c1: BN, c2: BN }} + * @async + */ + encrypt: async function encrypt(m, p, g, y) { + const redp = new _bn2.default.red(p); + const mred = m.toRed(redp); + const gred = g.toRed(redp); + const yred = y.toRed(redp); + // See Section 11.5 here: https://crypto.stanford.edu/~dabo/cryptobook/BonehShoup_0_4.pdf + const k = await _random2.default.getRandomBN(zero, p); // returns in [0, p-1] + return { + c1: gred.redPow(k).fromRed(), + c2: yred.redPow(k).redMul(mred).fromRed() + }; + }, + + /** + * ElGamal Encryption function + * @param {BN} c1 + * @param {BN} c2 + * @param {BN} p + * @param {BN} x + * @returns BN + * @async + */ + decrypt: async function decrypt(c1, c2, p, x) { + const redp = new _bn2.default.red(p); + const c1red = c1.toRed(redp); + const c2red = c2.toRed(redp); + return c1red.redPow(x).redInvm().redMul(c2red).fromRed(); + } +}; + +},{"../random":109,"bn.js":16}],100:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getPreferredHashAlgo = exports.generate = exports.nodeCurves = exports.webCurves = exports.curves = undefined; + +var _bn = require('bn.js'); + +var _bn2 = _interopRequireDefault(_bn); + +var _elliptic = require('elliptic'); + +var _key = require('./key'); + +var _key2 = _interopRequireDefault(_key); + +var _random = require('../../random'); + +var _random2 = _interopRequireDefault(_random); + +var _enums = require('../../../enums'); + +var _enums2 = _interopRequireDefault(_enums); + +var _util = require('../../../util'); + +var _util2 = _interopRequireDefault(_util); + +var _oid = require('../../../type/oid'); + +var _oid2 = _interopRequireDefault(_oid); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const webCrypto = _util2.default.getWebCrypto(); // OpenPGP.js - An OpenPGP implementation in javascript +// Copyright (C) 2015-2016 Decentral +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @fileoverview Wrapper of an instance of an Elliptic Curve + * @requires bn.js + * @requires elliptic + * @requires crypto/public_key/elliptic/key + * @requires crypto/random + * @requires enums + * @requires util + * @requires type/oid + * @module crypto/public_key/elliptic/curve + */ + +const nodeCrypto = _util2.default.getNodeCrypto(); + +const webCurves = { + 'p256': 'P-256', + 'p384': 'P-384', + 'p521': 'P-521' +}; +const knownCurves = nodeCrypto ? nodeCrypto.getCurves() : []; +const nodeCurves = nodeCrypto ? { + secp256k1: knownCurves.includes('secp256k1') ? 'secp256k1' : undefined, + p256: knownCurves.includes('prime256v1') ? 'prime256v1' : undefined, + p384: knownCurves.includes('secp384r1') ? 'secp384r1' : undefined, + p521: knownCurves.includes('secp521r1') ? 'secp521r1' : undefined, + ed25519: knownCurves.includes('ED25519') ? 'ED25519' : undefined, + curve25519: knownCurves.includes('X25519') ? 'X25519' : undefined, + brainpoolP256r1: knownCurves.includes('brainpoolP256r1') ? 'brainpoolP256r1' : undefined, + brainpoolP384r1: knownCurves.includes('brainpoolP384r1') ? 'brainpoolP384r1' : undefined, + brainpoolP512r1: knownCurves.includes('brainpoolP512r1') ? 'brainpoolP512r1' : undefined +} : {}; + +const curves = { + p256: { + oid: [0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07], + keyType: _enums2.default.publicKey.ecdsa, + hash: _enums2.default.hash.sha256, + cipher: _enums2.default.symmetric.aes128, + node: nodeCurves.p256, + web: webCurves.p256, + payloadSize: 32, + sharedSize: 256 + }, + p384: { + oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22], + keyType: _enums2.default.publicKey.ecdsa, + hash: _enums2.default.hash.sha384, + cipher: _enums2.default.symmetric.aes192, + node: nodeCurves.p384, + web: webCurves.p384, + payloadSize: 48, + sharedSize: 384 + }, + p521: { + oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23], + keyType: _enums2.default.publicKey.ecdsa, + hash: _enums2.default.hash.sha512, + cipher: _enums2.default.symmetric.aes256, + node: nodeCurves.p521, + web: webCurves.p521, + payloadSize: 66, + sharedSize: 528 + }, + secp256k1: { + oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x0A], + keyType: _enums2.default.publicKey.ecdsa, + hash: _enums2.default.hash.sha256, + cipher: _enums2.default.symmetric.aes128, + node: nodeCurves.secp256k1 + }, + ed25519: { + oid: [0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01], + keyType: _enums2.default.publicKey.eddsa, + hash: _enums2.default.hash.sha512, + node: false // nodeCurves.ed25519 TODO + }, + curve25519: { + oid: [0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01], + keyType: _enums2.default.publicKey.ecdsa, + hash: _enums2.default.hash.sha256, + cipher: _enums2.default.symmetric.aes128, + node: false // nodeCurves.curve25519 TODO + }, + brainpoolP256r1: { + oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07], + keyType: _enums2.default.publicKey.ecdsa, + hash: _enums2.default.hash.sha256, + cipher: _enums2.default.symmetric.aes128, + node: nodeCurves.brainpoolP256r1 + }, + brainpoolP384r1: { + oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B], + keyType: _enums2.default.publicKey.ecdsa, + hash: _enums2.default.hash.sha384, + cipher: _enums2.default.symmetric.aes192, + node: nodeCurves.brainpoolP384r1 + }, + brainpoolP512r1: { + oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D], + keyType: _enums2.default.publicKey.ecdsa, + hash: _enums2.default.hash.sha512, + cipher: _enums2.default.symmetric.aes256, + node: nodeCurves.brainpoolP512r1 + } +}; + +/** + * @constructor + */ +function Curve(oid_or_name, params) { + try { + if (_util2.default.isArray(oid_or_name) || _util2.default.isUint8Array(oid_or_name)) { + // by oid byte array + oid_or_name = new _oid2.default(oid_or_name); + } + if (oid_or_name instanceof _oid2.default) { + // by curve OID + oid_or_name = oid_or_name.getName(); + } + // by curve name or oid string + this.name = _enums2.default.write(_enums2.default.curve, oid_or_name); + } catch (err) { + throw new Error('Not valid curve'); + } + params = params || curves[this.name]; + + this.keyType = params.keyType; + switch (this.keyType) { + case _enums2.default.publicKey.ecdsa: + this.curve = new _elliptic.ec(this.name); + break; + case _enums2.default.publicKey.eddsa: + this.curve = new _elliptic.eddsa(this.name); + break; + default: + throw new Error('Unknown elliptic key type;'); + } + + this.oid = params.oid; + this.hash = params.hash; + this.cipher = params.cipher; + this.node = params.node && curves[this.name]; + this.web = params.web && curves[this.name]; + this.payloadSize = params.payloadSize; +} + +Curve.prototype.keyFromPrivate = function (priv) { + // Not for ed25519 + return new _key2.default(this, { priv: priv }); +}; + +Curve.prototype.keyFromPublic = function (pub) { + const keyPair = new _key2.default(this, { pub: pub }); + if (this.keyType === _enums2.default.publicKey.ecdsa && keyPair.keyPair.validate().result !== true) { + throw new Error('Invalid elliptic public key'); + } + return keyPair; +}; + +Curve.prototype.genKeyPair = async function () { + let keyPair; + if (this.web && _util2.default.getWebCrypto()) { + // If browser doesn't support a curve, we'll catch it + try { + keyPair = await webGenKeyPair(this.name); + } catch (err) { + _util2.default.print_debug("Browser did not support signing: " + err.message); + } + } else if (this.node && _util2.default.getNodeCrypto()) { + keyPair = await nodeGenKeyPair(this.name); + } + + if (!keyPair || !keyPair.priv) { + // elliptic fallback + const r = await this.curve.genKeyPair({ + entropy: _util2.default.Uint8Array_to_str((await _random2.default.getRandomBytes(32))) + }); + const compact = this.curve.curve.type === 'edwards' || this.curve.curve.type === 'mont'; + if (this.keyType === _enums2.default.publicKey.eddsa) { + keyPair = { secret: r.getSecret() }; + } else { + keyPair = { pub: r.getPublic('array', compact), priv: r.getPrivate().toArray() }; + } + } + return new _key2.default(this, keyPair); +}; + +async function generate(curve) { + curve = new Curve(curve); + const keyPair = await curve.genKeyPair(); + return { + oid: curve.oid, + Q: new _bn2.default(keyPair.getPublic()), + d: new _bn2.default(keyPair.getPrivate()), + hash: curve.hash, + cipher: curve.cipher + }; +} + +function getPreferredHashAlgo(oid) { + return curves[_enums2.default.write(_enums2.default.curve, oid.toHex())].hash; +} + +exports.default = Curve; +exports.curves = curves; +exports.webCurves = webCurves; +exports.nodeCurves = nodeCurves; +exports.generate = generate; +exports.getPreferredHashAlgo = getPreferredHashAlgo; + +////////////////////////// +// // +// Helper functions // +// // +////////////////////////// + + +async function webGenKeyPair(name) { + // Note: keys generated with ECDSA and ECDH are structurally equivalent + const webCryptoKey = await webCrypto.generateKey({ name: "ECDSA", namedCurve: webCurves[name] }, true, ["sign", "verify"]); + + const privateKey = await webCrypto.exportKey("jwk", webCryptoKey.privateKey); + const publicKey = await webCrypto.exportKey("jwk", webCryptoKey.publicKey); + + return { + pub: { + x: _util2.default.b64_to_Uint8Array(publicKey.x, true), + y: _util2.default.b64_to_Uint8Array(publicKey.y, true) + }, + priv: _util2.default.b64_to_Uint8Array(privateKey.d, true) + }; +} + +async function nodeGenKeyPair(name) { + // Note: ECDSA and ECDH key generation is structurally equivalent + const ecdh = nodeCrypto.createECDH(nodeCurves[name]); + await ecdh.generateKeys(); + + return { + pub: ecdh.getPublicKey().toJSON().data, + priv: ecdh.getPrivateKey().toJSON().data + }; +} + +},{"../../../enums":113,"../../../type/oid":150,"../../../util":152,"../../random":109,"./key":105,"bn.js":16,"elliptic":18}],101:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); // OpenPGP.js - An OpenPGP implementation in javascript +// Copyright (C) 2015-2016 Decentral +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @fileoverview Key encryption and decryption for RFC 6637 ECDH + * @requires bn.js + * @requires tweetnacl + * @requires crypto/public_key/elliptic/curve + * @requires crypto/aes_kw + * @requires crypto/cipher + * @requires crypto/hash + * @requires type/kdf_params + * @requires enums + * @requires util + * @module crypto/public_key/elliptic/ecdh + */ + +var _bn = require('bn.js'); + +var _bn2 = _interopRequireDefault(_bn); + +var _naclFastLight = require('tweetnacl/nacl-fast-light.js'); + +var _naclFastLight2 = _interopRequireDefault(_naclFastLight); + +var _curves = require('./curves'); + +var _curves2 = _interopRequireDefault(_curves); + +var _aes_kw = require('../../aes_kw'); + +var _aes_kw2 = _interopRequireDefault(_aes_kw); + +var _cipher = require('../../cipher'); + +var _cipher2 = _interopRequireDefault(_cipher); + +var _hash = require('../../hash'); + +var _hash2 = _interopRequireDefault(_hash); + +var _kdf_params = require('../../../type/kdf_params'); + +var _kdf_params2 = _interopRequireDefault(_kdf_params); + +var _enums = require('../../../enums'); + +var _enums2 = _interopRequireDefault(_enums); + +var _util = require('../../../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const webCrypto = _util2.default.getWebCrypto(); +const nodeCrypto = _util2.default.getNodeCrypto(); + +// Build Param for ECDH algorithm (RFC 6637) +function buildEcdhParam(public_algo, oid, cipher_algo, hash_algo, fingerprint) { + const kdf_params = new _kdf_params2.default([hash_algo, cipher_algo]); + return _util2.default.concatUint8Array([oid.write(), new Uint8Array([public_algo]), kdf_params.write(), _util2.default.str_to_Uint8Array("Anonymous Sender "), fingerprint.subarray(0, 20)]); +} + +// Key Derivation Function (RFC 6637) +async function kdf(hash_algo, X, length, param, stripLeading = false, stripTrailing = false) { + // Note: X is little endian for Curve25519, big-endian for all others. + // This is not ideal, but the RFC's are unclear + // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B + let i; + if (stripLeading) { + // Work around old go crypto bug + for (i = 0; i < X.length && X[i] === 0; i++); + X = X.subarray(i); + } + if (stripTrailing) { + // Work around old OpenPGP.js bug + for (i = X.length - 1; i >= 0 && X[i] === 0; i--); + X = X.subarray(0, i + 1); + } + const digest = await _hash2.default.digest(hash_algo, _util2.default.concatUint8Array([new Uint8Array([0, 0, 0, 1]), X, param])); + return digest.subarray(0, length); +} + +/** + * Generate ECDHE ephemeral key and secret from public key + * + * @param {Curve} curve Elliptic curve object + * @param {Uint8Array} Q Recipient public key + * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ +async function genPublicEphemeralKey(curve, Q) { + switch (curve.name) { + case 'curve25519': + { + var _nacl$box$keyPair = _naclFastLight2.default.box.keyPair(); + + const d = _nacl$box$keyPair.secretKey; + + var _ref = await genPrivateEphemeralKey(curve, Q, null, d); + + const secretKey = _ref.secretKey, + sharedKey = _ref.sharedKey; + + var _nacl$box$keyPair$fro = _naclFastLight2.default.box.keyPair.fromSecretKey(secretKey); + + let publicKey = _nacl$box$keyPair$fro.publicKey; + + publicKey = _util2.default.concatUint8Array([new Uint8Array([0x40]), publicKey]); + return { publicKey, sharedKey }; // Note: sharedKey is little-endian here, unlike below + } + case 'p256': + case 'p384': + case 'p521': + { + if (curve.web && _util2.default.getWebCrypto()) { + try { + return await webPublicEphemeralKey(curve, Q); + } catch (err) { + _util2.default.print_debug_error(err); + } + } + } + } + if (curve.node && nodeCrypto) { + return nodePublicEphemeralKey(curve, Q); + } + return ellipticPublicEphemeralKey(curve, Q); +} + +/** + * Encrypt and wrap a session key + * + * @param {module:type/oid} oid Elliptic curve object identifier + * @param {module:enums.symmetric} cipher_algo Symmetric cipher to use + * @param {module:enums.hash} hash_algo Hash algorithm to use + * @param {module:type/mpi} m Value derived from session key (RFC 6637) + * @param {Uint8Array} Q Recipient public key + * @param {String} fingerprint Recipient fingerprint + * @returns {Promise<{publicKey: Uint8Array, wrappedKey: Uint8Array}>} + * @async + */ +async function encrypt(oid, cipher_algo, hash_algo, m, Q, fingerprint) { + const curve = new _curves2.default(oid); + + var _ref2 = await genPublicEphemeralKey(curve, Q); + + const publicKey = _ref2.publicKey, + sharedKey = _ref2.sharedKey; + + const param = buildEcdhParam(_enums2.default.publicKey.ecdh, oid, cipher_algo, hash_algo, fingerprint); + cipher_algo = _enums2.default.read(_enums2.default.symmetric, cipher_algo); + const Z = await kdf(hash_algo, sharedKey, _cipher2.default[cipher_algo].keySize, param); + const wrappedKey = _aes_kw2.default.wrap(Z, m.toString()); + return { publicKey, wrappedKey }; +} + +/** + * Generate ECDHE secret from private key and public part of ephemeral key + * + * @param {Curve} curve Elliptic curve object + * @param {Uint8Array} V Public part of ephemeral key + * @param {Uint8Array} Q Recipient public key + * @param {Uint8Array} d Recipient private key + * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ +async function genPrivateEphemeralKey(curve, V, Q, d) { + switch (curve.name) { + case 'curve25519': + { + const one = new _bn2.default(1); + const mask = one.ushln(255 - 3).sub(one).ushln(3); + let secretKey = new _bn2.default(d); + secretKey = secretKey.or(one.ushln(255 - 1)); + secretKey = secretKey.and(mask); + secretKey = secretKey.toArrayLike(Uint8Array, 'le', 32); + const sharedKey = _naclFastLight2.default.scalarMult(secretKey, V.subarray(1)); + return { secretKey, sharedKey }; // Note: sharedKey is little-endian here, unlike below + } + case 'p256': + case 'p384': + case 'p521': + { + if (curve.web && _util2.default.getWebCrypto()) { + try { + return await webPrivateEphemeralKey(curve, V, Q, d); + } catch (err) { + _util2.default.print_debug_error(err); + } + } + } + } + if (curve.node && nodeCrypto) { + return nodePrivateEphemeralKey(curve, V, d); + } + return ellipticPrivateEphemeralKey(curve, V, d); +} + +/** + * Decrypt and unwrap the value derived from session key + * + * @param {module:type/oid} oid Elliptic curve object identifier + * @param {module:enums.symmetric} cipher_algo Symmetric cipher to use + * @param {module:enums.hash} hash_algo Hash algorithm to use + * @param {Uint8Array} V Public part of ephemeral key + * @param {Uint8Array} C Encrypted and wrapped value derived from session key + * @param {Uint8Array} Q Recipient public key + * @param {Uint8Array} d Recipient private key + * @param {String} fingerprint Recipient fingerprint + * @returns {Promise} Value derived from session key + * @async + */ +async function decrypt(oid, cipher_algo, hash_algo, V, C, Q, d, fingerprint) { + const curve = new _curves2.default(oid); + + var _ref3 = await genPrivateEphemeralKey(curve, V, Q, d); + + const sharedKey = _ref3.sharedKey; + + const param = buildEcdhParam(_enums2.default.publicKey.ecdh, oid, cipher_algo, hash_algo, fingerprint); + cipher_algo = _enums2.default.read(_enums2.default.symmetric, cipher_algo); + let err; + for (let i = 0; i < 3; i++) { + try { + // Work around old go crypto bug and old OpenPGP.js bug, respectively. + const Z = await kdf(hash_algo, sharedKey, _cipher2.default[cipher_algo].keySize, param, i === 1, i === 2); + return new _bn2.default(_aes_kw2.default.unwrap(Z, C)); + } catch (e) { + err = e; + } + } + throw err; +} + +/** + * Generate ECDHE secret from private key and public part of ephemeral key using webCrypto + * + * @param {Curve} curve Elliptic curve object + * @param {Uint8Array} V Public part of ephemeral key + * @param {Uint8Array} Q Recipient public key + * @param {Uint8Array} d Recipient private key + * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ +async function webPrivateEphemeralKey(curve, V, Q, d) { + const recipient = privateToJwk(curve.payloadSize, curve.web.web, d, Q); + let privateKey = webCrypto.importKey("jwk", recipient, { + name: "ECDH", + namedCurve: curve.web.web + }, true, ["deriveKey", "deriveBits"]); + const jwk = rawPublicToJwk(curve.payloadSize, curve.web.web, V); + let sender = webCrypto.importKey("jwk", jwk, { + name: "ECDH", + namedCurve: curve.web.web + }, true, []); + + var _ref4 = await Promise.all([privateKey, sender]); + + var _ref5 = _slicedToArray(_ref4, 2); + + privateKey = _ref5[0]; + sender = _ref5[1]; + + let S = webCrypto.deriveBits({ + name: "ECDH", + namedCurve: curve.web.web, + public: sender + }, privateKey, curve.web.sharedSize); + let secret = webCrypto.exportKey("jwk", privateKey); + + var _ref6 = await Promise.all([S, secret]); + + var _ref7 = _slicedToArray(_ref6, 2); + + S = _ref7[0]; + secret = _ref7[1]; + + const sharedKey = new Uint8Array(S); + const secretKey = _util2.default.b64_to_Uint8Array(secret.d, true); + return { secretKey, sharedKey }; +} + +/** + * Generate ECDHE ephemeral key and secret from public key using webCrypto + * + * @param {Curve} curve Elliptic curve object + * @param {Uint8Array} Q Recipient public key + * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ +async function webPublicEphemeralKey(curve, Q) { + const jwk = rawPublicToJwk(curve.payloadSize, curve.web.web, Q); + let keyPair = webCrypto.generateKey({ + name: "ECDH", + namedCurve: curve.web.web + }, true, ["deriveKey", "deriveBits"]); + let recipient = webCrypto.importKey("jwk", jwk, { + name: "ECDH", + namedCurve: curve.web.web + }, false, []); + + var _ref8 = await Promise.all([keyPair, recipient]); + + var _ref9 = _slicedToArray(_ref8, 2); + + keyPair = _ref9[0]; + recipient = _ref9[1]; + + let s = webCrypto.deriveBits({ + name: "ECDH", + namedCurve: curve.web.web, + public: recipient + }, keyPair.privateKey, curve.web.sharedSize); + let p = webCrypto.exportKey("jwk", keyPair.publicKey); + + var _ref10 = await Promise.all([s, p]); + + var _ref11 = _slicedToArray(_ref10, 2); + + s = _ref11[0]; + p = _ref11[1]; + + const sharedKey = new Uint8Array(s); + const publicKey = new Uint8Array(jwkToRawPublic(p)); + return { publicKey, sharedKey }; +} + +/** + * Generate ECDHE secret from private key and public part of ephemeral key using indutny/elliptic + * + * @param {Curve} curve Elliptic curve object + * @param {Uint8Array} V Public part of ephemeral key + * @param {Uint8Array} d Recipient private key + * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ +async function ellipticPrivateEphemeralKey(curve, V, d) { + V = curve.keyFromPublic(V); + d = curve.keyFromPrivate(d); + const secretKey = new Uint8Array(d.getPrivate()); + const S = d.derive(V); + const len = curve.curve.curve.p.byteLength(); + const sharedKey = S.toArrayLike(Uint8Array, 'be', len); + return { secretKey, sharedKey }; +} + +/** + * Generate ECDHE ephemeral key and secret from public key using indutny/elliptic + * + * @param {Curve} curve Elliptic curve object + * @param {Uint8Array} Q Recipient public key + * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ +async function ellipticPublicEphemeralKey(curve, Q) { + const v = await curve.genKeyPair(); + Q = curve.keyFromPublic(Q); + const publicKey = new Uint8Array(v.getPublic()); + const S = v.derive(Q); + const len = curve.curve.curve.p.byteLength(); + const sharedKey = S.toArrayLike(Uint8Array, 'be', len); + return { publicKey, sharedKey }; +} + +/** + * Generate ECDHE secret from private key and public part of ephemeral key using nodeCrypto + * + * @param {Curve} curve Elliptic curve object + * @param {Uint8Array} V Public part of ephemeral key + * @param {Uint8Array} d Recipient private key + * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ +async function nodePrivateEphemeralKey(curve, V, d) { + const recipient = nodeCrypto.createECDH(curve.node.node); + recipient.setPrivateKey(d); + const sharedKey = new Uint8Array(recipient.computeSecret(V)); + const secretKey = new Uint8Array(recipient.getPrivateKey()); + return { secretKey, sharedKey }; +} + +/** + * Generate ECDHE ephemeral key and secret from public key using nodeCrypto + * + * @param {Curve} curve Elliptic curve object + * @param {Uint8Array} Q Recipient public key + * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ +async function nodePublicEphemeralKey(curve, Q) { + const sender = nodeCrypto.createECDH(curve.node.node); + sender.generateKeys(); + const sharedKey = new Uint8Array(sender.computeSecret(Q)); + const publicKey = new Uint8Array(sender.getPublicKey()); + return { publicKey, sharedKey }; +} + +/** + * @param {Integer} payloadSize ec payload size + * @param {String} name curve name + * @param {Uint8Array} publicKey public key + * @returns {JsonWebKey} public key in jwk format + */ +function rawPublicToJwk(payloadSize, name, publicKey) { + const len = payloadSize; + const bufX = publicKey.slice(1, len + 1); + const bufY = publicKey.slice(len + 1, len * 2 + 1); + // https://www.rfc-editor.org/rfc/rfc7518.txt + const jwKey = { + kty: "EC", + crv: name, + x: _util2.default.Uint8Array_to_b64(bufX, true), + y: _util2.default.Uint8Array_to_b64(bufY, true), + ext: true + }; + return jwKey; +} + +/** + * @param {Integer} payloadSize ec payload size + * @param {String} name curve name + * @param {Uint8Array} publicKey public key + * @param {Uint8Array} privateKey private key + * @returns {JsonWebKey} private key in jwk format + */ +function privateToJwk(payloadSize, name, privateKey, publicKey) { + const jwk = rawPublicToJwk(payloadSize, name, publicKey); + jwk.d = _util2.default.Uint8Array_to_b64(privateKey, true); + return jwk; +} + +/** + * @param {JsonWebKey} jwk key for conversion + * @returns {Uint8Array} raw public key + */ +function jwkToRawPublic(jwk) { + const bufX = _util2.default.b64_to_Uint8Array(jwk.x); + const bufY = _util2.default.b64_to_Uint8Array(jwk.y); + const publicKey = new Uint8Array(bufX.length + bufY.length + 1); + publicKey[0] = 0x04; + publicKey.set(bufX, 1); + publicKey.set(bufY, bufX.length + 1); + return publicKey; +} + +exports.default = { encrypt, decrypt, genPublicEphemeralKey, genPrivateEphemeralKey, buildEcdhParam, kdf, webPublicEphemeralKey, webPrivateEphemeralKey, ellipticPublicEphemeralKey, ellipticPrivateEphemeralKey, nodePublicEphemeralKey, nodePrivateEphemeralKey }; + +},{"../../../enums":113,"../../../type/kdf_params":147,"../../../util":152,"../../aes_kw":80,"../../cipher":86,"../../hash":92,"./curves":100,"bn.js":16,"tweetnacl/nacl-fast-light.js":72}],102:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _curves = require('./curves'); + +var _curves2 = _interopRequireDefault(_curves); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Sign a message using the provided key + * @param {module:type/oid} oid Elliptic curve object identifier + * @param {module:enums.hash} hash_algo Hash algorithm used to sign + * @param {Uint8Array} m Message to sign + * @param {Uint8Array} d Private key used to sign the message + * @param {Uint8Array} hashed The hashed message + * @returns {{r: Uint8Array, + * s: Uint8Array}} Signature of the message + * @async + */ +async function sign(oid, hash_algo, m, d, hashed) { + const curve = new _curves2.default(oid); + const key = curve.keyFromPrivate(d); + const signature = await key.sign(m, hash_algo, hashed); + return { + r: signature.r.toArrayLike(Uint8Array), + s: signature.s.toArrayLike(Uint8Array) + }; +} + +/** + * Verifies if a signature is valid for a message + * @param {module:type/oid} oid Elliptic curve object identifier + * @param {module:enums.hash} hash_algo Hash algorithm used in the signature + * @param {{r: Uint8Array, + s: Uint8Array}} signature Signature to verify + * @param {Uint8Array} m Message to verify + * @param {Uint8Array} Q Public key used to verify the message + * @param {Uint8Array} hashed The hashed message + * @returns {Boolean} + * @async + */ +// OpenPGP.js - An OpenPGP implementation in javascript +// Copyright (C) 2015-2016 Decentral +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @fileoverview Implementation of ECDSA following RFC6637 for Openpgpjs + * @requires crypto/public_key/elliptic/curve + * @module crypto/public_key/elliptic/ecdsa + */ + +async function verify(oid, hash_algo, signature, m, Q, hashed) { + const curve = new _curves2.default(oid); + const key = curve.keyFromPublic(Q); + return key.verify(m, signature, hash_algo, hashed); +} + +exports.default = { sign, verify }; + +},{"./curves":100}],103:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _ = require('hash.js/lib/hash/sha/512'); + +var _2 = _interopRequireDefault(_); + +var _naclFastLight = require('tweetnacl/nacl-fast-light.js'); + +var _naclFastLight2 = _interopRequireDefault(_naclFastLight); + +var _util = require('../../../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +_naclFastLight2.default.hash = bytes => new Uint8Array((0, _2.default)().update(bytes).digest()); + +/** + * Sign a message using the provided key + * @param {module:type/oid} oid Elliptic curve object identifier + * @param {module:enums.hash} hash_algo Hash algorithm used to sign + * @param {Uint8Array} m Message to sign + * @param {Uint8Array} d Private key used to sign + * @param {Uint8Array} hashed The hashed message + * @returns {{R: Uint8Array, + * S: Uint8Array}} Signature of the message + * @async + */ +// OpenPGP.js - An OpenPGP implementation in javascript +// Copyright (C) 2018 Proton Technologies AG +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @fileoverview Implementation of EdDSA following RFC4880bis-03 for OpenPGP + * @requires hash.js + * @requires tweetnacl + * @requires crypto/public_key/elliptic/curve + * @requires util + * @module crypto/public_key/elliptic/eddsa + */ + +async function sign(oid, hash_algo, m, d, hashed) { + var _nacl$sign$keyPair$fr = _naclFastLight2.default.sign.keyPair.fromSeed(d); + + const secretKey = _nacl$sign$keyPair$fr.secretKey; + + const signature = _naclFastLight2.default.sign.detached(hashed, secretKey); + // EdDSA signature params are returned in little-endian format + return { + R: signature.subarray(0, 32), + S: signature.subarray(32) + }; +} + +/** + * Verifies if a signature is valid for a message + * @param {module:type/oid} oid Elliptic curve object identifier + * @param {module:enums.hash} hash_algo Hash algorithm used in the signature + * @param {{R: Uint8Array, + S: Uint8Array}} signature Signature to verify the message + * @param {Uint8Array} m Message to verify + * @param {Uint8Array} publicKey Public key used to verify the message + * @param {Uint8Array} hashed The hashed message + * @returns {Boolean} + * @async + */ +async function verify(oid, hash_algo, { R, S }, m, publicKey, hashed) { + const signature = _util2.default.concatUint8Array([R, S]); + return _naclFastLight2.default.sign.detached.verify(hashed, signature, publicKey.subarray(1)); +} + +exports.default = { sign, verify }; + +},{"../../../util":152,"hash.js/lib/hash/sha/512":43,"tweetnacl/nacl-fast-light.js":72}],104:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _curves = require('./curves'); + +var _curves2 = _interopRequireDefault(_curves); + +var _ecdsa = require('./ecdsa'); + +var _ecdsa2 = _interopRequireDefault(_ecdsa); + +var _eddsa = require('./eddsa'); + +var _eddsa2 = _interopRequireDefault(_eddsa); + +var _ecdh = require('./ecdh'); + +var _ecdh2 = _interopRequireDefault(_ecdh); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// OpenPGP.js - An OpenPGP implementation in javascript +// Copyright (C) 2015-2016 Decentral +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @fileoverview Functions to access Elliptic Curve Cryptography + * @see module:crypto/public_key/elliptic/curve + * @see module:crypto/public_key/elliptic/ecdh + * @see module:crypto/public_key/elliptic/ecdsa + * @see module:crypto/public_key/elliptic/eddsa + * @module crypto/public_key/elliptic + */ + +exports.default = { + Curve: _curves2.default, ecdh: _ecdh2.default, ecdsa: _ecdsa2.default, eddsa: _eddsa2.default, generate: _curves.generate, getPreferredHashAlgo: _curves.getPreferredHashAlgo +}; + +},{"./curves":100,"./ecdh":101,"./ecdsa":102,"./eddsa":103}],105:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _bn = require('bn.js'); + +var _bn2 = _interopRequireDefault(_bn); + +var _webStreamTools = require('web-stream-tools'); + +var _webStreamTools2 = _interopRequireDefault(_webStreamTools); + +var _curves = require('./curves'); + +var _util = require('../../../util'); + +var _util2 = _interopRequireDefault(_util); + +var _enums = require('../../../enums'); + +var _enums2 = _interopRequireDefault(_enums); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const webCrypto = _util2.default.getWebCrypto(); // OpenPGP.js - An OpenPGP implementation in javascript +// Copyright (C) 2015-2016 Decentral +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @fileoverview Wrapper for a KeyPair of an Elliptic Curve + * @requires bn.js + * @requires web-stream-tools + * @requires crypto/public_key/elliptic/curves + * @requires util + * @requires enums + * @requires asn1.js + * @module crypto/public_key/elliptic/key + */ + +const nodeCrypto = _util2.default.getNodeCrypto(); + +/** + * @constructor + */ +function KeyPair(curve, options) { + this.curve = curve; + this.keyType = curve.curve.type === 'edwards' ? _enums2.default.publicKey.eddsa : _enums2.default.publicKey.ecdsa; + this.keyPair = this.curve.curve.keyPair(options); +} + +KeyPair.prototype.sign = async function (message, hash_algo, hashed) { + if (message && !message.locked) { + message = await _webStreamTools2.default.readToEnd(message); + if (this.curve.web && _util2.default.getWebCrypto()) { + // If browser doesn't support a curve, we'll catch it + try { + // need to await to make sure browser succeeds + const signature = await webSign(this.curve, hash_algo, message, this.keyPair); + return signature; + } catch (err) { + _util2.default.print_debug("Browser did not support signing: " + err.message); + } + } else if (this.curve.node && _util2.default.getNodeCrypto()) { + return nodeSign(this.curve, hash_algo, message, this.keyPair); + } + } + const digest = typeof hash_algo === 'undefined' ? message : hashed; + return this.keyPair.sign(digest); +}; + +KeyPair.prototype.verify = async function (message, signature, hash_algo, hashed) { + if (message && !message.locked) { + message = await _webStreamTools2.default.readToEnd(message); + if (this.curve.web && _util2.default.getWebCrypto()) { + // If browser doesn't support a curve, we'll catch it + try { + // need to await to make sure browser succeeds + const result = await webVerify(this.curve, hash_algo, signature, message, this.keyPair.getPublic()); + return result; + } catch (err) { + _util2.default.print_debug("Browser did not support signing: " + err.message); + } + } else if (this.curve.node && _util2.default.getNodeCrypto()) { + return nodeVerify(this.curve, hash_algo, signature, message, this.keyPair.getPublic()); + } + } + const digest = typeof hash_algo === 'undefined' ? message : hashed; + return this.keyPair.verify(digest, signature); +}; + +KeyPair.prototype.derive = function (pub) { + if (this.keyType === _enums2.default.publicKey.eddsa) { + throw new Error('Key can only be used for EdDSA'); + } + return this.keyPair.derive(pub.keyPair.getPublic()); +}; + +KeyPair.prototype.getPublic = function () { + const compact = this.curve.curve.curve.type === 'edwards' || this.curve.curve.curve.type === 'mont'; + return this.keyPair.getPublic('array', compact); +}; + +KeyPair.prototype.getPrivate = function () { + if (this.curve.keyType === _enums2.default.publicKey.eddsa) { + return this.keyPair.getSecret(); + } + return this.keyPair.getPrivate().toArray(); +}; + +exports.default = KeyPair; + +////////////////////////// +// // +// Helper functions // +// // +////////////////////////// + + +async function webSign(curve, hash_algo, message, keyPair) { + const len = curve.payloadSize; + const key = await webCrypto.importKey("jwk", { + "kty": "EC", + "crv": _curves.webCurves[curve.name], + "x": _util2.default.Uint8Array_to_b64(new Uint8Array(keyPair.getPublic().getX().toArray('be', len)), true), + "y": _util2.default.Uint8Array_to_b64(new Uint8Array(keyPair.getPublic().getY().toArray('be', len)), true), + "d": _util2.default.Uint8Array_to_b64(new Uint8Array(keyPair.getPrivate().toArray('be', len)), true), + "use": "sig", + "kid": "ECDSA Private Key" + }, { + "name": "ECDSA", + "namedCurve": _curves.webCurves[curve.name], + "hash": { name: _enums2.default.read(_enums2.default.webHash, curve.hash) } + }, false, ["sign"]); + + const signature = new Uint8Array((await webCrypto.sign({ + "name": 'ECDSA', + "namedCurve": _curves.webCurves[curve.name], + "hash": { name: _enums2.default.read(_enums2.default.webHash, hash_algo) } + }, key, message))); + + return { + r: new _bn2.default(signature.slice(0, len)), + s: new _bn2.default(signature.slice(len, len << 1)) + }; +} + +async function webVerify(curve, hash_algo, { r, s }, message, publicKey) { + const len = curve.payloadSize; + const key = await webCrypto.importKey("jwk", { + "kty": "EC", + "crv": _curves.webCurves[curve.name], + "x": _util2.default.Uint8Array_to_b64(new Uint8Array(publicKey.getX().toArray('be', len)), true), + "y": _util2.default.Uint8Array_to_b64(new Uint8Array(publicKey.getY().toArray('be', len)), true), + "use": "sig", + "kid": "ECDSA Public Key" + }, { + "name": "ECDSA", + "namedCurve": _curves.webCurves[curve.name], + "hash": { name: _enums2.default.read(_enums2.default.webHash, curve.hash) } + }, false, ["verify"]); + + const signature = _util2.default.concatUint8Array([new Uint8Array(len - r.length), r, new Uint8Array(len - s.length), s]).buffer; + + return webCrypto.verify({ + "name": 'ECDSA', + "namedCurve": _curves.webCurves[curve.name], + "hash": { name: _enums2.default.read(_enums2.default.webHash, hash_algo) } + }, key, signature, message); +} + +async function nodeSign(curve, hash_algo, message, keyPair) { + const sign = nodeCrypto.createSign(_enums2.default.read(_enums2.default.hash, hash_algo)); + sign.write(message); + sign.end(); + + const key = ECPrivateKey.encode({ + version: 1, + parameters: curve.oid, + privateKey: keyPair.getPrivate().toArray(), + publicKey: { unused: 0, data: keyPair.getPublic().encode() } + }, 'pem', { + label: 'EC PRIVATE KEY' + }); + + return ECDSASignature.decode(sign.sign(key), 'der'); +} + +async function nodeVerify(curve, hash_algo, { r, s }, message, publicKey) { + const verify = nodeCrypto.createVerify(_enums2.default.read(_enums2.default.hash, hash_algo)); + verify.write(message); + verify.end(); + + const key = SubjectPublicKeyInfo.encode({ + algorithm: { + algorithm: [1, 2, 840, 10045, 2, 1], + parameters: curve.oid + }, + subjectPublicKey: { unused: 0, data: publicKey.encode() } + }, 'pem', { + label: 'PUBLIC KEY' + }); + + const signature = ECDSASignature.encode({ + r: new _bn2.default(r), s: new _bn2.default(s) + }, 'der'); + + try { + return verify.verify(key, signature); + } catch (err) { + return false; + } +} + +// Originally written by Owen Smith https://github.com/omsmith +// Adapted on Feb 2018 from https://github.com/Brightspace/node-jwk-to-pem/ + +/* eslint-disable no-invalid-this */ + +const asn1 = nodeCrypto ? require('asn1.js') : undefined; + +const ECDSASignature = nodeCrypto ? asn1.define('ECDSASignature', function () { + this.seq().obj(this.key('r').int(), this.key('s').int()); +}) : undefined; + +const ECPrivateKey = nodeCrypto ? asn1.define('ECPrivateKey', function () { + this.seq().obj(this.key('version').int(), this.key('privateKey').octstr(), this.key('parameters').explicit(0).optional().any(), this.key('publicKey').explicit(1).optional().bitstr()); +}) : undefined; + +const AlgorithmIdentifier = nodeCrypto ? asn1.define('AlgorithmIdentifier', function () { + this.seq().obj(this.key('algorithm').objid(), this.key('parameters').optional().any()); +}) : undefined; + +const SubjectPublicKeyInfo = nodeCrypto ? asn1.define('SubjectPublicKeyInfo', function () { + this.seq().obj(this.key('algorithm').use(AlgorithmIdentifier), this.key('subjectPublicKey').bitstr()); +}) : undefined; + +},{"../../../enums":113,"../../../util":152,"./curves":100,"asn1.js":"asn1.js","bn.js":16,"web-stream-tools":75}],106:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _naclFastLight = require('tweetnacl/nacl-fast-light.js'); + +var _naclFastLight2 = _interopRequireDefault(_naclFastLight); + +var _rsa = require('./rsa'); + +var _rsa2 = _interopRequireDefault(_rsa); + +var _elgamal = require('./elgamal'); + +var _elgamal2 = _interopRequireDefault(_elgamal); + +var _elliptic = require('./elliptic'); + +var _elliptic2 = _interopRequireDefault(_elliptic); + +var _dsa = require('./dsa'); + +var _dsa2 = _interopRequireDefault(_dsa); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = { + /** @see module:crypto/public_key/rsa */ + rsa: _rsa2.default, + /** @see module:crypto/public_key/elgamal */ + elgamal: _elgamal2.default, + /** @see module:crypto/public_key/elliptic */ + elliptic: _elliptic2.default, + /** @see module:crypto/public_key/dsa */ + dsa: _dsa2.default, + /** @see tweetnacl */ + nacl: _naclFastLight2.default +}; /** + * @fileoverview Asymmetric cryptography functions + * @requires tweetnacl + * @requires crypto/public_key/dsa + * @requires crypto/public_key/elgamal + * @requires crypto/public_key/elliptic + * @requires crypto/public_key/rsa + * @module crypto/public_key + */ + +},{"./dsa":98,"./elgamal":99,"./elliptic":104,"./rsa":108,"tweetnacl/nacl-fast-light.js":72}],107:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _bn = require('bn.js'); + +var _bn2 = _interopRequireDefault(_bn); + +var _random = require('../random'); + +var _random2 = _interopRequireDefault(_random); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// OpenPGP.js - An OpenPGP implementation in javascript +// Copyright (C) 2018 Proton Technologies AG +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @fileoverview Algorithms for probabilistic random prime generation + * @requires bn.js + * @requires crypto/random + * @module crypto/public_key/prime + */ + +exports.default = { + randomProbablePrime, isProbablePrime, fermat, millerRabin, divisionTest +}; + +/** + * Probabilistic random number generator + * @param {Integer} bits Bit length of the prime + * @param {BN} e Optional RSA exponent to check against the prime + * @param {Integer} k Optional number of iterations of Miller-Rabin test + * @returns BN + * @async + */ + +async function randomProbablePrime(bits, e, k) { + const min = new _bn2.default(1).shln(bits - 1); + const thirty = new _bn2.default(30); + /* + * We can avoid any multiples of 3 and 5 by looking at n mod 30 + * n mod 30 = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 + * the next possible prime is mod 30: + * 1 7 7 7 7 7 7 11 11 11 11 13 13 17 17 17 17 19 19 23 23 23 23 29 29 29 29 29 29 1 + */ + const adds = [1, 6, 5, 4, 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, 3, 2, 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1, 2]; + + let n = await _random2.default.getRandomBN(min, min.shln(1)); + let i = n.mod(thirty).toNumber(); + + do { + n.iaddn(adds[i]); + i = (i + adds[i]) % adds.length; + // If reached the maximum, go back to the minimum. + if (n.bitLength() > bits) { + n = n.mod(min.shln(1)).iadd(min); + i = n.mod(thirty).toNumber(); + } + } while (!(await isProbablePrime(n, e, k))); + return n; +} + +/** + * Probabilistic primality testing + * @param {BN} n Number to test + * @param {BN} e Optional RSA exponent to check against the prime + * @param {Integer} k Optional number of iterations of Miller-Rabin test + * @returns {boolean} + * @async + */ +async function isProbablePrime(n, e, k) { + if (e && !n.subn(1).gcd(e).eqn(1)) { + return false; + } + if (!divisionTest(n)) { + return false; + } + if (!fermat(n)) { + return false; + } + if (!(await millerRabin(n, k))) { + return false; + } + // TODO implement the Lucas test + // See Section C.3.3 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf + return true; +} + +/** + * Tests whether n is probably prime or not using Fermat's test with b = 2. + * Fails if b^(n-1) mod n === 1. + * @param {BN} n Number to test + * @param {Integer} b Optional Fermat test base + * @returns {boolean} + */ +function fermat(n, b) { + b = b || new _bn2.default(2); + return b.toRed(_bn2.default.mont(n)).redPow(n.subn(1)).fromRed().cmpn(1) === 0; +} + +function divisionTest(n) { + return small_primes.every(m => { + return n.modn(m) !== 0; + }); +} + +// https://github.com/gpg/libgcrypt/blob/master/cipher/primegen.c +const small_primes = [7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999]; + +// Miller-Rabin - Miller Rabin algorithm for primality test +// Copyright Fedor Indutny, 2014. +// +// This software is licensed under the MIT License. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// Adapted on Jan 2018 from version 4.0.1 at https://github.com/indutny/miller-rabin + +// Sample syntax for Fixed-Base Miller-Rabin: +// millerRabin(n, k, () => new BN(small_primes[Math.random() * small_primes.length | 0])) + +/** + * Tests whether n is probably prime or not using the Miller-Rabin test. + * See HAC Remark 4.28. + * @param {BN} n Number to test + * @param {Integer} k Optional number of iterations of Miller-Rabin test + * @param {Function} rand Optional function to generate potential witnesses + * @returns {boolean} + * @async + */ +async function millerRabin(n, k, rand) { + const len = n.bitLength(); + const red = _bn2.default.mont(n); + const rone = new _bn2.default(1).toRed(red); + + if (!k) { + k = Math.max(1, len / 48 | 0); + } + + const n1 = n.subn(1); + const rn1 = n1.toRed(red); + + // Find d and s, (n - 1) = (2 ^ s) * d; + let s = 0; + while (!n1.testn(s)) { + s++; + } + const d = n.shrn(s); + + for (; k > 0; k--) { + const a = rand ? rand() : await _random2.default.getRandomBN(new _bn2.default(2), n1); + + let x = a.toRed(red).redPow(d); + if (x.eq(rone) || x.eq(rn1)) { + continue; + } + + let i; + for (i = 1; i < s; i++) { + x = x.redSqr(); + + if (x.eq(rone)) { + return false; + } + if (x.eq(rn1)) { + break; + } + } + + if (i === s) { + return false; + } + } + + return true; +} + +},{"../random":109,"bn.js":16}],108:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _bn = require('bn.js'); + +var _bn2 = _interopRequireDefault(_bn); + +var _prime = require('./prime'); + +var _prime2 = _interopRequireDefault(_prime); + +var _random = require('../random'); + +var _random2 = _interopRequireDefault(_random); + +var _config = require('../../config'); + +var _config2 = _interopRequireDefault(_config); + +var _util = require('../../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// Helper for IE11 KeyOperation objects +function promisifyIE11Op(keyObj, err) { + if (typeof keyObj.then !== 'function') { + // IE11 KeyOperation + return new Promise(function (resolve, reject) { + keyObj.onerror = function () { + reject(new Error(err)); + }; + keyObj.oncomplete = function (e) { + resolve(e.target.result); + }; + }); + } + return keyObj; +} // GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @fileoverview RSA implementation + * @requires bn.js + * @requires crypto/public_key/prime + * @requires crypto/random + * @requires config + * @requires util + * @module crypto/public_key/rsa + */ + +exports.default = { + /** Create signature + * @param {BN} m message + * @param {BN} n RSA public modulus + * @param {BN} e RSA public exponent + * @param {BN} d RSA private exponent + * @returns {BN} RSA Signature + * @async + */ + sign: async function sign(m, n, e, d) { + if (n.cmp(m) <= 0) { + throw new Error('Message size cannot exceed modulus size'); + } + const nred = new _bn2.default.red(n); + return m.toRed(nred).redPow(d).toArrayLike(Uint8Array, 'be', n.byteLength()); + }, + + /** + * Verify signature + * @param {BN} s signature + * @param {BN} n RSA public modulus + * @param {BN} e RSA public exponent + * @returns {BN} + * @async + */ + verify: async function verify(s, n, e) { + if (n.cmp(s) <= 0) { + throw new Error('Signature size cannot exceed modulus size'); + } + const nred = new _bn2.default.red(n); + return s.toRed(nred).redPow(e).toArrayLike(Uint8Array, 'be', n.byteLength()); + }, + + /** + * Encrypt message + * @param {BN} m message + * @param {BN} n RSA public modulus + * @param {BN} e RSA public exponent + * @returns {BN} RSA Ciphertext + * @async + */ + encrypt: async function encrypt(m, n, e) { + if (n.cmp(m) <= 0) { + throw new Error('Message size cannot exceed modulus size'); + } + const nred = new _bn2.default.red(n); + return m.toRed(nred).redPow(e).toArrayLike(Uint8Array, 'be', n.byteLength()); + }, + + /** + * Decrypt RSA message + * @param {BN} m message + * @param {BN} n RSA public modulus + * @param {BN} e RSA public exponent + * @param {BN} d RSA private exponent + * @param {BN} p RSA private prime p + * @param {BN} q RSA private prime q + * @param {BN} u RSA private inverse of prime q + * @returns {BN} RSA Plaintext + * @async + */ + decrypt: async function decrypt(m, n, e, d, p, q, u) { + if (n.cmp(m) <= 0) { + throw new Error('Data too large.'); + } + const dq = d.mod(q.subn(1)); // d mod (q-1) + const dp = d.mod(p.subn(1)); // d mod (p-1) + const pred = new _bn2.default.red(p); + const qred = new _bn2.default.red(q); + const nred = new _bn2.default.red(n); + + let blinder; + let unblinder; + if (_config2.default.rsa_blinding) { + unblinder = (await _random2.default.getRandomBN(new _bn2.default(2), n)).toRed(nred); + blinder = unblinder.redInvm().redPow(e); + m = m.toRed(nred).redMul(blinder).fromRed(); + } + + const mp = m.toRed(pred).redPow(dp); + const mq = m.toRed(qred).redPow(dq); + const t = mq.redSub(mp.fromRed().toRed(qred)); + const h = u.toRed(qred).redMul(t).fromRed(); + + let result = h.mul(p).add(mp).toRed(nred); + + if (_config2.default.rsa_blinding) { + result = result.redMul(unblinder); + } + + return result.toArrayLike(Uint8Array, 'be', n.byteLength()); + }, + + /** + * Generate a new random private key B bits long with public exponent E. + * + * When possible, webCrypto is used. Otherwise, primes are generated using + * 40 rounds of the Miller-Rabin probabilistic random prime generation algorithm. + * @see module:crypto/public_key/prime + * @param {Integer} B RSA bit length + * @param {String} E RSA public exponent in hex string + * @returns {{n: BN, e: BN, d: BN, + * p: BN, q: BN, u: BN}} RSA public modulus, RSA public exponent, RSA private exponent, + * RSA private prime p, RSA private prime q, u = q ** -1 mod p + * @async + */ + generate: async function generate(B, E) { + let key; + E = new _bn2.default(E, 16); + const webCrypto = _util2.default.getWebCryptoAll(); + + // Native RSA keygen using Web Crypto + if (webCrypto) { + let keyPair; + let keyGenOpt; + if (window.crypto && window.crypto.subtle || window.msCrypto) { + // current standard spec + keyGenOpt = { + name: 'RSASSA-PKCS1-v1_5', + modulusLength: B, // the specified keysize in bits + publicExponent: E.toArrayLike(Uint8Array), // take three bytes (max 65537) for exponent + hash: { + name: 'SHA-1' // not required for actual RSA keys, but for crypto api 'sign' and 'verify' + } + }; + keyPair = webCrypto.generateKey(keyGenOpt, true, ['sign', 'verify']); + keyPair = await promisifyIE11Op(keyPair, 'Error generating RSA key pair.'); + } else if (window.crypto && window.crypto.webkitSubtle) { + // outdated spec implemented by old Webkit + keyGenOpt = { + name: 'RSA-OAEP', + modulusLength: B, // the specified keysize in bits + publicExponent: E.toArrayLike(Uint8Array), // take three bytes (max 65537) for exponent + hash: { + name: 'SHA-1' // not required for actual RSA keys, but for crypto api 'sign' and 'verify' + } + }; + keyPair = await webCrypto.generateKey(keyGenOpt, true, ['encrypt', 'decrypt']); + } else { + throw new Error('Unknown WebCrypto implementation'); + } + + // export the generated keys as JsonWebKey (JWK) + // https://tools.ietf.org/html/draft-ietf-jose-json-web-key-33 + let jwk = webCrypto.exportKey('jwk', keyPair.privateKey); + jwk = await promisifyIE11Op(jwk, 'Error exporting RSA key pair.'); + + // parse raw ArrayBuffer bytes to jwk/json (WebKit/Safari/IE11 quirk) + if (jwk instanceof ArrayBuffer) { + jwk = JSON.parse(String.fromCharCode.apply(null, new Uint8Array(jwk))); + } + + // map JWK parameters to BN + key = {}; + key.n = new _bn2.default(_util2.default.b64_to_Uint8Array(jwk.n)); + key.e = E; + key.d = new _bn2.default(_util2.default.b64_to_Uint8Array(jwk.d)); + key.p = new _bn2.default(_util2.default.b64_to_Uint8Array(jwk.p)); + key.q = new _bn2.default(_util2.default.b64_to_Uint8Array(jwk.q)); + key.u = key.p.invm(key.q); + return key; + } + + // RSA keygen fallback using 40 iterations of the Miller-Rabin test + // See https://stackoverflow.com/a/6330138 for justification + // Also see section C.3 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST + let p = await _prime2.default.randomProbablePrime(B - (B >> 1), E, 40); + let q = await _prime2.default.randomProbablePrime(B >> 1, E, 40); + + if (p.cmp(q) < 0) { + var _ref = [q, p]; + p = _ref[0]; + q = _ref[1]; + } + + const phi = p.subn(1).mul(q.subn(1)); + return { + n: p.mul(q), + e: E, + d: E.invm(phi), + p: p, + q: q, + // dp: d.mod(p.subn(1)), + // dq: d.mod(q.subn(1)), + u: p.invm(q) + }; + }, + + prime: _prime2.default +}; + +},{"../../config":79,"../../util":152,"../random":109,"./prime":107,"bn.js":16}],109:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _bn = require('bn.js'); + +var _bn2 = _interopRequireDefault(_bn); + +var _util = require('../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// Do not use util.getNodeCrypto because we need this regardless of use_native setting +// GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +// The GPG4Browsers crypto interface + +/** + * @fileoverview Provides tools for retrieving secure randomness from browsers or Node.js + * @requires bn.js + * @requires util + * @module crypto/random + */ + +const nodeCrypto = _util2.default.detectNode() && require('crypto'); + +exports.default = { + /** + * Retrieve secure random byte array of the specified length + * @param {Integer} length Length in bytes to generate + * @returns {Uint8Array} Random byte array + * @async + */ + getRandomBytes: async function getRandomBytes(length) { + const buf = new Uint8Array(length); + if (typeof window !== 'undefined' && window.crypto && window.crypto.getRandomValues) { + window.crypto.getRandomValues(buf); + } else if (typeof window !== 'undefined' && typeof window.msCrypto === 'object' && typeof window.msCrypto.getRandomValues === 'function') { + window.msCrypto.getRandomValues(buf); + } else if (nodeCrypto) { + const bytes = nodeCrypto.randomBytes(buf.length); + buf.set(bytes); + } else if (this.randomBuffer.buffer) { + await this.randomBuffer.get(buf); + } else { + throw new Error('No secure random number generator available.'); + } + return buf; + }, + + /** + * Create a secure random MPI that is greater than or equal to min and less than max. + * @param {module:type/mpi} min Lower bound, included + * @param {module:type/mpi} max Upper bound, excluded + * @returns {module:BN} Random MPI + * @async + */ + getRandomBN: async function getRandomBN(min, max) { + if (max.cmp(min) <= 0) { + throw new Error('Illegal parameter value: max <= min'); + } + + const modulus = max.sub(min); + const bytes = modulus.byteLength(); + + // Using a while loop is necessary to avoid bias introduced by the mod operation. + // However, we request 64 extra random bits so that the bias is negligible. + // Section B.1.1 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf + const r = new _bn2.default((await this.getRandomBytes(bytes + 8))); + return r.mod(modulus).add(min); + }, + + randomBuffer: new RandomBuffer() +}; + +/** + * Buffer for secure random numbers + */ + +function RandomBuffer() { + this.buffer = null; + this.size = null; + this.callback = null; +} + +/** + * Initialize buffer + * @param {Integer} size size of buffer + */ +RandomBuffer.prototype.init = function (size, callback) { + this.buffer = new Uint8Array(size); + this.size = 0; + this.callback = callback; +}; + +/** + * Concat array of secure random numbers to buffer + * @param {Uint8Array} buf + */ +RandomBuffer.prototype.set = function (buf) { + if (!this.buffer) { + throw new Error('RandomBuffer is not initialized'); + } + if (!(buf instanceof Uint8Array)) { + throw new Error('Invalid type: buf not an Uint8Array'); + } + const freeSpace = this.buffer.length - this.size; + if (buf.length > freeSpace) { + buf = buf.subarray(0, freeSpace); + } + // set buf with offset old size of buffer + this.buffer.set(buf, this.size); + this.size += buf.length; +}; + +/** + * Take numbers out of buffer and copy to array + * @param {Uint8Array} buf the destination array + */ +RandomBuffer.prototype.get = async function (buf) { + if (!this.buffer) { + throw new Error('RandomBuffer is not initialized'); + } + if (!(buf instanceof Uint8Array)) { + throw new Error('Invalid type: buf not an Uint8Array'); + } + if (this.size < buf.length) { + if (!this.callback) { + throw new Error('Random number buffer depleted'); + } + // Wait for random bytes from main context, then try again + await this.callback(); + return this.get(buf); + } + for (let i = 0; i < buf.length; i++) { + buf[i] = this.buffer[--this.size]; + // clear buffer value + this.buffer[this.size] = 0; + } +}; + +},{"../util":152,"bn.js":16,"crypto":"crypto"}],110:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _bn = require('bn.js'); + +var _bn2 = _interopRequireDefault(_bn); + +var _crypto = require('./crypto'); + +var _crypto2 = _interopRequireDefault(_crypto); + +var _public_key = require('./public_key'); + +var _public_key2 = _interopRequireDefault(_public_key); + +var _pkcs = require('./pkcs1'); + +var _pkcs2 = _interopRequireDefault(_pkcs); + +var _enums = require('../enums'); + +var _enums2 = _interopRequireDefault(_enums); + +var _util = require('../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * @fileoverview Provides functions for asymmetric signing and signature verification + * @requires bn.js + * @requires crypto/crypto + * @requires crypto/public_key + * @requires crypto/pkcs1 + * @requires enums + * @requires util + * @module crypto/signature +*/ + +exports.default = { + /** + * Verifies the signature provided for data using specified algorithms and public key parameters. + * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} + * and {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4} + * for public key and hash algorithms. + * @param {module:enums.publicKey} algo Public key algorithm + * @param {module:enums.hash} hash_algo Hash algorithm + * @param {Array} msg_MPIs Algorithm-specific signature parameters + * @param {Array} pub_MPIs Algorithm-specific public key parameters + * @param {Uint8Array} data Data for which the signature was created + * @param {Uint8Array} hashed The hashed data + * @returns {Boolean} True if signature is valid + * @async + */ + verify: async function verify(algo, hash_algo, msg_MPIs, pub_MPIs, data, hashed) { + const types = _crypto2.default.getPubKeyParamTypes(algo); + if (pub_MPIs.length < types.length) { + throw new Error('Missing public key parameters'); + } + switch (algo) { + case _enums2.default.publicKey.rsa_encrypt_sign: + case _enums2.default.publicKey.rsa_encrypt: + case _enums2.default.publicKey.rsa_sign: + { + const m = msg_MPIs[0].toBN(); + const n = pub_MPIs[0].toBN(); + const e = pub_MPIs[1].toBN(); + const EM = await _public_key2.default.rsa.verify(m, n, e); + const EM2 = await _pkcs2.default.emsa.encode(hash_algo, hashed, n.byteLength()); + return _util2.default.Uint8Array_to_hex(EM) === EM2; + } + case _enums2.default.publicKey.dsa: + { + const r = msg_MPIs[0].toBN(); + const s = msg_MPIs[1].toBN(); + const p = pub_MPIs[0].toBN(); + const q = pub_MPIs[1].toBN(); + const g = pub_MPIs[2].toBN(); + const y = pub_MPIs[3].toBN(); + return _public_key2.default.dsa.verify(hash_algo, r, s, hashed, g, p, q, y); + } + case _enums2.default.publicKey.ecdsa: + { + const oid = pub_MPIs[0]; + const signature = { r: msg_MPIs[0].toUint8Array(), s: msg_MPIs[1].toUint8Array() }; + const Q = pub_MPIs[1].toUint8Array(); + return _public_key2.default.elliptic.ecdsa.verify(oid, hash_algo, signature, data, Q, hashed); + } + case _enums2.default.publicKey.eddsa: + { + const oid = pub_MPIs[0]; + // EdDSA signature params are expected in little-endian format + const signature = { + R: msg_MPIs[0].toUint8Array('le', 32), + S: msg_MPIs[1].toUint8Array('le', 32) + }; + const Q = pub_MPIs[1].toUint8Array('be', 33); + return _public_key2.default.elliptic.eddsa.verify(oid, hash_algo, signature, data, Q, hashed); + } + default: + throw new Error('Invalid signature algorithm.'); + } + }, + + /** + * Creates a signature on data using specified algorithms and private key parameters. + * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} + * and {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4} + * for public key and hash algorithms. + * @param {module:enums.publicKey} algo Public key algorithm + * @param {module:enums.hash} hash_algo Hash algorithm + * @param {Array} key_params Algorithm-specific public and private key parameters + * @param {Uint8Array} data Data to be signed + * @param {Uint8Array} hashed The hashed data + * @returns {Uint8Array} Signature + * @async + */ + sign: async function sign(algo, hash_algo, key_params, data, hashed) { + const types = [].concat(_crypto2.default.getPubKeyParamTypes(algo), _crypto2.default.getPrivKeyParamTypes(algo)); + if (key_params.length < types.length) { + throw new Error('Missing private key parameters'); + } + switch (algo) { + case _enums2.default.publicKey.rsa_encrypt_sign: + case _enums2.default.publicKey.rsa_encrypt: + case _enums2.default.publicKey.rsa_sign: + { + const n = key_params[0].toBN(); + const e = key_params[1].toBN(); + const d = key_params[2].toBN(); + const m = new _bn2.default((await _pkcs2.default.emsa.encode(hash_algo, hashed, n.byteLength())), 16); + const signature = await _public_key2.default.rsa.sign(m, n, e, d); + return _util2.default.Uint8Array_to_MPI(signature); + } + case _enums2.default.publicKey.dsa: + { + const p = key_params[0].toBN(); + const q = key_params[1].toBN(); + const g = key_params[2].toBN(); + const x = key_params[4].toBN(); + const signature = await _public_key2.default.dsa.sign(hash_algo, hashed, g, p, q, x); + return _util2.default.concatUint8Array([_util2.default.Uint8Array_to_MPI(signature.r), _util2.default.Uint8Array_to_MPI(signature.s)]); + } + case _enums2.default.publicKey.elgamal: + { + throw new Error('Signing with Elgamal is not defined in the OpenPGP standard.'); + } + case _enums2.default.publicKey.ecdsa: + { + const oid = key_params[0]; + const d = key_params[2].toUint8Array(); + const signature = await _public_key2.default.elliptic.ecdsa.sign(oid, hash_algo, data, d, hashed); + return _util2.default.concatUint8Array([_util2.default.Uint8Array_to_MPI(signature.r), _util2.default.Uint8Array_to_MPI(signature.s)]); + } + case _enums2.default.publicKey.eddsa: + { + const oid = key_params[0]; + const d = key_params[2].toUint8Array('be', 32); + const signature = await _public_key2.default.elliptic.eddsa.sign(oid, hash_algo, data, d, hashed); + return _util2.default.concatUint8Array([_util2.default.Uint8Array_to_MPI(signature.R), _util2.default.Uint8Array_to_MPI(signature.S)]); + } + default: + throw new Error('Invalid signature algorithm.'); + } + } +}; + +},{"../enums":113,"../util":152,"./crypto":89,"./pkcs1":96,"./public_key":106,"bn.js":16}],111:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _webStreamTools = require('web-stream-tools'); + +var _webStreamTools2 = _interopRequireDefault(_webStreamTools); + +var _base = require('./base64.js'); + +var _base2 = _interopRequireDefault(_base); + +var _enums = require('../enums.js'); + +var _enums2 = _interopRequireDefault(_enums); + +var _config = require('../config'); + +var _config2 = _interopRequireDefault(_config); + +var _util = require('../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Finds out which Ascii Armoring type is used. Throws error if unknown type. + * @private + * @param {String} text [String] ascii armored text + * @returns {Integer} 0 = MESSAGE PART n of m + * 1 = MESSAGE PART n + * 2 = SIGNED MESSAGE + * 3 = PGP MESSAGE + * 4 = PUBLIC KEY BLOCK + * 5 = PRIVATE KEY BLOCK + * 6 = SIGNATURE + */ +function getType(text) { + const reHeader = /^-----BEGIN PGP (MESSAGE, PART \d+\/\d+|MESSAGE, PART \d+|SIGNED MESSAGE|MESSAGE|PUBLIC KEY BLOCK|PRIVATE KEY BLOCK|SIGNATURE)-----$/m; + + const header = text.match(reHeader); + + if (!header) { + throw new Error('Unknown ASCII armor type'); + } + + // BEGIN PGP MESSAGE, PART X/Y + // Used for multi-part messages, where the armor is split amongst Y + // parts, and this is the Xth part out of Y. + if (/MESSAGE, PART \d+\/\d+/.test(header[1])) { + return _enums2.default.armor.multipart_section; + } else + // BEGIN PGP MESSAGE, PART X + // Used for multi-part messages, where this is the Xth part of an + // unspecified number of parts. Requires the MESSAGE-ID Armor + // Header to be used. + if (/MESSAGE, PART \d+/.test(header[1])) { + return _enums2.default.armor.multipart_last; + } else + // BEGIN PGP SIGNED MESSAGE + if (/SIGNED MESSAGE/.test(header[1])) { + return _enums2.default.armor.signed; + } else + // BEGIN PGP MESSAGE + // Used for signed, encrypted, or compressed files. + if (/MESSAGE/.test(header[1])) { + return _enums2.default.armor.message; + } else + // BEGIN PGP PUBLIC KEY BLOCK + // Used for armoring public keys. + if (/PUBLIC KEY BLOCK/.test(header[1])) { + return _enums2.default.armor.public_key; + } else + // BEGIN PGP PRIVATE KEY BLOCK + // Used for armoring private keys. + if (/PRIVATE KEY BLOCK/.test(header[1])) { + return _enums2.default.armor.private_key; + } else + // BEGIN PGP SIGNATURE + // Used for detached signatures, OpenPGP/MIME signatures, and + // cleartext signatures. Note that PGP 2.x uses BEGIN PGP MESSAGE + // for detached signatures. + if (/SIGNATURE/.test(header[1])) { + return _enums2.default.armor.signature; + } +} + +/** + * Add additional information to the armor version of an OpenPGP binary + * packet block. + * @author Alex + * @version 2011-12-16 + * @param {String} customComment (optional) additional comment to add to the armored string + * @returns {String} The header information + */ +// GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @requires web-stream-tools + * @requires encoding/base64 + * @requires enums + * @requires config + * @requires util + * @module encoding/armor + */ + +function addheader(customComment) { + let result = ""; + if (_config2.default.show_version) { + result += "Version: " + _config2.default.versionstring + '\r\n'; + } + if (_config2.default.show_comment) { + result += "Comment: " + _config2.default.commentstring + '\r\n'; + } + if (customComment) { + result += "Comment: " + customComment + '\r\n'; + } + result += '\r\n'; + return result; +} + +/** + * Calculates a checksum over the given data and returns it base64 encoded + * @param {String | ReadableStream} data Data to create a CRC-24 checksum for + * @returns {String | ReadableStream} Base64 encoded checksum + */ +function getCheckSum(data) { + const crc = createcrc24(data); + return _base2.default.encode(crc); +} + +const crc_table = [0x00000000, 0x00864cfb, 0x018ad50d, 0x010c99f6, 0x0393e6e1, 0x0315aa1a, 0x021933ec, 0x029f7f17, 0x07a18139, 0x0727cdc2, 0x062b5434, 0x06ad18cf, 0x043267d8, 0x04b42b23, 0x05b8b2d5, 0x053efe2e, 0x0fc54e89, 0x0f430272, 0x0e4f9b84, 0x0ec9d77f, 0x0c56a868, 0x0cd0e493, 0x0ddc7d65, 0x0d5a319e, 0x0864cfb0, 0x08e2834b, 0x09ee1abd, 0x09685646, 0x0bf72951, 0x0b7165aa, 0x0a7dfc5c, 0x0afbb0a7, 0x1f0cd1e9, 0x1f8a9d12, 0x1e8604e4, 0x1e00481f, 0x1c9f3708, 0x1c197bf3, 0x1d15e205, 0x1d93aefe, 0x18ad50d0, 0x182b1c2b, 0x192785dd, 0x19a1c926, 0x1b3eb631, 0x1bb8faca, 0x1ab4633c, 0x1a322fc7, 0x10c99f60, 0x104fd39b, 0x11434a6d, 0x11c50696, 0x135a7981, 0x13dc357a, 0x12d0ac8c, 0x1256e077, 0x17681e59, 0x17ee52a2, 0x16e2cb54, 0x166487af, 0x14fbf8b8, 0x147db443, 0x15712db5, 0x15f7614e, 0x3e19a3d2, 0x3e9fef29, 0x3f9376df, 0x3f153a24, 0x3d8a4533, 0x3d0c09c8, 0x3c00903e, 0x3c86dcc5, 0x39b822eb, 0x393e6e10, 0x3832f7e6, 0x38b4bb1d, 0x3a2bc40a, 0x3aad88f1, 0x3ba11107, 0x3b275dfc, 0x31dced5b, 0x315aa1a0, 0x30563856, 0x30d074ad, 0x324f0bba, 0x32c94741, 0x33c5deb7, 0x3343924c, 0x367d6c62, 0x36fb2099, 0x37f7b96f, 0x3771f594, 0x35ee8a83, 0x3568c678, 0x34645f8e, 0x34e21375, 0x2115723b, 0x21933ec0, 0x209fa736, 0x2019ebcd, 0x228694da, 0x2200d821, 0x230c41d7, 0x238a0d2c, 0x26b4f302, 0x2632bff9, 0x273e260f, 0x27b86af4, 0x252715e3, 0x25a15918, 0x24adc0ee, 0x242b8c15, 0x2ed03cb2, 0x2e567049, 0x2f5ae9bf, 0x2fdca544, 0x2d43da53, 0x2dc596a8, 0x2cc90f5e, 0x2c4f43a5, 0x2971bd8b, 0x29f7f170, 0x28fb6886, 0x287d247d, 0x2ae25b6a, 0x2a641791, 0x2b688e67, 0x2beec29c, 0x7c3347a4, 0x7cb50b5f, 0x7db992a9, 0x7d3fde52, 0x7fa0a145, 0x7f26edbe, 0x7e2a7448, 0x7eac38b3, 0x7b92c69d, 0x7b148a66, 0x7a181390, 0x7a9e5f6b, 0x7801207c, 0x78876c87, 0x798bf571, 0x790db98a, 0x73f6092d, 0x737045d6, 0x727cdc20, 0x72fa90db, 0x7065efcc, 0x70e3a337, 0x71ef3ac1, 0x7169763a, 0x74578814, 0x74d1c4ef, 0x75dd5d19, 0x755b11e2, 0x77c46ef5, 0x7742220e, 0x764ebbf8, 0x76c8f703, 0x633f964d, 0x63b9dab6, 0x62b54340, 0x62330fbb, 0x60ac70ac, 0x602a3c57, 0x6126a5a1, 0x61a0e95a, 0x649e1774, 0x64185b8f, 0x6514c279, 0x65928e82, 0x670df195, 0x678bbd6e, 0x66872498, 0x66016863, 0x6cfad8c4, 0x6c7c943f, 0x6d700dc9, 0x6df64132, 0x6f693e25, 0x6fef72de, 0x6ee3eb28, 0x6e65a7d3, 0x6b5b59fd, 0x6bdd1506, 0x6ad18cf0, 0x6a57c00b, 0x68c8bf1c, 0x684ef3e7, 0x69426a11, 0x69c426ea, 0x422ae476, 0x42aca88d, 0x43a0317b, 0x43267d80, 0x41b90297, 0x413f4e6c, 0x4033d79a, 0x40b59b61, 0x458b654f, 0x450d29b4, 0x4401b042, 0x4487fcb9, 0x461883ae, 0x469ecf55, 0x479256a3, 0x47141a58, 0x4defaaff, 0x4d69e604, 0x4c657ff2, 0x4ce33309, 0x4e7c4c1e, 0x4efa00e5, 0x4ff69913, 0x4f70d5e8, 0x4a4e2bc6, 0x4ac8673d, 0x4bc4fecb, 0x4b42b230, 0x49ddcd27, 0x495b81dc, 0x4857182a, 0x48d154d1, 0x5d26359f, 0x5da07964, 0x5cace092, 0x5c2aac69, 0x5eb5d37e, 0x5e339f85, 0x5f3f0673, 0x5fb94a88, 0x5a87b4a6, 0x5a01f85d, 0x5b0d61ab, 0x5b8b2d50, 0x59145247, 0x59921ebc, 0x589e874a, 0x5818cbb1, 0x52e37b16, 0x526537ed, 0x5369ae1b, 0x53efe2e0, 0x51709df7, 0x51f6d10c, 0x50fa48fa, 0x507c0401, 0x5542fa2f, 0x55c4b6d4, 0x54c82f22, 0x544e63d9, 0x56d11cce, 0x56575035, 0x575bc9c3, 0x57dd8538]; + +/** + * Internal function to calculate a CRC-24 checksum over a given string (data) + * @param {String | ReadableStream} data Data to create a CRC-24 checksum for + * @returns {Uint8Array | ReadableStream} The CRC-24 checksum + */ +function createcrc24(input) { + let crc = 0xB704CE; + return _webStreamTools2.default.transform(input, value => { + for (let index = 0; index < value.length; index++) { + crc = crc << 8 ^ crc_table[(crc >> 16 ^ value[index]) & 0xff]; + } + }, () => new Uint8Array([crc >> 16, crc >> 8, crc])); +} + +/** + * Verify armored headers. RFC4880, section 6.3: "OpenPGP should consider improperly formatted + * Armor Headers to be corruption of the ASCII Armor." + * @private + * @param {Array} headers Armor headers + */ +function verifyHeaders(headers) { + for (let i = 0; i < headers.length; i++) { + if (!/^([^\s:]|[^\s:][^:]*[^\s:]): .+$/.test(headers[i])) { + throw new Error('Improperly formatted armor header: ' + headers[i]); + } + if (!/^(Version|Comment|MessageID|Hash|Charset): .+$/.test(headers[i])) { + _util2.default.print_debug_error(new Error('Unknown header: ' + headers[i])); + } + } +} + +/** + * Splits a message into two parts, the body and the checksum. This is an internal function + * @param {String} text OpenPGP armored message part + * @returns {Object} An object with attribute "body" containing the body + * and an attribute "checksum" containing the checksum. + */ +function splitChecksum(text) { + let body = text; + let checksum = ""; + + const lastEquals = text.lastIndexOf("="); + + if (lastEquals >= 0 && lastEquals !== text.length - 1) { + // '=' as the last char means no checksum + body = text.slice(0, lastEquals); + checksum = text.slice(lastEquals + 1).substr(0, 4); + } + + return { body: body, checksum: checksum }; +} + +/** + * DeArmor an OpenPGP armored message; verify the checksum and return + * the encoded bytes + * @param {String} text OpenPGP armored message + * @returns {Promise} An object with attribute "text" containing the message text, + * an attribute "data" containing a stream of bytes and "type" for the ASCII armor type + * @async + * @static + */ +function dearmor(input) { + return new Promise(async (resolve, reject) => { + try { + const reSplit = /^-----[^-]+-----$/m; + const reEmptyLine = /^[ \f\r\t\u00a0\u2000-\u200a\u202f\u205f\u3000]*$/; + + let type; + const headers = []; + let lastHeaders = headers; + let headersDone; + let text = []; + let textDone; + let checksum; + let data = _base2.default.decode(_webStreamTools2.default.transformPair(input, async (readable, writable) => { + const reader = _webStreamTools2.default.getReader(readable); + try { + while (true) { + let line = await reader.readLine(); + if (line === undefined) { + throw new Error('Misformed armored text'); + } + // remove trailing whitespace at end of lines + line = _util2.default.removeTrailingSpaces(line.replace(/[\r\n]/g, '')); + if (!type) { + if (reSplit.test(line)) { + type = getType(line); + } + } else if (!headersDone) { + if (reSplit.test(line)) { + reject(new Error('Mandatory blank line missing between armor headers and armor data')); + } + if (!reEmptyLine.test(line)) { + lastHeaders.push(line); + } else { + verifyHeaders(lastHeaders); + headersDone = true; + if (textDone || type !== 2) { + resolve({ text, data, headers, type }); + break; + } + } + } else if (!textDone && type === 2) { + if (!reSplit.test(line)) { + // Reverse dash-escaping for msg + text.push(line.replace(/^- /, '')); + } else { + text = text.join('\r\n'); + textDone = true; + verifyHeaders(lastHeaders); + lastHeaders = []; + headersDone = false; + } + } + } + } catch (e) { + reject(e); + return; + } + const writer = _webStreamTools2.default.getWriter(writable); + try { + while (true) { + await writer.ready; + + var _ref = await reader.read(); + + const done = _ref.done, + value = _ref.value; + + if (done) { + throw new Error('Misformed armored text'); + } + const line = value + ''; + if (line.indexOf('=') === -1 && line.indexOf('-') === -1) { + await writer.write(line); + } else { + let remainder = await reader.readToEnd(); + if (!remainder.length) remainder = ''; + remainder = line + remainder; + remainder = _util2.default.removeTrailingSpaces(remainder.replace(/\r/g, '')); + const parts = remainder.split(reSplit); + if (parts.length === 1) { + throw new Error('Misformed armored text'); + } + const split = splitChecksum(parts[0].slice(0, -1)); + checksum = split.checksum; + await writer.write(split.body); + break; + } + } + await writer.ready; + await writer.close(); + } catch (e) { + await writer.abort(e); + } + })); + data = _webStreamTools2.default.transformPair(data, async (readable, writable) => { + const checksumVerified = getCheckSum(_webStreamTools2.default.passiveClone(readable)); + await _webStreamTools2.default.pipe(readable, writable, { + preventClose: true + }); + const writer = _webStreamTools2.default.getWriter(writable); + try { + const checksumVerifiedString = await _webStreamTools2.default.readToEnd(checksumVerified); + if (checksum !== checksumVerifiedString && (checksum || _config2.default.checksum_required)) { + throw new Error("Ascii armor integrity check on message failed: '" + checksum + "' should be '" + checksumVerifiedString + "'"); + } + await writer.ready; + await writer.close(); + } catch (e) { + await writer.abort(e); + } + }); + } catch (e) { + reject(e); + } + }); +} + +/** + * Armor an OpenPGP binary packet block + * @param {Integer} messagetype type of the message + * @param body + * @param {Integer} partindex + * @param {Integer} parttotal + * @param {String} customComment (optional) additional comment to add to the armored string + * @returns {String | ReadableStream} Armored text + * @static + */ +function armor(messagetype, body, partindex, parttotal, customComment) { + let text; + let hash; + if (messagetype === _enums2.default.armor.signed) { + text = body.text; + hash = body.hash; + body = body.data; + } + const bodyClone = _webStreamTools2.default.passiveClone(body); + const result = []; + switch (messagetype) { + case _enums2.default.armor.multipart_section: + result.push("-----BEGIN PGP MESSAGE, PART " + partindex + "/" + parttotal + "-----\r\n"); + result.push(addheader(customComment)); + result.push(_base2.default.encode(body)); + result.push("\r\n=", getCheckSum(bodyClone), "\r\n"); + result.push("-----END PGP MESSAGE, PART " + partindex + "/" + parttotal + "-----\r\n"); + break; + case _enums2.default.armor.multipart_last: + result.push("-----BEGIN PGP MESSAGE, PART " + partindex + "-----\r\n"); + result.push(addheader(customComment)); + result.push(_base2.default.encode(body)); + result.push("\r\n=", getCheckSum(bodyClone), "\r\n"); + result.push("-----END PGP MESSAGE, PART " + partindex + "-----\r\n"); + break; + case _enums2.default.armor.signed: + result.push("\r\n-----BEGIN PGP SIGNED MESSAGE-----\r\n"); + result.push("Hash: " + hash + "\r\n\r\n"); + result.push(text.replace(/^-/mg, "- -")); + result.push("\r\n-----BEGIN PGP SIGNATURE-----\r\n"); + result.push(addheader(customComment)); + result.push(_base2.default.encode(body)); + result.push("\r\n=", getCheckSum(bodyClone), "\r\n"); + result.push("-----END PGP SIGNATURE-----\r\n"); + break; + case _enums2.default.armor.message: + result.push("-----BEGIN PGP MESSAGE-----\r\n"); + result.push(addheader(customComment)); + result.push(_base2.default.encode(body)); + result.push("\r\n=", getCheckSum(bodyClone), "\r\n"); + result.push("-----END PGP MESSAGE-----\r\n"); + break; + case _enums2.default.armor.public_key: + result.push("-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n"); + result.push(addheader(customComment)); + result.push(_base2.default.encode(body)); + result.push("\r\n=", getCheckSum(bodyClone), "\r\n"); + result.push("-----END PGP PUBLIC KEY BLOCK-----\r\n"); + break; + case _enums2.default.armor.private_key: + result.push("-----BEGIN PGP PRIVATE KEY BLOCK-----\r\n"); + result.push(addheader(customComment)); + result.push(_base2.default.encode(body)); + result.push("\r\n=", getCheckSum(bodyClone), "\r\n"); + result.push("-----END PGP PRIVATE KEY BLOCK-----\r\n"); + break; + case _enums2.default.armor.signature: + result.push("-----BEGIN PGP SIGNATURE-----\r\n"); + result.push(addheader(customComment)); + result.push(_base2.default.encode(body)); + result.push("\r\n=", getCheckSum(bodyClone), "\r\n"); + result.push("-----END PGP SIGNATURE-----\r\n"); + break; + } + + return _util2.default.concat(result); +} + +exports.default = { + encode: armor, + decode: dearmor +}; + +},{"../config":79,"../enums.js":113,"../util":152,"./base64.js":112,"web-stream-tools":75}],112:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _webStreamTools = require('web-stream-tools'); + +var _webStreamTools2 = _interopRequireDefault(_webStreamTools); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const b64s = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; // Standard radix-64 +/* OpenPGP radix-64/base64 string encoding/decoding + * Copyright 2005 Herbert Hanewinkel, www.haneWIN.de + * version 1.0, check www.haneWIN.de for the latest version + * + * This software is provided as-is, without express or implied warranty. + * Permission to use, copy, modify, distribute or sell this software, with or + * without fee, for any purpose and by any individual or organization, is hereby + * granted, provided that the above copyright notice and this paragraph appear + * in all copies. Distribution as a part of an application or binary must + * include the above copyright notice in the documentation and/or other materials + * provided with the application or distribution. + */ + +/** + * @requires web-stream-tools + * @module encoding/base64 + */ + +const b64u = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'; // URL-safe radix-64 + +const b64toByte = []; +for (let i = 0; i < b64s.length; i++) { + b64toByte[b64s.charCodeAt(i)] = i; +} +b64toByte[b64u.charCodeAt(62)] = 62; +b64toByte[b64u.charCodeAt(63)] = 63; + +/** + * Convert binary array to radix-64 + * @param {Uint8Array | ReadableStream} t Uint8Array to convert + * @param {bool} u if true, output is URL-safe + * @returns {String | ReadableStream} radix-64 version of input string + * @static + */ +function s2r(t, u = false) { + // TODO check btoa alternative + const b64 = u ? b64u : b64s; + let a; + let c; + + let l = 0; + let s = 0; + + return _webStreamTools2.default.transform(t, value => { + const r = []; + const tl = value.length; + for (let n = 0; n < tl; n++) { + if (l && l % 60 === 0 && !u) { + r.push("\r\n"); + } + c = value[n]; + if (s === 0) { + r.push(b64.charAt(c >> 2 & 63)); + a = (c & 3) << 4; + } else if (s === 1) { + r.push(b64.charAt(a | c >> 4 & 15)); + a = (c & 15) << 2; + } else if (s === 2) { + r.push(b64.charAt(a | c >> 6 & 3)); + l += 1; + if (l % 60 === 0 && !u) { + r.push("\r\n"); + } + r.push(b64.charAt(c & 63)); + } + l += 1; + s += 1; + if (s === 3) { + s = 0; + } + } + return r.join(''); + }, () => { + const r = []; + if (s > 0) { + r.push(b64.charAt(a)); + l += 1; + if (l % 60 === 0 && !u) { + r.push("\r\n"); + } + if (!u) { + r.push('='); + l += 1; + } + } + if (s === 1 && !u) { + if (l % 60 === 0 && !u) { + r.push("\r\n"); + } + r.push('='); + } + return r.join(''); + }); +} + +/** + * Convert radix-64 to binary array + * @param {String | ReadableStream} t radix-64 string to convert + * @param {bool} u if true, input is interpreted as URL-safe + * @returns {Uint8Array | ReadableStream} binary array version of input string + * @static + */ +function r2s(t, u) { + // TODO check atob alternative + let c; + + let s = 0; + let a = 0; + + return _webStreamTools2.default.transform(t, value => { + const tl = value.length; + const r = new Uint8Array(Math.ceil(0.75 * tl)); + let index = 0; + for (let n = 0; n < tl; n++) { + c = b64toByte[value.charCodeAt(n)]; + if (c >= 0) { + if (s) { + r[index++] = a | c >> 6 - s & 255; + } + s = s + 2 & 7; + a = c << s & 255; + } + } + return r.subarray(0, index); + }); +} + +exports.default = { + encode: s2r, + decode: r2s +}; + +},{"web-stream-tools":75}],113:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +/** + * @module enums + */ + +const byValue = Symbol('byValue'); + +exports.default = { + + /** Maps curve names under various standards to one + * @see {@link https://wiki.gnupg.org/ECC|ECC - GnuPG wiki} + * @enum {String} + * @readonly + */ + curve: { + /** NIST P-256 Curve */ + "p256": "p256", + "P-256": "p256", + "secp256r1": "p256", + "prime256v1": "p256", + "1.2.840.10045.3.1.7": "p256", + "2a8648ce3d030107": "p256", + "2A8648CE3D030107": "p256", + + /** NIST P-384 Curve */ + "p384": "p384", + "P-384": "p384", + "secp384r1": "p384", + "1.3.132.0.34": "p384", + "2b81040022": "p384", + "2B81040022": "p384", + + /** NIST P-521 Curve */ + "p521": "p521", + "P-521": "p521", + "secp521r1": "p521", + "1.3.132.0.35": "p521", + "2b81040023": "p521", + "2B81040023": "p521", + + /** SECG SECP256k1 Curve */ + "secp256k1": "secp256k1", + "1.3.132.0.10": "secp256k1", + "2b8104000a": "secp256k1", + "2B8104000A": "secp256k1", + + /** Ed25519 */ + "ED25519": "ed25519", + "ed25519": "ed25519", + "Ed25519": "ed25519", + "1.3.6.1.4.1.11591.15.1": "ed25519", + "2b06010401da470f01": "ed25519", + "2B06010401DA470F01": "ed25519", + + /** Curve25519 */ + "X25519": "curve25519", + "cv25519": "curve25519", + "curve25519": "curve25519", + "Curve25519": "curve25519", + "1.3.6.1.4.1.3029.1.5.1": "curve25519", + "2b060104019755010501": "curve25519", + "2B060104019755010501": "curve25519", + + /** BrainpoolP256r1 Curve */ + "brainpoolP256r1": "brainpoolP256r1", + "1.3.36.3.3.2.8.1.1.7": "brainpoolP256r1", + "2b2403030208010107": "brainpoolP256r1", + "2B2403030208010107": "brainpoolP256r1", + + /** BrainpoolP384r1 Curve */ + "brainpoolP384r1": "brainpoolP384r1", + "1.3.36.3.3.2.8.1.1.11": "brainpoolP384r1", + "2b240303020801010b": "brainpoolP384r1", + "2B240303020801010B": "brainpoolP384r1", + + /** BrainpoolP512r1 Curve */ + "brainpoolP512r1": "brainpoolP512r1", + "1.3.36.3.3.2.8.1.1.13": "brainpoolP512r1", + "2b240303020801010d": "brainpoolP512r1", + "2B240303020801010D": "brainpoolP512r1" + }, + + /** A string to key specifier type + * @enum {Integer} + * @readonly + */ + s2k: { + simple: 0, + salted: 1, + iterated: 3, + gnu: 101 + }, + + /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-9.1|RFC4880bis-04, section 9.1} + * @enum {Integer} + * @readonly + */ + publicKey: { + /** RSA (Encrypt or Sign) [HAC] */ + rsa_encrypt_sign: 1, + /** RSA (Encrypt only) [HAC] */ + rsa_encrypt: 2, + /** RSA (Sign only) [HAC] */ + rsa_sign: 3, + /** Elgamal (Encrypt only) [ELGAMAL] [HAC] */ + elgamal: 16, + /** DSA (Sign only) [FIPS186] [HAC] */ + dsa: 17, + /** ECDH (Encrypt only) [RFC6637] */ + ecdh: 18, + /** ECDSA (Sign only) [RFC6637] */ + ecdsa: 19, + /** EdDSA (Sign only) + * [{@link https://tools.ietf.org/html/draft-koch-eddsa-for-openpgp-04|Draft RFC}] */ + eddsa: 22, + /** Reserved for AEDH */ + aedh: 23, + /** Reserved for AEDSA */ + aedsa: 24 + }, + + /** {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC4880, section 9.2} + * @enum {Integer} + * @readonly + */ + symmetric: { + plaintext: 0, + /** Not implemented! */ + idea: 1, + '3des': 2, + tripledes: 2, + cast5: 3, + blowfish: 4, + aes128: 7, + aes192: 8, + aes256: 9, + twofish: 10 + }, + + /** {@link https://tools.ietf.org/html/rfc4880#section-9.3|RFC4880, section 9.3} + * @enum {Integer} + * @readonly + */ + compression: { + uncompressed: 0, + /** RFC1951 */ + zip: 1, + /** RFC1950 */ + zlib: 2, + bzip2: 3 + }, + + /** {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC4880, section 9.4} + * @enum {Integer} + * @readonly + */ + hash: { + md5: 1, + sha1: 2, + ripemd: 3, + sha256: 8, + sha384: 9, + sha512: 10, + sha224: 11 + }, + + /** A list of hash names as accepted by webCrypto functions. + * {@link https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest|Parameters, algo} + * @enum {String} + */ + webHash: { + 'SHA-1': 2, + 'SHA-256': 8, + 'SHA-384': 9, + 'SHA-512': 10 + }, + + /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-9.6|RFC4880bis-04, section 9.6} + * @enum {Integer} + * @readonly + */ + aead: { + eax: 1, + ocb: 2, + experimental_gcm: 100 // Private algorithm + }, + + /** A list of packet types and numeric tags associated with them. + * @enum {Integer} + * @readonly + */ + packet: { + publicKeyEncryptedSessionKey: 1, + signature: 2, + symEncryptedSessionKey: 3, + onePassSignature: 4, + secretKey: 5, + publicKey: 6, + secretSubkey: 7, + compressed: 8, + symmetricallyEncrypted: 9, + marker: 10, + literal: 11, + trust: 12, + userid: 13, + publicSubkey: 14, + userAttribute: 17, + symEncryptedIntegrityProtected: 18, + modificationDetectionCode: 19, + symEncryptedAEADProtected: 20 // see IETF draft: https://tools.ietf.org/html/draft-ford-openpgp-format-00#section-2.1 + }, + + /** Data types in the literal packet + * @enum {Integer} + * @readonly + */ + literal: { + /** Binary data 'b' */ + binary: 'b'.charCodeAt(), + /** Text data 't' */ + text: 't'.charCodeAt(), + /** Utf8 data 'u' */ + utf8: 'u'.charCodeAt(), + /** MIME message body part 'm' */ + mime: 'm'.charCodeAt() + }, + + /** One pass signature packet type + * @enum {Integer} + * @readonly + */ + signature: { + /** 0x00: Signature of a binary document. */ + binary: 0, + /** 0x01: Signature of a canonical text document. + * + * Canonicalyzing the document by converting line endings. */ + text: 1, + /** 0x02: Standalone signature. + * + * This signature is a signature of only its own subpacket contents. + * It is calculated identically to a signature over a zero-lengh + * binary document. Note that it doesn't make sense to have a V3 + * standalone signature. */ + standalone: 2, + /** 0x10: Generic certification of a User ID and Public-Key packet. + * + * The issuer of this certification does not make any particular + * assertion as to how well the certifier has checked that the owner + * of the key is in fact the person described by the User ID. */ + cert_generic: 16, + /** 0x11: Persona certification of a User ID and Public-Key packet. + * + * The issuer of this certification has not done any verification of + * the claim that the owner of this key is the User ID specified. */ + cert_persona: 17, + /** 0x12: Casual certification of a User ID and Public-Key packet. + * + * The issuer of this certification has done some casual + * verification of the claim of identity. */ + cert_casual: 18, + /** 0x13: Positive certification of a User ID and Public-Key packet. + * + * The issuer of this certification has done substantial + * verification of the claim of identity. + * + * Most OpenPGP implementations make their "key signatures" as 0x10 + * certifications. Some implementations can issue 0x11-0x13 + * certifications, but few differentiate between the types. */ + cert_positive: 19, + /** 0x30: Certification revocation signature + * + * This signature revokes an earlier User ID certification signature + * (signature class 0x10 through 0x13) or direct-key signature + * (0x1F). It should be issued by the same key that issued the + * revoked signature or an authorized revocation key. The signature + * is computed over the same data as the certificate that it + * revokes, and should have a later creation date than that + * certificate. */ + cert_revocation: 48, + /** 0x18: Subkey Binding Signature + * + * This signature is a statement by the top-level signing key that + * indicates that it owns the subkey. This signature is calculated + * directly on the primary key and subkey, and not on any User ID or + * other packets. A signature that binds a signing subkey MUST have + * an Embedded Signature subpacket in this binding signature that + * contains a 0x19 signature made by the signing subkey on the + * primary key and subkey. */ + subkey_binding: 24, + /** 0x19: Primary Key Binding Signature + * + * This signature is a statement by a signing subkey, indicating + * that it is owned by the primary key and subkey. This signature + * is calculated the same way as a 0x18 signature: directly on the + * primary key and subkey, and not on any User ID or other packets. + * + * When a signature is made over a key, the hash data starts with the + * octet 0x99, followed by a two-octet length of the key, and then body + * of the key packet. (Note that this is an old-style packet header for + * a key packet with two-octet length.) A subkey binding signature + * (type 0x18) or primary key binding signature (type 0x19) then hashes + * the subkey using the same format as the main key (also using 0x99 as + * the first octet). */ + key_binding: 25, + /** 0x1F: Signature directly on a key + * + * This signature is calculated directly on a key. It binds the + * information in the Signature subpackets to the key, and is + * appropriate to be used for subpackets that provide information + * about the key, such as the Revocation Key subpacket. It is also + * appropriate for statements that non-self certifiers want to make + * about the key itself, rather than the binding between a key and a + * name. */ + key: 31, + /** 0x20: Key revocation signature + * + * The signature is calculated directly on the key being revoked. A + * revoked key is not to be used. Only revocation signatures by the + * key being revoked, or by an authorized revocation key, should be + * considered valid revocation signatures.a */ + key_revocation: 32, + /** 0x28: Subkey revocation signature + * + * The signature is calculated directly on the subkey being revoked. + * A revoked subkey is not to be used. Only revocation signatures + * by the top-level signature key that is bound to this subkey, or + * by an authorized revocation key, should be considered valid + * revocation signatures. + * + * Key revocation signatures (types 0x20 and 0x28) + * hash only the key being revoked. */ + subkey_revocation: 40, + /** 0x40: Timestamp signature. + * This signature is only meaningful for the timestamp contained in + * it. */ + timestamp: 64, + /** 0x50: Third-Party Confirmation signature. + * + * This signature is a signature over some other OpenPGP Signature + * packet(s). It is analogous to a notary seal on the signed data. + * A third-party signature SHOULD include Signature Target + * subpacket(s) to give easy identification. Note that we really do + * mean SHOULD. There are plausible uses for this (such as a blind + * party that only sees the signature, not the key or source + * document) that cannot include a target subpacket. */ + third_party: 80 + }, + + /** Signature subpacket type + * @enum {Integer} + * @readonly + */ + signatureSubpacket: { + signature_creation_time: 2, + signature_expiration_time: 3, + exportable_certification: 4, + trust_signature: 5, + regular_expression: 6, + revocable: 7, + key_expiration_time: 9, + placeholder_backwards_compatibility: 10, + preferred_symmetric_algorithms: 11, + revocation_key: 12, + issuer: 16, + notation_data: 20, + preferred_hash_algorithms: 21, + preferred_compression_algorithms: 22, + key_server_preferences: 23, + preferred_key_server: 24, + primary_user_id: 25, + policy_uri: 26, + key_flags: 27, + signers_user_id: 28, + reason_for_revocation: 29, + features: 30, + signature_target: 31, + embedded_signature: 32, + issuer_fingerprint: 33, + preferred_aead_algorithms: 34 + }, + + /** Key flags + * @enum {Integer} + * @readonly + */ + keyFlags: { + /** 0x01 - This key may be used to certify other keys. */ + certify_keys: 1, + /** 0x02 - This key may be used to sign data. */ + sign_data: 2, + /** 0x04 - This key may be used to encrypt communications. */ + encrypt_communication: 4, + /** 0x08 - This key may be used to encrypt storage. */ + encrypt_storage: 8, + /** 0x10 - The private component of this key may have been split + * by a secret-sharing mechanism. */ + split_private_key: 16, + /** 0x20 - This key may be used for authentication. */ + authentication: 32, + /** 0x80 - The private component of this key may be in the + * possession of more than one person. */ + shared_private_key: 128 + }, + + /** Key status + * @enum {Integer} + * @readonly + */ + keyStatus: { + invalid: 0, + expired: 1, + revoked: 2, + valid: 3, + no_self_cert: 4 + }, + + /** Armor type + * @enum {Integer} + * @readonly + */ + armor: { + multipart_section: 0, + multipart_last: 1, + signed: 2, + message: 3, + public_key: 4, + private_key: 5, + signature: 6 + }, + + /** {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.23|RFC4880, section 5.2.3.23} + * @enum {Integer} + * @readonly + */ + reasonForRevocation: { + /** No reason specified (key revocations or cert revocations) */ + no_reason: 0, + /** Key is superseded (key revocations) */ + key_superseded: 1, + /** Key material has been compromised (key revocations) */ + key_compromised: 2, + /** Key is retired and no longer used (key revocations) */ + key_retired: 3, + /** User ID information is no longer valid (cert revocations) */ + userid_invalid: 32 + }, + + /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.2.3.25|RFC4880bis-04, section 5.2.3.25} + * @enum {Integer} + * @readonly + */ + features: { + /** 0x01 - Modification Detection (packets 18 and 19) */ + modification_detection: 1, + /** 0x02 - AEAD Encrypted Data Packet (packet 20) and version 5 + * Symmetric-Key Encrypted Session Key Packets (packet 3) */ + aead: 2, + /** 0x04 - Version 5 Public-Key Packet format and corresponding new + * fingerprint format */ + v5_keys: 4 + }, + + /** Asserts validity and converts from string/integer to integer. */ + write: function write(type, e) { + if (typeof e === 'number') { + e = this.read(type, e); + } + + if (type[e] !== undefined) { + return type[e]; + } + + throw new Error('Invalid enum value.'); + }, + + /** Converts from an integer to string. */ + read: function read(type, e) { + if (!type[byValue]) { + type[byValue] = []; + Object.entries(type).forEach(([key, value]) => { + type[byValue][value] = key; + }); + } + + if (type[byValue][e] !== undefined) { + return type[byValue][e]; + } + + throw new Error('Invalid enum value.'); + } + +}; + +},{}],114:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _config = require('./config'); + +var _config2 = _interopRequireDefault(_config); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Initialize the HKP client and configure it with the key server url and fetch function. + * @constructor + * @param {String} keyServerBaseUrl (optional) The HKP key server base url including + * the protocol to use, e.g. 'https://pgp.mit.edu'; defaults to + * openpgp.config.keyserver (https://keyserver.ubuntu.com) + */ +function HKP(keyServerBaseUrl) { + this._baseUrl = keyServerBaseUrl || _config2.default.keyserver; + this._fetch = typeof window !== 'undefined' ? window.fetch : require('node-fetch'); +} + +/** + * Search for a public key on the key server either by key ID or part of the user ID. + * @param {String} options.keyID The long public key ID. + * @param {String} options.query This can be any part of the key user ID such as name + * or email address. + * @returns {Promise} The ascii armored public key. + * @async + */ +// OpenPGP.js - An OpenPGP implementation in javascript +// Copyright (C) 2015 Tankred Hase +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @fileoverview This class implements a client for the OpenPGP HTTP Keyserver Protocol (HKP) + * in order to lookup and upload keys on standard public key servers. + * @module hkp + */ + +HKP.prototype.lookup = function (options) { + let uri = this._baseUrl + '/pks/lookup?op=get&options=mr&search='; + const fetch = this._fetch; + + if (options.keyId) { + uri += '0x' + encodeURIComponent(options.keyId); + } else if (options.query) { + uri += encodeURIComponent(options.query); + } else { + throw new Error('You must provide a query parameter!'); + } + + return fetch(uri).then(function (response) { + if (response.status === 200) { + return response.text(); + } + }).then(function (publicKeyArmored) { + if (!publicKeyArmored || publicKeyArmored.indexOf('-----END PGP PUBLIC KEY BLOCK-----') < 0) { + return; + } + return publicKeyArmored.trim(); + }); +}; + +/** + * Upload a public key to the server. + * @param {String} publicKeyArmored An ascii armored public key to be uploaded. + * @returns {Promise} + * @async + */ +HKP.prototype.upload = function (publicKeyArmored) { + const uri = this._baseUrl + '/pks/add'; + const fetch = this._fetch; + + return fetch(uri, { + method: 'post', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' + }, + body: 'keytext=' + encodeURIComponent(publicKeyArmored) + }); +}; + +exports.default = HKP; + +},{"./config":79,"node-fetch":"node-fetch"}],115:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.WKD = exports.HKP = exports.AsyncProxy = exports.Keyring = exports.crypto = exports.config = exports.enums = exports.armor = exports.stream = exports.OID = exports.KDFParams = exports.ECDHSymmetricKey = exports.Keyid = exports.S2K = exports.MPI = exports.packet = exports.util = exports.cleartext = exports.message = exports.signature = exports.key = exports.destroyWorker = exports.getWorker = exports.initWorker = exports.decryptSessionKeys = exports.encryptSessionKey = exports.decryptKey = exports.revokeKey = exports.reformatKey = exports.generateKey = exports.verify = exports.sign = exports.decrypt = exports.encrypt = undefined; + +var _openpgp = require('./openpgp'); + +Object.defineProperty(exports, 'encrypt', { + enumerable: true, + get: function get() { + return _openpgp.encrypt; + } +}); +Object.defineProperty(exports, 'decrypt', { + enumerable: true, + get: function get() { + return _openpgp.decrypt; + } +}); +Object.defineProperty(exports, 'sign', { + enumerable: true, + get: function get() { + return _openpgp.sign; + } +}); +Object.defineProperty(exports, 'verify', { + enumerable: true, + get: function get() { + return _openpgp.verify; + } +}); +Object.defineProperty(exports, 'generateKey', { + enumerable: true, + get: function get() { + return _openpgp.generateKey; + } +}); +Object.defineProperty(exports, 'reformatKey', { + enumerable: true, + get: function get() { + return _openpgp.reformatKey; + } +}); +Object.defineProperty(exports, 'revokeKey', { + enumerable: true, + get: function get() { + return _openpgp.revokeKey; + } +}); +Object.defineProperty(exports, 'decryptKey', { + enumerable: true, + get: function get() { + return _openpgp.decryptKey; + } +}); +Object.defineProperty(exports, 'encryptSessionKey', { + enumerable: true, + get: function get() { + return _openpgp.encryptSessionKey; + } +}); +Object.defineProperty(exports, 'decryptSessionKeys', { + enumerable: true, + get: function get() { + return _openpgp.decryptSessionKeys; + } +}); +Object.defineProperty(exports, 'initWorker', { + enumerable: true, + get: function get() { + return _openpgp.initWorker; + } +}); +Object.defineProperty(exports, 'getWorker', { + enumerable: true, + get: function get() { + return _openpgp.getWorker; + } +}); +Object.defineProperty(exports, 'destroyWorker', { + enumerable: true, + get: function get() { + return _openpgp.destroyWorker; + } +}); + +var _util = require('./util'); + +Object.defineProperty(exports, 'util', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_util).default; + } +}); + +var _packet = require('./packet'); + +Object.defineProperty(exports, 'packet', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_packet).default; + } +}); + +var _mpi = require('./type/mpi'); + +Object.defineProperty(exports, 'MPI', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_mpi).default; + } +}); + +var _s2k = require('./type/s2k'); + +Object.defineProperty(exports, 'S2K', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_s2k).default; + } +}); + +var _keyid = require('./type/keyid'); + +Object.defineProperty(exports, 'Keyid', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_keyid).default; + } +}); + +var _ecdh_symkey = require('./type/ecdh_symkey'); + +Object.defineProperty(exports, 'ECDHSymmetricKey', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_ecdh_symkey).default; + } +}); + +var _kdf_params = require('./type/kdf_params'); + +Object.defineProperty(exports, 'KDFParams', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_kdf_params).default; + } +}); + +var _oid = require('./type/oid'); + +Object.defineProperty(exports, 'OID', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_oid).default; + } +}); + +var _webStreamTools = require('web-stream-tools'); + +Object.defineProperty(exports, 'stream', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_webStreamTools).default; + } +}); + +var _armor = require('./encoding/armor'); + +Object.defineProperty(exports, 'armor', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_armor).default; + } +}); + +var _enums = require('./enums'); + +Object.defineProperty(exports, 'enums', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_enums).default; + } +}); + +var _config = require('./config/config'); + +Object.defineProperty(exports, 'config', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_config).default; + } +}); + +var _crypto = require('./crypto'); + +Object.defineProperty(exports, 'crypto', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_crypto).default; + } +}); + +var _keyring = require('./keyring'); + +Object.defineProperty(exports, 'Keyring', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_keyring).default; + } +}); + +var _async_proxy = require('./worker/async_proxy'); + +Object.defineProperty(exports, 'AsyncProxy', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_async_proxy).default; + } +}); + +var _hkp = require('./hkp'); + +Object.defineProperty(exports, 'HKP', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_hkp).default; + } +}); + +var _wkd = require('./wkd'); + +Object.defineProperty(exports, 'WKD', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_wkd).default; + } +}); + +var openpgp = _interopRequireWildcard(_openpgp); + +var _key = require('./key'); + +var keyMod = _interopRequireWildcard(_key); + +var _signature = require('./signature'); + +var signatureMod = _interopRequireWildcard(_signature); + +var _message = require('./message'); + +var messageMod = _interopRequireWildcard(_message); + +var _cleartext = require('./cleartext'); + +var cleartextMod = _interopRequireWildcard(_cleartext); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = openpgp; + +/** + * Export each high level api function separately. + * Usage: + * + * import { encryptMessage } from 'openpgp.js' + * encryptMessage(keys, text) + */ +/* eslint-disable import/newline-after-import, import/first */ + +/** + * Export high level api as default. + * Usage: + * + * import openpgp from 'openpgp.js' + * openpgp.encryptMessage(keys, text) + */ + + +/** + * @see module:key + * @name module:openpgp.key + */ + +const key = exports.key = keyMod; + +/** + * @see module:signature + * @name module:openpgp.signature + */ +const signature = exports.signature = signatureMod; + +/** + * @see module:message + * @name module:openpgp.message + */ +const message = exports.message = messageMod; + +/** + * @see module:cleartext + * @name module:openpgp.cleartext + */ +const cleartext = exports.cleartext = cleartextMod; + +/** + * @see module:util + * @name module:openpgp.util + */ + +},{"./cleartext":77,"./config/config":78,"./crypto":94,"./encoding/armor":111,"./enums":113,"./hkp":114,"./key":116,"./keyring":117,"./message":120,"./openpgp":121,"./packet":125,"./signature":145,"./type/ecdh_symkey":146,"./type/kdf_params":147,"./type/keyid":148,"./type/mpi":149,"./type/oid":150,"./type/s2k":151,"./util":152,"./wkd":153,"./worker/async_proxy":154,"web-stream-tools":75}],116:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); // GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @requires encoding/armor + * @requires crypto + * @requires packet + * @requires config + * @requires enums + * @requires util + * @module key + */ + +exports.Key = Key; +exports.createSignaturePacket = createSignaturePacket; +exports.read = read; +exports.readArmored = readArmored; +exports.generate = generate; +exports.reformat = reformat; +exports.getPreferredHashAlgo = getPreferredHashAlgo; +exports.getPreferredAlgo = getPreferredAlgo; +exports.isAeadSupported = isAeadSupported; + +var _armor = require('./encoding/armor'); + +var _armor2 = _interopRequireDefault(_armor); + +var _crypto = require('./crypto'); + +var _crypto2 = _interopRequireDefault(_crypto); + +var _packet = require('./packet'); + +var _packet2 = _interopRequireDefault(_packet); + +var _config = require('./config'); + +var _config2 = _interopRequireDefault(_config); + +var _enums = require('./enums'); + +var _enums2 = _interopRequireDefault(_enums); + +var _util = require('./util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * @class + * @classdesc Class that represents an OpenPGP key. Must contain a primary key. + * Can contain additional subkeys, signatures, user ids, user attributes. + * @param {module:packet.List} packetlist The packets that form this key + * @borrows module:packet.PublicKey#getKeyId as Key#getKeyId + * @borrows module:packet.PublicKey#getFingerprint as Key#getFingerprint + * @borrows module:packet.PublicKey#hasSameFingerprintAs as Key#hasSameFingerprintAs + * @borrows module:packet.PublicKey#getAlgorithmInfo as Key#getAlgorithmInfo + * @borrows module:packet.PublicKey#getCreationTime as Key#getCreationTime + * @borrows module:packet.PublicKey#isDecrypted as Key#isDecrypted + */ +function Key(packetlist) { + if (!(this instanceof Key)) { + return new Key(packetlist); + } + // same data as in packetlist but in structured form + this.keyPacket = null; + this.revocationSignatures = []; + this.directSignatures = []; + this.users = []; + this.subKeys = []; + this.packetlist2structure(packetlist); + if (!this.keyPacket || !this.users.length) { + throw new Error('Invalid key: need at least key and user ID packet'); + } +} + +Object.defineProperty(Key.prototype, 'primaryKey', { + get() { + return this.keyPacket; + }, + configurable: true, + enumerable: true +}); + +/** + * Transforms packetlist to structured key data + * @param {module:packet.List} packetlist The packets that form a key + */ +Key.prototype.packetlist2structure = function (packetlist) { + let user; + let primaryKeyId; + let subKey; + for (let i = 0; i < packetlist.length; i++) { + switch (packetlist[i].tag) { + case _enums2.default.packet.publicKey: + case _enums2.default.packet.secretKey: + this.keyPacket = packetlist[i]; + primaryKeyId = this.getKeyId(); + break; + case _enums2.default.packet.userid: + case _enums2.default.packet.userAttribute: + user = new User(packetlist[i]); + this.users.push(user); + break; + case _enums2.default.packet.publicSubkey: + case _enums2.default.packet.secretSubkey: + user = null; + subKey = new SubKey(packetlist[i]); + this.subKeys.push(subKey); + break; + case _enums2.default.packet.signature: + switch (packetlist[i].signatureType) { + case _enums2.default.signature.cert_generic: + case _enums2.default.signature.cert_persona: + case _enums2.default.signature.cert_casual: + case _enums2.default.signature.cert_positive: + if (!user) { + _util2.default.print_debug('Dropping certification signatures without preceding user packet'); + continue; + } + if (packetlist[i].issuerKeyId.equals(primaryKeyId)) { + checkRevocationKey(packetlist[i], primaryKeyId); + user.selfCertifications.push(packetlist[i]); + } else { + user.otherCertifications.push(packetlist[i]); + } + break; + case _enums2.default.signature.cert_revocation: + if (user) { + user.revocationSignatures.push(packetlist[i]); + } else { + this.directSignatures.push(packetlist[i]); + } + break; + case _enums2.default.signature.key: + checkRevocationKey(packetlist[i], primaryKeyId); + this.directSignatures.push(packetlist[i]); + break; + case _enums2.default.signature.subkey_binding: + if (!subKey) { + _util2.default.print_debug('Dropping subkey binding signature without preceding subkey packet'); + continue; + } + checkRevocationKey(packetlist[i], primaryKeyId); + subKey.bindingSignatures.push(packetlist[i]); + break; + case _enums2.default.signature.key_revocation: + this.revocationSignatures.push(packetlist[i]); + break; + case _enums2.default.signature.subkey_revocation: + if (!subKey) { + _util2.default.print_debug('Dropping subkey revocation signature without preceding subkey packet'); + continue; + } + subKey.revocationSignatures.push(packetlist[i]); + break; + } + break; + } + } +}; + +/** + * Transforms structured key data to packetlist + * @returns {module:packet.List} The packets that form a key + */ +Key.prototype.toPacketlist = function () { + const packetlist = new _packet2.default.List(); + packetlist.push(this.keyPacket); + packetlist.concat(this.revocationSignatures); + packetlist.concat(this.directSignatures); + this.users.map(user => packetlist.concat(user.toPacketlist())); + this.subKeys.map(subKey => packetlist.concat(subKey.toPacketlist())); + return packetlist; +}; + +/** + * Returns an array containing all public or private subkeys matching keyId; + * If keyId is not present, returns all subkeys. + * @param {type/keyid} keyId + * @returns {Array} + */ +Key.prototype.getSubkeys = function (keyId = null) { + const subKeys = []; + this.subKeys.forEach(subKey => { + if (!keyId || subKey.getKeyId().equals(keyId, true)) { + subKeys.push(subKey); + } + }); + return subKeys; +}; + +/** + * Returns an array containing all public or private keys matching keyId. + * If keyId is not present, returns all keys starting with the primary key. + * @param {type/keyid} keyId + * @returns {Array} + */ +Key.prototype.getKeys = function (keyId = null) { + const keys = []; + if (!keyId || this.getKeyId().equals(keyId, true)) { + keys.push(this); + } + return keys.concat(this.getSubkeys(keyId)); +}; + +/** + * Returns key IDs of all keys + * @returns {Array} + */ +Key.prototype.getKeyIds = function () { + return this.getKeys().map(key => key.getKeyId()); +}; + +/** + * Returns userids + * @returns {Array} array of userids + */ +Key.prototype.getUserIds = function () { + return this.users.map(user => { + return user.userId ? user.userId.userid : null; + }).filter(userid => userid !== null); +}; + +/** + * Returns true if this is a public key + * @returns {Boolean} + */ +Key.prototype.isPublic = function () { + return this.keyPacket.tag === _enums2.default.packet.publicKey; +}; + +/** + * Returns true if this is a private key + * @returns {Boolean} + */ +Key.prototype.isPrivate = function () { + return this.keyPacket.tag === _enums2.default.packet.secretKey; +}; + +/** + * Returns key as public key (shallow copy) + * @returns {module:key.Key} new public Key + */ +Key.prototype.toPublic = function () { + const packetlist = new _packet2.default.List(); + const keyPackets = this.toPacketlist(); + let bytes; + let pubKeyPacket; + let pubSubkeyPacket; + for (let i = 0; i < keyPackets.length; i++) { + switch (keyPackets[i].tag) { + case _enums2.default.packet.secretKey: + bytes = keyPackets[i].writePublicKey(); + pubKeyPacket = new _packet2.default.PublicKey(); + pubKeyPacket.read(bytes); + packetlist.push(pubKeyPacket); + break; + case _enums2.default.packet.secretSubkey: + bytes = keyPackets[i].writePublicKey(); + pubSubkeyPacket = new _packet2.default.PublicSubkey(); + pubSubkeyPacket.read(bytes); + packetlist.push(pubSubkeyPacket); + break; + default: + packetlist.push(keyPackets[i]); + } + } + return new Key(packetlist); +}; + +/** + * Returns ASCII armored text of key + * @returns {ReadableStream} ASCII armor + */ +Key.prototype.armor = function () { + const type = this.isPublic() ? _enums2.default.armor.public_key : _enums2.default.armor.private_key; + return _armor2.default.encode(type, this.toPacketlist().write()); +}; + +/** + * Returns the valid and non-expired signature that has the latest creation date, while ignoring signatures created in the future. + * @param {Array} signatures List of signatures + * @param {Date} date Use the given date instead of the current time + * @returns {Promise} The latest valid signature + * @async + */ +async function getLatestValidSignature(signatures, primaryKey, signatureType, dataToVerify, date = new Date()) { + let signature; + for (let i = signatures.length - 1; i >= 0; i--) { + if ((!signature || signatures[i].created >= signature.created) && + // check binding signature is not expired (ie, check for V4 expiration time) + !signatures[i].isExpired(date) && ( + // check binding signature is verified + signatures[i].verified || (await signatures[i].verify(primaryKey, signatureType, dataToVerify)))) { + signature = signatures[i]; + } + } + return signature; +} + +/** + * Returns last created key or key by given keyId that is available for signing and verification + * @param {module:type/keyid} keyId, optional + * @param {Date} date (optional) use the given date for verification instead of the current time + * @param {Object} userId, optional user ID + * @returns {Promise} key or null if no signing key has been found + * @async + */ +Key.prototype.getSigningKey = async function (keyId = null, date = new Date(), userId = {}) { + const primaryKey = this.keyPacket; + if ((await this.verifyPrimaryKey(date, userId)) === _enums2.default.keyStatus.valid) { + const subKeys = this.subKeys.slice().sort((a, b) => b.keyPacket.created - a.keyPacket.created); + for (let i = 0; i < subKeys.length; i++) { + if (!keyId || subKeys[i].getKeyId().equals(keyId)) { + if ((await subKeys[i].verify(primaryKey, date)) === _enums2.default.keyStatus.valid) { + const dataToVerify = { key: primaryKey, bind: subKeys[i].keyPacket }; + const bindingSignature = await getLatestValidSignature(subKeys[i].bindingSignatures, primaryKey, _enums2.default.signature.subkey_binding, dataToVerify, date); + if (bindingSignature && bindingSignature.embeddedSignature && isValidSigningKeyPacket(subKeys[i].keyPacket, bindingSignature) && (await getLatestValidSignature([bindingSignature.embeddedSignature], subKeys[i].keyPacket, _enums2.default.signature.key_binding, dataToVerify, date))) { + return subKeys[i]; + } + } + } + } + const primaryUser = await this.getPrimaryUser(date, userId); + if (primaryUser && (!keyId || primaryKey.getKeyId().equals(keyId)) && isValidSigningKeyPacket(primaryKey, primaryUser.selfCertification)) { + return this; + } + } + return null; + + function isValidSigningKeyPacket(keyPacket, signature) { + if (!signature.verified || signature.revoked !== false) { + // Sanity check + throw new Error('Signature not verified'); + } + return keyPacket.algorithm !== _enums2.default.read(_enums2.default.publicKey, _enums2.default.publicKey.rsa_encrypt) && keyPacket.algorithm !== _enums2.default.read(_enums2.default.publicKey, _enums2.default.publicKey.elgamal) && keyPacket.algorithm !== _enums2.default.read(_enums2.default.publicKey, _enums2.default.publicKey.ecdh) && (!signature.keyFlags || (signature.keyFlags[0] & _enums2.default.keyFlags.sign_data) !== 0); + } +}; + +/** + * Returns last created key or key by given keyId that is available for encryption or decryption + * @param {module:type/keyid} keyId, optional + * @param {Date} date, optional + * @param {String} userId, optional + * @returns {Promise} key or null if no encryption key has been found + * @async + */ +Key.prototype.getEncryptionKey = async function (keyId, date = new Date(), userId = {}) { + const primaryKey = this.keyPacket; + if ((await this.verifyPrimaryKey(date, userId)) === _enums2.default.keyStatus.valid) { + // V4: by convention subkeys are preferred for encryption service + const subKeys = this.subKeys.slice().sort((a, b) => b.keyPacket.created - a.keyPacket.created); + for (let i = 0; i < subKeys.length; i++) { + if (!keyId || subKeys[i].getKeyId().equals(keyId)) { + if ((await subKeys[i].verify(primaryKey, date)) === _enums2.default.keyStatus.valid) { + const dataToVerify = { key: primaryKey, bind: subKeys[i].keyPacket }; + const bindingSignature = await getLatestValidSignature(subKeys[i].bindingSignatures, primaryKey, _enums2.default.signature.subkey_binding, dataToVerify, date); + if (bindingSignature && isValidEncryptionKeyPacket(subKeys[i].keyPacket, bindingSignature)) { + return subKeys[i]; + } + } + } + } + // if no valid subkey for encryption, evaluate primary key + const primaryUser = await this.getPrimaryUser(date, userId); + if (primaryUser && (!keyId || primaryKey.getKeyId().equals(keyId)) && isValidEncryptionKeyPacket(primaryKey, primaryUser.selfCertification)) { + return this; + } + } + return null; + + function isValidEncryptionKeyPacket(keyPacket, signature) { + if (!signature.verified || signature.revoked !== false) { + // Sanity check + throw new Error('Signature not verified'); + } + return keyPacket.algorithm !== _enums2.default.read(_enums2.default.publicKey, _enums2.default.publicKey.dsa) && keyPacket.algorithm !== _enums2.default.read(_enums2.default.publicKey, _enums2.default.publicKey.rsa_sign) && keyPacket.algorithm !== _enums2.default.read(_enums2.default.publicKey, _enums2.default.publicKey.ecdsa) && keyPacket.algorithm !== _enums2.default.read(_enums2.default.publicKey, _enums2.default.publicKey.eddsa) && (!signature.keyFlags || (signature.keyFlags[0] & _enums2.default.keyFlags.encrypt_communication) !== 0 || (signature.keyFlags[0] & _enums2.default.keyFlags.encrypt_storage) !== 0); + } +}; + +/** + * Encrypts all secret key and subkey packets matching keyId + * @param {String|Array} passphrases - if multiple passphrases, then should be in same order as packets each should encrypt + * @param {module:type/keyid} keyId + * @returns {Promise>} + * @async + */ +Key.prototype.encrypt = async function (passphrases, keyId = null) { + if (!this.isPrivate()) { + throw new Error("Nothing to encrypt in a public key"); + } + + const keys = this.getKeys(keyId); + passphrases = _util2.default.isArray(passphrases) ? passphrases : new Array(keys.length).fill(passphrases); + if (passphrases.length !== keys.length) { + throw new Error("Invalid number of passphrases for key"); + } + + return Promise.all(keys.map(async function (key, i) { + const keyPacket = key.keyPacket; + + await keyPacket.encrypt(passphrases[i]); + keyPacket.clearPrivateParams(); + return keyPacket; + })); +}; + +/** + * Decrypts all secret key and subkey packets matching keyId + * @param {String|Array} passphrases + * @param {module:type/keyid} keyId + * @returns {Promise} true if all matching key and subkey packets decrypted successfully + * @async + */ +Key.prototype.decrypt = async function (passphrases, keyId = null) { + if (!this.isPrivate()) { + throw new Error("Nothing to decrypt in a public key"); + } + passphrases = _util2.default.isArray(passphrases) ? passphrases : [passphrases]; + + const results = await Promise.all(this.getKeys(keyId).map(async function (key) { + let decrypted = false; + let error = null; + await Promise.all(passphrases.map(async function (passphrase) { + try { + await key.keyPacket.decrypt(passphrase); + decrypted = true; + } catch (e) { + error = e; + } + })); + if (!decrypted) { + throw error; + } + return decrypted; + })); + return results.every(result => result === true); +}; + +/** + * Checks if a signature on a key is revoked + * @param {module:packet.SecretKey| + * @param {module:packet.Signature} signature The signature to verify + * @param {module:packet.PublicSubkey| + * module:packet.SecretSubkey| + * module:packet.PublicKey| + * module:packet.SecretKey} key, optional The key to verify the signature + * @param {Date} date Use the given date instead of the current time + * @returns {Promise} True if the certificate is revoked + * @async + */ +Key.prototype.isRevoked = async function (signature, key, date = new Date()) { + return isDataRevoked(this.keyPacket, _enums2.default.signature.key_revocation, { key: this.keyPacket }, this.revocationSignatures, signature, key, date); +}; + +/** + * Verify primary key. Checks for revocation signatures, expiration time + * and valid self signature + * @param {Date} date (optional) use the given date for verification instead of the current time + * @param {Object} userId (optional) user ID + * @returns {Promise} The status of the primary key + * @async + */ +Key.prototype.verifyPrimaryKey = async function (date = new Date(), userId = {}) { + const primaryKey = this.keyPacket; + // check for key revocation signatures + if (await this.isRevoked(null, null, date)) { + return _enums2.default.keyStatus.revoked; + } + // check for at least one self signature. Self signature of user ID not mandatory + // See {@link https://tools.ietf.org/html/rfc4880#section-11.1} + if (!this.users.some(user => user.userId && user.selfCertifications.length)) { + return _enums2.default.keyStatus.no_self_cert; + } + // check for valid, unrevoked, unexpired self signature + + var _ref = (await this.getPrimaryUser(date, userId)) || {}; + + const user = _ref.user, + selfCertification = _ref.selfCertification; + + if (!user) { + return _enums2.default.keyStatus.invalid; + } + // check for expiration time + if (isDataExpired(primaryKey, selfCertification, date)) { + return _enums2.default.keyStatus.expired; + } + return _enums2.default.keyStatus.valid; +}; + +/** + * Returns the latest date when the key can be used for encrypting, signing, or both, depending on the `capabilities` paramater. + * When `capabilities` is null, defaults to returning the expiry date of the primary key. + * Returns null if `capabilities` is passed and the key does not have the specified capabilities or is revoked or invalid. + * Returns Infinity if the key doesn't expire. + * @param {encrypt|sign|encrypt_sign} capabilities, optional + * @param {module:type/keyid} keyId, optional + * @param {Object} userId, optional user ID + * @returns {Promise} + * @async + */ +Key.prototype.getExpirationTime = async function (capabilities, keyId, userId) { + const primaryUser = await this.getPrimaryUser(null, userId); + if (!primaryUser) { + throw new Error('Could not find primary user'); + } + const selfCert = primaryUser.selfCertification; + const keyExpiry = getExpirationTime(this.keyPacket, selfCert); + const sigExpiry = selfCert.getExpirationTime(); + let expiry = keyExpiry < sigExpiry ? keyExpiry : sigExpiry; + if (capabilities === 'encrypt' || capabilities === 'encrypt_sign') { + const encryptKey = (await this.getEncryptionKey(keyId, expiry, userId)) || (await this.getEncryptionKey(keyId, null, userId)); + if (!encryptKey) return null; + const encryptExpiry = await encryptKey.getExpirationTime(this.keyPacket); + if (encryptExpiry < expiry) expiry = encryptExpiry; + } + if (capabilities === 'sign' || capabilities === 'encrypt_sign') { + const signKey = (await this.getSigningKey(keyId, expiry, userId)) || (await this.getSigningKey(keyId, null, userId)); + if (!signKey) return null; + const signExpiry = await signKey.getExpirationTime(this.keyPacket); + if (signExpiry < expiry) expiry = signExpiry; + } + return expiry; +}; + +/** + * Returns primary user and most significant (latest valid) self signature + * - if multiple primary users exist, returns the one with the latest self signature + * - otherwise, returns the user with the latest self signature + * @param {Date} date (optional) use the given date for verification instead of the current time + * @param {Object} userId (optional) user ID to get instead of the primary user, if it exists + * @returns {Promise<{user: module:key.User, + * selfCertification: module:packet.Signature}>} The primary user and the self signature + * @async + */ +Key.prototype.getPrimaryUser = async function (date = new Date(), userId = {}) { + const primaryKey = this.keyPacket; + const users = []; + for (let i = 0; i < this.users.length; i++) { + const user = this.users[i]; + if (!user.userId || !((userId.name === undefined || user.userId.name === userId.name) && (userId.email === undefined || user.userId.email === userId.email) && (userId.comment === undefined || user.userId.comment === userId.comment))) continue; + const dataToVerify = { userId: user.userId, key: primaryKey }; + const selfCertification = await getLatestValidSignature(user.selfCertifications, primaryKey, _enums2.default.signature.cert_generic, dataToVerify, date); + if (!selfCertification) continue; + users.push({ index: i, user, selfCertification }); + } + if (!users.length) { + if (userId.name !== undefined || userId.email !== undefined || userId.comment !== undefined) { + throw new Error('Could not find user that matches that user ID'); + } + return null; + } + await Promise.all(users.map(async function (a) { + return a.user.revoked || a.user.isRevoked(primaryKey, a.selfCertification, null, date); + })); + // sort by primary user flag and signature creation time + const primaryUser = users.sort(function (a, b) { + const A = a.selfCertification; + const B = b.selfCertification; + return B.revoked - A.revoked || A.isPrimaryUserID - B.isPrimaryUserID || A.created - B.created; + }).pop(); + const user = primaryUser.user, + cert = primaryUser.selfCertification; + + if (cert.revoked || (await user.isRevoked(primaryKey, cert, null, date))) { + return null; + } + return primaryUser; +}; + +/** + * Update key with new components from specified key with same key ID: + * users, subkeys, certificates are merged into the destination key, + * duplicates and expired signatures are ignored. + * + * If the specified key is a private key and the destination key is public, + * the destination key is transformed to a private key. + * @param {module:key.Key} key Source key to merge + * @returns {Promise} + * @async + */ +Key.prototype.update = async function (key) { + if ((await key.verifyPrimaryKey()) === _enums2.default.keyStatus.invalid) { + return; + } + if (!this.hasSameFingerprintAs(key)) { + throw new Error('Key update method: fingerprints of keys not equal'); + } + if (this.isPublic() && key.isPrivate()) { + // check for equal subkey packets + const equal = this.subKeys.length === key.subKeys.length && this.subKeys.every(destSubKey => { + return key.subKeys.some(srcSubKey => { + return destSubKey.hasSameFingerprintAs(srcSubKey); + }); + }); + if (!equal) { + throw new Error('Cannot update public key with private key if subkey mismatch'); + } + this.keyPacket = key.keyPacket; + } + // revocation signatures + await mergeSignatures(key, this, 'revocationSignatures', srcRevSig => { + return isDataRevoked(this.keyPacket, _enums2.default.signature.key_revocation, this, [srcRevSig], null, key.keyPacket); + }); + // direct signatures + await mergeSignatures(key, this, 'directSignatures'); + // TODO replace when Promise.some or Promise.any are implemented + // users + await Promise.all(key.users.map(async srcUser => { + let found = false; + await Promise.all(this.users.map(async dstUser => { + if (srcUser.userId && dstUser.userId && srcUser.userId.userid === dstUser.userId.userid || srcUser.userAttribute && srcUser.userAttribute.equals(dstUser.userAttribute)) { + await dstUser.update(srcUser, this.keyPacket); + found = true; + } + })); + if (!found) { + this.users.push(srcUser); + } + })); + // TODO replace when Promise.some or Promise.any are implemented + // subkeys + await Promise.all(key.subKeys.map(async srcSubKey => { + let found = false; + await Promise.all(this.subKeys.map(async dstSubKey => { + if (dstSubKey.hasSameFingerprintAs(srcSubKey)) { + await dstSubKey.update(srcSubKey, this.keyPacket); + found = true; + } + })); + if (!found) { + this.subKeys.push(srcSubKey); + } + })); +}; + +/** + * Merges signatures from source[attr] to dest[attr] + * @private + * @param {Object} source + * @param {Object} dest + * @param {String} attr + * @param {Function} checkFn optional, signature only merged if true + */ +async function mergeSignatures(source, dest, attr, checkFn) { + source = source[attr]; + if (source) { + if (!dest[attr].length) { + dest[attr] = source; + } else { + await Promise.all(source.map(async function (sourceSig) { + if (!sourceSig.isExpired() && (!checkFn || (await checkFn(sourceSig))) && !dest[attr].some(function (destSig) { + return _util2.default.equalsUint8Array(destSig.signature, sourceSig.signature); + })) { + dest[attr].push(sourceSig); + } + })); + } + } +} + +/** + * Revokes the key + * @param {Object} reasonForRevocation optional, object indicating the reason for revocation + * @param {module:enums.reasonForRevocation} reasonForRevocation.flag optional, flag indicating the reason for revocation + * @param {String} reasonForRevocation.string optional, string explaining the reason for revocation + * @param {Date} date optional, override the creationtime of the revocation signature + * @returns {Promise} new key with revocation signature + * @async + */ +Key.prototype.revoke = async function ({ + flag: reasonForRevocationFlag = _enums2.default.reasonForRevocation.no_reason, + string: reasonForRevocationString = '' +} = {}, date = new Date()) { + if (this.isPublic()) { + throw new Error('Need private key for revoking'); + } + const dataToSign = { key: this.keyPacket }; + const key = new Key(this.toPacketlist()); + key.revocationSignatures.push((await createSignaturePacket(dataToSign, null, this.keyPacket, { + signatureType: _enums2.default.signature.key_revocation, + reasonForRevocationFlag: _enums2.default.write(_enums2.default.reasonForRevocation, reasonForRevocationFlag), + reasonForRevocationString + }, date))); + return key; +}; + +/** + * Get revocation certificate from a revoked key. + * (To get a revocation certificate for an unrevoked key, call revoke() first.) + * @returns {Promise} armored revocation certificate + * @async + */ +Key.prototype.getRevocationCertificate = async function () { + const dataToVerify = { key: this.keyPacket }; + const revocationSignature = await getLatestValidSignature(this.revocationSignatures, this.keyPacket, _enums2.default.signature.key_revocation, dataToVerify); + if (revocationSignature) { + const packetlist = new _packet2.default.List(); + packetlist.push(revocationSignature); + return _armor2.default.encode(_enums2.default.armor.public_key, packetlist.write(), null, null, 'This is a revocation certificate'); + } +}; + +/** + * Applies a revocation certificate to a key + * This adds the first signature packet in the armored text to the key, + * if it is a valid revocation signature. + * @param {String} revocationCertificate armored revocation certificate + * @returns {Promise} new revoked key + * @async + */ +Key.prototype.applyRevocationCertificate = async function (revocationCertificate) { + const input = await _armor2.default.decode(revocationCertificate); + const packetlist = new _packet2.default.List(); + await packetlist.read(input.data); + const revocationSignature = packetlist.findPacket(_enums2.default.packet.signature); + if (!revocationSignature || revocationSignature.signatureType !== _enums2.default.signature.key_revocation) { + throw new Error('Could not find revocation signature packet'); + } + if (!revocationSignature.issuerKeyId.equals(this.getKeyId())) { + throw new Error('Revocation signature does not match key'); + } + if (revocationSignature.isExpired()) { + throw new Error('Revocation signature is expired'); + } + if (!(await revocationSignature.verify(this.keyPacket, _enums2.default.signature.key_revocation, { key: this.keyPacket }))) { + throw new Error('Could not verify revocation signature'); + } + const key = new Key(this.toPacketlist()); + key.revocationSignatures.push(revocationSignature); + return key; +}; + +/** + * Signs primary user of key + * @param {Array} privateKey decrypted private keys for signing + * @param {Date} date (optional) use the given date for verification instead of the current time + * @param {Object} userId (optional) user ID to get instead of the primary user, if it exists + * @returns {Promise} new public key with new certificate signature + * @async + */ +Key.prototype.signPrimaryUser = async function (privateKeys, date, userId) { + var _ref2 = (await this.getPrimaryUser(date, userId)) || {}; + + const index = _ref2.index, + user = _ref2.user; + + if (!user) { + throw new Error('Could not find primary user'); + } + const userSign = await user.sign(this.keyPacket, privateKeys); + const key = new Key(this.toPacketlist()); + key.users[index] = userSign; + return key; +}; + +/** + * Signs all users of key + * @param {Array} privateKeys decrypted private keys for signing + * @returns {Promise} new public key with new certificate signature + * @async + */ +Key.prototype.signAllUsers = async function (privateKeys) { + const that = this; + const key = new Key(this.toPacketlist()); + key.users = await Promise.all(this.users.map(function (user) { + return user.sign(that.keyPacket, privateKeys); + })); + return key; +}; + +/** + * Verifies primary user of key + * - if no arguments are given, verifies the self certificates; + * - otherwise, verifies all certificates signed with given keys. + * @param {Array} keys array of keys to verify certificate signatures + * @param {Date} date (optional) use the given date for verification instead of the current time + * @param {Object} userId (optional) user ID to get instead of the primary user, if it exists + * @returns {Promise>} List of signer's keyid and validity of signature + * @async + */ +Key.prototype.verifyPrimaryUser = async function (keys, date, userId) { + const primaryKey = this.keyPacket; + + var _ref3 = (await this.getPrimaryUser(date, userId)) || {}; + + const user = _ref3.user; + + if (!user) { + throw new Error('Could not find primary user'); + } + const results = keys ? await user.verifyAllCertifications(primaryKey, keys) : [{ keyid: primaryKey.keyid, valid: (await user.verify(primaryKey)) === _enums2.default.keyStatus.valid }]; + return results; +}; + +/** + * Verifies all users of key + * - if no arguments are given, verifies the self certificates; + * - otherwise, verifies all certificates signed with given keys. + * @param {Array} keys array of keys to verify certificate signatures + * @returns {Promise>} list of userid, signer's keyid and validity of signature + * @async + */ +Key.prototype.verifyAllUsers = async function (keys) { + const results = []; + const primaryKey = this.keyPacket; + await Promise.all(this.users.map(async function (user) { + const signatures = keys ? await user.verifyAllCertifications(primaryKey, keys) : [{ keyid: primaryKey.keyid, valid: (await user.verify(primaryKey)) === _enums2.default.keyStatus.valid }]; + signatures.forEach(signature => { + results.push({ + userid: user.userId.userid, + keyid: signature.keyid, + valid: signature.valid + }); + }); + })); + return results; +}; + +/** + * @class + * @classdesc Class that represents an user ID or attribute packet and the relevant signatures. + */ +function User(userPacket) { + if (!(this instanceof User)) { + return new User(userPacket); + } + this.userId = userPacket.tag === _enums2.default.packet.userid ? userPacket : null; + this.userAttribute = userPacket.tag === _enums2.default.packet.userAttribute ? userPacket : null; + this.selfCertifications = []; + this.otherCertifications = []; + this.revocationSignatures = []; +} + +/** + * Transforms structured user data to packetlist + * @returns {module:packet.List} + */ +User.prototype.toPacketlist = function () { + const packetlist = new _packet2.default.List(); + packetlist.push(this.userId || this.userAttribute); + packetlist.concat(this.revocationSignatures); + packetlist.concat(this.selfCertifications); + packetlist.concat(this.otherCertifications); + return packetlist; +}; + +/** + * Signs user + * @param {module:packet.SecretKey| + * module:packet.PublicKey} primaryKey The primary key packet + * @param {Array} privateKeys Decrypted private keys for signing + * @returns {Promise} New user with new certificate signatures + * @async + */ +User.prototype.sign = async function (primaryKey, privateKeys) { + const dataToSign = { + userId: this.userId, + userAttribute: this.userAttribute, + key: primaryKey + }; + const user = new User(dataToSign.userId || dataToSign.userAttribute); + user.otherCertifications = await Promise.all(privateKeys.map(async function (privateKey) { + if (privateKey.isPublic()) { + throw new Error('Need private key for signing'); + } + if (privateKey.hasSameFingerprintAs(primaryKey)) { + throw new Error('Not implemented for self signing'); + } + const signingKey = await privateKey.getSigningKey(); + if (!signingKey) { + throw new Error('Could not find valid signing key packet in key ' + privateKey.getKeyId().toHex()); + } + return createSignaturePacket(dataToSign, privateKey, signingKey.keyPacket, { + // Most OpenPGP implementations use generic certification (0x10) + signatureType: _enums2.default.signature.cert_generic, + keyFlags: [_enums2.default.keyFlags.certify_keys | _enums2.default.keyFlags.sign_data] + }); + })); + await user.update(this, primaryKey); + return user; +}; + +/** + * Checks if a given certificate of the user is revoked + * @param {module:packet.SecretKey| + * module:packet.PublicKey} primaryKey The primary key packet + * @param {module:packet.Signature} certificate The certificate to verify + * @param {module:packet.PublicSubkey| + * module:packet.SecretSubkey| + * module:packet.PublicKey| + * module:packet.SecretKey} key, optional The key to verify the signature + * @param {Date} date Use the given date instead of the current time + * @returns {Promise} True if the certificate is revoked + * @async + */ +User.prototype.isRevoked = async function (primaryKey, certificate, key, date = new Date()) { + return isDataRevoked(primaryKey, _enums2.default.signature.cert_revocation, { + key: primaryKey, + userId: this.userId, + userAttribute: this.userAttribute + }, this.revocationSignatures, certificate, key, date); +}; + +/** + * Create signature packet + * @param {Object} dataToSign Contains packets to be signed + * @param {module:packet.SecretKey| + * module:packet.SecretSubkey} signingKeyPacket secret key packet for signing + * @param {Object} signatureProperties (optional) properties to write on the signature packet before signing + * @param {Date} date (optional) override the creationtime of the signature + * @param {Object} userId (optional) user ID + * @param {Object} detached (optional) whether to create a detached signature packet + * @returns {module:packet/signature} signature packet + */ +async function createSignaturePacket(dataToSign, privateKey, signingKeyPacket, signatureProperties, date, userId, detached = false) { + if (!signingKeyPacket.isDecrypted()) { + throw new Error('Private key is not decrypted.'); + } + const signaturePacket = new _packet2.default.Signature(date); + Object.assign(signaturePacket, signatureProperties); + signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm; + signaturePacket.hashAlgorithm = await getPreferredHashAlgo(privateKey, signingKeyPacket, date, userId); + await signaturePacket.sign(signingKeyPacket, dataToSign, detached); + return signaturePacket; +} + +/** + * Verifies the user certificate + * @param {module:packet.SecretKey| + * module:packet.PublicKey} primaryKey The primary key packet + * @param {module:packet.Signature} certificate A certificate of this user + * @param {Array} keys Array of keys to verify certificate signatures + * @param {Date} date Use the given date instead of the current time + * @returns {Promise} status of the certificate + * @async + */ +User.prototype.verifyCertificate = async function (primaryKey, certificate, keys, date = new Date()) { + const that = this; + const keyid = certificate.issuerKeyId; + const dataToVerify = { + userId: this.userId, + userAttribute: this.userAttribute, + key: primaryKey + }; + const results = await Promise.all(keys.map(async function (key) { + if (!key.getKeyIds().some(id => id.equals(keyid))) { + return; + } + const signingKey = await key.getSigningKey(keyid, date); + if (certificate.revoked || (await that.isRevoked(primaryKey, certificate, signingKey.keyPacket, date))) { + return _enums2.default.keyStatus.revoked; + } + if (!(certificate.verified || (await certificate.verify(signingKey.keyPacket, _enums2.default.signature.cert_generic, dataToVerify)))) { + return _enums2.default.keyStatus.invalid; + } + if (certificate.isExpired(date)) { + return _enums2.default.keyStatus.expired; + } + return _enums2.default.keyStatus.valid; + })); + return results.find(result => result !== undefined); +}; + +/** + * Verifies all user certificates + * @param {module:packet.SecretKey| + * module:packet.PublicKey} primaryKey The primary key packet + * @param {Array} keys Array of keys to verify certificate signatures + * @param {Date} date Use the given date instead of the current time + * @returns {Promise>} List of signer's keyid and validity of signature + * @async + */ +User.prototype.verifyAllCertifications = async function (primaryKey, keys, date = new Date()) { + const that = this; + const certifications = this.selfCertifications.concat(this.otherCertifications); + return Promise.all(certifications.map(async function (certification) { + const status = await that.verifyCertificate(primaryKey, certification, keys, date); + return { + keyid: certification.issuerKeyId, + valid: status === undefined ? null : status === _enums2.default.keyStatus.valid + }; + })); +}; + +/** + * Verify User. Checks for existence of self signatures, revocation signatures + * and validity of self signature + * @param {module:packet.SecretKey| + * module:packet.PublicKey} primaryKey The primary key packet + * @param {Date} date Use the given date instead of the current time + * @returns {Promise} Status of user + * @async + */ +User.prototype.verify = async function (primaryKey, date = new Date()) { + if (!this.selfCertifications.length) { + return _enums2.default.keyStatus.no_self_cert; + } + const that = this; + const dataToVerify = { + userId: this.userId, + userAttribute: this.userAttribute, + key: primaryKey + }; + // TODO replace when Promise.some or Promise.any are implemented + const results = [_enums2.default.keyStatus.invalid].concat((await Promise.all(this.selfCertifications.map(async function (selfCertification) { + if (selfCertification.revoked || (await that.isRevoked(primaryKey, selfCertification, undefined, date))) { + return _enums2.default.keyStatus.revoked; + } + if (!(selfCertification.verified || (await selfCertification.verify(primaryKey, _enums2.default.signature.cert_generic, dataToVerify)))) { + return _enums2.default.keyStatus.invalid; + } + if (selfCertification.isExpired(date)) { + return _enums2.default.keyStatus.expired; + } + return _enums2.default.keyStatus.valid; + })))); + return results.some(status => status === _enums2.default.keyStatus.valid) ? _enums2.default.keyStatus.valid : results.pop(); +}; + +/** + * Update user with new components from specified user + * @param {module:key.User} user Source user to merge + * @param {module:packet.SecretKey| + * module:packet.SecretSubkey} primaryKey primary key used for validation + * @returns {Promise} + * @async + */ +User.prototype.update = async function (user, primaryKey) { + const dataToVerify = { + userId: this.userId, + userAttribute: this.userAttribute, + key: primaryKey + }; + // self signatures + await mergeSignatures(user, this, 'selfCertifications', async function (srcSelfSig) { + return srcSelfSig.verified || srcSelfSig.verify(primaryKey, _enums2.default.signature.cert_generic, dataToVerify); + }); + // other signatures + await mergeSignatures(user, this, 'otherCertifications'); + // revocation signatures + await mergeSignatures(user, this, 'revocationSignatures', function (srcRevSig) { + return isDataRevoked(primaryKey, _enums2.default.signature.cert_revocation, dataToVerify, [srcRevSig]); + }); +}; + +/** + * @class + * @classdesc Class that represents a subkey packet and the relevant signatures. + * @borrows module:packet.PublicSubkey#getKeyId as SubKey#getKeyId + * @borrows module:packet.PublicSubkey#getFingerprint as SubKey#getFingerprint + * @borrows module:packet.PublicSubkey#hasSameFingerprintAs as SubKey#hasSameFingerprintAs + * @borrows module:packet.PublicSubkey#getAlgorithmInfo as SubKey#getAlgorithmInfo + * @borrows module:packet.PublicSubkey#getCreationTime as SubKey#getCreationTime + * @borrows module:packet.PublicSubkey#isDecrypted as SubKey#isDecrypted + */ +function SubKey(subKeyPacket) { + if (!(this instanceof SubKey)) { + return new SubKey(subKeyPacket); + } + this.keyPacket = subKeyPacket; + this.bindingSignatures = []; + this.revocationSignatures = []; +} + +/** + * Transforms structured subkey data to packetlist + * @returns {module:packet.List} + */ +SubKey.prototype.toPacketlist = function () { + const packetlist = new _packet2.default.List(); + packetlist.push(this.keyPacket); + packetlist.concat(this.revocationSignatures); + packetlist.concat(this.bindingSignatures); + return packetlist; +}; + +/** + * Checks if a binding signature of a subkey is revoked + * @param {module:packet.SecretKey| + * module:packet.PublicKey} primaryKey The primary key packet + * @param {module:packet.Signature} signature The binding signature to verify + * @param {module:packet.PublicSubkey| + * module:packet.SecretSubkey| + * module:packet.PublicKey| + * module:packet.SecretKey} key, optional The key to verify the signature + * @param {Date} date Use the given date instead of the current time + * @returns {Promise} True if the binding signature is revoked + * @async + */ +SubKey.prototype.isRevoked = async function (primaryKey, signature, key, date = new Date()) { + return isDataRevoked(primaryKey, _enums2.default.signature.subkey_revocation, { + key: primaryKey, + bind: this.keyPacket + }, this.revocationSignatures, signature, key, date); +}; + +/** + * Verify subkey. Checks for revocation signatures, expiration time + * and valid binding signature + * @param {module:packet.SecretKey| + * module:packet.PublicKey} primaryKey The primary key packet + * @param {Date} date Use the given date instead of the current time + * @returns {Promise} The status of the subkey + * @async + */ +SubKey.prototype.verify = async function (primaryKey, date = new Date()) { + const that = this; + const dataToVerify = { key: primaryKey, bind: this.keyPacket }; + // check subkey binding signatures + const bindingSignature = await getLatestValidSignature(this.bindingSignatures, primaryKey, _enums2.default.signature.subkey_binding, dataToVerify, date); + // check binding signature is verified + if (!bindingSignature) { + return _enums2.default.keyStatus.invalid; + } + // check binding signature is not revoked + if (bindingSignature.revoked || (await that.isRevoked(primaryKey, bindingSignature, null, date))) { + return _enums2.default.keyStatus.revoked; + } + // check for expiration time + if (isDataExpired(this.keyPacket, bindingSignature, date)) { + return _enums2.default.keyStatus.expired; + } + return _enums2.default.keyStatus.valid; // binding signature passed all checks +}; + +/** + * Returns the expiration time of the subkey or Infinity if key does not expire + * Returns null if the subkey is invalid. + * @param {module:packet.SecretKey| + * module:packet.PublicKey} primaryKey The primary key packet + * @param {Date} date Use the given date instead of the current time + * @returns {Promise} + * @async + */ +SubKey.prototype.getExpirationTime = async function (primaryKey, date = new Date()) { + const dataToVerify = { key: primaryKey, bind: this.keyPacket }; + const bindingSignature = await getLatestValidSignature(this.bindingSignatures, primaryKey, _enums2.default.signature.subkey_binding, dataToVerify, date); + if (!bindingSignature) return null; + const keyExpiry = getExpirationTime(this.keyPacket, bindingSignature); + const sigExpiry = bindingSignature.getExpirationTime(); + return keyExpiry < sigExpiry ? keyExpiry : sigExpiry; +}; + +/** + * Update subkey with new components from specified subkey + * @param {module:key~SubKey} subKey Source subkey to merge + * @param {module:packet.SecretKey| + module:packet.SecretSubkey} primaryKey primary key used for validation + * @returns {Promise} + * @async + */ +SubKey.prototype.update = async function (subKey, primaryKey) { + if ((await subKey.verify(primaryKey)) === _enums2.default.keyStatus.invalid) { + return; + } + if (!this.hasSameFingerprintAs(subKey)) { + throw new Error('SubKey update method: fingerprints of subkeys not equal'); + } + // key packet + if (this.keyPacket.tag === _enums2.default.packet.publicSubkey && subKey.keyPacket.tag === _enums2.default.packet.secretSubkey) { + this.keyPacket = subKey.keyPacket; + } + // update missing binding signatures + const that = this; + const dataToVerify = { key: primaryKey, bind: that.keyPacket }; + await mergeSignatures(subKey, this, 'bindingSignatures', async function (srcBindSig) { + if (!(srcBindSig.verified || (await srcBindSig.verify(primaryKey, _enums2.default.signature.subkey_binding, dataToVerify)))) { + return false; + } + for (let i = 0; i < that.bindingSignatures.length; i++) { + if (that.bindingSignatures[i].issuerKeyId.equals(srcBindSig.issuerKeyId)) { + if (srcBindSig.created > that.bindingSignatures[i].created) { + that.bindingSignatures[i] = srcBindSig; + } + return false; + } + } + return true; + }); + // revocation signatures + await mergeSignatures(subKey, this, 'revocationSignatures', function (srcRevSig) { + return isDataRevoked(primaryKey, _enums2.default.signature.subkey_revocation, dataToVerify, [srcRevSig]); + }); +}; + +/** + * Revokes the subkey + * @param {module:packet.SecretKey} primaryKey decrypted private primary key for revocation + * @param {Object} reasonForRevocation optional, object indicating the reason for revocation + * @param {module:enums.reasonForRevocation} reasonForRevocation.flag optional, flag indicating the reason for revocation + * @param {String} reasonForRevocation.string optional, string explaining the reason for revocation + * @param {Date} date optional, override the creationtime of the revocation signature + * @returns {Promise} new subkey with revocation signature + * @async + */ +SubKey.prototype.revoke = async function (primaryKey, { + flag: reasonForRevocationFlag = _enums2.default.reasonForRevocation.no_reason, + string: reasonForRevocationString = '' +} = {}, date = new Date()) { + const dataToSign = { key: primaryKey, bind: this.keyPacket }; + const subKey = new SubKey(this.keyPacket); + subKey.revocationSignatures.push((await createSignaturePacket(dataToSign, null, primaryKey, { + signatureType: _enums2.default.signature.subkey_revocation, + reasonForRevocationFlag: _enums2.default.write(_enums2.default.reasonForRevocation, reasonForRevocationFlag), + reasonForRevocationString + }, date))); + await subKey.update(this, primaryKey); + return subKey; +}; + +['getKeyId', 'getFingerprint', 'getAlgorithmInfo', 'getCreationTime', 'isDecrypted'].forEach(name => { + Key.prototype[name] = SubKey.prototype[name] = function () { + return this.keyPacket[name](); + }; +}); + +Key.prototype.hasSameFingerprintAs = SubKey.prototype.hasSameFingerprintAs = function (other) { + return this.keyPacket.hasSameFingerprintAs(other.keyPacket || other); +}; + +/** + * Reads an unarmored OpenPGP key list and returns one or multiple key objects + * @param {Uint8Array} data to be parsed + * @returns {Promise<{keys: Array, + * err: (Array|null)}>} result object with key and error arrays + * @async + * @static + */ +async function read(data) { + const result = {}; + result.keys = []; + const err = []; + try { + const packetlist = new _packet2.default.List(); + await packetlist.read(data); + const keyIndex = packetlist.indexOfTag(_enums2.default.packet.publicKey, _enums2.default.packet.secretKey); + if (keyIndex.length === 0) { + throw new Error('No key packet found'); + } + for (let i = 0; i < keyIndex.length; i++) { + const oneKeyList = packetlist.slice(keyIndex[i], keyIndex[i + 1]); + try { + const newKey = new Key(oneKeyList); + result.keys.push(newKey); + } catch (e) { + err.push(e); + } + } + } catch (e) { + err.push(e); + } + if (err.length) { + result.err = err; + } + return result; +} + +/** + * Reads an OpenPGP armored text and returns one or multiple key objects + * @param {String | ReadableStream} armoredText text to be parsed + * @returns {Promise<{keys: Array, + * err: (Array|null)}>} result object with key and error arrays + * @async + * @static + */ +async function readArmored(armoredText) { + try { + const input = await _armor2.default.decode(armoredText); + if (!(input.type === _enums2.default.armor.public_key || input.type === _enums2.default.armor.private_key)) { + throw new Error('Armored text not of type key'); + } + return read(input.data); + } catch (e) { + const result = { keys: [], err: [] }; + result.err.push(e); + return result; + } +} + +/** + * Generates a new OpenPGP key. Supports RSA and ECC keys. + * Primary and subkey will be of same type. + * @param {module:enums.publicKey} [options.keyType=module:enums.publicKey.rsa_encrypt_sign] + * To indicate what type of key to make. + * RSA is 1. See {@link https://tools.ietf.org/html/rfc4880#section-9.1} + * @param {Integer} options.numBits number of bits for the key creation. + * @param {String|Array} options.userIds + * Assumes already in form of "User Name " + * If array is used, the first userId is set as primary user Id + * @param {String} options.passphrase The passphrase used to encrypt the resulting private key + * @param {Number} [options.keyExpirationTime=0] + * The number of seconds after the key creation time that the key expires + * @param {String} curve (optional) elliptic curve for ECC keys + * @param {Date} date Override the creation date of the key and the key signatures + * @param {Array} subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}] + * sign parameter defaults to false, and indicates whether the subkey should sign rather than encrypt + * @returns {Promise} + * @async + * @static + */ +async function generate(options) { + options.sign = true; // primary key is always a signing key + options = sanitizeKeyOptions(options); + options.subkeys = options.subkeys.map(function (subkey, index) { + return sanitizeKeyOptions(options.subkeys[index], options); + }); + + let promises = [generateSecretKey(options)]; + promises = promises.concat(options.subkeys.map(generateSecretSubkey)); + return Promise.all(promises).then(packets => wrapKeyObject(packets[0], packets.slice(1), options)); + + function sanitizeKeyOptions(options, subkeyDefaults = {}) { + options.curve = options.curve || subkeyDefaults.curve; + options.numBits = options.numBits || subkeyDefaults.numBits; + options.keyExpirationTime = options.keyExpirationTime !== undefined ? options.keyExpirationTime : subkeyDefaults.keyExpirationTime; + options.passphrase = _util2.default.isString(options.passphrase) ? options.passphrase : subkeyDefaults.passphrase; + options.date = options.date || subkeyDefaults.date; + + options.sign = options.sign || false; + + if (options.curve) { + try { + options.curve = _enums2.default.write(_enums2.default.curve, options.curve); + } catch (e) { + throw new Error('Not valid curve.'); + } + if (options.curve === _enums2.default.curve.ed25519 || options.curve === _enums2.default.curve.curve25519) { + if (options.sign) { + options.algorithm = _enums2.default.publicKey.eddsa; + options.curve = _enums2.default.curve.ed25519; + } else { + options.algorithm = _enums2.default.publicKey.ecdh; + options.curve = _enums2.default.curve.curve25519; + } + } else { + if (options.sign) { + options.algorithm = _enums2.default.publicKey.ecdsa; + } else { + options.algorithm = _enums2.default.publicKey.ecdh; + } + } + } else if (options.numBits) { + options.algorithm = _enums2.default.publicKey.rsa_encrypt_sign; + } else { + throw new Error('Unrecognized key type'); + } + return options; + } + + async function generateSecretKey(options) { + const secretKeyPacket = new _packet2.default.SecretKey(options.date); + secretKeyPacket.packets = null; + secretKeyPacket.algorithm = _enums2.default.read(_enums2.default.publicKey, options.algorithm); + await secretKeyPacket.generate(options.numBits, options.curve); + return secretKeyPacket; + } + + async function generateSecretSubkey(options) { + const secretSubkeyPacket = new _packet2.default.SecretSubkey(options.date); + secretSubkeyPacket.packets = null; + secretSubkeyPacket.algorithm = _enums2.default.read(_enums2.default.publicKey, options.algorithm); + await secretSubkeyPacket.generate(options.numBits, options.curve); + return secretSubkeyPacket; + } +} + +/** + * Reformats and signs an OpenPGP key with a given User ID. Currently only supports RSA keys. + * @param {module:key.Key} options.privateKey The private key to reformat + * @param {module:enums.publicKey} [options.keyType=module:enums.publicKey.rsa_encrypt_sign] + * @param {String|Array} options.userIds + * Assumes already in form of "User Name " + * If array is used, the first userId is set as primary user Id + * @param {String} options.passphrase The passphrase used to encrypt the resulting private key + * @param {Number} [options.keyExpirationTime=0] + * The number of seconds after the key creation time that the key expires + * @param {Date} date Override the creation date of the key and the key signatures + * @param {Array} subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}] + * + * @returns {Promise} + * @async + * @static + */ +async function reformat(options) { + options = sanitizeKeyOptions(options); + + try { + const isDecrypted = options.privateKey.getKeys().every(key => key.isDecrypted()); + if (!isDecrypted) { + await options.privateKey.decrypt(); + } + } catch (err) { + throw new Error('Key not decrypted'); + } + + const packetlist = options.privateKey.toPacketlist(); + let secretKeyPacket; + const secretSubkeyPackets = []; + for (let i = 0; i < packetlist.length; i++) { + if (packetlist[i].tag === _enums2.default.packet.secretKey) { + secretKeyPacket = packetlist[i]; + } else if (packetlist[i].tag === _enums2.default.packet.secretSubkey) { + secretSubkeyPackets.push(packetlist[i]); + } + } + if (!secretKeyPacket) { + throw new Error('Key does not contain a secret key packet'); + } + + if (!options.subkeys) { + options.subkeys = await Promise.all(secretSubkeyPackets.map(async secretSubkeyPacket => ({ + sign: (await options.privateKey.getSigningKey(secretSubkeyPacket.getKeyId(), null)) && !(await options.privateKey.getEncryptionKey(secretSubkeyPacket.getKeyId(), null)) + }))); + } + + if (options.subkeys.length !== secretSubkeyPackets.length) { + throw new Error('Number of subkey options does not match number of subkeys'); + } + + options.subkeys = options.subkeys.map(function (subkey, index) { + return sanitizeKeyOptions(options.subkeys[index], options); + }); + + return wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options); + + function sanitizeKeyOptions(options, subkeyDefaults = {}) { + options.keyExpirationTime = options.keyExpirationTime || subkeyDefaults.keyExpirationTime; + options.passphrase = _util2.default.isString(options.passphrase) ? options.passphrase : subkeyDefaults.passphrase; + options.date = options.date || subkeyDefaults.date; + + return options; + } +} + +async function wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options) { + // set passphrase protection + if (options.passphrase) { + await secretKeyPacket.encrypt(options.passphrase); + } + + await Promise.all(secretSubkeyPackets.map(async function (secretSubkeyPacket, index) { + const subkeyPassphrase = options.subkeys[index].passphrase; + if (subkeyPassphrase) { + await secretSubkeyPacket.encrypt(subkeyPassphrase); + } + })); + + const packetlist = new _packet2.default.List(); + + packetlist.push(secretKeyPacket); + + await Promise.all(options.userIds.map(async function (userId, index) { + function createdPreferredAlgos(algos, configAlgo) { + if (configAlgo) { + // Not `uncompressed` / `plaintext` + const configIndex = algos.indexOf(configAlgo); + if (configIndex >= 1) { + // If it is included and not in first place, + algos.splice(configIndex, 1); // remove it. + } + if (configIndex !== 0) { + // If it was included and not in first place, or wasn't included, + algos.unshift(configAlgo); // add it to the front. + } + } + return algos; + } + + const userIdPacket = new _packet2.default.Userid(); + userIdPacket.format(userId); + + const dataToSign = {}; + dataToSign.userId = userIdPacket; + dataToSign.key = secretKeyPacket; + const signaturePacket = new _packet2.default.Signature(options.date); + signaturePacket.signatureType = _enums2.default.signature.cert_generic; + signaturePacket.publicKeyAlgorithm = secretKeyPacket.algorithm; + signaturePacket.hashAlgorithm = await getPreferredHashAlgo(null, secretKeyPacket); + signaturePacket.keyFlags = [_enums2.default.keyFlags.certify_keys | _enums2.default.keyFlags.sign_data]; + signaturePacket.preferredSymmetricAlgorithms = createdPreferredAlgos([ + // prefer aes256, aes128, then aes192 (no WebCrypto support: https://www.chromium.org/blink/webcrypto#TOC-AES-support) + _enums2.default.symmetric.aes256, _enums2.default.symmetric.aes128, _enums2.default.symmetric.aes192, _enums2.default.symmetric.cast5, _enums2.default.symmetric.tripledes], _config2.default.encryption_cipher); + if (_config2.default.aead_protect) { + signaturePacket.preferredAeadAlgorithms = createdPreferredAlgos([_enums2.default.aead.eax, _enums2.default.aead.ocb], _config2.default.aead_mode); + } + signaturePacket.preferredHashAlgorithms = createdPreferredAlgos([ + // prefer fast asm.js implementations (SHA-256). SHA-1 will not be secure much longer...move to bottom of list + _enums2.default.hash.sha256, _enums2.default.hash.sha512, _enums2.default.hash.sha1], _config2.default.prefer_hash_algorithm); + signaturePacket.preferredCompressionAlgorithms = createdPreferredAlgos([_enums2.default.compression.zlib, _enums2.default.compression.zip], _config2.default.compression); + if (index === 0) { + signaturePacket.isPrimaryUserID = true; + } + if (_config2.default.integrity_protect) { + signaturePacket.features = [0]; + signaturePacket.features[0] |= _enums2.default.features.modification_detection; + } + if (_config2.default.aead_protect) { + signaturePacket.features || (signaturePacket.features = [0]); + signaturePacket.features[0] |= _enums2.default.features.aead; + } + if (_config2.default.v5_keys) { + signaturePacket.features || (signaturePacket.features = [0]); + signaturePacket.features[0] |= _enums2.default.features.v5_keys; + } + if (options.keyExpirationTime > 0) { + signaturePacket.keyExpirationTime = options.keyExpirationTime; + signaturePacket.keyNeverExpires = false; + } + await signaturePacket.sign(secretKeyPacket, dataToSign); + + return { userIdPacket, signaturePacket }; + })).then(list => { + list.forEach(({ userIdPacket, signaturePacket }) => { + packetlist.push(userIdPacket); + packetlist.push(signaturePacket); + }); + }); + + await Promise.all(secretSubkeyPackets.map(async function (secretSubkeyPacket, index) { + const subkeyOptions = options.subkeys[index]; + const dataToSign = {}; + dataToSign.key = secretKeyPacket; + dataToSign.bind = secretSubkeyPacket; + const subkeySignaturePacket = new _packet2.default.Signature(subkeyOptions.date); + subkeySignaturePacket.signatureType = _enums2.default.signature.subkey_binding; + subkeySignaturePacket.publicKeyAlgorithm = secretKeyPacket.algorithm; + subkeySignaturePacket.hashAlgorithm = await getPreferredHashAlgo(null, secretSubkeyPacket); + if (subkeyOptions.sign) { + subkeySignaturePacket.keyFlags = [_enums2.default.keyFlags.sign_data]; + subkeySignaturePacket.embeddedSignature = await createSignaturePacket(dataToSign, null, secretSubkeyPacket, { + signatureType: _enums2.default.signature.key_binding + }, subkeyOptions.date); + } else { + subkeySignaturePacket.keyFlags = [_enums2.default.keyFlags.encrypt_communication | _enums2.default.keyFlags.encrypt_storage]; + } + if (subkeyOptions.keyExpirationTime > 0) { + subkeySignaturePacket.keyExpirationTime = subkeyOptions.keyExpirationTime; + subkeySignaturePacket.keyNeverExpires = false; + } + await subkeySignaturePacket.sign(secretKeyPacket, dataToSign); + + return { secretSubkeyPacket, subkeySignaturePacket }; + })).then(packets => { + packets.forEach(({ secretSubkeyPacket, subkeySignaturePacket }) => { + packetlist.push(secretSubkeyPacket); + packetlist.push(subkeySignaturePacket); + }); + }); + + // Add revocation signature packet for creating a revocation certificate. + // This packet should be removed before returning the key. + const dataToSign = { key: secretKeyPacket }; + packetlist.push((await createSignaturePacket(dataToSign, null, secretKeyPacket, { + signatureType: _enums2.default.signature.key_revocation, + reasonForRevocationFlag: _enums2.default.reasonForRevocation.no_reason, + reasonForRevocationString: '' + }, options.date))); + + // set passphrase protection + if (options.passphrase) { + secretKeyPacket.clearPrivateParams(); + } + + await Promise.all(secretSubkeyPackets.map(async function (secretSubkeyPacket, index) { + const subkeyPassphrase = options.subkeys[index].passphrase; + if (subkeyPassphrase) { + secretSubkeyPacket.clearPrivateParams(); + } + })); + + return new Key(packetlist); +} + +/** + * Checks if a given certificate or binding signature is revoked + * @param {module:packet.SecretKey| + * module:packet.PublicKey} primaryKey The primary key packet + * @param {Object} dataToVerify The data to check + * @param {Array} revocations The revocation signatures to check + * @param {module:packet.Signature} signature The certificate or signature to check + * @param {module:packet.PublicSubkey| + * module:packet.SecretSubkey| + * module:packet.PublicKey| + * module:packet.SecretKey} key, optional The key packet to check the signature + * @param {Date} date Use the given date instead of the current time + * @returns {Promise} True if the signature revokes the data + * @async + */ +async function isDataRevoked(primaryKey, signatureType, dataToVerify, revocations, signature, key, date = new Date()) { + key = key || primaryKey; + const normDate = _util2.default.normalizeDate(date); + const revocationKeyIds = []; + await Promise.all(revocations.map(async function (revocationSignature) { + if ( + // Note: a third-party revocation signature could legitimately revoke a + // self-signature if the signature has an authorized revocation key. + // However, we don't support passing authorized revocation keys, nor + // verifying such revocation signatures. Instead, we indicate an error + // when parsing a key with an authorized revocation key, and ignore + // third-party revocation signatures here. (It could also be revoking a + // third-party key certification, which should only affect + // `verifyAllCertifications`.) + (!signature || revocationSignature.issuerKeyId.equals(signature.issuerKeyId)) && !(_config2.default.revocations_expire && revocationSignature.isExpired(normDate)) && (revocationSignature.verified || (await revocationSignature.verify(key, signatureType, dataToVerify)))) { + // TODO get an identifier of the revoked object instead + revocationKeyIds.push(revocationSignature.issuerKeyId); + return true; + } + return false; + })); + // TODO further verify that this is the signature that should be revoked + if (signature) { + signature.revoked = revocationKeyIds.some(keyId => keyId.equals(signature.issuerKeyId)) ? true : signature.revoked || false; + return signature.revoked; + } + return revocationKeyIds.length > 0; +} + +function isDataExpired(keyPacket, signature, date = new Date()) { + const normDate = _util2.default.normalizeDate(date); + if (normDate !== null) { + const expirationTime = getExpirationTime(keyPacket, signature); + return !(keyPacket.created <= normDate && normDate <= expirationTime) || signature && signature.isExpired(date); + } + return false; +} + +function getExpirationTime(keyPacket, signature) { + let expirationTime; + // check V4 expiration time + if (signature.keyNeverExpires === false) { + expirationTime = keyPacket.created.getTime() + signature.keyExpirationTime * 1000; + } + return expirationTime ? new Date(expirationTime) : Infinity; +} + +/** + * Check if signature has revocation key sub packet (not supported by OpenPGP.js) + * and throw error if found + * @param {module:packet.Signature} signature The certificate or signature to check + * @param {type/keyid} keyId Check only certificates or signatures from a certain issuer key ID + */ +function checkRevocationKey(signature, keyId) { + if (signature.revocationKeyClass !== null && signature.issuerKeyId.equals(keyId)) { + throw new Error('This key is intended to be revoked with an authorized key, which OpenPGP.js does not support.'); + } +} + +/** + * Returns the preferred signature hash algorithm of a key + * @param {module:key.Key} key (optional) the key to get preferences from + * @param {module:packet.SecretKey|module:packet.SecretSubkey} keyPacket key packet used for signing + * @param {Date} date (optional) use the given date for verification instead of the current time + * @param {Object} userId (optional) user ID + * @returns {Promise} + * @async + */ +async function getPreferredHashAlgo(key, keyPacket, date = new Date(), userId = {}) { + let hash_algo = _config2.default.prefer_hash_algorithm; + let pref_algo = hash_algo; + if (key instanceof Key) { + const primaryUser = await key.getPrimaryUser(date, userId); + if (primaryUser && primaryUser.selfCertification.preferredHashAlgorithms) { + var _primaryUser$selfCert = _slicedToArray(primaryUser.selfCertification.preferredHashAlgorithms, 1); + + pref_algo = _primaryUser$selfCert[0]; + + hash_algo = _crypto2.default.hash.getHashByteLength(hash_algo) <= _crypto2.default.hash.getHashByteLength(pref_algo) ? pref_algo : hash_algo; + } + } + switch (Object.getPrototypeOf(keyPacket)) { + case _packet2.default.SecretKey.prototype: + case _packet2.default.PublicKey.prototype: + case _packet2.default.SecretSubkey.prototype: + case _packet2.default.PublicSubkey.prototype: + switch (keyPacket.algorithm) { + case 'ecdh': + case 'ecdsa': + case 'eddsa': + pref_algo = _crypto2.default.publicKey.elliptic.getPreferredHashAlgo(keyPacket.params[0]); + } + } + return _crypto2.default.hash.getHashByteLength(hash_algo) <= _crypto2.default.hash.getHashByteLength(pref_algo) ? pref_algo : hash_algo; +} + +/** + * Returns the preferred symmetric/aead algorithm for a set of keys + * @param {symmetric|aead} type Type of preference to return + * @param {Array} keys Set of keys + * @param {Date} date (optional) use the given date for verification instead of the current time + * @param {Array} userIds (optional) user IDs + * @returns {Promise} Preferred symmetric algorithm + * @async + */ +async function getPreferredAlgo(type, keys, date = new Date(), userIds = []) { + const prefProperty = type === 'symmetric' ? 'preferredSymmetricAlgorithms' : 'preferredAeadAlgorithms'; + const defaultAlgo = type === 'symmetric' ? _enums2.default.symmetric.aes128 : _enums2.default.aead.eax; + const prioMap = {}; + await Promise.all(keys.map(async function (key, i) { + const primaryUser = await key.getPrimaryUser(date, userIds[i]); + if (!primaryUser || !primaryUser.selfCertification[prefProperty]) { + return defaultAlgo; + } + primaryUser.selfCertification[prefProperty].forEach(function (algo, index) { + const entry = prioMap[algo] || (prioMap[algo] = { prio: 0, count: 0, algo: algo }); + entry.prio += 64 >> index; + entry.count++; + }); + })); + let prefAlgo = { prio: 0, algo: defaultAlgo }; + Object.values(prioMap).forEach(({ prio, count, algo }) => { + try { + if (algo !== _enums2.default[type].plaintext && algo !== _enums2.default[type].idea && // not implemented + _enums2.default.read(_enums2.default[type], algo) && // known algorithm + count === keys.length && // available for all keys + prio > prefAlgo.prio) { + prefAlgo = prioMap[algo]; + } + } catch (e) {} + }); + return prefAlgo.algo; +} + +/** + * Returns whether aead is supported by all keys in the set + * @param {Array} keys Set of keys + * @param {Date} date (optional) use the given date for verification instead of the current time + * @param {Array} userIds (optional) user IDs + * @returns {Promise} + * @async + */ +async function isAeadSupported(keys, date = new Date(), userIds = []) { + let supported = true; + // TODO replace when Promise.some or Promise.any are implemented + await Promise.all(keys.map(async function (key, i) { + const primaryUser = await key.getPrimaryUser(date, userIds[i]); + if (!primaryUser || !primaryUser.selfCertification.features || !(primaryUser.selfCertification.features[0] & _enums2.default.features.aead)) { + supported = false; + } + })); + return supported; +} + +},{"./config":79,"./crypto":94,"./encoding/armor":111,"./enums":113,"./packet":125,"./util":152}],117:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _keyring = require('./keyring.js'); + +var _keyring2 = _interopRequireDefault(_keyring); + +var _localstore = require('./localstore.js'); + +var _localstore2 = _interopRequireDefault(_localstore); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * @fileoverview Functions dealing with storage of the keyring. + * @see module:keyring/keyring + * @see module:keyring/localstore + * @module keyring + */ +_keyring2.default.localstore = _localstore2.default; + +exports.default = _keyring2.default; + +},{"./keyring.js":118,"./localstore.js":119}],118:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _key = require('../key'); + +var _localstore = require('./localstore'); + +var _localstore2 = _interopRequireDefault(_localstore); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Initialization routine for the keyring. + * @constructor + * @param {keyring/localstore} [storeHandler] class implementing loadPublic(), loadPrivate(), storePublic(), and storePrivate() methods + */ +// GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @fileoverview Provides the Keyring class + * @requires key + * @requires keyring/localstore + * @module keyring/keyring + */ + +function Keyring(storeHandler) { + this.storeHandler = storeHandler || new _localstore2.default(); +} + +/** + * Calls the storeHandler to load the keys + * @async + */ +Keyring.prototype.load = async function () { + this.publicKeys = new KeyArray((await this.storeHandler.loadPublic())); + this.privateKeys = new KeyArray((await this.storeHandler.loadPrivate())); +}; + +/** + * Calls the storeHandler to save the keys + * @async + */ +Keyring.prototype.store = async function () { + await Promise.all([this.storeHandler.storePublic(this.publicKeys.keys), this.storeHandler.storePrivate(this.privateKeys.keys)]); +}; + +/** + * Clear the keyring - erase all the keys + */ +Keyring.prototype.clear = function () { + this.publicKeys.keys = []; + this.privateKeys.keys = []; +}; + +/** + * Searches the keyring for keys having the specified key id + * @param {String} keyId provided as string of lowercase hex number + * withouth 0x prefix (can be 16-character key ID or fingerprint) + * @param {Boolean} deep if true search also in subkeys + * @returns {Array|null} keys found or null + */ +Keyring.prototype.getKeysForId = function (keyId, deep) { + let result = []; + result = result.concat(this.publicKeys.getForId(keyId, deep) || []); + result = result.concat(this.privateKeys.getForId(keyId, deep) || []); + return result.length ? result : null; +}; + +/** + * Removes keys having the specified key id from the keyring + * @param {String} keyId provided as string of lowercase hex number + * withouth 0x prefix (can be 16-character key ID or fingerprint) + * @returns {Array|null} keys found or null + */ +Keyring.prototype.removeKeysForId = function (keyId) { + let result = []; + result = result.concat(this.publicKeys.removeForId(keyId) || []); + result = result.concat(this.privateKeys.removeForId(keyId) || []); + return result.length ? result : null; +}; + +/** + * Get all public and private keys + * @returns {Array} all keys + */ +Keyring.prototype.getAllKeys = function () { + return this.publicKeys.keys.concat(this.privateKeys.keys); +}; + +/** + * Array of keys + * @param {Array} keys The keys to store in this array + */ +function KeyArray(keys) { + this.keys = keys; +} + +/** + * Searches all keys in the KeyArray matching the address or address part of the user ids + * @param {String} email email address to search for + * @returns {Array} The public keys associated with provided email address. + */ +KeyArray.prototype.getForAddress = function (email) { + const results = []; + for (let i = 0; i < this.keys.length; i++) { + if (emailCheck(email, this.keys[i])) { + results.push(this.keys[i]); + } + } + return results; +}; + +/** + * Checks a key to see if it matches the specified email address + * @private + * @param {String} email email address to search for + * @param {module:key.Key} key The key to be checked. + * @returns {Boolean} True if the email address is defined in the specified key + */ +function emailCheck(email, key) { + email = email.toLowerCase(); + // escape email before using in regular expression + const emailEsc = email.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); + const emailRegex = new RegExp('<' + emailEsc + '>'); + const userIds = key.getUserIds(); + for (let i = 0; i < userIds.length; i++) { + const userId = userIds[i].toLowerCase(); + if (email === userId || emailRegex.test(userId)) { + return true; + } + } + return false; +} + +/** + * Checks a key to see if it matches the specified keyid + * @private + * @param {String} keyId provided as string of lowercase hex number + * withouth 0x prefix (can be 16-character key ID or fingerprint) + * @param {module:key.Key|module:key.SubKey} key The key to be checked + * @returns {Boolean} True if key has the specified keyid + */ +function keyIdCheck(keyId, key) { + if (keyId.length === 16) { + return keyId === key.getKeyId().toHex(); + } + return keyId === key.getFingerprint(); +} + +/** + * Searches the KeyArray for a key having the specified key id + * @param {String} keyId provided as string of lowercase hex number + * withouth 0x prefix (can be 16-character key ID or fingerprint) + * @param {Boolean} deep if true search also in subkeys + * @returns {module:key.Key|null} key found or null + */ +KeyArray.prototype.getForId = function (keyId, deep) { + for (let i = 0; i < this.keys.length; i++) { + if (keyIdCheck(keyId, this.keys[i])) { + return this.keys[i]; + } + if (deep && this.keys[i].subKeys.length) { + for (let j = 0; j < this.keys[i].subKeys.length; j++) { + if (keyIdCheck(keyId, this.keys[i].subKeys[j])) { + return this.keys[i]; + } + } + } + } + return null; +}; + +/** + * Imports a key from an ascii armored message + * @param {String} armored message to read the keys/key from + * @returns {Promise|null>} array of error objects or null + * @async + */ +KeyArray.prototype.importKey = async function (armored) { + const imported = await (0, _key.readArmored)(armored); + for (let i = 0; i < imported.keys.length; i++) { + const key = imported.keys[i]; + // check if key already in key array + const keyidHex = key.getKeyId().toHex(); + const keyFound = this.getForId(keyidHex); + if (keyFound) { + await keyFound.update(key); + } else { + this.push(key); + } + } + return imported.err ? imported.err : null; +}; + +/** + * Add key to KeyArray + * @param {module:key.Key} key The key that will be added to the keyring + * @returns {Number} The new length of the KeyArray + */ +KeyArray.prototype.push = function (key) { + return this.keys.push(key); +}; + +/** + * Removes a key with the specified keyid from the keyring + * @param {String} keyId provided as string of lowercase hex number + * withouth 0x prefix (can be 16-character key ID or fingerprint) + * @returns {module:key.Key|null} The key object which has been removed or null + */ +KeyArray.prototype.removeForId = function (keyId) { + for (let i = 0; i < this.keys.length; i++) { + if (keyIdCheck(keyId, this.keys[i])) { + return this.keys.splice(i, 1)[0]; + } + } + return null; +}; + +exports.default = Keyring; + +},{"../key":116,"./localstore":119}],119:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _webStreamTools = require('web-stream-tools'); + +var _webStreamTools2 = _interopRequireDefault(_webStreamTools); + +var _config = require('../config'); + +var _config2 = _interopRequireDefault(_config); + +var _key = require('../key'); + +var _util = require('../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The class that deals with storage of the keyring. + * Currently the only option is to use HTML5 local storage. + * @constructor + * @param {String} prefix prefix for itemnames in localstore + */ +// GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @fileoverview Provides the LocalStore class + * @requires web-stream-tools + * @requires config + * @requires key + * @requires util + * @module keyring/localstore + */ + +function LocalStore(prefix) { + prefix = prefix || 'openpgp-'; + this.publicKeysItem = prefix + this.publicKeysItem; + this.privateKeysItem = prefix + this.privateKeysItem; + if (typeof window !== 'undefined' && window.localStorage) { + this.storage = window.localStorage; + } else { + this.storage = new (require('node-localstorage').LocalStorage)(_config2.default.node_store); + } +} + +/* + * Declare the localstore itemnames + */ +LocalStore.prototype.publicKeysItem = 'public-keys'; +LocalStore.prototype.privateKeysItem = 'private-keys'; + +/** + * Load the public keys from HTML5 local storage. + * @returns {Array} array of keys retrieved from localstore + * @async + */ +LocalStore.prototype.loadPublic = async function () { + return loadKeys(this.storage, this.publicKeysItem); +}; + +/** + * Load the private keys from HTML5 local storage. + * @returns {Array} array of keys retrieved from localstore + * @async + */ +LocalStore.prototype.loadPrivate = async function () { + return loadKeys(this.storage, this.privateKeysItem); +}; + +async function loadKeys(storage, itemname) { + const armoredKeys = JSON.parse(storage.getItem(itemname)); + const keys = []; + if (armoredKeys !== null && armoredKeys.length !== 0) { + let key; + for (let i = 0; i < armoredKeys.length; i++) { + key = await (0, _key.readArmored)(armoredKeys[i]); + if (!key.err) { + keys.push(key.keys[0]); + } else { + _util2.default.print_debug("Error reading armored key from keyring index: " + i); + } + } + } + return keys; +} + +/** + * Saves the current state of the public keys to HTML5 local storage. + * The key array gets stringified using JSON + * @param {Array} keys array of keys to save in localstore + * @async + */ +LocalStore.prototype.storePublic = async function (keys) { + await storeKeys(this.storage, this.publicKeysItem, keys); +}; + +/** + * Saves the current state of the private keys to HTML5 local storage. + * The key array gets stringified using JSON + * @param {Array} keys array of keys to save in localstore + * @async + */ +LocalStore.prototype.storePrivate = async function (keys) { + await storeKeys(this.storage, this.privateKeysItem, keys); +}; + +async function storeKeys(storage, itemname, keys) { + if (keys.length) { + const armoredKeys = await Promise.all(keys.map(key => _webStreamTools2.default.readToEnd(key.armor()))); + storage.setItem(itemname, JSON.stringify(armoredKeys)); + } else { + storage.removeItem(itemname); + } +} + +exports.default = LocalStore; + +},{"../config":79,"../key":116,"../util":152,"node-localstorage":"node-localstorage","web-stream-tools":75}],120:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Message = Message; +exports.encryptSessionKey = encryptSessionKey; +exports.createSignaturePackets = createSignaturePackets; +exports.createVerificationObjects = createVerificationObjects; +exports.readArmored = readArmored; +exports.read = read; +exports.fromText = fromText; +exports.fromBinary = fromBinary; + +var _webStreamTools = require('web-stream-tools'); + +var _webStreamTools2 = _interopRequireDefault(_webStreamTools); + +var _armor = require('./encoding/armor'); + +var _armor2 = _interopRequireDefault(_armor); + +var _keyid = require('./type/keyid'); + +var _keyid2 = _interopRequireDefault(_keyid); + +var _config = require('./config'); + +var _config2 = _interopRequireDefault(_config); + +var _crypto = require('./crypto'); + +var _crypto2 = _interopRequireDefault(_crypto); + +var _enums = require('./enums'); + +var _enums2 = _interopRequireDefault(_enums); + +var _util = require('./util'); + +var _util2 = _interopRequireDefault(_util); + +var _packet = require('./packet'); + +var _packet2 = _interopRequireDefault(_packet); + +var _signature = require('./signature'); + +var _key = require('./key'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * @class + * @classdesc Class that represents an OpenPGP message. + * Can be an encrypted message, signed message, compressed message or literal message + * @param {module:packet.List} packetlist The packets that form this message + * See {@link https://tools.ietf.org/html/rfc4880#section-11.3} + */ + +// GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @requires web-stream-tools + * @requires encoding/armor + * @requires type/keyid + * @requires config + * @requires crypto + * @requires enums + * @requires util + * @requires packet + * @requires signature + * @requires key + * @module message + */ + +function Message(packetlist) { + if (!(this instanceof Message)) { + return new Message(packetlist); + } + this.packets = packetlist || new _packet2.default.List(); +} + +/** + * Returns the key IDs of the keys to which the session key is encrypted + * @returns {Array} array of keyid objects + */ +Message.prototype.getEncryptionKeyIds = function () { + const keyIds = []; + const pkESKeyPacketlist = this.packets.filterByTag(_enums2.default.packet.publicKeyEncryptedSessionKey); + pkESKeyPacketlist.forEach(function (packet) { + keyIds.push(packet.publicKeyId); + }); + return keyIds; +}; + +/** + * Returns the key IDs of the keys that signed the message + * @returns {Array} array of keyid objects + */ +Message.prototype.getSigningKeyIds = function () { + const keyIds = []; + const msg = this.unwrapCompressed(); + // search for one pass signatures + const onePassSigList = msg.packets.filterByTag(_enums2.default.packet.onePassSignature); + onePassSigList.forEach(function (packet) { + keyIds.push(packet.issuerKeyId); + }); + // if nothing found look for signature packets + if (!keyIds.length) { + const signatureList = msg.packets.filterByTag(_enums2.default.packet.signature); + signatureList.forEach(function (packet) { + keyIds.push(packet.issuerKeyId); + }); + } + return keyIds; +}; + +/** + * Decrypt the message. Either a private key, a session key, or a password must be specified. + * @param {Array} privateKeys (optional) private keys with decrypted secret data + * @param {Array} passwords (optional) passwords used to decrypt + * @param {Array} sessionKeys (optional) session keys in the form: { data:Uint8Array, algorithm:String, [aeadAlgorithm:String] } + * @param {Boolean} streaming (optional) whether to process data as a stream + * @returns {Promise} new message with decrypted content + * @async + */ +Message.prototype.decrypt = async function (privateKeys, passwords, sessionKeys, streaming) { + const keyObjs = sessionKeys || (await this.decryptSessionKeys(privateKeys, passwords)); + + const symEncryptedPacketlist = this.packets.filterByTag(_enums2.default.packet.symmetricallyEncrypted, _enums2.default.packet.symEncryptedIntegrityProtected, _enums2.default.packet.symEncryptedAEADProtected); + + if (symEncryptedPacketlist.length === 0) { + return this; + } + + const symEncryptedPacket = symEncryptedPacketlist[0]; + let exception = null; + const decryptedPromise = Promise.all(keyObjs.map(async keyObj => { + if (!keyObj || !_util2.default.isUint8Array(keyObj.data) || !_util2.default.isString(keyObj.algorithm)) { + throw new Error('Invalid session key for decryption.'); + } + + try { + await symEncryptedPacket.decrypt(keyObj.algorithm, keyObj.data, streaming); + } catch (e) { + _util2.default.print_debug_error(e); + exception = e; + } + })); + // We don't await stream.cancel here because it only returns when the other copy is canceled too. + _webStreamTools2.default.cancel(symEncryptedPacket.encrypted); // Don't keep copy of encrypted data in memory. + symEncryptedPacket.encrypted = null; + await decryptedPromise; + + if (!symEncryptedPacket.packets || !symEncryptedPacket.packets.length) { + throw exception || new Error('Decryption failed.'); + } + + const resultMsg = new Message(symEncryptedPacket.packets); + symEncryptedPacket.packets = new _packet2.default.List(); // remove packets after decryption + + return resultMsg; +}; + +/** + * Decrypt encrypted session keys either with private keys or passwords. + * @param {Array} privateKeys (optional) private keys with decrypted secret data + * @param {Array} passwords (optional) passwords used to decrypt + * @returns {Promise>} array of object with potential sessionKey, algorithm pairs + * @async + */ +Message.prototype.decryptSessionKeys = async function (privateKeys, passwords) { + let keyPackets = []; + + let exception; + if (passwords) { + const symESKeyPacketlist = this.packets.filterByTag(_enums2.default.packet.symEncryptedSessionKey); + if (!symESKeyPacketlist) { + throw new Error('No symmetrically encrypted session key packet found.'); + } + await Promise.all(passwords.map(async function (password, i) { + let packets; + if (i) { + packets = new _packet2.default.List(); + await packets.read(symESKeyPacketlist.write()); + } else { + packets = symESKeyPacketlist; + } + await Promise.all(packets.map(async function (keyPacket) { + try { + await keyPacket.decrypt(password); + keyPackets.push(keyPacket); + } catch (err) { + _util2.default.print_debug_error(err); + } + })); + })); + } else if (privateKeys) { + const pkESKeyPacketlist = this.packets.filterByTag(_enums2.default.packet.publicKeyEncryptedSessionKey); + if (!pkESKeyPacketlist) { + throw new Error('No public key encrypted session key packet found.'); + } + await Promise.all(pkESKeyPacketlist.map(async function (keyPacket) { + await Promise.all(privateKeys.map(async function (privateKey) { + const primaryUser = await privateKey.getPrimaryUser(); // TODO: Pass userId from somewhere. + let algos = [_enums2.default.symmetric.aes256, // Old OpenPGP.js default fallback + _enums2.default.symmetric.aes128, // RFC4880bis fallback + _enums2.default.symmetric.tripledes, // RFC4880 fallback + _enums2.default.symmetric.cast5 // Golang OpenPGP fallback + ]; + if (primaryUser && primaryUser.selfCertification.preferredSymmetricAlgorithms) { + algos = algos.concat(primaryUser.selfCertification.preferredSymmetricAlgorithms); + } + + const privateKeyPackets = privateKey.getKeys(keyPacket.publicKeyId).map(key => key.keyPacket); + await Promise.all(privateKeyPackets.map(async function (privateKeyPacket) { + if (!privateKeyPacket) { + return; + } + if (!privateKeyPacket.isDecrypted()) { + throw new Error('Private key is not decrypted.'); + } + try { + await keyPacket.decrypt(privateKeyPacket); + if (!algos.includes(_enums2.default.write(_enums2.default.symmetric, keyPacket.sessionKeyAlgorithm))) { + throw new Error('A non-preferred symmetric algorithm was used.'); + } + keyPackets.push(keyPacket); + } catch (err) { + _util2.default.print_debug_error(err); + exception = err; + } + })); + })); + _webStreamTools2.default.cancel(keyPacket.encrypted); // Don't keep copy of encrypted data in memory. + keyPacket.encrypted = null; + })); + } else { + throw new Error('No key or password specified.'); + } + + if (keyPackets.length) { + // Return only unique session keys + if (keyPackets.length > 1) { + const seen = {}; + keyPackets = keyPackets.filter(function (item) { + const k = item.sessionKeyAlgorithm + _util2.default.Uint8Array_to_str(item.sessionKey); + if (seen.hasOwnProperty(k)) { + return false; + } + seen[k] = true; + return true; + }); + } + + return keyPackets.map(packet => ({ data: packet.sessionKey, algorithm: packet.sessionKeyAlgorithm })); + } + throw exception || new Error('Session key decryption failed.'); +}; + +/** + * Get literal data that is the body of the message + * @returns {(Uint8Array|null)} literal body of the message as Uint8Array + */ +Message.prototype.getLiteralData = function () { + const msg = this.unwrapCompressed(); + const literal = msg.packets.findPacket(_enums2.default.packet.literal); + return literal && literal.getBytes() || null; +}; + +/** + * Get filename from literal data packet + * @returns {(String|null)} filename of literal data packet as string + */ +Message.prototype.getFilename = function () { + const msg = this.unwrapCompressed(); + const literal = msg.packets.findPacket(_enums2.default.packet.literal); + return literal && literal.getFilename() || null; +}; + +/** + * Get literal data as text + * @returns {(String|null)} literal body of the message interpreted as text + */ +Message.prototype.getText = function () { + const msg = this.unwrapCompressed(); + const literal = msg.packets.findPacket(_enums2.default.packet.literal); + if (literal) { + return literal.getText(); + } + return null; +}; + +/** + * Encrypt the message either with public keys, passwords, or both at once. + * @param {Array} keys (optional) public key(s) for message encryption + * @param {Array} passwords (optional) password(s) for message encryption + * @param {Object} sessionKey (optional) session key in the form: { data:Uint8Array, algorithm:String, [aeadAlgorithm:String] } + * @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs + * @param {Date} date (optional) override the creation date of the literal package + * @param {Array} userIds (optional) user IDs to encrypt for, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }] + * @param {Boolean} streaming (optional) whether to process data as a stream + * @returns {Promise} new message with encrypted content + * @async + */ +Message.prototype.encrypt = async function (keys, passwords, sessionKey, wildcard = false, date = new Date(), userIds = [], streaming) { + let symAlgo; + let aeadAlgo; + let symEncryptedPacket; + + if (sessionKey) { + if (!_util2.default.isUint8Array(sessionKey.data) || !_util2.default.isString(sessionKey.algorithm)) { + throw new Error('Invalid session key for encryption.'); + } + symAlgo = sessionKey.algorithm; + aeadAlgo = sessionKey.aeadAlgorithm; + sessionKey = sessionKey.data; + } else if (keys && keys.length) { + symAlgo = _enums2.default.read(_enums2.default.symmetric, (await (0, _key.getPreferredAlgo)('symmetric', keys, date, userIds))); + if (_config2.default.aead_protect && (await (0, _key.isAeadSupported)(keys, date, userIds))) { + aeadAlgo = _enums2.default.read(_enums2.default.aead, (await (0, _key.getPreferredAlgo)('aead', keys, date, userIds))); + } + } else if (passwords && passwords.length) { + symAlgo = _enums2.default.read(_enums2.default.symmetric, _config2.default.encryption_cipher); + aeadAlgo = _enums2.default.read(_enums2.default.aead, _config2.default.aead_mode); + } else { + throw new Error('No keys, passwords, or session key provided.'); + } + + if (!sessionKey) { + sessionKey = await _crypto2.default.generateSessionKey(symAlgo); + } + + const msg = await encryptSessionKey(sessionKey, symAlgo, aeadAlgo, keys, passwords, wildcard, date, userIds); + + if (_config2.default.aead_protect && aeadAlgo) { + symEncryptedPacket = new _packet2.default.SymEncryptedAEADProtected(); + symEncryptedPacket.aeadAlgorithm = aeadAlgo; + } else if (_config2.default.integrity_protect) { + symEncryptedPacket = new _packet2.default.SymEncryptedIntegrityProtected(); + } else { + symEncryptedPacket = new _packet2.default.SymmetricallyEncrypted(); + } + symEncryptedPacket.packets = this.packets; + + await symEncryptedPacket.encrypt(symAlgo, sessionKey, streaming); + + msg.packets.push(symEncryptedPacket); + symEncryptedPacket.packets = new _packet2.default.List(); // remove packets after encryption + return { + message: msg, + sessionKey: { + data: sessionKey, + algorithm: symAlgo, + aeadAlgorithm: aeadAlgo + } + }; +}; + +/** + * Encrypt a session key either with public keys, passwords, or both at once. + * @param {Uint8Array} sessionKey session key for encryption + * @param {String} symAlgo session key algorithm + * @param {String} aeadAlgo (optional) aead algorithm, e.g. 'eax' or 'ocb' + * @param {Array} publicKeys (optional) public key(s) for message encryption + * @param {Array} passwords (optional) for message encryption + * @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs + * @param {Date} date (optional) override the date + * @param {Array} userIds (optional) user IDs to encrypt for, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }] + * @returns {Promise} new message with encrypted content + * @async + */ +async function encryptSessionKey(sessionKey, symAlgo, aeadAlgo, publicKeys, passwords, wildcard = false, date = new Date(), userIds = []) { + const packetlist = new _packet2.default.List(); + + if (publicKeys) { + const results = await Promise.all(publicKeys.map(async function (publicKey) { + const encryptionKey = await publicKey.getEncryptionKey(undefined, date, userIds); + if (!encryptionKey) { + throw new Error('Could not find valid key packet for encryption in key ' + publicKey.getKeyId().toHex()); + } + const pkESKeyPacket = new _packet2.default.PublicKeyEncryptedSessionKey(); + pkESKeyPacket.publicKeyId = wildcard ? _keyid2.default.wildcard() : encryptionKey.getKeyId(); + pkESKeyPacket.publicKeyAlgorithm = encryptionKey.keyPacket.algorithm; + pkESKeyPacket.sessionKey = sessionKey; + pkESKeyPacket.sessionKeyAlgorithm = symAlgo; + await pkESKeyPacket.encrypt(encryptionKey.keyPacket); + delete pkESKeyPacket.sessionKey; // delete plaintext session key after encryption + return pkESKeyPacket; + })); + packetlist.concat(results); + } + if (passwords) { + const testDecrypt = async function testDecrypt(keyPacket, password) { + try { + await keyPacket.decrypt(password); + return 1; + } catch (e) { + return 0; + } + }; + + const sum = (accumulator, currentValue) => accumulator + currentValue; + + const encryptPassword = async function encryptPassword(sessionKey, symAlgo, aeadAlgo, password) { + const symEncryptedSessionKeyPacket = new _packet2.default.SymEncryptedSessionKey(); + symEncryptedSessionKeyPacket.sessionKey = sessionKey; + symEncryptedSessionKeyPacket.sessionKeyAlgorithm = symAlgo; + if (aeadAlgo) { + symEncryptedSessionKeyPacket.aeadAlgorithm = aeadAlgo; + } + await symEncryptedSessionKeyPacket.encrypt(password); + + if (_config2.default.password_collision_check) { + const results = await Promise.all(passwords.map(pwd => testDecrypt(symEncryptedSessionKeyPacket, pwd))); + if (results.reduce(sum) !== 1) { + return encryptPassword(sessionKey, symAlgo, password); + } + } + + delete symEncryptedSessionKeyPacket.sessionKey; // delete plaintext session key after encryption + return symEncryptedSessionKeyPacket; + }; + + const results = await Promise.all(passwords.map(pwd => encryptPassword(sessionKey, symAlgo, aeadAlgo, pwd))); + packetlist.concat(results); + } + + return new Message(packetlist); +} + +/** + * Sign the message (the literal data packet of the message) + * @param {Array} privateKeys private keys with decrypted secret key data for signing + * @param {Signature} signature (optional) any existing detached signature to add to the message + * @param {Date} date (optional) override the creation time of the signature + * @param {Array} userIds (optional) user IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] + * @returns {Promise} new message with signed content + * @async + */ +Message.prototype.sign = async function (privateKeys = [], signature = null, date = new Date(), userIds = []) { + const packetlist = new _packet2.default.List(); + + const literalDataPacket = this.packets.findPacket(_enums2.default.packet.literal); + if (!literalDataPacket) { + throw new Error('No literal data packet to sign.'); + } + + let i; + let existingSigPacketlist; + // If data packet was created from Uint8Array, use binary, otherwise use text + const signatureType = literalDataPacket.text === null ? _enums2.default.signature.binary : _enums2.default.signature.text; + + if (signature) { + existingSigPacketlist = signature.packets.filterByTag(_enums2.default.packet.signature); + for (i = existingSigPacketlist.length - 1; i >= 0; i--) { + const signaturePacket = existingSigPacketlist[i]; + const onePassSig = new _packet2.default.OnePassSignature(); + onePassSig.signatureType = signaturePacket.signatureType; + onePassSig.hashAlgorithm = signaturePacket.hashAlgorithm; + onePassSig.publicKeyAlgorithm = signaturePacket.publicKeyAlgorithm; + onePassSig.issuerKeyId = signaturePacket.issuerKeyId; + if (!privateKeys.length && i === 0) { + onePassSig.flags = 1; + } + packetlist.push(onePassSig); + } + } + + await Promise.all(Array.from(privateKeys).reverse().map(async function (privateKey, i) { + if (privateKey.isPublic()) { + throw new Error('Need private key for signing'); + } + const signingKey = await privateKey.getSigningKey(undefined, date, userIds); + if (!signingKey) { + throw new Error('Could not find valid key packet for signing in key ' + privateKey.getKeyId().toHex()); + } + const onePassSig = new _packet2.default.OnePassSignature(); + onePassSig.signatureType = signatureType; + onePassSig.hashAlgorithm = await (0, _key.getPreferredHashAlgo)(privateKey, signingKey.keyPacket, date, userIds); + onePassSig.publicKeyAlgorithm = signingKey.keyPacket.algorithm; + onePassSig.issuerKeyId = signingKey.getKeyId(); + if (i === privateKeys.length - 1) { + onePassSig.flags = 1; + } + return onePassSig; + })).then(onePassSignatureList => { + onePassSignatureList.forEach(onePassSig => packetlist.push(onePassSig)); + }); + + packetlist.push(literalDataPacket); + packetlist.concat((await createSignaturePackets(literalDataPacket, privateKeys, signature, date, false))); + + return new Message(packetlist); +}; + +/** + * Compresses the message (the literal and -if signed- signature data packets of the message) + * @param {module:enums.compression} compression compression algorithm to be used + * @returns {module:message.Message} new message with compressed content + */ +Message.prototype.compress = function (compression) { + if (compression === _enums2.default.compression.uncompressed) { + return this; + } + + const compressed = new _packet2.default.Compressed(); + compressed.packets = this.packets; + compressed.algorithm = _enums2.default.read(_enums2.default.compression, compression); + + const packetList = new _packet2.default.List(); + packetList.push(compressed); + + return new Message(packetList); +}; + +/** + * Create a detached signature for the message (the literal data packet of the message) + * @param {Array} privateKeys private keys with decrypted secret key data for signing + * @param {Signature} signature (optional) any existing detached signature + * @param {Date} date (optional) override the creation time of the signature + * @param {Array} userIds (optional) user IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] + * @returns {Promise} new detached signature of message content + * @async + */ +Message.prototype.signDetached = async function (privateKeys = [], signature = null, date = new Date(), userIds = []) { + const literalDataPacket = this.packets.findPacket(_enums2.default.packet.literal); + if (!literalDataPacket) { + throw new Error('No literal data packet to sign.'); + } + return new _signature.Signature((await createSignaturePackets(literalDataPacket, privateKeys, signature, date, userIds, true))); +}; + +/** + * Create signature packets for the message + * @param {module:packet.Literal} literalDataPacket the literal data packet to sign + * @param {Array} privateKeys private keys with decrypted secret key data for signing + * @param {Signature} signature (optional) any existing detached signature to append + * @param {Date} date (optional) override the creationtime of the signature + * @param {Array} userIds (optional) user IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] + * @param {Boolean} detached (optional) whether to create detached signature packets + * @returns {Promise} list of signature packets + * @async + */ +async function createSignaturePackets(literalDataPacket, privateKeys, signature = null, date = new Date(), userIds = [], detached = false) { + const packetlist = new _packet2.default.List(); + + // If data packet was created from Uint8Array, use binary, otherwise use text + const signatureType = literalDataPacket.text === null ? _enums2.default.signature.binary : _enums2.default.signature.text; + + await Promise.all(privateKeys.map(async (privateKey, i) => { + const userId = userIds[i]; + if (privateKey.isPublic()) { + throw new Error('Need private key for signing'); + } + const signingKey = await privateKey.getSigningKey(undefined, date, userId); + if (!signingKey) { + throw new Error(`Could not find valid signing key packet in key ${privateKey.getKeyId().toHex()}`); + } + return (0, _key.createSignaturePacket)(literalDataPacket, privateKey, signingKey.keyPacket, { signatureType }, date, userId, detached); + })).then(signatureList => { + signatureList.forEach(signaturePacket => packetlist.push(signaturePacket)); + }); + + if (signature) { + const existingSigPacketlist = signature.packets.filterByTag(_enums2.default.packet.signature); + packetlist.concat(existingSigPacketlist); + } + return packetlist; +} + +/** + * Verify message signatures + * @param {Array} keys array of keys to verify signatures + * @param {Date} date (optional) Verify the signature against the given date, i.e. check signature creation time < date < expiration time + * @param {Boolean} streaming (optional) whether to process data as a stream + * @returns {Promise>} list of signer's keyid and validity of signature + * @async + */ +Message.prototype.verify = async function (keys, date = new Date(), streaming) { + const msg = this.unwrapCompressed(); + const literalDataList = msg.packets.filterByTag(_enums2.default.packet.literal); + if (literalDataList.length !== 1) { + throw new Error('Can only verify message with one literal data packet.'); + } + const onePassSigList = msg.packets.filterByTag(_enums2.default.packet.onePassSignature).reverse(); + const signatureList = msg.packets.filterByTag(_enums2.default.packet.signature); + if (onePassSigList.length && !signatureList.length && msg.packets.stream) { + await Promise.all(onePassSigList.map(async onePassSig => { + onePassSig.correspondingSig = new Promise((resolve, reject) => { + onePassSig.correspondingSigResolve = resolve; + onePassSig.correspondingSigReject = reject; + }); + onePassSig.signatureData = _webStreamTools2.default.fromAsync(async () => (await onePassSig.correspondingSig).signatureData); + onePassSig.hashed = await onePassSig.hash(onePassSig.signatureType, literalDataList[0], undefined, false, streaming); + })); + msg.packets.stream = _webStreamTools2.default.transformPair(msg.packets.stream, async (readable, writable) => { + const reader = _webStreamTools2.default.getReader(readable); + const writer = _webStreamTools2.default.getWriter(writable); + try { + for (let i = 0; i < onePassSigList.length; i++) { + var _ref = await reader.read(); + + const signature = _ref.value; + + onePassSigList[i].correspondingSigResolve(signature); + } + await reader.readToEnd(); + await writer.ready; + await writer.close(); + } catch (e) { + onePassSigList.forEach(onePassSig => { + onePassSig.correspondingSigReject(e); + }); + await writer.abort(e); + } + }); + return createVerificationObjects(onePassSigList, literalDataList, keys, date, false); + } + return createVerificationObjects(signatureList, literalDataList, keys, date, false); +}; + +/** + * Verify detached message signature + * @param {Array} keys array of keys to verify signatures + * @param {Signature} signature + * @param {Date} date Verify the signature against the given date, i.e. check signature creation time < date < expiration time + * @returns {Promise>} list of signer's keyid and validity of signature + * @async + */ +Message.prototype.verifyDetached = function (signature, keys, date = new Date()) { + const msg = this.unwrapCompressed(); + const literalDataList = msg.packets.filterByTag(_enums2.default.packet.literal); + if (literalDataList.length !== 1) { + throw new Error('Can only verify message with one literal data packet.'); + } + const signatureList = signature.packets; + return createVerificationObjects(signatureList, literalDataList, keys, date, true); +}; + +/** + * Create object containing signer's keyid and validity of signature + * @param {module:packet.Signature} signature signature packets + * @param {Array} literalDataList array of literal data packets + * @param {Array} keys array of keys to verify signatures + * @param {Date} date Verify the signature against the given date, + * i.e. check signature creation time < date < expiration time + * @param {Boolean} detached (optional) whether to verify detached signature packets + * @returns {Promise>} list of signer's keyid and validity of signature + * @async + */ +async function createVerificationObject(signature, literalDataList, keys, date = new Date(), detached = false) { + let primaryKey = null; + let signingKey = null; + await Promise.all(keys.map(async function (key) { + // Look for the unique key that matches issuerKeyId of signature + const result = await key.getSigningKey(signature.issuerKeyId, null); + if (result) { + primaryKey = key; + signingKey = result; + } + })); + + const signaturePacket = signature.correspondingSig || signature; + const verifiedSig = { + keyid: signature.issuerKeyId, + verified: (async () => { + if (!signingKey) { + return null; + } + const verified = await signature.verify(signingKey.keyPacket, signature.signatureType, literalDataList[0], detached); + const sig = await signaturePacket; + if (sig.isExpired(date) || !(sig.created >= signingKey.getCreationTime() && sig.created < (await (signingKey === primaryKey ? signingKey.getExpirationTime() : signingKey.getExpirationTime(primaryKey, date))))) { + return null; + } + return verified; + })(), + signature: (async () => { + const sig = await signaturePacket; + const packetlist = new _packet2.default.List(); + packetlist.push(sig); + return new _signature.Signature(packetlist); + })() + }; + + // Mark potential promise rejections as "handled". This is needed because in + // some cases, we reject them before the user has a reasonable chance to + // handle them (e.g. `await readToEnd(result.data); await result.verified` and + // the data stream errors). + verifiedSig.signature.catch(() => {}); + verifiedSig.verified.catch(() => {}); + + return verifiedSig; +} + +/** + * Create list of objects containing signer's keyid and validity of signature + * @param {Array} signatureList array of signature packets + * @param {Array} literalDataList array of literal data packets + * @param {Array} keys array of keys to verify signatures + * @param {Date} date Verify the signature against the given date, + * i.e. check signature creation time < date < expiration time + * @param {Boolean} detached (optional) whether to verify detached signature packets + * @returns {Promise>} list of signer's keyid and validity of signature + * @async + */ +async function createVerificationObjects(signatureList, literalDataList, keys, date = new Date(), detached = false) { + return Promise.all(signatureList.filter(function (signature) { + return ['text', 'binary'].includes(_enums2.default.read(_enums2.default.signature, signature.signatureType)); + }).map(async function (signature) { + return createVerificationObject(signature, literalDataList, keys, date, detached); + })); +} + +/** + * Unwrap compressed message + * @returns {module:message.Message} message Content of compressed message + */ +Message.prototype.unwrapCompressed = function () { + const compressed = this.packets.filterByTag(_enums2.default.packet.compressed); + if (compressed.length) { + return new Message(compressed[0].packets); + } + return this; +}; + +/** + * Append signature to unencrypted message object + * @param {String|Uint8Array} detachedSignature The detached ASCII-armored or Uint8Array PGP signature + */ +Message.prototype.appendSignature = async function (detachedSignature) { + await this.packets.read(_util2.default.isUint8Array(detachedSignature) ? detachedSignature : (await _armor2.default.decode(detachedSignature)).data); +}; + +/** + * Returns ASCII armored text of message + * @returns {ReadableStream} ASCII armor + */ +Message.prototype.armor = function () { + return _armor2.default.encode(_enums2.default.armor.message, this.packets.write()); +}; + +/** + * reads an OpenPGP armored message and returns a message object + * @param {String | ReadableStream} armoredText text to be parsed + * @returns {Promise} new message object + * @async + * @static + */ +async function readArmored(armoredText) { + //TODO how do we want to handle bad text? Exception throwing + //TODO don't accept non-message armored texts + const streamType = _util2.default.isStream(armoredText); + if (streamType === 'node') { + armoredText = _webStreamTools2.default.nodeToWeb(armoredText); + } + const input = await _armor2.default.decode(armoredText); + return read(input.data, streamType); +} + +/** + * reads an OpenPGP message as byte array and returns a message object + * @param {Uint8Array | ReadableStream} input binary message + * @param {Boolean} fromStream whether the message was created from a Stream + * @returns {Promise} new message object + * @async + * @static + */ +async function read(input, fromStream = _util2.default.isStream(input)) { + const streamType = _util2.default.isStream(input); + if (streamType === 'node') { + input = _webStreamTools2.default.nodeToWeb(input); + } + const packetlist = new _packet2.default.List(); + await packetlist.read(input, fromStream); + const message = new Message(packetlist); + message.fromStream = fromStream; + return message; +} + +/** + * creates new message object from text + * @param {String | ReadableStream} text + * @param {String} filename (optional) + * @param {Date} date (optional) + * @param {utf8|binary|text|mime} type (optional) data packet type + * @returns {module:message.Message} new message object + * @static + */ +function fromText(text, filename, date = new Date(), type = 'utf8') { + const streamType = _util2.default.isStream(text); + if (streamType === 'node') { + text = _webStreamTools2.default.nodeToWeb(text); + } + const literalDataPacket = new _packet2.default.Literal(date); + // text will be converted to UTF8 + literalDataPacket.setText(text, type); + if (filename !== undefined) { + literalDataPacket.setFilename(filename); + } + const literalDataPacketlist = new _packet2.default.List(); + literalDataPacketlist.push(literalDataPacket); + const message = new Message(literalDataPacketlist); + message.fromStream = streamType; + return message; +} + +/** + * creates new message object from binary data + * @param {Uint8Array | ReadableStream} bytes + * @param {String} filename (optional) + * @param {Date} date (optional) + * @param {utf8|binary|text|mime} type (optional) data packet type + * @returns {module:message.Message} new message object + * @static + */ +function fromBinary(bytes, filename, date = new Date(), type = 'binary') { + const streamType = _util2.default.isStream(bytes); + if (!_util2.default.isUint8Array(bytes) && !streamType) { + throw new Error('Data must be in the form of a Uint8Array or Stream'); + } + if (streamType === 'node') { + bytes = _webStreamTools2.default.nodeToWeb(bytes); + } + + const literalDataPacket = new _packet2.default.Literal(date); + literalDataPacket.setBytes(bytes, type); + if (filename !== undefined) { + literalDataPacket.setFilename(filename); + } + const literalDataPacketlist = new _packet2.default.List(); + literalDataPacketlist.push(literalDataPacket); + const message = new Message(literalDataPacketlist); + message.fromStream = streamType; + return message; +} + +},{"./config":79,"./crypto":94,"./encoding/armor":111,"./enums":113,"./key":116,"./packet":125,"./signature":145,"./type/keyid":148,"./util":152,"web-stream-tools":75}],121:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.initWorker = initWorker; +exports.getWorker = getWorker; +exports.destroyWorker = destroyWorker; +exports.generateKey = generateKey; +exports.reformatKey = reformatKey; +exports.revokeKey = revokeKey; +exports.decryptKey = decryptKey; +exports.encryptKey = encryptKey; +exports.encrypt = encrypt; +exports.decrypt = decrypt; +exports.sign = sign; +exports.verify = verify; +exports.encryptSessionKey = encryptSessionKey; +exports.decryptSessionKeys = decryptSessionKeys; + +var _webStreamTools = require('web-stream-tools'); + +var _webStreamTools2 = _interopRequireDefault(_webStreamTools); + +var _message = require('./message'); + +var messageLib = _interopRequireWildcard(_message); + +var _cleartext = require('./cleartext'); + +var _key = require('./key'); + +var _config = require('./config/config'); + +var _config2 = _interopRequireDefault(_config); + +var _enums = require('./enums'); + +var _enums2 = _interopRequireDefault(_enums); + +require('./polyfills'); + +var _util = require('./util'); + +var _util2 = _interopRequireDefault(_util); + +var _async_proxy = require('./worker/async_proxy'); + +var _async_proxy2 = _interopRequireDefault(_async_proxy); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +////////////////////////// +// // +// Web Worker setup // +// // +////////////////////////// + + +let asyncProxy; // instance of the asyncproxy + +/** + * Set the path for the web worker script and create an instance of the async proxy + * @param {String} path relative path to the worker scripts, default: 'openpgp.worker.js' + * @param {Number} n number of workers to initialize + * @param {Array} workers alternative to path parameter: web workers initialized with 'openpgp.worker.js' + * @returns {Promise} returns a promise that resolves to true if all workers have succesfully finished loading + * @async + */ +// OpenPGP.js - An OpenPGP implementation in javascript +// Copyright (C) 2016 Tankred Hase +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @fileoverview The openpgp base module should provide all of the functionality + * to consume the openpgp.js library. All additional classes are documented + * for extending and developing on top of the base library. + * @requires web-stream-tools + * @requires message + * @requires cleartext + * @requires key + * @requires config + * @requires enums + * @requires util + * @requires polyfills + * @requires worker/async_proxy + * @module openpgp + */ + +// This file intentionally has two separate file overviews so that +// a reference to this module appears at the end of doc/index.html. + +/** + * @fileoverview To view the full API documentation, start from + * {@link module:openpgp} + */ + +async function initWorker({ path = 'openpgp.worker.js', n = 1, workers = [] } = {}) { + if (workers.length || typeof window !== 'undefined' && window.Worker && window.MessageChannel) { + const proxy = new _async_proxy2.default({ path, n, workers, config: _config2.default }); + const loaded = await proxy.loaded(); + if (loaded) { + asyncProxy = proxy; + return true; + } + } + return false; +} + +/** + * Returns a reference to the async proxy if the worker was initialized with openpgp.initWorker() + * @returns {module:worker/async_proxy.AsyncProxy|null} the async proxy or null if not initialized + */ +function getWorker() { + return asyncProxy; +} + +/** + * Cleanup the current instance of the web worker. + */ +function destroyWorker() { + asyncProxy = undefined; +} + +////////////////////// +// // +// Key handling // +// // +////////////////////// + + +/** + * Generates a new OpenPGP key pair. Supports RSA and ECC keys. Primary and subkey will be of same type. + * @param {Array} userIds array of user IDs e.g. [{ name:'Phil Zimmermann', email:'phil@openpgp.org' }] + * @param {String} passphrase (optional) The passphrase used to encrypt the resulting private key + * @param {Number} numBits (optional) number of bits for RSA keys: 2048 or 4096. + * @param {Number} keyExpirationTime (optional) The number of seconds after the key creation time that the key expires + * @param {String} curve (optional) elliptic curve for ECC keys: + * curve25519, p256, p384, p521, secp256k1, + * brainpoolP256r1, brainpoolP384r1, or brainpoolP512r1. + * @param {Date} date (optional) override the creation date of the key and the key signatures + * @param {Array} subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}] + * sign parameter defaults to false, and indicates whether the subkey should sign rather than encrypt + * @returns {Promise} The generated key object in the form: + * { key:Key, privateKeyArmored:String, publicKeyArmored:String, revocationCertificate:String } + * @async + * @static + */ + +function generateKey({ userIds = [], passphrase = "", numBits = 2048, keyExpirationTime = 0, curve = "", date = new Date(), subkeys = [{}] }) { + userIds = toArray(userIds); + const options = { userIds, passphrase, numBits, keyExpirationTime, curve, date, subkeys }; + if (_util2.default.getWebCryptoAll() && numBits < 2048) { + throw new Error('numBits should be 2048 or 4096, found: ' + numBits); + } + + if (!_util2.default.getWebCryptoAll() && asyncProxy) { + // use web worker if web crypto apis are not supported + return asyncProxy.delegate('generateKey', options); + } + + return (0, _key.generate)(options).then(async key => { + const revocationCertificate = await key.getRevocationCertificate(); + key.revocationSignatures = []; + + return convertStreams({ + + key: key, + privateKeyArmored: key.armor(), + publicKeyArmored: key.toPublic().armor(), + revocationCertificate: revocationCertificate + + }); + }).catch(onError.bind(null, 'Error generating keypair')); +} + +/** + * Reformats signature packets for a key and rewraps key object. + * @param {Key} privateKey private key to reformat + * @param {Array} userIds array of user IDs e.g. [{ name:'Phil Zimmermann', email:'phil@openpgp.org' }] + * @param {String} passphrase (optional) The passphrase used to encrypt the resulting private key + * @param {Number} keyExpirationTime (optional) The number of seconds after the key creation time that the key expires + * @param {Boolean} revocationCertificate (optional) Whether the returned object should include a revocation certificate to revoke the public key + * @returns {Promise} The generated key object in the form: + * { key:Key, privateKeyArmored:String, publicKeyArmored:String, revocationCertificate:String } + * @async + * @static + */ +function reformatKey({ privateKey, userIds = [], passphrase = "", keyExpirationTime = 0, date, revocationCertificate = true }) { + userIds = toArray(userIds); + const options = { privateKey, userIds, passphrase, keyExpirationTime, date, revocationCertificate }; + if (asyncProxy) { + return asyncProxy.delegate('reformatKey', options); + } + + options.revoked = options.revocationCertificate; + + return (0, _key.reformat)(options).then(async key => { + const revocationCertificate = await key.getRevocationCertificate(); + key.revocationSignatures = []; + + return convertStreams({ + + key: key, + privateKeyArmored: key.armor(), + publicKeyArmored: key.toPublic().armor(), + revocationCertificate: revocationCertificate + + }); + }).catch(onError.bind(null, 'Error reformatting keypair')); +} + +/** + * Revokes a key. Requires either a private key or a revocation certificate. + * If a revocation certificate is passed, the reasonForRevocation parameters will be ignored. + * @param {Key} key (optional) public or private key to revoke + * @param {String} revocationCertificate (optional) revocation certificate to revoke the key with + * @param {Object} reasonForRevocation (optional) object indicating the reason for revocation + * @param {module:enums.reasonForRevocation} reasonForRevocation.flag (optional) flag indicating the reason for revocation + * @param {String} reasonForRevocation.string (optional) string explaining the reason for revocation + * @returns {Promise} The revoked key object in the form: + * { privateKey:Key, privateKeyArmored:String, publicKey:Key, publicKeyArmored:String } + * (if private key is passed) or { publicKey:Key, publicKeyArmored:String } (otherwise) + * @static + */ +function revokeKey({ + key, revocationCertificate, reasonForRevocation +} = {}) { + const options = { + key, revocationCertificate, reasonForRevocation + }; + + if (!_util2.default.getWebCryptoAll() && asyncProxy) { + // use web worker if web crypto apis are not supported + return asyncProxy.delegate('revokeKey', options); + } + + return Promise.resolve().then(() => { + if (revocationCertificate) { + return key.applyRevocationCertificate(revocationCertificate); + } else { + return key.revoke(reasonForRevocation); + } + }).then(async key => { + await convertStreams(key); + if (key.isPrivate()) { + const publicKey = key.toPublic(); + return { + privateKey: key, + privateKeyArmored: key.armor(), + publicKey: publicKey, + publicKeyArmored: publicKey.armor() + }; + } + return { + publicKey: key, + publicKeyArmored: key.armor() + }; + }).catch(onError.bind(null, 'Error revoking key')); +} + +/** + * Unlock a private key with your passphrase. + * @param {Key} privateKey the private key that is to be decrypted + * @param {String|Array} passphrase the user's passphrase(s) chosen during key generation + * @returns {Promise} the unlocked key object in the form: { key:Key } + * @async + */ +function decryptKey({ privateKey, passphrase }) { + if (asyncProxy) { + // use web worker if available + return asyncProxy.delegate('decryptKey', { privateKey, passphrase }); + } + + return Promise.resolve().then(async function () { + await privateKey.decrypt(passphrase); + + return { + key: privateKey + }; + }).catch(onError.bind(null, 'Error decrypting private key')); +} + +/** + * Lock a private key with your passphrase. + * @param {Key} privateKey the private key that is to be decrypted + * @param {String|Array} passphrase the user's passphrase(s) chosen during key generation + * @returns {Promise} the locked key object in the form: { key:Key } + * @async + */ +function encryptKey({ privateKey, passphrase }) { + if (asyncProxy) { + // use web worker if available + return asyncProxy.delegate('encryptKey', { privateKey, passphrase }); + } + + return Promise.resolve().then(async function () { + await privateKey.encrypt(passphrase); + + return { + key: privateKey + }; + }).catch(onError.bind(null, 'Error decrypting private key')); +} + +/////////////////////////////////////////// +// // +// Message encryption and decryption // +// // +/////////////////////////////////////////// + + +/** + * Encrypts message text/data with public keys, passwords or both at once. At least either public keys or passwords + * must be specified. If private keys are specified, those will be used to sign the message. + * @param {Message} message message to be encrypted as created by openpgp.message.fromText or openpgp.message.fromBinary + * @param {Key|Array} publicKeys (optional) array of keys or single key, used to encrypt the message + * @param {Key|Array} privateKeys (optional) private keys for signing. If omitted message will not be signed + * @param {String|Array} passwords (optional) array of passwords or a single password to encrypt the message + * @param {Object} sessionKey (optional) session key in the form: { data:Uint8Array, algorithm:String } + * @param {module:enums.compression} compression (optional) which compression algorithm to compress the message with, defaults to what is specified in config + * @param {Boolean} armor (optional) if the return values should be ascii armored or the message/signature objects + * @param {'web'|'node'|false} streaming (optional) whether to return data as a stream. Defaults to the type of stream `message` was created from, if any. + * @param {Boolean} detached (optional) if the signature should be detached (if true, signature will be added to returned object) + * @param {Signature} signature (optional) a detached signature to add to the encrypted message + * @param {Boolean} returnSessionKey (optional) if the unencrypted session key should be added to returned object + * @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs + * @param {Date} date (optional) override the creation date of the message signature + * @param {Array} fromUserIds (optional) array of user IDs to sign with, one per key in `privateKeys`, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] + * @param {Array} toUserIds (optional) array of user IDs to encrypt for, one per key in `publicKeys`, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }] + * @returns {Promise} Object containing encrypted (and optionally signed) message in the form: + * + * { + * data: String|ReadableStream|NodeStream, (if `armor` was true, the default) + * message: Message, (if `armor` was false) + * signature: String|ReadableStream|NodeStream, (if `detached` was true and `armor` was true) + * signature: Signature (if `detached` was true and `armor` was false) + * sessionKey: { data, algorithm, aeadAlgorithm } (if `returnSessionKey` was true) + * } + * @async + * @static + */ +function encrypt({ message, publicKeys, privateKeys, passwords, sessionKey, compression = _config2.default.compression, armor = true, streaming = message && message.fromStream, detached = false, signature = null, returnSessionKey = false, wildcard = false, date = new Date(), fromUserIds = [], toUserIds = [] }) { + checkMessage(message);publicKeys = toArray(publicKeys);privateKeys = toArray(privateKeys);passwords = toArray(passwords);fromUserIds = toArray(fromUserIds);toUserIds = toArray(toUserIds); + + if (!nativeAEAD() && asyncProxy) { + // use web worker if web crypto apis are not supported + return asyncProxy.delegate('encrypt', { message, publicKeys, privateKeys, passwords, sessionKey, compression, armor, streaming, detached, signature, returnSessionKey, wildcard, date, fromUserIds, toUserIds }); + } + const result = {}; + return Promise.resolve().then(async function () { + if (!privateKeys) { + privateKeys = []; + } + if (privateKeys.length || signature) { + // sign the message only if private keys or signature is specified + if (detached) { + const detachedSignature = await message.signDetached(privateKeys, signature, date, fromUserIds); + result.signature = armor ? detachedSignature.armor() : detachedSignature; + } else { + message = await message.sign(privateKeys, signature, date, fromUserIds); + } + } + message = message.compress(compression); + return message.encrypt(publicKeys, passwords, sessionKey, wildcard, date, toUserIds, streaming); + }).then(async encrypted => { + if (armor) { + result.data = encrypted.message.armor(); + } else { + result.message = encrypted.message; + } + if (returnSessionKey) { + result.sessionKey = encrypted.sessionKey; + } + return convertStreams(result, streaming, armor ? ['signature', 'data'] : []); + }).catch(onError.bind(null, 'Error encrypting message')); +} + +/** + * Decrypts a message with the user's private key, a session key or a password. Either a private key, + * a session key or a password must be specified. + * @param {Message} message the message object with the encrypted data + * @param {Key|Array} privateKeys (optional) private keys with decrypted secret key data or session key + * @param {String|Array} passwords (optional) passwords to decrypt the message + * @param {Object|Array} sessionKeys (optional) session keys in the form: { data:Uint8Array, algorithm:String } + * @param {Key|Array} publicKeys (optional) array of public keys or single key, to verify signatures + * @param {'utf8'|'binary'} format (optional) whether to return data as a string(Stream) or Uint8Array(Stream). If 'utf8' (the default), also normalize newlines. + * @param {'web'|'node'|false} streaming (optional) whether to return data as a stream. Defaults to the type of stream `message` was created from, if any. + * @param {Signature} signature (optional) detached signature for verification + * @param {Date} date (optional) use the given date for verification instead of the current time + * @returns {Promise} Object containing decrypted and verified message in the form: + * + * { + * data: String|ReadableStream|NodeStream, (if format was 'utf8', the default) + * data: Uint8Array|ReadableStream|NodeStream, (if format was 'binary') + * filename: String, + * signatures: [ + * { + * keyid: module:type/keyid, + * verified: Promise, + * valid: Boolean (if streaming was false) + * }, ... + * ] + * } + * @async + * @static + */ +function decrypt({ message, privateKeys, passwords, sessionKeys, publicKeys, format = 'utf8', streaming = message && message.fromStream, signature = null, date = new Date() }) { + checkMessage(message);publicKeys = toArray(publicKeys);privateKeys = toArray(privateKeys);passwords = toArray(passwords);sessionKeys = toArray(sessionKeys); + + if (!nativeAEAD() && asyncProxy) { + // use web worker if web crypto apis are not supported + return asyncProxy.delegate('decrypt', { message, privateKeys, passwords, sessionKeys, publicKeys, format, streaming, signature, date }); + } + + return message.decrypt(privateKeys, passwords, sessionKeys, streaming).then(async function (decrypted) { + if (!publicKeys) { + publicKeys = []; + } + + const result = {}; + result.signatures = signature ? await decrypted.verifyDetached(signature, publicKeys, date, streaming) : await decrypted.verify(publicKeys, date, streaming); + result.data = format === 'binary' ? decrypted.getLiteralData() : decrypted.getText(); + result.filename = decrypted.getFilename(); + if (streaming) linkStreams(result, message); + result.data = await convertStream(result.data, streaming); + if (!streaming) await prepareSignatures(result.signatures); + return result; + }).catch(onError.bind(null, 'Error decrypting message')); +} + +////////////////////////////////////////// +// // +// Message signing and verification // +// // +////////////////////////////////////////// + + +/** + * Signs a cleartext message. + * @param {CleartextMessage|Message} message (cleartext) message to be signed + * @param {Key|Array} privateKeys array of keys or single key with decrypted secret key data to sign cleartext + * @param {Boolean} armor (optional) if the return value should be ascii armored or the message object + * @param {'web'|'node'|false} streaming (optional) whether to return data as a stream. Defaults to the type of stream `message` was created from, if any. + * @param {Boolean} detached (optional) if the return value should contain a detached signature + * @param {Date} date (optional) override the creation date of the signature + * @param {Array} fromUserIds (optional) array of user IDs to sign with, one per key in `privateKeys`, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] + * @returns {Promise} Object containing signed message in the form: + * + * { + * data: String|ReadableStream|NodeStream, (if `armor` was true, the default) + * message: Message (if `armor` was false) + * } + * + * Or, if `detached` was true: + * + * { + * signature: String|ReadableStream|NodeStream, (if `armor` was true, the default) + * signature: Signature (if `armor` was false) + * } + * @async + * @static + */ +function sign({ message, privateKeys, armor = true, streaming = message && message.fromStream, detached = false, date = new Date(), fromUserIds = [] }) { + checkCleartextOrMessage(message); + privateKeys = toArray(privateKeys);fromUserIds = toArray(fromUserIds); + + if (asyncProxy) { + // use web worker if available + return asyncProxy.delegate('sign', { + message, privateKeys, armor, streaming, detached, date, fromUserIds + }); + } + + const result = {}; + return Promise.resolve().then(async function () { + if (detached) { + const signature = await message.signDetached(privateKeys, undefined, date, fromUserIds); + result.signature = armor ? signature.armor() : signature; + if (message.packets) { + result.signature = _webStreamTools2.default.transformPair(message.packets.write(), async (readable, writable) => { + await Promise.all([_webStreamTools2.default.pipe(result.signature, writable), _webStreamTools2.default.readToEnd(readable).catch(() => {})]); + }); + } + } else { + message = await message.sign(privateKeys, undefined, date, fromUserIds); + if (armor) { + result.data = message.armor(); + } else { + result.message = message; + } + } + return convertStreams(result, streaming, armor ? ['signature', 'data'] : []); + }).catch(onError.bind(null, 'Error signing cleartext message')); +} + +/** + * Verifies signatures of cleartext signed message + * @param {Key|Array} publicKeys array of publicKeys or single key, to verify signatures + * @param {CleartextMessage|Message} message (cleartext) message object with signatures + * @param {'web'|'node'|false} streaming (optional) whether to return data as a stream. Defaults to the type of stream `message` was created from, if any. + * @param {Signature} signature (optional) detached signature for verification + * @param {Date} date (optional) use the given date for verification instead of the current time + * @returns {Promise} Object containing verified message in the form: + * + * { + * data: String|ReadableStream|NodeStream, (if `message` was a CleartextMessage) + * data: Uint8Array|ReadableStream|NodeStream, (if `message` was a Message) + * signatures: [ + * { + * keyid: module:type/keyid, + * verified: Promise, + * valid: Boolean (if `streaming` was false) + * }, ... + * ] + * } + * @async + * @static + */ +function verify({ message, publicKeys, streaming = message && message.fromStream, signature = null, date = new Date() }) { + checkCleartextOrMessage(message); + publicKeys = toArray(publicKeys); + + if (asyncProxy) { + // use web worker if available + return asyncProxy.delegate('verify', { message, publicKeys, streaming, signature, date }); + } + + return Promise.resolve().then(async function () { + const result = {}; + result.signatures = signature ? await message.verifyDetached(signature, publicKeys, date, streaming) : await message.verify(publicKeys, date, streaming); + result.data = message instanceof _cleartext.CleartextMessage ? message.getText() : message.getLiteralData(); + if (streaming) linkStreams(result, message); + result.data = await convertStream(result.data, streaming); + if (!streaming) await prepareSignatures(result.signatures); + return result; + }).catch(onError.bind(null, 'Error verifying cleartext signed message')); +} + +/////////////////////////////////////////////// +// // +// Session key encryption and decryption // +// // +/////////////////////////////////////////////// + + +/** + * Encrypt a symmetric session key with public keys, passwords, or both at once. At least either public keys + * or passwords must be specified. + * @param {Uint8Array} data the session key to be encrypted e.g. 16 random bytes (for aes128) + * @param {String} algorithm algorithm of the symmetric session key e.g. 'aes128' or 'aes256' + * @param {String} aeadAlgorithm (optional) aead algorithm, e.g. 'eax' or 'ocb' + * @param {Key|Array} publicKeys (optional) array of public keys or single key, used to encrypt the key + * @param {String|Array} passwords (optional) passwords for the message + * @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs + * @param {Date} date (optional) override the date + * @param {Array} toUserIds (optional) array of user IDs to encrypt for, one per key in `publicKeys`, e.g. [{ name:'Phil Zimmermann', email:'phil@openpgp.org' }] + * @returns {Promise} the encrypted session key packets contained in a message object + * @async + * @static + */ +function encryptSessionKey({ data, algorithm, aeadAlgorithm, publicKeys, passwords, wildcard = false, date = new Date(), toUserIds = [] }) { + checkBinary(data);checkString(algorithm, 'algorithm');publicKeys = toArray(publicKeys);passwords = toArray(passwords);toUserIds = toArray(toUserIds); + + if (asyncProxy) { + // use web worker if available + return asyncProxy.delegate('encryptSessionKey', { data, algorithm, aeadAlgorithm, publicKeys, passwords, wildcard, date, toUserIds }); + } + + return Promise.resolve().then(async function () { + + return { message: await messageLib.encryptSessionKey(data, algorithm, aeadAlgorithm, publicKeys, passwords, wildcard, date, toUserIds) }; + }).catch(onError.bind(null, 'Error encrypting session key')); +} + +/** + * Decrypt symmetric session keys with a private key or password. Either a private key or + * a password must be specified. + * @param {Message} message a message object containing the encrypted session key packets + * @param {Key|Array} privateKeys (optional) private keys with decrypted secret key data + * @param {String|Array} passwords (optional) passwords to decrypt the session key + * @returns {Promise} Array of decrypted session key, algorithm pairs in form: + * { data:Uint8Array, algorithm:String } + * or 'undefined' if no key packets found + * @async + * @static + */ +function decryptSessionKeys({ message, privateKeys, passwords }) { + checkMessage(message);privateKeys = toArray(privateKeys);passwords = toArray(passwords); + + if (asyncProxy) { + // use web worker if available + return asyncProxy.delegate('decryptSessionKeys', { message, privateKeys, passwords }); + } + + return Promise.resolve().then(async function () { + + return message.decryptSessionKeys(privateKeys, passwords); + }).catch(onError.bind(null, 'Error decrypting session keys')); +} + +////////////////////////// +// // +// Helper functions // +// // +////////////////////////// + + +/** + * Input validation + */ +function checkString(data, name) { + if (!_util2.default.isString(data)) { + throw new Error('Parameter [' + (name || 'data') + '] must be of type String'); + } +} +function checkBinary(data, name) { + if (!_util2.default.isUint8Array(data)) { + throw new Error('Parameter [' + (name || 'data') + '] must be of type Uint8Array'); + } +} +function checkMessage(message) { + if (!(message instanceof messageLib.Message)) { + throw new Error('Parameter [message] needs to be of type Message'); + } +} +function checkCleartextOrMessage(message) { + if (!(message instanceof _cleartext.CleartextMessage) && !(message instanceof messageLib.Message)) { + throw new Error('Parameter [message] needs to be of type Message or CleartextMessage'); + } +} + +/** + * Normalize parameter to an array if it is not undefined. + * @param {Object} param the parameter to be normalized + * @returns {Array|undefined} the resulting array or undefined + */ +function toArray(param) { + if (param && !_util2.default.isArray(param)) { + param = [param]; + } + return param; +} + +/** + * Convert data to or from Stream + * @param {Object} data the data to convert + * @param {'web'|'node'|false} streaming (optional) whether to return a ReadableStream + * @returns {Object} the data in the respective format + */ +async function convertStream(data, streaming) { + if (!streaming && _util2.default.isStream(data)) { + return _webStreamTools2.default.readToEnd(data); + } + if (streaming && !_util2.default.isStream(data)) { + data = new ReadableStream({ + start(controller) { + controller.enqueue(data); + controller.close(); + } + }); + } + if (streaming === 'node') { + data = _webStreamTools2.default.webToNode(data); + } + return data; +} + +/** + * Convert object properties from Stream + * @param {Object} obj the data to convert + * @param {'web'|'node'|false} streaming (optional) whether to return ReadableStreams + * @param {Array} keys (optional) which keys to return as streams, if possible + * @returns {Object} the data in the respective format + */ +async function convertStreams(obj, streaming, keys = []) { + if (Object.prototype.isPrototypeOf(obj) && !Uint8Array.prototype.isPrototypeOf(obj)) { + await Promise.all(Object.entries(obj).map(async ([key, value]) => { + // recursively search all children + if (_util2.default.isStream(value) || keys.includes(key)) { + obj[key] = await convertStream(value, streaming); + } else { + await convertStreams(obj[key], streaming); + } + })); + } + return obj; +} + +/** + * Link result.data to the message stream for cancellation. + * @param {Object} result the data to convert + * @param {Message} message message object + * @returns {Object} + */ +function linkStreams(result, message) { + result.data = _webStreamTools2.default.transformPair(message.packets.stream, async (readable, writable) => { + await _webStreamTools2.default.pipe(result.data, writable); + }); +} + +/** + * Wait until signature objects have been verified + * @param {Object} signatures list of signatures + */ +async function prepareSignatures(signatures) { + await Promise.all(signatures.map(async signature => { + signature.signature = await signature.signature; + try { + signature.valid = await signature.verified; + } catch (e) { + signature.valid = null; + signature.error = e; + _util2.default.print_debug_error(e); + } + })); +} + +/** + * Global error handler that logs the stack trace and rethrows a high lvl error message. + * @param {String} message A human readable high level error Message + * @param {Error} error The internal error that caused the failure + */ +function onError(message, error) { + // log the stack trace + _util2.default.print_debug_error(error); + + // update error message + try { + error.message = message + ': ' + error.message; + } catch (e) {} + + throw error; +} + +/** + * Check for native AEAD support and configuration by the user. Only + * browsers that implement the current WebCrypto specification support + * native GCM. Native EAX is built on CTR and CBC, which current + * browsers support. OCB and CFB are not natively supported. + * @returns {Boolean} If authenticated encryption should be used + */ +function nativeAEAD() { + return _config2.default.aead_protect && (_config2.default.aead_mode === _enums2.default.aead.eax || _config2.default.aead_mode === _enums2.default.aead.experimental_gcm) && _util2.default.getWebCrypto(); +} + +},{"./cleartext":77,"./config/config":78,"./enums":113,"./key":116,"./message":120,"./polyfills":144,"./util":152,"./worker/async_proxy":154,"web-stream-tools":75}],122:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Trust = exports.Signature = exports.SecretSubkey = exports.Userid = exports.SecretKey = exports.OnePassSignature = exports.UserAttribute = exports.PublicSubkey = exports.Marker = exports.SymmetricallyEncrypted = exports.PublicKey = exports.Literal = exports.SymEncryptedSessionKey = exports.PublicKeyEncryptedSessionKey = exports.SymEncryptedAEADProtected = exports.SymEncryptedIntegrityProtected = exports.Compressed = undefined; + +var _compressed = require('./compressed.js'); + +Object.defineProperty(exports, 'Compressed', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_compressed).default; + } +}); + +var _sym_encrypted_integrity_protected = require('./sym_encrypted_integrity_protected.js'); + +Object.defineProperty(exports, 'SymEncryptedIntegrityProtected', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_sym_encrypted_integrity_protected).default; + } +}); + +var _sym_encrypted_aead_protected = require('./sym_encrypted_aead_protected.js'); + +Object.defineProperty(exports, 'SymEncryptedAEADProtected', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_sym_encrypted_aead_protected).default; + } +}); + +var _public_key_encrypted_session_key = require('./public_key_encrypted_session_key.js'); + +Object.defineProperty(exports, 'PublicKeyEncryptedSessionKey', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_public_key_encrypted_session_key).default; + } +}); + +var _sym_encrypted_session_key = require('./sym_encrypted_session_key.js'); + +Object.defineProperty(exports, 'SymEncryptedSessionKey', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_sym_encrypted_session_key).default; + } +}); + +var _literal = require('./literal.js'); + +Object.defineProperty(exports, 'Literal', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_literal).default; + } +}); + +var _public_key = require('./public_key.js'); + +Object.defineProperty(exports, 'PublicKey', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_public_key).default; + } +}); + +var _symmetrically_encrypted = require('./symmetrically_encrypted.js'); + +Object.defineProperty(exports, 'SymmetricallyEncrypted', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_symmetrically_encrypted).default; + } +}); + +var _marker = require('./marker.js'); + +Object.defineProperty(exports, 'Marker', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_marker).default; + } +}); + +var _public_subkey = require('./public_subkey.js'); + +Object.defineProperty(exports, 'PublicSubkey', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_public_subkey).default; + } +}); + +var _user_attribute = require('./user_attribute.js'); + +Object.defineProperty(exports, 'UserAttribute', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_user_attribute).default; + } +}); + +var _one_pass_signature = require('./one_pass_signature.js'); + +Object.defineProperty(exports, 'OnePassSignature', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_one_pass_signature).default; + } +}); + +var _secret_key = require('./secret_key.js'); + +Object.defineProperty(exports, 'SecretKey', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_secret_key).default; + } +}); + +var _userid = require('./userid.js'); + +Object.defineProperty(exports, 'Userid', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_userid).default; + } +}); + +var _secret_subkey = require('./secret_subkey.js'); + +Object.defineProperty(exports, 'SecretSubkey', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_secret_subkey).default; + } +}); + +var _signature = require('./signature.js'); + +Object.defineProperty(exports, 'Signature', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_signature).default; + } +}); + +var _trust = require('./trust.js'); + +Object.defineProperty(exports, 'Trust', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_trust).default; + } +}); +exports.newPacketFromTag = newPacketFromTag; +exports.fromStructuredClone = fromStructuredClone; + +var _enums = require('../enums.js'); + +var _enums2 = _interopRequireDefault(_enums); + +var _all_packets = require('./all_packets.js'); + +var packets = _interopRequireWildcard(_all_packets); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Allocate a new packet + * @function newPacketFromTag + * @memberof module:packet + * @param {String} tag property name from {@link module:enums.packet} + * @returns {Object} new packet object with type based on tag + */ +function newPacketFromTag(tag) { + return new packets[packetClassFromTagName(tag)](); +} + +/** + * Allocate a new packet from structured packet clone + * @see {@link https://w3c.github.io/html/infrastructure.html#safe-passing-of-structured-data} + * @function fromStructuredClone + * @memberof module:packet + * @param {Object} packetClone packet clone + * @returns {Object} new packet object with data from packet clone + */ +function fromStructuredClone(packetClone) { + const tagName = _enums2.default.read(_enums2.default.packet, packetClone.tag); + const packet = newPacketFromTag(tagName); + Object.assign(packet, packetClone); + if (packet.postCloneTypeFix) { + packet.postCloneTypeFix(); + } + return packet; +} + +/** + * Convert tag name to class name + * @param {String} tag property name from {@link module:enums.packet} + * @returns {String} + * @private + */ +function packetClassFromTagName(tag) { + return tag.substr(0, 1).toUpperCase() + tag.substr(1); +} + +},{"../enums.js":113,"./all_packets.js":122,"./compressed.js":124,"./literal.js":126,"./marker.js":127,"./one_pass_signature.js":128,"./public_key.js":131,"./public_key_encrypted_session_key.js":132,"./public_subkey.js":133,"./secret_key.js":134,"./secret_subkey.js":135,"./signature.js":136,"./sym_encrypted_aead_protected.js":137,"./sym_encrypted_integrity_protected.js":138,"./sym_encrypted_session_key.js":139,"./symmetrically_encrypted.js":140,"./trust.js":141,"./user_attribute.js":142,"./userid.js":143}],123:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.clonePackets = clonePackets; +exports.parseClonedPackets = parseClonedPackets; + +var _webStreamTools = require('web-stream-tools'); + +var _webStreamTools2 = _interopRequireDefault(_webStreamTools); + +var _key = require('../key'); + +var _message = require('../message'); + +var _cleartext = require('../cleartext'); + +var _signature = require('../signature'); + +var _packetlist = require('./packetlist'); + +var _packetlist2 = _interopRequireDefault(_packetlist); + +var _keyid = require('../type/keyid'); + +var _keyid2 = _interopRequireDefault(_keyid); + +var _util = require('../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +////////////////////////////// +// // +// List --> Clone // +// // +////////////////////////////// + + +/** + * Create a packetlist from the correspoding object types. + * @param {Object} options the object passed to and from the web worker + * @returns {Object} a mutated version of the options optject + */ +// OpenPGP.js - An OpenPGP implementation in javascript +// Copyright (C) 2015 Tankred Hase +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @fileoverview This module implements packet list cloning required to + * pass certain object types between the web worker and main thread using + * the structured cloning algorithm. + * @module packet/clone + */ + +function clonePackets(options) { + if (options.publicKeys) { + options.publicKeys = options.publicKeys.map(key => key.toPacketlist()); + } + if (options.privateKeys) { + options.privateKeys = options.privateKeys.map(key => key.toPacketlist()); + } + if (options.privateKey) { + options.privateKey = options.privateKey.toPacketlist(); + } + if (options.key) { + options.key = options.key.toPacketlist(); + } + if (options.message) { + //could be either a Message or CleartextMessage object + if (options.message instanceof _message.Message) { + options.message = options.message.packets; + } else if (options.message instanceof _cleartext.CleartextMessage) { + options.message = { text: options.message.text, signature: options.message.signature.packets }; + } + } + if (options.signature && options.signature instanceof _signature.Signature) { + options.signature = options.signature.packets; + } + if (options.signatures) { + options.signatures.forEach(verificationObjectToClone); + } + return options; +} + +function verificationObjectToClone(verObject) { + const verified = verObject.verified; + verObject.verified = _webStreamTools2.default.fromAsync(() => verified); + if (verObject.signature instanceof Promise) { + const signature = verObject.signature; + verObject.signature = _webStreamTools2.default.fromAsync(async () => { + const packets = (await signature).packets; + try { + await verified; + delete packets[0].signature; + } catch (e) {} + return packets; + }); + } else { + verObject.signature = verObject.signature.packets; + } + if (verObject.error) { + verObject.error = verObject.error.message; + } + return verObject; +} + +////////////////////////////// +// // +// Clone --> List // +// // +////////////////////////////// + + +/** + * Creates an object with the correct prototype from a corresponding packetlist. + * @param {Object} options the object passed to and from the web worker + * @param {String} method the public api function name to be delegated to the worker + * @returns {Object} a mutated version of the options optject + */ +function parseClonedPackets(options) { + if (options.publicKeys) { + options.publicKeys = options.publicKeys.map(packetlistCloneToKey); + } + if (options.privateKeys) { + options.privateKeys = options.privateKeys.map(packetlistCloneToKey); + } + if (options.privateKey) { + options.privateKey = packetlistCloneToKey(options.privateKey); + } + if (options.key) { + options.key = packetlistCloneToKey(options.key); + } + if (options.message && options.message.signature) { + options.message = packetlistCloneToCleartextMessage(options.message); + } else if (options.message) { + options.message = packetlistCloneToMessage(options.message); + } + if (options.signatures) { + options.signatures = options.signatures.map(packetlistCloneToSignatures); + } + if (options.signature) { + options.signature = packetlistCloneToSignature(options.signature); + } + return options; +} + +function packetlistCloneToKey(clone) { + const packetlist = _packetlist2.default.fromStructuredClone(clone); + return new _key.Key(packetlist); +} + +function packetlistCloneToMessage(clone) { + const packetlist = _packetlist2.default.fromStructuredClone(clone); + return new _message.Message(packetlist); +} + +function packetlistCloneToCleartextMessage(clone) { + const packetlist = _packetlist2.default.fromStructuredClone(clone.signature); + return new _cleartext.CleartextMessage(clone.text, new _signature.Signature(packetlist)); +} + +//verification objects +function packetlistCloneToSignatures(clone) { + clone.keyid = _keyid2.default.fromClone(clone.keyid); + if (_util2.default.isStream(clone.signature)) { + clone.signature = _webStreamTools2.default.readToEnd(clone.signature, ([signature]) => new _signature.Signature(_packetlist2.default.fromStructuredClone(signature))); + clone.signature.catch(() => {}); + } else { + clone.signature = new _signature.Signature(_packetlist2.default.fromStructuredClone(clone.signature)); + } + clone.verified = _webStreamTools2.default.readToEnd(clone.verified, ([verified]) => verified); + clone.verified.catch(() => {}); + if (clone.error) { + clone.error = new Error(clone.error); + } + return clone; +} + +function packetlistCloneToSignature(clone) { + if (_util2.default.isString(clone) || _util2.default.isStream(clone)) { + //signature is armored + return clone; + } + const packetlist = _packetlist2.default.fromStructuredClone(clone); + return new _signature.Signature(packetlist); +} + +},{"../cleartext":77,"../key":116,"../message":120,"../signature":145,"../type/keyid":148,"../util":152,"./packetlist":130,"web-stream-tools":75}],124:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _pako = require('pako'); + +var _pako2 = _interopRequireDefault(_pako); + +var _seekBzip = require('seek-bzip'); + +var _seekBzip2 = _interopRequireDefault(_seekBzip); + +var _webStreamTools = require('web-stream-tools'); + +var _webStreamTools2 = _interopRequireDefault(_webStreamTools); + +var _config = require('../config'); + +var _config2 = _interopRequireDefault(_config); + +var _enums = require('../enums'); + +var _enums2 = _interopRequireDefault(_enums); + +var _util = require('../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Implementation of the Compressed Data Packet (Tag 8) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.6|RFC4880 5.6}: + * The Compressed Data packet contains compressed data. Typically, + * this packet is found as the contents of an encrypted packet, or following + * a Signature or One-Pass Signature packet, and contains a literal data packet. + * @memberof module:packet + * @constructor + */ +// GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @requires web-stream-tools + * @requires pako + * @requires config + * @requires enums + * @requires util + * @requires compression/bzip2 + */ + +function Compressed() { + /** + * Packet type + * @type {module:enums.packet} + */ + this.tag = _enums2.default.packet.compressed; + /** + * List of packets + * @type {module:packet.List} + */ + this.packets = null; + /** + * Compression algorithm + * @type {compression} + */ + this.algorithm = 'zip'; + + /** + * Compressed packet data + * @type {Uint8Array | ReadableStream} + */ + this.compressed = null; +} + +/** + * Parsing function for the packet. + * @param {Uint8Array | ReadableStream} bytes Payload of a tag 8 packet + */ +Compressed.prototype.read = async function (bytes, streaming) { + await _webStreamTools2.default.parse(bytes, async reader => { + + // One octet that gives the algorithm used to compress the packet. + this.algorithm = _enums2.default.read(_enums2.default.compression, (await reader.readByte())); + + // Compressed data, which makes up the remainder of the packet. + this.compressed = reader.remainder(); + + await this.decompress(streaming); + }); +}; + +/** + * Return the compressed packet. + * @returns {Uint8Array | ReadableStream} binary compressed packet + */ +Compressed.prototype.write = function () { + if (this.compressed === null) { + this.compress(); + } + + return _util2.default.concat([new Uint8Array([_enums2.default.write(_enums2.default.compression, this.algorithm)]), this.compressed]); +}; + +/** + * Decompression method for decompressing the compressed data + * read by read_packet + */ +Compressed.prototype.decompress = async function (streaming) { + + if (!decompress_fns[this.algorithm]) { + throw new Error(this.algorithm + ' decompression not supported'); + } + + await this.packets.read(decompress_fns[this.algorithm](this.compressed), streaming); +}; + +/** + * Compress the packet data (member decompressedData) + */ +Compressed.prototype.compress = function () { + + if (!compress_fns[this.algorithm]) { + throw new Error(this.algorithm + ' compression not supported'); + } + + this.compressed = compress_fns[this.algorithm](this.packets.write()); +}; + +exports.default = Compressed; + +////////////////////////// +// // +// Helper functions // +// // +////////////////////////// + + +const nodeZlib = _util2.default.getNodeZlib(); + +function node_zlib(func, options = {}) { + return function (data) { + return _webStreamTools2.default.nodeToWeb(_webStreamTools2.default.webToNode(data).pipe(func(options))); + }; +} + +function pako_zlib(constructor, options = {}) { + return function (data) { + const obj = new constructor(options); + return _webStreamTools2.default.transform(data, value => { + if (value.length) { + obj.push(value, _pako2.default.Z_SYNC_FLUSH); + return obj.result; + } + }, () => { + if (constructor === _pako2.default.Deflate) { + obj.push([], _pako2.default.Z_FINISH); + return obj.result; + } + }); + }; +} + +function bzip2(func) { + return function (data) { + return _webStreamTools2.default.fromAsync(async () => func((await _webStreamTools2.default.readToEnd(data)))); + }; +} + +let compress_fns; +let decompress_fns; +if (nodeZlib) { + // Use Node native zlib for DEFLATE compression/decompression + compress_fns = { + zip: node_zlib(nodeZlib.createDeflateRaw, { level: _config2.default.deflate_level }), + zlib: node_zlib(nodeZlib.createDeflate, { level: _config2.default.deflate_level }) + }; + + decompress_fns = { + zip: node_zlib(nodeZlib.createInflateRaw), + zlib: node_zlib(nodeZlib.createInflate), + bzip2: bzip2(_seekBzip2.default.decode) + }; +} else { + // Use JS fallbacks + compress_fns = { + zip: pako_zlib(_pako2.default.Deflate, { raw: true, level: _config2.default.deflate_level }), + zlib: pako_zlib(_pako2.default.Deflate, { level: _config2.default.deflate_level }) + }; + + decompress_fns = { + zip: pako_zlib(_pako2.default.Inflate, { raw: true }), + zlib: pako_zlib(_pako2.default.Inflate), + bzip2: bzip2(_seekBzip2.default.decode) + }; +} + +},{"../config":79,"../enums":113,"../util":152,"pako":50,"seek-bzip":69,"web-stream-tools":75}],125:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _all_packets = require('./all_packets'); + +var packets = _interopRequireWildcard(_all_packets); + +var _clone = require('./clone'); + +var clone = _interopRequireWildcard(_clone); + +var _packetlist = require('./packetlist'); + +var _packetlist2 = _interopRequireDefault(_packetlist); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +const mod = { + List: _packetlist2.default, + clone +}; /** + * @fileoverview OpenPGP packet types + * @see module:packet/all_packets + * @see module:packet/clone + * @see module:packet.List + * @module packet + */ + +Object.assign(mod, packets); + +exports.default = mod; + +},{"./all_packets":122,"./clone":123,"./packetlist":130}],126:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _webStreamTools = require('web-stream-tools'); + +var _webStreamTools2 = _interopRequireDefault(_webStreamTools); + +var _enums = require('../enums'); + +var _enums2 = _interopRequireDefault(_enums); + +var _util = require('../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Implementation of the Literal Data Packet (Tag 11) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.9|RFC4880 5.9}: + * A Literal Data packet contains the body of a message; data that is not to be + * further interpreted. + * @param {Date} date the creation date of the literal package + * @memberof module:packet + * @constructor + */ +function Literal(date = new Date()) { + this.tag = _enums2.default.packet.literal; + this.format = 'utf8'; // default format for literal data packets + this.date = _util2.default.normalizeDate(date); + this.text = null; // textual data representation + this.data = null; // literal data representation + this.filename = 'msg.txt'; +} + +/** + * Set the packet data to a javascript native string, end of line + * will be normalized to \r\n and by default text is converted to UTF8 + * @param {String | ReadableStream} text Any native javascript string + * @param {utf8|binary|text|mime} format (optional) The format of the string of bytes + */ +// GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @requires web-stream-tools + * @requires enums + * @requires util + */ + +Literal.prototype.setText = function (text, format = 'utf8') { + this.format = format; + this.text = text; + this.data = null; +}; + +/** + * Returns literal data packets as native JavaScript string + * with normalized end of line to \n + * @param {Boolean} clone (optional) Whether to return a clone so that getBytes/getText can be called again + * @returns {String | ReadableStream} literal data as text + */ +Literal.prototype.getText = function (clone = false) { + if (this.text === null || _util2.default.isStream(this.text)) { + // Assume that this.text has been read + this.text = _util2.default.nativeEOL(_util2.default.decode_utf8(this.getBytes(clone))); + } + return this.text; +}; + +/** + * Set the packet data to value represented by the provided string of bytes. + * @param {Uint8Array | ReadableStream} bytes The string of bytes + * @param {utf8|binary|text|mime} format The format of the string of bytes + */ +Literal.prototype.setBytes = function (bytes, format) { + this.format = format; + this.data = bytes; + this.text = null; +}; + +/** + * Get the byte sequence representing the literal packet data + * @param {Boolean} clone (optional) Whether to return a clone so that getBytes/getText can be called again + * @returns {Uint8Array | ReadableStream} A sequence of bytes + */ +Literal.prototype.getBytes = function (clone = false) { + if (this.data === null) { + // normalize EOL to \r\n and encode UTF8 + this.data = _util2.default.encode_utf8(_util2.default.canonicalizeEOL(this.text)); + } + if (clone) { + return _webStreamTools2.default.passiveClone(this.data); + } + return this.data; +}; + +/** + * Sets the filename of the literal packet data + * @param {String} filename Any native javascript string + */ +Literal.prototype.setFilename = function (filename) { + this.filename = filename; +}; + +/** + * Get the filename of the literal packet data + * @returns {String} filename + */ +Literal.prototype.getFilename = function () { + return this.filename; +}; + +/** + * Parsing function for a literal data packet (tag 11). + * + * @param {Uint8Array | ReadableStream} input Payload of a tag 11 packet + * @returns {module:packet.Literal} object representation + */ +Literal.prototype.read = async function (bytes) { + await _webStreamTools2.default.parse(bytes, async reader => { + // - A one-octet field that describes how the data is formatted. + const format = _enums2.default.read(_enums2.default.literal, (await reader.readByte())); + + const filename_len = await reader.readByte(); + this.filename = _util2.default.decode_utf8((await reader.readBytes(filename_len))); + + this.date = _util2.default.readDate((await reader.readBytes(4))); + + const data = reader.remainder(); + + this.setBytes(data, format); + }); +}; + +/** + * Creates a Uint8Array representation of the packet, excluding the data + * + * @returns {Uint8Array} Uint8Array representation of the packet + */ +Literal.prototype.writeHeader = function () { + const filename = _util2.default.encode_utf8(this.filename); + const filename_length = new Uint8Array([filename.length]); + + const format = new Uint8Array([_enums2.default.write(_enums2.default.literal, this.format)]); + const date = _util2.default.writeDate(this.date); + + return _util2.default.concatUint8Array([format, filename_length, filename, date]); +}; + +/** + * Creates a Uint8Array representation of the packet + * + * @returns {Uint8Array | ReadableStream} Uint8Array representation of the packet + */ +Literal.prototype.write = function () { + const header = this.writeHeader(); + const data = this.getBytes(); + + return _util2.default.concat([header, data]); +}; + +exports.default = Literal; + +},{"../enums":113,"../util":152,"web-stream-tools":75}],127:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _enums = require('../enums'); + +var _enums2 = _interopRequireDefault(_enums); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Implementation of the strange "Marker packet" (Tag 10) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.8|RFC4880 5.8}: + * An experimental version of PGP used this packet as the Literal + * packet, but no released version of PGP generated Literal packets with this + * tag. With PGP 5.x, this packet has been reassigned and is reserved for use as + * the Marker packet. + * + * Such a packet MUST be ignored when received. + * @memberof module:packet + * @constructor + */ +function Marker() { + this.tag = _enums2.default.packet.marker; +} + +/** + * Parsing function for a literal data packet (tag 10). + * + * @param {String} input Payload of a tag 10 packet + * @param {Integer} position + * Position to start reading from the input string + * @param {Integer} len + * Length of the packet or the remaining length of + * input at position + * @returns {module:packet.Marker} Object representation + */ +// GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @requires enums + */ + +Marker.prototype.read = function (bytes) { + if (bytes[0] === 0x50 && // P + bytes[1] === 0x47 && // G + bytes[2] === 0x50) { + // P + return true; + } + // marker packet does not contain "PGP" + return false; +}; + +exports.default = Marker; + +},{"../enums":113}],128:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _webStreamTools = require('web-stream-tools'); + +var _webStreamTools2 = _interopRequireDefault(_webStreamTools); + +var _signature = require('./signature'); + +var _signature2 = _interopRequireDefault(_signature); + +var _keyid = require('../type/keyid'); + +var _keyid2 = _interopRequireDefault(_keyid); + +var _enums = require('../enums'); + +var _enums2 = _interopRequireDefault(_enums); + +var _util = require('../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Implementation of the One-Pass Signature Packets (Tag 4) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.4|RFC4880 5.4}: + * The One-Pass Signature packet precedes the signed data and contains + * enough information to allow the receiver to begin calculating any + * hashes needed to verify the signature. It allows the Signature + * packet to be placed at the end of the message, so that the signer + * can compute the entire signed message in one pass. + * @memberof module:packet + * @constructor + */ +function OnePassSignature() { + /** + * Packet type + * @type {module:enums.packet} + */ + this.tag = _enums2.default.packet.onePassSignature; + /** A one-octet version number. The current version is 3. */ + this.version = null; + /** + * A one-octet signature type. + * Signature types are described in + * {@link https://tools.ietf.org/html/rfc4880#section-5.2.1|RFC4880 Section 5.2.1}. + */ + this.signatureType = null; + /** + * A one-octet number describing the hash algorithm used. + * @see {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC4880 9.4} + */ + this.hashAlgorithm = null; + /** + * A one-octet number describing the public-key algorithm used. + * @see {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC4880 9.1} + */ + this.publicKeyAlgorithm = null; + /** An eight-octet number holding the Key ID of the signing key. */ + this.issuerKeyId = null; + /** + * A one-octet number holding a flag showing whether the signature is nested. + * A zero value indicates that the next packet is another One-Pass Signature packet + * that describes another signature to be applied to the same message data. + */ + this.flags = null; +} + +/** + * parsing function for a one-pass signature packet (tag 4). + * @param {Uint8Array} bytes payload of a tag 4 packet + * @returns {module:packet.OnePassSignature} object representation + */ +// GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @requires web-stream-tools + * @requires packet/signature + * @requires type/keyid + * @requires enums + * @requires util + */ + +OnePassSignature.prototype.read = function (bytes) { + let mypos = 0; + // A one-octet version number. The current version is 3. + this.version = bytes[mypos++]; + + // A one-octet signature type. Signature types are described in + // Section 5.2.1. + this.signatureType = bytes[mypos++]; + + // A one-octet number describing the hash algorithm used. + this.hashAlgorithm = bytes[mypos++]; + + // A one-octet number describing the public-key algorithm used. + this.publicKeyAlgorithm = bytes[mypos++]; + + // An eight-octet number holding the Key ID of the signing key. + this.issuerKeyId = new _keyid2.default(); + this.issuerKeyId.read(bytes.subarray(mypos, mypos + 8)); + mypos += 8; + + // A one-octet number holding a flag showing whether the signature + // is nested. A zero value indicates that the next packet is + // another One-Pass Signature packet that describes another + // signature to be applied to the same message data. + this.flags = bytes[mypos++]; + return this; +}; + +/** + * creates a string representation of a one-pass signature packet + * @returns {Uint8Array} a Uint8Array representation of a one-pass signature packet + */ +OnePassSignature.prototype.write = function () { + const start = new Uint8Array([3, _enums2.default.write(_enums2.default.signature, this.signatureType), _enums2.default.write(_enums2.default.hash, this.hashAlgorithm), _enums2.default.write(_enums2.default.publicKey, this.publicKeyAlgorithm)]); + + const end = new Uint8Array([this.flags]); + + return _util2.default.concatUint8Array([start, this.issuerKeyId.write(), end]); +}; + +/** + * Fix custom types after cloning + */ +OnePassSignature.prototype.postCloneTypeFix = function () { + this.issuerKeyId = _keyid2.default.fromClone(this.issuerKeyId); +}; + +OnePassSignature.prototype.hash = _signature2.default.prototype.hash; +OnePassSignature.prototype.toHash = _signature2.default.prototype.toHash; +OnePassSignature.prototype.toSign = _signature2.default.prototype.toSign; +OnePassSignature.prototype.calculateTrailer = function (...args) { + return _webStreamTools2.default.fromAsync(async () => (await this.correspondingSig).calculateTrailer(...args)); +}; + +OnePassSignature.prototype.verify = async function () { + const correspondingSig = await this.correspondingSig; + if (!correspondingSig || correspondingSig.tag !== _enums2.default.packet.signature) { + throw new Error('Corresponding signature packet missing'); + } + if (correspondingSig.signatureType !== this.signatureType || correspondingSig.hashAlgorithm !== this.hashAlgorithm || correspondingSig.publicKeyAlgorithm !== this.publicKeyAlgorithm || !correspondingSig.issuerKeyId.equals(this.issuerKeyId)) { + throw new Error('Corresponding signature packet does not match one-pass signature packet'); + } + correspondingSig.hashed = this.hashed; + return correspondingSig.verify.apply(correspondingSig, arguments); +}; + +exports.default = OnePassSignature; + +},{"../enums":113,"../type/keyid":148,"../util":152,"./signature":136,"web-stream-tools":75}],129:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); // GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/* eslint-disable callback-return */ + +/** + * @fileoverview Functions for reading and writing packets + * @requires web-stream-tools + * @requires enums + * @requires util + * @module packet/packet + */ + +var _webStreamTools = require('web-stream-tools'); + +var _webStreamTools2 = _interopRequireDefault(_webStreamTools); + +var _enums = require('../enums'); + +var _enums2 = _interopRequireDefault(_enums); + +var _util = require('../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = { + readSimpleLength: function readSimpleLength(bytes) { + let len = 0; + let offset; + const type = bytes[0]; + + if (type < 192) { + var _bytes = _slicedToArray(bytes, 1); + + len = _bytes[0]; + + offset = 1; + } else if (type < 255) { + len = (bytes[0] - 192 << 8) + bytes[1] + 192; + offset = 2; + } else if (type === 255) { + len = _util2.default.readNumber(bytes.subarray(1, 1 + 4)); + offset = 5; + } + + return { + len: len, + offset: offset + }; + }, + + /** + * Encodes a given integer of length to the openpgp length specifier to a + * string + * + * @param {Integer} length The length to encode + * @returns {Uint8Array} String with openpgp length representation + */ + writeSimpleLength: function writeSimpleLength(length) { + if (length < 192) { + return new Uint8Array([length]); + } else if (length > 191 && length < 8384) { + /* + * let a = (total data packet length) - 192 let bc = two octet + * representation of a let d = b + 192 + */ + return new Uint8Array([(length - 192 >> 8) + 192, length - 192 & 0xFF]); + } + return _util2.default.concatUint8Array([new Uint8Array([255]), _util2.default.writeNumber(length, 4)]); + }, + + writePartialLength: function writePartialLength(power) { + if (power < 0 || power > 30) { + throw new Error('Partial Length power must be between 1 and 30'); + } + return new Uint8Array([224 + power]); + }, + + writeTag: function writeTag(tag_type) { + /* we're only generating v4 packet headers here */ + return new Uint8Array([0xC0 | tag_type]); + }, + + /** + * Writes a packet header version 4 with the given tag_type and length to a + * string + * + * @param {Integer} tag_type Tag type + * @param {Integer} length Length of the payload + * @returns {String} String of the header + */ + writeHeader: function writeHeader(tag_type, length) { + /* we're only generating v4 packet headers here */ + return _util2.default.concatUint8Array([this.writeTag(tag_type), this.writeSimpleLength(length)]); + }, + + /** + * Whether the packet type supports partial lengths per RFC4880 + * @param {Integer} tag_type Tag type + * @returns {Boolean} String of the header + */ + supportsStreaming: function supportsStreaming(tag_type) { + return [_enums2.default.packet.literal, _enums2.default.packet.compressed, _enums2.default.packet.symmetricallyEncrypted, _enums2.default.packet.symEncryptedIntegrityProtected, _enums2.default.packet.symEncryptedAEADProtected].includes(tag_type); + }, + + /** + * Generic static Packet Parser function + * + * @param {Uint8Array | ReadableStream} input Input stream as string + * @param {Function} callback Function to call with the parsed packet + * @returns {Boolean} Returns false if the stream was empty and parsing is done, and true otherwise. + */ + read: async function read(input, streaming, callback) { + const reader = _webStreamTools2.default.getReader(input); + let writer; + let callbackReturned; + try { + const peekedBytes = await reader.peekBytes(2); + // some sanity checks + if (!peekedBytes || peekedBytes.length < 2 || (peekedBytes[0] & 0x80) === 0) { + throw new Error("Error during parsing. This message / key probably does not conform to a valid OpenPGP format."); + } + const headerByte = await reader.readByte(); + let tag = -1; + let format = -1; + let packet_length; + + format = 0; // 0 = old format; 1 = new format + if ((headerByte & 0x40) !== 0) { + format = 1; + } + + let packet_length_type; + if (format) { + // new format header + tag = headerByte & 0x3F; // bit 5-0 + } else { + // old format header + tag = (headerByte & 0x3F) >> 2; // bit 5-2 + packet_length_type = headerByte & 0x03; // bit 1-0 + } + + const supportsStreaming = this.supportsStreaming(tag); + let packet = null; + if (streaming && supportsStreaming) { + const transform = new TransformStream(); + writer = _webStreamTools2.default.getWriter(transform.writable); + packet = transform.readable; + callbackReturned = callback({ tag, packet }); + } else { + packet = []; + } + + let wasPartialLength; + do { + if (!format) { + // 4.2.1. Old Format Packet Lengths + switch (packet_length_type) { + case 0: + // The packet has a one-octet length. The header is 2 octets + // long. + packet_length = await reader.readByte(); + break; + case 1: + // The packet has a two-octet length. The header is 3 octets + // long. + packet_length = (await reader.readByte()) << 8 | (await reader.readByte()); + break; + case 2: + // The packet has a four-octet length. The header is 5 + // octets long. + packet_length = (await reader.readByte()) << 24 | (await reader.readByte()) << 16 | (await reader.readByte()) << 8 | (await reader.readByte()); + break; + default: + // 3 - The packet is of indeterminate length. The header is 1 + // octet long, and the implementation must determine how long + // the packet is. If the packet is in a file, this means that + // the packet extends until the end of the file. In general, + // an implementation SHOULD NOT use indeterminate-length + // packets except where the end of the data will be clear + // from the context, and even then it is better to use a + // definite length, or a new format header. The new format + // headers described below have a mechanism for precisely + // encoding data of indeterminate length. + packet_length = Infinity; + break; + } + } else { + // 4.2.2. New Format Packet Lengths + // 4.2.2.1. One-Octet Lengths + const lengthByte = await reader.readByte(); + wasPartialLength = false; + if (lengthByte < 192) { + packet_length = lengthByte; + // 4.2.2.2. Two-Octet Lengths + } else if (lengthByte >= 192 && lengthByte < 224) { + packet_length = (lengthByte - 192 << 8) + (await reader.readByte()) + 192; + // 4.2.2.4. Partial Body Lengths + } else if (lengthByte > 223 && lengthByte < 255) { + packet_length = 1 << (lengthByte & 0x1F); + wasPartialLength = true; + if (!supportsStreaming) { + throw new TypeError('This packet type does not support partial lengths.'); + } + // 4.2.2.3. Five-Octet Lengths + } else { + packet_length = (await reader.readByte()) << 24 | (await reader.readByte()) << 16 | (await reader.readByte()) << 8 | (await reader.readByte()); + } + } + if (packet_length > 0) { + let bytesRead = 0; + while (true) { + if (writer) await writer.ready; + + var _ref = await reader.read(); + + const done = _ref.done, + value = _ref.value; + + if (done) { + if (packet_length === Infinity) break; + throw new Error('Unexpected end of packet'); + } + const chunk = packet_length === Infinity ? value : value.subarray(0, packet_length - bytesRead); + if (writer) await writer.write(chunk);else packet.push(chunk); + bytesRead += value.length; + if (bytesRead >= packet_length) { + reader.unshift(value.subarray(packet_length - bytesRead + value.length)); + break; + } + } + } + } while (wasPartialLength); + + // If this was not a packet that "supports streaming", we peek to check + // whether it is the last packet in the message. We peek 2 bytes instead + // of 1 because the beginning of this function also peeks 2 bytes, and we + // want to cut a `subarray` of the correct length into `web-stream-tools`' + // `externalBuffer` as a tiny optimization here. + // + // If it *was* a streaming packet (i.e. the data packets), we peek at the + // entire remainder of the stream, in order to forward errors in the + // remainder of the stream to the packet data. (Note that this means we + // read/peek at all signature packets before closing the literal data + // packet, for example.) This forwards armor checksum errors to the + // encrypted data stream, for example, so that they don't get lost / + // forgotten on encryptedMessage.packets.stream, which we never look at. + // + // Note that subsequent packet parsing errors could still end up there if + // `config.tolerant` is set to false, or on malformed messages with + // multiple data packets, but usually it shouldn't happen. + // + // An example of what we do when stream-parsing a message containing + // [ one-pass signature packet, literal data packet, signature packet ]: + // 1. Read the one-pass signature packet + // 2. Peek 2 bytes of the literal data packet + // 3. Parse the one-pass signature packet + // + // 4. Read the literal data packet, simultaneously stream-parsing it + // 5. Peek until the end of the message + // 6. Finish parsing the literal data packet + // + // 7. Read the signature packet again (we already peeked at it in step 5) + // 8. Peek at the end of the stream again (`peekBytes` returns undefined) + // 9. Parse the signature packet + // + // Note that this means that if there's an error in the very end of the + // stream, such as an MDC error, we throw in step 5 instead of in step 8 + // (or never), which is the point of this exercise. + const nextPacket = await reader.peekBytes(supportsStreaming ? Infinity : 2); + if (writer) { + await writer.ready; + await writer.close(); + } else { + packet = _util2.default.concatUint8Array(packet); + await callback({ tag, packet }); + } + return !nextPacket || !nextPacket.length; + } catch (e) { + if (writer) { + await writer.abort(e); + return true; + } else { + throw e; + } + } finally { + if (writer) { + await callbackReturned; + } + reader.releaseLock(); + } + } +}; + +},{"../enums":113,"../util":152,"web-stream-tools":75}],130:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _webStreamTools = require('web-stream-tools'); + +var _webStreamTools2 = _interopRequireDefault(_webStreamTools); + +var _all_packets = require('./all_packets'); + +var packets = _interopRequireWildcard(_all_packets); + +var _packet = require('./packet'); + +var _packet2 = _interopRequireDefault(_packet); + +var _config = require('../config'); + +var _config2 = _interopRequireDefault(_config); + +var _enums = require('../enums'); + +var _enums2 = _interopRequireDefault(_enums); + +var _util = require('../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * This class represents a list of openpgp packets. + * Take care when iterating over it - the packets themselves + * are stored as numerical indices. + * @memberof module:packet + * @constructor + * @extends Array + */ +/* eslint-disable callback-return */ +/** + * @requires web-stream-tools + * @requires packet/all_packets + * @requires packet/packet + * @requires config + * @requires enums + * @requires util + */ + +function List() { + /** + * The number of packets contained within the list. + * @readonly + * @type {Integer} + */ + this.length = 0; +} + +List.prototype = []; + +/** + * Reads a stream of binary data and interprents it as a list of packets. + * @param {Uint8Array | ReadableStream} A Uint8Array of bytes. + */ +List.prototype.read = async function (bytes, streaming) { + this.stream = _webStreamTools2.default.transformPair(bytes, async (readable, writable) => { + const writer = _webStreamTools2.default.getWriter(writable); + try { + while (true) { + await writer.ready; + const done = await _packet2.default.read(readable, streaming, async parsed => { + try { + const tag = _enums2.default.read(_enums2.default.packet, parsed.tag); + const packet = packets.newPacketFromTag(tag); + packet.packets = new List(); + packet.fromStream = _util2.default.isStream(parsed.packet); + await packet.read(parsed.packet, streaming); + await writer.write(packet); + } catch (e) { + if (!_config2.default.tolerant || _packet2.default.supportsStreaming(parsed.tag)) { + // The packets that support streaming are the ones that contain + // message data. Those are also the ones we want to be more strict + // about and throw on parse errors for. + await writer.abort(e); + } + _util2.default.print_debug_error(e); + } + }); + if (done) { + await writer.ready; + await writer.close(); + return; + } + } + } catch (e) { + await writer.abort(e); + } + }); + + // Wait until first few packets have been read + const reader = _webStreamTools2.default.getReader(this.stream); + while (true) { + var _ref = await reader.read(); + + const done = _ref.done, + value = _ref.value; + + if (!done) { + this.push(value); + } else { + this.stream = null; + } + if (done || _packet2.default.supportsStreaming(value.tag)) { + break; + } + } + reader.releaseLock(); +}; + +/** + * Creates a binary representation of openpgp objects contained within the + * class instance. + * @returns {Uint8Array} A Uint8Array containing valid openpgp packets. + */ +List.prototype.write = function () { + const arr = []; + + for (let i = 0; i < this.length; i++) { + const packetbytes = this[i].write(); + if (_util2.default.isStream(packetbytes) && _packet2.default.supportsStreaming(this[i].tag)) { + let buffer = []; + let bufferLength = 0; + const minLength = 512; + arr.push(_packet2.default.writeTag(this[i].tag)); + arr.push(_webStreamTools2.default.transform(packetbytes, value => { + buffer.push(value); + bufferLength += value.length; + if (bufferLength >= minLength) { + const powerOf2 = Math.min(Math.log(bufferLength) / Math.LN2 | 0, 30); + const chunkSize = 2 ** powerOf2; + const bufferConcat = _util2.default.concat([_packet2.default.writePartialLength(powerOf2)].concat(buffer)); + buffer = [bufferConcat.subarray(1 + chunkSize)]; + bufferLength = buffer[0].length; + return bufferConcat.subarray(0, 1 + chunkSize); + } + }, () => _util2.default.concat([_packet2.default.writeSimpleLength(bufferLength)].concat(buffer)))); + } else { + if (_util2.default.isStream(packetbytes)) { + let length = 0; + arr.push(_webStreamTools2.default.transform(_webStreamTools2.default.clone(packetbytes), value => { + length += value.length; + }, () => _packet2.default.writeHeader(this[i].tag, length))); + } else { + arr.push(_packet2.default.writeHeader(this[i].tag, packetbytes.length)); + } + arr.push(packetbytes); + } + } + + return _util2.default.concat(arr); +}; + +/** + * Adds a packet to the list. This is the only supported method of doing so; + * writing to packetlist[i] directly will result in an error. + * @param {Object} packet Packet to push + */ +List.prototype.push = function (packet) { + if (!packet) { + return; + } + + packet.packets = packet.packets || new List(); + + this[this.length] = packet; + this.length++; +}; + +/** + * Creates a new PacketList with all packets from the given types + */ +List.prototype.filterByTag = function (...args) { + const filtered = new List(); + + const handle = tag => packetType => tag === packetType; + + for (let i = 0; i < this.length; i++) { + if (args.some(handle(this[i].tag))) { + filtered.push(this[i]); + } + } + + return filtered; +}; + +/** + * Traverses packet tree and returns first matching packet + * @param {module:enums.packet} type The packet type + * @returns {module:packet/packet|undefined} + */ +List.prototype.findPacket = function (type) { + return this.find(packet => packet.tag === type); +}; + +/** + * Returns array of found indices by tag + */ +List.prototype.indexOfTag = function (...args) { + const tagIndex = []; + const that = this; + + const handle = tag => packetType => tag === packetType; + + for (let i = 0; i < this.length; i++) { + if (args.some(handle(that[i].tag))) { + tagIndex.push(i); + } + } + return tagIndex; +}; + +/** + * Concatenates packetlist or array of packets + */ +List.prototype.concat = function (packetlist) { + if (packetlist) { + for (let i = 0; i < packetlist.length; i++) { + this.push(packetlist[i]); + } + } + return this; +}; + +/** + * Allocate a new packetlist from structured packetlist clone + * See {@link https://w3c.github.io/html/infrastructure.html#safe-passing-of-structured-data} + * @param {Object} packetClone packetlist clone + * @returns {Object} new packetlist object with data from packetlist clone + */ +List.fromStructuredClone = function (packetlistClone) { + const packetlist = new List(); + for (let i = 0; i < packetlistClone.length; i++) { + const packet = packets.fromStructuredClone(packetlistClone[i]); + packetlist.push(packet); + if (packet.embeddedSignature) { + packet.embeddedSignature = packets.fromStructuredClone(packet.embeddedSignature); + } + if (packet.packets.length !== 0) { + packet.packets = this.fromStructuredClone(packet.packets); + } else { + packet.packets = new List(); + } + } + if (packetlistClone.stream) { + packetlist.stream = _webStreamTools2.default.transform(packetlistClone.stream, packet => packets.fromStructuredClone(packet)); + } + return packetlist; +}; + +exports.default = List; + +},{"../config":79,"../enums":113,"../util":152,"./all_packets":122,"./packet":129,"web-stream-tools":75}],131:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _sha = require('asmcrypto.js/dist_es5/hash/sha1/sha1'); + +var _sha2 = require('asmcrypto.js/dist_es5/hash/sha256/sha256'); + +var _keyid = require('../type/keyid'); + +var _keyid2 = _interopRequireDefault(_keyid); + +var _mpi = require('../type/mpi'); + +var _mpi2 = _interopRequireDefault(_mpi); + +var _config = require('../config'); + +var _config2 = _interopRequireDefault(_config); + +var _crypto = require('../crypto'); + +var _crypto2 = _interopRequireDefault(_crypto); + +var _enums = require('../enums'); + +var _enums2 = _interopRequireDefault(_enums); + +var _util = require('../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Implementation of the Key Material Packet (Tag 5,6,7,14) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.5|RFC4480 5.5}: + * A key material packet contains all the information about a public or + * private key. There are four variants of this packet type, and two + * major versions. + * + * A Public-Key packet starts a series of packets that forms an OpenPGP + * key (sometimes called an OpenPGP certificate). + * @memberof module:packet + * @constructor + */ +// GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @requires type/keyid + * @requires type/mpi + * @requires config + * @requires crypto + * @requires enums + * @requires util + */ + +function PublicKey(date = new Date()) { + /** + * Packet type + * @type {module:enums.packet} + */ + this.tag = _enums2.default.packet.publicKey; + /** + * Packet version + * @type {Integer} + */ + this.version = _config2.default.v5_keys ? 5 : 4; + /** + * Key creation date. + * @type {Date} + */ + this.created = _util2.default.normalizeDate(date); + /** + * Public key algorithm. + * @type {String} + */ + this.algorithm = null; + /** + * Algorithm specific params + * @type {Array} + */ + this.params = []; + /** + * Time until expiration in days (V3 only) + * @type {Integer} + */ + this.expirationTimeV3 = 0; + /** + * Fingerprint in lowercase hex + * @type {String} + */ + this.fingerprint = null; + /** + * Keyid + * @type {module:type/keyid} + */ + this.keyid = null; +} + +/** + * Internal Parser for public keys as specified in {@link https://tools.ietf.org/html/rfc4880#section-5.5.2|RFC 4880 section 5.5.2 Public-Key Packet Formats} + * called by read_tag<num> + * @param {Uint8Array} bytes Input array to read the packet from + * @returns {Object} This object with attributes set by the parser + */ +PublicKey.prototype.read = function (bytes) { + let pos = 0; + // A one-octet version number (3, 4 or 5). + this.version = bytes[pos++]; + + if (this.version === 4 || this.version === 5) { + // - A four-octet number denoting the time that the key was created. + this.created = _util2.default.readDate(bytes.subarray(pos, pos + 4)); + pos += 4; + + // - A one-octet number denoting the public-key algorithm of this key. + this.algorithm = _enums2.default.read(_enums2.default.publicKey, bytes[pos++]); + const algo = _enums2.default.write(_enums2.default.publicKey, this.algorithm); + + if (this.version === 5) { + // - A four-octet scalar octet count for the following key material. + pos += 4; + } + + // - A series of values comprising the key material. This is + // algorithm-specific and described in section XXXX. + const types = _crypto2.default.getPubKeyParamTypes(algo); + this.params = _crypto2.default.constructParams(types); + + for (let i = 0; i < types.length && pos < bytes.length; i++) { + pos += this.params[i].read(bytes.subarray(pos, bytes.length)); + if (pos > bytes.length) { + throw new Error('Error reading MPI @:' + pos); + } + } + + return pos; + } + throw new Error('Version ' + this.version + ' of the key packet is unsupported.'); +}; + +/** + * Alias of read() + * @see module:packet.PublicKey#read + */ +PublicKey.prototype.readPublicKey = PublicKey.prototype.read; + +/** + * Same as write_private_key, but has less information because of + * public key. + * @returns {Uint8Array} OpenPGP packet body contents, + */ +PublicKey.prototype.write = function () { + const arr = []; + // Version + arr.push(new Uint8Array([this.version])); + arr.push(_util2.default.writeDate(this.created)); + // A one-octet number denoting the public-key algorithm of this key + const algo = _enums2.default.write(_enums2.default.publicKey, this.algorithm); + arr.push(new Uint8Array([algo])); + + const paramCount = _crypto2.default.getPubKeyParamTypes(algo).length; + const params = _util2.default.concatUint8Array(this.params.slice(0, paramCount).map(param => param.write())); + if (this.version === 5) { + // A four-octet scalar octet count for the following key material + arr.push(_util2.default.writeNumber(params.length, 4)); + } + // Algorithm-specific params + arr.push(params); + return _util2.default.concatUint8Array(arr); +}; + +/** + * Alias of write() + * @see module:packet.PublicKey#write + */ +PublicKey.prototype.writePublicKey = PublicKey.prototype.write; + +/** + * Write packet in order to be hashed; either for a signature or a fingerprint. + */ +PublicKey.prototype.writeForHash = function (version) { + const bytes = this.writePublicKey(); + + if (version === 5) { + return _util2.default.concatUint8Array([new Uint8Array([0x9A]), _util2.default.writeNumber(bytes.length, 4), bytes]); + } + return _util2.default.concatUint8Array([new Uint8Array([0x99]), _util2.default.writeNumber(bytes.length, 2), bytes]); +}; + +/** + * Check whether secret-key data is available in decrypted form. Returns null for public keys. + * @returns {Boolean|null} + */ +PublicKey.prototype.isDecrypted = function () { + return null; +}; + +/** + * Returns the creation time of the key + * @returns {Date} + */ +PublicKey.prototype.getCreationTime = function () { + return this.created; +}; + +/** + * Calculates the key id of the key + * @returns {String} A 8 byte key id + */ +PublicKey.prototype.getKeyId = function () { + if (this.keyid) { + return this.keyid; + } + this.keyid = new _keyid2.default(); + if (this.version === 5) { + this.keyid.read(_util2.default.hex_to_Uint8Array(this.getFingerprint()).subarray(0, 8)); + } else if (this.version === 4) { + this.keyid.read(_util2.default.hex_to_Uint8Array(this.getFingerprint()).subarray(12, 20)); + } + return this.keyid; +}; + +/** + * Calculates the fingerprint of the key + * @returns {Uint8Array} A Uint8Array containing the fingerprint + */ +PublicKey.prototype.getFingerprintBytes = function () { + if (this.fingerprint) { + return this.fingerprint; + } + const toHash = this.writeForHash(this.version); + if (this.version === 5) { + this.fingerprint = _sha2.Sha256.bytes(toHash); + } else if (this.version === 4) { + this.fingerprint = _sha.Sha1.bytes(toHash); + } + return this.fingerprint; +}; + +/** + * Calculates the fingerprint of the key + * @returns {String} A string containing the fingerprint in lowercase hex + */ +PublicKey.prototype.getFingerprint = function () { + return _util2.default.Uint8Array_to_hex(this.getFingerprintBytes()); +}; + +/** + * Calculates whether two keys have the same fingerprint without actually calculating the fingerprint + * @returns {Boolean} Whether the two keys have the same version and public key data + */ +PublicKey.prototype.hasSameFingerprintAs = function (other) { + return this.version === other.version && _util2.default.equalsUint8Array(this.writePublicKey(), other.writePublicKey()); +}; + +/** + * Returns algorithm information + * @returns {Object} An object of the form {algorithm: String, bits:int, curve:String} + */ +PublicKey.prototype.getAlgorithmInfo = function () { + const result = {}; + result.algorithm = this.algorithm; + if (this.params[0] instanceof _mpi2.default) { + result.bits = this.params[0].byteLength() * 8; + } else { + result.curve = this.params[0].getName(); + } + return result; +}; + +/** + * Fix custom types after cloning + */ +PublicKey.prototype.postCloneTypeFix = function () { + const algo = _enums2.default.write(_enums2.default.publicKey, this.algorithm); + const types = _crypto2.default.getPubKeyParamTypes(algo); + for (let i = 0; i < types.length; i++) { + const param = this.params[i]; + this.params[i] = types[i].fromClone(param); + } + if (this.keyid) { + this.keyid = _keyid2.default.fromClone(this.keyid); + } +}; + +exports.default = PublicKey; + +},{"../config":79,"../crypto":94,"../enums":113,"../type/keyid":148,"../type/mpi":149,"../util":152,"asmcrypto.js/dist_es5/hash/sha1/sha1":11,"asmcrypto.js/dist_es5/hash/sha256/sha256":13}],132:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _keyid = require('../type/keyid'); + +var _keyid2 = _interopRequireDefault(_keyid); + +var _mpi = require('../type/mpi'); + +var _mpi2 = _interopRequireDefault(_mpi); + +var _crypto = require('../crypto'); + +var _crypto2 = _interopRequireDefault(_crypto); + +var _enums = require('../enums'); + +var _enums2 = _interopRequireDefault(_enums); + +var _util = require('../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Public-Key Encrypted Session Key Packets (Tag 1) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.1|RFC4880 5.1}: + * A Public-Key Encrypted Session Key packet holds the session key + * used to encrypt a message. Zero or more Public-Key Encrypted Session Key + * packets and/or Symmetric-Key Encrypted Session Key packets may precede a + * Symmetrically Encrypted Data Packet, which holds an encrypted message. The + * message is encrypted with the session key, and the session key is itself + * encrypted and stored in the Encrypted Session Key packet(s). The + * Symmetrically Encrypted Data Packet is preceded by one Public-Key Encrypted + * Session Key packet for each OpenPGP key to which the message is encrypted. + * The recipient of the message finds a session key that is encrypted to their + * public key, decrypts the session key, and then uses the session key to + * decrypt the message. + * @memberof module:packet + * @constructor + */ +function PublicKeyEncryptedSessionKey() { + this.tag = _enums2.default.packet.publicKeyEncryptedSessionKey; + this.version = 3; + + this.publicKeyId = new _keyid2.default(); + this.publicKeyAlgorithm = null; + + this.sessionKey = null; + this.sessionKeyAlgorithm = null; + + /** @type {Array} */ + this.encrypted = []; +} + +/** + * Parsing function for a publickey encrypted session key packet (tag 1). + * + * @param {Uint8Array} input Payload of a tag 1 packet + * @param {Integer} position Position to start reading from the input string + * @param {Integer} len Length of the packet or the remaining length of + * input at position + * @returns {module:packet.PublicKeyEncryptedSessionKey} Object representation + */ +// GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @requires type/keyid + * @requires type/mpi + * @requires crypto + * @requires enums + * @requires util + */ + +PublicKeyEncryptedSessionKey.prototype.read = function (bytes) { + this.version = bytes[0]; + this.publicKeyId.read(bytes.subarray(1, bytes.length)); + this.publicKeyAlgorithm = _enums2.default.read(_enums2.default.publicKey, bytes[9]); + + let i = 10; + + const algo = _enums2.default.write(_enums2.default.publicKey, this.publicKeyAlgorithm); + const types = _crypto2.default.getEncSessionKeyParamTypes(algo); + this.encrypted = _crypto2.default.constructParams(types); + + for (let j = 0; j < types.length; j++) { + i += this.encrypted[j].read(bytes.subarray(i, bytes.length)); + } +}; + +/** + * Create a string representation of a tag 1 packet + * + * @returns {Uint8Array} The Uint8Array representation + */ +PublicKeyEncryptedSessionKey.prototype.write = function () { + const arr = [new Uint8Array([this.version]), this.publicKeyId.write(), new Uint8Array([_enums2.default.write(_enums2.default.publicKey, this.publicKeyAlgorithm)])]; + + for (let i = 0; i < this.encrypted.length; i++) { + arr.push(this.encrypted[i].write()); + } + + return _util2.default.concatUint8Array(arr); +}; + +/** + * Encrypt session key packet + * @param {module:packet.PublicKey} key Public key + * @returns {Promise} + * @async + */ +PublicKeyEncryptedSessionKey.prototype.encrypt = async function (key) { + let data = String.fromCharCode(_enums2.default.write(_enums2.default.symmetric, this.sessionKeyAlgorithm)); + + data += _util2.default.Uint8Array_to_str(this.sessionKey); + data += _util2.default.Uint8Array_to_str(_util2.default.write_checksum(this.sessionKey)); + + let toEncrypt; + const algo = _enums2.default.write(_enums2.default.publicKey, this.publicKeyAlgorithm); + if (algo === _enums2.default.publicKey.ecdh) { + toEncrypt = new _mpi2.default(_crypto2.default.pkcs5.encode(data)); + } else { + toEncrypt = new _mpi2.default((await _crypto2.default.pkcs1.eme.encode(data, key.params[0].byteLength()))); + } + + this.encrypted = await _crypto2.default.publicKeyEncrypt(algo, key.params, toEncrypt, key.getFingerprintBytes()); + return true; +}; + +/** + * Decrypts the session key (only for public key encrypted session key + * packets (tag 1) + * + * @param {module:packet.SecretKey} key + * Private key with secret params unlocked + * @returns {Promise} + * @async + */ +PublicKeyEncryptedSessionKey.prototype.decrypt = async function (key) { + const algo = _enums2.default.write(_enums2.default.publicKey, this.publicKeyAlgorithm); + const result = new _mpi2.default((await _crypto2.default.publicKeyDecrypt(algo, key.params, this.encrypted, key.getFingerprintBytes()))); + + let checksum; + let decoded; + if (algo === _enums2.default.publicKey.ecdh) { + decoded = _crypto2.default.pkcs5.decode(result.toString()); + checksum = _util2.default.str_to_Uint8Array(decoded.substr(decoded.length - 2)); + } else { + decoded = _crypto2.default.pkcs1.eme.decode(result.toString()); + checksum = result.toUint8Array().slice(result.byteLength() - 2); + } + + key = _util2.default.str_to_Uint8Array(decoded.substring(1, decoded.length - 2)); + + if (!_util2.default.equalsUint8Array(checksum, _util2.default.write_checksum(key))) { + throw new Error('Decryption error'); + } else { + this.sessionKey = key; + this.sessionKeyAlgorithm = _enums2.default.read(_enums2.default.symmetric, decoded.charCodeAt(0)); + } + return true; +}; + +/** + * Fix custom types after cloning + */ +PublicKeyEncryptedSessionKey.prototype.postCloneTypeFix = function () { + this.publicKeyId = _keyid2.default.fromClone(this.publicKeyId); + const algo = _enums2.default.write(_enums2.default.publicKey, this.publicKeyAlgorithm); + const types = _crypto2.default.getEncSessionKeyParamTypes(algo); + for (let i = 0; i < this.encrypted.length; i++) { + this.encrypted[i] = types[i].fromClone(this.encrypted[i]); + } +}; + +exports.default = PublicKeyEncryptedSessionKey; + +},{"../crypto":94,"../enums":113,"../type/keyid":148,"../type/mpi":149,"../util":152}],133:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _public_key = require('./public_key'); + +var _public_key2 = _interopRequireDefault(_public_key); + +var _enums = require('../enums'); + +var _enums2 = _interopRequireDefault(_enums); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * A Public-Subkey packet (tag 14) has exactly the same format as a + * Public-Key packet, but denotes a subkey. One or more subkeys may be + * associated with a top-level key. By convention, the top-level key + * provides signature services, and the subkeys provide encryption + * services. + * @memberof module:packet + * @constructor + * @extends module:packet.PublicKey + */ +// GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @requires packet/public_key + * @requires enums + */ + +function PublicSubkey() { + _public_key2.default.call(this); + this.tag = _enums2.default.packet.publicSubkey; +} + +PublicSubkey.prototype = new _public_key2.default(); +PublicSubkey.prototype.constructor = PublicSubkey; + +exports.default = PublicSubkey; + +},{"../enums":113,"./public_key":131}],134:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _public_key = require('./public_key'); + +var _public_key2 = _interopRequireDefault(_public_key); + +var _keyid = require('../type/keyid.js'); + +var _keyid2 = _interopRequireDefault(_keyid); + +var _s2k = require('../type/s2k'); + +var _s2k2 = _interopRequireDefault(_s2k); + +var _crypto = require('../crypto'); + +var _crypto2 = _interopRequireDefault(_crypto); + +var _enums = require('../enums'); + +var _enums2 = _interopRequireDefault(_enums); + +var _util = require('../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * A Secret-Key packet contains all the information that is found in a + * Public-Key packet, including the public-key material, but also + * includes the secret-key material after all the public-key fields. + * @memberof module:packet + * @constructor + * @extends module:packet.PublicKey + */ +// GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @requires packet/public_key + * @requires type/keyid + * @requires type/s2k + * @requires crypto + * @requires enums + * @requires util + */ + +function SecretKey(date = new Date()) { + _public_key2.default.call(this, date); + /** + * Packet type + * @type {module:enums.packet} + */ + this.tag = _enums2.default.packet.secretKey; + /** + * Secret-key data + */ + this.keyMaterial = null; + /** + * Indicates whether secret-key data is encrypted. `this.isEncrypted === false` means data is available in decrypted form. + */ + this.isEncrypted = null; + /** + * S2K usage + * @type {Integer} + */ + this.s2k_usage = 0; + /** + * S2K object + * @type {type/s2k} + */ + this.s2k = null; + /** + * Symmetric algorithm + * @type {String} + */ + this.symmetric = 'aes256'; + /** + * AEAD algorithm + * @type {String} + */ + this.aead = 'eax'; +} + +SecretKey.prototype = new _public_key2.default(); +SecretKey.prototype.constructor = SecretKey; + +// Helper function + +function parse_cleartext_params(cleartext, algorithm) { + const algo = _enums2.default.write(_enums2.default.publicKey, algorithm); + const types = _crypto2.default.getPrivKeyParamTypes(algo); + const params = _crypto2.default.constructParams(types); + let p = 0; + + for (let i = 0; i < types.length && p < cleartext.length; i++) { + p += params[i].read(cleartext.subarray(p, cleartext.length)); + if (p > cleartext.length) { + throw new Error('Error reading param @:' + p); + } + } + + return params; +} + +function write_cleartext_params(params, algorithm) { + const arr = []; + const algo = _enums2.default.write(_enums2.default.publicKey, algorithm); + const numPublicParams = _crypto2.default.getPubKeyParamTypes(algo).length; + + for (let i = numPublicParams; i < params.length; i++) { + arr.push(params[i].write()); + } + + return _util2.default.concatUint8Array(arr); +} + +// 5.5.3. Secret-Key Packet Formats + +/** + * Internal parser for private keys as specified in + * {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.5.3|RFC4880bis-04 section 5.5.3} + * @param {String} bytes Input string to read the packet from + */ +SecretKey.prototype.read = function (bytes) { + // - A Public-Key or Public-Subkey packet, as described above. + let i = this.readPublicKey(bytes); + + // - One octet indicating string-to-key usage conventions. Zero + // indicates that the secret-key data is not encrypted. 255 or 254 + // indicates that a string-to-key specifier is being given. Any + // other value is a symmetric-key encryption algorithm identifier. + this.s2k_usage = bytes[i++]; + + // - Only for a version 5 packet, a one-octet scalar octet count of + // the next 4 optional fields. + if (this.version === 5) { + i++; + } + + // - [Optional] If string-to-key usage octet was 255, 254, or 253, a + // one-octet symmetric encryption algorithm. + if (this.s2k_usage === 255 || this.s2k_usage === 254 || this.s2k_usage === 253) { + this.symmetric = bytes[i++]; + this.symmetric = _enums2.default.read(_enums2.default.symmetric, this.symmetric); + + // - [Optional] If string-to-key usage octet was 253, a one-octet + // AEAD algorithm. + if (this.s2k_usage === 253) { + this.aead = bytes[i++]; + this.aead = _enums2.default.read(_enums2.default.aead, this.aead); + } + + // - [Optional] If string-to-key usage octet was 255, 254, or 253, a + // string-to-key specifier. The length of the string-to-key + // specifier is implied by its type, as described above. + this.s2k = new _s2k2.default(); + i += this.s2k.read(bytes.subarray(i, bytes.length)); + + if (this.s2k.type === 'gnu-dummy') { + return; + } + } else if (this.s2k_usage) { + this.symmetric = this.s2k_usage; + this.symmetric = _enums2.default.read(_enums2.default.symmetric, this.symmetric); + } + + // - [Optional] If secret data is encrypted (string-to-key usage octet + // not zero), an Initial Vector (IV) of the same length as the + // cipher's block size. + if (this.s2k_usage) { + this.iv = bytes.subarray(i, i + _crypto2.default.cipher[this.symmetric].blockSize); + + i += this.iv.length; + } + + // - Only for a version 5 packet, a four-octet scalar octet count for + // the following key material. + if (this.version === 5) { + i += 4; + } + + // - Plain or encrypted multiprecision integers comprising the secret + // key data. These algorithm-specific fields are as described + // below. + this.keyMaterial = bytes.subarray(i); + this.isEncrypted = !!this.s2k_usage; + + if (!this.isEncrypted) { + const cleartext = this.keyMaterial.subarray(0, -2); + if (!_util2.default.equalsUint8Array(_util2.default.write_checksum(cleartext), this.keyMaterial.subarray(-2))) { + throw new Error('Key checksum mismatch'); + } + const privParams = parse_cleartext_params(cleartext, this.algorithm); + this.params = this.params.concat(privParams); + } +}; + +/** + * Creates an OpenPGP key packet for the given key. + * @returns {String} A string of bytes containing the secret key OpenPGP packet + */ +SecretKey.prototype.write = function () { + const arr = [this.writePublicKey()]; + + arr.push(new Uint8Array([this.s2k_usage])); + + const optionalFieldsArr = []; + // - [Optional] If string-to-key usage octet was 255, 254, or 253, a + // one- octet symmetric encryption algorithm. + if (this.s2k_usage === 255 || this.s2k_usage === 254 || this.s2k_usage === 253) { + optionalFieldsArr.push(_enums2.default.write(_enums2.default.symmetric, this.symmetric)); + + // - [Optional] If string-to-key usage octet was 253, a one-octet + // AEAD algorithm. + if (this.s2k_usage === 253) { + optionalFieldsArr.push(_enums2.default.write(_enums2.default.aead, this.aead)); + } + + // - [Optional] If string-to-key usage octet was 255, 254, or 253, a + // string-to-key specifier. The length of the string-to-key + // specifier is implied by its type, as described above. + optionalFieldsArr.push(...this.s2k.write()); + } + + // - [Optional] If secret data is encrypted (string-to-key usage octet + // not zero), an Initial Vector (IV) of the same length as the + // cipher's block size. + if (this.s2k_usage && this.s2k.type !== 'gnu-dummy') { + optionalFieldsArr.push(...this.iv); + } + + if (this.version === 5) { + arr.push(new Uint8Array([optionalFieldsArr.length])); + } + arr.push(new Uint8Array(optionalFieldsArr)); + + if (!this.s2k || this.s2k.type !== 'gnu-dummy') { + if (!this.s2k_usage) { + const cleartextParams = write_cleartext_params(this.params, this.algorithm); + this.keyMaterial = _util2.default.concatUint8Array([cleartextParams, _util2.default.write_checksum(cleartextParams)]); + } + + if (this.version === 5) { + arr.push(_util2.default.writeNumber(this.keyMaterial.length, 4)); + } + arr.push(this.keyMaterial); + } + + return _util2.default.concatUint8Array(arr); +}; + +/** + * Check whether secret-key data is available in decrypted form. Returns null for public keys. + * @returns {Boolean|null} + */ +SecretKey.prototype.isDecrypted = function () { + return this.isEncrypted === false; +}; + +/** + * Encrypt the payload. By default, we use aes256 and iterated, salted string + * to key specifier. If the key is in a decrypted state (isEncrypted === false) + * and the passphrase is empty or undefined, the key will be set as not encrypted. + * This can be used to remove passphrase protection after calling decrypt(). + * @param {String} passphrase + * @returns {Promise} + * @async + */ +SecretKey.prototype.encrypt = async function (passphrase) { + if (this.s2k && this.s2k.type === 'gnu-dummy') { + return false; + } + + if (this.isDecrypted() && !passphrase) { + this.s2k_usage = 0; + return false; + } else if (!passphrase) { + throw new Error('The key must be decrypted before removing passphrase protection.'); + } + + this.s2k = new _s2k2.default(); + this.s2k.salt = await _crypto2.default.random.getRandomBytes(8); + const cleartext = write_cleartext_params(this.params, this.algorithm); + const key = await produceEncryptionKey(this.s2k, passphrase, this.symmetric); + const blockLen = _crypto2.default.cipher[this.symmetric].blockSize; + this.iv = await _crypto2.default.random.getRandomBytes(blockLen); + + if (this.version === 5) { + this.s2k_usage = 253; + const mode = _crypto2.default[this.aead]; + const modeInstance = await mode(this.symmetric, key); + this.keyMaterial = await modeInstance.encrypt(cleartext, this.iv.subarray(0, mode.ivLength), new Uint8Array()); + } else { + this.s2k_usage = 254; + this.keyMaterial = _crypto2.default.cfb.encrypt(this.symmetric, key, _util2.default.concatUint8Array([cleartext, await _crypto2.default.hash.sha1(cleartext)]), this.iv); + } + return true; +}; + +async function produceEncryptionKey(s2k, passphrase, algorithm) { + return s2k.produce_key(passphrase, _crypto2.default.cipher[algorithm].keySize); +} + +/** + * Decrypts the private key params which are needed to use the key. + * {@link module:packet.SecretKey.isDecrypted} should be false, as + * otherwise calls to this function will throw an error. + * @param {String} passphrase The passphrase for this private key as string + * @returns {Promise} + * @async + */ +SecretKey.prototype.decrypt = async function (passphrase) { + if (this.s2k.type === 'gnu-dummy') { + this.isEncrypted = false; + return false; + } + + if (this.isDecrypted()) { + throw new Error('Key packet is already decrypted.'); + } + + let key; + if (this.s2k_usage === 255 || this.s2k_usage === 254 || this.s2k_usage === 253) { + key = await produceEncryptionKey(this.s2k, passphrase, this.symmetric); + } else { + key = await _crypto2.default.hash.md5(passphrase); + } + + let cleartext; + if (this.s2k_usage === 253) { + const mode = _crypto2.default[this.aead]; + try { + const modeInstance = await mode(this.symmetric, key); + cleartext = await modeInstance.decrypt(this.keyMaterial, this.iv.subarray(0, mode.ivLength), new Uint8Array()); + } catch (err) { + if (err.message === 'Authentication tag mismatch') { + throw new Error('Incorrect key passphrase: ' + err.message); + } + throw err; + } + } else { + const cleartextWithHash = await _crypto2.default.cfb.decrypt(this.symmetric, key, this.keyMaterial, this.iv); + + let hash; + let hashlen; + if (this.s2k_usage === 255) { + hashlen = 2; + cleartext = cleartextWithHash.subarray(0, -hashlen); + hash = _util2.default.write_checksum(cleartext); + } else { + hashlen = 20; + cleartext = cleartextWithHash.subarray(0, -hashlen); + hash = await _crypto2.default.hash.sha1(cleartext); + } + + if (!_util2.default.equalsUint8Array(hash, cleartextWithHash.subarray(-hashlen))) { + throw new Error('Incorrect key passphrase'); + } + } + + const privParams = parse_cleartext_params(cleartext, this.algorithm); + this.params = this.params.concat(privParams); + this.isEncrypted = false; + this.keyMaterial = null; + this.s2k_usage = 0; + + return true; +}; + +SecretKey.prototype.generate = async function (bits, curve) { + const algo = _enums2.default.write(_enums2.default.publicKey, this.algorithm); + this.params = await _crypto2.default.generateParams(algo, bits, curve); + this.isEncrypted = false; +}; + +/** + * Clear private params, return to initial state + */ +SecretKey.prototype.clearPrivateParams = function () { + if (this.s2k && this.s2k.type === 'gnu-dummy') { + this.isEncrypted = true; + return; + } + + if (!this.keyMaterial) { + throw new Error('If secret key is not encrypted, clearing private params is irreversible.'); + } + const algo = _enums2.default.write(_enums2.default.publicKey, this.algorithm); + this.params = this.params.slice(0, _crypto2.default.getPubKeyParamTypes(algo).length); + this.isEncrypted = true; +}; + +/** + * Fix custom types after cloning + */ +SecretKey.prototype.postCloneTypeFix = function () { + const algo = _enums2.default.write(_enums2.default.publicKey, this.algorithm); + const types = [].concat(_crypto2.default.getPubKeyParamTypes(algo), _crypto2.default.getPrivKeyParamTypes(algo)); + for (let i = 0; i < this.params.length; i++) { + const param = this.params[i]; + this.params[i] = types[i].fromClone(param); + } + if (this.keyid) { + this.keyid = _keyid2.default.fromClone(this.keyid); + } +}; + +exports.default = SecretKey; + +},{"../crypto":94,"../enums":113,"../type/keyid.js":148,"../type/s2k":151,"../util":152,"./public_key":131}],135:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _secret_key = require('./secret_key'); + +var _secret_key2 = _interopRequireDefault(_secret_key); + +var _enums = require('../enums'); + +var _enums2 = _interopRequireDefault(_enums); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * A Secret-Subkey packet (tag 7) is the subkey analog of the Secret + * Key packet and has exactly the same format. + * @memberof module:packet + * @constructor + * @extends module:packet.SecretKey + */ +// GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @requires packet/secret_key + * @requires enums + */ + +function SecretSubkey(date = new Date()) { + _secret_key2.default.call(this, date); + this.tag = _enums2.default.packet.secretSubkey; +} + +SecretSubkey.prototype = new _secret_key2.default(); +SecretSubkey.prototype.constructor = SecretSubkey; + +exports.default = SecretSubkey; + +},{"../enums":113,"./secret_key":134}],136:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _webStreamTools = require('web-stream-tools'); + +var _webStreamTools2 = _interopRequireDefault(_webStreamTools); + +var _packet = require('./packet'); + +var _packet2 = _interopRequireDefault(_packet); + +var _keyid = require('../type/keyid.js'); + +var _keyid2 = _interopRequireDefault(_keyid); + +var _mpi = require('../type/mpi.js'); + +var _mpi2 = _interopRequireDefault(_mpi); + +var _crypto = require('../crypto'); + +var _crypto2 = _interopRequireDefault(_crypto); + +var _enums = require('../enums'); + +var _enums2 = _interopRequireDefault(_enums); + +var _util = require('../util'); + +var _util2 = _interopRequireDefault(_util); + +var _config = require('../config'); + +var _config2 = _interopRequireDefault(_config); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Implementation of the Signature Packet (Tag 2) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.2|RFC4480 5.2}: + * A Signature packet describes a binding between some public key and + * some data. The most common signatures are a signature of a file or a + * block of text, and a signature that is a certification of a User ID. + * @memberof module:packet + * @constructor + * @param {Date} date the creation date of the signature + */ +// GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @requires web-stream-tools + * @requires packet/packet + * @requires type/keyid + * @requires type/mpi + * @requires crypto + * @requires enums + * @requires util + */ + +function Signature(date = new Date()) { + this.tag = _enums2.default.packet.signature; + this.version = 4; // This is set to 5 below if we sign with a V5 key. + this.signatureType = null; + this.hashAlgorithm = null; + this.publicKeyAlgorithm = null; + + this.signatureData = null; + this.unhashedSubpackets = []; + this.signedHashValue = null; + + this.created = _util2.default.normalizeDate(date); + this.signatureExpirationTime = null; + this.signatureNeverExpires = true; + this.exportable = null; + this.trustLevel = null; + this.trustAmount = null; + this.regularExpression = null; + this.revocable = null; + this.keyExpirationTime = null; + this.keyNeverExpires = null; + this.preferredSymmetricAlgorithms = null; + this.revocationKeyClass = null; + this.revocationKeyAlgorithm = null; + this.revocationKeyFingerprint = null; + this.issuerKeyId = new _keyid2.default(); + this.notations = []; + this.preferredHashAlgorithms = null; + this.preferredCompressionAlgorithms = null; + this.keyServerPreferences = null; + this.preferredKeyServer = null; + this.isPrimaryUserID = null; + this.policyURI = null; + this.keyFlags = null; + this.signersUserId = null; + this.reasonForRevocationFlag = null; + this.reasonForRevocationString = null; + this.features = null; + this.signatureTargetPublicKeyAlgorithm = null; + this.signatureTargetHashAlgorithm = null; + this.signatureTargetHash = null; + this.embeddedSignature = null; + this.issuerKeyVersion = null; + this.issuerFingerprint = null; + this.preferredAeadAlgorithms = null; + + this.verified = null; + this.revoked = null; +} + +/** + * parsing function for a signature packet (tag 2). + * @param {String} bytes payload of a tag 2 packet + * @param {Integer} position position to start reading from the bytes string + * @param {Integer} len length of the packet or the remaining length of bytes at position + * @returns {module:packet.Signature} object representation + */ +Signature.prototype.read = function (bytes) { + let i = 0; + this.version = bytes[i++]; + + if (this.version !== 4 && this.version !== 5) { + throw new Error('Version ' + this.version + ' of the signature is unsupported.'); + } + + this.signatureType = bytes[i++]; + this.publicKeyAlgorithm = bytes[i++]; + this.hashAlgorithm = bytes[i++]; + + // hashed subpackets + i += this.read_sub_packets(bytes.subarray(i, bytes.length), true); + + // A V4 signature hashes the packet body + // starting from its first field, the version number, through the end + // of the hashed subpacket data. Thus, the fields hashed are the + // signature version, the signature type, the public-key algorithm, the + // hash algorithm, the hashed subpacket length, and the hashed + // subpacket body. + this.signatureData = bytes.subarray(0, i); + + // unhashed subpackets + i += this.read_sub_packets(bytes.subarray(i, bytes.length), false); + + // Two-octet field holding left 16 bits of signed hash value. + this.signedHashValue = bytes.subarray(i, i + 2); + i += 2; + + this.signature = bytes.subarray(i, bytes.length); +}; + +Signature.prototype.write = function () { + const arr = []; + arr.push(this.signatureData); + arr.push(this.write_unhashed_sub_packets()); + arr.push(this.signedHashValue); + arr.push(_webStreamTools2.default.clone(this.signature)); + return _util2.default.concat(arr); +}; + +/** + * Signs provided data. This needs to be done prior to serialization. + * @param {module:packet.SecretKey} key private key used to sign the message. + * @param {Object} data Contains packets to be signed. + * @param {Boolean} detached (optional) whether to create a detached signature + * @returns {Promise} + * @async + */ +Signature.prototype.sign = async function (key, data, detached = false) { + const signatureType = _enums2.default.write(_enums2.default.signature, this.signatureType); + const publicKeyAlgorithm = _enums2.default.write(_enums2.default.publicKey, this.publicKeyAlgorithm); + const hashAlgorithm = _enums2.default.write(_enums2.default.hash, this.hashAlgorithm); + + if (key.version === 5) { + this.version = 5; + } + const arr = [new Uint8Array([this.version, signatureType, publicKeyAlgorithm, hashAlgorithm])]; + + if (key.version === 5) { + // We could also generate this subpacket for version 4 keys, but for + // now we don't. + this.issuerKeyVersion = key.version; + this.issuerFingerprint = key.getFingerprintBytes(); + } + + this.issuerKeyId = key.getKeyId(); + + // Add hashed subpackets + arr.push(this.write_hashed_sub_packets()); + + this.signatureData = _util2.default.concat(arr); + + const toHash = this.toHash(signatureType, data, detached); + const hash = await this.hash(signatureType, data, toHash, detached); + + this.signedHashValue = _webStreamTools2.default.slice(_webStreamTools2.default.clone(hash), 0, 2); + + const params = key.params; + this.signature = _webStreamTools2.default.fromAsync(async () => _crypto2.default.signature.sign(publicKeyAlgorithm, hashAlgorithm, params, toHash, (await _webStreamTools2.default.readToEnd(hash)))); + + // Store the fact that this signature is valid, e.g. for when we call `await + // getLatestValidSignature(this.revocationSignatures, key, data)` later. Note + // that this only holds up if the key and data passed to verify are the same + // as the ones passed to sign. + this.verified = true; + return true; +}; + +/** + * Creates Uint8Array of bytes of all subpacket data except Issuer and Embedded Signature subpackets + * @returns {Uint8Array} subpacket data + */ +Signature.prototype.write_hashed_sub_packets = function () { + const sub = _enums2.default.signatureSubpacket; + const arr = []; + let bytes; + if (this.created !== null) { + arr.push(write_sub_packet(sub.signature_creation_time, _util2.default.writeDate(this.created))); + } + if (this.signatureExpirationTime !== null) { + arr.push(write_sub_packet(sub.signature_expiration_time, _util2.default.writeNumber(this.signatureExpirationTime, 4))); + } + if (this.exportable !== null) { + arr.push(write_sub_packet(sub.exportable_certification, new Uint8Array([this.exportable ? 1 : 0]))); + } + if (this.trustLevel !== null) { + bytes = new Uint8Array([this.trustLevel, this.trustAmount]); + arr.push(write_sub_packet(sub.trust_signature, bytes)); + } + if (this.regularExpression !== null) { + arr.push(write_sub_packet(sub.regular_expression, this.regularExpression)); + } + if (this.revocable !== null) { + arr.push(write_sub_packet(sub.revocable, new Uint8Array([this.revocable ? 1 : 0]))); + } + if (this.keyExpirationTime !== null) { + arr.push(write_sub_packet(sub.key_expiration_time, _util2.default.writeNumber(this.keyExpirationTime, 4))); + } + if (this.preferredSymmetricAlgorithms !== null) { + bytes = _util2.default.str_to_Uint8Array(_util2.default.Uint8Array_to_str(this.preferredSymmetricAlgorithms)); + arr.push(write_sub_packet(sub.preferred_symmetric_algorithms, bytes)); + } + if (this.revocationKeyClass !== null) { + bytes = new Uint8Array([this.revocationKeyClass, this.revocationKeyAlgorithm]); + bytes = _util2.default.concat([bytes, this.revocationKeyFingerprint]); + arr.push(write_sub_packet(sub.revocation_key, bytes)); + } + this.notations.forEach(([name, value]) => { + bytes = [new Uint8Array([0x80, 0, 0, 0])]; + // 2 octets of name length + bytes.push(_util2.default.writeNumber(name.length, 2)); + // 2 octets of value length + bytes.push(_util2.default.writeNumber(value.length, 2)); + bytes.push(_util2.default.str_to_Uint8Array(name + value)); + bytes = _util2.default.concat(bytes); + arr.push(write_sub_packet(sub.notation_data, bytes)); + }); + if (this.preferredHashAlgorithms !== null) { + bytes = _util2.default.str_to_Uint8Array(_util2.default.Uint8Array_to_str(this.preferredHashAlgorithms)); + arr.push(write_sub_packet(sub.preferred_hash_algorithms, bytes)); + } + if (this.preferredCompressionAlgorithms !== null) { + bytes = _util2.default.str_to_Uint8Array(_util2.default.Uint8Array_to_str(this.preferredCompressionAlgorithms)); + arr.push(write_sub_packet(sub.preferred_compression_algorithms, bytes)); + } + if (this.keyServerPreferences !== null) { + bytes = _util2.default.str_to_Uint8Array(_util2.default.Uint8Array_to_str(this.keyServerPreferences)); + arr.push(write_sub_packet(sub.key_server_preferences, bytes)); + } + if (this.preferredKeyServer !== null) { + arr.push(write_sub_packet(sub.preferred_key_server, _util2.default.str_to_Uint8Array(this.preferredKeyServer))); + } + if (this.isPrimaryUserID !== null) { + arr.push(write_sub_packet(sub.primary_user_id, new Uint8Array([this.isPrimaryUserID ? 1 : 0]))); + } + if (this.policyURI !== null) { + arr.push(write_sub_packet(sub.policy_uri, _util2.default.str_to_Uint8Array(this.policyURI))); + } + if (this.keyFlags !== null) { + bytes = _util2.default.str_to_Uint8Array(_util2.default.Uint8Array_to_str(this.keyFlags)); + arr.push(write_sub_packet(sub.key_flags, bytes)); + } + if (this.signersUserId !== null) { + arr.push(write_sub_packet(sub.signers_user_id, _util2.default.str_to_Uint8Array(this.signersUserId))); + } + if (this.reasonForRevocationFlag !== null) { + bytes = _util2.default.str_to_Uint8Array(String.fromCharCode(this.reasonForRevocationFlag) + this.reasonForRevocationString); + arr.push(write_sub_packet(sub.reason_for_revocation, bytes)); + } + if (this.features !== null) { + bytes = _util2.default.str_to_Uint8Array(_util2.default.Uint8Array_to_str(this.features)); + arr.push(write_sub_packet(sub.features, bytes)); + } + if (this.signatureTargetPublicKeyAlgorithm !== null) { + bytes = [new Uint8Array([this.signatureTargetPublicKeyAlgorithm, this.signatureTargetHashAlgorithm])]; + bytes.push(_util2.default.str_to_Uint8Array(this.signatureTargetHash)); + bytes = _util2.default.concat(bytes); + arr.push(write_sub_packet(sub.signature_target, bytes)); + } + if (this.preferredAeadAlgorithms !== null) { + bytes = _util2.default.str_to_Uint8Array(_util2.default.Uint8Array_to_str(this.preferredAeadAlgorithms)); + arr.push(write_sub_packet(sub.preferred_aead_algorithms, bytes)); + } + + const result = _util2.default.concat(arr); + const length = _util2.default.writeNumber(result.length, 2); + + return _util2.default.concat([length, result]); +}; + +/** + * Creates Uint8Array of bytes of Issuer and Embedded Signature subpackets + * @returns {Uint8Array} subpacket data + */ +Signature.prototype.write_unhashed_sub_packets = function () { + const sub = _enums2.default.signatureSubpacket; + const arr = []; + let bytes; + if (!this.issuerKeyId.isNull() && this.issuerKeyVersion !== 5) { + // If the version of [the] key is greater than 4, this subpacket + // MUST NOT be included in the signature. + arr.push(write_sub_packet(sub.issuer, this.issuerKeyId.write())); + } + if (this.embeddedSignature !== null) { + arr.push(write_sub_packet(sub.embedded_signature, this.embeddedSignature.write())); + } + if (this.issuerFingerprint !== null) { + bytes = [new Uint8Array([this.issuerKeyVersion]), this.issuerFingerprint]; + bytes = _util2.default.concat(bytes); + arr.push(write_sub_packet(sub.issuer_fingerprint, bytes)); + } + this.unhashedSubpackets.forEach(data => { + arr.push(_packet2.default.writeSimpleLength(data.length)); + arr.push(data); + }); + + const result = _util2.default.concat(arr); + const length = _util2.default.writeNumber(result.length, 2); + + return _util2.default.concat([length, result]); +}; + +/** + * Creates a string representation of a sub signature packet + * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.1|RFC4880 5.2.3.1} + * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.2|RFC4880 5.2.3.2} + * @param {Integer} type subpacket signature type. + * @param {String} data data to be included + * @returns {String} a string-representation of a sub signature packet + * @private + */ +function write_sub_packet(type, data) { + const arr = []; + arr.push(_packet2.default.writeSimpleLength(data.length + 1)); + arr.push(new Uint8Array([type])); + arr.push(data); + return _util2.default.concat(arr); +} + +// V4 signature sub packets + +Signature.prototype.read_sub_packet = function (bytes, trusted = true) { + let mypos = 0; + + const read_array = (prop, bytes) => { + this[prop] = []; + + for (let i = 0; i < bytes.length; i++) { + this[prop].push(bytes[i]); + } + }; + + // The leftmost bit denotes a "critical" packet + const critical = bytes[mypos] & 0x80; + const type = bytes[mypos] & 0x7F; + + // GPG puts the Issuer and Signature subpackets in the unhashed area. + // Tampering with those invalidates the signature, so we can trust them. + // Ignore all other unhashed subpackets. + if (!trusted && ![_enums2.default.signatureSubpacket.issuer, _enums2.default.signatureSubpacket.issuer_fingerprint, _enums2.default.signatureSubpacket.embedded_signature].includes(type)) { + this.unhashedSubpackets.push(bytes.subarray(mypos, bytes.length)); + return; + } + + mypos++; + + // subpacket type + switch (type) { + case 2: + // Signature Creation Time + this.created = _util2.default.readDate(bytes.subarray(mypos, bytes.length)); + break; + case 3: + { + // Signature Expiration Time in seconds + const seconds = _util2.default.readNumber(bytes.subarray(mypos, bytes.length)); + + this.signatureNeverExpires = seconds === 0; + this.signatureExpirationTime = seconds; + + break; + } + case 4: + // Exportable Certification + this.exportable = bytes[mypos++] === 1; + break; + case 5: + // Trust Signature + this.trustLevel = bytes[mypos++]; + this.trustAmount = bytes[mypos++]; + break; + case 6: + // Regular Expression + this.regularExpression = bytes[mypos]; + break; + case 7: + // Revocable + this.revocable = bytes[mypos++] === 1; + break; + case 9: + { + // Key Expiration Time in seconds + const seconds = _util2.default.readNumber(bytes.subarray(mypos, bytes.length)); + + this.keyExpirationTime = seconds; + this.keyNeverExpires = seconds === 0; + + break; + } + case 11: + // Preferred Symmetric Algorithms + read_array('preferredSymmetricAlgorithms', bytes.subarray(mypos, bytes.length)); + break; + case 12: + // Revocation Key + // (1 octet of class, 1 octet of public-key algorithm ID, 20 + // octets of + // fingerprint) + this.revocationKeyClass = bytes[mypos++]; + this.revocationKeyAlgorithm = bytes[mypos++]; + this.revocationKeyFingerprint = bytes.subarray(mypos, mypos + 20); + break; + + case 16: + // Issuer + this.issuerKeyId.read(bytes.subarray(mypos, bytes.length)); + break; + + case 20: + // Notation Data + // We don't know how to handle anything but a text flagged data. + if (bytes[mypos] === 0x80) { + // We extract key/value tuple from the byte stream. + mypos += 4; + const m = _util2.default.readNumber(bytes.subarray(mypos, mypos + 2)); + mypos += 2; + const n = _util2.default.readNumber(bytes.subarray(mypos, mypos + 2)); + mypos += 2; + + const name = _util2.default.Uint8Array_to_str(bytes.subarray(mypos, mypos + m)); + const value = _util2.default.Uint8Array_to_str(bytes.subarray(mypos + m, mypos + m + n)); + + this.notations.push([name, value]); + + if (critical && _config2.default.known_notations.indexOf(name) === -1) { + throw new Error("Unknown critical notation: " + name); + } + } else { + _util2.default.print_debug("Unsupported notation flag " + bytes[mypos]); + } + break; + case 21: + // Preferred Hash Algorithms + read_array('preferredHashAlgorithms', bytes.subarray(mypos, bytes.length)); + break; + case 22: + // Preferred Compression Algorithms + read_array('preferredCompressionAlgorithms', bytes.subarray(mypos, bytes.length)); + break; + case 23: + // Key Server Preferences + read_array('keyServerPreferences', bytes.subarray(mypos, bytes.length)); + break; + case 24: + // Preferred Key Server + this.preferredKeyServer = _util2.default.Uint8Array_to_str(bytes.subarray(mypos, bytes.length)); + break; + case 25: + // Primary User ID + this.isPrimaryUserID = bytes[mypos++] !== 0; + break; + case 26: + // Policy URI + this.policyURI = _util2.default.Uint8Array_to_str(bytes.subarray(mypos, bytes.length)); + break; + case 27: + // Key Flags + read_array('keyFlags', bytes.subarray(mypos, bytes.length)); + break; + case 28: + // Signer's User ID + this.signersUserId = _util2.default.Uint8Array_to_str(bytes.subarray(mypos, bytes.length)); + break; + case 29: + // Reason for Revocation + this.reasonForRevocationFlag = bytes[mypos++]; + this.reasonForRevocationString = _util2.default.Uint8Array_to_str(bytes.subarray(mypos, bytes.length)); + break; + case 30: + // Features + read_array('features', bytes.subarray(mypos, bytes.length)); + break; + case 31: + { + // Signature Target + // (1 octet public-key algorithm, 1 octet hash algorithm, N octets hash) + this.signatureTargetPublicKeyAlgorithm = bytes[mypos++]; + this.signatureTargetHashAlgorithm = bytes[mypos++]; + + const len = _crypto2.default.getHashByteLength(this.signatureTargetHashAlgorithm); + + this.signatureTargetHash = _util2.default.Uint8Array_to_str(bytes.subarray(mypos, mypos + len)); + break; + } + case 32: + // Embedded Signature + this.embeddedSignature = new Signature(); + this.embeddedSignature.read(bytes.subarray(mypos, bytes.length)); + break; + case 33: + // Issuer Fingerprint + this.issuerKeyVersion = bytes[mypos++]; + this.issuerFingerprint = bytes.subarray(mypos, bytes.length); + if (this.issuerKeyVersion === 5) { + this.issuerKeyId.read(this.issuerFingerprint); + } else { + this.issuerKeyId.read(this.issuerFingerprint.subarray(-8)); + } + break; + case 34: + // Preferred AEAD Algorithms + read_array.call(this, 'preferredAeadAlgorithms', bytes.subarray(mypos, bytes.length)); + break; + default: + { + const err = new Error("Unknown signature subpacket type " + type + " @:" + mypos); + if (critical) { + throw err; + } else { + _util2.default.print_debug(err); + } + } + } +}; + +Signature.prototype.read_sub_packets = function (bytes, trusted = true) { + // Two-octet scalar octet count for following subpacket data. + const subpacket_length = _util2.default.readNumber(bytes.subarray(0, 2)); + + let i = 2; + + // subpacket data set (zero or more subpackets) + while (i < 2 + subpacket_length) { + const len = _packet2.default.readSimpleLength(bytes.subarray(i, bytes.length)); + i += len.offset; + + this.read_sub_packet(bytes.subarray(i, i + len.len), trusted); + + i += len.len; + } + + return i; +}; + +// Produces data to produce signature on +Signature.prototype.toSign = function (type, data) { + const t = _enums2.default.signature; + + switch (type) { + case t.binary: + if (data.text !== null) { + return _util2.default.str_to_Uint8Array(data.getText(true)); + } + return data.getBytes(true); + + case t.text: + { + let text = data.getText(true); + // normalize EOL to \r\n + text = _util2.default.canonicalizeEOL(text); + // encode UTF8 + return _util2.default.encode_utf8(text); + } + case t.standalone: + return new Uint8Array(0); + + case t.cert_generic: + case t.cert_persona: + case t.cert_casual: + case t.cert_positive: + case t.cert_revocation: + { + let packet; + let tag; + + if (data.userId) { + tag = 0xB4; + packet = data.userId; + } else if (data.userAttribute) { + tag = 0xD1; + packet = data.userAttribute; + } else { + throw new Error('Either a userId or userAttribute packet needs to be ' + 'supplied for certification.'); + } + + const bytes = packet.write(); + + return _util2.default.concat([this.toSign(t.key, data), new Uint8Array([tag]), _util2.default.writeNumber(bytes.length, 4), bytes]); + } + case t.subkey_binding: + case t.subkey_revocation: + case t.key_binding: + return _util2.default.concat([this.toSign(t.key, data), this.toSign(t.key, { + key: data.bind + })]); + + case t.key: + if (data.key === undefined) { + throw new Error('Key packet is required for this signature.'); + } + return data.key.writeForHash(this.version); + + case t.key_revocation: + return this.toSign(t.key, data); + case t.timestamp: + return new Uint8Array(0); + case t.third_party: + throw new Error('Not implemented'); + default: + throw new Error('Unknown signature type.'); + } +}; + +Signature.prototype.calculateTrailer = function (data, detached) { + let length = 0; + return _webStreamTools2.default.transform(_webStreamTools2.default.clone(this.signatureData), value => { + length += value.length; + }, () => { + const arr = []; + if (this.version === 5 && (this.signatureType === _enums2.default.signature.binary || this.signatureType === _enums2.default.signature.text)) { + if (detached) { + arr.push(new Uint8Array(6)); + } else { + arr.push(data.writeHeader()); + } + } + arr.push(new Uint8Array([this.version, 0xFF])); + if (this.version === 5) { + arr.push(new Uint8Array(4)); + } + arr.push(_util2.default.writeNumber(length, 4)); + // For v5, this should really be writeNumber(length, 8) rather than the + // hardcoded 4 zero bytes above + return _util2.default.concat(arr); + }); +}; + +Signature.prototype.toHash = function (signatureType, data, detached = false) { + const bytes = this.toSign(signatureType, data); + + return _util2.default.concat([bytes, this.signatureData, this.calculateTrailer(data, detached)]); +}; + +Signature.prototype.hash = async function (signatureType, data, toHash, detached = false, streaming = true) { + const hashAlgorithm = _enums2.default.write(_enums2.default.hash, this.hashAlgorithm); + if (!toHash) toHash = this.toHash(signatureType, data, detached); + if (!streaming && _util2.default.isStream(toHash)) { + return _webStreamTools2.default.fromAsync(async () => this.hash(signatureType, data, (await _webStreamTools2.default.readToEnd(toHash)), detached)); + } + return _crypto2.default.hash.digest(hashAlgorithm, toHash); +}; + +/** + * verifys the signature packet. Note: not signature types are implemented + * @param {module:packet.PublicSubkey|module:packet.PublicKey| + * module:packet.SecretSubkey|module:packet.SecretKey} key the public key to verify the signature + * @param {module:enums.signature} signatureType expected signature type + * @param {String|Object} data data which on the signature applies + * @param {Boolean} detached (optional) whether to verify a detached signature + * @returns {Promise} True if message is verified, else false. + * @async + */ +Signature.prototype.verify = async function (key, signatureType, data, detached = false) { + const publicKeyAlgorithm = _enums2.default.write(_enums2.default.publicKey, this.publicKeyAlgorithm); + const hashAlgorithm = _enums2.default.write(_enums2.default.hash, this.hashAlgorithm); + + if (publicKeyAlgorithm !== _enums2.default.write(_enums2.default.publicKey, key.algorithm)) { + throw new Error('Public key algorithm used to sign signature does not match issuer key algorithm.'); + } + + let toHash; + let hash; + if (this.hashed) { + hash = this.hashed; + } else { + toHash = this.toHash(signatureType, data, detached); + hash = await this.hash(signatureType, data, toHash); + } + hash = await _webStreamTools2.default.readToEnd(hash); + + if (this.signedHashValue[0] !== hash[0] || this.signedHashValue[1] !== hash[1]) { + this.verified = false; + } else { + let mpicount = 0; + // Algorithm-Specific Fields for RSA signatures: + // - multiprecision number (MPI) of RSA signature value m**d mod n. + if (publicKeyAlgorithm > 0 && publicKeyAlgorithm < 4) { + mpicount = 1; + + // Algorithm-Specific Fields for DSA, ECDSA, and EdDSA signatures: + // - MPI of DSA value r. + // - MPI of DSA value s. + } else if (publicKeyAlgorithm === _enums2.default.publicKey.dsa || publicKeyAlgorithm === _enums2.default.publicKey.ecdsa || publicKeyAlgorithm === _enums2.default.publicKey.eddsa) { + mpicount = 2; + } + + // EdDSA signature parameters are encoded in little-endian format + // https://tools.ietf.org/html/rfc8032#section-5.1.2 + const endian = publicKeyAlgorithm === _enums2.default.publicKey.eddsa ? 'le' : 'be'; + const mpi = []; + let i = 0; + this.signature = await _webStreamTools2.default.readToEnd(this.signature); + for (let j = 0; j < mpicount; j++) { + mpi[j] = new _mpi2.default(); + i += mpi[j].read(this.signature.subarray(i, this.signature.length), endian); + } + + this.verified = await _crypto2.default.signature.verify(publicKeyAlgorithm, hashAlgorithm, mpi, key.params, toHash, hash); + } + return this.verified; +}; + +/** + * Verifies signature expiration date + * @param {Date} date (optional) use the given date for verification instead of the current time + * @returns {Boolean} true if expired + */ +Signature.prototype.isExpired = function (date = new Date()) { + const normDate = _util2.default.normalizeDate(date); + if (normDate !== null) { + const expirationTime = this.getExpirationTime(); + return !(this.created <= normDate && normDate <= expirationTime); + } + return false; +}; + +/** + * Returns the expiration time of the signature or Infinity if signature does not expire + * @returns {Date} expiration time + */ +Signature.prototype.getExpirationTime = function () { + return !this.signatureNeverExpires ? new Date(this.created.getTime() + this.signatureExpirationTime * 1000) : Infinity; +}; + +/** + * Fix custom types after cloning + */ +Signature.prototype.postCloneTypeFix = function () { + this.issuerKeyId = _keyid2.default.fromClone(this.issuerKeyId); +}; + +exports.default = Signature; + +},{"../config":79,"../crypto":94,"../enums":113,"../type/keyid.js":148,"../type/mpi.js":149,"../util":152,"./packet":129,"web-stream-tools":75}],137:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _webStreamTools = require('web-stream-tools'); + +var _webStreamTools2 = _interopRequireDefault(_webStreamTools); + +var _config = require('../config'); + +var _config2 = _interopRequireDefault(_config); + +var _crypto = require('../crypto'); + +var _crypto2 = _interopRequireDefault(_crypto); + +var _enums = require('../enums'); + +var _enums2 = _interopRequireDefault(_enums); + +var _util = require('../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const VERSION = 1; // A one-octet version number of the data packet. + +/** + * Implementation of the Symmetrically Encrypted Authenticated Encryption with + * Additional Data (AEAD) Protected Data Packet + * + * {@link https://tools.ietf.org/html/draft-ford-openpgp-format-00#section-2.1}: + * AEAD Protected Data Packet + * @memberof module:packet + * @constructor + */ +// OpenPGP.js - An OpenPGP implementation in javascript +// Copyright (C) 2016 Tankred Hase +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @requires web-stream-tools + * @requires config + * @requires crypto + * @requires enums + * @requires util + */ + +function SymEncryptedAEADProtected() { + this.tag = _enums2.default.packet.symEncryptedAEADProtected; + this.version = VERSION; + this.cipherAlgo = null; + this.aeadAlgorithm = 'eax'; + this.aeadAlgo = null; + this.chunkSizeByte = null; + this.iv = null; + this.encrypted = null; + this.packets = null; +} + +exports.default = SymEncryptedAEADProtected; + +/** + * Parse an encrypted payload of bytes in the order: version, IV, ciphertext (see specification) + * @param {Uint8Array | ReadableStream} bytes + */ + +SymEncryptedAEADProtected.prototype.read = async function (bytes) { + await _webStreamTools2.default.parse(bytes, async reader => { + if ((await reader.readByte()) !== VERSION) { + // The only currently defined value is 1. + throw new Error('Invalid packet version.'); + } + this.cipherAlgo = await reader.readByte(); + this.aeadAlgo = await reader.readByte(); + this.chunkSizeByte = await reader.readByte(); + const mode = _crypto2.default[_enums2.default.read(_enums2.default.aead, this.aeadAlgo)]; + this.iv = await reader.readBytes(mode.ivLength); + this.encrypted = reader.remainder(); + }); +}; + +/** + * Write the encrypted payload of bytes in the order: version, IV, ciphertext (see specification) + * @returns {Uint8Array | ReadableStream} The encrypted payload + */ +SymEncryptedAEADProtected.prototype.write = function () { + return _util2.default.concat([new Uint8Array([this.version, this.cipherAlgo, this.aeadAlgo, this.chunkSizeByte]), this.iv, this.encrypted]); +}; + +/** + * Decrypt the encrypted payload. + * @param {String} sessionKeyAlgorithm The session key's cipher algorithm e.g. 'aes128' + * @param {Uint8Array} key The session key used to encrypt the payload + * @param {Boolean} streaming Whether the top-level function will return a stream + * @returns {Boolean} + * @async + */ +SymEncryptedAEADProtected.prototype.decrypt = async function (sessionKeyAlgorithm, key, streaming) { + await this.packets.read((await this.crypt('decrypt', key, _webStreamTools2.default.clone(this.encrypted), streaming)), streaming); + return true; +}; + +/** + * Encrypt the packet list payload. + * @param {String} sessionKeyAlgorithm The session key's cipher algorithm e.g. 'aes128' + * @param {Uint8Array} key The session key used to encrypt the payload + * @param {Boolean} streaming Whether the top-level function will return a stream + * @async + */ +SymEncryptedAEADProtected.prototype.encrypt = async function (sessionKeyAlgorithm, key, streaming) { + this.cipherAlgo = _enums2.default.write(_enums2.default.symmetric, sessionKeyAlgorithm); + this.aeadAlgo = _enums2.default.write(_enums2.default.aead, this.aeadAlgorithm); + const mode = _crypto2.default[_enums2.default.read(_enums2.default.aead, this.aeadAlgo)]; + this.iv = await _crypto2.default.random.getRandomBytes(mode.ivLength); // generate new random IV + this.chunkSizeByte = _config2.default.aead_chunk_size_byte; + const data = this.packets.write(); + this.encrypted = await this.crypt('encrypt', key, data, streaming); +}; + +/** + * En/decrypt the payload. + * @param {encrypt|decrypt} fn Whether to encrypt or decrypt + * @param {Uint8Array} key The session key used to en/decrypt the payload + * @param {Uint8Array | ReadableStream} data The data to en/decrypt + * @param {Boolean} streaming Whether the top-level function will return a stream + * @returns {Uint8Array | ReadableStream} + * @async + */ +SymEncryptedAEADProtected.prototype.crypt = async function (fn, key, data, streaming) { + const cipher = _enums2.default.read(_enums2.default.symmetric, this.cipherAlgo); + const mode = _crypto2.default[_enums2.default.read(_enums2.default.aead, this.aeadAlgo)]; + const modeInstance = await mode(cipher, key); + const tagLengthIfDecrypting = fn === 'decrypt' ? mode.tagLength : 0; + const chunkSize = 2 ** (this.chunkSizeByte + 6) + tagLengthIfDecrypting; // ((uint64_t)1 << (c + 6)) + const adataBuffer = new ArrayBuffer(21); + const adataArray = new Uint8Array(adataBuffer, 0, 13); + const adataTagArray = new Uint8Array(adataBuffer); + const adataView = new DataView(adataBuffer); + const chunkIndexArray = new Uint8Array(adataBuffer, 5, 8); + adataArray.set([0xC0 | this.tag, this.version, this.cipherAlgo, this.aeadAlgo, this.chunkSizeByte], 0); + let chunkIndex = 0; + let latestPromise = Promise.resolve(); + let cryptedBytes = 0; + let queuedBytes = 0; + const iv = this.iv; + return _webStreamTools2.default.transformPair(data, async (readable, writable) => { + const reader = _webStreamTools2.default.getReader(readable); + const buffer = new TransformStream({}, { + highWaterMark: streaming ? _util2.default.getHardwareConcurrency() * 2 ** (_config2.default.aead_chunk_size_byte + 6) : Infinity, + size: array => array.length + }); + _webStreamTools2.default.pipe(buffer.readable, writable); + const writer = _webStreamTools2.default.getWriter(buffer.writable); + try { + while (true) { + let chunk = (await reader.readBytes(chunkSize + tagLengthIfDecrypting)) || new Uint8Array(); + const finalChunk = chunk.subarray(chunk.length - tagLengthIfDecrypting); + chunk = chunk.subarray(0, chunk.length - tagLengthIfDecrypting); + let cryptedPromise; + let done; + if (!chunkIndex || chunk.length) { + reader.unshift(finalChunk); + cryptedPromise = modeInstance[fn](chunk, mode.getNonce(iv, chunkIndexArray), adataArray); + } else { + // After the last chunk, we either encrypt a final, empty + // data chunk to get the final authentication tag or + // validate that final authentication tag. + adataView.setInt32(13 + 4, cryptedBytes); // Should be setInt64(13, ...) + cryptedPromise = modeInstance[fn](finalChunk, mode.getNonce(iv, chunkIndexArray), adataTagArray); + done = true; + } + cryptedBytes += chunk.length - tagLengthIfDecrypting; + queuedBytes += chunk.length - tagLengthIfDecrypting; + // eslint-disable-next-line no-loop-func + latestPromise = latestPromise.then(() => cryptedPromise).then(async crypted => { + await writer.ready; + await writer.write(crypted); + queuedBytes -= chunk.length; + }).catch(err => writer.abort(err)); + if (done || queuedBytes > writer.desiredSize) { + await latestPromise; // Respect backpressure + } + if (!done) { + adataView.setInt32(5 + 4, ++chunkIndex); // Should be setInt64(5, ...) + } else { + await writer.close(); + break; + } + } + } catch (e) { + await writer.abort(e); + } + }); +}; + +},{"../config":79,"../crypto":94,"../enums":113,"../util":152,"web-stream-tools":75}],138:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _webStreamTools = require('web-stream-tools'); + +var _webStreamTools2 = _interopRequireDefault(_webStreamTools); + +var _config = require('../config'); + +var _config2 = _interopRequireDefault(_config); + +var _crypto = require('../crypto'); + +var _crypto2 = _interopRequireDefault(_crypto); + +var _enums = require('../enums'); + +var _enums2 = _interopRequireDefault(_enums); + +var _util = require('../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const VERSION = 1; // A one-octet version number of the data packet. + +/** + * Implementation of the Sym. Encrypted Integrity Protected Data Packet (Tag 18) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.13|RFC4880 5.13}: + * The Symmetrically Encrypted Integrity Protected Data packet is + * a variant of the Symmetrically Encrypted Data packet. It is a new feature + * created for OpenPGP that addresses the problem of detecting a modification to + * encrypted data. It is used in combination with a Modification Detection Code + * packet. + * @memberof module:packet + * @constructor + */ +// GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @requires asmcrypto.js + * @requires web-stream-tools + * @requires config + * @requires crypto + * @requires enums + * @requires util + */ + +function SymEncryptedIntegrityProtected() { + this.tag = _enums2.default.packet.symEncryptedIntegrityProtected; + this.version = VERSION; + /** The encrypted payload. */ + this.encrypted = null; // string + /** + * If after decrypting the packet this is set to true, + * a modification has been detected and thus the contents + * should be discarded. + * @type {Boolean} + */ + this.modification = false; + this.packets = null; +} + +SymEncryptedIntegrityProtected.prototype.read = async function (bytes) { + await _webStreamTools2.default.parse(bytes, async reader => { + + // - A one-octet version number. The only currently defined value is 1. + if ((await reader.readByte()) !== VERSION) { + throw new Error('Invalid packet version.'); + } + + // - Encrypted data, the output of the selected symmetric-key cipher + // operating in Cipher Feedback mode with shift amount equal to the + // block size of the cipher (CFB-n where n is the block size). + this.encrypted = reader.remainder(); + }); +}; + +SymEncryptedIntegrityProtected.prototype.write = function () { + return _util2.default.concat([new Uint8Array([VERSION]), this.encrypted]); +}; + +/** + * Encrypt the payload in the packet. + * @param {String} sessionKeyAlgorithm The selected symmetric encryption algorithm to be used e.g. 'aes128' + * @param {Uint8Array} key The key of cipher blocksize length to be used + * @param {Boolean} streaming Whether to set this.encrypted to a stream + * @returns {Promise} + * @async + */ +SymEncryptedIntegrityProtected.prototype.encrypt = async function (sessionKeyAlgorithm, key, streaming) { + let bytes = this.packets.write(); + if (!streaming) bytes = await _webStreamTools2.default.readToEnd(bytes); + const prefix = await _crypto2.default.getPrefixRandom(sessionKeyAlgorithm); + const mdc = new Uint8Array([0xD3, 0x14]); // modification detection code packet + + const tohash = _util2.default.concat([prefix, bytes, mdc]); + const hash = await _crypto2.default.hash.sha1(_webStreamTools2.default.passiveClone(tohash)); + const plaintext = _util2.default.concat([tohash, hash]); + + this.encrypted = await _crypto2.default.cfb.encrypt(sessionKeyAlgorithm, key, plaintext, new Uint8Array(_crypto2.default.cipher[sessionKeyAlgorithm].blockSize)); + return true; +}; + +/** + * Decrypts the encrypted data contained in the packet. + * @param {String} sessionKeyAlgorithm The selected symmetric encryption algorithm to be used e.g. 'aes128' + * @param {Uint8Array} key The key of cipher blocksize length to be used + * @param {Boolean} streaming Whether to read this.encrypted as a stream + * @returns {Promise} + * @async + */ +SymEncryptedIntegrityProtected.prototype.decrypt = async function (sessionKeyAlgorithm, key, streaming) { + let encrypted = _webStreamTools2.default.clone(this.encrypted); + if (!streaming) encrypted = await _webStreamTools2.default.readToEnd(encrypted); + const decrypted = await _crypto2.default.cfb.decrypt(sessionKeyAlgorithm, key, encrypted, new Uint8Array(_crypto2.default.cipher[sessionKeyAlgorithm].blockSize)); + + // there must be a modification detection code packet as the + // last packet and everything gets hashed except the hash itself + const realHash = _webStreamTools2.default.slice(_webStreamTools2.default.passiveClone(decrypted), -20); + const tohash = _webStreamTools2.default.slice(decrypted, 0, -20); + const verifyHash = Promise.all([_webStreamTools2.default.readToEnd((await _crypto2.default.hash.sha1(_webStreamTools2.default.passiveClone(tohash)))), _webStreamTools2.default.readToEnd(realHash)]).then(([hash, mdc]) => { + if (!_util2.default.equalsUint8Array(hash, mdc)) { + throw new Error('Modification detected.'); + } + return new Uint8Array(); + }); + const bytes = _webStreamTools2.default.slice(tohash, _crypto2.default.cipher[sessionKeyAlgorithm].blockSize + 2); // Remove random prefix + let packetbytes = _webStreamTools2.default.slice(bytes, 0, -2); // Remove MDC packet + packetbytes = _webStreamTools2.default.concat([packetbytes, _webStreamTools2.default.fromAsync(() => verifyHash)]); + if (!_util2.default.isStream(encrypted) || !_config2.default.allow_unauthenticated_stream) { + packetbytes = await _webStreamTools2.default.readToEnd(packetbytes); + } + await this.packets.read(packetbytes, streaming); + return true; +}; + +exports.default = SymEncryptedIntegrityProtected; + +},{"../config":79,"../crypto":94,"../enums":113,"../util":152,"web-stream-tools":75}],139:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _s2k = require('../type/s2k'); + +var _s2k2 = _interopRequireDefault(_s2k); + +var _config = require('../config'); + +var _config2 = _interopRequireDefault(_config); + +var _crypto = require('../crypto'); + +var _crypto2 = _interopRequireDefault(_crypto); + +var _enums = require('../enums'); + +var _enums2 = _interopRequireDefault(_enums); + +var _util = require('../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Public-Key Encrypted Session Key Packets (Tag 1) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.1|RFC4880 5.1}: + * A Public-Key Encrypted Session Key packet holds the session key + * used to encrypt a message. Zero or more Public-Key Encrypted Session Key + * packets and/or Symmetric-Key Encrypted Session Key packets may precede a + * Symmetrically Encrypted Data Packet, which holds an encrypted message. The + * message is encrypted with the session key, and the session key is itself + * encrypted and stored in the Encrypted Session Key packet(s). The + * Symmetrically Encrypted Data Packet is preceded by one Public-Key Encrypted + * Session Key packet for each OpenPGP key to which the message is encrypted. + * The recipient of the message finds a session key that is encrypted to their + * public key, decrypts the session key, and then uses the session key to + * decrypt the message. + * @memberof module:packet + * @constructor + */ +function SymEncryptedSessionKey() { + this.tag = _enums2.default.packet.symEncryptedSessionKey; + this.version = _config2.default.aead_protect ? 5 : 4; + this.sessionKey = null; + this.sessionKeyEncryptionAlgorithm = null; + this.sessionKeyAlgorithm = 'aes256'; + this.aeadAlgorithm = _enums2.default.read(_enums2.default.aead, _config2.default.aead_mode); + this.encrypted = null; + this.s2k = null; + this.iv = null; +} + +/** + * Parsing function for a symmetric encrypted session key packet (tag 3). + * + * @param {Uint8Array} input Payload of a tag 1 packet + * @param {Integer} position Position to start reading from the input string + * @param {Integer} len + * Length of the packet or the remaining length of + * input at position + * @returns {module:packet.SymEncryptedSessionKey} Object representation + */ +// GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @requires type/s2k + * @requires config + * @requires crypto + * @requires enums + * @requires util + */ + +SymEncryptedSessionKey.prototype.read = function (bytes) { + let offset = 0; + + // A one-octet version number. The only currently defined version is 4. + this.version = bytes[offset++]; + + // A one-octet number describing the symmetric algorithm used. + const algo = _enums2.default.read(_enums2.default.symmetric, bytes[offset++]); + + if (this.version === 5) { + // A one-octet AEAD algorithm. + this.aeadAlgorithm = _enums2.default.read(_enums2.default.aead, bytes[offset++]); + } + + // A string-to-key (S2K) specifier, length as defined above. + this.s2k = new _s2k2.default(); + offset += this.s2k.read(bytes.subarray(offset, bytes.length)); + + if (this.version === 5) { + const mode = _crypto2.default[this.aeadAlgorithm]; + + // A starting initialization vector of size specified by the AEAD + // algorithm. + this.iv = bytes.subarray(offset, offset += mode.ivLength); + } + + // The encrypted session key itself, which is decrypted with the + // string-to-key object. This is optional in version 4. + if (this.version === 5 || offset < bytes.length) { + this.encrypted = bytes.subarray(offset, bytes.length); + this.sessionKeyEncryptionAlgorithm = algo; + } else { + this.sessionKeyAlgorithm = algo; + } +}; + +SymEncryptedSessionKey.prototype.write = function () { + const algo = this.encrypted === null ? this.sessionKeyAlgorithm : this.sessionKeyEncryptionAlgorithm; + + let bytes; + + if (this.version === 5) { + bytes = _util2.default.concatUint8Array([new Uint8Array([this.version, _enums2.default.write(_enums2.default.symmetric, algo), _enums2.default.write(_enums2.default.aead, this.aeadAlgorithm)]), this.s2k.write(), this.iv, this.encrypted]); + } else { + bytes = _util2.default.concatUint8Array([new Uint8Array([this.version, _enums2.default.write(_enums2.default.symmetric, algo)]), this.s2k.write()]); + + if (this.encrypted !== null) { + bytes = _util2.default.concatUint8Array([bytes, this.encrypted]); + } + } + + return bytes; +}; + +/** + * Decrypts the session key + * @param {String} passphrase The passphrase in string form + * @returns {Promise} + * @async + */ +SymEncryptedSessionKey.prototype.decrypt = async function (passphrase) { + const algo = this.sessionKeyEncryptionAlgorithm !== null ? this.sessionKeyEncryptionAlgorithm : this.sessionKeyAlgorithm; + + const length = _crypto2.default.cipher[algo].keySize; + const key = await this.s2k.produce_key(passphrase, length); + + if (this.version === 5) { + const mode = _crypto2.default[this.aeadAlgorithm]; + const adata = new Uint8Array([0xC0 | this.tag, this.version, _enums2.default.write(_enums2.default.symmetric, this.sessionKeyEncryptionAlgorithm), _enums2.default.write(_enums2.default.aead, this.aeadAlgorithm)]); + const modeInstance = await mode(algo, key); + this.sessionKey = await modeInstance.decrypt(this.encrypted, this.iv, adata); + } else if (this.encrypted !== null) { + const decrypted = await _crypto2.default.cfb.decrypt(algo, key, this.encrypted, new Uint8Array(_crypto2.default.cipher[algo].blockSize)); + + this.sessionKeyAlgorithm = _enums2.default.read(_enums2.default.symmetric, decrypted[0]); + this.sessionKey = decrypted.subarray(1, decrypted.length); + } else { + this.sessionKey = key; + } + + return true; +}; + +/** + * Encrypts the session key + * @param {String} passphrase The passphrase in string form + * @returns {Promise} + * @async + */ +SymEncryptedSessionKey.prototype.encrypt = async function (passphrase) { + const algo = this.sessionKeyEncryptionAlgorithm !== null ? this.sessionKeyEncryptionAlgorithm : this.sessionKeyAlgorithm; + + this.sessionKeyEncryptionAlgorithm = algo; + + this.s2k = new _s2k2.default(); + this.s2k.salt = await _crypto2.default.random.getRandomBytes(8); + + const length = _crypto2.default.cipher[algo].keySize; + const key = await this.s2k.produce_key(passphrase, length); + + if (this.sessionKey === null) { + this.sessionKey = await _crypto2.default.generateSessionKey(this.sessionKeyAlgorithm); + } + + if (this.version === 5) { + const mode = _crypto2.default[this.aeadAlgorithm]; + this.iv = await _crypto2.default.random.getRandomBytes(mode.ivLength); // generate new random IV + const adata = new Uint8Array([0xC0 | this.tag, this.version, _enums2.default.write(_enums2.default.symmetric, this.sessionKeyEncryptionAlgorithm), _enums2.default.write(_enums2.default.aead, this.aeadAlgorithm)]); + const modeInstance = await mode(algo, key); + this.encrypted = await modeInstance.encrypt(this.sessionKey, this.iv, adata); + } else { + const algo_enum = new Uint8Array([_enums2.default.write(_enums2.default.symmetric, this.sessionKeyAlgorithm)]); + const private_key = _util2.default.concatUint8Array([algo_enum, this.sessionKey]); + this.encrypted = await _crypto2.default.cfb.encrypt(algo, key, private_key, new Uint8Array(_crypto2.default.cipher[algo].blockSize)); + } + + return true; +}; + +/** + * Fix custom types after cloning + */ +SymEncryptedSessionKey.prototype.postCloneTypeFix = function () { + this.s2k = _s2k2.default.fromClone(this.s2k); +}; + +exports.default = SymEncryptedSessionKey; + +},{"../config":79,"../crypto":94,"../enums":113,"../type/s2k":151,"../util":152}],140:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _webStreamTools = require('web-stream-tools'); + +var _webStreamTools2 = _interopRequireDefault(_webStreamTools); + +var _config = require('../config'); + +var _config2 = _interopRequireDefault(_config); + +var _crypto = require('../crypto'); + +var _crypto2 = _interopRequireDefault(_crypto); + +var _enums = require('../enums'); + +var _enums2 = _interopRequireDefault(_enums); + +var _util = require('../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Implementation of the Symmetrically Encrypted Data Packet (Tag 9) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.7|RFC4880 5.7}: + * The Symmetrically Encrypted Data packet contains data encrypted with a + * symmetric-key algorithm. When it has been decrypted, it contains other + * packets (usually a literal data packet or compressed data packet, but in + * theory other Symmetrically Encrypted Data packets or sequences of packets + * that form whole OpenPGP messages). + * @memberof module:packet + * @constructor + */ +function SymmetricallyEncrypted() { + /** + * Packet type + * @type {module:enums.packet} + */ + this.tag = _enums2.default.packet.symmetricallyEncrypted; + /** + * Encrypted secret-key data + */ + this.encrypted = null; + /** + * Decrypted packets contained within. + * @type {module:packet.List} + */ + this.packets = null; + /** + * When true, decrypt fails if message is not integrity protected + * @see module:config.ignore_mdc_error + */ + this.ignore_mdc_error = _config2.default.ignore_mdc_error; +} // GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @requires web-stream-tools + * @requires config + * @requires crypto + * @requires enums + * @requires util + */ + +SymmetricallyEncrypted.prototype.read = function (bytes) { + this.encrypted = bytes; +}; + +SymmetricallyEncrypted.prototype.write = function () { + return this.encrypted; +}; + +/** + * Decrypt the symmetrically-encrypted packet data + * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. + * @param {module:enums.symmetric} sessionKeyAlgorithm Symmetric key algorithm to use + * @param {Uint8Array} key The key of cipher blocksize length to be used + * @returns {Promise} + * @async + */ +SymmetricallyEncrypted.prototype.decrypt = async function (sessionKeyAlgorithm, key) { + // If MDC errors are not being ignored, all missing MDC packets in symmetrically encrypted data should throw an error + if (!this.ignore_mdc_error) { + throw new Error('Decryption failed due to missing MDC.'); + } + + this.encrypted = await _webStreamTools2.default.readToEnd(this.encrypted); + const decrypted = await _crypto2.default.cfb.decrypt(sessionKeyAlgorithm, key, this.encrypted.subarray(_crypto2.default.cipher[sessionKeyAlgorithm].blockSize + 2), this.encrypted.subarray(2, _crypto2.default.cipher[sessionKeyAlgorithm].blockSize + 2)); + + await this.packets.read(decrypted); + + return true; +}; + +/** + * Encrypt the symmetrically-encrypted packet data + * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. + * @param {module:enums.symmetric} sessionKeyAlgorithm Symmetric key algorithm to use + * @param {Uint8Array} key The key of cipher blocksize length to be used + * @returns {Promise} + * @async + */ +SymmetricallyEncrypted.prototype.encrypt = async function (algo, key) { + const data = this.packets.write(); + + const prefix = await _crypto2.default.getPrefixRandom(algo); + const FRE = await _crypto2.default.cfb.encrypt(algo, key, prefix, new Uint8Array(_crypto2.default.cipher[algo].blockSize)); + const ciphertext = await _crypto2.default.cfb.encrypt(algo, key, data, FRE.subarray(2)); + this.encrypted = _util2.default.concat([FRE, ciphertext]); + + return true; +}; + +exports.default = SymmetricallyEncrypted; + +},{"../config":79,"../crypto":94,"../enums":113,"../util":152,"web-stream-tools":75}],141:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _enums = require('../enums'); + +var _enums2 = _interopRequireDefault(_enums); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Implementation of the Trust Packet (Tag 12) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.10|RFC4880 5.10}: + * The Trust packet is used only within keyrings and is not normally + * exported. Trust packets contain data that record the user's + * specifications of which key holders are trustworthy introducers, + * along with other information that implementing software uses for + * trust information. The format of Trust packets is defined by a given + * implementation. + * + * Trust packets SHOULD NOT be emitted to output streams that are + * transferred to other users, and they SHOULD be ignored on any input + * other than local keyring files. + * @memberof module:packet + * @constructor + */ +function Trust() { + this.tag = _enums2.default.packet.trust; +} + +/** + * Parsing function for a trust packet (tag 12). + * Currently not implemented as we ignore trust packets + * @param {String} byptes payload of a tag 12 packet + */ +/** + * @requires enums + */ + +Trust.prototype.read = function () {}; // TODO + +exports.default = Trust; + +},{"../enums":113}],142:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _packet = require('./packet'); + +var _packet2 = _interopRequireDefault(_packet); + +var _enums = require('../enums'); + +var _enums2 = _interopRequireDefault(_enums); + +var _util = require('../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Implementation of the User Attribute Packet (Tag 17) + * + * The User Attribute packet is a variation of the User ID packet. It + * is capable of storing more types of data than the User ID packet, + * which is limited to text. Like the User ID packet, a User Attribute + * packet may be certified by the key owner ("self-signed") or any other + * key owner who cares to certify it. Except as noted, a User Attribute + * packet may be used anywhere that a User ID packet may be used. + * + * While User Attribute packets are not a required part of the OpenPGP + * standard, implementations SHOULD provide at least enough + * compatibility to properly handle a certification signature on the + * User Attribute packet. A simple way to do this is by treating the + * User Attribute packet as a User ID packet with opaque contents, but + * an implementation may use any method desired. + * @memberof module:packet + * @constructor + */ +function UserAttribute() { + this.tag = _enums2.default.packet.userAttribute; + this.attributes = []; +} + +/** + * parsing function for a user attribute packet (tag 17). + * @param {Uint8Array} input payload of a tag 17 packet + */ +// GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @requires packet + * @requires enums + * @requires util + */ + +UserAttribute.prototype.read = function (bytes) { + let i = 0; + while (i < bytes.length) { + const len = _packet2.default.readSimpleLength(bytes.subarray(i, bytes.length)); + i += len.offset; + + this.attributes.push(_util2.default.Uint8Array_to_str(bytes.subarray(i, i + len.len))); + i += len.len; + } +}; + +/** + * Creates a binary representation of the user attribute packet + * @returns {Uint8Array} string representation + */ +UserAttribute.prototype.write = function () { + const arr = []; + for (let i = 0; i < this.attributes.length; i++) { + arr.push(_packet2.default.writeSimpleLength(this.attributes[i].length)); + arr.push(_util2.default.str_to_Uint8Array(this.attributes[i])); + } + return _util2.default.concatUint8Array(arr); +}; + +/** + * Compare for equality + * @param {module:packet.UserAttribute} usrAttr + * @returns {Boolean} true if equal + */ +UserAttribute.prototype.equals = function (usrAttr) { + if (!usrAttr || !(usrAttr instanceof UserAttribute)) { + return false; + } + return this.attributes.every(function (attr, index) { + return attr === usrAttr.attributes[index]; + }); +}; + +exports.default = UserAttribute; + +},{"../enums":113,"../util":152,"./packet":129}],143:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _enums = require('../enums'); + +var _enums2 = _interopRequireDefault(_enums); + +var _util = require('../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Implementation of the User ID Packet (Tag 13) + * + * A User ID packet consists of UTF-8 text that is intended to represent + * the name and email address of the key holder. By convention, it + * includes an RFC 2822 [RFC2822] mail name-addr, but there are no + * restrictions on its content. The packet length in the header + * specifies the length of the User ID. + * @memberof module:packet + * @constructor + */ +// GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @requires enums + * @requires util + */ + +function Userid() { + this.tag = _enums2.default.packet.userid; + /** A string containing the user id. Usually in the form + * John Doe + * @type {String} + */ + this.userid = ''; + + this.name = ''; + this.email = ''; + this.comment = ''; +} + +/** + * Parsing function for a user id packet (tag 13). + * @param {Uint8Array} input payload of a tag 13 packet + */ +Userid.prototype.read = function (bytes) { + this.parse(_util2.default.decode_utf8(bytes)); +}; + +/** + * Parse userid string, e.g. 'John Doe ' + */ +Userid.prototype.parse = function (userid) { + try { + Object.assign(this, _util2.default.parseUserId(userid)); + } catch (e) {} + this.userid = userid; +}; + +/** + * Creates a binary representation of the user id packet + * @returns {Uint8Array} binary representation + */ +Userid.prototype.write = function () { + return _util2.default.encode_utf8(this.userid); +}; + +/** + * Set userid string from object, e.g. { name:'Phil Zimmermann', email:'phil@openpgp.org' } + */ +Userid.prototype.format = function (userid) { + if (_util2.default.isString(userid)) { + userid = _util2.default.parseUserId(userid); + } + Object.assign(this, userid); + this.userid = _util2.default.formatUserId(userid); +}; + +exports.default = Userid; + +},{"../enums":113,"../util":152}],144:[function(require,module,exports){ +(function (global){ +'use strict'; + +var _util = require('./util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +if (typeof window !== 'undefined') { + /******************************************************************** + * NOTE: This list is duplicated in Gruntfile.js, * + * so that these polyfills are only included in the compat bundle. * + ********************************************************************/ + + try { + if (typeof window.fetch === 'undefined') { + require('whatwg-fetch'); + } + if (typeof Array.prototype.fill === 'undefined') { + require('core-js/fn/array/fill'); + } + if (typeof Array.prototype.find === 'undefined') { + require('core-js/fn/array/find'); + } + if (typeof Array.prototype.includes === 'undefined') { + require('core-js/fn/array/includes'); + } + if (typeof Array.from === 'undefined') { + require('core-js/fn/array/from'); + } + + // No if-statement on Promise because of IE11. Otherwise Promise is undefined in the service worker. + require('core-js/fn/promise'); + + if (typeof Uint8Array.from === 'undefined') { + require('core-js/fn/typed/uint8-array'); + } + if (typeof String.prototype.repeat === 'undefined') { + require('core-js/fn/string/repeat'); + } + if (typeof Symbol === 'undefined') { + require('core-js/fn/symbol'); + } + if (typeof Object.assign === 'undefined') { + require('core-js/fn/object/assign'); + } + } catch (e) {} +} /** + * @fileoverview Old browser polyfills + * All are listed as dev dependencies because Node does not need them + * and for browser babel will take care of it + * @requires util + * @module polyfills + */ + +if (typeof TransformStream === 'undefined') { + require('@mattiasbuelens/web-streams-polyfill/es6'); +} +if (typeof TextEncoder === 'undefined') { + const nodeUtil = _util2.default.nodeRequire('util') || {}; + global.TextEncoder = nodeUtil.TextEncoder; + global.TextDecoder = nodeUtil.TextDecoder; +} +if (typeof TextEncoder === 'undefined') { + const textEncoding = require('text-encoding-utf-8'); + global.TextEncoder = textEncoding.TextEncoder; + global.TextDecoder = textEncoding.TextDecoder; +} + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./util":152,"@mattiasbuelens/web-streams-polyfill/es6":1,"core-js/fn/array/fill":"core-js/fn/array/fill","core-js/fn/array/find":"core-js/fn/array/find","core-js/fn/array/from":"core-js/fn/array/from","core-js/fn/array/includes":"core-js/fn/array/includes","core-js/fn/object/assign":"core-js/fn/object/assign","core-js/fn/promise":"core-js/fn/promise","core-js/fn/string/repeat":"core-js/fn/string/repeat","core-js/fn/symbol":"core-js/fn/symbol","core-js/fn/typed/uint8-array":"core-js/fn/typed/uint8-array","text-encoding-utf-8":71,"whatwg-fetch":"whatwg-fetch"}],145:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Signature = Signature; +exports.readArmored = readArmored; +exports.read = read; + +var _armor = require('./encoding/armor'); + +var _armor2 = _interopRequireDefault(_armor); + +var _packet = require('./packet'); + +var _packet2 = _interopRequireDefault(_packet); + +var _enums = require('./enums'); + +var _enums2 = _interopRequireDefault(_enums); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * @class + * @classdesc Class that represents an OpenPGP signature. + * @param {module:packet.List} packetlist The signature packets + */ +function Signature(packetlist) { + if (!(this instanceof Signature)) { + return new Signature(packetlist); + } + this.packets = packetlist || new _packet2.default.List(); +} + +/** + * Returns ASCII armored text of signature + * @returns {ReadableStream} ASCII armor + */ +// GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @requires encoding/armor + * @requires packet + * @requires enums + * @module signature + */ + +Signature.prototype.armor = function () { + return _armor2.default.encode(_enums2.default.armor.signature, this.packets.write()); +}; + +/** + * reads an OpenPGP armored signature and returns a signature object + * @param {String | ReadableStream} armoredText text to be parsed + * @returns {Signature} new signature object + * @async + * @static + */ +async function readArmored(armoredText) { + const input = await _armor2.default.decode(armoredText); + return read(input.data); +} + +/** + * reads an OpenPGP signature as byte array and returns a signature object + * @param {Uint8Array | ReadableStream} input binary signature + * @returns {Signature} new signature object + * @async + * @static + */ +async function read(input) { + const packetlist = new _packet2.default.List(); + await packetlist.read(input); + return new Signature(packetlist); +} + +},{"./encoding/armor":111,"./enums":113,"./packet":125}],146:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _util = require('../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * @constructor + */ +function ECDHSymmetricKey(data) { + if (typeof data === 'undefined') { + data = new Uint8Array([]); + } else if (_util2.default.isString(data)) { + data = _util2.default.str_to_Uint8Array(data); + } else { + data = new Uint8Array(data); + } + this.data = data; +} + +/** + * Read an ECDHSymmetricKey from an Uint8Array + * @param {Uint8Array} input Where to read the encoded symmetric key from + * @returns {Number} Number of read bytes + */ +// OpenPGP.js - An OpenPGP implementation in javascript +// Copyright (C) 2015-2016 Decentral +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * Encoded symmetric key for ECDH + * + * @requires util + * @module type/ecdh_symkey + */ + +ECDHSymmetricKey.prototype.read = function (input) { + if (input.length >= 1) { + const length = input[0]; + if (input.length >= 1 + length) { + this.data = input.subarray(1, 1 + length); + return 1 + this.data.length; + } + } + throw new Error('Invalid symmetric key'); +}; + +/** + * Write an ECDHSymmetricKey as an Uint8Array + * @returns {Uint8Array} An array containing the value + */ +ECDHSymmetricKey.prototype.write = function () { + return _util2.default.concatUint8Array([new Uint8Array([this.data.length]), this.data]); +}; + +ECDHSymmetricKey.fromClone = function (clone) { + return new ECDHSymmetricKey(clone.data); +}; + +exports.default = ECDHSymmetricKey; + +},{"../util":152}],147:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _enums = require('../enums.js'); + +var _enums2 = _interopRequireDefault(_enums); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * @constructor + * @param {enums.hash} hash Hash algorithm + * @param {enums.symmetric} cipher Symmetric algorithm + */ +function KDFParams(data) { + if (data && data.length === 2) { + this.hash = data[0]; + this.cipher = data[1]; + } else { + this.hash = _enums2.default.hash.sha1; + this.cipher = _enums2.default.symmetric.aes128; + } +} + +/** + * Read KDFParams from an Uint8Array + * @param {Uint8Array} input Where to read the KDFParams from + * @returns {Number} Number of read bytes + */ +// OpenPGP.js - An OpenPGP implementation in javascript +// Copyright (C) 2015-2016 Decentral +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * Implementation of type KDF parameters + * + * {@link https://tools.ietf.org/html/rfc6637#section-7|RFC 6637 7}: + * A key derivation function (KDF) is necessary to implement the EC + * encryption. The Concatenation Key Derivation Function (Approved + * Alternative 1) [NIST-SP800-56A] with the KDF hash function that is + * SHA2-256 [FIPS-180-3] or stronger is REQUIRED. + * @requires enums + * @module type/kdf_params + */ + +KDFParams.prototype.read = function (input) { + if (input.length < 4 || input[0] !== 3 || input[1] !== 1) { + throw new Error('Cannot read KDFParams'); + } + this.hash = input[2]; + this.cipher = input[3]; + return 4; +}; + +/** + * Write KDFParams to an Uint8Array + * @returns {Uint8Array} Array with the KDFParams value + */ +KDFParams.prototype.write = function () { + return new Uint8Array([3, 1, this.hash, this.cipher]); +}; + +KDFParams.fromClone = function (clone) { + return new KDFParams([clone.hash, clone.cipher]); +}; + +exports.default = KDFParams; + +},{"../enums.js":113}],148:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _util = require('../util.js'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * @constructor + */ +function Keyid() { + this.bytes = ''; +} + +/** + * Parsing method for a key id + * @param {Uint8Array} input Input to read the key id from + */ +// GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * Implementation of type key id + * + * {@link https://tools.ietf.org/html/rfc4880#section-3.3|RFC4880 3.3}: + * A Key ID is an eight-octet scalar that identifies a key. + * Implementations SHOULD NOT assume that Key IDs are unique. The + * section "Enhanced Key Formats" below describes how Key IDs are + * formed. + * @requires util + * @module type/keyid + */ + +Keyid.prototype.read = function (bytes) { + this.bytes = _util2.default.Uint8Array_to_str(bytes.subarray(0, 8)); +}; + +Keyid.prototype.write = function () { + return _util2.default.str_to_Uint8Array(this.bytes); +}; + +Keyid.prototype.toHex = function () { + return _util2.default.str_to_hex(this.bytes); +}; + +/** + * Checks equality of Key ID's + * @param {Keyid} keyid + * @param {Boolean} matchWildcard Indicates whether to check if either keyid is a wildcard + */ +Keyid.prototype.equals = function (keyid, matchWildcard = false) { + return matchWildcard && (keyid.isWildcard() || this.isWildcard()) || this.bytes === keyid.bytes; +}; + +Keyid.prototype.isNull = function () { + return this.bytes === ''; +}; + +Keyid.prototype.isWildcard = function () { + return (/^0+$/.test(this.toHex()) + ); +}; + +Keyid.mapToHex = function (keyId) { + return keyId.toHex(); +}; + +Keyid.fromClone = function (clone) { + const keyid = new Keyid(); + keyid.bytes = clone.bytes; + return keyid; +}; + +Keyid.fromId = function (hex) { + const keyid = new Keyid(); + keyid.read(_util2.default.hex_to_Uint8Array(hex)); + return keyid; +}; + +Keyid.wildcard = function () { + const keyid = new Keyid(); + keyid.read(new Uint8Array(8)); + return keyid; +}; + +exports.default = Keyid; + +},{"../util.js":152}],149:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _bn = require('bn.js'); + +var _bn2 = _interopRequireDefault(_bn); + +var _util = require('../util'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * @constructor + */ +// GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +// Hint: We hold our MPIs as an array of octets in big endian format preceding a two +// octet scalar: MPI: [a,b,c,d,e,f] +// - MPI size: (a << 8) | b +// - MPI = c | d << 8 | e << ((MPI.length -2)*8) | f ((MPI.length -2)*8) + +/** + * Implementation of type MPI ({@link https://tools.ietf.org/html/rfc4880#section-3.2|RFC4880 3.2}) + * Multiprecision integers (also called MPIs) are unsigned integers used + * to hold large integers such as the ones used in cryptographic + * calculations. + * An MPI consists of two pieces: a two-octet scalar that is the length + * of the MPI in bits followed by a string of octets that contain the + * actual integer. + * @requires bn.js + * @requires util + * @module type/mpi + */ + +function MPI(data) { + /** An implementation dependent integer */ + if (data instanceof MPI) { + this.data = data.data; + } else if (_bn2.default.isBN(data)) { + this.fromBN(data); + } else if (_util2.default.isUint8Array(data)) { + this.fromUint8Array(data); + } else if (_util2.default.isString(data)) { + this.fromString(data); + } else { + this.data = null; + } +} + +/** + * Parsing function for a MPI ({@link https://tools.ietf.org/html/rfc4880#section-3.2|RFC 4880 3.2}). + * @param {Uint8Array} input Payload of MPI data + * @param {String} endian Endianness of the data; 'be' for big-endian or 'le' for little-endian + * @returns {Integer} Length of data read + */ +MPI.prototype.read = function (bytes, endian = 'be') { + if (_util2.default.isString(bytes)) { + bytes = _util2.default.str_to_Uint8Array(bytes); + } + + const bits = bytes[0] << 8 | bytes[1]; + const bytelen = bits + 7 >>> 3; + const payload = bytes.subarray(2, 2 + bytelen); + + this.fromUint8Array(payload, endian); + + return 2 + bytelen; +}; + +/** + * Converts the mpi object to a bytes as specified in + * {@link https://tools.ietf.org/html/rfc4880#section-3.2|RFC4880 3.2} + * @param {String} endian Endianness of the payload; 'be' for big-endian or 'le' for little-endian + * @param {Integer} length Length of the data part of the MPI + * @returns {Uint8Aray} mpi Byte representation + */ +MPI.prototype.write = function (endian, length) { + return _util2.default.Uint8Array_to_MPI(this.toUint8Array(endian, length)); +}; + +MPI.prototype.bitLength = function () { + return (this.data.length - 1) * 8 + _util2.default.nbits(this.data[0]); +}; + +MPI.prototype.byteLength = function () { + return this.data.length; +}; + +MPI.prototype.toUint8Array = function (endian, length) { + endian = endian || 'be'; + length = length || this.data.length; + + const payload = new Uint8Array(length); + const start = length - this.data.length; + if (start < 0) { + throw new Error('Payload is too large.'); + } + + payload.set(this.data, start); + if (endian === 'le') { + payload.reverse(); + } + + return payload; +}; + +MPI.prototype.fromUint8Array = function (bytes, endian = 'be') { + this.data = new Uint8Array(bytes.length); + this.data.set(bytes); + + if (endian === 'le') { + this.data.reverse(); + } +}; + +MPI.prototype.toString = function () { + return _util2.default.Uint8Array_to_str(this.toUint8Array()); +}; + +MPI.prototype.fromString = function (str, endian = 'be') { + this.fromUint8Array(_util2.default.str_to_Uint8Array(str), endian); +}; + +MPI.prototype.toBN = function () { + return new _bn2.default(this.toUint8Array()); +}; + +MPI.prototype.fromBN = function (bn) { + this.data = bn.toArrayLike(Uint8Array); +}; + +MPI.fromClone = function (clone) { + return new MPI(clone.data); +}; + +exports.default = MPI; + +},{"../util":152,"bn.js":16}],150:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _util = require('../util'); + +var _util2 = _interopRequireDefault(_util); + +var _enums = require('../enums'); + +var _enums2 = _interopRequireDefault(_enums); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * @constructor + */ +// OpenPGP.js - An OpenPGP implementation in javascript +// Copyright (C) 2015-2016 Decentral +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * Wrapper to an OID value + * + * {@link https://tools.ietf.org/html/rfc6637#section-11|RFC6637, section 11}: + * The sequence of octets in the third column is the result of applying + * the Distinguished Encoding Rules (DER) to the ASN.1 Object Identifier + * with subsequent truncation. The truncation removes the two fields of + * encoded Object Identifier. The first omitted field is one octet + * representing the Object Identifier tag, and the second omitted field + * is the length of the Object Identifier body. For example, the + * complete ASN.1 DER encoding for the NIST P-256 curve OID is "06 08 2A + * 86 48 CE 3D 03 01 07", from which the first entry in the table above + * is constructed by omitting the first two octets. Only the truncated + * sequence of octets is the valid representation of a curve OID. + * @requires util + * @requires enums + * @module type/oid + */ + +function OID(oid) { + if (oid instanceof OID) { + this.oid = oid.oid; + } else if (_util2.default.isArray(oid) || _util2.default.isUint8Array(oid)) { + oid = new Uint8Array(oid); + if (oid[0] === 0x06) { + // DER encoded oid byte array + if (oid[1] !== oid.length - 2) { + throw new Error('Length mismatch in DER encoded oid'); + } + oid = oid.subarray(2); + } + this.oid = oid; + } else { + this.oid = ''; + } +} + +/** + * Method to read an OID object + * @param {Uint8Array} input Where to read the OID from + * @returns {Number} Number of read bytes + */ +OID.prototype.read = function (input) { + if (input.length >= 1) { + const length = input[0]; + if (input.length >= 1 + length) { + this.oid = input.subarray(1, 1 + length); + return 1 + this.oid.length; + } + } + throw new Error('Invalid oid'); +}; + +/** + * Serialize an OID object + * @returns {Uint8Array} Array with the serialized value the OID + */ +OID.prototype.write = function () { + return _util2.default.concatUint8Array([new Uint8Array([this.oid.length]), this.oid]); +}; + +/** + * Serialize an OID object as a hex string + * @returns {string} String with the hex value of the OID + */ +OID.prototype.toHex = function () { + return _util2.default.Uint8Array_to_hex(this.oid); +}; + +/** + * If a known curve object identifier, return the canonical name of the curve + * @returns {string} String with the canonical name of the curve + */ +OID.prototype.getName = function () { + const hex = this.toHex(); + if (_enums2.default.curve[hex]) { + return _enums2.default.write(_enums2.default.curve, hex); + } else { + throw new Error('Unknown curve object identifier.'); + } +}; + +OID.fromClone = function (clone) { + return new OID(clone.oid); +}; + +exports.default = OID; + +},{"../enums":113,"../util":152}],151:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _config = require('../config'); + +var _config2 = _interopRequireDefault(_config); + +var _crypto = require('../crypto'); + +var _crypto2 = _interopRequireDefault(_crypto); + +var _enums = require('../enums.js'); + +var _enums2 = _interopRequireDefault(_enums); + +var _util = require('../util.js'); + +var _util2 = _interopRequireDefault(_util); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * @constructor + */ +// GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * Implementation of the String-to-key specifier + * + * {@link https://tools.ietf.org/html/rfc4880#section-3.7|RFC4880 3.7}: + * String-to-key (S2K) specifiers are used to convert passphrase strings + * into symmetric-key encryption/decryption keys. They are used in two + * places, currently: to encrypt the secret part of private keys in the + * private keyring, and to convert passphrases to encryption keys for + * symmetrically encrypted messages. + * @requires config + * @requires crypto + * @requires enums + * @requires util + * @module type/s2k + */ + +function S2K() { + /** @type {module:enums.hash} */ + this.algorithm = 'sha256'; + /** @type {module:enums.s2k} */ + this.type = 'iterated'; + /** @type {Integer} */ + this.c = _config2.default.s2k_iteration_count_byte; + /** Eight bytes of salt in a binary string. + * @type {String} + */ + this.salt = null; +} + +S2K.prototype.get_count = function () { + // Exponent bias, defined in RFC4880 + const expbias = 6; + + return 16 + (this.c & 15) << (this.c >> 4) + expbias; +}; + +/** + * Parsing function for a string-to-key specifier ({@link https://tools.ietf.org/html/rfc4880#section-3.7|RFC 4880 3.7}). + * @param {String} input Payload of string-to-key specifier + * @returns {Integer} Actual length of the object + */ +S2K.prototype.read = function (bytes) { + let i = 0; + this.type = _enums2.default.read(_enums2.default.s2k, bytes[i++]); + this.algorithm = bytes[i++]; + if (this.type !== 'gnu') { + this.algorithm = _enums2.default.read(_enums2.default.hash, this.algorithm); + } + + switch (this.type) { + case 'simple': + break; + + case 'salted': + this.salt = bytes.subarray(i, i + 8); + i += 8; + break; + + case 'iterated': + this.salt = bytes.subarray(i, i + 8); + i += 8; + + // Octet 10: count, a one-octet, coded value + this.c = bytes[i++]; + break; + + case 'gnu': + if (_util2.default.Uint8Array_to_str(bytes.subarray(i, i + 3)) === "GNU") { + i += 3; // GNU + const gnuExtType = 1000 + bytes[i++]; + if (gnuExtType === 1001) { + this.type = 'gnu-dummy'; + // GnuPG extension mode 1001 -- don't write secret key at all + } else { + throw new Error("Unknown s2k gnu protection mode."); + } + } else { + throw new Error("Unknown s2k type."); + } + break; + + default: + throw new Error("Unknown s2k type."); + } + + return i; +}; + +/** + * Serializes s2k information + * @returns {Uint8Array} binary representation of s2k + */ +S2K.prototype.write = function () { + if (this.type === 'gnu-dummy') { + return new Uint8Array([101, 0, ..._util2.default.str_to_Uint8Array('GNU'), 1]); + } + + const arr = [new Uint8Array([_enums2.default.write(_enums2.default.s2k, this.type), _enums2.default.write(_enums2.default.hash, this.algorithm)])]; + + switch (this.type) { + case 'simple': + break; + case 'salted': + arr.push(this.salt); + break; + case 'iterated': + arr.push(this.salt); + arr.push(new Uint8Array([this.c])); + break; + case 'gnu': + throw new Error("GNU s2k type not supported."); + default: + throw new Error("Unknown s2k type."); + } + + return _util2.default.concatUint8Array(arr); +}; + +/** + * Produces a key using the specified passphrase and the defined + * hashAlgorithm + * @param {String} passphrase Passphrase containing user input + * @returns {Uint8Array} Produced key with a length corresponding to + * hashAlgorithm hash length + */ +S2K.prototype.produce_key = async function (passphrase, numBytes) { + passphrase = _util2.default.encode_utf8(passphrase); + + async function round(prefix, s2k) { + const algorithm = _enums2.default.write(_enums2.default.hash, s2k.algorithm); + + switch (s2k.type) { + case 'simple': + return _crypto2.default.hash.digest(algorithm, _util2.default.concatUint8Array([prefix, passphrase])); + + case 'salted': + return _crypto2.default.hash.digest(algorithm, _util2.default.concatUint8Array([prefix, s2k.salt, passphrase])); + + case 'iterated': + { + const count = s2k.get_count(); + const data = _util2.default.concatUint8Array([s2k.salt, passphrase]); + const datalen = data.length; + const isp = new Uint8Array(prefix.length + count + datalen); + isp.set(prefix); + for (let pos = prefix.length; pos < count; pos += datalen) { + isp.set(data, pos); + } + return _crypto2.default.hash.digest(algorithm, isp.subarray(0, prefix.length + count)); + } + case 'gnu': + throw new Error("GNU s2k type not supported."); + + default: + throw new Error("Unknown s2k type."); + } + } + + const arr = []; + let rlength = 0; + const prefix = new Uint8Array(numBytes); + + for (let i = 0; i < numBytes; i++) { + prefix[i] = 0; + } + + let i = 0; + while (rlength < numBytes) { + const result = await round(prefix.subarray(0, i), this); + arr.push(result); + rlength += result.length; + i++; + } + + return _util2.default.concatUint8Array(arr).subarray(0, numBytes); +}; + +S2K.fromClone = function (clone) { + const s2k = new S2K(); + s2k.algorithm = clone.algorithm; + s2k.type = clone.type; + s2k.c = clone.c; + s2k.salt = clone.salt; + return s2k; +}; + +exports.default = S2K; + +},{"../config":79,"../crypto":94,"../enums.js":113,"../util.js":152}],152:[function(require,module,exports){ +(function (global){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _emailAddresses = require('email-addresses'); + +var _emailAddresses2 = _interopRequireDefault(_emailAddresses); + +var _webStreamTools = require('web-stream-tools'); + +var _webStreamTools2 = _interopRequireDefault(_webStreamTools); + +var _config = require('./config'); + +var _config2 = _interopRequireDefault(_config); + +var _util = require('./util'); + +var _util2 = _interopRequireDefault(_util); + +var _base = require('./encoding/base64'); + +var _base2 = _interopRequireDefault(_base); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = { + isString: function isString(data) { + return typeof data === 'string' || String.prototype.isPrototypeOf(data); + }, + + isArray: function isArray(data) { + return Array.prototype.isPrototypeOf(data); + }, + + isUint8Array: _webStreamTools2.default.isUint8Array, + + isStream: _webStreamTools2.default.isStream, + + /** + * Get transferable objects to pass buffers with zero copy (similar to "pass by reference" in C++) + * See: https://developer.mozilla.org/en-US/docs/Web/API/Worker/postMessage + * Also, convert ReadableStreams to MessagePorts + * @param {Object} obj the options object to be passed to the web worker + * @returns {Array} an array of binary data to be passed + */ + getTransferables: function getTransferables(obj, zero_copy) { + const transferables = []; + _util2.default.collectTransferables(obj, transferables, zero_copy); + return transferables.length ? transferables : undefined; + }, + + collectTransferables: function collectTransferables(obj, collection, zero_copy) { + if (!obj) { + return; + } + + if (_util2.default.isUint8Array(obj)) { + if (zero_copy && collection.indexOf(obj.buffer) === -1 && !(navigator.userAgent.indexOf('Version/11.1') !== -1 || // Safari 11.1 + (navigator.userAgent.match(/Chrome\/(\d+)/) || [])[1] < 56 && navigator.userAgent.indexOf('Edge') === -1 // Chrome < 56 + )) { + collection.push(obj.buffer); + } + return; + } + if (Object.prototype.isPrototypeOf(obj)) { + Object.entries(obj).forEach(([key, value]) => { + // recursively search all children + if (_util2.default.isStream(value)) { + if (value.locked) { + obj[key] = null; + } else { + const transformed = _webStreamTools2.default.transformPair(value, async readable => { + const reader = _webStreamTools2.default.getReader(readable); + + var _ref = new MessageChannel(); + + const port1 = _ref.port1, + port2 = _ref.port2; + + port1.onmessage = async function ({ data: { action } }) { + if (action === 'read') { + try { + const result = await reader.read(); + port1.postMessage(result, _util2.default.getTransferables(result)); + } catch (e) { + port1.postMessage({ error: e.message }); + } + } else if (action === 'cancel') { + await transformed.cancel(); + port1.postMessage(); + } + }; + obj[key] = port2; + collection.push(port2); + }); + } + return; + } + if (Object.prototype.toString.call(value) === '[object MessagePort]') { + throw new Error("Can't transfer the same stream twice."); + } + _util2.default.collectTransferables(value, collection, zero_copy); + }); + } + }, + + /** + * Convert MessagePorts back to ReadableStreams + * @param {Object} obj + * @returns {Object} + */ + restoreStreams: function restoreStreams(obj) { + if (Object.prototype.isPrototypeOf(obj) && !Uint8Array.prototype.isPrototypeOf(obj)) { + Object.entries(obj).forEach(([key, value]) => { + // recursively search all children + if (Object.prototype.toString.call(value) === '[object MessagePort]') { + obj[key] = new ReadableStream({ + pull(controller) { + return new Promise(resolve => { + value.onmessage = evt => { + var _evt$data = evt.data; + const done = _evt$data.done, + value = _evt$data.value, + error = _evt$data.error; + + if (error) { + controller.error(new Error(error)); + } else if (!done) { + controller.enqueue(value); + } else { + controller.close(); + } + resolve(); + }; + value.postMessage({ action: 'read' }); + }); + }, + cancel() { + return new Promise(resolve => { + value.onmessage = resolve; + value.postMessage({ action: 'cancel' }); + }); + } + }, { highWaterMark: 0 }); + return; + } + _util2.default.restoreStreams(value); + }); + } + return obj; + }, + + readNumber: function readNumber(bytes) { + let n = 0; + for (let i = 0; i < bytes.length; i++) { + n += 256 ** i * bytes[bytes.length - 1 - i]; + } + return n; + }, + + writeNumber: function writeNumber(n, bytes) { + const b = new Uint8Array(bytes); + for (let i = 0; i < bytes; i++) { + b[i] = n >> 8 * (bytes - i - 1) & 0xFF; + } + + return b; + }, + + readDate: function readDate(bytes) { + const n = _util2.default.readNumber(bytes); + const d = new Date(n * 1000); + return d; + }, + + writeDate: function writeDate(time) { + const numeric = Math.floor(time.getTime() / 1000); + + return _util2.default.writeNumber(numeric, 4); + }, + + normalizeDate: function normalizeDate(time = Date.now()) { + return time === null || time === Infinity ? time : new Date(Math.floor(+time / 1000) * 1000); + }, + + /** + * Create hex string from a binary + * @param {String} str String to convert + * @returns {String} String containing the hexadecimal values + */ + str_to_hex: function str_to_hex(str) { + if (str === null) { + return ""; + } + const r = []; + const e = str.length; + let c = 0; + let h; + while (c < e) { + h = str.charCodeAt(c++).toString(16); + while (h.length < 2) { + h = "0" + h; + } + r.push("" + h); + } + return r.join(''); + }, + + /** + * Create binary string from a hex encoded string + * @param {String} str Hex string to convert + * @returns {String} + */ + hex_to_str: function hex_to_str(hex) { + let str = ''; + for (let i = 0; i < hex.length; i += 2) { + str += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); + } + return str; + }, + + /** + * Convert a Uint8Array to an MPI-formatted Uint8Array. + * Note: the output is **not** an MPI object. + * @see {@link module:type/mpi/MPI.fromUint8Array} + * @see {@link module:type/mpi/MPI.toUint8Array} + * @param {Uint8Array} bin An array of 8-bit integers to convert + * @returns {Uint8Array} MPI-formatted Uint8Array + */ + Uint8Array_to_MPI: function Uint8Array_to_MPI(bin) { + const size = (bin.length - 1) * 8 + _util2.default.nbits(bin[0]); + const prefix = Uint8Array.from([(size & 0xFF00) >> 8, size & 0xFF]); + return _util2.default.concatUint8Array([prefix, bin]); + }, + + /** + * Convert a Base-64 encoded string an array of 8-bit integer + * + * Note: accepts both Radix-64 and URL-safe strings + * @param {String} base64 Base-64 encoded string to convert + * @returns {Uint8Array} An array of 8-bit integers + */ + b64_to_Uint8Array: function b64_to_Uint8Array(base64) { + return _base2.default.decode(base64.replace(/-/g, '+').replace(/_/g, '/')); + }, + + /** + * Convert an array of 8-bit integer to a Base-64 encoded string + * @param {Uint8Array} bytes An array of 8-bit integers to convert + * @param {bool} url If true, output is URL-safe + * @returns {String} Base-64 encoded string + */ + Uint8Array_to_b64: function Uint8Array_to_b64(bytes, url) { + return _base2.default.encode(bytes, url).replace(/(\n)/g, ''); + }, + + /** + * Convert a hex string to an array of 8-bit integers + * @param {String} hex A hex string to convert + * @returns {Uint8Array} An array of 8-bit integers + */ + hex_to_Uint8Array: function hex_to_Uint8Array(hex) { + const result = new Uint8Array(hex.length >> 1); + for (let k = 0; k < hex.length >> 1; k++) { + result[k] = parseInt(hex.substr(k << 1, 2), 16); + } + return result; + }, + + /** + * Convert an array of 8-bit integers to a hex string + * @param {Uint8Array} bytes Array of 8-bit integers to convert + * @returns {String} Hexadecimal representation of the array + */ + Uint8Array_to_hex: function Uint8Array_to_hex(bytes) { + const r = []; + const e = bytes.length; + let c = 0; + let h; + while (c < e) { + h = bytes[c++].toString(16); + while (h.length < 2) { + h = "0" + h; + } + r.push("" + h); + } + return r.join(''); + }, + + /** + * Convert a string to an array of 8-bit integers + * @param {String} str String to convert + * @returns {Uint8Array} An array of 8-bit integers + */ + str_to_Uint8Array: function str_to_Uint8Array(str) { + return _webStreamTools2.default.transform(str, str => { + if (!_util2.default.isString(str)) { + throw new Error('str_to_Uint8Array: Data must be in the form of a string'); + } + + const result = new Uint8Array(str.length); + for (let i = 0; i < str.length; i++) { + result[i] = str.charCodeAt(i); + } + return result; + }); + }, + + /** + * Convert an array of 8-bit integers to a string + * @param {Uint8Array} bytes An array of 8-bit integers to convert + * @returns {String} String representation of the array + */ + Uint8Array_to_str: function Uint8Array_to_str(bytes) { + bytes = new Uint8Array(bytes); + const result = []; + const bs = 1 << 14; + const j = bytes.length; + + for (let i = 0; i < j; i += bs) { + result.push(String.fromCharCode.apply(String, bytes.subarray(i, i + bs < j ? i + bs : j))); + } + return result.join(''); + }, + + /** + * Convert a native javascript string to a Uint8Array of utf8 bytes + * @param {String|ReadableStream} str The string to convert + * @returns {Uint8Array|ReadableStream} A valid squence of utf8 bytes + */ + encode_utf8: function encode_utf8(str) { + const encoder = new TextEncoder('utf-8'); + // eslint-disable-next-line no-inner-declarations + function process(value, lastChunk = false) { + return encoder.encode(value, { stream: !lastChunk }); + } + return _webStreamTools2.default.transform(str, process, () => process('', true)); + }, + + /** + * Convert a Uint8Array of utf8 bytes to a native javascript string + * @param {Uint8Array|ReadableStream} utf8 A valid squence of utf8 bytes + * @returns {String|ReadableStream} A native javascript string + */ + decode_utf8: function decode_utf8(utf8) { + const decoder = new TextDecoder('utf-8'); + // eslint-disable-next-line no-inner-declarations + function process(value, lastChunk = false) { + return decoder.decode(value, { stream: !lastChunk }); + } + return _webStreamTools2.default.transform(utf8, process, () => process(new Uint8Array(), true)); + }, + + /** + * Concat a list of Uint8Arrays, Strings or Streams + * The caller must not mix Uint8Arrays with Strings, but may mix Streams with non-Streams. + * @param {Array} Array of Uint8Arrays/Strings/Streams to concatenate + * @returns {Uint8Array|String|ReadableStream} Concatenated array + */ + concat: _webStreamTools2.default.concat, + + /** + * Concat Uint8Arrays + * @param {Array} Array of Uint8Arrays to concatenate + * @returns {Uint8Array} Concatenated array + */ + concatUint8Array: _webStreamTools2.default.concatUint8Array, + + /** + * Check Uint8Array equality + * @param {Uint8Array} first array + * @param {Uint8Array} second array + * @returns {Boolean} equality + */ + equalsUint8Array: function equalsUint8Array(array1, array2) { + if (!_util2.default.isUint8Array(array1) || !_util2.default.isUint8Array(array2)) { + throw new Error('Data must be in the form of a Uint8Array'); + } + + if (array1.length !== array2.length) { + return false; + } + + for (let i = 0; i < array1.length; i++) { + if (array1[i] !== array2[i]) { + return false; + } + } + return true; + }, + + /** + * Calculates a 16bit sum of a Uint8Array by adding each character + * codes modulus 65535 + * @param {Uint8Array} Uint8Array to create a sum of + * @returns {Uint8Array} 2 bytes containing the sum of all charcodes % 65535 + */ + write_checksum: function write_checksum(text) { + let s = 0; + for (let i = 0; i < text.length; i++) { + s = s + text[i] & 0xFFFF; + } + return _util2.default.writeNumber(s, 2); + }, + + /** + * Helper function to print a debug message. Debug + * messages are only printed if + * @link module:config/config.debug is set to true. + * @param {String} str String of the debug message + */ + print_debug: function print_debug(str) { + if (_config2.default.debug) { + console.log(str); + } + }, + + /** + * Helper function to print a debug message. Debug + * messages are only printed if + * @link module:config/config.debug is set to true. + * Different than print_debug because will call Uint8Array_to_hex iff necessary. + * @param {String} str String of the debug message + */ + print_debug_hexarray_dump: function print_debug_hexarray_dump(str, arrToHex) { + if (_config2.default.debug) { + str += ': ' + _util2.default.Uint8Array_to_hex(arrToHex); + console.log(str); + } + }, + + /** + * Helper function to print a debug message. Debug + * messages are only printed if + * @link module:config/config.debug is set to true. + * Different than print_debug because will call str_to_hex iff necessary. + * @param {String} str String of the debug message + */ + print_debug_hexstr_dump: function print_debug_hexstr_dump(str, strToHex) { + if (_config2.default.debug) { + str += _util2.default.str_to_hex(strToHex); + console.log(str); + } + }, + + /** + * Helper function to print a debug error. Debug + * messages are only printed if + * @link module:config/config.debug is set to true. + * @param {String} str String of the debug message + */ + print_debug_error: function print_debug_error(error) { + if (_config2.default.debug) { + console.error(error); + } + }, + + /** + * Read a stream to the end and print it to the console when it's closed. + * @param {String} str String of the debug message + * @param {ReadableStream|Uint8array|String} input Stream to print + * @param {Function} concat Function to concatenate chunks of the stream (defaults to util.concat). + */ + print_entire_stream: function print_entire_stream(str, input, concat) { + _webStreamTools2.default.readToEnd(_webStreamTools2.default.clone(input), concat).then(result => { + console.log(str + ': ', result); + }); + }, + + // returns bit length of the integer x + nbits: function nbits(x) { + let r = 1; + let t = x >>> 16; + if (t !== 0) { + x = t; + r += 16; + } + t = x >> 8; + if (t !== 0) { + x = t; + r += 8; + } + t = x >> 4; + if (t !== 0) { + x = t; + r += 4; + } + t = x >> 2; + if (t !== 0) { + x = t; + r += 2; + } + t = x >> 1; + if (t !== 0) { + x = t; + r += 1; + } + return r; + }, + + /** + * If S[1] == 0, then double(S) == (S[2..128] || 0); + * otherwise, double(S) == (S[2..128] || 0) xor + * (zeros(120) || 10000111). + * + * Both OCB and EAX (through CMAC) require this function to be constant-time. + * + * @param {Uint8Array} data + */ + double: function double(data) { + const double_var = new Uint8Array(data.length); + const last = data.length - 1; + for (let i = 0; i < last; i++) { + double_var[i] = data[i] << 1 ^ data[i + 1] >> 7; + } + double_var[last] = data[last] << 1 ^ (data[0] >> 7) * 0x87; + return double_var; + }, + + /** + * Shift a Uint8Array to the right by n bits + * @param {Uint8Array} array The array to shift + * @param {Integer} bits Amount of bits to shift (MUST be smaller + * than 8) + * @returns {String} Resulting array. + */ + shiftRight: function shiftRight(array, bits) { + if (bits) { + for (let i = array.length - 1; i >= 0; i--) { + array[i] >>= bits; + if (i > 0) { + array[i] |= array[i - 1] << 8 - bits; + } + } + } + return array; + }, + + /** + * Get native Web Cryptography api, only the current version of the spec. + * The default configuration is to use the api when available. But it can + * be deactivated with config.use_native + * @returns {Object} The SubtleCrypto api or 'undefined' + */ + getWebCrypto: function getWebCrypto() { + if (!_config2.default.use_native) { + return; + } + + return typeof window !== 'undefined' && window.crypto && window.crypto.subtle; + }, + + /** + * Get native Web Cryptography api for all browsers, including legacy + * implementations of the spec e.g IE11 and Safari 8/9. The default + * configuration is to use the api when available. But it can be deactivated + * with config.use_native + * @returns {Object} The SubtleCrypto api or 'undefined' + */ + getWebCryptoAll: function getWebCryptoAll() { + if (!_config2.default.use_native) { + return; + } + + if (typeof window !== 'undefined') { + if (window.crypto) { + return window.crypto.subtle || window.crypto.webkitSubtle; + } + if (window.msCrypto) { + return window.msCrypto.subtle; + } + } + }, + + /** + * Detect Node.js runtime. + */ + detectNode: function detectNode() { + return typeof global.process === 'object' && typeof global.process.versions === 'object'; + }, + + /** + * Get native Node.js module + * @param {String} The module to require + * @returns {Object} The required module or 'undefined' + */ + nodeRequire: function nodeRequire(module) { + if (!_util2.default.detectNode()) { + return; + } + + // Requiring the module dynamically allows us to access the native node module. + // otherwise, it gets replaced with the browserified version + // eslint-disable-next-line import/no-dynamic-require + return require(module); + }, + + /** + * Get native Node.js crypto api. The default configuration is to use + * the api when available. But it can also be deactivated with config.use_native + * @returns {Object} The crypto module or 'undefined' + */ + getNodeCrypto: function getNodeCrypto() { + if (!_config2.default.use_native) { + return; + } + + return _util2.default.nodeRequire('crypto'); + }, + + getNodeZlib: function getNodeZlib() { + if (!_config2.default.use_native) { + return; + } + + return _util2.default.nodeRequire('zlib'); + }, + + /** + * Get native Node.js Buffer constructor. This should be used since + * Buffer is not available under browserify. + * @returns {Function} The Buffer constructor or 'undefined' + */ + getNodeBuffer: function getNodeBuffer() { + return (_util2.default.nodeRequire('buffer') || {}).Buffer; + }, + + getNodeStream: function getNodeStream() { + return (_util2.default.nodeRequire('stream') || {}).Readable; + }, + + getHardwareConcurrency: function getHardwareConcurrency() { + if (_util2.default.detectNode()) { + const os = _util2.default.nodeRequire('os'); + return os.cpus().length; + } + + return navigator.hardwareConcurrency || 1; + }, + + isEmailAddress: function isEmailAddress(data) { + if (!_util2.default.isString(data)) { + return false; + } + const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+([a-zA-Z]{2,}|xn--[a-zA-Z\-0-9]+)))$/; + return re.test(data); + }, + + /** + * Format user id for internal use. + */ + formatUserId: function formatUserId(id) { + // name, email address and comment can be empty but must be of the correct type + if (id.name && !_util2.default.isString(id.name) || id.email && !_util2.default.isEmailAddress(id.email) || id.comment && !_util2.default.isString(id.comment)) { + throw new Error('Invalid user id format'); + } + const components = []; + if (id.name) { + components.push(id.name); + } + if (id.comment) { + components.push(`(${id.comment})`); + } + if (id.email) { + components.push(`<${id.email}>`); + } + return components.join(' '); + }, + + /** + * Parse user id. + */ + parseUserId: function parseUserId(userid) { + if (userid.length > _config2.default.max_userid_length) { + throw new Error('User id string is too long'); + } + try { + var _emailAddresses$parse = _emailAddresses2.default.parseOneAddress(userid); + + const name = _emailAddresses$parse.name, + email = _emailAddresses$parse.address, + comments = _emailAddresses$parse.comments; + + return { name, email, comment: comments.replace(/^\(|\)$/g, '') }; + } catch (e) { + throw new Error('Invalid user id format'); + } + }, + + /** + * Normalize line endings to \r\n + */ + canonicalizeEOL: function canonicalizeEOL(text) { + return _webStreamTools2.default.transform(_util2.default.nativeEOL(text), value => value.replace(/\r/g, "\n").replace(/\n/g, "\r\n")); + }, + + /** + * Convert line endings from canonicalized \r\n to native \n + */ + nativeEOL: function nativeEOL(text) { + let lastChar = ''; + return _webStreamTools2.default.transform(text, value => { + value = lastChar + value; + if (value[value.length - 1] === '\r') { + lastChar = '\r'; + value = value.slice(0, -1); + } else { + lastChar = ''; + } + return value.replace(/\r\n/g, '\n'); + }, () => lastChar); + }, + + /** + * Remove trailing spaces and tabs from each line + */ + removeTrailingSpaces: function removeTrailingSpaces(text) { + return text.split('\n').map(line => { + let i = line.length - 1; + for (; i >= 0 && (line[i] === ' ' || line[i] === '\t'); i--); + return line.substr(0, i + 1); + }).join('\n'); + }, + + /** + * Encode input buffer using Z-Base32 encoding. + * See: https://tools.ietf.org/html/rfc6189#section-5.1.6 + * + * @param {Uint8Array} data The binary data to encode + * @returns {String} Binary data encoded using Z-Base32 + */ + encodeZBase32: function encodeZBase32(data) { + if (data.length === 0) { + return ""; + } + const ALPHABET = "ybndrfg8ejkmcpqxot1uwisza345h769"; + const SHIFT = 5; + const MASK = 31; + let buffer = data[0]; + let index = 1; + let bitsLeft = 8; + let result = ''; + while (bitsLeft > 0 || index < data.length) { + if (bitsLeft < SHIFT) { + if (index < data.length) { + buffer <<= 8; + buffer |= data[index++] & 0xff; + bitsLeft += 8; + } else { + const pad = SHIFT - bitsLeft; + buffer <<= pad; + bitsLeft += pad; + } + } + bitsLeft -= SHIFT; + result += ALPHABET[MASK & buffer >> bitsLeft]; + } + return result; + } +}; // re-import module to access util functions +// GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/* eslint-disable no-console */ + +/** + * This object contains utility functions + * @requires email-addresses + * @requires web-stream-tools + * @requires config + * @requires encoding/base64 + * @module util + */ + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./config":79,"./encoding/base64":112,"./util":152,"email-addresses":33,"web-stream-tools":75}],153:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); // OpenPGP.js - An OpenPGP implementation in javascript +// Copyright (C) 2018 Wiktor Kwapisiewicz +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @fileoverview This class implements a client for the Web Key Directory (wkd) protocol + * in order to lookup keys on designated servers. + * See: https://datatracker.ietf.org/doc/draft-koch-openpgp-webkey-service/ + * @module wkd + */ + +var _util = require('./util'); + +var _util2 = _interopRequireDefault(_util); + +var _crypto = require('./crypto'); + +var _crypto2 = _interopRequireDefault(_crypto); + +var _key = require('./key'); + +var keyMod = _interopRequireWildcard(_key); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Initialize the WKD client + * @constructor + */ +function WKD() { + this._fetch = typeof window !== 'undefined' ? window.fetch : require('node-fetch'); +} + +/** + * Search for a public key using Web Key Directory protocol. + * @param {String} options.email User's email. + * @param {Boolean} options.rawBytes Returns Uint8Array instead of parsed key. + * @returns {Promise, + * err: (Array|null)}>} The public key. + * @async + */ +WKD.prototype.lookup = async function (options) { + const fetch = this._fetch; + + if (!options.email) { + throw new Error('You must provide an email parameter!'); + } + + if (!_util2.default.isEmailAddress(options.email)) { + throw new Error('Invalid e-mail address.'); + } + + var _$exec = /(.*)@(.*)/.exec(options.email), + _$exec2 = _slicedToArray(_$exec, 3); + + const localPart = _$exec2[1], + domain = _$exec2[2]; + + const localEncoded = _util2.default.encodeZBase32((await _crypto2.default.hash.sha1(_util2.default.str_to_Uint8Array(localPart.toLowerCase())))); + + const url = `https://${domain}/.well-known/openpgpkey/hu/${localEncoded}`; + + return fetch(url).then(function (response) { + if (response.status === 200) { + return response.arrayBuffer(); + } + }).then(function (publicKey) { + if (publicKey) { + const rawBytes = new Uint8Array(publicKey); + if (options.rawBytes) { + return rawBytes; + } + return keyMod.read(rawBytes); + } + }); +}; + +exports.default = WKD; + +},{"./crypto":94,"./key":116,"./util":152,"node-fetch":"node-fetch"}],154:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _util = require('../util.js'); + +var _util2 = _interopRequireDefault(_util); + +var _config = require('../config'); + +var _config2 = _interopRequireDefault(_config); + +var _crypto = require('../crypto'); + +var _crypto2 = _interopRequireDefault(_crypto); + +var _packet = require('../packet'); + +var _packet2 = _interopRequireDefault(_packet); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Initializes a new proxy and loads the web worker + * @param {String} path The path to the worker or 'openpgp.worker.js' by default + * @param {Number} n number of workers to initialize if path given + * @param {Object} config config The worker configuration + * @param {Array} worker alternative to path parameter: web worker initialized with 'openpgp.worker.js' + * @constructor + */ +// GPG4Browsers - An OpenPGP implementation in javascript +// Copyright (C) 2011 Recurity Labs GmbH +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * @fileoverview Provides functions for maintaining browser workers + * @see module:openpgp.initWorker + * @see module:openpgp.getWorker + * @see module:openpgp.destroyWorker + * @see module:worker/worker + * @requires util + * @requires config + * @requires crypto + * @requires packet + * @module worker/async_proxy + */ + +function AsyncProxy({ path = 'openpgp.worker.js', n = 1, workers = [], config } = {}) { + /** + * Message handling + */ + const handleMessage = workerId => event => { + const msg = event.data; + switch (msg.event) { + case 'loaded': + this.workers[workerId].loadedResolve(true); + break; + case 'method-return': + if (msg.err) { + // fail + const err = new Error(msg.err); + // add worker stack + err.workerStack = msg.stack; + this.tasks[msg.id].reject(err); + } else { + // success + this.tasks[msg.id].resolve(msg.data); + } + delete this.tasks[msg.id]; + this.workers[workerId].requests--; + break; + case 'request-seed': + this.seedRandom(workerId, msg.amount); + break; + default: + throw new Error('Unknown Worker Event.'); + } + }; + + if (workers.length) { + this.workers = workers; + } else { + this.workers = []; + while (this.workers.length < n) { + this.workers.push(new Worker(path)); + } + } + + let workerId = 0; + this.workers.forEach(worker => { + worker.loadedPromise = new Promise(resolve => { + worker.loadedResolve = resolve; + }); + worker.requests = 0; + worker.onmessage = handleMessage(workerId++); + worker.onerror = e => { + worker.loadedResolve(false); + console.error('Unhandled error in openpgp worker: ' + e.message + ' (' + e.filename + ':' + e.lineno + ')'); + return false; + }; + + if (config) { + worker.postMessage({ event: 'configure', config }); + } + }); + + // Cannot rely on task order being maintained, use object keyed by request ID to track tasks + this.tasks = {}; + this.currentID = 0; +} + +/** + * Returns a promise that resolves when all workers have finished loading + * @returns {Promise} Resolves to true if all workers have loaded succesfully; false otherwise +*/ +AsyncProxy.prototype.loaded = async function () { + const loaded = await Promise.all(this.workers.map(worker => worker.loadedPromise)); + return loaded.every(Boolean); +}; + +/** + * Get new request ID + * @returns {integer} New unique request ID +*/ +AsyncProxy.prototype.getID = function () { + return this.currentID++; +}; + +/** + * Send message to worker with random data + * @param {Integer} size Number of bytes to send + * @async + */ +AsyncProxy.prototype.seedRandom = async function (workerId, size) { + const buf = await _crypto2.default.random.getRandomBytes(size); + this.workers[workerId].postMessage({ event: 'seed-random', buf }, _util2.default.getTransferables(buf, true)); +}; + +/** + * Terminates the workers + */ +AsyncProxy.prototype.terminate = function () { + this.workers.forEach(worker => { + worker.terminate(); + }); +}; + +/** + * Generic proxy function that handles all commands from the public api. + * @param {String} method the public api function to be delegated to the worker thread + * @param {Object} options the api function's options + * @returns {Promise} see the corresponding public api functions for their return types + * @async + */ +AsyncProxy.prototype.delegate = function (method, options) { + + const id = this.getID(); + const requests = this.workers.map(worker => worker.requests); + const minRequests = Math.min(...requests); + let workerId = 0; + for (; workerId < this.workers.length; workerId++) { + if (this.workers[workerId].requests === minRequests) { + break; + } + } + + return new Promise((_resolve, reject) => { + // clone packets (for web worker structured cloning algorithm) + this.workers[workerId].postMessage({ id: id, event: method, options: _packet2.default.clone.clonePackets(options) }, _util2.default.getTransferables(options, _config2.default.zero_copy)); + this.workers[workerId].requests++; + + // remember to handle parsing cloned packets from worker + this.tasks[id] = { resolve: data => _resolve(_packet2.default.clone.parseClonedPackets(_util2.default.restoreStreams(data), method)), reject }; + }); +}; + +exports.default = AsyncProxy; + +},{"../config":79,"../crypto":94,"../packet":125,"../util.js":152}]},{},[115])(115) +}); From 8d22994074dc1586a9899f8cf49baaccc8ccf965 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 3 Feb 2022 21:08:35 +0200 Subject: [PATCH 004/179] wip --- Core/source/core/pgp-key.ts | 36 +++++++++++------------ Core/source/core/pgp-msg.ts | 14 ++++----- Core/source/core/pgp.ts | 8 ++--- Core/source/core/types/openpgp.d.ts | 19 +++++++----- Core/source/mobile-interface/endpoints.ts | 2 +- Core/source/platform/store.ts | 14 +++++---- 6 files changed, 49 insertions(+), 44 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index 358b9a9b7..aa713b1f4 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -32,8 +32,8 @@ export interface PrvKeyInfo { private: string; longid: string; passphrase?: string; - decrypted?: OpenPGP.key.Key; // only for internal use in this file - parsed?: OpenPGP.key.Key; // only for internal use in this file + decrypted?: OpenPGP.Key; // only for internal use in this file + parsed?: OpenPGP.Key; // only for internal use in this file } export type KeyAlgo = 'curve25519' | 'rsa2048' | 'rsa4096'; @@ -105,8 +105,8 @@ export class PgpKey { /** * Read many keys, could be armored or binary, in single armor or separately, useful for importing keychains of various formats */ - public static readMany = async (fileData: Buf): Promise<{ keys: OpenPGP.key.Key[], errs: Error[] }> => { - const allKeys: OpenPGP.key.Key[] = []; + public static readMany = async (fileData: Buf): Promise<{ keys: OpenPGP.Key[], errs: Error[] }> => { + const allKeys: OpenPGP.Key[] = []; const allErrs: Error[] = []; const { blocks } = MsgBlockParser.detectBlocks(fileData.toUtfStr()); const armoredPublicKeyBlocks = blocks.filter(block => block.type === 'publicKey' || block.type === 'privateKey'); @@ -134,7 +134,7 @@ export class PgpKey { return p.tag === openpgp.enums.packet.secretKey || p.tag === openpgp.enums.packet.secretSubkey; } - public static decrypt = async (prv: OpenPGP.key.Key, passphrase: string, optionalKeyid?: OpenPGP.Keyid, optionalBehaviorFlag?: 'OK-IF-ALREADY-DECRYPTED'): Promise => { + public static decrypt = async (prv: OpenPGP.Key, passphrase: string, optionalKeyid?: OpenPGP.Keyid, optionalBehaviorFlag?: 'OK-IF-ALREADY-DECRYPTED'): Promise => { if (!prv.isPrivate()) { throw new Error("Nothing to decrypt in a public key"); } @@ -162,7 +162,7 @@ export class PgpKey { return true; } - public static encrypt = async (prv: OpenPGP.key.Key, passphrase: string) => { + public static encrypt = async (prv: OpenPGP.Key, passphrase: string) => { if (!passphrase || passphrase === 'undefined' || passphrase === 'null') { throw new Error(`Encryption passphrase should not be empty:${typeof passphrase}:${passphrase}`); } @@ -177,16 +177,16 @@ export class PgpKey { await prv.encrypt(passphrase); } - public static normalize = async (armored: string): Promise<{ normalized: string, keys: OpenPGP.key.Key[] }> => { + public static normalize = async (armored: string): Promise<{ normalized: string, keys: OpenPGP.Key[] }> => { try { - let keys: OpenPGP.key.Key[] = []; + let keys: OpenPGP.Key[] = []; armored = PgpArmor.normalize(armored, 'key'); if (RegExp(PgpArmor.headers('publicKey', 're').begin).test(armored)) { keys = (await openpgp.key.readArmored(armored)).keys; } else if (RegExp(PgpArmor.headers('privateKey', 're').begin).test(armored)) { keys = (await openpgp.key.readArmored(armored)).keys; } else if (RegExp(PgpArmor.headers('encryptedMsg', 're').begin).test(armored)) { - keys = [new openpgp.key.Key((await openpgp.message.readArmored(armored)).packets)]; + keys = [new OpenPGP.Key((await openpgp.message.readArmored(armored)).packets)]; } for (const k of keys) { for (const u of k.users) { @@ -200,10 +200,10 @@ export class PgpKey { } } - public static fingerprint = async (key: OpenPGP.key.Key | string, formatting: "default" | "spaced" = 'default'): Promise => { + public static fingerprint = async (key: OpenPGP.Key | string, formatting: "default" | "spaced" = 'default'): Promise => { if (!key) { return undefined; - } else if (key instanceof openpgp.key.Key) { + } else if (key instanceof OpenPGP.Key) { if (!key.primaryKey.getFingerprintBytes()) { return undefined; } @@ -230,7 +230,7 @@ export class PgpKey { } } - public static longid = async (keyOrFingerprintOrBytes: string | OpenPGP.key.Key | undefined): Promise => { + public static longid = async (keyOrFingerprintOrBytes: string | OpenPGP.Key | undefined): Promise => { if (!keyOrFingerprintOrBytes) { return undefined; } else if (typeof keyOrFingerprintOrBytes === 'string' && keyOrFingerprintOrBytes.length === 8) { @@ -268,7 +268,7 @@ export class PgpKey { return await PgpKey.usableButExpired(pubkey); } - public static expired = async (key: OpenPGP.key.Key): Promise => { + public static expired = async (key: OpenPGP.Key): Promise => { if (!key) { return false; } @@ -282,7 +282,7 @@ export class PgpKey { throw new Error(`Got unexpected value for expiration: ${exp}`); // exp must be either null, Infinity or a Date } - public static usableButExpired = async (key: OpenPGP.key.Key): Promise => { + public static usableButExpired = async (key: OpenPGP.Key): Promise => { if (!key) { return false; } @@ -297,7 +297,7 @@ export class PgpKey { return Boolean(await key.getEncryptionKey(undefined, oneSecondBeforeExpiration)); } - public static dateBeforeExpiration = async (key: OpenPGP.key.Key | string): Promise => { + public static dateBeforeExpiration = async (key: OpenPGP.Key | string): Promise => { const openPgpKey = typeof key === 'string' ? await PgpKey.read(key) : key; const expires = await openPgpKey.getExpirationTime('encrypt'); if (expires instanceof Date && expires.getTime() < Date.now()) { // expired @@ -311,7 +311,7 @@ export class PgpKey { return { original: armored, normalized, keys: await Promise.all(keys.map(PgpKey.details)) }; } - public static details = async (k: OpenPGP.key.Key): Promise => { + public static details = async (k: OpenPGP.Key): Promise => { const keys = k.getKeys(); const algoInfo = k.primaryKey.getAlgorithmInfo(); const algo = { algorithm: algoInfo.algorithm, bits: algoInfo.bits, curve: (algoInfo as any).curve, algorithmId: openpgp.enums.publicKey[algoInfo.algorithm] }; @@ -349,7 +349,7 @@ export class PgpKey { * Get latest self-signature date, in utc millis. * This is used to figure out how recently was key updated, and if one key is newer than other. */ - public static lastSig = async (key: OpenPGP.key.Key): Promise => { + public static lastSig = async (key: OpenPGP.Key): Promise => { await key.getExpirationTime(); // will force all sigs to be verified const allSignatures: OpenPGP.packet.Signature[] = []; for (const user of key.users) { @@ -366,7 +366,7 @@ export class PgpKey { throw new Error('No valid signature found in key'); } - public static revoke = async (key: OpenPGP.key.Key): Promise => { + public static revoke = async (key: OpenPGP.Key): Promise => { if (! await key.isRevoked()) { key = await key.revoke({}); } diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index 55fa03807..a03d0d70f 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -16,7 +16,7 @@ import { openpgp } from './pgp'; export namespace PgpMsgMethod { export namespace Arg { - export type Encrypt = { pubkeys: string[], signingPrv?: OpenPGP.key.Key, pwd?: string, data: Uint8Array, filename?: string, armor: boolean, date?: Date }; + export type Encrypt = { pubkeys: string[], signingPrv?: OpenPGP.Key, pwd?: string, data: Uint8Array, filename?: string, armor: boolean, date?: Date }; export type Type = { data: Uint8Array }; export type Decrypt = { kisWithPp: PrvKeyInfo[], encryptedData: Uint8Array, msgPwd?: string, verificationPubkeys?: string[] }; export type DiagnosePubkeys = { privateKis: KeyInfo[], message: Uint8Array }; @@ -30,7 +30,7 @@ export namespace PgpMsgMethod { } type SortedKeysForDecrypt = { - forVerification: OpenPGP.key.Key[]; + forVerification: OpenPGP.Key[]; encryptedFor: string[]; signedBy: string[]; prvMatching: PrvKeyInfo[]; @@ -115,7 +115,7 @@ export class PgpMsg { * Returns signed data if detached=false, armored * Returns signature if detached=true, armored */ - public static sign = async (signingPrv: OpenPGP.key.Key, data: string, detached = false): Promise => { + public static sign = async (signingPrv: OpenPGP.Key, data: string, detached = false): Promise => { const message = openpgp.cleartext.fromText(data); const signRes = await openpgp.sign({ message, armor: true, privateKeys: [signingPrv], detached }); if (detached) { @@ -127,7 +127,7 @@ export class PgpMsg { return await openpgp.stream.readToEnd((signRes as OpenPGP.SignArmorResult).data); } - public static verify = async (msgOrVerResults: OpenpgpMsgOrCleartext | OpenPGP.message.Verification[], pubs: OpenPGP.key.Key[]): Promise => { + public static verify = async (msgOrVerResults: OpenpgpMsgOrCleartext | OpenPGP.message.Verification[], pubs: OpenPGP.Key[]): Promise => { const sig: VerifyRes = { match: null }; // tslint:disable-line:no-null-keyword try { // While this looks like bad method API design, it's here to ensure execution order when 1) reading data, 2) verifying, 3) processing signatures @@ -377,12 +377,12 @@ export class PgpMsg { return keys; } - private static matchingKeyids = (key: OpenPGP.key.Key, encryptedFor: OpenPGP.Keyid[]): OpenPGP.Keyid[] => { + private static matchingKeyids = (key: OpenPGP.Key, encryptedFor: OpenPGP.Keyid[]): OpenPGP.Keyid[] => { const msgKeyidBytesArr = (encryptedFor || []).map(kid => kid.bytes); return key.getKeyIds().filter(kid => msgKeyidBytesArr.includes(kid.bytes)); } - private static decryptKeyFor = async (prv: OpenPGP.key.Key, passphrase: string, matchingKeyIds: OpenPGP.Keyid[]): Promise => { + private static decryptKeyFor = async (prv: OpenPGP.Key, passphrase: string, matchingKeyIds: OpenPGP.Keyid[]): Promise => { if (!matchingKeyIds.length) { // we don't know which keyids match, decrypt all key packets return await PgpKey.decrypt(prv, passphrase, undefined, 'OK-IF-ALREADY-DECRYPTED'); } @@ -394,7 +394,7 @@ export class PgpMsg { return true; } - private static isKeyDecryptedFor = (prv: OpenPGP.key.Key, msgKeyIds: OpenPGP.Keyid[]): boolean => { + private static isKeyDecryptedFor = (prv: OpenPGP.Key, msgKeyIds: OpenPGP.Keyid[]): boolean => { if (prv.isFullyDecrypted()) { return true; // primary k + all subkeys decrypted, therefore it must be decrypted for any/every particular keyid } diff --git a/Core/source/core/pgp.ts b/Core/source/core/pgp.ts index a3b28ba4c..fb40c220c 100644 --- a/Core/source/core/pgp.ts +++ b/Core/source/core/pgp.ts @@ -14,7 +14,7 @@ if (typeof openpgp !== 'undefined') { // in certain environments, eg browser con openpgp.config.commentstring = 'Seamlessly send and receive encrypted email'; openpgp.config.ignore_mdc_error = true; // we manually check for missing MDC and show loud warning to user (no auto-decrypt) // openpgp.config.require_uid_self_cert = false; - const getPrvPackets = (k: OpenPGP.key.Key) => { + const getPrvPackets = (k: OpenPGP.Key) => { if (!k.isPrivate()) { throw new Error("Cannot check encryption status of secret keys in a Public Key"); } @@ -31,13 +31,13 @@ if (typeof openpgp !== 'undefined') { // in certain environments, eg browser con } return nonDummyPrvPackets; }; - openpgp.key.Key.prototype.isFullyDecrypted = function () { + OpenPGP.Key.prototype.isFullyDecrypted = function () { return getPrvPackets(this).every(p => p.isDecrypted() === true); }; - openpgp.key.Key.prototype.isFullyEncrypted = function () { + OpenPGP.Key.prototype.isFullyEncrypted = function () { return getPrvPackets(this).every(p => p.isDecrypted() === false); }; - openpgp.key.Key.prototype.isPacketDecrypted = function (keyId: OpenPGP.Keyid) { + OpenPGP.Key.prototype.isPacketDecrypted = function (keyId: OpenPGP.Keyid) { if (!this.isPrivate()) { throw new Error("Cannot check packet encryption status of secret key in a Public Key"); } diff --git a/Core/source/core/types/openpgp.d.ts b/Core/source/core/types/openpgp.d.ts index c1b7bc831..dcfd98f55 100644 --- a/Core/source/core/types/openpgp.d.ts +++ b/Core/source/core/types/openpgp.d.ts @@ -1,12 +1,14 @@ /** * Type definitions for OpenPGP.js http://openpgpjs.org/ - * + * * Contributors: * - FlowCrypt a. s. * - Guillaume Lacasa * - Errietta Kostala */ +export namespace OpenPGP { + /* ############## v5 KEY #################### */ // The Key and PublicKey types can be used interchangably since TS cannot detect the difference, as they have the same class properties. // The declared readKey(s) return type is Key instead of a PublicKey since it seems more obvious that a Key can be cast to a PrivateKey. @@ -171,13 +173,13 @@ export class CleartextMessage { /* ############## v5 MSG #################### */ export function generateSessionKey(options: { encryptionKeys: MaybeArray, date?: Date, encryptionUserIDs?: MaybeArray, config?: PartialConfig }): Promise; -export function encryptSessionKey(options: SessionKey & { +export function encryptSessionKey(options: SessionKey & { encryptionKeys?: MaybeArray, passwords?: MaybeArray, format?: 'armored', wildcard?: boolean, encryptionKeyIDs?: MaybeArray, date?: Date, encryptionUserIDs?: MaybeArray, config?: PartialConfig }) : Promise; -export function encryptSessionKey(options: SessionKey & { +export function encryptSessionKey(options: SessionKey & { encryptionKeys?: MaybeArray, passwords?: MaybeArray, format: 'binary', wildcard?: boolean, encryptionKeyIDs?: MaybeArray, date?: Date, encryptionUserIDs?: MaybeArray, config?: PartialConfig }) : Promise; -export function encryptSessionKey(options: SessionKey & { +export function encryptSessionKey(options: SessionKey & { encryptionKeys?: MaybeArray, passwords?: MaybeArray, format: 'object', wildcard?: boolean, encryptionKeyIDs?: MaybeArray, date?: Date, encryptionUserIDs?: MaybeArray, config?: PartialConfig }) : Promise>; export function decryptSessionKeys>(options: { message: Message, decryptionKeys?: MaybeArray, passwords?: MaybeArray, date?: Date, config?: PartialConfig }): Promise; @@ -349,7 +351,7 @@ interface PartialConfig extends Partial {} /* ############## v5 PACKET #################### */ -declare abstract class BasePacket { +abstract class BasePacket { static readonly tag: enums.packet; public read(bytes: Uint8Array): void; public write(): Uint8Array; @@ -360,7 +362,7 @@ declare abstract class BasePacket { * - A Secret (Sub)Key Packet can always be used when a Public one is expected. * - A Subkey Packet cannot always be used when a Primary Key Packet is expected (and vice versa). */ -declare abstract class BasePublicKeyPacket extends BasePacket { +abstract class BasePublicKeyPacket extends BasePacket { public algorithm: enums.publicKey; public created: Date; public version: number; @@ -388,7 +390,7 @@ export class PublicSubkeyPacket extends BasePublicKeyPacket { protected isSubkey(): true; } -declare abstract class BaseSecretKeyPacket extends BasePublicKeyPacket { +abstract class BaseSecretKeyPacket extends BasePublicKeyPacket { public privateParams: object | null; public encrypt(passphrase: string, config?: Config): Promise; // throws on error public decrypt(passphrase: string): Promise; // throws on error @@ -688,7 +690,7 @@ interface SubkeyOptions { config?: PartialConfig; } -declare class KeyID { +class KeyID { bytes: string; equals(keyID: KeyID, matchWildcard?: boolean): boolean; toHex(): string; @@ -884,3 +886,4 @@ export namespace enums { mime = 109 } } +} // namespace OpenPGP diff --git a/Core/source/mobile-interface/endpoints.ts b/Core/source/mobile-interface/endpoints.ts index e3290847a..b371c21ab 100644 --- a/Core/source/mobile-interface/endpoints.ts +++ b/Core/source/mobile-interface/endpoints.ts @@ -294,7 +294,7 @@ export class Endpoints { } } -export const getSigningPrv = async (req: NodeRequest.composeEmailEncrypted): Promise => { +export const getSigningPrv = async (req: NodeRequest.composeEmailEncrypted): Promise => { if (!req.signingPrv) { return undefined; } diff --git a/Core/source/platform/store.ts b/Core/source/platform/store.ts index 04a749467..12232c7c3 100644 --- a/Core/source/platform/store.ts +++ b/Core/source/platform/store.ts @@ -2,31 +2,33 @@ 'use strict'; +/// openpgp.util.str_to_hex(k.getKeyId().bytes).toUpperCase(); +const keyLongid = (k: OpenPGP.Key) => openpgp.str_to_hex(k.getKeyId().bytes).toUpperCase(); export class Store { - static decryptedKeyCacheSet = (k: OpenPGP.key.Key) => { + static decryptedKeyCacheSet = (k: OpenPGP.Key) => { Store.keyCacheRenewExpiry(); KEY_CACHE[keyLongid(k)] = k; } - static decryptedKeyCacheGet = (longid: string): OpenPGP.key.Key | undefined => { + static decryptedKeyCacheGet = (longid: string): OpenPGP.Key | undefined => { Store.keyCacheRenewExpiry(); return KEY_CACHE[longid]; } - static armoredKeyCacheSet = (armored: string, k: OpenPGP.key.Key) => { + static armoredKeyCacheSet = (armored: string, k: OpenPGP.Key) => { Store.keyCacheRenewExpiry(); KEY_CACHE[armored] = k; } - static armoredKeyCacheGet = (armored: string): OpenPGP.key.Key | undefined => { + static armoredKeyCacheGet = (armored: string): OpenPGP.Key | undefined => { Store.keyCacheRenewExpiry(); return KEY_CACHE[armored]; } From 479a81c2b152862298f15a527bb00447c588e6c3 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 3 Feb 2022 21:26:56 +0200 Subject: [PATCH 005/179] wip --- Core/source/core/pgp-key.ts | 12 ++++++------ Core/source/core/pgp-msg.ts | 6 +++--- Core/source/core/types/openpgp.d.ts | 2 +- Core/source/core/types/openpgpv4.d.ts | 2 +- Core/source/gen-compat-assets.ts | 4 ++-- Core/source/mobile-interface/endpoints.ts | 2 +- Core/source/mobile-interface/validate-input.ts | 2 +- Core/source/platform/store.ts | 4 ++-- Core/source/test.ts | 12 ++++++------ 9 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index aa713b1f4..12b3fd423 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -95,7 +95,7 @@ export class PgpKey { if (fromCache) { return fromCache; } - const { keys: [key] } = await openpgp.key.readArmored(armoredKey); + const { keys: [key] } = await openpgp.readArmored(armoredKey); if (key?.isPrivate()) { Store.armoredKeyCacheSet(armoredKey, key); } @@ -112,8 +112,8 @@ export class PgpKey { const armoredPublicKeyBlocks = blocks.filter(block => block.type === 'publicKey' || block.type === 'privateKey'); const pushKeysAndErrs = async (content: string | Buf, type: 'readArmored' | 'read') => { try { - const { err, keys } = type === 'readArmored' ? await openpgp.key.readArmored(content.toString()) - : await openpgp.key.read(typeof content === 'string' ? Buf.fromUtfStr(content) : content); + const { err, keys } = type === 'readArmored' ? await openpgp.readArmored(content.toString()) + : await openpgp.read(typeof content === 'string' ? Buf.fromUtfStr(content) : content); allErrs.push(...(err || [])); allKeys.push(...keys); } catch (e) { @@ -182,9 +182,9 @@ export class PgpKey { let keys: OpenPGP.Key[] = []; armored = PgpArmor.normalize(armored, 'key'); if (RegExp(PgpArmor.headers('publicKey', 're').begin).test(armored)) { - keys = (await openpgp.key.readArmored(armored)).keys; + keys = (await openpgp.readArmored(armored)).keys; } else if (RegExp(PgpArmor.headers('privateKey', 're').begin).test(armored)) { - keys = (await openpgp.key.readArmored(armored)).keys; + keys = (await openpgp.readArmored(armored)).keys; } else if (RegExp(PgpArmor.headers('encryptedMsg', 're').begin).test(armored)) { keys = [new OpenPGP.Key((await openpgp.message.readArmored(armored)).packets)]; } @@ -258,7 +258,7 @@ export class PgpKey { if (!PgpKey.fingerprint(armored)) { return false; } - const { keys: [pubkey] } = await openpgp.key.readArmored(armored); + const { keys: [pubkey] } = await openpgp.readArmored(armored); if (!pubkey) { return false; } diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index a03d0d70f..2de3437af 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -162,7 +162,7 @@ export class PgpMsg { const keys = await PgpMsg.getSortedKeys([], message); if (verificationPubkeys) { for (const verificationPubkey of verificationPubkeys) { - keys.forVerification.push(...(await openpgp.key.readArmored(verificationPubkey)).keys); + keys.forVerification.push(...(await openpgp.readArmored(verificationPubkey)).keys); } } return await PgpMsg.verify(message, keys.forVerification); @@ -226,7 +226,7 @@ export class PgpMsg { if (pubkeys) { options.publicKeys = []; for (const armoredPubkey of pubkeys) { - const { keys: publicKeys } = await openpgp.key.readArmored(armoredPubkey); + const { keys: publicKeys } = await openpgp.readArmored(armoredPubkey); options.publicKeys.push(...publicKeys); } } @@ -318,7 +318,7 @@ export class PgpMsg { if (typeof verificationPubkeys !== 'undefined') { keys.forVerification = []; for (const verificationPubkey of verificationPubkeys) { - const { keys: keysForVerification } = await openpgp.key.readArmored(verificationPubkey); + const { keys: keysForVerification } = await openpgp.readArmored(verificationPubkey); keys.forVerification.push(...keysForVerification); } } diff --git a/Core/source/core/types/openpgp.d.ts b/Core/source/core/types/openpgp.d.ts index dcfd98f55..05cfc74c7 100644 --- a/Core/source/core/types/openpgp.d.ts +++ b/Core/source/core/types/openpgp.d.ts @@ -7,7 +7,7 @@ * - Errietta Kostala */ -export namespace OpenPGP { +declare namespace OpenPGP { /* ############## v5 KEY #################### */ // The Key and PublicKey types can be used interchangably since TS cannot detect the difference, as they have the same class properties. diff --git a/Core/source/core/types/openpgpv4.d.ts b/Core/source/core/types/openpgpv4.d.ts index 6b0926394..d7d13a319 100644 --- a/Core/source/core/types/openpgpv4.d.ts +++ b/Core/source/core/types/openpgpv4.d.ts @@ -336,7 +336,7 @@ declare namespace OpenPGP { } /** - * Intended for internal use with openpgp.key.generate() + * Intended for internal use with openpgp.generate() * It's recommended that users choose openpgp.generateKey() that requires KeyOptions instead */ export interface FullKeyOptions { diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index 4f5dba5e8..83b25894b 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -204,7 +204,7 @@ ava.default('mime-email-plain-html.txt', async t => { ava.default('mime-email-encrypted-inline-text-signed.txt', async t => { const { keys } = getKeypairs('rsa1'); - const signingPrv = (await openpgp.key.readArmored(keys[0].private)).keys[0]; + const signingPrv = (await openpgp.readArmored(keys[0].private)).keys[0]; // console.log("rsa1 key fingerprint:" + signingPrv.getFingerprint().toUpperCase()); if (!(await signingPrv.decrypt(keys[0].passphrase))) throw Error('Can\'t decrypt private key'); const { data } = await PgpMsg.encrypt({ data: text, signingPrv: signingPrv, pubkeys, armor: true }) as OpenPGP.EncryptArmorResult; @@ -214,7 +214,7 @@ ava.default('mime-email-encrypted-inline-text-signed.txt', async t => { ava.default('mime-email-plain-signed.txt', async t => { const { keys } = getKeypairs('rsa1'); - const signingPrv = (await openpgp.key.readArmored(keys[0].private)).keys[0]; + const signingPrv = (await openpgp.readArmored(keys[0].private)).keys[0]; if (!(await signingPrv.decrypt(keys[0].passphrase))) throw Error('Can\'t decrypt private key'); const data = text.toString(); const signed = await PgpMsg.sign(signingPrv, data); diff --git a/Core/source/mobile-interface/endpoints.ts b/Core/source/mobile-interface/endpoints.ts index b371c21ab..547069904 100644 --- a/Core/source/mobile-interface/endpoints.ts +++ b/Core/source/mobile-interface/endpoints.ts @@ -252,7 +252,7 @@ export class Endpoints { return fmtRes({ format: 'armored', keyDetails }); } // binary - const { keys: openPgpKeys } = await openpgp.key.read(allData); + const { keys: openPgpKeys } = await openpgp.read(allData); for (const openPgpKey of openPgpKeys) { keyDetails.push(await PgpKey.details(openPgpKey)) } diff --git a/Core/source/mobile-interface/validate-input.ts b/Core/source/mobile-interface/validate-input.ts index 87a8f8407..d0fd949ba 100644 --- a/Core/source/mobile-interface/validate-input.ts +++ b/Core/source/mobile-interface/validate-input.ts @@ -178,7 +178,7 @@ const hasProp = (v: Obj, name: string, type: 'string[]' | 'string[]?' | 'object' } export const readArmoredKeyOrThrow = async (armored: string) => { - const { keys: [key], err } = await openpgp.key.readArmored(armored); + const { keys: [key], err } = await openpgp.readArmored(armored); if (err && err.length && err[0] instanceof Error) { throw err[0]; } diff --git a/Core/source/platform/store.ts b/Core/source/platform/store.ts index 12232c7c3..3cbd95e35 100644 --- a/Core/source/platform/store.ts +++ b/Core/source/platform/store.ts @@ -2,14 +2,14 @@ 'use strict'; -/// import { openpgp } from '../core/pgp'; let KEY_CACHE: { [longidOrArmoredKey: string]: OpenPGP.Key } = {}; let KEY_CACHE_WIPE_TIMEOUT: NodeJS.Timeout; -const keyLongid = (k: OpenPGP.Key) => openpgp.str_to_hex(k.getKeyId().bytes).toUpperCase(); +const keyLongid = (k: OpenPGP.Key) => openpgp.str_to_hex(k.getKeyID().bytes).toUpperCase(); export class Store { diff --git a/Core/source/test.ts b/Core/source/test.ts index ac1afaf0f..fa77b9938 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -428,7 +428,7 @@ ava.default('parseKeys - revoked', async t => { ava.default('decryptKey', async t => { const { keys: [key] } = getKeypairs('rsa1'); const { data, json } = parseResponse(await endpoints.decryptKey({ armored: key.private, passphrases: [key.passphrase] })); - const { keys: [decryptedKey] } = await openpgp.key.readArmored(json.decryptedKey); + const { keys: [decryptedKey] } = await openpgp.readArmored(json.decryptedKey); expect(decryptedKey.isFullyDecrypted()).to.be.true; expect(decryptedKey.isFullyEncrypted()).to.be.false; expectNoData(data); @@ -439,7 +439,7 @@ ava.default('encryptKey', async t => { const passphrase = 'this is some pass phrase'; const { decrypted: [decryptedKey] } = getKeypairs('rsa1'); const { data, json } = parseResponse(await endpoints.encryptKey({ armored: decryptedKey, passphrase })); - const { keys: [encryptedKey] } = await openpgp.key.readArmored(json.encryptedKey); + const { keys: [encryptedKey] } = await openpgp.readArmored(json.encryptedKey); expect(encryptedKey.isFullyEncrypted()).to.be.true; expect(encryptedKey.isFullyDecrypted()).to.be.false; expect(await encryptedKey.decrypt(passphrase)).to.be.true; @@ -449,19 +449,19 @@ ava.default('encryptKey', async t => { ava.default('decryptKey gpg-dummy', async t => { const { keys: [key] } = getKeypairs('gpg-dummy'); - const { keys: [encryptedKey] } = await openpgp.key.readArmored(key.private); + const { keys: [encryptedKey] } = await openpgp.readArmored(key.private); expect(encryptedKey.isFullyEncrypted()).to.be.true; expect(encryptedKey.isFullyDecrypted()).to.be.false; const { json } = parseResponse(await endpoints.decryptKey({ armored: key.private, passphrases: [key.passphrase] })); - const { keys: [decryptedKey] } = await openpgp.key.readArmored(json.decryptedKey); + const { keys: [decryptedKey] } = await openpgp.readArmored(json.decryptedKey); expect(decryptedKey.isFullyEncrypted()).to.be.false; expect(decryptedKey.isFullyDecrypted()).to.be.true; const { json: json2 } = parseResponse(await endpoints.encryptKey({ armored: decryptedKey.armor(), passphrase: 'another pass phrase' })); - const { keys: [reEncryptedKey] } = await openpgp.key.readArmored(json2.encryptedKey); + const { keys: [reEncryptedKey] } = await openpgp.readArmored(json2.encryptedKey); expect(reEncryptedKey.isFullyEncrypted()).to.be.true; expect(reEncryptedKey.isFullyDecrypted()).to.be.false; const { json: json3 } = parseResponse(await endpoints.decryptKey({ armored: reEncryptedKey.armor(), passphrases: ['another pass phrase'] })); - const { keys: [reDecryptedKey] } = await openpgp.key.readArmored(json3.decryptedKey); + const { keys: [reDecryptedKey] } = await openpgp.readArmored(json3.decryptedKey); expect(reDecryptedKey.isFullyEncrypted()).to.be.false; expect(reDecryptedKey.isFullyDecrypted()).to.be.true; t.pass(); From 4ccb2ff4e4a5178b917e2106195308cb7744cb46 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 3 Feb 2022 21:49:40 +0200 Subject: [PATCH 006/179] wip --- Core/source/core/pgp-armor.ts | 11 ++++--- Core/source/core/pgp-password.ts | 4 +-- Core/source/platform/store.ts | 4 +-- Core/source/platform/util.ts | 53 ++++++++++++++++++++++++++++++++ Core/source/test.ts | 12 ++++---- 5 files changed, 69 insertions(+), 15 deletions(-) diff --git a/Core/source/core/pgp-armor.ts b/Core/source/core/pgp-armor.ts index 062733b19..ca1061d0b 100644 --- a/Core/source/core/pgp-armor.ts +++ b/Core/source/core/pgp-armor.ts @@ -7,8 +7,9 @@ import { ReplaceableMsgBlockType } from './msg-block'; import { Str } from './common'; import { openpgp } from './pgp'; -export type PreparedForDecrypt = { isArmored: boolean, isCleartext: true, message: OpenPGP.cleartext.CleartextMessage } - | { isArmored: boolean, isCleartext: false, message: OpenPGP.message.Message }; +export type PreparedForDecrypt = { isArmored: boolean, isCleartext: true, message: OpenPGP.CleartextMessage } + | { isArmored: boolean, isCleartext: false, message: OpenPGP.Message // TODO: Maybe smth better? + }; type CryptoArmorHeaderDefinitions = { readonly [type in ReplaceableMsgBlockType | 'null' | 'signature']: CryptoArmorHeaderDefinition; }; type CryptoArmorHeaderDefinition = { begin: string, middle?: string, end: string | RegExp, replace: boolean }; @@ -83,11 +84,11 @@ export class PgpArmor { const isArmoredSignedOnly = utfChunk.includes(PgpArmor.headers('signedMsg').begin); const isArmored = isArmoredEncrypted || isArmoredSignedOnly; if (isArmoredSignedOnly) { - return { isArmored, isCleartext: true, message: await openpgp.cleartext.readArmored(new Buf(encrypted).toUtfStr()) }; + return { isArmored, isCleartext: true, message: await openpgp.readCleartextMessage(new Buf(encrypted).toUtfStr()) }; } else if (isArmoredEncrypted) { - return { isArmored, isCleartext: false, message: await openpgp.message.readArmored(new Buf(encrypted).toUtfStr()) }; + return { isArmored, isCleartext: false, message: await openpgp.readArmored(new Buf(encrypted).toUtfStr()) }; } else if (encrypted instanceof Uint8Array) { - return { isArmored, isCleartext: false, message: await openpgp.message.read(encrypted) }; + return { isArmored, isCleartext: false, message: await openpgp.read(encrypted) }; } throw new Error('Message does not have armor headers'); } diff --git a/Core/source/core/pgp-password.ts b/Core/source/core/pgp-password.ts index 62d444638..6b0a5213a 100644 --- a/Core/source/core/pgp-password.ts +++ b/Core/source/core/pgp-password.ts @@ -2,7 +2,7 @@ 'use strict'; -import { base64encode, secureRandomBytes } from '../platform/util'; +import { base64encode, secureRandomBytes, Uint8Array_to_str } from '../platform/util'; import { openpgp } from './pgp'; @@ -66,7 +66,7 @@ export class PgpPwd { } public static random = () => { // eg TDW6-DU5M-TANI-LJXY - return base64encode(openpgp.util.Uint8Array_to_str(secureRandomBytes(128))).toUpperCase().replace(/[^A-Z0-9]|0|O|1/g, '').replace(/(.{4})/g, '$1-').substr(0, 19); + return base64encode(Uint8Array_to_str(secureRandomBytes(128))).toUpperCase().replace(/[^A-Z0-9]|0|O|1/g, '').replace(/(.{4})/g, '$1-').substr(0, 19); } private static readableCrackTime = (totalSeconds: number) => { // http://stackoverflow.com/questions/8211744/convert-time-interval-given-in-seconds-into-more-human-readable-form diff --git a/Core/source/platform/store.ts b/Core/source/platform/store.ts index 3cbd95e35..3e258eedd 100644 --- a/Core/source/platform/store.ts +++ b/Core/source/platform/store.ts @@ -4,12 +4,12 @@ /// -import { openpgp } from '../core/pgp'; +import { str_to_hex } from './util'; let KEY_CACHE: { [longidOrArmoredKey: string]: OpenPGP.Key } = {}; let KEY_CACHE_WIPE_TIMEOUT: NodeJS.Timeout; -const keyLongid = (k: OpenPGP.Key) => openpgp.str_to_hex(k.getKeyID().bytes).toUpperCase(); +const keyLongid = (k: OpenPGP.Key) => str_to_hex(k.getKeyID().bytes).toUpperCase(); export class Store { diff --git a/Core/source/platform/util.ts b/Core/source/platform/util.ts index 13116dd7c..177d047e5 100644 --- a/Core/source/platform/util.ts +++ b/Core/source/platform/util.ts @@ -30,3 +30,56 @@ export const setGlobals = () => { export const iso2022jpToUtf = (content: Buf) => { return dereq_encoding_japanese.convert(content, { to: 'UTF8', from: 'JIS', type: 'string' }); } + +/** + * Create hex string from a binary + * @param {String} str String to convert + * @returns {String} String containing the hexadecimal values + */ +export const str_to_hex = (str: string): string => { + if (str === null) { + return ""; + } + const r = []; + const e = str.length; + let c = 0; + let h; + while (c < e) { + h = str.charCodeAt(c++).toString(16); + while (h.length < 2) { + h = "0" + h; + } + r.push("" + h); + } + return r.join(''); +} + +/** + * Create binary string from a hex encoded string + * @param {String} str Hex string to convert + * @returns {String} + */ +export const hex_to_str = (hex: string): string => { + let str = ''; + for (let i = 0; i < hex.length; i += 2) { + str += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); + } + return str; +} + +/** + * Convert an array of 8-bit integers to a string + * @param {Uint8Array} bytes An array of 8-bit integers to convert + * @returns {String} String representation of the array + */ +export const Uint8Array_to_str = (bytes: Uint8Array): string => { + bytes = new Uint8Array(bytes); + const result = []; + const bs = 1 << 14; + const j = bytes.length; + + for (let i = 0; i < j; i += bs) { + result.push(String.fromCharCode.apply(String, bytes.subarray(i, i + bs < j ? i + bs : j))); + } + return result.join(''); +} diff --git a/Core/source/test.ts b/Core/source/test.ts index fa77b9938..0ccdb3bf9 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -428,7 +428,7 @@ ava.default('parseKeys - revoked', async t => { ava.default('decryptKey', async t => { const { keys: [key] } = getKeypairs('rsa1'); const { data, json } = parseResponse(await endpoints.decryptKey({ armored: key.private, passphrases: [key.passphrase] })); - const { keys: [decryptedKey] } = await openpgp.readArmored(json.decryptedKey); + const { keys: [decryptedKey] } = await openpgp.readKey({armoredKey: json.decryptedKey}); expect(decryptedKey.isFullyDecrypted()).to.be.true; expect(decryptedKey.isFullyEncrypted()).to.be.false; expectNoData(data); @@ -439,7 +439,7 @@ ava.default('encryptKey', async t => { const passphrase = 'this is some pass phrase'; const { decrypted: [decryptedKey] } = getKeypairs('rsa1'); const { data, json } = parseResponse(await endpoints.encryptKey({ armored: decryptedKey, passphrase })); - const { keys: [encryptedKey] } = await openpgp.readArmored(json.encryptedKey); + const { keys: [encryptedKey] } = await openpgp.readKey({armoredKey: json.encryptedKey}); expect(encryptedKey.isFullyEncrypted()).to.be.true; expect(encryptedKey.isFullyDecrypted()).to.be.false; expect(await encryptedKey.decrypt(passphrase)).to.be.true; @@ -449,19 +449,19 @@ ava.default('encryptKey', async t => { ava.default('decryptKey gpg-dummy', async t => { const { keys: [key] } = getKeypairs('gpg-dummy'); - const { keys: [encryptedKey] } = await openpgp.readArmored(key.private); + const { keys: [encryptedKey] } = await openpgp.readKey({armoredKey: key.private}); expect(encryptedKey.isFullyEncrypted()).to.be.true; expect(encryptedKey.isFullyDecrypted()).to.be.false; const { json } = parseResponse(await endpoints.decryptKey({ armored: key.private, passphrases: [key.passphrase] })); - const { keys: [decryptedKey] } = await openpgp.readArmored(json.decryptedKey); + const { keys: [decryptedKey] } = await openpgp.readKey({armoredKey: json.decryptedKey}); expect(decryptedKey.isFullyEncrypted()).to.be.false; expect(decryptedKey.isFullyDecrypted()).to.be.true; const { json: json2 } = parseResponse(await endpoints.encryptKey({ armored: decryptedKey.armor(), passphrase: 'another pass phrase' })); - const { keys: [reEncryptedKey] } = await openpgp.readArmored(json2.encryptedKey); + const { keys: [reEncryptedKey] } = await openpgp.readKey({armoredKey: json2.encryptedKey}); expect(reEncryptedKey.isFullyEncrypted()).to.be.true; expect(reEncryptedKey.isFullyDecrypted()).to.be.false; const { json: json3 } = parseResponse(await endpoints.decryptKey({ armored: reEncryptedKey.armor(), passphrases: ['another pass phrase'] })); - const { keys: [reDecryptedKey] } = await openpgp.readArmored(json3.decryptedKey); + const { keys: [reDecryptedKey] } = await openpgp.readKey({armoredKey: json3.decryptedKey}); expect(reDecryptedKey.isFullyEncrypted()).to.be.false; expect(reDecryptedKey.isFullyDecrypted()).to.be.true; t.pass(); From c8ceff85c6ef6b56b5489313700f7216ab969282 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 3 Feb 2022 21:50:10 +0200 Subject: [PATCH 007/179] wip --- Core/source/core/pgp-password.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/Core/source/core/pgp-password.ts b/Core/source/core/pgp-password.ts index 6b0a5213a..a743d26cf 100644 --- a/Core/source/core/pgp-password.ts +++ b/Core/source/core/pgp-password.ts @@ -4,8 +4,6 @@ import { base64encode, secureRandomBytes, Uint8Array_to_str } from '../platform/util'; -import { openpgp } from './pgp'; - interface PwdStrengthResult { word: { match: string; From ad376d5d527abfefb0f92b00248b42dfd28c0dd8 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 3 Feb 2022 22:04:04 +0200 Subject: [PATCH 008/179] wip --- Core/source/core/pgp-key.ts | 4 ++-- Core/source/core/pgp-msg.ts | 8 +++---- Core/source/core/pgp.ts | 6 +++--- Core/source/core/types/openpgp.d.ts | 5 +++++ Core/source/core/types/openpgpv4.d.ts | 30 +++++++++++++-------------- Core/source/test.ts | 10 ++++----- 6 files changed, 34 insertions(+), 29 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index 12b3fd423..ba26437a3 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -134,7 +134,7 @@ export class PgpKey { return p.tag === openpgp.enums.packet.secretKey || p.tag === openpgp.enums.packet.secretSubkey; } - public static decrypt = async (prv: OpenPGP.Key, passphrase: string, optionalKeyid?: OpenPGP.Keyid, optionalBehaviorFlag?: 'OK-IF-ALREADY-DECRYPTED'): Promise => { + public static decrypt = async (prv: OpenPGP.Key, passphrase: string, optionalKeyid?: OpenPGP.KeyID, optionalBehaviorFlag?: 'OK-IF-ALREADY-DECRYPTED'): Promise => { if (!prv.isPrivate()) { throw new Error("Nothing to decrypt in a public key"); } @@ -243,7 +243,7 @@ export class PgpKey { return await PgpKey.longid(await PgpKey.fingerprint(keyOrFingerprintOrBytes)); } - public static longids = async (keyIds: OpenPGP.Keyid[]) => { + public static longids = async (keyIds: OpenPGP.KeyID[]) => { const longids: string[] = []; for (const id of keyIds) { const longid = await PgpKey.longid(id.bytes); diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index 2de3437af..cae9743b1 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -245,7 +245,7 @@ export class PgpMsg { public static diagnosePubkeys: PgpMsgMethod.DiagnosePubkeys = async ({ privateKis, message }) => { const m = await openpgp.message.readArmored(Buf.fromUint8(message).toUtfStr()); const msgKeyIds = m.getEncryptionKeyIds ? m.getEncryptionKeyIds() : []; - const localKeyIds: OpenPGP.Keyid[] = []; + const localKeyIds: OpenPGP.KeyID[] = []; for (const k of await Promise.all(privateKis.map(ki => PgpKey.read(ki.public)))) { localKeyIds.push(...k.getKeyIds()); } @@ -377,12 +377,12 @@ export class PgpMsg { return keys; } - private static matchingKeyids = (key: OpenPGP.Key, encryptedFor: OpenPGP.Keyid[]): OpenPGP.Keyid[] => { + private static matchingKeyids = (key: OpenPGP.Key, encryptedFor: OpenPGP.KeyID[]): OpenPGP.KeyID[] => { const msgKeyidBytesArr = (encryptedFor || []).map(kid => kid.bytes); return key.getKeyIds().filter(kid => msgKeyidBytesArr.includes(kid.bytes)); } - private static decryptKeyFor = async (prv: OpenPGP.Key, passphrase: string, matchingKeyIds: OpenPGP.Keyid[]): Promise => { + private static decryptKeyFor = async (prv: OpenPGP.Key, passphrase: string, matchingKeyIds: OpenPGP.KeyID[]): Promise => { if (!matchingKeyIds.length) { // we don't know which keyids match, decrypt all key packets return await PgpKey.decrypt(prv, passphrase, undefined, 'OK-IF-ALREADY-DECRYPTED'); } @@ -394,7 +394,7 @@ export class PgpMsg { return true; } - private static isKeyDecryptedFor = (prv: OpenPGP.Key, msgKeyIds: OpenPGP.Keyid[]): boolean => { + private static isKeyDecryptedFor = (prv: OpenPGP.Key, msgKeyIds: OpenPGP.KeyID[]): boolean => { if (prv.isFullyDecrypted()) { return true; // primary k + all subkeys decrypted, therefore it must be decrypted for any/every particular keyid } diff --git a/Core/source/core/pgp.ts b/Core/source/core/pgp.ts index fb40c220c..168fffe99 100644 --- a/Core/source/core/pgp.ts +++ b/Core/source/core/pgp.ts @@ -37,16 +37,16 @@ if (typeof openpgp !== 'undefined') { // in certain environments, eg browser con OpenPGP.Key.prototype.isFullyEncrypted = function () { return getPrvPackets(this).every(p => p.isDecrypted() === false); }; - OpenPGP.Key.prototype.isPacketDecrypted = function (keyId: OpenPGP.Keyid) { + OpenPGP.Key.prototype.isPacketDecrypted = function (keyId: OpenPGP.KeyID) { if (!this.isPrivate()) { throw new Error("Cannot check packet encryption status of secret key in a Public Key"); } if (!keyId) { - throw new Error("No Keyid provided to isPacketDecrypted"); + throw new Error("No KeyID provided to isPacketDecrypted"); } const [key] = this.getKeys(keyId); if (!key) { - throw new Error("Keyid not found in Private Key"); + throw new Error("KeyID not found in Private Key"); } return key.keyPacket.isDecrypted() === true; }; diff --git a/Core/source/core/types/openpgp.d.ts b/Core/source/core/types/openpgp.d.ts index 05cfc74c7..85054ae8f 100644 --- a/Core/source/core/types/openpgp.d.ts +++ b/Core/source/core/types/openpgp.d.ts @@ -70,6 +70,11 @@ export abstract class Key { public getAlgorithmInfo(): AlgorithmInfo; public getKeyID(): KeyID; public toPacketList(): PacketList; + // ----- BEGIN ADDED BY FLOWCRYPT ----- + public isFullyEncrypted(): boolean; + public isFullyDecrypted(): boolean; + public isPacketDecrypted(keyId: KeyID): boolean; + // ----- END ADDED BY FLOWCRYPT ----- } type AllowedKeyPackets = PublicKeyPacket | PublicSubkeyPacket | SecretKeyPacket | SecretSubkeyPacket | UserIDPacket | UserAttributePacket | SignaturePacket; diff --git a/Core/source/core/types/openpgpv4.d.ts b/Core/source/core/types/openpgpv4.d.ts index d7d13a319..e6b03300e 100644 --- a/Core/source/core/types/openpgpv4.d.ts +++ b/Core/source/core/types/openpgpv4.d.ts @@ -118,7 +118,7 @@ declare namespace OpenPGP { getFingerprint(): string; getFingerprintBytes(): Uint8Array | null; getCreationTime(): Date; - getKeyId(): Keyid; + getKeyId(): KeyID; version: number; expirationTimeV3: number | null; @@ -225,7 +225,7 @@ declare namespace OpenPGP { revocationKeyClass: null | number; revocationKeyAlgorithm: null | number; revocationKeyFingerprint: null | Uint8Array; - issuerKeyId: Keyid; + issuerKeyId: KeyID; notation: null | { [name: string]: string }; preferredHashAlgorithms: null | number[]; preferredCompressionAlgorithms: null | number[]; @@ -349,7 +349,7 @@ declare namespace OpenPGP { subkeys: KeyOptions[]; // required unline KeyOptions.subkeys } - export interface Keyid { + export interface KeyID { bytes: string; } @@ -524,7 +524,7 @@ declare namespace OpenPGP { /** Returns the key IDs of the keys that signed the cleartext message */ - getSigningKeyIds(): Array; + getSigningKeyIds(): Array; /** Get cleartext */ @@ -814,10 +814,10 @@ declare namespace OpenPGP { class Key { constructor(packetlist: packet.List); armor(): string; - decrypt(passphrase: string | string[], keyId?: Keyid): Promise; + decrypt(passphrase: string | string[], keyId?: KeyID): Promise; encrypt(passphrase: string | string[]): Promise; - getExpirationTime(capability?: 'encrypt' | 'encrypt_sign' | 'sign' | null, keyId?: Keyid | null, userId?: UserId | null): Promise; // Returns null if `capabilities` is passed and the key does not have the specified capabilities or is revoked or invalid. - getKeyIds(): Keyid[]; + getExpirationTime(capability?: 'encrypt' | 'encrypt_sign' | 'sign' | null, keyId?: KeyID | null, userId?: UserId | null): Promise; // Returns null if `capabilities` is passed and the key does not have the specified capabilities or is revoked or invalid. + getKeyIds(): KeyID[]; getPrimaryUser(): Promise; getUserIds(): string[]; isPrivate(): boolean; @@ -828,17 +828,17 @@ declare namespace OpenPGP { isRevoked(): Promise; revoke(reason: { flag?: enums.reasonForRevocation; string?: string; }, date?: Date): Promise; getRevocationCertificate(): Promise | string | undefined>; - getEncryptionKey(keyid?: Keyid | null, date?: Date, userId?: UserId | null): Promise; + getEncryptionKey(keyid?: KeyID | null, date?: Date, userId?: UserId | null): Promise; getSigningKey(): Promise; - getKeys(keyId?: Keyid): (Key | SubKey)[]; + getKeys(keyId?: KeyID): (Key | SubKey)[]; // isDecrypted(): boolean; isFullyEncrypted(): boolean; isFullyDecrypted(): boolean; - isPacketDecrypted(keyId: Keyid): boolean; + isPacketDecrypted(keyId: KeyID): boolean; getFingerprint(): string; getCreationTime(): Date; getAlgorithmInfo(): AlgorithmInfo; - getKeyId(): Keyid; + getKeyId(): KeyID; primaryKey: packet.PublicKey | packet.SecretKey; subKeys: SubKey[]; users: User[]; @@ -857,7 +857,7 @@ declare namespace OpenPGP { getFingerprint(): string; getCreationTime(): Date; getAlgorithmInfo(): AlgorithmInfo; - getKeyId(): Keyid; + getKeyId(): KeyID; } export interface User { @@ -943,7 +943,7 @@ declare namespace OpenPGP { /** Returns the key IDs of the keys to which the session key is encrypted */ - getEncryptionKeyIds(): Keyid[]; + getEncryptionKeyIds(): KeyID[]; /** Get literal data that is the body of the message */ @@ -951,7 +951,7 @@ declare namespace OpenPGP { /** Returns the key IDs of the keys that signed the message */ - getSigningKeyIds(): Keyid[]; + getSigningKeyIds(): KeyID[]; /** Get literal data as text */ @@ -987,7 +987,7 @@ declare namespace OpenPGP { } export interface Verification { - keyid: Keyid; + keyid: KeyID; verified: Promise; signature: Promise; } diff --git a/Core/source/test.ts b/Core/source/test.ts index 0ccdb3bf9..fb0518289 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -439,7 +439,7 @@ ava.default('encryptKey', async t => { const passphrase = 'this is some pass phrase'; const { decrypted: [decryptedKey] } = getKeypairs('rsa1'); const { data, json } = parseResponse(await endpoints.encryptKey({ armored: decryptedKey, passphrase })); - const { keys: [encryptedKey] } = await openpgp.readKey({armoredKey: json.encryptedKey}); + const encryptedKey = await openpgp.readKey({armoredKey: json.encryptedKey}); expect(encryptedKey.isFullyEncrypted()).to.be.true; expect(encryptedKey.isFullyDecrypted()).to.be.false; expect(await encryptedKey.decrypt(passphrase)).to.be.true; @@ -449,19 +449,19 @@ ava.default('encryptKey', async t => { ava.default('decryptKey gpg-dummy', async t => { const { keys: [key] } = getKeypairs('gpg-dummy'); - const { keys: [encryptedKey] } = await openpgp.readKey({armoredKey: key.private}); + const encryptedKey = await openpgp.readKey({armoredKey: key.private}); expect(encryptedKey.isFullyEncrypted()).to.be.true; expect(encryptedKey.isFullyDecrypted()).to.be.false; const { json } = parseResponse(await endpoints.decryptKey({ armored: key.private, passphrases: [key.passphrase] })); - const { keys: [decryptedKey] } = await openpgp.readKey({armoredKey: json.decryptedKey}); + const decryptedKey = await openpgp.readKey({armoredKey: json.decryptedKey}); expect(decryptedKey.isFullyEncrypted()).to.be.false; expect(decryptedKey.isFullyDecrypted()).to.be.true; const { json: json2 } = parseResponse(await endpoints.encryptKey({ armored: decryptedKey.armor(), passphrase: 'another pass phrase' })); - const { keys: [reEncryptedKey] } = await openpgp.readKey({armoredKey: json2.encryptedKey}); + const reEncryptedKey = await openpgp.readKey({armoredKey: json2.encryptedKey}); expect(reEncryptedKey.isFullyEncrypted()).to.be.true; expect(reEncryptedKey.isFullyDecrypted()).to.be.false; const { json: json3 } = parseResponse(await endpoints.decryptKey({ armored: reEncryptedKey.armor(), passphrases: ['another pass phrase'] })); - const { keys: [reDecryptedKey] } = await openpgp.readKey({armoredKey: json3.decryptedKey}); + const reDecryptedKey = await openpgp.readKey({armoredKey: json3.decryptedKey}); expect(reDecryptedKey.isFullyEncrypted()).to.be.false; expect(reDecryptedKey.isFullyDecrypted()).to.be.true; t.pass(); From a2ff73e3a2ed6164dd7f836a9db08d7bc317ea98 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 3 Feb 2022 22:04:39 +0200 Subject: [PATCH 009/179] wip --- Core/source/core/types/openpgpv4.d.ts | 30 +++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Core/source/core/types/openpgpv4.d.ts b/Core/source/core/types/openpgpv4.d.ts index e6b03300e..d7d13a319 100644 --- a/Core/source/core/types/openpgpv4.d.ts +++ b/Core/source/core/types/openpgpv4.d.ts @@ -118,7 +118,7 @@ declare namespace OpenPGP { getFingerprint(): string; getFingerprintBytes(): Uint8Array | null; getCreationTime(): Date; - getKeyId(): KeyID; + getKeyId(): Keyid; version: number; expirationTimeV3: number | null; @@ -225,7 +225,7 @@ declare namespace OpenPGP { revocationKeyClass: null | number; revocationKeyAlgorithm: null | number; revocationKeyFingerprint: null | Uint8Array; - issuerKeyId: KeyID; + issuerKeyId: Keyid; notation: null | { [name: string]: string }; preferredHashAlgorithms: null | number[]; preferredCompressionAlgorithms: null | number[]; @@ -349,7 +349,7 @@ declare namespace OpenPGP { subkeys: KeyOptions[]; // required unline KeyOptions.subkeys } - export interface KeyID { + export interface Keyid { bytes: string; } @@ -524,7 +524,7 @@ declare namespace OpenPGP { /** Returns the key IDs of the keys that signed the cleartext message */ - getSigningKeyIds(): Array; + getSigningKeyIds(): Array; /** Get cleartext */ @@ -814,10 +814,10 @@ declare namespace OpenPGP { class Key { constructor(packetlist: packet.List); armor(): string; - decrypt(passphrase: string | string[], keyId?: KeyID): Promise; + decrypt(passphrase: string | string[], keyId?: Keyid): Promise; encrypt(passphrase: string | string[]): Promise; - getExpirationTime(capability?: 'encrypt' | 'encrypt_sign' | 'sign' | null, keyId?: KeyID | null, userId?: UserId | null): Promise; // Returns null if `capabilities` is passed and the key does not have the specified capabilities or is revoked or invalid. - getKeyIds(): KeyID[]; + getExpirationTime(capability?: 'encrypt' | 'encrypt_sign' | 'sign' | null, keyId?: Keyid | null, userId?: UserId | null): Promise; // Returns null if `capabilities` is passed and the key does not have the specified capabilities or is revoked or invalid. + getKeyIds(): Keyid[]; getPrimaryUser(): Promise; getUserIds(): string[]; isPrivate(): boolean; @@ -828,17 +828,17 @@ declare namespace OpenPGP { isRevoked(): Promise; revoke(reason: { flag?: enums.reasonForRevocation; string?: string; }, date?: Date): Promise; getRevocationCertificate(): Promise | string | undefined>; - getEncryptionKey(keyid?: KeyID | null, date?: Date, userId?: UserId | null): Promise; + getEncryptionKey(keyid?: Keyid | null, date?: Date, userId?: UserId | null): Promise; getSigningKey(): Promise; - getKeys(keyId?: KeyID): (Key | SubKey)[]; + getKeys(keyId?: Keyid): (Key | SubKey)[]; // isDecrypted(): boolean; isFullyEncrypted(): boolean; isFullyDecrypted(): boolean; - isPacketDecrypted(keyId: KeyID): boolean; + isPacketDecrypted(keyId: Keyid): boolean; getFingerprint(): string; getCreationTime(): Date; getAlgorithmInfo(): AlgorithmInfo; - getKeyId(): KeyID; + getKeyId(): Keyid; primaryKey: packet.PublicKey | packet.SecretKey; subKeys: SubKey[]; users: User[]; @@ -857,7 +857,7 @@ declare namespace OpenPGP { getFingerprint(): string; getCreationTime(): Date; getAlgorithmInfo(): AlgorithmInfo; - getKeyId(): KeyID; + getKeyId(): Keyid; } export interface User { @@ -943,7 +943,7 @@ declare namespace OpenPGP { /** Returns the key IDs of the keys to which the session key is encrypted */ - getEncryptionKeyIds(): KeyID[]; + getEncryptionKeyIds(): Keyid[]; /** Get literal data that is the body of the message */ @@ -951,7 +951,7 @@ declare namespace OpenPGP { /** Returns the key IDs of the keys that signed the message */ - getSigningKeyIds(): KeyID[]; + getSigningKeyIds(): Keyid[]; /** Get literal data as text */ @@ -987,7 +987,7 @@ declare namespace OpenPGP { } export interface Verification { - keyid: KeyID; + keyid: Keyid; verified: Promise; signature: Promise; } From 5d71a3c2cbfedc55fbdf636f79a48fdaac23678f Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 3 Feb 2022 22:13:41 +0200 Subject: [PATCH 010/179] wip --- Core/source/test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/source/test.ts b/Core/source/test.ts index fb0518289..fbc768940 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -428,7 +428,7 @@ ava.default('parseKeys - revoked', async t => { ava.default('decryptKey', async t => { const { keys: [key] } = getKeypairs('rsa1'); const { data, json } = parseResponse(await endpoints.decryptKey({ armored: key.private, passphrases: [key.passphrase] })); - const { keys: [decryptedKey] } = await openpgp.readKey({armoredKey: json.decryptedKey}); + const decryptedKey = await openpgp.readKey({armoredKey: json.decryptedKey}); expect(decryptedKey.isFullyDecrypted()).to.be.true; expect(decryptedKey.isFullyEncrypted()).to.be.false; expectNoData(data); From 33d7bf64898c58ac6d1b78755fd224be96776887 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 3 Feb 2022 22:20:43 +0200 Subject: [PATCH 011/179] wip --- Core/source/core/pgp.ts | 8 +++++--- Core/source/test.ts | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Core/source/core/pgp.ts b/Core/source/core/pgp.ts index 168fffe99..8ffa57744 100644 --- a/Core/source/core/pgp.ts +++ b/Core/source/core/pgp.ts @@ -10,9 +10,11 @@ import { requireOpenpgp } from '../platform/require'; export const openpgp = requireOpenpgp(); if (typeof openpgp !== 'undefined') { // in certain environments, eg browser content scripts, openpgp is not included (not all functions below need it) - openpgp.config.versionstring = `FlowCrypt ${VERSION} Gmail Encryption`; - openpgp.config.commentstring = 'Seamlessly send and receive encrypted email'; - openpgp.config.ignore_mdc_error = true; // we manually check for missing MDC and show loud warning to user (no auto-decrypt) + openpgp.config.versionString = `FlowCrypt ${VERSION} Gmail Encryption`; + openpgp.config.commentString = 'Seamlessly send and receive encrypted email'; + // we manually check for missing MDC and show loud warning to user (no auto-decrypt) + openpgp.config.allowUnauthenticatedMessages = true; + openpgp.config.allowUnauthenticatedStream = true; // openpgp.config.require_uid_self_cert = false; const getPrvPackets = (k: OpenPGP.Key) => { if (!k.isPrivate()) { diff --git a/Core/source/test.ts b/Core/source/test.ts index fbc768940..c5c4517d5 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -442,7 +442,7 @@ ava.default('encryptKey', async t => { const encryptedKey = await openpgp.readKey({armoredKey: json.encryptedKey}); expect(encryptedKey.isFullyEncrypted()).to.be.true; expect(encryptedKey.isFullyDecrypted()).to.be.false; - expect(await encryptedKey.decrypt(passphrase)).to.be.true; + expect(await (encryptedKey as OpenPGP.PrivateKey).decrypt(passphrase)).to.be.true; expectNoData(data); t.pass(); }); From 0f58944b05f1323b7aaf9d34e8844be53a6087b1 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 3 Feb 2022 22:24:09 +0200 Subject: [PATCH 012/179] wip --- Core/source/test.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Core/source/test.ts b/Core/source/test.ts index c5c4517d5..508f9d157 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -442,7 +442,10 @@ ava.default('encryptKey', async t => { const encryptedKey = await openpgp.readKey({armoredKey: json.encryptedKey}); expect(encryptedKey.isFullyEncrypted()).to.be.true; expect(encryptedKey.isFullyDecrypted()).to.be.false; - expect(await (encryptedKey as OpenPGP.PrivateKey).decrypt(passphrase)).to.be.true; + expect(await openpgp.decryptKey({ + privateKey: (encryptedKey as OpenPGP.PrivateKey), + passphrase: passphrase + })).to.be.true expectNoData(data); t.pass(); }); From 0a28c3111b1028d0b5b0a8f9f1ef5f92782542a3 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 3 Feb 2022 22:36:15 +0200 Subject: [PATCH 013/179] wip --- Core/source/core/pgp-armor.ts | 20 ++++++++++++++++---- Core/source/core/types/openpgp.d.ts | 1 + 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/Core/source/core/pgp-armor.ts b/Core/source/core/pgp-armor.ts index ca1061d0b..9c474d205 100644 --- a/Core/source/core/pgp-armor.ts +++ b/Core/source/core/pgp-armor.ts @@ -8,7 +8,7 @@ import { Str } from './common'; import { openpgp } from './pgp'; export type PreparedForDecrypt = { isArmored: boolean, isCleartext: true, message: OpenPGP.CleartextMessage } - | { isArmored: boolean, isCleartext: false, message: OpenPGP.Message // TODO: Maybe smth better? + | { isArmored: boolean, isCleartext: false, message: OpenPGP.Message }; type CryptoArmorHeaderDefinitions = { readonly [type in ReplaceableMsgBlockType | 'null' | 'signature']: CryptoArmorHeaderDefinition; }; @@ -84,11 +84,23 @@ export class PgpArmor { const isArmoredSignedOnly = utfChunk.includes(PgpArmor.headers('signedMsg').begin); const isArmored = isArmoredEncrypted || isArmoredSignedOnly; if (isArmoredSignedOnly) { - return { isArmored, isCleartext: true, message: await openpgp.readCleartextMessage(new Buf(encrypted).toUtfStr()) }; + return { + isArmored, + isCleartext: true, + message: await openpgp.readCleartextMessage({cleartextMessage: (new Buf(encrypted)).toUtfStr()}) + }; } else if (isArmoredEncrypted) { - return { isArmored, isCleartext: false, message: await openpgp.readArmored(new Buf(encrypted).toUtfStr()) }; + return { + isArmored, + isCleartext: false, + message: await openpgp.readMessage({armoredMessage: (new Buf(encrypted)).toUtfStr()}) + }; } else if (encrypted instanceof Uint8Array) { - return { isArmored, isCleartext: false, message: await openpgp.read(encrypted) }; + return { + isArmored, + isCleartext: false, + message: await openpgp.readMessage({binaryMessage: encrypted}) + }; } throw new Error('Message does not have armor headers'); } diff --git a/Core/source/core/types/openpgp.d.ts b/Core/source/core/types/openpgp.d.ts index 85054ae8f..487f8dcd2 100644 --- a/Core/source/core/types/openpgp.d.ts +++ b/Core/source/core/types/openpgp.d.ts @@ -891,4 +891,5 @@ export namespace enums { mime = 109 } } + } // namespace OpenPGP From e6a5f811bceda66c746278ea3c71f03b459d3a63 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 3 Feb 2022 22:39:05 +0200 Subject: [PATCH 014/179] wip --- Core/source/core/pgp-key.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index ba26437a3..007221338 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -70,7 +70,7 @@ export interface KeyDetails { curve?: string; }; } -export type PrvPacket = (OpenPGP.packet.SecretKey | OpenPGP.packet.SecretSubkey); +export type PrvPacket = (OpenPGP.SecretKey | OpenPGP.SecretSubkey); export class PgpKey { public static create = async (userIds: { name: string, email: string }[], variant: KeyAlgo, passphrase: string): @@ -95,7 +95,7 @@ export class PgpKey { if (fromCache) { return fromCache; } - const { keys: [key] } = await openpgp.readArmored(armoredKey); + const key = await openpgp.readKey({armoredKey: armoredKey}); if (key?.isPrivate()) { Store.armoredKeyCacheSet(armoredKey, key); } From 8f14ee40873b36f0b5b01870eb83c642555b3043 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Fri, 4 Feb 2022 09:14:59 +0200 Subject: [PATCH 015/179] wip --- Core/source/core/pgp-key.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index 007221338..16098d001 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -70,18 +70,18 @@ export interface KeyDetails { curve?: string; }; } -export type PrvPacket = (OpenPGP.SecretKey | OpenPGP.SecretSubkey); +export type PrvPacket = (OpenPGP.SecretKeyPacket | OpenPGP.SecretSubkeyPacket); export class PgpKey { - public static create = async (userIds: { name: string, email: string }[], variant: KeyAlgo, passphrase: string): + public static create = async (userIds: OpenPGP.UserID[], variant: KeyAlgo, passphrase: string): Promise<{ private: string, public: string }> => { - const opt: OpenPGP.KeyOptions = { userIds, passphrase }; + const opt: OpenPGP.KeyOptions = { userIDs: userIds, passphrase }; if (variant === 'curve25519') { opt.curve = 'curve25519'; } else if (variant === 'rsa2048') { - opt.numBits = 2048; + opt.rsaBits = 2048; } else { - opt.numBits = 4096; + opt.rsaBits = 4096; } const k = await openpgp.generateKey(opt); return { public: k.publicKeyArmored, private: k.privateKeyArmored }; From 48a1603e910f100da7cc28cb191c92d7885bd7ba Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Fri, 4 Feb 2022 09:39:51 +0200 Subject: [PATCH 016/179] wip --- Core/source/core/pgp-key.ts | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index 16098d001..b4aa349fc 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -74,17 +74,16 @@ export type PrvPacket = (OpenPGP.SecretKeyPacket | OpenPGP.SecretSubkeyPacket); export class PgpKey { public static create = async (userIds: OpenPGP.UserID[], variant: KeyAlgo, passphrase: string): - Promise<{ private: string, public: string }> => { - const opt: OpenPGP.KeyOptions = { userIDs: userIds, passphrase }; - if (variant === 'curve25519') { - opt.curve = 'curve25519'; - } else if (variant === 'rsa2048') { - opt.rsaBits = 2048; - } else { - opt.rsaBits = 4096; - } - const k = await openpgp.generateKey(opt); - return { public: k.publicKeyArmored, private: k.privateKeyArmored }; + Promise<{ private: string, public: string, revCert: string }> => { + // With openpgp.js v5 Separate declaration of variable of type OpenPGP.KeyOptions + // leads to error when calling generate(). + // I don't know how to overcome this, so just passing "inline" object, which works. + const k = await openpgp.generateKey({ + userIDs: userIds, passphrase: passphrase, format: 'armored', + curve: (variant === 'curve25519' ? 'curve25519' : undefined), + rsaBits: (variant === 'curve25519' ? undefined : (variant === 'rsa2048' ? 2048 : 4096)) + }); + return { public: k.publicKey, private: k.privateKey, revCert: k.revocationCertificate }; } /** @@ -103,7 +102,8 @@ export class PgpKey { } /** - * Read many keys, could be armored or binary, in single armor or separately, useful for importing keychains of various formats + * Read many keys, could be armored or binary, in single armor or separately, + * useful for importing keychains of various formats */ public static readMany = async (fileData: Buf): Promise<{ keys: OpenPGP.Key[], errs: Error[] }> => { const allKeys: OpenPGP.Key[] = []; @@ -112,9 +112,9 @@ export class PgpKey { const armoredPublicKeyBlocks = blocks.filter(block => block.type === 'publicKey' || block.type === 'privateKey'); const pushKeysAndErrs = async (content: string | Buf, type: 'readArmored' | 'read') => { try { - const { err, keys } = type === 'readArmored' ? await openpgp.readArmored(content.toString()) - : await openpgp.read(typeof content === 'string' ? Buf.fromUtfStr(content) : content); - allErrs.push(...(err || [])); + const keys = type === 'readArmored' + ? await openpgp.readKeys({armoredKeys: content.toString()}) + : await openpgp.readKeys({binaryKeys: (typeof content === 'string' ? Buf.fromUtfStr(content) : content)}); allKeys.push(...keys); } catch (e) { allErrs.push(e instanceof Error ? e : new Error(String(e))); @@ -130,7 +130,7 @@ export class PgpKey { return { keys: allKeys, errs: allErrs }; } - public static isPacketPrivate = (p: OpenPGP.packet.AnyKeyPacket): p is PrvPacket => { + public static isPacketPrivate = (p: OpenPGP.AnyKeyPacket): p is PrvPacket => { return p.tag === openpgp.enums.packet.secretKey || p.tag === openpgp.enums.packet.secretSubkey; } From 4b033d88a4f0d5e7275d5554b96c467e7e6e7cf7 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Fri, 4 Feb 2022 19:25:38 +0200 Subject: [PATCH 017/179] wip --- Core/source/core/pgp-key.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index b4aa349fc..970da5773 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -9,6 +9,7 @@ import { PgpArmor } from './pgp-armor'; import { Store } from '../platform/store'; import { mnemonic } from './mnemonic'; import { openpgp } from './pgp'; +import { PrivateKey, SecretKeyPacket, SecretSubkeyPacket } from 'openpgp'; export type Contact = { email: string; @@ -131,7 +132,7 @@ export class PgpKey { } public static isPacketPrivate = (p: OpenPGP.AnyKeyPacket): p is PrvPacket => { - return p.tag === openpgp.enums.packet.secretKey || p.tag === openpgp.enums.packet.secretSubkey; + return p instanceof SecretKeyPacket || p instanceof SecretSubkeyPacket; } public static decrypt = async (prv: OpenPGP.Key, passphrase: string, optionalKeyid?: OpenPGP.KeyID, optionalBehaviorFlag?: 'OK-IF-ALREADY-DECRYPTED'): Promise => { From 48083bdbca48ff0456831ed368ac5aca7db93c6b Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Fri, 4 Feb 2022 19:37:47 +0200 Subject: [PATCH 018/179] wip --- Core/source/core/pgp-key.ts | 9 +++++---- Core/source/core/types/openpgp.d.ts | 6 +++++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index 970da5773..d84b0cf36 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -175,7 +175,7 @@ export class PgpKey { if (encryptedPacketCount) { throw new Error(`Cannot encrypt a key that has ${encryptedPacketCount} of ${secretPackets.length} private packets still encrypted`); } - await prv.encrypt(passphrase); + await ((prv as unknown) as OpenPGP.BaseSecretKeyPacket).encrypt(passphrase); } public static normalize = async (armored: string): Promise<{ normalized: string, keys: OpenPGP.Key[] }> => { @@ -183,11 +183,12 @@ export class PgpKey { let keys: OpenPGP.Key[] = []; armored = PgpArmor.normalize(armored, 'key'); if (RegExp(PgpArmor.headers('publicKey', 're').begin).test(armored)) { - keys = (await openpgp.readArmored(armored)).keys; + keys = (await openpgp.readKeys({armoredKeys: armored})); } else if (RegExp(PgpArmor.headers('privateKey', 're').begin).test(armored)) { - keys = (await openpgp.readArmored(armored)).keys; + keys = (await openpgp.readKeys({armoredKeys: armored})); } else if (RegExp(PgpArmor.headers('encryptedMsg', 're').begin).test(armored)) { - keys = [new OpenPGP.Key((await openpgp.message.readArmored(armored)).packets)]; + const msg = await openpgp.readMessage({armoredMessage: armored}); + keys = [new OpenPGP.PublicKey(msg.packets as OpenPGP.PacketList)]; } for (const k of keys) { for (const u of k.users) { diff --git a/Core/source/core/types/openpgp.d.ts b/Core/source/core/types/openpgp.d.ts index 487f8dcd2..c51e3680d 100644 --- a/Core/source/core/types/openpgp.d.ts +++ b/Core/source/core/types/openpgp.d.ts @@ -7,7 +7,9 @@ * - Errietta Kostala */ -declare namespace OpenPGP { + // ----- BEGIN ADDED BY FLOWCRYPT ----- + declare namespace OpenPGP { + // ----- END ADDED BY FLOWCRYPT ----- /* ############## v5 KEY #################### */ // The Key and PublicKey types can be used interchangably since TS cannot detect the difference, as they have the same class properties. @@ -892,4 +894,6 @@ export namespace enums { } } +// ----- BEGIN ADDED BY FLOWCRYPT ----- } // namespace OpenPGP +// ----- END ADDED BY FLOWCRYPT ----- From e096883ff284d5750949d1bae58da54fa1934d5a Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Fri, 4 Feb 2022 19:56:59 +0200 Subject: [PATCH 019/179] wip --- Core/source/core/pgp-key.ts | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index d84b0cf36..1f02927e2 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -10,6 +10,7 @@ import { Store } from '../platform/store'; import { mnemonic } from './mnemonic'; import { openpgp } from './pgp'; import { PrivateKey, SecretKeyPacket, SecretSubkeyPacket } from 'openpgp'; +import { str_to_hex } from '../platform/util'; export type Contact = { email: string; @@ -206,11 +207,8 @@ export class PgpKey { if (!key) { return undefined; } else if (key instanceof OpenPGP.Key) { - if (!key.primaryKey.getFingerprintBytes()) { - return undefined; - } try { - const fp = key.primaryKey.getFingerprint().toUpperCase(); + const fp = key.getFingerprint().toUpperCase(); if (formatting === 'spaced') { return fp.replace(/(.{4})/g, '$1 ').trim(); } @@ -236,7 +234,7 @@ export class PgpKey { if (!keyOrFingerprintOrBytes) { return undefined; } else if (typeof keyOrFingerprintOrBytes === 'string' && keyOrFingerprintOrBytes.length === 8) { - return openpgp.util.str_to_hex(keyOrFingerprintOrBytes).toUpperCase(); + return str_to_hex(keyOrFingerprintOrBytes).toUpperCase(); } else if (typeof keyOrFingerprintOrBytes === 'string' && keyOrFingerprintOrBytes.length === 40) { return keyOrFingerprintOrBytes.substr(-16); } else if (typeof keyOrFingerprintOrBytes === 'string' && keyOrFingerprintOrBytes.length === 49) { @@ -260,7 +258,7 @@ export class PgpKey { if (!PgpKey.fingerprint(armored)) { return false; } - const { keys: [pubkey] } = await openpgp.readArmored(armored); + const pubkey = await openpgp.readKey({armoredKey: armored}); if (!pubkey) { return false; } @@ -274,7 +272,7 @@ export class PgpKey { if (!key) { return false; } - const exp = await key.getExpirationTime('encrypt'); + const exp = await key.getExpirationTime(); if (exp === Infinity || !exp) { return false; } @@ -301,7 +299,7 @@ export class PgpKey { public static dateBeforeExpiration = async (key: OpenPGP.Key | string): Promise => { const openPgpKey = typeof key === 'string' ? await PgpKey.read(key) : key; - const expires = await openPgpKey.getExpirationTime('encrypt'); + const expires = await openPgpKey.getExpirationTime(); if (expires instanceof Date && expires.getTime() < Date.now()) { // expired return new Date(expires.getTime() - 1000); } @@ -315,10 +313,10 @@ export class PgpKey { public static details = async (k: OpenPGP.Key): Promise => { const keys = k.getKeys(); - const algoInfo = k.primaryKey.getAlgorithmInfo(); + const algoInfo = k.getAlgorithmInfo(); const algo = { algorithm: algoInfo.algorithm, bits: algoInfo.bits, curve: (algoInfo as any).curve, algorithmId: openpgp.enums.publicKey[algoInfo.algorithm] }; - const created = k.primaryKey.created.getTime() / 1000; - const exp = await k.getExpirationTime('encrypt'); + const created = k.getCreationTime().getTime() / 1000; + const exp = await k.getExpirationTime(); const expiration = exp === Infinity || !exp ? undefined : (exp as Date).getTime() / 1000; const lastModified = await PgpKey.lastSig(k) / 1000; const ids: KeyDetails$ids[] = []; @@ -337,7 +335,7 @@ export class PgpKey { isFullyDecrypted: k.isPrivate() ? k.isFullyDecrypted() : undefined, isFullyEncrypted: k.isPrivate() ? k.isFullyEncrypted() : undefined, public: k.toPublic().armor(), - users: k.getUserIds(), + users: k.getUserIDs(), ids, algo, created, @@ -353,17 +351,17 @@ export class PgpKey { */ public static lastSig = async (key: OpenPGP.Key): Promise => { await key.getExpirationTime(); // will force all sigs to be verified - const allSignatures: OpenPGP.packet.Signature[] = []; + const allSignatures: OpenPGP.SignaturePacket[] = []; for (const user of key.users) { allSignatures.push(...user.selfCertifications); } - for (const subKey of key.subKeys) { + for (const subKey of key.subkeys) { allSignatures.push(...subKey.bindingSignatures); } - allSignatures.sort((a, b) => b.created.getTime() - a.created.getTime()); + allSignatures.sort((a, b) => (b.created ? b.created.getTime() : 0) - (a.created ? a.created.getTime() : 0)); const newestSig = allSignatures.find(sig => sig.verified === true); if (newestSig) { - return newestSig.created.getTime(); + return newestSig.created ? newestSig.created.getTime() : 0; } throw new Error('No valid signature found in key'); } From 5dea93ed2ec080bff7f6c51c15537b52217495b4 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Fri, 4 Feb 2022 20:06:25 +0200 Subject: [PATCH 020/179] wip --- Core/source/core/pgp.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Core/source/core/pgp.ts b/Core/source/core/pgp.ts index 8ffa57744..ef553eaf3 100644 --- a/Core/source/core/pgp.ts +++ b/Core/source/core/pgp.ts @@ -27,7 +27,8 @@ if (typeof openpgp !== 'undefined') { // in certain environments, eg browser con // only encrypted keys have s2k (decrypted keys don't needed, already decrypted) // if s2k is present and it indicates it's a dummy key, filter it out // if s2k is not present, it's a decrypted real key (not dummy) - const nonDummyPrvPackets = prvPackets.filter(p => !p.s2k || p.s2k.type !== 'gnu-dummy'); + // openpgp.js v5 provides isDummy() instead. + const nonDummyPrvPackets = prvPackets.filter(p => !p.isDummy()); if (!nonDummyPrvPackets.length) { throw new Error("This key only has a gnu-dummy private packet, with no actual secret keys."); } From a6139ed82bfa40fba08abe1b1f42548888a5d9a0 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Fri, 4 Feb 2022 20:25:14 +0200 Subject: [PATCH 021/179] wip --- Core/source/core/pgp-key.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index 1f02927e2..493ecca8b 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -367,7 +367,8 @@ export class PgpKey { } public static revoke = async (key: OpenPGP.Key): Promise => { - if (! await key.isRevoked()) { + if (! await key.isRevoked(null)) { + openpgp.revokeKey({key: key.keyPacket}); key = await key.revoke({}); } const certificate = await key.getRevocationCertificate(); From f4401e53fce889afdf6af5a1f09316bdd3b35822 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sat, 5 Feb 2022 18:56:37 +0200 Subject: [PATCH 022/179] wip --- Core/source/core/pgp-key.ts | 10 ++++++---- Core/source/core/pgp-msg.ts | 22 ++++++++++++++-------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index 493ecca8b..b9c343b66 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -367,15 +367,17 @@ export class PgpKey { } public static revoke = async (key: OpenPGP.Key): Promise => { - if (! await key.isRevoked(null)) { - openpgp.revokeKey({key: key.keyPacket}); - key = await key.revoke({}); + // It was call to isRevoked(), but it turns that the whole logic truns in to just this: + if (key.revocationSignatures.length == 0) { + if (!key.isPrivate()) throw Error('Revocation of public key not implemented'); + const keypair = await openpgp.revokeKey({key: key as OpenPGP.PrivateKey, format: 'object'}); + key = keypair.privateKey; } const certificate = await key.getRevocationCertificate(); if (!certificate || typeof certificate === 'string') { return certificate || undefined; } else { - return await openpgp.stream.readToEnd(certificate); + return await certificate.read // TODO read whole certifcate, not sure how } } } diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index cae9743b1..a1330e04a 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -26,7 +26,7 @@ export namespace PgpMsgMethod { export type VerifyDetached = (arg: Arg.VerifyDetached) => Promise; export type Decrypt = (arg: Arg.Decrypt) => Promise; export type Type = (arg: Arg.Type) => Promise; - export type Encrypt = (arg: Arg.Encrypt) => Promise; + export type Encrypt = (arg: Arg.Encrypt) => Promise>>; } type SortedKeysForDecrypt = { @@ -44,12 +44,12 @@ type DecryptError$error = { type: DecryptErrTypes; message: string; }; type DecryptError$longids = { message: string[]; matching: string[]; chosen: string[]; needPassphrase: string[]; }; export type DecryptError = { success: false; error: DecryptError$error; longids: DecryptError$longids; content?: Buf; - isEncrypted?: boolean; message?: OpenPGP.message.Message | OpenPGP.cleartext.CleartextMessage; + isEncrypted?: boolean; message?: OpenPGP.Message | OpenPGP.CleartextMessage; }; -type PreparedForDecrypt = { isArmored: boolean, isCleartext: true, message: OpenPGP.cleartext.CleartextMessage } - | { isArmored: boolean, isCleartext: false, message: OpenPGP.message.Message }; +type PreparedForDecrypt = { isArmored: boolean, isCleartext: true, message: OpenPGP.CleartextMessage } + | { isArmored: boolean, isCleartext: false, message: OpenPGP.Message }; -type OpenpgpMsgOrCleartext = OpenPGP.message.Message | OpenPGP.cleartext.CleartextMessage; +type OpenpgpMsgOrCleartext = OpenPGP.Message | OpenPGP.CleartextMessage; export type VerifyRes = { signer?: string; @@ -100,7 +100,13 @@ export class PgpMsg { // This does not 100% mean it's OpenPGP message // But it's a good indication that it may const t = openpgp.enums.packet; - const msgTpes = [t.symEncryptedIntegrityProtected, t.modificationDetectionCode, t.symEncryptedAEADProtected, t.symmetricallyEncrypted, t.compressed]; + const msgTpes = [ + t.symEncryptedIntegrityProtectedData, + t.modificationDetectionCode, + t.aeadEncryptedData, + t.symmetricallyEncryptedData, + t.compressedData + ]; return { armored: false, type: msgTpes.includes(tagNumber) ? 'encryptedMsg' : 'publicKey' }; } } @@ -116,8 +122,8 @@ export class PgpMsg { * Returns signature if detached=true, armored */ public static sign = async (signingPrv: OpenPGP.Key, data: string, detached = false): Promise => { - const message = openpgp.cleartext.fromText(data); - const signRes = await openpgp.sign({ message, armor: true, privateKeys: [signingPrv], detached }); + const message = await openpgp.createCleartextMessage({text: data}); + const signRes = await openpgp.sign({ message, format: 'armored', privateKeys: [signingPrv], detached }); if (detached) { if (typeof signRes.signature !== 'string') { throw new Error('signRes.signature unexpectedly not a string when creating detached signature'); From 5199534184c146fde932b6e1491ec03318ec4469 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sat, 5 Feb 2022 19:09:06 +0200 Subject: [PATCH 023/179] wip --- Core/source/core/pgp-msg.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index a1330e04a..44d8d25b5 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -123,7 +123,7 @@ export class PgpMsg { */ public static sign = async (signingPrv: OpenPGP.Key, data: string, detached = false): Promise => { const message = await openpgp.createCleartextMessage({text: data}); - const signRes = await openpgp.sign({ message, format: 'armored', privateKeys: [signingPrv], detached }); + const signRes = await openpgp.sign({ message, signingKeys: (signingPrv as OpenPGP.PrivateKey), detached }); if (detached) { if (typeof signRes.signature !== 'string') { throw new Error('signRes.signature unexpectedly not a string when creating detached signature'); @@ -133,7 +133,7 @@ export class PgpMsg { return await openpgp.stream.readToEnd((signRes as OpenPGP.SignArmorResult).data); } - public static verify = async (msgOrVerResults: OpenpgpMsgOrCleartext | OpenPGP.message.Verification[], pubs: OpenPGP.Key[]): Promise => { + public static verify = async (msgOrVerResults: OpenpgpMsgOrCleartext | OpenPGP.Verification[], pubs: OpenPGP.Key[]): Promise => { const sig: VerifyRes = { match: null }; // tslint:disable-line:no-null-keyword try { // While this looks like bad method API design, it's here to ensure execution order when 1) reading data, 2) verifying, 3) processing signatures From df8aae868fb475ccf712ac3260efe5b95f6d5174 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sat, 5 Feb 2022 19:25:07 +0200 Subject: [PATCH 024/179] wip --- Core/source/core/pgp-msg.ts | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index 44d8d25b5..480d542e2 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -123,20 +123,25 @@ export class PgpMsg { */ public static sign = async (signingPrv: OpenPGP.Key, data: string, detached = false): Promise => { const message = await openpgp.createCleartextMessage({text: data}); - const signRes = await openpgp.sign({ message, signingKeys: (signingPrv as OpenPGP.PrivateKey), detached }); - if (detached) { - if (typeof signRes.signature !== 'string') { - throw new Error('signRes.signature unexpectedly not a string when creating detached signature'); - } - return signRes.signature; - } - return await openpgp.stream.readToEnd((signRes as OpenPGP.SignArmorResult).data); + const signRes = await openpgp.sign({ + message, + signingKeys: (signingPrv as OpenPGP.PrivateKey), + detached, + format: 'armored' + }); + return signRes; } - public static verify = async (msgOrVerResults: OpenpgpMsgOrCleartext | OpenPGP.Verification[], pubs: OpenPGP.Key[]): Promise => { + public static verify = async ( + msgOrVerResults: OpenpgpMsgOrCleartext | OpenPGP.VerificationResult[], + pubs: OpenPGP.Key[] + ): Promise => { const sig: VerifyRes = { match: null }; // tslint:disable-line:no-null-keyword try { - // While this looks like bad method API design, it's here to ensure execution order when 1) reading data, 2) verifying, 3) processing signatures + // While this looks like bad method API design, it's here to ensure execution order when: + // 1. reading data + // 2. verifying + // 3. processing signatures // Else it will hang trying to read a stream: https://github.com/openpgpjs/openpgpjs/issues/916#issuecomment-510620625 const verifyResults = Array.isArray(msgOrVerResults) ? msgOrVerResults : await msgOrVerResults.verify(pubs); for (const verifyRes of verifyResults) { @@ -147,7 +152,7 @@ export class PgpMsg { sig.match = (sig.match === true || sig.match === null) && await verifyRes.verified; if (!sig.signer) { // todo - currently only the first signer will be reported. Should we be showing all signers? How common is that? - sig.signer = await PgpKey.longid(verifyRes.keyid.bytes); + sig.signer = await PgpKey.longid(verifyRes.keyID.bytes); } } } catch (verifyErr) { @@ -163,12 +168,13 @@ export class PgpMsg { } public static verifyDetached: PgpMsgMethod.VerifyDetached = async ({ plaintext, sigText, verificationPubkeys }) => { - const message = openpgp.message.fromText(Buf.fromUint8(plaintext).toUtfStr()); + const message = await openpgp.createMessage({text: Buf.fromUint8(plaintext).toUtfStr()}); await message.appendSignature(Buf.fromUint8(sigText).toUtfStr()); const keys = await PgpMsg.getSortedKeys([], message); if (verificationPubkeys) { for (const verificationPubkey of verificationPubkeys) { - keys.forVerification.push(...(await openpgp.readArmored(verificationPubkey)).keys); + const k = await openpgp.readKeys({armoredKeys: verificationPubkey}); + keys.forVerification.push(...k); } } return await PgpMsg.verify(message, keys.forVerification); From 2169ee3309f6f5804b267cfe7077b294c939ea8a Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sat, 5 Feb 2022 19:39:54 +0200 Subject: [PATCH 025/179] wip --- Core/source/core/pgp-msg.ts | 47 +++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index 480d542e2..2ef15e5fa 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -200,28 +200,46 @@ export class PgpMsg { return { success: true, content: Buf.fromUtfStr(text), isEncrypted, signature }; } if (!keys.prvMatching.length && !msgPwd) { - return { success: false, error: { type: DecryptErrTypes.keyMismatch, message: 'Missing appropriate key' }, message: prepared.message, longids, isEncrypted }; + return { + success: false, + error: { type: DecryptErrTypes.keyMismatch, message: 'Missing appropriate key' }, + message: prepared.message, + longids, + isEncrypted + }; } if (!keys.prvForDecryptDecrypted.length && !msgPwd) { - return { success: false, error: { type: DecryptErrTypes.needPassphrase, message: 'Missing pass phrase' }, message: prepared.message, longids, isEncrypted }; + return { + success: false, + error: { type: DecryptErrTypes.needPassphrase, message: 'Missing pass phrase' }, + message: prepared.message, + longids, + isEncrypted + }; } try { - const packets = (prepared.message as OpenPGP.message.Message).packets; - const isSymEncrypted = packets.filter(p => p.tag === openpgp.enums.packet.symEncryptedSessionKey).length > 0; - const isPubEncrypted = packets.filter(p => p.tag === openpgp.enums.packet.publicKeyEncryptedSessionKey).length > 0; + const packets = (prepared.message as OpenPGP.Message).packets; + const isSymEncrypted = packets.filterByTag(openpgp.enums.packet.symEncryptedSessionKey).length > 0; + const isPubEncrypted = packets.filterByTag(openpgp.enums.packet.publicKeyEncryptedSessionKey).length > 0; if (isSymEncrypted && !isPubEncrypted && !msgPwd) { - return { success: false, error: { type: DecryptErrTypes.usePassword, message: 'Use message password' }, longids, isEncrypted }; + return { + success: false, + error: { type: DecryptErrTypes.usePassword, message: 'Use message password' }, + longids, + isEncrypted + }; } const passwords = msgPwd ? [msgPwd] : undefined; const privateKeys = keys.prvForDecryptDecrypted.map(ki => ki.decrypted!); - const decrypted = await (prepared.message as OpenPGP.message.Message).decrypt(privateKeys, passwords, undefined, false); + const decrypted = await (prepared.message as OpenPGP.Message).decrypt(privateKeys, passwords, undefined, false); // we can only figure out who signed the msg once it's decrypted await PgpMsg.cryptoMsgGetSignedBy(decrypted, keys); await PgpMsg.populateKeysForVerification(keys, verificationPubkeys); const verifyResults = keys.signedBy.length ? await decrypted.verify(keys.forVerification) : undefined; // verify first to prevent stream hang const content = new Buf(await openpgp.stream.readToEnd(decrypted.getLiteralData()!)); // read content second to prevent stream hang const signature = verifyResults ? await PgpMsg.verify(verifyResults, []) : undefined; // evaluate verify results third to prevent stream hang - if (!prepared.isCleartext && (prepared.message as OpenPGP.message.Message).packets.filterByTag(openpgp.enums.packet.symmetricallyEncrypted).length) { + if (!prepared.isCleartext && (prepared.message as OpenPGP.Message).packets + .filterByTag(openpgp.enums.packet.symmetricallyEncryptedData).length) { const noMdc = 'Security threat!\n\nMessage is missing integrity checks (MDC). The sender should update their outdated software and resend.'; return { success: false, content, error: { type: DecryptErrTypes.noMdc, message: noMdc }, message: prepared.message, longids, isEncrypted }; } @@ -232,14 +250,13 @@ export class PgpMsg { } public static encrypt: PgpMsgMethod.Encrypt = async ({ pubkeys, signingPrv, pwd, data, filename, armor, date }) => { - const message = openpgp.message.fromBinary(data, filename, date); - - const options: OpenPGP.EncryptOptions = { armor, message, date }; + const message = await openpgp.createMessage({binary: data, filename, date}); + const options: OpenPGP.EncryptOptions = { format: (armor ? 'armored' : 'binary'), message, date }; if (pubkeys) { - options.publicKeys = []; + options.encryptionKeys = []; for (const armoredPubkey of pubkeys) { - const { keys: publicKeys } = await openpgp.readArmored(armoredPubkey); - options.publicKeys.push(...publicKeys); + const publicKeys = await openpgp.readKeys({armoredKeys: armoredPubkey}); + options.encryptionKeys.push(...publicKeys); } } if (pwd) { @@ -249,7 +266,7 @@ export class PgpMsg { throw new Error('no-pubkeys-no-challenge'); } if (signingPrv && typeof signingPrv.isPrivate !== 'undefined' && signingPrv.isPrivate()) { // tslint:disable-line:no-unbound-method - only testing if exists - options.privateKeys = [signingPrv]; + options.signingKeys = signingPrv; } return await openpgp.encrypt(options); } From a1d529a4f1f8e96ef57e77765872eb8c9c2c217a Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sat, 5 Feb 2022 19:41:43 +0200 Subject: [PATCH 026/179] wip --- Core/source/core/pgp-msg.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index 2ef15e5fa..daaf6c098 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -272,11 +272,11 @@ export class PgpMsg { } public static diagnosePubkeys: PgpMsgMethod.DiagnosePubkeys = async ({ privateKis, message }) => { - const m = await openpgp.message.readArmored(Buf.fromUint8(message).toUtfStr()); - const msgKeyIds = m.getEncryptionKeyIds ? m.getEncryptionKeyIds() : []; + const m = await openpgp.readMessage({ armoredMessage: Buf.fromUint8(message).toUtfStr() }); + const msgKeyIds = m.getEncryptionKeyIDs ? m.getEncryptionKeyIDs() : []; const localKeyIds: OpenPGP.KeyID[] = []; for (const k of await Promise.all(privateKis.map(ki => PgpKey.read(ki.public)))) { - localKeyIds.push(...k.getKeyIds()); + localKeyIds.push(...k.getKeyIDs()); } const diagnosis = { found_match: false, receivers: msgKeyIds.length }; for (const msgKeyId of msgKeyIds) { From 5266d3079c1cba9dc511cd4aee6a7d83c5ad2a0a Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sat, 5 Feb 2022 19:45:02 +0200 Subject: [PATCH 027/179] wip --- Core/source/core/pgp-msg.ts | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index daaf6c098..ce62d6423 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -295,10 +295,16 @@ export class PgpMsg { // `${linkText}\n` // thus we use RegEx so that it works on both browser and node if (decryptedContent.includes('class="cryptup_file"')) { - decryptedContent = decryptedContent.replace(/[^<]+<\/a>\n?/gm, (_, url, fcData) => { + decryptedContent = decryptedContent.replace( + /[^<]+<\/a>\n?/gm, (_, url, fcData) => { const a = Str.htmlAttrDecode(String(fcData)); if (PgpMsg.isFcAttLinkData(a)) { - blocks.push(MsgBlock.fromAtt('encryptedAttLink', '', { type: a.type, name: a.name, length: a.size, url: String(url) })); + blocks.push(MsgBlock.fromAtt('encryptedAttLink', '', { + type: a.type, + name: a.name, + length: a.size, + url: String(url) + })); } return ''; }); @@ -318,7 +324,8 @@ export class PgpMsg { return normalized; } - // public static extractFcReplyToken = (decryptedContent: string) => { // todo - used exclusively on the web - move to a web package + // public static extractFcReplyToken = (decryptedContent: string) => { + // // todo - used exclusively on the web - move to a web package // const fcTokenElement = $(`
${decryptedContent}
`).find('.cryptup_reply'); // if (fcTokenElement.length) { // const fcData = fcTokenElement.attr('cryptup-data'); @@ -339,7 +346,7 @@ export class PgpMsg { private static cryptoMsgGetSignedBy = async (msg: OpenpgpMsgOrCleartext, keys: SortedKeysForDecrypt) => { keys.signedBy = Value.arr.unique(await PgpKey.longids( - msg.getSigningKeyIds ? msg.getSigningKeyIds() : [])); + msg.getSigningKeyIDs ? msg.getSigningKeyIDs() : [])); } private static populateKeysForVerification = async (keys: SortedKeysForDecrypt, @@ -347,7 +354,7 @@ export class PgpMsg { if (typeof verificationPubkeys !== 'undefined') { keys.forVerification = []; for (const verificationPubkey of verificationPubkeys) { - const { keys: keysForVerification } = await openpgp.readArmored(verificationPubkey); + const keysForVerification = await openpgp.readKeys({ armoredKeys: verificationPubkey }); keys.forVerification.push(...keysForVerification); } } @@ -363,8 +370,8 @@ export class PgpMsg { prvForDecryptDecrypted: [], prvForDecryptWithoutPassphrases: [], }; - const encryptedForKeyids = msg instanceof openpgp.message.Message - ? (msg as OpenPGP.message.Message).getEncryptionKeyIds() + const encryptedForKeyids = msg instanceof openpgp.Message + ? (msg as OpenPGP.Message).getEncryptionKeyIDs() : []; keys.encryptedFor = await PgpKey.longids(encryptedForKeyids); await PgpMsg.cryptoMsgGetSignedBy(msg, keys); @@ -378,7 +385,7 @@ export class PgpMsg { // encrypted for subkeys, thus we have to parse the key to get the info // we are filtering here to avoid a significant performance issue of having // to attempt decrypting with all keys simultaneously - for (const longid of await Promise.all(ki.parsed.getKeyIds().map(({ bytes }) => PgpKey.longid(bytes)))) { + for (const longid of await Promise.all(ki.parsed.getKeyIDs().map(({ bytes }) => PgpKey.longid(bytes)))) { if (keys.encryptedFor.includes(longid!)) { keys.prvMatching.push(ki); break; @@ -408,7 +415,7 @@ export class PgpMsg { private static matchingKeyids = (key: OpenPGP.Key, encryptedFor: OpenPGP.KeyID[]): OpenPGP.KeyID[] => { const msgKeyidBytesArr = (encryptedFor || []).map(kid => kid.bytes); - return key.getKeyIds().filter(kid => msgKeyidBytesArr.includes(kid.bytes)); + return key.getKeyIDs().filter(kid => msgKeyidBytesArr.includes(kid.bytes)); } private static decryptKeyFor = async (prv: OpenPGP.Key, passphrase: string, matchingKeyIds: OpenPGP.KeyID[]): Promise => { From 6caa9e9cf7a60c8d3798a95bfb569f7d096dceba Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sat, 5 Feb 2022 19:54:14 +0200 Subject: [PATCH 028/179] wip --- Core/source/core/pgp-msg.ts | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index ce62d6423..b2f243d4d 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -16,9 +16,22 @@ import { openpgp } from './pgp'; export namespace PgpMsgMethod { export namespace Arg { - export type Encrypt = { pubkeys: string[], signingPrv?: OpenPGP.Key, pwd?: string, data: Uint8Array, filename?: string, armor: boolean, date?: Date }; + export type Encrypt = { + pubkeys: string[], + signingPrv?: OpenPGP.Key, + pwd?: string, + data: Uint8Array, + filename?: string, + armor: boolean, + date?: Date + }; export type Type = { data: Uint8Array }; - export type Decrypt = { kisWithPp: PrvKeyInfo[], encryptedData: Uint8Array, msgPwd?: string, verificationPubkeys?: string[] }; + export type Decrypt = { + kisWithPp: PrvKeyInfo[], + encryptedData: Uint8Array, + msgPwd?: string, + verificationPubkeys?: string[] + }; export type DiagnosePubkeys = { privateKis: KeyInfo[], message: Uint8Array }; export type VerifyDetached = { plaintext: Uint8Array, sigText: Uint8Array, verificationPubkeys?: string[] }; } @@ -251,7 +264,8 @@ export class PgpMsg { public static encrypt: PgpMsgMethod.Encrypt = async ({ pubkeys, signingPrv, pwd, data, filename, armor, date }) => { const message = await openpgp.createMessage({binary: data, filename, date}); - const options: OpenPGP.EncryptOptions = { format: (armor ? 'armored' : 'binary'), message, date }; + const options: OpenPGP.EncryptOptions = { message, date }; + if (armor) options.format = 'armored'; if (pubkeys) { options.encryptionKeys = []; for (const armoredPubkey of pubkeys) { @@ -265,7 +279,8 @@ export class PgpMsg { if (!pubkeys && !pwd) { throw new Error('no-pubkeys-no-challenge'); } - if (signingPrv && typeof signingPrv.isPrivate !== 'undefined' && signingPrv.isPrivate()) { // tslint:disable-line:no-unbound-method - only testing if exists + // tslint:disable-next-line:no-unbound-method - only testing if exists + if (signingPrv && typeof signingPrv.isPrivate !== 'undefined' && signingPrv.isPrivate()) { options.signingKeys = signingPrv; } return await openpgp.encrypt(options); From 4fc6df015bb0ec4d6ee05aa2fb59d4207f9e479c Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sat, 5 Feb 2022 20:03:22 +0200 Subject: [PATCH 029/179] wip --- Core/source/core/pgp-key.ts | 4 ++-- Core/source/core/pgp-msg.ts | 10 +++++----- Core/source/gen-compat-assets.ts | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index b9c343b66..c3305e047 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -9,7 +9,7 @@ import { PgpArmor } from './pgp-armor'; import { Store } from '../platform/store'; import { mnemonic } from './mnemonic'; import { openpgp } from './pgp'; -import { PrivateKey, SecretKeyPacket, SecretSubkeyPacket } from 'openpgp'; +import { SecretKeyPacket, SecretSubkeyPacket } from 'openpgp'; import { str_to_hex } from '../platform/util'; export type Contact = { @@ -377,7 +377,7 @@ export class PgpKey { if (!certificate || typeof certificate === 'string') { return certificate || undefined; } else { - return await certificate.read // TODO read whole certifcate, not sure how + return await openpgp.stream.readToEnd(certificate); } } } diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index b2f243d4d..9a8fe5fb3 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -39,7 +39,7 @@ export namespace PgpMsgMethod { export type VerifyDetached = (arg: Arg.VerifyDetached) => Promise; export type Decrypt = (arg: Arg.Decrypt) => Promise; export type Type = (arg: Arg.Type) => Promise; - export type Encrypt = (arg: Arg.Encrypt) => Promise>>; + export type Encrypt = (arg: Arg.Encrypt) => Promise>>; } type SortedKeysForDecrypt = { @@ -243,8 +243,8 @@ export class PgpMsg { }; } const passwords = msgPwd ? [msgPwd] : undefined; - const privateKeys = keys.prvForDecryptDecrypted.map(ki => ki.decrypted!); - const decrypted = await (prepared.message as OpenPGP.Message).decrypt(privateKeys, passwords, undefined, false); + const privateKeys = keys.prvForDecryptDecrypted.map(ki => ki.decrypted!) as OpenPGP.PrivateKey[]; + const decrypted = await (prepared.message as OpenPGP.Message).decrypt(privateKeys, passwords); // we can only figure out who signed the msg once it's decrypted await PgpMsg.cryptoMsgGetSignedBy(decrypted, keys); await PgpMsg.populateKeysForVerification(keys, verificationPubkeys); @@ -280,10 +280,10 @@ export class PgpMsg { throw new Error('no-pubkeys-no-challenge'); } // tslint:disable-next-line:no-unbound-method - only testing if exists - if (signingPrv && typeof signingPrv.isPrivate !== 'undefined' && signingPrv.isPrivate()) { + if (signingPrv && signingPrv.isPrivate()) { options.signingKeys = signingPrv; } - return await openpgp.encrypt(options); + return await openpgp.encrypt(options as any); } public static diagnosePubkeys: PgpMsgMethod.DiagnosePubkeys = async ({ privateKis, message }) => { diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index 83b25894b..c013f2f7c 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -204,7 +204,7 @@ ava.default('mime-email-plain-html.txt', async t => { ava.default('mime-email-encrypted-inline-text-signed.txt', async t => { const { keys } = getKeypairs('rsa1'); - const signingPrv = (await openpgp.readArmored(keys[0].private)).keys[0]; + const signingPrv = await openpgp.readKey({armoredKey: keys[0].private}) as OpenPGP.PrivateKey; // console.log("rsa1 key fingerprint:" + signingPrv.getFingerprint().toUpperCase()); if (!(await signingPrv.decrypt(keys[0].passphrase))) throw Error('Can\'t decrypt private key'); const { data } = await PgpMsg.encrypt({ data: text, signingPrv: signingPrv, pubkeys, armor: true }) as OpenPGP.EncryptArmorResult; @@ -214,7 +214,7 @@ ava.default('mime-email-encrypted-inline-text-signed.txt', async t => { ava.default('mime-email-plain-signed.txt', async t => { const { keys } = getKeypairs('rsa1'); - const signingPrv = (await openpgp.readArmored(keys[0].private)).keys[0]; + const signingPrv = await openpgp.readKey({armoredKey: keys[0].private}) as OpenPGP.PrivateKey; if (!(await signingPrv.decrypt(keys[0].passphrase))) throw Error('Can\'t decrypt private key'); const data = text.toString(); const signed = await PgpMsg.sign(signingPrv, data); From af630a0354e49cd6ed75c1d44063162950ae42a8 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sat, 5 Feb 2022 20:11:02 +0200 Subject: [PATCH 030/179] wip --- Core/source/core/pgp-msg.ts | 2 +- Core/source/gen-compat-assets.ts | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index 9a8fe5fb3..31e6bfaa6 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -39,7 +39,7 @@ export namespace PgpMsgMethod { export type VerifyDetached = (arg: Arg.VerifyDetached) => Promise; export type Decrypt = (arg: Arg.Decrypt) => Promise; export type Type = (arg: Arg.Type) => Promise; - export type Encrypt = (arg: Arg.Encrypt) => Promise>>; + export type Encrypt = (arg: Arg.Encrypt) => Promise>; } type SortedKeysForDecrypt = { diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index c013f2f7c..89bee1faa 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -146,25 +146,26 @@ const write = async (t: AvaContext, fileContent: Buffer | string) => { } ava.default('direct-encrypted-text.txt', async t => { - const { data } = await PgpMsg.encrypt({ data: text, pubkeys, armor: true }) as OpenPGP.EncryptArmorResult; + const data = openpgp.stream.readToEnd(await PgpMsg.encrypt({ data: text, pubkeys, armor: true })); await write(t, data); t.pass(); }); ava.default('direct-encrypted-pgpmime.txt', async t => { - const { data } = await PgpMsg.encrypt({ data: mimePgp(t, text), pubkeys, armor: true }) as OpenPGP.EncryptArmorResult; + const data = openpgp.stream.readToEnd(await PgpMsg.encrypt({ data: mimePgp(t, text), pubkeys, armor: true })); await write(t, data); t.pass(); }); ava.default('direct-encrypted-pgpmime-special-chars.txt', async t => { - const { data } = await PgpMsg.encrypt({ data: mimePgp(t, textSpecialChars), pubkeys, armor: true }) as OpenPGP.EncryptArmorResult; + const data = openpgp.stream.readToEnd( + await PgpMsg.encrypt({ data: mimePgp(t, textSpecialChars), pubkeys, armor: true })); await write(t, data); t.pass(); }); ava.default('direct-encrypted-text-special-chars.txt', async t => { - const { data } = await PgpMsg.encrypt({ data: textSpecialChars, pubkeys, armor: true }) as OpenPGP.EncryptArmorResult; + const data = openpgp.stream.readToEnd(await PgpMsg.encrypt({ data: textSpecialChars, pubkeys, armor: true })); await write(t, data); t.pass(); }); @@ -180,19 +181,19 @@ ava.default('mime-email-plain-with-pubkey.txt', async t => { }); ava.default('mime-email-encrypted-inline-text.txt', async t => { - const { data } = await PgpMsg.encrypt({ data: text, pubkeys, armor: true }) as OpenPGP.EncryptArmorResult; + const data = openpgp.stream.readToEnd(await PgpMsg.encrypt({ data: text, pubkeys, armor: true })); await write(t, mimeEmail(t, data)); t.pass(); }); ava.default('mime-email-encrypted-inline-pgpmime.txt', async t => { - const { data } = await PgpMsg.encrypt({ data: mimePgp(t, text), pubkeys, armor: true }) as OpenPGP.EncryptArmorResult; + const data = openpgp.stream.readToEnd(await PgpMsg.encrypt({ data: mimePgp(t, text), pubkeys, armor: true })); await write(t, mimeEmail(t, data)); t.pass(); }); ava.default('mime-email-encrypted-inline-text-2.txt', async t => { - const { data } = await PgpMsg.encrypt({ data: text, pubkeys, armor: true }) as OpenPGP.EncryptArmorResult; + const data = openpgp.stream.readToEnd(await PgpMsg.encrypt({ data: text, pubkeys, armor: true })); await write(t, textEncoderMimeEmail(t, data)); t.pass(); }); @@ -207,7 +208,8 @@ ava.default('mime-email-encrypted-inline-text-signed.txt', async t => { const signingPrv = await openpgp.readKey({armoredKey: keys[0].private}) as OpenPGP.PrivateKey; // console.log("rsa1 key fingerprint:" + signingPrv.getFingerprint().toUpperCase()); if (!(await signingPrv.decrypt(keys[0].passphrase))) throw Error('Can\'t decrypt private key'); - const { data } = await PgpMsg.encrypt({ data: text, signingPrv: signingPrv, pubkeys, armor: true }) as OpenPGP.EncryptArmorResult; + const data = openpgp.stream.readToEnd( + await PgpMsg.encrypt({ data: text, signingPrv: signingPrv, pubkeys, armor: true })); await write(t, mimeEmail2(t, data)); t.pass(); }); From c514b0405d3be40744381c07e5cfdf5c84808f7c Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 6 Feb 2022 14:51:45 +0200 Subject: [PATCH 031/179] wip --- Core/source/core/pgp-key.ts | 4 +-- Core/source/gen-compat-assets.ts | 57 +++++++++++++++++++++++++------- Core/source/platform/util.ts | 5 +++ 3 files changed, 52 insertions(+), 14 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index c3305e047..e3a6d09e2 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -10,7 +10,7 @@ import { Store } from '../platform/store'; import { mnemonic } from './mnemonic'; import { openpgp } from './pgp'; import { SecretKeyPacket, SecretSubkeyPacket } from 'openpgp'; -import { str_to_hex } from '../platform/util'; +import { readToEnd, str_to_hex } from '../platform/util'; export type Contact = { email: string; @@ -377,7 +377,7 @@ export class PgpKey { if (!certificate || typeof certificate === 'string') { return certificate || undefined; } else { - return await openpgp.stream.readToEnd(certificate); + return await readToEnd(certificate); } } } diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index 89bee1faa..dfe80d954 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -14,11 +14,45 @@ import { AvaContext, getKeypairs, writeFile } from './test/test-utils'; import { PgpMsg } from './core/pgp-msg'; import { Xss } from './platform/xss'; import { openpgp } from './core/pgp'; +import { readToEnd } from './platform/util'; const text = Buffer.from('some\n汉\ntxt'); const textSpecialChars = Buffer.from('> special & other\n> second line'); -const pubkeys = ['-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: FlowCrypt 6.3.5 Gmail Encryption\nComment: Seamlessly send and receive encrypted email\n\nxsBNBFwBWOEBB/9uIqBYIPDQbBqHMvGXhgnm+b2i5rNLXrrGoalrp7wYQ654\nZln/+ffxzttRLRiwRQAOG0z78aMDXAHRfI9d3GaRKTkhTqVY+C02E8NxgB3+\nmbSsF0Ui+oh1//LT1ic6ZnISCA7Q2h2U/DSAPNxDZUMu9kjh9TjkKlR81fiA\nlxuD05ivRxCnmZnzqZtHoUvvCqsENgRjO9a5oWpMwtdItjdRFF7UFKYpfeA+\nct0uUNMRVdPK7MXBEr2FdWiKN1K21dQ1pWiAwj/5cTA8hu5Jue2RcF8FcPfs\nniRihQkNqtLDsfY5no1B3xeSnyO2SES1bAHw8ObXZn/C/6jxFztkn4NbABEB\nAAHNEFRlc3QgPHRAZXN0LmNvbT7CwHUEEAEIACkFAlwBWOEGCwkHCAMCCRA6\nMPTMCpqPEAQVCAoCAxYCAQIZAQIbAwIeAQAA1pMH/R9oEVHaTdEzs/jbsfJk\n6xm2oQ/G7KewtSqawAC6nou0+GKvgICxvkNK+BivMLylut+MJqh2gHuExdzx\nHFNtKH69BzlK7hDBjyyrLuHIxc4YZaxHGe5ny3wF4QkEgfI+C5chH7Bi+jV6\n94L40zEeFO2OhIif8Ti9bRb2Pk6UV5MrsdM0K6J0gTQeTaRecQSg07vO3E8/\nGwfP2Dnq4yHICF/eaop+9QWj8UstEE6nEs7SSTrjIAxwAeZzpkjkXPXTLjz6\nEcS/9EU7B+5v1qwXk1YeW1qerKJn6Qd6hqJ5gkVzq3sy3eODyrEwpNQoAR4J\n8e3VQkKOn9oiAlFTglFeBhfOwE0EXAFY4QEH/2dyWbH3y9+hKk9RxwFzO+5n\nGaqT6Njoh368GEEWgSG11NKlrD8k2y1/R1Nc3xEIWMHSUe1rnWWVONKhupwX\nABTnj8coM5beoxVu9p1oYgum4IwLF0yAtaWll1hjsECm/U33Ok36JDa0iu+d\nRDfXbEo5cX9bzc1QnWdM5tBg2mxRkssbY3eTPXUe4FLcT0WAQ5hjLW0tPneG\nzlu2q9DkmngjDlwGgGhMCa/508wMpgGugE/C4V41EiiTAtOtVzGtdqPGVdoZ\neaYZLc9nTQderaDu8oipaWIwsshYWX4uVVvo7xsx5c5PWXRdI70aUs5IwMRz\nuljbq+SYCNta/uJRYc0AEQEAAcLAXwQYAQgAEwUCXAFY4QkQOjD0zAqajxAC\nGwwAAI03B/9aWF8l1v66Qaw4O8P3VyQn0/PkVWJYVt5KjMW4nexAfM4BlUw6\n97rP5IvfYXNh47Cm8VKqxgcXodzJrouzgwiPFxXmJe5Ug24FOpmeSeIl83Uf\nCzaiIm+B6K5cf2NuHTrr4pElDaQ7RQGH2m2cMcimv4oWU9a0tRjt1e7XQAfQ\nSWoCalUbLBeYORgVAF97MUNqeth6FMT5STjq+AGgnNZ2vdsUnASS/HbQQUUO\naVGVjo29lB6fS+UHT2gV/E/WQInjok5UrUMaFHwpO0VNP057DNyqhZwxaAs5\nBsSgJlOC5hrT+PKlfr9ic75fqnJqmLircB+hVnfhGR9OzH3RCIky\n=VKq5\n-----END PGP PUBLIC KEY BLOCK-----\n']; +const pubkeys = [ + '-----BEGIN PGP PUBLIC KEY BLOCK-----\n' + + 'Version: FlowCrypt 6.3.5 Gmail Encryption\n' + + 'Comment: Seamlessly send and receive encrypted email\n' + + '\n' + + 'xsBNBFwBWOEBB/9uIqBYIPDQbBqHMvGXhgnm+b2i5rNLXrrGoalrp7wYQ654\n' + + 'Zln/+ffxzttRLRiwRQAOG0z78aMDXAHRfI9d3GaRKTkhTqVY+C02E8NxgB3+\n' + + 'mbSsF0Ui+oh1//LT1ic6ZnISCA7Q2h2U/DSAPNxDZUMu9kjh9TjkKlR81fiA\n' + + 'lxuD05ivRxCnmZnzqZtHoUvvCqsENgRjO9a5oWpMwtdItjdRFF7UFKYpfeA+\n' + + 'ct0uUNMRVdPK7MXBEr2FdWiKN1K21dQ1pWiAwj/5cTA8hu5Jue2RcF8FcPfs\n' + + 'niRihQkNqtLDsfY5no1B3xeSnyO2SES1bAHw8ObXZn/C/6jxFztkn4NbABEB\n' + + 'AAHNEFRlc3QgPHRAZXN0LmNvbT7CwHUEEAEIACkFAlwBWOEGCwkHCAMCCRA6\n' + + 'MPTMCpqPEAQVCAoCAxYCAQIZAQIbAwIeAQAA1pMH/R9oEVHaTdEzs/jbsfJk\n' + + '6xm2oQ/G7KewtSqawAC6nou0+GKvgICxvkNK+BivMLylut+MJqh2gHuExdzx\n' + + 'HFNtKH69BzlK7hDBjyyrLuHIxc4YZaxHGe5ny3wF4QkEgfI+C5chH7Bi+jV6\n' + + '94L40zEeFO2OhIif8Ti9bRb2Pk6UV5MrsdM0K6J0gTQeTaRecQSg07vO3E8/\n' + + 'GwfP2Dnq4yHICF/eaop+9QWj8UstEE6nEs7SSTrjIAxwAeZzpkjkXPXTLjz6\n' + + 'EcS/9EU7B+5v1qwXk1YeW1qerKJn6Qd6hqJ5gkVzq3sy3eODyrEwpNQoAR4J\n' + + '8e3VQkKOn9oiAlFTglFeBhfOwE0EXAFY4QEH/2dyWbH3y9+hKk9RxwFzO+5n\n' + + 'GaqT6Njoh368GEEWgSG11NKlrD8k2y1/R1Nc3xEIWMHSUe1rnWWVONKhupwX\n' + + 'ABTnj8coM5beoxVu9p1oYgum4IwLF0yAtaWll1hjsECm/U33Ok36JDa0iu+d\n' + + 'RDfXbEo5cX9bzc1QnWdM5tBg2mxRkssbY3eTPXUe4FLcT0WAQ5hjLW0tPneG\n' + + 'zlu2q9DkmngjDlwGgGhMCa/508wMpgGugE/C4V41EiiTAtOtVzGtdqPGVdoZ\n' + + 'eaYZLc9nTQderaDu8oipaWIwsshYWX4uVVvo7xsx5c5PWXRdI70aUs5IwMRz\n' + + 'uljbq+SYCNta/uJRYc0AEQEAAcLAXwQYAQgAEwUCXAFY4QkQOjD0zAqajxAC\n' + + 'GwwAAI03B/9aWF8l1v66Qaw4O8P3VyQn0/PkVWJYVt5KjMW4nexAfM4BlUw6\n' + + '97rP5IvfYXNh47Cm8VKqxgcXodzJrouzgwiPFxXmJe5Ug24FOpmeSeIl83Uf\n' + + 'CzaiIm+B6K5cf2NuHTrr4pElDaQ7RQGH2m2cMcimv4oWU9a0tRjt1e7XQAfQ\n' + + 'SWoCalUbLBeYORgVAF97MUNqeth6FMT5STjq+AGgnNZ2vdsUnASS/HbQQUUO\n' + + 'aVGVjo29lB6fS+UHT2gV/E/WQInjok5UrUMaFHwpO0VNP057DNyqhZwxaAs5\n' + + 'BsSgJlOC5hrT+PKlfr9ic75fqnJqmLircB+hVnfhGR9OzH3RCIky\n' + + '=VKq5\n' + + '-----END PGP PUBLIC KEY BLOCK-----\n' +]; const subject = (t: AvaContext) => t.title.replace(/\.txt$/, '').replace(/-/g, ' '); @@ -142,30 +176,30 @@ ${Xss.escape(text.toString()).replace(/\n/g, '
')} `.replace(/^\n/, '')); const write = async (t: AvaContext, fileContent: Buffer | string) => { - await writeFile(`./source/assets/compat/${t.title}`, fileContent instanceof Buffer ? fileContent : Buffer.from(fileContent)); + await writeFile(`./source/assets/compat/${t.title}`, + fileContent instanceof Buffer ? fileContent : Buffer.from(fileContent)); } ava.default('direct-encrypted-text.txt', async t => { - const data = openpgp.stream.readToEnd(await PgpMsg.encrypt({ data: text, pubkeys, armor: true })); + const data = await readToEnd(await PgpMsg.encrypt({ data: text, pubkeys, armor: true })); await write(t, data); t.pass(); }); ava.default('direct-encrypted-pgpmime.txt', async t => { - const data = openpgp.stream.readToEnd(await PgpMsg.encrypt({ data: mimePgp(t, text), pubkeys, armor: true })); + const data = await readToEnd(await PgpMsg.encrypt({ data: mimePgp(t, text), pubkeys, armor: true })); await write(t, data); t.pass(); }); ava.default('direct-encrypted-pgpmime-special-chars.txt', async t => { - const data = openpgp.stream.readToEnd( - await PgpMsg.encrypt({ data: mimePgp(t, textSpecialChars), pubkeys, armor: true })); + const data = await readToEnd(await PgpMsg.encrypt({ data: mimePgp(t, textSpecialChars), pubkeys, armor: true })); await write(t, data); t.pass(); }); ava.default('direct-encrypted-text-special-chars.txt', async t => { - const data = openpgp.stream.readToEnd(await PgpMsg.encrypt({ data: textSpecialChars, pubkeys, armor: true })); + const data = await readToEnd(await PgpMsg.encrypt({ data: textSpecialChars, pubkeys, armor: true })); await write(t, data); t.pass(); }); @@ -181,19 +215,19 @@ ava.default('mime-email-plain-with-pubkey.txt', async t => { }); ava.default('mime-email-encrypted-inline-text.txt', async t => { - const data = openpgp.stream.readToEnd(await PgpMsg.encrypt({ data: text, pubkeys, armor: true })); + const data = await readToEnd(await PgpMsg.encrypt({ data: text, pubkeys, armor: true })); await write(t, mimeEmail(t, data)); t.pass(); }); ava.default('mime-email-encrypted-inline-pgpmime.txt', async t => { - const data = openpgp.stream.readToEnd(await PgpMsg.encrypt({ data: mimePgp(t, text), pubkeys, armor: true })); + const data = await readToEnd(await PgpMsg.encrypt({ data: mimePgp(t, text), pubkeys, armor: true })); await write(t, mimeEmail(t, data)); t.pass(); }); ava.default('mime-email-encrypted-inline-text-2.txt', async t => { - const data = openpgp.stream.readToEnd(await PgpMsg.encrypt({ data: text, pubkeys, armor: true })); + const data = await readToEnd(await PgpMsg.encrypt({ data: text, pubkeys, armor: true })); await write(t, textEncoderMimeEmail(t, data)); t.pass(); }); @@ -208,8 +242,7 @@ ava.default('mime-email-encrypted-inline-text-signed.txt', async t => { const signingPrv = await openpgp.readKey({armoredKey: keys[0].private}) as OpenPGP.PrivateKey; // console.log("rsa1 key fingerprint:" + signingPrv.getFingerprint().toUpperCase()); if (!(await signingPrv.decrypt(keys[0].passphrase))) throw Error('Can\'t decrypt private key'); - const data = openpgp.stream.readToEnd( - await PgpMsg.encrypt({ data: text, signingPrv: signingPrv, pubkeys, armor: true })); + const data = await readToEnd(await PgpMsg.encrypt({ data: text, signingPrv: signingPrv, pubkeys, armor: true })); await write(t, mimeEmail2(t, data)); t.pass(); }); diff --git a/Core/source/platform/util.ts b/Core/source/platform/util.ts index 177d047e5..b175c0d11 100644 --- a/Core/source/platform/util.ts +++ b/Core/source/platform/util.ts @@ -83,3 +83,8 @@ export const Uint8Array_to_str = (bytes: Uint8Array): string => { } return result.join(''); } + +export const readToEnd = async (stream: OpenPGP.MaybeStream): Promise => { + // TODO - stream + return ''; +} From 31ec18ecd8e6f9318b7e06619b08a95af7aad174 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 6 Feb 2022 14:54:59 +0200 Subject: [PATCH 032/179] wip --- Core/source/core/pgp-msg.ts | 5 +++-- Core/source/platform/util.ts | 7 ++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index 31e6bfaa6..a09dc18f7 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -13,6 +13,7 @@ import { MsgBlockParser } from './msg-block-parser'; import { PgpArmor } from './pgp-armor'; import { Store } from '../platform/store'; import { openpgp } from './pgp'; +import { readToEnd, readToEndBinary } from '../platform/util'; export namespace PgpMsgMethod { export namespace Arg { @@ -209,7 +210,7 @@ export class PgpMsg { const isEncrypted = !prepared.isCleartext; if (!isEncrypted) { const signature = await PgpMsg.verify(prepared.message, keys.forVerification); - const text = await openpgp.stream.readToEnd(prepared.message.getText()!); + const text = await readToEnd(prepared.message.getText()!); return { success: true, content: Buf.fromUtfStr(text), isEncrypted, signature }; } if (!keys.prvMatching.length && !msgPwd) { @@ -249,7 +250,7 @@ export class PgpMsg { await PgpMsg.cryptoMsgGetSignedBy(decrypted, keys); await PgpMsg.populateKeysForVerification(keys, verificationPubkeys); const verifyResults = keys.signedBy.length ? await decrypted.verify(keys.forVerification) : undefined; // verify first to prevent stream hang - const content = new Buf(await openpgp.stream.readToEnd(decrypted.getLiteralData()!)); // read content second to prevent stream hang + const content = new Buf(await readToEndBinary(decrypted.getLiteralData()!)); // read content second to prevent stream hang const signature = verifyResults ? await PgpMsg.verify(verifyResults, []) : undefined; // evaluate verify results third to prevent stream hang if (!prepared.isCleartext && (prepared.message as OpenPGP.Message).packets .filterByTag(openpgp.enums.packet.symmetricallyEncryptedData).length) { diff --git a/Core/source/platform/util.ts b/Core/source/platform/util.ts index b175c0d11..ef295ebbd 100644 --- a/Core/source/platform/util.ts +++ b/Core/source/platform/util.ts @@ -85,6 +85,11 @@ export const Uint8Array_to_str = (bytes: Uint8Array): string => { } export const readToEnd = async (stream: OpenPGP.MaybeStream): Promise => { - // TODO - stream + // TODO - implement return ''; } + +export const readToEndBinary = async (stream: OpenPGP.MaybeStream): Promise => { + // TODO - implement + return new Uint8Array(); +} From 629bd14facdf5547d4515ba1d69629feb992713d Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 6 Feb 2022 15:00:09 +0200 Subject: [PATCH 033/179] wip --- Core/source/gen-compat-assets.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index dfe80d954..5bcc48d3a 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -241,8 +241,10 @@ ava.default('mime-email-encrypted-inline-text-signed.txt', async t => { const { keys } = getKeypairs('rsa1'); const signingPrv = await openpgp.readKey({armoredKey: keys[0].private}) as OpenPGP.PrivateKey; // console.log("rsa1 key fingerprint:" + signingPrv.getFingerprint().toUpperCase()); - if (!(await signingPrv.decrypt(keys[0].passphrase))) throw Error('Can\'t decrypt private key'); - const data = await readToEnd(await PgpMsg.encrypt({ data: text, signingPrv: signingPrv, pubkeys, armor: true })); + const signingPrvDecrypted = await OpenPGP.decryptKey({privateKey: signingPrv, passphrase: keys[0].passphrase}); + if (!signingPrvDecrypted) throw Error('Can\'t decrypt private key'); + const data = await readToEnd(await PgpMsg.encrypt( + { data: text, signingPrv: signingPrvDecrypted, pubkeys, armor: true })); await write(t, mimeEmail2(t, data)); t.pass(); }); @@ -250,9 +252,10 @@ ava.default('mime-email-encrypted-inline-text-signed.txt', async t => { ava.default('mime-email-plain-signed.txt', async t => { const { keys } = getKeypairs('rsa1'); const signingPrv = await openpgp.readKey({armoredKey: keys[0].private}) as OpenPGP.PrivateKey; - if (!(await signingPrv.decrypt(keys[0].passphrase))) throw Error('Can\'t decrypt private key'); + const signingPrvDecrypted = await OpenPGP.decryptKey({privateKey: signingPrv, passphrase: keys[0].passphrase}); + if (!signingPrvDecrypted) throw Error('Can\'t decrypt private key'); const data = text.toString(); - const signed = await PgpMsg.sign(signingPrv, data); + const signed = await PgpMsg.sign(signingPrvDecrypted, data); await write(t, mimeEmail2(t, signed)); t.pass(); }); From abe18559dd594c97f7808d08c047d42b2fb8dc08 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 6 Feb 2022 15:15:38 +0200 Subject: [PATCH 034/179] wip --- Core/source/platform/util.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Core/source/platform/util.ts b/Core/source/platform/util.ts index ef295ebbd..f9c2e8ae2 100644 --- a/Core/source/platform/util.ts +++ b/Core/source/platform/util.ts @@ -84,12 +84,14 @@ export const Uint8Array_to_str = (bytes: Uint8Array): string => { return result.join(''); } -export const readToEnd = async (stream: OpenPGP.MaybeStream): Promise => { +export const readToEnd = async (maybeStream: OpenPGP.MaybeStream): Promise => { + if (typeof maybeStream === 'string') return maybeStream; // TODO - implement return ''; } -export const readToEndBinary = async (stream: OpenPGP.MaybeStream): Promise => { +export const readToEndBinary = async (maybeStream: OpenPGP.MaybeStream): Promise => { + if (maybeStream instanceof Uint8Array) return maybeStream; // TODO - implement return new Uint8Array(); } From 4e4f7f82866fb66a16c7e6e6a0f7016d7d197287 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 6 Feb 2022 15:16:13 +0200 Subject: [PATCH 035/179] wip --- Core/source/platform/util.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/source/platform/util.ts b/Core/source/platform/util.ts index f9c2e8ae2..01257ad5d 100644 --- a/Core/source/platform/util.ts +++ b/Core/source/platform/util.ts @@ -87,11 +87,11 @@ export const Uint8Array_to_str = (bytes: Uint8Array): string => { export const readToEnd = async (maybeStream: OpenPGP.MaybeStream): Promise => { if (typeof maybeStream === 'string') return maybeStream; // TODO - implement - return ''; + throw Error('Can\'t read stream'); } export const readToEndBinary = async (maybeStream: OpenPGP.MaybeStream): Promise => { if (maybeStream instanceof Uint8Array) return maybeStream; // TODO - implement - return new Uint8Array(); + throw Error('Can\'t read stream'); } From 24b0cd21b96074afa026114c569b2b67a04c9fe6 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 6 Feb 2022 15:44:17 +0200 Subject: [PATCH 036/179] wip --- Core/source/core/pgp-msg.ts | 54 ++++++++++++------- .../source/mobile-interface/validate-input.ts | 7 +-- 2 files changed, 38 insertions(+), 23 deletions(-) diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index a09dc18f7..ae4e26d24 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -40,7 +40,7 @@ export namespace PgpMsgMethod { export type VerifyDetached = (arg: Arg.VerifyDetached) => Promise; export type Decrypt = (arg: Arg.Decrypt) => Promise; export type Type = (arg: Arg.Type) => Promise; - export type Encrypt = (arg: Arg.Encrypt) => Promise>; + export type Encrypt = (arg: Arg.Encrypt) => Promise; } type SortedKeysForDecrypt = { @@ -264,27 +264,45 @@ export class PgpMsg { } public static encrypt: PgpMsgMethod.Encrypt = async ({ pubkeys, signingPrv, pwd, data, filename, armor, date }) => { - const message = await openpgp.createMessage({binary: data, filename, date}); - const options: OpenPGP.EncryptOptions = { message, date }; - if (armor) options.format = 'armored'; - if (pubkeys) { - options.encryptionKeys = []; - for (const armoredPubkey of pubkeys) { - const publicKeys = await openpgp.readKeys({armoredKeys: armoredPubkey}); - options.encryptionKeys.push(...publicKeys); - } - } - if (pwd) { - options.passwords = [pwd]; - } if (!pubkeys && !pwd) { throw new Error('no-pubkeys-no-challenge'); } - // tslint:disable-next-line:no-unbound-method - only testing if exists - if (signingPrv && signingPrv.isPrivate()) { - options.signingKeys = signingPrv; + + const message = await openpgp.createMessage({binary: data, filename, date}); + + if (armor) { + return await openpgp.encrypt({ + format: 'armored', + message, + date, + encryptionKeys: await (async () => { + const encryptionKeys = []; + for (const armoredPubkey of pubkeys) { + const publicKeys = await openpgp.readKeys({armoredKeys: armoredPubkey}); + encryptionKeys.push(...publicKeys); + } + return encryptionKeys; + })(), + passwords: pwd ? [pwd] : undefined, + signingKeys: signingPrv && signingPrv.isPrivate() ? signingPrv : undefined + }); + } else { + return await openpgp.encrypt({ + format: 'binary', + message, + date, + encryptionKeys: await (async () => { + const encryptionKeys = []; + for (const armoredPubkey of pubkeys) { + const publicKeys = await openpgp.readKeys({armoredKeys: armoredPubkey}); + encryptionKeys.push(...publicKeys); + } + return encryptionKeys; + })(), + passwords: pwd ? [pwd] : undefined, + signingKeys: signingPrv && signingPrv.isPrivate() ? signingPrv : undefined + }); } - return await openpgp.encrypt(options as any); } public static diagnosePubkeys: PgpMsgMethod.DiagnosePubkeys = async ({ privateKis, message }) => { diff --git a/Core/source/mobile-interface/validate-input.ts b/Core/source/mobile-interface/validate-input.ts index d0fd949ba..0f6799ea5 100644 --- a/Core/source/mobile-interface/validate-input.ts +++ b/Core/source/mobile-interface/validate-input.ts @@ -178,12 +178,9 @@ const hasProp = (v: Obj, name: string, type: 'string[]' | 'string[]?' | 'object' } export const readArmoredKeyOrThrow = async (armored: string) => { - const { keys: [key], err } = await openpgp.readArmored(armored); - if (err && err.length && err[0] instanceof Error) { - throw err[0]; - } + const key = await openpgp.readKey({armoredKey: armored}); if (!key) { throw new Error('No key found'); } return key; -} \ No newline at end of file +} From 7adb33b8fd27af78f4ec2c10c2ac52d4a7d0e618 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 6 Feb 2022 15:47:19 +0200 Subject: [PATCH 037/179] wip --- Core/source/gen-compat-assets.ts | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index 5bcc48d3a..65036acfb 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -14,7 +14,6 @@ import { AvaContext, getKeypairs, writeFile } from './test/test-utils'; import { PgpMsg } from './core/pgp-msg'; import { Xss } from './platform/xss'; import { openpgp } from './core/pgp'; -import { readToEnd } from './platform/util'; const text = Buffer.from('some\n汉\ntxt'); const textSpecialChars = Buffer.from('> special & other\n> second line'); @@ -181,25 +180,25 @@ const write = async (t: AvaContext, fileContent: Buffer | string) => { } ava.default('direct-encrypted-text.txt', async t => { - const data = await readToEnd(await PgpMsg.encrypt({ data: text, pubkeys, armor: true })); + const data = await PgpMsg.encrypt({ data: text, pubkeys, armor: true }) as string; await write(t, data); t.pass(); }); ava.default('direct-encrypted-pgpmime.txt', async t => { - const data = await readToEnd(await PgpMsg.encrypt({ data: mimePgp(t, text), pubkeys, armor: true })); + const data = await PgpMsg.encrypt({ data: mimePgp(t, text), pubkeys, armor: true }) as string; await write(t, data); t.pass(); }); ava.default('direct-encrypted-pgpmime-special-chars.txt', async t => { - const data = await readToEnd(await PgpMsg.encrypt({ data: mimePgp(t, textSpecialChars), pubkeys, armor: true })); + const data = await PgpMsg.encrypt({ data: mimePgp(t, textSpecialChars), pubkeys, armor: true }) as string; await write(t, data); t.pass(); }); ava.default('direct-encrypted-text-special-chars.txt', async t => { - const data = await readToEnd(await PgpMsg.encrypt({ data: textSpecialChars, pubkeys, armor: true })); + const data = await PgpMsg.encrypt({ data: textSpecialChars, pubkeys, armor: true }) as string; await write(t, data); t.pass(); }); @@ -215,19 +214,19 @@ ava.default('mime-email-plain-with-pubkey.txt', async t => { }); ava.default('mime-email-encrypted-inline-text.txt', async t => { - const data = await readToEnd(await PgpMsg.encrypt({ data: text, pubkeys, armor: true })); + const data = await PgpMsg.encrypt({ data: text, pubkeys, armor: true }) as string; await write(t, mimeEmail(t, data)); t.pass(); }); ava.default('mime-email-encrypted-inline-pgpmime.txt', async t => { - const data = await readToEnd(await PgpMsg.encrypt({ data: mimePgp(t, text), pubkeys, armor: true })); + const data = await PgpMsg.encrypt({ data: mimePgp(t, text), pubkeys, armor: true }) as string; await write(t, mimeEmail(t, data)); t.pass(); }); ava.default('mime-email-encrypted-inline-text-2.txt', async t => { - const data = await readToEnd(await PgpMsg.encrypt({ data: text, pubkeys, armor: true })); + const data = await PgpMsg.encrypt({ data: text, pubkeys, armor: true }) as string; await write(t, textEncoderMimeEmail(t, data)); t.pass(); }); @@ -243,8 +242,7 @@ ava.default('mime-email-encrypted-inline-text-signed.txt', async t => { // console.log("rsa1 key fingerprint:" + signingPrv.getFingerprint().toUpperCase()); const signingPrvDecrypted = await OpenPGP.decryptKey({privateKey: signingPrv, passphrase: keys[0].passphrase}); if (!signingPrvDecrypted) throw Error('Can\'t decrypt private key'); - const data = await readToEnd(await PgpMsg.encrypt( - { data: text, signingPrv: signingPrvDecrypted, pubkeys, armor: true })); + const data = await PgpMsg.encrypt({ data: text, signingPrv: signingPrvDecrypted, pubkeys, armor: true }) as string; await write(t, mimeEmail2(t, data)); t.pass(); }); From edeb0ee647624cd5a34139c8aa2d54bc489f3a67 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 6 Feb 2022 15:52:46 +0200 Subject: [PATCH 038/179] wip --- Core/source/mobile-interface/endpoints.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Core/source/mobile-interface/endpoints.ts b/Core/source/mobile-interface/endpoints.ts index 547069904..22a20fae3 100644 --- a/Core/source/mobile-interface/endpoints.ts +++ b/Core/source/mobile-interface/endpoints.ts @@ -55,13 +55,13 @@ export class Endpoints { } else if (req.format === 'encrypt-inline') { const encryptedAtts: Att[] = []; for (const att of req.atts || []) { - const encryptedAtt = await PgpMsg.encrypt({ pubkeys: req.pubKeys, data: Buf.fromBase64Str(att.base64), filename: att.name, armor: false }) as OpenPGP.EncryptBinaryResult; - encryptedAtts.push(new Att({ name: `${att.name}.pgp`, type: 'application/pgp-encrypted', data: encryptedAtt.message.packets.write() })) + const encryptedAtt = await PgpMsg.encrypt({ pubkeys: req.pubKeys, data: Buf.fromBase64Str(att.base64), filename: att.name, armor: false }) as Uint8Array; + encryptedAtts.push(new Att({ name: `${att.name}.pgp`, type: 'application/pgp-encrypted', data: encryptedAtt })) } const signingPrv = await getSigningPrv(req); - const encrypted = await PgpMsg.encrypt({ pubkeys: req.pubKeys, signingPrv, data: Buf.fromUtfStr(req.text), armor: true }) as OpenPGP.EncryptArmorResult; - return fmtRes({}, Buf.fromUtfStr(await Mime.encode({ 'text/plain': encrypted.data }, mimeHeaders, encryptedAtts))); + const encrypted = await PgpMsg.encrypt({ pubkeys: req.pubKeys, signingPrv, data: Buf.fromUtfStr(req.text), armor: true }) as string; + return fmtRes({}, Buf.fromUtfStr(await Mime.encode({ 'text/plain': encrypted }, mimeHeaders, encryptedAtts))); } else { throw new Error(`Unknown format: ${req.format}`); } @@ -69,14 +69,14 @@ export class Endpoints { public encryptMsg = async (uncheckedReq: any, data: Buffers): Promise => { const req = ValidateInput.encryptMsg(uncheckedReq); - const encrypted = await PgpMsg.encrypt({ pubkeys: req.pubKeys, pwd: req.msgPwd, data: Buf.concat(data), armor: true }) as OpenPGP.EncryptArmorResult; - return fmtRes({}, Buf.fromUtfStr(encrypted.data)); + const encrypted = await PgpMsg.encrypt({ pubkeys: req.pubKeys, pwd: req.msgPwd, data: Buf.concat(data), armor: true }) as string; + return fmtRes({}, Buf.fromUtfStr(encrypted)); } public encryptFile = async (uncheckedReq: any, data: Buffers): Promise => { const req = ValidateInput.encryptFile(uncheckedReq); - const encrypted = await PgpMsg.encrypt({ pubkeys: req.pubKeys, data: Buf.concat(data), filename: req.name, armor: false }) as OpenPGP.EncryptBinaryResult; - return fmtRes({}, encrypted.message.packets.write()); + const encrypted = await PgpMsg.encrypt({ pubkeys: req.pubKeys, data: Buf.concat(data), filename: req.name, armor: false }) as Uint8Array; + return fmtRes({}, encrypted); } public parseDecryptMsg = async (uncheckedReq: any, data: Buffers): Promise => { @@ -252,7 +252,7 @@ export class Endpoints { return fmtRes({ format: 'armored', keyDetails }); } // binary - const { keys: openPgpKeys } = await openpgp.read(allData); + const openPgpKeys = await openpgp.readKeys({binaryKeys: allData}); for (const openPgpKey of openPgpKeys) { keyDetails.push(await PgpKey.details(openPgpKey)) } From 23f6a6b456a7c1c45da587a9f9b18dfc0a0c6709 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 6 Feb 2022 16:04:53 +0200 Subject: [PATCH 039/179] wip --- Core/source/mobile-interface/endpoints.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/source/mobile-interface/endpoints.ts b/Core/source/mobile-interface/endpoints.ts index 22a20fae3..70e802763 100644 --- a/Core/source/mobile-interface/endpoints.ts +++ b/Core/source/mobile-interface/endpoints.ts @@ -280,12 +280,12 @@ export class Endpoints { public encryptKey = async (uncheckedReq: any): Promise => { Store.keyCacheWipe(); // encryptKey may be used when changing major settings, wipe cache to prevent dated results const { armored, passphrase } = ValidateInput.encryptKey(uncheckedReq); - const key = await readArmoredKeyOrThrow(armored); + const privateKey = await readArmoredKeyOrThrow(armored) as OpenPGP.PrivateKey; if (!passphrase || passphrase.length < 12) { // last resort check, this should never happen throw new Error('Pass phrase length seems way too low! Pass phrase strength should be properly checked before encrypting a key.'); } - await key.encrypt(passphrase); - return fmtRes({ encryptedKey: key.armor() }); + const encryptedKey = await openpgp.encryptKey({privateKey, passphrase}); + return fmtRes({ encryptedKey: encryptedKey.armor() }); } public keyCacheWipe = async (): Promise => { From cecea497dc5eee4540d1e21ee46175be13d2f266 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 6 Feb 2022 16:08:37 +0200 Subject: [PATCH 040/179] wip --- Core/tooling/fix-bundles.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Core/tooling/fix-bundles.js b/Core/tooling/fix-bundles.js index b273ce58b..916b2de0d 100644 --- a/Core/tooling/fix-bundles.js +++ b/Core/tooling/fix-bundles.js @@ -73,6 +73,7 @@ const replace = (libSrc, regex, replacement) => { let openpgpLib = fs.readFileSync('source/lib/openpgp.js').toString(); const openpgpLibNodeDev = openpgpLib; // dev node runs without any host, no modifications needed +/* openpgpLib = replace( // rsa decrypt on host openpgpLib, /[a-z0-9A-Z_]+\.default\.rsa\.decrypt\(c, n, e, d, p, q, u\)/, @@ -85,9 +86,11 @@ openpgpLib = replace( // rsa verify on host const computed = await coreHost.verifyRsaModPow(m.toString(10), e.toString(10), n.toString(10)); // returns empty str if not supported: js fallback below const EM = computed ? new _bn2.default(computed, 10).toArrayLike(Uint8Array, 'be', n.byteLength()) : await _public_key2.default.rsa.verify(m, n, e);` ); +*/ let openpgpLibBare = openpgpLib; // further modify bare code below +/* openpgpLibBare = replace( // bare - produce s2k (decrypt key) on host (because JS sha256 implementation is too slow) openpgpLibBare, /const data = _util2\.default\.concatUint8Array\(\[s2k\.salt, passphrase\]\);/, @@ -99,6 +102,7 @@ openpgpLibBare = replace( // bare - aes decrypt on host /return _cfb\.AES_CFB\.decrypt\(ct, key, iv\);/, `return Uint8Array.from(coreHost.decryptAesCfbNoPadding(ct, key, iv));` ); +*/ const asn1LibBare = fs.readFileSync(`${bundleWipDir}/bare-asn1.js`).toString(); From 0c991f62d69b42ee78205e07ed3625a58c7fdb8d Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 6 Feb 2022 19:09:38 +0200 Subject: [PATCH 041/179] wip --- Core/source/core/pgp-key.ts | 4 ++-- Core/source/core/pgp-msg.ts | 5 ++--- Core/source/core/types/openpgp.d.ts | 4 ++++ Core/source/platform/util.ts | 12 ------------ 4 files changed, 8 insertions(+), 17 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index e3a6d09e2..50b25efc0 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -10,7 +10,7 @@ import { Store } from '../platform/store'; import { mnemonic } from './mnemonic'; import { openpgp } from './pgp'; import { SecretKeyPacket, SecretSubkeyPacket } from 'openpgp'; -import { readToEnd, str_to_hex } from '../platform/util'; +import { str_to_hex } from '../platform/util'; export type Contact = { email: string; @@ -377,7 +377,7 @@ export class PgpKey { if (!certificate || typeof certificate === 'string') { return certificate || undefined; } else { - return await readToEnd(certificate); + return await openpgp.readToEnd(certificate); } } } diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index ae4e26d24..3d25f7f1e 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -13,7 +13,6 @@ import { MsgBlockParser } from './msg-block-parser'; import { PgpArmor } from './pgp-armor'; import { Store } from '../platform/store'; import { openpgp } from './pgp'; -import { readToEnd, readToEndBinary } from '../platform/util'; export namespace PgpMsgMethod { export namespace Arg { @@ -210,7 +209,7 @@ export class PgpMsg { const isEncrypted = !prepared.isCleartext; if (!isEncrypted) { const signature = await PgpMsg.verify(prepared.message, keys.forVerification); - const text = await readToEnd(prepared.message.getText()!); + const text = await openpgp.readToEnd(prepared.message.getText()!); return { success: true, content: Buf.fromUtfStr(text), isEncrypted, signature }; } if (!keys.prvMatching.length && !msgPwd) { @@ -250,7 +249,7 @@ export class PgpMsg { await PgpMsg.cryptoMsgGetSignedBy(decrypted, keys); await PgpMsg.populateKeysForVerification(keys, verificationPubkeys); const verifyResults = keys.signedBy.length ? await decrypted.verify(keys.forVerification) : undefined; // verify first to prevent stream hang - const content = new Buf(await readToEndBinary(decrypted.getLiteralData()!)); // read content second to prevent stream hang + const content = new Buf(await openpgp.readToEnd(decrypted.getLiteralData()!)); // read content second to prevent stream hang const signature = verifyResults ? await PgpMsg.verify(verifyResults, []) : undefined; // evaluate verify results third to prevent stream hang if (!prepared.isCleartext && (prepared.message as OpenPGP.Message).packets .filterByTag(openpgp.enums.packet.symmetricallyEncryptedData).length) { diff --git a/Core/source/core/types/openpgp.d.ts b/Core/source/core/types/openpgp.d.ts index c51e3680d..c6acdfb51 100644 --- a/Core/source/core/types/openpgp.d.ts +++ b/Core/source/core/types/openpgp.d.ts @@ -894,6 +894,10 @@ export namespace enums { } } +// ----- BEGIN ADDED BY FLOWCRYPT ----- +export function readToEnd(input: MaybeStream, concat?: (list: T[]) => T): Promise; +// ----- END ADDED BY FLOWCRYPT ----- + // ----- BEGIN ADDED BY FLOWCRYPT ----- } // namespace OpenPGP // ----- END ADDED BY FLOWCRYPT ----- diff --git a/Core/source/platform/util.ts b/Core/source/platform/util.ts index 01257ad5d..177d047e5 100644 --- a/Core/source/platform/util.ts +++ b/Core/source/platform/util.ts @@ -83,15 +83,3 @@ export const Uint8Array_to_str = (bytes: Uint8Array): string => { } return result.join(''); } - -export const readToEnd = async (maybeStream: OpenPGP.MaybeStream): Promise => { - if (typeof maybeStream === 'string') return maybeStream; - // TODO - implement - throw Error('Can\'t read stream'); -} - -export const readToEndBinary = async (maybeStream: OpenPGP.MaybeStream): Promise => { - if (maybeStream instanceof Uint8Array) return maybeStream; - // TODO - implement - throw Error('Can\'t read stream'); -} From dfc0832c616ba689aeef05ce70878938e3bf2d40 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 6 Feb 2022 19:26:43 +0200 Subject: [PATCH 042/179] wip --- Core/source/core/pgp-password.ts | 5 +++-- Core/source/core/types/openpgp.d.ts | 6 ++++++ Core/source/platform/util.ts | 30 ----------------------------- 3 files changed, 9 insertions(+), 32 deletions(-) diff --git a/Core/source/core/pgp-password.ts b/Core/source/core/pgp-password.ts index a743d26cf..a537e7432 100644 --- a/Core/source/core/pgp-password.ts +++ b/Core/source/core/pgp-password.ts @@ -2,7 +2,7 @@ 'use strict'; -import { base64encode, secureRandomBytes, Uint8Array_to_str } from '../platform/util'; +import { base64encode, secureRandomBytes } from '../platform/util'; interface PwdStrengthResult { word: { @@ -64,7 +64,8 @@ export class PgpPwd { } public static random = () => { // eg TDW6-DU5M-TANI-LJXY - return base64encode(Uint8Array_to_str(secureRandomBytes(128))).toUpperCase().replace(/[^A-Z0-9]|0|O|1/g, '').replace(/(.{4})/g, '$1-').substr(0, 19); + return base64encode(OpenPGP.util.uint8ArrayToString(secureRandomBytes(128))) + .toUpperCase().replace(/[^A-Z0-9]|0|O|1/g, '').replace(/(.{4})/g, '$1-').substr(0, 19); } private static readableCrackTime = (totalSeconds: number) => { // http://stackoverflow.com/questions/8211744/convert-time-interval-given-in-seconds-into-more-human-readable-form diff --git a/Core/source/core/types/openpgp.d.ts b/Core/source/core/types/openpgp.d.ts index c6acdfb51..ab94741db 100644 --- a/Core/source/core/types/openpgp.d.ts +++ b/Core/source/core/types/openpgp.d.ts @@ -898,6 +898,12 @@ export namespace enums { export function readToEnd(input: MaybeStream, concat?: (list: T[]) => T): Promise; // ----- END ADDED BY FLOWCRYPT ----- +// ----- BEGIN ADDED BY FLOWCRYPT ----- +export namespace util { + function uint8ArrayToString(bytes: Uint8Array): string; +} +// ----- END ADDED BY FLOWCRYPT ----- + // ----- BEGIN ADDED BY FLOWCRYPT ----- } // namespace OpenPGP // ----- END ADDED BY FLOWCRYPT ----- diff --git a/Core/source/platform/util.ts b/Core/source/platform/util.ts index 177d047e5..08c2844b9 100644 --- a/Core/source/platform/util.ts +++ b/Core/source/platform/util.ts @@ -53,33 +53,3 @@ export const str_to_hex = (str: string): string => { } return r.join(''); } - -/** - * Create binary string from a hex encoded string - * @param {String} str Hex string to convert - * @returns {String} - */ -export const hex_to_str = (hex: string): string => { - let str = ''; - for (let i = 0; i < hex.length; i += 2) { - str += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); - } - return str; -} - -/** - * Convert an array of 8-bit integers to a string - * @param {Uint8Array} bytes An array of 8-bit integers to convert - * @returns {String} String representation of the array - */ -export const Uint8Array_to_str = (bytes: Uint8Array): string => { - bytes = new Uint8Array(bytes); - const result = []; - const bs = 1 << 14; - const j = bytes.length; - - for (let i = 0; i < j; i += bs) { - result.push(String.fromCharCode.apply(String, bytes.subarray(i, i + bs < j ? i + bs : j))); - } - return result.join(''); -} From da90df6395a578a874205b8b75c3a4d426e4c248 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 6 Feb 2022 19:28:10 +0200 Subject: [PATCH 043/179] wip --- Core/source/core/types/openpgp.d.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/source/core/types/openpgp.d.ts b/Core/source/core/types/openpgp.d.ts index ab94741db..438a69ba8 100644 --- a/Core/source/core/types/openpgp.d.ts +++ b/Core/source/core/types/openpgp.d.ts @@ -7,9 +7,9 @@ * - Errietta Kostala */ - // ----- BEGIN ADDED BY FLOWCRYPT ----- - declare namespace OpenPGP { - // ----- END ADDED BY FLOWCRYPT ----- +// ----- BEGIN ADDED BY FLOWCRYPT ----- +declare namespace OpenPGP { +// ----- END ADDED BY FLOWCRYPT ----- /* ############## v5 KEY #################### */ // The Key and PublicKey types can be used interchangably since TS cannot detect the difference, as they have the same class properties. From 50894a99db40b1d652be9e0254bbd1897e1c035c Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 6 Feb 2022 23:13:26 +0200 Subject: [PATCH 044/179] wip --- Core/source/core/pgp-key.ts | 3 +-- Core/source/core/types/openpgp.d.ts | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index 50b25efc0..13b8b08e7 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -367,8 +367,7 @@ export class PgpKey { } public static revoke = async (key: OpenPGP.Key): Promise => { - // It was call to isRevoked(), but it turns that the whole logic truns in to just this: - if (key.revocationSignatures.length == 0) { + if (!key.isRevoked()) { if (!key.isPrivate()) throw Error('Revocation of public key not implemented'); const keypair = await openpgp.revokeKey({key: key as OpenPGP.PrivateKey, format: 'object'}); key = keypair.privateKey; diff --git a/Core/source/core/types/openpgp.d.ts b/Core/source/core/types/openpgp.d.ts index 438a69ba8..16d8a1872 100644 --- a/Core/source/core/types/openpgp.d.ts +++ b/Core/source/core/types/openpgp.d.ts @@ -61,7 +61,7 @@ export abstract class Key { public verifyPrimaryKey(date?: Date, userID?: UserID, config?: Config): Promise; // throws on error public verifyPrimaryUser(publicKeys: PublicKey[], date?: Date, userIDs?: UserID, config?: Config): Promise<{ keyID: KeyID, valid: boolean | null }[]>; public verifyAllUsers(publicKeys: PublicKey[], date?: Date, config?: Config): Promise<{ userID: string, keyID: KeyID, valid: boolean | null }[]>; - public isRevoked(signature: SignaturePacket, key?: AnyKeyPacket, date?: Date, config?: Config): Promise; + public isRevoked(signature?: SignaturePacket, key?: AnyKeyPacket, date?: Date, config?: Config): Promise; public getRevocationCertificate(date?: Date, config?: Config): Promise | undefined>; public getEncryptionKey(keyID?: KeyID, date?: Date | null, userID?: UserID, config?: Config): Promise; public getSigningKey(keyID?: KeyID, date?: Date | null, userID?: UserID, config?: Config): Promise; From 70dabb49a3b76269304c6890d915b038910a74c4 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 6 Feb 2022 23:16:19 +0200 Subject: [PATCH 045/179] wip --- Core/source/core/types/openpgp.d.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Core/source/core/types/openpgp.d.ts b/Core/source/core/types/openpgp.d.ts index 16d8a1872..bd3a59b31 100644 --- a/Core/source/core/types/openpgp.d.ts +++ b/Core/source/core/types/openpgp.d.ts @@ -61,7 +61,10 @@ export abstract class Key { public verifyPrimaryKey(date?: Date, userID?: UserID, config?: Config): Promise; // throws on error public verifyPrimaryUser(publicKeys: PublicKey[], date?: Date, userIDs?: UserID, config?: Config): Promise<{ keyID: KeyID, valid: boolean | null }[]>; public verifyAllUsers(publicKeys: PublicKey[], date?: Date, config?: Config): Promise<{ userID: string, keyID: KeyID, valid: boolean | null }[]>; + // ----- BEGIN CHANGED BY FLOWCRYPT ----- + // public isRevoked(signature: SignaturePacket, key?: AnyKeyPacket, date?: Date, config?: Config): Promise; public isRevoked(signature?: SignaturePacket, key?: AnyKeyPacket, date?: Date, config?: Config): Promise; + // ----- END CHANGED BY FLOWCRYPT ----- public getRevocationCertificate(date?: Date, config?: Config): Promise | undefined>; public getEncryptionKey(keyID?: KeyID, date?: Date | null, userID?: UserID, config?: Config): Promise; public getSigningKey(keyID?: KeyID, date?: Date | null, userID?: UserID, config?: Config): Promise; From eacc82c90e542c3c0bb6d88b244d7cf3d3b5106f Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 6 Feb 2022 23:25:25 +0200 Subject: [PATCH 046/179] wip --- Core/source/core/pgp-key.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index 13b8b08e7..b5ca11189 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -207,8 +207,11 @@ export class PgpKey { if (!key) { return undefined; } else if (key instanceof OpenPGP.Key) { + if (!key.keyPacket.getFingerprintBytes()) { + return undefined; + } try { - const fp = key.getFingerprint().toUpperCase(); + const fp = key.keyPacket.getFingerprint().toUpperCase(); if (formatting === 'spaced') { return fp.replace(/(.{4})/g, '$1 ').trim(); } @@ -313,9 +316,9 @@ export class PgpKey { public static details = async (k: OpenPGP.Key): Promise => { const keys = k.getKeys(); - const algoInfo = k.getAlgorithmInfo(); + const algoInfo = k.keyPacket.getAlgorithmInfo(); const algo = { algorithm: algoInfo.algorithm, bits: algoInfo.bits, curve: (algoInfo as any).curve, algorithmId: openpgp.enums.publicKey[algoInfo.algorithm] }; - const created = k.getCreationTime().getTime() / 1000; + const created = k.keyPacket.created.getTime() / 1000; const exp = await k.getExpirationTime(); const expiration = exp === Infinity || !exp ? undefined : (exp as Date).getTime() / 1000; const lastModified = await PgpKey.lastSig(k) / 1000; From ef7824cf7b9ce7d8e909144068ac119134e2a4e5 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 6 Feb 2022 23:40:55 +0200 Subject: [PATCH 047/179] wip --- Core/source/core/pgp.ts | 6 +++--- Core/source/core/types/openpgp.d.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Core/source/core/pgp.ts b/Core/source/core/pgp.ts index ef553eaf3..fe237e477 100644 --- a/Core/source/core/pgp.ts +++ b/Core/source/core/pgp.ts @@ -40,14 +40,14 @@ if (typeof openpgp !== 'undefined') { // in certain environments, eg browser con OpenPGP.Key.prototype.isFullyEncrypted = function () { return getPrvPackets(this).every(p => p.isDecrypted() === false); }; - OpenPGP.Key.prototype.isPacketDecrypted = function (keyId: OpenPGP.KeyID) { + OpenPGP.Key.prototype.isPacketDecrypted = function (keyID: OpenPGP.KeyID) { if (!this.isPrivate()) { throw new Error("Cannot check packet encryption status of secret key in a Public Key"); } - if (!keyId) { + if (!keyID) { throw new Error("No KeyID provided to isPacketDecrypted"); } - const [key] = this.getKeys(keyId); + const [key] = this.getKeys(keyID); if (!key) { throw new Error("KeyID not found in Private Key"); } diff --git a/Core/source/core/types/openpgp.d.ts b/Core/source/core/types/openpgp.d.ts index bd3a59b31..e79969c69 100644 --- a/Core/source/core/types/openpgp.d.ts +++ b/Core/source/core/types/openpgp.d.ts @@ -78,7 +78,7 @@ export abstract class Key { // ----- BEGIN ADDED BY FLOWCRYPT ----- public isFullyEncrypted(): boolean; public isFullyDecrypted(): boolean; - public isPacketDecrypted(keyId: KeyID): boolean; + public isPacketDecrypted(keyID: KeyID): boolean; // ----- END ADDED BY FLOWCRYPT ----- } From f4247965951de7e513f0d601fd8bdd7474b03324 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 6 Feb 2022 23:41:34 +0200 Subject: [PATCH 048/179] wip --- Core/source/core/types/openpgp.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/source/core/types/openpgp.d.ts b/Core/source/core/types/openpgp.d.ts index e79969c69..c825a5f71 100644 --- a/Core/source/core/types/openpgp.d.ts +++ b/Core/source/core/types/openpgp.d.ts @@ -61,10 +61,10 @@ export abstract class Key { public verifyPrimaryKey(date?: Date, userID?: UserID, config?: Config): Promise; // throws on error public verifyPrimaryUser(publicKeys: PublicKey[], date?: Date, userIDs?: UserID, config?: Config): Promise<{ keyID: KeyID, valid: boolean | null }[]>; public verifyAllUsers(publicKeys: PublicKey[], date?: Date, config?: Config): Promise<{ userID: string, keyID: KeyID, valid: boolean | null }[]>; - // ----- BEGIN CHANGED BY FLOWCRYPT ----- + // ----- BEGIN MODIFIED BY FLOWCRYPT ----- // public isRevoked(signature: SignaturePacket, key?: AnyKeyPacket, date?: Date, config?: Config): Promise; public isRevoked(signature?: SignaturePacket, key?: AnyKeyPacket, date?: Date, config?: Config): Promise; - // ----- END CHANGED BY FLOWCRYPT ----- + // ----- END MODIFIED BY FLOWCRYPT ----- public getRevocationCertificate(date?: Date, config?: Config): Promise | undefined>; public getEncryptionKey(keyID?: KeyID, date?: Date | null, userID?: UserID, config?: Config): Promise; public getSigningKey(keyID?: KeyID, date?: Date | null, userID?: UserID, config?: Config): Promise; From 20464f597f1ae04afd12487ba00076ceb733cfde Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 6 Feb 2022 23:58:08 +0200 Subject: [PATCH 049/179] wip --- Core/source/core/types/openpgp.d.ts | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/Core/source/core/types/openpgp.d.ts b/Core/source/core/types/openpgp.d.ts index c825a5f71..dda348e9e 100644 --- a/Core/source/core/types/openpgp.d.ts +++ b/Core/source/core/types/openpgp.d.ts @@ -7,9 +7,9 @@ * - Errietta Kostala */ -// ----- BEGIN ADDED BY FLOWCRYPT ----- +// -----BEGIN ADDED BY FLOWCRYPT----- declare namespace OpenPGP { -// ----- END ADDED BY FLOWCRYPT ----- +// -----END ADDED BY FLOWCRYPT----- /* ############## v5 KEY #################### */ // The Key and PublicKey types can be used interchangably since TS cannot detect the difference, as they have the same class properties. @@ -61,10 +61,10 @@ export abstract class Key { public verifyPrimaryKey(date?: Date, userID?: UserID, config?: Config): Promise; // throws on error public verifyPrimaryUser(publicKeys: PublicKey[], date?: Date, userIDs?: UserID, config?: Config): Promise<{ keyID: KeyID, valid: boolean | null }[]>; public verifyAllUsers(publicKeys: PublicKey[], date?: Date, config?: Config): Promise<{ userID: string, keyID: KeyID, valid: boolean | null }[]>; - // ----- BEGIN MODIFIED BY FLOWCRYPT ----- + // -----BEGIN MODIFIED BY FLOWCRYPT----- // public isRevoked(signature: SignaturePacket, key?: AnyKeyPacket, date?: Date, config?: Config): Promise; public isRevoked(signature?: SignaturePacket, key?: AnyKeyPacket, date?: Date, config?: Config): Promise; - // ----- END MODIFIED BY FLOWCRYPT ----- + // -----END MODIFIED BY FLOWCRYPT----- public getRevocationCertificate(date?: Date, config?: Config): Promise | undefined>; public getEncryptionKey(keyID?: KeyID, date?: Date | null, userID?: UserID, config?: Config): Promise; public getSigningKey(keyID?: KeyID, date?: Date | null, userID?: UserID, config?: Config): Promise; @@ -75,11 +75,11 @@ export abstract class Key { public getAlgorithmInfo(): AlgorithmInfo; public getKeyID(): KeyID; public toPacketList(): PacketList; - // ----- BEGIN ADDED BY FLOWCRYPT ----- + // -----BEGIN ADDED BY FLOWCRYPT----- public isFullyEncrypted(): boolean; public isFullyDecrypted(): boolean; public isPacketDecrypted(keyID: KeyID): boolean; - // ----- END ADDED BY FLOWCRYPT ----- + // -----END ADDED BY FLOWCRYPT----- } type AllowedKeyPackets = PublicKeyPacket | PublicSubkeyPacket | SecretKeyPacket | SecretSubkeyPacket | UserIDPacket | UserAttributePacket | SignaturePacket; @@ -897,16 +897,17 @@ export namespace enums { } } -// ----- BEGIN ADDED BY FLOWCRYPT ----- +// -----BEGIN ADDED BY FLOWCRYPT----- export function readToEnd(input: MaybeStream, concat?: (list: T[]) => T): Promise; -// ----- END ADDED BY FLOWCRYPT ----- +// -----END ADDED BY FLOWCRYPT----- -// ----- BEGIN ADDED BY FLOWCRYPT ----- +// -----BEGIN ADDED BY FLOWCRYPT----- export namespace util { + // we can't copy this into our sources (i.e. util.ts) because of LGPL function uint8ArrayToString(bytes: Uint8Array): string; } -// ----- END ADDED BY FLOWCRYPT ----- +// -----END ADDED BY FLOWCRYPT----- -// ----- BEGIN ADDED BY FLOWCRYPT ----- +// -----BEGIN ADDED BY FLOWCRYPT----- } // namespace OpenPGP -// ----- END ADDED BY FLOWCRYPT ----- +// -----END ADDED BY FLOWCRYPT----- From b26d2740bdca3fa7cdefbf22a4eba0687793c7f0 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 7 Feb 2022 00:11:37 +0200 Subject: [PATCH 050/179] wip --- Core/source/lib/openpgp.js | 52 ++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/Core/source/lib/openpgp.js b/Core/source/lib/openpgp.js index 2ec404742..d15b6c8bf 100644 --- a/Core/source/lib/openpgp.js +++ b/Core/source/lib/openpgp.js @@ -7578,7 +7578,7 @@ var sha256_asm = function ( stdlib, foreign, buffer ) { f = H5; g = H6; h = H7; - + // 0 h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x428a2f98 )|0; d = ( d + h )|0; @@ -15373,10 +15373,10 @@ var TYPED_OK = typeof Uint8Array !== "undefined" && // reduce buffer size, avoiding mem copy function shrinkBuf(buf, size) { if (buf.length === size) { - return buf; + return buf; } if (buf.subarray) { - return buf.subarray(0, size); + return buf.subarray(0, size); } buf.length = size; return buf; @@ -15501,8 +15501,8 @@ const Z_DEFLATED = 8; function zero$1(buf) { let len = buf.length; while (--len >= 0) { - buf[len] = 0; - } + buf[len] = 0; + } } // From zutil.h @@ -15772,7 +15772,7 @@ function gen_bitlen(s, desc) /* We overwrite tree[n].Dad which is no longer needed */ if (n > max_code) { - continue; + continue; } /* not a leaf node */ s.bl_count[bits]++; @@ -15787,7 +15787,7 @@ function gen_bitlen(s, desc) } } if (overflow === 0) { - return; + return; } // Trace((stderr,"\nbit length overflow\n")); @@ -15797,7 +15797,7 @@ function gen_bitlen(s, desc) do { bits = max_length - 1; while (s.bl_count[bits] === 0) { - bits--; + bits--; } s.bl_count[bits]--; /* move one leaf down the tree */ s.bl_count[bits + 1] += 2; /* move one overflow item as its brother */ @@ -15818,7 +15818,7 @@ function gen_bitlen(s, desc) while (n !== 0) { m = s.heap[--h]; if (m > max_code) { - continue; + continue; } if (tree[m * 2 + 1]/*.Len*/ !== bits) { // Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); @@ -15865,7 +15865,7 @@ function gen_codes(tree, max_code, bl_count) for (n = 0; n <= max_code; n++) { const len = tree[n * 2 + 1]/*.Len*/; if (len === 0) { - continue; + continue; } /* Now reverse the bits */ tree[n * 2]/*.Code*/ = bi_reverse(next_code[len]++, len); @@ -15988,13 +15988,13 @@ function init_block(s) { /* Initialize the trees. */ for (n = 0; n < L_CODES; n++) { - s.dyn_ltree[n * 2]/*.Freq*/ = 0; + s.dyn_ltree[n * 2]/*.Freq*/ = 0; } for (n = 0; n < D_CODES; n++) { - s.dyn_dtree[n * 2]/*.Freq*/ = 0; + s.dyn_dtree[n * 2]/*.Freq*/ = 0; } for (n = 0; n < BL_CODES; n++) { - s.bl_tree[n * 2]/*.Freq*/ = 0; + s.bl_tree[n * 2]/*.Freq*/ = 0; } s.dyn_ltree[END_BLOCK * 2]/*.Freq*/ = 1; @@ -16072,7 +16072,7 @@ function pqdownheap(s, tree, k) } /* Exit if v is smaller than both sons */ if (smaller(tree, v, s.heap[j], s.depth)) { - break; + break; } /* Exchange v with the smallest son */ @@ -16203,7 +16203,7 @@ function build_tree(s, desc) * establish sub-heaps of increasing lengths: */ for (n = s.heap_len >> 1/*int /2*/; n >= 1; n--) { - pqdownheap(s, tree, n); + pqdownheap(s, tree, n); } /* Construct the Huffman tree by repeatedly combining the least two @@ -16284,7 +16284,7 @@ function scan_tree(s, tree, max_code) } else if (curlen !== 0) { if (curlen !== prevlen) { - s.bl_tree[curlen * 2]/*.Freq*/++; + s.bl_tree[curlen * 2]/*.Freq*/++; } s.bl_tree[REP_3_6 * 2]/*.Freq*/++; @@ -16348,7 +16348,7 @@ function send_tree(s, tree, max_code) } else if (count < min_count) { do { - send_code(s, curlen, s.bl_tree); + send_code(s, curlen, s.bl_tree); } while (--count !== 0); } else if (curlen !== 0) { @@ -16596,7 +16596,7 @@ function _tr_flush_block(s, buf, stored_len, last) // s->last_lit)); if (static_lenb <= opt_lenb) { - opt_lenb = static_lenb; + opt_lenb = static_lenb; } } else { @@ -18611,11 +18611,11 @@ exports.deflateTune = deflateTune; // String encode/decode helpers try { - String.fromCharCode.apply(null, [ 0 ]); + String.fromCharCode.apply(null, [ 0 ]); } catch (__) { } try { - String.fromCharCode.apply(null, new Uint8Array(1)); + String.fromCharCode.apply(null, new Uint8Array(1)); } catch (__) { } @@ -19443,7 +19443,7 @@ function inflate_table(type, lens, lens_index, codes, table, table_index, work, root = bits; for (max = MAXBITS; max >= 1; max--) { if (count[max] !== 0) { - break; + break; } } if (root > max) { @@ -19466,7 +19466,7 @@ function inflate_table(type, lens, lens_index, codes, table, table_index, work, } for (min = 1; min < max; min++) { if (count[min] !== 0) { - break; + break; } } if (root < min) { @@ -19607,7 +19607,7 @@ function inflate_table(type, lens, lens_index, codes, table, table_index, work, sym++; if (--count[len] === 0) { if (len === max) { - break; + break; } len = lens[lens_index + work[sym]]; } @@ -19628,7 +19628,7 @@ function inflate_table(type, lens, lens_index, codes, table, table_index, work, while (curr + drop < max) { left -= count[curr + drop]; if (left <= 0) { - break; + break; } curr++; left <<= 1; @@ -43544,3 +43544,7 @@ exports.revokeKey = revokeKey; exports.sign = sign$5; exports.unarmor = unarmor; exports.verify = verify$5; +// -----BEGIN ADDED BY FLOWCRYPT---- +exports.utils = utils; +exports.readToEnd = readToEnd; +// -----END ADDED BY FLOWCRYPT----- From b5183d831a1fc7405187f9f1277082ac817af3f8 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 7 Feb 2022 00:12:39 +0200 Subject: [PATCH 051/179] wip --- Core/source/lib/openpgp.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/source/lib/openpgp.js b/Core/source/lib/openpgp.js index d15b6c8bf..bed4fa86f 100644 --- a/Core/source/lib/openpgp.js +++ b/Core/source/lib/openpgp.js @@ -43545,6 +43545,6 @@ exports.sign = sign$5; exports.unarmor = unarmor; exports.verify = verify$5; // -----BEGIN ADDED BY FLOWCRYPT---- -exports.utils = utils; exports.readToEnd = readToEnd; +exports.utils = utils; // -----END ADDED BY FLOWCRYPT----- From 287b5e86a9c3cbda3f570b132498d50bf58bf632 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 7 Feb 2022 00:13:12 +0200 Subject: [PATCH 052/179] wip --- Core/source/lib/openpgp.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/source/lib/openpgp.js b/Core/source/lib/openpgp.js index bed4fa86f..756b5acb9 100644 --- a/Core/source/lib/openpgp.js +++ b/Core/source/lib/openpgp.js @@ -43546,5 +43546,5 @@ exports.unarmor = unarmor; exports.verify = verify$5; // -----BEGIN ADDED BY FLOWCRYPT---- exports.readToEnd = readToEnd; -exports.utils = utils; +exports.util = util; // -----END ADDED BY FLOWCRYPT----- From a879d049bba20e5e99207de178f1bb0c161ed867 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 7 Feb 2022 00:13:44 +0200 Subject: [PATCH 053/179] wip --- Core/source/lib/openpgp.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Core/source/lib/openpgp.js b/Core/source/lib/openpgp.js index 756b5acb9..8f5afedac 100644 --- a/Core/source/lib/openpgp.js +++ b/Core/source/lib/openpgp.js @@ -43544,6 +43544,7 @@ exports.revokeKey = revokeKey; exports.sign = sign$5; exports.unarmor = unarmor; exports.verify = verify$5; + // -----BEGIN ADDED BY FLOWCRYPT---- exports.readToEnd = readToEnd; exports.util = util; From 7b42263ac43b56dde3d4adfe08a1d73035abd75d Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 7 Feb 2022 21:06:25 +0200 Subject: [PATCH 054/179] wip --- Core/source/core/pgp.ts | 92 ++++++++++++++--------------- Core/source/core/types/openpgp.d.ts | 12 ++-- Core/source/gen-compat-assets.ts | 10 ++-- Core/source/platform/require.ts | 14 ----- Core/source/test.ts | 18 +++--- 5 files changed, 64 insertions(+), 82 deletions(-) diff --git a/Core/source/core/pgp.ts b/Core/source/core/pgp.ts index fe237e477..724c3bfc7 100644 --- a/Core/source/core/pgp.ts +++ b/Core/source/core/pgp.ts @@ -5,52 +5,48 @@ import { PgpKey, PrvPacket } from './pgp-key'; import { VERSION } from './const'; -import { requireOpenpgp } from '../platform/require'; +import { Key, KeyID, config } from './types/openpgp'; -export const openpgp = requireOpenpgp(); - -if (typeof openpgp !== 'undefined') { // in certain environments, eg browser content scripts, openpgp is not included (not all functions below need it) - openpgp.config.versionString = `FlowCrypt ${VERSION} Gmail Encryption`; - openpgp.config.commentString = 'Seamlessly send and receive encrypted email'; - // we manually check for missing MDC and show loud warning to user (no auto-decrypt) - openpgp.config.allowUnauthenticatedMessages = true; - openpgp.config.allowUnauthenticatedStream = true; - // openpgp.config.require_uid_self_cert = false; - const getPrvPackets = (k: OpenPGP.Key) => { - if (!k.isPrivate()) { - throw new Error("Cannot check encryption status of secret keys in a Public Key"); - } - const prvPackets = k.getKeys().map(k => k.keyPacket).filter(PgpKey.isPacketPrivate) as PrvPacket[]; - if (!prvPackets.length) { - throw new Error("This key has no private packets. Is it a Private Key?"); - } - // only encrypted keys have s2k (decrypted keys don't needed, already decrypted) - // if s2k is present and it indicates it's a dummy key, filter it out - // if s2k is not present, it's a decrypted real key (not dummy) - // openpgp.js v5 provides isDummy() instead. - const nonDummyPrvPackets = prvPackets.filter(p => !p.isDummy()); - if (!nonDummyPrvPackets.length) { - throw new Error("This key only has a gnu-dummy private packet, with no actual secret keys."); - } - return nonDummyPrvPackets; - }; - OpenPGP.Key.prototype.isFullyDecrypted = function () { - return getPrvPackets(this).every(p => p.isDecrypted() === true); - }; - OpenPGP.Key.prototype.isFullyEncrypted = function () { - return getPrvPackets(this).every(p => p.isDecrypted() === false); - }; - OpenPGP.Key.prototype.isPacketDecrypted = function (keyID: OpenPGP.KeyID) { - if (!this.isPrivate()) { - throw new Error("Cannot check packet encryption status of secret key in a Public Key"); - } - if (!keyID) { - throw new Error("No KeyID provided to isPacketDecrypted"); - } - const [key] = this.getKeys(keyID); - if (!key) { - throw new Error("KeyID not found in Private Key"); - } - return key.keyPacket.isDecrypted() === true; - }; -} +config.versionString = `FlowCrypt ${VERSION} Gmail Encryption`; +config.commentString = 'Seamlessly send and receive encrypted email'; +// we manually check for missing MDC and show loud warning to user (no auto-decrypt) +config.allowUnauthenticatedMessages = true; +config.allowUnauthenticatedStream = true; +// openpgp.config.require_uid_self_cert = false; +const getPrvPackets = (k: Key) => { + if (!k.isPrivate()) { + throw new Error("Cannot check encryption status of secret keys in a Public Key"); + } + const prvPackets = k.getKeys().map(k => k.keyPacket).filter(PgpKey.isPacketPrivate) as PrvPacket[]; + if (!prvPackets.length) { + throw new Error("This key has no private packets. Is it a Private Key?"); + } + // only encrypted keys have s2k (decrypted keys don't needed, already decrypted) + // if s2k is present and it indicates it's a dummy key, filter it out + // if s2k is not present, it's a decrypted real key (not dummy) + // openpgp.js v5 provides isDummy() instead. + const nonDummyPrvPackets = prvPackets.filter(p => !p.isDummy()); + if (!nonDummyPrvPackets.length) { + throw new Error("This key only has a gnu-dummy private packet, with no actual secret keys."); + } + return nonDummyPrvPackets; +}; +Key.prototype.isFullyDecrypted = function () { + return getPrvPackets(this).every(p => p.isDecrypted() === true); +}; +Key.prototype.isFullyEncrypted = function () { + return getPrvPackets(this).every(p => p.isDecrypted() === false); +}; +Key.prototype.isPacketDecrypted = function (keyID: KeyID) { + if (!this.isPrivate()) { + throw new Error("Cannot check packet encryption status of secret key in a Public Key"); + } + if (!keyID) { + throw new Error("No KeyID provided to isPacketDecrypted"); + } + const [key] = this.getKeys(keyID); + if (!key) { + throw new Error("KeyID not found in Private Key"); + } + return key.keyPacket.isDecrypted() === true; +}; diff --git a/Core/source/core/types/openpgp.d.ts b/Core/source/core/types/openpgp.d.ts index dda348e9e..6509a3f15 100644 --- a/Core/source/core/types/openpgp.d.ts +++ b/Core/source/core/types/openpgp.d.ts @@ -8,7 +8,7 @@ */ // -----BEGIN ADDED BY FLOWCRYPT----- -declare namespace OpenPGP { +// declare namespace OpenPGP { // -----END ADDED BY FLOWCRYPT----- /* ############## v5 KEY #################### */ @@ -361,7 +361,7 @@ interface PartialConfig extends Partial {} /* ############## v5 PACKET #################### */ -abstract class BasePacket { +export abstract class BasePacket { static readonly tag: enums.packet; public read(bytes: Uint8Array): void; public write(): Uint8Array; @@ -372,7 +372,7 @@ abstract class BasePacket { * - A Secret (Sub)Key Packet can always be used when a Public one is expected. * - A Subkey Packet cannot always be used when a Primary Key Packet is expected (and vice versa). */ -abstract class BasePublicKeyPacket extends BasePacket { +export abstract class BasePublicKeyPacket extends BasePacket { public algorithm: enums.publicKey; public created: Date; public version: number; @@ -400,7 +400,7 @@ export class PublicSubkeyPacket extends BasePublicKeyPacket { protected isSubkey(): true; } -abstract class BaseSecretKeyPacket extends BasePublicKeyPacket { +export abstract class BaseSecretKeyPacket extends BasePublicKeyPacket { public privateParams: object | null; public encrypt(passphrase: string, config?: Config): Promise; // throws on error public decrypt(passphrase: string): Promise; // throws on error @@ -700,7 +700,7 @@ interface SubkeyOptions { config?: PartialConfig; } -class KeyID { +export class KeyID { bytes: string; equals(keyID: KeyID, matchWildcard?: boolean): boolean; toHex(): string; @@ -909,5 +909,5 @@ export namespace util { // -----END ADDED BY FLOWCRYPT----- // -----BEGIN ADDED BY FLOWCRYPT----- -} // namespace OpenPGP +// } // namespace OpenPGP // -----END ADDED BY FLOWCRYPT----- diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index 65036acfb..6b5ea20ff 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -13,7 +13,7 @@ import * as ava from 'ava'; import { AvaContext, getKeypairs, writeFile } from './test/test-utils'; import { PgpMsg } from './core/pgp-msg'; import { Xss } from './platform/xss'; -import { openpgp } from './core/pgp'; +import { decryptKey, PrivateKey, readKey } from './core/types/openpgp'; const text = Buffer.from('some\n汉\ntxt'); const textSpecialChars = Buffer.from('> special & other\n> second line'); @@ -238,9 +238,9 @@ ava.default('mime-email-plain-html.txt', async t => { ava.default('mime-email-encrypted-inline-text-signed.txt', async t => { const { keys } = getKeypairs('rsa1'); - const signingPrv = await openpgp.readKey({armoredKey: keys[0].private}) as OpenPGP.PrivateKey; + const signingPrv = await readKey({armoredKey: keys[0].private}) as PrivateKey; // console.log("rsa1 key fingerprint:" + signingPrv.getFingerprint().toUpperCase()); - const signingPrvDecrypted = await OpenPGP.decryptKey({privateKey: signingPrv, passphrase: keys[0].passphrase}); + const signingPrvDecrypted = await decryptKey({privateKey: signingPrv, passphrase: keys[0].passphrase}); if (!signingPrvDecrypted) throw Error('Can\'t decrypt private key'); const data = await PgpMsg.encrypt({ data: text, signingPrv: signingPrvDecrypted, pubkeys, armor: true }) as string; await write(t, mimeEmail2(t, data)); @@ -249,8 +249,8 @@ ava.default('mime-email-encrypted-inline-text-signed.txt', async t => { ava.default('mime-email-plain-signed.txt', async t => { const { keys } = getKeypairs('rsa1'); - const signingPrv = await openpgp.readKey({armoredKey: keys[0].private}) as OpenPGP.PrivateKey; - const signingPrvDecrypted = await OpenPGP.decryptKey({privateKey: signingPrv, passphrase: keys[0].passphrase}); + const signingPrv = await readKey({armoredKey: keys[0].private}) as PrivateKey; + const signingPrvDecrypted = await decryptKey({privateKey: signingPrv, passphrase: keys[0].passphrase}); if (!signingPrvDecrypted) throw Error('Can\'t decrypt private key'); const data = text.toString(); const signed = await PgpMsg.sign(signingPrvDecrypted, data); diff --git a/Core/source/platform/require.ts b/Core/source/platform/require.ts index 1c0c193ac..a5eb54908 100644 --- a/Core/source/platform/require.ts +++ b/Core/source/platform/require.ts @@ -2,20 +2,6 @@ 'use strict'; -/// - -export const requireOpenpgp = (): typeof OpenPGP => { - // @ts-ignore; - if (typeof openpgp !== 'undefined') { - // @ts-ignore; - return openpgp; // self-contained node-mobile - } - // running tests on a desktop os node instance - // making the require semi-dynamic to surpress Webpack warnings/errors. This line does not rely on webpack at all - // if this was webpack, then the `openpgp` variable would be already set, and it would never get down here - return require(`${'../../../source/lib/openpgp'}`); // points to flowcrypt-mobile-core/source/lib/openpgp.js -}; - export const requireMimeParser = (): any => { // @ts-ignore; return global['emailjs-mime-parser']; diff --git a/Core/source/test.ts b/Core/source/test.ts index 508f9d157..5d90f864f 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -16,8 +16,8 @@ import { allKeypairNames, expectData, expectEmptyJson, expectNoData, getCompatAs import { Xss } from './platform/xss'; import { expect } from 'chai'; -import { openpgp } from './core/pgp'; import { Endpoints } from './mobile-interface/endpoints'; +import { decryptKey, PrivateKey, readKey } from './core/types/openpgp'; const text = 'some\n汉\ntxt'; const htmlContent = text.replace(/\n/g, '
'); @@ -428,7 +428,7 @@ ava.default('parseKeys - revoked', async t => { ava.default('decryptKey', async t => { const { keys: [key] } = getKeypairs('rsa1'); const { data, json } = parseResponse(await endpoints.decryptKey({ armored: key.private, passphrases: [key.passphrase] })); - const decryptedKey = await openpgp.readKey({armoredKey: json.decryptedKey}); + const decryptedKey = await readKey({armoredKey: json.decryptedKey}); expect(decryptedKey.isFullyDecrypted()).to.be.true; expect(decryptedKey.isFullyEncrypted()).to.be.false; expectNoData(data); @@ -439,11 +439,11 @@ ava.default('encryptKey', async t => { const passphrase = 'this is some pass phrase'; const { decrypted: [decryptedKey] } = getKeypairs('rsa1'); const { data, json } = parseResponse(await endpoints.encryptKey({ armored: decryptedKey, passphrase })); - const encryptedKey = await openpgp.readKey({armoredKey: json.encryptedKey}); + const encryptedKey = await readKey({armoredKey: json.encryptedKey}); expect(encryptedKey.isFullyEncrypted()).to.be.true; expect(encryptedKey.isFullyDecrypted()).to.be.false; - expect(await openpgp.decryptKey({ - privateKey: (encryptedKey as OpenPGP.PrivateKey), + expect(await decryptKey({ + privateKey: (encryptedKey as PrivateKey), passphrase: passphrase })).to.be.true expectNoData(data); @@ -452,19 +452,19 @@ ava.default('encryptKey', async t => { ava.default('decryptKey gpg-dummy', async t => { const { keys: [key] } = getKeypairs('gpg-dummy'); - const encryptedKey = await openpgp.readKey({armoredKey: key.private}); + const encryptedKey = await readKey({armoredKey: key.private}); expect(encryptedKey.isFullyEncrypted()).to.be.true; expect(encryptedKey.isFullyDecrypted()).to.be.false; const { json } = parseResponse(await endpoints.decryptKey({ armored: key.private, passphrases: [key.passphrase] })); - const decryptedKey = await openpgp.readKey({armoredKey: json.decryptedKey}); + const decryptedKey = await readKey({armoredKey: json.decryptedKey}); expect(decryptedKey.isFullyEncrypted()).to.be.false; expect(decryptedKey.isFullyDecrypted()).to.be.true; const { json: json2 } = parseResponse(await endpoints.encryptKey({ armored: decryptedKey.armor(), passphrase: 'another pass phrase' })); - const reEncryptedKey = await openpgp.readKey({armoredKey: json2.encryptedKey}); + const reEncryptedKey = await readKey({armoredKey: json2.encryptedKey}); expect(reEncryptedKey.isFullyEncrypted()).to.be.true; expect(reEncryptedKey.isFullyDecrypted()).to.be.false; const { json: json3 } = parseResponse(await endpoints.decryptKey({ armored: reEncryptedKey.armor(), passphrases: ['another pass phrase'] })); - const reDecryptedKey = await openpgp.readKey({armoredKey: json3.decryptedKey}); + const reDecryptedKey = await readKey({armoredKey: json3.decryptedKey}); expect(reDecryptedKey.isFullyEncrypted()).to.be.false; expect(reDecryptedKey.isFullyDecrypted()).to.be.true; t.pass(); From e843a1f7d95545e3b89a2e8d4c6c642666876ffe Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 7 Feb 2022 21:06:57 +0200 Subject: [PATCH 055/179] wip --- Core/source/core/pgp.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Core/source/core/pgp.ts b/Core/source/core/pgp.ts index 724c3bfc7..db89b0182 100644 --- a/Core/source/core/pgp.ts +++ b/Core/source/core/pgp.ts @@ -31,12 +31,15 @@ const getPrvPackets = (k: Key) => { } return nonDummyPrvPackets; }; + Key.prototype.isFullyDecrypted = function () { return getPrvPackets(this).every(p => p.isDecrypted() === true); }; + Key.prototype.isFullyEncrypted = function () { return getPrvPackets(this).every(p => p.isDecrypted() === false); }; + Key.prototype.isPacketDecrypted = function (keyID: KeyID) { if (!this.isPrivate()) { throw new Error("Cannot check packet encryption status of secret key in a Public Key"); From 3026822a5ba66bda2f513facb1c231d089b85459 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 7 Feb 2022 21:07:27 +0200 Subject: [PATCH 056/179] wip --- Core/source/core/pgp.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Core/source/core/pgp.ts b/Core/source/core/pgp.ts index db89b0182..419143c84 100644 --- a/Core/source/core/pgp.ts +++ b/Core/source/core/pgp.ts @@ -12,7 +12,8 @@ config.commentString = 'Seamlessly send and receive encrypted email'; // we manually check for missing MDC and show loud warning to user (no auto-decrypt) config.allowUnauthenticatedMessages = true; config.allowUnauthenticatedStream = true; -// openpgp.config.require_uid_self_cert = false; +// config.require_uid_self_cert = false; + const getPrvPackets = (k: Key) => { if (!k.isPrivate()) { throw new Error("Cannot check encryption status of secret keys in a Public Key"); From 0cf29b8db05a1608f4c2e2ffb47b8b53f5cbd512 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 7 Feb 2022 21:09:59 +0200 Subject: [PATCH 057/179] wip --- Core/source/core/pgp-armor.ts | 13 ++++++------- Core/source/core/pgp-hash.ts | 1 - 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Core/source/core/pgp-armor.ts b/Core/source/core/pgp-armor.ts index 9c474d205..30bf32813 100644 --- a/Core/source/core/pgp-armor.ts +++ b/Core/source/core/pgp-armor.ts @@ -5,11 +5,10 @@ import { Buf } from './buf'; import { ReplaceableMsgBlockType } from './msg-block'; import { Str } from './common'; -import { openpgp } from './pgp'; +import { CleartextMessage, Data, Message, readCleartextMessage, readMessage } from './types/openpgp'; -export type PreparedForDecrypt = { isArmored: boolean, isCleartext: true, message: OpenPGP.CleartextMessage } - | { isArmored: boolean, isCleartext: false, message: OpenPGP.Message - }; +export type PreparedForDecrypt = { isArmored: boolean, isCleartext: true, message: CleartextMessage } + | { isArmored: boolean, isCleartext: false, message: Message }; type CryptoArmorHeaderDefinitions = { readonly [type in ReplaceableMsgBlockType | 'null' | 'signature']: CryptoArmorHeaderDefinition; }; type CryptoArmorHeaderDefinition = { begin: string, middle?: string, end: string | RegExp, replace: boolean }; @@ -87,19 +86,19 @@ export class PgpArmor { return { isArmored, isCleartext: true, - message: await openpgp.readCleartextMessage({cleartextMessage: (new Buf(encrypted)).toUtfStr()}) + message: await readCleartextMessage({cleartextMessage: (new Buf(encrypted)).toUtfStr()}) }; } else if (isArmoredEncrypted) { return { isArmored, isCleartext: false, - message: await openpgp.readMessage({armoredMessage: (new Buf(encrypted)).toUtfStr()}) + message: await readMessage({armoredMessage: (new Buf(encrypted)).toUtfStr()}) }; } else if (encrypted instanceof Uint8Array) { return { isArmored, isCleartext: false, - message: await openpgp.readMessage({binaryMessage: encrypted}) + message: await readMessage({binaryMessage: encrypted}) }; } throw new Error('Message does not have armor headers'); diff --git a/Core/source/core/pgp-hash.ts b/Core/source/core/pgp-hash.ts index 31f0ec8ac..a52226ae3 100644 --- a/Core/source/core/pgp-hash.ts +++ b/Core/source/core/pgp-hash.ts @@ -3,7 +3,6 @@ 'use strict'; import { Buf } from './buf'; -import { openpgp } from './pgp'; export class PgpHash { From d5ee74981fdc12ff1157665d188a599d68a8db7d Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 7 Feb 2022 22:07:59 +0200 Subject: [PATCH 058/179] wip --- Core/source/core/pgp-hash.ts | 5 +++-- Core/source/core/types/openpgp.d.ts | 16 +++++++++++++--- Core/source/lib/openpgp.js | 3 +++ 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/Core/source/core/pgp-hash.ts b/Core/source/core/pgp-hash.ts index a52226ae3..45059839e 100644 --- a/Core/source/core/pgp-hash.ts +++ b/Core/source/core/pgp-hash.ts @@ -2,16 +2,17 @@ 'use strict'; +import { util, Sha1, Sha256 } from './types/openpgp'; import { Buf } from './buf'; export class PgpHash { public static sha1UtfStr = async (string: string): Promise => { - return openpgp.util.Uint8Array_to_hex(await openpgp.crypto.hash.digest(openpgp.enums.hash.sha1, Buf.fromUtfStr(string))); + return util.uint8ArrayToHex((new Sha1()).process(Buf.fromUtfStr(string)).finish().result); } public static sha256UtfStr = async (string: string) => { - return openpgp.util.Uint8Array_to_hex(await openpgp.crypto.hash.digest(openpgp.enums.hash.sha256, Buf.fromUtfStr(string))); + return util.uint8ArrayToHex((new Sha256()).process(Buf.fromUtfStr(string)).finish().result); } public static doubleSha1Upper = async (string: string) => { diff --git a/Core/source/core/types/openpgp.d.ts b/Core/source/core/types/openpgp.d.ts index 6509a3f15..7aafaaff3 100644 --- a/Core/source/core/types/openpgp.d.ts +++ b/Core/source/core/types/openpgp.d.ts @@ -899,13 +899,23 @@ export namespace enums { // -----BEGIN ADDED BY FLOWCRYPT----- export function readToEnd(input: MaybeStream, concat?: (list: T[]) => T): Promise; -// -----END ADDED BY FLOWCRYPT----- -// -----BEGIN ADDED BY FLOWCRYPT----- export namespace util { - // we can't copy this into our sources (i.e. util.ts) because of LGPL + // we can't copy this from openpgp.js into our sources (i.e. util.ts) because of LGPL function uint8ArrayToString(bytes: Uint8Array): string; + function uint8ArrayToHex(bytes: Uint8Array): string; +} + +export class Hash { + public reset(): Hash; + public process(data: Uint8Array): Hash; + public finish(): Hash; + public result: Uint8Array; } + +export class Sha1 extends Hash {} +export class Sha256 extends Hash {} + // -----END ADDED BY FLOWCRYPT----- // -----BEGIN ADDED BY FLOWCRYPT----- diff --git a/Core/source/lib/openpgp.js b/Core/source/lib/openpgp.js index 8f5afedac..256bb30fb 100644 --- a/Core/source/lib/openpgp.js +++ b/Core/source/lib/openpgp.js @@ -43546,6 +43546,9 @@ exports.unarmor = unarmor; exports.verify = verify$5; // -----BEGIN ADDED BY FLOWCRYPT---- +exports.Hash = Hash; +exports.Sha1 = Sha1; +exports.Sha256 = Sha256; exports.readToEnd = readToEnd; exports.util = util; // -----END ADDED BY FLOWCRYPT----- From 94def1b5523be1e8eeff95919b60f7dac11ccb59 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 7 Feb 2022 22:19:53 +0200 Subject: [PATCH 059/179] wip --- Core/source/core/pgp-key.ts | 85 ++++++++++--------- Core/source/entrypoint-bare.ts | 2 - Core/source/gen-compat-assets.ts | 2 - Core/source/mobile-interface/endpoints.ts | 12 ++- .../source/mobile-interface/validate-input.ts | 4 +- Core/source/platform/store.ts | 16 ++-- 6 files changed, 59 insertions(+), 62 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index b5ca11189..76290f71d 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -8,9 +8,8 @@ import { MsgBlockParser } from './msg-block-parser'; import { PgpArmor } from './pgp-armor'; import { Store } from '../platform/store'; import { mnemonic } from './mnemonic'; -import { openpgp } from './pgp'; -import { SecretKeyPacket, SecretSubkeyPacket } from 'openpgp'; import { str_to_hex } from '../platform/util'; +import { AnyKeyPacket, BaseSecretKeyPacket, enums, generateKey, Key, KeyID, PacketList, PrivateKey, PublicKey, readKey, readKeys, readMessage, readToEnd, revokeKey, SecretKeyPacket, SecretSubkeyPacket, SignaturePacket, UserID } from './types/openpgp'; export type Contact = { email: string; @@ -34,8 +33,8 @@ export interface PrvKeyInfo { private: string; longid: string; passphrase?: string; - decrypted?: OpenPGP.Key; // only for internal use in this file - parsed?: OpenPGP.Key; // only for internal use in this file + decrypted?: Key; // only for internal use in this file + parsed?: Key; // only for internal use in this file } export type KeyAlgo = 'curve25519' | 'rsa2048' | 'rsa4096'; @@ -72,15 +71,15 @@ export interface KeyDetails { curve?: string; }; } -export type PrvPacket = (OpenPGP.SecretKeyPacket | OpenPGP.SecretSubkeyPacket); +export type PrvPacket = (SecretKeyPacket | SecretSubkeyPacket); export class PgpKey { - public static create = async (userIds: OpenPGP.UserID[], variant: KeyAlgo, passphrase: string): + public static create = async (userIds: UserID[], variant: KeyAlgo, passphrase: string): Promise<{ private: string, public: string, revCert: string }> => { // With openpgp.js v5 Separate declaration of variable of type OpenPGP.KeyOptions // leads to error when calling generate(). // I don't know how to overcome this, so just passing "inline" object, which works. - const k = await openpgp.generateKey({ + const k = await generateKey({ userIDs: userIds, passphrase: passphrase, format: 'armored', curve: (variant === 'curve25519' ? 'curve25519' : undefined), rsaBits: (variant === 'curve25519' ? undefined : (variant === 'rsa2048' ? 2048 : 4096)) @@ -96,7 +95,7 @@ export class PgpKey { if (fromCache) { return fromCache; } - const key = await openpgp.readKey({armoredKey: armoredKey}); + const key = await readKey({armoredKey: armoredKey}); if (key?.isPrivate()) { Store.armoredKeyCacheSet(armoredKey, key); } @@ -107,16 +106,16 @@ export class PgpKey { * Read many keys, could be armored or binary, in single armor or separately, * useful for importing keychains of various formats */ - public static readMany = async (fileData: Buf): Promise<{ keys: OpenPGP.Key[], errs: Error[] }> => { - const allKeys: OpenPGP.Key[] = []; + public static readMany = async (fileData: Buf): Promise<{ keys: Key[], errs: Error[] }> => { + const allKeys: Key[] = []; const allErrs: Error[] = []; const { blocks } = MsgBlockParser.detectBlocks(fileData.toUtfStr()); const armoredPublicKeyBlocks = blocks.filter(block => block.type === 'publicKey' || block.type === 'privateKey'); const pushKeysAndErrs = async (content: string | Buf, type: 'readArmored' | 'read') => { try { const keys = type === 'readArmored' - ? await openpgp.readKeys({armoredKeys: content.toString()}) - : await openpgp.readKeys({binaryKeys: (typeof content === 'string' ? Buf.fromUtfStr(content) : content)}); + ? await readKeys({armoredKeys: content.toString()}) + : await readKeys({binaryKeys: (typeof content === 'string' ? Buf.fromUtfStr(content) : content)}); allKeys.push(...keys); } catch (e) { allErrs.push(e instanceof Error ? e : new Error(String(e))); @@ -132,17 +131,20 @@ export class PgpKey { return { keys: allKeys, errs: allErrs }; } - public static isPacketPrivate = (p: OpenPGP.AnyKeyPacket): p is PrvPacket => { + public static isPacketPrivate = (p: AnyKeyPacket): p is PrvPacket => { return p instanceof SecretKeyPacket || p instanceof SecretSubkeyPacket; } - public static decrypt = async (prv: OpenPGP.Key, passphrase: string, optionalKeyid?: OpenPGP.KeyID, optionalBehaviorFlag?: 'OK-IF-ALREADY-DECRYPTED'): Promise => { + public static decrypt = async (prv: Key, passphrase: string, optionalKeyid?: KeyID, + optionalBehaviorFlag?: 'OK-IF-ALREADY-DECRYPTED'): Promise => { if (!prv.isPrivate()) { throw new Error("Nothing to decrypt in a public key"); } - const chosenPrvPackets = prv.getKeys(optionalKeyid).map(k => k.keyPacket).filter(PgpKey.isPacketPrivate) as PrvPacket[]; + const chosenPrvPackets = prv.getKeys(optionalKeyid).map(k => k.keyPacket) + .filter(PgpKey.isPacketPrivate) as PrvPacket[]; if (!chosenPrvPackets.length) { - throw new Error(`No private key packets selected of ${prv.getKeys().map(k => k.keyPacket).filter(PgpKey.isPacketPrivate).length} prv packets available`); + throw new Error('No private key packets selected of' + + `${prv.getKeys().map(k => k.keyPacket).filter(PgpKey.isPacketPrivate).length} prv packets available`); } for (const prvPacket of chosenPrvPackets) { if (prvPacket.isDecrypted()) { @@ -164,7 +166,7 @@ export class PgpKey { return true; } - public static encrypt = async (prv: OpenPGP.Key, passphrase: string) => { + public static encrypt = async (prv: Key, passphrase: string) => { if (!passphrase || passphrase === 'undefined' || passphrase === 'null') { throw new Error(`Encryption passphrase should not be empty:${typeof passphrase}:${passphrase}`); } @@ -174,22 +176,23 @@ export class PgpKey { throw new Error(`No private key packets in key to encrypt. Is this a private key?`); } if (encryptedPacketCount) { - throw new Error(`Cannot encrypt a key that has ${encryptedPacketCount} of ${secretPackets.length} private packets still encrypted`); + throw new Error(`Cannot encrypt a key that has ${encryptedPacketCount} of ` + + `${secretPackets.length} private packets still encrypted`); } - await ((prv as unknown) as OpenPGP.BaseSecretKeyPacket).encrypt(passphrase); + await ((prv as unknown) as BaseSecretKeyPacket).encrypt(passphrase); } - public static normalize = async (armored: string): Promise<{ normalized: string, keys: OpenPGP.Key[] }> => { + public static normalize = async (armored: string): Promise<{ normalized: string, keys: Key[] }> => { try { - let keys: OpenPGP.Key[] = []; + let keys: Key[] = []; armored = PgpArmor.normalize(armored, 'key'); if (RegExp(PgpArmor.headers('publicKey', 're').begin).test(armored)) { - keys = (await openpgp.readKeys({armoredKeys: armored})); + keys = (await readKeys({armoredKeys: armored})); } else if (RegExp(PgpArmor.headers('privateKey', 're').begin).test(armored)) { - keys = (await openpgp.readKeys({armoredKeys: armored})); + keys = (await readKeys({armoredKeys: armored})); } else if (RegExp(PgpArmor.headers('encryptedMsg', 're').begin).test(armored)) { - const msg = await openpgp.readMessage({armoredMessage: armored}); - keys = [new OpenPGP.PublicKey(msg.packets as OpenPGP.PacketList)]; + const msg = await readMessage({armoredMessage: armored}); + keys = [new PublicKey(msg.packets as PacketList)]; } for (const k of keys) { for (const u of k.users) { @@ -203,10 +206,11 @@ export class PgpKey { } } - public static fingerprint = async (key: OpenPGP.Key | string, formatting: "default" | "spaced" = 'default'): Promise => { + public static fingerprint = async (key: Key | string, formatting: "default" | "spaced" = 'default'): + Promise => { if (!key) { return undefined; - } else if (key instanceof OpenPGP.Key) { + } else if (key instanceof Key) { if (!key.keyPacket.getFingerprintBytes()) { return undefined; } @@ -233,7 +237,7 @@ export class PgpKey { } } - public static longid = async (keyOrFingerprintOrBytes: string | OpenPGP.Key | undefined): Promise => { + public static longid = async (keyOrFingerprintOrBytes: string | Key | undefined): Promise => { if (!keyOrFingerprintOrBytes) { return undefined; } else if (typeof keyOrFingerprintOrBytes === 'string' && keyOrFingerprintOrBytes.length === 8) { @@ -246,7 +250,7 @@ export class PgpKey { return await PgpKey.longid(await PgpKey.fingerprint(keyOrFingerprintOrBytes)); } - public static longids = async (keyIds: OpenPGP.KeyID[]) => { + public static longids = async (keyIds: KeyID[]) => { const longids: string[] = []; for (const id of keyIds) { const longid = await PgpKey.longid(id.bytes); @@ -261,7 +265,7 @@ export class PgpKey { if (!PgpKey.fingerprint(armored)) { return false; } - const pubkey = await openpgp.readKey({armoredKey: armored}); + const pubkey = await readKey({armoredKey: armored}); if (!pubkey) { return false; } @@ -271,7 +275,7 @@ export class PgpKey { return await PgpKey.usableButExpired(pubkey); } - public static expired = async (key: OpenPGP.Key): Promise => { + public static expired = async (key: Key): Promise => { if (!key) { return false; } @@ -285,7 +289,7 @@ export class PgpKey { throw new Error(`Got unexpected value for expiration: ${exp}`); // exp must be either null, Infinity or a Date } - public static usableButExpired = async (key: OpenPGP.Key): Promise => { + public static usableButExpired = async (key: Key): Promise => { if (!key) { return false; } @@ -300,7 +304,7 @@ export class PgpKey { return Boolean(await key.getEncryptionKey(undefined, oneSecondBeforeExpiration)); } - public static dateBeforeExpiration = async (key: OpenPGP.Key | string): Promise => { + public static dateBeforeExpiration = async (key: Key | string): Promise => { const openPgpKey = typeof key === 'string' ? await PgpKey.read(key) : key; const expires = await openPgpKey.getExpirationTime(); if (expires instanceof Date && expires.getTime() < Date.now()) { // expired @@ -314,10 +318,11 @@ export class PgpKey { return { original: armored, normalized, keys: await Promise.all(keys.map(PgpKey.details)) }; } - public static details = async (k: OpenPGP.Key): Promise => { + public static details = async (k: Key): Promise => { const keys = k.getKeys(); const algoInfo = k.keyPacket.getAlgorithmInfo(); - const algo = { algorithm: algoInfo.algorithm, bits: algoInfo.bits, curve: (algoInfo as any).curve, algorithmId: openpgp.enums.publicKey[algoInfo.algorithm] }; + const algo = { algorithm: algoInfo.algorithm, bits: algoInfo.bits, curve: (algoInfo as any).curve, + algorithmId: enums.publicKey[algoInfo.algorithm] }; const created = k.keyPacket.created.getTime() / 1000; const exp = await k.getExpirationTime(); const expiration = exp === Infinity || !exp ? undefined : (exp as Date).getTime() / 1000; @@ -352,9 +357,9 @@ export class PgpKey { * Get latest self-signature date, in utc millis. * This is used to figure out how recently was key updated, and if one key is newer than other. */ - public static lastSig = async (key: OpenPGP.Key): Promise => { + public static lastSig = async (key: Key): Promise => { await key.getExpirationTime(); // will force all sigs to be verified - const allSignatures: OpenPGP.SignaturePacket[] = []; + const allSignatures: SignaturePacket[] = []; for (const user of key.users) { allSignatures.push(...user.selfCertifications); } @@ -369,17 +374,17 @@ export class PgpKey { throw new Error('No valid signature found in key'); } - public static revoke = async (key: OpenPGP.Key): Promise => { + public static revoke = async (key: Key): Promise => { if (!key.isRevoked()) { if (!key.isPrivate()) throw Error('Revocation of public key not implemented'); - const keypair = await openpgp.revokeKey({key: key as OpenPGP.PrivateKey, format: 'object'}); + const keypair = await revokeKey({key: key as PrivateKey, format: 'object'}); key = keypair.privateKey; } const certificate = await key.getRevocationCertificate(); if (!certificate || typeof certificate === 'string') { return certificate || undefined; } else { - return await openpgp.readToEnd(certificate); + return await readToEnd(certificate); } } } diff --git a/Core/source/entrypoint-bare.ts b/Core/source/entrypoint-bare.ts index 7e15dbc5c..2adb13956 100644 --- a/Core/source/entrypoint-bare.ts +++ b/Core/source/entrypoint-bare.ts @@ -1,7 +1,5 @@ /* © 2016-present FlowCrypt a. s. Limitations apply. Contact human@flowcrypt.com */ -/// - 'use strict'; import { Endpoints } from './mobile-interface/endpoints'; diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index 6b5ea20ff..381d8d696 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -1,7 +1,5 @@ /* © 2016-present FlowCrypt a. s. Limitations apply. Contact human@flowcrypt.com */ -/// - 'use strict'; // @ts-ignore - it cannot figure out the types, because we don't want to install them from npm diff --git a/Core/source/mobile-interface/endpoints.ts b/Core/source/mobile-interface/endpoints.ts index 70e802763..a6ca2b980 100644 --- a/Core/source/mobile-interface/endpoints.ts +++ b/Core/source/mobile-interface/endpoints.ts @@ -1,7 +1,5 @@ /* © 2016-present FlowCrypt a. s. Limitations apply. Contact human@flowcrypt.com */ -/// - 'use strict'; import { Buffers, EndpointRes, fmtContentBlock, fmtRes, isContentBlock } from './format-output'; @@ -20,7 +18,7 @@ import { VERSION } from '../core/const'; import { ValidateInput, readArmoredKeyOrThrow, NodeRequest } from './validate-input'; import { Xss } from '../platform/xss'; import { gmailBackupSearchQuery } from '../core/const'; -import { openpgp } from '../core/pgp'; +import { encryptKey, Key, PrivateKey, readKeys } from '../core/types/openpgp'; export class Endpoints { @@ -252,7 +250,7 @@ export class Endpoints { return fmtRes({ format: 'armored', keyDetails }); } // binary - const openPgpKeys = await openpgp.readKeys({binaryKeys: allData}); + const openPgpKeys = await readKeys({binaryKeys: allData}); for (const openPgpKey of openPgpKeys) { keyDetails.push(await PgpKey.details(openPgpKey)) } @@ -280,11 +278,11 @@ export class Endpoints { public encryptKey = async (uncheckedReq: any): Promise => { Store.keyCacheWipe(); // encryptKey may be used when changing major settings, wipe cache to prevent dated results const { armored, passphrase } = ValidateInput.encryptKey(uncheckedReq); - const privateKey = await readArmoredKeyOrThrow(armored) as OpenPGP.PrivateKey; + const privateKey = await readArmoredKeyOrThrow(armored) as PrivateKey; if (!passphrase || passphrase.length < 12) { // last resort check, this should never happen throw new Error('Pass phrase length seems way too low! Pass phrase strength should be properly checked before encrypting a key.'); } - const encryptedKey = await openpgp.encryptKey({privateKey, passphrase}); + const encryptedKey = await encryptKey({privateKey, passphrase}); return fmtRes({ encryptedKey: encryptedKey.armor() }); } @@ -294,7 +292,7 @@ export class Endpoints { } } -export const getSigningPrv = async (req: NodeRequest.composeEmailEncrypted): Promise => { +export const getSigningPrv = async (req: NodeRequest.composeEmailEncrypted): Promise => { if (!req.signingPrv) { return undefined; } diff --git a/Core/source/mobile-interface/validate-input.ts b/Core/source/mobile-interface/validate-input.ts index 0f6799ea5..7a702b215 100644 --- a/Core/source/mobile-interface/validate-input.ts +++ b/Core/source/mobile-interface/validate-input.ts @@ -2,7 +2,7 @@ 'use strict'; -import { openpgp } from '../core/pgp'; +import { readKey } from "../core/types/openpgp"; type Obj = { [k: string]: any }; @@ -178,7 +178,7 @@ const hasProp = (v: Obj, name: string, type: 'string[]' | 'string[]?' | 'object' } export const readArmoredKeyOrThrow = async (armored: string) => { - const key = await openpgp.readKey({armoredKey: armored}); + const key = await readKey({armoredKey: armored}); if (!key) { throw new Error('No key found'); } diff --git a/Core/source/platform/store.ts b/Core/source/platform/store.ts index 3e258eedd..93322cf04 100644 --- a/Core/source/platform/store.ts +++ b/Core/source/platform/store.ts @@ -2,33 +2,32 @@ 'use strict'; -/// - +import { Key } from '../core/types/openpgp'; import { str_to_hex } from './util'; -let KEY_CACHE: { [longidOrArmoredKey: string]: OpenPGP.Key } = {}; +let KEY_CACHE: { [longidOrArmoredKey: string]: Key } = {}; let KEY_CACHE_WIPE_TIMEOUT: NodeJS.Timeout; -const keyLongid = (k: OpenPGP.Key) => str_to_hex(k.getKeyID().bytes).toUpperCase(); +const keyLongid = (k: Key) => str_to_hex(k.getKeyID().bytes).toUpperCase(); export class Store { - static decryptedKeyCacheSet = (k: OpenPGP.Key) => { + static decryptedKeyCacheSet = (k: Key) => { Store.keyCacheRenewExpiry(); KEY_CACHE[keyLongid(k)] = k; } - static decryptedKeyCacheGet = (longid: string): OpenPGP.Key | undefined => { + static decryptedKeyCacheGet = (longid: string): Key | undefined => { Store.keyCacheRenewExpiry(); return KEY_CACHE[longid]; } - static armoredKeyCacheSet = (armored: string, k: OpenPGP.Key) => { + static armoredKeyCacheSet = (armored: string, k: Key) => { Store.keyCacheRenewExpiry(); KEY_CACHE[armored] = k; } - static armoredKeyCacheGet = (armored: string): OpenPGP.Key | undefined => { + static armoredKeyCacheGet = (armored: string): Key | undefined => { Store.keyCacheRenewExpiry(); return KEY_CACHE[armored]; } @@ -43,5 +42,4 @@ export class Store { } KEY_CACHE_WIPE_TIMEOUT = setTimeout(Store.keyCacheWipe, 2 * 60 * 1000); } - } From 473d9f18179c556435d2a7161708c37c2e7e7092 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 7 Feb 2022 22:27:07 +0200 Subject: [PATCH 060/179] wip --- Core/source/core/pgp-key.ts | 3 -- Core/source/core/pgp-msg.ts | 82 ++++++++++++++++++------------------- 2 files changed, 40 insertions(+), 45 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index 76290f71d..3aaed6e51 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -76,9 +76,6 @@ export type PrvPacket = (SecretKeyPacket | SecretSubkeyPacket); export class PgpKey { public static create = async (userIds: UserID[], variant: KeyAlgo, passphrase: string): Promise<{ private: string, public: string, revCert: string }> => { - // With openpgp.js v5 Separate declaration of variable of type OpenPGP.KeyOptions - // leads to error when calling generate(). - // I don't know how to overcome this, so just passing "inline" object, which works. const k = await generateKey({ userIDs: userIds, passphrase: passphrase, format: 'armored', curve: (variant === 'curve25519' ? 'curve25519' : undefined), diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index 3d25f7f1e..65cc36f83 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -12,13 +12,13 @@ import { FcAttLinkData } from './att'; import { MsgBlockParser } from './msg-block-parser'; import { PgpArmor } from './pgp-armor'; import { Store } from '../platform/store'; -import { openpgp } from './pgp'; +import { CleartextMessage, createCleartextMessage, createMessage, Data, encrypt, enums, Key, KeyID, Message, PrivateKey, readKeys, readMessage, readToEnd, sign, VerificationResult } from './types/openpgp'; export namespace PgpMsgMethod { export namespace Arg { export type Encrypt = { pubkeys: string[], - signingPrv?: OpenPGP.Key, + signingPrv?: Key, pwd?: string, data: Uint8Array, filename?: string, @@ -39,11 +39,11 @@ export namespace PgpMsgMethod { export type VerifyDetached = (arg: Arg.VerifyDetached) => Promise; export type Decrypt = (arg: Arg.Decrypt) => Promise; export type Type = (arg: Arg.Type) => Promise; - export type Encrypt = (arg: Arg.Encrypt) => Promise; + export type Encrypt = (arg: Arg.Encrypt) => Promise; } type SortedKeysForDecrypt = { - forVerification: OpenPGP.Key[]; + forVerification: Key[]; encryptedFor: string[]; signedBy: string[]; prvMatching: PrvKeyInfo[]; @@ -57,12 +57,12 @@ type DecryptError$error = { type: DecryptErrTypes; message: string; }; type DecryptError$longids = { message: string[]; matching: string[]; chosen: string[]; needPassphrase: string[]; }; export type DecryptError = { success: false; error: DecryptError$error; longids: DecryptError$longids; content?: Buf; - isEncrypted?: boolean; message?: OpenPGP.Message | OpenPGP.CleartextMessage; + isEncrypted?: boolean; message?: Message | CleartextMessage; }; -type PreparedForDecrypt = { isArmored: boolean, isCleartext: true, message: OpenPGP.CleartextMessage } - | { isArmored: boolean, isCleartext: false, message: OpenPGP.Message }; +type PreparedForDecrypt = { isArmored: boolean, isCleartext: true, message: CleartextMessage } + | { isArmored: boolean, isCleartext: false, message: Message }; -type OpenpgpMsgOrCleartext = OpenPGP.Message | OpenPGP.CleartextMessage; +type OpenpgpMsgOrCleartext = Message | CleartextMessage; export type VerifyRes = { signer?: string; @@ -108,11 +108,11 @@ export class PgpMsg { } else { // 10XX XXXX - potential old pgp packet tag tagNumber = (firstByte & 0b00111100) / 4; // 10TTTTLL where T is tag number bit. Division by 4 in place of two bit shifts. I hate bit shifts. } - if (Object.values(openpgp.enums.packet).includes(tagNumber)) { + if (Object.values(enums.packet).includes(tagNumber)) { // Indeed a valid OpenPGP packet tag number // This does not 100% mean it's OpenPGP message // But it's a good indication that it may - const t = openpgp.enums.packet; + const t = enums.packet; const msgTpes = [ t.symEncryptedIntegrityProtectedData, t.modificationDetectionCode, @@ -134,11 +134,11 @@ export class PgpMsg { * Returns signed data if detached=false, armored * Returns signature if detached=true, armored */ - public static sign = async (signingPrv: OpenPGP.Key, data: string, detached = false): Promise => { - const message = await openpgp.createCleartextMessage({text: data}); - const signRes = await openpgp.sign({ + public static sign = async (signingPrv: Key, data: string, detached = false): Promise => { + const message = await createCleartextMessage({text: data}); + const signRes = await sign({ message, - signingKeys: (signingPrv as OpenPGP.PrivateKey), + signingKeys: (signingPrv as PrivateKey), detached, format: 'armored' }); @@ -146,8 +146,8 @@ export class PgpMsg { } public static verify = async ( - msgOrVerResults: OpenpgpMsgOrCleartext | OpenPGP.VerificationResult[], - pubs: OpenPGP.Key[] + msgOrVerResults: OpenpgpMsgOrCleartext | VerificationResult[], + pubs: Key[] ): Promise => { const sig: VerifyRes = { match: null }; // tslint:disable-line:no-null-keyword try { @@ -181,12 +181,12 @@ export class PgpMsg { } public static verifyDetached: PgpMsgMethod.VerifyDetached = async ({ plaintext, sigText, verificationPubkeys }) => { - const message = await openpgp.createMessage({text: Buf.fromUint8(plaintext).toUtfStr()}); + const message = await createMessage({text: Buf.fromUint8(plaintext).toUtfStr()}); await message.appendSignature(Buf.fromUint8(sigText).toUtfStr()); const keys = await PgpMsg.getSortedKeys([], message); if (verificationPubkeys) { for (const verificationPubkey of verificationPubkeys) { - const k = await openpgp.readKeys({armoredKeys: verificationPubkey}); + const k = await readKeys({armoredKeys: verificationPubkey}); keys.forVerification.push(...k); } } @@ -209,7 +209,7 @@ export class PgpMsg { const isEncrypted = !prepared.isCleartext; if (!isEncrypted) { const signature = await PgpMsg.verify(prepared.message, keys.forVerification); - const text = await openpgp.readToEnd(prepared.message.getText()!); + const text = await readToEnd(prepared.message.getText()!); return { success: true, content: Buf.fromUtfStr(text), isEncrypted, signature }; } if (!keys.prvMatching.length && !msgPwd) { @@ -231,9 +231,9 @@ export class PgpMsg { }; } try { - const packets = (prepared.message as OpenPGP.Message).packets; - const isSymEncrypted = packets.filterByTag(openpgp.enums.packet.symEncryptedSessionKey).length > 0; - const isPubEncrypted = packets.filterByTag(openpgp.enums.packet.publicKeyEncryptedSessionKey).length > 0; + const packets = (prepared.message as Message).packets; + const isSymEncrypted = packets.filterByTag(enums.packet.symEncryptedSessionKey).length > 0; + const isPubEncrypted = packets.filterByTag(enums.packet.publicKeyEncryptedSessionKey).length > 0; if (isSymEncrypted && !isPubEncrypted && !msgPwd) { return { success: false, @@ -243,16 +243,16 @@ export class PgpMsg { }; } const passwords = msgPwd ? [msgPwd] : undefined; - const privateKeys = keys.prvForDecryptDecrypted.map(ki => ki.decrypted!) as OpenPGP.PrivateKey[]; - const decrypted = await (prepared.message as OpenPGP.Message).decrypt(privateKeys, passwords); + const privateKeys = keys.prvForDecryptDecrypted.map(ki => ki.decrypted!) as PrivateKey[]; + const decrypted = await (prepared.message as Message).decrypt(privateKeys, passwords); // we can only figure out who signed the msg once it's decrypted await PgpMsg.cryptoMsgGetSignedBy(decrypted, keys); await PgpMsg.populateKeysForVerification(keys, verificationPubkeys); const verifyResults = keys.signedBy.length ? await decrypted.verify(keys.forVerification) : undefined; // verify first to prevent stream hang - const content = new Buf(await openpgp.readToEnd(decrypted.getLiteralData()!)); // read content second to prevent stream hang + const content = new Buf(await readToEnd(decrypted.getLiteralData()!)); // read content second to prevent stream hang const signature = verifyResults ? await PgpMsg.verify(verifyResults, []) : undefined; // evaluate verify results third to prevent stream hang - if (!prepared.isCleartext && (prepared.message as OpenPGP.Message).packets - .filterByTag(openpgp.enums.packet.symmetricallyEncryptedData).length) { + if (!prepared.isCleartext && (prepared.message as Message).packets + .filterByTag(enums.packet.symmetricallyEncryptedData).length) { const noMdc = 'Security threat!\n\nMessage is missing integrity checks (MDC). The sender should update their outdated software and resend.'; return { success: false, content, error: { type: DecryptErrTypes.noMdc, message: noMdc }, message: prepared.message, longids, isEncrypted }; } @@ -266,18 +266,16 @@ export class PgpMsg { if (!pubkeys && !pwd) { throw new Error('no-pubkeys-no-challenge'); } - - const message = await openpgp.createMessage({binary: data, filename, date}); - + const message = await createMessage({binary: data, filename, date}); if (armor) { - return await openpgp.encrypt({ + return await encrypt({ format: 'armored', message, date, encryptionKeys: await (async () => { const encryptionKeys = []; for (const armoredPubkey of pubkeys) { - const publicKeys = await openpgp.readKeys({armoredKeys: armoredPubkey}); + const publicKeys = await readKeys({armoredKeys: armoredPubkey}); encryptionKeys.push(...publicKeys); } return encryptionKeys; @@ -286,14 +284,14 @@ export class PgpMsg { signingKeys: signingPrv && signingPrv.isPrivate() ? signingPrv : undefined }); } else { - return await openpgp.encrypt({ + return await encrypt({ format: 'binary', message, date, encryptionKeys: await (async () => { const encryptionKeys = []; for (const armoredPubkey of pubkeys) { - const publicKeys = await openpgp.readKeys({armoredKeys: armoredPubkey}); + const publicKeys = await readKeys({armoredKeys: armoredPubkey}); encryptionKeys.push(...publicKeys); } return encryptionKeys; @@ -305,9 +303,9 @@ export class PgpMsg { } public static diagnosePubkeys: PgpMsgMethod.DiagnosePubkeys = async ({ privateKis, message }) => { - const m = await openpgp.readMessage({ armoredMessage: Buf.fromUint8(message).toUtfStr() }); + const m = await readMessage({ armoredMessage: Buf.fromUint8(message).toUtfStr() }); const msgKeyIds = m.getEncryptionKeyIDs ? m.getEncryptionKeyIDs() : []; - const localKeyIds: OpenPGP.KeyID[] = []; + const localKeyIds: KeyID[] = []; for (const k of await Promise.all(privateKis.map(ki => PgpKey.read(ki.public)))) { localKeyIds.push(...k.getKeyIDs()); } @@ -387,7 +385,7 @@ export class PgpMsg { if (typeof verificationPubkeys !== 'undefined') { keys.forVerification = []; for (const verificationPubkey of verificationPubkeys) { - const keysForVerification = await openpgp.readKeys({ armoredKeys: verificationPubkey }); + const keysForVerification = await readKeys({ armoredKeys: verificationPubkey }); keys.forVerification.push(...keysForVerification); } } @@ -403,8 +401,8 @@ export class PgpMsg { prvForDecryptDecrypted: [], prvForDecryptWithoutPassphrases: [], }; - const encryptedForKeyids = msg instanceof openpgp.Message - ? (msg as OpenPGP.Message).getEncryptionKeyIDs() + const encryptedForKeyids = msg instanceof Message + ? (msg as Message).getEncryptionKeyIDs() : []; keys.encryptedFor = await PgpKey.longids(encryptedForKeyids); await PgpMsg.cryptoMsgGetSignedBy(msg, keys); @@ -446,12 +444,12 @@ export class PgpMsg { return keys; } - private static matchingKeyids = (key: OpenPGP.Key, encryptedFor: OpenPGP.KeyID[]): OpenPGP.KeyID[] => { + private static matchingKeyids = (key: Key, encryptedFor: KeyID[]): KeyID[] => { const msgKeyidBytesArr = (encryptedFor || []).map(kid => kid.bytes); return key.getKeyIDs().filter(kid => msgKeyidBytesArr.includes(kid.bytes)); } - private static decryptKeyFor = async (prv: OpenPGP.Key, passphrase: string, matchingKeyIds: OpenPGP.KeyID[]): Promise => { + private static decryptKeyFor = async (prv: Key, passphrase: string, matchingKeyIds: KeyID[]): Promise => { if (!matchingKeyIds.length) { // we don't know which keyids match, decrypt all key packets return await PgpKey.decrypt(prv, passphrase, undefined, 'OK-IF-ALREADY-DECRYPTED'); } @@ -463,7 +461,7 @@ export class PgpMsg { return true; } - private static isKeyDecryptedFor = (prv: OpenPGP.Key, msgKeyIds: OpenPGP.KeyID[]): boolean => { + private static isKeyDecryptedFor = (prv: Key, msgKeyIds: KeyID[]): boolean => { if (prv.isFullyDecrypted()) { return true; // primary k + all subkeys decrypted, therefore it must be decrypted for any/every particular keyid } From 6f75ac507536c954770c2f79ad1997f36b5a52ff Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 7 Feb 2022 22:28:41 +0200 Subject: [PATCH 061/179] wip --- Core/source/core/pgp.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Core/source/core/pgp.ts b/Core/source/core/pgp.ts index 419143c84..c120f660f 100644 --- a/Core/source/core/pgp.ts +++ b/Core/source/core/pgp.ts @@ -22,10 +22,6 @@ const getPrvPackets = (k: Key) => { if (!prvPackets.length) { throw new Error("This key has no private packets. Is it a Private Key?"); } - // only encrypted keys have s2k (decrypted keys don't needed, already decrypted) - // if s2k is present and it indicates it's a dummy key, filter it out - // if s2k is not present, it's a decrypted real key (not dummy) - // openpgp.js v5 provides isDummy() instead. const nonDummyPrvPackets = prvPackets.filter(p => !p.isDummy()); if (!nonDummyPrvPackets.length) { throw new Error("This key only has a gnu-dummy private packet, with no actual secret keys."); From 35e6248f5078d2d726acd61155f54e57da7a82f1 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 7 Feb 2022 22:30:20 +0200 Subject: [PATCH 062/179] wip --- Core/source/core/types/openpgp.d.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/Core/source/core/types/openpgp.d.ts b/Core/source/core/types/openpgp.d.ts index 7aafaaff3..502116338 100644 --- a/Core/source/core/types/openpgp.d.ts +++ b/Core/source/core/types/openpgp.d.ts @@ -7,10 +7,6 @@ * - Errietta Kostala */ -// -----BEGIN ADDED BY FLOWCRYPT----- -// declare namespace OpenPGP { -// -----END ADDED BY FLOWCRYPT----- - /* ############## v5 KEY #################### */ // The Key and PublicKey types can be used interchangably since TS cannot detect the difference, as they have the same class properties. // The declared readKey(s) return type is Key instead of a PublicKey since it seems more obvious that a Key can be cast to a PrivateKey. @@ -898,6 +894,7 @@ export namespace enums { } // -----BEGIN ADDED BY FLOWCRYPT----- + export function readToEnd(input: MaybeStream, concat?: (list: T[]) => T): Promise; export namespace util { @@ -917,7 +914,3 @@ export class Sha1 extends Hash {} export class Sha256 extends Hash {} // -----END ADDED BY FLOWCRYPT----- - -// -----BEGIN ADDED BY FLOWCRYPT----- -// } // namespace OpenPGP -// -----END ADDED BY FLOWCRYPT----- From 48c72aab93e7ff22d346dd29648f9a29ad697ea2 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 7 Feb 2022 22:34:10 +0200 Subject: [PATCH 063/179] wip --- Core/source/core/types/openpgp.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/source/core/types/openpgp.d.ts b/Core/source/core/types/openpgp.d.ts index 502116338..8d483518b 100644 --- a/Core/source/core/types/openpgp.d.ts +++ b/Core/source/core/types/openpgp.d.ts @@ -58,7 +58,7 @@ export abstract class Key { public verifyPrimaryUser(publicKeys: PublicKey[], date?: Date, userIDs?: UserID, config?: Config): Promise<{ keyID: KeyID, valid: boolean | null }[]>; public verifyAllUsers(publicKeys: PublicKey[], date?: Date, config?: Config): Promise<{ userID: string, keyID: KeyID, valid: boolean | null }[]>; // -----BEGIN MODIFIED BY FLOWCRYPT----- - // public isRevoked(signature: SignaturePacket, key?: AnyKeyPacket, date?: Date, config?: Config): Promise; + // Make this permanent: https://github.com/openpgpjs/openpgpjs/pull/1486 public isRevoked(signature?: SignaturePacket, key?: AnyKeyPacket, date?: Date, config?: Config): Promise; // -----END MODIFIED BY FLOWCRYPT----- public getRevocationCertificate(date?: Date, config?: Config): Promise | undefined>; From fc96f1bf45b696e9d650d5a6ebdcf5f9b63e9439 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 7 Feb 2022 23:02:16 +0200 Subject: [PATCH 064/179] wip --- Core/source/core/pgp-key.ts | 2 +- Core/source/core/pgp-password.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index 3aaed6e51..58c08b91b 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -64,7 +64,7 @@ export interface KeyDetails { lastModified: number | undefined; // date of last signature, or undefined if never had valid signature expiration: number | undefined; // number of millis of expiration or undefined if never expires revoked: boolean; - algo: { // same as OpenPGP.key.AlgorithmInfo + algo: { // same as openpgp.js Key.AlgorithmInfo algorithm: string; algorithmId: number; bits?: number; diff --git a/Core/source/core/pgp-password.ts b/Core/source/core/pgp-password.ts index a537e7432..8b4972f43 100644 --- a/Core/source/core/pgp-password.ts +++ b/Core/source/core/pgp-password.ts @@ -3,6 +3,7 @@ 'use strict'; import { base64encode, secureRandomBytes } from '../platform/util'; +import { util } from './types/openpgp'; interface PwdStrengthResult { word: { @@ -64,7 +65,7 @@ export class PgpPwd { } public static random = () => { // eg TDW6-DU5M-TANI-LJXY - return base64encode(OpenPGP.util.uint8ArrayToString(secureRandomBytes(128))) + return base64encode(util.uint8ArrayToString(secureRandomBytes(128))) .toUpperCase().replace(/[^A-Z0-9]|0|O|1/g, '').replace(/(.{4})/g, '$1-').substr(0, 19); } From d7f59bd6353fc4acc93c09dcebb0566d34bebdac Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 7 Feb 2022 23:10:11 +0200 Subject: [PATCH 065/179] wip --- Core/source/core/pgp-armor.ts | 2 +- Core/source/core/pgp-hash.ts | 2 +- Core/source/core/pgp-key.ts | 2 +- Core/source/core/pgp-msg.ts | 2 +- Core/source/core/pgp-password.ts | 2 +- Core/source/core/pgp.ts | 2 +- Core/source/gen-compat-assets.ts | 2 +- Core/source/{core/types => lib}/openpgp.d.ts | 0 Core/source/{core/types => lib}/openpgpv4.d.ts | 0 Core/source/mobile-interface/endpoints.ts | 2 +- Core/source/mobile-interface/validate-input.ts | 2 +- Core/source/platform/store.ts | 2 +- Core/source/test.ts | 2 +- 13 files changed, 11 insertions(+), 11 deletions(-) rename Core/source/{core/types => lib}/openpgp.d.ts (100%) rename Core/source/{core/types => lib}/openpgpv4.d.ts (100%) diff --git a/Core/source/core/pgp-armor.ts b/Core/source/core/pgp-armor.ts index 30bf32813..1bcd9c2fd 100644 --- a/Core/source/core/pgp-armor.ts +++ b/Core/source/core/pgp-armor.ts @@ -5,7 +5,7 @@ import { Buf } from './buf'; import { ReplaceableMsgBlockType } from './msg-block'; import { Str } from './common'; -import { CleartextMessage, Data, Message, readCleartextMessage, readMessage } from './types/openpgp'; +import { CleartextMessage, Data, Message, readCleartextMessage, readMessage } from '../lib/openpgp'; export type PreparedForDecrypt = { isArmored: boolean, isCleartext: true, message: CleartextMessage } | { isArmored: boolean, isCleartext: false, message: Message }; diff --git a/Core/source/core/pgp-hash.ts b/Core/source/core/pgp-hash.ts index 45059839e..0bbf28321 100644 --- a/Core/source/core/pgp-hash.ts +++ b/Core/source/core/pgp-hash.ts @@ -2,7 +2,7 @@ 'use strict'; -import { util, Sha1, Sha256 } from './types/openpgp'; +import { util, Sha1, Sha256 } from '../lib/openpgp'; import { Buf } from './buf'; export class PgpHash { diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index 58c08b91b..b58375f43 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -9,7 +9,7 @@ import { PgpArmor } from './pgp-armor'; import { Store } from '../platform/store'; import { mnemonic } from './mnemonic'; import { str_to_hex } from '../platform/util'; -import { AnyKeyPacket, BaseSecretKeyPacket, enums, generateKey, Key, KeyID, PacketList, PrivateKey, PublicKey, readKey, readKeys, readMessage, readToEnd, revokeKey, SecretKeyPacket, SecretSubkeyPacket, SignaturePacket, UserID } from './types/openpgp'; +import { AnyKeyPacket, BaseSecretKeyPacket, enums, generateKey, Key, KeyID, PacketList, PrivateKey, PublicKey, readKey, readKeys, readMessage, readToEnd, revokeKey, SecretKeyPacket, SecretSubkeyPacket, SignaturePacket, UserID } from '../lib/openpgp'; export type Contact = { email: string; diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index 65cc36f83..e0218e984 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -12,7 +12,7 @@ import { FcAttLinkData } from './att'; import { MsgBlockParser } from './msg-block-parser'; import { PgpArmor } from './pgp-armor'; import { Store } from '../platform/store'; -import { CleartextMessage, createCleartextMessage, createMessage, Data, encrypt, enums, Key, KeyID, Message, PrivateKey, readKeys, readMessage, readToEnd, sign, VerificationResult } from './types/openpgp'; +import { CleartextMessage, createCleartextMessage, createMessage, Data, encrypt, enums, Key, KeyID, Message, PrivateKey, readKeys, readMessage, readToEnd, sign, VerificationResult } from '../lib/openpgp'; export namespace PgpMsgMethod { export namespace Arg { diff --git a/Core/source/core/pgp-password.ts b/Core/source/core/pgp-password.ts index 8b4972f43..1b17a86a7 100644 --- a/Core/source/core/pgp-password.ts +++ b/Core/source/core/pgp-password.ts @@ -3,7 +3,7 @@ 'use strict'; import { base64encode, secureRandomBytes } from '../platform/util'; -import { util } from './types/openpgp'; +import { util } from '../lib/openpgp'; interface PwdStrengthResult { word: { diff --git a/Core/source/core/pgp.ts b/Core/source/core/pgp.ts index c120f660f..a252be7b4 100644 --- a/Core/source/core/pgp.ts +++ b/Core/source/core/pgp.ts @@ -5,7 +5,7 @@ import { PgpKey, PrvPacket } from './pgp-key'; import { VERSION } from './const'; -import { Key, KeyID, config } from './types/openpgp'; +import { Key, KeyID, config } from '../lib/openpgp'; config.versionString = `FlowCrypt ${VERSION} Gmail Encryption`; config.commentString = 'Seamlessly send and receive encrypted email'; diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index 381d8d696..cbe3fd21f 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -11,7 +11,7 @@ import * as ava from 'ava'; import { AvaContext, getKeypairs, writeFile } from './test/test-utils'; import { PgpMsg } from './core/pgp-msg'; import { Xss } from './platform/xss'; -import { decryptKey, PrivateKey, readKey } from './core/types/openpgp'; +import { decryptKey, PrivateKey, readKey } from './lib/openpgp'; const text = Buffer.from('some\n汉\ntxt'); const textSpecialChars = Buffer.from('> special & other\n> second line'); diff --git a/Core/source/core/types/openpgp.d.ts b/Core/source/lib/openpgp.d.ts similarity index 100% rename from Core/source/core/types/openpgp.d.ts rename to Core/source/lib/openpgp.d.ts diff --git a/Core/source/core/types/openpgpv4.d.ts b/Core/source/lib/openpgpv4.d.ts similarity index 100% rename from Core/source/core/types/openpgpv4.d.ts rename to Core/source/lib/openpgpv4.d.ts diff --git a/Core/source/mobile-interface/endpoints.ts b/Core/source/mobile-interface/endpoints.ts index a6ca2b980..ac415bf4b 100644 --- a/Core/source/mobile-interface/endpoints.ts +++ b/Core/source/mobile-interface/endpoints.ts @@ -18,7 +18,7 @@ import { VERSION } from '../core/const'; import { ValidateInput, readArmoredKeyOrThrow, NodeRequest } from './validate-input'; import { Xss } from '../platform/xss'; import { gmailBackupSearchQuery } from '../core/const'; -import { encryptKey, Key, PrivateKey, readKeys } from '../core/types/openpgp'; +import { encryptKey, Key, PrivateKey, readKeys } from '../lib/openpgp'; export class Endpoints { diff --git a/Core/source/mobile-interface/validate-input.ts b/Core/source/mobile-interface/validate-input.ts index 7a702b215..d54121c2e 100644 --- a/Core/source/mobile-interface/validate-input.ts +++ b/Core/source/mobile-interface/validate-input.ts @@ -2,7 +2,7 @@ 'use strict'; -import { readKey } from "../core/types/openpgp"; +import { readKey } from "../lib/openpgp"; type Obj = { [k: string]: any }; diff --git a/Core/source/platform/store.ts b/Core/source/platform/store.ts index 93322cf04..a1a388170 100644 --- a/Core/source/platform/store.ts +++ b/Core/source/platform/store.ts @@ -2,7 +2,7 @@ 'use strict'; -import { Key } from '../core/types/openpgp'; +import { Key } from '../lib/openpgp'; import { str_to_hex } from './util'; let KEY_CACHE: { [longidOrArmoredKey: string]: Key } = {}; diff --git a/Core/source/test.ts b/Core/source/test.ts index 5d90f864f..58be31ad8 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -17,7 +17,7 @@ import { allKeypairNames, expectData, expectEmptyJson, expectNoData, getCompatAs import { Xss } from './platform/xss'; import { expect } from 'chai'; import { Endpoints } from './mobile-interface/endpoints'; -import { decryptKey, PrivateKey, readKey } from './core/types/openpgp'; +import { decryptKey, PrivateKey, readKey } from './lib/openpgp'; const text = 'some\n汉\ntxt'; const htmlContent = text.replace(/\n/g, '
'); From fff755e15e527c2fe855d60ec1cd7f0aae1040f9 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Mon, 7 Feb 2022 23:21:40 +0200 Subject: [PATCH 066/179] wip --- Core/tooling/fix-bundles.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/tooling/fix-bundles.js b/Core/tooling/fix-bundles.js index 916b2de0d..3a12d9ddb 100644 --- a/Core/tooling/fix-bundles.js +++ b/Core/tooling/fix-bundles.js @@ -70,7 +70,7 @@ const replace = (libSrc, regex, replacement) => { return libSrc.replace(regex, replacement); } -let openpgpLib = fs.readFileSync('source/lib/openpgp.js').toString(); +let openpgpLib = fs.readFileSync(`${libsDir}/openpgp.js`).toString(); const openpgpLibNodeDev = openpgpLib; // dev node runs without any host, no modifications needed /* From 2e8b12b76768a197963d606d5815b34e46dd4e6f Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Tue, 8 Feb 2022 19:16:08 +0200 Subject: [PATCH 067/179] wip --- Core/source/core/pgp-armor.ts | 2 +- Core/source/core/pgp-hash.ts | 2 +- Core/source/core/pgp-key.ts | 7 ++-- Core/source/core/pgp-msg.ts | 10 +++-- Core/source/core/pgp-password.ts | 2 +- Core/source/core/pgp.ts | 20 +++++----- Core/source/gen-compat-assets.ts | 2 +- Core/source/lib/openpgp.d.ts | 5 --- Core/source/mobile-interface/endpoints.ts | 2 +- .../source/mobile-interface/validate-input.ts | 2 +- Core/source/platform/store.ts | 2 +- Core/source/test.ts | 37 ++++++++++--------- 12 files changed, 47 insertions(+), 46 deletions(-) diff --git a/Core/source/core/pgp-armor.ts b/Core/source/core/pgp-armor.ts index 1bcd9c2fd..a34f00cd5 100644 --- a/Core/source/core/pgp-armor.ts +++ b/Core/source/core/pgp-armor.ts @@ -5,7 +5,7 @@ import { Buf } from './buf'; import { ReplaceableMsgBlockType } from './msg-block'; import { Str } from './common'; -import { CleartextMessage, Data, Message, readCleartextMessage, readMessage } from '../lib/openpgp'; +import { CleartextMessage, Data, Message, readCleartextMessage, readMessage } from 'openpgp'; export type PreparedForDecrypt = { isArmored: boolean, isCleartext: true, message: CleartextMessage } | { isArmored: boolean, isCleartext: false, message: Message }; diff --git a/Core/source/core/pgp-hash.ts b/Core/source/core/pgp-hash.ts index 0bbf28321..933e3b265 100644 --- a/Core/source/core/pgp-hash.ts +++ b/Core/source/core/pgp-hash.ts @@ -2,7 +2,7 @@ 'use strict'; -import { util, Sha1, Sha256 } from '../lib/openpgp'; +import { util, Sha1, Sha256 } from 'openpgp'; import { Buf } from './buf'; export class PgpHash { diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index b58375f43..42ddf2bf3 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -9,7 +9,8 @@ import { PgpArmor } from './pgp-armor'; import { Store } from '../platform/store'; import { mnemonic } from './mnemonic'; import { str_to_hex } from '../platform/util'; -import { AnyKeyPacket, BaseSecretKeyPacket, enums, generateKey, Key, KeyID, PacketList, PrivateKey, PublicKey, readKey, readKeys, readMessage, readToEnd, revokeKey, SecretKeyPacket, SecretSubkeyPacket, SignaturePacket, UserID } from '../lib/openpgp'; +import { AnyKeyPacket, BaseSecretKeyPacket, enums, generateKey, Key, KeyID, PacketList, PrivateKey, PublicKey, readKey, readKeys, readMessage, readToEnd, revokeKey, SecretKeyPacket, SecretSubkeyPacket, SignaturePacket, UserID } from 'openpgp'; +import { isFullyDecrypted, isFullyEncrypted } from './pgp'; export type Contact = { email: string; @@ -337,8 +338,8 @@ export class PgpKey { } return { private: k.isPrivate() ? k.armor() : undefined, - isFullyDecrypted: k.isPrivate() ? k.isFullyDecrypted() : undefined, - isFullyEncrypted: k.isPrivate() ? k.isFullyEncrypted() : undefined, + isFullyDecrypted: k.isPrivate() ? isFullyDecrypted(k) : undefined, + isFullyEncrypted: k.isPrivate() ? isFullyEncrypted(k) : undefined, public: k.toPublic().armor(), users: k.getUserIDs(), ids, diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index e0218e984..67f7271fc 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -12,7 +12,8 @@ import { FcAttLinkData } from './att'; import { MsgBlockParser } from './msg-block-parser'; import { PgpArmor } from './pgp-armor'; import { Store } from '../platform/store'; -import { CleartextMessage, createCleartextMessage, createMessage, Data, encrypt, enums, Key, KeyID, Message, PrivateKey, readKeys, readMessage, readToEnd, sign, VerificationResult } from '../lib/openpgp'; +import { CleartextMessage, createCleartextMessage, createMessage, Data, encrypt, enums, Key, KeyID, Message, PrivateKey, readKeys, readMessage, readToEnd, sign, VerificationResult } from 'openpgp'; +import { isFullyDecrypted, isFullyEncrypted, isPacketDecrypted } from './pgp'; export namespace PgpMsgMethod { export namespace Arg { @@ -462,16 +463,17 @@ export class PgpMsg { } private static isKeyDecryptedFor = (prv: Key, msgKeyIds: KeyID[]): boolean => { - if (prv.isFullyDecrypted()) { + if (isFullyDecrypted(prv)) { return true; // primary k + all subkeys decrypted, therefore it must be decrypted for any/every particular keyid } - if (prv.isFullyEncrypted()) { + if (isFullyEncrypted(prv)) { return false; // not decrypted at all } if (!msgKeyIds.length) { return false; // we don't know which keyId to decrypt - must decrypt all (but key is only partially decrypted) } - return msgKeyIds.filter(kid => prv.isPacketDecrypted(kid)).length === msgKeyIds.length; // test if all needed key packets are decrypted + // test if all needed key packets are decrypted + return msgKeyIds.filter(kid => isPacketDecrypted(prv, kid)).length === msgKeyIds.length; } private static cryptoMsgDecryptCategorizeErr = (decryptErr: any, msgPwd?: string): DecryptError$error => { diff --git a/Core/source/core/pgp-password.ts b/Core/source/core/pgp-password.ts index 1b17a86a7..57f2572f3 100644 --- a/Core/source/core/pgp-password.ts +++ b/Core/source/core/pgp-password.ts @@ -3,7 +3,7 @@ 'use strict'; import { base64encode, secureRandomBytes } from '../platform/util'; -import { util } from '../lib/openpgp'; +import { util } from 'openpgp'; interface PwdStrengthResult { word: { diff --git a/Core/source/core/pgp.ts b/Core/source/core/pgp.ts index a252be7b4..6f8e59568 100644 --- a/Core/source/core/pgp.ts +++ b/Core/source/core/pgp.ts @@ -5,7 +5,7 @@ import { PgpKey, PrvPacket } from './pgp-key'; import { VERSION } from './const'; -import { Key, KeyID, config } from '../lib/openpgp'; +import { Key, KeyID, config } from 'openpgp'; config.versionString = `FlowCrypt ${VERSION} Gmail Encryption`; config.commentString = 'Seamlessly send and receive encrypted email'; @@ -29,24 +29,24 @@ const getPrvPackets = (k: Key) => { return nonDummyPrvPackets; }; -Key.prototype.isFullyDecrypted = function () { - return getPrvPackets(this).every(p => p.isDecrypted() === true); +export const isFullyDecrypted = (key: Key): boolean => { + return getPrvPackets(key).every(p => p.isDecrypted() === true); }; -Key.prototype.isFullyEncrypted = function () { - return getPrvPackets(this).every(p => p.isDecrypted() === false); +export const isFullyEncrypted = (key: Key): boolean => { + return getPrvPackets(key).every(p => p.isDecrypted() === false); }; -Key.prototype.isPacketDecrypted = function (keyID: KeyID) { - if (!this.isPrivate()) { +export const isPacketDecrypted = (key: Key, keyID: KeyID): boolean => { + if (!key.isPrivate()) { throw new Error("Cannot check packet encryption status of secret key in a Public Key"); } if (!keyID) { throw new Error("No KeyID provided to isPacketDecrypted"); } - const [key] = this.getKeys(keyID); - if (!key) { + const [k] = key.getKeys(keyID); + if (!k) { throw new Error("KeyID not found in Private Key"); } - return key.keyPacket.isDecrypted() === true; + return k.keyPacket.isDecrypted() === true; }; diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index cbe3fd21f..f0562cd53 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -11,7 +11,7 @@ import * as ava from 'ava'; import { AvaContext, getKeypairs, writeFile } from './test/test-utils'; import { PgpMsg } from './core/pgp-msg'; import { Xss } from './platform/xss'; -import { decryptKey, PrivateKey, readKey } from './lib/openpgp'; +import { decryptKey, PrivateKey, readKey } from 'openpgp'; const text = Buffer.from('some\n汉\ntxt'); const textSpecialChars = Buffer.from('> special & other\n> second line'); diff --git a/Core/source/lib/openpgp.d.ts b/Core/source/lib/openpgp.d.ts index 8d483518b..066818dba 100644 --- a/Core/source/lib/openpgp.d.ts +++ b/Core/source/lib/openpgp.d.ts @@ -71,11 +71,6 @@ export abstract class Key { public getAlgorithmInfo(): AlgorithmInfo; public getKeyID(): KeyID; public toPacketList(): PacketList; - // -----BEGIN ADDED BY FLOWCRYPT----- - public isFullyEncrypted(): boolean; - public isFullyDecrypted(): boolean; - public isPacketDecrypted(keyID: KeyID): boolean; - // -----END ADDED BY FLOWCRYPT----- } type AllowedKeyPackets = PublicKeyPacket | PublicSubkeyPacket | SecretKeyPacket | SecretSubkeyPacket | UserIDPacket | UserAttributePacket | SignaturePacket; diff --git a/Core/source/mobile-interface/endpoints.ts b/Core/source/mobile-interface/endpoints.ts index ac415bf4b..75fec0ca5 100644 --- a/Core/source/mobile-interface/endpoints.ts +++ b/Core/source/mobile-interface/endpoints.ts @@ -18,7 +18,7 @@ import { VERSION } from '../core/const'; import { ValidateInput, readArmoredKeyOrThrow, NodeRequest } from './validate-input'; import { Xss } from '../platform/xss'; import { gmailBackupSearchQuery } from '../core/const'; -import { encryptKey, Key, PrivateKey, readKeys } from '../lib/openpgp'; +import { encryptKey, Key, PrivateKey, readKeys } from 'openpgp'; export class Endpoints { diff --git a/Core/source/mobile-interface/validate-input.ts b/Core/source/mobile-interface/validate-input.ts index d54121c2e..bfa3e0694 100644 --- a/Core/source/mobile-interface/validate-input.ts +++ b/Core/source/mobile-interface/validate-input.ts @@ -2,7 +2,7 @@ 'use strict'; -import { readKey } from "../lib/openpgp"; +import { readKey } from "openpgp"; type Obj = { [k: string]: any }; diff --git a/Core/source/platform/store.ts b/Core/source/platform/store.ts index a1a388170..e99c839f3 100644 --- a/Core/source/platform/store.ts +++ b/Core/source/platform/store.ts @@ -2,7 +2,7 @@ 'use strict'; -import { Key } from '../lib/openpgp'; +import { Key } from 'openpgp'; import { str_to_hex } from './util'; let KEY_CACHE: { [longidOrArmoredKey: string]: Key } = {}; diff --git a/Core/source/test.ts b/Core/source/test.ts index 58be31ad8..b67c29f65 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -17,7 +17,8 @@ import { allKeypairNames, expectData, expectEmptyJson, expectNoData, getCompatAs import { Xss } from './platform/xss'; import { expect } from 'chai'; import { Endpoints } from './mobile-interface/endpoints'; -import { decryptKey, PrivateKey, readKey } from './lib/openpgp'; +import { decryptKey, PrivateKey, readKey } from 'openpgp'; +import { isFullyDecrypted, isFullyEncrypted } from './core/pgp'; const text = 'some\n汉\ntxt'; const htmlContent = text.replace(/\n/g, '
'); @@ -36,8 +37,8 @@ ava.default('generateKey', async t => { const { json, data } = parseResponse(await endpoints.generateKey({ variant: 'curve25519', passphrase: 'riruekfhydekdmdbsyd', userIds: [{ email: 'a@b.com', name: 'Him' }] })); expect(json.key.private).to.contain('-----BEGIN PGP PRIVATE KEY BLOCK-----'); expect(json.key.public).to.contain('-----BEGIN PGP PUBLIC KEY BLOCK-----'); - expect(json.key.isFullyEncrypted).to.be.true; - expect(json.key.isFullyDecrypted).to.be.false; + expect(isFullyDecrypted(json.key)).to.be.true; + expect(isFullyDecrypted(json.key)).to.be.false; expect(json.key.algo).to.deep.equal({ algorithm: 'eddsa', curve: 'ed25519', algorithmId: 22 }); expectNoData(data); t.pass(); @@ -429,8 +430,8 @@ ava.default('decryptKey', async t => { const { keys: [key] } = getKeypairs('rsa1'); const { data, json } = parseResponse(await endpoints.decryptKey({ armored: key.private, passphrases: [key.passphrase] })); const decryptedKey = await readKey({armoredKey: json.decryptedKey}); - expect(decryptedKey.isFullyDecrypted()).to.be.true; - expect(decryptedKey.isFullyEncrypted()).to.be.false; + expect(isFullyDecrypted(decryptedKey)).to.be.true; + expect(isFullyEncrypted(decryptedKey)).to.be.false; expectNoData(data); t.pass(); }); @@ -440,8 +441,8 @@ ava.default('encryptKey', async t => { const { decrypted: [decryptedKey] } = getKeypairs('rsa1'); const { data, json } = parseResponse(await endpoints.encryptKey({ armored: decryptedKey, passphrase })); const encryptedKey = await readKey({armoredKey: json.encryptedKey}); - expect(encryptedKey.isFullyEncrypted()).to.be.true; - expect(encryptedKey.isFullyDecrypted()).to.be.false; + expect(isFullyEncrypted(encryptedKey)).to.be.true; + expect(isFullyDecrypted(encryptedKey)).to.be.false; expect(await decryptKey({ privateKey: (encryptedKey as PrivateKey), passphrase: passphrase @@ -453,20 +454,22 @@ ava.default('encryptKey', async t => { ava.default('decryptKey gpg-dummy', async t => { const { keys: [key] } = getKeypairs('gpg-dummy'); const encryptedKey = await readKey({armoredKey: key.private}); - expect(encryptedKey.isFullyEncrypted()).to.be.true; - expect(encryptedKey.isFullyDecrypted()).to.be.false; + expect(isFullyEncrypted(encryptedKey)).to.be.true; + expect(isFullyDecrypted(encryptedKey)).to.be.false; const { json } = parseResponse(await endpoints.decryptKey({ armored: key.private, passphrases: [key.passphrase] })); const decryptedKey = await readKey({armoredKey: json.decryptedKey}); - expect(decryptedKey.isFullyEncrypted()).to.be.false; - expect(decryptedKey.isFullyDecrypted()).to.be.true; - const { json: json2 } = parseResponse(await endpoints.encryptKey({ armored: decryptedKey.armor(), passphrase: 'another pass phrase' })); + expect(isFullyEncrypted(decryptedKey)).to.be.false; + expect(isFullyDecrypted(decryptedKey)).to.be.true; + const { json: json2 } = parseResponse(await endpoints.encryptKey( + { armored: decryptedKey.armor(), passphrase: 'another pass phrase' })); const reEncryptedKey = await readKey({armoredKey: json2.encryptedKey}); - expect(reEncryptedKey.isFullyEncrypted()).to.be.true; - expect(reEncryptedKey.isFullyDecrypted()).to.be.false; - const { json: json3 } = parseResponse(await endpoints.decryptKey({ armored: reEncryptedKey.armor(), passphrases: ['another pass phrase'] })); + expect(isFullyEncrypted(reEncryptedKey)).to.be.true; + expect(isFullyDecrypted(reEncryptedKey)).to.be.false; + const { json: json3 } = parseResponse(await endpoints.decryptKey( + { armored: reEncryptedKey.armor(), passphrases: ['another pass phrase'] })); const reDecryptedKey = await readKey({armoredKey: json3.decryptedKey}); - expect(reDecryptedKey.isFullyEncrypted()).to.be.false; - expect(reDecryptedKey.isFullyDecrypted()).to.be.true; + expect(isFullyEncrypted(reDecryptedKey)).to.be.false; + expect(isFullyDecrypted(reDecryptedKey)).to.be.true; t.pass(); }); From c41dde8d40297012ba99d9e8b63c19704062d4e7 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Tue, 8 Feb 2022 19:19:33 +0200 Subject: [PATCH 068/179] wip --- Core/package-lock.json | 45 ++++++++++++++++++++++++++++++++++++++++++ Core/package.json | 3 ++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/Core/package-lock.json b/Core/package-lock.json index c09ebd6a7..6e27b73e7 100644 --- a/Core/package-lock.json +++ b/Core/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.1", "license": "SEE LICENSE IN ", "dependencies": { + "@openpgp/web-stream-tools": "^0.0.9", "encoding-japanese": "^1.0.30", "openpgp": "5.1.0", "sanitize-html": "2.6.1", @@ -355,6 +356,14 @@ "node": ">=10.0.0" } }, + "node_modules/@mattiasbuelens/web-streams-adapter": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@mattiasbuelens/web-streams-adapter/-/web-streams-adapter-0.1.0.tgz", + "integrity": "sha512-oV4PyZfwJNtmFWhvlJLqYIX1Nn22ML8FZpS16ZUKv0hg7414xV1fjsGqxQzLT2dyK92TKxsJSwMOd7VNHAtPmA==", + "engines": { + "node": ">= 12" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -390,6 +399,15 @@ "node": ">= 8" } }, + "node_modules/@openpgp/web-stream-tools": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@openpgp/web-stream-tools/-/web-stream-tools-0.0.9.tgz", + "integrity": "sha512-GEKuXpQRshUqgKH4sMcwYbHolxaUSHIowcIMd02EsnLv4q5acP0z9pRUy3kjV0ZyRPgyD0vXAy60Rf0MPKoCMw==", + "dependencies": { + "@mattiasbuelens/web-streams-adapter": "~0.1.0", + "web-streams-polyfill": "~3.0.3" + } + }, "node_modules/@types/chai": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.0.tgz", @@ -7913,6 +7931,14 @@ "node": ">=8.0" } }, + "node_modules/web-streams-polyfill": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.0.3.tgz", + "integrity": "sha512-d2H/t0eqRNM4w2WvmTdoeIvzAUSpK7JmATB8Nr2lb7nQ9BTIJVjbQ/TRFVEh2gUH1HwclPdoPtfMoFfetXaZnA==", + "engines": { + "node": ">= 8" + } + }, "node_modules/webpack": { "version": "4.46.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", @@ -8751,6 +8777,11 @@ "integrity": "sha512-ws57AidsDvREKrZKYffXddNkyaF14iHNHm8VQnZH6t99E8gczjNN0GpvcGny0imC80yQ0tHz1xVUKk/KFQSUyA==", "dev": true }, + "@mattiasbuelens/web-streams-adapter": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@mattiasbuelens/web-streams-adapter/-/web-streams-adapter-0.1.0.tgz", + "integrity": "sha512-oV4PyZfwJNtmFWhvlJLqYIX1Nn22ML8FZpS16ZUKv0hg7414xV1fjsGqxQzLT2dyK92TKxsJSwMOd7VNHAtPmA==" + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -8777,6 +8808,15 @@ "fastq": "^1.6.0" } }, + "@openpgp/web-stream-tools": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@openpgp/web-stream-tools/-/web-stream-tools-0.0.9.tgz", + "integrity": "sha512-GEKuXpQRshUqgKH4sMcwYbHolxaUSHIowcIMd02EsnLv4q5acP0z9pRUy3kjV0ZyRPgyD0vXAy60Rf0MPKoCMw==", + "requires": { + "@mattiasbuelens/web-streams-adapter": "~0.1.0", + "web-streams-polyfill": "~3.0.3" + } + }, "@types/chai": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.0.tgz", @@ -14871,6 +14911,11 @@ "chokidar": "^2.1.8" } }, + "web-streams-polyfill": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.0.3.tgz", + "integrity": "sha512-d2H/t0eqRNM4w2WvmTdoeIvzAUSpK7JmATB8Nr2lb7nQ9BTIJVjbQ/TRFVEh2gUH1HwclPdoPtfMoFfetXaZnA==" + }, "webpack": { "version": "4.46.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", diff --git a/Core/package.json b/Core/package.json index b03ace331..ef1031b37 100644 --- a/Core/package.json +++ b/Core/package.json @@ -3,6 +3,7 @@ "version": "0.0.1", "description": "TypeScript core for FlowCrypt iOS internal use", "dependencies": { + "@openpgp/web-stream-tools": "^0.0.9", "encoding-japanese": "^1.0.30", "openpgp": "5.1.0", "sanitize-html": "2.6.1", @@ -42,4 +43,4 @@ "license": "SEE LICENSE IN ", "private": true, "homepage": "https://flowcrypt.com" -} \ No newline at end of file +} From ad23f0482aebf4b6b2c172575ed116ef80648a31 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Tue, 8 Feb 2022 21:17:27 +0200 Subject: [PATCH 069/179] wip --- Core/source/core/pgp-msg.ts | 5 +- .../web-stream-tools/node-conversions.d.ts | 6 + .../@openpgp/web-stream-tools/reader.d.ts | 75 +++++++++ .../@openpgp/web-stream-tools/streams.d.ts | 145 ++++++++++++++++++ .../types/@openpgp/web-stream-tools/util.d.ts | 21 +++ .../@openpgp/web-stream-tools/writer.d.ts | 65 ++++++++ 6 files changed, 316 insertions(+), 1 deletion(-) create mode 100644 Core/source/core/types/@openpgp/web-stream-tools/node-conversions.d.ts create mode 100644 Core/source/core/types/@openpgp/web-stream-tools/reader.d.ts create mode 100644 Core/source/core/types/@openpgp/web-stream-tools/streams.d.ts create mode 100644 Core/source/core/types/@openpgp/web-stream-tools/util.d.ts create mode 100644 Core/source/core/types/@openpgp/web-stream-tools/writer.d.ts diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index 67f7271fc..0e99702a5 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -2,6 +2,8 @@ 'use strict'; +/// + import { KeyInfo, PgpKey, PrvKeyInfo } from './pgp-key'; import { MsgBlock, MsgBlockType } from './msg-block'; import { Str, Value } from './common'; @@ -12,8 +14,9 @@ import { FcAttLinkData } from './att'; import { MsgBlockParser } from './msg-block-parser'; import { PgpArmor } from './pgp-armor'; import { Store } from '../platform/store'; -import { CleartextMessage, createCleartextMessage, createMessage, Data, encrypt, enums, Key, KeyID, Message, PrivateKey, readKeys, readMessage, readToEnd, sign, VerificationResult } from 'openpgp'; +import { CleartextMessage, createCleartextMessage, createMessage, Data, encrypt, enums, Key, KeyID, Message, PrivateKey, readKeys, readMessage, sign, VerificationResult } from 'openpgp'; import { isFullyDecrypted, isFullyEncrypted, isPacketDecrypted } from './pgp'; +import { readToEnd } from '@openpgp/web-stream-tools'; export namespace PgpMsgMethod { export namespace Arg { diff --git a/Core/source/core/types/@openpgp/web-stream-tools/node-conversions.d.ts b/Core/source/core/types/@openpgp/web-stream-tools/node-conversions.d.ts new file mode 100644 index 000000000..2bbcb2da2 --- /dev/null +++ b/Core/source/core/types/@openpgp/web-stream-tools/node-conversions.d.ts @@ -0,0 +1,6 @@ +/** + * Web / node stream conversion functions + * From https://github.com/gwicke/node-web-streams + */ +export let nodeToWeb: any; +export let webToNode: any; diff --git a/Core/source/core/types/@openpgp/web-stream-tools/reader.d.ts b/Core/source/core/types/@openpgp/web-stream-tools/reader.d.ts new file mode 100644 index 000000000..318b344ce --- /dev/null +++ b/Core/source/core/types/@openpgp/web-stream-tools/reader.d.ts @@ -0,0 +1,75 @@ +/** + * A wrapper class over the native ReadableStreamDefaultReader. + * This additionally implements pushing back data on the stream, which + * lets us implement peeking and a host of convenience functions. + * It also lets you read data other than streams, such as a Uint8Array. + * @class + */ +export function Reader(input: any): void; +export class Reader { + /** + * A wrapper class over the native ReadableStreamDefaultReader. + * This additionally implements pushing back data on the stream, which + * lets us implement peeking and a host of convenience functions. + * It also lets you read data other than streams, such as a Uint8Array. + * @class + */ + constructor(input: any); + stream: any; + _read: any; + _releaseLock: () => void; + _cancel: any; + /** + * Read a chunk of data. + * @returns {Promise} Either { done: false, value: Uint8Array | String } or { done: true, value: undefined } + * @async + */ + read(): Promise; + /** + * Allow others to read the stream. + */ + releaseLock(): void; + /** + * Cancel the stream. + */ + cancel(reason: any): any; + /** + * Read up to and including the first \n character. + * @returns {Promise} + * @async + */ + readLine(): Promise; + /** + * Read a single byte/character. + * @returns {Promise} + * @async + */ + readByte(): Promise; + /** + * Read a specific amount of bytes/characters, unless the stream ends before that amount. + * @returns {Promise} + * @async + */ + readBytes(length: any): Promise; + /** + * Peek (look ahead) a specific amount of bytes/characters, unless the stream ends before that amount. + * @returns {Promise} + * @async + */ + peekBytes(length: any): Promise; + /** + * Push data to the front of the stream. + * Data must have been read in the last call to read*. + * @param {...(Uint8Array|String|Undefined)} values + */ + unshift(...values: (Uint8Array | string | undefined)[]): void; + /** + * Read the stream to the end and return its contents, concatenated by the join function (defaults to streams.concat). + * @param {Function} join + * @returns {Promise} the return value of join() + * @async + */ + readToEnd(join?: Function): Promise; + [externalBuffer]: any; +} +export const externalBuffer: unique symbol; diff --git a/Core/source/core/types/@openpgp/web-stream-tools/streams.d.ts b/Core/source/core/types/@openpgp/web-stream-tools/streams.d.ts new file mode 100644 index 000000000..0718da19e --- /dev/null +++ b/Core/source/core/types/@openpgp/web-stream-tools/streams.d.ts @@ -0,0 +1,145 @@ +export let ReadableStream: { + new (underlyingSource?: UnderlyingSource, strategy?: QueuingStrategy): ReadableStream; + prototype: ReadableStream; +}; +export let WritableStream: { + new (underlyingSink?: UnderlyingSink, strategy?: QueuingStrategy): WritableStream; + prototype: WritableStream; +}; +export let TransformStream: { + new (transformer?: Transformer, writableStrategy?: QueuingStrategy, readableStrategy?: QueuingStrategy): TransformStream; + prototype: TransformStream; +}; +import { ArrayStream } from "./writer"; +export function loadStreamsPonyfill(): Promise; +import { isStream } from "./util"; +import { isArrayStream } from "./util"; +import { isUint8Array } from "./util"; +/** + * Convert data to Stream + * @param {ReadableStream|Uint8array|String} input data to convert + * @returns {ReadableStream} Converted data + */ +export function toStream(input: ReadableStream | Uint8array | string): ReadableStream; +export let toPonyfillReadable: any; +export let toNativeReadable: any; +import { concatUint8Array } from "./util"; +/** + * Concat a list of Streams + * @param {Array} list Array of Uint8Arrays/Strings/Streams to concatenate + * @returns {ReadableStream} Concatenated list + */ +export function concatStream(list: Array): ReadableStream; +/** + * Concat a list of Uint8Arrays, Strings or Streams + * The caller should not mix Uint8Arrays with Strings, but may mix Streams with non-Streams. + * @param {Array} Array of Uint8Arrays/Strings/Streams to concatenate + * @returns {Uint8array|String|ReadableStream} Concatenated array + */ +export function concat(list: any): Uint8array | string | ReadableStream; +/** + * Get a Reader + * @param {ReadableStream|Uint8array|String} input + * @returns {Reader} + */ +export function getReader(input: ReadableStream | Uint8array | string): Reader; +/** + * Get a Writer + * @param {WritableStream} input + * @returns {Writer} + */ +export function getWriter(input: WritableStream): Writer; +/** + * Pipe a readable stream to a writable stream. Don't throw on input stream errors, but forward them to the output stream. + * @param {ReadableStream|Uint8array|String} input + * @param {WritableStream} target + * @param {Object} (optional) options + * @returns {Promise} Promise indicating when piping has finished (input stream closed or errored) + * @async + */ +export function pipe(input: ReadableStream | Uint8array | string, target: WritableStream, { preventClose, preventAbort, preventCancel }?: any): Promise; +/** + * Pipe a readable stream through a transform stream. + * @param {ReadableStream|Uint8array|String} input + * @param {Object} (optional) options + * @returns {ReadableStream} transformed stream + */ +export function transformRaw(input: ReadableStream | Uint8array | string, options: any): ReadableStream; +/** + * Transform a stream using helper functions which are called on each chunk, and on stream close, respectively. + * @param {ReadableStream|Uint8array|String} input + * @param {Function} process + * @param {Function} finish + * @returns {ReadableStream|Uint8array|String} + */ +export function transform(input: ReadableStream | Uint8array | string, process?: Function, finish?: Function): ReadableStream | Uint8array | string; +/** + * Transform a stream using a helper function which is passed a readable and a writable stream. + * This function also maintains the possibility to cancel the input stream, + * and does so on cancelation of the output stream, despite cancelation + * normally being impossible when the input stream is being read from. + * @param {ReadableStream|Uint8array|String} input + * @param {Function} fn + * @returns {ReadableStream} + */ +export function transformPair(input: ReadableStream | Uint8array | string, fn: Function): ReadableStream; +/** + * Parse a stream using a helper function which is passed a Reader. + * The reader additionally has a remainder() method which returns a + * stream pointing to the remainder of input, and is linked to input + * for cancelation. + * @param {ReadableStream|Uint8array|String} input + * @param {Function} fn + * @returns {Any} the return value of fn() + */ +export function parse(input: ReadableStream | Uint8array | string, fn: Function): Any; +/** + * Clone a Stream for reading it twice. The input stream can still be read after clone()ing. + * Reading from the clone will pull from the input stream. + * The input stream will only be canceled if both the clone and the input stream are canceled. + * @param {ReadableStream|Uint8array|String} input + * @returns {ReadableStream|Uint8array|String} cloned input + */ +export function clone(input: ReadableStream | Uint8array | string): ReadableStream | Uint8array | string; +/** + * Clone a Stream for reading it twice. Data will arrive at the same rate as the input stream is being read. + * Reading from the clone will NOT pull from the input stream. Data only arrives when reading the input stream. + * The input stream will NOT be canceled if the clone is canceled, only if the input stream are canceled. + * If the input stream is canceled, the clone will be errored. + * @param {ReadableStream|Uint8array|String} input + * @returns {ReadableStream|Uint8array|String} cloned input + */ +export function passiveClone(input: ReadableStream | Uint8array | string): ReadableStream | Uint8array | string; +/** + * Return a stream pointing to a part of the input stream. + * @param {ReadableStream|Uint8array|String} input + * @returns {ReadableStream|Uint8array|String} clone + */ +export function slice(input: ReadableStream | Uint8array | string, begin?: number, end?: number): ReadableStream | Uint8array | string; +/** + * Read a stream to the end and return its contents, concatenated by the join function (defaults to concat). + * @param {ReadableStream|Uint8array|String} input + * @param {Function} join + * @returns {Promise} the return value of join() + * @async + */ +export function readToEnd(input: ReadableStream | Uint8array | string, join?: Function): Promise; +/** + * Cancel a stream. + * @param {ReadableStream|Uint8array|String} input + * @param {Any} reason + * @returns {Promise} indicates when the stream has been canceled + * @async + */ +export function cancel(input: ReadableStream | Uint8array | string, reason: Any): Promise; +/** + * Convert an async function to an ArrayStream. When the function returns, its return value is written to the stream. + * @param {Function} fn + * @returns {ArrayStream} + */ +export function fromAsync(fn: Function): ArrayStream; +import { nodeToWeb } from "./node-conversions"; +import { webToNode } from "./node-conversions"; +import { Reader } from "./reader"; +import { Writer } from "./writer"; +export { ArrayStream, isStream, isArrayStream, isUint8Array, concatUint8Array, nodeToWeb, webToNode }; diff --git a/Core/source/core/types/@openpgp/web-stream-tools/util.d.ts b/Core/source/core/types/@openpgp/web-stream-tools/util.d.ts new file mode 100644 index 000000000..dfcb8efcd --- /dev/null +++ b/Core/source/core/types/@openpgp/web-stream-tools/util.d.ts @@ -0,0 +1,21 @@ +export const isNode: boolean; +/** + * Check whether data is a Stream, and if so of which type + * @param {Any} input data to check + * @returns {'web'|'ponyfill'|'node'|'array'|'web-like'|false} + */ +export function isStream(input: Any): 'web' | 'ponyfill' | 'node' | 'array' | 'web-like' | false; +import { isArrayStream } from "./writer"; +/** + * Check whether data is a Uint8Array + * @param {Any} input data to check + * @returns {Boolean} + */ +export function isUint8Array(input: Any): boolean; +/** + * Concat Uint8Arrays + * @param {Array} Array of Uint8Arrays to concatenate + * @returns {Uint8array} Concatenated array + */ +export function concatUint8Array(arrays: any): Uint8array; +export { isArrayStream }; diff --git a/Core/source/core/types/@openpgp/web-stream-tools/writer.d.ts b/Core/source/core/types/@openpgp/web-stream-tools/writer.d.ts new file mode 100644 index 000000000..ff81d1df2 --- /dev/null +++ b/Core/source/core/types/@openpgp/web-stream-tools/writer.d.ts @@ -0,0 +1,65 @@ +export class ArrayStream extends Array { + constructor(); + getReader(): { + read: () => Promise<{ + value: any; + done: boolean; + }>; + }; + readToEnd(join: any): Promise; + clone(): ArrayStream; + [doneWritingPromise]: any; + [doneWritingResolve]: any; + [doneWritingReject]: any; + [readingIndex]: number; +} +/** + * Check whether data is an ArrayStream + * @param {Any} input data to check + * @returns {boolean} + */ +export function isArrayStream(input: Any): boolean; +/** + * A wrapper class over the native WritableStreamDefaultWriter. + * It also lets you "write data to" array streams instead of streams. + * @class + */ +export function Writer(input: any): any; +export class Writer { + /** + * A wrapper class over the native WritableStreamDefaultWriter. + * It also lets you "write data to" array streams instead of streams. + * @class + */ + constructor(input: any); + stream: any; + /** + * Write a chunk of data. + * @returns {Promise} + * @async + */ + write(chunk: any): Promise; + /** + * Close the stream. + * @returns {Promise} + * @async + */ + close(): Promise; + /** + * Error the stream. + * @returns {Promise} + * @async + */ + abort(reason: any): Promise; + /** + * Release the writer's lock. + * @returns {undefined} + * @async + */ + releaseLock(): undefined; +} +export const doneWritingPromise: unique symbol; +declare const doneWritingResolve: unique symbol; +declare const doneWritingReject: unique symbol; +declare const readingIndex: unique symbol; +export {}; From d22eec9e2a2eb838be011c5914a0cc5a4cf1303b Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Tue, 8 Feb 2022 21:18:06 +0200 Subject: [PATCH 070/179] wip --- Core/source/core/pgp-msg.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index 0e99702a5..4648268aa 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -2,8 +2,6 @@ 'use strict'; -/// - import { KeyInfo, PgpKey, PrvKeyInfo } from './pgp-key'; import { MsgBlock, MsgBlockType } from './msg-block'; import { Str, Value } from './common'; From 79e8fef69e17b42cf37c9b155fce51a225dba3d7 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Tue, 8 Feb 2022 21:31:03 +0200 Subject: [PATCH 071/179] wip --- Core/source/core/pgp-msg.ts | 2 ++ Core/source/{lib => core/types/openpgp}/openpgp.d.ts | 0 Core/source/{lib => core/types/openpgp}/openpgpv4.d.ts | 0 3 files changed, 2 insertions(+) rename Core/source/{lib => core/types/openpgp}/openpgp.d.ts (100%) rename Core/source/{lib => core/types/openpgp}/openpgpv4.d.ts (100%) diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index 4648268aa..5bc37fd6b 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -2,6 +2,8 @@ 'use strict'; +/// + import { KeyInfo, PgpKey, PrvKeyInfo } from './pgp-key'; import { MsgBlock, MsgBlockType } from './msg-block'; import { Str, Value } from './common'; diff --git a/Core/source/lib/openpgp.d.ts b/Core/source/core/types/openpgp/openpgp.d.ts similarity index 100% rename from Core/source/lib/openpgp.d.ts rename to Core/source/core/types/openpgp/openpgp.d.ts diff --git a/Core/source/lib/openpgpv4.d.ts b/Core/source/core/types/openpgp/openpgpv4.d.ts similarity index 100% rename from Core/source/lib/openpgpv4.d.ts rename to Core/source/core/types/openpgp/openpgpv4.d.ts From 30db75cdd52f47cd9a304f4f42eeae7d5815b015 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Tue, 8 Feb 2022 21:35:56 +0200 Subject: [PATCH 072/179] wip --- Core/source/core/types/@openpgp/web-stream-tools/README.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Core/source/core/types/@openpgp/web-stream-tools/README.txt diff --git a/Core/source/core/types/@openpgp/web-stream-tools/README.txt b/Core/source/core/types/@openpgp/web-stream-tools/README.txt new file mode 100644 index 000000000..73544f12d --- /dev/null +++ b/Core/source/core/types/@openpgp/web-stream-tools/README.txt @@ -0,0 +1,3 @@ +web-stream-tools don't provide Typescript definitions at the moment. +So I've had to generate them myself using its source code and these instructions: +https://www.typescriptlang.org/docs/handbook/declaration-files/dts-from-js.html From 9b516123df08b68266cf2487d92acbcdcd3853e1 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Tue, 8 Feb 2022 22:11:38 +0200 Subject: [PATCH 073/179] wip --- .../core/types/{@openpgp => openpgp}/web-stream-tools/README.txt | 0 .../{@openpgp => openpgp}/web-stream-tools/node-conversions.d.ts | 0 .../core/types/{@openpgp => openpgp}/web-stream-tools/reader.d.ts | 0 .../types/{@openpgp => openpgp}/web-stream-tools/streams.d.ts | 0 .../core/types/{@openpgp => openpgp}/web-stream-tools/util.d.ts | 0 .../core/types/{@openpgp => openpgp}/web-stream-tools/writer.d.ts | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename Core/source/core/types/{@openpgp => openpgp}/web-stream-tools/README.txt (100%) rename Core/source/core/types/{@openpgp => openpgp}/web-stream-tools/node-conversions.d.ts (100%) rename Core/source/core/types/{@openpgp => openpgp}/web-stream-tools/reader.d.ts (100%) rename Core/source/core/types/{@openpgp => openpgp}/web-stream-tools/streams.d.ts (100%) rename Core/source/core/types/{@openpgp => openpgp}/web-stream-tools/util.d.ts (100%) rename Core/source/core/types/{@openpgp => openpgp}/web-stream-tools/writer.d.ts (100%) diff --git a/Core/source/core/types/@openpgp/web-stream-tools/README.txt b/Core/source/core/types/openpgp/web-stream-tools/README.txt similarity index 100% rename from Core/source/core/types/@openpgp/web-stream-tools/README.txt rename to Core/source/core/types/openpgp/web-stream-tools/README.txt diff --git a/Core/source/core/types/@openpgp/web-stream-tools/node-conversions.d.ts b/Core/source/core/types/openpgp/web-stream-tools/node-conversions.d.ts similarity index 100% rename from Core/source/core/types/@openpgp/web-stream-tools/node-conversions.d.ts rename to Core/source/core/types/openpgp/web-stream-tools/node-conversions.d.ts diff --git a/Core/source/core/types/@openpgp/web-stream-tools/reader.d.ts b/Core/source/core/types/openpgp/web-stream-tools/reader.d.ts similarity index 100% rename from Core/source/core/types/@openpgp/web-stream-tools/reader.d.ts rename to Core/source/core/types/openpgp/web-stream-tools/reader.d.ts diff --git a/Core/source/core/types/@openpgp/web-stream-tools/streams.d.ts b/Core/source/core/types/openpgp/web-stream-tools/streams.d.ts similarity index 100% rename from Core/source/core/types/@openpgp/web-stream-tools/streams.d.ts rename to Core/source/core/types/openpgp/web-stream-tools/streams.d.ts diff --git a/Core/source/core/types/@openpgp/web-stream-tools/util.d.ts b/Core/source/core/types/openpgp/web-stream-tools/util.d.ts similarity index 100% rename from Core/source/core/types/@openpgp/web-stream-tools/util.d.ts rename to Core/source/core/types/openpgp/web-stream-tools/util.d.ts diff --git a/Core/source/core/types/@openpgp/web-stream-tools/writer.d.ts b/Core/source/core/types/openpgp/web-stream-tools/writer.d.ts similarity index 100% rename from Core/source/core/types/@openpgp/web-stream-tools/writer.d.ts rename to Core/source/core/types/openpgp/web-stream-tools/writer.d.ts From 5a860f95cd3d5b44a1ad3fc8625c3aa7a237676f Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Tue, 8 Feb 2022 22:19:59 +0200 Subject: [PATCH 074/179] wip --- Core/source/core/pgp-msg.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index 5bc37fd6b..9a8659f85 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -16,7 +16,7 @@ import { PgpArmor } from './pgp-armor'; import { Store } from '../platform/store'; import { CleartextMessage, createCleartextMessage, createMessage, Data, encrypt, enums, Key, KeyID, Message, PrivateKey, readKeys, readMessage, sign, VerificationResult } from 'openpgp'; import { isFullyDecrypted, isFullyEncrypted, isPacketDecrypted } from './pgp'; -import { readToEnd } from '@openpgp/web-stream-tools'; +import { readToEnd } from '@openpgp/web-stream-tools/streams'; export namespace PgpMsgMethod { export namespace Arg { From 7c3f3480d635c1acd97128fbecf56cf2beca1978 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Tue, 8 Feb 2022 22:31:10 +0200 Subject: [PATCH 075/179] wip --- Core/source/core/pgp-armor.ts | 2 +- Core/source/core/pgp-hash.ts | 2 +- Core/source/core/pgp-key.ts | 2 +- Core/source/core/pgp-msg.ts | 3 +-- Core/source/core/pgp-password.ts | 2 +- Core/source/core/pgp.ts | 2 +- Core/source/core/types/{openpgp => openpgpv4}/openpgpv4.d.ts | 0 Core/source/gen-compat-assets.ts | 2 +- Core/source/mobile-interface/endpoints.ts | 2 +- Core/source/platform/store.ts | 2 +- Core/source/test.ts | 2 +- 11 files changed, 10 insertions(+), 11 deletions(-) rename Core/source/core/types/{openpgp => openpgpv4}/openpgpv4.d.ts (100%) diff --git a/Core/source/core/pgp-armor.ts b/Core/source/core/pgp-armor.ts index a34f00cd5..1bcd9c2fd 100644 --- a/Core/source/core/pgp-armor.ts +++ b/Core/source/core/pgp-armor.ts @@ -5,7 +5,7 @@ import { Buf } from './buf'; import { ReplaceableMsgBlockType } from './msg-block'; import { Str } from './common'; -import { CleartextMessage, Data, Message, readCleartextMessage, readMessage } from 'openpgp'; +import { CleartextMessage, Data, Message, readCleartextMessage, readMessage } from '../lib/openpgp'; export type PreparedForDecrypt = { isArmored: boolean, isCleartext: true, message: CleartextMessage } | { isArmored: boolean, isCleartext: false, message: Message }; diff --git a/Core/source/core/pgp-hash.ts b/Core/source/core/pgp-hash.ts index 933e3b265..0bbf28321 100644 --- a/Core/source/core/pgp-hash.ts +++ b/Core/source/core/pgp-hash.ts @@ -2,7 +2,7 @@ 'use strict'; -import { util, Sha1, Sha256 } from 'openpgp'; +import { util, Sha1, Sha256 } from '../lib/openpgp'; import { Buf } from './buf'; export class PgpHash { diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index 42ddf2bf3..c0e212d87 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -9,7 +9,7 @@ import { PgpArmor } from './pgp-armor'; import { Store } from '../platform/store'; import { mnemonic } from './mnemonic'; import { str_to_hex } from '../platform/util'; -import { AnyKeyPacket, BaseSecretKeyPacket, enums, generateKey, Key, KeyID, PacketList, PrivateKey, PublicKey, readKey, readKeys, readMessage, readToEnd, revokeKey, SecretKeyPacket, SecretSubkeyPacket, SignaturePacket, UserID } from 'openpgp'; +import { AnyKeyPacket, BaseSecretKeyPacket, enums, generateKey, Key, KeyID, PacketList, PrivateKey, PublicKey, readKey, readKeys, readMessage, readToEnd, revokeKey, SecretKeyPacket, SecretSubkeyPacket, SignaturePacket, UserID } from '../lib/openpgp'; import { isFullyDecrypted, isFullyEncrypted } from './pgp'; export type Contact = { diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index 9a8659f85..e9de6beb6 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -14,9 +14,8 @@ import { FcAttLinkData } from './att'; import { MsgBlockParser } from './msg-block-parser'; import { PgpArmor } from './pgp-armor'; import { Store } from '../platform/store'; -import { CleartextMessage, createCleartextMessage, createMessage, Data, encrypt, enums, Key, KeyID, Message, PrivateKey, readKeys, readMessage, sign, VerificationResult } from 'openpgp'; +import { CleartextMessage, createCleartextMessage, createMessage, Data, encrypt, enums, Key, KeyID, Message, PrivateKey, readKeys, readMessage, readToEnd, sign, VerificationResult } from '../lib/openpgp'; import { isFullyDecrypted, isFullyEncrypted, isPacketDecrypted } from './pgp'; -import { readToEnd } from '@openpgp/web-stream-tools/streams'; export namespace PgpMsgMethod { export namespace Arg { diff --git a/Core/source/core/pgp-password.ts b/Core/source/core/pgp-password.ts index 57f2572f3..1b17a86a7 100644 --- a/Core/source/core/pgp-password.ts +++ b/Core/source/core/pgp-password.ts @@ -3,7 +3,7 @@ 'use strict'; import { base64encode, secureRandomBytes } from '../platform/util'; -import { util } from 'openpgp'; +import { util } from '../lib/openpgp'; interface PwdStrengthResult { word: { diff --git a/Core/source/core/pgp.ts b/Core/source/core/pgp.ts index 6f8e59568..166b925fb 100644 --- a/Core/source/core/pgp.ts +++ b/Core/source/core/pgp.ts @@ -5,7 +5,7 @@ import { PgpKey, PrvPacket } from './pgp-key'; import { VERSION } from './const'; -import { Key, KeyID, config } from 'openpgp'; +import { Key, KeyID, config } from '../lib/openpgp'; config.versionString = `FlowCrypt ${VERSION} Gmail Encryption`; config.commentString = 'Seamlessly send and receive encrypted email'; diff --git a/Core/source/core/types/openpgp/openpgpv4.d.ts b/Core/source/core/types/openpgpv4/openpgpv4.d.ts similarity index 100% rename from Core/source/core/types/openpgp/openpgpv4.d.ts rename to Core/source/core/types/openpgpv4/openpgpv4.d.ts diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index f0562cd53..cbe3fd21f 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -11,7 +11,7 @@ import * as ava from 'ava'; import { AvaContext, getKeypairs, writeFile } from './test/test-utils'; import { PgpMsg } from './core/pgp-msg'; import { Xss } from './platform/xss'; -import { decryptKey, PrivateKey, readKey } from 'openpgp'; +import { decryptKey, PrivateKey, readKey } from './lib/openpgp'; const text = Buffer.from('some\n汉\ntxt'); const textSpecialChars = Buffer.from('> special & other\n> second line'); diff --git a/Core/source/mobile-interface/endpoints.ts b/Core/source/mobile-interface/endpoints.ts index 75fec0ca5..ac415bf4b 100644 --- a/Core/source/mobile-interface/endpoints.ts +++ b/Core/source/mobile-interface/endpoints.ts @@ -18,7 +18,7 @@ import { VERSION } from '../core/const'; import { ValidateInput, readArmoredKeyOrThrow, NodeRequest } from './validate-input'; import { Xss } from '../platform/xss'; import { gmailBackupSearchQuery } from '../core/const'; -import { encryptKey, Key, PrivateKey, readKeys } from 'openpgp'; +import { encryptKey, Key, PrivateKey, readKeys } from '../lib/openpgp'; export class Endpoints { diff --git a/Core/source/platform/store.ts b/Core/source/platform/store.ts index e99c839f3..a1a388170 100644 --- a/Core/source/platform/store.ts +++ b/Core/source/platform/store.ts @@ -2,7 +2,7 @@ 'use strict'; -import { Key } from 'openpgp'; +import { Key } from '../lib/openpgp'; import { str_to_hex } from './util'; let KEY_CACHE: { [longidOrArmoredKey: string]: Key } = {}; diff --git a/Core/source/test.ts b/Core/source/test.ts index b67c29f65..b50f0baf6 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -17,7 +17,7 @@ import { allKeypairNames, expectData, expectEmptyJson, expectNoData, getCompatAs import { Xss } from './platform/xss'; import { expect } from 'chai'; import { Endpoints } from './mobile-interface/endpoints'; -import { decryptKey, PrivateKey, readKey } from 'openpgp'; +import { decryptKey, PrivateKey, readKey } from './lib/openpgp'; import { isFullyDecrypted, isFullyEncrypted } from './core/pgp'; const text = 'some\n汉\ntxt'; From 9fc62ffa78e1ec50fa18169e994285dd30ea6d6d Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 06:15:52 +0200 Subject: [PATCH 076/179] wip --- Core/{source/lib => .old}/openpgpv4.js | 0 Core/{source/core/types => .old}/openpgpv4/openpgpv4.d.ts | 0 Core/tsconfig.json | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) rename Core/{source/lib => .old}/openpgpv4.js (100%) rename Core/{source/core/types => .old}/openpgpv4/openpgpv4.d.ts (100%) diff --git a/Core/source/lib/openpgpv4.js b/Core/.old/openpgpv4.js similarity index 100% rename from Core/source/lib/openpgpv4.js rename to Core/.old/openpgpv4.js diff --git a/Core/source/core/types/openpgpv4/openpgpv4.d.ts b/Core/.old/openpgpv4/openpgpv4.d.ts similarity index 100% rename from Core/source/core/types/openpgpv4/openpgpv4.d.ts rename to Core/.old/openpgpv4/openpgpv4.d.ts diff --git a/Core/tsconfig.json b/Core/tsconfig.json index 3f4bcdc34..da90f4b0b 100644 --- a/Core/tsconfig.json +++ b/Core/tsconfig.json @@ -18,7 +18,7 @@ "sourceMap": false, "checkJs": false, "outDir": "./build/ts", - "baseUrl": "..", + "baseUrl": "./", "typeRoots": [ "./source/core/types/", "./node_modules/@types/" From 4d594a9662b135fbc87a97b8beb2af1bfdf20645 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 06:24:49 +0200 Subject: [PATCH 077/179] wip --- Core/source/core/pgp-armor.ts | 2 +- Core/source/core/pgp-hash.ts | 2 +- Core/source/core/pgp-key.ts | 2 +- Core/source/core/pgp-msg.ts | 4 ++-- Core/source/core/pgp-password.ts | 2 +- Core/source/core/pgp.ts | 2 +- Core/source/gen-compat-assets.ts | 2 +- Core/source/mobile-interface/endpoints.ts | 2 +- Core/source/platform/store.ts | 2 +- Core/source/test.ts | 2 +- Core/tsconfig.json | 3 +++ 11 files changed, 14 insertions(+), 11 deletions(-) diff --git a/Core/source/core/pgp-armor.ts b/Core/source/core/pgp-armor.ts index 1bcd9c2fd..a34f00cd5 100644 --- a/Core/source/core/pgp-armor.ts +++ b/Core/source/core/pgp-armor.ts @@ -5,7 +5,7 @@ import { Buf } from './buf'; import { ReplaceableMsgBlockType } from './msg-block'; import { Str } from './common'; -import { CleartextMessage, Data, Message, readCleartextMessage, readMessage } from '../lib/openpgp'; +import { CleartextMessage, Data, Message, readCleartextMessage, readMessage } from 'openpgp'; export type PreparedForDecrypt = { isArmored: boolean, isCleartext: true, message: CleartextMessage } | { isArmored: boolean, isCleartext: false, message: Message }; diff --git a/Core/source/core/pgp-hash.ts b/Core/source/core/pgp-hash.ts index 0bbf28321..933e3b265 100644 --- a/Core/source/core/pgp-hash.ts +++ b/Core/source/core/pgp-hash.ts @@ -2,7 +2,7 @@ 'use strict'; -import { util, Sha1, Sha256 } from '../lib/openpgp'; +import { util, Sha1, Sha256 } from 'openpgp'; import { Buf } from './buf'; export class PgpHash { diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index c0e212d87..42ddf2bf3 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -9,7 +9,7 @@ import { PgpArmor } from './pgp-armor'; import { Store } from '../platform/store'; import { mnemonic } from './mnemonic'; import { str_to_hex } from '../platform/util'; -import { AnyKeyPacket, BaseSecretKeyPacket, enums, generateKey, Key, KeyID, PacketList, PrivateKey, PublicKey, readKey, readKeys, readMessage, readToEnd, revokeKey, SecretKeyPacket, SecretSubkeyPacket, SignaturePacket, UserID } from '../lib/openpgp'; +import { AnyKeyPacket, BaseSecretKeyPacket, enums, generateKey, Key, KeyID, PacketList, PrivateKey, PublicKey, readKey, readKeys, readMessage, readToEnd, revokeKey, SecretKeyPacket, SecretSubkeyPacket, SignaturePacket, UserID } from 'openpgp'; import { isFullyDecrypted, isFullyEncrypted } from './pgp'; export type Contact = { diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index e9de6beb6..e1a72b932 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -14,7 +14,7 @@ import { FcAttLinkData } from './att'; import { MsgBlockParser } from './msg-block-parser'; import { PgpArmor } from './pgp-armor'; import { Store } from '../platform/store'; -import { CleartextMessage, createCleartextMessage, createMessage, Data, encrypt, enums, Key, KeyID, Message, PrivateKey, readKeys, readMessage, readToEnd, sign, VerificationResult } from '../lib/openpgp'; +import { CleartextMessage, createCleartextMessage, createMessage, Data, encrypt, enums, Key, KeyID, Message, PrivateKey, readKeys, readMessage, readToEnd, sign, VerificationResult } from 'openpgp'; import { isFullyDecrypted, isFullyEncrypted, isPacketDecrypted } from './pgp'; export namespace PgpMsgMethod { @@ -449,7 +449,7 @@ export class PgpMsg { private static matchingKeyids = (key: Key, encryptedFor: KeyID[]): KeyID[] => { const msgKeyidBytesArr = (encryptedFor || []).map(kid => kid.bytes); - return key.getKeyIDs().filter(kid => msgKeyidBytesArr.includes(kid.bytes)); + return key.getKeyIDs().filter(kid => msgKeyidBytesArr.includes((kid as KeyID).bytes)); } private static decryptKeyFor = async (prv: Key, passphrase: string, matchingKeyIds: KeyID[]): Promise => { diff --git a/Core/source/core/pgp-password.ts b/Core/source/core/pgp-password.ts index 1b17a86a7..57f2572f3 100644 --- a/Core/source/core/pgp-password.ts +++ b/Core/source/core/pgp-password.ts @@ -3,7 +3,7 @@ 'use strict'; import { base64encode, secureRandomBytes } from '../platform/util'; -import { util } from '../lib/openpgp'; +import { util } from 'openpgp'; interface PwdStrengthResult { word: { diff --git a/Core/source/core/pgp.ts b/Core/source/core/pgp.ts index 166b925fb..6f8e59568 100644 --- a/Core/source/core/pgp.ts +++ b/Core/source/core/pgp.ts @@ -5,7 +5,7 @@ import { PgpKey, PrvPacket } from './pgp-key'; import { VERSION } from './const'; -import { Key, KeyID, config } from '../lib/openpgp'; +import { Key, KeyID, config } from 'openpgp'; config.versionString = `FlowCrypt ${VERSION} Gmail Encryption`; config.commentString = 'Seamlessly send and receive encrypted email'; diff --git a/Core/source/gen-compat-assets.ts b/Core/source/gen-compat-assets.ts index cbe3fd21f..f0562cd53 100644 --- a/Core/source/gen-compat-assets.ts +++ b/Core/source/gen-compat-assets.ts @@ -11,7 +11,7 @@ import * as ava from 'ava'; import { AvaContext, getKeypairs, writeFile } from './test/test-utils'; import { PgpMsg } from './core/pgp-msg'; import { Xss } from './platform/xss'; -import { decryptKey, PrivateKey, readKey } from './lib/openpgp'; +import { decryptKey, PrivateKey, readKey } from 'openpgp'; const text = Buffer.from('some\n汉\ntxt'); const textSpecialChars = Buffer.from('> special & other\n> second line'); diff --git a/Core/source/mobile-interface/endpoints.ts b/Core/source/mobile-interface/endpoints.ts index ac415bf4b..75fec0ca5 100644 --- a/Core/source/mobile-interface/endpoints.ts +++ b/Core/source/mobile-interface/endpoints.ts @@ -18,7 +18,7 @@ import { VERSION } from '../core/const'; import { ValidateInput, readArmoredKeyOrThrow, NodeRequest } from './validate-input'; import { Xss } from '../platform/xss'; import { gmailBackupSearchQuery } from '../core/const'; -import { encryptKey, Key, PrivateKey, readKeys } from '../lib/openpgp'; +import { encryptKey, Key, PrivateKey, readKeys } from 'openpgp'; export class Endpoints { diff --git a/Core/source/platform/store.ts b/Core/source/platform/store.ts index a1a388170..e99c839f3 100644 --- a/Core/source/platform/store.ts +++ b/Core/source/platform/store.ts @@ -2,7 +2,7 @@ 'use strict'; -import { Key } from '../lib/openpgp'; +import { Key } from 'openpgp'; import { str_to_hex } from './util'; let KEY_CACHE: { [longidOrArmoredKey: string]: Key } = {}; diff --git a/Core/source/test.ts b/Core/source/test.ts index b50f0baf6..b67c29f65 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -17,7 +17,7 @@ import { allKeypairNames, expectData, expectEmptyJson, expectNoData, getCompatAs import { Xss } from './platform/xss'; import { expect } from 'chai'; import { Endpoints } from './mobile-interface/endpoints'; -import { decryptKey, PrivateKey, readKey } from './lib/openpgp'; +import { decryptKey, PrivateKey, readKey } from 'openpgp'; import { isFullyDecrypted, isFullyEncrypted } from './core/pgp'; const text = 'some\n汉\ntxt'; diff --git a/Core/tsconfig.json b/Core/tsconfig.json index da90f4b0b..42a9dc373 100644 --- a/Core/tsconfig.json +++ b/Core/tsconfig.json @@ -19,6 +19,9 @@ "checkJs": false, "outDir": "./build/ts", "baseUrl": "./", + "paths": { + "openpgp": ["source/lib"] + }, "typeRoots": [ "./source/core/types/", "./node_modules/@types/" From ffcffe2a23cac5def449db8b484e730353fe3ef2 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 06:26:50 +0200 Subject: [PATCH 078/179] wip --- Core/source/core/pgp-password.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Core/source/core/pgp-password.ts b/Core/source/core/pgp-password.ts index 57f2572f3..4fea534e5 100644 --- a/Core/source/core/pgp-password.ts +++ b/Core/source/core/pgp-password.ts @@ -19,7 +19,9 @@ interface PwdStrengthResult { export class PgpPwd { - // (10k pc)*(2 core p/pc)*(4k guess p/core) httpshttps://www.abuse.ch/?p=3294://threatpost.com/how-much-does-botnet-cost-022813/77573/ https://www.abuse.ch/?p=3294 + // (10k pc)*(2 core p/pc)*(4k guess p/core) + // https://www.abuse.ch/?p=3294://threatpost.com/how-much-does-botnet-cost-022813/77573/ + // https://www.abuse.ch/?p=3294 private static CRACK_GUESSES_PER_SECOND = 10000 * 2 * 4000; private static CRACK_TIME_WORDS_PWD = [ // the requirements for a one-time password are less strict @@ -57,9 +59,11 @@ export class PgpPwd { public static weakWords = () => { return [ - 'crypt', 'up', 'cryptup', 'flow', 'flowcrypt', 'encryption', 'pgp', 'email', 'set', 'backup', 'passphrase', 'best', 'pass', 'phrases', 'are', 'long', 'and', 'have', 'several', - 'words', 'in', 'them', 'Best pass phrases are long', 'have several words', 'in them', 'bestpassphrasesarelong', 'haveseveralwords', 'inthem', - 'Loss of this pass phrase', 'cannot be recovered', 'Note it down', 'on a paper', 'lossofthispassphrase', 'cannotberecovered', 'noteitdown', 'onapaper', + 'crypt', 'up', 'cryptup', 'flow', 'flowcrypt', 'encryption', 'pgp', 'email', 'set', 'backup', 'passphrase', + 'best', 'pass', 'phrases', 'are', 'long', 'and', 'have', 'several', 'words', 'in', 'them', + 'Best pass phrases are long', 'have several words', 'in them', 'bestpassphrasesarelong', 'haveseveralwords', + 'inthem', 'Loss of this pass phrase', 'cannot be recovered', 'Note it down', 'on a paper', + 'lossofthispassphrase', 'cannotberecovered', 'noteitdown', 'onapaper', 'setpassword', 'set password', 'set pass word', 'setpassphrase', 'set pass phrase', 'set passphrase' ]; } @@ -69,7 +73,8 @@ export class PgpPwd { .toUpperCase().replace(/[^A-Z0-9]|0|O|1/g, '').replace(/(.{4})/g, '$1-').substr(0, 19); } - private static readableCrackTime = (totalSeconds: number) => { // http://stackoverflow.com/questions/8211744/convert-time-interval-given-in-seconds-into-more-human-readable-form + private static readableCrackTime = (totalSeconds: number) => { + // See http://stackoverflow.com/questions/8211744/convert-time-interval-given-in-seconds-into-more-human-readable-form const numberWordEnding = (n: number) => (n > 1) ? 's' : ''; totalSeconds = Math.round(totalSeconds); const millennia = Math.round(totalSeconds / (86400 * 30 * 12 * 100 * 1000)); From 938ab4439f30da68131b164a3055cd4ed17b28b2 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 06:39:16 +0200 Subject: [PATCH 079/179] wip --- Core/source/core/types/openpgp/{openpgp.d.ts => index.d.ts} | 0 Core/tsconfig.json | 1 + 2 files changed, 1 insertion(+) rename Core/source/core/types/openpgp/{openpgp.d.ts => index.d.ts} (100%) diff --git a/Core/source/core/types/openpgp/openpgp.d.ts b/Core/source/core/types/openpgp/index.d.ts similarity index 100% rename from Core/source/core/types/openpgp/openpgp.d.ts rename to Core/source/core/types/openpgp/index.d.ts diff --git a/Core/tsconfig.json b/Core/tsconfig.json index 42a9dc373..84364385f 100644 --- a/Core/tsconfig.json +++ b/Core/tsconfig.json @@ -22,6 +22,7 @@ "paths": { "openpgp": ["source/lib"] }, + "traceResolution": true, "typeRoots": [ "./source/core/types/", "./node_modules/@types/" From 7e99ada9e0381c23a8a3579cb7c8db590240279c Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 06:44:41 +0200 Subject: [PATCH 080/179] wip --- Core/source/core/types/{openpgp/index.d.ts => openpgp.d.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Core/source/core/types/{openpgp/index.d.ts => openpgp.d.ts} (100%) diff --git a/Core/source/core/types/openpgp/index.d.ts b/Core/source/core/types/openpgp.d.ts similarity index 100% rename from Core/source/core/types/openpgp/index.d.ts rename to Core/source/core/types/openpgp.d.ts From 6fabe55c648835f8d47e289d1c5bf4b8e17c0589 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 06:49:28 +0200 Subject: [PATCH 081/179] wip --- Core/tooling/build.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Core/tooling/build.sh b/Core/tooling/build.sh index 8eb243ad1..eb05dfe37 100755 --- a/Core/tooling/build.sh +++ b/Core/tooling/build.sh @@ -2,15 +2,19 @@ set -euxo pipefail +# fix openpgp node_modules +cp -f source/types/openpgp.d.ts node_modules/openpgp +cp -f source/lib/openpgp.js node_modules/dist/node + # clean up rm -rf build/ts build/bundles build/final/* mkdir -p build/final # build our source with typescript -./node_modules/.bin/tsc --project tsconfig.json +node_modules/.bin/tsc --project tsconfig.json # build raw/ with webpack -./node_modules/.bin/webpack --config webpack.bare.config.js +node_modules/.bin/webpack --config webpack.bare.config.js # move modified raw/ to bundles/ node tooling/fix-bundles.js From 71bcee246c658f99e2e100835689a8ebd1e0a5ce Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 06:50:30 +0200 Subject: [PATCH 082/179] wip --- Core/tooling/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/tooling/build.sh b/Core/tooling/build.sh index eb05dfe37..ae6bdc410 100755 --- a/Core/tooling/build.sh +++ b/Core/tooling/build.sh @@ -3,7 +3,7 @@ set -euxo pipefail # fix openpgp node_modules -cp -f source/types/openpgp.d.ts node_modules/openpgp +cp -f source/core/types/openpgp.d.ts node_modules/openpgp cp -f source/lib/openpgp.js node_modules/dist/node # clean up From 0c68330ceb59cf9cf07f283b3d2b8cdc70251cc1 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 06:51:12 +0200 Subject: [PATCH 083/179] wip --- Core/tooling/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/tooling/build.sh b/Core/tooling/build.sh index ae6bdc410..d98d41cf4 100755 --- a/Core/tooling/build.sh +++ b/Core/tooling/build.sh @@ -4,7 +4,7 @@ set -euxo pipefail # fix openpgp node_modules cp -f source/core/types/openpgp.d.ts node_modules/openpgp -cp -f source/lib/openpgp.js node_modules/dist/node +cp -f source/lib/openpgp.js node_modules/openpgp/dist/node # clean up rm -rf build/ts build/bundles build/final/* From 9f39607c79281f17e9a393683b74d10dca7a79a4 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 06:51:58 +0200 Subject: [PATCH 084/179] wip --- Core/tooling/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/tooling/build.sh b/Core/tooling/build.sh index d98d41cf4..4a3081238 100755 --- a/Core/tooling/build.sh +++ b/Core/tooling/build.sh @@ -2,7 +2,7 @@ set -euxo pipefail -# fix openpgp node_modules +# fix openpgp in node_modules cp -f source/core/types/openpgp.d.ts node_modules/openpgp cp -f source/lib/openpgp.js node_modules/openpgp/dist/node From 3a07a62fa99881443b3219852c57b6cf1d54f379 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 07:05:08 +0200 Subject: [PATCH 085/179] wip --- Core/source/lib/{ => openpgp/node}/openpgp.js | 0 Core/source/lib/openpgp/openpgp.js | 43537 ++++++++++++++++ Core/tooling/build.sh | 3 +- 3 files changed, 43539 insertions(+), 1 deletion(-) rename Core/source/lib/{ => openpgp/node}/openpgp.js (100%) create mode 100644 Core/source/lib/openpgp/openpgp.js diff --git a/Core/source/lib/openpgp.js b/Core/source/lib/openpgp/node/openpgp.js similarity index 100% rename from Core/source/lib/openpgp.js rename to Core/source/lib/openpgp/node/openpgp.js diff --git a/Core/source/lib/openpgp/openpgp.js b/Core/source/lib/openpgp/openpgp.js new file mode 100644 index 000000000..5bf2c1131 --- /dev/null +++ b/Core/source/lib/openpgp/openpgp.js @@ -0,0 +1,43537 @@ +/*! OpenPGP.js v5.1.0 - 2022-01-24 - this is LGPL licensed code, see LICENSE/our website https://openpgpjs.org/ for more information. */ +var openpgp = (function (exports) { + 'use strict'; + + const globalThis = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + + const doneWritingPromise = Symbol('doneWritingPromise'); + const doneWritingResolve = Symbol('doneWritingResolve'); + const doneWritingReject = Symbol('doneWritingReject'); + + const readingIndex = Symbol('readingIndex'); + + class ArrayStream extends Array { + constructor() { + super(); + this[doneWritingPromise] = new Promise((resolve, reject) => { + this[doneWritingResolve] = resolve; + this[doneWritingReject] = reject; + }); + this[doneWritingPromise].catch(() => {}); + } + } + + ArrayStream.prototype.getReader = function() { + if (this[readingIndex] === undefined) { + this[readingIndex] = 0; + } + return { + read: async () => { + await this[doneWritingPromise]; + if (this[readingIndex] === this.length) { + return { value: undefined, done: true }; + } + return { value: this[this[readingIndex]++], done: false }; + } + }; + }; + + ArrayStream.prototype.readToEnd = async function(join) { + await this[doneWritingPromise]; + const result = join(this.slice(this[readingIndex])); + this.length = 0; + return result; + }; + + ArrayStream.prototype.clone = function() { + const clone = new ArrayStream(); + clone[doneWritingPromise] = this[doneWritingPromise].then(() => { + clone.push(...this); + }); + return clone; + }; + + /** + * Check whether data is an ArrayStream + * @param {Any} input data to check + * @returns {boolean} + */ + function isArrayStream(input) { + return input && input.getReader && Array.isArray(input); + } + + /** + * A wrapper class over the native WritableStreamDefaultWriter. + * It also lets you "write data to" array streams instead of streams. + * @class + */ + function Writer(input) { + if (!isArrayStream(input)) { + const writer = input.getWriter(); + const releaseLock = writer.releaseLock; + writer.releaseLock = () => { + writer.closed.catch(function() {}); + releaseLock.call(writer); + }; + return writer; + } + this.stream = input; + } + + /** + * Write a chunk of data. + * @returns {Promise} + * @async + */ + Writer.prototype.write = async function(chunk) { + this.stream.push(chunk); + }; + + /** + * Close the stream. + * @returns {Promise} + * @async + */ + Writer.prototype.close = async function() { + this.stream[doneWritingResolve](); + }; + + /** + * Error the stream. + * @returns {Promise} + * @async + */ + Writer.prototype.abort = async function(reason) { + this.stream[doneWritingReject](reason); + return reason; + }; + + /** + * Release the writer's lock. + * @returns {undefined} + * @async + */ + Writer.prototype.releaseLock = function() {}; + + const isNode = typeof globalThis.process === 'object' && + typeof globalThis.process.versions === 'object'; + + const NodeReadableStream = isNode && void('stream').Readable; + + /** + * Check whether data is a Stream, and if so of which type + * @param {Any} input data to check + * @returns {'web'|'ponyfill'|'node'|'array'|'web-like'|false} + */ + function isStream(input) { + if (isArrayStream(input)) { + return 'array'; + } + if (globalThis.ReadableStream && globalThis.ReadableStream.prototype.isPrototypeOf(input)) { + return 'web'; + } + if (ReadableStream && ReadableStream.prototype.isPrototypeOf(input)) { + return 'ponyfill'; + } + if (NodeReadableStream && NodeReadableStream.prototype.isPrototypeOf(input)) { + return 'node'; + } + if (input && input.getReader) { + return 'web-like'; + } + return false; + } + + /** + * Check whether data is a Uint8Array + * @param {Any} input data to check + * @returns {Boolean} + */ + function isUint8Array(input) { + return Uint8Array.prototype.isPrototypeOf(input); + } + + /** + * Concat Uint8Arrays + * @param {Array} Array of Uint8Arrays to concatenate + * @returns {Uint8array} Concatenated array + */ + function concatUint8Array(arrays) { + if (arrays.length === 1) return arrays[0]; + + let totalLength = 0; + for (let i = 0; i < arrays.length; i++) { + if (!isUint8Array(arrays[i])) { + throw new Error('concatUint8Array: Data must be in the form of a Uint8Array'); + } + + totalLength += arrays[i].length; + } + + const result = new Uint8Array(totalLength); + let pos = 0; + arrays.forEach(function (element) { + result.set(element, pos); + pos += element.length; + }); + + return result; + } + + const NodeBuffer = isNode && void('buffer').Buffer; + const NodeReadableStream$1 = isNode && void('stream').Readable; + + /** + * Web / node stream conversion functions + * From https://github.com/gwicke/node-web-streams + */ + + let nodeToWeb; + let webToNode; + + if (NodeReadableStream$1) { + + /** + * Convert a Node Readable Stream to a Web ReadableStream + * @param {Readable} nodeStream + * @returns {ReadableStream} + */ + nodeToWeb = function(nodeStream) { + let canceled = false; + return new ReadableStream({ + start(controller) { + nodeStream.pause(); + nodeStream.on('data', chunk => { + if (canceled) { + return; + } + if (NodeBuffer.isBuffer(chunk)) { + chunk = new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength); + } + controller.enqueue(chunk); + nodeStream.pause(); + }); + nodeStream.on('end', () => { + if (canceled) { + return; + } + controller.close(); + }); + nodeStream.on('error', e => controller.error(e)); + }, + pull() { + nodeStream.resume(); + }, + cancel(reason) { + canceled = true; + nodeStream.destroy(reason); + } + }); + }; + + + class NodeReadable extends NodeReadableStream$1 { + constructor(webStream, options) { + super(options); + this._reader = getReader(webStream); + } + + async _read(size) { + try { + while (true) { + const { done, value } = await this._reader.read(); + if (done) { + this.push(null); + break; + } + if (!this.push(value) || this._cancelling) { + this._reading = false; + break; + } + } + } catch(e) { + this.emit('error', e); + } + } + + _destroy(reason) { + this._reader.cancel(reason); + } + } + + /** + * Convert a Web ReadableStream to a Node Readable Stream + * @param {ReadableStream} webStream + * @param {Object} options + * @returns {Readable} + */ + webToNode = function(webStream, options) { + return new NodeReadable(webStream, options); + }; + + } + + const doneReadingSet = new WeakSet(); + const externalBuffer = Symbol('externalBuffer'); + + /** + * A wrapper class over the native ReadableStreamDefaultReader. + * This additionally implements pushing back data on the stream, which + * lets us implement peeking and a host of convenience functions. + * It also lets you read data other than streams, such as a Uint8Array. + * @class + */ + function Reader(input) { + this.stream = input; + if (input[externalBuffer]) { + this[externalBuffer] = input[externalBuffer].slice(); + } + if (isArrayStream(input)) { + const reader = input.getReader(); + this._read = reader.read.bind(reader); + this._releaseLock = () => {}; + this._cancel = () => {}; + return; + } + let streamType = isStream(input); + if (streamType === 'node') { + input = nodeToWeb(input); + } + if (streamType) { + const reader = input.getReader(); + this._read = reader.read.bind(reader); + this._releaseLock = () => { + reader.closed.catch(function() {}); + reader.releaseLock(); + }; + this._cancel = reader.cancel.bind(reader); + return; + } + let doneReading = false; + this._read = async () => { + if (doneReading || doneReadingSet.has(input)) { + return { value: undefined, done: true }; + } + doneReading = true; + return { value: input, done: false }; + }; + this._releaseLock = () => { + if (doneReading) { + try { + doneReadingSet.add(input); + } catch(e) {} + } + }; + } + + /** + * Read a chunk of data. + * @returns {Promise} Either { done: false, value: Uint8Array | String } or { done: true, value: undefined } + * @async + */ + Reader.prototype.read = async function() { + if (this[externalBuffer] && this[externalBuffer].length) { + const value = this[externalBuffer].shift(); + return { done: false, value }; + } + return this._read(); + }; + + /** + * Allow others to read the stream. + */ + Reader.prototype.releaseLock = function() { + if (this[externalBuffer]) { + this.stream[externalBuffer] = this[externalBuffer]; + } + this._releaseLock(); + }; + + /** + * Cancel the stream. + */ + Reader.prototype.cancel = function(reason) { + return this._cancel(reason); + }; + + /** + * Read up to and including the first \n character. + * @returns {Promise} + * @async + */ + Reader.prototype.readLine = async function() { + let buffer = []; + let returnVal; + while (!returnVal) { + let { done, value } = await this.read(); + value += ''; + if (done) { + if (buffer.length) return concat(buffer); + return; + } + const lineEndIndex = value.indexOf('\n') + 1; + if (lineEndIndex) { + returnVal = concat(buffer.concat(value.substr(0, lineEndIndex))); + buffer = []; + } + if (lineEndIndex !== value.length) { + buffer.push(value.substr(lineEndIndex)); + } + } + this.unshift(...buffer); + return returnVal; + }; + + /** + * Read a single byte/character. + * @returns {Promise} + * @async + */ + Reader.prototype.readByte = async function() { + const { done, value } = await this.read(); + if (done) return; + const byte = value[0]; + this.unshift(slice(value, 1)); + return byte; + }; + + /** + * Read a specific amount of bytes/characters, unless the stream ends before that amount. + * @returns {Promise} + * @async + */ + Reader.prototype.readBytes = async function(length) { + const buffer = []; + let bufferLength = 0; + while (true) { + const { done, value } = await this.read(); + if (done) { + if (buffer.length) return concat(buffer); + return; + } + buffer.push(value); + bufferLength += value.length; + if (bufferLength >= length) { + const bufferConcat = concat(buffer); + this.unshift(slice(bufferConcat, length)); + return slice(bufferConcat, 0, length); + } + } + }; + + /** + * Peek (look ahead) a specific amount of bytes/characters, unless the stream ends before that amount. + * @returns {Promise} + * @async + */ + Reader.prototype.peekBytes = async function(length) { + const bytes = await this.readBytes(length); + this.unshift(bytes); + return bytes; + }; + + /** + * Push data to the front of the stream. + * Data must have been read in the last call to read*. + * @param {...(Uint8Array|String|Undefined)} values + */ + Reader.prototype.unshift = function(...values) { + if (!this[externalBuffer]) { + this[externalBuffer] = []; + } + if ( + values.length === 1 && isUint8Array(values[0]) && + this[externalBuffer].length && values[0].length && + this[externalBuffer][0].byteOffset >= values[0].length + ) { + this[externalBuffer][0] = new Uint8Array( + this[externalBuffer][0].buffer, + this[externalBuffer][0].byteOffset - values[0].length, + this[externalBuffer][0].byteLength + values[0].length + ); + return; + } + this[externalBuffer].unshift(...values.filter(value => value && value.length)); + }; + + /** + * Read the stream to the end and return its contents, concatenated by the join function (defaults to streams.concat). + * @param {Function} join + * @returns {Promise} the return value of join() + * @async + */ + Reader.prototype.readToEnd = async function(join=concat) { + const result = []; + while (true) { + const { done, value } = await this.read(); + if (done) break; + result.push(value); + } + return join(result); + }; + + let { ReadableStream, WritableStream, TransformStream } = globalThis; + + let toPonyfillReadable, toNativeReadable; + + async function loadStreamsPonyfill() { + if (TransformStream) { + return; + } + + const [ponyfill, adapter] = await Promise.all([ + Promise.resolve().then(function () { return ponyfill_es6; }), + Promise.resolve().then(function () { return webStreamsAdapter; }) + ]); + + ({ ReadableStream, WritableStream, TransformStream } = ponyfill); + + const { createReadableStreamWrapper } = adapter; + + if (globalThis.ReadableStream && ReadableStream !== globalThis.ReadableStream) { + toPonyfillReadable = createReadableStreamWrapper(ReadableStream); + toNativeReadable = createReadableStreamWrapper(globalThis.ReadableStream); + } + } + + const NodeBuffer$1 = isNode && void('buffer').Buffer; + + /** + * Convert data to Stream + * @param {ReadableStream|Uint8array|String} input data to convert + * @returns {ReadableStream} Converted data + */ + function toStream(input) { + let streamType = isStream(input); + if (streamType === 'node') { + return nodeToWeb(input); + } + if (streamType === 'web' && toPonyfillReadable) { + return toPonyfillReadable(input); + } + if (streamType) { + return input; + } + return new ReadableStream({ + start(controller) { + controller.enqueue(input); + controller.close(); + } + }); + } + + /** + * Convert data to ArrayStream + * @param {Object} input data to convert + * @returns {ArrayStream} Converted data + */ + function toArrayStream(input) { + if (isStream(input)) { + return input; + } + const stream = new ArrayStream(); + (async () => { + const writer = getWriter(stream); + await writer.write(input); + await writer.close(); + })(); + return stream; + } + + /** + * Concat a list of Uint8Arrays, Strings or Streams + * The caller should not mix Uint8Arrays with Strings, but may mix Streams with non-Streams. + * @param {Array} Array of Uint8Arrays/Strings/Streams to concatenate + * @returns {Uint8array|String|ReadableStream} Concatenated array + */ + function concat(list) { + if (list.some(stream => isStream(stream) && !isArrayStream(stream))) { + return concatStream(list); + } + if (list.some(stream => isArrayStream(stream))) { + return concatArrayStream(list); + } + if (typeof list[0] === 'string') { + return list.join(''); + } + if (NodeBuffer$1 && NodeBuffer$1.isBuffer(list[0])) { + return NodeBuffer$1.concat(list); + } + return concatUint8Array(list); + } + + /** + * Concat a list of Streams + * @param {Array} list Array of Uint8Arrays/Strings/Streams to concatenate + * @returns {ReadableStream} Concatenated list + */ + function concatStream(list) { + list = list.map(toStream); + const transform = transformWithCancel(async function(reason) { + await Promise.all(transforms.map(stream => cancel(stream, reason))); + }); + let prev = Promise.resolve(); + const transforms = list.map((stream, i) => transformPair(stream, (readable, writable) => { + prev = prev.then(() => pipe(readable, transform.writable, { + preventClose: i !== list.length - 1 + })); + return prev; + })); + return transform.readable; + } + + /** + * Concat a list of ArrayStreams + * @param {Array} list Array of Uint8Arrays/Strings/ArrayStreams to concatenate + * @returns {ArrayStream} Concatenated streams + */ + function concatArrayStream(list) { + const result = new ArrayStream(); + let prev = Promise.resolve(); + list.forEach((stream, i) => { + prev = prev.then(() => pipe(stream, result, { + preventClose: i !== list.length - 1 + })); + return prev; + }); + return result; + } + + /** + * Get a Reader + * @param {ReadableStream|Uint8array|String} input + * @returns {Reader} + */ + function getReader(input) { + return new Reader(input); + } + + /** + * Get a Writer + * @param {WritableStream} input + * @returns {Writer} + */ + function getWriter(input) { + return new Writer(input); + } + + /** + * Pipe a readable stream to a writable stream. Don't throw on input stream errors, but forward them to the output stream. + * @param {ReadableStream|Uint8array|String} input + * @param {WritableStream} target + * @param {Object} (optional) options + * @returns {Promise} Promise indicating when piping has finished (input stream closed or errored) + * @async + */ + async function pipe(input, target, { + preventClose = false, + preventAbort = false, + preventCancel = false + } = {}) { + if (isStream(input) && !isArrayStream(input)) { + input = toStream(input); + try { + if (input[externalBuffer]) { + const writer = getWriter(target); + for (let i = 0; i < input[externalBuffer].length; i++) { + await writer.ready; + await writer.write(input[externalBuffer][i]); + } + writer.releaseLock(); + } + await input.pipeTo(target, { + preventClose, + preventAbort, + preventCancel + }); + } catch(e) {} + return; + } + input = toArrayStream(input); + const reader = getReader(input); + const writer = getWriter(target); + try { + while (true) { + await writer.ready; + const { done, value } = await reader.read(); + if (done) { + if (!preventClose) await writer.close(); + break; + } + await writer.write(value); + } + } catch (e) { + if (!preventAbort) await writer.abort(e); + } finally { + reader.releaseLock(); + writer.releaseLock(); + } + } + + /** + * Pipe a readable stream through a transform stream. + * @param {ReadableStream|Uint8array|String} input + * @param {Object} (optional) options + * @returns {ReadableStream} transformed stream + */ + function transformRaw(input, options) { + const transformStream = new TransformStream(options); + pipe(input, transformStream.writable); + return transformStream.readable; + } + + /** + * Create a cancelable TransformStream. + * @param {Function} cancel + * @returns {TransformStream} + */ + function transformWithCancel(cancel) { + let pulled = false; + let backpressureChangePromiseResolve; + let outputController; + return { + readable: new ReadableStream({ + start(controller) { + outputController = controller; + }, + pull() { + if (backpressureChangePromiseResolve) { + backpressureChangePromiseResolve(); + } else { + pulled = true; + } + }, + cancel + }, {highWaterMark: 0}), + writable: new WritableStream({ + write: async function(chunk) { + outputController.enqueue(chunk); + if (!pulled) { + await new Promise(resolve => { + backpressureChangePromiseResolve = resolve; + }); + backpressureChangePromiseResolve = null; + } else { + pulled = false; + } + }, + close: outputController.close.bind(outputController), + abort: outputController.error.bind(outputController) + }) + }; + } + + /** + * Transform a stream using helper functions which are called on each chunk, and on stream close, respectively. + * @param {ReadableStream|Uint8array|String} input + * @param {Function} process + * @param {Function} finish + * @returns {ReadableStream|Uint8array|String} + */ + function transform(input, process = () => undefined, finish = () => undefined) { + if (isArrayStream(input)) { + const output = new ArrayStream(); + (async () => { + const data = await readToEnd(input); + const result1 = process(data); + const result2 = finish(); + let result; + if (result1 !== undefined && result2 !== undefined) result = concat([result1, result2]); + else result = result1 !== undefined ? result1 : result2; + const writer = getWriter(output); + await writer.write(result); + await writer.close(); + })(); + return output; + } + if (isStream(input)) { + return transformRaw(input, { + async transform(value, controller) { + try { + const result = await process(value); + if (result !== undefined) controller.enqueue(result); + } catch(e) { + controller.error(e); + } + }, + async flush(controller) { + try { + const result = await finish(); + if (result !== undefined) controller.enqueue(result); + } catch(e) { + controller.error(e); + } + } + }); + } + const result1 = process(input); + const result2 = finish(); + if (result1 !== undefined && result2 !== undefined) return concat([result1, result2]); + return result1 !== undefined ? result1 : result2; + } + + /** + * Transform a stream using a helper function which is passed a readable and a writable stream. + * This function also maintains the possibility to cancel the input stream, + * and does so on cancelation of the output stream, despite cancelation + * normally being impossible when the input stream is being read from. + * @param {ReadableStream|Uint8array|String} input + * @param {Function} fn + * @returns {ReadableStream} + */ + function transformPair(input, fn) { + if (isStream(input) && !isArrayStream(input)) { + let incomingTransformController; + const incoming = new TransformStream({ + start(controller) { + incomingTransformController = controller; + } + }); + + const pipeDonePromise = pipe(input, incoming.writable); + + const outgoing = transformWithCancel(async function() { + incomingTransformController.error(new Error('Readable side was canceled.')); + await pipeDonePromise; + await new Promise(setTimeout); + }); + fn(incoming.readable, outgoing.writable); + return outgoing.readable; + } + input = toArrayStream(input); + const output = new ArrayStream(); + fn(input, output); + return output; + } + + /** + * Parse a stream using a helper function which is passed a Reader. + * The reader additionally has a remainder() method which returns a + * stream pointing to the remainder of input, and is linked to input + * for cancelation. + * @param {ReadableStream|Uint8array|String} input + * @param {Function} fn + * @returns {Any} the return value of fn() + */ + function parse(input, fn) { + let returnValue; + const transformed = transformPair(input, (readable, writable) => { + const reader = getReader(readable); + reader.remainder = () => { + reader.releaseLock(); + pipe(readable, writable); + return transformed; + }; + returnValue = fn(reader); + }); + return returnValue; + } + + /** + * Tee a Stream for reading it twice. The input stream can no longer be read after tee()ing. + * Reading either of the two returned streams will pull from the input stream. + * The input stream will only be canceled if both of the returned streams are canceled. + * @param {ReadableStream|Uint8array|String} input + * @returns {Array} array containing two copies of input + */ + function tee(input) { + if (isArrayStream(input)) { + throw new Error('ArrayStream cannot be tee()d, use clone() instead'); + } + if (isStream(input)) { + const teed = toStream(input).tee(); + teed[0][externalBuffer] = teed[1][externalBuffer] = input[externalBuffer]; + return teed; + } + return [slice(input), slice(input)]; + } + + /** + * Clone a Stream for reading it twice. The input stream can still be read after clone()ing. + * Reading from the clone will pull from the input stream. + * The input stream will only be canceled if both the clone and the input stream are canceled. + * @param {ReadableStream|Uint8array|String} input + * @returns {ReadableStream|Uint8array|String} cloned input + */ + function clone(input) { + if (isArrayStream(input)) { + return input.clone(); + } + if (isStream(input)) { + const teed = tee(input); + overwrite(input, teed[0]); + return teed[1]; + } + return slice(input); + } + + /** + * Clone a Stream for reading it twice. Data will arrive at the same rate as the input stream is being read. + * Reading from the clone will NOT pull from the input stream. Data only arrives when reading the input stream. + * The input stream will NOT be canceled if the clone is canceled, only if the input stream are canceled. + * If the input stream is canceled, the clone will be errored. + * @param {ReadableStream|Uint8array|String} input + * @returns {ReadableStream|Uint8array|String} cloned input + */ + function passiveClone(input) { + if (isArrayStream(input)) { + return clone(input); + } + if (isStream(input)) { + return new ReadableStream({ + start(controller) { + const transformed = transformPair(input, async (readable, writable) => { + const reader = getReader(readable); + const writer = getWriter(writable); + try { + while (true) { + await writer.ready; + const { done, value } = await reader.read(); + if (done) { + try { controller.close(); } catch(e) {} + await writer.close(); + return; + } + try { controller.enqueue(value); } catch(e) {} + await writer.write(value); + } + } catch(e) { + controller.error(e); + await writer.abort(e); + } + }); + overwrite(input, transformed); + } + }); + } + return slice(input); + } + + /** + * Modify a stream object to point to a different stream object. + * This is used internally by clone() and passiveClone() to provide an abstraction over tee(). + * @param {ReadableStream} input + * @param {ReadableStream} clone + */ + function overwrite(input, clone) { + // Overwrite input.getReader, input.locked, etc to point to clone + Object.entries(Object.getOwnPropertyDescriptors(input.constructor.prototype)).forEach(([name, descriptor]) => { + if (name === 'constructor') { + return; + } + if (descriptor.value) { + descriptor.value = descriptor.value.bind(clone); + } else { + descriptor.get = descriptor.get.bind(clone); + } + Object.defineProperty(input, name, descriptor); + }); + } + + /** + * Return a stream pointing to a part of the input stream. + * @param {ReadableStream|Uint8array|String} input + * @returns {ReadableStream|Uint8array|String} clone + */ + function slice(input, begin=0, end=Infinity) { + if (isArrayStream(input)) { + throw new Error('Not implemented'); + } + if (isStream(input)) { + if (begin >= 0 && end >= 0) { + let bytesRead = 0; + return transformRaw(input, { + transform(value, controller) { + if (bytesRead < end) { + if (bytesRead + value.length >= begin) { + controller.enqueue(slice(value, Math.max(begin - bytesRead, 0), end - bytesRead)); + } + bytesRead += value.length; + } else { + controller.terminate(); + } + } + }); + } + if (begin < 0 && (end < 0 || end === Infinity)) { + let lastBytes = []; + return transform(input, value => { + if (value.length >= -begin) lastBytes = [value]; + else lastBytes.push(value); + }, () => slice(concat(lastBytes), begin, end)); + } + if (begin === 0 && end < 0) { + let lastBytes; + return transform(input, value => { + const returnValue = lastBytes ? concat([lastBytes, value]) : value; + if (returnValue.length >= -end) { + lastBytes = slice(returnValue, end); + return slice(returnValue, begin, end); + } else { + lastBytes = returnValue; + } + }); + } + console.warn(`stream.slice(input, ${begin}, ${end}) not implemented efficiently.`); + return fromAsync(async () => slice(await readToEnd(input), begin, end)); + } + if (input[externalBuffer]) { + input = concat(input[externalBuffer].concat([input])); + } + if (isUint8Array(input) && !(NodeBuffer$1 && NodeBuffer$1.isBuffer(input))) { + if (end === Infinity) end = input.length; + return input.subarray(begin, end); + } + return input.slice(begin, end); + } + + /** + * Read a stream to the end and return its contents, concatenated by the join function (defaults to concat). + * @param {ReadableStream|Uint8array|String} input + * @param {Function} join + * @returns {Promise} the return value of join() + * @async + */ + async function readToEnd(input, join=concat) { + if (isArrayStream(input)) { + return input.readToEnd(join); + } + if (isStream(input)) { + return getReader(input).readToEnd(join); + } + return input; + } + + /** + * Cancel a stream. + * @param {ReadableStream|Uint8array|String} input + * @param {Any} reason + * @returns {Promise} indicates when the stream has been canceled + * @async + */ + async function cancel(input, reason) { + if (isStream(input)) { + if (input.cancel) { + return input.cancel(reason); + } + if (input.destroy) { + input.destroy(reason); + await new Promise(setTimeout); + return reason; + } + } + } + + /** + * Convert an async function to an ArrayStream. When the function returns, its return value is written to the stream. + * @param {Function} fn + * @returns {ArrayStream} + */ + function fromAsync(fn) { + const arrayStream = new ArrayStream(); + (async () => { + const writer = getWriter(arrayStream); + try { + await writer.write(await fn()); + await writer.close(); + } catch (e) { + await writer.abort(e); + } + })(); + return arrayStream; + } + + /* eslint-disable new-cap */ + + /** + * @fileoverview + * BigInteger implementation of basic operations + * that wraps the native BigInt library. + * Operations are not constant time, + * but we try and limit timing leakage where we can + * @module biginteger/native + * @private + */ + + /** + * @private + */ + class BigInteger { + /** + * Get a BigInteger (input must be big endian for strings and arrays) + * @param {Number|String|Uint8Array} n - Value to convert + * @throws {Error} on null or undefined input + */ + constructor(n) { + if (n === undefined) { + throw new Error('Invalid BigInteger input'); + } + + if (n instanceof Uint8Array) { + const bytes = n; + const hex = new Array(bytes.length); + for (let i = 0; i < bytes.length; i++) { + const hexByte = bytes[i].toString(16); + hex[i] = (bytes[i] <= 0xF) ? ('0' + hexByte) : hexByte; + } + this.value = BigInt('0x0' + hex.join('')); + } else { + this.value = BigInt(n); + } + } + + clone() { + return new BigInteger(this.value); + } + + /** + * BigInteger increment in place + */ + iinc() { + this.value++; + return this; + } + + /** + * BigInteger increment + * @returns {BigInteger} this + 1. + */ + inc() { + return this.clone().iinc(); + } + + /** + * BigInteger decrement in place + */ + idec() { + this.value--; + return this; + } + + /** + * BigInteger decrement + * @returns {BigInteger} this - 1. + */ + dec() { + return this.clone().idec(); + } + + /** + * BigInteger addition in place + * @param {BigInteger} x - Value to add + */ + iadd(x) { + this.value += x.value; + return this; + } + + /** + * BigInteger addition + * @param {BigInteger} x - Value to add + * @returns {BigInteger} this + x. + */ + add(x) { + return this.clone().iadd(x); + } + + /** + * BigInteger subtraction in place + * @param {BigInteger} x - Value to subtract + */ + isub(x) { + this.value -= x.value; + return this; + } + + /** + * BigInteger subtraction + * @param {BigInteger} x - Value to subtract + * @returns {BigInteger} this - x. + */ + sub(x) { + return this.clone().isub(x); + } + + /** + * BigInteger multiplication in place + * @param {BigInteger} x - Value to multiply + */ + imul(x) { + this.value *= x.value; + return this; + } + + /** + * BigInteger multiplication + * @param {BigInteger} x - Value to multiply + * @returns {BigInteger} this * x. + */ + mul(x) { + return this.clone().imul(x); + } + + /** + * Compute value modulo m, in place + * @param {BigInteger} m - Modulo + */ + imod(m) { + this.value %= m.value; + if (this.isNegative()) { + this.iadd(m); + } + return this; + } + + /** + * Compute value modulo m + * @param {BigInteger} m - Modulo + * @returns {BigInteger} this mod m. + */ + mod(m) { + return this.clone().imod(m); + } + + /** + * Compute modular exponentiation using square and multiply + * @param {BigInteger} e - Exponent + * @param {BigInteger} n - Modulo + * @returns {BigInteger} this ** e mod n. + */ + modExp(e, n) { + if (n.isZero()) throw Error('Modulo cannot be zero'); + if (n.isOne()) return new BigInteger(0); + if (e.isNegative()) throw Error('Unsopported negative exponent'); + + let exp = e.value; + let x = this.value; + + x %= n.value; + let r = BigInt(1); + while (exp > BigInt(0)) { + const lsb = exp & BigInt(1); + exp >>= BigInt(1); // e / 2 + // Always compute multiplication step, to reduce timing leakage + const rx = (r * x) % n.value; + // Update r only if lsb is 1 (odd exponent) + r = lsb ? rx : r; + x = (x * x) % n.value; // Square + } + return new BigInteger(r); + } + + + /** + * Compute the inverse of this value modulo n + * Note: this and and n must be relatively prime + * @param {BigInteger} n - Modulo + * @returns {BigInteger} x such that this*x = 1 mod n + * @throws {Error} if the inverse does not exist + */ + modInv(n) { + const { gcd, x } = this._egcd(n); + if (!gcd.isOne()) { + throw new Error('Inverse does not exist'); + } + return x.add(n).mod(n); + } + + /** + * Extended Eucleadian algorithm (http://anh.cs.luc.edu/331/notes/xgcd.pdf) + * Given a = this and b, compute (x, y) such that ax + by = gdc(a, b) + * @param {BigInteger} b - Second operand + * @returns {{ gcd, x, y: BigInteger }} + */ + _egcd(b) { + let x = BigInt(0); + let y = BigInt(1); + let xPrev = BigInt(1); + let yPrev = BigInt(0); + + let a = this.value; + b = b.value; + + while (b !== BigInt(0)) { + const q = a / b; + let tmp = x; + x = xPrev - q * x; + xPrev = tmp; + + tmp = y; + y = yPrev - q * y; + yPrev = tmp; + + tmp = b; + b = a % b; + a = tmp; + } + + return { + x: new BigInteger(xPrev), + y: new BigInteger(yPrev), + gcd: new BigInteger(a) + }; + } + + /** + * Compute greatest common divisor between this and n + * @param {BigInteger} b - Operand + * @returns {BigInteger} gcd + */ + gcd(b) { + let a = this.value; + b = b.value; + while (b !== BigInt(0)) { + const tmp = b; + b = a % b; + a = tmp; + } + return new BigInteger(a); + } + + /** + * Shift this to the left by x, in place + * @param {BigInteger} x - Shift value + */ + ileftShift(x) { + this.value <<= x.value; + return this; + } + + /** + * Shift this to the left by x + * @param {BigInteger} x - Shift value + * @returns {BigInteger} this << x. + */ + leftShift(x) { + return this.clone().ileftShift(x); + } + + /** + * Shift this to the right by x, in place + * @param {BigInteger} x - Shift value + */ + irightShift(x) { + this.value >>= x.value; + return this; + } + + /** + * Shift this to the right by x + * @param {BigInteger} x - Shift value + * @returns {BigInteger} this >> x. + */ + rightShift(x) { + return this.clone().irightShift(x); + } + + /** + * Whether this value is equal to x + * @param {BigInteger} x + * @returns {Boolean} + */ + equal(x) { + return this.value === x.value; + } + + /** + * Whether this value is less than x + * @param {BigInteger} x + * @returns {Boolean} + */ + lt(x) { + return this.value < x.value; + } + + /** + * Whether this value is less than or equal to x + * @param {BigInteger} x + * @returns {Boolean} + */ + lte(x) { + return this.value <= x.value; + } + + /** + * Whether this value is greater than x + * @param {BigInteger} x + * @returns {Boolean} + */ + gt(x) { + return this.value > x.value; + } + + /** + * Whether this value is greater than or equal to x + * @param {BigInteger} x + * @returns {Boolean} + */ + gte(x) { + return this.value >= x.value; + } + + isZero() { + return this.value === BigInt(0); + } + + isOne() { + return this.value === BigInt(1); + } + + isNegative() { + return this.value < BigInt(0); + } + + isEven() { + return !(this.value & BigInt(1)); + } + + abs() { + const res = this.clone(); + if (this.isNegative()) { + res.value = -res.value; + } + return res; + } + + /** + * Get this value as a string + * @returns {String} this value. + */ + toString() { + return this.value.toString(); + } + + /** + * Get this value as an exact Number (max 53 bits) + * Fails if this value is too large + * @returns {Number} + */ + toNumber() { + const number = Number(this.value); + if (number > Number.MAX_SAFE_INTEGER) { + // We throw and error to conform with the bn.js implementation + throw new Error('Number can only safely store up to 53 bits'); + } + return number; + } + + /** + * Get value of i-th bit + * @param {Number} i - Bit index + * @returns {Number} Bit value. + */ + getBit(i) { + const bit = (this.value >> BigInt(i)) & BigInt(1); + return (bit === BigInt(0)) ? 0 : 1; + } + + /** + * Compute bit length + * @returns {Number} Bit length. + */ + bitLength() { + const zero = new BigInteger(0); + const one = new BigInteger(1); + const negOne = new BigInteger(-1); + + // -1n >> -1n is -1n + // 1n >> 1n is 0n + const target = this.isNegative() ? negOne : zero; + let bitlen = 1; + const tmp = this.clone(); + while (!tmp.irightShift(one).equal(target)) { + bitlen++; + } + return bitlen; + } + + /** + * Compute byte length + * @returns {Number} Byte length. + */ + byteLength() { + const zero = new BigInteger(0); + const negOne = new BigInteger(-1); + + const target = this.isNegative() ? negOne : zero; + const eight = new BigInteger(8); + let len = 1; + const tmp = this.clone(); + while (!tmp.irightShift(eight).equal(target)) { + len++; + } + return len; + } + + /** + * Get Uint8Array representation of this number + * @param {String} endian - Endianess of output array (defaults to 'be') + * @param {Number} length - Of output array + * @returns {Uint8Array} + */ + toUint8Array(endian = 'be', length) { + // we get and parse the hex string (https://coolaj86.com/articles/convert-js-bigints-to-typedarrays/) + // this is faster than shift+mod iterations + let hex = this.value.toString(16); + if (hex.length % 2 === 1) { + hex = '0' + hex; + } + + const rawLength = hex.length / 2; + const bytes = new Uint8Array(length || rawLength); + // parse hex + const offset = length ? (length - rawLength) : 0; + let i = 0; + while (i < rawLength) { + bytes[i + offset] = parseInt(hex.slice(2 * i, 2 * i + 2), 16); + i++; + } + + if (endian !== 'be') { + bytes.reverse(); + } + + return bytes; + } + } + + async function getBigInteger() { + if (util.detectBigInt()) { + return BigInteger; + } else { + const { default: BigInteger } = await Promise.resolve().then(function () { return bn_interface; }); + return BigInteger; + } + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + const debugMode = (() => { + try { + return process.env.NODE_ENV === 'development'; // eslint-disable-line no-process-env + } catch (e) {} + return false; + })(); + + const util = { + isString: function(data) { + return typeof data === 'string' || String.prototype.isPrototypeOf(data); + }, + + isArray: function(data) { + return Array.prototype.isPrototypeOf(data); + }, + + isUint8Array: isUint8Array, + + isStream: isStream, + + readNumber: function (bytes) { + let n = 0; + for (let i = 0; i < bytes.length; i++) { + n += (256 ** i) * bytes[bytes.length - 1 - i]; + } + return n; + }, + + writeNumber: function (n, bytes) { + const b = new Uint8Array(bytes); + for (let i = 0; i < bytes; i++) { + b[i] = (n >> (8 * (bytes - i - 1))) & 0xFF; + } + + return b; + }, + + readDate: function (bytes) { + const n = util.readNumber(bytes); + const d = new Date(n * 1000); + return d; + }, + + writeDate: function (time) { + const numeric = Math.floor(time.getTime() / 1000); + + return util.writeNumber(numeric, 4); + }, + + normalizeDate: function (time = Date.now()) { + return time === null || time === Infinity ? time : new Date(Math.floor(+time / 1000) * 1000); + }, + + /** + * Read one MPI from bytes in input + * @param {Uint8Array} bytes - Input data to parse + * @returns {Uint8Array} Parsed MPI. + */ + readMPI: function (bytes) { + const bits = (bytes[0] << 8) | bytes[1]; + const bytelen = (bits + 7) >>> 3; + return bytes.subarray(2, 2 + bytelen); + }, + + /** + * Left-pad Uint8Array to length by adding 0x0 bytes + * @param {Uint8Array} bytes - Data to pad + * @param {Number} length - Padded length + * @returns {Uint8Array} Padded bytes. + */ + leftPad(bytes, length) { + const padded = new Uint8Array(length); + const offset = length - bytes.length; + padded.set(bytes, offset); + return padded; + }, + + /** + * Convert a Uint8Array to an MPI-formatted Uint8Array. + * @param {Uint8Array} bin - An array of 8-bit integers to convert + * @returns {Uint8Array} MPI-formatted Uint8Array. + */ + uint8ArrayToMPI: function (bin) { + const bitSize = util.uint8ArrayBitLength(bin); + if (bitSize === 0) { + throw new Error('Zero MPI'); + } + const stripped = bin.subarray(bin.length - Math.ceil(bitSize / 8)); + const prefix = new Uint8Array([(bitSize & 0xFF00) >> 8, bitSize & 0xFF]); + return util.concatUint8Array([prefix, stripped]); + }, + + /** + * Return bit length of the input data + * @param {Uint8Array} bin input data (big endian) + * @returns bit length + */ + uint8ArrayBitLength: function (bin) { + let i; // index of leading non-zero byte + for (i = 0; i < bin.length; i++) if (bin[i] !== 0) break; + if (i === bin.length) { + return 0; + } + const stripped = bin.subarray(i); + return (stripped.length - 1) * 8 + util.nbits(stripped[0]); + }, + + /** + * Convert a hex string to an array of 8-bit integers + * @param {String} hex - A hex string to convert + * @returns {Uint8Array} An array of 8-bit integers. + */ + hexToUint8Array: function (hex) { + const result = new Uint8Array(hex.length >> 1); + for (let k = 0; k < hex.length >> 1; k++) { + result[k] = parseInt(hex.substr(k << 1, 2), 16); + } + return result; + }, + + /** + * Convert an array of 8-bit integers to a hex string + * @param {Uint8Array} bytes - Array of 8-bit integers to convert + * @returns {String} Hexadecimal representation of the array. + */ + uint8ArrayToHex: function (bytes) { + const r = []; + const e = bytes.length; + let c = 0; + let h; + while (c < e) { + h = bytes[c++].toString(16); + while (h.length < 2) { + h = '0' + h; + } + r.push('' + h); + } + return r.join(''); + }, + + /** + * Convert a string to an array of 8-bit integers + * @param {String} str - String to convert + * @returns {Uint8Array} An array of 8-bit integers. + */ + stringToUint8Array: function (str) { + return transform(str, str => { + if (!util.isString(str)) { + throw new Error('stringToUint8Array: Data must be in the form of a string'); + } + + const result = new Uint8Array(str.length); + for (let i = 0; i < str.length; i++) { + result[i] = str.charCodeAt(i); + } + return result; + }); + }, + + /** + * Convert an array of 8-bit integers to a string + * @param {Uint8Array} bytes - An array of 8-bit integers to convert + * @returns {String} String representation of the array. + */ + uint8ArrayToString: function (bytes) { + bytes = new Uint8Array(bytes); + const result = []; + const bs = 1 << 14; + const j = bytes.length; + + for (let i = 0; i < j; i += bs) { + result.push(String.fromCharCode.apply(String, bytes.subarray(i, i + bs < j ? i + bs : j))); + } + return result.join(''); + }, + + /** + * Convert a native javascript string to a Uint8Array of utf8 bytes + * @param {String|ReadableStream} str - The string to convert + * @returns {Uint8Array|ReadableStream} A valid squence of utf8 bytes. + */ + encodeUTF8: function (str) { + const encoder = new TextEncoder('utf-8'); + // eslint-disable-next-line no-inner-declarations + function process(value, lastChunk = false) { + return encoder.encode(value, { stream: !lastChunk }); + } + return transform(str, process, () => process('', true)); + }, + + /** + * Convert a Uint8Array of utf8 bytes to a native javascript string + * @param {Uint8Array|ReadableStream} utf8 - A valid squence of utf8 bytes + * @returns {String|ReadableStream} A native javascript string. + */ + decodeUTF8: function (utf8) { + const decoder = new TextDecoder('utf-8'); + // eslint-disable-next-line no-inner-declarations + function process(value, lastChunk = false) { + return decoder.decode(value, { stream: !lastChunk }); + } + return transform(utf8, process, () => process(new Uint8Array(), true)); + }, + + /** + * Concat a list of Uint8Arrays, Strings or Streams + * The caller must not mix Uint8Arrays with Strings, but may mix Streams with non-Streams. + * @param {Array} Array - Of Uint8Arrays/Strings/Streams to concatenate + * @returns {Uint8Array|String|ReadableStream} Concatenated array. + */ + concat: concat, + + /** + * Concat Uint8Arrays + * @param {Array} Array - Of Uint8Arrays to concatenate + * @returns {Uint8Array} Concatenated array. + */ + concatUint8Array: concatUint8Array, + + /** + * Check Uint8Array equality + * @param {Uint8Array} array1 - First array + * @param {Uint8Array} array2 - Second array + * @returns {Boolean} Equality. + */ + equalsUint8Array: function (array1, array2) { + if (!util.isUint8Array(array1) || !util.isUint8Array(array2)) { + throw new Error('Data must be in the form of a Uint8Array'); + } + + if (array1.length !== array2.length) { + return false; + } + + for (let i = 0; i < array1.length; i++) { + if (array1[i] !== array2[i]) { + return false; + } + } + return true; + }, + + /** + * Calculates a 16bit sum of a Uint8Array by adding each character + * codes modulus 65535 + * @param {Uint8Array} Uint8Array - To create a sum of + * @returns {Uint8Array} 2 bytes containing the sum of all charcodes % 65535. + */ + writeChecksum: function (text) { + let s = 0; + for (let i = 0; i < text.length; i++) { + s = (s + text[i]) & 0xFFFF; + } + return util.writeNumber(s, 2); + }, + + /** + * Helper function to print a debug message. Debug + * messages are only printed if + * @param {String} str - String of the debug message + */ + printDebug: function (str) { + if (debugMode) { + console.log(str); + } + }, + + /** + * Helper function to print a debug error. Debug + * messages are only printed if + * @param {String} str - String of the debug message + */ + printDebugError: function (error) { + if (debugMode) { + console.error(error); + } + }, + + // returns bit length of the integer x + nbits: function (x) { + let r = 1; + let t = x >>> 16; + if (t !== 0) { + x = t; + r += 16; + } + t = x >> 8; + if (t !== 0) { + x = t; + r += 8; + } + t = x >> 4; + if (t !== 0) { + x = t; + r += 4; + } + t = x >> 2; + if (t !== 0) { + x = t; + r += 2; + } + t = x >> 1; + if (t !== 0) { + x = t; + r += 1; + } + return r; + }, + + /** + * If S[1] == 0, then double(S) == (S[2..128] || 0); + * otherwise, double(S) == (S[2..128] || 0) xor + * (zeros(120) || 10000111). + * + * Both OCB and EAX (through CMAC) require this function to be constant-time. + * + * @param {Uint8Array} data + */ + double: function(data) { + const doubleVar = new Uint8Array(data.length); + const last = data.length - 1; + for (let i = 0; i < last; i++) { + doubleVar[i] = (data[i] << 1) ^ (data[i + 1] >> 7); + } + doubleVar[last] = (data[last] << 1) ^ ((data[0] >> 7) * 0x87); + return doubleVar; + }, + + /** + * Shift a Uint8Array to the right by n bits + * @param {Uint8Array} array - The array to shift + * @param {Integer} bits - Amount of bits to shift (MUST be smaller + * than 8) + * @returns {String} Resulting array. + */ + shiftRight: function (array, bits) { + if (bits) { + for (let i = array.length - 1; i >= 0; i--) { + array[i] >>= bits; + if (i > 0) { + array[i] |= (array[i - 1] << (8 - bits)); + } + } + } + return array; + }, + + /** + * Get native Web Cryptography api, only the current version of the spec. + * @returns {Object} The SubtleCrypto api or 'undefined'. + */ + getWebCrypto: function() { + return typeof globalThis !== 'undefined' && globalThis.crypto && globalThis.crypto.subtle; + }, + + /** + * Detect Node.js runtime. + */ + detectNode: function() { + return typeof globalThis.process === 'object' && + typeof globalThis.process.versions === 'object'; + }, + + /** + * Detect native BigInt support + */ + detectBigInt: () => typeof BigInt !== 'undefined', + + /** + * Get BigInteger class + * It wraps the native BigInt type if it's available + * Otherwise it relies on bn.js + * @returns {BigInteger} + * @async + */ + getBigInteger, + + /** + * Get native Node.js crypto api. + * @returns {Object} The crypto module or 'undefined'. + */ + getNodeCrypto: function() { + return void('crypto'); + }, + + getNodeZlib: function() { + return void('zlib'); + }, + + /** + * Get native Node.js Buffer constructor. This should be used since + * Buffer is not available under browserify. + * @returns {Function} The Buffer constructor or 'undefined'. + */ + getNodeBuffer: function() { + return ({}).Buffer; + }, + + getHardwareConcurrency: function() { + if (util.detectNode()) { + const os = void('os'); + return os.cpus().length; + } + + return navigator.hardwareConcurrency || 1; + }, + + isEmailAddress: function(data) { + if (!util.isString(data)) { + return false; + } + const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+([a-zA-Z]{2,}|xn--[a-zA-Z\-0-9]+)))$/; + return re.test(data); + }, + + /** + * Normalize line endings to + * Support any encoding where CR=0x0D, LF=0x0A + */ + canonicalizeEOL: function(data) { + const CR = 13; + const LF = 10; + let carryOverCR = false; + + return transform(data, bytes => { + if (carryOverCR) { + bytes = util.concatUint8Array([new Uint8Array([CR]), bytes]); + } + + if (bytes[bytes.length - 1] === CR) { + carryOverCR = true; + bytes = bytes.subarray(0, -1); + } else { + carryOverCR = false; + } + + let index; + const indices = []; + for (let i = 0; ; i = index) { + index = bytes.indexOf(LF, i) + 1; + if (index) { + if (bytes[index - 2] !== CR) indices.push(index); + } else { + break; + } + } + if (!indices.length) { + return bytes; + } + + const normalized = new Uint8Array(bytes.length + indices.length); + let j = 0; + for (let i = 0; i < indices.length; i++) { + const sub = bytes.subarray(indices[i - 1] || 0, indices[i]); + normalized.set(sub, j); + j += sub.length; + normalized[j - 1] = CR; + normalized[j] = LF; + j++; + } + normalized.set(bytes.subarray(indices[indices.length - 1] || 0), j); + return normalized; + }, () => (carryOverCR ? new Uint8Array([CR]) : undefined)); + }, + + /** + * Convert line endings from canonicalized to native + * Support any encoding where CR=0x0D, LF=0x0A + */ + nativeEOL: function(data) { + const CR = 13; + const LF = 10; + let carryOverCR = false; + + return transform(data, bytes => { + if (carryOverCR && bytes[0] !== LF) { + bytes = util.concatUint8Array([new Uint8Array([CR]), bytes]); + } else { + bytes = new Uint8Array(bytes); // Don't mutate passed bytes + } + + if (bytes[bytes.length - 1] === CR) { + carryOverCR = true; + bytes = bytes.subarray(0, -1); + } else { + carryOverCR = false; + } + + let index; + let j = 0; + for (let i = 0; i !== bytes.length; i = index) { + index = bytes.indexOf(CR, i) + 1; + if (!index) index = bytes.length; + const last = index - (bytes[index] === LF ? 1 : 0); + if (i) bytes.copyWithin(j, i, last); + j += last - i; + } + return bytes.subarray(0, j); + }, () => (carryOverCR ? new Uint8Array([CR]) : undefined)); + }, + + /** + * Remove trailing spaces and tabs from each line + */ + removeTrailingSpaces: function(text) { + return text.split('\n').map(line => { + let i = line.length - 1; + for (; i >= 0 && (line[i] === ' ' || line[i] === '\t'); i--); + return line.substr(0, i + 1); + }).join('\n'); + }, + + wrapError: function(message, error) { + if (!error) { + return new Error(message); + } + + // update error message + try { + error.message = message + ': ' + error.message; + } catch (e) {} + + return error; + }, + + /** + * Map allowed packet tags to corresponding classes + * Meant to be used to format `allowedPacket` for Packetlist.read + * @param {Array} allowedClasses + * @returns {Object} map from enum.packet to corresponding *Packet class + */ + constructAllowedPackets: function(allowedClasses) { + const map = {}; + allowedClasses.forEach(PacketClass => { + if (!PacketClass.tag) { + throw new Error('Invalid input: expected a packet class'); + } + map[PacketClass.tag] = PacketClass; + }); + return map; + }, + + /** + * Return a Promise that will resolve as soon as one of the promises in input resolves + * or will reject if all input promises all rejected + * (similar to Promise.any, but with slightly different error handling) + * @param {Array} promises + * @return {Promise} Promise resolving to the result of the fastest fulfilled promise + * or rejected with the Error of the last resolved Promise (if all promises are rejected) + */ + anyPromise: function(promises) { + return new Promise(async (resolve, reject) => { + let exception; + await Promise.all(promises.map(async promise => { + try { + resolve(await promise); + } catch (e) { + exception = e; + } + })); + reject(exception); + }); + }, + + /** + * Return either `a` or `b` based on `cond`, in algorithmic constant time. + * @param {Boolean} cond + * @param {Uint8Array} a + * @param {Uint8Array} b + * @returns `a` if `cond` is true, `b` otherwise + */ + selectUint8Array: function(cond, a, b) { + const length = Math.max(a.length, b.length); + const result = new Uint8Array(length); + let end = 0; + for (let i = 0; i < result.length; i++) { + result[i] = (a[i] & (256 - cond)) | (b[i] & (255 + cond)); + end += (cond & i < a.length) | ((1 - cond) & i < b.length); + } + return result.subarray(0, end); + }, + /** + * Return either `a` or `b` based on `cond`, in algorithmic constant time. + * NB: it only supports `a, b` with values between 0-255. + * @param {Boolean} cond + * @param {Uint8} a + * @param {Uint8} b + * @returns `a` if `cond` is true, `b` otherwise + */ + selectUint8: function(cond, a, b) { + return (a & (256 - cond)) | (b & (255 + cond)); + } + }; + + /* OpenPGP radix-64/base64 string encoding/decoding + * Copyright 2005 Herbert Hanewinkel, www.haneWIN.de + * version 1.0, check www.haneWIN.de for the latest version + * + * This software is provided as-is, without express or implied warranty. + * Permission to use, copy, modify, distribute or sell this software, with or + * without fee, for any purpose and by any individual or organization, is hereby + * granted, provided that the above copyright notice and this paragraph appear + * in all copies. Distribution as a part of an application or binary must + * include the above copyright notice in the documentation and/or other materials + * provided with the application or distribution. + */ + + const Buffer = util.getNodeBuffer(); + + let encodeChunk; + let decodeChunk; + if (Buffer) { + encodeChunk = buf => Buffer.from(buf).toString('base64'); + decodeChunk = str => { + const b = Buffer.from(str, 'base64'); + return new Uint8Array(b.buffer, b.byteOffset, b.byteLength); + }; + } else { + encodeChunk = buf => btoa(util.uint8ArrayToString(buf)); + decodeChunk = str => util.stringToUint8Array(atob(str)); + } + + /** + * Convert binary array to radix-64 + * @param {Uint8Array | ReadableStream} data - Uint8Array to convert + * @returns {String | ReadableStream} Radix-64 version of input string. + * @static + */ + function encode(data) { + let buf = new Uint8Array(); + return transform(data, value => { + buf = util.concatUint8Array([buf, value]); + const r = []; + const bytesPerLine = 45; // 60 chars per line * (3 bytes / 4 chars of base64). + const lines = Math.floor(buf.length / bytesPerLine); + const bytes = lines * bytesPerLine; + const encoded = encodeChunk(buf.subarray(0, bytes)); + for (let i = 0; i < lines; i++) { + r.push(encoded.substr(i * 60, 60)); + r.push('\n'); + } + buf = buf.subarray(bytes); + return r.join(''); + }, () => (buf.length ? encodeChunk(buf) + '\n' : '')); + } + + /** + * Convert radix-64 to binary array + * @param {String | ReadableStream} data - Radix-64 string to convert + * @returns {Uint8Array | ReadableStream} Binary array version of input string. + * @static + */ + function decode(data) { + let buf = ''; + return transform(data, value => { + buf += value; + + // Count how many whitespace characters there are in buf + let spaces = 0; + const spacechars = [' ', '\t', '\r', '\n']; + for (let i = 0; i < spacechars.length; i++) { + const spacechar = spacechars[i]; + for (let pos = buf.indexOf(spacechar); pos !== -1; pos = buf.indexOf(spacechar, pos + 1)) { + spaces++; + } + } + + // Backtrack until we have 4n non-whitespace characters + // that we can safely base64-decode + let length = buf.length; + for (; length > 0 && (length - spaces) % 4 !== 0; length--) { + if (spacechars.includes(buf[length])) spaces--; + } + + const decoded = decodeChunk(buf.substr(0, length)); + buf = buf.substr(length); + return decoded; + }, () => decodeChunk(buf)); + } + + /** + * Convert a Base-64 encoded string an array of 8-bit integer + * + * Note: accepts both Radix-64 and URL-safe strings + * @param {String} base64 - Base-64 encoded string to convert + * @returns {Uint8Array} An array of 8-bit integers. + */ + function b64ToUint8Array(base64) { + return decode(base64.replace(/-/g, '+').replace(/_/g, '/')); + } + + /** + * Convert an array of 8-bit integer to a Base-64 encoded string + * @param {Uint8Array} bytes - An array of 8-bit integers to convert + * @param {bool} url - If true, output is URL-safe + * @returns {String} Base-64 encoded string. + */ + function uint8ArrayToB64(bytes, url) { + let encoded = encode(bytes).replace(/[\r\n]/g, ''); + if (url) { + encoded = encoded.replace(/[+]/g, '-').replace(/[/]/g, '_').replace(/[=]/g, ''); + } + return encoded; + } + + /** + * @module enums + */ + + const byValue = Symbol('byValue'); + + var enums = { + + /** Maps curve names under various standards to one + * @see {@link https://wiki.gnupg.org/ECC|ECC - GnuPG wiki} + * @enum {String} + * @readonly + */ + curve: { + /** NIST P-256 Curve */ + 'p256': 'p256', + 'P-256': 'p256', + 'secp256r1': 'p256', + 'prime256v1': 'p256', + '1.2.840.10045.3.1.7': 'p256', + '2a8648ce3d030107': 'p256', + '2A8648CE3D030107': 'p256', + + /** NIST P-384 Curve */ + 'p384': 'p384', + 'P-384': 'p384', + 'secp384r1': 'p384', + '1.3.132.0.34': 'p384', + '2b81040022': 'p384', + '2B81040022': 'p384', + + /** NIST P-521 Curve */ + 'p521': 'p521', + 'P-521': 'p521', + 'secp521r1': 'p521', + '1.3.132.0.35': 'p521', + '2b81040023': 'p521', + '2B81040023': 'p521', + + /** SECG SECP256k1 Curve */ + 'secp256k1': 'secp256k1', + '1.3.132.0.10': 'secp256k1', + '2b8104000a': 'secp256k1', + '2B8104000A': 'secp256k1', + + /** Ed25519 */ + 'ED25519': 'ed25519', + 'ed25519': 'ed25519', + 'Ed25519': 'ed25519', + '1.3.6.1.4.1.11591.15.1': 'ed25519', + '2b06010401da470f01': 'ed25519', + '2B06010401DA470F01': 'ed25519', + + /** Curve25519 */ + 'X25519': 'curve25519', + 'cv25519': 'curve25519', + 'curve25519': 'curve25519', + 'Curve25519': 'curve25519', + '1.3.6.1.4.1.3029.1.5.1': 'curve25519', + '2b060104019755010501': 'curve25519', + '2B060104019755010501': 'curve25519', + + /** BrainpoolP256r1 Curve */ + 'brainpoolP256r1': 'brainpoolP256r1', + '1.3.36.3.3.2.8.1.1.7': 'brainpoolP256r1', + '2b2403030208010107': 'brainpoolP256r1', + '2B2403030208010107': 'brainpoolP256r1', + + /** BrainpoolP384r1 Curve */ + 'brainpoolP384r1': 'brainpoolP384r1', + '1.3.36.3.3.2.8.1.1.11': 'brainpoolP384r1', + '2b240303020801010b': 'brainpoolP384r1', + '2B240303020801010B': 'brainpoolP384r1', + + /** BrainpoolP512r1 Curve */ + 'brainpoolP512r1': 'brainpoolP512r1', + '1.3.36.3.3.2.8.1.1.13': 'brainpoolP512r1', + '2b240303020801010d': 'brainpoolP512r1', + '2B240303020801010D': 'brainpoolP512r1' + }, + + /** A string to key specifier type + * @enum {Integer} + * @readonly + */ + s2k: { + simple: 0, + salted: 1, + iterated: 3, + gnu: 101 + }, + + /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-9.1|RFC4880bis-04, section 9.1} + * @enum {Integer} + * @readonly + */ + publicKey: { + /** RSA (Encrypt or Sign) [HAC] */ + rsaEncryptSign: 1, + /** RSA (Encrypt only) [HAC] */ + rsaEncrypt: 2, + /** RSA (Sign only) [HAC] */ + rsaSign: 3, + /** Elgamal (Encrypt only) [ELGAMAL] [HAC] */ + elgamal: 16, + /** DSA (Sign only) [FIPS186] [HAC] */ + dsa: 17, + /** ECDH (Encrypt only) [RFC6637] */ + ecdh: 18, + /** ECDSA (Sign only) [RFC6637] */ + ecdsa: 19, + /** EdDSA (Sign only) + * [{@link https://tools.ietf.org/html/draft-koch-eddsa-for-openpgp-04|Draft RFC}] */ + eddsa: 22, + /** Reserved for AEDH */ + aedh: 23, + /** Reserved for AEDSA */ + aedsa: 24 + }, + + /** {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC4880, section 9.2} + * @enum {Integer} + * @readonly + */ + symmetric: { + plaintext: 0, + /** Not implemented! */ + idea: 1, + tripledes: 2, + cast5: 3, + blowfish: 4, + aes128: 7, + aes192: 8, + aes256: 9, + twofish: 10 + }, + + /** {@link https://tools.ietf.org/html/rfc4880#section-9.3|RFC4880, section 9.3} + * @enum {Integer} + * @readonly + */ + compression: { + uncompressed: 0, + /** RFC1951 */ + zip: 1, + /** RFC1950 */ + zlib: 2, + bzip2: 3 + }, + + /** {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC4880, section 9.4} + * @enum {Integer} + * @readonly + */ + hash: { + md5: 1, + sha1: 2, + ripemd: 3, + sha256: 8, + sha384: 9, + sha512: 10, + sha224: 11 + }, + + /** A list of hash names as accepted by webCrypto functions. + * {@link https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest|Parameters, algo} + * @enum {String} + */ + webHash: { + 'SHA-1': 2, + 'SHA-256': 8, + 'SHA-384': 9, + 'SHA-512': 10 + }, + + /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-9.6|RFC4880bis-04, section 9.6} + * @enum {Integer} + * @readonly + */ + aead: { + eax: 1, + ocb: 2, + experimentalGCM: 100 // Private algorithm + }, + + /** A list of packet types and numeric tags associated with them. + * @enum {Integer} + * @readonly + */ + packet: { + publicKeyEncryptedSessionKey: 1, + signature: 2, + symEncryptedSessionKey: 3, + onePassSignature: 4, + secretKey: 5, + publicKey: 6, + secretSubkey: 7, + compressedData: 8, + symmetricallyEncryptedData: 9, + marker: 10, + literalData: 11, + trust: 12, + userID: 13, + publicSubkey: 14, + userAttribute: 17, + symEncryptedIntegrityProtectedData: 18, + modificationDetectionCode: 19, + aeadEncryptedData: 20 // see IETF draft: https://tools.ietf.org/html/draft-ford-openpgp-format-00#section-2.1 + }, + + /** Data types in the literal packet + * @enum {Integer} + * @readonly + */ + literal: { + /** Binary data 'b' */ + binary: 'b'.charCodeAt(), + /** Text data 't' */ + text: 't'.charCodeAt(), + /** Utf8 data 'u' */ + utf8: 'u'.charCodeAt(), + /** MIME message body part 'm' */ + mime: 'm'.charCodeAt() + }, + + + /** One pass signature packet type + * @enum {Integer} + * @readonly + */ + signature: { + /** 0x00: Signature of a binary document. */ + binary: 0, + /** 0x01: Signature of a canonical text document. + * + * Canonicalyzing the document by converting line endings. */ + text: 1, + /** 0x02: Standalone signature. + * + * This signature is a signature of only its own subpacket contents. + * It is calculated identically to a signature over a zero-lengh + * binary document. Note that it doesn't make sense to have a V3 + * standalone signature. */ + standalone: 2, + /** 0x10: Generic certification of a User ID and Public-Key packet. + * + * The issuer of this certification does not make any particular + * assertion as to how well the certifier has checked that the owner + * of the key is in fact the person described by the User ID. */ + certGeneric: 16, + /** 0x11: Persona certification of a User ID and Public-Key packet. + * + * The issuer of this certification has not done any verification of + * the claim that the owner of this key is the User ID specified. */ + certPersona: 17, + /** 0x12: Casual certification of a User ID and Public-Key packet. + * + * The issuer of this certification has done some casual + * verification of the claim of identity. */ + certCasual: 18, + /** 0x13: Positive certification of a User ID and Public-Key packet. + * + * The issuer of this certification has done substantial + * verification of the claim of identity. + * + * Most OpenPGP implementations make their "key signatures" as 0x10 + * certifications. Some implementations can issue 0x11-0x13 + * certifications, but few differentiate between the types. */ + certPositive: 19, + /** 0x30: Certification revocation signature + * + * This signature revokes an earlier User ID certification signature + * (signature class 0x10 through 0x13) or direct-key signature + * (0x1F). It should be issued by the same key that issued the + * revoked signature or an authorized revocation key. The signature + * is computed over the same data as the certificate that it + * revokes, and should have a later creation date than that + * certificate. */ + certRevocation: 48, + /** 0x18: Subkey Binding Signature + * + * This signature is a statement by the top-level signing key that + * indicates that it owns the subkey. This signature is calculated + * directly on the primary key and subkey, and not on any User ID or + * other packets. A signature that binds a signing subkey MUST have + * an Embedded Signature subpacket in this binding signature that + * contains a 0x19 signature made by the signing subkey on the + * primary key and subkey. */ + subkeyBinding: 24, + /** 0x19: Primary Key Binding Signature + * + * This signature is a statement by a signing subkey, indicating + * that it is owned by the primary key and subkey. This signature + * is calculated the same way as a 0x18 signature: directly on the + * primary key and subkey, and not on any User ID or other packets. + * + * When a signature is made over a key, the hash data starts with the + * octet 0x99, followed by a two-octet length of the key, and then body + * of the key packet. (Note that this is an old-style packet header for + * a key packet with two-octet length.) A subkey binding signature + * (type 0x18) or primary key binding signature (type 0x19) then hashes + * the subkey using the same format as the main key (also using 0x99 as + * the first octet). */ + keyBinding: 25, + /** 0x1F: Signature directly on a key + * + * This signature is calculated directly on a key. It binds the + * information in the Signature subpackets to the key, and is + * appropriate to be used for subpackets that provide information + * about the key, such as the Revocation Key subpacket. It is also + * appropriate for statements that non-self certifiers want to make + * about the key itself, rather than the binding between a key and a + * name. */ + key: 31, + /** 0x20: Key revocation signature + * + * The signature is calculated directly on the key being revoked. A + * revoked key is not to be used. Only revocation signatures by the + * key being revoked, or by an authorized revocation key, should be + * considered valid revocation signatures.a */ + keyRevocation: 32, + /** 0x28: Subkey revocation signature + * + * The signature is calculated directly on the subkey being revoked. + * A revoked subkey is not to be used. Only revocation signatures + * by the top-level signature key that is bound to this subkey, or + * by an authorized revocation key, should be considered valid + * revocation signatures. + * + * Key revocation signatures (types 0x20 and 0x28) + * hash only the key being revoked. */ + subkeyRevocation: 40, + /** 0x40: Timestamp signature. + * This signature is only meaningful for the timestamp contained in + * it. */ + timestamp: 64, + /** 0x50: Third-Party Confirmation signature. + * + * This signature is a signature over some other OpenPGP Signature + * packet(s). It is analogous to a notary seal on the signed data. + * A third-party signature SHOULD include Signature Target + * subpacket(s) to give easy identification. Note that we really do + * mean SHOULD. There are plausible uses for this (such as a blind + * party that only sees the signature, not the key or source + * document) that cannot include a target subpacket. */ + thirdParty: 80 + }, + + /** Signature subpacket type + * @enum {Integer} + * @readonly + */ + signatureSubpacket: { + signatureCreationTime: 2, + signatureExpirationTime: 3, + exportableCertification: 4, + trustSignature: 5, + regularExpression: 6, + revocable: 7, + keyExpirationTime: 9, + placeholderBackwardsCompatibility: 10, + preferredSymmetricAlgorithms: 11, + revocationKey: 12, + issuer: 16, + notationData: 20, + preferredHashAlgorithms: 21, + preferredCompressionAlgorithms: 22, + keyServerPreferences: 23, + preferredKeyServer: 24, + primaryUserID: 25, + policyURI: 26, + keyFlags: 27, + signersUserID: 28, + reasonForRevocation: 29, + features: 30, + signatureTarget: 31, + embeddedSignature: 32, + issuerFingerprint: 33, + preferredAEADAlgorithms: 34 + }, + + /** Key flags + * @enum {Integer} + * @readonly + */ + keyFlags: { + /** 0x01 - This key may be used to certify other keys. */ + certifyKeys: 1, + /** 0x02 - This key may be used to sign data. */ + signData: 2, + /** 0x04 - This key may be used to encrypt communications. */ + encryptCommunication: 4, + /** 0x08 - This key may be used to encrypt storage. */ + encryptStorage: 8, + /** 0x10 - The private component of this key may have been split + * by a secret-sharing mechanism. */ + splitPrivateKey: 16, + /** 0x20 - This key may be used for authentication. */ + authentication: 32, + /** 0x80 - The private component of this key may be in the + * possession of more than one person. */ + sharedPrivateKey: 128 + }, + + /** Armor type + * @enum {Integer} + * @readonly + */ + armor: { + multipartSection: 0, + multipartLast: 1, + signed: 2, + message: 3, + publicKey: 4, + privateKey: 5, + signature: 6 + }, + + /** {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.23|RFC4880, section 5.2.3.23} + * @enum {Integer} + * @readonly + */ + reasonForRevocation: { + /** No reason specified (key revocations or cert revocations) */ + noReason: 0, + /** Key is superseded (key revocations) */ + keySuperseded: 1, + /** Key material has been compromised (key revocations) */ + keyCompromised: 2, + /** Key is retired and no longer used (key revocations) */ + keyRetired: 3, + /** User ID information is no longer valid (cert revocations) */ + userIDInvalid: 32 + }, + + /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.2.3.25|RFC4880bis-04, section 5.2.3.25} + * @enum {Integer} + * @readonly + */ + features: { + /** 0x01 - Modification Detection (packets 18 and 19) */ + modificationDetection: 1, + /** 0x02 - AEAD Encrypted Data Packet (packet 20) and version 5 + * Symmetric-Key Encrypted Session Key Packets (packet 3) */ + aead: 2, + /** 0x04 - Version 5 Public-Key Packet format and corresponding new + * fingerprint format */ + v5Keys: 4 + }, + + /** + * Asserts validity of given value and converts from string/integer to integer. + * @param {Object} type target enum type + * @param {String|Integer} e value to check and/or convert + * @returns {Integer} enum value if it exists + * @throws {Error} if the value is invalid + */ + write: function(type, e) { + if (typeof e === 'number') { + e = this.read(type, e); + } + + if (type[e] !== undefined) { + return type[e]; + } + + throw new Error('Invalid enum value.'); + }, + + /** + * Converts enum integer value to the corresponding string, if it exists. + * @param {Object} type target enum type + * @param {Integer} e value to convert + * @returns {String} name of enum value if it exists + * @throws {Error} if the value is invalid + */ + read: function(type, e) { + if (!type[byValue]) { + type[byValue] = []; + Object.entries(type).forEach(([key, value]) => { + type[byValue][value] = key; + }); + } + + if (type[byValue][e] !== undefined) { + return type[byValue][e]; + } + + throw new Error('Invalid enum value.'); + } + }; + + // GPG4Browsers - An OpenPGP implementation in javascript + + var defaultConfig = { + /** + * @memberof module:config + * @property {Integer} preferredHashAlgorithm Default hash algorithm {@link module:enums.hash} + */ + preferredHashAlgorithm: enums.hash.sha256, + /** + * @memberof module:config + * @property {Integer} preferredSymmetricAlgorithm Default encryption cipher {@link module:enums.symmetric} + */ + preferredSymmetricAlgorithm: enums.symmetric.aes256, + /** + * @memberof module:config + * @property {Integer} compression Default compression algorithm {@link module:enums.compression} + */ + preferredCompressionAlgorithm: enums.compression.uncompressed, + /** + * @memberof module:config + * @property {Integer} deflateLevel Default zip/zlib compression level, between 1 and 9 + */ + deflateLevel: 6, + + /** + * Use Authenticated Encryption with Additional Data (AEAD) protection for symmetric encryption. + * Note: not all OpenPGP implementations are compatible with this option. + * **FUTURE OPENPGP.JS VERSIONS MAY BREAK COMPATIBILITY WHEN USING THIS OPTION** + * @see {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-07|RFC4880bis-07} + * @memberof module:config + * @property {Boolean} aeadProtect + */ + aeadProtect: false, + /** + * Default Authenticated Encryption with Additional Data (AEAD) encryption mode + * Only has an effect when aeadProtect is set to true. + * @memberof module:config + * @property {Integer} preferredAEADAlgorithm Default AEAD mode {@link module:enums.aead} + */ + preferredAEADAlgorithm: enums.aead.eax, + /** + * Chunk Size Byte for Authenticated Encryption with Additional Data (AEAD) mode + * Only has an effect when aeadProtect is set to true. + * Must be an integer value from 0 to 56. + * @memberof module:config + * @property {Integer} aeadChunkSizeByte + */ + aeadChunkSizeByte: 12, + /** + * Use V5 keys. + * Note: not all OpenPGP implementations are compatible with this option. + * **FUTURE OPENPGP.JS VERSIONS MAY BREAK COMPATIBILITY WHEN USING THIS OPTION** + * @memberof module:config + * @property {Boolean} v5Keys + */ + v5Keys: false, + /** + * {@link https://tools.ietf.org/html/rfc4880#section-3.7.1.3|RFC4880 3.7.1.3}: + * Iteration Count Byte for S2K (String to Key) + * @memberof module:config + * @property {Integer} s2kIterationCountByte + */ + s2kIterationCountByte: 224, + /** + * Allow decryption of messages without integrity protection. + * This is an **insecure** setting: + * - message modifications cannot be detected, thus processing the decrypted data is potentially unsafe. + * - it enables downgrade attacks against integrity-protected messages. + * @memberof module:config + * @property {Boolean} allowUnauthenticatedMessages + */ + allowUnauthenticatedMessages: false, + /** + * Allow streaming unauthenticated data before its integrity has been checked. + * This setting is **insecure** if the partially decrypted message is processed further or displayed to the user. + * @memberof module:config + * @property {Boolean} allowUnauthenticatedStream + */ + allowUnauthenticatedStream: false, + /** + * @memberof module:config + * @property {Boolean} checksumRequired Do not throw error when armor is missing a checksum + */ + checksumRequired: false, + /** + * Minimum RSA key size allowed for key generation and message signing, verification and encryption. + * The default is 2047 since due to a bug, previous versions of OpenPGP.js could generate 2047-bit keys instead of 2048-bit ones. + * @memberof module:config + * @property {Number} minRSABits + */ + minRSABits: 2047, + /** + * Work-around for rare GPG decryption bug when encrypting with multiple passwords. + * **Slower and slightly less secure** + * @memberof module:config + * @property {Boolean} passwordCollisionCheck + */ + passwordCollisionCheck: false, + /** + * @memberof module:config + * @property {Boolean} revocationsExpire If true, expired revocation signatures are ignored + */ + revocationsExpire: false, + /** + * Allow decryption using RSA keys without `encrypt` flag. + * This setting is potentially insecure, but it is needed to get around an old openpgpjs bug + * where key flags were ignored when selecting a key for encryption. + * @memberof module:config + * @property {Boolean} allowInsecureDecryptionWithSigningKeys + */ + allowInsecureDecryptionWithSigningKeys: false, + /** + * Allow verification of message signatures with keys whose validity at the time of signing cannot be determined. + * Instead, a verification key will also be consider valid as long as it is valid at the current time. + * This setting is potentially insecure, but it is needed to verify messages signed with keys that were later reformatted, + * and have self-signature's creation date that does not match the primary key creation date. + * @memberof module:config + * @property {Boolean} allowInsecureDecryptionWithSigningKeys + */ + allowInsecureVerificationWithReformattedKeys: false, + + /** + * Enable constant-time decryption of RSA- and ElGamal-encrypted session keys, to hinder Bleichenbacher-like attacks (https://link.springer.com/chapter/10.1007/BFb0055716). + * This setting has measurable performance impact and it is only helpful in application scenarios where both of the following conditions apply: + * - new/incoming messages are automatically decrypted (without user interaction); + * - an attacker can determine how long it takes to decrypt each message (e.g. due to decryption errors being logged remotely). + * See also `constantTimePKCS1DecryptionSupportedSymmetricAlgorithms`. + * @memberof module:config + * @property {Boolean} constantTimePKCS1Decryption + */ + constantTimePKCS1Decryption: false, + /** + * This setting is only meaningful if `constantTimePKCS1Decryption` is enabled. + * Decryption of RSA- and ElGamal-encrypted session keys of symmetric algorithms different from the ones specified here will fail. + * However, the more algorithms are added, the slower the decryption procedure becomes. + * @memberof module:config + * @property {Set} constantTimePKCS1DecryptionSupportedSymmetricAlgorithms {@link module:enums.symmetric} + */ + constantTimePKCS1DecryptionSupportedSymmetricAlgorithms: new Set([enums.symmetric.aes128, enums.symmetric.aes192, enums.symmetric.aes256]), + + /** + * @memberof module:config + * @property {Integer} minBytesForWebCrypto The minimum amount of bytes for which to use native WebCrypto APIs when available + */ + minBytesForWebCrypto: 1000, + /** + * @memberof module:config + * @property {Boolean} ignoreUnsupportedPackets Ignore unsupported/unrecognizable packets on parsing instead of throwing an error + */ + ignoreUnsupportedPackets: true, + /** + * @memberof module:config + * @property {Boolean} ignoreMalformedPackets Ignore malformed packets on parsing instead of throwing an error + */ + ignoreMalformedPackets: false, + /** + * @memberof module:config + * @property {Boolean} showVersion Whether to include {@link module:config/config.versionString} in armored messages + */ + showVersion: false, + /** + * @memberof module:config + * @property {Boolean} showComment Whether to include {@link module:config/config.commentString} in armored messages + */ + showComment: false, + /** + * @memberof module:config + * @property {String} versionString A version string to be included in armored messages + */ + versionString: 'OpenPGP.js 5.1.0', + /** + * @memberof module:config + * @property {String} commentString A comment string to be included in armored messages + */ + commentString: 'https://openpgpjs.org', + + /** + * Max userID string length (used for parsing) + * @memberof module:config + * @property {Integer} maxUserIDLength + */ + maxUserIDLength: 1024 * 5, + /** + * Contains notatations that are considered "known". Known notations do not trigger + * validation error when the notation is marked as critical. + * @memberof module:config + * @property {Array} knownNotations + */ + knownNotations: ['preferred-email-encoding@pgp.com', 'pka-address@gnupg.org'], + /** + * Whether to use the indutny/elliptic library for curves (other than Curve25519) that are not supported by the available native crypto API. + * When false, certain standard curves will not be supported (depending on the platform). + * Note: the indutny/elliptic curve library is not designed to be constant time. + * @memberof module:config + * @property {Boolean} useIndutnyElliptic + */ + useIndutnyElliptic: true, + /** + * Reject insecure hash algorithms + * @memberof module:config + * @property {Set} rejectHashAlgorithms {@link module:enums.hash} + */ + rejectHashAlgorithms: new Set([enums.hash.md5, enums.hash.ripemd]), + /** + * Reject insecure message hash algorithms + * @memberof module:config + * @property {Set} rejectMessageHashAlgorithms {@link module:enums.hash} + */ + rejectMessageHashAlgorithms: new Set([enums.hash.md5, enums.hash.ripemd, enums.hash.sha1]), + /** + * Reject insecure public key algorithms for key generation and message encryption, signing or verification + * @memberof module:config + * @property {Set} rejectPublicKeyAlgorithms {@link module:enums.publicKey} + */ + rejectPublicKeyAlgorithms: new Set([enums.publicKey.elgamal, enums.publicKey.dsa]), + /** + * Reject non-standard curves for key generation, message encryption, signing or verification + * @memberof module:config + * @property {Set} rejectCurves {@link module:enums.curve} + */ + rejectCurves: new Set([enums.curve.brainpoolP256r1, enums.curve.brainpoolP384r1, enums.curve.brainpoolP512r1, enums.curve.secp256k1]) + }; + + // GPG4Browsers - An OpenPGP implementation in javascript + + /** + * Finds out which Ascii Armoring type is used. Throws error if unknown type. + * @param {String} text - ascii armored text + * @returns {Integer} 0 = MESSAGE PART n of m. + * 1 = MESSAGE PART n + * 2 = SIGNED MESSAGE + * 3 = PGP MESSAGE + * 4 = PUBLIC KEY BLOCK + * 5 = PRIVATE KEY BLOCK + * 6 = SIGNATURE + * @private + */ + function getType(text) { + const reHeader = /^-----BEGIN PGP (MESSAGE, PART \d+\/\d+|MESSAGE, PART \d+|SIGNED MESSAGE|MESSAGE|PUBLIC KEY BLOCK|PRIVATE KEY BLOCK|SIGNATURE)-----$/m; + + const header = text.match(reHeader); + + if (!header) { + throw new Error('Unknown ASCII armor type'); + } + + // BEGIN PGP MESSAGE, PART X/Y + // Used for multi-part messages, where the armor is split amongst Y + // parts, and this is the Xth part out of Y. + if (/MESSAGE, PART \d+\/\d+/.test(header[1])) { + return enums.armor.multipartSection; + } else + // BEGIN PGP MESSAGE, PART X + // Used for multi-part messages, where this is the Xth part of an + // unspecified number of parts. Requires the MESSAGE-ID Armor + // Header to be used. + if (/MESSAGE, PART \d+/.test(header[1])) { + return enums.armor.multipartLast; + } else + // BEGIN PGP SIGNED MESSAGE + if (/SIGNED MESSAGE/.test(header[1])) { + return enums.armor.signed; + } else + // BEGIN PGP MESSAGE + // Used for signed, encrypted, or compressed files. + if (/MESSAGE/.test(header[1])) { + return enums.armor.message; + } else + // BEGIN PGP PUBLIC KEY BLOCK + // Used for armoring public keys. + if (/PUBLIC KEY BLOCK/.test(header[1])) { + return enums.armor.publicKey; + } else + // BEGIN PGP PRIVATE KEY BLOCK + // Used for armoring private keys. + if (/PRIVATE KEY BLOCK/.test(header[1])) { + return enums.armor.privateKey; + } else + // BEGIN PGP SIGNATURE + // Used for detached signatures, OpenPGP/MIME signatures, and + // cleartext signatures. Note that PGP 2.x uses BEGIN PGP MESSAGE + // for detached signatures. + if (/SIGNATURE/.test(header[1])) { + return enums.armor.signature; + } + } + + /** + * Add additional information to the armor version of an OpenPGP binary + * packet block. + * @author Alex + * @version 2011-12-16 + * @param {String} [customComment] - Additional comment to add to the armored string + * @returns {String} The header information. + * @private + */ + function addheader(customComment, config) { + let result = ''; + if (config.showVersion) { + result += 'Version: ' + config.versionString + '\n'; + } + if (config.showComment) { + result += 'Comment: ' + config.commentString + '\n'; + } + if (customComment) { + result += 'Comment: ' + customComment + '\n'; + } + result += '\n'; + return result; + } + + + /** + * Calculates a checksum over the given data and returns it base64 encoded + * @param {String | ReadableStream} data - Data to create a CRC-24 checksum for + * @returns {String | ReadableStream} Base64 encoded checksum. + * @private + */ + function getCheckSum(data) { + const crc = createcrc24(data); + return encode(crc); + } + + // https://create.stephan-brumme.com/crc32/#slicing-by-8-overview + + const crc_table = [ + new Array(0xFF), + new Array(0xFF), + new Array(0xFF), + new Array(0xFF) + ]; + + for (let i = 0; i <= 0xFF; i++) { + let crc = i << 16; + for (let j = 0; j < 8; j++) { + crc = (crc << 1) ^ ((crc & 0x800000) !== 0 ? 0x864CFB : 0); + } + crc_table[0][i] = + ((crc & 0xFF0000) >> 16) | + (crc & 0x00FF00) | + ((crc & 0x0000FF) << 16); + } + for (let i = 0; i <= 0xFF; i++) { + crc_table[1][i] = (crc_table[0][i] >> 8) ^ crc_table[0][crc_table[0][i] & 0xFF]; + } + for (let i = 0; i <= 0xFF; i++) { + crc_table[2][i] = (crc_table[1][i] >> 8) ^ crc_table[0][crc_table[1][i] & 0xFF]; + } + for (let i = 0; i <= 0xFF; i++) { + crc_table[3][i] = (crc_table[2][i] >> 8) ^ crc_table[0][crc_table[2][i] & 0xFF]; + } + + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView#Endianness + const isLittleEndian = (function() { + const buffer = new ArrayBuffer(2); + new DataView(buffer).setInt16(0, 0xFF, true /* littleEndian */); + // Int16Array uses the platform's endianness. + return new Int16Array(buffer)[0] === 0xFF; + }()); + + /** + * Internal function to calculate a CRC-24 checksum over a given string (data) + * @param {String | ReadableStream} input - Data to create a CRC-24 checksum for + * @returns {Uint8Array | ReadableStream} The CRC-24 checksum. + * @private + */ + function createcrc24(input) { + let crc = 0xCE04B7; + return transform(input, value => { + const len32 = isLittleEndian ? Math.floor(value.length / 4) : 0; + const arr32 = new Uint32Array(value.buffer, value.byteOffset, len32); + for (let i = 0; i < len32; i++) { + crc ^= arr32[i]; + crc = + crc_table[0][(crc >> 24) & 0xFF] ^ + crc_table[1][(crc >> 16) & 0xFF] ^ + crc_table[2][(crc >> 8) & 0xFF] ^ + crc_table[3][(crc >> 0) & 0xFF]; + } + for (let i = len32 * 4; i < value.length; i++) { + crc = (crc >> 8) ^ crc_table[0][(crc & 0xFF) ^ value[i]]; + } + }, () => new Uint8Array([crc, crc >> 8, crc >> 16])); + } + + /** + * Verify armored headers. RFC4880, section 6.3: "OpenPGP should consider improperly formatted + * Armor Headers to be corruption of the ASCII Armor." + * @private + * @param {Array} headers - Armor headers + */ + function verifyHeaders(headers) { + for (let i = 0; i < headers.length; i++) { + if (!/^([^\s:]|[^\s:][^:]*[^\s:]): .+$/.test(headers[i])) { + throw new Error('Improperly formatted armor header: ' + headers[i]); + } + if (!/^(Version|Comment|MessageID|Hash|Charset): .+$/.test(headers[i])) { + util.printDebugError(new Error('Unknown header: ' + headers[i])); + } + } + } + + /** + * Splits a message into two parts, the body and the checksum. This is an internal function + * @param {String} text - OpenPGP armored message part + * @returns {Object} An object with attribute "body" containing the body. + * and an attribute "checksum" containing the checksum. + * @private + */ + function splitChecksum(text) { + let body = text; + let checksum = ''; + + const lastEquals = text.lastIndexOf('='); + + if (lastEquals >= 0 && lastEquals !== text.length - 1) { // '=' as the last char means no checksum + body = text.slice(0, lastEquals); + checksum = text.slice(lastEquals + 1).substr(0, 4); + } + + return { body: body, checksum: checksum }; + } + + /** + * Dearmor an OpenPGP armored message; verify the checksum and return + * the encoded bytes + * @param {String} input - OpenPGP armored message + * @returns {Promise} An object with attribute "text" containing the message text, + * an attribute "data" containing a stream of bytes and "type" for the ASCII armor type + * @async + * @static + */ + function unarmor(input, config = defaultConfig) { + return new Promise(async (resolve, reject) => { + try { + const reSplit = /^-----[^-]+-----$/m; + const reEmptyLine = /^[ \f\r\t\u00a0\u2000-\u200a\u202f\u205f\u3000]*$/; + + let type; + const headers = []; + let lastHeaders = headers; + let headersDone; + let text = []; + let textDone; + let checksum; + let data = decode(transformPair(input, async (readable, writable) => { + const reader = getReader(readable); + try { + while (true) { + let line = await reader.readLine(); + if (line === undefined) { + throw new Error('Misformed armored text'); + } + // remove trailing whitespace at end of lines + line = util.removeTrailingSpaces(line.replace(/[\r\n]/g, '')); + if (!type) { + if (reSplit.test(line)) { + type = getType(line); + } + } else if (!headersDone) { + if (reSplit.test(line)) { + reject(new Error('Mandatory blank line missing between armor headers and armor data')); + } + if (!reEmptyLine.test(line)) { + lastHeaders.push(line); + } else { + verifyHeaders(lastHeaders); + headersDone = true; + if (textDone || type !== 2) { + resolve({ text, data, headers, type }); + break; + } + } + } else if (!textDone && type === 2) { + if (!reSplit.test(line)) { + // Reverse dash-escaping for msg + text.push(line.replace(/^- /, '')); + } else { + text = text.join('\r\n'); + textDone = true; + verifyHeaders(lastHeaders); + lastHeaders = []; + headersDone = false; + } + } + } + } catch (e) { + reject(e); + return; + } + const writer = getWriter(writable); + try { + while (true) { + await writer.ready; + const { done, value } = await reader.read(); + if (done) { + throw new Error('Misformed armored text'); + } + const line = value + ''; + if (line.indexOf('=') === -1 && line.indexOf('-') === -1) { + await writer.write(line); + } else { + let remainder = await reader.readToEnd(); + if (!remainder.length) remainder = ''; + remainder = line + remainder; + remainder = util.removeTrailingSpaces(remainder.replace(/\r/g, '')); + const parts = remainder.split(reSplit); + if (parts.length === 1) { + throw new Error('Misformed armored text'); + } + const split = splitChecksum(parts[0].slice(0, -1)); + checksum = split.checksum; + await writer.write(split.body); + break; + } + } + await writer.ready; + await writer.close(); + } catch (e) { + await writer.abort(e); + } + })); + data = transformPair(data, async (readable, writable) => { + const checksumVerified = readToEnd(getCheckSum(passiveClone(readable))); + checksumVerified.catch(() => {}); + await pipe(readable, writable, { + preventClose: true + }); + const writer = getWriter(writable); + try { + const checksumVerifiedString = (await checksumVerified).replace('\n', ''); + if (checksum !== checksumVerifiedString && (checksum || config.checksumRequired)) { + throw new Error('Ascii armor integrity check failed'); + } + await writer.ready; + await writer.close(); + } catch (e) { + await writer.abort(e); + } + }); + } catch (e) { + reject(e); + } + }).then(async result => { + if (isArrayStream(result.data)) { + result.data = await readToEnd(result.data); + } + return result; + }); + } + + + /** + * Armor an OpenPGP binary packet block + * @param {module:enums.armor} messageType - Type of the message + * @param {Uint8Array | ReadableStream} body - The message body to armor + * @param {Integer} [partIndex] + * @param {Integer} [partTotal] + * @param {String} [customComment] - Additional comment to add to the armored string + * @returns {String | ReadableStream} Armored text. + * @static + */ + function armor(messageType, body, partIndex, partTotal, customComment, config = defaultConfig) { + let text; + let hash; + if (messageType === enums.armor.signed) { + text = body.text; + hash = body.hash; + body = body.data; + } + const bodyClone = passiveClone(body); + const result = []; + switch (messageType) { + case enums.armor.multipartSection: + result.push('-----BEGIN PGP MESSAGE, PART ' + partIndex + '/' + partTotal + '-----\n'); + result.push(addheader(customComment, config)); + result.push(encode(body)); + result.push('=', getCheckSum(bodyClone)); + result.push('-----END PGP MESSAGE, PART ' + partIndex + '/' + partTotal + '-----\n'); + break; + case enums.armor.multipartLast: + result.push('-----BEGIN PGP MESSAGE, PART ' + partIndex + '-----\n'); + result.push(addheader(customComment, config)); + result.push(encode(body)); + result.push('=', getCheckSum(bodyClone)); + result.push('-----END PGP MESSAGE, PART ' + partIndex + '-----\n'); + break; + case enums.armor.signed: + result.push('\n-----BEGIN PGP SIGNED MESSAGE-----\n'); + result.push('Hash: ' + hash + '\n\n'); + result.push(text.replace(/^-/mg, '- -')); + result.push('\n-----BEGIN PGP SIGNATURE-----\n'); + result.push(addheader(customComment, config)); + result.push(encode(body)); + result.push('=', getCheckSum(bodyClone)); + result.push('-----END PGP SIGNATURE-----\n'); + break; + case enums.armor.message: + result.push('-----BEGIN PGP MESSAGE-----\n'); + result.push(addheader(customComment, config)); + result.push(encode(body)); + result.push('=', getCheckSum(bodyClone)); + result.push('-----END PGP MESSAGE-----\n'); + break; + case enums.armor.publicKey: + result.push('-----BEGIN PGP PUBLIC KEY BLOCK-----\n'); + result.push(addheader(customComment, config)); + result.push(encode(body)); + result.push('=', getCheckSum(bodyClone)); + result.push('-----END PGP PUBLIC KEY BLOCK-----\n'); + break; + case enums.armor.privateKey: + result.push('-----BEGIN PGP PRIVATE KEY BLOCK-----\n'); + result.push(addheader(customComment, config)); + result.push(encode(body)); + result.push('=', getCheckSum(bodyClone)); + result.push('-----END PGP PRIVATE KEY BLOCK-----\n'); + break; + case enums.armor.signature: + result.push('-----BEGIN PGP SIGNATURE-----\n'); + result.push(addheader(customComment, config)); + result.push(encode(body)); + result.push('=', getCheckSum(bodyClone)); + result.push('-----END PGP SIGNATURE-----\n'); + break; + } + + return util.concat(result); + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + /** + * Implementation of type key id + * + * {@link https://tools.ietf.org/html/rfc4880#section-3.3|RFC4880 3.3}: + * A Key ID is an eight-octet scalar that identifies a key. + * Implementations SHOULD NOT assume that Key IDs are unique. The + * section "Enhanced Key Formats" below describes how Key IDs are + * formed. + */ + class KeyID { + constructor() { + this.bytes = ''; + } + + /** + * Parsing method for a key id + * @param {Uint8Array} bytes - Input to read the key id from + */ + read(bytes) { + this.bytes = util.uint8ArrayToString(bytes.subarray(0, 8)); + } + + /** + * Serializes the Key ID + * @returns {Uint8Array} Key ID as a Uint8Array. + */ + write() { + return util.stringToUint8Array(this.bytes); + } + + /** + * Returns the Key ID represented as a hexadecimal string + * @returns {String} Key ID as a hexadecimal string. + */ + toHex() { + return util.uint8ArrayToHex(util.stringToUint8Array(this.bytes)); + } + + /** + * Checks equality of Key ID's + * @param {KeyID} keyID + * @param {Boolean} matchWildcard - Indicates whether to check if either keyID is a wildcard + */ + equals(keyID, matchWildcard = false) { + return (matchWildcard && (keyID.isWildcard() || this.isWildcard())) || this.bytes === keyID.bytes; + } + + /** + * Checks to see if the Key ID is unset + * @returns {Boolean} True if the Key ID is null. + */ + isNull() { + return this.bytes === ''; + } + + /** + * Checks to see if the Key ID is a "wildcard" Key ID (all zeros) + * @returns {Boolean} True if this is a wildcard Key ID. + */ + isWildcard() { + return /^0+$/.test(this.toHex()); + } + + static mapToHex(keyID) { + return keyID.toHex(); + } + + static fromID(hex) { + const keyID = new KeyID(); + keyID.read(util.hexToUint8Array(hex)); + return keyID; + } + + static wildcard() { + const keyID = new KeyID(); + keyID.read(new Uint8Array(8)); + return keyID; + } + } + + /** + * @file {@link http://asmjs.org Asm.js} implementation of the {@link https://en.wikipedia.org/wiki/Advanced_Encryption_Standard Advanced Encryption Standard}. + * @author Artem S Vybornov + * @license MIT + */ + var AES_asm = function () { + + /** + * Galois Field stuff init flag + */ + var ginit_done = false; + + /** + * Galois Field exponentiation and logarithm tables for 3 (the generator) + */ + var gexp3, glog3; + + /** + * Init Galois Field tables + */ + function ginit() { + gexp3 = [], + glog3 = []; + + var a = 1, c, d; + for (c = 0; c < 255; c++) { + gexp3[c] = a; + + // Multiply by three + d = a & 0x80, a <<= 1, a &= 255; + if (d === 0x80) a ^= 0x1b; + a ^= gexp3[c]; + + // Set the log table value + glog3[gexp3[c]] = c; + } + gexp3[255] = gexp3[0]; + glog3[0] = 0; + + ginit_done = true; + } + + /** + * Galois Field multiplication + * @param {number} a + * @param {number} b + * @return {number} + */ + function gmul(a, b) { + var c = gexp3[(glog3[a] + glog3[b]) % 255]; + if (a === 0 || b === 0) c = 0; + return c; + } + + /** + * Galois Field reciprocal + * @param {number} a + * @return {number} + */ + function ginv(a) { + var i = gexp3[255 - glog3[a]]; + if (a === 0) i = 0; + return i; + } + + /** + * AES stuff init flag + */ + var aes_init_done = false; + + /** + * Encryption, Decryption, S-Box and KeyTransform tables + * + * @type {number[]} + */ + var aes_sbox; + + /** + * @type {number[]} + */ + var aes_sinv; + + /** + * @type {number[][]} + */ + var aes_enc; + + /** + * @type {number[][]} + */ + var aes_dec; + + /** + * Init AES tables + */ + function aes_init() { + if (!ginit_done) ginit(); + + // Calculates AES S-Box value + function _s(a) { + var c, s, x; + s = x = ginv(a); + for (c = 0; c < 4; c++) { + s = ((s << 1) | (s >>> 7)) & 255; + x ^= s; + } + x ^= 99; + return x; + } + + // Tables + aes_sbox = [], + aes_sinv = [], + aes_enc = [[], [], [], []], + aes_dec = [[], [], [], []]; + + for (var i = 0; i < 256; i++) { + var s = _s(i); + + // S-Box and its inverse + aes_sbox[i] = s; + aes_sinv[s] = i; + + // Ecryption and Decryption tables + aes_enc[0][i] = (gmul(2, s) << 24) | (s << 16) | (s << 8) | gmul(3, s); + aes_dec[0][s] = (gmul(14, i) << 24) | (gmul(9, i) << 16) | (gmul(13, i) << 8) | gmul(11, i); + // Rotate tables + for (var t = 1; t < 4; t++) { + aes_enc[t][i] = (aes_enc[t - 1][i] >>> 8) | (aes_enc[t - 1][i] << 24); + aes_dec[t][s] = (aes_dec[t - 1][s] >>> 8) | (aes_dec[t - 1][s] << 24); + } + } + + aes_init_done = true; + } + + /** + * Asm.js module constructor. + * + *

+ * Heap buffer layout by offset: + *

+     * 0x0000   encryption key schedule
+     * 0x0400   decryption key schedule
+     * 0x0800   sbox
+     * 0x0c00   inv sbox
+     * 0x1000   encryption tables
+     * 0x2000   decryption tables
+     * 0x3000   reserved (future GCM multiplication lookup table)
+     * 0x4000   data
+     * 
+ * Don't touch anything before 0x400. + *

+ * + * @alias AES_asm + * @class + * @param foreign - ignored + * @param buffer - heap buffer to link with + */ + var wrapper = function (foreign, buffer) { + // Init AES stuff for the first time + if (!aes_init_done) aes_init(); + + // Fill up AES tables + var heap = new Uint32Array(buffer); + heap.set(aes_sbox, 0x0800 >> 2); + heap.set(aes_sinv, 0x0c00 >> 2); + for (var i = 0; i < 4; i++) { + heap.set(aes_enc[i], (0x1000 + 0x400 * i) >> 2); + heap.set(aes_dec[i], (0x2000 + 0x400 * i) >> 2); + } + + /** + * Calculate AES key schedules. + * @instance + * @memberof AES_asm + * @param {number} ks - key size, 4/6/8 (for 128/192/256-bit key correspondingly) + * @param {number} k0 - key vector components + * @param {number} k1 - key vector components + * @param {number} k2 - key vector components + * @param {number} k3 - key vector components + * @param {number} k4 - key vector components + * @param {number} k5 - key vector components + * @param {number} k6 - key vector components + * @param {number} k7 - key vector components + */ + function set_key(ks, k0, k1, k2, k3, k4, k5, k6, k7) { + var ekeys = heap.subarray(0x000, 60), + dkeys = heap.subarray(0x100, 0x100 + 60); + + // Encryption key schedule + ekeys.set([k0, k1, k2, k3, k4, k5, k6, k7]); + for (var i = ks, rcon = 1; i < 4 * ks + 28; i++) { + var k = ekeys[i - 1]; + if ((i % ks === 0) || (ks === 8 && i % ks === 4)) { + k = aes_sbox[k >>> 24] << 24 ^ aes_sbox[k >>> 16 & 255] << 16 ^ aes_sbox[k >>> 8 & 255] << 8 ^ aes_sbox[k & 255]; + } + if (i % ks === 0) { + k = (k << 8) ^ (k >>> 24) ^ (rcon << 24); + rcon = (rcon << 1) ^ ((rcon & 0x80) ? 0x1b : 0); + } + ekeys[i] = ekeys[i - ks] ^ k; + } + + // Decryption key schedule + for (var j = 0; j < i; j += 4) { + for (var jj = 0; jj < 4; jj++) { + var k = ekeys[i - (4 + j) + (4 - jj) % 4]; + if (j < 4 || j >= i - 4) { + dkeys[j + jj] = k; + } else { + dkeys[j + jj] = aes_dec[0][aes_sbox[k >>> 24]] + ^ aes_dec[1][aes_sbox[k >>> 16 & 255]] + ^ aes_dec[2][aes_sbox[k >>> 8 & 255]] + ^ aes_dec[3][aes_sbox[k & 255]]; + } + } + } + + // Set rounds number + asm.set_rounds(ks + 5); + } + + // create library object with necessary properties + var stdlib = {Uint8Array: Uint8Array, Uint32Array: Uint32Array}; + + var asm = function (stdlib, foreign, buffer) { + "use asm"; + + var S0 = 0, S1 = 0, S2 = 0, S3 = 0, + I0 = 0, I1 = 0, I2 = 0, I3 = 0, + N0 = 0, N1 = 0, N2 = 0, N3 = 0, + M0 = 0, M1 = 0, M2 = 0, M3 = 0, + H0 = 0, H1 = 0, H2 = 0, H3 = 0, + R = 0; + + var HEAP = new stdlib.Uint32Array(buffer), + DATA = new stdlib.Uint8Array(buffer); + + /** + * AES core + * @param {number} k - precomputed key schedule offset + * @param {number} s - precomputed sbox table offset + * @param {number} t - precomputed round table offset + * @param {number} r - number of inner rounds to perform + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _core(k, s, t, r, x0, x1, x2, x3) { + k = k | 0; + s = s | 0; + t = t | 0; + r = r | 0; + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + var t1 = 0, t2 = 0, t3 = 0, + y0 = 0, y1 = 0, y2 = 0, y3 = 0, + i = 0; + + t1 = t | 0x400, t2 = t | 0x800, t3 = t | 0xc00; + + // round 0 + x0 = x0 ^ HEAP[(k | 0) >> 2], + x1 = x1 ^ HEAP[(k | 4) >> 2], + x2 = x2 ^ HEAP[(k | 8) >> 2], + x3 = x3 ^ HEAP[(k | 12) >> 2]; + + // round 1..r + for (i = 16; (i | 0) <= (r << 4); i = (i + 16) | 0) { + y0 = HEAP[(t | x0 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x1 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x2 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x3 << 2 & 1020) >> 2] ^ HEAP[(k | i | 0) >> 2], + y1 = HEAP[(t | x1 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x2 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x3 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x0 << 2 & 1020) >> 2] ^ HEAP[(k | i | 4) >> 2], + y2 = HEAP[(t | x2 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x3 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x0 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x1 << 2 & 1020) >> 2] ^ HEAP[(k | i | 8) >> 2], + y3 = HEAP[(t | x3 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x0 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x1 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x2 << 2 & 1020) >> 2] ^ HEAP[(k | i | 12) >> 2]; + x0 = y0, x1 = y1, x2 = y2, x3 = y3; + } + + // final round + S0 = HEAP[(s | x0 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x1 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x2 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x3 << 2 & 1020) >> 2] ^ HEAP[(k | i | 0) >> 2], + S1 = HEAP[(s | x1 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x2 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x3 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x0 << 2 & 1020) >> 2] ^ HEAP[(k | i | 4) >> 2], + S2 = HEAP[(s | x2 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x3 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x0 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x1 << 2 & 1020) >> 2] ^ HEAP[(k | i | 8) >> 2], + S3 = HEAP[(s | x3 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x0 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x1 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x2 << 2 & 1020) >> 2] ^ HEAP[(k | i | 12) >> 2]; + } + + /** + * ECB mode encryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _ecb_enc(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + _core( + 0x0000, 0x0800, 0x1000, + R, + x0, + x1, + x2, + x3 + ); + } + + /** + * ECB mode decryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _ecb_dec(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + var t = 0; + + _core( + 0x0400, 0x0c00, 0x2000, + R, + x0, + x3, + x2, + x1 + ); + + t = S1, S1 = S3, S3 = t; + } + + + /** + * CBC mode encryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _cbc_enc(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + _core( + 0x0000, 0x0800, 0x1000, + R, + I0 ^ x0, + I1 ^ x1, + I2 ^ x2, + I3 ^ x3 + ); + + I0 = S0, + I1 = S1, + I2 = S2, + I3 = S3; + } + + /** + * CBC mode decryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _cbc_dec(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + var t = 0; + + _core( + 0x0400, 0x0c00, 0x2000, + R, + x0, + x3, + x2, + x1 + ); + + t = S1, S1 = S3, S3 = t; + + S0 = S0 ^ I0, + S1 = S1 ^ I1, + S2 = S2 ^ I2, + S3 = S3 ^ I3; + + I0 = x0, + I1 = x1, + I2 = x2, + I3 = x3; + } + + /** + * CFB mode encryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _cfb_enc(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + _core( + 0x0000, 0x0800, 0x1000, + R, + I0, + I1, + I2, + I3 + ); + + I0 = S0 = S0 ^ x0, + I1 = S1 = S1 ^ x1, + I2 = S2 = S2 ^ x2, + I3 = S3 = S3 ^ x3; + } + + + /** + * CFB mode decryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _cfb_dec(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + _core( + 0x0000, 0x0800, 0x1000, + R, + I0, + I1, + I2, + I3 + ); + + S0 = S0 ^ x0, + S1 = S1 ^ x1, + S2 = S2 ^ x2, + S3 = S3 ^ x3; + + I0 = x0, + I1 = x1, + I2 = x2, + I3 = x3; + } + + /** + * OFB mode encryption / decryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _ofb(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + _core( + 0x0000, 0x0800, 0x1000, + R, + I0, + I1, + I2, + I3 + ); + + I0 = S0, + I1 = S1, + I2 = S2, + I3 = S3; + + S0 = S0 ^ x0, + S1 = S1 ^ x1, + S2 = S2 ^ x2, + S3 = S3 ^ x3; + } + + /** + * CTR mode encryption / decryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _ctr(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + _core( + 0x0000, 0x0800, 0x1000, + R, + N0, + N1, + N2, + N3 + ); + + N3 = (~M3 & N3) | M3 & (N3 + 1); + N2 = (~M2 & N2) | M2 & (N2 + ((N3 | 0) == 0)); + N1 = (~M1 & N1) | M1 & (N1 + ((N2 | 0) == 0)); + N0 = (~M0 & N0) | M0 & (N0 + ((N1 | 0) == 0)); + + S0 = S0 ^ x0; + S1 = S1 ^ x1; + S2 = S2 ^ x2; + S3 = S3 ^ x3; + } + + /** + * GCM mode MAC calculation + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _gcm_mac(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + var y0 = 0, y1 = 0, y2 = 0, y3 = 0, + z0 = 0, z1 = 0, z2 = 0, z3 = 0, + i = 0, c = 0; + + x0 = x0 ^ I0, + x1 = x1 ^ I1, + x2 = x2 ^ I2, + x3 = x3 ^ I3; + + y0 = H0 | 0, + y1 = H1 | 0, + y2 = H2 | 0, + y3 = H3 | 0; + + for (; (i | 0) < 128; i = (i + 1) | 0) { + if (y0 >>> 31) { + z0 = z0 ^ x0, + z1 = z1 ^ x1, + z2 = z2 ^ x2, + z3 = z3 ^ x3; + } + + y0 = (y0 << 1) | (y1 >>> 31), + y1 = (y1 << 1) | (y2 >>> 31), + y2 = (y2 << 1) | (y3 >>> 31), + y3 = (y3 << 1); + + c = x3 & 1; + + x3 = (x3 >>> 1) | (x2 << 31), + x2 = (x2 >>> 1) | (x1 << 31), + x1 = (x1 >>> 1) | (x0 << 31), + x0 = (x0 >>> 1); + + if (c) x0 = x0 ^ 0xe1000000; + } + + I0 = z0, + I1 = z1, + I2 = z2, + I3 = z3; + } + + /** + * Set the internal rounds number. + * @instance + * @memberof AES_asm + * @param {number} r - number if inner AES rounds + */ + function set_rounds(r) { + r = r | 0; + R = r; + } + + /** + * Populate the internal state of the module. + * @instance + * @memberof AES_asm + * @param {number} s0 - state vector + * @param {number} s1 - state vector + * @param {number} s2 - state vector + * @param {number} s3 - state vector + */ + function set_state(s0, s1, s2, s3) { + s0 = s0 | 0; + s1 = s1 | 0; + s2 = s2 | 0; + s3 = s3 | 0; + + S0 = s0, + S1 = s1, + S2 = s2, + S3 = s3; + } + + /** + * Populate the internal iv of the module. + * @instance + * @memberof AES_asm + * @param {number} i0 - iv vector + * @param {number} i1 - iv vector + * @param {number} i2 - iv vector + * @param {number} i3 - iv vector + */ + function set_iv(i0, i1, i2, i3) { + i0 = i0 | 0; + i1 = i1 | 0; + i2 = i2 | 0; + i3 = i3 | 0; + + I0 = i0, + I1 = i1, + I2 = i2, + I3 = i3; + } + + /** + * Set nonce for CTR-family modes. + * @instance + * @memberof AES_asm + * @param {number} n0 - nonce vector + * @param {number} n1 - nonce vector + * @param {number} n2 - nonce vector + * @param {number} n3 - nonce vector + */ + function set_nonce(n0, n1, n2, n3) { + n0 = n0 | 0; + n1 = n1 | 0; + n2 = n2 | 0; + n3 = n3 | 0; + + N0 = n0, + N1 = n1, + N2 = n2, + N3 = n3; + } + + /** + * Set counter mask for CTR-family modes. + * @instance + * @memberof AES_asm + * @param {number} m0 - counter mask vector + * @param {number} m1 - counter mask vector + * @param {number} m2 - counter mask vector + * @param {number} m3 - counter mask vector + */ + function set_mask(m0, m1, m2, m3) { + m0 = m0 | 0; + m1 = m1 | 0; + m2 = m2 | 0; + m3 = m3 | 0; + + M0 = m0, + M1 = m1, + M2 = m2, + M3 = m3; + } + + /** + * Set counter for CTR-family modes. + * @instance + * @memberof AES_asm + * @param {number} c0 - counter vector + * @param {number} c1 - counter vector + * @param {number} c2 - counter vector + * @param {number} c3 - counter vector + */ + function set_counter(c0, c1, c2, c3) { + c0 = c0 | 0; + c1 = c1 | 0; + c2 = c2 | 0; + c3 = c3 | 0; + + N3 = (~M3 & N3) | M3 & c3, + N2 = (~M2 & N2) | M2 & c2, + N1 = (~M1 & N1) | M1 & c1, + N0 = (~M0 & N0) | M0 & c0; + } + + /** + * Store the internal state vector into the heap. + * @instance + * @memberof AES_asm + * @param {number} pos - offset where to put the data + * @return {number} The number of bytes have been written into the heap, always 16. + */ + function get_state(pos) { + pos = pos | 0; + + if (pos & 15) return -1; + + DATA[pos | 0] = S0 >>> 24, + DATA[pos | 1] = S0 >>> 16 & 255, + DATA[pos | 2] = S0 >>> 8 & 255, + DATA[pos | 3] = S0 & 255, + DATA[pos | 4] = S1 >>> 24, + DATA[pos | 5] = S1 >>> 16 & 255, + DATA[pos | 6] = S1 >>> 8 & 255, + DATA[pos | 7] = S1 & 255, + DATA[pos | 8] = S2 >>> 24, + DATA[pos | 9] = S2 >>> 16 & 255, + DATA[pos | 10] = S2 >>> 8 & 255, + DATA[pos | 11] = S2 & 255, + DATA[pos | 12] = S3 >>> 24, + DATA[pos | 13] = S3 >>> 16 & 255, + DATA[pos | 14] = S3 >>> 8 & 255, + DATA[pos | 15] = S3 & 255; + + return 16; + } + + /** + * Store the internal iv vector into the heap. + * @instance + * @memberof AES_asm + * @param {number} pos - offset where to put the data + * @return {number} The number of bytes have been written into the heap, always 16. + */ + function get_iv(pos) { + pos = pos | 0; + + if (pos & 15) return -1; + + DATA[pos | 0] = I0 >>> 24, + DATA[pos | 1] = I0 >>> 16 & 255, + DATA[pos | 2] = I0 >>> 8 & 255, + DATA[pos | 3] = I0 & 255, + DATA[pos | 4] = I1 >>> 24, + DATA[pos | 5] = I1 >>> 16 & 255, + DATA[pos | 6] = I1 >>> 8 & 255, + DATA[pos | 7] = I1 & 255, + DATA[pos | 8] = I2 >>> 24, + DATA[pos | 9] = I2 >>> 16 & 255, + DATA[pos | 10] = I2 >>> 8 & 255, + DATA[pos | 11] = I2 & 255, + DATA[pos | 12] = I3 >>> 24, + DATA[pos | 13] = I3 >>> 16 & 255, + DATA[pos | 14] = I3 >>> 8 & 255, + DATA[pos | 15] = I3 & 255; + + return 16; + } + + /** + * GCM initialization. + * @instance + * @memberof AES_asm + */ + function gcm_init() { + _ecb_enc(0, 0, 0, 0); + H0 = S0, + H1 = S1, + H2 = S2, + H3 = S3; + } + + /** + * Perform ciphering operation on the supplied data. + * @instance + * @memberof AES_asm + * @param {number} mode - block cipher mode (see {@link AES_asm} mode constants) + * @param {number} pos - offset of the data being processed + * @param {number} len - length of the data being processed + * @return {number} Actual amount of data have been processed. + */ + function cipher(mode, pos, len) { + mode = mode | 0; + pos = pos | 0; + len = len | 0; + + var ret = 0; + + if (pos & 15) return -1; + + while ((len | 0) >= 16) { + _cipher_modes[mode & 7]( + DATA[pos | 0] << 24 | DATA[pos | 1] << 16 | DATA[pos | 2] << 8 | DATA[pos | 3], + DATA[pos | 4] << 24 | DATA[pos | 5] << 16 | DATA[pos | 6] << 8 | DATA[pos | 7], + DATA[pos | 8] << 24 | DATA[pos | 9] << 16 | DATA[pos | 10] << 8 | DATA[pos | 11], + DATA[pos | 12] << 24 | DATA[pos | 13] << 16 | DATA[pos | 14] << 8 | DATA[pos | 15] + ); + + DATA[pos | 0] = S0 >>> 24, + DATA[pos | 1] = S0 >>> 16 & 255, + DATA[pos | 2] = S0 >>> 8 & 255, + DATA[pos | 3] = S0 & 255, + DATA[pos | 4] = S1 >>> 24, + DATA[pos | 5] = S1 >>> 16 & 255, + DATA[pos | 6] = S1 >>> 8 & 255, + DATA[pos | 7] = S1 & 255, + DATA[pos | 8] = S2 >>> 24, + DATA[pos | 9] = S2 >>> 16 & 255, + DATA[pos | 10] = S2 >>> 8 & 255, + DATA[pos | 11] = S2 & 255, + DATA[pos | 12] = S3 >>> 24, + DATA[pos | 13] = S3 >>> 16 & 255, + DATA[pos | 14] = S3 >>> 8 & 255, + DATA[pos | 15] = S3 & 255; + + ret = (ret + 16) | 0, + pos = (pos + 16) | 0, + len = (len - 16) | 0; + } + + return ret | 0; + } + + /** + * Calculates MAC of the supplied data. + * @instance + * @memberof AES_asm + * @param {number} mode - block cipher mode (see {@link AES_asm} mode constants) + * @param {number} pos - offset of the data being processed + * @param {number} len - length of the data being processed + * @return {number} Actual amount of data have been processed. + */ + function mac(mode, pos, len) { + mode = mode | 0; + pos = pos | 0; + len = len | 0; + + var ret = 0; + + if (pos & 15) return -1; + + while ((len | 0) >= 16) { + _mac_modes[mode & 1]( + DATA[pos | 0] << 24 | DATA[pos | 1] << 16 | DATA[pos | 2] << 8 | DATA[pos | 3], + DATA[pos | 4] << 24 | DATA[pos | 5] << 16 | DATA[pos | 6] << 8 | DATA[pos | 7], + DATA[pos | 8] << 24 | DATA[pos | 9] << 16 | DATA[pos | 10] << 8 | DATA[pos | 11], + DATA[pos | 12] << 24 | DATA[pos | 13] << 16 | DATA[pos | 14] << 8 | DATA[pos | 15] + ); + + ret = (ret + 16) | 0, + pos = (pos + 16) | 0, + len = (len - 16) | 0; + } + + return ret | 0; + } + + /** + * AES cipher modes table (virual methods) + */ + var _cipher_modes = [_ecb_enc, _ecb_dec, _cbc_enc, _cbc_dec, _cfb_enc, _cfb_dec, _ofb, _ctr]; + + /** + * AES MAC modes table (virual methods) + */ + var _mac_modes = [_cbc_enc, _gcm_mac]; + + /** + * Asm.js module exports + */ + return { + set_rounds: set_rounds, + set_state: set_state, + set_iv: set_iv, + set_nonce: set_nonce, + set_mask: set_mask, + set_counter: set_counter, + get_state: get_state, + get_iv: get_iv, + gcm_init: gcm_init, + cipher: cipher, + mac: mac, + }; + }(stdlib, foreign, buffer); + + asm.set_key = set_key; + + return asm; + }; + + /** + * AES enciphering mode constants + * @enum {number} + * @const + */ + wrapper.ENC = { + ECB: 0, + CBC: 2, + CFB: 4, + OFB: 6, + CTR: 7, + }, + + /** + * AES deciphering mode constants + * @enum {number} + * @const + */ + wrapper.DEC = { + ECB: 1, + CBC: 3, + CFB: 5, + OFB: 6, + CTR: 7, + }, + + /** + * AES MAC mode constants + * @enum {number} + * @const + */ + wrapper.MAC = { + CBC: 0, + GCM: 1, + }; + + /** + * Heap data offset + * @type {number} + * @const + */ + wrapper.HEAP_DATA = 0x4000; + + return wrapper; + }(); + + function is_bytes(a) { + return a instanceof Uint8Array; + } + function _heap_init(heap, heapSize) { + const size = heap ? heap.byteLength : heapSize || 65536; + if (size & 0xfff || size <= 0) + throw new Error('heap size must be a positive integer and a multiple of 4096'); + heap = heap || new Uint8Array(new ArrayBuffer(size)); + return heap; + } + function _heap_write(heap, hpos, data, dpos, dlen) { + const hlen = heap.length - hpos; + const wlen = hlen < dlen ? hlen : dlen; + heap.set(data.subarray(dpos, dpos + wlen), hpos); + return wlen; + } + function joinBytes(...arg) { + const totalLenght = arg.reduce((sum, curr) => sum + curr.length, 0); + const ret = new Uint8Array(totalLenght); + let cursor = 0; + for (let i = 0; i < arg.length; i++) { + ret.set(arg[i], cursor); + cursor += arg[i].length; + } + return ret; + } + + class IllegalStateError extends Error { + constructor(...args) { + super(...args); + } + } + class IllegalArgumentError extends Error { + constructor(...args) { + super(...args); + } + } + class SecurityError extends Error { + constructor(...args) { + super(...args); + } + } + + const heap_pool = []; + const asm_pool = []; + class AES { + constructor(key, iv, padding = true, mode, heap, asm) { + this.pos = 0; + this.len = 0; + this.mode = mode; + // The AES object state + this.pos = 0; + this.len = 0; + this.key = key; + this.iv = iv; + this.padding = padding; + // The AES "worker" + this.acquire_asm(heap, asm); + } + acquire_asm(heap, asm) { + if (this.heap === undefined || this.asm === undefined) { + this.heap = heap || heap_pool.pop() || _heap_init().subarray(AES_asm.HEAP_DATA); + this.asm = asm || asm_pool.pop() || new AES_asm(null, this.heap.buffer); + this.reset(this.key, this.iv); + } + return { heap: this.heap, asm: this.asm }; + } + release_asm() { + if (this.heap !== undefined && this.asm !== undefined) { + heap_pool.push(this.heap); + asm_pool.push(this.asm); + } + this.heap = undefined; + this.asm = undefined; + } + reset(key, iv) { + const { asm } = this.acquire_asm(); + // Key + const keylen = key.length; + if (keylen !== 16 && keylen !== 24 && keylen !== 32) + throw new IllegalArgumentError('illegal key size'); + const keyview = new DataView(key.buffer, key.byteOffset, key.byteLength); + asm.set_key(keylen >> 2, keyview.getUint32(0), keyview.getUint32(4), keyview.getUint32(8), keyview.getUint32(12), keylen > 16 ? keyview.getUint32(16) : 0, keylen > 16 ? keyview.getUint32(20) : 0, keylen > 24 ? keyview.getUint32(24) : 0, keylen > 24 ? keyview.getUint32(28) : 0); + // IV + if (iv !== undefined) { + if (iv.length !== 16) + throw new IllegalArgumentError('illegal iv size'); + let ivview = new DataView(iv.buffer, iv.byteOffset, iv.byteLength); + asm.set_iv(ivview.getUint32(0), ivview.getUint32(4), ivview.getUint32(8), ivview.getUint32(12)); + } + else { + asm.set_iv(0, 0, 0, 0); + } + } + AES_Encrypt_process(data) { + if (!is_bytes(data)) + throw new TypeError("data isn't of expected type"); + let { heap, asm } = this.acquire_asm(); + let amode = AES_asm.ENC[this.mode]; + let hpos = AES_asm.HEAP_DATA; + let pos = this.pos; + let len = this.len; + let dpos = 0; + let dlen = data.length || 0; + let rpos = 0; + let rlen = (len + dlen) & -16; + let wlen = 0; + let result = new Uint8Array(rlen); + while (dlen > 0) { + wlen = _heap_write(heap, pos + len, data, dpos, dlen); + len += wlen; + dpos += wlen; + dlen -= wlen; + wlen = asm.cipher(amode, hpos + pos, len); + if (wlen) + result.set(heap.subarray(pos, pos + wlen), rpos); + rpos += wlen; + if (wlen < len) { + pos += wlen; + len -= wlen; + } + else { + pos = 0; + len = 0; + } + } + this.pos = pos; + this.len = len; + return result; + } + AES_Encrypt_finish() { + let { heap, asm } = this.acquire_asm(); + let amode = AES_asm.ENC[this.mode]; + let hpos = AES_asm.HEAP_DATA; + let pos = this.pos; + let len = this.len; + let plen = 16 - (len % 16); + let rlen = len; + if (this.hasOwnProperty('padding')) { + if (this.padding) { + for (let p = 0; p < plen; ++p) { + heap[pos + len + p] = plen; + } + len += plen; + rlen = len; + } + else if (len % 16) { + throw new IllegalArgumentError('data length must be a multiple of the block size'); + } + } + else { + len += plen; + } + const result = new Uint8Array(rlen); + if (len) + asm.cipher(amode, hpos + pos, len); + if (rlen) + result.set(heap.subarray(pos, pos + rlen)); + this.pos = 0; + this.len = 0; + this.release_asm(); + return result; + } + AES_Decrypt_process(data) { + if (!is_bytes(data)) + throw new TypeError("data isn't of expected type"); + let { heap, asm } = this.acquire_asm(); + let amode = AES_asm.DEC[this.mode]; + let hpos = AES_asm.HEAP_DATA; + let pos = this.pos; + let len = this.len; + let dpos = 0; + let dlen = data.length || 0; + let rpos = 0; + let rlen = (len + dlen) & -16; + let plen = 0; + let wlen = 0; + if (this.padding) { + plen = len + dlen - rlen || 16; + rlen -= plen; + } + const result = new Uint8Array(rlen); + while (dlen > 0) { + wlen = _heap_write(heap, pos + len, data, dpos, dlen); + len += wlen; + dpos += wlen; + dlen -= wlen; + wlen = asm.cipher(amode, hpos + pos, len - (!dlen ? plen : 0)); + if (wlen) + result.set(heap.subarray(pos, pos + wlen), rpos); + rpos += wlen; + if (wlen < len) { + pos += wlen; + len -= wlen; + } + else { + pos = 0; + len = 0; + } + } + this.pos = pos; + this.len = len; + return result; + } + AES_Decrypt_finish() { + let { heap, asm } = this.acquire_asm(); + let amode = AES_asm.DEC[this.mode]; + let hpos = AES_asm.HEAP_DATA; + let pos = this.pos; + let len = this.len; + let rlen = len; + if (len > 0) { + if (len % 16) { + if (this.hasOwnProperty('padding')) { + throw new IllegalArgumentError('data length must be a multiple of the block size'); + } + else { + len += 16 - (len % 16); + } + } + asm.cipher(amode, hpos + pos, len); + if (this.hasOwnProperty('padding') && this.padding) { + let pad = heap[pos + rlen - 1]; + if (pad < 1 || pad > 16 || pad > rlen) + throw new SecurityError('bad padding'); + let pcheck = 0; + for (let i = pad; i > 1; i--) + pcheck |= pad ^ heap[pos + rlen - i]; + if (pcheck) + throw new SecurityError('bad padding'); + rlen -= pad; + } + } + const result = new Uint8Array(rlen); + if (rlen > 0) { + result.set(heap.subarray(pos, pos + rlen)); + } + this.pos = 0; + this.len = 0; + this.release_asm(); + return result; + } + } + + class AES_ECB { + static encrypt(data, key, padding = false) { + return new AES_ECB(key, padding).encrypt(data); + } + static decrypt(data, key, padding = false) { + return new AES_ECB(key, padding).decrypt(data); + } + constructor(key, padding = false, aes) { + this.aes = aes ? aes : new AES(key, undefined, padding, 'ECB'); + } + encrypt(data) { + const r1 = this.aes.AES_Encrypt_process(data); + const r2 = this.aes.AES_Encrypt_finish(); + return joinBytes(r1, r2); + } + decrypt(data) { + const r1 = this.aes.AES_Decrypt_process(data); + const r2 = this.aes.AES_Decrypt_finish(); + return joinBytes(r1, r2); + } + } + + /** + * Javascript AES implementation. + * This is used as fallback if the native Crypto APIs are not available. + */ + function aes(length) { + const C = function(key) { + const aesECB = new AES_ECB(key); + + this.encrypt = function(block) { + return aesECB.encrypt(block); + }; + + this.decrypt = function(block) { + return aesECB.decrypt(block); + }; + }; + + C.blockSize = C.prototype.blockSize = 16; + C.keySize = C.prototype.keySize = length / 8; + + return C; + } + + //Paul Tero, July 2001 + //http://www.tero.co.uk/des/ + // + //Optimised for performance with large blocks by Michael Hayworth, November 2001 + //http://www.netdealing.com + // + // Modified by Recurity Labs GmbH + + //THIS SOFTWARE IS PROVIDED "AS IS" AND + //ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + //IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + //ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + //FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + //DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + //OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + //HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + //LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + //OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + //SUCH DAMAGE. + + //des + //this takes the key, the message, and whether to encrypt or decrypt + + function des(keys, message, encrypt, mode, iv, padding) { + //declaring this locally speeds things up a bit + const spfunction1 = [ + 0x1010400, 0, 0x10000, 0x1010404, 0x1010004, 0x10404, 0x4, 0x10000, 0x400, 0x1010400, + 0x1010404, 0x400, 0x1000404, 0x1010004, 0x1000000, 0x4, 0x404, 0x1000400, 0x1000400, 0x10400, 0x10400, 0x1010000, + 0x1010000, 0x1000404, 0x10004, 0x1000004, 0x1000004, 0x10004, 0, 0x404, 0x10404, 0x1000000, 0x10000, 0x1010404, 0x4, + 0x1010000, 0x1010400, 0x1000000, 0x1000000, 0x400, 0x1010004, 0x10000, 0x10400, 0x1000004, 0x400, 0x4, 0x1000404, + 0x10404, 0x1010404, 0x10004, 0x1010000, 0x1000404, 0x1000004, 0x404, 0x10404, 0x1010400, 0x404, 0x1000400, + 0x1000400, 0, 0x10004, 0x10400, 0, 0x1010004 + ]; + const spfunction2 = [ + -0x7fef7fe0, -0x7fff8000, 0x8000, 0x108020, 0x100000, 0x20, -0x7fefffe0, -0x7fff7fe0, + -0x7fffffe0, -0x7fef7fe0, -0x7fef8000, -0x80000000, -0x7fff8000, 0x100000, 0x20, -0x7fefffe0, 0x108000, 0x100020, + -0x7fff7fe0, 0, -0x80000000, 0x8000, 0x108020, -0x7ff00000, 0x100020, -0x7fffffe0, 0, 0x108000, 0x8020, -0x7fef8000, + -0x7ff00000, 0x8020, 0, 0x108020, -0x7fefffe0, 0x100000, -0x7fff7fe0, -0x7ff00000, -0x7fef8000, 0x8000, -0x7ff00000, + -0x7fff8000, 0x20, -0x7fef7fe0, 0x108020, 0x20, 0x8000, -0x80000000, 0x8020, -0x7fef8000, 0x100000, -0x7fffffe0, + 0x100020, -0x7fff7fe0, -0x7fffffe0, 0x100020, 0x108000, 0, -0x7fff8000, 0x8020, -0x80000000, -0x7fefffe0, + -0x7fef7fe0, 0x108000 + ]; + const spfunction3 = [ + 0x208, 0x8020200, 0, 0x8020008, 0x8000200, 0, 0x20208, 0x8000200, 0x20008, 0x8000008, + 0x8000008, 0x20000, 0x8020208, 0x20008, 0x8020000, 0x208, 0x8000000, 0x8, 0x8020200, 0x200, 0x20200, 0x8020000, + 0x8020008, 0x20208, 0x8000208, 0x20200, 0x20000, 0x8000208, 0x8, 0x8020208, 0x200, 0x8000000, 0x8020200, 0x8000000, + 0x20008, 0x208, 0x20000, 0x8020200, 0x8000200, 0, 0x200, 0x20008, 0x8020208, 0x8000200, 0x8000008, 0x200, 0, + 0x8020008, 0x8000208, 0x20000, 0x8000000, 0x8020208, 0x8, 0x20208, 0x20200, 0x8000008, 0x8020000, 0x8000208, 0x208, + 0x8020000, 0x20208, 0x8, 0x8020008, 0x20200 + ]; + const spfunction4 = [ + 0x802001, 0x2081, 0x2081, 0x80, 0x802080, 0x800081, 0x800001, 0x2001, 0, 0x802000, + 0x802000, 0x802081, 0x81, 0, 0x800080, 0x800001, 0x1, 0x2000, 0x800000, 0x802001, 0x80, 0x800000, 0x2001, 0x2080, + 0x800081, 0x1, 0x2080, 0x800080, 0x2000, 0x802080, 0x802081, 0x81, 0x800080, 0x800001, 0x802000, 0x802081, 0x81, 0, + 0, 0x802000, 0x2080, 0x800080, 0x800081, 0x1, 0x802001, 0x2081, 0x2081, 0x80, 0x802081, 0x81, 0x1, 0x2000, 0x800001, + 0x2001, 0x802080, 0x800081, 0x2001, 0x2080, 0x800000, 0x802001, 0x80, 0x800000, 0x2000, 0x802080 + ]; + const spfunction5 = [ + 0x100, 0x2080100, 0x2080000, 0x42000100, 0x80000, 0x100, 0x40000000, 0x2080000, + 0x40080100, 0x80000, 0x2000100, 0x40080100, 0x42000100, 0x42080000, 0x80100, 0x40000000, 0x2000000, 0x40080000, + 0x40080000, 0, 0x40000100, 0x42080100, 0x42080100, 0x2000100, 0x42080000, 0x40000100, 0, 0x42000000, 0x2080100, + 0x2000000, 0x42000000, 0x80100, 0x80000, 0x42000100, 0x100, 0x2000000, 0x40000000, 0x2080000, 0x42000100, + 0x40080100, 0x2000100, 0x40000000, 0x42080000, 0x2080100, 0x40080100, 0x100, 0x2000000, 0x42080000, 0x42080100, + 0x80100, 0x42000000, 0x42080100, 0x2080000, 0, 0x40080000, 0x42000000, 0x80100, 0x2000100, 0x40000100, 0x80000, 0, + 0x40080000, 0x2080100, 0x40000100 + ]; + const spfunction6 = [ + 0x20000010, 0x20400000, 0x4000, 0x20404010, 0x20400000, 0x10, 0x20404010, 0x400000, + 0x20004000, 0x404010, 0x400000, 0x20000010, 0x400010, 0x20004000, 0x20000000, 0x4010, 0, 0x400010, 0x20004010, + 0x4000, 0x404000, 0x20004010, 0x10, 0x20400010, 0x20400010, 0, 0x404010, 0x20404000, 0x4010, 0x404000, 0x20404000, + 0x20000000, 0x20004000, 0x10, 0x20400010, 0x404000, 0x20404010, 0x400000, 0x4010, 0x20000010, 0x400000, 0x20004000, + 0x20000000, 0x4010, 0x20000010, 0x20404010, 0x404000, 0x20400000, 0x404010, 0x20404000, 0, 0x20400010, 0x10, 0x4000, + 0x20400000, 0x404010, 0x4000, 0x400010, 0x20004010, 0, 0x20404000, 0x20000000, 0x400010, 0x20004010 + ]; + const spfunction7 = [ + 0x200000, 0x4200002, 0x4000802, 0, 0x800, 0x4000802, 0x200802, 0x4200800, 0x4200802, + 0x200000, 0, 0x4000002, 0x2, 0x4000000, 0x4200002, 0x802, 0x4000800, 0x200802, 0x200002, 0x4000800, 0x4000002, + 0x4200000, 0x4200800, 0x200002, 0x4200000, 0x800, 0x802, 0x4200802, 0x200800, 0x2, 0x4000000, 0x200800, 0x4000000, + 0x200800, 0x200000, 0x4000802, 0x4000802, 0x4200002, 0x4200002, 0x2, 0x200002, 0x4000000, 0x4000800, 0x200000, + 0x4200800, 0x802, 0x200802, 0x4200800, 0x802, 0x4000002, 0x4200802, 0x4200000, 0x200800, 0, 0x2, 0x4200802, 0, + 0x200802, 0x4200000, 0x800, 0x4000002, 0x4000800, 0x800, 0x200002 + ]; + const spfunction8 = [ + 0x10001040, 0x1000, 0x40000, 0x10041040, 0x10000000, 0x10001040, 0x40, 0x10000000, + 0x40040, 0x10040000, 0x10041040, 0x41000, 0x10041000, 0x41040, 0x1000, 0x40, 0x10040000, 0x10000040, 0x10001000, + 0x1040, 0x41000, 0x40040, 0x10040040, 0x10041000, 0x1040, 0, 0, 0x10040040, 0x10000040, 0x10001000, 0x41040, + 0x40000, 0x41040, 0x40000, 0x10041000, 0x1000, 0x40, 0x10040040, 0x1000, 0x41040, 0x10001000, 0x40, 0x10000040, + 0x10040000, 0x10040040, 0x10000000, 0x40000, 0x10001040, 0, 0x10041040, 0x40040, 0x10000040, 0x10040000, 0x10001000, + 0x10001040, 0, 0x10041040, 0x41000, 0x41000, 0x1040, 0x1040, 0x40040, 0x10000000, 0x10041000 + ]; + + //create the 16 or 48 subkeys we will need + let m = 0; + let i; + let j; + let temp; + let right1; + let right2; + let left; + let right; + let looping; + let cbcleft; + let cbcleft2; + let cbcright; + let cbcright2; + let endloop; + let loopinc; + let len = message.length; + + //set up the loops for single and triple des + const iterations = keys.length === 32 ? 3 : 9; //single or triple des + if (iterations === 3) { + looping = encrypt ? [0, 32, 2] : [30, -2, -2]; + } else { + looping = encrypt ? [0, 32, 2, 62, 30, -2, 64, 96, 2] : [94, 62, -2, 32, 64, 2, 30, -2, -2]; + } + + //pad the message depending on the padding parameter + //only add padding if encrypting - note that you need to use the same padding option for both encrypt and decrypt + if (encrypt) { + message = desAddPadding(message, padding); + len = message.length; + } + + //store the result here + let result = new Uint8Array(len); + let k = 0; + + if (mode === 1) { //CBC mode + cbcleft = (iv[m++] << 24) | (iv[m++] << 16) | (iv[m++] << 8) | iv[m++]; + cbcright = (iv[m++] << 24) | (iv[m++] << 16) | (iv[m++] << 8) | iv[m++]; + m = 0; + } + + //loop through each 64 bit chunk of the message + while (m < len) { + left = (message[m++] << 24) | (message[m++] << 16) | (message[m++] << 8) | message[m++]; + right = (message[m++] << 24) | (message[m++] << 16) | (message[m++] << 8) | message[m++]; + + //for Cipher Block Chaining mode, xor the message with the previous result + if (mode === 1) { + if (encrypt) { + left ^= cbcleft; + right ^= cbcright; + } else { + cbcleft2 = cbcleft; + cbcright2 = cbcright; + cbcleft = left; + cbcright = right; + } + } + + //first each 64 but chunk of the message must be permuted according to IP + temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; + right ^= temp; + left ^= (temp << 4); + temp = ((left >>> 16) ^ right) & 0x0000ffff; + right ^= temp; + left ^= (temp << 16); + temp = ((right >>> 2) ^ left) & 0x33333333; + left ^= temp; + right ^= (temp << 2); + temp = ((right >>> 8) ^ left) & 0x00ff00ff; + left ^= temp; + right ^= (temp << 8); + temp = ((left >>> 1) ^ right) & 0x55555555; + right ^= temp; + left ^= (temp << 1); + + left = ((left << 1) | (left >>> 31)); + right = ((right << 1) | (right >>> 31)); + + //do this either 1 or 3 times for each chunk of the message + for (j = 0; j < iterations; j += 3) { + endloop = looping[j + 1]; + loopinc = looping[j + 2]; + //now go through and perform the encryption or decryption + for (i = looping[j]; i !== endloop; i += loopinc) { //for efficiency + right1 = right ^ keys[i]; + right2 = ((right >>> 4) | (right << 28)) ^ keys[i + 1]; + //the result is attained by passing these bytes through the S selection functions + temp = left; + left = right; + right = temp ^ (spfunction2[(right1 >>> 24) & 0x3f] | spfunction4[(right1 >>> 16) & 0x3f] | spfunction6[(right1 >>> + 8) & 0x3f] | spfunction8[right1 & 0x3f] | spfunction1[(right2 >>> 24) & 0x3f] | spfunction3[(right2 >>> 16) & + 0x3f] | spfunction5[(right2 >>> 8) & 0x3f] | spfunction7[right2 & 0x3f]); + } + temp = left; + left = right; + right = temp; //unreverse left and right + } //for either 1 or 3 iterations + + //move then each one bit to the right + left = ((left >>> 1) | (left << 31)); + right = ((right >>> 1) | (right << 31)); + + //now perform IP-1, which is IP in the opposite direction + temp = ((left >>> 1) ^ right) & 0x55555555; + right ^= temp; + left ^= (temp << 1); + temp = ((right >>> 8) ^ left) & 0x00ff00ff; + left ^= temp; + right ^= (temp << 8); + temp = ((right >>> 2) ^ left) & 0x33333333; + left ^= temp; + right ^= (temp << 2); + temp = ((left >>> 16) ^ right) & 0x0000ffff; + right ^= temp; + left ^= (temp << 16); + temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; + right ^= temp; + left ^= (temp << 4); + + //for Cipher Block Chaining mode, xor the message with the previous result + if (mode === 1) { + if (encrypt) { + cbcleft = left; + cbcright = right; + } else { + left ^= cbcleft2; + right ^= cbcright2; + } + } + + result[k++] = (left >>> 24); + result[k++] = ((left >>> 16) & 0xff); + result[k++] = ((left >>> 8) & 0xff); + result[k++] = (left & 0xff); + result[k++] = (right >>> 24); + result[k++] = ((right >>> 16) & 0xff); + result[k++] = ((right >>> 8) & 0xff); + result[k++] = (right & 0xff); + } //for every 8 characters, or 64 bits in the message + + //only remove padding if decrypting - note that you need to use the same padding option for both encrypt and decrypt + if (!encrypt) { + result = desRemovePadding(result, padding); + } + + return result; + } //end of des + + + //desCreateKeys + //this takes as input a 64 bit key (even though only 56 bits are used) + //as an array of 2 integers, and returns 16 48 bit keys + + function desCreateKeys(key) { + //declaring this locally speeds things up a bit + const pc2bytes0 = [ + 0, 0x4, 0x20000000, 0x20000004, 0x10000, 0x10004, 0x20010000, 0x20010004, 0x200, 0x204, + 0x20000200, 0x20000204, 0x10200, 0x10204, 0x20010200, 0x20010204 + ]; + const pc2bytes1 = [ + 0, 0x1, 0x100000, 0x100001, 0x4000000, 0x4000001, 0x4100000, 0x4100001, 0x100, 0x101, 0x100100, + 0x100101, 0x4000100, 0x4000101, 0x4100100, 0x4100101 + ]; + const pc2bytes2 = [ + 0, 0x8, 0x800, 0x808, 0x1000000, 0x1000008, 0x1000800, 0x1000808, 0, 0x8, 0x800, 0x808, + 0x1000000, 0x1000008, 0x1000800, 0x1000808 + ]; + const pc2bytes3 = [ + 0, 0x200000, 0x8000000, 0x8200000, 0x2000, 0x202000, 0x8002000, 0x8202000, 0x20000, 0x220000, + 0x8020000, 0x8220000, 0x22000, 0x222000, 0x8022000, 0x8222000 + ]; + const pc2bytes4 = [ + 0, 0x40000, 0x10, 0x40010, 0, 0x40000, 0x10, 0x40010, 0x1000, 0x41000, 0x1010, 0x41010, 0x1000, + 0x41000, 0x1010, 0x41010 + ]; + const pc2bytes5 = [ + 0, 0x400, 0x20, 0x420, 0, 0x400, 0x20, 0x420, 0x2000000, 0x2000400, 0x2000020, 0x2000420, + 0x2000000, 0x2000400, 0x2000020, 0x2000420 + ]; + const pc2bytes6 = [ + 0, 0x10000000, 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002, 0, 0x10000000, + 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002 + ]; + const pc2bytes7 = [ + 0, 0x10000, 0x800, 0x10800, 0x20000000, 0x20010000, 0x20000800, 0x20010800, 0x20000, 0x30000, + 0x20800, 0x30800, 0x20020000, 0x20030000, 0x20020800, 0x20030800 + ]; + const pc2bytes8 = [ + 0, 0x40000, 0, 0x40000, 0x2, 0x40002, 0x2, 0x40002, 0x2000000, 0x2040000, 0x2000000, 0x2040000, + 0x2000002, 0x2040002, 0x2000002, 0x2040002 + ]; + const pc2bytes9 = [ + 0, 0x10000000, 0x8, 0x10000008, 0, 0x10000000, 0x8, 0x10000008, 0x400, 0x10000400, 0x408, + 0x10000408, 0x400, 0x10000400, 0x408, 0x10000408 + ]; + const pc2bytes10 = [ + 0, 0x20, 0, 0x20, 0x100000, 0x100020, 0x100000, 0x100020, 0x2000, 0x2020, 0x2000, 0x2020, + 0x102000, 0x102020, 0x102000, 0x102020 + ]; + const pc2bytes11 = [ + 0, 0x1000000, 0x200, 0x1000200, 0x200000, 0x1200000, 0x200200, 0x1200200, 0x4000000, 0x5000000, + 0x4000200, 0x5000200, 0x4200000, 0x5200000, 0x4200200, 0x5200200 + ]; + const pc2bytes12 = [ + 0, 0x1000, 0x8000000, 0x8001000, 0x80000, 0x81000, 0x8080000, 0x8081000, 0x10, 0x1010, + 0x8000010, 0x8001010, 0x80010, 0x81010, 0x8080010, 0x8081010 + ]; + const pc2bytes13 = [0, 0x4, 0x100, 0x104, 0, 0x4, 0x100, 0x104, 0x1, 0x5, 0x101, 0x105, 0x1, 0x5, 0x101, 0x105]; + + //how many iterations (1 for des, 3 for triple des) + const iterations = key.length > 8 ? 3 : 1; //changed by Paul 16/6/2007 to use Triple DES for 9+ byte keys + //stores the return keys + const keys = new Array(32 * iterations); + //now define the left shifts which need to be done + const shifts = [0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0]; + //other variables + let lefttemp; + let righttemp; + let m = 0; + let n = 0; + let temp; + + for (let j = 0; j < iterations; j++) { //either 1 or 3 iterations + let left = (key[m++] << 24) | (key[m++] << 16) | (key[m++] << 8) | key[m++]; + let right = (key[m++] << 24) | (key[m++] << 16) | (key[m++] << 8) | key[m++]; + + temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; + right ^= temp; + left ^= (temp << 4); + temp = ((right >>> -16) ^ left) & 0x0000ffff; + left ^= temp; + right ^= (temp << -16); + temp = ((left >>> 2) ^ right) & 0x33333333; + right ^= temp; + left ^= (temp << 2); + temp = ((right >>> -16) ^ left) & 0x0000ffff; + left ^= temp; + right ^= (temp << -16); + temp = ((left >>> 1) ^ right) & 0x55555555; + right ^= temp; + left ^= (temp << 1); + temp = ((right >>> 8) ^ left) & 0x00ff00ff; + left ^= temp; + right ^= (temp << 8); + temp = ((left >>> 1) ^ right) & 0x55555555; + right ^= temp; + left ^= (temp << 1); + + //the right side needs to be shifted and to get the last four bits of the left side + temp = (left << 8) | ((right >>> 20) & 0x000000f0); + //left needs to be put upside down + left = (right << 24) | ((right << 8) & 0xff0000) | ((right >>> 8) & 0xff00) | ((right >>> 24) & 0xf0); + right = temp; + + //now go through and perform these shifts on the left and right keys + for (let i = 0; i < shifts.length; i++) { + //shift the keys either one or two bits to the left + if (shifts[i]) { + left = (left << 2) | (left >>> 26); + right = (right << 2) | (right >>> 26); + } else { + left = (left << 1) | (left >>> 27); + right = (right << 1) | (right >>> 27); + } + left &= -0xf; + right &= -0xf; + + //now apply PC-2, in such a way that E is easier when encrypting or decrypting + //this conversion will look like PC-2 except only the last 6 bits of each byte are used + //rather than 48 consecutive bits and the order of lines will be according to + //how the S selection functions will be applied: S2, S4, S6, S8, S1, S3, S5, S7 + lefttemp = pc2bytes0[left >>> 28] | pc2bytes1[(left >>> 24) & 0xf] | pc2bytes2[(left >>> 20) & 0xf] | pc2bytes3[( + left >>> 16) & 0xf] | pc2bytes4[(left >>> 12) & 0xf] | pc2bytes5[(left >>> 8) & 0xf] | pc2bytes6[(left >>> 4) & + 0xf]; + righttemp = pc2bytes7[right >>> 28] | pc2bytes8[(right >>> 24) & 0xf] | pc2bytes9[(right >>> 20) & 0xf] | + pc2bytes10[(right >>> 16) & 0xf] | pc2bytes11[(right >>> 12) & 0xf] | pc2bytes12[(right >>> 8) & 0xf] | + pc2bytes13[(right >>> 4) & 0xf]; + temp = ((righttemp >>> 16) ^ lefttemp) & 0x0000ffff; + keys[n++] = lefttemp ^ temp; + keys[n++] = righttemp ^ (temp << 16); + } + } //for each iterations + //return the keys we've created + return keys; + } //end of desCreateKeys + + + function desAddPadding(message, padding) { + const padLength = 8 - (message.length % 8); + + let pad; + if (padding === 2 && (padLength < 8)) { //pad the message with spaces + pad = ' '.charCodeAt(0); + } else if (padding === 1) { //PKCS7 padding + pad = padLength; + } else if (!padding && (padLength < 8)) { //pad the message out with null bytes + pad = 0; + } else if (padLength === 8) { + return message; + } else { + throw new Error('des: invalid padding'); + } + + const paddedMessage = new Uint8Array(message.length + padLength); + for (let i = 0; i < message.length; i++) { + paddedMessage[i] = message[i]; + } + for (let j = 0; j < padLength; j++) { + paddedMessage[message.length + j] = pad; + } + + return paddedMessage; + } + + function desRemovePadding(message, padding) { + let padLength = null; + let pad; + if (padding === 2) { // space padded + pad = ' '.charCodeAt(0); + } else if (padding === 1) { // PKCS7 + padLength = message[message.length - 1]; + } else if (!padding) { // null padding + pad = 0; + } else { + throw new Error('des: invalid padding'); + } + + if (!padLength) { + padLength = 1; + while (message[message.length - padLength] === pad) { + padLength++; + } + padLength--; + } + + return message.subarray(0, message.length - padLength); + } + + // added by Recurity Labs + + function TripleDES(key) { + this.key = []; + + for (let i = 0; i < 3; i++) { + this.key.push(new Uint8Array(key.subarray(i * 8, (i * 8) + 8))); + } + + this.encrypt = function(block) { + return des( + desCreateKeys(this.key[2]), + des( + desCreateKeys(this.key[1]), + des( + desCreateKeys(this.key[0]), + block, true, 0, null, null + ), + false, 0, null, null + ), true, 0, null, null + ); + }; + } + + TripleDES.keySize = TripleDES.prototype.keySize = 24; + TripleDES.blockSize = TripleDES.prototype.blockSize = 8; + + // This is "original" DES + + function DES(key) { + this.key = key; + + this.encrypt = function(block, padding) { + const keys = desCreateKeys(this.key); + return des(keys, block, true, 0, null, padding); + }; + + this.decrypt = function(block, padding) { + const keys = desCreateKeys(this.key); + return des(keys, block, false, 0, null, padding); + }; + } + + // Use of this source code is governed by a BSD-style + // license that can be found in the LICENSE file. + + // Copyright 2010 pjacobs@xeekr.com . All rights reserved. + + // Modified by Recurity Labs GmbH + + // fixed/modified by Herbert Hanewinkel, www.haneWIN.de + // check www.haneWIN.de for the latest version + + // cast5.js is a Javascript implementation of CAST-128, as defined in RFC 2144. + // CAST-128 is a common OpenPGP cipher. + + + // CAST5 constructor + + function OpenPGPSymEncCAST5() { + this.BlockSize = 8; + this.KeySize = 16; + + this.setKey = function(key) { + this.masking = new Array(16); + this.rotate = new Array(16); + + this.reset(); + + if (key.length === this.KeySize) { + this.keySchedule(key); + } else { + throw new Error('CAST-128: keys must be 16 bytes'); + } + return true; + }; + + this.reset = function() { + for (let i = 0; i < 16; i++) { + this.masking[i] = 0; + this.rotate[i] = 0; + } + }; + + this.getBlockSize = function() { + return this.BlockSize; + }; + + this.encrypt = function(src) { + const dst = new Array(src.length); + + for (let i = 0; i < src.length; i += 8) { + let l = (src[i] << 24) | (src[i + 1] << 16) | (src[i + 2] << 8) | src[i + 3]; + let r = (src[i + 4] << 24) | (src[i + 5] << 16) | (src[i + 6] << 8) | src[i + 7]; + let t; + + t = r; + r = l ^ f1(r, this.masking[0], this.rotate[0]); + l = t; + t = r; + r = l ^ f2(r, this.masking[1], this.rotate[1]); + l = t; + t = r; + r = l ^ f3(r, this.masking[2], this.rotate[2]); + l = t; + t = r; + r = l ^ f1(r, this.masking[3], this.rotate[3]); + l = t; + + t = r; + r = l ^ f2(r, this.masking[4], this.rotate[4]); + l = t; + t = r; + r = l ^ f3(r, this.masking[5], this.rotate[5]); + l = t; + t = r; + r = l ^ f1(r, this.masking[6], this.rotate[6]); + l = t; + t = r; + r = l ^ f2(r, this.masking[7], this.rotate[7]); + l = t; + + t = r; + r = l ^ f3(r, this.masking[8], this.rotate[8]); + l = t; + t = r; + r = l ^ f1(r, this.masking[9], this.rotate[9]); + l = t; + t = r; + r = l ^ f2(r, this.masking[10], this.rotate[10]); + l = t; + t = r; + r = l ^ f3(r, this.masking[11], this.rotate[11]); + l = t; + + t = r; + r = l ^ f1(r, this.masking[12], this.rotate[12]); + l = t; + t = r; + r = l ^ f2(r, this.masking[13], this.rotate[13]); + l = t; + t = r; + r = l ^ f3(r, this.masking[14], this.rotate[14]); + l = t; + t = r; + r = l ^ f1(r, this.masking[15], this.rotate[15]); + l = t; + + dst[i] = (r >>> 24) & 255; + dst[i + 1] = (r >>> 16) & 255; + dst[i + 2] = (r >>> 8) & 255; + dst[i + 3] = r & 255; + dst[i + 4] = (l >>> 24) & 255; + dst[i + 5] = (l >>> 16) & 255; + dst[i + 6] = (l >>> 8) & 255; + dst[i + 7] = l & 255; + } + + return dst; + }; + + this.decrypt = function(src) { + const dst = new Array(src.length); + + for (let i = 0; i < src.length; i += 8) { + let l = (src[i] << 24) | (src[i + 1] << 16) | (src[i + 2] << 8) | src[i + 3]; + let r = (src[i + 4] << 24) | (src[i + 5] << 16) | (src[i + 6] << 8) | src[i + 7]; + let t; + + t = r; + r = l ^ f1(r, this.masking[15], this.rotate[15]); + l = t; + t = r; + r = l ^ f3(r, this.masking[14], this.rotate[14]); + l = t; + t = r; + r = l ^ f2(r, this.masking[13], this.rotate[13]); + l = t; + t = r; + r = l ^ f1(r, this.masking[12], this.rotate[12]); + l = t; + + t = r; + r = l ^ f3(r, this.masking[11], this.rotate[11]); + l = t; + t = r; + r = l ^ f2(r, this.masking[10], this.rotate[10]); + l = t; + t = r; + r = l ^ f1(r, this.masking[9], this.rotate[9]); + l = t; + t = r; + r = l ^ f3(r, this.masking[8], this.rotate[8]); + l = t; + + t = r; + r = l ^ f2(r, this.masking[7], this.rotate[7]); + l = t; + t = r; + r = l ^ f1(r, this.masking[6], this.rotate[6]); + l = t; + t = r; + r = l ^ f3(r, this.masking[5], this.rotate[5]); + l = t; + t = r; + r = l ^ f2(r, this.masking[4], this.rotate[4]); + l = t; + + t = r; + r = l ^ f1(r, this.masking[3], this.rotate[3]); + l = t; + t = r; + r = l ^ f3(r, this.masking[2], this.rotate[2]); + l = t; + t = r; + r = l ^ f2(r, this.masking[1], this.rotate[1]); + l = t; + t = r; + r = l ^ f1(r, this.masking[0], this.rotate[0]); + l = t; + + dst[i] = (r >>> 24) & 255; + dst[i + 1] = (r >>> 16) & 255; + dst[i + 2] = (r >>> 8) & 255; + dst[i + 3] = r & 255; + dst[i + 4] = (l >>> 24) & 255; + dst[i + 5] = (l >> 16) & 255; + dst[i + 6] = (l >> 8) & 255; + dst[i + 7] = l & 255; + } + + return dst; + }; + const scheduleA = new Array(4); + + scheduleA[0] = new Array(4); + scheduleA[0][0] = [4, 0, 0xd, 0xf, 0xc, 0xe, 0x8]; + scheduleA[0][1] = [5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa]; + scheduleA[0][2] = [6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9]; + scheduleA[0][3] = [7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb]; + + scheduleA[1] = new Array(4); + scheduleA[1][0] = [0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0]; + scheduleA[1][1] = [1, 4, 0, 2, 1, 3, 16 + 2]; + scheduleA[1][2] = [2, 5, 7, 6, 5, 4, 16 + 1]; + scheduleA[1][3] = [3, 7, 0xa, 9, 0xb, 8, 16 + 3]; + + scheduleA[2] = new Array(4); + scheduleA[2][0] = [4, 0, 0xd, 0xf, 0xc, 0xe, 8]; + scheduleA[2][1] = [5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa]; + scheduleA[2][2] = [6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9]; + scheduleA[2][3] = [7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb]; + + + scheduleA[3] = new Array(4); + scheduleA[3][0] = [0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0]; + scheduleA[3][1] = [1, 4, 0, 2, 1, 3, 16 + 2]; + scheduleA[3][2] = [2, 5, 7, 6, 5, 4, 16 + 1]; + scheduleA[3][3] = [3, 7, 0xa, 9, 0xb, 8, 16 + 3]; + + const scheduleB = new Array(4); + + scheduleB[0] = new Array(4); + scheduleB[0][0] = [16 + 8, 16 + 9, 16 + 7, 16 + 6, 16 + 2]; + scheduleB[0][1] = [16 + 0xa, 16 + 0xb, 16 + 5, 16 + 4, 16 + 6]; + scheduleB[0][2] = [16 + 0xc, 16 + 0xd, 16 + 3, 16 + 2, 16 + 9]; + scheduleB[0][3] = [16 + 0xe, 16 + 0xf, 16 + 1, 16 + 0, 16 + 0xc]; + + scheduleB[1] = new Array(4); + scheduleB[1][0] = [3, 2, 0xc, 0xd, 8]; + scheduleB[1][1] = [1, 0, 0xe, 0xf, 0xd]; + scheduleB[1][2] = [7, 6, 8, 9, 3]; + scheduleB[1][3] = [5, 4, 0xa, 0xb, 7]; + + + scheduleB[2] = new Array(4); + scheduleB[2][0] = [16 + 3, 16 + 2, 16 + 0xc, 16 + 0xd, 16 + 9]; + scheduleB[2][1] = [16 + 1, 16 + 0, 16 + 0xe, 16 + 0xf, 16 + 0xc]; + scheduleB[2][2] = [16 + 7, 16 + 6, 16 + 8, 16 + 9, 16 + 2]; + scheduleB[2][3] = [16 + 5, 16 + 4, 16 + 0xa, 16 + 0xb, 16 + 6]; + + + scheduleB[3] = new Array(4); + scheduleB[3][0] = [8, 9, 7, 6, 3]; + scheduleB[3][1] = [0xa, 0xb, 5, 4, 7]; + scheduleB[3][2] = [0xc, 0xd, 3, 2, 8]; + scheduleB[3][3] = [0xe, 0xf, 1, 0, 0xd]; + + // changed 'in' to 'inn' (in javascript 'in' is a reserved word) + this.keySchedule = function(inn) { + const t = new Array(8); + const k = new Array(32); + + let j; + + for (let i = 0; i < 4; i++) { + j = i * 4; + t[i] = (inn[j] << 24) | (inn[j + 1] << 16) | (inn[j + 2] << 8) | inn[j + 3]; + } + + const x = [6, 7, 4, 5]; + let ki = 0; + let w; + + for (let half = 0; half < 2; half++) { + for (let round = 0; round < 4; round++) { + for (j = 0; j < 4; j++) { + const a = scheduleA[round][j]; + w = t[a[1]]; + + w ^= sBox[4][(t[a[2] >>> 2] >>> (24 - 8 * (a[2] & 3))) & 0xff]; + w ^= sBox[5][(t[a[3] >>> 2] >>> (24 - 8 * (a[3] & 3))) & 0xff]; + w ^= sBox[6][(t[a[4] >>> 2] >>> (24 - 8 * (a[4] & 3))) & 0xff]; + w ^= sBox[7][(t[a[5] >>> 2] >>> (24 - 8 * (a[5] & 3))) & 0xff]; + w ^= sBox[x[j]][(t[a[6] >>> 2] >>> (24 - 8 * (a[6] & 3))) & 0xff]; + t[a[0]] = w; + } + + for (j = 0; j < 4; j++) { + const b = scheduleB[round][j]; + w = sBox[4][(t[b[0] >>> 2] >>> (24 - 8 * (b[0] & 3))) & 0xff]; + + w ^= sBox[5][(t[b[1] >>> 2] >>> (24 - 8 * (b[1] & 3))) & 0xff]; + w ^= sBox[6][(t[b[2] >>> 2] >>> (24 - 8 * (b[2] & 3))) & 0xff]; + w ^= sBox[7][(t[b[3] >>> 2] >>> (24 - 8 * (b[3] & 3))) & 0xff]; + w ^= sBox[4 + j][(t[b[4] >>> 2] >>> (24 - 8 * (b[4] & 3))) & 0xff]; + k[ki] = w; + ki++; + } + } + } + + for (let i = 0; i < 16; i++) { + this.masking[i] = k[i]; + this.rotate[i] = k[16 + i] & 0x1f; + } + }; + + // These are the three 'f' functions. See RFC 2144, section 2.2. + + function f1(d, m, r) { + const t = m + d; + const I = (t << r) | (t >>> (32 - r)); + return ((sBox[0][I >>> 24] ^ sBox[1][(I >>> 16) & 255]) - sBox[2][(I >>> 8) & 255]) + sBox[3][I & 255]; + } + + function f2(d, m, r) { + const t = m ^ d; + const I = (t << r) | (t >>> (32 - r)); + return ((sBox[0][I >>> 24] - sBox[1][(I >>> 16) & 255]) + sBox[2][(I >>> 8) & 255]) ^ sBox[3][I & 255]; + } + + function f3(d, m, r) { + const t = m - d; + const I = (t << r) | (t >>> (32 - r)); + return ((sBox[0][I >>> 24] + sBox[1][(I >>> 16) & 255]) ^ sBox[2][(I >>> 8) & 255]) - sBox[3][I & 255]; + } + + const sBox = new Array(8); + sBox[0] = [ + 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949, + 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, + 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, + 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0, + 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, + 0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935, + 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d, + 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, + 0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe, + 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3, + 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, + 0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291, + 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779, + 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, + 0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, + 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d, + 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, + 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, + 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c, + 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, + 0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d, + 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96, + 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, + 0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, + 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, + 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, + 0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, + 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872, + 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, + 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, + 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9, + 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf + ]; + + sBox[1] = [ + 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651, + 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, + 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, + 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806, + 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, + 0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359, + 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b, + 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, + 0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34, + 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb, + 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, + 0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860, + 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b, + 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, + 0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, + 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, + 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, + 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, + 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f, + 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, + 0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6, + 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58, + 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, + 0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, + 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6, + 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, + 0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6, + 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f, + 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, + 0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, + 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9, + 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1 + ]; + + sBox[2] = [ + 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90, + 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, + 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, + 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240, + 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, + 0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, + 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71, + 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, + 0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, + 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15, + 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, + 0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176, + 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148, + 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, + 0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, + 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e, + 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, + 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, + 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a, + 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, + 0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, + 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5, + 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, + 0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536, + 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, + 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, + 0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69, + 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, + 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, + 0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, + 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a, + 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783 + ]; + + sBox[3] = [ + 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1, + 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, + 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, + 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121, + 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, + 0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, + 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb, + 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, + 0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d, + 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6, + 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, + 0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003, + 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, + 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, + 0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, + 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a, + 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, + 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, + 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26, + 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, + 0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7, + 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417, + 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, + 0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2, + 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, + 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, + 0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, + 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, + 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, + 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, + 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282, + 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2 + ]; + + sBox[4] = [ + 0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f, + 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, + 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, + 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02, + 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, + 0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7, + 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9, + 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, + 0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774, + 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655, + 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, + 0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910, + 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1, + 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, + 0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, + 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f, + 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, + 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, + 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3, + 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, + 0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4, + 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2, + 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, + 0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5, + 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, + 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, + 0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801, + 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, + 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, + 0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, + 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8, + 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4 + ]; + + sBox[5] = [ + 0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac, + 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, + 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, + 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98, + 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, + 0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3, + 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd, + 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, + 0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9, + 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54, + 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, + 0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc, + 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf, + 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, + 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, + 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289, + 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, + 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, + 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b, + 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, + 0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13, + 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976, + 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, + 0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891, + 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da, + 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, + 0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084, + 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25, + 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, + 0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, + 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd, + 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f + ]; + + sBox[6] = [ + 0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f, + 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, + 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, + 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19, + 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, + 0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516, + 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88, + 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, + 0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756, + 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, + 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, + 0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688, + 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28, + 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, + 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, + 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, + 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, + 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, + 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566, + 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, + 0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962, + 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e, + 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, + 0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c, + 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, + 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, + 0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be, + 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767, + 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, + 0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, + 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c, + 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3 + ]; + + sBox[7] = [ + 0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5, + 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, + 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, + 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d, + 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, + 0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862, + 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc, + 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, + 0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e, + 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039, + 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, + 0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42, + 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5, + 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, + 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, + 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c, + 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, + 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, + 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70, + 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, + 0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c, + 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3, + 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, + 0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101, + 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f, + 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, + 0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a, + 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c, + 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, + 0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, + 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82, + 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e + ]; + } + + function CAST5(key) { + this.cast5 = new OpenPGPSymEncCAST5(); + this.cast5.setKey(key); + + this.encrypt = function(block) { + return this.cast5.encrypt(block); + }; + } + + CAST5.blockSize = CAST5.prototype.blockSize = 8; + CAST5.keySize = CAST5.prototype.keySize = 16; + + /* eslint-disable no-mixed-operators, no-fallthrough */ + + + /* Modified by Recurity Labs GmbH + * + * Cipher.js + * A block-cipher algorithm implementation on JavaScript + * See Cipher.readme.txt for further information. + * + * Copyright(c) 2009 Atsushi Oka [ http://oka.nu/ ] + * This script file is distributed under the LGPL + * + * ACKNOWLEDGMENT + * + * The main subroutines are written by Michiel van Everdingen. + * + * Michiel van Everdingen + * http://home.versatel.nl/MAvanEverdingen/index.html + * + * All rights for these routines are reserved to Michiel van Everdingen. + * + */ + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //Math + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + const MAXINT = 0xFFFFFFFF; + + function rotw(w, n) { + return (w << n | w >>> (32 - n)) & MAXINT; + } + + function getW(a, i) { + return a[i] | a[i + 1] << 8 | a[i + 2] << 16 | a[i + 3] << 24; + } + + function setW(a, i, w) { + a.splice(i, 4, w & 0xFF, (w >>> 8) & 0xFF, (w >>> 16) & 0xFF, (w >>> 24) & 0xFF); + } + + function getB(x, n) { + return (x >>> (n * 8)) & 0xFF; + } + + // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Twofish + // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + function createTwofish() { + // + let keyBytes = null; + let dataBytes = null; + let dataOffset = -1; + // var dataLength = -1; + // var idx2 = -1; + // + + let tfsKey = []; + let tfsM = [ + [], + [], + [], + [] + ]; + + function tfsInit(key) { + keyBytes = key; + let i; + let a; + let b; + let c; + let d; + const meKey = []; + const moKey = []; + const inKey = []; + let kLen; + const sKey = []; + let f01; + let f5b; + let fef; + + const q0 = [ + [8, 1, 7, 13, 6, 15, 3, 2, 0, 11, 5, 9, 14, 12, 10, 4], + [2, 8, 11, 13, 15, 7, 6, 14, 3, 1, 9, 4, 0, 10, 12, 5] + ]; + const q1 = [ + [14, 12, 11, 8, 1, 2, 3, 5, 15, 4, 10, 6, 7, 0, 9, 13], + [1, 14, 2, 11, 4, 12, 3, 7, 6, 13, 10, 5, 15, 9, 0, 8] + ]; + const q2 = [ + [11, 10, 5, 14, 6, 13, 9, 0, 12, 8, 15, 3, 2, 4, 7, 1], + [4, 12, 7, 5, 1, 6, 9, 10, 0, 14, 13, 8, 2, 11, 3, 15] + ]; + const q3 = [ + [13, 7, 15, 4, 1, 2, 6, 14, 9, 11, 3, 0, 8, 5, 12, 10], + [11, 9, 5, 1, 12, 3, 13, 14, 6, 4, 7, 15, 2, 0, 8, 10] + ]; + const ror4 = [0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15]; + const ashx = [0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 5, 14, 7]; + const q = [ + [], + [] + ]; + const m = [ + [], + [], + [], + [] + ]; + + function ffm5b(x) { + return x ^ (x >> 2) ^ [0, 90, 180, 238][x & 3]; + } + + function ffmEf(x) { + return x ^ (x >> 1) ^ (x >> 2) ^ [0, 238, 180, 90][x & 3]; + } + + function mdsRem(p, q) { + let i; + let t; + let u; + for (i = 0; i < 8; i++) { + t = q >>> 24; + q = ((q << 8) & MAXINT) | p >>> 24; + p = (p << 8) & MAXINT; + u = t << 1; + if (t & 128) { + u ^= 333; + } + q ^= t ^ (u << 16); + u ^= t >>> 1; + if (t & 1) { + u ^= 166; + } + q ^= u << 24 | u << 8; + } + return q; + } + + function qp(n, x) { + const a = x >> 4; + const b = x & 15; + const c = q0[n][a ^ b]; + const d = q1[n][ror4[b] ^ ashx[a]]; + return q3[n][ror4[d] ^ ashx[c]] << 4 | q2[n][c ^ d]; + } + + function hFun(x, key) { + let a = getB(x, 0); + let b = getB(x, 1); + let c = getB(x, 2); + let d = getB(x, 3); + switch (kLen) { + case 4: + a = q[1][a] ^ getB(key[3], 0); + b = q[0][b] ^ getB(key[3], 1); + c = q[0][c] ^ getB(key[3], 2); + d = q[1][d] ^ getB(key[3], 3); + case 3: + a = q[1][a] ^ getB(key[2], 0); + b = q[1][b] ^ getB(key[2], 1); + c = q[0][c] ^ getB(key[2], 2); + d = q[0][d] ^ getB(key[2], 3); + case 2: + a = q[0][q[0][a] ^ getB(key[1], 0)] ^ getB(key[0], 0); + b = q[0][q[1][b] ^ getB(key[1], 1)] ^ getB(key[0], 1); + c = q[1][q[0][c] ^ getB(key[1], 2)] ^ getB(key[0], 2); + d = q[1][q[1][d] ^ getB(key[1], 3)] ^ getB(key[0], 3); + } + return m[0][a] ^ m[1][b] ^ m[2][c] ^ m[3][d]; + } + + keyBytes = keyBytes.slice(0, 32); + i = keyBytes.length; + while (i !== 16 && i !== 24 && i !== 32) { + keyBytes[i++] = 0; + } + + for (i = 0; i < keyBytes.length; i += 4) { + inKey[i >> 2] = getW(keyBytes, i); + } + for (i = 0; i < 256; i++) { + q[0][i] = qp(0, i); + q[1][i] = qp(1, i); + } + for (i = 0; i < 256; i++) { + f01 = q[1][i]; + f5b = ffm5b(f01); + fef = ffmEf(f01); + m[0][i] = f01 + (f5b << 8) + (fef << 16) + (fef << 24); + m[2][i] = f5b + (fef << 8) + (f01 << 16) + (fef << 24); + f01 = q[0][i]; + f5b = ffm5b(f01); + fef = ffmEf(f01); + m[1][i] = fef + (fef << 8) + (f5b << 16) + (f01 << 24); + m[3][i] = f5b + (f01 << 8) + (fef << 16) + (f5b << 24); + } + + kLen = inKey.length / 2; + for (i = 0; i < kLen; i++) { + a = inKey[i + i]; + meKey[i] = a; + b = inKey[i + i + 1]; + moKey[i] = b; + sKey[kLen - i - 1] = mdsRem(a, b); + } + for (i = 0; i < 40; i += 2) { + a = 0x1010101 * i; + b = a + 0x1010101; + a = hFun(a, meKey); + b = rotw(hFun(b, moKey), 8); + tfsKey[i] = (a + b) & MAXINT; + tfsKey[i + 1] = rotw(a + 2 * b, 9); + } + for (i = 0; i < 256; i++) { + a = b = c = d = i; + switch (kLen) { + case 4: + a = q[1][a] ^ getB(sKey[3], 0); + b = q[0][b] ^ getB(sKey[3], 1); + c = q[0][c] ^ getB(sKey[3], 2); + d = q[1][d] ^ getB(sKey[3], 3); + case 3: + a = q[1][a] ^ getB(sKey[2], 0); + b = q[1][b] ^ getB(sKey[2], 1); + c = q[0][c] ^ getB(sKey[2], 2); + d = q[0][d] ^ getB(sKey[2], 3); + case 2: + tfsM[0][i] = m[0][q[0][q[0][a] ^ getB(sKey[1], 0)] ^ getB(sKey[0], 0)]; + tfsM[1][i] = m[1][q[0][q[1][b] ^ getB(sKey[1], 1)] ^ getB(sKey[0], 1)]; + tfsM[2][i] = m[2][q[1][q[0][c] ^ getB(sKey[1], 2)] ^ getB(sKey[0], 2)]; + tfsM[3][i] = m[3][q[1][q[1][d] ^ getB(sKey[1], 3)] ^ getB(sKey[0], 3)]; + } + } + } + + function tfsG0(x) { + return tfsM[0][getB(x, 0)] ^ tfsM[1][getB(x, 1)] ^ tfsM[2][getB(x, 2)] ^ tfsM[3][getB(x, 3)]; + } + + function tfsG1(x) { + return tfsM[0][getB(x, 3)] ^ tfsM[1][getB(x, 0)] ^ tfsM[2][getB(x, 1)] ^ tfsM[3][getB(x, 2)]; + } + + function tfsFrnd(r, blk) { + let a = tfsG0(blk[0]); + let b = tfsG1(blk[1]); + blk[2] = rotw(blk[2] ^ (a + b + tfsKey[4 * r + 8]) & MAXINT, 31); + blk[3] = rotw(blk[3], 1) ^ (a + 2 * b + tfsKey[4 * r + 9]) & MAXINT; + a = tfsG0(blk[2]); + b = tfsG1(blk[3]); + blk[0] = rotw(blk[0] ^ (a + b + tfsKey[4 * r + 10]) & MAXINT, 31); + blk[1] = rotw(blk[1], 1) ^ (a + 2 * b + tfsKey[4 * r + 11]) & MAXINT; + } + + function tfsIrnd(i, blk) { + let a = tfsG0(blk[0]); + let b = tfsG1(blk[1]); + blk[2] = rotw(blk[2], 1) ^ (a + b + tfsKey[4 * i + 10]) & MAXINT; + blk[3] = rotw(blk[3] ^ (a + 2 * b + tfsKey[4 * i + 11]) & MAXINT, 31); + a = tfsG0(blk[2]); + b = tfsG1(blk[3]); + blk[0] = rotw(blk[0], 1) ^ (a + b + tfsKey[4 * i + 8]) & MAXINT; + blk[1] = rotw(blk[1] ^ (a + 2 * b + tfsKey[4 * i + 9]) & MAXINT, 31); + } + + function tfsClose() { + tfsKey = []; + tfsM = [ + [], + [], + [], + [] + ]; + } + + function tfsEncrypt(data, offset) { + dataBytes = data; + dataOffset = offset; + const blk = [getW(dataBytes, dataOffset) ^ tfsKey[0], + getW(dataBytes, dataOffset + 4) ^ tfsKey[1], + getW(dataBytes, dataOffset + 8) ^ tfsKey[2], + getW(dataBytes, dataOffset + 12) ^ tfsKey[3]]; + for (let j = 0; j < 8; j++) { + tfsFrnd(j, blk); + } + setW(dataBytes, dataOffset, blk[2] ^ tfsKey[4]); + setW(dataBytes, dataOffset + 4, blk[3] ^ tfsKey[5]); + setW(dataBytes, dataOffset + 8, blk[0] ^ tfsKey[6]); + setW(dataBytes, dataOffset + 12, blk[1] ^ tfsKey[7]); + dataOffset += 16; + return dataBytes; + } + + function tfsDecrypt(data, offset) { + dataBytes = data; + dataOffset = offset; + const blk = [getW(dataBytes, dataOffset) ^ tfsKey[4], + getW(dataBytes, dataOffset + 4) ^ tfsKey[5], + getW(dataBytes, dataOffset + 8) ^ tfsKey[6], + getW(dataBytes, dataOffset + 12) ^ tfsKey[7]]; + for (let j = 7; j >= 0; j--) { + tfsIrnd(j, blk); + } + setW(dataBytes, dataOffset, blk[2] ^ tfsKey[0]); + setW(dataBytes, dataOffset + 4, blk[3] ^ tfsKey[1]); + setW(dataBytes, dataOffset + 8, blk[0] ^ tfsKey[2]); + setW(dataBytes, dataOffset + 12, blk[1] ^ tfsKey[3]); + dataOffset += 16; + } + + // added by Recurity Labs + + function tfsFinal() { + return dataBytes; + } + + return { + name: 'twofish', + blocksize: 128 / 8, + open: tfsInit, + close: tfsClose, + encrypt: tfsEncrypt, + decrypt: tfsDecrypt, + // added by Recurity Labs + finalize: tfsFinal + }; + } + + // added by Recurity Labs + + function TF(key) { + this.tf = createTwofish(); + this.tf.open(Array.from(key), 0); + + this.encrypt = function(block) { + return this.tf.encrypt(Array.from(block), 0); + }; + } + + TF.keySize = TF.prototype.keySize = 32; + TF.blockSize = TF.prototype.blockSize = 16; + + /* Modified by Recurity Labs GmbH + * + * Originally written by nklein software (nklein.com) + */ + + /* + * Javascript implementation based on Bruce Schneier's reference implementation. + * + * + * The constructor doesn't do much of anything. It's just here + * so we can start defining properties and methods and such. + */ + function Blowfish() {} + + /* + * Declare the block size so that protocols know what size + * Initialization Vector (IV) they will need. + */ + Blowfish.prototype.BLOCKSIZE = 8; + + /* + * These are the default SBOXES. + */ + Blowfish.prototype.SBOXES = [ + [ + 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, + 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, + 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658, + 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, + 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, + 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, + 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6, + 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, + 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, + 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, + 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, + 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, + 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, + 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, + 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, + 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, + 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, + 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, + 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, + 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, + 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, + 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, + 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, + 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, + 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, + 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, + 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8, + 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, + 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, + 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, + 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, + 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, + 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, + 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, + 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, + 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, + 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, + 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, + 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, + 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, + 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, + 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, + 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a + ], + [ + 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, + 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, + 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, + 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, + 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, + 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, + 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, + 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, + 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, + 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, + 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, + 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, + 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, + 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, + 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, + 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, + 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, + 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, + 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, + 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, + 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, + 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, + 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, + 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, + 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, + 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, + 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, + 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, + 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, + 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, + 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, + 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, + 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, + 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, + 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, + 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, + 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, + 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, + 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, + 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, + 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, + 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, + 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7 + ], + [ + 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, + 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, + 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, + 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, + 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, + 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, + 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, + 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, + 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, + 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, + 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, + 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, + 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, + 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, + 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, + 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, + 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, + 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, + 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74, + 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, + 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, + 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, + 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, + 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, + 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, + 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, + 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, + 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, + 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, + 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, + 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, + 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, + 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, + 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, + 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, + 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, + 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, + 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, + 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, + 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, + 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, + 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, + 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0 + ], + [ + 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, + 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, + 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, + 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, + 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, + 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, + 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, + 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, + 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, + 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, + 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, + 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, + 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, + 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, + 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5, + 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, + 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, + 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, + 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd, + 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, + 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, + 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, + 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc, + 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, + 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, + 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, + 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, + 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, + 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, + 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, + 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, + 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, + 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, + 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, + 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623, + 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, + 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, + 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, + 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3, + 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, + 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, + 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, + 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 + ] + ]; + + //* + //* This is the default PARRAY + //* + Blowfish.prototype.PARRAY = [ + 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, + 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, + 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b + ]; + + //* + //* This is the number of rounds the cipher will go + //* + Blowfish.prototype.NN = 16; + + //* + //* This function is needed to get rid of problems + //* with the high-bit getting set. If we don't do + //* this, then sometimes ( aa & 0x00FFFFFFFF ) is not + //* equal to ( bb & 0x00FFFFFFFF ) even when they + //* agree bit-for-bit for the first 32 bits. + //* + Blowfish.prototype._clean = function(xx) { + if (xx < 0) { + const yy = xx & 0x7FFFFFFF; + xx = yy + 0x80000000; + } + return xx; + }; + + //* + //* This is the mixing function that uses the sboxes + //* + Blowfish.prototype._F = function(xx) { + let yy; + + const dd = xx & 0x00FF; + xx >>>= 8; + const cc = xx & 0x00FF; + xx >>>= 8; + const bb = xx & 0x00FF; + xx >>>= 8; + const aa = xx & 0x00FF; + + yy = this.sboxes[0][aa] + this.sboxes[1][bb]; + yy ^= this.sboxes[2][cc]; + yy += this.sboxes[3][dd]; + + return yy; + }; + + //* + //* This method takes an array with two values, left and right + //* and does NN rounds of Blowfish on them. + //* + Blowfish.prototype._encryptBlock = function(vals) { + let dataL = vals[0]; + let dataR = vals[1]; + + let ii; + + for (ii = 0; ii < this.NN; ++ii) { + dataL ^= this.parray[ii]; + dataR = this._F(dataL) ^ dataR; + + const tmp = dataL; + dataL = dataR; + dataR = tmp; + } + + dataL ^= this.parray[this.NN + 0]; + dataR ^= this.parray[this.NN + 1]; + + vals[0] = this._clean(dataR); + vals[1] = this._clean(dataL); + }; + + //* + //* This method takes a vector of numbers and turns them + //* into long words so that they can be processed by the + //* real algorithm. + //* + //* Maybe I should make the real algorithm above take a vector + //* instead. That will involve more looping, but it won't require + //* the F() method to deconstruct the vector. + //* + Blowfish.prototype.encryptBlock = function(vector) { + let ii; + const vals = [0, 0]; + const off = this.BLOCKSIZE / 2; + for (ii = 0; ii < this.BLOCKSIZE / 2; ++ii) { + vals[0] = (vals[0] << 8) | (vector[ii + 0] & 0x00FF); + vals[1] = (vals[1] << 8) | (vector[ii + off] & 0x00FF); + } + + this._encryptBlock(vals); + + const ret = []; + for (ii = 0; ii < this.BLOCKSIZE / 2; ++ii) { + ret[ii + 0] = ((vals[0] >>> (24 - 8 * (ii))) & 0x00FF); + ret[ii + off] = ((vals[1] >>> (24 - 8 * (ii))) & 0x00FF); + // vals[ 0 ] = ( vals[ 0 ] >>> 8 ); + // vals[ 1 ] = ( vals[ 1 ] >>> 8 ); + } + + return ret; + }; + + //* + //* This method takes an array with two values, left and right + //* and undoes NN rounds of Blowfish on them. + //* + Blowfish.prototype._decryptBlock = function(vals) { + let dataL = vals[0]; + let dataR = vals[1]; + + let ii; + + for (ii = this.NN + 1; ii > 1; --ii) { + dataL ^= this.parray[ii]; + dataR = this._F(dataL) ^ dataR; + + const tmp = dataL; + dataL = dataR; + dataR = tmp; + } + + dataL ^= this.parray[1]; + dataR ^= this.parray[0]; + + vals[0] = this._clean(dataR); + vals[1] = this._clean(dataL); + }; + + //* + //* This method takes a key array and initializes the + //* sboxes and parray for this encryption. + //* + Blowfish.prototype.init = function(key) { + let ii; + let jj = 0; + + this.parray = []; + for (ii = 0; ii < this.NN + 2; ++ii) { + let data = 0x00000000; + for (let kk = 0; kk < 4; ++kk) { + data = (data << 8) | (key[jj] & 0x00FF); + if (++jj >= key.length) { + jj = 0; + } + } + this.parray[ii] = this.PARRAY[ii] ^ data; + } + + this.sboxes = []; + for (ii = 0; ii < 4; ++ii) { + this.sboxes[ii] = []; + for (jj = 0; jj < 256; ++jj) { + this.sboxes[ii][jj] = this.SBOXES[ii][jj]; + } + } + + const vals = [0x00000000, 0x00000000]; + + for (ii = 0; ii < this.NN + 2; ii += 2) { + this._encryptBlock(vals); + this.parray[ii + 0] = vals[0]; + this.parray[ii + 1] = vals[1]; + } + + for (ii = 0; ii < 4; ++ii) { + for (jj = 0; jj < 256; jj += 2) { + this._encryptBlock(vals); + this.sboxes[ii][jj + 0] = vals[0]; + this.sboxes[ii][jj + 1] = vals[1]; + } + } + }; + + // added by Recurity Labs + function BF(key) { + this.bf = new Blowfish(); + this.bf.init(key); + + this.encrypt = function(block) { + return this.bf.encryptBlock(block); + }; + } + + BF.keySize = BF.prototype.keySize = 16; + BF.blockSize = BF.prototype.blockSize = 8; + + /** + * @fileoverview Symmetric cryptography functions + * @module crypto/cipher + * @private + */ + + /** + * AES-128 encryption and decryption (ID 7) + * @function + * @param {String} key - 128-bit key + * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} + * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} + * @returns {Object} + */ + const aes128 = aes(128); + /** + * AES-128 Block Cipher (ID 8) + * @function + * @param {String} key - 192-bit key + * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} + * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} + * @returns {Object} + */ + const aes192 = aes(192); + /** + * AES-128 Block Cipher (ID 9) + * @function + * @param {String} key - 256-bit key + * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} + * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} + * @returns {Object} + */ + const aes256 = aes(256); + // Not in OpenPGP specifications + const des$1 = DES; + /** + * Triple DES Block Cipher (ID 2) + * @function + * @param {String} key - 192-bit key + * @see {@link https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-67r2.pdf|NIST SP 800-67} + * @returns {Object} + */ + const tripledes = TripleDES; + /** + * CAST-128 Block Cipher (ID 3) + * @function + * @param {String} key - 128-bit key + * @see {@link https://tools.ietf.org/html/rfc2144|The CAST-128 Encryption Algorithm} + * @returns {Object} + */ + const cast5 = CAST5; + /** + * Twofish Block Cipher (ID 10) + * @function + * @param {String} key - 256-bit key + * @see {@link https://tools.ietf.org/html/rfc4880#ref-TWOFISH|TWOFISH} + * @returns {Object} + */ + const twofish = TF; + /** + * Blowfish Block Cipher (ID 4) + * @function + * @param {String} key - 128-bit key + * @see {@link https://tools.ietf.org/html/rfc4880#ref-BLOWFISH|BLOWFISH} + * @returns {Object} + */ + const blowfish = BF; + /** + * Not implemented + * @function + * @throws {Error} + */ + const idea = function() { + throw new Error('IDEA symmetric-key algorithm not implemented'); + }; + + var cipher = /*#__PURE__*/Object.freeze({ + __proto__: null, + aes128: aes128, + aes192: aes192, + aes256: aes256, + des: des$1, + tripledes: tripledes, + cast5: cast5, + twofish: twofish, + blowfish: blowfish, + idea: idea + }); + + var sha1_asm = function ( stdlib, foreign, buffer ) { + "use asm"; + + // SHA256 state + var H0 = 0, H1 = 0, H2 = 0, H3 = 0, H4 = 0, + TOTAL0 = 0, TOTAL1 = 0; + + // HMAC state + var I0 = 0, I1 = 0, I2 = 0, I3 = 0, I4 = 0, + O0 = 0, O1 = 0, O2 = 0, O3 = 0, O4 = 0; + + // I/O buffer + var HEAP = new stdlib.Uint8Array(buffer); + + function _core ( w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15 ) { + w0 = w0|0; + w1 = w1|0; + w2 = w2|0; + w3 = w3|0; + w4 = w4|0; + w5 = w5|0; + w6 = w6|0; + w7 = w7|0; + w8 = w8|0; + w9 = w9|0; + w10 = w10|0; + w11 = w11|0; + w12 = w12|0; + w13 = w13|0; + w14 = w14|0; + w15 = w15|0; + + var a = 0, b = 0, c = 0, d = 0, e = 0, n = 0, t = 0, + w16 = 0, w17 = 0, w18 = 0, w19 = 0, + w20 = 0, w21 = 0, w22 = 0, w23 = 0, w24 = 0, w25 = 0, w26 = 0, w27 = 0, w28 = 0, w29 = 0, + w30 = 0, w31 = 0, w32 = 0, w33 = 0, w34 = 0, w35 = 0, w36 = 0, w37 = 0, w38 = 0, w39 = 0, + w40 = 0, w41 = 0, w42 = 0, w43 = 0, w44 = 0, w45 = 0, w46 = 0, w47 = 0, w48 = 0, w49 = 0, + w50 = 0, w51 = 0, w52 = 0, w53 = 0, w54 = 0, w55 = 0, w56 = 0, w57 = 0, w58 = 0, w59 = 0, + w60 = 0, w61 = 0, w62 = 0, w63 = 0, w64 = 0, w65 = 0, w66 = 0, w67 = 0, w68 = 0, w69 = 0, + w70 = 0, w71 = 0, w72 = 0, w73 = 0, w74 = 0, w75 = 0, w76 = 0, w77 = 0, w78 = 0, w79 = 0; + + a = H0; + b = H1; + c = H2; + d = H3; + e = H4; + + // 0 + t = ( w0 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 1 + t = ( w1 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 2 + t = ( w2 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 3 + t = ( w3 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 4 + t = ( w4 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 5 + t = ( w5 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 6 + t = ( w6 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 7 + t = ( w7 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 8 + t = ( w8 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 9 + t = ( w9 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 10 + t = ( w10 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 11 + t = ( w11 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 12 + t = ( w12 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 13 + t = ( w13 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 14 + t = ( w14 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 15 + t = ( w15 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 16 + n = w13 ^ w8 ^ w2 ^ w0; + w16 = (n << 1) | (n >>> 31); + t = (w16 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 17 + n = w14 ^ w9 ^ w3 ^ w1; + w17 = (n << 1) | (n >>> 31); + t = (w17 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 18 + n = w15 ^ w10 ^ w4 ^ w2; + w18 = (n << 1) | (n >>> 31); + t = (w18 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 19 + n = w16 ^ w11 ^ w5 ^ w3; + w19 = (n << 1) | (n >>> 31); + t = (w19 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 20 + n = w17 ^ w12 ^ w6 ^ w4; + w20 = (n << 1) | (n >>> 31); + t = (w20 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 21 + n = w18 ^ w13 ^ w7 ^ w5; + w21 = (n << 1) | (n >>> 31); + t = (w21 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 22 + n = w19 ^ w14 ^ w8 ^ w6; + w22 = (n << 1) | (n >>> 31); + t = (w22 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 23 + n = w20 ^ w15 ^ w9 ^ w7; + w23 = (n << 1) | (n >>> 31); + t = (w23 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 24 + n = w21 ^ w16 ^ w10 ^ w8; + w24 = (n << 1) | (n >>> 31); + t = (w24 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 25 + n = w22 ^ w17 ^ w11 ^ w9; + w25 = (n << 1) | (n >>> 31); + t = (w25 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 26 + n = w23 ^ w18 ^ w12 ^ w10; + w26 = (n << 1) | (n >>> 31); + t = (w26 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 27 + n = w24 ^ w19 ^ w13 ^ w11; + w27 = (n << 1) | (n >>> 31); + t = (w27 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 28 + n = w25 ^ w20 ^ w14 ^ w12; + w28 = (n << 1) | (n >>> 31); + t = (w28 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 29 + n = w26 ^ w21 ^ w15 ^ w13; + w29 = (n << 1) | (n >>> 31); + t = (w29 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 30 + n = w27 ^ w22 ^ w16 ^ w14; + w30 = (n << 1) | (n >>> 31); + t = (w30 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 31 + n = w28 ^ w23 ^ w17 ^ w15; + w31 = (n << 1) | (n >>> 31); + t = (w31 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 32 + n = w29 ^ w24 ^ w18 ^ w16; + w32 = (n << 1) | (n >>> 31); + t = (w32 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 33 + n = w30 ^ w25 ^ w19 ^ w17; + w33 = (n << 1) | (n >>> 31); + t = (w33 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 34 + n = w31 ^ w26 ^ w20 ^ w18; + w34 = (n << 1) | (n >>> 31); + t = (w34 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 35 + n = w32 ^ w27 ^ w21 ^ w19; + w35 = (n << 1) | (n >>> 31); + t = (w35 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 36 + n = w33 ^ w28 ^ w22 ^ w20; + w36 = (n << 1) | (n >>> 31); + t = (w36 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 37 + n = w34 ^ w29 ^ w23 ^ w21; + w37 = (n << 1) | (n >>> 31); + t = (w37 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 38 + n = w35 ^ w30 ^ w24 ^ w22; + w38 = (n << 1) | (n >>> 31); + t = (w38 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 39 + n = w36 ^ w31 ^ w25 ^ w23; + w39 = (n << 1) | (n >>> 31); + t = (w39 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 40 + n = w37 ^ w32 ^ w26 ^ w24; + w40 = (n << 1) | (n >>> 31); + t = (w40 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 41 + n = w38 ^ w33 ^ w27 ^ w25; + w41 = (n << 1) | (n >>> 31); + t = (w41 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 42 + n = w39 ^ w34 ^ w28 ^ w26; + w42 = (n << 1) | (n >>> 31); + t = (w42 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 43 + n = w40 ^ w35 ^ w29 ^ w27; + w43 = (n << 1) | (n >>> 31); + t = (w43 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 44 + n = w41 ^ w36 ^ w30 ^ w28; + w44 = (n << 1) | (n >>> 31); + t = (w44 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 45 + n = w42 ^ w37 ^ w31 ^ w29; + w45 = (n << 1) | (n >>> 31); + t = (w45 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 46 + n = w43 ^ w38 ^ w32 ^ w30; + w46 = (n << 1) | (n >>> 31); + t = (w46 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 47 + n = w44 ^ w39 ^ w33 ^ w31; + w47 = (n << 1) | (n >>> 31); + t = (w47 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 48 + n = w45 ^ w40 ^ w34 ^ w32; + w48 = (n << 1) | (n >>> 31); + t = (w48 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 49 + n = w46 ^ w41 ^ w35 ^ w33; + w49 = (n << 1) | (n >>> 31); + t = (w49 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 50 + n = w47 ^ w42 ^ w36 ^ w34; + w50 = (n << 1) | (n >>> 31); + t = (w50 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 51 + n = w48 ^ w43 ^ w37 ^ w35; + w51 = (n << 1) | (n >>> 31); + t = (w51 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 52 + n = w49 ^ w44 ^ w38 ^ w36; + w52 = (n << 1) | (n >>> 31); + t = (w52 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 53 + n = w50 ^ w45 ^ w39 ^ w37; + w53 = (n << 1) | (n >>> 31); + t = (w53 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 54 + n = w51 ^ w46 ^ w40 ^ w38; + w54 = (n << 1) | (n >>> 31); + t = (w54 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 55 + n = w52 ^ w47 ^ w41 ^ w39; + w55 = (n << 1) | (n >>> 31); + t = (w55 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 56 + n = w53 ^ w48 ^ w42 ^ w40; + w56 = (n << 1) | (n >>> 31); + t = (w56 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 57 + n = w54 ^ w49 ^ w43 ^ w41; + w57 = (n << 1) | (n >>> 31); + t = (w57 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 58 + n = w55 ^ w50 ^ w44 ^ w42; + w58 = (n << 1) | (n >>> 31); + t = (w58 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 59 + n = w56 ^ w51 ^ w45 ^ w43; + w59 = (n << 1) | (n >>> 31); + t = (w59 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 60 + n = w57 ^ w52 ^ w46 ^ w44; + w60 = (n << 1) | (n >>> 31); + t = (w60 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 61 + n = w58 ^ w53 ^ w47 ^ w45; + w61 = (n << 1) | (n >>> 31); + t = (w61 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 62 + n = w59 ^ w54 ^ w48 ^ w46; + w62 = (n << 1) | (n >>> 31); + t = (w62 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 63 + n = w60 ^ w55 ^ w49 ^ w47; + w63 = (n << 1) | (n >>> 31); + t = (w63 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 64 + n = w61 ^ w56 ^ w50 ^ w48; + w64 = (n << 1) | (n >>> 31); + t = (w64 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 65 + n = w62 ^ w57 ^ w51 ^ w49; + w65 = (n << 1) | (n >>> 31); + t = (w65 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 66 + n = w63 ^ w58 ^ w52 ^ w50; + w66 = (n << 1) | (n >>> 31); + t = (w66 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 67 + n = w64 ^ w59 ^ w53 ^ w51; + w67 = (n << 1) | (n >>> 31); + t = (w67 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 68 + n = w65 ^ w60 ^ w54 ^ w52; + w68 = (n << 1) | (n >>> 31); + t = (w68 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 69 + n = w66 ^ w61 ^ w55 ^ w53; + w69 = (n << 1) | (n >>> 31); + t = (w69 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 70 + n = w67 ^ w62 ^ w56 ^ w54; + w70 = (n << 1) | (n >>> 31); + t = (w70 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 71 + n = w68 ^ w63 ^ w57 ^ w55; + w71 = (n << 1) | (n >>> 31); + t = (w71 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 72 + n = w69 ^ w64 ^ w58 ^ w56; + w72 = (n << 1) | (n >>> 31); + t = (w72 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 73 + n = w70 ^ w65 ^ w59 ^ w57; + w73 = (n << 1) | (n >>> 31); + t = (w73 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 74 + n = w71 ^ w66 ^ w60 ^ w58; + w74 = (n << 1) | (n >>> 31); + t = (w74 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 75 + n = w72 ^ w67 ^ w61 ^ w59; + w75 = (n << 1) | (n >>> 31); + t = (w75 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 76 + n = w73 ^ w68 ^ w62 ^ w60; + w76 = (n << 1) | (n >>> 31); + t = (w76 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 77 + n = w74 ^ w69 ^ w63 ^ w61; + w77 = (n << 1) | (n >>> 31); + t = (w77 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 78 + n = w75 ^ w70 ^ w64 ^ w62; + w78 = (n << 1) | (n >>> 31); + t = (w78 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 79 + n = w76 ^ w71 ^ w65 ^ w63; + w79 = (n << 1) | (n >>> 31); + t = (w79 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + H0 = ( H0 + a )|0; + H1 = ( H1 + b )|0; + H2 = ( H2 + c )|0; + H3 = ( H3 + d )|0; + H4 = ( H4 + e )|0; + + } + + function _core_heap ( offset ) { + offset = offset|0; + + _core( + HEAP[offset|0]<<24 | HEAP[offset|1]<<16 | HEAP[offset|2]<<8 | HEAP[offset|3], + HEAP[offset|4]<<24 | HEAP[offset|5]<<16 | HEAP[offset|6]<<8 | HEAP[offset|7], + HEAP[offset|8]<<24 | HEAP[offset|9]<<16 | HEAP[offset|10]<<8 | HEAP[offset|11], + HEAP[offset|12]<<24 | HEAP[offset|13]<<16 | HEAP[offset|14]<<8 | HEAP[offset|15], + HEAP[offset|16]<<24 | HEAP[offset|17]<<16 | HEAP[offset|18]<<8 | HEAP[offset|19], + HEAP[offset|20]<<24 | HEAP[offset|21]<<16 | HEAP[offset|22]<<8 | HEAP[offset|23], + HEAP[offset|24]<<24 | HEAP[offset|25]<<16 | HEAP[offset|26]<<8 | HEAP[offset|27], + HEAP[offset|28]<<24 | HEAP[offset|29]<<16 | HEAP[offset|30]<<8 | HEAP[offset|31], + HEAP[offset|32]<<24 | HEAP[offset|33]<<16 | HEAP[offset|34]<<8 | HEAP[offset|35], + HEAP[offset|36]<<24 | HEAP[offset|37]<<16 | HEAP[offset|38]<<8 | HEAP[offset|39], + HEAP[offset|40]<<24 | HEAP[offset|41]<<16 | HEAP[offset|42]<<8 | HEAP[offset|43], + HEAP[offset|44]<<24 | HEAP[offset|45]<<16 | HEAP[offset|46]<<8 | HEAP[offset|47], + HEAP[offset|48]<<24 | HEAP[offset|49]<<16 | HEAP[offset|50]<<8 | HEAP[offset|51], + HEAP[offset|52]<<24 | HEAP[offset|53]<<16 | HEAP[offset|54]<<8 | HEAP[offset|55], + HEAP[offset|56]<<24 | HEAP[offset|57]<<16 | HEAP[offset|58]<<8 | HEAP[offset|59], + HEAP[offset|60]<<24 | HEAP[offset|61]<<16 | HEAP[offset|62]<<8 | HEAP[offset|63] + ); + } + + // offset — multiple of 32 + function _state_to_heap ( output ) { + output = output|0; + + HEAP[output|0] = H0>>>24; + HEAP[output|1] = H0>>>16&255; + HEAP[output|2] = H0>>>8&255; + HEAP[output|3] = H0&255; + HEAP[output|4] = H1>>>24; + HEAP[output|5] = H1>>>16&255; + HEAP[output|6] = H1>>>8&255; + HEAP[output|7] = H1&255; + HEAP[output|8] = H2>>>24; + HEAP[output|9] = H2>>>16&255; + HEAP[output|10] = H2>>>8&255; + HEAP[output|11] = H2&255; + HEAP[output|12] = H3>>>24; + HEAP[output|13] = H3>>>16&255; + HEAP[output|14] = H3>>>8&255; + HEAP[output|15] = H3&255; + HEAP[output|16] = H4>>>24; + HEAP[output|17] = H4>>>16&255; + HEAP[output|18] = H4>>>8&255; + HEAP[output|19] = H4&255; + } + + function reset () { + H0 = 0x67452301; + H1 = 0xefcdab89; + H2 = 0x98badcfe; + H3 = 0x10325476; + H4 = 0xc3d2e1f0; + TOTAL0 = TOTAL1 = 0; + } + + function init ( h0, h1, h2, h3, h4, total0, total1 ) { + h0 = h0|0; + h1 = h1|0; + h2 = h2|0; + h3 = h3|0; + h4 = h4|0; + total0 = total0|0; + total1 = total1|0; + + H0 = h0; + H1 = h1; + H2 = h2; + H3 = h3; + H4 = h4; + TOTAL0 = total0; + TOTAL1 = total1; + } + + // offset — multiple of 64 + function process ( offset, length ) { + offset = offset|0; + length = length|0; + + var hashed = 0; + + if ( offset & 63 ) + return -1; + + while ( (length|0) >= 64 ) { + _core_heap(offset); + + offset = ( offset + 64 )|0; + length = ( length - 64 )|0; + + hashed = ( hashed + 64 )|0; + } + + TOTAL0 = ( TOTAL0 + hashed )|0; + if ( TOTAL0>>>0 < hashed>>>0 ) TOTAL1 = ( TOTAL1 + 1 )|0; + + return hashed|0; + } + + // offset — multiple of 64 + // output — multiple of 32 + function finish ( offset, length, output ) { + offset = offset|0; + length = length|0; + output = output|0; + + var hashed = 0, + i = 0; + + if ( offset & 63 ) + return -1; + + if ( ~output ) + if ( output & 31 ) + return -1; + + if ( (length|0) >= 64 ) { + hashed = process( offset, length )|0; + if ( (hashed|0) == -1 ) + return -1; + + offset = ( offset + hashed )|0; + length = ( length - hashed )|0; + } + + hashed = ( hashed + length )|0; + TOTAL0 = ( TOTAL0 + length )|0; + if ( TOTAL0>>>0 < length>>>0 ) TOTAL1 = (TOTAL1 + 1)|0; + + HEAP[offset|length] = 0x80; + + if ( (length|0) >= 56 ) { + for ( i = (length+1)|0; (i|0) < 64; i = (i+1)|0 ) + HEAP[offset|i] = 0x00; + _core_heap(offset); + + length = 0; + + HEAP[offset|0] = 0; + } + + for ( i = (length+1)|0; (i|0) < 59; i = (i+1)|0 ) + HEAP[offset|i] = 0; + + HEAP[offset|56] = TOTAL1>>>21&255; + HEAP[offset|57] = TOTAL1>>>13&255; + HEAP[offset|58] = TOTAL1>>>5&255; + HEAP[offset|59] = TOTAL1<<3&255 | TOTAL0>>>29; + HEAP[offset|60] = TOTAL0>>>21&255; + HEAP[offset|61] = TOTAL0>>>13&255; + HEAP[offset|62] = TOTAL0>>>5&255; + HEAP[offset|63] = TOTAL0<<3&255; + _core_heap(offset); + + if ( ~output ) + _state_to_heap(output); + + return hashed|0; + } + + function hmac_reset () { + H0 = I0; + H1 = I1; + H2 = I2; + H3 = I3; + H4 = I4; + TOTAL0 = 64; + TOTAL1 = 0; + } + + function _hmac_opad () { + H0 = O0; + H1 = O1; + H2 = O2; + H3 = O3; + H4 = O4; + TOTAL0 = 64; + TOTAL1 = 0; + } + + function hmac_init ( p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15 ) { + p0 = p0|0; + p1 = p1|0; + p2 = p2|0; + p3 = p3|0; + p4 = p4|0; + p5 = p5|0; + p6 = p6|0; + p7 = p7|0; + p8 = p8|0; + p9 = p9|0; + p10 = p10|0; + p11 = p11|0; + p12 = p12|0; + p13 = p13|0; + p14 = p14|0; + p15 = p15|0; + + // opad + reset(); + _core( + p0 ^ 0x5c5c5c5c, + p1 ^ 0x5c5c5c5c, + p2 ^ 0x5c5c5c5c, + p3 ^ 0x5c5c5c5c, + p4 ^ 0x5c5c5c5c, + p5 ^ 0x5c5c5c5c, + p6 ^ 0x5c5c5c5c, + p7 ^ 0x5c5c5c5c, + p8 ^ 0x5c5c5c5c, + p9 ^ 0x5c5c5c5c, + p10 ^ 0x5c5c5c5c, + p11 ^ 0x5c5c5c5c, + p12 ^ 0x5c5c5c5c, + p13 ^ 0x5c5c5c5c, + p14 ^ 0x5c5c5c5c, + p15 ^ 0x5c5c5c5c + ); + O0 = H0; + O1 = H1; + O2 = H2; + O3 = H3; + O4 = H4; + + // ipad + reset(); + _core( + p0 ^ 0x36363636, + p1 ^ 0x36363636, + p2 ^ 0x36363636, + p3 ^ 0x36363636, + p4 ^ 0x36363636, + p5 ^ 0x36363636, + p6 ^ 0x36363636, + p7 ^ 0x36363636, + p8 ^ 0x36363636, + p9 ^ 0x36363636, + p10 ^ 0x36363636, + p11 ^ 0x36363636, + p12 ^ 0x36363636, + p13 ^ 0x36363636, + p14 ^ 0x36363636, + p15 ^ 0x36363636 + ); + I0 = H0; + I1 = H1; + I2 = H2; + I3 = H3; + I4 = H4; + + TOTAL0 = 64; + TOTAL1 = 0; + } + + // offset — multiple of 64 + // output — multiple of 32 + function hmac_finish ( offset, length, output ) { + offset = offset|0; + length = length|0; + output = output|0; + + var t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, hashed = 0; + + if ( offset & 63 ) + return -1; + + if ( ~output ) + if ( output & 31 ) + return -1; + + hashed = finish( offset, length, -1 )|0; + t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; + + _hmac_opad(); + _core( t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672 ); + + if ( ~output ) + _state_to_heap(output); + + return hashed|0; + } + + // salt is assumed to be already processed + // offset — multiple of 64 + // output — multiple of 32 + function pbkdf2_generate_block ( offset, length, block, count, output ) { + offset = offset|0; + length = length|0; + block = block|0; + count = count|0; + output = output|0; + + var h0 = 0, h1 = 0, h2 = 0, h3 = 0, h4 = 0, + t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0; + + if ( offset & 63 ) + return -1; + + if ( ~output ) + if ( output & 31 ) + return -1; + + // pad block number into heap + // FIXME probable OOB write + HEAP[(offset+length)|0] = block>>>24; + HEAP[(offset+length+1)|0] = block>>>16&255; + HEAP[(offset+length+2)|0] = block>>>8&255; + HEAP[(offset+length+3)|0] = block&255; + + // finish first iteration + hmac_finish( offset, (length+4)|0, -1 )|0; + h0 = t0 = H0, h1 = t1 = H1, h2 = t2 = H2, h3 = t3 = H3, h4 = t4 = H4; + count = (count-1)|0; + + // perform the rest iterations + while ( (count|0) > 0 ) { + hmac_reset(); + _core( t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672 ); + t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; + + _hmac_opad(); + _core( t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672 ); + t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; + + h0 = h0 ^ H0; + h1 = h1 ^ H1; + h2 = h2 ^ H2; + h3 = h3 ^ H3; + h4 = h4 ^ H4; + + count = (count-1)|0; + } + + H0 = h0; + H1 = h1; + H2 = h2; + H3 = h3; + H4 = h4; + + if ( ~output ) + _state_to_heap(output); + + return 0; + } + + return { + // SHA1 + reset: reset, + init: init, + process: process, + finish: finish, + + // HMAC-SHA1 + hmac_reset: hmac_reset, + hmac_init: hmac_init, + hmac_finish: hmac_finish, + + // PBKDF2-HMAC-SHA1 + pbkdf2_generate_block: pbkdf2_generate_block + } + }; + + class Hash { + constructor() { + this.pos = 0; + this.len = 0; + } + reset() { + const { asm } = this.acquire_asm(); + this.result = null; + this.pos = 0; + this.len = 0; + asm.reset(); + return this; + } + process(data) { + if (this.result !== null) + throw new IllegalStateError('state must be reset before processing new data'); + const { asm, heap } = this.acquire_asm(); + let hpos = this.pos; + let hlen = this.len; + let dpos = 0; + let dlen = data.length; + let wlen = 0; + while (dlen > 0) { + wlen = _heap_write(heap, hpos + hlen, data, dpos, dlen); + hlen += wlen; + dpos += wlen; + dlen -= wlen; + wlen = asm.process(hpos, hlen); + hpos += wlen; + hlen -= wlen; + if (!hlen) + hpos = 0; + } + this.pos = hpos; + this.len = hlen; + return this; + } + finish() { + if (this.result !== null) + throw new IllegalStateError('state must be reset before processing new data'); + const { asm, heap } = this.acquire_asm(); + asm.finish(this.pos, this.len, 0); + this.result = new Uint8Array(this.HASH_SIZE); + this.result.set(heap.subarray(0, this.HASH_SIZE)); + this.pos = 0; + this.len = 0; + this.release_asm(); + return this; + } + } + + const _sha1_block_size = 64; + const _sha1_hash_size = 20; + const heap_pool$1 = []; + const asm_pool$1 = []; + class Sha1 extends Hash { + constructor() { + super(); + this.NAME = 'sha1'; + this.BLOCK_SIZE = _sha1_block_size; + this.HASH_SIZE = _sha1_hash_size; + this.acquire_asm(); + } + acquire_asm() { + if (this.heap === undefined || this.asm === undefined) { + this.heap = heap_pool$1.pop() || _heap_init(); + this.asm = asm_pool$1.pop() || sha1_asm({ Uint8Array: Uint8Array }, null, this.heap.buffer); + this.reset(); + } + return { heap: this.heap, asm: this.asm }; + } + release_asm() { + if (this.heap !== undefined && this.asm !== undefined) { + heap_pool$1.push(this.heap); + asm_pool$1.push(this.asm); + } + this.heap = undefined; + this.asm = undefined; + } + static bytes(data) { + return new Sha1().process(data).finish().result; + } + } + Sha1.NAME = 'sha1'; + Sha1.heap_pool = []; + Sha1.asm_pool = []; + Sha1.asm_function = sha1_asm; + + var sha256_asm = function ( stdlib, foreign, buffer ) { + "use asm"; + + // SHA256 state + var H0 = 0, H1 = 0, H2 = 0, H3 = 0, H4 = 0, H5 = 0, H6 = 0, H7 = 0, + TOTAL0 = 0, TOTAL1 = 0; + + // HMAC state + var I0 = 0, I1 = 0, I2 = 0, I3 = 0, I4 = 0, I5 = 0, I6 = 0, I7 = 0, + O0 = 0, O1 = 0, O2 = 0, O3 = 0, O4 = 0, O5 = 0, O6 = 0, O7 = 0; + + // I/O buffer + var HEAP = new stdlib.Uint8Array(buffer); + + function _core ( w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15 ) { + w0 = w0|0; + w1 = w1|0; + w2 = w2|0; + w3 = w3|0; + w4 = w4|0; + w5 = w5|0; + w6 = w6|0; + w7 = w7|0; + w8 = w8|0; + w9 = w9|0; + w10 = w10|0; + w11 = w11|0; + w12 = w12|0; + w13 = w13|0; + w14 = w14|0; + w15 = w15|0; + + var a = 0, b = 0, c = 0, d = 0, e = 0, f = 0, g = 0, h = 0; + + a = H0; + b = H1; + c = H2; + d = H3; + e = H4; + f = H5; + g = H6; + h = H7; + + // 0 + h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x428a2f98 )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; + + // 1 + g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x71374491 )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; + + // 2 + f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0xb5c0fbcf )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; + + // 3 + e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0xe9b5dba5 )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; + + // 4 + d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x3956c25b )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; + + // 5 + c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x59f111f1 )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; + + // 6 + b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x923f82a4 )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; + + // 7 + a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0xab1c5ed5 )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; + + // 8 + h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0xd807aa98 )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; + + // 9 + g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x12835b01 )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; + + // 10 + f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x243185be )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; + + // 11 + e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x550c7dc3 )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; + + // 12 + d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x72be5d74 )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; + + // 13 + c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x80deb1fe )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; + + // 14 + b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x9bdc06a7 )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; + + // 15 + a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0xc19bf174 )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; + + // 16 + w0 = ( ( w1>>>7 ^ w1>>>18 ^ w1>>>3 ^ w1<<25 ^ w1<<14 ) + ( w14>>>17 ^ w14>>>19 ^ w14>>>10 ^ w14<<15 ^ w14<<13 ) + w0 + w9 )|0; + h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0xe49b69c1 )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; + + // 17 + w1 = ( ( w2>>>7 ^ w2>>>18 ^ w2>>>3 ^ w2<<25 ^ w2<<14 ) + ( w15>>>17 ^ w15>>>19 ^ w15>>>10 ^ w15<<15 ^ w15<<13 ) + w1 + w10 )|0; + g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0xefbe4786 )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; + + // 18 + w2 = ( ( w3>>>7 ^ w3>>>18 ^ w3>>>3 ^ w3<<25 ^ w3<<14 ) + ( w0>>>17 ^ w0>>>19 ^ w0>>>10 ^ w0<<15 ^ w0<<13 ) + w2 + w11 )|0; + f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x0fc19dc6 )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; + + // 19 + w3 = ( ( w4>>>7 ^ w4>>>18 ^ w4>>>3 ^ w4<<25 ^ w4<<14 ) + ( w1>>>17 ^ w1>>>19 ^ w1>>>10 ^ w1<<15 ^ w1<<13 ) + w3 + w12 )|0; + e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x240ca1cc )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; + + // 20 + w4 = ( ( w5>>>7 ^ w5>>>18 ^ w5>>>3 ^ w5<<25 ^ w5<<14 ) + ( w2>>>17 ^ w2>>>19 ^ w2>>>10 ^ w2<<15 ^ w2<<13 ) + w4 + w13 )|0; + d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x2de92c6f )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; + + // 21 + w5 = ( ( w6>>>7 ^ w6>>>18 ^ w6>>>3 ^ w6<<25 ^ w6<<14 ) + ( w3>>>17 ^ w3>>>19 ^ w3>>>10 ^ w3<<15 ^ w3<<13 ) + w5 + w14 )|0; + c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x4a7484aa )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; + + // 22 + w6 = ( ( w7>>>7 ^ w7>>>18 ^ w7>>>3 ^ w7<<25 ^ w7<<14 ) + ( w4>>>17 ^ w4>>>19 ^ w4>>>10 ^ w4<<15 ^ w4<<13 ) + w6 + w15 )|0; + b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x5cb0a9dc )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; + + // 23 + w7 = ( ( w8>>>7 ^ w8>>>18 ^ w8>>>3 ^ w8<<25 ^ w8<<14 ) + ( w5>>>17 ^ w5>>>19 ^ w5>>>10 ^ w5<<15 ^ w5<<13 ) + w7 + w0 )|0; + a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x76f988da )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; + + // 24 + w8 = ( ( w9>>>7 ^ w9>>>18 ^ w9>>>3 ^ w9<<25 ^ w9<<14 ) + ( w6>>>17 ^ w6>>>19 ^ w6>>>10 ^ w6<<15 ^ w6<<13 ) + w8 + w1 )|0; + h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x983e5152 )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; + + // 25 + w9 = ( ( w10>>>7 ^ w10>>>18 ^ w10>>>3 ^ w10<<25 ^ w10<<14 ) + ( w7>>>17 ^ w7>>>19 ^ w7>>>10 ^ w7<<15 ^ w7<<13 ) + w9 + w2 )|0; + g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0xa831c66d )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; + + // 26 + w10 = ( ( w11>>>7 ^ w11>>>18 ^ w11>>>3 ^ w11<<25 ^ w11<<14 ) + ( w8>>>17 ^ w8>>>19 ^ w8>>>10 ^ w8<<15 ^ w8<<13 ) + w10 + w3 )|0; + f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0xb00327c8 )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; + + // 27 + w11 = ( ( w12>>>7 ^ w12>>>18 ^ w12>>>3 ^ w12<<25 ^ w12<<14 ) + ( w9>>>17 ^ w9>>>19 ^ w9>>>10 ^ w9<<15 ^ w9<<13 ) + w11 + w4 )|0; + e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0xbf597fc7 )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; + + // 28 + w12 = ( ( w13>>>7 ^ w13>>>18 ^ w13>>>3 ^ w13<<25 ^ w13<<14 ) + ( w10>>>17 ^ w10>>>19 ^ w10>>>10 ^ w10<<15 ^ w10<<13 ) + w12 + w5 )|0; + d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0xc6e00bf3 )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; + + // 29 + w13 = ( ( w14>>>7 ^ w14>>>18 ^ w14>>>3 ^ w14<<25 ^ w14<<14 ) + ( w11>>>17 ^ w11>>>19 ^ w11>>>10 ^ w11<<15 ^ w11<<13 ) + w13 + w6 )|0; + c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0xd5a79147 )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; + + // 30 + w14 = ( ( w15>>>7 ^ w15>>>18 ^ w15>>>3 ^ w15<<25 ^ w15<<14 ) + ( w12>>>17 ^ w12>>>19 ^ w12>>>10 ^ w12<<15 ^ w12<<13 ) + w14 + w7 )|0; + b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x06ca6351 )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; + + // 31 + w15 = ( ( w0>>>7 ^ w0>>>18 ^ w0>>>3 ^ w0<<25 ^ w0<<14 ) + ( w13>>>17 ^ w13>>>19 ^ w13>>>10 ^ w13<<15 ^ w13<<13 ) + w15 + w8 )|0; + a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x14292967 )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; + + // 32 + w0 = ( ( w1>>>7 ^ w1>>>18 ^ w1>>>3 ^ w1<<25 ^ w1<<14 ) + ( w14>>>17 ^ w14>>>19 ^ w14>>>10 ^ w14<<15 ^ w14<<13 ) + w0 + w9 )|0; + h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x27b70a85 )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; + + // 33 + w1 = ( ( w2>>>7 ^ w2>>>18 ^ w2>>>3 ^ w2<<25 ^ w2<<14 ) + ( w15>>>17 ^ w15>>>19 ^ w15>>>10 ^ w15<<15 ^ w15<<13 ) + w1 + w10 )|0; + g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x2e1b2138 )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; + + // 34 + w2 = ( ( w3>>>7 ^ w3>>>18 ^ w3>>>3 ^ w3<<25 ^ w3<<14 ) + ( w0>>>17 ^ w0>>>19 ^ w0>>>10 ^ w0<<15 ^ w0<<13 ) + w2 + w11 )|0; + f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x4d2c6dfc )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; + + // 35 + w3 = ( ( w4>>>7 ^ w4>>>18 ^ w4>>>3 ^ w4<<25 ^ w4<<14 ) + ( w1>>>17 ^ w1>>>19 ^ w1>>>10 ^ w1<<15 ^ w1<<13 ) + w3 + w12 )|0; + e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x53380d13 )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; + + // 36 + w4 = ( ( w5>>>7 ^ w5>>>18 ^ w5>>>3 ^ w5<<25 ^ w5<<14 ) + ( w2>>>17 ^ w2>>>19 ^ w2>>>10 ^ w2<<15 ^ w2<<13 ) + w4 + w13 )|0; + d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x650a7354 )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; + + // 37 + w5 = ( ( w6>>>7 ^ w6>>>18 ^ w6>>>3 ^ w6<<25 ^ w6<<14 ) + ( w3>>>17 ^ w3>>>19 ^ w3>>>10 ^ w3<<15 ^ w3<<13 ) + w5 + w14 )|0; + c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x766a0abb )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; + + // 38 + w6 = ( ( w7>>>7 ^ w7>>>18 ^ w7>>>3 ^ w7<<25 ^ w7<<14 ) + ( w4>>>17 ^ w4>>>19 ^ w4>>>10 ^ w4<<15 ^ w4<<13 ) + w6 + w15 )|0; + b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x81c2c92e )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; + + // 39 + w7 = ( ( w8>>>7 ^ w8>>>18 ^ w8>>>3 ^ w8<<25 ^ w8<<14 ) + ( w5>>>17 ^ w5>>>19 ^ w5>>>10 ^ w5<<15 ^ w5<<13 ) + w7 + w0 )|0; + a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x92722c85 )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; + + // 40 + w8 = ( ( w9>>>7 ^ w9>>>18 ^ w9>>>3 ^ w9<<25 ^ w9<<14 ) + ( w6>>>17 ^ w6>>>19 ^ w6>>>10 ^ w6<<15 ^ w6<<13 ) + w8 + w1 )|0; + h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0xa2bfe8a1 )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; + + // 41 + w9 = ( ( w10>>>7 ^ w10>>>18 ^ w10>>>3 ^ w10<<25 ^ w10<<14 ) + ( w7>>>17 ^ w7>>>19 ^ w7>>>10 ^ w7<<15 ^ w7<<13 ) + w9 + w2 )|0; + g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0xa81a664b )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; + + // 42 + w10 = ( ( w11>>>7 ^ w11>>>18 ^ w11>>>3 ^ w11<<25 ^ w11<<14 ) + ( w8>>>17 ^ w8>>>19 ^ w8>>>10 ^ w8<<15 ^ w8<<13 ) + w10 + w3 )|0; + f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0xc24b8b70 )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; + + // 43 + w11 = ( ( w12>>>7 ^ w12>>>18 ^ w12>>>3 ^ w12<<25 ^ w12<<14 ) + ( w9>>>17 ^ w9>>>19 ^ w9>>>10 ^ w9<<15 ^ w9<<13 ) + w11 + w4 )|0; + e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0xc76c51a3 )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; + + // 44 + w12 = ( ( w13>>>7 ^ w13>>>18 ^ w13>>>3 ^ w13<<25 ^ w13<<14 ) + ( w10>>>17 ^ w10>>>19 ^ w10>>>10 ^ w10<<15 ^ w10<<13 ) + w12 + w5 )|0; + d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0xd192e819 )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; + + // 45 + w13 = ( ( w14>>>7 ^ w14>>>18 ^ w14>>>3 ^ w14<<25 ^ w14<<14 ) + ( w11>>>17 ^ w11>>>19 ^ w11>>>10 ^ w11<<15 ^ w11<<13 ) + w13 + w6 )|0; + c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0xd6990624 )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; + + // 46 + w14 = ( ( w15>>>7 ^ w15>>>18 ^ w15>>>3 ^ w15<<25 ^ w15<<14 ) + ( w12>>>17 ^ w12>>>19 ^ w12>>>10 ^ w12<<15 ^ w12<<13 ) + w14 + w7 )|0; + b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0xf40e3585 )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; + + // 47 + w15 = ( ( w0>>>7 ^ w0>>>18 ^ w0>>>3 ^ w0<<25 ^ w0<<14 ) + ( w13>>>17 ^ w13>>>19 ^ w13>>>10 ^ w13<<15 ^ w13<<13 ) + w15 + w8 )|0; + a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x106aa070 )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; + + // 48 + w0 = ( ( w1>>>7 ^ w1>>>18 ^ w1>>>3 ^ w1<<25 ^ w1<<14 ) + ( w14>>>17 ^ w14>>>19 ^ w14>>>10 ^ w14<<15 ^ w14<<13 ) + w0 + w9 )|0; + h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x19a4c116 )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; + + // 49 + w1 = ( ( w2>>>7 ^ w2>>>18 ^ w2>>>3 ^ w2<<25 ^ w2<<14 ) + ( w15>>>17 ^ w15>>>19 ^ w15>>>10 ^ w15<<15 ^ w15<<13 ) + w1 + w10 )|0; + g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x1e376c08 )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; + + // 50 + w2 = ( ( w3>>>7 ^ w3>>>18 ^ w3>>>3 ^ w3<<25 ^ w3<<14 ) + ( w0>>>17 ^ w0>>>19 ^ w0>>>10 ^ w0<<15 ^ w0<<13 ) + w2 + w11 )|0; + f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x2748774c )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; + + // 51 + w3 = ( ( w4>>>7 ^ w4>>>18 ^ w4>>>3 ^ w4<<25 ^ w4<<14 ) + ( w1>>>17 ^ w1>>>19 ^ w1>>>10 ^ w1<<15 ^ w1<<13 ) + w3 + w12 )|0; + e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x34b0bcb5 )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; + + // 52 + w4 = ( ( w5>>>7 ^ w5>>>18 ^ w5>>>3 ^ w5<<25 ^ w5<<14 ) + ( w2>>>17 ^ w2>>>19 ^ w2>>>10 ^ w2<<15 ^ w2<<13 ) + w4 + w13 )|0; + d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x391c0cb3 )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; + + // 53 + w5 = ( ( w6>>>7 ^ w6>>>18 ^ w6>>>3 ^ w6<<25 ^ w6<<14 ) + ( w3>>>17 ^ w3>>>19 ^ w3>>>10 ^ w3<<15 ^ w3<<13 ) + w5 + w14 )|0; + c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x4ed8aa4a )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; + + // 54 + w6 = ( ( w7>>>7 ^ w7>>>18 ^ w7>>>3 ^ w7<<25 ^ w7<<14 ) + ( w4>>>17 ^ w4>>>19 ^ w4>>>10 ^ w4<<15 ^ w4<<13 ) + w6 + w15 )|0; + b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x5b9cca4f )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; + + // 55 + w7 = ( ( w8>>>7 ^ w8>>>18 ^ w8>>>3 ^ w8<<25 ^ w8<<14 ) + ( w5>>>17 ^ w5>>>19 ^ w5>>>10 ^ w5<<15 ^ w5<<13 ) + w7 + w0 )|0; + a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x682e6ff3 )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; + + // 56 + w8 = ( ( w9>>>7 ^ w9>>>18 ^ w9>>>3 ^ w9<<25 ^ w9<<14 ) + ( w6>>>17 ^ w6>>>19 ^ w6>>>10 ^ w6<<15 ^ w6<<13 ) + w8 + w1 )|0; + h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x748f82ee )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; + + // 57 + w9 = ( ( w10>>>7 ^ w10>>>18 ^ w10>>>3 ^ w10<<25 ^ w10<<14 ) + ( w7>>>17 ^ w7>>>19 ^ w7>>>10 ^ w7<<15 ^ w7<<13 ) + w9 + w2 )|0; + g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x78a5636f )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; + + // 58 + w10 = ( ( w11>>>7 ^ w11>>>18 ^ w11>>>3 ^ w11<<25 ^ w11<<14 ) + ( w8>>>17 ^ w8>>>19 ^ w8>>>10 ^ w8<<15 ^ w8<<13 ) + w10 + w3 )|0; + f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x84c87814 )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; + + // 59 + w11 = ( ( w12>>>7 ^ w12>>>18 ^ w12>>>3 ^ w12<<25 ^ w12<<14 ) + ( w9>>>17 ^ w9>>>19 ^ w9>>>10 ^ w9<<15 ^ w9<<13 ) + w11 + w4 )|0; + e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x8cc70208 )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; + + // 60 + w12 = ( ( w13>>>7 ^ w13>>>18 ^ w13>>>3 ^ w13<<25 ^ w13<<14 ) + ( w10>>>17 ^ w10>>>19 ^ w10>>>10 ^ w10<<15 ^ w10<<13 ) + w12 + w5 )|0; + d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x90befffa )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; + + // 61 + w13 = ( ( w14>>>7 ^ w14>>>18 ^ w14>>>3 ^ w14<<25 ^ w14<<14 ) + ( w11>>>17 ^ w11>>>19 ^ w11>>>10 ^ w11<<15 ^ w11<<13 ) + w13 + w6 )|0; + c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0xa4506ceb )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; + + // 62 + w14 = ( ( w15>>>7 ^ w15>>>18 ^ w15>>>3 ^ w15<<25 ^ w15<<14 ) + ( w12>>>17 ^ w12>>>19 ^ w12>>>10 ^ w12<<15 ^ w12<<13 ) + w14 + w7 )|0; + b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0xbef9a3f7 )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; + + // 63 + w15 = ( ( w0>>>7 ^ w0>>>18 ^ w0>>>3 ^ w0<<25 ^ w0<<14 ) + ( w13>>>17 ^ w13>>>19 ^ w13>>>10 ^ w13<<15 ^ w13<<13 ) + w15 + w8 )|0; + a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0xc67178f2 )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; + + H0 = ( H0 + a )|0; + H1 = ( H1 + b )|0; + H2 = ( H2 + c )|0; + H3 = ( H3 + d )|0; + H4 = ( H4 + e )|0; + H5 = ( H5 + f )|0; + H6 = ( H6 + g )|0; + H7 = ( H7 + h )|0; + } + + function _core_heap ( offset ) { + offset = offset|0; + + _core( + HEAP[offset|0]<<24 | HEAP[offset|1]<<16 | HEAP[offset|2]<<8 | HEAP[offset|3], + HEAP[offset|4]<<24 | HEAP[offset|5]<<16 | HEAP[offset|6]<<8 | HEAP[offset|7], + HEAP[offset|8]<<24 | HEAP[offset|9]<<16 | HEAP[offset|10]<<8 | HEAP[offset|11], + HEAP[offset|12]<<24 | HEAP[offset|13]<<16 | HEAP[offset|14]<<8 | HEAP[offset|15], + HEAP[offset|16]<<24 | HEAP[offset|17]<<16 | HEAP[offset|18]<<8 | HEAP[offset|19], + HEAP[offset|20]<<24 | HEAP[offset|21]<<16 | HEAP[offset|22]<<8 | HEAP[offset|23], + HEAP[offset|24]<<24 | HEAP[offset|25]<<16 | HEAP[offset|26]<<8 | HEAP[offset|27], + HEAP[offset|28]<<24 | HEAP[offset|29]<<16 | HEAP[offset|30]<<8 | HEAP[offset|31], + HEAP[offset|32]<<24 | HEAP[offset|33]<<16 | HEAP[offset|34]<<8 | HEAP[offset|35], + HEAP[offset|36]<<24 | HEAP[offset|37]<<16 | HEAP[offset|38]<<8 | HEAP[offset|39], + HEAP[offset|40]<<24 | HEAP[offset|41]<<16 | HEAP[offset|42]<<8 | HEAP[offset|43], + HEAP[offset|44]<<24 | HEAP[offset|45]<<16 | HEAP[offset|46]<<8 | HEAP[offset|47], + HEAP[offset|48]<<24 | HEAP[offset|49]<<16 | HEAP[offset|50]<<8 | HEAP[offset|51], + HEAP[offset|52]<<24 | HEAP[offset|53]<<16 | HEAP[offset|54]<<8 | HEAP[offset|55], + HEAP[offset|56]<<24 | HEAP[offset|57]<<16 | HEAP[offset|58]<<8 | HEAP[offset|59], + HEAP[offset|60]<<24 | HEAP[offset|61]<<16 | HEAP[offset|62]<<8 | HEAP[offset|63] + ); + } + + // offset — multiple of 32 + function _state_to_heap ( output ) { + output = output|0; + + HEAP[output|0] = H0>>>24; + HEAP[output|1] = H0>>>16&255; + HEAP[output|2] = H0>>>8&255; + HEAP[output|3] = H0&255; + HEAP[output|4] = H1>>>24; + HEAP[output|5] = H1>>>16&255; + HEAP[output|6] = H1>>>8&255; + HEAP[output|7] = H1&255; + HEAP[output|8] = H2>>>24; + HEAP[output|9] = H2>>>16&255; + HEAP[output|10] = H2>>>8&255; + HEAP[output|11] = H2&255; + HEAP[output|12] = H3>>>24; + HEAP[output|13] = H3>>>16&255; + HEAP[output|14] = H3>>>8&255; + HEAP[output|15] = H3&255; + HEAP[output|16] = H4>>>24; + HEAP[output|17] = H4>>>16&255; + HEAP[output|18] = H4>>>8&255; + HEAP[output|19] = H4&255; + HEAP[output|20] = H5>>>24; + HEAP[output|21] = H5>>>16&255; + HEAP[output|22] = H5>>>8&255; + HEAP[output|23] = H5&255; + HEAP[output|24] = H6>>>24; + HEAP[output|25] = H6>>>16&255; + HEAP[output|26] = H6>>>8&255; + HEAP[output|27] = H6&255; + HEAP[output|28] = H7>>>24; + HEAP[output|29] = H7>>>16&255; + HEAP[output|30] = H7>>>8&255; + HEAP[output|31] = H7&255; + } + + function reset () { + H0 = 0x6a09e667; + H1 = 0xbb67ae85; + H2 = 0x3c6ef372; + H3 = 0xa54ff53a; + H4 = 0x510e527f; + H5 = 0x9b05688c; + H6 = 0x1f83d9ab; + H7 = 0x5be0cd19; + TOTAL0 = TOTAL1 = 0; + } + + function init ( h0, h1, h2, h3, h4, h5, h6, h7, total0, total1 ) { + h0 = h0|0; + h1 = h1|0; + h2 = h2|0; + h3 = h3|0; + h4 = h4|0; + h5 = h5|0; + h6 = h6|0; + h7 = h7|0; + total0 = total0|0; + total1 = total1|0; + + H0 = h0; + H1 = h1; + H2 = h2; + H3 = h3; + H4 = h4; + H5 = h5; + H6 = h6; + H7 = h7; + TOTAL0 = total0; + TOTAL1 = total1; + } + + // offset — multiple of 64 + function process ( offset, length ) { + offset = offset|0; + length = length|0; + + var hashed = 0; + + if ( offset & 63 ) + return -1; + + while ( (length|0) >= 64 ) { + _core_heap(offset); + + offset = ( offset + 64 )|0; + length = ( length - 64 )|0; + + hashed = ( hashed + 64 )|0; + } + + TOTAL0 = ( TOTAL0 + hashed )|0; + if ( TOTAL0>>>0 < hashed>>>0 ) TOTAL1 = ( TOTAL1 + 1 )|0; + + return hashed|0; + } + + // offset — multiple of 64 + // output — multiple of 32 + function finish ( offset, length, output ) { + offset = offset|0; + length = length|0; + output = output|0; + + var hashed = 0, + i = 0; + + if ( offset & 63 ) + return -1; + + if ( ~output ) + if ( output & 31 ) + return -1; + + if ( (length|0) >= 64 ) { + hashed = process( offset, length )|0; + if ( (hashed|0) == -1 ) + return -1; + + offset = ( offset + hashed )|0; + length = ( length - hashed )|0; + } + + hashed = ( hashed + length )|0; + TOTAL0 = ( TOTAL0 + length )|0; + if ( TOTAL0>>>0 < length>>>0 ) TOTAL1 = ( TOTAL1 + 1 )|0; + + HEAP[offset|length] = 0x80; + + if ( (length|0) >= 56 ) { + for ( i = (length+1)|0; (i|0) < 64; i = (i+1)|0 ) + HEAP[offset|i] = 0x00; + + _core_heap(offset); + + length = 0; + + HEAP[offset|0] = 0; + } + + for ( i = (length+1)|0; (i|0) < 59; i = (i+1)|0 ) + HEAP[offset|i] = 0; + + HEAP[offset|56] = TOTAL1>>>21&255; + HEAP[offset|57] = TOTAL1>>>13&255; + HEAP[offset|58] = TOTAL1>>>5&255; + HEAP[offset|59] = TOTAL1<<3&255 | TOTAL0>>>29; + HEAP[offset|60] = TOTAL0>>>21&255; + HEAP[offset|61] = TOTAL0>>>13&255; + HEAP[offset|62] = TOTAL0>>>5&255; + HEAP[offset|63] = TOTAL0<<3&255; + _core_heap(offset); + + if ( ~output ) + _state_to_heap(output); + + return hashed|0; + } + + function hmac_reset () { + H0 = I0; + H1 = I1; + H2 = I2; + H3 = I3; + H4 = I4; + H5 = I5; + H6 = I6; + H7 = I7; + TOTAL0 = 64; + TOTAL1 = 0; + } + + function _hmac_opad () { + H0 = O0; + H1 = O1; + H2 = O2; + H3 = O3; + H4 = O4; + H5 = O5; + H6 = O6; + H7 = O7; + TOTAL0 = 64; + TOTAL1 = 0; + } + + function hmac_init ( p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15 ) { + p0 = p0|0; + p1 = p1|0; + p2 = p2|0; + p3 = p3|0; + p4 = p4|0; + p5 = p5|0; + p6 = p6|0; + p7 = p7|0; + p8 = p8|0; + p9 = p9|0; + p10 = p10|0; + p11 = p11|0; + p12 = p12|0; + p13 = p13|0; + p14 = p14|0; + p15 = p15|0; + + // opad + reset(); + _core( + p0 ^ 0x5c5c5c5c, + p1 ^ 0x5c5c5c5c, + p2 ^ 0x5c5c5c5c, + p3 ^ 0x5c5c5c5c, + p4 ^ 0x5c5c5c5c, + p5 ^ 0x5c5c5c5c, + p6 ^ 0x5c5c5c5c, + p7 ^ 0x5c5c5c5c, + p8 ^ 0x5c5c5c5c, + p9 ^ 0x5c5c5c5c, + p10 ^ 0x5c5c5c5c, + p11 ^ 0x5c5c5c5c, + p12 ^ 0x5c5c5c5c, + p13 ^ 0x5c5c5c5c, + p14 ^ 0x5c5c5c5c, + p15 ^ 0x5c5c5c5c + ); + O0 = H0; + O1 = H1; + O2 = H2; + O3 = H3; + O4 = H4; + O5 = H5; + O6 = H6; + O7 = H7; + + // ipad + reset(); + _core( + p0 ^ 0x36363636, + p1 ^ 0x36363636, + p2 ^ 0x36363636, + p3 ^ 0x36363636, + p4 ^ 0x36363636, + p5 ^ 0x36363636, + p6 ^ 0x36363636, + p7 ^ 0x36363636, + p8 ^ 0x36363636, + p9 ^ 0x36363636, + p10 ^ 0x36363636, + p11 ^ 0x36363636, + p12 ^ 0x36363636, + p13 ^ 0x36363636, + p14 ^ 0x36363636, + p15 ^ 0x36363636 + ); + I0 = H0; + I1 = H1; + I2 = H2; + I3 = H3; + I4 = H4; + I5 = H5; + I6 = H6; + I7 = H7; + + TOTAL0 = 64; + TOTAL1 = 0; + } + + // offset — multiple of 64 + // output — multiple of 32 + function hmac_finish ( offset, length, output ) { + offset = offset|0; + length = length|0; + output = output|0; + + var t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0, + hashed = 0; + + if ( offset & 63 ) + return -1; + + if ( ~output ) + if ( output & 31 ) + return -1; + + hashed = finish( offset, length, -1 )|0; + t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; + + _hmac_opad(); + _core( t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768 ); + + if ( ~output ) + _state_to_heap(output); + + return hashed|0; + } + + // salt is assumed to be already processed + // offset — multiple of 64 + // output — multiple of 32 + function pbkdf2_generate_block ( offset, length, block, count, output ) { + offset = offset|0; + length = length|0; + block = block|0; + count = count|0; + output = output|0; + + var h0 = 0, h1 = 0, h2 = 0, h3 = 0, h4 = 0, h5 = 0, h6 = 0, h7 = 0, + t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0; + + if ( offset & 63 ) + return -1; + + if ( ~output ) + if ( output & 31 ) + return -1; + + // pad block number into heap + // FIXME probable OOB write + HEAP[(offset+length)|0] = block>>>24; + HEAP[(offset+length+1)|0] = block>>>16&255; + HEAP[(offset+length+2)|0] = block>>>8&255; + HEAP[(offset+length+3)|0] = block&255; + + // finish first iteration + hmac_finish( offset, (length+4)|0, -1 )|0; + h0 = t0 = H0, h1 = t1 = H1, h2 = t2 = H2, h3 = t3 = H3, h4 = t4 = H4, h5 = t5 = H5, h6 = t6 = H6, h7 = t7 = H7; + count = (count-1)|0; + + // perform the rest iterations + while ( (count|0) > 0 ) { + hmac_reset(); + _core( t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768 ); + t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; + + _hmac_opad(); + _core( t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768 ); + t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; + + h0 = h0 ^ H0; + h1 = h1 ^ H1; + h2 = h2 ^ H2; + h3 = h3 ^ H3; + h4 = h4 ^ H4; + h5 = h5 ^ H5; + h6 = h6 ^ H6; + h7 = h7 ^ H7; + + count = (count-1)|0; + } + + H0 = h0; + H1 = h1; + H2 = h2; + H3 = h3; + H4 = h4; + H5 = h5; + H6 = h6; + H7 = h7; + + if ( ~output ) + _state_to_heap(output); + + return 0; + } + + return { + // SHA256 + reset: reset, + init: init, + process: process, + finish: finish, + + // HMAC-SHA256 + hmac_reset: hmac_reset, + hmac_init: hmac_init, + hmac_finish: hmac_finish, + + // PBKDF2-HMAC-SHA256 + pbkdf2_generate_block: pbkdf2_generate_block + } + }; + + const _sha256_block_size = 64; + const _sha256_hash_size = 32; + const heap_pool$2 = []; + const asm_pool$2 = []; + class Sha256 extends Hash { + constructor() { + super(); + this.NAME = 'sha256'; + this.BLOCK_SIZE = _sha256_block_size; + this.HASH_SIZE = _sha256_hash_size; + this.acquire_asm(); + } + acquire_asm() { + if (this.heap === undefined || this.asm === undefined) { + this.heap = heap_pool$2.pop() || _heap_init(); + this.asm = asm_pool$2.pop() || sha256_asm({ Uint8Array: Uint8Array }, null, this.heap.buffer); + this.reset(); + } + return { heap: this.heap, asm: this.asm }; + } + release_asm() { + if (this.heap !== undefined && this.asm !== undefined) { + heap_pool$2.push(this.heap); + asm_pool$2.push(this.asm); + } + this.heap = undefined; + this.asm = undefined; + } + static bytes(data) { + return new Sha256().process(data).finish().result; + } + } + Sha256.NAME = 'sha256'; + + var minimalisticAssert = assert; + + function assert(val, msg) { + if (!val) + throw new Error(msg || 'Assertion failed'); + } + + assert.equal = function assertEqual(l, r, msg) { + if (l != r) + throw new Error(msg || ('Assertion failed: ' + l + ' != ' + r)); + }; + + var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + + function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; + } + + function commonjsRequire () { + throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs'); + } + + var inherits_browser = createCommonjsModule(function (module) { + if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor; + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; + } else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor; + var TempCtor = function () {}; + TempCtor.prototype = superCtor.prototype; + ctor.prototype = new TempCtor(); + ctor.prototype.constructor = ctor; + }; + } + }); + + var inherits_1 = inherits_browser; + + function toArray(msg, enc) { + if (Array.isArray(msg)) + return msg.slice(); + if (!msg) + return []; + var res = []; + if (typeof msg === 'string') { + if (!enc) { + for (var i = 0; i < msg.length; i++) { + var c = msg.charCodeAt(i); + var hi = c >> 8; + var lo = c & 0xff; + if (hi) + res.push(hi, lo); + else + res.push(lo); + } + } else if (enc === 'hex') { + msg = msg.replace(/[^a-z0-9]+/ig, ''); + if (msg.length % 2 !== 0) + msg = '0' + msg; + for (i = 0; i < msg.length; i += 2) + res.push(parseInt(msg[i] + msg[i + 1], 16)); + } + } else { + for (i = 0; i < msg.length; i++) + res[i] = msg[i] | 0; + } + return res; + } + var toArray_1 = toArray; + + function toHex(msg) { + var res = ''; + for (var i = 0; i < msg.length; i++) + res += zero2(msg[i].toString(16)); + return res; + } + var toHex_1 = toHex; + + function htonl(w) { + var res = (w >>> 24) | + ((w >>> 8) & 0xff00) | + ((w << 8) & 0xff0000) | + ((w & 0xff) << 24); + return res >>> 0; + } + var htonl_1 = htonl; + + function toHex32(msg, endian) { + var res = ''; + for (var i = 0; i < msg.length; i++) { + var w = msg[i]; + if (endian === 'little') + w = htonl(w); + res += zero8(w.toString(16)); + } + return res; + } + var toHex32_1 = toHex32; + + function zero2(word) { + if (word.length === 1) + return '0' + word; + else + return word; + } + var zero2_1 = zero2; + + function zero8(word) { + if (word.length === 7) + return '0' + word; + else if (word.length === 6) + return '00' + word; + else if (word.length === 5) + return '000' + word; + else if (word.length === 4) + return '0000' + word; + else if (word.length === 3) + return '00000' + word; + else if (word.length === 2) + return '000000' + word; + else if (word.length === 1) + return '0000000' + word; + else + return word; + } + var zero8_1 = zero8; + + function join32(msg, start, end, endian) { + var len = end - start; + minimalisticAssert(len % 4 === 0); + var res = new Array(len / 4); + for (var i = 0, k = start; i < res.length; i++, k += 4) { + var w; + if (endian === 'big') + w = (msg[k] << 24) | (msg[k + 1] << 16) | (msg[k + 2] << 8) | msg[k + 3]; + else + w = (msg[k + 3] << 24) | (msg[k + 2] << 16) | (msg[k + 1] << 8) | msg[k]; + res[i] = w >>> 0; + } + return res; + } + var join32_1 = join32; + + function split32(msg, endian) { + var res = new Array(msg.length * 4); + for (var i = 0, k = 0; i < msg.length; i++, k += 4) { + var m = msg[i]; + if (endian === 'big') { + res[k] = m >>> 24; + res[k + 1] = (m >>> 16) & 0xff; + res[k + 2] = (m >>> 8) & 0xff; + res[k + 3] = m & 0xff; + } else { + res[k + 3] = m >>> 24; + res[k + 2] = (m >>> 16) & 0xff; + res[k + 1] = (m >>> 8) & 0xff; + res[k] = m & 0xff; + } + } + return res; + } + var split32_1 = split32; + + function rotr32(w, b) { + return (w >>> b) | (w << (32 - b)); + } + var rotr32_1 = rotr32; + + function rotl32(w, b) { + return (w << b) | (w >>> (32 - b)); + } + var rotl32_1 = rotl32; + + function sum32(a, b) { + return (a + b) >>> 0; + } + var sum32_1 = sum32; + + function sum32_3(a, b, c) { + return (a + b + c) >>> 0; + } + var sum32_3_1 = sum32_3; + + function sum32_4(a, b, c, d) { + return (a + b + c + d) >>> 0; + } + var sum32_4_1 = sum32_4; + + function sum32_5(a, b, c, d, e) { + return (a + b + c + d + e) >>> 0; + } + var sum32_5_1 = sum32_5; + + function sum64(buf, pos, ah, al) { + var bh = buf[pos]; + var bl = buf[pos + 1]; + + var lo = (al + bl) >>> 0; + var hi = (lo < al ? 1 : 0) + ah + bh; + buf[pos] = hi >>> 0; + buf[pos + 1] = lo; + } + var sum64_1 = sum64; + + function sum64_hi(ah, al, bh, bl) { + var lo = (al + bl) >>> 0; + var hi = (lo < al ? 1 : 0) + ah + bh; + return hi >>> 0; + } + var sum64_hi_1 = sum64_hi; + + function sum64_lo(ah, al, bh, bl) { + var lo = al + bl; + return lo >>> 0; + } + var sum64_lo_1 = sum64_lo; + + function sum64_4_hi(ah, al, bh, bl, ch, cl, dh, dl) { + var carry = 0; + var lo = al; + lo = (lo + bl) >>> 0; + carry += lo < al ? 1 : 0; + lo = (lo + cl) >>> 0; + carry += lo < cl ? 1 : 0; + lo = (lo + dl) >>> 0; + carry += lo < dl ? 1 : 0; + + var hi = ah + bh + ch + dh + carry; + return hi >>> 0; + } + var sum64_4_hi_1 = sum64_4_hi; + + function sum64_4_lo(ah, al, bh, bl, ch, cl, dh, dl) { + var lo = al + bl + cl + dl; + return lo >>> 0; + } + var sum64_4_lo_1 = sum64_4_lo; + + function sum64_5_hi(ah, al, bh, bl, ch, cl, dh, dl, eh, el) { + var carry = 0; + var lo = al; + lo = (lo + bl) >>> 0; + carry += lo < al ? 1 : 0; + lo = (lo + cl) >>> 0; + carry += lo < cl ? 1 : 0; + lo = (lo + dl) >>> 0; + carry += lo < dl ? 1 : 0; + lo = (lo + el) >>> 0; + carry += lo < el ? 1 : 0; + + var hi = ah + bh + ch + dh + eh + carry; + return hi >>> 0; + } + var sum64_5_hi_1 = sum64_5_hi; + + function sum64_5_lo(ah, al, bh, bl, ch, cl, dh, dl, eh, el) { + var lo = al + bl + cl + dl + el; + + return lo >>> 0; + } + var sum64_5_lo_1 = sum64_5_lo; + + function rotr64_hi(ah, al, num) { + var r = (al << (32 - num)) | (ah >>> num); + return r >>> 0; + } + var rotr64_hi_1 = rotr64_hi; + + function rotr64_lo(ah, al, num) { + var r = (ah << (32 - num)) | (al >>> num); + return r >>> 0; + } + var rotr64_lo_1 = rotr64_lo; + + function shr64_hi(ah, al, num) { + return ah >>> num; + } + var shr64_hi_1 = shr64_hi; + + function shr64_lo(ah, al, num) { + var r = (ah << (32 - num)) | (al >>> num); + return r >>> 0; + } + var shr64_lo_1 = shr64_lo; + + var utils = { + inherits: inherits_1, + toArray: toArray_1, + toHex: toHex_1, + htonl: htonl_1, + toHex32: toHex32_1, + zero2: zero2_1, + zero8: zero8_1, + join32: join32_1, + split32: split32_1, + rotr32: rotr32_1, + rotl32: rotl32_1, + sum32: sum32_1, + sum32_3: sum32_3_1, + sum32_4: sum32_4_1, + sum32_5: sum32_5_1, + sum64: sum64_1, + sum64_hi: sum64_hi_1, + sum64_lo: sum64_lo_1, + sum64_4_hi: sum64_4_hi_1, + sum64_4_lo: sum64_4_lo_1, + sum64_5_hi: sum64_5_hi_1, + sum64_5_lo: sum64_5_lo_1, + rotr64_hi: rotr64_hi_1, + rotr64_lo: rotr64_lo_1, + shr64_hi: shr64_hi_1, + shr64_lo: shr64_lo_1 + }; + + function BlockHash() { + this.pending = null; + this.pendingTotal = 0; + this.blockSize = this.constructor.blockSize; + this.outSize = this.constructor.outSize; + this.hmacStrength = this.constructor.hmacStrength; + this.padLength = this.constructor.padLength / 8; + this.endian = 'big'; + + this._delta8 = this.blockSize / 8; + this._delta32 = this.blockSize / 32; + } + var BlockHash_1 = BlockHash; + + BlockHash.prototype.update = function update(msg, enc) { + // Convert message to array, pad it, and join into 32bit blocks + msg = utils.toArray(msg, enc); + if (!this.pending) + this.pending = msg; + else + this.pending = this.pending.concat(msg); + this.pendingTotal += msg.length; + + // Enough data, try updating + if (this.pending.length >= this._delta8) { + msg = this.pending; + + // Process pending data in blocks + var r = msg.length % this._delta8; + this.pending = msg.slice(msg.length - r, msg.length); + if (this.pending.length === 0) + this.pending = null; + + msg = utils.join32(msg, 0, msg.length - r, this.endian); + for (var i = 0; i < msg.length; i += this._delta32) + this._update(msg, i, i + this._delta32); + } + + return this; + }; + + BlockHash.prototype.digest = function digest(enc) { + this.update(this._pad()); + minimalisticAssert(this.pending === null); + + return this._digest(enc); + }; + + BlockHash.prototype._pad = function pad() { + var len = this.pendingTotal; + var bytes = this._delta8; + var k = bytes - ((len + this.padLength) % bytes); + var res = new Array(k + this.padLength); + res[0] = 0x80; + for (var i = 1; i < k; i++) + res[i] = 0; + + // Append length + len <<= 3; + if (this.endian === 'big') { + for (var t = 8; t < this.padLength; t++) + res[i++] = 0; + + res[i++] = 0; + res[i++] = 0; + res[i++] = 0; + res[i++] = 0; + res[i++] = (len >>> 24) & 0xff; + res[i++] = (len >>> 16) & 0xff; + res[i++] = (len >>> 8) & 0xff; + res[i++] = len & 0xff; + } else { + res[i++] = len & 0xff; + res[i++] = (len >>> 8) & 0xff; + res[i++] = (len >>> 16) & 0xff; + res[i++] = (len >>> 24) & 0xff; + res[i++] = 0; + res[i++] = 0; + res[i++] = 0; + res[i++] = 0; + + for (t = 8; t < this.padLength; t++) + res[i++] = 0; + } + + return res; + }; + + var common = { + BlockHash: BlockHash_1 + }; + + var rotr32$1 = utils.rotr32; + + function ft_1(s, x, y, z) { + if (s === 0) + return ch32(x, y, z); + if (s === 1 || s === 3) + return p32(x, y, z); + if (s === 2) + return maj32(x, y, z); + } + var ft_1_1 = ft_1; + + function ch32(x, y, z) { + return (x & y) ^ ((~x) & z); + } + var ch32_1 = ch32; + + function maj32(x, y, z) { + return (x & y) ^ (x & z) ^ (y & z); + } + var maj32_1 = maj32; + + function p32(x, y, z) { + return x ^ y ^ z; + } + var p32_1 = p32; + + function s0_256(x) { + return rotr32$1(x, 2) ^ rotr32$1(x, 13) ^ rotr32$1(x, 22); + } + var s0_256_1 = s0_256; + + function s1_256(x) { + return rotr32$1(x, 6) ^ rotr32$1(x, 11) ^ rotr32$1(x, 25); + } + var s1_256_1 = s1_256; + + function g0_256(x) { + return rotr32$1(x, 7) ^ rotr32$1(x, 18) ^ (x >>> 3); + } + var g0_256_1 = g0_256; + + function g1_256(x) { + return rotr32$1(x, 17) ^ rotr32$1(x, 19) ^ (x >>> 10); + } + var g1_256_1 = g1_256; + + var common$1 = { + ft_1: ft_1_1, + ch32: ch32_1, + maj32: maj32_1, + p32: p32_1, + s0_256: s0_256_1, + s1_256: s1_256_1, + g0_256: g0_256_1, + g1_256: g1_256_1 + }; + + var sum32$1 = utils.sum32; + var sum32_4$1 = utils.sum32_4; + var sum32_5$1 = utils.sum32_5; + var ch32$1 = common$1.ch32; + var maj32$1 = common$1.maj32; + var s0_256$1 = common$1.s0_256; + var s1_256$1 = common$1.s1_256; + var g0_256$1 = common$1.g0_256; + var g1_256$1 = common$1.g1_256; + + var BlockHash$1 = common.BlockHash; + + var sha256_K = [ + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 + ]; + + function SHA256() { + if (!(this instanceof SHA256)) + return new SHA256(); + + BlockHash$1.call(this); + this.h = [ + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 + ]; + this.k = sha256_K; + this.W = new Array(64); + } + utils.inherits(SHA256, BlockHash$1); + var _256 = SHA256; + + SHA256.blockSize = 512; + SHA256.outSize = 256; + SHA256.hmacStrength = 192; + SHA256.padLength = 64; + + SHA256.prototype._update = function _update(msg, start) { + var W = this.W; + + for (var i = 0; i < 16; i++) + W[i] = msg[start + i]; + for (; i < W.length; i++) + W[i] = sum32_4$1(g1_256$1(W[i - 2]), W[i - 7], g0_256$1(W[i - 15]), W[i - 16]); + + var a = this.h[0]; + var b = this.h[1]; + var c = this.h[2]; + var d = this.h[3]; + var e = this.h[4]; + var f = this.h[5]; + var g = this.h[6]; + var h = this.h[7]; + + minimalisticAssert(this.k.length === W.length); + for (i = 0; i < W.length; i++) { + var T1 = sum32_5$1(h, s1_256$1(e), ch32$1(e, f, g), this.k[i], W[i]); + var T2 = sum32$1(s0_256$1(a), maj32$1(a, b, c)); + h = g; + g = f; + f = e; + e = sum32$1(d, T1); + d = c; + c = b; + b = a; + a = sum32$1(T1, T2); + } + + this.h[0] = sum32$1(this.h[0], a); + this.h[1] = sum32$1(this.h[1], b); + this.h[2] = sum32$1(this.h[2], c); + this.h[3] = sum32$1(this.h[3], d); + this.h[4] = sum32$1(this.h[4], e); + this.h[5] = sum32$1(this.h[5], f); + this.h[6] = sum32$1(this.h[6], g); + this.h[7] = sum32$1(this.h[7], h); + }; + + SHA256.prototype._digest = function digest(enc) { + if (enc === 'hex') + return utils.toHex32(this.h, 'big'); + else + return utils.split32(this.h, 'big'); + }; + + function SHA224() { + if (!(this instanceof SHA224)) + return new SHA224(); + + _256.call(this); + this.h = [ + 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, + 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 ]; + } + utils.inherits(SHA224, _256); + var _224 = SHA224; + + SHA224.blockSize = 512; + SHA224.outSize = 224; + SHA224.hmacStrength = 192; + SHA224.padLength = 64; + + SHA224.prototype._digest = function digest(enc) { + // Just truncate output + if (enc === 'hex') + return utils.toHex32(this.h.slice(0, 7), 'big'); + else + return utils.split32(this.h.slice(0, 7), 'big'); + }; + + var rotr64_hi$1 = utils.rotr64_hi; + var rotr64_lo$1 = utils.rotr64_lo; + var shr64_hi$1 = utils.shr64_hi; + var shr64_lo$1 = utils.shr64_lo; + var sum64$1 = utils.sum64; + var sum64_hi$1 = utils.sum64_hi; + var sum64_lo$1 = utils.sum64_lo; + var sum64_4_hi$1 = utils.sum64_4_hi; + var sum64_4_lo$1 = utils.sum64_4_lo; + var sum64_5_hi$1 = utils.sum64_5_hi; + var sum64_5_lo$1 = utils.sum64_5_lo; + + var BlockHash$2 = common.BlockHash; + + var sha512_K = [ + 0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd, + 0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc, + 0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019, + 0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118, + 0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe, + 0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2, + 0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1, + 0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694, + 0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3, + 0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65, + 0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483, + 0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5, + 0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210, + 0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4, + 0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725, + 0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70, + 0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926, + 0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df, + 0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8, + 0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b, + 0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001, + 0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30, + 0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910, + 0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8, + 0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53, + 0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8, + 0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb, + 0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3, + 0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60, + 0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec, + 0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9, + 0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b, + 0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207, + 0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178, + 0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6, + 0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b, + 0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493, + 0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c, + 0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a, + 0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817 + ]; + + function SHA512() { + if (!(this instanceof SHA512)) + return new SHA512(); + + BlockHash$2.call(this); + this.h = [ + 0x6a09e667, 0xf3bcc908, + 0xbb67ae85, 0x84caa73b, + 0x3c6ef372, 0xfe94f82b, + 0xa54ff53a, 0x5f1d36f1, + 0x510e527f, 0xade682d1, + 0x9b05688c, 0x2b3e6c1f, + 0x1f83d9ab, 0xfb41bd6b, + 0x5be0cd19, 0x137e2179 ]; + this.k = sha512_K; + this.W = new Array(160); + } + utils.inherits(SHA512, BlockHash$2); + var _512 = SHA512; + + SHA512.blockSize = 1024; + SHA512.outSize = 512; + SHA512.hmacStrength = 192; + SHA512.padLength = 128; + + SHA512.prototype._prepareBlock = function _prepareBlock(msg, start) { + var W = this.W; + + // 32 x 32bit words + for (var i = 0; i < 32; i++) + W[i] = msg[start + i]; + for (; i < W.length; i += 2) { + var c0_hi = g1_512_hi(W[i - 4], W[i - 3]); // i - 2 + var c0_lo = g1_512_lo(W[i - 4], W[i - 3]); + var c1_hi = W[i - 14]; // i - 7 + var c1_lo = W[i - 13]; + var c2_hi = g0_512_hi(W[i - 30], W[i - 29]); // i - 15 + var c2_lo = g0_512_lo(W[i - 30], W[i - 29]); + var c3_hi = W[i - 32]; // i - 16 + var c3_lo = W[i - 31]; + + W[i] = sum64_4_hi$1( + c0_hi, c0_lo, + c1_hi, c1_lo, + c2_hi, c2_lo, + c3_hi, c3_lo); + W[i + 1] = sum64_4_lo$1( + c0_hi, c0_lo, + c1_hi, c1_lo, + c2_hi, c2_lo, + c3_hi, c3_lo); + } + }; + + SHA512.prototype._update = function _update(msg, start) { + this._prepareBlock(msg, start); + + var W = this.W; + + var ah = this.h[0]; + var al = this.h[1]; + var bh = this.h[2]; + var bl = this.h[3]; + var ch = this.h[4]; + var cl = this.h[5]; + var dh = this.h[6]; + var dl = this.h[7]; + var eh = this.h[8]; + var el = this.h[9]; + var fh = this.h[10]; + var fl = this.h[11]; + var gh = this.h[12]; + var gl = this.h[13]; + var hh = this.h[14]; + var hl = this.h[15]; + + minimalisticAssert(this.k.length === W.length); + for (var i = 0; i < W.length; i += 2) { + var c0_hi = hh; + var c0_lo = hl; + var c1_hi = s1_512_hi(eh, el); + var c1_lo = s1_512_lo(eh, el); + var c2_hi = ch64_hi(eh, el, fh, fl, gh); + var c2_lo = ch64_lo(eh, el, fh, fl, gh, gl); + var c3_hi = this.k[i]; + var c3_lo = this.k[i + 1]; + var c4_hi = W[i]; + var c4_lo = W[i + 1]; + + var T1_hi = sum64_5_hi$1( + c0_hi, c0_lo, + c1_hi, c1_lo, + c2_hi, c2_lo, + c3_hi, c3_lo, + c4_hi, c4_lo); + var T1_lo = sum64_5_lo$1( + c0_hi, c0_lo, + c1_hi, c1_lo, + c2_hi, c2_lo, + c3_hi, c3_lo, + c4_hi, c4_lo); + + c0_hi = s0_512_hi(ah, al); + c0_lo = s0_512_lo(ah, al); + c1_hi = maj64_hi(ah, al, bh, bl, ch); + c1_lo = maj64_lo(ah, al, bh, bl, ch, cl); + + var T2_hi = sum64_hi$1(c0_hi, c0_lo, c1_hi, c1_lo); + var T2_lo = sum64_lo$1(c0_hi, c0_lo, c1_hi, c1_lo); + + hh = gh; + hl = gl; + + gh = fh; + gl = fl; + + fh = eh; + fl = el; + + eh = sum64_hi$1(dh, dl, T1_hi, T1_lo); + el = sum64_lo$1(dl, dl, T1_hi, T1_lo); + + dh = ch; + dl = cl; + + ch = bh; + cl = bl; + + bh = ah; + bl = al; + + ah = sum64_hi$1(T1_hi, T1_lo, T2_hi, T2_lo); + al = sum64_lo$1(T1_hi, T1_lo, T2_hi, T2_lo); + } + + sum64$1(this.h, 0, ah, al); + sum64$1(this.h, 2, bh, bl); + sum64$1(this.h, 4, ch, cl); + sum64$1(this.h, 6, dh, dl); + sum64$1(this.h, 8, eh, el); + sum64$1(this.h, 10, fh, fl); + sum64$1(this.h, 12, gh, gl); + sum64$1(this.h, 14, hh, hl); + }; + + SHA512.prototype._digest = function digest(enc) { + if (enc === 'hex') + return utils.toHex32(this.h, 'big'); + else + return utils.split32(this.h, 'big'); + }; + + function ch64_hi(xh, xl, yh, yl, zh) { + var r = (xh & yh) ^ ((~xh) & zh); + if (r < 0) + r += 0x100000000; + return r; + } + + function ch64_lo(xh, xl, yh, yl, zh, zl) { + var r = (xl & yl) ^ ((~xl) & zl); + if (r < 0) + r += 0x100000000; + return r; + } + + function maj64_hi(xh, xl, yh, yl, zh) { + var r = (xh & yh) ^ (xh & zh) ^ (yh & zh); + if (r < 0) + r += 0x100000000; + return r; + } + + function maj64_lo(xh, xl, yh, yl, zh, zl) { + var r = (xl & yl) ^ (xl & zl) ^ (yl & zl); + if (r < 0) + r += 0x100000000; + return r; + } + + function s0_512_hi(xh, xl) { + var c0_hi = rotr64_hi$1(xh, xl, 28); + var c1_hi = rotr64_hi$1(xl, xh, 2); // 34 + var c2_hi = rotr64_hi$1(xl, xh, 7); // 39 + + var r = c0_hi ^ c1_hi ^ c2_hi; + if (r < 0) + r += 0x100000000; + return r; + } + + function s0_512_lo(xh, xl) { + var c0_lo = rotr64_lo$1(xh, xl, 28); + var c1_lo = rotr64_lo$1(xl, xh, 2); // 34 + var c2_lo = rotr64_lo$1(xl, xh, 7); // 39 + + var r = c0_lo ^ c1_lo ^ c2_lo; + if (r < 0) + r += 0x100000000; + return r; + } + + function s1_512_hi(xh, xl) { + var c0_hi = rotr64_hi$1(xh, xl, 14); + var c1_hi = rotr64_hi$1(xh, xl, 18); + var c2_hi = rotr64_hi$1(xl, xh, 9); // 41 + + var r = c0_hi ^ c1_hi ^ c2_hi; + if (r < 0) + r += 0x100000000; + return r; + } + + function s1_512_lo(xh, xl) { + var c0_lo = rotr64_lo$1(xh, xl, 14); + var c1_lo = rotr64_lo$1(xh, xl, 18); + var c2_lo = rotr64_lo$1(xl, xh, 9); // 41 + + var r = c0_lo ^ c1_lo ^ c2_lo; + if (r < 0) + r += 0x100000000; + return r; + } + + function g0_512_hi(xh, xl) { + var c0_hi = rotr64_hi$1(xh, xl, 1); + var c1_hi = rotr64_hi$1(xh, xl, 8); + var c2_hi = shr64_hi$1(xh, xl, 7); + + var r = c0_hi ^ c1_hi ^ c2_hi; + if (r < 0) + r += 0x100000000; + return r; + } + + function g0_512_lo(xh, xl) { + var c0_lo = rotr64_lo$1(xh, xl, 1); + var c1_lo = rotr64_lo$1(xh, xl, 8); + var c2_lo = shr64_lo$1(xh, xl, 7); + + var r = c0_lo ^ c1_lo ^ c2_lo; + if (r < 0) + r += 0x100000000; + return r; + } + + function g1_512_hi(xh, xl) { + var c0_hi = rotr64_hi$1(xh, xl, 19); + var c1_hi = rotr64_hi$1(xl, xh, 29); // 61 + var c2_hi = shr64_hi$1(xh, xl, 6); + + var r = c0_hi ^ c1_hi ^ c2_hi; + if (r < 0) + r += 0x100000000; + return r; + } + + function g1_512_lo(xh, xl) { + var c0_lo = rotr64_lo$1(xh, xl, 19); + var c1_lo = rotr64_lo$1(xl, xh, 29); // 61 + var c2_lo = shr64_lo$1(xh, xl, 6); + + var r = c0_lo ^ c1_lo ^ c2_lo; + if (r < 0) + r += 0x100000000; + return r; + } + + function SHA384() { + if (!(this instanceof SHA384)) + return new SHA384(); + + _512.call(this); + this.h = [ + 0xcbbb9d5d, 0xc1059ed8, + 0x629a292a, 0x367cd507, + 0x9159015a, 0x3070dd17, + 0x152fecd8, 0xf70e5939, + 0x67332667, 0xffc00b31, + 0x8eb44a87, 0x68581511, + 0xdb0c2e0d, 0x64f98fa7, + 0x47b5481d, 0xbefa4fa4 ]; + } + utils.inherits(SHA384, _512); + var _384 = SHA384; + + SHA384.blockSize = 1024; + SHA384.outSize = 384; + SHA384.hmacStrength = 192; + SHA384.padLength = 128; + + SHA384.prototype._digest = function digest(enc) { + if (enc === 'hex') + return utils.toHex32(this.h.slice(0, 12), 'big'); + else + return utils.split32(this.h.slice(0, 12), 'big'); + }; + + var rotl32$1 = utils.rotl32; + var sum32$2 = utils.sum32; + var sum32_3$1 = utils.sum32_3; + var sum32_4$2 = utils.sum32_4; + var BlockHash$3 = common.BlockHash; + + function RIPEMD160() { + if (!(this instanceof RIPEMD160)) + return new RIPEMD160(); + + BlockHash$3.call(this); + + this.h = [ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 ]; + this.endian = 'little'; + } + utils.inherits(RIPEMD160, BlockHash$3); + var ripemd160 = RIPEMD160; + + RIPEMD160.blockSize = 512; + RIPEMD160.outSize = 160; + RIPEMD160.hmacStrength = 192; + RIPEMD160.padLength = 64; + + RIPEMD160.prototype._update = function update(msg, start) { + var A = this.h[0]; + var B = this.h[1]; + var C = this.h[2]; + var D = this.h[3]; + var E = this.h[4]; + var Ah = A; + var Bh = B; + var Ch = C; + var Dh = D; + var Eh = E; + for (var j = 0; j < 80; j++) { + var T = sum32$2( + rotl32$1( + sum32_4$2(A, f(j, B, C, D), msg[r[j] + start], K(j)), + s[j]), + E); + A = E; + E = D; + D = rotl32$1(C, 10); + C = B; + B = T; + T = sum32$2( + rotl32$1( + sum32_4$2(Ah, f(79 - j, Bh, Ch, Dh), msg[rh[j] + start], Kh(j)), + sh[j]), + Eh); + Ah = Eh; + Eh = Dh; + Dh = rotl32$1(Ch, 10); + Ch = Bh; + Bh = T; + } + T = sum32_3$1(this.h[1], C, Dh); + this.h[1] = sum32_3$1(this.h[2], D, Eh); + this.h[2] = sum32_3$1(this.h[3], E, Ah); + this.h[3] = sum32_3$1(this.h[4], A, Bh); + this.h[4] = sum32_3$1(this.h[0], B, Ch); + this.h[0] = T; + }; + + RIPEMD160.prototype._digest = function digest(enc) { + if (enc === 'hex') + return utils.toHex32(this.h, 'little'); + else + return utils.split32(this.h, 'little'); + }; + + function f(j, x, y, z) { + if (j <= 15) + return x ^ y ^ z; + else if (j <= 31) + return (x & y) | ((~x) & z); + else if (j <= 47) + return (x | (~y)) ^ z; + else if (j <= 63) + return (x & z) | (y & (~z)); + else + return x ^ (y | (~z)); + } + + function K(j) { + if (j <= 15) + return 0x00000000; + else if (j <= 31) + return 0x5a827999; + else if (j <= 47) + return 0x6ed9eba1; + else if (j <= 63) + return 0x8f1bbcdc; + else + return 0xa953fd4e; + } + + function Kh(j) { + if (j <= 15) + return 0x50a28be6; + else if (j <= 31) + return 0x5c4dd124; + else if (j <= 47) + return 0x6d703ef3; + else if (j <= 63) + return 0x7a6d76e9; + else + return 0x00000000; + } + + var r = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, + 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, + 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, + 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 + ]; + + var rh = [ + 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, + 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, + 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, + 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, + 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 + ]; + + var s = [ + 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, + 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, + 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, + 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, + 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 + ]; + + var sh = [ + 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, + 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, + 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, + 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, + 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 + ]; + + var ripemd = { + ripemd160: ripemd160 + }; + + /** + * A fast MD5 JavaScript implementation + * Copyright (c) 2012 Joseph Myers + * http://www.myersdaily.org/joseph/javascript/md5-text.html + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purposes and without + * fee is hereby granted provided that this copyright notice + * appears in all copies. + * + * Of course, this soft is provided "as is" without express or implied + * warranty of any kind. + */ + + // MD5 Digest + async function md5(entree) { + const digest = md51(util.uint8ArrayToString(entree)); + return util.hexToUint8Array(hex(digest)); + } + + function md5cycle(x, k) { + let a = x[0]; + let b = x[1]; + let c = x[2]; + let d = x[3]; + + a = ff(a, b, c, d, k[0], 7, -680876936); + d = ff(d, a, b, c, k[1], 12, -389564586); + c = ff(c, d, a, b, k[2], 17, 606105819); + b = ff(b, c, d, a, k[3], 22, -1044525330); + a = ff(a, b, c, d, k[4], 7, -176418897); + d = ff(d, a, b, c, k[5], 12, 1200080426); + c = ff(c, d, a, b, k[6], 17, -1473231341); + b = ff(b, c, d, a, k[7], 22, -45705983); + a = ff(a, b, c, d, k[8], 7, 1770035416); + d = ff(d, a, b, c, k[9], 12, -1958414417); + c = ff(c, d, a, b, k[10], 17, -42063); + b = ff(b, c, d, a, k[11], 22, -1990404162); + a = ff(a, b, c, d, k[12], 7, 1804603682); + d = ff(d, a, b, c, k[13], 12, -40341101); + c = ff(c, d, a, b, k[14], 17, -1502002290); + b = ff(b, c, d, a, k[15], 22, 1236535329); + + a = gg(a, b, c, d, k[1], 5, -165796510); + d = gg(d, a, b, c, k[6], 9, -1069501632); + c = gg(c, d, a, b, k[11], 14, 643717713); + b = gg(b, c, d, a, k[0], 20, -373897302); + a = gg(a, b, c, d, k[5], 5, -701558691); + d = gg(d, a, b, c, k[10], 9, 38016083); + c = gg(c, d, a, b, k[15], 14, -660478335); + b = gg(b, c, d, a, k[4], 20, -405537848); + a = gg(a, b, c, d, k[9], 5, 568446438); + d = gg(d, a, b, c, k[14], 9, -1019803690); + c = gg(c, d, a, b, k[3], 14, -187363961); + b = gg(b, c, d, a, k[8], 20, 1163531501); + a = gg(a, b, c, d, k[13], 5, -1444681467); + d = gg(d, a, b, c, k[2], 9, -51403784); + c = gg(c, d, a, b, k[7], 14, 1735328473); + b = gg(b, c, d, a, k[12], 20, -1926607734); + + a = hh(a, b, c, d, k[5], 4, -378558); + d = hh(d, a, b, c, k[8], 11, -2022574463); + c = hh(c, d, a, b, k[11], 16, 1839030562); + b = hh(b, c, d, a, k[14], 23, -35309556); + a = hh(a, b, c, d, k[1], 4, -1530992060); + d = hh(d, a, b, c, k[4], 11, 1272893353); + c = hh(c, d, a, b, k[7], 16, -155497632); + b = hh(b, c, d, a, k[10], 23, -1094730640); + a = hh(a, b, c, d, k[13], 4, 681279174); + d = hh(d, a, b, c, k[0], 11, -358537222); + c = hh(c, d, a, b, k[3], 16, -722521979); + b = hh(b, c, d, a, k[6], 23, 76029189); + a = hh(a, b, c, d, k[9], 4, -640364487); + d = hh(d, a, b, c, k[12], 11, -421815835); + c = hh(c, d, a, b, k[15], 16, 530742520); + b = hh(b, c, d, a, k[2], 23, -995338651); + + a = ii(a, b, c, d, k[0], 6, -198630844); + d = ii(d, a, b, c, k[7], 10, 1126891415); + c = ii(c, d, a, b, k[14], 15, -1416354905); + b = ii(b, c, d, a, k[5], 21, -57434055); + a = ii(a, b, c, d, k[12], 6, 1700485571); + d = ii(d, a, b, c, k[3], 10, -1894986606); + c = ii(c, d, a, b, k[10], 15, -1051523); + b = ii(b, c, d, a, k[1], 21, -2054922799); + a = ii(a, b, c, d, k[8], 6, 1873313359); + d = ii(d, a, b, c, k[15], 10, -30611744); + c = ii(c, d, a, b, k[6], 15, -1560198380); + b = ii(b, c, d, a, k[13], 21, 1309151649); + a = ii(a, b, c, d, k[4], 6, -145523070); + d = ii(d, a, b, c, k[11], 10, -1120210379); + c = ii(c, d, a, b, k[2], 15, 718787259); + b = ii(b, c, d, a, k[9], 21, -343485551); + + x[0] = add32(a, x[0]); + x[1] = add32(b, x[1]); + x[2] = add32(c, x[2]); + x[3] = add32(d, x[3]); + } + + function cmn(q, a, b, x, s, t) { + a = add32(add32(a, q), add32(x, t)); + return add32((a << s) | (a >>> (32 - s)), b); + } + + function ff(a, b, c, d, x, s, t) { + return cmn((b & c) | ((~b) & d), a, b, x, s, t); + } + + function gg(a, b, c, d, x, s, t) { + return cmn((b & d) | (c & (~d)), a, b, x, s, t); + } + + function hh(a, b, c, d, x, s, t) { + return cmn(b ^ c ^ d, a, b, x, s, t); + } + + function ii(a, b, c, d, x, s, t) { + return cmn(c ^ (b | (~d)), a, b, x, s, t); + } + + function md51(s) { + const n = s.length; + const state = [1732584193, -271733879, -1732584194, 271733878]; + let i; + for (i = 64; i <= s.length; i += 64) { + md5cycle(state, md5blk(s.substring(i - 64, i))); + } + s = s.substring(i - 64); + const tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + for (i = 0; i < s.length; i++) { + tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3); + } + tail[i >> 2] |= 0x80 << ((i % 4) << 3); + if (i > 55) { + md5cycle(state, tail); + for (i = 0; i < 16; i++) { + tail[i] = 0; + } + } + tail[14] = n * 8; + md5cycle(state, tail); + return state; + } + + /* there needs to be support for Unicode here, + * unless we pretend that we can redefine the MD-5 + * algorithm for multi-byte characters (perhaps + * by adding every four 16-bit characters and + * shortening the sum to 32 bits). Otherwise + * I suggest performing MD-5 as if every character + * was two bytes--e.g., 0040 0025 = @%--but then + * how will an ordinary MD-5 sum be matched? + * There is no way to standardize text to something + * like UTF-8 before transformation; speed cost is + * utterly prohibitive. The JavaScript standard + * itself needs to look at this: it should start + * providing access to strings as preformed UTF-8 + * 8-bit unsigned value arrays. + */ + function md5blk(s) { /* I figured global was faster. */ + const md5blks = []; + let i; /* Andy King said do it this way. */ + for (i = 0; i < 64; i += 4) { + md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << + 24); + } + return md5blks; + } + + const hex_chr = '0123456789abcdef'.split(''); + + function rhex(n) { + let s = ''; + let j = 0; + for (; j < 4; j++) { + s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F]; + } + return s; + } + + function hex(x) { + for (let i = 0; i < x.length; i++) { + x[i] = rhex(x[i]); + } + return x.join(''); + } + + /* this function is much faster, + so if possible we use it. Some IEs + are the only ones I know of that + need the idiotic second function, + generated by an if clause. */ + + function add32(a, b) { + return (a + b) & 0xFFFFFFFF; + } + + /** + * @fileoverview Provides an interface to hashing functions available in Node.js or external libraries. + * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} + * @see {@link https://github.com/indutny/hash.js|hash.js} + * @module crypto/hash + * @private + */ + + const webCrypto = util.getWebCrypto(); + const nodeCrypto = util.getNodeCrypto(); + + function nodeHash(type) { + return async function (data) { + const shasum = nodeCrypto.createHash(type); + return transform(data, value => { + shasum.update(value); + }, () => new Uint8Array(shasum.digest())); + }; + } + + function hashjsHash(hash, webCryptoHash) { + return async function(data, config = defaultConfig) { + if (isArrayStream(data)) { + data = await readToEnd(data); + } + if (!util.isStream(data) && webCrypto && webCryptoHash && data.length >= config.minBytesForWebCrypto) { + return new Uint8Array(await webCrypto.digest(webCryptoHash, data)); + } + const hashInstance = hash(); + return transform(data, value => { + hashInstance.update(value); + }, () => new Uint8Array(hashInstance.digest())); + }; + } + + function asmcryptoHash(hash, webCryptoHash) { + return async function(data, config = defaultConfig) { + if (isArrayStream(data)) { + data = await readToEnd(data); + } + if (util.isStream(data)) { + const hashInstance = new hash(); + return transform(data, value => { + hashInstance.process(value); + }, () => hashInstance.finish().result); + } else if (webCrypto && webCryptoHash && data.length >= config.minBytesForWebCrypto) { + return new Uint8Array(await webCrypto.digest(webCryptoHash, data)); + } else { + return hash.bytes(data); + } + }; + } + + let hashFunctions; + if (nodeCrypto) { // Use Node native crypto for all hash functions + hashFunctions = { + md5: nodeHash('md5'), + sha1: nodeHash('sha1'), + sha224: nodeHash('sha224'), + sha256: nodeHash('sha256'), + sha384: nodeHash('sha384'), + sha512: nodeHash('sha512'), + ripemd: nodeHash('ripemd160') + }; + } else { // Use JS fallbacks + hashFunctions = { + md5: md5, + sha1: asmcryptoHash(Sha1, (!navigator.userAgent || navigator.userAgent.indexOf('Edge') === -1) && 'SHA-1'), + sha224: hashjsHash(_224), + sha256: asmcryptoHash(Sha256, 'SHA-256'), + sha384: hashjsHash(_384, 'SHA-384'), + sha512: hashjsHash(_512, 'SHA-512'), // asmcrypto sha512 is huge. + ripemd: hashjsHash(ripemd160) + }; + } + + var hash = { + + /** @see module:md5 */ + md5: hashFunctions.md5, + /** @see asmCrypto */ + sha1: hashFunctions.sha1, + /** @see hash.js */ + sha224: hashFunctions.sha224, + /** @see asmCrypto */ + sha256: hashFunctions.sha256, + /** @see hash.js */ + sha384: hashFunctions.sha384, + /** @see asmCrypto */ + sha512: hashFunctions.sha512, + /** @see hash.js */ + ripemd: hashFunctions.ripemd, + + /** + * Create a hash on the specified data using the specified algorithm + * @param {module:enums.hash} algo - Hash algorithm type (see {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}) + * @param {Uint8Array} data - Data to be hashed + * @returns {Promise} Hash value. + */ + digest: function(algo, data) { + switch (algo) { + case enums.hash.md5: + return this.md5(data); + case enums.hash.sha1: + return this.sha1(data); + case enums.hash.ripemd: + return this.ripemd(data); + case enums.hash.sha256: + return this.sha256(data); + case enums.hash.sha384: + return this.sha384(data); + case enums.hash.sha512: + return this.sha512(data); + case enums.hash.sha224: + return this.sha224(data); + default: + throw new Error('Invalid hash function.'); + } + }, + + /** + * Returns the hash size in bytes of the specified hash algorithm type + * @param {module:enums.hash} algo - Hash algorithm type (See {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}) + * @returns {Integer} Size in bytes of the resulting hash. + */ + getHashByteLength: function(algo) { + switch (algo) { + case enums.hash.md5: + return 16; + case enums.hash.sha1: + case enums.hash.ripemd: + return 20; + case enums.hash.sha256: + return 32; + case enums.hash.sha384: + return 48; + case enums.hash.sha512: + return 64; + case enums.hash.sha224: + return 28; + default: + throw new Error('Invalid hash algorithm.'); + } + } + }; + + class AES_CFB { + static encrypt(data, key, iv) { + return new AES_CFB(key, iv).encrypt(data); + } + static decrypt(data, key, iv) { + return new AES_CFB(key, iv).decrypt(data); + } + constructor(key, iv, aes) { + this.aes = aes ? aes : new AES(key, iv, true, 'CFB'); + delete this.aes.padding; + } + encrypt(data) { + const r1 = this.aes.AES_Encrypt_process(data); + const r2 = this.aes.AES_Encrypt_finish(); + return joinBytes(r1, r2); + } + decrypt(data) { + const r1 = this.aes.AES_Decrypt_process(data); + const r2 = this.aes.AES_Decrypt_finish(); + return joinBytes(r1, r2); + } + } + + // Modified by ProtonTech AG + + const webCrypto$1 = util.getWebCrypto(); + const nodeCrypto$1 = util.getNodeCrypto(); + + const knownAlgos = nodeCrypto$1 ? nodeCrypto$1.getCiphers() : []; + const nodeAlgos = { + idea: knownAlgos.includes('idea-cfb') ? 'idea-cfb' : undefined, /* Unused, not implemented */ + tripledes: knownAlgos.includes('des-ede3-cfb') ? 'des-ede3-cfb' : undefined, + cast5: knownAlgos.includes('cast5-cfb') ? 'cast5-cfb' : undefined, + blowfish: knownAlgos.includes('bf-cfb') ? 'bf-cfb' : undefined, + aes128: knownAlgos.includes('aes-128-cfb') ? 'aes-128-cfb' : undefined, + aes192: knownAlgos.includes('aes-192-cfb') ? 'aes-192-cfb' : undefined, + aes256: knownAlgos.includes('aes-256-cfb') ? 'aes-256-cfb' : undefined + /* twofish is not implemented in OpenSSL */ + }; + + /** + * CFB encryption + * @param {enums.symmetric} algo - block cipher algorithm + * @param {Uint8Array} key + * @param {MaybeStream} plaintext + * @param {Uint8Array} iv + * @param {Object} config - full configuration, defaults to openpgp.config + * @returns MaybeStream + */ + async function encrypt(algo, key, plaintext, iv, config) { + const algoName = enums.read(enums.symmetric, algo); + if (util.getNodeCrypto() && nodeAlgos[algoName]) { // Node crypto library. + return nodeEncrypt(algo, key, plaintext, iv); + } + if (algoName.substr(0, 3) === 'aes') { + return aesEncrypt(algo, key, plaintext, iv, config); + } + + const cipherfn = new cipher[algoName](key); + const block_size = cipherfn.blockSize; + + const blockc = iv.slice(); + let pt = new Uint8Array(); + const process = chunk => { + if (chunk) { + pt = util.concatUint8Array([pt, chunk]); + } + const ciphertext = new Uint8Array(pt.length); + let i; + let j = 0; + while (chunk ? pt.length >= block_size : pt.length) { + const encblock = cipherfn.encrypt(blockc); + for (i = 0; i < block_size; i++) { + blockc[i] = pt[i] ^ encblock[i]; + ciphertext[j++] = blockc[i]; + } + pt = pt.subarray(block_size); + } + return ciphertext.subarray(0, j); + }; + return transform(plaintext, process, process); + } + + /** + * CFB decryption + * @param {enums.symmetric} algo - block cipher algorithm + * @param {Uint8Array} key + * @param {MaybeStream} ciphertext + * @param {Uint8Array} iv + * @returns MaybeStream + */ + async function decrypt(algo, key, ciphertext, iv) { + const algoName = enums.read(enums.symmetric, algo); + if (util.getNodeCrypto() && nodeAlgos[algoName]) { // Node crypto library. + return nodeDecrypt(algo, key, ciphertext, iv); + } + if (algoName.substr(0, 3) === 'aes') { + return aesDecrypt(algo, key, ciphertext, iv); + } + + const cipherfn = new cipher[algoName](key); + const block_size = cipherfn.blockSize; + + let blockp = iv; + let ct = new Uint8Array(); + const process = chunk => { + if (chunk) { + ct = util.concatUint8Array([ct, chunk]); + } + const plaintext = new Uint8Array(ct.length); + let i; + let j = 0; + while (chunk ? ct.length >= block_size : ct.length) { + const decblock = cipherfn.encrypt(blockp); + blockp = ct; + for (i = 0; i < block_size; i++) { + plaintext[j++] = blockp[i] ^ decblock[i]; + } + ct = ct.subarray(block_size); + } + return plaintext.subarray(0, j); + }; + return transform(ciphertext, process, process); + } + + function aesEncrypt(algo, key, pt, iv, config) { + if ( + util.getWebCrypto() && + key.length !== 24 && // Chrome doesn't support 192 bit keys, see https://www.chromium.org/blink/webcrypto#TOC-AES-support + !util.isStream(pt) && + pt.length >= 3000 * config.minBytesForWebCrypto // Default to a 3MB minimum. Chrome is pretty slow for small messages, see: https://bugs.chromium.org/p/chromium/issues/detail?id=701188#c2 + ) { // Web Crypto + return webEncrypt(algo, key, pt, iv); + } + // asm.js fallback + const cfb = new AES_CFB(key, iv); + return transform(pt, value => cfb.aes.AES_Encrypt_process(value), () => cfb.aes.AES_Encrypt_finish()); + } + + function aesDecrypt(algo, key, ct, iv) { + if (util.isStream(ct)) { + const cfb = new AES_CFB(key, iv); + return transform(ct, value => cfb.aes.AES_Decrypt_process(value), () => cfb.aes.AES_Decrypt_finish()); + } + return AES_CFB.decrypt(ct, key, iv); + } + + function xorMut(a, b) { + for (let i = 0; i < a.length; i++) { + a[i] = a[i] ^ b[i]; + } + } + + async function webEncrypt(algo, key, pt, iv) { + const ALGO = 'AES-CBC'; + const _key = await webCrypto$1.importKey('raw', key, { name: ALGO }, false, ['encrypt']); + const { blockSize } = crypto.getCipher(algo); + const cbc_pt = util.concatUint8Array([new Uint8Array(blockSize), pt]); + const ct = new Uint8Array(await webCrypto$1.encrypt({ name: ALGO, iv }, _key, cbc_pt)).subarray(0, pt.length); + xorMut(ct, pt); + return ct; + } + + function nodeEncrypt(algo, key, pt, iv) { + const algoName = enums.read(enums.symmetric, algo); + const cipherObj = new nodeCrypto$1.createCipheriv(nodeAlgos[algoName], key, iv); + return transform(pt, value => new Uint8Array(cipherObj.update(value))); + } + + function nodeDecrypt(algo, key, ct, iv) { + const algoName = enums.read(enums.symmetric, algo); + const decipherObj = new nodeCrypto$1.createDecipheriv(nodeAlgos[algoName], key, iv); + return transform(ct, value => new Uint8Array(decipherObj.update(value))); + } + + var cfb = /*#__PURE__*/Object.freeze({ + __proto__: null, + encrypt: encrypt, + decrypt: decrypt + }); + + class AES_CTR { + static encrypt(data, key, nonce) { + return new AES_CTR(key, nonce).encrypt(data); + } + static decrypt(data, key, nonce) { + return new AES_CTR(key, nonce).encrypt(data); + } + constructor(key, nonce, aes) { + this.aes = aes ? aes : new AES(key, undefined, false, 'CTR'); + delete this.aes.padding; + this.AES_CTR_set_options(nonce); + } + encrypt(data) { + const r1 = this.aes.AES_Encrypt_process(data); + const r2 = this.aes.AES_Encrypt_finish(); + return joinBytes(r1, r2); + } + decrypt(data) { + const r1 = this.aes.AES_Encrypt_process(data); + const r2 = this.aes.AES_Encrypt_finish(); + return joinBytes(r1, r2); + } + AES_CTR_set_options(nonce, counter, size) { + let { asm } = this.aes.acquire_asm(); + if (size !== undefined) { + if (size < 8 || size > 48) + throw new IllegalArgumentError('illegal counter size'); + let mask = Math.pow(2, size) - 1; + asm.set_mask(0, 0, (mask / 0x100000000) | 0, mask | 0); + } + else { + size = 48; + asm.set_mask(0, 0, 0xffff, 0xffffffff); + } + if (nonce !== undefined) { + let len = nonce.length; + if (!len || len > 16) + throw new IllegalArgumentError('illegal nonce size'); + let view = new DataView(new ArrayBuffer(16)); + new Uint8Array(view.buffer).set(nonce); + asm.set_nonce(view.getUint32(0), view.getUint32(4), view.getUint32(8), view.getUint32(12)); + } + else { + throw new Error('nonce is required'); + } + if (counter !== undefined) { + if (counter < 0 || counter >= Math.pow(2, size)) + throw new IllegalArgumentError('illegal counter value'); + asm.set_counter(0, 0, (counter / 0x100000000) | 0, counter | 0); + } + } + } + + class AES_CBC { + static encrypt(data, key, padding = true, iv) { + return new AES_CBC(key, iv, padding).encrypt(data); + } + static decrypt(data, key, padding = true, iv) { + return new AES_CBC(key, iv, padding).decrypt(data); + } + constructor(key, iv, padding = true, aes) { + this.aes = aes ? aes : new AES(key, iv, padding, 'CBC'); + } + encrypt(data) { + const r1 = this.aes.AES_Encrypt_process(data); + const r2 = this.aes.AES_Encrypt_finish(); + return joinBytes(r1, r2); + } + decrypt(data) { + const r1 = this.aes.AES_Decrypt_process(data); + const r2 = this.aes.AES_Decrypt_finish(); + return joinBytes(r1, r2); + } + } + + /** + * @fileoverview This module implements AES-CMAC on top of + * native AES-CBC using either the WebCrypto API or Node.js' crypto API. + * @module crypto/cmac + * @private + */ + + const webCrypto$2 = util.getWebCrypto(); + const nodeCrypto$2 = util.getNodeCrypto(); + + + /** + * This implementation of CMAC is based on the description of OMAC in + * http://web.cs.ucdavis.edu/~rogaway/papers/eax.pdf. As per that + * document: + * + * We have made a small modification to the OMAC algorithm as it was + * originally presented, changing one of its two constants. + * Specifically, the constant 4 at line 85 was the constant 1/2 (the + * multiplicative inverse of 2) in the original definition of OMAC [14]. + * The OMAC authors indicate that they will promulgate this modification + * [15], which slightly simplifies implementations. + */ + + const blockLength = 16; + + + /** + * xor `padding` into the end of `data`. This function implements "the + * operation xor→ [which] xors the shorter string into the end of longer + * one". Since data is always as least as long as padding, we can + * simplify the implementation. + * @param {Uint8Array} data + * @param {Uint8Array} padding + */ + function rightXORMut(data, padding) { + const offset = data.length - blockLength; + for (let i = 0; i < blockLength; i++) { + data[i + offset] ^= padding[i]; + } + return data; + } + + function pad(data, padding, padding2) { + // if |M| in {n, 2n, 3n, ...} + if (data.length && data.length % blockLength === 0) { + // then return M xor→ B, + return rightXORMut(data, padding); + } + // else return (M || 10^(n−1−(|M| mod n))) xor→ P + const padded = new Uint8Array(data.length + (blockLength - data.length % blockLength)); + padded.set(data); + padded[data.length] = 0b10000000; + return rightXORMut(padded, padding2); + } + + const zeroBlock = new Uint8Array(blockLength); + + async function CMAC(key) { + const cbc = await CBC(key); + + // L ← E_K(0^n); B ← 2L; P ← 4L + const padding = util.double(await cbc(zeroBlock)); + const padding2 = util.double(padding); + + return async function(data) { + // return CBC_K(pad(M; B, P)) + return (await cbc(pad(data, padding, padding2))).subarray(-blockLength); + }; + } + + async function CBC(key) { + if (util.getWebCrypto() && key.length !== 24) { // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support + key = await webCrypto$2.importKey('raw', key, { name: 'AES-CBC', length: key.length * 8 }, false, ['encrypt']); + return async function(pt) { + const ct = await webCrypto$2.encrypt({ name: 'AES-CBC', iv: zeroBlock, length: blockLength * 8 }, key, pt); + return new Uint8Array(ct).subarray(0, ct.byteLength - blockLength); + }; + } + if (util.getNodeCrypto()) { // Node crypto library + return async function(pt) { + const en = new nodeCrypto$2.createCipheriv('aes-' + (key.length * 8) + '-cbc', key, zeroBlock); + const ct = en.update(pt); + return new Uint8Array(ct); + }; + } + // asm.js fallback + return async function(pt) { + return AES_CBC.encrypt(pt, key, false, zeroBlock); + }; + } + + // OpenPGP.js - An OpenPGP implementation in javascript + + const webCrypto$3 = util.getWebCrypto(); + const nodeCrypto$3 = util.getNodeCrypto(); + const Buffer$1 = util.getNodeBuffer(); + + + const blockLength$1 = 16; + const ivLength = blockLength$1; + const tagLength = blockLength$1; + + const zero = new Uint8Array(blockLength$1); + const one = new Uint8Array(blockLength$1); one[blockLength$1 - 1] = 1; + const two = new Uint8Array(blockLength$1); two[blockLength$1 - 1] = 2; + + async function OMAC(key) { + const cmac = await CMAC(key); + return function(t, message) { + return cmac(util.concatUint8Array([t, message])); + }; + } + + async function CTR(key) { + if ( + util.getWebCrypto() && + key.length !== 24 && // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support + (!navigator.userAgent || navigator.userAgent.indexOf('Edge') === -1) + ) { + key = await webCrypto$3.importKey('raw', key, { name: 'AES-CTR', length: key.length * 8 }, false, ['encrypt']); + return async function(pt, iv) { + const ct = await webCrypto$3.encrypt({ name: 'AES-CTR', counter: iv, length: blockLength$1 * 8 }, key, pt); + return new Uint8Array(ct); + }; + } + if (util.getNodeCrypto()) { // Node crypto library + return async function(pt, iv) { + const en = new nodeCrypto$3.createCipheriv('aes-' + (key.length * 8) + '-ctr', key, iv); + const ct = Buffer$1.concat([en.update(pt), en.final()]); + return new Uint8Array(ct); + }; + } + // asm.js fallback + return async function(pt, iv) { + return AES_CTR.encrypt(pt, key, iv); + }; + } + + + /** + * Class to en/decrypt using EAX mode. + * @param {enums.symmetric} cipher - The symmetric cipher algorithm to use + * @param {Uint8Array} key - The encryption key + */ + async function EAX(cipher, key) { + if (cipher !== enums.symmetric.aes128 && + cipher !== enums.symmetric.aes192 && + cipher !== enums.symmetric.aes256) { + throw new Error('EAX mode supports only AES cipher'); + } + + const [ + omac, + ctr + ] = await Promise.all([ + OMAC(key), + CTR(key) + ]); + + return { + /** + * Encrypt plaintext input. + * @param {Uint8Array} plaintext - The cleartext input to be encrypted + * @param {Uint8Array} nonce - The nonce (16 bytes) + * @param {Uint8Array} adata - Associated data to sign + * @returns {Promise} The ciphertext output. + */ + encrypt: async function(plaintext, nonce, adata) { + const [ + omacNonce, + omacAdata + ] = await Promise.all([ + omac(zero, nonce), + omac(one, adata) + ]); + const ciphered = await ctr(plaintext, omacNonce); + const omacCiphered = await omac(two, ciphered); + const tag = omacCiphered; // Assumes that omac(*).length === tagLength. + for (let i = 0; i < tagLength; i++) { + tag[i] ^= omacAdata[i] ^ omacNonce[i]; + } + return util.concatUint8Array([ciphered, tag]); + }, + + /** + * Decrypt ciphertext input. + * @param {Uint8Array} ciphertext - The ciphertext input to be decrypted + * @param {Uint8Array} nonce - The nonce (16 bytes) + * @param {Uint8Array} adata - Associated data to verify + * @returns {Promise} The plaintext output. + */ + decrypt: async function(ciphertext, nonce, adata) { + if (ciphertext.length < tagLength) throw new Error('Invalid EAX ciphertext'); + const ciphered = ciphertext.subarray(0, -tagLength); + const ctTag = ciphertext.subarray(-tagLength); + const [ + omacNonce, + omacAdata, + omacCiphered + ] = await Promise.all([ + omac(zero, nonce), + omac(one, adata), + omac(two, ciphered) + ]); + const tag = omacCiphered; // Assumes that omac(*).length === tagLength. + for (let i = 0; i < tagLength; i++) { + tag[i] ^= omacAdata[i] ^ omacNonce[i]; + } + if (!util.equalsUint8Array(ctTag, tag)) throw new Error('Authentication tag mismatch'); + const plaintext = await ctr(ciphered, omacNonce); + return plaintext; + } + }; + } + + + /** + * Get EAX nonce as defined by {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.1|RFC4880bis-04, section 5.16.1}. + * @param {Uint8Array} iv - The initialization vector (16 bytes) + * @param {Uint8Array} chunkIndex - The chunk index (8 bytes) + */ + EAX.getNonce = function(iv, chunkIndex) { + const nonce = iv.slice(); + for (let i = 0; i < chunkIndex.length; i++) { + nonce[8 + i] ^= chunkIndex[i]; + } + return nonce; + }; + + EAX.blockLength = blockLength$1; + EAX.ivLength = ivLength; + EAX.tagLength = tagLength; + + // OpenPGP.js - An OpenPGP implementation in javascript + + const blockLength$2 = 16; + const ivLength$1 = 15; + + // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.2: + // While OCB [RFC7253] allows the authentication tag length to be of any + // number up to 128 bits long, this document requires a fixed + // authentication tag length of 128 bits (16 octets) for simplicity. + const tagLength$1 = 16; + + + function ntz(n) { + let ntz = 0; + for (let i = 1; (n & i) === 0; i <<= 1) { + ntz++; + } + return ntz; + } + + function xorMut$1(S, T) { + for (let i = 0; i < S.length; i++) { + S[i] ^= T[i]; + } + return S; + } + + function xor(S, T) { + return xorMut$1(S.slice(), T); + } + + const zeroBlock$1 = new Uint8Array(blockLength$2); + const one$1 = new Uint8Array([1]); + + /** + * Class to en/decrypt using OCB mode. + * @param {enums.symmetric} cipher - The symmetric cipher algorithm to use + * @param {Uint8Array} key - The encryption key + */ + async function OCB(cipher$1, key) { + + let maxNtz = 0; + let encipher; + let decipher; + let mask; + + constructKeyVariables(cipher$1, key); + + function constructKeyVariables(cipher$1, key) { + const cipherName = enums.read(enums.symmetric, cipher$1); + const aes = new cipher[cipherName](key); + encipher = aes.encrypt.bind(aes); + decipher = aes.decrypt.bind(aes); + + const mask_x = encipher(zeroBlock$1); + const mask_$ = util.double(mask_x); + mask = []; + mask[0] = util.double(mask_$); + + + mask.x = mask_x; + mask.$ = mask_$; + } + + function extendKeyVariables(text, adata) { + const newMaxNtz = util.nbits(Math.max(text.length, adata.length) / blockLength$2 | 0) - 1; + for (let i = maxNtz + 1; i <= newMaxNtz; i++) { + mask[i] = util.double(mask[i - 1]); + } + maxNtz = newMaxNtz; + } + + function hash(adata) { + if (!adata.length) { + // Fast path + return zeroBlock$1; + } + + // + // Consider A as a sequence of 128-bit blocks + // + const m = adata.length / blockLength$2 | 0; + + const offset = new Uint8Array(blockLength$2); + const sum = new Uint8Array(blockLength$2); + for (let i = 0; i < m; i++) { + xorMut$1(offset, mask[ntz(i + 1)]); + xorMut$1(sum, encipher(xor(offset, adata))); + adata = adata.subarray(blockLength$2); + } + + // + // Process any final partial block; compute final hash value + // + if (adata.length) { + xorMut$1(offset, mask.x); + + const cipherInput = new Uint8Array(blockLength$2); + cipherInput.set(adata, 0); + cipherInput[adata.length] = 0b10000000; + xorMut$1(cipherInput, offset); + + xorMut$1(sum, encipher(cipherInput)); + } + + return sum; + } + + /** + * Encrypt/decrypt data. + * @param {encipher|decipher} fn - Encryption/decryption block cipher function + * @param {Uint8Array} text - The cleartext or ciphertext (without tag) input + * @param {Uint8Array} nonce - The nonce (15 bytes) + * @param {Uint8Array} adata - Associated data to sign + * @returns {Promise} The ciphertext or plaintext output, with tag appended in both cases. + */ + function crypt(fn, text, nonce, adata) { + // + // Consider P as a sequence of 128-bit blocks + // + const m = text.length / blockLength$2 | 0; + + // + // Key-dependent variables + // + extendKeyVariables(text, adata); + + // + // Nonce-dependent and per-encryption variables + // + // Nonce = num2str(TAGLEN mod 128,7) || zeros(120-bitlen(N)) || 1 || N + // Note: We assume here that tagLength mod 16 == 0. + const paddedNonce = util.concatUint8Array([zeroBlock$1.subarray(0, ivLength$1 - nonce.length), one$1, nonce]); + // bottom = str2num(Nonce[123..128]) + const bottom = paddedNonce[blockLength$2 - 1] & 0b111111; + // Ktop = ENCIPHER(K, Nonce[1..122] || zeros(6)) + paddedNonce[blockLength$2 - 1] &= 0b11000000; + const kTop = encipher(paddedNonce); + // Stretch = Ktop || (Ktop[1..64] xor Ktop[9..72]) + const stretched = util.concatUint8Array([kTop, xor(kTop.subarray(0, 8), kTop.subarray(1, 9))]); + // Offset_0 = Stretch[1+bottom..128+bottom] + const offset = util.shiftRight(stretched.subarray(0 + (bottom >> 3), 17 + (bottom >> 3)), 8 - (bottom & 7)).subarray(1); + // Checksum_0 = zeros(128) + const checksum = new Uint8Array(blockLength$2); + + const ct = new Uint8Array(text.length + tagLength$1); + + // + // Process any whole blocks + // + let i; + let pos = 0; + for (i = 0; i < m; i++) { + // Offset_i = Offset_{i-1} xor L_{ntz(i)} + xorMut$1(offset, mask[ntz(i + 1)]); + // C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) + // P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i) + ct.set(xorMut$1(fn(xor(offset, text)), offset), pos); + // Checksum_i = Checksum_{i-1} xor P_i + xorMut$1(checksum, fn === encipher ? text : ct.subarray(pos)); + + text = text.subarray(blockLength$2); + pos += blockLength$2; + } + + // + // Process any final partial block and compute raw tag + // + if (text.length) { + // Offset_* = Offset_m xor L_* + xorMut$1(offset, mask.x); + // Pad = ENCIPHER(K, Offset_*) + const padding = encipher(offset); + // C_* = P_* xor Pad[1..bitlen(P_*)] + ct.set(xor(text, padding), pos); + + // Checksum_* = Checksum_m xor (P_* || 1 || new Uint8Array(127-bitlen(P_*))) + const xorInput = new Uint8Array(blockLength$2); + xorInput.set(fn === encipher ? text : ct.subarray(pos, -tagLength$1), 0); + xorInput[text.length] = 0b10000000; + xorMut$1(checksum, xorInput); + pos += text.length; + } + // Tag = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) xor HASH(K,A) + const tag = xorMut$1(encipher(xorMut$1(xorMut$1(checksum, offset), mask.$)), hash(adata)); + + // + // Assemble ciphertext + // + // C = C_1 || C_2 || ... || C_m || C_* || Tag[1..TAGLEN] + ct.set(tag, pos); + return ct; + } + + + return { + /** + * Encrypt plaintext input. + * @param {Uint8Array} plaintext - The cleartext input to be encrypted + * @param {Uint8Array} nonce - The nonce (15 bytes) + * @param {Uint8Array} adata - Associated data to sign + * @returns {Promise} The ciphertext output. + */ + encrypt: async function(plaintext, nonce, adata) { + return crypt(encipher, plaintext, nonce, adata); + }, + + /** + * Decrypt ciphertext input. + * @param {Uint8Array} ciphertext - The ciphertext input to be decrypted + * @param {Uint8Array} nonce - The nonce (15 bytes) + * @param {Uint8Array} adata - Associated data to sign + * @returns {Promise} The ciphertext output. + */ + decrypt: async function(ciphertext, nonce, adata) { + if (ciphertext.length < tagLength$1) throw new Error('Invalid OCB ciphertext'); + + const tag = ciphertext.subarray(-tagLength$1); + ciphertext = ciphertext.subarray(0, -tagLength$1); + + const crypted = crypt(decipher, ciphertext, nonce, adata); + // if (Tag[1..TAGLEN] == T) + if (util.equalsUint8Array(tag, crypted.subarray(-tagLength$1))) { + return crypted.subarray(0, -tagLength$1); + } + throw new Error('Authentication tag mismatch'); + } + }; + } + + + /** + * Get OCB nonce as defined by {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.2|RFC4880bis-04, section 5.16.2}. + * @param {Uint8Array} iv - The initialization vector (15 bytes) + * @param {Uint8Array} chunkIndex - The chunk index (8 bytes) + */ + OCB.getNonce = function(iv, chunkIndex) { + const nonce = iv.slice(); + for (let i = 0; i < chunkIndex.length; i++) { + nonce[7 + i] ^= chunkIndex[i]; + } + return nonce; + }; + + OCB.blockLength = blockLength$2; + OCB.ivLength = ivLength$1; + OCB.tagLength = tagLength$1; + + const _AES_GCM_data_maxLength = 68719476704; // 2^36 - 2^5 + class AES_GCM { + constructor(key, nonce, adata, tagSize = 16, aes) { + this.tagSize = tagSize; + this.gamma0 = 0; + this.counter = 1; + this.aes = aes ? aes : new AES(key, undefined, false, 'CTR'); + let { asm, heap } = this.aes.acquire_asm(); + // Init GCM + asm.gcm_init(); + // Tag size + if (this.tagSize < 4 || this.tagSize > 16) + throw new IllegalArgumentError('illegal tagSize value'); + // Nonce + const noncelen = nonce.length || 0; + const noncebuf = new Uint8Array(16); + if (noncelen !== 12) { + this._gcm_mac_process(nonce); + heap[0] = 0; + heap[1] = 0; + heap[2] = 0; + heap[3] = 0; + heap[4] = 0; + heap[5] = 0; + heap[6] = 0; + heap[7] = 0; + heap[8] = 0; + heap[9] = 0; + heap[10] = 0; + heap[11] = noncelen >>> 29; + heap[12] = (noncelen >>> 21) & 255; + heap[13] = (noncelen >>> 13) & 255; + heap[14] = (noncelen >>> 5) & 255; + heap[15] = (noncelen << 3) & 255; + asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16); + asm.get_iv(AES_asm.HEAP_DATA); + asm.set_iv(0, 0, 0, 0); + noncebuf.set(heap.subarray(0, 16)); + } + else { + noncebuf.set(nonce); + noncebuf[15] = 1; + } + const nonceview = new DataView(noncebuf.buffer); + this.gamma0 = nonceview.getUint32(12); + asm.set_nonce(nonceview.getUint32(0), nonceview.getUint32(4), nonceview.getUint32(8), 0); + asm.set_mask(0, 0, 0, 0xffffffff); + // Associated data + if (adata !== undefined) { + if (adata.length > _AES_GCM_data_maxLength) + throw new IllegalArgumentError('illegal adata length'); + if (adata.length) { + this.adata = adata; + this._gcm_mac_process(adata); + } + else { + this.adata = undefined; + } + } + else { + this.adata = undefined; + } + // Counter + if (this.counter < 1 || this.counter > 0xffffffff) + throw new RangeError('counter must be a positive 32-bit integer'); + asm.set_counter(0, 0, 0, (this.gamma0 + this.counter) | 0); + } + static encrypt(cleartext, key, nonce, adata, tagsize) { + return new AES_GCM(key, nonce, adata, tagsize).encrypt(cleartext); + } + static decrypt(ciphertext, key, nonce, adata, tagsize) { + return new AES_GCM(key, nonce, adata, tagsize).decrypt(ciphertext); + } + encrypt(data) { + return this.AES_GCM_encrypt(data); + } + decrypt(data) { + return this.AES_GCM_decrypt(data); + } + AES_GCM_Encrypt_process(data) { + let dpos = 0; + let dlen = data.length || 0; + let { asm, heap } = this.aes.acquire_asm(); + let counter = this.counter; + let pos = this.aes.pos; + let len = this.aes.len; + let rpos = 0; + let rlen = (len + dlen) & -16; + let wlen = 0; + if (((counter - 1) << 4) + len + dlen > _AES_GCM_data_maxLength) + throw new RangeError('counter overflow'); + const result = new Uint8Array(rlen); + while (dlen > 0) { + wlen = _heap_write(heap, pos + len, data, dpos, dlen); + len += wlen; + dpos += wlen; + dlen -= wlen; + wlen = asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, len); + wlen = asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, wlen); + if (wlen) + result.set(heap.subarray(pos, pos + wlen), rpos); + counter += wlen >>> 4; + rpos += wlen; + if (wlen < len) { + pos += wlen; + len -= wlen; + } + else { + pos = 0; + len = 0; + } + } + this.counter = counter; + this.aes.pos = pos; + this.aes.len = len; + return result; + } + AES_GCM_Encrypt_finish() { + let { asm, heap } = this.aes.acquire_asm(); + let counter = this.counter; + let tagSize = this.tagSize; + let adata = this.adata; + let pos = this.aes.pos; + let len = this.aes.len; + const result = new Uint8Array(len + tagSize); + asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, (len + 15) & -16); + if (len) + result.set(heap.subarray(pos, pos + len)); + let i = len; + for (; i & 15; i++) + heap[pos + i] = 0; + asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, i); + const alen = adata !== undefined ? adata.length : 0; + const clen = ((counter - 1) << 4) + len; + heap[0] = 0; + heap[1] = 0; + heap[2] = 0; + heap[3] = alen >>> 29; + heap[4] = alen >>> 21; + heap[5] = (alen >>> 13) & 255; + heap[6] = (alen >>> 5) & 255; + heap[7] = (alen << 3) & 255; + heap[8] = heap[9] = heap[10] = 0; + heap[11] = clen >>> 29; + heap[12] = (clen >>> 21) & 255; + heap[13] = (clen >>> 13) & 255; + heap[14] = (clen >>> 5) & 255; + heap[15] = (clen << 3) & 255; + asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16); + asm.get_iv(AES_asm.HEAP_DATA); + asm.set_counter(0, 0, 0, this.gamma0); + asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16); + result.set(heap.subarray(0, tagSize), len); + this.counter = 1; + this.aes.pos = 0; + this.aes.len = 0; + return result; + } + AES_GCM_Decrypt_process(data) { + let dpos = 0; + let dlen = data.length || 0; + let { asm, heap } = this.aes.acquire_asm(); + let counter = this.counter; + let tagSize = this.tagSize; + let pos = this.aes.pos; + let len = this.aes.len; + let rpos = 0; + let rlen = len + dlen > tagSize ? (len + dlen - tagSize) & -16 : 0; + let tlen = len + dlen - rlen; + let wlen = 0; + if (((counter - 1) << 4) + len + dlen > _AES_GCM_data_maxLength) + throw new RangeError('counter overflow'); + const result = new Uint8Array(rlen); + while (dlen > tlen) { + wlen = _heap_write(heap, pos + len, data, dpos, dlen - tlen); + len += wlen; + dpos += wlen; + dlen -= wlen; + wlen = asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, wlen); + wlen = asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, wlen); + if (wlen) + result.set(heap.subarray(pos, pos + wlen), rpos); + counter += wlen >>> 4; + rpos += wlen; + pos = 0; + len = 0; + } + if (dlen > 0) { + len += _heap_write(heap, 0, data, dpos, dlen); + } + this.counter = counter; + this.aes.pos = pos; + this.aes.len = len; + return result; + } + AES_GCM_Decrypt_finish() { + let { asm, heap } = this.aes.acquire_asm(); + let tagSize = this.tagSize; + let adata = this.adata; + let counter = this.counter; + let pos = this.aes.pos; + let len = this.aes.len; + let rlen = len - tagSize; + if (len < tagSize) + throw new IllegalStateError('authentication tag not found'); + const result = new Uint8Array(rlen); + const atag = new Uint8Array(heap.subarray(pos + rlen, pos + len)); + let i = rlen; + for (; i & 15; i++) + heap[pos + i] = 0; + asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, i); + asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, i); + if (rlen) + result.set(heap.subarray(pos, pos + rlen)); + const alen = adata !== undefined ? adata.length : 0; + const clen = ((counter - 1) << 4) + len - tagSize; + heap[0] = 0; + heap[1] = 0; + heap[2] = 0; + heap[3] = alen >>> 29; + heap[4] = alen >>> 21; + heap[5] = (alen >>> 13) & 255; + heap[6] = (alen >>> 5) & 255; + heap[7] = (alen << 3) & 255; + heap[8] = heap[9] = heap[10] = 0; + heap[11] = clen >>> 29; + heap[12] = (clen >>> 21) & 255; + heap[13] = (clen >>> 13) & 255; + heap[14] = (clen >>> 5) & 255; + heap[15] = (clen << 3) & 255; + asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16); + asm.get_iv(AES_asm.HEAP_DATA); + asm.set_counter(0, 0, 0, this.gamma0); + asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16); + let acheck = 0; + for (let i = 0; i < tagSize; ++i) + acheck |= atag[i] ^ heap[i]; + if (acheck) + throw new SecurityError('data integrity check failed'); + this.counter = 1; + this.aes.pos = 0; + this.aes.len = 0; + return result; + } + AES_GCM_decrypt(data) { + const result1 = this.AES_GCM_Decrypt_process(data); + const result2 = this.AES_GCM_Decrypt_finish(); + const result = new Uint8Array(result1.length + result2.length); + if (result1.length) + result.set(result1); + if (result2.length) + result.set(result2, result1.length); + return result; + } + AES_GCM_encrypt(data) { + const result1 = this.AES_GCM_Encrypt_process(data); + const result2 = this.AES_GCM_Encrypt_finish(); + const result = new Uint8Array(result1.length + result2.length); + if (result1.length) + result.set(result1); + if (result2.length) + result.set(result2, result1.length); + return result; + } + _gcm_mac_process(data) { + let { asm, heap } = this.aes.acquire_asm(); + let dpos = 0; + let dlen = data.length || 0; + let wlen = 0; + while (dlen > 0) { + wlen = _heap_write(heap, 0, data, dpos, dlen); + dpos += wlen; + dlen -= wlen; + while (wlen & 15) + heap[wlen++] = 0; + asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, wlen); + } + } + } + + // OpenPGP.js - An OpenPGP implementation in javascript + + const webCrypto$4 = util.getWebCrypto(); + const nodeCrypto$4 = util.getNodeCrypto(); + const Buffer$2 = util.getNodeBuffer(); + + const blockLength$3 = 16; + const ivLength$2 = 12; // size of the IV in bytes + const tagLength$2 = 16; // size of the tag in bytes + const ALGO = 'AES-GCM'; + + /** + * Class to en/decrypt using GCM mode. + * @param {enums.symmetric} cipher - The symmetric cipher algorithm to use + * @param {Uint8Array} key - The encryption key + */ + async function GCM(cipher, key) { + if (cipher !== enums.symmetric.aes128 && + cipher !== enums.symmetric.aes192 && + cipher !== enums.symmetric.aes256) { + throw new Error('GCM mode supports only AES cipher'); + } + + if (util.getWebCrypto() && key.length !== 24) { // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support + const _key = await webCrypto$4.importKey('raw', key, { name: ALGO }, false, ['encrypt', 'decrypt']); + + return { + encrypt: async function(pt, iv, adata = new Uint8Array()) { + if ( + !pt.length || + // iOS does not support GCM-en/decrypting empty messages + // Also, synchronous en/decryption might be faster in this case. + (!adata.length && navigator.userAgent && navigator.userAgent.indexOf('Edge') !== -1) + // Edge does not support GCM-en/decrypting without ADATA + ) { + return AES_GCM.encrypt(pt, key, iv, adata); + } + const ct = await webCrypto$4.encrypt({ name: ALGO, iv, additionalData: adata, tagLength: tagLength$2 * 8 }, _key, pt); + return new Uint8Array(ct); + }, + + decrypt: async function(ct, iv, adata = new Uint8Array()) { + if ( + ct.length === tagLength$2 || + // iOS does not support GCM-en/decrypting empty messages + // Also, synchronous en/decryption might be faster in this case. + (!adata.length && navigator.userAgent && navigator.userAgent.indexOf('Edge') !== -1) + // Edge does not support GCM-en/decrypting without ADATA + ) { + return AES_GCM.decrypt(ct, key, iv, adata); + } + const pt = await webCrypto$4.decrypt({ name: ALGO, iv, additionalData: adata, tagLength: tagLength$2 * 8 }, _key, ct); + return new Uint8Array(pt); + } + }; + } + + if (util.getNodeCrypto()) { // Node crypto library + return { + encrypt: async function(pt, iv, adata = new Uint8Array()) { + const en = new nodeCrypto$4.createCipheriv('aes-' + (key.length * 8) + '-gcm', key, iv); + en.setAAD(adata); + const ct = Buffer$2.concat([en.update(pt), en.final(), en.getAuthTag()]); // append auth tag to ciphertext + return new Uint8Array(ct); + }, + + decrypt: async function(ct, iv, adata = new Uint8Array()) { + const de = new nodeCrypto$4.createDecipheriv('aes-' + (key.length * 8) + '-gcm', key, iv); + de.setAAD(adata); + de.setAuthTag(ct.slice(ct.length - tagLength$2, ct.length)); // read auth tag at end of ciphertext + const pt = Buffer$2.concat([de.update(ct.slice(0, ct.length - tagLength$2)), de.final()]); + return new Uint8Array(pt); + } + }; + } + + return { + encrypt: async function(pt, iv, adata) { + return AES_GCM.encrypt(pt, key, iv, adata); + }, + + decrypt: async function(ct, iv, adata) { + return AES_GCM.decrypt(ct, key, iv, adata); + } + }; + } + + + /** + * Get GCM nonce. Note: this operation is not defined by the standard. + * A future version of the standard may define GCM mode differently, + * hopefully under a different ID (we use Private/Experimental algorithm + * ID 100) so that we can maintain backwards compatibility. + * @param {Uint8Array} iv - The initialization vector (12 bytes) + * @param {Uint8Array} chunkIndex - The chunk index (8 bytes) + */ + GCM.getNonce = function(iv, chunkIndex) { + const nonce = iv.slice(); + for (let i = 0; i < chunkIndex.length; i++) { + nonce[4 + i] ^= chunkIndex[i]; + } + return nonce; + }; + + GCM.blockLength = blockLength$3; + GCM.ivLength = ivLength$2; + GCM.tagLength = tagLength$2; + + /** + * @fileoverview Cipher modes + * @module crypto/mode + * @private + */ + + var mode = { + /** @see module:crypto/mode/cfb */ + cfb: cfb, + /** @see module:crypto/mode/gcm */ + gcm: GCM, + experimentalGCM: GCM, + /** @see module:crypto/mode/eax */ + eax: EAX, + /** @see module:crypto/mode/ocb */ + ocb: OCB + }; + + var naclFastLight = createCommonjsModule(function (module) { + /*jshint bitwise: false*/ + + (function(nacl) { + + // Ported in 2014 by Dmitry Chestnykh and Devi Mandiri. + // Public domain. + // + // Implementation derived from TweetNaCl version 20140427. + // See for details: http://tweetnacl.cr.yp.to/ + + var gf = function(init) { + var i, r = new Float64Array(16); + if (init) for (i = 0; i < init.length; i++) r[i] = init[i]; + return r; + }; + + // Pluggable, initialized in high-level API below. + var randombytes = function(/* x, n */) { throw new Error('no PRNG'); }; + + var _9 = new Uint8Array(32); _9[0] = 9; + + var gf0 = gf(), + gf1 = gf([1]), + _121665 = gf([0xdb41, 1]), + D = gf([0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203]), + D2 = gf([0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406]), + X = gf([0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169]), + Y = gf([0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666]), + I = gf([0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83]); + + function vn(x, xi, y, yi, n) { + var i,d = 0; + for (i = 0; i < n; i++) d |= x[xi+i]^y[yi+i]; + return (1 & ((d - 1) >>> 8)) - 1; + } + + function crypto_verify_32(x, xi, y, yi) { + return vn(x,xi,y,yi,32); + } + + function set25519(r, a) { + var i; + for (i = 0; i < 16; i++) r[i] = a[i]|0; + } + + function car25519(o) { + var i, v, c = 1; + for (i = 0; i < 16; i++) { + v = o[i] + c + 65535; + c = Math.floor(v / 65536); + o[i] = v - c * 65536; + } + o[0] += c-1 + 37 * (c-1); + } + + function sel25519(p, q, b) { + var t, c = ~(b-1); + for (var i = 0; i < 16; i++) { + t = c & (p[i] ^ q[i]); + p[i] ^= t; + q[i] ^= t; + } + } + + function pack25519(o, n) { + var i, j, b; + var m = gf(), t = gf(); + for (i = 0; i < 16; i++) t[i] = n[i]; + car25519(t); + car25519(t); + car25519(t); + for (j = 0; j < 2; j++) { + m[0] = t[0] - 0xffed; + for (i = 1; i < 15; i++) { + m[i] = t[i] - 0xffff - ((m[i-1]>>16) & 1); + m[i-1] &= 0xffff; + } + m[15] = t[15] - 0x7fff - ((m[14]>>16) & 1); + b = (m[15]>>16) & 1; + m[14] &= 0xffff; + sel25519(t, m, 1-b); + } + for (i = 0; i < 16; i++) { + o[2*i] = t[i] & 0xff; + o[2*i+1] = t[i]>>8; + } + } + + function neq25519(a, b) { + var c = new Uint8Array(32), d = new Uint8Array(32); + pack25519(c, a); + pack25519(d, b); + return crypto_verify_32(c, 0, d, 0); + } + + function par25519(a) { + var d = new Uint8Array(32); + pack25519(d, a); + return d[0] & 1; + } + + function unpack25519(o, n) { + var i; + for (i = 0; i < 16; i++) o[i] = n[2*i] + (n[2*i+1] << 8); + o[15] &= 0x7fff; + } + + function A(o, a, b) { + for (var i = 0; i < 16; i++) o[i] = a[i] + b[i]; + } + + function Z(o, a, b) { + for (var i = 0; i < 16; i++) o[i] = a[i] - b[i]; + } + + function M(o, a, b) { + var v, c, + t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0, + t8 = 0, t9 = 0, t10 = 0, t11 = 0, t12 = 0, t13 = 0, t14 = 0, t15 = 0, + t16 = 0, t17 = 0, t18 = 0, t19 = 0, t20 = 0, t21 = 0, t22 = 0, t23 = 0, + t24 = 0, t25 = 0, t26 = 0, t27 = 0, t28 = 0, t29 = 0, t30 = 0, + b0 = b[0], + b1 = b[1], + b2 = b[2], + b3 = b[3], + b4 = b[4], + b5 = b[5], + b6 = b[6], + b7 = b[7], + b8 = b[8], + b9 = b[9], + b10 = b[10], + b11 = b[11], + b12 = b[12], + b13 = b[13], + b14 = b[14], + b15 = b[15]; + + v = a[0]; + t0 += v * b0; + t1 += v * b1; + t2 += v * b2; + t3 += v * b3; + t4 += v * b4; + t5 += v * b5; + t6 += v * b6; + t7 += v * b7; + t8 += v * b8; + t9 += v * b9; + t10 += v * b10; + t11 += v * b11; + t12 += v * b12; + t13 += v * b13; + t14 += v * b14; + t15 += v * b15; + v = a[1]; + t1 += v * b0; + t2 += v * b1; + t3 += v * b2; + t4 += v * b3; + t5 += v * b4; + t6 += v * b5; + t7 += v * b6; + t8 += v * b7; + t9 += v * b8; + t10 += v * b9; + t11 += v * b10; + t12 += v * b11; + t13 += v * b12; + t14 += v * b13; + t15 += v * b14; + t16 += v * b15; + v = a[2]; + t2 += v * b0; + t3 += v * b1; + t4 += v * b2; + t5 += v * b3; + t6 += v * b4; + t7 += v * b5; + t8 += v * b6; + t9 += v * b7; + t10 += v * b8; + t11 += v * b9; + t12 += v * b10; + t13 += v * b11; + t14 += v * b12; + t15 += v * b13; + t16 += v * b14; + t17 += v * b15; + v = a[3]; + t3 += v * b0; + t4 += v * b1; + t5 += v * b2; + t6 += v * b3; + t7 += v * b4; + t8 += v * b5; + t9 += v * b6; + t10 += v * b7; + t11 += v * b8; + t12 += v * b9; + t13 += v * b10; + t14 += v * b11; + t15 += v * b12; + t16 += v * b13; + t17 += v * b14; + t18 += v * b15; + v = a[4]; + t4 += v * b0; + t5 += v * b1; + t6 += v * b2; + t7 += v * b3; + t8 += v * b4; + t9 += v * b5; + t10 += v * b6; + t11 += v * b7; + t12 += v * b8; + t13 += v * b9; + t14 += v * b10; + t15 += v * b11; + t16 += v * b12; + t17 += v * b13; + t18 += v * b14; + t19 += v * b15; + v = a[5]; + t5 += v * b0; + t6 += v * b1; + t7 += v * b2; + t8 += v * b3; + t9 += v * b4; + t10 += v * b5; + t11 += v * b6; + t12 += v * b7; + t13 += v * b8; + t14 += v * b9; + t15 += v * b10; + t16 += v * b11; + t17 += v * b12; + t18 += v * b13; + t19 += v * b14; + t20 += v * b15; + v = a[6]; + t6 += v * b0; + t7 += v * b1; + t8 += v * b2; + t9 += v * b3; + t10 += v * b4; + t11 += v * b5; + t12 += v * b6; + t13 += v * b7; + t14 += v * b8; + t15 += v * b9; + t16 += v * b10; + t17 += v * b11; + t18 += v * b12; + t19 += v * b13; + t20 += v * b14; + t21 += v * b15; + v = a[7]; + t7 += v * b0; + t8 += v * b1; + t9 += v * b2; + t10 += v * b3; + t11 += v * b4; + t12 += v * b5; + t13 += v * b6; + t14 += v * b7; + t15 += v * b8; + t16 += v * b9; + t17 += v * b10; + t18 += v * b11; + t19 += v * b12; + t20 += v * b13; + t21 += v * b14; + t22 += v * b15; + v = a[8]; + t8 += v * b0; + t9 += v * b1; + t10 += v * b2; + t11 += v * b3; + t12 += v * b4; + t13 += v * b5; + t14 += v * b6; + t15 += v * b7; + t16 += v * b8; + t17 += v * b9; + t18 += v * b10; + t19 += v * b11; + t20 += v * b12; + t21 += v * b13; + t22 += v * b14; + t23 += v * b15; + v = a[9]; + t9 += v * b0; + t10 += v * b1; + t11 += v * b2; + t12 += v * b3; + t13 += v * b4; + t14 += v * b5; + t15 += v * b6; + t16 += v * b7; + t17 += v * b8; + t18 += v * b9; + t19 += v * b10; + t20 += v * b11; + t21 += v * b12; + t22 += v * b13; + t23 += v * b14; + t24 += v * b15; + v = a[10]; + t10 += v * b0; + t11 += v * b1; + t12 += v * b2; + t13 += v * b3; + t14 += v * b4; + t15 += v * b5; + t16 += v * b6; + t17 += v * b7; + t18 += v * b8; + t19 += v * b9; + t20 += v * b10; + t21 += v * b11; + t22 += v * b12; + t23 += v * b13; + t24 += v * b14; + t25 += v * b15; + v = a[11]; + t11 += v * b0; + t12 += v * b1; + t13 += v * b2; + t14 += v * b3; + t15 += v * b4; + t16 += v * b5; + t17 += v * b6; + t18 += v * b7; + t19 += v * b8; + t20 += v * b9; + t21 += v * b10; + t22 += v * b11; + t23 += v * b12; + t24 += v * b13; + t25 += v * b14; + t26 += v * b15; + v = a[12]; + t12 += v * b0; + t13 += v * b1; + t14 += v * b2; + t15 += v * b3; + t16 += v * b4; + t17 += v * b5; + t18 += v * b6; + t19 += v * b7; + t20 += v * b8; + t21 += v * b9; + t22 += v * b10; + t23 += v * b11; + t24 += v * b12; + t25 += v * b13; + t26 += v * b14; + t27 += v * b15; + v = a[13]; + t13 += v * b0; + t14 += v * b1; + t15 += v * b2; + t16 += v * b3; + t17 += v * b4; + t18 += v * b5; + t19 += v * b6; + t20 += v * b7; + t21 += v * b8; + t22 += v * b9; + t23 += v * b10; + t24 += v * b11; + t25 += v * b12; + t26 += v * b13; + t27 += v * b14; + t28 += v * b15; + v = a[14]; + t14 += v * b0; + t15 += v * b1; + t16 += v * b2; + t17 += v * b3; + t18 += v * b4; + t19 += v * b5; + t20 += v * b6; + t21 += v * b7; + t22 += v * b8; + t23 += v * b9; + t24 += v * b10; + t25 += v * b11; + t26 += v * b12; + t27 += v * b13; + t28 += v * b14; + t29 += v * b15; + v = a[15]; + t15 += v * b0; + t16 += v * b1; + t17 += v * b2; + t18 += v * b3; + t19 += v * b4; + t20 += v * b5; + t21 += v * b6; + t22 += v * b7; + t23 += v * b8; + t24 += v * b9; + t25 += v * b10; + t26 += v * b11; + t27 += v * b12; + t28 += v * b13; + t29 += v * b14; + t30 += v * b15; + + t0 += 38 * t16; + t1 += 38 * t17; + t2 += 38 * t18; + t3 += 38 * t19; + t4 += 38 * t20; + t5 += 38 * t21; + t6 += 38 * t22; + t7 += 38 * t23; + t8 += 38 * t24; + t9 += 38 * t25; + t10 += 38 * t26; + t11 += 38 * t27; + t12 += 38 * t28; + t13 += 38 * t29; + t14 += 38 * t30; + // t15 left as is + + // first car + c = 1; + v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536; + v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536; + v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536; + v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536; + v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536; + v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536; + v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536; + v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536; + v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536; + v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536; + v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536; + v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536; + v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536; + v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536; + v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536; + v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536; + t0 += c-1 + 37 * (c-1); + + // second car + c = 1; + v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536; + v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536; + v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536; + v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536; + v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536; + v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536; + v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536; + v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536; + v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536; + v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536; + v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536; + v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536; + v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536; + v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536; + v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536; + v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536; + t0 += c-1 + 37 * (c-1); + + o[ 0] = t0; + o[ 1] = t1; + o[ 2] = t2; + o[ 3] = t3; + o[ 4] = t4; + o[ 5] = t5; + o[ 6] = t6; + o[ 7] = t7; + o[ 8] = t8; + o[ 9] = t9; + o[10] = t10; + o[11] = t11; + o[12] = t12; + o[13] = t13; + o[14] = t14; + o[15] = t15; + } + + function S(o, a) { + M(o, a, a); + } + + function inv25519(o, i) { + var c = gf(); + var a; + for (a = 0; a < 16; a++) c[a] = i[a]; + for (a = 253; a >= 0; a--) { + S(c, c); + if(a !== 2 && a !== 4) M(c, c, i); + } + for (a = 0; a < 16; a++) o[a] = c[a]; + } + + function pow2523(o, i) { + var c = gf(); + var a; + for (a = 0; a < 16; a++) c[a] = i[a]; + for (a = 250; a >= 0; a--) { + S(c, c); + if(a !== 1) M(c, c, i); + } + for (a = 0; a < 16; a++) o[a] = c[a]; + } + + function crypto_scalarmult(q, n, p) { + var z = new Uint8Array(32); + var x = new Float64Array(80), r, i; + var a = gf(), b = gf(), c = gf(), + d = gf(), e = gf(), f = gf(); + for (i = 0; i < 31; i++) z[i] = n[i]; + z[31]=(n[31]&127)|64; + z[0]&=248; + unpack25519(x,p); + for (i = 0; i < 16; i++) { + b[i]=x[i]; + d[i]=a[i]=c[i]=0; + } + a[0]=d[0]=1; + for (i=254; i>=0; --i) { + r=(z[i>>>3]>>>(i&7))&1; + sel25519(a,b,r); + sel25519(c,d,r); + A(e,a,c); + Z(a,a,c); + A(c,b,d); + Z(b,b,d); + S(d,e); + S(f,a); + M(a,c,a); + M(c,b,e); + A(e,a,c); + Z(a,a,c); + S(b,a); + Z(c,d,f); + M(a,c,_121665); + A(a,a,d); + M(c,c,a); + M(a,d,f); + M(d,b,x); + S(b,e); + sel25519(a,b,r); + sel25519(c,d,r); + } + for (i = 0; i < 16; i++) { + x[i+16]=a[i]; + x[i+32]=c[i]; + x[i+48]=b[i]; + x[i+64]=d[i]; + } + var x32 = x.subarray(32); + var x16 = x.subarray(16); + inv25519(x32,x32); + M(x16,x16,x32); + pack25519(q,x16); + return 0; + } + + function crypto_scalarmult_base(q, n) { + return crypto_scalarmult(q, n, _9); + } + + function crypto_box_keypair(y, x) { + randombytes(x, 32); + return crypto_scalarmult_base(y, x); + } + + function add(p, q) { + var a = gf(), b = gf(), c = gf(), + d = gf(), e = gf(), f = gf(), + g = gf(), h = gf(), t = gf(); + + Z(a, p[1], p[0]); + Z(t, q[1], q[0]); + M(a, a, t); + A(b, p[0], p[1]); + A(t, q[0], q[1]); + M(b, b, t); + M(c, p[3], q[3]); + M(c, c, D2); + M(d, p[2], q[2]); + A(d, d, d); + Z(e, b, a); + Z(f, d, c); + A(g, d, c); + A(h, b, a); + + M(p[0], e, f); + M(p[1], h, g); + M(p[2], g, f); + M(p[3], e, h); + } + + function cswap(p, q, b) { + var i; + for (i = 0; i < 4; i++) { + sel25519(p[i], q[i], b); + } + } + + function pack(r, p) { + var tx = gf(), ty = gf(), zi = gf(); + inv25519(zi, p[2]); + M(tx, p[0], zi); + M(ty, p[1], zi); + pack25519(r, ty); + r[31] ^= par25519(tx) << 7; + } + + function scalarmult(p, q, s) { + var b, i; + set25519(p[0], gf0); + set25519(p[1], gf1); + set25519(p[2], gf1); + set25519(p[3], gf0); + for (i = 255; i >= 0; --i) { + b = (s[(i/8)|0] >> (i&7)) & 1; + cswap(p, q, b); + add(q, p); + add(p, p); + cswap(p, q, b); + } + } + + function scalarbase(p, s) { + var q = [gf(), gf(), gf(), gf()]; + set25519(q[0], X); + set25519(q[1], Y); + set25519(q[2], gf1); + M(q[3], X, Y); + scalarmult(p, q, s); + } + + function crypto_sign_keypair(pk, sk, seeded) { + var d; + var p = [gf(), gf(), gf(), gf()]; + var i; + + if (!seeded) randombytes(sk, 32); + d = nacl.hash(sk.subarray(0, 32)); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + scalarbase(p, d); + pack(pk, p); + + for (i = 0; i < 32; i++) sk[i+32] = pk[i]; + return 0; + } + + var L = new Float64Array([0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10]); + + function modL(r, x) { + var carry, i, j, k; + for (i = 63; i >= 32; --i) { + carry = 0; + for (j = i - 32, k = i - 12; j < k; ++j) { + x[j] += carry - 16 * x[i] * L[j - (i - 32)]; + carry = Math.floor((x[j] + 128) / 256); + x[j] -= carry * 256; + } + x[j] += carry; + x[i] = 0; + } + carry = 0; + for (j = 0; j < 32; j++) { + x[j] += carry - (x[31] >> 4) * L[j]; + carry = x[j] >> 8; + x[j] &= 255; + } + for (j = 0; j < 32; j++) x[j] -= carry * L[j]; + for (i = 0; i < 32; i++) { + x[i+1] += x[i] >> 8; + r[i] = x[i] & 255; + } + } + + function reduce(r) { + var x = new Float64Array(64), i; + for (i = 0; i < 64; i++) x[i] = r[i]; + for (i = 0; i < 64; i++) r[i] = 0; + modL(r, x); + } + + // Note: difference from C - smlen returned, not passed as argument. + function crypto_sign(sm, m, n, sk) { + var d, h, r; + var i, j, x = new Float64Array(64); + var p = [gf(), gf(), gf(), gf()]; + + d = nacl.hash(sk.subarray(0, 32)); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + var smlen = n + 64; + for (i = 0; i < n; i++) sm[64 + i] = m[i]; + for (i = 0; i < 32; i++) sm[32 + i] = d[32 + i]; + + r = nacl.hash(sm.subarray(32, smlen)); + reduce(r); + scalarbase(p, r); + pack(sm, p); + + for (i = 32; i < 64; i++) sm[i] = sk[i]; + h = nacl.hash(sm.subarray(0, smlen)); + reduce(h); + + for (i = 0; i < 64; i++) x[i] = 0; + for (i = 0; i < 32; i++) x[i] = r[i]; + for (i = 0; i < 32; i++) { + for (j = 0; j < 32; j++) { + x[i+j] += h[i] * d[j]; + } + } + + modL(sm.subarray(32), x); + return smlen; + } + + function unpackneg(r, p) { + var t = gf(), chk = gf(), num = gf(), + den = gf(), den2 = gf(), den4 = gf(), + den6 = gf(); + + set25519(r[2], gf1); + unpack25519(r[1], p); + S(num, r[1]); + M(den, num, D); + Z(num, num, r[2]); + A(den, r[2], den); + + S(den2, den); + S(den4, den2); + M(den6, den4, den2); + M(t, den6, num); + M(t, t, den); + + pow2523(t, t); + M(t, t, num); + M(t, t, den); + M(t, t, den); + M(r[0], t, den); + + S(chk, r[0]); + M(chk, chk, den); + if (neq25519(chk, num)) M(r[0], r[0], I); + + S(chk, r[0]); + M(chk, chk, den); + if (neq25519(chk, num)) return -1; + + if (par25519(r[0]) === (p[31]>>7)) Z(r[0], gf0, r[0]); + + M(r[3], r[0], r[1]); + return 0; + } + + function crypto_sign_open(m, sm, n, pk) { + var i; + var t = new Uint8Array(32), h; + var p = [gf(), gf(), gf(), gf()], + q = [gf(), gf(), gf(), gf()]; + + if (n < 64) return -1; + + if (unpackneg(q, pk)) return -1; + + for (i = 0; i < n; i++) m[i] = sm[i]; + for (i = 0; i < 32; i++) m[i+32] = pk[i]; + h = nacl.hash(m.subarray(0, n)); + reduce(h); + scalarmult(p, q, h); + + scalarbase(q, sm.subarray(32)); + add(p, q); + pack(t, p); + + n -= 64; + if (crypto_verify_32(sm, 0, t, 0)) { + for (i = 0; i < n; i++) m[i] = 0; + return -1; + } + + for (i = 0; i < n; i++) m[i] = sm[i + 64]; + return n; + } + + var crypto_scalarmult_BYTES = 32, + crypto_scalarmult_SCALARBYTES = 32, + crypto_box_PUBLICKEYBYTES = 32, + crypto_box_SECRETKEYBYTES = 32, + crypto_sign_BYTES = 64, + crypto_sign_PUBLICKEYBYTES = 32, + crypto_sign_SECRETKEYBYTES = 64, + crypto_sign_SEEDBYTES = 32; + + function checkArrayTypes() { + for (var i = 0; i < arguments.length; i++) { + if (!(arguments[i] instanceof Uint8Array)) + throw new TypeError('unexpected type, use Uint8Array'); + } + } + + function cleanup(arr) { + for (var i = 0; i < arr.length; i++) arr[i] = 0; + } + + nacl.scalarMult = function(n, p) { + checkArrayTypes(n, p); + if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error('bad n size'); + if (p.length !== crypto_scalarmult_BYTES) throw new Error('bad p size'); + var q = new Uint8Array(crypto_scalarmult_BYTES); + crypto_scalarmult(q, n, p); + return q; + }; + + nacl.box = {}; + + nacl.box.keyPair = function() { + var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); + var sk = new Uint8Array(crypto_box_SECRETKEYBYTES); + crypto_box_keypair(pk, sk); + return {publicKey: pk, secretKey: sk}; + }; + + nacl.box.keyPair.fromSecretKey = function(secretKey) { + checkArrayTypes(secretKey); + if (secretKey.length !== crypto_box_SECRETKEYBYTES) + throw new Error('bad secret key size'); + var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); + crypto_scalarmult_base(pk, secretKey); + return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; + }; + + nacl.sign = function(msg, secretKey) { + checkArrayTypes(msg, secretKey); + if (secretKey.length !== crypto_sign_SECRETKEYBYTES) + throw new Error('bad secret key size'); + var signedMsg = new Uint8Array(crypto_sign_BYTES+msg.length); + crypto_sign(signedMsg, msg, msg.length, secretKey); + return signedMsg; + }; + + nacl.sign.detached = function(msg, secretKey) { + var signedMsg = nacl.sign(msg, secretKey); + var sig = new Uint8Array(crypto_sign_BYTES); + for (var i = 0; i < sig.length; i++) sig[i] = signedMsg[i]; + return sig; + }; + + nacl.sign.detached.verify = function(msg, sig, publicKey) { + checkArrayTypes(msg, sig, publicKey); + if (sig.length !== crypto_sign_BYTES) + throw new Error('bad signature size'); + if (publicKey.length !== crypto_sign_PUBLICKEYBYTES) + throw new Error('bad public key size'); + var sm = new Uint8Array(crypto_sign_BYTES + msg.length); + var m = new Uint8Array(crypto_sign_BYTES + msg.length); + var i; + for (i = 0; i < crypto_sign_BYTES; i++) sm[i] = sig[i]; + for (i = 0; i < msg.length; i++) sm[i+crypto_sign_BYTES] = msg[i]; + return (crypto_sign_open(m, sm, sm.length, publicKey) >= 0); + }; + + nacl.sign.keyPair = function() { + var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); + var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); + crypto_sign_keypair(pk, sk); + return {publicKey: pk, secretKey: sk}; + }; + + nacl.sign.keyPair.fromSecretKey = function(secretKey) { + checkArrayTypes(secretKey); + if (secretKey.length !== crypto_sign_SECRETKEYBYTES) + throw new Error('bad secret key size'); + var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); + for (var i = 0; i < pk.length; i++) pk[i] = secretKey[32+i]; + return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; + }; + + nacl.sign.keyPair.fromSeed = function(seed) { + checkArrayTypes(seed); + if (seed.length !== crypto_sign_SEEDBYTES) + throw new Error('bad seed size'); + var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); + var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); + for (var i = 0; i < 32; i++) sk[i] = seed[i]; + crypto_sign_keypair(pk, sk, true); + return {publicKey: pk, secretKey: sk}; + }; + + nacl.setPRNG = function(fn) { + randombytes = fn; + }; + + (function() { + // Initialize PRNG if environment provides CSPRNG. + // If not, methods calling randombytes will throw. + var crypto = typeof self !== 'undefined' ? (self.crypto || self.msCrypto) : null; + if (crypto && crypto.getRandomValues) { + // Browsers. + var QUOTA = 65536; + nacl.setPRNG(function(x, n) { + var i, v = new Uint8Array(n); + for (i = 0; i < n; i += QUOTA) { + crypto.getRandomValues(v.subarray(i, i + Math.min(n - i, QUOTA))); + } + for (i = 0; i < n; i++) x[i] = v[i]; + cleanup(v); + }); + } else if (typeof commonjsRequire !== 'undefined') { + // Node.js. + crypto = void('crypto'); + if (crypto && crypto.randomBytes) { + nacl.setPRNG(function(x, n) { + var i, v = crypto.randomBytes(n); + for (i = 0; i < n; i++) x[i] = v[i]; + cleanup(v); + }); + } + } + })(); + + })(module.exports ? module.exports : (self.nacl = self.nacl || {})); + }); + + // GPG4Browsers - An OpenPGP implementation in javascript + + const nodeCrypto$5 = util.getNodeCrypto(); + + /** + * Buffer for secure random numbers + */ + class RandomBuffer { + constructor() { + this.buffer = null; + this.size = null; + this.callback = null; + } + + /** + * Initialize buffer + * @param {Integer} size - size of buffer + */ + init(size, callback) { + this.buffer = new Uint8Array(size); + this.size = 0; + this.callback = callback; + } + + /** + * Concat array of secure random numbers to buffer + * @param {Uint8Array} buf + */ + set(buf) { + if (!this.buffer) { + throw new Error('RandomBuffer is not initialized'); + } + if (!(buf instanceof Uint8Array)) { + throw new Error('Invalid type: buf not an Uint8Array'); + } + const freeSpace = this.buffer.length - this.size; + if (buf.length > freeSpace) { + buf = buf.subarray(0, freeSpace); + } + // set buf with offset old size of buffer + this.buffer.set(buf, this.size); + this.size += buf.length; + } + + /** + * Take numbers out of buffer and copy to array + * @param {Uint8Array} buf - The destination array + */ + async get(buf) { + if (!this.buffer) { + throw new Error('RandomBuffer is not initialized'); + } + if (!(buf instanceof Uint8Array)) { + throw new Error('Invalid type: buf not an Uint8Array'); + } + if (this.size < buf.length) { + if (!this.callback) { + throw new Error('Random number buffer depleted'); + } + // Wait for random bytes from main context, then try again + await this.callback(); + return this.get(buf); + } + for (let i = 0; i < buf.length; i++) { + buf[i] = this.buffer[--this.size]; + // clear buffer value + this.buffer[this.size] = 0; + } + } + } + + /** + * Retrieve secure random byte array of the specified length + * @param {Integer} length - Length in bytes to generate + * @returns {Promise} Random byte array. + * @async + */ + async function getRandomBytes(length) { + const buf = new Uint8Array(length); + if (typeof crypto !== 'undefined' && crypto.getRandomValues) { + crypto.getRandomValues(buf); + } else if (nodeCrypto$5) { + const bytes = nodeCrypto$5.randomBytes(buf.length); + buf.set(bytes); + } else if (randomBuffer.buffer) { + await randomBuffer.get(buf); + } else { + throw new Error('No secure random number generator available.'); + } + return buf; + } + + /** + * Create a secure random BigInteger that is greater than or equal to min and less than max. + * @param {module:BigInteger} min - Lower bound, included + * @param {module:BigInteger} max - Upper bound, excluded + * @returns {Promise} Random BigInteger. + * @async + */ + async function getRandomBigInteger(min, max) { + const BigInteger = await util.getBigInteger(); + + if (max.lt(min)) { + throw new Error('Illegal parameter value: max <= min'); + } + + const modulus = max.sub(min); + const bytes = modulus.byteLength(); + + // Using a while loop is necessary to avoid bias introduced by the mod operation. + // However, we request 64 extra random bits so that the bias is negligible. + // Section B.1.1 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf + const r = new BigInteger(await getRandomBytes(bytes + 8)); + return r.mod(modulus).add(min); + } + + const randomBuffer = new RandomBuffer(); + + var random = /*#__PURE__*/Object.freeze({ + __proto__: null, + getRandomBytes: getRandomBytes, + getRandomBigInteger: getRandomBigInteger, + randomBuffer: randomBuffer + }); + + // OpenPGP.js - An OpenPGP implementation in javascript + + /** + * Generate a probably prime random number + * @param {Integer} bits - Bit length of the prime + * @param {BigInteger} e - Optional RSA exponent to check against the prime + * @param {Integer} k - Optional number of iterations of Miller-Rabin test + * @returns BigInteger + * @async + */ + async function randomProbablePrime(bits, e, k) { + const BigInteger = await util.getBigInteger(); + const one = new BigInteger(1); + const min = one.leftShift(new BigInteger(bits - 1)); + const thirty = new BigInteger(30); + /* + * We can avoid any multiples of 3 and 5 by looking at n mod 30 + * n mod 30 = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 + * the next possible prime is mod 30: + * 1 7 7 7 7 7 7 11 11 11 11 13 13 17 17 17 17 19 19 23 23 23 23 29 29 29 29 29 29 1 + */ + const adds = [1, 6, 5, 4, 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, 3, 2, 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1, 2]; + + const n = await getRandomBigInteger(min, min.leftShift(one)); + let i = n.mod(thirty).toNumber(); + + do { + n.iadd(new BigInteger(adds[i])); + i = (i + adds[i]) % adds.length; + // If reached the maximum, go back to the minimum. + if (n.bitLength() > bits) { + n.imod(min.leftShift(one)).iadd(min); + i = n.mod(thirty).toNumber(); + } + } while (!await isProbablePrime(n, e, k)); + return n; + } + + /** + * Probabilistic primality testing + * @param {BigInteger} n - Number to test + * @param {BigInteger} e - Optional RSA exponent to check against the prime + * @param {Integer} k - Optional number of iterations of Miller-Rabin test + * @returns {boolean} + * @async + */ + async function isProbablePrime(n, e, k) { + if (e && !n.dec().gcd(e).isOne()) { + return false; + } + if (!await divisionTest(n)) { + return false; + } + if (!await fermat(n)) { + return false; + } + if (!await millerRabin(n, k)) { + return false; + } + // TODO implement the Lucas test + // See Section C.3.3 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf + return true; + } + + /** + * Tests whether n is probably prime or not using Fermat's test with b = 2. + * Fails if b^(n-1) mod n != 1. + * @param {BigInteger} n - Number to test + * @param {BigInteger} b - Optional Fermat test base + * @returns {boolean} + */ + async function fermat(n, b) { + const BigInteger = await util.getBigInteger(); + b = b || new BigInteger(2); + return b.modExp(n.dec(), n).isOne(); + } + + async function divisionTest(n) { + const BigInteger = await util.getBigInteger(); + return smallPrimes.every(m => { + return n.mod(new BigInteger(m)) !== 0; + }); + } + + // https://github.com/gpg/libgcrypt/blob/master/cipher/primegen.c + const smallPrimes = [ + 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, + 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, + 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, + 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, + 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, + 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, + 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, + 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, + 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, + 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, + 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, + 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, + 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, + 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, + 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, + 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, + 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, + 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, + 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, + 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, + 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, + 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, + 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, + 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, + 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, + 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, + 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, + 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, + 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, + 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, + 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, + 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, + 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, + 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, + 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, + 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, + 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, + 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, + 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, + 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, + 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, + 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, + 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, + 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, + 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, + 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, + 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, + 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, + 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, + 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, + 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, + 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, + 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, + 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, + 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, + 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, + 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, + 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, + 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, + 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, + 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, + 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, + 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, + 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, + 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, + 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, + 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, + 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, + 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, + 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, + 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457, + 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, + 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, + 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, + 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, + 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, + 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, + 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, + 4957, 4967, 4969, 4973, 4987, 4993, 4999 + ]; + + + // Miller-Rabin - Miller Rabin algorithm for primality test + // Copyright Fedor Indutny, 2014. + // + // This software is licensed under the MIT License. + // + // Permission is hereby granted, free of charge, to any person obtaining a + // copy of this software and associated documentation files (the + // "Software"), to deal in the Software without restriction, including + // without limitation the rights to use, copy, modify, merge, publish, + // distribute, sublicense, and/or sell copies of the Software, and to permit + // persons to whom the Software is furnished to do so, subject to the + // following conditions: + // + // The above copyright notice and this permission notice shall be included + // in all copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + // USE OR OTHER DEALINGS IN THE SOFTWARE. + + // Adapted on Jan 2018 from version 4.0.1 at https://github.com/indutny/miller-rabin + + // Sample syntax for Fixed-Base Miller-Rabin: + // millerRabin(n, k, () => new BN(small_primes[Math.random() * small_primes.length | 0])) + + /** + * Tests whether n is probably prime or not using the Miller-Rabin test. + * See HAC Remark 4.28. + * @param {BigInteger} n - Number to test + * @param {Integer} k - Optional number of iterations of Miller-Rabin test + * @param {Function} rand - Optional function to generate potential witnesses + * @returns {boolean} + * @async + */ + async function millerRabin(n, k, rand) { + const BigInteger = await util.getBigInteger(); + const len = n.bitLength(); + + if (!k) { + k = Math.max(1, (len / 48) | 0); + } + + const n1 = n.dec(); // n - 1 + + // Find d and s, (n - 1) = (2 ^ s) * d; + let s = 0; + while (!n1.getBit(s)) { s++; } + const d = n.rightShift(new BigInteger(s)); + + for (; k > 0; k--) { + const a = rand ? rand() : await getRandomBigInteger(new BigInteger(2), n1); + + let x = a.modExp(d, n); + if (x.isOne() || x.equal(n1)) { + continue; + } + + let i; + for (i = 1; i < s; i++) { + x = x.mul(x).mod(n); + + if (x.isOne()) { + return false; + } + if (x.equal(n1)) { + break; + } + } + + if (i === s) { + return false; + } + } + + return true; + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + /** + * ASN1 object identifiers for hashes + * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.2} + */ + const hash_headers = []; + hash_headers[1] = [0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, + 0x10]; + hash_headers[2] = [0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14]; + hash_headers[3] = [0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14]; + hash_headers[8] = [0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, + 0x04, 0x20]; + hash_headers[9] = [0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, + 0x04, 0x30]; + hash_headers[10] = [0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, + 0x00, 0x04, 0x40]; + hash_headers[11] = [0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, + 0x00, 0x04, 0x1C]; + + /** + * Create padding with secure random data + * @private + * @param {Integer} length - Length of the padding in bytes + * @returns {Promise} Random padding. + * @async + */ + async function getPKCS1Padding(length) { + const result = new Uint8Array(length); + let count = 0; + while (count < length) { + const randomBytes = await getRandomBytes(length - count); + for (let i = 0; i < randomBytes.length; i++) { + if (randomBytes[i] !== 0) { + result[count++] = randomBytes[i]; + } + } + } + return result; + } + + /** + * Create a EME-PKCS1-v1_5 padded message + * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.1|RFC 4880 13.1.1} + * @param {Uint8Array} message - Message to be encoded + * @param {Integer} keyLength - The length in octets of the key modulus + * @returns {Promise} EME-PKCS1 padded message. + * @async + */ + async function emeEncode(message, keyLength) { + const mLength = message.length; + // length checking + if (mLength > keyLength - 11) { + throw new Error('Message too long'); + } + // Generate an octet string PS of length k - mLen - 3 consisting of + // pseudo-randomly generated nonzero octets + const PS = await getPKCS1Padding(keyLength - mLength - 3); + // Concatenate PS, the message M, and other padding to form an + // encoded message EM of length k octets as EM = 0x00 || 0x02 || PS || 0x00 || M. + const encoded = new Uint8Array(keyLength); + // 0x00 byte + encoded[1] = 2; + encoded.set(PS, 2); + // 0x00 bytes + encoded.set(message, keyLength - mLength); + return encoded; + } + + /** + * Decode a EME-PKCS1-v1_5 padded message + * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.2|RFC 4880 13.1.2} + * @param {Uint8Array} encoded - Encoded message bytes + * @param {Uint8Array} randomPayload - Data to return in case of decoding error (needed for constant-time processing) + * @returns {Uint8Array} decoded data or `randomPayload` (on error, if given) + * @throws {Error} on decoding failure, unless `randomPayload` is provided + */ + function emeDecode(encoded, randomPayload) { + // encoded format: 0x00 0x02 0x00 + let offset = 2; + let separatorNotFound = 1; + for (let j = offset; j < encoded.length; j++) { + separatorNotFound &= encoded[j] !== 0; + offset += separatorNotFound; + } + + const psLen = offset - 2; + const payload = encoded.subarray(offset + 1); // discard the 0x00 separator + const isValidPadding = encoded[0] === 0 & encoded[1] === 2 & psLen >= 8 & !separatorNotFound; + + if (randomPayload) { + return util.selectUint8Array(isValidPadding, payload, randomPayload); + } + + if (isValidPadding) { + return payload; + } + + throw new Error('Decryption error'); + } + + /** + * Create a EMSA-PKCS1-v1_5 padded message + * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.3|RFC 4880 13.1.3} + * @param {Integer} algo - Hash algorithm type used + * @param {Uint8Array} hashed - Message to be encoded + * @param {Integer} emLen - Intended length in octets of the encoded message + * @returns {Uint8Array} Encoded message. + */ + async function emsaEncode(algo, hashed, emLen) { + let i; + if (hashed.length !== hash.getHashByteLength(algo)) { + throw new Error('Invalid hash length'); + } + // produce an ASN.1 DER value for the hash function used. + // Let T be the full hash prefix + const hashPrefix = new Uint8Array(hash_headers[algo].length); + for (i = 0; i < hash_headers[algo].length; i++) { + hashPrefix[i] = hash_headers[algo][i]; + } + // and let tLen be the length in octets prefix and hashed data + const tLen = hashPrefix.length + hashed.length; + if (emLen < tLen + 11) { + throw new Error('Intended encoded message length too short'); + } + // an octet string PS consisting of emLen - tLen - 3 octets with hexadecimal value 0xFF + // The length of PS will be at least 8 octets + const PS = new Uint8Array(emLen - tLen - 3).fill(0xff); + + // Concatenate PS, the hash prefix, hashed data, and other padding to form the + // encoded message EM as EM = 0x00 || 0x01 || PS || 0x00 || prefix || hashed + const EM = new Uint8Array(emLen); + EM[1] = 0x01; + EM.set(PS, 2); + EM.set(hashPrefix, emLen - tLen); + EM.set(hashed, emLen - hashed.length); + return EM; + } + + var pkcs1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + emeEncode: emeEncode, + emeDecode: emeDecode, + emsaEncode: emsaEncode + }); + + // GPG4Browsers - An OpenPGP implementation in javascript + + const webCrypto$5 = util.getWebCrypto(); + const nodeCrypto$6 = util.getNodeCrypto(); + const asn1 = nodeCrypto$6 ? void('asn1.js') : undefined; + + /* eslint-disable no-invalid-this */ + const RSAPrivateKey = util.detectNode() ? asn1.define('RSAPrivateKey', function () { + this.seq().obj( // used for native NodeJS crypto + this.key('version').int(), // 0 + this.key('modulus').int(), // n + this.key('publicExponent').int(), // e + this.key('privateExponent').int(), // d + this.key('prime1').int(), // p + this.key('prime2').int(), // q + this.key('exponent1').int(), // dp + this.key('exponent2').int(), // dq + this.key('coefficient').int() // u + ); + }) : undefined; + + const RSAPublicKey = util.detectNode() ? asn1.define('RSAPubliceKey', function () { + this.seq().obj( // used for native NodeJS crypto + this.key('modulus').int(), // n + this.key('publicExponent').int(), // e + ); + }) : undefined; + /* eslint-enable no-invalid-this */ + + /** Create signature + * @param {module:enums.hash} hashAlgo - Hash algorithm + * @param {Uint8Array} data - Message + * @param {Uint8Array} n - RSA public modulus + * @param {Uint8Array} e - RSA public exponent + * @param {Uint8Array} d - RSA private exponent + * @param {Uint8Array} p - RSA private prime p + * @param {Uint8Array} q - RSA private prime q + * @param {Uint8Array} u - RSA private coefficient + * @param {Uint8Array} hashed - Hashed message + * @returns {Promise} RSA Signature. + * @async + */ + async function sign(hashAlgo, data, n, e, d, p, q, u, hashed) { + if (data && !util.isStream(data)) { + if (util.getWebCrypto()) { + try { + return await webSign(enums.read(enums.webHash, hashAlgo), data, n, e, d, p, q, u); + } catch (err) { + util.printDebugError(err); + } + } else if (util.getNodeCrypto()) { + return nodeSign(hashAlgo, data, n, e, d, p, q, u); + } + } + return bnSign(hashAlgo, n, d, hashed); + } + + /** + * Verify signature + * @param {module:enums.hash} hashAlgo - Hash algorithm + * @param {Uint8Array} data - Message + * @param {Uint8Array} s - Signature + * @param {Uint8Array} n - RSA public modulus + * @param {Uint8Array} e - RSA public exponent + * @param {Uint8Array} hashed - Hashed message + * @returns {Boolean} + * @async + */ + async function verify(hashAlgo, data, s, n, e, hashed) { + if (data && !util.isStream(data)) { + if (util.getWebCrypto()) { + try { + return await webVerify(enums.read(enums.webHash, hashAlgo), data, s, n, e); + } catch (err) { + util.printDebugError(err); + } + } else if (util.getNodeCrypto()) { + return nodeVerify(hashAlgo, data, s, n, e); + } + } + return bnVerify(hashAlgo, s, n, e, hashed); + } + + /** + * Encrypt message + * @param {Uint8Array} data - Message + * @param {Uint8Array} n - RSA public modulus + * @param {Uint8Array} e - RSA public exponent + * @returns {Promise} RSA Ciphertext. + * @async + */ + async function encrypt$1(data, n, e) { + if (util.getNodeCrypto()) { + return nodeEncrypt$1(data, n, e); + } + return bnEncrypt(data, n, e); + } + + /** + * Decrypt RSA message + * @param {Uint8Array} m - Message + * @param {Uint8Array} n - RSA public modulus + * @param {Uint8Array} e - RSA public exponent + * @param {Uint8Array} d - RSA private exponent + * @param {Uint8Array} p - RSA private prime p + * @param {Uint8Array} q - RSA private prime q + * @param {Uint8Array} u - RSA private coefficient + * @param {Uint8Array} randomPayload - Data to return on decryption error, instead of throwing + * (needed for constant-time processing) + * @returns {Promise} RSA Plaintext. + * @throws {Error} on decryption error, unless `randomPayload` is given + * @async + */ + async function decrypt$1(data, n, e, d, p, q, u, randomPayload) { + if (util.getNodeCrypto()) { + return nodeDecrypt$1(data, n, e, d, p, q, u, randomPayload); + } + return bnDecrypt(data, n, e, d, p, q, u, randomPayload); + } + + /** + * Generate a new random private key B bits long with public exponent E. + * + * When possible, webCrypto or nodeCrypto is used. Otherwise, primes are generated using + * 40 rounds of the Miller-Rabin probabilistic random prime generation algorithm. + * @see module:crypto/public_key/prime + * @param {Integer} bits - RSA bit length + * @param {Integer} e - RSA public exponent + * @returns {{n, e, d, + * p, q ,u: Uint8Array}} RSA public modulus, RSA public exponent, RSA private exponent, + * RSA private prime p, RSA private prime q, u = p ** -1 mod q + * @async + */ + async function generate(bits, e) { + const BigInteger = await util.getBigInteger(); + + e = new BigInteger(e); + + // Native RSA keygen using Web Crypto + if (util.getWebCrypto()) { + const keyGenOpt = { + name: 'RSASSA-PKCS1-v1_5', + modulusLength: bits, // the specified keysize in bits + publicExponent: e.toUint8Array(), // take three bytes (max 65537) for exponent + hash: { + name: 'SHA-1' // not required for actual RSA keys, but for crypto api 'sign' and 'verify' + } + }; + const keyPair = await webCrypto$5.generateKey(keyGenOpt, true, ['sign', 'verify']); + + // export the generated keys as JsonWebKey (JWK) + // https://tools.ietf.org/html/draft-ietf-jose-json-web-key-33 + const jwk = await webCrypto$5.exportKey('jwk', keyPair.privateKey); + // map JWK parameters to corresponding OpenPGP names + return { + n: b64ToUint8Array(jwk.n), + e: e.toUint8Array(), + d: b64ToUint8Array(jwk.d), + // switch p and q + p: b64ToUint8Array(jwk.q), + q: b64ToUint8Array(jwk.p), + // Since p and q are switched in places, u is the inverse of jwk.q + u: b64ToUint8Array(jwk.qi) + }; + } else if (util.getNodeCrypto() && nodeCrypto$6.generateKeyPair && RSAPrivateKey) { + const opts = { + modulusLength: bits, + publicExponent: e.toNumber(), + publicKeyEncoding: { type: 'pkcs1', format: 'der' }, + privateKeyEncoding: { type: 'pkcs1', format: 'der' } + }; + const prv = await new Promise((resolve, reject) => nodeCrypto$6.generateKeyPair('rsa', opts, (err, _, der) => { + if (err) { + reject(err); + } else { + resolve(RSAPrivateKey.decode(der, 'der')); + } + })); + /** + * OpenPGP spec differs from DER spec, DER: `u = (inverse of q) mod p`, OpenPGP: `u = (inverse of p) mod q`. + * @link https://tools.ietf.org/html/rfc3447#section-3.2 + * @link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-08#section-5.6.1 + */ + return { + n: prv.modulus.toArrayLike(Uint8Array), + e: prv.publicExponent.toArrayLike(Uint8Array), + d: prv.privateExponent.toArrayLike(Uint8Array), + // switch p and q + p: prv.prime2.toArrayLike(Uint8Array), + q: prv.prime1.toArrayLike(Uint8Array), + // Since p and q are switched in places, we can keep u as defined by DER + u: prv.coefficient.toArrayLike(Uint8Array) + }; + } + + // RSA keygen fallback using 40 iterations of the Miller-Rabin test + // See https://stackoverflow.com/a/6330138 for justification + // Also see section C.3 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST + let p; + let q; + let n; + do { + q = await randomProbablePrime(bits - (bits >> 1), e, 40); + p = await randomProbablePrime(bits >> 1, e, 40); + n = p.mul(q); + } while (n.bitLength() !== bits); + + const phi = p.dec().imul(q.dec()); + + if (q.lt(p)) { + [p, q] = [q, p]; + } + + return { + n: n.toUint8Array(), + e: e.toUint8Array(), + d: e.modInv(phi).toUint8Array(), + p: p.toUint8Array(), + q: q.toUint8Array(), + // dp: d.mod(p.subn(1)), + // dq: d.mod(q.subn(1)), + u: p.modInv(q).toUint8Array() + }; + } + + /** + * Validate RSA parameters + * @param {Uint8Array} n - RSA public modulus + * @param {Uint8Array} e - RSA public exponent + * @param {Uint8Array} d - RSA private exponent + * @param {Uint8Array} p - RSA private prime p + * @param {Uint8Array} q - RSA private prime q + * @param {Uint8Array} u - RSA inverse of p w.r.t. q + * @returns {Promise} Whether params are valid. + * @async + */ + async function validateParams(n, e, d, p, q, u) { + const BigInteger = await util.getBigInteger(); + n = new BigInteger(n); + p = new BigInteger(p); + q = new BigInteger(q); + + // expect pq = n + if (!p.mul(q).equal(n)) { + return false; + } + + const two = new BigInteger(2); + // expect p*u = 1 mod q + u = new BigInteger(u); + if (!p.mul(u).mod(q).isOne()) { + return false; + } + + e = new BigInteger(e); + d = new BigInteger(d); + /** + * In RSA pkcs#1 the exponents (d, e) are inverses modulo lcm(p-1, q-1) + * We check that [de = 1 mod (p-1)] and [de = 1 mod (q-1)] + * By CRT on coprime factors of (p-1, q-1) it follows that [de = 1 mod lcm(p-1, q-1)] + * + * We blind the multiplication with r, and check that rde = r mod lcm(p-1, q-1) + */ + const nSizeOver3 = new BigInteger(Math.floor(n.bitLength() / 3)); + const r = await getRandomBigInteger(two, two.leftShift(nSizeOver3)); // r in [ 2, 2^{|n|/3} ) < p and q + const rde = r.mul(d).mul(e); + + const areInverses = rde.mod(p.dec()).equal(r) && rde.mod(q.dec()).equal(r); + if (!areInverses) { + return false; + } + + return true; + } + + async function bnSign(hashAlgo, n, d, hashed) { + const BigInteger = await util.getBigInteger(); + n = new BigInteger(n); + const m = new BigInteger(await emsaEncode(hashAlgo, hashed, n.byteLength())); + d = new BigInteger(d); + if (m.gte(n)) { + throw new Error('Message size cannot exceed modulus size'); + } + return m.modExp(d, n).toUint8Array('be', n.byteLength()); + } + + async function webSign(hashName, data, n, e, d, p, q, u) { + /** OpenPGP keys require that p < q, and Safari Web Crypto requires that p > q. + * We swap them in privateToJWK, so it usually works out, but nevertheless, + * not all OpenPGP keys are compatible with this requirement. + * OpenPGP.js used to generate RSA keys the wrong way around (p > q), and still + * does if the underlying Web Crypto does so (e.g. old MS Edge 50% of the time). + */ + const jwk = await privateToJWK(n, e, d, p, q, u); + const algo = { + name: 'RSASSA-PKCS1-v1_5', + hash: { name: hashName } + }; + const key = await webCrypto$5.importKey('jwk', jwk, algo, false, ['sign']); + // add hash field for ms edge support + return new Uint8Array(await webCrypto$5.sign({ 'name': 'RSASSA-PKCS1-v1_5', 'hash': hashName }, key, data)); + } + + async function nodeSign(hashAlgo, data, n, e, d, p, q, u) { + const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); + const pBNum = new BN(p); + const qBNum = new BN(q); + const dBNum = new BN(d); + const dq = dBNum.mod(qBNum.subn(1)); // d mod (q-1) + const dp = dBNum.mod(pBNum.subn(1)); // d mod (p-1) + const sign = nodeCrypto$6.createSign(enums.read(enums.hash, hashAlgo)); + sign.write(data); + sign.end(); + const keyObject = { + version: 0, + modulus: new BN(n), + publicExponent: new BN(e), + privateExponent: new BN(d), + // switch p and q + prime1: new BN(q), + prime2: new BN(p), + // switch dp and dq + exponent1: dq, + exponent2: dp, + coefficient: new BN(u) + }; + if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { //from version 11.6.0 Node supports der encoded key objects + const der = RSAPrivateKey.encode(keyObject, 'der'); + return new Uint8Array(sign.sign({ key: der, format: 'der', type: 'pkcs1' })); + } + const pem = RSAPrivateKey.encode(keyObject, 'pem', { + label: 'RSA PRIVATE KEY' + }); + return new Uint8Array(sign.sign(pem)); + } + + async function bnVerify(hashAlgo, s, n, e, hashed) { + const BigInteger = await util.getBigInteger(); + n = new BigInteger(n); + s = new BigInteger(s); + e = new BigInteger(e); + if (s.gte(n)) { + throw new Error('Signature size cannot exceed modulus size'); + } + const EM1 = s.modExp(e, n).toUint8Array('be', n.byteLength()); + const EM2 = await emsaEncode(hashAlgo, hashed, n.byteLength()); + return util.equalsUint8Array(EM1, EM2); + } + + async function webVerify(hashName, data, s, n, e) { + const jwk = publicToJWK(n, e); + const key = await webCrypto$5.importKey('jwk', jwk, { + name: 'RSASSA-PKCS1-v1_5', + hash: { name: hashName } + }, false, ['verify']); + // add hash field for ms edge support + return webCrypto$5.verify({ 'name': 'RSASSA-PKCS1-v1_5', 'hash': hashName }, key, s, data); + } + + async function nodeVerify(hashAlgo, data, s, n, e) { + const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); + + const verify = nodeCrypto$6.createVerify(enums.read(enums.hash, hashAlgo)); + verify.write(data); + verify.end(); + const keyObject = { + modulus: new BN(n), + publicExponent: new BN(e) + }; + let key; + if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { //from version 11.6.0 Node supports der encoded key objects + const der = RSAPublicKey.encode(keyObject, 'der'); + key = { key: der, format: 'der', type: 'pkcs1' }; + } else { + key = RSAPublicKey.encode(keyObject, 'pem', { + label: 'RSA PUBLIC KEY' + }); + } + try { + return await verify.verify(key, s); + } catch (err) { + return false; + } + } + + async function nodeEncrypt$1(data, n, e) { + const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); + + const keyObject = { + modulus: new BN(n), + publicExponent: new BN(e) + }; + let key; + if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { + const der = RSAPublicKey.encode(keyObject, 'der'); + key = { key: der, format: 'der', type: 'pkcs1', padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; + } else { + const pem = RSAPublicKey.encode(keyObject, 'pem', { + label: 'RSA PUBLIC KEY' + }); + key = { key: pem, padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; + } + return new Uint8Array(nodeCrypto$6.publicEncrypt(key, data)); + } + + async function bnEncrypt(data, n, e) { + const BigInteger = await util.getBigInteger(); + n = new BigInteger(n); + data = new BigInteger(await emeEncode(data, n.byteLength())); + e = new BigInteger(e); + if (data.gte(n)) { + throw new Error('Message size cannot exceed modulus size'); + } + return data.modExp(e, n).toUint8Array('be', n.byteLength()); + } + + async function nodeDecrypt$1(data, n, e, d, p, q, u, randomPayload) { + const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); + + const pBNum = new BN(p); + const qBNum = new BN(q); + const dBNum = new BN(d); + const dq = dBNum.mod(qBNum.subn(1)); // d mod (q-1) + const dp = dBNum.mod(pBNum.subn(1)); // d mod (p-1) + const keyObject = { + version: 0, + modulus: new BN(n), + publicExponent: new BN(e), + privateExponent: new BN(d), + // switch p and q + prime1: new BN(q), + prime2: new BN(p), + // switch dp and dq + exponent1: dq, + exponent2: dp, + coefficient: new BN(u) + }; + let key; + if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { + const der = RSAPrivateKey.encode(keyObject, 'der'); + key = { key: der, format: 'der' , type: 'pkcs1', padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; + } else { + const pem = RSAPrivateKey.encode(keyObject, 'pem', { + label: 'RSA PRIVATE KEY' + }); + key = { key: pem, padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; + } + try { + return new Uint8Array(nodeCrypto$6.privateDecrypt(key, data)); + } catch (err) { + if (randomPayload) { + return randomPayload; + } + throw new Error('Decryption error'); + } + } + + async function bnDecrypt(data, n, e, d, p, q, u, randomPayload) { + const BigInteger = await util.getBigInteger(); + data = new BigInteger(data); + n = new BigInteger(n); + e = new BigInteger(e); + d = new BigInteger(d); + p = new BigInteger(p); + q = new BigInteger(q); + u = new BigInteger(u); + if (data.gte(n)) { + throw new Error('Data too large.'); + } + const dq = d.mod(q.dec()); // d mod (q-1) + const dp = d.mod(p.dec()); // d mod (p-1) + + const unblinder = (await getRandomBigInteger(new BigInteger(2), n)).mod(n); + const blinder = unblinder.modInv(n).modExp(e, n); + data = data.mul(blinder).mod(n); + + + const mp = data.modExp(dp, p); // data**{d mod (q-1)} mod p + const mq = data.modExp(dq, q); // data**{d mod (p-1)} mod q + const h = u.mul(mq.sub(mp)).mod(q); // u * (mq-mp) mod q (operands already < q) + + let result = h.mul(p).add(mp); // result < n due to relations above + + result = result.mul(unblinder).mod(n); + + + return emeDecode(result.toUint8Array('be', n.byteLength()), randomPayload); + } + + /** Convert Openpgp private key params to jwk key according to + * @link https://tools.ietf.org/html/rfc7517 + * @param {String} hashAlgo + * @param {Uint8Array} n + * @param {Uint8Array} e + * @param {Uint8Array} d + * @param {Uint8Array} p + * @param {Uint8Array} q + * @param {Uint8Array} u + */ + async function privateToJWK(n, e, d, p, q, u) { + const BigInteger = await util.getBigInteger(); + const pNum = new BigInteger(p); + const qNum = new BigInteger(q); + const dNum = new BigInteger(d); + + let dq = dNum.mod(qNum.dec()); // d mod (q-1) + let dp = dNum.mod(pNum.dec()); // d mod (p-1) + dp = dp.toUint8Array(); + dq = dq.toUint8Array(); + return { + kty: 'RSA', + n: uint8ArrayToB64(n, true), + e: uint8ArrayToB64(e, true), + d: uint8ArrayToB64(d, true), + // switch p and q + p: uint8ArrayToB64(q, true), + q: uint8ArrayToB64(p, true), + // switch dp and dq + dp: uint8ArrayToB64(dq, true), + dq: uint8ArrayToB64(dp, true), + qi: uint8ArrayToB64(u, true), + ext: true + }; + } + + /** Convert Openpgp key public params to jwk key according to + * @link https://tools.ietf.org/html/rfc7517 + * @param {String} hashAlgo + * @param {Uint8Array} n + * @param {Uint8Array} e + */ + function publicToJWK(n, e) { + return { + kty: 'RSA', + n: uint8ArrayToB64(n, true), + e: uint8ArrayToB64(e, true), + ext: true + }; + } + + var rsa = /*#__PURE__*/Object.freeze({ + __proto__: null, + sign: sign, + verify: verify, + encrypt: encrypt$1, + decrypt: decrypt$1, + generate: generate, + validateParams: validateParams + }); + + // GPG4Browsers - An OpenPGP implementation in javascript + + /** + * ElGamal Encryption function + * Note that in OpenPGP, the message needs to be padded with PKCS#1 (same as RSA) + * @param {Uint8Array} data - To be padded and encrypted + * @param {Uint8Array} p + * @param {Uint8Array} g + * @param {Uint8Array} y + * @returns {Promise<{ c1: Uint8Array, c2: Uint8Array }>} + * @async + */ + async function encrypt$2(data, p, g, y) { + const BigInteger = await util.getBigInteger(); + p = new BigInteger(p); + g = new BigInteger(g); + y = new BigInteger(y); + + const padded = await emeEncode(data, p.byteLength()); + const m = new BigInteger(padded); + + // OpenPGP uses a "special" version of ElGamal where g is generator of the full group Z/pZ* + // hence g has order p-1, and to avoid that k = 0 mod p-1, we need to pick k in [1, p-2] + const k = await getRandomBigInteger(new BigInteger(1), p.dec()); + return { + c1: g.modExp(k, p).toUint8Array(), + c2: y.modExp(k, p).imul(m).imod(p).toUint8Array() + }; + } + + /** + * ElGamal Encryption function + * @param {Uint8Array} c1 + * @param {Uint8Array} c2 + * @param {Uint8Array} p + * @param {Uint8Array} x + * @param {Uint8Array} randomPayload - Data to return on unpadding error, instead of throwing + * (needed for constant-time processing) + * @returns {Promise} Unpadded message. + * @throws {Error} on decryption error, unless `randomPayload` is given + * @async + */ + async function decrypt$2(c1, c2, p, x, randomPayload) { + const BigInteger = await util.getBigInteger(); + c1 = new BigInteger(c1); + c2 = new BigInteger(c2); + p = new BigInteger(p); + x = new BigInteger(x); + + const padded = c1.modExp(x, p).modInv(p).imul(c2).imod(p); + return emeDecode(padded.toUint8Array('be', p.byteLength()), randomPayload); + } + + /** + * Validate ElGamal parameters + * @param {Uint8Array} p - ElGamal prime + * @param {Uint8Array} g - ElGamal group generator + * @param {Uint8Array} y - ElGamal public key + * @param {Uint8Array} x - ElGamal private exponent + * @returns {Promise} Whether params are valid. + * @async + */ + async function validateParams$1(p, g, y, x) { + const BigInteger = await util.getBigInteger(); + p = new BigInteger(p); + g = new BigInteger(g); + y = new BigInteger(y); + + const one = new BigInteger(1); + // Check that 1 < g < p + if (g.lte(one) || g.gte(p)) { + return false; + } + + // Expect p-1 to be large + const pSize = new BigInteger(p.bitLength()); + const n1023 = new BigInteger(1023); + if (pSize.lt(n1023)) { + return false; + } + + /** + * g should have order p-1 + * Check that g ** (p-1) = 1 mod p + */ + if (!g.modExp(p.dec(), p).isOne()) { + return false; + } + + /** + * Since p-1 is not prime, g might have a smaller order that divides p-1 + * We want to make sure that the order is large enough to hinder a small subgroup attack + * + * We just check g**i != 1 for all i up to a threshold + */ + let res = g; + const i = new BigInteger(1); + const threshold = new BigInteger(2).leftShift(new BigInteger(17)); // we want order > threshold + while (i.lt(threshold)) { + res = res.mul(g).imod(p); + if (res.isOne()) { + return false; + } + i.iinc(); + } + + /** + * Re-derive public key y' = g ** x mod p + * Expect y == y' + * + * Blinded exponentiation computes g**{r(p-1) + x} to compare to y + */ + x = new BigInteger(x); + const two = new BigInteger(2); + const r = await getRandomBigInteger(two.leftShift(pSize.dec()), two.leftShift(pSize)); // draw r of same size as p-1 + const rqx = p.dec().imul(r).iadd(x); + if (!y.equal(g.modExp(rqx, p))) { + return false; + } + + return true; + } + + var elgamal = /*#__PURE__*/Object.freeze({ + __proto__: null, + encrypt: encrypt$2, + decrypt: decrypt$2, + validateParams: validateParams$1 + }); + + // OpenPGP.js - An OpenPGP implementation in javascript + + class OID { + constructor(oid) { + if (oid instanceof OID) { + this.oid = oid.oid; + } else if (util.isArray(oid) || + util.isUint8Array(oid)) { + oid = new Uint8Array(oid); + if (oid[0] === 0x06) { // DER encoded oid byte array + if (oid[1] !== oid.length - 2) { + throw new Error('Length mismatch in DER encoded oid'); + } + oid = oid.subarray(2); + } + this.oid = oid; + } else { + this.oid = ''; + } + } + + /** + * Method to read an OID object + * @param {Uint8Array} input - Where to read the OID from + * @returns {Number} Number of read bytes. + */ + read(input) { + if (input.length >= 1) { + const length = input[0]; + if (input.length >= 1 + length) { + this.oid = input.subarray(1, 1 + length); + return 1 + this.oid.length; + } + } + throw new Error('Invalid oid'); + } + + /** + * Serialize an OID object + * @returns {Uint8Array} Array with the serialized value the OID. + */ + write() { + return util.concatUint8Array([new Uint8Array([this.oid.length]), this.oid]); + } + + /** + * Serialize an OID object as a hex string + * @returns {string} String with the hex value of the OID. + */ + toHex() { + return util.uint8ArrayToHex(this.oid); + } + + /** + * If a known curve object identifier, return the canonical name of the curve + * @returns {string} String with the canonical name of the curve. + */ + getName() { + const hex = this.toHex(); + if (enums.curve[hex]) { + return enums.write(enums.curve, hex); + } else { + throw new Error('Unknown curve object identifier.'); + } + } + } + + // OpenPGP.js - An OpenPGP implementation in javascript + + function keyFromPrivate(indutnyCurve, priv) { + const keyPair = indutnyCurve.keyPair({ priv: priv }); + return keyPair; + } + + function keyFromPublic(indutnyCurve, pub) { + const keyPair = indutnyCurve.keyPair({ pub: pub }); + if (keyPair.validate().result !== true) { + throw new Error('Invalid elliptic public key'); + } + return keyPair; + } + + async function getIndutnyCurve(name) { + if (!defaultConfig.useIndutnyElliptic) { + throw new Error('This curve is only supported in the full build of OpenPGP.js'); + } + const { default: elliptic } = await Promise.resolve().then(function () { return elliptic$1; }); + return new elliptic.ec(name); + } + + // OpenPGP.js - An OpenPGP implementation in javascript + + const webCrypto$6 = util.getWebCrypto(); + const nodeCrypto$7 = util.getNodeCrypto(); + + const webCurves = { + 'p256': 'P-256', + 'p384': 'P-384', + 'p521': 'P-521' + }; + const knownCurves = nodeCrypto$7 ? nodeCrypto$7.getCurves() : []; + const nodeCurves = nodeCrypto$7 ? { + secp256k1: knownCurves.includes('secp256k1') ? 'secp256k1' : undefined, + p256: knownCurves.includes('prime256v1') ? 'prime256v1' : undefined, + p384: knownCurves.includes('secp384r1') ? 'secp384r1' : undefined, + p521: knownCurves.includes('secp521r1') ? 'secp521r1' : undefined, + ed25519: knownCurves.includes('ED25519') ? 'ED25519' : undefined, + curve25519: knownCurves.includes('X25519') ? 'X25519' : undefined, + brainpoolP256r1: knownCurves.includes('brainpoolP256r1') ? 'brainpoolP256r1' : undefined, + brainpoolP384r1: knownCurves.includes('brainpoolP384r1') ? 'brainpoolP384r1' : undefined, + brainpoolP512r1: knownCurves.includes('brainpoolP512r1') ? 'brainpoolP512r1' : undefined + } : {}; + + const curves = { + p256: { + oid: [0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07], + keyType: enums.publicKey.ecdsa, + hash: enums.hash.sha256, + cipher: enums.symmetric.aes128, + node: nodeCurves.p256, + web: webCurves.p256, + payloadSize: 32, + sharedSize: 256 + }, + p384: { + oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22], + keyType: enums.publicKey.ecdsa, + hash: enums.hash.sha384, + cipher: enums.symmetric.aes192, + node: nodeCurves.p384, + web: webCurves.p384, + payloadSize: 48, + sharedSize: 384 + }, + p521: { + oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23], + keyType: enums.publicKey.ecdsa, + hash: enums.hash.sha512, + cipher: enums.symmetric.aes256, + node: nodeCurves.p521, + web: webCurves.p521, + payloadSize: 66, + sharedSize: 528 + }, + secp256k1: { + oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x0A], + keyType: enums.publicKey.ecdsa, + hash: enums.hash.sha256, + cipher: enums.symmetric.aes128, + node: nodeCurves.secp256k1, + payloadSize: 32 + }, + ed25519: { + oid: [0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01], + keyType: enums.publicKey.eddsa, + hash: enums.hash.sha512, + node: false, // nodeCurves.ed25519 TODO + payloadSize: 32 + }, + curve25519: { + oid: [0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01], + keyType: enums.publicKey.ecdh, + hash: enums.hash.sha256, + cipher: enums.symmetric.aes128, + node: false, // nodeCurves.curve25519 TODO + payloadSize: 32 + }, + brainpoolP256r1: { + oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07], + keyType: enums.publicKey.ecdsa, + hash: enums.hash.sha256, + cipher: enums.symmetric.aes128, + node: nodeCurves.brainpoolP256r1, + payloadSize: 32 + }, + brainpoolP384r1: { + oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B], + keyType: enums.publicKey.ecdsa, + hash: enums.hash.sha384, + cipher: enums.symmetric.aes192, + node: nodeCurves.brainpoolP384r1, + payloadSize: 48 + }, + brainpoolP512r1: { + oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D], + keyType: enums.publicKey.ecdsa, + hash: enums.hash.sha512, + cipher: enums.symmetric.aes256, + node: nodeCurves.brainpoolP512r1, + payloadSize: 64 + } + }; + + class Curve { + constructor(oidOrName, params) { + try { + if (util.isArray(oidOrName) || + util.isUint8Array(oidOrName)) { + // by oid byte array + oidOrName = new OID(oidOrName); + } + if (oidOrName instanceof OID) { + // by curve OID + oidOrName = oidOrName.getName(); + } + // by curve name or oid string + this.name = enums.write(enums.curve, oidOrName); + } catch (err) { + throw new Error('Not valid curve'); + } + params = params || curves[this.name]; + + this.keyType = params.keyType; + + this.oid = params.oid; + this.hash = params.hash; + this.cipher = params.cipher; + this.node = params.node && curves[this.name]; + this.web = params.web && curves[this.name]; + this.payloadSize = params.payloadSize; + if (this.web && util.getWebCrypto()) { + this.type = 'web'; + } else if (this.node && util.getNodeCrypto()) { + this.type = 'node'; + } else if (this.name === 'curve25519') { + this.type = 'curve25519'; + } else if (this.name === 'ed25519') { + this.type = 'ed25519'; + } + } + + async genKeyPair() { + let keyPair; + switch (this.type) { + case 'web': + try { + return await webGenKeyPair(this.name); + } catch (err) { + util.printDebugError('Browser did not support generating ec key ' + err.message); + break; + } + case 'node': + return nodeGenKeyPair(this.name); + case 'curve25519': { + const privateKey = await getRandomBytes(32); + privateKey[0] = (privateKey[0] & 127) | 64; + privateKey[31] &= 248; + const secretKey = privateKey.slice().reverse(); + keyPair = naclFastLight.box.keyPair.fromSecretKey(secretKey); + const publicKey = util.concatUint8Array([new Uint8Array([0x40]), keyPair.publicKey]); + return { publicKey, privateKey }; + } + case 'ed25519': { + const privateKey = await getRandomBytes(32); + const keyPair = naclFastLight.sign.keyPair.fromSeed(privateKey); + const publicKey = util.concatUint8Array([new Uint8Array([0x40]), keyPair.publicKey]); + return { publicKey, privateKey }; + } + } + const indutnyCurve = await getIndutnyCurve(this.name); + keyPair = await indutnyCurve.genKeyPair({ + entropy: util.uint8ArrayToString(await getRandomBytes(32)) + }); + return { publicKey: new Uint8Array(keyPair.getPublic('array', false)), privateKey: keyPair.getPrivate().toArrayLike(Uint8Array) }; + } + } + + async function generate$1(curve) { + const BigInteger = await util.getBigInteger(); + + curve = new Curve(curve); + const keyPair = await curve.genKeyPair(); + const Q = new BigInteger(keyPair.publicKey).toUint8Array(); + const secret = new BigInteger(keyPair.privateKey).toUint8Array('be', curve.payloadSize); + return { + oid: curve.oid, + Q, + secret, + hash: curve.hash, + cipher: curve.cipher + }; + } + + /** + * Get preferred hash algo to use with the given curve + * @param {module:type/oid} oid - curve oid + * @returns {enums.hash} hash algorithm + */ + function getPreferredHashAlgo(oid) { + return curves[enums.write(enums.curve, oid.toHex())].hash; + } + + /** + * Validate ECDH and ECDSA parameters + * Not suitable for EdDSA (different secret key format) + * @param {module:enums.publicKey} algo - EC algorithm, to filter supported curves + * @param {module:type/oid} oid - EC object identifier + * @param {Uint8Array} Q - EC public point + * @param {Uint8Array} d - EC secret scalar + * @returns {Promise} Whether params are valid. + * @async + */ + async function validateStandardParams(algo, oid, Q, d) { + const supportedCurves = { + p256: true, + p384: true, + p521: true, + secp256k1: true, + curve25519: algo === enums.publicKey.ecdh, + brainpoolP256r1: true, + brainpoolP384r1: true, + brainpoolP512r1: true + }; + + // Check whether the given curve is supported + const curveName = oid.getName(); + if (!supportedCurves[curveName]) { + return false; + } + + if (curveName === 'curve25519') { + d = d.slice().reverse(); + // Re-derive public point Q' + const { publicKey } = naclFastLight.box.keyPair.fromSecretKey(d); + + Q = new Uint8Array(Q); + const dG = new Uint8Array([0x40, ...publicKey]); // Add public key prefix + if (!util.equalsUint8Array(dG, Q)) { + return false; + } + + return true; + } + + const curve = await getIndutnyCurve(curveName); + try { + // Parse Q and check that it is on the curve but not at infinity + Q = keyFromPublic(curve, Q).getPublic(); + } catch (validationErrors) { + return false; + } + + /** + * Re-derive public point Q' = dG from private key + * Expect Q == Q' + */ + const dG = keyFromPrivate(curve, d).getPublic(); + if (!dG.eq(Q)) { + return false; + } + + return true; + } + + ////////////////////////// + // // + // Helper functions // + // // + ////////////////////////// + + + async function webGenKeyPair(name) { + // Note: keys generated with ECDSA and ECDH are structurally equivalent + const webCryptoKey = await webCrypto$6.generateKey({ name: 'ECDSA', namedCurve: webCurves[name] }, true, ['sign', 'verify']); + + const privateKey = await webCrypto$6.exportKey('jwk', webCryptoKey.privateKey); + const publicKey = await webCrypto$6.exportKey('jwk', webCryptoKey.publicKey); + + return { + publicKey: jwkToRawPublic(publicKey), + privateKey: b64ToUint8Array(privateKey.d) + }; + } + + async function nodeGenKeyPair(name) { + // Note: ECDSA and ECDH key generation is structurally equivalent + const ecdh = nodeCrypto$7.createECDH(nodeCurves[name]); + await ecdh.generateKeys(); + return { + publicKey: new Uint8Array(ecdh.getPublicKey()), + privateKey: new Uint8Array(ecdh.getPrivateKey()) + }; + } + + ////////////////////////// + // // + // Helper functions // + // // + ////////////////////////// + + /** + * @param {JsonWebKey} jwk - key for conversion + * + * @returns {Uint8Array} Raw public key. + */ + function jwkToRawPublic(jwk) { + const bufX = b64ToUint8Array(jwk.x); + const bufY = b64ToUint8Array(jwk.y); + const publicKey = new Uint8Array(bufX.length + bufY.length + 1); + publicKey[0] = 0x04; + publicKey.set(bufX, 1); + publicKey.set(bufY, bufX.length + 1); + return publicKey; + } + + /** + * @param {Integer} payloadSize - ec payload size + * @param {String} name - curve name + * @param {Uint8Array} publicKey - public key + * + * @returns {JsonWebKey} Public key in jwk format. + */ + function rawPublicToJWK(payloadSize, name, publicKey) { + const len = payloadSize; + const bufX = publicKey.slice(1, len + 1); + const bufY = publicKey.slice(len + 1, len * 2 + 1); + // https://www.rfc-editor.org/rfc/rfc7518.txt + const jwk = { + kty: 'EC', + crv: name, + x: uint8ArrayToB64(bufX, true), + y: uint8ArrayToB64(bufY, true), + ext: true + }; + return jwk; + } + + /** + * @param {Integer} payloadSize - ec payload size + * @param {String} name - curve name + * @param {Uint8Array} publicKey - public key + * @param {Uint8Array} privateKey - private key + * + * @returns {JsonWebKey} Private key in jwk format. + */ + function privateToJWK$1(payloadSize, name, publicKey, privateKey) { + const jwk = rawPublicToJWK(payloadSize, name, publicKey); + jwk.d = uint8ArrayToB64(privateKey, true); + return jwk; + } + + // OpenPGP.js - An OpenPGP implementation in javascript + + const webCrypto$7 = util.getWebCrypto(); + const nodeCrypto$8 = util.getNodeCrypto(); + + /** + * Sign a message using the provided key + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {module:enums.hash} hashAlgo - Hash algorithm used to sign + * @param {Uint8Array} message - Message to sign + * @param {Uint8Array} publicKey - Public key + * @param {Uint8Array} privateKey - Private key used to sign the message + * @param {Uint8Array} hashed - The hashed message + * @returns {Promise<{ + * r: Uint8Array, + * s: Uint8Array + * }>} Signature of the message + * @async + */ + async function sign$1(oid, hashAlgo, message, publicKey, privateKey, hashed) { + const curve = new Curve(oid); + if (message && !util.isStream(message)) { + const keyPair = { publicKey, privateKey }; + switch (curve.type) { + case 'web': { + // If browser doesn't support a curve, we'll catch it + try { + // Need to await to make sure browser succeeds + return await webSign$1(curve, hashAlgo, message, keyPair); + } catch (err) { + // We do not fallback if the error is related to key integrity + // Unfortunaley Safari does not support p521 and throws a DataError when using it + // So we need to always fallback for that curve + if (curve.name !== 'p521' && (err.name === 'DataError' || err.name === 'OperationError')) { + throw err; + } + util.printDebugError('Browser did not support signing: ' + err.message); + } + break; + } + case 'node': { + const signature = await nodeSign$1(curve, hashAlgo, message, keyPair); + return { + r: signature.r.toArrayLike(Uint8Array), + s: signature.s.toArrayLike(Uint8Array) + }; + } + } + } + return ellipticSign(curve, hashed, privateKey); + } + + /** + * Verifies if a signature is valid for a message + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {module:enums.hash} hashAlgo - Hash algorithm used in the signature + * @param {{r: Uint8Array, + s: Uint8Array}} signature Signature to verify + * @param {Uint8Array} message - Message to verify + * @param {Uint8Array} publicKey - Public key used to verify the message + * @param {Uint8Array} hashed - The hashed message + * @returns {Boolean} + * @async + */ + async function verify$1(oid, hashAlgo, signature, message, publicKey, hashed) { + const curve = new Curve(oid); + if (message && !util.isStream(message)) { + switch (curve.type) { + case 'web': + try { + // Need to await to make sure browser succeeds + return await webVerify$1(curve, hashAlgo, signature, message, publicKey); + } catch (err) { + // We do not fallback if the error is related to key integrity + // Unfortunately Safari does not support p521 and throws a DataError when using it + // So we need to always fallback for that curve + if (curve.name !== 'p521' && (err.name === 'DataError' || err.name === 'OperationError')) { + throw err; + } + util.printDebugError('Browser did not support verifying: ' + err.message); + } + break; + case 'node': + return nodeVerify$1(curve, hashAlgo, signature, message, publicKey); + } + } + const digest = (typeof hashAlgo === 'undefined') ? message : hashed; + return ellipticVerify(curve, signature, digest, publicKey); + } + + /** + * Validate ECDSA parameters + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {Uint8Array} Q - ECDSA public point + * @param {Uint8Array} d - ECDSA secret scalar + * @returns {Promise} Whether params are valid. + * @async + */ + async function validateParams$2(oid, Q, d) { + const curve = new Curve(oid); + // Reject curves x25519 and ed25519 + if (curve.keyType !== enums.publicKey.ecdsa) { + return false; + } + + // To speed up the validation, we try to use node- or webcrypto when available + // and sign + verify a random message + switch (curve.type) { + case 'web': + case 'node': { + const message = await getRandomBytes(8); + const hashAlgo = enums.hash.sha256; + const hashed = await hash.digest(hashAlgo, message); + try { + const signature = await sign$1(oid, hashAlgo, message, Q, d, hashed); + return await verify$1(oid, hashAlgo, signature, message, Q, hashed); + } catch (err) { + return false; + } + } + default: + return validateStandardParams(enums.publicKey.ecdsa, oid, Q, d); + } + } + + + ////////////////////////// + // // + // Helper functions // + // // + ////////////////////////// + + async function ellipticSign(curve, hashed, privateKey) { + const indutnyCurve = await getIndutnyCurve(curve.name); + const key = keyFromPrivate(indutnyCurve, privateKey); + const signature = key.sign(hashed); + return { + r: signature.r.toArrayLike(Uint8Array), + s: signature.s.toArrayLike(Uint8Array) + }; + } + + async function ellipticVerify(curve, signature, digest, publicKey) { + const indutnyCurve = await getIndutnyCurve(curve.name); + const key = keyFromPublic(indutnyCurve, publicKey); + return key.verify(digest, signature); + } + + async function webSign$1(curve, hashAlgo, message, keyPair) { + const len = curve.payloadSize; + const jwk = privateToJWK$1(curve.payloadSize, webCurves[curve.name], keyPair.publicKey, keyPair.privateKey); + const key = await webCrypto$7.importKey( + 'jwk', + jwk, + { + 'name': 'ECDSA', + 'namedCurve': webCurves[curve.name], + 'hash': { name: enums.read(enums.webHash, curve.hash) } + }, + false, + ['sign'] + ); + + const signature = new Uint8Array(await webCrypto$7.sign( + { + 'name': 'ECDSA', + 'namedCurve': webCurves[curve.name], + 'hash': { name: enums.read(enums.webHash, hashAlgo) } + }, + key, + message + )); + + return { + r: signature.slice(0, len), + s: signature.slice(len, len << 1) + }; + } + + async function webVerify$1(curve, hashAlgo, { r, s }, message, publicKey) { + const jwk = rawPublicToJWK(curve.payloadSize, webCurves[curve.name], publicKey); + const key = await webCrypto$7.importKey( + 'jwk', + jwk, + { + 'name': 'ECDSA', + 'namedCurve': webCurves[curve.name], + 'hash': { name: enums.read(enums.webHash, curve.hash) } + }, + false, + ['verify'] + ); + + const signature = util.concatUint8Array([r, s]).buffer; + + return webCrypto$7.verify( + { + 'name': 'ECDSA', + 'namedCurve': webCurves[curve.name], + 'hash': { name: enums.read(enums.webHash, hashAlgo) } + }, + key, + signature, + message + ); + } + + async function nodeSign$1(curve, hashAlgo, message, keyPair) { + const sign = nodeCrypto$8.createSign(enums.read(enums.hash, hashAlgo)); + sign.write(message); + sign.end(); + const key = ECPrivateKey.encode({ + version: 1, + parameters: curve.oid, + privateKey: Array.from(keyPair.privateKey), + publicKey: { unused: 0, data: Array.from(keyPair.publicKey) } + }, 'pem', { + label: 'EC PRIVATE KEY' + }); + + return ECDSASignature.decode(sign.sign(key), 'der'); + } + + async function nodeVerify$1(curve, hashAlgo, { r, s }, message, publicKey) { + const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); + + const verify = nodeCrypto$8.createVerify(enums.read(enums.hash, hashAlgo)); + verify.write(message); + verify.end(); + const key = SubjectPublicKeyInfo.encode({ + algorithm: { + algorithm: [1, 2, 840, 10045, 2, 1], + parameters: curve.oid + }, + subjectPublicKey: { unused: 0, data: Array.from(publicKey) } + }, 'pem', { + label: 'PUBLIC KEY' + }); + const signature = ECDSASignature.encode({ + r: new BN(r), s: new BN(s) + }, 'der'); + + try { + return verify.verify(key, signature); + } catch (err) { + return false; + } + } + + // Originally written by Owen Smith https://github.com/omsmith + // Adapted on Feb 2018 from https://github.com/Brightspace/node-jwk-to-pem/ + + /* eslint-disable no-invalid-this */ + + const asn1$1 = nodeCrypto$8 ? void('asn1.js') : undefined; + + const ECDSASignature = nodeCrypto$8 ? + asn1$1.define('ECDSASignature', function() { + this.seq().obj( + this.key('r').int(), + this.key('s').int() + ); + }) : undefined; + + const ECPrivateKey = nodeCrypto$8 ? + asn1$1.define('ECPrivateKey', function() { + this.seq().obj( + this.key('version').int(), + this.key('privateKey').octstr(), + this.key('parameters').explicit(0).optional().any(), + this.key('publicKey').explicit(1).optional().bitstr() + ); + }) : undefined; + + const AlgorithmIdentifier = nodeCrypto$8 ? + asn1$1.define('AlgorithmIdentifier', function() { + this.seq().obj( + this.key('algorithm').objid(), + this.key('parameters').optional().any() + ); + }) : undefined; + + const SubjectPublicKeyInfo = nodeCrypto$8 ? + asn1$1.define('SubjectPublicKeyInfo', function() { + this.seq().obj( + this.key('algorithm').use(AlgorithmIdentifier), + this.key('subjectPublicKey').bitstr() + ); + }) : undefined; + + var ecdsa = /*#__PURE__*/Object.freeze({ + __proto__: null, + sign: sign$1, + verify: verify$1, + validateParams: validateParams$2 + }); + + // OpenPGP.js - An OpenPGP implementation in javascript + + naclFastLight.hash = bytes => new Uint8Array(_512().update(bytes).digest()); + + /** + * Sign a message using the provided key + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {module:enums.hash} hashAlgo - Hash algorithm used to sign (must be sha256 or stronger) + * @param {Uint8Array} message - Message to sign + * @param {Uint8Array} publicKey - Public key + * @param {Uint8Array} privateKey - Private key used to sign the message + * @param {Uint8Array} hashed - The hashed message + * @returns {Promise<{ + * r: Uint8Array, + * s: Uint8Array + * }>} Signature of the message + * @async + */ + async function sign$2(oid, hashAlgo, message, publicKey, privateKey, hashed) { + if (hash.getHashByteLength(hashAlgo) < hash.getHashByteLength(enums.hash.sha256)) { + // see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2 + throw new Error('Hash algorithm too weak: sha256 or stronger is required for EdDSA.'); + } + const secretKey = util.concatUint8Array([privateKey, publicKey.subarray(1)]); + const signature = naclFastLight.sign.detached(hashed, secretKey); + // EdDSA signature params are returned in little-endian format + return { + r: signature.subarray(0, 32), + s: signature.subarray(32) + }; + } + + /** + * Verifies if a signature is valid for a message + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {module:enums.hash} hashAlgo - Hash algorithm used in the signature + * @param {{r: Uint8Array, + s: Uint8Array}} signature Signature to verify the message + * @param {Uint8Array} m - Message to verify + * @param {Uint8Array} publicKey - Public key used to verify the message + * @param {Uint8Array} hashed - The hashed message + * @returns {Boolean} + * @async + */ + async function verify$2(oid, hashAlgo, { r, s }, m, publicKey, hashed) { + const signature = util.concatUint8Array([r, s]); + return naclFastLight.sign.detached.verify(hashed, signature, publicKey.subarray(1)); + } + /** + * Validate EdDSA parameters + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {Uint8Array} Q - EdDSA public point + * @param {Uint8Array} k - EdDSA secret seed + * @returns {Promise} Whether params are valid. + * @async + */ + async function validateParams$3(oid, Q, k) { + // Check whether the given curve is supported + if (oid.getName() !== 'ed25519') { + return false; + } + + /** + * Derive public point Q' = dG from private key + * and expect Q == Q' + */ + const { publicKey } = naclFastLight.sign.keyPair.fromSeed(k); + const dG = new Uint8Array([0x40, ...publicKey]); // Add public key prefix + return util.equalsUint8Array(Q, dG); + } + + var eddsa = /*#__PURE__*/Object.freeze({ + __proto__: null, + sign: sign$2, + verify: verify$2, + validateParams: validateParams$3 + }); + + // OpenPGP.js - An OpenPGP implementation in javascript + + /** + * AES key wrap + * @function + * @param {Uint8Array} key + * @param {Uint8Array} data + * @returns {Uint8Array} + */ + function wrap(key, data) { + const aes = new cipher['aes' + (key.length * 8)](key); + const IV = new Uint32Array([0xA6A6A6A6, 0xA6A6A6A6]); + const P = unpack(data); + let A = IV; + const R = P; + const n = P.length / 2; + const t = new Uint32Array([0, 0]); + let B = new Uint32Array(4); + for (let j = 0; j <= 5; ++j) { + for (let i = 0; i < n; ++i) { + t[1] = n * j + (1 + i); + // B = A + B[0] = A[0]; + B[1] = A[1]; + // B = A || R[i] + B[2] = R[2 * i]; + B[3] = R[2 * i + 1]; + // B = AES(K, B) + B = unpack(aes.encrypt(pack(B))); + // A = MSB(64, B) ^ t + A = B.subarray(0, 2); + A[0] ^= t[0]; + A[1] ^= t[1]; + // R[i] = LSB(64, B) + R[2 * i] = B[2]; + R[2 * i + 1] = B[3]; + } + } + return pack(A, R); + } + + /** + * AES key unwrap + * @function + * @param {String} key + * @param {String} data + * @returns {Uint8Array} + * @throws {Error} + */ + function unwrap(key, data) { + const aes = new cipher['aes' + (key.length * 8)](key); + const IV = new Uint32Array([0xA6A6A6A6, 0xA6A6A6A6]); + const C = unpack(data); + let A = C.subarray(0, 2); + const R = C.subarray(2); + const n = C.length / 2 - 1; + const t = new Uint32Array([0, 0]); + let B = new Uint32Array(4); + for (let j = 5; j >= 0; --j) { + for (let i = n - 1; i >= 0; --i) { + t[1] = n * j + (i + 1); + // B = A ^ t + B[0] = A[0] ^ t[0]; + B[1] = A[1] ^ t[1]; + // B = (A ^ t) || R[i] + B[2] = R[2 * i]; + B[3] = R[2 * i + 1]; + // B = AES-1(B) + B = unpack(aes.decrypt(pack(B))); + // A = MSB(64, B) + A = B.subarray(0, 2); + // R[i] = LSB(64, B) + R[2 * i] = B[2]; + R[2 * i + 1] = B[3]; + } + } + if (A[0] === IV[0] && A[1] === IV[1]) { + return pack(R); + } + throw new Error('Key Data Integrity failed'); + } + + function createArrayBuffer(data) { + if (util.isString(data)) { + const { length } = data; + const buffer = new ArrayBuffer(length); + const view = new Uint8Array(buffer); + for (let j = 0; j < length; ++j) { + view[j] = data.charCodeAt(j); + } + return buffer; + } + return new Uint8Array(data).buffer; + } + + function unpack(data) { + const { length } = data; + const buffer = createArrayBuffer(data); + const view = new DataView(buffer); + const arr = new Uint32Array(length / 4); + for (let i = 0; i < length / 4; ++i) { + arr[i] = view.getUint32(4 * i); + } + return arr; + } + + function pack() { + let length = 0; + for (let k = 0; k < arguments.length; ++k) { + length += 4 * arguments[k].length; + } + const buffer = new ArrayBuffer(length); + const view = new DataView(buffer); + let offset = 0; + for (let i = 0; i < arguments.length; ++i) { + for (let j = 0; j < arguments[i].length; ++j) { + view.setUint32(offset + 4 * j, arguments[i][j]); + } + offset += 4 * arguments[i].length; + } + return new Uint8Array(buffer); + } + + var aesKW = /*#__PURE__*/Object.freeze({ + __proto__: null, + wrap: wrap, + unwrap: unwrap + }); + + // OpenPGP.js - An OpenPGP implementation in javascript + + /** + * @fileoverview Functions to add and remove PKCS5 padding + * @see PublicKeyEncryptedSessionKeyPacket + * @module crypto/pkcs5 + * @private + */ + + /** + * Add pkcs5 padding to a message + * @param {Uint8Array} message - message to pad + * @returns {Uint8Array} Padded message. + */ + function encode$1(message) { + const c = 8 - (message.length % 8); + const padded = new Uint8Array(message.length + c).fill(c); + padded.set(message); + return padded; + } + + /** + * Remove pkcs5 padding from a message + * @param {Uint8Array} message - message to remove padding from + * @returns {Uint8Array} Message without padding. + */ + function decode$1(message) { + const len = message.length; + if (len > 0) { + const c = message[len - 1]; + if (c >= 1) { + const provided = message.subarray(len - c); + const computed = new Uint8Array(c).fill(c); + if (util.equalsUint8Array(provided, computed)) { + return message.subarray(0, len - c); + } + } + } + throw new Error('Invalid padding'); + } + + var pkcs5 = /*#__PURE__*/Object.freeze({ + __proto__: null, + encode: encode$1, + decode: decode$1 + }); + + // OpenPGP.js - An OpenPGP implementation in javascript + + class ECDHSymmetricKey { + constructor(data) { + if (typeof data === 'undefined') { + data = new Uint8Array([]); + } else if (util.isString(data)) { + data = util.stringToUint8Array(data); + } else { + data = new Uint8Array(data); + } + this.data = data; + } + + /** + * Read an ECDHSymmetricKey from an Uint8Array + * @param {Uint8Array} input - Where to read the encoded symmetric key from + * @returns {Number} Number of read bytes. + */ + read(input) { + if (input.length >= 1) { + const length = input[0]; + if (input.length >= 1 + length) { + this.data = input.subarray(1, 1 + length); + return 1 + this.data.length; + } + } + throw new Error('Invalid symmetric key'); + } + + /** + * Write an ECDHSymmetricKey as an Uint8Array + * @returns {Uint8Array} An array containing the value + */ + write() { + return util.concatUint8Array([new Uint8Array([this.data.length]), this.data]); + } + } + + // OpenPGP.js - An OpenPGP implementation in javascript + // Copyright (C) 2015-2016 Decentral + // + // This library is free software; you can redistribute it and/or + // modify it under the terms of the GNU Lesser General Public + // License as published by the Free Software Foundation; either + // version 3.0 of the License, or (at your option) any later version. + // + // This library is distributed in the hope that it will be useful, + // but WITHOUT ANY WARRANTY; without even the implied warranty of + // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + // Lesser General Public License for more details. + // + // You should have received a copy of the GNU Lesser General Public + // License along with this library; if not, write to the Free Software + // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + /** + * Implementation of type KDF parameters + * + * {@link https://tools.ietf.org/html/rfc6637#section-7|RFC 6637 7}: + * A key derivation function (KDF) is necessary to implement the EC + * encryption. The Concatenation Key Derivation Function (Approved + * Alternative 1) [NIST-SP800-56A] with the KDF hash function that is + * SHA2-256 [FIPS-180-3] or stronger is REQUIRED. + * @module type/kdf_params + * @private + */ + + class KDFParams { + /** + * @param {enums.hash} hash - Hash algorithm + * @param {enums.symmetric} cipher - Symmetric algorithm + */ + constructor(data) { + if (data) { + const { hash, cipher } = data; + this.hash = hash; + this.cipher = cipher; + } else { + this.hash = null; + this.cipher = null; + } + } + + /** + * Read KDFParams from an Uint8Array + * @param {Uint8Array} input - Where to read the KDFParams from + * @returns {Number} Number of read bytes. + */ + read(input) { + if (input.length < 4 || input[0] !== 3 || input[1] !== 1) { + throw new Error('Cannot read KDFParams'); + } + this.hash = input[2]; + this.cipher = input[3]; + return 4; + } + + /** + * Write KDFParams to an Uint8Array + * @returns {Uint8Array} Array with the KDFParams value + */ + write() { + return new Uint8Array([3, 1, this.hash, this.cipher]); + } + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + /** + * Encrypts data using specified algorithm and public key parameters. + * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} for public key algorithms. + * @param {module:enums.publicKey} algo - Public key algorithm + * @param {Object} publicParams - Algorithm-specific public key parameters + * @param {Uint8Array} data - Data to be encrypted + * @param {Uint8Array} fingerprint - Recipient fingerprint + * @returns {Promise} Encrypted session key parameters. + * @async + */ + async function publicKeyEncrypt(algo, publicParams, data, fingerprint) { + switch (algo) { + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaEncryptSign: { + const { n, e } = publicParams; + const c = await publicKey.rsa.encrypt(data, n, e); + return { c }; + } + case enums.publicKey.elgamal: { + const { p, g, y } = publicParams; + return publicKey.elgamal.encrypt(data, p, g, y); + } + case enums.publicKey.ecdh: { + const { oid, Q, kdfParams } = publicParams; + const { publicKey: V, wrappedKey: C } = await publicKey.elliptic.ecdh.encrypt( + oid, kdfParams, data, Q, fingerprint); + return { V, C: new ECDHSymmetricKey(C) }; + } + default: + return []; + } + } + + /** + * Decrypts data using specified algorithm and private key parameters. + * See {@link https://tools.ietf.org/html/rfc4880#section-5.5.3|RFC 4880 5.5.3} + * @param {module:enums.publicKey} algo - Public key algorithm + * @param {Object} publicKeyParams - Algorithm-specific public key parameters + * @param {Object} privateKeyParams - Algorithm-specific private key parameters + * @param {Object} sessionKeyParams - Encrypted session key parameters + * @param {Uint8Array} fingerprint - Recipient fingerprint + * @param {Uint8Array} [randomPayload] - Data to return on decryption error, instead of throwing + * (needed for constant-time processing in RSA and ElGamal) + * @returns {Promise} Decrypted data. + * @throws {Error} on sensitive decryption error, unless `randomPayload` is given + * @async + */ + async function publicKeyDecrypt(algo, publicKeyParams, privateKeyParams, sessionKeyParams, fingerprint, randomPayload) { + switch (algo) { + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaEncrypt: { + const { c } = sessionKeyParams; + const { n, e } = publicKeyParams; + const { d, p, q, u } = privateKeyParams; + return publicKey.rsa.decrypt(c, n, e, d, p, q, u, randomPayload); + } + case enums.publicKey.elgamal: { + const { c1, c2 } = sessionKeyParams; + const p = publicKeyParams.p; + const x = privateKeyParams.x; + return publicKey.elgamal.decrypt(c1, c2, p, x, randomPayload); + } + case enums.publicKey.ecdh: { + const { oid, Q, kdfParams } = publicKeyParams; + const { d } = privateKeyParams; + const { V, C } = sessionKeyParams; + return publicKey.elliptic.ecdh.decrypt( + oid, kdfParams, V, C.data, Q, d, fingerprint); + } + default: + throw new Error('Invalid public key encryption algorithm.'); + } + } + + /** + * Parse public key material in binary form to get the key parameters + * @param {module:enums.publicKey} algo - The key algorithm + * @param {Uint8Array} bytes - The key material to parse + * @returns {{ read: Number, publicParams: Object }} Number of read bytes plus key parameters referenced by name. + */ + function parsePublicKeyParams(algo, bytes) { + let read = 0; + switch (algo) { + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaSign: { + const n = util.readMPI(bytes.subarray(read)); read += n.length + 2; + const e = util.readMPI(bytes.subarray(read)); read += e.length + 2; + return { read, publicParams: { n, e } }; + } + case enums.publicKey.dsa: { + const p = util.readMPI(bytes.subarray(read)); read += p.length + 2; + const q = util.readMPI(bytes.subarray(read)); read += q.length + 2; + const g = util.readMPI(bytes.subarray(read)); read += g.length + 2; + const y = util.readMPI(bytes.subarray(read)); read += y.length + 2; + return { read, publicParams: { p, q, g, y } }; + } + case enums.publicKey.elgamal: { + const p = util.readMPI(bytes.subarray(read)); read += p.length + 2; + const g = util.readMPI(bytes.subarray(read)); read += g.length + 2; + const y = util.readMPI(bytes.subarray(read)); read += y.length + 2; + return { read, publicParams: { p, g, y } }; + } + case enums.publicKey.ecdsa: { + const oid = new OID(); read += oid.read(bytes); + const Q = util.readMPI(bytes.subarray(read)); read += Q.length + 2; + return { read: read, publicParams: { oid, Q } }; + } + case enums.publicKey.eddsa: { + const oid = new OID(); read += oid.read(bytes); + let Q = util.readMPI(bytes.subarray(read)); read += Q.length + 2; + Q = util.leftPad(Q, 33); + return { read: read, publicParams: { oid, Q } }; + } + case enums.publicKey.ecdh: { + const oid = new OID(); read += oid.read(bytes); + const Q = util.readMPI(bytes.subarray(read)); read += Q.length + 2; + const kdfParams = new KDFParams(); read += kdfParams.read(bytes.subarray(read)); + return { read: read, publicParams: { oid, Q, kdfParams } }; + } + default: + throw new Error('Invalid public key encryption algorithm.'); + } + } + + /** + * Parse private key material in binary form to get the key parameters + * @param {module:enums.publicKey} algo - The key algorithm + * @param {Uint8Array} bytes - The key material to parse + * @param {Object} publicParams - (ECC only) public params, needed to format some private params + * @returns {{ read: Number, privateParams: Object }} Number of read bytes plus the key parameters referenced by name. + */ + function parsePrivateKeyParams(algo, bytes, publicParams) { + let read = 0; + switch (algo) { + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaSign: { + const d = util.readMPI(bytes.subarray(read)); read += d.length + 2; + const p = util.readMPI(bytes.subarray(read)); read += p.length + 2; + const q = util.readMPI(bytes.subarray(read)); read += q.length + 2; + const u = util.readMPI(bytes.subarray(read)); read += u.length + 2; + return { read, privateParams: { d, p, q, u } }; + } + case enums.publicKey.dsa: + case enums.publicKey.elgamal: { + const x = util.readMPI(bytes.subarray(read)); read += x.length + 2; + return { read, privateParams: { x } }; + } + case enums.publicKey.ecdsa: + case enums.publicKey.ecdh: { + const curve = new Curve(publicParams.oid); + let d = util.readMPI(bytes.subarray(read)); read += d.length + 2; + d = util.leftPad(d, curve.payloadSize); + return { read, privateParams: { d } }; + } + case enums.publicKey.eddsa: { + let seed = util.readMPI(bytes.subarray(read)); read += seed.length + 2; + seed = util.leftPad(seed, 32); + return { read, privateParams: { seed } }; + } + default: + throw new Error('Invalid public key encryption algorithm.'); + } + } + + /** Returns the types comprising the encrypted session key of an algorithm + * @param {module:enums.publicKey} algo - The key algorithm + * @param {Uint8Array} bytes - The key material to parse + * @returns {Object} The session key parameters referenced by name. + */ + function parseEncSessionKeyParams(algo, bytes) { + let read = 0; + switch (algo) { + // Algorithm-Specific Fields for RSA encrypted session keys: + // - MPI of RSA encrypted value m**e mod n. + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaEncryptSign: { + const c = util.readMPI(bytes.subarray(read)); + return { c }; + } + + // Algorithm-Specific Fields for Elgamal encrypted session keys: + // - MPI of Elgamal value g**k mod p + // - MPI of Elgamal value m * y**k mod p + case enums.publicKey.elgamal: { + const c1 = util.readMPI(bytes.subarray(read)); read += c1.length + 2; + const c2 = util.readMPI(bytes.subarray(read)); + return { c1, c2 }; + } + // Algorithm-Specific Fields for ECDH encrypted session keys: + // - MPI containing the ephemeral key used to establish the shared secret + // - ECDH Symmetric Key + case enums.publicKey.ecdh: { + const V = util.readMPI(bytes.subarray(read)); read += V.length + 2; + const C = new ECDHSymmetricKey(); C.read(bytes.subarray(read)); + return { V, C }; + } + default: + throw new Error('Invalid public key encryption algorithm.'); + } + } + + /** + * Convert params to MPI and serializes them in the proper order + * @param {module:enums.publicKey} algo - The public key algorithm + * @param {Object} params - The key parameters indexed by name + * @returns {Uint8Array} The array containing the MPIs. + */ + function serializeParams(algo, params) { + const orderedParams = Object.keys(params).map(name => { + const param = params[name]; + return util.isUint8Array(param) ? util.uint8ArrayToMPI(param) : param.write(); + }); + return util.concatUint8Array(orderedParams); + } + + /** + * Generate algorithm-specific key parameters + * @param {module:enums.publicKey} algo - The public key algorithm + * @param {Integer} bits - Bit length for RSA keys + * @param {module:type/oid} oid - Object identifier for ECC keys + * @returns {Promise<{ publicParams: {Object}, privateParams: {Object} }>} The parameters referenced by name. + * @async + */ + function generateParams(algo, bits, oid) { + switch (algo) { + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaSign: { + return publicKey.rsa.generate(bits, 65537).then(({ n, e, d, p, q, u }) => ({ + privateParams: { d, p, q, u }, + publicParams: { n, e } + })); + } + case enums.publicKey.ecdsa: + return publicKey.elliptic.generate(oid).then(({ oid, Q, secret }) => ({ + privateParams: { d: secret }, + publicParams: { oid: new OID(oid), Q } + })); + case enums.publicKey.eddsa: + return publicKey.elliptic.generate(oid).then(({ oid, Q, secret }) => ({ + privateParams: { seed: secret }, + publicParams: { oid: new OID(oid), Q } + })); + case enums.publicKey.ecdh: + return publicKey.elliptic.generate(oid).then(({ oid, Q, secret, hash, cipher }) => ({ + privateParams: { d: secret }, + publicParams: { + oid: new OID(oid), + Q, + kdfParams: new KDFParams({ hash, cipher }) + } + })); + case enums.publicKey.dsa: + case enums.publicKey.elgamal: + throw new Error('Unsupported algorithm for key generation.'); + default: + throw new Error('Invalid public key algorithm.'); + } + } + + /** + * Validate algorithm-specific key parameters + * @param {module:enums.publicKey} algo - The public key algorithm + * @param {Object} publicParams - Algorithm-specific public key parameters + * @param {Object} privateParams - Algorithm-specific private key parameters + * @returns {Promise} Whether the parameters are valid. + * @async + */ + async function validateParams$4(algo, publicParams, privateParams) { + if (!publicParams || !privateParams) { + throw new Error('Missing key parameters'); + } + switch (algo) { + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaSign: { + const { n, e } = publicParams; + const { d, p, q, u } = privateParams; + return publicKey.rsa.validateParams(n, e, d, p, q, u); + } + case enums.publicKey.dsa: { + const { p, q, g, y } = publicParams; + const { x } = privateParams; + return publicKey.dsa.validateParams(p, q, g, y, x); + } + case enums.publicKey.elgamal: { + const { p, g, y } = publicParams; + const { x } = privateParams; + return publicKey.elgamal.validateParams(p, g, y, x); + } + case enums.publicKey.ecdsa: + case enums.publicKey.ecdh: { + const algoModule = publicKey.elliptic[enums.read(enums.publicKey, algo)]; + const { oid, Q } = publicParams; + const { d } = privateParams; + return algoModule.validateParams(oid, Q, d); + } + case enums.publicKey.eddsa: { + const { oid, Q } = publicParams; + const { seed } = privateParams; + return publicKey.elliptic.eddsa.validateParams(oid, Q, seed); + } + default: + throw new Error('Invalid public key algorithm.'); + } + } + + /** + * Generates a random byte prefix for the specified algorithm + * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. + * @param {module:enums.symmetric} algo - Symmetric encryption algorithm + * @returns {Promise} Random bytes with length equal to the block size of the cipher, plus the last two bytes repeated. + * @async + */ + async function getPrefixRandom(algo) { + const { blockSize } = getCipher(algo); + const prefixrandom = await getRandomBytes(blockSize); + const repeat = new Uint8Array([prefixrandom[prefixrandom.length - 2], prefixrandom[prefixrandom.length - 1]]); + return util.concat([prefixrandom, repeat]); + } + + /** + * Generating a session key for the specified symmetric algorithm + * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. + * @param {module:enums.symmetric} algo - Symmetric encryption algorithm + * @returns {Promise} Random bytes as a string to be used as a key. + * @async + */ + function generateSessionKey(algo) { + const { keySize } = getCipher(algo); + return getRandomBytes(keySize); + } + + /** + * Get implementation of the given AEAD mode + * @param {enums.aead} algo + * @returns {Object} + * @throws {Error} on invalid algo + */ + function getAEADMode(algo) { + const algoName = enums.read(enums.aead, algo); + return mode[algoName]; + } + + /** + * Get implementation of the given cipher + * @param {enums.symmetric} algo + * @returns {Object} + * @throws {Error} on invalid algo + */ + function getCipher(algo) { + const algoName = enums.read(enums.symmetric, algo); + return cipher[algoName]; + } + + var crypto$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + publicKeyEncrypt: publicKeyEncrypt, + publicKeyDecrypt: publicKeyDecrypt, + parsePublicKeyParams: parsePublicKeyParams, + parsePrivateKeyParams: parsePrivateKeyParams, + parseEncSessionKeyParams: parseEncSessionKeyParams, + serializeParams: serializeParams, + generateParams: generateParams, + validateParams: validateParams$4, + getPrefixRandom: getPrefixRandom, + generateSessionKey: generateSessionKey, + getAEADMode: getAEADMode, + getCipher: getCipher + }); + + // OpenPGP.js - An OpenPGP implementation in javascript + + const webCrypto$8 = util.getWebCrypto(); + const nodeCrypto$9 = util.getNodeCrypto(); + + /** + * Validate ECDH parameters + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {Uint8Array} Q - ECDH public point + * @param {Uint8Array} d - ECDH secret scalar + * @returns {Promise} Whether params are valid. + * @async + */ + async function validateParams$5(oid, Q, d) { + return validateStandardParams(enums.publicKey.ecdh, oid, Q, d); + } + + // Build Param for ECDH algorithm (RFC 6637) + function buildEcdhParam(public_algo, oid, kdfParams, fingerprint) { + return util.concatUint8Array([ + oid.write(), + new Uint8Array([public_algo]), + kdfParams.write(), + util.stringToUint8Array('Anonymous Sender '), + fingerprint.subarray(0, 20) + ]); + } + + // Key Derivation Function (RFC 6637) + async function kdf(hashAlgo, X, length, param, stripLeading = false, stripTrailing = false) { + // Note: X is little endian for Curve25519, big-endian for all others. + // This is not ideal, but the RFC's are unclear + // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B + let i; + if (stripLeading) { + // Work around old go crypto bug + for (i = 0; i < X.length && X[i] === 0; i++); + X = X.subarray(i); + } + if (stripTrailing) { + // Work around old OpenPGP.js bug + for (i = X.length - 1; i >= 0 && X[i] === 0; i--); + X = X.subarray(0, i + 1); + } + const digest = await hash.digest(hashAlgo, util.concatUint8Array([ + new Uint8Array([0, 0, 0, 1]), + X, + param + ])); + return digest.subarray(0, length); + } + + /** + * Generate ECDHE ephemeral key and secret from public key + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} Q - Recipient public key + * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ + async function genPublicEphemeralKey(curve, Q) { + switch (curve.type) { + case 'curve25519': { + const d = await getRandomBytes(32); + const { secretKey, sharedKey } = await genPrivateEphemeralKey(curve, Q, null, d); + let { publicKey } = naclFastLight.box.keyPair.fromSecretKey(secretKey); + publicKey = util.concatUint8Array([new Uint8Array([0x40]), publicKey]); + return { publicKey, sharedKey }; // Note: sharedKey is little-endian here, unlike below + } + case 'web': + if (curve.web && util.getWebCrypto()) { + try { + return await webPublicEphemeralKey(curve, Q); + } catch (err) { + util.printDebugError(err); + } + } + break; + case 'node': + return nodePublicEphemeralKey(curve, Q); + } + return ellipticPublicEphemeralKey(curve, Q); + } + + /** + * Encrypt and wrap a session key + * + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {module:type/kdf_params} kdfParams - KDF params including cipher and algorithm to use + * @param {Uint8Array} data - Unpadded session key data + * @param {Uint8Array} Q - Recipient public key + * @param {Uint8Array} fingerprint - Recipient fingerprint + * @returns {Promise<{publicKey: Uint8Array, wrappedKey: Uint8Array}>} + * @async + */ + async function encrypt$3(oid, kdfParams, data, Q, fingerprint) { + const m = encode$1(data); + + const curve = new Curve(oid); + const { publicKey, sharedKey } = await genPublicEphemeralKey(curve, Q); + const param = buildEcdhParam(enums.publicKey.ecdh, oid, kdfParams, fingerprint); + const { keySize } = getCipher(kdfParams.cipher); + const Z = await kdf(kdfParams.hash, sharedKey, keySize, param); + const wrappedKey = wrap(Z, m); + return { publicKey, wrappedKey }; + } + + /** + * Generate ECDHE secret from private key and public part of ephemeral key + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} V - Public part of ephemeral key + * @param {Uint8Array} Q - Recipient public key + * @param {Uint8Array} d - Recipient private key + * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ + async function genPrivateEphemeralKey(curve, V, Q, d) { + if (d.length !== curve.payloadSize) { + const privateKey = new Uint8Array(curve.payloadSize); + privateKey.set(d, curve.payloadSize - d.length); + d = privateKey; + } + switch (curve.type) { + case 'curve25519': { + const secretKey = d.slice().reverse(); + const sharedKey = naclFastLight.scalarMult(secretKey, V.subarray(1)); + return { secretKey, sharedKey }; // Note: sharedKey is little-endian here, unlike below + } + case 'web': + if (curve.web && util.getWebCrypto()) { + try { + return await webPrivateEphemeralKey(curve, V, Q, d); + } catch (err) { + util.printDebugError(err); + } + } + break; + case 'node': + return nodePrivateEphemeralKey(curve, V, d); + } + return ellipticPrivateEphemeralKey(curve, V, d); + } + + /** + * Decrypt and unwrap the value derived from session key + * + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {module:type/kdf_params} kdfParams - KDF params including cipher and algorithm to use + * @param {Uint8Array} V - Public part of ephemeral key + * @param {Uint8Array} C - Encrypted and wrapped value derived from session key + * @param {Uint8Array} Q - Recipient public key + * @param {Uint8Array} d - Recipient private key + * @param {Uint8Array} fingerprint - Recipient fingerprint + * @returns {Promise} Value derived from session key. + * @async + */ + async function decrypt$3(oid, kdfParams, V, C, Q, d, fingerprint) { + const curve = new Curve(oid); + const { sharedKey } = await genPrivateEphemeralKey(curve, V, Q, d); + const param = buildEcdhParam(enums.publicKey.ecdh, oid, kdfParams, fingerprint); + const { keySize } = getCipher(kdfParams.cipher); + let err; + for (let i = 0; i < 3; i++) { + try { + // Work around old go crypto bug and old OpenPGP.js bug, respectively. + const Z = await kdf(kdfParams.hash, sharedKey, keySize, param, i === 1, i === 2); + return decode$1(unwrap(Z, C)); + } catch (e) { + err = e; + } + } + throw err; + } + + /** + * Generate ECDHE secret from private key and public part of ephemeral key using webCrypto + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} V - Public part of ephemeral key + * @param {Uint8Array} Q - Recipient public key + * @param {Uint8Array} d - Recipient private key + * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ + async function webPrivateEphemeralKey(curve, V, Q, d) { + const recipient = privateToJWK$1(curve.payloadSize, curve.web.web, Q, d); + let privateKey = webCrypto$8.importKey( + 'jwk', + recipient, + { + name: 'ECDH', + namedCurve: curve.web.web + }, + true, + ['deriveKey', 'deriveBits'] + ); + const jwk = rawPublicToJWK(curve.payloadSize, curve.web.web, V); + let sender = webCrypto$8.importKey( + 'jwk', + jwk, + { + name: 'ECDH', + namedCurve: curve.web.web + }, + true, + [] + ); + [privateKey, sender] = await Promise.all([privateKey, sender]); + let S = webCrypto$8.deriveBits( + { + name: 'ECDH', + namedCurve: curve.web.web, + public: sender + }, + privateKey, + curve.web.sharedSize + ); + let secret = webCrypto$8.exportKey( + 'jwk', + privateKey + ); + [S, secret] = await Promise.all([S, secret]); + const sharedKey = new Uint8Array(S); + const secretKey = b64ToUint8Array(secret.d); + return { secretKey, sharedKey }; + } + + /** + * Generate ECDHE ephemeral key and secret from public key using webCrypto + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} Q - Recipient public key + * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ + async function webPublicEphemeralKey(curve, Q) { + const jwk = rawPublicToJWK(curve.payloadSize, curve.web.web, Q); + let keyPair = webCrypto$8.generateKey( + { + name: 'ECDH', + namedCurve: curve.web.web + }, + true, + ['deriveKey', 'deriveBits'] + ); + let recipient = webCrypto$8.importKey( + 'jwk', + jwk, + { + name: 'ECDH', + namedCurve: curve.web.web + }, + false, + [] + ); + [keyPair, recipient] = await Promise.all([keyPair, recipient]); + let s = webCrypto$8.deriveBits( + { + name: 'ECDH', + namedCurve: curve.web.web, + public: recipient + }, + keyPair.privateKey, + curve.web.sharedSize + ); + let p = webCrypto$8.exportKey( + 'jwk', + keyPair.publicKey + ); + [s, p] = await Promise.all([s, p]); + const sharedKey = new Uint8Array(s); + const publicKey = new Uint8Array(jwkToRawPublic(p)); + return { publicKey, sharedKey }; + } + + /** + * Generate ECDHE secret from private key and public part of ephemeral key using indutny/elliptic + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} V - Public part of ephemeral key + * @param {Uint8Array} d - Recipient private key + * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ + async function ellipticPrivateEphemeralKey(curve, V, d) { + const indutnyCurve = await getIndutnyCurve(curve.name); + V = keyFromPublic(indutnyCurve, V); + d = keyFromPrivate(indutnyCurve, d); + const secretKey = new Uint8Array(d.getPrivate()); + const S = d.derive(V.getPublic()); + const len = indutnyCurve.curve.p.byteLength(); + const sharedKey = S.toArrayLike(Uint8Array, 'be', len); + return { secretKey, sharedKey }; + } + + /** + * Generate ECDHE ephemeral key and secret from public key using indutny/elliptic + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} Q - Recipient public key + * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ + async function ellipticPublicEphemeralKey(curve, Q) { + const indutnyCurve = await getIndutnyCurve(curve.name); + const v = await curve.genKeyPair(); + Q = keyFromPublic(indutnyCurve, Q); + const V = keyFromPrivate(indutnyCurve, v.privateKey); + const publicKey = v.publicKey; + const S = V.derive(Q.getPublic()); + const len = indutnyCurve.curve.p.byteLength(); + const sharedKey = S.toArrayLike(Uint8Array, 'be', len); + return { publicKey, sharedKey }; + } + + /** + * Generate ECDHE secret from private key and public part of ephemeral key using nodeCrypto + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} V - Public part of ephemeral key + * @param {Uint8Array} d - Recipient private key + * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ + async function nodePrivateEphemeralKey(curve, V, d) { + const recipient = nodeCrypto$9.createECDH(curve.node.node); + recipient.setPrivateKey(d); + const sharedKey = new Uint8Array(recipient.computeSecret(V)); + const secretKey = new Uint8Array(recipient.getPrivateKey()); + return { secretKey, sharedKey }; + } + + /** + * Generate ECDHE ephemeral key and secret from public key using nodeCrypto + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} Q - Recipient public key + * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ + async function nodePublicEphemeralKey(curve, Q) { + const sender = nodeCrypto$9.createECDH(curve.node.node); + sender.generateKeys(); + const sharedKey = new Uint8Array(sender.computeSecret(Q)); + const publicKey = new Uint8Array(sender.getPublicKey()); + return { publicKey, sharedKey }; + } + + var ecdh = /*#__PURE__*/Object.freeze({ + __proto__: null, + validateParams: validateParams$5, + encrypt: encrypt$3, + decrypt: decrypt$3 + }); + + // OpenPGP.js - An OpenPGP implementation in javascript + + var elliptic = /*#__PURE__*/Object.freeze({ + __proto__: null, + Curve: Curve, + ecdh: ecdh, + ecdsa: ecdsa, + eddsa: eddsa, + generate: generate$1, + getPreferredHashAlgo: getPreferredHashAlgo + }); + + // GPG4Browsers - An OpenPGP implementation in javascript + + /* + TODO regarding the hash function, read: + https://tools.ietf.org/html/rfc4880#section-13.6 + https://tools.ietf.org/html/rfc4880#section-14 + */ + + /** + * DSA Sign function + * @param {Integer} hashAlgo + * @param {Uint8Array} hashed + * @param {Uint8Array} g + * @param {Uint8Array} p + * @param {Uint8Array} q + * @param {Uint8Array} x + * @returns {Promise<{ r: Uint8Array, s: Uint8Array }>} + * @async + */ + async function sign$3(hashAlgo, hashed, g, p, q, x) { + const BigInteger = await util.getBigInteger(); + const one = new BigInteger(1); + p = new BigInteger(p); + q = new BigInteger(q); + g = new BigInteger(g); + x = new BigInteger(x); + + let k; + let r; + let s; + let t; + g = g.mod(p); + x = x.mod(q); + // If the output size of the chosen hash is larger than the number of + // bits of q, the hash result is truncated to fit by taking the number + // of leftmost bits equal to the number of bits of q. This (possibly + // truncated) hash function result is treated as a number and used + // directly in the DSA signature algorithm. + const h = new BigInteger(hashed.subarray(0, q.byteLength())).mod(q); + // FIPS-186-4, section 4.6: + // The values of r and s shall be checked to determine if r = 0 or s = 0. + // If either r = 0 or s = 0, a new value of k shall be generated, and the + // signature shall be recalculated. It is extremely unlikely that r = 0 + // or s = 0 if signatures are generated properly. + while (true) { + // See Appendix B here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf + k = await getRandomBigInteger(one, q); // returns in [1, q-1] + r = g.modExp(k, p).imod(q); // (g**k mod p) mod q + if (r.isZero()) { + continue; + } + const xr = x.mul(r).imod(q); + t = h.add(xr).imod(q); // H(m) + x*r mod q + s = k.modInv(q).imul(t).imod(q); // k**-1 * (H(m) + x*r) mod q + if (s.isZero()) { + continue; + } + break; + } + return { + r: r.toUint8Array('be', q.byteLength()), + s: s.toUint8Array('be', q.byteLength()) + }; + } + + /** + * DSA Verify function + * @param {Integer} hashAlgo + * @param {Uint8Array} r + * @param {Uint8Array} s + * @param {Uint8Array} hashed + * @param {Uint8Array} g + * @param {Uint8Array} p + * @param {Uint8Array} q + * @param {Uint8Array} y + * @returns {boolean} + * @async + */ + async function verify$3(hashAlgo, r, s, hashed, g, p, q, y) { + const BigInteger = await util.getBigInteger(); + const zero = new BigInteger(0); + r = new BigInteger(r); + s = new BigInteger(s); + + p = new BigInteger(p); + q = new BigInteger(q); + g = new BigInteger(g); + y = new BigInteger(y); + + if (r.lte(zero) || r.gte(q) || + s.lte(zero) || s.gte(q)) { + util.printDebug('invalid DSA Signature'); + return false; + } + const h = new BigInteger(hashed.subarray(0, q.byteLength())).imod(q); + const w = s.modInv(q); // s**-1 mod q + if (w.isZero()) { + util.printDebug('invalid DSA Signature'); + return false; + } + + g = g.mod(p); + y = y.mod(p); + const u1 = h.mul(w).imod(q); // H(m) * w mod q + const u2 = r.mul(w).imod(q); // r * w mod q + const t1 = g.modExp(u1, p); // g**u1 mod p + const t2 = y.modExp(u2, p); // y**u2 mod p + const v = t1.mul(t2).imod(p).imod(q); // (g**u1 * y**u2 mod p) mod q + return v.equal(r); + } + + /** + * Validate DSA parameters + * @param {Uint8Array} p - DSA prime + * @param {Uint8Array} q - DSA group order + * @param {Uint8Array} g - DSA sub-group generator + * @param {Uint8Array} y - DSA public key + * @param {Uint8Array} x - DSA private key + * @returns {Promise} Whether params are valid. + * @async + */ + async function validateParams$6(p, q, g, y, x) { + const BigInteger = await util.getBigInteger(); + p = new BigInteger(p); + q = new BigInteger(q); + g = new BigInteger(g); + y = new BigInteger(y); + const one = new BigInteger(1); + // Check that 1 < g < p + if (g.lte(one) || g.gte(p)) { + return false; + } + + /** + * Check that subgroup order q divides p-1 + */ + if (!p.dec().mod(q).isZero()) { + return false; + } + + /** + * g has order q + * Check that g ** q = 1 mod p + */ + if (!g.modExp(q, p).isOne()) { + return false; + } + + /** + * Check q is large and probably prime (we mainly want to avoid small factors) + */ + const qSize = new BigInteger(q.bitLength()); + const n150 = new BigInteger(150); + if (qSize.lt(n150) || !(await isProbablePrime(q, null, 32))) { + return false; + } + + /** + * Re-derive public key y' = g ** x mod p + * Expect y == y' + * + * Blinded exponentiation computes g**{rq + x} to compare to y + */ + x = new BigInteger(x); + const two = new BigInteger(2); + const r = await getRandomBigInteger(two.leftShift(qSize.dec()), two.leftShift(qSize)); // draw r of same size as q + const rqx = q.mul(r).add(x); + if (!y.equal(g.modExp(rqx, p))) { + return false; + } + + return true; + } + + var dsa = /*#__PURE__*/Object.freeze({ + __proto__: null, + sign: sign$3, + verify: verify$3, + validateParams: validateParams$6 + }); + + /** + * @fileoverview Asymmetric cryptography functions + * @module crypto/public_key + * @private + */ + + var publicKey = { + /** @see module:crypto/public_key/rsa */ + rsa: rsa, + /** @see module:crypto/public_key/elgamal */ + elgamal: elgamal, + /** @see module:crypto/public_key/elliptic */ + elliptic: elliptic, + /** @see module:crypto/public_key/dsa */ + dsa: dsa, + /** @see tweetnacl */ + nacl: naclFastLight + }; + + /** + * @fileoverview Provides functions for asymmetric signing and signature verification + * @module crypto/signature + * @private + */ + + /** + * Parse signature in binary form to get the parameters. + * The returned values are only padded for EdDSA, since in the other cases their expected length + * depends on the key params, hence we delegate the padding to the signature verification function. + * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} + * See {@link https://tools.ietf.org/html/rfc4880#section-5.2.2|RFC 4880 5.2.2.} + * @param {module:enums.publicKey} algo - Public key algorithm + * @param {Uint8Array} signature - Data for which the signature was created + * @returns {Promise} True if signature is valid. + * @async + */ + function parseSignatureParams(algo, signature) { + let read = 0; + switch (algo) { + // Algorithm-Specific Fields for RSA signatures: + // - MPI of RSA signature value m**d mod n. + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaSign: { + const s = util.readMPI(signature.subarray(read)); + // The signature needs to be the same length as the public key modulo n. + // We pad s on signature verification, where we have access to n. + return { s }; + } + // Algorithm-Specific Fields for DSA or ECDSA signatures: + // - MPI of DSA or ECDSA value r. + // - MPI of DSA or ECDSA value s. + case enums.publicKey.dsa: + case enums.publicKey.ecdsa: + { + const r = util.readMPI(signature.subarray(read)); read += r.length + 2; + const s = util.readMPI(signature.subarray(read)); + return { r, s }; + } + // Algorithm-Specific Fields for EdDSA signatures: + // - MPI of an EC point r. + // - EdDSA value s, in MPI, in the little endian representation + case enums.publicKey.eddsa: { + // When parsing little-endian MPI data, we always need to left-pad it, as done with big-endian values: + // https://www.ietf.org/archive/id/draft-ietf-openpgp-rfc4880bis-10.html#section-3.2-9 + let r = util.readMPI(signature.subarray(read)); read += r.length + 2; + r = util.leftPad(r, 32); + let s = util.readMPI(signature.subarray(read)); + s = util.leftPad(s, 32); + return { r, s }; + } + default: + throw new Error('Invalid signature algorithm.'); + } + } + + /** + * Verifies the signature provided for data using specified algorithms and public key parameters. + * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} + * and {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4} + * for public key and hash algorithms. + * @param {module:enums.publicKey} algo - Public key algorithm + * @param {module:enums.hash} hashAlgo - Hash algorithm + * @param {Object} signature - Named algorithm-specific signature parameters + * @param {Object} publicParams - Algorithm-specific public key parameters + * @param {Uint8Array} data - Data for which the signature was created + * @param {Uint8Array} hashed - The hashed data + * @returns {Promise} True if signature is valid. + * @async + */ + async function verify$4(algo, hashAlgo, signature, publicParams, data, hashed) { + switch (algo) { + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaSign: { + const { n, e } = publicParams; + const s = util.leftPad(signature.s, n.length); // padding needed for webcrypto and node crypto + return publicKey.rsa.verify(hashAlgo, data, s, n, e, hashed); + } + case enums.publicKey.dsa: { + const { g, p, q, y } = publicParams; + const { r, s } = signature; // no need to pad, since we always handle them as BigIntegers + return publicKey.dsa.verify(hashAlgo, r, s, hashed, g, p, q, y); + } + case enums.publicKey.ecdsa: { + const { oid, Q } = publicParams; + const curveSize = new publicKey.elliptic.Curve(oid).payloadSize; + // padding needed for webcrypto + const r = util.leftPad(signature.r, curveSize); + const s = util.leftPad(signature.s, curveSize); + return publicKey.elliptic.ecdsa.verify(oid, hashAlgo, { r, s }, data, Q, hashed); + } + case enums.publicKey.eddsa: { + const { oid, Q } = publicParams; + // signature already padded on parsing + return publicKey.elliptic.eddsa.verify(oid, hashAlgo, signature, data, Q, hashed); + } + default: + throw new Error('Invalid signature algorithm.'); + } + } + + /** + * Creates a signature on data using specified algorithms and private key parameters. + * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} + * and {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4} + * for public key and hash algorithms. + * @param {module:enums.publicKey} algo - Public key algorithm + * @param {module:enums.hash} hashAlgo - Hash algorithm + * @param {Object} publicKeyParams - Algorithm-specific public and private key parameters + * @param {Object} privateKeyParams - Algorithm-specific public and private key parameters + * @param {Uint8Array} data - Data to be signed + * @param {Uint8Array} hashed - The hashed data + * @returns {Promise} Signature Object containing named signature parameters. + * @async + */ + async function sign$4(algo, hashAlgo, publicKeyParams, privateKeyParams, data, hashed) { + if (!publicKeyParams || !privateKeyParams) { + throw new Error('Missing key parameters'); + } + switch (algo) { + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaSign: { + const { n, e } = publicKeyParams; + const { d, p, q, u } = privateKeyParams; + const s = await publicKey.rsa.sign(hashAlgo, data, n, e, d, p, q, u, hashed); + return { s }; + } + case enums.publicKey.dsa: { + const { g, p, q } = publicKeyParams; + const { x } = privateKeyParams; + return publicKey.dsa.sign(hashAlgo, hashed, g, p, q, x); + } + case enums.publicKey.elgamal: { + throw new Error('Signing with Elgamal is not defined in the OpenPGP standard.'); + } + case enums.publicKey.ecdsa: { + const { oid, Q } = publicKeyParams; + const { d } = privateKeyParams; + return publicKey.elliptic.ecdsa.sign(oid, hashAlgo, data, Q, d, hashed); + } + case enums.publicKey.eddsa: { + const { oid, Q } = publicKeyParams; + const { seed } = privateKeyParams; + return publicKey.elliptic.eddsa.sign(oid, hashAlgo, data, Q, seed, hashed); + } + default: + throw new Error('Invalid signature algorithm.'); + } + } + + var signature = /*#__PURE__*/Object.freeze({ + __proto__: null, + parseSignatureParams: parseSignatureParams, + verify: verify$4, + sign: sign$4 + }); + + /** + * @fileoverview Provides access to all cryptographic primitives used in OpenPGP.js + * @see module:crypto/crypto + * @see module:crypto/signature + * @see module:crypto/public_key + * @see module:crypto/cipher + * @see module:crypto/random + * @see module:crypto/hash + * @module crypto + * @private + */ + + // TODO move cfb and gcm to cipher + const mod = { + /** @see module:crypto/cipher */ + cipher: cipher, + /** @see module:crypto/hash */ + hash: hash, + /** @see module:crypto/mode */ + mode: mode, + /** @see module:crypto/public_key */ + publicKey: publicKey, + /** @see module:crypto/signature */ + signature: signature, + /** @see module:crypto/random */ + random: random, + /** @see module:crypto/pkcs1 */ + pkcs1: pkcs1, + /** @see module:crypto/pkcs5 */ + pkcs5: pkcs5, + /** @see module:crypto/aes_kw */ + aesKW: aesKW + }; + + Object.assign(mod, crypto$1); + + var TYPED_OK = typeof Uint8Array !== "undefined" && + typeof Uint16Array !== "undefined" && + typeof Int32Array !== "undefined"; + + + // reduce buffer size, avoiding mem copy + function shrinkBuf(buf, size) { + if (buf.length === size) { + return buf; + } + if (buf.subarray) { + return buf.subarray(0, size); + } + buf.length = size; + return buf; + } + + + const fnTyped = { + arraySet: function (dest, src, src_offs, len, dest_offs) { + if (src.subarray && dest.subarray) { + dest.set(src.subarray(src_offs, src_offs + len), dest_offs); + return; + } + // Fallback to ordinary array + for (let i = 0; i < len; i++) { + dest[dest_offs + i] = src[src_offs + i]; + } + }, + // Join array of chunks to single array. + flattenChunks: function (chunks) { + let i, l, len, pos, chunk; + + // calculate data length + len = 0; + for (i = 0, l = chunks.length; i < l; i++) { + len += chunks[i].length; + } + + // join chunks + const result = new Uint8Array(len); + pos = 0; + for (i = 0, l = chunks.length; i < l; i++) { + chunk = chunks[i]; + result.set(chunk, pos); + pos += chunk.length; + } + + return result; + } + }; + + const fnUntyped = { + arraySet: function (dest, src, src_offs, len, dest_offs) { + for (let i = 0; i < len; i++) { + dest[dest_offs + i] = src[src_offs + i]; + } + }, + // Join array of chunks to single array. + flattenChunks: function (chunks) { + return [].concat.apply([], chunks); + } + }; + + + // Enable/Disable typed arrays use, for testing + // + + let Buf8 = TYPED_OK ? Uint8Array : Array; + let Buf16 = TYPED_OK ? Uint16Array : Array; + let Buf32 = TYPED_OK ? Int32Array : Array; + let flattenChunks = TYPED_OK ? fnTyped.flattenChunks : fnUntyped.flattenChunks; + let arraySet = TYPED_OK ? fnTyped.arraySet : fnUntyped.arraySet; + + // (C) 1995-2013 Jean-loup Gailly and Mark Adler + // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin + // + // This software is provided 'as-is', without any express or implied + // warranty. In no event will the authors be held liable for any damages + // arising from the use of this software. + // + // Permission is granted to anyone to use this software for any purpose, + // including commercial applications, and to alter it and redistribute it + // freely, subject to the following restrictions: + // + // 1. The origin of this software must not be misrepresented; you must not + // claim that you wrote the original software. If you use this software + // in a product, an acknowledgment in the product documentation would be + // appreciated but is not required. + // 2. Altered source versions must be plainly marked as such, and must not be + // misrepresented as being the original software. + // 3. This notice may not be removed or altered from any source distribution. + + /* Allowed flush values; see deflate() and inflate() below for details */ + const Z_NO_FLUSH = 0; + const Z_PARTIAL_FLUSH = 1; + const Z_SYNC_FLUSH = 2; + const Z_FULL_FLUSH = 3; + const Z_FINISH = 4; + const Z_BLOCK = 5; + const Z_TREES = 6; + + /* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + const Z_OK = 0; + const Z_STREAM_END = 1; + const Z_NEED_DICT = 2; + const Z_STREAM_ERROR = -2; + const Z_DATA_ERROR = -3; + //export const Z_MEM_ERROR = -4; + const Z_BUF_ERROR = -5; + const Z_DEFAULT_COMPRESSION = -1; + + + const Z_FILTERED = 1; + const Z_HUFFMAN_ONLY = 2; + const Z_RLE = 3; + const Z_FIXED = 4; + const Z_DEFAULT_STRATEGY = 0; + + /* Possible values of the data_type field (though see inflate()) */ + const Z_BINARY = 0; + const Z_TEXT = 1; + //export const Z_ASCII = 1; // = Z_TEXT (deprecated) + const Z_UNKNOWN = 2; + + /* The deflate compression method */ + const Z_DEFLATED = 8; + //export const Z_NULL = null // Use -1 or null inline, depending on var type + + /*============================================================================*/ + + + function zero$1(buf) { + let len = buf.length; while (--len >= 0) { + buf[len] = 0; + } + } + + // From zutil.h + + const STORED_BLOCK = 0; + const STATIC_TREES = 1; + const DYN_TREES = 2; + /* The three kinds of block type */ + + const MIN_MATCH = 3; + const MAX_MATCH = 258; + /* The minimum and maximum match lengths */ + + // From deflate.h + /* =========================================================================== + * Internal compression state. + */ + + const LENGTH_CODES = 29; + /* number of length codes, not counting the special END_BLOCK code */ + + const LITERALS = 256; + /* number of literal bytes 0..255 */ + + const L_CODES = LITERALS + 1 + LENGTH_CODES; + /* number of Literal or Length codes, including the END_BLOCK code */ + + const D_CODES = 30; + /* number of distance codes */ + + const BL_CODES = 19; + /* number of codes used to transfer the bit lengths */ + + const HEAP_SIZE = 2 * L_CODES + 1; + /* maximum heap size */ + + const MAX_BITS = 15; + /* All codes must not exceed MAX_BITS bits */ + + const Buf_size = 16; + /* size of bit buffer in bi_buf */ + + + /* =========================================================================== + * Constants + */ + + const MAX_BL_BITS = 7; + /* Bit length codes must not exceed MAX_BL_BITS bits */ + + const END_BLOCK = 256; + /* end of block literal code */ + + const REP_3_6 = 16; + /* repeat previous bit length 3-6 times (2 bits of repeat count) */ + + const REPZ_3_10 = 17; + /* repeat a zero length 3-10 times (3 bits of repeat count) */ + + const REPZ_11_138 = 18; + /* repeat a zero length 11-138 times (7 bits of repeat count) */ + + /* eslint-disable comma-spacing,array-bracket-spacing */ + const extra_lbits = /* extra bits for each length code */ + [0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0]; + + const extra_dbits = /* extra bits for each distance code */ + [0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13]; + + const extra_blbits = /* extra bits for each bit length code */ + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7]; + + const bl_order = + [16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]; + /* eslint-enable comma-spacing,array-bracket-spacing */ + + /* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + + /* =========================================================================== + * Local data. These are initialized only once. + */ + + // We pre-fill arrays with 0 to avoid uninitialized gaps + + const DIST_CODE_LEN = 512; /* see definition of array dist_code below */ + + // !!!! Use flat array instead of structure, Freq = i*2, Len = i*2+1 + const static_ltree = new Array((L_CODES + 2) * 2); + zero$1(static_ltree); + /* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + + const static_dtree = new Array(D_CODES * 2); + zero$1(static_dtree); + /* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + + const _dist_code = new Array(DIST_CODE_LEN); + zero$1(_dist_code); + /* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + + const _length_code = new Array(MAX_MATCH - MIN_MATCH + 1); + zero$1(_length_code); + /* length code for each normalized match length (0 == MIN_MATCH) */ + + const base_length = new Array(LENGTH_CODES); + zero$1(base_length); + /* First normalized length for each code (0 = MIN_MATCH) */ + + const base_dist = new Array(D_CODES); + zero$1(base_dist); + /* First normalized distance for each code (0 = distance of 1) */ + + + function StaticTreeDesc(static_tree, extra_bits, extra_base, elems, max_length) { + + this.static_tree = static_tree; /* static tree or NULL */ + this.extra_bits = extra_bits; /* extra bits for each code or NULL */ + this.extra_base = extra_base; /* base index for extra_bits */ + this.elems = elems; /* max number of elements in the tree */ + this.max_length = max_length; /* max bit length for the codes */ + + // show if `static_tree` has data or dummy - needed for monomorphic objects + this.has_stree = static_tree && static_tree.length; + } + + + let static_l_desc; + let static_d_desc; + let static_bl_desc; + + + function TreeDesc(dyn_tree, stat_desc) { + this.dyn_tree = dyn_tree; /* the dynamic tree */ + this.max_code = 0; /* largest code with non zero frequency */ + this.stat_desc = stat_desc; /* the corresponding static tree */ + } + + + + function d_code(dist) { + return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)]; + } + + + /* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ + function put_short(s, w) { + // put_byte(s, (uch)((w) & 0xff)); + // put_byte(s, (uch)((ush)(w) >> 8)); + s.pending_buf[s.pending++] = w & 0xff; + s.pending_buf[s.pending++] = w >>> 8 & 0xff; + } + + + /* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ + function send_bits(s, value, length) { + if (s.bi_valid > Buf_size - length) { + s.bi_buf |= value << s.bi_valid & 0xffff; + put_short(s, s.bi_buf); + s.bi_buf = value >> Buf_size - s.bi_valid; + s.bi_valid += length - Buf_size; + } else { + s.bi_buf |= value << s.bi_valid & 0xffff; + s.bi_valid += length; + } + } + + + function send_code(s, c, tree) { + send_bits(s, tree[c * 2]/*.Code*/, tree[c * 2 + 1]/*.Len*/); + } + + + /* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ + function bi_reverse(code, len) { + let res = 0; + do { + res |= code & 1; + code >>>= 1; + res <<= 1; + } while (--len > 0); + return res >>> 1; + } + + + /* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ + function bi_flush(s) { + if (s.bi_valid === 16) { + put_short(s, s.bi_buf); + s.bi_buf = 0; + s.bi_valid = 0; + + } else if (s.bi_valid >= 8) { + s.pending_buf[s.pending++] = s.bi_buf & 0xff; + s.bi_buf >>= 8; + s.bi_valid -= 8; + } + } + + + /* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ + function gen_bitlen(s, desc) + // deflate_state *s; + // tree_desc *desc; /* the tree descriptor */ + { + const tree = desc.dyn_tree; + const max_code = desc.max_code; + const stree = desc.stat_desc.static_tree; + const has_stree = desc.stat_desc.has_stree; + const extra = desc.stat_desc.extra_bits; + const base = desc.stat_desc.extra_base; + const max_length = desc.stat_desc.max_length; + let h; /* heap index */ + let n, m; /* iterate over the tree elements */ + let bits; /* bit length */ + let xbits; /* extra bits */ + let f; /* frequency */ + let overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) { + s.bl_count[bits] = 0; + } + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s.heap[s.heap_max] * 2 + 1]/*.Len*/ = 0; /* root of the heap */ + + for (h = s.heap_max + 1; h < HEAP_SIZE; h++) { + n = s.heap[h]; + bits = tree[tree[n * 2 + 1]/*.Dad*/ * 2 + 1]/*.Len*/ + 1; + if (bits > max_length) { + bits = max_length; + overflow++; + } + tree[n * 2 + 1]/*.Len*/ = bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) { + continue; + } /* not a leaf node */ + + s.bl_count[bits]++; + xbits = 0; + if (n >= base) { + xbits = extra[n - base]; + } + f = tree[n * 2]/*.Freq*/; + s.opt_len += f * (bits + xbits); + if (has_stree) { + s.static_len += f * (stree[n * 2 + 1]/*.Len*/ + xbits); + } + } + if (overflow === 0) { + return; + } + + // Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length - 1; + while (s.bl_count[bits] === 0) { + bits--; + } + s.bl_count[bits]--; /* move one leaf down the tree */ + s.bl_count[bits + 1] += 2; /* move one overflow item as its brother */ + s.bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits !== 0; bits--) { + n = s.bl_count[bits]; + while (n !== 0) { + m = s.heap[--h]; + if (m > max_code) { + continue; + } + if (tree[m * 2 + 1]/*.Len*/ !== bits) { + // Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s.opt_len += (bits - tree[m * 2 + 1]/*.Len*/) * tree[m * 2]/*.Freq*/; + tree[m * 2 + 1]/*.Len*/ = bits; + } + n--; + } + } + } + + + /* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ + function gen_codes(tree, max_code, bl_count) + // ct_data *tree; /* the tree to decorate */ + // int max_code; /* largest code with non zero frequency */ + // ushf *bl_count; /* number of codes at each bit length */ + { + const next_code = new Array(MAX_BITS + 1); /* next code value for each bit length */ + let code = 0; /* running code value */ + let bits; /* bit index */ + let n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = code + bl_count[bits - 1] << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + //Assert (code + bl_count[MAX_BITS]-1 == (1< length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES - 1; code++) { + base_length[code] = length; + for (n = 0; n < 1 << extra_lbits[code]; n++) { + _length_code[length++] = code; + } + } + //Assert (length == 256, "tr_static_init: length != 256"); + /* Note that the length 255 (match length 258) can be represented + * in two different ways: code 284 + 5 bits or code 285, so we + * overwrite length_code[255] to use the best encoding: + */ + _length_code[length - 1] = code; + + /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ + dist = 0; + for (code = 0; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < 1 << extra_dbits[code]; n++) { + _dist_code[dist++] = code; + } + } + //Assert (dist == 256, "tr_static_init: dist != 256"); + dist >>= 7; /* from now on, all distances are divided by 128 */ + for (; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < 1 << extra_dbits[code] - 7; n++) { + _dist_code[256 + dist++] = code; + } + } + //Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) { + bl_count[bits] = 0; + } + + n = 0; + while (n <= 143) { + static_ltree[n * 2 + 1]/*.Len*/ = 8; + n++; + bl_count[8]++; + } + while (n <= 255) { + static_ltree[n * 2 + 1]/*.Len*/ = 9; + n++; + bl_count[9]++; + } + while (n <= 279) { + static_ltree[n * 2 + 1]/*.Len*/ = 7; + n++; + bl_count[7]++; + } + while (n <= 287) { + static_ltree[n * 2 + 1]/*.Len*/ = 8; + n++; + bl_count[8]++; + } + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes(static_ltree, L_CODES + 1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n * 2 + 1]/*.Len*/ = 5; + static_dtree[n * 2]/*.Code*/ = bi_reverse(n, 5); + } + + // Now data ready and we can init static trees + static_l_desc = new StaticTreeDesc(static_ltree, extra_lbits, LITERALS + 1, L_CODES, MAX_BITS); + static_d_desc = new StaticTreeDesc(static_dtree, extra_dbits, 0, D_CODES, MAX_BITS); + static_bl_desc = new StaticTreeDesc(new Array(0), extra_blbits, 0, BL_CODES, MAX_BL_BITS); + + //static_init_done = true; + } + + + /* =========================================================================== + * Initialize a new block. + */ + function init_block(s) { + let n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) { + s.dyn_ltree[n * 2]/*.Freq*/ = 0; + } + for (n = 0; n < D_CODES; n++) { + s.dyn_dtree[n * 2]/*.Freq*/ = 0; + } + for (n = 0; n < BL_CODES; n++) { + s.bl_tree[n * 2]/*.Freq*/ = 0; + } + + s.dyn_ltree[END_BLOCK * 2]/*.Freq*/ = 1; + s.opt_len = s.static_len = 0; + s.last_lit = s.matches = 0; + } + + + /* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ + function bi_windup(s) { + if (s.bi_valid > 8) { + put_short(s, s.bi_buf); + } else if (s.bi_valid > 0) { + //put_byte(s, (Byte)s->bi_buf); + s.pending_buf[s.pending++] = s.bi_buf; + } + s.bi_buf = 0; + s.bi_valid = 0; + } + + /* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ + function copy_block(s, buf, len, header) + //DeflateState *s; + //charf *buf; /* the input data */ + //unsigned len; /* its length */ + //int header; /* true if block header must be written */ + { + bi_windup(s); /* align on byte boundary */ + + if (header) { + put_short(s, len); + put_short(s, ~len); + } + // while (len--) { + // put_byte(s, *buf++); + // } + arraySet(s.pending_buf, s.window, buf, len, s.pending); + s.pending += len; + } + + /* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ + function smaller(tree, n, m, depth) { + const _n2 = n * 2; + const _m2 = m * 2; + return tree[_n2]/*.Freq*/ < tree[_m2]/*.Freq*/ || + tree[_n2]/*.Freq*/ === tree[_m2]/*.Freq*/ && depth[n] <= depth[m]; + } + + /* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ + function pqdownheap(s, tree, k) + // deflate_state *s; + // ct_data *tree; /* the tree to restore */ + // int k; /* node to move down */ + { + const v = s.heap[k]; + let j = k << 1; /* left son of k */ + while (j <= s.heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s.heap_len && + smaller(tree, s.heap[j + 1], s.heap[j], s.depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s.heap[j], s.depth)) { + break; + } + + /* Exchange v with the smallest son */ + s.heap[k] = s.heap[j]; + k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s.heap[k] = v; + } + + + // inlined manually + // var SMALLEST = 1; + + /* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ + function compress_block(s, ltree, dtree) + // deflate_state *s; + // const ct_data *ltree; /* literal tree */ + // const ct_data *dtree; /* distance tree */ + { + let dist; /* distance of matched string */ + let lc; /* match length or unmatched char (if dist == 0) */ + let lx = 0; /* running index in l_buf */ + let code; /* the code to send */ + let extra; /* number of extra bits to send */ + + if (s.last_lit !== 0) { + do { + dist = s.pending_buf[s.d_buf + lx * 2] << 8 | s.pending_buf[s.d_buf + lx * 2 + 1]; + lc = s.pending_buf[s.l_buf + lx]; + lx++; + + if (dist === 0) { + send_code(s, lc, ltree); /* send a literal byte */ + //Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code + LITERALS + 1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra !== 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + //Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra !== 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + //Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + // "pendingBuf overflow"); + + } while (lx < s.last_lit); + } + + send_code(s, END_BLOCK, ltree); + } + + + /* =========================================================================== + * Construct one Huffman tree and assigns the code bit strings and lengths. + * Update the total bit length for the current block. + * IN assertion: the field freq is set for all tree elements. + * OUT assertions: the fields len and code are set to the optimal bit length + * and corresponding code. The length opt_len is updated; static_len is + * also updated if stree is not null. The field max_code is set. + */ + function build_tree(s, desc) + // deflate_state *s; + // tree_desc *desc; /* the tree descriptor */ + { + const tree = desc.dyn_tree; + const stree = desc.stat_desc.static_tree; + const has_stree = desc.stat_desc.has_stree; + const elems = desc.stat_desc.elems; + let n, m; /* iterate over heap elements */ + let max_code = -1; /* largest code with non zero frequency */ + let node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s.heap_len = 0; + s.heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n * 2]/*.Freq*/ !== 0) { + s.heap[++s.heap_len] = max_code = n; + s.depth[n] = 0; + + } else { + tree[n * 2 + 1]/*.Len*/ = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s.heap_len < 2) { + node = s.heap[++s.heap_len] = max_code < 2 ? ++max_code : 0; + tree[node * 2]/*.Freq*/ = 1; + s.depth[node] = 0; + s.opt_len--; + + if (has_stree) { + s.static_len -= stree[node * 2 + 1]/*.Len*/; + } + /* node is 0 or 1 so it does not have extra bits */ + } + desc.max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s.heap_len >> 1/*int /2*/; n >= 1; n--) { + pqdownheap(s, tree, n); + } + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + //pqremove(s, tree, n); /* n = node of least frequency */ + /*** pqremove ***/ + n = s.heap[1/*SMALLEST*/]; + s.heap[1/*SMALLEST*/] = s.heap[s.heap_len--]; + pqdownheap(s, tree, 1/*SMALLEST*/); + /***/ + + m = s.heap[1/*SMALLEST*/]; /* m = node of next least frequency */ + + s.heap[--s.heap_max] = n; /* keep the nodes sorted by frequency */ + s.heap[--s.heap_max] = m; + + /* Create a new node father of n and m */ + tree[node * 2]/*.Freq*/ = tree[n * 2]/*.Freq*/ + tree[m * 2]/*.Freq*/; + s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1; + tree[n * 2 + 1]/*.Dad*/ = tree[m * 2 + 1]/*.Dad*/ = node; + + /* and insert the new node in the heap */ + s.heap[1/*SMALLEST*/] = node++; + pqdownheap(s, tree, 1/*SMALLEST*/); + + } while (s.heap_len >= 2); + + s.heap[--s.heap_max] = s.heap[1/*SMALLEST*/]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes(tree, max_code, s.bl_count); + } + + + /* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ + function scan_tree(s, tree, max_code) + // deflate_state *s; + // ct_data *tree; /* the tree to be scanned */ + // int max_code; /* and its largest code of non zero frequency */ + { + let n; /* iterates over all tree elements */ + let prevlen = -1; /* last emitted length */ + let curlen; /* length of current code */ + + let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */ + + let count = 0; /* repeat count of the current code */ + let max_count = 7; /* max repeat count */ + let min_count = 4; /* min repeat count */ + + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } + tree[(max_code + 1) * 2 + 1]/*.Len*/ = 0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[(n + 1) * 2 + 1]/*.Len*/; + + if (++count < max_count && curlen === nextlen) { + continue; + + } else if (count < min_count) { + s.bl_tree[curlen * 2]/*.Freq*/ += count; + + } else if (curlen !== 0) { + + if (curlen !== prevlen) { + s.bl_tree[curlen * 2]/*.Freq*/++; + } + s.bl_tree[REP_3_6 * 2]/*.Freq*/++; + + } else if (count <= 10) { + s.bl_tree[REPZ_3_10 * 2]/*.Freq*/++; + + } else { + s.bl_tree[REPZ_11_138 * 2]/*.Freq*/++; + } + + count = 0; + prevlen = curlen; + + if (nextlen === 0) { + max_count = 138; + min_count = 3; + + } else if (curlen === nextlen) { + max_count = 6; + min_count = 3; + + } else { + max_count = 7; + min_count = 4; + } + } + } + + + /* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ + function send_tree(s, tree, max_code) + // deflate_state *s; + // ct_data *tree; /* the tree to be scanned */ + // int max_code; /* and its largest code of non zero frequency */ + { + let n; /* iterates over all tree elements */ + let prevlen = -1; /* last emitted length */ + let curlen; /* length of current code */ + + let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */ + + let count = 0; /* repeat count of the current code */ + let max_count = 7; /* max repeat count */ + let min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[(n + 1) * 2 + 1]/*.Len*/; + + if (++count < max_count && curlen === nextlen) { + continue; + + } else if (count < min_count) { + do { + send_code(s, curlen, s.bl_tree); + } while (--count !== 0); + + } else if (curlen !== 0) { + if (curlen !== prevlen) { + send_code(s, curlen, s.bl_tree); + count--; + } + //Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s.bl_tree); + send_bits(s, count - 3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s.bl_tree); + send_bits(s, count - 3, 3); + + } else { + send_code(s, REPZ_11_138, s.bl_tree); + send_bits(s, count - 11, 7); + } + + count = 0; + prevlen = curlen; + if (nextlen === 0) { + max_count = 138; + min_count = 3; + + } else if (curlen === nextlen) { + max_count = 6; + min_count = 3; + + } else { + max_count = 7; + min_count = 4; + } + } + } + + + /* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ + function build_bl_tree(s) { + let max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, s.dyn_ltree, s.l_desc.max_code); + scan_tree(s, s.dyn_dtree, s.d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, s.bl_desc); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) { + if (s.bl_tree[bl_order[max_blindex] * 2 + 1]/*.Len*/ !== 0) { + break; + } + } + /* Update opt_len to include the bit length tree and counts */ + s.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4; + //Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + // s->opt_len, s->static_len)); + + return max_blindex; + } + + + /* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ + function send_all_trees(s, lcodes, dcodes, blcodes) + // deflate_state *s; + // int lcodes, dcodes, blcodes; /* number of codes for each tree */ + { + let rank; /* index in bl_order */ + + //Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + //Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + // "too many codes"); + //Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes - 1, 5); + send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + //Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s.bl_tree[bl_order[rank] * 2 + 1]/*.Len*/, 3); + } + //Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, s.dyn_ltree, lcodes - 1); /* literal tree */ + //Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, s.dyn_dtree, dcodes - 1); /* distance tree */ + //Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); + } + + + /* =========================================================================== + * Check if the data type is TEXT or BINARY, using the following algorithm: + * - TEXT if the two conditions below are satisfied: + * a) There are no non-portable control characters belonging to the + * "black list" (0..6, 14..25, 28..31). + * b) There is at least one printable character belonging to the + * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). + * - BINARY otherwise. + * - The following partially-portable control characters form a + * "gray list" that is ignored in this detection algorithm: + * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). + * IN assertion: the fields Freq of dyn_ltree are set. + */ + function detect_data_type(s) { + /* black_mask is the bit mask of black-listed bytes + * set bits 0..6, 14..25, and 28..31 + * 0xf3ffc07f = binary 11110011111111111100000001111111 + */ + let black_mask = 0xf3ffc07f; + let n; + + /* Check for non-textual ("black-listed") bytes. */ + for (n = 0; n <= 31; n++, black_mask >>>= 1) { + if (black_mask & 1 && s.dyn_ltree[n * 2]/*.Freq*/ !== 0) { + return Z_BINARY; + } + } + + /* Check for textual ("white-listed") bytes. */ + if (s.dyn_ltree[9 * 2]/*.Freq*/ !== 0 || s.dyn_ltree[10 * 2]/*.Freq*/ !== 0 || + s.dyn_ltree[13 * 2]/*.Freq*/ !== 0) { + return Z_TEXT; + } + for (n = 32; n < LITERALS; n++) { + if (s.dyn_ltree[n * 2]/*.Freq*/ !== 0) { + return Z_TEXT; + } + } + + /* There are no "black-listed" or "white-listed" bytes: + * this stream either is empty or has tolerated ("gray-listed") bytes only. + */ + return Z_BINARY; + } + + + let static_init_done = false; + + /* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ + function _tr_init(s) { + + if (!static_init_done) { + tr_static_init(); + static_init_done = true; + } + + s.l_desc = new TreeDesc(s.dyn_ltree, static_l_desc); + s.d_desc = new TreeDesc(s.dyn_dtree, static_d_desc); + s.bl_desc = new TreeDesc(s.bl_tree, static_bl_desc); + + s.bi_buf = 0; + s.bi_valid = 0; + + /* Initialize the first block of the first file: */ + init_block(s); + } + + + /* =========================================================================== + * Send a stored block + */ + function _tr_stored_block(s, buf, stored_len, last) + //DeflateState *s; + //charf *buf; /* input block */ + //ulg stored_len; /* length of input block */ + //int last; /* one if this is the last block for a file */ + { + send_bits(s, (STORED_BLOCK << 1) + (last ? 1 : 0), 3); /* send block type */ + copy_block(s, buf, stored_len, true); /* with header */ + } + + + /* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + */ + function _tr_align(s) { + send_bits(s, STATIC_TREES << 1, 3); + send_code(s, END_BLOCK, static_ltree); + bi_flush(s); + } + + + /* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ + function _tr_flush_block(s, buf, stored_len, last) + //DeflateState *s; + //charf *buf; /* input block, or NULL if too old */ + //ulg stored_len; /* length of input block */ + //int last; /* one if this is the last block for a file */ + { + let opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + let max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s.level > 0) { + + /* Check if the file is binary or text */ + if (s.strm.data_type === Z_UNKNOWN) { + s.strm.data_type = detect_data_type(s); + } + + /* Construct the literal and distance trees */ + build_tree(s, s.l_desc); + // Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + // s->static_len)); + + build_tree(s, s.d_desc); + // Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + // s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = s.opt_len + 3 + 7 >>> 3; + static_lenb = s.static_len + 3 + 7 >>> 3; + + // Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + // opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + // s->last_lit)); + + if (static_lenb <= opt_lenb) { + opt_lenb = static_lenb; + } + + } else { + // Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + + if (stored_len + 4 <= opt_lenb && buf !== -1) { + /* 4: two words for the lengths */ + + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, last); + + } else if (s.strategy === Z_FIXED || static_lenb === opt_lenb) { + + send_bits(s, (STATIC_TREES << 1) + (last ? 1 : 0), 3); + compress_block(s, static_ltree, static_dtree); + + } else { + send_bits(s, (DYN_TREES << 1) + (last ? 1 : 0), 3); + send_all_trees(s, s.l_desc.max_code + 1, s.d_desc.max_code + 1, max_blindex + 1); + compress_block(s, s.dyn_ltree, s.dyn_dtree); + } + // Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (last) { + bi_windup(s); + } + // Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + // s->compressed_len-7*last)); + } + + /* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ + function _tr_tally(s, dist, lc) + // deflate_state *s; + // unsigned dist; /* distance of matched string */ + // unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ + { + //var out_length, in_length, dcode; + + s.pending_buf[s.d_buf + s.last_lit * 2] = dist >>> 8 & 0xff; + s.pending_buf[s.d_buf + s.last_lit * 2 + 1] = dist & 0xff; + + s.pending_buf[s.l_buf + s.last_lit] = lc & 0xff; + s.last_lit++; + + if (dist === 0) { + /* lc is the unmatched char */ + s.dyn_ltree[lc * 2]/*.Freq*/++; + } else { + s.matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + //Assert((ush)dist < (ush)MAX_DIST(s) && + // (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + // (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s.dyn_ltree[(_length_code[lc] + LITERALS + 1) * 2]/*.Freq*/++; + s.dyn_dtree[d_code(dist) * 2]/*.Freq*/++; + } + + // (!) This block is disabled in zlib defaults, + // don't enable it for binary compatibility + + //#ifdef TRUNCATE_BLOCK + // /* Try to guess if it is profitable to stop the current block here */ + // if ((s.last_lit & 0x1fff) === 0 && s.level > 2) { + // /* Compute an upper bound for the compressed length */ + // out_length = s.last_lit*8; + // in_length = s.strstart - s.block_start; + // + // for (dcode = 0; dcode < D_CODES; dcode++) { + // out_length += s.dyn_dtree[dcode*2]/*.Freq*/ * (5 + extra_dbits[dcode]); + // } + // out_length >>>= 3; + // //Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + // // s->last_lit, in_length, out_length, + // // 100L - out_length*100L/in_length)); + // if (s.matches < (s.last_lit>>1)/*int /2*/ && out_length < (in_length>>1)/*int /2*/) { + // return true; + // } + // } + //#endif + + return s.last_lit === s.lit_bufsize - 1; + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ + } + + // Note: adler32 takes 12% for level 0 and 2% for level 6. + // It isn't worth it to make additional optimizations as in original. + // Small size is preferable. + + // (C) 1995-2013 Jean-loup Gailly and Mark Adler + // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin + // + // This software is provided 'as-is', without any express or implied + // warranty. In no event will the authors be held liable for any damages + // arising from the use of this software. + // + // Permission is granted to anyone to use this software for any purpose, + // including commercial applications, and to alter it and redistribute it + // freely, subject to the following restrictions: + // + // 1. The origin of this software must not be misrepresented; you must not + // claim that you wrote the original software. If you use this software + // in a product, an acknowledgment in the product documentation would be + // appreciated but is not required. + // 2. Altered source versions must be plainly marked as such, and must not be + // misrepresented as being the original software. + // 3. This notice may not be removed or altered from any source distribution. + + function adler32(adler, buf, len, pos) { + let s1 = adler & 0xffff |0, + s2 = adler >>> 16 & 0xffff |0, + n = 0; + + while (len !== 0) { + // Set limit ~ twice less than 5552, to keep + // s2 in 31-bits, because we force signed ints. + // in other case %= will fail. + n = len > 2000 ? 2000 : len; + len -= n; + + do { + s1 = s1 + buf[pos++] |0; + s2 = s2 + s1 |0; + } while (--n); + + s1 %= 65521; + s2 %= 65521; + } + + return s1 | s2 << 16 |0; + } + + // Note: we can't get significant speed boost here. + // So write code to minimize size - no pregenerated tables + // and array tools dependencies. + + // (C) 1995-2013 Jean-loup Gailly and Mark Adler + // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin + // + // This software is provided 'as-is', without any express or implied + // warranty. In no event will the authors be held liable for any damages + // arising from the use of this software. + // + // Permission is granted to anyone to use this software for any purpose, + // including commercial applications, and to alter it and redistribute it + // freely, subject to the following restrictions: + // + // 1. The origin of this software must not be misrepresented; you must not + // claim that you wrote the original software. If you use this software + // in a product, an acknowledgment in the product documentation would be + // appreciated but is not required. + // 2. Altered source versions must be plainly marked as such, and must not be + // misrepresented as being the original software. + // 3. This notice may not be removed or altered from any source distribution. + + // Use ordinary array, since untyped makes no boost here + function makeTable() { + let c; + const table = []; + + for (let n = 0; n < 256; n++) { + c = n; + for (let k = 0; k < 8; k++) { + c = c & 1 ? 0xEDB88320 ^ c >>> 1 : c >>> 1; + } + table[n] = c; + } + + return table; + } + + // Create table on load. Just 255 signed longs. Not a problem. + const crcTable = makeTable(); + + + function crc32(crc, buf, len, pos) { + const t = crcTable, + end = pos + len; + + crc ^= -1; + + for (let i = pos; i < end; i++) { + crc = crc >>> 8 ^ t[(crc ^ buf[i]) & 0xFF]; + } + + return crc ^ -1; // >>> 0; + } + + // (C) 1995-2013 Jean-loup Gailly and Mark Adler + // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin + // + // This software is provided 'as-is', without any express or implied + // warranty. In no event will the authors be held liable for any damages + // arising from the use of this software. + // + // Permission is granted to anyone to use this software for any purpose, + // including commercial applications, and to alter it and redistribute it + // freely, subject to the following restrictions: + // + // 1. The origin of this software must not be misrepresented; you must not + // claim that you wrote the original software. If you use this software + // in a product, an acknowledgment in the product documentation would be + // appreciated but is not required. + // 2. Altered source versions must be plainly marked as such, and must not be + // misrepresented as being the original software. + // 3. This notice may not be removed or altered from any source distribution. + + var msg = { + 2: "need dictionary", /* Z_NEED_DICT 2 */ + 1: "stream end", /* Z_STREAM_END 1 */ + 0: "", /* Z_OK 0 */ + "-1": "file error", /* Z_ERRNO (-1) */ + "-2": "stream error", /* Z_STREAM_ERROR (-2) */ + "-3": "data error", /* Z_DATA_ERROR (-3) */ + "-4": "insufficient memory", /* Z_MEM_ERROR (-4) */ + "-5": "buffer error", /* Z_BUF_ERROR (-5) */ + "-6": "incompatible version" /* Z_VERSION_ERROR (-6) */ + }; + + /*============================================================================*/ + + + const MAX_MEM_LEVEL = 9; + + + const LENGTH_CODES$1 = 29; + /* number of length codes, not counting the special END_BLOCK code */ + const LITERALS$1 = 256; + /* number of literal bytes 0..255 */ + const L_CODES$1 = LITERALS$1 + 1 + LENGTH_CODES$1; + /* number of Literal or Length codes, including the END_BLOCK code */ + const D_CODES$1 = 30; + /* number of distance codes */ + const BL_CODES$1 = 19; + /* number of codes used to transfer the bit lengths */ + const HEAP_SIZE$1 = 2 * L_CODES$1 + 1; + /* maximum heap size */ + const MAX_BITS$1 = 15; + /* All codes must not exceed MAX_BITS bits */ + + const MIN_MATCH$1 = 3; + const MAX_MATCH$1 = 258; + const MIN_LOOKAHEAD = (MAX_MATCH$1 + MIN_MATCH$1 + 1); + + const PRESET_DICT = 0x20; + + const INIT_STATE = 42; + const EXTRA_STATE = 69; + const NAME_STATE = 73; + const COMMENT_STATE = 91; + const HCRC_STATE = 103; + const BUSY_STATE = 113; + const FINISH_STATE = 666; + + const BS_NEED_MORE = 1; /* block not completed, need more input or more output */ + const BS_BLOCK_DONE = 2; /* block flush performed */ + const BS_FINISH_STARTED = 3; /* finish started, need only more output at next deflate */ + const BS_FINISH_DONE = 4; /* finish done, accept no more input or output */ + + const OS_CODE = 0x03; // Unix :) . Don't detect, use this default. + + function err(strm, errorCode) { + strm.msg = msg[errorCode]; + return errorCode; + } + + function rank(f) { + return ((f) << 1) - ((f) > 4 ? 9 : 0); + } + + function zero$2(buf) { let len = buf.length; while (--len >= 0) { buf[len] = 0; } } + + + /* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->output buffer and copying into it. + * (See also read_buf()). + */ + function flush_pending(strm) { + const s = strm.state; + + //_tr_flush_bits(s); + let len = s.pending; + if (len > strm.avail_out) { + len = strm.avail_out; + } + if (len === 0) { return; } + + arraySet(strm.output, s.pending_buf, s.pending_out, len, strm.next_out); + strm.next_out += len; + s.pending_out += len; + strm.total_out += len; + strm.avail_out -= len; + s.pending -= len; + if (s.pending === 0) { + s.pending_out = 0; + } + } + + + function flush_block_only(s, last) { + _tr_flush_block(s, (s.block_start >= 0 ? s.block_start : -1), s.strstart - s.block_start, last); + s.block_start = s.strstart; + flush_pending(s.strm); + } + + + function put_byte(s, b) { + s.pending_buf[s.pending++] = b; + } + + + /* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ + function putShortMSB(s, b) { + // put_byte(s, (Byte)(b >> 8)); + // put_byte(s, (Byte)(b & 0xff)); + s.pending_buf[s.pending++] = (b >>> 8) & 0xff; + s.pending_buf[s.pending++] = b & 0xff; + } + + + /* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->input buffer and copying from it. + * (See also flush_pending()). + */ + function read_buf(strm, buf, start, size) { + let len = strm.avail_in; + + if (len > size) { len = size; } + if (len === 0) { return 0; } + + strm.avail_in -= len; + + // zmemcpy(buf, strm->next_in, len); + arraySet(buf, strm.input, strm.next_in, len, start); + if (strm.state.wrap === 1) { + strm.adler = adler32(strm.adler, buf, len, start); + } + + else if (strm.state.wrap === 2) { + strm.adler = crc32(strm.adler, buf, len, start); + } + + strm.next_in += len; + strm.total_in += len; + + return len; + } + + + /* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ + function longest_match(s, cur_match) { + let chain_length = s.max_chain_length; /* max hash chain length */ + let scan = s.strstart; /* current string */ + let match; /* matched string */ + let len; /* length of current match */ + let best_len = s.prev_length; /* best match length so far */ + let nice_match = s.nice_match; /* stop if match long enough */ + const limit = (s.strstart > (s.w_size - MIN_LOOKAHEAD)) ? + s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0/*NIL*/; + + const _win = s.window; // shortcut + + const wmask = s.w_mask; + const prev = s.prev; + + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + + const strend = s.strstart + MAX_MATCH$1; + let scan_end1 = _win[scan + best_len - 1]; + let scan_end = _win[scan + best_len]; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + // Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s.prev_length >= s.good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if (nice_match > s.lookahead) { nice_match = s.lookahead; } + + // Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + // Assert(cur_match < s->strstart, "no future"); + match = cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2. Note that the checks below + * for insufficient lookahead only occur occasionally for performance + * reasons. Therefore uninitialized memory will be accessed, and + * conditional jumps will be made that depend on those values. + * However the length of the match is limited to the lookahead, so + * the output of deflate is not affected by the uninitialized values. + */ + + if (_win[match + best_len] !== scan_end || + _win[match + best_len - 1] !== scan_end1 || + _win[match] !== _win[scan] || + _win[++match] !== _win[scan + 1]) { + continue; + } + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2; + match++; + // Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + /*jshint noempty:false*/ + } while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + scan < strend); + + // Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH$1 - (strend - scan); + scan = strend - MAX_MATCH$1; + + if (len > best_len) { + s.match_start = cur_match; + best_len = len; + if (len >= nice_match) { + break; + } + scan_end1 = _win[scan + best_len - 1]; + scan_end = _win[scan + best_len]; + } + } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0); + + if (best_len <= s.lookahead) { + return best_len; + } + return s.lookahead; + } + + + /* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ + function fill_window(s) { + const _w_size = s.w_size; + let p, n, m, more, str; + + //Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); + + do { + more = s.window_size - s.lookahead - s.strstart; + + // JS ints have 32 bit, block below not needed + /* Deal with !@#$% 64K limit: */ + //if (sizeof(int) <= 2) { + // if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + // more = wsize; + // + // } else if (more == (unsigned)(-1)) { + // /* Very unlikely, but possible on 16 bit machine if + // * strstart == 0 && lookahead == 1 (input done a byte at time) + // */ + // more--; + // } + //} + + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) { + + arraySet(s.window, s.window, _w_size, _w_size, 0); + s.match_start -= _w_size; + s.strstart -= _w_size; + /* we now have strstart >= MAX_DIST */ + s.block_start -= _w_size; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + + n = s.hash_size; + p = n; + do { + m = s.head[--p]; + s.head[p] = (m >= _w_size ? m - _w_size : 0); + } while (--n); + + n = _w_size; + p = n; + do { + m = s.prev[--p]; + s.prev[p] = (m >= _w_size ? m - _w_size : 0); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); + + more += _w_size; + } + if (s.strm.avail_in === 0) { + break; + } + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + //Assert(more >= 2, "more < 2"); + n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more); + s.lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s.lookahead + s.insert >= MIN_MATCH$1) { + str = s.strstart - s.insert; + s.ins_h = s.window[str]; + + /* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + 1]) & s.hash_mask; + //#if MIN_MATCH != 3 + // Call update_hash() MIN_MATCH-3 more times + //#endif + while (s.insert) { + /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH$1 - 1]) & s.hash_mask; + + s.prev[str & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = str; + str++; + s.insert--; + if (s.lookahead + s.insert < MIN_MATCH$1) { + break; + } + } + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0); + + /* If the WIN_INIT bytes after the end of the current data have never been + * written, then zero those bytes in order to avoid memory check reports of + * the use of uninitialized (or uninitialised as Julian writes) bytes by + * the longest match routines. Update the high water mark for the next + * time through here. WIN_INIT is set to MAX_MATCH since the longest match + * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. + */ + // if (s.high_water < s.window_size) { + // var curr = s.strstart + s.lookahead; + // var init = 0; + // + // if (s.high_water < curr) { + // /* Previous high water mark below current data -- zero WIN_INIT + // * bytes or up to end of window, whichever is less. + // */ + // init = s.window_size - curr; + // if (init > WIN_INIT) + // init = WIN_INIT; + // zmemzero(s->window + curr, (unsigned)init); + // s->high_water = curr + init; + // } + // else if (s->high_water < (ulg)curr + WIN_INIT) { + // /* High water mark at or above current data, but below current data + // * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up + // * to end of window, whichever is less. + // */ + // init = (ulg)curr + WIN_INIT - s->high_water; + // if (init > s->window_size - s->high_water) + // init = s->window_size - s->high_water; + // zmemzero(s->window + s->high_water, (unsigned)init); + // s->high_water += init; + // } + // } + // + // Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, + // "not enough room for search"); + } + + /* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ + function deflate_stored(s, flush) { + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + let max_block_size = 0xffff; + + if (max_block_size > s.pending_buf_size - 5) { + max_block_size = s.pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (; ;) { + /* Fill the window as much as possible: */ + if (s.lookahead <= 1) { + + //Assert(s->strstart < s->w_size+MAX_DIST(s) || + // s->block_start >= (long)s->w_size, "slide too late"); + // if (!(s.strstart < s.w_size + (s.w_size - MIN_LOOKAHEAD) || + // s.block_start >= s.w_size)) { + // throw new Error("slide too late"); + // } + + fill_window(s); + if (s.lookahead === 0 && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + + if (s.lookahead === 0) { + break; + } + /* flush the current block */ + } + //Assert(s->block_start >= 0L, "block gone"); + // if (s.block_start < 0) throw new Error("block gone"); + + s.strstart += s.lookahead; + s.lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + const max_start = s.block_start + max_block_size; + + if (s.strstart === 0 || s.strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s.lookahead = s.strstart - max_start; + s.strstart = max_start; + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + + + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s.strstart - s.block_start >= (s.w_size - MIN_LOOKAHEAD)) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + + s.insert = 0; + + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + + if (s.strstart > s.block_start) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + + return BS_NEED_MORE; + } + + /* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ + function deflate_fast(s, flush) { + let hash_head; /* head of the hash chain */ + let bflush; /* set if current block must be flushed */ + + for (; ;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s.lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { + break; /* flush the current block */ + } + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = 0/*NIL*/; + if (s.lookahead >= MIN_MATCH$1) { + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head !== 0/*NIL*/ && ((s.strstart - hash_head) <= (s.w_size - MIN_LOOKAHEAD))) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s.match_length = longest_match(s, hash_head); + /* longest_match() sets match_start */ + } + if (s.match_length >= MIN_MATCH$1) { + // check_match(s, s.strstart, s.match_start, s.match_length); // for debug only + + /*** _tr_tally_dist(s, s.strstart - s.match_start, + s.match_length - MIN_MATCH, bflush); ***/ + bflush = _tr_tally(s, s.strstart - s.match_start, s.match_length - MIN_MATCH$1); + + s.lookahead -= s.match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ + if (s.match_length <= s.max_lazy_match/*max_insert_length*/ && s.lookahead >= MIN_MATCH$1) { + s.match_length--; /* string at strstart already in table */ + do { + s.strstart++; + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s.match_length !== 0); + s.strstart++; + } else { + s.strstart += s.match_length; + s.match_length = 0; + s.ins_h = s.window[s.strstart]; + /* UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]); */ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + 1]) & s.hash_mask; + + //#if MIN_MATCH != 3 + // Call UPDATE_HASH() MIN_MATCH-3 more times + //#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + //Tracevv((stderr,"%c", s.window[s.strstart])); + /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ + bflush = _tr_tally(s, 0, s.window[s.strstart]); + + s.lookahead--; + s.strstart++; + } + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + s.insert = ((s.strstart < (MIN_MATCH$1 - 1)) ? s.strstart : MIN_MATCH$1 - 1); + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + return BS_BLOCK_DONE; + } + + /* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ + function deflate_slow(s, flush) { + let hash_head; /* head of hash chain */ + let bflush; /* set if current block must be flushed */ + + let max_insert; + + /* Process the input block. */ + for (; ;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s.lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { break; } /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = 0/*NIL*/; + if (s.lookahead >= MIN_MATCH$1) { + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + } + + /* Find the longest match, discarding those <= prev_length. + */ + s.prev_length = s.match_length; + s.prev_match = s.match_start; + s.match_length = MIN_MATCH$1 - 1; + + if (hash_head !== 0/*NIL*/ && s.prev_length < s.max_lazy_match && + s.strstart - hash_head <= (s.w_size - MIN_LOOKAHEAD)/*MAX_DIST(s)*/) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s.match_length = longest_match(s, hash_head); + /* longest_match() sets match_start */ + + if (s.match_length <= 5 && + (s.strategy === Z_FILTERED || (s.match_length === MIN_MATCH$1 && s.strstart - s.match_start > 4096/*TOO_FAR*/))) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s.match_length = MIN_MATCH$1 - 1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s.prev_length >= MIN_MATCH$1 && s.match_length <= s.prev_length) { + max_insert = s.strstart + s.lookahead - MIN_MATCH$1; + /* Do not insert strings in hash table beyond this. */ + + //check_match(s, s.strstart-1, s.prev_match, s.prev_length); + + /***_tr_tally_dist(s, s.strstart - 1 - s.prev_match, + s.prev_length - MIN_MATCH, bflush);***/ + bflush = _tr_tally(s, s.strstart - 1 - s.prev_match, s.prev_length - MIN_MATCH$1); + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s.lookahead -= s.prev_length - 1; + s.prev_length -= 2; + do { + if (++s.strstart <= max_insert) { + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + } + } while (--s.prev_length !== 0); + s.match_available = 0; + s.match_length = MIN_MATCH$1 - 1; + s.strstart++; + + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + + } else if (s.match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + //Tracevv((stderr,"%c", s->window[s->strstart-1])); + /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ + bflush = _tr_tally(s, 0, s.window[s.strstart - 1]); + + if (bflush) { + /*** FLUSH_BLOCK_ONLY(s, 0) ***/ + flush_block_only(s, false); + /***/ + } + s.strstart++; + s.lookahead--; + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s.match_available = 1; + s.strstart++; + s.lookahead--; + } + } + //Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s.match_available) { + //Tracevv((stderr,"%c", s->window[s->strstart-1])); + /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ + bflush = _tr_tally(s, 0, s.window[s.strstart - 1]); + + s.match_available = 0; + } + s.insert = s.strstart < MIN_MATCH$1 - 1 ? s.strstart : MIN_MATCH$1 - 1; + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + + return BS_BLOCK_DONE; + } + + + /* =========================================================================== + * For Z_RLE, simply look for runs of bytes, generate matches only of distance + * one. Do not maintain a hash table. (It will be regenerated if this run of + * deflate switches away from Z_RLE.) + */ + function deflate_rle(s, flush) { + let bflush; /* set if current block must be flushed */ + let prev; /* byte at distance one to match */ + let scan, strend; /* scan goes up to strend for length of run */ + + const _win = s.window; + + for (; ;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the longest run, plus one for the unrolled loop. + */ + if (s.lookahead <= MAX_MATCH$1) { + fill_window(s); + if (s.lookahead <= MAX_MATCH$1 && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { break; } /* flush the current block */ + } + + /* See how many times the previous byte repeats */ + s.match_length = 0; + if (s.lookahead >= MIN_MATCH$1 && s.strstart > 0) { + scan = s.strstart - 1; + prev = _win[scan]; + if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) { + strend = s.strstart + MAX_MATCH$1; + do { + /*jshint noempty:false*/ + } while (prev === _win[++scan] && prev === _win[++scan] && + prev === _win[++scan] && prev === _win[++scan] && + prev === _win[++scan] && prev === _win[++scan] && + prev === _win[++scan] && prev === _win[++scan] && + scan < strend); + s.match_length = MAX_MATCH$1 - (strend - scan); + if (s.match_length > s.lookahead) { + s.match_length = s.lookahead; + } + } + //Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); + } + + /* Emit match if have run of MIN_MATCH or longer, else emit literal */ + if (s.match_length >= MIN_MATCH$1) { + //check_match(s, s.strstart, s.strstart - 1, s.match_length); + + /*** _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ***/ + bflush = _tr_tally(s, 1, s.match_length - MIN_MATCH$1); + + s.lookahead -= s.match_length; + s.strstart += s.match_length; + s.match_length = 0; + } else { + /* No match, output a literal byte */ + //Tracevv((stderr,"%c", s->window[s->strstart])); + /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ + bflush = _tr_tally(s, 0, s.window[s.strstart]); + + s.lookahead--; + s.strstart++; + } + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + s.insert = 0; + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + return BS_BLOCK_DONE; + } + + /* =========================================================================== + * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. + * (It will be regenerated if this run of deflate switches away from Huffman.) + */ + function deflate_huff(s, flush) { + let bflush; /* set if current block must be flushed */ + + for (; ;) { + /* Make sure that we have a literal to write. */ + if (s.lookahead === 0) { + fill_window(s); + if (s.lookahead === 0) { + if (flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + break; /* flush the current block */ + } + } + + /* Output a literal byte */ + s.match_length = 0; + //Tracevv((stderr,"%c", s->window[s->strstart])); + /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ + bflush = _tr_tally(s, 0, s.window[s.strstart]); + s.lookahead--; + s.strstart++; + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + s.insert = 0; + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + return BS_BLOCK_DONE; + } + + /* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ + class Config { + constructor(good_length, max_lazy, nice_length, max_chain, func) { + this.good_length = good_length; + this.max_lazy = max_lazy; + this.nice_length = nice_length; + this.max_chain = max_chain; + this.func = func; + } + } + const configuration_table = [ + /* good lazy nice chain */ + new Config(0, 0, 0, 0, deflate_stored), /* 0 store only */ + new Config(4, 4, 8, 4, deflate_fast), /* 1 max speed, no lazy matches */ + new Config(4, 5, 16, 8, deflate_fast), /* 2 */ + new Config(4, 6, 32, 32, deflate_fast), /* 3 */ + + new Config(4, 4, 16, 16, deflate_slow), /* 4 lazy matches */ + new Config(8, 16, 32, 32, deflate_slow), /* 5 */ + new Config(8, 16, 128, 128, deflate_slow), /* 6 */ + new Config(8, 32, 128, 256, deflate_slow), /* 7 */ + new Config(32, 128, 258, 1024, deflate_slow), /* 8 */ + new Config(32, 258, 258, 4096, deflate_slow) /* 9 max compression */ + ]; + + + /* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ + function lm_init(s) { + s.window_size = 2 * s.w_size; + + /*** CLEAR_HASH(s); ***/ + zero$2(s.head); // Fill with NIL (= 0); + + /* Set the default configuration parameters: + */ + s.max_lazy_match = configuration_table[s.level].max_lazy; + s.good_match = configuration_table[s.level].good_length; + s.nice_match = configuration_table[s.level].nice_length; + s.max_chain_length = configuration_table[s.level].max_chain; + + s.strstart = 0; + s.block_start = 0; + s.lookahead = 0; + s.insert = 0; + s.match_length = s.prev_length = MIN_MATCH$1 - 1; + s.match_available = 0; + s.ins_h = 0; + } + + class DeflateState { + constructor() { + this.strm = null; /* pointer back to this zlib stream */ + this.status = 0; /* as the name implies */ + this.pending_buf = null; /* output still pending */ + this.pending_buf_size = 0; /* size of pending_buf */ + this.pending_out = 0; /* next pending byte to output to the stream */ + this.pending = 0; /* nb of bytes in the pending buffer */ + this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ + this.gzhead = null; /* gzip header information to write */ + this.gzindex = 0; /* where in extra, name, or comment */ + this.method = Z_DEFLATED; /* can only be DEFLATED */ + this.last_flush = -1; /* value of flush param for previous deflate call */ + + this.w_size = 0; /* LZ77 window size (32K by default) */ + this.w_bits = 0; /* log2(w_size) (8..16) */ + this.w_mask = 0; /* w_size - 1 */ + + this.window = null; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. + */ + + this.window_size = 0; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + this.prev = null; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + this.head = null; /* Heads of the hash chains or NIL. */ + + this.ins_h = 0; /* hash index of string to be inserted */ + this.hash_size = 0; /* number of elements in hash table */ + this.hash_bits = 0; /* log2(hash_size) */ + this.hash_mask = 0; /* hash_size-1 */ + + this.hash_shift = 0; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + this.block_start = 0; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + this.match_length = 0; /* length of best match */ + this.prev_match = 0; /* previous match */ + this.match_available = 0; /* set if previous match exists */ + this.strstart = 0; /* start of string to insert */ + this.match_start = 0; /* start of matching string */ + this.lookahead = 0; /* number of valid bytes ahead in window */ + + this.prev_length = 0; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + this.max_chain_length = 0; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + this.max_lazy_match = 0; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ + // That's alias to max_lazy_match, don't use directly + //this.max_insert_length = 0; + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + this.level = 0; /* compression level (1..9) */ + this.strategy = 0; /* favor or force Huffman coding*/ + + this.good_match = 0; + /* Use a faster search when the previous match is longer than this */ + + this.nice_match = 0; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + + /* Didn't use ct_data typedef below to suppress compiler warning */ + + // struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + // struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + // struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + // Use flat array of DOUBLE size, with interleaved fata, + // because JS does not support effective + this.dyn_ltree = new Buf16(HEAP_SIZE$1 * 2); + this.dyn_dtree = new Buf16((2 * D_CODES$1 + 1) * 2); + this.bl_tree = new Buf16((2 * BL_CODES$1 + 1) * 2); + zero$2(this.dyn_ltree); + zero$2(this.dyn_dtree); + zero$2(this.bl_tree); + + this.l_desc = null; /* desc. for literal tree */ + this.d_desc = null; /* desc. for distance tree */ + this.bl_desc = null; /* desc. for bit length tree */ + + //ush bl_count[MAX_BITS+1]; + this.bl_count = new Buf16(MAX_BITS$1 + 1); + /* number of codes at each bit length for an optimal tree */ + + //int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + this.heap = new Buf16(2 * L_CODES$1 + 1); /* heap used to build the Huffman trees */ + zero$2(this.heap); + + this.heap_len = 0; /* number of elements in the heap */ + this.heap_max = 0; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + this.depth = new Buf16(2 * L_CODES$1 + 1); //uch depth[2*L_CODES+1]; + zero$2(this.depth); + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + this.l_buf = 0; /* buffer index for literals or lengths */ + + this.lit_bufsize = 0; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + this.last_lit = 0; /* running index in l_buf */ + + this.d_buf = 0; + /* Buffer index for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + this.opt_len = 0; /* bit length of current block with optimal trees */ + this.static_len = 0; /* bit length of current block with static trees */ + this.matches = 0; /* number of string matches in current block */ + this.insert = 0; /* bytes at end of window left to insert */ + + + this.bi_buf = 0; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + this.bi_valid = 0; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + + // Used for window memory init. We safely ignore it for JS. That makes + // sense only for pointers and memory check tools. + //this.high_water = 0; + /* High water mark offset in window for initialized bytes -- bytes above + * this are set to zero in order to avoid memory check warnings when + * longest match routines access bytes past the input. This is then + * updated to the new high water mark. + */ + } + } + + function deflateResetKeep(strm) { + let s; + + if (!strm || !strm.state) { + return err(strm, Z_STREAM_ERROR); + } + + strm.total_in = strm.total_out = 0; + strm.data_type = Z_UNKNOWN; + + s = strm.state; + s.pending = 0; + s.pending_out = 0; + + if (s.wrap < 0) { + s.wrap = -s.wrap; + /* was made negative by deflate(..., Z_FINISH); */ + } + s.status = (s.wrap ? INIT_STATE : BUSY_STATE); + strm.adler = (s.wrap === 2) ? + 0 // crc32(0, Z_NULL, 0) + : + 1; // adler32(0, Z_NULL, 0) + s.last_flush = Z_NO_FLUSH; + _tr_init(s); + return Z_OK; + } + + + function deflateReset(strm) { + const ret = deflateResetKeep(strm); + if (ret === Z_OK) { + lm_init(strm.state); + } + return ret; + } + + + function deflateSetHeader(strm, head) { + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + if (strm.state.wrap !== 2) { return Z_STREAM_ERROR; } + strm.state.gzhead = head; + return Z_OK; + } + + + function deflateInit2(strm, level, method, windowBits, memLevel, strategy) { + if (!strm) { // === Z_NULL + return Z_STREAM_ERROR; + } + let wrap = 1; + + if (level === Z_DEFAULT_COMPRESSION) { + level = 6; + } + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } + + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } + + + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method !== Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_FIXED) { + return err(strm, Z_STREAM_ERROR); + } + + + if (windowBits === 8) { + windowBits = 9; + } + /* until 256-byte window bug fixed */ + + const s = new DeflateState(); + + strm.state = s; + s.strm = strm; + + s.wrap = wrap; + s.gzhead = null; + s.w_bits = windowBits; + s.w_size = 1 << s.w_bits; + s.w_mask = s.w_size - 1; + + s.hash_bits = memLevel + 7; + s.hash_size = 1 << s.hash_bits; + s.hash_mask = s.hash_size - 1; + s.hash_shift = ~~((s.hash_bits + MIN_MATCH$1 - 1) / MIN_MATCH$1); + s.window = new Buf8(s.w_size * 2); + s.head = new Buf16(s.hash_size); + s.prev = new Buf16(s.w_size); + + // Don't need mem init magic for JS. + //s.high_water = 0; /* nothing written to s->window yet */ + + s.lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + s.pending_buf_size = s.lit_bufsize * 4; + + //overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + //s->pending_buf = (uchf *) overlay; + s.pending_buf = new Buf8(s.pending_buf_size); + + // It is offset from `s.pending_buf` (size is `s.lit_bufsize * 2`) + //s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s.d_buf = 1 * s.lit_bufsize; + + //s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + s.l_buf = (1 + 2) * s.lit_bufsize; + + s.level = level; + s.strategy = strategy; + s.method = method; + + return deflateReset(strm); + } + + + function deflate(strm, flush) { + let old_flush, s; + let beg, val; // for gzip header write only + + if (!strm || !strm.state || + flush > Z_BLOCK || flush < 0) { + return strm ? err(strm, Z_STREAM_ERROR) : Z_STREAM_ERROR; + } + + s = strm.state; + + if (!strm.output || + (!strm.input && strm.avail_in !== 0) || + (s.status === FINISH_STATE && flush !== Z_FINISH)) { + return err(strm, (strm.avail_out === 0) ? Z_BUF_ERROR : Z_STREAM_ERROR); + } + + s.strm = strm; /* just in case */ + old_flush = s.last_flush; + s.last_flush = flush; + + /* Write the header */ + if (s.status === INIT_STATE) { + + if (s.wrap === 2) { // GZIP header + strm.adler = 0; //crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (!s.gzhead) { // s->gzhead == Z_NULL + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s.level === 9 ? 2 : + (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s.status = BUSY_STATE; + } + else { + put_byte(s, (s.gzhead.text ? 1 : 0) + + (s.gzhead.hcrc ? 2 : 0) + + (!s.gzhead.extra ? 0 : 4) + + (!s.gzhead.name ? 0 : 8) + + (!s.gzhead.comment ? 0 : 16) + ); + put_byte(s, s.gzhead.time & 0xff); + put_byte(s, (s.gzhead.time >> 8) & 0xff); + put_byte(s, (s.gzhead.time >> 16) & 0xff); + put_byte(s, (s.gzhead.time >> 24) & 0xff); + put_byte(s, s.level === 9 ? 2 : + (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? + 4 : 0)); + put_byte(s, s.gzhead.os & 0xff); + if (s.gzhead.extra && s.gzhead.extra.length) { + put_byte(s, s.gzhead.extra.length & 0xff); + put_byte(s, (s.gzhead.extra.length >> 8) & 0xff); + } + if (s.gzhead.hcrc) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending, 0); + } + s.gzindex = 0; + s.status = EXTRA_STATE; + } + } + else // DEFLATE header + { + let header = (Z_DEFLATED + ((s.w_bits - 8) << 4)) << 8; + let level_flags = -1; + + if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) { + level_flags = 0; + } else if (s.level < 6) { + level_flags = 1; + } else if (s.level === 6) { + level_flags = 2; + } else { + level_flags = 3; + } + header |= (level_flags << 6); + if (s.strstart !== 0) { header |= PRESET_DICT; } + header += 31 - (header % 31); + + s.status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s.strstart !== 0) { + putShortMSB(s, strm.adler >>> 16); + putShortMSB(s, strm.adler & 0xffff); + } + strm.adler = 1; // adler32(0L, Z_NULL, 0); + } + } + + //#ifdef GZIP + if (s.status === EXTRA_STATE) { + if (s.gzhead.extra/* != Z_NULL*/) { + beg = s.pending; /* start of bytes to update crc */ + + while (s.gzindex < (s.gzhead.extra.length & 0xffff)) { + if (s.pending === s.pending_buf_size) { + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + flush_pending(strm); + beg = s.pending; + if (s.pending === s.pending_buf_size) { + break; + } + } + put_byte(s, s.gzhead.extra[s.gzindex] & 0xff); + s.gzindex++; + } + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + if (s.gzindex === s.gzhead.extra.length) { + s.gzindex = 0; + s.status = NAME_STATE; + } + } + else { + s.status = NAME_STATE; + } + } + if (s.status === NAME_STATE) { + if (s.gzhead.name/* != Z_NULL*/) { + beg = s.pending; /* start of bytes to update crc */ + //int val; + + do { + if (s.pending === s.pending_buf_size) { + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + flush_pending(strm); + beg = s.pending; + if (s.pending === s.pending_buf_size) { + val = 1; + break; + } + } + // JS specific: little magic to add zero terminator to end of string + if (s.gzindex < s.gzhead.name.length) { + val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff; + } else { + val = 0; + } + put_byte(s, val); + } while (val !== 0); + + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + if (val === 0) { + s.gzindex = 0; + s.status = COMMENT_STATE; + } + } + else { + s.status = COMMENT_STATE; + } + } + if (s.status === COMMENT_STATE) { + if (s.gzhead.comment/* != Z_NULL*/) { + beg = s.pending; /* start of bytes to update crc */ + //int val; + + do { + if (s.pending === s.pending_buf_size) { + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + flush_pending(strm); + beg = s.pending; + if (s.pending === s.pending_buf_size) { + val = 1; + break; + } + } + // JS specific: little magic to add zero terminator to end of string + if (s.gzindex < s.gzhead.comment.length) { + val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff; + } else { + val = 0; + } + put_byte(s, val); + } while (val !== 0); + + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + if (val === 0) { + s.status = HCRC_STATE; + } + } + else { + s.status = HCRC_STATE; + } + } + if (s.status === HCRC_STATE) { + if (s.gzhead.hcrc) { + if (s.pending + 2 > s.pending_buf_size) { + flush_pending(strm); + } + if (s.pending + 2 <= s.pending_buf_size) { + put_byte(s, strm.adler & 0xff); + put_byte(s, (strm.adler >> 8) & 0xff); + strm.adler = 0; //crc32(0L, Z_NULL, 0); + s.status = BUSY_STATE; + } + } + else { + s.status = BUSY_STATE; + } + } + //#endif + + /* Flush as much pending output as possible */ + if (s.pending !== 0) { + flush_pending(strm); + if (strm.avail_out === 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s.last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) && + flush !== Z_FINISH) { + return err(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s.status === FINISH_STATE && strm.avail_in !== 0) { + return err(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm.avail_in !== 0 || s.lookahead !== 0 || + (flush !== Z_NO_FLUSH && s.status !== FINISH_STATE)) { + var bstate = (s.strategy === Z_HUFFMAN_ONLY) ? deflate_huff(s, flush) : + (s.strategy === Z_RLE ? deflate_rle(s, flush) : + configuration_table[s.level].func(s, flush)); + + if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) { + s.status = FINISH_STATE; + } + if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) { + if (strm.avail_out === 0) { + s.last_flush = -1; + /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate === BS_BLOCK_DONE) { + if (flush === Z_PARTIAL_FLUSH) { + _tr_align(s); + } + else if (flush !== Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ + + _tr_stored_block(s, 0, 0, false); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush === Z_FULL_FLUSH) { + /*** CLEAR_HASH(s); ***/ /* forget history */ + zero$2(s.head); // Fill with NIL (= 0); + + if (s.lookahead === 0) { + s.strstart = 0; + s.block_start = 0; + s.insert = 0; + } + } + } + flush_pending(strm); + if (strm.avail_out === 0) { + s.last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + //Assert(strm->avail_out > 0, "bug2"); + //if (strm.avail_out <= 0) { throw new Error("bug2");} + + if (flush !== Z_FINISH) { return Z_OK; } + if (s.wrap <= 0) { return Z_STREAM_END; } + + /* Write the trailer */ + if (s.wrap === 2) { + put_byte(s, strm.adler & 0xff); + put_byte(s, (strm.adler >> 8) & 0xff); + put_byte(s, (strm.adler >> 16) & 0xff); + put_byte(s, (strm.adler >> 24) & 0xff); + put_byte(s, strm.total_in & 0xff); + put_byte(s, (strm.total_in >> 8) & 0xff); + put_byte(s, (strm.total_in >> 16) & 0xff); + put_byte(s, (strm.total_in >> 24) & 0xff); + } + else { + putShortMSB(s, strm.adler >>> 16); + putShortMSB(s, strm.adler & 0xffff); + } + + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s.wrap > 0) { s.wrap = -s.wrap; } + /* write the trailer only once! */ + return s.pending !== 0 ? Z_OK : Z_STREAM_END; + } + + function deflateEnd(strm) { + let status; + + if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) { + return Z_STREAM_ERROR; + } + + status = strm.state.status; + if (status !== INIT_STATE && + status !== EXTRA_STATE && + status !== NAME_STATE && + status !== COMMENT_STATE && + status !== HCRC_STATE && + status !== BUSY_STATE && + status !== FINISH_STATE + ) { + return err(strm, Z_STREAM_ERROR); + } + + strm.state = null; + + return status === BUSY_STATE ? err(strm, Z_DATA_ERROR) : Z_OK; + } + + + /* ========================================================================= + * Initializes the compression dictionary from the given byte + * sequence without producing any compressed output. + */ + function deflateSetDictionary(strm, dictionary) { + let dictLength = dictionary.length; + + let s; + let str, n; + let wrap; + let avail; + let next; + let input; + let tmpDict; + + if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) { + return Z_STREAM_ERROR; + } + + s = strm.state; + wrap = s.wrap; + + if (wrap === 2 || (wrap === 1 && s.status !== INIT_STATE) || s.lookahead) { + return Z_STREAM_ERROR; + } + + /* when using zlib wrappers, compute Adler-32 for provided dictionary */ + if (wrap === 1) { + /* adler32(strm->adler, dictionary, dictLength); */ + strm.adler = adler32(strm.adler, dictionary, dictLength, 0); + } + + s.wrap = 0; /* avoid computing Adler-32 in read_buf */ + + /* if dictionary would fill window, just replace the history */ + if (dictLength >= s.w_size) { + if (wrap === 0) { /* already empty otherwise */ + /*** CLEAR_HASH(s); ***/ + zero$2(s.head); // Fill with NIL (= 0); + s.strstart = 0; + s.block_start = 0; + s.insert = 0; + } + /* use the tail */ + // dictionary = dictionary.slice(dictLength - s.w_size); + tmpDict = new Buf8(s.w_size); + arraySet(tmpDict, dictionary, dictLength - s.w_size, s.w_size, 0); + dictionary = tmpDict; + dictLength = s.w_size; + } + /* insert dictionary into window and hash */ + avail = strm.avail_in; + next = strm.next_in; + input = strm.input; + strm.avail_in = dictLength; + strm.next_in = 0; + strm.input = dictionary; + fill_window(s); + while (s.lookahead >= MIN_MATCH$1) { + str = s.strstart; + n = s.lookahead - (MIN_MATCH$1 - 1); + do { + /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH$1 - 1]) & s.hash_mask; + + s.prev[str & s.w_mask] = s.head[s.ins_h]; + + s.head[s.ins_h] = str; + str++; + } while (--n); + s.strstart = str; + s.lookahead = MIN_MATCH$1 - 1; + fill_window(s); + } + s.strstart += s.lookahead; + s.block_start = s.strstart; + s.insert = s.lookahead; + s.lookahead = 0; + s.match_length = s.prev_length = MIN_MATCH$1 - 1; + s.match_available = 0; + strm.next_in = next; + strm.input = input; + strm.avail_in = avail; + s.wrap = wrap; + return Z_OK; + } + + /* Not implemented + exports.deflateBound = deflateBound; + exports.deflateCopy = deflateCopy; + exports.deflateParams = deflateParams; + exports.deflatePending = deflatePending; + exports.deflatePrime = deflatePrime; + exports.deflateTune = deflateTune; + */ + + // String encode/decode helpers + + try { + String.fromCharCode.apply(null, [ 0 ]); + } catch (__) { + } + try { + String.fromCharCode.apply(null, new Uint8Array(1)); + } catch (__) { + } + + + // Table with utf8 lengths (calculated by first byte of sequence) + // Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS, + // because max possible codepoint is 0x10ffff + const _utf8len = new Buf8(256); + for (let q = 0; q < 256; q++) { + _utf8len[q] = q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1; + } + _utf8len[254] = _utf8len[254] = 1; // Invalid sequence start + + + // convert string to array (typed, when possible) + function string2buf (str) { + let c, c2, m_pos, i, buf_len = 0; + const str_len = str.length; + + // count binary size + for (m_pos = 0; m_pos < str_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && m_pos + 1 < str_len) { + c2 = str.charCodeAt(m_pos + 1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + (c - 0xd800 << 10) + (c2 - 0xdc00); + m_pos++; + } + } + buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4; + } + + // allocate buffer + const buf = new Buf8(buf_len); + + // convert + for (i = 0, m_pos = 0; i < buf_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && m_pos + 1 < str_len) { + c2 = str.charCodeAt(m_pos + 1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + (c - 0xd800 << 10) + (c2 - 0xdc00); + m_pos++; + } + } + if (c < 0x80) { + /* one byte */ + buf[i++] = c; + } else if (c < 0x800) { + /* two bytes */ + buf[i++] = 0xC0 | c >>> 6; + buf[i++] = 0x80 | c & 0x3f; + } else if (c < 0x10000) { + /* three bytes */ + buf[i++] = 0xE0 | c >>> 12; + buf[i++] = 0x80 | c >>> 6 & 0x3f; + buf[i++] = 0x80 | c & 0x3f; + } else { + /* four bytes */ + buf[i++] = 0xf0 | c >>> 18; + buf[i++] = 0x80 | c >>> 12 & 0x3f; + buf[i++] = 0x80 | c >>> 6 & 0x3f; + buf[i++] = 0x80 | c & 0x3f; + } + } + + return buf; + } + + + // Convert binary string (typed, when possible) + function binstring2buf (str) { + const buf = new Buf8(str.length); + for (let i = 0, len = buf.length; i < len; i++) { + buf[i] = str.charCodeAt(i); + } + return buf; + } + + // (C) 1995-2013 Jean-loup Gailly and Mark Adler + // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin + // + // This software is provided 'as-is', without any express or implied + // warranty. In no event will the authors be held liable for any damages + // arising from the use of this software. + // + // Permission is granted to anyone to use this software for any purpose, + // including commercial applications, and to alter it and redistribute it + // freely, subject to the following restrictions: + // + // 1. The origin of this software must not be misrepresented; you must not + // claim that you wrote the original software. If you use this software + // in a product, an acknowledgment in the product documentation would be + // appreciated but is not required. + // 2. Altered source versions must be plainly marked as such, and must not be + // misrepresented as being the original software. + // 3. This notice may not be removed or altered from any source distribution. + + class ZStream { + constructor() { + /* next input byte */ + this.input = null; // JS specific, because we have no pointers + this.next_in = 0; + /* number of bytes available at input */ + this.avail_in = 0; + /* total number of input bytes read so far */ + this.total_in = 0; + /* next output byte should be put there */ + this.output = null; // JS specific, because we have no pointers + this.next_out = 0; + /* remaining free space at output */ + this.avail_out = 0; + /* total number of bytes output so far */ + this.total_out = 0; + /* last error message, NULL if no error */ + this.msg = ''/*Z_NULL*/; + /* not visible by applications */ + this.state = null; + /* best guess about the data type: binary or text */ + this.data_type = 2/*Z_UNKNOWN*/; + /* adler32 value of the uncompressed data */ + this.adler = 0; + } + } + + /* ===========================================================================*/ + + + /** + * class Deflate + * + * Generic JS-style wrapper for zlib calls. If you don't need + * streaming behaviour - use more simple functions: [[deflate]], + * [[deflateRaw]] and [[gzip]]. + **/ + + /* internal + * Deflate.chunks -> Array + * + * Chunks of output data, if [[Deflate#onData]] not overridden. + **/ + + /** + * Deflate.result -> Uint8Array|Array + * + * Compressed result, generated by default [[Deflate#onData]] + * and [[Deflate#onEnd]] handlers. Filled after you push last chunk + * (call [[Deflate#push]] with `Z_FINISH` / `true` param) or if you + * push a chunk with explicit flush (call [[Deflate#push]] with + * `Z_SYNC_FLUSH` param). + **/ + + /** + * Deflate.err -> Number + * + * Error code after deflate finished. 0 (Z_OK) on success. + * You will not need it in real life, because deflate errors + * are possible only on wrong options or bad `onData` / `onEnd` + * custom handlers. + **/ + + /** + * Deflate.msg -> String + * + * Error message, if [[Deflate.err]] != 0 + **/ + + + /** + * new Deflate(options) + * - options (Object): zlib deflate options. + * + * Creates new deflator instance with specified params. Throws exception + * on bad params. Supported options: + * + * - `level` + * - `windowBits` + * - `memLevel` + * - `strategy` + * - `dictionary` + * + * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) + * for more information on these. + * + * Additional options, for internal needs: + * + * - `chunkSize` - size of generated data chunks (16K by default) + * - `raw` (Boolean) - do raw deflate + * - `gzip` (Boolean) - create gzip wrapper + * - `to` (String) - if equal to 'string', then result will be "binary string" + * (each char code [0..255]) + * - `header` (Object) - custom header for gzip + * - `text` (Boolean) - true if compressed data believed to be text + * - `time` (Number) - modification time, unix timestamp + * - `os` (Number) - operation system code + * - `extra` (Array) - array of bytes with extra data (max 65536) + * - `name` (String) - file name (binary string) + * - `comment` (String) - comment (binary string) + * - `hcrc` (Boolean) - true if header crc should be added + * + * ##### Example: + * + * ```javascript + * var pako = void('pako') + * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9]) + * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]); + * + * var deflate = new pako.Deflate({ level: 3}); + * + * deflate.push(chunk1, false); + * deflate.push(chunk2, true); // true -> last chunk + * + * if (deflate.err) { throw new Error(deflate.err); } + * + * console.log(deflate.result); + * ``` + **/ + + class Deflate { + constructor(options) { + this.options = { + level: Z_DEFAULT_COMPRESSION, + method: Z_DEFLATED, + chunkSize: 16384, + windowBits: 15, + memLevel: 8, + strategy: Z_DEFAULT_STRATEGY, + ...(options || {}) + }; + + const opt = this.options; + + if (opt.raw && (opt.windowBits > 0)) { + opt.windowBits = -opt.windowBits; + } + + else if (opt.gzip && (opt.windowBits > 0) && (opt.windowBits < 16)) { + opt.windowBits += 16; + } + + this.err = 0; // error code, if happens (0 = Z_OK) + this.msg = ''; // error message + this.ended = false; // used to avoid multiple onEnd() calls + this.chunks = []; // chunks of compressed data + + this.strm = new ZStream(); + this.strm.avail_out = 0; + + var status = deflateInit2( + this.strm, + opt.level, + opt.method, + opt.windowBits, + opt.memLevel, + opt.strategy + ); + + if (status !== Z_OK) { + throw new Error(msg[status]); + } + + if (opt.header) { + deflateSetHeader(this.strm, opt.header); + } + + if (opt.dictionary) { + let dict; + // Convert data if needed + if (typeof opt.dictionary === 'string') { + // If we need to compress text, change encoding to utf8. + dict = string2buf(opt.dictionary); + } else if (opt.dictionary instanceof ArrayBuffer) { + dict = new Uint8Array(opt.dictionary); + } else { + dict = opt.dictionary; + } + + status = deflateSetDictionary(this.strm, dict); + + if (status !== Z_OK) { + throw new Error(msg[status]); + } + + this._dict_set = true; + } + } + + /** + * Deflate#push(data[, mode]) -> Boolean + * - data (Uint8Array|Array|ArrayBuffer|String): input data. Strings will be + * converted to utf8 byte sequence. + * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. + * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH. + * + * Sends input data to deflate pipe, generating [[Deflate#onData]] calls with + * new compressed chunks. Returns `true` on success. The last data block must have + * mode Z_FINISH (or `true`). That will flush internal pending buffers and call + * [[Deflate#onEnd]]. For interim explicit flushes (without ending the stream) you + * can use mode Z_SYNC_FLUSH, keeping the compression context. + * + * On fail call [[Deflate#onEnd]] with error code and return false. + * + * We strongly recommend to use `Uint8Array` on input for best speed (output + * array format is detected automatically). Also, don't skip last param and always + * use the same type in your code (boolean or number). That will improve JS speed. + * + * For regular `Array`-s make sure all elements are [0..255]. + * + * ##### Example + * + * ```javascript + * push(chunk, false); // push one of data chunks + * ... + * push(chunk, true); // push last chunk + * ``` + **/ + push(data, mode) { + const { strm, options: { chunkSize } } = this; + var status, _mode; + + if (this.ended) { return false; } + + _mode = (mode === ~~mode) ? mode : ((mode === true) ? Z_FINISH : Z_NO_FLUSH); + + // Convert data if needed + if (typeof data === 'string') { + // If we need to compress text, change encoding to utf8. + strm.input = string2buf(data); + } else if (data instanceof ArrayBuffer) { + strm.input = new Uint8Array(data); + } else { + strm.input = data; + } + + strm.next_in = 0; + strm.avail_in = strm.input.length; + + do { + if (strm.avail_out === 0) { + strm.output = new Buf8(chunkSize); + strm.next_out = 0; + strm.avail_out = chunkSize; + } + status = deflate(strm, _mode); /* no bad return value */ + + if (status !== Z_STREAM_END && status !== Z_OK) { + this.onEnd(status); + this.ended = true; + return false; + } + if (strm.avail_out === 0 || (strm.avail_in === 0 && (_mode === Z_FINISH || _mode === Z_SYNC_FLUSH))) { + this.onData(shrinkBuf(strm.output, strm.next_out)); + } + } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== Z_STREAM_END); + + // Finalize on the last chunk. + if (_mode === Z_FINISH) { + status = deflateEnd(this.strm); + this.onEnd(status); + this.ended = true; + return status === Z_OK; + } + + // callback interim results if Z_SYNC_FLUSH. + if (_mode === Z_SYNC_FLUSH) { + this.onEnd(Z_OK); + strm.avail_out = 0; + return true; + } + + return true; + }; + /** + * Deflate#onData(chunk) -> Void + * - chunk (Uint8Array|Array|String): output data. Type of array depends + * on js engine support. When string output requested, each chunk + * will be string. + * + * By default, stores data blocks in `chunks[]` property and glue + * those in `onEnd`. Override this handler, if you need another behaviour. + **/ + onData(chunk) { + this.chunks.push(chunk); + }; + + /** + * Deflate#onEnd(status) -> Void + * - status (Number): deflate status. 0 (Z_OK) on success, + * other if not. + * + * Called once after you tell deflate that the input stream is + * complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH) + * or if an error happened. By default - join collected chunks, + * free memory and fill `results` / `err` properties. + **/ + onEnd(status) { + // On success - join + if (status === Z_OK) { + this.result = flattenChunks(this.chunks); + } + this.chunks = []; + this.err = status; + this.msg = this.strm.msg; + }; + } + + // (C) 1995-2013 Jean-loup Gailly and Mark Adler + // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin + // + // This software is provided 'as-is', without any express or implied + // warranty. In no event will the authors be held liable for any damages + // arising from the use of this software. + // + // Permission is granted to anyone to use this software for any purpose, + // including commercial applications, and to alter it and redistribute it + // freely, subject to the following restrictions: + // + // 1. The origin of this software must not be misrepresented; you must not + // claim that you wrote the original software. If you use this software + // in a product, an acknowledgment in the product documentation would be + // appreciated but is not required. + // 2. Altered source versions must be plainly marked as such, and must not be + // misrepresented as being the original software. + // 3. This notice may not be removed or altered from any source distribution. + + // See state defs from inflate.js + const BAD = 30; /* got a data error -- remain here until reset */ + const TYPE = 12; /* i: waiting for type bits, including last-flag bit */ + + /* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state.mode === LEN + strm.avail_in >= 6 + strm.avail_out >= 258 + start >= strm.avail_out + state.bits < 8 + + On return, state.mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm.avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm.avail_out >= 258 for each loop to avoid checking for + output space. + */ + function inflate_fast(strm, start) { + let _in; /* local strm.input */ + let _out; /* local strm.output */ + // Use `s_window` instead `window`, avoid conflict with instrumentation tools + let hold; /* local strm.hold */ + let bits; /* local strm.bits */ + let here; /* retrieved table entry */ + let op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + let len; /* match length, unused bytes */ + let dist; /* match distance */ + let from; /* where to copy match from */ + let from_source; + + + + /* copy state to local variables */ + const state = strm.state; + //here = state.here; + _in = strm.next_in; + const input = strm.input; + const last = _in + (strm.avail_in - 5); + _out = strm.next_out; + const output = strm.output; + const beg = _out - (start - strm.avail_out); + const end = _out + (strm.avail_out - 257); + //#ifdef INFLATE_STRICT + const dmax = state.dmax; + //#endif + const wsize = state.wsize; + const whave = state.whave; + const wnext = state.wnext; + const s_window = state.window; + hold = state.hold; + bits = state.bits; + const lcode = state.lencode; + const dcode = state.distcode; + const lmask = (1 << state.lenbits) - 1; + const dmask = (1 << state.distbits) - 1; + + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + + top: + do { + if (bits < 15) { + hold += input[_in++] << bits; + bits += 8; + hold += input[_in++] << bits; + bits += 8; + } + + here = lcode[hold & lmask]; + + dolen: + for (;;) { // Goto emulation + op = here >>> 24/*here.bits*/; + hold >>>= op; + bits -= op; + op = here >>> 16 & 0xff/*here.op*/; + if (op === 0) { /* literal */ + //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + // "inflate: literal '%c'\n" : + // "inflate: literal 0x%02x\n", here.val)); + output[_out++] = here & 0xffff/*here.val*/; + } else if (op & 16) { /* length base */ + len = here & 0xffff/*here.val*/; + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + } + len += hold & (1 << op) - 1; + hold >>>= op; + bits -= op; + } + //Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += input[_in++] << bits; + bits += 8; + hold += input[_in++] << bits; + bits += 8; + } + here = dcode[hold & dmask]; + + dodist: + for (;;) { // goto emulation + op = here >>> 24/*here.bits*/; + hold >>>= op; + bits -= op; + op = here >>> 16 & 0xff/*here.op*/; + + if (op & 16) { /* distance base */ + dist = here & 0xffff/*here.val*/; + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + } + } + dist += hold & (1 << op) - 1; + //#ifdef INFLATE_STRICT + if (dist > dmax) { + strm.msg = "invalid distance too far back"; + state.mode = BAD; + break top; + } + //#endif + hold >>>= op; + bits -= op; + //Tracevv((stderr, "inflate: distance %u\n", dist)); + op = _out - beg; /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state.sane) { + strm.msg = "invalid distance too far back"; + state.mode = BAD; + break top; + } + + // (!) This block is disabled in zlib defaults, + // don't enable it for binary compatibility + //#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + // if (len <= op - whave) { + // do { + // output[_out++] = 0; + // } while (--len); + // continue top; + // } + // len -= op - whave; + // do { + // output[_out++] = 0; + // } while (--op > whave); + // if (op === 0) { + // from = _out - dist; + // do { + // output[_out++] = output[from++]; + // } while (--len); + // continue top; + // } + //#endif + } + from = 0; // window index + from_source = s_window; + if (wnext === 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } else if (wnext < op) { /* wrap around window */ + from += wsize + wnext - op; + op -= wnext; + if (op < len) { /* some from end of window */ + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = 0; + if (wnext < len) { /* some from start of window */ + op = wnext; + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } + } else { /* contiguous in window */ + from += wnext - op; + if (op < len) { /* some from window */ + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } + while (len > 2) { + output[_out++] = from_source[from++]; + output[_out++] = from_source[from++]; + output[_out++] = from_source[from++]; + len -= 3; + } + if (len) { + output[_out++] = from_source[from++]; + if (len > 1) { + output[_out++] = from_source[from++]; + } + } + } else { + from = _out - dist; /* copy direct from output */ + do { /* minimum length is three */ + output[_out++] = output[from++]; + output[_out++] = output[from++]; + output[_out++] = output[from++]; + len -= 3; + } while (len > 2); + if (len) { + output[_out++] = output[from++]; + if (len > 1) { + output[_out++] = output[from++]; + } + } + } + } else if ((op & 64) === 0) { /* 2nd level distance code */ + here = dcode[(here & 0xffff)/*here.val*/ + (hold & (1 << op) - 1)]; + continue dodist; + } else { + strm.msg = "invalid distance code"; + state.mode = BAD; + break top; + } + + break; // need to emulate goto via "continue" + } + } else if ((op & 64) === 0) { /* 2nd level length code */ + here = lcode[(here & 0xffff)/*here.val*/ + (hold & (1 << op) - 1)]; + continue dolen; + } else if (op & 32) { /* end-of-block */ + //Tracevv((stderr, "inflate: end of block\n")); + state.mode = TYPE; + break top; + } else { + strm.msg = "invalid literal/length code"; + state.mode = BAD; + break top; + } + + break; // need to emulate goto via "continue" + } + } while (_in < last && _out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + _in -= len; + bits -= len << 3; + hold &= (1 << bits) - 1; + + /* update state and return */ + strm.next_in = _in; + strm.next_out = _out; + strm.avail_in = _in < last ? 5 + (last - _in) : 5 - (_in - last); + strm.avail_out = _out < end ? 257 + (end - _out) : 257 - (_out - end); + state.hold = hold; + state.bits = bits; + return; + } + + const MAXBITS = 15; + const ENOUGH_LENS = 852; + const ENOUGH_DISTS = 592; + //var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); + + const CODES = 0; + const LENS = 1; + const DISTS = 2; + + const lbase = [ /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 + ]; + + const lext = [ /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78 + ]; + + const dbase = [ /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0 + ]; + + const dext = [ /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64 + ]; + + function inflate_table(type, lens, lens_index, codes, table, table_index, work, opts) { + const bits = opts.bits; + //here = opts.here; /* table entry for duplication */ + + let len = 0; /* a code's length in bits */ + let sym = 0; /* index of code symbols */ + let min = 0, max = 0; /* minimum and maximum code lengths */ + let root = 0; /* number of index bits for root table */ + let curr = 0; /* number of index bits for current table */ + let drop = 0; /* code bits to drop for sub-table */ + let left = 0; /* number of prefix codes available */ + let used = 0; /* code entries in table used */ + let huff = 0; /* Huffman code */ + let incr; /* for incrementing code, index */ + let fill; /* index for replicating entries */ + let low; /* low bits for current root entry */ + let next; /* next available space in table */ + let base = null; /* base value table to use */ + let base_index = 0; + // var shoextra; /* extra bits table to use */ + let end; /* use base and extra for symbol > end */ + const count = new Buf16(MAXBITS + 1); //[MAXBITS+1]; /* number of codes of each length */ + const offs = new Buf16(MAXBITS + 1); //[MAXBITS+1]; /* offsets in table for each length */ + let extra = null; + let extra_index = 0; + + let here_bits, here_op, here_val; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) { + count[len] = 0; + } + for (sym = 0; sym < codes; sym++) { + count[lens[lens_index + sym]]++; + } + + /* bound code lengths, force root to be within code lengths */ + root = bits; + for (max = MAXBITS; max >= 1; max--) { + if (count[max] !== 0) { + break; + } + } + if (root > max) { + root = max; + } + if (max === 0) { /* no symbols to code at all */ + //table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */ + //table.bits[opts.table_index] = 1; //here.bits = (var char)1; + //table.val[opts.table_index++] = 0; //here.val = (var short)0; + table[table_index++] = 1 << 24 | 64 << 16 | 0; + + + //table.op[opts.table_index] = 64; + //table.bits[opts.table_index] = 1; + //table.val[opts.table_index++] = 0; + table[table_index++] = 1 << 24 | 64 << 16 | 0; + + opts.bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min < max; min++) { + if (count[min] !== 0) { + break; + } + } + if (root < min) { + root = min; + } + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) { + return -1; + } /* over-subscribed */ + } + if (left > 0 && (type === CODES || max !== 1)) { + return -1; /* incomplete set */ + } + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) { + offs[len + 1] = offs[len] + count[len]; + } + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) { + if (lens[lens_index + sym] !== 0) { + work[offs[lens[lens_index + sym]]++] = sym; + } + } + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftrees.h + for more information. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + // poor man optimization - use if-else instead of switch, + // to avoid deopts in old v8 + if (type === CODES) { + base = extra = work; /* dummy value--not used */ + end = 19; + + } else if (type === LENS) { + base = lbase; + base_index -= 257; + extra = lext; + extra_index -= 257; + end = 256; + + } else { /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize opts for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = table_index; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = -1; /* trigger new sub-table when len > root */ + used = 1 << root; /* use root table entries */ + const mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if (type === LENS && used > ENOUGH_LENS || + type === DISTS && used > ENOUGH_DISTS) { + return 1; + } + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + here_bits = len - drop; + if (work[sym] < end) { + here_op = 0; + here_val = work[sym]; + } else if (work[sym] > end) { + here_op = extra[extra_index + work[sym]]; + here_val = base[base_index + work[sym]]; + } else { + here_op = 32 + 64; /* end of block */ + here_val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1 << len - drop; + fill = 1 << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + table[next + (huff >> drop) + fill] = here_bits << 24 | here_op << 16 | here_val |0; + } while (fill !== 0); + + /* backwards increment the len-bit code huff */ + incr = 1 << len - 1; + while (huff & incr) { + incr >>= 1; + } + if (incr !== 0) { + huff &= incr - 1; + huff += incr; + } else { + huff = 0; + } + + /* go to next symbol, update count, len */ + sym++; + if (--count[len] === 0) { + if (len === max) { + break; + } + len = lens[lens_index + work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) !== low) { + /* if first time, transition to sub-tables */ + if (drop === 0) { + drop = root; + } + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = 1 << curr; + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) { + break; + } + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1 << curr; + if (type === LENS && used > ENOUGH_LENS || + type === DISTS && used > ENOUGH_DISTS) { + return 1; + } + + /* point entry in root table to sub-table */ + low = huff & mask; + /*table.op[low] = curr; + table.bits[low] = root; + table.val[low] = next - opts.table_index;*/ + table[low] = root << 24 | curr << 16 | next - table_index |0; + } + } + + /* fill in remaining table entry if code is incomplete (guaranteed to have + at most one remaining entry, since if the code is incomplete, the + maximum code length that was allowed to get this far is one bit) */ + if (huff !== 0) { + //table.op[next + huff] = 64; /* invalid code marker */ + //table.bits[next + huff] = len - drop; + //table.val[next + huff] = 0; + table[next + huff] = len - drop << 24 | 64 << 16 |0; + } + + /* set return parameters */ + //opts.table_index += used; + opts.bits = root; + return 0; + } + + const CODES$1 = 0; + const LENS$1 = 1; + const DISTS$1 = 2; + + /* STATES ====================================================================*/ + /* ===========================================================================*/ + + + const HEAD = 1; /* i: waiting for magic header */ + const FLAGS = 2; /* i: waiting for method and flags (gzip) */ + const TIME = 3; /* i: waiting for modification time (gzip) */ + const OS = 4; /* i: waiting for extra flags and operating system (gzip) */ + const EXLEN = 5; /* i: waiting for extra length (gzip) */ + const EXTRA = 6; /* i: waiting for extra bytes (gzip) */ + const NAME = 7; /* i: waiting for end of file name (gzip) */ + const COMMENT = 8; /* i: waiting for end of comment (gzip) */ + const HCRC = 9; /* i: waiting for header crc (gzip) */ + const DICTID = 10; /* i: waiting for dictionary check value */ + const DICT = 11; /* waiting for inflateSetDictionary() call */ + const TYPE$1 = 12; /* i: waiting for type bits, including last-flag bit */ + const TYPEDO = 13; /* i: same, but skip check to exit inflate on new block */ + const STORED = 14; /* i: waiting for stored size (length and complement) */ + const COPY_ = 15; /* i/o: same as COPY below, but only first time in */ + const COPY = 16; /* i/o: waiting for input or output to copy stored block */ + const TABLE = 17; /* i: waiting for dynamic block table lengths */ + const LENLENS = 18; /* i: waiting for code length code lengths */ + const CODELENS = 19; /* i: waiting for length/lit and distance code lengths */ + const LEN_ = 20; /* i: same as LEN below, but only first time in */ + const LEN = 21; /* i: waiting for length/lit/eob code */ + const LENEXT = 22; /* i: waiting for length extra bits */ + const DIST = 23; /* i: waiting for distance code */ + const DISTEXT = 24; /* i: waiting for distance extra bits */ + const MATCH = 25; /* o: waiting for output space to copy string */ + const LIT = 26; /* o: waiting for output space to write literal */ + const CHECK = 27; /* i: waiting for 32-bit check value */ + const LENGTH = 28; /* i: waiting for 32-bit length (gzip) */ + const DONE = 29; /* finished check, done -- remain here until reset */ + const BAD$1 = 30; /* got a data error -- remain here until reset */ + //const MEM = 31; /* got an inflate() memory error -- remain here until reset */ + const SYNC = 32; /* looking for synchronization bytes to restart inflate() */ + + /* ===========================================================================*/ + + + + const ENOUGH_LENS$1 = 852; + const ENOUGH_DISTS$1 = 592; + + + function zswap32(q) { + return (((q >>> 24) & 0xff) + + ((q >>> 8) & 0xff00) + + ((q & 0xff00) << 8) + + ((q & 0xff) << 24)); + } + + + class InflateState { + constructor() { + this.mode = 0; /* current inflate mode */ + this.last = false; /* true if processing last block */ + this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ + this.havedict = false; /* true if dictionary provided */ + this.flags = 0; /* gzip header method and flags (0 if zlib) */ + this.dmax = 0; /* zlib header max distance (INFLATE_STRICT) */ + this.check = 0; /* protected copy of check value */ + this.total = 0; /* protected copy of output count */ + // TODO: may be {} + this.head = null; /* where to save gzip header information */ + + /* sliding window */ + this.wbits = 0; /* log base 2 of requested window size */ + this.wsize = 0; /* window size or zero if not using window */ + this.whave = 0; /* valid bytes in the window */ + this.wnext = 0; /* window write index */ + this.window = null; /* allocated sliding window, if needed */ + + /* bit accumulator */ + this.hold = 0; /* input bit accumulator */ + this.bits = 0; /* number of bits in "in" */ + + /* for string and stored block copying */ + this.length = 0; /* literal or length of data to copy */ + this.offset = 0; /* distance back to copy string from */ + + /* for table and code decoding */ + this.extra = 0; /* extra bits needed */ + + /* fixed and dynamic code tables */ + this.lencode = null; /* starting table for length/literal codes */ + this.distcode = null; /* starting table for distance codes */ + this.lenbits = 0; /* index bits for lencode */ + this.distbits = 0; /* index bits for distcode */ + + /* dynamic table building */ + this.ncode = 0; /* number of code length code lengths */ + this.nlen = 0; /* number of length code lengths */ + this.ndist = 0; /* number of distance code lengths */ + this.have = 0; /* number of code lengths in lens[] */ + this.next = null; /* next available space in codes[] */ + + this.lens = new Buf16(320); /* temporary storage for code lengths */ + this.work = new Buf16(288); /* work area for code table building */ + + /* + because we don't have pointers in js, we use lencode and distcode directly + as buffers so we don't need codes + */ + //this.codes = new utils.Buf32(ENOUGH); /* space for code tables */ + this.lendyn = null; /* dynamic table for length/literal codes (JS specific) */ + this.distdyn = null; /* dynamic table for distance codes (JS specific) */ + this.sane = 0; /* if false, allow invalid distance too far */ + this.back = 0; /* bits back of last unprocessed length/lit */ + this.was = 0; /* initial length of match */ + } + } + + function inflateResetKeep(strm) { + let state; + + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + strm.total_in = strm.total_out = state.total = 0; + strm.msg = ''; /*Z_NULL*/ + if (state.wrap) { /* to support ill-conceived Java test suite */ + strm.adler = state.wrap & 1; + } + state.mode = HEAD; + state.last = 0; + state.havedict = 0; + state.dmax = 32768; + state.head = null/*Z_NULL*/; + state.hold = 0; + state.bits = 0; + //state.lencode = state.distcode = state.next = state.codes; + state.lencode = state.lendyn = new Buf32(ENOUGH_LENS$1); + state.distcode = state.distdyn = new Buf32(ENOUGH_DISTS$1); + + state.sane = 1; + state.back = -1; + //Tracev((stderr, "inflate: reset\n")); + return Z_OK; + } + + function inflateReset(strm) { + let state; + + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + state.wsize = 0; + state.whave = 0; + state.wnext = 0; + return inflateResetKeep(strm); + + } + + function inflateReset2(strm, windowBits) { + let wrap; + let state; + + /* get the state */ + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } + else { + wrap = (windowBits >> 4) + 1; + if (windowBits < 48) { + windowBits &= 15; + } + } + + /* set number of window bits, free window if different */ + if (windowBits && (windowBits < 8 || windowBits > 15)) { + return Z_STREAM_ERROR; + } + if (state.window !== null && state.wbits !== windowBits) { + state.window = null; + } + + /* update state and reset the rest of it */ + state.wrap = wrap; + state.wbits = windowBits; + return inflateReset(strm); + } + + function inflateInit2(strm, windowBits) { + let ret; + let state; + + if (!strm) { return Z_STREAM_ERROR; } + //strm.msg = Z_NULL; /* in case we return an error */ + + state = new InflateState(); + + //if (state === Z_NULL) return Z_MEM_ERROR; + //Tracev((stderr, "inflate: allocated\n")); + strm.state = state; + state.window = null/*Z_NULL*/; + ret = inflateReset2(strm, windowBits); + if (ret !== Z_OK) { + strm.state = null/*Z_NULL*/; + } + return ret; + } + + + /* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ + let virgin = true; + + let lenfix, distfix; // We have no pointers in JS, so keep tables separate + + function fixedtables(state) { + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + let sym; + + lenfix = new Buf32(512); + distfix = new Buf32(32); + + /* literal/length table */ + sym = 0; + while (sym < 144) { state.lens[sym++] = 8; } + while (sym < 256) { state.lens[sym++] = 9; } + while (sym < 280) { state.lens[sym++] = 7; } + while (sym < 288) { state.lens[sym++] = 8; } + + inflate_table(LENS$1, state.lens, 0, 288, lenfix, 0, state.work, { bits: 9 }); + + /* distance table */ + sym = 0; + while (sym < 32) { state.lens[sym++] = 5; } + + inflate_table(DISTS$1, state.lens, 0, 32, distfix, 0, state.work, { bits: 5 }); + + /* do this just once */ + virgin = false; + } + + state.lencode = lenfix; + state.lenbits = 9; + state.distcode = distfix; + state.distbits = 5; + } + + + /* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ + function updatewindow(strm, src, end, copy) { + let dist; + const state = strm.state; + + /* if it hasn't been done already, allocate space for the window */ + if (state.window === null) { + state.wsize = 1 << state.wbits; + state.wnext = 0; + state.whave = 0; + + state.window = new Buf8(state.wsize); + } + + /* copy state->wsize or less output bytes into the circular window */ + if (copy >= state.wsize) { + arraySet(state.window, src, end - state.wsize, state.wsize, 0); + state.wnext = 0; + state.whave = state.wsize; + } + else { + dist = state.wsize - state.wnext; + if (dist > copy) { + dist = copy; + } + //zmemcpy(state->window + state->wnext, end - copy, dist); + arraySet(state.window, src, end - copy, dist, state.wnext); + copy -= dist; + if (copy) { + //zmemcpy(state->window, end - copy, copy); + arraySet(state.window, src, end - copy, copy, 0); + state.wnext = copy; + state.whave = state.wsize; + } + else { + state.wnext += dist; + if (state.wnext === state.wsize) { state.wnext = 0; } + if (state.whave < state.wsize) { state.whave += dist; } + } + } + return 0; + } + + function inflate(strm, flush) { + let state; + let input, output; // input/output buffers + let next; /* next input INDEX */ + let put; /* next output INDEX */ + let have, left; /* available input and output */ + let hold; /* bit buffer */ + let bits; /* bits in bit buffer */ + let _in, _out; /* save starting available input and output */ + let copy; /* number of stored or match bytes to copy */ + let from; /* where to copy match bytes from */ + let from_source; + let here = 0; /* current decoding table entry */ + let here_bits, here_op, here_val; // paked "here" denormalized (JS specific) + //var last; /* parent table entry */ + let last_bits, last_op, last_val; // paked "last" denormalized (JS specific) + let len; /* length to copy for repeats, bits to drop */ + let ret; /* return code */ + let hbuf = new Buf8(4); /* buffer for gzip header crc calculation */ + let opts; + + let n; // temporary var for NEED_BITS + + const order = /* permutation of code lengths */ + [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ]; + + + if (!strm || !strm.state || !strm.output || + (!strm.input && strm.avail_in !== 0)) { + return Z_STREAM_ERROR; + } + + state = strm.state; + if (state.mode === TYPE$1) { state.mode = TYPEDO; } /* skip check */ + + + //--- LOAD() --- + put = strm.next_out; + output = strm.output; + left = strm.avail_out; + next = strm.next_in; + input = strm.input; + have = strm.avail_in; + hold = state.hold; + bits = state.bits; + //--- + + _in = have; + _out = left; + ret = Z_OK; + + inf_leave: // goto emulation + for (;;) { + switch (state.mode) { + case HEAD: + if (state.wrap === 0) { + state.mode = TYPEDO; + break; + } + //=== NEEDBITS(16); + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if ((state.wrap & 2) && hold === 0x8b1f) { /* gzip header */ + state.check = 0/*crc32(0L, Z_NULL, 0)*/; + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = FLAGS; + break; + } + state.flags = 0; /* expect zlib header */ + if (state.head) { + state.head.done = false; + } + if (!(state.wrap & 1) || /* check if zlib header allowed */ + (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) { + strm.msg = 'incorrect header check'; + state.mode = BAD$1; + break; + } + if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) { + strm.msg = 'unknown compression method'; + state.mode = BAD$1; + break; + } + //--- DROPBITS(4) ---// + hold >>>= 4; + bits -= 4; + //---// + len = (hold & 0x0f)/*BITS(4)*/ + 8; + if (state.wbits === 0) { + state.wbits = len; + } + else if (len > state.wbits) { + strm.msg = 'invalid window size'; + state.mode = BAD$1; + break; + } + state.dmax = 1 << len; + //Tracev((stderr, "inflate: zlib header ok\n")); + strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; + state.mode = hold & 0x200 ? DICTID : TYPE$1; + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + break; + case FLAGS: + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.flags = hold; + if ((state.flags & 0xff) !== Z_DEFLATED) { + strm.msg = 'unknown compression method'; + state.mode = BAD$1; + break; + } + if (state.flags & 0xe000) { + strm.msg = 'unknown header flags set'; + state.mode = BAD$1; + break; + } + if (state.head) { + state.head.text = ((hold >> 8) & 1); + } + if (state.flags & 0x0200) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = TIME; + /* falls through */ + case TIME: + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (state.head) { + state.head.time = hold; + } + if (state.flags & 0x0200) { + //=== CRC4(state.check, hold) + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + hbuf[2] = (hold >>> 16) & 0xff; + hbuf[3] = (hold >>> 24) & 0xff; + state.check = crc32(state.check, hbuf, 4, 0); + //=== + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = OS; + /* falls through */ + case OS: + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (state.head) { + state.head.xflags = (hold & 0xff); + state.head.os = (hold >> 8); + } + if (state.flags & 0x0200) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = EXLEN; + /* falls through */ + case EXLEN: + if (state.flags & 0x0400) { + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.length = hold; + if (state.head) { + state.head.extra_len = hold; + } + if (state.flags & 0x0200) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + } + else if (state.head) { + state.head.extra = null/*Z_NULL*/; + } + state.mode = EXTRA; + /* falls through */ + case EXTRA: + if (state.flags & 0x0400) { + copy = state.length; + if (copy > have) { copy = have; } + if (copy) { + if (state.head) { + len = state.head.extra_len - state.length; + if (!state.head.extra) { + // Use untyped array for more convenient processing later + state.head.extra = new Array(state.head.extra_len); + } + arraySet( + state.head.extra, + input, + next, + // extra field is limited to 65536 bytes + // - no need for additional size check + copy, + /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/ + len + ); + //zmemcpy(state.head.extra + len, next, + // len + copy > state.head.extra_max ? + // state.head.extra_max - len : copy); + } + if (state.flags & 0x0200) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + state.length -= copy; + } + if (state.length) { break inf_leave; } + } + state.length = 0; + state.mode = NAME; + /* falls through */ + case NAME: + if (state.flags & 0x0800) { + if (have === 0) { break inf_leave; } + copy = 0; + do { + // TODO: 2 or 1 bytes? + len = input[next + copy++]; + /* use constant limit because in js we should not preallocate memory */ + if (state.head && len && + (state.length < 65536 /*state.head.name_max*/)) { + state.head.name += String.fromCharCode(len); + } + } while (len && copy < have); + + if (state.flags & 0x0200) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + if (len) { break inf_leave; } + } + else if (state.head) { + state.head.name = null; + } + state.length = 0; + state.mode = COMMENT; + /* falls through */ + case COMMENT: + if (state.flags & 0x1000) { + if (have === 0) { break inf_leave; } + copy = 0; + do { + len = input[next + copy++]; + /* use constant limit because in js we should not preallocate memory */ + if (state.head && len && + (state.length < 65536 /*state.head.comm_max*/)) { + state.head.comment += String.fromCharCode(len); + } + } while (len && copy < have); + if (state.flags & 0x0200) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + if (len) { break inf_leave; } + } + else if (state.head) { + state.head.comment = null; + } + state.mode = HCRC; + /* falls through */ + case HCRC: + if (state.flags & 0x0200) { + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (hold !== (state.check & 0xffff)) { + strm.msg = 'header crc mismatch'; + state.mode = BAD$1; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + } + if (state.head) { + state.head.hcrc = ((state.flags >> 9) & 1); + state.head.done = true; + } + strm.adler = state.check = 0; + state.mode = TYPE$1; + break; + case DICTID: + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + strm.adler = state.check = zswap32(hold); + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = DICT; + /* falls through */ + case DICT: + if (state.havedict === 0) { + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + return Z_NEED_DICT; + } + strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; + state.mode = TYPE$1; + /* falls through */ + case TYPE$1: + if (flush === Z_BLOCK || flush === Z_TREES) { break inf_leave; } + /* falls through */ + case TYPEDO: + if (state.last) { + //--- BYTEBITS() ---// + hold >>>= bits & 7; + bits -= bits & 7; + //---// + state.mode = CHECK; + break; + } + //=== NEEDBITS(3); */ + while (bits < 3) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.last = (hold & 0x01)/*BITS(1)*/; + //--- DROPBITS(1) ---// + hold >>>= 1; + bits -= 1; + //---// + + switch ((hold & 0x03)/*BITS(2)*/) { + case 0: /* stored block */ + //Tracev((stderr, "inflate: stored block%s\n", + // state.last ? " (last)" : "")); + state.mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + //Tracev((stderr, "inflate: fixed codes block%s\n", + // state.last ? " (last)" : "")); + state.mode = LEN_; /* decode codes */ + if (flush === Z_TREES) { + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + break inf_leave; + } + break; + case 2: /* dynamic block */ + //Tracev((stderr, "inflate: dynamic codes block%s\n", + // state.last ? " (last)" : "")); + state.mode = TABLE; + break; + case 3: + strm.msg = 'invalid block type'; + state.mode = BAD$1; + } + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + break; + case STORED: + //--- BYTEBITS() ---// /* go to byte boundary */ + hold >>>= bits & 7; + bits -= bits & 7; + //---// + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) { + strm.msg = 'invalid stored block lengths'; + state.mode = BAD$1; + break; + } + state.length = hold & 0xffff; + //Tracev((stderr, "inflate: stored length %u\n", + // state.length)); + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = COPY_; + if (flush === Z_TREES) { break inf_leave; } + /* falls through */ + case COPY_: + state.mode = COPY; + /* falls through */ + case COPY: + copy = state.length; + if (copy) { + if (copy > have) { copy = have; } + if (copy > left) { copy = left; } + if (copy === 0) { break inf_leave; } + //--- zmemcpy(put, next, copy); --- + arraySet(output, input, next, copy, put); + //---// + have -= copy; + next += copy; + left -= copy; + put += copy; + state.length -= copy; + break; + } + //Tracev((stderr, "inflate: stored end\n")); + state.mode = TYPE$1; + break; + case TABLE: + //=== NEEDBITS(14); */ + while (bits < 14) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257; + //--- DROPBITS(5) ---// + hold >>>= 5; + bits -= 5; + //---// + state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1; + //--- DROPBITS(5) ---// + hold >>>= 5; + bits -= 5; + //---// + state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4; + //--- DROPBITS(4) ---// + hold >>>= 4; + bits -= 4; + //---// + //#ifndef PKZIP_BUG_WORKAROUND + if (state.nlen > 286 || state.ndist > 30) { + strm.msg = 'too many length or distance symbols'; + state.mode = BAD$1; + break; + } + //#endif + //Tracev((stderr, "inflate: table sizes ok\n")); + state.have = 0; + state.mode = LENLENS; + /* falls through */ + case LENLENS: + while (state.have < state.ncode) { + //=== NEEDBITS(3); + while (bits < 3) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.lens[order[state.have++]] = (hold & 0x07);//BITS(3); + //--- DROPBITS(3) ---// + hold >>>= 3; + bits -= 3; + //---// + } + while (state.have < 19) { + state.lens[order[state.have++]] = 0; + } + // We have separate tables & no pointers. 2 commented lines below not needed. + //state.next = state.codes; + //state.lencode = state.next; + // Switch to use dynamic table + state.lencode = state.lendyn; + state.lenbits = 7; + + opts = { bits: state.lenbits }; + ret = inflate_table(CODES$1, state.lens, 0, 19, state.lencode, 0, state.work, opts); + state.lenbits = opts.bits; + + if (ret) { + strm.msg = 'invalid code lengths set'; + state.mode = BAD$1; + break; + } + //Tracev((stderr, "inflate: code lengths ok\n")); + state.have = 0; + state.mode = CODELENS; + /* falls through */ + case CODELENS: + while (state.have < state.nlen + state.ndist) { + for (;;) { + here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if (here_val < 16) { + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.lens[state.have++] = here_val; + } + else { + if (here_val === 16) { + //=== NEEDBITS(here.bits + 2); + n = here_bits + 2; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + if (state.have === 0) { + strm.msg = 'invalid bit length repeat'; + state.mode = BAD$1; + break; + } + len = state.lens[state.have - 1]; + copy = 3 + (hold & 0x03);//BITS(2); + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + } + else if (here_val === 17) { + //=== NEEDBITS(here.bits + 3); + n = here_bits + 3; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + len = 0; + copy = 3 + (hold & 0x07);//BITS(3); + //--- DROPBITS(3) ---// + hold >>>= 3; + bits -= 3; + //---// + } + else { + //=== NEEDBITS(here.bits + 7); + n = here_bits + 7; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + len = 0; + copy = 11 + (hold & 0x7f);//BITS(7); + //--- DROPBITS(7) ---// + hold >>>= 7; + bits -= 7; + //---// + } + if (state.have + copy > state.nlen + state.ndist) { + strm.msg = 'invalid bit length repeat'; + state.mode = BAD$1; + break; + } + while (copy--) { + state.lens[state.have++] = len; + } + } + } + + /* handle error breaks in while */ + if (state.mode === BAD$1) { break; } + + /* check for end-of-block code (better have one) */ + if (state.lens[256] === 0) { + strm.msg = 'invalid code -- missing end-of-block'; + state.mode = BAD$1; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state.lenbits = 9; + + opts = { bits: state.lenbits }; + ret = inflate_table(LENS$1, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts); + // We have separate tables & no pointers. 2 commented lines below not needed. + // state.next_index = opts.table_index; + state.lenbits = opts.bits; + // state.lencode = state.next; + + if (ret) { + strm.msg = 'invalid literal/lengths set'; + state.mode = BAD$1; + break; + } + + state.distbits = 6; + //state.distcode.copy(state.codes); + // Switch to use dynamic table + state.distcode = state.distdyn; + opts = { bits: state.distbits }; + ret = inflate_table(DISTS$1, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts); + // We have separate tables & no pointers. 2 commented lines below not needed. + // state.next_index = opts.table_index; + state.distbits = opts.bits; + // state.distcode = state.next; + + if (ret) { + strm.msg = 'invalid distances set'; + state.mode = BAD$1; + break; + } + //Tracev((stderr, 'inflate: codes ok\n')); + state.mode = LEN_; + if (flush === Z_TREES) { break inf_leave; } + /* falls through */ + case LEN_: + state.mode = LEN; + /* falls through */ + case LEN: + if (have >= 6 && left >= 258) { + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + inflate_fast(strm, _out); + //--- LOAD() --- + put = strm.next_out; + output = strm.output; + left = strm.avail_out; + next = strm.next_in; + input = strm.input; + have = strm.avail_in; + hold = state.hold; + bits = state.bits; + //--- + + if (state.mode === TYPE$1) { + state.back = -1; + } + break; + } + state.back = 0; + for (;;) { + here = state.lencode[hold & ((1 << state.lenbits) - 1)]; /*BITS(state.lenbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if (here_bits <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if (here_op && (here_op & 0xf0) === 0) { + last_bits = here_bits; + last_op = here_op; + last_val = here_val; + for (;;) { + here = state.lencode[last_val + + ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((last_bits + here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + //--- DROPBITS(last.bits) ---// + hold >>>= last_bits; + bits -= last_bits; + //---// + state.back += last_bits; + } + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.back += here_bits; + state.length = here_val; + if (here_op === 0) { + //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + // "inflate: literal '%c'\n" : + // "inflate: literal 0x%02x\n", here.val)); + state.mode = LIT; + break; + } + if (here_op & 32) { + //Tracevv((stderr, "inflate: end of block\n")); + state.back = -1; + state.mode = TYPE$1; + break; + } + if (here_op & 64) { + strm.msg = 'invalid literal/length code'; + state.mode = BAD$1; + break; + } + state.extra = here_op & 15; + state.mode = LENEXT; + /* falls through */ + case LENEXT: + if (state.extra) { + //=== NEEDBITS(state.extra); + n = state.extra; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.length += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; + //--- DROPBITS(state.extra) ---// + hold >>>= state.extra; + bits -= state.extra; + //---// + state.back += state.extra; + } + //Tracevv((stderr, "inflate: length %u\n", state.length)); + state.was = state.length; + state.mode = DIST; + /* falls through */ + case DIST: + for (;;) { + here = state.distcode[hold & ((1 << state.distbits) - 1)];/*BITS(state.distbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if ((here_op & 0xf0) === 0) { + last_bits = here_bits; + last_op = here_op; + last_val = here_val; + for (;;) { + here = state.distcode[last_val + + ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((last_bits + here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + //--- DROPBITS(last.bits) ---// + hold >>>= last_bits; + bits -= last_bits; + //---// + state.back += last_bits; + } + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.back += here_bits; + if (here_op & 64) { + strm.msg = 'invalid distance code'; + state.mode = BAD$1; + break; + } + state.offset = here_val; + state.extra = (here_op) & 15; + state.mode = DISTEXT; + /* falls through */ + case DISTEXT: + if (state.extra) { + //=== NEEDBITS(state.extra); + n = state.extra; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.offset += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; + //--- DROPBITS(state.extra) ---// + hold >>>= state.extra; + bits -= state.extra; + //---// + state.back += state.extra; + } + //#ifdef INFLATE_STRICT + if (state.offset > state.dmax) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD$1; + break; + } + //#endif + //Tracevv((stderr, "inflate: distance %u\n", state.offset)); + state.mode = MATCH; + /* falls through */ + case MATCH: + if (left === 0) { break inf_leave; } + copy = _out - left; + if (state.offset > copy) { /* copy from window */ + copy = state.offset - copy; + if (copy > state.whave) { + if (state.sane) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD$1; + break; + } + // (!) This block is disabled in zlib defaults, + // don't enable it for binary compatibility + //#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + // Trace((stderr, "inflate.c too far\n")); + // copy -= state.whave; + // if (copy > state.length) { copy = state.length; } + // if (copy > left) { copy = left; } + // left -= copy; + // state.length -= copy; + // do { + // output[put++] = 0; + // } while (--copy); + // if (state.length === 0) { state.mode = LEN; } + // break; + //#endif + } + if (copy > state.wnext) { + copy -= state.wnext; + from = state.wsize - copy; + } + else { + from = state.wnext - copy; + } + if (copy > state.length) { copy = state.length; } + from_source = state.window; + } + else { /* copy from output */ + from_source = output; + from = put - state.offset; + copy = state.length; + } + if (copy > left) { copy = left; } + left -= copy; + state.length -= copy; + do { + output[put++] = from_source[from++]; + } while (--copy); + if (state.length === 0) { state.mode = LEN; } + break; + case LIT: + if (left === 0) { break inf_leave; } + output[put++] = state.length; + left--; + state.mode = LEN; + break; + case CHECK: + if (state.wrap) { + //=== NEEDBITS(32); + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + // Use '|' instead of '+' to make sure that result is signed + hold |= input[next++] << bits; + bits += 8; + } + //===// + _out -= left; + strm.total_out += _out; + state.total += _out; + if (_out) { + strm.adler = state.check = + /*UPDATE(state.check, put - _out, _out);*/ + (state.flags ? crc32(state.check, output, _out, put - _out) : adler32(state.check, output, _out, put - _out)); + + } + _out = left; + // NB: crc32 stored as signed 32-bit int, zswap32 returns signed too + if ((state.flags ? hold : zswap32(hold)) !== state.check) { + strm.msg = 'incorrect data check'; + state.mode = BAD$1; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + //Tracev((stderr, "inflate: check matches trailer\n")); + } + state.mode = LENGTH; + /* falls through */ + case LENGTH: + if (state.wrap && state.flags) { + //=== NEEDBITS(32); + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (hold !== (state.total & 0xffffffff)) { + strm.msg = 'incorrect length check'; + state.mode = BAD$1; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + //Tracev((stderr, "inflate: length matches trailer\n")); + } + state.mode = DONE; + /* falls through */ + case DONE: + ret = Z_STREAM_END; + break inf_leave; + case BAD$1: + ret = Z_DATA_ERROR; + break inf_leave; + // case MEM: + // return Z_MEM_ERROR; + case SYNC: + /* falls through */ + default: + return Z_STREAM_ERROR; + } + } + + // inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave" + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + + if (state.wsize || (_out !== strm.avail_out && state.mode < BAD$1 && + (state.mode < CHECK || flush !== Z_FINISH))) { + if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) ; + } + _in -= strm.avail_in; + _out -= strm.avail_out; + strm.total_in += _in; + strm.total_out += _out; + state.total += _out; + if (state.wrap && _out) { + strm.adler = state.check = /*UPDATE(state.check, strm.next_out - _out, _out);*/ + (state.flags ? crc32(state.check, output, _out, strm.next_out - _out) : adler32(state.check, output, _out, strm.next_out - _out)); + } + strm.data_type = state.bits + (state.last ? 64 : 0) + + (state.mode === TYPE$1 ? 128 : 0) + + (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0); + if (((_in === 0 && _out === 0) || flush === Z_FINISH) && ret === Z_OK) { + ret = Z_BUF_ERROR; + } + return ret; + } + + function inflateEnd(strm) { + + if (!strm || !strm.state /*|| strm->zfree == (free_func)0*/) { + return Z_STREAM_ERROR; + } + + const state = strm.state; + if (state.window) { + state.window = null; + } + strm.state = null; + return Z_OK; + } + + function inflateGetHeader(strm, head) { + let state; + + /* check state */ + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR; } + + /* save header structure */ + state.head = head; + head.done = false; + return Z_OK; + } + + function inflateSetDictionary(strm, dictionary) { + const dictLength = dictionary.length; + + let state; + let dictid; + + /* check state */ + if (!strm /* == Z_NULL */ || !strm.state /* == Z_NULL */) { return Z_STREAM_ERROR; } + state = strm.state; + + if (state.wrap !== 0 && state.mode !== DICT) { + return Z_STREAM_ERROR; + } + + /* check for correct dictionary identifier */ + if (state.mode === DICT) { + dictid = 1; /* adler32(0, null, 0)*/ + /* dictid = adler32(dictid, dictionary, dictLength); */ + dictid = adler32(dictid, dictionary, dictLength, 0); + if (dictid !== state.check) { + return Z_DATA_ERROR; + } + } + /* copy dictionary to window using updatewindow(), which will amend the + existing dictionary if appropriate */ + updatewindow(strm, dictionary, dictLength, dictLength); + // if (ret) { + // state.mode = MEM; + // return Z_MEM_ERROR; + // } + state.havedict = 1; + // Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; + } + + /* Not implemented + exports.inflateCopy = inflateCopy; + exports.inflateGetDictionary = inflateGetDictionary; + exports.inflateMark = inflateMark; + exports.inflatePrime = inflatePrime; + exports.inflateSync = inflateSync; + exports.inflateSyncPoint = inflateSyncPoint; + exports.inflateUndermine = inflateUndermine; + */ + + // (C) 1995-2013 Jean-loup Gailly and Mark Adler + // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin + // + // This software is provided 'as-is', without any express or implied + // warranty. In no event will the authors be held liable for any damages + // arising from the use of this software. + // + // Permission is granted to anyone to use this software for any purpose, + // including commercial applications, and to alter it and redistribute it + // freely, subject to the following restrictions: + // + // 1. The origin of this software must not be misrepresented; you must not + // claim that you wrote the original software. If you use this software + // in a product, an acknowledgment in the product documentation would be + // appreciated but is not required. + // 2. Altered source versions must be plainly marked as such, and must not be + // misrepresented as being the original software. + // 3. This notice may not be removed or altered from any source distribution. + + class GZheader { + constructor() { + /* true if compressed data believed to be text */ + this.text = 0; + /* modification time */ + this.time = 0; + /* extra flags (not used when writing a gzip file) */ + this.xflags = 0; + /* operating system */ + this.os = 0; + /* pointer to extra field or Z_NULL if none */ + this.extra = null; + /* extra field length (valid if extra != Z_NULL) */ + this.extra_len = 0; // Actually, we don't need it in JS, + // but leave for few code modifications + + // + // Setup limits is not necessary because in js we should not preallocate memory + // for inflate use constant limit in 65536 bytes + // + + /* space at extra (only when reading header) */ + // this.extra_max = 0; + /* pointer to zero-terminated file name or Z_NULL */ + this.name = ''; + /* space at name (only when reading header) */ + // this.name_max = 0; + /* pointer to zero-terminated comment or Z_NULL */ + this.comment = ''; + /* space at comment (only when reading header) */ + // this.comm_max = 0; + /* true if there was or will be a header crc */ + this.hcrc = 0; + /* true when done reading gzip header (not used when writing a gzip file) */ + this.done = false; + } + } + + /** + * class Inflate + * + * Generic JS-style wrapper for zlib calls. If you don't need + * streaming behaviour - use more simple functions: [[inflate]] + * and [[inflateRaw]]. + **/ + + /* internal + * inflate.chunks -> Array + * + * Chunks of output data, if [[Inflate#onData]] not overridden. + **/ + + /** + * Inflate.result -> Uint8Array|Array|String + * + * Uncompressed result, generated by default [[Inflate#onData]] + * and [[Inflate#onEnd]] handlers. Filled after you push last chunk + * (call [[Inflate#push]] with `Z_FINISH` / `true` param) or if you + * push a chunk with explicit flush (call [[Inflate#push]] with + * `Z_SYNC_FLUSH` param). + **/ + + /** + * Inflate.err -> Number + * + * Error code after inflate finished. 0 (Z_OK) on success. + * Should be checked if broken data possible. + **/ + + /** + * Inflate.msg -> String + * + * Error message, if [[Inflate.err]] != 0 + **/ + + + /** + * new Inflate(options) + * - options (Object): zlib inflate options. + * + * Creates new inflator instance with specified params. Throws exception + * on bad params. Supported options: + * + * - `windowBits` + * - `dictionary` + * + * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) + * for more information on these. + * + * Additional options, for internal needs: + * + * - `chunkSize` - size of generated data chunks (16K by default) + * - `raw` (Boolean) - do raw inflate + * - `to` (String) - if equal to 'string', then result will be converted + * from utf8 to utf16 (javascript) string. When string output requested, + * chunk length can differ from `chunkSize`, depending on content. + * + * By default, when no options set, autodetect deflate/gzip data format via + * wrapper header. + * + * ##### Example: + * + * ```javascript + * var pako = void('pako') + * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9]) + * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]); + * + * var inflate = new pako.Inflate({ level: 3}); + * + * inflate.push(chunk1, false); + * inflate.push(chunk2, true); // true -> last chunk + * + * if (inflate.err) { throw new Error(inflate.err); } + * + * console.log(inflate.result); + * ``` + **/ + class Inflate { + constructor(options) { + this.options = { + chunkSize: 16384, + windowBits: 0, + ...(options || {}) + }; + + const opt = this.options; + + // Force window size for `raw` data, if not set directly, + // because we have no header for autodetect. + if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) { + opt.windowBits = -opt.windowBits; + if (opt.windowBits === 0) { opt.windowBits = -15; } + } + + // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate + if ((opt.windowBits >= 0) && (opt.windowBits < 16) && + !(options && options.windowBits)) { + opt.windowBits += 32; + } + + // Gzip header has no info about windows size, we can do autodetect only + // for deflate. So, if window size not set, force it to max when gzip possible + if ((opt.windowBits > 15) && (opt.windowBits < 48)) { + // bit 3 (16) -> gzipped data + // bit 4 (32) -> autodetect gzip/deflate + if ((opt.windowBits & 15) === 0) { + opt.windowBits |= 15; + } + } + + this.err = 0; // error code, if happens (0 = Z_OK) + this.msg = ''; // error message + this.ended = false; // used to avoid multiple onEnd() calls + this.chunks = []; // chunks of compressed data + + this.strm = new ZStream(); + this.strm.avail_out = 0; + + let status = inflateInit2( + this.strm, + opt.windowBits + ); + + if (status !== Z_OK) { + throw new Error(msg[status]); + } + + this.header = new GZheader(); + + inflateGetHeader(this.strm, this.header); + + // Setup dictionary + if (opt.dictionary) { + // Convert data if needed + if (typeof opt.dictionary === 'string') { + opt.dictionary = string2buf(opt.dictionary); + } else if (opt.dictionary instanceof ArrayBuffer) { + opt.dictionary = new Uint8Array(opt.dictionary); + } + if (opt.raw) { //In raw mode we need to set the dictionary early + status = inflateSetDictionary(this.strm, opt.dictionary); + if (status !== Z_OK) { + throw new Error(msg[status]); + } + } + } + } + /** + * Inflate#push(data[, mode]) -> Boolean + * - data (Uint8Array|Array|ArrayBuffer|String): input data + * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. + * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH. + * + * Sends input data to inflate pipe, generating [[Inflate#onData]] calls with + * new output chunks. Returns `true` on success. The last data block must have + * mode Z_FINISH (or `true`). That will flush internal pending buffers and call + * [[Inflate#onEnd]]. For interim explicit flushes (without ending the stream) you + * can use mode Z_SYNC_FLUSH, keeping the decompression context. + * + * On fail call [[Inflate#onEnd]] with error code and return false. + * + * We strongly recommend to use `Uint8Array` on input for best speed (output + * format is detected automatically). Also, don't skip last param and always + * use the same type in your code (boolean or number). That will improve JS speed. + * + * For regular `Array`-s make sure all elements are [0..255]. + * + * ##### Example + * + * ```javascript + * push(chunk, false); // push one of data chunks + * ... + * push(chunk, true); // push last chunk + * ``` + **/ + push(data, mode) { + const { strm, options: { chunkSize, dictionary } } = this; + let status, _mode; + + // Flag to properly process Z_BUF_ERROR on testing inflate call + // when we check that all output data was flushed. + let allowBufError = false; + + if (this.ended) { return false; } + _mode = (mode === ~~mode) ? mode : ((mode === true) ? Z_FINISH : Z_NO_FLUSH); + + // Convert data if needed + if (typeof data === 'string') { + // Only binary strings can be decompressed on practice + strm.input = binstring2buf(data); + } else if (data instanceof ArrayBuffer) { + strm.input = new Uint8Array(data); + } else { + strm.input = data; + } + + strm.next_in = 0; + strm.avail_in = strm.input.length; + + do { + if (strm.avail_out === 0) { + strm.output = new Buf8(chunkSize); + strm.next_out = 0; + strm.avail_out = chunkSize; + } + + status = inflate(strm, Z_NO_FLUSH); /* no bad return value */ + + if (status === Z_NEED_DICT && dictionary) { + status = inflateSetDictionary(this.strm, dictionary); + } + + if (status === Z_BUF_ERROR && allowBufError === true) { + status = Z_OK; + allowBufError = false; + } + + if (status !== Z_STREAM_END && status !== Z_OK) { + this.onEnd(status); + this.ended = true; + return false; + } + + if (strm.next_out) { + if (strm.avail_out === 0 || status === Z_STREAM_END || (strm.avail_in === 0 && (_mode === Z_FINISH || _mode === Z_SYNC_FLUSH))) { + this.onData(shrinkBuf(strm.output, strm.next_out)); + } + } + + // When no more input data, we should check that internal inflate buffers + // are flushed. The only way to do it when avail_out = 0 - run one more + // inflate pass. But if output data not exists, inflate return Z_BUF_ERROR. + // Here we set flag to process this error properly. + // + // NOTE. Deflate does not return error in this case and does not needs such + // logic. + if (strm.avail_in === 0 && strm.avail_out === 0) { + allowBufError = true; + } + + } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== Z_STREAM_END); + + if (status === Z_STREAM_END) { + _mode = Z_FINISH; + } + + // Finalize on the last chunk. + if (_mode === Z_FINISH) { + status = inflateEnd(this.strm); + this.onEnd(status); + this.ended = true; + return status === Z_OK; + } + + // callback interim results if Z_SYNC_FLUSH. + if (_mode === Z_SYNC_FLUSH) { + this.onEnd(Z_OK); + strm.avail_out = 0; + return true; + } + + return true; + }; + + /** + * Inflate#onData(chunk) -> Void + * - chunk (Uint8Array|Array|String): output data. Type of array depends + * on js engine support. When string output requested, each chunk + * will be string. + * + * By default, stores data blocks in `chunks[]` property and glue + * those in `onEnd`. Override this handler, if you need another behaviour. + **/ + onData(chunk) { + this.chunks.push(chunk); + }; + + + + /** + * Inflate#onEnd(status) -> Void + * - status (Number): inflate status. 0 (Z_OK) on success, + * other if not. + * + * Called either after you tell inflate that the input stream is + * complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH) + * or if an error happened. By default - join collected chunks, + * free memory and fill `results` / `err` properties. + **/ + onEnd(status) { + // On success - join + if (status === Z_OK) { + this.result = flattenChunks(this.chunks); + } + this.chunks = []; + this.err = status; + this.msg = this.strm.msg; + }; + } + + /* + node-bzip - a pure-javascript Node.JS module for decoding bzip2 data + + Copyright (C) 2012 Eli Skeggs + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see + http://www.gnu.org/licenses/lgpl-2.1.html + + Adapted from bzip2.js, copyright 2011 antimatter15 (antimatter15@gmail.com). + + Based on micro-bunzip by Rob Landley (rob@landley.net). + + Based on bzip2 decompression code by Julian R Seward (jseward@acm.org), + which also acknowledges contributions by Mike Burrows, David Wheeler, + Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten, + Robert Sedgewick, and Jon L. Bentley. + */ + + var BITMASK = [0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF]; + + // offset in bytes + var BitReader = function(stream) { + this.stream = stream; + this.bitOffset = 0; + this.curByte = 0; + this.hasByte = false; + }; + + BitReader.prototype._ensureByte = function() { + if (!this.hasByte) { + this.curByte = this.stream.readByte(); + this.hasByte = true; + } + }; + + // reads bits from the buffer + BitReader.prototype.read = function(bits) { + var result = 0; + while (bits > 0) { + this._ensureByte(); + var remaining = 8 - this.bitOffset; + // if we're in a byte + if (bits >= remaining) { + result <<= remaining; + result |= BITMASK[remaining] & this.curByte; + this.hasByte = false; + this.bitOffset = 0; + bits -= remaining; + } else { + result <<= bits; + var shift = remaining - bits; + result |= (this.curByte & (BITMASK[bits] << shift)) >> shift; + this.bitOffset += bits; + bits = 0; + } + } + return result; + }; + + // seek to an arbitrary point in the buffer (expressed in bits) + BitReader.prototype.seek = function(pos) { + var n_bit = pos % 8; + var n_byte = (pos - n_bit) / 8; + this.bitOffset = n_bit; + this.stream.seek(n_byte); + this.hasByte = false; + }; + + // reads 6 bytes worth of data using the read method + BitReader.prototype.pi = function() { + var buf = new Uint8Array(6), i; + for (i = 0; i < buf.length; i++) { + buf[i] = this.read(8); + } + return bufToHex(buf); + }; + + function bufToHex(buf) { + return Array.prototype.map.call(buf, x => ('00' + x.toString(16)).slice(-2)).join(''); + } + + var bitreader = BitReader; + + /* very simple input/output stream interface */ + var Stream = function() { + }; + + // input streams ////////////// + /** Returns the next byte, or -1 for EOF. */ + Stream.prototype.readByte = function() { + throw new Error("abstract method readByte() not implemented"); + }; + /** Attempts to fill the buffer; returns number of bytes read, or + * -1 for EOF. */ + Stream.prototype.read = function(buffer, bufOffset, length) { + var bytesRead = 0; + while (bytesRead < length) { + var c = this.readByte(); + if (c < 0) { // EOF + return (bytesRead===0) ? -1 : bytesRead; + } + buffer[bufOffset++] = c; + bytesRead++; + } + return bytesRead; + }; + Stream.prototype.seek = function(new_pos) { + throw new Error("abstract method seek() not implemented"); + }; + + // output streams /////////// + Stream.prototype.writeByte = function(_byte) { + throw new Error("abstract method readByte() not implemented"); + }; + Stream.prototype.write = function(buffer, bufOffset, length) { + var i; + for (i=0; i>> 0; // return an unsigned value + }; + + /** + * Update the CRC with a single byte + * @param value The value to update the CRC with + */ + this.updateCRC = function(value) { + crc = (crc << 8) ^ crc32Lookup[((crc >>> 24) ^ value) & 0xff]; + }; + + /** + * Update the CRC with a sequence of identical bytes + * @param value The value to update the CRC with + * @param count The number of bytes + */ + this.updateCRCRun = function(value, count) { + while (count-- > 0) { + crc = (crc << 8) ^ crc32Lookup[((crc >>> 24) ^ value) & 0xff]; + } + }; + }; + return CRC32; + })(); + + /* + seek-bzip - a pure-javascript module for seeking within bzip2 data + + Copyright (C) 2013 C. Scott Ananian + Copyright (C) 2012 Eli Skeggs + Copyright (C) 2011 Kevin Kwok + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see + http://www.gnu.org/licenses/lgpl-2.1.html + + Adapted from node-bzip, copyright 2012 Eli Skeggs. + Adapted from bzip2.js, copyright 2011 Kevin Kwok (antimatter15@gmail.com). + + Based on micro-bunzip by Rob Landley (rob@landley.net). + + Based on bzip2 decompression code by Julian R Seward (jseward@acm.org), + which also acknowledges contributions by Mike Burrows, David Wheeler, + Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten, + Robert Sedgewick, and Jon L. Bentley. + */ + + + + + + var MAX_HUFCODE_BITS = 20; + var MAX_SYMBOLS = 258; + var SYMBOL_RUNA = 0; + var SYMBOL_RUNB = 1; + var MIN_GROUPS = 2; + var MAX_GROUPS = 6; + var GROUP_SIZE = 50; + + var WHOLEPI = "314159265359"; + var SQRTPI = "177245385090"; + + var mtf = function(array, index) { + var src = array[index], i; + for (i = index; i > 0; i--) { + array[i] = array[i-1]; + } + array[0] = src; + return src; + }; + + var Err = { + OK: 0, + LAST_BLOCK: -1, + NOT_BZIP_DATA: -2, + UNEXPECTED_INPUT_EOF: -3, + UNEXPECTED_OUTPUT_EOF: -4, + DATA_ERROR: -5, + OUT_OF_MEMORY: -6, + OBSOLETE_INPUT: -7, + END_OF_BLOCK: -8 + }; + var ErrorMessages = {}; + ErrorMessages[Err.LAST_BLOCK] = "Bad file checksum"; + ErrorMessages[Err.NOT_BZIP_DATA] = "Not bzip data"; + ErrorMessages[Err.UNEXPECTED_INPUT_EOF] = "Unexpected input EOF"; + ErrorMessages[Err.UNEXPECTED_OUTPUT_EOF] = "Unexpected output EOF"; + ErrorMessages[Err.DATA_ERROR] = "Data error"; + ErrorMessages[Err.OUT_OF_MEMORY] = "Out of memory"; + ErrorMessages[Err.OBSOLETE_INPUT] = "Obsolete (pre 0.9.5) bzip format not supported."; + + var _throw = function(status, optDetail) { + var msg = ErrorMessages[status] || 'unknown error'; + if (optDetail) { msg += ': '+optDetail; } + var e = new TypeError(msg); + e.errorCode = status; + throw e; + }; + + var Bunzip = function(inputStream, outputStream) { + this.writePos = this.writeCurrent = this.writeCount = 0; + + this._start_bunzip(inputStream, outputStream); + }; + Bunzip.prototype._init_block = function() { + var moreBlocks = this._get_next_block(); + if ( !moreBlocks ) { + this.writeCount = -1; + return false; /* no more blocks */ + } + this.blockCRC = new crc32$1(); + return true; + }; + /* XXX micro-bunzip uses (inputStream, inputBuffer, len) as arguments */ + Bunzip.prototype._start_bunzip = function(inputStream, outputStream) { + /* Ensure that file starts with "BZh['1'-'9']." */ + var buf = new Uint8Array(4); + if (inputStream.read(buf, 0, 4) !== 4 || + String.fromCharCode(buf[0], buf[1], buf[2]) !== 'BZh') + _throw(Err.NOT_BZIP_DATA, 'bad magic'); + + var level = buf[3] - 0x30; + if (level < 1 || level > 9) + _throw(Err.NOT_BZIP_DATA, 'level out of range'); + + this.reader = new bitreader(inputStream); + + /* Fourth byte (ascii '1'-'9'), indicates block size in units of 100k of + uncompressed data. Allocate intermediate buffer for block. */ + this.dbufSize = 100000 * level; + this.nextoutput = 0; + this.outputStream = outputStream; + this.streamCRC = 0; + }; + Bunzip.prototype._get_next_block = function() { + var i, j, k; + var reader = this.reader; + // this is get_next_block() function from micro-bunzip: + /* Read in header signature and CRC, then validate signature. + (last block signature means CRC is for whole file, return now) */ + var h = reader.pi(); + if (h === SQRTPI) { // last block + return false; /* no more blocks */ + } + if (h !== WHOLEPI) + _throw(Err.NOT_BZIP_DATA); + this.targetBlockCRC = reader.read(32) >>> 0; // (convert to unsigned) + this.streamCRC = (this.targetBlockCRC ^ + ((this.streamCRC << 1) | (this.streamCRC>>>31))) >>> 0; + /* We can add support for blockRandomised if anybody complains. There was + some code for this in busybox 1.0.0-pre3, but nobody ever noticed that + it didn't actually work. */ + if (reader.read(1)) + _throw(Err.OBSOLETE_INPUT); + var origPointer = reader.read(24); + if (origPointer > this.dbufSize) + _throw(Err.DATA_ERROR, 'initial position out of bounds'); + /* mapping table: if some byte values are never used (encoding things + like ascii text), the compression code removes the gaps to have fewer + symbols to deal with, and writes a sparse bitfield indicating which + values were present. We make a translation table to convert the symbols + back to the corresponding bytes. */ + var t = reader.read(16); + var symToByte = new Uint8Array(256), symTotal = 0; + for (i = 0; i < 16; i++) { + if (t & (1 << (0xF - i))) { + var o = i * 16; + k = reader.read(16); + for (j = 0; j < 16; j++) + if (k & (1 << (0xF - j))) + symToByte[symTotal++] = o + j; + } + } + + /* How many different huffman coding groups does this block use? */ + var groupCount = reader.read(3); + if (groupCount < MIN_GROUPS || groupCount > MAX_GROUPS) + _throw(Err.DATA_ERROR); + /* nSelectors: Every GROUP_SIZE many symbols we select a new huffman coding + group. Read in the group selector list, which is stored as MTF encoded + bit runs. (MTF=Move To Front, as each value is used it's moved to the + start of the list.) */ + var nSelectors = reader.read(15); + if (nSelectors === 0) + _throw(Err.DATA_ERROR); + + var mtfSymbol = new Uint8Array(256); + for (i = 0; i < groupCount; i++) + mtfSymbol[i] = i; + + var selectors = new Uint8Array(nSelectors); // was 32768... + + for (i = 0; i < nSelectors; i++) { + /* Get next value */ + for (j = 0; reader.read(1); j++) + if (j >= groupCount) _throw(Err.DATA_ERROR); + /* Decode MTF to get the next selector */ + selectors[i] = mtf(mtfSymbol, j); + } + + /* Read the huffman coding tables for each group, which code for symTotal + literal symbols, plus two run symbols (RUNA, RUNB) */ + var symCount = symTotal + 2; + var groups = [], hufGroup; + for (j = 0; j < groupCount; j++) { + var length = new Uint8Array(symCount), temp = new Uint16Array(MAX_HUFCODE_BITS + 1); + /* Read huffman code lengths for each symbol. They're stored in + a way similar to mtf; record a starting value for the first symbol, + and an offset from the previous value for everys symbol after that. */ + t = reader.read(5); // lengths + for (i = 0; i < symCount; i++) { + for (;;) { + if (t < 1 || t > MAX_HUFCODE_BITS) _throw(Err.DATA_ERROR); + /* If first bit is 0, stop. Else second bit indicates whether + to increment or decrement the value. */ + if(!reader.read(1)) + break; + if(!reader.read(1)) + t++; + else + t--; + } + length[i] = t; + } + + /* Find largest and smallest lengths in this group */ + var minLen, maxLen; + minLen = maxLen = length[0]; + for (i = 1; i < symCount; i++) { + if (length[i] > maxLen) + maxLen = length[i]; + else if (length[i] < minLen) + minLen = length[i]; + } + + /* Calculate permute[], base[], and limit[] tables from length[]. + * + * permute[] is the lookup table for converting huffman coded symbols + * into decoded symbols. base[] is the amount to subtract from the + * value of a huffman symbol of a given length when using permute[]. + * + * limit[] indicates the largest numerical value a symbol with a given + * number of bits can have. This is how the huffman codes can vary in + * length: each code with a value>limit[length] needs another bit. + */ + hufGroup = {}; + groups.push(hufGroup); + hufGroup.permute = new Uint16Array(MAX_SYMBOLS); + hufGroup.limit = new Uint32Array(MAX_HUFCODE_BITS + 2); + hufGroup.base = new Uint32Array(MAX_HUFCODE_BITS + 1); + hufGroup.minLen = minLen; + hufGroup.maxLen = maxLen; + /* Calculate permute[]. Concurently, initialize temp[] and limit[]. */ + var pp = 0; + for (i = minLen; i <= maxLen; i++) { + temp[i] = hufGroup.limit[i] = 0; + for (t = 0; t < symCount; t++) + if (length[t] === i) + hufGroup.permute[pp++] = t; + } + /* Count symbols coded for at each bit length */ + for (i = 0; i < symCount; i++) + temp[length[i]]++; + /* Calculate limit[] (the largest symbol-coding value at each bit + * length, which is (previous limit<<1)+symbols at this level), and + * base[] (number of symbols to ignore at each bit length, which is + * limit minus the cumulative count of symbols coded for already). */ + pp = t = 0; + for (i = minLen; i < maxLen; i++) { + pp += temp[i]; + /* We read the largest possible symbol size and then unget bits + after determining how many we need, and those extra bits could + be set to anything. (They're noise from future symbols.) At + each level we're really only interested in the first few bits, + so here we set all the trailing to-be-ignored bits to 1 so they + don't affect the value>limit[length] comparison. */ + hufGroup.limit[i] = pp - 1; + pp <<= 1; + t += temp[i]; + hufGroup.base[i + 1] = pp - t; + } + hufGroup.limit[maxLen + 1] = Number.MAX_VALUE; /* Sentinal value for reading next sym. */ + hufGroup.limit[maxLen] = pp + temp[maxLen] - 1; + hufGroup.base[minLen] = 0; + } + /* We've finished reading and digesting the block header. Now read this + block's huffman coded symbols from the file and undo the huffman coding + and run length encoding, saving the result into dbuf[dbufCount++]=uc */ + + /* Initialize symbol occurrence counters and symbol Move To Front table */ + var byteCount = new Uint32Array(256); + for (i = 0; i < 256; i++) + mtfSymbol[i] = i; + /* Loop through compressed symbols. */ + var runPos = 0, dbufCount = 0, selector = 0, uc; + var dbuf = this.dbuf = new Uint32Array(this.dbufSize); + symCount = 0; + for (;;) { + /* Determine which huffman coding group to use. */ + if (!(symCount--)) { + symCount = GROUP_SIZE - 1; + if (selector >= nSelectors) { _throw(Err.DATA_ERROR); } + hufGroup = groups[selectors[selector++]]; + } + /* Read next huffman-coded symbol. */ + i = hufGroup.minLen; + j = reader.read(i); + for (;;i++) { + if (i > hufGroup.maxLen) { _throw(Err.DATA_ERROR); } + if (j <= hufGroup.limit[i]) + break; + j = (j << 1) | reader.read(1); + } + /* Huffman decode value to get nextSym (with bounds checking) */ + j -= hufGroup.base[i]; + if (j < 0 || j >= MAX_SYMBOLS) { _throw(Err.DATA_ERROR); } + var nextSym = hufGroup.permute[j]; + /* We have now decoded the symbol, which indicates either a new literal + byte, or a repeated run of the most recent literal byte. First, + check if nextSym indicates a repeated run, and if so loop collecting + how many times to repeat the last literal. */ + if (nextSym === SYMBOL_RUNA || nextSym === SYMBOL_RUNB) { + /* If this is the start of a new run, zero out counter */ + if (!runPos){ + runPos = 1; + t = 0; + } + /* Neat trick that saves 1 symbol: instead of or-ing 0 or 1 at + each bit position, add 1 or 2 instead. For example, + 1011 is 1<<0 + 1<<1 + 2<<2. 1010 is 2<<0 + 2<<1 + 1<<2. + You can make any bit pattern that way using 1 less symbol than + the basic or 0/1 method (except all bits 0, which would use no + symbols, but a run of length 0 doesn't mean anything in this + context). Thus space is saved. */ + if (nextSym === SYMBOL_RUNA) + t += runPos; + else + t += 2 * runPos; + runPos <<= 1; + continue; + } + /* When we hit the first non-run symbol after a run, we now know + how many times to repeat the last literal, so append that many + copies to our buffer of decoded symbols (dbuf) now. (The last + literal used is the one at the head of the mtfSymbol array.) */ + if (runPos){ + runPos = 0; + if (dbufCount + t > this.dbufSize) { _throw(Err.DATA_ERROR); } + uc = symToByte[mtfSymbol[0]]; + byteCount[uc] += t; + while (t--) + dbuf[dbufCount++] = uc; + } + /* Is this the terminating symbol? */ + if (nextSym > symTotal) + break; + /* At this point, nextSym indicates a new literal character. Subtract + one to get the position in the MTF array at which this literal is + currently to be found. (Note that the result can't be -1 or 0, + because 0 and 1 are RUNA and RUNB. But another instance of the + first symbol in the mtf array, position 0, would have been handled + as part of a run above. Therefore 1 unused mtf position minus + 2 non-literal nextSym values equals -1.) */ + if (dbufCount >= this.dbufSize) { _throw(Err.DATA_ERROR); } + i = nextSym - 1; + uc = mtf(mtfSymbol, i); + uc = symToByte[uc]; + /* We have our literal byte. Save it into dbuf. */ + byteCount[uc]++; + dbuf[dbufCount++] = uc; + } + /* At this point, we've read all the huffman-coded symbols (and repeated + runs) for this block from the input stream, and decoded them into the + intermediate buffer. There are dbufCount many decoded bytes in dbuf[]. + Now undo the Burrows-Wheeler transform on dbuf. + See http://dogma.net/markn/articles/bwt/bwt.htm + */ + if (origPointer < 0 || origPointer >= dbufCount) { _throw(Err.DATA_ERROR); } + /* Turn byteCount into cumulative occurrence counts of 0 to n-1. */ + j = 0; + for (i = 0; i < 256; i++) { + k = j + byteCount[i]; + byteCount[i] = j; + j = k; + } + /* Figure out what order dbuf would be in if we sorted it. */ + for (i = 0; i < dbufCount; i++) { + uc = dbuf[i] & 0xff; + dbuf[byteCount[uc]] |= (i << 8); + byteCount[uc]++; + } + /* Decode first byte by hand to initialize "previous" byte. Note that it + doesn't get output, and if the first three characters are identical + it doesn't qualify as a run (hence writeRunCountdown=5). */ + var pos = 0, current = 0, run = 0; + if (dbufCount) { + pos = dbuf[origPointer]; + current = (pos & 0xff); + pos >>= 8; + run = -1; + } + this.writePos = pos; + this.writeCurrent = current; + this.writeCount = dbufCount; + this.writeRun = run; + + return true; /* more blocks to come */ + }; + /* Undo burrows-wheeler transform on intermediate buffer to produce output. + If start_bunzip was initialized with out_fd=-1, then up to len bytes of + data are written to outbuf. Return value is number of bytes written or + error (all errors are negative numbers). If out_fd!=-1, outbuf and len + are ignored, data is written to out_fd and return is RETVAL_OK or error. + */ + Bunzip.prototype._read_bunzip = function(outputBuffer, len) { + var copies, previous, outbyte; + /* james@jamestaylor.org: writeCount goes to -1 when the buffer is fully + decoded, which results in this returning RETVAL_LAST_BLOCK, also + equal to -1... Confusing, I'm returning 0 here to indicate no + bytes written into the buffer */ + if (this.writeCount < 0) { return 0; } + var dbuf = this.dbuf, pos = this.writePos, current = this.writeCurrent; + var dbufCount = this.writeCount; this.outputsize; + var run = this.writeRun; + + while (dbufCount) { + dbufCount--; + previous = current; + pos = dbuf[pos]; + current = pos & 0xff; + pos >>= 8; + if (run++ === 3){ + copies = current; + outbyte = previous; + current = -1; + } else { + copies = 1; + outbyte = current; + } + this.blockCRC.updateCRCRun(outbyte, copies); + while (copies--) { + this.outputStream.writeByte(outbyte); + this.nextoutput++; + } + if (current != previous) + run = 0; + } + this.writeCount = dbufCount; + // check CRC + if (this.blockCRC.getCRC() !== this.targetBlockCRC) { + _throw(Err.DATA_ERROR, "Bad block CRC "+ + "(got "+this.blockCRC.getCRC().toString(16)+ + " expected "+this.targetBlockCRC.toString(16)+")"); + } + return this.nextoutput; + }; + + var coerceInputStream = function(input) { + if ('readByte' in input) { return input; } + var inputStream = new stream(); + inputStream.pos = 0; + inputStream.readByte = function() { return input[this.pos++]; }; + inputStream.seek = function(pos) { this.pos = pos; }; + inputStream.eof = function() { return this.pos >= input.length; }; + return inputStream; + }; + var coerceOutputStream = function(output) { + var outputStream = new stream(); + var resizeOk = true; + if (output) { + if (typeof(output)==='number') { + outputStream.buffer = new Uint8Array(output); + resizeOk = false; + } else if ('writeByte' in output) { + return output; + } else { + outputStream.buffer = output; + resizeOk = false; + } + } else { + outputStream.buffer = new Uint8Array(16384); + } + outputStream.pos = 0; + outputStream.writeByte = function(_byte) { + if (resizeOk && this.pos >= this.buffer.length) { + var newBuffer = new Uint8Array(this.buffer.length*2); + newBuffer.set(this.buffer); + this.buffer = newBuffer; + } + this.buffer[this.pos++] = _byte; + }; + outputStream.getBuffer = function() { + // trim buffer + if (this.pos !== this.buffer.length) { + if (!resizeOk) + throw new TypeError('outputsize does not match decoded input'); + var newBuffer = new Uint8Array(this.pos); + newBuffer.set(this.buffer.subarray(0, this.pos)); + this.buffer = newBuffer; + } + return this.buffer; + }; + outputStream._coerced = true; + return outputStream; + }; + + /* Static helper functions */ + // 'input' can be a stream or a buffer + // 'output' can be a stream or a buffer or a number (buffer size) + const decode$2 = function(input, output, multistream) { + // make a stream from a buffer, if necessary + var inputStream = coerceInputStream(input); + var outputStream = coerceOutputStream(output); + + var bz = new Bunzip(inputStream, outputStream); + while (true) { + if ('eof' in inputStream && inputStream.eof()) break; + if (bz._init_block()) { + bz._read_bunzip(); + } else { + var targetStreamCRC = bz.reader.read(32) >>> 0; // (convert to unsigned) + if (targetStreamCRC !== bz.streamCRC) { + _throw(Err.DATA_ERROR, "Bad stream CRC "+ + "(got "+bz.streamCRC.toString(16)+ + " expected "+targetStreamCRC.toString(16)+")"); + } + if (multistream && + 'eof' in inputStream && + !inputStream.eof()) { + // note that start_bunzip will also resync the bit reader to next byte + bz._start_bunzip(inputStream, outputStream); + } else break; + } + } + if ('getBuffer' in outputStream) + return outputStream.getBuffer(); + }; + const decodeBlock = function(input, pos, output) { + // make a stream from a buffer, if necessary + var inputStream = coerceInputStream(input); + var outputStream = coerceOutputStream(output); + var bz = new Bunzip(inputStream, outputStream); + bz.reader.seek(pos); + /* Fill the decode buffer for the block */ + var moreBlocks = bz._get_next_block(); + if (moreBlocks) { + /* Init the CRC for writing */ + bz.blockCRC = new crc32$1(); + + /* Zero this so the current byte from before the seek is not written */ + bz.writeCopies = 0; + + /* Decompress the block and write to stdout */ + bz._read_bunzip(); + // XXX keep writing? + } + if ('getBuffer' in outputStream) + return outputStream.getBuffer(); + }; + /* Reads bzip2 file from stream or buffer `input`, and invoke + * `callback(position, size)` once for each bzip2 block, + * where position gives the starting position (in *bits*) + * and size gives uncompressed size of the block (in *bytes*). */ + const table = function(input, callback, multistream) { + // make a stream from a buffer, if necessary + var inputStream = new stream(); + inputStream.delegate = coerceInputStream(input); + inputStream.pos = 0; + inputStream.readByte = function() { + this.pos++; + return this.delegate.readByte(); + }; + if (inputStream.delegate.eof) { + inputStream.eof = inputStream.delegate.eof.bind(inputStream.delegate); + } + var outputStream = new stream(); + outputStream.pos = 0; + outputStream.writeByte = function() { this.pos++; }; + + var bz = new Bunzip(inputStream, outputStream); + var blockSize = bz.dbufSize; + while (true) { + if ('eof' in inputStream && inputStream.eof()) break; + + var position = inputStream.pos*8 + bz.reader.bitOffset; + if (bz.reader.hasByte) { position -= 8; } + + if (bz._init_block()) { + var start = outputStream.pos; + bz._read_bunzip(); + callback(position, outputStream.pos - start); + } else { + bz.reader.read(32); // (but we ignore the crc) + if (multistream && + 'eof' in inputStream && + !inputStream.eof()) { + // note that start_bunzip will also resync the bit reader to next byte + bz._start_bunzip(inputStream, outputStream); + console.assert(bz.dbufSize === blockSize, + "shouldn't change block size within multistream file"); + } else break; + } + } + }; + + var lib = { + Bunzip, + Stream: stream, + Err, + decode: decode$2, + decodeBlock, + table + }; + var lib_4 = lib.decode; + + // GPG4Browsers - An OpenPGP implementation in javascript + + /** + * Implementation of the Literal Data Packet (Tag 11) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.9|RFC4880 5.9}: + * A Literal Data packet contains the body of a message; data that is not to be + * further interpreted. + */ + class LiteralDataPacket { + static get tag() { + return enums.packet.literalData; + } + + /** + * @param {Date} date - The creation date of the literal package + */ + constructor(date = new Date()) { + this.format = enums.literal.utf8; // default format for literal data packets + this.date = util.normalizeDate(date); + this.text = null; // textual data representation + this.data = null; // literal data representation + this.filename = ''; + } + + /** + * Set the packet data to a javascript native string, end of line + * will be normalized to \r\n and by default text is converted to UTF8 + * @param {String | ReadableStream} text - Any native javascript string + * @param {enums.literal} [format] - The format of the string of bytes + */ + setText(text, format = enums.literal.utf8) { + this.format = format; + this.text = text; + this.data = null; + } + + /** + * Returns literal data packets as native JavaScript string + * with normalized end of line to \n + * @param {Boolean} [clone] - Whether to return a clone so that getBytes/getText can be called again + * @returns {String | ReadableStream} Literal data as text. + */ + getText(clone = false) { + if (this.text === null || util.isStream(this.text)) { // Assume that this.text has been read + this.text = util.decodeUTF8(util.nativeEOL(this.getBytes(clone))); + } + return this.text; + } + + /** + * Set the packet data to value represented by the provided string of bytes. + * @param {Uint8Array | ReadableStream} bytes - The string of bytes + * @param {enums.literal} format - The format of the string of bytes + */ + setBytes(bytes, format) { + this.format = format; + this.data = bytes; + this.text = null; + } + + + /** + * Get the byte sequence representing the literal packet data + * @param {Boolean} [clone] - Whether to return a clone so that getBytes/getText can be called again + * @returns {Uint8Array | ReadableStream} A sequence of bytes. + */ + getBytes(clone = false) { + if (this.data === null) { + // encode UTF8 and normalize EOL to \r\n + this.data = util.canonicalizeEOL(util.encodeUTF8(this.text)); + } + if (clone) { + return passiveClone(this.data); + } + return this.data; + } + + + /** + * Sets the filename of the literal packet data + * @param {String} filename - Any native javascript string + */ + setFilename(filename) { + this.filename = filename; + } + + + /** + * Get the filename of the literal packet data + * @returns {String} Filename. + */ + getFilename() { + return this.filename; + } + + /** + * Parsing function for a literal data packet (tag 11). + * + * @param {Uint8Array | ReadableStream} input - Payload of a tag 11 packet + * @returns {Promise} Object representation. + * @async + */ + async read(bytes) { + await parse(bytes, async reader => { + // - A one-octet field that describes how the data is formatted. + const format = await reader.readByte(); // enums.literal + + const filename_len = await reader.readByte(); + this.filename = util.decodeUTF8(await reader.readBytes(filename_len)); + + this.date = util.readDate(await reader.readBytes(4)); + + let data = reader.remainder(); + if (isArrayStream(data)) data = await readToEnd(data); + this.setBytes(data, format); + }); + } + + /** + * Creates a Uint8Array representation of the packet, excluding the data + * + * @returns {Uint8Array} Uint8Array representation of the packet. + */ + writeHeader() { + const filename = util.encodeUTF8(this.filename); + const filename_length = new Uint8Array([filename.length]); + + const format = new Uint8Array([this.format]); + const date = util.writeDate(this.date); + + return util.concatUint8Array([format, filename_length, filename, date]); + } + + /** + * Creates a Uint8Array representation of the packet + * + * @returns {Uint8Array | ReadableStream} Uint8Array representation of the packet. + */ + write() { + const header = this.writeHeader(); + const data = this.getBytes(); + + return util.concat([header, data]); + } + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + function readSimpleLength(bytes) { + let len = 0; + let offset; + const type = bytes[0]; + + + if (type < 192) { + [len] = bytes; + offset = 1; + } else if (type < 255) { + len = ((bytes[0] - 192) << 8) + (bytes[1]) + 192; + offset = 2; + } else if (type === 255) { + len = util.readNumber(bytes.subarray(1, 1 + 4)); + offset = 5; + } + + return { + len: len, + offset: offset + }; + } + + /** + * Encodes a given integer of length to the openpgp length specifier to a + * string + * + * @param {Integer} length - The length to encode + * @returns {Uint8Array} String with openpgp length representation. + */ + function writeSimpleLength(length) { + if (length < 192) { + return new Uint8Array([length]); + } else if (length > 191 && length < 8384) { + /* + * let a = (total data packet length) - 192 let bc = two octet + * representation of a let d = b + 192 + */ + return new Uint8Array([((length - 192) >> 8) + 192, (length - 192) & 0xFF]); + } + return util.concatUint8Array([new Uint8Array([255]), util.writeNumber(length, 4)]); + } + + function writePartialLength(power) { + if (power < 0 || power > 30) { + throw new Error('Partial Length power must be between 1 and 30'); + } + return new Uint8Array([224 + power]); + } + + function writeTag(tag_type) { + /* we're only generating v4 packet headers here */ + return new Uint8Array([0xC0 | tag_type]); + } + + /** + * Writes a packet header version 4 with the given tag_type and length to a + * string + * + * @param {Integer} tag_type - Tag type + * @param {Integer} length - Length of the payload + * @returns {String} String of the header. + */ + function writeHeader(tag_type, length) { + /* we're only generating v4 packet headers here */ + return util.concatUint8Array([writeTag(tag_type), writeSimpleLength(length)]); + } + + /** + * Whether the packet type supports partial lengths per RFC4880 + * @param {Integer} tag - Tag type + * @returns {Boolean} String of the header. + */ + function supportsStreaming(tag) { + return [ + enums.packet.literalData, + enums.packet.compressedData, + enums.packet.symmetricallyEncryptedData, + enums.packet.symEncryptedIntegrityProtectedData, + enums.packet.aeadEncryptedData + ].includes(tag); + } + + /** + * Generic static Packet Parser function + * + * @param {Uint8Array | ReadableStream} input - Input stream as string + * @param {Function} callback - Function to call with the parsed packet + * @returns {Boolean} Returns false if the stream was empty and parsing is done, and true otherwise. + */ + async function readPackets(input, callback) { + const reader = getReader(input); + let writer; + let callbackReturned; + try { + const peekedBytes = await reader.peekBytes(2); + // some sanity checks + if (!peekedBytes || peekedBytes.length < 2 || (peekedBytes[0] & 0x80) === 0) { + throw new Error('Error during parsing. This message / key probably does not conform to a valid OpenPGP format.'); + } + const headerByte = await reader.readByte(); + let tag = -1; + let format = -1; + let packetLength; + + format = 0; // 0 = old format; 1 = new format + if ((headerByte & 0x40) !== 0) { + format = 1; + } + + let packetLengthType; + if (format) { + // new format header + tag = headerByte & 0x3F; // bit 5-0 + } else { + // old format header + tag = (headerByte & 0x3F) >> 2; // bit 5-2 + packetLengthType = headerByte & 0x03; // bit 1-0 + } + + const packetSupportsStreaming = supportsStreaming(tag); + let packet = null; + if (packetSupportsStreaming) { + if (util.isStream(input) === 'array') { + const arrayStream = new ArrayStream(); + writer = getWriter(arrayStream); + packet = arrayStream; + } else { + const transform = new TransformStream(); + writer = getWriter(transform.writable); + packet = transform.readable; + } + callbackReturned = callback({ tag, packet }); + } else { + packet = []; + } + + let wasPartialLength; + do { + if (!format) { + // 4.2.1. Old Format Packet Lengths + switch (packetLengthType) { + case 0: + // The packet has a one-octet length. The header is 2 octets + // long. + packetLength = await reader.readByte(); + break; + case 1: + // The packet has a two-octet length. The header is 3 octets + // long. + packetLength = (await reader.readByte() << 8) | await reader.readByte(); + break; + case 2: + // The packet has a four-octet length. The header is 5 + // octets long. + packetLength = (await reader.readByte() << 24) | (await reader.readByte() << 16) | (await reader.readByte() << + 8) | await reader.readByte(); + break; + default: + // 3 - The packet is of indeterminate length. The header is 1 + // octet long, and the implementation must determine how long + // the packet is. If the packet is in a file, this means that + // the packet extends until the end of the file. In general, + // an implementation SHOULD NOT use indeterminate-length + // packets except where the end of the data will be clear + // from the context, and even then it is better to use a + // definite length, or a new format header. The new format + // headers described below have a mechanism for precisely + // encoding data of indeterminate length. + packetLength = Infinity; + break; + } + } else { // 4.2.2. New Format Packet Lengths + // 4.2.2.1. One-Octet Lengths + const lengthByte = await reader.readByte(); + wasPartialLength = false; + if (lengthByte < 192) { + packetLength = lengthByte; + // 4.2.2.2. Two-Octet Lengths + } else if (lengthByte >= 192 && lengthByte < 224) { + packetLength = ((lengthByte - 192) << 8) + (await reader.readByte()) + 192; + // 4.2.2.4. Partial Body Lengths + } else if (lengthByte > 223 && lengthByte < 255) { + packetLength = 1 << (lengthByte & 0x1F); + wasPartialLength = true; + if (!packetSupportsStreaming) { + throw new TypeError('This packet type does not support partial lengths.'); + } + // 4.2.2.3. Five-Octet Lengths + } else { + packetLength = (await reader.readByte() << 24) | (await reader.readByte() << 16) | (await reader.readByte() << + 8) | await reader.readByte(); + } + } + if (packetLength > 0) { + let bytesRead = 0; + while (true) { + if (writer) await writer.ready; + const { done, value } = await reader.read(); + if (done) { + if (packetLength === Infinity) break; + throw new Error('Unexpected end of packet'); + } + const chunk = packetLength === Infinity ? value : value.subarray(0, packetLength - bytesRead); + if (writer) await writer.write(chunk); + else packet.push(chunk); + bytesRead += value.length; + if (bytesRead >= packetLength) { + reader.unshift(value.subarray(packetLength - bytesRead + value.length)); + break; + } + } + } + } while (wasPartialLength); + + // If this was not a packet that "supports streaming", we peek to check + // whether it is the last packet in the message. We peek 2 bytes instead + // of 1 because the beginning of this function also peeks 2 bytes, and we + // want to cut a `subarray` of the correct length into `web-stream-tools`' + // `externalBuffer` as a tiny optimization here. + // + // If it *was* a streaming packet (i.e. the data packets), we peek at the + // entire remainder of the stream, in order to forward errors in the + // remainder of the stream to the packet data. (Note that this means we + // read/peek at all signature packets before closing the literal data + // packet, for example.) This forwards MDC errors to the literal data + // stream, for example, so that they don't get lost / forgotten on + // decryptedMessage.packets.stream, which we never look at. + // + // An example of what we do when stream-parsing a message containing + // [ one-pass signature packet, literal data packet, signature packet ]: + // 1. Read the one-pass signature packet + // 2. Peek 2 bytes of the literal data packet + // 3. Parse the one-pass signature packet + // + // 4. Read the literal data packet, simultaneously stream-parsing it + // 5. Peek until the end of the message + // 6. Finish parsing the literal data packet + // + // 7. Read the signature packet again (we already peeked at it in step 5) + // 8. Peek at the end of the stream again (`peekBytes` returns undefined) + // 9. Parse the signature packet + // + // Note that this means that if there's an error in the very end of the + // stream, such as an MDC error, we throw in step 5 instead of in step 8 + // (or never), which is the point of this exercise. + const nextPacket = await reader.peekBytes(packetSupportsStreaming ? Infinity : 2); + if (writer) { + await writer.ready; + await writer.close(); + } else { + packet = util.concatUint8Array(packet); + await callback({ tag, packet }); + } + return !nextPacket || !nextPacket.length; + } catch (e) { + if (writer) { + await writer.abort(e); + return true; + } else { + throw e; + } + } finally { + if (writer) { + await callbackReturned; + } + reader.releaseLock(); + } + } + + class UnsupportedError extends Error { + constructor(...params) { + super(...params); + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, UnsupportedError); + } + + this.name = 'UnsupportedError'; + } + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + // Symbol to store cryptographic validity of the signature, to avoid recomputing multiple times on verification. + const verified = Symbol('verified'); + + // GPG puts the Issuer and Signature subpackets in the unhashed area. + // Tampering with those invalidates the signature, so we still trust them and parse them. + // All other unhashed subpackets are ignored. + const allowedUnhashedSubpackets = new Set([ + enums.signatureSubpacket.issuer, + enums.signatureSubpacket.issuerFingerprint, + enums.signatureSubpacket.embeddedSignature + ]); + + /** + * Implementation of the Signature Packet (Tag 2) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.2|RFC4480 5.2}: + * A Signature packet describes a binding between some public key and + * some data. The most common signatures are a signature of a file or a + * block of text, and a signature that is a certification of a User ID. + */ + class SignaturePacket { + static get tag() { + return enums.packet.signature; + } + + constructor() { + this.version = null; + /** @type {enums.signature} */ + this.signatureType = null; + /** @type {enums.hash} */ + this.hashAlgorithm = null; + /** @type {enums.publicKey} */ + this.publicKeyAlgorithm = null; + + this.signatureData = null; + this.unhashedSubpackets = []; + this.signedHashValue = null; + + this.created = null; + this.signatureExpirationTime = null; + this.signatureNeverExpires = true; + this.exportable = null; + this.trustLevel = null; + this.trustAmount = null; + this.regularExpression = null; + this.revocable = null; + this.keyExpirationTime = null; + this.keyNeverExpires = null; + this.preferredSymmetricAlgorithms = null; + this.revocationKeyClass = null; + this.revocationKeyAlgorithm = null; + this.revocationKeyFingerprint = null; + this.issuerKeyID = new KeyID(); + this.rawNotations = []; + this.notations = {}; + this.preferredHashAlgorithms = null; + this.preferredCompressionAlgorithms = null; + this.keyServerPreferences = null; + this.preferredKeyServer = null; + this.isPrimaryUserID = null; + this.policyURI = null; + this.keyFlags = null; + this.signersUserID = null; + this.reasonForRevocationFlag = null; + this.reasonForRevocationString = null; + this.features = null; + this.signatureTargetPublicKeyAlgorithm = null; + this.signatureTargetHashAlgorithm = null; + this.signatureTargetHash = null; + this.embeddedSignature = null; + this.issuerKeyVersion = null; + this.issuerFingerprint = null; + this.preferredAEADAlgorithms = null; + + this.revoked = null; + this[verified] = null; + } + + /** + * parsing function for a signature packet (tag 2). + * @param {String} bytes - Payload of a tag 2 packet + * @returns {SignaturePacket} Object representation. + */ + read(bytes) { + let i = 0; + this.version = bytes[i++]; + + if (this.version !== 4 && this.version !== 5) { + throw new UnsupportedError(`Version ${this.version} of the signature packet is unsupported.`); + } + + this.signatureType = bytes[i++]; + this.publicKeyAlgorithm = bytes[i++]; + this.hashAlgorithm = bytes[i++]; + + // hashed subpackets + i += this.readSubPackets(bytes.subarray(i, bytes.length), true); + if (!this.created) { + throw new Error('Missing signature creation time subpacket.'); + } + + // A V4 signature hashes the packet body + // starting from its first field, the version number, through the end + // of the hashed subpacket data. Thus, the fields hashed are the + // signature version, the signature type, the public-key algorithm, the + // hash algorithm, the hashed subpacket length, and the hashed + // subpacket body. + this.signatureData = bytes.subarray(0, i); + + // unhashed subpackets + i += this.readSubPackets(bytes.subarray(i, bytes.length), false); + + // Two-octet field holding left 16 bits of signed hash value. + this.signedHashValue = bytes.subarray(i, i + 2); + i += 2; + + this.params = mod.signature.parseSignatureParams(this.publicKeyAlgorithm, bytes.subarray(i, bytes.length)); + } + + /** + * @returns {Uint8Array | ReadableStream} + */ + writeParams() { + if (this.params instanceof Promise) { + return fromAsync( + async () => mod.serializeParams(this.publicKeyAlgorithm, await this.params) + ); + } + return mod.serializeParams(this.publicKeyAlgorithm, this.params); + } + + write() { + const arr = []; + arr.push(this.signatureData); + arr.push(this.writeUnhashedSubPackets()); + arr.push(this.signedHashValue); + arr.push(this.writeParams()); + return util.concat(arr); + } + + /** + * Signs provided data. This needs to be done prior to serialization. + * @param {SecretKeyPacket} key - Private key used to sign the message. + * @param {Object} data - Contains packets to be signed. + * @param {Date} [date] - The signature creation time. + * @param {Boolean} [detached] - Whether to create a detached signature + * @throws {Error} if signing failed + * @async + */ + async sign(key, data, date = new Date(), detached = false) { + if (key.version === 5) { + this.version = 5; + } else { + this.version = 4; + } + const arr = [new Uint8Array([this.version, this.signatureType, this.publicKeyAlgorithm, this.hashAlgorithm])]; + + this.created = util.normalizeDate(date); + this.issuerKeyVersion = key.version; + this.issuerFingerprint = key.getFingerprintBytes(); + this.issuerKeyID = key.getKeyID(); + + // Add hashed subpackets + arr.push(this.writeHashedSubPackets()); + + this.signatureData = util.concat(arr); + + const toHash = this.toHash(this.signatureType, data, detached); + const hash = await this.hash(this.signatureType, data, toHash, detached); + + this.signedHashValue = slice(clone(hash), 0, 2); + const signed = async () => mod.signature.sign( + this.publicKeyAlgorithm, this.hashAlgorithm, key.publicParams, key.privateParams, toHash, await readToEnd(hash) + ); + if (util.isStream(hash)) { + this.params = signed(); + } else { + this.params = await signed(); + + // Store the fact that this signature is valid, e.g. for when we call `await + // getLatestValidSignature(this.revocationSignatures, key, data)` later. + // Note that this only holds up if the key and data passed to verify are the + // same as the ones passed to sign. + this[verified] = true; + } + } + + /** + * Creates Uint8Array of bytes of all subpacket data except Issuer and Embedded Signature subpackets + * @returns {Uint8Array} Subpacket data. + */ + writeHashedSubPackets() { + const sub = enums.signatureSubpacket; + const arr = []; + let bytes; + if (this.created === null) { + throw new Error('Missing signature creation time'); + } + arr.push(writeSubPacket(sub.signatureCreationTime, util.writeDate(this.created))); + if (this.signatureExpirationTime !== null) { + arr.push(writeSubPacket(sub.signatureExpirationTime, util.writeNumber(this.signatureExpirationTime, 4))); + } + if (this.exportable !== null) { + arr.push(writeSubPacket(sub.exportableCertification, new Uint8Array([this.exportable ? 1 : 0]))); + } + if (this.trustLevel !== null) { + bytes = new Uint8Array([this.trustLevel, this.trustAmount]); + arr.push(writeSubPacket(sub.trustSignature, bytes)); + } + if (this.regularExpression !== null) { + arr.push(writeSubPacket(sub.regularExpression, this.regularExpression)); + } + if (this.revocable !== null) { + arr.push(writeSubPacket(sub.revocable, new Uint8Array([this.revocable ? 1 : 0]))); + } + if (this.keyExpirationTime !== null) { + arr.push(writeSubPacket(sub.keyExpirationTime, util.writeNumber(this.keyExpirationTime, 4))); + } + if (this.preferredSymmetricAlgorithms !== null) { + bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredSymmetricAlgorithms)); + arr.push(writeSubPacket(sub.preferredSymmetricAlgorithms, bytes)); + } + if (this.revocationKeyClass !== null) { + bytes = new Uint8Array([this.revocationKeyClass, this.revocationKeyAlgorithm]); + bytes = util.concat([bytes, this.revocationKeyFingerprint]); + arr.push(writeSubPacket(sub.revocationKey, bytes)); + } + this.rawNotations.forEach(([{ name, value, humanReadable }]) => { + bytes = [new Uint8Array([humanReadable ? 0x80 : 0, 0, 0, 0])]; + // 2 octets of name length + bytes.push(util.writeNumber(name.length, 2)); + // 2 octets of value length + bytes.push(util.writeNumber(value.length, 2)); + bytes.push(util.stringToUint8Array(name)); + bytes.push(value); + bytes = util.concat(bytes); + arr.push(writeSubPacket(sub.notationData, bytes)); + }); + if (this.preferredHashAlgorithms !== null) { + bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredHashAlgorithms)); + arr.push(writeSubPacket(sub.preferredHashAlgorithms, bytes)); + } + if (this.preferredCompressionAlgorithms !== null) { + bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredCompressionAlgorithms)); + arr.push(writeSubPacket(sub.preferredCompressionAlgorithms, bytes)); + } + if (this.keyServerPreferences !== null) { + bytes = util.stringToUint8Array(util.uint8ArrayToString(this.keyServerPreferences)); + arr.push(writeSubPacket(sub.keyServerPreferences, bytes)); + } + if (this.preferredKeyServer !== null) { + arr.push(writeSubPacket(sub.preferredKeyServer, util.stringToUint8Array(this.preferredKeyServer))); + } + if (this.isPrimaryUserID !== null) { + arr.push(writeSubPacket(sub.primaryUserID, new Uint8Array([this.isPrimaryUserID ? 1 : 0]))); + } + if (this.policyURI !== null) { + arr.push(writeSubPacket(sub.policyURI, util.stringToUint8Array(this.policyURI))); + } + if (this.keyFlags !== null) { + bytes = util.stringToUint8Array(util.uint8ArrayToString(this.keyFlags)); + arr.push(writeSubPacket(sub.keyFlags, bytes)); + } + if (this.signersUserID !== null) { + arr.push(writeSubPacket(sub.signersUserID, util.stringToUint8Array(this.signersUserID))); + } + if (this.reasonForRevocationFlag !== null) { + bytes = util.stringToUint8Array(String.fromCharCode(this.reasonForRevocationFlag) + this.reasonForRevocationString); + arr.push(writeSubPacket(sub.reasonForRevocation, bytes)); + } + if (this.features !== null) { + bytes = util.stringToUint8Array(util.uint8ArrayToString(this.features)); + arr.push(writeSubPacket(sub.features, bytes)); + } + if (this.signatureTargetPublicKeyAlgorithm !== null) { + bytes = [new Uint8Array([this.signatureTargetPublicKeyAlgorithm, this.signatureTargetHashAlgorithm])]; + bytes.push(util.stringToUint8Array(this.signatureTargetHash)); + bytes = util.concat(bytes); + arr.push(writeSubPacket(sub.signatureTarget, bytes)); + } + if (this.preferredAEADAlgorithms !== null) { + bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredAEADAlgorithms)); + arr.push(writeSubPacket(sub.preferredAEADAlgorithms, bytes)); + } + + const result = util.concat(arr); + const length = util.writeNumber(result.length, 2); + + return util.concat([length, result]); + } + + /** + * Creates Uint8Array of bytes of Issuer and Embedded Signature subpackets + * @returns {Uint8Array} Subpacket data. + */ + writeUnhashedSubPackets() { + const sub = enums.signatureSubpacket; + const arr = []; + let bytes; + if (!this.issuerKeyID.isNull() && this.issuerKeyVersion !== 5) { + // If the version of [the] key is greater than 4, this subpacket + // MUST NOT be included in the signature. + arr.push(writeSubPacket(sub.issuer, this.issuerKeyID.write())); + } + if (this.embeddedSignature !== null) { + arr.push(writeSubPacket(sub.embeddedSignature, this.embeddedSignature.write())); + } + if (this.issuerFingerprint !== null) { + bytes = [new Uint8Array([this.issuerKeyVersion]), this.issuerFingerprint]; + bytes = util.concat(bytes); + arr.push(writeSubPacket(sub.issuerFingerprint, bytes)); + } + this.unhashedSubpackets.forEach(data => { + arr.push(writeSimpleLength(data.length)); + arr.push(data); + }); + + const result = util.concat(arr); + const length = util.writeNumber(result.length, 2); + + return util.concat([length, result]); + } + + // V4 signature sub packets + readSubPacket(bytes, hashed = true) { + let mypos = 0; + + // The leftmost bit denotes a "critical" packet + const critical = bytes[mypos] & 0x80; + const type = bytes[mypos] & 0x7F; + + if (!hashed && !allowedUnhashedSubpackets.has(type)) { + this.unhashedSubpackets.push(bytes.subarray(mypos, bytes.length)); + return; + } + + mypos++; + + // subpacket type + switch (type) { + case enums.signatureSubpacket.signatureCreationTime: + // Signature Creation Time + this.created = util.readDate(bytes.subarray(mypos, bytes.length)); + break; + case enums.signatureSubpacket.signatureExpirationTime: { + // Signature Expiration Time in seconds + const seconds = util.readNumber(bytes.subarray(mypos, bytes.length)); + + this.signatureNeverExpires = seconds === 0; + this.signatureExpirationTime = seconds; + + break; + } + case enums.signatureSubpacket.exportableCertification: + // Exportable Certification + this.exportable = bytes[mypos++] === 1; + break; + case enums.signatureSubpacket.trustSignature: + // Trust Signature + this.trustLevel = bytes[mypos++]; + this.trustAmount = bytes[mypos++]; + break; + case enums.signatureSubpacket.regularExpression: + // Regular Expression + this.regularExpression = bytes[mypos]; + break; + case enums.signatureSubpacket.revocable: + // Revocable + this.revocable = bytes[mypos++] === 1; + break; + case enums.signatureSubpacket.keyExpirationTime: { + // Key Expiration Time in seconds + const seconds = util.readNumber(bytes.subarray(mypos, bytes.length)); + + this.keyExpirationTime = seconds; + this.keyNeverExpires = seconds === 0; + + break; + } + case enums.signatureSubpacket.preferredSymmetricAlgorithms: + // Preferred Symmetric Algorithms + this.preferredSymmetricAlgorithms = [...bytes.subarray(mypos, bytes.length)]; + break; + case enums.signatureSubpacket.revocationKey: + // Revocation Key + // (1 octet of class, 1 octet of public-key algorithm ID, 20 + // octets of + // fingerprint) + this.revocationKeyClass = bytes[mypos++]; + this.revocationKeyAlgorithm = bytes[mypos++]; + this.revocationKeyFingerprint = bytes.subarray(mypos, mypos + 20); + break; + + case enums.signatureSubpacket.issuer: + // Issuer + this.issuerKeyID.read(bytes.subarray(mypos, bytes.length)); + break; + + case enums.signatureSubpacket.notationData: { + // Notation Data + const humanReadable = !!(bytes[mypos] & 0x80); + + // We extract key/value tuple from the byte stream. + mypos += 4; + const m = util.readNumber(bytes.subarray(mypos, mypos + 2)); + mypos += 2; + const n = util.readNumber(bytes.subarray(mypos, mypos + 2)); + mypos += 2; + + const name = util.uint8ArrayToString(bytes.subarray(mypos, mypos + m)); + const value = bytes.subarray(mypos + m, mypos + m + n); + + this.rawNotations.push({ name, humanReadable, value, critical }); + + if (humanReadable) { + this.notations[name] = util.uint8ArrayToString(value); + } + break; + } + case enums.signatureSubpacket.preferredHashAlgorithms: + // Preferred Hash Algorithms + this.preferredHashAlgorithms = [...bytes.subarray(mypos, bytes.length)]; + break; + case enums.signatureSubpacket.preferredCompressionAlgorithms: + // Preferred Compression Algorithms + this.preferredCompressionAlgorithms = [...bytes.subarray(mypos, bytes.length)]; + break; + case enums.signatureSubpacket.keyServerPreferences: + // Key Server Preferences + this.keyServerPreferences = [...bytes.subarray(mypos, bytes.length)]; + break; + case enums.signatureSubpacket.preferredKeyServer: + // Preferred Key Server + this.preferredKeyServer = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); + break; + case enums.signatureSubpacket.primaryUserID: + // Primary User ID + this.isPrimaryUserID = bytes[mypos++] !== 0; + break; + case enums.signatureSubpacket.policyURI: + // Policy URI + this.policyURI = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); + break; + case enums.signatureSubpacket.keyFlags: + // Key Flags + this.keyFlags = [...bytes.subarray(mypos, bytes.length)]; + break; + case enums.signatureSubpacket.signersUserID: + // Signer's User ID + this.signersUserID = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); + break; + case enums.signatureSubpacket.reasonForRevocation: + // Reason for Revocation + this.reasonForRevocationFlag = bytes[mypos++]; + this.reasonForRevocationString = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); + break; + case enums.signatureSubpacket.features: + // Features + this.features = [...bytes.subarray(mypos, bytes.length)]; + break; + case enums.signatureSubpacket.signatureTarget: { + // Signature Target + // (1 octet public-key algorithm, 1 octet hash algorithm, N octets hash) + this.signatureTargetPublicKeyAlgorithm = bytes[mypos++]; + this.signatureTargetHashAlgorithm = bytes[mypos++]; + + const len = mod.getHashByteLength(this.signatureTargetHashAlgorithm); + + this.signatureTargetHash = util.uint8ArrayToString(bytes.subarray(mypos, mypos + len)); + break; + } + case enums.signatureSubpacket.embeddedSignature: + // Embedded Signature + this.embeddedSignature = new SignaturePacket(); + this.embeddedSignature.read(bytes.subarray(mypos, bytes.length)); + break; + case enums.signatureSubpacket.issuerFingerprint: + // Issuer Fingerprint + this.issuerKeyVersion = bytes[mypos++]; + this.issuerFingerprint = bytes.subarray(mypos, bytes.length); + if (this.issuerKeyVersion === 5) { + this.issuerKeyID.read(this.issuerFingerprint); + } else { + this.issuerKeyID.read(this.issuerFingerprint.subarray(-8)); + } + break; + case enums.signatureSubpacket.preferredAEADAlgorithms: + // Preferred AEAD Algorithms + this.preferredAEADAlgorithms = [...bytes.subarray(mypos, bytes.length)]; + break; + default: { + const err = new Error(`Unknown signature subpacket type ${type}`); + if (critical) { + throw err; + } else { + util.printDebug(err); + } + } + } + } + + readSubPackets(bytes, trusted = true, config) { + // Two-octet scalar octet count for following subpacket data. + const subpacketLength = util.readNumber(bytes.subarray(0, 2)); + + let i = 2; + + // subpacket data set (zero or more subpackets) + while (i < 2 + subpacketLength) { + const len = readSimpleLength(bytes.subarray(i, bytes.length)); + i += len.offset; + + this.readSubPacket(bytes.subarray(i, i + len.len), trusted, config); + + i += len.len; + } + + return i; + } + + // Produces data to produce signature on + toSign(type, data) { + const t = enums.signature; + + switch (type) { + case t.binary: + if (data.text !== null) { + return util.encodeUTF8(data.getText(true)); + } + return data.getBytes(true); + + case t.text: { + const bytes = data.getBytes(true); + // normalize EOL to \r\n + return util.canonicalizeEOL(bytes); + } + case t.standalone: + return new Uint8Array(0); + + case t.certGeneric: + case t.certPersona: + case t.certCasual: + case t.certPositive: + case t.certRevocation: { + let packet; + let tag; + + if (data.userID) { + tag = 0xB4; + packet = data.userID; + } else if (data.userAttribute) { + tag = 0xD1; + packet = data.userAttribute; + } else { + throw new Error('Either a userID or userAttribute packet needs to be ' + + 'supplied for certification.'); + } + + const bytes = packet.write(); + + return util.concat([this.toSign(t.key, data), + new Uint8Array([tag]), + util.writeNumber(bytes.length, 4), + bytes]); + } + case t.subkeyBinding: + case t.subkeyRevocation: + case t.keyBinding: + return util.concat([this.toSign(t.key, data), this.toSign(t.key, { + key: data.bind + })]); + + case t.key: + if (data.key === undefined) { + throw new Error('Key packet is required for this signature.'); + } + return data.key.writeForHash(this.version); + + case t.keyRevocation: + return this.toSign(t.key, data); + case t.timestamp: + return new Uint8Array(0); + case t.thirdParty: + throw new Error('Not implemented'); + default: + throw new Error('Unknown signature type.'); + } + } + + calculateTrailer(data, detached) { + let length = 0; + return transform(clone(this.signatureData), value => { + length += value.length; + }, () => { + const arr = []; + if (this.version === 5 && (this.signatureType === enums.signature.binary || this.signatureType === enums.signature.text)) { + if (detached) { + arr.push(new Uint8Array(6)); + } else { + arr.push(data.writeHeader()); + } + } + arr.push(new Uint8Array([this.version, 0xFF])); + if (this.version === 5) { + arr.push(new Uint8Array(4)); + } + arr.push(util.writeNumber(length, 4)); + // For v5, this should really be writeNumber(length, 8) rather than the + // hardcoded 4 zero bytes above + return util.concat(arr); + }); + } + + toHash(signatureType, data, detached = false) { + const bytes = this.toSign(signatureType, data); + + return util.concat([bytes, this.signatureData, this.calculateTrailer(data, detached)]); + } + + async hash(signatureType, data, toHash, detached = false) { + if (!toHash) toHash = this.toHash(signatureType, data, detached); + return mod.hash.digest(this.hashAlgorithm, toHash); + } + + /** + * verifies the signature packet. Note: not all signature types are implemented + * @param {PublicSubkeyPacket|PublicKeyPacket| + * SecretSubkeyPacket|SecretKeyPacket} key - the public key to verify the signature + * @param {module:enums.signature} signatureType - Expected signature type + * @param {String|Object} data - Data which on the signature applies + * @param {Date} [date] - Use the given date instead of the current time to check for signature validity and expiration + * @param {Boolean} [detached] - Whether to verify a detached signature + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if signature validation failed + * @async + */ + async verify(key, signatureType, data, date = new Date(), detached = false, config = defaultConfig) { + if (!this.issuerKeyID.equals(key.getKeyID())) { + throw new Error('Signature was not issued by the given public key'); + } + if (this.publicKeyAlgorithm !== key.algorithm) { + throw new Error('Public key algorithm used to sign signature does not match issuer key algorithm.'); + } + + const isMessageSignature = signatureType === enums.signature.binary || signatureType === enums.signature.text; + // Cryptographic validity is cached after one successful verification. + // However, for message signatures, we always re-verify, since the passed `data` can change + const skipVerify = this[verified] && !isMessageSignature; + if (!skipVerify) { + let toHash; + let hash; + if (this.hashed) { + hash = await this.hashed; + } else { + toHash = this.toHash(signatureType, data, detached); + hash = await this.hash(signatureType, data, toHash); + } + hash = await readToEnd(hash); + if (this.signedHashValue[0] !== hash[0] || + this.signedHashValue[1] !== hash[1]) { + throw new Error('Signed digest did not match'); + } + + this.params = await this.params; + + this[verified] = await mod.signature.verify( + this.publicKeyAlgorithm, this.hashAlgorithm, this.params, key.publicParams, + toHash, hash + ); + + if (!this[verified]) { + throw new Error('Signature verification failed'); + } + } + + const normDate = util.normalizeDate(date); + if (normDate && this.created > normDate) { + throw new Error('Signature creation time is in the future'); + } + if (normDate && normDate >= this.getExpirationTime()) { + throw new Error('Signature is expired'); + } + if (config.rejectHashAlgorithms.has(this.hashAlgorithm)) { + throw new Error('Insecure hash algorithm: ' + enums.read(enums.hash, this.hashAlgorithm).toUpperCase()); + } + if (config.rejectMessageHashAlgorithms.has(this.hashAlgorithm) && + [enums.signature.binary, enums.signature.text].includes(this.signatureType)) { + throw new Error('Insecure message hash algorithm: ' + enums.read(enums.hash, this.hashAlgorithm).toUpperCase()); + } + this.rawNotations.forEach(({ name, critical }) => { + if (critical && (config.knownNotations.indexOf(name) < 0)) { + throw new Error(`Unknown critical notation: ${name}`); + } + }); + if (this.revocationKeyClass !== null) { + throw new Error('This key is intended to be revoked with an authorized key, which OpenPGP.js does not support.'); + } + } + + /** + * Verifies signature expiration date + * @param {Date} [date] - Use the given date for verification instead of the current time + * @returns {Boolean} True if expired. + */ + isExpired(date = new Date()) { + const normDate = util.normalizeDate(date); + if (normDate !== null) { + return !(this.created <= normDate && normDate < this.getExpirationTime()); + } + return false; + } + + /** + * Returns the expiration time of the signature or Infinity if signature does not expire + * @returns {Date | Infinity} Expiration time. + */ + getExpirationTime() { + return this.signatureNeverExpires ? Infinity : new Date(this.created.getTime() + this.signatureExpirationTime * 1000); + } + } + + /** + * Creates a string representation of a sub signature packet + * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.1|RFC4880 5.2.3.1} + * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.2|RFC4880 5.2.3.2} + * @param {Integer} type - Subpacket signature type. + * @param {String} data - Data to be included + * @returns {String} A string-representation of a sub signature packet. + * @private + */ + function writeSubPacket(type, data) { + const arr = []; + arr.push(writeSimpleLength(data.length + 1)); + arr.push(new Uint8Array([type])); + arr.push(data); + return util.concat(arr); + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + const VERSION = 3; + + /** + * Implementation of the One-Pass Signature Packets (Tag 4) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.4|RFC4880 5.4}: + * The One-Pass Signature packet precedes the signed data and contains + * enough information to allow the receiver to begin calculating any + * hashes needed to verify the signature. It allows the Signature + * packet to be placed at the end of the message, so that the signer + * can compute the entire signed message in one pass. + */ + class OnePassSignaturePacket { + static get tag() { + return enums.packet.onePassSignature; + } + + constructor() { + /** A one-octet version number. The current version is 3. */ + this.version = null; + /** + * A one-octet signature type. + * Signature types are described in + * {@link https://tools.ietf.org/html/rfc4880#section-5.2.1|RFC4880 Section 5.2.1}. + * @type {enums.signature} + + */ + this.signatureType = null; + /** + * A one-octet number describing the hash algorithm used. + * @see {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC4880 9.4} + * @type {enums.hash} + */ + this.hashAlgorithm = null; + /** + * A one-octet number describing the public-key algorithm used. + * @see {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC4880 9.1} + * @type {enums.publicKey} + */ + this.publicKeyAlgorithm = null; + /** An eight-octet number holding the Key ID of the signing key. */ + this.issuerKeyID = null; + /** + * A one-octet number holding a flag showing whether the signature is nested. + * A zero value indicates that the next packet is another One-Pass Signature packet + * that describes another signature to be applied to the same message data. + */ + this.flags = null; + } + + /** + * parsing function for a one-pass signature packet (tag 4). + * @param {Uint8Array} bytes - Payload of a tag 4 packet + * @returns {OnePassSignaturePacket} Object representation. + */ + read(bytes) { + let mypos = 0; + // A one-octet version number. The current version is 3. + this.version = bytes[mypos++]; + if (this.version !== VERSION) { + throw new UnsupportedError(`Version ${this.version} of the one-pass signature packet is unsupported.`); + } + + // A one-octet signature type. Signature types are described in + // Section 5.2.1. + this.signatureType = bytes[mypos++]; + + // A one-octet number describing the hash algorithm used. + this.hashAlgorithm = bytes[mypos++]; + + // A one-octet number describing the public-key algorithm used. + this.publicKeyAlgorithm = bytes[mypos++]; + + // An eight-octet number holding the Key ID of the signing key. + this.issuerKeyID = new KeyID(); + this.issuerKeyID.read(bytes.subarray(mypos, mypos + 8)); + mypos += 8; + + // A one-octet number holding a flag showing whether the signature + // is nested. A zero value indicates that the next packet is + // another One-Pass Signature packet that describes another + // signature to be applied to the same message data. + this.flags = bytes[mypos++]; + return this; + } + + /** + * creates a string representation of a one-pass signature packet + * @returns {Uint8Array} A Uint8Array representation of a one-pass signature packet. + */ + write() { + const start = new Uint8Array([VERSION, this.signatureType, this.hashAlgorithm, this.publicKeyAlgorithm]); + + const end = new Uint8Array([this.flags]); + + return util.concatUint8Array([start, this.issuerKeyID.write(), end]); + } + + calculateTrailer(...args) { + return fromAsync(async () => SignaturePacket.prototype.calculateTrailer.apply(await this.correspondingSig, args)); + } + + async verify() { + const correspondingSig = await this.correspondingSig; + if (!correspondingSig || correspondingSig.constructor.tag !== enums.packet.signature) { + throw new Error('Corresponding signature packet missing'); + } + if ( + correspondingSig.signatureType !== this.signatureType || + correspondingSig.hashAlgorithm !== this.hashAlgorithm || + correspondingSig.publicKeyAlgorithm !== this.publicKeyAlgorithm || + !correspondingSig.issuerKeyID.equals(this.issuerKeyID) + ) { + throw new Error('Corresponding signature packet does not match one-pass signature packet'); + } + correspondingSig.hashed = this.hashed; + return correspondingSig.verify.apply(correspondingSig, arguments); + } + } + + OnePassSignaturePacket.prototype.hash = SignaturePacket.prototype.hash; + OnePassSignaturePacket.prototype.toHash = SignaturePacket.prototype.toHash; + OnePassSignaturePacket.prototype.toSign = SignaturePacket.prototype.toSign; + + /** + * Instantiate a new packet given its tag + * @function newPacketFromTag + * @param {module:enums.packet} tag - Property value from {@link module:enums.packet} + * @param {Object} allowedPackets - mapping where keys are allowed packet tags, pointing to their Packet class + * @returns {Object} New packet object with type based on tag + * @throws {Error|UnsupportedError} for disallowed or unknown packets + */ + function newPacketFromTag(tag, allowedPackets) { + if (!allowedPackets[tag]) { + // distinguish between disallowed packets and unknown ones + let packetType; + try { + packetType = enums.read(enums.packet, tag); + } catch (e) { + throw new UnsupportedError(`Unknown packet type with tag: ${tag}`); + } + throw new Error(`Packet not allowed in this context: ${packetType}`); + } + return new allowedPackets[tag](); + } + + /** + * This class represents a list of openpgp packets. + * Take care when iterating over it - the packets themselves + * are stored as numerical indices. + * @extends Array + */ + class PacketList extends Array { + /** + * Parses the given binary data and returns a list of packets. + * Equivalent to calling `read` on an empty PacketList instance. + * @param {Uint8Array | ReadableStream} bytes - binary data to parse + * @param {Object} allowedPackets - mapping where keys are allowed packet tags, pointing to their Packet class + * @param {Object} [config] - full configuration, defaults to openpgp.config + * @returns {PacketList} parsed list of packets + * @throws on parsing errors + * @async + */ + static async fromBinary(bytes, allowedPackets, config = defaultConfig) { + const packets = new PacketList(); + await packets.read(bytes, allowedPackets, config); + return packets; + } + + /** + * Reads a stream of binary data and interprets it as a list of packets. + * @param {Uint8Array | ReadableStream} bytes - binary data to parse + * @param {Object} allowedPackets - mapping where keys are allowed packet tags, pointing to their Packet class + * @param {Object} [config] - full configuration, defaults to openpgp.config + * @throws on parsing errors + * @async + */ + async read(bytes, allowedPackets, config = defaultConfig) { + this.stream = transformPair(bytes, async (readable, writable) => { + const writer = getWriter(writable); + try { + while (true) { + await writer.ready; + const done = await readPackets(readable, async parsed => { + try { + if (parsed.tag === enums.packet.marker || parsed.tag === enums.packet.trust) { + // According to the spec, these packet types should be ignored and not cause parsing errors, even if not esplicitly allowed: + // - Marker packets MUST be ignored when received: https://github.com/openpgpjs/openpgpjs/issues/1145 + // - Trust packets SHOULD be ignored outside of keyrings (unsupported): https://datatracker.ietf.org/doc/html/rfc4880#section-5.10 + return; + } + const packet = newPacketFromTag(parsed.tag, allowedPackets); + packet.packets = new PacketList(); + packet.fromStream = util.isStream(parsed.packet); + await packet.read(parsed.packet, config); + await writer.write(packet); + } catch (e) { + const throwUnsupportedError = !config.ignoreUnsupportedPackets && e instanceof UnsupportedError; + const throwMalformedError = !config.ignoreMalformedPackets && !(e instanceof UnsupportedError); + if (throwUnsupportedError || throwMalformedError || supportsStreaming(parsed.tag)) { + // The packets that support streaming are the ones that contain message data. + // Those are also the ones we want to be more strict about and throw on parse errors + // (since we likely cannot process the message without these packets anyway). + await writer.abort(e); + } + util.printDebugError(e); + } + }); + if (done) { + await writer.ready; + await writer.close(); + return; + } + } + } catch (e) { + await writer.abort(e); + } + }); + + // Wait until first few packets have been read + const reader = getReader(this.stream); + while (true) { + const { done, value } = await reader.read(); + if (!done) { + this.push(value); + } else { + this.stream = null; + } + if (done || supportsStreaming(value.constructor.tag)) { + break; + } + } + reader.releaseLock(); + } + + /** + * Creates a binary representation of openpgp objects contained within the + * class instance. + * @returns {Uint8Array} A Uint8Array containing valid openpgp packets. + */ + write() { + const arr = []; + + for (let i = 0; i < this.length; i++) { + const packetbytes = this[i].write(); + if (util.isStream(packetbytes) && supportsStreaming(this[i].constructor.tag)) { + let buffer = []; + let bufferLength = 0; + const minLength = 512; + arr.push(writeTag(this[i].constructor.tag)); + arr.push(transform(packetbytes, value => { + buffer.push(value); + bufferLength += value.length; + if (bufferLength >= minLength) { + const powerOf2 = Math.min(Math.log(bufferLength) / Math.LN2 | 0, 30); + const chunkSize = 2 ** powerOf2; + const bufferConcat = util.concat([writePartialLength(powerOf2)].concat(buffer)); + buffer = [bufferConcat.subarray(1 + chunkSize)]; + bufferLength = buffer[0].length; + return bufferConcat.subarray(0, 1 + chunkSize); + } + }, () => util.concat([writeSimpleLength(bufferLength)].concat(buffer)))); + } else { + if (util.isStream(packetbytes)) { + let length = 0; + arr.push(transform(clone(packetbytes), value => { + length += value.length; + }, () => writeHeader(this[i].constructor.tag, length))); + } else { + arr.push(writeHeader(this[i].constructor.tag, packetbytes.length)); + } + arr.push(packetbytes); + } + } + + return util.concat(arr); + } + + /** + * Creates a new PacketList with all packets matching the given tag(s) + * @param {...module:enums.packet} tags - packet tags to look for + * @returns {PacketList} + */ + filterByTag(...tags) { + const filtered = new PacketList(); + + const handle = tag => packetType => tag === packetType; + + for (let i = 0; i < this.length; i++) { + if (tags.some(handle(this[i].constructor.tag))) { + filtered.push(this[i]); + } + } + + return filtered; + } + + /** + * Traverses packet list and returns first packet with matching tag + * @param {module:enums.packet} tag - The packet tag + * @returns {Packet|undefined} + */ + findPacket(tag) { + return this.find(packet => packet.constructor.tag === tag); + } + + /** + * Find indices of packets with the given tag(s) + * @param {...module:enums.packet} tags - packet tags to look for + * @returns {Integer[]} packet indices + */ + indexOfTag(...tags) { + const tagIndex = []; + const that = this; + + const handle = tag => packetType => tag === packetType; + + for (let i = 0; i < this.length; i++) { + if (tags.some(handle(that[i].constructor.tag))) { + tagIndex.push(i); + } + } + return tagIndex; + } + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + // A Compressed Data packet can contain the following packet types + const allowedPackets = /*#__PURE__*/ util.constructAllowedPackets([ + LiteralDataPacket, + OnePassSignaturePacket, + SignaturePacket + ]); + + /** + * Implementation of the Compressed Data Packet (Tag 8) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.6|RFC4880 5.6}: + * The Compressed Data packet contains compressed data. Typically, + * this packet is found as the contents of an encrypted packet, or following + * a Signature or One-Pass Signature packet, and contains a literal data packet. + */ + class CompressedDataPacket { + static get tag() { + return enums.packet.compressedData; + } + + /** + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + constructor(config = defaultConfig) { + /** + * List of packets + * @type {PacketList} + */ + this.packets = null; + /** + * Compression algorithm + * @type {enums.compression} + */ + this.algorithm = config.preferredCompressionAlgorithm; + + /** + * Compressed packet data + * @type {Uint8Array | ReadableStream} + */ + this.compressed = null; + + /** + * zip/zlib compression level, between 1 and 9 + */ + this.deflateLevel = config.deflateLevel; + } + + /** + * Parsing function for the packet. + * @param {Uint8Array | ReadableStream} bytes - Payload of a tag 8 packet + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + async read(bytes, config = defaultConfig) { + await parse(bytes, async reader => { + + // One octet that gives the algorithm used to compress the packet. + this.algorithm = await reader.readByte(); + + // Compressed data, which makes up the remainder of the packet. + this.compressed = reader.remainder(); + + await this.decompress(config); + }); + } + + + /** + * Return the compressed packet. + * @returns {Uint8Array | ReadableStream} Binary compressed packet. + */ + write() { + if (this.compressed === null) { + this.compress(); + } + + return util.concat([new Uint8Array([this.algorithm]), this.compressed]); + } + + + /** + * Decompression method for decompressing the compressed data + * read by read_packet + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + async decompress(config = defaultConfig) { + const compressionName = enums.read(enums.compression, this.algorithm); + const decompressionFn = decompress_fns[compressionName]; + if (!decompressionFn) { + throw new Error(`${compressionName} decompression not supported`); + } + + this.packets = await PacketList.fromBinary(decompressionFn(this.compressed), allowedPackets, config); + } + + /** + * Compress the packet data (member decompressedData) + */ + compress() { + const compressionName = enums.read(enums.compression, this.algorithm); + const compressionFn = compress_fns[compressionName]; + if (!compressionFn) { + throw new Error(`${compressionName} compression not supported`); + } + + this.compressed = compressionFn(this.packets.write(), this.deflateLevel); + } + } + + ////////////////////////// + // // + // Helper functions // + // // + ////////////////////////// + + + const nodeZlib = util.getNodeZlib(); + + function uncompressed(data) { + return data; + } + + function node_zlib(func, create, options = {}) { + return function (data) { + if (!util.isStream(data) || isArrayStream(data)) { + return fromAsync(() => readToEnd(data).then(data => { + return new Promise((resolve, reject) => { + func(data, options, (err, result) => { + if (err) return reject(err); + resolve(result); + }); + }); + })); + } + return nodeToWeb(webToNode(data).pipe(create(options))); + }; + } + + function pako_zlib(constructor, options = {}) { + return function(data) { + const obj = new constructor(options); + return transform(data, value => { + if (value.length) { + obj.push(value, Z_SYNC_FLUSH); + return obj.result; + } + }, () => { + if (constructor === Deflate) { + obj.push([], Z_FINISH); + return obj.result; + } + }); + }; + } + + function bzip2(func) { + return function(data) { + return fromAsync(async () => func(await readToEnd(data))); + }; + } + + const compress_fns = nodeZlib ? { + zip: /*#__PURE__*/ (compressed, level) => node_zlib(nodeZlib.deflateRaw, nodeZlib.createDeflateRaw, { level })(compressed), + zlib: /*#__PURE__*/ (compressed, level) => node_zlib(nodeZlib.deflate, nodeZlib.createDeflate, { level })(compressed) + } : { + zip: /*#__PURE__*/ (compressed, level) => pako_zlib(Deflate, { raw: true, level })(compressed), + zlib: /*#__PURE__*/ (compressed, level) => pako_zlib(Deflate, { level })(compressed) + }; + + const decompress_fns = nodeZlib ? { + uncompressed: uncompressed, + zip: /*#__PURE__*/ node_zlib(nodeZlib.inflateRaw, nodeZlib.createInflateRaw), + zlib: /*#__PURE__*/ node_zlib(nodeZlib.inflate, nodeZlib.createInflate), + bzip2: /*#__PURE__*/ bzip2(lib_4) + } : { + uncompressed: uncompressed, + zip: /*#__PURE__*/ pako_zlib(Inflate, { raw: true }), + zlib: /*#__PURE__*/ pako_zlib(Inflate), + bzip2: /*#__PURE__*/ bzip2(lib_4) + }; + + // GPG4Browsers - An OpenPGP implementation in javascript + + // A SEIP packet can contain the following packet types + const allowedPackets$1 = /*#__PURE__*/ util.constructAllowedPackets([ + LiteralDataPacket, + CompressedDataPacket, + OnePassSignaturePacket, + SignaturePacket + ]); + + const VERSION$1 = 1; // A one-octet version number of the data packet. + + /** + * Implementation of the Sym. Encrypted Integrity Protected Data Packet (Tag 18) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.13|RFC4880 5.13}: + * The Symmetrically Encrypted Integrity Protected Data packet is + * a variant of the Symmetrically Encrypted Data packet. It is a new feature + * created for OpenPGP that addresses the problem of detecting a modification to + * encrypted data. It is used in combination with a Modification Detection Code + * packet. + */ + class SymEncryptedIntegrityProtectedDataPacket { + static get tag() { + return enums.packet.symEncryptedIntegrityProtectedData; + } + + constructor() { + this.version = VERSION$1; + this.encrypted = null; + this.packets = null; + } + + async read(bytes) { + await parse(bytes, async reader => { + const version = await reader.readByte(); + // - A one-octet version number. The only currently defined value is 1. + if (version !== VERSION$1) { + throw new UnsupportedError(`Version ${version} of the SEIP packet is unsupported.`); + } + + // - Encrypted data, the output of the selected symmetric-key cipher + // operating in Cipher Feedback mode with shift amount equal to the + // block size of the cipher (CFB-n where n is the block size). + this.encrypted = reader.remainder(); + }); + } + + write() { + return util.concat([new Uint8Array([VERSION$1]), this.encrypted]); + } + + /** + * Encrypt the payload in the packet. + * @param {enums.symmetric} sessionKeyAlgorithm - The symmetric encryption algorithm to use + * @param {Uint8Array} key - The key of cipher blocksize length to be used + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} + * @throws {Error} on encryption failure + * @async + */ + async encrypt(sessionKeyAlgorithm, key, config = defaultConfig) { + const { blockSize } = mod.getCipher(sessionKeyAlgorithm); + + let bytes = this.packets.write(); + if (isArrayStream(bytes)) bytes = await readToEnd(bytes); + const prefix = await mod.getPrefixRandom(sessionKeyAlgorithm); + const mdc = new Uint8Array([0xD3, 0x14]); // modification detection code packet + + const tohash = util.concat([prefix, bytes, mdc]); + const hash = await mod.hash.sha1(passiveClone(tohash)); + const plaintext = util.concat([tohash, hash]); + + this.encrypted = await mod.mode.cfb.encrypt(sessionKeyAlgorithm, key, plaintext, new Uint8Array(blockSize), config); + return true; + } + + /** + * Decrypts the encrypted data contained in the packet. + * @param {enums.symmetric} sessionKeyAlgorithm - The selected symmetric encryption algorithm to be used + * @param {Uint8Array} key - The key of cipher blocksize length to be used + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} + * @throws {Error} on decryption failure + * @async + */ + async decrypt(sessionKeyAlgorithm, key, config = defaultConfig) { + const { blockSize } = mod.getCipher(sessionKeyAlgorithm); + let encrypted = clone(this.encrypted); + if (isArrayStream(encrypted)) encrypted = await readToEnd(encrypted); + const decrypted = await mod.mode.cfb.decrypt(sessionKeyAlgorithm, key, encrypted, new Uint8Array(blockSize)); + + // there must be a modification detection code packet as the + // last packet and everything gets hashed except the hash itself + const realHash = slice(passiveClone(decrypted), -20); + const tohash = slice(decrypted, 0, -20); + const verifyHash = Promise.all([ + readToEnd(await mod.hash.sha1(passiveClone(tohash))), + readToEnd(realHash) + ]).then(([hash, mdc]) => { + if (!util.equalsUint8Array(hash, mdc)) { + throw new Error('Modification detected.'); + } + return new Uint8Array(); + }); + const bytes = slice(tohash, blockSize + 2); // Remove random prefix + let packetbytes = slice(bytes, 0, -2); // Remove MDC packet + packetbytes = concat([packetbytes, fromAsync(() => verifyHash)]); + if (!util.isStream(encrypted) || !config.allowUnauthenticatedStream) { + packetbytes = await readToEnd(packetbytes); + } + this.packets = await PacketList.fromBinary(packetbytes, allowedPackets$1, config); + return true; + } + } + + // OpenPGP.js - An OpenPGP implementation in javascript + + // An AEAD-encrypted Data packet can contain the following packet types + const allowedPackets$2 = /*#__PURE__*/ util.constructAllowedPackets([ + LiteralDataPacket, + CompressedDataPacket, + OnePassSignaturePacket, + SignaturePacket + ]); + + const VERSION$2 = 1; // A one-octet version number of the data packet. + + /** + * Implementation of the Symmetrically Encrypted Authenticated Encryption with + * Additional Data (AEAD) Protected Data Packet + * + * {@link https://tools.ietf.org/html/draft-ford-openpgp-format-00#section-2.1}: + * AEAD Protected Data Packet + */ + class AEADEncryptedDataPacket { + static get tag() { + return enums.packet.aeadEncryptedData; + } + + constructor() { + this.version = VERSION$2; + /** @type {enums.symmetric} */ + this.cipherAlgorithm = null; + /** @type {enums.aead} */ + this.aeadAlgorithm = enums.aead.eax; + this.chunkSizeByte = null; + this.iv = null; + this.encrypted = null; + this.packets = null; + } + + /** + * Parse an encrypted payload of bytes in the order: version, IV, ciphertext (see specification) + * @param {Uint8Array | ReadableStream} bytes + * @throws {Error} on parsing failure + */ + async read(bytes) { + await parse(bytes, async reader => { + const version = await reader.readByte(); + if (version !== VERSION$2) { // The only currently defined value is 1. + throw new UnsupportedError(`Version ${version} of the AEAD-encrypted data packet is not supported.`); + } + this.cipherAlgorithm = await reader.readByte(); + this.aeadAlgorithm = await reader.readByte(); + this.chunkSizeByte = await reader.readByte(); + + const mode = mod.getAEADMode(this.aeadAlgorithm); + this.iv = await reader.readBytes(mode.ivLength); + this.encrypted = reader.remainder(); + }); + } + + /** + * Write the encrypted payload of bytes in the order: version, IV, ciphertext (see specification) + * @returns {Uint8Array | ReadableStream} The encrypted payload. + */ + write() { + return util.concat([new Uint8Array([this.version, this.cipherAlgorithm, this.aeadAlgorithm, this.chunkSizeByte]), this.iv, this.encrypted]); + } + + /** + * Decrypt the encrypted payload. + * @param {enums.symmetric} sessionKeyAlgorithm - The session key's cipher algorithm + * @param {Uint8Array} key - The session key used to encrypt the payload + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if decryption was not successful + * @async + */ + async decrypt(sessionKeyAlgorithm, key, config = defaultConfig) { + this.packets = await PacketList.fromBinary( + await this.crypt('decrypt', key, clone(this.encrypted)), + allowedPackets$2, + config + ); + } + + /** + * Encrypt the packet payload. + * @param {enums.symmetric} sessionKeyAlgorithm - The session key's cipher algorithm + * @param {Uint8Array} key - The session key used to encrypt the payload + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if encryption was not successful + * @async + */ + async encrypt(sessionKeyAlgorithm, key, config = defaultConfig) { + this.cipherAlgorithm = sessionKeyAlgorithm; + + const { ivLength } = mod.getAEADMode(this.aeadAlgorithm); + this.iv = await mod.random.getRandomBytes(ivLength); // generate new random IV + this.chunkSizeByte = config.aeadChunkSizeByte; + const data = this.packets.write(); + this.encrypted = await this.crypt('encrypt', key, data); + } + + /** + * En/decrypt the payload. + * @param {encrypt|decrypt} fn - Whether to encrypt or decrypt + * @param {Uint8Array} key - The session key used to en/decrypt the payload + * @param {Uint8Array | ReadableStream} data - The data to en/decrypt + * @returns {Promise>} + * @async + */ + async crypt(fn, key, data) { + const mode = mod.getAEADMode(this.aeadAlgorithm); + const modeInstance = await mode(this.cipherAlgorithm, key); + const tagLengthIfDecrypting = fn === 'decrypt' ? mode.tagLength : 0; + const tagLengthIfEncrypting = fn === 'encrypt' ? mode.tagLength : 0; + const chunkSize = 2 ** (this.chunkSizeByte + 6) + tagLengthIfDecrypting; // ((uint64_t)1 << (c + 6)) + const adataBuffer = new ArrayBuffer(21); + const adataArray = new Uint8Array(adataBuffer, 0, 13); + const adataTagArray = new Uint8Array(adataBuffer); + const adataView = new DataView(adataBuffer); + const chunkIndexArray = new Uint8Array(adataBuffer, 5, 8); + adataArray.set([0xC0 | AEADEncryptedDataPacket.tag, this.version, this.cipherAlgorithm, this.aeadAlgorithm, this.chunkSizeByte], 0); + let chunkIndex = 0; + let latestPromise = Promise.resolve(); + let cryptedBytes = 0; + let queuedBytes = 0; + const iv = this.iv; + return transformPair(data, async (readable, writable) => { + if (util.isStream(readable) !== 'array') { + const buffer = new TransformStream({}, { + highWaterMark: util.getHardwareConcurrency() * 2 ** (this.chunkSizeByte + 6), + size: array => array.length + }); + pipe(buffer.readable, writable); + writable = buffer.writable; + } + const reader = getReader(readable); + const writer = getWriter(writable); + try { + while (true) { + let chunk = await reader.readBytes(chunkSize + tagLengthIfDecrypting) || new Uint8Array(); + const finalChunk = chunk.subarray(chunk.length - tagLengthIfDecrypting); + chunk = chunk.subarray(0, chunk.length - tagLengthIfDecrypting); + let cryptedPromise; + let done; + if (!chunkIndex || chunk.length) { + reader.unshift(finalChunk); + cryptedPromise = modeInstance[fn](chunk, mode.getNonce(iv, chunkIndexArray), adataArray); + queuedBytes += chunk.length - tagLengthIfDecrypting + tagLengthIfEncrypting; + } else { + // After the last chunk, we either encrypt a final, empty + // data chunk to get the final authentication tag or + // validate that final authentication tag. + adataView.setInt32(13 + 4, cryptedBytes); // Should be setInt64(13, ...) + cryptedPromise = modeInstance[fn](finalChunk, mode.getNonce(iv, chunkIndexArray), adataTagArray); + queuedBytes += tagLengthIfEncrypting; + done = true; + } + cryptedBytes += chunk.length - tagLengthIfDecrypting; + // eslint-disable-next-line no-loop-func + latestPromise = latestPromise.then(() => cryptedPromise).then(async crypted => { + await writer.ready; + await writer.write(crypted); + queuedBytes -= crypted.length; + }).catch(err => writer.abort(err)); + if (done || queuedBytes > writer.desiredSize) { + await latestPromise; // Respect backpressure + } + if (!done) { + adataView.setInt32(5 + 4, ++chunkIndex); // Should be setInt64(5, ...) + } else { + await writer.close(); + break; + } + } + } catch (e) { + await writer.abort(e); + } + }); + } + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + const VERSION$3 = 3; + + /** + * Public-Key Encrypted Session Key Packets (Tag 1) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.1|RFC4880 5.1}: + * A Public-Key Encrypted Session Key packet holds the session key + * used to encrypt a message. Zero or more Public-Key Encrypted Session Key + * packets and/or Symmetric-Key Encrypted Session Key packets may precede a + * Symmetrically Encrypted Data Packet, which holds an encrypted message. The + * message is encrypted with the session key, and the session key is itself + * encrypted and stored in the Encrypted Session Key packet(s). The + * Symmetrically Encrypted Data Packet is preceded by one Public-Key Encrypted + * Session Key packet for each OpenPGP key to which the message is encrypted. + * The recipient of the message finds a session key that is encrypted to their + * public key, decrypts the session key, and then uses the session key to + * decrypt the message. + */ + class PublicKeyEncryptedSessionKeyPacket { + static get tag() { + return enums.packet.publicKeyEncryptedSessionKey; + } + + constructor() { + this.version = 3; + + this.publicKeyID = new KeyID(); + this.publicKeyAlgorithm = null; + + this.sessionKey = null; + /** + * Algorithm to encrypt the message with + * @type {enums.symmetric} + */ + this.sessionKeyAlgorithm = null; + + /** @type {Object} */ + this.encrypted = {}; + } + + /** + * Parsing function for a publickey encrypted session key packet (tag 1). + * + * @param {Uint8Array} bytes - Payload of a tag 1 packet + */ + read(bytes) { + this.version = bytes[0]; + if (this.version !== VERSION$3) { + throw new UnsupportedError(`Version ${this.version} of the PKESK packet is unsupported.`); + } + this.publicKeyID.read(bytes.subarray(1, bytes.length)); + this.publicKeyAlgorithm = bytes[9]; + this.encrypted = mod.parseEncSessionKeyParams(this.publicKeyAlgorithm, bytes.subarray(10)); + } + + /** + * Create a binary representation of a tag 1 packet + * + * @returns {Uint8Array} The Uint8Array representation. + */ + write() { + const arr = [ + new Uint8Array([this.version]), + this.publicKeyID.write(), + new Uint8Array([this.publicKeyAlgorithm]), + mod.serializeParams(this.publicKeyAlgorithm, this.encrypted) + ]; + + return util.concatUint8Array(arr); + } + + /** + * Encrypt session key packet + * @param {PublicKeyPacket} key - Public key + * @throws {Error} if encryption failed + * @async + */ + async encrypt(key) { + const data = util.concatUint8Array([ + new Uint8Array([enums.write(enums.symmetric, this.sessionKeyAlgorithm)]), + this.sessionKey, + util.writeChecksum(this.sessionKey) + ]); + const algo = enums.write(enums.publicKey, this.publicKeyAlgorithm); + this.encrypted = await mod.publicKeyEncrypt( + algo, key.publicParams, data, key.getFingerprintBytes()); + } + + /** + * Decrypts the session key (only for public key encrypted session key packets (tag 1) + * @param {SecretKeyPacket} key - decrypted private key + * @param {Object} [randomSessionKey] - Bogus session key to use in case of sensitive decryption error, or if the decrypted session key is of a different type/size. + * This is needed for constant-time processing. Expected object of the form: { sessionKey: Uint8Array, sessionKeyAlgorithm: enums.symmetric } + * @throws {Error} if decryption failed, unless `randomSessionKey` is given + * @async + */ + async decrypt(key, randomSessionKey) { + // check that session key algo matches the secret key algo + if (this.publicKeyAlgorithm !== key.algorithm) { + throw new Error('Decryption error'); + } + + const randomPayload = randomSessionKey ? util.concatUint8Array([ + new Uint8Array([randomSessionKey.sessionKeyAlgorithm]), + randomSessionKey.sessionKey, + util.writeChecksum(randomSessionKey.sessionKey) + ]) : null; + const decoded = await mod.publicKeyDecrypt(this.publicKeyAlgorithm, key.publicParams, key.privateParams, this.encrypted, key.getFingerprintBytes(), randomPayload); + const symmetricAlgoByte = decoded[0]; + const sessionKey = decoded.subarray(1, decoded.length - 2); + const checksum = decoded.subarray(decoded.length - 2); + const computedChecksum = util.writeChecksum(sessionKey); + const isValidChecksum = computedChecksum[0] === checksum[0] & computedChecksum[1] === checksum[1]; + + if (randomSessionKey) { + // We must not leak info about the validity of the decrypted checksum or cipher algo. + // The decrypted session key must be of the same algo and size as the random session key, otherwise we discard it and use the random data. + const isValidPayload = isValidChecksum & symmetricAlgoByte === randomSessionKey.sessionKeyAlgorithm & sessionKey.length === randomSessionKey.sessionKey.length; + this.sessionKeyAlgorithm = util.selectUint8(isValidPayload, symmetricAlgoByte, randomSessionKey.sessionKeyAlgorithm); + this.sessionKey = util.selectUint8Array(isValidPayload, sessionKey, randomSessionKey.sessionKey); + + } else { + const isValidPayload = isValidChecksum && enums.read(enums.symmetric, symmetricAlgoByte); + if (isValidPayload) { + this.sessionKey = sessionKey; + this.sessionKeyAlgorithm = symmetricAlgoByte; + } else { + throw new Error('Decryption error'); + } + } + } + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + class S2K { + /** + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + constructor(config = defaultConfig) { + /** + * Hash function identifier, or 0 for gnu-dummy keys + * @type {module:enums.hash | 0} + */ + this.algorithm = enums.hash.sha256; + /** + * enums.s2k identifier or 'gnu-dummy' + * @type {String} + */ + this.type = 'iterated'; + /** @type {Integer} */ + this.c = config.s2kIterationCountByte; + /** Eight bytes of salt in a binary string. + * @type {Uint8Array} + */ + this.salt = null; + } + + getCount() { + // Exponent bias, defined in RFC4880 + const expbias = 6; + + return (16 + (this.c & 15)) << ((this.c >> 4) + expbias); + } + + /** + * Parsing function for a string-to-key specifier ({@link https://tools.ietf.org/html/rfc4880#section-3.7|RFC 4880 3.7}). + * @param {Uint8Array} bytes - Payload of string-to-key specifier + * @returns {Integer} Actual length of the object. + */ + read(bytes) { + let i = 0; + this.type = enums.read(enums.s2k, bytes[i++]); + this.algorithm = bytes[i++]; + + switch (this.type) { + case 'simple': + break; + + case 'salted': + this.salt = bytes.subarray(i, i + 8); + i += 8; + break; + + case 'iterated': + this.salt = bytes.subarray(i, i + 8); + i += 8; + + // Octet 10: count, a one-octet, coded value + this.c = bytes[i++]; + break; + + case 'gnu': + if (util.uint8ArrayToString(bytes.subarray(i, i + 3)) === 'GNU') { + i += 3; // GNU + const gnuExtType = 1000 + bytes[i++]; + if (gnuExtType === 1001) { + this.type = 'gnu-dummy'; + // GnuPG extension mode 1001 -- don't write secret key at all + } else { + throw new Error('Unknown s2k gnu protection mode.'); + } + } else { + throw new Error('Unknown s2k type.'); + } + break; + + default: + throw new Error('Unknown s2k type.'); + } + + return i; + } + + /** + * Serializes s2k information + * @returns {Uint8Array} Binary representation of s2k. + */ + write() { + if (this.type === 'gnu-dummy') { + return new Uint8Array([101, 0, ...util.stringToUint8Array('GNU'), 1]); + } + const arr = [new Uint8Array([enums.write(enums.s2k, this.type), this.algorithm])]; + + switch (this.type) { + case 'simple': + break; + case 'salted': + arr.push(this.salt); + break; + case 'iterated': + arr.push(this.salt); + arr.push(new Uint8Array([this.c])); + break; + case 'gnu': + throw new Error('GNU s2k type not supported.'); + default: + throw new Error('Unknown s2k type.'); + } + + return util.concatUint8Array(arr); + } + + /** + * Produces a key using the specified passphrase and the defined + * hashAlgorithm + * @param {String} passphrase - Passphrase containing user input + * @returns {Promise} Produced key with a length corresponding to. + * hashAlgorithm hash length + * @async + */ + async produceKey(passphrase, numBytes) { + passphrase = util.encodeUTF8(passphrase); + + const arr = []; + let rlength = 0; + + let prefixlen = 0; + while (rlength < numBytes) { + let toHash; + switch (this.type) { + case 'simple': + toHash = util.concatUint8Array([new Uint8Array(prefixlen), passphrase]); + break; + case 'salted': + toHash = util.concatUint8Array([new Uint8Array(prefixlen), this.salt, passphrase]); + break; + case 'iterated': { + const data = util.concatUint8Array([this.salt, passphrase]); + let datalen = data.length; + const count = Math.max(this.getCount(), datalen); + toHash = new Uint8Array(prefixlen + count); + toHash.set(data, prefixlen); + for (let pos = prefixlen + datalen; pos < count; pos += datalen, datalen *= 2) { + toHash.copyWithin(pos, prefixlen, pos); + } + break; + } + case 'gnu': + throw new Error('GNU s2k type not supported.'); + default: + throw new Error('Unknown s2k type.'); + } + const result = await mod.hash.digest(this.algorithm, toHash); + arr.push(result); + rlength += result.length; + prefixlen++; + } + + return util.concatUint8Array(arr).subarray(0, numBytes); + } + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + /** + * Symmetric-Key Encrypted Session Key Packets (Tag 3) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.3|RFC4880 5.3}: + * The Symmetric-Key Encrypted Session Key packet holds the + * symmetric-key encryption of a session key used to encrypt a message. + * Zero or more Public-Key Encrypted Session Key packets and/or + * Symmetric-Key Encrypted Session Key packets may precede a + * Symmetrically Encrypted Data packet that holds an encrypted message. + * The message is encrypted with a session key, and the session key is + * itself encrypted and stored in the Encrypted Session Key packet or + * the Symmetric-Key Encrypted Session Key packet. + */ + class SymEncryptedSessionKeyPacket { + static get tag() { + return enums.packet.symEncryptedSessionKey; + } + + /** + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + constructor(config = defaultConfig) { + this.version = config.aeadProtect ? 5 : 4; + this.sessionKey = null; + /** + * Algorithm to encrypt the session key with + * @type {enums.symmetric} + */ + this.sessionKeyEncryptionAlgorithm = null; + /** + * Algorithm to encrypt the message with + * @type {enums.symmetric} + */ + this.sessionKeyAlgorithm = enums.symmetric.aes256; + /** + * AEAD mode to encrypt the session key with (if AEAD protection is enabled) + * @type {enums.aead} + */ + this.aeadAlgorithm = enums.write(enums.aead, config.preferredAEADAlgorithm); + this.encrypted = null; + this.s2k = null; + this.iv = null; + } + + /** + * Parsing function for a symmetric encrypted session key packet (tag 3). + * + * @param {Uint8Array} bytes - Payload of a tag 3 packet + */ + read(bytes) { + let offset = 0; + + // A one-octet version number. The only currently defined version is 4. + this.version = bytes[offset++]; + if (this.version !== 4 && this.version !== 5) { + throw new UnsupportedError(`Version ${this.version} of the SKESK packet is unsupported.`); + } + + // A one-octet number describing the symmetric algorithm used. + const algo = bytes[offset++]; + + if (this.version === 5) { + // A one-octet AEAD algorithm. + this.aeadAlgorithm = bytes[offset++]; + } + + // A string-to-key (S2K) specifier, length as defined above. + this.s2k = new S2K(); + offset += this.s2k.read(bytes.subarray(offset, bytes.length)); + + if (this.version === 5) { + const mode = mod.getAEADMode(this.aeadAlgorithm); + + // A starting initialization vector of size specified by the AEAD + // algorithm. + this.iv = bytes.subarray(offset, offset += mode.ivLength); + } + + // The encrypted session key itself, which is decrypted with the + // string-to-key object. This is optional in version 4. + if (this.version === 5 || offset < bytes.length) { + this.encrypted = bytes.subarray(offset, bytes.length); + this.sessionKeyEncryptionAlgorithm = algo; + } else { + this.sessionKeyAlgorithm = algo; + } + } + + /** + * Create a binary representation of a tag 3 packet + * + * @returns {Uint8Array} The Uint8Array representation. + */ + write() { + const algo = this.encrypted === null ? + this.sessionKeyAlgorithm : + this.sessionKeyEncryptionAlgorithm; + + let bytes; + + if (this.version === 5) { + bytes = util.concatUint8Array([new Uint8Array([this.version, algo, this.aeadAlgorithm]), this.s2k.write(), this.iv, this.encrypted]); + } else { + bytes = util.concatUint8Array([new Uint8Array([this.version, algo]), this.s2k.write()]); + + if (this.encrypted !== null) { + bytes = util.concatUint8Array([bytes, this.encrypted]); + } + } + + return bytes; + } + + /** + * Decrypts the session key with the given passphrase + * @param {String} passphrase - The passphrase in string form + * @throws {Error} if decryption was not successful + * @async + */ + async decrypt(passphrase) { + const algo = this.sessionKeyEncryptionAlgorithm !== null ? + this.sessionKeyEncryptionAlgorithm : + this.sessionKeyAlgorithm; + + const { blockSize, keySize } = mod.getCipher(algo); + const key = await this.s2k.produceKey(passphrase, keySize); + + if (this.version === 5) { + const mode = mod.getAEADMode(this.aeadAlgorithm); + const adata = new Uint8Array([0xC0 | SymEncryptedSessionKeyPacket.tag, this.version, this.sessionKeyEncryptionAlgorithm, this.aeadAlgorithm]); + const modeInstance = await mode(algo, key); + this.sessionKey = await modeInstance.decrypt(this.encrypted, this.iv, adata); + } else if (this.encrypted !== null) { + const decrypted = await mod.mode.cfb.decrypt(algo, key, this.encrypted, new Uint8Array(blockSize)); + + this.sessionKeyAlgorithm = enums.write(enums.symmetric, decrypted[0]); + this.sessionKey = decrypted.subarray(1, decrypted.length); + } else { + this.sessionKey = key; + } + } + + /** + * Encrypts the session key with the given passphrase + * @param {String} passphrase - The passphrase in string form + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if encryption was not successful + * @async + */ + async encrypt(passphrase, config = defaultConfig) { + const algo = this.sessionKeyEncryptionAlgorithm !== null ? + this.sessionKeyEncryptionAlgorithm : + this.sessionKeyAlgorithm; + + this.sessionKeyEncryptionAlgorithm = algo; + + this.s2k = new S2K(config); + this.s2k.salt = await mod.random.getRandomBytes(8); + + const { blockSize, keySize } = mod.getCipher(algo); + const encryptionKey = await this.s2k.produceKey(passphrase, keySize); + + if (this.sessionKey === null) { + this.sessionKey = await mod.generateSessionKey(this.sessionKeyAlgorithm); + } + + if (this.version === 5) { + const mode = mod.getAEADMode(this.aeadAlgorithm); + this.iv = await mod.random.getRandomBytes(mode.ivLength); // generate new random IV + const associatedData = new Uint8Array([0xC0 | SymEncryptedSessionKeyPacket.tag, this.version, this.sessionKeyEncryptionAlgorithm, this.aeadAlgorithm]); + const modeInstance = await mode(algo, encryptionKey); + this.encrypted = await modeInstance.encrypt(this.sessionKey, this.iv, associatedData); + } else { + const toEncrypt = util.concatUint8Array([ + new Uint8Array([this.sessionKeyAlgorithm]), + this.sessionKey + ]); + this.encrypted = await mod.mode.cfb.encrypt(algo, encryptionKey, toEncrypt, new Uint8Array(blockSize), config); + } + } + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + /** + * Implementation of the Key Material Packet (Tag 5,6,7,14) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.5|RFC4480 5.5}: + * A key material packet contains all the information about a public or + * private key. There are four variants of this packet type, and two + * major versions. + * + * A Public-Key packet starts a series of packets that forms an OpenPGP + * key (sometimes called an OpenPGP certificate). + */ + class PublicKeyPacket { + static get tag() { + return enums.packet.publicKey; + } + + /** + * @param {Date} [date] - Creation date + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + constructor(date = new Date(), config = defaultConfig) { + /** + * Packet version + * @type {Integer} + */ + this.version = config.v5Keys ? 5 : 4; + /** + * Key creation date. + * @type {Date} + */ + this.created = util.normalizeDate(date); + /** + * Public key algorithm. + * @type {enums.publicKey} + */ + this.algorithm = null; + /** + * Algorithm specific public params + * @type {Object} + */ + this.publicParams = null; + /** + * Time until expiration in days (V3 only) + * @type {Integer} + */ + this.expirationTimeV3 = 0; + /** + * Fingerprint bytes + * @type {Uint8Array} + */ + this.fingerprint = null; + /** + * KeyID + * @type {module:type/keyid~KeyID} + */ + this.keyID = null; + } + + /** + * Create a PublicKeyPacket from a SecretKeyPacket + * @param {SecretKeyPacket} secretKeyPacket - key packet to convert + * @returns {PublicKeyPacket} public key packet + * @static + */ + static fromSecretKeyPacket(secretKeyPacket) { + const keyPacket = new PublicKeyPacket(); + const { version, created, algorithm, publicParams, keyID, fingerprint } = secretKeyPacket; + keyPacket.version = version; + keyPacket.created = created; + keyPacket.algorithm = algorithm; + keyPacket.publicParams = publicParams; + keyPacket.keyID = keyID; + keyPacket.fingerprint = fingerprint; + return keyPacket; + } + + /** + * Internal Parser for public keys as specified in {@link https://tools.ietf.org/html/rfc4880#section-5.5.2|RFC 4880 section 5.5.2 Public-Key Packet Formats} + * @param {Uint8Array} bytes - Input array to read the packet from + * @returns {Object} This object with attributes set by the parser + * @async + */ + async read(bytes) { + let pos = 0; + // A one-octet version number (3, 4 or 5). + this.version = bytes[pos++]; + + if (this.version === 4 || this.version === 5) { + // - A four-octet number denoting the time that the key was created. + this.created = util.readDate(bytes.subarray(pos, pos + 4)); + pos += 4; + + // - A one-octet number denoting the public-key algorithm of this key. + this.algorithm = bytes[pos++]; + + if (this.version === 5) { + // - A four-octet scalar octet count for the following key material. + pos += 4; + } + + // - A series of values comprising the key material. + try { + const { read, publicParams } = mod.parsePublicKeyParams(this.algorithm, bytes.subarray(pos)); + this.publicParams = publicParams; + pos += read; + } catch (err) { + throw new Error('Error reading MPIs'); + } + + // we set the fingerprint and keyID already to make it possible to put together the key packets directly in the Key constructor + await this.computeFingerprintAndKeyID(); + return pos; + } + throw new UnsupportedError(`Version ${this.version} of the key packet is unsupported.`); + } + + /** + * Creates an OpenPGP public key packet for the given key. + * @returns {Uint8Array} Bytes encoding the public key OpenPGP packet. + */ + write() { + const arr = []; + // Version + arr.push(new Uint8Array([this.version])); + arr.push(util.writeDate(this.created)); + // A one-octet number denoting the public-key algorithm of this key + arr.push(new Uint8Array([this.algorithm])); + + const params = mod.serializeParams(this.algorithm, this.publicParams); + if (this.version === 5) { + // A four-octet scalar octet count for the following key material + arr.push(util.writeNumber(params.length, 4)); + } + // Algorithm-specific params + arr.push(params); + return util.concatUint8Array(arr); + } + + /** + * Write packet in order to be hashed; either for a signature or a fingerprint + * @param {Integer} version - target version of signature or key + */ + writeForHash(version) { + const bytes = this.writePublicKey(); + + if (version === 5) { + return util.concatUint8Array([new Uint8Array([0x9A]), util.writeNumber(bytes.length, 4), bytes]); + } + return util.concatUint8Array([new Uint8Array([0x99]), util.writeNumber(bytes.length, 2), bytes]); + } + + /** + * Check whether secret-key data is available in decrypted form. Returns null for public keys. + * @returns {Boolean|null} + */ + isDecrypted() { + return null; + } + + /** + * Returns the creation time of the key + * @returns {Date} + */ + getCreationTime() { + return this.created; + } + + /** + * Return the key ID of the key + * @returns {module:type/keyid~KeyID} The 8-byte key ID + */ + getKeyID() { + return this.keyID; + } + + /** + * Computes and set the key ID and fingerprint of the key + * @async + */ + async computeFingerprintAndKeyID() { + await this.computeFingerprint(); + this.keyID = new KeyID(); + + if (this.version === 5) { + this.keyID.read(this.fingerprint.subarray(0, 8)); + } else if (this.version === 4) { + this.keyID.read(this.fingerprint.subarray(12, 20)); + } else { + throw new Error('Unsupported key version'); + } + } + + /** + * Computes and set the fingerprint of the key + */ + async computeFingerprint() { + const toHash = this.writeForHash(this.version); + + if (this.version === 5) { + this.fingerprint = await mod.hash.sha256(toHash); + } else if (this.version === 4) { + this.fingerprint = await mod.hash.sha1(toHash); + } else { + throw new Error('Unsupported key version'); + } + } + + /** + * Returns the fingerprint of the key, as an array of bytes + * @returns {Uint8Array} A Uint8Array containing the fingerprint + */ + getFingerprintBytes() { + return this.fingerprint; + } + + /** + * Calculates and returns the fingerprint of the key, as a string + * @returns {String} A string containing the fingerprint in lowercase hex + */ + getFingerprint() { + return util.uint8ArrayToHex(this.getFingerprintBytes()); + } + + /** + * Calculates whether two keys have the same fingerprint without actually calculating the fingerprint + * @returns {Boolean} Whether the two keys have the same version and public key data. + */ + hasSameFingerprintAs(other) { + return this.version === other.version && util.equalsUint8Array(this.writePublicKey(), other.writePublicKey()); + } + + /** + * Returns algorithm information + * @returns {Object} An object of the form {algorithm: String, bits:int, curve:String}. + */ + getAlgorithmInfo() { + const result = {}; + result.algorithm = enums.read(enums.publicKey, this.algorithm); + // RSA, DSA or ElGamal public modulo + const modulo = this.publicParams.n || this.publicParams.p; + if (modulo) { + result.bits = util.uint8ArrayBitLength(modulo); + } else { + result.curve = this.publicParams.oid.getName(); + } + return result; + } + } + + /** + * Alias of read() + * @see PublicKeyPacket#read + */ + PublicKeyPacket.prototype.readPublicKey = PublicKeyPacket.prototype.read; + + /** + * Alias of write() + * @see PublicKeyPacket#write + */ + PublicKeyPacket.prototype.writePublicKey = PublicKeyPacket.prototype.write; + + // GPG4Browsers - An OpenPGP implementation in javascript + + // A SE packet can contain the following packet types + const allowedPackets$3 = /*#__PURE__*/ util.constructAllowedPackets([ + LiteralDataPacket, + CompressedDataPacket, + OnePassSignaturePacket, + SignaturePacket + ]); + + /** + * Implementation of the Symmetrically Encrypted Data Packet (Tag 9) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.7|RFC4880 5.7}: + * The Symmetrically Encrypted Data packet contains data encrypted with a + * symmetric-key algorithm. When it has been decrypted, it contains other + * packets (usually a literal data packet or compressed data packet, but in + * theory other Symmetrically Encrypted Data packets or sequences of packets + * that form whole OpenPGP messages). + */ + class SymmetricallyEncryptedDataPacket { + static get tag() { + return enums.packet.symmetricallyEncryptedData; + } + + constructor() { + /** + * Encrypted secret-key data + */ + this.encrypted = null; + /** + * Decrypted packets contained within. + * @type {PacketList} + */ + this.packets = null; + } + + read(bytes) { + this.encrypted = bytes; + } + + write() { + return this.encrypted; + } + + /** + * Decrypt the symmetrically-encrypted packet data + * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. + * @param {module:enums.symmetric} sessionKeyAlgorithm - Symmetric key algorithm to use + * @param {Uint8Array} key - The key of cipher blocksize length to be used + * @param {Object} [config] - Full configuration, defaults to openpgp.config + + * @throws {Error} if decryption was not successful + * @async + */ + async decrypt(sessionKeyAlgorithm, key, config = defaultConfig) { + // If MDC errors are not being ignored, all missing MDC packets in symmetrically encrypted data should throw an error + if (!config.allowUnauthenticatedMessages) { + throw new Error('Message is not authenticated.'); + } + + const { blockSize } = mod.getCipher(sessionKeyAlgorithm); + const encrypted = await readToEnd(clone(this.encrypted)); + const decrypted = await mod.mode.cfb.decrypt(sessionKeyAlgorithm, key, + encrypted.subarray(blockSize + 2), + encrypted.subarray(2, blockSize + 2) + ); + + this.packets = await PacketList.fromBinary(decrypted, allowedPackets$3, config); + } + + /** + * Encrypt the symmetrically-encrypted packet data + * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. + * @param {module:enums.symmetric} sessionKeyAlgorithm - Symmetric key algorithm to use + * @param {Uint8Array} key - The key of cipher blocksize length to be used + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if encryption was not successful + * @async + */ + async encrypt(sessionKeyAlgorithm, key, config = defaultConfig) { + const data = this.packets.write(); + const { blockSize } = mod.getCipher(sessionKeyAlgorithm); + + const prefix = await mod.getPrefixRandom(sessionKeyAlgorithm); + const FRE = await mod.mode.cfb.encrypt(sessionKeyAlgorithm, key, prefix, new Uint8Array(blockSize), config); + const ciphertext = await mod.mode.cfb.encrypt(sessionKeyAlgorithm, key, data, FRE.subarray(2), config); + this.encrypted = util.concat([FRE, ciphertext]); + } + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + /** + * Implementation of the strange "Marker packet" (Tag 10) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.8|RFC4880 5.8}: + * An experimental version of PGP used this packet as the Literal + * packet, but no released version of PGP generated Literal packets with this + * tag. With PGP 5.x, this packet has been reassigned and is reserved for use as + * the Marker packet. + * + * The body of this packet consists of: + * The three octets 0x50, 0x47, 0x50 (which spell "PGP" in UTF-8). + * + * Such a packet MUST be ignored when received. It may be placed at the + * beginning of a message that uses features not available in PGP + * version 2.6 in order to cause that version to report that newer + * software is necessary to process the message. + */ + class MarkerPacket { + static get tag() { + return enums.packet.marker; + } + + /** + * Parsing function for a marker data packet (tag 10). + * @param {Uint8Array} bytes - Payload of a tag 10 packet + * @returns {Boolean} whether the packet payload contains "PGP" + */ + read(bytes) { + if (bytes[0] === 0x50 && // P + bytes[1] === 0x47 && // G + bytes[2] === 0x50) { // P + return true; + } + return false; + } + + write() { + return new Uint8Array([0x50, 0x47, 0x50]); + } + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + /** + * A Public-Subkey packet (tag 14) has exactly the same format as a + * Public-Key packet, but denotes a subkey. One or more subkeys may be + * associated with a top-level key. By convention, the top-level key + * provides signature services, and the subkeys provide encryption + * services. + * @extends PublicKeyPacket + */ + class PublicSubkeyPacket extends PublicKeyPacket { + static get tag() { + return enums.packet.publicSubkey; + } + + /** + * @param {Date} [date] - Creation date + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + // eslint-disable-next-line no-useless-constructor + constructor(date, config) { + super(date, config); + } + + /** + * Create a PublicSubkeyPacket from a SecretSubkeyPacket + * @param {SecretSubkeyPacket} secretSubkeyPacket - subkey packet to convert + * @returns {SecretSubkeyPacket} public key packet + * @static + */ + static fromSecretSubkeyPacket(secretSubkeyPacket) { + const keyPacket = new PublicSubkeyPacket(); + const { version, created, algorithm, publicParams, keyID, fingerprint } = secretSubkeyPacket; + keyPacket.version = version; + keyPacket.created = created; + keyPacket.algorithm = algorithm; + keyPacket.publicParams = publicParams; + keyPacket.keyID = keyID; + keyPacket.fingerprint = fingerprint; + return keyPacket; + } + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + /** + * Implementation of the User Attribute Packet (Tag 17) + * + * The User Attribute packet is a variation of the User ID packet. It + * is capable of storing more types of data than the User ID packet, + * which is limited to text. Like the User ID packet, a User Attribute + * packet may be certified by the key owner ("self-signed") or any other + * key owner who cares to certify it. Except as noted, a User Attribute + * packet may be used anywhere that a User ID packet may be used. + * + * While User Attribute packets are not a required part of the OpenPGP + * standard, implementations SHOULD provide at least enough + * compatibility to properly handle a certification signature on the + * User Attribute packet. A simple way to do this is by treating the + * User Attribute packet as a User ID packet with opaque contents, but + * an implementation may use any method desired. + */ + class UserAttributePacket { + static get tag() { + return enums.packet.userAttribute; + } + + constructor() { + this.attributes = []; + } + + /** + * parsing function for a user attribute packet (tag 17). + * @param {Uint8Array} input - Payload of a tag 17 packet + */ + read(bytes) { + let i = 0; + while (i < bytes.length) { + const len = readSimpleLength(bytes.subarray(i, bytes.length)); + i += len.offset; + + this.attributes.push(util.uint8ArrayToString(bytes.subarray(i, i + len.len))); + i += len.len; + } + } + + /** + * Creates a binary representation of the user attribute packet + * @returns {Uint8Array} String representation. + */ + write() { + const arr = []; + for (let i = 0; i < this.attributes.length; i++) { + arr.push(writeSimpleLength(this.attributes[i].length)); + arr.push(util.stringToUint8Array(this.attributes[i])); + } + return util.concatUint8Array(arr); + } + + /** + * Compare for equality + * @param {UserAttributePacket} usrAttr + * @returns {Boolean} True if equal. + */ + equals(usrAttr) { + if (!usrAttr || !(usrAttr instanceof UserAttributePacket)) { + return false; + } + return this.attributes.every(function(attr, index) { + return attr === usrAttr.attributes[index]; + }); + } + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + /** + * A Secret-Key packet contains all the information that is found in a + * Public-Key packet, including the public-key material, but also + * includes the secret-key material after all the public-key fields. + * @extends PublicKeyPacket + */ + class SecretKeyPacket extends PublicKeyPacket { + static get tag() { + return enums.packet.secretKey; + } + + /** + * @param {Date} [date] - Creation date + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + constructor(date = new Date(), config = defaultConfig) { + super(date, config); + /** + * Secret-key data + */ + this.keyMaterial = null; + /** + * Indicates whether secret-key data is encrypted. `this.isEncrypted === false` means data is available in decrypted form. + */ + this.isEncrypted = null; + /** + * S2K usage + * @type {enums.symmetric} + */ + this.s2kUsage = 0; + /** + * S2K object + * @type {type/s2k} + */ + this.s2k = null; + /** + * Symmetric algorithm to encrypt the key with + * @type {enums.symmetric} + */ + this.symmetric = null; + /** + * AEAD algorithm to encrypt the key with (if AEAD protection is enabled) + * @type {enums.aead} + */ + this.aead = null; + /** + * Decrypted private parameters, referenced by name + * @type {Object} + */ + this.privateParams = null; + } + + // 5.5.3. Secret-Key Packet Formats + + /** + * Internal parser for private keys as specified in + * {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.5.3|RFC4880bis-04 section 5.5.3} + * @param {Uint8Array} bytes - Input string to read the packet from + * @async + */ + async read(bytes) { + // - A Public-Key or Public-Subkey packet, as described above. + let i = await this.readPublicKey(bytes); + + // - One octet indicating string-to-key usage conventions. Zero + // indicates that the secret-key data is not encrypted. 255 or 254 + // indicates that a string-to-key specifier is being given. Any + // other value is a symmetric-key encryption algorithm identifier. + this.s2kUsage = bytes[i++]; + + // - Only for a version 5 packet, a one-octet scalar octet count of + // the next 4 optional fields. + if (this.version === 5) { + i++; + } + + // - [Optional] If string-to-key usage octet was 255, 254, or 253, a + // one-octet symmetric encryption algorithm. + if (this.s2kUsage === 255 || this.s2kUsage === 254 || this.s2kUsage === 253) { + this.symmetric = bytes[i++]; + + // - [Optional] If string-to-key usage octet was 253, a one-octet + // AEAD algorithm. + if (this.s2kUsage === 253) { + this.aead = bytes[i++]; + } + + // - [Optional] If string-to-key usage octet was 255, 254, or 253, a + // string-to-key specifier. The length of the string-to-key + // specifier is implied by its type, as described above. + this.s2k = new S2K(); + i += this.s2k.read(bytes.subarray(i, bytes.length)); + + if (this.s2k.type === 'gnu-dummy') { + return; + } + } else if (this.s2kUsage) { + this.symmetric = this.s2kUsage; + } + + // - [Optional] If secret data is encrypted (string-to-key usage octet + // not zero), an Initial Vector (IV) of the same length as the + // cipher's block size. + if (this.s2kUsage) { + this.iv = bytes.subarray( + i, + i + mod.getCipher(this.symmetric).blockSize + ); + + i += this.iv.length; + } + + // - Only for a version 5 packet, a four-octet scalar octet count for + // the following key material. + if (this.version === 5) { + i += 4; + } + + // - Plain or encrypted multiprecision integers comprising the secret + // key data. These algorithm-specific fields are as described + // below. + this.keyMaterial = bytes.subarray(i); + this.isEncrypted = !!this.s2kUsage; + + if (!this.isEncrypted) { + const cleartext = this.keyMaterial.subarray(0, -2); + if (!util.equalsUint8Array(util.writeChecksum(cleartext), this.keyMaterial.subarray(-2))) { + throw new Error('Key checksum mismatch'); + } + try { + const { privateParams } = mod.parsePrivateKeyParams(this.algorithm, cleartext, this.publicParams); + this.privateParams = privateParams; + } catch (err) { + throw new Error('Error reading MPIs'); + } + } + } + + /** + * Creates an OpenPGP key packet for the given key. + * @returns {Uint8Array} A string of bytes containing the secret key OpenPGP packet. + */ + write() { + const arr = [this.writePublicKey()]; + + arr.push(new Uint8Array([this.s2kUsage])); + + const optionalFieldsArr = []; + // - [Optional] If string-to-key usage octet was 255, 254, or 253, a + // one- octet symmetric encryption algorithm. + if (this.s2kUsage === 255 || this.s2kUsage === 254 || this.s2kUsage === 253) { + optionalFieldsArr.push(this.symmetric); + + // - [Optional] If string-to-key usage octet was 253, a one-octet + // AEAD algorithm. + if (this.s2kUsage === 253) { + optionalFieldsArr.push(this.aead); + } + + // - [Optional] If string-to-key usage octet was 255, 254, or 253, a + // string-to-key specifier. The length of the string-to-key + // specifier is implied by its type, as described above. + optionalFieldsArr.push(...this.s2k.write()); + } + + // - [Optional] If secret data is encrypted (string-to-key usage octet + // not zero), an Initial Vector (IV) of the same length as the + // cipher's block size. + if (this.s2kUsage && this.s2k.type !== 'gnu-dummy') { + optionalFieldsArr.push(...this.iv); + } + + if (this.version === 5) { + arr.push(new Uint8Array([optionalFieldsArr.length])); + } + arr.push(new Uint8Array(optionalFieldsArr)); + + if (!this.isDummy()) { + if (!this.s2kUsage) { + this.keyMaterial = mod.serializeParams(this.algorithm, this.privateParams); + } + + if (this.version === 5) { + arr.push(util.writeNumber(this.keyMaterial.length, 4)); + } + arr.push(this.keyMaterial); + + if (!this.s2kUsage) { + arr.push(util.writeChecksum(this.keyMaterial)); + } + } + + return util.concatUint8Array(arr); + } + + /** + * Check whether secret-key data is available in decrypted form. + * Returns false for gnu-dummy keys and null for public keys. + * @returns {Boolean|null} + */ + isDecrypted() { + return this.isEncrypted === false; + } + + /** + * Check whether this is a gnu-dummy key + * @returns {Boolean} + */ + isDummy() { + return !!(this.s2k && this.s2k.type === 'gnu-dummy'); + } + + /** + * Remove private key material, converting the key to a dummy one. + * The resulting key cannot be used for signing/decrypting but can still verify signatures. + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + makeDummy(config = defaultConfig) { + if (this.isDummy()) { + return; + } + if (this.isDecrypted()) { + this.clearPrivateParams(); + } + this.isEncrypted = null; + this.keyMaterial = null; + this.s2k = new S2K(config); + this.s2k.algorithm = 0; + this.s2k.c = 0; + this.s2k.type = 'gnu-dummy'; + this.s2kUsage = 254; + this.symmetric = enums.symmetric.aes256; + } + + /** + * Encrypt the payload. By default, we use aes256 and iterated, salted string + * to key specifier. If the key is in a decrypted state (isEncrypted === false) + * and the passphrase is empty or undefined, the key will be set as not encrypted. + * This can be used to remove passphrase protection after calling decrypt(). + * @param {String} passphrase + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if encryption was not successful + * @async + */ + async encrypt(passphrase, config = defaultConfig) { + if (this.isDummy()) { + return; + } + + if (!this.isDecrypted()) { + throw new Error('Key packet is already encrypted'); + } + + if (this.isDecrypted() && !passphrase) { + this.s2kUsage = 0; + return; + } else if (!passphrase) { + throw new Error('The key must be decrypted before removing passphrase protection.'); + } + + this.s2k = new S2K(config); + this.s2k.salt = await mod.random.getRandomBytes(8); + const cleartext = mod.serializeParams(this.algorithm, this.privateParams); + this.symmetric = enums.symmetric.aes256; + const key = await produceEncryptionKey(this.s2k, passphrase, this.symmetric); + + const { blockSize } = mod.getCipher(this.symmetric); + this.iv = await mod.random.getRandomBytes(blockSize); + + if (config.aeadProtect) { + this.s2kUsage = 253; + this.aead = enums.aead.eax; + const mode = mod.getAEADMode(this.aead); + const modeInstance = await mode(this.symmetric, key); + this.keyMaterial = await modeInstance.encrypt(cleartext, this.iv.subarray(0, mode.ivLength), new Uint8Array()); + } else { + this.s2kUsage = 254; + this.keyMaterial = await mod.mode.cfb.encrypt(this.symmetric, key, util.concatUint8Array([ + cleartext, + await mod.hash.sha1(cleartext, config) + ]), this.iv, config); + } + } + + /** + * Decrypts the private key params which are needed to use the key. + * Successful decryption does not imply key integrity, call validate() to confirm that. + * {@link SecretKeyPacket.isDecrypted} should be false, as + * otherwise calls to this function will throw an error. + * @param {String} passphrase - The passphrase for this private key as string + * @throws {Error} if the key is already decrypted, or if decryption was not successful + * @async + */ + async decrypt(passphrase) { + if (this.isDummy()) { + return false; + } + + if (this.isDecrypted()) { + throw new Error('Key packet is already decrypted.'); + } + + let key; + if (this.s2kUsage === 254 || this.s2kUsage === 253) { + key = await produceEncryptionKey(this.s2k, passphrase, this.symmetric); + } else if (this.s2kUsage === 255) { + throw new Error('Encrypted private key is authenticated using an insecure two-byte hash'); + } else { + throw new Error('Private key is encrypted using an insecure S2K function: unsalted MD5'); + } + + let cleartext; + if (this.s2kUsage === 253) { + const mode = mod.getAEADMode(this.aead); + const modeInstance = await mode(this.symmetric, key); + try { + cleartext = await modeInstance.decrypt(this.keyMaterial, this.iv.subarray(0, mode.ivLength), new Uint8Array()); + } catch (err) { + if (err.message === 'Authentication tag mismatch') { + throw new Error('Incorrect key passphrase: ' + err.message); + } + throw err; + } + } else { + const cleartextWithHash = await mod.mode.cfb.decrypt(this.symmetric, key, this.keyMaterial, this.iv); + + cleartext = cleartextWithHash.subarray(0, -20); + const hash = await mod.hash.sha1(cleartext); + + if (!util.equalsUint8Array(hash, cleartextWithHash.subarray(-20))) { + throw new Error('Incorrect key passphrase'); + } + } + + try { + const { privateParams } = mod.parsePrivateKeyParams(this.algorithm, cleartext, this.publicParams); + this.privateParams = privateParams; + } catch (err) { + throw new Error('Error reading MPIs'); + } + this.isEncrypted = false; + this.keyMaterial = null; + this.s2kUsage = 0; + } + + /** + * Checks that the key parameters are consistent + * @throws {Error} if validation was not successful + * @async + */ + async validate() { + if (this.isDummy()) { + return; + } + + if (!this.isDecrypted()) { + throw new Error('Key is not decrypted'); + } + + let validParams; + try { + // this can throw if some parameters are undefined + validParams = await mod.validateParams(this.algorithm, this.publicParams, this.privateParams); + } catch (_) { + validParams = false; + } + if (!validParams) { + throw new Error('Key is invalid'); + } + } + + async generate(bits, curve) { + const { privateParams, publicParams } = await mod.generateParams(this.algorithm, bits, curve); + this.privateParams = privateParams; + this.publicParams = publicParams; + this.isEncrypted = false; + } + + /** + * Clear private key parameters + */ + clearPrivateParams() { + if (this.isDummy()) { + return; + } + + Object.keys(this.privateParams).forEach(name => { + const param = this.privateParams[name]; + param.fill(0); + delete this.privateParams[name]; + }); + this.privateParams = null; + this.isEncrypted = true; + } + } + + async function produceEncryptionKey(s2k, passphrase, algorithm) { + const { keySize } = mod.getCipher(algorithm); + return s2k.produceKey(passphrase, keySize); + } + + var emailAddresses = createCommonjsModule(function (module) { + // email-addresses.js - RFC 5322 email address parser + // v 3.1.0 + // + // http://tools.ietf.org/html/rfc5322 + // + // This library does not validate email addresses. + // emailAddresses attempts to parse addresses using the (fairly liberal) + // grammar specified in RFC 5322. + // + // email-addresses returns { + // ast: , + // addresses: [{ + // node: , + // name: , + // address: , + // local: , + // domain: + // }, ...] + // } + // + // emailAddresses.parseOneAddress and emailAddresses.parseAddressList + // work as you might expect. Try it out. + // + // Many thanks to Dominic Sayers and his documentation on the is_email function, + // http://code.google.com/p/isemail/ , which helped greatly in writing this parser. + + (function (global) { + + function parse5322(opts) { + + // tokenizing functions + + function inStr() { return pos < len; } + function curTok() { return parseString[pos]; } + function getPos() { return pos; } + function setPos(i) { pos = i; } + function nextTok() { pos += 1; } + function initialize() { + pos = 0; + len = parseString.length; + } + + // parser helper functions + + function o(name, value) { + return { + name: name, + tokens: value || "", + semantic: value || "", + children: [] + }; + } + + function wrap(name, ast) { + var n; + if (ast === null) { return null; } + n = o(name); + n.tokens = ast.tokens; + n.semantic = ast.semantic; + n.children.push(ast); + return n; + } + + function add(parent, child) { + if (child !== null) { + parent.tokens += child.tokens; + parent.semantic += child.semantic; + } + parent.children.push(child); + return parent; + } + + function compareToken(fxnCompare) { + var tok; + if (!inStr()) { return null; } + tok = curTok(); + if (fxnCompare(tok)) { + nextTok(); + return o('token', tok); + } + return null; + } + + function literal(lit) { + return function literalFunc() { + return wrap('literal', compareToken(function (tok) { + return tok === lit; + })); + }; + } + + function and() { + var args = arguments; + return function andFunc() { + var i, s, result, start; + start = getPos(); + s = o('and'); + for (i = 0; i < args.length; i += 1) { + result = args[i](); + if (result === null) { + setPos(start); + return null; + } + add(s, result); + } + return s; + }; + } + + function or() { + var args = arguments; + return function orFunc() { + var i, result, start; + start = getPos(); + for (i = 0; i < args.length; i += 1) { + result = args[i](); + if (result !== null) { + return result; + } + setPos(start); + } + return null; + }; + } + + function opt(prod) { + return function optFunc() { + var result, start; + start = getPos(); + result = prod(); + if (result !== null) { + return result; + } + else { + setPos(start); + return o('opt'); + } + }; + } + + function invis(prod) { + return function invisFunc() { + var result = prod(); + if (result !== null) { + result.semantic = ""; + } + return result; + }; + } + + function colwsp(prod) { + return function collapseSemanticWhitespace() { + var result = prod(); + if (result !== null && result.semantic.length > 0) { + result.semantic = " "; + } + return result; + }; + } + + function star(prod, minimum) { + return function starFunc() { + var s, result, count, start, min; + start = getPos(); + s = o('star'); + count = 0; + min = minimum === undefined ? 0 : minimum; + while ((result = prod()) !== null) { + count = count + 1; + add(s, result); + } + if (count >= min) { + return s; + } + else { + setPos(start); + return null; + } + }; + } + + // One expects names to get normalized like this: + // " First Last " -> "First Last" + // "First Last" -> "First Last" + // "First Last" -> "First Last" + function collapseWhitespace(s) { + return s.replace(/([ \t]|\r\n)+/g, ' ').replace(/^\s*/, '').replace(/\s*$/, ''); + } + + // UTF-8 pseudo-production (RFC 6532) + // RFC 6532 extends RFC 5322 productions to include UTF-8 + // using the following productions: + // UTF8-non-ascii = UTF8-2 / UTF8-3 / UTF8-4 + // UTF8-2 = + // UTF8-3 = + // UTF8-4 = + // + // For reference, the extended RFC 5322 productions are: + // VCHAR =/ UTF8-non-ascii + // ctext =/ UTF8-non-ascii + // atext =/ UTF8-non-ascii + // qtext =/ UTF8-non-ascii + // dtext =/ UTF8-non-ascii + function isUTF8NonAscii(tok) { + // In JavaScript, we just deal directly with Unicode code points, + // so we aren't checking individual bytes for UTF-8 encoding. + // Just check that the character is non-ascii. + return tok.charCodeAt(0) >= 128; + } + + + // common productions (RFC 5234) + // http://tools.ietf.org/html/rfc5234 + // B.1. Core Rules + + // CR = %x0D + // ; carriage return + function cr() { return wrap('cr', literal('\r')()); } + + // CRLF = CR LF + // ; Internet standard newline + function crlf() { return wrap('crlf', and(cr, lf)()); } + + // DQUOTE = %x22 + // ; " (Double Quote) + function dquote() { return wrap('dquote', literal('"')()); } + + // HTAB = %x09 + // ; horizontal tab + function htab() { return wrap('htab', literal('\t')()); } + + // LF = %x0A + // ; linefeed + function lf() { return wrap('lf', literal('\n')()); } + + // SP = %x20 + function sp() { return wrap('sp', literal(' ')()); } + + // VCHAR = %x21-7E + // ; visible (printing) characters + function vchar() { + return wrap('vchar', compareToken(function vcharFunc(tok) { + var code = tok.charCodeAt(0); + var accept = (0x21 <= code && code <= 0x7E); + if (opts.rfc6532) { + accept = accept || isUTF8NonAscii(tok); + } + return accept; + })); + } + + // WSP = SP / HTAB + // ; white space + function wsp() { return wrap('wsp', or(sp, htab)()); } + + + // email productions (RFC 5322) + // http://tools.ietf.org/html/rfc5322 + // 3.2.1. Quoted characters + + // quoted-pair = ("\" (VCHAR / WSP)) / obs-qp + function quotedPair() { + var qp = wrap('quoted-pair', + or( + and(literal('\\'), or(vchar, wsp)), + obsQP + )()); + if (qp === null) { return null; } + // a quoted pair will be two characters, and the "\" character + // should be semantically "invisible" (RFC 5322 3.2.1) + qp.semantic = qp.semantic[1]; + return qp; + } + + // 3.2.2. Folding White Space and Comments + + // FWS = ([*WSP CRLF] 1*WSP) / obs-FWS + function fws() { + return wrap('fws', or( + obsFws, + and( + opt(and( + star(wsp), + invis(crlf) + )), + star(wsp, 1) + ) + )()); + } + + // ctext = %d33-39 / ; Printable US-ASCII + // %d42-91 / ; characters not including + // %d93-126 / ; "(", ")", or "\" + // obs-ctext + function ctext() { + return wrap('ctext', or( + function ctextFunc1() { + return compareToken(function ctextFunc2(tok) { + var code = tok.charCodeAt(0); + var accept = + (33 <= code && code <= 39) || + (42 <= code && code <= 91) || + (93 <= code && code <= 126); + if (opts.rfc6532) { + accept = accept || isUTF8NonAscii(tok); + } + return accept; + }); + }, + obsCtext + )()); + } + + // ccontent = ctext / quoted-pair / comment + function ccontent() { + return wrap('ccontent', or(ctext, quotedPair, comment)()); + } + + // comment = "(" *([FWS] ccontent) [FWS] ")" + function comment() { + return wrap('comment', and( + literal('('), + star(and(opt(fws), ccontent)), + opt(fws), + literal(')') + )()); + } + + // CFWS = (1*([FWS] comment) [FWS]) / FWS + function cfws() { + return wrap('cfws', or( + and( + star( + and(opt(fws), comment), + 1 + ), + opt(fws) + ), + fws + )()); + } + + // 3.2.3. Atom + + //atext = ALPHA / DIGIT / ; Printable US-ASCII + // "!" / "#" / ; characters not including + // "$" / "%" / ; specials. Used for atoms. + // "&" / "'" / + // "*" / "+" / + // "-" / "/" / + // "=" / "?" / + // "^" / "_" / + // "`" / "{" / + // "|" / "}" / + // "~" + function atext() { + return wrap('atext', compareToken(function atextFunc(tok) { + var accept = + ('a' <= tok && tok <= 'z') || + ('A' <= tok && tok <= 'Z') || + ('0' <= tok && tok <= '9') || + (['!', '#', '$', '%', '&', '\'', '*', '+', '-', '/', + '=', '?', '^', '_', '`', '{', '|', '}', '~'].indexOf(tok) >= 0); + if (opts.rfc6532) { + accept = accept || isUTF8NonAscii(tok); + } + return accept; + })); + } + + // atom = [CFWS] 1*atext [CFWS] + function atom() { + return wrap('atom', and(colwsp(opt(cfws)), star(atext, 1), colwsp(opt(cfws)))()); + } + + // dot-atom-text = 1*atext *("." 1*atext) + function dotAtomText() { + var s, maybeText; + s = wrap('dot-atom-text', star(atext, 1)()); + if (s === null) { return s; } + maybeText = star(and(literal('.'), star(atext, 1)))(); + if (maybeText !== null) { + add(s, maybeText); + } + return s; + } + + // dot-atom = [CFWS] dot-atom-text [CFWS] + function dotAtom() { + return wrap('dot-atom', and(invis(opt(cfws)), dotAtomText, invis(opt(cfws)))()); + } + + // 3.2.4. Quoted Strings + + // qtext = %d33 / ; Printable US-ASCII + // %d35-91 / ; characters not including + // %d93-126 / ; "\" or the quote character + // obs-qtext + function qtext() { + return wrap('qtext', or( + function qtextFunc1() { + return compareToken(function qtextFunc2(tok) { + var code = tok.charCodeAt(0); + var accept = + (33 === code) || + (35 <= code && code <= 91) || + (93 <= code && code <= 126); + if (opts.rfc6532) { + accept = accept || isUTF8NonAscii(tok); + } + return accept; + }); + }, + obsQtext + )()); + } + + // qcontent = qtext / quoted-pair + function qcontent() { + return wrap('qcontent', or(qtext, quotedPair)()); + } + + // quoted-string = [CFWS] + // DQUOTE *([FWS] qcontent) [FWS] DQUOTE + // [CFWS] + function quotedString() { + return wrap('quoted-string', and( + invis(opt(cfws)), + invis(dquote), star(and(opt(colwsp(fws)), qcontent)), opt(invis(fws)), invis(dquote), + invis(opt(cfws)) + )()); + } + + // 3.2.5 Miscellaneous Tokens + + // word = atom / quoted-string + function word() { + return wrap('word', or(atom, quotedString)()); + } + + // phrase = 1*word / obs-phrase + function phrase() { + return wrap('phrase', or(obsPhrase, star(word, 1))()); + } + + // 3.4. Address Specification + // address = mailbox / group + function address() { + return wrap('address', or(mailbox, group)()); + } + + // mailbox = name-addr / addr-spec + function mailbox() { + return wrap('mailbox', or(nameAddr, addrSpec)()); + } + + // name-addr = [display-name] angle-addr + function nameAddr() { + return wrap('name-addr', and(opt(displayName), angleAddr)()); + } + + // angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / + // obs-angle-addr + function angleAddr() { + return wrap('angle-addr', or( + and( + invis(opt(cfws)), + literal('<'), + addrSpec, + literal('>'), + invis(opt(cfws)) + ), + obsAngleAddr + )()); + } + + // group = display-name ":" [group-list] ";" [CFWS] + function group() { + return wrap('group', and( + displayName, + literal(':'), + opt(groupList), + literal(';'), + invis(opt(cfws)) + )()); + } + + // display-name = phrase + function displayName() { + return wrap('display-name', function phraseFixedSemantic() { + var result = phrase(); + if (result !== null) { + result.semantic = collapseWhitespace(result.semantic); + } + return result; + }()); + } + + // mailbox-list = (mailbox *("," mailbox)) / obs-mbox-list + function mailboxList() { + return wrap('mailbox-list', or( + and( + mailbox, + star(and(literal(','), mailbox)) + ), + obsMboxList + )()); + } + + // address-list = (address *("," address)) / obs-addr-list + function addressList() { + return wrap('address-list', or( + and( + address, + star(and(literal(','), address)) + ), + obsAddrList + )()); + } + + // group-list = mailbox-list / CFWS / obs-group-list + function groupList() { + return wrap('group-list', or( + mailboxList, + invis(cfws), + obsGroupList + )()); + } + + // 3.4.1 Addr-Spec Specification + + // local-part = dot-atom / quoted-string / obs-local-part + function localPart() { + // note: quoted-string, dotAtom are proper subsets of obs-local-part + // so we really just have to look for obsLocalPart, if we don't care about the exact parse tree + return wrap('local-part', or(obsLocalPart, dotAtom, quotedString)()); + } + + // dtext = %d33-90 / ; Printable US-ASCII + // %d94-126 / ; characters not including + // obs-dtext ; "[", "]", or "\" + function dtext() { + return wrap('dtext', or( + function dtextFunc1() { + return compareToken(function dtextFunc2(tok) { + var code = tok.charCodeAt(0); + var accept = + (33 <= code && code <= 90) || + (94 <= code && code <= 126); + if (opts.rfc6532) { + accept = accept || isUTF8NonAscii(tok); + } + return accept; + }); + }, + obsDtext + )() + ); + } + + // domain-literal = [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS] + function domainLiteral() { + return wrap('domain-literal', and( + invis(opt(cfws)), + literal('['), + star(and(opt(fws), dtext)), + opt(fws), + literal(']'), + invis(opt(cfws)) + )()); + } + + // domain = dot-atom / domain-literal / obs-domain + function domain() { + return wrap('domain', function domainCheckTLD() { + var result = or(obsDomain, dotAtom, domainLiteral)(); + if (opts.rejectTLD) { + if (result && result.semantic && result.semantic.indexOf('.') < 0) { + return null; + } + } + // strip all whitespace from domains + if (result) { + result.semantic = result.semantic.replace(/\s+/g, ''); + } + return result; + }()); + } + + // addr-spec = local-part "@" domain + function addrSpec() { + return wrap('addr-spec', and( + localPart, literal('@'), domain + )()); + } + + // 3.6.2 Originator Fields + // Below we only parse the field body, not the name of the field + // like "From:", "Sender:", or "Reply-To:". Other libraries that + // parse email headers can parse those and defer to these productions + // for the "RFC 5322" part. + + // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields + // from = "From:" (mailbox-list / address-list) CRLF + function fromSpec() { + return wrap('from', or( + mailboxList, + addressList + )()); + } + + // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields + // sender = "Sender:" (mailbox / address) CRLF + function senderSpec() { + return wrap('sender', or( + mailbox, + address + )()); + } + + // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields + // reply-to = "Reply-To:" address-list CRLF + function replyToSpec() { + return wrap('reply-to', addressList()); + } + + // 4.1. Miscellaneous Obsolete Tokens + + // obs-NO-WS-CTL = %d1-8 / ; US-ASCII control + // %d11 / ; characters that do not + // %d12 / ; include the carriage + // %d14-31 / ; return, line feed, and + // %d127 ; white space characters + function obsNoWsCtl() { + return opts.strict ? null : wrap('obs-NO-WS-CTL', compareToken(function (tok) { + var code = tok.charCodeAt(0); + return ((1 <= code && code <= 8) || + (11 === code || 12 === code) || + (14 <= code && code <= 31) || + (127 === code)); + })); + } + + // obs-ctext = obs-NO-WS-CTL + function obsCtext() { return opts.strict ? null : wrap('obs-ctext', obsNoWsCtl()); } + + // obs-qtext = obs-NO-WS-CTL + function obsQtext() { return opts.strict ? null : wrap('obs-qtext', obsNoWsCtl()); } + + // obs-qp = "\" (%d0 / obs-NO-WS-CTL / LF / CR) + function obsQP() { + return opts.strict ? null : wrap('obs-qp', and( + literal('\\'), + or(literal('\0'), obsNoWsCtl, lf, cr) + )()); + } + + // obs-phrase = word *(word / "." / CFWS) + function obsPhrase() { + if (opts.strict ) return null; + return opts.atInDisplayName ? wrap('obs-phrase', and( + word, + star(or(word, literal('.'), literal('@'), colwsp(cfws))) + )()) : + wrap('obs-phrase', and( + word, + star(or(word, literal('.'), colwsp(cfws))) + )()); + } + + // 4.2. Obsolete Folding White Space + + // NOTE: read the errata http://www.rfc-editor.org/errata_search.php?rfc=5322&eid=1908 + // obs-FWS = 1*([CRLF] WSP) + function obsFws() { + return opts.strict ? null : wrap('obs-FWS', star( + and(invis(opt(crlf)), wsp), + 1 + )()); + } + + // 4.4. Obsolete Addressing + + // obs-angle-addr = [CFWS] "<" obs-route addr-spec ">" [CFWS] + function obsAngleAddr() { + return opts.strict ? null : wrap('obs-angle-addr', and( + invis(opt(cfws)), + literal('<'), + obsRoute, + addrSpec, + literal('>'), + invis(opt(cfws)) + )()); + } + + // obs-route = obs-domain-list ":" + function obsRoute() { + return opts.strict ? null : wrap('obs-route', and( + obsDomainList, + literal(':') + )()); + } + + // obs-domain-list = *(CFWS / ",") "@" domain + // *("," [CFWS] ["@" domain]) + function obsDomainList() { + return opts.strict ? null : wrap('obs-domain-list', and( + star(or(invis(cfws), literal(','))), + literal('@'), + domain, + star(and( + literal(','), + invis(opt(cfws)), + opt(and(literal('@'), domain)) + )) + )()); + } + + // obs-mbox-list = *([CFWS] ",") mailbox *("," [mailbox / CFWS]) + function obsMboxList() { + return opts.strict ? null : wrap('obs-mbox-list', and( + star(and( + invis(opt(cfws)), + literal(',') + )), + mailbox, + star(and( + literal(','), + opt(and( + mailbox, + invis(cfws) + )) + )) + )()); + } + + // obs-addr-list = *([CFWS] ",") address *("," [address / CFWS]) + function obsAddrList() { + return opts.strict ? null : wrap('obs-addr-list', and( + star(and( + invis(opt(cfws)), + literal(',') + )), + address, + star(and( + literal(','), + opt(and( + address, + invis(cfws) + )) + )) + )()); + } + + // obs-group-list = 1*([CFWS] ",") [CFWS] + function obsGroupList() { + return opts.strict ? null : wrap('obs-group-list', and( + star(and( + invis(opt(cfws)), + literal(',') + ), 1), + invis(opt(cfws)) + )()); + } + + // obs-local-part = word *("." word) + function obsLocalPart() { + return opts.strict ? null : wrap('obs-local-part', and(word, star(and(literal('.'), word)))()); + } + + // obs-domain = atom *("." atom) + function obsDomain() { + return opts.strict ? null : wrap('obs-domain', and(atom, star(and(literal('.'), atom)))()); + } + + // obs-dtext = obs-NO-WS-CTL / quoted-pair + function obsDtext() { + return opts.strict ? null : wrap('obs-dtext', or(obsNoWsCtl, quotedPair)()); + } + + ///////////////////////////////////////////////////// + + // ast analysis + + function findNode(name, root) { + var i, stack, node; + if (root === null || root === undefined) { return null; } + stack = [root]; + while (stack.length > 0) { + node = stack.pop(); + if (node.name === name) { + return node; + } + for (i = node.children.length - 1; i >= 0; i -= 1) { + stack.push(node.children[i]); + } + } + return null; + } + + function findAllNodes(name, root) { + var i, stack, node, result; + if (root === null || root === undefined) { return null; } + stack = [root]; + result = []; + while (stack.length > 0) { + node = stack.pop(); + if (node.name === name) { + result.push(node); + } + for (i = node.children.length - 1; i >= 0; i -= 1) { + stack.push(node.children[i]); + } + } + return result; + } + + function findAllNodesNoChildren(names, root) { + var i, stack, node, result, namesLookup; + if (root === null || root === undefined) { return null; } + stack = [root]; + result = []; + namesLookup = {}; + for (i = 0; i < names.length; i += 1) { + namesLookup[names[i]] = true; + } + + while (stack.length > 0) { + node = stack.pop(); + if (node.name in namesLookup) { + result.push(node); + // don't look at children (hence findAllNodesNoChildren) + } else { + for (i = node.children.length - 1; i >= 0; i -= 1) { + stack.push(node.children[i]); + } + } + } + return result; + } + + function giveResult(ast) { + var addresses, groupsAndMailboxes, i, groupOrMailbox, result; + if (ast === null) { + return null; + } + addresses = []; + + // An address is a 'group' (i.e. a list of mailboxes) or a 'mailbox'. + groupsAndMailboxes = findAllNodesNoChildren(['group', 'mailbox'], ast); + for (i = 0; i < groupsAndMailboxes.length; i += 1) { + groupOrMailbox = groupsAndMailboxes[i]; + if (groupOrMailbox.name === 'group') { + addresses.push(giveResultGroup(groupOrMailbox)); + } else if (groupOrMailbox.name === 'mailbox') { + addresses.push(giveResultMailbox(groupOrMailbox)); + } + } + + result = { + ast: ast, + addresses: addresses, + }; + if (opts.simple) { + result = simplifyResult(result); + } + if (opts.oneResult) { + return oneResult(result); + } + if (opts.simple) { + return result && result.addresses; + } else { + return result; + } + } + + function giveResultGroup(group) { + var i; + var groupName = findNode('display-name', group); + var groupResultMailboxes = []; + var mailboxes = findAllNodesNoChildren(['mailbox'], group); + for (i = 0; i < mailboxes.length; i += 1) { + groupResultMailboxes.push(giveResultMailbox(mailboxes[i])); + } + return { + node: group, + parts: { + name: groupName, + }, + type: group.name, // 'group' + name: grabSemantic(groupName), + addresses: groupResultMailboxes, + }; + } + + function giveResultMailbox(mailbox) { + var name = findNode('display-name', mailbox); + var aspec = findNode('addr-spec', mailbox); + var cfws = findAllNodes('cfws', mailbox); + var comments = findAllNodesNoChildren(['comment'], mailbox); + + + var local = findNode('local-part', aspec); + var domain = findNode('domain', aspec); + return { + node: mailbox, + parts: { + name: name, + address: aspec, + local: local, + domain: domain, + comments: cfws + }, + type: mailbox.name, // 'mailbox' + name: grabSemantic(name), + address: grabSemantic(aspec), + local: grabSemantic(local), + domain: grabSemantic(domain), + comments: concatComments(comments), + groupName: grabSemantic(mailbox.groupName), + }; + } + + function grabSemantic(n) { + return n !== null && n !== undefined ? n.semantic : null; + } + + function simplifyResult(result) { + var i; + if (result && result.addresses) { + for (i = 0; i < result.addresses.length; i += 1) { + delete result.addresses[i].node; + } + } + return result; + } + + function concatComments(comments) { + var result = ''; + if (comments) { + for (var i = 0; i < comments.length; i += 1) { + result += grabSemantic(comments[i]); + } + } + return result; + } + + function oneResult(result) { + if (!result) { return null; } + if (!opts.partial && result.addresses.length > 1) { return null; } + return result.addresses && result.addresses[0]; + } + + ///////////////////////////////////////////////////// + + var parseString, pos, len, parsed, startProduction; + + opts = handleOpts(opts, {}); + if (opts === null) { return null; } + + parseString = opts.input; + + startProduction = { + 'address': address, + 'address-list': addressList, + 'angle-addr': angleAddr, + 'from': fromSpec, + 'group': group, + 'mailbox': mailbox, + 'mailbox-list': mailboxList, + 'reply-to': replyToSpec, + 'sender': senderSpec, + }[opts.startAt] || addressList; + + if (!opts.strict) { + initialize(); + opts.strict = true; + parsed = startProduction(parseString); + if (opts.partial || !inStr()) { + return giveResult(parsed); + } + opts.strict = false; + } + + initialize(); + parsed = startProduction(parseString); + if (!opts.partial && inStr()) { return null; } + return giveResult(parsed); + } + + function parseOneAddressSimple(opts) { + return parse5322(handleOpts(opts, { + oneResult: true, + rfc6532: true, + simple: true, + startAt: 'address-list', + })); + } + + function parseAddressListSimple(opts) { + return parse5322(handleOpts(opts, { + rfc6532: true, + simple: true, + startAt: 'address-list', + })); + } + + function parseFromSimple(opts) { + return parse5322(handleOpts(opts, { + rfc6532: true, + simple: true, + startAt: 'from', + })); + } + + function parseSenderSimple(opts) { + return parse5322(handleOpts(opts, { + oneResult: true, + rfc6532: true, + simple: true, + startAt: 'sender', + })); + } + + function parseReplyToSimple(opts) { + return parse5322(handleOpts(opts, { + rfc6532: true, + simple: true, + startAt: 'reply-to', + })); + } + + function handleOpts(opts, defs) { + function isString(str) { + return Object.prototype.toString.call(str) === '[object String]'; + } + + function isObject(o) { + return o === Object(o); + } + + function isNullUndef(o) { + return o === null || o === undefined; + } + + var defaults, o; + + if (isString(opts)) { + opts = { input: opts }; + } else if (!isObject(opts)) { + return null; + } + + if (!isString(opts.input)) { return null; } + if (!defs) { return null; } + + defaults = { + oneResult: false, + partial: false, + rejectTLD: false, + rfc6532: false, + simple: false, + startAt: 'address-list', + strict: false, + atInDisplayName: false + }; + + for (o in defaults) { + if (isNullUndef(opts[o])) { + opts[o] = !isNullUndef(defs[o]) ? defs[o] : defaults[o]; + } + } + return opts; + } + + parse5322.parseOneAddress = parseOneAddressSimple; + parse5322.parseAddressList = parseAddressListSimple; + parse5322.parseFrom = parseFromSimple; + parse5322.parseSender = parseSenderSimple; + parse5322.parseReplyTo = parseReplyToSimple; + + { + module.exports = parse5322; + } + + }()); + }); + + // GPG4Browsers - An OpenPGP implementation in javascript + + /** + * Implementation of the User ID Packet (Tag 13) + * + * A User ID packet consists of UTF-8 text that is intended to represent + * the name and email address of the key holder. By convention, it + * includes an RFC 2822 [RFC2822] mail name-addr, but there are no + * restrictions on its content. The packet length in the header + * specifies the length of the User ID. + */ + class UserIDPacket { + static get tag() { + return enums.packet.userID; + } + + constructor() { + /** A string containing the user id. Usually in the form + * John Doe + * @type {String} + */ + this.userID = ''; + + this.name = ''; + this.email = ''; + this.comment = ''; + } + + /** + * Create UserIDPacket instance from object + * @param {Object} userID - Object specifying userID name, email and comment + * @returns {UserIDPacket} + * @static + */ + static fromObject(userID) { + if (util.isString(userID) || + (userID.name && !util.isString(userID.name)) || + (userID.email && !util.isEmailAddress(userID.email)) || + (userID.comment && !util.isString(userID.comment))) { + throw new Error('Invalid user ID format'); + } + const packet = new UserIDPacket(); + Object.assign(packet, userID); + const components = []; + if (packet.name) components.push(packet.name); + if (packet.comment) components.push(`(${packet.comment})`); + if (packet.email) components.push(`<${packet.email}>`); + packet.userID = components.join(' '); + return packet; + } + + /** + * Parsing function for a user id packet (tag 13). + * @param {Uint8Array} input - Payload of a tag 13 packet + */ + read(bytes, config = defaultConfig) { + const userID = util.decodeUTF8(bytes); + if (userID.length > config.maxUserIDLength) { + throw new Error('User ID string is too long'); + } + try { + const { name, address: email, comments } = emailAddresses.parseOneAddress({ input: userID, atInDisplayName: true }); + this.comment = comments.replace(/^\(|\)$/g, ''); + this.name = name; + this.email = email; + } catch (e) {} + this.userID = userID; + } + + /** + * Creates a binary representation of the user id packet + * @returns {Uint8Array} Binary representation. + */ + write() { + return util.encodeUTF8(this.userID); + } + + equals(otherUserID) { + return otherUserID && otherUserID.userID === this.userID; + } + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + /** + * A Secret-Subkey packet (tag 7) is the subkey analog of the Secret + * Key packet and has exactly the same format. + * @extends SecretKeyPacket + */ + class SecretSubkeyPacket extends SecretKeyPacket { + static get tag() { + return enums.packet.secretSubkey; + } + + /** + * @param {Date} [date] - Creation date + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + constructor(date = new Date(), config = defaultConfig) { + super(date, config); + } + } + + /** + * Implementation of the Trust Packet (Tag 12) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.10|RFC4880 5.10}: + * The Trust packet is used only within keyrings and is not normally + * exported. Trust packets contain data that record the user's + * specifications of which key holders are trustworthy introducers, + * along with other information that implementing software uses for + * trust information. The format of Trust packets is defined by a given + * implementation. + * + * Trust packets SHOULD NOT be emitted to output streams that are + * transferred to other users, and they SHOULD be ignored on any input + * other than local keyring files. + */ + class TrustPacket { + static get tag() { + return enums.packet.trust; + } + + /** + * Parsing function for a trust packet (tag 12). + * Currently not implemented as we ignore trust packets + */ + read() { + throw new UnsupportedError('Trust packets are not supported'); + } + + write() { + throw new UnsupportedError('Trust packets are not supported'); + } + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + // A Signature can contain the following packets + const allowedPackets$4 = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); + + /** + * Class that represents an OpenPGP signature. + */ + class Signature { + /** + * @param {PacketList} packetlist - The signature packets + */ + constructor(packetlist) { + this.packets = packetlist || new PacketList(); + } + + /** + * Returns binary encoded signature + * @returns {ReadableStream} Binary signature. + */ + write() { + return this.packets.write(); + } + + /** + * Returns ASCII armored text of signature + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {ReadableStream} ASCII armor. + */ + armor(config = defaultConfig) { + return armor(enums.armor.signature, this.write(), undefined, undefined, undefined, config); + } + + /** + * Returns an array of KeyIDs of all of the issuers who created this signature + * @returns {Array} The Key IDs of the signing keys + */ + getSigningKeyIDs() { + return this.packets.map(packet => packet.issuerKeyID); + } + } + + /** + * reads an (optionally armored) OpenPGP signature and returns a signature object + * @param {Object} options + * @param {String} [options.armoredSignature] - Armored signature to be parsed + * @param {Uint8Array} [options.binarySignature] - Binary signature to be parsed + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} New signature object. + * @async + * @static + */ + async function readSignature({ armoredSignature, binarySignature, config, ...rest }) { + config = { ...defaultConfig, ...config }; + let input = armoredSignature || binarySignature; + if (!input) { + throw new Error('readSignature: must pass options object containing `armoredSignature` or `binarySignature`'); + } + if (armoredSignature && !util.isString(armoredSignature)) { + throw new Error('readSignature: options.armoredSignature must be a string'); + } + if (binarySignature && !util.isUint8Array(binarySignature)) { + throw new Error('readSignature: options.binarySignature must be a Uint8Array'); + } + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + if (armoredSignature) { + const { type, data } = await unarmor(input, config); + if (type !== enums.armor.signature) { + throw new Error('Armored text not of type signature'); + } + input = data; + } + const packetlist = await PacketList.fromBinary(input, allowedPackets$4, config); + return new Signature(packetlist); + } + + /** + * @fileoverview Provides helpers methods for key module + * @module key/helper + * @private + */ + + async function generateSecretSubkey(options, config) { + const secretSubkeyPacket = new SecretSubkeyPacket(options.date, config); + secretSubkeyPacket.packets = null; + secretSubkeyPacket.algorithm = enums.write(enums.publicKey, options.algorithm); + await secretSubkeyPacket.generate(options.rsaBits, options.curve); + await secretSubkeyPacket.computeFingerprintAndKeyID(); + return secretSubkeyPacket; + } + + async function generateSecretKey(options, config) { + const secretKeyPacket = new SecretKeyPacket(options.date, config); + secretKeyPacket.packets = null; + secretKeyPacket.algorithm = enums.write(enums.publicKey, options.algorithm); + await secretKeyPacket.generate(options.rsaBits, options.curve, options.config); + await secretKeyPacket.computeFingerprintAndKeyID(); + return secretKeyPacket; + } + + /** + * Returns the valid and non-expired signature that has the latest creation date, while ignoring signatures created in the future. + * @param {Array} signatures - List of signatures + * @param {PublicKeyPacket|PublicSubkeyPacket} publicKey - Public key packet to verify the signature + * @param {Date} date - Use the given date instead of the current time + * @param {Object} config - full configuration + * @returns {Promise} The latest valid signature. + * @async + */ + async function getLatestValidSignature(signatures, publicKey, signatureType, dataToVerify, date = new Date(), config) { + let latestValid; + let exception; + for (let i = signatures.length - 1; i >= 0; i--) { + try { + if ( + (!latestValid || signatures[i].created >= latestValid.created) + ) { + await signatures[i].verify(publicKey, signatureType, dataToVerify, date, undefined, config); + latestValid = signatures[i]; + } + } catch (e) { + exception = e; + } + } + if (!latestValid) { + throw util.wrapError( + `Could not find valid ${enums.read(enums.signature, signatureType)} signature in key ${publicKey.getKeyID().toHex()}` + .replace('certGeneric ', 'self-') + .replace(/([a-z])([A-Z])/g, (_, $1, $2) => $1 + ' ' + $2.toLowerCase()) + , exception); + } + return latestValid; + } + + function isDataExpired(keyPacket, signature, date = new Date()) { + const normDate = util.normalizeDate(date); + if (normDate !== null) { + const expirationTime = getKeyExpirationTime(keyPacket, signature); + return !(keyPacket.created <= normDate && normDate < expirationTime); + } + return false; + } + + /** + * Create Binding signature to the key according to the {@link https://tools.ietf.org/html/rfc4880#section-5.2.1} + * @param {SecretSubkeyPacket} subkey - Subkey key packet + * @param {SecretKeyPacket} primaryKey - Primary key packet + * @param {Object} options + * @param {Object} config - Full configuration + */ + async function createBindingSignature(subkey, primaryKey, options, config) { + const dataToSign = {}; + dataToSign.key = primaryKey; + dataToSign.bind = subkey; + const subkeySignaturePacket = new SignaturePacket(); + subkeySignaturePacket.signatureType = enums.signature.subkeyBinding; + subkeySignaturePacket.publicKeyAlgorithm = primaryKey.algorithm; + subkeySignaturePacket.hashAlgorithm = await getPreferredHashAlgo$1(null, subkey, undefined, undefined, config); + if (options.sign) { + subkeySignaturePacket.keyFlags = [enums.keyFlags.signData]; + subkeySignaturePacket.embeddedSignature = await createSignaturePacket(dataToSign, null, subkey, { + signatureType: enums.signature.keyBinding + }, options.date, undefined, undefined, config); + } else { + subkeySignaturePacket.keyFlags = [enums.keyFlags.encryptCommunication | enums.keyFlags.encryptStorage]; + } + if (options.keyExpirationTime > 0) { + subkeySignaturePacket.keyExpirationTime = options.keyExpirationTime; + subkeySignaturePacket.keyNeverExpires = false; + } + await subkeySignaturePacket.sign(primaryKey, dataToSign, options.date); + return subkeySignaturePacket; + } + + /** + * Returns the preferred signature hash algorithm of a key + * @param {Key} [key] - The key to get preferences from + * @param {SecretKeyPacket|SecretSubkeyPacket} keyPacket - key packet used for signing + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} [userID] - User ID + * @param {Object} config - full configuration + * @returns {Promise} + * @async + */ + async function getPreferredHashAlgo$1(key, keyPacket, date = new Date(), userID = {}, config) { + let hashAlgo = config.preferredHashAlgorithm; + let prefAlgo = hashAlgo; + if (key) { + const primaryUser = await key.getPrimaryUser(date, userID, config); + if (primaryUser.selfCertification.preferredHashAlgorithms) { + [prefAlgo] = primaryUser.selfCertification.preferredHashAlgorithms; + hashAlgo = mod.hash.getHashByteLength(hashAlgo) <= mod.hash.getHashByteLength(prefAlgo) ? + prefAlgo : hashAlgo; + } + } + switch (Object.getPrototypeOf(keyPacket)) { + case SecretKeyPacket.prototype: + case PublicKeyPacket.prototype: + case SecretSubkeyPacket.prototype: + case PublicSubkeyPacket.prototype: + switch (keyPacket.algorithm) { + case enums.publicKey.ecdh: + case enums.publicKey.ecdsa: + case enums.publicKey.eddsa: + prefAlgo = mod.publicKey.elliptic.getPreferredHashAlgo(keyPacket.publicParams.oid); + } + } + return mod.hash.getHashByteLength(hashAlgo) <= mod.hash.getHashByteLength(prefAlgo) ? + prefAlgo : hashAlgo; + } + + /** + * Returns the preferred symmetric/aead/compression algorithm for a set of keys + * @param {'symmetric'|'aead'|'compression'} type - Type of preference to return + * @param {Array} [keys] - Set of keys + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Array} [userIDs] - User IDs + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} Preferred algorithm + * @async + */ + async function getPreferredAlgo(type, keys = [], date = new Date(), userIDs = [], config = defaultConfig) { + const defaultAlgo = { // these are all must-implement in rfc4880bis + 'symmetric': enums.symmetric.aes128, + 'aead': enums.aead.eax, + 'compression': enums.compression.uncompressed + }[type]; + const preferredSenderAlgo = { + 'symmetric': config.preferredSymmetricAlgorithm, + 'aead': config.preferredAEADAlgorithm, + 'compression': config.preferredCompressionAlgorithm + }[type]; + const prefPropertyName = { + 'symmetric': 'preferredSymmetricAlgorithms', + 'aead': 'preferredAEADAlgorithms', + 'compression': 'preferredCompressionAlgorithms' + }[type]; + + // if preferredSenderAlgo appears in the prefs of all recipients, we pick it + // otherwise we use the default algo + // if no keys are available, preferredSenderAlgo is returned + const senderAlgoSupport = await Promise.all(keys.map(async function(key, i) { + const primaryUser = await key.getPrimaryUser(date, userIDs[i], config); + const recipientPrefs = primaryUser.selfCertification[prefPropertyName]; + return !!recipientPrefs && recipientPrefs.indexOf(preferredSenderAlgo) >= 0; + })); + return senderAlgoSupport.every(Boolean) ? preferredSenderAlgo : defaultAlgo; + } + + /** + * Create signature packet + * @param {Object} dataToSign - Contains packets to be signed + * @param {PrivateKey} privateKey - key to get preferences from + * @param {SecretKeyPacket| + * SecretSubkeyPacket} signingKeyPacket secret key packet for signing + * @param {Object} [signatureProperties] - Properties to write on the signature packet before signing + * @param {Date} [date] - Override the creationtime of the signature + * @param {Object} [userID] - User ID + * @param {Object} [detached] - Whether to create a detached signature packet + * @param {Object} config - full configuration + * @returns {Promise} Signature packet. + */ + async function createSignaturePacket(dataToSign, privateKey, signingKeyPacket, signatureProperties, date, userID, detached = false, config) { + if (signingKeyPacket.isDummy()) { + throw new Error('Cannot sign with a gnu-dummy key.'); + } + if (!signingKeyPacket.isDecrypted()) { + throw new Error('Signing key is not decrypted.'); + } + const signaturePacket = new SignaturePacket(); + Object.assign(signaturePacket, signatureProperties); + signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm; + signaturePacket.hashAlgorithm = await getPreferredHashAlgo$1(privateKey, signingKeyPacket, date, userID, config); + await signaturePacket.sign(signingKeyPacket, dataToSign, date, detached); + return signaturePacket; + } + + /** + * Merges signatures from source[attr] to dest[attr] + * @param {Object} source + * @param {Object} dest + * @param {String} attr + * @param {Date} [date] - date to use for signature expiration check, instead of the current time + * @param {Function} [checkFn] - signature only merged if true + */ + async function mergeSignatures(source, dest, attr, date = new Date(), checkFn) { + source = source[attr]; + if (source) { + if (!dest[attr].length) { + dest[attr] = source; + } else { + await Promise.all(source.map(async function(sourceSig) { + if (!sourceSig.isExpired(date) && (!checkFn || await checkFn(sourceSig)) && + !dest[attr].some(function(destSig) { + return util.equalsUint8Array(destSig.writeParams(), sourceSig.writeParams()); + })) { + dest[attr].push(sourceSig); + } + })); + } + } + } + + /** + * Checks if a given certificate or binding signature is revoked + * @param {SecretKeyPacket| + * PublicKeyPacket} primaryKey The primary key packet + * @param {Object} dataToVerify - The data to check + * @param {Array} revocations - The revocation signatures to check + * @param {SignaturePacket} signature - The certificate or signature to check + * @param {PublicSubkeyPacket| + * SecretSubkeyPacket| + * PublicKeyPacket| + * SecretKeyPacket} key, optional The key packet to verify the signature, instead of the primary key + * @param {Date} date - Use the given date instead of the current time + * @param {Object} config - Full configuration + * @returns {Promise} True if the signature revokes the data. + * @async + */ + async function isDataRevoked(primaryKey, signatureType, dataToVerify, revocations, signature, key, date = new Date(), config) { + key = key || primaryKey; + const revocationKeyIDs = []; + await Promise.all(revocations.map(async function(revocationSignature) { + try { + if ( + // Note: a third-party revocation signature could legitimately revoke a + // self-signature if the signature has an authorized revocation key. + // However, we don't support passing authorized revocation keys, nor + // verifying such revocation signatures. Instead, we indicate an error + // when parsing a key with an authorized revocation key, and ignore + // third-party revocation signatures here. (It could also be revoking a + // third-party key certification, which should only affect + // `verifyAllCertifications`.) + !signature || revocationSignature.issuerKeyID.equals(signature.issuerKeyID) + ) { + await revocationSignature.verify( + key, signatureType, dataToVerify, config.revocationsExpire ? date : null, false, config + ); + + // TODO get an identifier of the revoked object instead + revocationKeyIDs.push(revocationSignature.issuerKeyID); + } + } catch (e) {} + })); + // TODO further verify that this is the signature that should be revoked + if (signature) { + signature.revoked = revocationKeyIDs.some(keyID => keyID.equals(signature.issuerKeyID)) ? true : + signature.revoked || false; + return signature.revoked; + } + return revocationKeyIDs.length > 0; + } + + /** + * Returns key expiration time based on the given certification signature. + * The expiration time of the signature is ignored. + * @param {PublicSubkeyPacket|PublicKeyPacket} keyPacket - key to check + * @param {SignaturePacket} signature - signature to process + * @returns {Date|Infinity} expiration time or infinity if the key does not expire + */ + function getKeyExpirationTime(keyPacket, signature) { + let expirationTime; + // check V4 expiration time + if (signature.keyNeverExpires === false) { + expirationTime = keyPacket.created.getTime() + signature.keyExpirationTime * 1000; + } + return expirationTime ? new Date(expirationTime) : Infinity; + } + + /** + * Returns whether aead is supported by all keys in the set + * @param {Array} keys - Set of keys + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Array} [userIDs] - User IDs + * @param {Object} config - full configuration + * @returns {Promise} + * @async + */ + async function isAEADSupported(keys, date = new Date(), userIDs = [], config = defaultConfig) { + let supported = true; + // TODO replace when Promise.some or Promise.any are implemented + await Promise.all(keys.map(async function(key, i) { + const primaryUser = await key.getPrimaryUser(date, userIDs[i], config); + if (!primaryUser.selfCertification.features || + !(primaryUser.selfCertification.features[0] & enums.features.aead)) { + supported = false; + } + })); + return supported; + } + + function sanitizeKeyOptions(options, subkeyDefaults = {}) { + options.type = options.type || subkeyDefaults.type; + options.curve = options.curve || subkeyDefaults.curve; + options.rsaBits = options.rsaBits || subkeyDefaults.rsaBits; + options.keyExpirationTime = options.keyExpirationTime !== undefined ? options.keyExpirationTime : subkeyDefaults.keyExpirationTime; + options.passphrase = util.isString(options.passphrase) ? options.passphrase : subkeyDefaults.passphrase; + options.date = options.date || subkeyDefaults.date; + + options.sign = options.sign || false; + + switch (options.type) { + case 'ecc': + try { + options.curve = enums.write(enums.curve, options.curve); + } catch (e) { + throw new Error('Invalid curve'); + } + if (options.curve === enums.curve.ed25519 || options.curve === enums.curve.curve25519) { + options.curve = options.sign ? enums.curve.ed25519 : enums.curve.curve25519; + } + if (options.sign) { + options.algorithm = options.curve === enums.curve.ed25519 ? enums.publicKey.eddsa : enums.publicKey.ecdsa; + } else { + options.algorithm = enums.publicKey.ecdh; + } + break; + case 'rsa': + options.algorithm = enums.publicKey.rsaEncryptSign; + break; + default: + throw new Error(`Unsupported key type ${options.type}`); + } + return options; + } + + function isValidSigningKeyPacket(keyPacket, signature) { + const keyAlgo = keyPacket.algorithm; + return keyAlgo !== enums.publicKey.rsaEncrypt && + keyAlgo !== enums.publicKey.elgamal && + keyAlgo !== enums.publicKey.ecdh && + (!signature.keyFlags || + (signature.keyFlags[0] & enums.keyFlags.signData) !== 0); + } + + function isValidEncryptionKeyPacket(keyPacket, signature) { + const keyAlgo = keyPacket.algorithm; + return keyAlgo !== enums.publicKey.dsa && + keyAlgo !== enums.publicKey.rsaSign && + keyAlgo !== enums.publicKey.ecdsa && + keyAlgo !== enums.publicKey.eddsa && + (!signature.keyFlags || + (signature.keyFlags[0] & enums.keyFlags.encryptCommunication) !== 0 || + (signature.keyFlags[0] & enums.keyFlags.encryptStorage) !== 0); + } + + function isValidDecryptionKeyPacket(signature, config) { + if (config.allowInsecureDecryptionWithSigningKeys) { + // This is only relevant for RSA keys, all other signing algorithms cannot decrypt + return true; + } + + return !signature.keyFlags || + (signature.keyFlags[0] & enums.keyFlags.encryptCommunication) !== 0 || + (signature.keyFlags[0] & enums.keyFlags.encryptStorage) !== 0; + } + + /** + * Check key against blacklisted algorithms and minimum strength requirements. + * @param {SecretKeyPacket|PublicKeyPacket| + * SecretSubkeyPacket|PublicSubkeyPacket} keyPacket + * @param {Config} config + * @throws {Error} if the key packet does not meet the requirements + */ + function checkKeyRequirements(keyPacket, config) { + const keyAlgo = enums.write(enums.publicKey, keyPacket.algorithm); + const algoInfo = keyPacket.getAlgorithmInfo(); + if (config.rejectPublicKeyAlgorithms.has(keyAlgo)) { + throw new Error(`${algoInfo.algorithm} keys are considered too weak.`); + } + switch (keyAlgo) { + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaSign: + case enums.publicKey.rsaEncrypt: + if (algoInfo.bits < config.minRSABits) { + throw new Error(`RSA keys shorter than ${config.minRSABits} bits are considered too weak.`); + } + break; + case enums.publicKey.ecdsa: + case enums.publicKey.eddsa: + case enums.publicKey.ecdh: + if (config.rejectCurves.has(algoInfo.curve)) { + throw new Error(`Support for ${algoInfo.algorithm} keys using curve ${algoInfo.curve} is disabled.`); + } + break; + } + } + + /** + * @module key/User + * @private + */ + + /** + * Class that represents an user ID or attribute packet and the relevant signatures. + * @param {UserIDPacket|UserAttributePacket} userPacket - packet containing the user info + * @param {Key} mainKey - reference to main Key object containing the primary key and subkeys that the user is associated with + */ + class User { + constructor(userPacket, mainKey) { + this.userID = userPacket.constructor.tag === enums.packet.userID ? userPacket : null; + this.userAttribute = userPacket.constructor.tag === enums.packet.userAttribute ? userPacket : null; + this.selfCertifications = []; + this.otherCertifications = []; + this.revocationSignatures = []; + this.mainKey = mainKey; + } + + /** + * Transforms structured user data to packetlist + * @returns {PacketList} + */ + toPacketList() { + const packetlist = new PacketList(); + packetlist.push(this.userID || this.userAttribute); + packetlist.push(...this.revocationSignatures); + packetlist.push(...this.selfCertifications); + packetlist.push(...this.otherCertifications); + return packetlist; + } + + /** + * Shallow clone + * @returns {User} + */ + clone() { + const user = new User(this.userID || this.userAttribute, this.mainKey); + user.selfCertifications = [...this.selfCertifications]; + user.otherCertifications = [...this.otherCertifications]; + user.revocationSignatures = [...this.revocationSignatures]; + return user; + } + + /** + * Generate third-party certifications over this user and its primary key + * @param {Array} signingKeys - Decrypted private keys for signing + * @param {Date} [date] - Date to use as creation date of the certificate, instead of the current time + * @param {Object} config - Full configuration + * @returns {Promise} New user with new certifications. + * @async + */ + async certify(signingKeys, date, config) { + const primaryKey = this.mainKey.keyPacket; + const dataToSign = { + userID: this.userID, + userAttribute: this.userAttribute, + key: primaryKey + }; + const user = new User(dataToSign.userID || dataToSign.userAttribute, this.mainKey); + user.otherCertifications = await Promise.all(signingKeys.map(async function(privateKey) { + if (!privateKey.isPrivate()) { + throw new Error('Need private key for signing'); + } + if (privateKey.hasSameFingerprintAs(primaryKey)) { + throw new Error("The user's own key can only be used for self-certifications"); + } + const signingKey = await privateKey.getSigningKey(undefined, date, undefined, config); + return createSignaturePacket(dataToSign, privateKey, signingKey.keyPacket, { + // Most OpenPGP implementations use generic certification (0x10) + signatureType: enums.signature.certGeneric, + keyFlags: [enums.keyFlags.certifyKeys | enums.keyFlags.signData] + }, date, undefined, undefined, config); + })); + await user.update(this, date, config); + return user; + } + + /** + * Checks if a given certificate of the user is revoked + * @param {SignaturePacket} certificate - The certificate to verify + * @param {PublicSubkeyPacket| + * SecretSubkeyPacket| + * PublicKeyPacket| + * SecretKeyPacket} [keyPacket] The key packet to verify the signature, instead of the primary key + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} config - Full configuration + * @returns {Promise} True if the certificate is revoked. + * @async + */ + async isRevoked(certificate, keyPacket, date = new Date(), config) { + const primaryKey = this.mainKey.keyPacket; + return isDataRevoked(primaryKey, enums.signature.certRevocation, { + key: primaryKey, + userID: this.userID, + userAttribute: this.userAttribute + }, this.revocationSignatures, certificate, keyPacket, date, config); + } + + /** + * Verifies the user certificate. + * @param {SignaturePacket} certificate - A certificate of this user + * @param {Array} verificationKeys - Array of keys to verify certificate signatures + * @param {Date} [date] - Use the given date instead of the current time + * @param {Object} config - Full configuration + * @returns {Promise} true if the certificate could be verified, or null if the verification keys do not correspond to the certificate + * @throws if the user certificate is invalid. + * @async + */ + async verifyCertificate(certificate, verificationKeys, date = new Date(), config) { + const that = this; + const primaryKey = this.mainKey.keyPacket; + const dataToVerify = { + userID: this.userID, + userAttribute: this.userAttribute, + key: primaryKey + }; + const { issuerKeyID } = certificate; + const issuerKeys = verificationKeys.filter(key => key.getKeys(issuerKeyID).length > 0); + if (issuerKeys.length === 0) { + return null; + } + await Promise.all(issuerKeys.map(async key => { + const signingKey = await key.getSigningKey(issuerKeyID, certificate.created, undefined, config); + if (certificate.revoked || await that.isRevoked(certificate, signingKey.keyPacket, date, config)) { + throw new Error('User certificate is revoked'); + } + try { + await certificate.verify(signingKey.keyPacket, enums.signature.certGeneric, dataToVerify, date, undefined, config); + } catch (e) { + throw util.wrapError('User certificate is invalid', e); + } + })); + return true; + } + + /** + * Verifies all user certificates + * @param {Array} verificationKeys - Array of keys to verify certificate signatures + * @param {Date} [date] - Use the given date instead of the current time + * @param {Object} config - Full configuration + * @returns {Promise>} List of signer's keyID and validity of signature. + * Signature validity is null if the verification keys do not correspond to the certificate. + * @async + */ + async verifyAllCertifications(verificationKeys, date = new Date(), config) { + const that = this; + const certifications = this.selfCertifications.concat(this.otherCertifications); + return Promise.all(certifications.map(async certification => ({ + keyID: certification.issuerKeyID, + valid: await that.verifyCertificate(certification, verificationKeys, date, config).catch(() => false) + }))); + } + + /** + * Verify User. Checks for existence of self signatures, revocation signatures + * and validity of self signature. + * @param {Date} date - Use the given date instead of the current time + * @param {Object} config - Full configuration + * @returns {Promise} Status of user. + * @throws {Error} if there are no valid self signatures. + * @async + */ + async verify(date = new Date(), config) { + if (!this.selfCertifications.length) { + throw new Error('No self-certifications found'); + } + const that = this; + const primaryKey = this.mainKey.keyPacket; + const dataToVerify = { + userID: this.userID, + userAttribute: this.userAttribute, + key: primaryKey + }; + // TODO replace when Promise.some or Promise.any are implemented + let exception; + for (let i = this.selfCertifications.length - 1; i >= 0; i--) { + try { + const selfCertification = this.selfCertifications[i]; + if (selfCertification.revoked || await that.isRevoked(selfCertification, undefined, date, config)) { + throw new Error('Self-certification is revoked'); + } + try { + await selfCertification.verify(primaryKey, enums.signature.certGeneric, dataToVerify, date, undefined, config); + } catch (e) { + throw util.wrapError('Self-certification is invalid', e); + } + return true; + } catch (e) { + exception = e; + } + } + throw exception; + } + + /** + * Update user with new components from specified user + * @param {User} sourceUser - Source user to merge + * @param {Date} date - Date to verify the validity of signatures + * @param {Object} config - Full configuration + * @returns {Promise} + * @async + */ + async update(sourceUser, date, config) { + const primaryKey = this.mainKey.keyPacket; + const dataToVerify = { + userID: this.userID, + userAttribute: this.userAttribute, + key: primaryKey + }; + // self signatures + await mergeSignatures(sourceUser, this, 'selfCertifications', date, async function(srcSelfSig) { + try { + await srcSelfSig.verify(primaryKey, enums.signature.certGeneric, dataToVerify, date, false, config); + return true; + } catch (e) { + return false; + } + }); + // other signatures + await mergeSignatures(sourceUser, this, 'otherCertifications', date); + // revocation signatures + await mergeSignatures(sourceUser, this, 'revocationSignatures', date, function(srcRevSig) { + return isDataRevoked(primaryKey, enums.signature.certRevocation, dataToVerify, [srcRevSig], undefined, undefined, date, config); + }); + } + } + + /** + * @module key/Subkey + * @private + */ + + /** + * Class that represents a subkey packet and the relevant signatures. + * @borrows PublicSubkeyPacket#getKeyID as Subkey#getKeyID + * @borrows PublicSubkeyPacket#getFingerprint as Subkey#getFingerprint + * @borrows PublicSubkeyPacket#hasSameFingerprintAs as Subkey#hasSameFingerprintAs + * @borrows PublicSubkeyPacket#getAlgorithmInfo as Subkey#getAlgorithmInfo + * @borrows PublicSubkeyPacket#getCreationTime as Subkey#getCreationTime + * @borrows PublicSubkeyPacket#isDecrypted as Subkey#isDecrypted + */ + class Subkey { + /** + * @param {SecretSubkeyPacket|PublicSubkeyPacket} subkeyPacket - subkey packet to hold in the Subkey + * @param {Key} mainKey - reference to main Key object, containing the primary key packet corresponding to the subkey + */ + constructor(subkeyPacket, mainKey) { + this.keyPacket = subkeyPacket; + this.bindingSignatures = []; + this.revocationSignatures = []; + this.mainKey = mainKey; + } + + /** + * Transforms structured subkey data to packetlist + * @returns {PacketList} + */ + toPacketList() { + const packetlist = new PacketList(); + packetlist.push(this.keyPacket); + packetlist.push(...this.revocationSignatures); + packetlist.push(...this.bindingSignatures); + return packetlist; + } + + /** + * Shallow clone + * @return {Subkey} + */ + clone() { + const subkey = new Subkey(this.keyPacket, this.mainKey); + subkey.bindingSignatures = [...this.bindingSignatures]; + subkey.revocationSignatures = [...this.revocationSignatures]; + return subkey; + } + + /** + * Checks if a binding signature of a subkey is revoked + * @param {SignaturePacket} signature - The binding signature to verify + * @param {PublicSubkeyPacket| + * SecretSubkeyPacket| + * PublicKeyPacket| + * SecretKeyPacket} key, optional The key to verify the signature + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} True if the binding signature is revoked. + * @async + */ + async isRevoked(signature, key, date = new Date(), config = defaultConfig) { + const primaryKey = this.mainKey.keyPacket; + return isDataRevoked( + primaryKey, enums.signature.subkeyRevocation, { + key: primaryKey, + bind: this.keyPacket + }, this.revocationSignatures, signature, key, date, config + ); + } + + /** + * Verify subkey. Checks for revocation signatures, expiration time + * and valid binding signature. + * @param {Date} date - Use the given date instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} + * @throws {Error} if the subkey is invalid. + * @async + */ + async verify(date = new Date(), config = defaultConfig) { + const primaryKey = this.mainKey.keyPacket; + const dataToVerify = { key: primaryKey, bind: this.keyPacket }; + // check subkey binding signatures + const bindingSignature = await getLatestValidSignature(this.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); + // check binding signature is not revoked + if (bindingSignature.revoked || await this.isRevoked(bindingSignature, null, date, config)) { + throw new Error('Subkey is revoked'); + } + // check for expiration time + if (isDataExpired(this.keyPacket, bindingSignature, date)) { + throw new Error('Subkey is expired'); + } + return bindingSignature; + } + + /** + * Returns the expiration time of the subkey or Infinity if key does not expire. + * Returns null if the subkey is invalid. + * @param {Date} date - Use the given date instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} + * @async + */ + async getExpirationTime(date = new Date(), config = defaultConfig) { + const primaryKey = this.mainKey.keyPacket; + const dataToVerify = { key: primaryKey, bind: this.keyPacket }; + let bindingSignature; + try { + bindingSignature = await getLatestValidSignature(this.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); + } catch (e) { + return null; + } + const keyExpiry = getKeyExpirationTime(this.keyPacket, bindingSignature); + const sigExpiry = bindingSignature.getExpirationTime(); + return keyExpiry < sigExpiry ? keyExpiry : sigExpiry; + } + + /** + * Update subkey with new components from specified subkey + * @param {Subkey} subkey - Source subkey to merge + * @param {Date} [date] - Date to verify validity of signatures + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if update failed + * @async + */ + async update(subkey, date = new Date(), config = defaultConfig) { + const primaryKey = this.mainKey.keyPacket; + if (!this.hasSameFingerprintAs(subkey)) { + throw new Error('Subkey update method: fingerprints of subkeys not equal'); + } + // key packet + if (this.keyPacket.constructor.tag === enums.packet.publicSubkey && + subkey.keyPacket.constructor.tag === enums.packet.secretSubkey) { + this.keyPacket = subkey.keyPacket; + } + // update missing binding signatures + const that = this; + const dataToVerify = { key: primaryKey, bind: that.keyPacket }; + await mergeSignatures(subkey, this, 'bindingSignatures', date, async function(srcBindSig) { + for (let i = 0; i < that.bindingSignatures.length; i++) { + if (that.bindingSignatures[i].issuerKeyID.equals(srcBindSig.issuerKeyID)) { + if (srcBindSig.created > that.bindingSignatures[i].created) { + that.bindingSignatures[i] = srcBindSig; + } + return false; + } + } + try { + await srcBindSig.verify(primaryKey, enums.signature.subkeyBinding, dataToVerify, date, undefined, config); + return true; + } catch (e) { + return false; + } + }); + // revocation signatures + await mergeSignatures(subkey, this, 'revocationSignatures', date, function(srcRevSig) { + return isDataRevoked(primaryKey, enums.signature.subkeyRevocation, dataToVerify, [srcRevSig], undefined, undefined, date, config); + }); + } + + /** + * Revokes the subkey + * @param {SecretKeyPacket} primaryKey - decrypted private primary key for revocation + * @param {Object} reasonForRevocation - optional, object indicating the reason for revocation + * @param {module:enums.reasonForRevocation} reasonForRevocation.flag optional, flag indicating the reason for revocation + * @param {String} reasonForRevocation.string optional, string explaining the reason for revocation + * @param {Date} date - optional, override the creationtime of the revocation signature + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New subkey with revocation signature. + * @async + */ + async revoke( + primaryKey, + { + flag: reasonForRevocationFlag = enums.reasonForRevocation.noReason, + string: reasonForRevocationString = '' + } = {}, + date = new Date(), + config = defaultConfig + ) { + const dataToSign = { key: primaryKey, bind: this.keyPacket }; + const subkey = new Subkey(this.keyPacket, this.mainKey); + subkey.revocationSignatures.push(await createSignaturePacket(dataToSign, null, primaryKey, { + signatureType: enums.signature.subkeyRevocation, + reasonForRevocationFlag: enums.write(enums.reasonForRevocation, reasonForRevocationFlag), + reasonForRevocationString + }, date, undefined, false, config)); + await subkey.update(this); + return subkey; + } + + hasSameFingerprintAs(other) { + return this.keyPacket.hasSameFingerprintAs(other.keyPacket || other); + } + } + + ['getKeyID', 'getFingerprint', 'getAlgorithmInfo', 'getCreationTime', 'isDecrypted'].forEach(name => { + Subkey.prototype[name] = + function() { + return this.keyPacket[name](); + }; + }); + + // GPG4Browsers - An OpenPGP implementation in javascript + + // A key revocation certificate can contain the following packets + const allowedRevocationPackets = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); + + /** + * Abstract class that represents an OpenPGP key. Must contain a primary key. + * Can contain additional subkeys, signatures, user ids, user attributes. + * @borrows PublicKeyPacket#getKeyID as Key#getKeyID + * @borrows PublicKeyPacket#getFingerprint as Key#getFingerprint + * @borrows PublicKeyPacket#hasSameFingerprintAs as Key#hasSameFingerprintAs + * @borrows PublicKeyPacket#getAlgorithmInfo as Key#getAlgorithmInfo + * @borrows PublicKeyPacket#getCreationTime as Key#getCreationTime + */ + class Key { + /** + * Transforms packetlist to structured key data + * @param {PacketList} packetlist - The packets that form a key + * @param {Set} disallowedPackets - disallowed packet tags + */ + packetListToStructure(packetlist, disallowedPackets = new Set()) { + let user; + let primaryKeyID; + let subkey; + for (const packet of packetlist) { + const tag = packet.constructor.tag; + if (disallowedPackets.has(tag)) { + throw new Error(`Unexpected packet type: ${tag}`); + } + switch (tag) { + case enums.packet.publicKey: + case enums.packet.secretKey: + if (this.keyPacket) { + throw new Error('Key block contains multiple keys'); + } + this.keyPacket = packet; + primaryKeyID = this.getKeyID(); + if (!primaryKeyID) { + throw new Error('Missing Key ID'); + } + break; + case enums.packet.userID: + case enums.packet.userAttribute: + user = new User(packet, this); + this.users.push(user); + break; + case enums.packet.publicSubkey: + case enums.packet.secretSubkey: + user = null; + subkey = new Subkey(packet, this); + this.subkeys.push(subkey); + break; + case enums.packet.signature: + switch (packet.signatureType) { + case enums.signature.certGeneric: + case enums.signature.certPersona: + case enums.signature.certCasual: + case enums.signature.certPositive: + if (!user) { + util.printDebug('Dropping certification signatures without preceding user packet'); + continue; + } + if (packet.issuerKeyID.equals(primaryKeyID)) { + user.selfCertifications.push(packet); + } else { + user.otherCertifications.push(packet); + } + break; + case enums.signature.certRevocation: + if (user) { + user.revocationSignatures.push(packet); + } else { + this.directSignatures.push(packet); + } + break; + case enums.signature.key: + this.directSignatures.push(packet); + break; + case enums.signature.subkeyBinding: + if (!subkey) { + util.printDebug('Dropping subkey binding signature without preceding subkey packet'); + continue; + } + subkey.bindingSignatures.push(packet); + break; + case enums.signature.keyRevocation: + this.revocationSignatures.push(packet); + break; + case enums.signature.subkeyRevocation: + if (!subkey) { + util.printDebug('Dropping subkey revocation signature without preceding subkey packet'); + continue; + } + subkey.revocationSignatures.push(packet); + break; + } + break; + } + } + } + + /** + * Transforms structured key data to packetlist + * @returns {PacketList} The packets that form a key. + */ + toPacketList() { + const packetlist = new PacketList(); + packetlist.push(this.keyPacket); + packetlist.push(...this.revocationSignatures); + packetlist.push(...this.directSignatures); + this.users.map(user => packetlist.push(...user.toPacketList())); + this.subkeys.map(subkey => packetlist.push(...subkey.toPacketList())); + return packetlist; + } + + /** + * Clones the key object + * @param {Boolean} [deep=false] Whether to return a deep clone + * @returns {Promise} Clone of the key. + */ + clone(deep = false) { + const key = new this.constructor(this.toPacketList()); + if (deep) { + key.getKeys().forEach(k => { + // shallow clone the key packets + k.keyPacket = Object.create( + Object.getPrototypeOf(k.keyPacket), + Object.getOwnPropertyDescriptors(k.keyPacket) + ); + if (!k.keyPacket.isDecrypted()) return; + // deep clone the private params, which are cleared during encryption + const privateParams = {}; + Object.keys(k.keyPacket.privateParams).forEach(name => { + privateParams[name] = new Uint8Array(k.keyPacket.privateParams[name]); + }); + k.keyPacket.privateParams = privateParams; + }); + } + return key; + } + + /** + * Returns an array containing all public or private subkeys matching keyID; + * If no keyID is given, returns all subkeys. + * @param {type/keyID} [keyID] - key ID to look for + * @returns {Array} array of subkeys + */ + getSubkeys(keyID = null) { + const subkeys = this.subkeys.filter(subkey => ( + !keyID || subkey.getKeyID().equals(keyID, true) + )); + return subkeys; + } + + /** + * Returns an array containing all public or private keys matching keyID. + * If no keyID is given, returns all keys, starting with the primary key. + * @param {type/keyid~KeyID} [keyID] - key ID to look for + * @returns {Array} array of keys + */ + getKeys(keyID = null) { + const keys = []; + if (!keyID || this.getKeyID().equals(keyID, true)) { + keys.push(this); + } + return keys.concat(this.getSubkeys(keyID)); + } + + /** + * Returns key IDs of all keys + * @returns {Array} + */ + getKeyIDs() { + return this.getKeys().map(key => key.getKeyID()); + } + + /** + * Returns userIDs + * @returns {Array} Array of userIDs. + */ + getUserIDs() { + return this.users.map(user => { + return user.userID ? user.userID.userID : null; + }).filter(userID => userID !== null); + } + + /** + * Returns binary encoded key + * @returns {Uint8Array} Binary key. + */ + write() { + return this.toPacketList().write(); + } + + /** + * Returns last created key or key by given keyID that is available for signing and verification + * @param {module:type/keyid~KeyID} [keyID] - key ID of a specific key to retrieve + * @param {Date} [date] - use the fiven date date to to check key validity instead of the current date + * @param {Object} [userID] - filter keys for the given user ID + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} signing key + * @throws if no valid signing key was found + * @async + */ + async getSigningKey(keyID = null, date = new Date(), userID = {}, config = defaultConfig) { + await this.verifyPrimaryKey(date, userID, config); + const primaryKey = this.keyPacket; + const subkeys = this.subkeys.slice().sort((a, b) => b.keyPacket.created - a.keyPacket.created); + let exception; + for (const subkey of subkeys) { + if (!keyID || subkey.getKeyID().equals(keyID)) { + try { + await subkey.verify(date, config); + const dataToVerify = { key: primaryKey, bind: subkey.keyPacket }; + const bindingSignature = await getLatestValidSignature( + subkey.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config + ); + if (!isValidSigningKeyPacket(subkey.keyPacket, bindingSignature)) { + continue; + } + if (!bindingSignature.embeddedSignature) { + throw new Error('Missing embedded signature'); + } + // verify embedded signature + await getLatestValidSignature( + [bindingSignature.embeddedSignature], subkey.keyPacket, enums.signature.keyBinding, dataToVerify, date, config + ); + checkKeyRequirements(subkey.keyPacket, config); + return subkey; + } catch (e) { + exception = e; + } + } + } + + try { + const primaryUser = await this.getPrimaryUser(date, userID, config); + if ((!keyID || primaryKey.getKeyID().equals(keyID)) && + isValidSigningKeyPacket(primaryKey, primaryUser.selfCertification, config)) { + checkKeyRequirements(primaryKey, config); + return this; + } + } catch (e) { + exception = e; + } + throw util.wrapError('Could not find valid signing key packet in key ' + this.getKeyID().toHex(), exception); + } + + /** + * Returns last created key or key by given keyID that is available for encryption or decryption + * @param {module:type/keyid~KeyID} [keyID] - key ID of a specific key to retrieve + * @param {Date} [date] - use the fiven date date to to check key validity instead of the current date + * @param {Object} [userID] - filter keys for the given user ID + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} encryption key + * @throws if no valid encryption key was found + * @async + */ + async getEncryptionKey(keyID, date = new Date(), userID = {}, config = defaultConfig) { + await this.verifyPrimaryKey(date, userID, config); + const primaryKey = this.keyPacket; + // V4: by convention subkeys are preferred for encryption service + const subkeys = this.subkeys.slice().sort((a, b) => b.keyPacket.created - a.keyPacket.created); + let exception; + for (const subkey of subkeys) { + if (!keyID || subkey.getKeyID().equals(keyID)) { + try { + await subkey.verify(date, config); + const dataToVerify = { key: primaryKey, bind: subkey.keyPacket }; + const bindingSignature = await getLatestValidSignature(subkey.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); + if (isValidEncryptionKeyPacket(subkey.keyPacket, bindingSignature)) { + checkKeyRequirements(subkey.keyPacket, config); + return subkey; + } + } catch (e) { + exception = e; + } + } + } + + try { + // if no valid subkey for encryption, evaluate primary key + const primaryUser = await this.getPrimaryUser(date, userID, config); + if ((!keyID || primaryKey.getKeyID().equals(keyID)) && + isValidEncryptionKeyPacket(primaryKey, primaryUser.selfCertification)) { + checkKeyRequirements(primaryKey, config); + return this; + } + } catch (e) { + exception = e; + } + throw util.wrapError('Could not find valid encryption key packet in key ' + this.getKeyID().toHex(), exception); + } + + /** + * Checks if a signature on a key is revoked + * @param {SignaturePacket} signature - The signature to verify + * @param {PublicSubkeyPacket| + * SecretSubkeyPacket| + * PublicKeyPacket| + * SecretKeyPacket} key, optional The key to verify the signature + * @param {Date} [date] - Use the given date for verification, instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} True if the certificate is revoked. + * @async + */ + async isRevoked(signature, key, date = new Date(), config = defaultConfig) { + return isDataRevoked( + this.keyPacket, enums.signature.keyRevocation, { key: this.keyPacket }, this.revocationSignatures, signature, key, date, config + ); + } + + /** + * Verify primary key. Checks for revocation signatures, expiration time + * and valid self signature. Throws if the primary key is invalid. + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} [userID] - User ID + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} If key verification failed + * @async + */ + async verifyPrimaryKey(date = new Date(), userID = {}, config = defaultConfig) { + const primaryKey = this.keyPacket; + // check for key revocation signatures + if (await this.isRevoked(null, null, date, config)) { + throw new Error('Primary key is revoked'); + } + // check for valid, unrevoked, unexpired self signature + const { selfCertification } = await this.getPrimaryUser(date, userID, config); + // check for expiration time in binding signatures + if (isDataExpired(primaryKey, selfCertification, date)) { + throw new Error('Primary key is expired'); + } + // check for expiration time in direct signatures + const directSignature = await getLatestValidSignature( + this.directSignatures, primaryKey, enums.signature.key, { key: primaryKey }, date, config + ).catch(() => {}); // invalid signatures are discarded, to avoid breaking the key + + if (directSignature && isDataExpired(primaryKey, directSignature, date)) { + throw new Error('Primary key is expired'); + } + } + + /** + * Returns the expiration date of the primary key, considering self-certifications and direct-key signatures. + * Returns `Infinity` if the key doesn't expire, or `null` if the key is revoked or invalid. + * @param {Object} [userID] - User ID to consider instead of the primary user + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} + * @async + */ + async getExpirationTime(userID, config = defaultConfig) { + let primaryKeyExpiry; + try { + const { selfCertification } = await this.getPrimaryUser(null, userID, config); + const selfSigKeyExpiry = getKeyExpirationTime(this.keyPacket, selfCertification); + const selfSigExpiry = selfCertification.getExpirationTime(); + const directSignature = await getLatestValidSignature( + this.directSignatures, this.keyPacket, enums.signature.key, { key: this.keyPacket }, null, config + ).catch(() => {}); + if (directSignature) { + const directSigKeyExpiry = getKeyExpirationTime(this.keyPacket, directSignature); + // We do not support the edge case where the direct signature expires, since it would invalidate the corresponding key expiration, + // causing a discountinous validy period for the key + primaryKeyExpiry = Math.min(selfSigKeyExpiry, selfSigExpiry, directSigKeyExpiry); + } else { + primaryKeyExpiry = selfSigKeyExpiry < selfSigExpiry ? selfSigKeyExpiry : selfSigExpiry; + } + } catch (e) { + primaryKeyExpiry = null; + } + + return util.normalizeDate(primaryKeyExpiry); + } + + + /** + * Returns primary user and most significant (latest valid) self signature + * - if multiple primary users exist, returns the one with the latest self signature + * - otherwise, returns the user with the latest self signature + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} [userID] - User ID to get instead of the primary user, if it exists + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise<{ + * user: User, + * selfCertification: SignaturePacket + * }>} The primary user and the self signature + * @async + */ + async getPrimaryUser(date = new Date(), userID = {}, config = defaultConfig) { + const primaryKey = this.keyPacket; + const users = []; + let exception; + for (let i = 0; i < this.users.length; i++) { + try { + const user = this.users[i]; + if (!user.userID) { + continue; + } + if ( + (userID.name !== undefined && user.userID.name !== userID.name) || + (userID.email !== undefined && user.userID.email !== userID.email) || + (userID.comment !== undefined && user.userID.comment !== userID.comment) + ) { + throw new Error('Could not find user that matches that user ID'); + } + const dataToVerify = { userID: user.userID, key: primaryKey }; + const selfCertification = await getLatestValidSignature(user.selfCertifications, primaryKey, enums.signature.certGeneric, dataToVerify, date, config); + users.push({ index: i, user, selfCertification }); + } catch (e) { + exception = e; + } + } + if (!users.length) { + throw exception || new Error('Could not find primary user'); + } + await Promise.all(users.map(async function (a) { + return a.user.revoked || a.user.isRevoked(a.selfCertification, null, date, config); + })); + // sort by primary user flag and signature creation time + const primaryUser = users.sort(function(a, b) { + const A = a.selfCertification; + const B = b.selfCertification; + return B.revoked - A.revoked || A.isPrimaryUserID - B.isPrimaryUserID || A.created - B.created; + }).pop(); + const { user, selfCertification: cert } = primaryUser; + if (cert.revoked || await user.isRevoked(cert, null, date, config)) { + throw new Error('Primary user is revoked'); + } + return primaryUser; + } + + /** + * Update key with new components from specified key with same key ID: + * users, subkeys, certificates are merged into the destination key, + * duplicates and expired signatures are ignored. + * + * If the source key is a private key and the destination key is public, + * a private key is returned. + * @param {Key} sourceKey - Source key to merge + * @param {Date} [date] - Date to verify validity of signatures and keys + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} updated key + * @async + */ + async update(sourceKey, date = new Date(), config = defaultConfig) { + if (!this.hasSameFingerprintAs(sourceKey)) { + throw new Error('Primary key fingerprints must be equal to update the key'); + } + if (!this.isPrivate() && sourceKey.isPrivate()) { + // check for equal subkey packets + const equal = (this.subkeys.length === sourceKey.subkeys.length) && + (this.subkeys.every(destSubkey => { + return sourceKey.subkeys.some(srcSubkey => { + return destSubkey.hasSameFingerprintAs(srcSubkey); + }); + })); + if (!equal) { + throw new Error('Cannot update public key with private key if subkeys mismatch'); + } + + return sourceKey.update(this, config); + } + // from here on, either: + // - destination key is private, source key is public + // - the keys are of the same type + // hence we don't need to convert the destination key type + const updatedKey = this.clone(); + // revocation signatures + await mergeSignatures(sourceKey, updatedKey, 'revocationSignatures', date, srcRevSig => { + return isDataRevoked(updatedKey.keyPacket, enums.signature.keyRevocation, updatedKey, [srcRevSig], null, sourceKey.keyPacket, date, config); + }); + // direct signatures + await mergeSignatures(sourceKey, updatedKey, 'directSignatures', date); + // update users + await Promise.all(sourceKey.users.map(async srcUser => { + // multiple users with the same ID/attribute are not explicitly disallowed by the spec + // hence we support them, just in case + const usersToUpdate = updatedKey.users.filter(dstUser => ( + (srcUser.userID && srcUser.userID.equals(dstUser.userID)) || + (srcUser.userAttribute && srcUser.userAttribute.equals(dstUser.userAttribute)) + )); + if (usersToUpdate.length > 0) { + await Promise.all( + usersToUpdate.map(userToUpdate => userToUpdate.update(srcUser, date, config)) + ); + } else { + const newUser = srcUser.clone(); + newUser.mainKey = updatedKey; + updatedKey.users.push(newUser); + } + })); + // update subkeys + await Promise.all(sourceKey.subkeys.map(async srcSubkey => { + // multiple subkeys with same fingerprint might be preset + const subkeysToUpdate = updatedKey.subkeys.filter(dstSubkey => ( + dstSubkey.hasSameFingerprintAs(srcSubkey) + )); + if (subkeysToUpdate.length > 0) { + await Promise.all( + subkeysToUpdate.map(subkeyToUpdate => subkeyToUpdate.update(srcSubkey, date, config)) + ); + } else { + const newSubkey = srcSubkey.clone(); + newSubkey.mainKey = updatedKey; + updatedKey.subkeys.push(newSubkey); + } + })); + + return updatedKey; + } + + /** + * Get revocation certificate from a revoked key. + * (To get a revocation certificate for an unrevoked key, call revoke() first.) + * @param {Date} date - Use the given date instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} Armored revocation certificate. + * @async + */ + async getRevocationCertificate(date = new Date(), config = defaultConfig) { + const dataToVerify = { key: this.keyPacket }; + const revocationSignature = await getLatestValidSignature(this.revocationSignatures, this.keyPacket, enums.signature.keyRevocation, dataToVerify, date, config); + const packetlist = new PacketList(); + packetlist.push(revocationSignature); + return armor(enums.armor.publicKey, packetlist.write(), null, null, 'This is a revocation certificate'); + } + + /** + * Applies a revocation certificate to a key + * This adds the first signature packet in the armored text to the key, + * if it is a valid revocation signature. + * @param {String} revocationCertificate - armored revocation certificate + * @param {Date} [date] - Date to verify the certificate + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} Revoked key. + * @async + */ + async applyRevocationCertificate(revocationCertificate, date = new Date(), config = defaultConfig) { + const input = await unarmor(revocationCertificate, config); + const packetlist = await PacketList.fromBinary(input.data, allowedRevocationPackets, config); + const revocationSignature = packetlist.findPacket(enums.packet.signature); + if (!revocationSignature || revocationSignature.signatureType !== enums.signature.keyRevocation) { + throw new Error('Could not find revocation signature packet'); + } + if (!revocationSignature.issuerKeyID.equals(this.getKeyID())) { + throw new Error('Revocation signature does not match key'); + } + try { + await revocationSignature.verify(this.keyPacket, enums.signature.keyRevocation, { key: this.keyPacket }, date, undefined, config); + } catch (e) { + throw util.wrapError('Could not verify revocation signature', e); + } + const key = this.clone(); + key.revocationSignatures.push(revocationSignature); + return key; + } + + /** + * Signs primary user of key + * @param {Array} privateKeys - decrypted private keys for signing + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} [userID] - User ID to get instead of the primary user, if it exists + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} Key with new certificate signature. + * @async + */ + async signPrimaryUser(privateKeys, date, userID, config = defaultConfig) { + const { index, user } = await this.getPrimaryUser(date, userID, config); + const userSign = await user.certify(privateKeys, date, config); + const key = this.clone(); + key.users[index] = userSign; + return key; + } + + /** + * Signs all users of key + * @param {Array} privateKeys - decrypted private keys for signing + * @param {Date} [date] - Use the given date for signing, instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} Key with new certificate signature. + * @async + */ + async signAllUsers(privateKeys, date = new Date(), config = defaultConfig) { + const key = this.clone(); + key.users = await Promise.all(this.users.map(function(user) { + return user.certify(privateKeys, date, config); + })); + return key; + } + + /** + * Verifies primary user of key + * - if no arguments are given, verifies the self certificates; + * - otherwise, verifies all certificates signed with given keys. + * @param {Array} [verificationKeys] - array of keys to verify certificate signatures, instead of the primary key + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} [userID] - User ID to get instead of the primary user, if it exists + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise>} List of signer's keyID and validity of signature. + * Signature validity is null if the verification keys do not correspond to the certificate. + * @async + */ + async verifyPrimaryUser(verificationKeys, date = new Date(), userID, config = defaultConfig) { + const primaryKey = this.keyPacket; + const { user } = await this.getPrimaryUser(date, userID, config); + const results = verificationKeys ? + await user.verifyAllCertifications(verificationKeys, date, config) : + [{ keyID: primaryKey.getKeyID(), valid: await user.verify(date, config).catch(() => false) }]; + return results; + } + + /** + * Verifies all users of key + * - if no arguments are given, verifies the self certificates; + * - otherwise, verifies all certificates signed with given keys. + * @param {Array} [verificationKeys] - array of keys to verify certificate signatures + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise>} List of userID, signer's keyID and validity of signature. + * Signature validity is null if the verification keys do not correspond to the certificate. + * @async + */ + async verifyAllUsers(verificationKeys, date = new Date(), config = defaultConfig) { + const primaryKey = this.keyPacket; + const results = []; + await Promise.all(this.users.map(async user => { + const signatures = verificationKeys ? + await user.verifyAllCertifications(verificationKeys, date, config) : + [{ keyID: primaryKey.getKeyID(), valid: await user.verify(date, config).catch(() => false) }]; + + results.push(...signatures.map( + signature => ({ + userID: user.userID.userID, + keyID: signature.keyID, + valid: signature.valid + })) + ); + })); + return results; + } + } + + ['getKeyID', 'getFingerprint', 'getAlgorithmInfo', 'getCreationTime', 'hasSameFingerprintAs'].forEach(name => { + Key.prototype[name] = + Subkey.prototype[name]; + }); + + /** + * Creates a PublicKey or PrivateKey depending on the packetlist in input + * @param {PacketList} - packets to parse + * @return {Key} parsed key + * @throws if no key packet was found + */ + function createKey(packetlist) { + for (const packet of packetlist) { + switch (packet.constructor.tag) { + case enums.packet.secretKey: + return new PrivateKey(packetlist); + case enums.packet.publicKey: + return new PublicKey(packetlist); + } + } + throw new Error('No key packet found'); + } + + // This library is free software; you can redistribute it and/or + + /** + * Class that represents an OpenPGP Public Key + */ + class PublicKey extends Key { + /** + * @param {PacketList} packetlist - The packets that form this key + */ + constructor(packetlist) { + super(); + this.keyPacket = null; + this.revocationSignatures = []; + this.directSignatures = []; + this.users = []; + this.subkeys = []; + if (packetlist) { + this.packetListToStructure(packetlist, new Set([enums.packet.secretKey, enums.packet.secretSubkey])); + if (!this.keyPacket) { + throw new Error('Invalid key: missing public-key packet'); + } + } + } + + /** + * Returns true if this is a private key + * @returns {false} + */ + isPrivate() { + return false; + } + + /** + * Returns key as public key (shallow copy) + * @returns {PublicKey} New public Key + */ + toPublic() { + return this; + } + + /** + * Returns ASCII armored text of key + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {ReadableStream} ASCII armor. + */ + armor(config = defaultConfig) { + return armor(enums.armor.publicKey, this.toPacketList().write(), undefined, undefined, undefined, config); + } + } + + /** + * Class that represents an OpenPGP Private key + */ + class PrivateKey extends PublicKey { + /** + * @param {PacketList} packetlist - The packets that form this key + */ + constructor(packetlist) { + super(); + this.packetListToStructure(packetlist, new Set([enums.packet.publicKey, enums.packet.publicSubkey])); + if (!this.keyPacket) { + throw new Error('Invalid key: missing private-key packet'); + } + } + + /** + * Returns true if this is a private key + * @returns {Boolean} + */ + isPrivate() { + return true; + } + + /** + * Returns key as public key (shallow copy) + * @returns {PublicKey} New public Key + */ + toPublic() { + const packetlist = new PacketList(); + const keyPackets = this.toPacketList(); + for (const keyPacket of keyPackets) { + switch (keyPacket.constructor.tag) { + case enums.packet.secretKey: { + const pubKeyPacket = PublicKeyPacket.fromSecretKeyPacket(keyPacket); + packetlist.push(pubKeyPacket); + break; + } + case enums.packet.secretSubkey: { + const pubSubkeyPacket = PublicSubkeyPacket.fromSecretSubkeyPacket(keyPacket); + packetlist.push(pubSubkeyPacket); + break; + } + default: + packetlist.push(keyPacket); + } + } + return new PublicKey(packetlist); + } + + /** + * Returns ASCII armored text of key + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {ReadableStream} ASCII armor. + */ + armor(config = defaultConfig) { + return armor(enums.armor.privateKey, this.toPacketList().write(), undefined, undefined, undefined, config); + } + + /** + * Returns all keys that are available for decryption, matching the keyID when given + * This is useful to retrieve keys for session key decryption + * @param {module:type/keyid~KeyID} keyID, optional + * @param {Date} date, optional + * @param {String} userID, optional + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise>} Array of decryption keys. + * @async + */ + async getDecryptionKeys(keyID, date = new Date(), userID = {}, config = defaultConfig) { + const primaryKey = this.keyPacket; + const keys = []; + for (let i = 0; i < this.subkeys.length; i++) { + if (!keyID || this.subkeys[i].getKeyID().equals(keyID, true)) { + try { + const dataToVerify = { key: primaryKey, bind: this.subkeys[i].keyPacket }; + const bindingSignature = await getLatestValidSignature(this.subkeys[i].bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); + if (isValidDecryptionKeyPacket(bindingSignature, config)) { + keys.push(this.subkeys[i]); + } + } catch (e) {} + } + } + + // evaluate primary key + const primaryUser = await this.getPrimaryUser(date, userID, config); + if ((!keyID || primaryKey.getKeyID().equals(keyID, true)) && + isValidDecryptionKeyPacket(primaryUser.selfCertification, config)) { + keys.push(this); + } + + return keys; + } + + /** + * Returns true if the primary key or any subkey is decrypted. + * A dummy key is considered encrypted. + */ + isDecrypted() { + return this.getKeys().some(({ keyPacket }) => keyPacket.isDecrypted()); + } + + /** + * Check whether the private and public primary key parameters correspond + * Together with verification of binding signatures, this guarantees key integrity + * In case of gnu-dummy primary key, it is enough to validate any signing subkeys + * otherwise all encryption subkeys are validated + * If only gnu-dummy keys are found, we cannot properly validate so we throw an error + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if validation was not successful and the key cannot be trusted + * @async + */ + async validate(config = defaultConfig) { + if (!this.isPrivate()) { + throw new Error('Cannot validate a public key'); + } + + let signingKeyPacket; + if (!this.keyPacket.isDummy()) { + signingKeyPacket = this.keyPacket; + } else { + /** + * It is enough to validate any signing keys + * since its binding signatures are also checked + */ + const signingKey = await this.getSigningKey(null, null, undefined, { ...config, rejectPublicKeyAlgorithms: new Set(), minRSABits: 0 }); + // This could again be a dummy key + if (signingKey && !signingKey.keyPacket.isDummy()) { + signingKeyPacket = signingKey.keyPacket; + } + } + + if (signingKeyPacket) { + return signingKeyPacket.validate(); + } else { + const keys = this.getKeys(); + const allDummies = keys.map(key => key.keyPacket.isDummy()).every(Boolean); + if (allDummies) { + throw new Error('Cannot validate an all-gnu-dummy key'); + } + + return Promise.all(keys.map(async key => key.keyPacket.validate())); + } + } + + /** + * Clear private key parameters + */ + clearPrivateParams() { + this.getKeys().forEach(({ keyPacket }) => { + if (keyPacket.isDecrypted()) { + keyPacket.clearPrivateParams(); + } + }); + } + + /** + * Revokes the key + * @param {Object} reasonForRevocation - optional, object indicating the reason for revocation + * @param {module:enums.reasonForRevocation} reasonForRevocation.flag optional, flag indicating the reason for revocation + * @param {String} reasonForRevocation.string optional, string explaining the reason for revocation + * @param {Date} date - optional, override the creationtime of the revocation signature + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New key with revocation signature. + * @async + */ + async revoke( + { + flag: reasonForRevocationFlag = enums.reasonForRevocation.noReason, + string: reasonForRevocationString = '' + } = {}, + date = new Date(), + config = defaultConfig + ) { + if (!this.isPrivate()) { + throw new Error('Need private key for revoking'); + } + const dataToSign = { key: this.keyPacket }; + const key = this.clone(); + key.revocationSignatures.push(await createSignaturePacket(dataToSign, null, this.keyPacket, { + signatureType: enums.signature.keyRevocation, + reasonForRevocationFlag: enums.write(enums.reasonForRevocation, reasonForRevocationFlag), + reasonForRevocationString + }, date, undefined, undefined, config)); + return key; + } + + + /** + * Generates a new OpenPGP subkey, and returns a clone of the Key object with the new subkey added. + * Supports RSA and ECC keys. Defaults to the algorithm and bit size/curve of the primary key. DSA primary keys default to RSA subkeys. + * @param {ecc|rsa} options.type The subkey algorithm: ECC or RSA + * @param {String} options.curve (optional) Elliptic curve for ECC keys + * @param {Integer} options.rsaBits (optional) Number of bits for RSA subkeys + * @param {Number} options.keyExpirationTime (optional) Number of seconds from the key creation time after which the key expires + * @param {Date} options.date (optional) Override the creation date of the key and the key signatures + * @param {Boolean} options.sign (optional) Indicates whether the subkey should sign rather than encrypt. Defaults to false + * @param {Object} options.config (optional) custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} + * @async + */ + async addSubkey(options = {}) { + const config = { ...defaultConfig, ...options.config }; + if (options.passphrase) { + throw new Error('Subkey could not be encrypted here, please encrypt whole key'); + } + if (options.rsaBits < config.minRSABits) { + throw new Error(`rsaBits should be at least ${config.minRSABits}, got: ${options.rsaBits}`); + } + const secretKeyPacket = this.keyPacket; + if (secretKeyPacket.isDummy()) { + throw new Error('Cannot add subkey to gnu-dummy primary key'); + } + if (!secretKeyPacket.isDecrypted()) { + throw new Error('Key is not decrypted'); + } + const defaultOptions = secretKeyPacket.getAlgorithmInfo(); + defaultOptions.type = defaultOptions.curve ? 'ecc' : 'rsa'; // DSA keys default to RSA + defaultOptions.rsaBits = defaultOptions.bits || 4096; + defaultOptions.curve = defaultOptions.curve || 'curve25519'; + options = sanitizeKeyOptions(options, defaultOptions); + const keyPacket = await generateSecretSubkey(options); + checkKeyRequirements(keyPacket, config); + const bindingSignature = await createBindingSignature(keyPacket, secretKeyPacket, options, config); + const packetList = this.toPacketList(); + packetList.push(keyPacket, bindingSignature); + return new PrivateKey(packetList); + } + } + + // OpenPGP.js - An OpenPGP implementation in javascript + + // A Key can contain the following packets + const allowedKeyPackets = /*#__PURE__*/ util.constructAllowedPackets([ + PublicKeyPacket, + PublicSubkeyPacket, + SecretKeyPacket, + SecretSubkeyPacket, + UserIDPacket, + UserAttributePacket, + SignaturePacket + ]); + + /** + * Generates a new OpenPGP key. Supports RSA and ECC keys. + * By default, primary and subkeys will be of same type. + * @param {ecc|rsa} options.type The primary key algorithm type: ECC or RSA + * @param {String} options.curve Elliptic curve for ECC keys + * @param {Integer} options.rsaBits Number of bits for RSA keys + * @param {Array} options.userIDs User IDs as strings or objects: 'Jo Doe ' or { name:'Jo Doe', email:'info@jo.com' } + * @param {String} options.passphrase Passphrase used to encrypt the resulting private key + * @param {Number} options.keyExpirationTime (optional) Number of seconds from the key creation time after which the key expires + * @param {Date} options.date Creation date of the key and the key signatures + * @param {Object} config - Full configuration + * @param {Array} options.subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}] + * sign parameter defaults to false, and indicates whether the subkey should sign rather than encrypt + * @returns {Promise<{{ key: PrivateKey, revocationCertificate: String }}>} + * @async + * @static + * @private + */ + async function generate$2(options, config) { + options.sign = true; // primary key is always a signing key + options = sanitizeKeyOptions(options); + options.subkeys = options.subkeys.map((subkey, index) => sanitizeKeyOptions(options.subkeys[index], options)); + let promises = [generateSecretKey(options, config)]; + promises = promises.concat(options.subkeys.map(options => generateSecretSubkey(options, config))); + const packets = await Promise.all(promises); + + const key = await wrapKeyObject(packets[0], packets.slice(1), options, config); + const revocationCertificate = await key.getRevocationCertificate(options.date, config); + key.revocationSignatures = []; + return { key, revocationCertificate }; + } + + /** + * Reformats and signs an OpenPGP key with a given User ID. Currently only supports RSA keys. + * @param {PrivateKey} options.privateKey The private key to reformat + * @param {Array} options.userIDs User IDs as strings or objects: 'Jo Doe ' or { name:'Jo Doe', email:'info@jo.com' } + * @param {String} options.passphrase Passphrase used to encrypt the resulting private key + * @param {Number} options.keyExpirationTime Number of seconds from the key creation time after which the key expires + * @param {Date} options.date Override the creation date of the key signatures + * @param {Array} options.subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}] + * @param {Object} config - Full configuration + * + * @returns {Promise<{{ key: PrivateKey, revocationCertificate: String }}>} + * @async + * @static + * @private + */ + async function reformat(options, config) { + options = sanitize(options); + const { privateKey } = options; + + if (!privateKey.isPrivate()) { + throw new Error('Cannot reformat a public key'); + } + + if (privateKey.keyPacket.isDummy()) { + throw new Error('Cannot reformat a gnu-dummy primary key'); + } + + const isDecrypted = privateKey.getKeys().every(({ keyPacket }) => keyPacket.isDecrypted()); + if (!isDecrypted) { + throw new Error('Key is not decrypted'); + } + + const secretKeyPacket = privateKey.keyPacket; + + if (!options.subkeys) { + options.subkeys = await Promise.all(privateKey.subkeys.map(async subkey => { + const secretSubkeyPacket = subkey.keyPacket; + const dataToVerify = { key: secretKeyPacket, bind: secretSubkeyPacket }; + const bindingSignature = await ( + getLatestValidSignature(subkey.bindingSignatures, secretKeyPacket, enums.signature.subkeyBinding, dataToVerify, null, config) + ).catch(() => ({})); + return { + sign: bindingSignature.keyFlags && (bindingSignature.keyFlags[0] & enums.keyFlags.signData) + }; + })); + } + + const secretSubkeyPackets = privateKey.subkeys.map(subkey => subkey.keyPacket); + if (options.subkeys.length !== secretSubkeyPackets.length) { + throw new Error('Number of subkey options does not match number of subkeys'); + } + + options.subkeys = options.subkeys.map(subkeyOptions => sanitize(subkeyOptions, options)); + + const key = await wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options, config); + const revocationCertificate = await key.getRevocationCertificate(options.date, config); + key.revocationSignatures = []; + return { key, revocationCertificate }; + + function sanitize(options, subkeyDefaults = {}) { + options.keyExpirationTime = options.keyExpirationTime || subkeyDefaults.keyExpirationTime; + options.passphrase = util.isString(options.passphrase) ? options.passphrase : subkeyDefaults.passphrase; + options.date = options.date || subkeyDefaults.date; + + return options; + } + } + + /** + * Construct PrivateKey object from the given key packets, add certification signatures and set passphrase protection + * The new key includes a revocation certificate that must be removed before returning the key, otherwise the key is considered revoked. + * @param {SecretKeyPacket} secretKeyPacket + * @param {SecretSubkeyPacket} secretSubkeyPackets + * @param {Object} options + * @param {Object} config - Full configuration + * @returns {PrivateKey} + */ + async function wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options, config) { + // set passphrase protection + if (options.passphrase) { + await secretKeyPacket.encrypt(options.passphrase, config); + } + + await Promise.all(secretSubkeyPackets.map(async function(secretSubkeyPacket, index) { + const subkeyPassphrase = options.subkeys[index].passphrase; + if (subkeyPassphrase) { + await secretSubkeyPacket.encrypt(subkeyPassphrase, config); + } + })); + + const packetlist = new PacketList(); + packetlist.push(secretKeyPacket); + + await Promise.all(options.userIDs.map(async function(userID, index) { + function createPreferredAlgos(algos, preferredAlgo) { + return [preferredAlgo, ...algos.filter(algo => algo !== preferredAlgo)]; + } + + const userIDPacket = UserIDPacket.fromObject(userID); + const dataToSign = {}; + dataToSign.userID = userIDPacket; + dataToSign.key = secretKeyPacket; + const signaturePacket = new SignaturePacket(); + signaturePacket.signatureType = enums.signature.certGeneric; + signaturePacket.publicKeyAlgorithm = secretKeyPacket.algorithm; + signaturePacket.hashAlgorithm = await getPreferredHashAlgo$1(null, secretKeyPacket, undefined, undefined, config); + signaturePacket.keyFlags = [enums.keyFlags.certifyKeys | enums.keyFlags.signData]; + signaturePacket.preferredSymmetricAlgorithms = createPreferredAlgos([ + // prefer aes256, aes128, then aes192 (no WebCrypto support: https://www.chromium.org/blink/webcrypto#TOC-AES-support) + enums.symmetric.aes256, + enums.symmetric.aes128, + enums.symmetric.aes192 + ], config.preferredSymmetricAlgorithm); + if (config.aeadProtect) { + signaturePacket.preferredAEADAlgorithms = createPreferredAlgos([ + enums.aead.eax, + enums.aead.ocb + ], config.preferredAEADAlgorithm); + } + signaturePacket.preferredHashAlgorithms = createPreferredAlgos([ + // prefer fast asm.js implementations (SHA-256) + enums.hash.sha256, + enums.hash.sha512 + ], config.preferredHashAlgorithm); + signaturePacket.preferredCompressionAlgorithms = createPreferredAlgos([ + enums.compression.zlib, + enums.compression.zip, + enums.compression.uncompressed + ], config.preferredCompressionAlgorithm); + if (index === 0) { + signaturePacket.isPrimaryUserID = true; + } + // integrity protection always enabled + signaturePacket.features = [0]; + signaturePacket.features[0] |= enums.features.modificationDetection; + if (config.aeadProtect) { + signaturePacket.features[0] |= enums.features.aead; + } + if (config.v5Keys) { + signaturePacket.features[0] |= enums.features.v5Keys; + } + if (options.keyExpirationTime > 0) { + signaturePacket.keyExpirationTime = options.keyExpirationTime; + signaturePacket.keyNeverExpires = false; + } + await signaturePacket.sign(secretKeyPacket, dataToSign, options.date); + + return { userIDPacket, signaturePacket }; + })).then(list => { + list.forEach(({ userIDPacket, signaturePacket }) => { + packetlist.push(userIDPacket); + packetlist.push(signaturePacket); + }); + }); + + await Promise.all(secretSubkeyPackets.map(async function(secretSubkeyPacket, index) { + const subkeyOptions = options.subkeys[index]; + const subkeySignaturePacket = await createBindingSignature(secretSubkeyPacket, secretKeyPacket, subkeyOptions, config); + return { secretSubkeyPacket, subkeySignaturePacket }; + })).then(packets => { + packets.forEach(({ secretSubkeyPacket, subkeySignaturePacket }) => { + packetlist.push(secretSubkeyPacket); + packetlist.push(subkeySignaturePacket); + }); + }); + + // Add revocation signature packet for creating a revocation certificate. + // This packet should be removed before returning the key. + const dataToSign = { key: secretKeyPacket }; + packetlist.push(await createSignaturePacket(dataToSign, null, secretKeyPacket, { + signatureType: enums.signature.keyRevocation, + reasonForRevocationFlag: enums.reasonForRevocation.noReason, + reasonForRevocationString: '' + }, options.date, undefined, undefined, config)); + + if (options.passphrase) { + secretKeyPacket.clearPrivateParams(); + } + + await Promise.all(secretSubkeyPackets.map(async function(secretSubkeyPacket, index) { + const subkeyPassphrase = options.subkeys[index].passphrase; + if (subkeyPassphrase) { + secretSubkeyPacket.clearPrivateParams(); + } + })); + + return new PrivateKey(packetlist); + } + + /** + * Reads an (optionally armored) OpenPGP key and returns a key object + * @param {Object} options + * @param {String} [options.armoredKey] - Armored key to be parsed + * @param {Uint8Array} [options.binaryKey] - Binary key to be parsed + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} Key object. + * @async + * @static + */ + async function readKey({ armoredKey, binaryKey, config, ...rest }) { + config = { ...defaultConfig, ...config }; + if (!armoredKey && !binaryKey) { + throw new Error('readKey: must pass options object containing `armoredKey` or `binaryKey`'); + } + if (armoredKey && !util.isString(armoredKey)) { + throw new Error('readKey: options.armoredKey must be a string'); + } + if (binaryKey && !util.isUint8Array(binaryKey)) { + throw new Error('readKey: options.binaryKey must be a Uint8Array'); + } + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + let input; + if (armoredKey) { + const { type, data } = await unarmor(armoredKey, config); + if (!(type === enums.armor.publicKey || type === enums.armor.privateKey)) { + throw new Error('Armored text not of type key'); + } + input = data; + } else { + input = binaryKey; + } + const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); + return createKey(packetlist); + } + + /** + * Reads an (optionally armored) OpenPGP private key and returns a PrivateKey object + * @param {Object} options + * @param {String} [options.armoredKey] - Armored key to be parsed + * @param {Uint8Array} [options.binaryKey] - Binary key to be parsed + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} Key object. + * @async + * @static + */ + async function readPrivateKey({ armoredKey, binaryKey, config, ...rest }) { + config = { ...defaultConfig, ...config }; + if (!armoredKey && !binaryKey) { + throw new Error('readPrivateKey: must pass options object containing `armoredKey` or `binaryKey`'); + } + if (armoredKey && !util.isString(armoredKey)) { + throw new Error('readPrivateKey: options.armoredKey must be a string'); + } + if (binaryKey && !util.isUint8Array(binaryKey)) { + throw new Error('readPrivateKey: options.binaryKey must be a Uint8Array'); + } + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + let input; + if (armoredKey) { + const { type, data } = await unarmor(armoredKey, config); + if (!(type === enums.armor.privateKey)) { + throw new Error('Armored text not of type private key'); + } + input = data; + } else { + input = binaryKey; + } + const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); + return new PrivateKey(packetlist); + } + + /** + * Reads an (optionally armored) OpenPGP key block and returns a list of key objects + * @param {Object} options + * @param {String} [options.armoredKeys] - Armored keys to be parsed + * @param {Uint8Array} [options.binaryKeys] - Binary keys to be parsed + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise>} Key objects. + * @async + * @static + */ + async function readKeys({ armoredKeys, binaryKeys, config, ...rest }) { + config = { ...defaultConfig, ...config }; + let input = armoredKeys || binaryKeys; + if (!input) { + throw new Error('readKeys: must pass options object containing `armoredKeys` or `binaryKeys`'); + } + if (armoredKeys && !util.isString(armoredKeys)) { + throw new Error('readKeys: options.armoredKeys must be a string'); + } + if (binaryKeys && !util.isUint8Array(binaryKeys)) { + throw new Error('readKeys: options.binaryKeys must be a Uint8Array'); + } + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + if (armoredKeys) { + const { type, data } = await unarmor(armoredKeys, config); + if (type !== enums.armor.publicKey && type !== enums.armor.privateKey) { + throw new Error('Armored text not of type key'); + } + input = data; + } + const keys = []; + const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); + const keyIndex = packetlist.indexOfTag(enums.packet.publicKey, enums.packet.secretKey); + if (keyIndex.length === 0) { + throw new Error('No key packet found'); + } + for (let i = 0; i < keyIndex.length; i++) { + const oneKeyList = packetlist.slice(keyIndex[i], keyIndex[i + 1]); + const newKey = createKey(oneKeyList); + keys.push(newKey); + } + return keys; + } + + /** + * Reads an (optionally armored) OpenPGP private key block and returns a list of PrivateKey objects + * @param {Object} options + * @param {String} [options.armoredKeys] - Armored keys to be parsed + * @param {Uint8Array} [options.binaryKeys] - Binary keys to be parsed + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise>} Key objects. + * @async + * @static + */ + async function readPrivateKeys({ armoredKeys, binaryKeys, config }) { + config = { ...defaultConfig, ...config }; + let input = armoredKeys || binaryKeys; + if (!input) { + throw new Error('readPrivateKeys: must pass options object containing `armoredKeys` or `binaryKeys`'); + } + if (armoredKeys && !util.isString(armoredKeys)) { + throw new Error('readPrivateKeys: options.armoredKeys must be a string'); + } + if (binaryKeys && !util.isUint8Array(binaryKeys)) { + throw new Error('readPrivateKeys: options.binaryKeys must be a Uint8Array'); + } + if (armoredKeys) { + const { type, data } = await unarmor(armoredKeys, config); + if (type !== enums.armor.privateKey) { + throw new Error('Armored text not of type private key'); + } + input = data; + } + const keys = []; + const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); + const keyIndex = packetlist.indexOfTag(enums.packet.secretKey); + if (keyIndex.length === 0) { + throw new Error('No secret key packet found'); + } + for (let i = 0; i < keyIndex.length; i++) { + const oneKeyList = packetlist.slice(keyIndex[i], keyIndex[i + 1]); + const newKey = new PrivateKey(oneKeyList); + keys.push(newKey); + } + return keys; + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + // A Message can contain the following packets + const allowedMessagePackets = /*#__PURE__*/ util.constructAllowedPackets([ + LiteralDataPacket, + CompressedDataPacket, + AEADEncryptedDataPacket, + SymEncryptedIntegrityProtectedDataPacket, + SymmetricallyEncryptedDataPacket, + PublicKeyEncryptedSessionKeyPacket, + SymEncryptedSessionKeyPacket, + OnePassSignaturePacket, + SignaturePacket + ]); + // A SKESK packet can contain the following packets + const allowedSymSessionKeyPackets = /*#__PURE__*/ util.constructAllowedPackets([SymEncryptedSessionKeyPacket]); + // A detached signature can contain the following packets + const allowedDetachedSignaturePackets = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); + + /** + * Class that represents an OpenPGP message. + * Can be an encrypted message, signed message, compressed message or literal message + * See {@link https://tools.ietf.org/html/rfc4880#section-11.3} + */ + class Message { + /** + * @param {PacketList} packetlist - The packets that form this message + */ + constructor(packetlist) { + this.packets = packetlist || new PacketList(); + } + + /** + * Returns the key IDs of the keys to which the session key is encrypted + * @returns {Array} Array of keyID objects. + */ + getEncryptionKeyIDs() { + const keyIDs = []; + const pkESKeyPacketlist = this.packets.filterByTag(enums.packet.publicKeyEncryptedSessionKey); + pkESKeyPacketlist.forEach(function(packet) { + keyIDs.push(packet.publicKeyID); + }); + return keyIDs; + } + + /** + * Returns the key IDs of the keys that signed the message + * @returns {Array} Array of keyID objects. + */ + getSigningKeyIDs() { + const msg = this.unwrapCompressed(); + // search for one pass signatures + const onePassSigList = msg.packets.filterByTag(enums.packet.onePassSignature); + if (onePassSigList.length > 0) { + return onePassSigList.map(packet => packet.issuerKeyID); + } + // if nothing found look for signature packets + const signatureList = msg.packets.filterByTag(enums.packet.signature); + return signatureList.map(packet => packet.issuerKeyID); + } + + /** + * Decrypt the message. Either a private key, a session key, or a password must be specified. + * @param {Array} [decryptionKeys] - Private keys with decrypted secret data + * @param {Array} [passwords] - Passwords used to decrypt + * @param {Array} [sessionKeys] - Session keys in the form: { data:Uint8Array, algorithm:String, [aeadAlgorithm:String] } + * @param {Date} [date] - Use the given date for key verification instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New message with decrypted content. + * @async + */ + async decrypt(decryptionKeys, passwords, sessionKeys, date = new Date(), config = defaultConfig) { + const sessionKeyObjects = sessionKeys || await this.decryptSessionKeys(decryptionKeys, passwords, date, config); + + const symEncryptedPacketlist = this.packets.filterByTag( + enums.packet.symmetricallyEncryptedData, + enums.packet.symEncryptedIntegrityProtectedData, + enums.packet.aeadEncryptedData + ); + + if (symEncryptedPacketlist.length === 0) { + return this; + } + + const symEncryptedPacket = symEncryptedPacketlist[0]; + let exception = null; + const decryptedPromise = Promise.all(sessionKeyObjects.map(async ({ algorithm: algorithmName, data }) => { + if (!util.isUint8Array(data) || !util.isString(algorithmName)) { + throw new Error('Invalid session key for decryption.'); + } + + try { + const algo = enums.write(enums.symmetric, algorithmName); + await symEncryptedPacket.decrypt(algo, data, config); + } catch (e) { + util.printDebugError(e); + exception = e; + } + })); + // We don't await stream.cancel here because it only returns when the other copy is canceled too. + cancel(symEncryptedPacket.encrypted); // Don't keep copy of encrypted data in memory. + symEncryptedPacket.encrypted = null; + await decryptedPromise; + + if (!symEncryptedPacket.packets || !symEncryptedPacket.packets.length) { + throw exception || new Error('Decryption failed.'); + } + + const resultMsg = new Message(symEncryptedPacket.packets); + symEncryptedPacket.packets = new PacketList(); // remove packets after decryption + + return resultMsg; + } + + /** + * Decrypt encrypted session keys either with private keys or passwords. + * @param {Array} [decryptionKeys] - Private keys with decrypted secret data + * @param {Array} [passwords] - Passwords used to decrypt + * @param {Date} [date] - Use the given date for key verification, instead of current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise>} array of object with potential sessionKey, algorithm pairs + * @async + */ + async decryptSessionKeys(decryptionKeys, passwords, date = new Date(), config = defaultConfig) { + let decryptedSessionKeyPackets = []; + + let exception; + if (passwords) { + const skeskPackets = this.packets.filterByTag(enums.packet.symEncryptedSessionKey); + if (skeskPackets.length === 0) { + throw new Error('No symmetrically encrypted session key packet found.'); + } + await Promise.all(passwords.map(async function(password, i) { + let packets; + if (i) { + packets = await PacketList.fromBinary(skeskPackets.write(), allowedSymSessionKeyPackets, config); + } else { + packets = skeskPackets; + } + await Promise.all(packets.map(async function(skeskPacket) { + try { + await skeskPacket.decrypt(password); + decryptedSessionKeyPackets.push(skeskPacket); + } catch (err) { + util.printDebugError(err); + } + })); + })); + } else if (decryptionKeys) { + const pkeskPackets = this.packets.filterByTag(enums.packet.publicKeyEncryptedSessionKey); + if (pkeskPackets.length === 0) { + throw new Error('No public key encrypted session key packet found.'); + } + await Promise.all(pkeskPackets.map(async function(pkeskPacket) { + await Promise.all(decryptionKeys.map(async function(decryptionKey) { + let algos = [ + enums.symmetric.aes256, // Old OpenPGP.js default fallback + enums.symmetric.aes128, // RFC4880bis fallback + enums.symmetric.tripledes, // RFC4880 fallback + enums.symmetric.cast5 // Golang OpenPGP fallback + ]; + try { + const primaryUser = await decryptionKey.getPrimaryUser(date, undefined, config); // TODO: Pass userID from somewhere. + if (primaryUser.selfCertification.preferredSymmetricAlgorithms) { + algos = algos.concat(primaryUser.selfCertification.preferredSymmetricAlgorithms); + } + } catch (e) {} + + // do not check key expiration to allow decryption of old messages + const decryptionKeyPackets = (await decryptionKey.getDecryptionKeys(pkeskPacket.publicKeyID, null, undefined, config)).map(key => key.keyPacket); + await Promise.all(decryptionKeyPackets.map(async function(decryptionKeyPacket) { + if (!decryptionKeyPacket || decryptionKeyPacket.isDummy()) { + return; + } + if (!decryptionKeyPacket.isDecrypted()) { + throw new Error('Decryption key is not decrypted.'); + } + + // To hinder CCA attacks against PKCS1, we carry out a constant-time decryption flow if the `constantTimePKCS1Decryption` config option is set. + const doConstantTimeDecryption = config.constantTimePKCS1Decryption && ( + pkeskPacket.publicKeyAlgorithm === enums.publicKey.rsaEncrypt || + pkeskPacket.publicKeyAlgorithm === enums.publicKey.rsaEncryptSign || + pkeskPacket.publicKeyAlgorithm === enums.publicKey.rsaSign || + pkeskPacket.publicKeyAlgorithm === enums.publicKey.elgamal + ); + + if (doConstantTimeDecryption) { + // The goal is to not reveal whether PKESK decryption (specifically the PKCS1 decoding step) failed, hence, we always proceed to decrypt the message, + // either with the successfully decrypted session key, or with a randomly generated one. + // Since the SEIP/AEAD's symmetric algorithm and key size are stored in the encrypted portion of the PKESK, and the execution flow cannot depend on + // the decrypted payload, we always assume the message to be encrypted with one of the symmetric algorithms specified in `config.constantTimePKCS1DecryptionSupportedSymmetricAlgorithms`: + // - If the PKESK decryption succeeds, and the session key cipher is in the supported set, then we try to decrypt the data with the decrypted session key as well as with the + // randomly generated keys of the remaining key types. + // - If the PKESK decryptions fails, or if it succeeds but support for the cipher is not enabled, then we discard the session key and try to decrypt the data using only the randomly + // generated session keys. + // NB: as a result, if the data is encrypted with a non-suported cipher, decryption will always fail. + + const serialisedPKESK = pkeskPacket.write(); // make copies to be able to decrypt the PKESK packet multiple times + await Promise.all(Array.from(config.constantTimePKCS1DecryptionSupportedSymmetricAlgorithms).map(async sessionKeyAlgorithm => { + const pkeskPacketCopy = new PublicKeyEncryptedSessionKeyPacket(); + pkeskPacketCopy.read(serialisedPKESK); + const randomSessionKey = { + sessionKeyAlgorithm, + sessionKey: await mod.generateSessionKey(sessionKeyAlgorithm) + }; + try { + await pkeskPacketCopy.decrypt(decryptionKeyPacket, randomSessionKey); + decryptedSessionKeyPackets.push(pkeskPacketCopy); + } catch (err) { + // `decrypt` can still throw some non-security-sensitive errors + util.printDebugError(err); + exception = err; + } + })); + + } else { + try { + await pkeskPacket.decrypt(decryptionKeyPacket); + if (!algos.includes(enums.write(enums.symmetric, pkeskPacket.sessionKeyAlgorithm))) { + throw new Error('A non-preferred symmetric algorithm was used.'); + } + decryptedSessionKeyPackets.push(pkeskPacket); + } catch (err) { + util.printDebugError(err); + exception = err; + } + } + })); + })); + cancel(pkeskPacket.encrypted); // Don't keep copy of encrypted data in memory. + pkeskPacket.encrypted = null; + })); + } else { + throw new Error('No key or password specified.'); + } + + if (decryptedSessionKeyPackets.length > 0) { + // Return only unique session keys + if (decryptedSessionKeyPackets.length > 1) { + const seen = new Set(); + decryptedSessionKeyPackets = decryptedSessionKeyPackets.filter(item => { + const k = item.sessionKeyAlgorithm + util.uint8ArrayToString(item.sessionKey); + if (seen.has(k)) { + return false; + } + seen.add(k); + return true; + }); + } + + return decryptedSessionKeyPackets.map(packet => ({ + data: packet.sessionKey, + algorithm: enums.read(enums.symmetric, packet.sessionKeyAlgorithm) + })); + } + throw exception || new Error('Session key decryption failed.'); + } + + /** + * Get literal data that is the body of the message + * @returns {(Uint8Array|null)} Literal body of the message as Uint8Array. + */ + getLiteralData() { + const msg = this.unwrapCompressed(); + const literal = msg.packets.findPacket(enums.packet.literalData); + return (literal && literal.getBytes()) || null; + } + + /** + * Get filename from literal data packet + * @returns {(String|null)} Filename of literal data packet as string. + */ + getFilename() { + const msg = this.unwrapCompressed(); + const literal = msg.packets.findPacket(enums.packet.literalData); + return (literal && literal.getFilename()) || null; + } + + /** + * Get literal data as text + * @returns {(String|null)} Literal body of the message interpreted as text. + */ + getText() { + const msg = this.unwrapCompressed(); + const literal = msg.packets.findPacket(enums.packet.literalData); + if (literal) { + return literal.getText(); + } + return null; + } + + /** + * Generate a new session key object, taking the algorithm preferences of the passed encryption keys into account, if any. + * @param {Array} [encryptionKeys] - Public key(s) to select algorithm preferences for + * @param {Date} [date] - Date to select algorithm preferences at + * @param {Array} [userIDs] - User IDs to select algorithm preferences for + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise<{ data: Uint8Array, algorithm: String, aeadAlgorithm: undefined|String }>} Object with session key data and algorithms. + * @async + */ + static async generateSessionKey(encryptionKeys = [], date = new Date(), userIDs = [], config = defaultConfig) { + const algo = await getPreferredAlgo('symmetric', encryptionKeys, date, userIDs, config); + const algorithmName = enums.read(enums.symmetric, algo); + const aeadAlgorithmName = config.aeadProtect && await isAEADSupported(encryptionKeys, date, userIDs, config) ? + enums.read(enums.aead, await getPreferredAlgo('aead', encryptionKeys, date, userIDs, config)) : + undefined; + + const sessionKeyData = await mod.generateSessionKey(algo); + return { data: sessionKeyData, algorithm: algorithmName, aeadAlgorithm: aeadAlgorithmName }; + } + + /** + * Encrypt the message either with public keys, passwords, or both at once. + * @param {Array} [encryptionKeys] - Public key(s) for message encryption + * @param {Array} [passwords] - Password(s) for message encryption + * @param {Object} [sessionKey] - Session key in the form: { data:Uint8Array, algorithm:String, [aeadAlgorithm:String] } + * @param {Boolean} [wildcard] - Use a key ID of 0 instead of the public key IDs + * @param {Array} [encryptionKeyIDs] - Array of key IDs to use for encryption. Each encryptionKeyIDs[i] corresponds to keys[i] + * @param {Date} [date] - Override the creation date of the literal package + * @param {Array} [userIDs] - User IDs to encrypt for, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }] + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New message with encrypted content. + * @async + */ + async encrypt(encryptionKeys, passwords, sessionKey, wildcard = false, encryptionKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { + if (sessionKey) { + if (!util.isUint8Array(sessionKey.data) || !util.isString(sessionKey.algorithm)) { + throw new Error('Invalid session key for encryption.'); + } + } else if (encryptionKeys && encryptionKeys.length) { + sessionKey = await Message.generateSessionKey(encryptionKeys, date, userIDs, config); + } else if (passwords && passwords.length) { + sessionKey = await Message.generateSessionKey(undefined, undefined, undefined, config); + } else { + throw new Error('No keys, passwords, or session key provided.'); + } + + const { data: sessionKeyData, algorithm: algorithmName, aeadAlgorithm: aeadAlgorithmName } = sessionKey; + + const msg = await Message.encryptSessionKey(sessionKeyData, algorithmName, aeadAlgorithmName, encryptionKeys, passwords, wildcard, encryptionKeyIDs, date, userIDs, config); + + let symEncryptedPacket; + if (aeadAlgorithmName) { + symEncryptedPacket = new AEADEncryptedDataPacket(); + symEncryptedPacket.aeadAlgorithm = enums.write(enums.aead, aeadAlgorithmName); + } else { + symEncryptedPacket = new SymEncryptedIntegrityProtectedDataPacket(); + } + symEncryptedPacket.packets = this.packets; + + const algorithm = enums.write(enums.symmetric, algorithmName); + await symEncryptedPacket.encrypt(algorithm, sessionKeyData, config); + + msg.packets.push(symEncryptedPacket); + symEncryptedPacket.packets = new PacketList(); // remove packets after encryption + return msg; + } + + /** + * Encrypt a session key either with public keys, passwords, or both at once. + * @param {Uint8Array} sessionKey - session key for encryption + * @param {String} algorithmName - session key algorithm + * @param {String} [aeadAlgorithmName] - AEAD algorithm, e.g. 'eax' or 'ocb' + * @param {Array} [encryptionKeys] - Public key(s) for message encryption + * @param {Array} [passwords] - For message encryption + * @param {Boolean} [wildcard] - Use a key ID of 0 instead of the public key IDs + * @param {Array} [encryptionKeyIDs] - Array of key IDs to use for encryption. Each encryptionKeyIDs[i] corresponds to encryptionKeys[i] + * @param {Date} [date] - Override the date + * @param {Array} [userIDs] - User IDs to encrypt for, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }] + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New message with encrypted content. + * @async + */ + static async encryptSessionKey(sessionKey, algorithmName, aeadAlgorithmName, encryptionKeys, passwords, wildcard = false, encryptionKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { + const packetlist = new PacketList(); + const algorithm = enums.write(enums.symmetric, algorithmName); + const aeadAlgorithm = aeadAlgorithmName && enums.write(enums.aead, aeadAlgorithmName); + + if (encryptionKeys) { + const results = await Promise.all(encryptionKeys.map(async function(primaryKey, i) { + const encryptionKey = await primaryKey.getEncryptionKey(encryptionKeyIDs[i], date, userIDs, config); + const pkESKeyPacket = new PublicKeyEncryptedSessionKeyPacket(); + pkESKeyPacket.publicKeyID = wildcard ? KeyID.wildcard() : encryptionKey.getKeyID(); + pkESKeyPacket.publicKeyAlgorithm = encryptionKey.keyPacket.algorithm; + pkESKeyPacket.sessionKey = sessionKey; + pkESKeyPacket.sessionKeyAlgorithm = algorithm; + await pkESKeyPacket.encrypt(encryptionKey.keyPacket); + delete pkESKeyPacket.sessionKey; // delete plaintext session key after encryption + return pkESKeyPacket; + })); + packetlist.push(...results); + } + if (passwords) { + const testDecrypt = async function(keyPacket, password) { + try { + await keyPacket.decrypt(password); + return 1; + } catch (e) { + return 0; + } + }; + + const sum = (accumulator, currentValue) => accumulator + currentValue; + + const encryptPassword = async function(sessionKey, algorithm, aeadAlgorithm, password) { + const symEncryptedSessionKeyPacket = new SymEncryptedSessionKeyPacket(config); + symEncryptedSessionKeyPacket.sessionKey = sessionKey; + symEncryptedSessionKeyPacket.sessionKeyAlgorithm = algorithm; + if (aeadAlgorithm) { + symEncryptedSessionKeyPacket.aeadAlgorithm = aeadAlgorithm; + } + await symEncryptedSessionKeyPacket.encrypt(password, config); + + if (config.passwordCollisionCheck) { + const results = await Promise.all(passwords.map(pwd => testDecrypt(symEncryptedSessionKeyPacket, pwd))); + if (results.reduce(sum) !== 1) { + return encryptPassword(sessionKey, algorithm, password); + } + } + + delete symEncryptedSessionKeyPacket.sessionKey; // delete plaintext session key after encryption + return symEncryptedSessionKeyPacket; + }; + + const results = await Promise.all(passwords.map(pwd => encryptPassword(sessionKey, algorithm, aeadAlgorithm, pwd))); + packetlist.push(...results); + } + + return new Message(packetlist); + } + + /** + * Sign the message (the literal data packet of the message) + * @param {Array} signingKeys - private keys with decrypted secret key data for signing + * @param {Signature} [signature] - Any existing detached signature to add to the message + * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] + * @param {Date} [date] - Override the creation time of the signature + * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New message with signed content. + * @async + */ + async sign(signingKeys = [], signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { + const packetlist = new PacketList(); + + const literalDataPacket = this.packets.findPacket(enums.packet.literalData); + if (!literalDataPacket) { + throw new Error('No literal data packet to sign.'); + } + + let i; + let existingSigPacketlist; + // If data packet was created from Uint8Array, use binary, otherwise use text + const signatureType = literalDataPacket.text === null ? + enums.signature.binary : enums.signature.text; + + if (signature) { + existingSigPacketlist = signature.packets.filterByTag(enums.packet.signature); + for (i = existingSigPacketlist.length - 1; i >= 0; i--) { + const signaturePacket = existingSigPacketlist[i]; + const onePassSig = new OnePassSignaturePacket(); + onePassSig.signatureType = signaturePacket.signatureType; + onePassSig.hashAlgorithm = signaturePacket.hashAlgorithm; + onePassSig.publicKeyAlgorithm = signaturePacket.publicKeyAlgorithm; + onePassSig.issuerKeyID = signaturePacket.issuerKeyID; + if (!signingKeys.length && i === 0) { + onePassSig.flags = 1; + } + packetlist.push(onePassSig); + } + } + + await Promise.all(Array.from(signingKeys).reverse().map(async function (primaryKey, i) { + if (!primaryKey.isPrivate()) { + throw new Error('Need private key for signing'); + } + const signingKeyID = signingKeyIDs[signingKeys.length - 1 - i]; + const signingKey = await primaryKey.getSigningKey(signingKeyID, date, userIDs, config); + const onePassSig = new OnePassSignaturePacket(); + onePassSig.signatureType = signatureType; + onePassSig.hashAlgorithm = await getPreferredHashAlgo$1(primaryKey, signingKey.keyPacket, date, userIDs, config); + onePassSig.publicKeyAlgorithm = signingKey.keyPacket.algorithm; + onePassSig.issuerKeyID = signingKey.getKeyID(); + if (i === signingKeys.length - 1) { + onePassSig.flags = 1; + } + return onePassSig; + })).then(onePassSignatureList => { + onePassSignatureList.forEach(onePassSig => packetlist.push(onePassSig)); + }); + + packetlist.push(literalDataPacket); + packetlist.push(...(await createSignaturePackets(literalDataPacket, signingKeys, signature, signingKeyIDs, date, userIDs, false, config))); + + return new Message(packetlist); + } + + /** + * Compresses the message (the literal and -if signed- signature data packets of the message) + * @param {module:enums.compression} algo - compression algorithm + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Message} New message with compressed content. + */ + compress(algo, config = defaultConfig) { + if (algo === enums.compression.uncompressed) { + return this; + } + + const compressed = new CompressedDataPacket(config); + compressed.algorithm = algo; + compressed.packets = this.packets; + + const packetList = new PacketList(); + packetList.push(compressed); + + return new Message(packetList); + } + + /** + * Create a detached signature for the message (the literal data packet of the message) + * @param {Array} signingKeys - private keys with decrypted secret key data for signing + * @param {Signature} [signature] - Any existing detached signature + * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] + * @param {Date} [date] - Override the creation time of the signature + * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New detached signature of message content. + * @async + */ + async signDetached(signingKeys = [], signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { + const literalDataPacket = this.packets.findPacket(enums.packet.literalData); + if (!literalDataPacket) { + throw new Error('No literal data packet to sign.'); + } + return new Signature(await createSignaturePackets(literalDataPacket, signingKeys, signature, signingKeyIDs, date, userIDs, true, config)); + } + + /** + * Verify message signatures + * @param {Array} verificationKeys - Array of public keys to verify signatures + * @param {Date} [date] - Verify the signature against the given date, i.e. check signature creation time < date < expiration time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise, + * verified: Promise + * }>>} List of signer's keyID and validity of signatures. + * @async + */ + async verify(verificationKeys, date = new Date(), config = defaultConfig) { + const msg = this.unwrapCompressed(); + const literalDataList = msg.packets.filterByTag(enums.packet.literalData); + if (literalDataList.length !== 1) { + throw new Error('Can only verify message with one literal data packet.'); + } + if (isArrayStream(msg.packets.stream)) { + msg.packets.push(...await readToEnd(msg.packets.stream, _ => _ || [])); + } + const onePassSigList = msg.packets.filterByTag(enums.packet.onePassSignature).reverse(); + const signatureList = msg.packets.filterByTag(enums.packet.signature); + if (onePassSigList.length && !signatureList.length && util.isStream(msg.packets.stream) && !isArrayStream(msg.packets.stream)) { + await Promise.all(onePassSigList.map(async onePassSig => { + onePassSig.correspondingSig = new Promise((resolve, reject) => { + onePassSig.correspondingSigResolve = resolve; + onePassSig.correspondingSigReject = reject; + }); + onePassSig.signatureData = fromAsync(async () => (await onePassSig.correspondingSig).signatureData); + onePassSig.hashed = readToEnd(await onePassSig.hash(onePassSig.signatureType, literalDataList[0], undefined, false)); + onePassSig.hashed.catch(() => {}); + })); + msg.packets.stream = transformPair(msg.packets.stream, async (readable, writable) => { + const reader = getReader(readable); + const writer = getWriter(writable); + try { + for (let i = 0; i < onePassSigList.length; i++) { + const { value: signature } = await reader.read(); + onePassSigList[i].correspondingSigResolve(signature); + } + await reader.readToEnd(); + await writer.ready; + await writer.close(); + } catch (e) { + onePassSigList.forEach(onePassSig => { + onePassSig.correspondingSigReject(e); + }); + await writer.abort(e); + } + }); + return createVerificationObjects(onePassSigList, literalDataList, verificationKeys, date, false, config); + } + return createVerificationObjects(signatureList, literalDataList, verificationKeys, date, false, config); + } + + /** + * Verify detached message signature + * @param {Array} verificationKeys - Array of public keys to verify signatures + * @param {Signature} signature + * @param {Date} date - Verify the signature against the given date, i.e. check signature creation time < date < expiration time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise, + * verified: Promise + * }>>} List of signer's keyID and validity of signature. + * @async + */ + verifyDetached(signature, verificationKeys, date = new Date(), config = defaultConfig) { + const msg = this.unwrapCompressed(); + const literalDataList = msg.packets.filterByTag(enums.packet.literalData); + if (literalDataList.length !== 1) { + throw new Error('Can only verify message with one literal data packet.'); + } + const signatureList = signature.packets; + return createVerificationObjects(signatureList, literalDataList, verificationKeys, date, true, config); + } + + /** + * Unwrap compressed message + * @returns {Message} Message Content of compressed message. + */ + unwrapCompressed() { + const compressed = this.packets.filterByTag(enums.packet.compressedData); + if (compressed.length) { + return new Message(compressed[0].packets); + } + return this; + } + + /** + * Append signature to unencrypted message object + * @param {String|Uint8Array} detachedSignature - The detached ASCII-armored or Uint8Array PGP signature + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + async appendSignature(detachedSignature, config = defaultConfig) { + await this.packets.read( + util.isUint8Array(detachedSignature) ? detachedSignature : (await unarmor(detachedSignature)).data, + allowedDetachedSignaturePackets, + config + ); + } + + /** + * Returns binary encoded message + * @returns {ReadableStream} Binary message. + */ + write() { + return this.packets.write(); + } + + /** + * Returns ASCII armored text of message + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {ReadableStream} ASCII armor. + */ + armor(config = defaultConfig) { + return armor(enums.armor.message, this.write(), null, null, null, config); + } + } + + /** + * Create signature packets for the message + * @param {LiteralDataPacket} literalDataPacket - the literal data packet to sign + * @param {Array} [signingKeys] - private keys with decrypted secret key data for signing + * @param {Signature} [signature] - Any existing detached signature to append + * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] + * @param {Date} [date] - Override the creationtime of the signature + * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] + * @param {Boolean} [detached] - Whether to create detached signature packets + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} List of signature packets. + * @async + * @private + */ + async function createSignaturePackets(literalDataPacket, signingKeys, signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], detached = false, config = defaultConfig) { + const packetlist = new PacketList(); + + // If data packet was created from Uint8Array, use binary, otherwise use text + const signatureType = literalDataPacket.text === null ? + enums.signature.binary : enums.signature.text; + + await Promise.all(signingKeys.map(async (primaryKey, i) => { + const userID = userIDs[i]; + if (!primaryKey.isPrivate()) { + throw new Error('Need private key for signing'); + } + const signingKey = await primaryKey.getSigningKey(signingKeyIDs[i], date, userID, config); + return createSignaturePacket(literalDataPacket, primaryKey, signingKey.keyPacket, { signatureType }, date, userID, detached, config); + })).then(signatureList => { + packetlist.push(...signatureList); + }); + + if (signature) { + const existingSigPacketlist = signature.packets.filterByTag(enums.packet.signature); + packetlist.push(...existingSigPacketlist); + } + return packetlist; + } + + /** + * Create object containing signer's keyID and validity of signature + * @param {SignaturePacket} signature - Signature packet + * @param {Array} literalDataList - Array of literal data packets + * @param {Array} verificationKeys - Array of public keys to verify signatures + * @param {Date} [date] - Check signature validity with respect to the given date + * @param {Boolean} [detached] - Whether to verify detached signature packets + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise<{ + * keyID: module:type/keyid~KeyID, + * signature: Promise, + * verified: Promise + * }>} signer's keyID and validity of signature + * @async + * @private + */ + async function createVerificationObject(signature, literalDataList, verificationKeys, date = new Date(), detached = false, config = defaultConfig) { + let primaryKey; + let unverifiedSigningKey; + + for (const key of verificationKeys) { + const issuerKeys = key.getKeys(signature.issuerKeyID); + if (issuerKeys.length > 0) { + primaryKey = key; + unverifiedSigningKey = issuerKeys[0]; + break; + } + } + + const isOnePassSignature = signature instanceof OnePassSignaturePacket; + const signaturePacketPromise = isOnePassSignature ? signature.correspondingSig : signature; + + const verifiedSig = { + keyID: signature.issuerKeyID, + verified: (async () => { + if (!unverifiedSigningKey) { + throw new Error(`Could not find signing key with key ID ${signature.issuerKeyID.toHex()}`); + } + + await signature.verify(unverifiedSigningKey.keyPacket, signature.signatureType, literalDataList[0], date, detached, config); + const signaturePacket = await signaturePacketPromise; + if (unverifiedSigningKey.getCreationTime() > signaturePacket.created) { + throw new Error('Key is newer than the signature'); + } + // We pass the signature creation time to check whether the key was expired at the time of signing. + // We check this after signature verification because for streamed one-pass signatures, the creation time is not available before + try { + await primaryKey.getSigningKey(unverifiedSigningKey.getKeyID(), signaturePacket.created, undefined, config); + } catch (e) { + // If a key was reformatted then the self-signatures of the signing key might be in the future compared to the message signature, + // making the key invalid at the time of signing. + // However, if the key is valid at the given `date`, we still allow using it provided the relevant `config` setting is enabled. + // Note: we do not support the edge case of a key that was reformatted and it has expired. + if (config.allowInsecureVerificationWithReformattedKeys && e.message.match(/Signature creation time is in the future/)) { + await primaryKey.getSigningKey(unverifiedSigningKey.getKeyID(), date, undefined, config); + } else { + throw e; + } + } + return true; + })(), + signature: (async () => { + const signaturePacket = await signaturePacketPromise; + const packetlist = new PacketList(); + signaturePacket && packetlist.push(signaturePacket); + return new Signature(packetlist); + })() + }; + + // Mark potential promise rejections as "handled". This is needed because in + // some cases, we reject them before the user has a reasonable chance to + // handle them (e.g. `await readToEnd(result.data); await result.verified` and + // the data stream errors). + verifiedSig.signature.catch(() => {}); + verifiedSig.verified.catch(() => {}); + + return verifiedSig; + } + + /** + * Create list of objects containing signer's keyID and validity of signature + * @param {Array} signatureList - Array of signature packets + * @param {Array} literalDataList - Array of literal data packets + * @param {Array} verificationKeys - Array of public keys to verify signatures + * @param {Date} date - Verify the signature against the given date, + * i.e. check signature creation time < date < expiration time + * @param {Boolean} [detached] - Whether to verify detached signature packets + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise, + * verified: Promise + * }>>} list of signer's keyID and validity of signatures (one entry per signature packet in input) + * @async + * @private + */ + async function createVerificationObjects(signatureList, literalDataList, verificationKeys, date = new Date(), detached = false, config = defaultConfig) { + return Promise.all(signatureList.filter(function(signature) { + return ['text', 'binary'].includes(enums.read(enums.signature, signature.signatureType)); + }).map(async function(signature) { + return createVerificationObject(signature, literalDataList, verificationKeys, date, detached, config); + })); + } + + /** + * Reads an (optionally armored) OpenPGP message and returns a Message object + * @param {Object} options + * @param {String | ReadableStream} [options.armoredMessage] - Armored message to be parsed + * @param {Uint8Array | ReadableStream} [options.binaryMessage] - Binary to be parsed + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} New message object. + * @async + * @static + */ + async function readMessage({ armoredMessage, binaryMessage, config, ...rest }) { + config = { ...defaultConfig, ...config }; + let input = armoredMessage || binaryMessage; + if (!input) { + throw new Error('readMessage: must pass options object containing `armoredMessage` or `binaryMessage`'); + } + if (armoredMessage && !util.isString(armoredMessage) && !util.isStream(armoredMessage)) { + throw new Error('readMessage: options.armoredMessage must be a string or stream'); + } + if (binaryMessage && !util.isUint8Array(binaryMessage) && !util.isStream(binaryMessage)) { + throw new Error('readMessage: options.binaryMessage must be a Uint8Array or stream'); + } + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + const streamType = util.isStream(input); + if (streamType) { + await loadStreamsPonyfill(); + input = toStream(input); + } + if (armoredMessage) { + const { type, data } = await unarmor(input, config); + if (type !== enums.armor.message) { + throw new Error('Armored text not of type message'); + } + input = data; + } + const packetlist = await PacketList.fromBinary(input, allowedMessagePackets, config); + const message = new Message(packetlist); + message.fromStream = streamType; + return message; + } + + /** + * Creates new message object from text or binary data. + * @param {Object} options + * @param {String | ReadableStream} [options.text] - The text message contents + * @param {Uint8Array | ReadableStream} [options.binary] - The binary message contents + * @param {String} [options.filename=""] - Name of the file (if any) + * @param {Date} [options.date=current date] - Date of the message, or modification date of the file + * @param {'utf8'|'binary'|'text'|'mime'} [options.format='utf8' if text is passed, 'binary' otherwise] - Data packet type + * @returns {Promise} New message object. + * @async + * @static + */ + async function createMessage({ text, binary, filename, date = new Date(), format = text !== undefined ? 'utf8' : 'binary', ...rest }) { + let input = text !== undefined ? text : binary; + if (input === undefined) { + throw new Error('createMessage: must pass options object containing `text` or `binary`'); + } + if (text && !util.isString(text) && !util.isStream(text)) { + throw new Error('createMessage: options.text must be a string or stream'); + } + if (binary && !util.isUint8Array(binary) && !util.isStream(binary)) { + throw new Error('createMessage: options.binary must be a Uint8Array or stream'); + } + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + const streamType = util.isStream(input); + if (streamType) { + await loadStreamsPonyfill(); + input = toStream(input); + } + const literalDataPacket = new LiteralDataPacket(date); + if (text !== undefined) { + literalDataPacket.setText(input, enums.write(enums.literal, format)); + } else { + literalDataPacket.setBytes(input, enums.write(enums.literal, format)); + } + if (filename !== undefined) { + literalDataPacket.setFilename(filename); + } + const literalDataPacketlist = new PacketList(); + literalDataPacketlist.push(literalDataPacket); + const message = new Message(literalDataPacketlist); + message.fromStream = streamType; + return message; + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + // A Cleartext message can contain the following packets + const allowedPackets$5 = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); + + /** + * Class that represents an OpenPGP cleartext signed message. + * See {@link https://tools.ietf.org/html/rfc4880#section-7} + */ + class CleartextMessage { + /** + * @param {String} text - The cleartext of the signed message + * @param {Signature} signature - The detached signature or an empty signature for unsigned messages + */ + constructor(text, signature) { + // normalize EOL to canonical form + this.text = util.removeTrailingSpaces(text).replace(/\r?\n/g, '\r\n'); + if (signature && !(signature instanceof Signature)) { + throw new Error('Invalid signature input'); + } + this.signature = signature || new Signature(new PacketList()); + } + + /** + * Returns the key IDs of the keys that signed the cleartext message + * @returns {Array} Array of keyID objects. + */ + getSigningKeyIDs() { + const keyIDs = []; + const signatureList = this.signature.packets; + signatureList.forEach(function(packet) { + keyIDs.push(packet.issuerKeyID); + }); + return keyIDs; + } + + /** + * Sign the cleartext message + * @param {Array} privateKeys - private keys with decrypted secret key data for signing + * @param {Signature} [signature] - Any existing detached signature + * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to privateKeys[i] + * @param {Date} [date] - The creation time of the signature that should be created + * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New cleartext message with signed content. + * @async + */ + async sign(privateKeys, signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { + const literalDataPacket = new LiteralDataPacket(); + literalDataPacket.setText(this.text); + const newSignature = new Signature(await createSignaturePackets(literalDataPacket, privateKeys, signature, signingKeyIDs, date, userIDs, true, config)); + return new CleartextMessage(this.text, newSignature); + } + + /** + * Verify signatures of cleartext signed message + * @param {Array} keys - Array of keys to verify signatures + * @param {Date} [date] - Verify the signature against the given date, i.e. check signature creation time < date < expiration time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise, + * verified: Promise + * }>>} List of signer's keyID and validity of signature. + * @async + */ + verify(keys, date = new Date(), config = defaultConfig) { + const signatureList = this.signature.packets; + const literalDataPacket = new LiteralDataPacket(); + // we assume that cleartext signature is generated based on UTF8 cleartext + literalDataPacket.setText(this.text); + return createVerificationObjects(signatureList, [literalDataPacket], keys, date, true, config); + } + + /** + * Get cleartext + * @returns {String} Cleartext of message. + */ + getText() { + // normalize end of line to \n + return this.text.replace(/\r\n/g, '\n'); + } + + /** + * Returns ASCII armored text of cleartext signed message + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {String | ReadableStream} ASCII armor. + */ + armor(config = defaultConfig) { + let hashes = this.signature.packets.map(function(packet) { + return enums.read(enums.hash, packet.hashAlgorithm).toUpperCase(); + }); + hashes = hashes.filter(function(item, i, ar) { return ar.indexOf(item) === i; }); + const body = { + hash: hashes.join(), + text: this.text, + data: this.signature.packets.write() + }; + return armor(enums.armor.signed, body, undefined, undefined, undefined, config); + } + } + + /** + * Reads an OpenPGP cleartext signed message and returns a CleartextMessage object + * @param {Object} options + * @param {String} options.cleartextMessage - Text to be parsed + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} New cleartext message object. + * @async + * @static + */ + async function readCleartextMessage({ cleartextMessage, config, ...rest }) { + config = { ...defaultConfig, ...config }; + if (!cleartextMessage) { + throw new Error('readCleartextMessage: must pass options object containing `cleartextMessage`'); + } + if (!util.isString(cleartextMessage)) { + throw new Error('readCleartextMessage: options.cleartextMessage must be a string'); + } + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + const input = await unarmor(cleartextMessage); + if (input.type !== enums.armor.signed) { + throw new Error('No cleartext signed message.'); + } + const packetlist = await PacketList.fromBinary(input.data, allowedPackets$5, config); + verifyHeaders$1(input.headers, packetlist); + const signature = new Signature(packetlist); + return new CleartextMessage(input.text, signature); + } + + /** + * Compare hash algorithm specified in the armor header with signatures + * @param {Array} headers - Armor headers + * @param {PacketList} packetlist - The packetlist with signature packets + * @private + */ + function verifyHeaders$1(headers, packetlist) { + const checkHashAlgos = function(hashAlgos) { + const check = packet => algo => packet.hashAlgorithm === algo; + + for (let i = 0; i < packetlist.length; i++) { + if (packetlist[i].constructor.tag === enums.packet.signature && !hashAlgos.some(check(packetlist[i]))) { + return false; + } + } + return true; + }; + + let oneHeader = null; + let hashAlgos = []; + headers.forEach(function(header) { + oneHeader = header.match(/Hash: (.+)/); // get header value + if (oneHeader) { + oneHeader = oneHeader[1].replace(/\s/g, ''); // remove whitespace + oneHeader = oneHeader.split(','); + oneHeader = oneHeader.map(function(hash) { + hash = hash.toLowerCase(); + try { + return enums.write(enums.hash, hash); + } catch (e) { + throw new Error('Unknown hash algorithm in armor header: ' + hash); + } + }); + hashAlgos = hashAlgos.concat(oneHeader); + } else { + throw new Error('Only "Hash" header allowed in cleartext signed message'); + } + }); + + if (!hashAlgos.length && !checkHashAlgos([enums.hash.md5])) { + throw new Error('If no "Hash" header in cleartext signed message, then only MD5 signatures allowed'); + } else if (hashAlgos.length && !checkHashAlgos(hashAlgos)) { + throw new Error('Hash algorithm mismatch in armor header and signature'); + } + } + + /** + * Creates a new CleartextMessage object from text + * @param {Object} options + * @param {String} options.text + * @static + * @async + */ + async function createCleartextMessage({ text, ...rest }) { + if (!text) { + throw new Error('createCleartextMessage: must pass options object containing `text`'); + } + if (!util.isString(text)) { + throw new Error('createCleartextMessage: options.text must be a string'); + } + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + return new CleartextMessage(text); + } + + // OpenPGP.js - An OpenPGP implementation in javascript + + + ////////////////////// + // // + // Key handling // + // // + ////////////////////// + + + /** + * Generates a new OpenPGP key pair. Supports RSA and ECC keys. By default, primary and subkeys will be of same type. + * The generated primary key will have signing capabilities. By default, one subkey with encryption capabilities is also generated. + * @param {Object} options + * @param {Object|Array} options.userIDs - User IDs as objects: `{ name: 'Jo Doe', email: 'info@jo.com' }` + * @param {'ecc'|'rsa'} [options.type='ecc'] - The primary key algorithm type: ECC (default) or RSA + * @param {String} [options.passphrase=(not protected)] - The passphrase used to encrypt the generated private key. If omitted, the key won't be encrypted. + * @param {Number} [options.rsaBits=4096] - Number of bits for RSA keys + * @param {String} [options.curve='curve25519'] - Elliptic curve for ECC keys: + * curve25519 (default), p256, p384, p521, secp256k1, + * brainpoolP256r1, brainpoolP384r1, or brainpoolP512r1 + * @param {Date} [options.date=current date] - Override the creation date of the key and the key signatures + * @param {Number} [options.keyExpirationTime=0 (never expires)] - Number of seconds from the key creation time after which the key expires + * @param {Array} [options.subkeys=a single encryption subkey] - Options for each subkey e.g. `[{sign: true, passphrase: '123'}]` + * default to main key options, except for `sign` parameter that defaults to false, and indicates whether the subkey should sign rather than encrypt + * @param {'armored'|'binary'|'object'} [options.format='armored'] - format of the output keys + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} The generated key object in the form: + * { privateKey:PrivateKey|Uint8Array|String, publicKey:PublicKey|Uint8Array|String, revocationCertificate:String } + * @async + * @static + */ + async function generateKey({ userIDs = [], passphrase = '', type = 'ecc', rsaBits = 4096, curve = 'curve25519', keyExpirationTime = 0, date = new Date(), subkeys = [{}], format = 'armored', config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + userIDs = toArray$1(userIDs); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + if (userIDs.length === 0) { + throw new Error('UserIDs are required for key generation'); + } + if (type === 'rsa' && rsaBits < config.minRSABits) { + throw new Error(`rsaBits should be at least ${config.minRSABits}, got: ${rsaBits}`); + } + + const options = { userIDs, passphrase, type, rsaBits, curve, keyExpirationTime, date, subkeys }; + + try { + const { key, revocationCertificate } = await generate$2(options, config); + key.getKeys().forEach(({ keyPacket }) => checkKeyRequirements(keyPacket, config)); + + return { + privateKey: formatObject(key, format, config), + publicKey: formatObject(key.toPublic(), format, config), + revocationCertificate + }; + } catch (err) { + throw util.wrapError('Error generating keypair', err); + } + } + + /** + * Reformats signature packets for a key and rewraps key object. + * @param {Object} options + * @param {PrivateKey} options.privateKey - Private key to reformat + * @param {Object|Array} options.userIDs - User IDs as objects: `{ name: 'Jo Doe', email: 'info@jo.com' }` + * @param {String} [options.passphrase=(not protected)] - The passphrase used to encrypt the reformatted private key. If omitted, the key won't be encrypted. + * @param {Number} [options.keyExpirationTime=0 (never expires)] - Number of seconds from the key creation time after which the key expires + * @param {Date} [options.date] - Override the creation date of the key signatures. If the key was previously used to sign messages, it is recommended + * to set the same date as the key creation time to ensure that old message signatures will still be verifiable using the reformatted key. + * @param {'armored'|'binary'|'object'} [options.format='armored'] - format of the output keys + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} The generated key object in the form: + * { privateKey:PrivateKey|Uint8Array|String, publicKey:PublicKey|Uint8Array|String, revocationCertificate:String } + * @async + * @static + */ + async function reformatKey({ privateKey, userIDs = [], passphrase = '', keyExpirationTime = 0, date, format = 'armored', config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + userIDs = toArray$1(userIDs); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + if (userIDs.length === 0) { + throw new Error('UserIDs are required for key reformat'); + } + const options = { privateKey, userIDs, passphrase, keyExpirationTime, date }; + + try { + const { key: reformattedKey, revocationCertificate } = await reformat(options, config); + + return { + privateKey: formatObject(reformattedKey, format, config), + publicKey: formatObject(reformattedKey.toPublic(), format, config), + revocationCertificate + }; + } catch (err) { + throw util.wrapError('Error reformatting keypair', err); + } + } + + /** + * Revokes a key. Requires either a private key or a revocation certificate. + * If a revocation certificate is passed, the reasonForRevocation parameter will be ignored. + * @param {Object} options + * @param {Key} options.key - Public or private key to revoke + * @param {String} [options.revocationCertificate] - Revocation certificate to revoke the key with + * @param {Object} [options.reasonForRevocation] - Object indicating the reason for revocation + * @param {module:enums.reasonForRevocation} [options.reasonForRevocation.flag=[noReason]{@link module:enums.reasonForRevocation}] - Flag indicating the reason for revocation + * @param {String} [options.reasonForRevocation.string=""] - String explaining the reason for revocation + * @param {Date} [options.date] - Use the given date instead of the current time to verify validity of revocation certificate (if provided), or as creation time of the revocation signature + * @param {'armored'|'binary'|'object'} [options.format='armored'] - format of the output key(s) + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} The revoked key in the form: + * { privateKey:PrivateKey|Uint8Array|String, publicKey:PublicKey|Uint8Array|String } if private key is passed, or + * { privateKey: null, publicKey:PublicKey|Uint8Array|String } otherwise + * @async + * @static + */ + async function revokeKey({ key, revocationCertificate, reasonForRevocation, date = new Date(), format = 'armored', config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + try { + const revokedKey = revocationCertificate ? + await key.applyRevocationCertificate(revocationCertificate, date, config) : + await key.revoke(reasonForRevocation, date, config); + + return revokedKey.isPrivate() ? { + privateKey: formatObject(revokedKey, format, config), + publicKey: formatObject(revokedKey.toPublic(), format, config) + } : { + privateKey: null, + publicKey: formatObject(revokedKey, format, config) + }; + } catch (err) { + throw util.wrapError('Error revoking key', err); + } + } + + /** + * Unlock a private key with the given passphrase. + * This method does not change the original key. + * @param {Object} options + * @param {PrivateKey} options.privateKey - The private key to decrypt + * @param {String|Array} options.passphrase - The user's passphrase(s) + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} The unlocked key object. + * @async + */ + async function decryptKey({ privateKey, passphrase, config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + if (!privateKey.isPrivate()) { + throw new Error('Cannot decrypt a public key'); + } + const clonedPrivateKey = privateKey.clone(true); + const passphrases = util.isArray(passphrase) ? passphrase : [passphrase]; + + try { + await Promise.all(clonedPrivateKey.getKeys().map(key => ( + // try to decrypt each key with any of the given passphrases + util.anyPromise(passphrases.map(passphrase => key.keyPacket.decrypt(passphrase))) + ))); + + await clonedPrivateKey.validate(config); + return clonedPrivateKey; + } catch (err) { + clonedPrivateKey.clearPrivateParams(); + throw util.wrapError('Error decrypting private key', err); + } + } + + /** + * Lock a private key with the given passphrase. + * This method does not change the original key. + * @param {Object} options + * @param {PrivateKey} options.privateKey - The private key to encrypt + * @param {String|Array} options.passphrase - If multiple passphrases, they should be in the same order as the packets each should encrypt + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} The locked key object. + * @async + */ + async function encryptKey({ privateKey, passphrase, config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + if (!privateKey.isPrivate()) { + throw new Error('Cannot encrypt a public key'); + } + const clonedPrivateKey = privateKey.clone(true); + + const keys = clonedPrivateKey.getKeys(); + const passphrases = util.isArray(passphrase) ? passphrase : new Array(keys.length).fill(passphrase); + if (passphrases.length !== keys.length) { + throw new Error('Invalid number of passphrases given for key encryption'); + } + + try { + await Promise.all(keys.map(async (key, i) => { + const { keyPacket } = key; + await keyPacket.encrypt(passphrases[i], config); + keyPacket.clearPrivateParams(); + })); + return clonedPrivateKey; + } catch (err) { + clonedPrivateKey.clearPrivateParams(); + throw util.wrapError('Error encrypting private key', err); + } + } + + + /////////////////////////////////////////// + // // + // Message encryption and decryption // + // // + /////////////////////////////////////////// + + + /** + * Encrypts a message using public keys, passwords or both at once. At least one of `encryptionKeys` or `passwords` + * must be specified. If signing keys are specified, those will be used to sign the message. + * @param {Object} options + * @param {Message} options.message - Message to be encrypted as created by {@link createMessage} + * @param {PublicKey|PublicKey[]} [options.encryptionKeys] - Array of keys or single key, used to encrypt the message + * @param {PrivateKey|PrivateKey[]} [options.signingKeys] - Private keys for signing. If omitted message will not be signed + * @param {String|String[]} [options.passwords] - Array of passwords or a single password to encrypt the message + * @param {Object} [options.sessionKey] - Session key in the form: `{ data:Uint8Array, algorithm:String }` + * @param {'armored'|'binary'|'object'} [options.format='armored'] - Format of the returned message + * @param {Signature} [options.signature] - A detached signature to add to the encrypted message + * @param {Boolean} [options.wildcard=false] - Use a key ID of 0 instead of the public key IDs + * @param {KeyID|KeyID[]} [options.signingKeyIDs=latest-created valid signing (sub)keys] - Array of key IDs to use for signing. Each `signingKeyIDs[i]` corresponds to `signingKeys[i]` + * @param {KeyID|KeyID[]} [options.encryptionKeyIDs=latest-created valid encryption (sub)keys] - Array of key IDs to use for encryption. Each `encryptionKeyIDs[i]` corresponds to `encryptionKeys[i]` + * @param {Date} [options.date=current date] - Override the creation date of the message signature + * @param {Object|Object[]} [options.signingUserIDs=primary user IDs] - Array of user IDs to sign with, one per key in `signingKeys`, e.g. `[{ name: 'Steve Sender', email: 'steve@openpgp.org' }]` + * @param {Object|Object[]} [options.encryptionUserIDs=primary user IDs] - Array of user IDs to encrypt for, one per key in `encryptionKeys`, e.g. `[{ name: 'Robert Receiver', email: 'robert@openpgp.org' }]` + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise|MaybeStream>} Encrypted message (string if `armor` was true, the default; Uint8Array if `armor` was false). + * @async + * @static + */ + async function encrypt$4({ message, encryptionKeys, signingKeys, passwords, sessionKey, format = 'armored', signature = null, wildcard = false, signingKeyIDs = [], encryptionKeyIDs = [], date = new Date(), signingUserIDs = [], encryptionUserIDs = [], config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + checkMessage(message); checkOutputMessageFormat(format); + encryptionKeys = toArray$1(encryptionKeys); signingKeys = toArray$1(signingKeys); passwords = toArray$1(passwords); + signingKeyIDs = toArray$1(signingKeyIDs); encryptionKeyIDs = toArray$1(encryptionKeyIDs); signingUserIDs = toArray$1(signingUserIDs); encryptionUserIDs = toArray$1(encryptionUserIDs); + if (rest.detached) { + throw new Error("The `detached` option has been removed from openpgp.encrypt, separately call openpgp.sign instead. Don't forget to remove the `privateKeys` option as well."); + } + if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.encrypt, pass `encryptionKeys` instead'); + if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.encrypt, pass `signingKeys` instead'); + if (rest.armor !== undefined) throw new Error('The `armor` option has been removed from openpgp.encrypt, pass `format` instead.'); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + if (!signingKeys) { + signingKeys = []; + } + const streaming = message.fromStream; + try { + if (signingKeys.length || signature) { // sign the message only if signing keys or signature is specified + message = await message.sign(signingKeys, signature, signingKeyIDs, date, signingUserIDs, config); + } + message = message.compress( + await getPreferredAlgo('compression', encryptionKeys, date, encryptionUserIDs, config), + config + ); + message = await message.encrypt(encryptionKeys, passwords, sessionKey, wildcard, encryptionKeyIDs, date, encryptionUserIDs, config); + if (format === 'object') return message; + // serialize data + const armor = format === 'armored'; + const data = armor ? message.armor(config) : message.write(); + return convertStream(data, streaming, armor ? 'utf8' : 'binary'); + } catch (err) { + throw util.wrapError('Error encrypting message', err); + } + } + + /** + * Decrypts a message with the user's private key, a session key or a password. + * One of `decryptionKeys`, `sessionkeys` or `passwords` must be specified (passing a combination of these options is not supported). + * @param {Object} options + * @param {Message} options.message - The message object with the encrypted data + * @param {PrivateKey|PrivateKey[]} [options.decryptionKeys] - Private keys with decrypted secret key data or session key + * @param {String|String[]} [options.passwords] - Passwords to decrypt the message + * @param {Object|Object[]} [options.sessionKeys] - Session keys in the form: { data:Uint8Array, algorithm:String } + * @param {PublicKey|PublicKey[]} [options.verificationKeys] - Array of public keys or single key, to verify signatures + * @param {Boolean} [options.expectSigned=false] - If true, data decryption fails if the message is not signed with the provided publicKeys + * @param {'utf8'|'binary'} [options.format='utf8'] - Whether to return data as a string(Stream) or Uint8Array(Stream). If 'utf8' (the default), also normalize newlines. + * @param {Signature} [options.signature] - Detached signature for verification + * @param {Date} [options.date=current date] - Use the given date for verification instead of the current time + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} Object containing decrypted and verified message in the form: + * + * { + * data: MaybeStream, (if format was 'utf8', the default) + * data: MaybeStream, (if format was 'binary') + * filename: String, + * signatures: [ + * { + * keyID: module:type/keyid~KeyID, + * verified: Promise, + * signature: Promise + * }, ... + * ] + * } + * + * where `signatures` contains a separate entry for each signature packet found in the input message. + * @async + * @static + */ + async function decrypt$4({ message, decryptionKeys, passwords, sessionKeys, verificationKeys, expectSigned = false, format = 'utf8', signature = null, date = new Date(), config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + checkMessage(message); verificationKeys = toArray$1(verificationKeys); decryptionKeys = toArray$1(decryptionKeys); passwords = toArray$1(passwords); sessionKeys = toArray$1(sessionKeys); + if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.decrypt, pass `decryptionKeys` instead'); + if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.decrypt, pass `verificationKeys` instead'); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + try { + const decrypted = await message.decrypt(decryptionKeys, passwords, sessionKeys, date, config); + if (!verificationKeys) { + verificationKeys = []; + } + + const result = {}; + result.signatures = signature ? await decrypted.verifyDetached(signature, verificationKeys, date, config) : await decrypted.verify(verificationKeys, date, config); + result.data = format === 'binary' ? decrypted.getLiteralData() : decrypted.getText(); + result.filename = decrypted.getFilename(); + linkStreams(result, message); + if (expectSigned) { + if (verificationKeys.length === 0) { + throw new Error('Verification keys are required to verify message signatures'); + } + if (result.signatures.length === 0) { + throw new Error('Message is not signed'); + } + result.data = concat([ + result.data, + fromAsync(async () => { + await util.anyPromise(result.signatures.map(sig => sig.verified)); + }) + ]); + } + result.data = await convertStream(result.data, message.fromStream, format); + return result; + } catch (err) { + throw util.wrapError('Error decrypting message', err); + } + } + + + ////////////////////////////////////////// + // // + // Message signing and verification // + // // + ////////////////////////////////////////// + + + /** + * Signs a message. + * @param {Object} options + * @param {CleartextMessage|Message} options.message - (cleartext) message to be signed + * @param {PrivateKey|PrivateKey[]} options.signingKeys - Array of keys or single key with decrypted secret key data to sign cleartext + * @param {'armored'|'binary'|'object'} [options.format='armored'] - Format of the returned message + * @param {Boolean} [options.detached=false] - If the return value should contain a detached signature + * @param {KeyID|KeyID[]} [options.signingKeyIDs=latest-created valid signing (sub)keys] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] + * @param {Date} [options.date=current date] - Override the creation date of the signature + * @param {Object|Object[]} [options.signingUserIDs=primary user IDs] - Array of user IDs to sign with, one per key in `signingKeys`, e.g. `[{ name: 'Steve Sender', email: 'steve@openpgp.org' }]` + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise>} Signed message (string if `armor` was true, the default; Uint8Array if `armor` was false). + * @async + * @static + */ + async function sign$5({ message, signingKeys, format = 'armored', detached = false, signingKeyIDs = [], date = new Date(), signingUserIDs = [], config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + checkCleartextOrMessage(message); checkOutputMessageFormat(format); + signingKeys = toArray$1(signingKeys); signingKeyIDs = toArray$1(signingKeyIDs); signingUserIDs = toArray$1(signingUserIDs); + + if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.sign, pass `signingKeys` instead'); + if (rest.armor !== undefined) throw new Error('The `armor` option has been removed from openpgp.sign, pass `format` instead.'); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + if (message instanceof CleartextMessage && format === 'binary') throw new Error('Cannot return signed cleartext message in binary format'); + if (message instanceof CleartextMessage && detached) throw new Error('Cannot detach-sign a cleartext message'); + + if (!signingKeys || signingKeys.length === 0) { + throw new Error('No signing keys provided'); + } + + try { + let signature; + if (detached) { + signature = await message.signDetached(signingKeys, undefined, signingKeyIDs, date, signingUserIDs, config); + } else { + signature = await message.sign(signingKeys, undefined, signingKeyIDs, date, signingUserIDs, config); + } + if (format === 'object') return signature; + + const armor = format === 'armored'; + signature = armor ? signature.armor(config) : signature.write(); + if (detached) { + signature = transformPair(message.packets.write(), async (readable, writable) => { + await Promise.all([ + pipe(signature, writable), + readToEnd(readable).catch(() => {}) + ]); + }); + } + return convertStream(signature, message.fromStream, armor ? 'utf8' : 'binary'); + } catch (err) { + throw util.wrapError('Error signing message', err); + } + } + + /** + * Verifies signatures of cleartext signed message + * @param {Object} options + * @param {CleartextMessage|Message} options.message - (cleartext) message object with signatures + * @param {PublicKey|PublicKey[]} options.verificationKeys - Array of publicKeys or single key, to verify signatures + * @param {Boolean} [options.expectSigned=false] - If true, verification throws if the message is not signed with the provided publicKeys + * @param {'utf8'|'binary'} [options.format='utf8'] - Whether to return data as a string(Stream) or Uint8Array(Stream). If 'utf8' (the default), also normalize newlines. + * @param {Signature} [options.signature] - Detached signature for verification + * @param {Date} [options.date=current date] - Use the given date for verification instead of the current time + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} Object containing verified message in the form: + * + * { + * data: MaybeStream, (if `message` was a CleartextMessage) + * data: MaybeStream, (if `message` was a Message) + * signatures: [ + * { + * keyID: module:type/keyid~KeyID, + * verified: Promise, + * signature: Promise + * }, ... + * ] + * } + * + * where `signatures` contains a separate entry for each signature packet found in the input message. + * @async + * @static + */ + async function verify$5({ message, verificationKeys, expectSigned = false, format = 'utf8', signature = null, date = new Date(), config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + checkCleartextOrMessage(message); verificationKeys = toArray$1(verificationKeys); + if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.verify, pass `verificationKeys` instead'); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + if (message instanceof CleartextMessage && format === 'binary') throw new Error("Can't return cleartext message data as binary"); + if (message instanceof CleartextMessage && signature) throw new Error("Can't verify detached cleartext signature"); + + try { + const result = {}; + if (signature) { + result.signatures = await message.verifyDetached(signature, verificationKeys, date, config); + } else { + result.signatures = await message.verify(verificationKeys, date, config); + } + result.data = format === 'binary' ? message.getLiteralData() : message.getText(); + if (message.fromStream) linkStreams(result, message); + if (expectSigned) { + if (result.signatures.length === 0) { + throw new Error('Message is not signed'); + } + result.data = concat([ + result.data, + fromAsync(async () => { + await util.anyPromise(result.signatures.map(sig => sig.verified)); + }) + ]); + } + result.data = await convertStream(result.data, message.fromStream, format); + return result; + } catch (err) { + throw util.wrapError('Error verifying signed message', err); + } + } + + + /////////////////////////////////////////////// + // // + // Session key encryption and decryption // + // // + /////////////////////////////////////////////// + + /** + * Generate a new session key object, taking the algorithm preferences of the passed public keys into account. + * @param {Object} options + * @param {PublicKey|PublicKey[]} options.encryptionKeys - Array of public keys or single key used to select algorithm preferences for + * @param {Date} [options.date=current date] - Date to select algorithm preferences at + * @param {Object|Object[]} [options.encryptionUserIDs=primary user IDs] - User IDs to select algorithm preferences for + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise<{ data: Uint8Array, algorithm: String }>} Object with session key data and algorithm. + * @async + * @static + */ + async function generateSessionKey$1({ encryptionKeys, date = new Date(), encryptionUserIDs = [], config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + encryptionKeys = toArray$1(encryptionKeys); encryptionUserIDs = toArray$1(encryptionUserIDs); + if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.generateSessionKey, pass `encryptionKeys` instead'); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + try { + const sessionKeys = await Message.generateSessionKey(encryptionKeys, date, encryptionUserIDs, config); + return sessionKeys; + } catch (err) { + throw util.wrapError('Error generating session key', err); + } + } + + /** + * Encrypt a symmetric session key with public keys, passwords, or both at once. + * At least one of `encryptionKeys` or `passwords` must be specified. + * @param {Object} options + * @param {Uint8Array} options.data - The session key to be encrypted e.g. 16 random bytes (for aes128) + * @param {String} options.algorithm - Algorithm of the symmetric session key e.g. 'aes128' or 'aes256' + * @param {String} [options.aeadAlgorithm] - AEAD algorithm, e.g. 'eax' or 'ocb' + * @param {PublicKey|PublicKey[]} [options.encryptionKeys] - Array of public keys or single key, used to encrypt the key + * @param {String|String[]} [options.passwords] - Passwords for the message + * @param {'armored'|'binary'} [options.format='armored'] - Format of the returned value + * @param {Boolean} [options.wildcard=false] - Use a key ID of 0 instead of the public key IDs + * @param {KeyID|KeyID[]} [options.encryptionKeyIDs=latest-created valid encryption (sub)keys] - Array of key IDs to use for encryption. Each encryptionKeyIDs[i] corresponds to encryptionKeys[i] + * @param {Date} [options.date=current date] - Override the date + * @param {Object|Object[]} [options.encryptionUserIDs=primary user IDs] - Array of user IDs to encrypt for, one per key in `encryptionKeys`, e.g. `[{ name: 'Phil Zimmermann', email: 'phil@openpgp.org' }]` + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} Encrypted session keys (string if `armor` was true, the default; Uint8Array if `armor` was false). + * @async + * @static + */ + async function encryptSessionKey({ data, algorithm, aeadAlgorithm, encryptionKeys, passwords, format = 'armored', wildcard = false, encryptionKeyIDs = [], date = new Date(), encryptionUserIDs = [], config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + checkBinary(data); checkString(algorithm, 'algorithm'); checkOutputMessageFormat(format); + encryptionKeys = toArray$1(encryptionKeys); passwords = toArray$1(passwords); encryptionKeyIDs = toArray$1(encryptionKeyIDs); encryptionUserIDs = toArray$1(encryptionUserIDs); + if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.encryptSessionKey, pass `encryptionKeys` instead'); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + try { + const message = await Message.encryptSessionKey(data, algorithm, aeadAlgorithm, encryptionKeys, passwords, wildcard, encryptionKeyIDs, date, encryptionUserIDs, config); + return formatObject(message, format, config); + } catch (err) { + throw util.wrapError('Error encrypting session key', err); + } + } + + /** + * Decrypt symmetric session keys using private keys or passwords (not both). + * One of `decryptionKeys` or `passwords` must be specified. + * @param {Object} options + * @param {Message} options.message - A message object containing the encrypted session key packets + * @param {PrivateKey|PrivateKey[]} [options.decryptionKeys] - Private keys with decrypted secret key data + * @param {String|String[]} [options.passwords] - Passwords to decrypt the session key + * @param {Date} [options.date] - Date to use for key verification instead of the current time + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} Array of decrypted session key, algorithm pairs in the form: + * { data:Uint8Array, algorithm:String } + * @throws if no session key could be found or decrypted + * @async + * @static + */ + async function decryptSessionKeys({ message, decryptionKeys, passwords, date = new Date(), config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + checkMessage(message); decryptionKeys = toArray$1(decryptionKeys); passwords = toArray$1(passwords); + if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.decryptSessionKeys, pass `decryptionKeys` instead'); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + try { + const sessionKeys = await message.decryptSessionKeys(decryptionKeys, passwords, date, config); + return sessionKeys; + } catch (err) { + throw util.wrapError('Error decrypting session keys', err); + } + } + + + ////////////////////////// + // // + // Helper functions // + // // + ////////////////////////// + + + /** + * Input validation + * @private + */ + function checkString(data, name) { + if (!util.isString(data)) { + throw new Error('Parameter [' + (name || 'data') + '] must be of type String'); + } + } + function checkBinary(data, name) { + if (!util.isUint8Array(data)) { + throw new Error('Parameter [' + (name || 'data') + '] must be of type Uint8Array'); + } + } + function checkMessage(message) { + if (!(message instanceof Message)) { + throw new Error('Parameter [message] needs to be of type Message'); + } + } + function checkCleartextOrMessage(message) { + if (!(message instanceof CleartextMessage) && !(message instanceof Message)) { + throw new Error('Parameter [message] needs to be of type Message or CleartextMessage'); + } + } + function checkOutputMessageFormat(format) { + if (format !== 'armored' && format !== 'binary' && format !== 'object') { + throw new Error(`Unsupported format ${format}`); + } + } + const defaultConfigPropsCount = Object.keys(defaultConfig).length; + function checkConfig(config) { + const inputConfigProps = Object.keys(config); + if (inputConfigProps.length !== defaultConfigPropsCount) { + for (const inputProp of inputConfigProps) { + if (defaultConfig[inputProp] === undefined) { + throw new Error(`Unknown config property: ${inputProp}`); + } + } + } + } + + /** + * Normalize parameter to an array if it is not undefined. + * @param {Object} param - the parameter to be normalized + * @returns {Array|undefined} The resulting array or undefined. + * @private + */ + function toArray$1(param) { + if (param && !util.isArray(param)) { + param = [param]; + } + return param; + } + + /** + * Convert data to or from Stream + * @param {Object} data - the data to convert + * @param {'web'|'ponyfill'|'node'|false} streaming - Whether to return a ReadableStream, and of what type + * @param {'utf8'|'binary'} [encoding] - How to return data in Node Readable streams + * @returns {Promise} The data in the respective format. + * @async + * @private + */ + async function convertStream(data, streaming, encoding = 'utf8') { + const streamType = util.isStream(data); + if (streamType === 'array') { + return readToEnd(data); + } + if (streaming === 'node') { + data = webToNode(data); + if (encoding !== 'binary') data.setEncoding(encoding); + return data; + } + if (streaming === 'web' && streamType === 'ponyfill') { + return toNativeReadable(data); + } + return data; + } + + /** + * Link result.data to the message stream for cancellation. + * Also, forward errors in the message to result.data. + * @param {Object} result - the data to convert + * @param {Message} message - message object + * @returns {Object} + * @private + */ + function linkStreams(result, message) { + result.data = transformPair(message.packets.stream, async (readable, writable) => { + await pipe(result.data, writable, { + preventClose: true + }); + const writer = getWriter(writable); + try { + // Forward errors in the message stream to result.data. + await readToEnd(readable, _ => _); + await writer.close(); + } catch (e) { + await writer.abort(e); + } + }); + } + + /** + * Convert the object to the given format + * @param {Key|Message} object + * @param {'armored'|'binary'|'object'} format + * @param {Object} config - Full configuration + * @returns {String|Uint8Array|Object} + */ + function formatObject(object, format, config) { + switch (format) { + case 'object': + return object; + case 'armored': + return object.armor(config); + case 'binary': + return object.write(); + default: + throw new Error(`Unsupported format ${format}`); + } + } + + /** + * web-streams-polyfill v3.0.3 + */ + /// + const SymbolPolyfill = typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol' ? + Symbol : + description => `Symbol(${description})`; + + /// + function noop() { + return undefined; + } + function getGlobals() { + if (typeof self !== 'undefined') { + return self; + } + else if (typeof window !== 'undefined') { + return window; + } + else if (typeof global !== 'undefined') { + return global; + } + return undefined; + } + const globals = getGlobals(); + + function typeIsObject(x) { + return (typeof x === 'object' && x !== null) || typeof x === 'function'; + } + const rethrowAssertionErrorRejection = noop; + + const originalPromise = Promise; + const originalPromiseThen = Promise.prototype.then; + const originalPromiseResolve = Promise.resolve.bind(originalPromise); + const originalPromiseReject = Promise.reject.bind(originalPromise); + function newPromise(executor) { + return new originalPromise(executor); + } + function promiseResolvedWith(value) { + return originalPromiseResolve(value); + } + function promiseRejectedWith(reason) { + return originalPromiseReject(reason); + } + function PerformPromiseThen(promise, onFulfilled, onRejected) { + // There doesn't appear to be any way to correctly emulate the behaviour from JavaScript, so this is just an + // approximation. + return originalPromiseThen.call(promise, onFulfilled, onRejected); + } + function uponPromise(promise, onFulfilled, onRejected) { + PerformPromiseThen(PerformPromiseThen(promise, onFulfilled, onRejected), undefined, rethrowAssertionErrorRejection); + } + function uponFulfillment(promise, onFulfilled) { + uponPromise(promise, onFulfilled); + } + function uponRejection(promise, onRejected) { + uponPromise(promise, undefined, onRejected); + } + function transformPromiseWith(promise, fulfillmentHandler, rejectionHandler) { + return PerformPromiseThen(promise, fulfillmentHandler, rejectionHandler); + } + function setPromiseIsHandledToTrue(promise) { + PerformPromiseThen(promise, undefined, rethrowAssertionErrorRejection); + } + const queueMicrotask = (() => { + const globalQueueMicrotask = globals && globals.queueMicrotask; + if (typeof globalQueueMicrotask === 'function') { + return globalQueueMicrotask; + } + const resolvedPromise = promiseResolvedWith(undefined); + return (fn) => PerformPromiseThen(resolvedPromise, fn); + })(); + function reflectCall(F, V, args) { + if (typeof F !== 'function') { + throw new TypeError('Argument is not a function'); + } + return Function.prototype.apply.call(F, V, args); + } + function promiseCall(F, V, args) { + try { + return promiseResolvedWith(reflectCall(F, V, args)); + } + catch (value) { + return promiseRejectedWith(value); + } + } + + // Original from Chromium + // https://chromium.googlesource.com/chromium/src/+/0aee4434a4dba42a42abaea9bfbc0cd196a63bc1/third_party/blink/renderer/core/streams/SimpleQueue.js + const QUEUE_MAX_ARRAY_SIZE = 16384; + /** + * Simple queue structure. + * + * Avoids scalability issues with using a packed array directly by using + * multiple arrays in a linked list and keeping the array size bounded. + */ + class SimpleQueue { + constructor() { + this._cursor = 0; + this._size = 0; + // _front and _back are always defined. + this._front = { + _elements: [], + _next: undefined + }; + this._back = this._front; + // The cursor is used to avoid calling Array.shift(). + // It contains the index of the front element of the array inside the + // front-most node. It is always in the range [0, QUEUE_MAX_ARRAY_SIZE). + this._cursor = 0; + // When there is only one node, size === elements.length - cursor. + this._size = 0; + } + get length() { + return this._size; + } + // For exception safety, this method is structured in order: + // 1. Read state + // 2. Calculate required state mutations + // 3. Perform state mutations + push(element) { + const oldBack = this._back; + let newBack = oldBack; + if (oldBack._elements.length === QUEUE_MAX_ARRAY_SIZE - 1) { + newBack = { + _elements: [], + _next: undefined + }; + } + // push() is the mutation most likely to throw an exception, so it + // goes first. + oldBack._elements.push(element); + if (newBack !== oldBack) { + this._back = newBack; + oldBack._next = newBack; + } + ++this._size; + } + // Like push(), shift() follows the read -> calculate -> mutate pattern for + // exception safety. + shift() { // must not be called on an empty queue + const oldFront = this._front; + let newFront = oldFront; + const oldCursor = this._cursor; + let newCursor = oldCursor + 1; + const elements = oldFront._elements; + const element = elements[oldCursor]; + if (newCursor === QUEUE_MAX_ARRAY_SIZE) { + newFront = oldFront._next; + newCursor = 0; + } + // No mutations before this point. + --this._size; + this._cursor = newCursor; + if (oldFront !== newFront) { + this._front = newFront; + } + // Permit shifted element to be garbage collected. + elements[oldCursor] = undefined; + return element; + } + // The tricky thing about forEach() is that it can be called + // re-entrantly. The queue may be mutated inside the callback. It is easy to + // see that push() within the callback has no negative effects since the end + // of the queue is checked for on every iteration. If shift() is called + // repeatedly within the callback then the next iteration may return an + // element that has been removed. In this case the callback will be called + // with undefined values until we either "catch up" with elements that still + // exist or reach the back of the queue. + forEach(callback) { + let i = this._cursor; + let node = this._front; + let elements = node._elements; + while (i !== elements.length || node._next !== undefined) { + if (i === elements.length) { + node = node._next; + elements = node._elements; + i = 0; + if (elements.length === 0) { + break; + } + } + callback(elements[i]); + ++i; + } + } + // Return the element that would be returned if shift() was called now, + // without modifying the queue. + peek() { // must not be called on an empty queue + const front = this._front; + const cursor = this._cursor; + return front._elements[cursor]; + } + } + + function ReadableStreamReaderGenericInitialize(reader, stream) { + reader._ownerReadableStream = stream; + stream._reader = reader; + if (stream._state === 'readable') { + defaultReaderClosedPromiseInitialize(reader); + } + else if (stream._state === 'closed') { + defaultReaderClosedPromiseInitializeAsResolved(reader); + } + else { + defaultReaderClosedPromiseInitializeAsRejected(reader, stream._storedError); + } + } + // A client of ReadableStreamDefaultReader and ReadableStreamBYOBReader may use these functions directly to bypass state + // check. + function ReadableStreamReaderGenericCancel(reader, reason) { + const stream = reader._ownerReadableStream; + return ReadableStreamCancel(stream, reason); + } + function ReadableStreamReaderGenericRelease(reader) { + if (reader._ownerReadableStream._state === 'readable') { + defaultReaderClosedPromiseReject(reader, new TypeError(`Reader was released and can no longer be used to monitor the stream's closedness`)); + } + else { + defaultReaderClosedPromiseResetToRejected(reader, new TypeError(`Reader was released and can no longer be used to monitor the stream's closedness`)); + } + reader._ownerReadableStream._reader = undefined; + reader._ownerReadableStream = undefined; + } + // Helper functions for the readers. + function readerLockException(name) { + return new TypeError('Cannot ' + name + ' a stream using a released reader'); + } + // Helper functions for the ReadableStreamDefaultReader. + function defaultReaderClosedPromiseInitialize(reader) { + reader._closedPromise = newPromise((resolve, reject) => { + reader._closedPromise_resolve = resolve; + reader._closedPromise_reject = reject; + }); + } + function defaultReaderClosedPromiseInitializeAsRejected(reader, reason) { + defaultReaderClosedPromiseInitialize(reader); + defaultReaderClosedPromiseReject(reader, reason); + } + function defaultReaderClosedPromiseInitializeAsResolved(reader) { + defaultReaderClosedPromiseInitialize(reader); + defaultReaderClosedPromiseResolve(reader); + } + function defaultReaderClosedPromiseReject(reader, reason) { + if (reader._closedPromise_reject === undefined) { + return; + } + setPromiseIsHandledToTrue(reader._closedPromise); + reader._closedPromise_reject(reason); + reader._closedPromise_resolve = undefined; + reader._closedPromise_reject = undefined; + } + function defaultReaderClosedPromiseResetToRejected(reader, reason) { + defaultReaderClosedPromiseInitializeAsRejected(reader, reason); + } + function defaultReaderClosedPromiseResolve(reader) { + if (reader._closedPromise_resolve === undefined) { + return; + } + reader._closedPromise_resolve(undefined); + reader._closedPromise_resolve = undefined; + reader._closedPromise_reject = undefined; + } + + const AbortSteps = SymbolPolyfill('[[AbortSteps]]'); + const ErrorSteps = SymbolPolyfill('[[ErrorSteps]]'); + const CancelSteps = SymbolPolyfill('[[CancelSteps]]'); + const PullSteps = SymbolPolyfill('[[PullSteps]]'); + + /// + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isFinite#Polyfill + const NumberIsFinite = Number.isFinite || function (x) { + return typeof x === 'number' && isFinite(x); + }; + + /// + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc#Polyfill + const MathTrunc = Math.trunc || function (v) { + return v < 0 ? Math.ceil(v) : Math.floor(v); + }; + + // https://heycam.github.io/webidl/#idl-dictionaries + function isDictionary(x) { + return typeof x === 'object' || typeof x === 'function'; + } + function assertDictionary(obj, context) { + if (obj !== undefined && !isDictionary(obj)) { + throw new TypeError(`${context} is not an object.`); + } + } + // https://heycam.github.io/webidl/#idl-callback-functions + function assertFunction(x, context) { + if (typeof x !== 'function') { + throw new TypeError(`${context} is not a function.`); + } + } + // https://heycam.github.io/webidl/#idl-object + function isObject(x) { + return (typeof x === 'object' && x !== null) || typeof x === 'function'; + } + function assertObject(x, context) { + if (!isObject(x)) { + throw new TypeError(`${context} is not an object.`); + } + } + function assertRequiredArgument(x, position, context) { + if (x === undefined) { + throw new TypeError(`Parameter ${position} is required in '${context}'.`); + } + } + function assertRequiredField(x, field, context) { + if (x === undefined) { + throw new TypeError(`${field} is required in '${context}'.`); + } + } + // https://heycam.github.io/webidl/#idl-unrestricted-double + function convertUnrestrictedDouble(value) { + return Number(value); + } + function censorNegativeZero(x) { + return x === 0 ? 0 : x; + } + function integerPart(x) { + return censorNegativeZero(MathTrunc(x)); + } + // https://heycam.github.io/webidl/#idl-unsigned-long-long + function convertUnsignedLongLongWithEnforceRange(value, context) { + const lowerBound = 0; + const upperBound = Number.MAX_SAFE_INTEGER; + let x = Number(value); + x = censorNegativeZero(x); + if (!NumberIsFinite(x)) { + throw new TypeError(`${context} is not a finite number`); + } + x = integerPart(x); + if (x < lowerBound || x > upperBound) { + throw new TypeError(`${context} is outside the accepted range of ${lowerBound} to ${upperBound}, inclusive`); + } + if (!NumberIsFinite(x) || x === 0) { + return 0; + } + // TODO Use BigInt if supported? + // let xBigInt = BigInt(integerPart(x)); + // xBigInt = BigInt.asUintN(64, xBigInt); + // return Number(xBigInt); + return x; + } + + function assertReadableStream(x, context) { + if (!IsReadableStream(x)) { + throw new TypeError(`${context} is not a ReadableStream.`); + } + } + + // Abstract operations for the ReadableStream. + function AcquireReadableStreamDefaultReader(stream) { + return new ReadableStreamDefaultReader(stream); + } + // ReadableStream API exposed for controllers. + function ReadableStreamAddReadRequest(stream, readRequest) { + stream._reader._readRequests.push(readRequest); + } + function ReadableStreamFulfillReadRequest(stream, chunk, done) { + const reader = stream._reader; + const readRequest = reader._readRequests.shift(); + if (done) { + readRequest._closeSteps(); + } + else { + readRequest._chunkSteps(chunk); + } + } + function ReadableStreamGetNumReadRequests(stream) { + return stream._reader._readRequests.length; + } + function ReadableStreamHasDefaultReader(stream) { + const reader = stream._reader; + if (reader === undefined) { + return false; + } + if (!IsReadableStreamDefaultReader(reader)) { + return false; + } + return true; + } + /** + * A default reader vended by a {@link ReadableStream}. + * + * @public + */ + class ReadableStreamDefaultReader { + constructor(stream) { + assertRequiredArgument(stream, 1, 'ReadableStreamDefaultReader'); + assertReadableStream(stream, 'First parameter'); + if (IsReadableStreamLocked(stream)) { + throw new TypeError('This stream has already been locked for exclusive reading by another reader'); + } + ReadableStreamReaderGenericInitialize(this, stream); + this._readRequests = new SimpleQueue(); + } + /** + * Returns a promise that will be fulfilled when the stream becomes closed, + * or rejected if the stream ever errors or the reader's lock is released before the stream finishes closing. + */ + get closed() { + if (!IsReadableStreamDefaultReader(this)) { + return promiseRejectedWith(defaultReaderBrandCheckException('closed')); + } + return this._closedPromise; + } + /** + * If the reader is active, behaves the same as {@link ReadableStream.cancel | stream.cancel(reason)}. + */ + cancel(reason = undefined) { + if (!IsReadableStreamDefaultReader(this)) { + return promiseRejectedWith(defaultReaderBrandCheckException('cancel')); + } + if (this._ownerReadableStream === undefined) { + return promiseRejectedWith(readerLockException('cancel')); + } + return ReadableStreamReaderGenericCancel(this, reason); + } + /** + * Returns a promise that allows access to the next chunk from the stream's internal queue, if available. + * + * If reading a chunk causes the queue to become empty, more data will be pulled from the underlying source. + */ + read() { + if (!IsReadableStreamDefaultReader(this)) { + return promiseRejectedWith(defaultReaderBrandCheckException('read')); + } + if (this._ownerReadableStream === undefined) { + return promiseRejectedWith(readerLockException('read from')); + } + let resolvePromise; + let rejectPromise; + const promise = newPromise((resolve, reject) => { + resolvePromise = resolve; + rejectPromise = reject; + }); + const readRequest = { + _chunkSteps: chunk => resolvePromise({ value: chunk, done: false }), + _closeSteps: () => resolvePromise({ value: undefined, done: true }), + _errorSteps: e => rejectPromise(e) + }; + ReadableStreamDefaultReaderRead(this, readRequest); + return promise; + } + /** + * Releases the reader's lock on the corresponding stream. After the lock is released, the reader is no longer active. + * If the associated stream is errored when the lock is released, the reader will appear errored in the same way + * from now on; otherwise, the reader will appear closed. + * + * A reader's lock cannot be released while it still has a pending read request, i.e., if a promise returned by + * the reader's {@link ReadableStreamDefaultReader.read | read()} method has not yet been settled. Attempting to + * do so will throw a `TypeError` and leave the reader locked to the stream. + */ + releaseLock() { + if (!IsReadableStreamDefaultReader(this)) { + throw defaultReaderBrandCheckException('releaseLock'); + } + if (this._ownerReadableStream === undefined) { + return; + } + if (this._readRequests.length > 0) { + throw new TypeError('Tried to release a reader lock when that reader has pending read() calls un-settled'); + } + ReadableStreamReaderGenericRelease(this); + } + } + Object.defineProperties(ReadableStreamDefaultReader.prototype, { + cancel: { enumerable: true }, + read: { enumerable: true }, + releaseLock: { enumerable: true }, + closed: { enumerable: true } + }); + if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(ReadableStreamDefaultReader.prototype, SymbolPolyfill.toStringTag, { + value: 'ReadableStreamDefaultReader', + configurable: true + }); + } + // Abstract operations for the readers. + function IsReadableStreamDefaultReader(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_readRequests')) { + return false; + } + return true; + } + function ReadableStreamDefaultReaderRead(reader, readRequest) { + const stream = reader._ownerReadableStream; + stream._disturbed = true; + if (stream._state === 'closed') { + readRequest._closeSteps(); + } + else if (stream._state === 'errored') { + readRequest._errorSteps(stream._storedError); + } + else { + stream._readableStreamController[PullSteps](readRequest); + } + } + // Helper functions for the ReadableStreamDefaultReader. + function defaultReaderBrandCheckException(name) { + return new TypeError(`ReadableStreamDefaultReader.prototype.${name} can only be used on a ReadableStreamDefaultReader`); + } + + /// + let AsyncIteratorPrototype; + if (typeof SymbolPolyfill.asyncIterator === 'symbol') { + // We're running inside a ES2018+ environment, but we're compiling to an older syntax. + // We cannot access %AsyncIteratorPrototype% without non-ES2018 syntax, but we can re-create it. + AsyncIteratorPrototype = { + // 25.1.3.1 %AsyncIteratorPrototype% [ @@asyncIterator ] ( ) + // https://tc39.github.io/ecma262/#sec-asynciteratorprototype-asynciterator + [SymbolPolyfill.asyncIterator]() { + return this; + } + }; + Object.defineProperty(AsyncIteratorPrototype, SymbolPolyfill.asyncIterator, { enumerable: false }); + } + + /// + class ReadableStreamAsyncIteratorImpl { + constructor(reader, preventCancel) { + this._ongoingPromise = undefined; + this._isFinished = false; + this._reader = reader; + this._preventCancel = preventCancel; + } + next() { + const nextSteps = () => this._nextSteps(); + this._ongoingPromise = this._ongoingPromise ? + transformPromiseWith(this._ongoingPromise, nextSteps, nextSteps) : + nextSteps(); + return this._ongoingPromise; + } + return(value) { + const returnSteps = () => this._returnSteps(value); + return this._ongoingPromise ? + transformPromiseWith(this._ongoingPromise, returnSteps, returnSteps) : + returnSteps(); + } + _nextSteps() { + if (this._isFinished) { + return Promise.resolve({ value: undefined, done: true }); + } + const reader = this._reader; + if (reader._ownerReadableStream === undefined) { + return promiseRejectedWith(readerLockException('iterate')); + } + let resolvePromise; + let rejectPromise; + const promise = newPromise((resolve, reject) => { + resolvePromise = resolve; + rejectPromise = reject; + }); + const readRequest = { + _chunkSteps: chunk => { + this._ongoingPromise = undefined; + // This needs to be delayed by one microtask, otherwise we stop pulling too early which breaks a test. + // FIXME Is this a bug in the specification, or in the test? + queueMicrotask(() => resolvePromise({ value: chunk, done: false })); + }, + _closeSteps: () => { + this._ongoingPromise = undefined; + this._isFinished = true; + ReadableStreamReaderGenericRelease(reader); + resolvePromise({ value: undefined, done: true }); + }, + _errorSteps: reason => { + this._ongoingPromise = undefined; + this._isFinished = true; + ReadableStreamReaderGenericRelease(reader); + rejectPromise(reason); + } + }; + ReadableStreamDefaultReaderRead(reader, readRequest); + return promise; + } + _returnSteps(value) { + if (this._isFinished) { + return Promise.resolve({ value, done: true }); + } + this._isFinished = true; + const reader = this._reader; + if (reader._ownerReadableStream === undefined) { + return promiseRejectedWith(readerLockException('finish iterating')); + } + if (!this._preventCancel) { + const result = ReadableStreamReaderGenericCancel(reader, value); + ReadableStreamReaderGenericRelease(reader); + return transformPromiseWith(result, () => ({ value, done: true })); + } + ReadableStreamReaderGenericRelease(reader); + return promiseResolvedWith({ value, done: true }); + } + } + const ReadableStreamAsyncIteratorPrototype = { + next() { + if (!IsReadableStreamAsyncIterator(this)) { + return promiseRejectedWith(streamAsyncIteratorBrandCheckException('next')); + } + return this._asyncIteratorImpl.next(); + }, + return(value) { + if (!IsReadableStreamAsyncIterator(this)) { + return promiseRejectedWith(streamAsyncIteratorBrandCheckException('return')); + } + return this._asyncIteratorImpl.return(value); + } + }; + if (AsyncIteratorPrototype !== undefined) { + Object.setPrototypeOf(ReadableStreamAsyncIteratorPrototype, AsyncIteratorPrototype); + } + // Abstract operations for the ReadableStream. + function AcquireReadableStreamAsyncIterator(stream, preventCancel) { + const reader = AcquireReadableStreamDefaultReader(stream); + const impl = new ReadableStreamAsyncIteratorImpl(reader, preventCancel); + const iterator = Object.create(ReadableStreamAsyncIteratorPrototype); + iterator._asyncIteratorImpl = impl; + return iterator; + } + function IsReadableStreamAsyncIterator(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_asyncIteratorImpl')) { + return false; + } + return true; + } + // Helper functions for the ReadableStream. + function streamAsyncIteratorBrandCheckException(name) { + return new TypeError(`ReadableStreamAsyncIterator.${name} can only be used on a ReadableSteamAsyncIterator`); + } + + /// + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN#Polyfill + const NumberIsNaN = Number.isNaN || function (x) { + // eslint-disable-next-line no-self-compare + return x !== x; + }; + + function IsFiniteNonNegativeNumber(v) { + if (!IsNonNegativeNumber(v)) { + return false; + } + if (v === Infinity) { + return false; + } + return true; + } + function IsNonNegativeNumber(v) { + if (typeof v !== 'number') { + return false; + } + if (NumberIsNaN(v)) { + return false; + } + if (v < 0) { + return false; + } + return true; + } + + function DequeueValue(container) { + const pair = container._queue.shift(); + container._queueTotalSize -= pair.size; + if (container._queueTotalSize < 0) { + container._queueTotalSize = 0; + } + return pair.value; + } + function EnqueueValueWithSize(container, value, size) { + size = Number(size); + if (!IsFiniteNonNegativeNumber(size)) { + throw new RangeError('Size must be a finite, non-NaN, non-negative number.'); + } + container._queue.push({ value, size }); + container._queueTotalSize += size; + } + function PeekQueueValue(container) { + const pair = container._queue.peek(); + return pair.value; + } + function ResetQueue(container) { + container._queue = new SimpleQueue(); + container._queueTotalSize = 0; + } + + function CreateArrayFromList(elements) { + // We use arrays to represent lists, so this is basically a no-op. + // Do a slice though just in case we happen to depend on the unique-ness. + return elements.slice(); + } + function CopyDataBlockBytes(dest, destOffset, src, srcOffset, n) { + new Uint8Array(dest).set(new Uint8Array(src, srcOffset, n), destOffset); + } + // Not implemented correctly + function TransferArrayBuffer(O) { + return O; + } + // Not implemented correctly + function IsDetachedBuffer(O) { + return false; + } + + /** + * A pull-into request in a {@link ReadableByteStreamController}. + * + * @public + */ + class ReadableStreamBYOBRequest { + constructor() { + throw new TypeError('Illegal constructor'); + } + /** + * Returns the view for writing in to, or `null` if the BYOB request has already been responded to. + */ + get view() { + if (!IsReadableStreamBYOBRequest(this)) { + throw byobRequestBrandCheckException('view'); + } + return this._view; + } + respond(bytesWritten) { + if (!IsReadableStreamBYOBRequest(this)) { + throw byobRequestBrandCheckException('respond'); + } + assertRequiredArgument(bytesWritten, 1, 'respond'); + bytesWritten = convertUnsignedLongLongWithEnforceRange(bytesWritten, 'First parameter'); + if (this._associatedReadableByteStreamController === undefined) { + throw new TypeError('This BYOB request has been invalidated'); + } + if (IsDetachedBuffer(this._view.buffer)) ; + ReadableByteStreamControllerRespond(this._associatedReadableByteStreamController, bytesWritten); + } + respondWithNewView(view) { + if (!IsReadableStreamBYOBRequest(this)) { + throw byobRequestBrandCheckException('respondWithNewView'); + } + assertRequiredArgument(view, 1, 'respondWithNewView'); + if (!ArrayBuffer.isView(view)) { + throw new TypeError('You can only respond with array buffer views'); + } + if (view.byteLength === 0) { + throw new TypeError('chunk must have non-zero byteLength'); + } + if (view.buffer.byteLength === 0) { + throw new TypeError(`chunk's buffer must have non-zero byteLength`); + } + if (this._associatedReadableByteStreamController === undefined) { + throw new TypeError('This BYOB request has been invalidated'); + } + ReadableByteStreamControllerRespondWithNewView(this._associatedReadableByteStreamController, view); + } + } + Object.defineProperties(ReadableStreamBYOBRequest.prototype, { + respond: { enumerable: true }, + respondWithNewView: { enumerable: true }, + view: { enumerable: true } + }); + if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(ReadableStreamBYOBRequest.prototype, SymbolPolyfill.toStringTag, { + value: 'ReadableStreamBYOBRequest', + configurable: true + }); + } + /** + * Allows control of a {@link ReadableStream | readable byte stream}'s state and internal queue. + * + * @public + */ + class ReadableByteStreamController { + constructor() { + throw new TypeError('Illegal constructor'); + } + /** + * Returns the current BYOB pull request, or `null` if there isn't one. + */ + get byobRequest() { + if (!IsReadableByteStreamController(this)) { + throw byteStreamControllerBrandCheckException('byobRequest'); + } + if (this._byobRequest === null && this._pendingPullIntos.length > 0) { + const firstDescriptor = this._pendingPullIntos.peek(); + const view = new Uint8Array(firstDescriptor.buffer, firstDescriptor.byteOffset + firstDescriptor.bytesFilled, firstDescriptor.byteLength - firstDescriptor.bytesFilled); + const byobRequest = Object.create(ReadableStreamBYOBRequest.prototype); + SetUpReadableStreamBYOBRequest(byobRequest, this, view); + this._byobRequest = byobRequest; + } + return this._byobRequest; + } + /** + * Returns the desired size to fill the controlled stream's internal queue. It can be negative, if the queue is + * over-full. An underlying byte source ought to use this information to determine when and how to apply backpressure. + */ + get desiredSize() { + if (!IsReadableByteStreamController(this)) { + throw byteStreamControllerBrandCheckException('desiredSize'); + } + return ReadableByteStreamControllerGetDesiredSize(this); + } + /** + * Closes the controlled readable stream. Consumers will still be able to read any previously-enqueued chunks from + * the stream, but once those are read, the stream will become closed. + */ + close() { + if (!IsReadableByteStreamController(this)) { + throw byteStreamControllerBrandCheckException('close'); + } + if (this._closeRequested) { + throw new TypeError('The stream has already been closed; do not close it again!'); + } + const state = this._controlledReadableByteStream._state; + if (state !== 'readable') { + throw new TypeError(`The stream (in ${state} state) is not in the readable state and cannot be closed`); + } + ReadableByteStreamControllerClose(this); + } + enqueue(chunk) { + if (!IsReadableByteStreamController(this)) { + throw byteStreamControllerBrandCheckException('enqueue'); + } + assertRequiredArgument(chunk, 1, 'enqueue'); + if (!ArrayBuffer.isView(chunk)) { + throw new TypeError('chunk must be an array buffer view'); + } + if (chunk.byteLength === 0) { + throw new TypeError('chunk must have non-zero byteLength'); + } + if (chunk.buffer.byteLength === 0) { + throw new TypeError(`chunk's buffer must have non-zero byteLength`); + } + if (this._closeRequested) { + throw new TypeError('stream is closed or draining'); + } + const state = this._controlledReadableByteStream._state; + if (state !== 'readable') { + throw new TypeError(`The stream (in ${state} state) is not in the readable state and cannot be enqueued to`); + } + ReadableByteStreamControllerEnqueue(this, chunk); + } + /** + * Errors the controlled readable stream, making all future interactions with it fail with the given error `e`. + */ + error(e = undefined) { + if (!IsReadableByteStreamController(this)) { + throw byteStreamControllerBrandCheckException('error'); + } + ReadableByteStreamControllerError(this, e); + } + /** @internal */ + [CancelSteps](reason) { + if (this._pendingPullIntos.length > 0) { + const firstDescriptor = this._pendingPullIntos.peek(); + firstDescriptor.bytesFilled = 0; + } + ResetQueue(this); + const result = this._cancelAlgorithm(reason); + ReadableByteStreamControllerClearAlgorithms(this); + return result; + } + /** @internal */ + [PullSteps](readRequest) { + const stream = this._controlledReadableByteStream; + if (this._queueTotalSize > 0) { + const entry = this._queue.shift(); + this._queueTotalSize -= entry.byteLength; + ReadableByteStreamControllerHandleQueueDrain(this); + const view = new Uint8Array(entry.buffer, entry.byteOffset, entry.byteLength); + readRequest._chunkSteps(view); + return; + } + const autoAllocateChunkSize = this._autoAllocateChunkSize; + if (autoAllocateChunkSize !== undefined) { + let buffer; + try { + buffer = new ArrayBuffer(autoAllocateChunkSize); + } + catch (bufferE) { + readRequest._errorSteps(bufferE); + return; + } + const pullIntoDescriptor = { + buffer, + byteOffset: 0, + byteLength: autoAllocateChunkSize, + bytesFilled: 0, + elementSize: 1, + viewConstructor: Uint8Array, + readerType: 'default' + }; + this._pendingPullIntos.push(pullIntoDescriptor); + } + ReadableStreamAddReadRequest(stream, readRequest); + ReadableByteStreamControllerCallPullIfNeeded(this); + } + } + Object.defineProperties(ReadableByteStreamController.prototype, { + close: { enumerable: true }, + enqueue: { enumerable: true }, + error: { enumerable: true }, + byobRequest: { enumerable: true }, + desiredSize: { enumerable: true } + }); + if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(ReadableByteStreamController.prototype, SymbolPolyfill.toStringTag, { + value: 'ReadableByteStreamController', + configurable: true + }); + } + // Abstract operations for the ReadableByteStreamController. + function IsReadableByteStreamController(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_controlledReadableByteStream')) { + return false; + } + return true; + } + function IsReadableStreamBYOBRequest(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_associatedReadableByteStreamController')) { + return false; + } + return true; + } + function ReadableByteStreamControllerCallPullIfNeeded(controller) { + const shouldPull = ReadableByteStreamControllerShouldCallPull(controller); + if (!shouldPull) { + return; + } + if (controller._pulling) { + controller._pullAgain = true; + return; + } + controller._pulling = true; + // TODO: Test controller argument + const pullPromise = controller._pullAlgorithm(); + uponPromise(pullPromise, () => { + controller._pulling = false; + if (controller._pullAgain) { + controller._pullAgain = false; + ReadableByteStreamControllerCallPullIfNeeded(controller); + } + }, e => { + ReadableByteStreamControllerError(controller, e); + }); + } + function ReadableByteStreamControllerClearPendingPullIntos(controller) { + ReadableByteStreamControllerInvalidateBYOBRequest(controller); + controller._pendingPullIntos = new SimpleQueue(); + } + function ReadableByteStreamControllerCommitPullIntoDescriptor(stream, pullIntoDescriptor) { + let done = false; + if (stream._state === 'closed') { + done = true; + } + const filledView = ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor); + if (pullIntoDescriptor.readerType === 'default') { + ReadableStreamFulfillReadRequest(stream, filledView, done); + } + else { + ReadableStreamFulfillReadIntoRequest(stream, filledView, done); + } + } + function ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor) { + const bytesFilled = pullIntoDescriptor.bytesFilled; + const elementSize = pullIntoDescriptor.elementSize; + return new pullIntoDescriptor.viewConstructor(pullIntoDescriptor.buffer, pullIntoDescriptor.byteOffset, bytesFilled / elementSize); + } + function ReadableByteStreamControllerEnqueueChunkToQueue(controller, buffer, byteOffset, byteLength) { + controller._queue.push({ buffer, byteOffset, byteLength }); + controller._queueTotalSize += byteLength; + } + function ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor) { + const elementSize = pullIntoDescriptor.elementSize; + const currentAlignedBytes = pullIntoDescriptor.bytesFilled - pullIntoDescriptor.bytesFilled % elementSize; + const maxBytesToCopy = Math.min(controller._queueTotalSize, pullIntoDescriptor.byteLength - pullIntoDescriptor.bytesFilled); + const maxBytesFilled = pullIntoDescriptor.bytesFilled + maxBytesToCopy; + const maxAlignedBytes = maxBytesFilled - maxBytesFilled % elementSize; + let totalBytesToCopyRemaining = maxBytesToCopy; + let ready = false; + if (maxAlignedBytes > currentAlignedBytes) { + totalBytesToCopyRemaining = maxAlignedBytes - pullIntoDescriptor.bytesFilled; + ready = true; + } + const queue = controller._queue; + while (totalBytesToCopyRemaining > 0) { + const headOfQueue = queue.peek(); + const bytesToCopy = Math.min(totalBytesToCopyRemaining, headOfQueue.byteLength); + const destStart = pullIntoDescriptor.byteOffset + pullIntoDescriptor.bytesFilled; + CopyDataBlockBytes(pullIntoDescriptor.buffer, destStart, headOfQueue.buffer, headOfQueue.byteOffset, bytesToCopy); + if (headOfQueue.byteLength === bytesToCopy) { + queue.shift(); + } + else { + headOfQueue.byteOffset += bytesToCopy; + headOfQueue.byteLength -= bytesToCopy; + } + controller._queueTotalSize -= bytesToCopy; + ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, bytesToCopy, pullIntoDescriptor); + totalBytesToCopyRemaining -= bytesToCopy; + } + return ready; + } + function ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, size, pullIntoDescriptor) { + ReadableByteStreamControllerInvalidateBYOBRequest(controller); + pullIntoDescriptor.bytesFilled += size; + } + function ReadableByteStreamControllerHandleQueueDrain(controller) { + if (controller._queueTotalSize === 0 && controller._closeRequested) { + ReadableByteStreamControllerClearAlgorithms(controller); + ReadableStreamClose(controller._controlledReadableByteStream); + } + else { + ReadableByteStreamControllerCallPullIfNeeded(controller); + } + } + function ReadableByteStreamControllerInvalidateBYOBRequest(controller) { + if (controller._byobRequest === null) { + return; + } + controller._byobRequest._associatedReadableByteStreamController = undefined; + controller._byobRequest._view = null; + controller._byobRequest = null; + } + function ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller) { + while (controller._pendingPullIntos.length > 0) { + if (controller._queueTotalSize === 0) { + return; + } + const pullIntoDescriptor = controller._pendingPullIntos.peek(); + if (ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor)) { + ReadableByteStreamControllerShiftPendingPullInto(controller); + ReadableByteStreamControllerCommitPullIntoDescriptor(controller._controlledReadableByteStream, pullIntoDescriptor); + } + } + } + function ReadableByteStreamControllerPullInto(controller, view, readIntoRequest) { + const stream = controller._controlledReadableByteStream; + let elementSize = 1; + if (view.constructor !== DataView) { + elementSize = view.constructor.BYTES_PER_ELEMENT; + } + const ctor = view.constructor; + const buffer = TransferArrayBuffer(view.buffer); + const pullIntoDescriptor = { + buffer, + byteOffset: view.byteOffset, + byteLength: view.byteLength, + bytesFilled: 0, + elementSize, + viewConstructor: ctor, + readerType: 'byob' + }; + if (controller._pendingPullIntos.length > 0) { + controller._pendingPullIntos.push(pullIntoDescriptor); + // No ReadableByteStreamControllerCallPullIfNeeded() call since: + // - No change happens on desiredSize + // - The source has already been notified of that there's at least 1 pending read(view) + ReadableStreamAddReadIntoRequest(stream, readIntoRequest); + return; + } + if (stream._state === 'closed') { + const emptyView = new ctor(pullIntoDescriptor.buffer, pullIntoDescriptor.byteOffset, 0); + readIntoRequest._closeSteps(emptyView); + return; + } + if (controller._queueTotalSize > 0) { + if (ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor)) { + const filledView = ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor); + ReadableByteStreamControllerHandleQueueDrain(controller); + readIntoRequest._chunkSteps(filledView); + return; + } + if (controller._closeRequested) { + const e = new TypeError('Insufficient bytes to fill elements in the given buffer'); + ReadableByteStreamControllerError(controller, e); + readIntoRequest._errorSteps(e); + return; + } + } + controller._pendingPullIntos.push(pullIntoDescriptor); + ReadableStreamAddReadIntoRequest(stream, readIntoRequest); + ReadableByteStreamControllerCallPullIfNeeded(controller); + } + function ReadableByteStreamControllerRespondInClosedState(controller, firstDescriptor) { + firstDescriptor.buffer = TransferArrayBuffer(firstDescriptor.buffer); + const stream = controller._controlledReadableByteStream; + if (ReadableStreamHasBYOBReader(stream)) { + while (ReadableStreamGetNumReadIntoRequests(stream) > 0) { + const pullIntoDescriptor = ReadableByteStreamControllerShiftPendingPullInto(controller); + ReadableByteStreamControllerCommitPullIntoDescriptor(stream, pullIntoDescriptor); + } + } + } + function ReadableByteStreamControllerRespondInReadableState(controller, bytesWritten, pullIntoDescriptor) { + if (pullIntoDescriptor.bytesFilled + bytesWritten > pullIntoDescriptor.byteLength) { + throw new RangeError('bytesWritten out of range'); + } + ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, bytesWritten, pullIntoDescriptor); + if (pullIntoDescriptor.bytesFilled < pullIntoDescriptor.elementSize) { + // TODO: Figure out whether we should detach the buffer or not here. + return; + } + ReadableByteStreamControllerShiftPendingPullInto(controller); + const remainderSize = pullIntoDescriptor.bytesFilled % pullIntoDescriptor.elementSize; + if (remainderSize > 0) { + const end = pullIntoDescriptor.byteOffset + pullIntoDescriptor.bytesFilled; + const remainder = pullIntoDescriptor.buffer.slice(end - remainderSize, end); + ReadableByteStreamControllerEnqueueChunkToQueue(controller, remainder, 0, remainder.byteLength); + } + pullIntoDescriptor.buffer = TransferArrayBuffer(pullIntoDescriptor.buffer); + pullIntoDescriptor.bytesFilled -= remainderSize; + ReadableByteStreamControllerCommitPullIntoDescriptor(controller._controlledReadableByteStream, pullIntoDescriptor); + ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller); + } + function ReadableByteStreamControllerRespondInternal(controller, bytesWritten) { + const firstDescriptor = controller._pendingPullIntos.peek(); + const state = controller._controlledReadableByteStream._state; + if (state === 'closed') { + if (bytesWritten !== 0) { + throw new TypeError('bytesWritten must be 0 when calling respond() on a closed stream'); + } + ReadableByteStreamControllerRespondInClosedState(controller, firstDescriptor); + } + else { + ReadableByteStreamControllerRespondInReadableState(controller, bytesWritten, firstDescriptor); + } + ReadableByteStreamControllerCallPullIfNeeded(controller); + } + function ReadableByteStreamControllerShiftPendingPullInto(controller) { + const descriptor = controller._pendingPullIntos.shift(); + ReadableByteStreamControllerInvalidateBYOBRequest(controller); + return descriptor; + } + function ReadableByteStreamControllerShouldCallPull(controller) { + const stream = controller._controlledReadableByteStream; + if (stream._state !== 'readable') { + return false; + } + if (controller._closeRequested) { + return false; + } + if (!controller._started) { + return false; + } + if (ReadableStreamHasDefaultReader(stream) && ReadableStreamGetNumReadRequests(stream) > 0) { + return true; + } + if (ReadableStreamHasBYOBReader(stream) && ReadableStreamGetNumReadIntoRequests(stream) > 0) { + return true; + } + const desiredSize = ReadableByteStreamControllerGetDesiredSize(controller); + if (desiredSize > 0) { + return true; + } + return false; + } + function ReadableByteStreamControllerClearAlgorithms(controller) { + controller._pullAlgorithm = undefined; + controller._cancelAlgorithm = undefined; + } + // A client of ReadableByteStreamController may use these functions directly to bypass state check. + function ReadableByteStreamControllerClose(controller) { + const stream = controller._controlledReadableByteStream; + if (controller._closeRequested || stream._state !== 'readable') { + return; + } + if (controller._queueTotalSize > 0) { + controller._closeRequested = true; + return; + } + if (controller._pendingPullIntos.length > 0) { + const firstPendingPullInto = controller._pendingPullIntos.peek(); + if (firstPendingPullInto.bytesFilled > 0) { + const e = new TypeError('Insufficient bytes to fill elements in the given buffer'); + ReadableByteStreamControllerError(controller, e); + throw e; + } + } + ReadableByteStreamControllerClearAlgorithms(controller); + ReadableStreamClose(stream); + } + function ReadableByteStreamControllerEnqueue(controller, chunk) { + const stream = controller._controlledReadableByteStream; + if (controller._closeRequested || stream._state !== 'readable') { + return; + } + const buffer = chunk.buffer; + const byteOffset = chunk.byteOffset; + const byteLength = chunk.byteLength; + const transferredBuffer = TransferArrayBuffer(buffer); + if (ReadableStreamHasDefaultReader(stream)) { + if (ReadableStreamGetNumReadRequests(stream) === 0) { + ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength); + } + else { + const transferredView = new Uint8Array(transferredBuffer, byteOffset, byteLength); + ReadableStreamFulfillReadRequest(stream, transferredView, false); + } + } + else if (ReadableStreamHasBYOBReader(stream)) { + // TODO: Ideally in this branch detaching should happen only if the buffer is not consumed fully. + ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength); + ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller); + } + else { + ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength); + } + ReadableByteStreamControllerCallPullIfNeeded(controller); + } + function ReadableByteStreamControllerError(controller, e) { + const stream = controller._controlledReadableByteStream; + if (stream._state !== 'readable') { + return; + } + ReadableByteStreamControllerClearPendingPullIntos(controller); + ResetQueue(controller); + ReadableByteStreamControllerClearAlgorithms(controller); + ReadableStreamError(stream, e); + } + function ReadableByteStreamControllerGetDesiredSize(controller) { + const state = controller._controlledReadableByteStream._state; + if (state === 'errored') { + return null; + } + if (state === 'closed') { + return 0; + } + return controller._strategyHWM - controller._queueTotalSize; + } + function ReadableByteStreamControllerRespond(controller, bytesWritten) { + bytesWritten = Number(bytesWritten); + if (!IsFiniteNonNegativeNumber(bytesWritten)) { + throw new RangeError('bytesWritten must be a finite'); + } + ReadableByteStreamControllerRespondInternal(controller, bytesWritten); + } + function ReadableByteStreamControllerRespondWithNewView(controller, view) { + const firstDescriptor = controller._pendingPullIntos.peek(); + if (firstDescriptor.byteOffset + firstDescriptor.bytesFilled !== view.byteOffset) { + throw new RangeError('The region specified by view does not match byobRequest'); + } + if (firstDescriptor.byteLength !== view.byteLength) { + throw new RangeError('The buffer of view has different capacity than byobRequest'); + } + firstDescriptor.buffer = view.buffer; + ReadableByteStreamControllerRespondInternal(controller, view.byteLength); + } + function SetUpReadableByteStreamController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, autoAllocateChunkSize) { + controller._controlledReadableByteStream = stream; + controller._pullAgain = false; + controller._pulling = false; + controller._byobRequest = null; + // Need to set the slots so that the assert doesn't fire. In the spec the slots already exist implicitly. + controller._queue = controller._queueTotalSize = undefined; + ResetQueue(controller); + controller._closeRequested = false; + controller._started = false; + controller._strategyHWM = highWaterMark; + controller._pullAlgorithm = pullAlgorithm; + controller._cancelAlgorithm = cancelAlgorithm; + controller._autoAllocateChunkSize = autoAllocateChunkSize; + controller._pendingPullIntos = new SimpleQueue(); + stream._readableStreamController = controller; + const startResult = startAlgorithm(); + uponPromise(promiseResolvedWith(startResult), () => { + controller._started = true; + ReadableByteStreamControllerCallPullIfNeeded(controller); + }, r => { + ReadableByteStreamControllerError(controller, r); + }); + } + function SetUpReadableByteStreamControllerFromUnderlyingSource(stream, underlyingByteSource, highWaterMark) { + const controller = Object.create(ReadableByteStreamController.prototype); + let startAlgorithm = () => undefined; + let pullAlgorithm = () => promiseResolvedWith(undefined); + let cancelAlgorithm = () => promiseResolvedWith(undefined); + if (underlyingByteSource.start !== undefined) { + startAlgorithm = () => underlyingByteSource.start(controller); + } + if (underlyingByteSource.pull !== undefined) { + pullAlgorithm = () => underlyingByteSource.pull(controller); + } + if (underlyingByteSource.cancel !== undefined) { + cancelAlgorithm = reason => underlyingByteSource.cancel(reason); + } + const autoAllocateChunkSize = underlyingByteSource.autoAllocateChunkSize; + if (autoAllocateChunkSize === 0) { + throw new TypeError('autoAllocateChunkSize must be greater than 0'); + } + SetUpReadableByteStreamController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, autoAllocateChunkSize); + } + function SetUpReadableStreamBYOBRequest(request, controller, view) { + request._associatedReadableByteStreamController = controller; + request._view = view; + } + // Helper functions for the ReadableStreamBYOBRequest. + function byobRequestBrandCheckException(name) { + return new TypeError(`ReadableStreamBYOBRequest.prototype.${name} can only be used on a ReadableStreamBYOBRequest`); + } + // Helper functions for the ReadableByteStreamController. + function byteStreamControllerBrandCheckException(name) { + return new TypeError(`ReadableByteStreamController.prototype.${name} can only be used on a ReadableByteStreamController`); + } + + // Abstract operations for the ReadableStream. + function AcquireReadableStreamBYOBReader(stream) { + return new ReadableStreamBYOBReader(stream); + } + // ReadableStream API exposed for controllers. + function ReadableStreamAddReadIntoRequest(stream, readIntoRequest) { + stream._reader._readIntoRequests.push(readIntoRequest); + } + function ReadableStreamFulfillReadIntoRequest(stream, chunk, done) { + const reader = stream._reader; + const readIntoRequest = reader._readIntoRequests.shift(); + if (done) { + readIntoRequest._closeSteps(chunk); + } + else { + readIntoRequest._chunkSteps(chunk); + } + } + function ReadableStreamGetNumReadIntoRequests(stream) { + return stream._reader._readIntoRequests.length; + } + function ReadableStreamHasBYOBReader(stream) { + const reader = stream._reader; + if (reader === undefined) { + return false; + } + if (!IsReadableStreamBYOBReader(reader)) { + return false; + } + return true; + } + /** + * A BYOB reader vended by a {@link ReadableStream}. + * + * @public + */ + class ReadableStreamBYOBReader { + constructor(stream) { + assertRequiredArgument(stream, 1, 'ReadableStreamBYOBReader'); + assertReadableStream(stream, 'First parameter'); + if (IsReadableStreamLocked(stream)) { + throw new TypeError('This stream has already been locked for exclusive reading by another reader'); + } + if (!IsReadableByteStreamController(stream._readableStreamController)) { + throw new TypeError('Cannot construct a ReadableStreamBYOBReader for a stream not constructed with a byte ' + + 'source'); + } + ReadableStreamReaderGenericInitialize(this, stream); + this._readIntoRequests = new SimpleQueue(); + } + /** + * Returns a promise that will be fulfilled when the stream becomes closed, or rejected if the stream ever errors or + * the reader's lock is released before the stream finishes closing. + */ + get closed() { + if (!IsReadableStreamBYOBReader(this)) { + return promiseRejectedWith(byobReaderBrandCheckException('closed')); + } + return this._closedPromise; + } + /** + * If the reader is active, behaves the same as {@link ReadableStream.cancel | stream.cancel(reason)}. + */ + cancel(reason = undefined) { + if (!IsReadableStreamBYOBReader(this)) { + return promiseRejectedWith(byobReaderBrandCheckException('cancel')); + } + if (this._ownerReadableStream === undefined) { + return promiseRejectedWith(readerLockException('cancel')); + } + return ReadableStreamReaderGenericCancel(this, reason); + } + /** + * Attempts to reads bytes into view, and returns a promise resolved with the result. + * + * If reading a chunk causes the queue to become empty, more data will be pulled from the underlying source. + */ + read(view) { + if (!IsReadableStreamBYOBReader(this)) { + return promiseRejectedWith(byobReaderBrandCheckException('read')); + } + if (!ArrayBuffer.isView(view)) { + return promiseRejectedWith(new TypeError('view must be an array buffer view')); + } + if (view.byteLength === 0) { + return promiseRejectedWith(new TypeError('view must have non-zero byteLength')); + } + if (view.buffer.byteLength === 0) { + return promiseRejectedWith(new TypeError(`view's buffer must have non-zero byteLength`)); + } + if (this._ownerReadableStream === undefined) { + return promiseRejectedWith(readerLockException('read from')); + } + let resolvePromise; + let rejectPromise; + const promise = newPromise((resolve, reject) => { + resolvePromise = resolve; + rejectPromise = reject; + }); + const readIntoRequest = { + _chunkSteps: chunk => resolvePromise({ value: chunk, done: false }), + _closeSteps: chunk => resolvePromise({ value: chunk, done: true }), + _errorSteps: e => rejectPromise(e) + }; + ReadableStreamBYOBReaderRead(this, view, readIntoRequest); + return promise; + } + /** + * Releases the reader's lock on the corresponding stream. After the lock is released, the reader is no longer active. + * If the associated stream is errored when the lock is released, the reader will appear errored in the same way + * from now on; otherwise, the reader will appear closed. + * + * A reader's lock cannot be released while it still has a pending read request, i.e., if a promise returned by + * the reader's {@link ReadableStreamBYOBReader.read | read()} method has not yet been settled. Attempting to + * do so will throw a `TypeError` and leave the reader locked to the stream. + */ + releaseLock() { + if (!IsReadableStreamBYOBReader(this)) { + throw byobReaderBrandCheckException('releaseLock'); + } + if (this._ownerReadableStream === undefined) { + return; + } + if (this._readIntoRequests.length > 0) { + throw new TypeError('Tried to release a reader lock when that reader has pending read() calls un-settled'); + } + ReadableStreamReaderGenericRelease(this); + } + } + Object.defineProperties(ReadableStreamBYOBReader.prototype, { + cancel: { enumerable: true }, + read: { enumerable: true }, + releaseLock: { enumerable: true }, + closed: { enumerable: true } + }); + if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(ReadableStreamBYOBReader.prototype, SymbolPolyfill.toStringTag, { + value: 'ReadableStreamBYOBReader', + configurable: true + }); + } + // Abstract operations for the readers. + function IsReadableStreamBYOBReader(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_readIntoRequests')) { + return false; + } + return true; + } + function ReadableStreamBYOBReaderRead(reader, view, readIntoRequest) { + const stream = reader._ownerReadableStream; + stream._disturbed = true; + if (stream._state === 'errored') { + readIntoRequest._errorSteps(stream._storedError); + } + else { + ReadableByteStreamControllerPullInto(stream._readableStreamController, view, readIntoRequest); + } + } + // Helper functions for the ReadableStreamBYOBReader. + function byobReaderBrandCheckException(name) { + return new TypeError(`ReadableStreamBYOBReader.prototype.${name} can only be used on a ReadableStreamBYOBReader`); + } + + function ExtractHighWaterMark(strategy, defaultHWM) { + const { highWaterMark } = strategy; + if (highWaterMark === undefined) { + return defaultHWM; + } + if (NumberIsNaN(highWaterMark) || highWaterMark < 0) { + throw new RangeError('Invalid highWaterMark'); + } + return highWaterMark; + } + function ExtractSizeAlgorithm(strategy) { + const { size } = strategy; + if (!size) { + return () => 1; + } + return size; + } + + function convertQueuingStrategy(init, context) { + assertDictionary(init, context); + const highWaterMark = init === null || init === void 0 ? void 0 : init.highWaterMark; + const size = init === null || init === void 0 ? void 0 : init.size; + return { + highWaterMark: highWaterMark === undefined ? undefined : convertUnrestrictedDouble(highWaterMark), + size: size === undefined ? undefined : convertQueuingStrategySize(size, `${context} has member 'size' that`) + }; + } + function convertQueuingStrategySize(fn, context) { + assertFunction(fn, context); + return chunk => convertUnrestrictedDouble(fn(chunk)); + } + + function convertUnderlyingSink(original, context) { + assertDictionary(original, context); + const abort = original === null || original === void 0 ? void 0 : original.abort; + const close = original === null || original === void 0 ? void 0 : original.close; + const start = original === null || original === void 0 ? void 0 : original.start; + const type = original === null || original === void 0 ? void 0 : original.type; + const write = original === null || original === void 0 ? void 0 : original.write; + return { + abort: abort === undefined ? + undefined : + convertUnderlyingSinkAbortCallback(abort, original, `${context} has member 'abort' that`), + close: close === undefined ? + undefined : + convertUnderlyingSinkCloseCallback(close, original, `${context} has member 'close' that`), + start: start === undefined ? + undefined : + convertUnderlyingSinkStartCallback(start, original, `${context} has member 'start' that`), + write: write === undefined ? + undefined : + convertUnderlyingSinkWriteCallback(write, original, `${context} has member 'write' that`), + type + }; + } + function convertUnderlyingSinkAbortCallback(fn, original, context) { + assertFunction(fn, context); + return (reason) => promiseCall(fn, original, [reason]); + } + function convertUnderlyingSinkCloseCallback(fn, original, context) { + assertFunction(fn, context); + return () => promiseCall(fn, original, []); + } + function convertUnderlyingSinkStartCallback(fn, original, context) { + assertFunction(fn, context); + return (controller) => reflectCall(fn, original, [controller]); + } + function convertUnderlyingSinkWriteCallback(fn, original, context) { + assertFunction(fn, context); + return (chunk, controller) => promiseCall(fn, original, [chunk, controller]); + } + + function assertWritableStream(x, context) { + if (!IsWritableStream(x)) { + throw new TypeError(`${context} is not a WritableStream.`); + } + } + + /** + * A writable stream represents a destination for data, into which you can write. + * + * @public + */ + class WritableStream$1 { + constructor(rawUnderlyingSink = {}, rawStrategy = {}) { + if (rawUnderlyingSink === undefined) { + rawUnderlyingSink = null; + } + else { + assertObject(rawUnderlyingSink, 'First parameter'); + } + const strategy = convertQueuingStrategy(rawStrategy, 'Second parameter'); + const underlyingSink = convertUnderlyingSink(rawUnderlyingSink, 'First parameter'); + InitializeWritableStream(this); + const type = underlyingSink.type; + if (type !== undefined) { + throw new RangeError('Invalid type is specified'); + } + const sizeAlgorithm = ExtractSizeAlgorithm(strategy); + const highWaterMark = ExtractHighWaterMark(strategy, 1); + SetUpWritableStreamDefaultControllerFromUnderlyingSink(this, underlyingSink, highWaterMark, sizeAlgorithm); + } + /** + * Returns whether or not the writable stream is locked to a writer. + */ + get locked() { + if (!IsWritableStream(this)) { + throw streamBrandCheckException$2('locked'); + } + return IsWritableStreamLocked(this); + } + /** + * Aborts the stream, signaling that the producer can no longer successfully write to the stream and it is to be + * immediately moved to an errored state, with any queued-up writes discarded. This will also execute any abort + * mechanism of the underlying sink. + * + * The returned promise will fulfill if the stream shuts down successfully, or reject if the underlying sink signaled + * that there was an error doing so. Additionally, it will reject with a `TypeError` (without attempting to cancel + * the stream) if the stream is currently locked. + */ + abort(reason = undefined) { + if (!IsWritableStream(this)) { + return promiseRejectedWith(streamBrandCheckException$2('abort')); + } + if (IsWritableStreamLocked(this)) { + return promiseRejectedWith(new TypeError('Cannot abort a stream that already has a writer')); + } + return WritableStreamAbort(this, reason); + } + /** + * Closes the stream. The underlying sink will finish processing any previously-written chunks, before invoking its + * close behavior. During this time any further attempts to write will fail (without erroring the stream). + * + * The method returns a promise that will fulfill if all remaining chunks are successfully written and the stream + * successfully closes, or rejects if an error is encountered during this process. Additionally, it will reject with + * a `TypeError` (without attempting to cancel the stream) if the stream is currently locked. + */ + close() { + if (!IsWritableStream(this)) { + return promiseRejectedWith(streamBrandCheckException$2('close')); + } + if (IsWritableStreamLocked(this)) { + return promiseRejectedWith(new TypeError('Cannot close a stream that already has a writer')); + } + if (WritableStreamCloseQueuedOrInFlight(this)) { + return promiseRejectedWith(new TypeError('Cannot close an already-closing stream')); + } + return WritableStreamClose(this); + } + /** + * Creates a {@link WritableStreamDefaultWriter | writer} and locks the stream to the new writer. While the stream + * is locked, no other writer can be acquired until this one is released. + * + * This functionality is especially useful for creating abstractions that desire the ability to write to a stream + * without interruption or interleaving. By getting a writer for the stream, you can ensure nobody else can write at + * the same time, which would cause the resulting written data to be unpredictable and probably useless. + */ + getWriter() { + if (!IsWritableStream(this)) { + throw streamBrandCheckException$2('getWriter'); + } + return AcquireWritableStreamDefaultWriter(this); + } + } + Object.defineProperties(WritableStream$1.prototype, { + abort: { enumerable: true }, + close: { enumerable: true }, + getWriter: { enumerable: true }, + locked: { enumerable: true } + }); + if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(WritableStream$1.prototype, SymbolPolyfill.toStringTag, { + value: 'WritableStream', + configurable: true + }); + } + // Abstract operations for the WritableStream. + function AcquireWritableStreamDefaultWriter(stream) { + return new WritableStreamDefaultWriter(stream); + } + // Throws if and only if startAlgorithm throws. + function CreateWritableStream(startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark = 1, sizeAlgorithm = () => 1) { + const stream = Object.create(WritableStream$1.prototype); + InitializeWritableStream(stream); + const controller = Object.create(WritableStreamDefaultController.prototype); + SetUpWritableStreamDefaultController(stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark, sizeAlgorithm); + return stream; + } + function InitializeWritableStream(stream) { + stream._state = 'writable'; + // The error that will be reported by new method calls once the state becomes errored. Only set when [[state]] is + // 'erroring' or 'errored'. May be set to an undefined value. + stream._storedError = undefined; + stream._writer = undefined; + // Initialize to undefined first because the constructor of the controller checks this + // variable to validate the caller. + stream._writableStreamController = undefined; + // This queue is placed here instead of the writer class in order to allow for passing a writer to the next data + // producer without waiting for the queued writes to finish. + stream._writeRequests = new SimpleQueue(); + // Write requests are removed from _writeRequests when write() is called on the underlying sink. This prevents + // them from being erroneously rejected on error. If a write() call is in-flight, the request is stored here. + stream._inFlightWriteRequest = undefined; + // The promise that was returned from writer.close(). Stored here because it may be fulfilled after the writer + // has been detached. + stream._closeRequest = undefined; + // Close request is removed from _closeRequest when close() is called on the underlying sink. This prevents it + // from being erroneously rejected on error. If a close() call is in-flight, the request is stored here. + stream._inFlightCloseRequest = undefined; + // The promise that was returned from writer.abort(). This may also be fulfilled after the writer has detached. + stream._pendingAbortRequest = undefined; + // The backpressure signal set by the controller. + stream._backpressure = false; + } + function IsWritableStream(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_writableStreamController')) { + return false; + } + return true; + } + function IsWritableStreamLocked(stream) { + if (stream._writer === undefined) { + return false; + } + return true; + } + function WritableStreamAbort(stream, reason) { + const state = stream._state; + if (state === 'closed' || state === 'errored') { + return promiseResolvedWith(undefined); + } + if (stream._pendingAbortRequest !== undefined) { + return stream._pendingAbortRequest._promise; + } + let wasAlreadyErroring = false; + if (state === 'erroring') { + wasAlreadyErroring = true; + // reason will not be used, so don't keep a reference to it. + reason = undefined; + } + const promise = newPromise((resolve, reject) => { + stream._pendingAbortRequest = { + _promise: undefined, + _resolve: resolve, + _reject: reject, + _reason: reason, + _wasAlreadyErroring: wasAlreadyErroring + }; + }); + stream._pendingAbortRequest._promise = promise; + if (!wasAlreadyErroring) { + WritableStreamStartErroring(stream, reason); + } + return promise; + } + function WritableStreamClose(stream) { + const state = stream._state; + if (state === 'closed' || state === 'errored') { + return promiseRejectedWith(new TypeError(`The stream (in ${state} state) is not in the writable state and cannot be closed`)); + } + const promise = newPromise((resolve, reject) => { + const closeRequest = { + _resolve: resolve, + _reject: reject + }; + stream._closeRequest = closeRequest; + }); + const writer = stream._writer; + if (writer !== undefined && stream._backpressure && state === 'writable') { + defaultWriterReadyPromiseResolve(writer); + } + WritableStreamDefaultControllerClose(stream._writableStreamController); + return promise; + } + // WritableStream API exposed for controllers. + function WritableStreamAddWriteRequest(stream) { + const promise = newPromise((resolve, reject) => { + const writeRequest = { + _resolve: resolve, + _reject: reject + }; + stream._writeRequests.push(writeRequest); + }); + return promise; + } + function WritableStreamDealWithRejection(stream, error) { + const state = stream._state; + if (state === 'writable') { + WritableStreamStartErroring(stream, error); + return; + } + WritableStreamFinishErroring(stream); + } + function WritableStreamStartErroring(stream, reason) { + const controller = stream._writableStreamController; + stream._state = 'erroring'; + stream._storedError = reason; + const writer = stream._writer; + if (writer !== undefined) { + WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, reason); + } + if (!WritableStreamHasOperationMarkedInFlight(stream) && controller._started) { + WritableStreamFinishErroring(stream); + } + } + function WritableStreamFinishErroring(stream) { + stream._state = 'errored'; + stream._writableStreamController[ErrorSteps](); + const storedError = stream._storedError; + stream._writeRequests.forEach(writeRequest => { + writeRequest._reject(storedError); + }); + stream._writeRequests = new SimpleQueue(); + if (stream._pendingAbortRequest === undefined) { + WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); + return; + } + const abortRequest = stream._pendingAbortRequest; + stream._pendingAbortRequest = undefined; + if (abortRequest._wasAlreadyErroring) { + abortRequest._reject(storedError); + WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); + return; + } + const promise = stream._writableStreamController[AbortSteps](abortRequest._reason); + uponPromise(promise, () => { + abortRequest._resolve(); + WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); + }, (reason) => { + abortRequest._reject(reason); + WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); + }); + } + function WritableStreamFinishInFlightWrite(stream) { + stream._inFlightWriteRequest._resolve(undefined); + stream._inFlightWriteRequest = undefined; + } + function WritableStreamFinishInFlightWriteWithError(stream, error) { + stream._inFlightWriteRequest._reject(error); + stream._inFlightWriteRequest = undefined; + WritableStreamDealWithRejection(stream, error); + } + function WritableStreamFinishInFlightClose(stream) { + stream._inFlightCloseRequest._resolve(undefined); + stream._inFlightCloseRequest = undefined; + const state = stream._state; + if (state === 'erroring') { + // The error was too late to do anything, so it is ignored. + stream._storedError = undefined; + if (stream._pendingAbortRequest !== undefined) { + stream._pendingAbortRequest._resolve(); + stream._pendingAbortRequest = undefined; + } + } + stream._state = 'closed'; + const writer = stream._writer; + if (writer !== undefined) { + defaultWriterClosedPromiseResolve(writer); + } + } + function WritableStreamFinishInFlightCloseWithError(stream, error) { + stream._inFlightCloseRequest._reject(error); + stream._inFlightCloseRequest = undefined; + // Never execute sink abort() after sink close(). + if (stream._pendingAbortRequest !== undefined) { + stream._pendingAbortRequest._reject(error); + stream._pendingAbortRequest = undefined; + } + WritableStreamDealWithRejection(stream, error); + } + // TODO(ricea): Fix alphabetical order. + function WritableStreamCloseQueuedOrInFlight(stream) { + if (stream._closeRequest === undefined && stream._inFlightCloseRequest === undefined) { + return false; + } + return true; + } + function WritableStreamHasOperationMarkedInFlight(stream) { + if (stream._inFlightWriteRequest === undefined && stream._inFlightCloseRequest === undefined) { + return false; + } + return true; + } + function WritableStreamMarkCloseRequestInFlight(stream) { + stream._inFlightCloseRequest = stream._closeRequest; + stream._closeRequest = undefined; + } + function WritableStreamMarkFirstWriteRequestInFlight(stream) { + stream._inFlightWriteRequest = stream._writeRequests.shift(); + } + function WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream) { + if (stream._closeRequest !== undefined) { + stream._closeRequest._reject(stream._storedError); + stream._closeRequest = undefined; + } + const writer = stream._writer; + if (writer !== undefined) { + defaultWriterClosedPromiseReject(writer, stream._storedError); + } + } + function WritableStreamUpdateBackpressure(stream, backpressure) { + const writer = stream._writer; + if (writer !== undefined && backpressure !== stream._backpressure) { + if (backpressure) { + defaultWriterReadyPromiseReset(writer); + } + else { + defaultWriterReadyPromiseResolve(writer); + } + } + stream._backpressure = backpressure; + } + /** + * A default writer vended by a {@link WritableStream}. + * + * @public + */ + class WritableStreamDefaultWriter { + constructor(stream) { + assertRequiredArgument(stream, 1, 'WritableStreamDefaultWriter'); + assertWritableStream(stream, 'First parameter'); + if (IsWritableStreamLocked(stream)) { + throw new TypeError('This stream has already been locked for exclusive writing by another writer'); + } + this._ownerWritableStream = stream; + stream._writer = this; + const state = stream._state; + if (state === 'writable') { + if (!WritableStreamCloseQueuedOrInFlight(stream) && stream._backpressure) { + defaultWriterReadyPromiseInitialize(this); + } + else { + defaultWriterReadyPromiseInitializeAsResolved(this); + } + defaultWriterClosedPromiseInitialize(this); + } + else if (state === 'erroring') { + defaultWriterReadyPromiseInitializeAsRejected(this, stream._storedError); + defaultWriterClosedPromiseInitialize(this); + } + else if (state === 'closed') { + defaultWriterReadyPromiseInitializeAsResolved(this); + defaultWriterClosedPromiseInitializeAsResolved(this); + } + else { + const storedError = stream._storedError; + defaultWriterReadyPromiseInitializeAsRejected(this, storedError); + defaultWriterClosedPromiseInitializeAsRejected(this, storedError); + } + } + /** + * Returns a promise that will be fulfilled when the stream becomes closed, or rejected if the stream ever errors or + * the writer’s lock is released before the stream finishes closing. + */ + get closed() { + if (!IsWritableStreamDefaultWriter(this)) { + return promiseRejectedWith(defaultWriterBrandCheckException('closed')); + } + return this._closedPromise; + } + /** + * Returns the desired size to fill the stream’s internal queue. It can be negative, if the queue is over-full. + * A producer can use this information to determine the right amount of data to write. + * + * It will be `null` if the stream cannot be successfully written to (due to either being errored, or having an abort + * queued up). It will return zero if the stream is closed. And the getter will throw an exception if invoked when + * the writer’s lock is released. + */ + get desiredSize() { + if (!IsWritableStreamDefaultWriter(this)) { + throw defaultWriterBrandCheckException('desiredSize'); + } + if (this._ownerWritableStream === undefined) { + throw defaultWriterLockException('desiredSize'); + } + return WritableStreamDefaultWriterGetDesiredSize(this); + } + /** + * Returns a promise that will be fulfilled when the desired size to fill the stream’s internal queue transitions + * from non-positive to positive, signaling that it is no longer applying backpressure. Once the desired size dips + * back to zero or below, the getter will return a new promise that stays pending until the next transition. + * + * If the stream becomes errored or aborted, or the writer’s lock is released, the returned promise will become + * rejected. + */ + get ready() { + if (!IsWritableStreamDefaultWriter(this)) { + return promiseRejectedWith(defaultWriterBrandCheckException('ready')); + } + return this._readyPromise; + } + /** + * If the reader is active, behaves the same as {@link WritableStream.abort | stream.abort(reason)}. + */ + abort(reason = undefined) { + if (!IsWritableStreamDefaultWriter(this)) { + return promiseRejectedWith(defaultWriterBrandCheckException('abort')); + } + if (this._ownerWritableStream === undefined) { + return promiseRejectedWith(defaultWriterLockException('abort')); + } + return WritableStreamDefaultWriterAbort(this, reason); + } + /** + * If the reader is active, behaves the same as {@link WritableStream.close | stream.close()}. + */ + close() { + if (!IsWritableStreamDefaultWriter(this)) { + return promiseRejectedWith(defaultWriterBrandCheckException('close')); + } + const stream = this._ownerWritableStream; + if (stream === undefined) { + return promiseRejectedWith(defaultWriterLockException('close')); + } + if (WritableStreamCloseQueuedOrInFlight(stream)) { + return promiseRejectedWith(new TypeError('Cannot close an already-closing stream')); + } + return WritableStreamDefaultWriterClose(this); + } + /** + * Releases the writer’s lock on the corresponding stream. After the lock is released, the writer is no longer active. + * If the associated stream is errored when the lock is released, the writer will appear errored in the same way from + * now on; otherwise, the writer will appear closed. + * + * Note that the lock can still be released even if some ongoing writes have not yet finished (i.e. even if the + * promises returned from previous calls to {@link WritableStreamDefaultWriter.write | write()} have not yet settled). + * It’s not necessary to hold the lock on the writer for the duration of the write; the lock instead simply prevents + * other producers from writing in an interleaved manner. + */ + releaseLock() { + if (!IsWritableStreamDefaultWriter(this)) { + throw defaultWriterBrandCheckException('releaseLock'); + } + const stream = this._ownerWritableStream; + if (stream === undefined) { + return; + } + WritableStreamDefaultWriterRelease(this); + } + write(chunk = undefined) { + if (!IsWritableStreamDefaultWriter(this)) { + return promiseRejectedWith(defaultWriterBrandCheckException('write')); + } + if (this._ownerWritableStream === undefined) { + return promiseRejectedWith(defaultWriterLockException('write to')); + } + return WritableStreamDefaultWriterWrite(this, chunk); + } + } + Object.defineProperties(WritableStreamDefaultWriter.prototype, { + abort: { enumerable: true }, + close: { enumerable: true }, + releaseLock: { enumerable: true }, + write: { enumerable: true }, + closed: { enumerable: true }, + desiredSize: { enumerable: true }, + ready: { enumerable: true } + }); + if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(WritableStreamDefaultWriter.prototype, SymbolPolyfill.toStringTag, { + value: 'WritableStreamDefaultWriter', + configurable: true + }); + } + // Abstract operations for the WritableStreamDefaultWriter. + function IsWritableStreamDefaultWriter(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_ownerWritableStream')) { + return false; + } + return true; + } + // A client of WritableStreamDefaultWriter may use these functions directly to bypass state check. + function WritableStreamDefaultWriterAbort(writer, reason) { + const stream = writer._ownerWritableStream; + return WritableStreamAbort(stream, reason); + } + function WritableStreamDefaultWriterClose(writer) { + const stream = writer._ownerWritableStream; + return WritableStreamClose(stream); + } + function WritableStreamDefaultWriterCloseWithErrorPropagation(writer) { + const stream = writer._ownerWritableStream; + const state = stream._state; + if (WritableStreamCloseQueuedOrInFlight(stream) || state === 'closed') { + return promiseResolvedWith(undefined); + } + if (state === 'errored') { + return promiseRejectedWith(stream._storedError); + } + return WritableStreamDefaultWriterClose(writer); + } + function WritableStreamDefaultWriterEnsureClosedPromiseRejected(writer, error) { + if (writer._closedPromiseState === 'pending') { + defaultWriterClosedPromiseReject(writer, error); + } + else { + defaultWriterClosedPromiseResetToRejected(writer, error); + } + } + function WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, error) { + if (writer._readyPromiseState === 'pending') { + defaultWriterReadyPromiseReject(writer, error); + } + else { + defaultWriterReadyPromiseResetToRejected(writer, error); + } + } + function WritableStreamDefaultWriterGetDesiredSize(writer) { + const stream = writer._ownerWritableStream; + const state = stream._state; + if (state === 'errored' || state === 'erroring') { + return null; + } + if (state === 'closed') { + return 0; + } + return WritableStreamDefaultControllerGetDesiredSize(stream._writableStreamController); + } + function WritableStreamDefaultWriterRelease(writer) { + const stream = writer._ownerWritableStream; + const releasedError = new TypeError(`Writer was released and can no longer be used to monitor the stream's closedness`); + WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, releasedError); + // The state transitions to "errored" before the sink abort() method runs, but the writer.closed promise is not + // rejected until afterwards. This means that simply testing state will not work. + WritableStreamDefaultWriterEnsureClosedPromiseRejected(writer, releasedError); + stream._writer = undefined; + writer._ownerWritableStream = undefined; + } + function WritableStreamDefaultWriterWrite(writer, chunk) { + const stream = writer._ownerWritableStream; + const controller = stream._writableStreamController; + const chunkSize = WritableStreamDefaultControllerGetChunkSize(controller, chunk); + if (stream !== writer._ownerWritableStream) { + return promiseRejectedWith(defaultWriterLockException('write to')); + } + const state = stream._state; + if (state === 'errored') { + return promiseRejectedWith(stream._storedError); + } + if (WritableStreamCloseQueuedOrInFlight(stream) || state === 'closed') { + return promiseRejectedWith(new TypeError('The stream is closing or closed and cannot be written to')); + } + if (state === 'erroring') { + return promiseRejectedWith(stream._storedError); + } + const promise = WritableStreamAddWriteRequest(stream); + WritableStreamDefaultControllerWrite(controller, chunk, chunkSize); + return promise; + } + const closeSentinel = {}; + /** + * Allows control of a {@link WritableStream | writable stream}'s state and internal queue. + * + * @public + */ + class WritableStreamDefaultController { + constructor() { + throw new TypeError('Illegal constructor'); + } + /** + * Closes the controlled writable stream, making all future interactions with it fail with the given error `e`. + * + * This method is rarely used, since usually it suffices to return a rejected promise from one of the underlying + * sink's methods. However, it can be useful for suddenly shutting down a stream in response to an event outside the + * normal lifecycle of interactions with the underlying sink. + */ + error(e = undefined) { + if (!IsWritableStreamDefaultController(this)) { + throw new TypeError('WritableStreamDefaultController.prototype.error can only be used on a WritableStreamDefaultController'); + } + const state = this._controlledWritableStream._state; + if (state !== 'writable') { + // The stream is closed, errored or will be soon. The sink can't do anything useful if it gets an error here, so + // just treat it as a no-op. + return; + } + WritableStreamDefaultControllerError(this, e); + } + /** @internal */ + [AbortSteps](reason) { + const result = this._abortAlgorithm(reason); + WritableStreamDefaultControllerClearAlgorithms(this); + return result; + } + /** @internal */ + [ErrorSteps]() { + ResetQueue(this); + } + } + Object.defineProperties(WritableStreamDefaultController.prototype, { + error: { enumerable: true } + }); + if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(WritableStreamDefaultController.prototype, SymbolPolyfill.toStringTag, { + value: 'WritableStreamDefaultController', + configurable: true + }); + } + // Abstract operations implementing interface required by the WritableStream. + function IsWritableStreamDefaultController(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_controlledWritableStream')) { + return false; + } + return true; + } + function SetUpWritableStreamDefaultController(stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark, sizeAlgorithm) { + controller._controlledWritableStream = stream; + stream._writableStreamController = controller; + // Need to set the slots so that the assert doesn't fire. In the spec the slots already exist implicitly. + controller._queue = undefined; + controller._queueTotalSize = undefined; + ResetQueue(controller); + controller._started = false; + controller._strategySizeAlgorithm = sizeAlgorithm; + controller._strategyHWM = highWaterMark; + controller._writeAlgorithm = writeAlgorithm; + controller._closeAlgorithm = closeAlgorithm; + controller._abortAlgorithm = abortAlgorithm; + const backpressure = WritableStreamDefaultControllerGetBackpressure(controller); + WritableStreamUpdateBackpressure(stream, backpressure); + const startResult = startAlgorithm(); + const startPromise = promiseResolvedWith(startResult); + uponPromise(startPromise, () => { + controller._started = true; + WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); + }, r => { + controller._started = true; + WritableStreamDealWithRejection(stream, r); + }); + } + function SetUpWritableStreamDefaultControllerFromUnderlyingSink(stream, underlyingSink, highWaterMark, sizeAlgorithm) { + const controller = Object.create(WritableStreamDefaultController.prototype); + let startAlgorithm = () => undefined; + let writeAlgorithm = () => promiseResolvedWith(undefined); + let closeAlgorithm = () => promiseResolvedWith(undefined); + let abortAlgorithm = () => promiseResolvedWith(undefined); + if (underlyingSink.start !== undefined) { + startAlgorithm = () => underlyingSink.start(controller); + } + if (underlyingSink.write !== undefined) { + writeAlgorithm = chunk => underlyingSink.write(chunk, controller); + } + if (underlyingSink.close !== undefined) { + closeAlgorithm = () => underlyingSink.close(); + } + if (underlyingSink.abort !== undefined) { + abortAlgorithm = reason => underlyingSink.abort(reason); + } + SetUpWritableStreamDefaultController(stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark, sizeAlgorithm); + } + // ClearAlgorithms may be called twice. Erroring the same stream in multiple ways will often result in redundant calls. + function WritableStreamDefaultControllerClearAlgorithms(controller) { + controller._writeAlgorithm = undefined; + controller._closeAlgorithm = undefined; + controller._abortAlgorithm = undefined; + controller._strategySizeAlgorithm = undefined; + } + function WritableStreamDefaultControllerClose(controller) { + EnqueueValueWithSize(controller, closeSentinel, 0); + WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); + } + function WritableStreamDefaultControllerGetChunkSize(controller, chunk) { + try { + return controller._strategySizeAlgorithm(chunk); + } + catch (chunkSizeE) { + WritableStreamDefaultControllerErrorIfNeeded(controller, chunkSizeE); + return 1; + } + } + function WritableStreamDefaultControllerGetDesiredSize(controller) { + return controller._strategyHWM - controller._queueTotalSize; + } + function WritableStreamDefaultControllerWrite(controller, chunk, chunkSize) { + try { + EnqueueValueWithSize(controller, chunk, chunkSize); + } + catch (enqueueE) { + WritableStreamDefaultControllerErrorIfNeeded(controller, enqueueE); + return; + } + const stream = controller._controlledWritableStream; + if (!WritableStreamCloseQueuedOrInFlight(stream) && stream._state === 'writable') { + const backpressure = WritableStreamDefaultControllerGetBackpressure(controller); + WritableStreamUpdateBackpressure(stream, backpressure); + } + WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); + } + // Abstract operations for the WritableStreamDefaultController. + function WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller) { + const stream = controller._controlledWritableStream; + if (!controller._started) { + return; + } + if (stream._inFlightWriteRequest !== undefined) { + return; + } + const state = stream._state; + if (state === 'erroring') { + WritableStreamFinishErroring(stream); + return; + } + if (controller._queue.length === 0) { + return; + } + const value = PeekQueueValue(controller); + if (value === closeSentinel) { + WritableStreamDefaultControllerProcessClose(controller); + } + else { + WritableStreamDefaultControllerProcessWrite(controller, value); + } + } + function WritableStreamDefaultControllerErrorIfNeeded(controller, error) { + if (controller._controlledWritableStream._state === 'writable') { + WritableStreamDefaultControllerError(controller, error); + } + } + function WritableStreamDefaultControllerProcessClose(controller) { + const stream = controller._controlledWritableStream; + WritableStreamMarkCloseRequestInFlight(stream); + DequeueValue(controller); + const sinkClosePromise = controller._closeAlgorithm(); + WritableStreamDefaultControllerClearAlgorithms(controller); + uponPromise(sinkClosePromise, () => { + WritableStreamFinishInFlightClose(stream); + }, reason => { + WritableStreamFinishInFlightCloseWithError(stream, reason); + }); + } + function WritableStreamDefaultControllerProcessWrite(controller, chunk) { + const stream = controller._controlledWritableStream; + WritableStreamMarkFirstWriteRequestInFlight(stream); + const sinkWritePromise = controller._writeAlgorithm(chunk); + uponPromise(sinkWritePromise, () => { + WritableStreamFinishInFlightWrite(stream); + const state = stream._state; + DequeueValue(controller); + if (!WritableStreamCloseQueuedOrInFlight(stream) && state === 'writable') { + const backpressure = WritableStreamDefaultControllerGetBackpressure(controller); + WritableStreamUpdateBackpressure(stream, backpressure); + } + WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); + }, reason => { + if (stream._state === 'writable') { + WritableStreamDefaultControllerClearAlgorithms(controller); + } + WritableStreamFinishInFlightWriteWithError(stream, reason); + }); + } + function WritableStreamDefaultControllerGetBackpressure(controller) { + const desiredSize = WritableStreamDefaultControllerGetDesiredSize(controller); + return desiredSize <= 0; + } + // A client of WritableStreamDefaultController may use these functions directly to bypass state check. + function WritableStreamDefaultControllerError(controller, error) { + const stream = controller._controlledWritableStream; + WritableStreamDefaultControllerClearAlgorithms(controller); + WritableStreamStartErroring(stream, error); + } + // Helper functions for the WritableStream. + function streamBrandCheckException$2(name) { + return new TypeError(`WritableStream.prototype.${name} can only be used on a WritableStream`); + } + // Helper functions for the WritableStreamDefaultWriter. + function defaultWriterBrandCheckException(name) { + return new TypeError(`WritableStreamDefaultWriter.prototype.${name} can only be used on a WritableStreamDefaultWriter`); + } + function defaultWriterLockException(name) { + return new TypeError('Cannot ' + name + ' a stream using a released writer'); + } + function defaultWriterClosedPromiseInitialize(writer) { + writer._closedPromise = newPromise((resolve, reject) => { + writer._closedPromise_resolve = resolve; + writer._closedPromise_reject = reject; + writer._closedPromiseState = 'pending'; + }); + } + function defaultWriterClosedPromiseInitializeAsRejected(writer, reason) { + defaultWriterClosedPromiseInitialize(writer); + defaultWriterClosedPromiseReject(writer, reason); + } + function defaultWriterClosedPromiseInitializeAsResolved(writer) { + defaultWriterClosedPromiseInitialize(writer); + defaultWriterClosedPromiseResolve(writer); + } + function defaultWriterClosedPromiseReject(writer, reason) { + if (writer._closedPromise_reject === undefined) { + return; + } + setPromiseIsHandledToTrue(writer._closedPromise); + writer._closedPromise_reject(reason); + writer._closedPromise_resolve = undefined; + writer._closedPromise_reject = undefined; + writer._closedPromiseState = 'rejected'; + } + function defaultWriterClosedPromiseResetToRejected(writer, reason) { + defaultWriterClosedPromiseInitializeAsRejected(writer, reason); + } + function defaultWriterClosedPromiseResolve(writer) { + if (writer._closedPromise_resolve === undefined) { + return; + } + writer._closedPromise_resolve(undefined); + writer._closedPromise_resolve = undefined; + writer._closedPromise_reject = undefined; + writer._closedPromiseState = 'resolved'; + } + function defaultWriterReadyPromiseInitialize(writer) { + writer._readyPromise = newPromise((resolve, reject) => { + writer._readyPromise_resolve = resolve; + writer._readyPromise_reject = reject; + }); + writer._readyPromiseState = 'pending'; + } + function defaultWriterReadyPromiseInitializeAsRejected(writer, reason) { + defaultWriterReadyPromiseInitialize(writer); + defaultWriterReadyPromiseReject(writer, reason); + } + function defaultWriterReadyPromiseInitializeAsResolved(writer) { + defaultWriterReadyPromiseInitialize(writer); + defaultWriterReadyPromiseResolve(writer); + } + function defaultWriterReadyPromiseReject(writer, reason) { + if (writer._readyPromise_reject === undefined) { + return; + } + setPromiseIsHandledToTrue(writer._readyPromise); + writer._readyPromise_reject(reason); + writer._readyPromise_resolve = undefined; + writer._readyPromise_reject = undefined; + writer._readyPromiseState = 'rejected'; + } + function defaultWriterReadyPromiseReset(writer) { + defaultWriterReadyPromiseInitialize(writer); + } + function defaultWriterReadyPromiseResetToRejected(writer, reason) { + defaultWriterReadyPromiseInitializeAsRejected(writer, reason); + } + function defaultWriterReadyPromiseResolve(writer) { + if (writer._readyPromise_resolve === undefined) { + return; + } + writer._readyPromise_resolve(undefined); + writer._readyPromise_resolve = undefined; + writer._readyPromise_reject = undefined; + writer._readyPromiseState = 'fulfilled'; + } + + function isAbortSignal(value) { + if (typeof value !== 'object' || value === null) { + return false; + } + try { + return typeof value.aborted === 'boolean'; + } + catch (_a) { + // AbortSignal.prototype.aborted throws if its brand check fails + return false; + } + } + + /// + const NativeDOMException = typeof DOMException !== 'undefined' ? DOMException : undefined; + + /// + function isDOMExceptionConstructor(ctor) { + if (!(typeof ctor === 'function' || typeof ctor === 'object')) { + return false; + } + try { + new ctor(); + return true; + } + catch (_a) { + return false; + } + } + function createDOMExceptionPolyfill() { + // eslint-disable-next-line no-shadow + const ctor = function DOMException(message, name) { + this.message = message || ''; + this.name = name || 'Error'; + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + }; + ctor.prototype = Object.create(Error.prototype); + Object.defineProperty(ctor.prototype, 'constructor', { value: ctor, writable: true, configurable: true }); + return ctor; + } + // eslint-disable-next-line no-redeclare + const DOMException$1 = isDOMExceptionConstructor(NativeDOMException) ? NativeDOMException : createDOMExceptionPolyfill(); + + function ReadableStreamPipeTo(source, dest, preventClose, preventAbort, preventCancel, signal) { + const reader = AcquireReadableStreamDefaultReader(source); + const writer = AcquireWritableStreamDefaultWriter(dest); + source._disturbed = true; + let shuttingDown = false; + // This is used to keep track of the spec's requirement that we wait for ongoing writes during shutdown. + let currentWrite = promiseResolvedWith(undefined); + return newPromise((resolve, reject) => { + let abortAlgorithm; + if (signal !== undefined) { + abortAlgorithm = () => { + const error = new DOMException$1('Aborted', 'AbortError'); + const actions = []; + if (!preventAbort) { + actions.push(() => { + if (dest._state === 'writable') { + return WritableStreamAbort(dest, error); + } + return promiseResolvedWith(undefined); + }); + } + if (!preventCancel) { + actions.push(() => { + if (source._state === 'readable') { + return ReadableStreamCancel(source, error); + } + return promiseResolvedWith(undefined); + }); + } + shutdownWithAction(() => Promise.all(actions.map(action => action())), true, error); + }; + if (signal.aborted) { + abortAlgorithm(); + return; + } + signal.addEventListener('abort', abortAlgorithm); + } + // Using reader and writer, read all chunks from this and write them to dest + // - Backpressure must be enforced + // - Shutdown must stop all activity + function pipeLoop() { + return newPromise((resolveLoop, rejectLoop) => { + function next(done) { + if (done) { + resolveLoop(); + } + else { + // Use `PerformPromiseThen` instead of `uponPromise` to avoid + // adding unnecessary `.catch(rethrowAssertionErrorRejection)` handlers + PerformPromiseThen(pipeStep(), next, rejectLoop); + } + } + next(false); + }); + } + function pipeStep() { + if (shuttingDown) { + return promiseResolvedWith(true); + } + return PerformPromiseThen(writer._readyPromise, () => { + return newPromise((resolveRead, rejectRead) => { + ReadableStreamDefaultReaderRead(reader, { + _chunkSteps: chunk => { + currentWrite = PerformPromiseThen(WritableStreamDefaultWriterWrite(writer, chunk), undefined, noop); + resolveRead(false); + }, + _closeSteps: () => resolveRead(true), + _errorSteps: rejectRead + }); + }); + }); + } + // Errors must be propagated forward + isOrBecomesErrored(source, reader._closedPromise, storedError => { + if (!preventAbort) { + shutdownWithAction(() => WritableStreamAbort(dest, storedError), true, storedError); + } + else { + shutdown(true, storedError); + } + }); + // Errors must be propagated backward + isOrBecomesErrored(dest, writer._closedPromise, storedError => { + if (!preventCancel) { + shutdownWithAction(() => ReadableStreamCancel(source, storedError), true, storedError); + } + else { + shutdown(true, storedError); + } + }); + // Closing must be propagated forward + isOrBecomesClosed(source, reader._closedPromise, () => { + if (!preventClose) { + shutdownWithAction(() => WritableStreamDefaultWriterCloseWithErrorPropagation(writer)); + } + else { + shutdown(); + } + }); + // Closing must be propagated backward + if (WritableStreamCloseQueuedOrInFlight(dest) || dest._state === 'closed') { + const destClosed = new TypeError('the destination writable stream closed before all data could be piped to it'); + if (!preventCancel) { + shutdownWithAction(() => ReadableStreamCancel(source, destClosed), true, destClosed); + } + else { + shutdown(true, destClosed); + } + } + setPromiseIsHandledToTrue(pipeLoop()); + function waitForWritesToFinish() { + // Another write may have started while we were waiting on this currentWrite, so we have to be sure to wait + // for that too. + const oldCurrentWrite = currentWrite; + return PerformPromiseThen(currentWrite, () => oldCurrentWrite !== currentWrite ? waitForWritesToFinish() : undefined); + } + function isOrBecomesErrored(stream, promise, action) { + if (stream._state === 'errored') { + action(stream._storedError); + } + else { + uponRejection(promise, action); + } + } + function isOrBecomesClosed(stream, promise, action) { + if (stream._state === 'closed') { + action(); + } + else { + uponFulfillment(promise, action); + } + } + function shutdownWithAction(action, originalIsError, originalError) { + if (shuttingDown) { + return; + } + shuttingDown = true; + if (dest._state === 'writable' && !WritableStreamCloseQueuedOrInFlight(dest)) { + uponFulfillment(waitForWritesToFinish(), doTheRest); + } + else { + doTheRest(); + } + function doTheRest() { + uponPromise(action(), () => finalize(originalIsError, originalError), newError => finalize(true, newError)); + } + } + function shutdown(isError, error) { + if (shuttingDown) { + return; + } + shuttingDown = true; + if (dest._state === 'writable' && !WritableStreamCloseQueuedOrInFlight(dest)) { + uponFulfillment(waitForWritesToFinish(), () => finalize(isError, error)); + } + else { + finalize(isError, error); + } + } + function finalize(isError, error) { + WritableStreamDefaultWriterRelease(writer); + ReadableStreamReaderGenericRelease(reader); + if (signal !== undefined) { + signal.removeEventListener('abort', abortAlgorithm); + } + if (isError) { + reject(error); + } + else { + resolve(undefined); + } + } + }); + } + + /** + * Allows control of a {@link ReadableStream | readable stream}'s state and internal queue. + * + * @public + */ + class ReadableStreamDefaultController { + constructor() { + throw new TypeError('Illegal constructor'); + } + /** + * Returns the desired size to fill the controlled stream's internal queue. It can be negative, if the queue is + * over-full. An underlying source ought to use this information to determine when and how to apply backpressure. + */ + get desiredSize() { + if (!IsReadableStreamDefaultController(this)) { + throw defaultControllerBrandCheckException$1('desiredSize'); + } + return ReadableStreamDefaultControllerGetDesiredSize(this); + } + /** + * Closes the controlled readable stream. Consumers will still be able to read any previously-enqueued chunks from + * the stream, but once those are read, the stream will become closed. + */ + close() { + if (!IsReadableStreamDefaultController(this)) { + throw defaultControllerBrandCheckException$1('close'); + } + if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(this)) { + throw new TypeError('The stream is not in a state that permits close'); + } + ReadableStreamDefaultControllerClose(this); + } + enqueue(chunk = undefined) { + if (!IsReadableStreamDefaultController(this)) { + throw defaultControllerBrandCheckException$1('enqueue'); + } + if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(this)) { + throw new TypeError('The stream is not in a state that permits enqueue'); + } + return ReadableStreamDefaultControllerEnqueue(this, chunk); + } + /** + * Errors the controlled readable stream, making all future interactions with it fail with the given error `e`. + */ + error(e = undefined) { + if (!IsReadableStreamDefaultController(this)) { + throw defaultControllerBrandCheckException$1('error'); + } + ReadableStreamDefaultControllerError(this, e); + } + /** @internal */ + [CancelSteps](reason) { + ResetQueue(this); + const result = this._cancelAlgorithm(reason); + ReadableStreamDefaultControllerClearAlgorithms(this); + return result; + } + /** @internal */ + [PullSteps](readRequest) { + const stream = this._controlledReadableStream; + if (this._queue.length > 0) { + const chunk = DequeueValue(this); + if (this._closeRequested && this._queue.length === 0) { + ReadableStreamDefaultControllerClearAlgorithms(this); + ReadableStreamClose(stream); + } + else { + ReadableStreamDefaultControllerCallPullIfNeeded(this); + } + readRequest._chunkSteps(chunk); + } + else { + ReadableStreamAddReadRequest(stream, readRequest); + ReadableStreamDefaultControllerCallPullIfNeeded(this); + } + } + } + Object.defineProperties(ReadableStreamDefaultController.prototype, { + close: { enumerable: true }, + enqueue: { enumerable: true }, + error: { enumerable: true }, + desiredSize: { enumerable: true } + }); + if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(ReadableStreamDefaultController.prototype, SymbolPolyfill.toStringTag, { + value: 'ReadableStreamDefaultController', + configurable: true + }); + } + // Abstract operations for the ReadableStreamDefaultController. + function IsReadableStreamDefaultController(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_controlledReadableStream')) { + return false; + } + return true; + } + function ReadableStreamDefaultControllerCallPullIfNeeded(controller) { + const shouldPull = ReadableStreamDefaultControllerShouldCallPull(controller); + if (!shouldPull) { + return; + } + if (controller._pulling) { + controller._pullAgain = true; + return; + } + controller._pulling = true; + const pullPromise = controller._pullAlgorithm(); + uponPromise(pullPromise, () => { + controller._pulling = false; + if (controller._pullAgain) { + controller._pullAgain = false; + ReadableStreamDefaultControllerCallPullIfNeeded(controller); + } + }, e => { + ReadableStreamDefaultControllerError(controller, e); + }); + } + function ReadableStreamDefaultControllerShouldCallPull(controller) { + const stream = controller._controlledReadableStream; + if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(controller)) { + return false; + } + if (!controller._started) { + return false; + } + if (IsReadableStreamLocked(stream) && ReadableStreamGetNumReadRequests(stream) > 0) { + return true; + } + const desiredSize = ReadableStreamDefaultControllerGetDesiredSize(controller); + if (desiredSize > 0) { + return true; + } + return false; + } + function ReadableStreamDefaultControllerClearAlgorithms(controller) { + controller._pullAlgorithm = undefined; + controller._cancelAlgorithm = undefined; + controller._strategySizeAlgorithm = undefined; + } + // A client of ReadableStreamDefaultController may use these functions directly to bypass state check. + function ReadableStreamDefaultControllerClose(controller) { + if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(controller)) { + return; + } + const stream = controller._controlledReadableStream; + controller._closeRequested = true; + if (controller._queue.length === 0) { + ReadableStreamDefaultControllerClearAlgorithms(controller); + ReadableStreamClose(stream); + } + } + function ReadableStreamDefaultControllerEnqueue(controller, chunk) { + if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(controller)) { + return; + } + const stream = controller._controlledReadableStream; + if (IsReadableStreamLocked(stream) && ReadableStreamGetNumReadRequests(stream) > 0) { + ReadableStreamFulfillReadRequest(stream, chunk, false); + } + else { + let chunkSize; + try { + chunkSize = controller._strategySizeAlgorithm(chunk); + } + catch (chunkSizeE) { + ReadableStreamDefaultControllerError(controller, chunkSizeE); + throw chunkSizeE; + } + try { + EnqueueValueWithSize(controller, chunk, chunkSize); + } + catch (enqueueE) { + ReadableStreamDefaultControllerError(controller, enqueueE); + throw enqueueE; + } + } + ReadableStreamDefaultControllerCallPullIfNeeded(controller); + } + function ReadableStreamDefaultControllerError(controller, e) { + const stream = controller._controlledReadableStream; + if (stream._state !== 'readable') { + return; + } + ResetQueue(controller); + ReadableStreamDefaultControllerClearAlgorithms(controller); + ReadableStreamError(stream, e); + } + function ReadableStreamDefaultControllerGetDesiredSize(controller) { + const state = controller._controlledReadableStream._state; + if (state === 'errored') { + return null; + } + if (state === 'closed') { + return 0; + } + return controller._strategyHWM - controller._queueTotalSize; + } + // This is used in the implementation of TransformStream. + function ReadableStreamDefaultControllerHasBackpressure(controller) { + if (ReadableStreamDefaultControllerShouldCallPull(controller)) { + return false; + } + return true; + } + function ReadableStreamDefaultControllerCanCloseOrEnqueue(controller) { + const state = controller._controlledReadableStream._state; + if (!controller._closeRequested && state === 'readable') { + return true; + } + return false; + } + function SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm) { + controller._controlledReadableStream = stream; + controller._queue = undefined; + controller._queueTotalSize = undefined; + ResetQueue(controller); + controller._started = false; + controller._closeRequested = false; + controller._pullAgain = false; + controller._pulling = false; + controller._strategySizeAlgorithm = sizeAlgorithm; + controller._strategyHWM = highWaterMark; + controller._pullAlgorithm = pullAlgorithm; + controller._cancelAlgorithm = cancelAlgorithm; + stream._readableStreamController = controller; + const startResult = startAlgorithm(); + uponPromise(promiseResolvedWith(startResult), () => { + controller._started = true; + ReadableStreamDefaultControllerCallPullIfNeeded(controller); + }, r => { + ReadableStreamDefaultControllerError(controller, r); + }); + } + function SetUpReadableStreamDefaultControllerFromUnderlyingSource(stream, underlyingSource, highWaterMark, sizeAlgorithm) { + const controller = Object.create(ReadableStreamDefaultController.prototype); + let startAlgorithm = () => undefined; + let pullAlgorithm = () => promiseResolvedWith(undefined); + let cancelAlgorithm = () => promiseResolvedWith(undefined); + if (underlyingSource.start !== undefined) { + startAlgorithm = () => underlyingSource.start(controller); + } + if (underlyingSource.pull !== undefined) { + pullAlgorithm = () => underlyingSource.pull(controller); + } + if (underlyingSource.cancel !== undefined) { + cancelAlgorithm = reason => underlyingSource.cancel(reason); + } + SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm); + } + // Helper functions for the ReadableStreamDefaultController. + function defaultControllerBrandCheckException$1(name) { + return new TypeError(`ReadableStreamDefaultController.prototype.${name} can only be used on a ReadableStreamDefaultController`); + } + + function ReadableStreamTee(stream, cloneForBranch2) { + const reader = AcquireReadableStreamDefaultReader(stream); + let reading = false; + let canceled1 = false; + let canceled2 = false; + let reason1; + let reason2; + let branch1; + let branch2; + let resolveCancelPromise; + const cancelPromise = newPromise(resolve => { + resolveCancelPromise = resolve; + }); + function pullAlgorithm() { + if (reading) { + return promiseResolvedWith(undefined); + } + reading = true; + const readRequest = { + _chunkSteps: value => { + // This needs to be delayed a microtask because it takes at least a microtask to detect errors (using + // reader._closedPromise below), and we want errors in stream to error both branches immediately. We cannot let + // successful synchronously-available reads get ahead of asynchronously-available errors. + queueMicrotask(() => { + reading = false; + const value1 = value; + const value2 = value; + // There is no way to access the cloning code right now in the reference implementation. + // If we add one then we'll need an implementation for serializable objects. + // if (!canceled2 && cloneForBranch2) { + // value2 = StructuredDeserialize(StructuredSerialize(value2)); + // } + if (!canceled1) { + ReadableStreamDefaultControllerEnqueue(branch1._readableStreamController, value1); + } + if (!canceled2) { + ReadableStreamDefaultControllerEnqueue(branch2._readableStreamController, value2); + } + }); + }, + _closeSteps: () => { + reading = false; + if (!canceled1) { + ReadableStreamDefaultControllerClose(branch1._readableStreamController); + } + if (!canceled2) { + ReadableStreamDefaultControllerClose(branch2._readableStreamController); + } + if (!canceled1 || !canceled2) { + resolveCancelPromise(undefined); + } + }, + _errorSteps: () => { + reading = false; + } + }; + ReadableStreamDefaultReaderRead(reader, readRequest); + return promiseResolvedWith(undefined); + } + function cancel1Algorithm(reason) { + canceled1 = true; + reason1 = reason; + if (canceled2) { + const compositeReason = CreateArrayFromList([reason1, reason2]); + const cancelResult = ReadableStreamCancel(stream, compositeReason); + resolveCancelPromise(cancelResult); + } + return cancelPromise; + } + function cancel2Algorithm(reason) { + canceled2 = true; + reason2 = reason; + if (canceled1) { + const compositeReason = CreateArrayFromList([reason1, reason2]); + const cancelResult = ReadableStreamCancel(stream, compositeReason); + resolveCancelPromise(cancelResult); + } + return cancelPromise; + } + function startAlgorithm() { + // do nothing + } + branch1 = CreateReadableStream(startAlgorithm, pullAlgorithm, cancel1Algorithm); + branch2 = CreateReadableStream(startAlgorithm, pullAlgorithm, cancel2Algorithm); + uponRejection(reader._closedPromise, (r) => { + ReadableStreamDefaultControllerError(branch1._readableStreamController, r); + ReadableStreamDefaultControllerError(branch2._readableStreamController, r); + if (!canceled1 || !canceled2) { + resolveCancelPromise(undefined); + } + }); + return [branch1, branch2]; + } + + function convertUnderlyingDefaultOrByteSource(source, context) { + assertDictionary(source, context); + const original = source; + const autoAllocateChunkSize = original === null || original === void 0 ? void 0 : original.autoAllocateChunkSize; + const cancel = original === null || original === void 0 ? void 0 : original.cancel; + const pull = original === null || original === void 0 ? void 0 : original.pull; + const start = original === null || original === void 0 ? void 0 : original.start; + const type = original === null || original === void 0 ? void 0 : original.type; + return { + autoAllocateChunkSize: autoAllocateChunkSize === undefined ? + undefined : + convertUnsignedLongLongWithEnforceRange(autoAllocateChunkSize, `${context} has member 'autoAllocateChunkSize' that`), + cancel: cancel === undefined ? + undefined : + convertUnderlyingSourceCancelCallback(cancel, original, `${context} has member 'cancel' that`), + pull: pull === undefined ? + undefined : + convertUnderlyingSourcePullCallback(pull, original, `${context} has member 'pull' that`), + start: start === undefined ? + undefined : + convertUnderlyingSourceStartCallback(start, original, `${context} has member 'start' that`), + type: type === undefined ? undefined : convertReadableStreamType(type, `${context} has member 'type' that`) + }; + } + function convertUnderlyingSourceCancelCallback(fn, original, context) { + assertFunction(fn, context); + return (reason) => promiseCall(fn, original, [reason]); + } + function convertUnderlyingSourcePullCallback(fn, original, context) { + assertFunction(fn, context); + return (controller) => promiseCall(fn, original, [controller]); + } + function convertUnderlyingSourceStartCallback(fn, original, context) { + assertFunction(fn, context); + return (controller) => reflectCall(fn, original, [controller]); + } + function convertReadableStreamType(type, context) { + type = `${type}`; + if (type !== 'bytes') { + throw new TypeError(`${context} '${type}' is not a valid enumeration value for ReadableStreamType`); + } + return type; + } + + function convertReaderOptions(options, context) { + assertDictionary(options, context); + const mode = options === null || options === void 0 ? void 0 : options.mode; + return { + mode: mode === undefined ? undefined : convertReadableStreamReaderMode(mode, `${context} has member 'mode' that`) + }; + } + function convertReadableStreamReaderMode(mode, context) { + mode = `${mode}`; + if (mode !== 'byob') { + throw new TypeError(`${context} '${mode}' is not a valid enumeration value for ReadableStreamReaderMode`); + } + return mode; + } + + function convertIteratorOptions(options, context) { + assertDictionary(options, context); + const preventCancel = options === null || options === void 0 ? void 0 : options.preventCancel; + return { preventCancel: Boolean(preventCancel) }; + } + + function convertPipeOptions(options, context) { + assertDictionary(options, context); + const preventAbort = options === null || options === void 0 ? void 0 : options.preventAbort; + const preventCancel = options === null || options === void 0 ? void 0 : options.preventCancel; + const preventClose = options === null || options === void 0 ? void 0 : options.preventClose; + const signal = options === null || options === void 0 ? void 0 : options.signal; + if (signal !== undefined) { + assertAbortSignal(signal, `${context} has member 'signal' that`); + } + return { + preventAbort: Boolean(preventAbort), + preventCancel: Boolean(preventCancel), + preventClose: Boolean(preventClose), + signal + }; + } + function assertAbortSignal(signal, context) { + if (!isAbortSignal(signal)) { + throw new TypeError(`${context} is not an AbortSignal.`); + } + } + + function convertReadableWritablePair(pair, context) { + assertDictionary(pair, context); + const readable = pair === null || pair === void 0 ? void 0 : pair.readable; + assertRequiredField(readable, 'readable', 'ReadableWritablePair'); + assertReadableStream(readable, `${context} has member 'readable' that`); + const writable = pair === null || pair === void 0 ? void 0 : pair.writable; + assertRequiredField(writable, 'writable', 'ReadableWritablePair'); + assertWritableStream(writable, `${context} has member 'writable' that`); + return { readable, writable }; + } + + /** + * A readable stream represents a source of data, from which you can read. + * + * @public + */ + class ReadableStream$1 { + constructor(rawUnderlyingSource = {}, rawStrategy = {}) { + if (rawUnderlyingSource === undefined) { + rawUnderlyingSource = null; + } + else { + assertObject(rawUnderlyingSource, 'First parameter'); + } + const strategy = convertQueuingStrategy(rawStrategy, 'Second parameter'); + const underlyingSource = convertUnderlyingDefaultOrByteSource(rawUnderlyingSource, 'First parameter'); + InitializeReadableStream(this); + if (underlyingSource.type === 'bytes') { + if (strategy.size !== undefined) { + throw new RangeError('The strategy for a byte stream cannot have a size function'); + } + const highWaterMark = ExtractHighWaterMark(strategy, 0); + SetUpReadableByteStreamControllerFromUnderlyingSource(this, underlyingSource, highWaterMark); + } + else { + const sizeAlgorithm = ExtractSizeAlgorithm(strategy); + const highWaterMark = ExtractHighWaterMark(strategy, 1); + SetUpReadableStreamDefaultControllerFromUnderlyingSource(this, underlyingSource, highWaterMark, sizeAlgorithm); + } + } + /** + * Whether or not the readable stream is locked to a {@link ReadableStreamDefaultReader | reader}. + */ + get locked() { + if (!IsReadableStream(this)) { + throw streamBrandCheckException$1('locked'); + } + return IsReadableStreamLocked(this); + } + /** + * Cancels the stream, signaling a loss of interest in the stream by a consumer. + * + * The supplied `reason` argument will be given to the underlying source's {@link UnderlyingSource.cancel | cancel()} + * method, which might or might not use it. + */ + cancel(reason = undefined) { + if (!IsReadableStream(this)) { + return promiseRejectedWith(streamBrandCheckException$1('cancel')); + } + if (IsReadableStreamLocked(this)) { + return promiseRejectedWith(new TypeError('Cannot cancel a stream that already has a reader')); + } + return ReadableStreamCancel(this, reason); + } + getReader(rawOptions = undefined) { + if (!IsReadableStream(this)) { + throw streamBrandCheckException$1('getReader'); + } + const options = convertReaderOptions(rawOptions, 'First parameter'); + if (options.mode === undefined) { + return AcquireReadableStreamDefaultReader(this); + } + return AcquireReadableStreamBYOBReader(this); + } + pipeThrough(rawTransform, rawOptions = {}) { + if (!IsReadableStream(this)) { + throw streamBrandCheckException$1('pipeThrough'); + } + assertRequiredArgument(rawTransform, 1, 'pipeThrough'); + const transform = convertReadableWritablePair(rawTransform, 'First parameter'); + const options = convertPipeOptions(rawOptions, 'Second parameter'); + if (IsReadableStreamLocked(this)) { + throw new TypeError('ReadableStream.prototype.pipeThrough cannot be used on a locked ReadableStream'); + } + if (IsWritableStreamLocked(transform.writable)) { + throw new TypeError('ReadableStream.prototype.pipeThrough cannot be used on a locked WritableStream'); + } + const promise = ReadableStreamPipeTo(this, transform.writable, options.preventClose, options.preventAbort, options.preventCancel, options.signal); + setPromiseIsHandledToTrue(promise); + return transform.readable; + } + pipeTo(destination, rawOptions = {}) { + if (!IsReadableStream(this)) { + return promiseRejectedWith(streamBrandCheckException$1('pipeTo')); + } + if (destination === undefined) { + return promiseRejectedWith(`Parameter 1 is required in 'pipeTo'.`); + } + if (!IsWritableStream(destination)) { + return promiseRejectedWith(new TypeError(`ReadableStream.prototype.pipeTo's first argument must be a WritableStream`)); + } + let options; + try { + options = convertPipeOptions(rawOptions, 'Second parameter'); + } + catch (e) { + return promiseRejectedWith(e); + } + if (IsReadableStreamLocked(this)) { + return promiseRejectedWith(new TypeError('ReadableStream.prototype.pipeTo cannot be used on a locked ReadableStream')); + } + if (IsWritableStreamLocked(destination)) { + return promiseRejectedWith(new TypeError('ReadableStream.prototype.pipeTo cannot be used on a locked WritableStream')); + } + return ReadableStreamPipeTo(this, destination, options.preventClose, options.preventAbort, options.preventCancel, options.signal); + } + /** + * Tees this readable stream, returning a two-element array containing the two resulting branches as + * new {@link ReadableStream} instances. + * + * Teeing a stream will lock it, preventing any other consumer from acquiring a reader. + * To cancel the stream, cancel both of the resulting branches; a composite cancellation reason will then be + * propagated to the stream's underlying source. + * + * Note that the chunks seen in each branch will be the same object. If the chunks are not immutable, + * this could allow interference between the two branches. + */ + tee() { + if (!IsReadableStream(this)) { + throw streamBrandCheckException$1('tee'); + } + const branches = ReadableStreamTee(this); + return CreateArrayFromList(branches); + } + values(rawOptions = undefined) { + if (!IsReadableStream(this)) { + throw streamBrandCheckException$1('values'); + } + const options = convertIteratorOptions(rawOptions, 'First parameter'); + return AcquireReadableStreamAsyncIterator(this, options.preventCancel); + } + } + Object.defineProperties(ReadableStream$1.prototype, { + cancel: { enumerable: true }, + getReader: { enumerable: true }, + pipeThrough: { enumerable: true }, + pipeTo: { enumerable: true }, + tee: { enumerable: true }, + values: { enumerable: true }, + locked: { enumerable: true } + }); + if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(ReadableStream$1.prototype, SymbolPolyfill.toStringTag, { + value: 'ReadableStream', + configurable: true + }); + } + if (typeof SymbolPolyfill.asyncIterator === 'symbol') { + Object.defineProperty(ReadableStream$1.prototype, SymbolPolyfill.asyncIterator, { + value: ReadableStream$1.prototype.values, + writable: true, + configurable: true + }); + } + // Abstract operations for the ReadableStream. + // Throws if and only if startAlgorithm throws. + function CreateReadableStream(startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark = 1, sizeAlgorithm = () => 1) { + const stream = Object.create(ReadableStream$1.prototype); + InitializeReadableStream(stream); + const controller = Object.create(ReadableStreamDefaultController.prototype); + SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm); + return stream; + } + function InitializeReadableStream(stream) { + stream._state = 'readable'; + stream._reader = undefined; + stream._storedError = undefined; + stream._disturbed = false; + } + function IsReadableStream(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_readableStreamController')) { + return false; + } + return true; + } + function IsReadableStreamLocked(stream) { + if (stream._reader === undefined) { + return false; + } + return true; + } + // ReadableStream API exposed for controllers. + function ReadableStreamCancel(stream, reason) { + stream._disturbed = true; + if (stream._state === 'closed') { + return promiseResolvedWith(undefined); + } + if (stream._state === 'errored') { + return promiseRejectedWith(stream._storedError); + } + ReadableStreamClose(stream); + const sourceCancelPromise = stream._readableStreamController[CancelSteps](reason); + return transformPromiseWith(sourceCancelPromise, noop); + } + function ReadableStreamClose(stream) { + stream._state = 'closed'; + const reader = stream._reader; + if (reader === undefined) { + return; + } + defaultReaderClosedPromiseResolve(reader); + if (IsReadableStreamDefaultReader(reader)) { + reader._readRequests.forEach(readRequest => { + readRequest._closeSteps(); + }); + reader._readRequests = new SimpleQueue(); + } + } + function ReadableStreamError(stream, e) { + stream._state = 'errored'; + stream._storedError = e; + const reader = stream._reader; + if (reader === undefined) { + return; + } + defaultReaderClosedPromiseReject(reader, e); + if (IsReadableStreamDefaultReader(reader)) { + reader._readRequests.forEach(readRequest => { + readRequest._errorSteps(e); + }); + reader._readRequests = new SimpleQueue(); + } + else { + reader._readIntoRequests.forEach(readIntoRequest => { + readIntoRequest._errorSteps(e); + }); + reader._readIntoRequests = new SimpleQueue(); + } + } + // Helper functions for the ReadableStream. + function streamBrandCheckException$1(name) { + return new TypeError(`ReadableStream.prototype.${name} can only be used on a ReadableStream`); + } + + function convertQueuingStrategyInit(init, context) { + assertDictionary(init, context); + const highWaterMark = init === null || init === void 0 ? void 0 : init.highWaterMark; + assertRequiredField(highWaterMark, 'highWaterMark', 'QueuingStrategyInit'); + return { + highWaterMark: convertUnrestrictedDouble(highWaterMark) + }; + } + + const byteLengthSizeFunction = function size(chunk) { + return chunk.byteLength; + }; + /** + * A queuing strategy that counts the number of bytes in each chunk. + * + * @public + */ + class ByteLengthQueuingStrategy { + constructor(options) { + assertRequiredArgument(options, 1, 'ByteLengthQueuingStrategy'); + options = convertQueuingStrategyInit(options, 'First parameter'); + this._byteLengthQueuingStrategyHighWaterMark = options.highWaterMark; + } + /** + * Returns the high water mark provided to the constructor. + */ + get highWaterMark() { + if (!IsByteLengthQueuingStrategy(this)) { + throw byteLengthBrandCheckException('highWaterMark'); + } + return this._byteLengthQueuingStrategyHighWaterMark; + } + /** + * Measures the size of `chunk` by returning the value of its `byteLength` property. + */ + get size() { + if (!IsByteLengthQueuingStrategy(this)) { + throw byteLengthBrandCheckException('size'); + } + return byteLengthSizeFunction; + } + } + Object.defineProperties(ByteLengthQueuingStrategy.prototype, { + highWaterMark: { enumerable: true }, + size: { enumerable: true } + }); + if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(ByteLengthQueuingStrategy.prototype, SymbolPolyfill.toStringTag, { + value: 'ByteLengthQueuingStrategy', + configurable: true + }); + } + // Helper functions for the ByteLengthQueuingStrategy. + function byteLengthBrandCheckException(name) { + return new TypeError(`ByteLengthQueuingStrategy.prototype.${name} can only be used on a ByteLengthQueuingStrategy`); + } + function IsByteLengthQueuingStrategy(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_byteLengthQueuingStrategyHighWaterMark')) { + return false; + } + return true; + } + + const countSizeFunction = function size() { + return 1; + }; + /** + * A queuing strategy that counts the number of chunks. + * + * @public + */ + class CountQueuingStrategy { + constructor(options) { + assertRequiredArgument(options, 1, 'CountQueuingStrategy'); + options = convertQueuingStrategyInit(options, 'First parameter'); + this._countQueuingStrategyHighWaterMark = options.highWaterMark; + } + /** + * Returns the high water mark provided to the constructor. + */ + get highWaterMark() { + if (!IsCountQueuingStrategy(this)) { + throw countBrandCheckException('highWaterMark'); + } + return this._countQueuingStrategyHighWaterMark; + } + /** + * Measures the size of `chunk` by always returning 1. + * This ensures that the total queue size is a count of the number of chunks in the queue. + */ + get size() { + if (!IsCountQueuingStrategy(this)) { + throw countBrandCheckException('size'); + } + return countSizeFunction; + } + } + Object.defineProperties(CountQueuingStrategy.prototype, { + highWaterMark: { enumerable: true }, + size: { enumerable: true } + }); + if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(CountQueuingStrategy.prototype, SymbolPolyfill.toStringTag, { + value: 'CountQueuingStrategy', + configurable: true + }); + } + // Helper functions for the CountQueuingStrategy. + function countBrandCheckException(name) { + return new TypeError(`CountQueuingStrategy.prototype.${name} can only be used on a CountQueuingStrategy`); + } + function IsCountQueuingStrategy(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_countQueuingStrategyHighWaterMark')) { + return false; + } + return true; + } + + function convertTransformer(original, context) { + assertDictionary(original, context); + const flush = original === null || original === void 0 ? void 0 : original.flush; + const readableType = original === null || original === void 0 ? void 0 : original.readableType; + const start = original === null || original === void 0 ? void 0 : original.start; + const transform = original === null || original === void 0 ? void 0 : original.transform; + const writableType = original === null || original === void 0 ? void 0 : original.writableType; + return { + flush: flush === undefined ? + undefined : + convertTransformerFlushCallback(flush, original, `${context} has member 'flush' that`), + readableType, + start: start === undefined ? + undefined : + convertTransformerStartCallback(start, original, `${context} has member 'start' that`), + transform: transform === undefined ? + undefined : + convertTransformerTransformCallback(transform, original, `${context} has member 'transform' that`), + writableType + }; + } + function convertTransformerFlushCallback(fn, original, context) { + assertFunction(fn, context); + return (controller) => promiseCall(fn, original, [controller]); + } + function convertTransformerStartCallback(fn, original, context) { + assertFunction(fn, context); + return (controller) => reflectCall(fn, original, [controller]); + } + function convertTransformerTransformCallback(fn, original, context) { + assertFunction(fn, context); + return (chunk, controller) => promiseCall(fn, original, [chunk, controller]); + } + + // Class TransformStream + /** + * A transform stream consists of a pair of streams: a {@link WritableStream | writable stream}, + * known as its writable side, and a {@link ReadableStream | readable stream}, known as its readable side. + * In a manner specific to the transform stream in question, writes to the writable side result in new data being + * made available for reading from the readable side. + * + * @public + */ + class TransformStream$1 { + constructor(rawTransformer = {}, rawWritableStrategy = {}, rawReadableStrategy = {}) { + if (rawTransformer === undefined) { + rawTransformer = null; + } + const writableStrategy = convertQueuingStrategy(rawWritableStrategy, 'Second parameter'); + const readableStrategy = convertQueuingStrategy(rawReadableStrategy, 'Third parameter'); + const transformer = convertTransformer(rawTransformer, 'First parameter'); + if (transformer.readableType !== undefined) { + throw new RangeError('Invalid readableType specified'); + } + if (transformer.writableType !== undefined) { + throw new RangeError('Invalid writableType specified'); + } + const readableHighWaterMark = ExtractHighWaterMark(readableStrategy, 0); + const readableSizeAlgorithm = ExtractSizeAlgorithm(readableStrategy); + const writableHighWaterMark = ExtractHighWaterMark(writableStrategy, 1); + const writableSizeAlgorithm = ExtractSizeAlgorithm(writableStrategy); + let startPromise_resolve; + const startPromise = newPromise(resolve => { + startPromise_resolve = resolve; + }); + InitializeTransformStream(this, startPromise, writableHighWaterMark, writableSizeAlgorithm, readableHighWaterMark, readableSizeAlgorithm); + SetUpTransformStreamDefaultControllerFromTransformer(this, transformer); + if (transformer.start !== undefined) { + startPromise_resolve(transformer.start(this._transformStreamController)); + } + else { + startPromise_resolve(undefined); + } + } + /** + * The readable side of the transform stream. + */ + get readable() { + if (!IsTransformStream(this)) { + throw streamBrandCheckException('readable'); + } + return this._readable; + } + /** + * The writable side of the transform stream. + */ + get writable() { + if (!IsTransformStream(this)) { + throw streamBrandCheckException('writable'); + } + return this._writable; + } + } + Object.defineProperties(TransformStream$1.prototype, { + readable: { enumerable: true }, + writable: { enumerable: true } + }); + if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(TransformStream$1.prototype, SymbolPolyfill.toStringTag, { + value: 'TransformStream', + configurable: true + }); + } + function InitializeTransformStream(stream, startPromise, writableHighWaterMark, writableSizeAlgorithm, readableHighWaterMark, readableSizeAlgorithm) { + function startAlgorithm() { + return startPromise; + } + function writeAlgorithm(chunk) { + return TransformStreamDefaultSinkWriteAlgorithm(stream, chunk); + } + function abortAlgorithm(reason) { + return TransformStreamDefaultSinkAbortAlgorithm(stream, reason); + } + function closeAlgorithm() { + return TransformStreamDefaultSinkCloseAlgorithm(stream); + } + stream._writable = CreateWritableStream(startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, writableHighWaterMark, writableSizeAlgorithm); + function pullAlgorithm() { + return TransformStreamDefaultSourcePullAlgorithm(stream); + } + function cancelAlgorithm(reason) { + TransformStreamErrorWritableAndUnblockWrite(stream, reason); + return promiseResolvedWith(undefined); + } + stream._readable = CreateReadableStream(startAlgorithm, pullAlgorithm, cancelAlgorithm, readableHighWaterMark, readableSizeAlgorithm); + // The [[backpressure]] slot is set to undefined so that it can be initialised by TransformStreamSetBackpressure. + stream._backpressure = undefined; + stream._backpressureChangePromise = undefined; + stream._backpressureChangePromise_resolve = undefined; + TransformStreamSetBackpressure(stream, true); + stream._transformStreamController = undefined; + } + function IsTransformStream(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_transformStreamController')) { + return false; + } + return true; + } + // This is a no-op if both sides are already errored. + function TransformStreamError(stream, e) { + ReadableStreamDefaultControllerError(stream._readable._readableStreamController, e); + TransformStreamErrorWritableAndUnblockWrite(stream, e); + } + function TransformStreamErrorWritableAndUnblockWrite(stream, e) { + TransformStreamDefaultControllerClearAlgorithms(stream._transformStreamController); + WritableStreamDefaultControllerErrorIfNeeded(stream._writable._writableStreamController, e); + if (stream._backpressure) { + // Pretend that pull() was called to permit any pending write() calls to complete. TransformStreamSetBackpressure() + // cannot be called from enqueue() or pull() once the ReadableStream is errored, so this will will be the final time + // _backpressure is set. + TransformStreamSetBackpressure(stream, false); + } + } + function TransformStreamSetBackpressure(stream, backpressure) { + // Passes also when called during construction. + if (stream._backpressureChangePromise !== undefined) { + stream._backpressureChangePromise_resolve(); + } + stream._backpressureChangePromise = newPromise(resolve => { + stream._backpressureChangePromise_resolve = resolve; + }); + stream._backpressure = backpressure; + } + // Class TransformStreamDefaultController + /** + * Allows control of the {@link ReadableStream} and {@link WritableStream} of the associated {@link TransformStream}. + * + * @public + */ + class TransformStreamDefaultController { + constructor() { + throw new TypeError('Illegal constructor'); + } + /** + * Returns the desired size to fill the readable side’s internal queue. It can be negative, if the queue is over-full. + */ + get desiredSize() { + if (!IsTransformStreamDefaultController(this)) { + throw defaultControllerBrandCheckException('desiredSize'); + } + const readableController = this._controlledTransformStream._readable._readableStreamController; + return ReadableStreamDefaultControllerGetDesiredSize(readableController); + } + enqueue(chunk = undefined) { + if (!IsTransformStreamDefaultController(this)) { + throw defaultControllerBrandCheckException('enqueue'); + } + TransformStreamDefaultControllerEnqueue(this, chunk); + } + /** + * Errors both the readable side and the writable side of the controlled transform stream, making all future + * interactions with it fail with the given error `e`. Any chunks queued for transformation will be discarded. + */ + error(reason = undefined) { + if (!IsTransformStreamDefaultController(this)) { + throw defaultControllerBrandCheckException('error'); + } + TransformStreamDefaultControllerError(this, reason); + } + /** + * Closes the readable side and errors the writable side of the controlled transform stream. This is useful when the + * transformer only needs to consume a portion of the chunks written to the writable side. + */ + terminate() { + if (!IsTransformStreamDefaultController(this)) { + throw defaultControllerBrandCheckException('terminate'); + } + TransformStreamDefaultControllerTerminate(this); + } + } + Object.defineProperties(TransformStreamDefaultController.prototype, { + enqueue: { enumerable: true }, + error: { enumerable: true }, + terminate: { enumerable: true }, + desiredSize: { enumerable: true } + }); + if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(TransformStreamDefaultController.prototype, SymbolPolyfill.toStringTag, { + value: 'TransformStreamDefaultController', + configurable: true + }); + } + // Transform Stream Default Controller Abstract Operations + function IsTransformStreamDefaultController(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_controlledTransformStream')) { + return false; + } + return true; + } + function SetUpTransformStreamDefaultController(stream, controller, transformAlgorithm, flushAlgorithm) { + controller._controlledTransformStream = stream; + stream._transformStreamController = controller; + controller._transformAlgorithm = transformAlgorithm; + controller._flushAlgorithm = flushAlgorithm; + } + function SetUpTransformStreamDefaultControllerFromTransformer(stream, transformer) { + const controller = Object.create(TransformStreamDefaultController.prototype); + let transformAlgorithm = (chunk) => { + try { + TransformStreamDefaultControllerEnqueue(controller, chunk); + return promiseResolvedWith(undefined); + } + catch (transformResultE) { + return promiseRejectedWith(transformResultE); + } + }; + let flushAlgorithm = () => promiseResolvedWith(undefined); + if (transformer.transform !== undefined) { + transformAlgorithm = chunk => transformer.transform(chunk, controller); + } + if (transformer.flush !== undefined) { + flushAlgorithm = () => transformer.flush(controller); + } + SetUpTransformStreamDefaultController(stream, controller, transformAlgorithm, flushAlgorithm); + } + function TransformStreamDefaultControllerClearAlgorithms(controller) { + controller._transformAlgorithm = undefined; + controller._flushAlgorithm = undefined; + } + function TransformStreamDefaultControllerEnqueue(controller, chunk) { + const stream = controller._controlledTransformStream; + const readableController = stream._readable._readableStreamController; + if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(readableController)) { + throw new TypeError('Readable side is not in a state that permits enqueue'); + } + // We throttle transform invocations based on the backpressure of the ReadableStream, but we still + // accept TransformStreamDefaultControllerEnqueue() calls. + try { + ReadableStreamDefaultControllerEnqueue(readableController, chunk); + } + catch (e) { + // This happens when readableStrategy.size() throws. + TransformStreamErrorWritableAndUnblockWrite(stream, e); + throw stream._readable._storedError; + } + const backpressure = ReadableStreamDefaultControllerHasBackpressure(readableController); + if (backpressure !== stream._backpressure) { + TransformStreamSetBackpressure(stream, true); + } + } + function TransformStreamDefaultControllerError(controller, e) { + TransformStreamError(controller._controlledTransformStream, e); + } + function TransformStreamDefaultControllerPerformTransform(controller, chunk) { + const transformPromise = controller._transformAlgorithm(chunk); + return transformPromiseWith(transformPromise, undefined, r => { + TransformStreamError(controller._controlledTransformStream, r); + throw r; + }); + } + function TransformStreamDefaultControllerTerminate(controller) { + const stream = controller._controlledTransformStream; + const readableController = stream._readable._readableStreamController; + ReadableStreamDefaultControllerClose(readableController); + const error = new TypeError('TransformStream terminated'); + TransformStreamErrorWritableAndUnblockWrite(stream, error); + } + // TransformStreamDefaultSink Algorithms + function TransformStreamDefaultSinkWriteAlgorithm(stream, chunk) { + const controller = stream._transformStreamController; + if (stream._backpressure) { + const backpressureChangePromise = stream._backpressureChangePromise; + return transformPromiseWith(backpressureChangePromise, () => { + const writable = stream._writable; + const state = writable._state; + if (state === 'erroring') { + throw writable._storedError; + } + return TransformStreamDefaultControllerPerformTransform(controller, chunk); + }); + } + return TransformStreamDefaultControllerPerformTransform(controller, chunk); + } + function TransformStreamDefaultSinkAbortAlgorithm(stream, reason) { + // abort() is not called synchronously, so it is possible for abort() to be called when the stream is already + // errored. + TransformStreamError(stream, reason); + return promiseResolvedWith(undefined); + } + function TransformStreamDefaultSinkCloseAlgorithm(stream) { + // stream._readable cannot change after construction, so caching it across a call to user code is safe. + const readable = stream._readable; + const controller = stream._transformStreamController; + const flushPromise = controller._flushAlgorithm(); + TransformStreamDefaultControllerClearAlgorithms(controller); + // Return a promise that is fulfilled with undefined on success. + return transformPromiseWith(flushPromise, () => { + if (readable._state === 'errored') { + throw readable._storedError; + } + ReadableStreamDefaultControllerClose(readable._readableStreamController); + }, r => { + TransformStreamError(stream, r); + throw readable._storedError; + }); + } + // TransformStreamDefaultSource Algorithms + function TransformStreamDefaultSourcePullAlgorithm(stream) { + // Invariant. Enforced by the promises returned by start() and pull(). + TransformStreamSetBackpressure(stream, false); + // Prevent the next pull() call until there is backpressure. + return stream._backpressureChangePromise; + } + // Helper functions for the TransformStreamDefaultController. + function defaultControllerBrandCheckException(name) { + return new TypeError(`TransformStreamDefaultController.prototype.${name} can only be used on a TransformStreamDefaultController`); + } + // Helper functions for the TransformStream. + function streamBrandCheckException(name) { + return new TypeError(`TransformStream.prototype.${name} can only be used on a TransformStream`); + } + + var ponyfill_es6 = /*#__PURE__*/Object.freeze({ + __proto__: null, + ByteLengthQueuingStrategy: ByteLengthQueuingStrategy, + CountQueuingStrategy: CountQueuingStrategy, + ReadableByteStreamController: ReadableByteStreamController, + ReadableStream: ReadableStream$1, + ReadableStreamBYOBReader: ReadableStreamBYOBReader, + ReadableStreamBYOBRequest: ReadableStreamBYOBRequest, + ReadableStreamDefaultController: ReadableStreamDefaultController, + ReadableStreamDefaultReader: ReadableStreamDefaultReader, + TransformStream: TransformStream$1, + TransformStreamDefaultController: TransformStreamDefaultController, + WritableStream: WritableStream$1, + WritableStreamDefaultController: WritableStreamDefaultController, + WritableStreamDefaultWriter: WritableStreamDefaultWriter + }); + + /*! ***************************************************************************** + Copyright (c) Microsoft Corporation. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + PERFORMANCE OF THIS SOFTWARE. + ***************************************************************************** */ + /* global Reflect, Promise */ + + var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + + function __extends(d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + } + + function assert$1(test) { + if (!test) { + throw new TypeError('Assertion failed'); + } + } + + function noop$1() { + return; + } + function typeIsObject$1(x) { + return (typeof x === 'object' && x !== null) || typeof x === 'function'; + } + + function isStreamConstructor(ctor) { + if (typeof ctor !== 'function') { + return false; + } + var startCalled = false; + try { + new ctor({ + start: function () { + startCalled = true; + } + }); + } + catch (e) { + // ignore + } + return startCalled; + } + function isReadableStream(readable) { + if (!typeIsObject$1(readable)) { + return false; + } + if (typeof readable.getReader !== 'function') { + return false; + } + return true; + } + function isReadableStreamConstructor(ctor) { + if (!isStreamConstructor(ctor)) { + return false; + } + if (!isReadableStream(new ctor())) { + return false; + } + return true; + } + function isWritableStream(writable) { + if (!typeIsObject$1(writable)) { + return false; + } + if (typeof writable.getWriter !== 'function') { + return false; + } + return true; + } + function isWritableStreamConstructor(ctor) { + if (!isStreamConstructor(ctor)) { + return false; + } + if (!isWritableStream(new ctor())) { + return false; + } + return true; + } + function isTransformStream(transform) { + if (!typeIsObject$1(transform)) { + return false; + } + if (!isReadableStream(transform.readable)) { + return false; + } + if (!isWritableStream(transform.writable)) { + return false; + } + return true; + } + function isTransformStreamConstructor(ctor) { + if (!isStreamConstructor(ctor)) { + return false; + } + if (!isTransformStream(new ctor())) { + return false; + } + return true; + } + function supportsByobReader(readable) { + try { + var reader = readable.getReader({ mode: 'byob' }); + reader.releaseLock(); + return true; + } + catch (_a) { + return false; + } + } + function supportsByteSource(ctor) { + try { + new ctor({ type: 'bytes' }); + return true; + } + catch (_a) { + return false; + } + } + + function createReadableStreamWrapper(ctor) { + assert$1(isReadableStreamConstructor(ctor)); + var byteSourceSupported = supportsByteSource(ctor); + return function (readable, _a) { + var _b = _a === void 0 ? {} : _a, type = _b.type; + type = parseReadableType(type); + if (type === 'bytes' && !byteSourceSupported) { + type = undefined; + } + if (readable.constructor === ctor) { + if (type !== 'bytes' || supportsByobReader(readable)) { + return readable; + } + } + if (type === 'bytes') { + var source = createWrappingReadableSource(readable, { type: type }); + return new ctor(source); + } + else { + var source = createWrappingReadableSource(readable); + return new ctor(source); + } + }; + } + function createWrappingReadableSource(readable, _a) { + var _b = _a === void 0 ? {} : _a, type = _b.type; + assert$1(isReadableStream(readable)); + assert$1(readable.locked === false); + type = parseReadableType(type); + var source; + if (type === 'bytes') { + source = new WrappingReadableByteStreamSource(readable); + } + else { + source = new WrappingReadableStreamDefaultSource(readable); + } + return source; + } + function parseReadableType(type) { + var typeString = String(type); + if (typeString === 'bytes') { + return typeString; + } + else if (type === undefined) { + return type; + } + else { + throw new RangeError('Invalid type is specified'); + } + } + var AbstractWrappingReadableStreamSource = /** @class */ (function () { + function AbstractWrappingReadableStreamSource(underlyingStream) { + this._underlyingReader = undefined; + this._readerMode = undefined; + this._readableStreamController = undefined; + this._pendingRead = undefined; + this._underlyingStream = underlyingStream; + // always keep a reader attached to detect close/error + this._attachDefaultReader(); + } + AbstractWrappingReadableStreamSource.prototype.start = function (controller) { + this._readableStreamController = controller; + }; + AbstractWrappingReadableStreamSource.prototype.cancel = function (reason) { + assert$1(this._underlyingReader !== undefined); + return this._underlyingReader.cancel(reason); + }; + AbstractWrappingReadableStreamSource.prototype._attachDefaultReader = function () { + if (this._readerMode === "default" /* DEFAULT */) { + return; + } + this._detachReader(); + var reader = this._underlyingStream.getReader(); + this._readerMode = "default" /* DEFAULT */; + this._attachReader(reader); + }; + AbstractWrappingReadableStreamSource.prototype._attachReader = function (reader) { + var _this = this; + assert$1(this._underlyingReader === undefined); + this._underlyingReader = reader; + var closed = this._underlyingReader.closed; + if (!closed) { + return; + } + closed + .then(function () { return _this._finishPendingRead(); }) + .then(function () { + if (reader === _this._underlyingReader) { + _this._readableStreamController.close(); + } + }, function (reason) { + if (reader === _this._underlyingReader) { + _this._readableStreamController.error(reason); + } + }) + .catch(noop$1); + }; + AbstractWrappingReadableStreamSource.prototype._detachReader = function () { + if (this._underlyingReader === undefined) { + return; + } + this._underlyingReader.releaseLock(); + this._underlyingReader = undefined; + this._readerMode = undefined; + }; + AbstractWrappingReadableStreamSource.prototype._pullWithDefaultReader = function () { + var _this = this; + this._attachDefaultReader(); + // TODO Backpressure? + var read = this._underlyingReader.read() + .then(function (result) { + var controller = _this._readableStreamController; + if (result.done) { + _this._tryClose(); + } + else { + controller.enqueue(result.value); + } + }); + this._setPendingRead(read); + return read; + }; + AbstractWrappingReadableStreamSource.prototype._tryClose = function () { + try { + this._readableStreamController.close(); + } + catch (_a) { + // already errored or closed + } + }; + AbstractWrappingReadableStreamSource.prototype._setPendingRead = function (readPromise) { + var _this = this; + var pendingRead; + var finishRead = function () { + if (_this._pendingRead === pendingRead) { + _this._pendingRead = undefined; + } + }; + this._pendingRead = pendingRead = readPromise.then(finishRead, finishRead); + }; + AbstractWrappingReadableStreamSource.prototype._finishPendingRead = function () { + var _this = this; + if (!this._pendingRead) { + return undefined; + } + var afterRead = function () { return _this._finishPendingRead(); }; + return this._pendingRead.then(afterRead, afterRead); + }; + return AbstractWrappingReadableStreamSource; + }()); + var WrappingReadableStreamDefaultSource = /** @class */ (function (_super) { + __extends(WrappingReadableStreamDefaultSource, _super); + function WrappingReadableStreamDefaultSource() { + return _super !== null && _super.apply(this, arguments) || this; + } + WrappingReadableStreamDefaultSource.prototype.pull = function () { + return this._pullWithDefaultReader(); + }; + return WrappingReadableStreamDefaultSource; + }(AbstractWrappingReadableStreamSource)); + function toUint8Array(view) { + return new Uint8Array(view.buffer, view.byteOffset, view.byteLength); + } + function copyArrayBufferView(from, to) { + var fromArray = toUint8Array(from); + var toArray = toUint8Array(to); + toArray.set(fromArray, 0); + } + var WrappingReadableByteStreamSource = /** @class */ (function (_super) { + __extends(WrappingReadableByteStreamSource, _super); + function WrappingReadableByteStreamSource(underlyingStream) { + var _this = this; + var supportsByob = supportsByobReader(underlyingStream); + _this = _super.call(this, underlyingStream) || this; + _this._supportsByob = supportsByob; + return _this; + } + Object.defineProperty(WrappingReadableByteStreamSource.prototype, "type", { + get: function () { + return 'bytes'; + }, + enumerable: false, + configurable: true + }); + WrappingReadableByteStreamSource.prototype._attachByobReader = function () { + if (this._readerMode === "byob" /* BYOB */) { + return; + } + assert$1(this._supportsByob); + this._detachReader(); + var reader = this._underlyingStream.getReader({ mode: 'byob' }); + this._readerMode = "byob" /* BYOB */; + this._attachReader(reader); + }; + WrappingReadableByteStreamSource.prototype.pull = function () { + if (this._supportsByob) { + var byobRequest = this._readableStreamController.byobRequest; + if (byobRequest) { + return this._pullWithByobRequest(byobRequest); + } + } + return this._pullWithDefaultReader(); + }; + WrappingReadableByteStreamSource.prototype._pullWithByobRequest = function (byobRequest) { + var _this = this; + this._attachByobReader(); + // reader.read(view) detaches the input view, therefore we cannot pass byobRequest.view directly + // create a separate buffer to read into, then copy that to byobRequest.view + var buffer = new Uint8Array(byobRequest.view.byteLength); + // TODO Backpressure? + var read = this._underlyingReader.read(buffer) + .then(function (result) { + _this._readableStreamController; + if (result.done) { + _this._tryClose(); + byobRequest.respond(0); + } + else { + copyArrayBufferView(result.value, byobRequest.view); + byobRequest.respond(result.value.byteLength); + } + }); + this._setPendingRead(read); + return read; + }; + return WrappingReadableByteStreamSource; + }(AbstractWrappingReadableStreamSource)); + + function createWritableStreamWrapper(ctor) { + assert$1(isWritableStreamConstructor(ctor)); + return function (writable) { + if (writable.constructor === ctor) { + return writable; + } + var sink = createWrappingWritableSink(writable); + return new ctor(sink); + }; + } + function createWrappingWritableSink(writable) { + assert$1(isWritableStream(writable)); + assert$1(writable.locked === false); + var writer = writable.getWriter(); + return new WrappingWritableStreamSink(writer); + } + var WrappingWritableStreamSink = /** @class */ (function () { + function WrappingWritableStreamSink(underlyingWriter) { + var _this = this; + this._writableStreamController = undefined; + this._pendingWrite = undefined; + this._state = "writable" /* WRITABLE */; + this._storedError = undefined; + this._underlyingWriter = underlyingWriter; + this._errorPromise = new Promise(function (resolve, reject) { + _this._errorPromiseReject = reject; + }); + this._errorPromise.catch(noop$1); + } + WrappingWritableStreamSink.prototype.start = function (controller) { + var _this = this; + this._writableStreamController = controller; + this._underlyingWriter.closed + .then(function () { + _this._state = "closed" /* CLOSED */; + }) + .catch(function (reason) { return _this._finishErroring(reason); }); + }; + WrappingWritableStreamSink.prototype.write = function (chunk) { + var _this = this; + var writer = this._underlyingWriter; + // Detect past errors + if (writer.desiredSize === null) { + return writer.ready; + } + var writeRequest = writer.write(chunk); + // Detect future errors + writeRequest.catch(function (reason) { return _this._finishErroring(reason); }); + writer.ready.catch(function (reason) { return _this._startErroring(reason); }); + // Reject write when errored + var write = Promise.race([writeRequest, this._errorPromise]); + this._setPendingWrite(write); + return write; + }; + WrappingWritableStreamSink.prototype.close = function () { + var _this = this; + if (this._pendingWrite === undefined) { + return this._underlyingWriter.close(); + } + return this._finishPendingWrite().then(function () { return _this.close(); }); + }; + WrappingWritableStreamSink.prototype.abort = function (reason) { + if (this._state === "errored" /* ERRORED */) { + return undefined; + } + var writer = this._underlyingWriter; + return writer.abort(reason); + }; + WrappingWritableStreamSink.prototype._setPendingWrite = function (writePromise) { + var _this = this; + var pendingWrite; + var finishWrite = function () { + if (_this._pendingWrite === pendingWrite) { + _this._pendingWrite = undefined; + } + }; + this._pendingWrite = pendingWrite = writePromise.then(finishWrite, finishWrite); + }; + WrappingWritableStreamSink.prototype._finishPendingWrite = function () { + var _this = this; + if (this._pendingWrite === undefined) { + return Promise.resolve(); + } + var afterWrite = function () { return _this._finishPendingWrite(); }; + return this._pendingWrite.then(afterWrite, afterWrite); + }; + WrappingWritableStreamSink.prototype._startErroring = function (reason) { + var _this = this; + if (this._state === "writable" /* WRITABLE */) { + this._state = "erroring" /* ERRORING */; + this._storedError = reason; + var afterWrite = function () { return _this._finishErroring(reason); }; + if (this._pendingWrite === undefined) { + afterWrite(); + } + else { + this._finishPendingWrite().then(afterWrite, afterWrite); + } + this._writableStreamController.error(reason); + } + }; + WrappingWritableStreamSink.prototype._finishErroring = function (reason) { + if (this._state === "writable" /* WRITABLE */) { + this._startErroring(reason); + } + if (this._state === "erroring" /* ERRORING */) { + this._state = "errored" /* ERRORED */; + this._errorPromiseReject(this._storedError); + } + }; + return WrappingWritableStreamSink; + }()); + + function createTransformStreamWrapper(ctor) { + assert$1(isTransformStreamConstructor(ctor)); + return function (transform) { + if (transform.constructor === ctor) { + return transform; + } + var transformer = createWrappingTransformer(transform); + return new ctor(transformer); + }; + } + function createWrappingTransformer(transform) { + assert$1(isTransformStream(transform)); + var readable = transform.readable, writable = transform.writable; + assert$1(readable.locked === false); + assert$1(writable.locked === false); + var reader = readable.getReader(); + var writer; + try { + writer = writable.getWriter(); + } + catch (e) { + reader.releaseLock(); // do not leak reader + throw e; + } + return new WrappingTransformStreamTransformer(reader, writer); + } + var WrappingTransformStreamTransformer = /** @class */ (function () { + function WrappingTransformStreamTransformer(reader, writer) { + var _this = this; + this._transformStreamController = undefined; + this._onRead = function (result) { + if (result.done) { + return; + } + _this._transformStreamController.enqueue(result.value); + return _this._reader.read().then(_this._onRead); + }; + this._onError = function (reason) { + _this._flushReject(reason); + _this._transformStreamController.error(reason); + _this._reader.cancel(reason).catch(noop$1); + _this._writer.abort(reason).catch(noop$1); + }; + this._onTerminate = function () { + _this._flushResolve(); + _this._transformStreamController.terminate(); + var error = new TypeError('TransformStream terminated'); + _this._writer.abort(error).catch(noop$1); + }; + this._reader = reader; + this._writer = writer; + this._flushPromise = new Promise(function (resolve, reject) { + _this._flushResolve = resolve; + _this._flushReject = reject; + }); + } + WrappingTransformStreamTransformer.prototype.start = function (controller) { + this._transformStreamController = controller; + this._reader.read() + .then(this._onRead) + .then(this._onTerminate, this._onError); + var readerClosed = this._reader.closed; + if (readerClosed) { + readerClosed + .then(this._onTerminate, this._onError); + } + }; + WrappingTransformStreamTransformer.prototype.transform = function (chunk) { + return this._writer.write(chunk); + }; + WrappingTransformStreamTransformer.prototype.flush = function () { + var _this = this; + return this._writer.close() + .then(function () { return _this._flushPromise; }); + }; + return WrappingTransformStreamTransformer; + }()); + + var webStreamsAdapter = /*#__PURE__*/Object.freeze({ + __proto__: null, + createReadableStreamWrapper: createReadableStreamWrapper, + createTransformStreamWrapper: createTransformStreamWrapper, + createWrappingReadableSource: createWrappingReadableSource, + createWrappingTransformer: createWrappingTransformer, + createWrappingWritableSink: createWrappingWritableSink, + createWritableStreamWrapper: createWritableStreamWrapper + }); + + var bn = createCommonjsModule(function (module) { + (function (module, exports) { + + // Utils + function assert (val, msg) { + if (!val) throw new Error(msg || 'Assertion failed'); + } + + // Could use `inherits` module, but don't want to move from single file + // architecture yet. + function inherits (ctor, superCtor) { + ctor.super_ = superCtor; + var TempCtor = function () {}; + TempCtor.prototype = superCtor.prototype; + ctor.prototype = new TempCtor(); + ctor.prototype.constructor = ctor; + } + + // BN + + function BN (number, base, endian) { + if (BN.isBN(number)) { + return number; + } + + this.negative = 0; + this.words = null; + this.length = 0; + + // Reduction context + this.red = null; + + if (number !== null) { + if (base === 'le' || base === 'be') { + endian = base; + base = 10; + } + + this._init(number || 0, base || 10, endian || 'be'); + } + } + if (typeof module === 'object') { + module.exports = BN; + } else { + exports.BN = BN; + } + + BN.BN = BN; + BN.wordSize = 26; + + var Buffer; + try { + Buffer = void('buffer').Buffer; + } catch (e) { + } + + BN.isBN = function isBN (num) { + if (num instanceof BN) { + return true; + } + + return num !== null && typeof num === 'object' && + num.constructor.wordSize === BN.wordSize && Array.isArray(num.words); + }; + + BN.max = function max (left, right) { + if (left.cmp(right) > 0) return left; + return right; + }; + + BN.min = function min (left, right) { + if (left.cmp(right) < 0) return left; + return right; + }; + + BN.prototype._init = function init (number, base, endian) { + if (typeof number === 'number') { + return this._initNumber(number, base, endian); + } + + if (typeof number === 'object') { + return this._initArray(number, base, endian); + } + + if (base === 'hex') { + base = 16; + } + assert(base === (base | 0) && base >= 2 && base <= 36); + + number = number.toString().replace(/\s+/g, ''); + var start = 0; + if (number[0] === '-') { + start++; + } + + if (base === 16) { + this._parseHex(number, start); + } else { + this._parseBase(number, base, start); + } + + if (number[0] === '-') { + this.negative = 1; + } + + this.strip(); + + if (endian !== 'le') return; + + this._initArray(this.toArray(), base, endian); + }; + + BN.prototype._initNumber = function _initNumber (number, base, endian) { + if (number < 0) { + this.negative = 1; + number = -number; + } + if (number < 0x4000000) { + this.words = [ number & 0x3ffffff ]; + this.length = 1; + } else if (number < 0x10000000000000) { + this.words = [ + number & 0x3ffffff, + (number / 0x4000000) & 0x3ffffff + ]; + this.length = 2; + } else { + assert(number < 0x20000000000000); // 2 ^ 53 (unsafe) + this.words = [ + number & 0x3ffffff, + (number / 0x4000000) & 0x3ffffff, + 1 + ]; + this.length = 3; + } + + if (endian !== 'le') return; + + // Reverse the bytes + this._initArray(this.toArray(), base, endian); + }; + + BN.prototype._initArray = function _initArray (number, base, endian) { + // Perhaps a Uint8Array + assert(typeof number.length === 'number'); + if (number.length <= 0) { + this.words = [ 0 ]; + this.length = 1; + return this; + } + + this.length = Math.ceil(number.length / 3); + this.words = new Array(this.length); + for (var i = 0; i < this.length; i++) { + this.words[i] = 0; + } + + var j, w; + var off = 0; + if (endian === 'be') { + for (i = number.length - 1, j = 0; i >= 0; i -= 3) { + w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16); + this.words[j] |= (w << off) & 0x3ffffff; + this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; + off += 24; + if (off >= 26) { + off -= 26; + j++; + } + } + } else if (endian === 'le') { + for (i = 0, j = 0; i < number.length; i += 3) { + w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16); + this.words[j] |= (w << off) & 0x3ffffff; + this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; + off += 24; + if (off >= 26) { + off -= 26; + j++; + } + } + } + return this.strip(); + }; + + function parseHex (str, start, end) { + var r = 0; + var len = Math.min(str.length, end); + for (var i = start; i < len; i++) { + var c = str.charCodeAt(i) - 48; + + r <<= 4; + + // 'a' - 'f' + if (c >= 49 && c <= 54) { + r |= c - 49 + 0xa; + + // 'A' - 'F' + } else if (c >= 17 && c <= 22) { + r |= c - 17 + 0xa; + + // '0' - '9' + } else { + r |= c & 0xf; + } + } + return r; + } + + BN.prototype._parseHex = function _parseHex (number, start) { + // Create possibly bigger array to ensure that it fits the number + this.length = Math.ceil((number.length - start) / 6); + this.words = new Array(this.length); + for (var i = 0; i < this.length; i++) { + this.words[i] = 0; + } + + var j, w; + // Scan 24-bit chunks and add them to the number + var off = 0; + for (i = number.length - 6, j = 0; i >= start; i -= 6) { + w = parseHex(number, i, i + 6); + this.words[j] |= (w << off) & 0x3ffffff; + // NOTE: `0x3fffff` is intentional here, 26bits max shift + 24bit hex limb + this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; + off += 24; + if (off >= 26) { + off -= 26; + j++; + } + } + if (i + 6 !== start) { + w = parseHex(number, start, i + 6); + this.words[j] |= (w << off) & 0x3ffffff; + this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; + } + this.strip(); + }; + + function parseBase (str, start, end, mul) { + var r = 0; + var len = Math.min(str.length, end); + for (var i = start; i < len; i++) { + var c = str.charCodeAt(i) - 48; + + r *= mul; + + // 'a' + if (c >= 49) { + r += c - 49 + 0xa; + + // 'A' + } else if (c >= 17) { + r += c - 17 + 0xa; + + // '0' - '9' + } else { + r += c; + } + } + return r; + } + + BN.prototype._parseBase = function _parseBase (number, base, start) { + // Initialize as zero + this.words = [ 0 ]; + this.length = 1; + + // Find length of limb in base + for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) { + limbLen++; + } + limbLen--; + limbPow = (limbPow / base) | 0; + + var total = number.length - start; + var mod = total % limbLen; + var end = Math.min(total, total - mod) + start; + + var word = 0; + for (var i = start; i < end; i += limbLen) { + word = parseBase(number, i, i + limbLen, base); + + this.imuln(limbPow); + if (this.words[0] + word < 0x4000000) { + this.words[0] += word; + } else { + this._iaddn(word); + } + } + + if (mod !== 0) { + var pow = 1; + word = parseBase(number, i, number.length, base); + + for (i = 0; i < mod; i++) { + pow *= base; + } + + this.imuln(pow); + if (this.words[0] + word < 0x4000000) { + this.words[0] += word; + } else { + this._iaddn(word); + } + } + }; + + BN.prototype.copy = function copy (dest) { + dest.words = new Array(this.length); + for (var i = 0; i < this.length; i++) { + dest.words[i] = this.words[i]; + } + dest.length = this.length; + dest.negative = this.negative; + dest.red = this.red; + }; + + BN.prototype.clone = function clone () { + var r = new BN(null); + this.copy(r); + return r; + }; + + BN.prototype._expand = function _expand (size) { + while (this.length < size) { + this.words[this.length++] = 0; + } + return this; + }; + + // Remove leading `0` from `this` + BN.prototype.strip = function strip () { + while (this.length > 1 && this.words[this.length - 1] === 0) { + this.length--; + } + return this._normSign(); + }; + + BN.prototype._normSign = function _normSign () { + // -0 = 0 + if (this.length === 1 && this.words[0] === 0) { + this.negative = 0; + } + return this; + }; + + BN.prototype.inspect = function inspect () { + return (this.red ? ''; + }; + + /* + + var zeros = []; + var groupSizes = []; + var groupBases = []; + + var s = ''; + var i = -1; + while (++i < BN.wordSize) { + zeros[i] = s; + s += '0'; + } + groupSizes[0] = 0; + groupSizes[1] = 0; + groupBases[0] = 0; + groupBases[1] = 0; + var base = 2 - 1; + while (++base < 36 + 1) { + var groupSize = 0; + var groupBase = 1; + while (groupBase < (1 << BN.wordSize) / base) { + groupBase *= base; + groupSize += 1; + } + groupSizes[base] = groupSize; + groupBases[base] = groupBase; + } + + */ + + var zeros = [ + '', + '0', + '00', + '000', + '0000', + '00000', + '000000', + '0000000', + '00000000', + '000000000', + '0000000000', + '00000000000', + '000000000000', + '0000000000000', + '00000000000000', + '000000000000000', + '0000000000000000', + '00000000000000000', + '000000000000000000', + '0000000000000000000', + '00000000000000000000', + '000000000000000000000', + '0000000000000000000000', + '00000000000000000000000', + '000000000000000000000000', + '0000000000000000000000000' + ]; + + var groupSizes = [ + 0, 0, + 25, 16, 12, 11, 10, 9, 8, + 8, 7, 7, 7, 7, 6, 6, + 6, 6, 6, 6, 6, 5, 5, + 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5 + ]; + + var groupBases = [ + 0, 0, + 33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216, + 43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625, + 16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632, + 6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149, + 24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176 + ]; + + BN.prototype.toString = function toString (base, padding) { + base = base || 10; + padding = padding | 0 || 1; + + var out; + if (base === 16 || base === 'hex') { + out = ''; + var off = 0; + var carry = 0; + for (var i = 0; i < this.length; i++) { + var w = this.words[i]; + var word = (((w << off) | carry) & 0xffffff).toString(16); + carry = (w >>> (24 - off)) & 0xffffff; + if (carry !== 0 || i !== this.length - 1) { + out = zeros[6 - word.length] + word + out; + } else { + out = word + out; + } + off += 2; + if (off >= 26) { + off -= 26; + i--; + } + } + if (carry !== 0) { + out = carry.toString(16) + out; + } + while (out.length % padding !== 0) { + out = '0' + out; + } + if (this.negative !== 0) { + out = '-' + out; + } + return out; + } + + if (base === (base | 0) && base >= 2 && base <= 36) { + // var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base)); + var groupSize = groupSizes[base]; + // var groupBase = Math.pow(base, groupSize); + var groupBase = groupBases[base]; + out = ''; + var c = this.clone(); + c.negative = 0; + while (!c.isZero()) { + var r = c.modn(groupBase).toString(base); + c = c.idivn(groupBase); + + if (!c.isZero()) { + out = zeros[groupSize - r.length] + r + out; + } else { + out = r + out; + } + } + if (this.isZero()) { + out = '0' + out; + } + while (out.length % padding !== 0) { + out = '0' + out; + } + if (this.negative !== 0) { + out = '-' + out; + } + return out; + } + + assert(false, 'Base should be between 2 and 36'); + }; + + BN.prototype.toNumber = function toNumber () { + var ret = this.words[0]; + if (this.length === 2) { + ret += this.words[1] * 0x4000000; + } else if (this.length === 3 && this.words[2] === 0x01) { + // NOTE: at this stage it is known that the top bit is set + ret += 0x10000000000000 + (this.words[1] * 0x4000000); + } else if (this.length > 2) { + assert(false, 'Number can only safely store up to 53 bits'); + } + return (this.negative !== 0) ? -ret : ret; + }; + + BN.prototype.toJSON = function toJSON () { + return this.toString(16); + }; + + BN.prototype.toBuffer = function toBuffer (endian, length) { + assert(typeof Buffer !== 'undefined'); + return this.toArrayLike(Buffer, endian, length); + }; + + BN.prototype.toArray = function toArray (endian, length) { + return this.toArrayLike(Array, endian, length); + }; + + BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) { + var byteLength = this.byteLength(); + var reqLength = length || Math.max(1, byteLength); + assert(byteLength <= reqLength, 'byte array longer than desired length'); + assert(reqLength > 0, 'Requested array length <= 0'); + + this.strip(); + var littleEndian = endian === 'le'; + var res = new ArrayType(reqLength); + + var b, i; + var q = this.clone(); + if (!littleEndian) { + // Assume big-endian + for (i = 0; i < reqLength - byteLength; i++) { + res[i] = 0; + } + + for (i = 0; !q.isZero(); i++) { + b = q.andln(0xff); + q.iushrn(8); + + res[reqLength - i - 1] = b; + } + } else { + for (i = 0; !q.isZero(); i++) { + b = q.andln(0xff); + q.iushrn(8); + + res[i] = b; + } + + for (; i < reqLength; i++) { + res[i] = 0; + } + } + + return res; + }; + + if (Math.clz32) { + BN.prototype._countBits = function _countBits (w) { + return 32 - Math.clz32(w); + }; + } else { + BN.prototype._countBits = function _countBits (w) { + var t = w; + var r = 0; + if (t >= 0x1000) { + r += 13; + t >>>= 13; + } + if (t >= 0x40) { + r += 7; + t >>>= 7; + } + if (t >= 0x8) { + r += 4; + t >>>= 4; + } + if (t >= 0x02) { + r += 2; + t >>>= 2; + } + return r + t; + }; + } + + BN.prototype._zeroBits = function _zeroBits (w) { + // Short-cut + if (w === 0) return 26; + + var t = w; + var r = 0; + if ((t & 0x1fff) === 0) { + r += 13; + t >>>= 13; + } + if ((t & 0x7f) === 0) { + r += 7; + t >>>= 7; + } + if ((t & 0xf) === 0) { + r += 4; + t >>>= 4; + } + if ((t & 0x3) === 0) { + r += 2; + t >>>= 2; + } + if ((t & 0x1) === 0) { + r++; + } + return r; + }; + + // Return number of used bits in a BN + BN.prototype.bitLength = function bitLength () { + var w = this.words[this.length - 1]; + var hi = this._countBits(w); + return (this.length - 1) * 26 + hi; + }; + + function toBitArray (num) { + var w = new Array(num.bitLength()); + + for (var bit = 0; bit < w.length; bit++) { + var off = (bit / 26) | 0; + var wbit = bit % 26; + + w[bit] = (num.words[off] & (1 << wbit)) >>> wbit; + } + + return w; + } + + // Number of trailing zero bits + BN.prototype.zeroBits = function zeroBits () { + if (this.isZero()) return 0; + + var r = 0; + for (var i = 0; i < this.length; i++) { + var b = this._zeroBits(this.words[i]); + r += b; + if (b !== 26) break; + } + return r; + }; + + BN.prototype.byteLength = function byteLength () { + return Math.ceil(this.bitLength() / 8); + }; + + BN.prototype.toTwos = function toTwos (width) { + if (this.negative !== 0) { + return this.abs().inotn(width).iaddn(1); + } + return this.clone(); + }; + + BN.prototype.fromTwos = function fromTwos (width) { + if (this.testn(width - 1)) { + return this.notn(width).iaddn(1).ineg(); + } + return this.clone(); + }; + + BN.prototype.isNeg = function isNeg () { + return this.negative !== 0; + }; + + // Return negative clone of `this` + BN.prototype.neg = function neg () { + return this.clone().ineg(); + }; + + BN.prototype.ineg = function ineg () { + if (!this.isZero()) { + this.negative ^= 1; + } + + return this; + }; + + // Or `num` with `this` in-place + BN.prototype.iuor = function iuor (num) { + while (this.length < num.length) { + this.words[this.length++] = 0; + } + + for (var i = 0; i < num.length; i++) { + this.words[i] = this.words[i] | num.words[i]; + } + + return this.strip(); + }; + + BN.prototype.ior = function ior (num) { + assert((this.negative | num.negative) === 0); + return this.iuor(num); + }; + + // Or `num` with `this` + BN.prototype.or = function or (num) { + if (this.length > num.length) return this.clone().ior(num); + return num.clone().ior(this); + }; + + BN.prototype.uor = function uor (num) { + if (this.length > num.length) return this.clone().iuor(num); + return num.clone().iuor(this); + }; + + // And `num` with `this` in-place + BN.prototype.iuand = function iuand (num) { + // b = min-length(num, this) + var b; + if (this.length > num.length) { + b = num; + } else { + b = this; + } + + for (var i = 0; i < b.length; i++) { + this.words[i] = this.words[i] & num.words[i]; + } + + this.length = b.length; + + return this.strip(); + }; + + BN.prototype.iand = function iand (num) { + assert((this.negative | num.negative) === 0); + return this.iuand(num); + }; + + // And `num` with `this` + BN.prototype.and = function and (num) { + if (this.length > num.length) return this.clone().iand(num); + return num.clone().iand(this); + }; + + BN.prototype.uand = function uand (num) { + if (this.length > num.length) return this.clone().iuand(num); + return num.clone().iuand(this); + }; + + // Xor `num` with `this` in-place + BN.prototype.iuxor = function iuxor (num) { + // a.length > b.length + var a; + var b; + if (this.length > num.length) { + a = this; + b = num; + } else { + a = num; + b = this; + } + + for (var i = 0; i < b.length; i++) { + this.words[i] = a.words[i] ^ b.words[i]; + } + + if (this !== a) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } + } + + this.length = a.length; + + return this.strip(); + }; + + BN.prototype.ixor = function ixor (num) { + assert((this.negative | num.negative) === 0); + return this.iuxor(num); + }; + + // Xor `num` with `this` + BN.prototype.xor = function xor (num) { + if (this.length > num.length) return this.clone().ixor(num); + return num.clone().ixor(this); + }; + + BN.prototype.uxor = function uxor (num) { + if (this.length > num.length) return this.clone().iuxor(num); + return num.clone().iuxor(this); + }; + + // Not ``this`` with ``width`` bitwidth + BN.prototype.inotn = function inotn (width) { + assert(typeof width === 'number' && width >= 0); + + var bytesNeeded = Math.ceil(width / 26) | 0; + var bitsLeft = width % 26; + + // Extend the buffer with leading zeroes + this._expand(bytesNeeded); + + if (bitsLeft > 0) { + bytesNeeded--; + } + + // Handle complete words + for (var i = 0; i < bytesNeeded; i++) { + this.words[i] = ~this.words[i] & 0x3ffffff; + } + + // Handle the residue + if (bitsLeft > 0) { + this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft)); + } + + // And remove leading zeroes + return this.strip(); + }; + + BN.prototype.notn = function notn (width) { + return this.clone().inotn(width); + }; + + // Set `bit` of `this` + BN.prototype.setn = function setn (bit, val) { + assert(typeof bit === 'number' && bit >= 0); + + var off = (bit / 26) | 0; + var wbit = bit % 26; + + this._expand(off + 1); + + if (val) { + this.words[off] = this.words[off] | (1 << wbit); + } else { + this.words[off] = this.words[off] & ~(1 << wbit); + } + + return this.strip(); + }; + + // Add `num` to `this` in-place + BN.prototype.iadd = function iadd (num) { + var r; + + // negative + positive + if (this.negative !== 0 && num.negative === 0) { + this.negative = 0; + r = this.isub(num); + this.negative ^= 1; + return this._normSign(); + + // positive + negative + } else if (this.negative === 0 && num.negative !== 0) { + num.negative = 0; + r = this.isub(num); + num.negative = 1; + return r._normSign(); + } + + // a.length > b.length + var a, b; + if (this.length > num.length) { + a = this; + b = num; + } else { + a = num; + b = this; + } + + var carry = 0; + for (var i = 0; i < b.length; i++) { + r = (a.words[i] | 0) + (b.words[i] | 0) + carry; + this.words[i] = r & 0x3ffffff; + carry = r >>> 26; + } + for (; carry !== 0 && i < a.length; i++) { + r = (a.words[i] | 0) + carry; + this.words[i] = r & 0x3ffffff; + carry = r >>> 26; + } + + this.length = a.length; + if (carry !== 0) { + this.words[this.length] = carry; + this.length++; + // Copy the rest of the words + } else if (a !== this) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } + } + + return this; + }; + + // Add `num` to `this` + BN.prototype.add = function add (num) { + var res; + if (num.negative !== 0 && this.negative === 0) { + num.negative = 0; + res = this.sub(num); + num.negative ^= 1; + return res; + } else if (num.negative === 0 && this.negative !== 0) { + this.negative = 0; + res = num.sub(this); + this.negative = 1; + return res; + } + + if (this.length > num.length) return this.clone().iadd(num); + + return num.clone().iadd(this); + }; + + // Subtract `num` from `this` in-place + BN.prototype.isub = function isub (num) { + // this - (-num) = this + num + if (num.negative !== 0) { + num.negative = 0; + var r = this.iadd(num); + num.negative = 1; + return r._normSign(); + + // -this - num = -(this + num) + } else if (this.negative !== 0) { + this.negative = 0; + this.iadd(num); + this.negative = 1; + return this._normSign(); + } + + // At this point both numbers are positive + var cmp = this.cmp(num); + + // Optimization - zeroify + if (cmp === 0) { + this.negative = 0; + this.length = 1; + this.words[0] = 0; + return this; + } + + // a > b + var a, b; + if (cmp > 0) { + a = this; + b = num; + } else { + a = num; + b = this; + } + + var carry = 0; + for (var i = 0; i < b.length; i++) { + r = (a.words[i] | 0) - (b.words[i] | 0) + carry; + carry = r >> 26; + this.words[i] = r & 0x3ffffff; + } + for (; carry !== 0 && i < a.length; i++) { + r = (a.words[i] | 0) + carry; + carry = r >> 26; + this.words[i] = r & 0x3ffffff; + } + + // Copy rest of the words + if (carry === 0 && i < a.length && a !== this) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } + } + + this.length = Math.max(this.length, i); + + if (a !== this) { + this.negative = 1; + } + + return this.strip(); + }; + + // Subtract `num` from `this` + BN.prototype.sub = function sub (num) { + return this.clone().isub(num); + }; + + function smallMulTo (self, num, out) { + out.negative = num.negative ^ self.negative; + var len = (self.length + num.length) | 0; + out.length = len; + len = (len - 1) | 0; + + // Peel one iteration (compiler can't do it, because of code complexity) + var a = self.words[0] | 0; + var b = num.words[0] | 0; + var r = a * b; + + var lo = r & 0x3ffffff; + var carry = (r / 0x4000000) | 0; + out.words[0] = lo; + + for (var k = 1; k < len; k++) { + // Sum all words with the same `i + j = k` and accumulate `ncarry`, + // note that ncarry could be >= 0x3ffffff + var ncarry = carry >>> 26; + var rword = carry & 0x3ffffff; + var maxJ = Math.min(k, num.length - 1); + for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { + var i = (k - j) | 0; + a = self.words[i] | 0; + b = num.words[j] | 0; + r = a * b + rword; + ncarry += (r / 0x4000000) | 0; + rword = r & 0x3ffffff; + } + out.words[k] = rword | 0; + carry = ncarry | 0; + } + if (carry !== 0) { + out.words[k] = carry | 0; + } else { + out.length--; + } + + return out.strip(); + } + + // TODO(indutny): it may be reasonable to omit it for users who don't need + // to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit + // multiplication (like elliptic secp256k1). + var comb10MulTo = function comb10MulTo (self, num, out) { + var a = self.words; + var b = num.words; + var o = out.words; + var c = 0; + var lo; + var mid; + var hi; + var a0 = a[0] | 0; + var al0 = a0 & 0x1fff; + var ah0 = a0 >>> 13; + var a1 = a[1] | 0; + var al1 = a1 & 0x1fff; + var ah1 = a1 >>> 13; + var a2 = a[2] | 0; + var al2 = a2 & 0x1fff; + var ah2 = a2 >>> 13; + var a3 = a[3] | 0; + var al3 = a3 & 0x1fff; + var ah3 = a3 >>> 13; + var a4 = a[4] | 0; + var al4 = a4 & 0x1fff; + var ah4 = a4 >>> 13; + var a5 = a[5] | 0; + var al5 = a5 & 0x1fff; + var ah5 = a5 >>> 13; + var a6 = a[6] | 0; + var al6 = a6 & 0x1fff; + var ah6 = a6 >>> 13; + var a7 = a[7] | 0; + var al7 = a7 & 0x1fff; + var ah7 = a7 >>> 13; + var a8 = a[8] | 0; + var al8 = a8 & 0x1fff; + var ah8 = a8 >>> 13; + var a9 = a[9] | 0; + var al9 = a9 & 0x1fff; + var ah9 = a9 >>> 13; + var b0 = b[0] | 0; + var bl0 = b0 & 0x1fff; + var bh0 = b0 >>> 13; + var b1 = b[1] | 0; + var bl1 = b1 & 0x1fff; + var bh1 = b1 >>> 13; + var b2 = b[2] | 0; + var bl2 = b2 & 0x1fff; + var bh2 = b2 >>> 13; + var b3 = b[3] | 0; + var bl3 = b3 & 0x1fff; + var bh3 = b3 >>> 13; + var b4 = b[4] | 0; + var bl4 = b4 & 0x1fff; + var bh4 = b4 >>> 13; + var b5 = b[5] | 0; + var bl5 = b5 & 0x1fff; + var bh5 = b5 >>> 13; + var b6 = b[6] | 0; + var bl6 = b6 & 0x1fff; + var bh6 = b6 >>> 13; + var b7 = b[7] | 0; + var bl7 = b7 & 0x1fff; + var bh7 = b7 >>> 13; + var b8 = b[8] | 0; + var bl8 = b8 & 0x1fff; + var bh8 = b8 >>> 13; + var b9 = b[9] | 0; + var bl9 = b9 & 0x1fff; + var bh9 = b9 >>> 13; + + out.negative = self.negative ^ num.negative; + out.length = 19; + /* k = 0 */ + lo = Math.imul(al0, bl0); + mid = Math.imul(al0, bh0); + mid = (mid + Math.imul(ah0, bl0)) | 0; + hi = Math.imul(ah0, bh0); + var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0; + w0 &= 0x3ffffff; + /* k = 1 */ + lo = Math.imul(al1, bl0); + mid = Math.imul(al1, bh0); + mid = (mid + Math.imul(ah1, bl0)) | 0; + hi = Math.imul(ah1, bh0); + lo = (lo + Math.imul(al0, bl1)) | 0; + mid = (mid + Math.imul(al0, bh1)) | 0; + mid = (mid + Math.imul(ah0, bl1)) | 0; + hi = (hi + Math.imul(ah0, bh1)) | 0; + var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0; + w1 &= 0x3ffffff; + /* k = 2 */ + lo = Math.imul(al2, bl0); + mid = Math.imul(al2, bh0); + mid = (mid + Math.imul(ah2, bl0)) | 0; + hi = Math.imul(ah2, bh0); + lo = (lo + Math.imul(al1, bl1)) | 0; + mid = (mid + Math.imul(al1, bh1)) | 0; + mid = (mid + Math.imul(ah1, bl1)) | 0; + hi = (hi + Math.imul(ah1, bh1)) | 0; + lo = (lo + Math.imul(al0, bl2)) | 0; + mid = (mid + Math.imul(al0, bh2)) | 0; + mid = (mid + Math.imul(ah0, bl2)) | 0; + hi = (hi + Math.imul(ah0, bh2)) | 0; + var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0; + w2 &= 0x3ffffff; + /* k = 3 */ + lo = Math.imul(al3, bl0); + mid = Math.imul(al3, bh0); + mid = (mid + Math.imul(ah3, bl0)) | 0; + hi = Math.imul(ah3, bh0); + lo = (lo + Math.imul(al2, bl1)) | 0; + mid = (mid + Math.imul(al2, bh1)) | 0; + mid = (mid + Math.imul(ah2, bl1)) | 0; + hi = (hi + Math.imul(ah2, bh1)) | 0; + lo = (lo + Math.imul(al1, bl2)) | 0; + mid = (mid + Math.imul(al1, bh2)) | 0; + mid = (mid + Math.imul(ah1, bl2)) | 0; + hi = (hi + Math.imul(ah1, bh2)) | 0; + lo = (lo + Math.imul(al0, bl3)) | 0; + mid = (mid + Math.imul(al0, bh3)) | 0; + mid = (mid + Math.imul(ah0, bl3)) | 0; + hi = (hi + Math.imul(ah0, bh3)) | 0; + var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0; + w3 &= 0x3ffffff; + /* k = 4 */ + lo = Math.imul(al4, bl0); + mid = Math.imul(al4, bh0); + mid = (mid + Math.imul(ah4, bl0)) | 0; + hi = Math.imul(ah4, bh0); + lo = (lo + Math.imul(al3, bl1)) | 0; + mid = (mid + Math.imul(al3, bh1)) | 0; + mid = (mid + Math.imul(ah3, bl1)) | 0; + hi = (hi + Math.imul(ah3, bh1)) | 0; + lo = (lo + Math.imul(al2, bl2)) | 0; + mid = (mid + Math.imul(al2, bh2)) | 0; + mid = (mid + Math.imul(ah2, bl2)) | 0; + hi = (hi + Math.imul(ah2, bh2)) | 0; + lo = (lo + Math.imul(al1, bl3)) | 0; + mid = (mid + Math.imul(al1, bh3)) | 0; + mid = (mid + Math.imul(ah1, bl3)) | 0; + hi = (hi + Math.imul(ah1, bh3)) | 0; + lo = (lo + Math.imul(al0, bl4)) | 0; + mid = (mid + Math.imul(al0, bh4)) | 0; + mid = (mid + Math.imul(ah0, bl4)) | 0; + hi = (hi + Math.imul(ah0, bh4)) | 0; + var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0; + w4 &= 0x3ffffff; + /* k = 5 */ + lo = Math.imul(al5, bl0); + mid = Math.imul(al5, bh0); + mid = (mid + Math.imul(ah5, bl0)) | 0; + hi = Math.imul(ah5, bh0); + lo = (lo + Math.imul(al4, bl1)) | 0; + mid = (mid + Math.imul(al4, bh1)) | 0; + mid = (mid + Math.imul(ah4, bl1)) | 0; + hi = (hi + Math.imul(ah4, bh1)) | 0; + lo = (lo + Math.imul(al3, bl2)) | 0; + mid = (mid + Math.imul(al3, bh2)) | 0; + mid = (mid + Math.imul(ah3, bl2)) | 0; + hi = (hi + Math.imul(ah3, bh2)) | 0; + lo = (lo + Math.imul(al2, bl3)) | 0; + mid = (mid + Math.imul(al2, bh3)) | 0; + mid = (mid + Math.imul(ah2, bl3)) | 0; + hi = (hi + Math.imul(ah2, bh3)) | 0; + lo = (lo + Math.imul(al1, bl4)) | 0; + mid = (mid + Math.imul(al1, bh4)) | 0; + mid = (mid + Math.imul(ah1, bl4)) | 0; + hi = (hi + Math.imul(ah1, bh4)) | 0; + lo = (lo + Math.imul(al0, bl5)) | 0; + mid = (mid + Math.imul(al0, bh5)) | 0; + mid = (mid + Math.imul(ah0, bl5)) | 0; + hi = (hi + Math.imul(ah0, bh5)) | 0; + var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0; + w5 &= 0x3ffffff; + /* k = 6 */ + lo = Math.imul(al6, bl0); + mid = Math.imul(al6, bh0); + mid = (mid + Math.imul(ah6, bl0)) | 0; + hi = Math.imul(ah6, bh0); + lo = (lo + Math.imul(al5, bl1)) | 0; + mid = (mid + Math.imul(al5, bh1)) | 0; + mid = (mid + Math.imul(ah5, bl1)) | 0; + hi = (hi + Math.imul(ah5, bh1)) | 0; + lo = (lo + Math.imul(al4, bl2)) | 0; + mid = (mid + Math.imul(al4, bh2)) | 0; + mid = (mid + Math.imul(ah4, bl2)) | 0; + hi = (hi + Math.imul(ah4, bh2)) | 0; + lo = (lo + Math.imul(al3, bl3)) | 0; + mid = (mid + Math.imul(al3, bh3)) | 0; + mid = (mid + Math.imul(ah3, bl3)) | 0; + hi = (hi + Math.imul(ah3, bh3)) | 0; + lo = (lo + Math.imul(al2, bl4)) | 0; + mid = (mid + Math.imul(al2, bh4)) | 0; + mid = (mid + Math.imul(ah2, bl4)) | 0; + hi = (hi + Math.imul(ah2, bh4)) | 0; + lo = (lo + Math.imul(al1, bl5)) | 0; + mid = (mid + Math.imul(al1, bh5)) | 0; + mid = (mid + Math.imul(ah1, bl5)) | 0; + hi = (hi + Math.imul(ah1, bh5)) | 0; + lo = (lo + Math.imul(al0, bl6)) | 0; + mid = (mid + Math.imul(al0, bh6)) | 0; + mid = (mid + Math.imul(ah0, bl6)) | 0; + hi = (hi + Math.imul(ah0, bh6)) | 0; + var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0; + w6 &= 0x3ffffff; + /* k = 7 */ + lo = Math.imul(al7, bl0); + mid = Math.imul(al7, bh0); + mid = (mid + Math.imul(ah7, bl0)) | 0; + hi = Math.imul(ah7, bh0); + lo = (lo + Math.imul(al6, bl1)) | 0; + mid = (mid + Math.imul(al6, bh1)) | 0; + mid = (mid + Math.imul(ah6, bl1)) | 0; + hi = (hi + Math.imul(ah6, bh1)) | 0; + lo = (lo + Math.imul(al5, bl2)) | 0; + mid = (mid + Math.imul(al5, bh2)) | 0; + mid = (mid + Math.imul(ah5, bl2)) | 0; + hi = (hi + Math.imul(ah5, bh2)) | 0; + lo = (lo + Math.imul(al4, bl3)) | 0; + mid = (mid + Math.imul(al4, bh3)) | 0; + mid = (mid + Math.imul(ah4, bl3)) | 0; + hi = (hi + Math.imul(ah4, bh3)) | 0; + lo = (lo + Math.imul(al3, bl4)) | 0; + mid = (mid + Math.imul(al3, bh4)) | 0; + mid = (mid + Math.imul(ah3, bl4)) | 0; + hi = (hi + Math.imul(ah3, bh4)) | 0; + lo = (lo + Math.imul(al2, bl5)) | 0; + mid = (mid + Math.imul(al2, bh5)) | 0; + mid = (mid + Math.imul(ah2, bl5)) | 0; + hi = (hi + Math.imul(ah2, bh5)) | 0; + lo = (lo + Math.imul(al1, bl6)) | 0; + mid = (mid + Math.imul(al1, bh6)) | 0; + mid = (mid + Math.imul(ah1, bl6)) | 0; + hi = (hi + Math.imul(ah1, bh6)) | 0; + lo = (lo + Math.imul(al0, bl7)) | 0; + mid = (mid + Math.imul(al0, bh7)) | 0; + mid = (mid + Math.imul(ah0, bl7)) | 0; + hi = (hi + Math.imul(ah0, bh7)) | 0; + var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0; + w7 &= 0x3ffffff; + /* k = 8 */ + lo = Math.imul(al8, bl0); + mid = Math.imul(al8, bh0); + mid = (mid + Math.imul(ah8, bl0)) | 0; + hi = Math.imul(ah8, bh0); + lo = (lo + Math.imul(al7, bl1)) | 0; + mid = (mid + Math.imul(al7, bh1)) | 0; + mid = (mid + Math.imul(ah7, bl1)) | 0; + hi = (hi + Math.imul(ah7, bh1)) | 0; + lo = (lo + Math.imul(al6, bl2)) | 0; + mid = (mid + Math.imul(al6, bh2)) | 0; + mid = (mid + Math.imul(ah6, bl2)) | 0; + hi = (hi + Math.imul(ah6, bh2)) | 0; + lo = (lo + Math.imul(al5, bl3)) | 0; + mid = (mid + Math.imul(al5, bh3)) | 0; + mid = (mid + Math.imul(ah5, bl3)) | 0; + hi = (hi + Math.imul(ah5, bh3)) | 0; + lo = (lo + Math.imul(al4, bl4)) | 0; + mid = (mid + Math.imul(al4, bh4)) | 0; + mid = (mid + Math.imul(ah4, bl4)) | 0; + hi = (hi + Math.imul(ah4, bh4)) | 0; + lo = (lo + Math.imul(al3, bl5)) | 0; + mid = (mid + Math.imul(al3, bh5)) | 0; + mid = (mid + Math.imul(ah3, bl5)) | 0; + hi = (hi + Math.imul(ah3, bh5)) | 0; + lo = (lo + Math.imul(al2, bl6)) | 0; + mid = (mid + Math.imul(al2, bh6)) | 0; + mid = (mid + Math.imul(ah2, bl6)) | 0; + hi = (hi + Math.imul(ah2, bh6)) | 0; + lo = (lo + Math.imul(al1, bl7)) | 0; + mid = (mid + Math.imul(al1, bh7)) | 0; + mid = (mid + Math.imul(ah1, bl7)) | 0; + hi = (hi + Math.imul(ah1, bh7)) | 0; + lo = (lo + Math.imul(al0, bl8)) | 0; + mid = (mid + Math.imul(al0, bh8)) | 0; + mid = (mid + Math.imul(ah0, bl8)) | 0; + hi = (hi + Math.imul(ah0, bh8)) | 0; + var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0; + w8 &= 0x3ffffff; + /* k = 9 */ + lo = Math.imul(al9, bl0); + mid = Math.imul(al9, bh0); + mid = (mid + Math.imul(ah9, bl0)) | 0; + hi = Math.imul(ah9, bh0); + lo = (lo + Math.imul(al8, bl1)) | 0; + mid = (mid + Math.imul(al8, bh1)) | 0; + mid = (mid + Math.imul(ah8, bl1)) | 0; + hi = (hi + Math.imul(ah8, bh1)) | 0; + lo = (lo + Math.imul(al7, bl2)) | 0; + mid = (mid + Math.imul(al7, bh2)) | 0; + mid = (mid + Math.imul(ah7, bl2)) | 0; + hi = (hi + Math.imul(ah7, bh2)) | 0; + lo = (lo + Math.imul(al6, bl3)) | 0; + mid = (mid + Math.imul(al6, bh3)) | 0; + mid = (mid + Math.imul(ah6, bl3)) | 0; + hi = (hi + Math.imul(ah6, bh3)) | 0; + lo = (lo + Math.imul(al5, bl4)) | 0; + mid = (mid + Math.imul(al5, bh4)) | 0; + mid = (mid + Math.imul(ah5, bl4)) | 0; + hi = (hi + Math.imul(ah5, bh4)) | 0; + lo = (lo + Math.imul(al4, bl5)) | 0; + mid = (mid + Math.imul(al4, bh5)) | 0; + mid = (mid + Math.imul(ah4, bl5)) | 0; + hi = (hi + Math.imul(ah4, bh5)) | 0; + lo = (lo + Math.imul(al3, bl6)) | 0; + mid = (mid + Math.imul(al3, bh6)) | 0; + mid = (mid + Math.imul(ah3, bl6)) | 0; + hi = (hi + Math.imul(ah3, bh6)) | 0; + lo = (lo + Math.imul(al2, bl7)) | 0; + mid = (mid + Math.imul(al2, bh7)) | 0; + mid = (mid + Math.imul(ah2, bl7)) | 0; + hi = (hi + Math.imul(ah2, bh7)) | 0; + lo = (lo + Math.imul(al1, bl8)) | 0; + mid = (mid + Math.imul(al1, bh8)) | 0; + mid = (mid + Math.imul(ah1, bl8)) | 0; + hi = (hi + Math.imul(ah1, bh8)) | 0; + lo = (lo + Math.imul(al0, bl9)) | 0; + mid = (mid + Math.imul(al0, bh9)) | 0; + mid = (mid + Math.imul(ah0, bl9)) | 0; + hi = (hi + Math.imul(ah0, bh9)) | 0; + var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0; + w9 &= 0x3ffffff; + /* k = 10 */ + lo = Math.imul(al9, bl1); + mid = Math.imul(al9, bh1); + mid = (mid + Math.imul(ah9, bl1)) | 0; + hi = Math.imul(ah9, bh1); + lo = (lo + Math.imul(al8, bl2)) | 0; + mid = (mid + Math.imul(al8, bh2)) | 0; + mid = (mid + Math.imul(ah8, bl2)) | 0; + hi = (hi + Math.imul(ah8, bh2)) | 0; + lo = (lo + Math.imul(al7, bl3)) | 0; + mid = (mid + Math.imul(al7, bh3)) | 0; + mid = (mid + Math.imul(ah7, bl3)) | 0; + hi = (hi + Math.imul(ah7, bh3)) | 0; + lo = (lo + Math.imul(al6, bl4)) | 0; + mid = (mid + Math.imul(al6, bh4)) | 0; + mid = (mid + Math.imul(ah6, bl4)) | 0; + hi = (hi + Math.imul(ah6, bh4)) | 0; + lo = (lo + Math.imul(al5, bl5)) | 0; + mid = (mid + Math.imul(al5, bh5)) | 0; + mid = (mid + Math.imul(ah5, bl5)) | 0; + hi = (hi + Math.imul(ah5, bh5)) | 0; + lo = (lo + Math.imul(al4, bl6)) | 0; + mid = (mid + Math.imul(al4, bh6)) | 0; + mid = (mid + Math.imul(ah4, bl6)) | 0; + hi = (hi + Math.imul(ah4, bh6)) | 0; + lo = (lo + Math.imul(al3, bl7)) | 0; + mid = (mid + Math.imul(al3, bh7)) | 0; + mid = (mid + Math.imul(ah3, bl7)) | 0; + hi = (hi + Math.imul(ah3, bh7)) | 0; + lo = (lo + Math.imul(al2, bl8)) | 0; + mid = (mid + Math.imul(al2, bh8)) | 0; + mid = (mid + Math.imul(ah2, bl8)) | 0; + hi = (hi + Math.imul(ah2, bh8)) | 0; + lo = (lo + Math.imul(al1, bl9)) | 0; + mid = (mid + Math.imul(al1, bh9)) | 0; + mid = (mid + Math.imul(ah1, bl9)) | 0; + hi = (hi + Math.imul(ah1, bh9)) | 0; + var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0; + w10 &= 0x3ffffff; + /* k = 11 */ + lo = Math.imul(al9, bl2); + mid = Math.imul(al9, bh2); + mid = (mid + Math.imul(ah9, bl2)) | 0; + hi = Math.imul(ah9, bh2); + lo = (lo + Math.imul(al8, bl3)) | 0; + mid = (mid + Math.imul(al8, bh3)) | 0; + mid = (mid + Math.imul(ah8, bl3)) | 0; + hi = (hi + Math.imul(ah8, bh3)) | 0; + lo = (lo + Math.imul(al7, bl4)) | 0; + mid = (mid + Math.imul(al7, bh4)) | 0; + mid = (mid + Math.imul(ah7, bl4)) | 0; + hi = (hi + Math.imul(ah7, bh4)) | 0; + lo = (lo + Math.imul(al6, bl5)) | 0; + mid = (mid + Math.imul(al6, bh5)) | 0; + mid = (mid + Math.imul(ah6, bl5)) | 0; + hi = (hi + Math.imul(ah6, bh5)) | 0; + lo = (lo + Math.imul(al5, bl6)) | 0; + mid = (mid + Math.imul(al5, bh6)) | 0; + mid = (mid + Math.imul(ah5, bl6)) | 0; + hi = (hi + Math.imul(ah5, bh6)) | 0; + lo = (lo + Math.imul(al4, bl7)) | 0; + mid = (mid + Math.imul(al4, bh7)) | 0; + mid = (mid + Math.imul(ah4, bl7)) | 0; + hi = (hi + Math.imul(ah4, bh7)) | 0; + lo = (lo + Math.imul(al3, bl8)) | 0; + mid = (mid + Math.imul(al3, bh8)) | 0; + mid = (mid + Math.imul(ah3, bl8)) | 0; + hi = (hi + Math.imul(ah3, bh8)) | 0; + lo = (lo + Math.imul(al2, bl9)) | 0; + mid = (mid + Math.imul(al2, bh9)) | 0; + mid = (mid + Math.imul(ah2, bl9)) | 0; + hi = (hi + Math.imul(ah2, bh9)) | 0; + var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0; + w11 &= 0x3ffffff; + /* k = 12 */ + lo = Math.imul(al9, bl3); + mid = Math.imul(al9, bh3); + mid = (mid + Math.imul(ah9, bl3)) | 0; + hi = Math.imul(ah9, bh3); + lo = (lo + Math.imul(al8, bl4)) | 0; + mid = (mid + Math.imul(al8, bh4)) | 0; + mid = (mid + Math.imul(ah8, bl4)) | 0; + hi = (hi + Math.imul(ah8, bh4)) | 0; + lo = (lo + Math.imul(al7, bl5)) | 0; + mid = (mid + Math.imul(al7, bh5)) | 0; + mid = (mid + Math.imul(ah7, bl5)) | 0; + hi = (hi + Math.imul(ah7, bh5)) | 0; + lo = (lo + Math.imul(al6, bl6)) | 0; + mid = (mid + Math.imul(al6, bh6)) | 0; + mid = (mid + Math.imul(ah6, bl6)) | 0; + hi = (hi + Math.imul(ah6, bh6)) | 0; + lo = (lo + Math.imul(al5, bl7)) | 0; + mid = (mid + Math.imul(al5, bh7)) | 0; + mid = (mid + Math.imul(ah5, bl7)) | 0; + hi = (hi + Math.imul(ah5, bh7)) | 0; + lo = (lo + Math.imul(al4, bl8)) | 0; + mid = (mid + Math.imul(al4, bh8)) | 0; + mid = (mid + Math.imul(ah4, bl8)) | 0; + hi = (hi + Math.imul(ah4, bh8)) | 0; + lo = (lo + Math.imul(al3, bl9)) | 0; + mid = (mid + Math.imul(al3, bh9)) | 0; + mid = (mid + Math.imul(ah3, bl9)) | 0; + hi = (hi + Math.imul(ah3, bh9)) | 0; + var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0; + w12 &= 0x3ffffff; + /* k = 13 */ + lo = Math.imul(al9, bl4); + mid = Math.imul(al9, bh4); + mid = (mid + Math.imul(ah9, bl4)) | 0; + hi = Math.imul(ah9, bh4); + lo = (lo + Math.imul(al8, bl5)) | 0; + mid = (mid + Math.imul(al8, bh5)) | 0; + mid = (mid + Math.imul(ah8, bl5)) | 0; + hi = (hi + Math.imul(ah8, bh5)) | 0; + lo = (lo + Math.imul(al7, bl6)) | 0; + mid = (mid + Math.imul(al7, bh6)) | 0; + mid = (mid + Math.imul(ah7, bl6)) | 0; + hi = (hi + Math.imul(ah7, bh6)) | 0; + lo = (lo + Math.imul(al6, bl7)) | 0; + mid = (mid + Math.imul(al6, bh7)) | 0; + mid = (mid + Math.imul(ah6, bl7)) | 0; + hi = (hi + Math.imul(ah6, bh7)) | 0; + lo = (lo + Math.imul(al5, bl8)) | 0; + mid = (mid + Math.imul(al5, bh8)) | 0; + mid = (mid + Math.imul(ah5, bl8)) | 0; + hi = (hi + Math.imul(ah5, bh8)) | 0; + lo = (lo + Math.imul(al4, bl9)) | 0; + mid = (mid + Math.imul(al4, bh9)) | 0; + mid = (mid + Math.imul(ah4, bl9)) | 0; + hi = (hi + Math.imul(ah4, bh9)) | 0; + var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0; + w13 &= 0x3ffffff; + /* k = 14 */ + lo = Math.imul(al9, bl5); + mid = Math.imul(al9, bh5); + mid = (mid + Math.imul(ah9, bl5)) | 0; + hi = Math.imul(ah9, bh5); + lo = (lo + Math.imul(al8, bl6)) | 0; + mid = (mid + Math.imul(al8, bh6)) | 0; + mid = (mid + Math.imul(ah8, bl6)) | 0; + hi = (hi + Math.imul(ah8, bh6)) | 0; + lo = (lo + Math.imul(al7, bl7)) | 0; + mid = (mid + Math.imul(al7, bh7)) | 0; + mid = (mid + Math.imul(ah7, bl7)) | 0; + hi = (hi + Math.imul(ah7, bh7)) | 0; + lo = (lo + Math.imul(al6, bl8)) | 0; + mid = (mid + Math.imul(al6, bh8)) | 0; + mid = (mid + Math.imul(ah6, bl8)) | 0; + hi = (hi + Math.imul(ah6, bh8)) | 0; + lo = (lo + Math.imul(al5, bl9)) | 0; + mid = (mid + Math.imul(al5, bh9)) | 0; + mid = (mid + Math.imul(ah5, bl9)) | 0; + hi = (hi + Math.imul(ah5, bh9)) | 0; + var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0; + w14 &= 0x3ffffff; + /* k = 15 */ + lo = Math.imul(al9, bl6); + mid = Math.imul(al9, bh6); + mid = (mid + Math.imul(ah9, bl6)) | 0; + hi = Math.imul(ah9, bh6); + lo = (lo + Math.imul(al8, bl7)) | 0; + mid = (mid + Math.imul(al8, bh7)) | 0; + mid = (mid + Math.imul(ah8, bl7)) | 0; + hi = (hi + Math.imul(ah8, bh7)) | 0; + lo = (lo + Math.imul(al7, bl8)) | 0; + mid = (mid + Math.imul(al7, bh8)) | 0; + mid = (mid + Math.imul(ah7, bl8)) | 0; + hi = (hi + Math.imul(ah7, bh8)) | 0; + lo = (lo + Math.imul(al6, bl9)) | 0; + mid = (mid + Math.imul(al6, bh9)) | 0; + mid = (mid + Math.imul(ah6, bl9)) | 0; + hi = (hi + Math.imul(ah6, bh9)) | 0; + var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0; + w15 &= 0x3ffffff; + /* k = 16 */ + lo = Math.imul(al9, bl7); + mid = Math.imul(al9, bh7); + mid = (mid + Math.imul(ah9, bl7)) | 0; + hi = Math.imul(ah9, bh7); + lo = (lo + Math.imul(al8, bl8)) | 0; + mid = (mid + Math.imul(al8, bh8)) | 0; + mid = (mid + Math.imul(ah8, bl8)) | 0; + hi = (hi + Math.imul(ah8, bh8)) | 0; + lo = (lo + Math.imul(al7, bl9)) | 0; + mid = (mid + Math.imul(al7, bh9)) | 0; + mid = (mid + Math.imul(ah7, bl9)) | 0; + hi = (hi + Math.imul(ah7, bh9)) | 0; + var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0; + w16 &= 0x3ffffff; + /* k = 17 */ + lo = Math.imul(al9, bl8); + mid = Math.imul(al9, bh8); + mid = (mid + Math.imul(ah9, bl8)) | 0; + hi = Math.imul(ah9, bh8); + lo = (lo + Math.imul(al8, bl9)) | 0; + mid = (mid + Math.imul(al8, bh9)) | 0; + mid = (mid + Math.imul(ah8, bl9)) | 0; + hi = (hi + Math.imul(ah8, bh9)) | 0; + var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0; + w17 &= 0x3ffffff; + /* k = 18 */ + lo = Math.imul(al9, bl9); + mid = Math.imul(al9, bh9); + mid = (mid + Math.imul(ah9, bl9)) | 0; + hi = Math.imul(ah9, bh9); + var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0; + w18 &= 0x3ffffff; + o[0] = w0; + o[1] = w1; + o[2] = w2; + o[3] = w3; + o[4] = w4; + o[5] = w5; + o[6] = w6; + o[7] = w7; + o[8] = w8; + o[9] = w9; + o[10] = w10; + o[11] = w11; + o[12] = w12; + o[13] = w13; + o[14] = w14; + o[15] = w15; + o[16] = w16; + o[17] = w17; + o[18] = w18; + if (c !== 0) { + o[19] = c; + out.length++; + } + return out; + }; + + // Polyfill comb + if (!Math.imul) { + comb10MulTo = smallMulTo; + } + + function bigMulTo (self, num, out) { + out.negative = num.negative ^ self.negative; + out.length = self.length + num.length; + + var carry = 0; + var hncarry = 0; + for (var k = 0; k < out.length - 1; k++) { + // Sum all words with the same `i + j = k` and accumulate `ncarry`, + // note that ncarry could be >= 0x3ffffff + var ncarry = hncarry; + hncarry = 0; + var rword = carry & 0x3ffffff; + var maxJ = Math.min(k, num.length - 1); + for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { + var i = k - j; + var a = self.words[i] | 0; + var b = num.words[j] | 0; + var r = a * b; + + var lo = r & 0x3ffffff; + ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0; + lo = (lo + rword) | 0; + rword = lo & 0x3ffffff; + ncarry = (ncarry + (lo >>> 26)) | 0; + + hncarry += ncarry >>> 26; + ncarry &= 0x3ffffff; + } + out.words[k] = rword; + carry = ncarry; + ncarry = hncarry; + } + if (carry !== 0) { + out.words[k] = carry; + } else { + out.length--; + } + + return out.strip(); + } + + function jumboMulTo (self, num, out) { + var fftm = new FFTM(); + return fftm.mulp(self, num, out); + } + + BN.prototype.mulTo = function mulTo (num, out) { + var res; + var len = this.length + num.length; + if (this.length === 10 && num.length === 10) { + res = comb10MulTo(this, num, out); + } else if (len < 63) { + res = smallMulTo(this, num, out); + } else if (len < 1024) { + res = bigMulTo(this, num, out); + } else { + res = jumboMulTo(this, num, out); + } + + return res; + }; + + // Cooley-Tukey algorithm for FFT + // slightly revisited to rely on looping instead of recursion + + function FFTM (x, y) { + this.x = x; + this.y = y; + } + + FFTM.prototype.makeRBT = function makeRBT (N) { + var t = new Array(N); + var l = BN.prototype._countBits(N) - 1; + for (var i = 0; i < N; i++) { + t[i] = this.revBin(i, l, N); + } + + return t; + }; + + // Returns binary-reversed representation of `x` + FFTM.prototype.revBin = function revBin (x, l, N) { + if (x === 0 || x === N - 1) return x; + + var rb = 0; + for (var i = 0; i < l; i++) { + rb |= (x & 1) << (l - i - 1); + x >>= 1; + } + + return rb; + }; + + // Performs "tweedling" phase, therefore 'emulating' + // behaviour of the recursive algorithm + FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) { + for (var i = 0; i < N; i++) { + rtws[i] = rws[rbt[i]]; + itws[i] = iws[rbt[i]]; + } + }; + + FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) { + this.permute(rbt, rws, iws, rtws, itws, N); + + for (var s = 1; s < N; s <<= 1) { + var l = s << 1; + + var rtwdf = Math.cos(2 * Math.PI / l); + var itwdf = Math.sin(2 * Math.PI / l); + + for (var p = 0; p < N; p += l) { + var rtwdf_ = rtwdf; + var itwdf_ = itwdf; + + for (var j = 0; j < s; j++) { + var re = rtws[p + j]; + var ie = itws[p + j]; + + var ro = rtws[p + j + s]; + var io = itws[p + j + s]; + + var rx = rtwdf_ * ro - itwdf_ * io; + + io = rtwdf_ * io + itwdf_ * ro; + ro = rx; + + rtws[p + j] = re + ro; + itws[p + j] = ie + io; + + rtws[p + j + s] = re - ro; + itws[p + j + s] = ie - io; + + /* jshint maxdepth : false */ + if (j !== l) { + rx = rtwdf * rtwdf_ - itwdf * itwdf_; + + itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_; + rtwdf_ = rx; + } + } + } + } + }; + + FFTM.prototype.guessLen13b = function guessLen13b (n, m) { + var N = Math.max(m, n) | 1; + var odd = N & 1; + var i = 0; + for (N = N / 2 | 0; N; N = N >>> 1) { + i++; + } + + return 1 << i + 1 + odd; + }; + + FFTM.prototype.conjugate = function conjugate (rws, iws, N) { + if (N <= 1) return; + + for (var i = 0; i < N / 2; i++) { + var t = rws[i]; + + rws[i] = rws[N - i - 1]; + rws[N - i - 1] = t; + + t = iws[i]; + + iws[i] = -iws[N - i - 1]; + iws[N - i - 1] = -t; + } + }; + + FFTM.prototype.normalize13b = function normalize13b (ws, N) { + var carry = 0; + for (var i = 0; i < N / 2; i++) { + var w = Math.round(ws[2 * i + 1] / N) * 0x2000 + + Math.round(ws[2 * i] / N) + + carry; + + ws[i] = w & 0x3ffffff; + + if (w < 0x4000000) { + carry = 0; + } else { + carry = w / 0x4000000 | 0; + } + } + + return ws; + }; + + FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) { + var carry = 0; + for (var i = 0; i < len; i++) { + carry = carry + (ws[i] | 0); + + rws[2 * i] = carry & 0x1fff; carry = carry >>> 13; + rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13; + } + + // Pad with zeroes + for (i = 2 * len; i < N; ++i) { + rws[i] = 0; + } + + assert(carry === 0); + assert((carry & ~0x1fff) === 0); + }; + + FFTM.prototype.stub = function stub (N) { + var ph = new Array(N); + for (var i = 0; i < N; i++) { + ph[i] = 0; + } + + return ph; + }; + + FFTM.prototype.mulp = function mulp (x, y, out) { + var N = 2 * this.guessLen13b(x.length, y.length); + + var rbt = this.makeRBT(N); + + var _ = this.stub(N); + + var rws = new Array(N); + var rwst = new Array(N); + var iwst = new Array(N); + + var nrws = new Array(N); + var nrwst = new Array(N); + var niwst = new Array(N); + + var rmws = out.words; + rmws.length = N; + + this.convert13b(x.words, x.length, rws, N); + this.convert13b(y.words, y.length, nrws, N); + + this.transform(rws, _, rwst, iwst, N, rbt); + this.transform(nrws, _, nrwst, niwst, N, rbt); + + for (var i = 0; i < N; i++) { + var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i]; + iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i]; + rwst[i] = rx; + } + + this.conjugate(rwst, iwst, N); + this.transform(rwst, iwst, rmws, _, N, rbt); + this.conjugate(rmws, _, N); + this.normalize13b(rmws, N); + + out.negative = x.negative ^ y.negative; + out.length = x.length + y.length; + return out.strip(); + }; + + // Multiply `this` by `num` + BN.prototype.mul = function mul (num) { + var out = new BN(null); + out.words = new Array(this.length + num.length); + return this.mulTo(num, out); + }; + + // Multiply employing FFT + BN.prototype.mulf = function mulf (num) { + var out = new BN(null); + out.words = new Array(this.length + num.length); + return jumboMulTo(this, num, out); + }; + + // In-place Multiplication + BN.prototype.imul = function imul (num) { + return this.clone().mulTo(num, this); + }; + + BN.prototype.imuln = function imuln (num) { + assert(typeof num === 'number'); + assert(num < 0x4000000); + + // Carry + var carry = 0; + for (var i = 0; i < this.length; i++) { + var w = (this.words[i] | 0) * num; + var lo = (w & 0x3ffffff) + (carry & 0x3ffffff); + carry >>= 26; + carry += (w / 0x4000000) | 0; + // NOTE: lo is 27bit maximum + carry += lo >>> 26; + this.words[i] = lo & 0x3ffffff; + } + + if (carry !== 0) { + this.words[i] = carry; + this.length++; + } + + return this; + }; + + BN.prototype.muln = function muln (num) { + return this.clone().imuln(num); + }; + + // `this` * `this` + BN.prototype.sqr = function sqr () { + return this.mul(this); + }; + + // `this` * `this` in-place + BN.prototype.isqr = function isqr () { + return this.imul(this.clone()); + }; + + // Math.pow(`this`, `num`) + BN.prototype.pow = function pow (num) { + var w = toBitArray(num); + if (w.length === 0) return new BN(1); + + // Skip leading zeroes + var res = this; + for (var i = 0; i < w.length; i++, res = res.sqr()) { + if (w[i] !== 0) break; + } + + if (++i < w.length) { + for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) { + if (w[i] === 0) continue; + + res = res.mul(q); + } + } + + return res; + }; + + // Shift-left in-place + BN.prototype.iushln = function iushln (bits) { + assert(typeof bits === 'number' && bits >= 0); + var r = bits % 26; + var s = (bits - r) / 26; + var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r); + var i; + + if (r !== 0) { + var carry = 0; + + for (i = 0; i < this.length; i++) { + var newCarry = this.words[i] & carryMask; + var c = ((this.words[i] | 0) - newCarry) << r; + this.words[i] = c | carry; + carry = newCarry >>> (26 - r); + } + + if (carry) { + this.words[i] = carry; + this.length++; + } + } + + if (s !== 0) { + for (i = this.length - 1; i >= 0; i--) { + this.words[i + s] = this.words[i]; + } + + for (i = 0; i < s; i++) { + this.words[i] = 0; + } + + this.length += s; + } + + return this.strip(); + }; + + BN.prototype.ishln = function ishln (bits) { + // TODO(indutny): implement me + assert(this.negative === 0); + return this.iushln(bits); + }; + + // Shift-right in-place + // NOTE: `hint` is a lowest bit before trailing zeroes + // NOTE: if `extended` is present - it will be filled with destroyed bits + BN.prototype.iushrn = function iushrn (bits, hint, extended) { + assert(typeof bits === 'number' && bits >= 0); + var h; + if (hint) { + h = (hint - (hint % 26)) / 26; + } else { + h = 0; + } + + var r = bits % 26; + var s = Math.min((bits - r) / 26, this.length); + var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); + var maskedWords = extended; + + h -= s; + h = Math.max(0, h); + + // Extended mode, copy masked part + if (maskedWords) { + for (var i = 0; i < s; i++) { + maskedWords.words[i] = this.words[i]; + } + maskedWords.length = s; + } + + if (s === 0) ; else if (this.length > s) { + this.length -= s; + for (i = 0; i < this.length; i++) { + this.words[i] = this.words[i + s]; + } + } else { + this.words[0] = 0; + this.length = 1; + } + + var carry = 0; + for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) { + var word = this.words[i] | 0; + this.words[i] = (carry << (26 - r)) | (word >>> r); + carry = word & mask; + } + + // Push carried bits as a mask + if (maskedWords && carry !== 0) { + maskedWords.words[maskedWords.length++] = carry; + } + + if (this.length === 0) { + this.words[0] = 0; + this.length = 1; + } + + return this.strip(); + }; + + BN.prototype.ishrn = function ishrn (bits, hint, extended) { + // TODO(indutny): implement me + assert(this.negative === 0); + return this.iushrn(bits, hint, extended); + }; + + // Shift-left + BN.prototype.shln = function shln (bits) { + return this.clone().ishln(bits); + }; + + BN.prototype.ushln = function ushln (bits) { + return this.clone().iushln(bits); + }; + + // Shift-right + BN.prototype.shrn = function shrn (bits) { + return this.clone().ishrn(bits); + }; + + BN.prototype.ushrn = function ushrn (bits) { + return this.clone().iushrn(bits); + }; + + // Test if n bit is set + BN.prototype.testn = function testn (bit) { + assert(typeof bit === 'number' && bit >= 0); + var r = bit % 26; + var s = (bit - r) / 26; + var q = 1 << r; + + // Fast case: bit is much higher than all existing words + if (this.length <= s) return false; + + // Check bit and return + var w = this.words[s]; + + return !!(w & q); + }; + + // Return only lowers bits of number (in-place) + BN.prototype.imaskn = function imaskn (bits) { + assert(typeof bits === 'number' && bits >= 0); + var r = bits % 26; + var s = (bits - r) / 26; + + assert(this.negative === 0, 'imaskn works only with positive numbers'); + + if (this.length <= s) { + return this; + } + + if (r !== 0) { + s++; + } + this.length = Math.min(s, this.length); + + if (r !== 0) { + var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); + this.words[this.length - 1] &= mask; + } + + return this.strip(); + }; + + // Return only lowers bits of number + BN.prototype.maskn = function maskn (bits) { + return this.clone().imaskn(bits); + }; + + // Add plain number `num` to `this` + BN.prototype.iaddn = function iaddn (num) { + assert(typeof num === 'number'); + assert(num < 0x4000000); + if (num < 0) return this.isubn(-num); + + // Possible sign change + if (this.negative !== 0) { + if (this.length === 1 && (this.words[0] | 0) < num) { + this.words[0] = num - (this.words[0] | 0); + this.negative = 0; + return this; + } + + this.negative = 0; + this.isubn(num); + this.negative = 1; + return this; + } + + // Add without checks + return this._iaddn(num); + }; + + BN.prototype._iaddn = function _iaddn (num) { + this.words[0] += num; + + // Carry + for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) { + this.words[i] -= 0x4000000; + if (i === this.length - 1) { + this.words[i + 1] = 1; + } else { + this.words[i + 1]++; + } + } + this.length = Math.max(this.length, i + 1); + + return this; + }; + + // Subtract plain number `num` from `this` + BN.prototype.isubn = function isubn (num) { + assert(typeof num === 'number'); + assert(num < 0x4000000); + if (num < 0) return this.iaddn(-num); + + if (this.negative !== 0) { + this.negative = 0; + this.iaddn(num); + this.negative = 1; + return this; + } + + this.words[0] -= num; + + if (this.length === 1 && this.words[0] < 0) { + this.words[0] = -this.words[0]; + this.negative = 1; + } else { + // Carry + for (var i = 0; i < this.length && this.words[i] < 0; i++) { + this.words[i] += 0x4000000; + this.words[i + 1] -= 1; + } + } + + return this.strip(); + }; + + BN.prototype.addn = function addn (num) { + return this.clone().iaddn(num); + }; + + BN.prototype.subn = function subn (num) { + return this.clone().isubn(num); + }; + + BN.prototype.iabs = function iabs () { + this.negative = 0; + + return this; + }; + + BN.prototype.abs = function abs () { + return this.clone().iabs(); + }; + + BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) { + var len = num.length + shift; + var i; + + this._expand(len); + + var w; + var carry = 0; + for (i = 0; i < num.length; i++) { + w = (this.words[i + shift] | 0) + carry; + var right = (num.words[i] | 0) * mul; + w -= right & 0x3ffffff; + carry = (w >> 26) - ((right / 0x4000000) | 0); + this.words[i + shift] = w & 0x3ffffff; + } + for (; i < this.length - shift; i++) { + w = (this.words[i + shift] | 0) + carry; + carry = w >> 26; + this.words[i + shift] = w & 0x3ffffff; + } + + if (carry === 0) return this.strip(); + + // Subtraction overflow + assert(carry === -1); + carry = 0; + for (i = 0; i < this.length; i++) { + w = -(this.words[i] | 0) + carry; + carry = w >> 26; + this.words[i] = w & 0x3ffffff; + } + this.negative = 1; + + return this.strip(); + }; + + BN.prototype._wordDiv = function _wordDiv (num, mode) { + var shift = this.length - num.length; + + var a = this.clone(); + var b = num; + + // Normalize + var bhi = b.words[b.length - 1] | 0; + var bhiBits = this._countBits(bhi); + shift = 26 - bhiBits; + if (shift !== 0) { + b = b.ushln(shift); + a.iushln(shift); + bhi = b.words[b.length - 1] | 0; + } + + // Initialize quotient + var m = a.length - b.length; + var q; + + if (mode !== 'mod') { + q = new BN(null); + q.length = m + 1; + q.words = new Array(q.length); + for (var i = 0; i < q.length; i++) { + q.words[i] = 0; + } + } + + var diff = a.clone()._ishlnsubmul(b, 1, m); + if (diff.negative === 0) { + a = diff; + if (q) { + q.words[m] = 1; + } + } + + for (var j = m - 1; j >= 0; j--) { + var qj = (a.words[b.length + j] | 0) * 0x4000000 + + (a.words[b.length + j - 1] | 0); + + // NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max + // (0x7ffffff) + qj = Math.min((qj / bhi) | 0, 0x3ffffff); + + a._ishlnsubmul(b, qj, j); + while (a.negative !== 0) { + qj--; + a.negative = 0; + a._ishlnsubmul(b, 1, j); + if (!a.isZero()) { + a.negative ^= 1; + } + } + if (q) { + q.words[j] = qj; + } + } + if (q) { + q.strip(); + } + a.strip(); + + // Denormalize + if (mode !== 'div' && shift !== 0) { + a.iushrn(shift); + } + + return { + div: q || null, + mod: a + }; + }; + + // NOTE: 1) `mode` can be set to `mod` to request mod only, + // to `div` to request div only, or be absent to + // request both div & mod + // 2) `positive` is true if unsigned mod is requested + BN.prototype.divmod = function divmod (num, mode, positive) { + assert(!num.isZero()); + + if (this.isZero()) { + return { + div: new BN(0), + mod: new BN(0) + }; + } + + var div, mod, res; + if (this.negative !== 0 && num.negative === 0) { + res = this.neg().divmod(num, mode); + + if (mode !== 'mod') { + div = res.div.neg(); + } + + if (mode !== 'div') { + mod = res.mod.neg(); + if (positive && mod.negative !== 0) { + mod.iadd(num); + } + } + + return { + div: div, + mod: mod + }; + } + + if (this.negative === 0 && num.negative !== 0) { + res = this.divmod(num.neg(), mode); + + if (mode !== 'mod') { + div = res.div.neg(); + } + + return { + div: div, + mod: res.mod + }; + } + + if ((this.negative & num.negative) !== 0) { + res = this.neg().divmod(num.neg(), mode); + + if (mode !== 'div') { + mod = res.mod.neg(); + if (positive && mod.negative !== 0) { + mod.isub(num); + } + } + + return { + div: res.div, + mod: mod + }; + } + + // Both numbers are positive at this point + + // Strip both numbers to approximate shift value + if (num.length > this.length || this.cmp(num) < 0) { + return { + div: new BN(0), + mod: this + }; + } + + // Very short reduction + if (num.length === 1) { + if (mode === 'div') { + return { + div: this.divn(num.words[0]), + mod: null + }; + } + + if (mode === 'mod') { + return { + div: null, + mod: new BN(this.modn(num.words[0])) + }; + } + + return { + div: this.divn(num.words[0]), + mod: new BN(this.modn(num.words[0])) + }; + } + + return this._wordDiv(num, mode); + }; + + // Find `this` / `num` + BN.prototype.div = function div (num) { + return this.divmod(num, 'div', false).div; + }; + + // Find `this` % `num` + BN.prototype.mod = function mod (num) { + return this.divmod(num, 'mod', false).mod; + }; + + BN.prototype.umod = function umod (num) { + return this.divmod(num, 'mod', true).mod; + }; + + // Find Round(`this` / `num`) + BN.prototype.divRound = function divRound (num) { + var dm = this.divmod(num); + + // Fast case - exact division + if (dm.mod.isZero()) return dm.div; + + var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod; + + var half = num.ushrn(1); + var r2 = num.andln(1); + var cmp = mod.cmp(half); + + // Round down + if (cmp < 0 || r2 === 1 && cmp === 0) return dm.div; + + // Round up + return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1); + }; + + BN.prototype.modn = function modn (num) { + assert(num <= 0x3ffffff); + var p = (1 << 26) % num; + + var acc = 0; + for (var i = this.length - 1; i >= 0; i--) { + acc = (p * acc + (this.words[i] | 0)) % num; + } + + return acc; + }; + + // In-place division by number + BN.prototype.idivn = function idivn (num) { + assert(num <= 0x3ffffff); + + var carry = 0; + for (var i = this.length - 1; i >= 0; i--) { + var w = (this.words[i] | 0) + carry * 0x4000000; + this.words[i] = (w / num) | 0; + carry = w % num; + } + + return this.strip(); + }; + + BN.prototype.divn = function divn (num) { + return this.clone().idivn(num); + }; + + BN.prototype.egcd = function egcd (p) { + assert(p.negative === 0); + assert(!p.isZero()); + + var x = this; + var y = p.clone(); + + if (x.negative !== 0) { + x = x.umod(p); + } else { + x = x.clone(); + } + + // A * x + B * y = x + var A = new BN(1); + var B = new BN(0); + + // C * x + D * y = y + var C = new BN(0); + var D = new BN(1); + + var g = 0; + + while (x.isEven() && y.isEven()) { + x.iushrn(1); + y.iushrn(1); + ++g; + } + + var yp = y.clone(); + var xp = x.clone(); + + while (!x.isZero()) { + for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1); + if (i > 0) { + x.iushrn(i); + while (i-- > 0) { + if (A.isOdd() || B.isOdd()) { + A.iadd(yp); + B.isub(xp); + } + + A.iushrn(1); + B.iushrn(1); + } + } + + for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); + if (j > 0) { + y.iushrn(j); + while (j-- > 0) { + if (C.isOdd() || D.isOdd()) { + C.iadd(yp); + D.isub(xp); + } + + C.iushrn(1); + D.iushrn(1); + } + } + + if (x.cmp(y) >= 0) { + x.isub(y); + A.isub(C); + B.isub(D); + } else { + y.isub(x); + C.isub(A); + D.isub(B); + } + } + + return { + a: C, + b: D, + gcd: y.iushln(g) + }; + }; + + // This is reduced incarnation of the binary EEA + // above, designated to invert members of the + // _prime_ fields F(p) at a maximal speed + BN.prototype._invmp = function _invmp (p) { + assert(p.negative === 0); + assert(!p.isZero()); + + var a = this; + var b = p.clone(); + + if (a.negative !== 0) { + a = a.umod(p); + } else { + a = a.clone(); + } + + var x1 = new BN(1); + var x2 = new BN(0); + + var delta = b.clone(); + + while (a.cmpn(1) > 0 && b.cmpn(1) > 0) { + for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1); + if (i > 0) { + a.iushrn(i); + while (i-- > 0) { + if (x1.isOdd()) { + x1.iadd(delta); + } + + x1.iushrn(1); + } + } + + for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); + if (j > 0) { + b.iushrn(j); + while (j-- > 0) { + if (x2.isOdd()) { + x2.iadd(delta); + } + + x2.iushrn(1); + } + } + + if (a.cmp(b) >= 0) { + a.isub(b); + x1.isub(x2); + } else { + b.isub(a); + x2.isub(x1); + } + } + + var res; + if (a.cmpn(1) === 0) { + res = x1; + } else { + res = x2; + } + + if (res.cmpn(0) < 0) { + res.iadd(p); + } + + return res; + }; + + BN.prototype.gcd = function gcd (num) { + if (this.isZero()) return num.abs(); + if (num.isZero()) return this.abs(); + + var a = this.clone(); + var b = num.clone(); + a.negative = 0; + b.negative = 0; + + // Remove common factor of two + for (var shift = 0; a.isEven() && b.isEven(); shift++) { + a.iushrn(1); + b.iushrn(1); + } + + do { + while (a.isEven()) { + a.iushrn(1); + } + while (b.isEven()) { + b.iushrn(1); + } + + var r = a.cmp(b); + if (r < 0) { + // Swap `a` and `b` to make `a` always bigger than `b` + var t = a; + a = b; + b = t; + } else if (r === 0 || b.cmpn(1) === 0) { + break; + } + + a.isub(b); + } while (true); + + return b.iushln(shift); + }; + + // Invert number in the field F(num) + BN.prototype.invm = function invm (num) { + return this.egcd(num).a.umod(num); + }; + + BN.prototype.isEven = function isEven () { + return (this.words[0] & 1) === 0; + }; + + BN.prototype.isOdd = function isOdd () { + return (this.words[0] & 1) === 1; + }; + + // And first word and num + BN.prototype.andln = function andln (num) { + return this.words[0] & num; + }; + + // Increment at the bit position in-line + BN.prototype.bincn = function bincn (bit) { + assert(typeof bit === 'number'); + var r = bit % 26; + var s = (bit - r) / 26; + var q = 1 << r; + + // Fast case: bit is much higher than all existing words + if (this.length <= s) { + this._expand(s + 1); + this.words[s] |= q; + return this; + } + + // Add bit and propagate, if needed + var carry = q; + for (var i = s; carry !== 0 && i < this.length; i++) { + var w = this.words[i] | 0; + w += carry; + carry = w >>> 26; + w &= 0x3ffffff; + this.words[i] = w; + } + if (carry !== 0) { + this.words[i] = carry; + this.length++; + } + return this; + }; + + BN.prototype.isZero = function isZero () { + return this.length === 1 && this.words[0] === 0; + }; + + BN.prototype.cmpn = function cmpn (num) { + var negative = num < 0; + + if (this.negative !== 0 && !negative) return -1; + if (this.negative === 0 && negative) return 1; + + this.strip(); + + var res; + if (this.length > 1) { + res = 1; + } else { + if (negative) { + num = -num; + } + + assert(num <= 0x3ffffff, 'Number is too big'); + + var w = this.words[0] | 0; + res = w === num ? 0 : w < num ? -1 : 1; + } + if (this.negative !== 0) return -res | 0; + return res; + }; + + // Compare two numbers and return: + // 1 - if `this` > `num` + // 0 - if `this` == `num` + // -1 - if `this` < `num` + BN.prototype.cmp = function cmp (num) { + if (this.negative !== 0 && num.negative === 0) return -1; + if (this.negative === 0 && num.negative !== 0) return 1; + + var res = this.ucmp(num); + if (this.negative !== 0) return -res | 0; + return res; + }; + + // Unsigned comparison + BN.prototype.ucmp = function ucmp (num) { + // At this point both numbers have the same sign + if (this.length > num.length) return 1; + if (this.length < num.length) return -1; + + var res = 0; + for (var i = this.length - 1; i >= 0; i--) { + var a = this.words[i] | 0; + var b = num.words[i] | 0; + + if (a === b) continue; + if (a < b) { + res = -1; + } else if (a > b) { + res = 1; + } + break; + } + return res; + }; + + BN.prototype.gtn = function gtn (num) { + return this.cmpn(num) === 1; + }; + + BN.prototype.gt = function gt (num) { + return this.cmp(num) === 1; + }; + + BN.prototype.gten = function gten (num) { + return this.cmpn(num) >= 0; + }; + + BN.prototype.gte = function gte (num) { + return this.cmp(num) >= 0; + }; + + BN.prototype.ltn = function ltn (num) { + return this.cmpn(num) === -1; + }; + + BN.prototype.lt = function lt (num) { + return this.cmp(num) === -1; + }; + + BN.prototype.lten = function lten (num) { + return this.cmpn(num) <= 0; + }; + + BN.prototype.lte = function lte (num) { + return this.cmp(num) <= 0; + }; + + BN.prototype.eqn = function eqn (num) { + return this.cmpn(num) === 0; + }; + + BN.prototype.eq = function eq (num) { + return this.cmp(num) === 0; + }; + + // + // A reduce context, could be using montgomery or something better, depending + // on the `m` itself. + // + BN.red = function red (num) { + return new Red(num); + }; + + BN.prototype.toRed = function toRed (ctx) { + assert(!this.red, 'Already a number in reduction context'); + assert(this.negative === 0, 'red works only with positives'); + return ctx.convertTo(this)._forceRed(ctx); + }; + + BN.prototype.fromRed = function fromRed () { + assert(this.red, 'fromRed works only with numbers in reduction context'); + return this.red.convertFrom(this); + }; + + BN.prototype._forceRed = function _forceRed (ctx) { + this.red = ctx; + return this; + }; + + BN.prototype.forceRed = function forceRed (ctx) { + assert(!this.red, 'Already a number in reduction context'); + return this._forceRed(ctx); + }; + + BN.prototype.redAdd = function redAdd (num) { + assert(this.red, 'redAdd works only with red numbers'); + return this.red.add(this, num); + }; + + BN.prototype.redIAdd = function redIAdd (num) { + assert(this.red, 'redIAdd works only with red numbers'); + return this.red.iadd(this, num); + }; + + BN.prototype.redSub = function redSub (num) { + assert(this.red, 'redSub works only with red numbers'); + return this.red.sub(this, num); + }; + + BN.prototype.redISub = function redISub (num) { + assert(this.red, 'redISub works only with red numbers'); + return this.red.isub(this, num); + }; + + BN.prototype.redShl = function redShl (num) { + assert(this.red, 'redShl works only with red numbers'); + return this.red.shl(this, num); + }; + + BN.prototype.redMul = function redMul (num) { + assert(this.red, 'redMul works only with red numbers'); + this.red._verify2(this, num); + return this.red.mul(this, num); + }; + + BN.prototype.redIMul = function redIMul (num) { + assert(this.red, 'redMul works only with red numbers'); + this.red._verify2(this, num); + return this.red.imul(this, num); + }; + + BN.prototype.redSqr = function redSqr () { + assert(this.red, 'redSqr works only with red numbers'); + this.red._verify1(this); + return this.red.sqr(this); + }; + + BN.prototype.redISqr = function redISqr () { + assert(this.red, 'redISqr works only with red numbers'); + this.red._verify1(this); + return this.red.isqr(this); + }; + + // Square root over p + BN.prototype.redSqrt = function redSqrt () { + assert(this.red, 'redSqrt works only with red numbers'); + this.red._verify1(this); + return this.red.sqrt(this); + }; + + BN.prototype.redInvm = function redInvm () { + assert(this.red, 'redInvm works only with red numbers'); + this.red._verify1(this); + return this.red.invm(this); + }; + + // Return negative clone of `this` % `red modulo` + BN.prototype.redNeg = function redNeg () { + assert(this.red, 'redNeg works only with red numbers'); + this.red._verify1(this); + return this.red.neg(this); + }; + + BN.prototype.redPow = function redPow (num) { + assert(this.red && !num.red, 'redPow(normalNum)'); + this.red._verify1(this); + return this.red.pow(this, num); + }; + + // Prime numbers with efficient reduction + var primes = { + k256: null, + p224: null, + p192: null, + p25519: null + }; + + // Pseudo-Mersenne prime + function MPrime (name, p) { + // P = 2 ^ N - K + this.name = name; + this.p = new BN(p, 16); + this.n = this.p.bitLength(); + this.k = new BN(1).iushln(this.n).isub(this.p); + + this.tmp = this._tmp(); + } + + MPrime.prototype._tmp = function _tmp () { + var tmp = new BN(null); + tmp.words = new Array(Math.ceil(this.n / 13)); + return tmp; + }; + + MPrime.prototype.ireduce = function ireduce (num) { + // Assumes that `num` is less than `P^2` + // num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P) + var r = num; + var rlen; + + do { + this.split(r, this.tmp); + r = this.imulK(r); + r = r.iadd(this.tmp); + rlen = r.bitLength(); + } while (rlen > this.n); + + var cmp = rlen < this.n ? -1 : r.ucmp(this.p); + if (cmp === 0) { + r.words[0] = 0; + r.length = 1; + } else if (cmp > 0) { + r.isub(this.p); + } else { + r.strip(); + } + + return r; + }; + + MPrime.prototype.split = function split (input, out) { + input.iushrn(this.n, 0, out); + }; + + MPrime.prototype.imulK = function imulK (num) { + return num.imul(this.k); + }; + + function K256 () { + MPrime.call( + this, + 'k256', + 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f'); + } + inherits(K256, MPrime); + + K256.prototype.split = function split (input, output) { + // 256 = 9 * 26 + 22 + var mask = 0x3fffff; + + var outLen = Math.min(input.length, 9); + for (var i = 0; i < outLen; i++) { + output.words[i] = input.words[i]; + } + output.length = outLen; + + if (input.length <= 9) { + input.words[0] = 0; + input.length = 1; + return; + } + + // Shift by 9 limbs + var prev = input.words[9]; + output.words[output.length++] = prev & mask; + + for (i = 10; i < input.length; i++) { + var next = input.words[i] | 0; + input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22); + prev = next; + } + prev >>>= 22; + input.words[i - 10] = prev; + if (prev === 0 && input.length > 10) { + input.length -= 10; + } else { + input.length -= 9; + } + }; + + K256.prototype.imulK = function imulK (num) { + // K = 0x1000003d1 = [ 0x40, 0x3d1 ] + num.words[num.length] = 0; + num.words[num.length + 1] = 0; + num.length += 2; + + // bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390 + var lo = 0; + for (var i = 0; i < num.length; i++) { + var w = num.words[i] | 0; + lo += w * 0x3d1; + num.words[i] = lo & 0x3ffffff; + lo = w * 0x40 + ((lo / 0x4000000) | 0); + } + + // Fast length reduction + if (num.words[num.length - 1] === 0) { + num.length--; + if (num.words[num.length - 1] === 0) { + num.length--; + } + } + return num; + }; + + function P224 () { + MPrime.call( + this, + 'p224', + 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001'); + } + inherits(P224, MPrime); + + function P192 () { + MPrime.call( + this, + 'p192', + 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff'); + } + inherits(P192, MPrime); + + function P25519 () { + // 2 ^ 255 - 19 + MPrime.call( + this, + '25519', + '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed'); + } + inherits(P25519, MPrime); + + P25519.prototype.imulK = function imulK (num) { + // K = 0x13 + var carry = 0; + for (var i = 0; i < num.length; i++) { + var hi = (num.words[i] | 0) * 0x13 + carry; + var lo = hi & 0x3ffffff; + hi >>>= 26; + + num.words[i] = lo; + carry = hi; + } + if (carry !== 0) { + num.words[num.length++] = carry; + } + return num; + }; + + // Exported mostly for testing purposes, use plain name instead + BN._prime = function prime (name) { + // Cached version of prime + if (primes[name]) return primes[name]; + + var prime; + if (name === 'k256') { + prime = new K256(); + } else if (name === 'p224') { + prime = new P224(); + } else if (name === 'p192') { + prime = new P192(); + } else if (name === 'p25519') { + prime = new P25519(); + } else { + throw new Error('Unknown prime ' + name); + } + primes[name] = prime; + + return prime; + }; + + // + // Base reduction engine + // + function Red (m) { + if (typeof m === 'string') { + var prime = BN._prime(m); + this.m = prime.p; + this.prime = prime; + } else { + assert(m.gtn(1), 'modulus must be greater than 1'); + this.m = m; + this.prime = null; + } + } + + Red.prototype._verify1 = function _verify1 (a) { + assert(a.negative === 0, 'red works only with positives'); + assert(a.red, 'red works only with red numbers'); + }; + + Red.prototype._verify2 = function _verify2 (a, b) { + assert((a.negative | b.negative) === 0, 'red works only with positives'); + assert(a.red && a.red === b.red, + 'red works only with red numbers'); + }; + + Red.prototype.imod = function imod (a) { + if (this.prime) return this.prime.ireduce(a)._forceRed(this); + return a.umod(this.m)._forceRed(this); + }; + + Red.prototype.neg = function neg (a) { + if (a.isZero()) { + return a.clone(); + } + + return this.m.sub(a)._forceRed(this); + }; + + Red.prototype.add = function add (a, b) { + this._verify2(a, b); + + var res = a.add(b); + if (res.cmp(this.m) >= 0) { + res.isub(this.m); + } + return res._forceRed(this); + }; + + Red.prototype.iadd = function iadd (a, b) { + this._verify2(a, b); + + var res = a.iadd(b); + if (res.cmp(this.m) >= 0) { + res.isub(this.m); + } + return res; + }; + + Red.prototype.sub = function sub (a, b) { + this._verify2(a, b); + + var res = a.sub(b); + if (res.cmpn(0) < 0) { + res.iadd(this.m); + } + return res._forceRed(this); + }; + + Red.prototype.isub = function isub (a, b) { + this._verify2(a, b); + + var res = a.isub(b); + if (res.cmpn(0) < 0) { + res.iadd(this.m); + } + return res; + }; + + Red.prototype.shl = function shl (a, num) { + this._verify1(a); + return this.imod(a.ushln(num)); + }; + + Red.prototype.imul = function imul (a, b) { + this._verify2(a, b); + return this.imod(a.imul(b)); + }; + + Red.prototype.mul = function mul (a, b) { + this._verify2(a, b); + return this.imod(a.mul(b)); + }; + + Red.prototype.isqr = function isqr (a) { + return this.imul(a, a.clone()); + }; + + Red.prototype.sqr = function sqr (a) { + return this.mul(a, a); + }; + + Red.prototype.sqrt = function sqrt (a) { + if (a.isZero()) return a.clone(); + + var mod3 = this.m.andln(3); + assert(mod3 % 2 === 1); + + // Fast case + if (mod3 === 3) { + var pow = this.m.add(new BN(1)).iushrn(2); + return this.pow(a, pow); + } + + // Tonelli-Shanks algorithm (Totally unoptimized and slow) + // + // Find Q and S, that Q * 2 ^ S = (P - 1) + var q = this.m.subn(1); + var s = 0; + while (!q.isZero() && q.andln(1) === 0) { + s++; + q.iushrn(1); + } + assert(!q.isZero()); + + var one = new BN(1).toRed(this); + var nOne = one.redNeg(); + + // Find quadratic non-residue + // NOTE: Max is such because of generalized Riemann hypothesis. + var lpow = this.m.subn(1).iushrn(1); + var z = this.m.bitLength(); + z = new BN(2 * z * z).toRed(this); + + while (this.pow(z, lpow).cmp(nOne) !== 0) { + z.redIAdd(nOne); + } + + var c = this.pow(z, q); + var r = this.pow(a, q.addn(1).iushrn(1)); + var t = this.pow(a, q); + var m = s; + while (t.cmp(one) !== 0) { + var tmp = t; + for (var i = 0; tmp.cmp(one) !== 0; i++) { + tmp = tmp.redSqr(); + } + assert(i < m); + var b = this.pow(c, new BN(1).iushln(m - i - 1)); + + r = r.redMul(b); + c = b.redSqr(); + t = t.redMul(c); + m = i; + } + + return r; + }; + + Red.prototype.invm = function invm (a) { + var inv = a._invmp(this.m); + if (inv.negative !== 0) { + inv.negative = 0; + return this.imod(inv).redNeg(); + } else { + return this.imod(inv); + } + }; + + Red.prototype.pow = function pow (a, num) { + if (num.isZero()) return new BN(1).toRed(this); + if (num.cmpn(1) === 0) return a.clone(); + + var windowSize = 4; + var wnd = new Array(1 << windowSize); + wnd[0] = new BN(1).toRed(this); + wnd[1] = a; + for (var i = 2; i < wnd.length; i++) { + wnd[i] = this.mul(wnd[i - 1], a); + } + + var res = wnd[0]; + var current = 0; + var currentLen = 0; + var start = num.bitLength() % 26; + if (start === 0) { + start = 26; + } + + for (i = num.length - 1; i >= 0; i--) { + var word = num.words[i]; + for (var j = start - 1; j >= 0; j--) { + var bit = (word >> j) & 1; + if (res !== wnd[0]) { + res = this.sqr(res); + } + + if (bit === 0 && current === 0) { + currentLen = 0; + continue; + } + + current <<= 1; + current |= bit; + currentLen++; + if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue; + + res = this.mul(res, wnd[current]); + currentLen = 0; + current = 0; + } + start = 26; + } + + return res; + }; + + Red.prototype.convertTo = function convertTo (num) { + var r = num.umod(this.m); + + return r === num ? r.clone() : r; + }; + + Red.prototype.convertFrom = function convertFrom (num) { + var res = num.clone(); + res.red = null; + return res; + }; + + // + // Montgomery method engine + // + + BN.mont = function mont (num) { + return new Mont(num); + }; + + function Mont (m) { + Red.call(this, m); + + this.shift = this.m.bitLength(); + if (this.shift % 26 !== 0) { + this.shift += 26 - (this.shift % 26); + } + + this.r = new BN(1).iushln(this.shift); + this.r2 = this.imod(this.r.sqr()); + this.rinv = this.r._invmp(this.m); + + this.minv = this.rinv.mul(this.r).isubn(1).div(this.m); + this.minv = this.minv.umod(this.r); + this.minv = this.r.sub(this.minv); + } + inherits(Mont, Red); + + Mont.prototype.convertTo = function convertTo (num) { + return this.imod(num.ushln(this.shift)); + }; + + Mont.prototype.convertFrom = function convertFrom (num) { + var r = this.imod(num.mul(this.rinv)); + r.red = null; + return r; + }; + + Mont.prototype.imul = function imul (a, b) { + if (a.isZero() || b.isZero()) { + a.words[0] = 0; + a.length = 1; + return a; + } + + var t = a.imul(b); + var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); + var u = t.isub(c).iushrn(this.shift); + var res = u; + + if (u.cmp(this.m) >= 0) { + res = u.isub(this.m); + } else if (u.cmpn(0) < 0) { + res = u.iadd(this.m); + } + + return res._forceRed(this); + }; + + Mont.prototype.mul = function mul (a, b) { + if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this); + + var t = a.mul(b); + var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); + var u = t.isub(c).iushrn(this.shift); + var res = u; + if (u.cmp(this.m) >= 0) { + res = u.isub(this.m); + } else if (u.cmpn(0) < 0) { + res = u.iadd(this.m); + } + + return res._forceRed(this); + }; + + Mont.prototype.invm = function invm (a) { + // (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R + var res = this.imod(a._invmp(this.m).mul(this.r2)); + return res._forceRed(this); + }; + })(module, commonjsGlobal); + }); + + var bn$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + 'default': bn, + __moduleExports: bn + }); + + /** + * @fileoverview + * BigInteger implementation of basic operations + * Wrapper of bn.js library (wwww.github.com/indutny/bn.js) + * @module biginteger/bn + * @private + */ + + /** + * @private + */ + class BigInteger$1 { + /** + * Get a BigInteger (input must be big endian for strings and arrays) + * @param {Number|String|Uint8Array} n - Value to convert + * @throws {Error} on undefined input + */ + constructor(n) { + if (n === undefined) { + throw new Error('Invalid BigInteger input'); + } + + this.value = new bn(n); + } + + clone() { + const clone = new BigInteger$1(null); + this.value.copy(clone.value); + return clone; + } + + /** + * BigInteger increment in place + */ + iinc() { + this.value.iadd(new bn(1)); + return this; + } + + /** + * BigInteger increment + * @returns {BigInteger} this + 1. + */ + inc() { + return this.clone().iinc(); + } + + /** + * BigInteger decrement in place + */ + idec() { + this.value.isub(new bn(1)); + return this; + } + + /** + * BigInteger decrement + * @returns {BigInteger} this - 1. + */ + dec() { + return this.clone().idec(); + } + + + /** + * BigInteger addition in place + * @param {BigInteger} x - Value to add + */ + iadd(x) { + this.value.iadd(x.value); + return this; + } + + /** + * BigInteger addition + * @param {BigInteger} x - Value to add + * @returns {BigInteger} this + x. + */ + add(x) { + return this.clone().iadd(x); + } + + /** + * BigInteger subtraction in place + * @param {BigInteger} x - Value to subtract + */ + isub(x) { + this.value.isub(x.value); + return this; + } + + /** + * BigInteger subtraction + * @param {BigInteger} x - Value to subtract + * @returns {BigInteger} this - x. + */ + sub(x) { + return this.clone().isub(x); + } + + /** + * BigInteger multiplication in place + * @param {BigInteger} x - Value to multiply + */ + imul(x) { + this.value.imul(x.value); + return this; + } + + /** + * BigInteger multiplication + * @param {BigInteger} x - Value to multiply + * @returns {BigInteger} this * x. + */ + mul(x) { + return this.clone().imul(x); + } + + /** + * Compute value modulo m, in place + * @param {BigInteger} m - Modulo + */ + imod(m) { + this.value = this.value.umod(m.value); + return this; + } + + /** + * Compute value modulo m + * @param {BigInteger} m - Modulo + * @returns {BigInteger} this mod m. + */ + mod(m) { + return this.clone().imod(m); + } + + /** + * Compute modular exponentiation + * Much faster than this.exp(e).mod(n) + * @param {BigInteger} e - Exponent + * @param {BigInteger} n - Modulo + * @returns {BigInteger} this ** e mod n. + */ + modExp(e, n) { + // We use either Montgomery or normal reduction context + // Montgomery requires coprime n and R (montogmery multiplier) + // bn.js picks R as power of 2, so n must be odd + const nred = n.isEven() ? bn.red(n.value) : bn.mont(n.value); + const x = this.clone(); + x.value = x.value.toRed(nred).redPow(e.value).fromRed(); + return x; + } + + /** + * Compute the inverse of this value modulo n + * Note: this and and n must be relatively prime + * @param {BigInteger} n - Modulo + * @returns {BigInteger} x such that this*x = 1 mod n + * @throws {Error} if the inverse does not exist + */ + modInv(n) { + // invm returns a wrong result if the inverse does not exist + if (!this.gcd(n).isOne()) { + throw new Error('Inverse does not exist'); + } + return new BigInteger$1(this.value.invm(n.value)); + } + + /** + * Compute greatest common divisor between this and n + * @param {BigInteger} n - Operand + * @returns {BigInteger} gcd + */ + gcd(n) { + return new BigInteger$1(this.value.gcd(n.value)); + } + + /** + * Shift this to the left by x, in place + * @param {BigInteger} x - Shift value + */ + ileftShift(x) { + this.value.ishln(x.value.toNumber()); + return this; + } + + /** + * Shift this to the left by x + * @param {BigInteger} x - Shift value + * @returns {BigInteger} this << x. + */ + leftShift(x) { + return this.clone().ileftShift(x); + } + + /** + * Shift this to the right by x, in place + * @param {BigInteger} x - Shift value + */ + irightShift(x) { + this.value.ishrn(x.value.toNumber()); + return this; + } + + /** + * Shift this to the right by x + * @param {BigInteger} x - Shift value + * @returns {BigInteger} this >> x. + */ + rightShift(x) { + return this.clone().irightShift(x); + } + + /** + * Whether this value is equal to x + * @param {BigInteger} x + * @returns {Boolean} + */ + equal(x) { + return this.value.eq(x.value); + } + + /** + * Whether this value is less than x + * @param {BigInteger} x + * @returns {Boolean} + */ + lt(x) { + return this.value.lt(x.value); + } + + /** + * Whether this value is less than or equal to x + * @param {BigInteger} x + * @returns {Boolean} + */ + lte(x) { + return this.value.lte(x.value); + } + + /** + * Whether this value is greater than x + * @param {BigInteger} x + * @returns {Boolean} + */ + gt(x) { + return this.value.gt(x.value); + } + + /** + * Whether this value is greater than or equal to x + * @param {BigInteger} x + * @returns {Boolean} + */ + gte(x) { + return this.value.gte(x.value); + } + + isZero() { + return this.value.isZero(); + } + + isOne() { + return this.value.eq(new bn(1)); + } + + isNegative() { + return this.value.isNeg(); + } + + isEven() { + return this.value.isEven(); + } + + abs() { + const res = this.clone(); + res.value = res.value.abs(); + return res; + } + + /** + * Get this value as a string + * @returns {String} this value. + */ + toString() { + return this.value.toString(); + } + + /** + * Get this value as an exact Number (max 53 bits) + * Fails if this value is too large + * @returns {Number} + */ + toNumber() { + return this.value.toNumber(); + } + + /** + * Get value of i-th bit + * @param {Number} i - Bit index + * @returns {Number} Bit value. + */ + getBit(i) { + return this.value.testn(i) ? 1 : 0; + } + + /** + * Compute bit length + * @returns {Number} Bit length. + */ + bitLength() { + return this.value.bitLength(); + } + + /** + * Compute byte length + * @returns {Number} Byte length. + */ + byteLength() { + return this.value.byteLength(); + } + + /** + * Get Uint8Array representation of this number + * @param {String} endian - Endianess of output array (defaults to 'be') + * @param {Number} length - Of output array + * @returns {Uint8Array} + */ + toUint8Array(endian = 'be', length) { + return this.value.toArrayLike(Uint8Array, endian, length); + } + } + + var bn_interface = /*#__PURE__*/Object.freeze({ + __proto__: null, + 'default': BigInteger$1 + }); + + var utils_1 = createCommonjsModule(function (module, exports) { + + var utils = exports; + + function toArray(msg, enc) { + if (Array.isArray(msg)) + return msg.slice(); + if (!msg) + return []; + var res = []; + if (typeof msg !== 'string') { + for (var i = 0; i < msg.length; i++) + res[i] = msg[i] | 0; + return res; + } + if (enc === 'hex') { + msg = msg.replace(/[^a-z0-9]+/ig, ''); + if (msg.length % 2 !== 0) + msg = '0' + msg; + for (var i = 0; i < msg.length; i += 2) + res.push(parseInt(msg[i] + msg[i + 1], 16)); + } else { + for (var i = 0; i < msg.length; i++) { + var c = msg.charCodeAt(i); + var hi = c >> 8; + var lo = c & 0xff; + if (hi) + res.push(hi, lo); + else + res.push(lo); + } + } + return res; + } + utils.toArray = toArray; + + function zero2(word) { + if (word.length === 1) + return '0' + word; + else + return word; + } + utils.zero2 = zero2; + + function toHex(msg) { + var res = ''; + for (var i = 0; i < msg.length; i++) + res += zero2(msg[i].toString(16)); + return res; + } + utils.toHex = toHex; + + utils.encode = function encode(arr, enc) { + if (enc === 'hex') + return toHex(arr); + else + return arr; + }; + }); + + var utils_1$1 = createCommonjsModule(function (module, exports) { + + var utils = exports; + + + + + utils.assert = minimalisticAssert; + utils.toArray = utils_1.toArray; + utils.zero2 = utils_1.zero2; + utils.toHex = utils_1.toHex; + utils.encode = utils_1.encode; + + // Represent num in a w-NAF form + function getNAF(num, w) { + var naf = []; + var ws = 1 << (w + 1); + var k = num.clone(); + while (k.cmpn(1) >= 0) { + var z; + if (k.isOdd()) { + var mod = k.andln(ws - 1); + if (mod > (ws >> 1) - 1) + z = (ws >> 1) - mod; + else + z = mod; + k.isubn(z); + } else { + z = 0; + } + naf.push(z); + + // Optimization, shift by word if possible + var shift = (k.cmpn(0) !== 0 && k.andln(ws - 1) === 0) ? (w + 1) : 1; + for (var i = 1; i < shift; i++) + naf.push(0); + k.iushrn(shift); + } + + return naf; + } + utils.getNAF = getNAF; + + // Represent k1, k2 in a Joint Sparse Form + function getJSF(k1, k2) { + var jsf = [ + [], + [] + ]; + + k1 = k1.clone(); + k2 = k2.clone(); + var d1 = 0; + var d2 = 0; + while (k1.cmpn(-d1) > 0 || k2.cmpn(-d2) > 0) { + + // First phase + var m14 = (k1.andln(3) + d1) & 3; + var m24 = (k2.andln(3) + d2) & 3; + if (m14 === 3) + m14 = -1; + if (m24 === 3) + m24 = -1; + var u1; + if ((m14 & 1) === 0) { + u1 = 0; + } else { + var m8 = (k1.andln(7) + d1) & 7; + if ((m8 === 3 || m8 === 5) && m24 === 2) + u1 = -m14; + else + u1 = m14; + } + jsf[0].push(u1); + + var u2; + if ((m24 & 1) === 0) { + u2 = 0; + } else { + var m8 = (k2.andln(7) + d2) & 7; + if ((m8 === 3 || m8 === 5) && m14 === 2) + u2 = -m24; + else + u2 = m24; + } + jsf[1].push(u2); + + // Second phase + if (2 * d1 === u1 + 1) + d1 = 1 - d1; + if (2 * d2 === u2 + 1) + d2 = 1 - d2; + k1.iushrn(1); + k2.iushrn(1); + } + + return jsf; + } + utils.getJSF = getJSF; + + function cachedProperty(obj, name, computer) { + var key = '_' + name; + obj.prototype[name] = function cachedProperty() { + return this[key] !== undefined ? this[key] : + this[key] = computer.call(this); + }; + } + utils.cachedProperty = cachedProperty; + + function parseBytes(bytes) { + return typeof bytes === 'string' ? utils.toArray(bytes, 'hex') : + bytes; + } + utils.parseBytes = parseBytes; + + function intFromLE(bytes) { + return new bn(bytes, 'hex', 'le'); + } + utils.intFromLE = intFromLE; + }); + + var r$1; + + var brorand = function rand(len) { + if (!r$1) + r$1 = new Rand(null); + + return r$1.generate(len); + }; + + function Rand(rand) { + this.rand = rand; + } + var Rand_1 = Rand; + + Rand.prototype.generate = function generate(len) { + return this._rand(len); + }; + + // Emulate crypto API using randy + Rand.prototype._rand = function _rand(n) { + if (this.rand.getBytes) + return this.rand.getBytes(n); + + var res = new Uint8Array(n); + for (var i = 0; i < res.length; i++) + res[i] = this.rand.getByte(); + return res; + }; + + if (typeof self === 'object') { + if (self.crypto && self.crypto.getRandomValues) { + // Modern browsers + Rand.prototype._rand = function _rand(n) { + var arr = new Uint8Array(n); + self.crypto.getRandomValues(arr); + return arr; + }; + } else if (self.msCrypto && self.msCrypto.getRandomValues) { + // IE + Rand.prototype._rand = function _rand(n) { + var arr = new Uint8Array(n); + self.msCrypto.getRandomValues(arr); + return arr; + }; + + // Safari's WebWorkers do not have `crypto` + } else if (typeof window === 'object') { + // Old junk + Rand.prototype._rand = function() { + throw new Error('Not implemented yet'); + }; + } + } else { + // Node.js or Web worker with no crypto support + try { + var crypto$2 = void('crypto'); + if (typeof crypto$2.randomBytes !== 'function') + throw new Error('Not supported'); + + Rand.prototype._rand = function _rand(n) { + return crypto$2.randomBytes(n); + }; + } catch (e) { + } + } + brorand.Rand = Rand_1; + + var getNAF = utils_1$1.getNAF; + var getJSF = utils_1$1.getJSF; + var assert$2 = utils_1$1.assert; + + function BaseCurve(type, conf) { + this.type = type; + this.p = new bn(conf.p, 16); + + // Use Montgomery, when there is no fast reduction for the prime + this.red = conf.prime ? bn.red(conf.prime) : bn.mont(this.p); + + // Useful for many curves + this.zero = new bn(0).toRed(this.red); + this.one = new bn(1).toRed(this.red); + this.two = new bn(2).toRed(this.red); + + // Curve configuration, optional + this.n = conf.n && new bn(conf.n, 16); + this.g = conf.g && this.pointFromJSON(conf.g, conf.gRed); + + // Temporary arrays + this._wnafT1 = new Array(4); + this._wnafT2 = new Array(4); + this._wnafT3 = new Array(4); + this._wnafT4 = new Array(4); + + // Generalized Greg Maxwell's trick + var adjustCount = this.n && this.p.div(this.n); + if (!adjustCount || adjustCount.cmpn(100) > 0) { + this.redN = null; + } else { + this._maxwellTrick = true; + this.redN = this.n.toRed(this.red); + } + } + var base = BaseCurve; + + BaseCurve.prototype.point = function point() { + throw new Error('Not implemented'); + }; + + BaseCurve.prototype.validate = function validate() { + throw new Error('Not implemented'); + }; + + BaseCurve.prototype._fixedNafMul = function _fixedNafMul(p, k) { + assert$2(p.precomputed); + var doubles = p._getDoubles(); + + var naf = getNAF(k, 1); + var I = (1 << (doubles.step + 1)) - (doubles.step % 2 === 0 ? 2 : 1); + I /= 3; + + // Translate into more windowed form + var repr = []; + for (var j = 0; j < naf.length; j += doubles.step) { + var nafW = 0; + for (var k = j + doubles.step - 1; k >= j; k--) + nafW = (nafW << 1) + naf[k]; + repr.push(nafW); + } + + var a = this.jpoint(null, null, null); + var b = this.jpoint(null, null, null); + for (var i = I; i > 0; i--) { + for (var j = 0; j < repr.length; j++) { + var nafW = repr[j]; + if (nafW === i) + b = b.mixedAdd(doubles.points[j]); + else if (nafW === -i) + b = b.mixedAdd(doubles.points[j].neg()); + } + a = a.add(b); + } + return a.toP(); + }; + + BaseCurve.prototype._wnafMul = function _wnafMul(p, k) { + var w = 4; + + // Precompute window + var nafPoints = p._getNAFPoints(w); + w = nafPoints.wnd; + var wnd = nafPoints.points; + + // Get NAF form + var naf = getNAF(k, w); + + // Add `this`*(N+1) for every w-NAF index + var acc = this.jpoint(null, null, null); + for (var i = naf.length - 1; i >= 0; i--) { + // Count zeroes + for (var k = 0; i >= 0 && naf[i] === 0; i--) + k++; + if (i >= 0) + k++; + acc = acc.dblp(k); + + if (i < 0) + break; + var z = naf[i]; + assert$2(z !== 0); + if (p.type === 'affine') { + // J +- P + if (z > 0) + acc = acc.mixedAdd(wnd[(z - 1) >> 1]); + else + acc = acc.mixedAdd(wnd[(-z - 1) >> 1].neg()); + } else { + // J +- J + if (z > 0) + acc = acc.add(wnd[(z - 1) >> 1]); + else + acc = acc.add(wnd[(-z - 1) >> 1].neg()); + } + } + return p.type === 'affine' ? acc.toP() : acc; + }; + + BaseCurve.prototype._wnafMulAdd = function _wnafMulAdd(defW, + points, + coeffs, + len, + jacobianResult) { + var wndWidth = this._wnafT1; + var wnd = this._wnafT2; + var naf = this._wnafT3; + + // Fill all arrays + var max = 0; + for (var i = 0; i < len; i++) { + var p = points[i]; + var nafPoints = p._getNAFPoints(defW); + wndWidth[i] = nafPoints.wnd; + wnd[i] = nafPoints.points; + } + + // Comb small window NAFs + for (var i = len - 1; i >= 1; i -= 2) { + var a = i - 1; + var b = i; + if (wndWidth[a] !== 1 || wndWidth[b] !== 1) { + naf[a] = getNAF(coeffs[a], wndWidth[a]); + naf[b] = getNAF(coeffs[b], wndWidth[b]); + max = Math.max(naf[a].length, max); + max = Math.max(naf[b].length, max); + continue; + } + + var comb = [ + points[a], /* 1 */ + null, /* 3 */ + null, /* 5 */ + points[b] /* 7 */ + ]; + + // Try to avoid Projective points, if possible + if (points[a].y.cmp(points[b].y) === 0) { + comb[1] = points[a].add(points[b]); + comb[2] = points[a].toJ().mixedAdd(points[b].neg()); + } else if (points[a].y.cmp(points[b].y.redNeg()) === 0) { + comb[1] = points[a].toJ().mixedAdd(points[b]); + comb[2] = points[a].add(points[b].neg()); + } else { + comb[1] = points[a].toJ().mixedAdd(points[b]); + comb[2] = points[a].toJ().mixedAdd(points[b].neg()); + } + + var index = [ + -3, /* -1 -1 */ + -1, /* -1 0 */ + -5, /* -1 1 */ + -7, /* 0 -1 */ + 0, /* 0 0 */ + 7, /* 0 1 */ + 5, /* 1 -1 */ + 1, /* 1 0 */ + 3 /* 1 1 */ + ]; + + var jsf = getJSF(coeffs[a], coeffs[b]); + max = Math.max(jsf[0].length, max); + naf[a] = new Array(max); + naf[b] = new Array(max); + for (var j = 0; j < max; j++) { + var ja = jsf[0][j] | 0; + var jb = jsf[1][j] | 0; + + naf[a][j] = index[(ja + 1) * 3 + (jb + 1)]; + naf[b][j] = 0; + wnd[a] = comb; + } + } + + var acc = this.jpoint(null, null, null); + var tmp = this._wnafT4; + for (var i = max; i >= 0; i--) { + var k = 0; + + while (i >= 0) { + var zero = true; + for (var j = 0; j < len; j++) { + tmp[j] = naf[j][i] | 0; + if (tmp[j] !== 0) + zero = false; + } + if (!zero) + break; + k++; + i--; + } + if (i >= 0) + k++; + acc = acc.dblp(k); + if (i < 0) + break; + + for (var j = 0; j < len; j++) { + var z = tmp[j]; + var p; + if (z === 0) + continue; + else if (z > 0) + p = wnd[j][(z - 1) >> 1]; + else if (z < 0) + p = wnd[j][(-z - 1) >> 1].neg(); + + if (p.type === 'affine') + acc = acc.mixedAdd(p); + else + acc = acc.add(p); + } + } + // Zeroify references + for (var i = 0; i < len; i++) + wnd[i] = null; + + if (jacobianResult) + return acc; + else + return acc.toP(); + }; + + function BasePoint(curve, type) { + this.curve = curve; + this.type = type; + this.precomputed = null; + } + BaseCurve.BasePoint = BasePoint; + + BasePoint.prototype.eq = function eq(/*other*/) { + throw new Error('Not implemented'); + }; + + BasePoint.prototype.validate = function validate() { + return this.curve.validate(this); + }; + + BaseCurve.prototype.decodePoint = function decodePoint(bytes, enc) { + bytes = utils_1$1.toArray(bytes, enc); + + var len = this.p.byteLength(); + + // uncompressed, hybrid-odd, hybrid-even + if ((bytes[0] === 0x04 || bytes[0] === 0x06 || bytes[0] === 0x07) && + bytes.length - 1 === 2 * len) { + if (bytes[0] === 0x06) + assert$2(bytes[bytes.length - 1] % 2 === 0); + else if (bytes[0] === 0x07) + assert$2(bytes[bytes.length - 1] % 2 === 1); + + var res = this.point(bytes.slice(1, 1 + len), + bytes.slice(1 + len, 1 + 2 * len)); + + return res; + } else if ((bytes[0] === 0x02 || bytes[0] === 0x03) && + bytes.length - 1 === len) { + return this.pointFromX(bytes.slice(1, 1 + len), bytes[0] === 0x03); + } + throw new Error('Unknown point format'); + }; + + BasePoint.prototype.encodeCompressed = function encodeCompressed(enc) { + return this.encode(enc, true); + }; + + BasePoint.prototype._encode = function _encode(compact) { + var len = this.curve.p.byteLength(); + var x = this.getX().toArray('be', len); + + if (compact) + return [ this.getY().isEven() ? 0x02 : 0x03 ].concat(x); + + return [ 0x04 ].concat(x, this.getY().toArray('be', len)) ; + }; + + BasePoint.prototype.encode = function encode(enc, compact) { + return utils_1$1.encode(this._encode(compact), enc); + }; + + BasePoint.prototype.precompute = function precompute(power) { + if (this.precomputed) + return this; + + var precomputed = { + doubles: null, + naf: null, + beta: null + }; + precomputed.naf = this._getNAFPoints(8); + precomputed.doubles = this._getDoubles(4, power); + precomputed.beta = this._getBeta(); + this.precomputed = precomputed; + + return this; + }; + + BasePoint.prototype._hasDoubles = function _hasDoubles(k) { + if (!this.precomputed) + return false; + + var doubles = this.precomputed.doubles; + if (!doubles) + return false; + + return doubles.points.length >= Math.ceil((k.bitLength() + 1) / doubles.step); + }; + + BasePoint.prototype._getDoubles = function _getDoubles(step, power) { + if (this.precomputed && this.precomputed.doubles) + return this.precomputed.doubles; + + var doubles = [ this ]; + var acc = this; + for (var i = 0; i < power; i += step) { + for (var j = 0; j < step; j++) + acc = acc.dbl(); + doubles.push(acc); + } + return { + step: step, + points: doubles + }; + }; + + BasePoint.prototype._getNAFPoints = function _getNAFPoints(wnd) { + if (this.precomputed && this.precomputed.naf) + return this.precomputed.naf; + + var res = [ this ]; + var max = (1 << wnd) - 1; + var dbl = max === 1 ? null : this.dbl(); + for (var i = 1; i < max; i++) + res[i] = res[i - 1].add(dbl); + return { + wnd: wnd, + points: res + }; + }; + + BasePoint.prototype._getBeta = function _getBeta() { + return null; + }; + + BasePoint.prototype.dblp = function dblp(k) { + var r = this; + for (var i = 0; i < k; i++) + r = r.dbl(); + return r; + }; + + var assert$3 = utils_1$1.assert; + + function ShortCurve(conf) { + base.call(this, 'short', conf); + + this.a = new bn(conf.a, 16).toRed(this.red); + this.b = new bn(conf.b, 16).toRed(this.red); + this.tinv = this.two.redInvm(); + + this.zeroA = this.a.fromRed().cmpn(0) === 0; + this.threeA = this.a.fromRed().sub(this.p).cmpn(-3) === 0; + + // If the curve is endomorphic, precalculate beta and lambda + this.endo = this._getEndomorphism(conf); + this._endoWnafT1 = new Array(4); + this._endoWnafT2 = new Array(4); + } + inherits_browser(ShortCurve, base); + var short_1 = ShortCurve; + + ShortCurve.prototype._getEndomorphism = function _getEndomorphism(conf) { + // No efficient endomorphism + if (!this.zeroA || !this.g || !this.n || this.p.modn(3) !== 1) + return; + + // Compute beta and lambda, that lambda * P = (beta * Px; Py) + var beta; + var lambda; + if (conf.beta) { + beta = new bn(conf.beta, 16).toRed(this.red); + } else { + var betas = this._getEndoRoots(this.p); + // Choose the smallest beta + beta = betas[0].cmp(betas[1]) < 0 ? betas[0] : betas[1]; + beta = beta.toRed(this.red); + } + if (conf.lambda) { + lambda = new bn(conf.lambda, 16); + } else { + // Choose the lambda that is matching selected beta + var lambdas = this._getEndoRoots(this.n); + if (this.g.mul(lambdas[0]).x.cmp(this.g.x.redMul(beta)) === 0) { + lambda = lambdas[0]; + } else { + lambda = lambdas[1]; + assert$3(this.g.mul(lambda).x.cmp(this.g.x.redMul(beta)) === 0); + } + } + + // Get basis vectors, used for balanced length-two representation + var basis; + if (conf.basis) { + basis = conf.basis.map(function(vec) { + return { + a: new bn(vec.a, 16), + b: new bn(vec.b, 16) + }; + }); + } else { + basis = this._getEndoBasis(lambda); + } + + return { + beta: beta, + lambda: lambda, + basis: basis + }; + }; + + ShortCurve.prototype._getEndoRoots = function _getEndoRoots(num) { + // Find roots of for x^2 + x + 1 in F + // Root = (-1 +- Sqrt(-3)) / 2 + // + var red = num === this.p ? this.red : bn.mont(num); + var tinv = new bn(2).toRed(red).redInvm(); + var ntinv = tinv.redNeg(); + + var s = new bn(3).toRed(red).redNeg().redSqrt().redMul(tinv); + + var l1 = ntinv.redAdd(s).fromRed(); + var l2 = ntinv.redSub(s).fromRed(); + return [ l1, l2 ]; + }; + + ShortCurve.prototype._getEndoBasis = function _getEndoBasis(lambda) { + // aprxSqrt >= sqrt(this.n) + var aprxSqrt = this.n.ushrn(Math.floor(this.n.bitLength() / 2)); + + // 3.74 + // Run EGCD, until r(L + 1) < aprxSqrt + var u = lambda; + var v = this.n.clone(); + var x1 = new bn(1); + var y1 = new bn(0); + var x2 = new bn(0); + var y2 = new bn(1); + + // NOTE: all vectors are roots of: a + b * lambda = 0 (mod n) + var a0; + var b0; + // First vector + var a1; + var b1; + // Second vector + var a2; + var b2; + + var prevR; + var i = 0; + var r; + var x; + while (u.cmpn(0) !== 0) { + var q = v.div(u); + r = v.sub(q.mul(u)); + x = x2.sub(q.mul(x1)); + var y = y2.sub(q.mul(y1)); + + if (!a1 && r.cmp(aprxSqrt) < 0) { + a0 = prevR.neg(); + b0 = x1; + a1 = r.neg(); + b1 = x; + } else if (a1 && ++i === 2) { + break; + } + prevR = r; + + v = u; + u = r; + x2 = x1; + x1 = x; + y2 = y1; + y1 = y; + } + a2 = r.neg(); + b2 = x; + + var len1 = a1.sqr().add(b1.sqr()); + var len2 = a2.sqr().add(b2.sqr()); + if (len2.cmp(len1) >= 0) { + a2 = a0; + b2 = b0; + } + + // Normalize signs + if (a1.negative) { + a1 = a1.neg(); + b1 = b1.neg(); + } + if (a2.negative) { + a2 = a2.neg(); + b2 = b2.neg(); + } + + return [ + { a: a1, b: b1 }, + { a: a2, b: b2 } + ]; + }; + + ShortCurve.prototype._endoSplit = function _endoSplit(k) { + var basis = this.endo.basis; + var v1 = basis[0]; + var v2 = basis[1]; + + var c1 = v2.b.mul(k).divRound(this.n); + var c2 = v1.b.neg().mul(k).divRound(this.n); + + var p1 = c1.mul(v1.a); + var p2 = c2.mul(v2.a); + var q1 = c1.mul(v1.b); + var q2 = c2.mul(v2.b); + + // Calculate answer + var k1 = k.sub(p1).sub(p2); + var k2 = q1.add(q2).neg(); + return { k1: k1, k2: k2 }; + }; + + ShortCurve.prototype.pointFromX = function pointFromX(x, odd) { + x = new bn(x, 16); + if (!x.red) + x = x.toRed(this.red); + + var y2 = x.redSqr().redMul(x).redIAdd(x.redMul(this.a)).redIAdd(this.b); + var y = y2.redSqrt(); + if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) + throw new Error('invalid point'); + + // XXX Is there any way to tell if the number is odd without converting it + // to non-red form? + var isOdd = y.fromRed().isOdd(); + if (odd && !isOdd || !odd && isOdd) + y = y.redNeg(); + + return this.point(x, y); + }; + + ShortCurve.prototype.validate = function validate(point) { + if (point.inf) + return true; + + var x = point.x; + var y = point.y; + + var ax = this.a.redMul(x); + var rhs = x.redSqr().redMul(x).redIAdd(ax).redIAdd(this.b); + return y.redSqr().redISub(rhs).cmpn(0) === 0; + }; + + ShortCurve.prototype._endoWnafMulAdd = + function _endoWnafMulAdd(points, coeffs, jacobianResult) { + var npoints = this._endoWnafT1; + var ncoeffs = this._endoWnafT2; + for (var i = 0; i < points.length; i++) { + var split = this._endoSplit(coeffs[i]); + var p = points[i]; + var beta = p._getBeta(); + + if (split.k1.negative) { + split.k1.ineg(); + p = p.neg(true); + } + if (split.k2.negative) { + split.k2.ineg(); + beta = beta.neg(true); + } + + npoints[i * 2] = p; + npoints[i * 2 + 1] = beta; + ncoeffs[i * 2] = split.k1; + ncoeffs[i * 2 + 1] = split.k2; + } + var res = this._wnafMulAdd(1, npoints, ncoeffs, i * 2, jacobianResult); + + // Clean-up references to points and coefficients + for (var j = 0; j < i * 2; j++) { + npoints[j] = null; + ncoeffs[j] = null; + } + return res; + }; + + function Point(curve, x, y, isRed) { + base.BasePoint.call(this, curve, 'affine'); + if (x === null && y === null) { + this.x = null; + this.y = null; + this.inf = true; + } else { + this.x = new bn(x, 16); + this.y = new bn(y, 16); + // Force redgomery representation when loading from JSON + if (isRed) { + this.x.forceRed(this.curve.red); + this.y.forceRed(this.curve.red); + } + if (!this.x.red) + this.x = this.x.toRed(this.curve.red); + if (!this.y.red) + this.y = this.y.toRed(this.curve.red); + this.inf = false; + } + } + inherits_browser(Point, base.BasePoint); + + ShortCurve.prototype.point = function point(x, y, isRed) { + return new Point(this, x, y, isRed); + }; + + ShortCurve.prototype.pointFromJSON = function pointFromJSON(obj, red) { + return Point.fromJSON(this, obj, red); + }; + + Point.prototype._getBeta = function _getBeta() { + if (!this.curve.endo) + return; + + var pre = this.precomputed; + if (pre && pre.beta) + return pre.beta; + + var beta = this.curve.point(this.x.redMul(this.curve.endo.beta), this.y); + if (pre) { + var curve = this.curve; + var endoMul = function(p) { + return curve.point(p.x.redMul(curve.endo.beta), p.y); + }; + pre.beta = beta; + beta.precomputed = { + beta: null, + naf: pre.naf && { + wnd: pre.naf.wnd, + points: pre.naf.points.map(endoMul) + }, + doubles: pre.doubles && { + step: pre.doubles.step, + points: pre.doubles.points.map(endoMul) + } + }; + } + return beta; + }; + + Point.prototype.toJSON = function toJSON() { + if (!this.precomputed) + return [ this.x, this.y ]; + + return [ this.x, this.y, this.precomputed && { + doubles: this.precomputed.doubles && { + step: this.precomputed.doubles.step, + points: this.precomputed.doubles.points.slice(1) + }, + naf: this.precomputed.naf && { + wnd: this.precomputed.naf.wnd, + points: this.precomputed.naf.points.slice(1) + } + } ]; + }; + + Point.fromJSON = function fromJSON(curve, obj, red) { + if (typeof obj === 'string') + obj = JSON.parse(obj); + var res = curve.point(obj[0], obj[1], red); + if (!obj[2]) + return res; + + function obj2point(obj) { + return curve.point(obj[0], obj[1], red); + } + + var pre = obj[2]; + res.precomputed = { + beta: null, + doubles: pre.doubles && { + step: pre.doubles.step, + points: [ res ].concat(pre.doubles.points.map(obj2point)) + }, + naf: pre.naf && { + wnd: pre.naf.wnd, + points: [ res ].concat(pre.naf.points.map(obj2point)) + } + }; + return res; + }; + + Point.prototype.inspect = function inspect() { + if (this.isInfinity()) + return ''; + return ''; + }; + + Point.prototype.isInfinity = function isInfinity() { + return this.inf; + }; + + Point.prototype.add = function add(p) { + // O + P = P + if (this.inf) + return p; + + // P + O = P + if (p.inf) + return this; + + // P + P = 2P + if (this.eq(p)) + return this.dbl(); + + // P + (-P) = O + if (this.neg().eq(p)) + return this.curve.point(null, null); + + // P + Q = O + if (this.x.cmp(p.x) === 0) + return this.curve.point(null, null); + + var c = this.y.redSub(p.y); + if (c.cmpn(0) !== 0) + c = c.redMul(this.x.redSub(p.x).redInvm()); + var nx = c.redSqr().redISub(this.x).redISub(p.x); + var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); + return this.curve.point(nx, ny); + }; + + Point.prototype.dbl = function dbl() { + if (this.inf) + return this; + + // 2P = O + var ys1 = this.y.redAdd(this.y); + if (ys1.cmpn(0) === 0) + return this.curve.point(null, null); + + var a = this.curve.a; + + var x2 = this.x.redSqr(); + var dyinv = ys1.redInvm(); + var c = x2.redAdd(x2).redIAdd(x2).redIAdd(a).redMul(dyinv); + + var nx = c.redSqr().redISub(this.x.redAdd(this.x)); + var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); + return this.curve.point(nx, ny); + }; + + Point.prototype.getX = function getX() { + return this.x.fromRed(); + }; + + Point.prototype.getY = function getY() { + return this.y.fromRed(); + }; + + Point.prototype.mul = function mul(k) { + k = new bn(k, 16); + if (this.isInfinity()) + return this; + else if (this._hasDoubles(k)) + return this.curve._fixedNafMul(this, k); + else if (this.curve.endo) + return this.curve._endoWnafMulAdd([ this ], [ k ]); + else + return this.curve._wnafMul(this, k); + }; + + Point.prototype.mulAdd = function mulAdd(k1, p2, k2) { + var points = [ this, p2 ]; + var coeffs = [ k1, k2 ]; + if (this.curve.endo) + return this.curve._endoWnafMulAdd(points, coeffs); + else + return this.curve._wnafMulAdd(1, points, coeffs, 2); + }; + + Point.prototype.jmulAdd = function jmulAdd(k1, p2, k2) { + var points = [ this, p2 ]; + var coeffs = [ k1, k2 ]; + if (this.curve.endo) + return this.curve._endoWnafMulAdd(points, coeffs, true); + else + return this.curve._wnafMulAdd(1, points, coeffs, 2, true); + }; + + Point.prototype.eq = function eq(p) { + return this === p || + this.inf === p.inf && + (this.inf || this.x.cmp(p.x) === 0 && this.y.cmp(p.y) === 0); + }; + + Point.prototype.neg = function neg(_precompute) { + if (this.inf) + return this; + + var res = this.curve.point(this.x, this.y.redNeg()); + if (_precompute && this.precomputed) { + var pre = this.precomputed; + var negate = function(p) { + return p.neg(); + }; + res.precomputed = { + naf: pre.naf && { + wnd: pre.naf.wnd, + points: pre.naf.points.map(negate) + }, + doubles: pre.doubles && { + step: pre.doubles.step, + points: pre.doubles.points.map(negate) + } + }; + } + return res; + }; + + Point.prototype.toJ = function toJ() { + if (this.inf) + return this.curve.jpoint(null, null, null); + + var res = this.curve.jpoint(this.x, this.y, this.curve.one); + return res; + }; + + function JPoint(curve, x, y, z) { + base.BasePoint.call(this, curve, 'jacobian'); + if (x === null && y === null && z === null) { + this.x = this.curve.one; + this.y = this.curve.one; + this.z = new bn(0); + } else { + this.x = new bn(x, 16); + this.y = new bn(y, 16); + this.z = new bn(z, 16); + } + if (!this.x.red) + this.x = this.x.toRed(this.curve.red); + if (!this.y.red) + this.y = this.y.toRed(this.curve.red); + if (!this.z.red) + this.z = this.z.toRed(this.curve.red); + + this.zOne = this.z === this.curve.one; + } + inherits_browser(JPoint, base.BasePoint); + + ShortCurve.prototype.jpoint = function jpoint(x, y, z) { + return new JPoint(this, x, y, z); + }; + + JPoint.prototype.toP = function toP() { + if (this.isInfinity()) + return this.curve.point(null, null); + + var zinv = this.z.redInvm(); + var zinv2 = zinv.redSqr(); + var ax = this.x.redMul(zinv2); + var ay = this.y.redMul(zinv2).redMul(zinv); + + return this.curve.point(ax, ay); + }; + + JPoint.prototype.neg = function neg() { + return this.curve.jpoint(this.x, this.y.redNeg(), this.z); + }; + + JPoint.prototype.add = function add(p) { + // O + P = P + if (this.isInfinity()) + return p; + + // P + O = P + if (p.isInfinity()) + return this; + + // 12M + 4S + 7A + var pz2 = p.z.redSqr(); + var z2 = this.z.redSqr(); + var u1 = this.x.redMul(pz2); + var u2 = p.x.redMul(z2); + var s1 = this.y.redMul(pz2.redMul(p.z)); + var s2 = p.y.redMul(z2.redMul(this.z)); + + var h = u1.redSub(u2); + var r = s1.redSub(s2); + if (h.cmpn(0) === 0) { + if (r.cmpn(0) !== 0) + return this.curve.jpoint(null, null, null); + else + return this.dbl(); + } + + var h2 = h.redSqr(); + var h3 = h2.redMul(h); + var v = u1.redMul(h2); + + var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); + var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); + var nz = this.z.redMul(p.z).redMul(h); + + return this.curve.jpoint(nx, ny, nz); + }; + + JPoint.prototype.mixedAdd = function mixedAdd(p) { + // O + P = P + if (this.isInfinity()) + return p.toJ(); + + // P + O = P + if (p.isInfinity()) + return this; + + // 8M + 3S + 7A + var z2 = this.z.redSqr(); + var u1 = this.x; + var u2 = p.x.redMul(z2); + var s1 = this.y; + var s2 = p.y.redMul(z2).redMul(this.z); + + var h = u1.redSub(u2); + var r = s1.redSub(s2); + if (h.cmpn(0) === 0) { + if (r.cmpn(0) !== 0) + return this.curve.jpoint(null, null, null); + else + return this.dbl(); + } + + var h2 = h.redSqr(); + var h3 = h2.redMul(h); + var v = u1.redMul(h2); + + var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); + var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); + var nz = this.z.redMul(h); + + return this.curve.jpoint(nx, ny, nz); + }; + + JPoint.prototype.dblp = function dblp(pow) { + if (pow === 0) + return this; + if (this.isInfinity()) + return this; + if (!pow) + return this.dbl(); + + if (this.curve.zeroA || this.curve.threeA) { + var r = this; + for (var i = 0; i < pow; i++) + r = r.dbl(); + return r; + } + + // 1M + 2S + 1A + N * (4S + 5M + 8A) + // N = 1 => 6M + 6S + 9A + var a = this.curve.a; + var tinv = this.curve.tinv; + + var jx = this.x; + var jy = this.y; + var jz = this.z; + var jz4 = jz.redSqr().redSqr(); + + // Reuse results + var jyd = jy.redAdd(jy); + for (var i = 0; i < pow; i++) { + var jx2 = jx.redSqr(); + var jyd2 = jyd.redSqr(); + var jyd4 = jyd2.redSqr(); + var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); + + var t1 = jx.redMul(jyd2); + var nx = c.redSqr().redISub(t1.redAdd(t1)); + var t2 = t1.redISub(nx); + var dny = c.redMul(t2); + dny = dny.redIAdd(dny).redISub(jyd4); + var nz = jyd.redMul(jz); + if (i + 1 < pow) + jz4 = jz4.redMul(jyd4); + + jx = nx; + jz = nz; + jyd = dny; + } + + return this.curve.jpoint(jx, jyd.redMul(tinv), jz); + }; + + JPoint.prototype.dbl = function dbl() { + if (this.isInfinity()) + return this; + + if (this.curve.zeroA) + return this._zeroDbl(); + else if (this.curve.threeA) + return this._threeDbl(); + else + return this._dbl(); + }; + + JPoint.prototype._zeroDbl = function _zeroDbl() { + var nx; + var ny; + var nz; + // Z = 1 + if (this.zOne) { + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html + // #doubling-mdbl-2007-bl + // 1M + 5S + 14A + + // XX = X1^2 + var xx = this.x.redSqr(); + // YY = Y1^2 + var yy = this.y.redSqr(); + // YYYY = YY^2 + var yyyy = yy.redSqr(); + // S = 2 * ((X1 + YY)^2 - XX - YYYY) + var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); + s = s.redIAdd(s); + // M = 3 * XX + a; a = 0 + var m = xx.redAdd(xx).redIAdd(xx); + // T = M ^ 2 - 2*S + var t = m.redSqr().redISub(s).redISub(s); + + // 8 * YYYY + var yyyy8 = yyyy.redIAdd(yyyy); + yyyy8 = yyyy8.redIAdd(yyyy8); + yyyy8 = yyyy8.redIAdd(yyyy8); + + // X3 = T + nx = t; + // Y3 = M * (S - T) - 8 * YYYY + ny = m.redMul(s.redISub(t)).redISub(yyyy8); + // Z3 = 2*Y1 + nz = this.y.redAdd(this.y); + } else { + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html + // #doubling-dbl-2009-l + // 2M + 5S + 13A + + // A = X1^2 + var a = this.x.redSqr(); + // B = Y1^2 + var b = this.y.redSqr(); + // C = B^2 + var c = b.redSqr(); + // D = 2 * ((X1 + B)^2 - A - C) + var d = this.x.redAdd(b).redSqr().redISub(a).redISub(c); + d = d.redIAdd(d); + // E = 3 * A + var e = a.redAdd(a).redIAdd(a); + // F = E^2 + var f = e.redSqr(); + + // 8 * C + var c8 = c.redIAdd(c); + c8 = c8.redIAdd(c8); + c8 = c8.redIAdd(c8); + + // X3 = F - 2 * D + nx = f.redISub(d).redISub(d); + // Y3 = E * (D - X3) - 8 * C + ny = e.redMul(d.redISub(nx)).redISub(c8); + // Z3 = 2 * Y1 * Z1 + nz = this.y.redMul(this.z); + nz = nz.redIAdd(nz); + } + + return this.curve.jpoint(nx, ny, nz); + }; + + JPoint.prototype._threeDbl = function _threeDbl() { + var nx; + var ny; + var nz; + // Z = 1 + if (this.zOne) { + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html + // #doubling-mdbl-2007-bl + // 1M + 5S + 15A + + // XX = X1^2 + var xx = this.x.redSqr(); + // YY = Y1^2 + var yy = this.y.redSqr(); + // YYYY = YY^2 + var yyyy = yy.redSqr(); + // S = 2 * ((X1 + YY)^2 - XX - YYYY) + var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); + s = s.redIAdd(s); + // M = 3 * XX + a + var m = xx.redAdd(xx).redIAdd(xx).redIAdd(this.curve.a); + // T = M^2 - 2 * S + var t = m.redSqr().redISub(s).redISub(s); + // X3 = T + nx = t; + // Y3 = M * (S - T) - 8 * YYYY + var yyyy8 = yyyy.redIAdd(yyyy); + yyyy8 = yyyy8.redIAdd(yyyy8); + yyyy8 = yyyy8.redIAdd(yyyy8); + ny = m.redMul(s.redISub(t)).redISub(yyyy8); + // Z3 = 2 * Y1 + nz = this.y.redAdd(this.y); + } else { + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b + // 3M + 5S + + // delta = Z1^2 + var delta = this.z.redSqr(); + // gamma = Y1^2 + var gamma = this.y.redSqr(); + // beta = X1 * gamma + var beta = this.x.redMul(gamma); + // alpha = 3 * (X1 - delta) * (X1 + delta) + var alpha = this.x.redSub(delta).redMul(this.x.redAdd(delta)); + alpha = alpha.redAdd(alpha).redIAdd(alpha); + // X3 = alpha^2 - 8 * beta + var beta4 = beta.redIAdd(beta); + beta4 = beta4.redIAdd(beta4); + var beta8 = beta4.redAdd(beta4); + nx = alpha.redSqr().redISub(beta8); + // Z3 = (Y1 + Z1)^2 - gamma - delta + nz = this.y.redAdd(this.z).redSqr().redISub(gamma).redISub(delta); + // Y3 = alpha * (4 * beta - X3) - 8 * gamma^2 + var ggamma8 = gamma.redSqr(); + ggamma8 = ggamma8.redIAdd(ggamma8); + ggamma8 = ggamma8.redIAdd(ggamma8); + ggamma8 = ggamma8.redIAdd(ggamma8); + ny = alpha.redMul(beta4.redISub(nx)).redISub(ggamma8); + } + + return this.curve.jpoint(nx, ny, nz); + }; + + JPoint.prototype._dbl = function _dbl() { + var a = this.curve.a; + + // 4M + 6S + 10A + var jx = this.x; + var jy = this.y; + var jz = this.z; + var jz4 = jz.redSqr().redSqr(); + + var jx2 = jx.redSqr(); + var jy2 = jy.redSqr(); + + var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); + + var jxd4 = jx.redAdd(jx); + jxd4 = jxd4.redIAdd(jxd4); + var t1 = jxd4.redMul(jy2); + var nx = c.redSqr().redISub(t1.redAdd(t1)); + var t2 = t1.redISub(nx); + + var jyd8 = jy2.redSqr(); + jyd8 = jyd8.redIAdd(jyd8); + jyd8 = jyd8.redIAdd(jyd8); + jyd8 = jyd8.redIAdd(jyd8); + var ny = c.redMul(t2).redISub(jyd8); + var nz = jy.redAdd(jy).redMul(jz); + + return this.curve.jpoint(nx, ny, nz); + }; + + JPoint.prototype.trpl = function trpl() { + if (!this.curve.zeroA) + return this.dbl().add(this); + + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#tripling-tpl-2007-bl + // 5M + 10S + ... + + // XX = X1^2 + var xx = this.x.redSqr(); + // YY = Y1^2 + var yy = this.y.redSqr(); + // ZZ = Z1^2 + var zz = this.z.redSqr(); + // YYYY = YY^2 + var yyyy = yy.redSqr(); + // M = 3 * XX + a * ZZ2; a = 0 + var m = xx.redAdd(xx).redIAdd(xx); + // MM = M^2 + var mm = m.redSqr(); + // E = 6 * ((X1 + YY)^2 - XX - YYYY) - MM + var e = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); + e = e.redIAdd(e); + e = e.redAdd(e).redIAdd(e); + e = e.redISub(mm); + // EE = E^2 + var ee = e.redSqr(); + // T = 16*YYYY + var t = yyyy.redIAdd(yyyy); + t = t.redIAdd(t); + t = t.redIAdd(t); + t = t.redIAdd(t); + // U = (M + E)^2 - MM - EE - T + var u = m.redIAdd(e).redSqr().redISub(mm).redISub(ee).redISub(t); + // X3 = 4 * (X1 * EE - 4 * YY * U) + var yyu4 = yy.redMul(u); + yyu4 = yyu4.redIAdd(yyu4); + yyu4 = yyu4.redIAdd(yyu4); + var nx = this.x.redMul(ee).redISub(yyu4); + nx = nx.redIAdd(nx); + nx = nx.redIAdd(nx); + // Y3 = 8 * Y1 * (U * (T - U) - E * EE) + var ny = this.y.redMul(u.redMul(t.redISub(u)).redISub(e.redMul(ee))); + ny = ny.redIAdd(ny); + ny = ny.redIAdd(ny); + ny = ny.redIAdd(ny); + // Z3 = (Z1 + E)^2 - ZZ - EE + var nz = this.z.redAdd(e).redSqr().redISub(zz).redISub(ee); + + return this.curve.jpoint(nx, ny, nz); + }; + + JPoint.prototype.mul = function mul(k, kbase) { + k = new bn(k, kbase); + + return this.curve._wnafMul(this, k); + }; + + JPoint.prototype.eq = function eq(p) { + if (p.type === 'affine') + return this.eq(p.toJ()); + + if (this === p) + return true; + + // x1 * z2^2 == x2 * z1^2 + var z2 = this.z.redSqr(); + var pz2 = p.z.redSqr(); + if (this.x.redMul(pz2).redISub(p.x.redMul(z2)).cmpn(0) !== 0) + return false; + + // y1 * z2^3 == y2 * z1^3 + var z3 = z2.redMul(this.z); + var pz3 = pz2.redMul(p.z); + return this.y.redMul(pz3).redISub(p.y.redMul(z3)).cmpn(0) === 0; + }; + + JPoint.prototype.eqXToP = function eqXToP(x) { + var zs = this.z.redSqr(); + var rx = x.toRed(this.curve.red).redMul(zs); + if (this.x.cmp(rx) === 0) + return true; + + var xc = x.clone(); + var t = this.curve.redN.redMul(zs); + for (;;) { + xc.iadd(this.curve.n); + if (xc.cmp(this.curve.p) >= 0) + return false; + + rx.redIAdd(t); + if (this.x.cmp(rx) === 0) + return true; + } + }; + + JPoint.prototype.inspect = function inspect() { + if (this.isInfinity()) + return ''; + return ''; + }; + + JPoint.prototype.isInfinity = function isInfinity() { + // XXX This code assumes that zero is always zero in red + return this.z.cmpn(0) === 0; + }; + + function MontCurve(conf) { + base.call(this, 'mont', conf); + + this.a = new bn(conf.a, 16).toRed(this.red); + this.b = new bn(conf.b, 16).toRed(this.red); + this.i4 = new bn(4).toRed(this.red).redInvm(); + this.two = new bn(2).toRed(this.red); + // Note: this implementation is according to the original paper + // by P. Montgomery, NOT the one by D. J. Bernstein. + this.a24 = this.i4.redMul(this.a.redAdd(this.two)); + } + inherits_browser(MontCurve, base); + var mont = MontCurve; + + MontCurve.prototype.validate = function validate(point) { + var x = point.normalize().x; + var x2 = x.redSqr(); + var rhs = x2.redMul(x).redAdd(x2.redMul(this.a)).redAdd(x); + var y = rhs.redSqrt(); + + return y.redSqr().cmp(rhs) === 0; + }; + + function Point$1(curve, x, z) { + base.BasePoint.call(this, curve, 'projective'); + if (x === null && z === null) { + this.x = this.curve.one; + this.z = this.curve.zero; + } else { + this.x = new bn(x, 16); + this.z = new bn(z, 16); + if (!this.x.red) + this.x = this.x.toRed(this.curve.red); + if (!this.z.red) + this.z = this.z.toRed(this.curve.red); + } + } + inherits_browser(Point$1, base.BasePoint); + + MontCurve.prototype.decodePoint = function decodePoint(bytes, enc) { + var bytes = utils_1$1.toArray(bytes, enc); + + // TODO Curve448 + // Montgomery curve points must be represented in the compressed format + // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B + if (bytes.length === 33 && bytes[0] === 0x40) + bytes = bytes.slice(1, 33).reverse(); // point must be little-endian + if (bytes.length !== 32) + throw new Error('Unknown point compression format'); + return this.point(bytes, 1); + }; + + MontCurve.prototype.point = function point(x, z) { + return new Point$1(this, x, z); + }; + + MontCurve.prototype.pointFromJSON = function pointFromJSON(obj) { + return Point$1.fromJSON(this, obj); + }; + + Point$1.prototype.precompute = function precompute() { + // No-op + }; + + Point$1.prototype._encode = function _encode(compact) { + var len = this.curve.p.byteLength(); + + // Note: the output should always be little-endian + // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B + if (compact) { + return [ 0x40 ].concat(this.getX().toArray('le', len)); + } else { + return this.getX().toArray('be', len); + } + }; + + Point$1.fromJSON = function fromJSON(curve, obj) { + return new Point$1(curve, obj[0], obj[1] || curve.one); + }; + + Point$1.prototype.inspect = function inspect() { + if (this.isInfinity()) + return ''; + return ''; + }; + + Point$1.prototype.isInfinity = function isInfinity() { + // XXX This code assumes that zero is always zero in red + return this.z.cmpn(0) === 0; + }; + + Point$1.prototype.dbl = function dbl() { + // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#doubling-dbl-1987-m-3 + // 2M + 2S + 4A + + // A = X1 + Z1 + var a = this.x.redAdd(this.z); + // AA = A^2 + var aa = a.redSqr(); + // B = X1 - Z1 + var b = this.x.redSub(this.z); + // BB = B^2 + var bb = b.redSqr(); + // C = AA - BB + var c = aa.redSub(bb); + // X3 = AA * BB + var nx = aa.redMul(bb); + // Z3 = C * (BB + A24 * C) + var nz = c.redMul(bb.redAdd(this.curve.a24.redMul(c))); + return this.curve.point(nx, nz); + }; + + Point$1.prototype.add = function add() { + throw new Error('Not supported on Montgomery curve'); + }; + + Point$1.prototype.diffAdd = function diffAdd(p, diff) { + // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#diffadd-dadd-1987-m-3 + // 4M + 2S + 6A + + // A = X2 + Z2 + var a = this.x.redAdd(this.z); + // B = X2 - Z2 + var b = this.x.redSub(this.z); + // C = X3 + Z3 + var c = p.x.redAdd(p.z); + // D = X3 - Z3 + var d = p.x.redSub(p.z); + // DA = D * A + var da = d.redMul(a); + // CB = C * B + var cb = c.redMul(b); + // X5 = Z1 * (DA + CB)^2 + var nx = diff.z.redMul(da.redAdd(cb).redSqr()); + // Z5 = X1 * (DA - CB)^2 + var nz = diff.x.redMul(da.redISub(cb).redSqr()); + return this.curve.point(nx, nz); + }; + + Point$1.prototype.mul = function mul(k) { + k = new bn(k, 16); + + var t = k.clone(); + var a = this; // (N / 2) * Q + Q + var b = this.curve.point(null, null); // (N / 2) * Q + var c = this; // Q + + for (var bits = []; t.cmpn(0) !== 0; t.iushrn(1)) + bits.push(t.andln(1)); + + for (var i = bits.length - 1; i >= 0; i--) { + if (bits[i] === 0) { + // N * Q + Q = ((N / 2) * Q + Q)) + (N / 2) * Q + a = a.diffAdd(b, c); + // N * Q = 2 * ((N / 2) * Q + Q)) + b = b.dbl(); + } else { + // N * Q = ((N / 2) * Q + Q) + ((N / 2) * Q) + b = a.diffAdd(b, c); + // N * Q + Q = 2 * ((N / 2) * Q + Q) + a = a.dbl(); + } + } + return b; + }; + + Point$1.prototype.mulAdd = function mulAdd() { + throw new Error('Not supported on Montgomery curve'); + }; + + Point$1.prototype.jumlAdd = function jumlAdd() { + throw new Error('Not supported on Montgomery curve'); + }; + + Point$1.prototype.eq = function eq(other) { + return this.getX().cmp(other.getX()) === 0; + }; + + Point$1.prototype.normalize = function normalize() { + this.x = this.x.redMul(this.z.redInvm()); + this.z = this.curve.one; + return this; + }; + + Point$1.prototype.getX = function getX() { + // Normalize coordinates + this.normalize(); + + return this.x.fromRed(); + }; + + var assert$4 = utils_1$1.assert; + + function EdwardsCurve(conf) { + // NOTE: Important as we are creating point in Base.call() + this.twisted = (conf.a | 0) !== 1; + this.mOneA = this.twisted && (conf.a | 0) === -1; + this.extended = this.mOneA; + + base.call(this, 'edwards', conf); + + this.a = new bn(conf.a, 16).umod(this.red.m); + this.a = this.a.toRed(this.red); + this.c = new bn(conf.c, 16).toRed(this.red); + this.c2 = this.c.redSqr(); + this.d = new bn(conf.d, 16).toRed(this.red); + this.dd = this.d.redAdd(this.d); + + assert$4(!this.twisted || this.c.fromRed().cmpn(1) === 0); + this.oneC = (conf.c | 0) === 1; + } + inherits_browser(EdwardsCurve, base); + var edwards = EdwardsCurve; + + EdwardsCurve.prototype._mulA = function _mulA(num) { + if (this.mOneA) + return num.redNeg(); + else + return this.a.redMul(num); + }; + + EdwardsCurve.prototype._mulC = function _mulC(num) { + if (this.oneC) + return num; + else + return this.c.redMul(num); + }; + + // Just for compatibility with Short curve + EdwardsCurve.prototype.jpoint = function jpoint(x, y, z, t) { + return this.point(x, y, z, t); + }; + + EdwardsCurve.prototype.pointFromX = function pointFromX(x, odd) { + x = new bn(x, 16); + if (!x.red) + x = x.toRed(this.red); + + var x2 = x.redSqr(); + var rhs = this.c2.redSub(this.a.redMul(x2)); + var lhs = this.one.redSub(this.c2.redMul(this.d).redMul(x2)); + + var y2 = rhs.redMul(lhs.redInvm()); + var y = y2.redSqrt(); + if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) + throw new Error('invalid point'); + + var isOdd = y.fromRed().isOdd(); + if (odd && !isOdd || !odd && isOdd) + y = y.redNeg(); + + return this.point(x, y); + }; + + EdwardsCurve.prototype.pointFromY = function pointFromY(y, odd) { + y = new bn(y, 16); + if (!y.red) + y = y.toRed(this.red); + + // x^2 = (y^2 - c^2) / (c^2 d y^2 - a) + var y2 = y.redSqr(); + var lhs = y2.redSub(this.c2); + var rhs = y2.redMul(this.d).redMul(this.c2).redSub(this.a); + var x2 = lhs.redMul(rhs.redInvm()); + + if (x2.cmp(this.zero) === 0) { + if (odd) + throw new Error('invalid point'); + else + return this.point(this.zero, y); + } + + var x = x2.redSqrt(); + if (x.redSqr().redSub(x2).cmp(this.zero) !== 0) + throw new Error('invalid point'); + + if (x.fromRed().isOdd() !== odd) + x = x.redNeg(); + + return this.point(x, y); + }; + + EdwardsCurve.prototype.validate = function validate(point) { + if (point.isInfinity()) + return true; + + // Curve: A * X^2 + Y^2 = C^2 * (1 + D * X^2 * Y^2) + point.normalize(); + + var x2 = point.x.redSqr(); + var y2 = point.y.redSqr(); + var lhs = x2.redMul(this.a).redAdd(y2); + var rhs = this.c2.redMul(this.one.redAdd(this.d.redMul(x2).redMul(y2))); + + return lhs.cmp(rhs) === 0; + }; + + function Point$2(curve, x, y, z, t) { + base.BasePoint.call(this, curve, 'projective'); + if (x === null && y === null && z === null) { + this.x = this.curve.zero; + this.y = this.curve.one; + this.z = this.curve.one; + this.t = this.curve.zero; + this.zOne = true; + } else { + this.x = new bn(x, 16); + this.y = new bn(y, 16); + this.z = z ? new bn(z, 16) : this.curve.one; + this.t = t && new bn(t, 16); + if (!this.x.red) + this.x = this.x.toRed(this.curve.red); + if (!this.y.red) + this.y = this.y.toRed(this.curve.red); + if (!this.z.red) + this.z = this.z.toRed(this.curve.red); + if (this.t && !this.t.red) + this.t = this.t.toRed(this.curve.red); + this.zOne = this.z === this.curve.one; + + // Use extended coordinates + if (this.curve.extended && !this.t) { + this.t = this.x.redMul(this.y); + if (!this.zOne) + this.t = this.t.redMul(this.z.redInvm()); + } + } + } + inherits_browser(Point$2, base.BasePoint); + + EdwardsCurve.prototype.pointFromJSON = function pointFromJSON(obj) { + return Point$2.fromJSON(this, obj); + }; + + EdwardsCurve.prototype.point = function point(x, y, z, t) { + return new Point$2(this, x, y, z, t); + }; + + Point$2.fromJSON = function fromJSON(curve, obj) { + return new Point$2(curve, obj[0], obj[1], obj[2]); + }; + + Point$2.prototype.inspect = function inspect() { + if (this.isInfinity()) + return ''; + return ''; + }; + + Point$2.prototype.isInfinity = function isInfinity() { + // XXX This code assumes that zero is always zero in red + return this.x.cmpn(0) === 0 && + (this.y.cmp(this.z) === 0 || + (this.zOne && this.y.cmp(this.curve.c) === 0)); + }; + + Point$2.prototype._extDbl = function _extDbl() { + // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html + // #doubling-dbl-2008-hwcd + // 4M + 4S + + // A = X1^2 + var a = this.x.redSqr(); + // B = Y1^2 + var b = this.y.redSqr(); + // C = 2 * Z1^2 + var c = this.z.redSqr(); + c = c.redIAdd(c); + // D = a * A + var d = this.curve._mulA(a); + // E = (X1 + Y1)^2 - A - B + var e = this.x.redAdd(this.y).redSqr().redISub(a).redISub(b); + // G = D + B + var g = d.redAdd(b); + // F = G - C + var f = g.redSub(c); + // H = D - B + var h = d.redSub(b); + // X3 = E * F + var nx = e.redMul(f); + // Y3 = G * H + var ny = g.redMul(h); + // T3 = E * H + var nt = e.redMul(h); + // Z3 = F * G + var nz = f.redMul(g); + return this.curve.point(nx, ny, nz, nt); + }; + + Point$2.prototype._projDbl = function _projDbl() { + // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html + // #doubling-dbl-2008-bbjlp + // #doubling-dbl-2007-bl + // and others + // Generally 3M + 4S or 2M + 4S + + // B = (X1 + Y1)^2 + var b = this.x.redAdd(this.y).redSqr(); + // C = X1^2 + var c = this.x.redSqr(); + // D = Y1^2 + var d = this.y.redSqr(); + + var nx; + var ny; + var nz; + if (this.curve.twisted) { + // E = a * C + var e = this.curve._mulA(c); + // F = E + D + var f = e.redAdd(d); + if (this.zOne) { + // X3 = (B - C - D) * (F - 2) + nx = b.redSub(c).redSub(d).redMul(f.redSub(this.curve.two)); + // Y3 = F * (E - D) + ny = f.redMul(e.redSub(d)); + // Z3 = F^2 - 2 * F + nz = f.redSqr().redSub(f).redSub(f); + } else { + // H = Z1^2 + var h = this.z.redSqr(); + // J = F - 2 * H + var j = f.redSub(h).redISub(h); + // X3 = (B-C-D)*J + nx = b.redSub(c).redISub(d).redMul(j); + // Y3 = F * (E - D) + ny = f.redMul(e.redSub(d)); + // Z3 = F * J + nz = f.redMul(j); + } + } else { + // E = C + D + var e = c.redAdd(d); + // H = (c * Z1)^2 + var h = this.curve._mulC(this.z).redSqr(); + // J = E - 2 * H + var j = e.redSub(h).redSub(h); + // X3 = c * (B - E) * J + nx = this.curve._mulC(b.redISub(e)).redMul(j); + // Y3 = c * E * (C - D) + ny = this.curve._mulC(e).redMul(c.redISub(d)); + // Z3 = E * J + nz = e.redMul(j); + } + return this.curve.point(nx, ny, nz); + }; + + Point$2.prototype.dbl = function dbl() { + if (this.isInfinity()) + return this; + + // Double in extended coordinates + if (this.curve.extended) + return this._extDbl(); + else + return this._projDbl(); + }; + + Point$2.prototype._extAdd = function _extAdd(p) { + // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html + // #addition-add-2008-hwcd-3 + // 8M + + // A = (Y1 - X1) * (Y2 - X2) + var a = this.y.redSub(this.x).redMul(p.y.redSub(p.x)); + // B = (Y1 + X1) * (Y2 + X2) + var b = this.y.redAdd(this.x).redMul(p.y.redAdd(p.x)); + // C = T1 * k * T2 + var c = this.t.redMul(this.curve.dd).redMul(p.t); + // D = Z1 * 2 * Z2 + var d = this.z.redMul(p.z.redAdd(p.z)); + // E = B - A + var e = b.redSub(a); + // F = D - C + var f = d.redSub(c); + // G = D + C + var g = d.redAdd(c); + // H = B + A + var h = b.redAdd(a); + // X3 = E * F + var nx = e.redMul(f); + // Y3 = G * H + var ny = g.redMul(h); + // T3 = E * H + var nt = e.redMul(h); + // Z3 = F * G + var nz = f.redMul(g); + return this.curve.point(nx, ny, nz, nt); + }; + + Point$2.prototype._projAdd = function _projAdd(p) { + // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html + // #addition-add-2008-bbjlp + // #addition-add-2007-bl + // 10M + 1S + + // A = Z1 * Z2 + var a = this.z.redMul(p.z); + // B = A^2 + var b = a.redSqr(); + // C = X1 * X2 + var c = this.x.redMul(p.x); + // D = Y1 * Y2 + var d = this.y.redMul(p.y); + // E = d * C * D + var e = this.curve.d.redMul(c).redMul(d); + // F = B - E + var f = b.redSub(e); + // G = B + E + var g = b.redAdd(e); + // X3 = A * F * ((X1 + Y1) * (X2 + Y2) - C - D) + var tmp = this.x.redAdd(this.y).redMul(p.x.redAdd(p.y)).redISub(c).redISub(d); + var nx = a.redMul(f).redMul(tmp); + var ny; + var nz; + if (this.curve.twisted) { + // Y3 = A * G * (D - a * C) + ny = a.redMul(g).redMul(d.redSub(this.curve._mulA(c))); + // Z3 = F * G + nz = f.redMul(g); + } else { + // Y3 = A * G * (D - C) + ny = a.redMul(g).redMul(d.redSub(c)); + // Z3 = c * F * G + nz = this.curve._mulC(f).redMul(g); + } + return this.curve.point(nx, ny, nz); + }; + + Point$2.prototype.add = function add(p) { + if (this.isInfinity()) + return p; + if (p.isInfinity()) + return this; + + if (this.curve.extended) + return this._extAdd(p); + else + return this._projAdd(p); + }; + + Point$2.prototype.mul = function mul(k) { + if (this._hasDoubles(k)) + return this.curve._fixedNafMul(this, k); + else + return this.curve._wnafMul(this, k); + }; + + Point$2.prototype.mulAdd = function mulAdd(k1, p, k2) { + return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, false); + }; + + Point$2.prototype.jmulAdd = function jmulAdd(k1, p, k2) { + return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, true); + }; + + Point$2.prototype.normalize = function normalize() { + if (this.zOne) + return this; + + // Normalize coordinates + var zi = this.z.redInvm(); + this.x = this.x.redMul(zi); + this.y = this.y.redMul(zi); + if (this.t) + this.t = this.t.redMul(zi); + this.z = this.curve.one; + this.zOne = true; + return this; + }; + + Point$2.prototype.neg = function neg() { + return this.curve.point(this.x.redNeg(), + this.y, + this.z, + this.t && this.t.redNeg()); + }; + + Point$2.prototype.getX = function getX() { + this.normalize(); + return this.x.fromRed(); + }; + + Point$2.prototype.getY = function getY() { + this.normalize(); + return this.y.fromRed(); + }; + + Point$2.prototype.eq = function eq(other) { + return this === other || + this.getX().cmp(other.getX()) === 0 && + this.getY().cmp(other.getY()) === 0; + }; + + Point$2.prototype.eqXToP = function eqXToP(x) { + var rx = x.toRed(this.curve.red).redMul(this.z); + if (this.x.cmp(rx) === 0) + return true; + + var xc = x.clone(); + var t = this.curve.redN.redMul(this.z); + for (;;) { + xc.iadd(this.curve.n); + if (xc.cmp(this.curve.p) >= 0) + return false; + + rx.redIAdd(t); + if (this.x.cmp(rx) === 0) + return true; + } + }; + + // Compatibility with BaseCurve + Point$2.prototype.toP = Point$2.prototype.normalize; + Point$2.prototype.mixedAdd = Point$2.prototype.add; + + var curve_1 = createCommonjsModule(function (module, exports) { + + var curve = exports; + + curve.base = base; + curve.short = short_1; + curve.mont = mont; + curve.edwards = edwards; + }); + + var rotl32$2 = utils.rotl32; + var sum32$3 = utils.sum32; + var sum32_5$2 = utils.sum32_5; + var ft_1$1 = common$1.ft_1; + var BlockHash$4 = common.BlockHash; + + var sha1_K = [ + 0x5A827999, 0x6ED9EBA1, + 0x8F1BBCDC, 0xCA62C1D6 + ]; + + function SHA1() { + if (!(this instanceof SHA1)) + return new SHA1(); + + BlockHash$4.call(this); + this.h = [ + 0x67452301, 0xefcdab89, 0x98badcfe, + 0x10325476, 0xc3d2e1f0 ]; + this.W = new Array(80); + } + + utils.inherits(SHA1, BlockHash$4); + var _1 = SHA1; + + SHA1.blockSize = 512; + SHA1.outSize = 160; + SHA1.hmacStrength = 80; + SHA1.padLength = 64; + + SHA1.prototype._update = function _update(msg, start) { + var W = this.W; + + for (var i = 0; i < 16; i++) + W[i] = msg[start + i]; + + for(; i < W.length; i++) + W[i] = rotl32$2(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1); + + var a = this.h[0]; + var b = this.h[1]; + var c = this.h[2]; + var d = this.h[3]; + var e = this.h[4]; + + for (i = 0; i < W.length; i++) { + var s = ~~(i / 20); + var t = sum32_5$2(rotl32$2(a, 5), ft_1$1(s, b, c, d), e, W[i], sha1_K[s]); + e = d; + d = c; + c = rotl32$2(b, 30); + b = a; + a = t; + } + + this.h[0] = sum32$3(this.h[0], a); + this.h[1] = sum32$3(this.h[1], b); + this.h[2] = sum32$3(this.h[2], c); + this.h[3] = sum32$3(this.h[3], d); + this.h[4] = sum32$3(this.h[4], e); + }; + + SHA1.prototype._digest = function digest(enc) { + if (enc === 'hex') + return utils.toHex32(this.h, 'big'); + else + return utils.split32(this.h, 'big'); + }; + + var sha1 = _1; + var sha224 = _224; + var sha256 = _256; + var sha384 = _384; + var sha512 = _512; + + var sha = { + sha1: sha1, + sha224: sha224, + sha256: sha256, + sha384: sha384, + sha512: sha512 + }; + + function Hmac(hash, key, enc) { + if (!(this instanceof Hmac)) + return new Hmac(hash, key, enc); + this.Hash = hash; + this.blockSize = hash.blockSize / 8; + this.outSize = hash.outSize / 8; + this.inner = null; + this.outer = null; + + this._init(utils.toArray(key, enc)); + } + var hmac = Hmac; + + Hmac.prototype._init = function init(key) { + // Shorten key, if needed + if (key.length > this.blockSize) + key = new this.Hash().update(key).digest(); + minimalisticAssert(key.length <= this.blockSize); + + // Add padding to key + for (var i = key.length; i < this.blockSize; i++) + key.push(0); + + for (i = 0; i < key.length; i++) + key[i] ^= 0x36; + this.inner = new this.Hash().update(key); + + // 0x36 ^ 0x5c = 0x6a + for (i = 0; i < key.length; i++) + key[i] ^= 0x6a; + this.outer = new this.Hash().update(key); + }; + + Hmac.prototype.update = function update(msg, enc) { + this.inner.update(msg, enc); + return this; + }; + + Hmac.prototype.digest = function digest(enc) { + this.outer.update(this.inner.digest()); + return this.outer.digest(enc); + }; + + var hash_1 = createCommonjsModule(function (module, exports) { + var hash = exports; + + hash.utils = utils; + hash.common = common; + hash.sha = sha; + hash.ripemd = ripemd; + hash.hmac = hmac; + + // Proxy hash functions to the main object + hash.sha1 = hash.sha.sha1; + hash.sha256 = hash.sha.sha256; + hash.sha224 = hash.sha.sha224; + hash.sha384 = hash.sha.sha384; + hash.sha512 = hash.sha.sha512; + hash.ripemd160 = hash.ripemd.ripemd160; + }); + + var secp256k1 = { + doubles: { + step: 4, + points: [ + [ + 'e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a', + 'f7e3507399e595929db99f34f57937101296891e44d23f0be1f32cce69616821' + ], + [ + '8282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508', + '11f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf' + ], + [ + '175e159f728b865a72f99cc6c6fc846de0b93833fd2222ed73fce5b551e5b739', + 'd3506e0d9e3c79eba4ef97a51ff71f5eacb5955add24345c6efa6ffee9fed695' + ], + [ + '363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640', + '4e273adfc732221953b445397f3363145b9a89008199ecb62003c7f3bee9de9' + ], + [ + '8b4b5f165df3c2be8c6244b5b745638843e4a781a15bcd1b69f79a55dffdf80c', + '4aad0a6f68d308b4b3fbd7813ab0da04f9e336546162ee56b3eff0c65fd4fd36' + ], + [ + '723cbaa6e5db996d6bf771c00bd548c7b700dbffa6c0e77bcb6115925232fcda', + '96e867b5595cc498a921137488824d6e2660a0653779494801dc069d9eb39f5f' + ], + [ + 'eebfa4d493bebf98ba5feec812c2d3b50947961237a919839a533eca0e7dd7fa', + '5d9a8ca3970ef0f269ee7edaf178089d9ae4cdc3a711f712ddfd4fdae1de8999' + ], + [ + '100f44da696e71672791d0a09b7bde459f1215a29b3c03bfefd7835b39a48db0', + 'cdd9e13192a00b772ec8f3300c090666b7ff4a18ff5195ac0fbd5cd62bc65a09' + ], + [ + 'e1031be262c7ed1b1dc9227a4a04c017a77f8d4464f3b3852c8acde6e534fd2d', + '9d7061928940405e6bb6a4176597535af292dd419e1ced79a44f18f29456a00d' + ], + [ + 'feea6cae46d55b530ac2839f143bd7ec5cf8b266a41d6af52d5e688d9094696d', + 'e57c6b6c97dce1bab06e4e12bf3ecd5c981c8957cc41442d3155debf18090088' + ], + [ + 'da67a91d91049cdcb367be4be6ffca3cfeed657d808583de33fa978bc1ec6cb1', + '9bacaa35481642bc41f463f7ec9780e5dec7adc508f740a17e9ea8e27a68be1d' + ], + [ + '53904faa0b334cdda6e000935ef22151ec08d0f7bb11069f57545ccc1a37b7c0', + '5bc087d0bc80106d88c9eccac20d3c1c13999981e14434699dcb096b022771c8' + ], + [ + '8e7bcd0bd35983a7719cca7764ca906779b53a043a9b8bcaeff959f43ad86047', + '10b7770b2a3da4b3940310420ca9514579e88e2e47fd68b3ea10047e8460372a' + ], + [ + '385eed34c1cdff21e6d0818689b81bde71a7f4f18397e6690a841e1599c43862', + '283bebc3e8ea23f56701de19e9ebf4576b304eec2086dc8cc0458fe5542e5453' + ], + [ + '6f9d9b803ecf191637c73a4413dfa180fddf84a5947fbc9c606ed86c3fac3a7', + '7c80c68e603059ba69b8e2a30e45c4d47ea4dd2f5c281002d86890603a842160' + ], + [ + '3322d401243c4e2582a2147c104d6ecbf774d163db0f5e5313b7e0e742d0e6bd', + '56e70797e9664ef5bfb019bc4ddaf9b72805f63ea2873af624f3a2e96c28b2a0' + ], + [ + '85672c7d2de0b7da2bd1770d89665868741b3f9af7643397721d74d28134ab83', + '7c481b9b5b43b2eb6374049bfa62c2e5e77f17fcc5298f44c8e3094f790313a6' + ], + [ + '948bf809b1988a46b06c9f1919413b10f9226c60f668832ffd959af60c82a0a', + '53a562856dcb6646dc6b74c5d1c3418c6d4dff08c97cd2bed4cb7f88d8c8e589' + ], + [ + '6260ce7f461801c34f067ce0f02873a8f1b0e44dfc69752accecd819f38fd8e8', + 'bc2da82b6fa5b571a7f09049776a1ef7ecd292238051c198c1a84e95b2b4ae17' + ], + [ + 'e5037de0afc1d8d43d8348414bbf4103043ec8f575bfdc432953cc8d2037fa2d', + '4571534baa94d3b5f9f98d09fb990bddbd5f5b03ec481f10e0e5dc841d755bda' + ], + [ + 'e06372b0f4a207adf5ea905e8f1771b4e7e8dbd1c6a6c5b725866a0ae4fce725', + '7a908974bce18cfe12a27bb2ad5a488cd7484a7787104870b27034f94eee31dd' + ], + [ + '213c7a715cd5d45358d0bbf9dc0ce02204b10bdde2a3f58540ad6908d0559754', + '4b6dad0b5ae462507013ad06245ba190bb4850f5f36a7eeddff2c27534b458f2' + ], + [ + '4e7c272a7af4b34e8dbb9352a5419a87e2838c70adc62cddf0cc3a3b08fbd53c', + '17749c766c9d0b18e16fd09f6def681b530b9614bff7dd33e0b3941817dcaae6' + ], + [ + 'fea74e3dbe778b1b10f238ad61686aa5c76e3db2be43057632427e2840fb27b6', + '6e0568db9b0b13297cf674deccb6af93126b596b973f7b77701d3db7f23cb96f' + ], + [ + '76e64113f677cf0e10a2570d599968d31544e179b760432952c02a4417bdde39', + 'c90ddf8dee4e95cf577066d70681f0d35e2a33d2b56d2032b4b1752d1901ac01' + ], + [ + 'c738c56b03b2abe1e8281baa743f8f9a8f7cc643df26cbee3ab150242bcbb891', + '893fb578951ad2537f718f2eacbfbbbb82314eef7880cfe917e735d9699a84c3' + ], + [ + 'd895626548b65b81e264c7637c972877d1d72e5f3a925014372e9f6588f6c14b', + 'febfaa38f2bc7eae728ec60818c340eb03428d632bb067e179363ed75d7d991f' + ], + [ + 'b8da94032a957518eb0f6433571e8761ceffc73693e84edd49150a564f676e03', + '2804dfa44805a1e4d7c99cc9762808b092cc584d95ff3b511488e4e74efdf6e7' + ], + [ + 'e80fea14441fb33a7d8adab9475d7fab2019effb5156a792f1a11778e3c0df5d', + 'eed1de7f638e00771e89768ca3ca94472d155e80af322ea9fcb4291b6ac9ec78' + ], + [ + 'a301697bdfcd704313ba48e51d567543f2a182031efd6915ddc07bbcc4e16070', + '7370f91cfb67e4f5081809fa25d40f9b1735dbf7c0a11a130c0d1a041e177ea1' + ], + [ + '90ad85b389d6b936463f9d0512678de208cc330b11307fffab7ac63e3fb04ed4', + 'e507a3620a38261affdcbd9427222b839aefabe1582894d991d4d48cb6ef150' + ], + [ + '8f68b9d2f63b5f339239c1ad981f162ee88c5678723ea3351b7b444c9ec4c0da', + '662a9f2dba063986de1d90c2b6be215dbbea2cfe95510bfdf23cbf79501fff82' + ], + [ + 'e4f3fb0176af85d65ff99ff9198c36091f48e86503681e3e6686fd5053231e11', + '1e63633ad0ef4f1c1661a6d0ea02b7286cc7e74ec951d1c9822c38576feb73bc' + ], + [ + '8c00fa9b18ebf331eb961537a45a4266c7034f2f0d4e1d0716fb6eae20eae29e', + 'efa47267fea521a1a9dc343a3736c974c2fadafa81e36c54e7d2a4c66702414b' + ], + [ + 'e7a26ce69dd4829f3e10cec0a9e98ed3143d084f308b92c0997fddfc60cb3e41', + '2a758e300fa7984b471b006a1aafbb18d0a6b2c0420e83e20e8a9421cf2cfd51' + ], + [ + 'b6459e0ee3662ec8d23540c223bcbdc571cbcb967d79424f3cf29eb3de6b80ef', + '67c876d06f3e06de1dadf16e5661db3c4b3ae6d48e35b2ff30bf0b61a71ba45' + ], + [ + 'd68a80c8280bb840793234aa118f06231d6f1fc67e73c5a5deda0f5b496943e8', + 'db8ba9fff4b586d00c4b1f9177b0e28b5b0e7b8f7845295a294c84266b133120' + ], + [ + '324aed7df65c804252dc0270907a30b09612aeb973449cea4095980fc28d3d5d', + '648a365774b61f2ff130c0c35aec1f4f19213b0c7e332843967224af96ab7c84' + ], + [ + '4df9c14919cde61f6d51dfdbe5fee5dceec4143ba8d1ca888e8bd373fd054c96', + '35ec51092d8728050974c23a1d85d4b5d506cdc288490192ebac06cad10d5d' + ], + [ + '9c3919a84a474870faed8a9c1cc66021523489054d7f0308cbfc99c8ac1f98cd', + 'ddb84f0f4a4ddd57584f044bf260e641905326f76c64c8e6be7e5e03d4fc599d' + ], + [ + '6057170b1dd12fdf8de05f281d8e06bb91e1493a8b91d4cc5a21382120a959e5', + '9a1af0b26a6a4807add9a2daf71df262465152bc3ee24c65e899be932385a2a8' + ], + [ + 'a576df8e23a08411421439a4518da31880cef0fba7d4df12b1a6973eecb94266', + '40a6bf20e76640b2c92b97afe58cd82c432e10a7f514d9f3ee8be11ae1b28ec8' + ], + [ + '7778a78c28dec3e30a05fe9629de8c38bb30d1f5cf9a3a208f763889be58ad71', + '34626d9ab5a5b22ff7098e12f2ff580087b38411ff24ac563b513fc1fd9f43ac' + ], + [ + '928955ee637a84463729fd30e7afd2ed5f96274e5ad7e5cb09eda9c06d903ac', + 'c25621003d3f42a827b78a13093a95eeac3d26efa8a8d83fc5180e935bcd091f' + ], + [ + '85d0fef3ec6db109399064f3a0e3b2855645b4a907ad354527aae75163d82751', + '1f03648413a38c0be29d496e582cf5663e8751e96877331582c237a24eb1f962' + ], + [ + 'ff2b0dce97eece97c1c9b6041798b85dfdfb6d8882da20308f5404824526087e', + '493d13fef524ba188af4c4dc54d07936c7b7ed6fb90e2ceb2c951e01f0c29907' + ], + [ + '827fbbe4b1e880ea9ed2b2e6301b212b57f1ee148cd6dd28780e5e2cf856e241', + 'c60f9c923c727b0b71bef2c67d1d12687ff7a63186903166d605b68baec293ec' + ], + [ + 'eaa649f21f51bdbae7be4ae34ce6e5217a58fdce7f47f9aa7f3b58fa2120e2b3', + 'be3279ed5bbbb03ac69a80f89879aa5a01a6b965f13f7e59d47a5305ba5ad93d' + ], + [ + 'e4a42d43c5cf169d9391df6decf42ee541b6d8f0c9a137401e23632dda34d24f', + '4d9f92e716d1c73526fc99ccfb8ad34ce886eedfa8d8e4f13a7f7131deba9414' + ], + [ + '1ec80fef360cbdd954160fadab352b6b92b53576a88fea4947173b9d4300bf19', + 'aeefe93756b5340d2f3a4958a7abbf5e0146e77f6295a07b671cdc1cc107cefd' + ], + [ + '146a778c04670c2f91b00af4680dfa8bce3490717d58ba889ddb5928366642be', + 'b318e0ec3354028add669827f9d4b2870aaa971d2f7e5ed1d0b297483d83efd0' + ], + [ + 'fa50c0f61d22e5f07e3acebb1aa07b128d0012209a28b9776d76a8793180eef9', + '6b84c6922397eba9b72cd2872281a68a5e683293a57a213b38cd8d7d3f4f2811' + ], + [ + 'da1d61d0ca721a11b1a5bf6b7d88e8421a288ab5d5bba5220e53d32b5f067ec2', + '8157f55a7c99306c79c0766161c91e2966a73899d279b48a655fba0f1ad836f1' + ], + [ + 'a8e282ff0c9706907215ff98e8fd416615311de0446f1e062a73b0610d064e13', + '7f97355b8db81c09abfb7f3c5b2515888b679a3e50dd6bd6cef7c73111f4cc0c' + ], + [ + '174a53b9c9a285872d39e56e6913cab15d59b1fa512508c022f382de8319497c', + 'ccc9dc37abfc9c1657b4155f2c47f9e6646b3a1d8cb9854383da13ac079afa73' + ], + [ + '959396981943785c3d3e57edf5018cdbe039e730e4918b3d884fdff09475b7ba', + '2e7e552888c331dd8ba0386a4b9cd6849c653f64c8709385e9b8abf87524f2fd' + ], + [ + 'd2a63a50ae401e56d645a1153b109a8fcca0a43d561fba2dbb51340c9d82b151', + 'e82d86fb6443fcb7565aee58b2948220a70f750af484ca52d4142174dcf89405' + ], + [ + '64587e2335471eb890ee7896d7cfdc866bacbdbd3839317b3436f9b45617e073', + 'd99fcdd5bf6902e2ae96dd6447c299a185b90a39133aeab358299e5e9faf6589' + ], + [ + '8481bde0e4e4d885b3a546d3e549de042f0aa6cea250e7fd358d6c86dd45e458', + '38ee7b8cba5404dd84a25bf39cecb2ca900a79c42b262e556d64b1b59779057e' + ], + [ + '13464a57a78102aa62b6979ae817f4637ffcfed3c4b1ce30bcd6303f6caf666b', + '69be159004614580ef7e433453ccb0ca48f300a81d0942e13f495a907f6ecc27' + ], + [ + 'bc4a9df5b713fe2e9aef430bcc1dc97a0cd9ccede2f28588cada3a0d2d83f366', + 'd3a81ca6e785c06383937adf4b798caa6e8a9fbfa547b16d758d666581f33c1' + ], + [ + '8c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa', + '40a30463a3305193378fedf31f7cc0eb7ae784f0451cb9459e71dc73cbef9482' + ], + [ + '8ea9666139527a8c1dd94ce4f071fd23c8b350c5a4bb33748c4ba111faccae0', + '620efabbc8ee2782e24e7c0cfb95c5d735b783be9cf0f8e955af34a30e62b945' + ], + [ + 'dd3625faef5ba06074669716bbd3788d89bdde815959968092f76cc4eb9a9787', + '7a188fa3520e30d461da2501045731ca941461982883395937f68d00c644a573' + ], + [ + 'f710d79d9eb962297e4f6232b40e8f7feb2bc63814614d692c12de752408221e', + 'ea98e67232d3b3295d3b535532115ccac8612c721851617526ae47a9c77bfc82' + ] + ] + }, + naf: { + wnd: 7, + points: [ + [ + 'f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9', + '388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672' + ], + [ + '2f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4', + 'd8ac222636e5e3d6d4dba9dda6c9c426f788271bab0d6840dca87d3aa6ac62d6' + ], + [ + '5cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc', + '6aebca40ba255960a3178d6d861a54dba813d0b813fde7b5a5082628087264da' + ], + [ + 'acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe', + 'cc338921b0a7d9fd64380971763b61e9add888a4375f8e0f05cc262ac64f9c37' + ], + [ + '774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb', + 'd984a032eb6b5e190243dd56d7b7b365372db1e2dff9d6a8301d74c9c953c61b' + ], + [ + 'f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8', + 'ab0902e8d880a89758212eb65cdaf473a1a06da521fa91f29b5cb52db03ed81' + ], + [ + 'd7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e', + '581e2872a86c72a683842ec228cc6defea40af2bd896d3a5c504dc9ff6a26b58' + ], + [ + 'defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34', + '4211ab0694635168e997b0ead2a93daeced1f4a04a95c0f6cfb199f69e56eb77' + ], + [ + '2b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c', + '85e89bc037945d93b343083b5a1c86131a01f60c50269763b570c854e5c09b7a' + ], + [ + '352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5', + '321eb4075348f534d59c18259dda3e1f4a1b3b2e71b1039c67bd3d8bcf81998c' + ], + [ + '2fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f', + '2de1068295dd865b64569335bd5dd80181d70ecfc882648423ba76b532b7d67' + ], + [ + '9248279b09b4d68dab21a9b066edda83263c3d84e09572e269ca0cd7f5453714', + '73016f7bf234aade5d1aa71bdea2b1ff3fc0de2a887912ffe54a32ce97cb3402' + ], + [ + 'daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729', + 'a69dce4a7d6c98e8d4a1aca87ef8d7003f83c230f3afa726ab40e52290be1c55' + ], + [ + 'c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db', + '2119a460ce326cdc76c45926c982fdac0e106e861edf61c5a039063f0e0e6482' + ], + [ + '6a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4', + 'e022cf42c2bd4a708b3f5126f16a24ad8b33ba48d0423b6efd5e6348100d8a82' + ], + [ + '1697ffa6fd9de627c077e3d2fe541084ce13300b0bec1146f95ae57f0d0bd6a5', + 'b9c398f186806f5d27561506e4557433a2cf15009e498ae7adee9d63d01b2396' + ], + [ + '605bdb019981718b986d0f07e834cb0d9deb8360ffb7f61df982345ef27a7479', + '2972d2de4f8d20681a78d93ec96fe23c26bfae84fb14db43b01e1e9056b8c49' + ], + [ + '62d14dab4150bf497402fdc45a215e10dcb01c354959b10cfe31c7e9d87ff33d', + '80fc06bd8cc5b01098088a1950eed0db01aa132967ab472235f5642483b25eaf' + ], + [ + '80c60ad0040f27dade5b4b06c408e56b2c50e9f56b9b8b425e555c2f86308b6f', + '1c38303f1cc5c30f26e66bad7fe72f70a65eed4cbe7024eb1aa01f56430bd57a' + ], + [ + '7a9375ad6167ad54aa74c6348cc54d344cc5dc9487d847049d5eabb0fa03c8fb', + 'd0e3fa9eca8726909559e0d79269046bdc59ea10c70ce2b02d499ec224dc7f7' + ], + [ + 'd528ecd9b696b54c907a9ed045447a79bb408ec39b68df504bb51f459bc3ffc9', + 'eecf41253136e5f99966f21881fd656ebc4345405c520dbc063465b521409933' + ], + [ + '49370a4b5f43412ea25f514e8ecdad05266115e4a7ecb1387231808f8b45963', + '758f3f41afd6ed428b3081b0512fd62a54c3f3afbb5b6764b653052a12949c9a' + ], + [ + '77f230936ee88cbbd73df930d64702ef881d811e0e1498e2f1c13eb1fc345d74', + '958ef42a7886b6400a08266e9ba1b37896c95330d97077cbbe8eb3c7671c60d6' + ], + [ + 'f2dac991cc4ce4b9ea44887e5c7c0bce58c80074ab9d4dbaeb28531b7739f530', + 'e0dedc9b3b2f8dad4da1f32dec2531df9eb5fbeb0598e4fd1a117dba703a3c37' + ], + [ + '463b3d9f662621fb1b4be8fbbe2520125a216cdfc9dae3debcba4850c690d45b', + '5ed430d78c296c3543114306dd8622d7c622e27c970a1de31cb377b01af7307e' + ], + [ + 'f16f804244e46e2a09232d4aff3b59976b98fac14328a2d1a32496b49998f247', + 'cedabd9b82203f7e13d206fcdf4e33d92a6c53c26e5cce26d6579962c4e31df6' + ], + [ + 'caf754272dc84563b0352b7a14311af55d245315ace27c65369e15f7151d41d1', + 'cb474660ef35f5f2a41b643fa5e460575f4fa9b7962232a5c32f908318a04476' + ], + [ + '2600ca4b282cb986f85d0f1709979d8b44a09c07cb86d7c124497bc86f082120', + '4119b88753c15bd6a693b03fcddbb45d5ac6be74ab5f0ef44b0be9475a7e4b40' + ], + [ + '7635ca72d7e8432c338ec53cd12220bc01c48685e24f7dc8c602a7746998e435', + '91b649609489d613d1d5e590f78e6d74ecfc061d57048bad9e76f302c5b9c61' + ], + [ + '754e3239f325570cdbbf4a87deee8a66b7f2b33479d468fbc1a50743bf56cc18', + '673fb86e5bda30fb3cd0ed304ea49a023ee33d0197a695d0c5d98093c536683' + ], + [ + 'e3e6bd1071a1e96aff57859c82d570f0330800661d1c952f9fe2694691d9b9e8', + '59c9e0bba394e76f40c0aa58379a3cb6a5a2283993e90c4167002af4920e37f5' + ], + [ + '186b483d056a033826ae73d88f732985c4ccb1f32ba35f4b4cc47fdcf04aa6eb', + '3b952d32c67cf77e2e17446e204180ab21fb8090895138b4a4a797f86e80888b' + ], + [ + 'df9d70a6b9876ce544c98561f4be4f725442e6d2b737d9c91a8321724ce0963f', + '55eb2dafd84d6ccd5f862b785dc39d4ab157222720ef9da217b8c45cf2ba2417' + ], + [ + '5edd5cc23c51e87a497ca815d5dce0f8ab52554f849ed8995de64c5f34ce7143', + 'efae9c8dbc14130661e8cec030c89ad0c13c66c0d17a2905cdc706ab7399a868' + ], + [ + '290798c2b6476830da12fe02287e9e777aa3fba1c355b17a722d362f84614fba', + 'e38da76dcd440621988d00bcf79af25d5b29c094db2a23146d003afd41943e7a' + ], + [ + 'af3c423a95d9f5b3054754efa150ac39cd29552fe360257362dfdecef4053b45', + 'f98a3fd831eb2b749a93b0e6f35cfb40c8cd5aa667a15581bc2feded498fd9c6' + ], + [ + '766dbb24d134e745cccaa28c99bf274906bb66b26dcf98df8d2fed50d884249a', + '744b1152eacbe5e38dcc887980da38b897584a65fa06cedd2c924f97cbac5996' + ], + [ + '59dbf46f8c94759ba21277c33784f41645f7b44f6c596a58ce92e666191abe3e', + 'c534ad44175fbc300f4ea6ce648309a042ce739a7919798cd85e216c4a307f6e' + ], + [ + 'f13ada95103c4537305e691e74e9a4a8dd647e711a95e73cb62dc6018cfd87b8', + 'e13817b44ee14de663bf4bc808341f326949e21a6a75c2570778419bdaf5733d' + ], + [ + '7754b4fa0e8aced06d4167a2c59cca4cda1869c06ebadfb6488550015a88522c', + '30e93e864e669d82224b967c3020b8fa8d1e4e350b6cbcc537a48b57841163a2' + ], + [ + '948dcadf5990e048aa3874d46abef9d701858f95de8041d2a6828c99e2262519', + 'e491a42537f6e597d5d28a3224b1bc25df9154efbd2ef1d2cbba2cae5347d57e' + ], + [ + '7962414450c76c1689c7b48f8202ec37fb224cf5ac0bfa1570328a8a3d7c77ab', + '100b610ec4ffb4760d5c1fc133ef6f6b12507a051f04ac5760afa5b29db83437' + ], + [ + '3514087834964b54b15b160644d915485a16977225b8847bb0dd085137ec47ca', + 'ef0afbb2056205448e1652c48e8127fc6039e77c15c2378b7e7d15a0de293311' + ], + [ + 'd3cc30ad6b483e4bc79ce2c9dd8bc54993e947eb8df787b442943d3f7b527eaf', + '8b378a22d827278d89c5e9be8f9508ae3c2ad46290358630afb34db04eede0a4' + ], + [ + '1624d84780732860ce1c78fcbfefe08b2b29823db913f6493975ba0ff4847610', + '68651cf9b6da903e0914448c6cd9d4ca896878f5282be4c8cc06e2a404078575' + ], + [ + '733ce80da955a8a26902c95633e62a985192474b5af207da6df7b4fd5fc61cd4', + 'f5435a2bd2badf7d485a4d8b8db9fcce3e1ef8e0201e4578c54673bc1dc5ea1d' + ], + [ + '15d9441254945064cf1a1c33bbd3b49f8966c5092171e699ef258dfab81c045c', + 'd56eb30b69463e7234f5137b73b84177434800bacebfc685fc37bbe9efe4070d' + ], + [ + 'a1d0fcf2ec9de675b612136e5ce70d271c21417c9d2b8aaaac138599d0717940', + 'edd77f50bcb5a3cab2e90737309667f2641462a54070f3d519212d39c197a629' + ], + [ + 'e22fbe15c0af8ccc5780c0735f84dbe9a790badee8245c06c7ca37331cb36980', + 'a855babad5cd60c88b430a69f53a1a7a38289154964799be43d06d77d31da06' + ], + [ + '311091dd9860e8e20ee13473c1155f5f69635e394704eaa74009452246cfa9b3', + '66db656f87d1f04fffd1f04788c06830871ec5a64feee685bd80f0b1286d8374' + ], + [ + '34c1fd04d301be89b31c0442d3e6ac24883928b45a9340781867d4232ec2dbdf', + '9414685e97b1b5954bd46f730174136d57f1ceeb487443dc5321857ba73abee' + ], + [ + 'f219ea5d6b54701c1c14de5b557eb42a8d13f3abbcd08affcc2a5e6b049b8d63', + '4cb95957e83d40b0f73af4544cccf6b1f4b08d3c07b27fb8d8c2962a400766d1' + ], + [ + 'd7b8740f74a8fbaab1f683db8f45de26543a5490bca627087236912469a0b448', + 'fa77968128d9c92ee1010f337ad4717eff15db5ed3c049b3411e0315eaa4593b' + ], + [ + '32d31c222f8f6f0ef86f7c98d3a3335ead5bcd32abdd94289fe4d3091aa824bf', + '5f3032f5892156e39ccd3d7915b9e1da2e6dac9e6f26e961118d14b8462e1661' + ], + [ + '7461f371914ab32671045a155d9831ea8793d77cd59592c4340f86cbc18347b5', + '8ec0ba238b96bec0cbdddcae0aa442542eee1ff50c986ea6b39847b3cc092ff6' + ], + [ + 'ee079adb1df1860074356a25aa38206a6d716b2c3e67453d287698bad7b2b2d6', + '8dc2412aafe3be5c4c5f37e0ecc5f9f6a446989af04c4e25ebaac479ec1c8c1e' + ], + [ + '16ec93e447ec83f0467b18302ee620f7e65de331874c9dc72bfd8616ba9da6b5', + '5e4631150e62fb40d0e8c2a7ca5804a39d58186a50e497139626778e25b0674d' + ], + [ + 'eaa5f980c245f6f038978290afa70b6bd8855897f98b6aa485b96065d537bd99', + 'f65f5d3e292c2e0819a528391c994624d784869d7e6ea67fb18041024edc07dc' + ], + [ + '78c9407544ac132692ee1910a02439958ae04877151342ea96c4b6b35a49f51', + 'f3e0319169eb9b85d5404795539a5e68fa1fbd583c064d2462b675f194a3ddb4' + ], + [ + '494f4be219a1a77016dcd838431aea0001cdc8ae7a6fc688726578d9702857a5', + '42242a969283a5f339ba7f075e36ba2af925ce30d767ed6e55f4b031880d562c' + ], + [ + 'a598a8030da6d86c6bc7f2f5144ea549d28211ea58faa70ebf4c1e665c1fe9b5', + '204b5d6f84822c307e4b4a7140737aec23fc63b65b35f86a10026dbd2d864e6b' + ], + [ + 'c41916365abb2b5d09192f5f2dbeafec208f020f12570a184dbadc3e58595997', + '4f14351d0087efa49d245b328984989d5caf9450f34bfc0ed16e96b58fa9913' + ], + [ + '841d6063a586fa475a724604da03bc5b92a2e0d2e0a36acfe4c73a5514742881', + '73867f59c0659e81904f9a1c7543698e62562d6744c169ce7a36de01a8d6154' + ], + [ + '5e95bb399a6971d376026947f89bde2f282b33810928be4ded112ac4d70e20d5', + '39f23f366809085beebfc71181313775a99c9aed7d8ba38b161384c746012865' + ], + [ + '36e4641a53948fd476c39f8a99fd974e5ec07564b5315d8bf99471bca0ef2f66', + 'd2424b1b1abe4eb8164227b085c9aa9456ea13493fd563e06fd51cf5694c78fc' + ], + [ + '336581ea7bfbbb290c191a2f507a41cf5643842170e914faeab27c2c579f726', + 'ead12168595fe1be99252129b6e56b3391f7ab1410cd1e0ef3dcdcabd2fda224' + ], + [ + '8ab89816dadfd6b6a1f2634fcf00ec8403781025ed6890c4849742706bd43ede', + '6fdcef09f2f6d0a044e654aef624136f503d459c3e89845858a47a9129cdd24e' + ], + [ + '1e33f1a746c9c5778133344d9299fcaa20b0938e8acff2544bb40284b8c5fb94', + '60660257dd11b3aa9c8ed618d24edff2306d320f1d03010e33a7d2057f3b3b6' + ], + [ + '85b7c1dcb3cec1b7ee7f30ded79dd20a0ed1f4cc18cbcfcfa410361fd8f08f31', + '3d98a9cdd026dd43f39048f25a8847f4fcafad1895d7a633c6fed3c35e999511' + ], + [ + '29df9fbd8d9e46509275f4b125d6d45d7fbe9a3b878a7af872a2800661ac5f51', + 'b4c4fe99c775a606e2d8862179139ffda61dc861c019e55cd2876eb2a27d84b' + ], + [ + 'a0b1cae06b0a847a3fea6e671aaf8adfdfe58ca2f768105c8082b2e449fce252', + 'ae434102edde0958ec4b19d917a6a28e6b72da1834aff0e650f049503a296cf2' + ], + [ + '4e8ceafb9b3e9a136dc7ff67e840295b499dfb3b2133e4ba113f2e4c0e121e5', + 'cf2174118c8b6d7a4b48f6d534ce5c79422c086a63460502b827ce62a326683c' + ], + [ + 'd24a44e047e19b6f5afb81c7ca2f69080a5076689a010919f42725c2b789a33b', + '6fb8d5591b466f8fc63db50f1c0f1c69013f996887b8244d2cdec417afea8fa3' + ], + [ + 'ea01606a7a6c9cdd249fdfcfacb99584001edd28abbab77b5104e98e8e3b35d4', + '322af4908c7312b0cfbfe369f7a7b3cdb7d4494bc2823700cfd652188a3ea98d' + ], + [ + 'af8addbf2b661c8a6c6328655eb96651252007d8c5ea31be4ad196de8ce2131f', + '6749e67c029b85f52a034eafd096836b2520818680e26ac8f3dfbcdb71749700' + ], + [ + 'e3ae1974566ca06cc516d47e0fb165a674a3dabcfca15e722f0e3450f45889', + '2aeabe7e4531510116217f07bf4d07300de97e4874f81f533420a72eeb0bd6a4' + ], + [ + '591ee355313d99721cf6993ffed1e3e301993ff3ed258802075ea8ced397e246', + 'b0ea558a113c30bea60fc4775460c7901ff0b053d25ca2bdeee98f1a4be5d196' + ], + [ + '11396d55fda54c49f19aa97318d8da61fa8584e47b084945077cf03255b52984', + '998c74a8cd45ac01289d5833a7beb4744ff536b01b257be4c5767bea93ea57a4' + ], + [ + '3c5d2a1ba39c5a1790000738c9e0c40b8dcdfd5468754b6405540157e017aa7a', + 'b2284279995a34e2f9d4de7396fc18b80f9b8b9fdd270f6661f79ca4c81bd257' + ], + [ + 'cc8704b8a60a0defa3a99a7299f2e9c3fbc395afb04ac078425ef8a1793cc030', + 'bdd46039feed17881d1e0862db347f8cf395b74fc4bcdc4e940b74e3ac1f1b13' + ], + [ + 'c533e4f7ea8555aacd9777ac5cad29b97dd4defccc53ee7ea204119b2889b197', + '6f0a256bc5efdf429a2fb6242f1a43a2d9b925bb4a4b3a26bb8e0f45eb596096' + ], + [ + 'c14f8f2ccb27d6f109f6d08d03cc96a69ba8c34eec07bbcf566d48e33da6593', + 'c359d6923bb398f7fd4473e16fe1c28475b740dd098075e6c0e8649113dc3a38' + ], + [ + 'a6cbc3046bc6a450bac24789fa17115a4c9739ed75f8f21ce441f72e0b90e6ef', + '21ae7f4680e889bb130619e2c0f95a360ceb573c70603139862afd617fa9b9f' + ], + [ + '347d6d9a02c48927ebfb86c1359b1caf130a3c0267d11ce6344b39f99d43cc38', + '60ea7f61a353524d1c987f6ecec92f086d565ab687870cb12689ff1e31c74448' + ], + [ + 'da6545d2181db8d983f7dcb375ef5866d47c67b1bf31c8cf855ef7437b72656a', + '49b96715ab6878a79e78f07ce5680c5d6673051b4935bd897fea824b77dc208a' + ], + [ + 'c40747cc9d012cb1a13b8148309c6de7ec25d6945d657146b9d5994b8feb1111', + '5ca560753be2a12fc6de6caf2cb489565db936156b9514e1bb5e83037e0fa2d4' + ], + [ + '4e42c8ec82c99798ccf3a610be870e78338c7f713348bd34c8203ef4037f3502', + '7571d74ee5e0fb92a7a8b33a07783341a5492144cc54bcc40a94473693606437' + ], + [ + '3775ab7089bc6af823aba2e1af70b236d251cadb0c86743287522a1b3b0dedea', + 'be52d107bcfa09d8bcb9736a828cfa7fac8db17bf7a76a2c42ad961409018cf7' + ], + [ + 'cee31cbf7e34ec379d94fb814d3d775ad954595d1314ba8846959e3e82f74e26', + '8fd64a14c06b589c26b947ae2bcf6bfa0149ef0be14ed4d80f448a01c43b1c6d' + ], + [ + 'b4f9eaea09b6917619f6ea6a4eb5464efddb58fd45b1ebefcdc1a01d08b47986', + '39e5c9925b5a54b07433a4f18c61726f8bb131c012ca542eb24a8ac07200682a' + ], + [ + 'd4263dfc3d2df923a0179a48966d30ce84e2515afc3dccc1b77907792ebcc60e', + '62dfaf07a0f78feb30e30d6295853ce189e127760ad6cf7fae164e122a208d54' + ], + [ + '48457524820fa65a4f8d35eb6930857c0032acc0a4a2de422233eeda897612c4', + '25a748ab367979d98733c38a1fa1c2e7dc6cc07db2d60a9ae7a76aaa49bd0f77' + ], + [ + 'dfeeef1881101f2cb11644f3a2afdfc2045e19919152923f367a1767c11cceda', + 'ecfb7056cf1de042f9420bab396793c0c390bde74b4bbdff16a83ae09a9a7517' + ], + [ + '6d7ef6b17543f8373c573f44e1f389835d89bcbc6062ced36c82df83b8fae859', + 'cd450ec335438986dfefa10c57fea9bcc521a0959b2d80bbf74b190dca712d10' + ], + [ + 'e75605d59102a5a2684500d3b991f2e3f3c88b93225547035af25af66e04541f', + 'f5c54754a8f71ee540b9b48728473e314f729ac5308b06938360990e2bfad125' + ], + [ + 'eb98660f4c4dfaa06a2be453d5020bc99a0c2e60abe388457dd43fefb1ed620c', + '6cb9a8876d9cb8520609af3add26cd20a0a7cd8a9411131ce85f44100099223e' + ], + [ + '13e87b027d8514d35939f2e6892b19922154596941888336dc3563e3b8dba942', + 'fef5a3c68059a6dec5d624114bf1e91aac2b9da568d6abeb2570d55646b8adf1' + ], + [ + 'ee163026e9fd6fe017c38f06a5be6fc125424b371ce2708e7bf4491691e5764a', + '1acb250f255dd61c43d94ccc670d0f58f49ae3fa15b96623e5430da0ad6c62b2' + ], + [ + 'b268f5ef9ad51e4d78de3a750c2dc89b1e626d43505867999932e5db33af3d80', + '5f310d4b3c99b9ebb19f77d41c1dee018cf0d34fd4191614003e945a1216e423' + ], + [ + 'ff07f3118a9df035e9fad85eb6c7bfe42b02f01ca99ceea3bf7ffdba93c4750d', + '438136d603e858a3a5c440c38eccbaddc1d2942114e2eddd4740d098ced1f0d8' + ], + [ + '8d8b9855c7c052a34146fd20ffb658bea4b9f69e0d825ebec16e8c3ce2b526a1', + 'cdb559eedc2d79f926baf44fb84ea4d44bcf50fee51d7ceb30e2e7f463036758' + ], + [ + '52db0b5384dfbf05bfa9d472d7ae26dfe4b851ceca91b1eba54263180da32b63', + 'c3b997d050ee5d423ebaf66a6db9f57b3180c902875679de924b69d84a7b375' + ], + [ + 'e62f9490d3d51da6395efd24e80919cc7d0f29c3f3fa48c6fff543becbd43352', + '6d89ad7ba4876b0b22c2ca280c682862f342c8591f1daf5170e07bfd9ccafa7d' + ], + [ + '7f30ea2476b399b4957509c88f77d0191afa2ff5cb7b14fd6d8e7d65aaab1193', + 'ca5ef7d4b231c94c3b15389a5f6311e9daff7bb67b103e9880ef4bff637acaec' + ], + [ + '5098ff1e1d9f14fb46a210fada6c903fef0fb7b4a1dd1d9ac60a0361800b7a00', + '9731141d81fc8f8084d37c6e7542006b3ee1b40d60dfe5362a5b132fd17ddc0' + ], + [ + '32b78c7de9ee512a72895be6b9cbefa6e2f3c4ccce445c96b9f2c81e2778ad58', + 'ee1849f513df71e32efc3896ee28260c73bb80547ae2275ba497237794c8753c' + ], + [ + 'e2cb74fddc8e9fbcd076eef2a7c72b0ce37d50f08269dfc074b581550547a4f7', + 'd3aa2ed71c9dd2247a62df062736eb0baddea9e36122d2be8641abcb005cc4a4' + ], + [ + '8438447566d4d7bedadc299496ab357426009a35f235cb141be0d99cd10ae3a8', + 'c4e1020916980a4da5d01ac5e6ad330734ef0d7906631c4f2390426b2edd791f' + ], + [ + '4162d488b89402039b584c6fc6c308870587d9c46f660b878ab65c82c711d67e', + '67163e903236289f776f22c25fb8a3afc1732f2b84b4e95dbda47ae5a0852649' + ], + [ + '3fad3fa84caf0f34f0f89bfd2dcf54fc175d767aec3e50684f3ba4a4bf5f683d', + 'cd1bc7cb6cc407bb2f0ca647c718a730cf71872e7d0d2a53fa20efcdfe61826' + ], + [ + '674f2600a3007a00568c1a7ce05d0816c1fb84bf1370798f1c69532faeb1a86b', + '299d21f9413f33b3edf43b257004580b70db57da0b182259e09eecc69e0d38a5' + ], + [ + 'd32f4da54ade74abb81b815ad1fb3b263d82d6c692714bcff87d29bd5ee9f08f', + 'f9429e738b8e53b968e99016c059707782e14f4535359d582fc416910b3eea87' + ], + [ + '30e4e670435385556e593657135845d36fbb6931f72b08cb1ed954f1e3ce3ff6', + '462f9bce619898638499350113bbc9b10a878d35da70740dc695a559eb88db7b' + ], + [ + 'be2062003c51cc3004682904330e4dee7f3dcd10b01e580bf1971b04d4cad297', + '62188bc49d61e5428573d48a74e1c655b1c61090905682a0d5558ed72dccb9bc' + ], + [ + '93144423ace3451ed29e0fb9ac2af211cb6e84a601df5993c419859fff5df04a', + '7c10dfb164c3425f5c71a3f9d7992038f1065224f72bb9d1d902a6d13037b47c' + ], + [ + 'b015f8044f5fcbdcf21ca26d6c34fb8197829205c7b7d2a7cb66418c157b112c', + 'ab8c1e086d04e813744a655b2df8d5f83b3cdc6faa3088c1d3aea1454e3a1d5f' + ], + [ + 'd5e9e1da649d97d89e4868117a465a3a4f8a18de57a140d36b3f2af341a21b52', + '4cb04437f391ed73111a13cc1d4dd0db1693465c2240480d8955e8592f27447a' + ], + [ + 'd3ae41047dd7ca065dbf8ed77b992439983005cd72e16d6f996a5316d36966bb', + 'bd1aeb21ad22ebb22a10f0303417c6d964f8cdd7df0aca614b10dc14d125ac46' + ], + [ + '463e2763d885f958fc66cdd22800f0a487197d0a82e377b49f80af87c897b065', + 'bfefacdb0e5d0fd7df3a311a94de062b26b80c61fbc97508b79992671ef7ca7f' + ], + [ + '7985fdfd127c0567c6f53ec1bb63ec3158e597c40bfe747c83cddfc910641917', + '603c12daf3d9862ef2b25fe1de289aed24ed291e0ec6708703a5bd567f32ed03' + ], + [ + '74a1ad6b5f76e39db2dd249410eac7f99e74c59cb83d2d0ed5ff1543da7703e9', + 'cc6157ef18c9c63cd6193d83631bbea0093e0968942e8c33d5737fd790e0db08' + ], + [ + '30682a50703375f602d416664ba19b7fc9bab42c72747463a71d0896b22f6da3', + '553e04f6b018b4fa6c8f39e7f311d3176290d0e0f19ca73f17714d9977a22ff8' + ], + [ + '9e2158f0d7c0d5f26c3791efefa79597654e7a2b2464f52b1ee6c1347769ef57', + '712fcdd1b9053f09003a3481fa7762e9ffd7c8ef35a38509e2fbf2629008373' + ], + [ + '176e26989a43c9cfeba4029c202538c28172e566e3c4fce7322857f3be327d66', + 'ed8cc9d04b29eb877d270b4878dc43c19aefd31f4eee09ee7b47834c1fa4b1c3' + ], + [ + '75d46efea3771e6e68abb89a13ad747ecf1892393dfc4f1b7004788c50374da8', + '9852390a99507679fd0b86fd2b39a868d7efc22151346e1a3ca4726586a6bed8' + ], + [ + '809a20c67d64900ffb698c4c825f6d5f2310fb0451c869345b7319f645605721', + '9e994980d9917e22b76b061927fa04143d096ccc54963e6a5ebfa5f3f8e286c1' + ], + [ + '1b38903a43f7f114ed4500b4eac7083fdefece1cf29c63528d563446f972c180', + '4036edc931a60ae889353f77fd53de4a2708b26b6f5da72ad3394119daf408f9' + ] + ] + } + }; + + var curves_1 = createCommonjsModule(function (module, exports) { + + var curves = exports; + + + + + + var assert = utils_1$1.assert; + + function PresetCurve(options) { + if (options.type === 'short') + this.curve = new curve_1.short(options); + else if (options.type === 'edwards') + this.curve = new curve_1.edwards(options); + else if (options.type === 'mont') + this.curve = new curve_1.mont(options); + else throw new Error('Unknown curve type.'); + this.g = this.curve.g; + this.n = this.curve.n; + this.hash = options.hash; + + assert(this.g.validate(), 'Invalid curve'); + assert(this.g.mul(this.n).isInfinity(), 'Invalid curve, n*G != O'); + } + curves.PresetCurve = PresetCurve; + + function defineCurve(name, options) { + Object.defineProperty(curves, name, { + configurable: true, + enumerable: true, + get: function() { + var curve = new PresetCurve(options); + Object.defineProperty(curves, name, { + configurable: true, + enumerable: true, + value: curve + }); + return curve; + } + }); + } + + defineCurve('p192', { + type: 'short', + prime: 'p192', + p: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff', + a: 'ffffffff ffffffff ffffffff fffffffe ffffffff fffffffc', + b: '64210519 e59c80e7 0fa7e9ab 72243049 feb8deec c146b9b1', + n: 'ffffffff ffffffff ffffffff 99def836 146bc9b1 b4d22831', + hash: hash_1.sha256, + gRed: false, + g: [ + '188da80e b03090f6 7cbf20eb 43a18800 f4ff0afd 82ff1012', + '07192b95 ffc8da78 631011ed 6b24cdd5 73f977a1 1e794811' + ] + }); + + defineCurve('p224', { + type: 'short', + prime: 'p224', + p: 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001', + a: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff fffffffe', + b: 'b4050a85 0c04b3ab f5413256 5044b0b7 d7bfd8ba 270b3943 2355ffb4', + n: 'ffffffff ffffffff ffffffff ffff16a2 e0b8f03e 13dd2945 5c5c2a3d', + hash: hash_1.sha256, + gRed: false, + g: [ + 'b70e0cbd 6bb4bf7f 321390b9 4a03c1d3 56c21122 343280d6 115c1d21', + 'bd376388 b5f723fb 4c22dfe6 cd4375a0 5a074764 44d58199 85007e34' + ] + }); + + defineCurve('p256', { + type: 'short', + prime: null, + p: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff', + a: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff fffffffc', + b: '5ac635d8 aa3a93e7 b3ebbd55 769886bc 651d06b0 cc53b0f6 3bce3c3e 27d2604b', + n: 'ffffffff 00000000 ffffffff ffffffff bce6faad a7179e84 f3b9cac2 fc632551', + hash: hash_1.sha256, + gRed: false, + g: [ + '6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296', + '4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5' + ] + }); + + defineCurve('p384', { + type: 'short', + prime: null, + p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'fffffffe ffffffff 00000000 00000000 ffffffff', + a: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'fffffffe ffffffff 00000000 00000000 fffffffc', + b: 'b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112 0314088f ' + + '5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef', + n: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff c7634d81 ' + + 'f4372ddf 581a0db2 48b0a77a ecec196a ccc52973', + hash: hash_1.sha384, + gRed: false, + g: [ + 'aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98 59f741e0 82542a38 ' + + '5502f25d bf55296c 3a545e38 72760ab7', + '3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c e9da3113 b5f0b8c0 ' + + '0a60b1ce 1d7e819d 7a431d7c 90ea0e5f' + ] + }); + + defineCurve('p521', { + type: 'short', + prime: null, + p: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff ffffffff ffffffff ffffffff', + a: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff ffffffff ffffffff fffffffc', + b: '00000051 953eb961 8e1c9a1f 929a21a0 b68540ee a2da725b ' + + '99b315f3 b8b48991 8ef109e1 56193951 ec7e937b 1652c0bd ' + + '3bb1bf07 3573df88 3d2c34f1 ef451fd4 6b503f00', + n: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff fffffffa 51868783 bf2f966b 7fcc0148 ' + + 'f709a5d0 3bb5c9b8 899c47ae bb6fb71e 91386409', + hash: hash_1.sha512, + gRed: false, + g: [ + '000000c6 858e06b7 0404e9cd 9e3ecb66 2395b442 9c648139 ' + + '053fb521 f828af60 6b4d3dba a14b5e77 efe75928 fe1dc127 ' + + 'a2ffa8de 3348b3c1 856a429b f97e7e31 c2e5bd66', + '00000118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd9 98f54449 ' + + '579b4468 17afbd17 273e662c 97ee7299 5ef42640 c550b901 ' + + '3fad0761 353c7086 a272c240 88be9476 9fd16650' + ] + }); + + // https://tools.ietf.org/html/rfc7748#section-4.1 + defineCurve('curve25519', { + type: 'mont', + prime: 'p25519', + p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', + a: '76d06', + b: '1', + n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', + cofactor: '8', + hash: hash_1.sha256, + gRed: false, + g: [ + '9' + ] + }); + + defineCurve('ed25519', { + type: 'edwards', + prime: 'p25519', + p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', + a: '-1', + c: '1', + // -121665 * (121666^(-1)) (mod P) + d: '52036cee2b6ffe73 8cc740797779e898 00700a4d4141d8ab 75eb4dca135978a3', + n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', + cofactor: '8', + hash: hash_1.sha256, + gRed: false, + g: [ + '216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a', + // 4/5 + '6666666666666666666666666666666666666666666666666666666666666658' + ] + }); + + // https://tools.ietf.org/html/rfc5639#section-3.4 + defineCurve('brainpoolP256r1', { + type: 'short', + prime: null, + p: 'A9FB57DB A1EEA9BC 3E660A90 9D838D72 6E3BF623 D5262028 2013481D 1F6E5377', + a: '7D5A0975 FC2C3057 EEF67530 417AFFE7 FB8055C1 26DC5C6C E94A4B44 F330B5D9', + b: '26DC5C6C E94A4B44 F330B5D9 BBD77CBF 95841629 5CF7E1CE 6BCCDC18 FF8C07B6', + n: 'A9FB57DB A1EEA9BC 3E660A90 9D838D71 8C397AA3 B561A6F7 901E0E82 974856A7', + hash: hash_1.sha256, // or 384, or 512 + gRed: false, + g: [ + '8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262', + '547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997' + ] + }); + + // https://tools.ietf.org/html/rfc5639#section-3.6 + defineCurve('brainpoolP384r1', { + type: 'short', + prime: null, + p: '8CB91E82 A3386D28 0F5D6F7E 50E641DF 152F7109 ED5456B4 12B1DA19 7FB71123' + + 'ACD3A729 901D1A71 87470013 3107EC53', + a: '7BC382C6 3D8C150C 3C72080A CE05AFA0 C2BEA28E 4FB22787 139165EF BA91F90F' + + '8AA5814A 503AD4EB 04A8C7DD 22CE2826', + b: '04A8C7DD 22CE2826 8B39B554 16F0447C 2FB77DE1 07DCD2A6 2E880EA5 3EEB62D5' + + '7CB43902 95DBC994 3AB78696 FA504C11', + n: '8CB91E82 A3386D28 0F5D6F7E 50E641DF 152F7109 ED5456B3 1F166E6C AC0425A7' + + 'CF3AB6AF 6B7FC310 3B883202 E9046565', + hash: hash_1.sha384, // or 512 + gRed: false, + g: [ + '1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10' + + 'E8E826E03436D646AAEF87B2E247D4AF1E', + '8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129' + + '280E4646217791811142820341263C5315' + ] + }); + + // https://tools.ietf.org/html/rfc5639#section-3.7 + defineCurve('brainpoolP512r1', { + type: 'short', + prime: null, + p: 'AADD9DB8 DBE9C48B 3FD4E6AE 33C9FC07 CB308DB3 B3C9D20E D6639CCA 70330871' + + '7D4D9B00 9BC66842 AECDA12A E6A380E6 2881FF2F 2D82C685 28AA6056 583A48F3', + a: '7830A331 8B603B89 E2327145 AC234CC5 94CBDD8D 3DF91610 A83441CA EA9863BC' + + '2DED5D5A A8253AA1 0A2EF1C9 8B9AC8B5 7F1117A7 2BF2C7B9 E7C1AC4D 77FC94CA', + b: '3DF91610 A83441CA EA9863BC 2DED5D5A A8253AA1 0A2EF1C9 8B9AC8B5 7F1117A7' + + '2BF2C7B9 E7C1AC4D 77FC94CA DC083E67 984050B7 5EBAE5DD 2809BD63 8016F723', + n: 'AADD9DB8 DBE9C48B 3FD4E6AE 33C9FC07 CB308DB3 B3C9D20E D6639CCA 70330870' + + '553E5C41 4CA92619 41866119 7FAC1047 1DB1D381 085DDADD B5879682 9CA90069', + hash: hash_1.sha512, + gRed: false, + g: [ + '81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D009' + + '8EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822', + '7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F81' + + '11B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892' + ] + }); + + // https://en.bitcoin.it/wiki/Secp256k1 + var pre; + try { + pre = secp256k1; + } catch (e) { + pre = undefined; + } + + defineCurve('secp256k1', { + type: 'short', + prime: 'k256', + p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f', + a: '0', + b: '7', + n: 'ffffffff ffffffff ffffffff fffffffe baaedce6 af48a03b bfd25e8c d0364141', + h: '1', + hash: hash_1.sha256, + + // Precomputed endomorphism + beta: '7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee', + lambda: '5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72', + basis: [ + { + a: '3086d221a7d46bcde86c90e49284eb15', + b: '-e4437ed6010e88286f547fa90abfe4c3' + }, + { + a: '114ca50f7a8e2f3f657c1108d9d44cfd8', + b: '3086d221a7d46bcde86c90e49284eb15' + } + ], + + gRed: false, + g: [ + '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', + '483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', + pre + ] + }); + }); + + function HmacDRBG(options) { + if (!(this instanceof HmacDRBG)) + return new HmacDRBG(options); + this.hash = options.hash; + this.predResist = !!options.predResist; + + this.outLen = this.hash.outSize; + this.minEntropy = options.minEntropy || this.hash.hmacStrength; + + this._reseed = null; + this.reseedInterval = null; + this.K = null; + this.V = null; + + var entropy = utils_1.toArray(options.entropy, options.entropyEnc || 'hex'); + var nonce = utils_1.toArray(options.nonce, options.nonceEnc || 'hex'); + var pers = utils_1.toArray(options.pers, options.persEnc || 'hex'); + minimalisticAssert(entropy.length >= (this.minEntropy / 8), + 'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits'); + this._init(entropy, nonce, pers); + } + var hmacDrbg = HmacDRBG; + + HmacDRBG.prototype._init = function init(entropy, nonce, pers) { + var seed = entropy.concat(nonce).concat(pers); + + this.K = new Array(this.outLen / 8); + this.V = new Array(this.outLen / 8); + for (var i = 0; i < this.V.length; i++) { + this.K[i] = 0x00; + this.V[i] = 0x01; + } + + this._update(seed); + this._reseed = 1; + this.reseedInterval = 0x1000000000000; // 2^48 + }; + + HmacDRBG.prototype._hmac = function hmac() { + return new hash_1.hmac(this.hash, this.K); + }; + + HmacDRBG.prototype._update = function update(seed) { + var kmac = this._hmac() + .update(this.V) + .update([ 0x00 ]); + if (seed) + kmac = kmac.update(seed); + this.K = kmac.digest(); + this.V = this._hmac().update(this.V).digest(); + if (!seed) + return; + + this.K = this._hmac() + .update(this.V) + .update([ 0x01 ]) + .update(seed) + .digest(); + this.V = this._hmac().update(this.V).digest(); + }; + + HmacDRBG.prototype.reseed = function reseed(entropy, entropyEnc, add, addEnc) { + // Optional entropy enc + if (typeof entropyEnc !== 'string') { + addEnc = add; + add = entropyEnc; + entropyEnc = null; + } + + entropy = utils_1.toArray(entropy, entropyEnc); + add = utils_1.toArray(add, addEnc); + + minimalisticAssert(entropy.length >= (this.minEntropy / 8), + 'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits'); + + this._update(entropy.concat(add || [])); + this._reseed = 1; + }; + + HmacDRBG.prototype.generate = function generate(len, enc, add, addEnc) { + if (this._reseed > this.reseedInterval) + throw new Error('Reseed is required'); + + // Optional encoding + if (typeof enc !== 'string') { + addEnc = add; + add = enc; + enc = null; + } + + // Optional additional data + if (add) { + add = utils_1.toArray(add, addEnc || 'hex'); + this._update(add); + } + + var temp = []; + while (temp.length < len) { + this.V = this._hmac().update(this.V).digest(); + temp = temp.concat(this.V); + } + + var res = temp.slice(0, len); + this._update(add); + this._reseed++; + return utils_1.encode(res, enc); + }; + + var assert$5 = utils_1$1.assert; + + function KeyPair(ec, options) { + this.ec = ec; + this.priv = null; + this.pub = null; + + // KeyPair(ec, { priv: ..., pub: ... }) + if (options.priv) + this._importPrivate(options.priv, options.privEnc); + if (options.pub) + this._importPublic(options.pub, options.pubEnc); + } + var key = KeyPair; + + KeyPair.fromPublic = function fromPublic(ec, pub, enc) { + if (pub instanceof KeyPair) + return pub; + + return new KeyPair(ec, { + pub: pub, + pubEnc: enc + }); + }; + + KeyPair.fromPrivate = function fromPrivate(ec, priv, enc) { + if (priv instanceof KeyPair) + return priv; + + return new KeyPair(ec, { + priv: priv, + privEnc: enc + }); + }; + + // TODO: should not validate for X25519 + KeyPair.prototype.validate = function validate() { + var pub = this.getPublic(); + + if (pub.isInfinity()) + return { result: false, reason: 'Invalid public key' }; + if (!pub.validate()) + return { result: false, reason: 'Public key is not a point' }; + if (!pub.mul(this.ec.curve.n).isInfinity()) + return { result: false, reason: 'Public key * N != O' }; + + return { result: true, reason: null }; + }; + + KeyPair.prototype.getPublic = function getPublic(enc, compact) { + if (!this.pub) + this.pub = this.ec.g.mul(this.priv); + + if (!enc) + return this.pub; + + return this.pub.encode(enc, compact); + }; + + KeyPair.prototype.getPrivate = function getPrivate(enc) { + if (enc === 'hex') + return this.priv.toString(16, 2); + else + return this.priv; + }; + + KeyPair.prototype._importPrivate = function _importPrivate(key, enc) { + this.priv = new bn(key, enc || 16); + + // For Curve25519/Curve448 we have a specific procedure. + // TODO Curve448 + if (this.ec.curve.type === 'mont') { + var one = this.ec.curve.one; + var mask = one.ushln(255 - 3).sub(one).ushln(3); + this.priv = this.priv.or(one.ushln(255 - 1)); + this.priv = this.priv.and(mask); + } else + // Ensure that the priv won't be bigger than n, otherwise we may fail + // in fixed multiplication method + this.priv = this.priv.umod(this.ec.curve.n); + }; + + KeyPair.prototype._importPublic = function _importPublic(key, enc) { + if (key.x || key.y) { + // Montgomery points only have an `x` coordinate. + // Weierstrass/Edwards points on the other hand have both `x` and + // `y` coordinates. + if (this.ec.curve.type === 'mont') { + assert$5(key.x, 'Need x coordinate'); + } else if (this.ec.curve.type === 'short' || + this.ec.curve.type === 'edwards') { + assert$5(key.x && key.y, 'Need both x and y coordinate'); + } + this.pub = this.ec.curve.point(key.x, key.y); + return; + } + this.pub = this.ec.curve.decodePoint(key, enc); + }; + + // ECDH + KeyPair.prototype.derive = function derive(pub) { + return pub.mul(this.priv).getX(); + }; + + // ECDSA + KeyPair.prototype.sign = function sign(msg, enc, options) { + return this.ec.sign(msg, this, enc, options); + }; + + KeyPair.prototype.verify = function verify(msg, signature) { + return this.ec.verify(msg, signature, this); + }; + + KeyPair.prototype.inspect = function inspect() { + return ''; + }; + + var assert$6 = utils_1$1.assert; + + function Signature$1(options, enc) { + if (options instanceof Signature$1) + return options; + + if (this._importDER(options, enc)) + return; + + assert$6(options.r && options.s, 'Signature without r or s'); + this.r = new bn(options.r, 16); + this.s = new bn(options.s, 16); + if (options.recoveryParam === undefined) + this.recoveryParam = null; + else + this.recoveryParam = options.recoveryParam; + } + var signature$1 = Signature$1; + + function Position() { + this.place = 0; + } + + function getLength(buf, p) { + var initial = buf[p.place++]; + if (!(initial & 0x80)) { + return initial; + } + var octetLen = initial & 0xf; + var val = 0; + for (var i = 0, off = p.place; i < octetLen; i++, off++) { + val <<= 8; + val |= buf[off]; + } + p.place = off; + return val; + } + + function rmPadding(buf) { + var i = 0; + var len = buf.length - 1; + while (!buf[i] && !(buf[i + 1] & 0x80) && i < len) { + i++; + } + if (i === 0) { + return buf; + } + return buf.slice(i); + } + + Signature$1.prototype._importDER = function _importDER(data, enc) { + data = utils_1$1.toArray(data, enc); + var p = new Position(); + if (data[p.place++] !== 0x30) { + return false; + } + var len = getLength(data, p); + if ((len + p.place) !== data.length) { + return false; + } + if (data[p.place++] !== 0x02) { + return false; + } + var rlen = getLength(data, p); + var r = data.slice(p.place, rlen + p.place); + p.place += rlen; + if (data[p.place++] !== 0x02) { + return false; + } + var slen = getLength(data, p); + if (data.length !== slen + p.place) { + return false; + } + var s = data.slice(p.place, slen + p.place); + if (r[0] === 0 && (r[1] & 0x80)) { + r = r.slice(1); + } + if (s[0] === 0 && (s[1] & 0x80)) { + s = s.slice(1); + } + + this.r = new bn(r); + this.s = new bn(s); + this.recoveryParam = null; + + return true; + }; + + function constructLength(arr, len) { + if (len < 0x80) { + arr.push(len); + return; + } + var octets = 1 + (Math.log(len) / Math.LN2 >>> 3); + arr.push(octets | 0x80); + while (--octets) { + arr.push((len >>> (octets << 3)) & 0xff); + } + arr.push(len); + } + + Signature$1.prototype.toDER = function toDER(enc) { + var r = this.r.toArray(); + var s = this.s.toArray(); + + // Pad values + if (r[0] & 0x80) + r = [ 0 ].concat(r); + // Pad values + if (s[0] & 0x80) + s = [ 0 ].concat(s); + + r = rmPadding(r); + s = rmPadding(s); + + while (!s[0] && !(s[1] & 0x80)) { + s = s.slice(1); + } + var arr = [ 0x02 ]; + constructLength(arr, r.length); + arr = arr.concat(r); + arr.push(0x02); + constructLength(arr, s.length); + var backHalf = arr.concat(s); + var res = [ 0x30 ]; + constructLength(res, backHalf.length); + res = res.concat(backHalf); + return utils_1$1.encode(res, enc); + }; + + var assert$7 = utils_1$1.assert; + + + + + function EC(options) { + if (!(this instanceof EC)) + return new EC(options); + + // Shortcut `elliptic.ec(curve-name)` + if (typeof options === 'string') { + assert$7(curves_1.hasOwnProperty(options), 'Unknown curve ' + options); + + options = curves_1[options]; + } + + // Shortcut for `elliptic.ec(elliptic.curves.curveName)` + if (options instanceof curves_1.PresetCurve) + options = { curve: options }; + + this.curve = options.curve.curve; + this.n = this.curve.n; + this.nh = this.n.ushrn(1); + this.g = this.curve.g; + + // Point on curve + this.g = options.curve.g; + this.g.precompute(options.curve.n.bitLength() + 1); + + // Hash function for DRBG + this.hash = options.hash || options.curve.hash; + } + var ec = EC; + + EC.prototype.keyPair = function keyPair(options) { + return new key(this, options); + }; + + EC.prototype.keyFromPrivate = function keyFromPrivate(priv, enc) { + return key.fromPrivate(this, priv, enc); + }; + + EC.prototype.keyFromPublic = function keyFromPublic(pub, enc) { + return key.fromPublic(this, pub, enc); + }; + + EC.prototype.genKeyPair = function genKeyPair(options) { + if (!options) + options = {}; + + // Instantiate Hmac_DRBG + var drbg = new hmacDrbg({ + hash: this.hash, + pers: options.pers, + persEnc: options.persEnc || 'utf8', + entropy: options.entropy || brorand(this.hash.hmacStrength), + entropyEnc: options.entropy && options.entropyEnc || 'utf8', + nonce: this.n.toArray() + }); + + // Key generation for curve25519 is simpler + if (this.curve.type === 'mont') { + var priv = new bn(drbg.generate(32)); + return this.keyFromPrivate(priv); + } + + var bytes = this.n.byteLength(); + var ns2 = this.n.sub(new bn(2)); + do { + var priv = new bn(drbg.generate(bytes)); + if (priv.cmp(ns2) > 0) + continue; + + priv.iaddn(1); + return this.keyFromPrivate(priv); + } while (true); + }; + + EC.prototype._truncateToN = function truncateToN(msg, truncOnly, bitSize) { + bitSize = bitSize || msg.byteLength() * 8; + var delta = bitSize - this.n.bitLength(); + if (delta > 0) + msg = msg.ushrn(delta); + if (!truncOnly && msg.cmp(this.n) >= 0) + return msg.sub(this.n); + else + return msg; + }; + + EC.prototype.truncateMsg = function truncateMSG(msg) { + // Bit size is only determined correctly for Uint8Arrays and hex strings + var bitSize; + if (msg instanceof Uint8Array) { + bitSize = msg.byteLength * 8; + msg = this._truncateToN(new bn(msg, 16), false, bitSize); + } else if (typeof msg === 'string') { + bitSize = msg.length * 4; + msg = this._truncateToN(new bn(msg, 16), false, bitSize); + } else { + msg = this._truncateToN(new bn(msg, 16)); + } + return msg; + }; + + EC.prototype.sign = function sign(msg, key, enc, options) { + if (typeof enc === 'object') { + options = enc; + enc = null; + } + if (!options) + options = {}; + + key = this.keyFromPrivate(key, enc); + msg = this.truncateMsg(msg); + + // Zero-extend key to provide enough entropy + var bytes = this.n.byteLength(); + var bkey = key.getPrivate().toArray('be', bytes); + + // Zero-extend nonce to have the same byte size as N + var nonce = msg.toArray('be', bytes); + + // Instantiate Hmac_DRBG + var drbg = new hmacDrbg({ + hash: this.hash, + entropy: bkey, + nonce: nonce, + pers: options.pers, + persEnc: options.persEnc || 'utf8' + }); + + // Number of bytes to generate + var ns1 = this.n.sub(new bn(1)); + + for (var iter = 0; true; iter++) { + var k = options.k ? + options.k(iter) : + new bn(drbg.generate(this.n.byteLength())); + k = this._truncateToN(k, true); + if (k.cmpn(1) <= 0 || k.cmp(ns1) >= 0) + continue; + + var kp = this.g.mul(k); + if (kp.isInfinity()) + continue; + + var kpX = kp.getX(); + var r = kpX.umod(this.n); + if (r.cmpn(0) === 0) + continue; + + var s = k.invm(this.n).mul(r.mul(key.getPrivate()).iadd(msg)); + s = s.umod(this.n); + if (s.cmpn(0) === 0) + continue; + + var recoveryParam = (kp.getY().isOdd() ? 1 : 0) | + (kpX.cmp(r) !== 0 ? 2 : 0); + + // Use complement of `s`, if it is > `n / 2` + if (options.canonical && s.cmp(this.nh) > 0) { + s = this.n.sub(s); + recoveryParam ^= 1; + } + + return new signature$1({ r: r, s: s, recoveryParam: recoveryParam }); + } + }; + + EC.prototype.verify = function verify(msg, signature, key, enc) { + key = this.keyFromPublic(key, enc); + signature = new signature$1(signature, 'hex'); + // Fallback to the old code + var ret = this._verify(this.truncateMsg(msg), signature, key) || + this._verify(this._truncateToN(new bn(msg, 16)), signature, key); + return ret; + }; + + EC.prototype._verify = function _verify(msg, signature, key) { + // Perform primitive values validation + var r = signature.r; + var s = signature.s; + if (r.cmpn(1) < 0 || r.cmp(this.n) >= 0) + return false; + if (s.cmpn(1) < 0 || s.cmp(this.n) >= 0) + return false; + + // Validate signature + var sinv = s.invm(this.n); + var u1 = sinv.mul(msg).umod(this.n); + var u2 = sinv.mul(r).umod(this.n); + + if (!this.curve._maxwellTrick) { + var p = this.g.mulAdd(u1, key.getPublic(), u2); + if (p.isInfinity()) + return false; + + return p.getX().umod(this.n).cmp(r) === 0; + } + + // NOTE: Greg Maxwell's trick, inspired by: + // https://git.io/vad3K + + var p = this.g.jmulAdd(u1, key.getPublic(), u2); + if (p.isInfinity()) + return false; + + // Compare `p.x` of Jacobian point with `r`, + // this will do `p.x == r * p.z^2` instead of multiplying `p.x` by the + // inverse of `p.z^2` + return p.eqXToP(r); + }; + + EC.prototype.recoverPubKey = function(msg, signature, j, enc) { + assert$7((3 & j) === j, 'The recovery param is more than two bits'); + signature = new signature$1(signature, enc); + + var n = this.n; + var e = new bn(msg); + var r = signature.r; + var s = signature.s; + + // A set LSB signifies that the y-coordinate is odd + var isYOdd = j & 1; + var isSecondKey = j >> 1; + if (r.cmp(this.curve.p.umod(this.curve.n)) >= 0 && isSecondKey) + throw new Error('Unable to find sencond key candinate'); + + // 1.1. Let x = r + jn. + if (isSecondKey) + r = this.curve.pointFromX(r.add(this.curve.n), isYOdd); + else + r = this.curve.pointFromX(r, isYOdd); + + var rInv = signature.r.invm(n); + var s1 = n.sub(e).mul(rInv).umod(n); + var s2 = s.mul(rInv).umod(n); + + // 1.6.1 Compute Q = r^-1 (sR - eG) + // Q = r^-1 (sR + -eG) + return this.g.mulAdd(s1, r, s2); + }; + + EC.prototype.getKeyRecoveryParam = function(e, signature, Q, enc) { + signature = new signature$1(signature, enc); + if (signature.recoveryParam !== null) + return signature.recoveryParam; + + for (var i = 0; i < 4; i++) { + var Qprime; + try { + Qprime = this.recoverPubKey(e, signature, i); + } catch (e) { + continue; + } + + if (Qprime.eq(Q)) + return i; + } + throw new Error('Unable to find valid recovery factor'); + }; + + var assert$8 = utils_1$1.assert; + var parseBytes = utils_1$1.parseBytes; + var cachedProperty = utils_1$1.cachedProperty; + + /** + * @param {EDDSA} eddsa - instance + * @param {Object} params - public/private key parameters + * + * @param {Array} [params.secret] - secret seed bytes + * @param {Point} [params.pub] - public key point (aka `A` in eddsa terms) + * @param {Array} [params.pub] - public key point encoded as bytes + * + */ + function KeyPair$1(eddsa, params) { + this.eddsa = eddsa; + if (params.hasOwnProperty('secret')) + this._secret = parseBytes(params.secret); + if (eddsa.isPoint(params.pub)) + this._pub = params.pub; + else { + this._pubBytes = parseBytes(params.pub); + if (this._pubBytes && this._pubBytes.length === 33 && + this._pubBytes[0] === 0x40) + this._pubBytes = this._pubBytes.slice(1, 33); + if (this._pubBytes && this._pubBytes.length !== 32) + throw new Error('Unknown point compression format'); + } + } + + KeyPair$1.fromPublic = function fromPublic(eddsa, pub) { + if (pub instanceof KeyPair$1) + return pub; + return new KeyPair$1(eddsa, { pub: pub }); + }; + + KeyPair$1.fromSecret = function fromSecret(eddsa, secret) { + if (secret instanceof KeyPair$1) + return secret; + return new KeyPair$1(eddsa, { secret: secret }); + }; + + KeyPair$1.prototype.secret = function secret() { + return this._secret; + }; + + cachedProperty(KeyPair$1, 'pubBytes', function pubBytes() { + return this.eddsa.encodePoint(this.pub()); + }); + + cachedProperty(KeyPair$1, 'pub', function pub() { + if (this._pubBytes) + return this.eddsa.decodePoint(this._pubBytes); + return this.eddsa.g.mul(this.priv()); + }); + + cachedProperty(KeyPair$1, 'privBytes', function privBytes() { + var eddsa = this.eddsa; + var hash = this.hash(); + var lastIx = eddsa.encodingLength - 1; + + // https://tools.ietf.org/html/rfc8032#section-5.1.5 + var a = hash.slice(0, eddsa.encodingLength); + a[0] &= 248; + a[lastIx] &= 127; + a[lastIx] |= 64; + + return a; + }); + + cachedProperty(KeyPair$1, 'priv', function priv() { + return this.eddsa.decodeInt(this.privBytes()); + }); + + cachedProperty(KeyPair$1, 'hash', function hash() { + return this.eddsa.hash().update(this.secret()).digest(); + }); + + cachedProperty(KeyPair$1, 'messagePrefix', function messagePrefix() { + return this.hash().slice(this.eddsa.encodingLength); + }); + + KeyPair$1.prototype.sign = function sign(message) { + assert$8(this._secret, 'KeyPair can only verify'); + return this.eddsa.sign(message, this); + }; + + KeyPair$1.prototype.verify = function verify(message, sig) { + return this.eddsa.verify(message, sig, this); + }; + + KeyPair$1.prototype.getSecret = function getSecret(enc) { + assert$8(this._secret, 'KeyPair is public only'); + return utils_1$1.encode(this.secret(), enc); + }; + + KeyPair$1.prototype.getPublic = function getPublic(enc, compact) { + return utils_1$1.encode((compact ? [ 0x40 ] : []).concat(this.pubBytes()), enc); + }; + + var key$1 = KeyPair$1; + + var assert$9 = utils_1$1.assert; + var cachedProperty$1 = utils_1$1.cachedProperty; + var parseBytes$1 = utils_1$1.parseBytes; + + /** + * @param {EDDSA} eddsa - eddsa instance + * @param {Array|Object} sig - + * @param {Array|Point} [sig.R] - R point as Point or bytes + * @param {Array|bn} [sig.S] - S scalar as bn or bytes + * @param {Array} [sig.Rencoded] - R point encoded + * @param {Array} [sig.Sencoded] - S scalar encoded + */ + function Signature$2(eddsa, sig) { + this.eddsa = eddsa; + + if (typeof sig !== 'object') + sig = parseBytes$1(sig); + + if (Array.isArray(sig)) { + sig = { + R: sig.slice(0, eddsa.encodingLength), + S: sig.slice(eddsa.encodingLength) + }; + } + + assert$9(sig.R && sig.S, 'Signature without R or S'); + + if (eddsa.isPoint(sig.R)) + this._R = sig.R; + if (sig.S instanceof bn) + this._S = sig.S; + + this._Rencoded = Array.isArray(sig.R) ? sig.R : sig.Rencoded; + this._Sencoded = Array.isArray(sig.S) ? sig.S : sig.Sencoded; + } + + cachedProperty$1(Signature$2, 'S', function S() { + return this.eddsa.decodeInt(this.Sencoded()); + }); + + cachedProperty$1(Signature$2, 'R', function R() { + return this.eddsa.decodePoint(this.Rencoded()); + }); + + cachedProperty$1(Signature$2, 'Rencoded', function Rencoded() { + return this.eddsa.encodePoint(this.R()); + }); + + cachedProperty$1(Signature$2, 'Sencoded', function Sencoded() { + return this.eddsa.encodeInt(this.S()); + }); + + Signature$2.prototype.toBytes = function toBytes() { + return this.Rencoded().concat(this.Sencoded()); + }; + + Signature$2.prototype.toHex = function toHex() { + return utils_1$1.encode(this.toBytes(), 'hex').toUpperCase(); + }; + + var signature$2 = Signature$2; + + var assert$a = utils_1$1.assert; + var parseBytes$2 = utils_1$1.parseBytes; + + + + function EDDSA(curve) { + assert$a(curve === 'ed25519', 'only tested with ed25519 so far'); + + if (!(this instanceof EDDSA)) + return new EDDSA(curve); + + var curve = curves_1[curve].curve; + this.curve = curve; + this.g = curve.g; + this.g.precompute(curve.n.bitLength() + 1); + + this.pointClass = curve.point().constructor; + this.encodingLength = Math.ceil(curve.n.bitLength() / 8); + this.hash = hash_1.sha512; + } + + var eddsa$1 = EDDSA; + + /** + * @param {Array|String} message - message bytes + * @param {Array|String|KeyPair} secret - secret bytes or a keypair + * @returns {Signature} - signature + */ + EDDSA.prototype.sign = function sign(message, secret) { + message = parseBytes$2(message); + var key = this.keyFromSecret(secret); + var r = this.hashInt(key.messagePrefix(), message); + var R = this.g.mul(r); + var Rencoded = this.encodePoint(R); + var s_ = this.hashInt(Rencoded, key.pubBytes(), message) + .mul(key.priv()); + var S = r.add(s_).umod(this.curve.n); + return this.makeSignature({ R: R, S: S, Rencoded: Rencoded }); + }; + + /** + * @param {Array} message - message bytes + * @param {Array|String|Signature} sig - sig bytes + * @param {Array|String|Point|KeyPair} pub - public key + * @returns {Boolean} - true if public key matches sig of message + */ + EDDSA.prototype.verify = function verify(message, sig, pub) { + message = parseBytes$2(message); + sig = this.makeSignature(sig); + var key = this.keyFromPublic(pub); + var h = this.hashInt(sig.Rencoded(), key.pubBytes(), message); + var SG = this.g.mul(sig.S()); + var RplusAh = sig.R().add(key.pub().mul(h)); + return RplusAh.eq(SG); + }; + + EDDSA.prototype.hashInt = function hashInt() { + var hash = this.hash(); + for (var i = 0; i < arguments.length; i++) + hash.update(arguments[i]); + return utils_1$1.intFromLE(hash.digest()).umod(this.curve.n); + }; + + EDDSA.prototype.keyPair = function keyPair(options) { + return new key$1(this, options); + }; + + EDDSA.prototype.keyFromPublic = function keyFromPublic(pub) { + return key$1.fromPublic(this, pub); + }; + + EDDSA.prototype.keyFromSecret = function keyFromSecret(secret) { + return key$1.fromSecret(this, secret); + }; + + EDDSA.prototype.genKeyPair = function genKeyPair(options) { + if (!options) + options = {}; + + // Instantiate Hmac_DRBG + var drbg = new hmacDrbg({ + hash: this.hash, + pers: options.pers, + persEnc: options.persEnc || 'utf8', + entropy: options.entropy || brorand(this.hash.hmacStrength), + entropyEnc: options.entropy && options.entropyEnc || 'utf8', + nonce: this.curve.n.toArray() + }); + + return this.keyFromSecret(drbg.generate(32)); + }; + + EDDSA.prototype.makeSignature = function makeSignature(sig) { + if (sig instanceof signature$2) + return sig; + return new signature$2(this, sig); + }; + + /** + * * https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03#section-5.2 + * + * EDDSA defines methods for encoding and decoding points and integers. These are + * helper convenience methods, that pass along to utility functions implied + * parameters. + * + */ + EDDSA.prototype.encodePoint = function encodePoint(point) { + var enc = point.getY().toArray('le', this.encodingLength); + enc[this.encodingLength - 1] |= point.getX().isOdd() ? 0x80 : 0; + return enc; + }; + + EDDSA.prototype.decodePoint = function decodePoint(bytes) { + bytes = utils_1$1.parseBytes(bytes); + + var lastIx = bytes.length - 1; + var normed = bytes.slice(0, lastIx).concat(bytes[lastIx] & ~0x80); + var xIsOdd = (bytes[lastIx] & 0x80) !== 0; + + var y = utils_1$1.intFromLE(normed); + return this.curve.pointFromY(y, xIsOdd); + }; + + EDDSA.prototype.encodeInt = function encodeInt(num) { + return num.toArray('le', this.encodingLength); + }; + + EDDSA.prototype.decodeInt = function decodeInt(bytes) { + return utils_1$1.intFromLE(bytes); + }; + + EDDSA.prototype.isPoint = function isPoint(val) { + return val instanceof this.pointClass; + }; + + var elliptic_1 = createCommonjsModule(function (module, exports) { + + var elliptic = exports; + + elliptic.utils = utils_1$1; + elliptic.rand = brorand; + elliptic.curve = curve_1; + elliptic.curves = curves_1; + + // Protocols + elliptic.ec = ec; + elliptic.eddsa = eddsa$1; + }); + + var elliptic$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + 'default': elliptic_1, + __moduleExports: elliptic_1 + }); + + exports.AEADEncryptedDataPacket = AEADEncryptedDataPacket; + exports.CleartextMessage = CleartextMessage; + exports.CompressedDataPacket = CompressedDataPacket; + exports.LiteralDataPacket = LiteralDataPacket; + exports.MarkerPacket = MarkerPacket; + exports.Message = Message; + exports.OnePassSignaturePacket = OnePassSignaturePacket; + exports.PacketList = PacketList; + exports.PrivateKey = PrivateKey; + exports.PublicKey = PublicKey; + exports.PublicKeyEncryptedSessionKeyPacket = PublicKeyEncryptedSessionKeyPacket; + exports.PublicKeyPacket = PublicKeyPacket; + exports.PublicSubkeyPacket = PublicSubkeyPacket; + exports.SecretKeyPacket = SecretKeyPacket; + exports.SecretSubkeyPacket = SecretSubkeyPacket; + exports.Signature = Signature; + exports.SignaturePacket = SignaturePacket; + exports.Subkey = Subkey; + exports.SymEncryptedIntegrityProtectedDataPacket = SymEncryptedIntegrityProtectedDataPacket; + exports.SymEncryptedSessionKeyPacket = SymEncryptedSessionKeyPacket; + exports.SymmetricallyEncryptedDataPacket = SymmetricallyEncryptedDataPacket; + exports.TrustPacket = TrustPacket; + exports.UserAttributePacket = UserAttributePacket; + exports.UserIDPacket = UserIDPacket; + exports.armor = armor; + exports.config = defaultConfig; + exports.createCleartextMessage = createCleartextMessage; + exports.createMessage = createMessage; + exports.decrypt = decrypt$4; + exports.decryptKey = decryptKey; + exports.decryptSessionKeys = decryptSessionKeys; + exports.encrypt = encrypt$4; + exports.encryptKey = encryptKey; + exports.encryptSessionKey = encryptSessionKey; + exports.enums = enums; + exports.generateKey = generateKey; + exports.generateSessionKey = generateSessionKey$1; + exports.readCleartextMessage = readCleartextMessage; + exports.readKey = readKey; + exports.readKeys = readKeys; + exports.readMessage = readMessage; + exports.readPrivateKey = readPrivateKey; + exports.readPrivateKeys = readPrivateKeys; + exports.readSignature = readSignature; + exports.reformatKey = reformatKey; + exports.revokeKey = revokeKey; + exports.sign = sign$5; + exports.unarmor = unarmor; + exports.verify = verify$5; + + // -----BEGIN ADDED BY FLOWCRYPT---- + exports.Hash = Hash; + exports.Sha1 = Sha1; + exports.Sha256 = Sha256; + exports.readToEnd = readToEnd; + exports.util = util; + // -----END ADDED BY FLOWCRYPT----- + + Object.defineProperty(exports, '__esModule', { value: true }); + + return exports; + +}({})); diff --git a/Core/tooling/build.sh b/Core/tooling/build.sh index 4a3081238..5ae20f20a 100755 --- a/Core/tooling/build.sh +++ b/Core/tooling/build.sh @@ -4,7 +4,8 @@ set -euxo pipefail # fix openpgp in node_modules cp -f source/core/types/openpgp.d.ts node_modules/openpgp -cp -f source/lib/openpgp.js node_modules/openpgp/dist/node +cp -f source/lib/openpgp/openpgp.js node_modules/openpgp/dist +cp -f source/lib/openpgp/node/openpgp.js node_modules/openpgp/dist/node # clean up rm -rf build/ts build/bundles build/final/* From f433134f48b1317029150405656df937b7444381 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 07:07:45 +0200 Subject: [PATCH 086/179] wip --- Core/tooling/fix-bundles.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/tooling/fix-bundles.js b/Core/tooling/fix-bundles.js index 3a12d9ddb..830e080fb 100644 --- a/Core/tooling/fix-bundles.js +++ b/Core/tooling/fix-bundles.js @@ -70,7 +70,7 @@ const replace = (libSrc, regex, replacement) => { return libSrc.replace(regex, replacement); } -let openpgpLib = fs.readFileSync(`${libsDir}/openpgp.js`).toString(); +let openpgpLib = fs.readFileSync(`${libsDir}/openpgp/node/openpgp.js`).toString(); const openpgpLibNodeDev = openpgpLib; // dev node runs without any host, no modifications needed /* From 586f0a51914debcdbd3f572f7ad33167dac2a0a5 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 07:10:24 +0200 Subject: [PATCH 087/179] wip --- Core/tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/tsconfig.json b/Core/tsconfig.json index 84364385f..c02ecbc9a 100644 --- a/Core/tsconfig.json +++ b/Core/tsconfig.json @@ -22,7 +22,7 @@ "paths": { "openpgp": ["source/lib"] }, - "traceResolution": true, + "traceResolution": false, "typeRoots": [ "./source/core/types/", "./node_modules/@types/" From 86ca36c3c2e8f1ebc8d36803242c00b19b43b73b Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 07:18:32 +0200 Subject: [PATCH 088/179] wip --- Core/tooling/build.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Core/tooling/build.sh b/Core/tooling/build.sh index 5ae20f20a..31cb9a75a 100755 --- a/Core/tooling/build.sh +++ b/Core/tooling/build.sh @@ -6,6 +6,12 @@ set -euxo pipefail cp -f source/core/types/openpgp.d.ts node_modules/openpgp cp -f source/lib/openpgp/openpgp.js node_modules/openpgp/dist cp -f source/lib/openpgp/node/openpgp.js node_modules/openpgp/dist/node +for f in openpgp.min.js openpgp.min.js.map openpgp.min.mjs openpgp.min.mjs.map openpgp.mjs; do + if [ -f node_modules/openpgp/dist/$f ]; then rm -f node_modules/openpgp/dist/$f ; fi + if [ -f node_modules/openpgp/dist/node/$f ]; then rm -f node_modules/openpgp/dist/node/$f ; fi +done +sed -i 's/openpgp.min.js/openpgp.js/g' node_modules/openpgp/package.json +sed -i 's/openpgp.min.mjs/openpgp.mjs/g' node_modules/openpgp/package.json # clean up rm -rf build/ts build/bundles build/final/* From 9e00a7e47fcd475dd7454023bc6b0b6aa1e7912c Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 07:44:11 +0200 Subject: [PATCH 089/179] wip --- Core/tooling/build.sh | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/Core/tooling/build.sh b/Core/tooling/build.sh index 31cb9a75a..60dd057bf 100755 --- a/Core/tooling/build.sh +++ b/Core/tooling/build.sh @@ -13,6 +13,37 @@ done sed -i 's/openpgp.min.js/openpgp.js/g' node_modules/openpgp/package.json sed -i 's/openpgp.min.mjs/openpgp.mjs/g' node_modules/openpgp/package.json +extra_exports=" +// -----BEGIN ADDED BY FLOWCRYPT---- +exports.Hash = Hash; +exports.Sha1 = Sha1; +exports.Sha256 = Sha256; +exports.readToEnd = readToEnd; +exports.util = util; +// -----END ADDED BY FLOWCRYPT----- +" + +dist_js=node_modules/openpgp/dist/openpgp.js +tmp_js=${dist_js}.tmp +fc_added=$(grep 'BEGIN ADDED BY FLOWCRYPT' ${tmp_js} | wc -l) +if [ $fc_added = 0]; then + n=$(grep -n 'exports.verify' openpgp.js | cut -f1 -d':') + head -$n ${dist_js} >${tmp_js} + echo "$extra_exports" >>${tmp_js} + # https://stackoverflow.com/a/14110529/1540501 + { for ((i=1;i--;));do read;done;while read line;do echo $line;done } < ${dist_js} >>${tmp_js} +fi +mv -f ${tmp_js} ${dist_js} + +dist_js=node_modules/openpgp/dist/node/openpgp.js +tmp_js=${dist_js}.tmp +fc_added=$(grep 'BEGIN ADDED BY FLOWCRYPT' ${dist_js} | wc -l) +if [ $fc_added = 0]; then + cp -f ${dist_js} ${tmp_js} + echo "$extra_exports" >>${tmp_js} +fi +mv -f ${tmp_js} ${dist_js} + # clean up rm -rf build/ts build/bundles build/final/* mkdir -p build/final From 2b2ddfecdda881957f5f9baf7ee50f30a6a47a39 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 07:50:59 +0200 Subject: [PATCH 090/179] wip --- Core/tooling/build.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Core/tooling/build.sh b/Core/tooling/build.sh index 60dd057bf..ca86f0aed 100755 --- a/Core/tooling/build.sh +++ b/Core/tooling/build.sh @@ -27,11 +27,10 @@ dist_js=node_modules/openpgp/dist/openpgp.js tmp_js=${dist_js}.tmp fc_added=$(grep 'BEGIN ADDED BY FLOWCRYPT' ${tmp_js} | wc -l) if [ $fc_added = 0]; then - n=$(grep -n 'exports.verify' openpgp.js | cut -f1 -d':') + n=$(grep -n 'exports.verify' ${dist_js} | cut -f1 -d':') head -$n ${dist_js} >${tmp_js} echo "$extra_exports" >>${tmp_js} - # https://stackoverflow.com/a/14110529/1540501 - { for ((i=1;i--;));do read;done;while read line;do echo $line;done } < ${dist_js} >>${tmp_js} + tail -n +$((n+1)) ${dist_js} >>${tmp_js} fi mv -f ${tmp_js} ${dist_js} From a21e26c792d6292a9a4e644d088a53fff36b1ad2 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 07:58:58 +0200 Subject: [PATCH 091/179] wip --- Core/source/lib/openpgp/node/openpgp.js | 43554 ---------------------- Core/source/lib/openpgp/openpgp.js | 43537 --------------------- Core/tooling/build.sh | 16 +- Core/tooling/fix-bundles.js | 2 +- 4 files changed, 10 insertions(+), 87099 deletions(-) delete mode 100644 Core/source/lib/openpgp/node/openpgp.js delete mode 100644 Core/source/lib/openpgp/openpgp.js diff --git a/Core/source/lib/openpgp/node/openpgp.js b/Core/source/lib/openpgp/node/openpgp.js deleted file mode 100644 index 256bb30fb..000000000 --- a/Core/source/lib/openpgp/node/openpgp.js +++ /dev/null @@ -1,43554 +0,0 @@ -/*! OpenPGP.js v5.1.0 - 2022-01-24 - this is LGPL licensed code, see LICENSE/our website https://openpgpjs.org/ for more information. */ -'use strict'; - -const globalThis = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; - -Object.defineProperty(exports, '__esModule', { value: true }); - -var buffer = require('buffer'); -var stream$1 = require('stream'); -var crypto$3 = require('crypto'); -var zlib = require('zlib'); -var os = require('os'); -var util$1 = require('util'); -var asn1$2 = require('asn1.js'); - -function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } - -var buffer__default = /*#__PURE__*/_interopDefaultLegacy(buffer); -var stream__default = /*#__PURE__*/_interopDefaultLegacy(stream$1); -var crypto__default = /*#__PURE__*/_interopDefaultLegacy(crypto$3); -var zlib__default = /*#__PURE__*/_interopDefaultLegacy(zlib); -var os__default = /*#__PURE__*/_interopDefaultLegacy(os); -var util__default = /*#__PURE__*/_interopDefaultLegacy(util$1); -var asn1__default = /*#__PURE__*/_interopDefaultLegacy(asn1$2); - -const doneWritingPromise = Symbol('doneWritingPromise'); -const doneWritingResolve = Symbol('doneWritingResolve'); -const doneWritingReject = Symbol('doneWritingReject'); - -const readingIndex = Symbol('readingIndex'); - -class ArrayStream extends Array { - constructor() { - super(); - this[doneWritingPromise] = new Promise((resolve, reject) => { - this[doneWritingResolve] = resolve; - this[doneWritingReject] = reject; - }); - this[doneWritingPromise].catch(() => {}); - } -} - -ArrayStream.prototype.getReader = function() { - if (this[readingIndex] === undefined) { - this[readingIndex] = 0; - } - return { - read: async () => { - await this[doneWritingPromise]; - if (this[readingIndex] === this.length) { - return { value: undefined, done: true }; - } - return { value: this[this[readingIndex]++], done: false }; - } - }; -}; - -ArrayStream.prototype.readToEnd = async function(join) { - await this[doneWritingPromise]; - const result = join(this.slice(this[readingIndex])); - this.length = 0; - return result; -}; - -ArrayStream.prototype.clone = function() { - const clone = new ArrayStream(); - clone[doneWritingPromise] = this[doneWritingPromise].then(() => { - clone.push(...this); - }); - return clone; -}; - -/** - * Check whether data is an ArrayStream - * @param {Any} input data to check - * @returns {boolean} - */ -function isArrayStream(input) { - return input && input.getReader && Array.isArray(input); -} - -/** - * A wrapper class over the native WritableStreamDefaultWriter. - * It also lets you "write data to" array streams instead of streams. - * @class - */ -function Writer(input) { - if (!isArrayStream(input)) { - const writer = input.getWriter(); - const releaseLock = writer.releaseLock; - writer.releaseLock = () => { - writer.closed.catch(function() {}); - releaseLock.call(writer); - }; - return writer; - } - this.stream = input; -} - -/** - * Write a chunk of data. - * @returns {Promise} - * @async - */ -Writer.prototype.write = async function(chunk) { - this.stream.push(chunk); -}; - -/** - * Close the stream. - * @returns {Promise} - * @async - */ -Writer.prototype.close = async function() { - this.stream[doneWritingResolve](); -}; - -/** - * Error the stream. - * @returns {Promise} - * @async - */ -Writer.prototype.abort = async function(reason) { - this.stream[doneWritingReject](reason); - return reason; -}; - -/** - * Release the writer's lock. - * @returns {undefined} - * @async - */ -Writer.prototype.releaseLock = function() {}; - -const isNode = typeof globalThis.process === 'object' && - typeof globalThis.process.versions === 'object'; - -const NodeReadableStream = isNode && stream__default['default'].Readable; - -/** - * Check whether data is a Stream, and if so of which type - * @param {Any} input data to check - * @returns {'web'|'ponyfill'|'node'|'array'|'web-like'|false} - */ -function isStream(input) { - if (isArrayStream(input)) { - return 'array'; - } - if (globalThis.ReadableStream && globalThis.ReadableStream.prototype.isPrototypeOf(input)) { - return 'web'; - } - if (ReadableStream && ReadableStream.prototype.isPrototypeOf(input)) { - return 'ponyfill'; - } - if (NodeReadableStream && NodeReadableStream.prototype.isPrototypeOf(input)) { - return 'node'; - } - if (input && input.getReader) { - return 'web-like'; - } - return false; -} - -/** - * Check whether data is a Uint8Array - * @param {Any} input data to check - * @returns {Boolean} - */ -function isUint8Array(input) { - return Uint8Array.prototype.isPrototypeOf(input); -} - -/** - * Concat Uint8Arrays - * @param {Array} Array of Uint8Arrays to concatenate - * @returns {Uint8array} Concatenated array - */ -function concatUint8Array(arrays) { - if (arrays.length === 1) return arrays[0]; - - let totalLength = 0; - for (let i = 0; i < arrays.length; i++) { - if (!isUint8Array(arrays[i])) { - throw new Error('concatUint8Array: Data must be in the form of a Uint8Array'); - } - - totalLength += arrays[i].length; - } - - const result = new Uint8Array(totalLength); - let pos = 0; - arrays.forEach(function (element) { - result.set(element, pos); - pos += element.length; - }); - - return result; -} - -const NodeBuffer = isNode && buffer__default['default'].Buffer; -const NodeReadableStream$1 = isNode && stream__default['default'].Readable; - -/** - * Web / node stream conversion functions - * From https://github.com/gwicke/node-web-streams - */ - -let nodeToWeb; -let webToNode; - -if (NodeReadableStream$1) { - - /** - * Convert a Node Readable Stream to a Web ReadableStream - * @param {Readable} nodeStream - * @returns {ReadableStream} - */ - nodeToWeb = function(nodeStream) { - let canceled = false; - return new ReadableStream({ - start(controller) { - nodeStream.pause(); - nodeStream.on('data', chunk => { - if (canceled) { - return; - } - if (NodeBuffer.isBuffer(chunk)) { - chunk = new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength); - } - controller.enqueue(chunk); - nodeStream.pause(); - }); - nodeStream.on('end', () => { - if (canceled) { - return; - } - controller.close(); - }); - nodeStream.on('error', e => controller.error(e)); - }, - pull() { - nodeStream.resume(); - }, - cancel(reason) { - canceled = true; - nodeStream.destroy(reason); - } - }); - }; - - - class NodeReadable extends NodeReadableStream$1 { - constructor(webStream, options) { - super(options); - this._reader = getReader(webStream); - } - - async _read(size) { - try { - while (true) { - const { done, value } = await this._reader.read(); - if (done) { - this.push(null); - break; - } - if (!this.push(value) || this._cancelling) { - this._reading = false; - break; - } - } - } catch(e) { - this.emit('error', e); - } - } - - _destroy(reason) { - this._reader.cancel(reason); - } - } - - /** - * Convert a Web ReadableStream to a Node Readable Stream - * @param {ReadableStream} webStream - * @param {Object} options - * @returns {Readable} - */ - webToNode = function(webStream, options) { - return new NodeReadable(webStream, options); - }; - -} - -const doneReadingSet = new WeakSet(); -const externalBuffer = Symbol('externalBuffer'); - -/** - * A wrapper class over the native ReadableStreamDefaultReader. - * This additionally implements pushing back data on the stream, which - * lets us implement peeking and a host of convenience functions. - * It also lets you read data other than streams, such as a Uint8Array. - * @class - */ -function Reader(input) { - this.stream = input; - if (input[externalBuffer]) { - this[externalBuffer] = input[externalBuffer].slice(); - } - if (isArrayStream(input)) { - const reader = input.getReader(); - this._read = reader.read.bind(reader); - this._releaseLock = () => {}; - this._cancel = () => {}; - return; - } - let streamType = isStream(input); - if (streamType === 'node') { - input = nodeToWeb(input); - } - if (streamType) { - const reader = input.getReader(); - this._read = reader.read.bind(reader); - this._releaseLock = () => { - reader.closed.catch(function() {}); - reader.releaseLock(); - }; - this._cancel = reader.cancel.bind(reader); - return; - } - let doneReading = false; - this._read = async () => { - if (doneReading || doneReadingSet.has(input)) { - return { value: undefined, done: true }; - } - doneReading = true; - return { value: input, done: false }; - }; - this._releaseLock = () => { - if (doneReading) { - try { - doneReadingSet.add(input); - } catch(e) {} - } - }; -} - -/** - * Read a chunk of data. - * @returns {Promise} Either { done: false, value: Uint8Array | String } or { done: true, value: undefined } - * @async - */ -Reader.prototype.read = async function() { - if (this[externalBuffer] && this[externalBuffer].length) { - const value = this[externalBuffer].shift(); - return { done: false, value }; - } - return this._read(); -}; - -/** - * Allow others to read the stream. - */ -Reader.prototype.releaseLock = function() { - if (this[externalBuffer]) { - this.stream[externalBuffer] = this[externalBuffer]; - } - this._releaseLock(); -}; - -/** - * Cancel the stream. - */ -Reader.prototype.cancel = function(reason) { - return this._cancel(reason); -}; - -/** - * Read up to and including the first \n character. - * @returns {Promise} - * @async - */ -Reader.prototype.readLine = async function() { - let buffer = []; - let returnVal; - while (!returnVal) { - let { done, value } = await this.read(); - value += ''; - if (done) { - if (buffer.length) return concat(buffer); - return; - } - const lineEndIndex = value.indexOf('\n') + 1; - if (lineEndIndex) { - returnVal = concat(buffer.concat(value.substr(0, lineEndIndex))); - buffer = []; - } - if (lineEndIndex !== value.length) { - buffer.push(value.substr(lineEndIndex)); - } - } - this.unshift(...buffer); - return returnVal; -}; - -/** - * Read a single byte/character. - * @returns {Promise} - * @async - */ -Reader.prototype.readByte = async function() { - const { done, value } = await this.read(); - if (done) return; - const byte = value[0]; - this.unshift(slice(value, 1)); - return byte; -}; - -/** - * Read a specific amount of bytes/characters, unless the stream ends before that amount. - * @returns {Promise} - * @async - */ -Reader.prototype.readBytes = async function(length) { - const buffer = []; - let bufferLength = 0; - while (true) { - const { done, value } = await this.read(); - if (done) { - if (buffer.length) return concat(buffer); - return; - } - buffer.push(value); - bufferLength += value.length; - if (bufferLength >= length) { - const bufferConcat = concat(buffer); - this.unshift(slice(bufferConcat, length)); - return slice(bufferConcat, 0, length); - } - } -}; - -/** - * Peek (look ahead) a specific amount of bytes/characters, unless the stream ends before that amount. - * @returns {Promise} - * @async - */ -Reader.prototype.peekBytes = async function(length) { - const bytes = await this.readBytes(length); - this.unshift(bytes); - return bytes; -}; - -/** - * Push data to the front of the stream. - * Data must have been read in the last call to read*. - * @param {...(Uint8Array|String|Undefined)} values - */ -Reader.prototype.unshift = function(...values) { - if (!this[externalBuffer]) { - this[externalBuffer] = []; - } - if ( - values.length === 1 && isUint8Array(values[0]) && - this[externalBuffer].length && values[0].length && - this[externalBuffer][0].byteOffset >= values[0].length - ) { - this[externalBuffer][0] = new Uint8Array( - this[externalBuffer][0].buffer, - this[externalBuffer][0].byteOffset - values[0].length, - this[externalBuffer][0].byteLength + values[0].length - ); - return; - } - this[externalBuffer].unshift(...values.filter(value => value && value.length)); -}; - -/** - * Read the stream to the end and return its contents, concatenated by the join function (defaults to streams.concat). - * @param {Function} join - * @returns {Promise} the return value of join() - * @async - */ -Reader.prototype.readToEnd = async function(join=concat) { - const result = []; - while (true) { - const { done, value } = await this.read(); - if (done) break; - result.push(value); - } - return join(result); -}; - -let { ReadableStream, WritableStream, TransformStream } = globalThis; - -let toPonyfillReadable, toNativeReadable; - -async function loadStreamsPonyfill() { - if (TransformStream) { - return; - } - - const [ponyfill, adapter] = await Promise.all([ - Promise.resolve().then(function () { return ponyfill_es6; }), - Promise.resolve().then(function () { return webStreamsAdapter; }) - ]); - - ({ ReadableStream, WritableStream, TransformStream } = ponyfill); - - const { createReadableStreamWrapper } = adapter; - - if (globalThis.ReadableStream && ReadableStream !== globalThis.ReadableStream) { - toPonyfillReadable = createReadableStreamWrapper(ReadableStream); - toNativeReadable = createReadableStreamWrapper(globalThis.ReadableStream); - } -} - -const NodeBuffer$1 = isNode && buffer__default['default'].Buffer; - -/** - * Convert data to Stream - * @param {ReadableStream|Uint8array|String} input data to convert - * @returns {ReadableStream} Converted data - */ -function toStream(input) { - let streamType = isStream(input); - if (streamType === 'node') { - return nodeToWeb(input); - } - if (streamType === 'web' && toPonyfillReadable) { - return toPonyfillReadable(input); - } - if (streamType) { - return input; - } - return new ReadableStream({ - start(controller) { - controller.enqueue(input); - controller.close(); - } - }); -} - -/** - * Convert data to ArrayStream - * @param {Object} input data to convert - * @returns {ArrayStream} Converted data - */ -function toArrayStream(input) { - if (isStream(input)) { - return input; - } - const stream = new ArrayStream(); - (async () => { - const writer = getWriter(stream); - await writer.write(input); - await writer.close(); - })(); - return stream; -} - -/** - * Concat a list of Uint8Arrays, Strings or Streams - * The caller should not mix Uint8Arrays with Strings, but may mix Streams with non-Streams. - * @param {Array} Array of Uint8Arrays/Strings/Streams to concatenate - * @returns {Uint8array|String|ReadableStream} Concatenated array - */ -function concat(list) { - if (list.some(stream => isStream(stream) && !isArrayStream(stream))) { - return concatStream(list); - } - if (list.some(stream => isArrayStream(stream))) { - return concatArrayStream(list); - } - if (typeof list[0] === 'string') { - return list.join(''); - } - if (NodeBuffer$1 && NodeBuffer$1.isBuffer(list[0])) { - return NodeBuffer$1.concat(list); - } - return concatUint8Array(list); -} - -/** - * Concat a list of Streams - * @param {Array} list Array of Uint8Arrays/Strings/Streams to concatenate - * @returns {ReadableStream} Concatenated list - */ -function concatStream(list) { - list = list.map(toStream); - const transform = transformWithCancel(async function(reason) { - await Promise.all(transforms.map(stream => cancel(stream, reason))); - }); - let prev = Promise.resolve(); - const transforms = list.map((stream, i) => transformPair(stream, (readable, writable) => { - prev = prev.then(() => pipe(readable, transform.writable, { - preventClose: i !== list.length - 1 - })); - return prev; - })); - return transform.readable; -} - -/** - * Concat a list of ArrayStreams - * @param {Array} list Array of Uint8Arrays/Strings/ArrayStreams to concatenate - * @returns {ArrayStream} Concatenated streams - */ -function concatArrayStream(list) { - const result = new ArrayStream(); - let prev = Promise.resolve(); - list.forEach((stream, i) => { - prev = prev.then(() => pipe(stream, result, { - preventClose: i !== list.length - 1 - })); - return prev; - }); - return result; -} - -/** - * Get a Reader - * @param {ReadableStream|Uint8array|String} input - * @returns {Reader} - */ -function getReader(input) { - return new Reader(input); -} - -/** - * Get a Writer - * @param {WritableStream} input - * @returns {Writer} - */ -function getWriter(input) { - return new Writer(input); -} - -/** - * Pipe a readable stream to a writable stream. Don't throw on input stream errors, but forward them to the output stream. - * @param {ReadableStream|Uint8array|String} input - * @param {WritableStream} target - * @param {Object} (optional) options - * @returns {Promise} Promise indicating when piping has finished (input stream closed or errored) - * @async - */ -async function pipe(input, target, { - preventClose = false, - preventAbort = false, - preventCancel = false -} = {}) { - if (isStream(input) && !isArrayStream(input)) { - input = toStream(input); - try { - if (input[externalBuffer]) { - const writer = getWriter(target); - for (let i = 0; i < input[externalBuffer].length; i++) { - await writer.ready; - await writer.write(input[externalBuffer][i]); - } - writer.releaseLock(); - } - await input.pipeTo(target, { - preventClose, - preventAbort, - preventCancel - }); - } catch(e) {} - return; - } - input = toArrayStream(input); - const reader = getReader(input); - const writer = getWriter(target); - try { - while (true) { - await writer.ready; - const { done, value } = await reader.read(); - if (done) { - if (!preventClose) await writer.close(); - break; - } - await writer.write(value); - } - } catch (e) { - if (!preventAbort) await writer.abort(e); - } finally { - reader.releaseLock(); - writer.releaseLock(); - } -} - -/** - * Pipe a readable stream through a transform stream. - * @param {ReadableStream|Uint8array|String} input - * @param {Object} (optional) options - * @returns {ReadableStream} transformed stream - */ -function transformRaw(input, options) { - const transformStream = new TransformStream(options); - pipe(input, transformStream.writable); - return transformStream.readable; -} - -/** - * Create a cancelable TransformStream. - * @param {Function} cancel - * @returns {TransformStream} - */ -function transformWithCancel(cancel) { - let pulled = false; - let backpressureChangePromiseResolve; - let outputController; - return { - readable: new ReadableStream({ - start(controller) { - outputController = controller; - }, - pull() { - if (backpressureChangePromiseResolve) { - backpressureChangePromiseResolve(); - } else { - pulled = true; - } - }, - cancel - }, {highWaterMark: 0}), - writable: new WritableStream({ - write: async function(chunk) { - outputController.enqueue(chunk); - if (!pulled) { - await new Promise(resolve => { - backpressureChangePromiseResolve = resolve; - }); - backpressureChangePromiseResolve = null; - } else { - pulled = false; - } - }, - close: outputController.close.bind(outputController), - abort: outputController.error.bind(outputController) - }) - }; -} - -/** - * Transform a stream using helper functions which are called on each chunk, and on stream close, respectively. - * @param {ReadableStream|Uint8array|String} input - * @param {Function} process - * @param {Function} finish - * @returns {ReadableStream|Uint8array|String} - */ -function transform(input, process = () => undefined, finish = () => undefined) { - if (isArrayStream(input)) { - const output = new ArrayStream(); - (async () => { - const data = await readToEnd(input); - const result1 = process(data); - const result2 = finish(); - let result; - if (result1 !== undefined && result2 !== undefined) result = concat([result1, result2]); - else result = result1 !== undefined ? result1 : result2; - const writer = getWriter(output); - await writer.write(result); - await writer.close(); - })(); - return output; - } - if (isStream(input)) { - return transformRaw(input, { - async transform(value, controller) { - try { - const result = await process(value); - if (result !== undefined) controller.enqueue(result); - } catch(e) { - controller.error(e); - } - }, - async flush(controller) { - try { - const result = await finish(); - if (result !== undefined) controller.enqueue(result); - } catch(e) { - controller.error(e); - } - } - }); - } - const result1 = process(input); - const result2 = finish(); - if (result1 !== undefined && result2 !== undefined) return concat([result1, result2]); - return result1 !== undefined ? result1 : result2; -} - -/** - * Transform a stream using a helper function which is passed a readable and a writable stream. - * This function also maintains the possibility to cancel the input stream, - * and does so on cancelation of the output stream, despite cancelation - * normally being impossible when the input stream is being read from. - * @param {ReadableStream|Uint8array|String} input - * @param {Function} fn - * @returns {ReadableStream} - */ -function transformPair(input, fn) { - if (isStream(input) && !isArrayStream(input)) { - let incomingTransformController; - const incoming = new TransformStream({ - start(controller) { - incomingTransformController = controller; - } - }); - - const pipeDonePromise = pipe(input, incoming.writable); - - const outgoing = transformWithCancel(async function() { - incomingTransformController.error(new Error('Readable side was canceled.')); - await pipeDonePromise; - await new Promise(setTimeout); - }); - fn(incoming.readable, outgoing.writable); - return outgoing.readable; - } - input = toArrayStream(input); - const output = new ArrayStream(); - fn(input, output); - return output; -} - -/** - * Parse a stream using a helper function which is passed a Reader. - * The reader additionally has a remainder() method which returns a - * stream pointing to the remainder of input, and is linked to input - * for cancelation. - * @param {ReadableStream|Uint8array|String} input - * @param {Function} fn - * @returns {Any} the return value of fn() - */ -function parse(input, fn) { - let returnValue; - const transformed = transformPair(input, (readable, writable) => { - const reader = getReader(readable); - reader.remainder = () => { - reader.releaseLock(); - pipe(readable, writable); - return transformed; - }; - returnValue = fn(reader); - }); - return returnValue; -} - -/** - * Tee a Stream for reading it twice. The input stream can no longer be read after tee()ing. - * Reading either of the two returned streams will pull from the input stream. - * The input stream will only be canceled if both of the returned streams are canceled. - * @param {ReadableStream|Uint8array|String} input - * @returns {Array} array containing two copies of input - */ -function tee(input) { - if (isArrayStream(input)) { - throw new Error('ArrayStream cannot be tee()d, use clone() instead'); - } - if (isStream(input)) { - const teed = toStream(input).tee(); - teed[0][externalBuffer] = teed[1][externalBuffer] = input[externalBuffer]; - return teed; - } - return [slice(input), slice(input)]; -} - -/** - * Clone a Stream for reading it twice. The input stream can still be read after clone()ing. - * Reading from the clone will pull from the input stream. - * The input stream will only be canceled if both the clone and the input stream are canceled. - * @param {ReadableStream|Uint8array|String} input - * @returns {ReadableStream|Uint8array|String} cloned input - */ -function clone(input) { - if (isArrayStream(input)) { - return input.clone(); - } - if (isStream(input)) { - const teed = tee(input); - overwrite(input, teed[0]); - return teed[1]; - } - return slice(input); -} - -/** - * Clone a Stream for reading it twice. Data will arrive at the same rate as the input stream is being read. - * Reading from the clone will NOT pull from the input stream. Data only arrives when reading the input stream. - * The input stream will NOT be canceled if the clone is canceled, only if the input stream are canceled. - * If the input stream is canceled, the clone will be errored. - * @param {ReadableStream|Uint8array|String} input - * @returns {ReadableStream|Uint8array|String} cloned input - */ -function passiveClone(input) { - if (isArrayStream(input)) { - return clone(input); - } - if (isStream(input)) { - return new ReadableStream({ - start(controller) { - const transformed = transformPair(input, async (readable, writable) => { - const reader = getReader(readable); - const writer = getWriter(writable); - try { - while (true) { - await writer.ready; - const { done, value } = await reader.read(); - if (done) { - try { controller.close(); } catch(e) {} - await writer.close(); - return; - } - try { controller.enqueue(value); } catch(e) {} - await writer.write(value); - } - } catch(e) { - controller.error(e); - await writer.abort(e); - } - }); - overwrite(input, transformed); - } - }); - } - return slice(input); -} - -/** - * Modify a stream object to point to a different stream object. - * This is used internally by clone() and passiveClone() to provide an abstraction over tee(). - * @param {ReadableStream} input - * @param {ReadableStream} clone - */ -function overwrite(input, clone) { - // Overwrite input.getReader, input.locked, etc to point to clone - Object.entries(Object.getOwnPropertyDescriptors(input.constructor.prototype)).forEach(([name, descriptor]) => { - if (name === 'constructor') { - return; - } - if (descriptor.value) { - descriptor.value = descriptor.value.bind(clone); - } else { - descriptor.get = descriptor.get.bind(clone); - } - Object.defineProperty(input, name, descriptor); - }); -} - -/** - * Return a stream pointing to a part of the input stream. - * @param {ReadableStream|Uint8array|String} input - * @returns {ReadableStream|Uint8array|String} clone - */ -function slice(input, begin=0, end=Infinity) { - if (isArrayStream(input)) { - throw new Error('Not implemented'); - } - if (isStream(input)) { - if (begin >= 0 && end >= 0) { - let bytesRead = 0; - return transformRaw(input, { - transform(value, controller) { - if (bytesRead < end) { - if (bytesRead + value.length >= begin) { - controller.enqueue(slice(value, Math.max(begin - bytesRead, 0), end - bytesRead)); - } - bytesRead += value.length; - } else { - controller.terminate(); - } - } - }); - } - if (begin < 0 && (end < 0 || end === Infinity)) { - let lastBytes = []; - return transform(input, value => { - if (value.length >= -begin) lastBytes = [value]; - else lastBytes.push(value); - }, () => slice(concat(lastBytes), begin, end)); - } - if (begin === 0 && end < 0) { - let lastBytes; - return transform(input, value => { - const returnValue = lastBytes ? concat([lastBytes, value]) : value; - if (returnValue.length >= -end) { - lastBytes = slice(returnValue, end); - return slice(returnValue, begin, end); - } else { - lastBytes = returnValue; - } - }); - } - console.warn(`stream.slice(input, ${begin}, ${end}) not implemented efficiently.`); - return fromAsync(async () => slice(await readToEnd(input), begin, end)); - } - if (input[externalBuffer]) { - input = concat(input[externalBuffer].concat([input])); - } - if (isUint8Array(input) && !(NodeBuffer$1 && NodeBuffer$1.isBuffer(input))) { - if (end === Infinity) end = input.length; - return input.subarray(begin, end); - } - return input.slice(begin, end); -} - -/** - * Read a stream to the end and return its contents, concatenated by the join function (defaults to concat). - * @param {ReadableStream|Uint8array|String} input - * @param {Function} join - * @returns {Promise} the return value of join() - * @async - */ -async function readToEnd(input, join=concat) { - if (isArrayStream(input)) { - return input.readToEnd(join); - } - if (isStream(input)) { - return getReader(input).readToEnd(join); - } - return input; -} - -/** - * Cancel a stream. - * @param {ReadableStream|Uint8array|String} input - * @param {Any} reason - * @returns {Promise} indicates when the stream has been canceled - * @async - */ -async function cancel(input, reason) { - if (isStream(input)) { - if (input.cancel) { - return input.cancel(reason); - } - if (input.destroy) { - input.destroy(reason); - await new Promise(setTimeout); - return reason; - } - } -} - -/** - * Convert an async function to an ArrayStream. When the function returns, its return value is written to the stream. - * @param {Function} fn - * @returns {ArrayStream} - */ -function fromAsync(fn) { - const arrayStream = new ArrayStream(); - (async () => { - const writer = getWriter(arrayStream); - try { - await writer.write(await fn()); - await writer.close(); - } catch (e) { - await writer.abort(e); - } - })(); - return arrayStream; -} - -/* eslint-disable new-cap */ - -/** - * @fileoverview - * BigInteger implementation of basic operations - * that wraps the native BigInt library. - * Operations are not constant time, - * but we try and limit timing leakage where we can - * @module biginteger/native - * @private - */ - -/** - * @private - */ -class BigInteger { - /** - * Get a BigInteger (input must be big endian for strings and arrays) - * @param {Number|String|Uint8Array} n - Value to convert - * @throws {Error} on null or undefined input - */ - constructor(n) { - if (n === undefined) { - throw new Error('Invalid BigInteger input'); - } - - if (n instanceof Uint8Array) { - const bytes = n; - const hex = new Array(bytes.length); - for (let i = 0; i < bytes.length; i++) { - const hexByte = bytes[i].toString(16); - hex[i] = (bytes[i] <= 0xF) ? ('0' + hexByte) : hexByte; - } - this.value = BigInt('0x0' + hex.join('')); - } else { - this.value = BigInt(n); - } - } - - clone() { - return new BigInteger(this.value); - } - - /** - * BigInteger increment in place - */ - iinc() { - this.value++; - return this; - } - - /** - * BigInteger increment - * @returns {BigInteger} this + 1. - */ - inc() { - return this.clone().iinc(); - } - - /** - * BigInteger decrement in place - */ - idec() { - this.value--; - return this; - } - - /** - * BigInteger decrement - * @returns {BigInteger} this - 1. - */ - dec() { - return this.clone().idec(); - } - - /** - * BigInteger addition in place - * @param {BigInteger} x - Value to add - */ - iadd(x) { - this.value += x.value; - return this; - } - - /** - * BigInteger addition - * @param {BigInteger} x - Value to add - * @returns {BigInteger} this + x. - */ - add(x) { - return this.clone().iadd(x); - } - - /** - * BigInteger subtraction in place - * @param {BigInteger} x - Value to subtract - */ - isub(x) { - this.value -= x.value; - return this; - } - - /** - * BigInteger subtraction - * @param {BigInteger} x - Value to subtract - * @returns {BigInteger} this - x. - */ - sub(x) { - return this.clone().isub(x); - } - - /** - * BigInteger multiplication in place - * @param {BigInteger} x - Value to multiply - */ - imul(x) { - this.value *= x.value; - return this; - } - - /** - * BigInteger multiplication - * @param {BigInteger} x - Value to multiply - * @returns {BigInteger} this * x. - */ - mul(x) { - return this.clone().imul(x); - } - - /** - * Compute value modulo m, in place - * @param {BigInteger} m - Modulo - */ - imod(m) { - this.value %= m.value; - if (this.isNegative()) { - this.iadd(m); - } - return this; - } - - /** - * Compute value modulo m - * @param {BigInteger} m - Modulo - * @returns {BigInteger} this mod m. - */ - mod(m) { - return this.clone().imod(m); - } - - /** - * Compute modular exponentiation using square and multiply - * @param {BigInteger} e - Exponent - * @param {BigInteger} n - Modulo - * @returns {BigInteger} this ** e mod n. - */ - modExp(e, n) { - if (n.isZero()) throw Error('Modulo cannot be zero'); - if (n.isOne()) return new BigInteger(0); - if (e.isNegative()) throw Error('Unsopported negative exponent'); - - let exp = e.value; - let x = this.value; - - x %= n.value; - let r = BigInt(1); - while (exp > BigInt(0)) { - const lsb = exp & BigInt(1); - exp >>= BigInt(1); // e / 2 - // Always compute multiplication step, to reduce timing leakage - const rx = (r * x) % n.value; - // Update r only if lsb is 1 (odd exponent) - r = lsb ? rx : r; - x = (x * x) % n.value; // Square - } - return new BigInteger(r); - } - - - /** - * Compute the inverse of this value modulo n - * Note: this and and n must be relatively prime - * @param {BigInteger} n - Modulo - * @returns {BigInteger} x such that this*x = 1 mod n - * @throws {Error} if the inverse does not exist - */ - modInv(n) { - const { gcd, x } = this._egcd(n); - if (!gcd.isOne()) { - throw new Error('Inverse does not exist'); - } - return x.add(n).mod(n); - } - - /** - * Extended Eucleadian algorithm (http://anh.cs.luc.edu/331/notes/xgcd.pdf) - * Given a = this and b, compute (x, y) such that ax + by = gdc(a, b) - * @param {BigInteger} b - Second operand - * @returns {{ gcd, x, y: BigInteger }} - */ - _egcd(b) { - let x = BigInt(0); - let y = BigInt(1); - let xPrev = BigInt(1); - let yPrev = BigInt(0); - - let a = this.value; - b = b.value; - - while (b !== BigInt(0)) { - const q = a / b; - let tmp = x; - x = xPrev - q * x; - xPrev = tmp; - - tmp = y; - y = yPrev - q * y; - yPrev = tmp; - - tmp = b; - b = a % b; - a = tmp; - } - - return { - x: new BigInteger(xPrev), - y: new BigInteger(yPrev), - gcd: new BigInteger(a) - }; - } - - /** - * Compute greatest common divisor between this and n - * @param {BigInteger} b - Operand - * @returns {BigInteger} gcd - */ - gcd(b) { - let a = this.value; - b = b.value; - while (b !== BigInt(0)) { - const tmp = b; - b = a % b; - a = tmp; - } - return new BigInteger(a); - } - - /** - * Shift this to the left by x, in place - * @param {BigInteger} x - Shift value - */ - ileftShift(x) { - this.value <<= x.value; - return this; - } - - /** - * Shift this to the left by x - * @param {BigInteger} x - Shift value - * @returns {BigInteger} this << x. - */ - leftShift(x) { - return this.clone().ileftShift(x); - } - - /** - * Shift this to the right by x, in place - * @param {BigInteger} x - Shift value - */ - irightShift(x) { - this.value >>= x.value; - return this; - } - - /** - * Shift this to the right by x - * @param {BigInteger} x - Shift value - * @returns {BigInteger} this >> x. - */ - rightShift(x) { - return this.clone().irightShift(x); - } - - /** - * Whether this value is equal to x - * @param {BigInteger} x - * @returns {Boolean} - */ - equal(x) { - return this.value === x.value; - } - - /** - * Whether this value is less than x - * @param {BigInteger} x - * @returns {Boolean} - */ - lt(x) { - return this.value < x.value; - } - - /** - * Whether this value is less than or equal to x - * @param {BigInteger} x - * @returns {Boolean} - */ - lte(x) { - return this.value <= x.value; - } - - /** - * Whether this value is greater than x - * @param {BigInteger} x - * @returns {Boolean} - */ - gt(x) { - return this.value > x.value; - } - - /** - * Whether this value is greater than or equal to x - * @param {BigInteger} x - * @returns {Boolean} - */ - gte(x) { - return this.value >= x.value; - } - - isZero() { - return this.value === BigInt(0); - } - - isOne() { - return this.value === BigInt(1); - } - - isNegative() { - return this.value < BigInt(0); - } - - isEven() { - return !(this.value & BigInt(1)); - } - - abs() { - const res = this.clone(); - if (this.isNegative()) { - res.value = -res.value; - } - return res; - } - - /** - * Get this value as a string - * @returns {String} this value. - */ - toString() { - return this.value.toString(); - } - - /** - * Get this value as an exact Number (max 53 bits) - * Fails if this value is too large - * @returns {Number} - */ - toNumber() { - const number = Number(this.value); - if (number > Number.MAX_SAFE_INTEGER) { - // We throw and error to conform with the bn.js implementation - throw new Error('Number can only safely store up to 53 bits'); - } - return number; - } - - /** - * Get value of i-th bit - * @param {Number} i - Bit index - * @returns {Number} Bit value. - */ - getBit(i) { - const bit = (this.value >> BigInt(i)) & BigInt(1); - return (bit === BigInt(0)) ? 0 : 1; - } - - /** - * Compute bit length - * @returns {Number} Bit length. - */ - bitLength() { - const zero = new BigInteger(0); - const one = new BigInteger(1); - const negOne = new BigInteger(-1); - - // -1n >> -1n is -1n - // 1n >> 1n is 0n - const target = this.isNegative() ? negOne : zero; - let bitlen = 1; - const tmp = this.clone(); - while (!tmp.irightShift(one).equal(target)) { - bitlen++; - } - return bitlen; - } - - /** - * Compute byte length - * @returns {Number} Byte length. - */ - byteLength() { - const zero = new BigInteger(0); - const negOne = new BigInteger(-1); - - const target = this.isNegative() ? negOne : zero; - const eight = new BigInteger(8); - let len = 1; - const tmp = this.clone(); - while (!tmp.irightShift(eight).equal(target)) { - len++; - } - return len; - } - - /** - * Get Uint8Array representation of this number - * @param {String} endian - Endianess of output array (defaults to 'be') - * @param {Number} length - Of output array - * @returns {Uint8Array} - */ - toUint8Array(endian = 'be', length) { - // we get and parse the hex string (https://coolaj86.com/articles/convert-js-bigints-to-typedarrays/) - // this is faster than shift+mod iterations - let hex = this.value.toString(16); - if (hex.length % 2 === 1) { - hex = '0' + hex; - } - - const rawLength = hex.length / 2; - const bytes = new Uint8Array(length || rawLength); - // parse hex - const offset = length ? (length - rawLength) : 0; - let i = 0; - while (i < rawLength) { - bytes[i + offset] = parseInt(hex.slice(2 * i, 2 * i + 2), 16); - i++; - } - - if (endian !== 'be') { - bytes.reverse(); - } - - return bytes; - } -} - -async function getBigInteger() { - if (util.detectBigInt()) { - return BigInteger; - } else { - const { default: BigInteger } = await Promise.resolve().then(function () { return bn_interface; }); - return BigInteger; - } -} - -const debugMode = (() => { - try { - return process.env.NODE_ENV === 'development'; // eslint-disable-line no-process-env - } catch (e) {} - return false; -})(); - -const util = { - isString: function(data) { - return typeof data === 'string' || String.prototype.isPrototypeOf(data); - }, - - isArray: function(data) { - return Array.prototype.isPrototypeOf(data); - }, - - isUint8Array: isUint8Array, - - isStream: isStream, - - readNumber: function (bytes) { - let n = 0; - for (let i = 0; i < bytes.length; i++) { - n += (256 ** i) * bytes[bytes.length - 1 - i]; - } - return n; - }, - - writeNumber: function (n, bytes) { - const b = new Uint8Array(bytes); - for (let i = 0; i < bytes; i++) { - b[i] = (n >> (8 * (bytes - i - 1))) & 0xFF; - } - - return b; - }, - - readDate: function (bytes) { - const n = util.readNumber(bytes); - const d = new Date(n * 1000); - return d; - }, - - writeDate: function (time) { - const numeric = Math.floor(time.getTime() / 1000); - - return util.writeNumber(numeric, 4); - }, - - normalizeDate: function (time = Date.now()) { - return time === null || time === Infinity ? time : new Date(Math.floor(+time / 1000) * 1000); - }, - - /** - * Read one MPI from bytes in input - * @param {Uint8Array} bytes - Input data to parse - * @returns {Uint8Array} Parsed MPI. - */ - readMPI: function (bytes) { - const bits = (bytes[0] << 8) | bytes[1]; - const bytelen = (bits + 7) >>> 3; - return bytes.subarray(2, 2 + bytelen); - }, - - /** - * Left-pad Uint8Array to length by adding 0x0 bytes - * @param {Uint8Array} bytes - Data to pad - * @param {Number} length - Padded length - * @returns {Uint8Array} Padded bytes. - */ - leftPad(bytes, length) { - const padded = new Uint8Array(length); - const offset = length - bytes.length; - padded.set(bytes, offset); - return padded; - }, - - /** - * Convert a Uint8Array to an MPI-formatted Uint8Array. - * @param {Uint8Array} bin - An array of 8-bit integers to convert - * @returns {Uint8Array} MPI-formatted Uint8Array. - */ - uint8ArrayToMPI: function (bin) { - const bitSize = util.uint8ArrayBitLength(bin); - if (bitSize === 0) { - throw new Error('Zero MPI'); - } - const stripped = bin.subarray(bin.length - Math.ceil(bitSize / 8)); - const prefix = new Uint8Array([(bitSize & 0xFF00) >> 8, bitSize & 0xFF]); - return util.concatUint8Array([prefix, stripped]); - }, - - /** - * Return bit length of the input data - * @param {Uint8Array} bin input data (big endian) - * @returns bit length - */ - uint8ArrayBitLength: function (bin) { - let i; // index of leading non-zero byte - for (i = 0; i < bin.length; i++) if (bin[i] !== 0) break; - if (i === bin.length) { - return 0; - } - const stripped = bin.subarray(i); - return (stripped.length - 1) * 8 + util.nbits(stripped[0]); - }, - - /** - * Convert a hex string to an array of 8-bit integers - * @param {String} hex - A hex string to convert - * @returns {Uint8Array} An array of 8-bit integers. - */ - hexToUint8Array: function (hex) { - const result = new Uint8Array(hex.length >> 1); - for (let k = 0; k < hex.length >> 1; k++) { - result[k] = parseInt(hex.substr(k << 1, 2), 16); - } - return result; - }, - - /** - * Convert an array of 8-bit integers to a hex string - * @param {Uint8Array} bytes - Array of 8-bit integers to convert - * @returns {String} Hexadecimal representation of the array. - */ - uint8ArrayToHex: function (bytes) { - const r = []; - const e = bytes.length; - let c = 0; - let h; - while (c < e) { - h = bytes[c++].toString(16); - while (h.length < 2) { - h = '0' + h; - } - r.push('' + h); - } - return r.join(''); - }, - - /** - * Convert a string to an array of 8-bit integers - * @param {String} str - String to convert - * @returns {Uint8Array} An array of 8-bit integers. - */ - stringToUint8Array: function (str) { - return transform(str, str => { - if (!util.isString(str)) { - throw new Error('stringToUint8Array: Data must be in the form of a string'); - } - - const result = new Uint8Array(str.length); - for (let i = 0; i < str.length; i++) { - result[i] = str.charCodeAt(i); - } - return result; - }); - }, - - /** - * Convert an array of 8-bit integers to a string - * @param {Uint8Array} bytes - An array of 8-bit integers to convert - * @returns {String} String representation of the array. - */ - uint8ArrayToString: function (bytes) { - bytes = new Uint8Array(bytes); - const result = []; - const bs = 1 << 14; - const j = bytes.length; - - for (let i = 0; i < j; i += bs) { - result.push(String.fromCharCode.apply(String, bytes.subarray(i, i + bs < j ? i + bs : j))); - } - return result.join(''); - }, - - /** - * Convert a native javascript string to a Uint8Array of utf8 bytes - * @param {String|ReadableStream} str - The string to convert - * @returns {Uint8Array|ReadableStream} A valid squence of utf8 bytes. - */ - encodeUTF8: function (str) { - const encoder = new TextEncoder('utf-8'); - // eslint-disable-next-line no-inner-declarations - function process(value, lastChunk = false) { - return encoder.encode(value, { stream: !lastChunk }); - } - return transform(str, process, () => process('', true)); - }, - - /** - * Convert a Uint8Array of utf8 bytes to a native javascript string - * @param {Uint8Array|ReadableStream} utf8 - A valid squence of utf8 bytes - * @returns {String|ReadableStream} A native javascript string. - */ - decodeUTF8: function (utf8) { - const decoder = new TextDecoder('utf-8'); - // eslint-disable-next-line no-inner-declarations - function process(value, lastChunk = false) { - return decoder.decode(value, { stream: !lastChunk }); - } - return transform(utf8, process, () => process(new Uint8Array(), true)); - }, - - /** - * Concat a list of Uint8Arrays, Strings or Streams - * The caller must not mix Uint8Arrays with Strings, but may mix Streams with non-Streams. - * @param {Array} Array - Of Uint8Arrays/Strings/Streams to concatenate - * @returns {Uint8Array|String|ReadableStream} Concatenated array. - */ - concat: concat, - - /** - * Concat Uint8Arrays - * @param {Array} Array - Of Uint8Arrays to concatenate - * @returns {Uint8Array} Concatenated array. - */ - concatUint8Array: concatUint8Array, - - /** - * Check Uint8Array equality - * @param {Uint8Array} array1 - First array - * @param {Uint8Array} array2 - Second array - * @returns {Boolean} Equality. - */ - equalsUint8Array: function (array1, array2) { - if (!util.isUint8Array(array1) || !util.isUint8Array(array2)) { - throw new Error('Data must be in the form of a Uint8Array'); - } - - if (array1.length !== array2.length) { - return false; - } - - for (let i = 0; i < array1.length; i++) { - if (array1[i] !== array2[i]) { - return false; - } - } - return true; - }, - - /** - * Calculates a 16bit sum of a Uint8Array by adding each character - * codes modulus 65535 - * @param {Uint8Array} Uint8Array - To create a sum of - * @returns {Uint8Array} 2 bytes containing the sum of all charcodes % 65535. - */ - writeChecksum: function (text) { - let s = 0; - for (let i = 0; i < text.length; i++) { - s = (s + text[i]) & 0xFFFF; - } - return util.writeNumber(s, 2); - }, - - /** - * Helper function to print a debug message. Debug - * messages are only printed if - * @param {String} str - String of the debug message - */ - printDebug: function (str) { - if (debugMode) { - console.log(str); - } - }, - - /** - * Helper function to print a debug error. Debug - * messages are only printed if - * @param {String} str - String of the debug message - */ - printDebugError: function (error) { - if (debugMode) { - console.error(error); - } - }, - - // returns bit length of the integer x - nbits: function (x) { - let r = 1; - let t = x >>> 16; - if (t !== 0) { - x = t; - r += 16; - } - t = x >> 8; - if (t !== 0) { - x = t; - r += 8; - } - t = x >> 4; - if (t !== 0) { - x = t; - r += 4; - } - t = x >> 2; - if (t !== 0) { - x = t; - r += 2; - } - t = x >> 1; - if (t !== 0) { - x = t; - r += 1; - } - return r; - }, - - /** - * If S[1] == 0, then double(S) == (S[2..128] || 0); - * otherwise, double(S) == (S[2..128] || 0) xor - * (zeros(120) || 10000111). - * - * Both OCB and EAX (through CMAC) require this function to be constant-time. - * - * @param {Uint8Array} data - */ - double: function(data) { - const doubleVar = new Uint8Array(data.length); - const last = data.length - 1; - for (let i = 0; i < last; i++) { - doubleVar[i] = (data[i] << 1) ^ (data[i + 1] >> 7); - } - doubleVar[last] = (data[last] << 1) ^ ((data[0] >> 7) * 0x87); - return doubleVar; - }, - - /** - * Shift a Uint8Array to the right by n bits - * @param {Uint8Array} array - The array to shift - * @param {Integer} bits - Amount of bits to shift (MUST be smaller - * than 8) - * @returns {String} Resulting array. - */ - shiftRight: function (array, bits) { - if (bits) { - for (let i = array.length - 1; i >= 0; i--) { - array[i] >>= bits; - if (i > 0) { - array[i] |= (array[i - 1] << (8 - bits)); - } - } - } - return array; - }, - - /** - * Get native Web Cryptography api, only the current version of the spec. - * @returns {Object} The SubtleCrypto api or 'undefined'. - */ - getWebCrypto: function() { - return typeof globalThis !== 'undefined' && globalThis.crypto && globalThis.crypto.subtle; - }, - - /** - * Detect Node.js runtime. - */ - detectNode: function() { - return typeof globalThis.process === 'object' && - typeof globalThis.process.versions === 'object'; - }, - - /** - * Detect native BigInt support - */ - detectBigInt: () => typeof BigInt !== 'undefined', - - /** - * Get BigInteger class - * It wraps the native BigInt type if it's available - * Otherwise it relies on bn.js - * @returns {BigInteger} - * @async - */ - getBigInteger, - - /** - * Get native Node.js crypto api. - * @returns {Object} The crypto module or 'undefined'. - */ - getNodeCrypto: function() { - return crypto__default['default']; - }, - - getNodeZlib: function() { - return zlib__default['default']; - }, - - /** - * Get native Node.js Buffer constructor. This should be used since - * Buffer is not available under browserify. - * @returns {Function} The Buffer constructor or 'undefined'. - */ - getNodeBuffer: function() { - return (buffer__default['default'] || {}).Buffer; - }, - - getHardwareConcurrency: function() { - if (util.detectNode()) { - const os = os__default['default']; - return os.cpus().length; - } - - return navigator.hardwareConcurrency || 1; - }, - - isEmailAddress: function(data) { - if (!util.isString(data)) { - return false; - } - const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+([a-zA-Z]{2,}|xn--[a-zA-Z\-0-9]+)))$/; - return re.test(data); - }, - - /** - * Normalize line endings to - * Support any encoding where CR=0x0D, LF=0x0A - */ - canonicalizeEOL: function(data) { - const CR = 13; - const LF = 10; - let carryOverCR = false; - - return transform(data, bytes => { - if (carryOverCR) { - bytes = util.concatUint8Array([new Uint8Array([CR]), bytes]); - } - - if (bytes[bytes.length - 1] === CR) { - carryOverCR = true; - bytes = bytes.subarray(0, -1); - } else { - carryOverCR = false; - } - - let index; - const indices = []; - for (let i = 0; ; i = index) { - index = bytes.indexOf(LF, i) + 1; - if (index) { - if (bytes[index - 2] !== CR) indices.push(index); - } else { - break; - } - } - if (!indices.length) { - return bytes; - } - - const normalized = new Uint8Array(bytes.length + indices.length); - let j = 0; - for (let i = 0; i < indices.length; i++) { - const sub = bytes.subarray(indices[i - 1] || 0, indices[i]); - normalized.set(sub, j); - j += sub.length; - normalized[j - 1] = CR; - normalized[j] = LF; - j++; - } - normalized.set(bytes.subarray(indices[indices.length - 1] || 0), j); - return normalized; - }, () => (carryOverCR ? new Uint8Array([CR]) : undefined)); - }, - - /** - * Convert line endings from canonicalized to native - * Support any encoding where CR=0x0D, LF=0x0A - */ - nativeEOL: function(data) { - const CR = 13; - const LF = 10; - let carryOverCR = false; - - return transform(data, bytes => { - if (carryOverCR && bytes[0] !== LF) { - bytes = util.concatUint8Array([new Uint8Array([CR]), bytes]); - } else { - bytes = new Uint8Array(bytes); // Don't mutate passed bytes - } - - if (bytes[bytes.length - 1] === CR) { - carryOverCR = true; - bytes = bytes.subarray(0, -1); - } else { - carryOverCR = false; - } - - let index; - let j = 0; - for (let i = 0; i !== bytes.length; i = index) { - index = bytes.indexOf(CR, i) + 1; - if (!index) index = bytes.length; - const last = index - (bytes[index] === LF ? 1 : 0); - if (i) bytes.copyWithin(j, i, last); - j += last - i; - } - return bytes.subarray(0, j); - }, () => (carryOverCR ? new Uint8Array([CR]) : undefined)); - }, - - /** - * Remove trailing spaces and tabs from each line - */ - removeTrailingSpaces: function(text) { - return text.split('\n').map(line => { - let i = line.length - 1; - for (; i >= 0 && (line[i] === ' ' || line[i] === '\t'); i--); - return line.substr(0, i + 1); - }).join('\n'); - }, - - wrapError: function(message, error) { - if (!error) { - return new Error(message); - } - - // update error message - try { - error.message = message + ': ' + error.message; - } catch (e) {} - - return error; - }, - - /** - * Map allowed packet tags to corresponding classes - * Meant to be used to format `allowedPacket` for Packetlist.read - * @param {Array} allowedClasses - * @returns {Object} map from enum.packet to corresponding *Packet class - */ - constructAllowedPackets: function(allowedClasses) { - const map = {}; - allowedClasses.forEach(PacketClass => { - if (!PacketClass.tag) { - throw new Error('Invalid input: expected a packet class'); - } - map[PacketClass.tag] = PacketClass; - }); - return map; - }, - - /** - * Return a Promise that will resolve as soon as one of the promises in input resolves - * or will reject if all input promises all rejected - * (similar to Promise.any, but with slightly different error handling) - * @param {Array} promises - * @return {Promise} Promise resolving to the result of the fastest fulfilled promise - * or rejected with the Error of the last resolved Promise (if all promises are rejected) - */ - anyPromise: function(promises) { - return new Promise(async (resolve, reject) => { - let exception; - await Promise.all(promises.map(async promise => { - try { - resolve(await promise); - } catch (e) { - exception = e; - } - })); - reject(exception); - }); - }, - - /** - * Return either `a` or `b` based on `cond`, in algorithmic constant time. - * @param {Boolean} cond - * @param {Uint8Array} a - * @param {Uint8Array} b - * @returns `a` if `cond` is true, `b` otherwise - */ - selectUint8Array: function(cond, a, b) { - const length = Math.max(a.length, b.length); - const result = new Uint8Array(length); - let end = 0; - for (let i = 0; i < result.length; i++) { - result[i] = (a[i] & (256 - cond)) | (b[i] & (255 + cond)); - end += (cond & i < a.length) | ((1 - cond) & i < b.length); - } - return result.subarray(0, end); - }, - /** - * Return either `a` or `b` based on `cond`, in algorithmic constant time. - * NB: it only supports `a, b` with values between 0-255. - * @param {Boolean} cond - * @param {Uint8} a - * @param {Uint8} b - * @returns `a` if `cond` is true, `b` otherwise - */ - selectUint8: function(cond, a, b) { - return (a & (256 - cond)) | (b & (255 + cond)); - } -}; - -/* OpenPGP radix-64/base64 string encoding/decoding - * Copyright 2005 Herbert Hanewinkel, www.haneWIN.de - * version 1.0, check www.haneWIN.de for the latest version - * - * This software is provided as-is, without express or implied warranty. - * Permission to use, copy, modify, distribute or sell this software, with or - * without fee, for any purpose and by any individual or organization, is hereby - * granted, provided that the above copyright notice and this paragraph appear - * in all copies. Distribution as a part of an application or binary must - * include the above copyright notice in the documentation and/or other materials - * provided with the application or distribution. - */ - -const Buffer = util.getNodeBuffer(); - -let encodeChunk; -let decodeChunk; -if (Buffer) { - encodeChunk = buf => Buffer.from(buf).toString('base64'); - decodeChunk = str => { - const b = Buffer.from(str, 'base64'); - return new Uint8Array(b.buffer, b.byteOffset, b.byteLength); - }; -} else { - encodeChunk = buf => btoa(util.uint8ArrayToString(buf)); - decodeChunk = str => util.stringToUint8Array(atob(str)); -} - -/** - * Convert binary array to radix-64 - * @param {Uint8Array | ReadableStream} data - Uint8Array to convert - * @returns {String | ReadableStream} Radix-64 version of input string. - * @static - */ -function encode(data) { - let buf = new Uint8Array(); - return transform(data, value => { - buf = util.concatUint8Array([buf, value]); - const r = []; - const bytesPerLine = 45; // 60 chars per line * (3 bytes / 4 chars of base64). - const lines = Math.floor(buf.length / bytesPerLine); - const bytes = lines * bytesPerLine; - const encoded = encodeChunk(buf.subarray(0, bytes)); - for (let i = 0; i < lines; i++) { - r.push(encoded.substr(i * 60, 60)); - r.push('\n'); - } - buf = buf.subarray(bytes); - return r.join(''); - }, () => (buf.length ? encodeChunk(buf) + '\n' : '')); -} - -/** - * Convert radix-64 to binary array - * @param {String | ReadableStream} data - Radix-64 string to convert - * @returns {Uint8Array | ReadableStream} Binary array version of input string. - * @static - */ -function decode(data) { - let buf = ''; - return transform(data, value => { - buf += value; - - // Count how many whitespace characters there are in buf - let spaces = 0; - const spacechars = [' ', '\t', '\r', '\n']; - for (let i = 0; i < spacechars.length; i++) { - const spacechar = spacechars[i]; - for (let pos = buf.indexOf(spacechar); pos !== -1; pos = buf.indexOf(spacechar, pos + 1)) { - spaces++; - } - } - - // Backtrack until we have 4n non-whitespace characters - // that we can safely base64-decode - let length = buf.length; - for (; length > 0 && (length - spaces) % 4 !== 0; length--) { - if (spacechars.includes(buf[length])) spaces--; - } - - const decoded = decodeChunk(buf.substr(0, length)); - buf = buf.substr(length); - return decoded; - }, () => decodeChunk(buf)); -} - -/** - * Convert a Base-64 encoded string an array of 8-bit integer - * - * Note: accepts both Radix-64 and URL-safe strings - * @param {String} base64 - Base-64 encoded string to convert - * @returns {Uint8Array} An array of 8-bit integers. - */ -function b64ToUint8Array(base64) { - return decode(base64.replace(/-/g, '+').replace(/_/g, '/')); -} - -/** - * Convert an array of 8-bit integer to a Base-64 encoded string - * @param {Uint8Array} bytes - An array of 8-bit integers to convert - * @param {bool} url - If true, output is URL-safe - * @returns {String} Base-64 encoded string. - */ -function uint8ArrayToB64(bytes, url) { - let encoded = encode(bytes).replace(/[\r\n]/g, ''); - if (url) { - encoded = encoded.replace(/[+]/g, '-').replace(/[/]/g, '_').replace(/[=]/g, ''); - } - return encoded; -} - -/** - * @module enums - */ - -const byValue = Symbol('byValue'); - -var enums = { - - /** Maps curve names under various standards to one - * @see {@link https://wiki.gnupg.org/ECC|ECC - GnuPG wiki} - * @enum {String} - * @readonly - */ - curve: { - /** NIST P-256 Curve */ - 'p256': 'p256', - 'P-256': 'p256', - 'secp256r1': 'p256', - 'prime256v1': 'p256', - '1.2.840.10045.3.1.7': 'p256', - '2a8648ce3d030107': 'p256', - '2A8648CE3D030107': 'p256', - - /** NIST P-384 Curve */ - 'p384': 'p384', - 'P-384': 'p384', - 'secp384r1': 'p384', - '1.3.132.0.34': 'p384', - '2b81040022': 'p384', - '2B81040022': 'p384', - - /** NIST P-521 Curve */ - 'p521': 'p521', - 'P-521': 'p521', - 'secp521r1': 'p521', - '1.3.132.0.35': 'p521', - '2b81040023': 'p521', - '2B81040023': 'p521', - - /** SECG SECP256k1 Curve */ - 'secp256k1': 'secp256k1', - '1.3.132.0.10': 'secp256k1', - '2b8104000a': 'secp256k1', - '2B8104000A': 'secp256k1', - - /** Ed25519 */ - 'ED25519': 'ed25519', - 'ed25519': 'ed25519', - 'Ed25519': 'ed25519', - '1.3.6.1.4.1.11591.15.1': 'ed25519', - '2b06010401da470f01': 'ed25519', - '2B06010401DA470F01': 'ed25519', - - /** Curve25519 */ - 'X25519': 'curve25519', - 'cv25519': 'curve25519', - 'curve25519': 'curve25519', - 'Curve25519': 'curve25519', - '1.3.6.1.4.1.3029.1.5.1': 'curve25519', - '2b060104019755010501': 'curve25519', - '2B060104019755010501': 'curve25519', - - /** BrainpoolP256r1 Curve */ - 'brainpoolP256r1': 'brainpoolP256r1', - '1.3.36.3.3.2.8.1.1.7': 'brainpoolP256r1', - '2b2403030208010107': 'brainpoolP256r1', - '2B2403030208010107': 'brainpoolP256r1', - - /** BrainpoolP384r1 Curve */ - 'brainpoolP384r1': 'brainpoolP384r1', - '1.3.36.3.3.2.8.1.1.11': 'brainpoolP384r1', - '2b240303020801010b': 'brainpoolP384r1', - '2B240303020801010B': 'brainpoolP384r1', - - /** BrainpoolP512r1 Curve */ - 'brainpoolP512r1': 'brainpoolP512r1', - '1.3.36.3.3.2.8.1.1.13': 'brainpoolP512r1', - '2b240303020801010d': 'brainpoolP512r1', - '2B240303020801010D': 'brainpoolP512r1' - }, - - /** A string to key specifier type - * @enum {Integer} - * @readonly - */ - s2k: { - simple: 0, - salted: 1, - iterated: 3, - gnu: 101 - }, - - /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-9.1|RFC4880bis-04, section 9.1} - * @enum {Integer} - * @readonly - */ - publicKey: { - /** RSA (Encrypt or Sign) [HAC] */ - rsaEncryptSign: 1, - /** RSA (Encrypt only) [HAC] */ - rsaEncrypt: 2, - /** RSA (Sign only) [HAC] */ - rsaSign: 3, - /** Elgamal (Encrypt only) [ELGAMAL] [HAC] */ - elgamal: 16, - /** DSA (Sign only) [FIPS186] [HAC] */ - dsa: 17, - /** ECDH (Encrypt only) [RFC6637] */ - ecdh: 18, - /** ECDSA (Sign only) [RFC6637] */ - ecdsa: 19, - /** EdDSA (Sign only) - * [{@link https://tools.ietf.org/html/draft-koch-eddsa-for-openpgp-04|Draft RFC}] */ - eddsa: 22, - /** Reserved for AEDH */ - aedh: 23, - /** Reserved for AEDSA */ - aedsa: 24 - }, - - /** {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC4880, section 9.2} - * @enum {Integer} - * @readonly - */ - symmetric: { - plaintext: 0, - /** Not implemented! */ - idea: 1, - tripledes: 2, - cast5: 3, - blowfish: 4, - aes128: 7, - aes192: 8, - aes256: 9, - twofish: 10 - }, - - /** {@link https://tools.ietf.org/html/rfc4880#section-9.3|RFC4880, section 9.3} - * @enum {Integer} - * @readonly - */ - compression: { - uncompressed: 0, - /** RFC1951 */ - zip: 1, - /** RFC1950 */ - zlib: 2, - bzip2: 3 - }, - - /** {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC4880, section 9.4} - * @enum {Integer} - * @readonly - */ - hash: { - md5: 1, - sha1: 2, - ripemd: 3, - sha256: 8, - sha384: 9, - sha512: 10, - sha224: 11 - }, - - /** A list of hash names as accepted by webCrypto functions. - * {@link https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest|Parameters, algo} - * @enum {String} - */ - webHash: { - 'SHA-1': 2, - 'SHA-256': 8, - 'SHA-384': 9, - 'SHA-512': 10 - }, - - /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-9.6|RFC4880bis-04, section 9.6} - * @enum {Integer} - * @readonly - */ - aead: { - eax: 1, - ocb: 2, - experimentalGCM: 100 // Private algorithm - }, - - /** A list of packet types and numeric tags associated with them. - * @enum {Integer} - * @readonly - */ - packet: { - publicKeyEncryptedSessionKey: 1, - signature: 2, - symEncryptedSessionKey: 3, - onePassSignature: 4, - secretKey: 5, - publicKey: 6, - secretSubkey: 7, - compressedData: 8, - symmetricallyEncryptedData: 9, - marker: 10, - literalData: 11, - trust: 12, - userID: 13, - publicSubkey: 14, - userAttribute: 17, - symEncryptedIntegrityProtectedData: 18, - modificationDetectionCode: 19, - aeadEncryptedData: 20 // see IETF draft: https://tools.ietf.org/html/draft-ford-openpgp-format-00#section-2.1 - }, - - /** Data types in the literal packet - * @enum {Integer} - * @readonly - */ - literal: { - /** Binary data 'b' */ - binary: 'b'.charCodeAt(), - /** Text data 't' */ - text: 't'.charCodeAt(), - /** Utf8 data 'u' */ - utf8: 'u'.charCodeAt(), - /** MIME message body part 'm' */ - mime: 'm'.charCodeAt() - }, - - - /** One pass signature packet type - * @enum {Integer} - * @readonly - */ - signature: { - /** 0x00: Signature of a binary document. */ - binary: 0, - /** 0x01: Signature of a canonical text document. - * - * Canonicalyzing the document by converting line endings. */ - text: 1, - /** 0x02: Standalone signature. - * - * This signature is a signature of only its own subpacket contents. - * It is calculated identically to a signature over a zero-lengh - * binary document. Note that it doesn't make sense to have a V3 - * standalone signature. */ - standalone: 2, - /** 0x10: Generic certification of a User ID and Public-Key packet. - * - * The issuer of this certification does not make any particular - * assertion as to how well the certifier has checked that the owner - * of the key is in fact the person described by the User ID. */ - certGeneric: 16, - /** 0x11: Persona certification of a User ID and Public-Key packet. - * - * The issuer of this certification has not done any verification of - * the claim that the owner of this key is the User ID specified. */ - certPersona: 17, - /** 0x12: Casual certification of a User ID and Public-Key packet. - * - * The issuer of this certification has done some casual - * verification of the claim of identity. */ - certCasual: 18, - /** 0x13: Positive certification of a User ID and Public-Key packet. - * - * The issuer of this certification has done substantial - * verification of the claim of identity. - * - * Most OpenPGP implementations make their "key signatures" as 0x10 - * certifications. Some implementations can issue 0x11-0x13 - * certifications, but few differentiate between the types. */ - certPositive: 19, - /** 0x30: Certification revocation signature - * - * This signature revokes an earlier User ID certification signature - * (signature class 0x10 through 0x13) or direct-key signature - * (0x1F). It should be issued by the same key that issued the - * revoked signature or an authorized revocation key. The signature - * is computed over the same data as the certificate that it - * revokes, and should have a later creation date than that - * certificate. */ - certRevocation: 48, - /** 0x18: Subkey Binding Signature - * - * This signature is a statement by the top-level signing key that - * indicates that it owns the subkey. This signature is calculated - * directly on the primary key and subkey, and not on any User ID or - * other packets. A signature that binds a signing subkey MUST have - * an Embedded Signature subpacket in this binding signature that - * contains a 0x19 signature made by the signing subkey on the - * primary key and subkey. */ - subkeyBinding: 24, - /** 0x19: Primary Key Binding Signature - * - * This signature is a statement by a signing subkey, indicating - * that it is owned by the primary key and subkey. This signature - * is calculated the same way as a 0x18 signature: directly on the - * primary key and subkey, and not on any User ID or other packets. - * - * When a signature is made over a key, the hash data starts with the - * octet 0x99, followed by a two-octet length of the key, and then body - * of the key packet. (Note that this is an old-style packet header for - * a key packet with two-octet length.) A subkey binding signature - * (type 0x18) or primary key binding signature (type 0x19) then hashes - * the subkey using the same format as the main key (also using 0x99 as - * the first octet). */ - keyBinding: 25, - /** 0x1F: Signature directly on a key - * - * This signature is calculated directly on a key. It binds the - * information in the Signature subpackets to the key, and is - * appropriate to be used for subpackets that provide information - * about the key, such as the Revocation Key subpacket. It is also - * appropriate for statements that non-self certifiers want to make - * about the key itself, rather than the binding between a key and a - * name. */ - key: 31, - /** 0x20: Key revocation signature - * - * The signature is calculated directly on the key being revoked. A - * revoked key is not to be used. Only revocation signatures by the - * key being revoked, or by an authorized revocation key, should be - * considered valid revocation signatures.a */ - keyRevocation: 32, - /** 0x28: Subkey revocation signature - * - * The signature is calculated directly on the subkey being revoked. - * A revoked subkey is not to be used. Only revocation signatures - * by the top-level signature key that is bound to this subkey, or - * by an authorized revocation key, should be considered valid - * revocation signatures. - * - * Key revocation signatures (types 0x20 and 0x28) - * hash only the key being revoked. */ - subkeyRevocation: 40, - /** 0x40: Timestamp signature. - * This signature is only meaningful for the timestamp contained in - * it. */ - timestamp: 64, - /** 0x50: Third-Party Confirmation signature. - * - * This signature is a signature over some other OpenPGP Signature - * packet(s). It is analogous to a notary seal on the signed data. - * A third-party signature SHOULD include Signature Target - * subpacket(s) to give easy identification. Note that we really do - * mean SHOULD. There are plausible uses for this (such as a blind - * party that only sees the signature, not the key or source - * document) that cannot include a target subpacket. */ - thirdParty: 80 - }, - - /** Signature subpacket type - * @enum {Integer} - * @readonly - */ - signatureSubpacket: { - signatureCreationTime: 2, - signatureExpirationTime: 3, - exportableCertification: 4, - trustSignature: 5, - regularExpression: 6, - revocable: 7, - keyExpirationTime: 9, - placeholderBackwardsCompatibility: 10, - preferredSymmetricAlgorithms: 11, - revocationKey: 12, - issuer: 16, - notationData: 20, - preferredHashAlgorithms: 21, - preferredCompressionAlgorithms: 22, - keyServerPreferences: 23, - preferredKeyServer: 24, - primaryUserID: 25, - policyURI: 26, - keyFlags: 27, - signersUserID: 28, - reasonForRevocation: 29, - features: 30, - signatureTarget: 31, - embeddedSignature: 32, - issuerFingerprint: 33, - preferredAEADAlgorithms: 34 - }, - - /** Key flags - * @enum {Integer} - * @readonly - */ - keyFlags: { - /** 0x01 - This key may be used to certify other keys. */ - certifyKeys: 1, - /** 0x02 - This key may be used to sign data. */ - signData: 2, - /** 0x04 - This key may be used to encrypt communications. */ - encryptCommunication: 4, - /** 0x08 - This key may be used to encrypt storage. */ - encryptStorage: 8, - /** 0x10 - The private component of this key may have been split - * by a secret-sharing mechanism. */ - splitPrivateKey: 16, - /** 0x20 - This key may be used for authentication. */ - authentication: 32, - /** 0x80 - The private component of this key may be in the - * possession of more than one person. */ - sharedPrivateKey: 128 - }, - - /** Armor type - * @enum {Integer} - * @readonly - */ - armor: { - multipartSection: 0, - multipartLast: 1, - signed: 2, - message: 3, - publicKey: 4, - privateKey: 5, - signature: 6 - }, - - /** {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.23|RFC4880, section 5.2.3.23} - * @enum {Integer} - * @readonly - */ - reasonForRevocation: { - /** No reason specified (key revocations or cert revocations) */ - noReason: 0, - /** Key is superseded (key revocations) */ - keySuperseded: 1, - /** Key material has been compromised (key revocations) */ - keyCompromised: 2, - /** Key is retired and no longer used (key revocations) */ - keyRetired: 3, - /** User ID information is no longer valid (cert revocations) */ - userIDInvalid: 32 - }, - - /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.2.3.25|RFC4880bis-04, section 5.2.3.25} - * @enum {Integer} - * @readonly - */ - features: { - /** 0x01 - Modification Detection (packets 18 and 19) */ - modificationDetection: 1, - /** 0x02 - AEAD Encrypted Data Packet (packet 20) and version 5 - * Symmetric-Key Encrypted Session Key Packets (packet 3) */ - aead: 2, - /** 0x04 - Version 5 Public-Key Packet format and corresponding new - * fingerprint format */ - v5Keys: 4 - }, - - /** - * Asserts validity of given value and converts from string/integer to integer. - * @param {Object} type target enum type - * @param {String|Integer} e value to check and/or convert - * @returns {Integer} enum value if it exists - * @throws {Error} if the value is invalid - */ - write: function(type, e) { - if (typeof e === 'number') { - e = this.read(type, e); - } - - if (type[e] !== undefined) { - return type[e]; - } - - throw new Error('Invalid enum value.'); - }, - - /** - * Converts enum integer value to the corresponding string, if it exists. - * @param {Object} type target enum type - * @param {Integer} e value to convert - * @returns {String} name of enum value if it exists - * @throws {Error} if the value is invalid - */ - read: function(type, e) { - if (!type[byValue]) { - type[byValue] = []; - Object.entries(type).forEach(([key, value]) => { - type[byValue][value] = key; - }); - } - - if (type[byValue][e] !== undefined) { - return type[byValue][e]; - } - - throw new Error('Invalid enum value.'); - } -}; - -// GPG4Browsers - An OpenPGP implementation in javascript - -var defaultConfig = { - /** - * @memberof module:config - * @property {Integer} preferredHashAlgorithm Default hash algorithm {@link module:enums.hash} - */ - preferredHashAlgorithm: enums.hash.sha256, - /** - * @memberof module:config - * @property {Integer} preferredSymmetricAlgorithm Default encryption cipher {@link module:enums.symmetric} - */ - preferredSymmetricAlgorithm: enums.symmetric.aes256, - /** - * @memberof module:config - * @property {Integer} compression Default compression algorithm {@link module:enums.compression} - */ - preferredCompressionAlgorithm: enums.compression.uncompressed, - /** - * @memberof module:config - * @property {Integer} deflateLevel Default zip/zlib compression level, between 1 and 9 - */ - deflateLevel: 6, - - /** - * Use Authenticated Encryption with Additional Data (AEAD) protection for symmetric encryption. - * Note: not all OpenPGP implementations are compatible with this option. - * **FUTURE OPENPGP.JS VERSIONS MAY BREAK COMPATIBILITY WHEN USING THIS OPTION** - * @see {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-07|RFC4880bis-07} - * @memberof module:config - * @property {Boolean} aeadProtect - */ - aeadProtect: false, - /** - * Default Authenticated Encryption with Additional Data (AEAD) encryption mode - * Only has an effect when aeadProtect is set to true. - * @memberof module:config - * @property {Integer} preferredAEADAlgorithm Default AEAD mode {@link module:enums.aead} - */ - preferredAEADAlgorithm: enums.aead.eax, - /** - * Chunk Size Byte for Authenticated Encryption with Additional Data (AEAD) mode - * Only has an effect when aeadProtect is set to true. - * Must be an integer value from 0 to 56. - * @memberof module:config - * @property {Integer} aeadChunkSizeByte - */ - aeadChunkSizeByte: 12, - /** - * Use V5 keys. - * Note: not all OpenPGP implementations are compatible with this option. - * **FUTURE OPENPGP.JS VERSIONS MAY BREAK COMPATIBILITY WHEN USING THIS OPTION** - * @memberof module:config - * @property {Boolean} v5Keys - */ - v5Keys: false, - /** - * {@link https://tools.ietf.org/html/rfc4880#section-3.7.1.3|RFC4880 3.7.1.3}: - * Iteration Count Byte for S2K (String to Key) - * @memberof module:config - * @property {Integer} s2kIterationCountByte - */ - s2kIterationCountByte: 224, - /** - * Allow decryption of messages without integrity protection. - * This is an **insecure** setting: - * - message modifications cannot be detected, thus processing the decrypted data is potentially unsafe. - * - it enables downgrade attacks against integrity-protected messages. - * @memberof module:config - * @property {Boolean} allowUnauthenticatedMessages - */ - allowUnauthenticatedMessages: false, - /** - * Allow streaming unauthenticated data before its integrity has been checked. - * This setting is **insecure** if the partially decrypted message is processed further or displayed to the user. - * @memberof module:config - * @property {Boolean} allowUnauthenticatedStream - */ - allowUnauthenticatedStream: false, - /** - * @memberof module:config - * @property {Boolean} checksumRequired Do not throw error when armor is missing a checksum - */ - checksumRequired: false, - /** - * Minimum RSA key size allowed for key generation and message signing, verification and encryption. - * The default is 2047 since due to a bug, previous versions of OpenPGP.js could generate 2047-bit keys instead of 2048-bit ones. - * @memberof module:config - * @property {Number} minRSABits - */ - minRSABits: 2047, - /** - * Work-around for rare GPG decryption bug when encrypting with multiple passwords. - * **Slower and slightly less secure** - * @memberof module:config - * @property {Boolean} passwordCollisionCheck - */ - passwordCollisionCheck: false, - /** - * @memberof module:config - * @property {Boolean} revocationsExpire If true, expired revocation signatures are ignored - */ - revocationsExpire: false, - /** - * Allow decryption using RSA keys without `encrypt` flag. - * This setting is potentially insecure, but it is needed to get around an old openpgpjs bug - * where key flags were ignored when selecting a key for encryption. - * @memberof module:config - * @property {Boolean} allowInsecureDecryptionWithSigningKeys - */ - allowInsecureDecryptionWithSigningKeys: false, - /** - * Allow verification of message signatures with keys whose validity at the time of signing cannot be determined. - * Instead, a verification key will also be consider valid as long as it is valid at the current time. - * This setting is potentially insecure, but it is needed to verify messages signed with keys that were later reformatted, - * and have self-signature's creation date that does not match the primary key creation date. - * @memberof module:config - * @property {Boolean} allowInsecureDecryptionWithSigningKeys - */ - allowInsecureVerificationWithReformattedKeys: false, - - /** - * Enable constant-time decryption of RSA- and ElGamal-encrypted session keys, to hinder Bleichenbacher-like attacks (https://link.springer.com/chapter/10.1007/BFb0055716). - * This setting has measurable performance impact and it is only helpful in application scenarios where both of the following conditions apply: - * - new/incoming messages are automatically decrypted (without user interaction); - * - an attacker can determine how long it takes to decrypt each message (e.g. due to decryption errors being logged remotely). - * See also `constantTimePKCS1DecryptionSupportedSymmetricAlgorithms`. - * @memberof module:config - * @property {Boolean} constantTimePKCS1Decryption - */ - constantTimePKCS1Decryption: false, - /** - * This setting is only meaningful if `constantTimePKCS1Decryption` is enabled. - * Decryption of RSA- and ElGamal-encrypted session keys of symmetric algorithms different from the ones specified here will fail. - * However, the more algorithms are added, the slower the decryption procedure becomes. - * @memberof module:config - * @property {Set} constantTimePKCS1DecryptionSupportedSymmetricAlgorithms {@link module:enums.symmetric} - */ - constantTimePKCS1DecryptionSupportedSymmetricAlgorithms: new Set([enums.symmetric.aes128, enums.symmetric.aes192, enums.symmetric.aes256]), - - /** - * @memberof module:config - * @property {Integer} minBytesForWebCrypto The minimum amount of bytes for which to use native WebCrypto APIs when available - */ - minBytesForWebCrypto: 1000, - /** - * @memberof module:config - * @property {Boolean} ignoreUnsupportedPackets Ignore unsupported/unrecognizable packets on parsing instead of throwing an error - */ - ignoreUnsupportedPackets: true, - /** - * @memberof module:config - * @property {Boolean} ignoreMalformedPackets Ignore malformed packets on parsing instead of throwing an error - */ - ignoreMalformedPackets: false, - /** - * @memberof module:config - * @property {Boolean} showVersion Whether to include {@link module:config/config.versionString} in armored messages - */ - showVersion: false, - /** - * @memberof module:config - * @property {Boolean} showComment Whether to include {@link module:config/config.commentString} in armored messages - */ - showComment: false, - /** - * @memberof module:config - * @property {String} versionString A version string to be included in armored messages - */ - versionString: 'OpenPGP.js 5.1.0', - /** - * @memberof module:config - * @property {String} commentString A comment string to be included in armored messages - */ - commentString: 'https://openpgpjs.org', - - /** - * Max userID string length (used for parsing) - * @memberof module:config - * @property {Integer} maxUserIDLength - */ - maxUserIDLength: 1024 * 5, - /** - * Contains notatations that are considered "known". Known notations do not trigger - * validation error when the notation is marked as critical. - * @memberof module:config - * @property {Array} knownNotations - */ - knownNotations: ['preferred-email-encoding@pgp.com', 'pka-address@gnupg.org'], - /** - * Whether to use the indutny/elliptic library for curves (other than Curve25519) that are not supported by the available native crypto API. - * When false, certain standard curves will not be supported (depending on the platform). - * Note: the indutny/elliptic curve library is not designed to be constant time. - * @memberof module:config - * @property {Boolean} useIndutnyElliptic - */ - useIndutnyElliptic: true, - /** - * Reject insecure hash algorithms - * @memberof module:config - * @property {Set} rejectHashAlgorithms {@link module:enums.hash} - */ - rejectHashAlgorithms: new Set([enums.hash.md5, enums.hash.ripemd]), - /** - * Reject insecure message hash algorithms - * @memberof module:config - * @property {Set} rejectMessageHashAlgorithms {@link module:enums.hash} - */ - rejectMessageHashAlgorithms: new Set([enums.hash.md5, enums.hash.ripemd, enums.hash.sha1]), - /** - * Reject insecure public key algorithms for key generation and message encryption, signing or verification - * @memberof module:config - * @property {Set} rejectPublicKeyAlgorithms {@link module:enums.publicKey} - */ - rejectPublicKeyAlgorithms: new Set([enums.publicKey.elgamal, enums.publicKey.dsa]), - /** - * Reject non-standard curves for key generation, message encryption, signing or verification - * @memberof module:config - * @property {Set} rejectCurves {@link module:enums.curve} - */ - rejectCurves: new Set([enums.curve.brainpoolP256r1, enums.curve.brainpoolP384r1, enums.curve.brainpoolP512r1, enums.curve.secp256k1]) -}; - -// GPG4Browsers - An OpenPGP implementation in javascript - -/** - * Finds out which Ascii Armoring type is used. Throws error if unknown type. - * @param {String} text - ascii armored text - * @returns {Integer} 0 = MESSAGE PART n of m. - * 1 = MESSAGE PART n - * 2 = SIGNED MESSAGE - * 3 = PGP MESSAGE - * 4 = PUBLIC KEY BLOCK - * 5 = PRIVATE KEY BLOCK - * 6 = SIGNATURE - * @private - */ -function getType(text) { - const reHeader = /^-----BEGIN PGP (MESSAGE, PART \d+\/\d+|MESSAGE, PART \d+|SIGNED MESSAGE|MESSAGE|PUBLIC KEY BLOCK|PRIVATE KEY BLOCK|SIGNATURE)-----$/m; - - const header = text.match(reHeader); - - if (!header) { - throw new Error('Unknown ASCII armor type'); - } - - // BEGIN PGP MESSAGE, PART X/Y - // Used for multi-part messages, where the armor is split amongst Y - // parts, and this is the Xth part out of Y. - if (/MESSAGE, PART \d+\/\d+/.test(header[1])) { - return enums.armor.multipartSection; - } else - // BEGIN PGP MESSAGE, PART X - // Used for multi-part messages, where this is the Xth part of an - // unspecified number of parts. Requires the MESSAGE-ID Armor - // Header to be used. - if (/MESSAGE, PART \d+/.test(header[1])) { - return enums.armor.multipartLast; - } else - // BEGIN PGP SIGNED MESSAGE - if (/SIGNED MESSAGE/.test(header[1])) { - return enums.armor.signed; - } else - // BEGIN PGP MESSAGE - // Used for signed, encrypted, or compressed files. - if (/MESSAGE/.test(header[1])) { - return enums.armor.message; - } else - // BEGIN PGP PUBLIC KEY BLOCK - // Used for armoring public keys. - if (/PUBLIC KEY BLOCK/.test(header[1])) { - return enums.armor.publicKey; - } else - // BEGIN PGP PRIVATE KEY BLOCK - // Used for armoring private keys. - if (/PRIVATE KEY BLOCK/.test(header[1])) { - return enums.armor.privateKey; - } else - // BEGIN PGP SIGNATURE - // Used for detached signatures, OpenPGP/MIME signatures, and - // cleartext signatures. Note that PGP 2.x uses BEGIN PGP MESSAGE - // for detached signatures. - if (/SIGNATURE/.test(header[1])) { - return enums.armor.signature; - } -} - -/** - * Add additional information to the armor version of an OpenPGP binary - * packet block. - * @author Alex - * @version 2011-12-16 - * @param {String} [customComment] - Additional comment to add to the armored string - * @returns {String} The header information. - * @private - */ -function addheader(customComment, config) { - let result = ''; - if (config.showVersion) { - result += 'Version: ' + config.versionString + '\n'; - } - if (config.showComment) { - result += 'Comment: ' + config.commentString + '\n'; - } - if (customComment) { - result += 'Comment: ' + customComment + '\n'; - } - result += '\n'; - return result; -} - - -/** - * Calculates a checksum over the given data and returns it base64 encoded - * @param {String | ReadableStream} data - Data to create a CRC-24 checksum for - * @returns {String | ReadableStream} Base64 encoded checksum. - * @private - */ -function getCheckSum(data) { - const crc = createcrc24(data); - return encode(crc); -} - -// https://create.stephan-brumme.com/crc32/#slicing-by-8-overview - -const crc_table = [ - new Array(0xFF), - new Array(0xFF), - new Array(0xFF), - new Array(0xFF) -]; - -for (let i = 0; i <= 0xFF; i++) { - let crc = i << 16; - for (let j = 0; j < 8; j++) { - crc = (crc << 1) ^ ((crc & 0x800000) !== 0 ? 0x864CFB : 0); - } - crc_table[0][i] = - ((crc & 0xFF0000) >> 16) | - (crc & 0x00FF00) | - ((crc & 0x0000FF) << 16); -} -for (let i = 0; i <= 0xFF; i++) { - crc_table[1][i] = (crc_table[0][i] >> 8) ^ crc_table[0][crc_table[0][i] & 0xFF]; -} -for (let i = 0; i <= 0xFF; i++) { - crc_table[2][i] = (crc_table[1][i] >> 8) ^ crc_table[0][crc_table[1][i] & 0xFF]; -} -for (let i = 0; i <= 0xFF; i++) { - crc_table[3][i] = (crc_table[2][i] >> 8) ^ crc_table[0][crc_table[2][i] & 0xFF]; -} - -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView#Endianness -const isLittleEndian = (function() { - const buffer = new ArrayBuffer(2); - new DataView(buffer).setInt16(0, 0xFF, true /* littleEndian */); - // Int16Array uses the platform's endianness. - return new Int16Array(buffer)[0] === 0xFF; -}()); - -/** - * Internal function to calculate a CRC-24 checksum over a given string (data) - * @param {String | ReadableStream} input - Data to create a CRC-24 checksum for - * @returns {Uint8Array | ReadableStream} The CRC-24 checksum. - * @private - */ -function createcrc24(input) { - let crc = 0xCE04B7; - return transform(input, value => { - const len32 = isLittleEndian ? Math.floor(value.length / 4) : 0; - const arr32 = new Uint32Array(value.buffer, value.byteOffset, len32); - for (let i = 0; i < len32; i++) { - crc ^= arr32[i]; - crc = - crc_table[0][(crc >> 24) & 0xFF] ^ - crc_table[1][(crc >> 16) & 0xFF] ^ - crc_table[2][(crc >> 8) & 0xFF] ^ - crc_table[3][(crc >> 0) & 0xFF]; - } - for (let i = len32 * 4; i < value.length; i++) { - crc = (crc >> 8) ^ crc_table[0][(crc & 0xFF) ^ value[i]]; - } - }, () => new Uint8Array([crc, crc >> 8, crc >> 16])); -} - -/** - * Verify armored headers. RFC4880, section 6.3: "OpenPGP should consider improperly formatted - * Armor Headers to be corruption of the ASCII Armor." - * @private - * @param {Array} headers - Armor headers - */ -function verifyHeaders(headers) { - for (let i = 0; i < headers.length; i++) { - if (!/^([^\s:]|[^\s:][^:]*[^\s:]): .+$/.test(headers[i])) { - throw new Error('Improperly formatted armor header: ' + headers[i]); - } - if (!/^(Version|Comment|MessageID|Hash|Charset): .+$/.test(headers[i])) { - util.printDebugError(new Error('Unknown header: ' + headers[i])); - } - } -} - -/** - * Splits a message into two parts, the body and the checksum. This is an internal function - * @param {String} text - OpenPGP armored message part - * @returns {Object} An object with attribute "body" containing the body. - * and an attribute "checksum" containing the checksum. - * @private - */ -function splitChecksum(text) { - let body = text; - let checksum = ''; - - const lastEquals = text.lastIndexOf('='); - - if (lastEquals >= 0 && lastEquals !== text.length - 1) { // '=' as the last char means no checksum - body = text.slice(0, lastEquals); - checksum = text.slice(lastEquals + 1).substr(0, 4); - } - - return { body: body, checksum: checksum }; -} - -/** - * Dearmor an OpenPGP armored message; verify the checksum and return - * the encoded bytes - * @param {String} input - OpenPGP armored message - * @returns {Promise} An object with attribute "text" containing the message text, - * an attribute "data" containing a stream of bytes and "type" for the ASCII armor type - * @async - * @static - */ -function unarmor(input, config = defaultConfig) { - return new Promise(async (resolve, reject) => { - try { - const reSplit = /^-----[^-]+-----$/m; - const reEmptyLine = /^[ \f\r\t\u00a0\u2000-\u200a\u202f\u205f\u3000]*$/; - - let type; - const headers = []; - let lastHeaders = headers; - let headersDone; - let text = []; - let textDone; - let checksum; - let data = decode(transformPair(input, async (readable, writable) => { - const reader = getReader(readable); - try { - while (true) { - let line = await reader.readLine(); - if (line === undefined) { - throw new Error('Misformed armored text'); - } - // remove trailing whitespace at end of lines - line = util.removeTrailingSpaces(line.replace(/[\r\n]/g, '')); - if (!type) { - if (reSplit.test(line)) { - type = getType(line); - } - } else if (!headersDone) { - if (reSplit.test(line)) { - reject(new Error('Mandatory blank line missing between armor headers and armor data')); - } - if (!reEmptyLine.test(line)) { - lastHeaders.push(line); - } else { - verifyHeaders(lastHeaders); - headersDone = true; - if (textDone || type !== 2) { - resolve({ text, data, headers, type }); - break; - } - } - } else if (!textDone && type === 2) { - if (!reSplit.test(line)) { - // Reverse dash-escaping for msg - text.push(line.replace(/^- /, '')); - } else { - text = text.join('\r\n'); - textDone = true; - verifyHeaders(lastHeaders); - lastHeaders = []; - headersDone = false; - } - } - } - } catch (e) { - reject(e); - return; - } - const writer = getWriter(writable); - try { - while (true) { - await writer.ready; - const { done, value } = await reader.read(); - if (done) { - throw new Error('Misformed armored text'); - } - const line = value + ''; - if (line.indexOf('=') === -1 && line.indexOf('-') === -1) { - await writer.write(line); - } else { - let remainder = await reader.readToEnd(); - if (!remainder.length) remainder = ''; - remainder = line + remainder; - remainder = util.removeTrailingSpaces(remainder.replace(/\r/g, '')); - const parts = remainder.split(reSplit); - if (parts.length === 1) { - throw new Error('Misformed armored text'); - } - const split = splitChecksum(parts[0].slice(0, -1)); - checksum = split.checksum; - await writer.write(split.body); - break; - } - } - await writer.ready; - await writer.close(); - } catch (e) { - await writer.abort(e); - } - })); - data = transformPair(data, async (readable, writable) => { - const checksumVerified = readToEnd(getCheckSum(passiveClone(readable))); - checksumVerified.catch(() => {}); - await pipe(readable, writable, { - preventClose: true - }); - const writer = getWriter(writable); - try { - const checksumVerifiedString = (await checksumVerified).replace('\n', ''); - if (checksum !== checksumVerifiedString && (checksum || config.checksumRequired)) { - throw new Error('Ascii armor integrity check failed'); - } - await writer.ready; - await writer.close(); - } catch (e) { - await writer.abort(e); - } - }); - } catch (e) { - reject(e); - } - }).then(async result => { - if (isArrayStream(result.data)) { - result.data = await readToEnd(result.data); - } - return result; - }); -} - - -/** - * Armor an OpenPGP binary packet block - * @param {module:enums.armor} messageType - Type of the message - * @param {Uint8Array | ReadableStream} body - The message body to armor - * @param {Integer} [partIndex] - * @param {Integer} [partTotal] - * @param {String} [customComment] - Additional comment to add to the armored string - * @returns {String | ReadableStream} Armored text. - * @static - */ -function armor(messageType, body, partIndex, partTotal, customComment, config = defaultConfig) { - let text; - let hash; - if (messageType === enums.armor.signed) { - text = body.text; - hash = body.hash; - body = body.data; - } - const bodyClone = passiveClone(body); - const result = []; - switch (messageType) { - case enums.armor.multipartSection: - result.push('-----BEGIN PGP MESSAGE, PART ' + partIndex + '/' + partTotal + '-----\n'); - result.push(addheader(customComment, config)); - result.push(encode(body)); - result.push('=', getCheckSum(bodyClone)); - result.push('-----END PGP MESSAGE, PART ' + partIndex + '/' + partTotal + '-----\n'); - break; - case enums.armor.multipartLast: - result.push('-----BEGIN PGP MESSAGE, PART ' + partIndex + '-----\n'); - result.push(addheader(customComment, config)); - result.push(encode(body)); - result.push('=', getCheckSum(bodyClone)); - result.push('-----END PGP MESSAGE, PART ' + partIndex + '-----\n'); - break; - case enums.armor.signed: - result.push('\n-----BEGIN PGP SIGNED MESSAGE-----\n'); - result.push('Hash: ' + hash + '\n\n'); - result.push(text.replace(/^-/mg, '- -')); - result.push('\n-----BEGIN PGP SIGNATURE-----\n'); - result.push(addheader(customComment, config)); - result.push(encode(body)); - result.push('=', getCheckSum(bodyClone)); - result.push('-----END PGP SIGNATURE-----\n'); - break; - case enums.armor.message: - result.push('-----BEGIN PGP MESSAGE-----\n'); - result.push(addheader(customComment, config)); - result.push(encode(body)); - result.push('=', getCheckSum(bodyClone)); - result.push('-----END PGP MESSAGE-----\n'); - break; - case enums.armor.publicKey: - result.push('-----BEGIN PGP PUBLIC KEY BLOCK-----\n'); - result.push(addheader(customComment, config)); - result.push(encode(body)); - result.push('=', getCheckSum(bodyClone)); - result.push('-----END PGP PUBLIC KEY BLOCK-----\n'); - break; - case enums.armor.privateKey: - result.push('-----BEGIN PGP PRIVATE KEY BLOCK-----\n'); - result.push(addheader(customComment, config)); - result.push(encode(body)); - result.push('=', getCheckSum(bodyClone)); - result.push('-----END PGP PRIVATE KEY BLOCK-----\n'); - break; - case enums.armor.signature: - result.push('-----BEGIN PGP SIGNATURE-----\n'); - result.push(addheader(customComment, config)); - result.push(encode(body)); - result.push('=', getCheckSum(bodyClone)); - result.push('-----END PGP SIGNATURE-----\n'); - break; - } - - return util.concat(result); -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -/** - * Implementation of type key id - * - * {@link https://tools.ietf.org/html/rfc4880#section-3.3|RFC4880 3.3}: - * A Key ID is an eight-octet scalar that identifies a key. - * Implementations SHOULD NOT assume that Key IDs are unique. The - * section "Enhanced Key Formats" below describes how Key IDs are - * formed. - */ -class KeyID { - constructor() { - this.bytes = ''; - } - - /** - * Parsing method for a key id - * @param {Uint8Array} bytes - Input to read the key id from - */ - read(bytes) { - this.bytes = util.uint8ArrayToString(bytes.subarray(0, 8)); - } - - /** - * Serializes the Key ID - * @returns {Uint8Array} Key ID as a Uint8Array. - */ - write() { - return util.stringToUint8Array(this.bytes); - } - - /** - * Returns the Key ID represented as a hexadecimal string - * @returns {String} Key ID as a hexadecimal string. - */ - toHex() { - return util.uint8ArrayToHex(util.stringToUint8Array(this.bytes)); - } - - /** - * Checks equality of Key ID's - * @param {KeyID} keyID - * @param {Boolean} matchWildcard - Indicates whether to check if either keyID is a wildcard - */ - equals(keyID, matchWildcard = false) { - return (matchWildcard && (keyID.isWildcard() || this.isWildcard())) || this.bytes === keyID.bytes; - } - - /** - * Checks to see if the Key ID is unset - * @returns {Boolean} True if the Key ID is null. - */ - isNull() { - return this.bytes === ''; - } - - /** - * Checks to see if the Key ID is a "wildcard" Key ID (all zeros) - * @returns {Boolean} True if this is a wildcard Key ID. - */ - isWildcard() { - return /^0+$/.test(this.toHex()); - } - - static mapToHex(keyID) { - return keyID.toHex(); - } - - static fromID(hex) { - const keyID = new KeyID(); - keyID.read(util.hexToUint8Array(hex)); - return keyID; - } - - static wildcard() { - const keyID = new KeyID(); - keyID.read(new Uint8Array(8)); - return keyID; - } -} - -/** - * @file {@link http://asmjs.org Asm.js} implementation of the {@link https://en.wikipedia.org/wiki/Advanced_Encryption_Standard Advanced Encryption Standard}. - * @author Artem S Vybornov - * @license MIT - */ -var AES_asm = function () { - - /** - * Galois Field stuff init flag - */ - var ginit_done = false; - - /** - * Galois Field exponentiation and logarithm tables for 3 (the generator) - */ - var gexp3, glog3; - - /** - * Init Galois Field tables - */ - function ginit() { - gexp3 = [], - glog3 = []; - - var a = 1, c, d; - for (c = 0; c < 255; c++) { - gexp3[c] = a; - - // Multiply by three - d = a & 0x80, a <<= 1, a &= 255; - if (d === 0x80) a ^= 0x1b; - a ^= gexp3[c]; - - // Set the log table value - glog3[gexp3[c]] = c; - } - gexp3[255] = gexp3[0]; - glog3[0] = 0; - - ginit_done = true; - } - - /** - * Galois Field multiplication - * @param {number} a - * @param {number} b - * @return {number} - */ - function gmul(a, b) { - var c = gexp3[(glog3[a] + glog3[b]) % 255]; - if (a === 0 || b === 0) c = 0; - return c; - } - - /** - * Galois Field reciprocal - * @param {number} a - * @return {number} - */ - function ginv(a) { - var i = gexp3[255 - glog3[a]]; - if (a === 0) i = 0; - return i; - } - - /** - * AES stuff init flag - */ - var aes_init_done = false; - - /** - * Encryption, Decryption, S-Box and KeyTransform tables - * - * @type {number[]} - */ - var aes_sbox; - - /** - * @type {number[]} - */ - var aes_sinv; - - /** - * @type {number[][]} - */ - var aes_enc; - - /** - * @type {number[][]} - */ - var aes_dec; - - /** - * Init AES tables - */ - function aes_init() { - if (!ginit_done) ginit(); - - // Calculates AES S-Box value - function _s(a) { - var c, s, x; - s = x = ginv(a); - for (c = 0; c < 4; c++) { - s = ((s << 1) | (s >>> 7)) & 255; - x ^= s; - } - x ^= 99; - return x; - } - - // Tables - aes_sbox = [], - aes_sinv = [], - aes_enc = [[], [], [], []], - aes_dec = [[], [], [], []]; - - for (var i = 0; i < 256; i++) { - var s = _s(i); - - // S-Box and its inverse - aes_sbox[i] = s; - aes_sinv[s] = i; - - // Ecryption and Decryption tables - aes_enc[0][i] = (gmul(2, s) << 24) | (s << 16) | (s << 8) | gmul(3, s); - aes_dec[0][s] = (gmul(14, i) << 24) | (gmul(9, i) << 16) | (gmul(13, i) << 8) | gmul(11, i); - // Rotate tables - for (var t = 1; t < 4; t++) { - aes_enc[t][i] = (aes_enc[t - 1][i] >>> 8) | (aes_enc[t - 1][i] << 24); - aes_dec[t][s] = (aes_dec[t - 1][s] >>> 8) | (aes_dec[t - 1][s] << 24); - } - } - - aes_init_done = true; - } - - /** - * Asm.js module constructor. - * - *

- * Heap buffer layout by offset: - *

-   * 0x0000   encryption key schedule
-   * 0x0400   decryption key schedule
-   * 0x0800   sbox
-   * 0x0c00   inv sbox
-   * 0x1000   encryption tables
-   * 0x2000   decryption tables
-   * 0x3000   reserved (future GCM multiplication lookup table)
-   * 0x4000   data
-   * 
- * Don't touch anything before 0x400. - *

- * - * @alias AES_asm - * @class - * @param foreign - ignored - * @param buffer - heap buffer to link with - */ - var wrapper = function (foreign, buffer) { - // Init AES stuff for the first time - if (!aes_init_done) aes_init(); - - // Fill up AES tables - var heap = new Uint32Array(buffer); - heap.set(aes_sbox, 0x0800 >> 2); - heap.set(aes_sinv, 0x0c00 >> 2); - for (var i = 0; i < 4; i++) { - heap.set(aes_enc[i], (0x1000 + 0x400 * i) >> 2); - heap.set(aes_dec[i], (0x2000 + 0x400 * i) >> 2); - } - - /** - * Calculate AES key schedules. - * @instance - * @memberof AES_asm - * @param {number} ks - key size, 4/6/8 (for 128/192/256-bit key correspondingly) - * @param {number} k0 - key vector components - * @param {number} k1 - key vector components - * @param {number} k2 - key vector components - * @param {number} k3 - key vector components - * @param {number} k4 - key vector components - * @param {number} k5 - key vector components - * @param {number} k6 - key vector components - * @param {number} k7 - key vector components - */ - function set_key(ks, k0, k1, k2, k3, k4, k5, k6, k7) { - var ekeys = heap.subarray(0x000, 60), - dkeys = heap.subarray(0x100, 0x100 + 60); - - // Encryption key schedule - ekeys.set([k0, k1, k2, k3, k4, k5, k6, k7]); - for (var i = ks, rcon = 1; i < 4 * ks + 28; i++) { - var k = ekeys[i - 1]; - if ((i % ks === 0) || (ks === 8 && i % ks === 4)) { - k = aes_sbox[k >>> 24] << 24 ^ aes_sbox[k >>> 16 & 255] << 16 ^ aes_sbox[k >>> 8 & 255] << 8 ^ aes_sbox[k & 255]; - } - if (i % ks === 0) { - k = (k << 8) ^ (k >>> 24) ^ (rcon << 24); - rcon = (rcon << 1) ^ ((rcon & 0x80) ? 0x1b : 0); - } - ekeys[i] = ekeys[i - ks] ^ k; - } - - // Decryption key schedule - for (var j = 0; j < i; j += 4) { - for (var jj = 0; jj < 4; jj++) { - var k = ekeys[i - (4 + j) + (4 - jj) % 4]; - if (j < 4 || j >= i - 4) { - dkeys[j + jj] = k; - } else { - dkeys[j + jj] = aes_dec[0][aes_sbox[k >>> 24]] - ^ aes_dec[1][aes_sbox[k >>> 16 & 255]] - ^ aes_dec[2][aes_sbox[k >>> 8 & 255]] - ^ aes_dec[3][aes_sbox[k & 255]]; - } - } - } - - // Set rounds number - asm.set_rounds(ks + 5); - } - - // create library object with necessary properties - var stdlib = {Uint8Array: Uint8Array, Uint32Array: Uint32Array}; - - var asm = function (stdlib, foreign, buffer) { - "use asm"; - - var S0 = 0, S1 = 0, S2 = 0, S3 = 0, - I0 = 0, I1 = 0, I2 = 0, I3 = 0, - N0 = 0, N1 = 0, N2 = 0, N3 = 0, - M0 = 0, M1 = 0, M2 = 0, M3 = 0, - H0 = 0, H1 = 0, H2 = 0, H3 = 0, - R = 0; - - var HEAP = new stdlib.Uint32Array(buffer), - DATA = new stdlib.Uint8Array(buffer); - - /** - * AES core - * @param {number} k - precomputed key schedule offset - * @param {number} s - precomputed sbox table offset - * @param {number} t - precomputed round table offset - * @param {number} r - number of inner rounds to perform - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _core(k, s, t, r, x0, x1, x2, x3) { - k = k | 0; - s = s | 0; - t = t | 0; - r = r | 0; - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - var t1 = 0, t2 = 0, t3 = 0, - y0 = 0, y1 = 0, y2 = 0, y3 = 0, - i = 0; - - t1 = t | 0x400, t2 = t | 0x800, t3 = t | 0xc00; - - // round 0 - x0 = x0 ^ HEAP[(k | 0) >> 2], - x1 = x1 ^ HEAP[(k | 4) >> 2], - x2 = x2 ^ HEAP[(k | 8) >> 2], - x3 = x3 ^ HEAP[(k | 12) >> 2]; - - // round 1..r - for (i = 16; (i | 0) <= (r << 4); i = (i + 16) | 0) { - y0 = HEAP[(t | x0 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x1 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x2 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x3 << 2 & 1020) >> 2] ^ HEAP[(k | i | 0) >> 2], - y1 = HEAP[(t | x1 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x2 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x3 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x0 << 2 & 1020) >> 2] ^ HEAP[(k | i | 4) >> 2], - y2 = HEAP[(t | x2 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x3 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x0 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x1 << 2 & 1020) >> 2] ^ HEAP[(k | i | 8) >> 2], - y3 = HEAP[(t | x3 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x0 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x1 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x2 << 2 & 1020) >> 2] ^ HEAP[(k | i | 12) >> 2]; - x0 = y0, x1 = y1, x2 = y2, x3 = y3; - } - - // final round - S0 = HEAP[(s | x0 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x1 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x2 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x3 << 2 & 1020) >> 2] ^ HEAP[(k | i | 0) >> 2], - S1 = HEAP[(s | x1 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x2 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x3 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x0 << 2 & 1020) >> 2] ^ HEAP[(k | i | 4) >> 2], - S2 = HEAP[(s | x2 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x3 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x0 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x1 << 2 & 1020) >> 2] ^ HEAP[(k | i | 8) >> 2], - S3 = HEAP[(s | x3 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x0 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x1 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x2 << 2 & 1020) >> 2] ^ HEAP[(k | i | 12) >> 2]; - } - - /** - * ECB mode encryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _ecb_enc(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core( - 0x0000, 0x0800, 0x1000, - R, - x0, - x1, - x2, - x3 - ); - } - - /** - * ECB mode decryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _ecb_dec(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - var t = 0; - - _core( - 0x0400, 0x0c00, 0x2000, - R, - x0, - x3, - x2, - x1 - ); - - t = S1, S1 = S3, S3 = t; - } - - - /** - * CBC mode encryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _cbc_enc(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core( - 0x0000, 0x0800, 0x1000, - R, - I0 ^ x0, - I1 ^ x1, - I2 ^ x2, - I3 ^ x3 - ); - - I0 = S0, - I1 = S1, - I2 = S2, - I3 = S3; - } - - /** - * CBC mode decryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _cbc_dec(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - var t = 0; - - _core( - 0x0400, 0x0c00, 0x2000, - R, - x0, - x3, - x2, - x1 - ); - - t = S1, S1 = S3, S3 = t; - - S0 = S0 ^ I0, - S1 = S1 ^ I1, - S2 = S2 ^ I2, - S3 = S3 ^ I3; - - I0 = x0, - I1 = x1, - I2 = x2, - I3 = x3; - } - - /** - * CFB mode encryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _cfb_enc(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core( - 0x0000, 0x0800, 0x1000, - R, - I0, - I1, - I2, - I3 - ); - - I0 = S0 = S0 ^ x0, - I1 = S1 = S1 ^ x1, - I2 = S2 = S2 ^ x2, - I3 = S3 = S3 ^ x3; - } - - - /** - * CFB mode decryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _cfb_dec(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core( - 0x0000, 0x0800, 0x1000, - R, - I0, - I1, - I2, - I3 - ); - - S0 = S0 ^ x0, - S1 = S1 ^ x1, - S2 = S2 ^ x2, - S3 = S3 ^ x3; - - I0 = x0, - I1 = x1, - I2 = x2, - I3 = x3; - } - - /** - * OFB mode encryption / decryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _ofb(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core( - 0x0000, 0x0800, 0x1000, - R, - I0, - I1, - I2, - I3 - ); - - I0 = S0, - I1 = S1, - I2 = S2, - I3 = S3; - - S0 = S0 ^ x0, - S1 = S1 ^ x1, - S2 = S2 ^ x2, - S3 = S3 ^ x3; - } - - /** - * CTR mode encryption / decryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _ctr(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core( - 0x0000, 0x0800, 0x1000, - R, - N0, - N1, - N2, - N3 - ); - - N3 = (~M3 & N3) | M3 & (N3 + 1); - N2 = (~M2 & N2) | M2 & (N2 + ((N3 | 0) == 0)); - N1 = (~M1 & N1) | M1 & (N1 + ((N2 | 0) == 0)); - N0 = (~M0 & N0) | M0 & (N0 + ((N1 | 0) == 0)); - - S0 = S0 ^ x0; - S1 = S1 ^ x1; - S2 = S2 ^ x2; - S3 = S3 ^ x3; - } - - /** - * GCM mode MAC calculation - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _gcm_mac(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - var y0 = 0, y1 = 0, y2 = 0, y3 = 0, - z0 = 0, z1 = 0, z2 = 0, z3 = 0, - i = 0, c = 0; - - x0 = x0 ^ I0, - x1 = x1 ^ I1, - x2 = x2 ^ I2, - x3 = x3 ^ I3; - - y0 = H0 | 0, - y1 = H1 | 0, - y2 = H2 | 0, - y3 = H3 | 0; - - for (; (i | 0) < 128; i = (i + 1) | 0) { - if (y0 >>> 31) { - z0 = z0 ^ x0, - z1 = z1 ^ x1, - z2 = z2 ^ x2, - z3 = z3 ^ x3; - } - - y0 = (y0 << 1) | (y1 >>> 31), - y1 = (y1 << 1) | (y2 >>> 31), - y2 = (y2 << 1) | (y3 >>> 31), - y3 = (y3 << 1); - - c = x3 & 1; - - x3 = (x3 >>> 1) | (x2 << 31), - x2 = (x2 >>> 1) | (x1 << 31), - x1 = (x1 >>> 1) | (x0 << 31), - x0 = (x0 >>> 1); - - if (c) x0 = x0 ^ 0xe1000000; - } - - I0 = z0, - I1 = z1, - I2 = z2, - I3 = z3; - } - - /** - * Set the internal rounds number. - * @instance - * @memberof AES_asm - * @param {number} r - number if inner AES rounds - */ - function set_rounds(r) { - r = r | 0; - R = r; - } - - /** - * Populate the internal state of the module. - * @instance - * @memberof AES_asm - * @param {number} s0 - state vector - * @param {number} s1 - state vector - * @param {number} s2 - state vector - * @param {number} s3 - state vector - */ - function set_state(s0, s1, s2, s3) { - s0 = s0 | 0; - s1 = s1 | 0; - s2 = s2 | 0; - s3 = s3 | 0; - - S0 = s0, - S1 = s1, - S2 = s2, - S3 = s3; - } - - /** - * Populate the internal iv of the module. - * @instance - * @memberof AES_asm - * @param {number} i0 - iv vector - * @param {number} i1 - iv vector - * @param {number} i2 - iv vector - * @param {number} i3 - iv vector - */ - function set_iv(i0, i1, i2, i3) { - i0 = i0 | 0; - i1 = i1 | 0; - i2 = i2 | 0; - i3 = i3 | 0; - - I0 = i0, - I1 = i1, - I2 = i2, - I3 = i3; - } - - /** - * Set nonce for CTR-family modes. - * @instance - * @memberof AES_asm - * @param {number} n0 - nonce vector - * @param {number} n1 - nonce vector - * @param {number} n2 - nonce vector - * @param {number} n3 - nonce vector - */ - function set_nonce(n0, n1, n2, n3) { - n0 = n0 | 0; - n1 = n1 | 0; - n2 = n2 | 0; - n3 = n3 | 0; - - N0 = n0, - N1 = n1, - N2 = n2, - N3 = n3; - } - - /** - * Set counter mask for CTR-family modes. - * @instance - * @memberof AES_asm - * @param {number} m0 - counter mask vector - * @param {number} m1 - counter mask vector - * @param {number} m2 - counter mask vector - * @param {number} m3 - counter mask vector - */ - function set_mask(m0, m1, m2, m3) { - m0 = m0 | 0; - m1 = m1 | 0; - m2 = m2 | 0; - m3 = m3 | 0; - - M0 = m0, - M1 = m1, - M2 = m2, - M3 = m3; - } - - /** - * Set counter for CTR-family modes. - * @instance - * @memberof AES_asm - * @param {number} c0 - counter vector - * @param {number} c1 - counter vector - * @param {number} c2 - counter vector - * @param {number} c3 - counter vector - */ - function set_counter(c0, c1, c2, c3) { - c0 = c0 | 0; - c1 = c1 | 0; - c2 = c2 | 0; - c3 = c3 | 0; - - N3 = (~M3 & N3) | M3 & c3, - N2 = (~M2 & N2) | M2 & c2, - N1 = (~M1 & N1) | M1 & c1, - N0 = (~M0 & N0) | M0 & c0; - } - - /** - * Store the internal state vector into the heap. - * @instance - * @memberof AES_asm - * @param {number} pos - offset where to put the data - * @return {number} The number of bytes have been written into the heap, always 16. - */ - function get_state(pos) { - pos = pos | 0; - - if (pos & 15) return -1; - - DATA[pos | 0] = S0 >>> 24, - DATA[pos | 1] = S0 >>> 16 & 255, - DATA[pos | 2] = S0 >>> 8 & 255, - DATA[pos | 3] = S0 & 255, - DATA[pos | 4] = S1 >>> 24, - DATA[pos | 5] = S1 >>> 16 & 255, - DATA[pos | 6] = S1 >>> 8 & 255, - DATA[pos | 7] = S1 & 255, - DATA[pos | 8] = S2 >>> 24, - DATA[pos | 9] = S2 >>> 16 & 255, - DATA[pos | 10] = S2 >>> 8 & 255, - DATA[pos | 11] = S2 & 255, - DATA[pos | 12] = S3 >>> 24, - DATA[pos | 13] = S3 >>> 16 & 255, - DATA[pos | 14] = S3 >>> 8 & 255, - DATA[pos | 15] = S3 & 255; - - return 16; - } - - /** - * Store the internal iv vector into the heap. - * @instance - * @memberof AES_asm - * @param {number} pos - offset where to put the data - * @return {number} The number of bytes have been written into the heap, always 16. - */ - function get_iv(pos) { - pos = pos | 0; - - if (pos & 15) return -1; - - DATA[pos | 0] = I0 >>> 24, - DATA[pos | 1] = I0 >>> 16 & 255, - DATA[pos | 2] = I0 >>> 8 & 255, - DATA[pos | 3] = I0 & 255, - DATA[pos | 4] = I1 >>> 24, - DATA[pos | 5] = I1 >>> 16 & 255, - DATA[pos | 6] = I1 >>> 8 & 255, - DATA[pos | 7] = I1 & 255, - DATA[pos | 8] = I2 >>> 24, - DATA[pos | 9] = I2 >>> 16 & 255, - DATA[pos | 10] = I2 >>> 8 & 255, - DATA[pos | 11] = I2 & 255, - DATA[pos | 12] = I3 >>> 24, - DATA[pos | 13] = I3 >>> 16 & 255, - DATA[pos | 14] = I3 >>> 8 & 255, - DATA[pos | 15] = I3 & 255; - - return 16; - } - - /** - * GCM initialization. - * @instance - * @memberof AES_asm - */ - function gcm_init() { - _ecb_enc(0, 0, 0, 0); - H0 = S0, - H1 = S1, - H2 = S2, - H3 = S3; - } - - /** - * Perform ciphering operation on the supplied data. - * @instance - * @memberof AES_asm - * @param {number} mode - block cipher mode (see {@link AES_asm} mode constants) - * @param {number} pos - offset of the data being processed - * @param {number} len - length of the data being processed - * @return {number} Actual amount of data have been processed. - */ - function cipher(mode, pos, len) { - mode = mode | 0; - pos = pos | 0; - len = len | 0; - - var ret = 0; - - if (pos & 15) return -1; - - while ((len | 0) >= 16) { - _cipher_modes[mode & 7]( - DATA[pos | 0] << 24 | DATA[pos | 1] << 16 | DATA[pos | 2] << 8 | DATA[pos | 3], - DATA[pos | 4] << 24 | DATA[pos | 5] << 16 | DATA[pos | 6] << 8 | DATA[pos | 7], - DATA[pos | 8] << 24 | DATA[pos | 9] << 16 | DATA[pos | 10] << 8 | DATA[pos | 11], - DATA[pos | 12] << 24 | DATA[pos | 13] << 16 | DATA[pos | 14] << 8 | DATA[pos | 15] - ); - - DATA[pos | 0] = S0 >>> 24, - DATA[pos | 1] = S0 >>> 16 & 255, - DATA[pos | 2] = S0 >>> 8 & 255, - DATA[pos | 3] = S0 & 255, - DATA[pos | 4] = S1 >>> 24, - DATA[pos | 5] = S1 >>> 16 & 255, - DATA[pos | 6] = S1 >>> 8 & 255, - DATA[pos | 7] = S1 & 255, - DATA[pos | 8] = S2 >>> 24, - DATA[pos | 9] = S2 >>> 16 & 255, - DATA[pos | 10] = S2 >>> 8 & 255, - DATA[pos | 11] = S2 & 255, - DATA[pos | 12] = S3 >>> 24, - DATA[pos | 13] = S3 >>> 16 & 255, - DATA[pos | 14] = S3 >>> 8 & 255, - DATA[pos | 15] = S3 & 255; - - ret = (ret + 16) | 0, - pos = (pos + 16) | 0, - len = (len - 16) | 0; - } - - return ret | 0; - } - - /** - * Calculates MAC of the supplied data. - * @instance - * @memberof AES_asm - * @param {number} mode - block cipher mode (see {@link AES_asm} mode constants) - * @param {number} pos - offset of the data being processed - * @param {number} len - length of the data being processed - * @return {number} Actual amount of data have been processed. - */ - function mac(mode, pos, len) { - mode = mode | 0; - pos = pos | 0; - len = len | 0; - - var ret = 0; - - if (pos & 15) return -1; - - while ((len | 0) >= 16) { - _mac_modes[mode & 1]( - DATA[pos | 0] << 24 | DATA[pos | 1] << 16 | DATA[pos | 2] << 8 | DATA[pos | 3], - DATA[pos | 4] << 24 | DATA[pos | 5] << 16 | DATA[pos | 6] << 8 | DATA[pos | 7], - DATA[pos | 8] << 24 | DATA[pos | 9] << 16 | DATA[pos | 10] << 8 | DATA[pos | 11], - DATA[pos | 12] << 24 | DATA[pos | 13] << 16 | DATA[pos | 14] << 8 | DATA[pos | 15] - ); - - ret = (ret + 16) | 0, - pos = (pos + 16) | 0, - len = (len - 16) | 0; - } - - return ret | 0; - } - - /** - * AES cipher modes table (virual methods) - */ - var _cipher_modes = [_ecb_enc, _ecb_dec, _cbc_enc, _cbc_dec, _cfb_enc, _cfb_dec, _ofb, _ctr]; - - /** - * AES MAC modes table (virual methods) - */ - var _mac_modes = [_cbc_enc, _gcm_mac]; - - /** - * Asm.js module exports - */ - return { - set_rounds: set_rounds, - set_state: set_state, - set_iv: set_iv, - set_nonce: set_nonce, - set_mask: set_mask, - set_counter: set_counter, - get_state: get_state, - get_iv: get_iv, - gcm_init: gcm_init, - cipher: cipher, - mac: mac, - }; - }(stdlib, foreign, buffer); - - asm.set_key = set_key; - - return asm; - }; - - /** - * AES enciphering mode constants - * @enum {number} - * @const - */ - wrapper.ENC = { - ECB: 0, - CBC: 2, - CFB: 4, - OFB: 6, - CTR: 7, - }, - - /** - * AES deciphering mode constants - * @enum {number} - * @const - */ - wrapper.DEC = { - ECB: 1, - CBC: 3, - CFB: 5, - OFB: 6, - CTR: 7, - }, - - /** - * AES MAC mode constants - * @enum {number} - * @const - */ - wrapper.MAC = { - CBC: 0, - GCM: 1, - }; - - /** - * Heap data offset - * @type {number} - * @const - */ - wrapper.HEAP_DATA = 0x4000; - - return wrapper; -}(); - -function is_bytes(a) { - return a instanceof Uint8Array; -} -function _heap_init(heap, heapSize) { - const size = heap ? heap.byteLength : heapSize || 65536; - if (size & 0xfff || size <= 0) - throw new Error('heap size must be a positive integer and a multiple of 4096'); - heap = heap || new Uint8Array(new ArrayBuffer(size)); - return heap; -} -function _heap_write(heap, hpos, data, dpos, dlen) { - const hlen = heap.length - hpos; - const wlen = hlen < dlen ? hlen : dlen; - heap.set(data.subarray(dpos, dpos + wlen), hpos); - return wlen; -} -function joinBytes(...arg) { - const totalLenght = arg.reduce((sum, curr) => sum + curr.length, 0); - const ret = new Uint8Array(totalLenght); - let cursor = 0; - for (let i = 0; i < arg.length; i++) { - ret.set(arg[i], cursor); - cursor += arg[i].length; - } - return ret; -} - -class IllegalStateError extends Error { - constructor(...args) { - super(...args); - } -} -class IllegalArgumentError extends Error { - constructor(...args) { - super(...args); - } -} -class SecurityError extends Error { - constructor(...args) { - super(...args); - } -} - -const heap_pool = []; -const asm_pool = []; -class AES { - constructor(key, iv, padding = true, mode, heap, asm) { - this.pos = 0; - this.len = 0; - this.mode = mode; - // The AES object state - this.pos = 0; - this.len = 0; - this.key = key; - this.iv = iv; - this.padding = padding; - // The AES "worker" - this.acquire_asm(heap, asm); - } - acquire_asm(heap, asm) { - if (this.heap === undefined || this.asm === undefined) { - this.heap = heap || heap_pool.pop() || _heap_init().subarray(AES_asm.HEAP_DATA); - this.asm = asm || asm_pool.pop() || new AES_asm(null, this.heap.buffer); - this.reset(this.key, this.iv); - } - return { heap: this.heap, asm: this.asm }; - } - release_asm() { - if (this.heap !== undefined && this.asm !== undefined) { - heap_pool.push(this.heap); - asm_pool.push(this.asm); - } - this.heap = undefined; - this.asm = undefined; - } - reset(key, iv) { - const { asm } = this.acquire_asm(); - // Key - const keylen = key.length; - if (keylen !== 16 && keylen !== 24 && keylen !== 32) - throw new IllegalArgumentError('illegal key size'); - const keyview = new DataView(key.buffer, key.byteOffset, key.byteLength); - asm.set_key(keylen >> 2, keyview.getUint32(0), keyview.getUint32(4), keyview.getUint32(8), keyview.getUint32(12), keylen > 16 ? keyview.getUint32(16) : 0, keylen > 16 ? keyview.getUint32(20) : 0, keylen > 24 ? keyview.getUint32(24) : 0, keylen > 24 ? keyview.getUint32(28) : 0); - // IV - if (iv !== undefined) { - if (iv.length !== 16) - throw new IllegalArgumentError('illegal iv size'); - let ivview = new DataView(iv.buffer, iv.byteOffset, iv.byteLength); - asm.set_iv(ivview.getUint32(0), ivview.getUint32(4), ivview.getUint32(8), ivview.getUint32(12)); - } - else { - asm.set_iv(0, 0, 0, 0); - } - } - AES_Encrypt_process(data) { - if (!is_bytes(data)) - throw new TypeError("data isn't of expected type"); - let { heap, asm } = this.acquire_asm(); - let amode = AES_asm.ENC[this.mode]; - let hpos = AES_asm.HEAP_DATA; - let pos = this.pos; - let len = this.len; - let dpos = 0; - let dlen = data.length || 0; - let rpos = 0; - let rlen = (len + dlen) & -16; - let wlen = 0; - let result = new Uint8Array(rlen); - while (dlen > 0) { - wlen = _heap_write(heap, pos + len, data, dpos, dlen); - len += wlen; - dpos += wlen; - dlen -= wlen; - wlen = asm.cipher(amode, hpos + pos, len); - if (wlen) - result.set(heap.subarray(pos, pos + wlen), rpos); - rpos += wlen; - if (wlen < len) { - pos += wlen; - len -= wlen; - } - else { - pos = 0; - len = 0; - } - } - this.pos = pos; - this.len = len; - return result; - } - AES_Encrypt_finish() { - let { heap, asm } = this.acquire_asm(); - let amode = AES_asm.ENC[this.mode]; - let hpos = AES_asm.HEAP_DATA; - let pos = this.pos; - let len = this.len; - let plen = 16 - (len % 16); - let rlen = len; - if (this.hasOwnProperty('padding')) { - if (this.padding) { - for (let p = 0; p < plen; ++p) { - heap[pos + len + p] = plen; - } - len += plen; - rlen = len; - } - else if (len % 16) { - throw new IllegalArgumentError('data length must be a multiple of the block size'); - } - } - else { - len += plen; - } - const result = new Uint8Array(rlen); - if (len) - asm.cipher(amode, hpos + pos, len); - if (rlen) - result.set(heap.subarray(pos, pos + rlen)); - this.pos = 0; - this.len = 0; - this.release_asm(); - return result; - } - AES_Decrypt_process(data) { - if (!is_bytes(data)) - throw new TypeError("data isn't of expected type"); - let { heap, asm } = this.acquire_asm(); - let amode = AES_asm.DEC[this.mode]; - let hpos = AES_asm.HEAP_DATA; - let pos = this.pos; - let len = this.len; - let dpos = 0; - let dlen = data.length || 0; - let rpos = 0; - let rlen = (len + dlen) & -16; - let plen = 0; - let wlen = 0; - if (this.padding) { - plen = len + dlen - rlen || 16; - rlen -= plen; - } - const result = new Uint8Array(rlen); - while (dlen > 0) { - wlen = _heap_write(heap, pos + len, data, dpos, dlen); - len += wlen; - dpos += wlen; - dlen -= wlen; - wlen = asm.cipher(amode, hpos + pos, len - (!dlen ? plen : 0)); - if (wlen) - result.set(heap.subarray(pos, pos + wlen), rpos); - rpos += wlen; - if (wlen < len) { - pos += wlen; - len -= wlen; - } - else { - pos = 0; - len = 0; - } - } - this.pos = pos; - this.len = len; - return result; - } - AES_Decrypt_finish() { - let { heap, asm } = this.acquire_asm(); - let amode = AES_asm.DEC[this.mode]; - let hpos = AES_asm.HEAP_DATA; - let pos = this.pos; - let len = this.len; - let rlen = len; - if (len > 0) { - if (len % 16) { - if (this.hasOwnProperty('padding')) { - throw new IllegalArgumentError('data length must be a multiple of the block size'); - } - else { - len += 16 - (len % 16); - } - } - asm.cipher(amode, hpos + pos, len); - if (this.hasOwnProperty('padding') && this.padding) { - let pad = heap[pos + rlen - 1]; - if (pad < 1 || pad > 16 || pad > rlen) - throw new SecurityError('bad padding'); - let pcheck = 0; - for (let i = pad; i > 1; i--) - pcheck |= pad ^ heap[pos + rlen - i]; - if (pcheck) - throw new SecurityError('bad padding'); - rlen -= pad; - } - } - const result = new Uint8Array(rlen); - if (rlen > 0) { - result.set(heap.subarray(pos, pos + rlen)); - } - this.pos = 0; - this.len = 0; - this.release_asm(); - return result; - } -} - -class AES_ECB { - static encrypt(data, key, padding = false) { - return new AES_ECB(key, padding).encrypt(data); - } - static decrypt(data, key, padding = false) { - return new AES_ECB(key, padding).decrypt(data); - } - constructor(key, padding = false, aes) { - this.aes = aes ? aes : new AES(key, undefined, padding, 'ECB'); - } - encrypt(data) { - const r1 = this.aes.AES_Encrypt_process(data); - const r2 = this.aes.AES_Encrypt_finish(); - return joinBytes(r1, r2); - } - decrypt(data) { - const r1 = this.aes.AES_Decrypt_process(data); - const r2 = this.aes.AES_Decrypt_finish(); - return joinBytes(r1, r2); - } -} - -/** - * Javascript AES implementation. - * This is used as fallback if the native Crypto APIs are not available. - */ -function aes(length) { - const C = function(key) { - const aesECB = new AES_ECB(key); - - this.encrypt = function(block) { - return aesECB.encrypt(block); - }; - - this.decrypt = function(block) { - return aesECB.decrypt(block); - }; - }; - - C.blockSize = C.prototype.blockSize = 16; - C.keySize = C.prototype.keySize = length / 8; - - return C; -} - -//Paul Tero, July 2001 -//http://www.tero.co.uk/des/ -// -//Optimised for performance with large blocks by Michael Hayworth, November 2001 -//http://www.netdealing.com -// -// Modified by Recurity Labs GmbH - -//THIS SOFTWARE IS PROVIDED "AS IS" AND -//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -//FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -//DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -//OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -//HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -//OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -//SUCH DAMAGE. - -//des -//this takes the key, the message, and whether to encrypt or decrypt - -function des(keys, message, encrypt, mode, iv, padding) { - //declaring this locally speeds things up a bit - const spfunction1 = [ - 0x1010400, 0, 0x10000, 0x1010404, 0x1010004, 0x10404, 0x4, 0x10000, 0x400, 0x1010400, - 0x1010404, 0x400, 0x1000404, 0x1010004, 0x1000000, 0x4, 0x404, 0x1000400, 0x1000400, 0x10400, 0x10400, 0x1010000, - 0x1010000, 0x1000404, 0x10004, 0x1000004, 0x1000004, 0x10004, 0, 0x404, 0x10404, 0x1000000, 0x10000, 0x1010404, 0x4, - 0x1010000, 0x1010400, 0x1000000, 0x1000000, 0x400, 0x1010004, 0x10000, 0x10400, 0x1000004, 0x400, 0x4, 0x1000404, - 0x10404, 0x1010404, 0x10004, 0x1010000, 0x1000404, 0x1000004, 0x404, 0x10404, 0x1010400, 0x404, 0x1000400, - 0x1000400, 0, 0x10004, 0x10400, 0, 0x1010004 - ]; - const spfunction2 = [ - -0x7fef7fe0, -0x7fff8000, 0x8000, 0x108020, 0x100000, 0x20, -0x7fefffe0, -0x7fff7fe0, - -0x7fffffe0, -0x7fef7fe0, -0x7fef8000, -0x80000000, -0x7fff8000, 0x100000, 0x20, -0x7fefffe0, 0x108000, 0x100020, - -0x7fff7fe0, 0, -0x80000000, 0x8000, 0x108020, -0x7ff00000, 0x100020, -0x7fffffe0, 0, 0x108000, 0x8020, -0x7fef8000, - -0x7ff00000, 0x8020, 0, 0x108020, -0x7fefffe0, 0x100000, -0x7fff7fe0, -0x7ff00000, -0x7fef8000, 0x8000, -0x7ff00000, - -0x7fff8000, 0x20, -0x7fef7fe0, 0x108020, 0x20, 0x8000, -0x80000000, 0x8020, -0x7fef8000, 0x100000, -0x7fffffe0, - 0x100020, -0x7fff7fe0, -0x7fffffe0, 0x100020, 0x108000, 0, -0x7fff8000, 0x8020, -0x80000000, -0x7fefffe0, - -0x7fef7fe0, 0x108000 - ]; - const spfunction3 = [ - 0x208, 0x8020200, 0, 0x8020008, 0x8000200, 0, 0x20208, 0x8000200, 0x20008, 0x8000008, - 0x8000008, 0x20000, 0x8020208, 0x20008, 0x8020000, 0x208, 0x8000000, 0x8, 0x8020200, 0x200, 0x20200, 0x8020000, - 0x8020008, 0x20208, 0x8000208, 0x20200, 0x20000, 0x8000208, 0x8, 0x8020208, 0x200, 0x8000000, 0x8020200, 0x8000000, - 0x20008, 0x208, 0x20000, 0x8020200, 0x8000200, 0, 0x200, 0x20008, 0x8020208, 0x8000200, 0x8000008, 0x200, 0, - 0x8020008, 0x8000208, 0x20000, 0x8000000, 0x8020208, 0x8, 0x20208, 0x20200, 0x8000008, 0x8020000, 0x8000208, 0x208, - 0x8020000, 0x20208, 0x8, 0x8020008, 0x20200 - ]; - const spfunction4 = [ - 0x802001, 0x2081, 0x2081, 0x80, 0x802080, 0x800081, 0x800001, 0x2001, 0, 0x802000, - 0x802000, 0x802081, 0x81, 0, 0x800080, 0x800001, 0x1, 0x2000, 0x800000, 0x802001, 0x80, 0x800000, 0x2001, 0x2080, - 0x800081, 0x1, 0x2080, 0x800080, 0x2000, 0x802080, 0x802081, 0x81, 0x800080, 0x800001, 0x802000, 0x802081, 0x81, 0, - 0, 0x802000, 0x2080, 0x800080, 0x800081, 0x1, 0x802001, 0x2081, 0x2081, 0x80, 0x802081, 0x81, 0x1, 0x2000, 0x800001, - 0x2001, 0x802080, 0x800081, 0x2001, 0x2080, 0x800000, 0x802001, 0x80, 0x800000, 0x2000, 0x802080 - ]; - const spfunction5 = [ - 0x100, 0x2080100, 0x2080000, 0x42000100, 0x80000, 0x100, 0x40000000, 0x2080000, - 0x40080100, 0x80000, 0x2000100, 0x40080100, 0x42000100, 0x42080000, 0x80100, 0x40000000, 0x2000000, 0x40080000, - 0x40080000, 0, 0x40000100, 0x42080100, 0x42080100, 0x2000100, 0x42080000, 0x40000100, 0, 0x42000000, 0x2080100, - 0x2000000, 0x42000000, 0x80100, 0x80000, 0x42000100, 0x100, 0x2000000, 0x40000000, 0x2080000, 0x42000100, - 0x40080100, 0x2000100, 0x40000000, 0x42080000, 0x2080100, 0x40080100, 0x100, 0x2000000, 0x42080000, 0x42080100, - 0x80100, 0x42000000, 0x42080100, 0x2080000, 0, 0x40080000, 0x42000000, 0x80100, 0x2000100, 0x40000100, 0x80000, 0, - 0x40080000, 0x2080100, 0x40000100 - ]; - const spfunction6 = [ - 0x20000010, 0x20400000, 0x4000, 0x20404010, 0x20400000, 0x10, 0x20404010, 0x400000, - 0x20004000, 0x404010, 0x400000, 0x20000010, 0x400010, 0x20004000, 0x20000000, 0x4010, 0, 0x400010, 0x20004010, - 0x4000, 0x404000, 0x20004010, 0x10, 0x20400010, 0x20400010, 0, 0x404010, 0x20404000, 0x4010, 0x404000, 0x20404000, - 0x20000000, 0x20004000, 0x10, 0x20400010, 0x404000, 0x20404010, 0x400000, 0x4010, 0x20000010, 0x400000, 0x20004000, - 0x20000000, 0x4010, 0x20000010, 0x20404010, 0x404000, 0x20400000, 0x404010, 0x20404000, 0, 0x20400010, 0x10, 0x4000, - 0x20400000, 0x404010, 0x4000, 0x400010, 0x20004010, 0, 0x20404000, 0x20000000, 0x400010, 0x20004010 - ]; - const spfunction7 = [ - 0x200000, 0x4200002, 0x4000802, 0, 0x800, 0x4000802, 0x200802, 0x4200800, 0x4200802, - 0x200000, 0, 0x4000002, 0x2, 0x4000000, 0x4200002, 0x802, 0x4000800, 0x200802, 0x200002, 0x4000800, 0x4000002, - 0x4200000, 0x4200800, 0x200002, 0x4200000, 0x800, 0x802, 0x4200802, 0x200800, 0x2, 0x4000000, 0x200800, 0x4000000, - 0x200800, 0x200000, 0x4000802, 0x4000802, 0x4200002, 0x4200002, 0x2, 0x200002, 0x4000000, 0x4000800, 0x200000, - 0x4200800, 0x802, 0x200802, 0x4200800, 0x802, 0x4000002, 0x4200802, 0x4200000, 0x200800, 0, 0x2, 0x4200802, 0, - 0x200802, 0x4200000, 0x800, 0x4000002, 0x4000800, 0x800, 0x200002 - ]; - const spfunction8 = [ - 0x10001040, 0x1000, 0x40000, 0x10041040, 0x10000000, 0x10001040, 0x40, 0x10000000, - 0x40040, 0x10040000, 0x10041040, 0x41000, 0x10041000, 0x41040, 0x1000, 0x40, 0x10040000, 0x10000040, 0x10001000, - 0x1040, 0x41000, 0x40040, 0x10040040, 0x10041000, 0x1040, 0, 0, 0x10040040, 0x10000040, 0x10001000, 0x41040, - 0x40000, 0x41040, 0x40000, 0x10041000, 0x1000, 0x40, 0x10040040, 0x1000, 0x41040, 0x10001000, 0x40, 0x10000040, - 0x10040000, 0x10040040, 0x10000000, 0x40000, 0x10001040, 0, 0x10041040, 0x40040, 0x10000040, 0x10040000, 0x10001000, - 0x10001040, 0, 0x10041040, 0x41000, 0x41000, 0x1040, 0x1040, 0x40040, 0x10000000, 0x10041000 - ]; - - //create the 16 or 48 subkeys we will need - let m = 0; - let i; - let j; - let temp; - let right1; - let right2; - let left; - let right; - let looping; - let cbcleft; - let cbcleft2; - let cbcright; - let cbcright2; - let endloop; - let loopinc; - let len = message.length; - - //set up the loops for single and triple des - const iterations = keys.length === 32 ? 3 : 9; //single or triple des - if (iterations === 3) { - looping = encrypt ? [0, 32, 2] : [30, -2, -2]; - } else { - looping = encrypt ? [0, 32, 2, 62, 30, -2, 64, 96, 2] : [94, 62, -2, 32, 64, 2, 30, -2, -2]; - } - - //pad the message depending on the padding parameter - //only add padding if encrypting - note that you need to use the same padding option for both encrypt and decrypt - if (encrypt) { - message = desAddPadding(message, padding); - len = message.length; - } - - //store the result here - let result = new Uint8Array(len); - let k = 0; - - if (mode === 1) { //CBC mode - cbcleft = (iv[m++] << 24) | (iv[m++] << 16) | (iv[m++] << 8) | iv[m++]; - cbcright = (iv[m++] << 24) | (iv[m++] << 16) | (iv[m++] << 8) | iv[m++]; - m = 0; - } - - //loop through each 64 bit chunk of the message - while (m < len) { - left = (message[m++] << 24) | (message[m++] << 16) | (message[m++] << 8) | message[m++]; - right = (message[m++] << 24) | (message[m++] << 16) | (message[m++] << 8) | message[m++]; - - //for Cipher Block Chaining mode, xor the message with the previous result - if (mode === 1) { - if (encrypt) { - left ^= cbcleft; - right ^= cbcright; - } else { - cbcleft2 = cbcleft; - cbcright2 = cbcright; - cbcleft = left; - cbcright = right; - } - } - - //first each 64 but chunk of the message must be permuted according to IP - temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; - right ^= temp; - left ^= (temp << 4); - temp = ((left >>> 16) ^ right) & 0x0000ffff; - right ^= temp; - left ^= (temp << 16); - temp = ((right >>> 2) ^ left) & 0x33333333; - left ^= temp; - right ^= (temp << 2); - temp = ((right >>> 8) ^ left) & 0x00ff00ff; - left ^= temp; - right ^= (temp << 8); - temp = ((left >>> 1) ^ right) & 0x55555555; - right ^= temp; - left ^= (temp << 1); - - left = ((left << 1) | (left >>> 31)); - right = ((right << 1) | (right >>> 31)); - - //do this either 1 or 3 times for each chunk of the message - for (j = 0; j < iterations; j += 3) { - endloop = looping[j + 1]; - loopinc = looping[j + 2]; - //now go through and perform the encryption or decryption - for (i = looping[j]; i !== endloop; i += loopinc) { //for efficiency - right1 = right ^ keys[i]; - right2 = ((right >>> 4) | (right << 28)) ^ keys[i + 1]; - //the result is attained by passing these bytes through the S selection functions - temp = left; - left = right; - right = temp ^ (spfunction2[(right1 >>> 24) & 0x3f] | spfunction4[(right1 >>> 16) & 0x3f] | spfunction6[(right1 >>> - 8) & 0x3f] | spfunction8[right1 & 0x3f] | spfunction1[(right2 >>> 24) & 0x3f] | spfunction3[(right2 >>> 16) & - 0x3f] | spfunction5[(right2 >>> 8) & 0x3f] | spfunction7[right2 & 0x3f]); - } - temp = left; - left = right; - right = temp; //unreverse left and right - } //for either 1 or 3 iterations - - //move then each one bit to the right - left = ((left >>> 1) | (left << 31)); - right = ((right >>> 1) | (right << 31)); - - //now perform IP-1, which is IP in the opposite direction - temp = ((left >>> 1) ^ right) & 0x55555555; - right ^= temp; - left ^= (temp << 1); - temp = ((right >>> 8) ^ left) & 0x00ff00ff; - left ^= temp; - right ^= (temp << 8); - temp = ((right >>> 2) ^ left) & 0x33333333; - left ^= temp; - right ^= (temp << 2); - temp = ((left >>> 16) ^ right) & 0x0000ffff; - right ^= temp; - left ^= (temp << 16); - temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; - right ^= temp; - left ^= (temp << 4); - - //for Cipher Block Chaining mode, xor the message with the previous result - if (mode === 1) { - if (encrypt) { - cbcleft = left; - cbcright = right; - } else { - left ^= cbcleft2; - right ^= cbcright2; - } - } - - result[k++] = (left >>> 24); - result[k++] = ((left >>> 16) & 0xff); - result[k++] = ((left >>> 8) & 0xff); - result[k++] = (left & 0xff); - result[k++] = (right >>> 24); - result[k++] = ((right >>> 16) & 0xff); - result[k++] = ((right >>> 8) & 0xff); - result[k++] = (right & 0xff); - } //for every 8 characters, or 64 bits in the message - - //only remove padding if decrypting - note that you need to use the same padding option for both encrypt and decrypt - if (!encrypt) { - result = desRemovePadding(result, padding); - } - - return result; -} //end of des - - -//desCreateKeys -//this takes as input a 64 bit key (even though only 56 bits are used) -//as an array of 2 integers, and returns 16 48 bit keys - -function desCreateKeys(key) { - //declaring this locally speeds things up a bit - const pc2bytes0 = [ - 0, 0x4, 0x20000000, 0x20000004, 0x10000, 0x10004, 0x20010000, 0x20010004, 0x200, 0x204, - 0x20000200, 0x20000204, 0x10200, 0x10204, 0x20010200, 0x20010204 - ]; - const pc2bytes1 = [ - 0, 0x1, 0x100000, 0x100001, 0x4000000, 0x4000001, 0x4100000, 0x4100001, 0x100, 0x101, 0x100100, - 0x100101, 0x4000100, 0x4000101, 0x4100100, 0x4100101 - ]; - const pc2bytes2 = [ - 0, 0x8, 0x800, 0x808, 0x1000000, 0x1000008, 0x1000800, 0x1000808, 0, 0x8, 0x800, 0x808, - 0x1000000, 0x1000008, 0x1000800, 0x1000808 - ]; - const pc2bytes3 = [ - 0, 0x200000, 0x8000000, 0x8200000, 0x2000, 0x202000, 0x8002000, 0x8202000, 0x20000, 0x220000, - 0x8020000, 0x8220000, 0x22000, 0x222000, 0x8022000, 0x8222000 - ]; - const pc2bytes4 = [ - 0, 0x40000, 0x10, 0x40010, 0, 0x40000, 0x10, 0x40010, 0x1000, 0x41000, 0x1010, 0x41010, 0x1000, - 0x41000, 0x1010, 0x41010 - ]; - const pc2bytes5 = [ - 0, 0x400, 0x20, 0x420, 0, 0x400, 0x20, 0x420, 0x2000000, 0x2000400, 0x2000020, 0x2000420, - 0x2000000, 0x2000400, 0x2000020, 0x2000420 - ]; - const pc2bytes6 = [ - 0, 0x10000000, 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002, 0, 0x10000000, - 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002 - ]; - const pc2bytes7 = [ - 0, 0x10000, 0x800, 0x10800, 0x20000000, 0x20010000, 0x20000800, 0x20010800, 0x20000, 0x30000, - 0x20800, 0x30800, 0x20020000, 0x20030000, 0x20020800, 0x20030800 - ]; - const pc2bytes8 = [ - 0, 0x40000, 0, 0x40000, 0x2, 0x40002, 0x2, 0x40002, 0x2000000, 0x2040000, 0x2000000, 0x2040000, - 0x2000002, 0x2040002, 0x2000002, 0x2040002 - ]; - const pc2bytes9 = [ - 0, 0x10000000, 0x8, 0x10000008, 0, 0x10000000, 0x8, 0x10000008, 0x400, 0x10000400, 0x408, - 0x10000408, 0x400, 0x10000400, 0x408, 0x10000408 - ]; - const pc2bytes10 = [ - 0, 0x20, 0, 0x20, 0x100000, 0x100020, 0x100000, 0x100020, 0x2000, 0x2020, 0x2000, 0x2020, - 0x102000, 0x102020, 0x102000, 0x102020 - ]; - const pc2bytes11 = [ - 0, 0x1000000, 0x200, 0x1000200, 0x200000, 0x1200000, 0x200200, 0x1200200, 0x4000000, 0x5000000, - 0x4000200, 0x5000200, 0x4200000, 0x5200000, 0x4200200, 0x5200200 - ]; - const pc2bytes12 = [ - 0, 0x1000, 0x8000000, 0x8001000, 0x80000, 0x81000, 0x8080000, 0x8081000, 0x10, 0x1010, - 0x8000010, 0x8001010, 0x80010, 0x81010, 0x8080010, 0x8081010 - ]; - const pc2bytes13 = [0, 0x4, 0x100, 0x104, 0, 0x4, 0x100, 0x104, 0x1, 0x5, 0x101, 0x105, 0x1, 0x5, 0x101, 0x105]; - - //how many iterations (1 for des, 3 for triple des) - const iterations = key.length > 8 ? 3 : 1; //changed by Paul 16/6/2007 to use Triple DES for 9+ byte keys - //stores the return keys - const keys = new Array(32 * iterations); - //now define the left shifts which need to be done - const shifts = [0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0]; - //other variables - let lefttemp; - let righttemp; - let m = 0; - let n = 0; - let temp; - - for (let j = 0; j < iterations; j++) { //either 1 or 3 iterations - let left = (key[m++] << 24) | (key[m++] << 16) | (key[m++] << 8) | key[m++]; - let right = (key[m++] << 24) | (key[m++] << 16) | (key[m++] << 8) | key[m++]; - - temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; - right ^= temp; - left ^= (temp << 4); - temp = ((right >>> -16) ^ left) & 0x0000ffff; - left ^= temp; - right ^= (temp << -16); - temp = ((left >>> 2) ^ right) & 0x33333333; - right ^= temp; - left ^= (temp << 2); - temp = ((right >>> -16) ^ left) & 0x0000ffff; - left ^= temp; - right ^= (temp << -16); - temp = ((left >>> 1) ^ right) & 0x55555555; - right ^= temp; - left ^= (temp << 1); - temp = ((right >>> 8) ^ left) & 0x00ff00ff; - left ^= temp; - right ^= (temp << 8); - temp = ((left >>> 1) ^ right) & 0x55555555; - right ^= temp; - left ^= (temp << 1); - - //the right side needs to be shifted and to get the last four bits of the left side - temp = (left << 8) | ((right >>> 20) & 0x000000f0); - //left needs to be put upside down - left = (right << 24) | ((right << 8) & 0xff0000) | ((right >>> 8) & 0xff00) | ((right >>> 24) & 0xf0); - right = temp; - - //now go through and perform these shifts on the left and right keys - for (let i = 0; i < shifts.length; i++) { - //shift the keys either one or two bits to the left - if (shifts[i]) { - left = (left << 2) | (left >>> 26); - right = (right << 2) | (right >>> 26); - } else { - left = (left << 1) | (left >>> 27); - right = (right << 1) | (right >>> 27); - } - left &= -0xf; - right &= -0xf; - - //now apply PC-2, in such a way that E is easier when encrypting or decrypting - //this conversion will look like PC-2 except only the last 6 bits of each byte are used - //rather than 48 consecutive bits and the order of lines will be according to - //how the S selection functions will be applied: S2, S4, S6, S8, S1, S3, S5, S7 - lefttemp = pc2bytes0[left >>> 28] | pc2bytes1[(left >>> 24) & 0xf] | pc2bytes2[(left >>> 20) & 0xf] | pc2bytes3[( - left >>> 16) & 0xf] | pc2bytes4[(left >>> 12) & 0xf] | pc2bytes5[(left >>> 8) & 0xf] | pc2bytes6[(left >>> 4) & - 0xf]; - righttemp = pc2bytes7[right >>> 28] | pc2bytes8[(right >>> 24) & 0xf] | pc2bytes9[(right >>> 20) & 0xf] | - pc2bytes10[(right >>> 16) & 0xf] | pc2bytes11[(right >>> 12) & 0xf] | pc2bytes12[(right >>> 8) & 0xf] | - pc2bytes13[(right >>> 4) & 0xf]; - temp = ((righttemp >>> 16) ^ lefttemp) & 0x0000ffff; - keys[n++] = lefttemp ^ temp; - keys[n++] = righttemp ^ (temp << 16); - } - } //for each iterations - //return the keys we've created - return keys; -} //end of desCreateKeys - - -function desAddPadding(message, padding) { - const padLength = 8 - (message.length % 8); - - let pad; - if (padding === 2 && (padLength < 8)) { //pad the message with spaces - pad = ' '.charCodeAt(0); - } else if (padding === 1) { //PKCS7 padding - pad = padLength; - } else if (!padding && (padLength < 8)) { //pad the message out with null bytes - pad = 0; - } else if (padLength === 8) { - return message; - } else { - throw new Error('des: invalid padding'); - } - - const paddedMessage = new Uint8Array(message.length + padLength); - for (let i = 0; i < message.length; i++) { - paddedMessage[i] = message[i]; - } - for (let j = 0; j < padLength; j++) { - paddedMessage[message.length + j] = pad; - } - - return paddedMessage; -} - -function desRemovePadding(message, padding) { - let padLength = null; - let pad; - if (padding === 2) { // space padded - pad = ' '.charCodeAt(0); - } else if (padding === 1) { // PKCS7 - padLength = message[message.length - 1]; - } else if (!padding) { // null padding - pad = 0; - } else { - throw new Error('des: invalid padding'); - } - - if (!padLength) { - padLength = 1; - while (message[message.length - padLength] === pad) { - padLength++; - } - padLength--; - } - - return message.subarray(0, message.length - padLength); -} - -// added by Recurity Labs - -function TripleDES(key) { - this.key = []; - - for (let i = 0; i < 3; i++) { - this.key.push(new Uint8Array(key.subarray(i * 8, (i * 8) + 8))); - } - - this.encrypt = function(block) { - return des( - desCreateKeys(this.key[2]), - des( - desCreateKeys(this.key[1]), - des( - desCreateKeys(this.key[0]), - block, true, 0, null, null - ), - false, 0, null, null - ), true, 0, null, null - ); - }; -} - -TripleDES.keySize = TripleDES.prototype.keySize = 24; -TripleDES.blockSize = TripleDES.prototype.blockSize = 8; - -// This is "original" DES - -function DES(key) { - this.key = key; - - this.encrypt = function(block, padding) { - const keys = desCreateKeys(this.key); - return des(keys, block, true, 0, null, padding); - }; - - this.decrypt = function(block, padding) { - const keys = desCreateKeys(this.key); - return des(keys, block, false, 0, null, padding); - }; -} - -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Copyright 2010 pjacobs@xeekr.com . All rights reserved. - -// Modified by Recurity Labs GmbH - -// fixed/modified by Herbert Hanewinkel, www.haneWIN.de -// check www.haneWIN.de for the latest version - -// cast5.js is a Javascript implementation of CAST-128, as defined in RFC 2144. -// CAST-128 is a common OpenPGP cipher. - - -// CAST5 constructor - -function OpenPGPSymEncCAST5() { - this.BlockSize = 8; - this.KeySize = 16; - - this.setKey = function(key) { - this.masking = new Array(16); - this.rotate = new Array(16); - - this.reset(); - - if (key.length === this.KeySize) { - this.keySchedule(key); - } else { - throw new Error('CAST-128: keys must be 16 bytes'); - } - return true; - }; - - this.reset = function() { - for (let i = 0; i < 16; i++) { - this.masking[i] = 0; - this.rotate[i] = 0; - } - }; - - this.getBlockSize = function() { - return this.BlockSize; - }; - - this.encrypt = function(src) { - const dst = new Array(src.length); - - for (let i = 0; i < src.length; i += 8) { - let l = (src[i] << 24) | (src[i + 1] << 16) | (src[i + 2] << 8) | src[i + 3]; - let r = (src[i + 4] << 24) | (src[i + 5] << 16) | (src[i + 6] << 8) | src[i + 7]; - let t; - - t = r; - r = l ^ f1(r, this.masking[0], this.rotate[0]); - l = t; - t = r; - r = l ^ f2(r, this.masking[1], this.rotate[1]); - l = t; - t = r; - r = l ^ f3(r, this.masking[2], this.rotate[2]); - l = t; - t = r; - r = l ^ f1(r, this.masking[3], this.rotate[3]); - l = t; - - t = r; - r = l ^ f2(r, this.masking[4], this.rotate[4]); - l = t; - t = r; - r = l ^ f3(r, this.masking[5], this.rotate[5]); - l = t; - t = r; - r = l ^ f1(r, this.masking[6], this.rotate[6]); - l = t; - t = r; - r = l ^ f2(r, this.masking[7], this.rotate[7]); - l = t; - - t = r; - r = l ^ f3(r, this.masking[8], this.rotate[8]); - l = t; - t = r; - r = l ^ f1(r, this.masking[9], this.rotate[9]); - l = t; - t = r; - r = l ^ f2(r, this.masking[10], this.rotate[10]); - l = t; - t = r; - r = l ^ f3(r, this.masking[11], this.rotate[11]); - l = t; - - t = r; - r = l ^ f1(r, this.masking[12], this.rotate[12]); - l = t; - t = r; - r = l ^ f2(r, this.masking[13], this.rotate[13]); - l = t; - t = r; - r = l ^ f3(r, this.masking[14], this.rotate[14]); - l = t; - t = r; - r = l ^ f1(r, this.masking[15], this.rotate[15]); - l = t; - - dst[i] = (r >>> 24) & 255; - dst[i + 1] = (r >>> 16) & 255; - dst[i + 2] = (r >>> 8) & 255; - dst[i + 3] = r & 255; - dst[i + 4] = (l >>> 24) & 255; - dst[i + 5] = (l >>> 16) & 255; - dst[i + 6] = (l >>> 8) & 255; - dst[i + 7] = l & 255; - } - - return dst; - }; - - this.decrypt = function(src) { - const dst = new Array(src.length); - - for (let i = 0; i < src.length; i += 8) { - let l = (src[i] << 24) | (src[i + 1] << 16) | (src[i + 2] << 8) | src[i + 3]; - let r = (src[i + 4] << 24) | (src[i + 5] << 16) | (src[i + 6] << 8) | src[i + 7]; - let t; - - t = r; - r = l ^ f1(r, this.masking[15], this.rotate[15]); - l = t; - t = r; - r = l ^ f3(r, this.masking[14], this.rotate[14]); - l = t; - t = r; - r = l ^ f2(r, this.masking[13], this.rotate[13]); - l = t; - t = r; - r = l ^ f1(r, this.masking[12], this.rotate[12]); - l = t; - - t = r; - r = l ^ f3(r, this.masking[11], this.rotate[11]); - l = t; - t = r; - r = l ^ f2(r, this.masking[10], this.rotate[10]); - l = t; - t = r; - r = l ^ f1(r, this.masking[9], this.rotate[9]); - l = t; - t = r; - r = l ^ f3(r, this.masking[8], this.rotate[8]); - l = t; - - t = r; - r = l ^ f2(r, this.masking[7], this.rotate[7]); - l = t; - t = r; - r = l ^ f1(r, this.masking[6], this.rotate[6]); - l = t; - t = r; - r = l ^ f3(r, this.masking[5], this.rotate[5]); - l = t; - t = r; - r = l ^ f2(r, this.masking[4], this.rotate[4]); - l = t; - - t = r; - r = l ^ f1(r, this.masking[3], this.rotate[3]); - l = t; - t = r; - r = l ^ f3(r, this.masking[2], this.rotate[2]); - l = t; - t = r; - r = l ^ f2(r, this.masking[1], this.rotate[1]); - l = t; - t = r; - r = l ^ f1(r, this.masking[0], this.rotate[0]); - l = t; - - dst[i] = (r >>> 24) & 255; - dst[i + 1] = (r >>> 16) & 255; - dst[i + 2] = (r >>> 8) & 255; - dst[i + 3] = r & 255; - dst[i + 4] = (l >>> 24) & 255; - dst[i + 5] = (l >> 16) & 255; - dst[i + 6] = (l >> 8) & 255; - dst[i + 7] = l & 255; - } - - return dst; - }; - const scheduleA = new Array(4); - - scheduleA[0] = new Array(4); - scheduleA[0][0] = [4, 0, 0xd, 0xf, 0xc, 0xe, 0x8]; - scheduleA[0][1] = [5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa]; - scheduleA[0][2] = [6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9]; - scheduleA[0][3] = [7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb]; - - scheduleA[1] = new Array(4); - scheduleA[1][0] = [0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0]; - scheduleA[1][1] = [1, 4, 0, 2, 1, 3, 16 + 2]; - scheduleA[1][2] = [2, 5, 7, 6, 5, 4, 16 + 1]; - scheduleA[1][3] = [3, 7, 0xa, 9, 0xb, 8, 16 + 3]; - - scheduleA[2] = new Array(4); - scheduleA[2][0] = [4, 0, 0xd, 0xf, 0xc, 0xe, 8]; - scheduleA[2][1] = [5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa]; - scheduleA[2][2] = [6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9]; - scheduleA[2][3] = [7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb]; - - - scheduleA[3] = new Array(4); - scheduleA[3][0] = [0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0]; - scheduleA[3][1] = [1, 4, 0, 2, 1, 3, 16 + 2]; - scheduleA[3][2] = [2, 5, 7, 6, 5, 4, 16 + 1]; - scheduleA[3][3] = [3, 7, 0xa, 9, 0xb, 8, 16 + 3]; - - const scheduleB = new Array(4); - - scheduleB[0] = new Array(4); - scheduleB[0][0] = [16 + 8, 16 + 9, 16 + 7, 16 + 6, 16 + 2]; - scheduleB[0][1] = [16 + 0xa, 16 + 0xb, 16 + 5, 16 + 4, 16 + 6]; - scheduleB[0][2] = [16 + 0xc, 16 + 0xd, 16 + 3, 16 + 2, 16 + 9]; - scheduleB[0][3] = [16 + 0xe, 16 + 0xf, 16 + 1, 16 + 0, 16 + 0xc]; - - scheduleB[1] = new Array(4); - scheduleB[1][0] = [3, 2, 0xc, 0xd, 8]; - scheduleB[1][1] = [1, 0, 0xe, 0xf, 0xd]; - scheduleB[1][2] = [7, 6, 8, 9, 3]; - scheduleB[1][3] = [5, 4, 0xa, 0xb, 7]; - - - scheduleB[2] = new Array(4); - scheduleB[2][0] = [16 + 3, 16 + 2, 16 + 0xc, 16 + 0xd, 16 + 9]; - scheduleB[2][1] = [16 + 1, 16 + 0, 16 + 0xe, 16 + 0xf, 16 + 0xc]; - scheduleB[2][2] = [16 + 7, 16 + 6, 16 + 8, 16 + 9, 16 + 2]; - scheduleB[2][3] = [16 + 5, 16 + 4, 16 + 0xa, 16 + 0xb, 16 + 6]; - - - scheduleB[3] = new Array(4); - scheduleB[3][0] = [8, 9, 7, 6, 3]; - scheduleB[3][1] = [0xa, 0xb, 5, 4, 7]; - scheduleB[3][2] = [0xc, 0xd, 3, 2, 8]; - scheduleB[3][3] = [0xe, 0xf, 1, 0, 0xd]; - - // changed 'in' to 'inn' (in javascript 'in' is a reserved word) - this.keySchedule = function(inn) { - const t = new Array(8); - const k = new Array(32); - - let j; - - for (let i = 0; i < 4; i++) { - j = i * 4; - t[i] = (inn[j] << 24) | (inn[j + 1] << 16) | (inn[j + 2] << 8) | inn[j + 3]; - } - - const x = [6, 7, 4, 5]; - let ki = 0; - let w; - - for (let half = 0; half < 2; half++) { - for (let round = 0; round < 4; round++) { - for (j = 0; j < 4; j++) { - const a = scheduleA[round][j]; - w = t[a[1]]; - - w ^= sBox[4][(t[a[2] >>> 2] >>> (24 - 8 * (a[2] & 3))) & 0xff]; - w ^= sBox[5][(t[a[3] >>> 2] >>> (24 - 8 * (a[3] & 3))) & 0xff]; - w ^= sBox[6][(t[a[4] >>> 2] >>> (24 - 8 * (a[4] & 3))) & 0xff]; - w ^= sBox[7][(t[a[5] >>> 2] >>> (24 - 8 * (a[5] & 3))) & 0xff]; - w ^= sBox[x[j]][(t[a[6] >>> 2] >>> (24 - 8 * (a[6] & 3))) & 0xff]; - t[a[0]] = w; - } - - for (j = 0; j < 4; j++) { - const b = scheduleB[round][j]; - w = sBox[4][(t[b[0] >>> 2] >>> (24 - 8 * (b[0] & 3))) & 0xff]; - - w ^= sBox[5][(t[b[1] >>> 2] >>> (24 - 8 * (b[1] & 3))) & 0xff]; - w ^= sBox[6][(t[b[2] >>> 2] >>> (24 - 8 * (b[2] & 3))) & 0xff]; - w ^= sBox[7][(t[b[3] >>> 2] >>> (24 - 8 * (b[3] & 3))) & 0xff]; - w ^= sBox[4 + j][(t[b[4] >>> 2] >>> (24 - 8 * (b[4] & 3))) & 0xff]; - k[ki] = w; - ki++; - } - } - } - - for (let i = 0; i < 16; i++) { - this.masking[i] = k[i]; - this.rotate[i] = k[16 + i] & 0x1f; - } - }; - - // These are the three 'f' functions. See RFC 2144, section 2.2. - - function f1(d, m, r) { - const t = m + d; - const I = (t << r) | (t >>> (32 - r)); - return ((sBox[0][I >>> 24] ^ sBox[1][(I >>> 16) & 255]) - sBox[2][(I >>> 8) & 255]) + sBox[3][I & 255]; - } - - function f2(d, m, r) { - const t = m ^ d; - const I = (t << r) | (t >>> (32 - r)); - return ((sBox[0][I >>> 24] - sBox[1][(I >>> 16) & 255]) + sBox[2][(I >>> 8) & 255]) ^ sBox[3][I & 255]; - } - - function f3(d, m, r) { - const t = m - d; - const I = (t << r) | (t >>> (32 - r)); - return ((sBox[0][I >>> 24] + sBox[1][(I >>> 16) & 255]) ^ sBox[2][(I >>> 8) & 255]) - sBox[3][I & 255]; - } - - const sBox = new Array(8); - sBox[0] = [ - 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949, - 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, - 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, - 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0, - 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, - 0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935, - 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d, - 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, - 0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe, - 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3, - 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, - 0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291, - 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779, - 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, - 0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, - 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d, - 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, - 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, - 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c, - 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, - 0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d, - 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96, - 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, - 0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, - 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, - 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, - 0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, - 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872, - 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, - 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, - 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9, - 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf - ]; - - sBox[1] = [ - 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651, - 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, - 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, - 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806, - 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, - 0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359, - 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b, - 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, - 0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34, - 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb, - 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, - 0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860, - 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b, - 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, - 0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, - 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, - 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, - 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, - 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f, - 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, - 0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6, - 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58, - 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, - 0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, - 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6, - 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, - 0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6, - 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f, - 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, - 0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, - 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9, - 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1 - ]; - - sBox[2] = [ - 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90, - 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, - 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, - 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240, - 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, - 0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, - 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71, - 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, - 0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, - 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15, - 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, - 0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176, - 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148, - 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, - 0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, - 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e, - 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, - 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, - 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a, - 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, - 0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, - 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5, - 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, - 0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536, - 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, - 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, - 0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69, - 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, - 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, - 0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, - 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a, - 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783 - ]; - - sBox[3] = [ - 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1, - 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, - 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, - 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121, - 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, - 0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, - 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb, - 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, - 0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d, - 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6, - 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, - 0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003, - 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, - 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, - 0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, - 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a, - 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, - 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, - 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26, - 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, - 0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7, - 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417, - 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, - 0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2, - 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, - 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, - 0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, - 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, - 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, - 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, - 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282, - 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2 - ]; - - sBox[4] = [ - 0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f, - 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, - 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, - 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02, - 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, - 0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7, - 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9, - 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, - 0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774, - 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655, - 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, - 0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910, - 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1, - 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, - 0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, - 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f, - 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, - 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, - 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3, - 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, - 0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4, - 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2, - 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, - 0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5, - 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, - 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, - 0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801, - 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, - 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, - 0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, - 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8, - 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4 - ]; - - sBox[5] = [ - 0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac, - 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, - 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, - 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98, - 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, - 0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3, - 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd, - 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, - 0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9, - 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54, - 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, - 0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc, - 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf, - 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, - 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, - 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289, - 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, - 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, - 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b, - 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, - 0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13, - 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976, - 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, - 0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891, - 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da, - 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, - 0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084, - 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25, - 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, - 0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, - 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd, - 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f - ]; - - sBox[6] = [ - 0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f, - 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, - 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, - 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19, - 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, - 0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516, - 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88, - 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, - 0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756, - 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, - 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, - 0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688, - 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28, - 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, - 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, - 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, - 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, - 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, - 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566, - 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, - 0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962, - 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e, - 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, - 0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c, - 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, - 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, - 0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be, - 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767, - 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, - 0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, - 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c, - 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3 - ]; - - sBox[7] = [ - 0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5, - 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, - 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, - 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d, - 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, - 0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862, - 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc, - 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, - 0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e, - 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039, - 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, - 0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42, - 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5, - 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, - 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, - 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c, - 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, - 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, - 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70, - 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, - 0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c, - 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3, - 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, - 0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101, - 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f, - 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, - 0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a, - 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c, - 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, - 0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, - 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82, - 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e - ]; -} - -function CAST5(key) { - this.cast5 = new OpenPGPSymEncCAST5(); - this.cast5.setKey(key); - - this.encrypt = function(block) { - return this.cast5.encrypt(block); - }; -} - -CAST5.blockSize = CAST5.prototype.blockSize = 8; -CAST5.keySize = CAST5.prototype.keySize = 16; - -/* eslint-disable no-mixed-operators, no-fallthrough */ - - -/* Modified by Recurity Labs GmbH - * - * Cipher.js - * A block-cipher algorithm implementation on JavaScript - * See Cipher.readme.txt for further information. - * - * Copyright(c) 2009 Atsushi Oka [ http://oka.nu/ ] - * This script file is distributed under the LGPL - * - * ACKNOWLEDGMENT - * - * The main subroutines are written by Michiel van Everdingen. - * - * Michiel van Everdingen - * http://home.versatel.nl/MAvanEverdingen/index.html - * - * All rights for these routines are reserved to Michiel van Everdingen. - * - */ - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//Math -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -const MAXINT = 0xFFFFFFFF; - -function rotw(w, n) { - return (w << n | w >>> (32 - n)) & MAXINT; -} - -function getW(a, i) { - return a[i] | a[i + 1] << 8 | a[i + 2] << 16 | a[i + 3] << 24; -} - -function setW(a, i, w) { - a.splice(i, 4, w & 0xFF, (w >>> 8) & 0xFF, (w >>> 16) & 0xFF, (w >>> 24) & 0xFF); -} - -function getB(x, n) { - return (x >>> (n * 8)) & 0xFF; -} - -// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Twofish -// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -function createTwofish() { - // - let keyBytes = null; - let dataBytes = null; - let dataOffset = -1; - // var dataLength = -1; - // var idx2 = -1; - // - - let tfsKey = []; - let tfsM = [ - [], - [], - [], - [] - ]; - - function tfsInit(key) { - keyBytes = key; - let i; - let a; - let b; - let c; - let d; - const meKey = []; - const moKey = []; - const inKey = []; - let kLen; - const sKey = []; - let f01; - let f5b; - let fef; - - const q0 = [ - [8, 1, 7, 13, 6, 15, 3, 2, 0, 11, 5, 9, 14, 12, 10, 4], - [2, 8, 11, 13, 15, 7, 6, 14, 3, 1, 9, 4, 0, 10, 12, 5] - ]; - const q1 = [ - [14, 12, 11, 8, 1, 2, 3, 5, 15, 4, 10, 6, 7, 0, 9, 13], - [1, 14, 2, 11, 4, 12, 3, 7, 6, 13, 10, 5, 15, 9, 0, 8] - ]; - const q2 = [ - [11, 10, 5, 14, 6, 13, 9, 0, 12, 8, 15, 3, 2, 4, 7, 1], - [4, 12, 7, 5, 1, 6, 9, 10, 0, 14, 13, 8, 2, 11, 3, 15] - ]; - const q3 = [ - [13, 7, 15, 4, 1, 2, 6, 14, 9, 11, 3, 0, 8, 5, 12, 10], - [11, 9, 5, 1, 12, 3, 13, 14, 6, 4, 7, 15, 2, 0, 8, 10] - ]; - const ror4 = [0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15]; - const ashx = [0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 5, 14, 7]; - const q = [ - [], - [] - ]; - const m = [ - [], - [], - [], - [] - ]; - - function ffm5b(x) { - return x ^ (x >> 2) ^ [0, 90, 180, 238][x & 3]; - } - - function ffmEf(x) { - return x ^ (x >> 1) ^ (x >> 2) ^ [0, 238, 180, 90][x & 3]; - } - - function mdsRem(p, q) { - let i; - let t; - let u; - for (i = 0; i < 8; i++) { - t = q >>> 24; - q = ((q << 8) & MAXINT) | p >>> 24; - p = (p << 8) & MAXINT; - u = t << 1; - if (t & 128) { - u ^= 333; - } - q ^= t ^ (u << 16); - u ^= t >>> 1; - if (t & 1) { - u ^= 166; - } - q ^= u << 24 | u << 8; - } - return q; - } - - function qp(n, x) { - const a = x >> 4; - const b = x & 15; - const c = q0[n][a ^ b]; - const d = q1[n][ror4[b] ^ ashx[a]]; - return q3[n][ror4[d] ^ ashx[c]] << 4 | q2[n][c ^ d]; - } - - function hFun(x, key) { - let a = getB(x, 0); - let b = getB(x, 1); - let c = getB(x, 2); - let d = getB(x, 3); - switch (kLen) { - case 4: - a = q[1][a] ^ getB(key[3], 0); - b = q[0][b] ^ getB(key[3], 1); - c = q[0][c] ^ getB(key[3], 2); - d = q[1][d] ^ getB(key[3], 3); - case 3: - a = q[1][a] ^ getB(key[2], 0); - b = q[1][b] ^ getB(key[2], 1); - c = q[0][c] ^ getB(key[2], 2); - d = q[0][d] ^ getB(key[2], 3); - case 2: - a = q[0][q[0][a] ^ getB(key[1], 0)] ^ getB(key[0], 0); - b = q[0][q[1][b] ^ getB(key[1], 1)] ^ getB(key[0], 1); - c = q[1][q[0][c] ^ getB(key[1], 2)] ^ getB(key[0], 2); - d = q[1][q[1][d] ^ getB(key[1], 3)] ^ getB(key[0], 3); - } - return m[0][a] ^ m[1][b] ^ m[2][c] ^ m[3][d]; - } - - keyBytes = keyBytes.slice(0, 32); - i = keyBytes.length; - while (i !== 16 && i !== 24 && i !== 32) { - keyBytes[i++] = 0; - } - - for (i = 0; i < keyBytes.length; i += 4) { - inKey[i >> 2] = getW(keyBytes, i); - } - for (i = 0; i < 256; i++) { - q[0][i] = qp(0, i); - q[1][i] = qp(1, i); - } - for (i = 0; i < 256; i++) { - f01 = q[1][i]; - f5b = ffm5b(f01); - fef = ffmEf(f01); - m[0][i] = f01 + (f5b << 8) + (fef << 16) + (fef << 24); - m[2][i] = f5b + (fef << 8) + (f01 << 16) + (fef << 24); - f01 = q[0][i]; - f5b = ffm5b(f01); - fef = ffmEf(f01); - m[1][i] = fef + (fef << 8) + (f5b << 16) + (f01 << 24); - m[3][i] = f5b + (f01 << 8) + (fef << 16) + (f5b << 24); - } - - kLen = inKey.length / 2; - for (i = 0; i < kLen; i++) { - a = inKey[i + i]; - meKey[i] = a; - b = inKey[i + i + 1]; - moKey[i] = b; - sKey[kLen - i - 1] = mdsRem(a, b); - } - for (i = 0; i < 40; i += 2) { - a = 0x1010101 * i; - b = a + 0x1010101; - a = hFun(a, meKey); - b = rotw(hFun(b, moKey), 8); - tfsKey[i] = (a + b) & MAXINT; - tfsKey[i + 1] = rotw(a + 2 * b, 9); - } - for (i = 0; i < 256; i++) { - a = b = c = d = i; - switch (kLen) { - case 4: - a = q[1][a] ^ getB(sKey[3], 0); - b = q[0][b] ^ getB(sKey[3], 1); - c = q[0][c] ^ getB(sKey[3], 2); - d = q[1][d] ^ getB(sKey[3], 3); - case 3: - a = q[1][a] ^ getB(sKey[2], 0); - b = q[1][b] ^ getB(sKey[2], 1); - c = q[0][c] ^ getB(sKey[2], 2); - d = q[0][d] ^ getB(sKey[2], 3); - case 2: - tfsM[0][i] = m[0][q[0][q[0][a] ^ getB(sKey[1], 0)] ^ getB(sKey[0], 0)]; - tfsM[1][i] = m[1][q[0][q[1][b] ^ getB(sKey[1], 1)] ^ getB(sKey[0], 1)]; - tfsM[2][i] = m[2][q[1][q[0][c] ^ getB(sKey[1], 2)] ^ getB(sKey[0], 2)]; - tfsM[3][i] = m[3][q[1][q[1][d] ^ getB(sKey[1], 3)] ^ getB(sKey[0], 3)]; - } - } - } - - function tfsG0(x) { - return tfsM[0][getB(x, 0)] ^ tfsM[1][getB(x, 1)] ^ tfsM[2][getB(x, 2)] ^ tfsM[3][getB(x, 3)]; - } - - function tfsG1(x) { - return tfsM[0][getB(x, 3)] ^ tfsM[1][getB(x, 0)] ^ tfsM[2][getB(x, 1)] ^ tfsM[3][getB(x, 2)]; - } - - function tfsFrnd(r, blk) { - let a = tfsG0(blk[0]); - let b = tfsG1(blk[1]); - blk[2] = rotw(blk[2] ^ (a + b + tfsKey[4 * r + 8]) & MAXINT, 31); - blk[3] = rotw(blk[3], 1) ^ (a + 2 * b + tfsKey[4 * r + 9]) & MAXINT; - a = tfsG0(blk[2]); - b = tfsG1(blk[3]); - blk[0] = rotw(blk[0] ^ (a + b + tfsKey[4 * r + 10]) & MAXINT, 31); - blk[1] = rotw(blk[1], 1) ^ (a + 2 * b + tfsKey[4 * r + 11]) & MAXINT; - } - - function tfsIrnd(i, blk) { - let a = tfsG0(blk[0]); - let b = tfsG1(blk[1]); - blk[2] = rotw(blk[2], 1) ^ (a + b + tfsKey[4 * i + 10]) & MAXINT; - blk[3] = rotw(blk[3] ^ (a + 2 * b + tfsKey[4 * i + 11]) & MAXINT, 31); - a = tfsG0(blk[2]); - b = tfsG1(blk[3]); - blk[0] = rotw(blk[0], 1) ^ (a + b + tfsKey[4 * i + 8]) & MAXINT; - blk[1] = rotw(blk[1] ^ (a + 2 * b + tfsKey[4 * i + 9]) & MAXINT, 31); - } - - function tfsClose() { - tfsKey = []; - tfsM = [ - [], - [], - [], - [] - ]; - } - - function tfsEncrypt(data, offset) { - dataBytes = data; - dataOffset = offset; - const blk = [getW(dataBytes, dataOffset) ^ tfsKey[0], - getW(dataBytes, dataOffset + 4) ^ tfsKey[1], - getW(dataBytes, dataOffset + 8) ^ tfsKey[2], - getW(dataBytes, dataOffset + 12) ^ tfsKey[3]]; - for (let j = 0; j < 8; j++) { - tfsFrnd(j, blk); - } - setW(dataBytes, dataOffset, blk[2] ^ tfsKey[4]); - setW(dataBytes, dataOffset + 4, blk[3] ^ tfsKey[5]); - setW(dataBytes, dataOffset + 8, blk[0] ^ tfsKey[6]); - setW(dataBytes, dataOffset + 12, blk[1] ^ tfsKey[7]); - dataOffset += 16; - return dataBytes; - } - - function tfsDecrypt(data, offset) { - dataBytes = data; - dataOffset = offset; - const blk = [getW(dataBytes, dataOffset) ^ tfsKey[4], - getW(dataBytes, dataOffset + 4) ^ tfsKey[5], - getW(dataBytes, dataOffset + 8) ^ tfsKey[6], - getW(dataBytes, dataOffset + 12) ^ tfsKey[7]]; - for (let j = 7; j >= 0; j--) { - tfsIrnd(j, blk); - } - setW(dataBytes, dataOffset, blk[2] ^ tfsKey[0]); - setW(dataBytes, dataOffset + 4, blk[3] ^ tfsKey[1]); - setW(dataBytes, dataOffset + 8, blk[0] ^ tfsKey[2]); - setW(dataBytes, dataOffset + 12, blk[1] ^ tfsKey[3]); - dataOffset += 16; - } - - // added by Recurity Labs - - function tfsFinal() { - return dataBytes; - } - - return { - name: 'twofish', - blocksize: 128 / 8, - open: tfsInit, - close: tfsClose, - encrypt: tfsEncrypt, - decrypt: tfsDecrypt, - // added by Recurity Labs - finalize: tfsFinal - }; -} - -// added by Recurity Labs - -function TF(key) { - this.tf = createTwofish(); - this.tf.open(Array.from(key), 0); - - this.encrypt = function(block) { - return this.tf.encrypt(Array.from(block), 0); - }; -} - -TF.keySize = TF.prototype.keySize = 32; -TF.blockSize = TF.prototype.blockSize = 16; - -/* Modified by Recurity Labs GmbH - * - * Originally written by nklein software (nklein.com) - */ - -/* - * Javascript implementation based on Bruce Schneier's reference implementation. - * - * - * The constructor doesn't do much of anything. It's just here - * so we can start defining properties and methods and such. - */ -function Blowfish() {} - -/* - * Declare the block size so that protocols know what size - * Initialization Vector (IV) they will need. - */ -Blowfish.prototype.BLOCKSIZE = 8; - -/* - * These are the default SBOXES. - */ -Blowfish.prototype.SBOXES = [ - [ - 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, - 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, - 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658, - 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, - 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, - 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, - 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6, - 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, - 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, - 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, - 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, - 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, - 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, - 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, - 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, - 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, - 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, - 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, - 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, - 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, - 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, - 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, - 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, - 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, - 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, - 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, - 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8, - 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, - 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, - 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, - 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, - 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, - 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, - 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, - 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, - 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, - 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, - 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, - 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, - 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, - 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, - 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, - 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a - ], - [ - 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, - 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, - 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, - 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, - 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, - 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, - 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, - 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, - 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, - 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, - 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, - 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, - 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, - 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, - 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, - 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, - 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, - 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, - 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, - 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, - 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, - 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, - 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, - 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, - 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, - 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, - 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, - 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, - 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, - 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, - 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, - 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, - 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, - 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, - 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, - 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, - 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, - 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, - 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, - 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, - 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, - 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, - 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7 - ], - [ - 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, - 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, - 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, - 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, - 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, - 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, - 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, - 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, - 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, - 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, - 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, - 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, - 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, - 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, - 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, - 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, - 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, - 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, - 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74, - 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, - 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, - 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, - 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, - 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, - 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, - 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, - 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, - 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, - 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, - 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, - 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, - 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, - 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, - 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, - 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, - 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, - 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, - 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, - 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, - 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, - 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, - 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, - 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0 - ], - [ - 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, - 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, - 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, - 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, - 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, - 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, - 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, - 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, - 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, - 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, - 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, - 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, - 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, - 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, - 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5, - 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, - 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, - 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, - 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd, - 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, - 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, - 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, - 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc, - 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, - 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, - 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, - 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, - 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, - 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, - 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, - 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, - 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, - 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, - 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, - 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623, - 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, - 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, - 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, - 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3, - 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, - 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, - 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, - 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 - ] -]; - -//* -//* This is the default PARRAY -//* -Blowfish.prototype.PARRAY = [ - 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, - 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, - 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b -]; - -//* -//* This is the number of rounds the cipher will go -//* -Blowfish.prototype.NN = 16; - -//* -//* This function is needed to get rid of problems -//* with the high-bit getting set. If we don't do -//* this, then sometimes ( aa & 0x00FFFFFFFF ) is not -//* equal to ( bb & 0x00FFFFFFFF ) even when they -//* agree bit-for-bit for the first 32 bits. -//* -Blowfish.prototype._clean = function(xx) { - if (xx < 0) { - const yy = xx & 0x7FFFFFFF; - xx = yy + 0x80000000; - } - return xx; -}; - -//* -//* This is the mixing function that uses the sboxes -//* -Blowfish.prototype._F = function(xx) { - let yy; - - const dd = xx & 0x00FF; - xx >>>= 8; - const cc = xx & 0x00FF; - xx >>>= 8; - const bb = xx & 0x00FF; - xx >>>= 8; - const aa = xx & 0x00FF; - - yy = this.sboxes[0][aa] + this.sboxes[1][bb]; - yy ^= this.sboxes[2][cc]; - yy += this.sboxes[3][dd]; - - return yy; -}; - -//* -//* This method takes an array with two values, left and right -//* and does NN rounds of Blowfish on them. -//* -Blowfish.prototype._encryptBlock = function(vals) { - let dataL = vals[0]; - let dataR = vals[1]; - - let ii; - - for (ii = 0; ii < this.NN; ++ii) { - dataL ^= this.parray[ii]; - dataR = this._F(dataL) ^ dataR; - - const tmp = dataL; - dataL = dataR; - dataR = tmp; - } - - dataL ^= this.parray[this.NN + 0]; - dataR ^= this.parray[this.NN + 1]; - - vals[0] = this._clean(dataR); - vals[1] = this._clean(dataL); -}; - -//* -//* This method takes a vector of numbers and turns them -//* into long words so that they can be processed by the -//* real algorithm. -//* -//* Maybe I should make the real algorithm above take a vector -//* instead. That will involve more looping, but it won't require -//* the F() method to deconstruct the vector. -//* -Blowfish.prototype.encryptBlock = function(vector) { - let ii; - const vals = [0, 0]; - const off = this.BLOCKSIZE / 2; - for (ii = 0; ii < this.BLOCKSIZE / 2; ++ii) { - vals[0] = (vals[0] << 8) | (vector[ii + 0] & 0x00FF); - vals[1] = (vals[1] << 8) | (vector[ii + off] & 0x00FF); - } - - this._encryptBlock(vals); - - const ret = []; - for (ii = 0; ii < this.BLOCKSIZE / 2; ++ii) { - ret[ii + 0] = ((vals[0] >>> (24 - 8 * (ii))) & 0x00FF); - ret[ii + off] = ((vals[1] >>> (24 - 8 * (ii))) & 0x00FF); - // vals[ 0 ] = ( vals[ 0 ] >>> 8 ); - // vals[ 1 ] = ( vals[ 1 ] >>> 8 ); - } - - return ret; -}; - -//* -//* This method takes an array with two values, left and right -//* and undoes NN rounds of Blowfish on them. -//* -Blowfish.prototype._decryptBlock = function(vals) { - let dataL = vals[0]; - let dataR = vals[1]; - - let ii; - - for (ii = this.NN + 1; ii > 1; --ii) { - dataL ^= this.parray[ii]; - dataR = this._F(dataL) ^ dataR; - - const tmp = dataL; - dataL = dataR; - dataR = tmp; - } - - dataL ^= this.parray[1]; - dataR ^= this.parray[0]; - - vals[0] = this._clean(dataR); - vals[1] = this._clean(dataL); -}; - -//* -//* This method takes a key array and initializes the -//* sboxes and parray for this encryption. -//* -Blowfish.prototype.init = function(key) { - let ii; - let jj = 0; - - this.parray = []; - for (ii = 0; ii < this.NN + 2; ++ii) { - let data = 0x00000000; - for (let kk = 0; kk < 4; ++kk) { - data = (data << 8) | (key[jj] & 0x00FF); - if (++jj >= key.length) { - jj = 0; - } - } - this.parray[ii] = this.PARRAY[ii] ^ data; - } - - this.sboxes = []; - for (ii = 0; ii < 4; ++ii) { - this.sboxes[ii] = []; - for (jj = 0; jj < 256; ++jj) { - this.sboxes[ii][jj] = this.SBOXES[ii][jj]; - } - } - - const vals = [0x00000000, 0x00000000]; - - for (ii = 0; ii < this.NN + 2; ii += 2) { - this._encryptBlock(vals); - this.parray[ii + 0] = vals[0]; - this.parray[ii + 1] = vals[1]; - } - - for (ii = 0; ii < 4; ++ii) { - for (jj = 0; jj < 256; jj += 2) { - this._encryptBlock(vals); - this.sboxes[ii][jj + 0] = vals[0]; - this.sboxes[ii][jj + 1] = vals[1]; - } - } -}; - -// added by Recurity Labs -function BF(key) { - this.bf = new Blowfish(); - this.bf.init(key); - - this.encrypt = function(block) { - return this.bf.encryptBlock(block); - }; -} - -BF.keySize = BF.prototype.keySize = 16; -BF.blockSize = BF.prototype.blockSize = 8; - -/** - * @fileoverview Symmetric cryptography functions - * @module crypto/cipher - * @private - */ - -/** - * AES-128 encryption and decryption (ID 7) - * @function - * @param {String} key - 128-bit key - * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} - * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} - * @returns {Object} - */ -const aes128 = aes(128); -/** - * AES-128 Block Cipher (ID 8) - * @function - * @param {String} key - 192-bit key - * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} - * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} - * @returns {Object} - */ -const aes192 = aes(192); -/** - * AES-128 Block Cipher (ID 9) - * @function - * @param {String} key - 256-bit key - * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} - * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} - * @returns {Object} - */ -const aes256 = aes(256); -// Not in OpenPGP specifications -const des$1 = DES; -/** - * Triple DES Block Cipher (ID 2) - * @function - * @param {String} key - 192-bit key - * @see {@link https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-67r2.pdf|NIST SP 800-67} - * @returns {Object} - */ -const tripledes = TripleDES; -/** - * CAST-128 Block Cipher (ID 3) - * @function - * @param {String} key - 128-bit key - * @see {@link https://tools.ietf.org/html/rfc2144|The CAST-128 Encryption Algorithm} - * @returns {Object} - */ -const cast5 = CAST5; -/** - * Twofish Block Cipher (ID 10) - * @function - * @param {String} key - 256-bit key - * @see {@link https://tools.ietf.org/html/rfc4880#ref-TWOFISH|TWOFISH} - * @returns {Object} - */ -const twofish = TF; -/** - * Blowfish Block Cipher (ID 4) - * @function - * @param {String} key - 128-bit key - * @see {@link https://tools.ietf.org/html/rfc4880#ref-BLOWFISH|BLOWFISH} - * @returns {Object} - */ -const blowfish = BF; -/** - * Not implemented - * @function - * @throws {Error} - */ -const idea = function() { - throw new Error('IDEA symmetric-key algorithm not implemented'); -}; - -var cipher = /*#__PURE__*/Object.freeze({ - __proto__: null, - aes128: aes128, - aes192: aes192, - aes256: aes256, - des: des$1, - tripledes: tripledes, - cast5: cast5, - twofish: twofish, - blowfish: blowfish, - idea: idea -}); - -var sha1_asm = function ( stdlib, foreign, buffer ) { - "use asm"; - - // SHA256 state - var H0 = 0, H1 = 0, H2 = 0, H3 = 0, H4 = 0, - TOTAL0 = 0, TOTAL1 = 0; - - // HMAC state - var I0 = 0, I1 = 0, I2 = 0, I3 = 0, I4 = 0, - O0 = 0, O1 = 0, O2 = 0, O3 = 0, O4 = 0; - - // I/O buffer - var HEAP = new stdlib.Uint8Array(buffer); - - function _core ( w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15 ) { - w0 = w0|0; - w1 = w1|0; - w2 = w2|0; - w3 = w3|0; - w4 = w4|0; - w5 = w5|0; - w6 = w6|0; - w7 = w7|0; - w8 = w8|0; - w9 = w9|0; - w10 = w10|0; - w11 = w11|0; - w12 = w12|0; - w13 = w13|0; - w14 = w14|0; - w15 = w15|0; - - var a = 0, b = 0, c = 0, d = 0, e = 0, n = 0, t = 0, - w16 = 0, w17 = 0, w18 = 0, w19 = 0, - w20 = 0, w21 = 0, w22 = 0, w23 = 0, w24 = 0, w25 = 0, w26 = 0, w27 = 0, w28 = 0, w29 = 0, - w30 = 0, w31 = 0, w32 = 0, w33 = 0, w34 = 0, w35 = 0, w36 = 0, w37 = 0, w38 = 0, w39 = 0, - w40 = 0, w41 = 0, w42 = 0, w43 = 0, w44 = 0, w45 = 0, w46 = 0, w47 = 0, w48 = 0, w49 = 0, - w50 = 0, w51 = 0, w52 = 0, w53 = 0, w54 = 0, w55 = 0, w56 = 0, w57 = 0, w58 = 0, w59 = 0, - w60 = 0, w61 = 0, w62 = 0, w63 = 0, w64 = 0, w65 = 0, w66 = 0, w67 = 0, w68 = 0, w69 = 0, - w70 = 0, w71 = 0, w72 = 0, w73 = 0, w74 = 0, w75 = 0, w76 = 0, w77 = 0, w78 = 0, w79 = 0; - - a = H0; - b = H1; - c = H2; - d = H3; - e = H4; - - // 0 - t = ( w0 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 1 - t = ( w1 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 2 - t = ( w2 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 3 - t = ( w3 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 4 - t = ( w4 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 5 - t = ( w5 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 6 - t = ( w6 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 7 - t = ( w7 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 8 - t = ( w8 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 9 - t = ( w9 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 10 - t = ( w10 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 11 - t = ( w11 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 12 - t = ( w12 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 13 - t = ( w13 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 14 - t = ( w14 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 15 - t = ( w15 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 16 - n = w13 ^ w8 ^ w2 ^ w0; - w16 = (n << 1) | (n >>> 31); - t = (w16 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 17 - n = w14 ^ w9 ^ w3 ^ w1; - w17 = (n << 1) | (n >>> 31); - t = (w17 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 18 - n = w15 ^ w10 ^ w4 ^ w2; - w18 = (n << 1) | (n >>> 31); - t = (w18 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 19 - n = w16 ^ w11 ^ w5 ^ w3; - w19 = (n << 1) | (n >>> 31); - t = (w19 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 20 - n = w17 ^ w12 ^ w6 ^ w4; - w20 = (n << 1) | (n >>> 31); - t = (w20 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 21 - n = w18 ^ w13 ^ w7 ^ w5; - w21 = (n << 1) | (n >>> 31); - t = (w21 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 22 - n = w19 ^ w14 ^ w8 ^ w6; - w22 = (n << 1) | (n >>> 31); - t = (w22 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 23 - n = w20 ^ w15 ^ w9 ^ w7; - w23 = (n << 1) | (n >>> 31); - t = (w23 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 24 - n = w21 ^ w16 ^ w10 ^ w8; - w24 = (n << 1) | (n >>> 31); - t = (w24 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 25 - n = w22 ^ w17 ^ w11 ^ w9; - w25 = (n << 1) | (n >>> 31); - t = (w25 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 26 - n = w23 ^ w18 ^ w12 ^ w10; - w26 = (n << 1) | (n >>> 31); - t = (w26 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 27 - n = w24 ^ w19 ^ w13 ^ w11; - w27 = (n << 1) | (n >>> 31); - t = (w27 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 28 - n = w25 ^ w20 ^ w14 ^ w12; - w28 = (n << 1) | (n >>> 31); - t = (w28 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 29 - n = w26 ^ w21 ^ w15 ^ w13; - w29 = (n << 1) | (n >>> 31); - t = (w29 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 30 - n = w27 ^ w22 ^ w16 ^ w14; - w30 = (n << 1) | (n >>> 31); - t = (w30 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 31 - n = w28 ^ w23 ^ w17 ^ w15; - w31 = (n << 1) | (n >>> 31); - t = (w31 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 32 - n = w29 ^ w24 ^ w18 ^ w16; - w32 = (n << 1) | (n >>> 31); - t = (w32 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 33 - n = w30 ^ w25 ^ w19 ^ w17; - w33 = (n << 1) | (n >>> 31); - t = (w33 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 34 - n = w31 ^ w26 ^ w20 ^ w18; - w34 = (n << 1) | (n >>> 31); - t = (w34 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 35 - n = w32 ^ w27 ^ w21 ^ w19; - w35 = (n << 1) | (n >>> 31); - t = (w35 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 36 - n = w33 ^ w28 ^ w22 ^ w20; - w36 = (n << 1) | (n >>> 31); - t = (w36 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 37 - n = w34 ^ w29 ^ w23 ^ w21; - w37 = (n << 1) | (n >>> 31); - t = (w37 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 38 - n = w35 ^ w30 ^ w24 ^ w22; - w38 = (n << 1) | (n >>> 31); - t = (w38 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 39 - n = w36 ^ w31 ^ w25 ^ w23; - w39 = (n << 1) | (n >>> 31); - t = (w39 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 40 - n = w37 ^ w32 ^ w26 ^ w24; - w40 = (n << 1) | (n >>> 31); - t = (w40 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 41 - n = w38 ^ w33 ^ w27 ^ w25; - w41 = (n << 1) | (n >>> 31); - t = (w41 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 42 - n = w39 ^ w34 ^ w28 ^ w26; - w42 = (n << 1) | (n >>> 31); - t = (w42 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 43 - n = w40 ^ w35 ^ w29 ^ w27; - w43 = (n << 1) | (n >>> 31); - t = (w43 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 44 - n = w41 ^ w36 ^ w30 ^ w28; - w44 = (n << 1) | (n >>> 31); - t = (w44 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 45 - n = w42 ^ w37 ^ w31 ^ w29; - w45 = (n << 1) | (n >>> 31); - t = (w45 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 46 - n = w43 ^ w38 ^ w32 ^ w30; - w46 = (n << 1) | (n >>> 31); - t = (w46 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 47 - n = w44 ^ w39 ^ w33 ^ w31; - w47 = (n << 1) | (n >>> 31); - t = (w47 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 48 - n = w45 ^ w40 ^ w34 ^ w32; - w48 = (n << 1) | (n >>> 31); - t = (w48 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 49 - n = w46 ^ w41 ^ w35 ^ w33; - w49 = (n << 1) | (n >>> 31); - t = (w49 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 50 - n = w47 ^ w42 ^ w36 ^ w34; - w50 = (n << 1) | (n >>> 31); - t = (w50 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 51 - n = w48 ^ w43 ^ w37 ^ w35; - w51 = (n << 1) | (n >>> 31); - t = (w51 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 52 - n = w49 ^ w44 ^ w38 ^ w36; - w52 = (n << 1) | (n >>> 31); - t = (w52 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 53 - n = w50 ^ w45 ^ w39 ^ w37; - w53 = (n << 1) | (n >>> 31); - t = (w53 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 54 - n = w51 ^ w46 ^ w40 ^ w38; - w54 = (n << 1) | (n >>> 31); - t = (w54 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 55 - n = w52 ^ w47 ^ w41 ^ w39; - w55 = (n << 1) | (n >>> 31); - t = (w55 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 56 - n = w53 ^ w48 ^ w42 ^ w40; - w56 = (n << 1) | (n >>> 31); - t = (w56 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 57 - n = w54 ^ w49 ^ w43 ^ w41; - w57 = (n << 1) | (n >>> 31); - t = (w57 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 58 - n = w55 ^ w50 ^ w44 ^ w42; - w58 = (n << 1) | (n >>> 31); - t = (w58 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 59 - n = w56 ^ w51 ^ w45 ^ w43; - w59 = (n << 1) | (n >>> 31); - t = (w59 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 60 - n = w57 ^ w52 ^ w46 ^ w44; - w60 = (n << 1) | (n >>> 31); - t = (w60 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 61 - n = w58 ^ w53 ^ w47 ^ w45; - w61 = (n << 1) | (n >>> 31); - t = (w61 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 62 - n = w59 ^ w54 ^ w48 ^ w46; - w62 = (n << 1) | (n >>> 31); - t = (w62 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 63 - n = w60 ^ w55 ^ w49 ^ w47; - w63 = (n << 1) | (n >>> 31); - t = (w63 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 64 - n = w61 ^ w56 ^ w50 ^ w48; - w64 = (n << 1) | (n >>> 31); - t = (w64 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 65 - n = w62 ^ w57 ^ w51 ^ w49; - w65 = (n << 1) | (n >>> 31); - t = (w65 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 66 - n = w63 ^ w58 ^ w52 ^ w50; - w66 = (n << 1) | (n >>> 31); - t = (w66 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 67 - n = w64 ^ w59 ^ w53 ^ w51; - w67 = (n << 1) | (n >>> 31); - t = (w67 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 68 - n = w65 ^ w60 ^ w54 ^ w52; - w68 = (n << 1) | (n >>> 31); - t = (w68 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 69 - n = w66 ^ w61 ^ w55 ^ w53; - w69 = (n << 1) | (n >>> 31); - t = (w69 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 70 - n = w67 ^ w62 ^ w56 ^ w54; - w70 = (n << 1) | (n >>> 31); - t = (w70 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 71 - n = w68 ^ w63 ^ w57 ^ w55; - w71 = (n << 1) | (n >>> 31); - t = (w71 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 72 - n = w69 ^ w64 ^ w58 ^ w56; - w72 = (n << 1) | (n >>> 31); - t = (w72 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 73 - n = w70 ^ w65 ^ w59 ^ w57; - w73 = (n << 1) | (n >>> 31); - t = (w73 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 74 - n = w71 ^ w66 ^ w60 ^ w58; - w74 = (n << 1) | (n >>> 31); - t = (w74 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 75 - n = w72 ^ w67 ^ w61 ^ w59; - w75 = (n << 1) | (n >>> 31); - t = (w75 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 76 - n = w73 ^ w68 ^ w62 ^ w60; - w76 = (n << 1) | (n >>> 31); - t = (w76 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 77 - n = w74 ^ w69 ^ w63 ^ w61; - w77 = (n << 1) | (n >>> 31); - t = (w77 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 78 - n = w75 ^ w70 ^ w64 ^ w62; - w78 = (n << 1) | (n >>> 31); - t = (w78 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 79 - n = w76 ^ w71 ^ w65 ^ w63; - w79 = (n << 1) | (n >>> 31); - t = (w79 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - H0 = ( H0 + a )|0; - H1 = ( H1 + b )|0; - H2 = ( H2 + c )|0; - H3 = ( H3 + d )|0; - H4 = ( H4 + e )|0; - - } - - function _core_heap ( offset ) { - offset = offset|0; - - _core( - HEAP[offset|0]<<24 | HEAP[offset|1]<<16 | HEAP[offset|2]<<8 | HEAP[offset|3], - HEAP[offset|4]<<24 | HEAP[offset|5]<<16 | HEAP[offset|6]<<8 | HEAP[offset|7], - HEAP[offset|8]<<24 | HEAP[offset|9]<<16 | HEAP[offset|10]<<8 | HEAP[offset|11], - HEAP[offset|12]<<24 | HEAP[offset|13]<<16 | HEAP[offset|14]<<8 | HEAP[offset|15], - HEAP[offset|16]<<24 | HEAP[offset|17]<<16 | HEAP[offset|18]<<8 | HEAP[offset|19], - HEAP[offset|20]<<24 | HEAP[offset|21]<<16 | HEAP[offset|22]<<8 | HEAP[offset|23], - HEAP[offset|24]<<24 | HEAP[offset|25]<<16 | HEAP[offset|26]<<8 | HEAP[offset|27], - HEAP[offset|28]<<24 | HEAP[offset|29]<<16 | HEAP[offset|30]<<8 | HEAP[offset|31], - HEAP[offset|32]<<24 | HEAP[offset|33]<<16 | HEAP[offset|34]<<8 | HEAP[offset|35], - HEAP[offset|36]<<24 | HEAP[offset|37]<<16 | HEAP[offset|38]<<8 | HEAP[offset|39], - HEAP[offset|40]<<24 | HEAP[offset|41]<<16 | HEAP[offset|42]<<8 | HEAP[offset|43], - HEAP[offset|44]<<24 | HEAP[offset|45]<<16 | HEAP[offset|46]<<8 | HEAP[offset|47], - HEAP[offset|48]<<24 | HEAP[offset|49]<<16 | HEAP[offset|50]<<8 | HEAP[offset|51], - HEAP[offset|52]<<24 | HEAP[offset|53]<<16 | HEAP[offset|54]<<8 | HEAP[offset|55], - HEAP[offset|56]<<24 | HEAP[offset|57]<<16 | HEAP[offset|58]<<8 | HEAP[offset|59], - HEAP[offset|60]<<24 | HEAP[offset|61]<<16 | HEAP[offset|62]<<8 | HEAP[offset|63] - ); - } - - // offset — multiple of 32 - function _state_to_heap ( output ) { - output = output|0; - - HEAP[output|0] = H0>>>24; - HEAP[output|1] = H0>>>16&255; - HEAP[output|2] = H0>>>8&255; - HEAP[output|3] = H0&255; - HEAP[output|4] = H1>>>24; - HEAP[output|5] = H1>>>16&255; - HEAP[output|6] = H1>>>8&255; - HEAP[output|7] = H1&255; - HEAP[output|8] = H2>>>24; - HEAP[output|9] = H2>>>16&255; - HEAP[output|10] = H2>>>8&255; - HEAP[output|11] = H2&255; - HEAP[output|12] = H3>>>24; - HEAP[output|13] = H3>>>16&255; - HEAP[output|14] = H3>>>8&255; - HEAP[output|15] = H3&255; - HEAP[output|16] = H4>>>24; - HEAP[output|17] = H4>>>16&255; - HEAP[output|18] = H4>>>8&255; - HEAP[output|19] = H4&255; - } - - function reset () { - H0 = 0x67452301; - H1 = 0xefcdab89; - H2 = 0x98badcfe; - H3 = 0x10325476; - H4 = 0xc3d2e1f0; - TOTAL0 = TOTAL1 = 0; - } - - function init ( h0, h1, h2, h3, h4, total0, total1 ) { - h0 = h0|0; - h1 = h1|0; - h2 = h2|0; - h3 = h3|0; - h4 = h4|0; - total0 = total0|0; - total1 = total1|0; - - H0 = h0; - H1 = h1; - H2 = h2; - H3 = h3; - H4 = h4; - TOTAL0 = total0; - TOTAL1 = total1; - } - - // offset — multiple of 64 - function process ( offset, length ) { - offset = offset|0; - length = length|0; - - var hashed = 0; - - if ( offset & 63 ) - return -1; - - while ( (length|0) >= 64 ) { - _core_heap(offset); - - offset = ( offset + 64 )|0; - length = ( length - 64 )|0; - - hashed = ( hashed + 64 )|0; - } - - TOTAL0 = ( TOTAL0 + hashed )|0; - if ( TOTAL0>>>0 < hashed>>>0 ) TOTAL1 = ( TOTAL1 + 1 )|0; - - return hashed|0; - } - - // offset — multiple of 64 - // output — multiple of 32 - function finish ( offset, length, output ) { - offset = offset|0; - length = length|0; - output = output|0; - - var hashed = 0, - i = 0; - - if ( offset & 63 ) - return -1; - - if ( ~output ) - if ( output & 31 ) - return -1; - - if ( (length|0) >= 64 ) { - hashed = process( offset, length )|0; - if ( (hashed|0) == -1 ) - return -1; - - offset = ( offset + hashed )|0; - length = ( length - hashed )|0; - } - - hashed = ( hashed + length )|0; - TOTAL0 = ( TOTAL0 + length )|0; - if ( TOTAL0>>>0 < length>>>0 ) TOTAL1 = (TOTAL1 + 1)|0; - - HEAP[offset|length] = 0x80; - - if ( (length|0) >= 56 ) { - for ( i = (length+1)|0; (i|0) < 64; i = (i+1)|0 ) - HEAP[offset|i] = 0x00; - _core_heap(offset); - - length = 0; - - HEAP[offset|0] = 0; - } - - for ( i = (length+1)|0; (i|0) < 59; i = (i+1)|0 ) - HEAP[offset|i] = 0; - - HEAP[offset|56] = TOTAL1>>>21&255; - HEAP[offset|57] = TOTAL1>>>13&255; - HEAP[offset|58] = TOTAL1>>>5&255; - HEAP[offset|59] = TOTAL1<<3&255 | TOTAL0>>>29; - HEAP[offset|60] = TOTAL0>>>21&255; - HEAP[offset|61] = TOTAL0>>>13&255; - HEAP[offset|62] = TOTAL0>>>5&255; - HEAP[offset|63] = TOTAL0<<3&255; - _core_heap(offset); - - if ( ~output ) - _state_to_heap(output); - - return hashed|0; - } - - function hmac_reset () { - H0 = I0; - H1 = I1; - H2 = I2; - H3 = I3; - H4 = I4; - TOTAL0 = 64; - TOTAL1 = 0; - } - - function _hmac_opad () { - H0 = O0; - H1 = O1; - H2 = O2; - H3 = O3; - H4 = O4; - TOTAL0 = 64; - TOTAL1 = 0; - } - - function hmac_init ( p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15 ) { - p0 = p0|0; - p1 = p1|0; - p2 = p2|0; - p3 = p3|0; - p4 = p4|0; - p5 = p5|0; - p6 = p6|0; - p7 = p7|0; - p8 = p8|0; - p9 = p9|0; - p10 = p10|0; - p11 = p11|0; - p12 = p12|0; - p13 = p13|0; - p14 = p14|0; - p15 = p15|0; - - // opad - reset(); - _core( - p0 ^ 0x5c5c5c5c, - p1 ^ 0x5c5c5c5c, - p2 ^ 0x5c5c5c5c, - p3 ^ 0x5c5c5c5c, - p4 ^ 0x5c5c5c5c, - p5 ^ 0x5c5c5c5c, - p6 ^ 0x5c5c5c5c, - p7 ^ 0x5c5c5c5c, - p8 ^ 0x5c5c5c5c, - p9 ^ 0x5c5c5c5c, - p10 ^ 0x5c5c5c5c, - p11 ^ 0x5c5c5c5c, - p12 ^ 0x5c5c5c5c, - p13 ^ 0x5c5c5c5c, - p14 ^ 0x5c5c5c5c, - p15 ^ 0x5c5c5c5c - ); - O0 = H0; - O1 = H1; - O2 = H2; - O3 = H3; - O4 = H4; - - // ipad - reset(); - _core( - p0 ^ 0x36363636, - p1 ^ 0x36363636, - p2 ^ 0x36363636, - p3 ^ 0x36363636, - p4 ^ 0x36363636, - p5 ^ 0x36363636, - p6 ^ 0x36363636, - p7 ^ 0x36363636, - p8 ^ 0x36363636, - p9 ^ 0x36363636, - p10 ^ 0x36363636, - p11 ^ 0x36363636, - p12 ^ 0x36363636, - p13 ^ 0x36363636, - p14 ^ 0x36363636, - p15 ^ 0x36363636 - ); - I0 = H0; - I1 = H1; - I2 = H2; - I3 = H3; - I4 = H4; - - TOTAL0 = 64; - TOTAL1 = 0; - } - - // offset — multiple of 64 - // output — multiple of 32 - function hmac_finish ( offset, length, output ) { - offset = offset|0; - length = length|0; - output = output|0; - - var t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, hashed = 0; - - if ( offset & 63 ) - return -1; - - if ( ~output ) - if ( output & 31 ) - return -1; - - hashed = finish( offset, length, -1 )|0; - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; - - _hmac_opad(); - _core( t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672 ); - - if ( ~output ) - _state_to_heap(output); - - return hashed|0; - } - - // salt is assumed to be already processed - // offset — multiple of 64 - // output — multiple of 32 - function pbkdf2_generate_block ( offset, length, block, count, output ) { - offset = offset|0; - length = length|0; - block = block|0; - count = count|0; - output = output|0; - - var h0 = 0, h1 = 0, h2 = 0, h3 = 0, h4 = 0, - t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0; - - if ( offset & 63 ) - return -1; - - if ( ~output ) - if ( output & 31 ) - return -1; - - // pad block number into heap - // FIXME probable OOB write - HEAP[(offset+length)|0] = block>>>24; - HEAP[(offset+length+1)|0] = block>>>16&255; - HEAP[(offset+length+2)|0] = block>>>8&255; - HEAP[(offset+length+3)|0] = block&255; - - // finish first iteration - hmac_finish( offset, (length+4)|0, -1 )|0; - h0 = t0 = H0, h1 = t1 = H1, h2 = t2 = H2, h3 = t3 = H3, h4 = t4 = H4; - count = (count-1)|0; - - // perform the rest iterations - while ( (count|0) > 0 ) { - hmac_reset(); - _core( t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672 ); - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; - - _hmac_opad(); - _core( t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672 ); - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; - - h0 = h0 ^ H0; - h1 = h1 ^ H1; - h2 = h2 ^ H2; - h3 = h3 ^ H3; - h4 = h4 ^ H4; - - count = (count-1)|0; - } - - H0 = h0; - H1 = h1; - H2 = h2; - H3 = h3; - H4 = h4; - - if ( ~output ) - _state_to_heap(output); - - return 0; - } - - return { - // SHA1 - reset: reset, - init: init, - process: process, - finish: finish, - - // HMAC-SHA1 - hmac_reset: hmac_reset, - hmac_init: hmac_init, - hmac_finish: hmac_finish, - - // PBKDF2-HMAC-SHA1 - pbkdf2_generate_block: pbkdf2_generate_block - } -}; - -class Hash { - constructor() { - this.pos = 0; - this.len = 0; - } - reset() { - const { asm } = this.acquire_asm(); - this.result = null; - this.pos = 0; - this.len = 0; - asm.reset(); - return this; - } - process(data) { - if (this.result !== null) - throw new IllegalStateError('state must be reset before processing new data'); - const { asm, heap } = this.acquire_asm(); - let hpos = this.pos; - let hlen = this.len; - let dpos = 0; - let dlen = data.length; - let wlen = 0; - while (dlen > 0) { - wlen = _heap_write(heap, hpos + hlen, data, dpos, dlen); - hlen += wlen; - dpos += wlen; - dlen -= wlen; - wlen = asm.process(hpos, hlen); - hpos += wlen; - hlen -= wlen; - if (!hlen) - hpos = 0; - } - this.pos = hpos; - this.len = hlen; - return this; - } - finish() { - if (this.result !== null) - throw new IllegalStateError('state must be reset before processing new data'); - const { asm, heap } = this.acquire_asm(); - asm.finish(this.pos, this.len, 0); - this.result = new Uint8Array(this.HASH_SIZE); - this.result.set(heap.subarray(0, this.HASH_SIZE)); - this.pos = 0; - this.len = 0; - this.release_asm(); - return this; - } -} - -const _sha1_block_size = 64; -const _sha1_hash_size = 20; -const heap_pool$1 = []; -const asm_pool$1 = []; -class Sha1 extends Hash { - constructor() { - super(); - this.NAME = 'sha1'; - this.BLOCK_SIZE = _sha1_block_size; - this.HASH_SIZE = _sha1_hash_size; - this.acquire_asm(); - } - acquire_asm() { - if (this.heap === undefined || this.asm === undefined) { - this.heap = heap_pool$1.pop() || _heap_init(); - this.asm = asm_pool$1.pop() || sha1_asm({ Uint8Array: Uint8Array }, null, this.heap.buffer); - this.reset(); - } - return { heap: this.heap, asm: this.asm }; - } - release_asm() { - if (this.heap !== undefined && this.asm !== undefined) { - heap_pool$1.push(this.heap); - asm_pool$1.push(this.asm); - } - this.heap = undefined; - this.asm = undefined; - } - static bytes(data) { - return new Sha1().process(data).finish().result; - } -} -Sha1.NAME = 'sha1'; -Sha1.heap_pool = []; -Sha1.asm_pool = []; -Sha1.asm_function = sha1_asm; - -var sha256_asm = function ( stdlib, foreign, buffer ) { - "use asm"; - - // SHA256 state - var H0 = 0, H1 = 0, H2 = 0, H3 = 0, H4 = 0, H5 = 0, H6 = 0, H7 = 0, - TOTAL0 = 0, TOTAL1 = 0; - - // HMAC state - var I0 = 0, I1 = 0, I2 = 0, I3 = 0, I4 = 0, I5 = 0, I6 = 0, I7 = 0, - O0 = 0, O1 = 0, O2 = 0, O3 = 0, O4 = 0, O5 = 0, O6 = 0, O7 = 0; - - // I/O buffer - var HEAP = new stdlib.Uint8Array(buffer); - - function _core ( w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15 ) { - w0 = w0|0; - w1 = w1|0; - w2 = w2|0; - w3 = w3|0; - w4 = w4|0; - w5 = w5|0; - w6 = w6|0; - w7 = w7|0; - w8 = w8|0; - w9 = w9|0; - w10 = w10|0; - w11 = w11|0; - w12 = w12|0; - w13 = w13|0; - w14 = w14|0; - w15 = w15|0; - - var a = 0, b = 0, c = 0, d = 0, e = 0, f = 0, g = 0, h = 0; - - a = H0; - b = H1; - c = H2; - d = H3; - e = H4; - f = H5; - g = H6; - h = H7; - - // 0 - h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x428a2f98 )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 1 - g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x71374491 )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 2 - f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0xb5c0fbcf )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 3 - e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0xe9b5dba5 )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 4 - d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x3956c25b )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 5 - c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x59f111f1 )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 6 - b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x923f82a4 )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 7 - a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0xab1c5ed5 )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - // 8 - h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0xd807aa98 )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 9 - g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x12835b01 )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 10 - f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x243185be )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 11 - e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x550c7dc3 )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 12 - d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x72be5d74 )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 13 - c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x80deb1fe )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 14 - b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x9bdc06a7 )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 15 - a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0xc19bf174 )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - // 16 - w0 = ( ( w1>>>7 ^ w1>>>18 ^ w1>>>3 ^ w1<<25 ^ w1<<14 ) + ( w14>>>17 ^ w14>>>19 ^ w14>>>10 ^ w14<<15 ^ w14<<13 ) + w0 + w9 )|0; - h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0xe49b69c1 )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 17 - w1 = ( ( w2>>>7 ^ w2>>>18 ^ w2>>>3 ^ w2<<25 ^ w2<<14 ) + ( w15>>>17 ^ w15>>>19 ^ w15>>>10 ^ w15<<15 ^ w15<<13 ) + w1 + w10 )|0; - g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0xefbe4786 )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 18 - w2 = ( ( w3>>>7 ^ w3>>>18 ^ w3>>>3 ^ w3<<25 ^ w3<<14 ) + ( w0>>>17 ^ w0>>>19 ^ w0>>>10 ^ w0<<15 ^ w0<<13 ) + w2 + w11 )|0; - f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x0fc19dc6 )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 19 - w3 = ( ( w4>>>7 ^ w4>>>18 ^ w4>>>3 ^ w4<<25 ^ w4<<14 ) + ( w1>>>17 ^ w1>>>19 ^ w1>>>10 ^ w1<<15 ^ w1<<13 ) + w3 + w12 )|0; - e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x240ca1cc )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 20 - w4 = ( ( w5>>>7 ^ w5>>>18 ^ w5>>>3 ^ w5<<25 ^ w5<<14 ) + ( w2>>>17 ^ w2>>>19 ^ w2>>>10 ^ w2<<15 ^ w2<<13 ) + w4 + w13 )|0; - d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x2de92c6f )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 21 - w5 = ( ( w6>>>7 ^ w6>>>18 ^ w6>>>3 ^ w6<<25 ^ w6<<14 ) + ( w3>>>17 ^ w3>>>19 ^ w3>>>10 ^ w3<<15 ^ w3<<13 ) + w5 + w14 )|0; - c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x4a7484aa )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 22 - w6 = ( ( w7>>>7 ^ w7>>>18 ^ w7>>>3 ^ w7<<25 ^ w7<<14 ) + ( w4>>>17 ^ w4>>>19 ^ w4>>>10 ^ w4<<15 ^ w4<<13 ) + w6 + w15 )|0; - b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x5cb0a9dc )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 23 - w7 = ( ( w8>>>7 ^ w8>>>18 ^ w8>>>3 ^ w8<<25 ^ w8<<14 ) + ( w5>>>17 ^ w5>>>19 ^ w5>>>10 ^ w5<<15 ^ w5<<13 ) + w7 + w0 )|0; - a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x76f988da )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - // 24 - w8 = ( ( w9>>>7 ^ w9>>>18 ^ w9>>>3 ^ w9<<25 ^ w9<<14 ) + ( w6>>>17 ^ w6>>>19 ^ w6>>>10 ^ w6<<15 ^ w6<<13 ) + w8 + w1 )|0; - h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x983e5152 )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 25 - w9 = ( ( w10>>>7 ^ w10>>>18 ^ w10>>>3 ^ w10<<25 ^ w10<<14 ) + ( w7>>>17 ^ w7>>>19 ^ w7>>>10 ^ w7<<15 ^ w7<<13 ) + w9 + w2 )|0; - g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0xa831c66d )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 26 - w10 = ( ( w11>>>7 ^ w11>>>18 ^ w11>>>3 ^ w11<<25 ^ w11<<14 ) + ( w8>>>17 ^ w8>>>19 ^ w8>>>10 ^ w8<<15 ^ w8<<13 ) + w10 + w3 )|0; - f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0xb00327c8 )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 27 - w11 = ( ( w12>>>7 ^ w12>>>18 ^ w12>>>3 ^ w12<<25 ^ w12<<14 ) + ( w9>>>17 ^ w9>>>19 ^ w9>>>10 ^ w9<<15 ^ w9<<13 ) + w11 + w4 )|0; - e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0xbf597fc7 )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 28 - w12 = ( ( w13>>>7 ^ w13>>>18 ^ w13>>>3 ^ w13<<25 ^ w13<<14 ) + ( w10>>>17 ^ w10>>>19 ^ w10>>>10 ^ w10<<15 ^ w10<<13 ) + w12 + w5 )|0; - d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0xc6e00bf3 )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 29 - w13 = ( ( w14>>>7 ^ w14>>>18 ^ w14>>>3 ^ w14<<25 ^ w14<<14 ) + ( w11>>>17 ^ w11>>>19 ^ w11>>>10 ^ w11<<15 ^ w11<<13 ) + w13 + w6 )|0; - c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0xd5a79147 )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 30 - w14 = ( ( w15>>>7 ^ w15>>>18 ^ w15>>>3 ^ w15<<25 ^ w15<<14 ) + ( w12>>>17 ^ w12>>>19 ^ w12>>>10 ^ w12<<15 ^ w12<<13 ) + w14 + w7 )|0; - b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x06ca6351 )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 31 - w15 = ( ( w0>>>7 ^ w0>>>18 ^ w0>>>3 ^ w0<<25 ^ w0<<14 ) + ( w13>>>17 ^ w13>>>19 ^ w13>>>10 ^ w13<<15 ^ w13<<13 ) + w15 + w8 )|0; - a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x14292967 )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - // 32 - w0 = ( ( w1>>>7 ^ w1>>>18 ^ w1>>>3 ^ w1<<25 ^ w1<<14 ) + ( w14>>>17 ^ w14>>>19 ^ w14>>>10 ^ w14<<15 ^ w14<<13 ) + w0 + w9 )|0; - h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x27b70a85 )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 33 - w1 = ( ( w2>>>7 ^ w2>>>18 ^ w2>>>3 ^ w2<<25 ^ w2<<14 ) + ( w15>>>17 ^ w15>>>19 ^ w15>>>10 ^ w15<<15 ^ w15<<13 ) + w1 + w10 )|0; - g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x2e1b2138 )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 34 - w2 = ( ( w3>>>7 ^ w3>>>18 ^ w3>>>3 ^ w3<<25 ^ w3<<14 ) + ( w0>>>17 ^ w0>>>19 ^ w0>>>10 ^ w0<<15 ^ w0<<13 ) + w2 + w11 )|0; - f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x4d2c6dfc )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 35 - w3 = ( ( w4>>>7 ^ w4>>>18 ^ w4>>>3 ^ w4<<25 ^ w4<<14 ) + ( w1>>>17 ^ w1>>>19 ^ w1>>>10 ^ w1<<15 ^ w1<<13 ) + w3 + w12 )|0; - e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x53380d13 )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 36 - w4 = ( ( w5>>>7 ^ w5>>>18 ^ w5>>>3 ^ w5<<25 ^ w5<<14 ) + ( w2>>>17 ^ w2>>>19 ^ w2>>>10 ^ w2<<15 ^ w2<<13 ) + w4 + w13 )|0; - d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x650a7354 )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 37 - w5 = ( ( w6>>>7 ^ w6>>>18 ^ w6>>>3 ^ w6<<25 ^ w6<<14 ) + ( w3>>>17 ^ w3>>>19 ^ w3>>>10 ^ w3<<15 ^ w3<<13 ) + w5 + w14 )|0; - c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x766a0abb )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 38 - w6 = ( ( w7>>>7 ^ w7>>>18 ^ w7>>>3 ^ w7<<25 ^ w7<<14 ) + ( w4>>>17 ^ w4>>>19 ^ w4>>>10 ^ w4<<15 ^ w4<<13 ) + w6 + w15 )|0; - b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x81c2c92e )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 39 - w7 = ( ( w8>>>7 ^ w8>>>18 ^ w8>>>3 ^ w8<<25 ^ w8<<14 ) + ( w5>>>17 ^ w5>>>19 ^ w5>>>10 ^ w5<<15 ^ w5<<13 ) + w7 + w0 )|0; - a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x92722c85 )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - // 40 - w8 = ( ( w9>>>7 ^ w9>>>18 ^ w9>>>3 ^ w9<<25 ^ w9<<14 ) + ( w6>>>17 ^ w6>>>19 ^ w6>>>10 ^ w6<<15 ^ w6<<13 ) + w8 + w1 )|0; - h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0xa2bfe8a1 )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 41 - w9 = ( ( w10>>>7 ^ w10>>>18 ^ w10>>>3 ^ w10<<25 ^ w10<<14 ) + ( w7>>>17 ^ w7>>>19 ^ w7>>>10 ^ w7<<15 ^ w7<<13 ) + w9 + w2 )|0; - g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0xa81a664b )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 42 - w10 = ( ( w11>>>7 ^ w11>>>18 ^ w11>>>3 ^ w11<<25 ^ w11<<14 ) + ( w8>>>17 ^ w8>>>19 ^ w8>>>10 ^ w8<<15 ^ w8<<13 ) + w10 + w3 )|0; - f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0xc24b8b70 )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 43 - w11 = ( ( w12>>>7 ^ w12>>>18 ^ w12>>>3 ^ w12<<25 ^ w12<<14 ) + ( w9>>>17 ^ w9>>>19 ^ w9>>>10 ^ w9<<15 ^ w9<<13 ) + w11 + w4 )|0; - e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0xc76c51a3 )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 44 - w12 = ( ( w13>>>7 ^ w13>>>18 ^ w13>>>3 ^ w13<<25 ^ w13<<14 ) + ( w10>>>17 ^ w10>>>19 ^ w10>>>10 ^ w10<<15 ^ w10<<13 ) + w12 + w5 )|0; - d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0xd192e819 )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 45 - w13 = ( ( w14>>>7 ^ w14>>>18 ^ w14>>>3 ^ w14<<25 ^ w14<<14 ) + ( w11>>>17 ^ w11>>>19 ^ w11>>>10 ^ w11<<15 ^ w11<<13 ) + w13 + w6 )|0; - c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0xd6990624 )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 46 - w14 = ( ( w15>>>7 ^ w15>>>18 ^ w15>>>3 ^ w15<<25 ^ w15<<14 ) + ( w12>>>17 ^ w12>>>19 ^ w12>>>10 ^ w12<<15 ^ w12<<13 ) + w14 + w7 )|0; - b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0xf40e3585 )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 47 - w15 = ( ( w0>>>7 ^ w0>>>18 ^ w0>>>3 ^ w0<<25 ^ w0<<14 ) + ( w13>>>17 ^ w13>>>19 ^ w13>>>10 ^ w13<<15 ^ w13<<13 ) + w15 + w8 )|0; - a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x106aa070 )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - // 48 - w0 = ( ( w1>>>7 ^ w1>>>18 ^ w1>>>3 ^ w1<<25 ^ w1<<14 ) + ( w14>>>17 ^ w14>>>19 ^ w14>>>10 ^ w14<<15 ^ w14<<13 ) + w0 + w9 )|0; - h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x19a4c116 )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 49 - w1 = ( ( w2>>>7 ^ w2>>>18 ^ w2>>>3 ^ w2<<25 ^ w2<<14 ) + ( w15>>>17 ^ w15>>>19 ^ w15>>>10 ^ w15<<15 ^ w15<<13 ) + w1 + w10 )|0; - g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x1e376c08 )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 50 - w2 = ( ( w3>>>7 ^ w3>>>18 ^ w3>>>3 ^ w3<<25 ^ w3<<14 ) + ( w0>>>17 ^ w0>>>19 ^ w0>>>10 ^ w0<<15 ^ w0<<13 ) + w2 + w11 )|0; - f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x2748774c )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 51 - w3 = ( ( w4>>>7 ^ w4>>>18 ^ w4>>>3 ^ w4<<25 ^ w4<<14 ) + ( w1>>>17 ^ w1>>>19 ^ w1>>>10 ^ w1<<15 ^ w1<<13 ) + w3 + w12 )|0; - e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x34b0bcb5 )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 52 - w4 = ( ( w5>>>7 ^ w5>>>18 ^ w5>>>3 ^ w5<<25 ^ w5<<14 ) + ( w2>>>17 ^ w2>>>19 ^ w2>>>10 ^ w2<<15 ^ w2<<13 ) + w4 + w13 )|0; - d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x391c0cb3 )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 53 - w5 = ( ( w6>>>7 ^ w6>>>18 ^ w6>>>3 ^ w6<<25 ^ w6<<14 ) + ( w3>>>17 ^ w3>>>19 ^ w3>>>10 ^ w3<<15 ^ w3<<13 ) + w5 + w14 )|0; - c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x4ed8aa4a )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 54 - w6 = ( ( w7>>>7 ^ w7>>>18 ^ w7>>>3 ^ w7<<25 ^ w7<<14 ) + ( w4>>>17 ^ w4>>>19 ^ w4>>>10 ^ w4<<15 ^ w4<<13 ) + w6 + w15 )|0; - b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x5b9cca4f )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 55 - w7 = ( ( w8>>>7 ^ w8>>>18 ^ w8>>>3 ^ w8<<25 ^ w8<<14 ) + ( w5>>>17 ^ w5>>>19 ^ w5>>>10 ^ w5<<15 ^ w5<<13 ) + w7 + w0 )|0; - a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x682e6ff3 )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - // 56 - w8 = ( ( w9>>>7 ^ w9>>>18 ^ w9>>>3 ^ w9<<25 ^ w9<<14 ) + ( w6>>>17 ^ w6>>>19 ^ w6>>>10 ^ w6<<15 ^ w6<<13 ) + w8 + w1 )|0; - h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x748f82ee )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 57 - w9 = ( ( w10>>>7 ^ w10>>>18 ^ w10>>>3 ^ w10<<25 ^ w10<<14 ) + ( w7>>>17 ^ w7>>>19 ^ w7>>>10 ^ w7<<15 ^ w7<<13 ) + w9 + w2 )|0; - g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x78a5636f )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 58 - w10 = ( ( w11>>>7 ^ w11>>>18 ^ w11>>>3 ^ w11<<25 ^ w11<<14 ) + ( w8>>>17 ^ w8>>>19 ^ w8>>>10 ^ w8<<15 ^ w8<<13 ) + w10 + w3 )|0; - f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x84c87814 )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 59 - w11 = ( ( w12>>>7 ^ w12>>>18 ^ w12>>>3 ^ w12<<25 ^ w12<<14 ) + ( w9>>>17 ^ w9>>>19 ^ w9>>>10 ^ w9<<15 ^ w9<<13 ) + w11 + w4 )|0; - e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x8cc70208 )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 60 - w12 = ( ( w13>>>7 ^ w13>>>18 ^ w13>>>3 ^ w13<<25 ^ w13<<14 ) + ( w10>>>17 ^ w10>>>19 ^ w10>>>10 ^ w10<<15 ^ w10<<13 ) + w12 + w5 )|0; - d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x90befffa )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 61 - w13 = ( ( w14>>>7 ^ w14>>>18 ^ w14>>>3 ^ w14<<25 ^ w14<<14 ) + ( w11>>>17 ^ w11>>>19 ^ w11>>>10 ^ w11<<15 ^ w11<<13 ) + w13 + w6 )|0; - c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0xa4506ceb )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 62 - w14 = ( ( w15>>>7 ^ w15>>>18 ^ w15>>>3 ^ w15<<25 ^ w15<<14 ) + ( w12>>>17 ^ w12>>>19 ^ w12>>>10 ^ w12<<15 ^ w12<<13 ) + w14 + w7 )|0; - b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0xbef9a3f7 )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 63 - w15 = ( ( w0>>>7 ^ w0>>>18 ^ w0>>>3 ^ w0<<25 ^ w0<<14 ) + ( w13>>>17 ^ w13>>>19 ^ w13>>>10 ^ w13<<15 ^ w13<<13 ) + w15 + w8 )|0; - a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0xc67178f2 )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - H0 = ( H0 + a )|0; - H1 = ( H1 + b )|0; - H2 = ( H2 + c )|0; - H3 = ( H3 + d )|0; - H4 = ( H4 + e )|0; - H5 = ( H5 + f )|0; - H6 = ( H6 + g )|0; - H7 = ( H7 + h )|0; - } - - function _core_heap ( offset ) { - offset = offset|0; - - _core( - HEAP[offset|0]<<24 | HEAP[offset|1]<<16 | HEAP[offset|2]<<8 | HEAP[offset|3], - HEAP[offset|4]<<24 | HEAP[offset|5]<<16 | HEAP[offset|6]<<8 | HEAP[offset|7], - HEAP[offset|8]<<24 | HEAP[offset|9]<<16 | HEAP[offset|10]<<8 | HEAP[offset|11], - HEAP[offset|12]<<24 | HEAP[offset|13]<<16 | HEAP[offset|14]<<8 | HEAP[offset|15], - HEAP[offset|16]<<24 | HEAP[offset|17]<<16 | HEAP[offset|18]<<8 | HEAP[offset|19], - HEAP[offset|20]<<24 | HEAP[offset|21]<<16 | HEAP[offset|22]<<8 | HEAP[offset|23], - HEAP[offset|24]<<24 | HEAP[offset|25]<<16 | HEAP[offset|26]<<8 | HEAP[offset|27], - HEAP[offset|28]<<24 | HEAP[offset|29]<<16 | HEAP[offset|30]<<8 | HEAP[offset|31], - HEAP[offset|32]<<24 | HEAP[offset|33]<<16 | HEAP[offset|34]<<8 | HEAP[offset|35], - HEAP[offset|36]<<24 | HEAP[offset|37]<<16 | HEAP[offset|38]<<8 | HEAP[offset|39], - HEAP[offset|40]<<24 | HEAP[offset|41]<<16 | HEAP[offset|42]<<8 | HEAP[offset|43], - HEAP[offset|44]<<24 | HEAP[offset|45]<<16 | HEAP[offset|46]<<8 | HEAP[offset|47], - HEAP[offset|48]<<24 | HEAP[offset|49]<<16 | HEAP[offset|50]<<8 | HEAP[offset|51], - HEAP[offset|52]<<24 | HEAP[offset|53]<<16 | HEAP[offset|54]<<8 | HEAP[offset|55], - HEAP[offset|56]<<24 | HEAP[offset|57]<<16 | HEAP[offset|58]<<8 | HEAP[offset|59], - HEAP[offset|60]<<24 | HEAP[offset|61]<<16 | HEAP[offset|62]<<8 | HEAP[offset|63] - ); - } - - // offset — multiple of 32 - function _state_to_heap ( output ) { - output = output|0; - - HEAP[output|0] = H0>>>24; - HEAP[output|1] = H0>>>16&255; - HEAP[output|2] = H0>>>8&255; - HEAP[output|3] = H0&255; - HEAP[output|4] = H1>>>24; - HEAP[output|5] = H1>>>16&255; - HEAP[output|6] = H1>>>8&255; - HEAP[output|7] = H1&255; - HEAP[output|8] = H2>>>24; - HEAP[output|9] = H2>>>16&255; - HEAP[output|10] = H2>>>8&255; - HEAP[output|11] = H2&255; - HEAP[output|12] = H3>>>24; - HEAP[output|13] = H3>>>16&255; - HEAP[output|14] = H3>>>8&255; - HEAP[output|15] = H3&255; - HEAP[output|16] = H4>>>24; - HEAP[output|17] = H4>>>16&255; - HEAP[output|18] = H4>>>8&255; - HEAP[output|19] = H4&255; - HEAP[output|20] = H5>>>24; - HEAP[output|21] = H5>>>16&255; - HEAP[output|22] = H5>>>8&255; - HEAP[output|23] = H5&255; - HEAP[output|24] = H6>>>24; - HEAP[output|25] = H6>>>16&255; - HEAP[output|26] = H6>>>8&255; - HEAP[output|27] = H6&255; - HEAP[output|28] = H7>>>24; - HEAP[output|29] = H7>>>16&255; - HEAP[output|30] = H7>>>8&255; - HEAP[output|31] = H7&255; - } - - function reset () { - H0 = 0x6a09e667; - H1 = 0xbb67ae85; - H2 = 0x3c6ef372; - H3 = 0xa54ff53a; - H4 = 0x510e527f; - H5 = 0x9b05688c; - H6 = 0x1f83d9ab; - H7 = 0x5be0cd19; - TOTAL0 = TOTAL1 = 0; - } - - function init ( h0, h1, h2, h3, h4, h5, h6, h7, total0, total1 ) { - h0 = h0|0; - h1 = h1|0; - h2 = h2|0; - h3 = h3|0; - h4 = h4|0; - h5 = h5|0; - h6 = h6|0; - h7 = h7|0; - total0 = total0|0; - total1 = total1|0; - - H0 = h0; - H1 = h1; - H2 = h2; - H3 = h3; - H4 = h4; - H5 = h5; - H6 = h6; - H7 = h7; - TOTAL0 = total0; - TOTAL1 = total1; - } - - // offset — multiple of 64 - function process ( offset, length ) { - offset = offset|0; - length = length|0; - - var hashed = 0; - - if ( offset & 63 ) - return -1; - - while ( (length|0) >= 64 ) { - _core_heap(offset); - - offset = ( offset + 64 )|0; - length = ( length - 64 )|0; - - hashed = ( hashed + 64 )|0; - } - - TOTAL0 = ( TOTAL0 + hashed )|0; - if ( TOTAL0>>>0 < hashed>>>0 ) TOTAL1 = ( TOTAL1 + 1 )|0; - - return hashed|0; - } - - // offset — multiple of 64 - // output — multiple of 32 - function finish ( offset, length, output ) { - offset = offset|0; - length = length|0; - output = output|0; - - var hashed = 0, - i = 0; - - if ( offset & 63 ) - return -1; - - if ( ~output ) - if ( output & 31 ) - return -1; - - if ( (length|0) >= 64 ) { - hashed = process( offset, length )|0; - if ( (hashed|0) == -1 ) - return -1; - - offset = ( offset + hashed )|0; - length = ( length - hashed )|0; - } - - hashed = ( hashed + length )|0; - TOTAL0 = ( TOTAL0 + length )|0; - if ( TOTAL0>>>0 < length>>>0 ) TOTAL1 = ( TOTAL1 + 1 )|0; - - HEAP[offset|length] = 0x80; - - if ( (length|0) >= 56 ) { - for ( i = (length+1)|0; (i|0) < 64; i = (i+1)|0 ) - HEAP[offset|i] = 0x00; - - _core_heap(offset); - - length = 0; - - HEAP[offset|0] = 0; - } - - for ( i = (length+1)|0; (i|0) < 59; i = (i+1)|0 ) - HEAP[offset|i] = 0; - - HEAP[offset|56] = TOTAL1>>>21&255; - HEAP[offset|57] = TOTAL1>>>13&255; - HEAP[offset|58] = TOTAL1>>>5&255; - HEAP[offset|59] = TOTAL1<<3&255 | TOTAL0>>>29; - HEAP[offset|60] = TOTAL0>>>21&255; - HEAP[offset|61] = TOTAL0>>>13&255; - HEAP[offset|62] = TOTAL0>>>5&255; - HEAP[offset|63] = TOTAL0<<3&255; - _core_heap(offset); - - if ( ~output ) - _state_to_heap(output); - - return hashed|0; - } - - function hmac_reset () { - H0 = I0; - H1 = I1; - H2 = I2; - H3 = I3; - H4 = I4; - H5 = I5; - H6 = I6; - H7 = I7; - TOTAL0 = 64; - TOTAL1 = 0; - } - - function _hmac_opad () { - H0 = O0; - H1 = O1; - H2 = O2; - H3 = O3; - H4 = O4; - H5 = O5; - H6 = O6; - H7 = O7; - TOTAL0 = 64; - TOTAL1 = 0; - } - - function hmac_init ( p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15 ) { - p0 = p0|0; - p1 = p1|0; - p2 = p2|0; - p3 = p3|0; - p4 = p4|0; - p5 = p5|0; - p6 = p6|0; - p7 = p7|0; - p8 = p8|0; - p9 = p9|0; - p10 = p10|0; - p11 = p11|0; - p12 = p12|0; - p13 = p13|0; - p14 = p14|0; - p15 = p15|0; - - // opad - reset(); - _core( - p0 ^ 0x5c5c5c5c, - p1 ^ 0x5c5c5c5c, - p2 ^ 0x5c5c5c5c, - p3 ^ 0x5c5c5c5c, - p4 ^ 0x5c5c5c5c, - p5 ^ 0x5c5c5c5c, - p6 ^ 0x5c5c5c5c, - p7 ^ 0x5c5c5c5c, - p8 ^ 0x5c5c5c5c, - p9 ^ 0x5c5c5c5c, - p10 ^ 0x5c5c5c5c, - p11 ^ 0x5c5c5c5c, - p12 ^ 0x5c5c5c5c, - p13 ^ 0x5c5c5c5c, - p14 ^ 0x5c5c5c5c, - p15 ^ 0x5c5c5c5c - ); - O0 = H0; - O1 = H1; - O2 = H2; - O3 = H3; - O4 = H4; - O5 = H5; - O6 = H6; - O7 = H7; - - // ipad - reset(); - _core( - p0 ^ 0x36363636, - p1 ^ 0x36363636, - p2 ^ 0x36363636, - p3 ^ 0x36363636, - p4 ^ 0x36363636, - p5 ^ 0x36363636, - p6 ^ 0x36363636, - p7 ^ 0x36363636, - p8 ^ 0x36363636, - p9 ^ 0x36363636, - p10 ^ 0x36363636, - p11 ^ 0x36363636, - p12 ^ 0x36363636, - p13 ^ 0x36363636, - p14 ^ 0x36363636, - p15 ^ 0x36363636 - ); - I0 = H0; - I1 = H1; - I2 = H2; - I3 = H3; - I4 = H4; - I5 = H5; - I6 = H6; - I7 = H7; - - TOTAL0 = 64; - TOTAL1 = 0; - } - - // offset — multiple of 64 - // output — multiple of 32 - function hmac_finish ( offset, length, output ) { - offset = offset|0; - length = length|0; - output = output|0; - - var t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0, - hashed = 0; - - if ( offset & 63 ) - return -1; - - if ( ~output ) - if ( output & 31 ) - return -1; - - hashed = finish( offset, length, -1 )|0; - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; - - _hmac_opad(); - _core( t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768 ); - - if ( ~output ) - _state_to_heap(output); - - return hashed|0; - } - - // salt is assumed to be already processed - // offset — multiple of 64 - // output — multiple of 32 - function pbkdf2_generate_block ( offset, length, block, count, output ) { - offset = offset|0; - length = length|0; - block = block|0; - count = count|0; - output = output|0; - - var h0 = 0, h1 = 0, h2 = 0, h3 = 0, h4 = 0, h5 = 0, h6 = 0, h7 = 0, - t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0; - - if ( offset & 63 ) - return -1; - - if ( ~output ) - if ( output & 31 ) - return -1; - - // pad block number into heap - // FIXME probable OOB write - HEAP[(offset+length)|0] = block>>>24; - HEAP[(offset+length+1)|0] = block>>>16&255; - HEAP[(offset+length+2)|0] = block>>>8&255; - HEAP[(offset+length+3)|0] = block&255; - - // finish first iteration - hmac_finish( offset, (length+4)|0, -1 )|0; - h0 = t0 = H0, h1 = t1 = H1, h2 = t2 = H2, h3 = t3 = H3, h4 = t4 = H4, h5 = t5 = H5, h6 = t6 = H6, h7 = t7 = H7; - count = (count-1)|0; - - // perform the rest iterations - while ( (count|0) > 0 ) { - hmac_reset(); - _core( t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768 ); - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; - - _hmac_opad(); - _core( t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768 ); - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; - - h0 = h0 ^ H0; - h1 = h1 ^ H1; - h2 = h2 ^ H2; - h3 = h3 ^ H3; - h4 = h4 ^ H4; - h5 = h5 ^ H5; - h6 = h6 ^ H6; - h7 = h7 ^ H7; - - count = (count-1)|0; - } - - H0 = h0; - H1 = h1; - H2 = h2; - H3 = h3; - H4 = h4; - H5 = h5; - H6 = h6; - H7 = h7; - - if ( ~output ) - _state_to_heap(output); - - return 0; - } - - return { - // SHA256 - reset: reset, - init: init, - process: process, - finish: finish, - - // HMAC-SHA256 - hmac_reset: hmac_reset, - hmac_init: hmac_init, - hmac_finish: hmac_finish, - - // PBKDF2-HMAC-SHA256 - pbkdf2_generate_block: pbkdf2_generate_block - } -}; - -const _sha256_block_size = 64; -const _sha256_hash_size = 32; -const heap_pool$2 = []; -const asm_pool$2 = []; -class Sha256 extends Hash { - constructor() { - super(); - this.NAME = 'sha256'; - this.BLOCK_SIZE = _sha256_block_size; - this.HASH_SIZE = _sha256_hash_size; - this.acquire_asm(); - } - acquire_asm() { - if (this.heap === undefined || this.asm === undefined) { - this.heap = heap_pool$2.pop() || _heap_init(); - this.asm = asm_pool$2.pop() || sha256_asm({ Uint8Array: Uint8Array }, null, this.heap.buffer); - this.reset(); - } - return { heap: this.heap, asm: this.asm }; - } - release_asm() { - if (this.heap !== undefined && this.asm !== undefined) { - heap_pool$2.push(this.heap); - asm_pool$2.push(this.asm); - } - this.heap = undefined; - this.asm = undefined; - } - static bytes(data) { - return new Sha256().process(data).finish().result; - } -} -Sha256.NAME = 'sha256'; - -var minimalisticAssert = assert; - -function assert(val, msg) { - if (!val) - throw new Error(msg || 'Assertion failed'); -} - -assert.equal = function assertEqual(l, r, msg) { - if (l != r) - throw new Error(msg || ('Assertion failed: ' + l + ' != ' + r)); -}; - -var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; - -function createCommonjsModule(fn, module) { - return module = { exports: {} }, fn(module, module.exports), module.exports; -} - -function commonjsRequire () { - throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs'); -} - -var inherits_browser = createCommonjsModule(function (module) { -if (typeof Object.create === 'function') { - // implementation from standard node.js 'util' module - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor; - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }); - }; -} else { - // old school shim for old browsers - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor; - var TempCtor = function () {}; - TempCtor.prototype = superCtor.prototype; - ctor.prototype = new TempCtor(); - ctor.prototype.constructor = ctor; - }; -} -}); - -var inherits = createCommonjsModule(function (module) { -try { - var util = util__default['default']; - if (typeof util.inherits !== 'function') throw ''; - module.exports = util.inherits; -} catch (e) { - module.exports = inherits_browser; -} -}); - -var inherits_1 = inherits; - -function toArray(msg, enc) { - if (Array.isArray(msg)) - return msg.slice(); - if (!msg) - return []; - var res = []; - if (typeof msg === 'string') { - if (!enc) { - for (var i = 0; i < msg.length; i++) { - var c = msg.charCodeAt(i); - var hi = c >> 8; - var lo = c & 0xff; - if (hi) - res.push(hi, lo); - else - res.push(lo); - } - } else if (enc === 'hex') { - msg = msg.replace(/[^a-z0-9]+/ig, ''); - if (msg.length % 2 !== 0) - msg = '0' + msg; - for (i = 0; i < msg.length; i += 2) - res.push(parseInt(msg[i] + msg[i + 1], 16)); - } - } else { - for (i = 0; i < msg.length; i++) - res[i] = msg[i] | 0; - } - return res; -} -var toArray_1 = toArray; - -function toHex(msg) { - var res = ''; - for (var i = 0; i < msg.length; i++) - res += zero2(msg[i].toString(16)); - return res; -} -var toHex_1 = toHex; - -function htonl(w) { - var res = (w >>> 24) | - ((w >>> 8) & 0xff00) | - ((w << 8) & 0xff0000) | - ((w & 0xff) << 24); - return res >>> 0; -} -var htonl_1 = htonl; - -function toHex32(msg, endian) { - var res = ''; - for (var i = 0; i < msg.length; i++) { - var w = msg[i]; - if (endian === 'little') - w = htonl(w); - res += zero8(w.toString(16)); - } - return res; -} -var toHex32_1 = toHex32; - -function zero2(word) { - if (word.length === 1) - return '0' + word; - else - return word; -} -var zero2_1 = zero2; - -function zero8(word) { - if (word.length === 7) - return '0' + word; - else if (word.length === 6) - return '00' + word; - else if (word.length === 5) - return '000' + word; - else if (word.length === 4) - return '0000' + word; - else if (word.length === 3) - return '00000' + word; - else if (word.length === 2) - return '000000' + word; - else if (word.length === 1) - return '0000000' + word; - else - return word; -} -var zero8_1 = zero8; - -function join32(msg, start, end, endian) { - var len = end - start; - minimalisticAssert(len % 4 === 0); - var res = new Array(len / 4); - for (var i = 0, k = start; i < res.length; i++, k += 4) { - var w; - if (endian === 'big') - w = (msg[k] << 24) | (msg[k + 1] << 16) | (msg[k + 2] << 8) | msg[k + 3]; - else - w = (msg[k + 3] << 24) | (msg[k + 2] << 16) | (msg[k + 1] << 8) | msg[k]; - res[i] = w >>> 0; - } - return res; -} -var join32_1 = join32; - -function split32(msg, endian) { - var res = new Array(msg.length * 4); - for (var i = 0, k = 0; i < msg.length; i++, k += 4) { - var m = msg[i]; - if (endian === 'big') { - res[k] = m >>> 24; - res[k + 1] = (m >>> 16) & 0xff; - res[k + 2] = (m >>> 8) & 0xff; - res[k + 3] = m & 0xff; - } else { - res[k + 3] = m >>> 24; - res[k + 2] = (m >>> 16) & 0xff; - res[k + 1] = (m >>> 8) & 0xff; - res[k] = m & 0xff; - } - } - return res; -} -var split32_1 = split32; - -function rotr32(w, b) { - return (w >>> b) | (w << (32 - b)); -} -var rotr32_1 = rotr32; - -function rotl32(w, b) { - return (w << b) | (w >>> (32 - b)); -} -var rotl32_1 = rotl32; - -function sum32(a, b) { - return (a + b) >>> 0; -} -var sum32_1 = sum32; - -function sum32_3(a, b, c) { - return (a + b + c) >>> 0; -} -var sum32_3_1 = sum32_3; - -function sum32_4(a, b, c, d) { - return (a + b + c + d) >>> 0; -} -var sum32_4_1 = sum32_4; - -function sum32_5(a, b, c, d, e) { - return (a + b + c + d + e) >>> 0; -} -var sum32_5_1 = sum32_5; - -function sum64(buf, pos, ah, al) { - var bh = buf[pos]; - var bl = buf[pos + 1]; - - var lo = (al + bl) >>> 0; - var hi = (lo < al ? 1 : 0) + ah + bh; - buf[pos] = hi >>> 0; - buf[pos + 1] = lo; -} -var sum64_1 = sum64; - -function sum64_hi(ah, al, bh, bl) { - var lo = (al + bl) >>> 0; - var hi = (lo < al ? 1 : 0) + ah + bh; - return hi >>> 0; -} -var sum64_hi_1 = sum64_hi; - -function sum64_lo(ah, al, bh, bl) { - var lo = al + bl; - return lo >>> 0; -} -var sum64_lo_1 = sum64_lo; - -function sum64_4_hi(ah, al, bh, bl, ch, cl, dh, dl) { - var carry = 0; - var lo = al; - lo = (lo + bl) >>> 0; - carry += lo < al ? 1 : 0; - lo = (lo + cl) >>> 0; - carry += lo < cl ? 1 : 0; - lo = (lo + dl) >>> 0; - carry += lo < dl ? 1 : 0; - - var hi = ah + bh + ch + dh + carry; - return hi >>> 0; -} -var sum64_4_hi_1 = sum64_4_hi; - -function sum64_4_lo(ah, al, bh, bl, ch, cl, dh, dl) { - var lo = al + bl + cl + dl; - return lo >>> 0; -} -var sum64_4_lo_1 = sum64_4_lo; - -function sum64_5_hi(ah, al, bh, bl, ch, cl, dh, dl, eh, el) { - var carry = 0; - var lo = al; - lo = (lo + bl) >>> 0; - carry += lo < al ? 1 : 0; - lo = (lo + cl) >>> 0; - carry += lo < cl ? 1 : 0; - lo = (lo + dl) >>> 0; - carry += lo < dl ? 1 : 0; - lo = (lo + el) >>> 0; - carry += lo < el ? 1 : 0; - - var hi = ah + bh + ch + dh + eh + carry; - return hi >>> 0; -} -var sum64_5_hi_1 = sum64_5_hi; - -function sum64_5_lo(ah, al, bh, bl, ch, cl, dh, dl, eh, el) { - var lo = al + bl + cl + dl + el; - - return lo >>> 0; -} -var sum64_5_lo_1 = sum64_5_lo; - -function rotr64_hi(ah, al, num) { - var r = (al << (32 - num)) | (ah >>> num); - return r >>> 0; -} -var rotr64_hi_1 = rotr64_hi; - -function rotr64_lo(ah, al, num) { - var r = (ah << (32 - num)) | (al >>> num); - return r >>> 0; -} -var rotr64_lo_1 = rotr64_lo; - -function shr64_hi(ah, al, num) { - return ah >>> num; -} -var shr64_hi_1 = shr64_hi; - -function shr64_lo(ah, al, num) { - var r = (ah << (32 - num)) | (al >>> num); - return r >>> 0; -} -var shr64_lo_1 = shr64_lo; - -var utils = { - inherits: inherits_1, - toArray: toArray_1, - toHex: toHex_1, - htonl: htonl_1, - toHex32: toHex32_1, - zero2: zero2_1, - zero8: zero8_1, - join32: join32_1, - split32: split32_1, - rotr32: rotr32_1, - rotl32: rotl32_1, - sum32: sum32_1, - sum32_3: sum32_3_1, - sum32_4: sum32_4_1, - sum32_5: sum32_5_1, - sum64: sum64_1, - sum64_hi: sum64_hi_1, - sum64_lo: sum64_lo_1, - sum64_4_hi: sum64_4_hi_1, - sum64_4_lo: sum64_4_lo_1, - sum64_5_hi: sum64_5_hi_1, - sum64_5_lo: sum64_5_lo_1, - rotr64_hi: rotr64_hi_1, - rotr64_lo: rotr64_lo_1, - shr64_hi: shr64_hi_1, - shr64_lo: shr64_lo_1 -}; - -function BlockHash() { - this.pending = null; - this.pendingTotal = 0; - this.blockSize = this.constructor.blockSize; - this.outSize = this.constructor.outSize; - this.hmacStrength = this.constructor.hmacStrength; - this.padLength = this.constructor.padLength / 8; - this.endian = 'big'; - - this._delta8 = this.blockSize / 8; - this._delta32 = this.blockSize / 32; -} -var BlockHash_1 = BlockHash; - -BlockHash.prototype.update = function update(msg, enc) { - // Convert message to array, pad it, and join into 32bit blocks - msg = utils.toArray(msg, enc); - if (!this.pending) - this.pending = msg; - else - this.pending = this.pending.concat(msg); - this.pendingTotal += msg.length; - - // Enough data, try updating - if (this.pending.length >= this._delta8) { - msg = this.pending; - - // Process pending data in blocks - var r = msg.length % this._delta8; - this.pending = msg.slice(msg.length - r, msg.length); - if (this.pending.length === 0) - this.pending = null; - - msg = utils.join32(msg, 0, msg.length - r, this.endian); - for (var i = 0; i < msg.length; i += this._delta32) - this._update(msg, i, i + this._delta32); - } - - return this; -}; - -BlockHash.prototype.digest = function digest(enc) { - this.update(this._pad()); - minimalisticAssert(this.pending === null); - - return this._digest(enc); -}; - -BlockHash.prototype._pad = function pad() { - var len = this.pendingTotal; - var bytes = this._delta8; - var k = bytes - ((len + this.padLength) % bytes); - var res = new Array(k + this.padLength); - res[0] = 0x80; - for (var i = 1; i < k; i++) - res[i] = 0; - - // Append length - len <<= 3; - if (this.endian === 'big') { - for (var t = 8; t < this.padLength; t++) - res[i++] = 0; - - res[i++] = 0; - res[i++] = 0; - res[i++] = 0; - res[i++] = 0; - res[i++] = (len >>> 24) & 0xff; - res[i++] = (len >>> 16) & 0xff; - res[i++] = (len >>> 8) & 0xff; - res[i++] = len & 0xff; - } else { - res[i++] = len & 0xff; - res[i++] = (len >>> 8) & 0xff; - res[i++] = (len >>> 16) & 0xff; - res[i++] = (len >>> 24) & 0xff; - res[i++] = 0; - res[i++] = 0; - res[i++] = 0; - res[i++] = 0; - - for (t = 8; t < this.padLength; t++) - res[i++] = 0; - } - - return res; -}; - -var common = { - BlockHash: BlockHash_1 -}; - -var rotr32$1 = utils.rotr32; - -function ft_1(s, x, y, z) { - if (s === 0) - return ch32(x, y, z); - if (s === 1 || s === 3) - return p32(x, y, z); - if (s === 2) - return maj32(x, y, z); -} -var ft_1_1 = ft_1; - -function ch32(x, y, z) { - return (x & y) ^ ((~x) & z); -} -var ch32_1 = ch32; - -function maj32(x, y, z) { - return (x & y) ^ (x & z) ^ (y & z); -} -var maj32_1 = maj32; - -function p32(x, y, z) { - return x ^ y ^ z; -} -var p32_1 = p32; - -function s0_256(x) { - return rotr32$1(x, 2) ^ rotr32$1(x, 13) ^ rotr32$1(x, 22); -} -var s0_256_1 = s0_256; - -function s1_256(x) { - return rotr32$1(x, 6) ^ rotr32$1(x, 11) ^ rotr32$1(x, 25); -} -var s1_256_1 = s1_256; - -function g0_256(x) { - return rotr32$1(x, 7) ^ rotr32$1(x, 18) ^ (x >>> 3); -} -var g0_256_1 = g0_256; - -function g1_256(x) { - return rotr32$1(x, 17) ^ rotr32$1(x, 19) ^ (x >>> 10); -} -var g1_256_1 = g1_256; - -var common$1 = { - ft_1: ft_1_1, - ch32: ch32_1, - maj32: maj32_1, - p32: p32_1, - s0_256: s0_256_1, - s1_256: s1_256_1, - g0_256: g0_256_1, - g1_256: g1_256_1 -}; - -var sum32$1 = utils.sum32; -var sum32_4$1 = utils.sum32_4; -var sum32_5$1 = utils.sum32_5; -var ch32$1 = common$1.ch32; -var maj32$1 = common$1.maj32; -var s0_256$1 = common$1.s0_256; -var s1_256$1 = common$1.s1_256; -var g0_256$1 = common$1.g0_256; -var g1_256$1 = common$1.g1_256; - -var BlockHash$1 = common.BlockHash; - -var sha256_K = [ - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -]; - -function SHA256() { - if (!(this instanceof SHA256)) - return new SHA256(); - - BlockHash$1.call(this); - this.h = [ - 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, - 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 - ]; - this.k = sha256_K; - this.W = new Array(64); -} -utils.inherits(SHA256, BlockHash$1); -var _256 = SHA256; - -SHA256.blockSize = 512; -SHA256.outSize = 256; -SHA256.hmacStrength = 192; -SHA256.padLength = 64; - -SHA256.prototype._update = function _update(msg, start) { - var W = this.W; - - for (var i = 0; i < 16; i++) - W[i] = msg[start + i]; - for (; i < W.length; i++) - W[i] = sum32_4$1(g1_256$1(W[i - 2]), W[i - 7], g0_256$1(W[i - 15]), W[i - 16]); - - var a = this.h[0]; - var b = this.h[1]; - var c = this.h[2]; - var d = this.h[3]; - var e = this.h[4]; - var f = this.h[5]; - var g = this.h[6]; - var h = this.h[7]; - - minimalisticAssert(this.k.length === W.length); - for (i = 0; i < W.length; i++) { - var T1 = sum32_5$1(h, s1_256$1(e), ch32$1(e, f, g), this.k[i], W[i]); - var T2 = sum32$1(s0_256$1(a), maj32$1(a, b, c)); - h = g; - g = f; - f = e; - e = sum32$1(d, T1); - d = c; - c = b; - b = a; - a = sum32$1(T1, T2); - } - - this.h[0] = sum32$1(this.h[0], a); - this.h[1] = sum32$1(this.h[1], b); - this.h[2] = sum32$1(this.h[2], c); - this.h[3] = sum32$1(this.h[3], d); - this.h[4] = sum32$1(this.h[4], e); - this.h[5] = sum32$1(this.h[5], f); - this.h[6] = sum32$1(this.h[6], g); - this.h[7] = sum32$1(this.h[7], h); -}; - -SHA256.prototype._digest = function digest(enc) { - if (enc === 'hex') - return utils.toHex32(this.h, 'big'); - else - return utils.split32(this.h, 'big'); -}; - -function SHA224() { - if (!(this instanceof SHA224)) - return new SHA224(); - - _256.call(this); - this.h = [ - 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, - 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 ]; -} -utils.inherits(SHA224, _256); -var _224 = SHA224; - -SHA224.blockSize = 512; -SHA224.outSize = 224; -SHA224.hmacStrength = 192; -SHA224.padLength = 64; - -SHA224.prototype._digest = function digest(enc) { - // Just truncate output - if (enc === 'hex') - return utils.toHex32(this.h.slice(0, 7), 'big'); - else - return utils.split32(this.h.slice(0, 7), 'big'); -}; - -var rotr64_hi$1 = utils.rotr64_hi; -var rotr64_lo$1 = utils.rotr64_lo; -var shr64_hi$1 = utils.shr64_hi; -var shr64_lo$1 = utils.shr64_lo; -var sum64$1 = utils.sum64; -var sum64_hi$1 = utils.sum64_hi; -var sum64_lo$1 = utils.sum64_lo; -var sum64_4_hi$1 = utils.sum64_4_hi; -var sum64_4_lo$1 = utils.sum64_4_lo; -var sum64_5_hi$1 = utils.sum64_5_hi; -var sum64_5_lo$1 = utils.sum64_5_lo; - -var BlockHash$2 = common.BlockHash; - -var sha512_K = [ - 0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd, - 0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc, - 0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019, - 0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118, - 0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe, - 0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2, - 0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1, - 0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694, - 0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3, - 0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65, - 0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483, - 0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5, - 0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210, - 0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4, - 0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725, - 0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70, - 0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926, - 0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df, - 0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8, - 0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b, - 0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001, - 0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30, - 0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910, - 0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8, - 0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53, - 0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8, - 0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb, - 0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3, - 0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60, - 0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec, - 0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9, - 0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b, - 0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207, - 0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178, - 0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6, - 0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b, - 0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493, - 0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c, - 0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a, - 0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817 -]; - -function SHA512() { - if (!(this instanceof SHA512)) - return new SHA512(); - - BlockHash$2.call(this); - this.h = [ - 0x6a09e667, 0xf3bcc908, - 0xbb67ae85, 0x84caa73b, - 0x3c6ef372, 0xfe94f82b, - 0xa54ff53a, 0x5f1d36f1, - 0x510e527f, 0xade682d1, - 0x9b05688c, 0x2b3e6c1f, - 0x1f83d9ab, 0xfb41bd6b, - 0x5be0cd19, 0x137e2179 ]; - this.k = sha512_K; - this.W = new Array(160); -} -utils.inherits(SHA512, BlockHash$2); -var _512 = SHA512; - -SHA512.blockSize = 1024; -SHA512.outSize = 512; -SHA512.hmacStrength = 192; -SHA512.padLength = 128; - -SHA512.prototype._prepareBlock = function _prepareBlock(msg, start) { - var W = this.W; - - // 32 x 32bit words - for (var i = 0; i < 32; i++) - W[i] = msg[start + i]; - for (; i < W.length; i += 2) { - var c0_hi = g1_512_hi(W[i - 4], W[i - 3]); // i - 2 - var c0_lo = g1_512_lo(W[i - 4], W[i - 3]); - var c1_hi = W[i - 14]; // i - 7 - var c1_lo = W[i - 13]; - var c2_hi = g0_512_hi(W[i - 30], W[i - 29]); // i - 15 - var c2_lo = g0_512_lo(W[i - 30], W[i - 29]); - var c3_hi = W[i - 32]; // i - 16 - var c3_lo = W[i - 31]; - - W[i] = sum64_4_hi$1( - c0_hi, c0_lo, - c1_hi, c1_lo, - c2_hi, c2_lo, - c3_hi, c3_lo); - W[i + 1] = sum64_4_lo$1( - c0_hi, c0_lo, - c1_hi, c1_lo, - c2_hi, c2_lo, - c3_hi, c3_lo); - } -}; - -SHA512.prototype._update = function _update(msg, start) { - this._prepareBlock(msg, start); - - var W = this.W; - - var ah = this.h[0]; - var al = this.h[1]; - var bh = this.h[2]; - var bl = this.h[3]; - var ch = this.h[4]; - var cl = this.h[5]; - var dh = this.h[6]; - var dl = this.h[7]; - var eh = this.h[8]; - var el = this.h[9]; - var fh = this.h[10]; - var fl = this.h[11]; - var gh = this.h[12]; - var gl = this.h[13]; - var hh = this.h[14]; - var hl = this.h[15]; - - minimalisticAssert(this.k.length === W.length); - for (var i = 0; i < W.length; i += 2) { - var c0_hi = hh; - var c0_lo = hl; - var c1_hi = s1_512_hi(eh, el); - var c1_lo = s1_512_lo(eh, el); - var c2_hi = ch64_hi(eh, el, fh, fl, gh); - var c2_lo = ch64_lo(eh, el, fh, fl, gh, gl); - var c3_hi = this.k[i]; - var c3_lo = this.k[i + 1]; - var c4_hi = W[i]; - var c4_lo = W[i + 1]; - - var T1_hi = sum64_5_hi$1( - c0_hi, c0_lo, - c1_hi, c1_lo, - c2_hi, c2_lo, - c3_hi, c3_lo, - c4_hi, c4_lo); - var T1_lo = sum64_5_lo$1( - c0_hi, c0_lo, - c1_hi, c1_lo, - c2_hi, c2_lo, - c3_hi, c3_lo, - c4_hi, c4_lo); - - c0_hi = s0_512_hi(ah, al); - c0_lo = s0_512_lo(ah, al); - c1_hi = maj64_hi(ah, al, bh, bl, ch); - c1_lo = maj64_lo(ah, al, bh, bl, ch, cl); - - var T2_hi = sum64_hi$1(c0_hi, c0_lo, c1_hi, c1_lo); - var T2_lo = sum64_lo$1(c0_hi, c0_lo, c1_hi, c1_lo); - - hh = gh; - hl = gl; - - gh = fh; - gl = fl; - - fh = eh; - fl = el; - - eh = sum64_hi$1(dh, dl, T1_hi, T1_lo); - el = sum64_lo$1(dl, dl, T1_hi, T1_lo); - - dh = ch; - dl = cl; - - ch = bh; - cl = bl; - - bh = ah; - bl = al; - - ah = sum64_hi$1(T1_hi, T1_lo, T2_hi, T2_lo); - al = sum64_lo$1(T1_hi, T1_lo, T2_hi, T2_lo); - } - - sum64$1(this.h, 0, ah, al); - sum64$1(this.h, 2, bh, bl); - sum64$1(this.h, 4, ch, cl); - sum64$1(this.h, 6, dh, dl); - sum64$1(this.h, 8, eh, el); - sum64$1(this.h, 10, fh, fl); - sum64$1(this.h, 12, gh, gl); - sum64$1(this.h, 14, hh, hl); -}; - -SHA512.prototype._digest = function digest(enc) { - if (enc === 'hex') - return utils.toHex32(this.h, 'big'); - else - return utils.split32(this.h, 'big'); -}; - -function ch64_hi(xh, xl, yh, yl, zh) { - var r = (xh & yh) ^ ((~xh) & zh); - if (r < 0) - r += 0x100000000; - return r; -} - -function ch64_lo(xh, xl, yh, yl, zh, zl) { - var r = (xl & yl) ^ ((~xl) & zl); - if (r < 0) - r += 0x100000000; - return r; -} - -function maj64_hi(xh, xl, yh, yl, zh) { - var r = (xh & yh) ^ (xh & zh) ^ (yh & zh); - if (r < 0) - r += 0x100000000; - return r; -} - -function maj64_lo(xh, xl, yh, yl, zh, zl) { - var r = (xl & yl) ^ (xl & zl) ^ (yl & zl); - if (r < 0) - r += 0x100000000; - return r; -} - -function s0_512_hi(xh, xl) { - var c0_hi = rotr64_hi$1(xh, xl, 28); - var c1_hi = rotr64_hi$1(xl, xh, 2); // 34 - var c2_hi = rotr64_hi$1(xl, xh, 7); // 39 - - var r = c0_hi ^ c1_hi ^ c2_hi; - if (r < 0) - r += 0x100000000; - return r; -} - -function s0_512_lo(xh, xl) { - var c0_lo = rotr64_lo$1(xh, xl, 28); - var c1_lo = rotr64_lo$1(xl, xh, 2); // 34 - var c2_lo = rotr64_lo$1(xl, xh, 7); // 39 - - var r = c0_lo ^ c1_lo ^ c2_lo; - if (r < 0) - r += 0x100000000; - return r; -} - -function s1_512_hi(xh, xl) { - var c0_hi = rotr64_hi$1(xh, xl, 14); - var c1_hi = rotr64_hi$1(xh, xl, 18); - var c2_hi = rotr64_hi$1(xl, xh, 9); // 41 - - var r = c0_hi ^ c1_hi ^ c2_hi; - if (r < 0) - r += 0x100000000; - return r; -} - -function s1_512_lo(xh, xl) { - var c0_lo = rotr64_lo$1(xh, xl, 14); - var c1_lo = rotr64_lo$1(xh, xl, 18); - var c2_lo = rotr64_lo$1(xl, xh, 9); // 41 - - var r = c0_lo ^ c1_lo ^ c2_lo; - if (r < 0) - r += 0x100000000; - return r; -} - -function g0_512_hi(xh, xl) { - var c0_hi = rotr64_hi$1(xh, xl, 1); - var c1_hi = rotr64_hi$1(xh, xl, 8); - var c2_hi = shr64_hi$1(xh, xl, 7); - - var r = c0_hi ^ c1_hi ^ c2_hi; - if (r < 0) - r += 0x100000000; - return r; -} - -function g0_512_lo(xh, xl) { - var c0_lo = rotr64_lo$1(xh, xl, 1); - var c1_lo = rotr64_lo$1(xh, xl, 8); - var c2_lo = shr64_lo$1(xh, xl, 7); - - var r = c0_lo ^ c1_lo ^ c2_lo; - if (r < 0) - r += 0x100000000; - return r; -} - -function g1_512_hi(xh, xl) { - var c0_hi = rotr64_hi$1(xh, xl, 19); - var c1_hi = rotr64_hi$1(xl, xh, 29); // 61 - var c2_hi = shr64_hi$1(xh, xl, 6); - - var r = c0_hi ^ c1_hi ^ c2_hi; - if (r < 0) - r += 0x100000000; - return r; -} - -function g1_512_lo(xh, xl) { - var c0_lo = rotr64_lo$1(xh, xl, 19); - var c1_lo = rotr64_lo$1(xl, xh, 29); // 61 - var c2_lo = shr64_lo$1(xh, xl, 6); - - var r = c0_lo ^ c1_lo ^ c2_lo; - if (r < 0) - r += 0x100000000; - return r; -} - -function SHA384() { - if (!(this instanceof SHA384)) - return new SHA384(); - - _512.call(this); - this.h = [ - 0xcbbb9d5d, 0xc1059ed8, - 0x629a292a, 0x367cd507, - 0x9159015a, 0x3070dd17, - 0x152fecd8, 0xf70e5939, - 0x67332667, 0xffc00b31, - 0x8eb44a87, 0x68581511, - 0xdb0c2e0d, 0x64f98fa7, - 0x47b5481d, 0xbefa4fa4 ]; -} -utils.inherits(SHA384, _512); -var _384 = SHA384; - -SHA384.blockSize = 1024; -SHA384.outSize = 384; -SHA384.hmacStrength = 192; -SHA384.padLength = 128; - -SHA384.prototype._digest = function digest(enc) { - if (enc === 'hex') - return utils.toHex32(this.h.slice(0, 12), 'big'); - else - return utils.split32(this.h.slice(0, 12), 'big'); -}; - -var rotl32$1 = utils.rotl32; -var sum32$2 = utils.sum32; -var sum32_3$1 = utils.sum32_3; -var sum32_4$2 = utils.sum32_4; -var BlockHash$3 = common.BlockHash; - -function RIPEMD160() { - if (!(this instanceof RIPEMD160)) - return new RIPEMD160(); - - BlockHash$3.call(this); - - this.h = [ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 ]; - this.endian = 'little'; -} -utils.inherits(RIPEMD160, BlockHash$3); -var ripemd160 = RIPEMD160; - -RIPEMD160.blockSize = 512; -RIPEMD160.outSize = 160; -RIPEMD160.hmacStrength = 192; -RIPEMD160.padLength = 64; - -RIPEMD160.prototype._update = function update(msg, start) { - var A = this.h[0]; - var B = this.h[1]; - var C = this.h[2]; - var D = this.h[3]; - var E = this.h[4]; - var Ah = A; - var Bh = B; - var Ch = C; - var Dh = D; - var Eh = E; - for (var j = 0; j < 80; j++) { - var T = sum32$2( - rotl32$1( - sum32_4$2(A, f(j, B, C, D), msg[r[j] + start], K(j)), - s[j]), - E); - A = E; - E = D; - D = rotl32$1(C, 10); - C = B; - B = T; - T = sum32$2( - rotl32$1( - sum32_4$2(Ah, f(79 - j, Bh, Ch, Dh), msg[rh[j] + start], Kh(j)), - sh[j]), - Eh); - Ah = Eh; - Eh = Dh; - Dh = rotl32$1(Ch, 10); - Ch = Bh; - Bh = T; - } - T = sum32_3$1(this.h[1], C, Dh); - this.h[1] = sum32_3$1(this.h[2], D, Eh); - this.h[2] = sum32_3$1(this.h[3], E, Ah); - this.h[3] = sum32_3$1(this.h[4], A, Bh); - this.h[4] = sum32_3$1(this.h[0], B, Ch); - this.h[0] = T; -}; - -RIPEMD160.prototype._digest = function digest(enc) { - if (enc === 'hex') - return utils.toHex32(this.h, 'little'); - else - return utils.split32(this.h, 'little'); -}; - -function f(j, x, y, z) { - if (j <= 15) - return x ^ y ^ z; - else if (j <= 31) - return (x & y) | ((~x) & z); - else if (j <= 47) - return (x | (~y)) ^ z; - else if (j <= 63) - return (x & z) | (y & (~z)); - else - return x ^ (y | (~z)); -} - -function K(j) { - if (j <= 15) - return 0x00000000; - else if (j <= 31) - return 0x5a827999; - else if (j <= 47) - return 0x6ed9eba1; - else if (j <= 63) - return 0x8f1bbcdc; - else - return 0xa953fd4e; -} - -function Kh(j) { - if (j <= 15) - return 0x50a28be6; - else if (j <= 31) - return 0x5c4dd124; - else if (j <= 47) - return 0x6d703ef3; - else if (j <= 63) - return 0x7a6d76e9; - else - return 0x00000000; -} - -var r = [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, - 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, - 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, - 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 -]; - -var rh = [ - 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, - 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, - 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, - 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, - 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 -]; - -var s = [ - 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, - 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, - 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, - 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, - 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 -]; - -var sh = [ - 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, - 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, - 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, - 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, - 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 -]; - -var ripemd = { - ripemd160: ripemd160 -}; - -/** - * A fast MD5 JavaScript implementation - * Copyright (c) 2012 Joseph Myers - * http://www.myersdaily.org/joseph/javascript/md5-text.html - * - * Permission to use, copy, modify, and distribute this software - * and its documentation for any purposes and without - * fee is hereby granted provided that this copyright notice - * appears in all copies. - * - * Of course, this soft is provided "as is" without express or implied - * warranty of any kind. - */ - -// MD5 Digest -async function md5(entree) { - const digest = md51(util.uint8ArrayToString(entree)); - return util.hexToUint8Array(hex(digest)); -} - -function md5cycle(x, k) { - let a = x[0]; - let b = x[1]; - let c = x[2]; - let d = x[3]; - - a = ff(a, b, c, d, k[0], 7, -680876936); - d = ff(d, a, b, c, k[1], 12, -389564586); - c = ff(c, d, a, b, k[2], 17, 606105819); - b = ff(b, c, d, a, k[3], 22, -1044525330); - a = ff(a, b, c, d, k[4], 7, -176418897); - d = ff(d, a, b, c, k[5], 12, 1200080426); - c = ff(c, d, a, b, k[6], 17, -1473231341); - b = ff(b, c, d, a, k[7], 22, -45705983); - a = ff(a, b, c, d, k[8], 7, 1770035416); - d = ff(d, a, b, c, k[9], 12, -1958414417); - c = ff(c, d, a, b, k[10], 17, -42063); - b = ff(b, c, d, a, k[11], 22, -1990404162); - a = ff(a, b, c, d, k[12], 7, 1804603682); - d = ff(d, a, b, c, k[13], 12, -40341101); - c = ff(c, d, a, b, k[14], 17, -1502002290); - b = ff(b, c, d, a, k[15], 22, 1236535329); - - a = gg(a, b, c, d, k[1], 5, -165796510); - d = gg(d, a, b, c, k[6], 9, -1069501632); - c = gg(c, d, a, b, k[11], 14, 643717713); - b = gg(b, c, d, a, k[0], 20, -373897302); - a = gg(a, b, c, d, k[5], 5, -701558691); - d = gg(d, a, b, c, k[10], 9, 38016083); - c = gg(c, d, a, b, k[15], 14, -660478335); - b = gg(b, c, d, a, k[4], 20, -405537848); - a = gg(a, b, c, d, k[9], 5, 568446438); - d = gg(d, a, b, c, k[14], 9, -1019803690); - c = gg(c, d, a, b, k[3], 14, -187363961); - b = gg(b, c, d, a, k[8], 20, 1163531501); - a = gg(a, b, c, d, k[13], 5, -1444681467); - d = gg(d, a, b, c, k[2], 9, -51403784); - c = gg(c, d, a, b, k[7], 14, 1735328473); - b = gg(b, c, d, a, k[12], 20, -1926607734); - - a = hh(a, b, c, d, k[5], 4, -378558); - d = hh(d, a, b, c, k[8], 11, -2022574463); - c = hh(c, d, a, b, k[11], 16, 1839030562); - b = hh(b, c, d, a, k[14], 23, -35309556); - a = hh(a, b, c, d, k[1], 4, -1530992060); - d = hh(d, a, b, c, k[4], 11, 1272893353); - c = hh(c, d, a, b, k[7], 16, -155497632); - b = hh(b, c, d, a, k[10], 23, -1094730640); - a = hh(a, b, c, d, k[13], 4, 681279174); - d = hh(d, a, b, c, k[0], 11, -358537222); - c = hh(c, d, a, b, k[3], 16, -722521979); - b = hh(b, c, d, a, k[6], 23, 76029189); - a = hh(a, b, c, d, k[9], 4, -640364487); - d = hh(d, a, b, c, k[12], 11, -421815835); - c = hh(c, d, a, b, k[15], 16, 530742520); - b = hh(b, c, d, a, k[2], 23, -995338651); - - a = ii(a, b, c, d, k[0], 6, -198630844); - d = ii(d, a, b, c, k[7], 10, 1126891415); - c = ii(c, d, a, b, k[14], 15, -1416354905); - b = ii(b, c, d, a, k[5], 21, -57434055); - a = ii(a, b, c, d, k[12], 6, 1700485571); - d = ii(d, a, b, c, k[3], 10, -1894986606); - c = ii(c, d, a, b, k[10], 15, -1051523); - b = ii(b, c, d, a, k[1], 21, -2054922799); - a = ii(a, b, c, d, k[8], 6, 1873313359); - d = ii(d, a, b, c, k[15], 10, -30611744); - c = ii(c, d, a, b, k[6], 15, -1560198380); - b = ii(b, c, d, a, k[13], 21, 1309151649); - a = ii(a, b, c, d, k[4], 6, -145523070); - d = ii(d, a, b, c, k[11], 10, -1120210379); - c = ii(c, d, a, b, k[2], 15, 718787259); - b = ii(b, c, d, a, k[9], 21, -343485551); - - x[0] = add32(a, x[0]); - x[1] = add32(b, x[1]); - x[2] = add32(c, x[2]); - x[3] = add32(d, x[3]); -} - -function cmn(q, a, b, x, s, t) { - a = add32(add32(a, q), add32(x, t)); - return add32((a << s) | (a >>> (32 - s)), b); -} - -function ff(a, b, c, d, x, s, t) { - return cmn((b & c) | ((~b) & d), a, b, x, s, t); -} - -function gg(a, b, c, d, x, s, t) { - return cmn((b & d) | (c & (~d)), a, b, x, s, t); -} - -function hh(a, b, c, d, x, s, t) { - return cmn(b ^ c ^ d, a, b, x, s, t); -} - -function ii(a, b, c, d, x, s, t) { - return cmn(c ^ (b | (~d)), a, b, x, s, t); -} - -function md51(s) { - const n = s.length; - const state = [1732584193, -271733879, -1732584194, 271733878]; - let i; - for (i = 64; i <= s.length; i += 64) { - md5cycle(state, md5blk(s.substring(i - 64, i))); - } - s = s.substring(i - 64); - const tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; - for (i = 0; i < s.length; i++) { - tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3); - } - tail[i >> 2] |= 0x80 << ((i % 4) << 3); - if (i > 55) { - md5cycle(state, tail); - for (i = 0; i < 16; i++) { - tail[i] = 0; - } - } - tail[14] = n * 8; - md5cycle(state, tail); - return state; -} - -/* there needs to be support for Unicode here, - * unless we pretend that we can redefine the MD-5 - * algorithm for multi-byte characters (perhaps - * by adding every four 16-bit characters and - * shortening the sum to 32 bits). Otherwise - * I suggest performing MD-5 as if every character - * was two bytes--e.g., 0040 0025 = @%--but then - * how will an ordinary MD-5 sum be matched? - * There is no way to standardize text to something - * like UTF-8 before transformation; speed cost is - * utterly prohibitive. The JavaScript standard - * itself needs to look at this: it should start - * providing access to strings as preformed UTF-8 - * 8-bit unsigned value arrays. - */ -function md5blk(s) { /* I figured global was faster. */ - const md5blks = []; - let i; /* Andy King said do it this way. */ - for (i = 0; i < 64; i += 4) { - md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << - 24); - } - return md5blks; -} - -const hex_chr = '0123456789abcdef'.split(''); - -function rhex(n) { - let s = ''; - let j = 0; - for (; j < 4; j++) { - s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F]; - } - return s; -} - -function hex(x) { - for (let i = 0; i < x.length; i++) { - x[i] = rhex(x[i]); - } - return x.join(''); -} - -/* this function is much faster, -so if possible we use it. Some IEs -are the only ones I know of that -need the idiotic second function, -generated by an if clause. */ - -function add32(a, b) { - return (a + b) & 0xFFFFFFFF; -} - -/** - * @fileoverview Provides an interface to hashing functions available in Node.js or external libraries. - * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} - * @see {@link https://github.com/indutny/hash.js|hash.js} - * @module crypto/hash - * @private - */ - -const webCrypto = util.getWebCrypto(); -const nodeCrypto = util.getNodeCrypto(); - -function nodeHash(type) { - return async function (data) { - const shasum = nodeCrypto.createHash(type); - return transform(data, value => { - shasum.update(value); - }, () => new Uint8Array(shasum.digest())); - }; -} - -function hashjsHash(hash, webCryptoHash) { - return async function(data, config = defaultConfig) { - if (isArrayStream(data)) { - data = await readToEnd(data); - } - if (!util.isStream(data) && webCrypto && webCryptoHash && data.length >= config.minBytesForWebCrypto) { - return new Uint8Array(await webCrypto.digest(webCryptoHash, data)); - } - const hashInstance = hash(); - return transform(data, value => { - hashInstance.update(value); - }, () => new Uint8Array(hashInstance.digest())); - }; -} - -function asmcryptoHash(hash, webCryptoHash) { - return async function(data, config = defaultConfig) { - if (isArrayStream(data)) { - data = await readToEnd(data); - } - if (util.isStream(data)) { - const hashInstance = new hash(); - return transform(data, value => { - hashInstance.process(value); - }, () => hashInstance.finish().result); - } else if (webCrypto && webCryptoHash && data.length >= config.minBytesForWebCrypto) { - return new Uint8Array(await webCrypto.digest(webCryptoHash, data)); - } else { - return hash.bytes(data); - } - }; -} - -let hashFunctions; -if (nodeCrypto) { // Use Node native crypto for all hash functions - hashFunctions = { - md5: nodeHash('md5'), - sha1: nodeHash('sha1'), - sha224: nodeHash('sha224'), - sha256: nodeHash('sha256'), - sha384: nodeHash('sha384'), - sha512: nodeHash('sha512'), - ripemd: nodeHash('ripemd160') - }; -} else { // Use JS fallbacks - hashFunctions = { - md5: md5, - sha1: asmcryptoHash(Sha1, (!navigator.userAgent || navigator.userAgent.indexOf('Edge') === -1) && 'SHA-1'), - sha224: hashjsHash(_224), - sha256: asmcryptoHash(Sha256, 'SHA-256'), - sha384: hashjsHash(_384, 'SHA-384'), - sha512: hashjsHash(_512, 'SHA-512'), // asmcrypto sha512 is huge. - ripemd: hashjsHash(ripemd160) - }; -} - -var hash = { - - /** @see module:md5 */ - md5: hashFunctions.md5, - /** @see asmCrypto */ - sha1: hashFunctions.sha1, - /** @see hash.js */ - sha224: hashFunctions.sha224, - /** @see asmCrypto */ - sha256: hashFunctions.sha256, - /** @see hash.js */ - sha384: hashFunctions.sha384, - /** @see asmCrypto */ - sha512: hashFunctions.sha512, - /** @see hash.js */ - ripemd: hashFunctions.ripemd, - - /** - * Create a hash on the specified data using the specified algorithm - * @param {module:enums.hash} algo - Hash algorithm type (see {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}) - * @param {Uint8Array} data - Data to be hashed - * @returns {Promise} Hash value. - */ - digest: function(algo, data) { - switch (algo) { - case enums.hash.md5: - return this.md5(data); - case enums.hash.sha1: - return this.sha1(data); - case enums.hash.ripemd: - return this.ripemd(data); - case enums.hash.sha256: - return this.sha256(data); - case enums.hash.sha384: - return this.sha384(data); - case enums.hash.sha512: - return this.sha512(data); - case enums.hash.sha224: - return this.sha224(data); - default: - throw new Error('Invalid hash function.'); - } - }, - - /** - * Returns the hash size in bytes of the specified hash algorithm type - * @param {module:enums.hash} algo - Hash algorithm type (See {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}) - * @returns {Integer} Size in bytes of the resulting hash. - */ - getHashByteLength: function(algo) { - switch (algo) { - case enums.hash.md5: - return 16; - case enums.hash.sha1: - case enums.hash.ripemd: - return 20; - case enums.hash.sha256: - return 32; - case enums.hash.sha384: - return 48; - case enums.hash.sha512: - return 64; - case enums.hash.sha224: - return 28; - default: - throw new Error('Invalid hash algorithm.'); - } - } -}; - -class AES_CFB { - static encrypt(data, key, iv) { - return new AES_CFB(key, iv).encrypt(data); - } - static decrypt(data, key, iv) { - return new AES_CFB(key, iv).decrypt(data); - } - constructor(key, iv, aes) { - this.aes = aes ? aes : new AES(key, iv, true, 'CFB'); - delete this.aes.padding; - } - encrypt(data) { - const r1 = this.aes.AES_Encrypt_process(data); - const r2 = this.aes.AES_Encrypt_finish(); - return joinBytes(r1, r2); - } - decrypt(data) { - const r1 = this.aes.AES_Decrypt_process(data); - const r2 = this.aes.AES_Decrypt_finish(); - return joinBytes(r1, r2); - } -} - -// Modified by ProtonTech AG - -const webCrypto$1 = util.getWebCrypto(); -const nodeCrypto$1 = util.getNodeCrypto(); - -const knownAlgos = nodeCrypto$1 ? nodeCrypto$1.getCiphers() : []; -const nodeAlgos = { - idea: knownAlgos.includes('idea-cfb') ? 'idea-cfb' : undefined, /* Unused, not implemented */ - tripledes: knownAlgos.includes('des-ede3-cfb') ? 'des-ede3-cfb' : undefined, - cast5: knownAlgos.includes('cast5-cfb') ? 'cast5-cfb' : undefined, - blowfish: knownAlgos.includes('bf-cfb') ? 'bf-cfb' : undefined, - aes128: knownAlgos.includes('aes-128-cfb') ? 'aes-128-cfb' : undefined, - aes192: knownAlgos.includes('aes-192-cfb') ? 'aes-192-cfb' : undefined, - aes256: knownAlgos.includes('aes-256-cfb') ? 'aes-256-cfb' : undefined - /* twofish is not implemented in OpenSSL */ -}; - -/** - * CFB encryption - * @param {enums.symmetric} algo - block cipher algorithm - * @param {Uint8Array} key - * @param {MaybeStream} plaintext - * @param {Uint8Array} iv - * @param {Object} config - full configuration, defaults to openpgp.config - * @returns MaybeStream - */ -async function encrypt(algo, key, plaintext, iv, config) { - const algoName = enums.read(enums.symmetric, algo); - if (util.getNodeCrypto() && nodeAlgos[algoName]) { // Node crypto library. - return nodeEncrypt(algo, key, plaintext, iv); - } - if (algoName.substr(0, 3) === 'aes') { - return aesEncrypt(algo, key, plaintext, iv, config); - } - - const cipherfn = new cipher[algoName](key); - const block_size = cipherfn.blockSize; - - const blockc = iv.slice(); - let pt = new Uint8Array(); - const process = chunk => { - if (chunk) { - pt = util.concatUint8Array([pt, chunk]); - } - const ciphertext = new Uint8Array(pt.length); - let i; - let j = 0; - while (chunk ? pt.length >= block_size : pt.length) { - const encblock = cipherfn.encrypt(blockc); - for (i = 0; i < block_size; i++) { - blockc[i] = pt[i] ^ encblock[i]; - ciphertext[j++] = blockc[i]; - } - pt = pt.subarray(block_size); - } - return ciphertext.subarray(0, j); - }; - return transform(plaintext, process, process); -} - -/** - * CFB decryption - * @param {enums.symmetric} algo - block cipher algorithm - * @param {Uint8Array} key - * @param {MaybeStream} ciphertext - * @param {Uint8Array} iv - * @returns MaybeStream - */ -async function decrypt(algo, key, ciphertext, iv) { - const algoName = enums.read(enums.symmetric, algo); - if (util.getNodeCrypto() && nodeAlgos[algoName]) { // Node crypto library. - return nodeDecrypt(algo, key, ciphertext, iv); - } - if (algoName.substr(0, 3) === 'aes') { - return aesDecrypt(algo, key, ciphertext, iv); - } - - const cipherfn = new cipher[algoName](key); - const block_size = cipherfn.blockSize; - - let blockp = iv; - let ct = new Uint8Array(); - const process = chunk => { - if (chunk) { - ct = util.concatUint8Array([ct, chunk]); - } - const plaintext = new Uint8Array(ct.length); - let i; - let j = 0; - while (chunk ? ct.length >= block_size : ct.length) { - const decblock = cipherfn.encrypt(blockp); - blockp = ct; - for (i = 0; i < block_size; i++) { - plaintext[j++] = blockp[i] ^ decblock[i]; - } - ct = ct.subarray(block_size); - } - return plaintext.subarray(0, j); - }; - return transform(ciphertext, process, process); -} - -function aesEncrypt(algo, key, pt, iv, config) { - if ( - util.getWebCrypto() && - key.length !== 24 && // Chrome doesn't support 192 bit keys, see https://www.chromium.org/blink/webcrypto#TOC-AES-support - !util.isStream(pt) && - pt.length >= 3000 * config.minBytesForWebCrypto // Default to a 3MB minimum. Chrome is pretty slow for small messages, see: https://bugs.chromium.org/p/chromium/issues/detail?id=701188#c2 - ) { // Web Crypto - return webEncrypt(algo, key, pt, iv); - } - // asm.js fallback - const cfb = new AES_CFB(key, iv); - return transform(pt, value => cfb.aes.AES_Encrypt_process(value), () => cfb.aes.AES_Encrypt_finish()); -} - -function aesDecrypt(algo, key, ct, iv) { - if (util.isStream(ct)) { - const cfb = new AES_CFB(key, iv); - return transform(ct, value => cfb.aes.AES_Decrypt_process(value), () => cfb.aes.AES_Decrypt_finish()); - } - return AES_CFB.decrypt(ct, key, iv); -} - -function xorMut(a, b) { - for (let i = 0; i < a.length; i++) { - a[i] = a[i] ^ b[i]; - } -} - -async function webEncrypt(algo, key, pt, iv) { - const ALGO = 'AES-CBC'; - const _key = await webCrypto$1.importKey('raw', key, { name: ALGO }, false, ['encrypt']); - const { blockSize } = crypto.getCipher(algo); - const cbc_pt = util.concatUint8Array([new Uint8Array(blockSize), pt]); - const ct = new Uint8Array(await webCrypto$1.encrypt({ name: ALGO, iv }, _key, cbc_pt)).subarray(0, pt.length); - xorMut(ct, pt); - return ct; -} - -function nodeEncrypt(algo, key, pt, iv) { - const algoName = enums.read(enums.symmetric, algo); - const cipherObj = new nodeCrypto$1.createCipheriv(nodeAlgos[algoName], key, iv); - return transform(pt, value => new Uint8Array(cipherObj.update(value))); -} - -function nodeDecrypt(algo, key, ct, iv) { - const algoName = enums.read(enums.symmetric, algo); - const decipherObj = new nodeCrypto$1.createDecipheriv(nodeAlgos[algoName], key, iv); - return transform(ct, value => new Uint8Array(decipherObj.update(value))); -} - -var cfb = /*#__PURE__*/Object.freeze({ - __proto__: null, - encrypt: encrypt, - decrypt: decrypt -}); - -class AES_CTR { - static encrypt(data, key, nonce) { - return new AES_CTR(key, nonce).encrypt(data); - } - static decrypt(data, key, nonce) { - return new AES_CTR(key, nonce).encrypt(data); - } - constructor(key, nonce, aes) { - this.aes = aes ? aes : new AES(key, undefined, false, 'CTR'); - delete this.aes.padding; - this.AES_CTR_set_options(nonce); - } - encrypt(data) { - const r1 = this.aes.AES_Encrypt_process(data); - const r2 = this.aes.AES_Encrypt_finish(); - return joinBytes(r1, r2); - } - decrypt(data) { - const r1 = this.aes.AES_Encrypt_process(data); - const r2 = this.aes.AES_Encrypt_finish(); - return joinBytes(r1, r2); - } - AES_CTR_set_options(nonce, counter, size) { - let { asm } = this.aes.acquire_asm(); - if (size !== undefined) { - if (size < 8 || size > 48) - throw new IllegalArgumentError('illegal counter size'); - let mask = Math.pow(2, size) - 1; - asm.set_mask(0, 0, (mask / 0x100000000) | 0, mask | 0); - } - else { - size = 48; - asm.set_mask(0, 0, 0xffff, 0xffffffff); - } - if (nonce !== undefined) { - let len = nonce.length; - if (!len || len > 16) - throw new IllegalArgumentError('illegal nonce size'); - let view = new DataView(new ArrayBuffer(16)); - new Uint8Array(view.buffer).set(nonce); - asm.set_nonce(view.getUint32(0), view.getUint32(4), view.getUint32(8), view.getUint32(12)); - } - else { - throw new Error('nonce is required'); - } - if (counter !== undefined) { - if (counter < 0 || counter >= Math.pow(2, size)) - throw new IllegalArgumentError('illegal counter value'); - asm.set_counter(0, 0, (counter / 0x100000000) | 0, counter | 0); - } - } -} - -class AES_CBC { - static encrypt(data, key, padding = true, iv) { - return new AES_CBC(key, iv, padding).encrypt(data); - } - static decrypt(data, key, padding = true, iv) { - return new AES_CBC(key, iv, padding).decrypt(data); - } - constructor(key, iv, padding = true, aes) { - this.aes = aes ? aes : new AES(key, iv, padding, 'CBC'); - } - encrypt(data) { - const r1 = this.aes.AES_Encrypt_process(data); - const r2 = this.aes.AES_Encrypt_finish(); - return joinBytes(r1, r2); - } - decrypt(data) { - const r1 = this.aes.AES_Decrypt_process(data); - const r2 = this.aes.AES_Decrypt_finish(); - return joinBytes(r1, r2); - } -} - -/** - * @fileoverview This module implements AES-CMAC on top of - * native AES-CBC using either the WebCrypto API or Node.js' crypto API. - * @module crypto/cmac - * @private - */ - -const webCrypto$2 = util.getWebCrypto(); -const nodeCrypto$2 = util.getNodeCrypto(); - - -/** - * This implementation of CMAC is based on the description of OMAC in - * http://web.cs.ucdavis.edu/~rogaway/papers/eax.pdf. As per that - * document: - * - * We have made a small modification to the OMAC algorithm as it was - * originally presented, changing one of its two constants. - * Specifically, the constant 4 at line 85 was the constant 1/2 (the - * multiplicative inverse of 2) in the original definition of OMAC [14]. - * The OMAC authors indicate that they will promulgate this modification - * [15], which slightly simplifies implementations. - */ - -const blockLength = 16; - - -/** - * xor `padding` into the end of `data`. This function implements "the - * operation xor→ [which] xors the shorter string into the end of longer - * one". Since data is always as least as long as padding, we can - * simplify the implementation. - * @param {Uint8Array} data - * @param {Uint8Array} padding - */ -function rightXORMut(data, padding) { - const offset = data.length - blockLength; - for (let i = 0; i < blockLength; i++) { - data[i + offset] ^= padding[i]; - } - return data; -} - -function pad(data, padding, padding2) { - // if |M| in {n, 2n, 3n, ...} - if (data.length && data.length % blockLength === 0) { - // then return M xor→ B, - return rightXORMut(data, padding); - } - // else return (M || 10^(n−1−(|M| mod n))) xor→ P - const padded = new Uint8Array(data.length + (blockLength - data.length % blockLength)); - padded.set(data); - padded[data.length] = 0b10000000; - return rightXORMut(padded, padding2); -} - -const zeroBlock = new Uint8Array(blockLength); - -async function CMAC(key) { - const cbc = await CBC(key); - - // L ← E_K(0^n); B ← 2L; P ← 4L - const padding = util.double(await cbc(zeroBlock)); - const padding2 = util.double(padding); - - return async function(data) { - // return CBC_K(pad(M; B, P)) - return (await cbc(pad(data, padding, padding2))).subarray(-blockLength); - }; -} - -async function CBC(key) { - if (util.getWebCrypto() && key.length !== 24) { // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support - key = await webCrypto$2.importKey('raw', key, { name: 'AES-CBC', length: key.length * 8 }, false, ['encrypt']); - return async function(pt) { - const ct = await webCrypto$2.encrypt({ name: 'AES-CBC', iv: zeroBlock, length: blockLength * 8 }, key, pt); - return new Uint8Array(ct).subarray(0, ct.byteLength - blockLength); - }; - } - if (util.getNodeCrypto()) { // Node crypto library - return async function(pt) { - const en = new nodeCrypto$2.createCipheriv('aes-' + (key.length * 8) + '-cbc', key, zeroBlock); - const ct = en.update(pt); - return new Uint8Array(ct); - }; - } - // asm.js fallback - return async function(pt) { - return AES_CBC.encrypt(pt, key, false, zeroBlock); - }; -} - -// OpenPGP.js - An OpenPGP implementation in javascript - -const webCrypto$3 = util.getWebCrypto(); -const nodeCrypto$3 = util.getNodeCrypto(); -const Buffer$1 = util.getNodeBuffer(); - - -const blockLength$1 = 16; -const ivLength = blockLength$1; -const tagLength = blockLength$1; - -const zero = new Uint8Array(blockLength$1); -const one = new Uint8Array(blockLength$1); one[blockLength$1 - 1] = 1; -const two = new Uint8Array(blockLength$1); two[blockLength$1 - 1] = 2; - -async function OMAC(key) { - const cmac = await CMAC(key); - return function(t, message) { - return cmac(util.concatUint8Array([t, message])); - }; -} - -async function CTR(key) { - if ( - util.getWebCrypto() && - key.length !== 24 && // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support - (!navigator.userAgent || navigator.userAgent.indexOf('Edge') === -1) - ) { - key = await webCrypto$3.importKey('raw', key, { name: 'AES-CTR', length: key.length * 8 }, false, ['encrypt']); - return async function(pt, iv) { - const ct = await webCrypto$3.encrypt({ name: 'AES-CTR', counter: iv, length: blockLength$1 * 8 }, key, pt); - return new Uint8Array(ct); - }; - } - if (util.getNodeCrypto()) { // Node crypto library - return async function(pt, iv) { - const en = new nodeCrypto$3.createCipheriv('aes-' + (key.length * 8) + '-ctr', key, iv); - const ct = Buffer$1.concat([en.update(pt), en.final()]); - return new Uint8Array(ct); - }; - } - // asm.js fallback - return async function(pt, iv) { - return AES_CTR.encrypt(pt, key, iv); - }; -} - - -/** - * Class to en/decrypt using EAX mode. - * @param {enums.symmetric} cipher - The symmetric cipher algorithm to use - * @param {Uint8Array} key - The encryption key - */ -async function EAX(cipher, key) { - if (cipher !== enums.symmetric.aes128 && - cipher !== enums.symmetric.aes192 && - cipher !== enums.symmetric.aes256) { - throw new Error('EAX mode supports only AES cipher'); - } - - const [ - omac, - ctr - ] = await Promise.all([ - OMAC(key), - CTR(key) - ]); - - return { - /** - * Encrypt plaintext input. - * @param {Uint8Array} plaintext - The cleartext input to be encrypted - * @param {Uint8Array} nonce - The nonce (16 bytes) - * @param {Uint8Array} adata - Associated data to sign - * @returns {Promise} The ciphertext output. - */ - encrypt: async function(plaintext, nonce, adata) { - const [ - omacNonce, - omacAdata - ] = await Promise.all([ - omac(zero, nonce), - omac(one, adata) - ]); - const ciphered = await ctr(plaintext, omacNonce); - const omacCiphered = await omac(two, ciphered); - const tag = omacCiphered; // Assumes that omac(*).length === tagLength. - for (let i = 0; i < tagLength; i++) { - tag[i] ^= omacAdata[i] ^ omacNonce[i]; - } - return util.concatUint8Array([ciphered, tag]); - }, - - /** - * Decrypt ciphertext input. - * @param {Uint8Array} ciphertext - The ciphertext input to be decrypted - * @param {Uint8Array} nonce - The nonce (16 bytes) - * @param {Uint8Array} adata - Associated data to verify - * @returns {Promise} The plaintext output. - */ - decrypt: async function(ciphertext, nonce, adata) { - if (ciphertext.length < tagLength) throw new Error('Invalid EAX ciphertext'); - const ciphered = ciphertext.subarray(0, -tagLength); - const ctTag = ciphertext.subarray(-tagLength); - const [ - omacNonce, - omacAdata, - omacCiphered - ] = await Promise.all([ - omac(zero, nonce), - omac(one, adata), - omac(two, ciphered) - ]); - const tag = omacCiphered; // Assumes that omac(*).length === tagLength. - for (let i = 0; i < tagLength; i++) { - tag[i] ^= omacAdata[i] ^ omacNonce[i]; - } - if (!util.equalsUint8Array(ctTag, tag)) throw new Error('Authentication tag mismatch'); - const plaintext = await ctr(ciphered, omacNonce); - return plaintext; - } - }; -} - - -/** - * Get EAX nonce as defined by {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.1|RFC4880bis-04, section 5.16.1}. - * @param {Uint8Array} iv - The initialization vector (16 bytes) - * @param {Uint8Array} chunkIndex - The chunk index (8 bytes) - */ -EAX.getNonce = function(iv, chunkIndex) { - const nonce = iv.slice(); - for (let i = 0; i < chunkIndex.length; i++) { - nonce[8 + i] ^= chunkIndex[i]; - } - return nonce; -}; - -EAX.blockLength = blockLength$1; -EAX.ivLength = ivLength; -EAX.tagLength = tagLength; - -// OpenPGP.js - An OpenPGP implementation in javascript - -const blockLength$2 = 16; -const ivLength$1 = 15; - -// https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.2: -// While OCB [RFC7253] allows the authentication tag length to be of any -// number up to 128 bits long, this document requires a fixed -// authentication tag length of 128 bits (16 octets) for simplicity. -const tagLength$1 = 16; - - -function ntz(n) { - let ntz = 0; - for (let i = 1; (n & i) === 0; i <<= 1) { - ntz++; - } - return ntz; -} - -function xorMut$1(S, T) { - for (let i = 0; i < S.length; i++) { - S[i] ^= T[i]; - } - return S; -} - -function xor(S, T) { - return xorMut$1(S.slice(), T); -} - -const zeroBlock$1 = new Uint8Array(blockLength$2); -const one$1 = new Uint8Array([1]); - -/** - * Class to en/decrypt using OCB mode. - * @param {enums.symmetric} cipher - The symmetric cipher algorithm to use - * @param {Uint8Array} key - The encryption key - */ -async function OCB(cipher$1, key) { - - let maxNtz = 0; - let encipher; - let decipher; - let mask; - - constructKeyVariables(cipher$1, key); - - function constructKeyVariables(cipher$1, key) { - const cipherName = enums.read(enums.symmetric, cipher$1); - const aes = new cipher[cipherName](key); - encipher = aes.encrypt.bind(aes); - decipher = aes.decrypt.bind(aes); - - const mask_x = encipher(zeroBlock$1); - const mask_$ = util.double(mask_x); - mask = []; - mask[0] = util.double(mask_$); - - - mask.x = mask_x; - mask.$ = mask_$; - } - - function extendKeyVariables(text, adata) { - const newMaxNtz = util.nbits(Math.max(text.length, adata.length) / blockLength$2 | 0) - 1; - for (let i = maxNtz + 1; i <= newMaxNtz; i++) { - mask[i] = util.double(mask[i - 1]); - } - maxNtz = newMaxNtz; - } - - function hash(adata) { - if (!adata.length) { - // Fast path - return zeroBlock$1; - } - - // - // Consider A as a sequence of 128-bit blocks - // - const m = adata.length / blockLength$2 | 0; - - const offset = new Uint8Array(blockLength$2); - const sum = new Uint8Array(blockLength$2); - for (let i = 0; i < m; i++) { - xorMut$1(offset, mask[ntz(i + 1)]); - xorMut$1(sum, encipher(xor(offset, adata))); - adata = adata.subarray(blockLength$2); - } - - // - // Process any final partial block; compute final hash value - // - if (adata.length) { - xorMut$1(offset, mask.x); - - const cipherInput = new Uint8Array(blockLength$2); - cipherInput.set(adata, 0); - cipherInput[adata.length] = 0b10000000; - xorMut$1(cipherInput, offset); - - xorMut$1(sum, encipher(cipherInput)); - } - - return sum; - } - - /** - * Encrypt/decrypt data. - * @param {encipher|decipher} fn - Encryption/decryption block cipher function - * @param {Uint8Array} text - The cleartext or ciphertext (without tag) input - * @param {Uint8Array} nonce - The nonce (15 bytes) - * @param {Uint8Array} adata - Associated data to sign - * @returns {Promise} The ciphertext or plaintext output, with tag appended in both cases. - */ - function crypt(fn, text, nonce, adata) { - // - // Consider P as a sequence of 128-bit blocks - // - const m = text.length / blockLength$2 | 0; - - // - // Key-dependent variables - // - extendKeyVariables(text, adata); - - // - // Nonce-dependent and per-encryption variables - // - // Nonce = num2str(TAGLEN mod 128,7) || zeros(120-bitlen(N)) || 1 || N - // Note: We assume here that tagLength mod 16 == 0. - const paddedNonce = util.concatUint8Array([zeroBlock$1.subarray(0, ivLength$1 - nonce.length), one$1, nonce]); - // bottom = str2num(Nonce[123..128]) - const bottom = paddedNonce[blockLength$2 - 1] & 0b111111; - // Ktop = ENCIPHER(K, Nonce[1..122] || zeros(6)) - paddedNonce[blockLength$2 - 1] &= 0b11000000; - const kTop = encipher(paddedNonce); - // Stretch = Ktop || (Ktop[1..64] xor Ktop[9..72]) - const stretched = util.concatUint8Array([kTop, xor(kTop.subarray(0, 8), kTop.subarray(1, 9))]); - // Offset_0 = Stretch[1+bottom..128+bottom] - const offset = util.shiftRight(stretched.subarray(0 + (bottom >> 3), 17 + (bottom >> 3)), 8 - (bottom & 7)).subarray(1); - // Checksum_0 = zeros(128) - const checksum = new Uint8Array(blockLength$2); - - const ct = new Uint8Array(text.length + tagLength$1); - - // - // Process any whole blocks - // - let i; - let pos = 0; - for (i = 0; i < m; i++) { - // Offset_i = Offset_{i-1} xor L_{ntz(i)} - xorMut$1(offset, mask[ntz(i + 1)]); - // C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) - // P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i) - ct.set(xorMut$1(fn(xor(offset, text)), offset), pos); - // Checksum_i = Checksum_{i-1} xor P_i - xorMut$1(checksum, fn === encipher ? text : ct.subarray(pos)); - - text = text.subarray(blockLength$2); - pos += blockLength$2; - } - - // - // Process any final partial block and compute raw tag - // - if (text.length) { - // Offset_* = Offset_m xor L_* - xorMut$1(offset, mask.x); - // Pad = ENCIPHER(K, Offset_*) - const padding = encipher(offset); - // C_* = P_* xor Pad[1..bitlen(P_*)] - ct.set(xor(text, padding), pos); - - // Checksum_* = Checksum_m xor (P_* || 1 || new Uint8Array(127-bitlen(P_*))) - const xorInput = new Uint8Array(blockLength$2); - xorInput.set(fn === encipher ? text : ct.subarray(pos, -tagLength$1), 0); - xorInput[text.length] = 0b10000000; - xorMut$1(checksum, xorInput); - pos += text.length; - } - // Tag = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) xor HASH(K,A) - const tag = xorMut$1(encipher(xorMut$1(xorMut$1(checksum, offset), mask.$)), hash(adata)); - - // - // Assemble ciphertext - // - // C = C_1 || C_2 || ... || C_m || C_* || Tag[1..TAGLEN] - ct.set(tag, pos); - return ct; - } - - - return { - /** - * Encrypt plaintext input. - * @param {Uint8Array} plaintext - The cleartext input to be encrypted - * @param {Uint8Array} nonce - The nonce (15 bytes) - * @param {Uint8Array} adata - Associated data to sign - * @returns {Promise} The ciphertext output. - */ - encrypt: async function(plaintext, nonce, adata) { - return crypt(encipher, plaintext, nonce, adata); - }, - - /** - * Decrypt ciphertext input. - * @param {Uint8Array} ciphertext - The ciphertext input to be decrypted - * @param {Uint8Array} nonce - The nonce (15 bytes) - * @param {Uint8Array} adata - Associated data to sign - * @returns {Promise} The ciphertext output. - */ - decrypt: async function(ciphertext, nonce, adata) { - if (ciphertext.length < tagLength$1) throw new Error('Invalid OCB ciphertext'); - - const tag = ciphertext.subarray(-tagLength$1); - ciphertext = ciphertext.subarray(0, -tagLength$1); - - const crypted = crypt(decipher, ciphertext, nonce, adata); - // if (Tag[1..TAGLEN] == T) - if (util.equalsUint8Array(tag, crypted.subarray(-tagLength$1))) { - return crypted.subarray(0, -tagLength$1); - } - throw new Error('Authentication tag mismatch'); - } - }; -} - - -/** - * Get OCB nonce as defined by {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.2|RFC4880bis-04, section 5.16.2}. - * @param {Uint8Array} iv - The initialization vector (15 bytes) - * @param {Uint8Array} chunkIndex - The chunk index (8 bytes) - */ -OCB.getNonce = function(iv, chunkIndex) { - const nonce = iv.slice(); - for (let i = 0; i < chunkIndex.length; i++) { - nonce[7 + i] ^= chunkIndex[i]; - } - return nonce; -}; - -OCB.blockLength = blockLength$2; -OCB.ivLength = ivLength$1; -OCB.tagLength = tagLength$1; - -const _AES_GCM_data_maxLength = 68719476704; // 2^36 - 2^5 -class AES_GCM { - constructor(key, nonce, adata, tagSize = 16, aes) { - this.tagSize = tagSize; - this.gamma0 = 0; - this.counter = 1; - this.aes = aes ? aes : new AES(key, undefined, false, 'CTR'); - let { asm, heap } = this.aes.acquire_asm(); - // Init GCM - asm.gcm_init(); - // Tag size - if (this.tagSize < 4 || this.tagSize > 16) - throw new IllegalArgumentError('illegal tagSize value'); - // Nonce - const noncelen = nonce.length || 0; - const noncebuf = new Uint8Array(16); - if (noncelen !== 12) { - this._gcm_mac_process(nonce); - heap[0] = 0; - heap[1] = 0; - heap[2] = 0; - heap[3] = 0; - heap[4] = 0; - heap[5] = 0; - heap[6] = 0; - heap[7] = 0; - heap[8] = 0; - heap[9] = 0; - heap[10] = 0; - heap[11] = noncelen >>> 29; - heap[12] = (noncelen >>> 21) & 255; - heap[13] = (noncelen >>> 13) & 255; - heap[14] = (noncelen >>> 5) & 255; - heap[15] = (noncelen << 3) & 255; - asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16); - asm.get_iv(AES_asm.HEAP_DATA); - asm.set_iv(0, 0, 0, 0); - noncebuf.set(heap.subarray(0, 16)); - } - else { - noncebuf.set(nonce); - noncebuf[15] = 1; - } - const nonceview = new DataView(noncebuf.buffer); - this.gamma0 = nonceview.getUint32(12); - asm.set_nonce(nonceview.getUint32(0), nonceview.getUint32(4), nonceview.getUint32(8), 0); - asm.set_mask(0, 0, 0, 0xffffffff); - // Associated data - if (adata !== undefined) { - if (adata.length > _AES_GCM_data_maxLength) - throw new IllegalArgumentError('illegal adata length'); - if (adata.length) { - this.adata = adata; - this._gcm_mac_process(adata); - } - else { - this.adata = undefined; - } - } - else { - this.adata = undefined; - } - // Counter - if (this.counter < 1 || this.counter > 0xffffffff) - throw new RangeError('counter must be a positive 32-bit integer'); - asm.set_counter(0, 0, 0, (this.gamma0 + this.counter) | 0); - } - static encrypt(cleartext, key, nonce, adata, tagsize) { - return new AES_GCM(key, nonce, adata, tagsize).encrypt(cleartext); - } - static decrypt(ciphertext, key, nonce, adata, tagsize) { - return new AES_GCM(key, nonce, adata, tagsize).decrypt(ciphertext); - } - encrypt(data) { - return this.AES_GCM_encrypt(data); - } - decrypt(data) { - return this.AES_GCM_decrypt(data); - } - AES_GCM_Encrypt_process(data) { - let dpos = 0; - let dlen = data.length || 0; - let { asm, heap } = this.aes.acquire_asm(); - let counter = this.counter; - let pos = this.aes.pos; - let len = this.aes.len; - let rpos = 0; - let rlen = (len + dlen) & -16; - let wlen = 0; - if (((counter - 1) << 4) + len + dlen > _AES_GCM_data_maxLength) - throw new RangeError('counter overflow'); - const result = new Uint8Array(rlen); - while (dlen > 0) { - wlen = _heap_write(heap, pos + len, data, dpos, dlen); - len += wlen; - dpos += wlen; - dlen -= wlen; - wlen = asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, len); - wlen = asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, wlen); - if (wlen) - result.set(heap.subarray(pos, pos + wlen), rpos); - counter += wlen >>> 4; - rpos += wlen; - if (wlen < len) { - pos += wlen; - len -= wlen; - } - else { - pos = 0; - len = 0; - } - } - this.counter = counter; - this.aes.pos = pos; - this.aes.len = len; - return result; - } - AES_GCM_Encrypt_finish() { - let { asm, heap } = this.aes.acquire_asm(); - let counter = this.counter; - let tagSize = this.tagSize; - let adata = this.adata; - let pos = this.aes.pos; - let len = this.aes.len; - const result = new Uint8Array(len + tagSize); - asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, (len + 15) & -16); - if (len) - result.set(heap.subarray(pos, pos + len)); - let i = len; - for (; i & 15; i++) - heap[pos + i] = 0; - asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, i); - const alen = adata !== undefined ? adata.length : 0; - const clen = ((counter - 1) << 4) + len; - heap[0] = 0; - heap[1] = 0; - heap[2] = 0; - heap[3] = alen >>> 29; - heap[4] = alen >>> 21; - heap[5] = (alen >>> 13) & 255; - heap[6] = (alen >>> 5) & 255; - heap[7] = (alen << 3) & 255; - heap[8] = heap[9] = heap[10] = 0; - heap[11] = clen >>> 29; - heap[12] = (clen >>> 21) & 255; - heap[13] = (clen >>> 13) & 255; - heap[14] = (clen >>> 5) & 255; - heap[15] = (clen << 3) & 255; - asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16); - asm.get_iv(AES_asm.HEAP_DATA); - asm.set_counter(0, 0, 0, this.gamma0); - asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16); - result.set(heap.subarray(0, tagSize), len); - this.counter = 1; - this.aes.pos = 0; - this.aes.len = 0; - return result; - } - AES_GCM_Decrypt_process(data) { - let dpos = 0; - let dlen = data.length || 0; - let { asm, heap } = this.aes.acquire_asm(); - let counter = this.counter; - let tagSize = this.tagSize; - let pos = this.aes.pos; - let len = this.aes.len; - let rpos = 0; - let rlen = len + dlen > tagSize ? (len + dlen - tagSize) & -16 : 0; - let tlen = len + dlen - rlen; - let wlen = 0; - if (((counter - 1) << 4) + len + dlen > _AES_GCM_data_maxLength) - throw new RangeError('counter overflow'); - const result = new Uint8Array(rlen); - while (dlen > tlen) { - wlen = _heap_write(heap, pos + len, data, dpos, dlen - tlen); - len += wlen; - dpos += wlen; - dlen -= wlen; - wlen = asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, wlen); - wlen = asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, wlen); - if (wlen) - result.set(heap.subarray(pos, pos + wlen), rpos); - counter += wlen >>> 4; - rpos += wlen; - pos = 0; - len = 0; - } - if (dlen > 0) { - len += _heap_write(heap, 0, data, dpos, dlen); - } - this.counter = counter; - this.aes.pos = pos; - this.aes.len = len; - return result; - } - AES_GCM_Decrypt_finish() { - let { asm, heap } = this.aes.acquire_asm(); - let tagSize = this.tagSize; - let adata = this.adata; - let counter = this.counter; - let pos = this.aes.pos; - let len = this.aes.len; - let rlen = len - tagSize; - if (len < tagSize) - throw new IllegalStateError('authentication tag not found'); - const result = new Uint8Array(rlen); - const atag = new Uint8Array(heap.subarray(pos + rlen, pos + len)); - let i = rlen; - for (; i & 15; i++) - heap[pos + i] = 0; - asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, i); - asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, i); - if (rlen) - result.set(heap.subarray(pos, pos + rlen)); - const alen = adata !== undefined ? adata.length : 0; - const clen = ((counter - 1) << 4) + len - tagSize; - heap[0] = 0; - heap[1] = 0; - heap[2] = 0; - heap[3] = alen >>> 29; - heap[4] = alen >>> 21; - heap[5] = (alen >>> 13) & 255; - heap[6] = (alen >>> 5) & 255; - heap[7] = (alen << 3) & 255; - heap[8] = heap[9] = heap[10] = 0; - heap[11] = clen >>> 29; - heap[12] = (clen >>> 21) & 255; - heap[13] = (clen >>> 13) & 255; - heap[14] = (clen >>> 5) & 255; - heap[15] = (clen << 3) & 255; - asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16); - asm.get_iv(AES_asm.HEAP_DATA); - asm.set_counter(0, 0, 0, this.gamma0); - asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16); - let acheck = 0; - for (let i = 0; i < tagSize; ++i) - acheck |= atag[i] ^ heap[i]; - if (acheck) - throw new SecurityError('data integrity check failed'); - this.counter = 1; - this.aes.pos = 0; - this.aes.len = 0; - return result; - } - AES_GCM_decrypt(data) { - const result1 = this.AES_GCM_Decrypt_process(data); - const result2 = this.AES_GCM_Decrypt_finish(); - const result = new Uint8Array(result1.length + result2.length); - if (result1.length) - result.set(result1); - if (result2.length) - result.set(result2, result1.length); - return result; - } - AES_GCM_encrypt(data) { - const result1 = this.AES_GCM_Encrypt_process(data); - const result2 = this.AES_GCM_Encrypt_finish(); - const result = new Uint8Array(result1.length + result2.length); - if (result1.length) - result.set(result1); - if (result2.length) - result.set(result2, result1.length); - return result; - } - _gcm_mac_process(data) { - let { asm, heap } = this.aes.acquire_asm(); - let dpos = 0; - let dlen = data.length || 0; - let wlen = 0; - while (dlen > 0) { - wlen = _heap_write(heap, 0, data, dpos, dlen); - dpos += wlen; - dlen -= wlen; - while (wlen & 15) - heap[wlen++] = 0; - asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, wlen); - } - } -} - -// OpenPGP.js - An OpenPGP implementation in javascript - -const webCrypto$4 = util.getWebCrypto(); -const nodeCrypto$4 = util.getNodeCrypto(); -const Buffer$2 = util.getNodeBuffer(); - -const blockLength$3 = 16; -const ivLength$2 = 12; // size of the IV in bytes -const tagLength$2 = 16; // size of the tag in bytes -const ALGO = 'AES-GCM'; - -/** - * Class to en/decrypt using GCM mode. - * @param {enums.symmetric} cipher - The symmetric cipher algorithm to use - * @param {Uint8Array} key - The encryption key - */ -async function GCM(cipher, key) { - if (cipher !== enums.symmetric.aes128 && - cipher !== enums.symmetric.aes192 && - cipher !== enums.symmetric.aes256) { - throw new Error('GCM mode supports only AES cipher'); - } - - if (util.getWebCrypto() && key.length !== 24) { // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support - const _key = await webCrypto$4.importKey('raw', key, { name: ALGO }, false, ['encrypt', 'decrypt']); - - return { - encrypt: async function(pt, iv, adata = new Uint8Array()) { - if ( - !pt.length || - // iOS does not support GCM-en/decrypting empty messages - // Also, synchronous en/decryption might be faster in this case. - (!adata.length && navigator.userAgent && navigator.userAgent.indexOf('Edge') !== -1) - // Edge does not support GCM-en/decrypting without ADATA - ) { - return AES_GCM.encrypt(pt, key, iv, adata); - } - const ct = await webCrypto$4.encrypt({ name: ALGO, iv, additionalData: adata, tagLength: tagLength$2 * 8 }, _key, pt); - return new Uint8Array(ct); - }, - - decrypt: async function(ct, iv, adata = new Uint8Array()) { - if ( - ct.length === tagLength$2 || - // iOS does not support GCM-en/decrypting empty messages - // Also, synchronous en/decryption might be faster in this case. - (!adata.length && navigator.userAgent && navigator.userAgent.indexOf('Edge') !== -1) - // Edge does not support GCM-en/decrypting without ADATA - ) { - return AES_GCM.decrypt(ct, key, iv, adata); - } - const pt = await webCrypto$4.decrypt({ name: ALGO, iv, additionalData: adata, tagLength: tagLength$2 * 8 }, _key, ct); - return new Uint8Array(pt); - } - }; - } - - if (util.getNodeCrypto()) { // Node crypto library - return { - encrypt: async function(pt, iv, adata = new Uint8Array()) { - const en = new nodeCrypto$4.createCipheriv('aes-' + (key.length * 8) + '-gcm', key, iv); - en.setAAD(adata); - const ct = Buffer$2.concat([en.update(pt), en.final(), en.getAuthTag()]); // append auth tag to ciphertext - return new Uint8Array(ct); - }, - - decrypt: async function(ct, iv, adata = new Uint8Array()) { - const de = new nodeCrypto$4.createDecipheriv('aes-' + (key.length * 8) + '-gcm', key, iv); - de.setAAD(adata); - de.setAuthTag(ct.slice(ct.length - tagLength$2, ct.length)); // read auth tag at end of ciphertext - const pt = Buffer$2.concat([de.update(ct.slice(0, ct.length - tagLength$2)), de.final()]); - return new Uint8Array(pt); - } - }; - } - - return { - encrypt: async function(pt, iv, adata) { - return AES_GCM.encrypt(pt, key, iv, adata); - }, - - decrypt: async function(ct, iv, adata) { - return AES_GCM.decrypt(ct, key, iv, adata); - } - }; -} - - -/** - * Get GCM nonce. Note: this operation is not defined by the standard. - * A future version of the standard may define GCM mode differently, - * hopefully under a different ID (we use Private/Experimental algorithm - * ID 100) so that we can maintain backwards compatibility. - * @param {Uint8Array} iv - The initialization vector (12 bytes) - * @param {Uint8Array} chunkIndex - The chunk index (8 bytes) - */ -GCM.getNonce = function(iv, chunkIndex) { - const nonce = iv.slice(); - for (let i = 0; i < chunkIndex.length; i++) { - nonce[4 + i] ^= chunkIndex[i]; - } - return nonce; -}; - -GCM.blockLength = blockLength$3; -GCM.ivLength = ivLength$2; -GCM.tagLength = tagLength$2; - -/** - * @fileoverview Cipher modes - * @module crypto/mode - * @private - */ - -var mode = { - /** @see module:crypto/mode/cfb */ - cfb: cfb, - /** @see module:crypto/mode/gcm */ - gcm: GCM, - experimentalGCM: GCM, - /** @see module:crypto/mode/eax */ - eax: EAX, - /** @see module:crypto/mode/ocb */ - ocb: OCB -}; - -var naclFastLight = createCommonjsModule(function (module) { -/*jshint bitwise: false*/ - -(function(nacl) { - -// Ported in 2014 by Dmitry Chestnykh and Devi Mandiri. -// Public domain. -// -// Implementation derived from TweetNaCl version 20140427. -// See for details: http://tweetnacl.cr.yp.to/ - -var gf = function(init) { - var i, r = new Float64Array(16); - if (init) for (i = 0; i < init.length; i++) r[i] = init[i]; - return r; -}; - -// Pluggable, initialized in high-level API below. -var randombytes = function(/* x, n */) { throw new Error('no PRNG'); }; - -var _9 = new Uint8Array(32); _9[0] = 9; - -var gf0 = gf(), - gf1 = gf([1]), - _121665 = gf([0xdb41, 1]), - D = gf([0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203]), - D2 = gf([0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406]), - X = gf([0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169]), - Y = gf([0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666]), - I = gf([0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83]); - -function vn(x, xi, y, yi, n) { - var i,d = 0; - for (i = 0; i < n; i++) d |= x[xi+i]^y[yi+i]; - return (1 & ((d - 1) >>> 8)) - 1; -} - -function crypto_verify_32(x, xi, y, yi) { - return vn(x,xi,y,yi,32); -} - -function set25519(r, a) { - var i; - for (i = 0; i < 16; i++) r[i] = a[i]|0; -} - -function car25519(o) { - var i, v, c = 1; - for (i = 0; i < 16; i++) { - v = o[i] + c + 65535; - c = Math.floor(v / 65536); - o[i] = v - c * 65536; - } - o[0] += c-1 + 37 * (c-1); -} - -function sel25519(p, q, b) { - var t, c = ~(b-1); - for (var i = 0; i < 16; i++) { - t = c & (p[i] ^ q[i]); - p[i] ^= t; - q[i] ^= t; - } -} - -function pack25519(o, n) { - var i, j, b; - var m = gf(), t = gf(); - for (i = 0; i < 16; i++) t[i] = n[i]; - car25519(t); - car25519(t); - car25519(t); - for (j = 0; j < 2; j++) { - m[0] = t[0] - 0xffed; - for (i = 1; i < 15; i++) { - m[i] = t[i] - 0xffff - ((m[i-1]>>16) & 1); - m[i-1] &= 0xffff; - } - m[15] = t[15] - 0x7fff - ((m[14]>>16) & 1); - b = (m[15]>>16) & 1; - m[14] &= 0xffff; - sel25519(t, m, 1-b); - } - for (i = 0; i < 16; i++) { - o[2*i] = t[i] & 0xff; - o[2*i+1] = t[i]>>8; - } -} - -function neq25519(a, b) { - var c = new Uint8Array(32), d = new Uint8Array(32); - pack25519(c, a); - pack25519(d, b); - return crypto_verify_32(c, 0, d, 0); -} - -function par25519(a) { - var d = new Uint8Array(32); - pack25519(d, a); - return d[0] & 1; -} - -function unpack25519(o, n) { - var i; - for (i = 0; i < 16; i++) o[i] = n[2*i] + (n[2*i+1] << 8); - o[15] &= 0x7fff; -} - -function A(o, a, b) { - for (var i = 0; i < 16; i++) o[i] = a[i] + b[i]; -} - -function Z(o, a, b) { - for (var i = 0; i < 16; i++) o[i] = a[i] - b[i]; -} - -function M(o, a, b) { - var v, c, - t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0, - t8 = 0, t9 = 0, t10 = 0, t11 = 0, t12 = 0, t13 = 0, t14 = 0, t15 = 0, - t16 = 0, t17 = 0, t18 = 0, t19 = 0, t20 = 0, t21 = 0, t22 = 0, t23 = 0, - t24 = 0, t25 = 0, t26 = 0, t27 = 0, t28 = 0, t29 = 0, t30 = 0, - b0 = b[0], - b1 = b[1], - b2 = b[2], - b3 = b[3], - b4 = b[4], - b5 = b[5], - b6 = b[6], - b7 = b[7], - b8 = b[8], - b9 = b[9], - b10 = b[10], - b11 = b[11], - b12 = b[12], - b13 = b[13], - b14 = b[14], - b15 = b[15]; - - v = a[0]; - t0 += v * b0; - t1 += v * b1; - t2 += v * b2; - t3 += v * b3; - t4 += v * b4; - t5 += v * b5; - t6 += v * b6; - t7 += v * b7; - t8 += v * b8; - t9 += v * b9; - t10 += v * b10; - t11 += v * b11; - t12 += v * b12; - t13 += v * b13; - t14 += v * b14; - t15 += v * b15; - v = a[1]; - t1 += v * b0; - t2 += v * b1; - t3 += v * b2; - t4 += v * b3; - t5 += v * b4; - t6 += v * b5; - t7 += v * b6; - t8 += v * b7; - t9 += v * b8; - t10 += v * b9; - t11 += v * b10; - t12 += v * b11; - t13 += v * b12; - t14 += v * b13; - t15 += v * b14; - t16 += v * b15; - v = a[2]; - t2 += v * b0; - t3 += v * b1; - t4 += v * b2; - t5 += v * b3; - t6 += v * b4; - t7 += v * b5; - t8 += v * b6; - t9 += v * b7; - t10 += v * b8; - t11 += v * b9; - t12 += v * b10; - t13 += v * b11; - t14 += v * b12; - t15 += v * b13; - t16 += v * b14; - t17 += v * b15; - v = a[3]; - t3 += v * b0; - t4 += v * b1; - t5 += v * b2; - t6 += v * b3; - t7 += v * b4; - t8 += v * b5; - t9 += v * b6; - t10 += v * b7; - t11 += v * b8; - t12 += v * b9; - t13 += v * b10; - t14 += v * b11; - t15 += v * b12; - t16 += v * b13; - t17 += v * b14; - t18 += v * b15; - v = a[4]; - t4 += v * b0; - t5 += v * b1; - t6 += v * b2; - t7 += v * b3; - t8 += v * b4; - t9 += v * b5; - t10 += v * b6; - t11 += v * b7; - t12 += v * b8; - t13 += v * b9; - t14 += v * b10; - t15 += v * b11; - t16 += v * b12; - t17 += v * b13; - t18 += v * b14; - t19 += v * b15; - v = a[5]; - t5 += v * b0; - t6 += v * b1; - t7 += v * b2; - t8 += v * b3; - t9 += v * b4; - t10 += v * b5; - t11 += v * b6; - t12 += v * b7; - t13 += v * b8; - t14 += v * b9; - t15 += v * b10; - t16 += v * b11; - t17 += v * b12; - t18 += v * b13; - t19 += v * b14; - t20 += v * b15; - v = a[6]; - t6 += v * b0; - t7 += v * b1; - t8 += v * b2; - t9 += v * b3; - t10 += v * b4; - t11 += v * b5; - t12 += v * b6; - t13 += v * b7; - t14 += v * b8; - t15 += v * b9; - t16 += v * b10; - t17 += v * b11; - t18 += v * b12; - t19 += v * b13; - t20 += v * b14; - t21 += v * b15; - v = a[7]; - t7 += v * b0; - t8 += v * b1; - t9 += v * b2; - t10 += v * b3; - t11 += v * b4; - t12 += v * b5; - t13 += v * b6; - t14 += v * b7; - t15 += v * b8; - t16 += v * b9; - t17 += v * b10; - t18 += v * b11; - t19 += v * b12; - t20 += v * b13; - t21 += v * b14; - t22 += v * b15; - v = a[8]; - t8 += v * b0; - t9 += v * b1; - t10 += v * b2; - t11 += v * b3; - t12 += v * b4; - t13 += v * b5; - t14 += v * b6; - t15 += v * b7; - t16 += v * b8; - t17 += v * b9; - t18 += v * b10; - t19 += v * b11; - t20 += v * b12; - t21 += v * b13; - t22 += v * b14; - t23 += v * b15; - v = a[9]; - t9 += v * b0; - t10 += v * b1; - t11 += v * b2; - t12 += v * b3; - t13 += v * b4; - t14 += v * b5; - t15 += v * b6; - t16 += v * b7; - t17 += v * b8; - t18 += v * b9; - t19 += v * b10; - t20 += v * b11; - t21 += v * b12; - t22 += v * b13; - t23 += v * b14; - t24 += v * b15; - v = a[10]; - t10 += v * b0; - t11 += v * b1; - t12 += v * b2; - t13 += v * b3; - t14 += v * b4; - t15 += v * b5; - t16 += v * b6; - t17 += v * b7; - t18 += v * b8; - t19 += v * b9; - t20 += v * b10; - t21 += v * b11; - t22 += v * b12; - t23 += v * b13; - t24 += v * b14; - t25 += v * b15; - v = a[11]; - t11 += v * b0; - t12 += v * b1; - t13 += v * b2; - t14 += v * b3; - t15 += v * b4; - t16 += v * b5; - t17 += v * b6; - t18 += v * b7; - t19 += v * b8; - t20 += v * b9; - t21 += v * b10; - t22 += v * b11; - t23 += v * b12; - t24 += v * b13; - t25 += v * b14; - t26 += v * b15; - v = a[12]; - t12 += v * b0; - t13 += v * b1; - t14 += v * b2; - t15 += v * b3; - t16 += v * b4; - t17 += v * b5; - t18 += v * b6; - t19 += v * b7; - t20 += v * b8; - t21 += v * b9; - t22 += v * b10; - t23 += v * b11; - t24 += v * b12; - t25 += v * b13; - t26 += v * b14; - t27 += v * b15; - v = a[13]; - t13 += v * b0; - t14 += v * b1; - t15 += v * b2; - t16 += v * b3; - t17 += v * b4; - t18 += v * b5; - t19 += v * b6; - t20 += v * b7; - t21 += v * b8; - t22 += v * b9; - t23 += v * b10; - t24 += v * b11; - t25 += v * b12; - t26 += v * b13; - t27 += v * b14; - t28 += v * b15; - v = a[14]; - t14 += v * b0; - t15 += v * b1; - t16 += v * b2; - t17 += v * b3; - t18 += v * b4; - t19 += v * b5; - t20 += v * b6; - t21 += v * b7; - t22 += v * b8; - t23 += v * b9; - t24 += v * b10; - t25 += v * b11; - t26 += v * b12; - t27 += v * b13; - t28 += v * b14; - t29 += v * b15; - v = a[15]; - t15 += v * b0; - t16 += v * b1; - t17 += v * b2; - t18 += v * b3; - t19 += v * b4; - t20 += v * b5; - t21 += v * b6; - t22 += v * b7; - t23 += v * b8; - t24 += v * b9; - t25 += v * b10; - t26 += v * b11; - t27 += v * b12; - t28 += v * b13; - t29 += v * b14; - t30 += v * b15; - - t0 += 38 * t16; - t1 += 38 * t17; - t2 += 38 * t18; - t3 += 38 * t19; - t4 += 38 * t20; - t5 += 38 * t21; - t6 += 38 * t22; - t7 += 38 * t23; - t8 += 38 * t24; - t9 += 38 * t25; - t10 += 38 * t26; - t11 += 38 * t27; - t12 += 38 * t28; - t13 += 38 * t29; - t14 += 38 * t30; - // t15 left as is - - // first car - c = 1; - v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536; - v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536; - v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536; - v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536; - v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536; - v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536; - v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536; - v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536; - v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536; - v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536; - v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536; - v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536; - v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536; - v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536; - v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536; - v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536; - t0 += c-1 + 37 * (c-1); - - // second car - c = 1; - v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536; - v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536; - v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536; - v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536; - v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536; - v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536; - v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536; - v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536; - v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536; - v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536; - v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536; - v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536; - v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536; - v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536; - v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536; - v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536; - t0 += c-1 + 37 * (c-1); - - o[ 0] = t0; - o[ 1] = t1; - o[ 2] = t2; - o[ 3] = t3; - o[ 4] = t4; - o[ 5] = t5; - o[ 6] = t6; - o[ 7] = t7; - o[ 8] = t8; - o[ 9] = t9; - o[10] = t10; - o[11] = t11; - o[12] = t12; - o[13] = t13; - o[14] = t14; - o[15] = t15; -} - -function S(o, a) { - M(o, a, a); -} - -function inv25519(o, i) { - var c = gf(); - var a; - for (a = 0; a < 16; a++) c[a] = i[a]; - for (a = 253; a >= 0; a--) { - S(c, c); - if(a !== 2 && a !== 4) M(c, c, i); - } - for (a = 0; a < 16; a++) o[a] = c[a]; -} - -function pow2523(o, i) { - var c = gf(); - var a; - for (a = 0; a < 16; a++) c[a] = i[a]; - for (a = 250; a >= 0; a--) { - S(c, c); - if(a !== 1) M(c, c, i); - } - for (a = 0; a < 16; a++) o[a] = c[a]; -} - -function crypto_scalarmult(q, n, p) { - var z = new Uint8Array(32); - var x = new Float64Array(80), r, i; - var a = gf(), b = gf(), c = gf(), - d = gf(), e = gf(), f = gf(); - for (i = 0; i < 31; i++) z[i] = n[i]; - z[31]=(n[31]&127)|64; - z[0]&=248; - unpack25519(x,p); - for (i = 0; i < 16; i++) { - b[i]=x[i]; - d[i]=a[i]=c[i]=0; - } - a[0]=d[0]=1; - for (i=254; i>=0; --i) { - r=(z[i>>>3]>>>(i&7))&1; - sel25519(a,b,r); - sel25519(c,d,r); - A(e,a,c); - Z(a,a,c); - A(c,b,d); - Z(b,b,d); - S(d,e); - S(f,a); - M(a,c,a); - M(c,b,e); - A(e,a,c); - Z(a,a,c); - S(b,a); - Z(c,d,f); - M(a,c,_121665); - A(a,a,d); - M(c,c,a); - M(a,d,f); - M(d,b,x); - S(b,e); - sel25519(a,b,r); - sel25519(c,d,r); - } - for (i = 0; i < 16; i++) { - x[i+16]=a[i]; - x[i+32]=c[i]; - x[i+48]=b[i]; - x[i+64]=d[i]; - } - var x32 = x.subarray(32); - var x16 = x.subarray(16); - inv25519(x32,x32); - M(x16,x16,x32); - pack25519(q,x16); - return 0; -} - -function crypto_scalarmult_base(q, n) { - return crypto_scalarmult(q, n, _9); -} - -function crypto_box_keypair(y, x) { - randombytes(x, 32); - return crypto_scalarmult_base(y, x); -} - -function add(p, q) { - var a = gf(), b = gf(), c = gf(), - d = gf(), e = gf(), f = gf(), - g = gf(), h = gf(), t = gf(); - - Z(a, p[1], p[0]); - Z(t, q[1], q[0]); - M(a, a, t); - A(b, p[0], p[1]); - A(t, q[0], q[1]); - M(b, b, t); - M(c, p[3], q[3]); - M(c, c, D2); - M(d, p[2], q[2]); - A(d, d, d); - Z(e, b, a); - Z(f, d, c); - A(g, d, c); - A(h, b, a); - - M(p[0], e, f); - M(p[1], h, g); - M(p[2], g, f); - M(p[3], e, h); -} - -function cswap(p, q, b) { - var i; - for (i = 0; i < 4; i++) { - sel25519(p[i], q[i], b); - } -} - -function pack(r, p) { - var tx = gf(), ty = gf(), zi = gf(); - inv25519(zi, p[2]); - M(tx, p[0], zi); - M(ty, p[1], zi); - pack25519(r, ty); - r[31] ^= par25519(tx) << 7; -} - -function scalarmult(p, q, s) { - var b, i; - set25519(p[0], gf0); - set25519(p[1], gf1); - set25519(p[2], gf1); - set25519(p[3], gf0); - for (i = 255; i >= 0; --i) { - b = (s[(i/8)|0] >> (i&7)) & 1; - cswap(p, q, b); - add(q, p); - add(p, p); - cswap(p, q, b); - } -} - -function scalarbase(p, s) { - var q = [gf(), gf(), gf(), gf()]; - set25519(q[0], X); - set25519(q[1], Y); - set25519(q[2], gf1); - M(q[3], X, Y); - scalarmult(p, q, s); -} - -function crypto_sign_keypair(pk, sk, seeded) { - var d; - var p = [gf(), gf(), gf(), gf()]; - var i; - - if (!seeded) randombytes(sk, 32); - d = nacl.hash(sk.subarray(0, 32)); - d[0] &= 248; - d[31] &= 127; - d[31] |= 64; - - scalarbase(p, d); - pack(pk, p); - - for (i = 0; i < 32; i++) sk[i+32] = pk[i]; - return 0; -} - -var L = new Float64Array([0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10]); - -function modL(r, x) { - var carry, i, j, k; - for (i = 63; i >= 32; --i) { - carry = 0; - for (j = i - 32, k = i - 12; j < k; ++j) { - x[j] += carry - 16 * x[i] * L[j - (i - 32)]; - carry = Math.floor((x[j] + 128) / 256); - x[j] -= carry * 256; - } - x[j] += carry; - x[i] = 0; - } - carry = 0; - for (j = 0; j < 32; j++) { - x[j] += carry - (x[31] >> 4) * L[j]; - carry = x[j] >> 8; - x[j] &= 255; - } - for (j = 0; j < 32; j++) x[j] -= carry * L[j]; - for (i = 0; i < 32; i++) { - x[i+1] += x[i] >> 8; - r[i] = x[i] & 255; - } -} - -function reduce(r) { - var x = new Float64Array(64), i; - for (i = 0; i < 64; i++) x[i] = r[i]; - for (i = 0; i < 64; i++) r[i] = 0; - modL(r, x); -} - -// Note: difference from C - smlen returned, not passed as argument. -function crypto_sign(sm, m, n, sk) { - var d, h, r; - var i, j, x = new Float64Array(64); - var p = [gf(), gf(), gf(), gf()]; - - d = nacl.hash(sk.subarray(0, 32)); - d[0] &= 248; - d[31] &= 127; - d[31] |= 64; - - var smlen = n + 64; - for (i = 0; i < n; i++) sm[64 + i] = m[i]; - for (i = 0; i < 32; i++) sm[32 + i] = d[32 + i]; - - r = nacl.hash(sm.subarray(32, smlen)); - reduce(r); - scalarbase(p, r); - pack(sm, p); - - for (i = 32; i < 64; i++) sm[i] = sk[i]; - h = nacl.hash(sm.subarray(0, smlen)); - reduce(h); - - for (i = 0; i < 64; i++) x[i] = 0; - for (i = 0; i < 32; i++) x[i] = r[i]; - for (i = 0; i < 32; i++) { - for (j = 0; j < 32; j++) { - x[i+j] += h[i] * d[j]; - } - } - - modL(sm.subarray(32), x); - return smlen; -} - -function unpackneg(r, p) { - var t = gf(), chk = gf(), num = gf(), - den = gf(), den2 = gf(), den4 = gf(), - den6 = gf(); - - set25519(r[2], gf1); - unpack25519(r[1], p); - S(num, r[1]); - M(den, num, D); - Z(num, num, r[2]); - A(den, r[2], den); - - S(den2, den); - S(den4, den2); - M(den6, den4, den2); - M(t, den6, num); - M(t, t, den); - - pow2523(t, t); - M(t, t, num); - M(t, t, den); - M(t, t, den); - M(r[0], t, den); - - S(chk, r[0]); - M(chk, chk, den); - if (neq25519(chk, num)) M(r[0], r[0], I); - - S(chk, r[0]); - M(chk, chk, den); - if (neq25519(chk, num)) return -1; - - if (par25519(r[0]) === (p[31]>>7)) Z(r[0], gf0, r[0]); - - M(r[3], r[0], r[1]); - return 0; -} - -function crypto_sign_open(m, sm, n, pk) { - var i; - var t = new Uint8Array(32), h; - var p = [gf(), gf(), gf(), gf()], - q = [gf(), gf(), gf(), gf()]; - - if (n < 64) return -1; - - if (unpackneg(q, pk)) return -1; - - for (i = 0; i < n; i++) m[i] = sm[i]; - for (i = 0; i < 32; i++) m[i+32] = pk[i]; - h = nacl.hash(m.subarray(0, n)); - reduce(h); - scalarmult(p, q, h); - - scalarbase(q, sm.subarray(32)); - add(p, q); - pack(t, p); - - n -= 64; - if (crypto_verify_32(sm, 0, t, 0)) { - for (i = 0; i < n; i++) m[i] = 0; - return -1; - } - - for (i = 0; i < n; i++) m[i] = sm[i + 64]; - return n; -} - -var crypto_scalarmult_BYTES = 32, - crypto_scalarmult_SCALARBYTES = 32, - crypto_box_PUBLICKEYBYTES = 32, - crypto_box_SECRETKEYBYTES = 32, - crypto_sign_BYTES = 64, - crypto_sign_PUBLICKEYBYTES = 32, - crypto_sign_SECRETKEYBYTES = 64, - crypto_sign_SEEDBYTES = 32; - -function checkArrayTypes() { - for (var i = 0; i < arguments.length; i++) { - if (!(arguments[i] instanceof Uint8Array)) - throw new TypeError('unexpected type, use Uint8Array'); - } -} - -function cleanup(arr) { - for (var i = 0; i < arr.length; i++) arr[i] = 0; -} - -nacl.scalarMult = function(n, p) { - checkArrayTypes(n, p); - if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error('bad n size'); - if (p.length !== crypto_scalarmult_BYTES) throw new Error('bad p size'); - var q = new Uint8Array(crypto_scalarmult_BYTES); - crypto_scalarmult(q, n, p); - return q; -}; - -nacl.box = {}; - -nacl.box.keyPair = function() { - var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); - var sk = new Uint8Array(crypto_box_SECRETKEYBYTES); - crypto_box_keypair(pk, sk); - return {publicKey: pk, secretKey: sk}; -}; - -nacl.box.keyPair.fromSecretKey = function(secretKey) { - checkArrayTypes(secretKey); - if (secretKey.length !== crypto_box_SECRETKEYBYTES) - throw new Error('bad secret key size'); - var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); - crypto_scalarmult_base(pk, secretKey); - return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; -}; - -nacl.sign = function(msg, secretKey) { - checkArrayTypes(msg, secretKey); - if (secretKey.length !== crypto_sign_SECRETKEYBYTES) - throw new Error('bad secret key size'); - var signedMsg = new Uint8Array(crypto_sign_BYTES+msg.length); - crypto_sign(signedMsg, msg, msg.length, secretKey); - return signedMsg; -}; - -nacl.sign.detached = function(msg, secretKey) { - var signedMsg = nacl.sign(msg, secretKey); - var sig = new Uint8Array(crypto_sign_BYTES); - for (var i = 0; i < sig.length; i++) sig[i] = signedMsg[i]; - return sig; -}; - -nacl.sign.detached.verify = function(msg, sig, publicKey) { - checkArrayTypes(msg, sig, publicKey); - if (sig.length !== crypto_sign_BYTES) - throw new Error('bad signature size'); - if (publicKey.length !== crypto_sign_PUBLICKEYBYTES) - throw new Error('bad public key size'); - var sm = new Uint8Array(crypto_sign_BYTES + msg.length); - var m = new Uint8Array(crypto_sign_BYTES + msg.length); - var i; - for (i = 0; i < crypto_sign_BYTES; i++) sm[i] = sig[i]; - for (i = 0; i < msg.length; i++) sm[i+crypto_sign_BYTES] = msg[i]; - return (crypto_sign_open(m, sm, sm.length, publicKey) >= 0); -}; - -nacl.sign.keyPair = function() { - var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); - var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); - crypto_sign_keypair(pk, sk); - return {publicKey: pk, secretKey: sk}; -}; - -nacl.sign.keyPair.fromSecretKey = function(secretKey) { - checkArrayTypes(secretKey); - if (secretKey.length !== crypto_sign_SECRETKEYBYTES) - throw new Error('bad secret key size'); - var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); - for (var i = 0; i < pk.length; i++) pk[i] = secretKey[32+i]; - return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; -}; - -nacl.sign.keyPair.fromSeed = function(seed) { - checkArrayTypes(seed); - if (seed.length !== crypto_sign_SEEDBYTES) - throw new Error('bad seed size'); - var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); - var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); - for (var i = 0; i < 32; i++) sk[i] = seed[i]; - crypto_sign_keypair(pk, sk, true); - return {publicKey: pk, secretKey: sk}; -}; - -nacl.setPRNG = function(fn) { - randombytes = fn; -}; - -(function() { - // Initialize PRNG if environment provides CSPRNG. - // If not, methods calling randombytes will throw. - var crypto = typeof self !== 'undefined' ? (self.crypto || self.msCrypto) : null; - if (crypto && crypto.getRandomValues) { - // Browsers. - var QUOTA = 65536; - nacl.setPRNG(function(x, n) { - var i, v = new Uint8Array(n); - for (i = 0; i < n; i += QUOTA) { - crypto.getRandomValues(v.subarray(i, i + Math.min(n - i, QUOTA))); - } - for (i = 0; i < n; i++) x[i] = v[i]; - cleanup(v); - }); - } else if (typeof commonjsRequire !== 'undefined') { - // Node.js. - crypto = crypto__default['default']; - if (crypto && crypto.randomBytes) { - nacl.setPRNG(function(x, n) { - var i, v = crypto.randomBytes(n); - for (i = 0; i < n; i++) x[i] = v[i]; - cleanup(v); - }); - } - } -})(); - -})(module.exports ? module.exports : (self.nacl = self.nacl || {})); -}); - -// GPG4Browsers - An OpenPGP implementation in javascript - -const nodeCrypto$5 = util.getNodeCrypto(); - -/** - * Buffer for secure random numbers - */ -class RandomBuffer { - constructor() { - this.buffer = null; - this.size = null; - this.callback = null; - } - - /** - * Initialize buffer - * @param {Integer} size - size of buffer - */ - init(size, callback) { - this.buffer = new Uint8Array(size); - this.size = 0; - this.callback = callback; - } - - /** - * Concat array of secure random numbers to buffer - * @param {Uint8Array} buf - */ - set(buf) { - if (!this.buffer) { - throw new Error('RandomBuffer is not initialized'); - } - if (!(buf instanceof Uint8Array)) { - throw new Error('Invalid type: buf not an Uint8Array'); - } - const freeSpace = this.buffer.length - this.size; - if (buf.length > freeSpace) { - buf = buf.subarray(0, freeSpace); - } - // set buf with offset old size of buffer - this.buffer.set(buf, this.size); - this.size += buf.length; - } - - /** - * Take numbers out of buffer and copy to array - * @param {Uint8Array} buf - The destination array - */ - async get(buf) { - if (!this.buffer) { - throw new Error('RandomBuffer is not initialized'); - } - if (!(buf instanceof Uint8Array)) { - throw new Error('Invalid type: buf not an Uint8Array'); - } - if (this.size < buf.length) { - if (!this.callback) { - throw new Error('Random number buffer depleted'); - } - // Wait for random bytes from main context, then try again - await this.callback(); - return this.get(buf); - } - for (let i = 0; i < buf.length; i++) { - buf[i] = this.buffer[--this.size]; - // clear buffer value - this.buffer[this.size] = 0; - } - } -} - -/** - * Retrieve secure random byte array of the specified length - * @param {Integer} length - Length in bytes to generate - * @returns {Promise} Random byte array. - * @async - */ -async function getRandomBytes(length) { - const buf = new Uint8Array(length); - if (typeof crypto !== 'undefined' && crypto.getRandomValues) { - crypto.getRandomValues(buf); - } else if (nodeCrypto$5) { - const bytes = nodeCrypto$5.randomBytes(buf.length); - buf.set(bytes); - } else if (randomBuffer.buffer) { - await randomBuffer.get(buf); - } else { - throw new Error('No secure random number generator available.'); - } - return buf; -} - -/** - * Create a secure random BigInteger that is greater than or equal to min and less than max. - * @param {module:BigInteger} min - Lower bound, included - * @param {module:BigInteger} max - Upper bound, excluded - * @returns {Promise} Random BigInteger. - * @async - */ -async function getRandomBigInteger(min, max) { - const BigInteger = await util.getBigInteger(); - - if (max.lt(min)) { - throw new Error('Illegal parameter value: max <= min'); - } - - const modulus = max.sub(min); - const bytes = modulus.byteLength(); - - // Using a while loop is necessary to avoid bias introduced by the mod operation. - // However, we request 64 extra random bits so that the bias is negligible. - // Section B.1.1 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - const r = new BigInteger(await getRandomBytes(bytes + 8)); - return r.mod(modulus).add(min); -} - -const randomBuffer = new RandomBuffer(); - -var random = /*#__PURE__*/Object.freeze({ - __proto__: null, - getRandomBytes: getRandomBytes, - getRandomBigInteger: getRandomBigInteger, - randomBuffer: randomBuffer -}); - -// OpenPGP.js - An OpenPGP implementation in javascript - -/** - * Generate a probably prime random number - * @param {Integer} bits - Bit length of the prime - * @param {BigInteger} e - Optional RSA exponent to check against the prime - * @param {Integer} k - Optional number of iterations of Miller-Rabin test - * @returns BigInteger - * @async - */ -async function randomProbablePrime(bits, e, k) { - const BigInteger = await util.getBigInteger(); - const one = new BigInteger(1); - const min = one.leftShift(new BigInteger(bits - 1)); - const thirty = new BigInteger(30); - /* - * We can avoid any multiples of 3 and 5 by looking at n mod 30 - * n mod 30 = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 - * the next possible prime is mod 30: - * 1 7 7 7 7 7 7 11 11 11 11 13 13 17 17 17 17 19 19 23 23 23 23 29 29 29 29 29 29 1 - */ - const adds = [1, 6, 5, 4, 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, 3, 2, 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1, 2]; - - const n = await getRandomBigInteger(min, min.leftShift(one)); - let i = n.mod(thirty).toNumber(); - - do { - n.iadd(new BigInteger(adds[i])); - i = (i + adds[i]) % adds.length; - // If reached the maximum, go back to the minimum. - if (n.bitLength() > bits) { - n.imod(min.leftShift(one)).iadd(min); - i = n.mod(thirty).toNumber(); - } - } while (!await isProbablePrime(n, e, k)); - return n; -} - -/** - * Probabilistic primality testing - * @param {BigInteger} n - Number to test - * @param {BigInteger} e - Optional RSA exponent to check against the prime - * @param {Integer} k - Optional number of iterations of Miller-Rabin test - * @returns {boolean} - * @async - */ -async function isProbablePrime(n, e, k) { - if (e && !n.dec().gcd(e).isOne()) { - return false; - } - if (!await divisionTest(n)) { - return false; - } - if (!await fermat(n)) { - return false; - } - if (!await millerRabin(n, k)) { - return false; - } - // TODO implement the Lucas test - // See Section C.3.3 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - return true; -} - -/** - * Tests whether n is probably prime or not using Fermat's test with b = 2. - * Fails if b^(n-1) mod n != 1. - * @param {BigInteger} n - Number to test - * @param {BigInteger} b - Optional Fermat test base - * @returns {boolean} - */ -async function fermat(n, b) { - const BigInteger = await util.getBigInteger(); - b = b || new BigInteger(2); - return b.modExp(n.dec(), n).isOne(); -} - -async function divisionTest(n) { - const BigInteger = await util.getBigInteger(); - return smallPrimes.every(m => { - return n.mod(new BigInteger(m)) !== 0; - }); -} - -// https://github.com/gpg/libgcrypt/blob/master/cipher/primegen.c -const smallPrimes = [ - 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, - 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, - 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, - 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, - 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, - 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, - 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, - 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, - 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, - 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, - 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, - 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, - 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, - 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, - 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, - 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, - 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, - 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, - 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, - 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, - 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, - 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, - 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, - 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, - 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, - 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, - 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, - 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, - 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, - 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, - 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, - 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, - 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, - 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, - 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, - 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, - 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, - 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, - 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, - 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, - 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, - 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, - 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, - 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, - 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, - 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, - 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, - 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, - 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, - 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, - 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, - 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, - 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, - 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, - 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, - 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, - 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, - 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, - 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, - 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, - 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, - 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, - 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, - 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, - 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, - 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, - 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, - 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, - 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, - 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, - 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457, - 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, - 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, - 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, - 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, - 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, - 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, - 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, - 4957, 4967, 4969, 4973, 4987, 4993, 4999 -]; - - -// Miller-Rabin - Miller Rabin algorithm for primality test -// Copyright Fedor Indutny, 2014. -// -// This software is licensed under the MIT License. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -// Adapted on Jan 2018 from version 4.0.1 at https://github.com/indutny/miller-rabin - -// Sample syntax for Fixed-Base Miller-Rabin: -// millerRabin(n, k, () => new BN(small_primes[Math.random() * small_primes.length | 0])) - -/** - * Tests whether n is probably prime or not using the Miller-Rabin test. - * See HAC Remark 4.28. - * @param {BigInteger} n - Number to test - * @param {Integer} k - Optional number of iterations of Miller-Rabin test - * @param {Function} rand - Optional function to generate potential witnesses - * @returns {boolean} - * @async - */ -async function millerRabin(n, k, rand) { - const BigInteger = await util.getBigInteger(); - const len = n.bitLength(); - - if (!k) { - k = Math.max(1, (len / 48) | 0); - } - - const n1 = n.dec(); // n - 1 - - // Find d and s, (n - 1) = (2 ^ s) * d; - let s = 0; - while (!n1.getBit(s)) { s++; } - const d = n.rightShift(new BigInteger(s)); - - for (; k > 0; k--) { - const a = rand ? rand() : await getRandomBigInteger(new BigInteger(2), n1); - - let x = a.modExp(d, n); - if (x.isOne() || x.equal(n1)) { - continue; - } - - let i; - for (i = 1; i < s; i++) { - x = x.mul(x).mod(n); - - if (x.isOne()) { - return false; - } - if (x.equal(n1)) { - break; - } - } - - if (i === s) { - return false; - } - } - - return true; -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -/** - * ASN1 object identifiers for hashes - * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.2} - */ -const hash_headers = []; -hash_headers[1] = [0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, - 0x10]; -hash_headers[2] = [0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14]; -hash_headers[3] = [0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14]; -hash_headers[8] = [0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, - 0x04, 0x20]; -hash_headers[9] = [0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, - 0x04, 0x30]; -hash_headers[10] = [0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, - 0x00, 0x04, 0x40]; -hash_headers[11] = [0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, - 0x00, 0x04, 0x1C]; - -/** - * Create padding with secure random data - * @private - * @param {Integer} length - Length of the padding in bytes - * @returns {Promise} Random padding. - * @async - */ -async function getPKCS1Padding(length) { - const result = new Uint8Array(length); - let count = 0; - while (count < length) { - const randomBytes = await getRandomBytes(length - count); - for (let i = 0; i < randomBytes.length; i++) { - if (randomBytes[i] !== 0) { - result[count++] = randomBytes[i]; - } - } - } - return result; -} - -/** - * Create a EME-PKCS1-v1_5 padded message - * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.1|RFC 4880 13.1.1} - * @param {Uint8Array} message - Message to be encoded - * @param {Integer} keyLength - The length in octets of the key modulus - * @returns {Promise} EME-PKCS1 padded message. - * @async - */ -async function emeEncode(message, keyLength) { - const mLength = message.length; - // length checking - if (mLength > keyLength - 11) { - throw new Error('Message too long'); - } - // Generate an octet string PS of length k - mLen - 3 consisting of - // pseudo-randomly generated nonzero octets - const PS = await getPKCS1Padding(keyLength - mLength - 3); - // Concatenate PS, the message M, and other padding to form an - // encoded message EM of length k octets as EM = 0x00 || 0x02 || PS || 0x00 || M. - const encoded = new Uint8Array(keyLength); - // 0x00 byte - encoded[1] = 2; - encoded.set(PS, 2); - // 0x00 bytes - encoded.set(message, keyLength - mLength); - return encoded; -} - -/** - * Decode a EME-PKCS1-v1_5 padded message - * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.2|RFC 4880 13.1.2} - * @param {Uint8Array} encoded - Encoded message bytes - * @param {Uint8Array} randomPayload - Data to return in case of decoding error (needed for constant-time processing) - * @returns {Uint8Array} decoded data or `randomPayload` (on error, if given) - * @throws {Error} on decoding failure, unless `randomPayload` is provided - */ -function emeDecode(encoded, randomPayload) { - // encoded format: 0x00 0x02 0x00 - let offset = 2; - let separatorNotFound = 1; - for (let j = offset; j < encoded.length; j++) { - separatorNotFound &= encoded[j] !== 0; - offset += separatorNotFound; - } - - const psLen = offset - 2; - const payload = encoded.subarray(offset + 1); // discard the 0x00 separator - const isValidPadding = encoded[0] === 0 & encoded[1] === 2 & psLen >= 8 & !separatorNotFound; - - if (randomPayload) { - return util.selectUint8Array(isValidPadding, payload, randomPayload); - } - - if (isValidPadding) { - return payload; - } - - throw new Error('Decryption error'); -} - -/** - * Create a EMSA-PKCS1-v1_5 padded message - * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.3|RFC 4880 13.1.3} - * @param {Integer} algo - Hash algorithm type used - * @param {Uint8Array} hashed - Message to be encoded - * @param {Integer} emLen - Intended length in octets of the encoded message - * @returns {Uint8Array} Encoded message. - */ -async function emsaEncode(algo, hashed, emLen) { - let i; - if (hashed.length !== hash.getHashByteLength(algo)) { - throw new Error('Invalid hash length'); - } - // produce an ASN.1 DER value for the hash function used. - // Let T be the full hash prefix - const hashPrefix = new Uint8Array(hash_headers[algo].length); - for (i = 0; i < hash_headers[algo].length; i++) { - hashPrefix[i] = hash_headers[algo][i]; - } - // and let tLen be the length in octets prefix and hashed data - const tLen = hashPrefix.length + hashed.length; - if (emLen < tLen + 11) { - throw new Error('Intended encoded message length too short'); - } - // an octet string PS consisting of emLen - tLen - 3 octets with hexadecimal value 0xFF - // The length of PS will be at least 8 octets - const PS = new Uint8Array(emLen - tLen - 3).fill(0xff); - - // Concatenate PS, the hash prefix, hashed data, and other padding to form the - // encoded message EM as EM = 0x00 || 0x01 || PS || 0x00 || prefix || hashed - const EM = new Uint8Array(emLen); - EM[1] = 0x01; - EM.set(PS, 2); - EM.set(hashPrefix, emLen - tLen); - EM.set(hashed, emLen - hashed.length); - return EM; -} - -var pkcs1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - emeEncode: emeEncode, - emeDecode: emeDecode, - emsaEncode: emsaEncode -}); - -const webCrypto$5 = util.getWebCrypto(); -const nodeCrypto$6 = util.getNodeCrypto(); -const asn1 = nodeCrypto$6 ? asn1__default['default'] : undefined; - -/* eslint-disable no-invalid-this */ -const RSAPrivateKey = util.detectNode() ? asn1.define('RSAPrivateKey', function () { - this.seq().obj( // used for native NodeJS crypto - this.key('version').int(), // 0 - this.key('modulus').int(), // n - this.key('publicExponent').int(), // e - this.key('privateExponent').int(), // d - this.key('prime1').int(), // p - this.key('prime2').int(), // q - this.key('exponent1').int(), // dp - this.key('exponent2').int(), // dq - this.key('coefficient').int() // u - ); -}) : undefined; - -const RSAPublicKey = util.detectNode() ? asn1.define('RSAPubliceKey', function () { - this.seq().obj( // used for native NodeJS crypto - this.key('modulus').int(), // n - this.key('publicExponent').int(), // e - ); -}) : undefined; -/* eslint-enable no-invalid-this */ - -/** Create signature - * @param {module:enums.hash} hashAlgo - Hash algorithm - * @param {Uint8Array} data - Message - * @param {Uint8Array} n - RSA public modulus - * @param {Uint8Array} e - RSA public exponent - * @param {Uint8Array} d - RSA private exponent - * @param {Uint8Array} p - RSA private prime p - * @param {Uint8Array} q - RSA private prime q - * @param {Uint8Array} u - RSA private coefficient - * @param {Uint8Array} hashed - Hashed message - * @returns {Promise} RSA Signature. - * @async - */ -async function sign(hashAlgo, data, n, e, d, p, q, u, hashed) { - if (data && !util.isStream(data)) { - if (util.getWebCrypto()) { - try { - return await webSign(enums.read(enums.webHash, hashAlgo), data, n, e, d, p, q, u); - } catch (err) { - util.printDebugError(err); - } - } else if (util.getNodeCrypto()) { - return nodeSign(hashAlgo, data, n, e, d, p, q, u); - } - } - return bnSign(hashAlgo, n, d, hashed); -} - -/** - * Verify signature - * @param {module:enums.hash} hashAlgo - Hash algorithm - * @param {Uint8Array} data - Message - * @param {Uint8Array} s - Signature - * @param {Uint8Array} n - RSA public modulus - * @param {Uint8Array} e - RSA public exponent - * @param {Uint8Array} hashed - Hashed message - * @returns {Boolean} - * @async - */ -async function verify(hashAlgo, data, s, n, e, hashed) { - if (data && !util.isStream(data)) { - if (util.getWebCrypto()) { - try { - return await webVerify(enums.read(enums.webHash, hashAlgo), data, s, n, e); - } catch (err) { - util.printDebugError(err); - } - } else if (util.getNodeCrypto()) { - return nodeVerify(hashAlgo, data, s, n, e); - } - } - return bnVerify(hashAlgo, s, n, e, hashed); -} - -/** - * Encrypt message - * @param {Uint8Array} data - Message - * @param {Uint8Array} n - RSA public modulus - * @param {Uint8Array} e - RSA public exponent - * @returns {Promise} RSA Ciphertext. - * @async - */ -async function encrypt$1(data, n, e) { - if (util.getNodeCrypto()) { - return nodeEncrypt$1(data, n, e); - } - return bnEncrypt(data, n, e); -} - -/** - * Decrypt RSA message - * @param {Uint8Array} m - Message - * @param {Uint8Array} n - RSA public modulus - * @param {Uint8Array} e - RSA public exponent - * @param {Uint8Array} d - RSA private exponent - * @param {Uint8Array} p - RSA private prime p - * @param {Uint8Array} q - RSA private prime q - * @param {Uint8Array} u - RSA private coefficient - * @param {Uint8Array} randomPayload - Data to return on decryption error, instead of throwing - * (needed for constant-time processing) - * @returns {Promise} RSA Plaintext. - * @throws {Error} on decryption error, unless `randomPayload` is given - * @async - */ -async function decrypt$1(data, n, e, d, p, q, u, randomPayload) { - if (util.getNodeCrypto()) { - return nodeDecrypt$1(data, n, e, d, p, q, u, randomPayload); - } - return bnDecrypt(data, n, e, d, p, q, u, randomPayload); -} - -/** - * Generate a new random private key B bits long with public exponent E. - * - * When possible, webCrypto or nodeCrypto is used. Otherwise, primes are generated using - * 40 rounds of the Miller-Rabin probabilistic random prime generation algorithm. - * @see module:crypto/public_key/prime - * @param {Integer} bits - RSA bit length - * @param {Integer} e - RSA public exponent - * @returns {{n, e, d, - * p, q ,u: Uint8Array}} RSA public modulus, RSA public exponent, RSA private exponent, - * RSA private prime p, RSA private prime q, u = p ** -1 mod q - * @async - */ -async function generate(bits, e) { - const BigInteger = await util.getBigInteger(); - - e = new BigInteger(e); - - // Native RSA keygen using Web Crypto - if (util.getWebCrypto()) { - const keyGenOpt = { - name: 'RSASSA-PKCS1-v1_5', - modulusLength: bits, // the specified keysize in bits - publicExponent: e.toUint8Array(), // take three bytes (max 65537) for exponent - hash: { - name: 'SHA-1' // not required for actual RSA keys, but for crypto api 'sign' and 'verify' - } - }; - const keyPair = await webCrypto$5.generateKey(keyGenOpt, true, ['sign', 'verify']); - - // export the generated keys as JsonWebKey (JWK) - // https://tools.ietf.org/html/draft-ietf-jose-json-web-key-33 - const jwk = await webCrypto$5.exportKey('jwk', keyPair.privateKey); - // map JWK parameters to corresponding OpenPGP names - return { - n: b64ToUint8Array(jwk.n), - e: e.toUint8Array(), - d: b64ToUint8Array(jwk.d), - // switch p and q - p: b64ToUint8Array(jwk.q), - q: b64ToUint8Array(jwk.p), - // Since p and q are switched in places, u is the inverse of jwk.q - u: b64ToUint8Array(jwk.qi) - }; - } else if (util.getNodeCrypto() && nodeCrypto$6.generateKeyPair && RSAPrivateKey) { - const opts = { - modulusLength: bits, - publicExponent: e.toNumber(), - publicKeyEncoding: { type: 'pkcs1', format: 'der' }, - privateKeyEncoding: { type: 'pkcs1', format: 'der' } - }; - const prv = await new Promise((resolve, reject) => nodeCrypto$6.generateKeyPair('rsa', opts, (err, _, der) => { - if (err) { - reject(err); - } else { - resolve(RSAPrivateKey.decode(der, 'der')); - } - })); - /** - * OpenPGP spec differs from DER spec, DER: `u = (inverse of q) mod p`, OpenPGP: `u = (inverse of p) mod q`. - * @link https://tools.ietf.org/html/rfc3447#section-3.2 - * @link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-08#section-5.6.1 - */ - return { - n: prv.modulus.toArrayLike(Uint8Array), - e: prv.publicExponent.toArrayLike(Uint8Array), - d: prv.privateExponent.toArrayLike(Uint8Array), - // switch p and q - p: prv.prime2.toArrayLike(Uint8Array), - q: prv.prime1.toArrayLike(Uint8Array), - // Since p and q are switched in places, we can keep u as defined by DER - u: prv.coefficient.toArrayLike(Uint8Array) - }; - } - - // RSA keygen fallback using 40 iterations of the Miller-Rabin test - // See https://stackoverflow.com/a/6330138 for justification - // Also see section C.3 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST - let p; - let q; - let n; - do { - q = await randomProbablePrime(bits - (bits >> 1), e, 40); - p = await randomProbablePrime(bits >> 1, e, 40); - n = p.mul(q); - } while (n.bitLength() !== bits); - - const phi = p.dec().imul(q.dec()); - - if (q.lt(p)) { - [p, q] = [q, p]; - } - - return { - n: n.toUint8Array(), - e: e.toUint8Array(), - d: e.modInv(phi).toUint8Array(), - p: p.toUint8Array(), - q: q.toUint8Array(), - // dp: d.mod(p.subn(1)), - // dq: d.mod(q.subn(1)), - u: p.modInv(q).toUint8Array() - }; -} - -/** - * Validate RSA parameters - * @param {Uint8Array} n - RSA public modulus - * @param {Uint8Array} e - RSA public exponent - * @param {Uint8Array} d - RSA private exponent - * @param {Uint8Array} p - RSA private prime p - * @param {Uint8Array} q - RSA private prime q - * @param {Uint8Array} u - RSA inverse of p w.r.t. q - * @returns {Promise} Whether params are valid. - * @async - */ -async function validateParams(n, e, d, p, q, u) { - const BigInteger = await util.getBigInteger(); - n = new BigInteger(n); - p = new BigInteger(p); - q = new BigInteger(q); - - // expect pq = n - if (!p.mul(q).equal(n)) { - return false; - } - - const two = new BigInteger(2); - // expect p*u = 1 mod q - u = new BigInteger(u); - if (!p.mul(u).mod(q).isOne()) { - return false; - } - - e = new BigInteger(e); - d = new BigInteger(d); - /** - * In RSA pkcs#1 the exponents (d, e) are inverses modulo lcm(p-1, q-1) - * We check that [de = 1 mod (p-1)] and [de = 1 mod (q-1)] - * By CRT on coprime factors of (p-1, q-1) it follows that [de = 1 mod lcm(p-1, q-1)] - * - * We blind the multiplication with r, and check that rde = r mod lcm(p-1, q-1) - */ - const nSizeOver3 = new BigInteger(Math.floor(n.bitLength() / 3)); - const r = await getRandomBigInteger(two, two.leftShift(nSizeOver3)); // r in [ 2, 2^{|n|/3} ) < p and q - const rde = r.mul(d).mul(e); - - const areInverses = rde.mod(p.dec()).equal(r) && rde.mod(q.dec()).equal(r); - if (!areInverses) { - return false; - } - - return true; -} - -async function bnSign(hashAlgo, n, d, hashed) { - const BigInteger = await util.getBigInteger(); - n = new BigInteger(n); - const m = new BigInteger(await emsaEncode(hashAlgo, hashed, n.byteLength())); - d = new BigInteger(d); - if (m.gte(n)) { - throw new Error('Message size cannot exceed modulus size'); - } - return m.modExp(d, n).toUint8Array('be', n.byteLength()); -} - -async function webSign(hashName, data, n, e, d, p, q, u) { - /** OpenPGP keys require that p < q, and Safari Web Crypto requires that p > q. - * We swap them in privateToJWK, so it usually works out, but nevertheless, - * not all OpenPGP keys are compatible with this requirement. - * OpenPGP.js used to generate RSA keys the wrong way around (p > q), and still - * does if the underlying Web Crypto does so (e.g. old MS Edge 50% of the time). - */ - const jwk = await privateToJWK(n, e, d, p, q, u); - const algo = { - name: 'RSASSA-PKCS1-v1_5', - hash: { name: hashName } - }; - const key = await webCrypto$5.importKey('jwk', jwk, algo, false, ['sign']); - // add hash field for ms edge support - return new Uint8Array(await webCrypto$5.sign({ 'name': 'RSASSA-PKCS1-v1_5', 'hash': hashName }, key, data)); -} - -async function nodeSign(hashAlgo, data, n, e, d, p, q, u) { - const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); - const pBNum = new BN(p); - const qBNum = new BN(q); - const dBNum = new BN(d); - const dq = dBNum.mod(qBNum.subn(1)); // d mod (q-1) - const dp = dBNum.mod(pBNum.subn(1)); // d mod (p-1) - const sign = nodeCrypto$6.createSign(enums.read(enums.hash, hashAlgo)); - sign.write(data); - sign.end(); - const keyObject = { - version: 0, - modulus: new BN(n), - publicExponent: new BN(e), - privateExponent: new BN(d), - // switch p and q - prime1: new BN(q), - prime2: new BN(p), - // switch dp and dq - exponent1: dq, - exponent2: dp, - coefficient: new BN(u) - }; - if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { //from version 11.6.0 Node supports der encoded key objects - const der = RSAPrivateKey.encode(keyObject, 'der'); - return new Uint8Array(sign.sign({ key: der, format: 'der', type: 'pkcs1' })); - } - const pem = RSAPrivateKey.encode(keyObject, 'pem', { - label: 'RSA PRIVATE KEY' - }); - return new Uint8Array(sign.sign(pem)); -} - -async function bnVerify(hashAlgo, s, n, e, hashed) { - const BigInteger = await util.getBigInteger(); - n = new BigInteger(n); - s = new BigInteger(s); - e = new BigInteger(e); - if (s.gte(n)) { - throw new Error('Signature size cannot exceed modulus size'); - } - const EM1 = s.modExp(e, n).toUint8Array('be', n.byteLength()); - const EM2 = await emsaEncode(hashAlgo, hashed, n.byteLength()); - return util.equalsUint8Array(EM1, EM2); -} - -async function webVerify(hashName, data, s, n, e) { - const jwk = publicToJWK(n, e); - const key = await webCrypto$5.importKey('jwk', jwk, { - name: 'RSASSA-PKCS1-v1_5', - hash: { name: hashName } - }, false, ['verify']); - // add hash field for ms edge support - return webCrypto$5.verify({ 'name': 'RSASSA-PKCS1-v1_5', 'hash': hashName }, key, s, data); -} - -async function nodeVerify(hashAlgo, data, s, n, e) { - const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); - - const verify = nodeCrypto$6.createVerify(enums.read(enums.hash, hashAlgo)); - verify.write(data); - verify.end(); - const keyObject = { - modulus: new BN(n), - publicExponent: new BN(e) - }; - let key; - if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { //from version 11.6.0 Node supports der encoded key objects - const der = RSAPublicKey.encode(keyObject, 'der'); - key = { key: der, format: 'der', type: 'pkcs1' }; - } else { - key = RSAPublicKey.encode(keyObject, 'pem', { - label: 'RSA PUBLIC KEY' - }); - } - try { - return await verify.verify(key, s); - } catch (err) { - return false; - } -} - -async function nodeEncrypt$1(data, n, e) { - const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); - - const keyObject = { - modulus: new BN(n), - publicExponent: new BN(e) - }; - let key; - if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { - const der = RSAPublicKey.encode(keyObject, 'der'); - key = { key: der, format: 'der', type: 'pkcs1', padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; - } else { - const pem = RSAPublicKey.encode(keyObject, 'pem', { - label: 'RSA PUBLIC KEY' - }); - key = { key: pem, padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; - } - return new Uint8Array(nodeCrypto$6.publicEncrypt(key, data)); -} - -async function bnEncrypt(data, n, e) { - const BigInteger = await util.getBigInteger(); - n = new BigInteger(n); - data = new BigInteger(await emeEncode(data, n.byteLength())); - e = new BigInteger(e); - if (data.gte(n)) { - throw new Error('Message size cannot exceed modulus size'); - } - return data.modExp(e, n).toUint8Array('be', n.byteLength()); -} - -async function nodeDecrypt$1(data, n, e, d, p, q, u, randomPayload) { - const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); - - const pBNum = new BN(p); - const qBNum = new BN(q); - const dBNum = new BN(d); - const dq = dBNum.mod(qBNum.subn(1)); // d mod (q-1) - const dp = dBNum.mod(pBNum.subn(1)); // d mod (p-1) - const keyObject = { - version: 0, - modulus: new BN(n), - publicExponent: new BN(e), - privateExponent: new BN(d), - // switch p and q - prime1: new BN(q), - prime2: new BN(p), - // switch dp and dq - exponent1: dq, - exponent2: dp, - coefficient: new BN(u) - }; - let key; - if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { - const der = RSAPrivateKey.encode(keyObject, 'der'); - key = { key: der, format: 'der' , type: 'pkcs1', padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; - } else { - const pem = RSAPrivateKey.encode(keyObject, 'pem', { - label: 'RSA PRIVATE KEY' - }); - key = { key: pem, padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; - } - try { - return new Uint8Array(nodeCrypto$6.privateDecrypt(key, data)); - } catch (err) { - if (randomPayload) { - return randomPayload; - } - throw new Error('Decryption error'); - } -} - -async function bnDecrypt(data, n, e, d, p, q, u, randomPayload) { - const BigInteger = await util.getBigInteger(); - data = new BigInteger(data); - n = new BigInteger(n); - e = new BigInteger(e); - d = new BigInteger(d); - p = new BigInteger(p); - q = new BigInteger(q); - u = new BigInteger(u); - if (data.gte(n)) { - throw new Error('Data too large.'); - } - const dq = d.mod(q.dec()); // d mod (q-1) - const dp = d.mod(p.dec()); // d mod (p-1) - - const unblinder = (await getRandomBigInteger(new BigInteger(2), n)).mod(n); - const blinder = unblinder.modInv(n).modExp(e, n); - data = data.mul(blinder).mod(n); - - - const mp = data.modExp(dp, p); // data**{d mod (q-1)} mod p - const mq = data.modExp(dq, q); // data**{d mod (p-1)} mod q - const h = u.mul(mq.sub(mp)).mod(q); // u * (mq-mp) mod q (operands already < q) - - let result = h.mul(p).add(mp); // result < n due to relations above - - result = result.mul(unblinder).mod(n); - - - return emeDecode(result.toUint8Array('be', n.byteLength()), randomPayload); -} - -/** Convert Openpgp private key params to jwk key according to - * @link https://tools.ietf.org/html/rfc7517 - * @param {String} hashAlgo - * @param {Uint8Array} n - * @param {Uint8Array} e - * @param {Uint8Array} d - * @param {Uint8Array} p - * @param {Uint8Array} q - * @param {Uint8Array} u - */ -async function privateToJWK(n, e, d, p, q, u) { - const BigInteger = await util.getBigInteger(); - const pNum = new BigInteger(p); - const qNum = new BigInteger(q); - const dNum = new BigInteger(d); - - let dq = dNum.mod(qNum.dec()); // d mod (q-1) - let dp = dNum.mod(pNum.dec()); // d mod (p-1) - dp = dp.toUint8Array(); - dq = dq.toUint8Array(); - return { - kty: 'RSA', - n: uint8ArrayToB64(n, true), - e: uint8ArrayToB64(e, true), - d: uint8ArrayToB64(d, true), - // switch p and q - p: uint8ArrayToB64(q, true), - q: uint8ArrayToB64(p, true), - // switch dp and dq - dp: uint8ArrayToB64(dq, true), - dq: uint8ArrayToB64(dp, true), - qi: uint8ArrayToB64(u, true), - ext: true - }; -} - -/** Convert Openpgp key public params to jwk key according to - * @link https://tools.ietf.org/html/rfc7517 - * @param {String} hashAlgo - * @param {Uint8Array} n - * @param {Uint8Array} e - */ -function publicToJWK(n, e) { - return { - kty: 'RSA', - n: uint8ArrayToB64(n, true), - e: uint8ArrayToB64(e, true), - ext: true - }; -} - -var rsa = /*#__PURE__*/Object.freeze({ - __proto__: null, - sign: sign, - verify: verify, - encrypt: encrypt$1, - decrypt: decrypt$1, - generate: generate, - validateParams: validateParams -}); - -// GPG4Browsers - An OpenPGP implementation in javascript - -/** - * ElGamal Encryption function - * Note that in OpenPGP, the message needs to be padded with PKCS#1 (same as RSA) - * @param {Uint8Array} data - To be padded and encrypted - * @param {Uint8Array} p - * @param {Uint8Array} g - * @param {Uint8Array} y - * @returns {Promise<{ c1: Uint8Array, c2: Uint8Array }>} - * @async - */ -async function encrypt$2(data, p, g, y) { - const BigInteger = await util.getBigInteger(); - p = new BigInteger(p); - g = new BigInteger(g); - y = new BigInteger(y); - - const padded = await emeEncode(data, p.byteLength()); - const m = new BigInteger(padded); - - // OpenPGP uses a "special" version of ElGamal where g is generator of the full group Z/pZ* - // hence g has order p-1, and to avoid that k = 0 mod p-1, we need to pick k in [1, p-2] - const k = await getRandomBigInteger(new BigInteger(1), p.dec()); - return { - c1: g.modExp(k, p).toUint8Array(), - c2: y.modExp(k, p).imul(m).imod(p).toUint8Array() - }; -} - -/** - * ElGamal Encryption function - * @param {Uint8Array} c1 - * @param {Uint8Array} c2 - * @param {Uint8Array} p - * @param {Uint8Array} x - * @param {Uint8Array} randomPayload - Data to return on unpadding error, instead of throwing - * (needed for constant-time processing) - * @returns {Promise} Unpadded message. - * @throws {Error} on decryption error, unless `randomPayload` is given - * @async - */ -async function decrypt$2(c1, c2, p, x, randomPayload) { - const BigInteger = await util.getBigInteger(); - c1 = new BigInteger(c1); - c2 = new BigInteger(c2); - p = new BigInteger(p); - x = new BigInteger(x); - - const padded = c1.modExp(x, p).modInv(p).imul(c2).imod(p); - return emeDecode(padded.toUint8Array('be', p.byteLength()), randomPayload); -} - -/** - * Validate ElGamal parameters - * @param {Uint8Array} p - ElGamal prime - * @param {Uint8Array} g - ElGamal group generator - * @param {Uint8Array} y - ElGamal public key - * @param {Uint8Array} x - ElGamal private exponent - * @returns {Promise} Whether params are valid. - * @async - */ -async function validateParams$1(p, g, y, x) { - const BigInteger = await util.getBigInteger(); - p = new BigInteger(p); - g = new BigInteger(g); - y = new BigInteger(y); - - const one = new BigInteger(1); - // Check that 1 < g < p - if (g.lte(one) || g.gte(p)) { - return false; - } - - // Expect p-1 to be large - const pSize = new BigInteger(p.bitLength()); - const n1023 = new BigInteger(1023); - if (pSize.lt(n1023)) { - return false; - } - - /** - * g should have order p-1 - * Check that g ** (p-1) = 1 mod p - */ - if (!g.modExp(p.dec(), p).isOne()) { - return false; - } - - /** - * Since p-1 is not prime, g might have a smaller order that divides p-1 - * We want to make sure that the order is large enough to hinder a small subgroup attack - * - * We just check g**i != 1 for all i up to a threshold - */ - let res = g; - const i = new BigInteger(1); - const threshold = new BigInteger(2).leftShift(new BigInteger(17)); // we want order > threshold - while (i.lt(threshold)) { - res = res.mul(g).imod(p); - if (res.isOne()) { - return false; - } - i.iinc(); - } - - /** - * Re-derive public key y' = g ** x mod p - * Expect y == y' - * - * Blinded exponentiation computes g**{r(p-1) + x} to compare to y - */ - x = new BigInteger(x); - const two = new BigInteger(2); - const r = await getRandomBigInteger(two.leftShift(pSize.dec()), two.leftShift(pSize)); // draw r of same size as p-1 - const rqx = p.dec().imul(r).iadd(x); - if (!y.equal(g.modExp(rqx, p))) { - return false; - } - - return true; -} - -var elgamal = /*#__PURE__*/Object.freeze({ - __proto__: null, - encrypt: encrypt$2, - decrypt: decrypt$2, - validateParams: validateParams$1 -}); - -// OpenPGP.js - An OpenPGP implementation in javascript - -class OID { - constructor(oid) { - if (oid instanceof OID) { - this.oid = oid.oid; - } else if (util.isArray(oid) || - util.isUint8Array(oid)) { - oid = new Uint8Array(oid); - if (oid[0] === 0x06) { // DER encoded oid byte array - if (oid[1] !== oid.length - 2) { - throw new Error('Length mismatch in DER encoded oid'); - } - oid = oid.subarray(2); - } - this.oid = oid; - } else { - this.oid = ''; - } - } - - /** - * Method to read an OID object - * @param {Uint8Array} input - Where to read the OID from - * @returns {Number} Number of read bytes. - */ - read(input) { - if (input.length >= 1) { - const length = input[0]; - if (input.length >= 1 + length) { - this.oid = input.subarray(1, 1 + length); - return 1 + this.oid.length; - } - } - throw new Error('Invalid oid'); - } - - /** - * Serialize an OID object - * @returns {Uint8Array} Array with the serialized value the OID. - */ - write() { - return util.concatUint8Array([new Uint8Array([this.oid.length]), this.oid]); - } - - /** - * Serialize an OID object as a hex string - * @returns {string} String with the hex value of the OID. - */ - toHex() { - return util.uint8ArrayToHex(this.oid); - } - - /** - * If a known curve object identifier, return the canonical name of the curve - * @returns {string} String with the canonical name of the curve. - */ - getName() { - const hex = this.toHex(); - if (enums.curve[hex]) { - return enums.write(enums.curve, hex); - } else { - throw new Error('Unknown curve object identifier.'); - } - } -} - -// OpenPGP.js - An OpenPGP implementation in javascript - -function keyFromPrivate(indutnyCurve, priv) { - const keyPair = indutnyCurve.keyPair({ priv: priv }); - return keyPair; -} - -function keyFromPublic(indutnyCurve, pub) { - const keyPair = indutnyCurve.keyPair({ pub: pub }); - if (keyPair.validate().result !== true) { - throw new Error('Invalid elliptic public key'); - } - return keyPair; -} - -async function getIndutnyCurve(name) { - if (!defaultConfig.useIndutnyElliptic) { - throw new Error('This curve is only supported in the full build of OpenPGP.js'); - } - const { default: elliptic } = await Promise.resolve().then(function () { return elliptic$1; }); - return new elliptic.ec(name); -} - -// OpenPGP.js - An OpenPGP implementation in javascript - -const webCrypto$6 = util.getWebCrypto(); -const nodeCrypto$7 = util.getNodeCrypto(); - -const webCurves = { - 'p256': 'P-256', - 'p384': 'P-384', - 'p521': 'P-521' -}; -const knownCurves = nodeCrypto$7 ? nodeCrypto$7.getCurves() : []; -const nodeCurves = nodeCrypto$7 ? { - secp256k1: knownCurves.includes('secp256k1') ? 'secp256k1' : undefined, - p256: knownCurves.includes('prime256v1') ? 'prime256v1' : undefined, - p384: knownCurves.includes('secp384r1') ? 'secp384r1' : undefined, - p521: knownCurves.includes('secp521r1') ? 'secp521r1' : undefined, - ed25519: knownCurves.includes('ED25519') ? 'ED25519' : undefined, - curve25519: knownCurves.includes('X25519') ? 'X25519' : undefined, - brainpoolP256r1: knownCurves.includes('brainpoolP256r1') ? 'brainpoolP256r1' : undefined, - brainpoolP384r1: knownCurves.includes('brainpoolP384r1') ? 'brainpoolP384r1' : undefined, - brainpoolP512r1: knownCurves.includes('brainpoolP512r1') ? 'brainpoolP512r1' : undefined -} : {}; - -const curves = { - p256: { - oid: [0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07], - keyType: enums.publicKey.ecdsa, - hash: enums.hash.sha256, - cipher: enums.symmetric.aes128, - node: nodeCurves.p256, - web: webCurves.p256, - payloadSize: 32, - sharedSize: 256 - }, - p384: { - oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22], - keyType: enums.publicKey.ecdsa, - hash: enums.hash.sha384, - cipher: enums.symmetric.aes192, - node: nodeCurves.p384, - web: webCurves.p384, - payloadSize: 48, - sharedSize: 384 - }, - p521: { - oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23], - keyType: enums.publicKey.ecdsa, - hash: enums.hash.sha512, - cipher: enums.symmetric.aes256, - node: nodeCurves.p521, - web: webCurves.p521, - payloadSize: 66, - sharedSize: 528 - }, - secp256k1: { - oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x0A], - keyType: enums.publicKey.ecdsa, - hash: enums.hash.sha256, - cipher: enums.symmetric.aes128, - node: nodeCurves.secp256k1, - payloadSize: 32 - }, - ed25519: { - oid: [0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01], - keyType: enums.publicKey.eddsa, - hash: enums.hash.sha512, - node: false, // nodeCurves.ed25519 TODO - payloadSize: 32 - }, - curve25519: { - oid: [0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01], - keyType: enums.publicKey.ecdh, - hash: enums.hash.sha256, - cipher: enums.symmetric.aes128, - node: false, // nodeCurves.curve25519 TODO - payloadSize: 32 - }, - brainpoolP256r1: { - oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07], - keyType: enums.publicKey.ecdsa, - hash: enums.hash.sha256, - cipher: enums.symmetric.aes128, - node: nodeCurves.brainpoolP256r1, - payloadSize: 32 - }, - brainpoolP384r1: { - oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B], - keyType: enums.publicKey.ecdsa, - hash: enums.hash.sha384, - cipher: enums.symmetric.aes192, - node: nodeCurves.brainpoolP384r1, - payloadSize: 48 - }, - brainpoolP512r1: { - oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D], - keyType: enums.publicKey.ecdsa, - hash: enums.hash.sha512, - cipher: enums.symmetric.aes256, - node: nodeCurves.brainpoolP512r1, - payloadSize: 64 - } -}; - -class Curve { - constructor(oidOrName, params) { - try { - if (util.isArray(oidOrName) || - util.isUint8Array(oidOrName)) { - // by oid byte array - oidOrName = new OID(oidOrName); - } - if (oidOrName instanceof OID) { - // by curve OID - oidOrName = oidOrName.getName(); - } - // by curve name or oid string - this.name = enums.write(enums.curve, oidOrName); - } catch (err) { - throw new Error('Not valid curve'); - } - params = params || curves[this.name]; - - this.keyType = params.keyType; - - this.oid = params.oid; - this.hash = params.hash; - this.cipher = params.cipher; - this.node = params.node && curves[this.name]; - this.web = params.web && curves[this.name]; - this.payloadSize = params.payloadSize; - if (this.web && util.getWebCrypto()) { - this.type = 'web'; - } else if (this.node && util.getNodeCrypto()) { - this.type = 'node'; - } else if (this.name === 'curve25519') { - this.type = 'curve25519'; - } else if (this.name === 'ed25519') { - this.type = 'ed25519'; - } - } - - async genKeyPair() { - let keyPair; - switch (this.type) { - case 'web': - try { - return await webGenKeyPair(this.name); - } catch (err) { - util.printDebugError('Browser did not support generating ec key ' + err.message); - break; - } - case 'node': - return nodeGenKeyPair(this.name); - case 'curve25519': { - const privateKey = await getRandomBytes(32); - privateKey[0] = (privateKey[0] & 127) | 64; - privateKey[31] &= 248; - const secretKey = privateKey.slice().reverse(); - keyPair = naclFastLight.box.keyPair.fromSecretKey(secretKey); - const publicKey = util.concatUint8Array([new Uint8Array([0x40]), keyPair.publicKey]); - return { publicKey, privateKey }; - } - case 'ed25519': { - const privateKey = await getRandomBytes(32); - const keyPair = naclFastLight.sign.keyPair.fromSeed(privateKey); - const publicKey = util.concatUint8Array([new Uint8Array([0x40]), keyPair.publicKey]); - return { publicKey, privateKey }; - } - } - const indutnyCurve = await getIndutnyCurve(this.name); - keyPair = await indutnyCurve.genKeyPair({ - entropy: util.uint8ArrayToString(await getRandomBytes(32)) - }); - return { publicKey: new Uint8Array(keyPair.getPublic('array', false)), privateKey: keyPair.getPrivate().toArrayLike(Uint8Array) }; - } -} - -async function generate$1(curve) { - const BigInteger = await util.getBigInteger(); - - curve = new Curve(curve); - const keyPair = await curve.genKeyPair(); - const Q = new BigInteger(keyPair.publicKey).toUint8Array(); - const secret = new BigInteger(keyPair.privateKey).toUint8Array('be', curve.payloadSize); - return { - oid: curve.oid, - Q, - secret, - hash: curve.hash, - cipher: curve.cipher - }; -} - -/** - * Get preferred hash algo to use with the given curve - * @param {module:type/oid} oid - curve oid - * @returns {enums.hash} hash algorithm - */ -function getPreferredHashAlgo(oid) { - return curves[enums.write(enums.curve, oid.toHex())].hash; -} - -/** - * Validate ECDH and ECDSA parameters - * Not suitable for EdDSA (different secret key format) - * @param {module:enums.publicKey} algo - EC algorithm, to filter supported curves - * @param {module:type/oid} oid - EC object identifier - * @param {Uint8Array} Q - EC public point - * @param {Uint8Array} d - EC secret scalar - * @returns {Promise} Whether params are valid. - * @async - */ -async function validateStandardParams(algo, oid, Q, d) { - const supportedCurves = { - p256: true, - p384: true, - p521: true, - secp256k1: true, - curve25519: algo === enums.publicKey.ecdh, - brainpoolP256r1: true, - brainpoolP384r1: true, - brainpoolP512r1: true - }; - - // Check whether the given curve is supported - const curveName = oid.getName(); - if (!supportedCurves[curveName]) { - return false; - } - - if (curveName === 'curve25519') { - d = d.slice().reverse(); - // Re-derive public point Q' - const { publicKey } = naclFastLight.box.keyPair.fromSecretKey(d); - - Q = new Uint8Array(Q); - const dG = new Uint8Array([0x40, ...publicKey]); // Add public key prefix - if (!util.equalsUint8Array(dG, Q)) { - return false; - } - - return true; - } - - const curve = await getIndutnyCurve(curveName); - try { - // Parse Q and check that it is on the curve but not at infinity - Q = keyFromPublic(curve, Q).getPublic(); - } catch (validationErrors) { - return false; - } - - /** - * Re-derive public point Q' = dG from private key - * Expect Q == Q' - */ - const dG = keyFromPrivate(curve, d).getPublic(); - if (!dG.eq(Q)) { - return false; - } - - return true; -} - -////////////////////////// -// // -// Helper functions // -// // -////////////////////////// - - -async function webGenKeyPair(name) { - // Note: keys generated with ECDSA and ECDH are structurally equivalent - const webCryptoKey = await webCrypto$6.generateKey({ name: 'ECDSA', namedCurve: webCurves[name] }, true, ['sign', 'verify']); - - const privateKey = await webCrypto$6.exportKey('jwk', webCryptoKey.privateKey); - const publicKey = await webCrypto$6.exportKey('jwk', webCryptoKey.publicKey); - - return { - publicKey: jwkToRawPublic(publicKey), - privateKey: b64ToUint8Array(privateKey.d) - }; -} - -async function nodeGenKeyPair(name) { - // Note: ECDSA and ECDH key generation is structurally equivalent - const ecdh = nodeCrypto$7.createECDH(nodeCurves[name]); - await ecdh.generateKeys(); - return { - publicKey: new Uint8Array(ecdh.getPublicKey()), - privateKey: new Uint8Array(ecdh.getPrivateKey()) - }; -} - -////////////////////////// -// // -// Helper functions // -// // -////////////////////////// - -/** - * @param {JsonWebKey} jwk - key for conversion - * - * @returns {Uint8Array} Raw public key. - */ -function jwkToRawPublic(jwk) { - const bufX = b64ToUint8Array(jwk.x); - const bufY = b64ToUint8Array(jwk.y); - const publicKey = new Uint8Array(bufX.length + bufY.length + 1); - publicKey[0] = 0x04; - publicKey.set(bufX, 1); - publicKey.set(bufY, bufX.length + 1); - return publicKey; -} - -/** - * @param {Integer} payloadSize - ec payload size - * @param {String} name - curve name - * @param {Uint8Array} publicKey - public key - * - * @returns {JsonWebKey} Public key in jwk format. - */ -function rawPublicToJWK(payloadSize, name, publicKey) { - const len = payloadSize; - const bufX = publicKey.slice(1, len + 1); - const bufY = publicKey.slice(len + 1, len * 2 + 1); - // https://www.rfc-editor.org/rfc/rfc7518.txt - const jwk = { - kty: 'EC', - crv: name, - x: uint8ArrayToB64(bufX, true), - y: uint8ArrayToB64(bufY, true), - ext: true - }; - return jwk; -} - -/** - * @param {Integer} payloadSize - ec payload size - * @param {String} name - curve name - * @param {Uint8Array} publicKey - public key - * @param {Uint8Array} privateKey - private key - * - * @returns {JsonWebKey} Private key in jwk format. - */ -function privateToJWK$1(payloadSize, name, publicKey, privateKey) { - const jwk = rawPublicToJWK(payloadSize, name, publicKey); - jwk.d = uint8ArrayToB64(privateKey, true); - return jwk; -} - -const webCrypto$7 = util.getWebCrypto(); -const nodeCrypto$8 = util.getNodeCrypto(); - -/** - * Sign a message using the provided key - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {module:enums.hash} hashAlgo - Hash algorithm used to sign - * @param {Uint8Array} message - Message to sign - * @param {Uint8Array} publicKey - Public key - * @param {Uint8Array} privateKey - Private key used to sign the message - * @param {Uint8Array} hashed - The hashed message - * @returns {Promise<{ - * r: Uint8Array, - * s: Uint8Array - * }>} Signature of the message - * @async - */ -async function sign$1(oid, hashAlgo, message, publicKey, privateKey, hashed) { - const curve = new Curve(oid); - if (message && !util.isStream(message)) { - const keyPair = { publicKey, privateKey }; - switch (curve.type) { - case 'web': { - // If browser doesn't support a curve, we'll catch it - try { - // Need to await to make sure browser succeeds - return await webSign$1(curve, hashAlgo, message, keyPair); - } catch (err) { - // We do not fallback if the error is related to key integrity - // Unfortunaley Safari does not support p521 and throws a DataError when using it - // So we need to always fallback for that curve - if (curve.name !== 'p521' && (err.name === 'DataError' || err.name === 'OperationError')) { - throw err; - } - util.printDebugError('Browser did not support signing: ' + err.message); - } - break; - } - case 'node': { - const signature = await nodeSign$1(curve, hashAlgo, message, keyPair); - return { - r: signature.r.toArrayLike(Uint8Array), - s: signature.s.toArrayLike(Uint8Array) - }; - } - } - } - return ellipticSign(curve, hashed, privateKey); -} - -/** - * Verifies if a signature is valid for a message - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {module:enums.hash} hashAlgo - Hash algorithm used in the signature - * @param {{r: Uint8Array, - s: Uint8Array}} signature Signature to verify - * @param {Uint8Array} message - Message to verify - * @param {Uint8Array} publicKey - Public key used to verify the message - * @param {Uint8Array} hashed - The hashed message - * @returns {Boolean} - * @async - */ -async function verify$1(oid, hashAlgo, signature, message, publicKey, hashed) { - const curve = new Curve(oid); - if (message && !util.isStream(message)) { - switch (curve.type) { - case 'web': - try { - // Need to await to make sure browser succeeds - return await webVerify$1(curve, hashAlgo, signature, message, publicKey); - } catch (err) { - // We do not fallback if the error is related to key integrity - // Unfortunately Safari does not support p521 and throws a DataError when using it - // So we need to always fallback for that curve - if (curve.name !== 'p521' && (err.name === 'DataError' || err.name === 'OperationError')) { - throw err; - } - util.printDebugError('Browser did not support verifying: ' + err.message); - } - break; - case 'node': - return nodeVerify$1(curve, hashAlgo, signature, message, publicKey); - } - } - const digest = (typeof hashAlgo === 'undefined') ? message : hashed; - return ellipticVerify(curve, signature, digest, publicKey); -} - -/** - * Validate ECDSA parameters - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {Uint8Array} Q - ECDSA public point - * @param {Uint8Array} d - ECDSA secret scalar - * @returns {Promise} Whether params are valid. - * @async - */ -async function validateParams$2(oid, Q, d) { - const curve = new Curve(oid); - // Reject curves x25519 and ed25519 - if (curve.keyType !== enums.publicKey.ecdsa) { - return false; - } - - // To speed up the validation, we try to use node- or webcrypto when available - // and sign + verify a random message - switch (curve.type) { - case 'web': - case 'node': { - const message = await getRandomBytes(8); - const hashAlgo = enums.hash.sha256; - const hashed = await hash.digest(hashAlgo, message); - try { - const signature = await sign$1(oid, hashAlgo, message, Q, d, hashed); - return await verify$1(oid, hashAlgo, signature, message, Q, hashed); - } catch (err) { - return false; - } - } - default: - return validateStandardParams(enums.publicKey.ecdsa, oid, Q, d); - } -} - - -////////////////////////// -// // -// Helper functions // -// // -////////////////////////// - -async function ellipticSign(curve, hashed, privateKey) { - const indutnyCurve = await getIndutnyCurve(curve.name); - const key = keyFromPrivate(indutnyCurve, privateKey); - const signature = key.sign(hashed); - return { - r: signature.r.toArrayLike(Uint8Array), - s: signature.s.toArrayLike(Uint8Array) - }; -} - -async function ellipticVerify(curve, signature, digest, publicKey) { - const indutnyCurve = await getIndutnyCurve(curve.name); - const key = keyFromPublic(indutnyCurve, publicKey); - return key.verify(digest, signature); -} - -async function webSign$1(curve, hashAlgo, message, keyPair) { - const len = curve.payloadSize; - const jwk = privateToJWK$1(curve.payloadSize, webCurves[curve.name], keyPair.publicKey, keyPair.privateKey); - const key = await webCrypto$7.importKey( - 'jwk', - jwk, - { - 'name': 'ECDSA', - 'namedCurve': webCurves[curve.name], - 'hash': { name: enums.read(enums.webHash, curve.hash) } - }, - false, - ['sign'] - ); - - const signature = new Uint8Array(await webCrypto$7.sign( - { - 'name': 'ECDSA', - 'namedCurve': webCurves[curve.name], - 'hash': { name: enums.read(enums.webHash, hashAlgo) } - }, - key, - message - )); - - return { - r: signature.slice(0, len), - s: signature.slice(len, len << 1) - }; -} - -async function webVerify$1(curve, hashAlgo, { r, s }, message, publicKey) { - const jwk = rawPublicToJWK(curve.payloadSize, webCurves[curve.name], publicKey); - const key = await webCrypto$7.importKey( - 'jwk', - jwk, - { - 'name': 'ECDSA', - 'namedCurve': webCurves[curve.name], - 'hash': { name: enums.read(enums.webHash, curve.hash) } - }, - false, - ['verify'] - ); - - const signature = util.concatUint8Array([r, s]).buffer; - - return webCrypto$7.verify( - { - 'name': 'ECDSA', - 'namedCurve': webCurves[curve.name], - 'hash': { name: enums.read(enums.webHash, hashAlgo) } - }, - key, - signature, - message - ); -} - -async function nodeSign$1(curve, hashAlgo, message, keyPair) { - const sign = nodeCrypto$8.createSign(enums.read(enums.hash, hashAlgo)); - sign.write(message); - sign.end(); - const key = ECPrivateKey.encode({ - version: 1, - parameters: curve.oid, - privateKey: Array.from(keyPair.privateKey), - publicKey: { unused: 0, data: Array.from(keyPair.publicKey) } - }, 'pem', { - label: 'EC PRIVATE KEY' - }); - - return ECDSASignature.decode(sign.sign(key), 'der'); -} - -async function nodeVerify$1(curve, hashAlgo, { r, s }, message, publicKey) { - const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); - - const verify = nodeCrypto$8.createVerify(enums.read(enums.hash, hashAlgo)); - verify.write(message); - verify.end(); - const key = SubjectPublicKeyInfo.encode({ - algorithm: { - algorithm: [1, 2, 840, 10045, 2, 1], - parameters: curve.oid - }, - subjectPublicKey: { unused: 0, data: Array.from(publicKey) } - }, 'pem', { - label: 'PUBLIC KEY' - }); - const signature = ECDSASignature.encode({ - r: new BN(r), s: new BN(s) - }, 'der'); - - try { - return verify.verify(key, signature); - } catch (err) { - return false; - } -} - -// Originally written by Owen Smith https://github.com/omsmith -// Adapted on Feb 2018 from https://github.com/Brightspace/node-jwk-to-pem/ - -/* eslint-disable no-invalid-this */ - -const asn1$1 = nodeCrypto$8 ? asn1__default['default'] : undefined; - -const ECDSASignature = nodeCrypto$8 ? - asn1$1.define('ECDSASignature', function() { - this.seq().obj( - this.key('r').int(), - this.key('s').int() - ); - }) : undefined; - -const ECPrivateKey = nodeCrypto$8 ? - asn1$1.define('ECPrivateKey', function() { - this.seq().obj( - this.key('version').int(), - this.key('privateKey').octstr(), - this.key('parameters').explicit(0).optional().any(), - this.key('publicKey').explicit(1).optional().bitstr() - ); - }) : undefined; - -const AlgorithmIdentifier = nodeCrypto$8 ? - asn1$1.define('AlgorithmIdentifier', function() { - this.seq().obj( - this.key('algorithm').objid(), - this.key('parameters').optional().any() - ); - }) : undefined; - -const SubjectPublicKeyInfo = nodeCrypto$8 ? - asn1$1.define('SubjectPublicKeyInfo', function() { - this.seq().obj( - this.key('algorithm').use(AlgorithmIdentifier), - this.key('subjectPublicKey').bitstr() - ); - }) : undefined; - -var ecdsa = /*#__PURE__*/Object.freeze({ - __proto__: null, - sign: sign$1, - verify: verify$1, - validateParams: validateParams$2 -}); - -// OpenPGP.js - An OpenPGP implementation in javascript - -naclFastLight.hash = bytes => new Uint8Array(_512().update(bytes).digest()); - -/** - * Sign a message using the provided key - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {module:enums.hash} hashAlgo - Hash algorithm used to sign (must be sha256 or stronger) - * @param {Uint8Array} message - Message to sign - * @param {Uint8Array} publicKey - Public key - * @param {Uint8Array} privateKey - Private key used to sign the message - * @param {Uint8Array} hashed - The hashed message - * @returns {Promise<{ - * r: Uint8Array, - * s: Uint8Array - * }>} Signature of the message - * @async - */ -async function sign$2(oid, hashAlgo, message, publicKey, privateKey, hashed) { - if (hash.getHashByteLength(hashAlgo) < hash.getHashByteLength(enums.hash.sha256)) { - // see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2 - throw new Error('Hash algorithm too weak: sha256 or stronger is required for EdDSA.'); - } - const secretKey = util.concatUint8Array([privateKey, publicKey.subarray(1)]); - const signature = naclFastLight.sign.detached(hashed, secretKey); - // EdDSA signature params are returned in little-endian format - return { - r: signature.subarray(0, 32), - s: signature.subarray(32) - }; -} - -/** - * Verifies if a signature is valid for a message - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {module:enums.hash} hashAlgo - Hash algorithm used in the signature - * @param {{r: Uint8Array, - s: Uint8Array}} signature Signature to verify the message - * @param {Uint8Array} m - Message to verify - * @param {Uint8Array} publicKey - Public key used to verify the message - * @param {Uint8Array} hashed - The hashed message - * @returns {Boolean} - * @async - */ -async function verify$2(oid, hashAlgo, { r, s }, m, publicKey, hashed) { - const signature = util.concatUint8Array([r, s]); - return naclFastLight.sign.detached.verify(hashed, signature, publicKey.subarray(1)); -} -/** - * Validate EdDSA parameters - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {Uint8Array} Q - EdDSA public point - * @param {Uint8Array} k - EdDSA secret seed - * @returns {Promise} Whether params are valid. - * @async - */ -async function validateParams$3(oid, Q, k) { - // Check whether the given curve is supported - if (oid.getName() !== 'ed25519') { - return false; - } - - /** - * Derive public point Q' = dG from private key - * and expect Q == Q' - */ - const { publicKey } = naclFastLight.sign.keyPair.fromSeed(k); - const dG = new Uint8Array([0x40, ...publicKey]); // Add public key prefix - return util.equalsUint8Array(Q, dG); -} - -var eddsa = /*#__PURE__*/Object.freeze({ - __proto__: null, - sign: sign$2, - verify: verify$2, - validateParams: validateParams$3 -}); - -// OpenPGP.js - An OpenPGP implementation in javascript - -/** - * AES key wrap - * @function - * @param {Uint8Array} key - * @param {Uint8Array} data - * @returns {Uint8Array} - */ -function wrap(key, data) { - const aes = new cipher['aes' + (key.length * 8)](key); - const IV = new Uint32Array([0xA6A6A6A6, 0xA6A6A6A6]); - const P = unpack(data); - let A = IV; - const R = P; - const n = P.length / 2; - const t = new Uint32Array([0, 0]); - let B = new Uint32Array(4); - for (let j = 0; j <= 5; ++j) { - for (let i = 0; i < n; ++i) { - t[1] = n * j + (1 + i); - // B = A - B[0] = A[0]; - B[1] = A[1]; - // B = A || R[i] - B[2] = R[2 * i]; - B[3] = R[2 * i + 1]; - // B = AES(K, B) - B = unpack(aes.encrypt(pack(B))); - // A = MSB(64, B) ^ t - A = B.subarray(0, 2); - A[0] ^= t[0]; - A[1] ^= t[1]; - // R[i] = LSB(64, B) - R[2 * i] = B[2]; - R[2 * i + 1] = B[3]; - } - } - return pack(A, R); -} - -/** - * AES key unwrap - * @function - * @param {String} key - * @param {String} data - * @returns {Uint8Array} - * @throws {Error} - */ -function unwrap(key, data) { - const aes = new cipher['aes' + (key.length * 8)](key); - const IV = new Uint32Array([0xA6A6A6A6, 0xA6A6A6A6]); - const C = unpack(data); - let A = C.subarray(0, 2); - const R = C.subarray(2); - const n = C.length / 2 - 1; - const t = new Uint32Array([0, 0]); - let B = new Uint32Array(4); - for (let j = 5; j >= 0; --j) { - for (let i = n - 1; i >= 0; --i) { - t[1] = n * j + (i + 1); - // B = A ^ t - B[0] = A[0] ^ t[0]; - B[1] = A[1] ^ t[1]; - // B = (A ^ t) || R[i] - B[2] = R[2 * i]; - B[3] = R[2 * i + 1]; - // B = AES-1(B) - B = unpack(aes.decrypt(pack(B))); - // A = MSB(64, B) - A = B.subarray(0, 2); - // R[i] = LSB(64, B) - R[2 * i] = B[2]; - R[2 * i + 1] = B[3]; - } - } - if (A[0] === IV[0] && A[1] === IV[1]) { - return pack(R); - } - throw new Error('Key Data Integrity failed'); -} - -function createArrayBuffer(data) { - if (util.isString(data)) { - const { length } = data; - const buffer = new ArrayBuffer(length); - const view = new Uint8Array(buffer); - for (let j = 0; j < length; ++j) { - view[j] = data.charCodeAt(j); - } - return buffer; - } - return new Uint8Array(data).buffer; -} - -function unpack(data) { - const { length } = data; - const buffer = createArrayBuffer(data); - const view = new DataView(buffer); - const arr = new Uint32Array(length / 4); - for (let i = 0; i < length / 4; ++i) { - arr[i] = view.getUint32(4 * i); - } - return arr; -} - -function pack() { - let length = 0; - for (let k = 0; k < arguments.length; ++k) { - length += 4 * arguments[k].length; - } - const buffer = new ArrayBuffer(length); - const view = new DataView(buffer); - let offset = 0; - for (let i = 0; i < arguments.length; ++i) { - for (let j = 0; j < arguments[i].length; ++j) { - view.setUint32(offset + 4 * j, arguments[i][j]); - } - offset += 4 * arguments[i].length; - } - return new Uint8Array(buffer); -} - -var aesKW = /*#__PURE__*/Object.freeze({ - __proto__: null, - wrap: wrap, - unwrap: unwrap -}); - -// OpenPGP.js - An OpenPGP implementation in javascript - -/** - * @fileoverview Functions to add and remove PKCS5 padding - * @see PublicKeyEncryptedSessionKeyPacket - * @module crypto/pkcs5 - * @private - */ - -/** - * Add pkcs5 padding to a message - * @param {Uint8Array} message - message to pad - * @returns {Uint8Array} Padded message. - */ -function encode$1(message) { - const c = 8 - (message.length % 8); - const padded = new Uint8Array(message.length + c).fill(c); - padded.set(message); - return padded; -} - -/** - * Remove pkcs5 padding from a message - * @param {Uint8Array} message - message to remove padding from - * @returns {Uint8Array} Message without padding. - */ -function decode$1(message) { - const len = message.length; - if (len > 0) { - const c = message[len - 1]; - if (c >= 1) { - const provided = message.subarray(len - c); - const computed = new Uint8Array(c).fill(c); - if (util.equalsUint8Array(provided, computed)) { - return message.subarray(0, len - c); - } - } - } - throw new Error('Invalid padding'); -} - -var pkcs5 = /*#__PURE__*/Object.freeze({ - __proto__: null, - encode: encode$1, - decode: decode$1 -}); - -// OpenPGP.js - An OpenPGP implementation in javascript - -class ECDHSymmetricKey { - constructor(data) { - if (typeof data === 'undefined') { - data = new Uint8Array([]); - } else if (util.isString(data)) { - data = util.stringToUint8Array(data); - } else { - data = new Uint8Array(data); - } - this.data = data; - } - - /** - * Read an ECDHSymmetricKey from an Uint8Array - * @param {Uint8Array} input - Where to read the encoded symmetric key from - * @returns {Number} Number of read bytes. - */ - read(input) { - if (input.length >= 1) { - const length = input[0]; - if (input.length >= 1 + length) { - this.data = input.subarray(1, 1 + length); - return 1 + this.data.length; - } - } - throw new Error('Invalid symmetric key'); - } - - /** - * Write an ECDHSymmetricKey as an Uint8Array - * @returns {Uint8Array} An array containing the value - */ - write() { - return util.concatUint8Array([new Uint8Array([this.data.length]), this.data]); - } -} - -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2015-2016 Decentral -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * Implementation of type KDF parameters - * - * {@link https://tools.ietf.org/html/rfc6637#section-7|RFC 6637 7}: - * A key derivation function (KDF) is necessary to implement the EC - * encryption. The Concatenation Key Derivation Function (Approved - * Alternative 1) [NIST-SP800-56A] with the KDF hash function that is - * SHA2-256 [FIPS-180-3] or stronger is REQUIRED. - * @module type/kdf_params - * @private - */ - -class KDFParams { - /** - * @param {enums.hash} hash - Hash algorithm - * @param {enums.symmetric} cipher - Symmetric algorithm - */ - constructor(data) { - if (data) { - const { hash, cipher } = data; - this.hash = hash; - this.cipher = cipher; - } else { - this.hash = null; - this.cipher = null; - } - } - - /** - * Read KDFParams from an Uint8Array - * @param {Uint8Array} input - Where to read the KDFParams from - * @returns {Number} Number of read bytes. - */ - read(input) { - if (input.length < 4 || input[0] !== 3 || input[1] !== 1) { - throw new Error('Cannot read KDFParams'); - } - this.hash = input[2]; - this.cipher = input[3]; - return 4; - } - - /** - * Write KDFParams to an Uint8Array - * @returns {Uint8Array} Array with the KDFParams value - */ - write() { - return new Uint8Array([3, 1, this.hash, this.cipher]); - } -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -/** - * Encrypts data using specified algorithm and public key parameters. - * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} for public key algorithms. - * @param {module:enums.publicKey} algo - Public key algorithm - * @param {Object} publicParams - Algorithm-specific public key parameters - * @param {Uint8Array} data - Data to be encrypted - * @param {Uint8Array} fingerprint - Recipient fingerprint - * @returns {Promise} Encrypted session key parameters. - * @async - */ -async function publicKeyEncrypt(algo, publicParams, data, fingerprint) { - switch (algo) { - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaEncryptSign: { - const { n, e } = publicParams; - const c = await publicKey.rsa.encrypt(data, n, e); - return { c }; - } - case enums.publicKey.elgamal: { - const { p, g, y } = publicParams; - return publicKey.elgamal.encrypt(data, p, g, y); - } - case enums.publicKey.ecdh: { - const { oid, Q, kdfParams } = publicParams; - const { publicKey: V, wrappedKey: C } = await publicKey.elliptic.ecdh.encrypt( - oid, kdfParams, data, Q, fingerprint); - return { V, C: new ECDHSymmetricKey(C) }; - } - default: - return []; - } -} - -/** - * Decrypts data using specified algorithm and private key parameters. - * See {@link https://tools.ietf.org/html/rfc4880#section-5.5.3|RFC 4880 5.5.3} - * @param {module:enums.publicKey} algo - Public key algorithm - * @param {Object} publicKeyParams - Algorithm-specific public key parameters - * @param {Object} privateKeyParams - Algorithm-specific private key parameters - * @param {Object} sessionKeyParams - Encrypted session key parameters - * @param {Uint8Array} fingerprint - Recipient fingerprint - * @param {Uint8Array} [randomPayload] - Data to return on decryption error, instead of throwing - * (needed for constant-time processing in RSA and ElGamal) - * @returns {Promise} Decrypted data. - * @throws {Error} on sensitive decryption error, unless `randomPayload` is given - * @async - */ -async function publicKeyDecrypt(algo, publicKeyParams, privateKeyParams, sessionKeyParams, fingerprint, randomPayload) { - switch (algo) { - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaEncrypt: { - const { c } = sessionKeyParams; - const { n, e } = publicKeyParams; - const { d, p, q, u } = privateKeyParams; - return publicKey.rsa.decrypt(c, n, e, d, p, q, u, randomPayload); - } - case enums.publicKey.elgamal: { - const { c1, c2 } = sessionKeyParams; - const p = publicKeyParams.p; - const x = privateKeyParams.x; - return publicKey.elgamal.decrypt(c1, c2, p, x, randomPayload); - } - case enums.publicKey.ecdh: { - const { oid, Q, kdfParams } = publicKeyParams; - const { d } = privateKeyParams; - const { V, C } = sessionKeyParams; - return publicKey.elliptic.ecdh.decrypt( - oid, kdfParams, V, C.data, Q, d, fingerprint); - } - default: - throw new Error('Invalid public key encryption algorithm.'); - } -} - -/** - * Parse public key material in binary form to get the key parameters - * @param {module:enums.publicKey} algo - The key algorithm - * @param {Uint8Array} bytes - The key material to parse - * @returns {{ read: Number, publicParams: Object }} Number of read bytes plus key parameters referenced by name. - */ -function parsePublicKeyParams(algo, bytes) { - let read = 0; - switch (algo) { - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaSign: { - const n = util.readMPI(bytes.subarray(read)); read += n.length + 2; - const e = util.readMPI(bytes.subarray(read)); read += e.length + 2; - return { read, publicParams: { n, e } }; - } - case enums.publicKey.dsa: { - const p = util.readMPI(bytes.subarray(read)); read += p.length + 2; - const q = util.readMPI(bytes.subarray(read)); read += q.length + 2; - const g = util.readMPI(bytes.subarray(read)); read += g.length + 2; - const y = util.readMPI(bytes.subarray(read)); read += y.length + 2; - return { read, publicParams: { p, q, g, y } }; - } - case enums.publicKey.elgamal: { - const p = util.readMPI(bytes.subarray(read)); read += p.length + 2; - const g = util.readMPI(bytes.subarray(read)); read += g.length + 2; - const y = util.readMPI(bytes.subarray(read)); read += y.length + 2; - return { read, publicParams: { p, g, y } }; - } - case enums.publicKey.ecdsa: { - const oid = new OID(); read += oid.read(bytes); - const Q = util.readMPI(bytes.subarray(read)); read += Q.length + 2; - return { read: read, publicParams: { oid, Q } }; - } - case enums.publicKey.eddsa: { - const oid = new OID(); read += oid.read(bytes); - let Q = util.readMPI(bytes.subarray(read)); read += Q.length + 2; - Q = util.leftPad(Q, 33); - return { read: read, publicParams: { oid, Q } }; - } - case enums.publicKey.ecdh: { - const oid = new OID(); read += oid.read(bytes); - const Q = util.readMPI(bytes.subarray(read)); read += Q.length + 2; - const kdfParams = new KDFParams(); read += kdfParams.read(bytes.subarray(read)); - return { read: read, publicParams: { oid, Q, kdfParams } }; - } - default: - throw new Error('Invalid public key encryption algorithm.'); - } -} - -/** - * Parse private key material in binary form to get the key parameters - * @param {module:enums.publicKey} algo - The key algorithm - * @param {Uint8Array} bytes - The key material to parse - * @param {Object} publicParams - (ECC only) public params, needed to format some private params - * @returns {{ read: Number, privateParams: Object }} Number of read bytes plus the key parameters referenced by name. - */ -function parsePrivateKeyParams(algo, bytes, publicParams) { - let read = 0; - switch (algo) { - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaSign: { - const d = util.readMPI(bytes.subarray(read)); read += d.length + 2; - const p = util.readMPI(bytes.subarray(read)); read += p.length + 2; - const q = util.readMPI(bytes.subarray(read)); read += q.length + 2; - const u = util.readMPI(bytes.subarray(read)); read += u.length + 2; - return { read, privateParams: { d, p, q, u } }; - } - case enums.publicKey.dsa: - case enums.publicKey.elgamal: { - const x = util.readMPI(bytes.subarray(read)); read += x.length + 2; - return { read, privateParams: { x } }; - } - case enums.publicKey.ecdsa: - case enums.publicKey.ecdh: { - const curve = new Curve(publicParams.oid); - let d = util.readMPI(bytes.subarray(read)); read += d.length + 2; - d = util.leftPad(d, curve.payloadSize); - return { read, privateParams: { d } }; - } - case enums.publicKey.eddsa: { - let seed = util.readMPI(bytes.subarray(read)); read += seed.length + 2; - seed = util.leftPad(seed, 32); - return { read, privateParams: { seed } }; - } - default: - throw new Error('Invalid public key encryption algorithm.'); - } -} - -/** Returns the types comprising the encrypted session key of an algorithm - * @param {module:enums.publicKey} algo - The key algorithm - * @param {Uint8Array} bytes - The key material to parse - * @returns {Object} The session key parameters referenced by name. - */ -function parseEncSessionKeyParams(algo, bytes) { - let read = 0; - switch (algo) { - // Algorithm-Specific Fields for RSA encrypted session keys: - // - MPI of RSA encrypted value m**e mod n. - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaEncryptSign: { - const c = util.readMPI(bytes.subarray(read)); - return { c }; - } - - // Algorithm-Specific Fields for Elgamal encrypted session keys: - // - MPI of Elgamal value g**k mod p - // - MPI of Elgamal value m * y**k mod p - case enums.publicKey.elgamal: { - const c1 = util.readMPI(bytes.subarray(read)); read += c1.length + 2; - const c2 = util.readMPI(bytes.subarray(read)); - return { c1, c2 }; - } - // Algorithm-Specific Fields for ECDH encrypted session keys: - // - MPI containing the ephemeral key used to establish the shared secret - // - ECDH Symmetric Key - case enums.publicKey.ecdh: { - const V = util.readMPI(bytes.subarray(read)); read += V.length + 2; - const C = new ECDHSymmetricKey(); C.read(bytes.subarray(read)); - return { V, C }; - } - default: - throw new Error('Invalid public key encryption algorithm.'); - } -} - -/** - * Convert params to MPI and serializes them in the proper order - * @param {module:enums.publicKey} algo - The public key algorithm - * @param {Object} params - The key parameters indexed by name - * @returns {Uint8Array} The array containing the MPIs. - */ -function serializeParams(algo, params) { - const orderedParams = Object.keys(params).map(name => { - const param = params[name]; - return util.isUint8Array(param) ? util.uint8ArrayToMPI(param) : param.write(); - }); - return util.concatUint8Array(orderedParams); -} - -/** - * Generate algorithm-specific key parameters - * @param {module:enums.publicKey} algo - The public key algorithm - * @param {Integer} bits - Bit length for RSA keys - * @param {module:type/oid} oid - Object identifier for ECC keys - * @returns {Promise<{ publicParams: {Object}, privateParams: {Object} }>} The parameters referenced by name. - * @async - */ -function generateParams(algo, bits, oid) { - switch (algo) { - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaSign: { - return publicKey.rsa.generate(bits, 65537).then(({ n, e, d, p, q, u }) => ({ - privateParams: { d, p, q, u }, - publicParams: { n, e } - })); - } - case enums.publicKey.ecdsa: - return publicKey.elliptic.generate(oid).then(({ oid, Q, secret }) => ({ - privateParams: { d: secret }, - publicParams: { oid: new OID(oid), Q } - })); - case enums.publicKey.eddsa: - return publicKey.elliptic.generate(oid).then(({ oid, Q, secret }) => ({ - privateParams: { seed: secret }, - publicParams: { oid: new OID(oid), Q } - })); - case enums.publicKey.ecdh: - return publicKey.elliptic.generate(oid).then(({ oid, Q, secret, hash, cipher }) => ({ - privateParams: { d: secret }, - publicParams: { - oid: new OID(oid), - Q, - kdfParams: new KDFParams({ hash, cipher }) - } - })); - case enums.publicKey.dsa: - case enums.publicKey.elgamal: - throw new Error('Unsupported algorithm for key generation.'); - default: - throw new Error('Invalid public key algorithm.'); - } -} - -/** - * Validate algorithm-specific key parameters - * @param {module:enums.publicKey} algo - The public key algorithm - * @param {Object} publicParams - Algorithm-specific public key parameters - * @param {Object} privateParams - Algorithm-specific private key parameters - * @returns {Promise} Whether the parameters are valid. - * @async - */ -async function validateParams$4(algo, publicParams, privateParams) { - if (!publicParams || !privateParams) { - throw new Error('Missing key parameters'); - } - switch (algo) { - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaSign: { - const { n, e } = publicParams; - const { d, p, q, u } = privateParams; - return publicKey.rsa.validateParams(n, e, d, p, q, u); - } - case enums.publicKey.dsa: { - const { p, q, g, y } = publicParams; - const { x } = privateParams; - return publicKey.dsa.validateParams(p, q, g, y, x); - } - case enums.publicKey.elgamal: { - const { p, g, y } = publicParams; - const { x } = privateParams; - return publicKey.elgamal.validateParams(p, g, y, x); - } - case enums.publicKey.ecdsa: - case enums.publicKey.ecdh: { - const algoModule = publicKey.elliptic[enums.read(enums.publicKey, algo)]; - const { oid, Q } = publicParams; - const { d } = privateParams; - return algoModule.validateParams(oid, Q, d); - } - case enums.publicKey.eddsa: { - const { oid, Q } = publicParams; - const { seed } = privateParams; - return publicKey.elliptic.eddsa.validateParams(oid, Q, seed); - } - default: - throw new Error('Invalid public key algorithm.'); - } -} - -/** - * Generates a random byte prefix for the specified algorithm - * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. - * @param {module:enums.symmetric} algo - Symmetric encryption algorithm - * @returns {Promise} Random bytes with length equal to the block size of the cipher, plus the last two bytes repeated. - * @async - */ -async function getPrefixRandom(algo) { - const { blockSize } = getCipher(algo); - const prefixrandom = await getRandomBytes(blockSize); - const repeat = new Uint8Array([prefixrandom[prefixrandom.length - 2], prefixrandom[prefixrandom.length - 1]]); - return util.concat([prefixrandom, repeat]); -} - -/** - * Generating a session key for the specified symmetric algorithm - * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. - * @param {module:enums.symmetric} algo - Symmetric encryption algorithm - * @returns {Promise} Random bytes as a string to be used as a key. - * @async - */ -function generateSessionKey(algo) { - const { keySize } = getCipher(algo); - return getRandomBytes(keySize); -} - -/** - * Get implementation of the given AEAD mode - * @param {enums.aead} algo - * @returns {Object} - * @throws {Error} on invalid algo - */ -function getAEADMode(algo) { - const algoName = enums.read(enums.aead, algo); - return mode[algoName]; -} - -/** - * Get implementation of the given cipher - * @param {enums.symmetric} algo - * @returns {Object} - * @throws {Error} on invalid algo - */ -function getCipher(algo) { - const algoName = enums.read(enums.symmetric, algo); - return cipher[algoName]; -} - -var crypto$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - publicKeyEncrypt: publicKeyEncrypt, - publicKeyDecrypt: publicKeyDecrypt, - parsePublicKeyParams: parsePublicKeyParams, - parsePrivateKeyParams: parsePrivateKeyParams, - parseEncSessionKeyParams: parseEncSessionKeyParams, - serializeParams: serializeParams, - generateParams: generateParams, - validateParams: validateParams$4, - getPrefixRandom: getPrefixRandom, - generateSessionKey: generateSessionKey, - getAEADMode: getAEADMode, - getCipher: getCipher -}); - -// OpenPGP.js - An OpenPGP implementation in javascript - -const webCrypto$8 = util.getWebCrypto(); -const nodeCrypto$9 = util.getNodeCrypto(); - -/** - * Validate ECDH parameters - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {Uint8Array} Q - ECDH public point - * @param {Uint8Array} d - ECDH secret scalar - * @returns {Promise} Whether params are valid. - * @async - */ -async function validateParams$5(oid, Q, d) { - return validateStandardParams(enums.publicKey.ecdh, oid, Q, d); -} - -// Build Param for ECDH algorithm (RFC 6637) -function buildEcdhParam(public_algo, oid, kdfParams, fingerprint) { - return util.concatUint8Array([ - oid.write(), - new Uint8Array([public_algo]), - kdfParams.write(), - util.stringToUint8Array('Anonymous Sender '), - fingerprint.subarray(0, 20) - ]); -} - -// Key Derivation Function (RFC 6637) -async function kdf(hashAlgo, X, length, param, stripLeading = false, stripTrailing = false) { - // Note: X is little endian for Curve25519, big-endian for all others. - // This is not ideal, but the RFC's are unclear - // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B - let i; - if (stripLeading) { - // Work around old go crypto bug - for (i = 0; i < X.length && X[i] === 0; i++); - X = X.subarray(i); - } - if (stripTrailing) { - // Work around old OpenPGP.js bug - for (i = X.length - 1; i >= 0 && X[i] === 0; i--); - X = X.subarray(0, i + 1); - } - const digest = await hash.digest(hashAlgo, util.concatUint8Array([ - new Uint8Array([0, 0, 0, 1]), - X, - param - ])); - return digest.subarray(0, length); -} - -/** - * Generate ECDHE ephemeral key and secret from public key - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} Q - Recipient public key - * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ -async function genPublicEphemeralKey(curve, Q) { - switch (curve.type) { - case 'curve25519': { - const d = await getRandomBytes(32); - const { secretKey, sharedKey } = await genPrivateEphemeralKey(curve, Q, null, d); - let { publicKey } = naclFastLight.box.keyPair.fromSecretKey(secretKey); - publicKey = util.concatUint8Array([new Uint8Array([0x40]), publicKey]); - return { publicKey, sharedKey }; // Note: sharedKey is little-endian here, unlike below - } - case 'web': - if (curve.web && util.getWebCrypto()) { - try { - return await webPublicEphemeralKey(curve, Q); - } catch (err) { - util.printDebugError(err); - } - } - break; - case 'node': - return nodePublicEphemeralKey(curve, Q); - } - return ellipticPublicEphemeralKey(curve, Q); -} - -/** - * Encrypt and wrap a session key - * - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {module:type/kdf_params} kdfParams - KDF params including cipher and algorithm to use - * @param {Uint8Array} data - Unpadded session key data - * @param {Uint8Array} Q - Recipient public key - * @param {Uint8Array} fingerprint - Recipient fingerprint - * @returns {Promise<{publicKey: Uint8Array, wrappedKey: Uint8Array}>} - * @async - */ -async function encrypt$3(oid, kdfParams, data, Q, fingerprint) { - const m = encode$1(data); - - const curve = new Curve(oid); - const { publicKey, sharedKey } = await genPublicEphemeralKey(curve, Q); - const param = buildEcdhParam(enums.publicKey.ecdh, oid, kdfParams, fingerprint); - const { keySize } = getCipher(kdfParams.cipher); - const Z = await kdf(kdfParams.hash, sharedKey, keySize, param); - const wrappedKey = wrap(Z, m); - return { publicKey, wrappedKey }; -} - -/** - * Generate ECDHE secret from private key and public part of ephemeral key - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} V - Public part of ephemeral key - * @param {Uint8Array} Q - Recipient public key - * @param {Uint8Array} d - Recipient private key - * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ -async function genPrivateEphemeralKey(curve, V, Q, d) { - if (d.length !== curve.payloadSize) { - const privateKey = new Uint8Array(curve.payloadSize); - privateKey.set(d, curve.payloadSize - d.length); - d = privateKey; - } - switch (curve.type) { - case 'curve25519': { - const secretKey = d.slice().reverse(); - const sharedKey = naclFastLight.scalarMult(secretKey, V.subarray(1)); - return { secretKey, sharedKey }; // Note: sharedKey is little-endian here, unlike below - } - case 'web': - if (curve.web && util.getWebCrypto()) { - try { - return await webPrivateEphemeralKey(curve, V, Q, d); - } catch (err) { - util.printDebugError(err); - } - } - break; - case 'node': - return nodePrivateEphemeralKey(curve, V, d); - } - return ellipticPrivateEphemeralKey(curve, V, d); -} - -/** - * Decrypt and unwrap the value derived from session key - * - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {module:type/kdf_params} kdfParams - KDF params including cipher and algorithm to use - * @param {Uint8Array} V - Public part of ephemeral key - * @param {Uint8Array} C - Encrypted and wrapped value derived from session key - * @param {Uint8Array} Q - Recipient public key - * @param {Uint8Array} d - Recipient private key - * @param {Uint8Array} fingerprint - Recipient fingerprint - * @returns {Promise} Value derived from session key. - * @async - */ -async function decrypt$3(oid, kdfParams, V, C, Q, d, fingerprint) { - const curve = new Curve(oid); - const { sharedKey } = await genPrivateEphemeralKey(curve, V, Q, d); - const param = buildEcdhParam(enums.publicKey.ecdh, oid, kdfParams, fingerprint); - const { keySize } = getCipher(kdfParams.cipher); - let err; - for (let i = 0; i < 3; i++) { - try { - // Work around old go crypto bug and old OpenPGP.js bug, respectively. - const Z = await kdf(kdfParams.hash, sharedKey, keySize, param, i === 1, i === 2); - return decode$1(unwrap(Z, C)); - } catch (e) { - err = e; - } - } - throw err; -} - -/** - * Generate ECDHE secret from private key and public part of ephemeral key using webCrypto - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} V - Public part of ephemeral key - * @param {Uint8Array} Q - Recipient public key - * @param {Uint8Array} d - Recipient private key - * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ -async function webPrivateEphemeralKey(curve, V, Q, d) { - const recipient = privateToJWK$1(curve.payloadSize, curve.web.web, Q, d); - let privateKey = webCrypto$8.importKey( - 'jwk', - recipient, - { - name: 'ECDH', - namedCurve: curve.web.web - }, - true, - ['deriveKey', 'deriveBits'] - ); - const jwk = rawPublicToJWK(curve.payloadSize, curve.web.web, V); - let sender = webCrypto$8.importKey( - 'jwk', - jwk, - { - name: 'ECDH', - namedCurve: curve.web.web - }, - true, - [] - ); - [privateKey, sender] = await Promise.all([privateKey, sender]); - let S = webCrypto$8.deriveBits( - { - name: 'ECDH', - namedCurve: curve.web.web, - public: sender - }, - privateKey, - curve.web.sharedSize - ); - let secret = webCrypto$8.exportKey( - 'jwk', - privateKey - ); - [S, secret] = await Promise.all([S, secret]); - const sharedKey = new Uint8Array(S); - const secretKey = b64ToUint8Array(secret.d); - return { secretKey, sharedKey }; -} - -/** - * Generate ECDHE ephemeral key and secret from public key using webCrypto - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} Q - Recipient public key - * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ -async function webPublicEphemeralKey(curve, Q) { - const jwk = rawPublicToJWK(curve.payloadSize, curve.web.web, Q); - let keyPair = webCrypto$8.generateKey( - { - name: 'ECDH', - namedCurve: curve.web.web - }, - true, - ['deriveKey', 'deriveBits'] - ); - let recipient = webCrypto$8.importKey( - 'jwk', - jwk, - { - name: 'ECDH', - namedCurve: curve.web.web - }, - false, - [] - ); - [keyPair, recipient] = await Promise.all([keyPair, recipient]); - let s = webCrypto$8.deriveBits( - { - name: 'ECDH', - namedCurve: curve.web.web, - public: recipient - }, - keyPair.privateKey, - curve.web.sharedSize - ); - let p = webCrypto$8.exportKey( - 'jwk', - keyPair.publicKey - ); - [s, p] = await Promise.all([s, p]); - const sharedKey = new Uint8Array(s); - const publicKey = new Uint8Array(jwkToRawPublic(p)); - return { publicKey, sharedKey }; -} - -/** - * Generate ECDHE secret from private key and public part of ephemeral key using indutny/elliptic - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} V - Public part of ephemeral key - * @param {Uint8Array} d - Recipient private key - * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ -async function ellipticPrivateEphemeralKey(curve, V, d) { - const indutnyCurve = await getIndutnyCurve(curve.name); - V = keyFromPublic(indutnyCurve, V); - d = keyFromPrivate(indutnyCurve, d); - const secretKey = new Uint8Array(d.getPrivate()); - const S = d.derive(V.getPublic()); - const len = indutnyCurve.curve.p.byteLength(); - const sharedKey = S.toArrayLike(Uint8Array, 'be', len); - return { secretKey, sharedKey }; -} - -/** - * Generate ECDHE ephemeral key and secret from public key using indutny/elliptic - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} Q - Recipient public key - * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ -async function ellipticPublicEphemeralKey(curve, Q) { - const indutnyCurve = await getIndutnyCurve(curve.name); - const v = await curve.genKeyPair(); - Q = keyFromPublic(indutnyCurve, Q); - const V = keyFromPrivate(indutnyCurve, v.privateKey); - const publicKey = v.publicKey; - const S = V.derive(Q.getPublic()); - const len = indutnyCurve.curve.p.byteLength(); - const sharedKey = S.toArrayLike(Uint8Array, 'be', len); - return { publicKey, sharedKey }; -} - -/** - * Generate ECDHE secret from private key and public part of ephemeral key using nodeCrypto - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} V - Public part of ephemeral key - * @param {Uint8Array} d - Recipient private key - * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ -async function nodePrivateEphemeralKey(curve, V, d) { - const recipient = nodeCrypto$9.createECDH(curve.node.node); - recipient.setPrivateKey(d); - const sharedKey = new Uint8Array(recipient.computeSecret(V)); - const secretKey = new Uint8Array(recipient.getPrivateKey()); - return { secretKey, sharedKey }; -} - -/** - * Generate ECDHE ephemeral key and secret from public key using nodeCrypto - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} Q - Recipient public key - * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ -async function nodePublicEphemeralKey(curve, Q) { - const sender = nodeCrypto$9.createECDH(curve.node.node); - sender.generateKeys(); - const sharedKey = new Uint8Array(sender.computeSecret(Q)); - const publicKey = new Uint8Array(sender.getPublicKey()); - return { publicKey, sharedKey }; -} - -var ecdh = /*#__PURE__*/Object.freeze({ - __proto__: null, - validateParams: validateParams$5, - encrypt: encrypt$3, - decrypt: decrypt$3 -}); - -// OpenPGP.js - An OpenPGP implementation in javascript - -var elliptic = /*#__PURE__*/Object.freeze({ - __proto__: null, - Curve: Curve, - ecdh: ecdh, - ecdsa: ecdsa, - eddsa: eddsa, - generate: generate$1, - getPreferredHashAlgo: getPreferredHashAlgo -}); - -// GPG4Browsers - An OpenPGP implementation in javascript - -/* - TODO regarding the hash function, read: - https://tools.ietf.org/html/rfc4880#section-13.6 - https://tools.ietf.org/html/rfc4880#section-14 -*/ - -/** - * DSA Sign function - * @param {Integer} hashAlgo - * @param {Uint8Array} hashed - * @param {Uint8Array} g - * @param {Uint8Array} p - * @param {Uint8Array} q - * @param {Uint8Array} x - * @returns {Promise<{ r: Uint8Array, s: Uint8Array }>} - * @async - */ -async function sign$3(hashAlgo, hashed, g, p, q, x) { - const BigInteger = await util.getBigInteger(); - const one = new BigInteger(1); - p = new BigInteger(p); - q = new BigInteger(q); - g = new BigInteger(g); - x = new BigInteger(x); - - let k; - let r; - let s; - let t; - g = g.mod(p); - x = x.mod(q); - // If the output size of the chosen hash is larger than the number of - // bits of q, the hash result is truncated to fit by taking the number - // of leftmost bits equal to the number of bits of q. This (possibly - // truncated) hash function result is treated as a number and used - // directly in the DSA signature algorithm. - const h = new BigInteger(hashed.subarray(0, q.byteLength())).mod(q); - // FIPS-186-4, section 4.6: - // The values of r and s shall be checked to determine if r = 0 or s = 0. - // If either r = 0 or s = 0, a new value of k shall be generated, and the - // signature shall be recalculated. It is extremely unlikely that r = 0 - // or s = 0 if signatures are generated properly. - while (true) { - // See Appendix B here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - k = await getRandomBigInteger(one, q); // returns in [1, q-1] - r = g.modExp(k, p).imod(q); // (g**k mod p) mod q - if (r.isZero()) { - continue; - } - const xr = x.mul(r).imod(q); - t = h.add(xr).imod(q); // H(m) + x*r mod q - s = k.modInv(q).imul(t).imod(q); // k**-1 * (H(m) + x*r) mod q - if (s.isZero()) { - continue; - } - break; - } - return { - r: r.toUint8Array('be', q.byteLength()), - s: s.toUint8Array('be', q.byteLength()) - }; -} - -/** - * DSA Verify function - * @param {Integer} hashAlgo - * @param {Uint8Array} r - * @param {Uint8Array} s - * @param {Uint8Array} hashed - * @param {Uint8Array} g - * @param {Uint8Array} p - * @param {Uint8Array} q - * @param {Uint8Array} y - * @returns {boolean} - * @async - */ -async function verify$3(hashAlgo, r, s, hashed, g, p, q, y) { - const BigInteger = await util.getBigInteger(); - const zero = new BigInteger(0); - r = new BigInteger(r); - s = new BigInteger(s); - - p = new BigInteger(p); - q = new BigInteger(q); - g = new BigInteger(g); - y = new BigInteger(y); - - if (r.lte(zero) || r.gte(q) || - s.lte(zero) || s.gte(q)) { - util.printDebug('invalid DSA Signature'); - return false; - } - const h = new BigInteger(hashed.subarray(0, q.byteLength())).imod(q); - const w = s.modInv(q); // s**-1 mod q - if (w.isZero()) { - util.printDebug('invalid DSA Signature'); - return false; - } - - g = g.mod(p); - y = y.mod(p); - const u1 = h.mul(w).imod(q); // H(m) * w mod q - const u2 = r.mul(w).imod(q); // r * w mod q - const t1 = g.modExp(u1, p); // g**u1 mod p - const t2 = y.modExp(u2, p); // y**u2 mod p - const v = t1.mul(t2).imod(p).imod(q); // (g**u1 * y**u2 mod p) mod q - return v.equal(r); -} - -/** - * Validate DSA parameters - * @param {Uint8Array} p - DSA prime - * @param {Uint8Array} q - DSA group order - * @param {Uint8Array} g - DSA sub-group generator - * @param {Uint8Array} y - DSA public key - * @param {Uint8Array} x - DSA private key - * @returns {Promise} Whether params are valid. - * @async - */ -async function validateParams$6(p, q, g, y, x) { - const BigInteger = await util.getBigInteger(); - p = new BigInteger(p); - q = new BigInteger(q); - g = new BigInteger(g); - y = new BigInteger(y); - const one = new BigInteger(1); - // Check that 1 < g < p - if (g.lte(one) || g.gte(p)) { - return false; - } - - /** - * Check that subgroup order q divides p-1 - */ - if (!p.dec().mod(q).isZero()) { - return false; - } - - /** - * g has order q - * Check that g ** q = 1 mod p - */ - if (!g.modExp(q, p).isOne()) { - return false; - } - - /** - * Check q is large and probably prime (we mainly want to avoid small factors) - */ - const qSize = new BigInteger(q.bitLength()); - const n150 = new BigInteger(150); - if (qSize.lt(n150) || !(await isProbablePrime(q, null, 32))) { - return false; - } - - /** - * Re-derive public key y' = g ** x mod p - * Expect y == y' - * - * Blinded exponentiation computes g**{rq + x} to compare to y - */ - x = new BigInteger(x); - const two = new BigInteger(2); - const r = await getRandomBigInteger(two.leftShift(qSize.dec()), two.leftShift(qSize)); // draw r of same size as q - const rqx = q.mul(r).add(x); - if (!y.equal(g.modExp(rqx, p))) { - return false; - } - - return true; -} - -var dsa = /*#__PURE__*/Object.freeze({ - __proto__: null, - sign: sign$3, - verify: verify$3, - validateParams: validateParams$6 -}); - -/** - * @fileoverview Asymmetric cryptography functions - * @module crypto/public_key - * @private - */ - -var publicKey = { - /** @see module:crypto/public_key/rsa */ - rsa: rsa, - /** @see module:crypto/public_key/elgamal */ - elgamal: elgamal, - /** @see module:crypto/public_key/elliptic */ - elliptic: elliptic, - /** @see module:crypto/public_key/dsa */ - dsa: dsa, - /** @see tweetnacl */ - nacl: naclFastLight -}; - -/** - * @fileoverview Provides functions for asymmetric signing and signature verification - * @module crypto/signature - * @private - */ - -/** - * Parse signature in binary form to get the parameters. - * The returned values are only padded for EdDSA, since in the other cases their expected length - * depends on the key params, hence we delegate the padding to the signature verification function. - * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} - * See {@link https://tools.ietf.org/html/rfc4880#section-5.2.2|RFC 4880 5.2.2.} - * @param {module:enums.publicKey} algo - Public key algorithm - * @param {Uint8Array} signature - Data for which the signature was created - * @returns {Promise} True if signature is valid. - * @async - */ -function parseSignatureParams(algo, signature) { - let read = 0; - switch (algo) { - // Algorithm-Specific Fields for RSA signatures: - // - MPI of RSA signature value m**d mod n. - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaSign: { - const s = util.readMPI(signature.subarray(read)); - // The signature needs to be the same length as the public key modulo n. - // We pad s on signature verification, where we have access to n. - return { s }; - } - // Algorithm-Specific Fields for DSA or ECDSA signatures: - // - MPI of DSA or ECDSA value r. - // - MPI of DSA or ECDSA value s. - case enums.publicKey.dsa: - case enums.publicKey.ecdsa: - { - const r = util.readMPI(signature.subarray(read)); read += r.length + 2; - const s = util.readMPI(signature.subarray(read)); - return { r, s }; - } - // Algorithm-Specific Fields for EdDSA signatures: - // - MPI of an EC point r. - // - EdDSA value s, in MPI, in the little endian representation - case enums.publicKey.eddsa: { - // When parsing little-endian MPI data, we always need to left-pad it, as done with big-endian values: - // https://www.ietf.org/archive/id/draft-ietf-openpgp-rfc4880bis-10.html#section-3.2-9 - let r = util.readMPI(signature.subarray(read)); read += r.length + 2; - r = util.leftPad(r, 32); - let s = util.readMPI(signature.subarray(read)); - s = util.leftPad(s, 32); - return { r, s }; - } - default: - throw new Error('Invalid signature algorithm.'); - } -} - -/** - * Verifies the signature provided for data using specified algorithms and public key parameters. - * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} - * and {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4} - * for public key and hash algorithms. - * @param {module:enums.publicKey} algo - Public key algorithm - * @param {module:enums.hash} hashAlgo - Hash algorithm - * @param {Object} signature - Named algorithm-specific signature parameters - * @param {Object} publicParams - Algorithm-specific public key parameters - * @param {Uint8Array} data - Data for which the signature was created - * @param {Uint8Array} hashed - The hashed data - * @returns {Promise} True if signature is valid. - * @async - */ -async function verify$4(algo, hashAlgo, signature, publicParams, data, hashed) { - switch (algo) { - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaSign: { - const { n, e } = publicParams; - const s = util.leftPad(signature.s, n.length); // padding needed for webcrypto and node crypto - return publicKey.rsa.verify(hashAlgo, data, s, n, e, hashed); - } - case enums.publicKey.dsa: { - const { g, p, q, y } = publicParams; - const { r, s } = signature; // no need to pad, since we always handle them as BigIntegers - return publicKey.dsa.verify(hashAlgo, r, s, hashed, g, p, q, y); - } - case enums.publicKey.ecdsa: { - const { oid, Q } = publicParams; - const curveSize = new publicKey.elliptic.Curve(oid).payloadSize; - // padding needed for webcrypto - const r = util.leftPad(signature.r, curveSize); - const s = util.leftPad(signature.s, curveSize); - return publicKey.elliptic.ecdsa.verify(oid, hashAlgo, { r, s }, data, Q, hashed); - } - case enums.publicKey.eddsa: { - const { oid, Q } = publicParams; - // signature already padded on parsing - return publicKey.elliptic.eddsa.verify(oid, hashAlgo, signature, data, Q, hashed); - } - default: - throw new Error('Invalid signature algorithm.'); - } -} - -/** - * Creates a signature on data using specified algorithms and private key parameters. - * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} - * and {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4} - * for public key and hash algorithms. - * @param {module:enums.publicKey} algo - Public key algorithm - * @param {module:enums.hash} hashAlgo - Hash algorithm - * @param {Object} publicKeyParams - Algorithm-specific public and private key parameters - * @param {Object} privateKeyParams - Algorithm-specific public and private key parameters - * @param {Uint8Array} data - Data to be signed - * @param {Uint8Array} hashed - The hashed data - * @returns {Promise} Signature Object containing named signature parameters. - * @async - */ -async function sign$4(algo, hashAlgo, publicKeyParams, privateKeyParams, data, hashed) { - if (!publicKeyParams || !privateKeyParams) { - throw new Error('Missing key parameters'); - } - switch (algo) { - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaSign: { - const { n, e } = publicKeyParams; - const { d, p, q, u } = privateKeyParams; - const s = await publicKey.rsa.sign(hashAlgo, data, n, e, d, p, q, u, hashed); - return { s }; - } - case enums.publicKey.dsa: { - const { g, p, q } = publicKeyParams; - const { x } = privateKeyParams; - return publicKey.dsa.sign(hashAlgo, hashed, g, p, q, x); - } - case enums.publicKey.elgamal: { - throw new Error('Signing with Elgamal is not defined in the OpenPGP standard.'); - } - case enums.publicKey.ecdsa: { - const { oid, Q } = publicKeyParams; - const { d } = privateKeyParams; - return publicKey.elliptic.ecdsa.sign(oid, hashAlgo, data, Q, d, hashed); - } - case enums.publicKey.eddsa: { - const { oid, Q } = publicKeyParams; - const { seed } = privateKeyParams; - return publicKey.elliptic.eddsa.sign(oid, hashAlgo, data, Q, seed, hashed); - } - default: - throw new Error('Invalid signature algorithm.'); - } -} - -var signature = /*#__PURE__*/Object.freeze({ - __proto__: null, - parseSignatureParams: parseSignatureParams, - verify: verify$4, - sign: sign$4 -}); - -/** - * @fileoverview Provides access to all cryptographic primitives used in OpenPGP.js - * @see module:crypto/crypto - * @see module:crypto/signature - * @see module:crypto/public_key - * @see module:crypto/cipher - * @see module:crypto/random - * @see module:crypto/hash - * @module crypto - * @private - */ - -// TODO move cfb and gcm to cipher -const mod = { - /** @see module:crypto/cipher */ - cipher: cipher, - /** @see module:crypto/hash */ - hash: hash, - /** @see module:crypto/mode */ - mode: mode, - /** @see module:crypto/public_key */ - publicKey: publicKey, - /** @see module:crypto/signature */ - signature: signature, - /** @see module:crypto/random */ - random: random, - /** @see module:crypto/pkcs1 */ - pkcs1: pkcs1, - /** @see module:crypto/pkcs5 */ - pkcs5: pkcs5, - /** @see module:crypto/aes_kw */ - aesKW: aesKW -}; - -Object.assign(mod, crypto$1); - -var TYPED_OK = typeof Uint8Array !== "undefined" && - typeof Uint16Array !== "undefined" && - typeof Int32Array !== "undefined"; - - -// reduce buffer size, avoiding mem copy -function shrinkBuf(buf, size) { - if (buf.length === size) { - return buf; - } - if (buf.subarray) { - return buf.subarray(0, size); - } - buf.length = size; - return buf; -} - - -const fnTyped = { - arraySet: function (dest, src, src_offs, len, dest_offs) { - if (src.subarray && dest.subarray) { - dest.set(src.subarray(src_offs, src_offs + len), dest_offs); - return; - } - // Fallback to ordinary array - for (let i = 0; i < len; i++) { - dest[dest_offs + i] = src[src_offs + i]; - } - }, - // Join array of chunks to single array. - flattenChunks: function (chunks) { - let i, l, len, pos, chunk; - - // calculate data length - len = 0; - for (i = 0, l = chunks.length; i < l; i++) { - len += chunks[i].length; - } - - // join chunks - const result = new Uint8Array(len); - pos = 0; - for (i = 0, l = chunks.length; i < l; i++) { - chunk = chunks[i]; - result.set(chunk, pos); - pos += chunk.length; - } - - return result; - } -}; - -const fnUntyped = { - arraySet: function (dest, src, src_offs, len, dest_offs) { - for (let i = 0; i < len; i++) { - dest[dest_offs + i] = src[src_offs + i]; - } - }, - // Join array of chunks to single array. - flattenChunks: function (chunks) { - return [].concat.apply([], chunks); - } -}; - - -// Enable/Disable typed arrays use, for testing -// - -let Buf8 = TYPED_OK ? Uint8Array : Array; -let Buf16 = TYPED_OK ? Uint16Array : Array; -let Buf32 = TYPED_OK ? Int32Array : Array; -let flattenChunks = TYPED_OK ? fnTyped.flattenChunks : fnUntyped.flattenChunks; -let arraySet = TYPED_OK ? fnTyped.arraySet : fnUntyped.arraySet; - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -/* Allowed flush values; see deflate() and inflate() below for details */ -const Z_NO_FLUSH = 0; -const Z_PARTIAL_FLUSH = 1; -const Z_SYNC_FLUSH = 2; -const Z_FULL_FLUSH = 3; -const Z_FINISH = 4; -const Z_BLOCK = 5; -const Z_TREES = 6; - -/* Return codes for the compression/decompression functions. Negative values - * are errors, positive values are used for special but normal events. - */ -const Z_OK = 0; -const Z_STREAM_END = 1; -const Z_NEED_DICT = 2; -const Z_STREAM_ERROR = -2; -const Z_DATA_ERROR = -3; -//export const Z_MEM_ERROR = -4; -const Z_BUF_ERROR = -5; -const Z_DEFAULT_COMPRESSION = -1; - - -const Z_FILTERED = 1; -const Z_HUFFMAN_ONLY = 2; -const Z_RLE = 3; -const Z_FIXED = 4; -const Z_DEFAULT_STRATEGY = 0; - -/* Possible values of the data_type field (though see inflate()) */ -const Z_BINARY = 0; -const Z_TEXT = 1; -//export const Z_ASCII = 1; // = Z_TEXT (deprecated) -const Z_UNKNOWN = 2; - -/* The deflate compression method */ -const Z_DEFLATED = 8; -//export const Z_NULL = null // Use -1 or null inline, depending on var type - -/*============================================================================*/ - - -function zero$1(buf) { - let len = buf.length; while (--len >= 0) { - buf[len] = 0; - } -} - -// From zutil.h - -const STORED_BLOCK = 0; -const STATIC_TREES = 1; -const DYN_TREES = 2; -/* The three kinds of block type */ - -const MIN_MATCH = 3; -const MAX_MATCH = 258; -/* The minimum and maximum match lengths */ - -// From deflate.h -/* =========================================================================== - * Internal compression state. - */ - -const LENGTH_CODES = 29; -/* number of length codes, not counting the special END_BLOCK code */ - -const LITERALS = 256; -/* number of literal bytes 0..255 */ - -const L_CODES = LITERALS + 1 + LENGTH_CODES; -/* number of Literal or Length codes, including the END_BLOCK code */ - -const D_CODES = 30; -/* number of distance codes */ - -const BL_CODES = 19; -/* number of codes used to transfer the bit lengths */ - -const HEAP_SIZE = 2 * L_CODES + 1; -/* maximum heap size */ - -const MAX_BITS = 15; -/* All codes must not exceed MAX_BITS bits */ - -const Buf_size = 16; -/* size of bit buffer in bi_buf */ - - -/* =========================================================================== - * Constants - */ - -const MAX_BL_BITS = 7; -/* Bit length codes must not exceed MAX_BL_BITS bits */ - -const END_BLOCK = 256; -/* end of block literal code */ - -const REP_3_6 = 16; -/* repeat previous bit length 3-6 times (2 bits of repeat count) */ - -const REPZ_3_10 = 17; -/* repeat a zero length 3-10 times (3 bits of repeat count) */ - -const REPZ_11_138 = 18; -/* repeat a zero length 11-138 times (7 bits of repeat count) */ - -/* eslint-disable comma-spacing,array-bracket-spacing */ -const extra_lbits = /* extra bits for each length code */ - [0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0]; - -const extra_dbits = /* extra bits for each distance code */ - [0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13]; - -const extra_blbits = /* extra bits for each bit length code */ - [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7]; - -const bl_order = - [16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]; -/* eslint-enable comma-spacing,array-bracket-spacing */ - -/* The lengths of the bit length codes are sent in order of decreasing - * probability, to avoid transmitting the lengths for unused bit length codes. - */ - -/* =========================================================================== - * Local data. These are initialized only once. - */ - -// We pre-fill arrays with 0 to avoid uninitialized gaps - -const DIST_CODE_LEN = 512; /* see definition of array dist_code below */ - -// !!!! Use flat array instead of structure, Freq = i*2, Len = i*2+1 -const static_ltree = new Array((L_CODES + 2) * 2); -zero$1(static_ltree); -/* The static literal tree. Since the bit lengths are imposed, there is no - * need for the L_CODES extra codes used during heap construction. However - * The codes 286 and 287 are needed to build a canonical tree (see _tr_init - * below). - */ - -const static_dtree = new Array(D_CODES * 2); -zero$1(static_dtree); -/* The static distance tree. (Actually a trivial tree since all codes use - * 5 bits.) - */ - -const _dist_code = new Array(DIST_CODE_LEN); -zero$1(_dist_code); -/* Distance codes. The first 256 values correspond to the distances - * 3 .. 258, the last 256 values correspond to the top 8 bits of - * the 15 bit distances. - */ - -const _length_code = new Array(MAX_MATCH - MIN_MATCH + 1); -zero$1(_length_code); -/* length code for each normalized match length (0 == MIN_MATCH) */ - -const base_length = new Array(LENGTH_CODES); -zero$1(base_length); -/* First normalized length for each code (0 = MIN_MATCH) */ - -const base_dist = new Array(D_CODES); -zero$1(base_dist); -/* First normalized distance for each code (0 = distance of 1) */ - - -function StaticTreeDesc(static_tree, extra_bits, extra_base, elems, max_length) { - - this.static_tree = static_tree; /* static tree or NULL */ - this.extra_bits = extra_bits; /* extra bits for each code or NULL */ - this.extra_base = extra_base; /* base index for extra_bits */ - this.elems = elems; /* max number of elements in the tree */ - this.max_length = max_length; /* max bit length for the codes */ - - // show if `static_tree` has data or dummy - needed for monomorphic objects - this.has_stree = static_tree && static_tree.length; -} - - -let static_l_desc; -let static_d_desc; -let static_bl_desc; - - -function TreeDesc(dyn_tree, stat_desc) { - this.dyn_tree = dyn_tree; /* the dynamic tree */ - this.max_code = 0; /* largest code with non zero frequency */ - this.stat_desc = stat_desc; /* the corresponding static tree */ -} - - - -function d_code(dist) { - return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)]; -} - - -/* =========================================================================== - * Output a short LSB first on the stream. - * IN assertion: there is enough room in pendingBuf. - */ -function put_short(s, w) { -// put_byte(s, (uch)((w) & 0xff)); -// put_byte(s, (uch)((ush)(w) >> 8)); - s.pending_buf[s.pending++] = w & 0xff; - s.pending_buf[s.pending++] = w >>> 8 & 0xff; -} - - -/* =========================================================================== - * Send a value on a given number of bits. - * IN assertion: length <= 16 and value fits in length bits. - */ -function send_bits(s, value, length) { - if (s.bi_valid > Buf_size - length) { - s.bi_buf |= value << s.bi_valid & 0xffff; - put_short(s, s.bi_buf); - s.bi_buf = value >> Buf_size - s.bi_valid; - s.bi_valid += length - Buf_size; - } else { - s.bi_buf |= value << s.bi_valid & 0xffff; - s.bi_valid += length; - } -} - - -function send_code(s, c, tree) { - send_bits(s, tree[c * 2]/*.Code*/, tree[c * 2 + 1]/*.Len*/); -} - - -/* =========================================================================== - * Reverse the first len bits of a code, using straightforward code (a faster - * method would use a table) - * IN assertion: 1 <= len <= 15 - */ -function bi_reverse(code, len) { - let res = 0; - do { - res |= code & 1; - code >>>= 1; - res <<= 1; - } while (--len > 0); - return res >>> 1; -} - - -/* =========================================================================== - * Flush the bit buffer, keeping at most 7 bits in it. - */ -function bi_flush(s) { - if (s.bi_valid === 16) { - put_short(s, s.bi_buf); - s.bi_buf = 0; - s.bi_valid = 0; - - } else if (s.bi_valid >= 8) { - s.pending_buf[s.pending++] = s.bi_buf & 0xff; - s.bi_buf >>= 8; - s.bi_valid -= 8; - } -} - - -/* =========================================================================== - * Compute the optimal bit lengths for a tree and update the total bit length - * for the current block. - * IN assertion: the fields freq and dad are set, heap[heap_max] and - * above are the tree nodes sorted by increasing frequency. - * OUT assertions: the field len is set to the optimal bit length, the - * array bl_count contains the frequencies for each bit length. - * The length opt_len is updated; static_len is also updated if stree is - * not null. - */ -function gen_bitlen(s, desc) -// deflate_state *s; -// tree_desc *desc; /* the tree descriptor */ -{ - const tree = desc.dyn_tree; - const max_code = desc.max_code; - const stree = desc.stat_desc.static_tree; - const has_stree = desc.stat_desc.has_stree; - const extra = desc.stat_desc.extra_bits; - const base = desc.stat_desc.extra_base; - const max_length = desc.stat_desc.max_length; - let h; /* heap index */ - let n, m; /* iterate over the tree elements */ - let bits; /* bit length */ - let xbits; /* extra bits */ - let f; /* frequency */ - let overflow = 0; /* number of elements with bit length too large */ - - for (bits = 0; bits <= MAX_BITS; bits++) { - s.bl_count[bits] = 0; - } - - /* In a first pass, compute the optimal bit lengths (which may - * overflow in the case of the bit length tree). - */ - tree[s.heap[s.heap_max] * 2 + 1]/*.Len*/ = 0; /* root of the heap */ - - for (h = s.heap_max + 1; h < HEAP_SIZE; h++) { - n = s.heap[h]; - bits = tree[tree[n * 2 + 1]/*.Dad*/ * 2 + 1]/*.Len*/ + 1; - if (bits > max_length) { - bits = max_length; - overflow++; - } - tree[n * 2 + 1]/*.Len*/ = bits; - /* We overwrite tree[n].Dad which is no longer needed */ - - if (n > max_code) { - continue; - } /* not a leaf node */ - - s.bl_count[bits]++; - xbits = 0; - if (n >= base) { - xbits = extra[n - base]; - } - f = tree[n * 2]/*.Freq*/; - s.opt_len += f * (bits + xbits); - if (has_stree) { - s.static_len += f * (stree[n * 2 + 1]/*.Len*/ + xbits); - } - } - if (overflow === 0) { - return; - } - - // Trace((stderr,"\nbit length overflow\n")); - /* This happens for example on obj2 and pic of the Calgary corpus */ - - /* Find the first bit length which could increase: */ - do { - bits = max_length - 1; - while (s.bl_count[bits] === 0) { - bits--; - } - s.bl_count[bits]--; /* move one leaf down the tree */ - s.bl_count[bits + 1] += 2; /* move one overflow item as its brother */ - s.bl_count[max_length]--; - /* The brother of the overflow item also moves one step up, - * but this does not affect bl_count[max_length] - */ - overflow -= 2; - } while (overflow > 0); - - /* Now recompute all bit lengths, scanning in increasing frequency. - * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all - * lengths instead of fixing only the wrong ones. This idea is taken - * from 'ar' written by Haruhiko Okumura.) - */ - for (bits = max_length; bits !== 0; bits--) { - n = s.bl_count[bits]; - while (n !== 0) { - m = s.heap[--h]; - if (m > max_code) { - continue; - } - if (tree[m * 2 + 1]/*.Len*/ !== bits) { - // Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); - s.opt_len += (bits - tree[m * 2 + 1]/*.Len*/) * tree[m * 2]/*.Freq*/; - tree[m * 2 + 1]/*.Len*/ = bits; - } - n--; - } - } -} - - -/* =========================================================================== - * Generate the codes for a given tree and bit counts (which need not be - * optimal). - * IN assertion: the array bl_count contains the bit length statistics for - * the given tree and the field len is set for all tree elements. - * OUT assertion: the field code is set for all tree elements of non - * zero code length. - */ -function gen_codes(tree, max_code, bl_count) -// ct_data *tree; /* the tree to decorate */ -// int max_code; /* largest code with non zero frequency */ -// ushf *bl_count; /* number of codes at each bit length */ -{ - const next_code = new Array(MAX_BITS + 1); /* next code value for each bit length */ - let code = 0; /* running code value */ - let bits; /* bit index */ - let n; /* code index */ - - /* The distribution counts are first used to generate the code values - * without bit reversal. - */ - for (bits = 1; bits <= MAX_BITS; bits++) { - next_code[bits] = code = code + bl_count[bits - 1] << 1; - } - /* Check that the bit counts in bl_count are consistent. The last code - * must be all ones. - */ - //Assert (code + bl_count[MAX_BITS]-1 == (1< length code (0..28) */ - length = 0; - for (code = 0; code < LENGTH_CODES - 1; code++) { - base_length[code] = length; - for (n = 0; n < 1 << extra_lbits[code]; n++) { - _length_code[length++] = code; - } - } - //Assert (length == 256, "tr_static_init: length != 256"); - /* Note that the length 255 (match length 258) can be represented - * in two different ways: code 284 + 5 bits or code 285, so we - * overwrite length_code[255] to use the best encoding: - */ - _length_code[length - 1] = code; - - /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ - dist = 0; - for (code = 0; code < 16; code++) { - base_dist[code] = dist; - for (n = 0; n < 1 << extra_dbits[code]; n++) { - _dist_code[dist++] = code; - } - } - //Assert (dist == 256, "tr_static_init: dist != 256"); - dist >>= 7; /* from now on, all distances are divided by 128 */ - for (; code < D_CODES; code++) { - base_dist[code] = dist << 7; - for (n = 0; n < 1 << extra_dbits[code] - 7; n++) { - _dist_code[256 + dist++] = code; - } - } - //Assert (dist == 256, "tr_static_init: 256+dist != 512"); - - /* Construct the codes of the static literal tree */ - for (bits = 0; bits <= MAX_BITS; bits++) { - bl_count[bits] = 0; - } - - n = 0; - while (n <= 143) { - static_ltree[n * 2 + 1]/*.Len*/ = 8; - n++; - bl_count[8]++; - } - while (n <= 255) { - static_ltree[n * 2 + 1]/*.Len*/ = 9; - n++; - bl_count[9]++; - } - while (n <= 279) { - static_ltree[n * 2 + 1]/*.Len*/ = 7; - n++; - bl_count[7]++; - } - while (n <= 287) { - static_ltree[n * 2 + 1]/*.Len*/ = 8; - n++; - bl_count[8]++; - } - /* Codes 286 and 287 do not exist, but we must include them in the - * tree construction to get a canonical Huffman tree (longest code - * all ones) - */ - gen_codes(static_ltree, L_CODES + 1, bl_count); - - /* The static distance tree is trivial: */ - for (n = 0; n < D_CODES; n++) { - static_dtree[n * 2 + 1]/*.Len*/ = 5; - static_dtree[n * 2]/*.Code*/ = bi_reverse(n, 5); - } - - // Now data ready and we can init static trees - static_l_desc = new StaticTreeDesc(static_ltree, extra_lbits, LITERALS + 1, L_CODES, MAX_BITS); - static_d_desc = new StaticTreeDesc(static_dtree, extra_dbits, 0, D_CODES, MAX_BITS); - static_bl_desc = new StaticTreeDesc(new Array(0), extra_blbits, 0, BL_CODES, MAX_BL_BITS); - - //static_init_done = true; -} - - -/* =========================================================================== - * Initialize a new block. - */ -function init_block(s) { - let n; /* iterates over tree elements */ - - /* Initialize the trees. */ - for (n = 0; n < L_CODES; n++) { - s.dyn_ltree[n * 2]/*.Freq*/ = 0; - } - for (n = 0; n < D_CODES; n++) { - s.dyn_dtree[n * 2]/*.Freq*/ = 0; - } - for (n = 0; n < BL_CODES; n++) { - s.bl_tree[n * 2]/*.Freq*/ = 0; - } - - s.dyn_ltree[END_BLOCK * 2]/*.Freq*/ = 1; - s.opt_len = s.static_len = 0; - s.last_lit = s.matches = 0; -} - - -/* =========================================================================== - * Flush the bit buffer and align the output on a byte boundary - */ -function bi_windup(s) { - if (s.bi_valid > 8) { - put_short(s, s.bi_buf); - } else if (s.bi_valid > 0) { - //put_byte(s, (Byte)s->bi_buf); - s.pending_buf[s.pending++] = s.bi_buf; - } - s.bi_buf = 0; - s.bi_valid = 0; -} - -/* =========================================================================== - * Copy a stored block, storing first the length and its - * one's complement if requested. - */ -function copy_block(s, buf, len, header) -//DeflateState *s; -//charf *buf; /* the input data */ -//unsigned len; /* its length */ -//int header; /* true if block header must be written */ -{ - bi_windup(s); /* align on byte boundary */ - - if (header) { - put_short(s, len); - put_short(s, ~len); - } - // while (len--) { - // put_byte(s, *buf++); - // } - arraySet(s.pending_buf, s.window, buf, len, s.pending); - s.pending += len; -} - -/* =========================================================================== - * Compares to subtrees, using the tree depth as tie breaker when - * the subtrees have equal frequency. This minimizes the worst case length. - */ -function smaller(tree, n, m, depth) { - const _n2 = n * 2; - const _m2 = m * 2; - return tree[_n2]/*.Freq*/ < tree[_m2]/*.Freq*/ || - tree[_n2]/*.Freq*/ === tree[_m2]/*.Freq*/ && depth[n] <= depth[m]; -} - -/* =========================================================================== - * Restore the heap property by moving down the tree starting at node k, - * exchanging a node with the smallest of its two sons if necessary, stopping - * when the heap property is re-established (each father smaller than its - * two sons). - */ -function pqdownheap(s, tree, k) -// deflate_state *s; -// ct_data *tree; /* the tree to restore */ -// int k; /* node to move down */ -{ - const v = s.heap[k]; - let j = k << 1; /* left son of k */ - while (j <= s.heap_len) { - /* Set j to the smallest of the two sons: */ - if (j < s.heap_len && - smaller(tree, s.heap[j + 1], s.heap[j], s.depth)) { - j++; - } - /* Exit if v is smaller than both sons */ - if (smaller(tree, v, s.heap[j], s.depth)) { - break; - } - - /* Exchange v with the smallest son */ - s.heap[k] = s.heap[j]; - k = j; - - /* And continue down the tree, setting j to the left son of k */ - j <<= 1; - } - s.heap[k] = v; -} - - -// inlined manually -// var SMALLEST = 1; - -/* =========================================================================== - * Send the block data compressed using the given Huffman trees - */ -function compress_block(s, ltree, dtree) -// deflate_state *s; -// const ct_data *ltree; /* literal tree */ -// const ct_data *dtree; /* distance tree */ -{ - let dist; /* distance of matched string */ - let lc; /* match length or unmatched char (if dist == 0) */ - let lx = 0; /* running index in l_buf */ - let code; /* the code to send */ - let extra; /* number of extra bits to send */ - - if (s.last_lit !== 0) { - do { - dist = s.pending_buf[s.d_buf + lx * 2] << 8 | s.pending_buf[s.d_buf + lx * 2 + 1]; - lc = s.pending_buf[s.l_buf + lx]; - lx++; - - if (dist === 0) { - send_code(s, lc, ltree); /* send a literal byte */ - //Tracecv(isgraph(lc), (stderr," '%c' ", lc)); - } else { - /* Here, lc is the match length - MIN_MATCH */ - code = _length_code[lc]; - send_code(s, code + LITERALS + 1, ltree); /* send the length code */ - extra = extra_lbits[code]; - if (extra !== 0) { - lc -= base_length[code]; - send_bits(s, lc, extra); /* send the extra length bits */ - } - dist--; /* dist is now the match distance - 1 */ - code = d_code(dist); - //Assert (code < D_CODES, "bad d_code"); - - send_code(s, code, dtree); /* send the distance code */ - extra = extra_dbits[code]; - if (extra !== 0) { - dist -= base_dist[code]; - send_bits(s, dist, extra); /* send the extra distance bits */ - } - } /* literal or match pair ? */ - - /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ - //Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, - // "pendingBuf overflow"); - - } while (lx < s.last_lit); - } - - send_code(s, END_BLOCK, ltree); -} - - -/* =========================================================================== - * Construct one Huffman tree and assigns the code bit strings and lengths. - * Update the total bit length for the current block. - * IN assertion: the field freq is set for all tree elements. - * OUT assertions: the fields len and code are set to the optimal bit length - * and corresponding code. The length opt_len is updated; static_len is - * also updated if stree is not null. The field max_code is set. - */ -function build_tree(s, desc) -// deflate_state *s; -// tree_desc *desc; /* the tree descriptor */ -{ - const tree = desc.dyn_tree; - const stree = desc.stat_desc.static_tree; - const has_stree = desc.stat_desc.has_stree; - const elems = desc.stat_desc.elems; - let n, m; /* iterate over heap elements */ - let max_code = -1; /* largest code with non zero frequency */ - let node; /* new node being created */ - - /* Construct the initial heap, with least frequent element in - * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. - * heap[0] is not used. - */ - s.heap_len = 0; - s.heap_max = HEAP_SIZE; - - for (n = 0; n < elems; n++) { - if (tree[n * 2]/*.Freq*/ !== 0) { - s.heap[++s.heap_len] = max_code = n; - s.depth[n] = 0; - - } else { - tree[n * 2 + 1]/*.Len*/ = 0; - } - } - - /* The pkzip format requires that at least one distance code exists, - * and that at least one bit should be sent even if there is only one - * possible code. So to avoid special checks later on we force at least - * two codes of non zero frequency. - */ - while (s.heap_len < 2) { - node = s.heap[++s.heap_len] = max_code < 2 ? ++max_code : 0; - tree[node * 2]/*.Freq*/ = 1; - s.depth[node] = 0; - s.opt_len--; - - if (has_stree) { - s.static_len -= stree[node * 2 + 1]/*.Len*/; - } - /* node is 0 or 1 so it does not have extra bits */ - } - desc.max_code = max_code; - - /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, - * establish sub-heaps of increasing lengths: - */ - for (n = s.heap_len >> 1/*int /2*/; n >= 1; n--) { - pqdownheap(s, tree, n); - } - - /* Construct the Huffman tree by repeatedly combining the least two - * frequent nodes. - */ - node = elems; /* next internal node of the tree */ - do { - //pqremove(s, tree, n); /* n = node of least frequency */ - /*** pqremove ***/ - n = s.heap[1/*SMALLEST*/]; - s.heap[1/*SMALLEST*/] = s.heap[s.heap_len--]; - pqdownheap(s, tree, 1/*SMALLEST*/); - /***/ - - m = s.heap[1/*SMALLEST*/]; /* m = node of next least frequency */ - - s.heap[--s.heap_max] = n; /* keep the nodes sorted by frequency */ - s.heap[--s.heap_max] = m; - - /* Create a new node father of n and m */ - tree[node * 2]/*.Freq*/ = tree[n * 2]/*.Freq*/ + tree[m * 2]/*.Freq*/; - s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1; - tree[n * 2 + 1]/*.Dad*/ = tree[m * 2 + 1]/*.Dad*/ = node; - - /* and insert the new node in the heap */ - s.heap[1/*SMALLEST*/] = node++; - pqdownheap(s, tree, 1/*SMALLEST*/); - - } while (s.heap_len >= 2); - - s.heap[--s.heap_max] = s.heap[1/*SMALLEST*/]; - - /* At this point, the fields freq and dad are set. We can now - * generate the bit lengths. - */ - gen_bitlen(s, desc); - - /* The field len is now set, we can generate the bit codes */ - gen_codes(tree, max_code, s.bl_count); -} - - -/* =========================================================================== - * Scan a literal or distance tree to determine the frequencies of the codes - * in the bit length tree. - */ -function scan_tree(s, tree, max_code) -// deflate_state *s; -// ct_data *tree; /* the tree to be scanned */ -// int max_code; /* and its largest code of non zero frequency */ -{ - let n; /* iterates over all tree elements */ - let prevlen = -1; /* last emitted length */ - let curlen; /* length of current code */ - - let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */ - - let count = 0; /* repeat count of the current code */ - let max_count = 7; /* max repeat count */ - let min_count = 4; /* min repeat count */ - - if (nextlen === 0) { - max_count = 138; - min_count = 3; - } - tree[(max_code + 1) * 2 + 1]/*.Len*/ = 0xffff; /* guard */ - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; - nextlen = tree[(n + 1) * 2 + 1]/*.Len*/; - - if (++count < max_count && curlen === nextlen) { - continue; - - } else if (count < min_count) { - s.bl_tree[curlen * 2]/*.Freq*/ += count; - - } else if (curlen !== 0) { - - if (curlen !== prevlen) { - s.bl_tree[curlen * 2]/*.Freq*/++; - } - s.bl_tree[REP_3_6 * 2]/*.Freq*/++; - - } else if (count <= 10) { - s.bl_tree[REPZ_3_10 * 2]/*.Freq*/++; - - } else { - s.bl_tree[REPZ_11_138 * 2]/*.Freq*/++; - } - - count = 0; - prevlen = curlen; - - if (nextlen === 0) { - max_count = 138; - min_count = 3; - - } else if (curlen === nextlen) { - max_count = 6; - min_count = 3; - - } else { - max_count = 7; - min_count = 4; - } - } -} - - -/* =========================================================================== - * Send a literal or distance tree in compressed form, using the codes in - * bl_tree. - */ -function send_tree(s, tree, max_code) -// deflate_state *s; -// ct_data *tree; /* the tree to be scanned */ -// int max_code; /* and its largest code of non zero frequency */ -{ - let n; /* iterates over all tree elements */ - let prevlen = -1; /* last emitted length */ - let curlen; /* length of current code */ - - let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */ - - let count = 0; /* repeat count of the current code */ - let max_count = 7; /* max repeat count */ - let min_count = 4; /* min repeat count */ - - /* tree[max_code+1].Len = -1; */ /* guard already set */ - if (nextlen === 0) { - max_count = 138; - min_count = 3; - } - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; - nextlen = tree[(n + 1) * 2 + 1]/*.Len*/; - - if (++count < max_count && curlen === nextlen) { - continue; - - } else if (count < min_count) { - do { - send_code(s, curlen, s.bl_tree); - } while (--count !== 0); - - } else if (curlen !== 0) { - if (curlen !== prevlen) { - send_code(s, curlen, s.bl_tree); - count--; - } - //Assert(count >= 3 && count <= 6, " 3_6?"); - send_code(s, REP_3_6, s.bl_tree); - send_bits(s, count - 3, 2); - - } else if (count <= 10) { - send_code(s, REPZ_3_10, s.bl_tree); - send_bits(s, count - 3, 3); - - } else { - send_code(s, REPZ_11_138, s.bl_tree); - send_bits(s, count - 11, 7); - } - - count = 0; - prevlen = curlen; - if (nextlen === 0) { - max_count = 138; - min_count = 3; - - } else if (curlen === nextlen) { - max_count = 6; - min_count = 3; - - } else { - max_count = 7; - min_count = 4; - } - } -} - - -/* =========================================================================== - * Construct the Huffman tree for the bit lengths and return the index in - * bl_order of the last bit length code to send. - */ -function build_bl_tree(s) { - let max_blindex; /* index of last bit length code of non zero freq */ - - /* Determine the bit length frequencies for literal and distance trees */ - scan_tree(s, s.dyn_ltree, s.l_desc.max_code); - scan_tree(s, s.dyn_dtree, s.d_desc.max_code); - - /* Build the bit length tree: */ - build_tree(s, s.bl_desc); - /* opt_len now includes the length of the tree representations, except - * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. - */ - - /* Determine the number of bit length codes to send. The pkzip format - * requires that at least 4 bit length codes be sent. (appnote.txt says - * 3 but the actual value used is 4.) - */ - for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) { - if (s.bl_tree[bl_order[max_blindex] * 2 + 1]/*.Len*/ !== 0) { - break; - } - } - /* Update opt_len to include the bit length tree and counts */ - s.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4; - //Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", - // s->opt_len, s->static_len)); - - return max_blindex; -} - - -/* =========================================================================== - * Send the header for a block using dynamic Huffman trees: the counts, the - * lengths of the bit length codes, the literal tree and the distance tree. - * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. - */ -function send_all_trees(s, lcodes, dcodes, blcodes) -// deflate_state *s; -// int lcodes, dcodes, blcodes; /* number of codes for each tree */ -{ - let rank; /* index in bl_order */ - - //Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); - //Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, - // "too many codes"); - //Tracev((stderr, "\nbl counts: ")); - send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */ - send_bits(s, dcodes - 1, 5); - send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */ - for (rank = 0; rank < blcodes; rank++) { - //Tracev((stderr, "\nbl code %2d ", bl_order[rank])); - send_bits(s, s.bl_tree[bl_order[rank] * 2 + 1]/*.Len*/, 3); - } - //Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); - - send_tree(s, s.dyn_ltree, lcodes - 1); /* literal tree */ - //Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); - - send_tree(s, s.dyn_dtree, dcodes - 1); /* distance tree */ - //Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); -} - - -/* =========================================================================== - * Check if the data type is TEXT or BINARY, using the following algorithm: - * - TEXT if the two conditions below are satisfied: - * a) There are no non-portable control characters belonging to the - * "black list" (0..6, 14..25, 28..31). - * b) There is at least one printable character belonging to the - * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). - * - BINARY otherwise. - * - The following partially-portable control characters form a - * "gray list" that is ignored in this detection algorithm: - * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). - * IN assertion: the fields Freq of dyn_ltree are set. - */ -function detect_data_type(s) { - /* black_mask is the bit mask of black-listed bytes - * set bits 0..6, 14..25, and 28..31 - * 0xf3ffc07f = binary 11110011111111111100000001111111 - */ - let black_mask = 0xf3ffc07f; - let n; - - /* Check for non-textual ("black-listed") bytes. */ - for (n = 0; n <= 31; n++, black_mask >>>= 1) { - if (black_mask & 1 && s.dyn_ltree[n * 2]/*.Freq*/ !== 0) { - return Z_BINARY; - } - } - - /* Check for textual ("white-listed") bytes. */ - if (s.dyn_ltree[9 * 2]/*.Freq*/ !== 0 || s.dyn_ltree[10 * 2]/*.Freq*/ !== 0 || - s.dyn_ltree[13 * 2]/*.Freq*/ !== 0) { - return Z_TEXT; - } - for (n = 32; n < LITERALS; n++) { - if (s.dyn_ltree[n * 2]/*.Freq*/ !== 0) { - return Z_TEXT; - } - } - - /* There are no "black-listed" or "white-listed" bytes: - * this stream either is empty or has tolerated ("gray-listed") bytes only. - */ - return Z_BINARY; -} - - -let static_init_done = false; - -/* =========================================================================== - * Initialize the tree data structures for a new zlib stream. - */ -function _tr_init(s) { - - if (!static_init_done) { - tr_static_init(); - static_init_done = true; - } - - s.l_desc = new TreeDesc(s.dyn_ltree, static_l_desc); - s.d_desc = new TreeDesc(s.dyn_dtree, static_d_desc); - s.bl_desc = new TreeDesc(s.bl_tree, static_bl_desc); - - s.bi_buf = 0; - s.bi_valid = 0; - - /* Initialize the first block of the first file: */ - init_block(s); -} - - -/* =========================================================================== - * Send a stored block - */ -function _tr_stored_block(s, buf, stored_len, last) -//DeflateState *s; -//charf *buf; /* input block */ -//ulg stored_len; /* length of input block */ -//int last; /* one if this is the last block for a file */ -{ - send_bits(s, (STORED_BLOCK << 1) + (last ? 1 : 0), 3); /* send block type */ - copy_block(s, buf, stored_len, true); /* with header */ -} - - -/* =========================================================================== - * Send one empty static block to give enough lookahead for inflate. - * This takes 10 bits, of which 7 may remain in the bit buffer. - */ -function _tr_align(s) { - send_bits(s, STATIC_TREES << 1, 3); - send_code(s, END_BLOCK, static_ltree); - bi_flush(s); -} - - -/* =========================================================================== - * Determine the best encoding for the current block: dynamic trees, static - * trees or store, and output the encoded block to the zip file. - */ -function _tr_flush_block(s, buf, stored_len, last) -//DeflateState *s; -//charf *buf; /* input block, or NULL if too old */ -//ulg stored_len; /* length of input block */ -//int last; /* one if this is the last block for a file */ -{ - let opt_lenb, static_lenb; /* opt_len and static_len in bytes */ - let max_blindex = 0; /* index of last bit length code of non zero freq */ - - /* Build the Huffman trees unless a stored block is forced */ - if (s.level > 0) { - - /* Check if the file is binary or text */ - if (s.strm.data_type === Z_UNKNOWN) { - s.strm.data_type = detect_data_type(s); - } - - /* Construct the literal and distance trees */ - build_tree(s, s.l_desc); - // Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, - // s->static_len)); - - build_tree(s, s.d_desc); - // Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, - // s->static_len)); - /* At this point, opt_len and static_len are the total bit lengths of - * the compressed block data, excluding the tree representations. - */ - - /* Build the bit length tree for the above two trees, and get the index - * in bl_order of the last bit length code to send. - */ - max_blindex = build_bl_tree(s); - - /* Determine the best encoding. Compute the block lengths in bytes. */ - opt_lenb = s.opt_len + 3 + 7 >>> 3; - static_lenb = s.static_len + 3 + 7 >>> 3; - - // Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", - // opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, - // s->last_lit)); - - if (static_lenb <= opt_lenb) { - opt_lenb = static_lenb; - } - - } else { - // Assert(buf != (char*)0, "lost buf"); - opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ - } - - if (stored_len + 4 <= opt_lenb && buf !== -1) { - /* 4: two words for the lengths */ - - /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. - * Otherwise we can't have processed more than WSIZE input bytes since - * the last block flush, because compression would have been - * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to - * transform a block into a stored block. - */ - _tr_stored_block(s, buf, stored_len, last); - - } else if (s.strategy === Z_FIXED || static_lenb === opt_lenb) { - - send_bits(s, (STATIC_TREES << 1) + (last ? 1 : 0), 3); - compress_block(s, static_ltree, static_dtree); - - } else { - send_bits(s, (DYN_TREES << 1) + (last ? 1 : 0), 3); - send_all_trees(s, s.l_desc.max_code + 1, s.d_desc.max_code + 1, max_blindex + 1); - compress_block(s, s.dyn_ltree, s.dyn_dtree); - } - // Assert (s->compressed_len == s->bits_sent, "bad compressed size"); - /* The above check is made mod 2^32, for files larger than 512 MB - * and uLong implemented on 32 bits. - */ - init_block(s); - - if (last) { - bi_windup(s); - } - // Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, - // s->compressed_len-7*last)); -} - -/* =========================================================================== - * Save the match info and tally the frequency counts. Return true if - * the current block must be flushed. - */ -function _tr_tally(s, dist, lc) -// deflate_state *s; -// unsigned dist; /* distance of matched string */ -// unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ -{ - //var out_length, in_length, dcode; - - s.pending_buf[s.d_buf + s.last_lit * 2] = dist >>> 8 & 0xff; - s.pending_buf[s.d_buf + s.last_lit * 2 + 1] = dist & 0xff; - - s.pending_buf[s.l_buf + s.last_lit] = lc & 0xff; - s.last_lit++; - - if (dist === 0) { - /* lc is the unmatched char */ - s.dyn_ltree[lc * 2]/*.Freq*/++; - } else { - s.matches++; - /* Here, lc is the match length - MIN_MATCH */ - dist--; /* dist = match distance - 1 */ - //Assert((ush)dist < (ush)MAX_DIST(s) && - // (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && - // (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); - - s.dyn_ltree[(_length_code[lc] + LITERALS + 1) * 2]/*.Freq*/++; - s.dyn_dtree[d_code(dist) * 2]/*.Freq*/++; - } - - // (!) This block is disabled in zlib defaults, - // don't enable it for binary compatibility - - //#ifdef TRUNCATE_BLOCK - // /* Try to guess if it is profitable to stop the current block here */ - // if ((s.last_lit & 0x1fff) === 0 && s.level > 2) { - // /* Compute an upper bound for the compressed length */ - // out_length = s.last_lit*8; - // in_length = s.strstart - s.block_start; - // - // for (dcode = 0; dcode < D_CODES; dcode++) { - // out_length += s.dyn_dtree[dcode*2]/*.Freq*/ * (5 + extra_dbits[dcode]); - // } - // out_length >>>= 3; - // //Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", - // // s->last_lit, in_length, out_length, - // // 100L - out_length*100L/in_length)); - // if (s.matches < (s.last_lit>>1)/*int /2*/ && out_length < (in_length>>1)/*int /2*/) { - // return true; - // } - // } - //#endif - - return s.last_lit === s.lit_bufsize - 1; - /* We avoid equality with lit_bufsize because of wraparound at 64K - * on 16 bit machines and because stored blocks are restricted to - * 64K-1 bytes. - */ -} - -// Note: adler32 takes 12% for level 0 and 2% for level 6. -// It isn't worth it to make additional optimizations as in original. -// Small size is preferable. - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -function adler32(adler, buf, len, pos) { - let s1 = adler & 0xffff |0, - s2 = adler >>> 16 & 0xffff |0, - n = 0; - - while (len !== 0) { - // Set limit ~ twice less than 5552, to keep - // s2 in 31-bits, because we force signed ints. - // in other case %= will fail. - n = len > 2000 ? 2000 : len; - len -= n; - - do { - s1 = s1 + buf[pos++] |0; - s2 = s2 + s1 |0; - } while (--n); - - s1 %= 65521; - s2 %= 65521; - } - - return s1 | s2 << 16 |0; -} - -// Note: we can't get significant speed boost here. -// So write code to minimize size - no pregenerated tables -// and array tools dependencies. - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -// Use ordinary array, since untyped makes no boost here -function makeTable() { - let c; - const table = []; - - for (let n = 0; n < 256; n++) { - c = n; - for (let k = 0; k < 8; k++) { - c = c & 1 ? 0xEDB88320 ^ c >>> 1 : c >>> 1; - } - table[n] = c; - } - - return table; -} - -// Create table on load. Just 255 signed longs. Not a problem. -const crcTable = makeTable(); - - -function crc32(crc, buf, len, pos) { - const t = crcTable, - end = pos + len; - - crc ^= -1; - - for (let i = pos; i < end; i++) { - crc = crc >>> 8 ^ t[(crc ^ buf[i]) & 0xFF]; - } - - return crc ^ -1; // >>> 0; -} - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -var msg = { - 2: "need dictionary", /* Z_NEED_DICT 2 */ - 1: "stream end", /* Z_STREAM_END 1 */ - 0: "", /* Z_OK 0 */ - "-1": "file error", /* Z_ERRNO (-1) */ - "-2": "stream error", /* Z_STREAM_ERROR (-2) */ - "-3": "data error", /* Z_DATA_ERROR (-3) */ - "-4": "insufficient memory", /* Z_MEM_ERROR (-4) */ - "-5": "buffer error", /* Z_BUF_ERROR (-5) */ - "-6": "incompatible version" /* Z_VERSION_ERROR (-6) */ -}; - -/*============================================================================*/ - - -const MAX_MEM_LEVEL = 9; - - -const LENGTH_CODES$1 = 29; -/* number of length codes, not counting the special END_BLOCK code */ -const LITERALS$1 = 256; -/* number of literal bytes 0..255 */ -const L_CODES$1 = LITERALS$1 + 1 + LENGTH_CODES$1; -/* number of Literal or Length codes, including the END_BLOCK code */ -const D_CODES$1 = 30; -/* number of distance codes */ -const BL_CODES$1 = 19; -/* number of codes used to transfer the bit lengths */ -const HEAP_SIZE$1 = 2 * L_CODES$1 + 1; -/* maximum heap size */ -const MAX_BITS$1 = 15; -/* All codes must not exceed MAX_BITS bits */ - -const MIN_MATCH$1 = 3; -const MAX_MATCH$1 = 258; -const MIN_LOOKAHEAD = (MAX_MATCH$1 + MIN_MATCH$1 + 1); - -const PRESET_DICT = 0x20; - -const INIT_STATE = 42; -const EXTRA_STATE = 69; -const NAME_STATE = 73; -const COMMENT_STATE = 91; -const HCRC_STATE = 103; -const BUSY_STATE = 113; -const FINISH_STATE = 666; - -const BS_NEED_MORE = 1; /* block not completed, need more input or more output */ -const BS_BLOCK_DONE = 2; /* block flush performed */ -const BS_FINISH_STARTED = 3; /* finish started, need only more output at next deflate */ -const BS_FINISH_DONE = 4; /* finish done, accept no more input or output */ - -const OS_CODE = 0x03; // Unix :) . Don't detect, use this default. - -function err(strm, errorCode) { - strm.msg = msg[errorCode]; - return errorCode; -} - -function rank(f) { - return ((f) << 1) - ((f) > 4 ? 9 : 0); -} - -function zero$2(buf) { let len = buf.length; while (--len >= 0) { buf[len] = 0; } } - - -/* ========================================================================= - * Flush as much pending output as possible. All deflate() output goes - * through this function so some applications may wish to modify it - * to avoid allocating a large strm->output buffer and copying into it. - * (See also read_buf()). - */ -function flush_pending(strm) { - const s = strm.state; - - //_tr_flush_bits(s); - let len = s.pending; - if (len > strm.avail_out) { - len = strm.avail_out; - } - if (len === 0) { return; } - - arraySet(strm.output, s.pending_buf, s.pending_out, len, strm.next_out); - strm.next_out += len; - s.pending_out += len; - strm.total_out += len; - strm.avail_out -= len; - s.pending -= len; - if (s.pending === 0) { - s.pending_out = 0; - } -} - - -function flush_block_only(s, last) { - _tr_flush_block(s, (s.block_start >= 0 ? s.block_start : -1), s.strstart - s.block_start, last); - s.block_start = s.strstart; - flush_pending(s.strm); -} - - -function put_byte(s, b) { - s.pending_buf[s.pending++] = b; -} - - -/* ========================================================================= - * Put a short in the pending buffer. The 16-bit value is put in MSB order. - * IN assertion: the stream state is correct and there is enough room in - * pending_buf. - */ -function putShortMSB(s, b) { - // put_byte(s, (Byte)(b >> 8)); - // put_byte(s, (Byte)(b & 0xff)); - s.pending_buf[s.pending++] = (b >>> 8) & 0xff; - s.pending_buf[s.pending++] = b & 0xff; -} - - -/* =========================================================================== - * Read a new buffer from the current input stream, update the adler32 - * and total number of bytes read. All deflate() input goes through - * this function so some applications may wish to modify it to avoid - * allocating a large strm->input buffer and copying from it. - * (See also flush_pending()). - */ -function read_buf(strm, buf, start, size) { - let len = strm.avail_in; - - if (len > size) { len = size; } - if (len === 0) { return 0; } - - strm.avail_in -= len; - - // zmemcpy(buf, strm->next_in, len); - arraySet(buf, strm.input, strm.next_in, len, start); - if (strm.state.wrap === 1) { - strm.adler = adler32(strm.adler, buf, len, start); - } - - else if (strm.state.wrap === 2) { - strm.adler = crc32(strm.adler, buf, len, start); - } - - strm.next_in += len; - strm.total_in += len; - - return len; -} - - -/* =========================================================================== - * Set match_start to the longest match starting at the given string and - * return its length. Matches shorter or equal to prev_length are discarded, - * in which case the result is equal to prev_length and match_start is - * garbage. - * IN assertions: cur_match is the head of the hash chain for the current - * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 - * OUT assertion: the match length is not greater than s->lookahead. - */ -function longest_match(s, cur_match) { - let chain_length = s.max_chain_length; /* max hash chain length */ - let scan = s.strstart; /* current string */ - let match; /* matched string */ - let len; /* length of current match */ - let best_len = s.prev_length; /* best match length so far */ - let nice_match = s.nice_match; /* stop if match long enough */ - const limit = (s.strstart > (s.w_size - MIN_LOOKAHEAD)) ? - s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0/*NIL*/; - - const _win = s.window; // shortcut - - const wmask = s.w_mask; - const prev = s.prev; - - /* Stop when cur_match becomes <= limit. To simplify the code, - * we prevent matches with the string of window index 0. - */ - - const strend = s.strstart + MAX_MATCH$1; - let scan_end1 = _win[scan + best_len - 1]; - let scan_end = _win[scan + best_len]; - - /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - * It is easy to get rid of this optimization if necessary. - */ - // Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - - /* Do not waste too much time if we already have a good match: */ - if (s.prev_length >= s.good_match) { - chain_length >>= 2; - } - /* Do not look for matches beyond the end of the input. This is necessary - * to make deflate deterministic. - */ - if (nice_match > s.lookahead) { nice_match = s.lookahead; } - - // Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); - - do { - // Assert(cur_match < s->strstart, "no future"); - match = cur_match; - - /* Skip to next match if the match length cannot increase - * or if the match length is less than 2. Note that the checks below - * for insufficient lookahead only occur occasionally for performance - * reasons. Therefore uninitialized memory will be accessed, and - * conditional jumps will be made that depend on those values. - * However the length of the match is limited to the lookahead, so - * the output of deflate is not affected by the uninitialized values. - */ - - if (_win[match + best_len] !== scan_end || - _win[match + best_len - 1] !== scan_end1 || - _win[match] !== _win[scan] || - _win[++match] !== _win[scan + 1]) { - continue; - } - - /* The check at best_len-1 can be removed because it will be made - * again later. (This heuristic is not always a win.) - * It is not necessary to compare scan[2] and match[2] since they - * are always equal when the other bytes match, given that - * the hash keys are equal and that HASH_BITS >= 8. - */ - scan += 2; - match++; - // Assert(*scan == *match, "match[2]?"); - - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. - */ - do { - /*jshint noempty:false*/ - } while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - scan < strend); - - // Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - - len = MAX_MATCH$1 - (strend - scan); - scan = strend - MAX_MATCH$1; - - if (len > best_len) { - s.match_start = cur_match; - best_len = len; - if (len >= nice_match) { - break; - } - scan_end1 = _win[scan + best_len - 1]; - scan_end = _win[scan + best_len]; - } - } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0); - - if (best_len <= s.lookahead) { - return best_len; - } - return s.lookahead; -} - - -/* =========================================================================== - * Fill the window when the lookahead becomes insufficient. - * Updates strstart and lookahead. - * - * IN assertion: lookahead < MIN_LOOKAHEAD - * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD - * At least one byte has been read, or avail_in == 0; reads are - * performed for at least two bytes (required for the zip translate_eol - * option -- not supported here). - */ -function fill_window(s) { - const _w_size = s.w_size; - let p, n, m, more, str; - - //Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); - - do { - more = s.window_size - s.lookahead - s.strstart; - - // JS ints have 32 bit, block below not needed - /* Deal with !@#$% 64K limit: */ - //if (sizeof(int) <= 2) { - // if (more == 0 && s->strstart == 0 && s->lookahead == 0) { - // more = wsize; - // - // } else if (more == (unsigned)(-1)) { - // /* Very unlikely, but possible on 16 bit machine if - // * strstart == 0 && lookahead == 1 (input done a byte at time) - // */ - // more--; - // } - //} - - - /* If the window is almost full and there is insufficient lookahead, - * move the upper half to the lower one to make room in the upper half. - */ - if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) { - - arraySet(s.window, s.window, _w_size, _w_size, 0); - s.match_start -= _w_size; - s.strstart -= _w_size; - /* we now have strstart >= MAX_DIST */ - s.block_start -= _w_size; - - /* Slide the hash table (could be avoided with 32 bit values - at the expense of memory usage). We slide even when level == 0 - to keep the hash table consistent if we switch back to level > 0 - later. (Using level 0 permanently is not an optimal usage of - zlib, so we don't care about this pathological case.) - */ - - n = s.hash_size; - p = n; - do { - m = s.head[--p]; - s.head[p] = (m >= _w_size ? m - _w_size : 0); - } while (--n); - - n = _w_size; - p = n; - do { - m = s.prev[--p]; - s.prev[p] = (m >= _w_size ? m - _w_size : 0); - /* If n is not on any hash chain, prev[n] is garbage but - * its value will never be used. - */ - } while (--n); - - more += _w_size; - } - if (s.strm.avail_in === 0) { - break; - } - - /* If there was no sliding: - * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && - * more == window_size - lookahead - strstart - * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) - * => more >= window_size - 2*WSIZE + 2 - * In the BIG_MEM or MMAP case (not yet supported), - * window_size == input_size + MIN_LOOKAHEAD && - * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. - * Otherwise, window_size == 2*WSIZE so more >= 2. - * If there was sliding, more >= WSIZE. So in all cases, more >= 2. - */ - //Assert(more >= 2, "more < 2"); - n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more); - s.lookahead += n; - - /* Initialize the hash value now that we have some input: */ - if (s.lookahead + s.insert >= MIN_MATCH$1) { - str = s.strstart - s.insert; - s.ins_h = s.window[str]; - - /* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + 1]) & s.hash_mask; - //#if MIN_MATCH != 3 - // Call update_hash() MIN_MATCH-3 more times - //#endif - while (s.insert) { - /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH$1 - 1]) & s.hash_mask; - - s.prev[str & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = str; - str++; - s.insert--; - if (s.lookahead + s.insert < MIN_MATCH$1) { - break; - } - } - } - /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, - * but this is not important since only literal bytes will be emitted. - */ - - } while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0); - - /* If the WIN_INIT bytes after the end of the current data have never been - * written, then zero those bytes in order to avoid memory check reports of - * the use of uninitialized (or uninitialised as Julian writes) bytes by - * the longest match routines. Update the high water mark for the next - * time through here. WIN_INIT is set to MAX_MATCH since the longest match - * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. - */ - // if (s.high_water < s.window_size) { - // var curr = s.strstart + s.lookahead; - // var init = 0; - // - // if (s.high_water < curr) { - // /* Previous high water mark below current data -- zero WIN_INIT - // * bytes or up to end of window, whichever is less. - // */ - // init = s.window_size - curr; - // if (init > WIN_INIT) - // init = WIN_INIT; - // zmemzero(s->window + curr, (unsigned)init); - // s->high_water = curr + init; - // } - // else if (s->high_water < (ulg)curr + WIN_INIT) { - // /* High water mark at or above current data, but below current data - // * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up - // * to end of window, whichever is less. - // */ - // init = (ulg)curr + WIN_INIT - s->high_water; - // if (init > s->window_size - s->high_water) - // init = s->window_size - s->high_water; - // zmemzero(s->window + s->high_water, (unsigned)init); - // s->high_water += init; - // } - // } - // - // Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, - // "not enough room for search"); -} - -/* =========================================================================== - * Copy without compression as much as possible from the input stream, return - * the current block state. - * This function does not insert new strings in the dictionary since - * uncompressible data is probably not useful. This function is used - * only for the level=0 compression option. - * NOTE: this function should be optimized to avoid extra copying from - * window to pending_buf. - */ -function deflate_stored(s, flush) { - /* Stored blocks are limited to 0xffff bytes, pending_buf is limited - * to pending_buf_size, and each stored block has a 5 byte header: - */ - let max_block_size = 0xffff; - - if (max_block_size > s.pending_buf_size - 5) { - max_block_size = s.pending_buf_size - 5; - } - - /* Copy as much as possible from input to output: */ - for (; ;) { - /* Fill the window as much as possible: */ - if (s.lookahead <= 1) { - - //Assert(s->strstart < s->w_size+MAX_DIST(s) || - // s->block_start >= (long)s->w_size, "slide too late"); - // if (!(s.strstart < s.w_size + (s.w_size - MIN_LOOKAHEAD) || - // s.block_start >= s.w_size)) { - // throw new Error("slide too late"); - // } - - fill_window(s); - if (s.lookahead === 0 && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - - if (s.lookahead === 0) { - break; - } - /* flush the current block */ - } - //Assert(s->block_start >= 0L, "block gone"); - // if (s.block_start < 0) throw new Error("block gone"); - - s.strstart += s.lookahead; - s.lookahead = 0; - - /* Emit a stored block if pending_buf will be full: */ - const max_start = s.block_start + max_block_size; - - if (s.strstart === 0 || s.strstart >= max_start) { - /* strstart == 0 is possible when wraparound on 16-bit machine */ - s.lookahead = s.strstart - max_start; - s.strstart = max_start; - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - - - } - /* Flush if we may have to slide, otherwise block_start may become - * negative and the data will be gone: - */ - if (s.strstart - s.block_start >= (s.w_size - MIN_LOOKAHEAD)) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } - - s.insert = 0; - - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - - if (s.strstart > s.block_start) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - - return BS_NEED_MORE; -} - -/* =========================================================================== - * Compress as much as possible from the input stream, return the current - * block state. - * This function does not perform lazy evaluation of matches and inserts - * new strings in the dictionary only for unmatched strings or for short - * matches. It is used only for the fast compression options. - */ -function deflate_fast(s, flush) { - let hash_head; /* head of the hash chain */ - let bflush; /* set if current block must be flushed */ - - for (; ;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s.lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - if (s.lookahead === 0) { - break; /* flush the current block */ - } - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - hash_head = 0/*NIL*/; - if (s.lookahead >= MIN_MATCH$1) { - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - } - - /* Find the longest match, discarding those <= prev_length. - * At this point we have always match_length < MIN_MATCH - */ - if (hash_head !== 0/*NIL*/ && ((s.strstart - hash_head) <= (s.w_size - MIN_LOOKAHEAD))) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - s.match_length = longest_match(s, hash_head); - /* longest_match() sets match_start */ - } - if (s.match_length >= MIN_MATCH$1) { - // check_match(s, s.strstart, s.match_start, s.match_length); // for debug only - - /*** _tr_tally_dist(s, s.strstart - s.match_start, - s.match_length - MIN_MATCH, bflush); ***/ - bflush = _tr_tally(s, s.strstart - s.match_start, s.match_length - MIN_MATCH$1); - - s.lookahead -= s.match_length; - - /* Insert new strings in the hash table only if the match length - * is not too large. This saves time but degrades compression. - */ - if (s.match_length <= s.max_lazy_match/*max_insert_length*/ && s.lookahead >= MIN_MATCH$1) { - s.match_length--; /* string at strstart already in table */ - do { - s.strstart++; - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - /* strstart never exceeds WSIZE-MAX_MATCH, so there are - * always MIN_MATCH bytes ahead. - */ - } while (--s.match_length !== 0); - s.strstart++; - } else { - s.strstart += s.match_length; - s.match_length = 0; - s.ins_h = s.window[s.strstart]; - /* UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]); */ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + 1]) & s.hash_mask; - - //#if MIN_MATCH != 3 - // Call UPDATE_HASH() MIN_MATCH-3 more times - //#endif - /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not - * matter since it will be recomputed at next deflate call. - */ - } - } else { - /* No match, output a literal byte */ - //Tracevv((stderr,"%c", s.window[s.strstart])); - /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ - bflush = _tr_tally(s, 0, s.window[s.strstart]); - - s.lookahead--; - s.strstart++; - } - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } - s.insert = ((s.strstart < (MIN_MATCH$1 - 1)) ? s.strstart : MIN_MATCH$1 - 1); - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - return BS_BLOCK_DONE; -} - -/* =========================================================================== - * Same as above, but achieves better compression. We use a lazy - * evaluation for matches: a match is finally adopted only if there is - * no better match at the next window position. - */ -function deflate_slow(s, flush) { - let hash_head; /* head of hash chain */ - let bflush; /* set if current block must be flushed */ - - let max_insert; - - /* Process the input block. */ - for (; ;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s.lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - if (s.lookahead === 0) { break; } /* flush the current block */ - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - hash_head = 0/*NIL*/; - if (s.lookahead >= MIN_MATCH$1) { - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - } - - /* Find the longest match, discarding those <= prev_length. - */ - s.prev_length = s.match_length; - s.prev_match = s.match_start; - s.match_length = MIN_MATCH$1 - 1; - - if (hash_head !== 0/*NIL*/ && s.prev_length < s.max_lazy_match && - s.strstart - hash_head <= (s.w_size - MIN_LOOKAHEAD)/*MAX_DIST(s)*/) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - s.match_length = longest_match(s, hash_head); - /* longest_match() sets match_start */ - - if (s.match_length <= 5 && - (s.strategy === Z_FILTERED || (s.match_length === MIN_MATCH$1 && s.strstart - s.match_start > 4096/*TOO_FAR*/))) { - - /* If prev_match is also MIN_MATCH, match_start is garbage - * but we will ignore the current match anyway. - */ - s.match_length = MIN_MATCH$1 - 1; - } - } - /* If there was a match at the previous step and the current - * match is not better, output the previous match: - */ - if (s.prev_length >= MIN_MATCH$1 && s.match_length <= s.prev_length) { - max_insert = s.strstart + s.lookahead - MIN_MATCH$1; - /* Do not insert strings in hash table beyond this. */ - - //check_match(s, s.strstart-1, s.prev_match, s.prev_length); - - /***_tr_tally_dist(s, s.strstart - 1 - s.prev_match, - s.prev_length - MIN_MATCH, bflush);***/ - bflush = _tr_tally(s, s.strstart - 1 - s.prev_match, s.prev_length - MIN_MATCH$1); - /* Insert in hash table all strings up to the end of the match. - * strstart-1 and strstart are already inserted. If there is not - * enough lookahead, the last two strings are not inserted in - * the hash table. - */ - s.lookahead -= s.prev_length - 1; - s.prev_length -= 2; - do { - if (++s.strstart <= max_insert) { - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - } - } while (--s.prev_length !== 0); - s.match_available = 0; - s.match_length = MIN_MATCH$1 - 1; - s.strstart++; - - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - - } else if (s.match_available) { - /* If there was no match at the previous position, output a - * single literal. If there was a match but the current match - * is longer, truncate the previous match to a single literal. - */ - //Tracevv((stderr,"%c", s->window[s->strstart-1])); - /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ - bflush = _tr_tally(s, 0, s.window[s.strstart - 1]); - - if (bflush) { - /*** FLUSH_BLOCK_ONLY(s, 0) ***/ - flush_block_only(s, false); - /***/ - } - s.strstart++; - s.lookahead--; - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - } else { - /* There is no previous match to compare with, wait for - * the next step to decide. - */ - s.match_available = 1; - s.strstart++; - s.lookahead--; - } - } - //Assert (flush != Z_NO_FLUSH, "no flush?"); - if (s.match_available) { - //Tracevv((stderr,"%c", s->window[s->strstart-1])); - /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ - bflush = _tr_tally(s, 0, s.window[s.strstart - 1]); - - s.match_available = 0; - } - s.insert = s.strstart < MIN_MATCH$1 - 1 ? s.strstart : MIN_MATCH$1 - 1; - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - - return BS_BLOCK_DONE; -} - - -/* =========================================================================== - * For Z_RLE, simply look for runs of bytes, generate matches only of distance - * one. Do not maintain a hash table. (It will be regenerated if this run of - * deflate switches away from Z_RLE.) - */ -function deflate_rle(s, flush) { - let bflush; /* set if current block must be flushed */ - let prev; /* byte at distance one to match */ - let scan, strend; /* scan goes up to strend for length of run */ - - const _win = s.window; - - for (; ;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the longest run, plus one for the unrolled loop. - */ - if (s.lookahead <= MAX_MATCH$1) { - fill_window(s); - if (s.lookahead <= MAX_MATCH$1 && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - if (s.lookahead === 0) { break; } /* flush the current block */ - } - - /* See how many times the previous byte repeats */ - s.match_length = 0; - if (s.lookahead >= MIN_MATCH$1 && s.strstart > 0) { - scan = s.strstart - 1; - prev = _win[scan]; - if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) { - strend = s.strstart + MAX_MATCH$1; - do { - /*jshint noempty:false*/ - } while (prev === _win[++scan] && prev === _win[++scan] && - prev === _win[++scan] && prev === _win[++scan] && - prev === _win[++scan] && prev === _win[++scan] && - prev === _win[++scan] && prev === _win[++scan] && - scan < strend); - s.match_length = MAX_MATCH$1 - (strend - scan); - if (s.match_length > s.lookahead) { - s.match_length = s.lookahead; - } - } - //Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); - } - - /* Emit match if have run of MIN_MATCH or longer, else emit literal */ - if (s.match_length >= MIN_MATCH$1) { - //check_match(s, s.strstart, s.strstart - 1, s.match_length); - - /*** _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ***/ - bflush = _tr_tally(s, 1, s.match_length - MIN_MATCH$1); - - s.lookahead -= s.match_length; - s.strstart += s.match_length; - s.match_length = 0; - } else { - /* No match, output a literal byte */ - //Tracevv((stderr,"%c", s->window[s->strstart])); - /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ - bflush = _tr_tally(s, 0, s.window[s.strstart]); - - s.lookahead--; - s.strstart++; - } - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } - s.insert = 0; - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - return BS_BLOCK_DONE; -} - -/* =========================================================================== - * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. - * (It will be regenerated if this run of deflate switches away from Huffman.) - */ -function deflate_huff(s, flush) { - let bflush; /* set if current block must be flushed */ - - for (; ;) { - /* Make sure that we have a literal to write. */ - if (s.lookahead === 0) { - fill_window(s); - if (s.lookahead === 0) { - if (flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - break; /* flush the current block */ - } - } - - /* Output a literal byte */ - s.match_length = 0; - //Tracevv((stderr,"%c", s->window[s->strstart])); - /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ - bflush = _tr_tally(s, 0, s.window[s.strstart]); - s.lookahead--; - s.strstart++; - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } - s.insert = 0; - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - return BS_BLOCK_DONE; -} - -/* Values for max_lazy_match, good_match and max_chain_length, depending on - * the desired pack level (0..9). The values given below have been tuned to - * exclude worst case performance for pathological files. Better values may be - * found for specific files. - */ -class Config { - constructor(good_length, max_lazy, nice_length, max_chain, func) { - this.good_length = good_length; - this.max_lazy = max_lazy; - this.nice_length = nice_length; - this.max_chain = max_chain; - this.func = func; - } -} -const configuration_table = [ - /* good lazy nice chain */ - new Config(0, 0, 0, 0, deflate_stored), /* 0 store only */ - new Config(4, 4, 8, 4, deflate_fast), /* 1 max speed, no lazy matches */ - new Config(4, 5, 16, 8, deflate_fast), /* 2 */ - new Config(4, 6, 32, 32, deflate_fast), /* 3 */ - - new Config(4, 4, 16, 16, deflate_slow), /* 4 lazy matches */ - new Config(8, 16, 32, 32, deflate_slow), /* 5 */ - new Config(8, 16, 128, 128, deflate_slow), /* 6 */ - new Config(8, 32, 128, 256, deflate_slow), /* 7 */ - new Config(32, 128, 258, 1024, deflate_slow), /* 8 */ - new Config(32, 258, 258, 4096, deflate_slow) /* 9 max compression */ -]; - - -/* =========================================================================== - * Initialize the "longest match" routines for a new zlib stream - */ -function lm_init(s) { - s.window_size = 2 * s.w_size; - - /*** CLEAR_HASH(s); ***/ - zero$2(s.head); // Fill with NIL (= 0); - - /* Set the default configuration parameters: - */ - s.max_lazy_match = configuration_table[s.level].max_lazy; - s.good_match = configuration_table[s.level].good_length; - s.nice_match = configuration_table[s.level].nice_length; - s.max_chain_length = configuration_table[s.level].max_chain; - - s.strstart = 0; - s.block_start = 0; - s.lookahead = 0; - s.insert = 0; - s.match_length = s.prev_length = MIN_MATCH$1 - 1; - s.match_available = 0; - s.ins_h = 0; -} - -class DeflateState { - constructor() { - this.strm = null; /* pointer back to this zlib stream */ - this.status = 0; /* as the name implies */ - this.pending_buf = null; /* output still pending */ - this.pending_buf_size = 0; /* size of pending_buf */ - this.pending_out = 0; /* next pending byte to output to the stream */ - this.pending = 0; /* nb of bytes in the pending buffer */ - this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ - this.gzhead = null; /* gzip header information to write */ - this.gzindex = 0; /* where in extra, name, or comment */ - this.method = Z_DEFLATED; /* can only be DEFLATED */ - this.last_flush = -1; /* value of flush param for previous deflate call */ - - this.w_size = 0; /* LZ77 window size (32K by default) */ - this.w_bits = 0; /* log2(w_size) (8..16) */ - this.w_mask = 0; /* w_size - 1 */ - - this.window = null; - /* Sliding window. Input bytes are read into the second half of the window, - * and move to the first half later to keep a dictionary of at least wSize - * bytes. With this organization, matches are limited to a distance of - * wSize-MAX_MATCH bytes, but this ensures that IO is always - * performed with a length multiple of the block size. - */ - - this.window_size = 0; - /* Actual size of window: 2*wSize, except when the user input buffer - * is directly used as sliding window. - */ - - this.prev = null; - /* Link to older string with same hash index. To limit the size of this - * array to 64K, this link is maintained only for the last 32K strings. - * An index in this array is thus a window index modulo 32K. - */ - - this.head = null; /* Heads of the hash chains or NIL. */ - - this.ins_h = 0; /* hash index of string to be inserted */ - this.hash_size = 0; /* number of elements in hash table */ - this.hash_bits = 0; /* log2(hash_size) */ - this.hash_mask = 0; /* hash_size-1 */ - - this.hash_shift = 0; - /* Number of bits by which ins_h must be shifted at each input - * step. It must be such that after MIN_MATCH steps, the oldest - * byte no longer takes part in the hash key, that is: - * hash_shift * MIN_MATCH >= hash_bits - */ - - this.block_start = 0; - /* Window position at the beginning of the current output block. Gets - * negative when the window is moved backwards. - */ - - this.match_length = 0; /* length of best match */ - this.prev_match = 0; /* previous match */ - this.match_available = 0; /* set if previous match exists */ - this.strstart = 0; /* start of string to insert */ - this.match_start = 0; /* start of matching string */ - this.lookahead = 0; /* number of valid bytes ahead in window */ - - this.prev_length = 0; - /* Length of the best match at previous step. Matches not greater than this - * are discarded. This is used in the lazy match evaluation. - */ - - this.max_chain_length = 0; - /* To speed up deflation, hash chains are never searched beyond this - * length. A higher limit improves compression ratio but degrades the - * speed. - */ - - this.max_lazy_match = 0; - /* Attempt to find a better match only when the current match is strictly - * smaller than this value. This mechanism is used only for compression - * levels >= 4. - */ - // That's alias to max_lazy_match, don't use directly - //this.max_insert_length = 0; - /* Insert new strings in the hash table only if the match length is not - * greater than this length. This saves time but degrades compression. - * max_insert_length is used only for compression levels <= 3. - */ - - this.level = 0; /* compression level (1..9) */ - this.strategy = 0; /* favor or force Huffman coding*/ - - this.good_match = 0; - /* Use a faster search when the previous match is longer than this */ - - this.nice_match = 0; /* Stop searching when current match exceeds this */ - - /* used by trees.c: */ - - /* Didn't use ct_data typedef below to suppress compiler warning */ - - // struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ - // struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ - // struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ - - // Use flat array of DOUBLE size, with interleaved fata, - // because JS does not support effective - this.dyn_ltree = new Buf16(HEAP_SIZE$1 * 2); - this.dyn_dtree = new Buf16((2 * D_CODES$1 + 1) * 2); - this.bl_tree = new Buf16((2 * BL_CODES$1 + 1) * 2); - zero$2(this.dyn_ltree); - zero$2(this.dyn_dtree); - zero$2(this.bl_tree); - - this.l_desc = null; /* desc. for literal tree */ - this.d_desc = null; /* desc. for distance tree */ - this.bl_desc = null; /* desc. for bit length tree */ - - //ush bl_count[MAX_BITS+1]; - this.bl_count = new Buf16(MAX_BITS$1 + 1); - /* number of codes at each bit length for an optimal tree */ - - //int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ - this.heap = new Buf16(2 * L_CODES$1 + 1); /* heap used to build the Huffman trees */ - zero$2(this.heap); - - this.heap_len = 0; /* number of elements in the heap */ - this.heap_max = 0; /* element of largest frequency */ - /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. - * The same heap array is used to build all trees. - */ - - this.depth = new Buf16(2 * L_CODES$1 + 1); //uch depth[2*L_CODES+1]; - zero$2(this.depth); - /* Depth of each subtree used as tie breaker for trees of equal frequency - */ - - this.l_buf = 0; /* buffer index for literals or lengths */ - - this.lit_bufsize = 0; - /* Size of match buffer for literals/lengths. There are 4 reasons for - * limiting lit_bufsize to 64K: - * - frequencies can be kept in 16 bit counters - * - if compression is not successful for the first block, all input - * data is still in the window so we can still emit a stored block even - * when input comes from standard input. (This can also be done for - * all blocks if lit_bufsize is not greater than 32K.) - * - if compression is not successful for a file smaller than 64K, we can - * even emit a stored file instead of a stored block (saving 5 bytes). - * This is applicable only for zip (not gzip or zlib). - * - creating new Huffman trees less frequently may not provide fast - * adaptation to changes in the input data statistics. (Take for - * example a binary file with poorly compressible code followed by - * a highly compressible string table.) Smaller buffer sizes give - * fast adaptation but have of course the overhead of transmitting - * trees more frequently. - * - I can't count above 4 - */ - - this.last_lit = 0; /* running index in l_buf */ - - this.d_buf = 0; - /* Buffer index for distances. To simplify the code, d_buf and l_buf have - * the same number of elements. To use different lengths, an extra flag - * array would be necessary. - */ - - this.opt_len = 0; /* bit length of current block with optimal trees */ - this.static_len = 0; /* bit length of current block with static trees */ - this.matches = 0; /* number of string matches in current block */ - this.insert = 0; /* bytes at end of window left to insert */ - - - this.bi_buf = 0; - /* Output buffer. bits are inserted starting at the bottom (least - * significant bits). - */ - this.bi_valid = 0; - /* Number of valid bits in bi_buf. All bits above the last valid bit - * are always zero. - */ - - // Used for window memory init. We safely ignore it for JS. That makes - // sense only for pointers and memory check tools. - //this.high_water = 0; - /* High water mark offset in window for initialized bytes -- bytes above - * this are set to zero in order to avoid memory check warnings when - * longest match routines access bytes past the input. This is then - * updated to the new high water mark. - */ - } -} - -function deflateResetKeep(strm) { - let s; - - if (!strm || !strm.state) { - return err(strm, Z_STREAM_ERROR); - } - - strm.total_in = strm.total_out = 0; - strm.data_type = Z_UNKNOWN; - - s = strm.state; - s.pending = 0; - s.pending_out = 0; - - if (s.wrap < 0) { - s.wrap = -s.wrap; - /* was made negative by deflate(..., Z_FINISH); */ - } - s.status = (s.wrap ? INIT_STATE : BUSY_STATE); - strm.adler = (s.wrap === 2) ? - 0 // crc32(0, Z_NULL, 0) - : - 1; // adler32(0, Z_NULL, 0) - s.last_flush = Z_NO_FLUSH; - _tr_init(s); - return Z_OK; -} - - -function deflateReset(strm) { - const ret = deflateResetKeep(strm); - if (ret === Z_OK) { - lm_init(strm.state); - } - return ret; -} - - -function deflateSetHeader(strm, head) { - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - if (strm.state.wrap !== 2) { return Z_STREAM_ERROR; } - strm.state.gzhead = head; - return Z_OK; -} - - -function deflateInit2(strm, level, method, windowBits, memLevel, strategy) { - if (!strm) { // === Z_NULL - return Z_STREAM_ERROR; - } - let wrap = 1; - - if (level === Z_DEFAULT_COMPRESSION) { - level = 6; - } - - if (windowBits < 0) { /* suppress zlib wrapper */ - wrap = 0; - windowBits = -windowBits; - } - - else if (windowBits > 15) { - wrap = 2; /* write gzip wrapper instead */ - windowBits -= 16; - } - - - if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method !== Z_DEFLATED || - windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || - strategy < 0 || strategy > Z_FIXED) { - return err(strm, Z_STREAM_ERROR); - } - - - if (windowBits === 8) { - windowBits = 9; - } - /* until 256-byte window bug fixed */ - - const s = new DeflateState(); - - strm.state = s; - s.strm = strm; - - s.wrap = wrap; - s.gzhead = null; - s.w_bits = windowBits; - s.w_size = 1 << s.w_bits; - s.w_mask = s.w_size - 1; - - s.hash_bits = memLevel + 7; - s.hash_size = 1 << s.hash_bits; - s.hash_mask = s.hash_size - 1; - s.hash_shift = ~~((s.hash_bits + MIN_MATCH$1 - 1) / MIN_MATCH$1); - s.window = new Buf8(s.w_size * 2); - s.head = new Buf16(s.hash_size); - s.prev = new Buf16(s.w_size); - - // Don't need mem init magic for JS. - //s.high_water = 0; /* nothing written to s->window yet */ - - s.lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ - - s.pending_buf_size = s.lit_bufsize * 4; - - //overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); - //s->pending_buf = (uchf *) overlay; - s.pending_buf = new Buf8(s.pending_buf_size); - - // It is offset from `s.pending_buf` (size is `s.lit_bufsize * 2`) - //s->d_buf = overlay + s->lit_bufsize/sizeof(ush); - s.d_buf = 1 * s.lit_bufsize; - - //s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; - s.l_buf = (1 + 2) * s.lit_bufsize; - - s.level = level; - s.strategy = strategy; - s.method = method; - - return deflateReset(strm); -} - - -function deflate(strm, flush) { - let old_flush, s; - let beg, val; // for gzip header write only - - if (!strm || !strm.state || - flush > Z_BLOCK || flush < 0) { - return strm ? err(strm, Z_STREAM_ERROR) : Z_STREAM_ERROR; - } - - s = strm.state; - - if (!strm.output || - (!strm.input && strm.avail_in !== 0) || - (s.status === FINISH_STATE && flush !== Z_FINISH)) { - return err(strm, (strm.avail_out === 0) ? Z_BUF_ERROR : Z_STREAM_ERROR); - } - - s.strm = strm; /* just in case */ - old_flush = s.last_flush; - s.last_flush = flush; - - /* Write the header */ - if (s.status === INIT_STATE) { - - if (s.wrap === 2) { // GZIP header - strm.adler = 0; //crc32(0L, Z_NULL, 0); - put_byte(s, 31); - put_byte(s, 139); - put_byte(s, 8); - if (!s.gzhead) { // s->gzhead == Z_NULL - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, s.level === 9 ? 2 : - (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? - 4 : 0)); - put_byte(s, OS_CODE); - s.status = BUSY_STATE; - } - else { - put_byte(s, (s.gzhead.text ? 1 : 0) + - (s.gzhead.hcrc ? 2 : 0) + - (!s.gzhead.extra ? 0 : 4) + - (!s.gzhead.name ? 0 : 8) + - (!s.gzhead.comment ? 0 : 16) - ); - put_byte(s, s.gzhead.time & 0xff); - put_byte(s, (s.gzhead.time >> 8) & 0xff); - put_byte(s, (s.gzhead.time >> 16) & 0xff); - put_byte(s, (s.gzhead.time >> 24) & 0xff); - put_byte(s, s.level === 9 ? 2 : - (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? - 4 : 0)); - put_byte(s, s.gzhead.os & 0xff); - if (s.gzhead.extra && s.gzhead.extra.length) { - put_byte(s, s.gzhead.extra.length & 0xff); - put_byte(s, (s.gzhead.extra.length >> 8) & 0xff); - } - if (s.gzhead.hcrc) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending, 0); - } - s.gzindex = 0; - s.status = EXTRA_STATE; - } - } - else // DEFLATE header - { - let header = (Z_DEFLATED + ((s.w_bits - 8) << 4)) << 8; - let level_flags = -1; - - if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) { - level_flags = 0; - } else if (s.level < 6) { - level_flags = 1; - } else if (s.level === 6) { - level_flags = 2; - } else { - level_flags = 3; - } - header |= (level_flags << 6); - if (s.strstart !== 0) { header |= PRESET_DICT; } - header += 31 - (header % 31); - - s.status = BUSY_STATE; - putShortMSB(s, header); - - /* Save the adler32 of the preset dictionary: */ - if (s.strstart !== 0) { - putShortMSB(s, strm.adler >>> 16); - putShortMSB(s, strm.adler & 0xffff); - } - strm.adler = 1; // adler32(0L, Z_NULL, 0); - } - } - - //#ifdef GZIP - if (s.status === EXTRA_STATE) { - if (s.gzhead.extra/* != Z_NULL*/) { - beg = s.pending; /* start of bytes to update crc */ - - while (s.gzindex < (s.gzhead.extra.length & 0xffff)) { - if (s.pending === s.pending_buf_size) { - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - flush_pending(strm); - beg = s.pending; - if (s.pending === s.pending_buf_size) { - break; - } - } - put_byte(s, s.gzhead.extra[s.gzindex] & 0xff); - s.gzindex++; - } - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - if (s.gzindex === s.gzhead.extra.length) { - s.gzindex = 0; - s.status = NAME_STATE; - } - } - else { - s.status = NAME_STATE; - } - } - if (s.status === NAME_STATE) { - if (s.gzhead.name/* != Z_NULL*/) { - beg = s.pending; /* start of bytes to update crc */ - //int val; - - do { - if (s.pending === s.pending_buf_size) { - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - flush_pending(strm); - beg = s.pending; - if (s.pending === s.pending_buf_size) { - val = 1; - break; - } - } - // JS specific: little magic to add zero terminator to end of string - if (s.gzindex < s.gzhead.name.length) { - val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff; - } else { - val = 0; - } - put_byte(s, val); - } while (val !== 0); - - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - if (val === 0) { - s.gzindex = 0; - s.status = COMMENT_STATE; - } - } - else { - s.status = COMMENT_STATE; - } - } - if (s.status === COMMENT_STATE) { - if (s.gzhead.comment/* != Z_NULL*/) { - beg = s.pending; /* start of bytes to update crc */ - //int val; - - do { - if (s.pending === s.pending_buf_size) { - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - flush_pending(strm); - beg = s.pending; - if (s.pending === s.pending_buf_size) { - val = 1; - break; - } - } - // JS specific: little magic to add zero terminator to end of string - if (s.gzindex < s.gzhead.comment.length) { - val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff; - } else { - val = 0; - } - put_byte(s, val); - } while (val !== 0); - - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - if (val === 0) { - s.status = HCRC_STATE; - } - } - else { - s.status = HCRC_STATE; - } - } - if (s.status === HCRC_STATE) { - if (s.gzhead.hcrc) { - if (s.pending + 2 > s.pending_buf_size) { - flush_pending(strm); - } - if (s.pending + 2 <= s.pending_buf_size) { - put_byte(s, strm.adler & 0xff); - put_byte(s, (strm.adler >> 8) & 0xff); - strm.adler = 0; //crc32(0L, Z_NULL, 0); - s.status = BUSY_STATE; - } - } - else { - s.status = BUSY_STATE; - } - } - //#endif - - /* Flush as much pending output as possible */ - if (s.pending !== 0) { - flush_pending(strm); - if (strm.avail_out === 0) { - /* Since avail_out is 0, deflate will be called again with - * more output space, but possibly with both pending and - * avail_in equal to zero. There won't be anything to do, - * but this is not an error situation so make sure we - * return OK instead of BUF_ERROR at next call of deflate: - */ - s.last_flush = -1; - return Z_OK; - } - - /* Make sure there is something to do and avoid duplicate consecutive - * flushes. For repeated and useless calls with Z_FINISH, we keep - * returning Z_STREAM_END instead of Z_BUF_ERROR. - */ - } else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) && - flush !== Z_FINISH) { - return err(strm, Z_BUF_ERROR); - } - - /* User must not provide more input after the first FINISH: */ - if (s.status === FINISH_STATE && strm.avail_in !== 0) { - return err(strm, Z_BUF_ERROR); - } - - /* Start a new block or continue the current one. - */ - if (strm.avail_in !== 0 || s.lookahead !== 0 || - (flush !== Z_NO_FLUSH && s.status !== FINISH_STATE)) { - var bstate = (s.strategy === Z_HUFFMAN_ONLY) ? deflate_huff(s, flush) : - (s.strategy === Z_RLE ? deflate_rle(s, flush) : - configuration_table[s.level].func(s, flush)); - - if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) { - s.status = FINISH_STATE; - } - if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) { - if (strm.avail_out === 0) { - s.last_flush = -1; - /* avoid BUF_ERROR next call, see above */ - } - return Z_OK; - /* If flush != Z_NO_FLUSH && avail_out == 0, the next call - * of deflate should use the same flush parameter to make sure - * that the flush is complete. So we don't have to output an - * empty block here, this will be done at next call. This also - * ensures that for a very small output buffer, we emit at most - * one empty block. - */ - } - if (bstate === BS_BLOCK_DONE) { - if (flush === Z_PARTIAL_FLUSH) { - _tr_align(s); - } - else if (flush !== Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ - - _tr_stored_block(s, 0, 0, false); - /* For a full flush, this empty block will be recognized - * as a special marker by inflate_sync(). - */ - if (flush === Z_FULL_FLUSH) { - /*** CLEAR_HASH(s); ***/ /* forget history */ - zero$2(s.head); // Fill with NIL (= 0); - - if (s.lookahead === 0) { - s.strstart = 0; - s.block_start = 0; - s.insert = 0; - } - } - } - flush_pending(strm); - if (strm.avail_out === 0) { - s.last_flush = -1; /* avoid BUF_ERROR at next call, see above */ - return Z_OK; - } - } - } - //Assert(strm->avail_out > 0, "bug2"); - //if (strm.avail_out <= 0) { throw new Error("bug2");} - - if (flush !== Z_FINISH) { return Z_OK; } - if (s.wrap <= 0) { return Z_STREAM_END; } - - /* Write the trailer */ - if (s.wrap === 2) { - put_byte(s, strm.adler & 0xff); - put_byte(s, (strm.adler >> 8) & 0xff); - put_byte(s, (strm.adler >> 16) & 0xff); - put_byte(s, (strm.adler >> 24) & 0xff); - put_byte(s, strm.total_in & 0xff); - put_byte(s, (strm.total_in >> 8) & 0xff); - put_byte(s, (strm.total_in >> 16) & 0xff); - put_byte(s, (strm.total_in >> 24) & 0xff); - } - else { - putShortMSB(s, strm.adler >>> 16); - putShortMSB(s, strm.adler & 0xffff); - } - - flush_pending(strm); - /* If avail_out is zero, the application will call deflate again - * to flush the rest. - */ - if (s.wrap > 0) { s.wrap = -s.wrap; } - /* write the trailer only once! */ - return s.pending !== 0 ? Z_OK : Z_STREAM_END; -} - -function deflateEnd(strm) { - let status; - - if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) { - return Z_STREAM_ERROR; - } - - status = strm.state.status; - if (status !== INIT_STATE && - status !== EXTRA_STATE && - status !== NAME_STATE && - status !== COMMENT_STATE && - status !== HCRC_STATE && - status !== BUSY_STATE && - status !== FINISH_STATE - ) { - return err(strm, Z_STREAM_ERROR); - } - - strm.state = null; - - return status === BUSY_STATE ? err(strm, Z_DATA_ERROR) : Z_OK; -} - - -/* ========================================================================= - * Initializes the compression dictionary from the given byte - * sequence without producing any compressed output. - */ -function deflateSetDictionary(strm, dictionary) { - let dictLength = dictionary.length; - - let s; - let str, n; - let wrap; - let avail; - let next; - let input; - let tmpDict; - - if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) { - return Z_STREAM_ERROR; - } - - s = strm.state; - wrap = s.wrap; - - if (wrap === 2 || (wrap === 1 && s.status !== INIT_STATE) || s.lookahead) { - return Z_STREAM_ERROR; - } - - /* when using zlib wrappers, compute Adler-32 for provided dictionary */ - if (wrap === 1) { - /* adler32(strm->adler, dictionary, dictLength); */ - strm.adler = adler32(strm.adler, dictionary, dictLength, 0); - } - - s.wrap = 0; /* avoid computing Adler-32 in read_buf */ - - /* if dictionary would fill window, just replace the history */ - if (dictLength >= s.w_size) { - if (wrap === 0) { /* already empty otherwise */ - /*** CLEAR_HASH(s); ***/ - zero$2(s.head); // Fill with NIL (= 0); - s.strstart = 0; - s.block_start = 0; - s.insert = 0; - } - /* use the tail */ - // dictionary = dictionary.slice(dictLength - s.w_size); - tmpDict = new Buf8(s.w_size); - arraySet(tmpDict, dictionary, dictLength - s.w_size, s.w_size, 0); - dictionary = tmpDict; - dictLength = s.w_size; - } - /* insert dictionary into window and hash */ - avail = strm.avail_in; - next = strm.next_in; - input = strm.input; - strm.avail_in = dictLength; - strm.next_in = 0; - strm.input = dictionary; - fill_window(s); - while (s.lookahead >= MIN_MATCH$1) { - str = s.strstart; - n = s.lookahead - (MIN_MATCH$1 - 1); - do { - /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH$1 - 1]) & s.hash_mask; - - s.prev[str & s.w_mask] = s.head[s.ins_h]; - - s.head[s.ins_h] = str; - str++; - } while (--n); - s.strstart = str; - s.lookahead = MIN_MATCH$1 - 1; - fill_window(s); - } - s.strstart += s.lookahead; - s.block_start = s.strstart; - s.insert = s.lookahead; - s.lookahead = 0; - s.match_length = s.prev_length = MIN_MATCH$1 - 1; - s.match_available = 0; - strm.next_in = next; - strm.input = input; - strm.avail_in = avail; - s.wrap = wrap; - return Z_OK; -} - -/* Not implemented -exports.deflateBound = deflateBound; -exports.deflateCopy = deflateCopy; -exports.deflateParams = deflateParams; -exports.deflatePending = deflatePending; -exports.deflatePrime = deflatePrime; -exports.deflateTune = deflateTune; -*/ - -// String encode/decode helpers - -try { - String.fromCharCode.apply(null, [ 0 ]); -} catch (__) { -} -try { - String.fromCharCode.apply(null, new Uint8Array(1)); -} catch (__) { -} - - -// Table with utf8 lengths (calculated by first byte of sequence) -// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS, -// because max possible codepoint is 0x10ffff -const _utf8len = new Buf8(256); -for (let q = 0; q < 256; q++) { - _utf8len[q] = q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1; -} -_utf8len[254] = _utf8len[254] = 1; // Invalid sequence start - - -// convert string to array (typed, when possible) -function string2buf (str) { - let c, c2, m_pos, i, buf_len = 0; - const str_len = str.length; - - // count binary size - for (m_pos = 0; m_pos < str_len; m_pos++) { - c = str.charCodeAt(m_pos); - if ((c & 0xfc00) === 0xd800 && m_pos + 1 < str_len) { - c2 = str.charCodeAt(m_pos + 1); - if ((c2 & 0xfc00) === 0xdc00) { - c = 0x10000 + (c - 0xd800 << 10) + (c2 - 0xdc00); - m_pos++; - } - } - buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4; - } - - // allocate buffer - const buf = new Buf8(buf_len); - - // convert - for (i = 0, m_pos = 0; i < buf_len; m_pos++) { - c = str.charCodeAt(m_pos); - if ((c & 0xfc00) === 0xd800 && m_pos + 1 < str_len) { - c2 = str.charCodeAt(m_pos + 1); - if ((c2 & 0xfc00) === 0xdc00) { - c = 0x10000 + (c - 0xd800 << 10) + (c2 - 0xdc00); - m_pos++; - } - } - if (c < 0x80) { - /* one byte */ - buf[i++] = c; - } else if (c < 0x800) { - /* two bytes */ - buf[i++] = 0xC0 | c >>> 6; - buf[i++] = 0x80 | c & 0x3f; - } else if (c < 0x10000) { - /* three bytes */ - buf[i++] = 0xE0 | c >>> 12; - buf[i++] = 0x80 | c >>> 6 & 0x3f; - buf[i++] = 0x80 | c & 0x3f; - } else { - /* four bytes */ - buf[i++] = 0xf0 | c >>> 18; - buf[i++] = 0x80 | c >>> 12 & 0x3f; - buf[i++] = 0x80 | c >>> 6 & 0x3f; - buf[i++] = 0x80 | c & 0x3f; - } - } - - return buf; -} - - -// Convert binary string (typed, when possible) -function binstring2buf (str) { - const buf = new Buf8(str.length); - for (let i = 0, len = buf.length; i < len; i++) { - buf[i] = str.charCodeAt(i); - } - return buf; -} - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -class ZStream { - constructor() { - /* next input byte */ - this.input = null; // JS specific, because we have no pointers - this.next_in = 0; - /* number of bytes available at input */ - this.avail_in = 0; - /* total number of input bytes read so far */ - this.total_in = 0; - /* next output byte should be put there */ - this.output = null; // JS specific, because we have no pointers - this.next_out = 0; - /* remaining free space at output */ - this.avail_out = 0; - /* total number of bytes output so far */ - this.total_out = 0; - /* last error message, NULL if no error */ - this.msg = ''/*Z_NULL*/; - /* not visible by applications */ - this.state = null; - /* best guess about the data type: binary or text */ - this.data_type = 2/*Z_UNKNOWN*/; - /* adler32 value of the uncompressed data */ - this.adler = 0; - } -} - -/* ===========================================================================*/ - - -/** - * class Deflate - * - * Generic JS-style wrapper for zlib calls. If you don't need - * streaming behaviour - use more simple functions: [[deflate]], - * [[deflateRaw]] and [[gzip]]. - **/ - -/* internal - * Deflate.chunks -> Array - * - * Chunks of output data, if [[Deflate#onData]] not overridden. - **/ - -/** - * Deflate.result -> Uint8Array|Array - * - * Compressed result, generated by default [[Deflate#onData]] - * and [[Deflate#onEnd]] handlers. Filled after you push last chunk - * (call [[Deflate#push]] with `Z_FINISH` / `true` param) or if you - * push a chunk with explicit flush (call [[Deflate#push]] with - * `Z_SYNC_FLUSH` param). - **/ - -/** - * Deflate.err -> Number - * - * Error code after deflate finished. 0 (Z_OK) on success. - * You will not need it in real life, because deflate errors - * are possible only on wrong options or bad `onData` / `onEnd` - * custom handlers. - **/ - -/** - * Deflate.msg -> String - * - * Error message, if [[Deflate.err]] != 0 - **/ - - -/** - * new Deflate(options) - * - options (Object): zlib deflate options. - * - * Creates new deflator instance with specified params. Throws exception - * on bad params. Supported options: - * - * - `level` - * - `windowBits` - * - `memLevel` - * - `strategy` - * - `dictionary` - * - * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) - * for more information on these. - * - * Additional options, for internal needs: - * - * - `chunkSize` - size of generated data chunks (16K by default) - * - `raw` (Boolean) - do raw deflate - * - `gzip` (Boolean) - create gzip wrapper - * - `to` (String) - if equal to 'string', then result will be "binary string" - * (each char code [0..255]) - * - `header` (Object) - custom header for gzip - * - `text` (Boolean) - true if compressed data believed to be text - * - `time` (Number) - modification time, unix timestamp - * - `os` (Number) - operation system code - * - `extra` (Array) - array of bytes with extra data (max 65536) - * - `name` (String) - file name (binary string) - * - `comment` (String) - comment (binary string) - * - `hcrc` (Boolean) - true if header crc should be added - * - * ##### Example: - * - * ```javascript - * var pako = require('pako') - * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9]) - * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]); - * - * var deflate = new pako.Deflate({ level: 3}); - * - * deflate.push(chunk1, false); - * deflate.push(chunk2, true); // true -> last chunk - * - * if (deflate.err) { throw new Error(deflate.err); } - * - * console.log(deflate.result); - * ``` - **/ - -class Deflate { - constructor(options) { - this.options = { - level: Z_DEFAULT_COMPRESSION, - method: Z_DEFLATED, - chunkSize: 16384, - windowBits: 15, - memLevel: 8, - strategy: Z_DEFAULT_STRATEGY, - ...(options || {}) - }; - - const opt = this.options; - - if (opt.raw && (opt.windowBits > 0)) { - opt.windowBits = -opt.windowBits; - } - - else if (opt.gzip && (opt.windowBits > 0) && (opt.windowBits < 16)) { - opt.windowBits += 16; - } - - this.err = 0; // error code, if happens (0 = Z_OK) - this.msg = ''; // error message - this.ended = false; // used to avoid multiple onEnd() calls - this.chunks = []; // chunks of compressed data - - this.strm = new ZStream(); - this.strm.avail_out = 0; - - var status = deflateInit2( - this.strm, - opt.level, - opt.method, - opt.windowBits, - opt.memLevel, - opt.strategy - ); - - if (status !== Z_OK) { - throw new Error(msg[status]); - } - - if (opt.header) { - deflateSetHeader(this.strm, opt.header); - } - - if (opt.dictionary) { - let dict; - // Convert data if needed - if (typeof opt.dictionary === 'string') { - // If we need to compress text, change encoding to utf8. - dict = string2buf(opt.dictionary); - } else if (opt.dictionary instanceof ArrayBuffer) { - dict = new Uint8Array(opt.dictionary); - } else { - dict = opt.dictionary; - } - - status = deflateSetDictionary(this.strm, dict); - - if (status !== Z_OK) { - throw new Error(msg[status]); - } - - this._dict_set = true; - } - } - - /** - * Deflate#push(data[, mode]) -> Boolean - * - data (Uint8Array|Array|ArrayBuffer|String): input data. Strings will be - * converted to utf8 byte sequence. - * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. - * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH. - * - * Sends input data to deflate pipe, generating [[Deflate#onData]] calls with - * new compressed chunks. Returns `true` on success. The last data block must have - * mode Z_FINISH (or `true`). That will flush internal pending buffers and call - * [[Deflate#onEnd]]. For interim explicit flushes (without ending the stream) you - * can use mode Z_SYNC_FLUSH, keeping the compression context. - * - * On fail call [[Deflate#onEnd]] with error code and return false. - * - * We strongly recommend to use `Uint8Array` on input for best speed (output - * array format is detected automatically). Also, don't skip last param and always - * use the same type in your code (boolean or number). That will improve JS speed. - * - * For regular `Array`-s make sure all elements are [0..255]. - * - * ##### Example - * - * ```javascript - * push(chunk, false); // push one of data chunks - * ... - * push(chunk, true); // push last chunk - * ``` - **/ - push(data, mode) { - const { strm, options: { chunkSize } } = this; - var status, _mode; - - if (this.ended) { return false; } - - _mode = (mode === ~~mode) ? mode : ((mode === true) ? Z_FINISH : Z_NO_FLUSH); - - // Convert data if needed - if (typeof data === 'string') { - // If we need to compress text, change encoding to utf8. - strm.input = string2buf(data); - } else if (data instanceof ArrayBuffer) { - strm.input = new Uint8Array(data); - } else { - strm.input = data; - } - - strm.next_in = 0; - strm.avail_in = strm.input.length; - - do { - if (strm.avail_out === 0) { - strm.output = new Buf8(chunkSize); - strm.next_out = 0; - strm.avail_out = chunkSize; - } - status = deflate(strm, _mode); /* no bad return value */ - - if (status !== Z_STREAM_END && status !== Z_OK) { - this.onEnd(status); - this.ended = true; - return false; - } - if (strm.avail_out === 0 || (strm.avail_in === 0 && (_mode === Z_FINISH || _mode === Z_SYNC_FLUSH))) { - this.onData(shrinkBuf(strm.output, strm.next_out)); - } - } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== Z_STREAM_END); - - // Finalize on the last chunk. - if (_mode === Z_FINISH) { - status = deflateEnd(this.strm); - this.onEnd(status); - this.ended = true; - return status === Z_OK; - } - - // callback interim results if Z_SYNC_FLUSH. - if (_mode === Z_SYNC_FLUSH) { - this.onEnd(Z_OK); - strm.avail_out = 0; - return true; - } - - return true; - }; - /** - * Deflate#onData(chunk) -> Void - * - chunk (Uint8Array|Array|String): output data. Type of array depends - * on js engine support. When string output requested, each chunk - * will be string. - * - * By default, stores data blocks in `chunks[]` property and glue - * those in `onEnd`. Override this handler, if you need another behaviour. - **/ - onData(chunk) { - this.chunks.push(chunk); - }; - - /** - * Deflate#onEnd(status) -> Void - * - status (Number): deflate status. 0 (Z_OK) on success, - * other if not. - * - * Called once after you tell deflate that the input stream is - * complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH) - * or if an error happened. By default - join collected chunks, - * free memory and fill `results` / `err` properties. - **/ - onEnd(status) { - // On success - join - if (status === Z_OK) { - this.result = flattenChunks(this.chunks); - } - this.chunks = []; - this.err = status; - this.msg = this.strm.msg; - }; -} - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -// See state defs from inflate.js -const BAD = 30; /* got a data error -- remain here until reset */ -const TYPE = 12; /* i: waiting for type bits, including last-flag bit */ - -/* - Decode literal, length, and distance codes and write out the resulting - literal and match bytes until either not enough input or output is - available, an end-of-block is encountered, or a data error is encountered. - When large enough input and output buffers are supplied to inflate(), for - example, a 16K input buffer and a 64K output buffer, more than 95% of the - inflate execution time is spent in this routine. - - Entry assumptions: - - state.mode === LEN - strm.avail_in >= 6 - strm.avail_out >= 258 - start >= strm.avail_out - state.bits < 8 - - On return, state.mode is one of: - - LEN -- ran out of enough output space or enough available input - TYPE -- reached end of block code, inflate() to interpret next block - BAD -- error in block data - - Notes: - - - The maximum input bits used by a length/distance pair is 15 bits for the - length code, 5 bits for the length extra, 15 bits for the distance code, - and 13 bits for the distance extra. This totals 48 bits, or six bytes. - Therefore if strm.avail_in >= 6, then there is enough input to avoid - checking for available input while decoding. - - - The maximum bytes that a single length/distance pair can output is 258 - bytes, which is the maximum length that can be coded. inflate_fast() - requires strm.avail_out >= 258 for each loop to avoid checking for - output space. - */ -function inflate_fast(strm, start) { - let _in; /* local strm.input */ - let _out; /* local strm.output */ - // Use `s_window` instead `window`, avoid conflict with instrumentation tools - let hold; /* local strm.hold */ - let bits; /* local strm.bits */ - let here; /* retrieved table entry */ - let op; /* code bits, operation, extra bits, or */ - /* window position, window bytes to copy */ - let len; /* match length, unused bytes */ - let dist; /* match distance */ - let from; /* where to copy match from */ - let from_source; - - - - /* copy state to local variables */ - const state = strm.state; - //here = state.here; - _in = strm.next_in; - const input = strm.input; - const last = _in + (strm.avail_in - 5); - _out = strm.next_out; - const output = strm.output; - const beg = _out - (start - strm.avail_out); - const end = _out + (strm.avail_out - 257); - //#ifdef INFLATE_STRICT - const dmax = state.dmax; - //#endif - const wsize = state.wsize; - const whave = state.whave; - const wnext = state.wnext; - const s_window = state.window; - hold = state.hold; - bits = state.bits; - const lcode = state.lencode; - const dcode = state.distcode; - const lmask = (1 << state.lenbits) - 1; - const dmask = (1 << state.distbits) - 1; - - - /* decode literals and length/distances until end-of-block or not enough - input data or output space */ - - top: - do { - if (bits < 15) { - hold += input[_in++] << bits; - bits += 8; - hold += input[_in++] << bits; - bits += 8; - } - - here = lcode[hold & lmask]; - - dolen: - for (;;) { // Goto emulation - op = here >>> 24/*here.bits*/; - hold >>>= op; - bits -= op; - op = here >>> 16 & 0xff/*here.op*/; - if (op === 0) { /* literal */ - //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - // "inflate: literal '%c'\n" : - // "inflate: literal 0x%02x\n", here.val)); - output[_out++] = here & 0xffff/*here.val*/; - } else if (op & 16) { /* length base */ - len = here & 0xffff/*here.val*/; - op &= 15; /* number of extra bits */ - if (op) { - if (bits < op) { - hold += input[_in++] << bits; - bits += 8; - } - len += hold & (1 << op) - 1; - hold >>>= op; - bits -= op; - } - //Tracevv((stderr, "inflate: length %u\n", len)); - if (bits < 15) { - hold += input[_in++] << bits; - bits += 8; - hold += input[_in++] << bits; - bits += 8; - } - here = dcode[hold & dmask]; - - dodist: - for (;;) { // goto emulation - op = here >>> 24/*here.bits*/; - hold >>>= op; - bits -= op; - op = here >>> 16 & 0xff/*here.op*/; - - if (op & 16) { /* distance base */ - dist = here & 0xffff/*here.val*/; - op &= 15; /* number of extra bits */ - if (bits < op) { - hold += input[_in++] << bits; - bits += 8; - if (bits < op) { - hold += input[_in++] << bits; - bits += 8; - } - } - dist += hold & (1 << op) - 1; - //#ifdef INFLATE_STRICT - if (dist > dmax) { - strm.msg = "invalid distance too far back"; - state.mode = BAD; - break top; - } - //#endif - hold >>>= op; - bits -= op; - //Tracevv((stderr, "inflate: distance %u\n", dist)); - op = _out - beg; /* max distance in output */ - if (dist > op) { /* see if copy from window */ - op = dist - op; /* distance back in window */ - if (op > whave) { - if (state.sane) { - strm.msg = "invalid distance too far back"; - state.mode = BAD; - break top; - } - - // (!) This block is disabled in zlib defaults, - // don't enable it for binary compatibility - //#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR - // if (len <= op - whave) { - // do { - // output[_out++] = 0; - // } while (--len); - // continue top; - // } - // len -= op - whave; - // do { - // output[_out++] = 0; - // } while (--op > whave); - // if (op === 0) { - // from = _out - dist; - // do { - // output[_out++] = output[from++]; - // } while (--len); - // continue top; - // } - //#endif - } - from = 0; // window index - from_source = s_window; - if (wnext === 0) { /* very common case */ - from += wsize - op; - if (op < len) { /* some from window */ - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = _out - dist; /* rest from output */ - from_source = output; - } - } else if (wnext < op) { /* wrap around window */ - from += wsize + wnext - op; - op -= wnext; - if (op < len) { /* some from end of window */ - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = 0; - if (wnext < len) { /* some from start of window */ - op = wnext; - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = _out - dist; /* rest from output */ - from_source = output; - } - } - } else { /* contiguous in window */ - from += wnext - op; - if (op < len) { /* some from window */ - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = _out - dist; /* rest from output */ - from_source = output; - } - } - while (len > 2) { - output[_out++] = from_source[from++]; - output[_out++] = from_source[from++]; - output[_out++] = from_source[from++]; - len -= 3; - } - if (len) { - output[_out++] = from_source[from++]; - if (len > 1) { - output[_out++] = from_source[from++]; - } - } - } else { - from = _out - dist; /* copy direct from output */ - do { /* minimum length is three */ - output[_out++] = output[from++]; - output[_out++] = output[from++]; - output[_out++] = output[from++]; - len -= 3; - } while (len > 2); - if (len) { - output[_out++] = output[from++]; - if (len > 1) { - output[_out++] = output[from++]; - } - } - } - } else if ((op & 64) === 0) { /* 2nd level distance code */ - here = dcode[(here & 0xffff)/*here.val*/ + (hold & (1 << op) - 1)]; - continue dodist; - } else { - strm.msg = "invalid distance code"; - state.mode = BAD; - break top; - } - - break; // need to emulate goto via "continue" - } - } else if ((op & 64) === 0) { /* 2nd level length code */ - here = lcode[(here & 0xffff)/*here.val*/ + (hold & (1 << op) - 1)]; - continue dolen; - } else if (op & 32) { /* end-of-block */ - //Tracevv((stderr, "inflate: end of block\n")); - state.mode = TYPE; - break top; - } else { - strm.msg = "invalid literal/length code"; - state.mode = BAD; - break top; - } - - break; // need to emulate goto via "continue" - } - } while (_in < last && _out < end); - - /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ - len = bits >> 3; - _in -= len; - bits -= len << 3; - hold &= (1 << bits) - 1; - - /* update state and return */ - strm.next_in = _in; - strm.next_out = _out; - strm.avail_in = _in < last ? 5 + (last - _in) : 5 - (_in - last); - strm.avail_out = _out < end ? 257 + (end - _out) : 257 - (_out - end); - state.hold = hold; - state.bits = bits; - return; -} - -const MAXBITS = 15; -const ENOUGH_LENS = 852; -const ENOUGH_DISTS = 592; -//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); - -const CODES = 0; -const LENS = 1; -const DISTS = 2; - -const lbase = [ /* Length codes 257..285 base */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 -]; - -const lext = [ /* Length codes 257..285 extra */ - 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78 -]; - -const dbase = [ /* Distance codes 0..29 base */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577, 0, 0 -]; - -const dext = [ /* Distance codes 0..29 extra */ - 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, - 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, - 28, 28, 29, 29, 64, 64 -]; - -function inflate_table(type, lens, lens_index, codes, table, table_index, work, opts) { - const bits = opts.bits; - //here = opts.here; /* table entry for duplication */ - - let len = 0; /* a code's length in bits */ - let sym = 0; /* index of code symbols */ - let min = 0, max = 0; /* minimum and maximum code lengths */ - let root = 0; /* number of index bits for root table */ - let curr = 0; /* number of index bits for current table */ - let drop = 0; /* code bits to drop for sub-table */ - let left = 0; /* number of prefix codes available */ - let used = 0; /* code entries in table used */ - let huff = 0; /* Huffman code */ - let incr; /* for incrementing code, index */ - let fill; /* index for replicating entries */ - let low; /* low bits for current root entry */ - let next; /* next available space in table */ - let base = null; /* base value table to use */ - let base_index = 0; - // var shoextra; /* extra bits table to use */ - let end; /* use base and extra for symbol > end */ - const count = new Buf16(MAXBITS + 1); //[MAXBITS+1]; /* number of codes of each length */ - const offs = new Buf16(MAXBITS + 1); //[MAXBITS+1]; /* offsets in table for each length */ - let extra = null; - let extra_index = 0; - - let here_bits, here_op, here_val; - - /* - Process a set of code lengths to create a canonical Huffman code. The - code lengths are lens[0..codes-1]. Each length corresponds to the - symbols 0..codes-1. The Huffman code is generated by first sorting the - symbols by length from short to long, and retaining the symbol order - for codes with equal lengths. Then the code starts with all zero bits - for the first code of the shortest length, and the codes are integer - increments for the same length, and zeros are appended as the length - increases. For the deflate format, these bits are stored backwards - from their more natural integer increment ordering, and so when the - decoding tables are built in the large loop below, the integer codes - are incremented backwards. - - This routine assumes, but does not check, that all of the entries in - lens[] are in the range 0..MAXBITS. The caller must assure this. - 1..MAXBITS is interpreted as that code length. zero means that that - symbol does not occur in this code. - - The codes are sorted by computing a count of codes for each length, - creating from that a table of starting indices for each length in the - sorted table, and then entering the symbols in order in the sorted - table. The sorted table is work[], with that space being provided by - the caller. - - The length counts are used for other purposes as well, i.e. finding - the minimum and maximum length codes, determining if there are any - codes at all, checking for a valid set of lengths, and looking ahead - at length counts to determine sub-table sizes when building the - decoding tables. - */ - - /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ - for (len = 0; len <= MAXBITS; len++) { - count[len] = 0; - } - for (sym = 0; sym < codes; sym++) { - count[lens[lens_index + sym]]++; - } - - /* bound code lengths, force root to be within code lengths */ - root = bits; - for (max = MAXBITS; max >= 1; max--) { - if (count[max] !== 0) { - break; - } - } - if (root > max) { - root = max; - } - if (max === 0) { /* no symbols to code at all */ - //table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */ - //table.bits[opts.table_index] = 1; //here.bits = (var char)1; - //table.val[opts.table_index++] = 0; //here.val = (var short)0; - table[table_index++] = 1 << 24 | 64 << 16 | 0; - - - //table.op[opts.table_index] = 64; - //table.bits[opts.table_index] = 1; - //table.val[opts.table_index++] = 0; - table[table_index++] = 1 << 24 | 64 << 16 | 0; - - opts.bits = 1; - return 0; /* no symbols, but wait for decoding to report error */ - } - for (min = 1; min < max; min++) { - if (count[min] !== 0) { - break; - } - } - if (root < min) { - root = min; - } - - /* check for an over-subscribed or incomplete set of lengths */ - left = 1; - for (len = 1; len <= MAXBITS; len++) { - left <<= 1; - left -= count[len]; - if (left < 0) { - return -1; - } /* over-subscribed */ - } - if (left > 0 && (type === CODES || max !== 1)) { - return -1; /* incomplete set */ - } - - /* generate offsets into symbol table for each length for sorting */ - offs[1] = 0; - for (len = 1; len < MAXBITS; len++) { - offs[len + 1] = offs[len] + count[len]; - } - - /* sort symbols by length, by symbol order within each length */ - for (sym = 0; sym < codes; sym++) { - if (lens[lens_index + sym] !== 0) { - work[offs[lens[lens_index + sym]]++] = sym; - } - } - - /* - Create and fill in decoding tables. In this loop, the table being - filled is at next and has curr index bits. The code being used is huff - with length len. That code is converted to an index by dropping drop - bits off of the bottom. For codes where len is less than drop + curr, - those top drop + curr - len bits are incremented through all values to - fill the table with replicated entries. - - root is the number of index bits for the root table. When len exceeds - root, sub-tables are created pointed to by the root entry with an index - of the low root bits of huff. This is saved in low to check for when a - new sub-table should be started. drop is zero when the root table is - being filled, and drop is root when sub-tables are being filled. - - When a new sub-table is needed, it is necessary to look ahead in the - code lengths to determine what size sub-table is needed. The length - counts are used for this, and so count[] is decremented as codes are - entered in the tables. - - used keeps track of how many table entries have been allocated from the - provided *table space. It is checked for LENS and DIST tables against - the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in - the initial root table size constants. See the comments in inftrees.h - for more information. - - sym increments through all symbols, and the loop terminates when - all codes of length max, i.e. all codes, have been processed. This - routine permits incomplete codes, so another loop after this one fills - in the rest of the decoding tables with invalid code markers. - */ - - /* set up for code type */ - // poor man optimization - use if-else instead of switch, - // to avoid deopts in old v8 - if (type === CODES) { - base = extra = work; /* dummy value--not used */ - end = 19; - - } else if (type === LENS) { - base = lbase; - base_index -= 257; - extra = lext; - extra_index -= 257; - end = 256; - - } else { /* DISTS */ - base = dbase; - extra = dext; - end = -1; - } - - /* initialize opts for loop */ - huff = 0; /* starting code */ - sym = 0; /* starting code symbol */ - len = min; /* starting code length */ - next = table_index; /* current table to fill in */ - curr = root; /* current table index bits */ - drop = 0; /* current bits to drop from code for index */ - low = -1; /* trigger new sub-table when len > root */ - used = 1 << root; /* use root table entries */ - const mask = used - 1; /* mask for comparing low */ - - /* check available table space */ - if (type === LENS && used > ENOUGH_LENS || - type === DISTS && used > ENOUGH_DISTS) { - return 1; - } - - /* process all codes and make table entries */ - for (;;) { - /* create table entry */ - here_bits = len - drop; - if (work[sym] < end) { - here_op = 0; - here_val = work[sym]; - } else if (work[sym] > end) { - here_op = extra[extra_index + work[sym]]; - here_val = base[base_index + work[sym]]; - } else { - here_op = 32 + 64; /* end of block */ - here_val = 0; - } - - /* replicate for those indices with low len bits equal to huff */ - incr = 1 << len - drop; - fill = 1 << curr; - min = fill; /* save offset to next table */ - do { - fill -= incr; - table[next + (huff >> drop) + fill] = here_bits << 24 | here_op << 16 | here_val |0; - } while (fill !== 0); - - /* backwards increment the len-bit code huff */ - incr = 1 << len - 1; - while (huff & incr) { - incr >>= 1; - } - if (incr !== 0) { - huff &= incr - 1; - huff += incr; - } else { - huff = 0; - } - - /* go to next symbol, update count, len */ - sym++; - if (--count[len] === 0) { - if (len === max) { - break; - } - len = lens[lens_index + work[sym]]; - } - - /* create new sub-table if needed */ - if (len > root && (huff & mask) !== low) { - /* if first time, transition to sub-tables */ - if (drop === 0) { - drop = root; - } - - /* increment past last table */ - next += min; /* here min is 1 << curr */ - - /* determine length of next table */ - curr = len - drop; - left = 1 << curr; - while (curr + drop < max) { - left -= count[curr + drop]; - if (left <= 0) { - break; - } - curr++; - left <<= 1; - } - - /* check for enough space */ - used += 1 << curr; - if (type === LENS && used > ENOUGH_LENS || - type === DISTS && used > ENOUGH_DISTS) { - return 1; - } - - /* point entry in root table to sub-table */ - low = huff & mask; - /*table.op[low] = curr; - table.bits[low] = root; - table.val[low] = next - opts.table_index;*/ - table[low] = root << 24 | curr << 16 | next - table_index |0; - } - } - - /* fill in remaining table entry if code is incomplete (guaranteed to have - at most one remaining entry, since if the code is incomplete, the - maximum code length that was allowed to get this far is one bit) */ - if (huff !== 0) { - //table.op[next + huff] = 64; /* invalid code marker */ - //table.bits[next + huff] = len - drop; - //table.val[next + huff] = 0; - table[next + huff] = len - drop << 24 | 64 << 16 |0; - } - - /* set return parameters */ - //opts.table_index += used; - opts.bits = root; - return 0; -} - -const CODES$1 = 0; -const LENS$1 = 1; -const DISTS$1 = 2; - -/* STATES ====================================================================*/ -/* ===========================================================================*/ - - -const HEAD = 1; /* i: waiting for magic header */ -const FLAGS = 2; /* i: waiting for method and flags (gzip) */ -const TIME = 3; /* i: waiting for modification time (gzip) */ -const OS = 4; /* i: waiting for extra flags and operating system (gzip) */ -const EXLEN = 5; /* i: waiting for extra length (gzip) */ -const EXTRA = 6; /* i: waiting for extra bytes (gzip) */ -const NAME = 7; /* i: waiting for end of file name (gzip) */ -const COMMENT = 8; /* i: waiting for end of comment (gzip) */ -const HCRC = 9; /* i: waiting for header crc (gzip) */ -const DICTID = 10; /* i: waiting for dictionary check value */ -const DICT = 11; /* waiting for inflateSetDictionary() call */ -const TYPE$1 = 12; /* i: waiting for type bits, including last-flag bit */ -const TYPEDO = 13; /* i: same, but skip check to exit inflate on new block */ -const STORED = 14; /* i: waiting for stored size (length and complement) */ -const COPY_ = 15; /* i/o: same as COPY below, but only first time in */ -const COPY = 16; /* i/o: waiting for input or output to copy stored block */ -const TABLE = 17; /* i: waiting for dynamic block table lengths */ -const LENLENS = 18; /* i: waiting for code length code lengths */ -const CODELENS = 19; /* i: waiting for length/lit and distance code lengths */ -const LEN_ = 20; /* i: same as LEN below, but only first time in */ -const LEN = 21; /* i: waiting for length/lit/eob code */ -const LENEXT = 22; /* i: waiting for length extra bits */ -const DIST = 23; /* i: waiting for distance code */ -const DISTEXT = 24; /* i: waiting for distance extra bits */ -const MATCH = 25; /* o: waiting for output space to copy string */ -const LIT = 26; /* o: waiting for output space to write literal */ -const CHECK = 27; /* i: waiting for 32-bit check value */ -const LENGTH = 28; /* i: waiting for 32-bit length (gzip) */ -const DONE = 29; /* finished check, done -- remain here until reset */ -const BAD$1 = 30; /* got a data error -- remain here until reset */ -//const MEM = 31; /* got an inflate() memory error -- remain here until reset */ -const SYNC = 32; /* looking for synchronization bytes to restart inflate() */ - -/* ===========================================================================*/ - - - -const ENOUGH_LENS$1 = 852; -const ENOUGH_DISTS$1 = 592; - - -function zswap32(q) { - return (((q >>> 24) & 0xff) + - ((q >>> 8) & 0xff00) + - ((q & 0xff00) << 8) + - ((q & 0xff) << 24)); -} - - -class InflateState { - constructor() { - this.mode = 0; /* current inflate mode */ - this.last = false; /* true if processing last block */ - this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ - this.havedict = false; /* true if dictionary provided */ - this.flags = 0; /* gzip header method and flags (0 if zlib) */ - this.dmax = 0; /* zlib header max distance (INFLATE_STRICT) */ - this.check = 0; /* protected copy of check value */ - this.total = 0; /* protected copy of output count */ - // TODO: may be {} - this.head = null; /* where to save gzip header information */ - - /* sliding window */ - this.wbits = 0; /* log base 2 of requested window size */ - this.wsize = 0; /* window size or zero if not using window */ - this.whave = 0; /* valid bytes in the window */ - this.wnext = 0; /* window write index */ - this.window = null; /* allocated sliding window, if needed */ - - /* bit accumulator */ - this.hold = 0; /* input bit accumulator */ - this.bits = 0; /* number of bits in "in" */ - - /* for string and stored block copying */ - this.length = 0; /* literal or length of data to copy */ - this.offset = 0; /* distance back to copy string from */ - - /* for table and code decoding */ - this.extra = 0; /* extra bits needed */ - - /* fixed and dynamic code tables */ - this.lencode = null; /* starting table for length/literal codes */ - this.distcode = null; /* starting table for distance codes */ - this.lenbits = 0; /* index bits for lencode */ - this.distbits = 0; /* index bits for distcode */ - - /* dynamic table building */ - this.ncode = 0; /* number of code length code lengths */ - this.nlen = 0; /* number of length code lengths */ - this.ndist = 0; /* number of distance code lengths */ - this.have = 0; /* number of code lengths in lens[] */ - this.next = null; /* next available space in codes[] */ - - this.lens = new Buf16(320); /* temporary storage for code lengths */ - this.work = new Buf16(288); /* work area for code table building */ - - /* - because we don't have pointers in js, we use lencode and distcode directly - as buffers so we don't need codes - */ - //this.codes = new utils.Buf32(ENOUGH); /* space for code tables */ - this.lendyn = null; /* dynamic table for length/literal codes (JS specific) */ - this.distdyn = null; /* dynamic table for distance codes (JS specific) */ - this.sane = 0; /* if false, allow invalid distance too far */ - this.back = 0; /* bits back of last unprocessed length/lit */ - this.was = 0; /* initial length of match */ - } -} - -function inflateResetKeep(strm) { - let state; - - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - strm.total_in = strm.total_out = state.total = 0; - strm.msg = ''; /*Z_NULL*/ - if (state.wrap) { /* to support ill-conceived Java test suite */ - strm.adler = state.wrap & 1; - } - state.mode = HEAD; - state.last = 0; - state.havedict = 0; - state.dmax = 32768; - state.head = null/*Z_NULL*/; - state.hold = 0; - state.bits = 0; - //state.lencode = state.distcode = state.next = state.codes; - state.lencode = state.lendyn = new Buf32(ENOUGH_LENS$1); - state.distcode = state.distdyn = new Buf32(ENOUGH_DISTS$1); - - state.sane = 1; - state.back = -1; - //Tracev((stderr, "inflate: reset\n")); - return Z_OK; -} - -function inflateReset(strm) { - let state; - - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - state.wsize = 0; - state.whave = 0; - state.wnext = 0; - return inflateResetKeep(strm); - -} - -function inflateReset2(strm, windowBits) { - let wrap; - let state; - - /* get the state */ - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - - /* extract wrap request from windowBits parameter */ - if (windowBits < 0) { - wrap = 0; - windowBits = -windowBits; - } - else { - wrap = (windowBits >> 4) + 1; - if (windowBits < 48) { - windowBits &= 15; - } - } - - /* set number of window bits, free window if different */ - if (windowBits && (windowBits < 8 || windowBits > 15)) { - return Z_STREAM_ERROR; - } - if (state.window !== null && state.wbits !== windowBits) { - state.window = null; - } - - /* update state and reset the rest of it */ - state.wrap = wrap; - state.wbits = windowBits; - return inflateReset(strm); -} - -function inflateInit2(strm, windowBits) { - let ret; - let state; - - if (!strm) { return Z_STREAM_ERROR; } - //strm.msg = Z_NULL; /* in case we return an error */ - - state = new InflateState(); - - //if (state === Z_NULL) return Z_MEM_ERROR; - //Tracev((stderr, "inflate: allocated\n")); - strm.state = state; - state.window = null/*Z_NULL*/; - ret = inflateReset2(strm, windowBits); - if (ret !== Z_OK) { - strm.state = null/*Z_NULL*/; - } - return ret; -} - - -/* - Return state with length and distance decoding tables and index sizes set to - fixed code decoding. Normally this returns fixed tables from inffixed.h. - If BUILDFIXED is defined, then instead this routine builds the tables the - first time it's called, and returns those tables the first time and - thereafter. This reduces the size of the code by about 2K bytes, in - exchange for a little execution time. However, BUILDFIXED should not be - used for threaded applications, since the rewriting of the tables and virgin - may not be thread-safe. - */ -let virgin = true; - -let lenfix, distfix; // We have no pointers in JS, so keep tables separate - -function fixedtables(state) { - /* build fixed huffman tables if first call (may not be thread safe) */ - if (virgin) { - let sym; - - lenfix = new Buf32(512); - distfix = new Buf32(32); - - /* literal/length table */ - sym = 0; - while (sym < 144) { state.lens[sym++] = 8; } - while (sym < 256) { state.lens[sym++] = 9; } - while (sym < 280) { state.lens[sym++] = 7; } - while (sym < 288) { state.lens[sym++] = 8; } - - inflate_table(LENS$1, state.lens, 0, 288, lenfix, 0, state.work, { bits: 9 }); - - /* distance table */ - sym = 0; - while (sym < 32) { state.lens[sym++] = 5; } - - inflate_table(DISTS$1, state.lens, 0, 32, distfix, 0, state.work, { bits: 5 }); - - /* do this just once */ - virgin = false; - } - - state.lencode = lenfix; - state.lenbits = 9; - state.distcode = distfix; - state.distbits = 5; -} - - -/* - Update the window with the last wsize (normally 32K) bytes written before - returning. If window does not exist yet, create it. This is only called - when a window is already in use, or when output has been written during this - inflate call, but the end of the deflate stream has not been reached yet. - It is also called to create a window for dictionary data when a dictionary - is loaded. - - Providing output buffers larger than 32K to inflate() should provide a speed - advantage, since only the last 32K of output is copied to the sliding window - upon return from inflate(), and since all distances after the first 32K of - output will fall in the output data, making match copies simpler and faster. - The advantage may be dependent on the size of the processor's data caches. - */ -function updatewindow(strm, src, end, copy) { - let dist; - const state = strm.state; - - /* if it hasn't been done already, allocate space for the window */ - if (state.window === null) { - state.wsize = 1 << state.wbits; - state.wnext = 0; - state.whave = 0; - - state.window = new Buf8(state.wsize); - } - - /* copy state->wsize or less output bytes into the circular window */ - if (copy >= state.wsize) { - arraySet(state.window, src, end - state.wsize, state.wsize, 0); - state.wnext = 0; - state.whave = state.wsize; - } - else { - dist = state.wsize - state.wnext; - if (dist > copy) { - dist = copy; - } - //zmemcpy(state->window + state->wnext, end - copy, dist); - arraySet(state.window, src, end - copy, dist, state.wnext); - copy -= dist; - if (copy) { - //zmemcpy(state->window, end - copy, copy); - arraySet(state.window, src, end - copy, copy, 0); - state.wnext = copy; - state.whave = state.wsize; - } - else { - state.wnext += dist; - if (state.wnext === state.wsize) { state.wnext = 0; } - if (state.whave < state.wsize) { state.whave += dist; } - } - } - return 0; -} - -function inflate(strm, flush) { - let state; - let input, output; // input/output buffers - let next; /* next input INDEX */ - let put; /* next output INDEX */ - let have, left; /* available input and output */ - let hold; /* bit buffer */ - let bits; /* bits in bit buffer */ - let _in, _out; /* save starting available input and output */ - let copy; /* number of stored or match bytes to copy */ - let from; /* where to copy match bytes from */ - let from_source; - let here = 0; /* current decoding table entry */ - let here_bits, here_op, here_val; // paked "here" denormalized (JS specific) - //var last; /* parent table entry */ - let last_bits, last_op, last_val; // paked "last" denormalized (JS specific) - let len; /* length to copy for repeats, bits to drop */ - let ret; /* return code */ - let hbuf = new Buf8(4); /* buffer for gzip header crc calculation */ - let opts; - - let n; // temporary var for NEED_BITS - - const order = /* permutation of code lengths */ - [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ]; - - - if (!strm || !strm.state || !strm.output || - (!strm.input && strm.avail_in !== 0)) { - return Z_STREAM_ERROR; - } - - state = strm.state; - if (state.mode === TYPE$1) { state.mode = TYPEDO; } /* skip check */ - - - //--- LOAD() --- - put = strm.next_out; - output = strm.output; - left = strm.avail_out; - next = strm.next_in; - input = strm.input; - have = strm.avail_in; - hold = state.hold; - bits = state.bits; - //--- - - _in = have; - _out = left; - ret = Z_OK; - - inf_leave: // goto emulation - for (;;) { - switch (state.mode) { - case HEAD: - if (state.wrap === 0) { - state.mode = TYPEDO; - break; - } - //=== NEEDBITS(16); - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if ((state.wrap & 2) && hold === 0x8b1f) { /* gzip header */ - state.check = 0/*crc32(0L, Z_NULL, 0)*/; - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = FLAGS; - break; - } - state.flags = 0; /* expect zlib header */ - if (state.head) { - state.head.done = false; - } - if (!(state.wrap & 1) || /* check if zlib header allowed */ - (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) { - strm.msg = 'incorrect header check'; - state.mode = BAD$1; - break; - } - if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) { - strm.msg = 'unknown compression method'; - state.mode = BAD$1; - break; - } - //--- DROPBITS(4) ---// - hold >>>= 4; - bits -= 4; - //---// - len = (hold & 0x0f)/*BITS(4)*/ + 8; - if (state.wbits === 0) { - state.wbits = len; - } - else if (len > state.wbits) { - strm.msg = 'invalid window size'; - state.mode = BAD$1; - break; - } - state.dmax = 1 << len; - //Tracev((stderr, "inflate: zlib header ok\n")); - strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; - state.mode = hold & 0x200 ? DICTID : TYPE$1; - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - break; - case FLAGS: - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.flags = hold; - if ((state.flags & 0xff) !== Z_DEFLATED) { - strm.msg = 'unknown compression method'; - state.mode = BAD$1; - break; - } - if (state.flags & 0xe000) { - strm.msg = 'unknown header flags set'; - state.mode = BAD$1; - break; - } - if (state.head) { - state.head.text = ((hold >> 8) & 1); - } - if (state.flags & 0x0200) { - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = TIME; - /* falls through */ - case TIME: - //=== NEEDBITS(32); */ - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (state.head) { - state.head.time = hold; - } - if (state.flags & 0x0200) { - //=== CRC4(state.check, hold) - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - hbuf[2] = (hold >>> 16) & 0xff; - hbuf[3] = (hold >>> 24) & 0xff; - state.check = crc32(state.check, hbuf, 4, 0); - //=== - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = OS; - /* falls through */ - case OS: - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (state.head) { - state.head.xflags = (hold & 0xff); - state.head.os = (hold >> 8); - } - if (state.flags & 0x0200) { - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = EXLEN; - /* falls through */ - case EXLEN: - if (state.flags & 0x0400) { - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.length = hold; - if (state.head) { - state.head.extra_len = hold; - } - if (state.flags & 0x0200) { - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - } - else if (state.head) { - state.head.extra = null/*Z_NULL*/; - } - state.mode = EXTRA; - /* falls through */ - case EXTRA: - if (state.flags & 0x0400) { - copy = state.length; - if (copy > have) { copy = have; } - if (copy) { - if (state.head) { - len = state.head.extra_len - state.length; - if (!state.head.extra) { - // Use untyped array for more convenient processing later - state.head.extra = new Array(state.head.extra_len); - } - arraySet( - state.head.extra, - input, - next, - // extra field is limited to 65536 bytes - // - no need for additional size check - copy, - /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/ - len - ); - //zmemcpy(state.head.extra + len, next, - // len + copy > state.head.extra_max ? - // state.head.extra_max - len : copy); - } - if (state.flags & 0x0200) { - state.check = crc32(state.check, input, copy, next); - } - have -= copy; - next += copy; - state.length -= copy; - } - if (state.length) { break inf_leave; } - } - state.length = 0; - state.mode = NAME; - /* falls through */ - case NAME: - if (state.flags & 0x0800) { - if (have === 0) { break inf_leave; } - copy = 0; - do { - // TODO: 2 or 1 bytes? - len = input[next + copy++]; - /* use constant limit because in js we should not preallocate memory */ - if (state.head && len && - (state.length < 65536 /*state.head.name_max*/)) { - state.head.name += String.fromCharCode(len); - } - } while (len && copy < have); - - if (state.flags & 0x0200) { - state.check = crc32(state.check, input, copy, next); - } - have -= copy; - next += copy; - if (len) { break inf_leave; } - } - else if (state.head) { - state.head.name = null; - } - state.length = 0; - state.mode = COMMENT; - /* falls through */ - case COMMENT: - if (state.flags & 0x1000) { - if (have === 0) { break inf_leave; } - copy = 0; - do { - len = input[next + copy++]; - /* use constant limit because in js we should not preallocate memory */ - if (state.head && len && - (state.length < 65536 /*state.head.comm_max*/)) { - state.head.comment += String.fromCharCode(len); - } - } while (len && copy < have); - if (state.flags & 0x0200) { - state.check = crc32(state.check, input, copy, next); - } - have -= copy; - next += copy; - if (len) { break inf_leave; } - } - else if (state.head) { - state.head.comment = null; - } - state.mode = HCRC; - /* falls through */ - case HCRC: - if (state.flags & 0x0200) { - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (hold !== (state.check & 0xffff)) { - strm.msg = 'header crc mismatch'; - state.mode = BAD$1; - break; - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - } - if (state.head) { - state.head.hcrc = ((state.flags >> 9) & 1); - state.head.done = true; - } - strm.adler = state.check = 0; - state.mode = TYPE$1; - break; - case DICTID: - //=== NEEDBITS(32); */ - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - strm.adler = state.check = zswap32(hold); - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = DICT; - /* falls through */ - case DICT: - if (state.havedict === 0) { - //--- RESTORE() --- - strm.next_out = put; - strm.avail_out = left; - strm.next_in = next; - strm.avail_in = have; - state.hold = hold; - state.bits = bits; - //--- - return Z_NEED_DICT; - } - strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; - state.mode = TYPE$1; - /* falls through */ - case TYPE$1: - if (flush === Z_BLOCK || flush === Z_TREES) { break inf_leave; } - /* falls through */ - case TYPEDO: - if (state.last) { - //--- BYTEBITS() ---// - hold >>>= bits & 7; - bits -= bits & 7; - //---// - state.mode = CHECK; - break; - } - //=== NEEDBITS(3); */ - while (bits < 3) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.last = (hold & 0x01)/*BITS(1)*/; - //--- DROPBITS(1) ---// - hold >>>= 1; - bits -= 1; - //---// - - switch ((hold & 0x03)/*BITS(2)*/) { - case 0: /* stored block */ - //Tracev((stderr, "inflate: stored block%s\n", - // state.last ? " (last)" : "")); - state.mode = STORED; - break; - case 1: /* fixed block */ - fixedtables(state); - //Tracev((stderr, "inflate: fixed codes block%s\n", - // state.last ? " (last)" : "")); - state.mode = LEN_; /* decode codes */ - if (flush === Z_TREES) { - //--- DROPBITS(2) ---// - hold >>>= 2; - bits -= 2; - //---// - break inf_leave; - } - break; - case 2: /* dynamic block */ - //Tracev((stderr, "inflate: dynamic codes block%s\n", - // state.last ? " (last)" : "")); - state.mode = TABLE; - break; - case 3: - strm.msg = 'invalid block type'; - state.mode = BAD$1; - } - //--- DROPBITS(2) ---// - hold >>>= 2; - bits -= 2; - //---// - break; - case STORED: - //--- BYTEBITS() ---// /* go to byte boundary */ - hold >>>= bits & 7; - bits -= bits & 7; - //---// - //=== NEEDBITS(32); */ - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) { - strm.msg = 'invalid stored block lengths'; - state.mode = BAD$1; - break; - } - state.length = hold & 0xffff; - //Tracev((stderr, "inflate: stored length %u\n", - // state.length)); - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = COPY_; - if (flush === Z_TREES) { break inf_leave; } - /* falls through */ - case COPY_: - state.mode = COPY; - /* falls through */ - case COPY: - copy = state.length; - if (copy) { - if (copy > have) { copy = have; } - if (copy > left) { copy = left; } - if (copy === 0) { break inf_leave; } - //--- zmemcpy(put, next, copy); --- - arraySet(output, input, next, copy, put); - //---// - have -= copy; - next += copy; - left -= copy; - put += copy; - state.length -= copy; - break; - } - //Tracev((stderr, "inflate: stored end\n")); - state.mode = TYPE$1; - break; - case TABLE: - //=== NEEDBITS(14); */ - while (bits < 14) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257; - //--- DROPBITS(5) ---// - hold >>>= 5; - bits -= 5; - //---// - state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1; - //--- DROPBITS(5) ---// - hold >>>= 5; - bits -= 5; - //---// - state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4; - //--- DROPBITS(4) ---// - hold >>>= 4; - bits -= 4; - //---// -//#ifndef PKZIP_BUG_WORKAROUND - if (state.nlen > 286 || state.ndist > 30) { - strm.msg = 'too many length or distance symbols'; - state.mode = BAD$1; - break; - } -//#endif - //Tracev((stderr, "inflate: table sizes ok\n")); - state.have = 0; - state.mode = LENLENS; - /* falls through */ - case LENLENS: - while (state.have < state.ncode) { - //=== NEEDBITS(3); - while (bits < 3) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.lens[order[state.have++]] = (hold & 0x07);//BITS(3); - //--- DROPBITS(3) ---// - hold >>>= 3; - bits -= 3; - //---// - } - while (state.have < 19) { - state.lens[order[state.have++]] = 0; - } - // We have separate tables & no pointers. 2 commented lines below not needed. - //state.next = state.codes; - //state.lencode = state.next; - // Switch to use dynamic table - state.lencode = state.lendyn; - state.lenbits = 7; - - opts = { bits: state.lenbits }; - ret = inflate_table(CODES$1, state.lens, 0, 19, state.lencode, 0, state.work, opts); - state.lenbits = opts.bits; - - if (ret) { - strm.msg = 'invalid code lengths set'; - state.mode = BAD$1; - break; - } - //Tracev((stderr, "inflate: code lengths ok\n")); - state.have = 0; - state.mode = CODELENS; - /* falls through */ - case CODELENS: - while (state.have < state.nlen + state.ndist) { - for (;;) { - here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/ - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - if (here_val < 16) { - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - state.lens[state.have++] = here_val; - } - else { - if (here_val === 16) { - //=== NEEDBITS(here.bits + 2); - n = here_bits + 2; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - if (state.have === 0) { - strm.msg = 'invalid bit length repeat'; - state.mode = BAD$1; - break; - } - len = state.lens[state.have - 1]; - copy = 3 + (hold & 0x03);//BITS(2); - //--- DROPBITS(2) ---// - hold >>>= 2; - bits -= 2; - //---// - } - else if (here_val === 17) { - //=== NEEDBITS(here.bits + 3); - n = here_bits + 3; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - len = 0; - copy = 3 + (hold & 0x07);//BITS(3); - //--- DROPBITS(3) ---// - hold >>>= 3; - bits -= 3; - //---// - } - else { - //=== NEEDBITS(here.bits + 7); - n = here_bits + 7; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - len = 0; - copy = 11 + (hold & 0x7f);//BITS(7); - //--- DROPBITS(7) ---// - hold >>>= 7; - bits -= 7; - //---// - } - if (state.have + copy > state.nlen + state.ndist) { - strm.msg = 'invalid bit length repeat'; - state.mode = BAD$1; - break; - } - while (copy--) { - state.lens[state.have++] = len; - } - } - } - - /* handle error breaks in while */ - if (state.mode === BAD$1) { break; } - - /* check for end-of-block code (better have one) */ - if (state.lens[256] === 0) { - strm.msg = 'invalid code -- missing end-of-block'; - state.mode = BAD$1; - break; - } - - /* build code tables -- note: do not change the lenbits or distbits - values here (9 and 6) without reading the comments in inftrees.h - concerning the ENOUGH constants, which depend on those values */ - state.lenbits = 9; - - opts = { bits: state.lenbits }; - ret = inflate_table(LENS$1, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts); - // We have separate tables & no pointers. 2 commented lines below not needed. - // state.next_index = opts.table_index; - state.lenbits = opts.bits; - // state.lencode = state.next; - - if (ret) { - strm.msg = 'invalid literal/lengths set'; - state.mode = BAD$1; - break; - } - - state.distbits = 6; - //state.distcode.copy(state.codes); - // Switch to use dynamic table - state.distcode = state.distdyn; - opts = { bits: state.distbits }; - ret = inflate_table(DISTS$1, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts); - // We have separate tables & no pointers. 2 commented lines below not needed. - // state.next_index = opts.table_index; - state.distbits = opts.bits; - // state.distcode = state.next; - - if (ret) { - strm.msg = 'invalid distances set'; - state.mode = BAD$1; - break; - } - //Tracev((stderr, 'inflate: codes ok\n')); - state.mode = LEN_; - if (flush === Z_TREES) { break inf_leave; } - /* falls through */ - case LEN_: - state.mode = LEN; - /* falls through */ - case LEN: - if (have >= 6 && left >= 258) { - //--- RESTORE() --- - strm.next_out = put; - strm.avail_out = left; - strm.next_in = next; - strm.avail_in = have; - state.hold = hold; - state.bits = bits; - //--- - inflate_fast(strm, _out); - //--- LOAD() --- - put = strm.next_out; - output = strm.output; - left = strm.avail_out; - next = strm.next_in; - input = strm.input; - have = strm.avail_in; - hold = state.hold; - bits = state.bits; - //--- - - if (state.mode === TYPE$1) { - state.back = -1; - } - break; - } - state.back = 0; - for (;;) { - here = state.lencode[hold & ((1 << state.lenbits) - 1)]; /*BITS(state.lenbits)*/ - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if (here_bits <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - if (here_op && (here_op & 0xf0) === 0) { - last_bits = here_bits; - last_op = here_op; - last_val = here_val; - for (;;) { - here = state.lencode[last_val + - ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((last_bits + here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - //--- DROPBITS(last.bits) ---// - hold >>>= last_bits; - bits -= last_bits; - //---// - state.back += last_bits; - } - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - state.back += here_bits; - state.length = here_val; - if (here_op === 0) { - //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - // "inflate: literal '%c'\n" : - // "inflate: literal 0x%02x\n", here.val)); - state.mode = LIT; - break; - } - if (here_op & 32) { - //Tracevv((stderr, "inflate: end of block\n")); - state.back = -1; - state.mode = TYPE$1; - break; - } - if (here_op & 64) { - strm.msg = 'invalid literal/length code'; - state.mode = BAD$1; - break; - } - state.extra = here_op & 15; - state.mode = LENEXT; - /* falls through */ - case LENEXT: - if (state.extra) { - //=== NEEDBITS(state.extra); - n = state.extra; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.length += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; - //--- DROPBITS(state.extra) ---// - hold >>>= state.extra; - bits -= state.extra; - //---// - state.back += state.extra; - } - //Tracevv((stderr, "inflate: length %u\n", state.length)); - state.was = state.length; - state.mode = DIST; - /* falls through */ - case DIST: - for (;;) { - here = state.distcode[hold & ((1 << state.distbits) - 1)];/*BITS(state.distbits)*/ - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - if ((here_op & 0xf0) === 0) { - last_bits = here_bits; - last_op = here_op; - last_val = here_val; - for (;;) { - here = state.distcode[last_val + - ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((last_bits + here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - //--- DROPBITS(last.bits) ---// - hold >>>= last_bits; - bits -= last_bits; - //---// - state.back += last_bits; - } - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - state.back += here_bits; - if (here_op & 64) { - strm.msg = 'invalid distance code'; - state.mode = BAD$1; - break; - } - state.offset = here_val; - state.extra = (here_op) & 15; - state.mode = DISTEXT; - /* falls through */ - case DISTEXT: - if (state.extra) { - //=== NEEDBITS(state.extra); - n = state.extra; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.offset += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; - //--- DROPBITS(state.extra) ---// - hold >>>= state.extra; - bits -= state.extra; - //---// - state.back += state.extra; - } -//#ifdef INFLATE_STRICT - if (state.offset > state.dmax) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD$1; - break; - } -//#endif - //Tracevv((stderr, "inflate: distance %u\n", state.offset)); - state.mode = MATCH; - /* falls through */ - case MATCH: - if (left === 0) { break inf_leave; } - copy = _out - left; - if (state.offset > copy) { /* copy from window */ - copy = state.offset - copy; - if (copy > state.whave) { - if (state.sane) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD$1; - break; - } -// (!) This block is disabled in zlib defaults, -// don't enable it for binary compatibility -//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR -// Trace((stderr, "inflate.c too far\n")); -// copy -= state.whave; -// if (copy > state.length) { copy = state.length; } -// if (copy > left) { copy = left; } -// left -= copy; -// state.length -= copy; -// do { -// output[put++] = 0; -// } while (--copy); -// if (state.length === 0) { state.mode = LEN; } -// break; -//#endif - } - if (copy > state.wnext) { - copy -= state.wnext; - from = state.wsize - copy; - } - else { - from = state.wnext - copy; - } - if (copy > state.length) { copy = state.length; } - from_source = state.window; - } - else { /* copy from output */ - from_source = output; - from = put - state.offset; - copy = state.length; - } - if (copy > left) { copy = left; } - left -= copy; - state.length -= copy; - do { - output[put++] = from_source[from++]; - } while (--copy); - if (state.length === 0) { state.mode = LEN; } - break; - case LIT: - if (left === 0) { break inf_leave; } - output[put++] = state.length; - left--; - state.mode = LEN; - break; - case CHECK: - if (state.wrap) { - //=== NEEDBITS(32); - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - // Use '|' instead of '+' to make sure that result is signed - hold |= input[next++] << bits; - bits += 8; - } - //===// - _out -= left; - strm.total_out += _out; - state.total += _out; - if (_out) { - strm.adler = state.check = - /*UPDATE(state.check, put - _out, _out);*/ - (state.flags ? crc32(state.check, output, _out, put - _out) : adler32(state.check, output, _out, put - _out)); - - } - _out = left; - // NB: crc32 stored as signed 32-bit int, zswap32 returns signed too - if ((state.flags ? hold : zswap32(hold)) !== state.check) { - strm.msg = 'incorrect data check'; - state.mode = BAD$1; - break; - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - //Tracev((stderr, "inflate: check matches trailer\n")); - } - state.mode = LENGTH; - /* falls through */ - case LENGTH: - if (state.wrap && state.flags) { - //=== NEEDBITS(32); - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (hold !== (state.total & 0xffffffff)) { - strm.msg = 'incorrect length check'; - state.mode = BAD$1; - break; - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - //Tracev((stderr, "inflate: length matches trailer\n")); - } - state.mode = DONE; - /* falls through */ - case DONE: - ret = Z_STREAM_END; - break inf_leave; - case BAD$1: - ret = Z_DATA_ERROR; - break inf_leave; - // case MEM: - // return Z_MEM_ERROR; - case SYNC: - /* falls through */ - default: - return Z_STREAM_ERROR; - } - } - - // inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave" - - /* - Return from inflate(), updating the total counts and the check value. - If there was no progress during the inflate() call, return a buffer - error. Call updatewindow() to create and/or update the window state. - Note: a memory error from inflate() is non-recoverable. - */ - - //--- RESTORE() --- - strm.next_out = put; - strm.avail_out = left; - strm.next_in = next; - strm.avail_in = have; - state.hold = hold; - state.bits = bits; - //--- - - if (state.wsize || (_out !== strm.avail_out && state.mode < BAD$1 && - (state.mode < CHECK || flush !== Z_FINISH))) { - if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) ; - } - _in -= strm.avail_in; - _out -= strm.avail_out; - strm.total_in += _in; - strm.total_out += _out; - state.total += _out; - if (state.wrap && _out) { - strm.adler = state.check = /*UPDATE(state.check, strm.next_out - _out, _out);*/ - (state.flags ? crc32(state.check, output, _out, strm.next_out - _out) : adler32(state.check, output, _out, strm.next_out - _out)); - } - strm.data_type = state.bits + (state.last ? 64 : 0) + - (state.mode === TYPE$1 ? 128 : 0) + - (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0); - if (((_in === 0 && _out === 0) || flush === Z_FINISH) && ret === Z_OK) { - ret = Z_BUF_ERROR; - } - return ret; -} - -function inflateEnd(strm) { - - if (!strm || !strm.state /*|| strm->zfree == (free_func)0*/) { - return Z_STREAM_ERROR; - } - - const state = strm.state; - if (state.window) { - state.window = null; - } - strm.state = null; - return Z_OK; -} - -function inflateGetHeader(strm, head) { - let state; - - /* check state */ - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR; } - - /* save header structure */ - state.head = head; - head.done = false; - return Z_OK; -} - -function inflateSetDictionary(strm, dictionary) { - const dictLength = dictionary.length; - - let state; - let dictid; - - /* check state */ - if (!strm /* == Z_NULL */ || !strm.state /* == Z_NULL */) { return Z_STREAM_ERROR; } - state = strm.state; - - if (state.wrap !== 0 && state.mode !== DICT) { - return Z_STREAM_ERROR; - } - - /* check for correct dictionary identifier */ - if (state.mode === DICT) { - dictid = 1; /* adler32(0, null, 0)*/ - /* dictid = adler32(dictid, dictionary, dictLength); */ - dictid = adler32(dictid, dictionary, dictLength, 0); - if (dictid !== state.check) { - return Z_DATA_ERROR; - } - } - /* copy dictionary to window using updatewindow(), which will amend the - existing dictionary if appropriate */ - updatewindow(strm, dictionary, dictLength, dictLength); - // if (ret) { - // state.mode = MEM; - // return Z_MEM_ERROR; - // } - state.havedict = 1; - // Tracev((stderr, "inflate: dictionary set\n")); - return Z_OK; -} - -/* Not implemented -exports.inflateCopy = inflateCopy; -exports.inflateGetDictionary = inflateGetDictionary; -exports.inflateMark = inflateMark; -exports.inflatePrime = inflatePrime; -exports.inflateSync = inflateSync; -exports.inflateSyncPoint = inflateSyncPoint; -exports.inflateUndermine = inflateUndermine; -*/ - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -class GZheader { - constructor() { - /* true if compressed data believed to be text */ - this.text = 0; - /* modification time */ - this.time = 0; - /* extra flags (not used when writing a gzip file) */ - this.xflags = 0; - /* operating system */ - this.os = 0; - /* pointer to extra field or Z_NULL if none */ - this.extra = null; - /* extra field length (valid if extra != Z_NULL) */ - this.extra_len = 0; // Actually, we don't need it in JS, - // but leave for few code modifications - - // - // Setup limits is not necessary because in js we should not preallocate memory - // for inflate use constant limit in 65536 bytes - // - - /* space at extra (only when reading header) */ - // this.extra_max = 0; - /* pointer to zero-terminated file name or Z_NULL */ - this.name = ''; - /* space at name (only when reading header) */ - // this.name_max = 0; - /* pointer to zero-terminated comment or Z_NULL */ - this.comment = ''; - /* space at comment (only when reading header) */ - // this.comm_max = 0; - /* true if there was or will be a header crc */ - this.hcrc = 0; - /* true when done reading gzip header (not used when writing a gzip file) */ - this.done = false; - } -} - -/** - * class Inflate - * - * Generic JS-style wrapper for zlib calls. If you don't need - * streaming behaviour - use more simple functions: [[inflate]] - * and [[inflateRaw]]. - **/ - -/* internal - * inflate.chunks -> Array - * - * Chunks of output data, if [[Inflate#onData]] not overridden. - **/ - -/** - * Inflate.result -> Uint8Array|Array|String - * - * Uncompressed result, generated by default [[Inflate#onData]] - * and [[Inflate#onEnd]] handlers. Filled after you push last chunk - * (call [[Inflate#push]] with `Z_FINISH` / `true` param) or if you - * push a chunk with explicit flush (call [[Inflate#push]] with - * `Z_SYNC_FLUSH` param). - **/ - -/** - * Inflate.err -> Number - * - * Error code after inflate finished. 0 (Z_OK) on success. - * Should be checked if broken data possible. - **/ - -/** - * Inflate.msg -> String - * - * Error message, if [[Inflate.err]] != 0 - **/ - - -/** - * new Inflate(options) - * - options (Object): zlib inflate options. - * - * Creates new inflator instance with specified params. Throws exception - * on bad params. Supported options: - * - * - `windowBits` - * - `dictionary` - * - * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) - * for more information on these. - * - * Additional options, for internal needs: - * - * - `chunkSize` - size of generated data chunks (16K by default) - * - `raw` (Boolean) - do raw inflate - * - `to` (String) - if equal to 'string', then result will be converted - * from utf8 to utf16 (javascript) string. When string output requested, - * chunk length can differ from `chunkSize`, depending on content. - * - * By default, when no options set, autodetect deflate/gzip data format via - * wrapper header. - * - * ##### Example: - * - * ```javascript - * var pako = require('pako') - * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9]) - * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]); - * - * var inflate = new pako.Inflate({ level: 3}); - * - * inflate.push(chunk1, false); - * inflate.push(chunk2, true); // true -> last chunk - * - * if (inflate.err) { throw new Error(inflate.err); } - * - * console.log(inflate.result); - * ``` - **/ -class Inflate { - constructor(options) { - this.options = { - chunkSize: 16384, - windowBits: 0, - ...(options || {}) - }; - - const opt = this.options; - - // Force window size for `raw` data, if not set directly, - // because we have no header for autodetect. - if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) { - opt.windowBits = -opt.windowBits; - if (opt.windowBits === 0) { opt.windowBits = -15; } - } - - // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate - if ((opt.windowBits >= 0) && (opt.windowBits < 16) && - !(options && options.windowBits)) { - opt.windowBits += 32; - } - - // Gzip header has no info about windows size, we can do autodetect only - // for deflate. So, if window size not set, force it to max when gzip possible - if ((opt.windowBits > 15) && (opt.windowBits < 48)) { - // bit 3 (16) -> gzipped data - // bit 4 (32) -> autodetect gzip/deflate - if ((opt.windowBits & 15) === 0) { - opt.windowBits |= 15; - } - } - - this.err = 0; // error code, if happens (0 = Z_OK) - this.msg = ''; // error message - this.ended = false; // used to avoid multiple onEnd() calls - this.chunks = []; // chunks of compressed data - - this.strm = new ZStream(); - this.strm.avail_out = 0; - - let status = inflateInit2( - this.strm, - opt.windowBits - ); - - if (status !== Z_OK) { - throw new Error(msg[status]); - } - - this.header = new GZheader(); - - inflateGetHeader(this.strm, this.header); - - // Setup dictionary - if (opt.dictionary) { - // Convert data if needed - if (typeof opt.dictionary === 'string') { - opt.dictionary = string2buf(opt.dictionary); - } else if (opt.dictionary instanceof ArrayBuffer) { - opt.dictionary = new Uint8Array(opt.dictionary); - } - if (opt.raw) { //In raw mode we need to set the dictionary early - status = inflateSetDictionary(this.strm, opt.dictionary); - if (status !== Z_OK) { - throw new Error(msg[status]); - } - } - } - } - /** - * Inflate#push(data[, mode]) -> Boolean - * - data (Uint8Array|Array|ArrayBuffer|String): input data - * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. - * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH. - * - * Sends input data to inflate pipe, generating [[Inflate#onData]] calls with - * new output chunks. Returns `true` on success. The last data block must have - * mode Z_FINISH (or `true`). That will flush internal pending buffers and call - * [[Inflate#onEnd]]. For interim explicit flushes (without ending the stream) you - * can use mode Z_SYNC_FLUSH, keeping the decompression context. - * - * On fail call [[Inflate#onEnd]] with error code and return false. - * - * We strongly recommend to use `Uint8Array` on input for best speed (output - * format is detected automatically). Also, don't skip last param and always - * use the same type in your code (boolean or number). That will improve JS speed. - * - * For regular `Array`-s make sure all elements are [0..255]. - * - * ##### Example - * - * ```javascript - * push(chunk, false); // push one of data chunks - * ... - * push(chunk, true); // push last chunk - * ``` - **/ - push(data, mode) { - const { strm, options: { chunkSize, dictionary } } = this; - let status, _mode; - - // Flag to properly process Z_BUF_ERROR on testing inflate call - // when we check that all output data was flushed. - let allowBufError = false; - - if (this.ended) { return false; } - _mode = (mode === ~~mode) ? mode : ((mode === true) ? Z_FINISH : Z_NO_FLUSH); - - // Convert data if needed - if (typeof data === 'string') { - // Only binary strings can be decompressed on practice - strm.input = binstring2buf(data); - } else if (data instanceof ArrayBuffer) { - strm.input = new Uint8Array(data); - } else { - strm.input = data; - } - - strm.next_in = 0; - strm.avail_in = strm.input.length; - - do { - if (strm.avail_out === 0) { - strm.output = new Buf8(chunkSize); - strm.next_out = 0; - strm.avail_out = chunkSize; - } - - status = inflate(strm, Z_NO_FLUSH); /* no bad return value */ - - if (status === Z_NEED_DICT && dictionary) { - status = inflateSetDictionary(this.strm, dictionary); - } - - if (status === Z_BUF_ERROR && allowBufError === true) { - status = Z_OK; - allowBufError = false; - } - - if (status !== Z_STREAM_END && status !== Z_OK) { - this.onEnd(status); - this.ended = true; - return false; - } - - if (strm.next_out) { - if (strm.avail_out === 0 || status === Z_STREAM_END || (strm.avail_in === 0 && (_mode === Z_FINISH || _mode === Z_SYNC_FLUSH))) { - this.onData(shrinkBuf(strm.output, strm.next_out)); - } - } - - // When no more input data, we should check that internal inflate buffers - // are flushed. The only way to do it when avail_out = 0 - run one more - // inflate pass. But if output data not exists, inflate return Z_BUF_ERROR. - // Here we set flag to process this error properly. - // - // NOTE. Deflate does not return error in this case and does not needs such - // logic. - if (strm.avail_in === 0 && strm.avail_out === 0) { - allowBufError = true; - } - - } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== Z_STREAM_END); - - if (status === Z_STREAM_END) { - _mode = Z_FINISH; - } - - // Finalize on the last chunk. - if (_mode === Z_FINISH) { - status = inflateEnd(this.strm); - this.onEnd(status); - this.ended = true; - return status === Z_OK; - } - - // callback interim results if Z_SYNC_FLUSH. - if (_mode === Z_SYNC_FLUSH) { - this.onEnd(Z_OK); - strm.avail_out = 0; - return true; - } - - return true; - }; - - /** - * Inflate#onData(chunk) -> Void - * - chunk (Uint8Array|Array|String): output data. Type of array depends - * on js engine support. When string output requested, each chunk - * will be string. - * - * By default, stores data blocks in `chunks[]` property and glue - * those in `onEnd`. Override this handler, if you need another behaviour. - **/ - onData(chunk) { - this.chunks.push(chunk); - }; - - - - /** - * Inflate#onEnd(status) -> Void - * - status (Number): inflate status. 0 (Z_OK) on success, - * other if not. - * - * Called either after you tell inflate that the input stream is - * complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH) - * or if an error happened. By default - join collected chunks, - * free memory and fill `results` / `err` properties. - **/ - onEnd(status) { - // On success - join - if (status === Z_OK) { - this.result = flattenChunks(this.chunks); - } - this.chunks = []; - this.err = status; - this.msg = this.strm.msg; - }; -} - -/* -node-bzip - a pure-javascript Node.JS module for decoding bzip2 data - -Copyright (C) 2012 Eli Skeggs - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, see -http://www.gnu.org/licenses/lgpl-2.1.html - -Adapted from bzip2.js, copyright 2011 antimatter15 (antimatter15@gmail.com). - -Based on micro-bunzip by Rob Landley (rob@landley.net). - -Based on bzip2 decompression code by Julian R Seward (jseward@acm.org), -which also acknowledges contributions by Mike Burrows, David Wheeler, -Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten, -Robert Sedgewick, and Jon L. Bentley. -*/ - -var BITMASK = [0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF]; - -// offset in bytes -var BitReader = function(stream) { - this.stream = stream; - this.bitOffset = 0; - this.curByte = 0; - this.hasByte = false; -}; - -BitReader.prototype._ensureByte = function() { - if (!this.hasByte) { - this.curByte = this.stream.readByte(); - this.hasByte = true; - } -}; - -// reads bits from the buffer -BitReader.prototype.read = function(bits) { - var result = 0; - while (bits > 0) { - this._ensureByte(); - var remaining = 8 - this.bitOffset; - // if we're in a byte - if (bits >= remaining) { - result <<= remaining; - result |= BITMASK[remaining] & this.curByte; - this.hasByte = false; - this.bitOffset = 0; - bits -= remaining; - } else { - result <<= bits; - var shift = remaining - bits; - result |= (this.curByte & (BITMASK[bits] << shift)) >> shift; - this.bitOffset += bits; - bits = 0; - } - } - return result; -}; - -// seek to an arbitrary point in the buffer (expressed in bits) -BitReader.prototype.seek = function(pos) { - var n_bit = pos % 8; - var n_byte = (pos - n_bit) / 8; - this.bitOffset = n_bit; - this.stream.seek(n_byte); - this.hasByte = false; -}; - -// reads 6 bytes worth of data using the read method -BitReader.prototype.pi = function() { - var buf = new Uint8Array(6), i; - for (i = 0; i < buf.length; i++) { - buf[i] = this.read(8); - } - return bufToHex(buf); -}; - -function bufToHex(buf) { - return Array.prototype.map.call(buf, x => ('00' + x.toString(16)).slice(-2)).join(''); -} - -var bitreader = BitReader; - -/* very simple input/output stream interface */ -var Stream = function() { -}; - -// input streams ////////////// -/** Returns the next byte, or -1 for EOF. */ -Stream.prototype.readByte = function() { - throw new Error("abstract method readByte() not implemented"); -}; -/** Attempts to fill the buffer; returns number of bytes read, or - * -1 for EOF. */ -Stream.prototype.read = function(buffer, bufOffset, length) { - var bytesRead = 0; - while (bytesRead < length) { - var c = this.readByte(); - if (c < 0) { // EOF - return (bytesRead===0) ? -1 : bytesRead; - } - buffer[bufOffset++] = c; - bytesRead++; - } - return bytesRead; -}; -Stream.prototype.seek = function(new_pos) { - throw new Error("abstract method seek() not implemented"); -}; - -// output streams /////////// -Stream.prototype.writeByte = function(_byte) { - throw new Error("abstract method readByte() not implemented"); -}; -Stream.prototype.write = function(buffer, bufOffset, length) { - var i; - for (i=0; i>> 0; // return an unsigned value - }; - - /** - * Update the CRC with a single byte - * @param value The value to update the CRC with - */ - this.updateCRC = function(value) { - crc = (crc << 8) ^ crc32Lookup[((crc >>> 24) ^ value) & 0xff]; - }; - - /** - * Update the CRC with a sequence of identical bytes - * @param value The value to update the CRC with - * @param count The number of bytes - */ - this.updateCRCRun = function(value, count) { - while (count-- > 0) { - crc = (crc << 8) ^ crc32Lookup[((crc >>> 24) ^ value) & 0xff]; - } - }; - }; - return CRC32; -})(); - -/* -seek-bzip - a pure-javascript module for seeking within bzip2 data - -Copyright (C) 2013 C. Scott Ananian -Copyright (C) 2012 Eli Skeggs -Copyright (C) 2011 Kevin Kwok - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, see -http://www.gnu.org/licenses/lgpl-2.1.html - -Adapted from node-bzip, copyright 2012 Eli Skeggs. -Adapted from bzip2.js, copyright 2011 Kevin Kwok (antimatter15@gmail.com). - -Based on micro-bunzip by Rob Landley (rob@landley.net). - -Based on bzip2 decompression code by Julian R Seward (jseward@acm.org), -which also acknowledges contributions by Mike Burrows, David Wheeler, -Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten, -Robert Sedgewick, and Jon L. Bentley. -*/ - - - - - -var MAX_HUFCODE_BITS = 20; -var MAX_SYMBOLS = 258; -var SYMBOL_RUNA = 0; -var SYMBOL_RUNB = 1; -var MIN_GROUPS = 2; -var MAX_GROUPS = 6; -var GROUP_SIZE = 50; - -var WHOLEPI = "314159265359"; -var SQRTPI = "177245385090"; - -var mtf = function(array, index) { - var src = array[index], i; - for (i = index; i > 0; i--) { - array[i] = array[i-1]; - } - array[0] = src; - return src; -}; - -var Err = { - OK: 0, - LAST_BLOCK: -1, - NOT_BZIP_DATA: -2, - UNEXPECTED_INPUT_EOF: -3, - UNEXPECTED_OUTPUT_EOF: -4, - DATA_ERROR: -5, - OUT_OF_MEMORY: -6, - OBSOLETE_INPUT: -7, - END_OF_BLOCK: -8 -}; -var ErrorMessages = {}; -ErrorMessages[Err.LAST_BLOCK] = "Bad file checksum"; -ErrorMessages[Err.NOT_BZIP_DATA] = "Not bzip data"; -ErrorMessages[Err.UNEXPECTED_INPUT_EOF] = "Unexpected input EOF"; -ErrorMessages[Err.UNEXPECTED_OUTPUT_EOF] = "Unexpected output EOF"; -ErrorMessages[Err.DATA_ERROR] = "Data error"; -ErrorMessages[Err.OUT_OF_MEMORY] = "Out of memory"; -ErrorMessages[Err.OBSOLETE_INPUT] = "Obsolete (pre 0.9.5) bzip format not supported."; - -var _throw = function(status, optDetail) { - var msg = ErrorMessages[status] || 'unknown error'; - if (optDetail) { msg += ': '+optDetail; } - var e = new TypeError(msg); - e.errorCode = status; - throw e; -}; - -var Bunzip = function(inputStream, outputStream) { - this.writePos = this.writeCurrent = this.writeCount = 0; - - this._start_bunzip(inputStream, outputStream); -}; -Bunzip.prototype._init_block = function() { - var moreBlocks = this._get_next_block(); - if ( !moreBlocks ) { - this.writeCount = -1; - return false; /* no more blocks */ - } - this.blockCRC = new crc32$1(); - return true; -}; -/* XXX micro-bunzip uses (inputStream, inputBuffer, len) as arguments */ -Bunzip.prototype._start_bunzip = function(inputStream, outputStream) { - /* Ensure that file starts with "BZh['1'-'9']." */ - var buf = new Uint8Array(4); - if (inputStream.read(buf, 0, 4) !== 4 || - String.fromCharCode(buf[0], buf[1], buf[2]) !== 'BZh') - _throw(Err.NOT_BZIP_DATA, 'bad magic'); - - var level = buf[3] - 0x30; - if (level < 1 || level > 9) - _throw(Err.NOT_BZIP_DATA, 'level out of range'); - - this.reader = new bitreader(inputStream); - - /* Fourth byte (ascii '1'-'9'), indicates block size in units of 100k of - uncompressed data. Allocate intermediate buffer for block. */ - this.dbufSize = 100000 * level; - this.nextoutput = 0; - this.outputStream = outputStream; - this.streamCRC = 0; -}; -Bunzip.prototype._get_next_block = function() { - var i, j, k; - var reader = this.reader; - // this is get_next_block() function from micro-bunzip: - /* Read in header signature and CRC, then validate signature. - (last block signature means CRC is for whole file, return now) */ - var h = reader.pi(); - if (h === SQRTPI) { // last block - return false; /* no more blocks */ - } - if (h !== WHOLEPI) - _throw(Err.NOT_BZIP_DATA); - this.targetBlockCRC = reader.read(32) >>> 0; // (convert to unsigned) - this.streamCRC = (this.targetBlockCRC ^ - ((this.streamCRC << 1) | (this.streamCRC>>>31))) >>> 0; - /* We can add support for blockRandomised if anybody complains. There was - some code for this in busybox 1.0.0-pre3, but nobody ever noticed that - it didn't actually work. */ - if (reader.read(1)) - _throw(Err.OBSOLETE_INPUT); - var origPointer = reader.read(24); - if (origPointer > this.dbufSize) - _throw(Err.DATA_ERROR, 'initial position out of bounds'); - /* mapping table: if some byte values are never used (encoding things - like ascii text), the compression code removes the gaps to have fewer - symbols to deal with, and writes a sparse bitfield indicating which - values were present. We make a translation table to convert the symbols - back to the corresponding bytes. */ - var t = reader.read(16); - var symToByte = new Uint8Array(256), symTotal = 0; - for (i = 0; i < 16; i++) { - if (t & (1 << (0xF - i))) { - var o = i * 16; - k = reader.read(16); - for (j = 0; j < 16; j++) - if (k & (1 << (0xF - j))) - symToByte[symTotal++] = o + j; - } - } - - /* How many different huffman coding groups does this block use? */ - var groupCount = reader.read(3); - if (groupCount < MIN_GROUPS || groupCount > MAX_GROUPS) - _throw(Err.DATA_ERROR); - /* nSelectors: Every GROUP_SIZE many symbols we select a new huffman coding - group. Read in the group selector list, which is stored as MTF encoded - bit runs. (MTF=Move To Front, as each value is used it's moved to the - start of the list.) */ - var nSelectors = reader.read(15); - if (nSelectors === 0) - _throw(Err.DATA_ERROR); - - var mtfSymbol = new Uint8Array(256); - for (i = 0; i < groupCount; i++) - mtfSymbol[i] = i; - - var selectors = new Uint8Array(nSelectors); // was 32768... - - for (i = 0; i < nSelectors; i++) { - /* Get next value */ - for (j = 0; reader.read(1); j++) - if (j >= groupCount) _throw(Err.DATA_ERROR); - /* Decode MTF to get the next selector */ - selectors[i] = mtf(mtfSymbol, j); - } - - /* Read the huffman coding tables for each group, which code for symTotal - literal symbols, plus two run symbols (RUNA, RUNB) */ - var symCount = symTotal + 2; - var groups = [], hufGroup; - for (j = 0; j < groupCount; j++) { - var length = new Uint8Array(symCount), temp = new Uint16Array(MAX_HUFCODE_BITS + 1); - /* Read huffman code lengths for each symbol. They're stored in - a way similar to mtf; record a starting value for the first symbol, - and an offset from the previous value for everys symbol after that. */ - t = reader.read(5); // lengths - for (i = 0; i < symCount; i++) { - for (;;) { - if (t < 1 || t > MAX_HUFCODE_BITS) _throw(Err.DATA_ERROR); - /* If first bit is 0, stop. Else second bit indicates whether - to increment or decrement the value. */ - if(!reader.read(1)) - break; - if(!reader.read(1)) - t++; - else - t--; - } - length[i] = t; - } - - /* Find largest and smallest lengths in this group */ - var minLen, maxLen; - minLen = maxLen = length[0]; - for (i = 1; i < symCount; i++) { - if (length[i] > maxLen) - maxLen = length[i]; - else if (length[i] < minLen) - minLen = length[i]; - } - - /* Calculate permute[], base[], and limit[] tables from length[]. - * - * permute[] is the lookup table for converting huffman coded symbols - * into decoded symbols. base[] is the amount to subtract from the - * value of a huffman symbol of a given length when using permute[]. - * - * limit[] indicates the largest numerical value a symbol with a given - * number of bits can have. This is how the huffman codes can vary in - * length: each code with a value>limit[length] needs another bit. - */ - hufGroup = {}; - groups.push(hufGroup); - hufGroup.permute = new Uint16Array(MAX_SYMBOLS); - hufGroup.limit = new Uint32Array(MAX_HUFCODE_BITS + 2); - hufGroup.base = new Uint32Array(MAX_HUFCODE_BITS + 1); - hufGroup.minLen = minLen; - hufGroup.maxLen = maxLen; - /* Calculate permute[]. Concurently, initialize temp[] and limit[]. */ - var pp = 0; - for (i = minLen; i <= maxLen; i++) { - temp[i] = hufGroup.limit[i] = 0; - for (t = 0; t < symCount; t++) - if (length[t] === i) - hufGroup.permute[pp++] = t; - } - /* Count symbols coded for at each bit length */ - for (i = 0; i < symCount; i++) - temp[length[i]]++; - /* Calculate limit[] (the largest symbol-coding value at each bit - * length, which is (previous limit<<1)+symbols at this level), and - * base[] (number of symbols to ignore at each bit length, which is - * limit minus the cumulative count of symbols coded for already). */ - pp = t = 0; - for (i = minLen; i < maxLen; i++) { - pp += temp[i]; - /* We read the largest possible symbol size and then unget bits - after determining how many we need, and those extra bits could - be set to anything. (They're noise from future symbols.) At - each level we're really only interested in the first few bits, - so here we set all the trailing to-be-ignored bits to 1 so they - don't affect the value>limit[length] comparison. */ - hufGroup.limit[i] = pp - 1; - pp <<= 1; - t += temp[i]; - hufGroup.base[i + 1] = pp - t; - } - hufGroup.limit[maxLen + 1] = Number.MAX_VALUE; /* Sentinal value for reading next sym. */ - hufGroup.limit[maxLen] = pp + temp[maxLen] - 1; - hufGroup.base[minLen] = 0; - } - /* We've finished reading and digesting the block header. Now read this - block's huffman coded symbols from the file and undo the huffman coding - and run length encoding, saving the result into dbuf[dbufCount++]=uc */ - - /* Initialize symbol occurrence counters and symbol Move To Front table */ - var byteCount = new Uint32Array(256); - for (i = 0; i < 256; i++) - mtfSymbol[i] = i; - /* Loop through compressed symbols. */ - var runPos = 0, dbufCount = 0, selector = 0, uc; - var dbuf = this.dbuf = new Uint32Array(this.dbufSize); - symCount = 0; - for (;;) { - /* Determine which huffman coding group to use. */ - if (!(symCount--)) { - symCount = GROUP_SIZE - 1; - if (selector >= nSelectors) { _throw(Err.DATA_ERROR); } - hufGroup = groups[selectors[selector++]]; - } - /* Read next huffman-coded symbol. */ - i = hufGroup.minLen; - j = reader.read(i); - for (;;i++) { - if (i > hufGroup.maxLen) { _throw(Err.DATA_ERROR); } - if (j <= hufGroup.limit[i]) - break; - j = (j << 1) | reader.read(1); - } - /* Huffman decode value to get nextSym (with bounds checking) */ - j -= hufGroup.base[i]; - if (j < 0 || j >= MAX_SYMBOLS) { _throw(Err.DATA_ERROR); } - var nextSym = hufGroup.permute[j]; - /* We have now decoded the symbol, which indicates either a new literal - byte, or a repeated run of the most recent literal byte. First, - check if nextSym indicates a repeated run, and if so loop collecting - how many times to repeat the last literal. */ - if (nextSym === SYMBOL_RUNA || nextSym === SYMBOL_RUNB) { - /* If this is the start of a new run, zero out counter */ - if (!runPos){ - runPos = 1; - t = 0; - } - /* Neat trick that saves 1 symbol: instead of or-ing 0 or 1 at - each bit position, add 1 or 2 instead. For example, - 1011 is 1<<0 + 1<<1 + 2<<2. 1010 is 2<<0 + 2<<1 + 1<<2. - You can make any bit pattern that way using 1 less symbol than - the basic or 0/1 method (except all bits 0, which would use no - symbols, but a run of length 0 doesn't mean anything in this - context). Thus space is saved. */ - if (nextSym === SYMBOL_RUNA) - t += runPos; - else - t += 2 * runPos; - runPos <<= 1; - continue; - } - /* When we hit the first non-run symbol after a run, we now know - how many times to repeat the last literal, so append that many - copies to our buffer of decoded symbols (dbuf) now. (The last - literal used is the one at the head of the mtfSymbol array.) */ - if (runPos){ - runPos = 0; - if (dbufCount + t > this.dbufSize) { _throw(Err.DATA_ERROR); } - uc = symToByte[mtfSymbol[0]]; - byteCount[uc] += t; - while (t--) - dbuf[dbufCount++] = uc; - } - /* Is this the terminating symbol? */ - if (nextSym > symTotal) - break; - /* At this point, nextSym indicates a new literal character. Subtract - one to get the position in the MTF array at which this literal is - currently to be found. (Note that the result can't be -1 or 0, - because 0 and 1 are RUNA and RUNB. But another instance of the - first symbol in the mtf array, position 0, would have been handled - as part of a run above. Therefore 1 unused mtf position minus - 2 non-literal nextSym values equals -1.) */ - if (dbufCount >= this.dbufSize) { _throw(Err.DATA_ERROR); } - i = nextSym - 1; - uc = mtf(mtfSymbol, i); - uc = symToByte[uc]; - /* We have our literal byte. Save it into dbuf. */ - byteCount[uc]++; - dbuf[dbufCount++] = uc; - } - /* At this point, we've read all the huffman-coded symbols (and repeated - runs) for this block from the input stream, and decoded them into the - intermediate buffer. There are dbufCount many decoded bytes in dbuf[]. - Now undo the Burrows-Wheeler transform on dbuf. - See http://dogma.net/markn/articles/bwt/bwt.htm - */ - if (origPointer < 0 || origPointer >= dbufCount) { _throw(Err.DATA_ERROR); } - /* Turn byteCount into cumulative occurrence counts of 0 to n-1. */ - j = 0; - for (i = 0; i < 256; i++) { - k = j + byteCount[i]; - byteCount[i] = j; - j = k; - } - /* Figure out what order dbuf would be in if we sorted it. */ - for (i = 0; i < dbufCount; i++) { - uc = dbuf[i] & 0xff; - dbuf[byteCount[uc]] |= (i << 8); - byteCount[uc]++; - } - /* Decode first byte by hand to initialize "previous" byte. Note that it - doesn't get output, and if the first three characters are identical - it doesn't qualify as a run (hence writeRunCountdown=5). */ - var pos = 0, current = 0, run = 0; - if (dbufCount) { - pos = dbuf[origPointer]; - current = (pos & 0xff); - pos >>= 8; - run = -1; - } - this.writePos = pos; - this.writeCurrent = current; - this.writeCount = dbufCount; - this.writeRun = run; - - return true; /* more blocks to come */ -}; -/* Undo burrows-wheeler transform on intermediate buffer to produce output. - If start_bunzip was initialized with out_fd=-1, then up to len bytes of - data are written to outbuf. Return value is number of bytes written or - error (all errors are negative numbers). If out_fd!=-1, outbuf and len - are ignored, data is written to out_fd and return is RETVAL_OK or error. -*/ -Bunzip.prototype._read_bunzip = function(outputBuffer, len) { - var copies, previous, outbyte; - /* james@jamestaylor.org: writeCount goes to -1 when the buffer is fully - decoded, which results in this returning RETVAL_LAST_BLOCK, also - equal to -1... Confusing, I'm returning 0 here to indicate no - bytes written into the buffer */ - if (this.writeCount < 0) { return 0; } - var dbuf = this.dbuf, pos = this.writePos, current = this.writeCurrent; - var dbufCount = this.writeCount; this.outputsize; - var run = this.writeRun; - - while (dbufCount) { - dbufCount--; - previous = current; - pos = dbuf[pos]; - current = pos & 0xff; - pos >>= 8; - if (run++ === 3){ - copies = current; - outbyte = previous; - current = -1; - } else { - copies = 1; - outbyte = current; - } - this.blockCRC.updateCRCRun(outbyte, copies); - while (copies--) { - this.outputStream.writeByte(outbyte); - this.nextoutput++; - } - if (current != previous) - run = 0; - } - this.writeCount = dbufCount; - // check CRC - if (this.blockCRC.getCRC() !== this.targetBlockCRC) { - _throw(Err.DATA_ERROR, "Bad block CRC "+ - "(got "+this.blockCRC.getCRC().toString(16)+ - " expected "+this.targetBlockCRC.toString(16)+")"); - } - return this.nextoutput; -}; - -var coerceInputStream = function(input) { - if ('readByte' in input) { return input; } - var inputStream = new stream(); - inputStream.pos = 0; - inputStream.readByte = function() { return input[this.pos++]; }; - inputStream.seek = function(pos) { this.pos = pos; }; - inputStream.eof = function() { return this.pos >= input.length; }; - return inputStream; -}; -var coerceOutputStream = function(output) { - var outputStream = new stream(); - var resizeOk = true; - if (output) { - if (typeof(output)==='number') { - outputStream.buffer = new Uint8Array(output); - resizeOk = false; - } else if ('writeByte' in output) { - return output; - } else { - outputStream.buffer = output; - resizeOk = false; - } - } else { - outputStream.buffer = new Uint8Array(16384); - } - outputStream.pos = 0; - outputStream.writeByte = function(_byte) { - if (resizeOk && this.pos >= this.buffer.length) { - var newBuffer = new Uint8Array(this.buffer.length*2); - newBuffer.set(this.buffer); - this.buffer = newBuffer; - } - this.buffer[this.pos++] = _byte; - }; - outputStream.getBuffer = function() { - // trim buffer - if (this.pos !== this.buffer.length) { - if (!resizeOk) - throw new TypeError('outputsize does not match decoded input'); - var newBuffer = new Uint8Array(this.pos); - newBuffer.set(this.buffer.subarray(0, this.pos)); - this.buffer = newBuffer; - } - return this.buffer; - }; - outputStream._coerced = true; - return outputStream; -}; - -/* Static helper functions */ -// 'input' can be a stream or a buffer -// 'output' can be a stream or a buffer or a number (buffer size) -const decode$2 = function(input, output, multistream) { - // make a stream from a buffer, if necessary - var inputStream = coerceInputStream(input); - var outputStream = coerceOutputStream(output); - - var bz = new Bunzip(inputStream, outputStream); - while (true) { - if ('eof' in inputStream && inputStream.eof()) break; - if (bz._init_block()) { - bz._read_bunzip(); - } else { - var targetStreamCRC = bz.reader.read(32) >>> 0; // (convert to unsigned) - if (targetStreamCRC !== bz.streamCRC) { - _throw(Err.DATA_ERROR, "Bad stream CRC "+ - "(got "+bz.streamCRC.toString(16)+ - " expected "+targetStreamCRC.toString(16)+")"); - } - if (multistream && - 'eof' in inputStream && - !inputStream.eof()) { - // note that start_bunzip will also resync the bit reader to next byte - bz._start_bunzip(inputStream, outputStream); - } else break; - } - } - if ('getBuffer' in outputStream) - return outputStream.getBuffer(); -}; -const decodeBlock = function(input, pos, output) { - // make a stream from a buffer, if necessary - var inputStream = coerceInputStream(input); - var outputStream = coerceOutputStream(output); - var bz = new Bunzip(inputStream, outputStream); - bz.reader.seek(pos); - /* Fill the decode buffer for the block */ - var moreBlocks = bz._get_next_block(); - if (moreBlocks) { - /* Init the CRC for writing */ - bz.blockCRC = new crc32$1(); - - /* Zero this so the current byte from before the seek is not written */ - bz.writeCopies = 0; - - /* Decompress the block and write to stdout */ - bz._read_bunzip(); - // XXX keep writing? - } - if ('getBuffer' in outputStream) - return outputStream.getBuffer(); -}; -/* Reads bzip2 file from stream or buffer `input`, and invoke - * `callback(position, size)` once for each bzip2 block, - * where position gives the starting position (in *bits*) - * and size gives uncompressed size of the block (in *bytes*). */ -const table = function(input, callback, multistream) { - // make a stream from a buffer, if necessary - var inputStream = new stream(); - inputStream.delegate = coerceInputStream(input); - inputStream.pos = 0; - inputStream.readByte = function() { - this.pos++; - return this.delegate.readByte(); - }; - if (inputStream.delegate.eof) { - inputStream.eof = inputStream.delegate.eof.bind(inputStream.delegate); - } - var outputStream = new stream(); - outputStream.pos = 0; - outputStream.writeByte = function() { this.pos++; }; - - var bz = new Bunzip(inputStream, outputStream); - var blockSize = bz.dbufSize; - while (true) { - if ('eof' in inputStream && inputStream.eof()) break; - - var position = inputStream.pos*8 + bz.reader.bitOffset; - if (bz.reader.hasByte) { position -= 8; } - - if (bz._init_block()) { - var start = outputStream.pos; - bz._read_bunzip(); - callback(position, outputStream.pos - start); - } else { - bz.reader.read(32); // (but we ignore the crc) - if (multistream && - 'eof' in inputStream && - !inputStream.eof()) { - // note that start_bunzip will also resync the bit reader to next byte - bz._start_bunzip(inputStream, outputStream); - console.assert(bz.dbufSize === blockSize, - "shouldn't change block size within multistream file"); - } else break; - } - } -}; - -var lib = { - Bunzip, - Stream: stream, - Err, - decode: decode$2, - decodeBlock, - table -}; -var lib_4 = lib.decode; - -// GPG4Browsers - An OpenPGP implementation in javascript - -/** - * Implementation of the Literal Data Packet (Tag 11) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.9|RFC4880 5.9}: - * A Literal Data packet contains the body of a message; data that is not to be - * further interpreted. - */ -class LiteralDataPacket { - static get tag() { - return enums.packet.literalData; - } - - /** - * @param {Date} date - The creation date of the literal package - */ - constructor(date = new Date()) { - this.format = enums.literal.utf8; // default format for literal data packets - this.date = util.normalizeDate(date); - this.text = null; // textual data representation - this.data = null; // literal data representation - this.filename = ''; - } - - /** - * Set the packet data to a javascript native string, end of line - * will be normalized to \r\n and by default text is converted to UTF8 - * @param {String | ReadableStream} text - Any native javascript string - * @param {enums.literal} [format] - The format of the string of bytes - */ - setText(text, format = enums.literal.utf8) { - this.format = format; - this.text = text; - this.data = null; - } - - /** - * Returns literal data packets as native JavaScript string - * with normalized end of line to \n - * @param {Boolean} [clone] - Whether to return a clone so that getBytes/getText can be called again - * @returns {String | ReadableStream} Literal data as text. - */ - getText(clone = false) { - if (this.text === null || util.isStream(this.text)) { // Assume that this.text has been read - this.text = util.decodeUTF8(util.nativeEOL(this.getBytes(clone))); - } - return this.text; - } - - /** - * Set the packet data to value represented by the provided string of bytes. - * @param {Uint8Array | ReadableStream} bytes - The string of bytes - * @param {enums.literal} format - The format of the string of bytes - */ - setBytes(bytes, format) { - this.format = format; - this.data = bytes; - this.text = null; - } - - - /** - * Get the byte sequence representing the literal packet data - * @param {Boolean} [clone] - Whether to return a clone so that getBytes/getText can be called again - * @returns {Uint8Array | ReadableStream} A sequence of bytes. - */ - getBytes(clone = false) { - if (this.data === null) { - // encode UTF8 and normalize EOL to \r\n - this.data = util.canonicalizeEOL(util.encodeUTF8(this.text)); - } - if (clone) { - return passiveClone(this.data); - } - return this.data; - } - - - /** - * Sets the filename of the literal packet data - * @param {String} filename - Any native javascript string - */ - setFilename(filename) { - this.filename = filename; - } - - - /** - * Get the filename of the literal packet data - * @returns {String} Filename. - */ - getFilename() { - return this.filename; - } - - /** - * Parsing function for a literal data packet (tag 11). - * - * @param {Uint8Array | ReadableStream} input - Payload of a tag 11 packet - * @returns {Promise} Object representation. - * @async - */ - async read(bytes) { - await parse(bytes, async reader => { - // - A one-octet field that describes how the data is formatted. - const format = await reader.readByte(); // enums.literal - - const filename_len = await reader.readByte(); - this.filename = util.decodeUTF8(await reader.readBytes(filename_len)); - - this.date = util.readDate(await reader.readBytes(4)); - - let data = reader.remainder(); - if (isArrayStream(data)) data = await readToEnd(data); - this.setBytes(data, format); - }); - } - - /** - * Creates a Uint8Array representation of the packet, excluding the data - * - * @returns {Uint8Array} Uint8Array representation of the packet. - */ - writeHeader() { - const filename = util.encodeUTF8(this.filename); - const filename_length = new Uint8Array([filename.length]); - - const format = new Uint8Array([this.format]); - const date = util.writeDate(this.date); - - return util.concatUint8Array([format, filename_length, filename, date]); - } - - /** - * Creates a Uint8Array representation of the packet - * - * @returns {Uint8Array | ReadableStream} Uint8Array representation of the packet. - */ - write() { - const header = this.writeHeader(); - const data = this.getBytes(); - - return util.concat([header, data]); - } -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -function readSimpleLength(bytes) { - let len = 0; - let offset; - const type = bytes[0]; - - - if (type < 192) { - [len] = bytes; - offset = 1; - } else if (type < 255) { - len = ((bytes[0] - 192) << 8) + (bytes[1]) + 192; - offset = 2; - } else if (type === 255) { - len = util.readNumber(bytes.subarray(1, 1 + 4)); - offset = 5; - } - - return { - len: len, - offset: offset - }; -} - -/** - * Encodes a given integer of length to the openpgp length specifier to a - * string - * - * @param {Integer} length - The length to encode - * @returns {Uint8Array} String with openpgp length representation. - */ -function writeSimpleLength(length) { - if (length < 192) { - return new Uint8Array([length]); - } else if (length > 191 && length < 8384) { - /* - * let a = (total data packet length) - 192 let bc = two octet - * representation of a let d = b + 192 - */ - return new Uint8Array([((length - 192) >> 8) + 192, (length - 192) & 0xFF]); - } - return util.concatUint8Array([new Uint8Array([255]), util.writeNumber(length, 4)]); -} - -function writePartialLength(power) { - if (power < 0 || power > 30) { - throw new Error('Partial Length power must be between 1 and 30'); - } - return new Uint8Array([224 + power]); -} - -function writeTag(tag_type) { - /* we're only generating v4 packet headers here */ - return new Uint8Array([0xC0 | tag_type]); -} - -/** - * Writes a packet header version 4 with the given tag_type and length to a - * string - * - * @param {Integer} tag_type - Tag type - * @param {Integer} length - Length of the payload - * @returns {String} String of the header. - */ -function writeHeader(tag_type, length) { - /* we're only generating v4 packet headers here */ - return util.concatUint8Array([writeTag(tag_type), writeSimpleLength(length)]); -} - -/** - * Whether the packet type supports partial lengths per RFC4880 - * @param {Integer} tag - Tag type - * @returns {Boolean} String of the header. - */ -function supportsStreaming(tag) { - return [ - enums.packet.literalData, - enums.packet.compressedData, - enums.packet.symmetricallyEncryptedData, - enums.packet.symEncryptedIntegrityProtectedData, - enums.packet.aeadEncryptedData - ].includes(tag); -} - -/** - * Generic static Packet Parser function - * - * @param {Uint8Array | ReadableStream} input - Input stream as string - * @param {Function} callback - Function to call with the parsed packet - * @returns {Boolean} Returns false if the stream was empty and parsing is done, and true otherwise. - */ -async function readPackets(input, callback) { - const reader = getReader(input); - let writer; - let callbackReturned; - try { - const peekedBytes = await reader.peekBytes(2); - // some sanity checks - if (!peekedBytes || peekedBytes.length < 2 || (peekedBytes[0] & 0x80) === 0) { - throw new Error('Error during parsing. This message / key probably does not conform to a valid OpenPGP format.'); - } - const headerByte = await reader.readByte(); - let tag = -1; - let format = -1; - let packetLength; - - format = 0; // 0 = old format; 1 = new format - if ((headerByte & 0x40) !== 0) { - format = 1; - } - - let packetLengthType; - if (format) { - // new format header - tag = headerByte & 0x3F; // bit 5-0 - } else { - // old format header - tag = (headerByte & 0x3F) >> 2; // bit 5-2 - packetLengthType = headerByte & 0x03; // bit 1-0 - } - - const packetSupportsStreaming = supportsStreaming(tag); - let packet = null; - if (packetSupportsStreaming) { - if (util.isStream(input) === 'array') { - const arrayStream = new ArrayStream(); - writer = getWriter(arrayStream); - packet = arrayStream; - } else { - const transform = new TransformStream(); - writer = getWriter(transform.writable); - packet = transform.readable; - } - callbackReturned = callback({ tag, packet }); - } else { - packet = []; - } - - let wasPartialLength; - do { - if (!format) { - // 4.2.1. Old Format Packet Lengths - switch (packetLengthType) { - case 0: - // The packet has a one-octet length. The header is 2 octets - // long. - packetLength = await reader.readByte(); - break; - case 1: - // The packet has a two-octet length. The header is 3 octets - // long. - packetLength = (await reader.readByte() << 8) | await reader.readByte(); - break; - case 2: - // The packet has a four-octet length. The header is 5 - // octets long. - packetLength = (await reader.readByte() << 24) | (await reader.readByte() << 16) | (await reader.readByte() << - 8) | await reader.readByte(); - break; - default: - // 3 - The packet is of indeterminate length. The header is 1 - // octet long, and the implementation must determine how long - // the packet is. If the packet is in a file, this means that - // the packet extends until the end of the file. In general, - // an implementation SHOULD NOT use indeterminate-length - // packets except where the end of the data will be clear - // from the context, and even then it is better to use a - // definite length, or a new format header. The new format - // headers described below have a mechanism for precisely - // encoding data of indeterminate length. - packetLength = Infinity; - break; - } - } else { // 4.2.2. New Format Packet Lengths - // 4.2.2.1. One-Octet Lengths - const lengthByte = await reader.readByte(); - wasPartialLength = false; - if (lengthByte < 192) { - packetLength = lengthByte; - // 4.2.2.2. Two-Octet Lengths - } else if (lengthByte >= 192 && lengthByte < 224) { - packetLength = ((lengthByte - 192) << 8) + (await reader.readByte()) + 192; - // 4.2.2.4. Partial Body Lengths - } else if (lengthByte > 223 && lengthByte < 255) { - packetLength = 1 << (lengthByte & 0x1F); - wasPartialLength = true; - if (!packetSupportsStreaming) { - throw new TypeError('This packet type does not support partial lengths.'); - } - // 4.2.2.3. Five-Octet Lengths - } else { - packetLength = (await reader.readByte() << 24) | (await reader.readByte() << 16) | (await reader.readByte() << - 8) | await reader.readByte(); - } - } - if (packetLength > 0) { - let bytesRead = 0; - while (true) { - if (writer) await writer.ready; - const { done, value } = await reader.read(); - if (done) { - if (packetLength === Infinity) break; - throw new Error('Unexpected end of packet'); - } - const chunk = packetLength === Infinity ? value : value.subarray(0, packetLength - bytesRead); - if (writer) await writer.write(chunk); - else packet.push(chunk); - bytesRead += value.length; - if (bytesRead >= packetLength) { - reader.unshift(value.subarray(packetLength - bytesRead + value.length)); - break; - } - } - } - } while (wasPartialLength); - - // If this was not a packet that "supports streaming", we peek to check - // whether it is the last packet in the message. We peek 2 bytes instead - // of 1 because the beginning of this function also peeks 2 bytes, and we - // want to cut a `subarray` of the correct length into `web-stream-tools`' - // `externalBuffer` as a tiny optimization here. - // - // If it *was* a streaming packet (i.e. the data packets), we peek at the - // entire remainder of the stream, in order to forward errors in the - // remainder of the stream to the packet data. (Note that this means we - // read/peek at all signature packets before closing the literal data - // packet, for example.) This forwards MDC errors to the literal data - // stream, for example, so that they don't get lost / forgotten on - // decryptedMessage.packets.stream, which we never look at. - // - // An example of what we do when stream-parsing a message containing - // [ one-pass signature packet, literal data packet, signature packet ]: - // 1. Read the one-pass signature packet - // 2. Peek 2 bytes of the literal data packet - // 3. Parse the one-pass signature packet - // - // 4. Read the literal data packet, simultaneously stream-parsing it - // 5. Peek until the end of the message - // 6. Finish parsing the literal data packet - // - // 7. Read the signature packet again (we already peeked at it in step 5) - // 8. Peek at the end of the stream again (`peekBytes` returns undefined) - // 9. Parse the signature packet - // - // Note that this means that if there's an error in the very end of the - // stream, such as an MDC error, we throw in step 5 instead of in step 8 - // (or never), which is the point of this exercise. - const nextPacket = await reader.peekBytes(packetSupportsStreaming ? Infinity : 2); - if (writer) { - await writer.ready; - await writer.close(); - } else { - packet = util.concatUint8Array(packet); - await callback({ tag, packet }); - } - return !nextPacket || !nextPacket.length; - } catch (e) { - if (writer) { - await writer.abort(e); - return true; - } else { - throw e; - } - } finally { - if (writer) { - await callbackReturned; - } - reader.releaseLock(); - } -} - -class UnsupportedError extends Error { - constructor(...params) { - super(...params); - - if (Error.captureStackTrace) { - Error.captureStackTrace(this, UnsupportedError); - } - - this.name = 'UnsupportedError'; - } -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -// Symbol to store cryptographic validity of the signature, to avoid recomputing multiple times on verification. -const verified = Symbol('verified'); - -// GPG puts the Issuer and Signature subpackets in the unhashed area. -// Tampering with those invalidates the signature, so we still trust them and parse them. -// All other unhashed subpackets are ignored. -const allowedUnhashedSubpackets = new Set([ - enums.signatureSubpacket.issuer, - enums.signatureSubpacket.issuerFingerprint, - enums.signatureSubpacket.embeddedSignature -]); - -/** - * Implementation of the Signature Packet (Tag 2) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.2|RFC4480 5.2}: - * A Signature packet describes a binding between some public key and - * some data. The most common signatures are a signature of a file or a - * block of text, and a signature that is a certification of a User ID. - */ -class SignaturePacket { - static get tag() { - return enums.packet.signature; - } - - constructor() { - this.version = null; - /** @type {enums.signature} */ - this.signatureType = null; - /** @type {enums.hash} */ - this.hashAlgorithm = null; - /** @type {enums.publicKey} */ - this.publicKeyAlgorithm = null; - - this.signatureData = null; - this.unhashedSubpackets = []; - this.signedHashValue = null; - - this.created = null; - this.signatureExpirationTime = null; - this.signatureNeverExpires = true; - this.exportable = null; - this.trustLevel = null; - this.trustAmount = null; - this.regularExpression = null; - this.revocable = null; - this.keyExpirationTime = null; - this.keyNeverExpires = null; - this.preferredSymmetricAlgorithms = null; - this.revocationKeyClass = null; - this.revocationKeyAlgorithm = null; - this.revocationKeyFingerprint = null; - this.issuerKeyID = new KeyID(); - this.rawNotations = []; - this.notations = {}; - this.preferredHashAlgorithms = null; - this.preferredCompressionAlgorithms = null; - this.keyServerPreferences = null; - this.preferredKeyServer = null; - this.isPrimaryUserID = null; - this.policyURI = null; - this.keyFlags = null; - this.signersUserID = null; - this.reasonForRevocationFlag = null; - this.reasonForRevocationString = null; - this.features = null; - this.signatureTargetPublicKeyAlgorithm = null; - this.signatureTargetHashAlgorithm = null; - this.signatureTargetHash = null; - this.embeddedSignature = null; - this.issuerKeyVersion = null; - this.issuerFingerprint = null; - this.preferredAEADAlgorithms = null; - - this.revoked = null; - this[verified] = null; - } - - /** - * parsing function for a signature packet (tag 2). - * @param {String} bytes - Payload of a tag 2 packet - * @returns {SignaturePacket} Object representation. - */ - read(bytes) { - let i = 0; - this.version = bytes[i++]; - - if (this.version !== 4 && this.version !== 5) { - throw new UnsupportedError(`Version ${this.version} of the signature packet is unsupported.`); - } - - this.signatureType = bytes[i++]; - this.publicKeyAlgorithm = bytes[i++]; - this.hashAlgorithm = bytes[i++]; - - // hashed subpackets - i += this.readSubPackets(bytes.subarray(i, bytes.length), true); - if (!this.created) { - throw new Error('Missing signature creation time subpacket.'); - } - - // A V4 signature hashes the packet body - // starting from its first field, the version number, through the end - // of the hashed subpacket data. Thus, the fields hashed are the - // signature version, the signature type, the public-key algorithm, the - // hash algorithm, the hashed subpacket length, and the hashed - // subpacket body. - this.signatureData = bytes.subarray(0, i); - - // unhashed subpackets - i += this.readSubPackets(bytes.subarray(i, bytes.length), false); - - // Two-octet field holding left 16 bits of signed hash value. - this.signedHashValue = bytes.subarray(i, i + 2); - i += 2; - - this.params = mod.signature.parseSignatureParams(this.publicKeyAlgorithm, bytes.subarray(i, bytes.length)); - } - - /** - * @returns {Uint8Array | ReadableStream} - */ - writeParams() { - if (this.params instanceof Promise) { - return fromAsync( - async () => mod.serializeParams(this.publicKeyAlgorithm, await this.params) - ); - } - return mod.serializeParams(this.publicKeyAlgorithm, this.params); - } - - write() { - const arr = []; - arr.push(this.signatureData); - arr.push(this.writeUnhashedSubPackets()); - arr.push(this.signedHashValue); - arr.push(this.writeParams()); - return util.concat(arr); - } - - /** - * Signs provided data. This needs to be done prior to serialization. - * @param {SecretKeyPacket} key - Private key used to sign the message. - * @param {Object} data - Contains packets to be signed. - * @param {Date} [date] - The signature creation time. - * @param {Boolean} [detached] - Whether to create a detached signature - * @throws {Error} if signing failed - * @async - */ - async sign(key, data, date = new Date(), detached = false) { - if (key.version === 5) { - this.version = 5; - } else { - this.version = 4; - } - const arr = [new Uint8Array([this.version, this.signatureType, this.publicKeyAlgorithm, this.hashAlgorithm])]; - - this.created = util.normalizeDate(date); - this.issuerKeyVersion = key.version; - this.issuerFingerprint = key.getFingerprintBytes(); - this.issuerKeyID = key.getKeyID(); - - // Add hashed subpackets - arr.push(this.writeHashedSubPackets()); - - this.signatureData = util.concat(arr); - - const toHash = this.toHash(this.signatureType, data, detached); - const hash = await this.hash(this.signatureType, data, toHash, detached); - - this.signedHashValue = slice(clone(hash), 0, 2); - const signed = async () => mod.signature.sign( - this.publicKeyAlgorithm, this.hashAlgorithm, key.publicParams, key.privateParams, toHash, await readToEnd(hash) - ); - if (util.isStream(hash)) { - this.params = signed(); - } else { - this.params = await signed(); - - // Store the fact that this signature is valid, e.g. for when we call `await - // getLatestValidSignature(this.revocationSignatures, key, data)` later. - // Note that this only holds up if the key and data passed to verify are the - // same as the ones passed to sign. - this[verified] = true; - } - } - - /** - * Creates Uint8Array of bytes of all subpacket data except Issuer and Embedded Signature subpackets - * @returns {Uint8Array} Subpacket data. - */ - writeHashedSubPackets() { - const sub = enums.signatureSubpacket; - const arr = []; - let bytes; - if (this.created === null) { - throw new Error('Missing signature creation time'); - } - arr.push(writeSubPacket(sub.signatureCreationTime, util.writeDate(this.created))); - if (this.signatureExpirationTime !== null) { - arr.push(writeSubPacket(sub.signatureExpirationTime, util.writeNumber(this.signatureExpirationTime, 4))); - } - if (this.exportable !== null) { - arr.push(writeSubPacket(sub.exportableCertification, new Uint8Array([this.exportable ? 1 : 0]))); - } - if (this.trustLevel !== null) { - bytes = new Uint8Array([this.trustLevel, this.trustAmount]); - arr.push(writeSubPacket(sub.trustSignature, bytes)); - } - if (this.regularExpression !== null) { - arr.push(writeSubPacket(sub.regularExpression, this.regularExpression)); - } - if (this.revocable !== null) { - arr.push(writeSubPacket(sub.revocable, new Uint8Array([this.revocable ? 1 : 0]))); - } - if (this.keyExpirationTime !== null) { - arr.push(writeSubPacket(sub.keyExpirationTime, util.writeNumber(this.keyExpirationTime, 4))); - } - if (this.preferredSymmetricAlgorithms !== null) { - bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredSymmetricAlgorithms)); - arr.push(writeSubPacket(sub.preferredSymmetricAlgorithms, bytes)); - } - if (this.revocationKeyClass !== null) { - bytes = new Uint8Array([this.revocationKeyClass, this.revocationKeyAlgorithm]); - bytes = util.concat([bytes, this.revocationKeyFingerprint]); - arr.push(writeSubPacket(sub.revocationKey, bytes)); - } - this.rawNotations.forEach(([{ name, value, humanReadable }]) => { - bytes = [new Uint8Array([humanReadable ? 0x80 : 0, 0, 0, 0])]; - // 2 octets of name length - bytes.push(util.writeNumber(name.length, 2)); - // 2 octets of value length - bytes.push(util.writeNumber(value.length, 2)); - bytes.push(util.stringToUint8Array(name)); - bytes.push(value); - bytes = util.concat(bytes); - arr.push(writeSubPacket(sub.notationData, bytes)); - }); - if (this.preferredHashAlgorithms !== null) { - bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredHashAlgorithms)); - arr.push(writeSubPacket(sub.preferredHashAlgorithms, bytes)); - } - if (this.preferredCompressionAlgorithms !== null) { - bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredCompressionAlgorithms)); - arr.push(writeSubPacket(sub.preferredCompressionAlgorithms, bytes)); - } - if (this.keyServerPreferences !== null) { - bytes = util.stringToUint8Array(util.uint8ArrayToString(this.keyServerPreferences)); - arr.push(writeSubPacket(sub.keyServerPreferences, bytes)); - } - if (this.preferredKeyServer !== null) { - arr.push(writeSubPacket(sub.preferredKeyServer, util.stringToUint8Array(this.preferredKeyServer))); - } - if (this.isPrimaryUserID !== null) { - arr.push(writeSubPacket(sub.primaryUserID, new Uint8Array([this.isPrimaryUserID ? 1 : 0]))); - } - if (this.policyURI !== null) { - arr.push(writeSubPacket(sub.policyURI, util.stringToUint8Array(this.policyURI))); - } - if (this.keyFlags !== null) { - bytes = util.stringToUint8Array(util.uint8ArrayToString(this.keyFlags)); - arr.push(writeSubPacket(sub.keyFlags, bytes)); - } - if (this.signersUserID !== null) { - arr.push(writeSubPacket(sub.signersUserID, util.stringToUint8Array(this.signersUserID))); - } - if (this.reasonForRevocationFlag !== null) { - bytes = util.stringToUint8Array(String.fromCharCode(this.reasonForRevocationFlag) + this.reasonForRevocationString); - arr.push(writeSubPacket(sub.reasonForRevocation, bytes)); - } - if (this.features !== null) { - bytes = util.stringToUint8Array(util.uint8ArrayToString(this.features)); - arr.push(writeSubPacket(sub.features, bytes)); - } - if (this.signatureTargetPublicKeyAlgorithm !== null) { - bytes = [new Uint8Array([this.signatureTargetPublicKeyAlgorithm, this.signatureTargetHashAlgorithm])]; - bytes.push(util.stringToUint8Array(this.signatureTargetHash)); - bytes = util.concat(bytes); - arr.push(writeSubPacket(sub.signatureTarget, bytes)); - } - if (this.preferredAEADAlgorithms !== null) { - bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredAEADAlgorithms)); - arr.push(writeSubPacket(sub.preferredAEADAlgorithms, bytes)); - } - - const result = util.concat(arr); - const length = util.writeNumber(result.length, 2); - - return util.concat([length, result]); - } - - /** - * Creates Uint8Array of bytes of Issuer and Embedded Signature subpackets - * @returns {Uint8Array} Subpacket data. - */ - writeUnhashedSubPackets() { - const sub = enums.signatureSubpacket; - const arr = []; - let bytes; - if (!this.issuerKeyID.isNull() && this.issuerKeyVersion !== 5) { - // If the version of [the] key is greater than 4, this subpacket - // MUST NOT be included in the signature. - arr.push(writeSubPacket(sub.issuer, this.issuerKeyID.write())); - } - if (this.embeddedSignature !== null) { - arr.push(writeSubPacket(sub.embeddedSignature, this.embeddedSignature.write())); - } - if (this.issuerFingerprint !== null) { - bytes = [new Uint8Array([this.issuerKeyVersion]), this.issuerFingerprint]; - bytes = util.concat(bytes); - arr.push(writeSubPacket(sub.issuerFingerprint, bytes)); - } - this.unhashedSubpackets.forEach(data => { - arr.push(writeSimpleLength(data.length)); - arr.push(data); - }); - - const result = util.concat(arr); - const length = util.writeNumber(result.length, 2); - - return util.concat([length, result]); - } - - // V4 signature sub packets - readSubPacket(bytes, hashed = true) { - let mypos = 0; - - // The leftmost bit denotes a "critical" packet - const critical = bytes[mypos] & 0x80; - const type = bytes[mypos] & 0x7F; - - if (!hashed && !allowedUnhashedSubpackets.has(type)) { - this.unhashedSubpackets.push(bytes.subarray(mypos, bytes.length)); - return; - } - - mypos++; - - // subpacket type - switch (type) { - case enums.signatureSubpacket.signatureCreationTime: - // Signature Creation Time - this.created = util.readDate(bytes.subarray(mypos, bytes.length)); - break; - case enums.signatureSubpacket.signatureExpirationTime: { - // Signature Expiration Time in seconds - const seconds = util.readNumber(bytes.subarray(mypos, bytes.length)); - - this.signatureNeverExpires = seconds === 0; - this.signatureExpirationTime = seconds; - - break; - } - case enums.signatureSubpacket.exportableCertification: - // Exportable Certification - this.exportable = bytes[mypos++] === 1; - break; - case enums.signatureSubpacket.trustSignature: - // Trust Signature - this.trustLevel = bytes[mypos++]; - this.trustAmount = bytes[mypos++]; - break; - case enums.signatureSubpacket.regularExpression: - // Regular Expression - this.regularExpression = bytes[mypos]; - break; - case enums.signatureSubpacket.revocable: - // Revocable - this.revocable = bytes[mypos++] === 1; - break; - case enums.signatureSubpacket.keyExpirationTime: { - // Key Expiration Time in seconds - const seconds = util.readNumber(bytes.subarray(mypos, bytes.length)); - - this.keyExpirationTime = seconds; - this.keyNeverExpires = seconds === 0; - - break; - } - case enums.signatureSubpacket.preferredSymmetricAlgorithms: - // Preferred Symmetric Algorithms - this.preferredSymmetricAlgorithms = [...bytes.subarray(mypos, bytes.length)]; - break; - case enums.signatureSubpacket.revocationKey: - // Revocation Key - // (1 octet of class, 1 octet of public-key algorithm ID, 20 - // octets of - // fingerprint) - this.revocationKeyClass = bytes[mypos++]; - this.revocationKeyAlgorithm = bytes[mypos++]; - this.revocationKeyFingerprint = bytes.subarray(mypos, mypos + 20); - break; - - case enums.signatureSubpacket.issuer: - // Issuer - this.issuerKeyID.read(bytes.subarray(mypos, bytes.length)); - break; - - case enums.signatureSubpacket.notationData: { - // Notation Data - const humanReadable = !!(bytes[mypos] & 0x80); - - // We extract key/value tuple from the byte stream. - mypos += 4; - const m = util.readNumber(bytes.subarray(mypos, mypos + 2)); - mypos += 2; - const n = util.readNumber(bytes.subarray(mypos, mypos + 2)); - mypos += 2; - - const name = util.uint8ArrayToString(bytes.subarray(mypos, mypos + m)); - const value = bytes.subarray(mypos + m, mypos + m + n); - - this.rawNotations.push({ name, humanReadable, value, critical }); - - if (humanReadable) { - this.notations[name] = util.uint8ArrayToString(value); - } - break; - } - case enums.signatureSubpacket.preferredHashAlgorithms: - // Preferred Hash Algorithms - this.preferredHashAlgorithms = [...bytes.subarray(mypos, bytes.length)]; - break; - case enums.signatureSubpacket.preferredCompressionAlgorithms: - // Preferred Compression Algorithms - this.preferredCompressionAlgorithms = [...bytes.subarray(mypos, bytes.length)]; - break; - case enums.signatureSubpacket.keyServerPreferences: - // Key Server Preferences - this.keyServerPreferences = [...bytes.subarray(mypos, bytes.length)]; - break; - case enums.signatureSubpacket.preferredKeyServer: - // Preferred Key Server - this.preferredKeyServer = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); - break; - case enums.signatureSubpacket.primaryUserID: - // Primary User ID - this.isPrimaryUserID = bytes[mypos++] !== 0; - break; - case enums.signatureSubpacket.policyURI: - // Policy URI - this.policyURI = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); - break; - case enums.signatureSubpacket.keyFlags: - // Key Flags - this.keyFlags = [...bytes.subarray(mypos, bytes.length)]; - break; - case enums.signatureSubpacket.signersUserID: - // Signer's User ID - this.signersUserID = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); - break; - case enums.signatureSubpacket.reasonForRevocation: - // Reason for Revocation - this.reasonForRevocationFlag = bytes[mypos++]; - this.reasonForRevocationString = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); - break; - case enums.signatureSubpacket.features: - // Features - this.features = [...bytes.subarray(mypos, bytes.length)]; - break; - case enums.signatureSubpacket.signatureTarget: { - // Signature Target - // (1 octet public-key algorithm, 1 octet hash algorithm, N octets hash) - this.signatureTargetPublicKeyAlgorithm = bytes[mypos++]; - this.signatureTargetHashAlgorithm = bytes[mypos++]; - - const len = mod.getHashByteLength(this.signatureTargetHashAlgorithm); - - this.signatureTargetHash = util.uint8ArrayToString(bytes.subarray(mypos, mypos + len)); - break; - } - case enums.signatureSubpacket.embeddedSignature: - // Embedded Signature - this.embeddedSignature = new SignaturePacket(); - this.embeddedSignature.read(bytes.subarray(mypos, bytes.length)); - break; - case enums.signatureSubpacket.issuerFingerprint: - // Issuer Fingerprint - this.issuerKeyVersion = bytes[mypos++]; - this.issuerFingerprint = bytes.subarray(mypos, bytes.length); - if (this.issuerKeyVersion === 5) { - this.issuerKeyID.read(this.issuerFingerprint); - } else { - this.issuerKeyID.read(this.issuerFingerprint.subarray(-8)); - } - break; - case enums.signatureSubpacket.preferredAEADAlgorithms: - // Preferred AEAD Algorithms - this.preferredAEADAlgorithms = [...bytes.subarray(mypos, bytes.length)]; - break; - default: { - const err = new Error(`Unknown signature subpacket type ${type}`); - if (critical) { - throw err; - } else { - util.printDebug(err); - } - } - } - } - - readSubPackets(bytes, trusted = true, config) { - // Two-octet scalar octet count for following subpacket data. - const subpacketLength = util.readNumber(bytes.subarray(0, 2)); - - let i = 2; - - // subpacket data set (zero or more subpackets) - while (i < 2 + subpacketLength) { - const len = readSimpleLength(bytes.subarray(i, bytes.length)); - i += len.offset; - - this.readSubPacket(bytes.subarray(i, i + len.len), trusted, config); - - i += len.len; - } - - return i; - } - - // Produces data to produce signature on - toSign(type, data) { - const t = enums.signature; - - switch (type) { - case t.binary: - if (data.text !== null) { - return util.encodeUTF8(data.getText(true)); - } - return data.getBytes(true); - - case t.text: { - const bytes = data.getBytes(true); - // normalize EOL to \r\n - return util.canonicalizeEOL(bytes); - } - case t.standalone: - return new Uint8Array(0); - - case t.certGeneric: - case t.certPersona: - case t.certCasual: - case t.certPositive: - case t.certRevocation: { - let packet; - let tag; - - if (data.userID) { - tag = 0xB4; - packet = data.userID; - } else if (data.userAttribute) { - tag = 0xD1; - packet = data.userAttribute; - } else { - throw new Error('Either a userID or userAttribute packet needs to be ' + - 'supplied for certification.'); - } - - const bytes = packet.write(); - - return util.concat([this.toSign(t.key, data), - new Uint8Array([tag]), - util.writeNumber(bytes.length, 4), - bytes]); - } - case t.subkeyBinding: - case t.subkeyRevocation: - case t.keyBinding: - return util.concat([this.toSign(t.key, data), this.toSign(t.key, { - key: data.bind - })]); - - case t.key: - if (data.key === undefined) { - throw new Error('Key packet is required for this signature.'); - } - return data.key.writeForHash(this.version); - - case t.keyRevocation: - return this.toSign(t.key, data); - case t.timestamp: - return new Uint8Array(0); - case t.thirdParty: - throw new Error('Not implemented'); - default: - throw new Error('Unknown signature type.'); - } - } - - calculateTrailer(data, detached) { - let length = 0; - return transform(clone(this.signatureData), value => { - length += value.length; - }, () => { - const arr = []; - if (this.version === 5 && (this.signatureType === enums.signature.binary || this.signatureType === enums.signature.text)) { - if (detached) { - arr.push(new Uint8Array(6)); - } else { - arr.push(data.writeHeader()); - } - } - arr.push(new Uint8Array([this.version, 0xFF])); - if (this.version === 5) { - arr.push(new Uint8Array(4)); - } - arr.push(util.writeNumber(length, 4)); - // For v5, this should really be writeNumber(length, 8) rather than the - // hardcoded 4 zero bytes above - return util.concat(arr); - }); - } - - toHash(signatureType, data, detached = false) { - const bytes = this.toSign(signatureType, data); - - return util.concat([bytes, this.signatureData, this.calculateTrailer(data, detached)]); - } - - async hash(signatureType, data, toHash, detached = false) { - if (!toHash) toHash = this.toHash(signatureType, data, detached); - return mod.hash.digest(this.hashAlgorithm, toHash); - } - - /** - * verifies the signature packet. Note: not all signature types are implemented - * @param {PublicSubkeyPacket|PublicKeyPacket| - * SecretSubkeyPacket|SecretKeyPacket} key - the public key to verify the signature - * @param {module:enums.signature} signatureType - Expected signature type - * @param {String|Object} data - Data which on the signature applies - * @param {Date} [date] - Use the given date instead of the current time to check for signature validity and expiration - * @param {Boolean} [detached] - Whether to verify a detached signature - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if signature validation failed - * @async - */ - async verify(key, signatureType, data, date = new Date(), detached = false, config = defaultConfig) { - if (!this.issuerKeyID.equals(key.getKeyID())) { - throw new Error('Signature was not issued by the given public key'); - } - if (this.publicKeyAlgorithm !== key.algorithm) { - throw new Error('Public key algorithm used to sign signature does not match issuer key algorithm.'); - } - - const isMessageSignature = signatureType === enums.signature.binary || signatureType === enums.signature.text; - // Cryptographic validity is cached after one successful verification. - // However, for message signatures, we always re-verify, since the passed `data` can change - const skipVerify = this[verified] && !isMessageSignature; - if (!skipVerify) { - let toHash; - let hash; - if (this.hashed) { - hash = await this.hashed; - } else { - toHash = this.toHash(signatureType, data, detached); - hash = await this.hash(signatureType, data, toHash); - } - hash = await readToEnd(hash); - if (this.signedHashValue[0] !== hash[0] || - this.signedHashValue[1] !== hash[1]) { - throw new Error('Signed digest did not match'); - } - - this.params = await this.params; - - this[verified] = await mod.signature.verify( - this.publicKeyAlgorithm, this.hashAlgorithm, this.params, key.publicParams, - toHash, hash - ); - - if (!this[verified]) { - throw new Error('Signature verification failed'); - } - } - - const normDate = util.normalizeDate(date); - if (normDate && this.created > normDate) { - throw new Error('Signature creation time is in the future'); - } - if (normDate && normDate >= this.getExpirationTime()) { - throw new Error('Signature is expired'); - } - if (config.rejectHashAlgorithms.has(this.hashAlgorithm)) { - throw new Error('Insecure hash algorithm: ' + enums.read(enums.hash, this.hashAlgorithm).toUpperCase()); - } - if (config.rejectMessageHashAlgorithms.has(this.hashAlgorithm) && - [enums.signature.binary, enums.signature.text].includes(this.signatureType)) { - throw new Error('Insecure message hash algorithm: ' + enums.read(enums.hash, this.hashAlgorithm).toUpperCase()); - } - this.rawNotations.forEach(({ name, critical }) => { - if (critical && (config.knownNotations.indexOf(name) < 0)) { - throw new Error(`Unknown critical notation: ${name}`); - } - }); - if (this.revocationKeyClass !== null) { - throw new Error('This key is intended to be revoked with an authorized key, which OpenPGP.js does not support.'); - } - } - - /** - * Verifies signature expiration date - * @param {Date} [date] - Use the given date for verification instead of the current time - * @returns {Boolean} True if expired. - */ - isExpired(date = new Date()) { - const normDate = util.normalizeDate(date); - if (normDate !== null) { - return !(this.created <= normDate && normDate < this.getExpirationTime()); - } - return false; - } - - /** - * Returns the expiration time of the signature or Infinity if signature does not expire - * @returns {Date | Infinity} Expiration time. - */ - getExpirationTime() { - return this.signatureNeverExpires ? Infinity : new Date(this.created.getTime() + this.signatureExpirationTime * 1000); - } -} - -/** - * Creates a string representation of a sub signature packet - * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.1|RFC4880 5.2.3.1} - * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.2|RFC4880 5.2.3.2} - * @param {Integer} type - Subpacket signature type. - * @param {String} data - Data to be included - * @returns {String} A string-representation of a sub signature packet. - * @private - */ -function writeSubPacket(type, data) { - const arr = []; - arr.push(writeSimpleLength(data.length + 1)); - arr.push(new Uint8Array([type])); - arr.push(data); - return util.concat(arr); -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -const VERSION = 3; - -/** - * Implementation of the One-Pass Signature Packets (Tag 4) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.4|RFC4880 5.4}: - * The One-Pass Signature packet precedes the signed data and contains - * enough information to allow the receiver to begin calculating any - * hashes needed to verify the signature. It allows the Signature - * packet to be placed at the end of the message, so that the signer - * can compute the entire signed message in one pass. - */ -class OnePassSignaturePacket { - static get tag() { - return enums.packet.onePassSignature; - } - - constructor() { - /** A one-octet version number. The current version is 3. */ - this.version = null; - /** - * A one-octet signature type. - * Signature types are described in - * {@link https://tools.ietf.org/html/rfc4880#section-5.2.1|RFC4880 Section 5.2.1}. - * @type {enums.signature} - - */ - this.signatureType = null; - /** - * A one-octet number describing the hash algorithm used. - * @see {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC4880 9.4} - * @type {enums.hash} - */ - this.hashAlgorithm = null; - /** - * A one-octet number describing the public-key algorithm used. - * @see {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC4880 9.1} - * @type {enums.publicKey} - */ - this.publicKeyAlgorithm = null; - /** An eight-octet number holding the Key ID of the signing key. */ - this.issuerKeyID = null; - /** - * A one-octet number holding a flag showing whether the signature is nested. - * A zero value indicates that the next packet is another One-Pass Signature packet - * that describes another signature to be applied to the same message data. - */ - this.flags = null; - } - - /** - * parsing function for a one-pass signature packet (tag 4). - * @param {Uint8Array} bytes - Payload of a tag 4 packet - * @returns {OnePassSignaturePacket} Object representation. - */ - read(bytes) { - let mypos = 0; - // A one-octet version number. The current version is 3. - this.version = bytes[mypos++]; - if (this.version !== VERSION) { - throw new UnsupportedError(`Version ${this.version} of the one-pass signature packet is unsupported.`); - } - - // A one-octet signature type. Signature types are described in - // Section 5.2.1. - this.signatureType = bytes[mypos++]; - - // A one-octet number describing the hash algorithm used. - this.hashAlgorithm = bytes[mypos++]; - - // A one-octet number describing the public-key algorithm used. - this.publicKeyAlgorithm = bytes[mypos++]; - - // An eight-octet number holding the Key ID of the signing key. - this.issuerKeyID = new KeyID(); - this.issuerKeyID.read(bytes.subarray(mypos, mypos + 8)); - mypos += 8; - - // A one-octet number holding a flag showing whether the signature - // is nested. A zero value indicates that the next packet is - // another One-Pass Signature packet that describes another - // signature to be applied to the same message data. - this.flags = bytes[mypos++]; - return this; - } - - /** - * creates a string representation of a one-pass signature packet - * @returns {Uint8Array} A Uint8Array representation of a one-pass signature packet. - */ - write() { - const start = new Uint8Array([VERSION, this.signatureType, this.hashAlgorithm, this.publicKeyAlgorithm]); - - const end = new Uint8Array([this.flags]); - - return util.concatUint8Array([start, this.issuerKeyID.write(), end]); - } - - calculateTrailer(...args) { - return fromAsync(async () => SignaturePacket.prototype.calculateTrailer.apply(await this.correspondingSig, args)); - } - - async verify() { - const correspondingSig = await this.correspondingSig; - if (!correspondingSig || correspondingSig.constructor.tag !== enums.packet.signature) { - throw new Error('Corresponding signature packet missing'); - } - if ( - correspondingSig.signatureType !== this.signatureType || - correspondingSig.hashAlgorithm !== this.hashAlgorithm || - correspondingSig.publicKeyAlgorithm !== this.publicKeyAlgorithm || - !correspondingSig.issuerKeyID.equals(this.issuerKeyID) - ) { - throw new Error('Corresponding signature packet does not match one-pass signature packet'); - } - correspondingSig.hashed = this.hashed; - return correspondingSig.verify.apply(correspondingSig, arguments); - } -} - -OnePassSignaturePacket.prototype.hash = SignaturePacket.prototype.hash; -OnePassSignaturePacket.prototype.toHash = SignaturePacket.prototype.toHash; -OnePassSignaturePacket.prototype.toSign = SignaturePacket.prototype.toSign; - -/** - * Instantiate a new packet given its tag - * @function newPacketFromTag - * @param {module:enums.packet} tag - Property value from {@link module:enums.packet} - * @param {Object} allowedPackets - mapping where keys are allowed packet tags, pointing to their Packet class - * @returns {Object} New packet object with type based on tag - * @throws {Error|UnsupportedError} for disallowed or unknown packets - */ -function newPacketFromTag(tag, allowedPackets) { - if (!allowedPackets[tag]) { - // distinguish between disallowed packets and unknown ones - let packetType; - try { - packetType = enums.read(enums.packet, tag); - } catch (e) { - throw new UnsupportedError(`Unknown packet type with tag: ${tag}`); - } - throw new Error(`Packet not allowed in this context: ${packetType}`); - } - return new allowedPackets[tag](); -} - -/** - * This class represents a list of openpgp packets. - * Take care when iterating over it - the packets themselves - * are stored as numerical indices. - * @extends Array - */ -class PacketList extends Array { - /** - * Parses the given binary data and returns a list of packets. - * Equivalent to calling `read` on an empty PacketList instance. - * @param {Uint8Array | ReadableStream} bytes - binary data to parse - * @param {Object} allowedPackets - mapping where keys are allowed packet tags, pointing to their Packet class - * @param {Object} [config] - full configuration, defaults to openpgp.config - * @returns {PacketList} parsed list of packets - * @throws on parsing errors - * @async - */ - static async fromBinary(bytes, allowedPackets, config = defaultConfig) { - const packets = new PacketList(); - await packets.read(bytes, allowedPackets, config); - return packets; - } - - /** - * Reads a stream of binary data and interprets it as a list of packets. - * @param {Uint8Array | ReadableStream} bytes - binary data to parse - * @param {Object} allowedPackets - mapping where keys are allowed packet tags, pointing to their Packet class - * @param {Object} [config] - full configuration, defaults to openpgp.config - * @throws on parsing errors - * @async - */ - async read(bytes, allowedPackets, config = defaultConfig) { - this.stream = transformPair(bytes, async (readable, writable) => { - const writer = getWriter(writable); - try { - while (true) { - await writer.ready; - const done = await readPackets(readable, async parsed => { - try { - if (parsed.tag === enums.packet.marker || parsed.tag === enums.packet.trust) { - // According to the spec, these packet types should be ignored and not cause parsing errors, even if not esplicitly allowed: - // - Marker packets MUST be ignored when received: https://github.com/openpgpjs/openpgpjs/issues/1145 - // - Trust packets SHOULD be ignored outside of keyrings (unsupported): https://datatracker.ietf.org/doc/html/rfc4880#section-5.10 - return; - } - const packet = newPacketFromTag(parsed.tag, allowedPackets); - packet.packets = new PacketList(); - packet.fromStream = util.isStream(parsed.packet); - await packet.read(parsed.packet, config); - await writer.write(packet); - } catch (e) { - const throwUnsupportedError = !config.ignoreUnsupportedPackets && e instanceof UnsupportedError; - const throwMalformedError = !config.ignoreMalformedPackets && !(e instanceof UnsupportedError); - if (throwUnsupportedError || throwMalformedError || supportsStreaming(parsed.tag)) { - // The packets that support streaming are the ones that contain message data. - // Those are also the ones we want to be more strict about and throw on parse errors - // (since we likely cannot process the message without these packets anyway). - await writer.abort(e); - } - util.printDebugError(e); - } - }); - if (done) { - await writer.ready; - await writer.close(); - return; - } - } - } catch (e) { - await writer.abort(e); - } - }); - - // Wait until first few packets have been read - const reader = getReader(this.stream); - while (true) { - const { done, value } = await reader.read(); - if (!done) { - this.push(value); - } else { - this.stream = null; - } - if (done || supportsStreaming(value.constructor.tag)) { - break; - } - } - reader.releaseLock(); - } - - /** - * Creates a binary representation of openpgp objects contained within the - * class instance. - * @returns {Uint8Array} A Uint8Array containing valid openpgp packets. - */ - write() { - const arr = []; - - for (let i = 0; i < this.length; i++) { - const packetbytes = this[i].write(); - if (util.isStream(packetbytes) && supportsStreaming(this[i].constructor.tag)) { - let buffer = []; - let bufferLength = 0; - const minLength = 512; - arr.push(writeTag(this[i].constructor.tag)); - arr.push(transform(packetbytes, value => { - buffer.push(value); - bufferLength += value.length; - if (bufferLength >= minLength) { - const powerOf2 = Math.min(Math.log(bufferLength) / Math.LN2 | 0, 30); - const chunkSize = 2 ** powerOf2; - const bufferConcat = util.concat([writePartialLength(powerOf2)].concat(buffer)); - buffer = [bufferConcat.subarray(1 + chunkSize)]; - bufferLength = buffer[0].length; - return bufferConcat.subarray(0, 1 + chunkSize); - } - }, () => util.concat([writeSimpleLength(bufferLength)].concat(buffer)))); - } else { - if (util.isStream(packetbytes)) { - let length = 0; - arr.push(transform(clone(packetbytes), value => { - length += value.length; - }, () => writeHeader(this[i].constructor.tag, length))); - } else { - arr.push(writeHeader(this[i].constructor.tag, packetbytes.length)); - } - arr.push(packetbytes); - } - } - - return util.concat(arr); - } - - /** - * Creates a new PacketList with all packets matching the given tag(s) - * @param {...module:enums.packet} tags - packet tags to look for - * @returns {PacketList} - */ - filterByTag(...tags) { - const filtered = new PacketList(); - - const handle = tag => packetType => tag === packetType; - - for (let i = 0; i < this.length; i++) { - if (tags.some(handle(this[i].constructor.tag))) { - filtered.push(this[i]); - } - } - - return filtered; - } - - /** - * Traverses packet list and returns first packet with matching tag - * @param {module:enums.packet} tag - The packet tag - * @returns {Packet|undefined} - */ - findPacket(tag) { - return this.find(packet => packet.constructor.tag === tag); - } - - /** - * Find indices of packets with the given tag(s) - * @param {...module:enums.packet} tags - packet tags to look for - * @returns {Integer[]} packet indices - */ - indexOfTag(...tags) { - const tagIndex = []; - const that = this; - - const handle = tag => packetType => tag === packetType; - - for (let i = 0; i < this.length; i++) { - if (tags.some(handle(that[i].constructor.tag))) { - tagIndex.push(i); - } - } - return tagIndex; - } -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -// A Compressed Data packet can contain the following packet types -const allowedPackets = /*#__PURE__*/ util.constructAllowedPackets([ - LiteralDataPacket, - OnePassSignaturePacket, - SignaturePacket -]); - -/** - * Implementation of the Compressed Data Packet (Tag 8) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.6|RFC4880 5.6}: - * The Compressed Data packet contains compressed data. Typically, - * this packet is found as the contents of an encrypted packet, or following - * a Signature or One-Pass Signature packet, and contains a literal data packet. - */ -class CompressedDataPacket { - static get tag() { - return enums.packet.compressedData; - } - - /** - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - constructor(config = defaultConfig) { - /** - * List of packets - * @type {PacketList} - */ - this.packets = null; - /** - * Compression algorithm - * @type {enums.compression} - */ - this.algorithm = config.preferredCompressionAlgorithm; - - /** - * Compressed packet data - * @type {Uint8Array | ReadableStream} - */ - this.compressed = null; - - /** - * zip/zlib compression level, between 1 and 9 - */ - this.deflateLevel = config.deflateLevel; - } - - /** - * Parsing function for the packet. - * @param {Uint8Array | ReadableStream} bytes - Payload of a tag 8 packet - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - async read(bytes, config = defaultConfig) { - await parse(bytes, async reader => { - - // One octet that gives the algorithm used to compress the packet. - this.algorithm = await reader.readByte(); - - // Compressed data, which makes up the remainder of the packet. - this.compressed = reader.remainder(); - - await this.decompress(config); - }); - } - - - /** - * Return the compressed packet. - * @returns {Uint8Array | ReadableStream} Binary compressed packet. - */ - write() { - if (this.compressed === null) { - this.compress(); - } - - return util.concat([new Uint8Array([this.algorithm]), this.compressed]); - } - - - /** - * Decompression method for decompressing the compressed data - * read by read_packet - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - async decompress(config = defaultConfig) { - const compressionName = enums.read(enums.compression, this.algorithm); - const decompressionFn = decompress_fns[compressionName]; - if (!decompressionFn) { - throw new Error(`${compressionName} decompression not supported`); - } - - this.packets = await PacketList.fromBinary(decompressionFn(this.compressed), allowedPackets, config); - } - - /** - * Compress the packet data (member decompressedData) - */ - compress() { - const compressionName = enums.read(enums.compression, this.algorithm); - const compressionFn = compress_fns[compressionName]; - if (!compressionFn) { - throw new Error(`${compressionName} compression not supported`); - } - - this.compressed = compressionFn(this.packets.write(), this.deflateLevel); - } -} - -////////////////////////// -// // -// Helper functions // -// // -////////////////////////// - - -const nodeZlib = util.getNodeZlib(); - -function uncompressed(data) { - return data; -} - -function node_zlib(func, create, options = {}) { - return function (data) { - if (!util.isStream(data) || isArrayStream(data)) { - return fromAsync(() => readToEnd(data).then(data => { - return new Promise((resolve, reject) => { - func(data, options, (err, result) => { - if (err) return reject(err); - resolve(result); - }); - }); - })); - } - return nodeToWeb(webToNode(data).pipe(create(options))); - }; -} - -function pako_zlib(constructor, options = {}) { - return function(data) { - const obj = new constructor(options); - return transform(data, value => { - if (value.length) { - obj.push(value, Z_SYNC_FLUSH); - return obj.result; - } - }, () => { - if (constructor === Deflate) { - obj.push([], Z_FINISH); - return obj.result; - } - }); - }; -} - -function bzip2(func) { - return function(data) { - return fromAsync(async () => func(await readToEnd(data))); - }; -} - -const compress_fns = nodeZlib ? { - zip: /*#__PURE__*/ (compressed, level) => node_zlib(nodeZlib.deflateRaw, nodeZlib.createDeflateRaw, { level })(compressed), - zlib: /*#__PURE__*/ (compressed, level) => node_zlib(nodeZlib.deflate, nodeZlib.createDeflate, { level })(compressed) -} : { - zip: /*#__PURE__*/ (compressed, level) => pako_zlib(Deflate, { raw: true, level })(compressed), - zlib: /*#__PURE__*/ (compressed, level) => pako_zlib(Deflate, { level })(compressed) -}; - -const decompress_fns = nodeZlib ? { - uncompressed: uncompressed, - zip: /*#__PURE__*/ node_zlib(nodeZlib.inflateRaw, nodeZlib.createInflateRaw), - zlib: /*#__PURE__*/ node_zlib(nodeZlib.inflate, nodeZlib.createInflate), - bzip2: /*#__PURE__*/ bzip2(lib_4) -} : { - uncompressed: uncompressed, - zip: /*#__PURE__*/ pako_zlib(Inflate, { raw: true }), - zlib: /*#__PURE__*/ pako_zlib(Inflate), - bzip2: /*#__PURE__*/ bzip2(lib_4) -}; - -// GPG4Browsers - An OpenPGP implementation in javascript - -// A SEIP packet can contain the following packet types -const allowedPackets$1 = /*#__PURE__*/ util.constructAllowedPackets([ - LiteralDataPacket, - CompressedDataPacket, - OnePassSignaturePacket, - SignaturePacket -]); - -const VERSION$1 = 1; // A one-octet version number of the data packet. - -/** - * Implementation of the Sym. Encrypted Integrity Protected Data Packet (Tag 18) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.13|RFC4880 5.13}: - * The Symmetrically Encrypted Integrity Protected Data packet is - * a variant of the Symmetrically Encrypted Data packet. It is a new feature - * created for OpenPGP that addresses the problem of detecting a modification to - * encrypted data. It is used in combination with a Modification Detection Code - * packet. - */ -class SymEncryptedIntegrityProtectedDataPacket { - static get tag() { - return enums.packet.symEncryptedIntegrityProtectedData; - } - - constructor() { - this.version = VERSION$1; - this.encrypted = null; - this.packets = null; - } - - async read(bytes) { - await parse(bytes, async reader => { - const version = await reader.readByte(); - // - A one-octet version number. The only currently defined value is 1. - if (version !== VERSION$1) { - throw new UnsupportedError(`Version ${version} of the SEIP packet is unsupported.`); - } - - // - Encrypted data, the output of the selected symmetric-key cipher - // operating in Cipher Feedback mode with shift amount equal to the - // block size of the cipher (CFB-n where n is the block size). - this.encrypted = reader.remainder(); - }); - } - - write() { - return util.concat([new Uint8Array([VERSION$1]), this.encrypted]); - } - - /** - * Encrypt the payload in the packet. - * @param {enums.symmetric} sessionKeyAlgorithm - The symmetric encryption algorithm to use - * @param {Uint8Array} key - The key of cipher blocksize length to be used - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} - * @throws {Error} on encryption failure - * @async - */ - async encrypt(sessionKeyAlgorithm, key, config = defaultConfig) { - const { blockSize } = mod.getCipher(sessionKeyAlgorithm); - - let bytes = this.packets.write(); - if (isArrayStream(bytes)) bytes = await readToEnd(bytes); - const prefix = await mod.getPrefixRandom(sessionKeyAlgorithm); - const mdc = new Uint8Array([0xD3, 0x14]); // modification detection code packet - - const tohash = util.concat([prefix, bytes, mdc]); - const hash = await mod.hash.sha1(passiveClone(tohash)); - const plaintext = util.concat([tohash, hash]); - - this.encrypted = await mod.mode.cfb.encrypt(sessionKeyAlgorithm, key, plaintext, new Uint8Array(blockSize), config); - return true; - } - - /** - * Decrypts the encrypted data contained in the packet. - * @param {enums.symmetric} sessionKeyAlgorithm - The selected symmetric encryption algorithm to be used - * @param {Uint8Array} key - The key of cipher blocksize length to be used - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} - * @throws {Error} on decryption failure - * @async - */ - async decrypt(sessionKeyAlgorithm, key, config = defaultConfig) { - const { blockSize } = mod.getCipher(sessionKeyAlgorithm); - let encrypted = clone(this.encrypted); - if (isArrayStream(encrypted)) encrypted = await readToEnd(encrypted); - const decrypted = await mod.mode.cfb.decrypt(sessionKeyAlgorithm, key, encrypted, new Uint8Array(blockSize)); - - // there must be a modification detection code packet as the - // last packet and everything gets hashed except the hash itself - const realHash = slice(passiveClone(decrypted), -20); - const tohash = slice(decrypted, 0, -20); - const verifyHash = Promise.all([ - readToEnd(await mod.hash.sha1(passiveClone(tohash))), - readToEnd(realHash) - ]).then(([hash, mdc]) => { - if (!util.equalsUint8Array(hash, mdc)) { - throw new Error('Modification detected.'); - } - return new Uint8Array(); - }); - const bytes = slice(tohash, blockSize + 2); // Remove random prefix - let packetbytes = slice(bytes, 0, -2); // Remove MDC packet - packetbytes = concat([packetbytes, fromAsync(() => verifyHash)]); - if (!util.isStream(encrypted) || !config.allowUnauthenticatedStream) { - packetbytes = await readToEnd(packetbytes); - } - this.packets = await PacketList.fromBinary(packetbytes, allowedPackets$1, config); - return true; - } -} - -// OpenPGP.js - An OpenPGP implementation in javascript - -// An AEAD-encrypted Data packet can contain the following packet types -const allowedPackets$2 = /*#__PURE__*/ util.constructAllowedPackets([ - LiteralDataPacket, - CompressedDataPacket, - OnePassSignaturePacket, - SignaturePacket -]); - -const VERSION$2 = 1; // A one-octet version number of the data packet. - -/** - * Implementation of the Symmetrically Encrypted Authenticated Encryption with - * Additional Data (AEAD) Protected Data Packet - * - * {@link https://tools.ietf.org/html/draft-ford-openpgp-format-00#section-2.1}: - * AEAD Protected Data Packet - */ -class AEADEncryptedDataPacket { - static get tag() { - return enums.packet.aeadEncryptedData; - } - - constructor() { - this.version = VERSION$2; - /** @type {enums.symmetric} */ - this.cipherAlgorithm = null; - /** @type {enums.aead} */ - this.aeadAlgorithm = enums.aead.eax; - this.chunkSizeByte = null; - this.iv = null; - this.encrypted = null; - this.packets = null; - } - - /** - * Parse an encrypted payload of bytes in the order: version, IV, ciphertext (see specification) - * @param {Uint8Array | ReadableStream} bytes - * @throws {Error} on parsing failure - */ - async read(bytes) { - await parse(bytes, async reader => { - const version = await reader.readByte(); - if (version !== VERSION$2) { // The only currently defined value is 1. - throw new UnsupportedError(`Version ${version} of the AEAD-encrypted data packet is not supported.`); - } - this.cipherAlgorithm = await reader.readByte(); - this.aeadAlgorithm = await reader.readByte(); - this.chunkSizeByte = await reader.readByte(); - - const mode = mod.getAEADMode(this.aeadAlgorithm); - this.iv = await reader.readBytes(mode.ivLength); - this.encrypted = reader.remainder(); - }); - } - - /** - * Write the encrypted payload of bytes in the order: version, IV, ciphertext (see specification) - * @returns {Uint8Array | ReadableStream} The encrypted payload. - */ - write() { - return util.concat([new Uint8Array([this.version, this.cipherAlgorithm, this.aeadAlgorithm, this.chunkSizeByte]), this.iv, this.encrypted]); - } - - /** - * Decrypt the encrypted payload. - * @param {enums.symmetric} sessionKeyAlgorithm - The session key's cipher algorithm - * @param {Uint8Array} key - The session key used to encrypt the payload - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if decryption was not successful - * @async - */ - async decrypt(sessionKeyAlgorithm, key, config = defaultConfig) { - this.packets = await PacketList.fromBinary( - await this.crypt('decrypt', key, clone(this.encrypted)), - allowedPackets$2, - config - ); - } - - /** - * Encrypt the packet payload. - * @param {enums.symmetric} sessionKeyAlgorithm - The session key's cipher algorithm - * @param {Uint8Array} key - The session key used to encrypt the payload - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if encryption was not successful - * @async - */ - async encrypt(sessionKeyAlgorithm, key, config = defaultConfig) { - this.cipherAlgorithm = sessionKeyAlgorithm; - - const { ivLength } = mod.getAEADMode(this.aeadAlgorithm); - this.iv = await mod.random.getRandomBytes(ivLength); // generate new random IV - this.chunkSizeByte = config.aeadChunkSizeByte; - const data = this.packets.write(); - this.encrypted = await this.crypt('encrypt', key, data); - } - - /** - * En/decrypt the payload. - * @param {encrypt|decrypt} fn - Whether to encrypt or decrypt - * @param {Uint8Array} key - The session key used to en/decrypt the payload - * @param {Uint8Array | ReadableStream} data - The data to en/decrypt - * @returns {Promise>} - * @async - */ - async crypt(fn, key, data) { - const mode = mod.getAEADMode(this.aeadAlgorithm); - const modeInstance = await mode(this.cipherAlgorithm, key); - const tagLengthIfDecrypting = fn === 'decrypt' ? mode.tagLength : 0; - const tagLengthIfEncrypting = fn === 'encrypt' ? mode.tagLength : 0; - const chunkSize = 2 ** (this.chunkSizeByte + 6) + tagLengthIfDecrypting; // ((uint64_t)1 << (c + 6)) - const adataBuffer = new ArrayBuffer(21); - const adataArray = new Uint8Array(adataBuffer, 0, 13); - const adataTagArray = new Uint8Array(adataBuffer); - const adataView = new DataView(adataBuffer); - const chunkIndexArray = new Uint8Array(adataBuffer, 5, 8); - adataArray.set([0xC0 | AEADEncryptedDataPacket.tag, this.version, this.cipherAlgorithm, this.aeadAlgorithm, this.chunkSizeByte], 0); - let chunkIndex = 0; - let latestPromise = Promise.resolve(); - let cryptedBytes = 0; - let queuedBytes = 0; - const iv = this.iv; - return transformPair(data, async (readable, writable) => { - if (util.isStream(readable) !== 'array') { - const buffer = new TransformStream({}, { - highWaterMark: util.getHardwareConcurrency() * 2 ** (this.chunkSizeByte + 6), - size: array => array.length - }); - pipe(buffer.readable, writable); - writable = buffer.writable; - } - const reader = getReader(readable); - const writer = getWriter(writable); - try { - while (true) { - let chunk = await reader.readBytes(chunkSize + tagLengthIfDecrypting) || new Uint8Array(); - const finalChunk = chunk.subarray(chunk.length - tagLengthIfDecrypting); - chunk = chunk.subarray(0, chunk.length - tagLengthIfDecrypting); - let cryptedPromise; - let done; - if (!chunkIndex || chunk.length) { - reader.unshift(finalChunk); - cryptedPromise = modeInstance[fn](chunk, mode.getNonce(iv, chunkIndexArray), adataArray); - queuedBytes += chunk.length - tagLengthIfDecrypting + tagLengthIfEncrypting; - } else { - // After the last chunk, we either encrypt a final, empty - // data chunk to get the final authentication tag or - // validate that final authentication tag. - adataView.setInt32(13 + 4, cryptedBytes); // Should be setInt64(13, ...) - cryptedPromise = modeInstance[fn](finalChunk, mode.getNonce(iv, chunkIndexArray), adataTagArray); - queuedBytes += tagLengthIfEncrypting; - done = true; - } - cryptedBytes += chunk.length - tagLengthIfDecrypting; - // eslint-disable-next-line no-loop-func - latestPromise = latestPromise.then(() => cryptedPromise).then(async crypted => { - await writer.ready; - await writer.write(crypted); - queuedBytes -= crypted.length; - }).catch(err => writer.abort(err)); - if (done || queuedBytes > writer.desiredSize) { - await latestPromise; // Respect backpressure - } - if (!done) { - adataView.setInt32(5 + 4, ++chunkIndex); // Should be setInt64(5, ...) - } else { - await writer.close(); - break; - } - } - } catch (e) { - await writer.abort(e); - } - }); - } -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -const VERSION$3 = 3; - -/** - * Public-Key Encrypted Session Key Packets (Tag 1) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.1|RFC4880 5.1}: - * A Public-Key Encrypted Session Key packet holds the session key - * used to encrypt a message. Zero or more Public-Key Encrypted Session Key - * packets and/or Symmetric-Key Encrypted Session Key packets may precede a - * Symmetrically Encrypted Data Packet, which holds an encrypted message. The - * message is encrypted with the session key, and the session key is itself - * encrypted and stored in the Encrypted Session Key packet(s). The - * Symmetrically Encrypted Data Packet is preceded by one Public-Key Encrypted - * Session Key packet for each OpenPGP key to which the message is encrypted. - * The recipient of the message finds a session key that is encrypted to their - * public key, decrypts the session key, and then uses the session key to - * decrypt the message. - */ -class PublicKeyEncryptedSessionKeyPacket { - static get tag() { - return enums.packet.publicKeyEncryptedSessionKey; - } - - constructor() { - this.version = 3; - - this.publicKeyID = new KeyID(); - this.publicKeyAlgorithm = null; - - this.sessionKey = null; - /** - * Algorithm to encrypt the message with - * @type {enums.symmetric} - */ - this.sessionKeyAlgorithm = null; - - /** @type {Object} */ - this.encrypted = {}; - } - - /** - * Parsing function for a publickey encrypted session key packet (tag 1). - * - * @param {Uint8Array} bytes - Payload of a tag 1 packet - */ - read(bytes) { - this.version = bytes[0]; - if (this.version !== VERSION$3) { - throw new UnsupportedError(`Version ${this.version} of the PKESK packet is unsupported.`); - } - this.publicKeyID.read(bytes.subarray(1, bytes.length)); - this.publicKeyAlgorithm = bytes[9]; - this.encrypted = mod.parseEncSessionKeyParams(this.publicKeyAlgorithm, bytes.subarray(10)); - } - - /** - * Create a binary representation of a tag 1 packet - * - * @returns {Uint8Array} The Uint8Array representation. - */ - write() { - const arr = [ - new Uint8Array([this.version]), - this.publicKeyID.write(), - new Uint8Array([this.publicKeyAlgorithm]), - mod.serializeParams(this.publicKeyAlgorithm, this.encrypted) - ]; - - return util.concatUint8Array(arr); - } - - /** - * Encrypt session key packet - * @param {PublicKeyPacket} key - Public key - * @throws {Error} if encryption failed - * @async - */ - async encrypt(key) { - const data = util.concatUint8Array([ - new Uint8Array([enums.write(enums.symmetric, this.sessionKeyAlgorithm)]), - this.sessionKey, - util.writeChecksum(this.sessionKey) - ]); - const algo = enums.write(enums.publicKey, this.publicKeyAlgorithm); - this.encrypted = await mod.publicKeyEncrypt( - algo, key.publicParams, data, key.getFingerprintBytes()); - } - - /** - * Decrypts the session key (only for public key encrypted session key packets (tag 1) - * @param {SecretKeyPacket} key - decrypted private key - * @param {Object} [randomSessionKey] - Bogus session key to use in case of sensitive decryption error, or if the decrypted session key is of a different type/size. - * This is needed for constant-time processing. Expected object of the form: { sessionKey: Uint8Array, sessionKeyAlgorithm: enums.symmetric } - * @throws {Error} if decryption failed, unless `randomSessionKey` is given - * @async - */ - async decrypt(key, randomSessionKey) { - // check that session key algo matches the secret key algo - if (this.publicKeyAlgorithm !== key.algorithm) { - throw new Error('Decryption error'); - } - - const randomPayload = randomSessionKey ? util.concatUint8Array([ - new Uint8Array([randomSessionKey.sessionKeyAlgorithm]), - randomSessionKey.sessionKey, - util.writeChecksum(randomSessionKey.sessionKey) - ]) : null; - const decoded = await mod.publicKeyDecrypt(this.publicKeyAlgorithm, key.publicParams, key.privateParams, this.encrypted, key.getFingerprintBytes(), randomPayload); - const symmetricAlgoByte = decoded[0]; - const sessionKey = decoded.subarray(1, decoded.length - 2); - const checksum = decoded.subarray(decoded.length - 2); - const computedChecksum = util.writeChecksum(sessionKey); - const isValidChecksum = computedChecksum[0] === checksum[0] & computedChecksum[1] === checksum[1]; - - if (randomSessionKey) { - // We must not leak info about the validity of the decrypted checksum or cipher algo. - // The decrypted session key must be of the same algo and size as the random session key, otherwise we discard it and use the random data. - const isValidPayload = isValidChecksum & symmetricAlgoByte === randomSessionKey.sessionKeyAlgorithm & sessionKey.length === randomSessionKey.sessionKey.length; - this.sessionKeyAlgorithm = util.selectUint8(isValidPayload, symmetricAlgoByte, randomSessionKey.sessionKeyAlgorithm); - this.sessionKey = util.selectUint8Array(isValidPayload, sessionKey, randomSessionKey.sessionKey); - - } else { - const isValidPayload = isValidChecksum && enums.read(enums.symmetric, symmetricAlgoByte); - if (isValidPayload) { - this.sessionKey = sessionKey; - this.sessionKeyAlgorithm = symmetricAlgoByte; - } else { - throw new Error('Decryption error'); - } - } - } -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -class S2K { - /** - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - constructor(config = defaultConfig) { - /** - * Hash function identifier, or 0 for gnu-dummy keys - * @type {module:enums.hash | 0} - */ - this.algorithm = enums.hash.sha256; - /** - * enums.s2k identifier or 'gnu-dummy' - * @type {String} - */ - this.type = 'iterated'; - /** @type {Integer} */ - this.c = config.s2kIterationCountByte; - /** Eight bytes of salt in a binary string. - * @type {Uint8Array} - */ - this.salt = null; - } - - getCount() { - // Exponent bias, defined in RFC4880 - const expbias = 6; - - return (16 + (this.c & 15)) << ((this.c >> 4) + expbias); - } - - /** - * Parsing function for a string-to-key specifier ({@link https://tools.ietf.org/html/rfc4880#section-3.7|RFC 4880 3.7}). - * @param {Uint8Array} bytes - Payload of string-to-key specifier - * @returns {Integer} Actual length of the object. - */ - read(bytes) { - let i = 0; - this.type = enums.read(enums.s2k, bytes[i++]); - this.algorithm = bytes[i++]; - - switch (this.type) { - case 'simple': - break; - - case 'salted': - this.salt = bytes.subarray(i, i + 8); - i += 8; - break; - - case 'iterated': - this.salt = bytes.subarray(i, i + 8); - i += 8; - - // Octet 10: count, a one-octet, coded value - this.c = bytes[i++]; - break; - - case 'gnu': - if (util.uint8ArrayToString(bytes.subarray(i, i + 3)) === 'GNU') { - i += 3; // GNU - const gnuExtType = 1000 + bytes[i++]; - if (gnuExtType === 1001) { - this.type = 'gnu-dummy'; - // GnuPG extension mode 1001 -- don't write secret key at all - } else { - throw new Error('Unknown s2k gnu protection mode.'); - } - } else { - throw new Error('Unknown s2k type.'); - } - break; - - default: - throw new Error('Unknown s2k type.'); - } - - return i; - } - - /** - * Serializes s2k information - * @returns {Uint8Array} Binary representation of s2k. - */ - write() { - if (this.type === 'gnu-dummy') { - return new Uint8Array([101, 0, ...util.stringToUint8Array('GNU'), 1]); - } - const arr = [new Uint8Array([enums.write(enums.s2k, this.type), this.algorithm])]; - - switch (this.type) { - case 'simple': - break; - case 'salted': - arr.push(this.salt); - break; - case 'iterated': - arr.push(this.salt); - arr.push(new Uint8Array([this.c])); - break; - case 'gnu': - throw new Error('GNU s2k type not supported.'); - default: - throw new Error('Unknown s2k type.'); - } - - return util.concatUint8Array(arr); - } - - /** - * Produces a key using the specified passphrase and the defined - * hashAlgorithm - * @param {String} passphrase - Passphrase containing user input - * @returns {Promise} Produced key with a length corresponding to. - * hashAlgorithm hash length - * @async - */ - async produceKey(passphrase, numBytes) { - passphrase = util.encodeUTF8(passphrase); - - const arr = []; - let rlength = 0; - - let prefixlen = 0; - while (rlength < numBytes) { - let toHash; - switch (this.type) { - case 'simple': - toHash = util.concatUint8Array([new Uint8Array(prefixlen), passphrase]); - break; - case 'salted': - toHash = util.concatUint8Array([new Uint8Array(prefixlen), this.salt, passphrase]); - break; - case 'iterated': { - const data = util.concatUint8Array([this.salt, passphrase]); - let datalen = data.length; - const count = Math.max(this.getCount(), datalen); - toHash = new Uint8Array(prefixlen + count); - toHash.set(data, prefixlen); - for (let pos = prefixlen + datalen; pos < count; pos += datalen, datalen *= 2) { - toHash.copyWithin(pos, prefixlen, pos); - } - break; - } - case 'gnu': - throw new Error('GNU s2k type not supported.'); - default: - throw new Error('Unknown s2k type.'); - } - const result = await mod.hash.digest(this.algorithm, toHash); - arr.push(result); - rlength += result.length; - prefixlen++; - } - - return util.concatUint8Array(arr).subarray(0, numBytes); - } -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -/** - * Symmetric-Key Encrypted Session Key Packets (Tag 3) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.3|RFC4880 5.3}: - * The Symmetric-Key Encrypted Session Key packet holds the - * symmetric-key encryption of a session key used to encrypt a message. - * Zero or more Public-Key Encrypted Session Key packets and/or - * Symmetric-Key Encrypted Session Key packets may precede a - * Symmetrically Encrypted Data packet that holds an encrypted message. - * The message is encrypted with a session key, and the session key is - * itself encrypted and stored in the Encrypted Session Key packet or - * the Symmetric-Key Encrypted Session Key packet. - */ -class SymEncryptedSessionKeyPacket { - static get tag() { - return enums.packet.symEncryptedSessionKey; - } - - /** - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - constructor(config = defaultConfig) { - this.version = config.aeadProtect ? 5 : 4; - this.sessionKey = null; - /** - * Algorithm to encrypt the session key with - * @type {enums.symmetric} - */ - this.sessionKeyEncryptionAlgorithm = null; - /** - * Algorithm to encrypt the message with - * @type {enums.symmetric} - */ - this.sessionKeyAlgorithm = enums.symmetric.aes256; - /** - * AEAD mode to encrypt the session key with (if AEAD protection is enabled) - * @type {enums.aead} - */ - this.aeadAlgorithm = enums.write(enums.aead, config.preferredAEADAlgorithm); - this.encrypted = null; - this.s2k = null; - this.iv = null; - } - - /** - * Parsing function for a symmetric encrypted session key packet (tag 3). - * - * @param {Uint8Array} bytes - Payload of a tag 3 packet - */ - read(bytes) { - let offset = 0; - - // A one-octet version number. The only currently defined version is 4. - this.version = bytes[offset++]; - if (this.version !== 4 && this.version !== 5) { - throw new UnsupportedError(`Version ${this.version} of the SKESK packet is unsupported.`); - } - - // A one-octet number describing the symmetric algorithm used. - const algo = bytes[offset++]; - - if (this.version === 5) { - // A one-octet AEAD algorithm. - this.aeadAlgorithm = bytes[offset++]; - } - - // A string-to-key (S2K) specifier, length as defined above. - this.s2k = new S2K(); - offset += this.s2k.read(bytes.subarray(offset, bytes.length)); - - if (this.version === 5) { - const mode = mod.getAEADMode(this.aeadAlgorithm); - - // A starting initialization vector of size specified by the AEAD - // algorithm. - this.iv = bytes.subarray(offset, offset += mode.ivLength); - } - - // The encrypted session key itself, which is decrypted with the - // string-to-key object. This is optional in version 4. - if (this.version === 5 || offset < bytes.length) { - this.encrypted = bytes.subarray(offset, bytes.length); - this.sessionKeyEncryptionAlgorithm = algo; - } else { - this.sessionKeyAlgorithm = algo; - } - } - - /** - * Create a binary representation of a tag 3 packet - * - * @returns {Uint8Array} The Uint8Array representation. - */ - write() { - const algo = this.encrypted === null ? - this.sessionKeyAlgorithm : - this.sessionKeyEncryptionAlgorithm; - - let bytes; - - if (this.version === 5) { - bytes = util.concatUint8Array([new Uint8Array([this.version, algo, this.aeadAlgorithm]), this.s2k.write(), this.iv, this.encrypted]); - } else { - bytes = util.concatUint8Array([new Uint8Array([this.version, algo]), this.s2k.write()]); - - if (this.encrypted !== null) { - bytes = util.concatUint8Array([bytes, this.encrypted]); - } - } - - return bytes; - } - - /** - * Decrypts the session key with the given passphrase - * @param {String} passphrase - The passphrase in string form - * @throws {Error} if decryption was not successful - * @async - */ - async decrypt(passphrase) { - const algo = this.sessionKeyEncryptionAlgorithm !== null ? - this.sessionKeyEncryptionAlgorithm : - this.sessionKeyAlgorithm; - - const { blockSize, keySize } = mod.getCipher(algo); - const key = await this.s2k.produceKey(passphrase, keySize); - - if (this.version === 5) { - const mode = mod.getAEADMode(this.aeadAlgorithm); - const adata = new Uint8Array([0xC0 | SymEncryptedSessionKeyPacket.tag, this.version, this.sessionKeyEncryptionAlgorithm, this.aeadAlgorithm]); - const modeInstance = await mode(algo, key); - this.sessionKey = await modeInstance.decrypt(this.encrypted, this.iv, adata); - } else if (this.encrypted !== null) { - const decrypted = await mod.mode.cfb.decrypt(algo, key, this.encrypted, new Uint8Array(blockSize)); - - this.sessionKeyAlgorithm = enums.write(enums.symmetric, decrypted[0]); - this.sessionKey = decrypted.subarray(1, decrypted.length); - } else { - this.sessionKey = key; - } - } - - /** - * Encrypts the session key with the given passphrase - * @param {String} passphrase - The passphrase in string form - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if encryption was not successful - * @async - */ - async encrypt(passphrase, config = defaultConfig) { - const algo = this.sessionKeyEncryptionAlgorithm !== null ? - this.sessionKeyEncryptionAlgorithm : - this.sessionKeyAlgorithm; - - this.sessionKeyEncryptionAlgorithm = algo; - - this.s2k = new S2K(config); - this.s2k.salt = await mod.random.getRandomBytes(8); - - const { blockSize, keySize } = mod.getCipher(algo); - const encryptionKey = await this.s2k.produceKey(passphrase, keySize); - - if (this.sessionKey === null) { - this.sessionKey = await mod.generateSessionKey(this.sessionKeyAlgorithm); - } - - if (this.version === 5) { - const mode = mod.getAEADMode(this.aeadAlgorithm); - this.iv = await mod.random.getRandomBytes(mode.ivLength); // generate new random IV - const associatedData = new Uint8Array([0xC0 | SymEncryptedSessionKeyPacket.tag, this.version, this.sessionKeyEncryptionAlgorithm, this.aeadAlgorithm]); - const modeInstance = await mode(algo, encryptionKey); - this.encrypted = await modeInstance.encrypt(this.sessionKey, this.iv, associatedData); - } else { - const toEncrypt = util.concatUint8Array([ - new Uint8Array([this.sessionKeyAlgorithm]), - this.sessionKey - ]); - this.encrypted = await mod.mode.cfb.encrypt(algo, encryptionKey, toEncrypt, new Uint8Array(blockSize), config); - } - } -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -/** - * Implementation of the Key Material Packet (Tag 5,6,7,14) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.5|RFC4480 5.5}: - * A key material packet contains all the information about a public or - * private key. There are four variants of this packet type, and two - * major versions. - * - * A Public-Key packet starts a series of packets that forms an OpenPGP - * key (sometimes called an OpenPGP certificate). - */ -class PublicKeyPacket { - static get tag() { - return enums.packet.publicKey; - } - - /** - * @param {Date} [date] - Creation date - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - constructor(date = new Date(), config = defaultConfig) { - /** - * Packet version - * @type {Integer} - */ - this.version = config.v5Keys ? 5 : 4; - /** - * Key creation date. - * @type {Date} - */ - this.created = util.normalizeDate(date); - /** - * Public key algorithm. - * @type {enums.publicKey} - */ - this.algorithm = null; - /** - * Algorithm specific public params - * @type {Object} - */ - this.publicParams = null; - /** - * Time until expiration in days (V3 only) - * @type {Integer} - */ - this.expirationTimeV3 = 0; - /** - * Fingerprint bytes - * @type {Uint8Array} - */ - this.fingerprint = null; - /** - * KeyID - * @type {module:type/keyid~KeyID} - */ - this.keyID = null; - } - - /** - * Create a PublicKeyPacket from a SecretKeyPacket - * @param {SecretKeyPacket} secretKeyPacket - key packet to convert - * @returns {PublicKeyPacket} public key packet - * @static - */ - static fromSecretKeyPacket(secretKeyPacket) { - const keyPacket = new PublicKeyPacket(); - const { version, created, algorithm, publicParams, keyID, fingerprint } = secretKeyPacket; - keyPacket.version = version; - keyPacket.created = created; - keyPacket.algorithm = algorithm; - keyPacket.publicParams = publicParams; - keyPacket.keyID = keyID; - keyPacket.fingerprint = fingerprint; - return keyPacket; - } - - /** - * Internal Parser for public keys as specified in {@link https://tools.ietf.org/html/rfc4880#section-5.5.2|RFC 4880 section 5.5.2 Public-Key Packet Formats} - * @param {Uint8Array} bytes - Input array to read the packet from - * @returns {Object} This object with attributes set by the parser - * @async - */ - async read(bytes) { - let pos = 0; - // A one-octet version number (3, 4 or 5). - this.version = bytes[pos++]; - - if (this.version === 4 || this.version === 5) { - // - A four-octet number denoting the time that the key was created. - this.created = util.readDate(bytes.subarray(pos, pos + 4)); - pos += 4; - - // - A one-octet number denoting the public-key algorithm of this key. - this.algorithm = bytes[pos++]; - - if (this.version === 5) { - // - A four-octet scalar octet count for the following key material. - pos += 4; - } - - // - A series of values comprising the key material. - try { - const { read, publicParams } = mod.parsePublicKeyParams(this.algorithm, bytes.subarray(pos)); - this.publicParams = publicParams; - pos += read; - } catch (err) { - throw new Error('Error reading MPIs'); - } - - // we set the fingerprint and keyID already to make it possible to put together the key packets directly in the Key constructor - await this.computeFingerprintAndKeyID(); - return pos; - } - throw new UnsupportedError(`Version ${this.version} of the key packet is unsupported.`); - } - - /** - * Creates an OpenPGP public key packet for the given key. - * @returns {Uint8Array} Bytes encoding the public key OpenPGP packet. - */ - write() { - const arr = []; - // Version - arr.push(new Uint8Array([this.version])); - arr.push(util.writeDate(this.created)); - // A one-octet number denoting the public-key algorithm of this key - arr.push(new Uint8Array([this.algorithm])); - - const params = mod.serializeParams(this.algorithm, this.publicParams); - if (this.version === 5) { - // A four-octet scalar octet count for the following key material - arr.push(util.writeNumber(params.length, 4)); - } - // Algorithm-specific params - arr.push(params); - return util.concatUint8Array(arr); - } - - /** - * Write packet in order to be hashed; either for a signature or a fingerprint - * @param {Integer} version - target version of signature or key - */ - writeForHash(version) { - const bytes = this.writePublicKey(); - - if (version === 5) { - return util.concatUint8Array([new Uint8Array([0x9A]), util.writeNumber(bytes.length, 4), bytes]); - } - return util.concatUint8Array([new Uint8Array([0x99]), util.writeNumber(bytes.length, 2), bytes]); - } - - /** - * Check whether secret-key data is available in decrypted form. Returns null for public keys. - * @returns {Boolean|null} - */ - isDecrypted() { - return null; - } - - /** - * Returns the creation time of the key - * @returns {Date} - */ - getCreationTime() { - return this.created; - } - - /** - * Return the key ID of the key - * @returns {module:type/keyid~KeyID} The 8-byte key ID - */ - getKeyID() { - return this.keyID; - } - - /** - * Computes and set the key ID and fingerprint of the key - * @async - */ - async computeFingerprintAndKeyID() { - await this.computeFingerprint(); - this.keyID = new KeyID(); - - if (this.version === 5) { - this.keyID.read(this.fingerprint.subarray(0, 8)); - } else if (this.version === 4) { - this.keyID.read(this.fingerprint.subarray(12, 20)); - } else { - throw new Error('Unsupported key version'); - } - } - - /** - * Computes and set the fingerprint of the key - */ - async computeFingerprint() { - const toHash = this.writeForHash(this.version); - - if (this.version === 5) { - this.fingerprint = await mod.hash.sha256(toHash); - } else if (this.version === 4) { - this.fingerprint = await mod.hash.sha1(toHash); - } else { - throw new Error('Unsupported key version'); - } - } - - /** - * Returns the fingerprint of the key, as an array of bytes - * @returns {Uint8Array} A Uint8Array containing the fingerprint - */ - getFingerprintBytes() { - return this.fingerprint; - } - - /** - * Calculates and returns the fingerprint of the key, as a string - * @returns {String} A string containing the fingerprint in lowercase hex - */ - getFingerprint() { - return util.uint8ArrayToHex(this.getFingerprintBytes()); - } - - /** - * Calculates whether two keys have the same fingerprint without actually calculating the fingerprint - * @returns {Boolean} Whether the two keys have the same version and public key data. - */ - hasSameFingerprintAs(other) { - return this.version === other.version && util.equalsUint8Array(this.writePublicKey(), other.writePublicKey()); - } - - /** - * Returns algorithm information - * @returns {Object} An object of the form {algorithm: String, bits:int, curve:String}. - */ - getAlgorithmInfo() { - const result = {}; - result.algorithm = enums.read(enums.publicKey, this.algorithm); - // RSA, DSA or ElGamal public modulo - const modulo = this.publicParams.n || this.publicParams.p; - if (modulo) { - result.bits = util.uint8ArrayBitLength(modulo); - } else { - result.curve = this.publicParams.oid.getName(); - } - return result; - } -} - -/** - * Alias of read() - * @see PublicKeyPacket#read - */ -PublicKeyPacket.prototype.readPublicKey = PublicKeyPacket.prototype.read; - -/** - * Alias of write() - * @see PublicKeyPacket#write - */ -PublicKeyPacket.prototype.writePublicKey = PublicKeyPacket.prototype.write; - -// GPG4Browsers - An OpenPGP implementation in javascript - -// A SE packet can contain the following packet types -const allowedPackets$3 = /*#__PURE__*/ util.constructAllowedPackets([ - LiteralDataPacket, - CompressedDataPacket, - OnePassSignaturePacket, - SignaturePacket -]); - -/** - * Implementation of the Symmetrically Encrypted Data Packet (Tag 9) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.7|RFC4880 5.7}: - * The Symmetrically Encrypted Data packet contains data encrypted with a - * symmetric-key algorithm. When it has been decrypted, it contains other - * packets (usually a literal data packet or compressed data packet, but in - * theory other Symmetrically Encrypted Data packets or sequences of packets - * that form whole OpenPGP messages). - */ -class SymmetricallyEncryptedDataPacket { - static get tag() { - return enums.packet.symmetricallyEncryptedData; - } - - constructor() { - /** - * Encrypted secret-key data - */ - this.encrypted = null; - /** - * Decrypted packets contained within. - * @type {PacketList} - */ - this.packets = null; - } - - read(bytes) { - this.encrypted = bytes; - } - - write() { - return this.encrypted; - } - - /** - * Decrypt the symmetrically-encrypted packet data - * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. - * @param {module:enums.symmetric} sessionKeyAlgorithm - Symmetric key algorithm to use - * @param {Uint8Array} key - The key of cipher blocksize length to be used - * @param {Object} [config] - Full configuration, defaults to openpgp.config - - * @throws {Error} if decryption was not successful - * @async - */ - async decrypt(sessionKeyAlgorithm, key, config = defaultConfig) { - // If MDC errors are not being ignored, all missing MDC packets in symmetrically encrypted data should throw an error - if (!config.allowUnauthenticatedMessages) { - throw new Error('Message is not authenticated.'); - } - - const { blockSize } = mod.getCipher(sessionKeyAlgorithm); - const encrypted = await readToEnd(clone(this.encrypted)); - const decrypted = await mod.mode.cfb.decrypt(sessionKeyAlgorithm, key, - encrypted.subarray(blockSize + 2), - encrypted.subarray(2, blockSize + 2) - ); - - this.packets = await PacketList.fromBinary(decrypted, allowedPackets$3, config); - } - - /** - * Encrypt the symmetrically-encrypted packet data - * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. - * @param {module:enums.symmetric} sessionKeyAlgorithm - Symmetric key algorithm to use - * @param {Uint8Array} key - The key of cipher blocksize length to be used - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if encryption was not successful - * @async - */ - async encrypt(sessionKeyAlgorithm, key, config = defaultConfig) { - const data = this.packets.write(); - const { blockSize } = mod.getCipher(sessionKeyAlgorithm); - - const prefix = await mod.getPrefixRandom(sessionKeyAlgorithm); - const FRE = await mod.mode.cfb.encrypt(sessionKeyAlgorithm, key, prefix, new Uint8Array(blockSize), config); - const ciphertext = await mod.mode.cfb.encrypt(sessionKeyAlgorithm, key, data, FRE.subarray(2), config); - this.encrypted = util.concat([FRE, ciphertext]); - } -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -/** - * Implementation of the strange "Marker packet" (Tag 10) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.8|RFC4880 5.8}: - * An experimental version of PGP used this packet as the Literal - * packet, but no released version of PGP generated Literal packets with this - * tag. With PGP 5.x, this packet has been reassigned and is reserved for use as - * the Marker packet. - * - * The body of this packet consists of: - * The three octets 0x50, 0x47, 0x50 (which spell "PGP" in UTF-8). - * - * Such a packet MUST be ignored when received. It may be placed at the - * beginning of a message that uses features not available in PGP - * version 2.6 in order to cause that version to report that newer - * software is necessary to process the message. - */ -class MarkerPacket { - static get tag() { - return enums.packet.marker; - } - - /** - * Parsing function for a marker data packet (tag 10). - * @param {Uint8Array} bytes - Payload of a tag 10 packet - * @returns {Boolean} whether the packet payload contains "PGP" - */ - read(bytes) { - if (bytes[0] === 0x50 && // P - bytes[1] === 0x47 && // G - bytes[2] === 0x50) { // P - return true; - } - return false; - } - - write() { - return new Uint8Array([0x50, 0x47, 0x50]); - } -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -/** - * A Public-Subkey packet (tag 14) has exactly the same format as a - * Public-Key packet, but denotes a subkey. One or more subkeys may be - * associated with a top-level key. By convention, the top-level key - * provides signature services, and the subkeys provide encryption - * services. - * @extends PublicKeyPacket - */ -class PublicSubkeyPacket extends PublicKeyPacket { - static get tag() { - return enums.packet.publicSubkey; - } - - /** - * @param {Date} [date] - Creation date - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - // eslint-disable-next-line no-useless-constructor - constructor(date, config) { - super(date, config); - } - - /** - * Create a PublicSubkeyPacket from a SecretSubkeyPacket - * @param {SecretSubkeyPacket} secretSubkeyPacket - subkey packet to convert - * @returns {SecretSubkeyPacket} public key packet - * @static - */ - static fromSecretSubkeyPacket(secretSubkeyPacket) { - const keyPacket = new PublicSubkeyPacket(); - const { version, created, algorithm, publicParams, keyID, fingerprint } = secretSubkeyPacket; - keyPacket.version = version; - keyPacket.created = created; - keyPacket.algorithm = algorithm; - keyPacket.publicParams = publicParams; - keyPacket.keyID = keyID; - keyPacket.fingerprint = fingerprint; - return keyPacket; - } -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -/** - * Implementation of the User Attribute Packet (Tag 17) - * - * The User Attribute packet is a variation of the User ID packet. It - * is capable of storing more types of data than the User ID packet, - * which is limited to text. Like the User ID packet, a User Attribute - * packet may be certified by the key owner ("self-signed") or any other - * key owner who cares to certify it. Except as noted, a User Attribute - * packet may be used anywhere that a User ID packet may be used. - * - * While User Attribute packets are not a required part of the OpenPGP - * standard, implementations SHOULD provide at least enough - * compatibility to properly handle a certification signature on the - * User Attribute packet. A simple way to do this is by treating the - * User Attribute packet as a User ID packet with opaque contents, but - * an implementation may use any method desired. - */ -class UserAttributePacket { - static get tag() { - return enums.packet.userAttribute; - } - - constructor() { - this.attributes = []; - } - - /** - * parsing function for a user attribute packet (tag 17). - * @param {Uint8Array} input - Payload of a tag 17 packet - */ - read(bytes) { - let i = 0; - while (i < bytes.length) { - const len = readSimpleLength(bytes.subarray(i, bytes.length)); - i += len.offset; - - this.attributes.push(util.uint8ArrayToString(bytes.subarray(i, i + len.len))); - i += len.len; - } - } - - /** - * Creates a binary representation of the user attribute packet - * @returns {Uint8Array} String representation. - */ - write() { - const arr = []; - for (let i = 0; i < this.attributes.length; i++) { - arr.push(writeSimpleLength(this.attributes[i].length)); - arr.push(util.stringToUint8Array(this.attributes[i])); - } - return util.concatUint8Array(arr); - } - - /** - * Compare for equality - * @param {UserAttributePacket} usrAttr - * @returns {Boolean} True if equal. - */ - equals(usrAttr) { - if (!usrAttr || !(usrAttr instanceof UserAttributePacket)) { - return false; - } - return this.attributes.every(function(attr, index) { - return attr === usrAttr.attributes[index]; - }); - } -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -/** - * A Secret-Key packet contains all the information that is found in a - * Public-Key packet, including the public-key material, but also - * includes the secret-key material after all the public-key fields. - * @extends PublicKeyPacket - */ -class SecretKeyPacket extends PublicKeyPacket { - static get tag() { - return enums.packet.secretKey; - } - - /** - * @param {Date} [date] - Creation date - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - constructor(date = new Date(), config = defaultConfig) { - super(date, config); - /** - * Secret-key data - */ - this.keyMaterial = null; - /** - * Indicates whether secret-key data is encrypted. `this.isEncrypted === false` means data is available in decrypted form. - */ - this.isEncrypted = null; - /** - * S2K usage - * @type {enums.symmetric} - */ - this.s2kUsage = 0; - /** - * S2K object - * @type {type/s2k} - */ - this.s2k = null; - /** - * Symmetric algorithm to encrypt the key with - * @type {enums.symmetric} - */ - this.symmetric = null; - /** - * AEAD algorithm to encrypt the key with (if AEAD protection is enabled) - * @type {enums.aead} - */ - this.aead = null; - /** - * Decrypted private parameters, referenced by name - * @type {Object} - */ - this.privateParams = null; - } - - // 5.5.3. Secret-Key Packet Formats - - /** - * Internal parser for private keys as specified in - * {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.5.3|RFC4880bis-04 section 5.5.3} - * @param {Uint8Array} bytes - Input string to read the packet from - * @async - */ - async read(bytes) { - // - A Public-Key or Public-Subkey packet, as described above. - let i = await this.readPublicKey(bytes); - - // - One octet indicating string-to-key usage conventions. Zero - // indicates that the secret-key data is not encrypted. 255 or 254 - // indicates that a string-to-key specifier is being given. Any - // other value is a symmetric-key encryption algorithm identifier. - this.s2kUsage = bytes[i++]; - - // - Only for a version 5 packet, a one-octet scalar octet count of - // the next 4 optional fields. - if (this.version === 5) { - i++; - } - - // - [Optional] If string-to-key usage octet was 255, 254, or 253, a - // one-octet symmetric encryption algorithm. - if (this.s2kUsage === 255 || this.s2kUsage === 254 || this.s2kUsage === 253) { - this.symmetric = bytes[i++]; - - // - [Optional] If string-to-key usage octet was 253, a one-octet - // AEAD algorithm. - if (this.s2kUsage === 253) { - this.aead = bytes[i++]; - } - - // - [Optional] If string-to-key usage octet was 255, 254, or 253, a - // string-to-key specifier. The length of the string-to-key - // specifier is implied by its type, as described above. - this.s2k = new S2K(); - i += this.s2k.read(bytes.subarray(i, bytes.length)); - - if (this.s2k.type === 'gnu-dummy') { - return; - } - } else if (this.s2kUsage) { - this.symmetric = this.s2kUsage; - } - - // - [Optional] If secret data is encrypted (string-to-key usage octet - // not zero), an Initial Vector (IV) of the same length as the - // cipher's block size. - if (this.s2kUsage) { - this.iv = bytes.subarray( - i, - i + mod.getCipher(this.symmetric).blockSize - ); - - i += this.iv.length; - } - - // - Only for a version 5 packet, a four-octet scalar octet count for - // the following key material. - if (this.version === 5) { - i += 4; - } - - // - Plain or encrypted multiprecision integers comprising the secret - // key data. These algorithm-specific fields are as described - // below. - this.keyMaterial = bytes.subarray(i); - this.isEncrypted = !!this.s2kUsage; - - if (!this.isEncrypted) { - const cleartext = this.keyMaterial.subarray(0, -2); - if (!util.equalsUint8Array(util.writeChecksum(cleartext), this.keyMaterial.subarray(-2))) { - throw new Error('Key checksum mismatch'); - } - try { - const { privateParams } = mod.parsePrivateKeyParams(this.algorithm, cleartext, this.publicParams); - this.privateParams = privateParams; - } catch (err) { - throw new Error('Error reading MPIs'); - } - } - } - - /** - * Creates an OpenPGP key packet for the given key. - * @returns {Uint8Array} A string of bytes containing the secret key OpenPGP packet. - */ - write() { - const arr = [this.writePublicKey()]; - - arr.push(new Uint8Array([this.s2kUsage])); - - const optionalFieldsArr = []; - // - [Optional] If string-to-key usage octet was 255, 254, or 253, a - // one- octet symmetric encryption algorithm. - if (this.s2kUsage === 255 || this.s2kUsage === 254 || this.s2kUsage === 253) { - optionalFieldsArr.push(this.symmetric); - - // - [Optional] If string-to-key usage octet was 253, a one-octet - // AEAD algorithm. - if (this.s2kUsage === 253) { - optionalFieldsArr.push(this.aead); - } - - // - [Optional] If string-to-key usage octet was 255, 254, or 253, a - // string-to-key specifier. The length of the string-to-key - // specifier is implied by its type, as described above. - optionalFieldsArr.push(...this.s2k.write()); - } - - // - [Optional] If secret data is encrypted (string-to-key usage octet - // not zero), an Initial Vector (IV) of the same length as the - // cipher's block size. - if (this.s2kUsage && this.s2k.type !== 'gnu-dummy') { - optionalFieldsArr.push(...this.iv); - } - - if (this.version === 5) { - arr.push(new Uint8Array([optionalFieldsArr.length])); - } - arr.push(new Uint8Array(optionalFieldsArr)); - - if (!this.isDummy()) { - if (!this.s2kUsage) { - this.keyMaterial = mod.serializeParams(this.algorithm, this.privateParams); - } - - if (this.version === 5) { - arr.push(util.writeNumber(this.keyMaterial.length, 4)); - } - arr.push(this.keyMaterial); - - if (!this.s2kUsage) { - arr.push(util.writeChecksum(this.keyMaterial)); - } - } - - return util.concatUint8Array(arr); - } - - /** - * Check whether secret-key data is available in decrypted form. - * Returns false for gnu-dummy keys and null for public keys. - * @returns {Boolean|null} - */ - isDecrypted() { - return this.isEncrypted === false; - } - - /** - * Check whether this is a gnu-dummy key - * @returns {Boolean} - */ - isDummy() { - return !!(this.s2k && this.s2k.type === 'gnu-dummy'); - } - - /** - * Remove private key material, converting the key to a dummy one. - * The resulting key cannot be used for signing/decrypting but can still verify signatures. - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - makeDummy(config = defaultConfig) { - if (this.isDummy()) { - return; - } - if (this.isDecrypted()) { - this.clearPrivateParams(); - } - this.isEncrypted = null; - this.keyMaterial = null; - this.s2k = new S2K(config); - this.s2k.algorithm = 0; - this.s2k.c = 0; - this.s2k.type = 'gnu-dummy'; - this.s2kUsage = 254; - this.symmetric = enums.symmetric.aes256; - } - - /** - * Encrypt the payload. By default, we use aes256 and iterated, salted string - * to key specifier. If the key is in a decrypted state (isEncrypted === false) - * and the passphrase is empty or undefined, the key will be set as not encrypted. - * This can be used to remove passphrase protection after calling decrypt(). - * @param {String} passphrase - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if encryption was not successful - * @async - */ - async encrypt(passphrase, config = defaultConfig) { - if (this.isDummy()) { - return; - } - - if (!this.isDecrypted()) { - throw new Error('Key packet is already encrypted'); - } - - if (this.isDecrypted() && !passphrase) { - this.s2kUsage = 0; - return; - } else if (!passphrase) { - throw new Error('The key must be decrypted before removing passphrase protection.'); - } - - this.s2k = new S2K(config); - this.s2k.salt = await mod.random.getRandomBytes(8); - const cleartext = mod.serializeParams(this.algorithm, this.privateParams); - this.symmetric = enums.symmetric.aes256; - const key = await produceEncryptionKey(this.s2k, passphrase, this.symmetric); - - const { blockSize } = mod.getCipher(this.symmetric); - this.iv = await mod.random.getRandomBytes(blockSize); - - if (config.aeadProtect) { - this.s2kUsage = 253; - this.aead = enums.aead.eax; - const mode = mod.getAEADMode(this.aead); - const modeInstance = await mode(this.symmetric, key); - this.keyMaterial = await modeInstance.encrypt(cleartext, this.iv.subarray(0, mode.ivLength), new Uint8Array()); - } else { - this.s2kUsage = 254; - this.keyMaterial = await mod.mode.cfb.encrypt(this.symmetric, key, util.concatUint8Array([ - cleartext, - await mod.hash.sha1(cleartext, config) - ]), this.iv, config); - } - } - - /** - * Decrypts the private key params which are needed to use the key. - * Successful decryption does not imply key integrity, call validate() to confirm that. - * {@link SecretKeyPacket.isDecrypted} should be false, as - * otherwise calls to this function will throw an error. - * @param {String} passphrase - The passphrase for this private key as string - * @throws {Error} if the key is already decrypted, or if decryption was not successful - * @async - */ - async decrypt(passphrase) { - if (this.isDummy()) { - return false; - } - - if (this.isDecrypted()) { - throw new Error('Key packet is already decrypted.'); - } - - let key; - if (this.s2kUsage === 254 || this.s2kUsage === 253) { - key = await produceEncryptionKey(this.s2k, passphrase, this.symmetric); - } else if (this.s2kUsage === 255) { - throw new Error('Encrypted private key is authenticated using an insecure two-byte hash'); - } else { - throw new Error('Private key is encrypted using an insecure S2K function: unsalted MD5'); - } - - let cleartext; - if (this.s2kUsage === 253) { - const mode = mod.getAEADMode(this.aead); - const modeInstance = await mode(this.symmetric, key); - try { - cleartext = await modeInstance.decrypt(this.keyMaterial, this.iv.subarray(0, mode.ivLength), new Uint8Array()); - } catch (err) { - if (err.message === 'Authentication tag mismatch') { - throw new Error('Incorrect key passphrase: ' + err.message); - } - throw err; - } - } else { - const cleartextWithHash = await mod.mode.cfb.decrypt(this.symmetric, key, this.keyMaterial, this.iv); - - cleartext = cleartextWithHash.subarray(0, -20); - const hash = await mod.hash.sha1(cleartext); - - if (!util.equalsUint8Array(hash, cleartextWithHash.subarray(-20))) { - throw new Error('Incorrect key passphrase'); - } - } - - try { - const { privateParams } = mod.parsePrivateKeyParams(this.algorithm, cleartext, this.publicParams); - this.privateParams = privateParams; - } catch (err) { - throw new Error('Error reading MPIs'); - } - this.isEncrypted = false; - this.keyMaterial = null; - this.s2kUsage = 0; - } - - /** - * Checks that the key parameters are consistent - * @throws {Error} if validation was not successful - * @async - */ - async validate() { - if (this.isDummy()) { - return; - } - - if (!this.isDecrypted()) { - throw new Error('Key is not decrypted'); - } - - let validParams; - try { - // this can throw if some parameters are undefined - validParams = await mod.validateParams(this.algorithm, this.publicParams, this.privateParams); - } catch (_) { - validParams = false; - } - if (!validParams) { - throw new Error('Key is invalid'); - } - } - - async generate(bits, curve) { - const { privateParams, publicParams } = await mod.generateParams(this.algorithm, bits, curve); - this.privateParams = privateParams; - this.publicParams = publicParams; - this.isEncrypted = false; - } - - /** - * Clear private key parameters - */ - clearPrivateParams() { - if (this.isDummy()) { - return; - } - - Object.keys(this.privateParams).forEach(name => { - const param = this.privateParams[name]; - param.fill(0); - delete this.privateParams[name]; - }); - this.privateParams = null; - this.isEncrypted = true; - } -} - -async function produceEncryptionKey(s2k, passphrase, algorithm) { - const { keySize } = mod.getCipher(algorithm); - return s2k.produceKey(passphrase, keySize); -} - -var emailAddresses = createCommonjsModule(function (module) { -// email-addresses.js - RFC 5322 email address parser -// v 3.1.0 -// -// http://tools.ietf.org/html/rfc5322 -// -// This library does not validate email addresses. -// emailAddresses attempts to parse addresses using the (fairly liberal) -// grammar specified in RFC 5322. -// -// email-addresses returns { -// ast: , -// addresses: [{ -// node: , -// name: , -// address: , -// local: , -// domain: -// }, ...] -// } -// -// emailAddresses.parseOneAddress and emailAddresses.parseAddressList -// work as you might expect. Try it out. -// -// Many thanks to Dominic Sayers and his documentation on the is_email function, -// http://code.google.com/p/isemail/ , which helped greatly in writing this parser. - -(function (global) { - -function parse5322(opts) { - - // tokenizing functions - - function inStr() { return pos < len; } - function curTok() { return parseString[pos]; } - function getPos() { return pos; } - function setPos(i) { pos = i; } - function nextTok() { pos += 1; } - function initialize() { - pos = 0; - len = parseString.length; - } - - // parser helper functions - - function o(name, value) { - return { - name: name, - tokens: value || "", - semantic: value || "", - children: [] - }; - } - - function wrap(name, ast) { - var n; - if (ast === null) { return null; } - n = o(name); - n.tokens = ast.tokens; - n.semantic = ast.semantic; - n.children.push(ast); - return n; - } - - function add(parent, child) { - if (child !== null) { - parent.tokens += child.tokens; - parent.semantic += child.semantic; - } - parent.children.push(child); - return parent; - } - - function compareToken(fxnCompare) { - var tok; - if (!inStr()) { return null; } - tok = curTok(); - if (fxnCompare(tok)) { - nextTok(); - return o('token', tok); - } - return null; - } - - function literal(lit) { - return function literalFunc() { - return wrap('literal', compareToken(function (tok) { - return tok === lit; - })); - }; - } - - function and() { - var args = arguments; - return function andFunc() { - var i, s, result, start; - start = getPos(); - s = o('and'); - for (i = 0; i < args.length; i += 1) { - result = args[i](); - if (result === null) { - setPos(start); - return null; - } - add(s, result); - } - return s; - }; - } - - function or() { - var args = arguments; - return function orFunc() { - var i, result, start; - start = getPos(); - for (i = 0; i < args.length; i += 1) { - result = args[i](); - if (result !== null) { - return result; - } - setPos(start); - } - return null; - }; - } - - function opt(prod) { - return function optFunc() { - var result, start; - start = getPos(); - result = prod(); - if (result !== null) { - return result; - } - else { - setPos(start); - return o('opt'); - } - }; - } - - function invis(prod) { - return function invisFunc() { - var result = prod(); - if (result !== null) { - result.semantic = ""; - } - return result; - }; - } - - function colwsp(prod) { - return function collapseSemanticWhitespace() { - var result = prod(); - if (result !== null && result.semantic.length > 0) { - result.semantic = " "; - } - return result; - }; - } - - function star(prod, minimum) { - return function starFunc() { - var s, result, count, start, min; - start = getPos(); - s = o('star'); - count = 0; - min = minimum === undefined ? 0 : minimum; - while ((result = prod()) !== null) { - count = count + 1; - add(s, result); - } - if (count >= min) { - return s; - } - else { - setPos(start); - return null; - } - }; - } - - // One expects names to get normalized like this: - // " First Last " -> "First Last" - // "First Last" -> "First Last" - // "First Last" -> "First Last" - function collapseWhitespace(s) { - return s.replace(/([ \t]|\r\n)+/g, ' ').replace(/^\s*/, '').replace(/\s*$/, ''); - } - - // UTF-8 pseudo-production (RFC 6532) - // RFC 6532 extends RFC 5322 productions to include UTF-8 - // using the following productions: - // UTF8-non-ascii = UTF8-2 / UTF8-3 / UTF8-4 - // UTF8-2 = - // UTF8-3 = - // UTF8-4 = - // - // For reference, the extended RFC 5322 productions are: - // VCHAR =/ UTF8-non-ascii - // ctext =/ UTF8-non-ascii - // atext =/ UTF8-non-ascii - // qtext =/ UTF8-non-ascii - // dtext =/ UTF8-non-ascii - function isUTF8NonAscii(tok) { - // In JavaScript, we just deal directly with Unicode code points, - // so we aren't checking individual bytes for UTF-8 encoding. - // Just check that the character is non-ascii. - return tok.charCodeAt(0) >= 128; - } - - - // common productions (RFC 5234) - // http://tools.ietf.org/html/rfc5234 - // B.1. Core Rules - - // CR = %x0D - // ; carriage return - function cr() { return wrap('cr', literal('\r')()); } - - // CRLF = CR LF - // ; Internet standard newline - function crlf() { return wrap('crlf', and(cr, lf)()); } - - // DQUOTE = %x22 - // ; " (Double Quote) - function dquote() { return wrap('dquote', literal('"')()); } - - // HTAB = %x09 - // ; horizontal tab - function htab() { return wrap('htab', literal('\t')()); } - - // LF = %x0A - // ; linefeed - function lf() { return wrap('lf', literal('\n')()); } - - // SP = %x20 - function sp() { return wrap('sp', literal(' ')()); } - - // VCHAR = %x21-7E - // ; visible (printing) characters - function vchar() { - return wrap('vchar', compareToken(function vcharFunc(tok) { - var code = tok.charCodeAt(0); - var accept = (0x21 <= code && code <= 0x7E); - if (opts.rfc6532) { - accept = accept || isUTF8NonAscii(tok); - } - return accept; - })); - } - - // WSP = SP / HTAB - // ; white space - function wsp() { return wrap('wsp', or(sp, htab)()); } - - - // email productions (RFC 5322) - // http://tools.ietf.org/html/rfc5322 - // 3.2.1. Quoted characters - - // quoted-pair = ("\" (VCHAR / WSP)) / obs-qp - function quotedPair() { - var qp = wrap('quoted-pair', - or( - and(literal('\\'), or(vchar, wsp)), - obsQP - )()); - if (qp === null) { return null; } - // a quoted pair will be two characters, and the "\" character - // should be semantically "invisible" (RFC 5322 3.2.1) - qp.semantic = qp.semantic[1]; - return qp; - } - - // 3.2.2. Folding White Space and Comments - - // FWS = ([*WSP CRLF] 1*WSP) / obs-FWS - function fws() { - return wrap('fws', or( - obsFws, - and( - opt(and( - star(wsp), - invis(crlf) - )), - star(wsp, 1) - ) - )()); - } - - // ctext = %d33-39 / ; Printable US-ASCII - // %d42-91 / ; characters not including - // %d93-126 / ; "(", ")", or "\" - // obs-ctext - function ctext() { - return wrap('ctext', or( - function ctextFunc1() { - return compareToken(function ctextFunc2(tok) { - var code = tok.charCodeAt(0); - var accept = - (33 <= code && code <= 39) || - (42 <= code && code <= 91) || - (93 <= code && code <= 126); - if (opts.rfc6532) { - accept = accept || isUTF8NonAscii(tok); - } - return accept; - }); - }, - obsCtext - )()); - } - - // ccontent = ctext / quoted-pair / comment - function ccontent() { - return wrap('ccontent', or(ctext, quotedPair, comment)()); - } - - // comment = "(" *([FWS] ccontent) [FWS] ")" - function comment() { - return wrap('comment', and( - literal('('), - star(and(opt(fws), ccontent)), - opt(fws), - literal(')') - )()); - } - - // CFWS = (1*([FWS] comment) [FWS]) / FWS - function cfws() { - return wrap('cfws', or( - and( - star( - and(opt(fws), comment), - 1 - ), - opt(fws) - ), - fws - )()); - } - - // 3.2.3. Atom - - //atext = ALPHA / DIGIT / ; Printable US-ASCII - // "!" / "#" / ; characters not including - // "$" / "%" / ; specials. Used for atoms. - // "&" / "'" / - // "*" / "+" / - // "-" / "/" / - // "=" / "?" / - // "^" / "_" / - // "`" / "{" / - // "|" / "}" / - // "~" - function atext() { - return wrap('atext', compareToken(function atextFunc(tok) { - var accept = - ('a' <= tok && tok <= 'z') || - ('A' <= tok && tok <= 'Z') || - ('0' <= tok && tok <= '9') || - (['!', '#', '$', '%', '&', '\'', '*', '+', '-', '/', - '=', '?', '^', '_', '`', '{', '|', '}', '~'].indexOf(tok) >= 0); - if (opts.rfc6532) { - accept = accept || isUTF8NonAscii(tok); - } - return accept; - })); - } - - // atom = [CFWS] 1*atext [CFWS] - function atom() { - return wrap('atom', and(colwsp(opt(cfws)), star(atext, 1), colwsp(opt(cfws)))()); - } - - // dot-atom-text = 1*atext *("." 1*atext) - function dotAtomText() { - var s, maybeText; - s = wrap('dot-atom-text', star(atext, 1)()); - if (s === null) { return s; } - maybeText = star(and(literal('.'), star(atext, 1)))(); - if (maybeText !== null) { - add(s, maybeText); - } - return s; - } - - // dot-atom = [CFWS] dot-atom-text [CFWS] - function dotAtom() { - return wrap('dot-atom', and(invis(opt(cfws)), dotAtomText, invis(opt(cfws)))()); - } - - // 3.2.4. Quoted Strings - - // qtext = %d33 / ; Printable US-ASCII - // %d35-91 / ; characters not including - // %d93-126 / ; "\" or the quote character - // obs-qtext - function qtext() { - return wrap('qtext', or( - function qtextFunc1() { - return compareToken(function qtextFunc2(tok) { - var code = tok.charCodeAt(0); - var accept = - (33 === code) || - (35 <= code && code <= 91) || - (93 <= code && code <= 126); - if (opts.rfc6532) { - accept = accept || isUTF8NonAscii(tok); - } - return accept; - }); - }, - obsQtext - )()); - } - - // qcontent = qtext / quoted-pair - function qcontent() { - return wrap('qcontent', or(qtext, quotedPair)()); - } - - // quoted-string = [CFWS] - // DQUOTE *([FWS] qcontent) [FWS] DQUOTE - // [CFWS] - function quotedString() { - return wrap('quoted-string', and( - invis(opt(cfws)), - invis(dquote), star(and(opt(colwsp(fws)), qcontent)), opt(invis(fws)), invis(dquote), - invis(opt(cfws)) - )()); - } - - // 3.2.5 Miscellaneous Tokens - - // word = atom / quoted-string - function word() { - return wrap('word', or(atom, quotedString)()); - } - - // phrase = 1*word / obs-phrase - function phrase() { - return wrap('phrase', or(obsPhrase, star(word, 1))()); - } - - // 3.4. Address Specification - // address = mailbox / group - function address() { - return wrap('address', or(mailbox, group)()); - } - - // mailbox = name-addr / addr-spec - function mailbox() { - return wrap('mailbox', or(nameAddr, addrSpec)()); - } - - // name-addr = [display-name] angle-addr - function nameAddr() { - return wrap('name-addr', and(opt(displayName), angleAddr)()); - } - - // angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / - // obs-angle-addr - function angleAddr() { - return wrap('angle-addr', or( - and( - invis(opt(cfws)), - literal('<'), - addrSpec, - literal('>'), - invis(opt(cfws)) - ), - obsAngleAddr - )()); - } - - // group = display-name ":" [group-list] ";" [CFWS] - function group() { - return wrap('group', and( - displayName, - literal(':'), - opt(groupList), - literal(';'), - invis(opt(cfws)) - )()); - } - - // display-name = phrase - function displayName() { - return wrap('display-name', function phraseFixedSemantic() { - var result = phrase(); - if (result !== null) { - result.semantic = collapseWhitespace(result.semantic); - } - return result; - }()); - } - - // mailbox-list = (mailbox *("," mailbox)) / obs-mbox-list - function mailboxList() { - return wrap('mailbox-list', or( - and( - mailbox, - star(and(literal(','), mailbox)) - ), - obsMboxList - )()); - } - - // address-list = (address *("," address)) / obs-addr-list - function addressList() { - return wrap('address-list', or( - and( - address, - star(and(literal(','), address)) - ), - obsAddrList - )()); - } - - // group-list = mailbox-list / CFWS / obs-group-list - function groupList() { - return wrap('group-list', or( - mailboxList, - invis(cfws), - obsGroupList - )()); - } - - // 3.4.1 Addr-Spec Specification - - // local-part = dot-atom / quoted-string / obs-local-part - function localPart() { - // note: quoted-string, dotAtom are proper subsets of obs-local-part - // so we really just have to look for obsLocalPart, if we don't care about the exact parse tree - return wrap('local-part', or(obsLocalPart, dotAtom, quotedString)()); - } - - // dtext = %d33-90 / ; Printable US-ASCII - // %d94-126 / ; characters not including - // obs-dtext ; "[", "]", or "\" - function dtext() { - return wrap('dtext', or( - function dtextFunc1() { - return compareToken(function dtextFunc2(tok) { - var code = tok.charCodeAt(0); - var accept = - (33 <= code && code <= 90) || - (94 <= code && code <= 126); - if (opts.rfc6532) { - accept = accept || isUTF8NonAscii(tok); - } - return accept; - }); - }, - obsDtext - )() - ); - } - - // domain-literal = [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS] - function domainLiteral() { - return wrap('domain-literal', and( - invis(opt(cfws)), - literal('['), - star(and(opt(fws), dtext)), - opt(fws), - literal(']'), - invis(opt(cfws)) - )()); - } - - // domain = dot-atom / domain-literal / obs-domain - function domain() { - return wrap('domain', function domainCheckTLD() { - var result = or(obsDomain, dotAtom, domainLiteral)(); - if (opts.rejectTLD) { - if (result && result.semantic && result.semantic.indexOf('.') < 0) { - return null; - } - } - // strip all whitespace from domains - if (result) { - result.semantic = result.semantic.replace(/\s+/g, ''); - } - return result; - }()); - } - - // addr-spec = local-part "@" domain - function addrSpec() { - return wrap('addr-spec', and( - localPart, literal('@'), domain - )()); - } - - // 3.6.2 Originator Fields - // Below we only parse the field body, not the name of the field - // like "From:", "Sender:", or "Reply-To:". Other libraries that - // parse email headers can parse those and defer to these productions - // for the "RFC 5322" part. - - // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields - // from = "From:" (mailbox-list / address-list) CRLF - function fromSpec() { - return wrap('from', or( - mailboxList, - addressList - )()); - } - - // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields - // sender = "Sender:" (mailbox / address) CRLF - function senderSpec() { - return wrap('sender', or( - mailbox, - address - )()); - } - - // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields - // reply-to = "Reply-To:" address-list CRLF - function replyToSpec() { - return wrap('reply-to', addressList()); - } - - // 4.1. Miscellaneous Obsolete Tokens - - // obs-NO-WS-CTL = %d1-8 / ; US-ASCII control - // %d11 / ; characters that do not - // %d12 / ; include the carriage - // %d14-31 / ; return, line feed, and - // %d127 ; white space characters - function obsNoWsCtl() { - return opts.strict ? null : wrap('obs-NO-WS-CTL', compareToken(function (tok) { - var code = tok.charCodeAt(0); - return ((1 <= code && code <= 8) || - (11 === code || 12 === code) || - (14 <= code && code <= 31) || - (127 === code)); - })); - } - - // obs-ctext = obs-NO-WS-CTL - function obsCtext() { return opts.strict ? null : wrap('obs-ctext', obsNoWsCtl()); } - - // obs-qtext = obs-NO-WS-CTL - function obsQtext() { return opts.strict ? null : wrap('obs-qtext', obsNoWsCtl()); } - - // obs-qp = "\" (%d0 / obs-NO-WS-CTL / LF / CR) - function obsQP() { - return opts.strict ? null : wrap('obs-qp', and( - literal('\\'), - or(literal('\0'), obsNoWsCtl, lf, cr) - )()); - } - - // obs-phrase = word *(word / "." / CFWS) - function obsPhrase() { - if (opts.strict ) return null; - return opts.atInDisplayName ? wrap('obs-phrase', and( - word, - star(or(word, literal('.'), literal('@'), colwsp(cfws))) - )()) : - wrap('obs-phrase', and( - word, - star(or(word, literal('.'), colwsp(cfws))) - )()); - } - - // 4.2. Obsolete Folding White Space - - // NOTE: read the errata http://www.rfc-editor.org/errata_search.php?rfc=5322&eid=1908 - // obs-FWS = 1*([CRLF] WSP) - function obsFws() { - return opts.strict ? null : wrap('obs-FWS', star( - and(invis(opt(crlf)), wsp), - 1 - )()); - } - - // 4.4. Obsolete Addressing - - // obs-angle-addr = [CFWS] "<" obs-route addr-spec ">" [CFWS] - function obsAngleAddr() { - return opts.strict ? null : wrap('obs-angle-addr', and( - invis(opt(cfws)), - literal('<'), - obsRoute, - addrSpec, - literal('>'), - invis(opt(cfws)) - )()); - } - - // obs-route = obs-domain-list ":" - function obsRoute() { - return opts.strict ? null : wrap('obs-route', and( - obsDomainList, - literal(':') - )()); - } - - // obs-domain-list = *(CFWS / ",") "@" domain - // *("," [CFWS] ["@" domain]) - function obsDomainList() { - return opts.strict ? null : wrap('obs-domain-list', and( - star(or(invis(cfws), literal(','))), - literal('@'), - domain, - star(and( - literal(','), - invis(opt(cfws)), - opt(and(literal('@'), domain)) - )) - )()); - } - - // obs-mbox-list = *([CFWS] ",") mailbox *("," [mailbox / CFWS]) - function obsMboxList() { - return opts.strict ? null : wrap('obs-mbox-list', and( - star(and( - invis(opt(cfws)), - literal(',') - )), - mailbox, - star(and( - literal(','), - opt(and( - mailbox, - invis(cfws) - )) - )) - )()); - } - - // obs-addr-list = *([CFWS] ",") address *("," [address / CFWS]) - function obsAddrList() { - return opts.strict ? null : wrap('obs-addr-list', and( - star(and( - invis(opt(cfws)), - literal(',') - )), - address, - star(and( - literal(','), - opt(and( - address, - invis(cfws) - )) - )) - )()); - } - - // obs-group-list = 1*([CFWS] ",") [CFWS] - function obsGroupList() { - return opts.strict ? null : wrap('obs-group-list', and( - star(and( - invis(opt(cfws)), - literal(',') - ), 1), - invis(opt(cfws)) - )()); - } - - // obs-local-part = word *("." word) - function obsLocalPart() { - return opts.strict ? null : wrap('obs-local-part', and(word, star(and(literal('.'), word)))()); - } - - // obs-domain = atom *("." atom) - function obsDomain() { - return opts.strict ? null : wrap('obs-domain', and(atom, star(and(literal('.'), atom)))()); - } - - // obs-dtext = obs-NO-WS-CTL / quoted-pair - function obsDtext() { - return opts.strict ? null : wrap('obs-dtext', or(obsNoWsCtl, quotedPair)()); - } - - ///////////////////////////////////////////////////// - - // ast analysis - - function findNode(name, root) { - var i, stack, node; - if (root === null || root === undefined) { return null; } - stack = [root]; - while (stack.length > 0) { - node = stack.pop(); - if (node.name === name) { - return node; - } - for (i = node.children.length - 1; i >= 0; i -= 1) { - stack.push(node.children[i]); - } - } - return null; - } - - function findAllNodes(name, root) { - var i, stack, node, result; - if (root === null || root === undefined) { return null; } - stack = [root]; - result = []; - while (stack.length > 0) { - node = stack.pop(); - if (node.name === name) { - result.push(node); - } - for (i = node.children.length - 1; i >= 0; i -= 1) { - stack.push(node.children[i]); - } - } - return result; - } - - function findAllNodesNoChildren(names, root) { - var i, stack, node, result, namesLookup; - if (root === null || root === undefined) { return null; } - stack = [root]; - result = []; - namesLookup = {}; - for (i = 0; i < names.length; i += 1) { - namesLookup[names[i]] = true; - } - - while (stack.length > 0) { - node = stack.pop(); - if (node.name in namesLookup) { - result.push(node); - // don't look at children (hence findAllNodesNoChildren) - } else { - for (i = node.children.length - 1; i >= 0; i -= 1) { - stack.push(node.children[i]); - } - } - } - return result; - } - - function giveResult(ast) { - var addresses, groupsAndMailboxes, i, groupOrMailbox, result; - if (ast === null) { - return null; - } - addresses = []; - - // An address is a 'group' (i.e. a list of mailboxes) or a 'mailbox'. - groupsAndMailboxes = findAllNodesNoChildren(['group', 'mailbox'], ast); - for (i = 0; i < groupsAndMailboxes.length; i += 1) { - groupOrMailbox = groupsAndMailboxes[i]; - if (groupOrMailbox.name === 'group') { - addresses.push(giveResultGroup(groupOrMailbox)); - } else if (groupOrMailbox.name === 'mailbox') { - addresses.push(giveResultMailbox(groupOrMailbox)); - } - } - - result = { - ast: ast, - addresses: addresses, - }; - if (opts.simple) { - result = simplifyResult(result); - } - if (opts.oneResult) { - return oneResult(result); - } - if (opts.simple) { - return result && result.addresses; - } else { - return result; - } - } - - function giveResultGroup(group) { - var i; - var groupName = findNode('display-name', group); - var groupResultMailboxes = []; - var mailboxes = findAllNodesNoChildren(['mailbox'], group); - for (i = 0; i < mailboxes.length; i += 1) { - groupResultMailboxes.push(giveResultMailbox(mailboxes[i])); - } - return { - node: group, - parts: { - name: groupName, - }, - type: group.name, // 'group' - name: grabSemantic(groupName), - addresses: groupResultMailboxes, - }; - } - - function giveResultMailbox(mailbox) { - var name = findNode('display-name', mailbox); - var aspec = findNode('addr-spec', mailbox); - var cfws = findAllNodes('cfws', mailbox); - var comments = findAllNodesNoChildren(['comment'], mailbox); - - - var local = findNode('local-part', aspec); - var domain = findNode('domain', aspec); - return { - node: mailbox, - parts: { - name: name, - address: aspec, - local: local, - domain: domain, - comments: cfws - }, - type: mailbox.name, // 'mailbox' - name: grabSemantic(name), - address: grabSemantic(aspec), - local: grabSemantic(local), - domain: grabSemantic(domain), - comments: concatComments(comments), - groupName: grabSemantic(mailbox.groupName), - }; - } - - function grabSemantic(n) { - return n !== null && n !== undefined ? n.semantic : null; - } - - function simplifyResult(result) { - var i; - if (result && result.addresses) { - for (i = 0; i < result.addresses.length; i += 1) { - delete result.addresses[i].node; - } - } - return result; - } - - function concatComments(comments) { - var result = ''; - if (comments) { - for (var i = 0; i < comments.length; i += 1) { - result += grabSemantic(comments[i]); - } - } - return result; - } - - function oneResult(result) { - if (!result) { return null; } - if (!opts.partial && result.addresses.length > 1) { return null; } - return result.addresses && result.addresses[0]; - } - - ///////////////////////////////////////////////////// - - var parseString, pos, len, parsed, startProduction; - - opts = handleOpts(opts, {}); - if (opts === null) { return null; } - - parseString = opts.input; - - startProduction = { - 'address': address, - 'address-list': addressList, - 'angle-addr': angleAddr, - 'from': fromSpec, - 'group': group, - 'mailbox': mailbox, - 'mailbox-list': mailboxList, - 'reply-to': replyToSpec, - 'sender': senderSpec, - }[opts.startAt] || addressList; - - if (!opts.strict) { - initialize(); - opts.strict = true; - parsed = startProduction(parseString); - if (opts.partial || !inStr()) { - return giveResult(parsed); - } - opts.strict = false; - } - - initialize(); - parsed = startProduction(parseString); - if (!opts.partial && inStr()) { return null; } - return giveResult(parsed); -} - -function parseOneAddressSimple(opts) { - return parse5322(handleOpts(opts, { - oneResult: true, - rfc6532: true, - simple: true, - startAt: 'address-list', - })); -} - -function parseAddressListSimple(opts) { - return parse5322(handleOpts(opts, { - rfc6532: true, - simple: true, - startAt: 'address-list', - })); -} - -function parseFromSimple(opts) { - return parse5322(handleOpts(opts, { - rfc6532: true, - simple: true, - startAt: 'from', - })); -} - -function parseSenderSimple(opts) { - return parse5322(handleOpts(opts, { - oneResult: true, - rfc6532: true, - simple: true, - startAt: 'sender', - })); -} - -function parseReplyToSimple(opts) { - return parse5322(handleOpts(opts, { - rfc6532: true, - simple: true, - startAt: 'reply-to', - })); -} - -function handleOpts(opts, defs) { - function isString(str) { - return Object.prototype.toString.call(str) === '[object String]'; - } - - function isObject(o) { - return o === Object(o); - } - - function isNullUndef(o) { - return o === null || o === undefined; - } - - var defaults, o; - - if (isString(opts)) { - opts = { input: opts }; - } else if (!isObject(opts)) { - return null; - } - - if (!isString(opts.input)) { return null; } - if (!defs) { return null; } - - defaults = { - oneResult: false, - partial: false, - rejectTLD: false, - rfc6532: false, - simple: false, - startAt: 'address-list', - strict: false, - atInDisplayName: false - }; - - for (o in defaults) { - if (isNullUndef(opts[o])) { - opts[o] = !isNullUndef(defs[o]) ? defs[o] : defaults[o]; - } - } - return opts; -} - -parse5322.parseOneAddress = parseOneAddressSimple; -parse5322.parseAddressList = parseAddressListSimple; -parse5322.parseFrom = parseFromSimple; -parse5322.parseSender = parseSenderSimple; -parse5322.parseReplyTo = parseReplyToSimple; - -{ - module.exports = parse5322; -} - -}()); -}); - -// GPG4Browsers - An OpenPGP implementation in javascript - -/** - * Implementation of the User ID Packet (Tag 13) - * - * A User ID packet consists of UTF-8 text that is intended to represent - * the name and email address of the key holder. By convention, it - * includes an RFC 2822 [RFC2822] mail name-addr, but there are no - * restrictions on its content. The packet length in the header - * specifies the length of the User ID. - */ -class UserIDPacket { - static get tag() { - return enums.packet.userID; - } - - constructor() { - /** A string containing the user id. Usually in the form - * John Doe - * @type {String} - */ - this.userID = ''; - - this.name = ''; - this.email = ''; - this.comment = ''; - } - - /** - * Create UserIDPacket instance from object - * @param {Object} userID - Object specifying userID name, email and comment - * @returns {UserIDPacket} - * @static - */ - static fromObject(userID) { - if (util.isString(userID) || - (userID.name && !util.isString(userID.name)) || - (userID.email && !util.isEmailAddress(userID.email)) || - (userID.comment && !util.isString(userID.comment))) { - throw new Error('Invalid user ID format'); - } - const packet = new UserIDPacket(); - Object.assign(packet, userID); - const components = []; - if (packet.name) components.push(packet.name); - if (packet.comment) components.push(`(${packet.comment})`); - if (packet.email) components.push(`<${packet.email}>`); - packet.userID = components.join(' '); - return packet; - } - - /** - * Parsing function for a user id packet (tag 13). - * @param {Uint8Array} input - Payload of a tag 13 packet - */ - read(bytes, config = defaultConfig) { - const userID = util.decodeUTF8(bytes); - if (userID.length > config.maxUserIDLength) { - throw new Error('User ID string is too long'); - } - try { - const { name, address: email, comments } = emailAddresses.parseOneAddress({ input: userID, atInDisplayName: true }); - this.comment = comments.replace(/^\(|\)$/g, ''); - this.name = name; - this.email = email; - } catch (e) {} - this.userID = userID; - } - - /** - * Creates a binary representation of the user id packet - * @returns {Uint8Array} Binary representation. - */ - write() { - return util.encodeUTF8(this.userID); - } - - equals(otherUserID) { - return otherUserID && otherUserID.userID === this.userID; - } -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -/** - * A Secret-Subkey packet (tag 7) is the subkey analog of the Secret - * Key packet and has exactly the same format. - * @extends SecretKeyPacket - */ -class SecretSubkeyPacket extends SecretKeyPacket { - static get tag() { - return enums.packet.secretSubkey; - } - - /** - * @param {Date} [date] - Creation date - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - constructor(date = new Date(), config = defaultConfig) { - super(date, config); - } -} - -/** - * Implementation of the Trust Packet (Tag 12) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.10|RFC4880 5.10}: - * The Trust packet is used only within keyrings and is not normally - * exported. Trust packets contain data that record the user's - * specifications of which key holders are trustworthy introducers, - * along with other information that implementing software uses for - * trust information. The format of Trust packets is defined by a given - * implementation. - * - * Trust packets SHOULD NOT be emitted to output streams that are - * transferred to other users, and they SHOULD be ignored on any input - * other than local keyring files. - */ -class TrustPacket { - static get tag() { - return enums.packet.trust; - } - - /** - * Parsing function for a trust packet (tag 12). - * Currently not implemented as we ignore trust packets - */ - read() { - throw new UnsupportedError('Trust packets are not supported'); - } - - write() { - throw new UnsupportedError('Trust packets are not supported'); - } -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -// A Signature can contain the following packets -const allowedPackets$4 = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); - -/** - * Class that represents an OpenPGP signature. - */ -class Signature { - /** - * @param {PacketList} packetlist - The signature packets - */ - constructor(packetlist) { - this.packets = packetlist || new PacketList(); - } - - /** - * Returns binary encoded signature - * @returns {ReadableStream} Binary signature. - */ - write() { - return this.packets.write(); - } - - /** - * Returns ASCII armored text of signature - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {ReadableStream} ASCII armor. - */ - armor(config = defaultConfig) { - return armor(enums.armor.signature, this.write(), undefined, undefined, undefined, config); - } - - /** - * Returns an array of KeyIDs of all of the issuers who created this signature - * @returns {Array} The Key IDs of the signing keys - */ - getSigningKeyIDs() { - return this.packets.map(packet => packet.issuerKeyID); - } -} - -/** - * reads an (optionally armored) OpenPGP signature and returns a signature object - * @param {Object} options - * @param {String} [options.armoredSignature] - Armored signature to be parsed - * @param {Uint8Array} [options.binarySignature] - Binary signature to be parsed - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} New signature object. - * @async - * @static - */ -async function readSignature({ armoredSignature, binarySignature, config, ...rest }) { - config = { ...defaultConfig, ...config }; - let input = armoredSignature || binarySignature; - if (!input) { - throw new Error('readSignature: must pass options object containing `armoredSignature` or `binarySignature`'); - } - if (armoredSignature && !util.isString(armoredSignature)) { - throw new Error('readSignature: options.armoredSignature must be a string'); - } - if (binarySignature && !util.isUint8Array(binarySignature)) { - throw new Error('readSignature: options.binarySignature must be a Uint8Array'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (armoredSignature) { - const { type, data } = await unarmor(input, config); - if (type !== enums.armor.signature) { - throw new Error('Armored text not of type signature'); - } - input = data; - } - const packetlist = await PacketList.fromBinary(input, allowedPackets$4, config); - return new Signature(packetlist); -} - -/** - * @fileoverview Provides helpers methods for key module - * @module key/helper - * @private - */ - -async function generateSecretSubkey(options, config) { - const secretSubkeyPacket = new SecretSubkeyPacket(options.date, config); - secretSubkeyPacket.packets = null; - secretSubkeyPacket.algorithm = enums.write(enums.publicKey, options.algorithm); - await secretSubkeyPacket.generate(options.rsaBits, options.curve); - await secretSubkeyPacket.computeFingerprintAndKeyID(); - return secretSubkeyPacket; -} - -async function generateSecretKey(options, config) { - const secretKeyPacket = new SecretKeyPacket(options.date, config); - secretKeyPacket.packets = null; - secretKeyPacket.algorithm = enums.write(enums.publicKey, options.algorithm); - await secretKeyPacket.generate(options.rsaBits, options.curve, options.config); - await secretKeyPacket.computeFingerprintAndKeyID(); - return secretKeyPacket; -} - -/** - * Returns the valid and non-expired signature that has the latest creation date, while ignoring signatures created in the future. - * @param {Array} signatures - List of signatures - * @param {PublicKeyPacket|PublicSubkeyPacket} publicKey - Public key packet to verify the signature - * @param {Date} date - Use the given date instead of the current time - * @param {Object} config - full configuration - * @returns {Promise} The latest valid signature. - * @async - */ -async function getLatestValidSignature(signatures, publicKey, signatureType, dataToVerify, date = new Date(), config) { - let latestValid; - let exception; - for (let i = signatures.length - 1; i >= 0; i--) { - try { - if ( - (!latestValid || signatures[i].created >= latestValid.created) - ) { - await signatures[i].verify(publicKey, signatureType, dataToVerify, date, undefined, config); - latestValid = signatures[i]; - } - } catch (e) { - exception = e; - } - } - if (!latestValid) { - throw util.wrapError( - `Could not find valid ${enums.read(enums.signature, signatureType)} signature in key ${publicKey.getKeyID().toHex()}` - .replace('certGeneric ', 'self-') - .replace(/([a-z])([A-Z])/g, (_, $1, $2) => $1 + ' ' + $2.toLowerCase()) - , exception); - } - return latestValid; -} - -function isDataExpired(keyPacket, signature, date = new Date()) { - const normDate = util.normalizeDate(date); - if (normDate !== null) { - const expirationTime = getKeyExpirationTime(keyPacket, signature); - return !(keyPacket.created <= normDate && normDate < expirationTime); - } - return false; -} - -/** - * Create Binding signature to the key according to the {@link https://tools.ietf.org/html/rfc4880#section-5.2.1} - * @param {SecretSubkeyPacket} subkey - Subkey key packet - * @param {SecretKeyPacket} primaryKey - Primary key packet - * @param {Object} options - * @param {Object} config - Full configuration - */ -async function createBindingSignature(subkey, primaryKey, options, config) { - const dataToSign = {}; - dataToSign.key = primaryKey; - dataToSign.bind = subkey; - const subkeySignaturePacket = new SignaturePacket(); - subkeySignaturePacket.signatureType = enums.signature.subkeyBinding; - subkeySignaturePacket.publicKeyAlgorithm = primaryKey.algorithm; - subkeySignaturePacket.hashAlgorithm = await getPreferredHashAlgo$1(null, subkey, undefined, undefined, config); - if (options.sign) { - subkeySignaturePacket.keyFlags = [enums.keyFlags.signData]; - subkeySignaturePacket.embeddedSignature = await createSignaturePacket(dataToSign, null, subkey, { - signatureType: enums.signature.keyBinding - }, options.date, undefined, undefined, config); - } else { - subkeySignaturePacket.keyFlags = [enums.keyFlags.encryptCommunication | enums.keyFlags.encryptStorage]; - } - if (options.keyExpirationTime > 0) { - subkeySignaturePacket.keyExpirationTime = options.keyExpirationTime; - subkeySignaturePacket.keyNeverExpires = false; - } - await subkeySignaturePacket.sign(primaryKey, dataToSign, options.date); - return subkeySignaturePacket; -} - -/** - * Returns the preferred signature hash algorithm of a key - * @param {Key} [key] - The key to get preferences from - * @param {SecretKeyPacket|SecretSubkeyPacket} keyPacket - key packet used for signing - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} [userID] - User ID - * @param {Object} config - full configuration - * @returns {Promise} - * @async - */ -async function getPreferredHashAlgo$1(key, keyPacket, date = new Date(), userID = {}, config) { - let hashAlgo = config.preferredHashAlgorithm; - let prefAlgo = hashAlgo; - if (key) { - const primaryUser = await key.getPrimaryUser(date, userID, config); - if (primaryUser.selfCertification.preferredHashAlgorithms) { - [prefAlgo] = primaryUser.selfCertification.preferredHashAlgorithms; - hashAlgo = mod.hash.getHashByteLength(hashAlgo) <= mod.hash.getHashByteLength(prefAlgo) ? - prefAlgo : hashAlgo; - } - } - switch (Object.getPrototypeOf(keyPacket)) { - case SecretKeyPacket.prototype: - case PublicKeyPacket.prototype: - case SecretSubkeyPacket.prototype: - case PublicSubkeyPacket.prototype: - switch (keyPacket.algorithm) { - case enums.publicKey.ecdh: - case enums.publicKey.ecdsa: - case enums.publicKey.eddsa: - prefAlgo = mod.publicKey.elliptic.getPreferredHashAlgo(keyPacket.publicParams.oid); - } - } - return mod.hash.getHashByteLength(hashAlgo) <= mod.hash.getHashByteLength(prefAlgo) ? - prefAlgo : hashAlgo; -} - -/** - * Returns the preferred symmetric/aead/compression algorithm for a set of keys - * @param {'symmetric'|'aead'|'compression'} type - Type of preference to return - * @param {Array} [keys] - Set of keys - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Array} [userIDs] - User IDs - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} Preferred algorithm - * @async - */ -async function getPreferredAlgo(type, keys = [], date = new Date(), userIDs = [], config = defaultConfig) { - const defaultAlgo = { // these are all must-implement in rfc4880bis - 'symmetric': enums.symmetric.aes128, - 'aead': enums.aead.eax, - 'compression': enums.compression.uncompressed - }[type]; - const preferredSenderAlgo = { - 'symmetric': config.preferredSymmetricAlgorithm, - 'aead': config.preferredAEADAlgorithm, - 'compression': config.preferredCompressionAlgorithm - }[type]; - const prefPropertyName = { - 'symmetric': 'preferredSymmetricAlgorithms', - 'aead': 'preferredAEADAlgorithms', - 'compression': 'preferredCompressionAlgorithms' - }[type]; - - // if preferredSenderAlgo appears in the prefs of all recipients, we pick it - // otherwise we use the default algo - // if no keys are available, preferredSenderAlgo is returned - const senderAlgoSupport = await Promise.all(keys.map(async function(key, i) { - const primaryUser = await key.getPrimaryUser(date, userIDs[i], config); - const recipientPrefs = primaryUser.selfCertification[prefPropertyName]; - return !!recipientPrefs && recipientPrefs.indexOf(preferredSenderAlgo) >= 0; - })); - return senderAlgoSupport.every(Boolean) ? preferredSenderAlgo : defaultAlgo; -} - -/** - * Create signature packet - * @param {Object} dataToSign - Contains packets to be signed - * @param {PrivateKey} privateKey - key to get preferences from - * @param {SecretKeyPacket| - * SecretSubkeyPacket} signingKeyPacket secret key packet for signing - * @param {Object} [signatureProperties] - Properties to write on the signature packet before signing - * @param {Date} [date] - Override the creationtime of the signature - * @param {Object} [userID] - User ID - * @param {Object} [detached] - Whether to create a detached signature packet - * @param {Object} config - full configuration - * @returns {Promise} Signature packet. - */ -async function createSignaturePacket(dataToSign, privateKey, signingKeyPacket, signatureProperties, date, userID, detached = false, config) { - if (signingKeyPacket.isDummy()) { - throw new Error('Cannot sign with a gnu-dummy key.'); - } - if (!signingKeyPacket.isDecrypted()) { - throw new Error('Signing key is not decrypted.'); - } - const signaturePacket = new SignaturePacket(); - Object.assign(signaturePacket, signatureProperties); - signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm; - signaturePacket.hashAlgorithm = await getPreferredHashAlgo$1(privateKey, signingKeyPacket, date, userID, config); - await signaturePacket.sign(signingKeyPacket, dataToSign, date, detached); - return signaturePacket; -} - -/** - * Merges signatures from source[attr] to dest[attr] - * @param {Object} source - * @param {Object} dest - * @param {String} attr - * @param {Date} [date] - date to use for signature expiration check, instead of the current time - * @param {Function} [checkFn] - signature only merged if true - */ -async function mergeSignatures(source, dest, attr, date = new Date(), checkFn) { - source = source[attr]; - if (source) { - if (!dest[attr].length) { - dest[attr] = source; - } else { - await Promise.all(source.map(async function(sourceSig) { - if (!sourceSig.isExpired(date) && (!checkFn || await checkFn(sourceSig)) && - !dest[attr].some(function(destSig) { - return util.equalsUint8Array(destSig.writeParams(), sourceSig.writeParams()); - })) { - dest[attr].push(sourceSig); - } - })); - } - } -} - -/** - * Checks if a given certificate or binding signature is revoked - * @param {SecretKeyPacket| - * PublicKeyPacket} primaryKey The primary key packet - * @param {Object} dataToVerify - The data to check - * @param {Array} revocations - The revocation signatures to check - * @param {SignaturePacket} signature - The certificate or signature to check - * @param {PublicSubkeyPacket| - * SecretSubkeyPacket| - * PublicKeyPacket| - * SecretKeyPacket} key, optional The key packet to verify the signature, instead of the primary key - * @param {Date} date - Use the given date instead of the current time - * @param {Object} config - Full configuration - * @returns {Promise} True if the signature revokes the data. - * @async - */ -async function isDataRevoked(primaryKey, signatureType, dataToVerify, revocations, signature, key, date = new Date(), config) { - key = key || primaryKey; - const revocationKeyIDs = []; - await Promise.all(revocations.map(async function(revocationSignature) { - try { - if ( - // Note: a third-party revocation signature could legitimately revoke a - // self-signature if the signature has an authorized revocation key. - // However, we don't support passing authorized revocation keys, nor - // verifying such revocation signatures. Instead, we indicate an error - // when parsing a key with an authorized revocation key, and ignore - // third-party revocation signatures here. (It could also be revoking a - // third-party key certification, which should only affect - // `verifyAllCertifications`.) - !signature || revocationSignature.issuerKeyID.equals(signature.issuerKeyID) - ) { - await revocationSignature.verify( - key, signatureType, dataToVerify, config.revocationsExpire ? date : null, false, config - ); - - // TODO get an identifier of the revoked object instead - revocationKeyIDs.push(revocationSignature.issuerKeyID); - } - } catch (e) {} - })); - // TODO further verify that this is the signature that should be revoked - if (signature) { - signature.revoked = revocationKeyIDs.some(keyID => keyID.equals(signature.issuerKeyID)) ? true : - signature.revoked || false; - return signature.revoked; - } - return revocationKeyIDs.length > 0; -} - -/** - * Returns key expiration time based on the given certification signature. - * The expiration time of the signature is ignored. - * @param {PublicSubkeyPacket|PublicKeyPacket} keyPacket - key to check - * @param {SignaturePacket} signature - signature to process - * @returns {Date|Infinity} expiration time or infinity if the key does not expire - */ -function getKeyExpirationTime(keyPacket, signature) { - let expirationTime; - // check V4 expiration time - if (signature.keyNeverExpires === false) { - expirationTime = keyPacket.created.getTime() + signature.keyExpirationTime * 1000; - } - return expirationTime ? new Date(expirationTime) : Infinity; -} - -/** - * Returns whether aead is supported by all keys in the set - * @param {Array} keys - Set of keys - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Array} [userIDs] - User IDs - * @param {Object} config - full configuration - * @returns {Promise} - * @async - */ -async function isAEADSupported(keys, date = new Date(), userIDs = [], config = defaultConfig) { - let supported = true; - // TODO replace when Promise.some or Promise.any are implemented - await Promise.all(keys.map(async function(key, i) { - const primaryUser = await key.getPrimaryUser(date, userIDs[i], config); - if (!primaryUser.selfCertification.features || - !(primaryUser.selfCertification.features[0] & enums.features.aead)) { - supported = false; - } - })); - return supported; -} - -function sanitizeKeyOptions(options, subkeyDefaults = {}) { - options.type = options.type || subkeyDefaults.type; - options.curve = options.curve || subkeyDefaults.curve; - options.rsaBits = options.rsaBits || subkeyDefaults.rsaBits; - options.keyExpirationTime = options.keyExpirationTime !== undefined ? options.keyExpirationTime : subkeyDefaults.keyExpirationTime; - options.passphrase = util.isString(options.passphrase) ? options.passphrase : subkeyDefaults.passphrase; - options.date = options.date || subkeyDefaults.date; - - options.sign = options.sign || false; - - switch (options.type) { - case 'ecc': - try { - options.curve = enums.write(enums.curve, options.curve); - } catch (e) { - throw new Error('Invalid curve'); - } - if (options.curve === enums.curve.ed25519 || options.curve === enums.curve.curve25519) { - options.curve = options.sign ? enums.curve.ed25519 : enums.curve.curve25519; - } - if (options.sign) { - options.algorithm = options.curve === enums.curve.ed25519 ? enums.publicKey.eddsa : enums.publicKey.ecdsa; - } else { - options.algorithm = enums.publicKey.ecdh; - } - break; - case 'rsa': - options.algorithm = enums.publicKey.rsaEncryptSign; - break; - default: - throw new Error(`Unsupported key type ${options.type}`); - } - return options; -} - -function isValidSigningKeyPacket(keyPacket, signature) { - const keyAlgo = keyPacket.algorithm; - return keyAlgo !== enums.publicKey.rsaEncrypt && - keyAlgo !== enums.publicKey.elgamal && - keyAlgo !== enums.publicKey.ecdh && - (!signature.keyFlags || - (signature.keyFlags[0] & enums.keyFlags.signData) !== 0); -} - -function isValidEncryptionKeyPacket(keyPacket, signature) { - const keyAlgo = keyPacket.algorithm; - return keyAlgo !== enums.publicKey.dsa && - keyAlgo !== enums.publicKey.rsaSign && - keyAlgo !== enums.publicKey.ecdsa && - keyAlgo !== enums.publicKey.eddsa && - (!signature.keyFlags || - (signature.keyFlags[0] & enums.keyFlags.encryptCommunication) !== 0 || - (signature.keyFlags[0] & enums.keyFlags.encryptStorage) !== 0); -} - -function isValidDecryptionKeyPacket(signature, config) { - if (config.allowInsecureDecryptionWithSigningKeys) { - // This is only relevant for RSA keys, all other signing algorithms cannot decrypt - return true; - } - - return !signature.keyFlags || - (signature.keyFlags[0] & enums.keyFlags.encryptCommunication) !== 0 || - (signature.keyFlags[0] & enums.keyFlags.encryptStorage) !== 0; -} - -/** - * Check key against blacklisted algorithms and minimum strength requirements. - * @param {SecretKeyPacket|PublicKeyPacket| - * SecretSubkeyPacket|PublicSubkeyPacket} keyPacket - * @param {Config} config - * @throws {Error} if the key packet does not meet the requirements - */ -function checkKeyRequirements(keyPacket, config) { - const keyAlgo = enums.write(enums.publicKey, keyPacket.algorithm); - const algoInfo = keyPacket.getAlgorithmInfo(); - if (config.rejectPublicKeyAlgorithms.has(keyAlgo)) { - throw new Error(`${algoInfo.algorithm} keys are considered too weak.`); - } - switch (keyAlgo) { - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaSign: - case enums.publicKey.rsaEncrypt: - if (algoInfo.bits < config.minRSABits) { - throw new Error(`RSA keys shorter than ${config.minRSABits} bits are considered too weak.`); - } - break; - case enums.publicKey.ecdsa: - case enums.publicKey.eddsa: - case enums.publicKey.ecdh: - if (config.rejectCurves.has(algoInfo.curve)) { - throw new Error(`Support for ${algoInfo.algorithm} keys using curve ${algoInfo.curve} is disabled.`); - } - break; - } -} - -/** - * @module key/User - * @private - */ - -/** - * Class that represents an user ID or attribute packet and the relevant signatures. - * @param {UserIDPacket|UserAttributePacket} userPacket - packet containing the user info - * @param {Key} mainKey - reference to main Key object containing the primary key and subkeys that the user is associated with - */ -class User { - constructor(userPacket, mainKey) { - this.userID = userPacket.constructor.tag === enums.packet.userID ? userPacket : null; - this.userAttribute = userPacket.constructor.tag === enums.packet.userAttribute ? userPacket : null; - this.selfCertifications = []; - this.otherCertifications = []; - this.revocationSignatures = []; - this.mainKey = mainKey; - } - - /** - * Transforms structured user data to packetlist - * @returns {PacketList} - */ - toPacketList() { - const packetlist = new PacketList(); - packetlist.push(this.userID || this.userAttribute); - packetlist.push(...this.revocationSignatures); - packetlist.push(...this.selfCertifications); - packetlist.push(...this.otherCertifications); - return packetlist; - } - - /** - * Shallow clone - * @returns {User} - */ - clone() { - const user = new User(this.userID || this.userAttribute, this.mainKey); - user.selfCertifications = [...this.selfCertifications]; - user.otherCertifications = [...this.otherCertifications]; - user.revocationSignatures = [...this.revocationSignatures]; - return user; - } - - /** - * Generate third-party certifications over this user and its primary key - * @param {Array} signingKeys - Decrypted private keys for signing - * @param {Date} [date] - Date to use as creation date of the certificate, instead of the current time - * @param {Object} config - Full configuration - * @returns {Promise} New user with new certifications. - * @async - */ - async certify(signingKeys, date, config) { - const primaryKey = this.mainKey.keyPacket; - const dataToSign = { - userID: this.userID, - userAttribute: this.userAttribute, - key: primaryKey - }; - const user = new User(dataToSign.userID || dataToSign.userAttribute, this.mainKey); - user.otherCertifications = await Promise.all(signingKeys.map(async function(privateKey) { - if (!privateKey.isPrivate()) { - throw new Error('Need private key for signing'); - } - if (privateKey.hasSameFingerprintAs(primaryKey)) { - throw new Error("The user's own key can only be used for self-certifications"); - } - const signingKey = await privateKey.getSigningKey(undefined, date, undefined, config); - return createSignaturePacket(dataToSign, privateKey, signingKey.keyPacket, { - // Most OpenPGP implementations use generic certification (0x10) - signatureType: enums.signature.certGeneric, - keyFlags: [enums.keyFlags.certifyKeys | enums.keyFlags.signData] - }, date, undefined, undefined, config); - })); - await user.update(this, date, config); - return user; - } - - /** - * Checks if a given certificate of the user is revoked - * @param {SignaturePacket} certificate - The certificate to verify - * @param {PublicSubkeyPacket| - * SecretSubkeyPacket| - * PublicKeyPacket| - * SecretKeyPacket} [keyPacket] The key packet to verify the signature, instead of the primary key - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} config - Full configuration - * @returns {Promise} True if the certificate is revoked. - * @async - */ - async isRevoked(certificate, keyPacket, date = new Date(), config) { - const primaryKey = this.mainKey.keyPacket; - return isDataRevoked(primaryKey, enums.signature.certRevocation, { - key: primaryKey, - userID: this.userID, - userAttribute: this.userAttribute - }, this.revocationSignatures, certificate, keyPacket, date, config); - } - - /** - * Verifies the user certificate. - * @param {SignaturePacket} certificate - A certificate of this user - * @param {Array} verificationKeys - Array of keys to verify certificate signatures - * @param {Date} [date] - Use the given date instead of the current time - * @param {Object} config - Full configuration - * @returns {Promise} true if the certificate could be verified, or null if the verification keys do not correspond to the certificate - * @throws if the user certificate is invalid. - * @async - */ - async verifyCertificate(certificate, verificationKeys, date = new Date(), config) { - const that = this; - const primaryKey = this.mainKey.keyPacket; - const dataToVerify = { - userID: this.userID, - userAttribute: this.userAttribute, - key: primaryKey - }; - const { issuerKeyID } = certificate; - const issuerKeys = verificationKeys.filter(key => key.getKeys(issuerKeyID).length > 0); - if (issuerKeys.length === 0) { - return null; - } - await Promise.all(issuerKeys.map(async key => { - const signingKey = await key.getSigningKey(issuerKeyID, certificate.created, undefined, config); - if (certificate.revoked || await that.isRevoked(certificate, signingKey.keyPacket, date, config)) { - throw new Error('User certificate is revoked'); - } - try { - await certificate.verify(signingKey.keyPacket, enums.signature.certGeneric, dataToVerify, date, undefined, config); - } catch (e) { - throw util.wrapError('User certificate is invalid', e); - } - })); - return true; - } - - /** - * Verifies all user certificates - * @param {Array} verificationKeys - Array of keys to verify certificate signatures - * @param {Date} [date] - Use the given date instead of the current time - * @param {Object} config - Full configuration - * @returns {Promise>} List of signer's keyID and validity of signature. - * Signature validity is null if the verification keys do not correspond to the certificate. - * @async - */ - async verifyAllCertifications(verificationKeys, date = new Date(), config) { - const that = this; - const certifications = this.selfCertifications.concat(this.otherCertifications); - return Promise.all(certifications.map(async certification => ({ - keyID: certification.issuerKeyID, - valid: await that.verifyCertificate(certification, verificationKeys, date, config).catch(() => false) - }))); - } - - /** - * Verify User. Checks for existence of self signatures, revocation signatures - * and validity of self signature. - * @param {Date} date - Use the given date instead of the current time - * @param {Object} config - Full configuration - * @returns {Promise} Status of user. - * @throws {Error} if there are no valid self signatures. - * @async - */ - async verify(date = new Date(), config) { - if (!this.selfCertifications.length) { - throw new Error('No self-certifications found'); - } - const that = this; - const primaryKey = this.mainKey.keyPacket; - const dataToVerify = { - userID: this.userID, - userAttribute: this.userAttribute, - key: primaryKey - }; - // TODO replace when Promise.some or Promise.any are implemented - let exception; - for (let i = this.selfCertifications.length - 1; i >= 0; i--) { - try { - const selfCertification = this.selfCertifications[i]; - if (selfCertification.revoked || await that.isRevoked(selfCertification, undefined, date, config)) { - throw new Error('Self-certification is revoked'); - } - try { - await selfCertification.verify(primaryKey, enums.signature.certGeneric, dataToVerify, date, undefined, config); - } catch (e) { - throw util.wrapError('Self-certification is invalid', e); - } - return true; - } catch (e) { - exception = e; - } - } - throw exception; - } - - /** - * Update user with new components from specified user - * @param {User} sourceUser - Source user to merge - * @param {Date} date - Date to verify the validity of signatures - * @param {Object} config - Full configuration - * @returns {Promise} - * @async - */ - async update(sourceUser, date, config) { - const primaryKey = this.mainKey.keyPacket; - const dataToVerify = { - userID: this.userID, - userAttribute: this.userAttribute, - key: primaryKey - }; - // self signatures - await mergeSignatures(sourceUser, this, 'selfCertifications', date, async function(srcSelfSig) { - try { - await srcSelfSig.verify(primaryKey, enums.signature.certGeneric, dataToVerify, date, false, config); - return true; - } catch (e) { - return false; - } - }); - // other signatures - await mergeSignatures(sourceUser, this, 'otherCertifications', date); - // revocation signatures - await mergeSignatures(sourceUser, this, 'revocationSignatures', date, function(srcRevSig) { - return isDataRevoked(primaryKey, enums.signature.certRevocation, dataToVerify, [srcRevSig], undefined, undefined, date, config); - }); - } -} - -/** - * @module key/Subkey - * @private - */ - -/** - * Class that represents a subkey packet and the relevant signatures. - * @borrows PublicSubkeyPacket#getKeyID as Subkey#getKeyID - * @borrows PublicSubkeyPacket#getFingerprint as Subkey#getFingerprint - * @borrows PublicSubkeyPacket#hasSameFingerprintAs as Subkey#hasSameFingerprintAs - * @borrows PublicSubkeyPacket#getAlgorithmInfo as Subkey#getAlgorithmInfo - * @borrows PublicSubkeyPacket#getCreationTime as Subkey#getCreationTime - * @borrows PublicSubkeyPacket#isDecrypted as Subkey#isDecrypted - */ -class Subkey { - /** - * @param {SecretSubkeyPacket|PublicSubkeyPacket} subkeyPacket - subkey packet to hold in the Subkey - * @param {Key} mainKey - reference to main Key object, containing the primary key packet corresponding to the subkey - */ - constructor(subkeyPacket, mainKey) { - this.keyPacket = subkeyPacket; - this.bindingSignatures = []; - this.revocationSignatures = []; - this.mainKey = mainKey; - } - - /** - * Transforms structured subkey data to packetlist - * @returns {PacketList} - */ - toPacketList() { - const packetlist = new PacketList(); - packetlist.push(this.keyPacket); - packetlist.push(...this.revocationSignatures); - packetlist.push(...this.bindingSignatures); - return packetlist; - } - - /** - * Shallow clone - * @return {Subkey} - */ - clone() { - const subkey = new Subkey(this.keyPacket, this.mainKey); - subkey.bindingSignatures = [...this.bindingSignatures]; - subkey.revocationSignatures = [...this.revocationSignatures]; - return subkey; - } - - /** - * Checks if a binding signature of a subkey is revoked - * @param {SignaturePacket} signature - The binding signature to verify - * @param {PublicSubkeyPacket| - * SecretSubkeyPacket| - * PublicKeyPacket| - * SecretKeyPacket} key, optional The key to verify the signature - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} True if the binding signature is revoked. - * @async - */ - async isRevoked(signature, key, date = new Date(), config = defaultConfig) { - const primaryKey = this.mainKey.keyPacket; - return isDataRevoked( - primaryKey, enums.signature.subkeyRevocation, { - key: primaryKey, - bind: this.keyPacket - }, this.revocationSignatures, signature, key, date, config - ); - } - - /** - * Verify subkey. Checks for revocation signatures, expiration time - * and valid binding signature. - * @param {Date} date - Use the given date instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} - * @throws {Error} if the subkey is invalid. - * @async - */ - async verify(date = new Date(), config = defaultConfig) { - const primaryKey = this.mainKey.keyPacket; - const dataToVerify = { key: primaryKey, bind: this.keyPacket }; - // check subkey binding signatures - const bindingSignature = await getLatestValidSignature(this.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); - // check binding signature is not revoked - if (bindingSignature.revoked || await this.isRevoked(bindingSignature, null, date, config)) { - throw new Error('Subkey is revoked'); - } - // check for expiration time - if (isDataExpired(this.keyPacket, bindingSignature, date)) { - throw new Error('Subkey is expired'); - } - return bindingSignature; - } - - /** - * Returns the expiration time of the subkey or Infinity if key does not expire. - * Returns null if the subkey is invalid. - * @param {Date} date - Use the given date instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} - * @async - */ - async getExpirationTime(date = new Date(), config = defaultConfig) { - const primaryKey = this.mainKey.keyPacket; - const dataToVerify = { key: primaryKey, bind: this.keyPacket }; - let bindingSignature; - try { - bindingSignature = await getLatestValidSignature(this.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); - } catch (e) { - return null; - } - const keyExpiry = getKeyExpirationTime(this.keyPacket, bindingSignature); - const sigExpiry = bindingSignature.getExpirationTime(); - return keyExpiry < sigExpiry ? keyExpiry : sigExpiry; - } - - /** - * Update subkey with new components from specified subkey - * @param {Subkey} subkey - Source subkey to merge - * @param {Date} [date] - Date to verify validity of signatures - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if update failed - * @async - */ - async update(subkey, date = new Date(), config = defaultConfig) { - const primaryKey = this.mainKey.keyPacket; - if (!this.hasSameFingerprintAs(subkey)) { - throw new Error('Subkey update method: fingerprints of subkeys not equal'); - } - // key packet - if (this.keyPacket.constructor.tag === enums.packet.publicSubkey && - subkey.keyPacket.constructor.tag === enums.packet.secretSubkey) { - this.keyPacket = subkey.keyPacket; - } - // update missing binding signatures - const that = this; - const dataToVerify = { key: primaryKey, bind: that.keyPacket }; - await mergeSignatures(subkey, this, 'bindingSignatures', date, async function(srcBindSig) { - for (let i = 0; i < that.bindingSignatures.length; i++) { - if (that.bindingSignatures[i].issuerKeyID.equals(srcBindSig.issuerKeyID)) { - if (srcBindSig.created > that.bindingSignatures[i].created) { - that.bindingSignatures[i] = srcBindSig; - } - return false; - } - } - try { - await srcBindSig.verify(primaryKey, enums.signature.subkeyBinding, dataToVerify, date, undefined, config); - return true; - } catch (e) { - return false; - } - }); - // revocation signatures - await mergeSignatures(subkey, this, 'revocationSignatures', date, function(srcRevSig) { - return isDataRevoked(primaryKey, enums.signature.subkeyRevocation, dataToVerify, [srcRevSig], undefined, undefined, date, config); - }); - } - - /** - * Revokes the subkey - * @param {SecretKeyPacket} primaryKey - decrypted private primary key for revocation - * @param {Object} reasonForRevocation - optional, object indicating the reason for revocation - * @param {module:enums.reasonForRevocation} reasonForRevocation.flag optional, flag indicating the reason for revocation - * @param {String} reasonForRevocation.string optional, string explaining the reason for revocation - * @param {Date} date - optional, override the creationtime of the revocation signature - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New subkey with revocation signature. - * @async - */ - async revoke( - primaryKey, - { - flag: reasonForRevocationFlag = enums.reasonForRevocation.noReason, - string: reasonForRevocationString = '' - } = {}, - date = new Date(), - config = defaultConfig - ) { - const dataToSign = { key: primaryKey, bind: this.keyPacket }; - const subkey = new Subkey(this.keyPacket, this.mainKey); - subkey.revocationSignatures.push(await createSignaturePacket(dataToSign, null, primaryKey, { - signatureType: enums.signature.subkeyRevocation, - reasonForRevocationFlag: enums.write(enums.reasonForRevocation, reasonForRevocationFlag), - reasonForRevocationString - }, date, undefined, false, config)); - await subkey.update(this); - return subkey; - } - - hasSameFingerprintAs(other) { - return this.keyPacket.hasSameFingerprintAs(other.keyPacket || other); - } -} - -['getKeyID', 'getFingerprint', 'getAlgorithmInfo', 'getCreationTime', 'isDecrypted'].forEach(name => { - Subkey.prototype[name] = - function() { - return this.keyPacket[name](); - }; -}); - -// GPG4Browsers - An OpenPGP implementation in javascript - -// A key revocation certificate can contain the following packets -const allowedRevocationPackets = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); - -/** - * Abstract class that represents an OpenPGP key. Must contain a primary key. - * Can contain additional subkeys, signatures, user ids, user attributes. - * @borrows PublicKeyPacket#getKeyID as Key#getKeyID - * @borrows PublicKeyPacket#getFingerprint as Key#getFingerprint - * @borrows PublicKeyPacket#hasSameFingerprintAs as Key#hasSameFingerprintAs - * @borrows PublicKeyPacket#getAlgorithmInfo as Key#getAlgorithmInfo - * @borrows PublicKeyPacket#getCreationTime as Key#getCreationTime - */ -class Key { - /** - * Transforms packetlist to structured key data - * @param {PacketList} packetlist - The packets that form a key - * @param {Set} disallowedPackets - disallowed packet tags - */ - packetListToStructure(packetlist, disallowedPackets = new Set()) { - let user; - let primaryKeyID; - let subkey; - for (const packet of packetlist) { - const tag = packet.constructor.tag; - if (disallowedPackets.has(tag)) { - throw new Error(`Unexpected packet type: ${tag}`); - } - switch (tag) { - case enums.packet.publicKey: - case enums.packet.secretKey: - if (this.keyPacket) { - throw new Error('Key block contains multiple keys'); - } - this.keyPacket = packet; - primaryKeyID = this.getKeyID(); - if (!primaryKeyID) { - throw new Error('Missing Key ID'); - } - break; - case enums.packet.userID: - case enums.packet.userAttribute: - user = new User(packet, this); - this.users.push(user); - break; - case enums.packet.publicSubkey: - case enums.packet.secretSubkey: - user = null; - subkey = new Subkey(packet, this); - this.subkeys.push(subkey); - break; - case enums.packet.signature: - switch (packet.signatureType) { - case enums.signature.certGeneric: - case enums.signature.certPersona: - case enums.signature.certCasual: - case enums.signature.certPositive: - if (!user) { - util.printDebug('Dropping certification signatures without preceding user packet'); - continue; - } - if (packet.issuerKeyID.equals(primaryKeyID)) { - user.selfCertifications.push(packet); - } else { - user.otherCertifications.push(packet); - } - break; - case enums.signature.certRevocation: - if (user) { - user.revocationSignatures.push(packet); - } else { - this.directSignatures.push(packet); - } - break; - case enums.signature.key: - this.directSignatures.push(packet); - break; - case enums.signature.subkeyBinding: - if (!subkey) { - util.printDebug('Dropping subkey binding signature without preceding subkey packet'); - continue; - } - subkey.bindingSignatures.push(packet); - break; - case enums.signature.keyRevocation: - this.revocationSignatures.push(packet); - break; - case enums.signature.subkeyRevocation: - if (!subkey) { - util.printDebug('Dropping subkey revocation signature without preceding subkey packet'); - continue; - } - subkey.revocationSignatures.push(packet); - break; - } - break; - } - } - } - - /** - * Transforms structured key data to packetlist - * @returns {PacketList} The packets that form a key. - */ - toPacketList() { - const packetlist = new PacketList(); - packetlist.push(this.keyPacket); - packetlist.push(...this.revocationSignatures); - packetlist.push(...this.directSignatures); - this.users.map(user => packetlist.push(...user.toPacketList())); - this.subkeys.map(subkey => packetlist.push(...subkey.toPacketList())); - return packetlist; - } - - /** - * Clones the key object - * @param {Boolean} [deep=false] Whether to return a deep clone - * @returns {Promise} Clone of the key. - */ - clone(deep = false) { - const key = new this.constructor(this.toPacketList()); - if (deep) { - key.getKeys().forEach(k => { - // shallow clone the key packets - k.keyPacket = Object.create( - Object.getPrototypeOf(k.keyPacket), - Object.getOwnPropertyDescriptors(k.keyPacket) - ); - if (!k.keyPacket.isDecrypted()) return; - // deep clone the private params, which are cleared during encryption - const privateParams = {}; - Object.keys(k.keyPacket.privateParams).forEach(name => { - privateParams[name] = new Uint8Array(k.keyPacket.privateParams[name]); - }); - k.keyPacket.privateParams = privateParams; - }); - } - return key; - } - - /** - * Returns an array containing all public or private subkeys matching keyID; - * If no keyID is given, returns all subkeys. - * @param {type/keyID} [keyID] - key ID to look for - * @returns {Array} array of subkeys - */ - getSubkeys(keyID = null) { - const subkeys = this.subkeys.filter(subkey => ( - !keyID || subkey.getKeyID().equals(keyID, true) - )); - return subkeys; - } - - /** - * Returns an array containing all public or private keys matching keyID. - * If no keyID is given, returns all keys, starting with the primary key. - * @param {type/keyid~KeyID} [keyID] - key ID to look for - * @returns {Array} array of keys - */ - getKeys(keyID = null) { - const keys = []; - if (!keyID || this.getKeyID().equals(keyID, true)) { - keys.push(this); - } - return keys.concat(this.getSubkeys(keyID)); - } - - /** - * Returns key IDs of all keys - * @returns {Array} - */ - getKeyIDs() { - return this.getKeys().map(key => key.getKeyID()); - } - - /** - * Returns userIDs - * @returns {Array} Array of userIDs. - */ - getUserIDs() { - return this.users.map(user => { - return user.userID ? user.userID.userID : null; - }).filter(userID => userID !== null); - } - - /** - * Returns binary encoded key - * @returns {Uint8Array} Binary key. - */ - write() { - return this.toPacketList().write(); - } - - /** - * Returns last created key or key by given keyID that is available for signing and verification - * @param {module:type/keyid~KeyID} [keyID] - key ID of a specific key to retrieve - * @param {Date} [date] - use the fiven date date to to check key validity instead of the current date - * @param {Object} [userID] - filter keys for the given user ID - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} signing key - * @throws if no valid signing key was found - * @async - */ - async getSigningKey(keyID = null, date = new Date(), userID = {}, config = defaultConfig) { - await this.verifyPrimaryKey(date, userID, config); - const primaryKey = this.keyPacket; - const subkeys = this.subkeys.slice().sort((a, b) => b.keyPacket.created - a.keyPacket.created); - let exception; - for (const subkey of subkeys) { - if (!keyID || subkey.getKeyID().equals(keyID)) { - try { - await subkey.verify(date, config); - const dataToVerify = { key: primaryKey, bind: subkey.keyPacket }; - const bindingSignature = await getLatestValidSignature( - subkey.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config - ); - if (!isValidSigningKeyPacket(subkey.keyPacket, bindingSignature)) { - continue; - } - if (!bindingSignature.embeddedSignature) { - throw new Error('Missing embedded signature'); - } - // verify embedded signature - await getLatestValidSignature( - [bindingSignature.embeddedSignature], subkey.keyPacket, enums.signature.keyBinding, dataToVerify, date, config - ); - checkKeyRequirements(subkey.keyPacket, config); - return subkey; - } catch (e) { - exception = e; - } - } - } - - try { - const primaryUser = await this.getPrimaryUser(date, userID, config); - if ((!keyID || primaryKey.getKeyID().equals(keyID)) && - isValidSigningKeyPacket(primaryKey, primaryUser.selfCertification, config)) { - checkKeyRequirements(primaryKey, config); - return this; - } - } catch (e) { - exception = e; - } - throw util.wrapError('Could not find valid signing key packet in key ' + this.getKeyID().toHex(), exception); - } - - /** - * Returns last created key or key by given keyID that is available for encryption or decryption - * @param {module:type/keyid~KeyID} [keyID] - key ID of a specific key to retrieve - * @param {Date} [date] - use the fiven date date to to check key validity instead of the current date - * @param {Object} [userID] - filter keys for the given user ID - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} encryption key - * @throws if no valid encryption key was found - * @async - */ - async getEncryptionKey(keyID, date = new Date(), userID = {}, config = defaultConfig) { - await this.verifyPrimaryKey(date, userID, config); - const primaryKey = this.keyPacket; - // V4: by convention subkeys are preferred for encryption service - const subkeys = this.subkeys.slice().sort((a, b) => b.keyPacket.created - a.keyPacket.created); - let exception; - for (const subkey of subkeys) { - if (!keyID || subkey.getKeyID().equals(keyID)) { - try { - await subkey.verify(date, config); - const dataToVerify = { key: primaryKey, bind: subkey.keyPacket }; - const bindingSignature = await getLatestValidSignature(subkey.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); - if (isValidEncryptionKeyPacket(subkey.keyPacket, bindingSignature)) { - checkKeyRequirements(subkey.keyPacket, config); - return subkey; - } - } catch (e) { - exception = e; - } - } - } - - try { - // if no valid subkey for encryption, evaluate primary key - const primaryUser = await this.getPrimaryUser(date, userID, config); - if ((!keyID || primaryKey.getKeyID().equals(keyID)) && - isValidEncryptionKeyPacket(primaryKey, primaryUser.selfCertification)) { - checkKeyRequirements(primaryKey, config); - return this; - } - } catch (e) { - exception = e; - } - throw util.wrapError('Could not find valid encryption key packet in key ' + this.getKeyID().toHex(), exception); - } - - /** - * Checks if a signature on a key is revoked - * @param {SignaturePacket} signature - The signature to verify - * @param {PublicSubkeyPacket| - * SecretSubkeyPacket| - * PublicKeyPacket| - * SecretKeyPacket} key, optional The key to verify the signature - * @param {Date} [date] - Use the given date for verification, instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} True if the certificate is revoked. - * @async - */ - async isRevoked(signature, key, date = new Date(), config = defaultConfig) { - return isDataRevoked( - this.keyPacket, enums.signature.keyRevocation, { key: this.keyPacket }, this.revocationSignatures, signature, key, date, config - ); - } - - /** - * Verify primary key. Checks for revocation signatures, expiration time - * and valid self signature. Throws if the primary key is invalid. - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} [userID] - User ID - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} If key verification failed - * @async - */ - async verifyPrimaryKey(date = new Date(), userID = {}, config = defaultConfig) { - const primaryKey = this.keyPacket; - // check for key revocation signatures - if (await this.isRevoked(null, null, date, config)) { - throw new Error('Primary key is revoked'); - } - // check for valid, unrevoked, unexpired self signature - const { selfCertification } = await this.getPrimaryUser(date, userID, config); - // check for expiration time in binding signatures - if (isDataExpired(primaryKey, selfCertification, date)) { - throw new Error('Primary key is expired'); - } - // check for expiration time in direct signatures - const directSignature = await getLatestValidSignature( - this.directSignatures, primaryKey, enums.signature.key, { key: primaryKey }, date, config - ).catch(() => {}); // invalid signatures are discarded, to avoid breaking the key - - if (directSignature && isDataExpired(primaryKey, directSignature, date)) { - throw new Error('Primary key is expired'); - } - } - - /** - * Returns the expiration date of the primary key, considering self-certifications and direct-key signatures. - * Returns `Infinity` if the key doesn't expire, or `null` if the key is revoked or invalid. - * @param {Object} [userID] - User ID to consider instead of the primary user - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} - * @async - */ - async getExpirationTime(userID, config = defaultConfig) { - let primaryKeyExpiry; - try { - const { selfCertification } = await this.getPrimaryUser(null, userID, config); - const selfSigKeyExpiry = getKeyExpirationTime(this.keyPacket, selfCertification); - const selfSigExpiry = selfCertification.getExpirationTime(); - const directSignature = await getLatestValidSignature( - this.directSignatures, this.keyPacket, enums.signature.key, { key: this.keyPacket }, null, config - ).catch(() => {}); - if (directSignature) { - const directSigKeyExpiry = getKeyExpirationTime(this.keyPacket, directSignature); - // We do not support the edge case where the direct signature expires, since it would invalidate the corresponding key expiration, - // causing a discountinous validy period for the key - primaryKeyExpiry = Math.min(selfSigKeyExpiry, selfSigExpiry, directSigKeyExpiry); - } else { - primaryKeyExpiry = selfSigKeyExpiry < selfSigExpiry ? selfSigKeyExpiry : selfSigExpiry; - } - } catch (e) { - primaryKeyExpiry = null; - } - - return util.normalizeDate(primaryKeyExpiry); - } - - - /** - * Returns primary user and most significant (latest valid) self signature - * - if multiple primary users exist, returns the one with the latest self signature - * - otherwise, returns the user with the latest self signature - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} [userID] - User ID to get instead of the primary user, if it exists - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise<{ - * user: User, - * selfCertification: SignaturePacket - * }>} The primary user and the self signature - * @async - */ - async getPrimaryUser(date = new Date(), userID = {}, config = defaultConfig) { - const primaryKey = this.keyPacket; - const users = []; - let exception; - for (let i = 0; i < this.users.length; i++) { - try { - const user = this.users[i]; - if (!user.userID) { - continue; - } - if ( - (userID.name !== undefined && user.userID.name !== userID.name) || - (userID.email !== undefined && user.userID.email !== userID.email) || - (userID.comment !== undefined && user.userID.comment !== userID.comment) - ) { - throw new Error('Could not find user that matches that user ID'); - } - const dataToVerify = { userID: user.userID, key: primaryKey }; - const selfCertification = await getLatestValidSignature(user.selfCertifications, primaryKey, enums.signature.certGeneric, dataToVerify, date, config); - users.push({ index: i, user, selfCertification }); - } catch (e) { - exception = e; - } - } - if (!users.length) { - throw exception || new Error('Could not find primary user'); - } - await Promise.all(users.map(async function (a) { - return a.user.revoked || a.user.isRevoked(a.selfCertification, null, date, config); - })); - // sort by primary user flag and signature creation time - const primaryUser = users.sort(function(a, b) { - const A = a.selfCertification; - const B = b.selfCertification; - return B.revoked - A.revoked || A.isPrimaryUserID - B.isPrimaryUserID || A.created - B.created; - }).pop(); - const { user, selfCertification: cert } = primaryUser; - if (cert.revoked || await user.isRevoked(cert, null, date, config)) { - throw new Error('Primary user is revoked'); - } - return primaryUser; - } - - /** - * Update key with new components from specified key with same key ID: - * users, subkeys, certificates are merged into the destination key, - * duplicates and expired signatures are ignored. - * - * If the source key is a private key and the destination key is public, - * a private key is returned. - * @param {Key} sourceKey - Source key to merge - * @param {Date} [date] - Date to verify validity of signatures and keys - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} updated key - * @async - */ - async update(sourceKey, date = new Date(), config = defaultConfig) { - if (!this.hasSameFingerprintAs(sourceKey)) { - throw new Error('Primary key fingerprints must be equal to update the key'); - } - if (!this.isPrivate() && sourceKey.isPrivate()) { - // check for equal subkey packets - const equal = (this.subkeys.length === sourceKey.subkeys.length) && - (this.subkeys.every(destSubkey => { - return sourceKey.subkeys.some(srcSubkey => { - return destSubkey.hasSameFingerprintAs(srcSubkey); - }); - })); - if (!equal) { - throw new Error('Cannot update public key with private key if subkeys mismatch'); - } - - return sourceKey.update(this, config); - } - // from here on, either: - // - destination key is private, source key is public - // - the keys are of the same type - // hence we don't need to convert the destination key type - const updatedKey = this.clone(); - // revocation signatures - await mergeSignatures(sourceKey, updatedKey, 'revocationSignatures', date, srcRevSig => { - return isDataRevoked(updatedKey.keyPacket, enums.signature.keyRevocation, updatedKey, [srcRevSig], null, sourceKey.keyPacket, date, config); - }); - // direct signatures - await mergeSignatures(sourceKey, updatedKey, 'directSignatures', date); - // update users - await Promise.all(sourceKey.users.map(async srcUser => { - // multiple users with the same ID/attribute are not explicitly disallowed by the spec - // hence we support them, just in case - const usersToUpdate = updatedKey.users.filter(dstUser => ( - (srcUser.userID && srcUser.userID.equals(dstUser.userID)) || - (srcUser.userAttribute && srcUser.userAttribute.equals(dstUser.userAttribute)) - )); - if (usersToUpdate.length > 0) { - await Promise.all( - usersToUpdate.map(userToUpdate => userToUpdate.update(srcUser, date, config)) - ); - } else { - const newUser = srcUser.clone(); - newUser.mainKey = updatedKey; - updatedKey.users.push(newUser); - } - })); - // update subkeys - await Promise.all(sourceKey.subkeys.map(async srcSubkey => { - // multiple subkeys with same fingerprint might be preset - const subkeysToUpdate = updatedKey.subkeys.filter(dstSubkey => ( - dstSubkey.hasSameFingerprintAs(srcSubkey) - )); - if (subkeysToUpdate.length > 0) { - await Promise.all( - subkeysToUpdate.map(subkeyToUpdate => subkeyToUpdate.update(srcSubkey, date, config)) - ); - } else { - const newSubkey = srcSubkey.clone(); - newSubkey.mainKey = updatedKey; - updatedKey.subkeys.push(newSubkey); - } - })); - - return updatedKey; - } - - /** - * Get revocation certificate from a revoked key. - * (To get a revocation certificate for an unrevoked key, call revoke() first.) - * @param {Date} date - Use the given date instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} Armored revocation certificate. - * @async - */ - async getRevocationCertificate(date = new Date(), config = defaultConfig) { - const dataToVerify = { key: this.keyPacket }; - const revocationSignature = await getLatestValidSignature(this.revocationSignatures, this.keyPacket, enums.signature.keyRevocation, dataToVerify, date, config); - const packetlist = new PacketList(); - packetlist.push(revocationSignature); - return armor(enums.armor.publicKey, packetlist.write(), null, null, 'This is a revocation certificate'); - } - - /** - * Applies a revocation certificate to a key - * This adds the first signature packet in the armored text to the key, - * if it is a valid revocation signature. - * @param {String} revocationCertificate - armored revocation certificate - * @param {Date} [date] - Date to verify the certificate - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} Revoked key. - * @async - */ - async applyRevocationCertificate(revocationCertificate, date = new Date(), config = defaultConfig) { - const input = await unarmor(revocationCertificate, config); - const packetlist = await PacketList.fromBinary(input.data, allowedRevocationPackets, config); - const revocationSignature = packetlist.findPacket(enums.packet.signature); - if (!revocationSignature || revocationSignature.signatureType !== enums.signature.keyRevocation) { - throw new Error('Could not find revocation signature packet'); - } - if (!revocationSignature.issuerKeyID.equals(this.getKeyID())) { - throw new Error('Revocation signature does not match key'); - } - try { - await revocationSignature.verify(this.keyPacket, enums.signature.keyRevocation, { key: this.keyPacket }, date, undefined, config); - } catch (e) { - throw util.wrapError('Could not verify revocation signature', e); - } - const key = this.clone(); - key.revocationSignatures.push(revocationSignature); - return key; - } - - /** - * Signs primary user of key - * @param {Array} privateKeys - decrypted private keys for signing - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} [userID] - User ID to get instead of the primary user, if it exists - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} Key with new certificate signature. - * @async - */ - async signPrimaryUser(privateKeys, date, userID, config = defaultConfig) { - const { index, user } = await this.getPrimaryUser(date, userID, config); - const userSign = await user.certify(privateKeys, date, config); - const key = this.clone(); - key.users[index] = userSign; - return key; - } - - /** - * Signs all users of key - * @param {Array} privateKeys - decrypted private keys for signing - * @param {Date} [date] - Use the given date for signing, instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} Key with new certificate signature. - * @async - */ - async signAllUsers(privateKeys, date = new Date(), config = defaultConfig) { - const key = this.clone(); - key.users = await Promise.all(this.users.map(function(user) { - return user.certify(privateKeys, date, config); - })); - return key; - } - - /** - * Verifies primary user of key - * - if no arguments are given, verifies the self certificates; - * - otherwise, verifies all certificates signed with given keys. - * @param {Array} [verificationKeys] - array of keys to verify certificate signatures, instead of the primary key - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} [userID] - User ID to get instead of the primary user, if it exists - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise>} List of signer's keyID and validity of signature. - * Signature validity is null if the verification keys do not correspond to the certificate. - * @async - */ - async verifyPrimaryUser(verificationKeys, date = new Date(), userID, config = defaultConfig) { - const primaryKey = this.keyPacket; - const { user } = await this.getPrimaryUser(date, userID, config); - const results = verificationKeys ? - await user.verifyAllCertifications(verificationKeys, date, config) : - [{ keyID: primaryKey.getKeyID(), valid: await user.verify(date, config).catch(() => false) }]; - return results; - } - - /** - * Verifies all users of key - * - if no arguments are given, verifies the self certificates; - * - otherwise, verifies all certificates signed with given keys. - * @param {Array} [verificationKeys] - array of keys to verify certificate signatures - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise>} List of userID, signer's keyID and validity of signature. - * Signature validity is null if the verification keys do not correspond to the certificate. - * @async - */ - async verifyAllUsers(verificationKeys, date = new Date(), config = defaultConfig) { - const primaryKey = this.keyPacket; - const results = []; - await Promise.all(this.users.map(async user => { - const signatures = verificationKeys ? - await user.verifyAllCertifications(verificationKeys, date, config) : - [{ keyID: primaryKey.getKeyID(), valid: await user.verify(date, config).catch(() => false) }]; - - results.push(...signatures.map( - signature => ({ - userID: user.userID.userID, - keyID: signature.keyID, - valid: signature.valid - })) - ); - })); - return results; - } -} - -['getKeyID', 'getFingerprint', 'getAlgorithmInfo', 'getCreationTime', 'hasSameFingerprintAs'].forEach(name => { - Key.prototype[name] = - Subkey.prototype[name]; -}); - -/** - * Creates a PublicKey or PrivateKey depending on the packetlist in input - * @param {PacketList} - packets to parse - * @return {Key} parsed key - * @throws if no key packet was found - */ -function createKey(packetlist) { - for (const packet of packetlist) { - switch (packet.constructor.tag) { - case enums.packet.secretKey: - return new PrivateKey(packetlist); - case enums.packet.publicKey: - return new PublicKey(packetlist); - } - } - throw new Error('No key packet found'); -} - -// This library is free software; you can redistribute it and/or - -/** - * Class that represents an OpenPGP Public Key - */ -class PublicKey extends Key { - /** - * @param {PacketList} packetlist - The packets that form this key - */ - constructor(packetlist) { - super(); - this.keyPacket = null; - this.revocationSignatures = []; - this.directSignatures = []; - this.users = []; - this.subkeys = []; - if (packetlist) { - this.packetListToStructure(packetlist, new Set([enums.packet.secretKey, enums.packet.secretSubkey])); - if (!this.keyPacket) { - throw new Error('Invalid key: missing public-key packet'); - } - } - } - - /** - * Returns true if this is a private key - * @returns {false} - */ - isPrivate() { - return false; - } - - /** - * Returns key as public key (shallow copy) - * @returns {PublicKey} New public Key - */ - toPublic() { - return this; - } - - /** - * Returns ASCII armored text of key - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {ReadableStream} ASCII armor. - */ - armor(config = defaultConfig) { - return armor(enums.armor.publicKey, this.toPacketList().write(), undefined, undefined, undefined, config); - } -} - -/** - * Class that represents an OpenPGP Private key - */ -class PrivateKey extends PublicKey { - /** - * @param {PacketList} packetlist - The packets that form this key - */ - constructor(packetlist) { - super(); - this.packetListToStructure(packetlist, new Set([enums.packet.publicKey, enums.packet.publicSubkey])); - if (!this.keyPacket) { - throw new Error('Invalid key: missing private-key packet'); - } - } - - /** - * Returns true if this is a private key - * @returns {Boolean} - */ - isPrivate() { - return true; - } - - /** - * Returns key as public key (shallow copy) - * @returns {PublicKey} New public Key - */ - toPublic() { - const packetlist = new PacketList(); - const keyPackets = this.toPacketList(); - for (const keyPacket of keyPackets) { - switch (keyPacket.constructor.tag) { - case enums.packet.secretKey: { - const pubKeyPacket = PublicKeyPacket.fromSecretKeyPacket(keyPacket); - packetlist.push(pubKeyPacket); - break; - } - case enums.packet.secretSubkey: { - const pubSubkeyPacket = PublicSubkeyPacket.fromSecretSubkeyPacket(keyPacket); - packetlist.push(pubSubkeyPacket); - break; - } - default: - packetlist.push(keyPacket); - } - } - return new PublicKey(packetlist); - } - - /** - * Returns ASCII armored text of key - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {ReadableStream} ASCII armor. - */ - armor(config = defaultConfig) { - return armor(enums.armor.privateKey, this.toPacketList().write(), undefined, undefined, undefined, config); - } - - /** - * Returns all keys that are available for decryption, matching the keyID when given - * This is useful to retrieve keys for session key decryption - * @param {module:type/keyid~KeyID} keyID, optional - * @param {Date} date, optional - * @param {String} userID, optional - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise>} Array of decryption keys. - * @async - */ - async getDecryptionKeys(keyID, date = new Date(), userID = {}, config = defaultConfig) { - const primaryKey = this.keyPacket; - const keys = []; - for (let i = 0; i < this.subkeys.length; i++) { - if (!keyID || this.subkeys[i].getKeyID().equals(keyID, true)) { - try { - const dataToVerify = { key: primaryKey, bind: this.subkeys[i].keyPacket }; - const bindingSignature = await getLatestValidSignature(this.subkeys[i].bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); - if (isValidDecryptionKeyPacket(bindingSignature, config)) { - keys.push(this.subkeys[i]); - } - } catch (e) {} - } - } - - // evaluate primary key - const primaryUser = await this.getPrimaryUser(date, userID, config); - if ((!keyID || primaryKey.getKeyID().equals(keyID, true)) && - isValidDecryptionKeyPacket(primaryUser.selfCertification, config)) { - keys.push(this); - } - - return keys; - } - - /** - * Returns true if the primary key or any subkey is decrypted. - * A dummy key is considered encrypted. - */ - isDecrypted() { - return this.getKeys().some(({ keyPacket }) => keyPacket.isDecrypted()); - } - - /** - * Check whether the private and public primary key parameters correspond - * Together with verification of binding signatures, this guarantees key integrity - * In case of gnu-dummy primary key, it is enough to validate any signing subkeys - * otherwise all encryption subkeys are validated - * If only gnu-dummy keys are found, we cannot properly validate so we throw an error - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if validation was not successful and the key cannot be trusted - * @async - */ - async validate(config = defaultConfig) { - if (!this.isPrivate()) { - throw new Error('Cannot validate a public key'); - } - - let signingKeyPacket; - if (!this.keyPacket.isDummy()) { - signingKeyPacket = this.keyPacket; - } else { - /** - * It is enough to validate any signing keys - * since its binding signatures are also checked - */ - const signingKey = await this.getSigningKey(null, null, undefined, { ...config, rejectPublicKeyAlgorithms: new Set(), minRSABits: 0 }); - // This could again be a dummy key - if (signingKey && !signingKey.keyPacket.isDummy()) { - signingKeyPacket = signingKey.keyPacket; - } - } - - if (signingKeyPacket) { - return signingKeyPacket.validate(); - } else { - const keys = this.getKeys(); - const allDummies = keys.map(key => key.keyPacket.isDummy()).every(Boolean); - if (allDummies) { - throw new Error('Cannot validate an all-gnu-dummy key'); - } - - return Promise.all(keys.map(async key => key.keyPacket.validate())); - } - } - - /** - * Clear private key parameters - */ - clearPrivateParams() { - this.getKeys().forEach(({ keyPacket }) => { - if (keyPacket.isDecrypted()) { - keyPacket.clearPrivateParams(); - } - }); - } - - /** - * Revokes the key - * @param {Object} reasonForRevocation - optional, object indicating the reason for revocation - * @param {module:enums.reasonForRevocation} reasonForRevocation.flag optional, flag indicating the reason for revocation - * @param {String} reasonForRevocation.string optional, string explaining the reason for revocation - * @param {Date} date - optional, override the creationtime of the revocation signature - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New key with revocation signature. - * @async - */ - async revoke( - { - flag: reasonForRevocationFlag = enums.reasonForRevocation.noReason, - string: reasonForRevocationString = '' - } = {}, - date = new Date(), - config = defaultConfig - ) { - if (!this.isPrivate()) { - throw new Error('Need private key for revoking'); - } - const dataToSign = { key: this.keyPacket }; - const key = this.clone(); - key.revocationSignatures.push(await createSignaturePacket(dataToSign, null, this.keyPacket, { - signatureType: enums.signature.keyRevocation, - reasonForRevocationFlag: enums.write(enums.reasonForRevocation, reasonForRevocationFlag), - reasonForRevocationString - }, date, undefined, undefined, config)); - return key; - } - - - /** - * Generates a new OpenPGP subkey, and returns a clone of the Key object with the new subkey added. - * Supports RSA and ECC keys. Defaults to the algorithm and bit size/curve of the primary key. DSA primary keys default to RSA subkeys. - * @param {ecc|rsa} options.type The subkey algorithm: ECC or RSA - * @param {String} options.curve (optional) Elliptic curve for ECC keys - * @param {Integer} options.rsaBits (optional) Number of bits for RSA subkeys - * @param {Number} options.keyExpirationTime (optional) Number of seconds from the key creation time after which the key expires - * @param {Date} options.date (optional) Override the creation date of the key and the key signatures - * @param {Boolean} options.sign (optional) Indicates whether the subkey should sign rather than encrypt. Defaults to false - * @param {Object} options.config (optional) custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} - * @async - */ - async addSubkey(options = {}) { - const config = { ...defaultConfig, ...options.config }; - if (options.passphrase) { - throw new Error('Subkey could not be encrypted here, please encrypt whole key'); - } - if (options.rsaBits < config.minRSABits) { - throw new Error(`rsaBits should be at least ${config.minRSABits}, got: ${options.rsaBits}`); - } - const secretKeyPacket = this.keyPacket; - if (secretKeyPacket.isDummy()) { - throw new Error('Cannot add subkey to gnu-dummy primary key'); - } - if (!secretKeyPacket.isDecrypted()) { - throw new Error('Key is not decrypted'); - } - const defaultOptions = secretKeyPacket.getAlgorithmInfo(); - defaultOptions.type = defaultOptions.curve ? 'ecc' : 'rsa'; // DSA keys default to RSA - defaultOptions.rsaBits = defaultOptions.bits || 4096; - defaultOptions.curve = defaultOptions.curve || 'curve25519'; - options = sanitizeKeyOptions(options, defaultOptions); - const keyPacket = await generateSecretSubkey(options); - checkKeyRequirements(keyPacket, config); - const bindingSignature = await createBindingSignature(keyPacket, secretKeyPacket, options, config); - const packetList = this.toPacketList(); - packetList.push(keyPacket, bindingSignature); - return new PrivateKey(packetList); - } -} - -// OpenPGP.js - An OpenPGP implementation in javascript - -// A Key can contain the following packets -const allowedKeyPackets = /*#__PURE__*/ util.constructAllowedPackets([ - PublicKeyPacket, - PublicSubkeyPacket, - SecretKeyPacket, - SecretSubkeyPacket, - UserIDPacket, - UserAttributePacket, - SignaturePacket -]); - -/** - * Generates a new OpenPGP key. Supports RSA and ECC keys. - * By default, primary and subkeys will be of same type. - * @param {ecc|rsa} options.type The primary key algorithm type: ECC or RSA - * @param {String} options.curve Elliptic curve for ECC keys - * @param {Integer} options.rsaBits Number of bits for RSA keys - * @param {Array} options.userIDs User IDs as strings or objects: 'Jo Doe ' or { name:'Jo Doe', email:'info@jo.com' } - * @param {String} options.passphrase Passphrase used to encrypt the resulting private key - * @param {Number} options.keyExpirationTime (optional) Number of seconds from the key creation time after which the key expires - * @param {Date} options.date Creation date of the key and the key signatures - * @param {Object} config - Full configuration - * @param {Array} options.subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}] - * sign parameter defaults to false, and indicates whether the subkey should sign rather than encrypt - * @returns {Promise<{{ key: PrivateKey, revocationCertificate: String }}>} - * @async - * @static - * @private - */ -async function generate$2(options, config) { - options.sign = true; // primary key is always a signing key - options = sanitizeKeyOptions(options); - options.subkeys = options.subkeys.map((subkey, index) => sanitizeKeyOptions(options.subkeys[index], options)); - let promises = [generateSecretKey(options, config)]; - promises = promises.concat(options.subkeys.map(options => generateSecretSubkey(options, config))); - const packets = await Promise.all(promises); - - const key = await wrapKeyObject(packets[0], packets.slice(1), options, config); - const revocationCertificate = await key.getRevocationCertificate(options.date, config); - key.revocationSignatures = []; - return { key, revocationCertificate }; -} - -/** - * Reformats and signs an OpenPGP key with a given User ID. Currently only supports RSA keys. - * @param {PrivateKey} options.privateKey The private key to reformat - * @param {Array} options.userIDs User IDs as strings or objects: 'Jo Doe ' or { name:'Jo Doe', email:'info@jo.com' } - * @param {String} options.passphrase Passphrase used to encrypt the resulting private key - * @param {Number} options.keyExpirationTime Number of seconds from the key creation time after which the key expires - * @param {Date} options.date Override the creation date of the key signatures - * @param {Array} options.subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}] - * @param {Object} config - Full configuration - * - * @returns {Promise<{{ key: PrivateKey, revocationCertificate: String }}>} - * @async - * @static - * @private - */ -async function reformat(options, config) { - options = sanitize(options); - const { privateKey } = options; - - if (!privateKey.isPrivate()) { - throw new Error('Cannot reformat a public key'); - } - - if (privateKey.keyPacket.isDummy()) { - throw new Error('Cannot reformat a gnu-dummy primary key'); - } - - const isDecrypted = privateKey.getKeys().every(({ keyPacket }) => keyPacket.isDecrypted()); - if (!isDecrypted) { - throw new Error('Key is not decrypted'); - } - - const secretKeyPacket = privateKey.keyPacket; - - if (!options.subkeys) { - options.subkeys = await Promise.all(privateKey.subkeys.map(async subkey => { - const secretSubkeyPacket = subkey.keyPacket; - const dataToVerify = { key: secretKeyPacket, bind: secretSubkeyPacket }; - const bindingSignature = await ( - getLatestValidSignature(subkey.bindingSignatures, secretKeyPacket, enums.signature.subkeyBinding, dataToVerify, null, config) - ).catch(() => ({})); - return { - sign: bindingSignature.keyFlags && (bindingSignature.keyFlags[0] & enums.keyFlags.signData) - }; - })); - } - - const secretSubkeyPackets = privateKey.subkeys.map(subkey => subkey.keyPacket); - if (options.subkeys.length !== secretSubkeyPackets.length) { - throw new Error('Number of subkey options does not match number of subkeys'); - } - - options.subkeys = options.subkeys.map(subkeyOptions => sanitize(subkeyOptions, options)); - - const key = await wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options, config); - const revocationCertificate = await key.getRevocationCertificate(options.date, config); - key.revocationSignatures = []; - return { key, revocationCertificate }; - - function sanitize(options, subkeyDefaults = {}) { - options.keyExpirationTime = options.keyExpirationTime || subkeyDefaults.keyExpirationTime; - options.passphrase = util.isString(options.passphrase) ? options.passphrase : subkeyDefaults.passphrase; - options.date = options.date || subkeyDefaults.date; - - return options; - } -} - -/** - * Construct PrivateKey object from the given key packets, add certification signatures and set passphrase protection - * The new key includes a revocation certificate that must be removed before returning the key, otherwise the key is considered revoked. - * @param {SecretKeyPacket} secretKeyPacket - * @param {SecretSubkeyPacket} secretSubkeyPackets - * @param {Object} options - * @param {Object} config - Full configuration - * @returns {PrivateKey} - */ -async function wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options, config) { - // set passphrase protection - if (options.passphrase) { - await secretKeyPacket.encrypt(options.passphrase, config); - } - - await Promise.all(secretSubkeyPackets.map(async function(secretSubkeyPacket, index) { - const subkeyPassphrase = options.subkeys[index].passphrase; - if (subkeyPassphrase) { - await secretSubkeyPacket.encrypt(subkeyPassphrase, config); - } - })); - - const packetlist = new PacketList(); - packetlist.push(secretKeyPacket); - - await Promise.all(options.userIDs.map(async function(userID, index) { - function createPreferredAlgos(algos, preferredAlgo) { - return [preferredAlgo, ...algos.filter(algo => algo !== preferredAlgo)]; - } - - const userIDPacket = UserIDPacket.fromObject(userID); - const dataToSign = {}; - dataToSign.userID = userIDPacket; - dataToSign.key = secretKeyPacket; - const signaturePacket = new SignaturePacket(); - signaturePacket.signatureType = enums.signature.certGeneric; - signaturePacket.publicKeyAlgorithm = secretKeyPacket.algorithm; - signaturePacket.hashAlgorithm = await getPreferredHashAlgo$1(null, secretKeyPacket, undefined, undefined, config); - signaturePacket.keyFlags = [enums.keyFlags.certifyKeys | enums.keyFlags.signData]; - signaturePacket.preferredSymmetricAlgorithms = createPreferredAlgos([ - // prefer aes256, aes128, then aes192 (no WebCrypto support: https://www.chromium.org/blink/webcrypto#TOC-AES-support) - enums.symmetric.aes256, - enums.symmetric.aes128, - enums.symmetric.aes192 - ], config.preferredSymmetricAlgorithm); - if (config.aeadProtect) { - signaturePacket.preferredAEADAlgorithms = createPreferredAlgos([ - enums.aead.eax, - enums.aead.ocb - ], config.preferredAEADAlgorithm); - } - signaturePacket.preferredHashAlgorithms = createPreferredAlgos([ - // prefer fast asm.js implementations (SHA-256) - enums.hash.sha256, - enums.hash.sha512 - ], config.preferredHashAlgorithm); - signaturePacket.preferredCompressionAlgorithms = createPreferredAlgos([ - enums.compression.zlib, - enums.compression.zip, - enums.compression.uncompressed - ], config.preferredCompressionAlgorithm); - if (index === 0) { - signaturePacket.isPrimaryUserID = true; - } - // integrity protection always enabled - signaturePacket.features = [0]; - signaturePacket.features[0] |= enums.features.modificationDetection; - if (config.aeadProtect) { - signaturePacket.features[0] |= enums.features.aead; - } - if (config.v5Keys) { - signaturePacket.features[0] |= enums.features.v5Keys; - } - if (options.keyExpirationTime > 0) { - signaturePacket.keyExpirationTime = options.keyExpirationTime; - signaturePacket.keyNeverExpires = false; - } - await signaturePacket.sign(secretKeyPacket, dataToSign, options.date); - - return { userIDPacket, signaturePacket }; - })).then(list => { - list.forEach(({ userIDPacket, signaturePacket }) => { - packetlist.push(userIDPacket); - packetlist.push(signaturePacket); - }); - }); - - await Promise.all(secretSubkeyPackets.map(async function(secretSubkeyPacket, index) { - const subkeyOptions = options.subkeys[index]; - const subkeySignaturePacket = await createBindingSignature(secretSubkeyPacket, secretKeyPacket, subkeyOptions, config); - return { secretSubkeyPacket, subkeySignaturePacket }; - })).then(packets => { - packets.forEach(({ secretSubkeyPacket, subkeySignaturePacket }) => { - packetlist.push(secretSubkeyPacket); - packetlist.push(subkeySignaturePacket); - }); - }); - - // Add revocation signature packet for creating a revocation certificate. - // This packet should be removed before returning the key. - const dataToSign = { key: secretKeyPacket }; - packetlist.push(await createSignaturePacket(dataToSign, null, secretKeyPacket, { - signatureType: enums.signature.keyRevocation, - reasonForRevocationFlag: enums.reasonForRevocation.noReason, - reasonForRevocationString: '' - }, options.date, undefined, undefined, config)); - - if (options.passphrase) { - secretKeyPacket.clearPrivateParams(); - } - - await Promise.all(secretSubkeyPackets.map(async function(secretSubkeyPacket, index) { - const subkeyPassphrase = options.subkeys[index].passphrase; - if (subkeyPassphrase) { - secretSubkeyPacket.clearPrivateParams(); - } - })); - - return new PrivateKey(packetlist); -} - -/** - * Reads an (optionally armored) OpenPGP key and returns a key object - * @param {Object} options - * @param {String} [options.armoredKey] - Armored key to be parsed - * @param {Uint8Array} [options.binaryKey] - Binary key to be parsed - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} Key object. - * @async - * @static - */ -async function readKey({ armoredKey, binaryKey, config, ...rest }) { - config = { ...defaultConfig, ...config }; - if (!armoredKey && !binaryKey) { - throw new Error('readKey: must pass options object containing `armoredKey` or `binaryKey`'); - } - if (armoredKey && !util.isString(armoredKey)) { - throw new Error('readKey: options.armoredKey must be a string'); - } - if (binaryKey && !util.isUint8Array(binaryKey)) { - throw new Error('readKey: options.binaryKey must be a Uint8Array'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - let input; - if (armoredKey) { - const { type, data } = await unarmor(armoredKey, config); - if (!(type === enums.armor.publicKey || type === enums.armor.privateKey)) { - throw new Error('Armored text not of type key'); - } - input = data; - } else { - input = binaryKey; - } - const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); - return createKey(packetlist); -} - -/** - * Reads an (optionally armored) OpenPGP private key and returns a PrivateKey object - * @param {Object} options - * @param {String} [options.armoredKey] - Armored key to be parsed - * @param {Uint8Array} [options.binaryKey] - Binary key to be parsed - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} Key object. - * @async - * @static - */ -async function readPrivateKey({ armoredKey, binaryKey, config, ...rest }) { - config = { ...defaultConfig, ...config }; - if (!armoredKey && !binaryKey) { - throw new Error('readPrivateKey: must pass options object containing `armoredKey` or `binaryKey`'); - } - if (armoredKey && !util.isString(armoredKey)) { - throw new Error('readPrivateKey: options.armoredKey must be a string'); - } - if (binaryKey && !util.isUint8Array(binaryKey)) { - throw new Error('readPrivateKey: options.binaryKey must be a Uint8Array'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - let input; - if (armoredKey) { - const { type, data } = await unarmor(armoredKey, config); - if (!(type === enums.armor.privateKey)) { - throw new Error('Armored text not of type private key'); - } - input = data; - } else { - input = binaryKey; - } - const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); - return new PrivateKey(packetlist); -} - -/** - * Reads an (optionally armored) OpenPGP key block and returns a list of key objects - * @param {Object} options - * @param {String} [options.armoredKeys] - Armored keys to be parsed - * @param {Uint8Array} [options.binaryKeys] - Binary keys to be parsed - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise>} Key objects. - * @async - * @static - */ -async function readKeys({ armoredKeys, binaryKeys, config, ...rest }) { - config = { ...defaultConfig, ...config }; - let input = armoredKeys || binaryKeys; - if (!input) { - throw new Error('readKeys: must pass options object containing `armoredKeys` or `binaryKeys`'); - } - if (armoredKeys && !util.isString(armoredKeys)) { - throw new Error('readKeys: options.armoredKeys must be a string'); - } - if (binaryKeys && !util.isUint8Array(binaryKeys)) { - throw new Error('readKeys: options.binaryKeys must be a Uint8Array'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (armoredKeys) { - const { type, data } = await unarmor(armoredKeys, config); - if (type !== enums.armor.publicKey && type !== enums.armor.privateKey) { - throw new Error('Armored text not of type key'); - } - input = data; - } - const keys = []; - const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); - const keyIndex = packetlist.indexOfTag(enums.packet.publicKey, enums.packet.secretKey); - if (keyIndex.length === 0) { - throw new Error('No key packet found'); - } - for (let i = 0; i < keyIndex.length; i++) { - const oneKeyList = packetlist.slice(keyIndex[i], keyIndex[i + 1]); - const newKey = createKey(oneKeyList); - keys.push(newKey); - } - return keys; -} - -/** - * Reads an (optionally armored) OpenPGP private key block and returns a list of PrivateKey objects - * @param {Object} options - * @param {String} [options.armoredKeys] - Armored keys to be parsed - * @param {Uint8Array} [options.binaryKeys] - Binary keys to be parsed - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise>} Key objects. - * @async - * @static - */ -async function readPrivateKeys({ armoredKeys, binaryKeys, config }) { - config = { ...defaultConfig, ...config }; - let input = armoredKeys || binaryKeys; - if (!input) { - throw new Error('readPrivateKeys: must pass options object containing `armoredKeys` or `binaryKeys`'); - } - if (armoredKeys && !util.isString(armoredKeys)) { - throw new Error('readPrivateKeys: options.armoredKeys must be a string'); - } - if (binaryKeys && !util.isUint8Array(binaryKeys)) { - throw new Error('readPrivateKeys: options.binaryKeys must be a Uint8Array'); - } - if (armoredKeys) { - const { type, data } = await unarmor(armoredKeys, config); - if (type !== enums.armor.privateKey) { - throw new Error('Armored text not of type private key'); - } - input = data; - } - const keys = []; - const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); - const keyIndex = packetlist.indexOfTag(enums.packet.secretKey); - if (keyIndex.length === 0) { - throw new Error('No secret key packet found'); - } - for (let i = 0; i < keyIndex.length; i++) { - const oneKeyList = packetlist.slice(keyIndex[i], keyIndex[i + 1]); - const newKey = new PrivateKey(oneKeyList); - keys.push(newKey); - } - return keys; -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -// A Message can contain the following packets -const allowedMessagePackets = /*#__PURE__*/ util.constructAllowedPackets([ - LiteralDataPacket, - CompressedDataPacket, - AEADEncryptedDataPacket, - SymEncryptedIntegrityProtectedDataPacket, - SymmetricallyEncryptedDataPacket, - PublicKeyEncryptedSessionKeyPacket, - SymEncryptedSessionKeyPacket, - OnePassSignaturePacket, - SignaturePacket -]); -// A SKESK packet can contain the following packets -const allowedSymSessionKeyPackets = /*#__PURE__*/ util.constructAllowedPackets([SymEncryptedSessionKeyPacket]); -// A detached signature can contain the following packets -const allowedDetachedSignaturePackets = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); - -/** - * Class that represents an OpenPGP message. - * Can be an encrypted message, signed message, compressed message or literal message - * See {@link https://tools.ietf.org/html/rfc4880#section-11.3} - */ -class Message { - /** - * @param {PacketList} packetlist - The packets that form this message - */ - constructor(packetlist) { - this.packets = packetlist || new PacketList(); - } - - /** - * Returns the key IDs of the keys to which the session key is encrypted - * @returns {Array} Array of keyID objects. - */ - getEncryptionKeyIDs() { - const keyIDs = []; - const pkESKeyPacketlist = this.packets.filterByTag(enums.packet.publicKeyEncryptedSessionKey); - pkESKeyPacketlist.forEach(function(packet) { - keyIDs.push(packet.publicKeyID); - }); - return keyIDs; - } - - /** - * Returns the key IDs of the keys that signed the message - * @returns {Array} Array of keyID objects. - */ - getSigningKeyIDs() { - const msg = this.unwrapCompressed(); - // search for one pass signatures - const onePassSigList = msg.packets.filterByTag(enums.packet.onePassSignature); - if (onePassSigList.length > 0) { - return onePassSigList.map(packet => packet.issuerKeyID); - } - // if nothing found look for signature packets - const signatureList = msg.packets.filterByTag(enums.packet.signature); - return signatureList.map(packet => packet.issuerKeyID); - } - - /** - * Decrypt the message. Either a private key, a session key, or a password must be specified. - * @param {Array} [decryptionKeys] - Private keys with decrypted secret data - * @param {Array} [passwords] - Passwords used to decrypt - * @param {Array} [sessionKeys] - Session keys in the form: { data:Uint8Array, algorithm:String, [aeadAlgorithm:String] } - * @param {Date} [date] - Use the given date for key verification instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New message with decrypted content. - * @async - */ - async decrypt(decryptionKeys, passwords, sessionKeys, date = new Date(), config = defaultConfig) { - const sessionKeyObjects = sessionKeys || await this.decryptSessionKeys(decryptionKeys, passwords, date, config); - - const symEncryptedPacketlist = this.packets.filterByTag( - enums.packet.symmetricallyEncryptedData, - enums.packet.symEncryptedIntegrityProtectedData, - enums.packet.aeadEncryptedData - ); - - if (symEncryptedPacketlist.length === 0) { - return this; - } - - const symEncryptedPacket = symEncryptedPacketlist[0]; - let exception = null; - const decryptedPromise = Promise.all(sessionKeyObjects.map(async ({ algorithm: algorithmName, data }) => { - if (!util.isUint8Array(data) || !util.isString(algorithmName)) { - throw new Error('Invalid session key for decryption.'); - } - - try { - const algo = enums.write(enums.symmetric, algorithmName); - await symEncryptedPacket.decrypt(algo, data, config); - } catch (e) { - util.printDebugError(e); - exception = e; - } - })); - // We don't await stream.cancel here because it only returns when the other copy is canceled too. - cancel(symEncryptedPacket.encrypted); // Don't keep copy of encrypted data in memory. - symEncryptedPacket.encrypted = null; - await decryptedPromise; - - if (!symEncryptedPacket.packets || !symEncryptedPacket.packets.length) { - throw exception || new Error('Decryption failed.'); - } - - const resultMsg = new Message(symEncryptedPacket.packets); - symEncryptedPacket.packets = new PacketList(); // remove packets after decryption - - return resultMsg; - } - - /** - * Decrypt encrypted session keys either with private keys or passwords. - * @param {Array} [decryptionKeys] - Private keys with decrypted secret data - * @param {Array} [passwords] - Passwords used to decrypt - * @param {Date} [date] - Use the given date for key verification, instead of current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise>} array of object with potential sessionKey, algorithm pairs - * @async - */ - async decryptSessionKeys(decryptionKeys, passwords, date = new Date(), config = defaultConfig) { - let decryptedSessionKeyPackets = []; - - let exception; - if (passwords) { - const skeskPackets = this.packets.filterByTag(enums.packet.symEncryptedSessionKey); - if (skeskPackets.length === 0) { - throw new Error('No symmetrically encrypted session key packet found.'); - } - await Promise.all(passwords.map(async function(password, i) { - let packets; - if (i) { - packets = await PacketList.fromBinary(skeskPackets.write(), allowedSymSessionKeyPackets, config); - } else { - packets = skeskPackets; - } - await Promise.all(packets.map(async function(skeskPacket) { - try { - await skeskPacket.decrypt(password); - decryptedSessionKeyPackets.push(skeskPacket); - } catch (err) { - util.printDebugError(err); - } - })); - })); - } else if (decryptionKeys) { - const pkeskPackets = this.packets.filterByTag(enums.packet.publicKeyEncryptedSessionKey); - if (pkeskPackets.length === 0) { - throw new Error('No public key encrypted session key packet found.'); - } - await Promise.all(pkeskPackets.map(async function(pkeskPacket) { - await Promise.all(decryptionKeys.map(async function(decryptionKey) { - let algos = [ - enums.symmetric.aes256, // Old OpenPGP.js default fallback - enums.symmetric.aes128, // RFC4880bis fallback - enums.symmetric.tripledes, // RFC4880 fallback - enums.symmetric.cast5 // Golang OpenPGP fallback - ]; - try { - const primaryUser = await decryptionKey.getPrimaryUser(date, undefined, config); // TODO: Pass userID from somewhere. - if (primaryUser.selfCertification.preferredSymmetricAlgorithms) { - algos = algos.concat(primaryUser.selfCertification.preferredSymmetricAlgorithms); - } - } catch (e) {} - - // do not check key expiration to allow decryption of old messages - const decryptionKeyPackets = (await decryptionKey.getDecryptionKeys(pkeskPacket.publicKeyID, null, undefined, config)).map(key => key.keyPacket); - await Promise.all(decryptionKeyPackets.map(async function(decryptionKeyPacket) { - if (!decryptionKeyPacket || decryptionKeyPacket.isDummy()) { - return; - } - if (!decryptionKeyPacket.isDecrypted()) { - throw new Error('Decryption key is not decrypted.'); - } - - // To hinder CCA attacks against PKCS1, we carry out a constant-time decryption flow if the `constantTimePKCS1Decryption` config option is set. - const doConstantTimeDecryption = config.constantTimePKCS1Decryption && ( - pkeskPacket.publicKeyAlgorithm === enums.publicKey.rsaEncrypt || - pkeskPacket.publicKeyAlgorithm === enums.publicKey.rsaEncryptSign || - pkeskPacket.publicKeyAlgorithm === enums.publicKey.rsaSign || - pkeskPacket.publicKeyAlgorithm === enums.publicKey.elgamal - ); - - if (doConstantTimeDecryption) { - // The goal is to not reveal whether PKESK decryption (specifically the PKCS1 decoding step) failed, hence, we always proceed to decrypt the message, - // either with the successfully decrypted session key, or with a randomly generated one. - // Since the SEIP/AEAD's symmetric algorithm and key size are stored in the encrypted portion of the PKESK, and the execution flow cannot depend on - // the decrypted payload, we always assume the message to be encrypted with one of the symmetric algorithms specified in `config.constantTimePKCS1DecryptionSupportedSymmetricAlgorithms`: - // - If the PKESK decryption succeeds, and the session key cipher is in the supported set, then we try to decrypt the data with the decrypted session key as well as with the - // randomly generated keys of the remaining key types. - // - If the PKESK decryptions fails, or if it succeeds but support for the cipher is not enabled, then we discard the session key and try to decrypt the data using only the randomly - // generated session keys. - // NB: as a result, if the data is encrypted with a non-suported cipher, decryption will always fail. - - const serialisedPKESK = pkeskPacket.write(); // make copies to be able to decrypt the PKESK packet multiple times - await Promise.all(Array.from(config.constantTimePKCS1DecryptionSupportedSymmetricAlgorithms).map(async sessionKeyAlgorithm => { - const pkeskPacketCopy = new PublicKeyEncryptedSessionKeyPacket(); - pkeskPacketCopy.read(serialisedPKESK); - const randomSessionKey = { - sessionKeyAlgorithm, - sessionKey: await mod.generateSessionKey(sessionKeyAlgorithm) - }; - try { - await pkeskPacketCopy.decrypt(decryptionKeyPacket, randomSessionKey); - decryptedSessionKeyPackets.push(pkeskPacketCopy); - } catch (err) { - // `decrypt` can still throw some non-security-sensitive errors - util.printDebugError(err); - exception = err; - } - })); - - } else { - try { - await pkeskPacket.decrypt(decryptionKeyPacket); - if (!algos.includes(enums.write(enums.symmetric, pkeskPacket.sessionKeyAlgorithm))) { - throw new Error('A non-preferred symmetric algorithm was used.'); - } - decryptedSessionKeyPackets.push(pkeskPacket); - } catch (err) { - util.printDebugError(err); - exception = err; - } - } - })); - })); - cancel(pkeskPacket.encrypted); // Don't keep copy of encrypted data in memory. - pkeskPacket.encrypted = null; - })); - } else { - throw new Error('No key or password specified.'); - } - - if (decryptedSessionKeyPackets.length > 0) { - // Return only unique session keys - if (decryptedSessionKeyPackets.length > 1) { - const seen = new Set(); - decryptedSessionKeyPackets = decryptedSessionKeyPackets.filter(item => { - const k = item.sessionKeyAlgorithm + util.uint8ArrayToString(item.sessionKey); - if (seen.has(k)) { - return false; - } - seen.add(k); - return true; - }); - } - - return decryptedSessionKeyPackets.map(packet => ({ - data: packet.sessionKey, - algorithm: enums.read(enums.symmetric, packet.sessionKeyAlgorithm) - })); - } - throw exception || new Error('Session key decryption failed.'); - } - - /** - * Get literal data that is the body of the message - * @returns {(Uint8Array|null)} Literal body of the message as Uint8Array. - */ - getLiteralData() { - const msg = this.unwrapCompressed(); - const literal = msg.packets.findPacket(enums.packet.literalData); - return (literal && literal.getBytes()) || null; - } - - /** - * Get filename from literal data packet - * @returns {(String|null)} Filename of literal data packet as string. - */ - getFilename() { - const msg = this.unwrapCompressed(); - const literal = msg.packets.findPacket(enums.packet.literalData); - return (literal && literal.getFilename()) || null; - } - - /** - * Get literal data as text - * @returns {(String|null)} Literal body of the message interpreted as text. - */ - getText() { - const msg = this.unwrapCompressed(); - const literal = msg.packets.findPacket(enums.packet.literalData); - if (literal) { - return literal.getText(); - } - return null; - } - - /** - * Generate a new session key object, taking the algorithm preferences of the passed encryption keys into account, if any. - * @param {Array} [encryptionKeys] - Public key(s) to select algorithm preferences for - * @param {Date} [date] - Date to select algorithm preferences at - * @param {Array} [userIDs] - User IDs to select algorithm preferences for - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise<{ data: Uint8Array, algorithm: String, aeadAlgorithm: undefined|String }>} Object with session key data and algorithms. - * @async - */ - static async generateSessionKey(encryptionKeys = [], date = new Date(), userIDs = [], config = defaultConfig) { - const algo = await getPreferredAlgo('symmetric', encryptionKeys, date, userIDs, config); - const algorithmName = enums.read(enums.symmetric, algo); - const aeadAlgorithmName = config.aeadProtect && await isAEADSupported(encryptionKeys, date, userIDs, config) ? - enums.read(enums.aead, await getPreferredAlgo('aead', encryptionKeys, date, userIDs, config)) : - undefined; - - const sessionKeyData = await mod.generateSessionKey(algo); - return { data: sessionKeyData, algorithm: algorithmName, aeadAlgorithm: aeadAlgorithmName }; - } - - /** - * Encrypt the message either with public keys, passwords, or both at once. - * @param {Array} [encryptionKeys] - Public key(s) for message encryption - * @param {Array} [passwords] - Password(s) for message encryption - * @param {Object} [sessionKey] - Session key in the form: { data:Uint8Array, algorithm:String, [aeadAlgorithm:String] } - * @param {Boolean} [wildcard] - Use a key ID of 0 instead of the public key IDs - * @param {Array} [encryptionKeyIDs] - Array of key IDs to use for encryption. Each encryptionKeyIDs[i] corresponds to keys[i] - * @param {Date} [date] - Override the creation date of the literal package - * @param {Array} [userIDs] - User IDs to encrypt for, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }] - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New message with encrypted content. - * @async - */ - async encrypt(encryptionKeys, passwords, sessionKey, wildcard = false, encryptionKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { - if (sessionKey) { - if (!util.isUint8Array(sessionKey.data) || !util.isString(sessionKey.algorithm)) { - throw new Error('Invalid session key for encryption.'); - } - } else if (encryptionKeys && encryptionKeys.length) { - sessionKey = await Message.generateSessionKey(encryptionKeys, date, userIDs, config); - } else if (passwords && passwords.length) { - sessionKey = await Message.generateSessionKey(undefined, undefined, undefined, config); - } else { - throw new Error('No keys, passwords, or session key provided.'); - } - - const { data: sessionKeyData, algorithm: algorithmName, aeadAlgorithm: aeadAlgorithmName } = sessionKey; - - const msg = await Message.encryptSessionKey(sessionKeyData, algorithmName, aeadAlgorithmName, encryptionKeys, passwords, wildcard, encryptionKeyIDs, date, userIDs, config); - - let symEncryptedPacket; - if (aeadAlgorithmName) { - symEncryptedPacket = new AEADEncryptedDataPacket(); - symEncryptedPacket.aeadAlgorithm = enums.write(enums.aead, aeadAlgorithmName); - } else { - symEncryptedPacket = new SymEncryptedIntegrityProtectedDataPacket(); - } - symEncryptedPacket.packets = this.packets; - - const algorithm = enums.write(enums.symmetric, algorithmName); - await symEncryptedPacket.encrypt(algorithm, sessionKeyData, config); - - msg.packets.push(symEncryptedPacket); - symEncryptedPacket.packets = new PacketList(); // remove packets after encryption - return msg; - } - - /** - * Encrypt a session key either with public keys, passwords, or both at once. - * @param {Uint8Array} sessionKey - session key for encryption - * @param {String} algorithmName - session key algorithm - * @param {String} [aeadAlgorithmName] - AEAD algorithm, e.g. 'eax' or 'ocb' - * @param {Array} [encryptionKeys] - Public key(s) for message encryption - * @param {Array} [passwords] - For message encryption - * @param {Boolean} [wildcard] - Use a key ID of 0 instead of the public key IDs - * @param {Array} [encryptionKeyIDs] - Array of key IDs to use for encryption. Each encryptionKeyIDs[i] corresponds to encryptionKeys[i] - * @param {Date} [date] - Override the date - * @param {Array} [userIDs] - User IDs to encrypt for, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }] - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New message with encrypted content. - * @async - */ - static async encryptSessionKey(sessionKey, algorithmName, aeadAlgorithmName, encryptionKeys, passwords, wildcard = false, encryptionKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { - const packetlist = new PacketList(); - const algorithm = enums.write(enums.symmetric, algorithmName); - const aeadAlgorithm = aeadAlgorithmName && enums.write(enums.aead, aeadAlgorithmName); - - if (encryptionKeys) { - const results = await Promise.all(encryptionKeys.map(async function(primaryKey, i) { - const encryptionKey = await primaryKey.getEncryptionKey(encryptionKeyIDs[i], date, userIDs, config); - const pkESKeyPacket = new PublicKeyEncryptedSessionKeyPacket(); - pkESKeyPacket.publicKeyID = wildcard ? KeyID.wildcard() : encryptionKey.getKeyID(); - pkESKeyPacket.publicKeyAlgorithm = encryptionKey.keyPacket.algorithm; - pkESKeyPacket.sessionKey = sessionKey; - pkESKeyPacket.sessionKeyAlgorithm = algorithm; - await pkESKeyPacket.encrypt(encryptionKey.keyPacket); - delete pkESKeyPacket.sessionKey; // delete plaintext session key after encryption - return pkESKeyPacket; - })); - packetlist.push(...results); - } - if (passwords) { - const testDecrypt = async function(keyPacket, password) { - try { - await keyPacket.decrypt(password); - return 1; - } catch (e) { - return 0; - } - }; - - const sum = (accumulator, currentValue) => accumulator + currentValue; - - const encryptPassword = async function(sessionKey, algorithm, aeadAlgorithm, password) { - const symEncryptedSessionKeyPacket = new SymEncryptedSessionKeyPacket(config); - symEncryptedSessionKeyPacket.sessionKey = sessionKey; - symEncryptedSessionKeyPacket.sessionKeyAlgorithm = algorithm; - if (aeadAlgorithm) { - symEncryptedSessionKeyPacket.aeadAlgorithm = aeadAlgorithm; - } - await symEncryptedSessionKeyPacket.encrypt(password, config); - - if (config.passwordCollisionCheck) { - const results = await Promise.all(passwords.map(pwd => testDecrypt(symEncryptedSessionKeyPacket, pwd))); - if (results.reduce(sum) !== 1) { - return encryptPassword(sessionKey, algorithm, password); - } - } - - delete symEncryptedSessionKeyPacket.sessionKey; // delete plaintext session key after encryption - return symEncryptedSessionKeyPacket; - }; - - const results = await Promise.all(passwords.map(pwd => encryptPassword(sessionKey, algorithm, aeadAlgorithm, pwd))); - packetlist.push(...results); - } - - return new Message(packetlist); - } - - /** - * Sign the message (the literal data packet of the message) - * @param {Array} signingKeys - private keys with decrypted secret key data for signing - * @param {Signature} [signature] - Any existing detached signature to add to the message - * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] - * @param {Date} [date] - Override the creation time of the signature - * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New message with signed content. - * @async - */ - async sign(signingKeys = [], signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { - const packetlist = new PacketList(); - - const literalDataPacket = this.packets.findPacket(enums.packet.literalData); - if (!literalDataPacket) { - throw new Error('No literal data packet to sign.'); - } - - let i; - let existingSigPacketlist; - // If data packet was created from Uint8Array, use binary, otherwise use text - const signatureType = literalDataPacket.text === null ? - enums.signature.binary : enums.signature.text; - - if (signature) { - existingSigPacketlist = signature.packets.filterByTag(enums.packet.signature); - for (i = existingSigPacketlist.length - 1; i >= 0; i--) { - const signaturePacket = existingSigPacketlist[i]; - const onePassSig = new OnePassSignaturePacket(); - onePassSig.signatureType = signaturePacket.signatureType; - onePassSig.hashAlgorithm = signaturePacket.hashAlgorithm; - onePassSig.publicKeyAlgorithm = signaturePacket.publicKeyAlgorithm; - onePassSig.issuerKeyID = signaturePacket.issuerKeyID; - if (!signingKeys.length && i === 0) { - onePassSig.flags = 1; - } - packetlist.push(onePassSig); - } - } - - await Promise.all(Array.from(signingKeys).reverse().map(async function (primaryKey, i) { - if (!primaryKey.isPrivate()) { - throw new Error('Need private key for signing'); - } - const signingKeyID = signingKeyIDs[signingKeys.length - 1 - i]; - const signingKey = await primaryKey.getSigningKey(signingKeyID, date, userIDs, config); - const onePassSig = new OnePassSignaturePacket(); - onePassSig.signatureType = signatureType; - onePassSig.hashAlgorithm = await getPreferredHashAlgo$1(primaryKey, signingKey.keyPacket, date, userIDs, config); - onePassSig.publicKeyAlgorithm = signingKey.keyPacket.algorithm; - onePassSig.issuerKeyID = signingKey.getKeyID(); - if (i === signingKeys.length - 1) { - onePassSig.flags = 1; - } - return onePassSig; - })).then(onePassSignatureList => { - onePassSignatureList.forEach(onePassSig => packetlist.push(onePassSig)); - }); - - packetlist.push(literalDataPacket); - packetlist.push(...(await createSignaturePackets(literalDataPacket, signingKeys, signature, signingKeyIDs, date, userIDs, false, config))); - - return new Message(packetlist); - } - - /** - * Compresses the message (the literal and -if signed- signature data packets of the message) - * @param {module:enums.compression} algo - compression algorithm - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Message} New message with compressed content. - */ - compress(algo, config = defaultConfig) { - if (algo === enums.compression.uncompressed) { - return this; - } - - const compressed = new CompressedDataPacket(config); - compressed.algorithm = algo; - compressed.packets = this.packets; - - const packetList = new PacketList(); - packetList.push(compressed); - - return new Message(packetList); - } - - /** - * Create a detached signature for the message (the literal data packet of the message) - * @param {Array} signingKeys - private keys with decrypted secret key data for signing - * @param {Signature} [signature] - Any existing detached signature - * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] - * @param {Date} [date] - Override the creation time of the signature - * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New detached signature of message content. - * @async - */ - async signDetached(signingKeys = [], signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { - const literalDataPacket = this.packets.findPacket(enums.packet.literalData); - if (!literalDataPacket) { - throw new Error('No literal data packet to sign.'); - } - return new Signature(await createSignaturePackets(literalDataPacket, signingKeys, signature, signingKeyIDs, date, userIDs, true, config)); - } - - /** - * Verify message signatures - * @param {Array} verificationKeys - Array of public keys to verify signatures - * @param {Date} [date] - Verify the signature against the given date, i.e. check signature creation time < date < expiration time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise, - * verified: Promise - * }>>} List of signer's keyID and validity of signatures. - * @async - */ - async verify(verificationKeys, date = new Date(), config = defaultConfig) { - const msg = this.unwrapCompressed(); - const literalDataList = msg.packets.filterByTag(enums.packet.literalData); - if (literalDataList.length !== 1) { - throw new Error('Can only verify message with one literal data packet.'); - } - if (isArrayStream(msg.packets.stream)) { - msg.packets.push(...await readToEnd(msg.packets.stream, _ => _ || [])); - } - const onePassSigList = msg.packets.filterByTag(enums.packet.onePassSignature).reverse(); - const signatureList = msg.packets.filterByTag(enums.packet.signature); - if (onePassSigList.length && !signatureList.length && util.isStream(msg.packets.stream) && !isArrayStream(msg.packets.stream)) { - await Promise.all(onePassSigList.map(async onePassSig => { - onePassSig.correspondingSig = new Promise((resolve, reject) => { - onePassSig.correspondingSigResolve = resolve; - onePassSig.correspondingSigReject = reject; - }); - onePassSig.signatureData = fromAsync(async () => (await onePassSig.correspondingSig).signatureData); - onePassSig.hashed = readToEnd(await onePassSig.hash(onePassSig.signatureType, literalDataList[0], undefined, false)); - onePassSig.hashed.catch(() => {}); - })); - msg.packets.stream = transformPair(msg.packets.stream, async (readable, writable) => { - const reader = getReader(readable); - const writer = getWriter(writable); - try { - for (let i = 0; i < onePassSigList.length; i++) { - const { value: signature } = await reader.read(); - onePassSigList[i].correspondingSigResolve(signature); - } - await reader.readToEnd(); - await writer.ready; - await writer.close(); - } catch (e) { - onePassSigList.forEach(onePassSig => { - onePassSig.correspondingSigReject(e); - }); - await writer.abort(e); - } - }); - return createVerificationObjects(onePassSigList, literalDataList, verificationKeys, date, false, config); - } - return createVerificationObjects(signatureList, literalDataList, verificationKeys, date, false, config); - } - - /** - * Verify detached message signature - * @param {Array} verificationKeys - Array of public keys to verify signatures - * @param {Signature} signature - * @param {Date} date - Verify the signature against the given date, i.e. check signature creation time < date < expiration time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise, - * verified: Promise - * }>>} List of signer's keyID and validity of signature. - * @async - */ - verifyDetached(signature, verificationKeys, date = new Date(), config = defaultConfig) { - const msg = this.unwrapCompressed(); - const literalDataList = msg.packets.filterByTag(enums.packet.literalData); - if (literalDataList.length !== 1) { - throw new Error('Can only verify message with one literal data packet.'); - } - const signatureList = signature.packets; - return createVerificationObjects(signatureList, literalDataList, verificationKeys, date, true, config); - } - - /** - * Unwrap compressed message - * @returns {Message} Message Content of compressed message. - */ - unwrapCompressed() { - const compressed = this.packets.filterByTag(enums.packet.compressedData); - if (compressed.length) { - return new Message(compressed[0].packets); - } - return this; - } - - /** - * Append signature to unencrypted message object - * @param {String|Uint8Array} detachedSignature - The detached ASCII-armored or Uint8Array PGP signature - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - async appendSignature(detachedSignature, config = defaultConfig) { - await this.packets.read( - util.isUint8Array(detachedSignature) ? detachedSignature : (await unarmor(detachedSignature)).data, - allowedDetachedSignaturePackets, - config - ); - } - - /** - * Returns binary encoded message - * @returns {ReadableStream} Binary message. - */ - write() { - return this.packets.write(); - } - - /** - * Returns ASCII armored text of message - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {ReadableStream} ASCII armor. - */ - armor(config = defaultConfig) { - return armor(enums.armor.message, this.write(), null, null, null, config); - } -} - -/** - * Create signature packets for the message - * @param {LiteralDataPacket} literalDataPacket - the literal data packet to sign - * @param {Array} [signingKeys] - private keys with decrypted secret key data for signing - * @param {Signature} [signature] - Any existing detached signature to append - * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] - * @param {Date} [date] - Override the creationtime of the signature - * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] - * @param {Boolean} [detached] - Whether to create detached signature packets - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} List of signature packets. - * @async - * @private - */ -async function createSignaturePackets(literalDataPacket, signingKeys, signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], detached = false, config = defaultConfig) { - const packetlist = new PacketList(); - - // If data packet was created from Uint8Array, use binary, otherwise use text - const signatureType = literalDataPacket.text === null ? - enums.signature.binary : enums.signature.text; - - await Promise.all(signingKeys.map(async (primaryKey, i) => { - const userID = userIDs[i]; - if (!primaryKey.isPrivate()) { - throw new Error('Need private key for signing'); - } - const signingKey = await primaryKey.getSigningKey(signingKeyIDs[i], date, userID, config); - return createSignaturePacket(literalDataPacket, primaryKey, signingKey.keyPacket, { signatureType }, date, userID, detached, config); - })).then(signatureList => { - packetlist.push(...signatureList); - }); - - if (signature) { - const existingSigPacketlist = signature.packets.filterByTag(enums.packet.signature); - packetlist.push(...existingSigPacketlist); - } - return packetlist; -} - -/** - * Create object containing signer's keyID and validity of signature - * @param {SignaturePacket} signature - Signature packet - * @param {Array} literalDataList - Array of literal data packets - * @param {Array} verificationKeys - Array of public keys to verify signatures - * @param {Date} [date] - Check signature validity with respect to the given date - * @param {Boolean} [detached] - Whether to verify detached signature packets - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise<{ - * keyID: module:type/keyid~KeyID, - * signature: Promise, - * verified: Promise - * }>} signer's keyID and validity of signature - * @async - * @private - */ -async function createVerificationObject(signature, literalDataList, verificationKeys, date = new Date(), detached = false, config = defaultConfig) { - let primaryKey; - let unverifiedSigningKey; - - for (const key of verificationKeys) { - const issuerKeys = key.getKeys(signature.issuerKeyID); - if (issuerKeys.length > 0) { - primaryKey = key; - unverifiedSigningKey = issuerKeys[0]; - break; - } - } - - const isOnePassSignature = signature instanceof OnePassSignaturePacket; - const signaturePacketPromise = isOnePassSignature ? signature.correspondingSig : signature; - - const verifiedSig = { - keyID: signature.issuerKeyID, - verified: (async () => { - if (!unverifiedSigningKey) { - throw new Error(`Could not find signing key with key ID ${signature.issuerKeyID.toHex()}`); - } - - await signature.verify(unverifiedSigningKey.keyPacket, signature.signatureType, literalDataList[0], date, detached, config); - const signaturePacket = await signaturePacketPromise; - if (unverifiedSigningKey.getCreationTime() > signaturePacket.created) { - throw new Error('Key is newer than the signature'); - } - // We pass the signature creation time to check whether the key was expired at the time of signing. - // We check this after signature verification because for streamed one-pass signatures, the creation time is not available before - try { - await primaryKey.getSigningKey(unverifiedSigningKey.getKeyID(), signaturePacket.created, undefined, config); - } catch (e) { - // If a key was reformatted then the self-signatures of the signing key might be in the future compared to the message signature, - // making the key invalid at the time of signing. - // However, if the key is valid at the given `date`, we still allow using it provided the relevant `config` setting is enabled. - // Note: we do not support the edge case of a key that was reformatted and it has expired. - if (config.allowInsecureVerificationWithReformattedKeys && e.message.match(/Signature creation time is in the future/)) { - await primaryKey.getSigningKey(unverifiedSigningKey.getKeyID(), date, undefined, config); - } else { - throw e; - } - } - return true; - })(), - signature: (async () => { - const signaturePacket = await signaturePacketPromise; - const packetlist = new PacketList(); - signaturePacket && packetlist.push(signaturePacket); - return new Signature(packetlist); - })() - }; - - // Mark potential promise rejections as "handled". This is needed because in - // some cases, we reject them before the user has a reasonable chance to - // handle them (e.g. `await readToEnd(result.data); await result.verified` and - // the data stream errors). - verifiedSig.signature.catch(() => {}); - verifiedSig.verified.catch(() => {}); - - return verifiedSig; -} - -/** - * Create list of objects containing signer's keyID and validity of signature - * @param {Array} signatureList - Array of signature packets - * @param {Array} literalDataList - Array of literal data packets - * @param {Array} verificationKeys - Array of public keys to verify signatures - * @param {Date} date - Verify the signature against the given date, - * i.e. check signature creation time < date < expiration time - * @param {Boolean} [detached] - Whether to verify detached signature packets - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise, - * verified: Promise - * }>>} list of signer's keyID and validity of signatures (one entry per signature packet in input) - * @async - * @private - */ -async function createVerificationObjects(signatureList, literalDataList, verificationKeys, date = new Date(), detached = false, config = defaultConfig) { - return Promise.all(signatureList.filter(function(signature) { - return ['text', 'binary'].includes(enums.read(enums.signature, signature.signatureType)); - }).map(async function(signature) { - return createVerificationObject(signature, literalDataList, verificationKeys, date, detached, config); - })); -} - -/** - * Reads an (optionally armored) OpenPGP message and returns a Message object - * @param {Object} options - * @param {String | ReadableStream} [options.armoredMessage] - Armored message to be parsed - * @param {Uint8Array | ReadableStream} [options.binaryMessage] - Binary to be parsed - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} New message object. - * @async - * @static - */ -async function readMessage({ armoredMessage, binaryMessage, config, ...rest }) { - config = { ...defaultConfig, ...config }; - let input = armoredMessage || binaryMessage; - if (!input) { - throw new Error('readMessage: must pass options object containing `armoredMessage` or `binaryMessage`'); - } - if (armoredMessage && !util.isString(armoredMessage) && !util.isStream(armoredMessage)) { - throw new Error('readMessage: options.armoredMessage must be a string or stream'); - } - if (binaryMessage && !util.isUint8Array(binaryMessage) && !util.isStream(binaryMessage)) { - throw new Error('readMessage: options.binaryMessage must be a Uint8Array or stream'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - const streamType = util.isStream(input); - if (streamType) { - await loadStreamsPonyfill(); - input = toStream(input); - } - if (armoredMessage) { - const { type, data } = await unarmor(input, config); - if (type !== enums.armor.message) { - throw new Error('Armored text not of type message'); - } - input = data; - } - const packetlist = await PacketList.fromBinary(input, allowedMessagePackets, config); - const message = new Message(packetlist); - message.fromStream = streamType; - return message; -} - -/** - * Creates new message object from text or binary data. - * @param {Object} options - * @param {String | ReadableStream} [options.text] - The text message contents - * @param {Uint8Array | ReadableStream} [options.binary] - The binary message contents - * @param {String} [options.filename=""] - Name of the file (if any) - * @param {Date} [options.date=current date] - Date of the message, or modification date of the file - * @param {'utf8'|'binary'|'text'|'mime'} [options.format='utf8' if text is passed, 'binary' otherwise] - Data packet type - * @returns {Promise} New message object. - * @async - * @static - */ -async function createMessage({ text, binary, filename, date = new Date(), format = text !== undefined ? 'utf8' : 'binary', ...rest }) { - let input = text !== undefined ? text : binary; - if (input === undefined) { - throw new Error('createMessage: must pass options object containing `text` or `binary`'); - } - if (text && !util.isString(text) && !util.isStream(text)) { - throw new Error('createMessage: options.text must be a string or stream'); - } - if (binary && !util.isUint8Array(binary) && !util.isStream(binary)) { - throw new Error('createMessage: options.binary must be a Uint8Array or stream'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - const streamType = util.isStream(input); - if (streamType) { - await loadStreamsPonyfill(); - input = toStream(input); - } - const literalDataPacket = new LiteralDataPacket(date); - if (text !== undefined) { - literalDataPacket.setText(input, enums.write(enums.literal, format)); - } else { - literalDataPacket.setBytes(input, enums.write(enums.literal, format)); - } - if (filename !== undefined) { - literalDataPacket.setFilename(filename); - } - const literalDataPacketlist = new PacketList(); - literalDataPacketlist.push(literalDataPacket); - const message = new Message(literalDataPacketlist); - message.fromStream = streamType; - return message; -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -// A Cleartext message can contain the following packets -const allowedPackets$5 = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); - -/** - * Class that represents an OpenPGP cleartext signed message. - * See {@link https://tools.ietf.org/html/rfc4880#section-7} - */ -class CleartextMessage { - /** - * @param {String} text - The cleartext of the signed message - * @param {Signature} signature - The detached signature or an empty signature for unsigned messages - */ - constructor(text, signature) { - // normalize EOL to canonical form - this.text = util.removeTrailingSpaces(text).replace(/\r?\n/g, '\r\n'); - if (signature && !(signature instanceof Signature)) { - throw new Error('Invalid signature input'); - } - this.signature = signature || new Signature(new PacketList()); - } - - /** - * Returns the key IDs of the keys that signed the cleartext message - * @returns {Array} Array of keyID objects. - */ - getSigningKeyIDs() { - const keyIDs = []; - const signatureList = this.signature.packets; - signatureList.forEach(function(packet) { - keyIDs.push(packet.issuerKeyID); - }); - return keyIDs; - } - - /** - * Sign the cleartext message - * @param {Array} privateKeys - private keys with decrypted secret key data for signing - * @param {Signature} [signature] - Any existing detached signature - * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to privateKeys[i] - * @param {Date} [date] - The creation time of the signature that should be created - * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New cleartext message with signed content. - * @async - */ - async sign(privateKeys, signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { - const literalDataPacket = new LiteralDataPacket(); - literalDataPacket.setText(this.text); - const newSignature = new Signature(await createSignaturePackets(literalDataPacket, privateKeys, signature, signingKeyIDs, date, userIDs, true, config)); - return new CleartextMessage(this.text, newSignature); - } - - /** - * Verify signatures of cleartext signed message - * @param {Array} keys - Array of keys to verify signatures - * @param {Date} [date] - Verify the signature against the given date, i.e. check signature creation time < date < expiration time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise, - * verified: Promise - * }>>} List of signer's keyID and validity of signature. - * @async - */ - verify(keys, date = new Date(), config = defaultConfig) { - const signatureList = this.signature.packets; - const literalDataPacket = new LiteralDataPacket(); - // we assume that cleartext signature is generated based on UTF8 cleartext - literalDataPacket.setText(this.text); - return createVerificationObjects(signatureList, [literalDataPacket], keys, date, true, config); - } - - /** - * Get cleartext - * @returns {String} Cleartext of message. - */ - getText() { - // normalize end of line to \n - return this.text.replace(/\r\n/g, '\n'); - } - - /** - * Returns ASCII armored text of cleartext signed message - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {String | ReadableStream} ASCII armor. - */ - armor(config = defaultConfig) { - let hashes = this.signature.packets.map(function(packet) { - return enums.read(enums.hash, packet.hashAlgorithm).toUpperCase(); - }); - hashes = hashes.filter(function(item, i, ar) { return ar.indexOf(item) === i; }); - const body = { - hash: hashes.join(), - text: this.text, - data: this.signature.packets.write() - }; - return armor(enums.armor.signed, body, undefined, undefined, undefined, config); - } -} - -/** - * Reads an OpenPGP cleartext signed message and returns a CleartextMessage object - * @param {Object} options - * @param {String} options.cleartextMessage - Text to be parsed - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} New cleartext message object. - * @async - * @static - */ -async function readCleartextMessage({ cleartextMessage, config, ...rest }) { - config = { ...defaultConfig, ...config }; - if (!cleartextMessage) { - throw new Error('readCleartextMessage: must pass options object containing `cleartextMessage`'); - } - if (!util.isString(cleartextMessage)) { - throw new Error('readCleartextMessage: options.cleartextMessage must be a string'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - const input = await unarmor(cleartextMessage); - if (input.type !== enums.armor.signed) { - throw new Error('No cleartext signed message.'); - } - const packetlist = await PacketList.fromBinary(input.data, allowedPackets$5, config); - verifyHeaders$1(input.headers, packetlist); - const signature = new Signature(packetlist); - return new CleartextMessage(input.text, signature); -} - -/** - * Compare hash algorithm specified in the armor header with signatures - * @param {Array} headers - Armor headers - * @param {PacketList} packetlist - The packetlist with signature packets - * @private - */ -function verifyHeaders$1(headers, packetlist) { - const checkHashAlgos = function(hashAlgos) { - const check = packet => algo => packet.hashAlgorithm === algo; - - for (let i = 0; i < packetlist.length; i++) { - if (packetlist[i].constructor.tag === enums.packet.signature && !hashAlgos.some(check(packetlist[i]))) { - return false; - } - } - return true; - }; - - let oneHeader = null; - let hashAlgos = []; - headers.forEach(function(header) { - oneHeader = header.match(/Hash: (.+)/); // get header value - if (oneHeader) { - oneHeader = oneHeader[1].replace(/\s/g, ''); // remove whitespace - oneHeader = oneHeader.split(','); - oneHeader = oneHeader.map(function(hash) { - hash = hash.toLowerCase(); - try { - return enums.write(enums.hash, hash); - } catch (e) { - throw new Error('Unknown hash algorithm in armor header: ' + hash); - } - }); - hashAlgos = hashAlgos.concat(oneHeader); - } else { - throw new Error('Only "Hash" header allowed in cleartext signed message'); - } - }); - - if (!hashAlgos.length && !checkHashAlgos([enums.hash.md5])) { - throw new Error('If no "Hash" header in cleartext signed message, then only MD5 signatures allowed'); - } else if (hashAlgos.length && !checkHashAlgos(hashAlgos)) { - throw new Error('Hash algorithm mismatch in armor header and signature'); - } -} - -/** - * Creates a new CleartextMessage object from text - * @param {Object} options - * @param {String} options.text - * @static - * @async - */ -async function createCleartextMessage({ text, ...rest }) { - if (!text) { - throw new Error('createCleartextMessage: must pass options object containing `text`'); - } - if (!util.isString(text)) { - throw new Error('createCleartextMessage: options.text must be a string'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - return new CleartextMessage(text); -} - -// OpenPGP.js - An OpenPGP implementation in javascript - - -////////////////////// -// // -// Key handling // -// // -////////////////////// - - -/** - * Generates a new OpenPGP key pair. Supports RSA and ECC keys. By default, primary and subkeys will be of same type. - * The generated primary key will have signing capabilities. By default, one subkey with encryption capabilities is also generated. - * @param {Object} options - * @param {Object|Array} options.userIDs - User IDs as objects: `{ name: 'Jo Doe', email: 'info@jo.com' }` - * @param {'ecc'|'rsa'} [options.type='ecc'] - The primary key algorithm type: ECC (default) or RSA - * @param {String} [options.passphrase=(not protected)] - The passphrase used to encrypt the generated private key. If omitted, the key won't be encrypted. - * @param {Number} [options.rsaBits=4096] - Number of bits for RSA keys - * @param {String} [options.curve='curve25519'] - Elliptic curve for ECC keys: - * curve25519 (default), p256, p384, p521, secp256k1, - * brainpoolP256r1, brainpoolP384r1, or brainpoolP512r1 - * @param {Date} [options.date=current date] - Override the creation date of the key and the key signatures - * @param {Number} [options.keyExpirationTime=0 (never expires)] - Number of seconds from the key creation time after which the key expires - * @param {Array} [options.subkeys=a single encryption subkey] - Options for each subkey e.g. `[{sign: true, passphrase: '123'}]` - * default to main key options, except for `sign` parameter that defaults to false, and indicates whether the subkey should sign rather than encrypt - * @param {'armored'|'binary'|'object'} [options.format='armored'] - format of the output keys - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} The generated key object in the form: - * { privateKey:PrivateKey|Uint8Array|String, publicKey:PublicKey|Uint8Array|String, revocationCertificate:String } - * @async - * @static - */ -async function generateKey({ userIDs = [], passphrase = '', type = 'ecc', rsaBits = 4096, curve = 'curve25519', keyExpirationTime = 0, date = new Date(), subkeys = [{}], format = 'armored', config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - userIDs = toArray$1(userIDs); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (userIDs.length === 0) { - throw new Error('UserIDs are required for key generation'); - } - if (type === 'rsa' && rsaBits < config.minRSABits) { - throw new Error(`rsaBits should be at least ${config.minRSABits}, got: ${rsaBits}`); - } - - const options = { userIDs, passphrase, type, rsaBits, curve, keyExpirationTime, date, subkeys }; - - try { - const { key, revocationCertificate } = await generate$2(options, config); - key.getKeys().forEach(({ keyPacket }) => checkKeyRequirements(keyPacket, config)); - - return { - privateKey: formatObject(key, format, config), - publicKey: formatObject(key.toPublic(), format, config), - revocationCertificate - }; - } catch (err) { - throw util.wrapError('Error generating keypair', err); - } -} - -/** - * Reformats signature packets for a key and rewraps key object. - * @param {Object} options - * @param {PrivateKey} options.privateKey - Private key to reformat - * @param {Object|Array} options.userIDs - User IDs as objects: `{ name: 'Jo Doe', email: 'info@jo.com' }` - * @param {String} [options.passphrase=(not protected)] - The passphrase used to encrypt the reformatted private key. If omitted, the key won't be encrypted. - * @param {Number} [options.keyExpirationTime=0 (never expires)] - Number of seconds from the key creation time after which the key expires - * @param {Date} [options.date] - Override the creation date of the key signatures. If the key was previously used to sign messages, it is recommended - * to set the same date as the key creation time to ensure that old message signatures will still be verifiable using the reformatted key. - * @param {'armored'|'binary'|'object'} [options.format='armored'] - format of the output keys - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} The generated key object in the form: - * { privateKey:PrivateKey|Uint8Array|String, publicKey:PublicKey|Uint8Array|String, revocationCertificate:String } - * @async - * @static - */ -async function reformatKey({ privateKey, userIDs = [], passphrase = '', keyExpirationTime = 0, date, format = 'armored', config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - userIDs = toArray$1(userIDs); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (userIDs.length === 0) { - throw new Error('UserIDs are required for key reformat'); - } - const options = { privateKey, userIDs, passphrase, keyExpirationTime, date }; - - try { - const { key: reformattedKey, revocationCertificate } = await reformat(options, config); - - return { - privateKey: formatObject(reformattedKey, format, config), - publicKey: formatObject(reformattedKey.toPublic(), format, config), - revocationCertificate - }; - } catch (err) { - throw util.wrapError('Error reformatting keypair', err); - } -} - -/** - * Revokes a key. Requires either a private key or a revocation certificate. - * If a revocation certificate is passed, the reasonForRevocation parameter will be ignored. - * @param {Object} options - * @param {Key} options.key - Public or private key to revoke - * @param {String} [options.revocationCertificate] - Revocation certificate to revoke the key with - * @param {Object} [options.reasonForRevocation] - Object indicating the reason for revocation - * @param {module:enums.reasonForRevocation} [options.reasonForRevocation.flag=[noReason]{@link module:enums.reasonForRevocation}] - Flag indicating the reason for revocation - * @param {String} [options.reasonForRevocation.string=""] - String explaining the reason for revocation - * @param {Date} [options.date] - Use the given date instead of the current time to verify validity of revocation certificate (if provided), or as creation time of the revocation signature - * @param {'armored'|'binary'|'object'} [options.format='armored'] - format of the output key(s) - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} The revoked key in the form: - * { privateKey:PrivateKey|Uint8Array|String, publicKey:PublicKey|Uint8Array|String } if private key is passed, or - * { privateKey: null, publicKey:PublicKey|Uint8Array|String } otherwise - * @async - * @static - */ -async function revokeKey({ key, revocationCertificate, reasonForRevocation, date = new Date(), format = 'armored', config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - try { - const revokedKey = revocationCertificate ? - await key.applyRevocationCertificate(revocationCertificate, date, config) : - await key.revoke(reasonForRevocation, date, config); - - return revokedKey.isPrivate() ? { - privateKey: formatObject(revokedKey, format, config), - publicKey: formatObject(revokedKey.toPublic(), format, config) - } : { - privateKey: null, - publicKey: formatObject(revokedKey, format, config) - }; - } catch (err) { - throw util.wrapError('Error revoking key', err); - } -} - -/** - * Unlock a private key with the given passphrase. - * This method does not change the original key. - * @param {Object} options - * @param {PrivateKey} options.privateKey - The private key to decrypt - * @param {String|Array} options.passphrase - The user's passphrase(s) - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} The unlocked key object. - * @async - */ -async function decryptKey({ privateKey, passphrase, config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (!privateKey.isPrivate()) { - throw new Error('Cannot decrypt a public key'); - } - const clonedPrivateKey = privateKey.clone(true); - const passphrases = util.isArray(passphrase) ? passphrase : [passphrase]; - - try { - await Promise.all(clonedPrivateKey.getKeys().map(key => ( - // try to decrypt each key with any of the given passphrases - util.anyPromise(passphrases.map(passphrase => key.keyPacket.decrypt(passphrase))) - ))); - - await clonedPrivateKey.validate(config); - return clonedPrivateKey; - } catch (err) { - clonedPrivateKey.clearPrivateParams(); - throw util.wrapError('Error decrypting private key', err); - } -} - -/** - * Lock a private key with the given passphrase. - * This method does not change the original key. - * @param {Object} options - * @param {PrivateKey} options.privateKey - The private key to encrypt - * @param {String|Array} options.passphrase - If multiple passphrases, they should be in the same order as the packets each should encrypt - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} The locked key object. - * @async - */ -async function encryptKey({ privateKey, passphrase, config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (!privateKey.isPrivate()) { - throw new Error('Cannot encrypt a public key'); - } - const clonedPrivateKey = privateKey.clone(true); - - const keys = clonedPrivateKey.getKeys(); - const passphrases = util.isArray(passphrase) ? passphrase : new Array(keys.length).fill(passphrase); - if (passphrases.length !== keys.length) { - throw new Error('Invalid number of passphrases given for key encryption'); - } - - try { - await Promise.all(keys.map(async (key, i) => { - const { keyPacket } = key; - await keyPacket.encrypt(passphrases[i], config); - keyPacket.clearPrivateParams(); - })); - return clonedPrivateKey; - } catch (err) { - clonedPrivateKey.clearPrivateParams(); - throw util.wrapError('Error encrypting private key', err); - } -} - - -/////////////////////////////////////////// -// // -// Message encryption and decryption // -// // -/////////////////////////////////////////// - - -/** - * Encrypts a message using public keys, passwords or both at once. At least one of `encryptionKeys` or `passwords` - * must be specified. If signing keys are specified, those will be used to sign the message. - * @param {Object} options - * @param {Message} options.message - Message to be encrypted as created by {@link createMessage} - * @param {PublicKey|PublicKey[]} [options.encryptionKeys] - Array of keys or single key, used to encrypt the message - * @param {PrivateKey|PrivateKey[]} [options.signingKeys] - Private keys for signing. If omitted message will not be signed - * @param {String|String[]} [options.passwords] - Array of passwords or a single password to encrypt the message - * @param {Object} [options.sessionKey] - Session key in the form: `{ data:Uint8Array, algorithm:String }` - * @param {'armored'|'binary'|'object'} [options.format='armored'] - Format of the returned message - * @param {Signature} [options.signature] - A detached signature to add to the encrypted message - * @param {Boolean} [options.wildcard=false] - Use a key ID of 0 instead of the public key IDs - * @param {KeyID|KeyID[]} [options.signingKeyIDs=latest-created valid signing (sub)keys] - Array of key IDs to use for signing. Each `signingKeyIDs[i]` corresponds to `signingKeys[i]` - * @param {KeyID|KeyID[]} [options.encryptionKeyIDs=latest-created valid encryption (sub)keys] - Array of key IDs to use for encryption. Each `encryptionKeyIDs[i]` corresponds to `encryptionKeys[i]` - * @param {Date} [options.date=current date] - Override the creation date of the message signature - * @param {Object|Object[]} [options.signingUserIDs=primary user IDs] - Array of user IDs to sign with, one per key in `signingKeys`, e.g. `[{ name: 'Steve Sender', email: 'steve@openpgp.org' }]` - * @param {Object|Object[]} [options.encryptionUserIDs=primary user IDs] - Array of user IDs to encrypt for, one per key in `encryptionKeys`, e.g. `[{ name: 'Robert Receiver', email: 'robert@openpgp.org' }]` - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise|MaybeStream>} Encrypted message (string if `armor` was true, the default; Uint8Array if `armor` was false). - * @async - * @static - */ -async function encrypt$4({ message, encryptionKeys, signingKeys, passwords, sessionKey, format = 'armored', signature = null, wildcard = false, signingKeyIDs = [], encryptionKeyIDs = [], date = new Date(), signingUserIDs = [], encryptionUserIDs = [], config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - checkMessage(message); checkOutputMessageFormat(format); - encryptionKeys = toArray$1(encryptionKeys); signingKeys = toArray$1(signingKeys); passwords = toArray$1(passwords); - signingKeyIDs = toArray$1(signingKeyIDs); encryptionKeyIDs = toArray$1(encryptionKeyIDs); signingUserIDs = toArray$1(signingUserIDs); encryptionUserIDs = toArray$1(encryptionUserIDs); - if (rest.detached) { - throw new Error("The `detached` option has been removed from openpgp.encrypt, separately call openpgp.sign instead. Don't forget to remove the `privateKeys` option as well."); - } - if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.encrypt, pass `encryptionKeys` instead'); - if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.encrypt, pass `signingKeys` instead'); - if (rest.armor !== undefined) throw new Error('The `armor` option has been removed from openpgp.encrypt, pass `format` instead.'); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (!signingKeys) { - signingKeys = []; - } - const streaming = message.fromStream; - try { - if (signingKeys.length || signature) { // sign the message only if signing keys or signature is specified - message = await message.sign(signingKeys, signature, signingKeyIDs, date, signingUserIDs, config); - } - message = message.compress( - await getPreferredAlgo('compression', encryptionKeys, date, encryptionUserIDs, config), - config - ); - message = await message.encrypt(encryptionKeys, passwords, sessionKey, wildcard, encryptionKeyIDs, date, encryptionUserIDs, config); - if (format === 'object') return message; - // serialize data - const armor = format === 'armored'; - const data = armor ? message.armor(config) : message.write(); - return convertStream(data, streaming, armor ? 'utf8' : 'binary'); - } catch (err) { - throw util.wrapError('Error encrypting message', err); - } -} - -/** - * Decrypts a message with the user's private key, a session key or a password. - * One of `decryptionKeys`, `sessionkeys` or `passwords` must be specified (passing a combination of these options is not supported). - * @param {Object} options - * @param {Message} options.message - The message object with the encrypted data - * @param {PrivateKey|PrivateKey[]} [options.decryptionKeys] - Private keys with decrypted secret key data or session key - * @param {String|String[]} [options.passwords] - Passwords to decrypt the message - * @param {Object|Object[]} [options.sessionKeys] - Session keys in the form: { data:Uint8Array, algorithm:String } - * @param {PublicKey|PublicKey[]} [options.verificationKeys] - Array of public keys or single key, to verify signatures - * @param {Boolean} [options.expectSigned=false] - If true, data decryption fails if the message is not signed with the provided publicKeys - * @param {'utf8'|'binary'} [options.format='utf8'] - Whether to return data as a string(Stream) or Uint8Array(Stream). If 'utf8' (the default), also normalize newlines. - * @param {Signature} [options.signature] - Detached signature for verification - * @param {Date} [options.date=current date] - Use the given date for verification instead of the current time - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} Object containing decrypted and verified message in the form: - * - * { - * data: MaybeStream, (if format was 'utf8', the default) - * data: MaybeStream, (if format was 'binary') - * filename: String, - * signatures: [ - * { - * keyID: module:type/keyid~KeyID, - * verified: Promise, - * signature: Promise - * }, ... - * ] - * } - * - * where `signatures` contains a separate entry for each signature packet found in the input message. - * @async - * @static - */ -async function decrypt$4({ message, decryptionKeys, passwords, sessionKeys, verificationKeys, expectSigned = false, format = 'utf8', signature = null, date = new Date(), config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - checkMessage(message); verificationKeys = toArray$1(verificationKeys); decryptionKeys = toArray$1(decryptionKeys); passwords = toArray$1(passwords); sessionKeys = toArray$1(sessionKeys); - if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.decrypt, pass `decryptionKeys` instead'); - if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.decrypt, pass `verificationKeys` instead'); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - try { - const decrypted = await message.decrypt(decryptionKeys, passwords, sessionKeys, date, config); - if (!verificationKeys) { - verificationKeys = []; - } - - const result = {}; - result.signatures = signature ? await decrypted.verifyDetached(signature, verificationKeys, date, config) : await decrypted.verify(verificationKeys, date, config); - result.data = format === 'binary' ? decrypted.getLiteralData() : decrypted.getText(); - result.filename = decrypted.getFilename(); - linkStreams(result, message); - if (expectSigned) { - if (verificationKeys.length === 0) { - throw new Error('Verification keys are required to verify message signatures'); - } - if (result.signatures.length === 0) { - throw new Error('Message is not signed'); - } - result.data = concat([ - result.data, - fromAsync(async () => { - await util.anyPromise(result.signatures.map(sig => sig.verified)); - }) - ]); - } - result.data = await convertStream(result.data, message.fromStream, format); - return result; - } catch (err) { - throw util.wrapError('Error decrypting message', err); - } -} - - -////////////////////////////////////////// -// // -// Message signing and verification // -// // -////////////////////////////////////////// - - -/** - * Signs a message. - * @param {Object} options - * @param {CleartextMessage|Message} options.message - (cleartext) message to be signed - * @param {PrivateKey|PrivateKey[]} options.signingKeys - Array of keys or single key with decrypted secret key data to sign cleartext - * @param {'armored'|'binary'|'object'} [options.format='armored'] - Format of the returned message - * @param {Boolean} [options.detached=false] - If the return value should contain a detached signature - * @param {KeyID|KeyID[]} [options.signingKeyIDs=latest-created valid signing (sub)keys] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] - * @param {Date} [options.date=current date] - Override the creation date of the signature - * @param {Object|Object[]} [options.signingUserIDs=primary user IDs] - Array of user IDs to sign with, one per key in `signingKeys`, e.g. `[{ name: 'Steve Sender', email: 'steve@openpgp.org' }]` - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise>} Signed message (string if `armor` was true, the default; Uint8Array if `armor` was false). - * @async - * @static - */ -async function sign$5({ message, signingKeys, format = 'armored', detached = false, signingKeyIDs = [], date = new Date(), signingUserIDs = [], config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - checkCleartextOrMessage(message); checkOutputMessageFormat(format); - signingKeys = toArray$1(signingKeys); signingKeyIDs = toArray$1(signingKeyIDs); signingUserIDs = toArray$1(signingUserIDs); - - if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.sign, pass `signingKeys` instead'); - if (rest.armor !== undefined) throw new Error('The `armor` option has been removed from openpgp.sign, pass `format` instead.'); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (message instanceof CleartextMessage && format === 'binary') throw new Error('Cannot return signed cleartext message in binary format'); - if (message instanceof CleartextMessage && detached) throw new Error('Cannot detach-sign a cleartext message'); - - if (!signingKeys || signingKeys.length === 0) { - throw new Error('No signing keys provided'); - } - - try { - let signature; - if (detached) { - signature = await message.signDetached(signingKeys, undefined, signingKeyIDs, date, signingUserIDs, config); - } else { - signature = await message.sign(signingKeys, undefined, signingKeyIDs, date, signingUserIDs, config); - } - if (format === 'object') return signature; - - const armor = format === 'armored'; - signature = armor ? signature.armor(config) : signature.write(); - if (detached) { - signature = transformPair(message.packets.write(), async (readable, writable) => { - await Promise.all([ - pipe(signature, writable), - readToEnd(readable).catch(() => {}) - ]); - }); - } - return convertStream(signature, message.fromStream, armor ? 'utf8' : 'binary'); - } catch (err) { - throw util.wrapError('Error signing message', err); - } -} - -/** - * Verifies signatures of cleartext signed message - * @param {Object} options - * @param {CleartextMessage|Message} options.message - (cleartext) message object with signatures - * @param {PublicKey|PublicKey[]} options.verificationKeys - Array of publicKeys or single key, to verify signatures - * @param {Boolean} [options.expectSigned=false] - If true, verification throws if the message is not signed with the provided publicKeys - * @param {'utf8'|'binary'} [options.format='utf8'] - Whether to return data as a string(Stream) or Uint8Array(Stream). If 'utf8' (the default), also normalize newlines. - * @param {Signature} [options.signature] - Detached signature for verification - * @param {Date} [options.date=current date] - Use the given date for verification instead of the current time - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} Object containing verified message in the form: - * - * { - * data: MaybeStream, (if `message` was a CleartextMessage) - * data: MaybeStream, (if `message` was a Message) - * signatures: [ - * { - * keyID: module:type/keyid~KeyID, - * verified: Promise, - * signature: Promise - * }, ... - * ] - * } - * - * where `signatures` contains a separate entry for each signature packet found in the input message. - * @async - * @static - */ -async function verify$5({ message, verificationKeys, expectSigned = false, format = 'utf8', signature = null, date = new Date(), config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - checkCleartextOrMessage(message); verificationKeys = toArray$1(verificationKeys); - if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.verify, pass `verificationKeys` instead'); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (message instanceof CleartextMessage && format === 'binary') throw new Error("Can't return cleartext message data as binary"); - if (message instanceof CleartextMessage && signature) throw new Error("Can't verify detached cleartext signature"); - - try { - const result = {}; - if (signature) { - result.signatures = await message.verifyDetached(signature, verificationKeys, date, config); - } else { - result.signatures = await message.verify(verificationKeys, date, config); - } - result.data = format === 'binary' ? message.getLiteralData() : message.getText(); - if (message.fromStream) linkStreams(result, message); - if (expectSigned) { - if (result.signatures.length === 0) { - throw new Error('Message is not signed'); - } - result.data = concat([ - result.data, - fromAsync(async () => { - await util.anyPromise(result.signatures.map(sig => sig.verified)); - }) - ]); - } - result.data = await convertStream(result.data, message.fromStream, format); - return result; - } catch (err) { - throw util.wrapError('Error verifying signed message', err); - } -} - - -/////////////////////////////////////////////// -// // -// Session key encryption and decryption // -// // -/////////////////////////////////////////////// - -/** - * Generate a new session key object, taking the algorithm preferences of the passed public keys into account. - * @param {Object} options - * @param {PublicKey|PublicKey[]} options.encryptionKeys - Array of public keys or single key used to select algorithm preferences for - * @param {Date} [options.date=current date] - Date to select algorithm preferences at - * @param {Object|Object[]} [options.encryptionUserIDs=primary user IDs] - User IDs to select algorithm preferences for - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise<{ data: Uint8Array, algorithm: String }>} Object with session key data and algorithm. - * @async - * @static - */ -async function generateSessionKey$1({ encryptionKeys, date = new Date(), encryptionUserIDs = [], config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - encryptionKeys = toArray$1(encryptionKeys); encryptionUserIDs = toArray$1(encryptionUserIDs); - if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.generateSessionKey, pass `encryptionKeys` instead'); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - try { - const sessionKeys = await Message.generateSessionKey(encryptionKeys, date, encryptionUserIDs, config); - return sessionKeys; - } catch (err) { - throw util.wrapError('Error generating session key', err); - } -} - -/** - * Encrypt a symmetric session key with public keys, passwords, or both at once. - * At least one of `encryptionKeys` or `passwords` must be specified. - * @param {Object} options - * @param {Uint8Array} options.data - The session key to be encrypted e.g. 16 random bytes (for aes128) - * @param {String} options.algorithm - Algorithm of the symmetric session key e.g. 'aes128' or 'aes256' - * @param {String} [options.aeadAlgorithm] - AEAD algorithm, e.g. 'eax' or 'ocb' - * @param {PublicKey|PublicKey[]} [options.encryptionKeys] - Array of public keys or single key, used to encrypt the key - * @param {String|String[]} [options.passwords] - Passwords for the message - * @param {'armored'|'binary'} [options.format='armored'] - Format of the returned value - * @param {Boolean} [options.wildcard=false] - Use a key ID of 0 instead of the public key IDs - * @param {KeyID|KeyID[]} [options.encryptionKeyIDs=latest-created valid encryption (sub)keys] - Array of key IDs to use for encryption. Each encryptionKeyIDs[i] corresponds to encryptionKeys[i] - * @param {Date} [options.date=current date] - Override the date - * @param {Object|Object[]} [options.encryptionUserIDs=primary user IDs] - Array of user IDs to encrypt for, one per key in `encryptionKeys`, e.g. `[{ name: 'Phil Zimmermann', email: 'phil@openpgp.org' }]` - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} Encrypted session keys (string if `armor` was true, the default; Uint8Array if `armor` was false). - * @async - * @static - */ -async function encryptSessionKey({ data, algorithm, aeadAlgorithm, encryptionKeys, passwords, format = 'armored', wildcard = false, encryptionKeyIDs = [], date = new Date(), encryptionUserIDs = [], config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - checkBinary(data); checkString(algorithm, 'algorithm'); checkOutputMessageFormat(format); - encryptionKeys = toArray$1(encryptionKeys); passwords = toArray$1(passwords); encryptionKeyIDs = toArray$1(encryptionKeyIDs); encryptionUserIDs = toArray$1(encryptionUserIDs); - if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.encryptSessionKey, pass `encryptionKeys` instead'); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - try { - const message = await Message.encryptSessionKey(data, algorithm, aeadAlgorithm, encryptionKeys, passwords, wildcard, encryptionKeyIDs, date, encryptionUserIDs, config); - return formatObject(message, format, config); - } catch (err) { - throw util.wrapError('Error encrypting session key', err); - } -} - -/** - * Decrypt symmetric session keys using private keys or passwords (not both). - * One of `decryptionKeys` or `passwords` must be specified. - * @param {Object} options - * @param {Message} options.message - A message object containing the encrypted session key packets - * @param {PrivateKey|PrivateKey[]} [options.decryptionKeys] - Private keys with decrypted secret key data - * @param {String|String[]} [options.passwords] - Passwords to decrypt the session key - * @param {Date} [options.date] - Date to use for key verification instead of the current time - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} Array of decrypted session key, algorithm pairs in the form: - * { data:Uint8Array, algorithm:String } - * @throws if no session key could be found or decrypted - * @async - * @static - */ -async function decryptSessionKeys({ message, decryptionKeys, passwords, date = new Date(), config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - checkMessage(message); decryptionKeys = toArray$1(decryptionKeys); passwords = toArray$1(passwords); - if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.decryptSessionKeys, pass `decryptionKeys` instead'); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - try { - const sessionKeys = await message.decryptSessionKeys(decryptionKeys, passwords, date, config); - return sessionKeys; - } catch (err) { - throw util.wrapError('Error decrypting session keys', err); - } -} - - -////////////////////////// -// // -// Helper functions // -// // -////////////////////////// - - -/** - * Input validation - * @private - */ -function checkString(data, name) { - if (!util.isString(data)) { - throw new Error('Parameter [' + (name || 'data') + '] must be of type String'); - } -} -function checkBinary(data, name) { - if (!util.isUint8Array(data)) { - throw new Error('Parameter [' + (name || 'data') + '] must be of type Uint8Array'); - } -} -function checkMessage(message) { - if (!(message instanceof Message)) { - throw new Error('Parameter [message] needs to be of type Message'); - } -} -function checkCleartextOrMessage(message) { - if (!(message instanceof CleartextMessage) && !(message instanceof Message)) { - throw new Error('Parameter [message] needs to be of type Message or CleartextMessage'); - } -} -function checkOutputMessageFormat(format) { - if (format !== 'armored' && format !== 'binary' && format !== 'object') { - throw new Error(`Unsupported format ${format}`); - } -} -const defaultConfigPropsCount = Object.keys(defaultConfig).length; -function checkConfig(config) { - const inputConfigProps = Object.keys(config); - if (inputConfigProps.length !== defaultConfigPropsCount) { - for (const inputProp of inputConfigProps) { - if (defaultConfig[inputProp] === undefined) { - throw new Error(`Unknown config property: ${inputProp}`); - } - } - } -} - -/** - * Normalize parameter to an array if it is not undefined. - * @param {Object} param - the parameter to be normalized - * @returns {Array|undefined} The resulting array or undefined. - * @private - */ -function toArray$1(param) { - if (param && !util.isArray(param)) { - param = [param]; - } - return param; -} - -/** - * Convert data to or from Stream - * @param {Object} data - the data to convert - * @param {'web'|'ponyfill'|'node'|false} streaming - Whether to return a ReadableStream, and of what type - * @param {'utf8'|'binary'} [encoding] - How to return data in Node Readable streams - * @returns {Promise} The data in the respective format. - * @async - * @private - */ -async function convertStream(data, streaming, encoding = 'utf8') { - const streamType = util.isStream(data); - if (streamType === 'array') { - return readToEnd(data); - } - if (streaming === 'node') { - data = webToNode(data); - if (encoding !== 'binary') data.setEncoding(encoding); - return data; - } - if (streaming === 'web' && streamType === 'ponyfill') { - return toNativeReadable(data); - } - return data; -} - -/** - * Link result.data to the message stream for cancellation. - * Also, forward errors in the message to result.data. - * @param {Object} result - the data to convert - * @param {Message} message - message object - * @returns {Object} - * @private - */ -function linkStreams(result, message) { - result.data = transformPair(message.packets.stream, async (readable, writable) => { - await pipe(result.data, writable, { - preventClose: true - }); - const writer = getWriter(writable); - try { - // Forward errors in the message stream to result.data. - await readToEnd(readable, _ => _); - await writer.close(); - } catch (e) { - await writer.abort(e); - } - }); -} - -/** - * Convert the object to the given format - * @param {Key|Message} object - * @param {'armored'|'binary'|'object'} format - * @param {Object} config - Full configuration - * @returns {String|Uint8Array|Object} - */ -function formatObject(object, format, config) { - switch (format) { - case 'object': - return object; - case 'armored': - return object.armor(config); - case 'binary': - return object.write(); - default: - throw new Error(`Unsupported format ${format}`); - } -} - -/** - * web-streams-polyfill v3.0.3 - */ -/// -const SymbolPolyfill = typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol' ? - Symbol : - description => `Symbol(${description})`; - -/// -function noop() { - return undefined; -} -function getGlobals() { - if (typeof self !== 'undefined') { - return self; - } - else if (typeof window !== 'undefined') { - return window; - } - else if (typeof global !== 'undefined') { - return global; - } - return undefined; -} -const globals = getGlobals(); - -function typeIsObject(x) { - return (typeof x === 'object' && x !== null) || typeof x === 'function'; -} -const rethrowAssertionErrorRejection = noop; - -const originalPromise = Promise; -const originalPromiseThen = Promise.prototype.then; -const originalPromiseResolve = Promise.resolve.bind(originalPromise); -const originalPromiseReject = Promise.reject.bind(originalPromise); -function newPromise(executor) { - return new originalPromise(executor); -} -function promiseResolvedWith(value) { - return originalPromiseResolve(value); -} -function promiseRejectedWith(reason) { - return originalPromiseReject(reason); -} -function PerformPromiseThen(promise, onFulfilled, onRejected) { - // There doesn't appear to be any way to correctly emulate the behaviour from JavaScript, so this is just an - // approximation. - return originalPromiseThen.call(promise, onFulfilled, onRejected); -} -function uponPromise(promise, onFulfilled, onRejected) { - PerformPromiseThen(PerformPromiseThen(promise, onFulfilled, onRejected), undefined, rethrowAssertionErrorRejection); -} -function uponFulfillment(promise, onFulfilled) { - uponPromise(promise, onFulfilled); -} -function uponRejection(promise, onRejected) { - uponPromise(promise, undefined, onRejected); -} -function transformPromiseWith(promise, fulfillmentHandler, rejectionHandler) { - return PerformPromiseThen(promise, fulfillmentHandler, rejectionHandler); -} -function setPromiseIsHandledToTrue(promise) { - PerformPromiseThen(promise, undefined, rethrowAssertionErrorRejection); -} -const queueMicrotask = (() => { - const globalQueueMicrotask = globals && globals.queueMicrotask; - if (typeof globalQueueMicrotask === 'function') { - return globalQueueMicrotask; - } - const resolvedPromise = promiseResolvedWith(undefined); - return (fn) => PerformPromiseThen(resolvedPromise, fn); -})(); -function reflectCall(F, V, args) { - if (typeof F !== 'function') { - throw new TypeError('Argument is not a function'); - } - return Function.prototype.apply.call(F, V, args); -} -function promiseCall(F, V, args) { - try { - return promiseResolvedWith(reflectCall(F, V, args)); - } - catch (value) { - return promiseRejectedWith(value); - } -} - -// Original from Chromium -// https://chromium.googlesource.com/chromium/src/+/0aee4434a4dba42a42abaea9bfbc0cd196a63bc1/third_party/blink/renderer/core/streams/SimpleQueue.js -const QUEUE_MAX_ARRAY_SIZE = 16384; -/** - * Simple queue structure. - * - * Avoids scalability issues with using a packed array directly by using - * multiple arrays in a linked list and keeping the array size bounded. - */ -class SimpleQueue { - constructor() { - this._cursor = 0; - this._size = 0; - // _front and _back are always defined. - this._front = { - _elements: [], - _next: undefined - }; - this._back = this._front; - // The cursor is used to avoid calling Array.shift(). - // It contains the index of the front element of the array inside the - // front-most node. It is always in the range [0, QUEUE_MAX_ARRAY_SIZE). - this._cursor = 0; - // When there is only one node, size === elements.length - cursor. - this._size = 0; - } - get length() { - return this._size; - } - // For exception safety, this method is structured in order: - // 1. Read state - // 2. Calculate required state mutations - // 3. Perform state mutations - push(element) { - const oldBack = this._back; - let newBack = oldBack; - if (oldBack._elements.length === QUEUE_MAX_ARRAY_SIZE - 1) { - newBack = { - _elements: [], - _next: undefined - }; - } - // push() is the mutation most likely to throw an exception, so it - // goes first. - oldBack._elements.push(element); - if (newBack !== oldBack) { - this._back = newBack; - oldBack._next = newBack; - } - ++this._size; - } - // Like push(), shift() follows the read -> calculate -> mutate pattern for - // exception safety. - shift() { // must not be called on an empty queue - const oldFront = this._front; - let newFront = oldFront; - const oldCursor = this._cursor; - let newCursor = oldCursor + 1; - const elements = oldFront._elements; - const element = elements[oldCursor]; - if (newCursor === QUEUE_MAX_ARRAY_SIZE) { - newFront = oldFront._next; - newCursor = 0; - } - // No mutations before this point. - --this._size; - this._cursor = newCursor; - if (oldFront !== newFront) { - this._front = newFront; - } - // Permit shifted element to be garbage collected. - elements[oldCursor] = undefined; - return element; - } - // The tricky thing about forEach() is that it can be called - // re-entrantly. The queue may be mutated inside the callback. It is easy to - // see that push() within the callback has no negative effects since the end - // of the queue is checked for on every iteration. If shift() is called - // repeatedly within the callback then the next iteration may return an - // element that has been removed. In this case the callback will be called - // with undefined values until we either "catch up" with elements that still - // exist or reach the back of the queue. - forEach(callback) { - let i = this._cursor; - let node = this._front; - let elements = node._elements; - while (i !== elements.length || node._next !== undefined) { - if (i === elements.length) { - node = node._next; - elements = node._elements; - i = 0; - if (elements.length === 0) { - break; - } - } - callback(elements[i]); - ++i; - } - } - // Return the element that would be returned if shift() was called now, - // without modifying the queue. - peek() { // must not be called on an empty queue - const front = this._front; - const cursor = this._cursor; - return front._elements[cursor]; - } -} - -function ReadableStreamReaderGenericInitialize(reader, stream) { - reader._ownerReadableStream = stream; - stream._reader = reader; - if (stream._state === 'readable') { - defaultReaderClosedPromiseInitialize(reader); - } - else if (stream._state === 'closed') { - defaultReaderClosedPromiseInitializeAsResolved(reader); - } - else { - defaultReaderClosedPromiseInitializeAsRejected(reader, stream._storedError); - } -} -// A client of ReadableStreamDefaultReader and ReadableStreamBYOBReader may use these functions directly to bypass state -// check. -function ReadableStreamReaderGenericCancel(reader, reason) { - const stream = reader._ownerReadableStream; - return ReadableStreamCancel(stream, reason); -} -function ReadableStreamReaderGenericRelease(reader) { - if (reader._ownerReadableStream._state === 'readable') { - defaultReaderClosedPromiseReject(reader, new TypeError(`Reader was released and can no longer be used to monitor the stream's closedness`)); - } - else { - defaultReaderClosedPromiseResetToRejected(reader, new TypeError(`Reader was released and can no longer be used to monitor the stream's closedness`)); - } - reader._ownerReadableStream._reader = undefined; - reader._ownerReadableStream = undefined; -} -// Helper functions for the readers. -function readerLockException(name) { - return new TypeError('Cannot ' + name + ' a stream using a released reader'); -} -// Helper functions for the ReadableStreamDefaultReader. -function defaultReaderClosedPromiseInitialize(reader) { - reader._closedPromise = newPromise((resolve, reject) => { - reader._closedPromise_resolve = resolve; - reader._closedPromise_reject = reject; - }); -} -function defaultReaderClosedPromiseInitializeAsRejected(reader, reason) { - defaultReaderClosedPromiseInitialize(reader); - defaultReaderClosedPromiseReject(reader, reason); -} -function defaultReaderClosedPromiseInitializeAsResolved(reader) { - defaultReaderClosedPromiseInitialize(reader); - defaultReaderClosedPromiseResolve(reader); -} -function defaultReaderClosedPromiseReject(reader, reason) { - if (reader._closedPromise_reject === undefined) { - return; - } - setPromiseIsHandledToTrue(reader._closedPromise); - reader._closedPromise_reject(reason); - reader._closedPromise_resolve = undefined; - reader._closedPromise_reject = undefined; -} -function defaultReaderClosedPromiseResetToRejected(reader, reason) { - defaultReaderClosedPromiseInitializeAsRejected(reader, reason); -} -function defaultReaderClosedPromiseResolve(reader) { - if (reader._closedPromise_resolve === undefined) { - return; - } - reader._closedPromise_resolve(undefined); - reader._closedPromise_resolve = undefined; - reader._closedPromise_reject = undefined; -} - -const AbortSteps = SymbolPolyfill('[[AbortSteps]]'); -const ErrorSteps = SymbolPolyfill('[[ErrorSteps]]'); -const CancelSteps = SymbolPolyfill('[[CancelSteps]]'); -const PullSteps = SymbolPolyfill('[[PullSteps]]'); - -/// -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isFinite#Polyfill -const NumberIsFinite = Number.isFinite || function (x) { - return typeof x === 'number' && isFinite(x); -}; - -/// -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc#Polyfill -const MathTrunc = Math.trunc || function (v) { - return v < 0 ? Math.ceil(v) : Math.floor(v); -}; - -// https://heycam.github.io/webidl/#idl-dictionaries -function isDictionary(x) { - return typeof x === 'object' || typeof x === 'function'; -} -function assertDictionary(obj, context) { - if (obj !== undefined && !isDictionary(obj)) { - throw new TypeError(`${context} is not an object.`); - } -} -// https://heycam.github.io/webidl/#idl-callback-functions -function assertFunction(x, context) { - if (typeof x !== 'function') { - throw new TypeError(`${context} is not a function.`); - } -} -// https://heycam.github.io/webidl/#idl-object -function isObject(x) { - return (typeof x === 'object' && x !== null) || typeof x === 'function'; -} -function assertObject(x, context) { - if (!isObject(x)) { - throw new TypeError(`${context} is not an object.`); - } -} -function assertRequiredArgument(x, position, context) { - if (x === undefined) { - throw new TypeError(`Parameter ${position} is required in '${context}'.`); - } -} -function assertRequiredField(x, field, context) { - if (x === undefined) { - throw new TypeError(`${field} is required in '${context}'.`); - } -} -// https://heycam.github.io/webidl/#idl-unrestricted-double -function convertUnrestrictedDouble(value) { - return Number(value); -} -function censorNegativeZero(x) { - return x === 0 ? 0 : x; -} -function integerPart(x) { - return censorNegativeZero(MathTrunc(x)); -} -// https://heycam.github.io/webidl/#idl-unsigned-long-long -function convertUnsignedLongLongWithEnforceRange(value, context) { - const lowerBound = 0; - const upperBound = Number.MAX_SAFE_INTEGER; - let x = Number(value); - x = censorNegativeZero(x); - if (!NumberIsFinite(x)) { - throw new TypeError(`${context} is not a finite number`); - } - x = integerPart(x); - if (x < lowerBound || x > upperBound) { - throw new TypeError(`${context} is outside the accepted range of ${lowerBound} to ${upperBound}, inclusive`); - } - if (!NumberIsFinite(x) || x === 0) { - return 0; - } - // TODO Use BigInt if supported? - // let xBigInt = BigInt(integerPart(x)); - // xBigInt = BigInt.asUintN(64, xBigInt); - // return Number(xBigInt); - return x; -} - -function assertReadableStream(x, context) { - if (!IsReadableStream(x)) { - throw new TypeError(`${context} is not a ReadableStream.`); - } -} - -// Abstract operations for the ReadableStream. -function AcquireReadableStreamDefaultReader(stream) { - return new ReadableStreamDefaultReader(stream); -} -// ReadableStream API exposed for controllers. -function ReadableStreamAddReadRequest(stream, readRequest) { - stream._reader._readRequests.push(readRequest); -} -function ReadableStreamFulfillReadRequest(stream, chunk, done) { - const reader = stream._reader; - const readRequest = reader._readRequests.shift(); - if (done) { - readRequest._closeSteps(); - } - else { - readRequest._chunkSteps(chunk); - } -} -function ReadableStreamGetNumReadRequests(stream) { - return stream._reader._readRequests.length; -} -function ReadableStreamHasDefaultReader(stream) { - const reader = stream._reader; - if (reader === undefined) { - return false; - } - if (!IsReadableStreamDefaultReader(reader)) { - return false; - } - return true; -} -/** - * A default reader vended by a {@link ReadableStream}. - * - * @public - */ -class ReadableStreamDefaultReader { - constructor(stream) { - assertRequiredArgument(stream, 1, 'ReadableStreamDefaultReader'); - assertReadableStream(stream, 'First parameter'); - if (IsReadableStreamLocked(stream)) { - throw new TypeError('This stream has already been locked for exclusive reading by another reader'); - } - ReadableStreamReaderGenericInitialize(this, stream); - this._readRequests = new SimpleQueue(); - } - /** - * Returns a promise that will be fulfilled when the stream becomes closed, - * or rejected if the stream ever errors or the reader's lock is released before the stream finishes closing. - */ - get closed() { - if (!IsReadableStreamDefaultReader(this)) { - return promiseRejectedWith(defaultReaderBrandCheckException('closed')); - } - return this._closedPromise; - } - /** - * If the reader is active, behaves the same as {@link ReadableStream.cancel | stream.cancel(reason)}. - */ - cancel(reason = undefined) { - if (!IsReadableStreamDefaultReader(this)) { - return promiseRejectedWith(defaultReaderBrandCheckException('cancel')); - } - if (this._ownerReadableStream === undefined) { - return promiseRejectedWith(readerLockException('cancel')); - } - return ReadableStreamReaderGenericCancel(this, reason); - } - /** - * Returns a promise that allows access to the next chunk from the stream's internal queue, if available. - * - * If reading a chunk causes the queue to become empty, more data will be pulled from the underlying source. - */ - read() { - if (!IsReadableStreamDefaultReader(this)) { - return promiseRejectedWith(defaultReaderBrandCheckException('read')); - } - if (this._ownerReadableStream === undefined) { - return promiseRejectedWith(readerLockException('read from')); - } - let resolvePromise; - let rejectPromise; - const promise = newPromise((resolve, reject) => { - resolvePromise = resolve; - rejectPromise = reject; - }); - const readRequest = { - _chunkSteps: chunk => resolvePromise({ value: chunk, done: false }), - _closeSteps: () => resolvePromise({ value: undefined, done: true }), - _errorSteps: e => rejectPromise(e) - }; - ReadableStreamDefaultReaderRead(this, readRequest); - return promise; - } - /** - * Releases the reader's lock on the corresponding stream. After the lock is released, the reader is no longer active. - * If the associated stream is errored when the lock is released, the reader will appear errored in the same way - * from now on; otherwise, the reader will appear closed. - * - * A reader's lock cannot be released while it still has a pending read request, i.e., if a promise returned by - * the reader's {@link ReadableStreamDefaultReader.read | read()} method has not yet been settled. Attempting to - * do so will throw a `TypeError` and leave the reader locked to the stream. - */ - releaseLock() { - if (!IsReadableStreamDefaultReader(this)) { - throw defaultReaderBrandCheckException('releaseLock'); - } - if (this._ownerReadableStream === undefined) { - return; - } - if (this._readRequests.length > 0) { - throw new TypeError('Tried to release a reader lock when that reader has pending read() calls un-settled'); - } - ReadableStreamReaderGenericRelease(this); - } -} -Object.defineProperties(ReadableStreamDefaultReader.prototype, { - cancel: { enumerable: true }, - read: { enumerable: true }, - releaseLock: { enumerable: true }, - closed: { enumerable: true } -}); -if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(ReadableStreamDefaultReader.prototype, SymbolPolyfill.toStringTag, { - value: 'ReadableStreamDefaultReader', - configurable: true - }); -} -// Abstract operations for the readers. -function IsReadableStreamDefaultReader(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_readRequests')) { - return false; - } - return true; -} -function ReadableStreamDefaultReaderRead(reader, readRequest) { - const stream = reader._ownerReadableStream; - stream._disturbed = true; - if (stream._state === 'closed') { - readRequest._closeSteps(); - } - else if (stream._state === 'errored') { - readRequest._errorSteps(stream._storedError); - } - else { - stream._readableStreamController[PullSteps](readRequest); - } -} -// Helper functions for the ReadableStreamDefaultReader. -function defaultReaderBrandCheckException(name) { - return new TypeError(`ReadableStreamDefaultReader.prototype.${name} can only be used on a ReadableStreamDefaultReader`); -} - -/// -let AsyncIteratorPrototype; -if (typeof SymbolPolyfill.asyncIterator === 'symbol') { - // We're running inside a ES2018+ environment, but we're compiling to an older syntax. - // We cannot access %AsyncIteratorPrototype% without non-ES2018 syntax, but we can re-create it. - AsyncIteratorPrototype = { - // 25.1.3.1 %AsyncIteratorPrototype% [ @@asyncIterator ] ( ) - // https://tc39.github.io/ecma262/#sec-asynciteratorprototype-asynciterator - [SymbolPolyfill.asyncIterator]() { - return this; - } - }; - Object.defineProperty(AsyncIteratorPrototype, SymbolPolyfill.asyncIterator, { enumerable: false }); -} - -/// -class ReadableStreamAsyncIteratorImpl { - constructor(reader, preventCancel) { - this._ongoingPromise = undefined; - this._isFinished = false; - this._reader = reader; - this._preventCancel = preventCancel; - } - next() { - const nextSteps = () => this._nextSteps(); - this._ongoingPromise = this._ongoingPromise ? - transformPromiseWith(this._ongoingPromise, nextSteps, nextSteps) : - nextSteps(); - return this._ongoingPromise; - } - return(value) { - const returnSteps = () => this._returnSteps(value); - return this._ongoingPromise ? - transformPromiseWith(this._ongoingPromise, returnSteps, returnSteps) : - returnSteps(); - } - _nextSteps() { - if (this._isFinished) { - return Promise.resolve({ value: undefined, done: true }); - } - const reader = this._reader; - if (reader._ownerReadableStream === undefined) { - return promiseRejectedWith(readerLockException('iterate')); - } - let resolvePromise; - let rejectPromise; - const promise = newPromise((resolve, reject) => { - resolvePromise = resolve; - rejectPromise = reject; - }); - const readRequest = { - _chunkSteps: chunk => { - this._ongoingPromise = undefined; - // This needs to be delayed by one microtask, otherwise we stop pulling too early which breaks a test. - // FIXME Is this a bug in the specification, or in the test? - queueMicrotask(() => resolvePromise({ value: chunk, done: false })); - }, - _closeSteps: () => { - this._ongoingPromise = undefined; - this._isFinished = true; - ReadableStreamReaderGenericRelease(reader); - resolvePromise({ value: undefined, done: true }); - }, - _errorSteps: reason => { - this._ongoingPromise = undefined; - this._isFinished = true; - ReadableStreamReaderGenericRelease(reader); - rejectPromise(reason); - } - }; - ReadableStreamDefaultReaderRead(reader, readRequest); - return promise; - } - _returnSteps(value) { - if (this._isFinished) { - return Promise.resolve({ value, done: true }); - } - this._isFinished = true; - const reader = this._reader; - if (reader._ownerReadableStream === undefined) { - return promiseRejectedWith(readerLockException('finish iterating')); - } - if (!this._preventCancel) { - const result = ReadableStreamReaderGenericCancel(reader, value); - ReadableStreamReaderGenericRelease(reader); - return transformPromiseWith(result, () => ({ value, done: true })); - } - ReadableStreamReaderGenericRelease(reader); - return promiseResolvedWith({ value, done: true }); - } -} -const ReadableStreamAsyncIteratorPrototype = { - next() { - if (!IsReadableStreamAsyncIterator(this)) { - return promiseRejectedWith(streamAsyncIteratorBrandCheckException('next')); - } - return this._asyncIteratorImpl.next(); - }, - return(value) { - if (!IsReadableStreamAsyncIterator(this)) { - return promiseRejectedWith(streamAsyncIteratorBrandCheckException('return')); - } - return this._asyncIteratorImpl.return(value); - } -}; -if (AsyncIteratorPrototype !== undefined) { - Object.setPrototypeOf(ReadableStreamAsyncIteratorPrototype, AsyncIteratorPrototype); -} -// Abstract operations for the ReadableStream. -function AcquireReadableStreamAsyncIterator(stream, preventCancel) { - const reader = AcquireReadableStreamDefaultReader(stream); - const impl = new ReadableStreamAsyncIteratorImpl(reader, preventCancel); - const iterator = Object.create(ReadableStreamAsyncIteratorPrototype); - iterator._asyncIteratorImpl = impl; - return iterator; -} -function IsReadableStreamAsyncIterator(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_asyncIteratorImpl')) { - return false; - } - return true; -} -// Helper functions for the ReadableStream. -function streamAsyncIteratorBrandCheckException(name) { - return new TypeError(`ReadableStreamAsyncIterator.${name} can only be used on a ReadableSteamAsyncIterator`); -} - -/// -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN#Polyfill -const NumberIsNaN = Number.isNaN || function (x) { - // eslint-disable-next-line no-self-compare - return x !== x; -}; - -function IsFiniteNonNegativeNumber(v) { - if (!IsNonNegativeNumber(v)) { - return false; - } - if (v === Infinity) { - return false; - } - return true; -} -function IsNonNegativeNumber(v) { - if (typeof v !== 'number') { - return false; - } - if (NumberIsNaN(v)) { - return false; - } - if (v < 0) { - return false; - } - return true; -} - -function DequeueValue(container) { - const pair = container._queue.shift(); - container._queueTotalSize -= pair.size; - if (container._queueTotalSize < 0) { - container._queueTotalSize = 0; - } - return pair.value; -} -function EnqueueValueWithSize(container, value, size) { - size = Number(size); - if (!IsFiniteNonNegativeNumber(size)) { - throw new RangeError('Size must be a finite, non-NaN, non-negative number.'); - } - container._queue.push({ value, size }); - container._queueTotalSize += size; -} -function PeekQueueValue(container) { - const pair = container._queue.peek(); - return pair.value; -} -function ResetQueue(container) { - container._queue = new SimpleQueue(); - container._queueTotalSize = 0; -} - -function CreateArrayFromList(elements) { - // We use arrays to represent lists, so this is basically a no-op. - // Do a slice though just in case we happen to depend on the unique-ness. - return elements.slice(); -} -function CopyDataBlockBytes(dest, destOffset, src, srcOffset, n) { - new Uint8Array(dest).set(new Uint8Array(src, srcOffset, n), destOffset); -} -// Not implemented correctly -function TransferArrayBuffer(O) { - return O; -} -// Not implemented correctly -function IsDetachedBuffer(O) { - return false; -} - -/** - * A pull-into request in a {@link ReadableByteStreamController}. - * - * @public - */ -class ReadableStreamBYOBRequest { - constructor() { - throw new TypeError('Illegal constructor'); - } - /** - * Returns the view for writing in to, or `null` if the BYOB request has already been responded to. - */ - get view() { - if (!IsReadableStreamBYOBRequest(this)) { - throw byobRequestBrandCheckException('view'); - } - return this._view; - } - respond(bytesWritten) { - if (!IsReadableStreamBYOBRequest(this)) { - throw byobRequestBrandCheckException('respond'); - } - assertRequiredArgument(bytesWritten, 1, 'respond'); - bytesWritten = convertUnsignedLongLongWithEnforceRange(bytesWritten, 'First parameter'); - if (this._associatedReadableByteStreamController === undefined) { - throw new TypeError('This BYOB request has been invalidated'); - } - if (IsDetachedBuffer(this._view.buffer)) ; - ReadableByteStreamControllerRespond(this._associatedReadableByteStreamController, bytesWritten); - } - respondWithNewView(view) { - if (!IsReadableStreamBYOBRequest(this)) { - throw byobRequestBrandCheckException('respondWithNewView'); - } - assertRequiredArgument(view, 1, 'respondWithNewView'); - if (!ArrayBuffer.isView(view)) { - throw new TypeError('You can only respond with array buffer views'); - } - if (view.byteLength === 0) { - throw new TypeError('chunk must have non-zero byteLength'); - } - if (view.buffer.byteLength === 0) { - throw new TypeError(`chunk's buffer must have non-zero byteLength`); - } - if (this._associatedReadableByteStreamController === undefined) { - throw new TypeError('This BYOB request has been invalidated'); - } - ReadableByteStreamControllerRespondWithNewView(this._associatedReadableByteStreamController, view); - } -} -Object.defineProperties(ReadableStreamBYOBRequest.prototype, { - respond: { enumerable: true }, - respondWithNewView: { enumerable: true }, - view: { enumerable: true } -}); -if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(ReadableStreamBYOBRequest.prototype, SymbolPolyfill.toStringTag, { - value: 'ReadableStreamBYOBRequest', - configurable: true - }); -} -/** - * Allows control of a {@link ReadableStream | readable byte stream}'s state and internal queue. - * - * @public - */ -class ReadableByteStreamController { - constructor() { - throw new TypeError('Illegal constructor'); - } - /** - * Returns the current BYOB pull request, or `null` if there isn't one. - */ - get byobRequest() { - if (!IsReadableByteStreamController(this)) { - throw byteStreamControllerBrandCheckException('byobRequest'); - } - if (this._byobRequest === null && this._pendingPullIntos.length > 0) { - const firstDescriptor = this._pendingPullIntos.peek(); - const view = new Uint8Array(firstDescriptor.buffer, firstDescriptor.byteOffset + firstDescriptor.bytesFilled, firstDescriptor.byteLength - firstDescriptor.bytesFilled); - const byobRequest = Object.create(ReadableStreamBYOBRequest.prototype); - SetUpReadableStreamBYOBRequest(byobRequest, this, view); - this._byobRequest = byobRequest; - } - return this._byobRequest; - } - /** - * Returns the desired size to fill the controlled stream's internal queue. It can be negative, if the queue is - * over-full. An underlying byte source ought to use this information to determine when and how to apply backpressure. - */ - get desiredSize() { - if (!IsReadableByteStreamController(this)) { - throw byteStreamControllerBrandCheckException('desiredSize'); - } - return ReadableByteStreamControllerGetDesiredSize(this); - } - /** - * Closes the controlled readable stream. Consumers will still be able to read any previously-enqueued chunks from - * the stream, but once those are read, the stream will become closed. - */ - close() { - if (!IsReadableByteStreamController(this)) { - throw byteStreamControllerBrandCheckException('close'); - } - if (this._closeRequested) { - throw new TypeError('The stream has already been closed; do not close it again!'); - } - const state = this._controlledReadableByteStream._state; - if (state !== 'readable') { - throw new TypeError(`The stream (in ${state} state) is not in the readable state and cannot be closed`); - } - ReadableByteStreamControllerClose(this); - } - enqueue(chunk) { - if (!IsReadableByteStreamController(this)) { - throw byteStreamControllerBrandCheckException('enqueue'); - } - assertRequiredArgument(chunk, 1, 'enqueue'); - if (!ArrayBuffer.isView(chunk)) { - throw new TypeError('chunk must be an array buffer view'); - } - if (chunk.byteLength === 0) { - throw new TypeError('chunk must have non-zero byteLength'); - } - if (chunk.buffer.byteLength === 0) { - throw new TypeError(`chunk's buffer must have non-zero byteLength`); - } - if (this._closeRequested) { - throw new TypeError('stream is closed or draining'); - } - const state = this._controlledReadableByteStream._state; - if (state !== 'readable') { - throw new TypeError(`The stream (in ${state} state) is not in the readable state and cannot be enqueued to`); - } - ReadableByteStreamControllerEnqueue(this, chunk); - } - /** - * Errors the controlled readable stream, making all future interactions with it fail with the given error `e`. - */ - error(e = undefined) { - if (!IsReadableByteStreamController(this)) { - throw byteStreamControllerBrandCheckException('error'); - } - ReadableByteStreamControllerError(this, e); - } - /** @internal */ - [CancelSteps](reason) { - if (this._pendingPullIntos.length > 0) { - const firstDescriptor = this._pendingPullIntos.peek(); - firstDescriptor.bytesFilled = 0; - } - ResetQueue(this); - const result = this._cancelAlgorithm(reason); - ReadableByteStreamControllerClearAlgorithms(this); - return result; - } - /** @internal */ - [PullSteps](readRequest) { - const stream = this._controlledReadableByteStream; - if (this._queueTotalSize > 0) { - const entry = this._queue.shift(); - this._queueTotalSize -= entry.byteLength; - ReadableByteStreamControllerHandleQueueDrain(this); - const view = new Uint8Array(entry.buffer, entry.byteOffset, entry.byteLength); - readRequest._chunkSteps(view); - return; - } - const autoAllocateChunkSize = this._autoAllocateChunkSize; - if (autoAllocateChunkSize !== undefined) { - let buffer; - try { - buffer = new ArrayBuffer(autoAllocateChunkSize); - } - catch (bufferE) { - readRequest._errorSteps(bufferE); - return; - } - const pullIntoDescriptor = { - buffer, - byteOffset: 0, - byteLength: autoAllocateChunkSize, - bytesFilled: 0, - elementSize: 1, - viewConstructor: Uint8Array, - readerType: 'default' - }; - this._pendingPullIntos.push(pullIntoDescriptor); - } - ReadableStreamAddReadRequest(stream, readRequest); - ReadableByteStreamControllerCallPullIfNeeded(this); - } -} -Object.defineProperties(ReadableByteStreamController.prototype, { - close: { enumerable: true }, - enqueue: { enumerable: true }, - error: { enumerable: true }, - byobRequest: { enumerable: true }, - desiredSize: { enumerable: true } -}); -if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(ReadableByteStreamController.prototype, SymbolPolyfill.toStringTag, { - value: 'ReadableByteStreamController', - configurable: true - }); -} -// Abstract operations for the ReadableByteStreamController. -function IsReadableByteStreamController(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_controlledReadableByteStream')) { - return false; - } - return true; -} -function IsReadableStreamBYOBRequest(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_associatedReadableByteStreamController')) { - return false; - } - return true; -} -function ReadableByteStreamControllerCallPullIfNeeded(controller) { - const shouldPull = ReadableByteStreamControllerShouldCallPull(controller); - if (!shouldPull) { - return; - } - if (controller._pulling) { - controller._pullAgain = true; - return; - } - controller._pulling = true; - // TODO: Test controller argument - const pullPromise = controller._pullAlgorithm(); - uponPromise(pullPromise, () => { - controller._pulling = false; - if (controller._pullAgain) { - controller._pullAgain = false; - ReadableByteStreamControllerCallPullIfNeeded(controller); - } - }, e => { - ReadableByteStreamControllerError(controller, e); - }); -} -function ReadableByteStreamControllerClearPendingPullIntos(controller) { - ReadableByteStreamControllerInvalidateBYOBRequest(controller); - controller._pendingPullIntos = new SimpleQueue(); -} -function ReadableByteStreamControllerCommitPullIntoDescriptor(stream, pullIntoDescriptor) { - let done = false; - if (stream._state === 'closed') { - done = true; - } - const filledView = ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor); - if (pullIntoDescriptor.readerType === 'default') { - ReadableStreamFulfillReadRequest(stream, filledView, done); - } - else { - ReadableStreamFulfillReadIntoRequest(stream, filledView, done); - } -} -function ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor) { - const bytesFilled = pullIntoDescriptor.bytesFilled; - const elementSize = pullIntoDescriptor.elementSize; - return new pullIntoDescriptor.viewConstructor(pullIntoDescriptor.buffer, pullIntoDescriptor.byteOffset, bytesFilled / elementSize); -} -function ReadableByteStreamControllerEnqueueChunkToQueue(controller, buffer, byteOffset, byteLength) { - controller._queue.push({ buffer, byteOffset, byteLength }); - controller._queueTotalSize += byteLength; -} -function ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor) { - const elementSize = pullIntoDescriptor.elementSize; - const currentAlignedBytes = pullIntoDescriptor.bytesFilled - pullIntoDescriptor.bytesFilled % elementSize; - const maxBytesToCopy = Math.min(controller._queueTotalSize, pullIntoDescriptor.byteLength - pullIntoDescriptor.bytesFilled); - const maxBytesFilled = pullIntoDescriptor.bytesFilled + maxBytesToCopy; - const maxAlignedBytes = maxBytesFilled - maxBytesFilled % elementSize; - let totalBytesToCopyRemaining = maxBytesToCopy; - let ready = false; - if (maxAlignedBytes > currentAlignedBytes) { - totalBytesToCopyRemaining = maxAlignedBytes - pullIntoDescriptor.bytesFilled; - ready = true; - } - const queue = controller._queue; - while (totalBytesToCopyRemaining > 0) { - const headOfQueue = queue.peek(); - const bytesToCopy = Math.min(totalBytesToCopyRemaining, headOfQueue.byteLength); - const destStart = pullIntoDescriptor.byteOffset + pullIntoDescriptor.bytesFilled; - CopyDataBlockBytes(pullIntoDescriptor.buffer, destStart, headOfQueue.buffer, headOfQueue.byteOffset, bytesToCopy); - if (headOfQueue.byteLength === bytesToCopy) { - queue.shift(); - } - else { - headOfQueue.byteOffset += bytesToCopy; - headOfQueue.byteLength -= bytesToCopy; - } - controller._queueTotalSize -= bytesToCopy; - ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, bytesToCopy, pullIntoDescriptor); - totalBytesToCopyRemaining -= bytesToCopy; - } - return ready; -} -function ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, size, pullIntoDescriptor) { - ReadableByteStreamControllerInvalidateBYOBRequest(controller); - pullIntoDescriptor.bytesFilled += size; -} -function ReadableByteStreamControllerHandleQueueDrain(controller) { - if (controller._queueTotalSize === 0 && controller._closeRequested) { - ReadableByteStreamControllerClearAlgorithms(controller); - ReadableStreamClose(controller._controlledReadableByteStream); - } - else { - ReadableByteStreamControllerCallPullIfNeeded(controller); - } -} -function ReadableByteStreamControllerInvalidateBYOBRequest(controller) { - if (controller._byobRequest === null) { - return; - } - controller._byobRequest._associatedReadableByteStreamController = undefined; - controller._byobRequest._view = null; - controller._byobRequest = null; -} -function ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller) { - while (controller._pendingPullIntos.length > 0) { - if (controller._queueTotalSize === 0) { - return; - } - const pullIntoDescriptor = controller._pendingPullIntos.peek(); - if (ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor)) { - ReadableByteStreamControllerShiftPendingPullInto(controller); - ReadableByteStreamControllerCommitPullIntoDescriptor(controller._controlledReadableByteStream, pullIntoDescriptor); - } - } -} -function ReadableByteStreamControllerPullInto(controller, view, readIntoRequest) { - const stream = controller._controlledReadableByteStream; - let elementSize = 1; - if (view.constructor !== DataView) { - elementSize = view.constructor.BYTES_PER_ELEMENT; - } - const ctor = view.constructor; - const buffer = TransferArrayBuffer(view.buffer); - const pullIntoDescriptor = { - buffer, - byteOffset: view.byteOffset, - byteLength: view.byteLength, - bytesFilled: 0, - elementSize, - viewConstructor: ctor, - readerType: 'byob' - }; - if (controller._pendingPullIntos.length > 0) { - controller._pendingPullIntos.push(pullIntoDescriptor); - // No ReadableByteStreamControllerCallPullIfNeeded() call since: - // - No change happens on desiredSize - // - The source has already been notified of that there's at least 1 pending read(view) - ReadableStreamAddReadIntoRequest(stream, readIntoRequest); - return; - } - if (stream._state === 'closed') { - const emptyView = new ctor(pullIntoDescriptor.buffer, pullIntoDescriptor.byteOffset, 0); - readIntoRequest._closeSteps(emptyView); - return; - } - if (controller._queueTotalSize > 0) { - if (ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor)) { - const filledView = ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor); - ReadableByteStreamControllerHandleQueueDrain(controller); - readIntoRequest._chunkSteps(filledView); - return; - } - if (controller._closeRequested) { - const e = new TypeError('Insufficient bytes to fill elements in the given buffer'); - ReadableByteStreamControllerError(controller, e); - readIntoRequest._errorSteps(e); - return; - } - } - controller._pendingPullIntos.push(pullIntoDescriptor); - ReadableStreamAddReadIntoRequest(stream, readIntoRequest); - ReadableByteStreamControllerCallPullIfNeeded(controller); -} -function ReadableByteStreamControllerRespondInClosedState(controller, firstDescriptor) { - firstDescriptor.buffer = TransferArrayBuffer(firstDescriptor.buffer); - const stream = controller._controlledReadableByteStream; - if (ReadableStreamHasBYOBReader(stream)) { - while (ReadableStreamGetNumReadIntoRequests(stream) > 0) { - const pullIntoDescriptor = ReadableByteStreamControllerShiftPendingPullInto(controller); - ReadableByteStreamControllerCommitPullIntoDescriptor(stream, pullIntoDescriptor); - } - } -} -function ReadableByteStreamControllerRespondInReadableState(controller, bytesWritten, pullIntoDescriptor) { - if (pullIntoDescriptor.bytesFilled + bytesWritten > pullIntoDescriptor.byteLength) { - throw new RangeError('bytesWritten out of range'); - } - ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, bytesWritten, pullIntoDescriptor); - if (pullIntoDescriptor.bytesFilled < pullIntoDescriptor.elementSize) { - // TODO: Figure out whether we should detach the buffer or not here. - return; - } - ReadableByteStreamControllerShiftPendingPullInto(controller); - const remainderSize = pullIntoDescriptor.bytesFilled % pullIntoDescriptor.elementSize; - if (remainderSize > 0) { - const end = pullIntoDescriptor.byteOffset + pullIntoDescriptor.bytesFilled; - const remainder = pullIntoDescriptor.buffer.slice(end - remainderSize, end); - ReadableByteStreamControllerEnqueueChunkToQueue(controller, remainder, 0, remainder.byteLength); - } - pullIntoDescriptor.buffer = TransferArrayBuffer(pullIntoDescriptor.buffer); - pullIntoDescriptor.bytesFilled -= remainderSize; - ReadableByteStreamControllerCommitPullIntoDescriptor(controller._controlledReadableByteStream, pullIntoDescriptor); - ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller); -} -function ReadableByteStreamControllerRespondInternal(controller, bytesWritten) { - const firstDescriptor = controller._pendingPullIntos.peek(); - const state = controller._controlledReadableByteStream._state; - if (state === 'closed') { - if (bytesWritten !== 0) { - throw new TypeError('bytesWritten must be 0 when calling respond() on a closed stream'); - } - ReadableByteStreamControllerRespondInClosedState(controller, firstDescriptor); - } - else { - ReadableByteStreamControllerRespondInReadableState(controller, bytesWritten, firstDescriptor); - } - ReadableByteStreamControllerCallPullIfNeeded(controller); -} -function ReadableByteStreamControllerShiftPendingPullInto(controller) { - const descriptor = controller._pendingPullIntos.shift(); - ReadableByteStreamControllerInvalidateBYOBRequest(controller); - return descriptor; -} -function ReadableByteStreamControllerShouldCallPull(controller) { - const stream = controller._controlledReadableByteStream; - if (stream._state !== 'readable') { - return false; - } - if (controller._closeRequested) { - return false; - } - if (!controller._started) { - return false; - } - if (ReadableStreamHasDefaultReader(stream) && ReadableStreamGetNumReadRequests(stream) > 0) { - return true; - } - if (ReadableStreamHasBYOBReader(stream) && ReadableStreamGetNumReadIntoRequests(stream) > 0) { - return true; - } - const desiredSize = ReadableByteStreamControllerGetDesiredSize(controller); - if (desiredSize > 0) { - return true; - } - return false; -} -function ReadableByteStreamControllerClearAlgorithms(controller) { - controller._pullAlgorithm = undefined; - controller._cancelAlgorithm = undefined; -} -// A client of ReadableByteStreamController may use these functions directly to bypass state check. -function ReadableByteStreamControllerClose(controller) { - const stream = controller._controlledReadableByteStream; - if (controller._closeRequested || stream._state !== 'readable') { - return; - } - if (controller._queueTotalSize > 0) { - controller._closeRequested = true; - return; - } - if (controller._pendingPullIntos.length > 0) { - const firstPendingPullInto = controller._pendingPullIntos.peek(); - if (firstPendingPullInto.bytesFilled > 0) { - const e = new TypeError('Insufficient bytes to fill elements in the given buffer'); - ReadableByteStreamControllerError(controller, e); - throw e; - } - } - ReadableByteStreamControllerClearAlgorithms(controller); - ReadableStreamClose(stream); -} -function ReadableByteStreamControllerEnqueue(controller, chunk) { - const stream = controller._controlledReadableByteStream; - if (controller._closeRequested || stream._state !== 'readable') { - return; - } - const buffer = chunk.buffer; - const byteOffset = chunk.byteOffset; - const byteLength = chunk.byteLength; - const transferredBuffer = TransferArrayBuffer(buffer); - if (ReadableStreamHasDefaultReader(stream)) { - if (ReadableStreamGetNumReadRequests(stream) === 0) { - ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength); - } - else { - const transferredView = new Uint8Array(transferredBuffer, byteOffset, byteLength); - ReadableStreamFulfillReadRequest(stream, transferredView, false); - } - } - else if (ReadableStreamHasBYOBReader(stream)) { - // TODO: Ideally in this branch detaching should happen only if the buffer is not consumed fully. - ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength); - ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller); - } - else { - ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength); - } - ReadableByteStreamControllerCallPullIfNeeded(controller); -} -function ReadableByteStreamControllerError(controller, e) { - const stream = controller._controlledReadableByteStream; - if (stream._state !== 'readable') { - return; - } - ReadableByteStreamControllerClearPendingPullIntos(controller); - ResetQueue(controller); - ReadableByteStreamControllerClearAlgorithms(controller); - ReadableStreamError(stream, e); -} -function ReadableByteStreamControllerGetDesiredSize(controller) { - const state = controller._controlledReadableByteStream._state; - if (state === 'errored') { - return null; - } - if (state === 'closed') { - return 0; - } - return controller._strategyHWM - controller._queueTotalSize; -} -function ReadableByteStreamControllerRespond(controller, bytesWritten) { - bytesWritten = Number(bytesWritten); - if (!IsFiniteNonNegativeNumber(bytesWritten)) { - throw new RangeError('bytesWritten must be a finite'); - } - ReadableByteStreamControllerRespondInternal(controller, bytesWritten); -} -function ReadableByteStreamControllerRespondWithNewView(controller, view) { - const firstDescriptor = controller._pendingPullIntos.peek(); - if (firstDescriptor.byteOffset + firstDescriptor.bytesFilled !== view.byteOffset) { - throw new RangeError('The region specified by view does not match byobRequest'); - } - if (firstDescriptor.byteLength !== view.byteLength) { - throw new RangeError('The buffer of view has different capacity than byobRequest'); - } - firstDescriptor.buffer = view.buffer; - ReadableByteStreamControllerRespondInternal(controller, view.byteLength); -} -function SetUpReadableByteStreamController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, autoAllocateChunkSize) { - controller._controlledReadableByteStream = stream; - controller._pullAgain = false; - controller._pulling = false; - controller._byobRequest = null; - // Need to set the slots so that the assert doesn't fire. In the spec the slots already exist implicitly. - controller._queue = controller._queueTotalSize = undefined; - ResetQueue(controller); - controller._closeRequested = false; - controller._started = false; - controller._strategyHWM = highWaterMark; - controller._pullAlgorithm = pullAlgorithm; - controller._cancelAlgorithm = cancelAlgorithm; - controller._autoAllocateChunkSize = autoAllocateChunkSize; - controller._pendingPullIntos = new SimpleQueue(); - stream._readableStreamController = controller; - const startResult = startAlgorithm(); - uponPromise(promiseResolvedWith(startResult), () => { - controller._started = true; - ReadableByteStreamControllerCallPullIfNeeded(controller); - }, r => { - ReadableByteStreamControllerError(controller, r); - }); -} -function SetUpReadableByteStreamControllerFromUnderlyingSource(stream, underlyingByteSource, highWaterMark) { - const controller = Object.create(ReadableByteStreamController.prototype); - let startAlgorithm = () => undefined; - let pullAlgorithm = () => promiseResolvedWith(undefined); - let cancelAlgorithm = () => promiseResolvedWith(undefined); - if (underlyingByteSource.start !== undefined) { - startAlgorithm = () => underlyingByteSource.start(controller); - } - if (underlyingByteSource.pull !== undefined) { - pullAlgorithm = () => underlyingByteSource.pull(controller); - } - if (underlyingByteSource.cancel !== undefined) { - cancelAlgorithm = reason => underlyingByteSource.cancel(reason); - } - const autoAllocateChunkSize = underlyingByteSource.autoAllocateChunkSize; - if (autoAllocateChunkSize === 0) { - throw new TypeError('autoAllocateChunkSize must be greater than 0'); - } - SetUpReadableByteStreamController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, autoAllocateChunkSize); -} -function SetUpReadableStreamBYOBRequest(request, controller, view) { - request._associatedReadableByteStreamController = controller; - request._view = view; -} -// Helper functions for the ReadableStreamBYOBRequest. -function byobRequestBrandCheckException(name) { - return new TypeError(`ReadableStreamBYOBRequest.prototype.${name} can only be used on a ReadableStreamBYOBRequest`); -} -// Helper functions for the ReadableByteStreamController. -function byteStreamControllerBrandCheckException(name) { - return new TypeError(`ReadableByteStreamController.prototype.${name} can only be used on a ReadableByteStreamController`); -} - -// Abstract operations for the ReadableStream. -function AcquireReadableStreamBYOBReader(stream) { - return new ReadableStreamBYOBReader(stream); -} -// ReadableStream API exposed for controllers. -function ReadableStreamAddReadIntoRequest(stream, readIntoRequest) { - stream._reader._readIntoRequests.push(readIntoRequest); -} -function ReadableStreamFulfillReadIntoRequest(stream, chunk, done) { - const reader = stream._reader; - const readIntoRequest = reader._readIntoRequests.shift(); - if (done) { - readIntoRequest._closeSteps(chunk); - } - else { - readIntoRequest._chunkSteps(chunk); - } -} -function ReadableStreamGetNumReadIntoRequests(stream) { - return stream._reader._readIntoRequests.length; -} -function ReadableStreamHasBYOBReader(stream) { - const reader = stream._reader; - if (reader === undefined) { - return false; - } - if (!IsReadableStreamBYOBReader(reader)) { - return false; - } - return true; -} -/** - * A BYOB reader vended by a {@link ReadableStream}. - * - * @public - */ -class ReadableStreamBYOBReader { - constructor(stream) { - assertRequiredArgument(stream, 1, 'ReadableStreamBYOBReader'); - assertReadableStream(stream, 'First parameter'); - if (IsReadableStreamLocked(stream)) { - throw new TypeError('This stream has already been locked for exclusive reading by another reader'); - } - if (!IsReadableByteStreamController(stream._readableStreamController)) { - throw new TypeError('Cannot construct a ReadableStreamBYOBReader for a stream not constructed with a byte ' + - 'source'); - } - ReadableStreamReaderGenericInitialize(this, stream); - this._readIntoRequests = new SimpleQueue(); - } - /** - * Returns a promise that will be fulfilled when the stream becomes closed, or rejected if the stream ever errors or - * the reader's lock is released before the stream finishes closing. - */ - get closed() { - if (!IsReadableStreamBYOBReader(this)) { - return promiseRejectedWith(byobReaderBrandCheckException('closed')); - } - return this._closedPromise; - } - /** - * If the reader is active, behaves the same as {@link ReadableStream.cancel | stream.cancel(reason)}. - */ - cancel(reason = undefined) { - if (!IsReadableStreamBYOBReader(this)) { - return promiseRejectedWith(byobReaderBrandCheckException('cancel')); - } - if (this._ownerReadableStream === undefined) { - return promiseRejectedWith(readerLockException('cancel')); - } - return ReadableStreamReaderGenericCancel(this, reason); - } - /** - * Attempts to reads bytes into view, and returns a promise resolved with the result. - * - * If reading a chunk causes the queue to become empty, more data will be pulled from the underlying source. - */ - read(view) { - if (!IsReadableStreamBYOBReader(this)) { - return promiseRejectedWith(byobReaderBrandCheckException('read')); - } - if (!ArrayBuffer.isView(view)) { - return promiseRejectedWith(new TypeError('view must be an array buffer view')); - } - if (view.byteLength === 0) { - return promiseRejectedWith(new TypeError('view must have non-zero byteLength')); - } - if (view.buffer.byteLength === 0) { - return promiseRejectedWith(new TypeError(`view's buffer must have non-zero byteLength`)); - } - if (this._ownerReadableStream === undefined) { - return promiseRejectedWith(readerLockException('read from')); - } - let resolvePromise; - let rejectPromise; - const promise = newPromise((resolve, reject) => { - resolvePromise = resolve; - rejectPromise = reject; - }); - const readIntoRequest = { - _chunkSteps: chunk => resolvePromise({ value: chunk, done: false }), - _closeSteps: chunk => resolvePromise({ value: chunk, done: true }), - _errorSteps: e => rejectPromise(e) - }; - ReadableStreamBYOBReaderRead(this, view, readIntoRequest); - return promise; - } - /** - * Releases the reader's lock on the corresponding stream. After the lock is released, the reader is no longer active. - * If the associated stream is errored when the lock is released, the reader will appear errored in the same way - * from now on; otherwise, the reader will appear closed. - * - * A reader's lock cannot be released while it still has a pending read request, i.e., if a promise returned by - * the reader's {@link ReadableStreamBYOBReader.read | read()} method has not yet been settled. Attempting to - * do so will throw a `TypeError` and leave the reader locked to the stream. - */ - releaseLock() { - if (!IsReadableStreamBYOBReader(this)) { - throw byobReaderBrandCheckException('releaseLock'); - } - if (this._ownerReadableStream === undefined) { - return; - } - if (this._readIntoRequests.length > 0) { - throw new TypeError('Tried to release a reader lock when that reader has pending read() calls un-settled'); - } - ReadableStreamReaderGenericRelease(this); - } -} -Object.defineProperties(ReadableStreamBYOBReader.prototype, { - cancel: { enumerable: true }, - read: { enumerable: true }, - releaseLock: { enumerable: true }, - closed: { enumerable: true } -}); -if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(ReadableStreamBYOBReader.prototype, SymbolPolyfill.toStringTag, { - value: 'ReadableStreamBYOBReader', - configurable: true - }); -} -// Abstract operations for the readers. -function IsReadableStreamBYOBReader(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_readIntoRequests')) { - return false; - } - return true; -} -function ReadableStreamBYOBReaderRead(reader, view, readIntoRequest) { - const stream = reader._ownerReadableStream; - stream._disturbed = true; - if (stream._state === 'errored') { - readIntoRequest._errorSteps(stream._storedError); - } - else { - ReadableByteStreamControllerPullInto(stream._readableStreamController, view, readIntoRequest); - } -} -// Helper functions for the ReadableStreamBYOBReader. -function byobReaderBrandCheckException(name) { - return new TypeError(`ReadableStreamBYOBReader.prototype.${name} can only be used on a ReadableStreamBYOBReader`); -} - -function ExtractHighWaterMark(strategy, defaultHWM) { - const { highWaterMark } = strategy; - if (highWaterMark === undefined) { - return defaultHWM; - } - if (NumberIsNaN(highWaterMark) || highWaterMark < 0) { - throw new RangeError('Invalid highWaterMark'); - } - return highWaterMark; -} -function ExtractSizeAlgorithm(strategy) { - const { size } = strategy; - if (!size) { - return () => 1; - } - return size; -} - -function convertQueuingStrategy(init, context) { - assertDictionary(init, context); - const highWaterMark = init === null || init === void 0 ? void 0 : init.highWaterMark; - const size = init === null || init === void 0 ? void 0 : init.size; - return { - highWaterMark: highWaterMark === undefined ? undefined : convertUnrestrictedDouble(highWaterMark), - size: size === undefined ? undefined : convertQueuingStrategySize(size, `${context} has member 'size' that`) - }; -} -function convertQueuingStrategySize(fn, context) { - assertFunction(fn, context); - return chunk => convertUnrestrictedDouble(fn(chunk)); -} - -function convertUnderlyingSink(original, context) { - assertDictionary(original, context); - const abort = original === null || original === void 0 ? void 0 : original.abort; - const close = original === null || original === void 0 ? void 0 : original.close; - const start = original === null || original === void 0 ? void 0 : original.start; - const type = original === null || original === void 0 ? void 0 : original.type; - const write = original === null || original === void 0 ? void 0 : original.write; - return { - abort: abort === undefined ? - undefined : - convertUnderlyingSinkAbortCallback(abort, original, `${context} has member 'abort' that`), - close: close === undefined ? - undefined : - convertUnderlyingSinkCloseCallback(close, original, `${context} has member 'close' that`), - start: start === undefined ? - undefined : - convertUnderlyingSinkStartCallback(start, original, `${context} has member 'start' that`), - write: write === undefined ? - undefined : - convertUnderlyingSinkWriteCallback(write, original, `${context} has member 'write' that`), - type - }; -} -function convertUnderlyingSinkAbortCallback(fn, original, context) { - assertFunction(fn, context); - return (reason) => promiseCall(fn, original, [reason]); -} -function convertUnderlyingSinkCloseCallback(fn, original, context) { - assertFunction(fn, context); - return () => promiseCall(fn, original, []); -} -function convertUnderlyingSinkStartCallback(fn, original, context) { - assertFunction(fn, context); - return (controller) => reflectCall(fn, original, [controller]); -} -function convertUnderlyingSinkWriteCallback(fn, original, context) { - assertFunction(fn, context); - return (chunk, controller) => promiseCall(fn, original, [chunk, controller]); -} - -function assertWritableStream(x, context) { - if (!IsWritableStream(x)) { - throw new TypeError(`${context} is not a WritableStream.`); - } -} - -/** - * A writable stream represents a destination for data, into which you can write. - * - * @public - */ -class WritableStream$1 { - constructor(rawUnderlyingSink = {}, rawStrategy = {}) { - if (rawUnderlyingSink === undefined) { - rawUnderlyingSink = null; - } - else { - assertObject(rawUnderlyingSink, 'First parameter'); - } - const strategy = convertQueuingStrategy(rawStrategy, 'Second parameter'); - const underlyingSink = convertUnderlyingSink(rawUnderlyingSink, 'First parameter'); - InitializeWritableStream(this); - const type = underlyingSink.type; - if (type !== undefined) { - throw new RangeError('Invalid type is specified'); - } - const sizeAlgorithm = ExtractSizeAlgorithm(strategy); - const highWaterMark = ExtractHighWaterMark(strategy, 1); - SetUpWritableStreamDefaultControllerFromUnderlyingSink(this, underlyingSink, highWaterMark, sizeAlgorithm); - } - /** - * Returns whether or not the writable stream is locked to a writer. - */ - get locked() { - if (!IsWritableStream(this)) { - throw streamBrandCheckException$2('locked'); - } - return IsWritableStreamLocked(this); - } - /** - * Aborts the stream, signaling that the producer can no longer successfully write to the stream and it is to be - * immediately moved to an errored state, with any queued-up writes discarded. This will also execute any abort - * mechanism of the underlying sink. - * - * The returned promise will fulfill if the stream shuts down successfully, or reject if the underlying sink signaled - * that there was an error doing so. Additionally, it will reject with a `TypeError` (without attempting to cancel - * the stream) if the stream is currently locked. - */ - abort(reason = undefined) { - if (!IsWritableStream(this)) { - return promiseRejectedWith(streamBrandCheckException$2('abort')); - } - if (IsWritableStreamLocked(this)) { - return promiseRejectedWith(new TypeError('Cannot abort a stream that already has a writer')); - } - return WritableStreamAbort(this, reason); - } - /** - * Closes the stream. The underlying sink will finish processing any previously-written chunks, before invoking its - * close behavior. During this time any further attempts to write will fail (without erroring the stream). - * - * The method returns a promise that will fulfill if all remaining chunks are successfully written and the stream - * successfully closes, or rejects if an error is encountered during this process. Additionally, it will reject with - * a `TypeError` (without attempting to cancel the stream) if the stream is currently locked. - */ - close() { - if (!IsWritableStream(this)) { - return promiseRejectedWith(streamBrandCheckException$2('close')); - } - if (IsWritableStreamLocked(this)) { - return promiseRejectedWith(new TypeError('Cannot close a stream that already has a writer')); - } - if (WritableStreamCloseQueuedOrInFlight(this)) { - return promiseRejectedWith(new TypeError('Cannot close an already-closing stream')); - } - return WritableStreamClose(this); - } - /** - * Creates a {@link WritableStreamDefaultWriter | writer} and locks the stream to the new writer. While the stream - * is locked, no other writer can be acquired until this one is released. - * - * This functionality is especially useful for creating abstractions that desire the ability to write to a stream - * without interruption or interleaving. By getting a writer for the stream, you can ensure nobody else can write at - * the same time, which would cause the resulting written data to be unpredictable and probably useless. - */ - getWriter() { - if (!IsWritableStream(this)) { - throw streamBrandCheckException$2('getWriter'); - } - return AcquireWritableStreamDefaultWriter(this); - } -} -Object.defineProperties(WritableStream$1.prototype, { - abort: { enumerable: true }, - close: { enumerable: true }, - getWriter: { enumerable: true }, - locked: { enumerable: true } -}); -if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(WritableStream$1.prototype, SymbolPolyfill.toStringTag, { - value: 'WritableStream', - configurable: true - }); -} -// Abstract operations for the WritableStream. -function AcquireWritableStreamDefaultWriter(stream) { - return new WritableStreamDefaultWriter(stream); -} -// Throws if and only if startAlgorithm throws. -function CreateWritableStream(startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark = 1, sizeAlgorithm = () => 1) { - const stream = Object.create(WritableStream$1.prototype); - InitializeWritableStream(stream); - const controller = Object.create(WritableStreamDefaultController.prototype); - SetUpWritableStreamDefaultController(stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark, sizeAlgorithm); - return stream; -} -function InitializeWritableStream(stream) { - stream._state = 'writable'; - // The error that will be reported by new method calls once the state becomes errored. Only set when [[state]] is - // 'erroring' or 'errored'. May be set to an undefined value. - stream._storedError = undefined; - stream._writer = undefined; - // Initialize to undefined first because the constructor of the controller checks this - // variable to validate the caller. - stream._writableStreamController = undefined; - // This queue is placed here instead of the writer class in order to allow for passing a writer to the next data - // producer without waiting for the queued writes to finish. - stream._writeRequests = new SimpleQueue(); - // Write requests are removed from _writeRequests when write() is called on the underlying sink. This prevents - // them from being erroneously rejected on error. If a write() call is in-flight, the request is stored here. - stream._inFlightWriteRequest = undefined; - // The promise that was returned from writer.close(). Stored here because it may be fulfilled after the writer - // has been detached. - stream._closeRequest = undefined; - // Close request is removed from _closeRequest when close() is called on the underlying sink. This prevents it - // from being erroneously rejected on error. If a close() call is in-flight, the request is stored here. - stream._inFlightCloseRequest = undefined; - // The promise that was returned from writer.abort(). This may also be fulfilled after the writer has detached. - stream._pendingAbortRequest = undefined; - // The backpressure signal set by the controller. - stream._backpressure = false; -} -function IsWritableStream(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_writableStreamController')) { - return false; - } - return true; -} -function IsWritableStreamLocked(stream) { - if (stream._writer === undefined) { - return false; - } - return true; -} -function WritableStreamAbort(stream, reason) { - const state = stream._state; - if (state === 'closed' || state === 'errored') { - return promiseResolvedWith(undefined); - } - if (stream._pendingAbortRequest !== undefined) { - return stream._pendingAbortRequest._promise; - } - let wasAlreadyErroring = false; - if (state === 'erroring') { - wasAlreadyErroring = true; - // reason will not be used, so don't keep a reference to it. - reason = undefined; - } - const promise = newPromise((resolve, reject) => { - stream._pendingAbortRequest = { - _promise: undefined, - _resolve: resolve, - _reject: reject, - _reason: reason, - _wasAlreadyErroring: wasAlreadyErroring - }; - }); - stream._pendingAbortRequest._promise = promise; - if (!wasAlreadyErroring) { - WritableStreamStartErroring(stream, reason); - } - return promise; -} -function WritableStreamClose(stream) { - const state = stream._state; - if (state === 'closed' || state === 'errored') { - return promiseRejectedWith(new TypeError(`The stream (in ${state} state) is not in the writable state and cannot be closed`)); - } - const promise = newPromise((resolve, reject) => { - const closeRequest = { - _resolve: resolve, - _reject: reject - }; - stream._closeRequest = closeRequest; - }); - const writer = stream._writer; - if (writer !== undefined && stream._backpressure && state === 'writable') { - defaultWriterReadyPromiseResolve(writer); - } - WritableStreamDefaultControllerClose(stream._writableStreamController); - return promise; -} -// WritableStream API exposed for controllers. -function WritableStreamAddWriteRequest(stream) { - const promise = newPromise((resolve, reject) => { - const writeRequest = { - _resolve: resolve, - _reject: reject - }; - stream._writeRequests.push(writeRequest); - }); - return promise; -} -function WritableStreamDealWithRejection(stream, error) { - const state = stream._state; - if (state === 'writable') { - WritableStreamStartErroring(stream, error); - return; - } - WritableStreamFinishErroring(stream); -} -function WritableStreamStartErroring(stream, reason) { - const controller = stream._writableStreamController; - stream._state = 'erroring'; - stream._storedError = reason; - const writer = stream._writer; - if (writer !== undefined) { - WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, reason); - } - if (!WritableStreamHasOperationMarkedInFlight(stream) && controller._started) { - WritableStreamFinishErroring(stream); - } -} -function WritableStreamFinishErroring(stream) { - stream._state = 'errored'; - stream._writableStreamController[ErrorSteps](); - const storedError = stream._storedError; - stream._writeRequests.forEach(writeRequest => { - writeRequest._reject(storedError); - }); - stream._writeRequests = new SimpleQueue(); - if (stream._pendingAbortRequest === undefined) { - WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); - return; - } - const abortRequest = stream._pendingAbortRequest; - stream._pendingAbortRequest = undefined; - if (abortRequest._wasAlreadyErroring) { - abortRequest._reject(storedError); - WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); - return; - } - const promise = stream._writableStreamController[AbortSteps](abortRequest._reason); - uponPromise(promise, () => { - abortRequest._resolve(); - WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); - }, (reason) => { - abortRequest._reject(reason); - WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); - }); -} -function WritableStreamFinishInFlightWrite(stream) { - stream._inFlightWriteRequest._resolve(undefined); - stream._inFlightWriteRequest = undefined; -} -function WritableStreamFinishInFlightWriteWithError(stream, error) { - stream._inFlightWriteRequest._reject(error); - stream._inFlightWriteRequest = undefined; - WritableStreamDealWithRejection(stream, error); -} -function WritableStreamFinishInFlightClose(stream) { - stream._inFlightCloseRequest._resolve(undefined); - stream._inFlightCloseRequest = undefined; - const state = stream._state; - if (state === 'erroring') { - // The error was too late to do anything, so it is ignored. - stream._storedError = undefined; - if (stream._pendingAbortRequest !== undefined) { - stream._pendingAbortRequest._resolve(); - stream._pendingAbortRequest = undefined; - } - } - stream._state = 'closed'; - const writer = stream._writer; - if (writer !== undefined) { - defaultWriterClosedPromiseResolve(writer); - } -} -function WritableStreamFinishInFlightCloseWithError(stream, error) { - stream._inFlightCloseRequest._reject(error); - stream._inFlightCloseRequest = undefined; - // Never execute sink abort() after sink close(). - if (stream._pendingAbortRequest !== undefined) { - stream._pendingAbortRequest._reject(error); - stream._pendingAbortRequest = undefined; - } - WritableStreamDealWithRejection(stream, error); -} -// TODO(ricea): Fix alphabetical order. -function WritableStreamCloseQueuedOrInFlight(stream) { - if (stream._closeRequest === undefined && stream._inFlightCloseRequest === undefined) { - return false; - } - return true; -} -function WritableStreamHasOperationMarkedInFlight(stream) { - if (stream._inFlightWriteRequest === undefined && stream._inFlightCloseRequest === undefined) { - return false; - } - return true; -} -function WritableStreamMarkCloseRequestInFlight(stream) { - stream._inFlightCloseRequest = stream._closeRequest; - stream._closeRequest = undefined; -} -function WritableStreamMarkFirstWriteRequestInFlight(stream) { - stream._inFlightWriteRequest = stream._writeRequests.shift(); -} -function WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream) { - if (stream._closeRequest !== undefined) { - stream._closeRequest._reject(stream._storedError); - stream._closeRequest = undefined; - } - const writer = stream._writer; - if (writer !== undefined) { - defaultWriterClosedPromiseReject(writer, stream._storedError); - } -} -function WritableStreamUpdateBackpressure(stream, backpressure) { - const writer = stream._writer; - if (writer !== undefined && backpressure !== stream._backpressure) { - if (backpressure) { - defaultWriterReadyPromiseReset(writer); - } - else { - defaultWriterReadyPromiseResolve(writer); - } - } - stream._backpressure = backpressure; -} -/** - * A default writer vended by a {@link WritableStream}. - * - * @public - */ -class WritableStreamDefaultWriter { - constructor(stream) { - assertRequiredArgument(stream, 1, 'WritableStreamDefaultWriter'); - assertWritableStream(stream, 'First parameter'); - if (IsWritableStreamLocked(stream)) { - throw new TypeError('This stream has already been locked for exclusive writing by another writer'); - } - this._ownerWritableStream = stream; - stream._writer = this; - const state = stream._state; - if (state === 'writable') { - if (!WritableStreamCloseQueuedOrInFlight(stream) && stream._backpressure) { - defaultWriterReadyPromiseInitialize(this); - } - else { - defaultWriterReadyPromiseInitializeAsResolved(this); - } - defaultWriterClosedPromiseInitialize(this); - } - else if (state === 'erroring') { - defaultWriterReadyPromiseInitializeAsRejected(this, stream._storedError); - defaultWriterClosedPromiseInitialize(this); - } - else if (state === 'closed') { - defaultWriterReadyPromiseInitializeAsResolved(this); - defaultWriterClosedPromiseInitializeAsResolved(this); - } - else { - const storedError = stream._storedError; - defaultWriterReadyPromiseInitializeAsRejected(this, storedError); - defaultWriterClosedPromiseInitializeAsRejected(this, storedError); - } - } - /** - * Returns a promise that will be fulfilled when the stream becomes closed, or rejected if the stream ever errors or - * the writer’s lock is released before the stream finishes closing. - */ - get closed() { - if (!IsWritableStreamDefaultWriter(this)) { - return promiseRejectedWith(defaultWriterBrandCheckException('closed')); - } - return this._closedPromise; - } - /** - * Returns the desired size to fill the stream’s internal queue. It can be negative, if the queue is over-full. - * A producer can use this information to determine the right amount of data to write. - * - * It will be `null` if the stream cannot be successfully written to (due to either being errored, or having an abort - * queued up). It will return zero if the stream is closed. And the getter will throw an exception if invoked when - * the writer’s lock is released. - */ - get desiredSize() { - if (!IsWritableStreamDefaultWriter(this)) { - throw defaultWriterBrandCheckException('desiredSize'); - } - if (this._ownerWritableStream === undefined) { - throw defaultWriterLockException('desiredSize'); - } - return WritableStreamDefaultWriterGetDesiredSize(this); - } - /** - * Returns a promise that will be fulfilled when the desired size to fill the stream’s internal queue transitions - * from non-positive to positive, signaling that it is no longer applying backpressure. Once the desired size dips - * back to zero or below, the getter will return a new promise that stays pending until the next transition. - * - * If the stream becomes errored or aborted, or the writer’s lock is released, the returned promise will become - * rejected. - */ - get ready() { - if (!IsWritableStreamDefaultWriter(this)) { - return promiseRejectedWith(defaultWriterBrandCheckException('ready')); - } - return this._readyPromise; - } - /** - * If the reader is active, behaves the same as {@link WritableStream.abort | stream.abort(reason)}. - */ - abort(reason = undefined) { - if (!IsWritableStreamDefaultWriter(this)) { - return promiseRejectedWith(defaultWriterBrandCheckException('abort')); - } - if (this._ownerWritableStream === undefined) { - return promiseRejectedWith(defaultWriterLockException('abort')); - } - return WritableStreamDefaultWriterAbort(this, reason); - } - /** - * If the reader is active, behaves the same as {@link WritableStream.close | stream.close()}. - */ - close() { - if (!IsWritableStreamDefaultWriter(this)) { - return promiseRejectedWith(defaultWriterBrandCheckException('close')); - } - const stream = this._ownerWritableStream; - if (stream === undefined) { - return promiseRejectedWith(defaultWriterLockException('close')); - } - if (WritableStreamCloseQueuedOrInFlight(stream)) { - return promiseRejectedWith(new TypeError('Cannot close an already-closing stream')); - } - return WritableStreamDefaultWriterClose(this); - } - /** - * Releases the writer’s lock on the corresponding stream. After the lock is released, the writer is no longer active. - * If the associated stream is errored when the lock is released, the writer will appear errored in the same way from - * now on; otherwise, the writer will appear closed. - * - * Note that the lock can still be released even if some ongoing writes have not yet finished (i.e. even if the - * promises returned from previous calls to {@link WritableStreamDefaultWriter.write | write()} have not yet settled). - * It’s not necessary to hold the lock on the writer for the duration of the write; the lock instead simply prevents - * other producers from writing in an interleaved manner. - */ - releaseLock() { - if (!IsWritableStreamDefaultWriter(this)) { - throw defaultWriterBrandCheckException('releaseLock'); - } - const stream = this._ownerWritableStream; - if (stream === undefined) { - return; - } - WritableStreamDefaultWriterRelease(this); - } - write(chunk = undefined) { - if (!IsWritableStreamDefaultWriter(this)) { - return promiseRejectedWith(defaultWriterBrandCheckException('write')); - } - if (this._ownerWritableStream === undefined) { - return promiseRejectedWith(defaultWriterLockException('write to')); - } - return WritableStreamDefaultWriterWrite(this, chunk); - } -} -Object.defineProperties(WritableStreamDefaultWriter.prototype, { - abort: { enumerable: true }, - close: { enumerable: true }, - releaseLock: { enumerable: true }, - write: { enumerable: true }, - closed: { enumerable: true }, - desiredSize: { enumerable: true }, - ready: { enumerable: true } -}); -if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(WritableStreamDefaultWriter.prototype, SymbolPolyfill.toStringTag, { - value: 'WritableStreamDefaultWriter', - configurable: true - }); -} -// Abstract operations for the WritableStreamDefaultWriter. -function IsWritableStreamDefaultWriter(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_ownerWritableStream')) { - return false; - } - return true; -} -// A client of WritableStreamDefaultWriter may use these functions directly to bypass state check. -function WritableStreamDefaultWriterAbort(writer, reason) { - const stream = writer._ownerWritableStream; - return WritableStreamAbort(stream, reason); -} -function WritableStreamDefaultWriterClose(writer) { - const stream = writer._ownerWritableStream; - return WritableStreamClose(stream); -} -function WritableStreamDefaultWriterCloseWithErrorPropagation(writer) { - const stream = writer._ownerWritableStream; - const state = stream._state; - if (WritableStreamCloseQueuedOrInFlight(stream) || state === 'closed') { - return promiseResolvedWith(undefined); - } - if (state === 'errored') { - return promiseRejectedWith(stream._storedError); - } - return WritableStreamDefaultWriterClose(writer); -} -function WritableStreamDefaultWriterEnsureClosedPromiseRejected(writer, error) { - if (writer._closedPromiseState === 'pending') { - defaultWriterClosedPromiseReject(writer, error); - } - else { - defaultWriterClosedPromiseResetToRejected(writer, error); - } -} -function WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, error) { - if (writer._readyPromiseState === 'pending') { - defaultWriterReadyPromiseReject(writer, error); - } - else { - defaultWriterReadyPromiseResetToRejected(writer, error); - } -} -function WritableStreamDefaultWriterGetDesiredSize(writer) { - const stream = writer._ownerWritableStream; - const state = stream._state; - if (state === 'errored' || state === 'erroring') { - return null; - } - if (state === 'closed') { - return 0; - } - return WritableStreamDefaultControllerGetDesiredSize(stream._writableStreamController); -} -function WritableStreamDefaultWriterRelease(writer) { - const stream = writer._ownerWritableStream; - const releasedError = new TypeError(`Writer was released and can no longer be used to monitor the stream's closedness`); - WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, releasedError); - // The state transitions to "errored" before the sink abort() method runs, but the writer.closed promise is not - // rejected until afterwards. This means that simply testing state will not work. - WritableStreamDefaultWriterEnsureClosedPromiseRejected(writer, releasedError); - stream._writer = undefined; - writer._ownerWritableStream = undefined; -} -function WritableStreamDefaultWriterWrite(writer, chunk) { - const stream = writer._ownerWritableStream; - const controller = stream._writableStreamController; - const chunkSize = WritableStreamDefaultControllerGetChunkSize(controller, chunk); - if (stream !== writer._ownerWritableStream) { - return promiseRejectedWith(defaultWriterLockException('write to')); - } - const state = stream._state; - if (state === 'errored') { - return promiseRejectedWith(stream._storedError); - } - if (WritableStreamCloseQueuedOrInFlight(stream) || state === 'closed') { - return promiseRejectedWith(new TypeError('The stream is closing or closed and cannot be written to')); - } - if (state === 'erroring') { - return promiseRejectedWith(stream._storedError); - } - const promise = WritableStreamAddWriteRequest(stream); - WritableStreamDefaultControllerWrite(controller, chunk, chunkSize); - return promise; -} -const closeSentinel = {}; -/** - * Allows control of a {@link WritableStream | writable stream}'s state and internal queue. - * - * @public - */ -class WritableStreamDefaultController { - constructor() { - throw new TypeError('Illegal constructor'); - } - /** - * Closes the controlled writable stream, making all future interactions with it fail with the given error `e`. - * - * This method is rarely used, since usually it suffices to return a rejected promise from one of the underlying - * sink's methods. However, it can be useful for suddenly shutting down a stream in response to an event outside the - * normal lifecycle of interactions with the underlying sink. - */ - error(e = undefined) { - if (!IsWritableStreamDefaultController(this)) { - throw new TypeError('WritableStreamDefaultController.prototype.error can only be used on a WritableStreamDefaultController'); - } - const state = this._controlledWritableStream._state; - if (state !== 'writable') { - // The stream is closed, errored or will be soon. The sink can't do anything useful if it gets an error here, so - // just treat it as a no-op. - return; - } - WritableStreamDefaultControllerError(this, e); - } - /** @internal */ - [AbortSteps](reason) { - const result = this._abortAlgorithm(reason); - WritableStreamDefaultControllerClearAlgorithms(this); - return result; - } - /** @internal */ - [ErrorSteps]() { - ResetQueue(this); - } -} -Object.defineProperties(WritableStreamDefaultController.prototype, { - error: { enumerable: true } -}); -if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(WritableStreamDefaultController.prototype, SymbolPolyfill.toStringTag, { - value: 'WritableStreamDefaultController', - configurable: true - }); -} -// Abstract operations implementing interface required by the WritableStream. -function IsWritableStreamDefaultController(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_controlledWritableStream')) { - return false; - } - return true; -} -function SetUpWritableStreamDefaultController(stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark, sizeAlgorithm) { - controller._controlledWritableStream = stream; - stream._writableStreamController = controller; - // Need to set the slots so that the assert doesn't fire. In the spec the slots already exist implicitly. - controller._queue = undefined; - controller._queueTotalSize = undefined; - ResetQueue(controller); - controller._started = false; - controller._strategySizeAlgorithm = sizeAlgorithm; - controller._strategyHWM = highWaterMark; - controller._writeAlgorithm = writeAlgorithm; - controller._closeAlgorithm = closeAlgorithm; - controller._abortAlgorithm = abortAlgorithm; - const backpressure = WritableStreamDefaultControllerGetBackpressure(controller); - WritableStreamUpdateBackpressure(stream, backpressure); - const startResult = startAlgorithm(); - const startPromise = promiseResolvedWith(startResult); - uponPromise(startPromise, () => { - controller._started = true; - WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); - }, r => { - controller._started = true; - WritableStreamDealWithRejection(stream, r); - }); -} -function SetUpWritableStreamDefaultControllerFromUnderlyingSink(stream, underlyingSink, highWaterMark, sizeAlgorithm) { - const controller = Object.create(WritableStreamDefaultController.prototype); - let startAlgorithm = () => undefined; - let writeAlgorithm = () => promiseResolvedWith(undefined); - let closeAlgorithm = () => promiseResolvedWith(undefined); - let abortAlgorithm = () => promiseResolvedWith(undefined); - if (underlyingSink.start !== undefined) { - startAlgorithm = () => underlyingSink.start(controller); - } - if (underlyingSink.write !== undefined) { - writeAlgorithm = chunk => underlyingSink.write(chunk, controller); - } - if (underlyingSink.close !== undefined) { - closeAlgorithm = () => underlyingSink.close(); - } - if (underlyingSink.abort !== undefined) { - abortAlgorithm = reason => underlyingSink.abort(reason); - } - SetUpWritableStreamDefaultController(stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark, sizeAlgorithm); -} -// ClearAlgorithms may be called twice. Erroring the same stream in multiple ways will often result in redundant calls. -function WritableStreamDefaultControllerClearAlgorithms(controller) { - controller._writeAlgorithm = undefined; - controller._closeAlgorithm = undefined; - controller._abortAlgorithm = undefined; - controller._strategySizeAlgorithm = undefined; -} -function WritableStreamDefaultControllerClose(controller) { - EnqueueValueWithSize(controller, closeSentinel, 0); - WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); -} -function WritableStreamDefaultControllerGetChunkSize(controller, chunk) { - try { - return controller._strategySizeAlgorithm(chunk); - } - catch (chunkSizeE) { - WritableStreamDefaultControllerErrorIfNeeded(controller, chunkSizeE); - return 1; - } -} -function WritableStreamDefaultControllerGetDesiredSize(controller) { - return controller._strategyHWM - controller._queueTotalSize; -} -function WritableStreamDefaultControllerWrite(controller, chunk, chunkSize) { - try { - EnqueueValueWithSize(controller, chunk, chunkSize); - } - catch (enqueueE) { - WritableStreamDefaultControllerErrorIfNeeded(controller, enqueueE); - return; - } - const stream = controller._controlledWritableStream; - if (!WritableStreamCloseQueuedOrInFlight(stream) && stream._state === 'writable') { - const backpressure = WritableStreamDefaultControllerGetBackpressure(controller); - WritableStreamUpdateBackpressure(stream, backpressure); - } - WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); -} -// Abstract operations for the WritableStreamDefaultController. -function WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller) { - const stream = controller._controlledWritableStream; - if (!controller._started) { - return; - } - if (stream._inFlightWriteRequest !== undefined) { - return; - } - const state = stream._state; - if (state === 'erroring') { - WritableStreamFinishErroring(stream); - return; - } - if (controller._queue.length === 0) { - return; - } - const value = PeekQueueValue(controller); - if (value === closeSentinel) { - WritableStreamDefaultControllerProcessClose(controller); - } - else { - WritableStreamDefaultControllerProcessWrite(controller, value); - } -} -function WritableStreamDefaultControllerErrorIfNeeded(controller, error) { - if (controller._controlledWritableStream._state === 'writable') { - WritableStreamDefaultControllerError(controller, error); - } -} -function WritableStreamDefaultControllerProcessClose(controller) { - const stream = controller._controlledWritableStream; - WritableStreamMarkCloseRequestInFlight(stream); - DequeueValue(controller); - const sinkClosePromise = controller._closeAlgorithm(); - WritableStreamDefaultControllerClearAlgorithms(controller); - uponPromise(sinkClosePromise, () => { - WritableStreamFinishInFlightClose(stream); - }, reason => { - WritableStreamFinishInFlightCloseWithError(stream, reason); - }); -} -function WritableStreamDefaultControllerProcessWrite(controller, chunk) { - const stream = controller._controlledWritableStream; - WritableStreamMarkFirstWriteRequestInFlight(stream); - const sinkWritePromise = controller._writeAlgorithm(chunk); - uponPromise(sinkWritePromise, () => { - WritableStreamFinishInFlightWrite(stream); - const state = stream._state; - DequeueValue(controller); - if (!WritableStreamCloseQueuedOrInFlight(stream) && state === 'writable') { - const backpressure = WritableStreamDefaultControllerGetBackpressure(controller); - WritableStreamUpdateBackpressure(stream, backpressure); - } - WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); - }, reason => { - if (stream._state === 'writable') { - WritableStreamDefaultControllerClearAlgorithms(controller); - } - WritableStreamFinishInFlightWriteWithError(stream, reason); - }); -} -function WritableStreamDefaultControllerGetBackpressure(controller) { - const desiredSize = WritableStreamDefaultControllerGetDesiredSize(controller); - return desiredSize <= 0; -} -// A client of WritableStreamDefaultController may use these functions directly to bypass state check. -function WritableStreamDefaultControllerError(controller, error) { - const stream = controller._controlledWritableStream; - WritableStreamDefaultControllerClearAlgorithms(controller); - WritableStreamStartErroring(stream, error); -} -// Helper functions for the WritableStream. -function streamBrandCheckException$2(name) { - return new TypeError(`WritableStream.prototype.${name} can only be used on a WritableStream`); -} -// Helper functions for the WritableStreamDefaultWriter. -function defaultWriterBrandCheckException(name) { - return new TypeError(`WritableStreamDefaultWriter.prototype.${name} can only be used on a WritableStreamDefaultWriter`); -} -function defaultWriterLockException(name) { - return new TypeError('Cannot ' + name + ' a stream using a released writer'); -} -function defaultWriterClosedPromiseInitialize(writer) { - writer._closedPromise = newPromise((resolve, reject) => { - writer._closedPromise_resolve = resolve; - writer._closedPromise_reject = reject; - writer._closedPromiseState = 'pending'; - }); -} -function defaultWriterClosedPromiseInitializeAsRejected(writer, reason) { - defaultWriterClosedPromiseInitialize(writer); - defaultWriterClosedPromiseReject(writer, reason); -} -function defaultWriterClosedPromiseInitializeAsResolved(writer) { - defaultWriterClosedPromiseInitialize(writer); - defaultWriterClosedPromiseResolve(writer); -} -function defaultWriterClosedPromiseReject(writer, reason) { - if (writer._closedPromise_reject === undefined) { - return; - } - setPromiseIsHandledToTrue(writer._closedPromise); - writer._closedPromise_reject(reason); - writer._closedPromise_resolve = undefined; - writer._closedPromise_reject = undefined; - writer._closedPromiseState = 'rejected'; -} -function defaultWriterClosedPromiseResetToRejected(writer, reason) { - defaultWriterClosedPromiseInitializeAsRejected(writer, reason); -} -function defaultWriterClosedPromiseResolve(writer) { - if (writer._closedPromise_resolve === undefined) { - return; - } - writer._closedPromise_resolve(undefined); - writer._closedPromise_resolve = undefined; - writer._closedPromise_reject = undefined; - writer._closedPromiseState = 'resolved'; -} -function defaultWriterReadyPromiseInitialize(writer) { - writer._readyPromise = newPromise((resolve, reject) => { - writer._readyPromise_resolve = resolve; - writer._readyPromise_reject = reject; - }); - writer._readyPromiseState = 'pending'; -} -function defaultWriterReadyPromiseInitializeAsRejected(writer, reason) { - defaultWriterReadyPromiseInitialize(writer); - defaultWriterReadyPromiseReject(writer, reason); -} -function defaultWriterReadyPromiseInitializeAsResolved(writer) { - defaultWriterReadyPromiseInitialize(writer); - defaultWriterReadyPromiseResolve(writer); -} -function defaultWriterReadyPromiseReject(writer, reason) { - if (writer._readyPromise_reject === undefined) { - return; - } - setPromiseIsHandledToTrue(writer._readyPromise); - writer._readyPromise_reject(reason); - writer._readyPromise_resolve = undefined; - writer._readyPromise_reject = undefined; - writer._readyPromiseState = 'rejected'; -} -function defaultWriterReadyPromiseReset(writer) { - defaultWriterReadyPromiseInitialize(writer); -} -function defaultWriterReadyPromiseResetToRejected(writer, reason) { - defaultWriterReadyPromiseInitializeAsRejected(writer, reason); -} -function defaultWriterReadyPromiseResolve(writer) { - if (writer._readyPromise_resolve === undefined) { - return; - } - writer._readyPromise_resolve(undefined); - writer._readyPromise_resolve = undefined; - writer._readyPromise_reject = undefined; - writer._readyPromiseState = 'fulfilled'; -} - -function isAbortSignal(value) { - if (typeof value !== 'object' || value === null) { - return false; - } - try { - return typeof value.aborted === 'boolean'; - } - catch (_a) { - // AbortSignal.prototype.aborted throws if its brand check fails - return false; - } -} - -/// -const NativeDOMException = typeof DOMException !== 'undefined' ? DOMException : undefined; - -/// -function isDOMExceptionConstructor(ctor) { - if (!(typeof ctor === 'function' || typeof ctor === 'object')) { - return false; - } - try { - new ctor(); - return true; - } - catch (_a) { - return false; - } -} -function createDOMExceptionPolyfill() { - // eslint-disable-next-line no-shadow - const ctor = function DOMException(message, name) { - this.message = message || ''; - this.name = name || 'Error'; - if (Error.captureStackTrace) { - Error.captureStackTrace(this, this.constructor); - } - }; - ctor.prototype = Object.create(Error.prototype); - Object.defineProperty(ctor.prototype, 'constructor', { value: ctor, writable: true, configurable: true }); - return ctor; -} -// eslint-disable-next-line no-redeclare -const DOMException$1 = isDOMExceptionConstructor(NativeDOMException) ? NativeDOMException : createDOMExceptionPolyfill(); - -function ReadableStreamPipeTo(source, dest, preventClose, preventAbort, preventCancel, signal) { - const reader = AcquireReadableStreamDefaultReader(source); - const writer = AcquireWritableStreamDefaultWriter(dest); - source._disturbed = true; - let shuttingDown = false; - // This is used to keep track of the spec's requirement that we wait for ongoing writes during shutdown. - let currentWrite = promiseResolvedWith(undefined); - return newPromise((resolve, reject) => { - let abortAlgorithm; - if (signal !== undefined) { - abortAlgorithm = () => { - const error = new DOMException$1('Aborted', 'AbortError'); - const actions = []; - if (!preventAbort) { - actions.push(() => { - if (dest._state === 'writable') { - return WritableStreamAbort(dest, error); - } - return promiseResolvedWith(undefined); - }); - } - if (!preventCancel) { - actions.push(() => { - if (source._state === 'readable') { - return ReadableStreamCancel(source, error); - } - return promiseResolvedWith(undefined); - }); - } - shutdownWithAction(() => Promise.all(actions.map(action => action())), true, error); - }; - if (signal.aborted) { - abortAlgorithm(); - return; - } - signal.addEventListener('abort', abortAlgorithm); - } - // Using reader and writer, read all chunks from this and write them to dest - // - Backpressure must be enforced - // - Shutdown must stop all activity - function pipeLoop() { - return newPromise((resolveLoop, rejectLoop) => { - function next(done) { - if (done) { - resolveLoop(); - } - else { - // Use `PerformPromiseThen` instead of `uponPromise` to avoid - // adding unnecessary `.catch(rethrowAssertionErrorRejection)` handlers - PerformPromiseThen(pipeStep(), next, rejectLoop); - } - } - next(false); - }); - } - function pipeStep() { - if (shuttingDown) { - return promiseResolvedWith(true); - } - return PerformPromiseThen(writer._readyPromise, () => { - return newPromise((resolveRead, rejectRead) => { - ReadableStreamDefaultReaderRead(reader, { - _chunkSteps: chunk => { - currentWrite = PerformPromiseThen(WritableStreamDefaultWriterWrite(writer, chunk), undefined, noop); - resolveRead(false); - }, - _closeSteps: () => resolveRead(true), - _errorSteps: rejectRead - }); - }); - }); - } - // Errors must be propagated forward - isOrBecomesErrored(source, reader._closedPromise, storedError => { - if (!preventAbort) { - shutdownWithAction(() => WritableStreamAbort(dest, storedError), true, storedError); - } - else { - shutdown(true, storedError); - } - }); - // Errors must be propagated backward - isOrBecomesErrored(dest, writer._closedPromise, storedError => { - if (!preventCancel) { - shutdownWithAction(() => ReadableStreamCancel(source, storedError), true, storedError); - } - else { - shutdown(true, storedError); - } - }); - // Closing must be propagated forward - isOrBecomesClosed(source, reader._closedPromise, () => { - if (!preventClose) { - shutdownWithAction(() => WritableStreamDefaultWriterCloseWithErrorPropagation(writer)); - } - else { - shutdown(); - } - }); - // Closing must be propagated backward - if (WritableStreamCloseQueuedOrInFlight(dest) || dest._state === 'closed') { - const destClosed = new TypeError('the destination writable stream closed before all data could be piped to it'); - if (!preventCancel) { - shutdownWithAction(() => ReadableStreamCancel(source, destClosed), true, destClosed); - } - else { - shutdown(true, destClosed); - } - } - setPromiseIsHandledToTrue(pipeLoop()); - function waitForWritesToFinish() { - // Another write may have started while we were waiting on this currentWrite, so we have to be sure to wait - // for that too. - const oldCurrentWrite = currentWrite; - return PerformPromiseThen(currentWrite, () => oldCurrentWrite !== currentWrite ? waitForWritesToFinish() : undefined); - } - function isOrBecomesErrored(stream, promise, action) { - if (stream._state === 'errored') { - action(stream._storedError); - } - else { - uponRejection(promise, action); - } - } - function isOrBecomesClosed(stream, promise, action) { - if (stream._state === 'closed') { - action(); - } - else { - uponFulfillment(promise, action); - } - } - function shutdownWithAction(action, originalIsError, originalError) { - if (shuttingDown) { - return; - } - shuttingDown = true; - if (dest._state === 'writable' && !WritableStreamCloseQueuedOrInFlight(dest)) { - uponFulfillment(waitForWritesToFinish(), doTheRest); - } - else { - doTheRest(); - } - function doTheRest() { - uponPromise(action(), () => finalize(originalIsError, originalError), newError => finalize(true, newError)); - } - } - function shutdown(isError, error) { - if (shuttingDown) { - return; - } - shuttingDown = true; - if (dest._state === 'writable' && !WritableStreamCloseQueuedOrInFlight(dest)) { - uponFulfillment(waitForWritesToFinish(), () => finalize(isError, error)); - } - else { - finalize(isError, error); - } - } - function finalize(isError, error) { - WritableStreamDefaultWriterRelease(writer); - ReadableStreamReaderGenericRelease(reader); - if (signal !== undefined) { - signal.removeEventListener('abort', abortAlgorithm); - } - if (isError) { - reject(error); - } - else { - resolve(undefined); - } - } - }); -} - -/** - * Allows control of a {@link ReadableStream | readable stream}'s state and internal queue. - * - * @public - */ -class ReadableStreamDefaultController { - constructor() { - throw new TypeError('Illegal constructor'); - } - /** - * Returns the desired size to fill the controlled stream's internal queue. It can be negative, if the queue is - * over-full. An underlying source ought to use this information to determine when and how to apply backpressure. - */ - get desiredSize() { - if (!IsReadableStreamDefaultController(this)) { - throw defaultControllerBrandCheckException$1('desiredSize'); - } - return ReadableStreamDefaultControllerGetDesiredSize(this); - } - /** - * Closes the controlled readable stream. Consumers will still be able to read any previously-enqueued chunks from - * the stream, but once those are read, the stream will become closed. - */ - close() { - if (!IsReadableStreamDefaultController(this)) { - throw defaultControllerBrandCheckException$1('close'); - } - if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(this)) { - throw new TypeError('The stream is not in a state that permits close'); - } - ReadableStreamDefaultControllerClose(this); - } - enqueue(chunk = undefined) { - if (!IsReadableStreamDefaultController(this)) { - throw defaultControllerBrandCheckException$1('enqueue'); - } - if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(this)) { - throw new TypeError('The stream is not in a state that permits enqueue'); - } - return ReadableStreamDefaultControllerEnqueue(this, chunk); - } - /** - * Errors the controlled readable stream, making all future interactions with it fail with the given error `e`. - */ - error(e = undefined) { - if (!IsReadableStreamDefaultController(this)) { - throw defaultControllerBrandCheckException$1('error'); - } - ReadableStreamDefaultControllerError(this, e); - } - /** @internal */ - [CancelSteps](reason) { - ResetQueue(this); - const result = this._cancelAlgorithm(reason); - ReadableStreamDefaultControllerClearAlgorithms(this); - return result; - } - /** @internal */ - [PullSteps](readRequest) { - const stream = this._controlledReadableStream; - if (this._queue.length > 0) { - const chunk = DequeueValue(this); - if (this._closeRequested && this._queue.length === 0) { - ReadableStreamDefaultControllerClearAlgorithms(this); - ReadableStreamClose(stream); - } - else { - ReadableStreamDefaultControllerCallPullIfNeeded(this); - } - readRequest._chunkSteps(chunk); - } - else { - ReadableStreamAddReadRequest(stream, readRequest); - ReadableStreamDefaultControllerCallPullIfNeeded(this); - } - } -} -Object.defineProperties(ReadableStreamDefaultController.prototype, { - close: { enumerable: true }, - enqueue: { enumerable: true }, - error: { enumerable: true }, - desiredSize: { enumerable: true } -}); -if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(ReadableStreamDefaultController.prototype, SymbolPolyfill.toStringTag, { - value: 'ReadableStreamDefaultController', - configurable: true - }); -} -// Abstract operations for the ReadableStreamDefaultController. -function IsReadableStreamDefaultController(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_controlledReadableStream')) { - return false; - } - return true; -} -function ReadableStreamDefaultControllerCallPullIfNeeded(controller) { - const shouldPull = ReadableStreamDefaultControllerShouldCallPull(controller); - if (!shouldPull) { - return; - } - if (controller._pulling) { - controller._pullAgain = true; - return; - } - controller._pulling = true; - const pullPromise = controller._pullAlgorithm(); - uponPromise(pullPromise, () => { - controller._pulling = false; - if (controller._pullAgain) { - controller._pullAgain = false; - ReadableStreamDefaultControllerCallPullIfNeeded(controller); - } - }, e => { - ReadableStreamDefaultControllerError(controller, e); - }); -} -function ReadableStreamDefaultControllerShouldCallPull(controller) { - const stream = controller._controlledReadableStream; - if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(controller)) { - return false; - } - if (!controller._started) { - return false; - } - if (IsReadableStreamLocked(stream) && ReadableStreamGetNumReadRequests(stream) > 0) { - return true; - } - const desiredSize = ReadableStreamDefaultControllerGetDesiredSize(controller); - if (desiredSize > 0) { - return true; - } - return false; -} -function ReadableStreamDefaultControllerClearAlgorithms(controller) { - controller._pullAlgorithm = undefined; - controller._cancelAlgorithm = undefined; - controller._strategySizeAlgorithm = undefined; -} -// A client of ReadableStreamDefaultController may use these functions directly to bypass state check. -function ReadableStreamDefaultControllerClose(controller) { - if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(controller)) { - return; - } - const stream = controller._controlledReadableStream; - controller._closeRequested = true; - if (controller._queue.length === 0) { - ReadableStreamDefaultControllerClearAlgorithms(controller); - ReadableStreamClose(stream); - } -} -function ReadableStreamDefaultControllerEnqueue(controller, chunk) { - if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(controller)) { - return; - } - const stream = controller._controlledReadableStream; - if (IsReadableStreamLocked(stream) && ReadableStreamGetNumReadRequests(stream) > 0) { - ReadableStreamFulfillReadRequest(stream, chunk, false); - } - else { - let chunkSize; - try { - chunkSize = controller._strategySizeAlgorithm(chunk); - } - catch (chunkSizeE) { - ReadableStreamDefaultControllerError(controller, chunkSizeE); - throw chunkSizeE; - } - try { - EnqueueValueWithSize(controller, chunk, chunkSize); - } - catch (enqueueE) { - ReadableStreamDefaultControllerError(controller, enqueueE); - throw enqueueE; - } - } - ReadableStreamDefaultControllerCallPullIfNeeded(controller); -} -function ReadableStreamDefaultControllerError(controller, e) { - const stream = controller._controlledReadableStream; - if (stream._state !== 'readable') { - return; - } - ResetQueue(controller); - ReadableStreamDefaultControllerClearAlgorithms(controller); - ReadableStreamError(stream, e); -} -function ReadableStreamDefaultControllerGetDesiredSize(controller) { - const state = controller._controlledReadableStream._state; - if (state === 'errored') { - return null; - } - if (state === 'closed') { - return 0; - } - return controller._strategyHWM - controller._queueTotalSize; -} -// This is used in the implementation of TransformStream. -function ReadableStreamDefaultControllerHasBackpressure(controller) { - if (ReadableStreamDefaultControllerShouldCallPull(controller)) { - return false; - } - return true; -} -function ReadableStreamDefaultControllerCanCloseOrEnqueue(controller) { - const state = controller._controlledReadableStream._state; - if (!controller._closeRequested && state === 'readable') { - return true; - } - return false; -} -function SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm) { - controller._controlledReadableStream = stream; - controller._queue = undefined; - controller._queueTotalSize = undefined; - ResetQueue(controller); - controller._started = false; - controller._closeRequested = false; - controller._pullAgain = false; - controller._pulling = false; - controller._strategySizeAlgorithm = sizeAlgorithm; - controller._strategyHWM = highWaterMark; - controller._pullAlgorithm = pullAlgorithm; - controller._cancelAlgorithm = cancelAlgorithm; - stream._readableStreamController = controller; - const startResult = startAlgorithm(); - uponPromise(promiseResolvedWith(startResult), () => { - controller._started = true; - ReadableStreamDefaultControllerCallPullIfNeeded(controller); - }, r => { - ReadableStreamDefaultControllerError(controller, r); - }); -} -function SetUpReadableStreamDefaultControllerFromUnderlyingSource(stream, underlyingSource, highWaterMark, sizeAlgorithm) { - const controller = Object.create(ReadableStreamDefaultController.prototype); - let startAlgorithm = () => undefined; - let pullAlgorithm = () => promiseResolvedWith(undefined); - let cancelAlgorithm = () => promiseResolvedWith(undefined); - if (underlyingSource.start !== undefined) { - startAlgorithm = () => underlyingSource.start(controller); - } - if (underlyingSource.pull !== undefined) { - pullAlgorithm = () => underlyingSource.pull(controller); - } - if (underlyingSource.cancel !== undefined) { - cancelAlgorithm = reason => underlyingSource.cancel(reason); - } - SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm); -} -// Helper functions for the ReadableStreamDefaultController. -function defaultControllerBrandCheckException$1(name) { - return new TypeError(`ReadableStreamDefaultController.prototype.${name} can only be used on a ReadableStreamDefaultController`); -} - -function ReadableStreamTee(stream, cloneForBranch2) { - const reader = AcquireReadableStreamDefaultReader(stream); - let reading = false; - let canceled1 = false; - let canceled2 = false; - let reason1; - let reason2; - let branch1; - let branch2; - let resolveCancelPromise; - const cancelPromise = newPromise(resolve => { - resolveCancelPromise = resolve; - }); - function pullAlgorithm() { - if (reading) { - return promiseResolvedWith(undefined); - } - reading = true; - const readRequest = { - _chunkSteps: value => { - // This needs to be delayed a microtask because it takes at least a microtask to detect errors (using - // reader._closedPromise below), and we want errors in stream to error both branches immediately. We cannot let - // successful synchronously-available reads get ahead of asynchronously-available errors. - queueMicrotask(() => { - reading = false; - const value1 = value; - const value2 = value; - // There is no way to access the cloning code right now in the reference implementation. - // If we add one then we'll need an implementation for serializable objects. - // if (!canceled2 && cloneForBranch2) { - // value2 = StructuredDeserialize(StructuredSerialize(value2)); - // } - if (!canceled1) { - ReadableStreamDefaultControllerEnqueue(branch1._readableStreamController, value1); - } - if (!canceled2) { - ReadableStreamDefaultControllerEnqueue(branch2._readableStreamController, value2); - } - }); - }, - _closeSteps: () => { - reading = false; - if (!canceled1) { - ReadableStreamDefaultControllerClose(branch1._readableStreamController); - } - if (!canceled2) { - ReadableStreamDefaultControllerClose(branch2._readableStreamController); - } - if (!canceled1 || !canceled2) { - resolveCancelPromise(undefined); - } - }, - _errorSteps: () => { - reading = false; - } - }; - ReadableStreamDefaultReaderRead(reader, readRequest); - return promiseResolvedWith(undefined); - } - function cancel1Algorithm(reason) { - canceled1 = true; - reason1 = reason; - if (canceled2) { - const compositeReason = CreateArrayFromList([reason1, reason2]); - const cancelResult = ReadableStreamCancel(stream, compositeReason); - resolveCancelPromise(cancelResult); - } - return cancelPromise; - } - function cancel2Algorithm(reason) { - canceled2 = true; - reason2 = reason; - if (canceled1) { - const compositeReason = CreateArrayFromList([reason1, reason2]); - const cancelResult = ReadableStreamCancel(stream, compositeReason); - resolveCancelPromise(cancelResult); - } - return cancelPromise; - } - function startAlgorithm() { - // do nothing - } - branch1 = CreateReadableStream(startAlgorithm, pullAlgorithm, cancel1Algorithm); - branch2 = CreateReadableStream(startAlgorithm, pullAlgorithm, cancel2Algorithm); - uponRejection(reader._closedPromise, (r) => { - ReadableStreamDefaultControllerError(branch1._readableStreamController, r); - ReadableStreamDefaultControllerError(branch2._readableStreamController, r); - if (!canceled1 || !canceled2) { - resolveCancelPromise(undefined); - } - }); - return [branch1, branch2]; -} - -function convertUnderlyingDefaultOrByteSource(source, context) { - assertDictionary(source, context); - const original = source; - const autoAllocateChunkSize = original === null || original === void 0 ? void 0 : original.autoAllocateChunkSize; - const cancel = original === null || original === void 0 ? void 0 : original.cancel; - const pull = original === null || original === void 0 ? void 0 : original.pull; - const start = original === null || original === void 0 ? void 0 : original.start; - const type = original === null || original === void 0 ? void 0 : original.type; - return { - autoAllocateChunkSize: autoAllocateChunkSize === undefined ? - undefined : - convertUnsignedLongLongWithEnforceRange(autoAllocateChunkSize, `${context} has member 'autoAllocateChunkSize' that`), - cancel: cancel === undefined ? - undefined : - convertUnderlyingSourceCancelCallback(cancel, original, `${context} has member 'cancel' that`), - pull: pull === undefined ? - undefined : - convertUnderlyingSourcePullCallback(pull, original, `${context} has member 'pull' that`), - start: start === undefined ? - undefined : - convertUnderlyingSourceStartCallback(start, original, `${context} has member 'start' that`), - type: type === undefined ? undefined : convertReadableStreamType(type, `${context} has member 'type' that`) - }; -} -function convertUnderlyingSourceCancelCallback(fn, original, context) { - assertFunction(fn, context); - return (reason) => promiseCall(fn, original, [reason]); -} -function convertUnderlyingSourcePullCallback(fn, original, context) { - assertFunction(fn, context); - return (controller) => promiseCall(fn, original, [controller]); -} -function convertUnderlyingSourceStartCallback(fn, original, context) { - assertFunction(fn, context); - return (controller) => reflectCall(fn, original, [controller]); -} -function convertReadableStreamType(type, context) { - type = `${type}`; - if (type !== 'bytes') { - throw new TypeError(`${context} '${type}' is not a valid enumeration value for ReadableStreamType`); - } - return type; -} - -function convertReaderOptions(options, context) { - assertDictionary(options, context); - const mode = options === null || options === void 0 ? void 0 : options.mode; - return { - mode: mode === undefined ? undefined : convertReadableStreamReaderMode(mode, `${context} has member 'mode' that`) - }; -} -function convertReadableStreamReaderMode(mode, context) { - mode = `${mode}`; - if (mode !== 'byob') { - throw new TypeError(`${context} '${mode}' is not a valid enumeration value for ReadableStreamReaderMode`); - } - return mode; -} - -function convertIteratorOptions(options, context) { - assertDictionary(options, context); - const preventCancel = options === null || options === void 0 ? void 0 : options.preventCancel; - return { preventCancel: Boolean(preventCancel) }; -} - -function convertPipeOptions(options, context) { - assertDictionary(options, context); - const preventAbort = options === null || options === void 0 ? void 0 : options.preventAbort; - const preventCancel = options === null || options === void 0 ? void 0 : options.preventCancel; - const preventClose = options === null || options === void 0 ? void 0 : options.preventClose; - const signal = options === null || options === void 0 ? void 0 : options.signal; - if (signal !== undefined) { - assertAbortSignal(signal, `${context} has member 'signal' that`); - } - return { - preventAbort: Boolean(preventAbort), - preventCancel: Boolean(preventCancel), - preventClose: Boolean(preventClose), - signal - }; -} -function assertAbortSignal(signal, context) { - if (!isAbortSignal(signal)) { - throw new TypeError(`${context} is not an AbortSignal.`); - } -} - -function convertReadableWritablePair(pair, context) { - assertDictionary(pair, context); - const readable = pair === null || pair === void 0 ? void 0 : pair.readable; - assertRequiredField(readable, 'readable', 'ReadableWritablePair'); - assertReadableStream(readable, `${context} has member 'readable' that`); - const writable = pair === null || pair === void 0 ? void 0 : pair.writable; - assertRequiredField(writable, 'writable', 'ReadableWritablePair'); - assertWritableStream(writable, `${context} has member 'writable' that`); - return { readable, writable }; -} - -/** - * A readable stream represents a source of data, from which you can read. - * - * @public - */ -class ReadableStream$1 { - constructor(rawUnderlyingSource = {}, rawStrategy = {}) { - if (rawUnderlyingSource === undefined) { - rawUnderlyingSource = null; - } - else { - assertObject(rawUnderlyingSource, 'First parameter'); - } - const strategy = convertQueuingStrategy(rawStrategy, 'Second parameter'); - const underlyingSource = convertUnderlyingDefaultOrByteSource(rawUnderlyingSource, 'First parameter'); - InitializeReadableStream(this); - if (underlyingSource.type === 'bytes') { - if (strategy.size !== undefined) { - throw new RangeError('The strategy for a byte stream cannot have a size function'); - } - const highWaterMark = ExtractHighWaterMark(strategy, 0); - SetUpReadableByteStreamControllerFromUnderlyingSource(this, underlyingSource, highWaterMark); - } - else { - const sizeAlgorithm = ExtractSizeAlgorithm(strategy); - const highWaterMark = ExtractHighWaterMark(strategy, 1); - SetUpReadableStreamDefaultControllerFromUnderlyingSource(this, underlyingSource, highWaterMark, sizeAlgorithm); - } - } - /** - * Whether or not the readable stream is locked to a {@link ReadableStreamDefaultReader | reader}. - */ - get locked() { - if (!IsReadableStream(this)) { - throw streamBrandCheckException$1('locked'); - } - return IsReadableStreamLocked(this); - } - /** - * Cancels the stream, signaling a loss of interest in the stream by a consumer. - * - * The supplied `reason` argument will be given to the underlying source's {@link UnderlyingSource.cancel | cancel()} - * method, which might or might not use it. - */ - cancel(reason = undefined) { - if (!IsReadableStream(this)) { - return promiseRejectedWith(streamBrandCheckException$1('cancel')); - } - if (IsReadableStreamLocked(this)) { - return promiseRejectedWith(new TypeError('Cannot cancel a stream that already has a reader')); - } - return ReadableStreamCancel(this, reason); - } - getReader(rawOptions = undefined) { - if (!IsReadableStream(this)) { - throw streamBrandCheckException$1('getReader'); - } - const options = convertReaderOptions(rawOptions, 'First parameter'); - if (options.mode === undefined) { - return AcquireReadableStreamDefaultReader(this); - } - return AcquireReadableStreamBYOBReader(this); - } - pipeThrough(rawTransform, rawOptions = {}) { - if (!IsReadableStream(this)) { - throw streamBrandCheckException$1('pipeThrough'); - } - assertRequiredArgument(rawTransform, 1, 'pipeThrough'); - const transform = convertReadableWritablePair(rawTransform, 'First parameter'); - const options = convertPipeOptions(rawOptions, 'Second parameter'); - if (IsReadableStreamLocked(this)) { - throw new TypeError('ReadableStream.prototype.pipeThrough cannot be used on a locked ReadableStream'); - } - if (IsWritableStreamLocked(transform.writable)) { - throw new TypeError('ReadableStream.prototype.pipeThrough cannot be used on a locked WritableStream'); - } - const promise = ReadableStreamPipeTo(this, transform.writable, options.preventClose, options.preventAbort, options.preventCancel, options.signal); - setPromiseIsHandledToTrue(promise); - return transform.readable; - } - pipeTo(destination, rawOptions = {}) { - if (!IsReadableStream(this)) { - return promiseRejectedWith(streamBrandCheckException$1('pipeTo')); - } - if (destination === undefined) { - return promiseRejectedWith(`Parameter 1 is required in 'pipeTo'.`); - } - if (!IsWritableStream(destination)) { - return promiseRejectedWith(new TypeError(`ReadableStream.prototype.pipeTo's first argument must be a WritableStream`)); - } - let options; - try { - options = convertPipeOptions(rawOptions, 'Second parameter'); - } - catch (e) { - return promiseRejectedWith(e); - } - if (IsReadableStreamLocked(this)) { - return promiseRejectedWith(new TypeError('ReadableStream.prototype.pipeTo cannot be used on a locked ReadableStream')); - } - if (IsWritableStreamLocked(destination)) { - return promiseRejectedWith(new TypeError('ReadableStream.prototype.pipeTo cannot be used on a locked WritableStream')); - } - return ReadableStreamPipeTo(this, destination, options.preventClose, options.preventAbort, options.preventCancel, options.signal); - } - /** - * Tees this readable stream, returning a two-element array containing the two resulting branches as - * new {@link ReadableStream} instances. - * - * Teeing a stream will lock it, preventing any other consumer from acquiring a reader. - * To cancel the stream, cancel both of the resulting branches; a composite cancellation reason will then be - * propagated to the stream's underlying source. - * - * Note that the chunks seen in each branch will be the same object. If the chunks are not immutable, - * this could allow interference between the two branches. - */ - tee() { - if (!IsReadableStream(this)) { - throw streamBrandCheckException$1('tee'); - } - const branches = ReadableStreamTee(this); - return CreateArrayFromList(branches); - } - values(rawOptions = undefined) { - if (!IsReadableStream(this)) { - throw streamBrandCheckException$1('values'); - } - const options = convertIteratorOptions(rawOptions, 'First parameter'); - return AcquireReadableStreamAsyncIterator(this, options.preventCancel); - } -} -Object.defineProperties(ReadableStream$1.prototype, { - cancel: { enumerable: true }, - getReader: { enumerable: true }, - pipeThrough: { enumerable: true }, - pipeTo: { enumerable: true }, - tee: { enumerable: true }, - values: { enumerable: true }, - locked: { enumerable: true } -}); -if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(ReadableStream$1.prototype, SymbolPolyfill.toStringTag, { - value: 'ReadableStream', - configurable: true - }); -} -if (typeof SymbolPolyfill.asyncIterator === 'symbol') { - Object.defineProperty(ReadableStream$1.prototype, SymbolPolyfill.asyncIterator, { - value: ReadableStream$1.prototype.values, - writable: true, - configurable: true - }); -} -// Abstract operations for the ReadableStream. -// Throws if and only if startAlgorithm throws. -function CreateReadableStream(startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark = 1, sizeAlgorithm = () => 1) { - const stream = Object.create(ReadableStream$1.prototype); - InitializeReadableStream(stream); - const controller = Object.create(ReadableStreamDefaultController.prototype); - SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm); - return stream; -} -function InitializeReadableStream(stream) { - stream._state = 'readable'; - stream._reader = undefined; - stream._storedError = undefined; - stream._disturbed = false; -} -function IsReadableStream(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_readableStreamController')) { - return false; - } - return true; -} -function IsReadableStreamLocked(stream) { - if (stream._reader === undefined) { - return false; - } - return true; -} -// ReadableStream API exposed for controllers. -function ReadableStreamCancel(stream, reason) { - stream._disturbed = true; - if (stream._state === 'closed') { - return promiseResolvedWith(undefined); - } - if (stream._state === 'errored') { - return promiseRejectedWith(stream._storedError); - } - ReadableStreamClose(stream); - const sourceCancelPromise = stream._readableStreamController[CancelSteps](reason); - return transformPromiseWith(sourceCancelPromise, noop); -} -function ReadableStreamClose(stream) { - stream._state = 'closed'; - const reader = stream._reader; - if (reader === undefined) { - return; - } - defaultReaderClosedPromiseResolve(reader); - if (IsReadableStreamDefaultReader(reader)) { - reader._readRequests.forEach(readRequest => { - readRequest._closeSteps(); - }); - reader._readRequests = new SimpleQueue(); - } -} -function ReadableStreamError(stream, e) { - stream._state = 'errored'; - stream._storedError = e; - const reader = stream._reader; - if (reader === undefined) { - return; - } - defaultReaderClosedPromiseReject(reader, e); - if (IsReadableStreamDefaultReader(reader)) { - reader._readRequests.forEach(readRequest => { - readRequest._errorSteps(e); - }); - reader._readRequests = new SimpleQueue(); - } - else { - reader._readIntoRequests.forEach(readIntoRequest => { - readIntoRequest._errorSteps(e); - }); - reader._readIntoRequests = new SimpleQueue(); - } -} -// Helper functions for the ReadableStream. -function streamBrandCheckException$1(name) { - return new TypeError(`ReadableStream.prototype.${name} can only be used on a ReadableStream`); -} - -function convertQueuingStrategyInit(init, context) { - assertDictionary(init, context); - const highWaterMark = init === null || init === void 0 ? void 0 : init.highWaterMark; - assertRequiredField(highWaterMark, 'highWaterMark', 'QueuingStrategyInit'); - return { - highWaterMark: convertUnrestrictedDouble(highWaterMark) - }; -} - -const byteLengthSizeFunction = function size(chunk) { - return chunk.byteLength; -}; -/** - * A queuing strategy that counts the number of bytes in each chunk. - * - * @public - */ -class ByteLengthQueuingStrategy { - constructor(options) { - assertRequiredArgument(options, 1, 'ByteLengthQueuingStrategy'); - options = convertQueuingStrategyInit(options, 'First parameter'); - this._byteLengthQueuingStrategyHighWaterMark = options.highWaterMark; - } - /** - * Returns the high water mark provided to the constructor. - */ - get highWaterMark() { - if (!IsByteLengthQueuingStrategy(this)) { - throw byteLengthBrandCheckException('highWaterMark'); - } - return this._byteLengthQueuingStrategyHighWaterMark; - } - /** - * Measures the size of `chunk` by returning the value of its `byteLength` property. - */ - get size() { - if (!IsByteLengthQueuingStrategy(this)) { - throw byteLengthBrandCheckException('size'); - } - return byteLengthSizeFunction; - } -} -Object.defineProperties(ByteLengthQueuingStrategy.prototype, { - highWaterMark: { enumerable: true }, - size: { enumerable: true } -}); -if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(ByteLengthQueuingStrategy.prototype, SymbolPolyfill.toStringTag, { - value: 'ByteLengthQueuingStrategy', - configurable: true - }); -} -// Helper functions for the ByteLengthQueuingStrategy. -function byteLengthBrandCheckException(name) { - return new TypeError(`ByteLengthQueuingStrategy.prototype.${name} can only be used on a ByteLengthQueuingStrategy`); -} -function IsByteLengthQueuingStrategy(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_byteLengthQueuingStrategyHighWaterMark')) { - return false; - } - return true; -} - -const countSizeFunction = function size() { - return 1; -}; -/** - * A queuing strategy that counts the number of chunks. - * - * @public - */ -class CountQueuingStrategy { - constructor(options) { - assertRequiredArgument(options, 1, 'CountQueuingStrategy'); - options = convertQueuingStrategyInit(options, 'First parameter'); - this._countQueuingStrategyHighWaterMark = options.highWaterMark; - } - /** - * Returns the high water mark provided to the constructor. - */ - get highWaterMark() { - if (!IsCountQueuingStrategy(this)) { - throw countBrandCheckException('highWaterMark'); - } - return this._countQueuingStrategyHighWaterMark; - } - /** - * Measures the size of `chunk` by always returning 1. - * This ensures that the total queue size is a count of the number of chunks in the queue. - */ - get size() { - if (!IsCountQueuingStrategy(this)) { - throw countBrandCheckException('size'); - } - return countSizeFunction; - } -} -Object.defineProperties(CountQueuingStrategy.prototype, { - highWaterMark: { enumerable: true }, - size: { enumerable: true } -}); -if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(CountQueuingStrategy.prototype, SymbolPolyfill.toStringTag, { - value: 'CountQueuingStrategy', - configurable: true - }); -} -// Helper functions for the CountQueuingStrategy. -function countBrandCheckException(name) { - return new TypeError(`CountQueuingStrategy.prototype.${name} can only be used on a CountQueuingStrategy`); -} -function IsCountQueuingStrategy(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_countQueuingStrategyHighWaterMark')) { - return false; - } - return true; -} - -function convertTransformer(original, context) { - assertDictionary(original, context); - const flush = original === null || original === void 0 ? void 0 : original.flush; - const readableType = original === null || original === void 0 ? void 0 : original.readableType; - const start = original === null || original === void 0 ? void 0 : original.start; - const transform = original === null || original === void 0 ? void 0 : original.transform; - const writableType = original === null || original === void 0 ? void 0 : original.writableType; - return { - flush: flush === undefined ? - undefined : - convertTransformerFlushCallback(flush, original, `${context} has member 'flush' that`), - readableType, - start: start === undefined ? - undefined : - convertTransformerStartCallback(start, original, `${context} has member 'start' that`), - transform: transform === undefined ? - undefined : - convertTransformerTransformCallback(transform, original, `${context} has member 'transform' that`), - writableType - }; -} -function convertTransformerFlushCallback(fn, original, context) { - assertFunction(fn, context); - return (controller) => promiseCall(fn, original, [controller]); -} -function convertTransformerStartCallback(fn, original, context) { - assertFunction(fn, context); - return (controller) => reflectCall(fn, original, [controller]); -} -function convertTransformerTransformCallback(fn, original, context) { - assertFunction(fn, context); - return (chunk, controller) => promiseCall(fn, original, [chunk, controller]); -} - -// Class TransformStream -/** - * A transform stream consists of a pair of streams: a {@link WritableStream | writable stream}, - * known as its writable side, and a {@link ReadableStream | readable stream}, known as its readable side. - * In a manner specific to the transform stream in question, writes to the writable side result in new data being - * made available for reading from the readable side. - * - * @public - */ -class TransformStream$1 { - constructor(rawTransformer = {}, rawWritableStrategy = {}, rawReadableStrategy = {}) { - if (rawTransformer === undefined) { - rawTransformer = null; - } - const writableStrategy = convertQueuingStrategy(rawWritableStrategy, 'Second parameter'); - const readableStrategy = convertQueuingStrategy(rawReadableStrategy, 'Third parameter'); - const transformer = convertTransformer(rawTransformer, 'First parameter'); - if (transformer.readableType !== undefined) { - throw new RangeError('Invalid readableType specified'); - } - if (transformer.writableType !== undefined) { - throw new RangeError('Invalid writableType specified'); - } - const readableHighWaterMark = ExtractHighWaterMark(readableStrategy, 0); - const readableSizeAlgorithm = ExtractSizeAlgorithm(readableStrategy); - const writableHighWaterMark = ExtractHighWaterMark(writableStrategy, 1); - const writableSizeAlgorithm = ExtractSizeAlgorithm(writableStrategy); - let startPromise_resolve; - const startPromise = newPromise(resolve => { - startPromise_resolve = resolve; - }); - InitializeTransformStream(this, startPromise, writableHighWaterMark, writableSizeAlgorithm, readableHighWaterMark, readableSizeAlgorithm); - SetUpTransformStreamDefaultControllerFromTransformer(this, transformer); - if (transformer.start !== undefined) { - startPromise_resolve(transformer.start(this._transformStreamController)); - } - else { - startPromise_resolve(undefined); - } - } - /** - * The readable side of the transform stream. - */ - get readable() { - if (!IsTransformStream(this)) { - throw streamBrandCheckException('readable'); - } - return this._readable; - } - /** - * The writable side of the transform stream. - */ - get writable() { - if (!IsTransformStream(this)) { - throw streamBrandCheckException('writable'); - } - return this._writable; - } -} -Object.defineProperties(TransformStream$1.prototype, { - readable: { enumerable: true }, - writable: { enumerable: true } -}); -if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(TransformStream$1.prototype, SymbolPolyfill.toStringTag, { - value: 'TransformStream', - configurable: true - }); -} -function InitializeTransformStream(stream, startPromise, writableHighWaterMark, writableSizeAlgorithm, readableHighWaterMark, readableSizeAlgorithm) { - function startAlgorithm() { - return startPromise; - } - function writeAlgorithm(chunk) { - return TransformStreamDefaultSinkWriteAlgorithm(stream, chunk); - } - function abortAlgorithm(reason) { - return TransformStreamDefaultSinkAbortAlgorithm(stream, reason); - } - function closeAlgorithm() { - return TransformStreamDefaultSinkCloseAlgorithm(stream); - } - stream._writable = CreateWritableStream(startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, writableHighWaterMark, writableSizeAlgorithm); - function pullAlgorithm() { - return TransformStreamDefaultSourcePullAlgorithm(stream); - } - function cancelAlgorithm(reason) { - TransformStreamErrorWritableAndUnblockWrite(stream, reason); - return promiseResolvedWith(undefined); - } - stream._readable = CreateReadableStream(startAlgorithm, pullAlgorithm, cancelAlgorithm, readableHighWaterMark, readableSizeAlgorithm); - // The [[backpressure]] slot is set to undefined so that it can be initialised by TransformStreamSetBackpressure. - stream._backpressure = undefined; - stream._backpressureChangePromise = undefined; - stream._backpressureChangePromise_resolve = undefined; - TransformStreamSetBackpressure(stream, true); - stream._transformStreamController = undefined; -} -function IsTransformStream(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_transformStreamController')) { - return false; - } - return true; -} -// This is a no-op if both sides are already errored. -function TransformStreamError(stream, e) { - ReadableStreamDefaultControllerError(stream._readable._readableStreamController, e); - TransformStreamErrorWritableAndUnblockWrite(stream, e); -} -function TransformStreamErrorWritableAndUnblockWrite(stream, e) { - TransformStreamDefaultControllerClearAlgorithms(stream._transformStreamController); - WritableStreamDefaultControllerErrorIfNeeded(stream._writable._writableStreamController, e); - if (stream._backpressure) { - // Pretend that pull() was called to permit any pending write() calls to complete. TransformStreamSetBackpressure() - // cannot be called from enqueue() or pull() once the ReadableStream is errored, so this will will be the final time - // _backpressure is set. - TransformStreamSetBackpressure(stream, false); - } -} -function TransformStreamSetBackpressure(stream, backpressure) { - // Passes also when called during construction. - if (stream._backpressureChangePromise !== undefined) { - stream._backpressureChangePromise_resolve(); - } - stream._backpressureChangePromise = newPromise(resolve => { - stream._backpressureChangePromise_resolve = resolve; - }); - stream._backpressure = backpressure; -} -// Class TransformStreamDefaultController -/** - * Allows control of the {@link ReadableStream} and {@link WritableStream} of the associated {@link TransformStream}. - * - * @public - */ -class TransformStreamDefaultController { - constructor() { - throw new TypeError('Illegal constructor'); - } - /** - * Returns the desired size to fill the readable side’s internal queue. It can be negative, if the queue is over-full. - */ - get desiredSize() { - if (!IsTransformStreamDefaultController(this)) { - throw defaultControllerBrandCheckException('desiredSize'); - } - const readableController = this._controlledTransformStream._readable._readableStreamController; - return ReadableStreamDefaultControllerGetDesiredSize(readableController); - } - enqueue(chunk = undefined) { - if (!IsTransformStreamDefaultController(this)) { - throw defaultControllerBrandCheckException('enqueue'); - } - TransformStreamDefaultControllerEnqueue(this, chunk); - } - /** - * Errors both the readable side and the writable side of the controlled transform stream, making all future - * interactions with it fail with the given error `e`. Any chunks queued for transformation will be discarded. - */ - error(reason = undefined) { - if (!IsTransformStreamDefaultController(this)) { - throw defaultControllerBrandCheckException('error'); - } - TransformStreamDefaultControllerError(this, reason); - } - /** - * Closes the readable side and errors the writable side of the controlled transform stream. This is useful when the - * transformer only needs to consume a portion of the chunks written to the writable side. - */ - terminate() { - if (!IsTransformStreamDefaultController(this)) { - throw defaultControllerBrandCheckException('terminate'); - } - TransformStreamDefaultControllerTerminate(this); - } -} -Object.defineProperties(TransformStreamDefaultController.prototype, { - enqueue: { enumerable: true }, - error: { enumerable: true }, - terminate: { enumerable: true }, - desiredSize: { enumerable: true } -}); -if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(TransformStreamDefaultController.prototype, SymbolPolyfill.toStringTag, { - value: 'TransformStreamDefaultController', - configurable: true - }); -} -// Transform Stream Default Controller Abstract Operations -function IsTransformStreamDefaultController(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_controlledTransformStream')) { - return false; - } - return true; -} -function SetUpTransformStreamDefaultController(stream, controller, transformAlgorithm, flushAlgorithm) { - controller._controlledTransformStream = stream; - stream._transformStreamController = controller; - controller._transformAlgorithm = transformAlgorithm; - controller._flushAlgorithm = flushAlgorithm; -} -function SetUpTransformStreamDefaultControllerFromTransformer(stream, transformer) { - const controller = Object.create(TransformStreamDefaultController.prototype); - let transformAlgorithm = (chunk) => { - try { - TransformStreamDefaultControllerEnqueue(controller, chunk); - return promiseResolvedWith(undefined); - } - catch (transformResultE) { - return promiseRejectedWith(transformResultE); - } - }; - let flushAlgorithm = () => promiseResolvedWith(undefined); - if (transformer.transform !== undefined) { - transformAlgorithm = chunk => transformer.transform(chunk, controller); - } - if (transformer.flush !== undefined) { - flushAlgorithm = () => transformer.flush(controller); - } - SetUpTransformStreamDefaultController(stream, controller, transformAlgorithm, flushAlgorithm); -} -function TransformStreamDefaultControllerClearAlgorithms(controller) { - controller._transformAlgorithm = undefined; - controller._flushAlgorithm = undefined; -} -function TransformStreamDefaultControllerEnqueue(controller, chunk) { - const stream = controller._controlledTransformStream; - const readableController = stream._readable._readableStreamController; - if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(readableController)) { - throw new TypeError('Readable side is not in a state that permits enqueue'); - } - // We throttle transform invocations based on the backpressure of the ReadableStream, but we still - // accept TransformStreamDefaultControllerEnqueue() calls. - try { - ReadableStreamDefaultControllerEnqueue(readableController, chunk); - } - catch (e) { - // This happens when readableStrategy.size() throws. - TransformStreamErrorWritableAndUnblockWrite(stream, e); - throw stream._readable._storedError; - } - const backpressure = ReadableStreamDefaultControllerHasBackpressure(readableController); - if (backpressure !== stream._backpressure) { - TransformStreamSetBackpressure(stream, true); - } -} -function TransformStreamDefaultControllerError(controller, e) { - TransformStreamError(controller._controlledTransformStream, e); -} -function TransformStreamDefaultControllerPerformTransform(controller, chunk) { - const transformPromise = controller._transformAlgorithm(chunk); - return transformPromiseWith(transformPromise, undefined, r => { - TransformStreamError(controller._controlledTransformStream, r); - throw r; - }); -} -function TransformStreamDefaultControllerTerminate(controller) { - const stream = controller._controlledTransformStream; - const readableController = stream._readable._readableStreamController; - ReadableStreamDefaultControllerClose(readableController); - const error = new TypeError('TransformStream terminated'); - TransformStreamErrorWritableAndUnblockWrite(stream, error); -} -// TransformStreamDefaultSink Algorithms -function TransformStreamDefaultSinkWriteAlgorithm(stream, chunk) { - const controller = stream._transformStreamController; - if (stream._backpressure) { - const backpressureChangePromise = stream._backpressureChangePromise; - return transformPromiseWith(backpressureChangePromise, () => { - const writable = stream._writable; - const state = writable._state; - if (state === 'erroring') { - throw writable._storedError; - } - return TransformStreamDefaultControllerPerformTransform(controller, chunk); - }); - } - return TransformStreamDefaultControllerPerformTransform(controller, chunk); -} -function TransformStreamDefaultSinkAbortAlgorithm(stream, reason) { - // abort() is not called synchronously, so it is possible for abort() to be called when the stream is already - // errored. - TransformStreamError(stream, reason); - return promiseResolvedWith(undefined); -} -function TransformStreamDefaultSinkCloseAlgorithm(stream) { - // stream._readable cannot change after construction, so caching it across a call to user code is safe. - const readable = stream._readable; - const controller = stream._transformStreamController; - const flushPromise = controller._flushAlgorithm(); - TransformStreamDefaultControllerClearAlgorithms(controller); - // Return a promise that is fulfilled with undefined on success. - return transformPromiseWith(flushPromise, () => { - if (readable._state === 'errored') { - throw readable._storedError; - } - ReadableStreamDefaultControllerClose(readable._readableStreamController); - }, r => { - TransformStreamError(stream, r); - throw readable._storedError; - }); -} -// TransformStreamDefaultSource Algorithms -function TransformStreamDefaultSourcePullAlgorithm(stream) { - // Invariant. Enforced by the promises returned by start() and pull(). - TransformStreamSetBackpressure(stream, false); - // Prevent the next pull() call until there is backpressure. - return stream._backpressureChangePromise; -} -// Helper functions for the TransformStreamDefaultController. -function defaultControllerBrandCheckException(name) { - return new TypeError(`TransformStreamDefaultController.prototype.${name} can only be used on a TransformStreamDefaultController`); -} -// Helper functions for the TransformStream. -function streamBrandCheckException(name) { - return new TypeError(`TransformStream.prototype.${name} can only be used on a TransformStream`); -} - -var ponyfill_es6 = /*#__PURE__*/Object.freeze({ - __proto__: null, - ByteLengthQueuingStrategy: ByteLengthQueuingStrategy, - CountQueuingStrategy: CountQueuingStrategy, - ReadableByteStreamController: ReadableByteStreamController, - ReadableStream: ReadableStream$1, - ReadableStreamBYOBReader: ReadableStreamBYOBReader, - ReadableStreamBYOBRequest: ReadableStreamBYOBRequest, - ReadableStreamDefaultController: ReadableStreamDefaultController, - ReadableStreamDefaultReader: ReadableStreamDefaultReader, - TransformStream: TransformStream$1, - TransformStreamDefaultController: TransformStreamDefaultController, - WritableStream: WritableStream$1, - WritableStreamDefaultController: WritableStreamDefaultController, - WritableStreamDefaultWriter: WritableStreamDefaultWriter -}); - -/*! ***************************************************************************** -Copyright (c) Microsoft Corporation. - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. -***************************************************************************** */ -/* global Reflect, Promise */ - -var extendStatics = function(d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); -}; - -function __extends(d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); -} - -function assert$1(test) { - if (!test) { - throw new TypeError('Assertion failed'); - } -} - -function noop$1() { - return; -} -function typeIsObject$1(x) { - return (typeof x === 'object' && x !== null) || typeof x === 'function'; -} - -function isStreamConstructor(ctor) { - if (typeof ctor !== 'function') { - return false; - } - var startCalled = false; - try { - new ctor({ - start: function () { - startCalled = true; - } - }); - } - catch (e) { - // ignore - } - return startCalled; -} -function isReadableStream(readable) { - if (!typeIsObject$1(readable)) { - return false; - } - if (typeof readable.getReader !== 'function') { - return false; - } - return true; -} -function isReadableStreamConstructor(ctor) { - if (!isStreamConstructor(ctor)) { - return false; - } - if (!isReadableStream(new ctor())) { - return false; - } - return true; -} -function isWritableStream(writable) { - if (!typeIsObject$1(writable)) { - return false; - } - if (typeof writable.getWriter !== 'function') { - return false; - } - return true; -} -function isWritableStreamConstructor(ctor) { - if (!isStreamConstructor(ctor)) { - return false; - } - if (!isWritableStream(new ctor())) { - return false; - } - return true; -} -function isTransformStream(transform) { - if (!typeIsObject$1(transform)) { - return false; - } - if (!isReadableStream(transform.readable)) { - return false; - } - if (!isWritableStream(transform.writable)) { - return false; - } - return true; -} -function isTransformStreamConstructor(ctor) { - if (!isStreamConstructor(ctor)) { - return false; - } - if (!isTransformStream(new ctor())) { - return false; - } - return true; -} -function supportsByobReader(readable) { - try { - var reader = readable.getReader({ mode: 'byob' }); - reader.releaseLock(); - return true; - } - catch (_a) { - return false; - } -} -function supportsByteSource(ctor) { - try { - new ctor({ type: 'bytes' }); - return true; - } - catch (_a) { - return false; - } -} - -function createReadableStreamWrapper(ctor) { - assert$1(isReadableStreamConstructor(ctor)); - var byteSourceSupported = supportsByteSource(ctor); - return function (readable, _a) { - var _b = _a === void 0 ? {} : _a, type = _b.type; - type = parseReadableType(type); - if (type === 'bytes' && !byteSourceSupported) { - type = undefined; - } - if (readable.constructor === ctor) { - if (type !== 'bytes' || supportsByobReader(readable)) { - return readable; - } - } - if (type === 'bytes') { - var source = createWrappingReadableSource(readable, { type: type }); - return new ctor(source); - } - else { - var source = createWrappingReadableSource(readable); - return new ctor(source); - } - }; -} -function createWrappingReadableSource(readable, _a) { - var _b = _a === void 0 ? {} : _a, type = _b.type; - assert$1(isReadableStream(readable)); - assert$1(readable.locked === false); - type = parseReadableType(type); - var source; - if (type === 'bytes') { - source = new WrappingReadableByteStreamSource(readable); - } - else { - source = new WrappingReadableStreamDefaultSource(readable); - } - return source; -} -function parseReadableType(type) { - var typeString = String(type); - if (typeString === 'bytes') { - return typeString; - } - else if (type === undefined) { - return type; - } - else { - throw new RangeError('Invalid type is specified'); - } -} -var AbstractWrappingReadableStreamSource = /** @class */ (function () { - function AbstractWrappingReadableStreamSource(underlyingStream) { - this._underlyingReader = undefined; - this._readerMode = undefined; - this._readableStreamController = undefined; - this._pendingRead = undefined; - this._underlyingStream = underlyingStream; - // always keep a reader attached to detect close/error - this._attachDefaultReader(); - } - AbstractWrappingReadableStreamSource.prototype.start = function (controller) { - this._readableStreamController = controller; - }; - AbstractWrappingReadableStreamSource.prototype.cancel = function (reason) { - assert$1(this._underlyingReader !== undefined); - return this._underlyingReader.cancel(reason); - }; - AbstractWrappingReadableStreamSource.prototype._attachDefaultReader = function () { - if (this._readerMode === "default" /* DEFAULT */) { - return; - } - this._detachReader(); - var reader = this._underlyingStream.getReader(); - this._readerMode = "default" /* DEFAULT */; - this._attachReader(reader); - }; - AbstractWrappingReadableStreamSource.prototype._attachReader = function (reader) { - var _this = this; - assert$1(this._underlyingReader === undefined); - this._underlyingReader = reader; - var closed = this._underlyingReader.closed; - if (!closed) { - return; - } - closed - .then(function () { return _this._finishPendingRead(); }) - .then(function () { - if (reader === _this._underlyingReader) { - _this._readableStreamController.close(); - } - }, function (reason) { - if (reader === _this._underlyingReader) { - _this._readableStreamController.error(reason); - } - }) - .catch(noop$1); - }; - AbstractWrappingReadableStreamSource.prototype._detachReader = function () { - if (this._underlyingReader === undefined) { - return; - } - this._underlyingReader.releaseLock(); - this._underlyingReader = undefined; - this._readerMode = undefined; - }; - AbstractWrappingReadableStreamSource.prototype._pullWithDefaultReader = function () { - var _this = this; - this._attachDefaultReader(); - // TODO Backpressure? - var read = this._underlyingReader.read() - .then(function (result) { - var controller = _this._readableStreamController; - if (result.done) { - _this._tryClose(); - } - else { - controller.enqueue(result.value); - } - }); - this._setPendingRead(read); - return read; - }; - AbstractWrappingReadableStreamSource.prototype._tryClose = function () { - try { - this._readableStreamController.close(); - } - catch (_a) { - // already errored or closed - } - }; - AbstractWrappingReadableStreamSource.prototype._setPendingRead = function (readPromise) { - var _this = this; - var pendingRead; - var finishRead = function () { - if (_this._pendingRead === pendingRead) { - _this._pendingRead = undefined; - } - }; - this._pendingRead = pendingRead = readPromise.then(finishRead, finishRead); - }; - AbstractWrappingReadableStreamSource.prototype._finishPendingRead = function () { - var _this = this; - if (!this._pendingRead) { - return undefined; - } - var afterRead = function () { return _this._finishPendingRead(); }; - return this._pendingRead.then(afterRead, afterRead); - }; - return AbstractWrappingReadableStreamSource; -}()); -var WrappingReadableStreamDefaultSource = /** @class */ (function (_super) { - __extends(WrappingReadableStreamDefaultSource, _super); - function WrappingReadableStreamDefaultSource() { - return _super !== null && _super.apply(this, arguments) || this; - } - WrappingReadableStreamDefaultSource.prototype.pull = function () { - return this._pullWithDefaultReader(); - }; - return WrappingReadableStreamDefaultSource; -}(AbstractWrappingReadableStreamSource)); -function toUint8Array(view) { - return new Uint8Array(view.buffer, view.byteOffset, view.byteLength); -} -function copyArrayBufferView(from, to) { - var fromArray = toUint8Array(from); - var toArray = toUint8Array(to); - toArray.set(fromArray, 0); -} -var WrappingReadableByteStreamSource = /** @class */ (function (_super) { - __extends(WrappingReadableByteStreamSource, _super); - function WrappingReadableByteStreamSource(underlyingStream) { - var _this = this; - var supportsByob = supportsByobReader(underlyingStream); - _this = _super.call(this, underlyingStream) || this; - _this._supportsByob = supportsByob; - return _this; - } - Object.defineProperty(WrappingReadableByteStreamSource.prototype, "type", { - get: function () { - return 'bytes'; - }, - enumerable: false, - configurable: true - }); - WrappingReadableByteStreamSource.prototype._attachByobReader = function () { - if (this._readerMode === "byob" /* BYOB */) { - return; - } - assert$1(this._supportsByob); - this._detachReader(); - var reader = this._underlyingStream.getReader({ mode: 'byob' }); - this._readerMode = "byob" /* BYOB */; - this._attachReader(reader); - }; - WrappingReadableByteStreamSource.prototype.pull = function () { - if (this._supportsByob) { - var byobRequest = this._readableStreamController.byobRequest; - if (byobRequest) { - return this._pullWithByobRequest(byobRequest); - } - } - return this._pullWithDefaultReader(); - }; - WrappingReadableByteStreamSource.prototype._pullWithByobRequest = function (byobRequest) { - var _this = this; - this._attachByobReader(); - // reader.read(view) detaches the input view, therefore we cannot pass byobRequest.view directly - // create a separate buffer to read into, then copy that to byobRequest.view - var buffer = new Uint8Array(byobRequest.view.byteLength); - // TODO Backpressure? - var read = this._underlyingReader.read(buffer) - .then(function (result) { - _this._readableStreamController; - if (result.done) { - _this._tryClose(); - byobRequest.respond(0); - } - else { - copyArrayBufferView(result.value, byobRequest.view); - byobRequest.respond(result.value.byteLength); - } - }); - this._setPendingRead(read); - return read; - }; - return WrappingReadableByteStreamSource; -}(AbstractWrappingReadableStreamSource)); - -function createWritableStreamWrapper(ctor) { - assert$1(isWritableStreamConstructor(ctor)); - return function (writable) { - if (writable.constructor === ctor) { - return writable; - } - var sink = createWrappingWritableSink(writable); - return new ctor(sink); - }; -} -function createWrappingWritableSink(writable) { - assert$1(isWritableStream(writable)); - assert$1(writable.locked === false); - var writer = writable.getWriter(); - return new WrappingWritableStreamSink(writer); -} -var WrappingWritableStreamSink = /** @class */ (function () { - function WrappingWritableStreamSink(underlyingWriter) { - var _this = this; - this._writableStreamController = undefined; - this._pendingWrite = undefined; - this._state = "writable" /* WRITABLE */; - this._storedError = undefined; - this._underlyingWriter = underlyingWriter; - this._errorPromise = new Promise(function (resolve, reject) { - _this._errorPromiseReject = reject; - }); - this._errorPromise.catch(noop$1); - } - WrappingWritableStreamSink.prototype.start = function (controller) { - var _this = this; - this._writableStreamController = controller; - this._underlyingWriter.closed - .then(function () { - _this._state = "closed" /* CLOSED */; - }) - .catch(function (reason) { return _this._finishErroring(reason); }); - }; - WrappingWritableStreamSink.prototype.write = function (chunk) { - var _this = this; - var writer = this._underlyingWriter; - // Detect past errors - if (writer.desiredSize === null) { - return writer.ready; - } - var writeRequest = writer.write(chunk); - // Detect future errors - writeRequest.catch(function (reason) { return _this._finishErroring(reason); }); - writer.ready.catch(function (reason) { return _this._startErroring(reason); }); - // Reject write when errored - var write = Promise.race([writeRequest, this._errorPromise]); - this._setPendingWrite(write); - return write; - }; - WrappingWritableStreamSink.prototype.close = function () { - var _this = this; - if (this._pendingWrite === undefined) { - return this._underlyingWriter.close(); - } - return this._finishPendingWrite().then(function () { return _this.close(); }); - }; - WrappingWritableStreamSink.prototype.abort = function (reason) { - if (this._state === "errored" /* ERRORED */) { - return undefined; - } - var writer = this._underlyingWriter; - return writer.abort(reason); - }; - WrappingWritableStreamSink.prototype._setPendingWrite = function (writePromise) { - var _this = this; - var pendingWrite; - var finishWrite = function () { - if (_this._pendingWrite === pendingWrite) { - _this._pendingWrite = undefined; - } - }; - this._pendingWrite = pendingWrite = writePromise.then(finishWrite, finishWrite); - }; - WrappingWritableStreamSink.prototype._finishPendingWrite = function () { - var _this = this; - if (this._pendingWrite === undefined) { - return Promise.resolve(); - } - var afterWrite = function () { return _this._finishPendingWrite(); }; - return this._pendingWrite.then(afterWrite, afterWrite); - }; - WrappingWritableStreamSink.prototype._startErroring = function (reason) { - var _this = this; - if (this._state === "writable" /* WRITABLE */) { - this._state = "erroring" /* ERRORING */; - this._storedError = reason; - var afterWrite = function () { return _this._finishErroring(reason); }; - if (this._pendingWrite === undefined) { - afterWrite(); - } - else { - this._finishPendingWrite().then(afterWrite, afterWrite); - } - this._writableStreamController.error(reason); - } - }; - WrappingWritableStreamSink.prototype._finishErroring = function (reason) { - if (this._state === "writable" /* WRITABLE */) { - this._startErroring(reason); - } - if (this._state === "erroring" /* ERRORING */) { - this._state = "errored" /* ERRORED */; - this._errorPromiseReject(this._storedError); - } - }; - return WrappingWritableStreamSink; -}()); - -function createTransformStreamWrapper(ctor) { - assert$1(isTransformStreamConstructor(ctor)); - return function (transform) { - if (transform.constructor === ctor) { - return transform; - } - var transformer = createWrappingTransformer(transform); - return new ctor(transformer); - }; -} -function createWrappingTransformer(transform) { - assert$1(isTransformStream(transform)); - var readable = transform.readable, writable = transform.writable; - assert$1(readable.locked === false); - assert$1(writable.locked === false); - var reader = readable.getReader(); - var writer; - try { - writer = writable.getWriter(); - } - catch (e) { - reader.releaseLock(); // do not leak reader - throw e; - } - return new WrappingTransformStreamTransformer(reader, writer); -} -var WrappingTransformStreamTransformer = /** @class */ (function () { - function WrappingTransformStreamTransformer(reader, writer) { - var _this = this; - this._transformStreamController = undefined; - this._onRead = function (result) { - if (result.done) { - return; - } - _this._transformStreamController.enqueue(result.value); - return _this._reader.read().then(_this._onRead); - }; - this._onError = function (reason) { - _this._flushReject(reason); - _this._transformStreamController.error(reason); - _this._reader.cancel(reason).catch(noop$1); - _this._writer.abort(reason).catch(noop$1); - }; - this._onTerminate = function () { - _this._flushResolve(); - _this._transformStreamController.terminate(); - var error = new TypeError('TransformStream terminated'); - _this._writer.abort(error).catch(noop$1); - }; - this._reader = reader; - this._writer = writer; - this._flushPromise = new Promise(function (resolve, reject) { - _this._flushResolve = resolve; - _this._flushReject = reject; - }); - } - WrappingTransformStreamTransformer.prototype.start = function (controller) { - this._transformStreamController = controller; - this._reader.read() - .then(this._onRead) - .then(this._onTerminate, this._onError); - var readerClosed = this._reader.closed; - if (readerClosed) { - readerClosed - .then(this._onTerminate, this._onError); - } - }; - WrappingTransformStreamTransformer.prototype.transform = function (chunk) { - return this._writer.write(chunk); - }; - WrappingTransformStreamTransformer.prototype.flush = function () { - var _this = this; - return this._writer.close() - .then(function () { return _this._flushPromise; }); - }; - return WrappingTransformStreamTransformer; -}()); - -var webStreamsAdapter = /*#__PURE__*/Object.freeze({ - __proto__: null, - createReadableStreamWrapper: createReadableStreamWrapper, - createTransformStreamWrapper: createTransformStreamWrapper, - createWrappingReadableSource: createWrappingReadableSource, - createWrappingTransformer: createWrappingTransformer, - createWrappingWritableSink: createWrappingWritableSink, - createWritableStreamWrapper: createWritableStreamWrapper -}); - -var bn = createCommonjsModule(function (module) { -(function (module, exports) { - - // Utils - function assert (val, msg) { - if (!val) throw new Error(msg || 'Assertion failed'); - } - - // Could use `inherits` module, but don't want to move from single file - // architecture yet. - function inherits (ctor, superCtor) { - ctor.super_ = superCtor; - var TempCtor = function () {}; - TempCtor.prototype = superCtor.prototype; - ctor.prototype = new TempCtor(); - ctor.prototype.constructor = ctor; - } - - // BN - - function BN (number, base, endian) { - if (BN.isBN(number)) { - return number; - } - - this.negative = 0; - this.words = null; - this.length = 0; - - // Reduction context - this.red = null; - - if (number !== null) { - if (base === 'le' || base === 'be') { - endian = base; - base = 10; - } - - this._init(number || 0, base || 10, endian || 'be'); - } - } - if (typeof module === 'object') { - module.exports = BN; - } else { - exports.BN = BN; - } - - BN.BN = BN; - BN.wordSize = 26; - - var Buffer; - try { - Buffer = buffer__default['default'].Buffer; - } catch (e) { - } - - BN.isBN = function isBN (num) { - if (num instanceof BN) { - return true; - } - - return num !== null && typeof num === 'object' && - num.constructor.wordSize === BN.wordSize && Array.isArray(num.words); - }; - - BN.max = function max (left, right) { - if (left.cmp(right) > 0) return left; - return right; - }; - - BN.min = function min (left, right) { - if (left.cmp(right) < 0) return left; - return right; - }; - - BN.prototype._init = function init (number, base, endian) { - if (typeof number === 'number') { - return this._initNumber(number, base, endian); - } - - if (typeof number === 'object') { - return this._initArray(number, base, endian); - } - - if (base === 'hex') { - base = 16; - } - assert(base === (base | 0) && base >= 2 && base <= 36); - - number = number.toString().replace(/\s+/g, ''); - var start = 0; - if (number[0] === '-') { - start++; - } - - if (base === 16) { - this._parseHex(number, start); - } else { - this._parseBase(number, base, start); - } - - if (number[0] === '-') { - this.negative = 1; - } - - this.strip(); - - if (endian !== 'le') return; - - this._initArray(this.toArray(), base, endian); - }; - - BN.prototype._initNumber = function _initNumber (number, base, endian) { - if (number < 0) { - this.negative = 1; - number = -number; - } - if (number < 0x4000000) { - this.words = [ number & 0x3ffffff ]; - this.length = 1; - } else if (number < 0x10000000000000) { - this.words = [ - number & 0x3ffffff, - (number / 0x4000000) & 0x3ffffff - ]; - this.length = 2; - } else { - assert(number < 0x20000000000000); // 2 ^ 53 (unsafe) - this.words = [ - number & 0x3ffffff, - (number / 0x4000000) & 0x3ffffff, - 1 - ]; - this.length = 3; - } - - if (endian !== 'le') return; - - // Reverse the bytes - this._initArray(this.toArray(), base, endian); - }; - - BN.prototype._initArray = function _initArray (number, base, endian) { - // Perhaps a Uint8Array - assert(typeof number.length === 'number'); - if (number.length <= 0) { - this.words = [ 0 ]; - this.length = 1; - return this; - } - - this.length = Math.ceil(number.length / 3); - this.words = new Array(this.length); - for (var i = 0; i < this.length; i++) { - this.words[i] = 0; - } - - var j, w; - var off = 0; - if (endian === 'be') { - for (i = number.length - 1, j = 0; i >= 0; i -= 3) { - w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16); - this.words[j] |= (w << off) & 0x3ffffff; - this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; - off += 24; - if (off >= 26) { - off -= 26; - j++; - } - } - } else if (endian === 'le') { - for (i = 0, j = 0; i < number.length; i += 3) { - w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16); - this.words[j] |= (w << off) & 0x3ffffff; - this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; - off += 24; - if (off >= 26) { - off -= 26; - j++; - } - } - } - return this.strip(); - }; - - function parseHex (str, start, end) { - var r = 0; - var len = Math.min(str.length, end); - for (var i = start; i < len; i++) { - var c = str.charCodeAt(i) - 48; - - r <<= 4; - - // 'a' - 'f' - if (c >= 49 && c <= 54) { - r |= c - 49 + 0xa; - - // 'A' - 'F' - } else if (c >= 17 && c <= 22) { - r |= c - 17 + 0xa; - - // '0' - '9' - } else { - r |= c & 0xf; - } - } - return r; - } - - BN.prototype._parseHex = function _parseHex (number, start) { - // Create possibly bigger array to ensure that it fits the number - this.length = Math.ceil((number.length - start) / 6); - this.words = new Array(this.length); - for (var i = 0; i < this.length; i++) { - this.words[i] = 0; - } - - var j, w; - // Scan 24-bit chunks and add them to the number - var off = 0; - for (i = number.length - 6, j = 0; i >= start; i -= 6) { - w = parseHex(number, i, i + 6); - this.words[j] |= (w << off) & 0x3ffffff; - // NOTE: `0x3fffff` is intentional here, 26bits max shift + 24bit hex limb - this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; - off += 24; - if (off >= 26) { - off -= 26; - j++; - } - } - if (i + 6 !== start) { - w = parseHex(number, start, i + 6); - this.words[j] |= (w << off) & 0x3ffffff; - this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; - } - this.strip(); - }; - - function parseBase (str, start, end, mul) { - var r = 0; - var len = Math.min(str.length, end); - for (var i = start; i < len; i++) { - var c = str.charCodeAt(i) - 48; - - r *= mul; - - // 'a' - if (c >= 49) { - r += c - 49 + 0xa; - - // 'A' - } else if (c >= 17) { - r += c - 17 + 0xa; - - // '0' - '9' - } else { - r += c; - } - } - return r; - } - - BN.prototype._parseBase = function _parseBase (number, base, start) { - // Initialize as zero - this.words = [ 0 ]; - this.length = 1; - - // Find length of limb in base - for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) { - limbLen++; - } - limbLen--; - limbPow = (limbPow / base) | 0; - - var total = number.length - start; - var mod = total % limbLen; - var end = Math.min(total, total - mod) + start; - - var word = 0; - for (var i = start; i < end; i += limbLen) { - word = parseBase(number, i, i + limbLen, base); - - this.imuln(limbPow); - if (this.words[0] + word < 0x4000000) { - this.words[0] += word; - } else { - this._iaddn(word); - } - } - - if (mod !== 0) { - var pow = 1; - word = parseBase(number, i, number.length, base); - - for (i = 0; i < mod; i++) { - pow *= base; - } - - this.imuln(pow); - if (this.words[0] + word < 0x4000000) { - this.words[0] += word; - } else { - this._iaddn(word); - } - } - }; - - BN.prototype.copy = function copy (dest) { - dest.words = new Array(this.length); - for (var i = 0; i < this.length; i++) { - dest.words[i] = this.words[i]; - } - dest.length = this.length; - dest.negative = this.negative; - dest.red = this.red; - }; - - BN.prototype.clone = function clone () { - var r = new BN(null); - this.copy(r); - return r; - }; - - BN.prototype._expand = function _expand (size) { - while (this.length < size) { - this.words[this.length++] = 0; - } - return this; - }; - - // Remove leading `0` from `this` - BN.prototype.strip = function strip () { - while (this.length > 1 && this.words[this.length - 1] === 0) { - this.length--; - } - return this._normSign(); - }; - - BN.prototype._normSign = function _normSign () { - // -0 = 0 - if (this.length === 1 && this.words[0] === 0) { - this.negative = 0; - } - return this; - }; - - BN.prototype.inspect = function inspect () { - return (this.red ? ''; - }; - - /* - - var zeros = []; - var groupSizes = []; - var groupBases = []; - - var s = ''; - var i = -1; - while (++i < BN.wordSize) { - zeros[i] = s; - s += '0'; - } - groupSizes[0] = 0; - groupSizes[1] = 0; - groupBases[0] = 0; - groupBases[1] = 0; - var base = 2 - 1; - while (++base < 36 + 1) { - var groupSize = 0; - var groupBase = 1; - while (groupBase < (1 << BN.wordSize) / base) { - groupBase *= base; - groupSize += 1; - } - groupSizes[base] = groupSize; - groupBases[base] = groupBase; - } - - */ - - var zeros = [ - '', - '0', - '00', - '000', - '0000', - '00000', - '000000', - '0000000', - '00000000', - '000000000', - '0000000000', - '00000000000', - '000000000000', - '0000000000000', - '00000000000000', - '000000000000000', - '0000000000000000', - '00000000000000000', - '000000000000000000', - '0000000000000000000', - '00000000000000000000', - '000000000000000000000', - '0000000000000000000000', - '00000000000000000000000', - '000000000000000000000000', - '0000000000000000000000000' - ]; - - var groupSizes = [ - 0, 0, - 25, 16, 12, 11, 10, 9, 8, - 8, 7, 7, 7, 7, 6, 6, - 6, 6, 6, 6, 6, 5, 5, - 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5 - ]; - - var groupBases = [ - 0, 0, - 33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216, - 43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625, - 16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632, - 6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149, - 24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176 - ]; - - BN.prototype.toString = function toString (base, padding) { - base = base || 10; - padding = padding | 0 || 1; - - var out; - if (base === 16 || base === 'hex') { - out = ''; - var off = 0; - var carry = 0; - for (var i = 0; i < this.length; i++) { - var w = this.words[i]; - var word = (((w << off) | carry) & 0xffffff).toString(16); - carry = (w >>> (24 - off)) & 0xffffff; - if (carry !== 0 || i !== this.length - 1) { - out = zeros[6 - word.length] + word + out; - } else { - out = word + out; - } - off += 2; - if (off >= 26) { - off -= 26; - i--; - } - } - if (carry !== 0) { - out = carry.toString(16) + out; - } - while (out.length % padding !== 0) { - out = '0' + out; - } - if (this.negative !== 0) { - out = '-' + out; - } - return out; - } - - if (base === (base | 0) && base >= 2 && base <= 36) { - // var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base)); - var groupSize = groupSizes[base]; - // var groupBase = Math.pow(base, groupSize); - var groupBase = groupBases[base]; - out = ''; - var c = this.clone(); - c.negative = 0; - while (!c.isZero()) { - var r = c.modn(groupBase).toString(base); - c = c.idivn(groupBase); - - if (!c.isZero()) { - out = zeros[groupSize - r.length] + r + out; - } else { - out = r + out; - } - } - if (this.isZero()) { - out = '0' + out; - } - while (out.length % padding !== 0) { - out = '0' + out; - } - if (this.negative !== 0) { - out = '-' + out; - } - return out; - } - - assert(false, 'Base should be between 2 and 36'); - }; - - BN.prototype.toNumber = function toNumber () { - var ret = this.words[0]; - if (this.length === 2) { - ret += this.words[1] * 0x4000000; - } else if (this.length === 3 && this.words[2] === 0x01) { - // NOTE: at this stage it is known that the top bit is set - ret += 0x10000000000000 + (this.words[1] * 0x4000000); - } else if (this.length > 2) { - assert(false, 'Number can only safely store up to 53 bits'); - } - return (this.negative !== 0) ? -ret : ret; - }; - - BN.prototype.toJSON = function toJSON () { - return this.toString(16); - }; - - BN.prototype.toBuffer = function toBuffer (endian, length) { - assert(typeof Buffer !== 'undefined'); - return this.toArrayLike(Buffer, endian, length); - }; - - BN.prototype.toArray = function toArray (endian, length) { - return this.toArrayLike(Array, endian, length); - }; - - BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) { - var byteLength = this.byteLength(); - var reqLength = length || Math.max(1, byteLength); - assert(byteLength <= reqLength, 'byte array longer than desired length'); - assert(reqLength > 0, 'Requested array length <= 0'); - - this.strip(); - var littleEndian = endian === 'le'; - var res = new ArrayType(reqLength); - - var b, i; - var q = this.clone(); - if (!littleEndian) { - // Assume big-endian - for (i = 0; i < reqLength - byteLength; i++) { - res[i] = 0; - } - - for (i = 0; !q.isZero(); i++) { - b = q.andln(0xff); - q.iushrn(8); - - res[reqLength - i - 1] = b; - } - } else { - for (i = 0; !q.isZero(); i++) { - b = q.andln(0xff); - q.iushrn(8); - - res[i] = b; - } - - for (; i < reqLength; i++) { - res[i] = 0; - } - } - - return res; - }; - - if (Math.clz32) { - BN.prototype._countBits = function _countBits (w) { - return 32 - Math.clz32(w); - }; - } else { - BN.prototype._countBits = function _countBits (w) { - var t = w; - var r = 0; - if (t >= 0x1000) { - r += 13; - t >>>= 13; - } - if (t >= 0x40) { - r += 7; - t >>>= 7; - } - if (t >= 0x8) { - r += 4; - t >>>= 4; - } - if (t >= 0x02) { - r += 2; - t >>>= 2; - } - return r + t; - }; - } - - BN.prototype._zeroBits = function _zeroBits (w) { - // Short-cut - if (w === 0) return 26; - - var t = w; - var r = 0; - if ((t & 0x1fff) === 0) { - r += 13; - t >>>= 13; - } - if ((t & 0x7f) === 0) { - r += 7; - t >>>= 7; - } - if ((t & 0xf) === 0) { - r += 4; - t >>>= 4; - } - if ((t & 0x3) === 0) { - r += 2; - t >>>= 2; - } - if ((t & 0x1) === 0) { - r++; - } - return r; - }; - - // Return number of used bits in a BN - BN.prototype.bitLength = function bitLength () { - var w = this.words[this.length - 1]; - var hi = this._countBits(w); - return (this.length - 1) * 26 + hi; - }; - - function toBitArray (num) { - var w = new Array(num.bitLength()); - - for (var bit = 0; bit < w.length; bit++) { - var off = (bit / 26) | 0; - var wbit = bit % 26; - - w[bit] = (num.words[off] & (1 << wbit)) >>> wbit; - } - - return w; - } - - // Number of trailing zero bits - BN.prototype.zeroBits = function zeroBits () { - if (this.isZero()) return 0; - - var r = 0; - for (var i = 0; i < this.length; i++) { - var b = this._zeroBits(this.words[i]); - r += b; - if (b !== 26) break; - } - return r; - }; - - BN.prototype.byteLength = function byteLength () { - return Math.ceil(this.bitLength() / 8); - }; - - BN.prototype.toTwos = function toTwos (width) { - if (this.negative !== 0) { - return this.abs().inotn(width).iaddn(1); - } - return this.clone(); - }; - - BN.prototype.fromTwos = function fromTwos (width) { - if (this.testn(width - 1)) { - return this.notn(width).iaddn(1).ineg(); - } - return this.clone(); - }; - - BN.prototype.isNeg = function isNeg () { - return this.negative !== 0; - }; - - // Return negative clone of `this` - BN.prototype.neg = function neg () { - return this.clone().ineg(); - }; - - BN.prototype.ineg = function ineg () { - if (!this.isZero()) { - this.negative ^= 1; - } - - return this; - }; - - // Or `num` with `this` in-place - BN.prototype.iuor = function iuor (num) { - while (this.length < num.length) { - this.words[this.length++] = 0; - } - - for (var i = 0; i < num.length; i++) { - this.words[i] = this.words[i] | num.words[i]; - } - - return this.strip(); - }; - - BN.prototype.ior = function ior (num) { - assert((this.negative | num.negative) === 0); - return this.iuor(num); - }; - - // Or `num` with `this` - BN.prototype.or = function or (num) { - if (this.length > num.length) return this.clone().ior(num); - return num.clone().ior(this); - }; - - BN.prototype.uor = function uor (num) { - if (this.length > num.length) return this.clone().iuor(num); - return num.clone().iuor(this); - }; - - // And `num` with `this` in-place - BN.prototype.iuand = function iuand (num) { - // b = min-length(num, this) - var b; - if (this.length > num.length) { - b = num; - } else { - b = this; - } - - for (var i = 0; i < b.length; i++) { - this.words[i] = this.words[i] & num.words[i]; - } - - this.length = b.length; - - return this.strip(); - }; - - BN.prototype.iand = function iand (num) { - assert((this.negative | num.negative) === 0); - return this.iuand(num); - }; - - // And `num` with `this` - BN.prototype.and = function and (num) { - if (this.length > num.length) return this.clone().iand(num); - return num.clone().iand(this); - }; - - BN.prototype.uand = function uand (num) { - if (this.length > num.length) return this.clone().iuand(num); - return num.clone().iuand(this); - }; - - // Xor `num` with `this` in-place - BN.prototype.iuxor = function iuxor (num) { - // a.length > b.length - var a; - var b; - if (this.length > num.length) { - a = this; - b = num; - } else { - a = num; - b = this; - } - - for (var i = 0; i < b.length; i++) { - this.words[i] = a.words[i] ^ b.words[i]; - } - - if (this !== a) { - for (; i < a.length; i++) { - this.words[i] = a.words[i]; - } - } - - this.length = a.length; - - return this.strip(); - }; - - BN.prototype.ixor = function ixor (num) { - assert((this.negative | num.negative) === 0); - return this.iuxor(num); - }; - - // Xor `num` with `this` - BN.prototype.xor = function xor (num) { - if (this.length > num.length) return this.clone().ixor(num); - return num.clone().ixor(this); - }; - - BN.prototype.uxor = function uxor (num) { - if (this.length > num.length) return this.clone().iuxor(num); - return num.clone().iuxor(this); - }; - - // Not ``this`` with ``width`` bitwidth - BN.prototype.inotn = function inotn (width) { - assert(typeof width === 'number' && width >= 0); - - var bytesNeeded = Math.ceil(width / 26) | 0; - var bitsLeft = width % 26; - - // Extend the buffer with leading zeroes - this._expand(bytesNeeded); - - if (bitsLeft > 0) { - bytesNeeded--; - } - - // Handle complete words - for (var i = 0; i < bytesNeeded; i++) { - this.words[i] = ~this.words[i] & 0x3ffffff; - } - - // Handle the residue - if (bitsLeft > 0) { - this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft)); - } - - // And remove leading zeroes - return this.strip(); - }; - - BN.prototype.notn = function notn (width) { - return this.clone().inotn(width); - }; - - // Set `bit` of `this` - BN.prototype.setn = function setn (bit, val) { - assert(typeof bit === 'number' && bit >= 0); - - var off = (bit / 26) | 0; - var wbit = bit % 26; - - this._expand(off + 1); - - if (val) { - this.words[off] = this.words[off] | (1 << wbit); - } else { - this.words[off] = this.words[off] & ~(1 << wbit); - } - - return this.strip(); - }; - - // Add `num` to `this` in-place - BN.prototype.iadd = function iadd (num) { - var r; - - // negative + positive - if (this.negative !== 0 && num.negative === 0) { - this.negative = 0; - r = this.isub(num); - this.negative ^= 1; - return this._normSign(); - - // positive + negative - } else if (this.negative === 0 && num.negative !== 0) { - num.negative = 0; - r = this.isub(num); - num.negative = 1; - return r._normSign(); - } - - // a.length > b.length - var a, b; - if (this.length > num.length) { - a = this; - b = num; - } else { - a = num; - b = this; - } - - var carry = 0; - for (var i = 0; i < b.length; i++) { - r = (a.words[i] | 0) + (b.words[i] | 0) + carry; - this.words[i] = r & 0x3ffffff; - carry = r >>> 26; - } - for (; carry !== 0 && i < a.length; i++) { - r = (a.words[i] | 0) + carry; - this.words[i] = r & 0x3ffffff; - carry = r >>> 26; - } - - this.length = a.length; - if (carry !== 0) { - this.words[this.length] = carry; - this.length++; - // Copy the rest of the words - } else if (a !== this) { - for (; i < a.length; i++) { - this.words[i] = a.words[i]; - } - } - - return this; - }; - - // Add `num` to `this` - BN.prototype.add = function add (num) { - var res; - if (num.negative !== 0 && this.negative === 0) { - num.negative = 0; - res = this.sub(num); - num.negative ^= 1; - return res; - } else if (num.negative === 0 && this.negative !== 0) { - this.negative = 0; - res = num.sub(this); - this.negative = 1; - return res; - } - - if (this.length > num.length) return this.clone().iadd(num); - - return num.clone().iadd(this); - }; - - // Subtract `num` from `this` in-place - BN.prototype.isub = function isub (num) { - // this - (-num) = this + num - if (num.negative !== 0) { - num.negative = 0; - var r = this.iadd(num); - num.negative = 1; - return r._normSign(); - - // -this - num = -(this + num) - } else if (this.negative !== 0) { - this.negative = 0; - this.iadd(num); - this.negative = 1; - return this._normSign(); - } - - // At this point both numbers are positive - var cmp = this.cmp(num); - - // Optimization - zeroify - if (cmp === 0) { - this.negative = 0; - this.length = 1; - this.words[0] = 0; - return this; - } - - // a > b - var a, b; - if (cmp > 0) { - a = this; - b = num; - } else { - a = num; - b = this; - } - - var carry = 0; - for (var i = 0; i < b.length; i++) { - r = (a.words[i] | 0) - (b.words[i] | 0) + carry; - carry = r >> 26; - this.words[i] = r & 0x3ffffff; - } - for (; carry !== 0 && i < a.length; i++) { - r = (a.words[i] | 0) + carry; - carry = r >> 26; - this.words[i] = r & 0x3ffffff; - } - - // Copy rest of the words - if (carry === 0 && i < a.length && a !== this) { - for (; i < a.length; i++) { - this.words[i] = a.words[i]; - } - } - - this.length = Math.max(this.length, i); - - if (a !== this) { - this.negative = 1; - } - - return this.strip(); - }; - - // Subtract `num` from `this` - BN.prototype.sub = function sub (num) { - return this.clone().isub(num); - }; - - function smallMulTo (self, num, out) { - out.negative = num.negative ^ self.negative; - var len = (self.length + num.length) | 0; - out.length = len; - len = (len - 1) | 0; - - // Peel one iteration (compiler can't do it, because of code complexity) - var a = self.words[0] | 0; - var b = num.words[0] | 0; - var r = a * b; - - var lo = r & 0x3ffffff; - var carry = (r / 0x4000000) | 0; - out.words[0] = lo; - - for (var k = 1; k < len; k++) { - // Sum all words with the same `i + j = k` and accumulate `ncarry`, - // note that ncarry could be >= 0x3ffffff - var ncarry = carry >>> 26; - var rword = carry & 0x3ffffff; - var maxJ = Math.min(k, num.length - 1); - for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { - var i = (k - j) | 0; - a = self.words[i] | 0; - b = num.words[j] | 0; - r = a * b + rword; - ncarry += (r / 0x4000000) | 0; - rword = r & 0x3ffffff; - } - out.words[k] = rword | 0; - carry = ncarry | 0; - } - if (carry !== 0) { - out.words[k] = carry | 0; - } else { - out.length--; - } - - return out.strip(); - } - - // TODO(indutny): it may be reasonable to omit it for users who don't need - // to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit - // multiplication (like elliptic secp256k1). - var comb10MulTo = function comb10MulTo (self, num, out) { - var a = self.words; - var b = num.words; - var o = out.words; - var c = 0; - var lo; - var mid; - var hi; - var a0 = a[0] | 0; - var al0 = a0 & 0x1fff; - var ah0 = a0 >>> 13; - var a1 = a[1] | 0; - var al1 = a1 & 0x1fff; - var ah1 = a1 >>> 13; - var a2 = a[2] | 0; - var al2 = a2 & 0x1fff; - var ah2 = a2 >>> 13; - var a3 = a[3] | 0; - var al3 = a3 & 0x1fff; - var ah3 = a3 >>> 13; - var a4 = a[4] | 0; - var al4 = a4 & 0x1fff; - var ah4 = a4 >>> 13; - var a5 = a[5] | 0; - var al5 = a5 & 0x1fff; - var ah5 = a5 >>> 13; - var a6 = a[6] | 0; - var al6 = a6 & 0x1fff; - var ah6 = a6 >>> 13; - var a7 = a[7] | 0; - var al7 = a7 & 0x1fff; - var ah7 = a7 >>> 13; - var a8 = a[8] | 0; - var al8 = a8 & 0x1fff; - var ah8 = a8 >>> 13; - var a9 = a[9] | 0; - var al9 = a9 & 0x1fff; - var ah9 = a9 >>> 13; - var b0 = b[0] | 0; - var bl0 = b0 & 0x1fff; - var bh0 = b0 >>> 13; - var b1 = b[1] | 0; - var bl1 = b1 & 0x1fff; - var bh1 = b1 >>> 13; - var b2 = b[2] | 0; - var bl2 = b2 & 0x1fff; - var bh2 = b2 >>> 13; - var b3 = b[3] | 0; - var bl3 = b3 & 0x1fff; - var bh3 = b3 >>> 13; - var b4 = b[4] | 0; - var bl4 = b4 & 0x1fff; - var bh4 = b4 >>> 13; - var b5 = b[5] | 0; - var bl5 = b5 & 0x1fff; - var bh5 = b5 >>> 13; - var b6 = b[6] | 0; - var bl6 = b6 & 0x1fff; - var bh6 = b6 >>> 13; - var b7 = b[7] | 0; - var bl7 = b7 & 0x1fff; - var bh7 = b7 >>> 13; - var b8 = b[8] | 0; - var bl8 = b8 & 0x1fff; - var bh8 = b8 >>> 13; - var b9 = b[9] | 0; - var bl9 = b9 & 0x1fff; - var bh9 = b9 >>> 13; - - out.negative = self.negative ^ num.negative; - out.length = 19; - /* k = 0 */ - lo = Math.imul(al0, bl0); - mid = Math.imul(al0, bh0); - mid = (mid + Math.imul(ah0, bl0)) | 0; - hi = Math.imul(ah0, bh0); - var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0; - w0 &= 0x3ffffff; - /* k = 1 */ - lo = Math.imul(al1, bl0); - mid = Math.imul(al1, bh0); - mid = (mid + Math.imul(ah1, bl0)) | 0; - hi = Math.imul(ah1, bh0); - lo = (lo + Math.imul(al0, bl1)) | 0; - mid = (mid + Math.imul(al0, bh1)) | 0; - mid = (mid + Math.imul(ah0, bl1)) | 0; - hi = (hi + Math.imul(ah0, bh1)) | 0; - var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0; - w1 &= 0x3ffffff; - /* k = 2 */ - lo = Math.imul(al2, bl0); - mid = Math.imul(al2, bh0); - mid = (mid + Math.imul(ah2, bl0)) | 0; - hi = Math.imul(ah2, bh0); - lo = (lo + Math.imul(al1, bl1)) | 0; - mid = (mid + Math.imul(al1, bh1)) | 0; - mid = (mid + Math.imul(ah1, bl1)) | 0; - hi = (hi + Math.imul(ah1, bh1)) | 0; - lo = (lo + Math.imul(al0, bl2)) | 0; - mid = (mid + Math.imul(al0, bh2)) | 0; - mid = (mid + Math.imul(ah0, bl2)) | 0; - hi = (hi + Math.imul(ah0, bh2)) | 0; - var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0; - w2 &= 0x3ffffff; - /* k = 3 */ - lo = Math.imul(al3, bl0); - mid = Math.imul(al3, bh0); - mid = (mid + Math.imul(ah3, bl0)) | 0; - hi = Math.imul(ah3, bh0); - lo = (lo + Math.imul(al2, bl1)) | 0; - mid = (mid + Math.imul(al2, bh1)) | 0; - mid = (mid + Math.imul(ah2, bl1)) | 0; - hi = (hi + Math.imul(ah2, bh1)) | 0; - lo = (lo + Math.imul(al1, bl2)) | 0; - mid = (mid + Math.imul(al1, bh2)) | 0; - mid = (mid + Math.imul(ah1, bl2)) | 0; - hi = (hi + Math.imul(ah1, bh2)) | 0; - lo = (lo + Math.imul(al0, bl3)) | 0; - mid = (mid + Math.imul(al0, bh3)) | 0; - mid = (mid + Math.imul(ah0, bl3)) | 0; - hi = (hi + Math.imul(ah0, bh3)) | 0; - var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0; - w3 &= 0x3ffffff; - /* k = 4 */ - lo = Math.imul(al4, bl0); - mid = Math.imul(al4, bh0); - mid = (mid + Math.imul(ah4, bl0)) | 0; - hi = Math.imul(ah4, bh0); - lo = (lo + Math.imul(al3, bl1)) | 0; - mid = (mid + Math.imul(al3, bh1)) | 0; - mid = (mid + Math.imul(ah3, bl1)) | 0; - hi = (hi + Math.imul(ah3, bh1)) | 0; - lo = (lo + Math.imul(al2, bl2)) | 0; - mid = (mid + Math.imul(al2, bh2)) | 0; - mid = (mid + Math.imul(ah2, bl2)) | 0; - hi = (hi + Math.imul(ah2, bh2)) | 0; - lo = (lo + Math.imul(al1, bl3)) | 0; - mid = (mid + Math.imul(al1, bh3)) | 0; - mid = (mid + Math.imul(ah1, bl3)) | 0; - hi = (hi + Math.imul(ah1, bh3)) | 0; - lo = (lo + Math.imul(al0, bl4)) | 0; - mid = (mid + Math.imul(al0, bh4)) | 0; - mid = (mid + Math.imul(ah0, bl4)) | 0; - hi = (hi + Math.imul(ah0, bh4)) | 0; - var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0; - w4 &= 0x3ffffff; - /* k = 5 */ - lo = Math.imul(al5, bl0); - mid = Math.imul(al5, bh0); - mid = (mid + Math.imul(ah5, bl0)) | 0; - hi = Math.imul(ah5, bh0); - lo = (lo + Math.imul(al4, bl1)) | 0; - mid = (mid + Math.imul(al4, bh1)) | 0; - mid = (mid + Math.imul(ah4, bl1)) | 0; - hi = (hi + Math.imul(ah4, bh1)) | 0; - lo = (lo + Math.imul(al3, bl2)) | 0; - mid = (mid + Math.imul(al3, bh2)) | 0; - mid = (mid + Math.imul(ah3, bl2)) | 0; - hi = (hi + Math.imul(ah3, bh2)) | 0; - lo = (lo + Math.imul(al2, bl3)) | 0; - mid = (mid + Math.imul(al2, bh3)) | 0; - mid = (mid + Math.imul(ah2, bl3)) | 0; - hi = (hi + Math.imul(ah2, bh3)) | 0; - lo = (lo + Math.imul(al1, bl4)) | 0; - mid = (mid + Math.imul(al1, bh4)) | 0; - mid = (mid + Math.imul(ah1, bl4)) | 0; - hi = (hi + Math.imul(ah1, bh4)) | 0; - lo = (lo + Math.imul(al0, bl5)) | 0; - mid = (mid + Math.imul(al0, bh5)) | 0; - mid = (mid + Math.imul(ah0, bl5)) | 0; - hi = (hi + Math.imul(ah0, bh5)) | 0; - var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0; - w5 &= 0x3ffffff; - /* k = 6 */ - lo = Math.imul(al6, bl0); - mid = Math.imul(al6, bh0); - mid = (mid + Math.imul(ah6, bl0)) | 0; - hi = Math.imul(ah6, bh0); - lo = (lo + Math.imul(al5, bl1)) | 0; - mid = (mid + Math.imul(al5, bh1)) | 0; - mid = (mid + Math.imul(ah5, bl1)) | 0; - hi = (hi + Math.imul(ah5, bh1)) | 0; - lo = (lo + Math.imul(al4, bl2)) | 0; - mid = (mid + Math.imul(al4, bh2)) | 0; - mid = (mid + Math.imul(ah4, bl2)) | 0; - hi = (hi + Math.imul(ah4, bh2)) | 0; - lo = (lo + Math.imul(al3, bl3)) | 0; - mid = (mid + Math.imul(al3, bh3)) | 0; - mid = (mid + Math.imul(ah3, bl3)) | 0; - hi = (hi + Math.imul(ah3, bh3)) | 0; - lo = (lo + Math.imul(al2, bl4)) | 0; - mid = (mid + Math.imul(al2, bh4)) | 0; - mid = (mid + Math.imul(ah2, bl4)) | 0; - hi = (hi + Math.imul(ah2, bh4)) | 0; - lo = (lo + Math.imul(al1, bl5)) | 0; - mid = (mid + Math.imul(al1, bh5)) | 0; - mid = (mid + Math.imul(ah1, bl5)) | 0; - hi = (hi + Math.imul(ah1, bh5)) | 0; - lo = (lo + Math.imul(al0, bl6)) | 0; - mid = (mid + Math.imul(al0, bh6)) | 0; - mid = (mid + Math.imul(ah0, bl6)) | 0; - hi = (hi + Math.imul(ah0, bh6)) | 0; - var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0; - w6 &= 0x3ffffff; - /* k = 7 */ - lo = Math.imul(al7, bl0); - mid = Math.imul(al7, bh0); - mid = (mid + Math.imul(ah7, bl0)) | 0; - hi = Math.imul(ah7, bh0); - lo = (lo + Math.imul(al6, bl1)) | 0; - mid = (mid + Math.imul(al6, bh1)) | 0; - mid = (mid + Math.imul(ah6, bl1)) | 0; - hi = (hi + Math.imul(ah6, bh1)) | 0; - lo = (lo + Math.imul(al5, bl2)) | 0; - mid = (mid + Math.imul(al5, bh2)) | 0; - mid = (mid + Math.imul(ah5, bl2)) | 0; - hi = (hi + Math.imul(ah5, bh2)) | 0; - lo = (lo + Math.imul(al4, bl3)) | 0; - mid = (mid + Math.imul(al4, bh3)) | 0; - mid = (mid + Math.imul(ah4, bl3)) | 0; - hi = (hi + Math.imul(ah4, bh3)) | 0; - lo = (lo + Math.imul(al3, bl4)) | 0; - mid = (mid + Math.imul(al3, bh4)) | 0; - mid = (mid + Math.imul(ah3, bl4)) | 0; - hi = (hi + Math.imul(ah3, bh4)) | 0; - lo = (lo + Math.imul(al2, bl5)) | 0; - mid = (mid + Math.imul(al2, bh5)) | 0; - mid = (mid + Math.imul(ah2, bl5)) | 0; - hi = (hi + Math.imul(ah2, bh5)) | 0; - lo = (lo + Math.imul(al1, bl6)) | 0; - mid = (mid + Math.imul(al1, bh6)) | 0; - mid = (mid + Math.imul(ah1, bl6)) | 0; - hi = (hi + Math.imul(ah1, bh6)) | 0; - lo = (lo + Math.imul(al0, bl7)) | 0; - mid = (mid + Math.imul(al0, bh7)) | 0; - mid = (mid + Math.imul(ah0, bl7)) | 0; - hi = (hi + Math.imul(ah0, bh7)) | 0; - var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0; - w7 &= 0x3ffffff; - /* k = 8 */ - lo = Math.imul(al8, bl0); - mid = Math.imul(al8, bh0); - mid = (mid + Math.imul(ah8, bl0)) | 0; - hi = Math.imul(ah8, bh0); - lo = (lo + Math.imul(al7, bl1)) | 0; - mid = (mid + Math.imul(al7, bh1)) | 0; - mid = (mid + Math.imul(ah7, bl1)) | 0; - hi = (hi + Math.imul(ah7, bh1)) | 0; - lo = (lo + Math.imul(al6, bl2)) | 0; - mid = (mid + Math.imul(al6, bh2)) | 0; - mid = (mid + Math.imul(ah6, bl2)) | 0; - hi = (hi + Math.imul(ah6, bh2)) | 0; - lo = (lo + Math.imul(al5, bl3)) | 0; - mid = (mid + Math.imul(al5, bh3)) | 0; - mid = (mid + Math.imul(ah5, bl3)) | 0; - hi = (hi + Math.imul(ah5, bh3)) | 0; - lo = (lo + Math.imul(al4, bl4)) | 0; - mid = (mid + Math.imul(al4, bh4)) | 0; - mid = (mid + Math.imul(ah4, bl4)) | 0; - hi = (hi + Math.imul(ah4, bh4)) | 0; - lo = (lo + Math.imul(al3, bl5)) | 0; - mid = (mid + Math.imul(al3, bh5)) | 0; - mid = (mid + Math.imul(ah3, bl5)) | 0; - hi = (hi + Math.imul(ah3, bh5)) | 0; - lo = (lo + Math.imul(al2, bl6)) | 0; - mid = (mid + Math.imul(al2, bh6)) | 0; - mid = (mid + Math.imul(ah2, bl6)) | 0; - hi = (hi + Math.imul(ah2, bh6)) | 0; - lo = (lo + Math.imul(al1, bl7)) | 0; - mid = (mid + Math.imul(al1, bh7)) | 0; - mid = (mid + Math.imul(ah1, bl7)) | 0; - hi = (hi + Math.imul(ah1, bh7)) | 0; - lo = (lo + Math.imul(al0, bl8)) | 0; - mid = (mid + Math.imul(al0, bh8)) | 0; - mid = (mid + Math.imul(ah0, bl8)) | 0; - hi = (hi + Math.imul(ah0, bh8)) | 0; - var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0; - w8 &= 0x3ffffff; - /* k = 9 */ - lo = Math.imul(al9, bl0); - mid = Math.imul(al9, bh0); - mid = (mid + Math.imul(ah9, bl0)) | 0; - hi = Math.imul(ah9, bh0); - lo = (lo + Math.imul(al8, bl1)) | 0; - mid = (mid + Math.imul(al8, bh1)) | 0; - mid = (mid + Math.imul(ah8, bl1)) | 0; - hi = (hi + Math.imul(ah8, bh1)) | 0; - lo = (lo + Math.imul(al7, bl2)) | 0; - mid = (mid + Math.imul(al7, bh2)) | 0; - mid = (mid + Math.imul(ah7, bl2)) | 0; - hi = (hi + Math.imul(ah7, bh2)) | 0; - lo = (lo + Math.imul(al6, bl3)) | 0; - mid = (mid + Math.imul(al6, bh3)) | 0; - mid = (mid + Math.imul(ah6, bl3)) | 0; - hi = (hi + Math.imul(ah6, bh3)) | 0; - lo = (lo + Math.imul(al5, bl4)) | 0; - mid = (mid + Math.imul(al5, bh4)) | 0; - mid = (mid + Math.imul(ah5, bl4)) | 0; - hi = (hi + Math.imul(ah5, bh4)) | 0; - lo = (lo + Math.imul(al4, bl5)) | 0; - mid = (mid + Math.imul(al4, bh5)) | 0; - mid = (mid + Math.imul(ah4, bl5)) | 0; - hi = (hi + Math.imul(ah4, bh5)) | 0; - lo = (lo + Math.imul(al3, bl6)) | 0; - mid = (mid + Math.imul(al3, bh6)) | 0; - mid = (mid + Math.imul(ah3, bl6)) | 0; - hi = (hi + Math.imul(ah3, bh6)) | 0; - lo = (lo + Math.imul(al2, bl7)) | 0; - mid = (mid + Math.imul(al2, bh7)) | 0; - mid = (mid + Math.imul(ah2, bl7)) | 0; - hi = (hi + Math.imul(ah2, bh7)) | 0; - lo = (lo + Math.imul(al1, bl8)) | 0; - mid = (mid + Math.imul(al1, bh8)) | 0; - mid = (mid + Math.imul(ah1, bl8)) | 0; - hi = (hi + Math.imul(ah1, bh8)) | 0; - lo = (lo + Math.imul(al0, bl9)) | 0; - mid = (mid + Math.imul(al0, bh9)) | 0; - mid = (mid + Math.imul(ah0, bl9)) | 0; - hi = (hi + Math.imul(ah0, bh9)) | 0; - var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0; - w9 &= 0x3ffffff; - /* k = 10 */ - lo = Math.imul(al9, bl1); - mid = Math.imul(al9, bh1); - mid = (mid + Math.imul(ah9, bl1)) | 0; - hi = Math.imul(ah9, bh1); - lo = (lo + Math.imul(al8, bl2)) | 0; - mid = (mid + Math.imul(al8, bh2)) | 0; - mid = (mid + Math.imul(ah8, bl2)) | 0; - hi = (hi + Math.imul(ah8, bh2)) | 0; - lo = (lo + Math.imul(al7, bl3)) | 0; - mid = (mid + Math.imul(al7, bh3)) | 0; - mid = (mid + Math.imul(ah7, bl3)) | 0; - hi = (hi + Math.imul(ah7, bh3)) | 0; - lo = (lo + Math.imul(al6, bl4)) | 0; - mid = (mid + Math.imul(al6, bh4)) | 0; - mid = (mid + Math.imul(ah6, bl4)) | 0; - hi = (hi + Math.imul(ah6, bh4)) | 0; - lo = (lo + Math.imul(al5, bl5)) | 0; - mid = (mid + Math.imul(al5, bh5)) | 0; - mid = (mid + Math.imul(ah5, bl5)) | 0; - hi = (hi + Math.imul(ah5, bh5)) | 0; - lo = (lo + Math.imul(al4, bl6)) | 0; - mid = (mid + Math.imul(al4, bh6)) | 0; - mid = (mid + Math.imul(ah4, bl6)) | 0; - hi = (hi + Math.imul(ah4, bh6)) | 0; - lo = (lo + Math.imul(al3, bl7)) | 0; - mid = (mid + Math.imul(al3, bh7)) | 0; - mid = (mid + Math.imul(ah3, bl7)) | 0; - hi = (hi + Math.imul(ah3, bh7)) | 0; - lo = (lo + Math.imul(al2, bl8)) | 0; - mid = (mid + Math.imul(al2, bh8)) | 0; - mid = (mid + Math.imul(ah2, bl8)) | 0; - hi = (hi + Math.imul(ah2, bh8)) | 0; - lo = (lo + Math.imul(al1, bl9)) | 0; - mid = (mid + Math.imul(al1, bh9)) | 0; - mid = (mid + Math.imul(ah1, bl9)) | 0; - hi = (hi + Math.imul(ah1, bh9)) | 0; - var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0; - w10 &= 0x3ffffff; - /* k = 11 */ - lo = Math.imul(al9, bl2); - mid = Math.imul(al9, bh2); - mid = (mid + Math.imul(ah9, bl2)) | 0; - hi = Math.imul(ah9, bh2); - lo = (lo + Math.imul(al8, bl3)) | 0; - mid = (mid + Math.imul(al8, bh3)) | 0; - mid = (mid + Math.imul(ah8, bl3)) | 0; - hi = (hi + Math.imul(ah8, bh3)) | 0; - lo = (lo + Math.imul(al7, bl4)) | 0; - mid = (mid + Math.imul(al7, bh4)) | 0; - mid = (mid + Math.imul(ah7, bl4)) | 0; - hi = (hi + Math.imul(ah7, bh4)) | 0; - lo = (lo + Math.imul(al6, bl5)) | 0; - mid = (mid + Math.imul(al6, bh5)) | 0; - mid = (mid + Math.imul(ah6, bl5)) | 0; - hi = (hi + Math.imul(ah6, bh5)) | 0; - lo = (lo + Math.imul(al5, bl6)) | 0; - mid = (mid + Math.imul(al5, bh6)) | 0; - mid = (mid + Math.imul(ah5, bl6)) | 0; - hi = (hi + Math.imul(ah5, bh6)) | 0; - lo = (lo + Math.imul(al4, bl7)) | 0; - mid = (mid + Math.imul(al4, bh7)) | 0; - mid = (mid + Math.imul(ah4, bl7)) | 0; - hi = (hi + Math.imul(ah4, bh7)) | 0; - lo = (lo + Math.imul(al3, bl8)) | 0; - mid = (mid + Math.imul(al3, bh8)) | 0; - mid = (mid + Math.imul(ah3, bl8)) | 0; - hi = (hi + Math.imul(ah3, bh8)) | 0; - lo = (lo + Math.imul(al2, bl9)) | 0; - mid = (mid + Math.imul(al2, bh9)) | 0; - mid = (mid + Math.imul(ah2, bl9)) | 0; - hi = (hi + Math.imul(ah2, bh9)) | 0; - var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0; - w11 &= 0x3ffffff; - /* k = 12 */ - lo = Math.imul(al9, bl3); - mid = Math.imul(al9, bh3); - mid = (mid + Math.imul(ah9, bl3)) | 0; - hi = Math.imul(ah9, bh3); - lo = (lo + Math.imul(al8, bl4)) | 0; - mid = (mid + Math.imul(al8, bh4)) | 0; - mid = (mid + Math.imul(ah8, bl4)) | 0; - hi = (hi + Math.imul(ah8, bh4)) | 0; - lo = (lo + Math.imul(al7, bl5)) | 0; - mid = (mid + Math.imul(al7, bh5)) | 0; - mid = (mid + Math.imul(ah7, bl5)) | 0; - hi = (hi + Math.imul(ah7, bh5)) | 0; - lo = (lo + Math.imul(al6, bl6)) | 0; - mid = (mid + Math.imul(al6, bh6)) | 0; - mid = (mid + Math.imul(ah6, bl6)) | 0; - hi = (hi + Math.imul(ah6, bh6)) | 0; - lo = (lo + Math.imul(al5, bl7)) | 0; - mid = (mid + Math.imul(al5, bh7)) | 0; - mid = (mid + Math.imul(ah5, bl7)) | 0; - hi = (hi + Math.imul(ah5, bh7)) | 0; - lo = (lo + Math.imul(al4, bl8)) | 0; - mid = (mid + Math.imul(al4, bh8)) | 0; - mid = (mid + Math.imul(ah4, bl8)) | 0; - hi = (hi + Math.imul(ah4, bh8)) | 0; - lo = (lo + Math.imul(al3, bl9)) | 0; - mid = (mid + Math.imul(al3, bh9)) | 0; - mid = (mid + Math.imul(ah3, bl9)) | 0; - hi = (hi + Math.imul(ah3, bh9)) | 0; - var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0; - w12 &= 0x3ffffff; - /* k = 13 */ - lo = Math.imul(al9, bl4); - mid = Math.imul(al9, bh4); - mid = (mid + Math.imul(ah9, bl4)) | 0; - hi = Math.imul(ah9, bh4); - lo = (lo + Math.imul(al8, bl5)) | 0; - mid = (mid + Math.imul(al8, bh5)) | 0; - mid = (mid + Math.imul(ah8, bl5)) | 0; - hi = (hi + Math.imul(ah8, bh5)) | 0; - lo = (lo + Math.imul(al7, bl6)) | 0; - mid = (mid + Math.imul(al7, bh6)) | 0; - mid = (mid + Math.imul(ah7, bl6)) | 0; - hi = (hi + Math.imul(ah7, bh6)) | 0; - lo = (lo + Math.imul(al6, bl7)) | 0; - mid = (mid + Math.imul(al6, bh7)) | 0; - mid = (mid + Math.imul(ah6, bl7)) | 0; - hi = (hi + Math.imul(ah6, bh7)) | 0; - lo = (lo + Math.imul(al5, bl8)) | 0; - mid = (mid + Math.imul(al5, bh8)) | 0; - mid = (mid + Math.imul(ah5, bl8)) | 0; - hi = (hi + Math.imul(ah5, bh8)) | 0; - lo = (lo + Math.imul(al4, bl9)) | 0; - mid = (mid + Math.imul(al4, bh9)) | 0; - mid = (mid + Math.imul(ah4, bl9)) | 0; - hi = (hi + Math.imul(ah4, bh9)) | 0; - var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0; - w13 &= 0x3ffffff; - /* k = 14 */ - lo = Math.imul(al9, bl5); - mid = Math.imul(al9, bh5); - mid = (mid + Math.imul(ah9, bl5)) | 0; - hi = Math.imul(ah9, bh5); - lo = (lo + Math.imul(al8, bl6)) | 0; - mid = (mid + Math.imul(al8, bh6)) | 0; - mid = (mid + Math.imul(ah8, bl6)) | 0; - hi = (hi + Math.imul(ah8, bh6)) | 0; - lo = (lo + Math.imul(al7, bl7)) | 0; - mid = (mid + Math.imul(al7, bh7)) | 0; - mid = (mid + Math.imul(ah7, bl7)) | 0; - hi = (hi + Math.imul(ah7, bh7)) | 0; - lo = (lo + Math.imul(al6, bl8)) | 0; - mid = (mid + Math.imul(al6, bh8)) | 0; - mid = (mid + Math.imul(ah6, bl8)) | 0; - hi = (hi + Math.imul(ah6, bh8)) | 0; - lo = (lo + Math.imul(al5, bl9)) | 0; - mid = (mid + Math.imul(al5, bh9)) | 0; - mid = (mid + Math.imul(ah5, bl9)) | 0; - hi = (hi + Math.imul(ah5, bh9)) | 0; - var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0; - w14 &= 0x3ffffff; - /* k = 15 */ - lo = Math.imul(al9, bl6); - mid = Math.imul(al9, bh6); - mid = (mid + Math.imul(ah9, bl6)) | 0; - hi = Math.imul(ah9, bh6); - lo = (lo + Math.imul(al8, bl7)) | 0; - mid = (mid + Math.imul(al8, bh7)) | 0; - mid = (mid + Math.imul(ah8, bl7)) | 0; - hi = (hi + Math.imul(ah8, bh7)) | 0; - lo = (lo + Math.imul(al7, bl8)) | 0; - mid = (mid + Math.imul(al7, bh8)) | 0; - mid = (mid + Math.imul(ah7, bl8)) | 0; - hi = (hi + Math.imul(ah7, bh8)) | 0; - lo = (lo + Math.imul(al6, bl9)) | 0; - mid = (mid + Math.imul(al6, bh9)) | 0; - mid = (mid + Math.imul(ah6, bl9)) | 0; - hi = (hi + Math.imul(ah6, bh9)) | 0; - var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0; - w15 &= 0x3ffffff; - /* k = 16 */ - lo = Math.imul(al9, bl7); - mid = Math.imul(al9, bh7); - mid = (mid + Math.imul(ah9, bl7)) | 0; - hi = Math.imul(ah9, bh7); - lo = (lo + Math.imul(al8, bl8)) | 0; - mid = (mid + Math.imul(al8, bh8)) | 0; - mid = (mid + Math.imul(ah8, bl8)) | 0; - hi = (hi + Math.imul(ah8, bh8)) | 0; - lo = (lo + Math.imul(al7, bl9)) | 0; - mid = (mid + Math.imul(al7, bh9)) | 0; - mid = (mid + Math.imul(ah7, bl9)) | 0; - hi = (hi + Math.imul(ah7, bh9)) | 0; - var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0; - w16 &= 0x3ffffff; - /* k = 17 */ - lo = Math.imul(al9, bl8); - mid = Math.imul(al9, bh8); - mid = (mid + Math.imul(ah9, bl8)) | 0; - hi = Math.imul(ah9, bh8); - lo = (lo + Math.imul(al8, bl9)) | 0; - mid = (mid + Math.imul(al8, bh9)) | 0; - mid = (mid + Math.imul(ah8, bl9)) | 0; - hi = (hi + Math.imul(ah8, bh9)) | 0; - var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0; - w17 &= 0x3ffffff; - /* k = 18 */ - lo = Math.imul(al9, bl9); - mid = Math.imul(al9, bh9); - mid = (mid + Math.imul(ah9, bl9)) | 0; - hi = Math.imul(ah9, bh9); - var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0; - w18 &= 0x3ffffff; - o[0] = w0; - o[1] = w1; - o[2] = w2; - o[3] = w3; - o[4] = w4; - o[5] = w5; - o[6] = w6; - o[7] = w7; - o[8] = w8; - o[9] = w9; - o[10] = w10; - o[11] = w11; - o[12] = w12; - o[13] = w13; - o[14] = w14; - o[15] = w15; - o[16] = w16; - o[17] = w17; - o[18] = w18; - if (c !== 0) { - o[19] = c; - out.length++; - } - return out; - }; - - // Polyfill comb - if (!Math.imul) { - comb10MulTo = smallMulTo; - } - - function bigMulTo (self, num, out) { - out.negative = num.negative ^ self.negative; - out.length = self.length + num.length; - - var carry = 0; - var hncarry = 0; - for (var k = 0; k < out.length - 1; k++) { - // Sum all words with the same `i + j = k` and accumulate `ncarry`, - // note that ncarry could be >= 0x3ffffff - var ncarry = hncarry; - hncarry = 0; - var rword = carry & 0x3ffffff; - var maxJ = Math.min(k, num.length - 1); - for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { - var i = k - j; - var a = self.words[i] | 0; - var b = num.words[j] | 0; - var r = a * b; - - var lo = r & 0x3ffffff; - ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0; - lo = (lo + rword) | 0; - rword = lo & 0x3ffffff; - ncarry = (ncarry + (lo >>> 26)) | 0; - - hncarry += ncarry >>> 26; - ncarry &= 0x3ffffff; - } - out.words[k] = rword; - carry = ncarry; - ncarry = hncarry; - } - if (carry !== 0) { - out.words[k] = carry; - } else { - out.length--; - } - - return out.strip(); - } - - function jumboMulTo (self, num, out) { - var fftm = new FFTM(); - return fftm.mulp(self, num, out); - } - - BN.prototype.mulTo = function mulTo (num, out) { - var res; - var len = this.length + num.length; - if (this.length === 10 && num.length === 10) { - res = comb10MulTo(this, num, out); - } else if (len < 63) { - res = smallMulTo(this, num, out); - } else if (len < 1024) { - res = bigMulTo(this, num, out); - } else { - res = jumboMulTo(this, num, out); - } - - return res; - }; - - // Cooley-Tukey algorithm for FFT - // slightly revisited to rely on looping instead of recursion - - function FFTM (x, y) { - this.x = x; - this.y = y; - } - - FFTM.prototype.makeRBT = function makeRBT (N) { - var t = new Array(N); - var l = BN.prototype._countBits(N) - 1; - for (var i = 0; i < N; i++) { - t[i] = this.revBin(i, l, N); - } - - return t; - }; - - // Returns binary-reversed representation of `x` - FFTM.prototype.revBin = function revBin (x, l, N) { - if (x === 0 || x === N - 1) return x; - - var rb = 0; - for (var i = 0; i < l; i++) { - rb |= (x & 1) << (l - i - 1); - x >>= 1; - } - - return rb; - }; - - // Performs "tweedling" phase, therefore 'emulating' - // behaviour of the recursive algorithm - FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) { - for (var i = 0; i < N; i++) { - rtws[i] = rws[rbt[i]]; - itws[i] = iws[rbt[i]]; - } - }; - - FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) { - this.permute(rbt, rws, iws, rtws, itws, N); - - for (var s = 1; s < N; s <<= 1) { - var l = s << 1; - - var rtwdf = Math.cos(2 * Math.PI / l); - var itwdf = Math.sin(2 * Math.PI / l); - - for (var p = 0; p < N; p += l) { - var rtwdf_ = rtwdf; - var itwdf_ = itwdf; - - for (var j = 0; j < s; j++) { - var re = rtws[p + j]; - var ie = itws[p + j]; - - var ro = rtws[p + j + s]; - var io = itws[p + j + s]; - - var rx = rtwdf_ * ro - itwdf_ * io; - - io = rtwdf_ * io + itwdf_ * ro; - ro = rx; - - rtws[p + j] = re + ro; - itws[p + j] = ie + io; - - rtws[p + j + s] = re - ro; - itws[p + j + s] = ie - io; - - /* jshint maxdepth : false */ - if (j !== l) { - rx = rtwdf * rtwdf_ - itwdf * itwdf_; - - itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_; - rtwdf_ = rx; - } - } - } - } - }; - - FFTM.prototype.guessLen13b = function guessLen13b (n, m) { - var N = Math.max(m, n) | 1; - var odd = N & 1; - var i = 0; - for (N = N / 2 | 0; N; N = N >>> 1) { - i++; - } - - return 1 << i + 1 + odd; - }; - - FFTM.prototype.conjugate = function conjugate (rws, iws, N) { - if (N <= 1) return; - - for (var i = 0; i < N / 2; i++) { - var t = rws[i]; - - rws[i] = rws[N - i - 1]; - rws[N - i - 1] = t; - - t = iws[i]; - - iws[i] = -iws[N - i - 1]; - iws[N - i - 1] = -t; - } - }; - - FFTM.prototype.normalize13b = function normalize13b (ws, N) { - var carry = 0; - for (var i = 0; i < N / 2; i++) { - var w = Math.round(ws[2 * i + 1] / N) * 0x2000 + - Math.round(ws[2 * i] / N) + - carry; - - ws[i] = w & 0x3ffffff; - - if (w < 0x4000000) { - carry = 0; - } else { - carry = w / 0x4000000 | 0; - } - } - - return ws; - }; - - FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) { - var carry = 0; - for (var i = 0; i < len; i++) { - carry = carry + (ws[i] | 0); - - rws[2 * i] = carry & 0x1fff; carry = carry >>> 13; - rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13; - } - - // Pad with zeroes - for (i = 2 * len; i < N; ++i) { - rws[i] = 0; - } - - assert(carry === 0); - assert((carry & ~0x1fff) === 0); - }; - - FFTM.prototype.stub = function stub (N) { - var ph = new Array(N); - for (var i = 0; i < N; i++) { - ph[i] = 0; - } - - return ph; - }; - - FFTM.prototype.mulp = function mulp (x, y, out) { - var N = 2 * this.guessLen13b(x.length, y.length); - - var rbt = this.makeRBT(N); - - var _ = this.stub(N); - - var rws = new Array(N); - var rwst = new Array(N); - var iwst = new Array(N); - - var nrws = new Array(N); - var nrwst = new Array(N); - var niwst = new Array(N); - - var rmws = out.words; - rmws.length = N; - - this.convert13b(x.words, x.length, rws, N); - this.convert13b(y.words, y.length, nrws, N); - - this.transform(rws, _, rwst, iwst, N, rbt); - this.transform(nrws, _, nrwst, niwst, N, rbt); - - for (var i = 0; i < N; i++) { - var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i]; - iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i]; - rwst[i] = rx; - } - - this.conjugate(rwst, iwst, N); - this.transform(rwst, iwst, rmws, _, N, rbt); - this.conjugate(rmws, _, N); - this.normalize13b(rmws, N); - - out.negative = x.negative ^ y.negative; - out.length = x.length + y.length; - return out.strip(); - }; - - // Multiply `this` by `num` - BN.prototype.mul = function mul (num) { - var out = new BN(null); - out.words = new Array(this.length + num.length); - return this.mulTo(num, out); - }; - - // Multiply employing FFT - BN.prototype.mulf = function mulf (num) { - var out = new BN(null); - out.words = new Array(this.length + num.length); - return jumboMulTo(this, num, out); - }; - - // In-place Multiplication - BN.prototype.imul = function imul (num) { - return this.clone().mulTo(num, this); - }; - - BN.prototype.imuln = function imuln (num) { - assert(typeof num === 'number'); - assert(num < 0x4000000); - - // Carry - var carry = 0; - for (var i = 0; i < this.length; i++) { - var w = (this.words[i] | 0) * num; - var lo = (w & 0x3ffffff) + (carry & 0x3ffffff); - carry >>= 26; - carry += (w / 0x4000000) | 0; - // NOTE: lo is 27bit maximum - carry += lo >>> 26; - this.words[i] = lo & 0x3ffffff; - } - - if (carry !== 0) { - this.words[i] = carry; - this.length++; - } - - return this; - }; - - BN.prototype.muln = function muln (num) { - return this.clone().imuln(num); - }; - - // `this` * `this` - BN.prototype.sqr = function sqr () { - return this.mul(this); - }; - - // `this` * `this` in-place - BN.prototype.isqr = function isqr () { - return this.imul(this.clone()); - }; - - // Math.pow(`this`, `num`) - BN.prototype.pow = function pow (num) { - var w = toBitArray(num); - if (w.length === 0) return new BN(1); - - // Skip leading zeroes - var res = this; - for (var i = 0; i < w.length; i++, res = res.sqr()) { - if (w[i] !== 0) break; - } - - if (++i < w.length) { - for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) { - if (w[i] === 0) continue; - - res = res.mul(q); - } - } - - return res; - }; - - // Shift-left in-place - BN.prototype.iushln = function iushln (bits) { - assert(typeof bits === 'number' && bits >= 0); - var r = bits % 26; - var s = (bits - r) / 26; - var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r); - var i; - - if (r !== 0) { - var carry = 0; - - for (i = 0; i < this.length; i++) { - var newCarry = this.words[i] & carryMask; - var c = ((this.words[i] | 0) - newCarry) << r; - this.words[i] = c | carry; - carry = newCarry >>> (26 - r); - } - - if (carry) { - this.words[i] = carry; - this.length++; - } - } - - if (s !== 0) { - for (i = this.length - 1; i >= 0; i--) { - this.words[i + s] = this.words[i]; - } - - for (i = 0; i < s; i++) { - this.words[i] = 0; - } - - this.length += s; - } - - return this.strip(); - }; - - BN.prototype.ishln = function ishln (bits) { - // TODO(indutny): implement me - assert(this.negative === 0); - return this.iushln(bits); - }; - - // Shift-right in-place - // NOTE: `hint` is a lowest bit before trailing zeroes - // NOTE: if `extended` is present - it will be filled with destroyed bits - BN.prototype.iushrn = function iushrn (bits, hint, extended) { - assert(typeof bits === 'number' && bits >= 0); - var h; - if (hint) { - h = (hint - (hint % 26)) / 26; - } else { - h = 0; - } - - var r = bits % 26; - var s = Math.min((bits - r) / 26, this.length); - var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); - var maskedWords = extended; - - h -= s; - h = Math.max(0, h); - - // Extended mode, copy masked part - if (maskedWords) { - for (var i = 0; i < s; i++) { - maskedWords.words[i] = this.words[i]; - } - maskedWords.length = s; - } - - if (s === 0) ; else if (this.length > s) { - this.length -= s; - for (i = 0; i < this.length; i++) { - this.words[i] = this.words[i + s]; - } - } else { - this.words[0] = 0; - this.length = 1; - } - - var carry = 0; - for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) { - var word = this.words[i] | 0; - this.words[i] = (carry << (26 - r)) | (word >>> r); - carry = word & mask; - } - - // Push carried bits as a mask - if (maskedWords && carry !== 0) { - maskedWords.words[maskedWords.length++] = carry; - } - - if (this.length === 0) { - this.words[0] = 0; - this.length = 1; - } - - return this.strip(); - }; - - BN.prototype.ishrn = function ishrn (bits, hint, extended) { - // TODO(indutny): implement me - assert(this.negative === 0); - return this.iushrn(bits, hint, extended); - }; - - // Shift-left - BN.prototype.shln = function shln (bits) { - return this.clone().ishln(bits); - }; - - BN.prototype.ushln = function ushln (bits) { - return this.clone().iushln(bits); - }; - - // Shift-right - BN.prototype.shrn = function shrn (bits) { - return this.clone().ishrn(bits); - }; - - BN.prototype.ushrn = function ushrn (bits) { - return this.clone().iushrn(bits); - }; - - // Test if n bit is set - BN.prototype.testn = function testn (bit) { - assert(typeof bit === 'number' && bit >= 0); - var r = bit % 26; - var s = (bit - r) / 26; - var q = 1 << r; - - // Fast case: bit is much higher than all existing words - if (this.length <= s) return false; - - // Check bit and return - var w = this.words[s]; - - return !!(w & q); - }; - - // Return only lowers bits of number (in-place) - BN.prototype.imaskn = function imaskn (bits) { - assert(typeof bits === 'number' && bits >= 0); - var r = bits % 26; - var s = (bits - r) / 26; - - assert(this.negative === 0, 'imaskn works only with positive numbers'); - - if (this.length <= s) { - return this; - } - - if (r !== 0) { - s++; - } - this.length = Math.min(s, this.length); - - if (r !== 0) { - var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); - this.words[this.length - 1] &= mask; - } - - return this.strip(); - }; - - // Return only lowers bits of number - BN.prototype.maskn = function maskn (bits) { - return this.clone().imaskn(bits); - }; - - // Add plain number `num` to `this` - BN.prototype.iaddn = function iaddn (num) { - assert(typeof num === 'number'); - assert(num < 0x4000000); - if (num < 0) return this.isubn(-num); - - // Possible sign change - if (this.negative !== 0) { - if (this.length === 1 && (this.words[0] | 0) < num) { - this.words[0] = num - (this.words[0] | 0); - this.negative = 0; - return this; - } - - this.negative = 0; - this.isubn(num); - this.negative = 1; - return this; - } - - // Add without checks - return this._iaddn(num); - }; - - BN.prototype._iaddn = function _iaddn (num) { - this.words[0] += num; - - // Carry - for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) { - this.words[i] -= 0x4000000; - if (i === this.length - 1) { - this.words[i + 1] = 1; - } else { - this.words[i + 1]++; - } - } - this.length = Math.max(this.length, i + 1); - - return this; - }; - - // Subtract plain number `num` from `this` - BN.prototype.isubn = function isubn (num) { - assert(typeof num === 'number'); - assert(num < 0x4000000); - if (num < 0) return this.iaddn(-num); - - if (this.negative !== 0) { - this.negative = 0; - this.iaddn(num); - this.negative = 1; - return this; - } - - this.words[0] -= num; - - if (this.length === 1 && this.words[0] < 0) { - this.words[0] = -this.words[0]; - this.negative = 1; - } else { - // Carry - for (var i = 0; i < this.length && this.words[i] < 0; i++) { - this.words[i] += 0x4000000; - this.words[i + 1] -= 1; - } - } - - return this.strip(); - }; - - BN.prototype.addn = function addn (num) { - return this.clone().iaddn(num); - }; - - BN.prototype.subn = function subn (num) { - return this.clone().isubn(num); - }; - - BN.prototype.iabs = function iabs () { - this.negative = 0; - - return this; - }; - - BN.prototype.abs = function abs () { - return this.clone().iabs(); - }; - - BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) { - var len = num.length + shift; - var i; - - this._expand(len); - - var w; - var carry = 0; - for (i = 0; i < num.length; i++) { - w = (this.words[i + shift] | 0) + carry; - var right = (num.words[i] | 0) * mul; - w -= right & 0x3ffffff; - carry = (w >> 26) - ((right / 0x4000000) | 0); - this.words[i + shift] = w & 0x3ffffff; - } - for (; i < this.length - shift; i++) { - w = (this.words[i + shift] | 0) + carry; - carry = w >> 26; - this.words[i + shift] = w & 0x3ffffff; - } - - if (carry === 0) return this.strip(); - - // Subtraction overflow - assert(carry === -1); - carry = 0; - for (i = 0; i < this.length; i++) { - w = -(this.words[i] | 0) + carry; - carry = w >> 26; - this.words[i] = w & 0x3ffffff; - } - this.negative = 1; - - return this.strip(); - }; - - BN.prototype._wordDiv = function _wordDiv (num, mode) { - var shift = this.length - num.length; - - var a = this.clone(); - var b = num; - - // Normalize - var bhi = b.words[b.length - 1] | 0; - var bhiBits = this._countBits(bhi); - shift = 26 - bhiBits; - if (shift !== 0) { - b = b.ushln(shift); - a.iushln(shift); - bhi = b.words[b.length - 1] | 0; - } - - // Initialize quotient - var m = a.length - b.length; - var q; - - if (mode !== 'mod') { - q = new BN(null); - q.length = m + 1; - q.words = new Array(q.length); - for (var i = 0; i < q.length; i++) { - q.words[i] = 0; - } - } - - var diff = a.clone()._ishlnsubmul(b, 1, m); - if (diff.negative === 0) { - a = diff; - if (q) { - q.words[m] = 1; - } - } - - for (var j = m - 1; j >= 0; j--) { - var qj = (a.words[b.length + j] | 0) * 0x4000000 + - (a.words[b.length + j - 1] | 0); - - // NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max - // (0x7ffffff) - qj = Math.min((qj / bhi) | 0, 0x3ffffff); - - a._ishlnsubmul(b, qj, j); - while (a.negative !== 0) { - qj--; - a.negative = 0; - a._ishlnsubmul(b, 1, j); - if (!a.isZero()) { - a.negative ^= 1; - } - } - if (q) { - q.words[j] = qj; - } - } - if (q) { - q.strip(); - } - a.strip(); - - // Denormalize - if (mode !== 'div' && shift !== 0) { - a.iushrn(shift); - } - - return { - div: q || null, - mod: a - }; - }; - - // NOTE: 1) `mode` can be set to `mod` to request mod only, - // to `div` to request div only, or be absent to - // request both div & mod - // 2) `positive` is true if unsigned mod is requested - BN.prototype.divmod = function divmod (num, mode, positive) { - assert(!num.isZero()); - - if (this.isZero()) { - return { - div: new BN(0), - mod: new BN(0) - }; - } - - var div, mod, res; - if (this.negative !== 0 && num.negative === 0) { - res = this.neg().divmod(num, mode); - - if (mode !== 'mod') { - div = res.div.neg(); - } - - if (mode !== 'div') { - mod = res.mod.neg(); - if (positive && mod.negative !== 0) { - mod.iadd(num); - } - } - - return { - div: div, - mod: mod - }; - } - - if (this.negative === 0 && num.negative !== 0) { - res = this.divmod(num.neg(), mode); - - if (mode !== 'mod') { - div = res.div.neg(); - } - - return { - div: div, - mod: res.mod - }; - } - - if ((this.negative & num.negative) !== 0) { - res = this.neg().divmod(num.neg(), mode); - - if (mode !== 'div') { - mod = res.mod.neg(); - if (positive && mod.negative !== 0) { - mod.isub(num); - } - } - - return { - div: res.div, - mod: mod - }; - } - - // Both numbers are positive at this point - - // Strip both numbers to approximate shift value - if (num.length > this.length || this.cmp(num) < 0) { - return { - div: new BN(0), - mod: this - }; - } - - // Very short reduction - if (num.length === 1) { - if (mode === 'div') { - return { - div: this.divn(num.words[0]), - mod: null - }; - } - - if (mode === 'mod') { - return { - div: null, - mod: new BN(this.modn(num.words[0])) - }; - } - - return { - div: this.divn(num.words[0]), - mod: new BN(this.modn(num.words[0])) - }; - } - - return this._wordDiv(num, mode); - }; - - // Find `this` / `num` - BN.prototype.div = function div (num) { - return this.divmod(num, 'div', false).div; - }; - - // Find `this` % `num` - BN.prototype.mod = function mod (num) { - return this.divmod(num, 'mod', false).mod; - }; - - BN.prototype.umod = function umod (num) { - return this.divmod(num, 'mod', true).mod; - }; - - // Find Round(`this` / `num`) - BN.prototype.divRound = function divRound (num) { - var dm = this.divmod(num); - - // Fast case - exact division - if (dm.mod.isZero()) return dm.div; - - var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod; - - var half = num.ushrn(1); - var r2 = num.andln(1); - var cmp = mod.cmp(half); - - // Round down - if (cmp < 0 || r2 === 1 && cmp === 0) return dm.div; - - // Round up - return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1); - }; - - BN.prototype.modn = function modn (num) { - assert(num <= 0x3ffffff); - var p = (1 << 26) % num; - - var acc = 0; - for (var i = this.length - 1; i >= 0; i--) { - acc = (p * acc + (this.words[i] | 0)) % num; - } - - return acc; - }; - - // In-place division by number - BN.prototype.idivn = function idivn (num) { - assert(num <= 0x3ffffff); - - var carry = 0; - for (var i = this.length - 1; i >= 0; i--) { - var w = (this.words[i] | 0) + carry * 0x4000000; - this.words[i] = (w / num) | 0; - carry = w % num; - } - - return this.strip(); - }; - - BN.prototype.divn = function divn (num) { - return this.clone().idivn(num); - }; - - BN.prototype.egcd = function egcd (p) { - assert(p.negative === 0); - assert(!p.isZero()); - - var x = this; - var y = p.clone(); - - if (x.negative !== 0) { - x = x.umod(p); - } else { - x = x.clone(); - } - - // A * x + B * y = x - var A = new BN(1); - var B = new BN(0); - - // C * x + D * y = y - var C = new BN(0); - var D = new BN(1); - - var g = 0; - - while (x.isEven() && y.isEven()) { - x.iushrn(1); - y.iushrn(1); - ++g; - } - - var yp = y.clone(); - var xp = x.clone(); - - while (!x.isZero()) { - for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1); - if (i > 0) { - x.iushrn(i); - while (i-- > 0) { - if (A.isOdd() || B.isOdd()) { - A.iadd(yp); - B.isub(xp); - } - - A.iushrn(1); - B.iushrn(1); - } - } - - for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); - if (j > 0) { - y.iushrn(j); - while (j-- > 0) { - if (C.isOdd() || D.isOdd()) { - C.iadd(yp); - D.isub(xp); - } - - C.iushrn(1); - D.iushrn(1); - } - } - - if (x.cmp(y) >= 0) { - x.isub(y); - A.isub(C); - B.isub(D); - } else { - y.isub(x); - C.isub(A); - D.isub(B); - } - } - - return { - a: C, - b: D, - gcd: y.iushln(g) - }; - }; - - // This is reduced incarnation of the binary EEA - // above, designated to invert members of the - // _prime_ fields F(p) at a maximal speed - BN.prototype._invmp = function _invmp (p) { - assert(p.negative === 0); - assert(!p.isZero()); - - var a = this; - var b = p.clone(); - - if (a.negative !== 0) { - a = a.umod(p); - } else { - a = a.clone(); - } - - var x1 = new BN(1); - var x2 = new BN(0); - - var delta = b.clone(); - - while (a.cmpn(1) > 0 && b.cmpn(1) > 0) { - for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1); - if (i > 0) { - a.iushrn(i); - while (i-- > 0) { - if (x1.isOdd()) { - x1.iadd(delta); - } - - x1.iushrn(1); - } - } - - for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); - if (j > 0) { - b.iushrn(j); - while (j-- > 0) { - if (x2.isOdd()) { - x2.iadd(delta); - } - - x2.iushrn(1); - } - } - - if (a.cmp(b) >= 0) { - a.isub(b); - x1.isub(x2); - } else { - b.isub(a); - x2.isub(x1); - } - } - - var res; - if (a.cmpn(1) === 0) { - res = x1; - } else { - res = x2; - } - - if (res.cmpn(0) < 0) { - res.iadd(p); - } - - return res; - }; - - BN.prototype.gcd = function gcd (num) { - if (this.isZero()) return num.abs(); - if (num.isZero()) return this.abs(); - - var a = this.clone(); - var b = num.clone(); - a.negative = 0; - b.negative = 0; - - // Remove common factor of two - for (var shift = 0; a.isEven() && b.isEven(); shift++) { - a.iushrn(1); - b.iushrn(1); - } - - do { - while (a.isEven()) { - a.iushrn(1); - } - while (b.isEven()) { - b.iushrn(1); - } - - var r = a.cmp(b); - if (r < 0) { - // Swap `a` and `b` to make `a` always bigger than `b` - var t = a; - a = b; - b = t; - } else if (r === 0 || b.cmpn(1) === 0) { - break; - } - - a.isub(b); - } while (true); - - return b.iushln(shift); - }; - - // Invert number in the field F(num) - BN.prototype.invm = function invm (num) { - return this.egcd(num).a.umod(num); - }; - - BN.prototype.isEven = function isEven () { - return (this.words[0] & 1) === 0; - }; - - BN.prototype.isOdd = function isOdd () { - return (this.words[0] & 1) === 1; - }; - - // And first word and num - BN.prototype.andln = function andln (num) { - return this.words[0] & num; - }; - - // Increment at the bit position in-line - BN.prototype.bincn = function bincn (bit) { - assert(typeof bit === 'number'); - var r = bit % 26; - var s = (bit - r) / 26; - var q = 1 << r; - - // Fast case: bit is much higher than all existing words - if (this.length <= s) { - this._expand(s + 1); - this.words[s] |= q; - return this; - } - - // Add bit and propagate, if needed - var carry = q; - for (var i = s; carry !== 0 && i < this.length; i++) { - var w = this.words[i] | 0; - w += carry; - carry = w >>> 26; - w &= 0x3ffffff; - this.words[i] = w; - } - if (carry !== 0) { - this.words[i] = carry; - this.length++; - } - return this; - }; - - BN.prototype.isZero = function isZero () { - return this.length === 1 && this.words[0] === 0; - }; - - BN.prototype.cmpn = function cmpn (num) { - var negative = num < 0; - - if (this.negative !== 0 && !negative) return -1; - if (this.negative === 0 && negative) return 1; - - this.strip(); - - var res; - if (this.length > 1) { - res = 1; - } else { - if (negative) { - num = -num; - } - - assert(num <= 0x3ffffff, 'Number is too big'); - - var w = this.words[0] | 0; - res = w === num ? 0 : w < num ? -1 : 1; - } - if (this.negative !== 0) return -res | 0; - return res; - }; - - // Compare two numbers and return: - // 1 - if `this` > `num` - // 0 - if `this` == `num` - // -1 - if `this` < `num` - BN.prototype.cmp = function cmp (num) { - if (this.negative !== 0 && num.negative === 0) return -1; - if (this.negative === 0 && num.negative !== 0) return 1; - - var res = this.ucmp(num); - if (this.negative !== 0) return -res | 0; - return res; - }; - - // Unsigned comparison - BN.prototype.ucmp = function ucmp (num) { - // At this point both numbers have the same sign - if (this.length > num.length) return 1; - if (this.length < num.length) return -1; - - var res = 0; - for (var i = this.length - 1; i >= 0; i--) { - var a = this.words[i] | 0; - var b = num.words[i] | 0; - - if (a === b) continue; - if (a < b) { - res = -1; - } else if (a > b) { - res = 1; - } - break; - } - return res; - }; - - BN.prototype.gtn = function gtn (num) { - return this.cmpn(num) === 1; - }; - - BN.prototype.gt = function gt (num) { - return this.cmp(num) === 1; - }; - - BN.prototype.gten = function gten (num) { - return this.cmpn(num) >= 0; - }; - - BN.prototype.gte = function gte (num) { - return this.cmp(num) >= 0; - }; - - BN.prototype.ltn = function ltn (num) { - return this.cmpn(num) === -1; - }; - - BN.prototype.lt = function lt (num) { - return this.cmp(num) === -1; - }; - - BN.prototype.lten = function lten (num) { - return this.cmpn(num) <= 0; - }; - - BN.prototype.lte = function lte (num) { - return this.cmp(num) <= 0; - }; - - BN.prototype.eqn = function eqn (num) { - return this.cmpn(num) === 0; - }; - - BN.prototype.eq = function eq (num) { - return this.cmp(num) === 0; - }; - - // - // A reduce context, could be using montgomery or something better, depending - // on the `m` itself. - // - BN.red = function red (num) { - return new Red(num); - }; - - BN.prototype.toRed = function toRed (ctx) { - assert(!this.red, 'Already a number in reduction context'); - assert(this.negative === 0, 'red works only with positives'); - return ctx.convertTo(this)._forceRed(ctx); - }; - - BN.prototype.fromRed = function fromRed () { - assert(this.red, 'fromRed works only with numbers in reduction context'); - return this.red.convertFrom(this); - }; - - BN.prototype._forceRed = function _forceRed (ctx) { - this.red = ctx; - return this; - }; - - BN.prototype.forceRed = function forceRed (ctx) { - assert(!this.red, 'Already a number in reduction context'); - return this._forceRed(ctx); - }; - - BN.prototype.redAdd = function redAdd (num) { - assert(this.red, 'redAdd works only with red numbers'); - return this.red.add(this, num); - }; - - BN.prototype.redIAdd = function redIAdd (num) { - assert(this.red, 'redIAdd works only with red numbers'); - return this.red.iadd(this, num); - }; - - BN.prototype.redSub = function redSub (num) { - assert(this.red, 'redSub works only with red numbers'); - return this.red.sub(this, num); - }; - - BN.prototype.redISub = function redISub (num) { - assert(this.red, 'redISub works only with red numbers'); - return this.red.isub(this, num); - }; - - BN.prototype.redShl = function redShl (num) { - assert(this.red, 'redShl works only with red numbers'); - return this.red.shl(this, num); - }; - - BN.prototype.redMul = function redMul (num) { - assert(this.red, 'redMul works only with red numbers'); - this.red._verify2(this, num); - return this.red.mul(this, num); - }; - - BN.prototype.redIMul = function redIMul (num) { - assert(this.red, 'redMul works only with red numbers'); - this.red._verify2(this, num); - return this.red.imul(this, num); - }; - - BN.prototype.redSqr = function redSqr () { - assert(this.red, 'redSqr works only with red numbers'); - this.red._verify1(this); - return this.red.sqr(this); - }; - - BN.prototype.redISqr = function redISqr () { - assert(this.red, 'redISqr works only with red numbers'); - this.red._verify1(this); - return this.red.isqr(this); - }; - - // Square root over p - BN.prototype.redSqrt = function redSqrt () { - assert(this.red, 'redSqrt works only with red numbers'); - this.red._verify1(this); - return this.red.sqrt(this); - }; - - BN.prototype.redInvm = function redInvm () { - assert(this.red, 'redInvm works only with red numbers'); - this.red._verify1(this); - return this.red.invm(this); - }; - - // Return negative clone of `this` % `red modulo` - BN.prototype.redNeg = function redNeg () { - assert(this.red, 'redNeg works only with red numbers'); - this.red._verify1(this); - return this.red.neg(this); - }; - - BN.prototype.redPow = function redPow (num) { - assert(this.red && !num.red, 'redPow(normalNum)'); - this.red._verify1(this); - return this.red.pow(this, num); - }; - - // Prime numbers with efficient reduction - var primes = { - k256: null, - p224: null, - p192: null, - p25519: null - }; - - // Pseudo-Mersenne prime - function MPrime (name, p) { - // P = 2 ^ N - K - this.name = name; - this.p = new BN(p, 16); - this.n = this.p.bitLength(); - this.k = new BN(1).iushln(this.n).isub(this.p); - - this.tmp = this._tmp(); - } - - MPrime.prototype._tmp = function _tmp () { - var tmp = new BN(null); - tmp.words = new Array(Math.ceil(this.n / 13)); - return tmp; - }; - - MPrime.prototype.ireduce = function ireduce (num) { - // Assumes that `num` is less than `P^2` - // num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P) - var r = num; - var rlen; - - do { - this.split(r, this.tmp); - r = this.imulK(r); - r = r.iadd(this.tmp); - rlen = r.bitLength(); - } while (rlen > this.n); - - var cmp = rlen < this.n ? -1 : r.ucmp(this.p); - if (cmp === 0) { - r.words[0] = 0; - r.length = 1; - } else if (cmp > 0) { - r.isub(this.p); - } else { - r.strip(); - } - - return r; - }; - - MPrime.prototype.split = function split (input, out) { - input.iushrn(this.n, 0, out); - }; - - MPrime.prototype.imulK = function imulK (num) { - return num.imul(this.k); - }; - - function K256 () { - MPrime.call( - this, - 'k256', - 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f'); - } - inherits(K256, MPrime); - - K256.prototype.split = function split (input, output) { - // 256 = 9 * 26 + 22 - var mask = 0x3fffff; - - var outLen = Math.min(input.length, 9); - for (var i = 0; i < outLen; i++) { - output.words[i] = input.words[i]; - } - output.length = outLen; - - if (input.length <= 9) { - input.words[0] = 0; - input.length = 1; - return; - } - - // Shift by 9 limbs - var prev = input.words[9]; - output.words[output.length++] = prev & mask; - - for (i = 10; i < input.length; i++) { - var next = input.words[i] | 0; - input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22); - prev = next; - } - prev >>>= 22; - input.words[i - 10] = prev; - if (prev === 0 && input.length > 10) { - input.length -= 10; - } else { - input.length -= 9; - } - }; - - K256.prototype.imulK = function imulK (num) { - // K = 0x1000003d1 = [ 0x40, 0x3d1 ] - num.words[num.length] = 0; - num.words[num.length + 1] = 0; - num.length += 2; - - // bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390 - var lo = 0; - for (var i = 0; i < num.length; i++) { - var w = num.words[i] | 0; - lo += w * 0x3d1; - num.words[i] = lo & 0x3ffffff; - lo = w * 0x40 + ((lo / 0x4000000) | 0); - } - - // Fast length reduction - if (num.words[num.length - 1] === 0) { - num.length--; - if (num.words[num.length - 1] === 0) { - num.length--; - } - } - return num; - }; - - function P224 () { - MPrime.call( - this, - 'p224', - 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001'); - } - inherits(P224, MPrime); - - function P192 () { - MPrime.call( - this, - 'p192', - 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff'); - } - inherits(P192, MPrime); - - function P25519 () { - // 2 ^ 255 - 19 - MPrime.call( - this, - '25519', - '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed'); - } - inherits(P25519, MPrime); - - P25519.prototype.imulK = function imulK (num) { - // K = 0x13 - var carry = 0; - for (var i = 0; i < num.length; i++) { - var hi = (num.words[i] | 0) * 0x13 + carry; - var lo = hi & 0x3ffffff; - hi >>>= 26; - - num.words[i] = lo; - carry = hi; - } - if (carry !== 0) { - num.words[num.length++] = carry; - } - return num; - }; - - // Exported mostly for testing purposes, use plain name instead - BN._prime = function prime (name) { - // Cached version of prime - if (primes[name]) return primes[name]; - - var prime; - if (name === 'k256') { - prime = new K256(); - } else if (name === 'p224') { - prime = new P224(); - } else if (name === 'p192') { - prime = new P192(); - } else if (name === 'p25519') { - prime = new P25519(); - } else { - throw new Error('Unknown prime ' + name); - } - primes[name] = prime; - - return prime; - }; - - // - // Base reduction engine - // - function Red (m) { - if (typeof m === 'string') { - var prime = BN._prime(m); - this.m = prime.p; - this.prime = prime; - } else { - assert(m.gtn(1), 'modulus must be greater than 1'); - this.m = m; - this.prime = null; - } - } - - Red.prototype._verify1 = function _verify1 (a) { - assert(a.negative === 0, 'red works only with positives'); - assert(a.red, 'red works only with red numbers'); - }; - - Red.prototype._verify2 = function _verify2 (a, b) { - assert((a.negative | b.negative) === 0, 'red works only with positives'); - assert(a.red && a.red === b.red, - 'red works only with red numbers'); - }; - - Red.prototype.imod = function imod (a) { - if (this.prime) return this.prime.ireduce(a)._forceRed(this); - return a.umod(this.m)._forceRed(this); - }; - - Red.prototype.neg = function neg (a) { - if (a.isZero()) { - return a.clone(); - } - - return this.m.sub(a)._forceRed(this); - }; - - Red.prototype.add = function add (a, b) { - this._verify2(a, b); - - var res = a.add(b); - if (res.cmp(this.m) >= 0) { - res.isub(this.m); - } - return res._forceRed(this); - }; - - Red.prototype.iadd = function iadd (a, b) { - this._verify2(a, b); - - var res = a.iadd(b); - if (res.cmp(this.m) >= 0) { - res.isub(this.m); - } - return res; - }; - - Red.prototype.sub = function sub (a, b) { - this._verify2(a, b); - - var res = a.sub(b); - if (res.cmpn(0) < 0) { - res.iadd(this.m); - } - return res._forceRed(this); - }; - - Red.prototype.isub = function isub (a, b) { - this._verify2(a, b); - - var res = a.isub(b); - if (res.cmpn(0) < 0) { - res.iadd(this.m); - } - return res; - }; - - Red.prototype.shl = function shl (a, num) { - this._verify1(a); - return this.imod(a.ushln(num)); - }; - - Red.prototype.imul = function imul (a, b) { - this._verify2(a, b); - return this.imod(a.imul(b)); - }; - - Red.prototype.mul = function mul (a, b) { - this._verify2(a, b); - return this.imod(a.mul(b)); - }; - - Red.prototype.isqr = function isqr (a) { - return this.imul(a, a.clone()); - }; - - Red.prototype.sqr = function sqr (a) { - return this.mul(a, a); - }; - - Red.prototype.sqrt = function sqrt (a) { - if (a.isZero()) return a.clone(); - - var mod3 = this.m.andln(3); - assert(mod3 % 2 === 1); - - // Fast case - if (mod3 === 3) { - var pow = this.m.add(new BN(1)).iushrn(2); - return this.pow(a, pow); - } - - // Tonelli-Shanks algorithm (Totally unoptimized and slow) - // - // Find Q and S, that Q * 2 ^ S = (P - 1) - var q = this.m.subn(1); - var s = 0; - while (!q.isZero() && q.andln(1) === 0) { - s++; - q.iushrn(1); - } - assert(!q.isZero()); - - var one = new BN(1).toRed(this); - var nOne = one.redNeg(); - - // Find quadratic non-residue - // NOTE: Max is such because of generalized Riemann hypothesis. - var lpow = this.m.subn(1).iushrn(1); - var z = this.m.bitLength(); - z = new BN(2 * z * z).toRed(this); - - while (this.pow(z, lpow).cmp(nOne) !== 0) { - z.redIAdd(nOne); - } - - var c = this.pow(z, q); - var r = this.pow(a, q.addn(1).iushrn(1)); - var t = this.pow(a, q); - var m = s; - while (t.cmp(one) !== 0) { - var tmp = t; - for (var i = 0; tmp.cmp(one) !== 0; i++) { - tmp = tmp.redSqr(); - } - assert(i < m); - var b = this.pow(c, new BN(1).iushln(m - i - 1)); - - r = r.redMul(b); - c = b.redSqr(); - t = t.redMul(c); - m = i; - } - - return r; - }; - - Red.prototype.invm = function invm (a) { - var inv = a._invmp(this.m); - if (inv.negative !== 0) { - inv.negative = 0; - return this.imod(inv).redNeg(); - } else { - return this.imod(inv); - } - }; - - Red.prototype.pow = function pow (a, num) { - if (num.isZero()) return new BN(1).toRed(this); - if (num.cmpn(1) === 0) return a.clone(); - - var windowSize = 4; - var wnd = new Array(1 << windowSize); - wnd[0] = new BN(1).toRed(this); - wnd[1] = a; - for (var i = 2; i < wnd.length; i++) { - wnd[i] = this.mul(wnd[i - 1], a); - } - - var res = wnd[0]; - var current = 0; - var currentLen = 0; - var start = num.bitLength() % 26; - if (start === 0) { - start = 26; - } - - for (i = num.length - 1; i >= 0; i--) { - var word = num.words[i]; - for (var j = start - 1; j >= 0; j--) { - var bit = (word >> j) & 1; - if (res !== wnd[0]) { - res = this.sqr(res); - } - - if (bit === 0 && current === 0) { - currentLen = 0; - continue; - } - - current <<= 1; - current |= bit; - currentLen++; - if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue; - - res = this.mul(res, wnd[current]); - currentLen = 0; - current = 0; - } - start = 26; - } - - return res; - }; - - Red.prototype.convertTo = function convertTo (num) { - var r = num.umod(this.m); - - return r === num ? r.clone() : r; - }; - - Red.prototype.convertFrom = function convertFrom (num) { - var res = num.clone(); - res.red = null; - return res; - }; - - // - // Montgomery method engine - // - - BN.mont = function mont (num) { - return new Mont(num); - }; - - function Mont (m) { - Red.call(this, m); - - this.shift = this.m.bitLength(); - if (this.shift % 26 !== 0) { - this.shift += 26 - (this.shift % 26); - } - - this.r = new BN(1).iushln(this.shift); - this.r2 = this.imod(this.r.sqr()); - this.rinv = this.r._invmp(this.m); - - this.minv = this.rinv.mul(this.r).isubn(1).div(this.m); - this.minv = this.minv.umod(this.r); - this.minv = this.r.sub(this.minv); - } - inherits(Mont, Red); - - Mont.prototype.convertTo = function convertTo (num) { - return this.imod(num.ushln(this.shift)); - }; - - Mont.prototype.convertFrom = function convertFrom (num) { - var r = this.imod(num.mul(this.rinv)); - r.red = null; - return r; - }; - - Mont.prototype.imul = function imul (a, b) { - if (a.isZero() || b.isZero()) { - a.words[0] = 0; - a.length = 1; - return a; - } - - var t = a.imul(b); - var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); - var u = t.isub(c).iushrn(this.shift); - var res = u; - - if (u.cmp(this.m) >= 0) { - res = u.isub(this.m); - } else if (u.cmpn(0) < 0) { - res = u.iadd(this.m); - } - - return res._forceRed(this); - }; - - Mont.prototype.mul = function mul (a, b) { - if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this); - - var t = a.mul(b); - var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); - var u = t.isub(c).iushrn(this.shift); - var res = u; - if (u.cmp(this.m) >= 0) { - res = u.isub(this.m); - } else if (u.cmpn(0) < 0) { - res = u.iadd(this.m); - } - - return res._forceRed(this); - }; - - Mont.prototype.invm = function invm (a) { - // (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R - var res = this.imod(a._invmp(this.m).mul(this.r2)); - return res._forceRed(this); - }; -})(module, commonjsGlobal); -}); - -var bn$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - 'default': bn, - __moduleExports: bn -}); - -/** - * @fileoverview - * BigInteger implementation of basic operations - * Wrapper of bn.js library (wwww.github.com/indutny/bn.js) - * @module biginteger/bn - * @private - */ - -/** - * @private - */ -class BigInteger$1 { - /** - * Get a BigInteger (input must be big endian for strings and arrays) - * @param {Number|String|Uint8Array} n - Value to convert - * @throws {Error} on undefined input - */ - constructor(n) { - if (n === undefined) { - throw new Error('Invalid BigInteger input'); - } - - this.value = new bn(n); - } - - clone() { - const clone = new BigInteger$1(null); - this.value.copy(clone.value); - return clone; - } - - /** - * BigInteger increment in place - */ - iinc() { - this.value.iadd(new bn(1)); - return this; - } - - /** - * BigInteger increment - * @returns {BigInteger} this + 1. - */ - inc() { - return this.clone().iinc(); - } - - /** - * BigInteger decrement in place - */ - idec() { - this.value.isub(new bn(1)); - return this; - } - - /** - * BigInteger decrement - * @returns {BigInteger} this - 1. - */ - dec() { - return this.clone().idec(); - } - - - /** - * BigInteger addition in place - * @param {BigInteger} x - Value to add - */ - iadd(x) { - this.value.iadd(x.value); - return this; - } - - /** - * BigInteger addition - * @param {BigInteger} x - Value to add - * @returns {BigInteger} this + x. - */ - add(x) { - return this.clone().iadd(x); - } - - /** - * BigInteger subtraction in place - * @param {BigInteger} x - Value to subtract - */ - isub(x) { - this.value.isub(x.value); - return this; - } - - /** - * BigInteger subtraction - * @param {BigInteger} x - Value to subtract - * @returns {BigInteger} this - x. - */ - sub(x) { - return this.clone().isub(x); - } - - /** - * BigInteger multiplication in place - * @param {BigInteger} x - Value to multiply - */ - imul(x) { - this.value.imul(x.value); - return this; - } - - /** - * BigInteger multiplication - * @param {BigInteger} x - Value to multiply - * @returns {BigInteger} this * x. - */ - mul(x) { - return this.clone().imul(x); - } - - /** - * Compute value modulo m, in place - * @param {BigInteger} m - Modulo - */ - imod(m) { - this.value = this.value.umod(m.value); - return this; - } - - /** - * Compute value modulo m - * @param {BigInteger} m - Modulo - * @returns {BigInteger} this mod m. - */ - mod(m) { - return this.clone().imod(m); - } - - /** - * Compute modular exponentiation - * Much faster than this.exp(e).mod(n) - * @param {BigInteger} e - Exponent - * @param {BigInteger} n - Modulo - * @returns {BigInteger} this ** e mod n. - */ - modExp(e, n) { - // We use either Montgomery or normal reduction context - // Montgomery requires coprime n and R (montogmery multiplier) - // bn.js picks R as power of 2, so n must be odd - const nred = n.isEven() ? bn.red(n.value) : bn.mont(n.value); - const x = this.clone(); - x.value = x.value.toRed(nred).redPow(e.value).fromRed(); - return x; - } - - /** - * Compute the inverse of this value modulo n - * Note: this and and n must be relatively prime - * @param {BigInteger} n - Modulo - * @returns {BigInteger} x such that this*x = 1 mod n - * @throws {Error} if the inverse does not exist - */ - modInv(n) { - // invm returns a wrong result if the inverse does not exist - if (!this.gcd(n).isOne()) { - throw new Error('Inverse does not exist'); - } - return new BigInteger$1(this.value.invm(n.value)); - } - - /** - * Compute greatest common divisor between this and n - * @param {BigInteger} n - Operand - * @returns {BigInteger} gcd - */ - gcd(n) { - return new BigInteger$1(this.value.gcd(n.value)); - } - - /** - * Shift this to the left by x, in place - * @param {BigInteger} x - Shift value - */ - ileftShift(x) { - this.value.ishln(x.value.toNumber()); - return this; - } - - /** - * Shift this to the left by x - * @param {BigInteger} x - Shift value - * @returns {BigInteger} this << x. - */ - leftShift(x) { - return this.clone().ileftShift(x); - } - - /** - * Shift this to the right by x, in place - * @param {BigInteger} x - Shift value - */ - irightShift(x) { - this.value.ishrn(x.value.toNumber()); - return this; - } - - /** - * Shift this to the right by x - * @param {BigInteger} x - Shift value - * @returns {BigInteger} this >> x. - */ - rightShift(x) { - return this.clone().irightShift(x); - } - - /** - * Whether this value is equal to x - * @param {BigInteger} x - * @returns {Boolean} - */ - equal(x) { - return this.value.eq(x.value); - } - - /** - * Whether this value is less than x - * @param {BigInteger} x - * @returns {Boolean} - */ - lt(x) { - return this.value.lt(x.value); - } - - /** - * Whether this value is less than or equal to x - * @param {BigInteger} x - * @returns {Boolean} - */ - lte(x) { - return this.value.lte(x.value); - } - - /** - * Whether this value is greater than x - * @param {BigInteger} x - * @returns {Boolean} - */ - gt(x) { - return this.value.gt(x.value); - } - - /** - * Whether this value is greater than or equal to x - * @param {BigInteger} x - * @returns {Boolean} - */ - gte(x) { - return this.value.gte(x.value); - } - - isZero() { - return this.value.isZero(); - } - - isOne() { - return this.value.eq(new bn(1)); - } - - isNegative() { - return this.value.isNeg(); - } - - isEven() { - return this.value.isEven(); - } - - abs() { - const res = this.clone(); - res.value = res.value.abs(); - return res; - } - - /** - * Get this value as a string - * @returns {String} this value. - */ - toString() { - return this.value.toString(); - } - - /** - * Get this value as an exact Number (max 53 bits) - * Fails if this value is too large - * @returns {Number} - */ - toNumber() { - return this.value.toNumber(); - } - - /** - * Get value of i-th bit - * @param {Number} i - Bit index - * @returns {Number} Bit value. - */ - getBit(i) { - return this.value.testn(i) ? 1 : 0; - } - - /** - * Compute bit length - * @returns {Number} Bit length. - */ - bitLength() { - return this.value.bitLength(); - } - - /** - * Compute byte length - * @returns {Number} Byte length. - */ - byteLength() { - return this.value.byteLength(); - } - - /** - * Get Uint8Array representation of this number - * @param {String} endian - Endianess of output array (defaults to 'be') - * @param {Number} length - Of output array - * @returns {Uint8Array} - */ - toUint8Array(endian = 'be', length) { - return this.value.toArrayLike(Uint8Array, endian, length); - } -} - -var bn_interface = /*#__PURE__*/Object.freeze({ - __proto__: null, - 'default': BigInteger$1 -}); - -var utils_1 = createCommonjsModule(function (module, exports) { - -var utils = exports; - -function toArray(msg, enc) { - if (Array.isArray(msg)) - return msg.slice(); - if (!msg) - return []; - var res = []; - if (typeof msg !== 'string') { - for (var i = 0; i < msg.length; i++) - res[i] = msg[i] | 0; - return res; - } - if (enc === 'hex') { - msg = msg.replace(/[^a-z0-9]+/ig, ''); - if (msg.length % 2 !== 0) - msg = '0' + msg; - for (var i = 0; i < msg.length; i += 2) - res.push(parseInt(msg[i] + msg[i + 1], 16)); - } else { - for (var i = 0; i < msg.length; i++) { - var c = msg.charCodeAt(i); - var hi = c >> 8; - var lo = c & 0xff; - if (hi) - res.push(hi, lo); - else - res.push(lo); - } - } - return res; -} -utils.toArray = toArray; - -function zero2(word) { - if (word.length === 1) - return '0' + word; - else - return word; -} -utils.zero2 = zero2; - -function toHex(msg) { - var res = ''; - for (var i = 0; i < msg.length; i++) - res += zero2(msg[i].toString(16)); - return res; -} -utils.toHex = toHex; - -utils.encode = function encode(arr, enc) { - if (enc === 'hex') - return toHex(arr); - else - return arr; -}; -}); - -var utils_1$1 = createCommonjsModule(function (module, exports) { - -var utils = exports; - - - - -utils.assert = minimalisticAssert; -utils.toArray = utils_1.toArray; -utils.zero2 = utils_1.zero2; -utils.toHex = utils_1.toHex; -utils.encode = utils_1.encode; - -// Represent num in a w-NAF form -function getNAF(num, w) { - var naf = []; - var ws = 1 << (w + 1); - var k = num.clone(); - while (k.cmpn(1) >= 0) { - var z; - if (k.isOdd()) { - var mod = k.andln(ws - 1); - if (mod > (ws >> 1) - 1) - z = (ws >> 1) - mod; - else - z = mod; - k.isubn(z); - } else { - z = 0; - } - naf.push(z); - - // Optimization, shift by word if possible - var shift = (k.cmpn(0) !== 0 && k.andln(ws - 1) === 0) ? (w + 1) : 1; - for (var i = 1; i < shift; i++) - naf.push(0); - k.iushrn(shift); - } - - return naf; -} -utils.getNAF = getNAF; - -// Represent k1, k2 in a Joint Sparse Form -function getJSF(k1, k2) { - var jsf = [ - [], - [] - ]; - - k1 = k1.clone(); - k2 = k2.clone(); - var d1 = 0; - var d2 = 0; - while (k1.cmpn(-d1) > 0 || k2.cmpn(-d2) > 0) { - - // First phase - var m14 = (k1.andln(3) + d1) & 3; - var m24 = (k2.andln(3) + d2) & 3; - if (m14 === 3) - m14 = -1; - if (m24 === 3) - m24 = -1; - var u1; - if ((m14 & 1) === 0) { - u1 = 0; - } else { - var m8 = (k1.andln(7) + d1) & 7; - if ((m8 === 3 || m8 === 5) && m24 === 2) - u1 = -m14; - else - u1 = m14; - } - jsf[0].push(u1); - - var u2; - if ((m24 & 1) === 0) { - u2 = 0; - } else { - var m8 = (k2.andln(7) + d2) & 7; - if ((m8 === 3 || m8 === 5) && m14 === 2) - u2 = -m24; - else - u2 = m24; - } - jsf[1].push(u2); - - // Second phase - if (2 * d1 === u1 + 1) - d1 = 1 - d1; - if (2 * d2 === u2 + 1) - d2 = 1 - d2; - k1.iushrn(1); - k2.iushrn(1); - } - - return jsf; -} -utils.getJSF = getJSF; - -function cachedProperty(obj, name, computer) { - var key = '_' + name; - obj.prototype[name] = function cachedProperty() { - return this[key] !== undefined ? this[key] : - this[key] = computer.call(this); - }; -} -utils.cachedProperty = cachedProperty; - -function parseBytes(bytes) { - return typeof bytes === 'string' ? utils.toArray(bytes, 'hex') : - bytes; -} -utils.parseBytes = parseBytes; - -function intFromLE(bytes) { - return new bn(bytes, 'hex', 'le'); -} -utils.intFromLE = intFromLE; -}); - -var r$1; - -var brorand = function rand(len) { - if (!r$1) - r$1 = new Rand(null); - - return r$1.generate(len); -}; - -function Rand(rand) { - this.rand = rand; -} -var Rand_1 = Rand; - -Rand.prototype.generate = function generate(len) { - return this._rand(len); -}; - -// Emulate crypto API using randy -Rand.prototype._rand = function _rand(n) { - if (this.rand.getBytes) - return this.rand.getBytes(n); - - var res = new Uint8Array(n); - for (var i = 0; i < res.length; i++) - res[i] = this.rand.getByte(); - return res; -}; - -if (typeof self === 'object') { - if (self.crypto && self.crypto.getRandomValues) { - // Modern browsers - Rand.prototype._rand = function _rand(n) { - var arr = new Uint8Array(n); - self.crypto.getRandomValues(arr); - return arr; - }; - } else if (self.msCrypto && self.msCrypto.getRandomValues) { - // IE - Rand.prototype._rand = function _rand(n) { - var arr = new Uint8Array(n); - self.msCrypto.getRandomValues(arr); - return arr; - }; - - // Safari's WebWorkers do not have `crypto` - } else if (typeof window === 'object') { - // Old junk - Rand.prototype._rand = function() { - throw new Error('Not implemented yet'); - }; - } -} else { - // Node.js or Web worker with no crypto support - try { - var crypto$2 = crypto__default['default']; - if (typeof crypto$2.randomBytes !== 'function') - throw new Error('Not supported'); - - Rand.prototype._rand = function _rand(n) { - return crypto$2.randomBytes(n); - }; - } catch (e) { - } -} -brorand.Rand = Rand_1; - -var getNAF = utils_1$1.getNAF; -var getJSF = utils_1$1.getJSF; -var assert$2 = utils_1$1.assert; - -function BaseCurve(type, conf) { - this.type = type; - this.p = new bn(conf.p, 16); - - // Use Montgomery, when there is no fast reduction for the prime - this.red = conf.prime ? bn.red(conf.prime) : bn.mont(this.p); - - // Useful for many curves - this.zero = new bn(0).toRed(this.red); - this.one = new bn(1).toRed(this.red); - this.two = new bn(2).toRed(this.red); - - // Curve configuration, optional - this.n = conf.n && new bn(conf.n, 16); - this.g = conf.g && this.pointFromJSON(conf.g, conf.gRed); - - // Temporary arrays - this._wnafT1 = new Array(4); - this._wnafT2 = new Array(4); - this._wnafT3 = new Array(4); - this._wnafT4 = new Array(4); - - // Generalized Greg Maxwell's trick - var adjustCount = this.n && this.p.div(this.n); - if (!adjustCount || adjustCount.cmpn(100) > 0) { - this.redN = null; - } else { - this._maxwellTrick = true; - this.redN = this.n.toRed(this.red); - } -} -var base = BaseCurve; - -BaseCurve.prototype.point = function point() { - throw new Error('Not implemented'); -}; - -BaseCurve.prototype.validate = function validate() { - throw new Error('Not implemented'); -}; - -BaseCurve.prototype._fixedNafMul = function _fixedNafMul(p, k) { - assert$2(p.precomputed); - var doubles = p._getDoubles(); - - var naf = getNAF(k, 1); - var I = (1 << (doubles.step + 1)) - (doubles.step % 2 === 0 ? 2 : 1); - I /= 3; - - // Translate into more windowed form - var repr = []; - for (var j = 0; j < naf.length; j += doubles.step) { - var nafW = 0; - for (var k = j + doubles.step - 1; k >= j; k--) - nafW = (nafW << 1) + naf[k]; - repr.push(nafW); - } - - var a = this.jpoint(null, null, null); - var b = this.jpoint(null, null, null); - for (var i = I; i > 0; i--) { - for (var j = 0; j < repr.length; j++) { - var nafW = repr[j]; - if (nafW === i) - b = b.mixedAdd(doubles.points[j]); - else if (nafW === -i) - b = b.mixedAdd(doubles.points[j].neg()); - } - a = a.add(b); - } - return a.toP(); -}; - -BaseCurve.prototype._wnafMul = function _wnafMul(p, k) { - var w = 4; - - // Precompute window - var nafPoints = p._getNAFPoints(w); - w = nafPoints.wnd; - var wnd = nafPoints.points; - - // Get NAF form - var naf = getNAF(k, w); - - // Add `this`*(N+1) for every w-NAF index - var acc = this.jpoint(null, null, null); - for (var i = naf.length - 1; i >= 0; i--) { - // Count zeroes - for (var k = 0; i >= 0 && naf[i] === 0; i--) - k++; - if (i >= 0) - k++; - acc = acc.dblp(k); - - if (i < 0) - break; - var z = naf[i]; - assert$2(z !== 0); - if (p.type === 'affine') { - // J +- P - if (z > 0) - acc = acc.mixedAdd(wnd[(z - 1) >> 1]); - else - acc = acc.mixedAdd(wnd[(-z - 1) >> 1].neg()); - } else { - // J +- J - if (z > 0) - acc = acc.add(wnd[(z - 1) >> 1]); - else - acc = acc.add(wnd[(-z - 1) >> 1].neg()); - } - } - return p.type === 'affine' ? acc.toP() : acc; -}; - -BaseCurve.prototype._wnafMulAdd = function _wnafMulAdd(defW, - points, - coeffs, - len, - jacobianResult) { - var wndWidth = this._wnafT1; - var wnd = this._wnafT2; - var naf = this._wnafT3; - - // Fill all arrays - var max = 0; - for (var i = 0; i < len; i++) { - var p = points[i]; - var nafPoints = p._getNAFPoints(defW); - wndWidth[i] = nafPoints.wnd; - wnd[i] = nafPoints.points; - } - - // Comb small window NAFs - for (var i = len - 1; i >= 1; i -= 2) { - var a = i - 1; - var b = i; - if (wndWidth[a] !== 1 || wndWidth[b] !== 1) { - naf[a] = getNAF(coeffs[a], wndWidth[a]); - naf[b] = getNAF(coeffs[b], wndWidth[b]); - max = Math.max(naf[a].length, max); - max = Math.max(naf[b].length, max); - continue; - } - - var comb = [ - points[a], /* 1 */ - null, /* 3 */ - null, /* 5 */ - points[b] /* 7 */ - ]; - - // Try to avoid Projective points, if possible - if (points[a].y.cmp(points[b].y) === 0) { - comb[1] = points[a].add(points[b]); - comb[2] = points[a].toJ().mixedAdd(points[b].neg()); - } else if (points[a].y.cmp(points[b].y.redNeg()) === 0) { - comb[1] = points[a].toJ().mixedAdd(points[b]); - comb[2] = points[a].add(points[b].neg()); - } else { - comb[1] = points[a].toJ().mixedAdd(points[b]); - comb[2] = points[a].toJ().mixedAdd(points[b].neg()); - } - - var index = [ - -3, /* -1 -1 */ - -1, /* -1 0 */ - -5, /* -1 1 */ - -7, /* 0 -1 */ - 0, /* 0 0 */ - 7, /* 0 1 */ - 5, /* 1 -1 */ - 1, /* 1 0 */ - 3 /* 1 1 */ - ]; - - var jsf = getJSF(coeffs[a], coeffs[b]); - max = Math.max(jsf[0].length, max); - naf[a] = new Array(max); - naf[b] = new Array(max); - for (var j = 0; j < max; j++) { - var ja = jsf[0][j] | 0; - var jb = jsf[1][j] | 0; - - naf[a][j] = index[(ja + 1) * 3 + (jb + 1)]; - naf[b][j] = 0; - wnd[a] = comb; - } - } - - var acc = this.jpoint(null, null, null); - var tmp = this._wnafT4; - for (var i = max; i >= 0; i--) { - var k = 0; - - while (i >= 0) { - var zero = true; - for (var j = 0; j < len; j++) { - tmp[j] = naf[j][i] | 0; - if (tmp[j] !== 0) - zero = false; - } - if (!zero) - break; - k++; - i--; - } - if (i >= 0) - k++; - acc = acc.dblp(k); - if (i < 0) - break; - - for (var j = 0; j < len; j++) { - var z = tmp[j]; - var p; - if (z === 0) - continue; - else if (z > 0) - p = wnd[j][(z - 1) >> 1]; - else if (z < 0) - p = wnd[j][(-z - 1) >> 1].neg(); - - if (p.type === 'affine') - acc = acc.mixedAdd(p); - else - acc = acc.add(p); - } - } - // Zeroify references - for (var i = 0; i < len; i++) - wnd[i] = null; - - if (jacobianResult) - return acc; - else - return acc.toP(); -}; - -function BasePoint(curve, type) { - this.curve = curve; - this.type = type; - this.precomputed = null; -} -BaseCurve.BasePoint = BasePoint; - -BasePoint.prototype.eq = function eq(/*other*/) { - throw new Error('Not implemented'); -}; - -BasePoint.prototype.validate = function validate() { - return this.curve.validate(this); -}; - -BaseCurve.prototype.decodePoint = function decodePoint(bytes, enc) { - bytes = utils_1$1.toArray(bytes, enc); - - var len = this.p.byteLength(); - - // uncompressed, hybrid-odd, hybrid-even - if ((bytes[0] === 0x04 || bytes[0] === 0x06 || bytes[0] === 0x07) && - bytes.length - 1 === 2 * len) { - if (bytes[0] === 0x06) - assert$2(bytes[bytes.length - 1] % 2 === 0); - else if (bytes[0] === 0x07) - assert$2(bytes[bytes.length - 1] % 2 === 1); - - var res = this.point(bytes.slice(1, 1 + len), - bytes.slice(1 + len, 1 + 2 * len)); - - return res; - } else if ((bytes[0] === 0x02 || bytes[0] === 0x03) && - bytes.length - 1 === len) { - return this.pointFromX(bytes.slice(1, 1 + len), bytes[0] === 0x03); - } - throw new Error('Unknown point format'); -}; - -BasePoint.prototype.encodeCompressed = function encodeCompressed(enc) { - return this.encode(enc, true); -}; - -BasePoint.prototype._encode = function _encode(compact) { - var len = this.curve.p.byteLength(); - var x = this.getX().toArray('be', len); - - if (compact) - return [ this.getY().isEven() ? 0x02 : 0x03 ].concat(x); - - return [ 0x04 ].concat(x, this.getY().toArray('be', len)) ; -}; - -BasePoint.prototype.encode = function encode(enc, compact) { - return utils_1$1.encode(this._encode(compact), enc); -}; - -BasePoint.prototype.precompute = function precompute(power) { - if (this.precomputed) - return this; - - var precomputed = { - doubles: null, - naf: null, - beta: null - }; - precomputed.naf = this._getNAFPoints(8); - precomputed.doubles = this._getDoubles(4, power); - precomputed.beta = this._getBeta(); - this.precomputed = precomputed; - - return this; -}; - -BasePoint.prototype._hasDoubles = function _hasDoubles(k) { - if (!this.precomputed) - return false; - - var doubles = this.precomputed.doubles; - if (!doubles) - return false; - - return doubles.points.length >= Math.ceil((k.bitLength() + 1) / doubles.step); -}; - -BasePoint.prototype._getDoubles = function _getDoubles(step, power) { - if (this.precomputed && this.precomputed.doubles) - return this.precomputed.doubles; - - var doubles = [ this ]; - var acc = this; - for (var i = 0; i < power; i += step) { - for (var j = 0; j < step; j++) - acc = acc.dbl(); - doubles.push(acc); - } - return { - step: step, - points: doubles - }; -}; - -BasePoint.prototype._getNAFPoints = function _getNAFPoints(wnd) { - if (this.precomputed && this.precomputed.naf) - return this.precomputed.naf; - - var res = [ this ]; - var max = (1 << wnd) - 1; - var dbl = max === 1 ? null : this.dbl(); - for (var i = 1; i < max; i++) - res[i] = res[i - 1].add(dbl); - return { - wnd: wnd, - points: res - }; -}; - -BasePoint.prototype._getBeta = function _getBeta() { - return null; -}; - -BasePoint.prototype.dblp = function dblp(k) { - var r = this; - for (var i = 0; i < k; i++) - r = r.dbl(); - return r; -}; - -var assert$3 = utils_1$1.assert; - -function ShortCurve(conf) { - base.call(this, 'short', conf); - - this.a = new bn(conf.a, 16).toRed(this.red); - this.b = new bn(conf.b, 16).toRed(this.red); - this.tinv = this.two.redInvm(); - - this.zeroA = this.a.fromRed().cmpn(0) === 0; - this.threeA = this.a.fromRed().sub(this.p).cmpn(-3) === 0; - - // If the curve is endomorphic, precalculate beta and lambda - this.endo = this._getEndomorphism(conf); - this._endoWnafT1 = new Array(4); - this._endoWnafT2 = new Array(4); -} -inherits(ShortCurve, base); -var short_1 = ShortCurve; - -ShortCurve.prototype._getEndomorphism = function _getEndomorphism(conf) { - // No efficient endomorphism - if (!this.zeroA || !this.g || !this.n || this.p.modn(3) !== 1) - return; - - // Compute beta and lambda, that lambda * P = (beta * Px; Py) - var beta; - var lambda; - if (conf.beta) { - beta = new bn(conf.beta, 16).toRed(this.red); - } else { - var betas = this._getEndoRoots(this.p); - // Choose the smallest beta - beta = betas[0].cmp(betas[1]) < 0 ? betas[0] : betas[1]; - beta = beta.toRed(this.red); - } - if (conf.lambda) { - lambda = new bn(conf.lambda, 16); - } else { - // Choose the lambda that is matching selected beta - var lambdas = this._getEndoRoots(this.n); - if (this.g.mul(lambdas[0]).x.cmp(this.g.x.redMul(beta)) === 0) { - lambda = lambdas[0]; - } else { - lambda = lambdas[1]; - assert$3(this.g.mul(lambda).x.cmp(this.g.x.redMul(beta)) === 0); - } - } - - // Get basis vectors, used for balanced length-two representation - var basis; - if (conf.basis) { - basis = conf.basis.map(function(vec) { - return { - a: new bn(vec.a, 16), - b: new bn(vec.b, 16) - }; - }); - } else { - basis = this._getEndoBasis(lambda); - } - - return { - beta: beta, - lambda: lambda, - basis: basis - }; -}; - -ShortCurve.prototype._getEndoRoots = function _getEndoRoots(num) { - // Find roots of for x^2 + x + 1 in F - // Root = (-1 +- Sqrt(-3)) / 2 - // - var red = num === this.p ? this.red : bn.mont(num); - var tinv = new bn(2).toRed(red).redInvm(); - var ntinv = tinv.redNeg(); - - var s = new bn(3).toRed(red).redNeg().redSqrt().redMul(tinv); - - var l1 = ntinv.redAdd(s).fromRed(); - var l2 = ntinv.redSub(s).fromRed(); - return [ l1, l2 ]; -}; - -ShortCurve.prototype._getEndoBasis = function _getEndoBasis(lambda) { - // aprxSqrt >= sqrt(this.n) - var aprxSqrt = this.n.ushrn(Math.floor(this.n.bitLength() / 2)); - - // 3.74 - // Run EGCD, until r(L + 1) < aprxSqrt - var u = lambda; - var v = this.n.clone(); - var x1 = new bn(1); - var y1 = new bn(0); - var x2 = new bn(0); - var y2 = new bn(1); - - // NOTE: all vectors are roots of: a + b * lambda = 0 (mod n) - var a0; - var b0; - // First vector - var a1; - var b1; - // Second vector - var a2; - var b2; - - var prevR; - var i = 0; - var r; - var x; - while (u.cmpn(0) !== 0) { - var q = v.div(u); - r = v.sub(q.mul(u)); - x = x2.sub(q.mul(x1)); - var y = y2.sub(q.mul(y1)); - - if (!a1 && r.cmp(aprxSqrt) < 0) { - a0 = prevR.neg(); - b0 = x1; - a1 = r.neg(); - b1 = x; - } else if (a1 && ++i === 2) { - break; - } - prevR = r; - - v = u; - u = r; - x2 = x1; - x1 = x; - y2 = y1; - y1 = y; - } - a2 = r.neg(); - b2 = x; - - var len1 = a1.sqr().add(b1.sqr()); - var len2 = a2.sqr().add(b2.sqr()); - if (len2.cmp(len1) >= 0) { - a2 = a0; - b2 = b0; - } - - // Normalize signs - if (a1.negative) { - a1 = a1.neg(); - b1 = b1.neg(); - } - if (a2.negative) { - a2 = a2.neg(); - b2 = b2.neg(); - } - - return [ - { a: a1, b: b1 }, - { a: a2, b: b2 } - ]; -}; - -ShortCurve.prototype._endoSplit = function _endoSplit(k) { - var basis = this.endo.basis; - var v1 = basis[0]; - var v2 = basis[1]; - - var c1 = v2.b.mul(k).divRound(this.n); - var c2 = v1.b.neg().mul(k).divRound(this.n); - - var p1 = c1.mul(v1.a); - var p2 = c2.mul(v2.a); - var q1 = c1.mul(v1.b); - var q2 = c2.mul(v2.b); - - // Calculate answer - var k1 = k.sub(p1).sub(p2); - var k2 = q1.add(q2).neg(); - return { k1: k1, k2: k2 }; -}; - -ShortCurve.prototype.pointFromX = function pointFromX(x, odd) { - x = new bn(x, 16); - if (!x.red) - x = x.toRed(this.red); - - var y2 = x.redSqr().redMul(x).redIAdd(x.redMul(this.a)).redIAdd(this.b); - var y = y2.redSqrt(); - if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) - throw new Error('invalid point'); - - // XXX Is there any way to tell if the number is odd without converting it - // to non-red form? - var isOdd = y.fromRed().isOdd(); - if (odd && !isOdd || !odd && isOdd) - y = y.redNeg(); - - return this.point(x, y); -}; - -ShortCurve.prototype.validate = function validate(point) { - if (point.inf) - return true; - - var x = point.x; - var y = point.y; - - var ax = this.a.redMul(x); - var rhs = x.redSqr().redMul(x).redIAdd(ax).redIAdd(this.b); - return y.redSqr().redISub(rhs).cmpn(0) === 0; -}; - -ShortCurve.prototype._endoWnafMulAdd = - function _endoWnafMulAdd(points, coeffs, jacobianResult) { - var npoints = this._endoWnafT1; - var ncoeffs = this._endoWnafT2; - for (var i = 0; i < points.length; i++) { - var split = this._endoSplit(coeffs[i]); - var p = points[i]; - var beta = p._getBeta(); - - if (split.k1.negative) { - split.k1.ineg(); - p = p.neg(true); - } - if (split.k2.negative) { - split.k2.ineg(); - beta = beta.neg(true); - } - - npoints[i * 2] = p; - npoints[i * 2 + 1] = beta; - ncoeffs[i * 2] = split.k1; - ncoeffs[i * 2 + 1] = split.k2; - } - var res = this._wnafMulAdd(1, npoints, ncoeffs, i * 2, jacobianResult); - - // Clean-up references to points and coefficients - for (var j = 0; j < i * 2; j++) { - npoints[j] = null; - ncoeffs[j] = null; - } - return res; -}; - -function Point(curve, x, y, isRed) { - base.BasePoint.call(this, curve, 'affine'); - if (x === null && y === null) { - this.x = null; - this.y = null; - this.inf = true; - } else { - this.x = new bn(x, 16); - this.y = new bn(y, 16); - // Force redgomery representation when loading from JSON - if (isRed) { - this.x.forceRed(this.curve.red); - this.y.forceRed(this.curve.red); - } - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.y.red) - this.y = this.y.toRed(this.curve.red); - this.inf = false; - } -} -inherits(Point, base.BasePoint); - -ShortCurve.prototype.point = function point(x, y, isRed) { - return new Point(this, x, y, isRed); -}; - -ShortCurve.prototype.pointFromJSON = function pointFromJSON(obj, red) { - return Point.fromJSON(this, obj, red); -}; - -Point.prototype._getBeta = function _getBeta() { - if (!this.curve.endo) - return; - - var pre = this.precomputed; - if (pre && pre.beta) - return pre.beta; - - var beta = this.curve.point(this.x.redMul(this.curve.endo.beta), this.y); - if (pre) { - var curve = this.curve; - var endoMul = function(p) { - return curve.point(p.x.redMul(curve.endo.beta), p.y); - }; - pre.beta = beta; - beta.precomputed = { - beta: null, - naf: pre.naf && { - wnd: pre.naf.wnd, - points: pre.naf.points.map(endoMul) - }, - doubles: pre.doubles && { - step: pre.doubles.step, - points: pre.doubles.points.map(endoMul) - } - }; - } - return beta; -}; - -Point.prototype.toJSON = function toJSON() { - if (!this.precomputed) - return [ this.x, this.y ]; - - return [ this.x, this.y, this.precomputed && { - doubles: this.precomputed.doubles && { - step: this.precomputed.doubles.step, - points: this.precomputed.doubles.points.slice(1) - }, - naf: this.precomputed.naf && { - wnd: this.precomputed.naf.wnd, - points: this.precomputed.naf.points.slice(1) - } - } ]; -}; - -Point.fromJSON = function fromJSON(curve, obj, red) { - if (typeof obj === 'string') - obj = JSON.parse(obj); - var res = curve.point(obj[0], obj[1], red); - if (!obj[2]) - return res; - - function obj2point(obj) { - return curve.point(obj[0], obj[1], red); - } - - var pre = obj[2]; - res.precomputed = { - beta: null, - doubles: pre.doubles && { - step: pre.doubles.step, - points: [ res ].concat(pre.doubles.points.map(obj2point)) - }, - naf: pre.naf && { - wnd: pre.naf.wnd, - points: [ res ].concat(pre.naf.points.map(obj2point)) - } - }; - return res; -}; - -Point.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; -}; - -Point.prototype.isInfinity = function isInfinity() { - return this.inf; -}; - -Point.prototype.add = function add(p) { - // O + P = P - if (this.inf) - return p; - - // P + O = P - if (p.inf) - return this; - - // P + P = 2P - if (this.eq(p)) - return this.dbl(); - - // P + (-P) = O - if (this.neg().eq(p)) - return this.curve.point(null, null); - - // P + Q = O - if (this.x.cmp(p.x) === 0) - return this.curve.point(null, null); - - var c = this.y.redSub(p.y); - if (c.cmpn(0) !== 0) - c = c.redMul(this.x.redSub(p.x).redInvm()); - var nx = c.redSqr().redISub(this.x).redISub(p.x); - var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); - return this.curve.point(nx, ny); -}; - -Point.prototype.dbl = function dbl() { - if (this.inf) - return this; - - // 2P = O - var ys1 = this.y.redAdd(this.y); - if (ys1.cmpn(0) === 0) - return this.curve.point(null, null); - - var a = this.curve.a; - - var x2 = this.x.redSqr(); - var dyinv = ys1.redInvm(); - var c = x2.redAdd(x2).redIAdd(x2).redIAdd(a).redMul(dyinv); - - var nx = c.redSqr().redISub(this.x.redAdd(this.x)); - var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); - return this.curve.point(nx, ny); -}; - -Point.prototype.getX = function getX() { - return this.x.fromRed(); -}; - -Point.prototype.getY = function getY() { - return this.y.fromRed(); -}; - -Point.prototype.mul = function mul(k) { - k = new bn(k, 16); - if (this.isInfinity()) - return this; - else if (this._hasDoubles(k)) - return this.curve._fixedNafMul(this, k); - else if (this.curve.endo) - return this.curve._endoWnafMulAdd([ this ], [ k ]); - else - return this.curve._wnafMul(this, k); -}; - -Point.prototype.mulAdd = function mulAdd(k1, p2, k2) { - var points = [ this, p2 ]; - var coeffs = [ k1, k2 ]; - if (this.curve.endo) - return this.curve._endoWnafMulAdd(points, coeffs); - else - return this.curve._wnafMulAdd(1, points, coeffs, 2); -}; - -Point.prototype.jmulAdd = function jmulAdd(k1, p2, k2) { - var points = [ this, p2 ]; - var coeffs = [ k1, k2 ]; - if (this.curve.endo) - return this.curve._endoWnafMulAdd(points, coeffs, true); - else - return this.curve._wnafMulAdd(1, points, coeffs, 2, true); -}; - -Point.prototype.eq = function eq(p) { - return this === p || - this.inf === p.inf && - (this.inf || this.x.cmp(p.x) === 0 && this.y.cmp(p.y) === 0); -}; - -Point.prototype.neg = function neg(_precompute) { - if (this.inf) - return this; - - var res = this.curve.point(this.x, this.y.redNeg()); - if (_precompute && this.precomputed) { - var pre = this.precomputed; - var negate = function(p) { - return p.neg(); - }; - res.precomputed = { - naf: pre.naf && { - wnd: pre.naf.wnd, - points: pre.naf.points.map(negate) - }, - doubles: pre.doubles && { - step: pre.doubles.step, - points: pre.doubles.points.map(negate) - } - }; - } - return res; -}; - -Point.prototype.toJ = function toJ() { - if (this.inf) - return this.curve.jpoint(null, null, null); - - var res = this.curve.jpoint(this.x, this.y, this.curve.one); - return res; -}; - -function JPoint(curve, x, y, z) { - base.BasePoint.call(this, curve, 'jacobian'); - if (x === null && y === null && z === null) { - this.x = this.curve.one; - this.y = this.curve.one; - this.z = new bn(0); - } else { - this.x = new bn(x, 16); - this.y = new bn(y, 16); - this.z = new bn(z, 16); - } - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.y.red) - this.y = this.y.toRed(this.curve.red); - if (!this.z.red) - this.z = this.z.toRed(this.curve.red); - - this.zOne = this.z === this.curve.one; -} -inherits(JPoint, base.BasePoint); - -ShortCurve.prototype.jpoint = function jpoint(x, y, z) { - return new JPoint(this, x, y, z); -}; - -JPoint.prototype.toP = function toP() { - if (this.isInfinity()) - return this.curve.point(null, null); - - var zinv = this.z.redInvm(); - var zinv2 = zinv.redSqr(); - var ax = this.x.redMul(zinv2); - var ay = this.y.redMul(zinv2).redMul(zinv); - - return this.curve.point(ax, ay); -}; - -JPoint.prototype.neg = function neg() { - return this.curve.jpoint(this.x, this.y.redNeg(), this.z); -}; - -JPoint.prototype.add = function add(p) { - // O + P = P - if (this.isInfinity()) - return p; - - // P + O = P - if (p.isInfinity()) - return this; - - // 12M + 4S + 7A - var pz2 = p.z.redSqr(); - var z2 = this.z.redSqr(); - var u1 = this.x.redMul(pz2); - var u2 = p.x.redMul(z2); - var s1 = this.y.redMul(pz2.redMul(p.z)); - var s2 = p.y.redMul(z2.redMul(this.z)); - - var h = u1.redSub(u2); - var r = s1.redSub(s2); - if (h.cmpn(0) === 0) { - if (r.cmpn(0) !== 0) - return this.curve.jpoint(null, null, null); - else - return this.dbl(); - } - - var h2 = h.redSqr(); - var h3 = h2.redMul(h); - var v = u1.redMul(h2); - - var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); - var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); - var nz = this.z.redMul(p.z).redMul(h); - - return this.curve.jpoint(nx, ny, nz); -}; - -JPoint.prototype.mixedAdd = function mixedAdd(p) { - // O + P = P - if (this.isInfinity()) - return p.toJ(); - - // P + O = P - if (p.isInfinity()) - return this; - - // 8M + 3S + 7A - var z2 = this.z.redSqr(); - var u1 = this.x; - var u2 = p.x.redMul(z2); - var s1 = this.y; - var s2 = p.y.redMul(z2).redMul(this.z); - - var h = u1.redSub(u2); - var r = s1.redSub(s2); - if (h.cmpn(0) === 0) { - if (r.cmpn(0) !== 0) - return this.curve.jpoint(null, null, null); - else - return this.dbl(); - } - - var h2 = h.redSqr(); - var h3 = h2.redMul(h); - var v = u1.redMul(h2); - - var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); - var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); - var nz = this.z.redMul(h); - - return this.curve.jpoint(nx, ny, nz); -}; - -JPoint.prototype.dblp = function dblp(pow) { - if (pow === 0) - return this; - if (this.isInfinity()) - return this; - if (!pow) - return this.dbl(); - - if (this.curve.zeroA || this.curve.threeA) { - var r = this; - for (var i = 0; i < pow; i++) - r = r.dbl(); - return r; - } - - // 1M + 2S + 1A + N * (4S + 5M + 8A) - // N = 1 => 6M + 6S + 9A - var a = this.curve.a; - var tinv = this.curve.tinv; - - var jx = this.x; - var jy = this.y; - var jz = this.z; - var jz4 = jz.redSqr().redSqr(); - - // Reuse results - var jyd = jy.redAdd(jy); - for (var i = 0; i < pow; i++) { - var jx2 = jx.redSqr(); - var jyd2 = jyd.redSqr(); - var jyd4 = jyd2.redSqr(); - var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); - - var t1 = jx.redMul(jyd2); - var nx = c.redSqr().redISub(t1.redAdd(t1)); - var t2 = t1.redISub(nx); - var dny = c.redMul(t2); - dny = dny.redIAdd(dny).redISub(jyd4); - var nz = jyd.redMul(jz); - if (i + 1 < pow) - jz4 = jz4.redMul(jyd4); - - jx = nx; - jz = nz; - jyd = dny; - } - - return this.curve.jpoint(jx, jyd.redMul(tinv), jz); -}; - -JPoint.prototype.dbl = function dbl() { - if (this.isInfinity()) - return this; - - if (this.curve.zeroA) - return this._zeroDbl(); - else if (this.curve.threeA) - return this._threeDbl(); - else - return this._dbl(); -}; - -JPoint.prototype._zeroDbl = function _zeroDbl() { - var nx; - var ny; - var nz; - // Z = 1 - if (this.zOne) { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html - // #doubling-mdbl-2007-bl - // 1M + 5S + 14A - - // XX = X1^2 - var xx = this.x.redSqr(); - // YY = Y1^2 - var yy = this.y.redSqr(); - // YYYY = YY^2 - var yyyy = yy.redSqr(); - // S = 2 * ((X1 + YY)^2 - XX - YYYY) - var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); - s = s.redIAdd(s); - // M = 3 * XX + a; a = 0 - var m = xx.redAdd(xx).redIAdd(xx); - // T = M ^ 2 - 2*S - var t = m.redSqr().redISub(s).redISub(s); - - // 8 * YYYY - var yyyy8 = yyyy.redIAdd(yyyy); - yyyy8 = yyyy8.redIAdd(yyyy8); - yyyy8 = yyyy8.redIAdd(yyyy8); - - // X3 = T - nx = t; - // Y3 = M * (S - T) - 8 * YYYY - ny = m.redMul(s.redISub(t)).redISub(yyyy8); - // Z3 = 2*Y1 - nz = this.y.redAdd(this.y); - } else { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html - // #doubling-dbl-2009-l - // 2M + 5S + 13A - - // A = X1^2 - var a = this.x.redSqr(); - // B = Y1^2 - var b = this.y.redSqr(); - // C = B^2 - var c = b.redSqr(); - // D = 2 * ((X1 + B)^2 - A - C) - var d = this.x.redAdd(b).redSqr().redISub(a).redISub(c); - d = d.redIAdd(d); - // E = 3 * A - var e = a.redAdd(a).redIAdd(a); - // F = E^2 - var f = e.redSqr(); - - // 8 * C - var c8 = c.redIAdd(c); - c8 = c8.redIAdd(c8); - c8 = c8.redIAdd(c8); - - // X3 = F - 2 * D - nx = f.redISub(d).redISub(d); - // Y3 = E * (D - X3) - 8 * C - ny = e.redMul(d.redISub(nx)).redISub(c8); - // Z3 = 2 * Y1 * Z1 - nz = this.y.redMul(this.z); - nz = nz.redIAdd(nz); - } - - return this.curve.jpoint(nx, ny, nz); -}; - -JPoint.prototype._threeDbl = function _threeDbl() { - var nx; - var ny; - var nz; - // Z = 1 - if (this.zOne) { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html - // #doubling-mdbl-2007-bl - // 1M + 5S + 15A - - // XX = X1^2 - var xx = this.x.redSqr(); - // YY = Y1^2 - var yy = this.y.redSqr(); - // YYYY = YY^2 - var yyyy = yy.redSqr(); - // S = 2 * ((X1 + YY)^2 - XX - YYYY) - var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); - s = s.redIAdd(s); - // M = 3 * XX + a - var m = xx.redAdd(xx).redIAdd(xx).redIAdd(this.curve.a); - // T = M^2 - 2 * S - var t = m.redSqr().redISub(s).redISub(s); - // X3 = T - nx = t; - // Y3 = M * (S - T) - 8 * YYYY - var yyyy8 = yyyy.redIAdd(yyyy); - yyyy8 = yyyy8.redIAdd(yyyy8); - yyyy8 = yyyy8.redIAdd(yyyy8); - ny = m.redMul(s.redISub(t)).redISub(yyyy8); - // Z3 = 2 * Y1 - nz = this.y.redAdd(this.y); - } else { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b - // 3M + 5S - - // delta = Z1^2 - var delta = this.z.redSqr(); - // gamma = Y1^2 - var gamma = this.y.redSqr(); - // beta = X1 * gamma - var beta = this.x.redMul(gamma); - // alpha = 3 * (X1 - delta) * (X1 + delta) - var alpha = this.x.redSub(delta).redMul(this.x.redAdd(delta)); - alpha = alpha.redAdd(alpha).redIAdd(alpha); - // X3 = alpha^2 - 8 * beta - var beta4 = beta.redIAdd(beta); - beta4 = beta4.redIAdd(beta4); - var beta8 = beta4.redAdd(beta4); - nx = alpha.redSqr().redISub(beta8); - // Z3 = (Y1 + Z1)^2 - gamma - delta - nz = this.y.redAdd(this.z).redSqr().redISub(gamma).redISub(delta); - // Y3 = alpha * (4 * beta - X3) - 8 * gamma^2 - var ggamma8 = gamma.redSqr(); - ggamma8 = ggamma8.redIAdd(ggamma8); - ggamma8 = ggamma8.redIAdd(ggamma8); - ggamma8 = ggamma8.redIAdd(ggamma8); - ny = alpha.redMul(beta4.redISub(nx)).redISub(ggamma8); - } - - return this.curve.jpoint(nx, ny, nz); -}; - -JPoint.prototype._dbl = function _dbl() { - var a = this.curve.a; - - // 4M + 6S + 10A - var jx = this.x; - var jy = this.y; - var jz = this.z; - var jz4 = jz.redSqr().redSqr(); - - var jx2 = jx.redSqr(); - var jy2 = jy.redSqr(); - - var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); - - var jxd4 = jx.redAdd(jx); - jxd4 = jxd4.redIAdd(jxd4); - var t1 = jxd4.redMul(jy2); - var nx = c.redSqr().redISub(t1.redAdd(t1)); - var t2 = t1.redISub(nx); - - var jyd8 = jy2.redSqr(); - jyd8 = jyd8.redIAdd(jyd8); - jyd8 = jyd8.redIAdd(jyd8); - jyd8 = jyd8.redIAdd(jyd8); - var ny = c.redMul(t2).redISub(jyd8); - var nz = jy.redAdd(jy).redMul(jz); - - return this.curve.jpoint(nx, ny, nz); -}; - -JPoint.prototype.trpl = function trpl() { - if (!this.curve.zeroA) - return this.dbl().add(this); - - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#tripling-tpl-2007-bl - // 5M + 10S + ... - - // XX = X1^2 - var xx = this.x.redSqr(); - // YY = Y1^2 - var yy = this.y.redSqr(); - // ZZ = Z1^2 - var zz = this.z.redSqr(); - // YYYY = YY^2 - var yyyy = yy.redSqr(); - // M = 3 * XX + a * ZZ2; a = 0 - var m = xx.redAdd(xx).redIAdd(xx); - // MM = M^2 - var mm = m.redSqr(); - // E = 6 * ((X1 + YY)^2 - XX - YYYY) - MM - var e = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); - e = e.redIAdd(e); - e = e.redAdd(e).redIAdd(e); - e = e.redISub(mm); - // EE = E^2 - var ee = e.redSqr(); - // T = 16*YYYY - var t = yyyy.redIAdd(yyyy); - t = t.redIAdd(t); - t = t.redIAdd(t); - t = t.redIAdd(t); - // U = (M + E)^2 - MM - EE - T - var u = m.redIAdd(e).redSqr().redISub(mm).redISub(ee).redISub(t); - // X3 = 4 * (X1 * EE - 4 * YY * U) - var yyu4 = yy.redMul(u); - yyu4 = yyu4.redIAdd(yyu4); - yyu4 = yyu4.redIAdd(yyu4); - var nx = this.x.redMul(ee).redISub(yyu4); - nx = nx.redIAdd(nx); - nx = nx.redIAdd(nx); - // Y3 = 8 * Y1 * (U * (T - U) - E * EE) - var ny = this.y.redMul(u.redMul(t.redISub(u)).redISub(e.redMul(ee))); - ny = ny.redIAdd(ny); - ny = ny.redIAdd(ny); - ny = ny.redIAdd(ny); - // Z3 = (Z1 + E)^2 - ZZ - EE - var nz = this.z.redAdd(e).redSqr().redISub(zz).redISub(ee); - - return this.curve.jpoint(nx, ny, nz); -}; - -JPoint.prototype.mul = function mul(k, kbase) { - k = new bn(k, kbase); - - return this.curve._wnafMul(this, k); -}; - -JPoint.prototype.eq = function eq(p) { - if (p.type === 'affine') - return this.eq(p.toJ()); - - if (this === p) - return true; - - // x1 * z2^2 == x2 * z1^2 - var z2 = this.z.redSqr(); - var pz2 = p.z.redSqr(); - if (this.x.redMul(pz2).redISub(p.x.redMul(z2)).cmpn(0) !== 0) - return false; - - // y1 * z2^3 == y2 * z1^3 - var z3 = z2.redMul(this.z); - var pz3 = pz2.redMul(p.z); - return this.y.redMul(pz3).redISub(p.y.redMul(z3)).cmpn(0) === 0; -}; - -JPoint.prototype.eqXToP = function eqXToP(x) { - var zs = this.z.redSqr(); - var rx = x.toRed(this.curve.red).redMul(zs); - if (this.x.cmp(rx) === 0) - return true; - - var xc = x.clone(); - var t = this.curve.redN.redMul(zs); - for (;;) { - xc.iadd(this.curve.n); - if (xc.cmp(this.curve.p) >= 0) - return false; - - rx.redIAdd(t); - if (this.x.cmp(rx) === 0) - return true; - } -}; - -JPoint.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; -}; - -JPoint.prototype.isInfinity = function isInfinity() { - // XXX This code assumes that zero is always zero in red - return this.z.cmpn(0) === 0; -}; - -function MontCurve(conf) { - base.call(this, 'mont', conf); - - this.a = new bn(conf.a, 16).toRed(this.red); - this.b = new bn(conf.b, 16).toRed(this.red); - this.i4 = new bn(4).toRed(this.red).redInvm(); - this.two = new bn(2).toRed(this.red); - // Note: this implementation is according to the original paper - // by P. Montgomery, NOT the one by D. J. Bernstein. - this.a24 = this.i4.redMul(this.a.redAdd(this.two)); -} -inherits(MontCurve, base); -var mont = MontCurve; - -MontCurve.prototype.validate = function validate(point) { - var x = point.normalize().x; - var x2 = x.redSqr(); - var rhs = x2.redMul(x).redAdd(x2.redMul(this.a)).redAdd(x); - var y = rhs.redSqrt(); - - return y.redSqr().cmp(rhs) === 0; -}; - -function Point$1(curve, x, z) { - base.BasePoint.call(this, curve, 'projective'); - if (x === null && z === null) { - this.x = this.curve.one; - this.z = this.curve.zero; - } else { - this.x = new bn(x, 16); - this.z = new bn(z, 16); - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.z.red) - this.z = this.z.toRed(this.curve.red); - } -} -inherits(Point$1, base.BasePoint); - -MontCurve.prototype.decodePoint = function decodePoint(bytes, enc) { - var bytes = utils_1$1.toArray(bytes, enc); - - // TODO Curve448 - // Montgomery curve points must be represented in the compressed format - // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B - if (bytes.length === 33 && bytes[0] === 0x40) - bytes = bytes.slice(1, 33).reverse(); // point must be little-endian - if (bytes.length !== 32) - throw new Error('Unknown point compression format'); - return this.point(bytes, 1); -}; - -MontCurve.prototype.point = function point(x, z) { - return new Point$1(this, x, z); -}; - -MontCurve.prototype.pointFromJSON = function pointFromJSON(obj) { - return Point$1.fromJSON(this, obj); -}; - -Point$1.prototype.precompute = function precompute() { - // No-op -}; - -Point$1.prototype._encode = function _encode(compact) { - var len = this.curve.p.byteLength(); - - // Note: the output should always be little-endian - // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B - if (compact) { - return [ 0x40 ].concat(this.getX().toArray('le', len)); - } else { - return this.getX().toArray('be', len); - } -}; - -Point$1.fromJSON = function fromJSON(curve, obj) { - return new Point$1(curve, obj[0], obj[1] || curve.one); -}; - -Point$1.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; -}; - -Point$1.prototype.isInfinity = function isInfinity() { - // XXX This code assumes that zero is always zero in red - return this.z.cmpn(0) === 0; -}; - -Point$1.prototype.dbl = function dbl() { - // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#doubling-dbl-1987-m-3 - // 2M + 2S + 4A - - // A = X1 + Z1 - var a = this.x.redAdd(this.z); - // AA = A^2 - var aa = a.redSqr(); - // B = X1 - Z1 - var b = this.x.redSub(this.z); - // BB = B^2 - var bb = b.redSqr(); - // C = AA - BB - var c = aa.redSub(bb); - // X3 = AA * BB - var nx = aa.redMul(bb); - // Z3 = C * (BB + A24 * C) - var nz = c.redMul(bb.redAdd(this.curve.a24.redMul(c))); - return this.curve.point(nx, nz); -}; - -Point$1.prototype.add = function add() { - throw new Error('Not supported on Montgomery curve'); -}; - -Point$1.prototype.diffAdd = function diffAdd(p, diff) { - // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#diffadd-dadd-1987-m-3 - // 4M + 2S + 6A - - // A = X2 + Z2 - var a = this.x.redAdd(this.z); - // B = X2 - Z2 - var b = this.x.redSub(this.z); - // C = X3 + Z3 - var c = p.x.redAdd(p.z); - // D = X3 - Z3 - var d = p.x.redSub(p.z); - // DA = D * A - var da = d.redMul(a); - // CB = C * B - var cb = c.redMul(b); - // X5 = Z1 * (DA + CB)^2 - var nx = diff.z.redMul(da.redAdd(cb).redSqr()); - // Z5 = X1 * (DA - CB)^2 - var nz = diff.x.redMul(da.redISub(cb).redSqr()); - return this.curve.point(nx, nz); -}; - -Point$1.prototype.mul = function mul(k) { - k = new bn(k, 16); - - var t = k.clone(); - var a = this; // (N / 2) * Q + Q - var b = this.curve.point(null, null); // (N / 2) * Q - var c = this; // Q - - for (var bits = []; t.cmpn(0) !== 0; t.iushrn(1)) - bits.push(t.andln(1)); - - for (var i = bits.length - 1; i >= 0; i--) { - if (bits[i] === 0) { - // N * Q + Q = ((N / 2) * Q + Q)) + (N / 2) * Q - a = a.diffAdd(b, c); - // N * Q = 2 * ((N / 2) * Q + Q)) - b = b.dbl(); - } else { - // N * Q = ((N / 2) * Q + Q) + ((N / 2) * Q) - b = a.diffAdd(b, c); - // N * Q + Q = 2 * ((N / 2) * Q + Q) - a = a.dbl(); - } - } - return b; -}; - -Point$1.prototype.mulAdd = function mulAdd() { - throw new Error('Not supported on Montgomery curve'); -}; - -Point$1.prototype.jumlAdd = function jumlAdd() { - throw new Error('Not supported on Montgomery curve'); -}; - -Point$1.prototype.eq = function eq(other) { - return this.getX().cmp(other.getX()) === 0; -}; - -Point$1.prototype.normalize = function normalize() { - this.x = this.x.redMul(this.z.redInvm()); - this.z = this.curve.one; - return this; -}; - -Point$1.prototype.getX = function getX() { - // Normalize coordinates - this.normalize(); - - return this.x.fromRed(); -}; - -var assert$4 = utils_1$1.assert; - -function EdwardsCurve(conf) { - // NOTE: Important as we are creating point in Base.call() - this.twisted = (conf.a | 0) !== 1; - this.mOneA = this.twisted && (conf.a | 0) === -1; - this.extended = this.mOneA; - - base.call(this, 'edwards', conf); - - this.a = new bn(conf.a, 16).umod(this.red.m); - this.a = this.a.toRed(this.red); - this.c = new bn(conf.c, 16).toRed(this.red); - this.c2 = this.c.redSqr(); - this.d = new bn(conf.d, 16).toRed(this.red); - this.dd = this.d.redAdd(this.d); - - assert$4(!this.twisted || this.c.fromRed().cmpn(1) === 0); - this.oneC = (conf.c | 0) === 1; -} -inherits(EdwardsCurve, base); -var edwards = EdwardsCurve; - -EdwardsCurve.prototype._mulA = function _mulA(num) { - if (this.mOneA) - return num.redNeg(); - else - return this.a.redMul(num); -}; - -EdwardsCurve.prototype._mulC = function _mulC(num) { - if (this.oneC) - return num; - else - return this.c.redMul(num); -}; - -// Just for compatibility with Short curve -EdwardsCurve.prototype.jpoint = function jpoint(x, y, z, t) { - return this.point(x, y, z, t); -}; - -EdwardsCurve.prototype.pointFromX = function pointFromX(x, odd) { - x = new bn(x, 16); - if (!x.red) - x = x.toRed(this.red); - - var x2 = x.redSqr(); - var rhs = this.c2.redSub(this.a.redMul(x2)); - var lhs = this.one.redSub(this.c2.redMul(this.d).redMul(x2)); - - var y2 = rhs.redMul(lhs.redInvm()); - var y = y2.redSqrt(); - if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) - throw new Error('invalid point'); - - var isOdd = y.fromRed().isOdd(); - if (odd && !isOdd || !odd && isOdd) - y = y.redNeg(); - - return this.point(x, y); -}; - -EdwardsCurve.prototype.pointFromY = function pointFromY(y, odd) { - y = new bn(y, 16); - if (!y.red) - y = y.toRed(this.red); - - // x^2 = (y^2 - c^2) / (c^2 d y^2 - a) - var y2 = y.redSqr(); - var lhs = y2.redSub(this.c2); - var rhs = y2.redMul(this.d).redMul(this.c2).redSub(this.a); - var x2 = lhs.redMul(rhs.redInvm()); - - if (x2.cmp(this.zero) === 0) { - if (odd) - throw new Error('invalid point'); - else - return this.point(this.zero, y); - } - - var x = x2.redSqrt(); - if (x.redSqr().redSub(x2).cmp(this.zero) !== 0) - throw new Error('invalid point'); - - if (x.fromRed().isOdd() !== odd) - x = x.redNeg(); - - return this.point(x, y); -}; - -EdwardsCurve.prototype.validate = function validate(point) { - if (point.isInfinity()) - return true; - - // Curve: A * X^2 + Y^2 = C^2 * (1 + D * X^2 * Y^2) - point.normalize(); - - var x2 = point.x.redSqr(); - var y2 = point.y.redSqr(); - var lhs = x2.redMul(this.a).redAdd(y2); - var rhs = this.c2.redMul(this.one.redAdd(this.d.redMul(x2).redMul(y2))); - - return lhs.cmp(rhs) === 0; -}; - -function Point$2(curve, x, y, z, t) { - base.BasePoint.call(this, curve, 'projective'); - if (x === null && y === null && z === null) { - this.x = this.curve.zero; - this.y = this.curve.one; - this.z = this.curve.one; - this.t = this.curve.zero; - this.zOne = true; - } else { - this.x = new bn(x, 16); - this.y = new bn(y, 16); - this.z = z ? new bn(z, 16) : this.curve.one; - this.t = t && new bn(t, 16); - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.y.red) - this.y = this.y.toRed(this.curve.red); - if (!this.z.red) - this.z = this.z.toRed(this.curve.red); - if (this.t && !this.t.red) - this.t = this.t.toRed(this.curve.red); - this.zOne = this.z === this.curve.one; - - // Use extended coordinates - if (this.curve.extended && !this.t) { - this.t = this.x.redMul(this.y); - if (!this.zOne) - this.t = this.t.redMul(this.z.redInvm()); - } - } -} -inherits(Point$2, base.BasePoint); - -EdwardsCurve.prototype.pointFromJSON = function pointFromJSON(obj) { - return Point$2.fromJSON(this, obj); -}; - -EdwardsCurve.prototype.point = function point(x, y, z, t) { - return new Point$2(this, x, y, z, t); -}; - -Point$2.fromJSON = function fromJSON(curve, obj) { - return new Point$2(curve, obj[0], obj[1], obj[2]); -}; - -Point$2.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; -}; - -Point$2.prototype.isInfinity = function isInfinity() { - // XXX This code assumes that zero is always zero in red - return this.x.cmpn(0) === 0 && - (this.y.cmp(this.z) === 0 || - (this.zOne && this.y.cmp(this.curve.c) === 0)); -}; - -Point$2.prototype._extDbl = function _extDbl() { - // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html - // #doubling-dbl-2008-hwcd - // 4M + 4S - - // A = X1^2 - var a = this.x.redSqr(); - // B = Y1^2 - var b = this.y.redSqr(); - // C = 2 * Z1^2 - var c = this.z.redSqr(); - c = c.redIAdd(c); - // D = a * A - var d = this.curve._mulA(a); - // E = (X1 + Y1)^2 - A - B - var e = this.x.redAdd(this.y).redSqr().redISub(a).redISub(b); - // G = D + B - var g = d.redAdd(b); - // F = G - C - var f = g.redSub(c); - // H = D - B - var h = d.redSub(b); - // X3 = E * F - var nx = e.redMul(f); - // Y3 = G * H - var ny = g.redMul(h); - // T3 = E * H - var nt = e.redMul(h); - // Z3 = F * G - var nz = f.redMul(g); - return this.curve.point(nx, ny, nz, nt); -}; - -Point$2.prototype._projDbl = function _projDbl() { - // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html - // #doubling-dbl-2008-bbjlp - // #doubling-dbl-2007-bl - // and others - // Generally 3M + 4S or 2M + 4S - - // B = (X1 + Y1)^2 - var b = this.x.redAdd(this.y).redSqr(); - // C = X1^2 - var c = this.x.redSqr(); - // D = Y1^2 - var d = this.y.redSqr(); - - var nx; - var ny; - var nz; - if (this.curve.twisted) { - // E = a * C - var e = this.curve._mulA(c); - // F = E + D - var f = e.redAdd(d); - if (this.zOne) { - // X3 = (B - C - D) * (F - 2) - nx = b.redSub(c).redSub(d).redMul(f.redSub(this.curve.two)); - // Y3 = F * (E - D) - ny = f.redMul(e.redSub(d)); - // Z3 = F^2 - 2 * F - nz = f.redSqr().redSub(f).redSub(f); - } else { - // H = Z1^2 - var h = this.z.redSqr(); - // J = F - 2 * H - var j = f.redSub(h).redISub(h); - // X3 = (B-C-D)*J - nx = b.redSub(c).redISub(d).redMul(j); - // Y3 = F * (E - D) - ny = f.redMul(e.redSub(d)); - // Z3 = F * J - nz = f.redMul(j); - } - } else { - // E = C + D - var e = c.redAdd(d); - // H = (c * Z1)^2 - var h = this.curve._mulC(this.z).redSqr(); - // J = E - 2 * H - var j = e.redSub(h).redSub(h); - // X3 = c * (B - E) * J - nx = this.curve._mulC(b.redISub(e)).redMul(j); - // Y3 = c * E * (C - D) - ny = this.curve._mulC(e).redMul(c.redISub(d)); - // Z3 = E * J - nz = e.redMul(j); - } - return this.curve.point(nx, ny, nz); -}; - -Point$2.prototype.dbl = function dbl() { - if (this.isInfinity()) - return this; - - // Double in extended coordinates - if (this.curve.extended) - return this._extDbl(); - else - return this._projDbl(); -}; - -Point$2.prototype._extAdd = function _extAdd(p) { - // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html - // #addition-add-2008-hwcd-3 - // 8M - - // A = (Y1 - X1) * (Y2 - X2) - var a = this.y.redSub(this.x).redMul(p.y.redSub(p.x)); - // B = (Y1 + X1) * (Y2 + X2) - var b = this.y.redAdd(this.x).redMul(p.y.redAdd(p.x)); - // C = T1 * k * T2 - var c = this.t.redMul(this.curve.dd).redMul(p.t); - // D = Z1 * 2 * Z2 - var d = this.z.redMul(p.z.redAdd(p.z)); - // E = B - A - var e = b.redSub(a); - // F = D - C - var f = d.redSub(c); - // G = D + C - var g = d.redAdd(c); - // H = B + A - var h = b.redAdd(a); - // X3 = E * F - var nx = e.redMul(f); - // Y3 = G * H - var ny = g.redMul(h); - // T3 = E * H - var nt = e.redMul(h); - // Z3 = F * G - var nz = f.redMul(g); - return this.curve.point(nx, ny, nz, nt); -}; - -Point$2.prototype._projAdd = function _projAdd(p) { - // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html - // #addition-add-2008-bbjlp - // #addition-add-2007-bl - // 10M + 1S - - // A = Z1 * Z2 - var a = this.z.redMul(p.z); - // B = A^2 - var b = a.redSqr(); - // C = X1 * X2 - var c = this.x.redMul(p.x); - // D = Y1 * Y2 - var d = this.y.redMul(p.y); - // E = d * C * D - var e = this.curve.d.redMul(c).redMul(d); - // F = B - E - var f = b.redSub(e); - // G = B + E - var g = b.redAdd(e); - // X3 = A * F * ((X1 + Y1) * (X2 + Y2) - C - D) - var tmp = this.x.redAdd(this.y).redMul(p.x.redAdd(p.y)).redISub(c).redISub(d); - var nx = a.redMul(f).redMul(tmp); - var ny; - var nz; - if (this.curve.twisted) { - // Y3 = A * G * (D - a * C) - ny = a.redMul(g).redMul(d.redSub(this.curve._mulA(c))); - // Z3 = F * G - nz = f.redMul(g); - } else { - // Y3 = A * G * (D - C) - ny = a.redMul(g).redMul(d.redSub(c)); - // Z3 = c * F * G - nz = this.curve._mulC(f).redMul(g); - } - return this.curve.point(nx, ny, nz); -}; - -Point$2.prototype.add = function add(p) { - if (this.isInfinity()) - return p; - if (p.isInfinity()) - return this; - - if (this.curve.extended) - return this._extAdd(p); - else - return this._projAdd(p); -}; - -Point$2.prototype.mul = function mul(k) { - if (this._hasDoubles(k)) - return this.curve._fixedNafMul(this, k); - else - return this.curve._wnafMul(this, k); -}; - -Point$2.prototype.mulAdd = function mulAdd(k1, p, k2) { - return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, false); -}; - -Point$2.prototype.jmulAdd = function jmulAdd(k1, p, k2) { - return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, true); -}; - -Point$2.prototype.normalize = function normalize() { - if (this.zOne) - return this; - - // Normalize coordinates - var zi = this.z.redInvm(); - this.x = this.x.redMul(zi); - this.y = this.y.redMul(zi); - if (this.t) - this.t = this.t.redMul(zi); - this.z = this.curve.one; - this.zOne = true; - return this; -}; - -Point$2.prototype.neg = function neg() { - return this.curve.point(this.x.redNeg(), - this.y, - this.z, - this.t && this.t.redNeg()); -}; - -Point$2.prototype.getX = function getX() { - this.normalize(); - return this.x.fromRed(); -}; - -Point$2.prototype.getY = function getY() { - this.normalize(); - return this.y.fromRed(); -}; - -Point$2.prototype.eq = function eq(other) { - return this === other || - this.getX().cmp(other.getX()) === 0 && - this.getY().cmp(other.getY()) === 0; -}; - -Point$2.prototype.eqXToP = function eqXToP(x) { - var rx = x.toRed(this.curve.red).redMul(this.z); - if (this.x.cmp(rx) === 0) - return true; - - var xc = x.clone(); - var t = this.curve.redN.redMul(this.z); - for (;;) { - xc.iadd(this.curve.n); - if (xc.cmp(this.curve.p) >= 0) - return false; - - rx.redIAdd(t); - if (this.x.cmp(rx) === 0) - return true; - } -}; - -// Compatibility with BaseCurve -Point$2.prototype.toP = Point$2.prototype.normalize; -Point$2.prototype.mixedAdd = Point$2.prototype.add; - -var curve_1 = createCommonjsModule(function (module, exports) { - -var curve = exports; - -curve.base = base; -curve.short = short_1; -curve.mont = mont; -curve.edwards = edwards; -}); - -var rotl32$2 = utils.rotl32; -var sum32$3 = utils.sum32; -var sum32_5$2 = utils.sum32_5; -var ft_1$1 = common$1.ft_1; -var BlockHash$4 = common.BlockHash; - -var sha1_K = [ - 0x5A827999, 0x6ED9EBA1, - 0x8F1BBCDC, 0xCA62C1D6 -]; - -function SHA1() { - if (!(this instanceof SHA1)) - return new SHA1(); - - BlockHash$4.call(this); - this.h = [ - 0x67452301, 0xefcdab89, 0x98badcfe, - 0x10325476, 0xc3d2e1f0 ]; - this.W = new Array(80); -} - -utils.inherits(SHA1, BlockHash$4); -var _1 = SHA1; - -SHA1.blockSize = 512; -SHA1.outSize = 160; -SHA1.hmacStrength = 80; -SHA1.padLength = 64; - -SHA1.prototype._update = function _update(msg, start) { - var W = this.W; - - for (var i = 0; i < 16; i++) - W[i] = msg[start + i]; - - for(; i < W.length; i++) - W[i] = rotl32$2(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1); - - var a = this.h[0]; - var b = this.h[1]; - var c = this.h[2]; - var d = this.h[3]; - var e = this.h[4]; - - for (i = 0; i < W.length; i++) { - var s = ~~(i / 20); - var t = sum32_5$2(rotl32$2(a, 5), ft_1$1(s, b, c, d), e, W[i], sha1_K[s]); - e = d; - d = c; - c = rotl32$2(b, 30); - b = a; - a = t; - } - - this.h[0] = sum32$3(this.h[0], a); - this.h[1] = sum32$3(this.h[1], b); - this.h[2] = sum32$3(this.h[2], c); - this.h[3] = sum32$3(this.h[3], d); - this.h[4] = sum32$3(this.h[4], e); -}; - -SHA1.prototype._digest = function digest(enc) { - if (enc === 'hex') - return utils.toHex32(this.h, 'big'); - else - return utils.split32(this.h, 'big'); -}; - -var sha1 = _1; -var sha224 = _224; -var sha256 = _256; -var sha384 = _384; -var sha512 = _512; - -var sha = { - sha1: sha1, - sha224: sha224, - sha256: sha256, - sha384: sha384, - sha512: sha512 -}; - -function Hmac(hash, key, enc) { - if (!(this instanceof Hmac)) - return new Hmac(hash, key, enc); - this.Hash = hash; - this.blockSize = hash.blockSize / 8; - this.outSize = hash.outSize / 8; - this.inner = null; - this.outer = null; - - this._init(utils.toArray(key, enc)); -} -var hmac = Hmac; - -Hmac.prototype._init = function init(key) { - // Shorten key, if needed - if (key.length > this.blockSize) - key = new this.Hash().update(key).digest(); - minimalisticAssert(key.length <= this.blockSize); - - // Add padding to key - for (var i = key.length; i < this.blockSize; i++) - key.push(0); - - for (i = 0; i < key.length; i++) - key[i] ^= 0x36; - this.inner = new this.Hash().update(key); - - // 0x36 ^ 0x5c = 0x6a - for (i = 0; i < key.length; i++) - key[i] ^= 0x6a; - this.outer = new this.Hash().update(key); -}; - -Hmac.prototype.update = function update(msg, enc) { - this.inner.update(msg, enc); - return this; -}; - -Hmac.prototype.digest = function digest(enc) { - this.outer.update(this.inner.digest()); - return this.outer.digest(enc); -}; - -var hash_1 = createCommonjsModule(function (module, exports) { -var hash = exports; - -hash.utils = utils; -hash.common = common; -hash.sha = sha; -hash.ripemd = ripemd; -hash.hmac = hmac; - -// Proxy hash functions to the main object -hash.sha1 = hash.sha.sha1; -hash.sha256 = hash.sha.sha256; -hash.sha224 = hash.sha.sha224; -hash.sha384 = hash.sha.sha384; -hash.sha512 = hash.sha.sha512; -hash.ripemd160 = hash.ripemd.ripemd160; -}); - -var secp256k1 = { - doubles: { - step: 4, - points: [ - [ - 'e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a', - 'f7e3507399e595929db99f34f57937101296891e44d23f0be1f32cce69616821' - ], - [ - '8282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508', - '11f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf' - ], - [ - '175e159f728b865a72f99cc6c6fc846de0b93833fd2222ed73fce5b551e5b739', - 'd3506e0d9e3c79eba4ef97a51ff71f5eacb5955add24345c6efa6ffee9fed695' - ], - [ - '363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640', - '4e273adfc732221953b445397f3363145b9a89008199ecb62003c7f3bee9de9' - ], - [ - '8b4b5f165df3c2be8c6244b5b745638843e4a781a15bcd1b69f79a55dffdf80c', - '4aad0a6f68d308b4b3fbd7813ab0da04f9e336546162ee56b3eff0c65fd4fd36' - ], - [ - '723cbaa6e5db996d6bf771c00bd548c7b700dbffa6c0e77bcb6115925232fcda', - '96e867b5595cc498a921137488824d6e2660a0653779494801dc069d9eb39f5f' - ], - [ - 'eebfa4d493bebf98ba5feec812c2d3b50947961237a919839a533eca0e7dd7fa', - '5d9a8ca3970ef0f269ee7edaf178089d9ae4cdc3a711f712ddfd4fdae1de8999' - ], - [ - '100f44da696e71672791d0a09b7bde459f1215a29b3c03bfefd7835b39a48db0', - 'cdd9e13192a00b772ec8f3300c090666b7ff4a18ff5195ac0fbd5cd62bc65a09' - ], - [ - 'e1031be262c7ed1b1dc9227a4a04c017a77f8d4464f3b3852c8acde6e534fd2d', - '9d7061928940405e6bb6a4176597535af292dd419e1ced79a44f18f29456a00d' - ], - [ - 'feea6cae46d55b530ac2839f143bd7ec5cf8b266a41d6af52d5e688d9094696d', - 'e57c6b6c97dce1bab06e4e12bf3ecd5c981c8957cc41442d3155debf18090088' - ], - [ - 'da67a91d91049cdcb367be4be6ffca3cfeed657d808583de33fa978bc1ec6cb1', - '9bacaa35481642bc41f463f7ec9780e5dec7adc508f740a17e9ea8e27a68be1d' - ], - [ - '53904faa0b334cdda6e000935ef22151ec08d0f7bb11069f57545ccc1a37b7c0', - '5bc087d0bc80106d88c9eccac20d3c1c13999981e14434699dcb096b022771c8' - ], - [ - '8e7bcd0bd35983a7719cca7764ca906779b53a043a9b8bcaeff959f43ad86047', - '10b7770b2a3da4b3940310420ca9514579e88e2e47fd68b3ea10047e8460372a' - ], - [ - '385eed34c1cdff21e6d0818689b81bde71a7f4f18397e6690a841e1599c43862', - '283bebc3e8ea23f56701de19e9ebf4576b304eec2086dc8cc0458fe5542e5453' - ], - [ - '6f9d9b803ecf191637c73a4413dfa180fddf84a5947fbc9c606ed86c3fac3a7', - '7c80c68e603059ba69b8e2a30e45c4d47ea4dd2f5c281002d86890603a842160' - ], - [ - '3322d401243c4e2582a2147c104d6ecbf774d163db0f5e5313b7e0e742d0e6bd', - '56e70797e9664ef5bfb019bc4ddaf9b72805f63ea2873af624f3a2e96c28b2a0' - ], - [ - '85672c7d2de0b7da2bd1770d89665868741b3f9af7643397721d74d28134ab83', - '7c481b9b5b43b2eb6374049bfa62c2e5e77f17fcc5298f44c8e3094f790313a6' - ], - [ - '948bf809b1988a46b06c9f1919413b10f9226c60f668832ffd959af60c82a0a', - '53a562856dcb6646dc6b74c5d1c3418c6d4dff08c97cd2bed4cb7f88d8c8e589' - ], - [ - '6260ce7f461801c34f067ce0f02873a8f1b0e44dfc69752accecd819f38fd8e8', - 'bc2da82b6fa5b571a7f09049776a1ef7ecd292238051c198c1a84e95b2b4ae17' - ], - [ - 'e5037de0afc1d8d43d8348414bbf4103043ec8f575bfdc432953cc8d2037fa2d', - '4571534baa94d3b5f9f98d09fb990bddbd5f5b03ec481f10e0e5dc841d755bda' - ], - [ - 'e06372b0f4a207adf5ea905e8f1771b4e7e8dbd1c6a6c5b725866a0ae4fce725', - '7a908974bce18cfe12a27bb2ad5a488cd7484a7787104870b27034f94eee31dd' - ], - [ - '213c7a715cd5d45358d0bbf9dc0ce02204b10bdde2a3f58540ad6908d0559754', - '4b6dad0b5ae462507013ad06245ba190bb4850f5f36a7eeddff2c27534b458f2' - ], - [ - '4e7c272a7af4b34e8dbb9352a5419a87e2838c70adc62cddf0cc3a3b08fbd53c', - '17749c766c9d0b18e16fd09f6def681b530b9614bff7dd33e0b3941817dcaae6' - ], - [ - 'fea74e3dbe778b1b10f238ad61686aa5c76e3db2be43057632427e2840fb27b6', - '6e0568db9b0b13297cf674deccb6af93126b596b973f7b77701d3db7f23cb96f' - ], - [ - '76e64113f677cf0e10a2570d599968d31544e179b760432952c02a4417bdde39', - 'c90ddf8dee4e95cf577066d70681f0d35e2a33d2b56d2032b4b1752d1901ac01' - ], - [ - 'c738c56b03b2abe1e8281baa743f8f9a8f7cc643df26cbee3ab150242bcbb891', - '893fb578951ad2537f718f2eacbfbbbb82314eef7880cfe917e735d9699a84c3' - ], - [ - 'd895626548b65b81e264c7637c972877d1d72e5f3a925014372e9f6588f6c14b', - 'febfaa38f2bc7eae728ec60818c340eb03428d632bb067e179363ed75d7d991f' - ], - [ - 'b8da94032a957518eb0f6433571e8761ceffc73693e84edd49150a564f676e03', - '2804dfa44805a1e4d7c99cc9762808b092cc584d95ff3b511488e4e74efdf6e7' - ], - [ - 'e80fea14441fb33a7d8adab9475d7fab2019effb5156a792f1a11778e3c0df5d', - 'eed1de7f638e00771e89768ca3ca94472d155e80af322ea9fcb4291b6ac9ec78' - ], - [ - 'a301697bdfcd704313ba48e51d567543f2a182031efd6915ddc07bbcc4e16070', - '7370f91cfb67e4f5081809fa25d40f9b1735dbf7c0a11a130c0d1a041e177ea1' - ], - [ - '90ad85b389d6b936463f9d0512678de208cc330b11307fffab7ac63e3fb04ed4', - 'e507a3620a38261affdcbd9427222b839aefabe1582894d991d4d48cb6ef150' - ], - [ - '8f68b9d2f63b5f339239c1ad981f162ee88c5678723ea3351b7b444c9ec4c0da', - '662a9f2dba063986de1d90c2b6be215dbbea2cfe95510bfdf23cbf79501fff82' - ], - [ - 'e4f3fb0176af85d65ff99ff9198c36091f48e86503681e3e6686fd5053231e11', - '1e63633ad0ef4f1c1661a6d0ea02b7286cc7e74ec951d1c9822c38576feb73bc' - ], - [ - '8c00fa9b18ebf331eb961537a45a4266c7034f2f0d4e1d0716fb6eae20eae29e', - 'efa47267fea521a1a9dc343a3736c974c2fadafa81e36c54e7d2a4c66702414b' - ], - [ - 'e7a26ce69dd4829f3e10cec0a9e98ed3143d084f308b92c0997fddfc60cb3e41', - '2a758e300fa7984b471b006a1aafbb18d0a6b2c0420e83e20e8a9421cf2cfd51' - ], - [ - 'b6459e0ee3662ec8d23540c223bcbdc571cbcb967d79424f3cf29eb3de6b80ef', - '67c876d06f3e06de1dadf16e5661db3c4b3ae6d48e35b2ff30bf0b61a71ba45' - ], - [ - 'd68a80c8280bb840793234aa118f06231d6f1fc67e73c5a5deda0f5b496943e8', - 'db8ba9fff4b586d00c4b1f9177b0e28b5b0e7b8f7845295a294c84266b133120' - ], - [ - '324aed7df65c804252dc0270907a30b09612aeb973449cea4095980fc28d3d5d', - '648a365774b61f2ff130c0c35aec1f4f19213b0c7e332843967224af96ab7c84' - ], - [ - '4df9c14919cde61f6d51dfdbe5fee5dceec4143ba8d1ca888e8bd373fd054c96', - '35ec51092d8728050974c23a1d85d4b5d506cdc288490192ebac06cad10d5d' - ], - [ - '9c3919a84a474870faed8a9c1cc66021523489054d7f0308cbfc99c8ac1f98cd', - 'ddb84f0f4a4ddd57584f044bf260e641905326f76c64c8e6be7e5e03d4fc599d' - ], - [ - '6057170b1dd12fdf8de05f281d8e06bb91e1493a8b91d4cc5a21382120a959e5', - '9a1af0b26a6a4807add9a2daf71df262465152bc3ee24c65e899be932385a2a8' - ], - [ - 'a576df8e23a08411421439a4518da31880cef0fba7d4df12b1a6973eecb94266', - '40a6bf20e76640b2c92b97afe58cd82c432e10a7f514d9f3ee8be11ae1b28ec8' - ], - [ - '7778a78c28dec3e30a05fe9629de8c38bb30d1f5cf9a3a208f763889be58ad71', - '34626d9ab5a5b22ff7098e12f2ff580087b38411ff24ac563b513fc1fd9f43ac' - ], - [ - '928955ee637a84463729fd30e7afd2ed5f96274e5ad7e5cb09eda9c06d903ac', - 'c25621003d3f42a827b78a13093a95eeac3d26efa8a8d83fc5180e935bcd091f' - ], - [ - '85d0fef3ec6db109399064f3a0e3b2855645b4a907ad354527aae75163d82751', - '1f03648413a38c0be29d496e582cf5663e8751e96877331582c237a24eb1f962' - ], - [ - 'ff2b0dce97eece97c1c9b6041798b85dfdfb6d8882da20308f5404824526087e', - '493d13fef524ba188af4c4dc54d07936c7b7ed6fb90e2ceb2c951e01f0c29907' - ], - [ - '827fbbe4b1e880ea9ed2b2e6301b212b57f1ee148cd6dd28780e5e2cf856e241', - 'c60f9c923c727b0b71bef2c67d1d12687ff7a63186903166d605b68baec293ec' - ], - [ - 'eaa649f21f51bdbae7be4ae34ce6e5217a58fdce7f47f9aa7f3b58fa2120e2b3', - 'be3279ed5bbbb03ac69a80f89879aa5a01a6b965f13f7e59d47a5305ba5ad93d' - ], - [ - 'e4a42d43c5cf169d9391df6decf42ee541b6d8f0c9a137401e23632dda34d24f', - '4d9f92e716d1c73526fc99ccfb8ad34ce886eedfa8d8e4f13a7f7131deba9414' - ], - [ - '1ec80fef360cbdd954160fadab352b6b92b53576a88fea4947173b9d4300bf19', - 'aeefe93756b5340d2f3a4958a7abbf5e0146e77f6295a07b671cdc1cc107cefd' - ], - [ - '146a778c04670c2f91b00af4680dfa8bce3490717d58ba889ddb5928366642be', - 'b318e0ec3354028add669827f9d4b2870aaa971d2f7e5ed1d0b297483d83efd0' - ], - [ - 'fa50c0f61d22e5f07e3acebb1aa07b128d0012209a28b9776d76a8793180eef9', - '6b84c6922397eba9b72cd2872281a68a5e683293a57a213b38cd8d7d3f4f2811' - ], - [ - 'da1d61d0ca721a11b1a5bf6b7d88e8421a288ab5d5bba5220e53d32b5f067ec2', - '8157f55a7c99306c79c0766161c91e2966a73899d279b48a655fba0f1ad836f1' - ], - [ - 'a8e282ff0c9706907215ff98e8fd416615311de0446f1e062a73b0610d064e13', - '7f97355b8db81c09abfb7f3c5b2515888b679a3e50dd6bd6cef7c73111f4cc0c' - ], - [ - '174a53b9c9a285872d39e56e6913cab15d59b1fa512508c022f382de8319497c', - 'ccc9dc37abfc9c1657b4155f2c47f9e6646b3a1d8cb9854383da13ac079afa73' - ], - [ - '959396981943785c3d3e57edf5018cdbe039e730e4918b3d884fdff09475b7ba', - '2e7e552888c331dd8ba0386a4b9cd6849c653f64c8709385e9b8abf87524f2fd' - ], - [ - 'd2a63a50ae401e56d645a1153b109a8fcca0a43d561fba2dbb51340c9d82b151', - 'e82d86fb6443fcb7565aee58b2948220a70f750af484ca52d4142174dcf89405' - ], - [ - '64587e2335471eb890ee7896d7cfdc866bacbdbd3839317b3436f9b45617e073', - 'd99fcdd5bf6902e2ae96dd6447c299a185b90a39133aeab358299e5e9faf6589' - ], - [ - '8481bde0e4e4d885b3a546d3e549de042f0aa6cea250e7fd358d6c86dd45e458', - '38ee7b8cba5404dd84a25bf39cecb2ca900a79c42b262e556d64b1b59779057e' - ], - [ - '13464a57a78102aa62b6979ae817f4637ffcfed3c4b1ce30bcd6303f6caf666b', - '69be159004614580ef7e433453ccb0ca48f300a81d0942e13f495a907f6ecc27' - ], - [ - 'bc4a9df5b713fe2e9aef430bcc1dc97a0cd9ccede2f28588cada3a0d2d83f366', - 'd3a81ca6e785c06383937adf4b798caa6e8a9fbfa547b16d758d666581f33c1' - ], - [ - '8c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa', - '40a30463a3305193378fedf31f7cc0eb7ae784f0451cb9459e71dc73cbef9482' - ], - [ - '8ea9666139527a8c1dd94ce4f071fd23c8b350c5a4bb33748c4ba111faccae0', - '620efabbc8ee2782e24e7c0cfb95c5d735b783be9cf0f8e955af34a30e62b945' - ], - [ - 'dd3625faef5ba06074669716bbd3788d89bdde815959968092f76cc4eb9a9787', - '7a188fa3520e30d461da2501045731ca941461982883395937f68d00c644a573' - ], - [ - 'f710d79d9eb962297e4f6232b40e8f7feb2bc63814614d692c12de752408221e', - 'ea98e67232d3b3295d3b535532115ccac8612c721851617526ae47a9c77bfc82' - ] - ] - }, - naf: { - wnd: 7, - points: [ - [ - 'f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9', - '388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672' - ], - [ - '2f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4', - 'd8ac222636e5e3d6d4dba9dda6c9c426f788271bab0d6840dca87d3aa6ac62d6' - ], - [ - '5cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc', - '6aebca40ba255960a3178d6d861a54dba813d0b813fde7b5a5082628087264da' - ], - [ - 'acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe', - 'cc338921b0a7d9fd64380971763b61e9add888a4375f8e0f05cc262ac64f9c37' - ], - [ - '774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb', - 'd984a032eb6b5e190243dd56d7b7b365372db1e2dff9d6a8301d74c9c953c61b' - ], - [ - 'f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8', - 'ab0902e8d880a89758212eb65cdaf473a1a06da521fa91f29b5cb52db03ed81' - ], - [ - 'd7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e', - '581e2872a86c72a683842ec228cc6defea40af2bd896d3a5c504dc9ff6a26b58' - ], - [ - 'defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34', - '4211ab0694635168e997b0ead2a93daeced1f4a04a95c0f6cfb199f69e56eb77' - ], - [ - '2b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c', - '85e89bc037945d93b343083b5a1c86131a01f60c50269763b570c854e5c09b7a' - ], - [ - '352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5', - '321eb4075348f534d59c18259dda3e1f4a1b3b2e71b1039c67bd3d8bcf81998c' - ], - [ - '2fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f', - '2de1068295dd865b64569335bd5dd80181d70ecfc882648423ba76b532b7d67' - ], - [ - '9248279b09b4d68dab21a9b066edda83263c3d84e09572e269ca0cd7f5453714', - '73016f7bf234aade5d1aa71bdea2b1ff3fc0de2a887912ffe54a32ce97cb3402' - ], - [ - 'daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729', - 'a69dce4a7d6c98e8d4a1aca87ef8d7003f83c230f3afa726ab40e52290be1c55' - ], - [ - 'c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db', - '2119a460ce326cdc76c45926c982fdac0e106e861edf61c5a039063f0e0e6482' - ], - [ - '6a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4', - 'e022cf42c2bd4a708b3f5126f16a24ad8b33ba48d0423b6efd5e6348100d8a82' - ], - [ - '1697ffa6fd9de627c077e3d2fe541084ce13300b0bec1146f95ae57f0d0bd6a5', - 'b9c398f186806f5d27561506e4557433a2cf15009e498ae7adee9d63d01b2396' - ], - [ - '605bdb019981718b986d0f07e834cb0d9deb8360ffb7f61df982345ef27a7479', - '2972d2de4f8d20681a78d93ec96fe23c26bfae84fb14db43b01e1e9056b8c49' - ], - [ - '62d14dab4150bf497402fdc45a215e10dcb01c354959b10cfe31c7e9d87ff33d', - '80fc06bd8cc5b01098088a1950eed0db01aa132967ab472235f5642483b25eaf' - ], - [ - '80c60ad0040f27dade5b4b06c408e56b2c50e9f56b9b8b425e555c2f86308b6f', - '1c38303f1cc5c30f26e66bad7fe72f70a65eed4cbe7024eb1aa01f56430bd57a' - ], - [ - '7a9375ad6167ad54aa74c6348cc54d344cc5dc9487d847049d5eabb0fa03c8fb', - 'd0e3fa9eca8726909559e0d79269046bdc59ea10c70ce2b02d499ec224dc7f7' - ], - [ - 'd528ecd9b696b54c907a9ed045447a79bb408ec39b68df504bb51f459bc3ffc9', - 'eecf41253136e5f99966f21881fd656ebc4345405c520dbc063465b521409933' - ], - [ - '49370a4b5f43412ea25f514e8ecdad05266115e4a7ecb1387231808f8b45963', - '758f3f41afd6ed428b3081b0512fd62a54c3f3afbb5b6764b653052a12949c9a' - ], - [ - '77f230936ee88cbbd73df930d64702ef881d811e0e1498e2f1c13eb1fc345d74', - '958ef42a7886b6400a08266e9ba1b37896c95330d97077cbbe8eb3c7671c60d6' - ], - [ - 'f2dac991cc4ce4b9ea44887e5c7c0bce58c80074ab9d4dbaeb28531b7739f530', - 'e0dedc9b3b2f8dad4da1f32dec2531df9eb5fbeb0598e4fd1a117dba703a3c37' - ], - [ - '463b3d9f662621fb1b4be8fbbe2520125a216cdfc9dae3debcba4850c690d45b', - '5ed430d78c296c3543114306dd8622d7c622e27c970a1de31cb377b01af7307e' - ], - [ - 'f16f804244e46e2a09232d4aff3b59976b98fac14328a2d1a32496b49998f247', - 'cedabd9b82203f7e13d206fcdf4e33d92a6c53c26e5cce26d6579962c4e31df6' - ], - [ - 'caf754272dc84563b0352b7a14311af55d245315ace27c65369e15f7151d41d1', - 'cb474660ef35f5f2a41b643fa5e460575f4fa9b7962232a5c32f908318a04476' - ], - [ - '2600ca4b282cb986f85d0f1709979d8b44a09c07cb86d7c124497bc86f082120', - '4119b88753c15bd6a693b03fcddbb45d5ac6be74ab5f0ef44b0be9475a7e4b40' - ], - [ - '7635ca72d7e8432c338ec53cd12220bc01c48685e24f7dc8c602a7746998e435', - '91b649609489d613d1d5e590f78e6d74ecfc061d57048bad9e76f302c5b9c61' - ], - [ - '754e3239f325570cdbbf4a87deee8a66b7f2b33479d468fbc1a50743bf56cc18', - '673fb86e5bda30fb3cd0ed304ea49a023ee33d0197a695d0c5d98093c536683' - ], - [ - 'e3e6bd1071a1e96aff57859c82d570f0330800661d1c952f9fe2694691d9b9e8', - '59c9e0bba394e76f40c0aa58379a3cb6a5a2283993e90c4167002af4920e37f5' - ], - [ - '186b483d056a033826ae73d88f732985c4ccb1f32ba35f4b4cc47fdcf04aa6eb', - '3b952d32c67cf77e2e17446e204180ab21fb8090895138b4a4a797f86e80888b' - ], - [ - 'df9d70a6b9876ce544c98561f4be4f725442e6d2b737d9c91a8321724ce0963f', - '55eb2dafd84d6ccd5f862b785dc39d4ab157222720ef9da217b8c45cf2ba2417' - ], - [ - '5edd5cc23c51e87a497ca815d5dce0f8ab52554f849ed8995de64c5f34ce7143', - 'efae9c8dbc14130661e8cec030c89ad0c13c66c0d17a2905cdc706ab7399a868' - ], - [ - '290798c2b6476830da12fe02287e9e777aa3fba1c355b17a722d362f84614fba', - 'e38da76dcd440621988d00bcf79af25d5b29c094db2a23146d003afd41943e7a' - ], - [ - 'af3c423a95d9f5b3054754efa150ac39cd29552fe360257362dfdecef4053b45', - 'f98a3fd831eb2b749a93b0e6f35cfb40c8cd5aa667a15581bc2feded498fd9c6' - ], - [ - '766dbb24d134e745cccaa28c99bf274906bb66b26dcf98df8d2fed50d884249a', - '744b1152eacbe5e38dcc887980da38b897584a65fa06cedd2c924f97cbac5996' - ], - [ - '59dbf46f8c94759ba21277c33784f41645f7b44f6c596a58ce92e666191abe3e', - 'c534ad44175fbc300f4ea6ce648309a042ce739a7919798cd85e216c4a307f6e' - ], - [ - 'f13ada95103c4537305e691e74e9a4a8dd647e711a95e73cb62dc6018cfd87b8', - 'e13817b44ee14de663bf4bc808341f326949e21a6a75c2570778419bdaf5733d' - ], - [ - '7754b4fa0e8aced06d4167a2c59cca4cda1869c06ebadfb6488550015a88522c', - '30e93e864e669d82224b967c3020b8fa8d1e4e350b6cbcc537a48b57841163a2' - ], - [ - '948dcadf5990e048aa3874d46abef9d701858f95de8041d2a6828c99e2262519', - 'e491a42537f6e597d5d28a3224b1bc25df9154efbd2ef1d2cbba2cae5347d57e' - ], - [ - '7962414450c76c1689c7b48f8202ec37fb224cf5ac0bfa1570328a8a3d7c77ab', - '100b610ec4ffb4760d5c1fc133ef6f6b12507a051f04ac5760afa5b29db83437' - ], - [ - '3514087834964b54b15b160644d915485a16977225b8847bb0dd085137ec47ca', - 'ef0afbb2056205448e1652c48e8127fc6039e77c15c2378b7e7d15a0de293311' - ], - [ - 'd3cc30ad6b483e4bc79ce2c9dd8bc54993e947eb8df787b442943d3f7b527eaf', - '8b378a22d827278d89c5e9be8f9508ae3c2ad46290358630afb34db04eede0a4' - ], - [ - '1624d84780732860ce1c78fcbfefe08b2b29823db913f6493975ba0ff4847610', - '68651cf9b6da903e0914448c6cd9d4ca896878f5282be4c8cc06e2a404078575' - ], - [ - '733ce80da955a8a26902c95633e62a985192474b5af207da6df7b4fd5fc61cd4', - 'f5435a2bd2badf7d485a4d8b8db9fcce3e1ef8e0201e4578c54673bc1dc5ea1d' - ], - [ - '15d9441254945064cf1a1c33bbd3b49f8966c5092171e699ef258dfab81c045c', - 'd56eb30b69463e7234f5137b73b84177434800bacebfc685fc37bbe9efe4070d' - ], - [ - 'a1d0fcf2ec9de675b612136e5ce70d271c21417c9d2b8aaaac138599d0717940', - 'edd77f50bcb5a3cab2e90737309667f2641462a54070f3d519212d39c197a629' - ], - [ - 'e22fbe15c0af8ccc5780c0735f84dbe9a790badee8245c06c7ca37331cb36980', - 'a855babad5cd60c88b430a69f53a1a7a38289154964799be43d06d77d31da06' - ], - [ - '311091dd9860e8e20ee13473c1155f5f69635e394704eaa74009452246cfa9b3', - '66db656f87d1f04fffd1f04788c06830871ec5a64feee685bd80f0b1286d8374' - ], - [ - '34c1fd04d301be89b31c0442d3e6ac24883928b45a9340781867d4232ec2dbdf', - '9414685e97b1b5954bd46f730174136d57f1ceeb487443dc5321857ba73abee' - ], - [ - 'f219ea5d6b54701c1c14de5b557eb42a8d13f3abbcd08affcc2a5e6b049b8d63', - '4cb95957e83d40b0f73af4544cccf6b1f4b08d3c07b27fb8d8c2962a400766d1' - ], - [ - 'd7b8740f74a8fbaab1f683db8f45de26543a5490bca627087236912469a0b448', - 'fa77968128d9c92ee1010f337ad4717eff15db5ed3c049b3411e0315eaa4593b' - ], - [ - '32d31c222f8f6f0ef86f7c98d3a3335ead5bcd32abdd94289fe4d3091aa824bf', - '5f3032f5892156e39ccd3d7915b9e1da2e6dac9e6f26e961118d14b8462e1661' - ], - [ - '7461f371914ab32671045a155d9831ea8793d77cd59592c4340f86cbc18347b5', - '8ec0ba238b96bec0cbdddcae0aa442542eee1ff50c986ea6b39847b3cc092ff6' - ], - [ - 'ee079adb1df1860074356a25aa38206a6d716b2c3e67453d287698bad7b2b2d6', - '8dc2412aafe3be5c4c5f37e0ecc5f9f6a446989af04c4e25ebaac479ec1c8c1e' - ], - [ - '16ec93e447ec83f0467b18302ee620f7e65de331874c9dc72bfd8616ba9da6b5', - '5e4631150e62fb40d0e8c2a7ca5804a39d58186a50e497139626778e25b0674d' - ], - [ - 'eaa5f980c245f6f038978290afa70b6bd8855897f98b6aa485b96065d537bd99', - 'f65f5d3e292c2e0819a528391c994624d784869d7e6ea67fb18041024edc07dc' - ], - [ - '78c9407544ac132692ee1910a02439958ae04877151342ea96c4b6b35a49f51', - 'f3e0319169eb9b85d5404795539a5e68fa1fbd583c064d2462b675f194a3ddb4' - ], - [ - '494f4be219a1a77016dcd838431aea0001cdc8ae7a6fc688726578d9702857a5', - '42242a969283a5f339ba7f075e36ba2af925ce30d767ed6e55f4b031880d562c' - ], - [ - 'a598a8030da6d86c6bc7f2f5144ea549d28211ea58faa70ebf4c1e665c1fe9b5', - '204b5d6f84822c307e4b4a7140737aec23fc63b65b35f86a10026dbd2d864e6b' - ], - [ - 'c41916365abb2b5d09192f5f2dbeafec208f020f12570a184dbadc3e58595997', - '4f14351d0087efa49d245b328984989d5caf9450f34bfc0ed16e96b58fa9913' - ], - [ - '841d6063a586fa475a724604da03bc5b92a2e0d2e0a36acfe4c73a5514742881', - '73867f59c0659e81904f9a1c7543698e62562d6744c169ce7a36de01a8d6154' - ], - [ - '5e95bb399a6971d376026947f89bde2f282b33810928be4ded112ac4d70e20d5', - '39f23f366809085beebfc71181313775a99c9aed7d8ba38b161384c746012865' - ], - [ - '36e4641a53948fd476c39f8a99fd974e5ec07564b5315d8bf99471bca0ef2f66', - 'd2424b1b1abe4eb8164227b085c9aa9456ea13493fd563e06fd51cf5694c78fc' - ], - [ - '336581ea7bfbbb290c191a2f507a41cf5643842170e914faeab27c2c579f726', - 'ead12168595fe1be99252129b6e56b3391f7ab1410cd1e0ef3dcdcabd2fda224' - ], - [ - '8ab89816dadfd6b6a1f2634fcf00ec8403781025ed6890c4849742706bd43ede', - '6fdcef09f2f6d0a044e654aef624136f503d459c3e89845858a47a9129cdd24e' - ], - [ - '1e33f1a746c9c5778133344d9299fcaa20b0938e8acff2544bb40284b8c5fb94', - '60660257dd11b3aa9c8ed618d24edff2306d320f1d03010e33a7d2057f3b3b6' - ], - [ - '85b7c1dcb3cec1b7ee7f30ded79dd20a0ed1f4cc18cbcfcfa410361fd8f08f31', - '3d98a9cdd026dd43f39048f25a8847f4fcafad1895d7a633c6fed3c35e999511' - ], - [ - '29df9fbd8d9e46509275f4b125d6d45d7fbe9a3b878a7af872a2800661ac5f51', - 'b4c4fe99c775a606e2d8862179139ffda61dc861c019e55cd2876eb2a27d84b' - ], - [ - 'a0b1cae06b0a847a3fea6e671aaf8adfdfe58ca2f768105c8082b2e449fce252', - 'ae434102edde0958ec4b19d917a6a28e6b72da1834aff0e650f049503a296cf2' - ], - [ - '4e8ceafb9b3e9a136dc7ff67e840295b499dfb3b2133e4ba113f2e4c0e121e5', - 'cf2174118c8b6d7a4b48f6d534ce5c79422c086a63460502b827ce62a326683c' - ], - [ - 'd24a44e047e19b6f5afb81c7ca2f69080a5076689a010919f42725c2b789a33b', - '6fb8d5591b466f8fc63db50f1c0f1c69013f996887b8244d2cdec417afea8fa3' - ], - [ - 'ea01606a7a6c9cdd249fdfcfacb99584001edd28abbab77b5104e98e8e3b35d4', - '322af4908c7312b0cfbfe369f7a7b3cdb7d4494bc2823700cfd652188a3ea98d' - ], - [ - 'af8addbf2b661c8a6c6328655eb96651252007d8c5ea31be4ad196de8ce2131f', - '6749e67c029b85f52a034eafd096836b2520818680e26ac8f3dfbcdb71749700' - ], - [ - 'e3ae1974566ca06cc516d47e0fb165a674a3dabcfca15e722f0e3450f45889', - '2aeabe7e4531510116217f07bf4d07300de97e4874f81f533420a72eeb0bd6a4' - ], - [ - '591ee355313d99721cf6993ffed1e3e301993ff3ed258802075ea8ced397e246', - 'b0ea558a113c30bea60fc4775460c7901ff0b053d25ca2bdeee98f1a4be5d196' - ], - [ - '11396d55fda54c49f19aa97318d8da61fa8584e47b084945077cf03255b52984', - '998c74a8cd45ac01289d5833a7beb4744ff536b01b257be4c5767bea93ea57a4' - ], - [ - '3c5d2a1ba39c5a1790000738c9e0c40b8dcdfd5468754b6405540157e017aa7a', - 'b2284279995a34e2f9d4de7396fc18b80f9b8b9fdd270f6661f79ca4c81bd257' - ], - [ - 'cc8704b8a60a0defa3a99a7299f2e9c3fbc395afb04ac078425ef8a1793cc030', - 'bdd46039feed17881d1e0862db347f8cf395b74fc4bcdc4e940b74e3ac1f1b13' - ], - [ - 'c533e4f7ea8555aacd9777ac5cad29b97dd4defccc53ee7ea204119b2889b197', - '6f0a256bc5efdf429a2fb6242f1a43a2d9b925bb4a4b3a26bb8e0f45eb596096' - ], - [ - 'c14f8f2ccb27d6f109f6d08d03cc96a69ba8c34eec07bbcf566d48e33da6593', - 'c359d6923bb398f7fd4473e16fe1c28475b740dd098075e6c0e8649113dc3a38' - ], - [ - 'a6cbc3046bc6a450bac24789fa17115a4c9739ed75f8f21ce441f72e0b90e6ef', - '21ae7f4680e889bb130619e2c0f95a360ceb573c70603139862afd617fa9b9f' - ], - [ - '347d6d9a02c48927ebfb86c1359b1caf130a3c0267d11ce6344b39f99d43cc38', - '60ea7f61a353524d1c987f6ecec92f086d565ab687870cb12689ff1e31c74448' - ], - [ - 'da6545d2181db8d983f7dcb375ef5866d47c67b1bf31c8cf855ef7437b72656a', - '49b96715ab6878a79e78f07ce5680c5d6673051b4935bd897fea824b77dc208a' - ], - [ - 'c40747cc9d012cb1a13b8148309c6de7ec25d6945d657146b9d5994b8feb1111', - '5ca560753be2a12fc6de6caf2cb489565db936156b9514e1bb5e83037e0fa2d4' - ], - [ - '4e42c8ec82c99798ccf3a610be870e78338c7f713348bd34c8203ef4037f3502', - '7571d74ee5e0fb92a7a8b33a07783341a5492144cc54bcc40a94473693606437' - ], - [ - '3775ab7089bc6af823aba2e1af70b236d251cadb0c86743287522a1b3b0dedea', - 'be52d107bcfa09d8bcb9736a828cfa7fac8db17bf7a76a2c42ad961409018cf7' - ], - [ - 'cee31cbf7e34ec379d94fb814d3d775ad954595d1314ba8846959e3e82f74e26', - '8fd64a14c06b589c26b947ae2bcf6bfa0149ef0be14ed4d80f448a01c43b1c6d' - ], - [ - 'b4f9eaea09b6917619f6ea6a4eb5464efddb58fd45b1ebefcdc1a01d08b47986', - '39e5c9925b5a54b07433a4f18c61726f8bb131c012ca542eb24a8ac07200682a' - ], - [ - 'd4263dfc3d2df923a0179a48966d30ce84e2515afc3dccc1b77907792ebcc60e', - '62dfaf07a0f78feb30e30d6295853ce189e127760ad6cf7fae164e122a208d54' - ], - [ - '48457524820fa65a4f8d35eb6930857c0032acc0a4a2de422233eeda897612c4', - '25a748ab367979d98733c38a1fa1c2e7dc6cc07db2d60a9ae7a76aaa49bd0f77' - ], - [ - 'dfeeef1881101f2cb11644f3a2afdfc2045e19919152923f367a1767c11cceda', - 'ecfb7056cf1de042f9420bab396793c0c390bde74b4bbdff16a83ae09a9a7517' - ], - [ - '6d7ef6b17543f8373c573f44e1f389835d89bcbc6062ced36c82df83b8fae859', - 'cd450ec335438986dfefa10c57fea9bcc521a0959b2d80bbf74b190dca712d10' - ], - [ - 'e75605d59102a5a2684500d3b991f2e3f3c88b93225547035af25af66e04541f', - 'f5c54754a8f71ee540b9b48728473e314f729ac5308b06938360990e2bfad125' - ], - [ - 'eb98660f4c4dfaa06a2be453d5020bc99a0c2e60abe388457dd43fefb1ed620c', - '6cb9a8876d9cb8520609af3add26cd20a0a7cd8a9411131ce85f44100099223e' - ], - [ - '13e87b027d8514d35939f2e6892b19922154596941888336dc3563e3b8dba942', - 'fef5a3c68059a6dec5d624114bf1e91aac2b9da568d6abeb2570d55646b8adf1' - ], - [ - 'ee163026e9fd6fe017c38f06a5be6fc125424b371ce2708e7bf4491691e5764a', - '1acb250f255dd61c43d94ccc670d0f58f49ae3fa15b96623e5430da0ad6c62b2' - ], - [ - 'b268f5ef9ad51e4d78de3a750c2dc89b1e626d43505867999932e5db33af3d80', - '5f310d4b3c99b9ebb19f77d41c1dee018cf0d34fd4191614003e945a1216e423' - ], - [ - 'ff07f3118a9df035e9fad85eb6c7bfe42b02f01ca99ceea3bf7ffdba93c4750d', - '438136d603e858a3a5c440c38eccbaddc1d2942114e2eddd4740d098ced1f0d8' - ], - [ - '8d8b9855c7c052a34146fd20ffb658bea4b9f69e0d825ebec16e8c3ce2b526a1', - 'cdb559eedc2d79f926baf44fb84ea4d44bcf50fee51d7ceb30e2e7f463036758' - ], - [ - '52db0b5384dfbf05bfa9d472d7ae26dfe4b851ceca91b1eba54263180da32b63', - 'c3b997d050ee5d423ebaf66a6db9f57b3180c902875679de924b69d84a7b375' - ], - [ - 'e62f9490d3d51da6395efd24e80919cc7d0f29c3f3fa48c6fff543becbd43352', - '6d89ad7ba4876b0b22c2ca280c682862f342c8591f1daf5170e07bfd9ccafa7d' - ], - [ - '7f30ea2476b399b4957509c88f77d0191afa2ff5cb7b14fd6d8e7d65aaab1193', - 'ca5ef7d4b231c94c3b15389a5f6311e9daff7bb67b103e9880ef4bff637acaec' - ], - [ - '5098ff1e1d9f14fb46a210fada6c903fef0fb7b4a1dd1d9ac60a0361800b7a00', - '9731141d81fc8f8084d37c6e7542006b3ee1b40d60dfe5362a5b132fd17ddc0' - ], - [ - '32b78c7de9ee512a72895be6b9cbefa6e2f3c4ccce445c96b9f2c81e2778ad58', - 'ee1849f513df71e32efc3896ee28260c73bb80547ae2275ba497237794c8753c' - ], - [ - 'e2cb74fddc8e9fbcd076eef2a7c72b0ce37d50f08269dfc074b581550547a4f7', - 'd3aa2ed71c9dd2247a62df062736eb0baddea9e36122d2be8641abcb005cc4a4' - ], - [ - '8438447566d4d7bedadc299496ab357426009a35f235cb141be0d99cd10ae3a8', - 'c4e1020916980a4da5d01ac5e6ad330734ef0d7906631c4f2390426b2edd791f' - ], - [ - '4162d488b89402039b584c6fc6c308870587d9c46f660b878ab65c82c711d67e', - '67163e903236289f776f22c25fb8a3afc1732f2b84b4e95dbda47ae5a0852649' - ], - [ - '3fad3fa84caf0f34f0f89bfd2dcf54fc175d767aec3e50684f3ba4a4bf5f683d', - 'cd1bc7cb6cc407bb2f0ca647c718a730cf71872e7d0d2a53fa20efcdfe61826' - ], - [ - '674f2600a3007a00568c1a7ce05d0816c1fb84bf1370798f1c69532faeb1a86b', - '299d21f9413f33b3edf43b257004580b70db57da0b182259e09eecc69e0d38a5' - ], - [ - 'd32f4da54ade74abb81b815ad1fb3b263d82d6c692714bcff87d29bd5ee9f08f', - 'f9429e738b8e53b968e99016c059707782e14f4535359d582fc416910b3eea87' - ], - [ - '30e4e670435385556e593657135845d36fbb6931f72b08cb1ed954f1e3ce3ff6', - '462f9bce619898638499350113bbc9b10a878d35da70740dc695a559eb88db7b' - ], - [ - 'be2062003c51cc3004682904330e4dee7f3dcd10b01e580bf1971b04d4cad297', - '62188bc49d61e5428573d48a74e1c655b1c61090905682a0d5558ed72dccb9bc' - ], - [ - '93144423ace3451ed29e0fb9ac2af211cb6e84a601df5993c419859fff5df04a', - '7c10dfb164c3425f5c71a3f9d7992038f1065224f72bb9d1d902a6d13037b47c' - ], - [ - 'b015f8044f5fcbdcf21ca26d6c34fb8197829205c7b7d2a7cb66418c157b112c', - 'ab8c1e086d04e813744a655b2df8d5f83b3cdc6faa3088c1d3aea1454e3a1d5f' - ], - [ - 'd5e9e1da649d97d89e4868117a465a3a4f8a18de57a140d36b3f2af341a21b52', - '4cb04437f391ed73111a13cc1d4dd0db1693465c2240480d8955e8592f27447a' - ], - [ - 'd3ae41047dd7ca065dbf8ed77b992439983005cd72e16d6f996a5316d36966bb', - 'bd1aeb21ad22ebb22a10f0303417c6d964f8cdd7df0aca614b10dc14d125ac46' - ], - [ - '463e2763d885f958fc66cdd22800f0a487197d0a82e377b49f80af87c897b065', - 'bfefacdb0e5d0fd7df3a311a94de062b26b80c61fbc97508b79992671ef7ca7f' - ], - [ - '7985fdfd127c0567c6f53ec1bb63ec3158e597c40bfe747c83cddfc910641917', - '603c12daf3d9862ef2b25fe1de289aed24ed291e0ec6708703a5bd567f32ed03' - ], - [ - '74a1ad6b5f76e39db2dd249410eac7f99e74c59cb83d2d0ed5ff1543da7703e9', - 'cc6157ef18c9c63cd6193d83631bbea0093e0968942e8c33d5737fd790e0db08' - ], - [ - '30682a50703375f602d416664ba19b7fc9bab42c72747463a71d0896b22f6da3', - '553e04f6b018b4fa6c8f39e7f311d3176290d0e0f19ca73f17714d9977a22ff8' - ], - [ - '9e2158f0d7c0d5f26c3791efefa79597654e7a2b2464f52b1ee6c1347769ef57', - '712fcdd1b9053f09003a3481fa7762e9ffd7c8ef35a38509e2fbf2629008373' - ], - [ - '176e26989a43c9cfeba4029c202538c28172e566e3c4fce7322857f3be327d66', - 'ed8cc9d04b29eb877d270b4878dc43c19aefd31f4eee09ee7b47834c1fa4b1c3' - ], - [ - '75d46efea3771e6e68abb89a13ad747ecf1892393dfc4f1b7004788c50374da8', - '9852390a99507679fd0b86fd2b39a868d7efc22151346e1a3ca4726586a6bed8' - ], - [ - '809a20c67d64900ffb698c4c825f6d5f2310fb0451c869345b7319f645605721', - '9e994980d9917e22b76b061927fa04143d096ccc54963e6a5ebfa5f3f8e286c1' - ], - [ - '1b38903a43f7f114ed4500b4eac7083fdefece1cf29c63528d563446f972c180', - '4036edc931a60ae889353f77fd53de4a2708b26b6f5da72ad3394119daf408f9' - ] - ] - } -}; - -var curves_1 = createCommonjsModule(function (module, exports) { - -var curves = exports; - - - - - -var assert = utils_1$1.assert; - -function PresetCurve(options) { - if (options.type === 'short') - this.curve = new curve_1.short(options); - else if (options.type === 'edwards') - this.curve = new curve_1.edwards(options); - else if (options.type === 'mont') - this.curve = new curve_1.mont(options); - else throw new Error('Unknown curve type.'); - this.g = this.curve.g; - this.n = this.curve.n; - this.hash = options.hash; - - assert(this.g.validate(), 'Invalid curve'); - assert(this.g.mul(this.n).isInfinity(), 'Invalid curve, n*G != O'); -} -curves.PresetCurve = PresetCurve; - -function defineCurve(name, options) { - Object.defineProperty(curves, name, { - configurable: true, - enumerable: true, - get: function() { - var curve = new PresetCurve(options); - Object.defineProperty(curves, name, { - configurable: true, - enumerable: true, - value: curve - }); - return curve; - } - }); -} - -defineCurve('p192', { - type: 'short', - prime: 'p192', - p: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff', - a: 'ffffffff ffffffff ffffffff fffffffe ffffffff fffffffc', - b: '64210519 e59c80e7 0fa7e9ab 72243049 feb8deec c146b9b1', - n: 'ffffffff ffffffff ffffffff 99def836 146bc9b1 b4d22831', - hash: hash_1.sha256, - gRed: false, - g: [ - '188da80e b03090f6 7cbf20eb 43a18800 f4ff0afd 82ff1012', - '07192b95 ffc8da78 631011ed 6b24cdd5 73f977a1 1e794811' - ] -}); - -defineCurve('p224', { - type: 'short', - prime: 'p224', - p: 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001', - a: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff fffffffe', - b: 'b4050a85 0c04b3ab f5413256 5044b0b7 d7bfd8ba 270b3943 2355ffb4', - n: 'ffffffff ffffffff ffffffff ffff16a2 e0b8f03e 13dd2945 5c5c2a3d', - hash: hash_1.sha256, - gRed: false, - g: [ - 'b70e0cbd 6bb4bf7f 321390b9 4a03c1d3 56c21122 343280d6 115c1d21', - 'bd376388 b5f723fb 4c22dfe6 cd4375a0 5a074764 44d58199 85007e34' - ] -}); - -defineCurve('p256', { - type: 'short', - prime: null, - p: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff', - a: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff fffffffc', - b: '5ac635d8 aa3a93e7 b3ebbd55 769886bc 651d06b0 cc53b0f6 3bce3c3e 27d2604b', - n: 'ffffffff 00000000 ffffffff ffffffff bce6faad a7179e84 f3b9cac2 fc632551', - hash: hash_1.sha256, - gRed: false, - g: [ - '6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296', - '4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5' - ] -}); - -defineCurve('p384', { - type: 'short', - prime: null, - p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'fffffffe ffffffff 00000000 00000000 ffffffff', - a: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'fffffffe ffffffff 00000000 00000000 fffffffc', - b: 'b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112 0314088f ' + - '5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef', - n: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff c7634d81 ' + - 'f4372ddf 581a0db2 48b0a77a ecec196a ccc52973', - hash: hash_1.sha384, - gRed: false, - g: [ - 'aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98 59f741e0 82542a38 ' + - '5502f25d bf55296c 3a545e38 72760ab7', - '3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c e9da3113 b5f0b8c0 ' + - '0a60b1ce 1d7e819d 7a431d7c 90ea0e5f' - ] -}); - -defineCurve('p521', { - type: 'short', - prime: null, - p: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff ffffffff', - a: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff fffffffc', - b: '00000051 953eb961 8e1c9a1f 929a21a0 b68540ee a2da725b ' + - '99b315f3 b8b48991 8ef109e1 56193951 ec7e937b 1652c0bd ' + - '3bb1bf07 3573df88 3d2c34f1 ef451fd4 6b503f00', - n: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff fffffffa 51868783 bf2f966b 7fcc0148 ' + - 'f709a5d0 3bb5c9b8 899c47ae bb6fb71e 91386409', - hash: hash_1.sha512, - gRed: false, - g: [ - '000000c6 858e06b7 0404e9cd 9e3ecb66 2395b442 9c648139 ' + - '053fb521 f828af60 6b4d3dba a14b5e77 efe75928 fe1dc127 ' + - 'a2ffa8de 3348b3c1 856a429b f97e7e31 c2e5bd66', - '00000118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd9 98f54449 ' + - '579b4468 17afbd17 273e662c 97ee7299 5ef42640 c550b901 ' + - '3fad0761 353c7086 a272c240 88be9476 9fd16650' - ] -}); - -// https://tools.ietf.org/html/rfc7748#section-4.1 -defineCurve('curve25519', { - type: 'mont', - prime: 'p25519', - p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', - a: '76d06', - b: '1', - n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', - cofactor: '8', - hash: hash_1.sha256, - gRed: false, - g: [ - '9' - ] -}); - -defineCurve('ed25519', { - type: 'edwards', - prime: 'p25519', - p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', - a: '-1', - c: '1', - // -121665 * (121666^(-1)) (mod P) - d: '52036cee2b6ffe73 8cc740797779e898 00700a4d4141d8ab 75eb4dca135978a3', - n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', - cofactor: '8', - hash: hash_1.sha256, - gRed: false, - g: [ - '216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a', - // 4/5 - '6666666666666666666666666666666666666666666666666666666666666658' - ] -}); - -// https://tools.ietf.org/html/rfc5639#section-3.4 -defineCurve('brainpoolP256r1', { - type: 'short', - prime: null, - p: 'A9FB57DB A1EEA9BC 3E660A90 9D838D72 6E3BF623 D5262028 2013481D 1F6E5377', - a: '7D5A0975 FC2C3057 EEF67530 417AFFE7 FB8055C1 26DC5C6C E94A4B44 F330B5D9', - b: '26DC5C6C E94A4B44 F330B5D9 BBD77CBF 95841629 5CF7E1CE 6BCCDC18 FF8C07B6', - n: 'A9FB57DB A1EEA9BC 3E660A90 9D838D71 8C397AA3 B561A6F7 901E0E82 974856A7', - hash: hash_1.sha256, // or 384, or 512 - gRed: false, - g: [ - '8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262', - '547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997' - ] -}); - -// https://tools.ietf.org/html/rfc5639#section-3.6 -defineCurve('brainpoolP384r1', { - type: 'short', - prime: null, - p: '8CB91E82 A3386D28 0F5D6F7E 50E641DF 152F7109 ED5456B4 12B1DA19 7FB71123' + - 'ACD3A729 901D1A71 87470013 3107EC53', - a: '7BC382C6 3D8C150C 3C72080A CE05AFA0 C2BEA28E 4FB22787 139165EF BA91F90F' + - '8AA5814A 503AD4EB 04A8C7DD 22CE2826', - b: '04A8C7DD 22CE2826 8B39B554 16F0447C 2FB77DE1 07DCD2A6 2E880EA5 3EEB62D5' + - '7CB43902 95DBC994 3AB78696 FA504C11', - n: '8CB91E82 A3386D28 0F5D6F7E 50E641DF 152F7109 ED5456B3 1F166E6C AC0425A7' + - 'CF3AB6AF 6B7FC310 3B883202 E9046565', - hash: hash_1.sha384, // or 512 - gRed: false, - g: [ - '1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10' + - 'E8E826E03436D646AAEF87B2E247D4AF1E', - '8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129' + - '280E4646217791811142820341263C5315' - ] -}); - -// https://tools.ietf.org/html/rfc5639#section-3.7 -defineCurve('brainpoolP512r1', { - type: 'short', - prime: null, - p: 'AADD9DB8 DBE9C48B 3FD4E6AE 33C9FC07 CB308DB3 B3C9D20E D6639CCA 70330871' + - '7D4D9B00 9BC66842 AECDA12A E6A380E6 2881FF2F 2D82C685 28AA6056 583A48F3', - a: '7830A331 8B603B89 E2327145 AC234CC5 94CBDD8D 3DF91610 A83441CA EA9863BC' + - '2DED5D5A A8253AA1 0A2EF1C9 8B9AC8B5 7F1117A7 2BF2C7B9 E7C1AC4D 77FC94CA', - b: '3DF91610 A83441CA EA9863BC 2DED5D5A A8253AA1 0A2EF1C9 8B9AC8B5 7F1117A7' + - '2BF2C7B9 E7C1AC4D 77FC94CA DC083E67 984050B7 5EBAE5DD 2809BD63 8016F723', - n: 'AADD9DB8 DBE9C48B 3FD4E6AE 33C9FC07 CB308DB3 B3C9D20E D6639CCA 70330870' + - '553E5C41 4CA92619 41866119 7FAC1047 1DB1D381 085DDADD B5879682 9CA90069', - hash: hash_1.sha512, - gRed: false, - g: [ - '81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D009' + - '8EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822', - '7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F81' + - '11B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892' - ] -}); - -// https://en.bitcoin.it/wiki/Secp256k1 -var pre; -try { - pre = secp256k1; -} catch (e) { - pre = undefined; -} - -defineCurve('secp256k1', { - type: 'short', - prime: 'k256', - p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f', - a: '0', - b: '7', - n: 'ffffffff ffffffff ffffffff fffffffe baaedce6 af48a03b bfd25e8c d0364141', - h: '1', - hash: hash_1.sha256, - - // Precomputed endomorphism - beta: '7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee', - lambda: '5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72', - basis: [ - { - a: '3086d221a7d46bcde86c90e49284eb15', - b: '-e4437ed6010e88286f547fa90abfe4c3' - }, - { - a: '114ca50f7a8e2f3f657c1108d9d44cfd8', - b: '3086d221a7d46bcde86c90e49284eb15' - } - ], - - gRed: false, - g: [ - '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', - '483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', - pre - ] -}); -}); - -function HmacDRBG(options) { - if (!(this instanceof HmacDRBG)) - return new HmacDRBG(options); - this.hash = options.hash; - this.predResist = !!options.predResist; - - this.outLen = this.hash.outSize; - this.minEntropy = options.minEntropy || this.hash.hmacStrength; - - this._reseed = null; - this.reseedInterval = null; - this.K = null; - this.V = null; - - var entropy = utils_1.toArray(options.entropy, options.entropyEnc || 'hex'); - var nonce = utils_1.toArray(options.nonce, options.nonceEnc || 'hex'); - var pers = utils_1.toArray(options.pers, options.persEnc || 'hex'); - minimalisticAssert(entropy.length >= (this.minEntropy / 8), - 'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits'); - this._init(entropy, nonce, pers); -} -var hmacDrbg = HmacDRBG; - -HmacDRBG.prototype._init = function init(entropy, nonce, pers) { - var seed = entropy.concat(nonce).concat(pers); - - this.K = new Array(this.outLen / 8); - this.V = new Array(this.outLen / 8); - for (var i = 0; i < this.V.length; i++) { - this.K[i] = 0x00; - this.V[i] = 0x01; - } - - this._update(seed); - this._reseed = 1; - this.reseedInterval = 0x1000000000000; // 2^48 -}; - -HmacDRBG.prototype._hmac = function hmac() { - return new hash_1.hmac(this.hash, this.K); -}; - -HmacDRBG.prototype._update = function update(seed) { - var kmac = this._hmac() - .update(this.V) - .update([ 0x00 ]); - if (seed) - kmac = kmac.update(seed); - this.K = kmac.digest(); - this.V = this._hmac().update(this.V).digest(); - if (!seed) - return; - - this.K = this._hmac() - .update(this.V) - .update([ 0x01 ]) - .update(seed) - .digest(); - this.V = this._hmac().update(this.V).digest(); -}; - -HmacDRBG.prototype.reseed = function reseed(entropy, entropyEnc, add, addEnc) { - // Optional entropy enc - if (typeof entropyEnc !== 'string') { - addEnc = add; - add = entropyEnc; - entropyEnc = null; - } - - entropy = utils_1.toArray(entropy, entropyEnc); - add = utils_1.toArray(add, addEnc); - - minimalisticAssert(entropy.length >= (this.minEntropy / 8), - 'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits'); - - this._update(entropy.concat(add || [])); - this._reseed = 1; -}; - -HmacDRBG.prototype.generate = function generate(len, enc, add, addEnc) { - if (this._reseed > this.reseedInterval) - throw new Error('Reseed is required'); - - // Optional encoding - if (typeof enc !== 'string') { - addEnc = add; - add = enc; - enc = null; - } - - // Optional additional data - if (add) { - add = utils_1.toArray(add, addEnc || 'hex'); - this._update(add); - } - - var temp = []; - while (temp.length < len) { - this.V = this._hmac().update(this.V).digest(); - temp = temp.concat(this.V); - } - - var res = temp.slice(0, len); - this._update(add); - this._reseed++; - return utils_1.encode(res, enc); -}; - -var assert$5 = utils_1$1.assert; - -function KeyPair(ec, options) { - this.ec = ec; - this.priv = null; - this.pub = null; - - // KeyPair(ec, { priv: ..., pub: ... }) - if (options.priv) - this._importPrivate(options.priv, options.privEnc); - if (options.pub) - this._importPublic(options.pub, options.pubEnc); -} -var key = KeyPair; - -KeyPair.fromPublic = function fromPublic(ec, pub, enc) { - if (pub instanceof KeyPair) - return pub; - - return new KeyPair(ec, { - pub: pub, - pubEnc: enc - }); -}; - -KeyPair.fromPrivate = function fromPrivate(ec, priv, enc) { - if (priv instanceof KeyPair) - return priv; - - return new KeyPair(ec, { - priv: priv, - privEnc: enc - }); -}; - -// TODO: should not validate for X25519 -KeyPair.prototype.validate = function validate() { - var pub = this.getPublic(); - - if (pub.isInfinity()) - return { result: false, reason: 'Invalid public key' }; - if (!pub.validate()) - return { result: false, reason: 'Public key is not a point' }; - if (!pub.mul(this.ec.curve.n).isInfinity()) - return { result: false, reason: 'Public key * N != O' }; - - return { result: true, reason: null }; -}; - -KeyPair.prototype.getPublic = function getPublic(enc, compact) { - if (!this.pub) - this.pub = this.ec.g.mul(this.priv); - - if (!enc) - return this.pub; - - return this.pub.encode(enc, compact); -}; - -KeyPair.prototype.getPrivate = function getPrivate(enc) { - if (enc === 'hex') - return this.priv.toString(16, 2); - else - return this.priv; -}; - -KeyPair.prototype._importPrivate = function _importPrivate(key, enc) { - this.priv = new bn(key, enc || 16); - - // For Curve25519/Curve448 we have a specific procedure. - // TODO Curve448 - if (this.ec.curve.type === 'mont') { - var one = this.ec.curve.one; - var mask = one.ushln(255 - 3).sub(one).ushln(3); - this.priv = this.priv.or(one.ushln(255 - 1)); - this.priv = this.priv.and(mask); - } else - // Ensure that the priv won't be bigger than n, otherwise we may fail - // in fixed multiplication method - this.priv = this.priv.umod(this.ec.curve.n); -}; - -KeyPair.prototype._importPublic = function _importPublic(key, enc) { - if (key.x || key.y) { - // Montgomery points only have an `x` coordinate. - // Weierstrass/Edwards points on the other hand have both `x` and - // `y` coordinates. - if (this.ec.curve.type === 'mont') { - assert$5(key.x, 'Need x coordinate'); - } else if (this.ec.curve.type === 'short' || - this.ec.curve.type === 'edwards') { - assert$5(key.x && key.y, 'Need both x and y coordinate'); - } - this.pub = this.ec.curve.point(key.x, key.y); - return; - } - this.pub = this.ec.curve.decodePoint(key, enc); -}; - -// ECDH -KeyPair.prototype.derive = function derive(pub) { - return pub.mul(this.priv).getX(); -}; - -// ECDSA -KeyPair.prototype.sign = function sign(msg, enc, options) { - return this.ec.sign(msg, this, enc, options); -}; - -KeyPair.prototype.verify = function verify(msg, signature) { - return this.ec.verify(msg, signature, this); -}; - -KeyPair.prototype.inspect = function inspect() { - return ''; -}; - -var assert$6 = utils_1$1.assert; - -function Signature$1(options, enc) { - if (options instanceof Signature$1) - return options; - - if (this._importDER(options, enc)) - return; - - assert$6(options.r && options.s, 'Signature without r or s'); - this.r = new bn(options.r, 16); - this.s = new bn(options.s, 16); - if (options.recoveryParam === undefined) - this.recoveryParam = null; - else - this.recoveryParam = options.recoveryParam; -} -var signature$1 = Signature$1; - -function Position() { - this.place = 0; -} - -function getLength(buf, p) { - var initial = buf[p.place++]; - if (!(initial & 0x80)) { - return initial; - } - var octetLen = initial & 0xf; - var val = 0; - for (var i = 0, off = p.place; i < octetLen; i++, off++) { - val <<= 8; - val |= buf[off]; - } - p.place = off; - return val; -} - -function rmPadding(buf) { - var i = 0; - var len = buf.length - 1; - while (!buf[i] && !(buf[i + 1] & 0x80) && i < len) { - i++; - } - if (i === 0) { - return buf; - } - return buf.slice(i); -} - -Signature$1.prototype._importDER = function _importDER(data, enc) { - data = utils_1$1.toArray(data, enc); - var p = new Position(); - if (data[p.place++] !== 0x30) { - return false; - } - var len = getLength(data, p); - if ((len + p.place) !== data.length) { - return false; - } - if (data[p.place++] !== 0x02) { - return false; - } - var rlen = getLength(data, p); - var r = data.slice(p.place, rlen + p.place); - p.place += rlen; - if (data[p.place++] !== 0x02) { - return false; - } - var slen = getLength(data, p); - if (data.length !== slen + p.place) { - return false; - } - var s = data.slice(p.place, slen + p.place); - if (r[0] === 0 && (r[1] & 0x80)) { - r = r.slice(1); - } - if (s[0] === 0 && (s[1] & 0x80)) { - s = s.slice(1); - } - - this.r = new bn(r); - this.s = new bn(s); - this.recoveryParam = null; - - return true; -}; - -function constructLength(arr, len) { - if (len < 0x80) { - arr.push(len); - return; - } - var octets = 1 + (Math.log(len) / Math.LN2 >>> 3); - arr.push(octets | 0x80); - while (--octets) { - arr.push((len >>> (octets << 3)) & 0xff); - } - arr.push(len); -} - -Signature$1.prototype.toDER = function toDER(enc) { - var r = this.r.toArray(); - var s = this.s.toArray(); - - // Pad values - if (r[0] & 0x80) - r = [ 0 ].concat(r); - // Pad values - if (s[0] & 0x80) - s = [ 0 ].concat(s); - - r = rmPadding(r); - s = rmPadding(s); - - while (!s[0] && !(s[1] & 0x80)) { - s = s.slice(1); - } - var arr = [ 0x02 ]; - constructLength(arr, r.length); - arr = arr.concat(r); - arr.push(0x02); - constructLength(arr, s.length); - var backHalf = arr.concat(s); - var res = [ 0x30 ]; - constructLength(res, backHalf.length); - res = res.concat(backHalf); - return utils_1$1.encode(res, enc); -}; - -var assert$7 = utils_1$1.assert; - - - - -function EC(options) { - if (!(this instanceof EC)) - return new EC(options); - - // Shortcut `elliptic.ec(curve-name)` - if (typeof options === 'string') { - assert$7(curves_1.hasOwnProperty(options), 'Unknown curve ' + options); - - options = curves_1[options]; - } - - // Shortcut for `elliptic.ec(elliptic.curves.curveName)` - if (options instanceof curves_1.PresetCurve) - options = { curve: options }; - - this.curve = options.curve.curve; - this.n = this.curve.n; - this.nh = this.n.ushrn(1); - this.g = this.curve.g; - - // Point on curve - this.g = options.curve.g; - this.g.precompute(options.curve.n.bitLength() + 1); - - // Hash function for DRBG - this.hash = options.hash || options.curve.hash; -} -var ec = EC; - -EC.prototype.keyPair = function keyPair(options) { - return new key(this, options); -}; - -EC.prototype.keyFromPrivate = function keyFromPrivate(priv, enc) { - return key.fromPrivate(this, priv, enc); -}; - -EC.prototype.keyFromPublic = function keyFromPublic(pub, enc) { - return key.fromPublic(this, pub, enc); -}; - -EC.prototype.genKeyPair = function genKeyPair(options) { - if (!options) - options = {}; - - // Instantiate Hmac_DRBG - var drbg = new hmacDrbg({ - hash: this.hash, - pers: options.pers, - persEnc: options.persEnc || 'utf8', - entropy: options.entropy || brorand(this.hash.hmacStrength), - entropyEnc: options.entropy && options.entropyEnc || 'utf8', - nonce: this.n.toArray() - }); - - // Key generation for curve25519 is simpler - if (this.curve.type === 'mont') { - var priv = new bn(drbg.generate(32)); - return this.keyFromPrivate(priv); - } - - var bytes = this.n.byteLength(); - var ns2 = this.n.sub(new bn(2)); - do { - var priv = new bn(drbg.generate(bytes)); - if (priv.cmp(ns2) > 0) - continue; - - priv.iaddn(1); - return this.keyFromPrivate(priv); - } while (true); -}; - -EC.prototype._truncateToN = function truncateToN(msg, truncOnly, bitSize) { - bitSize = bitSize || msg.byteLength() * 8; - var delta = bitSize - this.n.bitLength(); - if (delta > 0) - msg = msg.ushrn(delta); - if (!truncOnly && msg.cmp(this.n) >= 0) - return msg.sub(this.n); - else - return msg; -}; - -EC.prototype.truncateMsg = function truncateMSG(msg) { - // Bit size is only determined correctly for Uint8Arrays and hex strings - var bitSize; - if (msg instanceof Uint8Array) { - bitSize = msg.byteLength * 8; - msg = this._truncateToN(new bn(msg, 16), false, bitSize); - } else if (typeof msg === 'string') { - bitSize = msg.length * 4; - msg = this._truncateToN(new bn(msg, 16), false, bitSize); - } else { - msg = this._truncateToN(new bn(msg, 16)); - } - return msg; -}; - -EC.prototype.sign = function sign(msg, key, enc, options) { - if (typeof enc === 'object') { - options = enc; - enc = null; - } - if (!options) - options = {}; - - key = this.keyFromPrivate(key, enc); - msg = this.truncateMsg(msg); - - // Zero-extend key to provide enough entropy - var bytes = this.n.byteLength(); - var bkey = key.getPrivate().toArray('be', bytes); - - // Zero-extend nonce to have the same byte size as N - var nonce = msg.toArray('be', bytes); - - // Instantiate Hmac_DRBG - var drbg = new hmacDrbg({ - hash: this.hash, - entropy: bkey, - nonce: nonce, - pers: options.pers, - persEnc: options.persEnc || 'utf8' - }); - - // Number of bytes to generate - var ns1 = this.n.sub(new bn(1)); - - for (var iter = 0; true; iter++) { - var k = options.k ? - options.k(iter) : - new bn(drbg.generate(this.n.byteLength())); - k = this._truncateToN(k, true); - if (k.cmpn(1) <= 0 || k.cmp(ns1) >= 0) - continue; - - var kp = this.g.mul(k); - if (kp.isInfinity()) - continue; - - var kpX = kp.getX(); - var r = kpX.umod(this.n); - if (r.cmpn(0) === 0) - continue; - - var s = k.invm(this.n).mul(r.mul(key.getPrivate()).iadd(msg)); - s = s.umod(this.n); - if (s.cmpn(0) === 0) - continue; - - var recoveryParam = (kp.getY().isOdd() ? 1 : 0) | - (kpX.cmp(r) !== 0 ? 2 : 0); - - // Use complement of `s`, if it is > `n / 2` - if (options.canonical && s.cmp(this.nh) > 0) { - s = this.n.sub(s); - recoveryParam ^= 1; - } - - return new signature$1({ r: r, s: s, recoveryParam: recoveryParam }); - } -}; - -EC.prototype.verify = function verify(msg, signature, key, enc) { - key = this.keyFromPublic(key, enc); - signature = new signature$1(signature, 'hex'); - // Fallback to the old code - var ret = this._verify(this.truncateMsg(msg), signature, key) || - this._verify(this._truncateToN(new bn(msg, 16)), signature, key); - return ret; -}; - -EC.prototype._verify = function _verify(msg, signature, key) { - // Perform primitive values validation - var r = signature.r; - var s = signature.s; - if (r.cmpn(1) < 0 || r.cmp(this.n) >= 0) - return false; - if (s.cmpn(1) < 0 || s.cmp(this.n) >= 0) - return false; - - // Validate signature - var sinv = s.invm(this.n); - var u1 = sinv.mul(msg).umod(this.n); - var u2 = sinv.mul(r).umod(this.n); - - if (!this.curve._maxwellTrick) { - var p = this.g.mulAdd(u1, key.getPublic(), u2); - if (p.isInfinity()) - return false; - - return p.getX().umod(this.n).cmp(r) === 0; - } - - // NOTE: Greg Maxwell's trick, inspired by: - // https://git.io/vad3K - - var p = this.g.jmulAdd(u1, key.getPublic(), u2); - if (p.isInfinity()) - return false; - - // Compare `p.x` of Jacobian point with `r`, - // this will do `p.x == r * p.z^2` instead of multiplying `p.x` by the - // inverse of `p.z^2` - return p.eqXToP(r); -}; - -EC.prototype.recoverPubKey = function(msg, signature, j, enc) { - assert$7((3 & j) === j, 'The recovery param is more than two bits'); - signature = new signature$1(signature, enc); - - var n = this.n; - var e = new bn(msg); - var r = signature.r; - var s = signature.s; - - // A set LSB signifies that the y-coordinate is odd - var isYOdd = j & 1; - var isSecondKey = j >> 1; - if (r.cmp(this.curve.p.umod(this.curve.n)) >= 0 && isSecondKey) - throw new Error('Unable to find sencond key candinate'); - - // 1.1. Let x = r + jn. - if (isSecondKey) - r = this.curve.pointFromX(r.add(this.curve.n), isYOdd); - else - r = this.curve.pointFromX(r, isYOdd); - - var rInv = signature.r.invm(n); - var s1 = n.sub(e).mul(rInv).umod(n); - var s2 = s.mul(rInv).umod(n); - - // 1.6.1 Compute Q = r^-1 (sR - eG) - // Q = r^-1 (sR + -eG) - return this.g.mulAdd(s1, r, s2); -}; - -EC.prototype.getKeyRecoveryParam = function(e, signature, Q, enc) { - signature = new signature$1(signature, enc); - if (signature.recoveryParam !== null) - return signature.recoveryParam; - - for (var i = 0; i < 4; i++) { - var Qprime; - try { - Qprime = this.recoverPubKey(e, signature, i); - } catch (e) { - continue; - } - - if (Qprime.eq(Q)) - return i; - } - throw new Error('Unable to find valid recovery factor'); -}; - -var assert$8 = utils_1$1.assert; -var parseBytes = utils_1$1.parseBytes; -var cachedProperty = utils_1$1.cachedProperty; - -/** -* @param {EDDSA} eddsa - instance -* @param {Object} params - public/private key parameters -* -* @param {Array} [params.secret] - secret seed bytes -* @param {Point} [params.pub] - public key point (aka `A` in eddsa terms) -* @param {Array} [params.pub] - public key point encoded as bytes -* -*/ -function KeyPair$1(eddsa, params) { - this.eddsa = eddsa; - if (params.hasOwnProperty('secret')) - this._secret = parseBytes(params.secret); - if (eddsa.isPoint(params.pub)) - this._pub = params.pub; - else { - this._pubBytes = parseBytes(params.pub); - if (this._pubBytes && this._pubBytes.length === 33 && - this._pubBytes[0] === 0x40) - this._pubBytes = this._pubBytes.slice(1, 33); - if (this._pubBytes && this._pubBytes.length !== 32) - throw new Error('Unknown point compression format'); - } -} - -KeyPair$1.fromPublic = function fromPublic(eddsa, pub) { - if (pub instanceof KeyPair$1) - return pub; - return new KeyPair$1(eddsa, { pub: pub }); -}; - -KeyPair$1.fromSecret = function fromSecret(eddsa, secret) { - if (secret instanceof KeyPair$1) - return secret; - return new KeyPair$1(eddsa, { secret: secret }); -}; - -KeyPair$1.prototype.secret = function secret() { - return this._secret; -}; - -cachedProperty(KeyPair$1, 'pubBytes', function pubBytes() { - return this.eddsa.encodePoint(this.pub()); -}); - -cachedProperty(KeyPair$1, 'pub', function pub() { - if (this._pubBytes) - return this.eddsa.decodePoint(this._pubBytes); - return this.eddsa.g.mul(this.priv()); -}); - -cachedProperty(KeyPair$1, 'privBytes', function privBytes() { - var eddsa = this.eddsa; - var hash = this.hash(); - var lastIx = eddsa.encodingLength - 1; - - // https://tools.ietf.org/html/rfc8032#section-5.1.5 - var a = hash.slice(0, eddsa.encodingLength); - a[0] &= 248; - a[lastIx] &= 127; - a[lastIx] |= 64; - - return a; -}); - -cachedProperty(KeyPair$1, 'priv', function priv() { - return this.eddsa.decodeInt(this.privBytes()); -}); - -cachedProperty(KeyPair$1, 'hash', function hash() { - return this.eddsa.hash().update(this.secret()).digest(); -}); - -cachedProperty(KeyPair$1, 'messagePrefix', function messagePrefix() { - return this.hash().slice(this.eddsa.encodingLength); -}); - -KeyPair$1.prototype.sign = function sign(message) { - assert$8(this._secret, 'KeyPair can only verify'); - return this.eddsa.sign(message, this); -}; - -KeyPair$1.prototype.verify = function verify(message, sig) { - return this.eddsa.verify(message, sig, this); -}; - -KeyPair$1.prototype.getSecret = function getSecret(enc) { - assert$8(this._secret, 'KeyPair is public only'); - return utils_1$1.encode(this.secret(), enc); -}; - -KeyPair$1.prototype.getPublic = function getPublic(enc, compact) { - return utils_1$1.encode((compact ? [ 0x40 ] : []).concat(this.pubBytes()), enc); -}; - -var key$1 = KeyPair$1; - -var assert$9 = utils_1$1.assert; -var cachedProperty$1 = utils_1$1.cachedProperty; -var parseBytes$1 = utils_1$1.parseBytes; - -/** -* @param {EDDSA} eddsa - eddsa instance -* @param {Array|Object} sig - -* @param {Array|Point} [sig.R] - R point as Point or bytes -* @param {Array|bn} [sig.S] - S scalar as bn or bytes -* @param {Array} [sig.Rencoded] - R point encoded -* @param {Array} [sig.Sencoded] - S scalar encoded -*/ -function Signature$2(eddsa, sig) { - this.eddsa = eddsa; - - if (typeof sig !== 'object') - sig = parseBytes$1(sig); - - if (Array.isArray(sig)) { - sig = { - R: sig.slice(0, eddsa.encodingLength), - S: sig.slice(eddsa.encodingLength) - }; - } - - assert$9(sig.R && sig.S, 'Signature without R or S'); - - if (eddsa.isPoint(sig.R)) - this._R = sig.R; - if (sig.S instanceof bn) - this._S = sig.S; - - this._Rencoded = Array.isArray(sig.R) ? sig.R : sig.Rencoded; - this._Sencoded = Array.isArray(sig.S) ? sig.S : sig.Sencoded; -} - -cachedProperty$1(Signature$2, 'S', function S() { - return this.eddsa.decodeInt(this.Sencoded()); -}); - -cachedProperty$1(Signature$2, 'R', function R() { - return this.eddsa.decodePoint(this.Rencoded()); -}); - -cachedProperty$1(Signature$2, 'Rencoded', function Rencoded() { - return this.eddsa.encodePoint(this.R()); -}); - -cachedProperty$1(Signature$2, 'Sencoded', function Sencoded() { - return this.eddsa.encodeInt(this.S()); -}); - -Signature$2.prototype.toBytes = function toBytes() { - return this.Rencoded().concat(this.Sencoded()); -}; - -Signature$2.prototype.toHex = function toHex() { - return utils_1$1.encode(this.toBytes(), 'hex').toUpperCase(); -}; - -var signature$2 = Signature$2; - -var assert$a = utils_1$1.assert; -var parseBytes$2 = utils_1$1.parseBytes; - - - -function EDDSA(curve) { - assert$a(curve === 'ed25519', 'only tested with ed25519 so far'); - - if (!(this instanceof EDDSA)) - return new EDDSA(curve); - - var curve = curves_1[curve].curve; - this.curve = curve; - this.g = curve.g; - this.g.precompute(curve.n.bitLength() + 1); - - this.pointClass = curve.point().constructor; - this.encodingLength = Math.ceil(curve.n.bitLength() / 8); - this.hash = hash_1.sha512; -} - -var eddsa$1 = EDDSA; - -/** -* @param {Array|String} message - message bytes -* @param {Array|String|KeyPair} secret - secret bytes or a keypair -* @returns {Signature} - signature -*/ -EDDSA.prototype.sign = function sign(message, secret) { - message = parseBytes$2(message); - var key = this.keyFromSecret(secret); - var r = this.hashInt(key.messagePrefix(), message); - var R = this.g.mul(r); - var Rencoded = this.encodePoint(R); - var s_ = this.hashInt(Rencoded, key.pubBytes(), message) - .mul(key.priv()); - var S = r.add(s_).umod(this.curve.n); - return this.makeSignature({ R: R, S: S, Rencoded: Rencoded }); -}; - -/** -* @param {Array} message - message bytes -* @param {Array|String|Signature} sig - sig bytes -* @param {Array|String|Point|KeyPair} pub - public key -* @returns {Boolean} - true if public key matches sig of message -*/ -EDDSA.prototype.verify = function verify(message, sig, pub) { - message = parseBytes$2(message); - sig = this.makeSignature(sig); - var key = this.keyFromPublic(pub); - var h = this.hashInt(sig.Rencoded(), key.pubBytes(), message); - var SG = this.g.mul(sig.S()); - var RplusAh = sig.R().add(key.pub().mul(h)); - return RplusAh.eq(SG); -}; - -EDDSA.prototype.hashInt = function hashInt() { - var hash = this.hash(); - for (var i = 0; i < arguments.length; i++) - hash.update(arguments[i]); - return utils_1$1.intFromLE(hash.digest()).umod(this.curve.n); -}; - -EDDSA.prototype.keyPair = function keyPair(options) { - return new key$1(this, options); -}; - -EDDSA.prototype.keyFromPublic = function keyFromPublic(pub) { - return key$1.fromPublic(this, pub); -}; - -EDDSA.prototype.keyFromSecret = function keyFromSecret(secret) { - return key$1.fromSecret(this, secret); -}; - -EDDSA.prototype.genKeyPair = function genKeyPair(options) { - if (!options) - options = {}; - - // Instantiate Hmac_DRBG - var drbg = new hmacDrbg({ - hash: this.hash, - pers: options.pers, - persEnc: options.persEnc || 'utf8', - entropy: options.entropy || brorand(this.hash.hmacStrength), - entropyEnc: options.entropy && options.entropyEnc || 'utf8', - nonce: this.curve.n.toArray() - }); - - return this.keyFromSecret(drbg.generate(32)); -}; - -EDDSA.prototype.makeSignature = function makeSignature(sig) { - if (sig instanceof signature$2) - return sig; - return new signature$2(this, sig); -}; - -/** -* * https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03#section-5.2 -* -* EDDSA defines methods for encoding and decoding points and integers. These are -* helper convenience methods, that pass along to utility functions implied -* parameters. -* -*/ -EDDSA.prototype.encodePoint = function encodePoint(point) { - var enc = point.getY().toArray('le', this.encodingLength); - enc[this.encodingLength - 1] |= point.getX().isOdd() ? 0x80 : 0; - return enc; -}; - -EDDSA.prototype.decodePoint = function decodePoint(bytes) { - bytes = utils_1$1.parseBytes(bytes); - - var lastIx = bytes.length - 1; - var normed = bytes.slice(0, lastIx).concat(bytes[lastIx] & ~0x80); - var xIsOdd = (bytes[lastIx] & 0x80) !== 0; - - var y = utils_1$1.intFromLE(normed); - return this.curve.pointFromY(y, xIsOdd); -}; - -EDDSA.prototype.encodeInt = function encodeInt(num) { - return num.toArray('le', this.encodingLength); -}; - -EDDSA.prototype.decodeInt = function decodeInt(bytes) { - return utils_1$1.intFromLE(bytes); -}; - -EDDSA.prototype.isPoint = function isPoint(val) { - return val instanceof this.pointClass; -}; - -var elliptic_1 = createCommonjsModule(function (module, exports) { - -var elliptic = exports; - -elliptic.utils = utils_1$1; -elliptic.rand = brorand; -elliptic.curve = curve_1; -elliptic.curves = curves_1; - -// Protocols -elliptic.ec = ec; -elliptic.eddsa = eddsa$1; -}); - -var elliptic$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - 'default': elliptic_1, - __moduleExports: elliptic_1 -}); - -exports.AEADEncryptedDataPacket = AEADEncryptedDataPacket; -exports.CleartextMessage = CleartextMessage; -exports.CompressedDataPacket = CompressedDataPacket; -exports.LiteralDataPacket = LiteralDataPacket; -exports.MarkerPacket = MarkerPacket; -exports.Message = Message; -exports.OnePassSignaturePacket = OnePassSignaturePacket; -exports.PacketList = PacketList; -exports.PrivateKey = PrivateKey; -exports.PublicKey = PublicKey; -exports.PublicKeyEncryptedSessionKeyPacket = PublicKeyEncryptedSessionKeyPacket; -exports.PublicKeyPacket = PublicKeyPacket; -exports.PublicSubkeyPacket = PublicSubkeyPacket; -exports.SecretKeyPacket = SecretKeyPacket; -exports.SecretSubkeyPacket = SecretSubkeyPacket; -exports.Signature = Signature; -exports.SignaturePacket = SignaturePacket; -exports.Subkey = Subkey; -exports.SymEncryptedIntegrityProtectedDataPacket = SymEncryptedIntegrityProtectedDataPacket; -exports.SymEncryptedSessionKeyPacket = SymEncryptedSessionKeyPacket; -exports.SymmetricallyEncryptedDataPacket = SymmetricallyEncryptedDataPacket; -exports.TrustPacket = TrustPacket; -exports.UserAttributePacket = UserAttributePacket; -exports.UserIDPacket = UserIDPacket; -exports.armor = armor; -exports.config = defaultConfig; -exports.createCleartextMessage = createCleartextMessage; -exports.createMessage = createMessage; -exports.decrypt = decrypt$4; -exports.decryptKey = decryptKey; -exports.decryptSessionKeys = decryptSessionKeys; -exports.encrypt = encrypt$4; -exports.encryptKey = encryptKey; -exports.encryptSessionKey = encryptSessionKey; -exports.enums = enums; -exports.generateKey = generateKey; -exports.generateSessionKey = generateSessionKey$1; -exports.readCleartextMessage = readCleartextMessage; -exports.readKey = readKey; -exports.readKeys = readKeys; -exports.readMessage = readMessage; -exports.readPrivateKey = readPrivateKey; -exports.readPrivateKeys = readPrivateKeys; -exports.readSignature = readSignature; -exports.reformatKey = reformatKey; -exports.revokeKey = revokeKey; -exports.sign = sign$5; -exports.unarmor = unarmor; -exports.verify = verify$5; - -// -----BEGIN ADDED BY FLOWCRYPT---- -exports.Hash = Hash; -exports.Sha1 = Sha1; -exports.Sha256 = Sha256; -exports.readToEnd = readToEnd; -exports.util = util; -// -----END ADDED BY FLOWCRYPT----- diff --git a/Core/source/lib/openpgp/openpgp.js b/Core/source/lib/openpgp/openpgp.js deleted file mode 100644 index 5bf2c1131..000000000 --- a/Core/source/lib/openpgp/openpgp.js +++ /dev/null @@ -1,43537 +0,0 @@ -/*! OpenPGP.js v5.1.0 - 2022-01-24 - this is LGPL licensed code, see LICENSE/our website https://openpgpjs.org/ for more information. */ -var openpgp = (function (exports) { - 'use strict'; - - const globalThis = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; - - const doneWritingPromise = Symbol('doneWritingPromise'); - const doneWritingResolve = Symbol('doneWritingResolve'); - const doneWritingReject = Symbol('doneWritingReject'); - - const readingIndex = Symbol('readingIndex'); - - class ArrayStream extends Array { - constructor() { - super(); - this[doneWritingPromise] = new Promise((resolve, reject) => { - this[doneWritingResolve] = resolve; - this[doneWritingReject] = reject; - }); - this[doneWritingPromise].catch(() => {}); - } - } - - ArrayStream.prototype.getReader = function() { - if (this[readingIndex] === undefined) { - this[readingIndex] = 0; - } - return { - read: async () => { - await this[doneWritingPromise]; - if (this[readingIndex] === this.length) { - return { value: undefined, done: true }; - } - return { value: this[this[readingIndex]++], done: false }; - } - }; - }; - - ArrayStream.prototype.readToEnd = async function(join) { - await this[doneWritingPromise]; - const result = join(this.slice(this[readingIndex])); - this.length = 0; - return result; - }; - - ArrayStream.prototype.clone = function() { - const clone = new ArrayStream(); - clone[doneWritingPromise] = this[doneWritingPromise].then(() => { - clone.push(...this); - }); - return clone; - }; - - /** - * Check whether data is an ArrayStream - * @param {Any} input data to check - * @returns {boolean} - */ - function isArrayStream(input) { - return input && input.getReader && Array.isArray(input); - } - - /** - * A wrapper class over the native WritableStreamDefaultWriter. - * It also lets you "write data to" array streams instead of streams. - * @class - */ - function Writer(input) { - if (!isArrayStream(input)) { - const writer = input.getWriter(); - const releaseLock = writer.releaseLock; - writer.releaseLock = () => { - writer.closed.catch(function() {}); - releaseLock.call(writer); - }; - return writer; - } - this.stream = input; - } - - /** - * Write a chunk of data. - * @returns {Promise} - * @async - */ - Writer.prototype.write = async function(chunk) { - this.stream.push(chunk); - }; - - /** - * Close the stream. - * @returns {Promise} - * @async - */ - Writer.prototype.close = async function() { - this.stream[doneWritingResolve](); - }; - - /** - * Error the stream. - * @returns {Promise} - * @async - */ - Writer.prototype.abort = async function(reason) { - this.stream[doneWritingReject](reason); - return reason; - }; - - /** - * Release the writer's lock. - * @returns {undefined} - * @async - */ - Writer.prototype.releaseLock = function() {}; - - const isNode = typeof globalThis.process === 'object' && - typeof globalThis.process.versions === 'object'; - - const NodeReadableStream = isNode && void('stream').Readable; - - /** - * Check whether data is a Stream, and if so of which type - * @param {Any} input data to check - * @returns {'web'|'ponyfill'|'node'|'array'|'web-like'|false} - */ - function isStream(input) { - if (isArrayStream(input)) { - return 'array'; - } - if (globalThis.ReadableStream && globalThis.ReadableStream.prototype.isPrototypeOf(input)) { - return 'web'; - } - if (ReadableStream && ReadableStream.prototype.isPrototypeOf(input)) { - return 'ponyfill'; - } - if (NodeReadableStream && NodeReadableStream.prototype.isPrototypeOf(input)) { - return 'node'; - } - if (input && input.getReader) { - return 'web-like'; - } - return false; - } - - /** - * Check whether data is a Uint8Array - * @param {Any} input data to check - * @returns {Boolean} - */ - function isUint8Array(input) { - return Uint8Array.prototype.isPrototypeOf(input); - } - - /** - * Concat Uint8Arrays - * @param {Array} Array of Uint8Arrays to concatenate - * @returns {Uint8array} Concatenated array - */ - function concatUint8Array(arrays) { - if (arrays.length === 1) return arrays[0]; - - let totalLength = 0; - for (let i = 0; i < arrays.length; i++) { - if (!isUint8Array(arrays[i])) { - throw new Error('concatUint8Array: Data must be in the form of a Uint8Array'); - } - - totalLength += arrays[i].length; - } - - const result = new Uint8Array(totalLength); - let pos = 0; - arrays.forEach(function (element) { - result.set(element, pos); - pos += element.length; - }); - - return result; - } - - const NodeBuffer = isNode && void('buffer').Buffer; - const NodeReadableStream$1 = isNode && void('stream').Readable; - - /** - * Web / node stream conversion functions - * From https://github.com/gwicke/node-web-streams - */ - - let nodeToWeb; - let webToNode; - - if (NodeReadableStream$1) { - - /** - * Convert a Node Readable Stream to a Web ReadableStream - * @param {Readable} nodeStream - * @returns {ReadableStream} - */ - nodeToWeb = function(nodeStream) { - let canceled = false; - return new ReadableStream({ - start(controller) { - nodeStream.pause(); - nodeStream.on('data', chunk => { - if (canceled) { - return; - } - if (NodeBuffer.isBuffer(chunk)) { - chunk = new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength); - } - controller.enqueue(chunk); - nodeStream.pause(); - }); - nodeStream.on('end', () => { - if (canceled) { - return; - } - controller.close(); - }); - nodeStream.on('error', e => controller.error(e)); - }, - pull() { - nodeStream.resume(); - }, - cancel(reason) { - canceled = true; - nodeStream.destroy(reason); - } - }); - }; - - - class NodeReadable extends NodeReadableStream$1 { - constructor(webStream, options) { - super(options); - this._reader = getReader(webStream); - } - - async _read(size) { - try { - while (true) { - const { done, value } = await this._reader.read(); - if (done) { - this.push(null); - break; - } - if (!this.push(value) || this._cancelling) { - this._reading = false; - break; - } - } - } catch(e) { - this.emit('error', e); - } - } - - _destroy(reason) { - this._reader.cancel(reason); - } - } - - /** - * Convert a Web ReadableStream to a Node Readable Stream - * @param {ReadableStream} webStream - * @param {Object} options - * @returns {Readable} - */ - webToNode = function(webStream, options) { - return new NodeReadable(webStream, options); - }; - - } - - const doneReadingSet = new WeakSet(); - const externalBuffer = Symbol('externalBuffer'); - - /** - * A wrapper class over the native ReadableStreamDefaultReader. - * This additionally implements pushing back data on the stream, which - * lets us implement peeking and a host of convenience functions. - * It also lets you read data other than streams, such as a Uint8Array. - * @class - */ - function Reader(input) { - this.stream = input; - if (input[externalBuffer]) { - this[externalBuffer] = input[externalBuffer].slice(); - } - if (isArrayStream(input)) { - const reader = input.getReader(); - this._read = reader.read.bind(reader); - this._releaseLock = () => {}; - this._cancel = () => {}; - return; - } - let streamType = isStream(input); - if (streamType === 'node') { - input = nodeToWeb(input); - } - if (streamType) { - const reader = input.getReader(); - this._read = reader.read.bind(reader); - this._releaseLock = () => { - reader.closed.catch(function() {}); - reader.releaseLock(); - }; - this._cancel = reader.cancel.bind(reader); - return; - } - let doneReading = false; - this._read = async () => { - if (doneReading || doneReadingSet.has(input)) { - return { value: undefined, done: true }; - } - doneReading = true; - return { value: input, done: false }; - }; - this._releaseLock = () => { - if (doneReading) { - try { - doneReadingSet.add(input); - } catch(e) {} - } - }; - } - - /** - * Read a chunk of data. - * @returns {Promise} Either { done: false, value: Uint8Array | String } or { done: true, value: undefined } - * @async - */ - Reader.prototype.read = async function() { - if (this[externalBuffer] && this[externalBuffer].length) { - const value = this[externalBuffer].shift(); - return { done: false, value }; - } - return this._read(); - }; - - /** - * Allow others to read the stream. - */ - Reader.prototype.releaseLock = function() { - if (this[externalBuffer]) { - this.stream[externalBuffer] = this[externalBuffer]; - } - this._releaseLock(); - }; - - /** - * Cancel the stream. - */ - Reader.prototype.cancel = function(reason) { - return this._cancel(reason); - }; - - /** - * Read up to and including the first \n character. - * @returns {Promise} - * @async - */ - Reader.prototype.readLine = async function() { - let buffer = []; - let returnVal; - while (!returnVal) { - let { done, value } = await this.read(); - value += ''; - if (done) { - if (buffer.length) return concat(buffer); - return; - } - const lineEndIndex = value.indexOf('\n') + 1; - if (lineEndIndex) { - returnVal = concat(buffer.concat(value.substr(0, lineEndIndex))); - buffer = []; - } - if (lineEndIndex !== value.length) { - buffer.push(value.substr(lineEndIndex)); - } - } - this.unshift(...buffer); - return returnVal; - }; - - /** - * Read a single byte/character. - * @returns {Promise} - * @async - */ - Reader.prototype.readByte = async function() { - const { done, value } = await this.read(); - if (done) return; - const byte = value[0]; - this.unshift(slice(value, 1)); - return byte; - }; - - /** - * Read a specific amount of bytes/characters, unless the stream ends before that amount. - * @returns {Promise} - * @async - */ - Reader.prototype.readBytes = async function(length) { - const buffer = []; - let bufferLength = 0; - while (true) { - const { done, value } = await this.read(); - if (done) { - if (buffer.length) return concat(buffer); - return; - } - buffer.push(value); - bufferLength += value.length; - if (bufferLength >= length) { - const bufferConcat = concat(buffer); - this.unshift(slice(bufferConcat, length)); - return slice(bufferConcat, 0, length); - } - } - }; - - /** - * Peek (look ahead) a specific amount of bytes/characters, unless the stream ends before that amount. - * @returns {Promise} - * @async - */ - Reader.prototype.peekBytes = async function(length) { - const bytes = await this.readBytes(length); - this.unshift(bytes); - return bytes; - }; - - /** - * Push data to the front of the stream. - * Data must have been read in the last call to read*. - * @param {...(Uint8Array|String|Undefined)} values - */ - Reader.prototype.unshift = function(...values) { - if (!this[externalBuffer]) { - this[externalBuffer] = []; - } - if ( - values.length === 1 && isUint8Array(values[0]) && - this[externalBuffer].length && values[0].length && - this[externalBuffer][0].byteOffset >= values[0].length - ) { - this[externalBuffer][0] = new Uint8Array( - this[externalBuffer][0].buffer, - this[externalBuffer][0].byteOffset - values[0].length, - this[externalBuffer][0].byteLength + values[0].length - ); - return; - } - this[externalBuffer].unshift(...values.filter(value => value && value.length)); - }; - - /** - * Read the stream to the end and return its contents, concatenated by the join function (defaults to streams.concat). - * @param {Function} join - * @returns {Promise} the return value of join() - * @async - */ - Reader.prototype.readToEnd = async function(join=concat) { - const result = []; - while (true) { - const { done, value } = await this.read(); - if (done) break; - result.push(value); - } - return join(result); - }; - - let { ReadableStream, WritableStream, TransformStream } = globalThis; - - let toPonyfillReadable, toNativeReadable; - - async function loadStreamsPonyfill() { - if (TransformStream) { - return; - } - - const [ponyfill, adapter] = await Promise.all([ - Promise.resolve().then(function () { return ponyfill_es6; }), - Promise.resolve().then(function () { return webStreamsAdapter; }) - ]); - - ({ ReadableStream, WritableStream, TransformStream } = ponyfill); - - const { createReadableStreamWrapper } = adapter; - - if (globalThis.ReadableStream && ReadableStream !== globalThis.ReadableStream) { - toPonyfillReadable = createReadableStreamWrapper(ReadableStream); - toNativeReadable = createReadableStreamWrapper(globalThis.ReadableStream); - } - } - - const NodeBuffer$1 = isNode && void('buffer').Buffer; - - /** - * Convert data to Stream - * @param {ReadableStream|Uint8array|String} input data to convert - * @returns {ReadableStream} Converted data - */ - function toStream(input) { - let streamType = isStream(input); - if (streamType === 'node') { - return nodeToWeb(input); - } - if (streamType === 'web' && toPonyfillReadable) { - return toPonyfillReadable(input); - } - if (streamType) { - return input; - } - return new ReadableStream({ - start(controller) { - controller.enqueue(input); - controller.close(); - } - }); - } - - /** - * Convert data to ArrayStream - * @param {Object} input data to convert - * @returns {ArrayStream} Converted data - */ - function toArrayStream(input) { - if (isStream(input)) { - return input; - } - const stream = new ArrayStream(); - (async () => { - const writer = getWriter(stream); - await writer.write(input); - await writer.close(); - })(); - return stream; - } - - /** - * Concat a list of Uint8Arrays, Strings or Streams - * The caller should not mix Uint8Arrays with Strings, but may mix Streams with non-Streams. - * @param {Array} Array of Uint8Arrays/Strings/Streams to concatenate - * @returns {Uint8array|String|ReadableStream} Concatenated array - */ - function concat(list) { - if (list.some(stream => isStream(stream) && !isArrayStream(stream))) { - return concatStream(list); - } - if (list.some(stream => isArrayStream(stream))) { - return concatArrayStream(list); - } - if (typeof list[0] === 'string') { - return list.join(''); - } - if (NodeBuffer$1 && NodeBuffer$1.isBuffer(list[0])) { - return NodeBuffer$1.concat(list); - } - return concatUint8Array(list); - } - - /** - * Concat a list of Streams - * @param {Array} list Array of Uint8Arrays/Strings/Streams to concatenate - * @returns {ReadableStream} Concatenated list - */ - function concatStream(list) { - list = list.map(toStream); - const transform = transformWithCancel(async function(reason) { - await Promise.all(transforms.map(stream => cancel(stream, reason))); - }); - let prev = Promise.resolve(); - const transforms = list.map((stream, i) => transformPair(stream, (readable, writable) => { - prev = prev.then(() => pipe(readable, transform.writable, { - preventClose: i !== list.length - 1 - })); - return prev; - })); - return transform.readable; - } - - /** - * Concat a list of ArrayStreams - * @param {Array} list Array of Uint8Arrays/Strings/ArrayStreams to concatenate - * @returns {ArrayStream} Concatenated streams - */ - function concatArrayStream(list) { - const result = new ArrayStream(); - let prev = Promise.resolve(); - list.forEach((stream, i) => { - prev = prev.then(() => pipe(stream, result, { - preventClose: i !== list.length - 1 - })); - return prev; - }); - return result; - } - - /** - * Get a Reader - * @param {ReadableStream|Uint8array|String} input - * @returns {Reader} - */ - function getReader(input) { - return new Reader(input); - } - - /** - * Get a Writer - * @param {WritableStream} input - * @returns {Writer} - */ - function getWriter(input) { - return new Writer(input); - } - - /** - * Pipe a readable stream to a writable stream. Don't throw on input stream errors, but forward them to the output stream. - * @param {ReadableStream|Uint8array|String} input - * @param {WritableStream} target - * @param {Object} (optional) options - * @returns {Promise} Promise indicating when piping has finished (input stream closed or errored) - * @async - */ - async function pipe(input, target, { - preventClose = false, - preventAbort = false, - preventCancel = false - } = {}) { - if (isStream(input) && !isArrayStream(input)) { - input = toStream(input); - try { - if (input[externalBuffer]) { - const writer = getWriter(target); - for (let i = 0; i < input[externalBuffer].length; i++) { - await writer.ready; - await writer.write(input[externalBuffer][i]); - } - writer.releaseLock(); - } - await input.pipeTo(target, { - preventClose, - preventAbort, - preventCancel - }); - } catch(e) {} - return; - } - input = toArrayStream(input); - const reader = getReader(input); - const writer = getWriter(target); - try { - while (true) { - await writer.ready; - const { done, value } = await reader.read(); - if (done) { - if (!preventClose) await writer.close(); - break; - } - await writer.write(value); - } - } catch (e) { - if (!preventAbort) await writer.abort(e); - } finally { - reader.releaseLock(); - writer.releaseLock(); - } - } - - /** - * Pipe a readable stream through a transform stream. - * @param {ReadableStream|Uint8array|String} input - * @param {Object} (optional) options - * @returns {ReadableStream} transformed stream - */ - function transformRaw(input, options) { - const transformStream = new TransformStream(options); - pipe(input, transformStream.writable); - return transformStream.readable; - } - - /** - * Create a cancelable TransformStream. - * @param {Function} cancel - * @returns {TransformStream} - */ - function transformWithCancel(cancel) { - let pulled = false; - let backpressureChangePromiseResolve; - let outputController; - return { - readable: new ReadableStream({ - start(controller) { - outputController = controller; - }, - pull() { - if (backpressureChangePromiseResolve) { - backpressureChangePromiseResolve(); - } else { - pulled = true; - } - }, - cancel - }, {highWaterMark: 0}), - writable: new WritableStream({ - write: async function(chunk) { - outputController.enqueue(chunk); - if (!pulled) { - await new Promise(resolve => { - backpressureChangePromiseResolve = resolve; - }); - backpressureChangePromiseResolve = null; - } else { - pulled = false; - } - }, - close: outputController.close.bind(outputController), - abort: outputController.error.bind(outputController) - }) - }; - } - - /** - * Transform a stream using helper functions which are called on each chunk, and on stream close, respectively. - * @param {ReadableStream|Uint8array|String} input - * @param {Function} process - * @param {Function} finish - * @returns {ReadableStream|Uint8array|String} - */ - function transform(input, process = () => undefined, finish = () => undefined) { - if (isArrayStream(input)) { - const output = new ArrayStream(); - (async () => { - const data = await readToEnd(input); - const result1 = process(data); - const result2 = finish(); - let result; - if (result1 !== undefined && result2 !== undefined) result = concat([result1, result2]); - else result = result1 !== undefined ? result1 : result2; - const writer = getWriter(output); - await writer.write(result); - await writer.close(); - })(); - return output; - } - if (isStream(input)) { - return transformRaw(input, { - async transform(value, controller) { - try { - const result = await process(value); - if (result !== undefined) controller.enqueue(result); - } catch(e) { - controller.error(e); - } - }, - async flush(controller) { - try { - const result = await finish(); - if (result !== undefined) controller.enqueue(result); - } catch(e) { - controller.error(e); - } - } - }); - } - const result1 = process(input); - const result2 = finish(); - if (result1 !== undefined && result2 !== undefined) return concat([result1, result2]); - return result1 !== undefined ? result1 : result2; - } - - /** - * Transform a stream using a helper function which is passed a readable and a writable stream. - * This function also maintains the possibility to cancel the input stream, - * and does so on cancelation of the output stream, despite cancelation - * normally being impossible when the input stream is being read from. - * @param {ReadableStream|Uint8array|String} input - * @param {Function} fn - * @returns {ReadableStream} - */ - function transformPair(input, fn) { - if (isStream(input) && !isArrayStream(input)) { - let incomingTransformController; - const incoming = new TransformStream({ - start(controller) { - incomingTransformController = controller; - } - }); - - const pipeDonePromise = pipe(input, incoming.writable); - - const outgoing = transformWithCancel(async function() { - incomingTransformController.error(new Error('Readable side was canceled.')); - await pipeDonePromise; - await new Promise(setTimeout); - }); - fn(incoming.readable, outgoing.writable); - return outgoing.readable; - } - input = toArrayStream(input); - const output = new ArrayStream(); - fn(input, output); - return output; - } - - /** - * Parse a stream using a helper function which is passed a Reader. - * The reader additionally has a remainder() method which returns a - * stream pointing to the remainder of input, and is linked to input - * for cancelation. - * @param {ReadableStream|Uint8array|String} input - * @param {Function} fn - * @returns {Any} the return value of fn() - */ - function parse(input, fn) { - let returnValue; - const transformed = transformPair(input, (readable, writable) => { - const reader = getReader(readable); - reader.remainder = () => { - reader.releaseLock(); - pipe(readable, writable); - return transformed; - }; - returnValue = fn(reader); - }); - return returnValue; - } - - /** - * Tee a Stream for reading it twice. The input stream can no longer be read after tee()ing. - * Reading either of the two returned streams will pull from the input stream. - * The input stream will only be canceled if both of the returned streams are canceled. - * @param {ReadableStream|Uint8array|String} input - * @returns {Array} array containing two copies of input - */ - function tee(input) { - if (isArrayStream(input)) { - throw new Error('ArrayStream cannot be tee()d, use clone() instead'); - } - if (isStream(input)) { - const teed = toStream(input).tee(); - teed[0][externalBuffer] = teed[1][externalBuffer] = input[externalBuffer]; - return teed; - } - return [slice(input), slice(input)]; - } - - /** - * Clone a Stream for reading it twice. The input stream can still be read after clone()ing. - * Reading from the clone will pull from the input stream. - * The input stream will only be canceled if both the clone and the input stream are canceled. - * @param {ReadableStream|Uint8array|String} input - * @returns {ReadableStream|Uint8array|String} cloned input - */ - function clone(input) { - if (isArrayStream(input)) { - return input.clone(); - } - if (isStream(input)) { - const teed = tee(input); - overwrite(input, teed[0]); - return teed[1]; - } - return slice(input); - } - - /** - * Clone a Stream for reading it twice. Data will arrive at the same rate as the input stream is being read. - * Reading from the clone will NOT pull from the input stream. Data only arrives when reading the input stream. - * The input stream will NOT be canceled if the clone is canceled, only if the input stream are canceled. - * If the input stream is canceled, the clone will be errored. - * @param {ReadableStream|Uint8array|String} input - * @returns {ReadableStream|Uint8array|String} cloned input - */ - function passiveClone(input) { - if (isArrayStream(input)) { - return clone(input); - } - if (isStream(input)) { - return new ReadableStream({ - start(controller) { - const transformed = transformPair(input, async (readable, writable) => { - const reader = getReader(readable); - const writer = getWriter(writable); - try { - while (true) { - await writer.ready; - const { done, value } = await reader.read(); - if (done) { - try { controller.close(); } catch(e) {} - await writer.close(); - return; - } - try { controller.enqueue(value); } catch(e) {} - await writer.write(value); - } - } catch(e) { - controller.error(e); - await writer.abort(e); - } - }); - overwrite(input, transformed); - } - }); - } - return slice(input); - } - - /** - * Modify a stream object to point to a different stream object. - * This is used internally by clone() and passiveClone() to provide an abstraction over tee(). - * @param {ReadableStream} input - * @param {ReadableStream} clone - */ - function overwrite(input, clone) { - // Overwrite input.getReader, input.locked, etc to point to clone - Object.entries(Object.getOwnPropertyDescriptors(input.constructor.prototype)).forEach(([name, descriptor]) => { - if (name === 'constructor') { - return; - } - if (descriptor.value) { - descriptor.value = descriptor.value.bind(clone); - } else { - descriptor.get = descriptor.get.bind(clone); - } - Object.defineProperty(input, name, descriptor); - }); - } - - /** - * Return a stream pointing to a part of the input stream. - * @param {ReadableStream|Uint8array|String} input - * @returns {ReadableStream|Uint8array|String} clone - */ - function slice(input, begin=0, end=Infinity) { - if (isArrayStream(input)) { - throw new Error('Not implemented'); - } - if (isStream(input)) { - if (begin >= 0 && end >= 0) { - let bytesRead = 0; - return transformRaw(input, { - transform(value, controller) { - if (bytesRead < end) { - if (bytesRead + value.length >= begin) { - controller.enqueue(slice(value, Math.max(begin - bytesRead, 0), end - bytesRead)); - } - bytesRead += value.length; - } else { - controller.terminate(); - } - } - }); - } - if (begin < 0 && (end < 0 || end === Infinity)) { - let lastBytes = []; - return transform(input, value => { - if (value.length >= -begin) lastBytes = [value]; - else lastBytes.push(value); - }, () => slice(concat(lastBytes), begin, end)); - } - if (begin === 0 && end < 0) { - let lastBytes; - return transform(input, value => { - const returnValue = lastBytes ? concat([lastBytes, value]) : value; - if (returnValue.length >= -end) { - lastBytes = slice(returnValue, end); - return slice(returnValue, begin, end); - } else { - lastBytes = returnValue; - } - }); - } - console.warn(`stream.slice(input, ${begin}, ${end}) not implemented efficiently.`); - return fromAsync(async () => slice(await readToEnd(input), begin, end)); - } - if (input[externalBuffer]) { - input = concat(input[externalBuffer].concat([input])); - } - if (isUint8Array(input) && !(NodeBuffer$1 && NodeBuffer$1.isBuffer(input))) { - if (end === Infinity) end = input.length; - return input.subarray(begin, end); - } - return input.slice(begin, end); - } - - /** - * Read a stream to the end and return its contents, concatenated by the join function (defaults to concat). - * @param {ReadableStream|Uint8array|String} input - * @param {Function} join - * @returns {Promise} the return value of join() - * @async - */ - async function readToEnd(input, join=concat) { - if (isArrayStream(input)) { - return input.readToEnd(join); - } - if (isStream(input)) { - return getReader(input).readToEnd(join); - } - return input; - } - - /** - * Cancel a stream. - * @param {ReadableStream|Uint8array|String} input - * @param {Any} reason - * @returns {Promise} indicates when the stream has been canceled - * @async - */ - async function cancel(input, reason) { - if (isStream(input)) { - if (input.cancel) { - return input.cancel(reason); - } - if (input.destroy) { - input.destroy(reason); - await new Promise(setTimeout); - return reason; - } - } - } - - /** - * Convert an async function to an ArrayStream. When the function returns, its return value is written to the stream. - * @param {Function} fn - * @returns {ArrayStream} - */ - function fromAsync(fn) { - const arrayStream = new ArrayStream(); - (async () => { - const writer = getWriter(arrayStream); - try { - await writer.write(await fn()); - await writer.close(); - } catch (e) { - await writer.abort(e); - } - })(); - return arrayStream; - } - - /* eslint-disable new-cap */ - - /** - * @fileoverview - * BigInteger implementation of basic operations - * that wraps the native BigInt library. - * Operations are not constant time, - * but we try and limit timing leakage where we can - * @module biginteger/native - * @private - */ - - /** - * @private - */ - class BigInteger { - /** - * Get a BigInteger (input must be big endian for strings and arrays) - * @param {Number|String|Uint8Array} n - Value to convert - * @throws {Error} on null or undefined input - */ - constructor(n) { - if (n === undefined) { - throw new Error('Invalid BigInteger input'); - } - - if (n instanceof Uint8Array) { - const bytes = n; - const hex = new Array(bytes.length); - for (let i = 0; i < bytes.length; i++) { - const hexByte = bytes[i].toString(16); - hex[i] = (bytes[i] <= 0xF) ? ('0' + hexByte) : hexByte; - } - this.value = BigInt('0x0' + hex.join('')); - } else { - this.value = BigInt(n); - } - } - - clone() { - return new BigInteger(this.value); - } - - /** - * BigInteger increment in place - */ - iinc() { - this.value++; - return this; - } - - /** - * BigInteger increment - * @returns {BigInteger} this + 1. - */ - inc() { - return this.clone().iinc(); - } - - /** - * BigInteger decrement in place - */ - idec() { - this.value--; - return this; - } - - /** - * BigInteger decrement - * @returns {BigInteger} this - 1. - */ - dec() { - return this.clone().idec(); - } - - /** - * BigInteger addition in place - * @param {BigInteger} x - Value to add - */ - iadd(x) { - this.value += x.value; - return this; - } - - /** - * BigInteger addition - * @param {BigInteger} x - Value to add - * @returns {BigInteger} this + x. - */ - add(x) { - return this.clone().iadd(x); - } - - /** - * BigInteger subtraction in place - * @param {BigInteger} x - Value to subtract - */ - isub(x) { - this.value -= x.value; - return this; - } - - /** - * BigInteger subtraction - * @param {BigInteger} x - Value to subtract - * @returns {BigInteger} this - x. - */ - sub(x) { - return this.clone().isub(x); - } - - /** - * BigInteger multiplication in place - * @param {BigInteger} x - Value to multiply - */ - imul(x) { - this.value *= x.value; - return this; - } - - /** - * BigInteger multiplication - * @param {BigInteger} x - Value to multiply - * @returns {BigInteger} this * x. - */ - mul(x) { - return this.clone().imul(x); - } - - /** - * Compute value modulo m, in place - * @param {BigInteger} m - Modulo - */ - imod(m) { - this.value %= m.value; - if (this.isNegative()) { - this.iadd(m); - } - return this; - } - - /** - * Compute value modulo m - * @param {BigInteger} m - Modulo - * @returns {BigInteger} this mod m. - */ - mod(m) { - return this.clone().imod(m); - } - - /** - * Compute modular exponentiation using square and multiply - * @param {BigInteger} e - Exponent - * @param {BigInteger} n - Modulo - * @returns {BigInteger} this ** e mod n. - */ - modExp(e, n) { - if (n.isZero()) throw Error('Modulo cannot be zero'); - if (n.isOne()) return new BigInteger(0); - if (e.isNegative()) throw Error('Unsopported negative exponent'); - - let exp = e.value; - let x = this.value; - - x %= n.value; - let r = BigInt(1); - while (exp > BigInt(0)) { - const lsb = exp & BigInt(1); - exp >>= BigInt(1); // e / 2 - // Always compute multiplication step, to reduce timing leakage - const rx = (r * x) % n.value; - // Update r only if lsb is 1 (odd exponent) - r = lsb ? rx : r; - x = (x * x) % n.value; // Square - } - return new BigInteger(r); - } - - - /** - * Compute the inverse of this value modulo n - * Note: this and and n must be relatively prime - * @param {BigInteger} n - Modulo - * @returns {BigInteger} x such that this*x = 1 mod n - * @throws {Error} if the inverse does not exist - */ - modInv(n) { - const { gcd, x } = this._egcd(n); - if (!gcd.isOne()) { - throw new Error('Inverse does not exist'); - } - return x.add(n).mod(n); - } - - /** - * Extended Eucleadian algorithm (http://anh.cs.luc.edu/331/notes/xgcd.pdf) - * Given a = this and b, compute (x, y) such that ax + by = gdc(a, b) - * @param {BigInteger} b - Second operand - * @returns {{ gcd, x, y: BigInteger }} - */ - _egcd(b) { - let x = BigInt(0); - let y = BigInt(1); - let xPrev = BigInt(1); - let yPrev = BigInt(0); - - let a = this.value; - b = b.value; - - while (b !== BigInt(0)) { - const q = a / b; - let tmp = x; - x = xPrev - q * x; - xPrev = tmp; - - tmp = y; - y = yPrev - q * y; - yPrev = tmp; - - tmp = b; - b = a % b; - a = tmp; - } - - return { - x: new BigInteger(xPrev), - y: new BigInteger(yPrev), - gcd: new BigInteger(a) - }; - } - - /** - * Compute greatest common divisor between this and n - * @param {BigInteger} b - Operand - * @returns {BigInteger} gcd - */ - gcd(b) { - let a = this.value; - b = b.value; - while (b !== BigInt(0)) { - const tmp = b; - b = a % b; - a = tmp; - } - return new BigInteger(a); - } - - /** - * Shift this to the left by x, in place - * @param {BigInteger} x - Shift value - */ - ileftShift(x) { - this.value <<= x.value; - return this; - } - - /** - * Shift this to the left by x - * @param {BigInteger} x - Shift value - * @returns {BigInteger} this << x. - */ - leftShift(x) { - return this.clone().ileftShift(x); - } - - /** - * Shift this to the right by x, in place - * @param {BigInteger} x - Shift value - */ - irightShift(x) { - this.value >>= x.value; - return this; - } - - /** - * Shift this to the right by x - * @param {BigInteger} x - Shift value - * @returns {BigInteger} this >> x. - */ - rightShift(x) { - return this.clone().irightShift(x); - } - - /** - * Whether this value is equal to x - * @param {BigInteger} x - * @returns {Boolean} - */ - equal(x) { - return this.value === x.value; - } - - /** - * Whether this value is less than x - * @param {BigInteger} x - * @returns {Boolean} - */ - lt(x) { - return this.value < x.value; - } - - /** - * Whether this value is less than or equal to x - * @param {BigInteger} x - * @returns {Boolean} - */ - lte(x) { - return this.value <= x.value; - } - - /** - * Whether this value is greater than x - * @param {BigInteger} x - * @returns {Boolean} - */ - gt(x) { - return this.value > x.value; - } - - /** - * Whether this value is greater than or equal to x - * @param {BigInteger} x - * @returns {Boolean} - */ - gte(x) { - return this.value >= x.value; - } - - isZero() { - return this.value === BigInt(0); - } - - isOne() { - return this.value === BigInt(1); - } - - isNegative() { - return this.value < BigInt(0); - } - - isEven() { - return !(this.value & BigInt(1)); - } - - abs() { - const res = this.clone(); - if (this.isNegative()) { - res.value = -res.value; - } - return res; - } - - /** - * Get this value as a string - * @returns {String} this value. - */ - toString() { - return this.value.toString(); - } - - /** - * Get this value as an exact Number (max 53 bits) - * Fails if this value is too large - * @returns {Number} - */ - toNumber() { - const number = Number(this.value); - if (number > Number.MAX_SAFE_INTEGER) { - // We throw and error to conform with the bn.js implementation - throw new Error('Number can only safely store up to 53 bits'); - } - return number; - } - - /** - * Get value of i-th bit - * @param {Number} i - Bit index - * @returns {Number} Bit value. - */ - getBit(i) { - const bit = (this.value >> BigInt(i)) & BigInt(1); - return (bit === BigInt(0)) ? 0 : 1; - } - - /** - * Compute bit length - * @returns {Number} Bit length. - */ - bitLength() { - const zero = new BigInteger(0); - const one = new BigInteger(1); - const negOne = new BigInteger(-1); - - // -1n >> -1n is -1n - // 1n >> 1n is 0n - const target = this.isNegative() ? negOne : zero; - let bitlen = 1; - const tmp = this.clone(); - while (!tmp.irightShift(one).equal(target)) { - bitlen++; - } - return bitlen; - } - - /** - * Compute byte length - * @returns {Number} Byte length. - */ - byteLength() { - const zero = new BigInteger(0); - const negOne = new BigInteger(-1); - - const target = this.isNegative() ? negOne : zero; - const eight = new BigInteger(8); - let len = 1; - const tmp = this.clone(); - while (!tmp.irightShift(eight).equal(target)) { - len++; - } - return len; - } - - /** - * Get Uint8Array representation of this number - * @param {String} endian - Endianess of output array (defaults to 'be') - * @param {Number} length - Of output array - * @returns {Uint8Array} - */ - toUint8Array(endian = 'be', length) { - // we get and parse the hex string (https://coolaj86.com/articles/convert-js-bigints-to-typedarrays/) - // this is faster than shift+mod iterations - let hex = this.value.toString(16); - if (hex.length % 2 === 1) { - hex = '0' + hex; - } - - const rawLength = hex.length / 2; - const bytes = new Uint8Array(length || rawLength); - // parse hex - const offset = length ? (length - rawLength) : 0; - let i = 0; - while (i < rawLength) { - bytes[i + offset] = parseInt(hex.slice(2 * i, 2 * i + 2), 16); - i++; - } - - if (endian !== 'be') { - bytes.reverse(); - } - - return bytes; - } - } - - async function getBigInteger() { - if (util.detectBigInt()) { - return BigInteger; - } else { - const { default: BigInteger } = await Promise.resolve().then(function () { return bn_interface; }); - return BigInteger; - } - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - const debugMode = (() => { - try { - return process.env.NODE_ENV === 'development'; // eslint-disable-line no-process-env - } catch (e) {} - return false; - })(); - - const util = { - isString: function(data) { - return typeof data === 'string' || String.prototype.isPrototypeOf(data); - }, - - isArray: function(data) { - return Array.prototype.isPrototypeOf(data); - }, - - isUint8Array: isUint8Array, - - isStream: isStream, - - readNumber: function (bytes) { - let n = 0; - for (let i = 0; i < bytes.length; i++) { - n += (256 ** i) * bytes[bytes.length - 1 - i]; - } - return n; - }, - - writeNumber: function (n, bytes) { - const b = new Uint8Array(bytes); - for (let i = 0; i < bytes; i++) { - b[i] = (n >> (8 * (bytes - i - 1))) & 0xFF; - } - - return b; - }, - - readDate: function (bytes) { - const n = util.readNumber(bytes); - const d = new Date(n * 1000); - return d; - }, - - writeDate: function (time) { - const numeric = Math.floor(time.getTime() / 1000); - - return util.writeNumber(numeric, 4); - }, - - normalizeDate: function (time = Date.now()) { - return time === null || time === Infinity ? time : new Date(Math.floor(+time / 1000) * 1000); - }, - - /** - * Read one MPI from bytes in input - * @param {Uint8Array} bytes - Input data to parse - * @returns {Uint8Array} Parsed MPI. - */ - readMPI: function (bytes) { - const bits = (bytes[0] << 8) | bytes[1]; - const bytelen = (bits + 7) >>> 3; - return bytes.subarray(2, 2 + bytelen); - }, - - /** - * Left-pad Uint8Array to length by adding 0x0 bytes - * @param {Uint8Array} bytes - Data to pad - * @param {Number} length - Padded length - * @returns {Uint8Array} Padded bytes. - */ - leftPad(bytes, length) { - const padded = new Uint8Array(length); - const offset = length - bytes.length; - padded.set(bytes, offset); - return padded; - }, - - /** - * Convert a Uint8Array to an MPI-formatted Uint8Array. - * @param {Uint8Array} bin - An array of 8-bit integers to convert - * @returns {Uint8Array} MPI-formatted Uint8Array. - */ - uint8ArrayToMPI: function (bin) { - const bitSize = util.uint8ArrayBitLength(bin); - if (bitSize === 0) { - throw new Error('Zero MPI'); - } - const stripped = bin.subarray(bin.length - Math.ceil(bitSize / 8)); - const prefix = new Uint8Array([(bitSize & 0xFF00) >> 8, bitSize & 0xFF]); - return util.concatUint8Array([prefix, stripped]); - }, - - /** - * Return bit length of the input data - * @param {Uint8Array} bin input data (big endian) - * @returns bit length - */ - uint8ArrayBitLength: function (bin) { - let i; // index of leading non-zero byte - for (i = 0; i < bin.length; i++) if (bin[i] !== 0) break; - if (i === bin.length) { - return 0; - } - const stripped = bin.subarray(i); - return (stripped.length - 1) * 8 + util.nbits(stripped[0]); - }, - - /** - * Convert a hex string to an array of 8-bit integers - * @param {String} hex - A hex string to convert - * @returns {Uint8Array} An array of 8-bit integers. - */ - hexToUint8Array: function (hex) { - const result = new Uint8Array(hex.length >> 1); - for (let k = 0; k < hex.length >> 1; k++) { - result[k] = parseInt(hex.substr(k << 1, 2), 16); - } - return result; - }, - - /** - * Convert an array of 8-bit integers to a hex string - * @param {Uint8Array} bytes - Array of 8-bit integers to convert - * @returns {String} Hexadecimal representation of the array. - */ - uint8ArrayToHex: function (bytes) { - const r = []; - const e = bytes.length; - let c = 0; - let h; - while (c < e) { - h = bytes[c++].toString(16); - while (h.length < 2) { - h = '0' + h; - } - r.push('' + h); - } - return r.join(''); - }, - - /** - * Convert a string to an array of 8-bit integers - * @param {String} str - String to convert - * @returns {Uint8Array} An array of 8-bit integers. - */ - stringToUint8Array: function (str) { - return transform(str, str => { - if (!util.isString(str)) { - throw new Error('stringToUint8Array: Data must be in the form of a string'); - } - - const result = new Uint8Array(str.length); - for (let i = 0; i < str.length; i++) { - result[i] = str.charCodeAt(i); - } - return result; - }); - }, - - /** - * Convert an array of 8-bit integers to a string - * @param {Uint8Array} bytes - An array of 8-bit integers to convert - * @returns {String} String representation of the array. - */ - uint8ArrayToString: function (bytes) { - bytes = new Uint8Array(bytes); - const result = []; - const bs = 1 << 14; - const j = bytes.length; - - for (let i = 0; i < j; i += bs) { - result.push(String.fromCharCode.apply(String, bytes.subarray(i, i + bs < j ? i + bs : j))); - } - return result.join(''); - }, - - /** - * Convert a native javascript string to a Uint8Array of utf8 bytes - * @param {String|ReadableStream} str - The string to convert - * @returns {Uint8Array|ReadableStream} A valid squence of utf8 bytes. - */ - encodeUTF8: function (str) { - const encoder = new TextEncoder('utf-8'); - // eslint-disable-next-line no-inner-declarations - function process(value, lastChunk = false) { - return encoder.encode(value, { stream: !lastChunk }); - } - return transform(str, process, () => process('', true)); - }, - - /** - * Convert a Uint8Array of utf8 bytes to a native javascript string - * @param {Uint8Array|ReadableStream} utf8 - A valid squence of utf8 bytes - * @returns {String|ReadableStream} A native javascript string. - */ - decodeUTF8: function (utf8) { - const decoder = new TextDecoder('utf-8'); - // eslint-disable-next-line no-inner-declarations - function process(value, lastChunk = false) { - return decoder.decode(value, { stream: !lastChunk }); - } - return transform(utf8, process, () => process(new Uint8Array(), true)); - }, - - /** - * Concat a list of Uint8Arrays, Strings or Streams - * The caller must not mix Uint8Arrays with Strings, but may mix Streams with non-Streams. - * @param {Array} Array - Of Uint8Arrays/Strings/Streams to concatenate - * @returns {Uint8Array|String|ReadableStream} Concatenated array. - */ - concat: concat, - - /** - * Concat Uint8Arrays - * @param {Array} Array - Of Uint8Arrays to concatenate - * @returns {Uint8Array} Concatenated array. - */ - concatUint8Array: concatUint8Array, - - /** - * Check Uint8Array equality - * @param {Uint8Array} array1 - First array - * @param {Uint8Array} array2 - Second array - * @returns {Boolean} Equality. - */ - equalsUint8Array: function (array1, array2) { - if (!util.isUint8Array(array1) || !util.isUint8Array(array2)) { - throw new Error('Data must be in the form of a Uint8Array'); - } - - if (array1.length !== array2.length) { - return false; - } - - for (let i = 0; i < array1.length; i++) { - if (array1[i] !== array2[i]) { - return false; - } - } - return true; - }, - - /** - * Calculates a 16bit sum of a Uint8Array by adding each character - * codes modulus 65535 - * @param {Uint8Array} Uint8Array - To create a sum of - * @returns {Uint8Array} 2 bytes containing the sum of all charcodes % 65535. - */ - writeChecksum: function (text) { - let s = 0; - for (let i = 0; i < text.length; i++) { - s = (s + text[i]) & 0xFFFF; - } - return util.writeNumber(s, 2); - }, - - /** - * Helper function to print a debug message. Debug - * messages are only printed if - * @param {String} str - String of the debug message - */ - printDebug: function (str) { - if (debugMode) { - console.log(str); - } - }, - - /** - * Helper function to print a debug error. Debug - * messages are only printed if - * @param {String} str - String of the debug message - */ - printDebugError: function (error) { - if (debugMode) { - console.error(error); - } - }, - - // returns bit length of the integer x - nbits: function (x) { - let r = 1; - let t = x >>> 16; - if (t !== 0) { - x = t; - r += 16; - } - t = x >> 8; - if (t !== 0) { - x = t; - r += 8; - } - t = x >> 4; - if (t !== 0) { - x = t; - r += 4; - } - t = x >> 2; - if (t !== 0) { - x = t; - r += 2; - } - t = x >> 1; - if (t !== 0) { - x = t; - r += 1; - } - return r; - }, - - /** - * If S[1] == 0, then double(S) == (S[2..128] || 0); - * otherwise, double(S) == (S[2..128] || 0) xor - * (zeros(120) || 10000111). - * - * Both OCB and EAX (through CMAC) require this function to be constant-time. - * - * @param {Uint8Array} data - */ - double: function(data) { - const doubleVar = new Uint8Array(data.length); - const last = data.length - 1; - for (let i = 0; i < last; i++) { - doubleVar[i] = (data[i] << 1) ^ (data[i + 1] >> 7); - } - doubleVar[last] = (data[last] << 1) ^ ((data[0] >> 7) * 0x87); - return doubleVar; - }, - - /** - * Shift a Uint8Array to the right by n bits - * @param {Uint8Array} array - The array to shift - * @param {Integer} bits - Amount of bits to shift (MUST be smaller - * than 8) - * @returns {String} Resulting array. - */ - shiftRight: function (array, bits) { - if (bits) { - for (let i = array.length - 1; i >= 0; i--) { - array[i] >>= bits; - if (i > 0) { - array[i] |= (array[i - 1] << (8 - bits)); - } - } - } - return array; - }, - - /** - * Get native Web Cryptography api, only the current version of the spec. - * @returns {Object} The SubtleCrypto api or 'undefined'. - */ - getWebCrypto: function() { - return typeof globalThis !== 'undefined' && globalThis.crypto && globalThis.crypto.subtle; - }, - - /** - * Detect Node.js runtime. - */ - detectNode: function() { - return typeof globalThis.process === 'object' && - typeof globalThis.process.versions === 'object'; - }, - - /** - * Detect native BigInt support - */ - detectBigInt: () => typeof BigInt !== 'undefined', - - /** - * Get BigInteger class - * It wraps the native BigInt type if it's available - * Otherwise it relies on bn.js - * @returns {BigInteger} - * @async - */ - getBigInteger, - - /** - * Get native Node.js crypto api. - * @returns {Object} The crypto module or 'undefined'. - */ - getNodeCrypto: function() { - return void('crypto'); - }, - - getNodeZlib: function() { - return void('zlib'); - }, - - /** - * Get native Node.js Buffer constructor. This should be used since - * Buffer is not available under browserify. - * @returns {Function} The Buffer constructor or 'undefined'. - */ - getNodeBuffer: function() { - return ({}).Buffer; - }, - - getHardwareConcurrency: function() { - if (util.detectNode()) { - const os = void('os'); - return os.cpus().length; - } - - return navigator.hardwareConcurrency || 1; - }, - - isEmailAddress: function(data) { - if (!util.isString(data)) { - return false; - } - const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+([a-zA-Z]{2,}|xn--[a-zA-Z\-0-9]+)))$/; - return re.test(data); - }, - - /** - * Normalize line endings to - * Support any encoding where CR=0x0D, LF=0x0A - */ - canonicalizeEOL: function(data) { - const CR = 13; - const LF = 10; - let carryOverCR = false; - - return transform(data, bytes => { - if (carryOverCR) { - bytes = util.concatUint8Array([new Uint8Array([CR]), bytes]); - } - - if (bytes[bytes.length - 1] === CR) { - carryOverCR = true; - bytes = bytes.subarray(0, -1); - } else { - carryOverCR = false; - } - - let index; - const indices = []; - for (let i = 0; ; i = index) { - index = bytes.indexOf(LF, i) + 1; - if (index) { - if (bytes[index - 2] !== CR) indices.push(index); - } else { - break; - } - } - if (!indices.length) { - return bytes; - } - - const normalized = new Uint8Array(bytes.length + indices.length); - let j = 0; - for (let i = 0; i < indices.length; i++) { - const sub = bytes.subarray(indices[i - 1] || 0, indices[i]); - normalized.set(sub, j); - j += sub.length; - normalized[j - 1] = CR; - normalized[j] = LF; - j++; - } - normalized.set(bytes.subarray(indices[indices.length - 1] || 0), j); - return normalized; - }, () => (carryOverCR ? new Uint8Array([CR]) : undefined)); - }, - - /** - * Convert line endings from canonicalized to native - * Support any encoding where CR=0x0D, LF=0x0A - */ - nativeEOL: function(data) { - const CR = 13; - const LF = 10; - let carryOverCR = false; - - return transform(data, bytes => { - if (carryOverCR && bytes[0] !== LF) { - bytes = util.concatUint8Array([new Uint8Array([CR]), bytes]); - } else { - bytes = new Uint8Array(bytes); // Don't mutate passed bytes - } - - if (bytes[bytes.length - 1] === CR) { - carryOverCR = true; - bytes = bytes.subarray(0, -1); - } else { - carryOverCR = false; - } - - let index; - let j = 0; - for (let i = 0; i !== bytes.length; i = index) { - index = bytes.indexOf(CR, i) + 1; - if (!index) index = bytes.length; - const last = index - (bytes[index] === LF ? 1 : 0); - if (i) bytes.copyWithin(j, i, last); - j += last - i; - } - return bytes.subarray(0, j); - }, () => (carryOverCR ? new Uint8Array([CR]) : undefined)); - }, - - /** - * Remove trailing spaces and tabs from each line - */ - removeTrailingSpaces: function(text) { - return text.split('\n').map(line => { - let i = line.length - 1; - for (; i >= 0 && (line[i] === ' ' || line[i] === '\t'); i--); - return line.substr(0, i + 1); - }).join('\n'); - }, - - wrapError: function(message, error) { - if (!error) { - return new Error(message); - } - - // update error message - try { - error.message = message + ': ' + error.message; - } catch (e) {} - - return error; - }, - - /** - * Map allowed packet tags to corresponding classes - * Meant to be used to format `allowedPacket` for Packetlist.read - * @param {Array} allowedClasses - * @returns {Object} map from enum.packet to corresponding *Packet class - */ - constructAllowedPackets: function(allowedClasses) { - const map = {}; - allowedClasses.forEach(PacketClass => { - if (!PacketClass.tag) { - throw new Error('Invalid input: expected a packet class'); - } - map[PacketClass.tag] = PacketClass; - }); - return map; - }, - - /** - * Return a Promise that will resolve as soon as one of the promises in input resolves - * or will reject if all input promises all rejected - * (similar to Promise.any, but with slightly different error handling) - * @param {Array} promises - * @return {Promise} Promise resolving to the result of the fastest fulfilled promise - * or rejected with the Error of the last resolved Promise (if all promises are rejected) - */ - anyPromise: function(promises) { - return new Promise(async (resolve, reject) => { - let exception; - await Promise.all(promises.map(async promise => { - try { - resolve(await promise); - } catch (e) { - exception = e; - } - })); - reject(exception); - }); - }, - - /** - * Return either `a` or `b` based on `cond`, in algorithmic constant time. - * @param {Boolean} cond - * @param {Uint8Array} a - * @param {Uint8Array} b - * @returns `a` if `cond` is true, `b` otherwise - */ - selectUint8Array: function(cond, a, b) { - const length = Math.max(a.length, b.length); - const result = new Uint8Array(length); - let end = 0; - for (let i = 0; i < result.length; i++) { - result[i] = (a[i] & (256 - cond)) | (b[i] & (255 + cond)); - end += (cond & i < a.length) | ((1 - cond) & i < b.length); - } - return result.subarray(0, end); - }, - /** - * Return either `a` or `b` based on `cond`, in algorithmic constant time. - * NB: it only supports `a, b` with values between 0-255. - * @param {Boolean} cond - * @param {Uint8} a - * @param {Uint8} b - * @returns `a` if `cond` is true, `b` otherwise - */ - selectUint8: function(cond, a, b) { - return (a & (256 - cond)) | (b & (255 + cond)); - } - }; - - /* OpenPGP radix-64/base64 string encoding/decoding - * Copyright 2005 Herbert Hanewinkel, www.haneWIN.de - * version 1.0, check www.haneWIN.de for the latest version - * - * This software is provided as-is, without express or implied warranty. - * Permission to use, copy, modify, distribute or sell this software, with or - * without fee, for any purpose and by any individual or organization, is hereby - * granted, provided that the above copyright notice and this paragraph appear - * in all copies. Distribution as a part of an application or binary must - * include the above copyright notice in the documentation and/or other materials - * provided with the application or distribution. - */ - - const Buffer = util.getNodeBuffer(); - - let encodeChunk; - let decodeChunk; - if (Buffer) { - encodeChunk = buf => Buffer.from(buf).toString('base64'); - decodeChunk = str => { - const b = Buffer.from(str, 'base64'); - return new Uint8Array(b.buffer, b.byteOffset, b.byteLength); - }; - } else { - encodeChunk = buf => btoa(util.uint8ArrayToString(buf)); - decodeChunk = str => util.stringToUint8Array(atob(str)); - } - - /** - * Convert binary array to radix-64 - * @param {Uint8Array | ReadableStream} data - Uint8Array to convert - * @returns {String | ReadableStream} Radix-64 version of input string. - * @static - */ - function encode(data) { - let buf = new Uint8Array(); - return transform(data, value => { - buf = util.concatUint8Array([buf, value]); - const r = []; - const bytesPerLine = 45; // 60 chars per line * (3 bytes / 4 chars of base64). - const lines = Math.floor(buf.length / bytesPerLine); - const bytes = lines * bytesPerLine; - const encoded = encodeChunk(buf.subarray(0, bytes)); - for (let i = 0; i < lines; i++) { - r.push(encoded.substr(i * 60, 60)); - r.push('\n'); - } - buf = buf.subarray(bytes); - return r.join(''); - }, () => (buf.length ? encodeChunk(buf) + '\n' : '')); - } - - /** - * Convert radix-64 to binary array - * @param {String | ReadableStream} data - Radix-64 string to convert - * @returns {Uint8Array | ReadableStream} Binary array version of input string. - * @static - */ - function decode(data) { - let buf = ''; - return transform(data, value => { - buf += value; - - // Count how many whitespace characters there are in buf - let spaces = 0; - const spacechars = [' ', '\t', '\r', '\n']; - for (let i = 0; i < spacechars.length; i++) { - const spacechar = spacechars[i]; - for (let pos = buf.indexOf(spacechar); pos !== -1; pos = buf.indexOf(spacechar, pos + 1)) { - spaces++; - } - } - - // Backtrack until we have 4n non-whitespace characters - // that we can safely base64-decode - let length = buf.length; - for (; length > 0 && (length - spaces) % 4 !== 0; length--) { - if (spacechars.includes(buf[length])) spaces--; - } - - const decoded = decodeChunk(buf.substr(0, length)); - buf = buf.substr(length); - return decoded; - }, () => decodeChunk(buf)); - } - - /** - * Convert a Base-64 encoded string an array of 8-bit integer - * - * Note: accepts both Radix-64 and URL-safe strings - * @param {String} base64 - Base-64 encoded string to convert - * @returns {Uint8Array} An array of 8-bit integers. - */ - function b64ToUint8Array(base64) { - return decode(base64.replace(/-/g, '+').replace(/_/g, '/')); - } - - /** - * Convert an array of 8-bit integer to a Base-64 encoded string - * @param {Uint8Array} bytes - An array of 8-bit integers to convert - * @param {bool} url - If true, output is URL-safe - * @returns {String} Base-64 encoded string. - */ - function uint8ArrayToB64(bytes, url) { - let encoded = encode(bytes).replace(/[\r\n]/g, ''); - if (url) { - encoded = encoded.replace(/[+]/g, '-').replace(/[/]/g, '_').replace(/[=]/g, ''); - } - return encoded; - } - - /** - * @module enums - */ - - const byValue = Symbol('byValue'); - - var enums = { - - /** Maps curve names under various standards to one - * @see {@link https://wiki.gnupg.org/ECC|ECC - GnuPG wiki} - * @enum {String} - * @readonly - */ - curve: { - /** NIST P-256 Curve */ - 'p256': 'p256', - 'P-256': 'p256', - 'secp256r1': 'p256', - 'prime256v1': 'p256', - '1.2.840.10045.3.1.7': 'p256', - '2a8648ce3d030107': 'p256', - '2A8648CE3D030107': 'p256', - - /** NIST P-384 Curve */ - 'p384': 'p384', - 'P-384': 'p384', - 'secp384r1': 'p384', - '1.3.132.0.34': 'p384', - '2b81040022': 'p384', - '2B81040022': 'p384', - - /** NIST P-521 Curve */ - 'p521': 'p521', - 'P-521': 'p521', - 'secp521r1': 'p521', - '1.3.132.0.35': 'p521', - '2b81040023': 'p521', - '2B81040023': 'p521', - - /** SECG SECP256k1 Curve */ - 'secp256k1': 'secp256k1', - '1.3.132.0.10': 'secp256k1', - '2b8104000a': 'secp256k1', - '2B8104000A': 'secp256k1', - - /** Ed25519 */ - 'ED25519': 'ed25519', - 'ed25519': 'ed25519', - 'Ed25519': 'ed25519', - '1.3.6.1.4.1.11591.15.1': 'ed25519', - '2b06010401da470f01': 'ed25519', - '2B06010401DA470F01': 'ed25519', - - /** Curve25519 */ - 'X25519': 'curve25519', - 'cv25519': 'curve25519', - 'curve25519': 'curve25519', - 'Curve25519': 'curve25519', - '1.3.6.1.4.1.3029.1.5.1': 'curve25519', - '2b060104019755010501': 'curve25519', - '2B060104019755010501': 'curve25519', - - /** BrainpoolP256r1 Curve */ - 'brainpoolP256r1': 'brainpoolP256r1', - '1.3.36.3.3.2.8.1.1.7': 'brainpoolP256r1', - '2b2403030208010107': 'brainpoolP256r1', - '2B2403030208010107': 'brainpoolP256r1', - - /** BrainpoolP384r1 Curve */ - 'brainpoolP384r1': 'brainpoolP384r1', - '1.3.36.3.3.2.8.1.1.11': 'brainpoolP384r1', - '2b240303020801010b': 'brainpoolP384r1', - '2B240303020801010B': 'brainpoolP384r1', - - /** BrainpoolP512r1 Curve */ - 'brainpoolP512r1': 'brainpoolP512r1', - '1.3.36.3.3.2.8.1.1.13': 'brainpoolP512r1', - '2b240303020801010d': 'brainpoolP512r1', - '2B240303020801010D': 'brainpoolP512r1' - }, - - /** A string to key specifier type - * @enum {Integer} - * @readonly - */ - s2k: { - simple: 0, - salted: 1, - iterated: 3, - gnu: 101 - }, - - /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-9.1|RFC4880bis-04, section 9.1} - * @enum {Integer} - * @readonly - */ - publicKey: { - /** RSA (Encrypt or Sign) [HAC] */ - rsaEncryptSign: 1, - /** RSA (Encrypt only) [HAC] */ - rsaEncrypt: 2, - /** RSA (Sign only) [HAC] */ - rsaSign: 3, - /** Elgamal (Encrypt only) [ELGAMAL] [HAC] */ - elgamal: 16, - /** DSA (Sign only) [FIPS186] [HAC] */ - dsa: 17, - /** ECDH (Encrypt only) [RFC6637] */ - ecdh: 18, - /** ECDSA (Sign only) [RFC6637] */ - ecdsa: 19, - /** EdDSA (Sign only) - * [{@link https://tools.ietf.org/html/draft-koch-eddsa-for-openpgp-04|Draft RFC}] */ - eddsa: 22, - /** Reserved for AEDH */ - aedh: 23, - /** Reserved for AEDSA */ - aedsa: 24 - }, - - /** {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC4880, section 9.2} - * @enum {Integer} - * @readonly - */ - symmetric: { - plaintext: 0, - /** Not implemented! */ - idea: 1, - tripledes: 2, - cast5: 3, - blowfish: 4, - aes128: 7, - aes192: 8, - aes256: 9, - twofish: 10 - }, - - /** {@link https://tools.ietf.org/html/rfc4880#section-9.3|RFC4880, section 9.3} - * @enum {Integer} - * @readonly - */ - compression: { - uncompressed: 0, - /** RFC1951 */ - zip: 1, - /** RFC1950 */ - zlib: 2, - bzip2: 3 - }, - - /** {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC4880, section 9.4} - * @enum {Integer} - * @readonly - */ - hash: { - md5: 1, - sha1: 2, - ripemd: 3, - sha256: 8, - sha384: 9, - sha512: 10, - sha224: 11 - }, - - /** A list of hash names as accepted by webCrypto functions. - * {@link https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest|Parameters, algo} - * @enum {String} - */ - webHash: { - 'SHA-1': 2, - 'SHA-256': 8, - 'SHA-384': 9, - 'SHA-512': 10 - }, - - /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-9.6|RFC4880bis-04, section 9.6} - * @enum {Integer} - * @readonly - */ - aead: { - eax: 1, - ocb: 2, - experimentalGCM: 100 // Private algorithm - }, - - /** A list of packet types and numeric tags associated with them. - * @enum {Integer} - * @readonly - */ - packet: { - publicKeyEncryptedSessionKey: 1, - signature: 2, - symEncryptedSessionKey: 3, - onePassSignature: 4, - secretKey: 5, - publicKey: 6, - secretSubkey: 7, - compressedData: 8, - symmetricallyEncryptedData: 9, - marker: 10, - literalData: 11, - trust: 12, - userID: 13, - publicSubkey: 14, - userAttribute: 17, - symEncryptedIntegrityProtectedData: 18, - modificationDetectionCode: 19, - aeadEncryptedData: 20 // see IETF draft: https://tools.ietf.org/html/draft-ford-openpgp-format-00#section-2.1 - }, - - /** Data types in the literal packet - * @enum {Integer} - * @readonly - */ - literal: { - /** Binary data 'b' */ - binary: 'b'.charCodeAt(), - /** Text data 't' */ - text: 't'.charCodeAt(), - /** Utf8 data 'u' */ - utf8: 'u'.charCodeAt(), - /** MIME message body part 'm' */ - mime: 'm'.charCodeAt() - }, - - - /** One pass signature packet type - * @enum {Integer} - * @readonly - */ - signature: { - /** 0x00: Signature of a binary document. */ - binary: 0, - /** 0x01: Signature of a canonical text document. - * - * Canonicalyzing the document by converting line endings. */ - text: 1, - /** 0x02: Standalone signature. - * - * This signature is a signature of only its own subpacket contents. - * It is calculated identically to a signature over a zero-lengh - * binary document. Note that it doesn't make sense to have a V3 - * standalone signature. */ - standalone: 2, - /** 0x10: Generic certification of a User ID and Public-Key packet. - * - * The issuer of this certification does not make any particular - * assertion as to how well the certifier has checked that the owner - * of the key is in fact the person described by the User ID. */ - certGeneric: 16, - /** 0x11: Persona certification of a User ID and Public-Key packet. - * - * The issuer of this certification has not done any verification of - * the claim that the owner of this key is the User ID specified. */ - certPersona: 17, - /** 0x12: Casual certification of a User ID and Public-Key packet. - * - * The issuer of this certification has done some casual - * verification of the claim of identity. */ - certCasual: 18, - /** 0x13: Positive certification of a User ID and Public-Key packet. - * - * The issuer of this certification has done substantial - * verification of the claim of identity. - * - * Most OpenPGP implementations make their "key signatures" as 0x10 - * certifications. Some implementations can issue 0x11-0x13 - * certifications, but few differentiate between the types. */ - certPositive: 19, - /** 0x30: Certification revocation signature - * - * This signature revokes an earlier User ID certification signature - * (signature class 0x10 through 0x13) or direct-key signature - * (0x1F). It should be issued by the same key that issued the - * revoked signature or an authorized revocation key. The signature - * is computed over the same data as the certificate that it - * revokes, and should have a later creation date than that - * certificate. */ - certRevocation: 48, - /** 0x18: Subkey Binding Signature - * - * This signature is a statement by the top-level signing key that - * indicates that it owns the subkey. This signature is calculated - * directly on the primary key and subkey, and not on any User ID or - * other packets. A signature that binds a signing subkey MUST have - * an Embedded Signature subpacket in this binding signature that - * contains a 0x19 signature made by the signing subkey on the - * primary key and subkey. */ - subkeyBinding: 24, - /** 0x19: Primary Key Binding Signature - * - * This signature is a statement by a signing subkey, indicating - * that it is owned by the primary key and subkey. This signature - * is calculated the same way as a 0x18 signature: directly on the - * primary key and subkey, and not on any User ID or other packets. - * - * When a signature is made over a key, the hash data starts with the - * octet 0x99, followed by a two-octet length of the key, and then body - * of the key packet. (Note that this is an old-style packet header for - * a key packet with two-octet length.) A subkey binding signature - * (type 0x18) or primary key binding signature (type 0x19) then hashes - * the subkey using the same format as the main key (also using 0x99 as - * the first octet). */ - keyBinding: 25, - /** 0x1F: Signature directly on a key - * - * This signature is calculated directly on a key. It binds the - * information in the Signature subpackets to the key, and is - * appropriate to be used for subpackets that provide information - * about the key, such as the Revocation Key subpacket. It is also - * appropriate for statements that non-self certifiers want to make - * about the key itself, rather than the binding between a key and a - * name. */ - key: 31, - /** 0x20: Key revocation signature - * - * The signature is calculated directly on the key being revoked. A - * revoked key is not to be used. Only revocation signatures by the - * key being revoked, or by an authorized revocation key, should be - * considered valid revocation signatures.a */ - keyRevocation: 32, - /** 0x28: Subkey revocation signature - * - * The signature is calculated directly on the subkey being revoked. - * A revoked subkey is not to be used. Only revocation signatures - * by the top-level signature key that is bound to this subkey, or - * by an authorized revocation key, should be considered valid - * revocation signatures. - * - * Key revocation signatures (types 0x20 and 0x28) - * hash only the key being revoked. */ - subkeyRevocation: 40, - /** 0x40: Timestamp signature. - * This signature is only meaningful for the timestamp contained in - * it. */ - timestamp: 64, - /** 0x50: Third-Party Confirmation signature. - * - * This signature is a signature over some other OpenPGP Signature - * packet(s). It is analogous to a notary seal on the signed data. - * A third-party signature SHOULD include Signature Target - * subpacket(s) to give easy identification. Note that we really do - * mean SHOULD. There are plausible uses for this (such as a blind - * party that only sees the signature, not the key or source - * document) that cannot include a target subpacket. */ - thirdParty: 80 - }, - - /** Signature subpacket type - * @enum {Integer} - * @readonly - */ - signatureSubpacket: { - signatureCreationTime: 2, - signatureExpirationTime: 3, - exportableCertification: 4, - trustSignature: 5, - regularExpression: 6, - revocable: 7, - keyExpirationTime: 9, - placeholderBackwardsCompatibility: 10, - preferredSymmetricAlgorithms: 11, - revocationKey: 12, - issuer: 16, - notationData: 20, - preferredHashAlgorithms: 21, - preferredCompressionAlgorithms: 22, - keyServerPreferences: 23, - preferredKeyServer: 24, - primaryUserID: 25, - policyURI: 26, - keyFlags: 27, - signersUserID: 28, - reasonForRevocation: 29, - features: 30, - signatureTarget: 31, - embeddedSignature: 32, - issuerFingerprint: 33, - preferredAEADAlgorithms: 34 - }, - - /** Key flags - * @enum {Integer} - * @readonly - */ - keyFlags: { - /** 0x01 - This key may be used to certify other keys. */ - certifyKeys: 1, - /** 0x02 - This key may be used to sign data. */ - signData: 2, - /** 0x04 - This key may be used to encrypt communications. */ - encryptCommunication: 4, - /** 0x08 - This key may be used to encrypt storage. */ - encryptStorage: 8, - /** 0x10 - The private component of this key may have been split - * by a secret-sharing mechanism. */ - splitPrivateKey: 16, - /** 0x20 - This key may be used for authentication. */ - authentication: 32, - /** 0x80 - The private component of this key may be in the - * possession of more than one person. */ - sharedPrivateKey: 128 - }, - - /** Armor type - * @enum {Integer} - * @readonly - */ - armor: { - multipartSection: 0, - multipartLast: 1, - signed: 2, - message: 3, - publicKey: 4, - privateKey: 5, - signature: 6 - }, - - /** {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.23|RFC4880, section 5.2.3.23} - * @enum {Integer} - * @readonly - */ - reasonForRevocation: { - /** No reason specified (key revocations or cert revocations) */ - noReason: 0, - /** Key is superseded (key revocations) */ - keySuperseded: 1, - /** Key material has been compromised (key revocations) */ - keyCompromised: 2, - /** Key is retired and no longer used (key revocations) */ - keyRetired: 3, - /** User ID information is no longer valid (cert revocations) */ - userIDInvalid: 32 - }, - - /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.2.3.25|RFC4880bis-04, section 5.2.3.25} - * @enum {Integer} - * @readonly - */ - features: { - /** 0x01 - Modification Detection (packets 18 and 19) */ - modificationDetection: 1, - /** 0x02 - AEAD Encrypted Data Packet (packet 20) and version 5 - * Symmetric-Key Encrypted Session Key Packets (packet 3) */ - aead: 2, - /** 0x04 - Version 5 Public-Key Packet format and corresponding new - * fingerprint format */ - v5Keys: 4 - }, - - /** - * Asserts validity of given value and converts from string/integer to integer. - * @param {Object} type target enum type - * @param {String|Integer} e value to check and/or convert - * @returns {Integer} enum value if it exists - * @throws {Error} if the value is invalid - */ - write: function(type, e) { - if (typeof e === 'number') { - e = this.read(type, e); - } - - if (type[e] !== undefined) { - return type[e]; - } - - throw new Error('Invalid enum value.'); - }, - - /** - * Converts enum integer value to the corresponding string, if it exists. - * @param {Object} type target enum type - * @param {Integer} e value to convert - * @returns {String} name of enum value if it exists - * @throws {Error} if the value is invalid - */ - read: function(type, e) { - if (!type[byValue]) { - type[byValue] = []; - Object.entries(type).forEach(([key, value]) => { - type[byValue][value] = key; - }); - } - - if (type[byValue][e] !== undefined) { - return type[byValue][e]; - } - - throw new Error('Invalid enum value.'); - } - }; - - // GPG4Browsers - An OpenPGP implementation in javascript - - var defaultConfig = { - /** - * @memberof module:config - * @property {Integer} preferredHashAlgorithm Default hash algorithm {@link module:enums.hash} - */ - preferredHashAlgorithm: enums.hash.sha256, - /** - * @memberof module:config - * @property {Integer} preferredSymmetricAlgorithm Default encryption cipher {@link module:enums.symmetric} - */ - preferredSymmetricAlgorithm: enums.symmetric.aes256, - /** - * @memberof module:config - * @property {Integer} compression Default compression algorithm {@link module:enums.compression} - */ - preferredCompressionAlgorithm: enums.compression.uncompressed, - /** - * @memberof module:config - * @property {Integer} deflateLevel Default zip/zlib compression level, between 1 and 9 - */ - deflateLevel: 6, - - /** - * Use Authenticated Encryption with Additional Data (AEAD) protection for symmetric encryption. - * Note: not all OpenPGP implementations are compatible with this option. - * **FUTURE OPENPGP.JS VERSIONS MAY BREAK COMPATIBILITY WHEN USING THIS OPTION** - * @see {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-07|RFC4880bis-07} - * @memberof module:config - * @property {Boolean} aeadProtect - */ - aeadProtect: false, - /** - * Default Authenticated Encryption with Additional Data (AEAD) encryption mode - * Only has an effect when aeadProtect is set to true. - * @memberof module:config - * @property {Integer} preferredAEADAlgorithm Default AEAD mode {@link module:enums.aead} - */ - preferredAEADAlgorithm: enums.aead.eax, - /** - * Chunk Size Byte for Authenticated Encryption with Additional Data (AEAD) mode - * Only has an effect when aeadProtect is set to true. - * Must be an integer value from 0 to 56. - * @memberof module:config - * @property {Integer} aeadChunkSizeByte - */ - aeadChunkSizeByte: 12, - /** - * Use V5 keys. - * Note: not all OpenPGP implementations are compatible with this option. - * **FUTURE OPENPGP.JS VERSIONS MAY BREAK COMPATIBILITY WHEN USING THIS OPTION** - * @memberof module:config - * @property {Boolean} v5Keys - */ - v5Keys: false, - /** - * {@link https://tools.ietf.org/html/rfc4880#section-3.7.1.3|RFC4880 3.7.1.3}: - * Iteration Count Byte for S2K (String to Key) - * @memberof module:config - * @property {Integer} s2kIterationCountByte - */ - s2kIterationCountByte: 224, - /** - * Allow decryption of messages without integrity protection. - * This is an **insecure** setting: - * - message modifications cannot be detected, thus processing the decrypted data is potentially unsafe. - * - it enables downgrade attacks against integrity-protected messages. - * @memberof module:config - * @property {Boolean} allowUnauthenticatedMessages - */ - allowUnauthenticatedMessages: false, - /** - * Allow streaming unauthenticated data before its integrity has been checked. - * This setting is **insecure** if the partially decrypted message is processed further or displayed to the user. - * @memberof module:config - * @property {Boolean} allowUnauthenticatedStream - */ - allowUnauthenticatedStream: false, - /** - * @memberof module:config - * @property {Boolean} checksumRequired Do not throw error when armor is missing a checksum - */ - checksumRequired: false, - /** - * Minimum RSA key size allowed for key generation and message signing, verification and encryption. - * The default is 2047 since due to a bug, previous versions of OpenPGP.js could generate 2047-bit keys instead of 2048-bit ones. - * @memberof module:config - * @property {Number} minRSABits - */ - minRSABits: 2047, - /** - * Work-around for rare GPG decryption bug when encrypting with multiple passwords. - * **Slower and slightly less secure** - * @memberof module:config - * @property {Boolean} passwordCollisionCheck - */ - passwordCollisionCheck: false, - /** - * @memberof module:config - * @property {Boolean} revocationsExpire If true, expired revocation signatures are ignored - */ - revocationsExpire: false, - /** - * Allow decryption using RSA keys without `encrypt` flag. - * This setting is potentially insecure, but it is needed to get around an old openpgpjs bug - * where key flags were ignored when selecting a key for encryption. - * @memberof module:config - * @property {Boolean} allowInsecureDecryptionWithSigningKeys - */ - allowInsecureDecryptionWithSigningKeys: false, - /** - * Allow verification of message signatures with keys whose validity at the time of signing cannot be determined. - * Instead, a verification key will also be consider valid as long as it is valid at the current time. - * This setting is potentially insecure, but it is needed to verify messages signed with keys that were later reformatted, - * and have self-signature's creation date that does not match the primary key creation date. - * @memberof module:config - * @property {Boolean} allowInsecureDecryptionWithSigningKeys - */ - allowInsecureVerificationWithReformattedKeys: false, - - /** - * Enable constant-time decryption of RSA- and ElGamal-encrypted session keys, to hinder Bleichenbacher-like attacks (https://link.springer.com/chapter/10.1007/BFb0055716). - * This setting has measurable performance impact and it is only helpful in application scenarios where both of the following conditions apply: - * - new/incoming messages are automatically decrypted (without user interaction); - * - an attacker can determine how long it takes to decrypt each message (e.g. due to decryption errors being logged remotely). - * See also `constantTimePKCS1DecryptionSupportedSymmetricAlgorithms`. - * @memberof module:config - * @property {Boolean} constantTimePKCS1Decryption - */ - constantTimePKCS1Decryption: false, - /** - * This setting is only meaningful if `constantTimePKCS1Decryption` is enabled. - * Decryption of RSA- and ElGamal-encrypted session keys of symmetric algorithms different from the ones specified here will fail. - * However, the more algorithms are added, the slower the decryption procedure becomes. - * @memberof module:config - * @property {Set} constantTimePKCS1DecryptionSupportedSymmetricAlgorithms {@link module:enums.symmetric} - */ - constantTimePKCS1DecryptionSupportedSymmetricAlgorithms: new Set([enums.symmetric.aes128, enums.symmetric.aes192, enums.symmetric.aes256]), - - /** - * @memberof module:config - * @property {Integer} minBytesForWebCrypto The minimum amount of bytes for which to use native WebCrypto APIs when available - */ - minBytesForWebCrypto: 1000, - /** - * @memberof module:config - * @property {Boolean} ignoreUnsupportedPackets Ignore unsupported/unrecognizable packets on parsing instead of throwing an error - */ - ignoreUnsupportedPackets: true, - /** - * @memberof module:config - * @property {Boolean} ignoreMalformedPackets Ignore malformed packets on parsing instead of throwing an error - */ - ignoreMalformedPackets: false, - /** - * @memberof module:config - * @property {Boolean} showVersion Whether to include {@link module:config/config.versionString} in armored messages - */ - showVersion: false, - /** - * @memberof module:config - * @property {Boolean} showComment Whether to include {@link module:config/config.commentString} in armored messages - */ - showComment: false, - /** - * @memberof module:config - * @property {String} versionString A version string to be included in armored messages - */ - versionString: 'OpenPGP.js 5.1.0', - /** - * @memberof module:config - * @property {String} commentString A comment string to be included in armored messages - */ - commentString: 'https://openpgpjs.org', - - /** - * Max userID string length (used for parsing) - * @memberof module:config - * @property {Integer} maxUserIDLength - */ - maxUserIDLength: 1024 * 5, - /** - * Contains notatations that are considered "known". Known notations do not trigger - * validation error when the notation is marked as critical. - * @memberof module:config - * @property {Array} knownNotations - */ - knownNotations: ['preferred-email-encoding@pgp.com', 'pka-address@gnupg.org'], - /** - * Whether to use the indutny/elliptic library for curves (other than Curve25519) that are not supported by the available native crypto API. - * When false, certain standard curves will not be supported (depending on the platform). - * Note: the indutny/elliptic curve library is not designed to be constant time. - * @memberof module:config - * @property {Boolean} useIndutnyElliptic - */ - useIndutnyElliptic: true, - /** - * Reject insecure hash algorithms - * @memberof module:config - * @property {Set} rejectHashAlgorithms {@link module:enums.hash} - */ - rejectHashAlgorithms: new Set([enums.hash.md5, enums.hash.ripemd]), - /** - * Reject insecure message hash algorithms - * @memberof module:config - * @property {Set} rejectMessageHashAlgorithms {@link module:enums.hash} - */ - rejectMessageHashAlgorithms: new Set([enums.hash.md5, enums.hash.ripemd, enums.hash.sha1]), - /** - * Reject insecure public key algorithms for key generation and message encryption, signing or verification - * @memberof module:config - * @property {Set} rejectPublicKeyAlgorithms {@link module:enums.publicKey} - */ - rejectPublicKeyAlgorithms: new Set([enums.publicKey.elgamal, enums.publicKey.dsa]), - /** - * Reject non-standard curves for key generation, message encryption, signing or verification - * @memberof module:config - * @property {Set} rejectCurves {@link module:enums.curve} - */ - rejectCurves: new Set([enums.curve.brainpoolP256r1, enums.curve.brainpoolP384r1, enums.curve.brainpoolP512r1, enums.curve.secp256k1]) - }; - - // GPG4Browsers - An OpenPGP implementation in javascript - - /** - * Finds out which Ascii Armoring type is used. Throws error if unknown type. - * @param {String} text - ascii armored text - * @returns {Integer} 0 = MESSAGE PART n of m. - * 1 = MESSAGE PART n - * 2 = SIGNED MESSAGE - * 3 = PGP MESSAGE - * 4 = PUBLIC KEY BLOCK - * 5 = PRIVATE KEY BLOCK - * 6 = SIGNATURE - * @private - */ - function getType(text) { - const reHeader = /^-----BEGIN PGP (MESSAGE, PART \d+\/\d+|MESSAGE, PART \d+|SIGNED MESSAGE|MESSAGE|PUBLIC KEY BLOCK|PRIVATE KEY BLOCK|SIGNATURE)-----$/m; - - const header = text.match(reHeader); - - if (!header) { - throw new Error('Unknown ASCII armor type'); - } - - // BEGIN PGP MESSAGE, PART X/Y - // Used for multi-part messages, where the armor is split amongst Y - // parts, and this is the Xth part out of Y. - if (/MESSAGE, PART \d+\/\d+/.test(header[1])) { - return enums.armor.multipartSection; - } else - // BEGIN PGP MESSAGE, PART X - // Used for multi-part messages, where this is the Xth part of an - // unspecified number of parts. Requires the MESSAGE-ID Armor - // Header to be used. - if (/MESSAGE, PART \d+/.test(header[1])) { - return enums.armor.multipartLast; - } else - // BEGIN PGP SIGNED MESSAGE - if (/SIGNED MESSAGE/.test(header[1])) { - return enums.armor.signed; - } else - // BEGIN PGP MESSAGE - // Used for signed, encrypted, or compressed files. - if (/MESSAGE/.test(header[1])) { - return enums.armor.message; - } else - // BEGIN PGP PUBLIC KEY BLOCK - // Used for armoring public keys. - if (/PUBLIC KEY BLOCK/.test(header[1])) { - return enums.armor.publicKey; - } else - // BEGIN PGP PRIVATE KEY BLOCK - // Used for armoring private keys. - if (/PRIVATE KEY BLOCK/.test(header[1])) { - return enums.armor.privateKey; - } else - // BEGIN PGP SIGNATURE - // Used for detached signatures, OpenPGP/MIME signatures, and - // cleartext signatures. Note that PGP 2.x uses BEGIN PGP MESSAGE - // for detached signatures. - if (/SIGNATURE/.test(header[1])) { - return enums.armor.signature; - } - } - - /** - * Add additional information to the armor version of an OpenPGP binary - * packet block. - * @author Alex - * @version 2011-12-16 - * @param {String} [customComment] - Additional comment to add to the armored string - * @returns {String} The header information. - * @private - */ - function addheader(customComment, config) { - let result = ''; - if (config.showVersion) { - result += 'Version: ' + config.versionString + '\n'; - } - if (config.showComment) { - result += 'Comment: ' + config.commentString + '\n'; - } - if (customComment) { - result += 'Comment: ' + customComment + '\n'; - } - result += '\n'; - return result; - } - - - /** - * Calculates a checksum over the given data and returns it base64 encoded - * @param {String | ReadableStream} data - Data to create a CRC-24 checksum for - * @returns {String | ReadableStream} Base64 encoded checksum. - * @private - */ - function getCheckSum(data) { - const crc = createcrc24(data); - return encode(crc); - } - - // https://create.stephan-brumme.com/crc32/#slicing-by-8-overview - - const crc_table = [ - new Array(0xFF), - new Array(0xFF), - new Array(0xFF), - new Array(0xFF) - ]; - - for (let i = 0; i <= 0xFF; i++) { - let crc = i << 16; - for (let j = 0; j < 8; j++) { - crc = (crc << 1) ^ ((crc & 0x800000) !== 0 ? 0x864CFB : 0); - } - crc_table[0][i] = - ((crc & 0xFF0000) >> 16) | - (crc & 0x00FF00) | - ((crc & 0x0000FF) << 16); - } - for (let i = 0; i <= 0xFF; i++) { - crc_table[1][i] = (crc_table[0][i] >> 8) ^ crc_table[0][crc_table[0][i] & 0xFF]; - } - for (let i = 0; i <= 0xFF; i++) { - crc_table[2][i] = (crc_table[1][i] >> 8) ^ crc_table[0][crc_table[1][i] & 0xFF]; - } - for (let i = 0; i <= 0xFF; i++) { - crc_table[3][i] = (crc_table[2][i] >> 8) ^ crc_table[0][crc_table[2][i] & 0xFF]; - } - - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView#Endianness - const isLittleEndian = (function() { - const buffer = new ArrayBuffer(2); - new DataView(buffer).setInt16(0, 0xFF, true /* littleEndian */); - // Int16Array uses the platform's endianness. - return new Int16Array(buffer)[0] === 0xFF; - }()); - - /** - * Internal function to calculate a CRC-24 checksum over a given string (data) - * @param {String | ReadableStream} input - Data to create a CRC-24 checksum for - * @returns {Uint8Array | ReadableStream} The CRC-24 checksum. - * @private - */ - function createcrc24(input) { - let crc = 0xCE04B7; - return transform(input, value => { - const len32 = isLittleEndian ? Math.floor(value.length / 4) : 0; - const arr32 = new Uint32Array(value.buffer, value.byteOffset, len32); - for (let i = 0; i < len32; i++) { - crc ^= arr32[i]; - crc = - crc_table[0][(crc >> 24) & 0xFF] ^ - crc_table[1][(crc >> 16) & 0xFF] ^ - crc_table[2][(crc >> 8) & 0xFF] ^ - crc_table[3][(crc >> 0) & 0xFF]; - } - for (let i = len32 * 4; i < value.length; i++) { - crc = (crc >> 8) ^ crc_table[0][(crc & 0xFF) ^ value[i]]; - } - }, () => new Uint8Array([crc, crc >> 8, crc >> 16])); - } - - /** - * Verify armored headers. RFC4880, section 6.3: "OpenPGP should consider improperly formatted - * Armor Headers to be corruption of the ASCII Armor." - * @private - * @param {Array} headers - Armor headers - */ - function verifyHeaders(headers) { - for (let i = 0; i < headers.length; i++) { - if (!/^([^\s:]|[^\s:][^:]*[^\s:]): .+$/.test(headers[i])) { - throw new Error('Improperly formatted armor header: ' + headers[i]); - } - if (!/^(Version|Comment|MessageID|Hash|Charset): .+$/.test(headers[i])) { - util.printDebugError(new Error('Unknown header: ' + headers[i])); - } - } - } - - /** - * Splits a message into two parts, the body and the checksum. This is an internal function - * @param {String} text - OpenPGP armored message part - * @returns {Object} An object with attribute "body" containing the body. - * and an attribute "checksum" containing the checksum. - * @private - */ - function splitChecksum(text) { - let body = text; - let checksum = ''; - - const lastEquals = text.lastIndexOf('='); - - if (lastEquals >= 0 && lastEquals !== text.length - 1) { // '=' as the last char means no checksum - body = text.slice(0, lastEquals); - checksum = text.slice(lastEquals + 1).substr(0, 4); - } - - return { body: body, checksum: checksum }; - } - - /** - * Dearmor an OpenPGP armored message; verify the checksum and return - * the encoded bytes - * @param {String} input - OpenPGP armored message - * @returns {Promise} An object with attribute "text" containing the message text, - * an attribute "data" containing a stream of bytes and "type" for the ASCII armor type - * @async - * @static - */ - function unarmor(input, config = defaultConfig) { - return new Promise(async (resolve, reject) => { - try { - const reSplit = /^-----[^-]+-----$/m; - const reEmptyLine = /^[ \f\r\t\u00a0\u2000-\u200a\u202f\u205f\u3000]*$/; - - let type; - const headers = []; - let lastHeaders = headers; - let headersDone; - let text = []; - let textDone; - let checksum; - let data = decode(transformPair(input, async (readable, writable) => { - const reader = getReader(readable); - try { - while (true) { - let line = await reader.readLine(); - if (line === undefined) { - throw new Error('Misformed armored text'); - } - // remove trailing whitespace at end of lines - line = util.removeTrailingSpaces(line.replace(/[\r\n]/g, '')); - if (!type) { - if (reSplit.test(line)) { - type = getType(line); - } - } else if (!headersDone) { - if (reSplit.test(line)) { - reject(new Error('Mandatory blank line missing between armor headers and armor data')); - } - if (!reEmptyLine.test(line)) { - lastHeaders.push(line); - } else { - verifyHeaders(lastHeaders); - headersDone = true; - if (textDone || type !== 2) { - resolve({ text, data, headers, type }); - break; - } - } - } else if (!textDone && type === 2) { - if (!reSplit.test(line)) { - // Reverse dash-escaping for msg - text.push(line.replace(/^- /, '')); - } else { - text = text.join('\r\n'); - textDone = true; - verifyHeaders(lastHeaders); - lastHeaders = []; - headersDone = false; - } - } - } - } catch (e) { - reject(e); - return; - } - const writer = getWriter(writable); - try { - while (true) { - await writer.ready; - const { done, value } = await reader.read(); - if (done) { - throw new Error('Misformed armored text'); - } - const line = value + ''; - if (line.indexOf('=') === -1 && line.indexOf('-') === -1) { - await writer.write(line); - } else { - let remainder = await reader.readToEnd(); - if (!remainder.length) remainder = ''; - remainder = line + remainder; - remainder = util.removeTrailingSpaces(remainder.replace(/\r/g, '')); - const parts = remainder.split(reSplit); - if (parts.length === 1) { - throw new Error('Misformed armored text'); - } - const split = splitChecksum(parts[0].slice(0, -1)); - checksum = split.checksum; - await writer.write(split.body); - break; - } - } - await writer.ready; - await writer.close(); - } catch (e) { - await writer.abort(e); - } - })); - data = transformPair(data, async (readable, writable) => { - const checksumVerified = readToEnd(getCheckSum(passiveClone(readable))); - checksumVerified.catch(() => {}); - await pipe(readable, writable, { - preventClose: true - }); - const writer = getWriter(writable); - try { - const checksumVerifiedString = (await checksumVerified).replace('\n', ''); - if (checksum !== checksumVerifiedString && (checksum || config.checksumRequired)) { - throw new Error('Ascii armor integrity check failed'); - } - await writer.ready; - await writer.close(); - } catch (e) { - await writer.abort(e); - } - }); - } catch (e) { - reject(e); - } - }).then(async result => { - if (isArrayStream(result.data)) { - result.data = await readToEnd(result.data); - } - return result; - }); - } - - - /** - * Armor an OpenPGP binary packet block - * @param {module:enums.armor} messageType - Type of the message - * @param {Uint8Array | ReadableStream} body - The message body to armor - * @param {Integer} [partIndex] - * @param {Integer} [partTotal] - * @param {String} [customComment] - Additional comment to add to the armored string - * @returns {String | ReadableStream} Armored text. - * @static - */ - function armor(messageType, body, partIndex, partTotal, customComment, config = defaultConfig) { - let text; - let hash; - if (messageType === enums.armor.signed) { - text = body.text; - hash = body.hash; - body = body.data; - } - const bodyClone = passiveClone(body); - const result = []; - switch (messageType) { - case enums.armor.multipartSection: - result.push('-----BEGIN PGP MESSAGE, PART ' + partIndex + '/' + partTotal + '-----\n'); - result.push(addheader(customComment, config)); - result.push(encode(body)); - result.push('=', getCheckSum(bodyClone)); - result.push('-----END PGP MESSAGE, PART ' + partIndex + '/' + partTotal + '-----\n'); - break; - case enums.armor.multipartLast: - result.push('-----BEGIN PGP MESSAGE, PART ' + partIndex + '-----\n'); - result.push(addheader(customComment, config)); - result.push(encode(body)); - result.push('=', getCheckSum(bodyClone)); - result.push('-----END PGP MESSAGE, PART ' + partIndex + '-----\n'); - break; - case enums.armor.signed: - result.push('\n-----BEGIN PGP SIGNED MESSAGE-----\n'); - result.push('Hash: ' + hash + '\n\n'); - result.push(text.replace(/^-/mg, '- -')); - result.push('\n-----BEGIN PGP SIGNATURE-----\n'); - result.push(addheader(customComment, config)); - result.push(encode(body)); - result.push('=', getCheckSum(bodyClone)); - result.push('-----END PGP SIGNATURE-----\n'); - break; - case enums.armor.message: - result.push('-----BEGIN PGP MESSAGE-----\n'); - result.push(addheader(customComment, config)); - result.push(encode(body)); - result.push('=', getCheckSum(bodyClone)); - result.push('-----END PGP MESSAGE-----\n'); - break; - case enums.armor.publicKey: - result.push('-----BEGIN PGP PUBLIC KEY BLOCK-----\n'); - result.push(addheader(customComment, config)); - result.push(encode(body)); - result.push('=', getCheckSum(bodyClone)); - result.push('-----END PGP PUBLIC KEY BLOCK-----\n'); - break; - case enums.armor.privateKey: - result.push('-----BEGIN PGP PRIVATE KEY BLOCK-----\n'); - result.push(addheader(customComment, config)); - result.push(encode(body)); - result.push('=', getCheckSum(bodyClone)); - result.push('-----END PGP PRIVATE KEY BLOCK-----\n'); - break; - case enums.armor.signature: - result.push('-----BEGIN PGP SIGNATURE-----\n'); - result.push(addheader(customComment, config)); - result.push(encode(body)); - result.push('=', getCheckSum(bodyClone)); - result.push('-----END PGP SIGNATURE-----\n'); - break; - } - - return util.concat(result); - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - /** - * Implementation of type key id - * - * {@link https://tools.ietf.org/html/rfc4880#section-3.3|RFC4880 3.3}: - * A Key ID is an eight-octet scalar that identifies a key. - * Implementations SHOULD NOT assume that Key IDs are unique. The - * section "Enhanced Key Formats" below describes how Key IDs are - * formed. - */ - class KeyID { - constructor() { - this.bytes = ''; - } - - /** - * Parsing method for a key id - * @param {Uint8Array} bytes - Input to read the key id from - */ - read(bytes) { - this.bytes = util.uint8ArrayToString(bytes.subarray(0, 8)); - } - - /** - * Serializes the Key ID - * @returns {Uint8Array} Key ID as a Uint8Array. - */ - write() { - return util.stringToUint8Array(this.bytes); - } - - /** - * Returns the Key ID represented as a hexadecimal string - * @returns {String} Key ID as a hexadecimal string. - */ - toHex() { - return util.uint8ArrayToHex(util.stringToUint8Array(this.bytes)); - } - - /** - * Checks equality of Key ID's - * @param {KeyID} keyID - * @param {Boolean} matchWildcard - Indicates whether to check if either keyID is a wildcard - */ - equals(keyID, matchWildcard = false) { - return (matchWildcard && (keyID.isWildcard() || this.isWildcard())) || this.bytes === keyID.bytes; - } - - /** - * Checks to see if the Key ID is unset - * @returns {Boolean} True if the Key ID is null. - */ - isNull() { - return this.bytes === ''; - } - - /** - * Checks to see if the Key ID is a "wildcard" Key ID (all zeros) - * @returns {Boolean} True if this is a wildcard Key ID. - */ - isWildcard() { - return /^0+$/.test(this.toHex()); - } - - static mapToHex(keyID) { - return keyID.toHex(); - } - - static fromID(hex) { - const keyID = new KeyID(); - keyID.read(util.hexToUint8Array(hex)); - return keyID; - } - - static wildcard() { - const keyID = new KeyID(); - keyID.read(new Uint8Array(8)); - return keyID; - } - } - - /** - * @file {@link http://asmjs.org Asm.js} implementation of the {@link https://en.wikipedia.org/wiki/Advanced_Encryption_Standard Advanced Encryption Standard}. - * @author Artem S Vybornov - * @license MIT - */ - var AES_asm = function () { - - /** - * Galois Field stuff init flag - */ - var ginit_done = false; - - /** - * Galois Field exponentiation and logarithm tables for 3 (the generator) - */ - var gexp3, glog3; - - /** - * Init Galois Field tables - */ - function ginit() { - gexp3 = [], - glog3 = []; - - var a = 1, c, d; - for (c = 0; c < 255; c++) { - gexp3[c] = a; - - // Multiply by three - d = a & 0x80, a <<= 1, a &= 255; - if (d === 0x80) a ^= 0x1b; - a ^= gexp3[c]; - - // Set the log table value - glog3[gexp3[c]] = c; - } - gexp3[255] = gexp3[0]; - glog3[0] = 0; - - ginit_done = true; - } - - /** - * Galois Field multiplication - * @param {number} a - * @param {number} b - * @return {number} - */ - function gmul(a, b) { - var c = gexp3[(glog3[a] + glog3[b]) % 255]; - if (a === 0 || b === 0) c = 0; - return c; - } - - /** - * Galois Field reciprocal - * @param {number} a - * @return {number} - */ - function ginv(a) { - var i = gexp3[255 - glog3[a]]; - if (a === 0) i = 0; - return i; - } - - /** - * AES stuff init flag - */ - var aes_init_done = false; - - /** - * Encryption, Decryption, S-Box and KeyTransform tables - * - * @type {number[]} - */ - var aes_sbox; - - /** - * @type {number[]} - */ - var aes_sinv; - - /** - * @type {number[][]} - */ - var aes_enc; - - /** - * @type {number[][]} - */ - var aes_dec; - - /** - * Init AES tables - */ - function aes_init() { - if (!ginit_done) ginit(); - - // Calculates AES S-Box value - function _s(a) { - var c, s, x; - s = x = ginv(a); - for (c = 0; c < 4; c++) { - s = ((s << 1) | (s >>> 7)) & 255; - x ^= s; - } - x ^= 99; - return x; - } - - // Tables - aes_sbox = [], - aes_sinv = [], - aes_enc = [[], [], [], []], - aes_dec = [[], [], [], []]; - - for (var i = 0; i < 256; i++) { - var s = _s(i); - - // S-Box and its inverse - aes_sbox[i] = s; - aes_sinv[s] = i; - - // Ecryption and Decryption tables - aes_enc[0][i] = (gmul(2, s) << 24) | (s << 16) | (s << 8) | gmul(3, s); - aes_dec[0][s] = (gmul(14, i) << 24) | (gmul(9, i) << 16) | (gmul(13, i) << 8) | gmul(11, i); - // Rotate tables - for (var t = 1; t < 4; t++) { - aes_enc[t][i] = (aes_enc[t - 1][i] >>> 8) | (aes_enc[t - 1][i] << 24); - aes_dec[t][s] = (aes_dec[t - 1][s] >>> 8) | (aes_dec[t - 1][s] << 24); - } - } - - aes_init_done = true; - } - - /** - * Asm.js module constructor. - * - *

- * Heap buffer layout by offset: - *

-     * 0x0000   encryption key schedule
-     * 0x0400   decryption key schedule
-     * 0x0800   sbox
-     * 0x0c00   inv sbox
-     * 0x1000   encryption tables
-     * 0x2000   decryption tables
-     * 0x3000   reserved (future GCM multiplication lookup table)
-     * 0x4000   data
-     * 
- * Don't touch anything before 0x400. - *

- * - * @alias AES_asm - * @class - * @param foreign - ignored - * @param buffer - heap buffer to link with - */ - var wrapper = function (foreign, buffer) { - // Init AES stuff for the first time - if (!aes_init_done) aes_init(); - - // Fill up AES tables - var heap = new Uint32Array(buffer); - heap.set(aes_sbox, 0x0800 >> 2); - heap.set(aes_sinv, 0x0c00 >> 2); - for (var i = 0; i < 4; i++) { - heap.set(aes_enc[i], (0x1000 + 0x400 * i) >> 2); - heap.set(aes_dec[i], (0x2000 + 0x400 * i) >> 2); - } - - /** - * Calculate AES key schedules. - * @instance - * @memberof AES_asm - * @param {number} ks - key size, 4/6/8 (for 128/192/256-bit key correspondingly) - * @param {number} k0 - key vector components - * @param {number} k1 - key vector components - * @param {number} k2 - key vector components - * @param {number} k3 - key vector components - * @param {number} k4 - key vector components - * @param {number} k5 - key vector components - * @param {number} k6 - key vector components - * @param {number} k7 - key vector components - */ - function set_key(ks, k0, k1, k2, k3, k4, k5, k6, k7) { - var ekeys = heap.subarray(0x000, 60), - dkeys = heap.subarray(0x100, 0x100 + 60); - - // Encryption key schedule - ekeys.set([k0, k1, k2, k3, k4, k5, k6, k7]); - for (var i = ks, rcon = 1; i < 4 * ks + 28; i++) { - var k = ekeys[i - 1]; - if ((i % ks === 0) || (ks === 8 && i % ks === 4)) { - k = aes_sbox[k >>> 24] << 24 ^ aes_sbox[k >>> 16 & 255] << 16 ^ aes_sbox[k >>> 8 & 255] << 8 ^ aes_sbox[k & 255]; - } - if (i % ks === 0) { - k = (k << 8) ^ (k >>> 24) ^ (rcon << 24); - rcon = (rcon << 1) ^ ((rcon & 0x80) ? 0x1b : 0); - } - ekeys[i] = ekeys[i - ks] ^ k; - } - - // Decryption key schedule - for (var j = 0; j < i; j += 4) { - for (var jj = 0; jj < 4; jj++) { - var k = ekeys[i - (4 + j) + (4 - jj) % 4]; - if (j < 4 || j >= i - 4) { - dkeys[j + jj] = k; - } else { - dkeys[j + jj] = aes_dec[0][aes_sbox[k >>> 24]] - ^ aes_dec[1][aes_sbox[k >>> 16 & 255]] - ^ aes_dec[2][aes_sbox[k >>> 8 & 255]] - ^ aes_dec[3][aes_sbox[k & 255]]; - } - } - } - - // Set rounds number - asm.set_rounds(ks + 5); - } - - // create library object with necessary properties - var stdlib = {Uint8Array: Uint8Array, Uint32Array: Uint32Array}; - - var asm = function (stdlib, foreign, buffer) { - "use asm"; - - var S0 = 0, S1 = 0, S2 = 0, S3 = 0, - I0 = 0, I1 = 0, I2 = 0, I3 = 0, - N0 = 0, N1 = 0, N2 = 0, N3 = 0, - M0 = 0, M1 = 0, M2 = 0, M3 = 0, - H0 = 0, H1 = 0, H2 = 0, H3 = 0, - R = 0; - - var HEAP = new stdlib.Uint32Array(buffer), - DATA = new stdlib.Uint8Array(buffer); - - /** - * AES core - * @param {number} k - precomputed key schedule offset - * @param {number} s - precomputed sbox table offset - * @param {number} t - precomputed round table offset - * @param {number} r - number of inner rounds to perform - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _core(k, s, t, r, x0, x1, x2, x3) { - k = k | 0; - s = s | 0; - t = t | 0; - r = r | 0; - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - var t1 = 0, t2 = 0, t3 = 0, - y0 = 0, y1 = 0, y2 = 0, y3 = 0, - i = 0; - - t1 = t | 0x400, t2 = t | 0x800, t3 = t | 0xc00; - - // round 0 - x0 = x0 ^ HEAP[(k | 0) >> 2], - x1 = x1 ^ HEAP[(k | 4) >> 2], - x2 = x2 ^ HEAP[(k | 8) >> 2], - x3 = x3 ^ HEAP[(k | 12) >> 2]; - - // round 1..r - for (i = 16; (i | 0) <= (r << 4); i = (i + 16) | 0) { - y0 = HEAP[(t | x0 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x1 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x2 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x3 << 2 & 1020) >> 2] ^ HEAP[(k | i | 0) >> 2], - y1 = HEAP[(t | x1 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x2 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x3 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x0 << 2 & 1020) >> 2] ^ HEAP[(k | i | 4) >> 2], - y2 = HEAP[(t | x2 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x3 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x0 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x1 << 2 & 1020) >> 2] ^ HEAP[(k | i | 8) >> 2], - y3 = HEAP[(t | x3 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x0 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x1 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x2 << 2 & 1020) >> 2] ^ HEAP[(k | i | 12) >> 2]; - x0 = y0, x1 = y1, x2 = y2, x3 = y3; - } - - // final round - S0 = HEAP[(s | x0 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x1 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x2 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x3 << 2 & 1020) >> 2] ^ HEAP[(k | i | 0) >> 2], - S1 = HEAP[(s | x1 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x2 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x3 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x0 << 2 & 1020) >> 2] ^ HEAP[(k | i | 4) >> 2], - S2 = HEAP[(s | x2 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x3 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x0 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x1 << 2 & 1020) >> 2] ^ HEAP[(k | i | 8) >> 2], - S3 = HEAP[(s | x3 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x0 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x1 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x2 << 2 & 1020) >> 2] ^ HEAP[(k | i | 12) >> 2]; - } - - /** - * ECB mode encryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _ecb_enc(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core( - 0x0000, 0x0800, 0x1000, - R, - x0, - x1, - x2, - x3 - ); - } - - /** - * ECB mode decryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _ecb_dec(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - var t = 0; - - _core( - 0x0400, 0x0c00, 0x2000, - R, - x0, - x3, - x2, - x1 - ); - - t = S1, S1 = S3, S3 = t; - } - - - /** - * CBC mode encryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _cbc_enc(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core( - 0x0000, 0x0800, 0x1000, - R, - I0 ^ x0, - I1 ^ x1, - I2 ^ x2, - I3 ^ x3 - ); - - I0 = S0, - I1 = S1, - I2 = S2, - I3 = S3; - } - - /** - * CBC mode decryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _cbc_dec(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - var t = 0; - - _core( - 0x0400, 0x0c00, 0x2000, - R, - x0, - x3, - x2, - x1 - ); - - t = S1, S1 = S3, S3 = t; - - S0 = S0 ^ I0, - S1 = S1 ^ I1, - S2 = S2 ^ I2, - S3 = S3 ^ I3; - - I0 = x0, - I1 = x1, - I2 = x2, - I3 = x3; - } - - /** - * CFB mode encryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _cfb_enc(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core( - 0x0000, 0x0800, 0x1000, - R, - I0, - I1, - I2, - I3 - ); - - I0 = S0 = S0 ^ x0, - I1 = S1 = S1 ^ x1, - I2 = S2 = S2 ^ x2, - I3 = S3 = S3 ^ x3; - } - - - /** - * CFB mode decryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _cfb_dec(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core( - 0x0000, 0x0800, 0x1000, - R, - I0, - I1, - I2, - I3 - ); - - S0 = S0 ^ x0, - S1 = S1 ^ x1, - S2 = S2 ^ x2, - S3 = S3 ^ x3; - - I0 = x0, - I1 = x1, - I2 = x2, - I3 = x3; - } - - /** - * OFB mode encryption / decryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _ofb(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core( - 0x0000, 0x0800, 0x1000, - R, - I0, - I1, - I2, - I3 - ); - - I0 = S0, - I1 = S1, - I2 = S2, - I3 = S3; - - S0 = S0 ^ x0, - S1 = S1 ^ x1, - S2 = S2 ^ x2, - S3 = S3 ^ x3; - } - - /** - * CTR mode encryption / decryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _ctr(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core( - 0x0000, 0x0800, 0x1000, - R, - N0, - N1, - N2, - N3 - ); - - N3 = (~M3 & N3) | M3 & (N3 + 1); - N2 = (~M2 & N2) | M2 & (N2 + ((N3 | 0) == 0)); - N1 = (~M1 & N1) | M1 & (N1 + ((N2 | 0) == 0)); - N0 = (~M0 & N0) | M0 & (N0 + ((N1 | 0) == 0)); - - S0 = S0 ^ x0; - S1 = S1 ^ x1; - S2 = S2 ^ x2; - S3 = S3 ^ x3; - } - - /** - * GCM mode MAC calculation - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _gcm_mac(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - var y0 = 0, y1 = 0, y2 = 0, y3 = 0, - z0 = 0, z1 = 0, z2 = 0, z3 = 0, - i = 0, c = 0; - - x0 = x0 ^ I0, - x1 = x1 ^ I1, - x2 = x2 ^ I2, - x3 = x3 ^ I3; - - y0 = H0 | 0, - y1 = H1 | 0, - y2 = H2 | 0, - y3 = H3 | 0; - - for (; (i | 0) < 128; i = (i + 1) | 0) { - if (y0 >>> 31) { - z0 = z0 ^ x0, - z1 = z1 ^ x1, - z2 = z2 ^ x2, - z3 = z3 ^ x3; - } - - y0 = (y0 << 1) | (y1 >>> 31), - y1 = (y1 << 1) | (y2 >>> 31), - y2 = (y2 << 1) | (y3 >>> 31), - y3 = (y3 << 1); - - c = x3 & 1; - - x3 = (x3 >>> 1) | (x2 << 31), - x2 = (x2 >>> 1) | (x1 << 31), - x1 = (x1 >>> 1) | (x0 << 31), - x0 = (x0 >>> 1); - - if (c) x0 = x0 ^ 0xe1000000; - } - - I0 = z0, - I1 = z1, - I2 = z2, - I3 = z3; - } - - /** - * Set the internal rounds number. - * @instance - * @memberof AES_asm - * @param {number} r - number if inner AES rounds - */ - function set_rounds(r) { - r = r | 0; - R = r; - } - - /** - * Populate the internal state of the module. - * @instance - * @memberof AES_asm - * @param {number} s0 - state vector - * @param {number} s1 - state vector - * @param {number} s2 - state vector - * @param {number} s3 - state vector - */ - function set_state(s0, s1, s2, s3) { - s0 = s0 | 0; - s1 = s1 | 0; - s2 = s2 | 0; - s3 = s3 | 0; - - S0 = s0, - S1 = s1, - S2 = s2, - S3 = s3; - } - - /** - * Populate the internal iv of the module. - * @instance - * @memberof AES_asm - * @param {number} i0 - iv vector - * @param {number} i1 - iv vector - * @param {number} i2 - iv vector - * @param {number} i3 - iv vector - */ - function set_iv(i0, i1, i2, i3) { - i0 = i0 | 0; - i1 = i1 | 0; - i2 = i2 | 0; - i3 = i3 | 0; - - I0 = i0, - I1 = i1, - I2 = i2, - I3 = i3; - } - - /** - * Set nonce for CTR-family modes. - * @instance - * @memberof AES_asm - * @param {number} n0 - nonce vector - * @param {number} n1 - nonce vector - * @param {number} n2 - nonce vector - * @param {number} n3 - nonce vector - */ - function set_nonce(n0, n1, n2, n3) { - n0 = n0 | 0; - n1 = n1 | 0; - n2 = n2 | 0; - n3 = n3 | 0; - - N0 = n0, - N1 = n1, - N2 = n2, - N3 = n3; - } - - /** - * Set counter mask for CTR-family modes. - * @instance - * @memberof AES_asm - * @param {number} m0 - counter mask vector - * @param {number} m1 - counter mask vector - * @param {number} m2 - counter mask vector - * @param {number} m3 - counter mask vector - */ - function set_mask(m0, m1, m2, m3) { - m0 = m0 | 0; - m1 = m1 | 0; - m2 = m2 | 0; - m3 = m3 | 0; - - M0 = m0, - M1 = m1, - M2 = m2, - M3 = m3; - } - - /** - * Set counter for CTR-family modes. - * @instance - * @memberof AES_asm - * @param {number} c0 - counter vector - * @param {number} c1 - counter vector - * @param {number} c2 - counter vector - * @param {number} c3 - counter vector - */ - function set_counter(c0, c1, c2, c3) { - c0 = c0 | 0; - c1 = c1 | 0; - c2 = c2 | 0; - c3 = c3 | 0; - - N3 = (~M3 & N3) | M3 & c3, - N2 = (~M2 & N2) | M2 & c2, - N1 = (~M1 & N1) | M1 & c1, - N0 = (~M0 & N0) | M0 & c0; - } - - /** - * Store the internal state vector into the heap. - * @instance - * @memberof AES_asm - * @param {number} pos - offset where to put the data - * @return {number} The number of bytes have been written into the heap, always 16. - */ - function get_state(pos) { - pos = pos | 0; - - if (pos & 15) return -1; - - DATA[pos | 0] = S0 >>> 24, - DATA[pos | 1] = S0 >>> 16 & 255, - DATA[pos | 2] = S0 >>> 8 & 255, - DATA[pos | 3] = S0 & 255, - DATA[pos | 4] = S1 >>> 24, - DATA[pos | 5] = S1 >>> 16 & 255, - DATA[pos | 6] = S1 >>> 8 & 255, - DATA[pos | 7] = S1 & 255, - DATA[pos | 8] = S2 >>> 24, - DATA[pos | 9] = S2 >>> 16 & 255, - DATA[pos | 10] = S2 >>> 8 & 255, - DATA[pos | 11] = S2 & 255, - DATA[pos | 12] = S3 >>> 24, - DATA[pos | 13] = S3 >>> 16 & 255, - DATA[pos | 14] = S3 >>> 8 & 255, - DATA[pos | 15] = S3 & 255; - - return 16; - } - - /** - * Store the internal iv vector into the heap. - * @instance - * @memberof AES_asm - * @param {number} pos - offset where to put the data - * @return {number} The number of bytes have been written into the heap, always 16. - */ - function get_iv(pos) { - pos = pos | 0; - - if (pos & 15) return -1; - - DATA[pos | 0] = I0 >>> 24, - DATA[pos | 1] = I0 >>> 16 & 255, - DATA[pos | 2] = I0 >>> 8 & 255, - DATA[pos | 3] = I0 & 255, - DATA[pos | 4] = I1 >>> 24, - DATA[pos | 5] = I1 >>> 16 & 255, - DATA[pos | 6] = I1 >>> 8 & 255, - DATA[pos | 7] = I1 & 255, - DATA[pos | 8] = I2 >>> 24, - DATA[pos | 9] = I2 >>> 16 & 255, - DATA[pos | 10] = I2 >>> 8 & 255, - DATA[pos | 11] = I2 & 255, - DATA[pos | 12] = I3 >>> 24, - DATA[pos | 13] = I3 >>> 16 & 255, - DATA[pos | 14] = I3 >>> 8 & 255, - DATA[pos | 15] = I3 & 255; - - return 16; - } - - /** - * GCM initialization. - * @instance - * @memberof AES_asm - */ - function gcm_init() { - _ecb_enc(0, 0, 0, 0); - H0 = S0, - H1 = S1, - H2 = S2, - H3 = S3; - } - - /** - * Perform ciphering operation on the supplied data. - * @instance - * @memberof AES_asm - * @param {number} mode - block cipher mode (see {@link AES_asm} mode constants) - * @param {number} pos - offset of the data being processed - * @param {number} len - length of the data being processed - * @return {number} Actual amount of data have been processed. - */ - function cipher(mode, pos, len) { - mode = mode | 0; - pos = pos | 0; - len = len | 0; - - var ret = 0; - - if (pos & 15) return -1; - - while ((len | 0) >= 16) { - _cipher_modes[mode & 7]( - DATA[pos | 0] << 24 | DATA[pos | 1] << 16 | DATA[pos | 2] << 8 | DATA[pos | 3], - DATA[pos | 4] << 24 | DATA[pos | 5] << 16 | DATA[pos | 6] << 8 | DATA[pos | 7], - DATA[pos | 8] << 24 | DATA[pos | 9] << 16 | DATA[pos | 10] << 8 | DATA[pos | 11], - DATA[pos | 12] << 24 | DATA[pos | 13] << 16 | DATA[pos | 14] << 8 | DATA[pos | 15] - ); - - DATA[pos | 0] = S0 >>> 24, - DATA[pos | 1] = S0 >>> 16 & 255, - DATA[pos | 2] = S0 >>> 8 & 255, - DATA[pos | 3] = S0 & 255, - DATA[pos | 4] = S1 >>> 24, - DATA[pos | 5] = S1 >>> 16 & 255, - DATA[pos | 6] = S1 >>> 8 & 255, - DATA[pos | 7] = S1 & 255, - DATA[pos | 8] = S2 >>> 24, - DATA[pos | 9] = S2 >>> 16 & 255, - DATA[pos | 10] = S2 >>> 8 & 255, - DATA[pos | 11] = S2 & 255, - DATA[pos | 12] = S3 >>> 24, - DATA[pos | 13] = S3 >>> 16 & 255, - DATA[pos | 14] = S3 >>> 8 & 255, - DATA[pos | 15] = S3 & 255; - - ret = (ret + 16) | 0, - pos = (pos + 16) | 0, - len = (len - 16) | 0; - } - - return ret | 0; - } - - /** - * Calculates MAC of the supplied data. - * @instance - * @memberof AES_asm - * @param {number} mode - block cipher mode (see {@link AES_asm} mode constants) - * @param {number} pos - offset of the data being processed - * @param {number} len - length of the data being processed - * @return {number} Actual amount of data have been processed. - */ - function mac(mode, pos, len) { - mode = mode | 0; - pos = pos | 0; - len = len | 0; - - var ret = 0; - - if (pos & 15) return -1; - - while ((len | 0) >= 16) { - _mac_modes[mode & 1]( - DATA[pos | 0] << 24 | DATA[pos | 1] << 16 | DATA[pos | 2] << 8 | DATA[pos | 3], - DATA[pos | 4] << 24 | DATA[pos | 5] << 16 | DATA[pos | 6] << 8 | DATA[pos | 7], - DATA[pos | 8] << 24 | DATA[pos | 9] << 16 | DATA[pos | 10] << 8 | DATA[pos | 11], - DATA[pos | 12] << 24 | DATA[pos | 13] << 16 | DATA[pos | 14] << 8 | DATA[pos | 15] - ); - - ret = (ret + 16) | 0, - pos = (pos + 16) | 0, - len = (len - 16) | 0; - } - - return ret | 0; - } - - /** - * AES cipher modes table (virual methods) - */ - var _cipher_modes = [_ecb_enc, _ecb_dec, _cbc_enc, _cbc_dec, _cfb_enc, _cfb_dec, _ofb, _ctr]; - - /** - * AES MAC modes table (virual methods) - */ - var _mac_modes = [_cbc_enc, _gcm_mac]; - - /** - * Asm.js module exports - */ - return { - set_rounds: set_rounds, - set_state: set_state, - set_iv: set_iv, - set_nonce: set_nonce, - set_mask: set_mask, - set_counter: set_counter, - get_state: get_state, - get_iv: get_iv, - gcm_init: gcm_init, - cipher: cipher, - mac: mac, - }; - }(stdlib, foreign, buffer); - - asm.set_key = set_key; - - return asm; - }; - - /** - * AES enciphering mode constants - * @enum {number} - * @const - */ - wrapper.ENC = { - ECB: 0, - CBC: 2, - CFB: 4, - OFB: 6, - CTR: 7, - }, - - /** - * AES deciphering mode constants - * @enum {number} - * @const - */ - wrapper.DEC = { - ECB: 1, - CBC: 3, - CFB: 5, - OFB: 6, - CTR: 7, - }, - - /** - * AES MAC mode constants - * @enum {number} - * @const - */ - wrapper.MAC = { - CBC: 0, - GCM: 1, - }; - - /** - * Heap data offset - * @type {number} - * @const - */ - wrapper.HEAP_DATA = 0x4000; - - return wrapper; - }(); - - function is_bytes(a) { - return a instanceof Uint8Array; - } - function _heap_init(heap, heapSize) { - const size = heap ? heap.byteLength : heapSize || 65536; - if (size & 0xfff || size <= 0) - throw new Error('heap size must be a positive integer and a multiple of 4096'); - heap = heap || new Uint8Array(new ArrayBuffer(size)); - return heap; - } - function _heap_write(heap, hpos, data, dpos, dlen) { - const hlen = heap.length - hpos; - const wlen = hlen < dlen ? hlen : dlen; - heap.set(data.subarray(dpos, dpos + wlen), hpos); - return wlen; - } - function joinBytes(...arg) { - const totalLenght = arg.reduce((sum, curr) => sum + curr.length, 0); - const ret = new Uint8Array(totalLenght); - let cursor = 0; - for (let i = 0; i < arg.length; i++) { - ret.set(arg[i], cursor); - cursor += arg[i].length; - } - return ret; - } - - class IllegalStateError extends Error { - constructor(...args) { - super(...args); - } - } - class IllegalArgumentError extends Error { - constructor(...args) { - super(...args); - } - } - class SecurityError extends Error { - constructor(...args) { - super(...args); - } - } - - const heap_pool = []; - const asm_pool = []; - class AES { - constructor(key, iv, padding = true, mode, heap, asm) { - this.pos = 0; - this.len = 0; - this.mode = mode; - // The AES object state - this.pos = 0; - this.len = 0; - this.key = key; - this.iv = iv; - this.padding = padding; - // The AES "worker" - this.acquire_asm(heap, asm); - } - acquire_asm(heap, asm) { - if (this.heap === undefined || this.asm === undefined) { - this.heap = heap || heap_pool.pop() || _heap_init().subarray(AES_asm.HEAP_DATA); - this.asm = asm || asm_pool.pop() || new AES_asm(null, this.heap.buffer); - this.reset(this.key, this.iv); - } - return { heap: this.heap, asm: this.asm }; - } - release_asm() { - if (this.heap !== undefined && this.asm !== undefined) { - heap_pool.push(this.heap); - asm_pool.push(this.asm); - } - this.heap = undefined; - this.asm = undefined; - } - reset(key, iv) { - const { asm } = this.acquire_asm(); - // Key - const keylen = key.length; - if (keylen !== 16 && keylen !== 24 && keylen !== 32) - throw new IllegalArgumentError('illegal key size'); - const keyview = new DataView(key.buffer, key.byteOffset, key.byteLength); - asm.set_key(keylen >> 2, keyview.getUint32(0), keyview.getUint32(4), keyview.getUint32(8), keyview.getUint32(12), keylen > 16 ? keyview.getUint32(16) : 0, keylen > 16 ? keyview.getUint32(20) : 0, keylen > 24 ? keyview.getUint32(24) : 0, keylen > 24 ? keyview.getUint32(28) : 0); - // IV - if (iv !== undefined) { - if (iv.length !== 16) - throw new IllegalArgumentError('illegal iv size'); - let ivview = new DataView(iv.buffer, iv.byteOffset, iv.byteLength); - asm.set_iv(ivview.getUint32(0), ivview.getUint32(4), ivview.getUint32(8), ivview.getUint32(12)); - } - else { - asm.set_iv(0, 0, 0, 0); - } - } - AES_Encrypt_process(data) { - if (!is_bytes(data)) - throw new TypeError("data isn't of expected type"); - let { heap, asm } = this.acquire_asm(); - let amode = AES_asm.ENC[this.mode]; - let hpos = AES_asm.HEAP_DATA; - let pos = this.pos; - let len = this.len; - let dpos = 0; - let dlen = data.length || 0; - let rpos = 0; - let rlen = (len + dlen) & -16; - let wlen = 0; - let result = new Uint8Array(rlen); - while (dlen > 0) { - wlen = _heap_write(heap, pos + len, data, dpos, dlen); - len += wlen; - dpos += wlen; - dlen -= wlen; - wlen = asm.cipher(amode, hpos + pos, len); - if (wlen) - result.set(heap.subarray(pos, pos + wlen), rpos); - rpos += wlen; - if (wlen < len) { - pos += wlen; - len -= wlen; - } - else { - pos = 0; - len = 0; - } - } - this.pos = pos; - this.len = len; - return result; - } - AES_Encrypt_finish() { - let { heap, asm } = this.acquire_asm(); - let amode = AES_asm.ENC[this.mode]; - let hpos = AES_asm.HEAP_DATA; - let pos = this.pos; - let len = this.len; - let plen = 16 - (len % 16); - let rlen = len; - if (this.hasOwnProperty('padding')) { - if (this.padding) { - for (let p = 0; p < plen; ++p) { - heap[pos + len + p] = plen; - } - len += plen; - rlen = len; - } - else if (len % 16) { - throw new IllegalArgumentError('data length must be a multiple of the block size'); - } - } - else { - len += plen; - } - const result = new Uint8Array(rlen); - if (len) - asm.cipher(amode, hpos + pos, len); - if (rlen) - result.set(heap.subarray(pos, pos + rlen)); - this.pos = 0; - this.len = 0; - this.release_asm(); - return result; - } - AES_Decrypt_process(data) { - if (!is_bytes(data)) - throw new TypeError("data isn't of expected type"); - let { heap, asm } = this.acquire_asm(); - let amode = AES_asm.DEC[this.mode]; - let hpos = AES_asm.HEAP_DATA; - let pos = this.pos; - let len = this.len; - let dpos = 0; - let dlen = data.length || 0; - let rpos = 0; - let rlen = (len + dlen) & -16; - let plen = 0; - let wlen = 0; - if (this.padding) { - plen = len + dlen - rlen || 16; - rlen -= plen; - } - const result = new Uint8Array(rlen); - while (dlen > 0) { - wlen = _heap_write(heap, pos + len, data, dpos, dlen); - len += wlen; - dpos += wlen; - dlen -= wlen; - wlen = asm.cipher(amode, hpos + pos, len - (!dlen ? plen : 0)); - if (wlen) - result.set(heap.subarray(pos, pos + wlen), rpos); - rpos += wlen; - if (wlen < len) { - pos += wlen; - len -= wlen; - } - else { - pos = 0; - len = 0; - } - } - this.pos = pos; - this.len = len; - return result; - } - AES_Decrypt_finish() { - let { heap, asm } = this.acquire_asm(); - let amode = AES_asm.DEC[this.mode]; - let hpos = AES_asm.HEAP_DATA; - let pos = this.pos; - let len = this.len; - let rlen = len; - if (len > 0) { - if (len % 16) { - if (this.hasOwnProperty('padding')) { - throw new IllegalArgumentError('data length must be a multiple of the block size'); - } - else { - len += 16 - (len % 16); - } - } - asm.cipher(amode, hpos + pos, len); - if (this.hasOwnProperty('padding') && this.padding) { - let pad = heap[pos + rlen - 1]; - if (pad < 1 || pad > 16 || pad > rlen) - throw new SecurityError('bad padding'); - let pcheck = 0; - for (let i = pad; i > 1; i--) - pcheck |= pad ^ heap[pos + rlen - i]; - if (pcheck) - throw new SecurityError('bad padding'); - rlen -= pad; - } - } - const result = new Uint8Array(rlen); - if (rlen > 0) { - result.set(heap.subarray(pos, pos + rlen)); - } - this.pos = 0; - this.len = 0; - this.release_asm(); - return result; - } - } - - class AES_ECB { - static encrypt(data, key, padding = false) { - return new AES_ECB(key, padding).encrypt(data); - } - static decrypt(data, key, padding = false) { - return new AES_ECB(key, padding).decrypt(data); - } - constructor(key, padding = false, aes) { - this.aes = aes ? aes : new AES(key, undefined, padding, 'ECB'); - } - encrypt(data) { - const r1 = this.aes.AES_Encrypt_process(data); - const r2 = this.aes.AES_Encrypt_finish(); - return joinBytes(r1, r2); - } - decrypt(data) { - const r1 = this.aes.AES_Decrypt_process(data); - const r2 = this.aes.AES_Decrypt_finish(); - return joinBytes(r1, r2); - } - } - - /** - * Javascript AES implementation. - * This is used as fallback if the native Crypto APIs are not available. - */ - function aes(length) { - const C = function(key) { - const aesECB = new AES_ECB(key); - - this.encrypt = function(block) { - return aesECB.encrypt(block); - }; - - this.decrypt = function(block) { - return aesECB.decrypt(block); - }; - }; - - C.blockSize = C.prototype.blockSize = 16; - C.keySize = C.prototype.keySize = length / 8; - - return C; - } - - //Paul Tero, July 2001 - //http://www.tero.co.uk/des/ - // - //Optimised for performance with large blocks by Michael Hayworth, November 2001 - //http://www.netdealing.com - // - // Modified by Recurity Labs GmbH - - //THIS SOFTWARE IS PROVIDED "AS IS" AND - //ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - //IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - //ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - //FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - //DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - //OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - //HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - //LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - //OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - //SUCH DAMAGE. - - //des - //this takes the key, the message, and whether to encrypt or decrypt - - function des(keys, message, encrypt, mode, iv, padding) { - //declaring this locally speeds things up a bit - const spfunction1 = [ - 0x1010400, 0, 0x10000, 0x1010404, 0x1010004, 0x10404, 0x4, 0x10000, 0x400, 0x1010400, - 0x1010404, 0x400, 0x1000404, 0x1010004, 0x1000000, 0x4, 0x404, 0x1000400, 0x1000400, 0x10400, 0x10400, 0x1010000, - 0x1010000, 0x1000404, 0x10004, 0x1000004, 0x1000004, 0x10004, 0, 0x404, 0x10404, 0x1000000, 0x10000, 0x1010404, 0x4, - 0x1010000, 0x1010400, 0x1000000, 0x1000000, 0x400, 0x1010004, 0x10000, 0x10400, 0x1000004, 0x400, 0x4, 0x1000404, - 0x10404, 0x1010404, 0x10004, 0x1010000, 0x1000404, 0x1000004, 0x404, 0x10404, 0x1010400, 0x404, 0x1000400, - 0x1000400, 0, 0x10004, 0x10400, 0, 0x1010004 - ]; - const spfunction2 = [ - -0x7fef7fe0, -0x7fff8000, 0x8000, 0x108020, 0x100000, 0x20, -0x7fefffe0, -0x7fff7fe0, - -0x7fffffe0, -0x7fef7fe0, -0x7fef8000, -0x80000000, -0x7fff8000, 0x100000, 0x20, -0x7fefffe0, 0x108000, 0x100020, - -0x7fff7fe0, 0, -0x80000000, 0x8000, 0x108020, -0x7ff00000, 0x100020, -0x7fffffe0, 0, 0x108000, 0x8020, -0x7fef8000, - -0x7ff00000, 0x8020, 0, 0x108020, -0x7fefffe0, 0x100000, -0x7fff7fe0, -0x7ff00000, -0x7fef8000, 0x8000, -0x7ff00000, - -0x7fff8000, 0x20, -0x7fef7fe0, 0x108020, 0x20, 0x8000, -0x80000000, 0x8020, -0x7fef8000, 0x100000, -0x7fffffe0, - 0x100020, -0x7fff7fe0, -0x7fffffe0, 0x100020, 0x108000, 0, -0x7fff8000, 0x8020, -0x80000000, -0x7fefffe0, - -0x7fef7fe0, 0x108000 - ]; - const spfunction3 = [ - 0x208, 0x8020200, 0, 0x8020008, 0x8000200, 0, 0x20208, 0x8000200, 0x20008, 0x8000008, - 0x8000008, 0x20000, 0x8020208, 0x20008, 0x8020000, 0x208, 0x8000000, 0x8, 0x8020200, 0x200, 0x20200, 0x8020000, - 0x8020008, 0x20208, 0x8000208, 0x20200, 0x20000, 0x8000208, 0x8, 0x8020208, 0x200, 0x8000000, 0x8020200, 0x8000000, - 0x20008, 0x208, 0x20000, 0x8020200, 0x8000200, 0, 0x200, 0x20008, 0x8020208, 0x8000200, 0x8000008, 0x200, 0, - 0x8020008, 0x8000208, 0x20000, 0x8000000, 0x8020208, 0x8, 0x20208, 0x20200, 0x8000008, 0x8020000, 0x8000208, 0x208, - 0x8020000, 0x20208, 0x8, 0x8020008, 0x20200 - ]; - const spfunction4 = [ - 0x802001, 0x2081, 0x2081, 0x80, 0x802080, 0x800081, 0x800001, 0x2001, 0, 0x802000, - 0x802000, 0x802081, 0x81, 0, 0x800080, 0x800001, 0x1, 0x2000, 0x800000, 0x802001, 0x80, 0x800000, 0x2001, 0x2080, - 0x800081, 0x1, 0x2080, 0x800080, 0x2000, 0x802080, 0x802081, 0x81, 0x800080, 0x800001, 0x802000, 0x802081, 0x81, 0, - 0, 0x802000, 0x2080, 0x800080, 0x800081, 0x1, 0x802001, 0x2081, 0x2081, 0x80, 0x802081, 0x81, 0x1, 0x2000, 0x800001, - 0x2001, 0x802080, 0x800081, 0x2001, 0x2080, 0x800000, 0x802001, 0x80, 0x800000, 0x2000, 0x802080 - ]; - const spfunction5 = [ - 0x100, 0x2080100, 0x2080000, 0x42000100, 0x80000, 0x100, 0x40000000, 0x2080000, - 0x40080100, 0x80000, 0x2000100, 0x40080100, 0x42000100, 0x42080000, 0x80100, 0x40000000, 0x2000000, 0x40080000, - 0x40080000, 0, 0x40000100, 0x42080100, 0x42080100, 0x2000100, 0x42080000, 0x40000100, 0, 0x42000000, 0x2080100, - 0x2000000, 0x42000000, 0x80100, 0x80000, 0x42000100, 0x100, 0x2000000, 0x40000000, 0x2080000, 0x42000100, - 0x40080100, 0x2000100, 0x40000000, 0x42080000, 0x2080100, 0x40080100, 0x100, 0x2000000, 0x42080000, 0x42080100, - 0x80100, 0x42000000, 0x42080100, 0x2080000, 0, 0x40080000, 0x42000000, 0x80100, 0x2000100, 0x40000100, 0x80000, 0, - 0x40080000, 0x2080100, 0x40000100 - ]; - const spfunction6 = [ - 0x20000010, 0x20400000, 0x4000, 0x20404010, 0x20400000, 0x10, 0x20404010, 0x400000, - 0x20004000, 0x404010, 0x400000, 0x20000010, 0x400010, 0x20004000, 0x20000000, 0x4010, 0, 0x400010, 0x20004010, - 0x4000, 0x404000, 0x20004010, 0x10, 0x20400010, 0x20400010, 0, 0x404010, 0x20404000, 0x4010, 0x404000, 0x20404000, - 0x20000000, 0x20004000, 0x10, 0x20400010, 0x404000, 0x20404010, 0x400000, 0x4010, 0x20000010, 0x400000, 0x20004000, - 0x20000000, 0x4010, 0x20000010, 0x20404010, 0x404000, 0x20400000, 0x404010, 0x20404000, 0, 0x20400010, 0x10, 0x4000, - 0x20400000, 0x404010, 0x4000, 0x400010, 0x20004010, 0, 0x20404000, 0x20000000, 0x400010, 0x20004010 - ]; - const spfunction7 = [ - 0x200000, 0x4200002, 0x4000802, 0, 0x800, 0x4000802, 0x200802, 0x4200800, 0x4200802, - 0x200000, 0, 0x4000002, 0x2, 0x4000000, 0x4200002, 0x802, 0x4000800, 0x200802, 0x200002, 0x4000800, 0x4000002, - 0x4200000, 0x4200800, 0x200002, 0x4200000, 0x800, 0x802, 0x4200802, 0x200800, 0x2, 0x4000000, 0x200800, 0x4000000, - 0x200800, 0x200000, 0x4000802, 0x4000802, 0x4200002, 0x4200002, 0x2, 0x200002, 0x4000000, 0x4000800, 0x200000, - 0x4200800, 0x802, 0x200802, 0x4200800, 0x802, 0x4000002, 0x4200802, 0x4200000, 0x200800, 0, 0x2, 0x4200802, 0, - 0x200802, 0x4200000, 0x800, 0x4000002, 0x4000800, 0x800, 0x200002 - ]; - const spfunction8 = [ - 0x10001040, 0x1000, 0x40000, 0x10041040, 0x10000000, 0x10001040, 0x40, 0x10000000, - 0x40040, 0x10040000, 0x10041040, 0x41000, 0x10041000, 0x41040, 0x1000, 0x40, 0x10040000, 0x10000040, 0x10001000, - 0x1040, 0x41000, 0x40040, 0x10040040, 0x10041000, 0x1040, 0, 0, 0x10040040, 0x10000040, 0x10001000, 0x41040, - 0x40000, 0x41040, 0x40000, 0x10041000, 0x1000, 0x40, 0x10040040, 0x1000, 0x41040, 0x10001000, 0x40, 0x10000040, - 0x10040000, 0x10040040, 0x10000000, 0x40000, 0x10001040, 0, 0x10041040, 0x40040, 0x10000040, 0x10040000, 0x10001000, - 0x10001040, 0, 0x10041040, 0x41000, 0x41000, 0x1040, 0x1040, 0x40040, 0x10000000, 0x10041000 - ]; - - //create the 16 or 48 subkeys we will need - let m = 0; - let i; - let j; - let temp; - let right1; - let right2; - let left; - let right; - let looping; - let cbcleft; - let cbcleft2; - let cbcright; - let cbcright2; - let endloop; - let loopinc; - let len = message.length; - - //set up the loops for single and triple des - const iterations = keys.length === 32 ? 3 : 9; //single or triple des - if (iterations === 3) { - looping = encrypt ? [0, 32, 2] : [30, -2, -2]; - } else { - looping = encrypt ? [0, 32, 2, 62, 30, -2, 64, 96, 2] : [94, 62, -2, 32, 64, 2, 30, -2, -2]; - } - - //pad the message depending on the padding parameter - //only add padding if encrypting - note that you need to use the same padding option for both encrypt and decrypt - if (encrypt) { - message = desAddPadding(message, padding); - len = message.length; - } - - //store the result here - let result = new Uint8Array(len); - let k = 0; - - if (mode === 1) { //CBC mode - cbcleft = (iv[m++] << 24) | (iv[m++] << 16) | (iv[m++] << 8) | iv[m++]; - cbcright = (iv[m++] << 24) | (iv[m++] << 16) | (iv[m++] << 8) | iv[m++]; - m = 0; - } - - //loop through each 64 bit chunk of the message - while (m < len) { - left = (message[m++] << 24) | (message[m++] << 16) | (message[m++] << 8) | message[m++]; - right = (message[m++] << 24) | (message[m++] << 16) | (message[m++] << 8) | message[m++]; - - //for Cipher Block Chaining mode, xor the message with the previous result - if (mode === 1) { - if (encrypt) { - left ^= cbcleft; - right ^= cbcright; - } else { - cbcleft2 = cbcleft; - cbcright2 = cbcright; - cbcleft = left; - cbcright = right; - } - } - - //first each 64 but chunk of the message must be permuted according to IP - temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; - right ^= temp; - left ^= (temp << 4); - temp = ((left >>> 16) ^ right) & 0x0000ffff; - right ^= temp; - left ^= (temp << 16); - temp = ((right >>> 2) ^ left) & 0x33333333; - left ^= temp; - right ^= (temp << 2); - temp = ((right >>> 8) ^ left) & 0x00ff00ff; - left ^= temp; - right ^= (temp << 8); - temp = ((left >>> 1) ^ right) & 0x55555555; - right ^= temp; - left ^= (temp << 1); - - left = ((left << 1) | (left >>> 31)); - right = ((right << 1) | (right >>> 31)); - - //do this either 1 or 3 times for each chunk of the message - for (j = 0; j < iterations; j += 3) { - endloop = looping[j + 1]; - loopinc = looping[j + 2]; - //now go through and perform the encryption or decryption - for (i = looping[j]; i !== endloop; i += loopinc) { //for efficiency - right1 = right ^ keys[i]; - right2 = ((right >>> 4) | (right << 28)) ^ keys[i + 1]; - //the result is attained by passing these bytes through the S selection functions - temp = left; - left = right; - right = temp ^ (spfunction2[(right1 >>> 24) & 0x3f] | spfunction4[(right1 >>> 16) & 0x3f] | spfunction6[(right1 >>> - 8) & 0x3f] | spfunction8[right1 & 0x3f] | spfunction1[(right2 >>> 24) & 0x3f] | spfunction3[(right2 >>> 16) & - 0x3f] | spfunction5[(right2 >>> 8) & 0x3f] | spfunction7[right2 & 0x3f]); - } - temp = left; - left = right; - right = temp; //unreverse left and right - } //for either 1 or 3 iterations - - //move then each one bit to the right - left = ((left >>> 1) | (left << 31)); - right = ((right >>> 1) | (right << 31)); - - //now perform IP-1, which is IP in the opposite direction - temp = ((left >>> 1) ^ right) & 0x55555555; - right ^= temp; - left ^= (temp << 1); - temp = ((right >>> 8) ^ left) & 0x00ff00ff; - left ^= temp; - right ^= (temp << 8); - temp = ((right >>> 2) ^ left) & 0x33333333; - left ^= temp; - right ^= (temp << 2); - temp = ((left >>> 16) ^ right) & 0x0000ffff; - right ^= temp; - left ^= (temp << 16); - temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; - right ^= temp; - left ^= (temp << 4); - - //for Cipher Block Chaining mode, xor the message with the previous result - if (mode === 1) { - if (encrypt) { - cbcleft = left; - cbcright = right; - } else { - left ^= cbcleft2; - right ^= cbcright2; - } - } - - result[k++] = (left >>> 24); - result[k++] = ((left >>> 16) & 0xff); - result[k++] = ((left >>> 8) & 0xff); - result[k++] = (left & 0xff); - result[k++] = (right >>> 24); - result[k++] = ((right >>> 16) & 0xff); - result[k++] = ((right >>> 8) & 0xff); - result[k++] = (right & 0xff); - } //for every 8 characters, or 64 bits in the message - - //only remove padding if decrypting - note that you need to use the same padding option for both encrypt and decrypt - if (!encrypt) { - result = desRemovePadding(result, padding); - } - - return result; - } //end of des - - - //desCreateKeys - //this takes as input a 64 bit key (even though only 56 bits are used) - //as an array of 2 integers, and returns 16 48 bit keys - - function desCreateKeys(key) { - //declaring this locally speeds things up a bit - const pc2bytes0 = [ - 0, 0x4, 0x20000000, 0x20000004, 0x10000, 0x10004, 0x20010000, 0x20010004, 0x200, 0x204, - 0x20000200, 0x20000204, 0x10200, 0x10204, 0x20010200, 0x20010204 - ]; - const pc2bytes1 = [ - 0, 0x1, 0x100000, 0x100001, 0x4000000, 0x4000001, 0x4100000, 0x4100001, 0x100, 0x101, 0x100100, - 0x100101, 0x4000100, 0x4000101, 0x4100100, 0x4100101 - ]; - const pc2bytes2 = [ - 0, 0x8, 0x800, 0x808, 0x1000000, 0x1000008, 0x1000800, 0x1000808, 0, 0x8, 0x800, 0x808, - 0x1000000, 0x1000008, 0x1000800, 0x1000808 - ]; - const pc2bytes3 = [ - 0, 0x200000, 0x8000000, 0x8200000, 0x2000, 0x202000, 0x8002000, 0x8202000, 0x20000, 0x220000, - 0x8020000, 0x8220000, 0x22000, 0x222000, 0x8022000, 0x8222000 - ]; - const pc2bytes4 = [ - 0, 0x40000, 0x10, 0x40010, 0, 0x40000, 0x10, 0x40010, 0x1000, 0x41000, 0x1010, 0x41010, 0x1000, - 0x41000, 0x1010, 0x41010 - ]; - const pc2bytes5 = [ - 0, 0x400, 0x20, 0x420, 0, 0x400, 0x20, 0x420, 0x2000000, 0x2000400, 0x2000020, 0x2000420, - 0x2000000, 0x2000400, 0x2000020, 0x2000420 - ]; - const pc2bytes6 = [ - 0, 0x10000000, 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002, 0, 0x10000000, - 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002 - ]; - const pc2bytes7 = [ - 0, 0x10000, 0x800, 0x10800, 0x20000000, 0x20010000, 0x20000800, 0x20010800, 0x20000, 0x30000, - 0x20800, 0x30800, 0x20020000, 0x20030000, 0x20020800, 0x20030800 - ]; - const pc2bytes8 = [ - 0, 0x40000, 0, 0x40000, 0x2, 0x40002, 0x2, 0x40002, 0x2000000, 0x2040000, 0x2000000, 0x2040000, - 0x2000002, 0x2040002, 0x2000002, 0x2040002 - ]; - const pc2bytes9 = [ - 0, 0x10000000, 0x8, 0x10000008, 0, 0x10000000, 0x8, 0x10000008, 0x400, 0x10000400, 0x408, - 0x10000408, 0x400, 0x10000400, 0x408, 0x10000408 - ]; - const pc2bytes10 = [ - 0, 0x20, 0, 0x20, 0x100000, 0x100020, 0x100000, 0x100020, 0x2000, 0x2020, 0x2000, 0x2020, - 0x102000, 0x102020, 0x102000, 0x102020 - ]; - const pc2bytes11 = [ - 0, 0x1000000, 0x200, 0x1000200, 0x200000, 0x1200000, 0x200200, 0x1200200, 0x4000000, 0x5000000, - 0x4000200, 0x5000200, 0x4200000, 0x5200000, 0x4200200, 0x5200200 - ]; - const pc2bytes12 = [ - 0, 0x1000, 0x8000000, 0x8001000, 0x80000, 0x81000, 0x8080000, 0x8081000, 0x10, 0x1010, - 0x8000010, 0x8001010, 0x80010, 0x81010, 0x8080010, 0x8081010 - ]; - const pc2bytes13 = [0, 0x4, 0x100, 0x104, 0, 0x4, 0x100, 0x104, 0x1, 0x5, 0x101, 0x105, 0x1, 0x5, 0x101, 0x105]; - - //how many iterations (1 for des, 3 for triple des) - const iterations = key.length > 8 ? 3 : 1; //changed by Paul 16/6/2007 to use Triple DES for 9+ byte keys - //stores the return keys - const keys = new Array(32 * iterations); - //now define the left shifts which need to be done - const shifts = [0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0]; - //other variables - let lefttemp; - let righttemp; - let m = 0; - let n = 0; - let temp; - - for (let j = 0; j < iterations; j++) { //either 1 or 3 iterations - let left = (key[m++] << 24) | (key[m++] << 16) | (key[m++] << 8) | key[m++]; - let right = (key[m++] << 24) | (key[m++] << 16) | (key[m++] << 8) | key[m++]; - - temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; - right ^= temp; - left ^= (temp << 4); - temp = ((right >>> -16) ^ left) & 0x0000ffff; - left ^= temp; - right ^= (temp << -16); - temp = ((left >>> 2) ^ right) & 0x33333333; - right ^= temp; - left ^= (temp << 2); - temp = ((right >>> -16) ^ left) & 0x0000ffff; - left ^= temp; - right ^= (temp << -16); - temp = ((left >>> 1) ^ right) & 0x55555555; - right ^= temp; - left ^= (temp << 1); - temp = ((right >>> 8) ^ left) & 0x00ff00ff; - left ^= temp; - right ^= (temp << 8); - temp = ((left >>> 1) ^ right) & 0x55555555; - right ^= temp; - left ^= (temp << 1); - - //the right side needs to be shifted and to get the last four bits of the left side - temp = (left << 8) | ((right >>> 20) & 0x000000f0); - //left needs to be put upside down - left = (right << 24) | ((right << 8) & 0xff0000) | ((right >>> 8) & 0xff00) | ((right >>> 24) & 0xf0); - right = temp; - - //now go through and perform these shifts on the left and right keys - for (let i = 0; i < shifts.length; i++) { - //shift the keys either one or two bits to the left - if (shifts[i]) { - left = (left << 2) | (left >>> 26); - right = (right << 2) | (right >>> 26); - } else { - left = (left << 1) | (left >>> 27); - right = (right << 1) | (right >>> 27); - } - left &= -0xf; - right &= -0xf; - - //now apply PC-2, in such a way that E is easier when encrypting or decrypting - //this conversion will look like PC-2 except only the last 6 bits of each byte are used - //rather than 48 consecutive bits and the order of lines will be according to - //how the S selection functions will be applied: S2, S4, S6, S8, S1, S3, S5, S7 - lefttemp = pc2bytes0[left >>> 28] | pc2bytes1[(left >>> 24) & 0xf] | pc2bytes2[(left >>> 20) & 0xf] | pc2bytes3[( - left >>> 16) & 0xf] | pc2bytes4[(left >>> 12) & 0xf] | pc2bytes5[(left >>> 8) & 0xf] | pc2bytes6[(left >>> 4) & - 0xf]; - righttemp = pc2bytes7[right >>> 28] | pc2bytes8[(right >>> 24) & 0xf] | pc2bytes9[(right >>> 20) & 0xf] | - pc2bytes10[(right >>> 16) & 0xf] | pc2bytes11[(right >>> 12) & 0xf] | pc2bytes12[(right >>> 8) & 0xf] | - pc2bytes13[(right >>> 4) & 0xf]; - temp = ((righttemp >>> 16) ^ lefttemp) & 0x0000ffff; - keys[n++] = lefttemp ^ temp; - keys[n++] = righttemp ^ (temp << 16); - } - } //for each iterations - //return the keys we've created - return keys; - } //end of desCreateKeys - - - function desAddPadding(message, padding) { - const padLength = 8 - (message.length % 8); - - let pad; - if (padding === 2 && (padLength < 8)) { //pad the message with spaces - pad = ' '.charCodeAt(0); - } else if (padding === 1) { //PKCS7 padding - pad = padLength; - } else if (!padding && (padLength < 8)) { //pad the message out with null bytes - pad = 0; - } else if (padLength === 8) { - return message; - } else { - throw new Error('des: invalid padding'); - } - - const paddedMessage = new Uint8Array(message.length + padLength); - for (let i = 0; i < message.length; i++) { - paddedMessage[i] = message[i]; - } - for (let j = 0; j < padLength; j++) { - paddedMessage[message.length + j] = pad; - } - - return paddedMessage; - } - - function desRemovePadding(message, padding) { - let padLength = null; - let pad; - if (padding === 2) { // space padded - pad = ' '.charCodeAt(0); - } else if (padding === 1) { // PKCS7 - padLength = message[message.length - 1]; - } else if (!padding) { // null padding - pad = 0; - } else { - throw new Error('des: invalid padding'); - } - - if (!padLength) { - padLength = 1; - while (message[message.length - padLength] === pad) { - padLength++; - } - padLength--; - } - - return message.subarray(0, message.length - padLength); - } - - // added by Recurity Labs - - function TripleDES(key) { - this.key = []; - - for (let i = 0; i < 3; i++) { - this.key.push(new Uint8Array(key.subarray(i * 8, (i * 8) + 8))); - } - - this.encrypt = function(block) { - return des( - desCreateKeys(this.key[2]), - des( - desCreateKeys(this.key[1]), - des( - desCreateKeys(this.key[0]), - block, true, 0, null, null - ), - false, 0, null, null - ), true, 0, null, null - ); - }; - } - - TripleDES.keySize = TripleDES.prototype.keySize = 24; - TripleDES.blockSize = TripleDES.prototype.blockSize = 8; - - // This is "original" DES - - function DES(key) { - this.key = key; - - this.encrypt = function(block, padding) { - const keys = desCreateKeys(this.key); - return des(keys, block, true, 0, null, padding); - }; - - this.decrypt = function(block, padding) { - const keys = desCreateKeys(this.key); - return des(keys, block, false, 0, null, padding); - }; - } - - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - - // Copyright 2010 pjacobs@xeekr.com . All rights reserved. - - // Modified by Recurity Labs GmbH - - // fixed/modified by Herbert Hanewinkel, www.haneWIN.de - // check www.haneWIN.de for the latest version - - // cast5.js is a Javascript implementation of CAST-128, as defined in RFC 2144. - // CAST-128 is a common OpenPGP cipher. - - - // CAST5 constructor - - function OpenPGPSymEncCAST5() { - this.BlockSize = 8; - this.KeySize = 16; - - this.setKey = function(key) { - this.masking = new Array(16); - this.rotate = new Array(16); - - this.reset(); - - if (key.length === this.KeySize) { - this.keySchedule(key); - } else { - throw new Error('CAST-128: keys must be 16 bytes'); - } - return true; - }; - - this.reset = function() { - for (let i = 0; i < 16; i++) { - this.masking[i] = 0; - this.rotate[i] = 0; - } - }; - - this.getBlockSize = function() { - return this.BlockSize; - }; - - this.encrypt = function(src) { - const dst = new Array(src.length); - - for (let i = 0; i < src.length; i += 8) { - let l = (src[i] << 24) | (src[i + 1] << 16) | (src[i + 2] << 8) | src[i + 3]; - let r = (src[i + 4] << 24) | (src[i + 5] << 16) | (src[i + 6] << 8) | src[i + 7]; - let t; - - t = r; - r = l ^ f1(r, this.masking[0], this.rotate[0]); - l = t; - t = r; - r = l ^ f2(r, this.masking[1], this.rotate[1]); - l = t; - t = r; - r = l ^ f3(r, this.masking[2], this.rotate[2]); - l = t; - t = r; - r = l ^ f1(r, this.masking[3], this.rotate[3]); - l = t; - - t = r; - r = l ^ f2(r, this.masking[4], this.rotate[4]); - l = t; - t = r; - r = l ^ f3(r, this.masking[5], this.rotate[5]); - l = t; - t = r; - r = l ^ f1(r, this.masking[6], this.rotate[6]); - l = t; - t = r; - r = l ^ f2(r, this.masking[7], this.rotate[7]); - l = t; - - t = r; - r = l ^ f3(r, this.masking[8], this.rotate[8]); - l = t; - t = r; - r = l ^ f1(r, this.masking[9], this.rotate[9]); - l = t; - t = r; - r = l ^ f2(r, this.masking[10], this.rotate[10]); - l = t; - t = r; - r = l ^ f3(r, this.masking[11], this.rotate[11]); - l = t; - - t = r; - r = l ^ f1(r, this.masking[12], this.rotate[12]); - l = t; - t = r; - r = l ^ f2(r, this.masking[13], this.rotate[13]); - l = t; - t = r; - r = l ^ f3(r, this.masking[14], this.rotate[14]); - l = t; - t = r; - r = l ^ f1(r, this.masking[15], this.rotate[15]); - l = t; - - dst[i] = (r >>> 24) & 255; - dst[i + 1] = (r >>> 16) & 255; - dst[i + 2] = (r >>> 8) & 255; - dst[i + 3] = r & 255; - dst[i + 4] = (l >>> 24) & 255; - dst[i + 5] = (l >>> 16) & 255; - dst[i + 6] = (l >>> 8) & 255; - dst[i + 7] = l & 255; - } - - return dst; - }; - - this.decrypt = function(src) { - const dst = new Array(src.length); - - for (let i = 0; i < src.length; i += 8) { - let l = (src[i] << 24) | (src[i + 1] << 16) | (src[i + 2] << 8) | src[i + 3]; - let r = (src[i + 4] << 24) | (src[i + 5] << 16) | (src[i + 6] << 8) | src[i + 7]; - let t; - - t = r; - r = l ^ f1(r, this.masking[15], this.rotate[15]); - l = t; - t = r; - r = l ^ f3(r, this.masking[14], this.rotate[14]); - l = t; - t = r; - r = l ^ f2(r, this.masking[13], this.rotate[13]); - l = t; - t = r; - r = l ^ f1(r, this.masking[12], this.rotate[12]); - l = t; - - t = r; - r = l ^ f3(r, this.masking[11], this.rotate[11]); - l = t; - t = r; - r = l ^ f2(r, this.masking[10], this.rotate[10]); - l = t; - t = r; - r = l ^ f1(r, this.masking[9], this.rotate[9]); - l = t; - t = r; - r = l ^ f3(r, this.masking[8], this.rotate[8]); - l = t; - - t = r; - r = l ^ f2(r, this.masking[7], this.rotate[7]); - l = t; - t = r; - r = l ^ f1(r, this.masking[6], this.rotate[6]); - l = t; - t = r; - r = l ^ f3(r, this.masking[5], this.rotate[5]); - l = t; - t = r; - r = l ^ f2(r, this.masking[4], this.rotate[4]); - l = t; - - t = r; - r = l ^ f1(r, this.masking[3], this.rotate[3]); - l = t; - t = r; - r = l ^ f3(r, this.masking[2], this.rotate[2]); - l = t; - t = r; - r = l ^ f2(r, this.masking[1], this.rotate[1]); - l = t; - t = r; - r = l ^ f1(r, this.masking[0], this.rotate[0]); - l = t; - - dst[i] = (r >>> 24) & 255; - dst[i + 1] = (r >>> 16) & 255; - dst[i + 2] = (r >>> 8) & 255; - dst[i + 3] = r & 255; - dst[i + 4] = (l >>> 24) & 255; - dst[i + 5] = (l >> 16) & 255; - dst[i + 6] = (l >> 8) & 255; - dst[i + 7] = l & 255; - } - - return dst; - }; - const scheduleA = new Array(4); - - scheduleA[0] = new Array(4); - scheduleA[0][0] = [4, 0, 0xd, 0xf, 0xc, 0xe, 0x8]; - scheduleA[0][1] = [5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa]; - scheduleA[0][2] = [6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9]; - scheduleA[0][3] = [7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb]; - - scheduleA[1] = new Array(4); - scheduleA[1][0] = [0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0]; - scheduleA[1][1] = [1, 4, 0, 2, 1, 3, 16 + 2]; - scheduleA[1][2] = [2, 5, 7, 6, 5, 4, 16 + 1]; - scheduleA[1][3] = [3, 7, 0xa, 9, 0xb, 8, 16 + 3]; - - scheduleA[2] = new Array(4); - scheduleA[2][0] = [4, 0, 0xd, 0xf, 0xc, 0xe, 8]; - scheduleA[2][1] = [5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa]; - scheduleA[2][2] = [6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9]; - scheduleA[2][3] = [7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb]; - - - scheduleA[3] = new Array(4); - scheduleA[3][0] = [0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0]; - scheduleA[3][1] = [1, 4, 0, 2, 1, 3, 16 + 2]; - scheduleA[3][2] = [2, 5, 7, 6, 5, 4, 16 + 1]; - scheduleA[3][3] = [3, 7, 0xa, 9, 0xb, 8, 16 + 3]; - - const scheduleB = new Array(4); - - scheduleB[0] = new Array(4); - scheduleB[0][0] = [16 + 8, 16 + 9, 16 + 7, 16 + 6, 16 + 2]; - scheduleB[0][1] = [16 + 0xa, 16 + 0xb, 16 + 5, 16 + 4, 16 + 6]; - scheduleB[0][2] = [16 + 0xc, 16 + 0xd, 16 + 3, 16 + 2, 16 + 9]; - scheduleB[0][3] = [16 + 0xe, 16 + 0xf, 16 + 1, 16 + 0, 16 + 0xc]; - - scheduleB[1] = new Array(4); - scheduleB[1][0] = [3, 2, 0xc, 0xd, 8]; - scheduleB[1][1] = [1, 0, 0xe, 0xf, 0xd]; - scheduleB[1][2] = [7, 6, 8, 9, 3]; - scheduleB[1][3] = [5, 4, 0xa, 0xb, 7]; - - - scheduleB[2] = new Array(4); - scheduleB[2][0] = [16 + 3, 16 + 2, 16 + 0xc, 16 + 0xd, 16 + 9]; - scheduleB[2][1] = [16 + 1, 16 + 0, 16 + 0xe, 16 + 0xf, 16 + 0xc]; - scheduleB[2][2] = [16 + 7, 16 + 6, 16 + 8, 16 + 9, 16 + 2]; - scheduleB[2][3] = [16 + 5, 16 + 4, 16 + 0xa, 16 + 0xb, 16 + 6]; - - - scheduleB[3] = new Array(4); - scheduleB[3][0] = [8, 9, 7, 6, 3]; - scheduleB[3][1] = [0xa, 0xb, 5, 4, 7]; - scheduleB[3][2] = [0xc, 0xd, 3, 2, 8]; - scheduleB[3][3] = [0xe, 0xf, 1, 0, 0xd]; - - // changed 'in' to 'inn' (in javascript 'in' is a reserved word) - this.keySchedule = function(inn) { - const t = new Array(8); - const k = new Array(32); - - let j; - - for (let i = 0; i < 4; i++) { - j = i * 4; - t[i] = (inn[j] << 24) | (inn[j + 1] << 16) | (inn[j + 2] << 8) | inn[j + 3]; - } - - const x = [6, 7, 4, 5]; - let ki = 0; - let w; - - for (let half = 0; half < 2; half++) { - for (let round = 0; round < 4; round++) { - for (j = 0; j < 4; j++) { - const a = scheduleA[round][j]; - w = t[a[1]]; - - w ^= sBox[4][(t[a[2] >>> 2] >>> (24 - 8 * (a[2] & 3))) & 0xff]; - w ^= sBox[5][(t[a[3] >>> 2] >>> (24 - 8 * (a[3] & 3))) & 0xff]; - w ^= sBox[6][(t[a[4] >>> 2] >>> (24 - 8 * (a[4] & 3))) & 0xff]; - w ^= sBox[7][(t[a[5] >>> 2] >>> (24 - 8 * (a[5] & 3))) & 0xff]; - w ^= sBox[x[j]][(t[a[6] >>> 2] >>> (24 - 8 * (a[6] & 3))) & 0xff]; - t[a[0]] = w; - } - - for (j = 0; j < 4; j++) { - const b = scheduleB[round][j]; - w = sBox[4][(t[b[0] >>> 2] >>> (24 - 8 * (b[0] & 3))) & 0xff]; - - w ^= sBox[5][(t[b[1] >>> 2] >>> (24 - 8 * (b[1] & 3))) & 0xff]; - w ^= sBox[6][(t[b[2] >>> 2] >>> (24 - 8 * (b[2] & 3))) & 0xff]; - w ^= sBox[7][(t[b[3] >>> 2] >>> (24 - 8 * (b[3] & 3))) & 0xff]; - w ^= sBox[4 + j][(t[b[4] >>> 2] >>> (24 - 8 * (b[4] & 3))) & 0xff]; - k[ki] = w; - ki++; - } - } - } - - for (let i = 0; i < 16; i++) { - this.masking[i] = k[i]; - this.rotate[i] = k[16 + i] & 0x1f; - } - }; - - // These are the three 'f' functions. See RFC 2144, section 2.2. - - function f1(d, m, r) { - const t = m + d; - const I = (t << r) | (t >>> (32 - r)); - return ((sBox[0][I >>> 24] ^ sBox[1][(I >>> 16) & 255]) - sBox[2][(I >>> 8) & 255]) + sBox[3][I & 255]; - } - - function f2(d, m, r) { - const t = m ^ d; - const I = (t << r) | (t >>> (32 - r)); - return ((sBox[0][I >>> 24] - sBox[1][(I >>> 16) & 255]) + sBox[2][(I >>> 8) & 255]) ^ sBox[3][I & 255]; - } - - function f3(d, m, r) { - const t = m - d; - const I = (t << r) | (t >>> (32 - r)); - return ((sBox[0][I >>> 24] + sBox[1][(I >>> 16) & 255]) ^ sBox[2][(I >>> 8) & 255]) - sBox[3][I & 255]; - } - - const sBox = new Array(8); - sBox[0] = [ - 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949, - 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, - 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, - 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0, - 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, - 0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935, - 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d, - 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, - 0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe, - 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3, - 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, - 0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291, - 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779, - 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, - 0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, - 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d, - 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, - 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, - 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c, - 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, - 0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d, - 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96, - 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, - 0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, - 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, - 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, - 0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, - 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872, - 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, - 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, - 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9, - 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf - ]; - - sBox[1] = [ - 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651, - 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, - 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, - 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806, - 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, - 0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359, - 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b, - 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, - 0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34, - 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb, - 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, - 0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860, - 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b, - 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, - 0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, - 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, - 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, - 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, - 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f, - 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, - 0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6, - 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58, - 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, - 0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, - 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6, - 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, - 0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6, - 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f, - 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, - 0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, - 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9, - 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1 - ]; - - sBox[2] = [ - 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90, - 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, - 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, - 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240, - 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, - 0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, - 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71, - 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, - 0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, - 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15, - 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, - 0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176, - 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148, - 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, - 0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, - 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e, - 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, - 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, - 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a, - 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, - 0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, - 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5, - 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, - 0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536, - 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, - 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, - 0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69, - 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, - 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, - 0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, - 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a, - 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783 - ]; - - sBox[3] = [ - 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1, - 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, - 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, - 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121, - 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, - 0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, - 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb, - 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, - 0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d, - 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6, - 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, - 0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003, - 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, - 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, - 0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, - 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a, - 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, - 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, - 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26, - 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, - 0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7, - 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417, - 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, - 0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2, - 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, - 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, - 0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, - 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, - 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, - 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, - 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282, - 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2 - ]; - - sBox[4] = [ - 0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f, - 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, - 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, - 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02, - 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, - 0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7, - 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9, - 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, - 0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774, - 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655, - 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, - 0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910, - 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1, - 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, - 0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, - 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f, - 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, - 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, - 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3, - 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, - 0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4, - 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2, - 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, - 0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5, - 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, - 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, - 0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801, - 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, - 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, - 0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, - 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8, - 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4 - ]; - - sBox[5] = [ - 0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac, - 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, - 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, - 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98, - 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, - 0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3, - 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd, - 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, - 0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9, - 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54, - 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, - 0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc, - 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf, - 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, - 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, - 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289, - 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, - 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, - 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b, - 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, - 0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13, - 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976, - 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, - 0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891, - 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da, - 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, - 0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084, - 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25, - 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, - 0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, - 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd, - 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f - ]; - - sBox[6] = [ - 0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f, - 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, - 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, - 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19, - 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, - 0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516, - 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88, - 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, - 0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756, - 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, - 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, - 0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688, - 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28, - 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, - 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, - 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, - 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, - 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, - 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566, - 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, - 0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962, - 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e, - 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, - 0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c, - 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, - 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, - 0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be, - 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767, - 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, - 0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, - 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c, - 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3 - ]; - - sBox[7] = [ - 0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5, - 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, - 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, - 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d, - 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, - 0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862, - 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc, - 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, - 0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e, - 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039, - 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, - 0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42, - 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5, - 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, - 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, - 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c, - 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, - 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, - 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70, - 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, - 0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c, - 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3, - 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, - 0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101, - 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f, - 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, - 0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a, - 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c, - 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, - 0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, - 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82, - 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e - ]; - } - - function CAST5(key) { - this.cast5 = new OpenPGPSymEncCAST5(); - this.cast5.setKey(key); - - this.encrypt = function(block) { - return this.cast5.encrypt(block); - }; - } - - CAST5.blockSize = CAST5.prototype.blockSize = 8; - CAST5.keySize = CAST5.prototype.keySize = 16; - - /* eslint-disable no-mixed-operators, no-fallthrough */ - - - /* Modified by Recurity Labs GmbH - * - * Cipher.js - * A block-cipher algorithm implementation on JavaScript - * See Cipher.readme.txt for further information. - * - * Copyright(c) 2009 Atsushi Oka [ http://oka.nu/ ] - * This script file is distributed under the LGPL - * - * ACKNOWLEDGMENT - * - * The main subroutines are written by Michiel van Everdingen. - * - * Michiel van Everdingen - * http://home.versatel.nl/MAvanEverdingen/index.html - * - * All rights for these routines are reserved to Michiel van Everdingen. - * - */ - - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - //Math - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - const MAXINT = 0xFFFFFFFF; - - function rotw(w, n) { - return (w << n | w >>> (32 - n)) & MAXINT; - } - - function getW(a, i) { - return a[i] | a[i + 1] << 8 | a[i + 2] << 16 | a[i + 3] << 24; - } - - function setW(a, i, w) { - a.splice(i, 4, w & 0xFF, (w >>> 8) & 0xFF, (w >>> 16) & 0xFF, (w >>> 24) & 0xFF); - } - - function getB(x, n) { - return (x >>> (n * 8)) & 0xFF; - } - - // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Twofish - // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - function createTwofish() { - // - let keyBytes = null; - let dataBytes = null; - let dataOffset = -1; - // var dataLength = -1; - // var idx2 = -1; - // - - let tfsKey = []; - let tfsM = [ - [], - [], - [], - [] - ]; - - function tfsInit(key) { - keyBytes = key; - let i; - let a; - let b; - let c; - let d; - const meKey = []; - const moKey = []; - const inKey = []; - let kLen; - const sKey = []; - let f01; - let f5b; - let fef; - - const q0 = [ - [8, 1, 7, 13, 6, 15, 3, 2, 0, 11, 5, 9, 14, 12, 10, 4], - [2, 8, 11, 13, 15, 7, 6, 14, 3, 1, 9, 4, 0, 10, 12, 5] - ]; - const q1 = [ - [14, 12, 11, 8, 1, 2, 3, 5, 15, 4, 10, 6, 7, 0, 9, 13], - [1, 14, 2, 11, 4, 12, 3, 7, 6, 13, 10, 5, 15, 9, 0, 8] - ]; - const q2 = [ - [11, 10, 5, 14, 6, 13, 9, 0, 12, 8, 15, 3, 2, 4, 7, 1], - [4, 12, 7, 5, 1, 6, 9, 10, 0, 14, 13, 8, 2, 11, 3, 15] - ]; - const q3 = [ - [13, 7, 15, 4, 1, 2, 6, 14, 9, 11, 3, 0, 8, 5, 12, 10], - [11, 9, 5, 1, 12, 3, 13, 14, 6, 4, 7, 15, 2, 0, 8, 10] - ]; - const ror4 = [0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15]; - const ashx = [0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 5, 14, 7]; - const q = [ - [], - [] - ]; - const m = [ - [], - [], - [], - [] - ]; - - function ffm5b(x) { - return x ^ (x >> 2) ^ [0, 90, 180, 238][x & 3]; - } - - function ffmEf(x) { - return x ^ (x >> 1) ^ (x >> 2) ^ [0, 238, 180, 90][x & 3]; - } - - function mdsRem(p, q) { - let i; - let t; - let u; - for (i = 0; i < 8; i++) { - t = q >>> 24; - q = ((q << 8) & MAXINT) | p >>> 24; - p = (p << 8) & MAXINT; - u = t << 1; - if (t & 128) { - u ^= 333; - } - q ^= t ^ (u << 16); - u ^= t >>> 1; - if (t & 1) { - u ^= 166; - } - q ^= u << 24 | u << 8; - } - return q; - } - - function qp(n, x) { - const a = x >> 4; - const b = x & 15; - const c = q0[n][a ^ b]; - const d = q1[n][ror4[b] ^ ashx[a]]; - return q3[n][ror4[d] ^ ashx[c]] << 4 | q2[n][c ^ d]; - } - - function hFun(x, key) { - let a = getB(x, 0); - let b = getB(x, 1); - let c = getB(x, 2); - let d = getB(x, 3); - switch (kLen) { - case 4: - a = q[1][a] ^ getB(key[3], 0); - b = q[0][b] ^ getB(key[3], 1); - c = q[0][c] ^ getB(key[3], 2); - d = q[1][d] ^ getB(key[3], 3); - case 3: - a = q[1][a] ^ getB(key[2], 0); - b = q[1][b] ^ getB(key[2], 1); - c = q[0][c] ^ getB(key[2], 2); - d = q[0][d] ^ getB(key[2], 3); - case 2: - a = q[0][q[0][a] ^ getB(key[1], 0)] ^ getB(key[0], 0); - b = q[0][q[1][b] ^ getB(key[1], 1)] ^ getB(key[0], 1); - c = q[1][q[0][c] ^ getB(key[1], 2)] ^ getB(key[0], 2); - d = q[1][q[1][d] ^ getB(key[1], 3)] ^ getB(key[0], 3); - } - return m[0][a] ^ m[1][b] ^ m[2][c] ^ m[3][d]; - } - - keyBytes = keyBytes.slice(0, 32); - i = keyBytes.length; - while (i !== 16 && i !== 24 && i !== 32) { - keyBytes[i++] = 0; - } - - for (i = 0; i < keyBytes.length; i += 4) { - inKey[i >> 2] = getW(keyBytes, i); - } - for (i = 0; i < 256; i++) { - q[0][i] = qp(0, i); - q[1][i] = qp(1, i); - } - for (i = 0; i < 256; i++) { - f01 = q[1][i]; - f5b = ffm5b(f01); - fef = ffmEf(f01); - m[0][i] = f01 + (f5b << 8) + (fef << 16) + (fef << 24); - m[2][i] = f5b + (fef << 8) + (f01 << 16) + (fef << 24); - f01 = q[0][i]; - f5b = ffm5b(f01); - fef = ffmEf(f01); - m[1][i] = fef + (fef << 8) + (f5b << 16) + (f01 << 24); - m[3][i] = f5b + (f01 << 8) + (fef << 16) + (f5b << 24); - } - - kLen = inKey.length / 2; - for (i = 0; i < kLen; i++) { - a = inKey[i + i]; - meKey[i] = a; - b = inKey[i + i + 1]; - moKey[i] = b; - sKey[kLen - i - 1] = mdsRem(a, b); - } - for (i = 0; i < 40; i += 2) { - a = 0x1010101 * i; - b = a + 0x1010101; - a = hFun(a, meKey); - b = rotw(hFun(b, moKey), 8); - tfsKey[i] = (a + b) & MAXINT; - tfsKey[i + 1] = rotw(a + 2 * b, 9); - } - for (i = 0; i < 256; i++) { - a = b = c = d = i; - switch (kLen) { - case 4: - a = q[1][a] ^ getB(sKey[3], 0); - b = q[0][b] ^ getB(sKey[3], 1); - c = q[0][c] ^ getB(sKey[3], 2); - d = q[1][d] ^ getB(sKey[3], 3); - case 3: - a = q[1][a] ^ getB(sKey[2], 0); - b = q[1][b] ^ getB(sKey[2], 1); - c = q[0][c] ^ getB(sKey[2], 2); - d = q[0][d] ^ getB(sKey[2], 3); - case 2: - tfsM[0][i] = m[0][q[0][q[0][a] ^ getB(sKey[1], 0)] ^ getB(sKey[0], 0)]; - tfsM[1][i] = m[1][q[0][q[1][b] ^ getB(sKey[1], 1)] ^ getB(sKey[0], 1)]; - tfsM[2][i] = m[2][q[1][q[0][c] ^ getB(sKey[1], 2)] ^ getB(sKey[0], 2)]; - tfsM[3][i] = m[3][q[1][q[1][d] ^ getB(sKey[1], 3)] ^ getB(sKey[0], 3)]; - } - } - } - - function tfsG0(x) { - return tfsM[0][getB(x, 0)] ^ tfsM[1][getB(x, 1)] ^ tfsM[2][getB(x, 2)] ^ tfsM[3][getB(x, 3)]; - } - - function tfsG1(x) { - return tfsM[0][getB(x, 3)] ^ tfsM[1][getB(x, 0)] ^ tfsM[2][getB(x, 1)] ^ tfsM[3][getB(x, 2)]; - } - - function tfsFrnd(r, blk) { - let a = tfsG0(blk[0]); - let b = tfsG1(blk[1]); - blk[2] = rotw(blk[2] ^ (a + b + tfsKey[4 * r + 8]) & MAXINT, 31); - blk[3] = rotw(blk[3], 1) ^ (a + 2 * b + tfsKey[4 * r + 9]) & MAXINT; - a = tfsG0(blk[2]); - b = tfsG1(blk[3]); - blk[0] = rotw(blk[0] ^ (a + b + tfsKey[4 * r + 10]) & MAXINT, 31); - blk[1] = rotw(blk[1], 1) ^ (a + 2 * b + tfsKey[4 * r + 11]) & MAXINT; - } - - function tfsIrnd(i, blk) { - let a = tfsG0(blk[0]); - let b = tfsG1(blk[1]); - blk[2] = rotw(blk[2], 1) ^ (a + b + tfsKey[4 * i + 10]) & MAXINT; - blk[3] = rotw(blk[3] ^ (a + 2 * b + tfsKey[4 * i + 11]) & MAXINT, 31); - a = tfsG0(blk[2]); - b = tfsG1(blk[3]); - blk[0] = rotw(blk[0], 1) ^ (a + b + tfsKey[4 * i + 8]) & MAXINT; - blk[1] = rotw(blk[1] ^ (a + 2 * b + tfsKey[4 * i + 9]) & MAXINT, 31); - } - - function tfsClose() { - tfsKey = []; - tfsM = [ - [], - [], - [], - [] - ]; - } - - function tfsEncrypt(data, offset) { - dataBytes = data; - dataOffset = offset; - const blk = [getW(dataBytes, dataOffset) ^ tfsKey[0], - getW(dataBytes, dataOffset + 4) ^ tfsKey[1], - getW(dataBytes, dataOffset + 8) ^ tfsKey[2], - getW(dataBytes, dataOffset + 12) ^ tfsKey[3]]; - for (let j = 0; j < 8; j++) { - tfsFrnd(j, blk); - } - setW(dataBytes, dataOffset, blk[2] ^ tfsKey[4]); - setW(dataBytes, dataOffset + 4, blk[3] ^ tfsKey[5]); - setW(dataBytes, dataOffset + 8, blk[0] ^ tfsKey[6]); - setW(dataBytes, dataOffset + 12, blk[1] ^ tfsKey[7]); - dataOffset += 16; - return dataBytes; - } - - function tfsDecrypt(data, offset) { - dataBytes = data; - dataOffset = offset; - const blk = [getW(dataBytes, dataOffset) ^ tfsKey[4], - getW(dataBytes, dataOffset + 4) ^ tfsKey[5], - getW(dataBytes, dataOffset + 8) ^ tfsKey[6], - getW(dataBytes, dataOffset + 12) ^ tfsKey[7]]; - for (let j = 7; j >= 0; j--) { - tfsIrnd(j, blk); - } - setW(dataBytes, dataOffset, blk[2] ^ tfsKey[0]); - setW(dataBytes, dataOffset + 4, blk[3] ^ tfsKey[1]); - setW(dataBytes, dataOffset + 8, blk[0] ^ tfsKey[2]); - setW(dataBytes, dataOffset + 12, blk[1] ^ tfsKey[3]); - dataOffset += 16; - } - - // added by Recurity Labs - - function tfsFinal() { - return dataBytes; - } - - return { - name: 'twofish', - blocksize: 128 / 8, - open: tfsInit, - close: tfsClose, - encrypt: tfsEncrypt, - decrypt: tfsDecrypt, - // added by Recurity Labs - finalize: tfsFinal - }; - } - - // added by Recurity Labs - - function TF(key) { - this.tf = createTwofish(); - this.tf.open(Array.from(key), 0); - - this.encrypt = function(block) { - return this.tf.encrypt(Array.from(block), 0); - }; - } - - TF.keySize = TF.prototype.keySize = 32; - TF.blockSize = TF.prototype.blockSize = 16; - - /* Modified by Recurity Labs GmbH - * - * Originally written by nklein software (nklein.com) - */ - - /* - * Javascript implementation based on Bruce Schneier's reference implementation. - * - * - * The constructor doesn't do much of anything. It's just here - * so we can start defining properties and methods and such. - */ - function Blowfish() {} - - /* - * Declare the block size so that protocols know what size - * Initialization Vector (IV) they will need. - */ - Blowfish.prototype.BLOCKSIZE = 8; - - /* - * These are the default SBOXES. - */ - Blowfish.prototype.SBOXES = [ - [ - 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, - 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, - 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658, - 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, - 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, - 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, - 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6, - 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, - 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, - 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, - 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, - 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, - 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, - 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, - 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, - 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, - 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, - 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, - 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, - 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, - 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, - 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, - 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, - 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, - 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, - 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, - 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8, - 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, - 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, - 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, - 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, - 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, - 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, - 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, - 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, - 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, - 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, - 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, - 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, - 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, - 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, - 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, - 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a - ], - [ - 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, - 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, - 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, - 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, - 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, - 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, - 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, - 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, - 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, - 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, - 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, - 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, - 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, - 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, - 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, - 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, - 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, - 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, - 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, - 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, - 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, - 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, - 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, - 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, - 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, - 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, - 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, - 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, - 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, - 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, - 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, - 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, - 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, - 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, - 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, - 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, - 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, - 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, - 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, - 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, - 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, - 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, - 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7 - ], - [ - 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, - 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, - 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, - 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, - 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, - 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, - 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, - 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, - 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, - 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, - 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, - 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, - 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, - 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, - 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, - 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, - 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, - 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, - 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74, - 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, - 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, - 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, - 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, - 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, - 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, - 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, - 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, - 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, - 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, - 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, - 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, - 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, - 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, - 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, - 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, - 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, - 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, - 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, - 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, - 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, - 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, - 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, - 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0 - ], - [ - 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, - 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, - 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, - 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, - 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, - 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, - 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, - 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, - 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, - 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, - 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, - 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, - 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, - 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, - 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5, - 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, - 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, - 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, - 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd, - 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, - 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, - 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, - 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc, - 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, - 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, - 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, - 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, - 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, - 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, - 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, - 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, - 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, - 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, - 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, - 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623, - 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, - 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, - 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, - 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3, - 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, - 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, - 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, - 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 - ] - ]; - - //* - //* This is the default PARRAY - //* - Blowfish.prototype.PARRAY = [ - 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, - 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, - 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b - ]; - - //* - //* This is the number of rounds the cipher will go - //* - Blowfish.prototype.NN = 16; - - //* - //* This function is needed to get rid of problems - //* with the high-bit getting set. If we don't do - //* this, then sometimes ( aa & 0x00FFFFFFFF ) is not - //* equal to ( bb & 0x00FFFFFFFF ) even when they - //* agree bit-for-bit for the first 32 bits. - //* - Blowfish.prototype._clean = function(xx) { - if (xx < 0) { - const yy = xx & 0x7FFFFFFF; - xx = yy + 0x80000000; - } - return xx; - }; - - //* - //* This is the mixing function that uses the sboxes - //* - Blowfish.prototype._F = function(xx) { - let yy; - - const dd = xx & 0x00FF; - xx >>>= 8; - const cc = xx & 0x00FF; - xx >>>= 8; - const bb = xx & 0x00FF; - xx >>>= 8; - const aa = xx & 0x00FF; - - yy = this.sboxes[0][aa] + this.sboxes[1][bb]; - yy ^= this.sboxes[2][cc]; - yy += this.sboxes[3][dd]; - - return yy; - }; - - //* - //* This method takes an array with two values, left and right - //* and does NN rounds of Blowfish on them. - //* - Blowfish.prototype._encryptBlock = function(vals) { - let dataL = vals[0]; - let dataR = vals[1]; - - let ii; - - for (ii = 0; ii < this.NN; ++ii) { - dataL ^= this.parray[ii]; - dataR = this._F(dataL) ^ dataR; - - const tmp = dataL; - dataL = dataR; - dataR = tmp; - } - - dataL ^= this.parray[this.NN + 0]; - dataR ^= this.parray[this.NN + 1]; - - vals[0] = this._clean(dataR); - vals[1] = this._clean(dataL); - }; - - //* - //* This method takes a vector of numbers and turns them - //* into long words so that they can be processed by the - //* real algorithm. - //* - //* Maybe I should make the real algorithm above take a vector - //* instead. That will involve more looping, but it won't require - //* the F() method to deconstruct the vector. - //* - Blowfish.prototype.encryptBlock = function(vector) { - let ii; - const vals = [0, 0]; - const off = this.BLOCKSIZE / 2; - for (ii = 0; ii < this.BLOCKSIZE / 2; ++ii) { - vals[0] = (vals[0] << 8) | (vector[ii + 0] & 0x00FF); - vals[1] = (vals[1] << 8) | (vector[ii + off] & 0x00FF); - } - - this._encryptBlock(vals); - - const ret = []; - for (ii = 0; ii < this.BLOCKSIZE / 2; ++ii) { - ret[ii + 0] = ((vals[0] >>> (24 - 8 * (ii))) & 0x00FF); - ret[ii + off] = ((vals[1] >>> (24 - 8 * (ii))) & 0x00FF); - // vals[ 0 ] = ( vals[ 0 ] >>> 8 ); - // vals[ 1 ] = ( vals[ 1 ] >>> 8 ); - } - - return ret; - }; - - //* - //* This method takes an array with two values, left and right - //* and undoes NN rounds of Blowfish on them. - //* - Blowfish.prototype._decryptBlock = function(vals) { - let dataL = vals[0]; - let dataR = vals[1]; - - let ii; - - for (ii = this.NN + 1; ii > 1; --ii) { - dataL ^= this.parray[ii]; - dataR = this._F(dataL) ^ dataR; - - const tmp = dataL; - dataL = dataR; - dataR = tmp; - } - - dataL ^= this.parray[1]; - dataR ^= this.parray[0]; - - vals[0] = this._clean(dataR); - vals[1] = this._clean(dataL); - }; - - //* - //* This method takes a key array and initializes the - //* sboxes and parray for this encryption. - //* - Blowfish.prototype.init = function(key) { - let ii; - let jj = 0; - - this.parray = []; - for (ii = 0; ii < this.NN + 2; ++ii) { - let data = 0x00000000; - for (let kk = 0; kk < 4; ++kk) { - data = (data << 8) | (key[jj] & 0x00FF); - if (++jj >= key.length) { - jj = 0; - } - } - this.parray[ii] = this.PARRAY[ii] ^ data; - } - - this.sboxes = []; - for (ii = 0; ii < 4; ++ii) { - this.sboxes[ii] = []; - for (jj = 0; jj < 256; ++jj) { - this.sboxes[ii][jj] = this.SBOXES[ii][jj]; - } - } - - const vals = [0x00000000, 0x00000000]; - - for (ii = 0; ii < this.NN + 2; ii += 2) { - this._encryptBlock(vals); - this.parray[ii + 0] = vals[0]; - this.parray[ii + 1] = vals[1]; - } - - for (ii = 0; ii < 4; ++ii) { - for (jj = 0; jj < 256; jj += 2) { - this._encryptBlock(vals); - this.sboxes[ii][jj + 0] = vals[0]; - this.sboxes[ii][jj + 1] = vals[1]; - } - } - }; - - // added by Recurity Labs - function BF(key) { - this.bf = new Blowfish(); - this.bf.init(key); - - this.encrypt = function(block) { - return this.bf.encryptBlock(block); - }; - } - - BF.keySize = BF.prototype.keySize = 16; - BF.blockSize = BF.prototype.blockSize = 8; - - /** - * @fileoverview Symmetric cryptography functions - * @module crypto/cipher - * @private - */ - - /** - * AES-128 encryption and decryption (ID 7) - * @function - * @param {String} key - 128-bit key - * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} - * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} - * @returns {Object} - */ - const aes128 = aes(128); - /** - * AES-128 Block Cipher (ID 8) - * @function - * @param {String} key - 192-bit key - * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} - * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} - * @returns {Object} - */ - const aes192 = aes(192); - /** - * AES-128 Block Cipher (ID 9) - * @function - * @param {String} key - 256-bit key - * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} - * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} - * @returns {Object} - */ - const aes256 = aes(256); - // Not in OpenPGP specifications - const des$1 = DES; - /** - * Triple DES Block Cipher (ID 2) - * @function - * @param {String} key - 192-bit key - * @see {@link https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-67r2.pdf|NIST SP 800-67} - * @returns {Object} - */ - const tripledes = TripleDES; - /** - * CAST-128 Block Cipher (ID 3) - * @function - * @param {String} key - 128-bit key - * @see {@link https://tools.ietf.org/html/rfc2144|The CAST-128 Encryption Algorithm} - * @returns {Object} - */ - const cast5 = CAST5; - /** - * Twofish Block Cipher (ID 10) - * @function - * @param {String} key - 256-bit key - * @see {@link https://tools.ietf.org/html/rfc4880#ref-TWOFISH|TWOFISH} - * @returns {Object} - */ - const twofish = TF; - /** - * Blowfish Block Cipher (ID 4) - * @function - * @param {String} key - 128-bit key - * @see {@link https://tools.ietf.org/html/rfc4880#ref-BLOWFISH|BLOWFISH} - * @returns {Object} - */ - const blowfish = BF; - /** - * Not implemented - * @function - * @throws {Error} - */ - const idea = function() { - throw new Error('IDEA symmetric-key algorithm not implemented'); - }; - - var cipher = /*#__PURE__*/Object.freeze({ - __proto__: null, - aes128: aes128, - aes192: aes192, - aes256: aes256, - des: des$1, - tripledes: tripledes, - cast5: cast5, - twofish: twofish, - blowfish: blowfish, - idea: idea - }); - - var sha1_asm = function ( stdlib, foreign, buffer ) { - "use asm"; - - // SHA256 state - var H0 = 0, H1 = 0, H2 = 0, H3 = 0, H4 = 0, - TOTAL0 = 0, TOTAL1 = 0; - - // HMAC state - var I0 = 0, I1 = 0, I2 = 0, I3 = 0, I4 = 0, - O0 = 0, O1 = 0, O2 = 0, O3 = 0, O4 = 0; - - // I/O buffer - var HEAP = new stdlib.Uint8Array(buffer); - - function _core ( w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15 ) { - w0 = w0|0; - w1 = w1|0; - w2 = w2|0; - w3 = w3|0; - w4 = w4|0; - w5 = w5|0; - w6 = w6|0; - w7 = w7|0; - w8 = w8|0; - w9 = w9|0; - w10 = w10|0; - w11 = w11|0; - w12 = w12|0; - w13 = w13|0; - w14 = w14|0; - w15 = w15|0; - - var a = 0, b = 0, c = 0, d = 0, e = 0, n = 0, t = 0, - w16 = 0, w17 = 0, w18 = 0, w19 = 0, - w20 = 0, w21 = 0, w22 = 0, w23 = 0, w24 = 0, w25 = 0, w26 = 0, w27 = 0, w28 = 0, w29 = 0, - w30 = 0, w31 = 0, w32 = 0, w33 = 0, w34 = 0, w35 = 0, w36 = 0, w37 = 0, w38 = 0, w39 = 0, - w40 = 0, w41 = 0, w42 = 0, w43 = 0, w44 = 0, w45 = 0, w46 = 0, w47 = 0, w48 = 0, w49 = 0, - w50 = 0, w51 = 0, w52 = 0, w53 = 0, w54 = 0, w55 = 0, w56 = 0, w57 = 0, w58 = 0, w59 = 0, - w60 = 0, w61 = 0, w62 = 0, w63 = 0, w64 = 0, w65 = 0, w66 = 0, w67 = 0, w68 = 0, w69 = 0, - w70 = 0, w71 = 0, w72 = 0, w73 = 0, w74 = 0, w75 = 0, w76 = 0, w77 = 0, w78 = 0, w79 = 0; - - a = H0; - b = H1; - c = H2; - d = H3; - e = H4; - - // 0 - t = ( w0 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 1 - t = ( w1 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 2 - t = ( w2 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 3 - t = ( w3 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 4 - t = ( w4 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 5 - t = ( w5 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 6 - t = ( w6 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 7 - t = ( w7 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 8 - t = ( w8 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 9 - t = ( w9 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 10 - t = ( w10 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 11 - t = ( w11 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 12 - t = ( w12 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 13 - t = ( w13 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 14 - t = ( w14 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 15 - t = ( w15 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 16 - n = w13 ^ w8 ^ w2 ^ w0; - w16 = (n << 1) | (n >>> 31); - t = (w16 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 17 - n = w14 ^ w9 ^ w3 ^ w1; - w17 = (n << 1) | (n >>> 31); - t = (w17 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 18 - n = w15 ^ w10 ^ w4 ^ w2; - w18 = (n << 1) | (n >>> 31); - t = (w18 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 19 - n = w16 ^ w11 ^ w5 ^ w3; - w19 = (n << 1) | (n >>> 31); - t = (w19 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 20 - n = w17 ^ w12 ^ w6 ^ w4; - w20 = (n << 1) | (n >>> 31); - t = (w20 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 21 - n = w18 ^ w13 ^ w7 ^ w5; - w21 = (n << 1) | (n >>> 31); - t = (w21 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 22 - n = w19 ^ w14 ^ w8 ^ w6; - w22 = (n << 1) | (n >>> 31); - t = (w22 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 23 - n = w20 ^ w15 ^ w9 ^ w7; - w23 = (n << 1) | (n >>> 31); - t = (w23 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 24 - n = w21 ^ w16 ^ w10 ^ w8; - w24 = (n << 1) | (n >>> 31); - t = (w24 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 25 - n = w22 ^ w17 ^ w11 ^ w9; - w25 = (n << 1) | (n >>> 31); - t = (w25 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 26 - n = w23 ^ w18 ^ w12 ^ w10; - w26 = (n << 1) | (n >>> 31); - t = (w26 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 27 - n = w24 ^ w19 ^ w13 ^ w11; - w27 = (n << 1) | (n >>> 31); - t = (w27 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 28 - n = w25 ^ w20 ^ w14 ^ w12; - w28 = (n << 1) | (n >>> 31); - t = (w28 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 29 - n = w26 ^ w21 ^ w15 ^ w13; - w29 = (n << 1) | (n >>> 31); - t = (w29 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 30 - n = w27 ^ w22 ^ w16 ^ w14; - w30 = (n << 1) | (n >>> 31); - t = (w30 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 31 - n = w28 ^ w23 ^ w17 ^ w15; - w31 = (n << 1) | (n >>> 31); - t = (w31 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 32 - n = w29 ^ w24 ^ w18 ^ w16; - w32 = (n << 1) | (n >>> 31); - t = (w32 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 33 - n = w30 ^ w25 ^ w19 ^ w17; - w33 = (n << 1) | (n >>> 31); - t = (w33 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 34 - n = w31 ^ w26 ^ w20 ^ w18; - w34 = (n << 1) | (n >>> 31); - t = (w34 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 35 - n = w32 ^ w27 ^ w21 ^ w19; - w35 = (n << 1) | (n >>> 31); - t = (w35 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 36 - n = w33 ^ w28 ^ w22 ^ w20; - w36 = (n << 1) | (n >>> 31); - t = (w36 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 37 - n = w34 ^ w29 ^ w23 ^ w21; - w37 = (n << 1) | (n >>> 31); - t = (w37 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 38 - n = w35 ^ w30 ^ w24 ^ w22; - w38 = (n << 1) | (n >>> 31); - t = (w38 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 39 - n = w36 ^ w31 ^ w25 ^ w23; - w39 = (n << 1) | (n >>> 31); - t = (w39 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 40 - n = w37 ^ w32 ^ w26 ^ w24; - w40 = (n << 1) | (n >>> 31); - t = (w40 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 41 - n = w38 ^ w33 ^ w27 ^ w25; - w41 = (n << 1) | (n >>> 31); - t = (w41 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 42 - n = w39 ^ w34 ^ w28 ^ w26; - w42 = (n << 1) | (n >>> 31); - t = (w42 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 43 - n = w40 ^ w35 ^ w29 ^ w27; - w43 = (n << 1) | (n >>> 31); - t = (w43 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 44 - n = w41 ^ w36 ^ w30 ^ w28; - w44 = (n << 1) | (n >>> 31); - t = (w44 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 45 - n = w42 ^ w37 ^ w31 ^ w29; - w45 = (n << 1) | (n >>> 31); - t = (w45 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 46 - n = w43 ^ w38 ^ w32 ^ w30; - w46 = (n << 1) | (n >>> 31); - t = (w46 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 47 - n = w44 ^ w39 ^ w33 ^ w31; - w47 = (n << 1) | (n >>> 31); - t = (w47 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 48 - n = w45 ^ w40 ^ w34 ^ w32; - w48 = (n << 1) | (n >>> 31); - t = (w48 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 49 - n = w46 ^ w41 ^ w35 ^ w33; - w49 = (n << 1) | (n >>> 31); - t = (w49 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 50 - n = w47 ^ w42 ^ w36 ^ w34; - w50 = (n << 1) | (n >>> 31); - t = (w50 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 51 - n = w48 ^ w43 ^ w37 ^ w35; - w51 = (n << 1) | (n >>> 31); - t = (w51 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 52 - n = w49 ^ w44 ^ w38 ^ w36; - w52 = (n << 1) | (n >>> 31); - t = (w52 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 53 - n = w50 ^ w45 ^ w39 ^ w37; - w53 = (n << 1) | (n >>> 31); - t = (w53 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 54 - n = w51 ^ w46 ^ w40 ^ w38; - w54 = (n << 1) | (n >>> 31); - t = (w54 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 55 - n = w52 ^ w47 ^ w41 ^ w39; - w55 = (n << 1) | (n >>> 31); - t = (w55 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 56 - n = w53 ^ w48 ^ w42 ^ w40; - w56 = (n << 1) | (n >>> 31); - t = (w56 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 57 - n = w54 ^ w49 ^ w43 ^ w41; - w57 = (n << 1) | (n >>> 31); - t = (w57 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 58 - n = w55 ^ w50 ^ w44 ^ w42; - w58 = (n << 1) | (n >>> 31); - t = (w58 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 59 - n = w56 ^ w51 ^ w45 ^ w43; - w59 = (n << 1) | (n >>> 31); - t = (w59 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 60 - n = w57 ^ w52 ^ w46 ^ w44; - w60 = (n << 1) | (n >>> 31); - t = (w60 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 61 - n = w58 ^ w53 ^ w47 ^ w45; - w61 = (n << 1) | (n >>> 31); - t = (w61 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 62 - n = w59 ^ w54 ^ w48 ^ w46; - w62 = (n << 1) | (n >>> 31); - t = (w62 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 63 - n = w60 ^ w55 ^ w49 ^ w47; - w63 = (n << 1) | (n >>> 31); - t = (w63 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 64 - n = w61 ^ w56 ^ w50 ^ w48; - w64 = (n << 1) | (n >>> 31); - t = (w64 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 65 - n = w62 ^ w57 ^ w51 ^ w49; - w65 = (n << 1) | (n >>> 31); - t = (w65 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 66 - n = w63 ^ w58 ^ w52 ^ w50; - w66 = (n << 1) | (n >>> 31); - t = (w66 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 67 - n = w64 ^ w59 ^ w53 ^ w51; - w67 = (n << 1) | (n >>> 31); - t = (w67 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 68 - n = w65 ^ w60 ^ w54 ^ w52; - w68 = (n << 1) | (n >>> 31); - t = (w68 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 69 - n = w66 ^ w61 ^ w55 ^ w53; - w69 = (n << 1) | (n >>> 31); - t = (w69 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 70 - n = w67 ^ w62 ^ w56 ^ w54; - w70 = (n << 1) | (n >>> 31); - t = (w70 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 71 - n = w68 ^ w63 ^ w57 ^ w55; - w71 = (n << 1) | (n >>> 31); - t = (w71 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 72 - n = w69 ^ w64 ^ w58 ^ w56; - w72 = (n << 1) | (n >>> 31); - t = (w72 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 73 - n = w70 ^ w65 ^ w59 ^ w57; - w73 = (n << 1) | (n >>> 31); - t = (w73 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 74 - n = w71 ^ w66 ^ w60 ^ w58; - w74 = (n << 1) | (n >>> 31); - t = (w74 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 75 - n = w72 ^ w67 ^ w61 ^ w59; - w75 = (n << 1) | (n >>> 31); - t = (w75 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 76 - n = w73 ^ w68 ^ w62 ^ w60; - w76 = (n << 1) | (n >>> 31); - t = (w76 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 77 - n = w74 ^ w69 ^ w63 ^ w61; - w77 = (n << 1) | (n >>> 31); - t = (w77 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 78 - n = w75 ^ w70 ^ w64 ^ w62; - w78 = (n << 1) | (n >>> 31); - t = (w78 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 79 - n = w76 ^ w71 ^ w65 ^ w63; - w79 = (n << 1) | (n >>> 31); - t = (w79 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - H0 = ( H0 + a )|0; - H1 = ( H1 + b )|0; - H2 = ( H2 + c )|0; - H3 = ( H3 + d )|0; - H4 = ( H4 + e )|0; - - } - - function _core_heap ( offset ) { - offset = offset|0; - - _core( - HEAP[offset|0]<<24 | HEAP[offset|1]<<16 | HEAP[offset|2]<<8 | HEAP[offset|3], - HEAP[offset|4]<<24 | HEAP[offset|5]<<16 | HEAP[offset|6]<<8 | HEAP[offset|7], - HEAP[offset|8]<<24 | HEAP[offset|9]<<16 | HEAP[offset|10]<<8 | HEAP[offset|11], - HEAP[offset|12]<<24 | HEAP[offset|13]<<16 | HEAP[offset|14]<<8 | HEAP[offset|15], - HEAP[offset|16]<<24 | HEAP[offset|17]<<16 | HEAP[offset|18]<<8 | HEAP[offset|19], - HEAP[offset|20]<<24 | HEAP[offset|21]<<16 | HEAP[offset|22]<<8 | HEAP[offset|23], - HEAP[offset|24]<<24 | HEAP[offset|25]<<16 | HEAP[offset|26]<<8 | HEAP[offset|27], - HEAP[offset|28]<<24 | HEAP[offset|29]<<16 | HEAP[offset|30]<<8 | HEAP[offset|31], - HEAP[offset|32]<<24 | HEAP[offset|33]<<16 | HEAP[offset|34]<<8 | HEAP[offset|35], - HEAP[offset|36]<<24 | HEAP[offset|37]<<16 | HEAP[offset|38]<<8 | HEAP[offset|39], - HEAP[offset|40]<<24 | HEAP[offset|41]<<16 | HEAP[offset|42]<<8 | HEAP[offset|43], - HEAP[offset|44]<<24 | HEAP[offset|45]<<16 | HEAP[offset|46]<<8 | HEAP[offset|47], - HEAP[offset|48]<<24 | HEAP[offset|49]<<16 | HEAP[offset|50]<<8 | HEAP[offset|51], - HEAP[offset|52]<<24 | HEAP[offset|53]<<16 | HEAP[offset|54]<<8 | HEAP[offset|55], - HEAP[offset|56]<<24 | HEAP[offset|57]<<16 | HEAP[offset|58]<<8 | HEAP[offset|59], - HEAP[offset|60]<<24 | HEAP[offset|61]<<16 | HEAP[offset|62]<<8 | HEAP[offset|63] - ); - } - - // offset — multiple of 32 - function _state_to_heap ( output ) { - output = output|0; - - HEAP[output|0] = H0>>>24; - HEAP[output|1] = H0>>>16&255; - HEAP[output|2] = H0>>>8&255; - HEAP[output|3] = H0&255; - HEAP[output|4] = H1>>>24; - HEAP[output|5] = H1>>>16&255; - HEAP[output|6] = H1>>>8&255; - HEAP[output|7] = H1&255; - HEAP[output|8] = H2>>>24; - HEAP[output|9] = H2>>>16&255; - HEAP[output|10] = H2>>>8&255; - HEAP[output|11] = H2&255; - HEAP[output|12] = H3>>>24; - HEAP[output|13] = H3>>>16&255; - HEAP[output|14] = H3>>>8&255; - HEAP[output|15] = H3&255; - HEAP[output|16] = H4>>>24; - HEAP[output|17] = H4>>>16&255; - HEAP[output|18] = H4>>>8&255; - HEAP[output|19] = H4&255; - } - - function reset () { - H0 = 0x67452301; - H1 = 0xefcdab89; - H2 = 0x98badcfe; - H3 = 0x10325476; - H4 = 0xc3d2e1f0; - TOTAL0 = TOTAL1 = 0; - } - - function init ( h0, h1, h2, h3, h4, total0, total1 ) { - h0 = h0|0; - h1 = h1|0; - h2 = h2|0; - h3 = h3|0; - h4 = h4|0; - total0 = total0|0; - total1 = total1|0; - - H0 = h0; - H1 = h1; - H2 = h2; - H3 = h3; - H4 = h4; - TOTAL0 = total0; - TOTAL1 = total1; - } - - // offset — multiple of 64 - function process ( offset, length ) { - offset = offset|0; - length = length|0; - - var hashed = 0; - - if ( offset & 63 ) - return -1; - - while ( (length|0) >= 64 ) { - _core_heap(offset); - - offset = ( offset + 64 )|0; - length = ( length - 64 )|0; - - hashed = ( hashed + 64 )|0; - } - - TOTAL0 = ( TOTAL0 + hashed )|0; - if ( TOTAL0>>>0 < hashed>>>0 ) TOTAL1 = ( TOTAL1 + 1 )|0; - - return hashed|0; - } - - // offset — multiple of 64 - // output — multiple of 32 - function finish ( offset, length, output ) { - offset = offset|0; - length = length|0; - output = output|0; - - var hashed = 0, - i = 0; - - if ( offset & 63 ) - return -1; - - if ( ~output ) - if ( output & 31 ) - return -1; - - if ( (length|0) >= 64 ) { - hashed = process( offset, length )|0; - if ( (hashed|0) == -1 ) - return -1; - - offset = ( offset + hashed )|0; - length = ( length - hashed )|0; - } - - hashed = ( hashed + length )|0; - TOTAL0 = ( TOTAL0 + length )|0; - if ( TOTAL0>>>0 < length>>>0 ) TOTAL1 = (TOTAL1 + 1)|0; - - HEAP[offset|length] = 0x80; - - if ( (length|0) >= 56 ) { - for ( i = (length+1)|0; (i|0) < 64; i = (i+1)|0 ) - HEAP[offset|i] = 0x00; - _core_heap(offset); - - length = 0; - - HEAP[offset|0] = 0; - } - - for ( i = (length+1)|0; (i|0) < 59; i = (i+1)|0 ) - HEAP[offset|i] = 0; - - HEAP[offset|56] = TOTAL1>>>21&255; - HEAP[offset|57] = TOTAL1>>>13&255; - HEAP[offset|58] = TOTAL1>>>5&255; - HEAP[offset|59] = TOTAL1<<3&255 | TOTAL0>>>29; - HEAP[offset|60] = TOTAL0>>>21&255; - HEAP[offset|61] = TOTAL0>>>13&255; - HEAP[offset|62] = TOTAL0>>>5&255; - HEAP[offset|63] = TOTAL0<<3&255; - _core_heap(offset); - - if ( ~output ) - _state_to_heap(output); - - return hashed|0; - } - - function hmac_reset () { - H0 = I0; - H1 = I1; - H2 = I2; - H3 = I3; - H4 = I4; - TOTAL0 = 64; - TOTAL1 = 0; - } - - function _hmac_opad () { - H0 = O0; - H1 = O1; - H2 = O2; - H3 = O3; - H4 = O4; - TOTAL0 = 64; - TOTAL1 = 0; - } - - function hmac_init ( p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15 ) { - p0 = p0|0; - p1 = p1|0; - p2 = p2|0; - p3 = p3|0; - p4 = p4|0; - p5 = p5|0; - p6 = p6|0; - p7 = p7|0; - p8 = p8|0; - p9 = p9|0; - p10 = p10|0; - p11 = p11|0; - p12 = p12|0; - p13 = p13|0; - p14 = p14|0; - p15 = p15|0; - - // opad - reset(); - _core( - p0 ^ 0x5c5c5c5c, - p1 ^ 0x5c5c5c5c, - p2 ^ 0x5c5c5c5c, - p3 ^ 0x5c5c5c5c, - p4 ^ 0x5c5c5c5c, - p5 ^ 0x5c5c5c5c, - p6 ^ 0x5c5c5c5c, - p7 ^ 0x5c5c5c5c, - p8 ^ 0x5c5c5c5c, - p9 ^ 0x5c5c5c5c, - p10 ^ 0x5c5c5c5c, - p11 ^ 0x5c5c5c5c, - p12 ^ 0x5c5c5c5c, - p13 ^ 0x5c5c5c5c, - p14 ^ 0x5c5c5c5c, - p15 ^ 0x5c5c5c5c - ); - O0 = H0; - O1 = H1; - O2 = H2; - O3 = H3; - O4 = H4; - - // ipad - reset(); - _core( - p0 ^ 0x36363636, - p1 ^ 0x36363636, - p2 ^ 0x36363636, - p3 ^ 0x36363636, - p4 ^ 0x36363636, - p5 ^ 0x36363636, - p6 ^ 0x36363636, - p7 ^ 0x36363636, - p8 ^ 0x36363636, - p9 ^ 0x36363636, - p10 ^ 0x36363636, - p11 ^ 0x36363636, - p12 ^ 0x36363636, - p13 ^ 0x36363636, - p14 ^ 0x36363636, - p15 ^ 0x36363636 - ); - I0 = H0; - I1 = H1; - I2 = H2; - I3 = H3; - I4 = H4; - - TOTAL0 = 64; - TOTAL1 = 0; - } - - // offset — multiple of 64 - // output — multiple of 32 - function hmac_finish ( offset, length, output ) { - offset = offset|0; - length = length|0; - output = output|0; - - var t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, hashed = 0; - - if ( offset & 63 ) - return -1; - - if ( ~output ) - if ( output & 31 ) - return -1; - - hashed = finish( offset, length, -1 )|0; - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; - - _hmac_opad(); - _core( t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672 ); - - if ( ~output ) - _state_to_heap(output); - - return hashed|0; - } - - // salt is assumed to be already processed - // offset — multiple of 64 - // output — multiple of 32 - function pbkdf2_generate_block ( offset, length, block, count, output ) { - offset = offset|0; - length = length|0; - block = block|0; - count = count|0; - output = output|0; - - var h0 = 0, h1 = 0, h2 = 0, h3 = 0, h4 = 0, - t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0; - - if ( offset & 63 ) - return -1; - - if ( ~output ) - if ( output & 31 ) - return -1; - - // pad block number into heap - // FIXME probable OOB write - HEAP[(offset+length)|0] = block>>>24; - HEAP[(offset+length+1)|0] = block>>>16&255; - HEAP[(offset+length+2)|0] = block>>>8&255; - HEAP[(offset+length+3)|0] = block&255; - - // finish first iteration - hmac_finish( offset, (length+4)|0, -1 )|0; - h0 = t0 = H0, h1 = t1 = H1, h2 = t2 = H2, h3 = t3 = H3, h4 = t4 = H4; - count = (count-1)|0; - - // perform the rest iterations - while ( (count|0) > 0 ) { - hmac_reset(); - _core( t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672 ); - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; - - _hmac_opad(); - _core( t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672 ); - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; - - h0 = h0 ^ H0; - h1 = h1 ^ H1; - h2 = h2 ^ H2; - h3 = h3 ^ H3; - h4 = h4 ^ H4; - - count = (count-1)|0; - } - - H0 = h0; - H1 = h1; - H2 = h2; - H3 = h3; - H4 = h4; - - if ( ~output ) - _state_to_heap(output); - - return 0; - } - - return { - // SHA1 - reset: reset, - init: init, - process: process, - finish: finish, - - // HMAC-SHA1 - hmac_reset: hmac_reset, - hmac_init: hmac_init, - hmac_finish: hmac_finish, - - // PBKDF2-HMAC-SHA1 - pbkdf2_generate_block: pbkdf2_generate_block - } - }; - - class Hash { - constructor() { - this.pos = 0; - this.len = 0; - } - reset() { - const { asm } = this.acquire_asm(); - this.result = null; - this.pos = 0; - this.len = 0; - asm.reset(); - return this; - } - process(data) { - if (this.result !== null) - throw new IllegalStateError('state must be reset before processing new data'); - const { asm, heap } = this.acquire_asm(); - let hpos = this.pos; - let hlen = this.len; - let dpos = 0; - let dlen = data.length; - let wlen = 0; - while (dlen > 0) { - wlen = _heap_write(heap, hpos + hlen, data, dpos, dlen); - hlen += wlen; - dpos += wlen; - dlen -= wlen; - wlen = asm.process(hpos, hlen); - hpos += wlen; - hlen -= wlen; - if (!hlen) - hpos = 0; - } - this.pos = hpos; - this.len = hlen; - return this; - } - finish() { - if (this.result !== null) - throw new IllegalStateError('state must be reset before processing new data'); - const { asm, heap } = this.acquire_asm(); - asm.finish(this.pos, this.len, 0); - this.result = new Uint8Array(this.HASH_SIZE); - this.result.set(heap.subarray(0, this.HASH_SIZE)); - this.pos = 0; - this.len = 0; - this.release_asm(); - return this; - } - } - - const _sha1_block_size = 64; - const _sha1_hash_size = 20; - const heap_pool$1 = []; - const asm_pool$1 = []; - class Sha1 extends Hash { - constructor() { - super(); - this.NAME = 'sha1'; - this.BLOCK_SIZE = _sha1_block_size; - this.HASH_SIZE = _sha1_hash_size; - this.acquire_asm(); - } - acquire_asm() { - if (this.heap === undefined || this.asm === undefined) { - this.heap = heap_pool$1.pop() || _heap_init(); - this.asm = asm_pool$1.pop() || sha1_asm({ Uint8Array: Uint8Array }, null, this.heap.buffer); - this.reset(); - } - return { heap: this.heap, asm: this.asm }; - } - release_asm() { - if (this.heap !== undefined && this.asm !== undefined) { - heap_pool$1.push(this.heap); - asm_pool$1.push(this.asm); - } - this.heap = undefined; - this.asm = undefined; - } - static bytes(data) { - return new Sha1().process(data).finish().result; - } - } - Sha1.NAME = 'sha1'; - Sha1.heap_pool = []; - Sha1.asm_pool = []; - Sha1.asm_function = sha1_asm; - - var sha256_asm = function ( stdlib, foreign, buffer ) { - "use asm"; - - // SHA256 state - var H0 = 0, H1 = 0, H2 = 0, H3 = 0, H4 = 0, H5 = 0, H6 = 0, H7 = 0, - TOTAL0 = 0, TOTAL1 = 0; - - // HMAC state - var I0 = 0, I1 = 0, I2 = 0, I3 = 0, I4 = 0, I5 = 0, I6 = 0, I7 = 0, - O0 = 0, O1 = 0, O2 = 0, O3 = 0, O4 = 0, O5 = 0, O6 = 0, O7 = 0; - - // I/O buffer - var HEAP = new stdlib.Uint8Array(buffer); - - function _core ( w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15 ) { - w0 = w0|0; - w1 = w1|0; - w2 = w2|0; - w3 = w3|0; - w4 = w4|0; - w5 = w5|0; - w6 = w6|0; - w7 = w7|0; - w8 = w8|0; - w9 = w9|0; - w10 = w10|0; - w11 = w11|0; - w12 = w12|0; - w13 = w13|0; - w14 = w14|0; - w15 = w15|0; - - var a = 0, b = 0, c = 0, d = 0, e = 0, f = 0, g = 0, h = 0; - - a = H0; - b = H1; - c = H2; - d = H3; - e = H4; - f = H5; - g = H6; - h = H7; - - // 0 - h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x428a2f98 )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 1 - g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x71374491 )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 2 - f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0xb5c0fbcf )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 3 - e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0xe9b5dba5 )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 4 - d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x3956c25b )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 5 - c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x59f111f1 )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 6 - b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x923f82a4 )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 7 - a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0xab1c5ed5 )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - // 8 - h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0xd807aa98 )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 9 - g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x12835b01 )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 10 - f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x243185be )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 11 - e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x550c7dc3 )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 12 - d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x72be5d74 )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 13 - c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x80deb1fe )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 14 - b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x9bdc06a7 )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 15 - a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0xc19bf174 )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - // 16 - w0 = ( ( w1>>>7 ^ w1>>>18 ^ w1>>>3 ^ w1<<25 ^ w1<<14 ) + ( w14>>>17 ^ w14>>>19 ^ w14>>>10 ^ w14<<15 ^ w14<<13 ) + w0 + w9 )|0; - h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0xe49b69c1 )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 17 - w1 = ( ( w2>>>7 ^ w2>>>18 ^ w2>>>3 ^ w2<<25 ^ w2<<14 ) + ( w15>>>17 ^ w15>>>19 ^ w15>>>10 ^ w15<<15 ^ w15<<13 ) + w1 + w10 )|0; - g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0xefbe4786 )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 18 - w2 = ( ( w3>>>7 ^ w3>>>18 ^ w3>>>3 ^ w3<<25 ^ w3<<14 ) + ( w0>>>17 ^ w0>>>19 ^ w0>>>10 ^ w0<<15 ^ w0<<13 ) + w2 + w11 )|0; - f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x0fc19dc6 )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 19 - w3 = ( ( w4>>>7 ^ w4>>>18 ^ w4>>>3 ^ w4<<25 ^ w4<<14 ) + ( w1>>>17 ^ w1>>>19 ^ w1>>>10 ^ w1<<15 ^ w1<<13 ) + w3 + w12 )|0; - e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x240ca1cc )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 20 - w4 = ( ( w5>>>7 ^ w5>>>18 ^ w5>>>3 ^ w5<<25 ^ w5<<14 ) + ( w2>>>17 ^ w2>>>19 ^ w2>>>10 ^ w2<<15 ^ w2<<13 ) + w4 + w13 )|0; - d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x2de92c6f )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 21 - w5 = ( ( w6>>>7 ^ w6>>>18 ^ w6>>>3 ^ w6<<25 ^ w6<<14 ) + ( w3>>>17 ^ w3>>>19 ^ w3>>>10 ^ w3<<15 ^ w3<<13 ) + w5 + w14 )|0; - c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x4a7484aa )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 22 - w6 = ( ( w7>>>7 ^ w7>>>18 ^ w7>>>3 ^ w7<<25 ^ w7<<14 ) + ( w4>>>17 ^ w4>>>19 ^ w4>>>10 ^ w4<<15 ^ w4<<13 ) + w6 + w15 )|0; - b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x5cb0a9dc )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 23 - w7 = ( ( w8>>>7 ^ w8>>>18 ^ w8>>>3 ^ w8<<25 ^ w8<<14 ) + ( w5>>>17 ^ w5>>>19 ^ w5>>>10 ^ w5<<15 ^ w5<<13 ) + w7 + w0 )|0; - a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x76f988da )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - // 24 - w8 = ( ( w9>>>7 ^ w9>>>18 ^ w9>>>3 ^ w9<<25 ^ w9<<14 ) + ( w6>>>17 ^ w6>>>19 ^ w6>>>10 ^ w6<<15 ^ w6<<13 ) + w8 + w1 )|0; - h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x983e5152 )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 25 - w9 = ( ( w10>>>7 ^ w10>>>18 ^ w10>>>3 ^ w10<<25 ^ w10<<14 ) + ( w7>>>17 ^ w7>>>19 ^ w7>>>10 ^ w7<<15 ^ w7<<13 ) + w9 + w2 )|0; - g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0xa831c66d )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 26 - w10 = ( ( w11>>>7 ^ w11>>>18 ^ w11>>>3 ^ w11<<25 ^ w11<<14 ) + ( w8>>>17 ^ w8>>>19 ^ w8>>>10 ^ w8<<15 ^ w8<<13 ) + w10 + w3 )|0; - f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0xb00327c8 )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 27 - w11 = ( ( w12>>>7 ^ w12>>>18 ^ w12>>>3 ^ w12<<25 ^ w12<<14 ) + ( w9>>>17 ^ w9>>>19 ^ w9>>>10 ^ w9<<15 ^ w9<<13 ) + w11 + w4 )|0; - e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0xbf597fc7 )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 28 - w12 = ( ( w13>>>7 ^ w13>>>18 ^ w13>>>3 ^ w13<<25 ^ w13<<14 ) + ( w10>>>17 ^ w10>>>19 ^ w10>>>10 ^ w10<<15 ^ w10<<13 ) + w12 + w5 )|0; - d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0xc6e00bf3 )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 29 - w13 = ( ( w14>>>7 ^ w14>>>18 ^ w14>>>3 ^ w14<<25 ^ w14<<14 ) + ( w11>>>17 ^ w11>>>19 ^ w11>>>10 ^ w11<<15 ^ w11<<13 ) + w13 + w6 )|0; - c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0xd5a79147 )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 30 - w14 = ( ( w15>>>7 ^ w15>>>18 ^ w15>>>3 ^ w15<<25 ^ w15<<14 ) + ( w12>>>17 ^ w12>>>19 ^ w12>>>10 ^ w12<<15 ^ w12<<13 ) + w14 + w7 )|0; - b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x06ca6351 )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 31 - w15 = ( ( w0>>>7 ^ w0>>>18 ^ w0>>>3 ^ w0<<25 ^ w0<<14 ) + ( w13>>>17 ^ w13>>>19 ^ w13>>>10 ^ w13<<15 ^ w13<<13 ) + w15 + w8 )|0; - a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x14292967 )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - // 32 - w0 = ( ( w1>>>7 ^ w1>>>18 ^ w1>>>3 ^ w1<<25 ^ w1<<14 ) + ( w14>>>17 ^ w14>>>19 ^ w14>>>10 ^ w14<<15 ^ w14<<13 ) + w0 + w9 )|0; - h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x27b70a85 )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 33 - w1 = ( ( w2>>>7 ^ w2>>>18 ^ w2>>>3 ^ w2<<25 ^ w2<<14 ) + ( w15>>>17 ^ w15>>>19 ^ w15>>>10 ^ w15<<15 ^ w15<<13 ) + w1 + w10 )|0; - g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x2e1b2138 )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 34 - w2 = ( ( w3>>>7 ^ w3>>>18 ^ w3>>>3 ^ w3<<25 ^ w3<<14 ) + ( w0>>>17 ^ w0>>>19 ^ w0>>>10 ^ w0<<15 ^ w0<<13 ) + w2 + w11 )|0; - f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x4d2c6dfc )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 35 - w3 = ( ( w4>>>7 ^ w4>>>18 ^ w4>>>3 ^ w4<<25 ^ w4<<14 ) + ( w1>>>17 ^ w1>>>19 ^ w1>>>10 ^ w1<<15 ^ w1<<13 ) + w3 + w12 )|0; - e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x53380d13 )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 36 - w4 = ( ( w5>>>7 ^ w5>>>18 ^ w5>>>3 ^ w5<<25 ^ w5<<14 ) + ( w2>>>17 ^ w2>>>19 ^ w2>>>10 ^ w2<<15 ^ w2<<13 ) + w4 + w13 )|0; - d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x650a7354 )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 37 - w5 = ( ( w6>>>7 ^ w6>>>18 ^ w6>>>3 ^ w6<<25 ^ w6<<14 ) + ( w3>>>17 ^ w3>>>19 ^ w3>>>10 ^ w3<<15 ^ w3<<13 ) + w5 + w14 )|0; - c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x766a0abb )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 38 - w6 = ( ( w7>>>7 ^ w7>>>18 ^ w7>>>3 ^ w7<<25 ^ w7<<14 ) + ( w4>>>17 ^ w4>>>19 ^ w4>>>10 ^ w4<<15 ^ w4<<13 ) + w6 + w15 )|0; - b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x81c2c92e )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 39 - w7 = ( ( w8>>>7 ^ w8>>>18 ^ w8>>>3 ^ w8<<25 ^ w8<<14 ) + ( w5>>>17 ^ w5>>>19 ^ w5>>>10 ^ w5<<15 ^ w5<<13 ) + w7 + w0 )|0; - a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x92722c85 )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - // 40 - w8 = ( ( w9>>>7 ^ w9>>>18 ^ w9>>>3 ^ w9<<25 ^ w9<<14 ) + ( w6>>>17 ^ w6>>>19 ^ w6>>>10 ^ w6<<15 ^ w6<<13 ) + w8 + w1 )|0; - h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0xa2bfe8a1 )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 41 - w9 = ( ( w10>>>7 ^ w10>>>18 ^ w10>>>3 ^ w10<<25 ^ w10<<14 ) + ( w7>>>17 ^ w7>>>19 ^ w7>>>10 ^ w7<<15 ^ w7<<13 ) + w9 + w2 )|0; - g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0xa81a664b )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 42 - w10 = ( ( w11>>>7 ^ w11>>>18 ^ w11>>>3 ^ w11<<25 ^ w11<<14 ) + ( w8>>>17 ^ w8>>>19 ^ w8>>>10 ^ w8<<15 ^ w8<<13 ) + w10 + w3 )|0; - f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0xc24b8b70 )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 43 - w11 = ( ( w12>>>7 ^ w12>>>18 ^ w12>>>3 ^ w12<<25 ^ w12<<14 ) + ( w9>>>17 ^ w9>>>19 ^ w9>>>10 ^ w9<<15 ^ w9<<13 ) + w11 + w4 )|0; - e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0xc76c51a3 )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 44 - w12 = ( ( w13>>>7 ^ w13>>>18 ^ w13>>>3 ^ w13<<25 ^ w13<<14 ) + ( w10>>>17 ^ w10>>>19 ^ w10>>>10 ^ w10<<15 ^ w10<<13 ) + w12 + w5 )|0; - d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0xd192e819 )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 45 - w13 = ( ( w14>>>7 ^ w14>>>18 ^ w14>>>3 ^ w14<<25 ^ w14<<14 ) + ( w11>>>17 ^ w11>>>19 ^ w11>>>10 ^ w11<<15 ^ w11<<13 ) + w13 + w6 )|0; - c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0xd6990624 )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 46 - w14 = ( ( w15>>>7 ^ w15>>>18 ^ w15>>>3 ^ w15<<25 ^ w15<<14 ) + ( w12>>>17 ^ w12>>>19 ^ w12>>>10 ^ w12<<15 ^ w12<<13 ) + w14 + w7 )|0; - b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0xf40e3585 )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 47 - w15 = ( ( w0>>>7 ^ w0>>>18 ^ w0>>>3 ^ w0<<25 ^ w0<<14 ) + ( w13>>>17 ^ w13>>>19 ^ w13>>>10 ^ w13<<15 ^ w13<<13 ) + w15 + w8 )|0; - a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x106aa070 )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - // 48 - w0 = ( ( w1>>>7 ^ w1>>>18 ^ w1>>>3 ^ w1<<25 ^ w1<<14 ) + ( w14>>>17 ^ w14>>>19 ^ w14>>>10 ^ w14<<15 ^ w14<<13 ) + w0 + w9 )|0; - h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x19a4c116 )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 49 - w1 = ( ( w2>>>7 ^ w2>>>18 ^ w2>>>3 ^ w2<<25 ^ w2<<14 ) + ( w15>>>17 ^ w15>>>19 ^ w15>>>10 ^ w15<<15 ^ w15<<13 ) + w1 + w10 )|0; - g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x1e376c08 )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 50 - w2 = ( ( w3>>>7 ^ w3>>>18 ^ w3>>>3 ^ w3<<25 ^ w3<<14 ) + ( w0>>>17 ^ w0>>>19 ^ w0>>>10 ^ w0<<15 ^ w0<<13 ) + w2 + w11 )|0; - f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x2748774c )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 51 - w3 = ( ( w4>>>7 ^ w4>>>18 ^ w4>>>3 ^ w4<<25 ^ w4<<14 ) + ( w1>>>17 ^ w1>>>19 ^ w1>>>10 ^ w1<<15 ^ w1<<13 ) + w3 + w12 )|0; - e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x34b0bcb5 )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 52 - w4 = ( ( w5>>>7 ^ w5>>>18 ^ w5>>>3 ^ w5<<25 ^ w5<<14 ) + ( w2>>>17 ^ w2>>>19 ^ w2>>>10 ^ w2<<15 ^ w2<<13 ) + w4 + w13 )|0; - d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x391c0cb3 )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 53 - w5 = ( ( w6>>>7 ^ w6>>>18 ^ w6>>>3 ^ w6<<25 ^ w6<<14 ) + ( w3>>>17 ^ w3>>>19 ^ w3>>>10 ^ w3<<15 ^ w3<<13 ) + w5 + w14 )|0; - c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x4ed8aa4a )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 54 - w6 = ( ( w7>>>7 ^ w7>>>18 ^ w7>>>3 ^ w7<<25 ^ w7<<14 ) + ( w4>>>17 ^ w4>>>19 ^ w4>>>10 ^ w4<<15 ^ w4<<13 ) + w6 + w15 )|0; - b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x5b9cca4f )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 55 - w7 = ( ( w8>>>7 ^ w8>>>18 ^ w8>>>3 ^ w8<<25 ^ w8<<14 ) + ( w5>>>17 ^ w5>>>19 ^ w5>>>10 ^ w5<<15 ^ w5<<13 ) + w7 + w0 )|0; - a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x682e6ff3 )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - // 56 - w8 = ( ( w9>>>7 ^ w9>>>18 ^ w9>>>3 ^ w9<<25 ^ w9<<14 ) + ( w6>>>17 ^ w6>>>19 ^ w6>>>10 ^ w6<<15 ^ w6<<13 ) + w8 + w1 )|0; - h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x748f82ee )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 57 - w9 = ( ( w10>>>7 ^ w10>>>18 ^ w10>>>3 ^ w10<<25 ^ w10<<14 ) + ( w7>>>17 ^ w7>>>19 ^ w7>>>10 ^ w7<<15 ^ w7<<13 ) + w9 + w2 )|0; - g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x78a5636f )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 58 - w10 = ( ( w11>>>7 ^ w11>>>18 ^ w11>>>3 ^ w11<<25 ^ w11<<14 ) + ( w8>>>17 ^ w8>>>19 ^ w8>>>10 ^ w8<<15 ^ w8<<13 ) + w10 + w3 )|0; - f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x84c87814 )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 59 - w11 = ( ( w12>>>7 ^ w12>>>18 ^ w12>>>3 ^ w12<<25 ^ w12<<14 ) + ( w9>>>17 ^ w9>>>19 ^ w9>>>10 ^ w9<<15 ^ w9<<13 ) + w11 + w4 )|0; - e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x8cc70208 )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 60 - w12 = ( ( w13>>>7 ^ w13>>>18 ^ w13>>>3 ^ w13<<25 ^ w13<<14 ) + ( w10>>>17 ^ w10>>>19 ^ w10>>>10 ^ w10<<15 ^ w10<<13 ) + w12 + w5 )|0; - d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x90befffa )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 61 - w13 = ( ( w14>>>7 ^ w14>>>18 ^ w14>>>3 ^ w14<<25 ^ w14<<14 ) + ( w11>>>17 ^ w11>>>19 ^ w11>>>10 ^ w11<<15 ^ w11<<13 ) + w13 + w6 )|0; - c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0xa4506ceb )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 62 - w14 = ( ( w15>>>7 ^ w15>>>18 ^ w15>>>3 ^ w15<<25 ^ w15<<14 ) + ( w12>>>17 ^ w12>>>19 ^ w12>>>10 ^ w12<<15 ^ w12<<13 ) + w14 + w7 )|0; - b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0xbef9a3f7 )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 63 - w15 = ( ( w0>>>7 ^ w0>>>18 ^ w0>>>3 ^ w0<<25 ^ w0<<14 ) + ( w13>>>17 ^ w13>>>19 ^ w13>>>10 ^ w13<<15 ^ w13<<13 ) + w15 + w8 )|0; - a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0xc67178f2 )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - H0 = ( H0 + a )|0; - H1 = ( H1 + b )|0; - H2 = ( H2 + c )|0; - H3 = ( H3 + d )|0; - H4 = ( H4 + e )|0; - H5 = ( H5 + f )|0; - H6 = ( H6 + g )|0; - H7 = ( H7 + h )|0; - } - - function _core_heap ( offset ) { - offset = offset|0; - - _core( - HEAP[offset|0]<<24 | HEAP[offset|1]<<16 | HEAP[offset|2]<<8 | HEAP[offset|3], - HEAP[offset|4]<<24 | HEAP[offset|5]<<16 | HEAP[offset|6]<<8 | HEAP[offset|7], - HEAP[offset|8]<<24 | HEAP[offset|9]<<16 | HEAP[offset|10]<<8 | HEAP[offset|11], - HEAP[offset|12]<<24 | HEAP[offset|13]<<16 | HEAP[offset|14]<<8 | HEAP[offset|15], - HEAP[offset|16]<<24 | HEAP[offset|17]<<16 | HEAP[offset|18]<<8 | HEAP[offset|19], - HEAP[offset|20]<<24 | HEAP[offset|21]<<16 | HEAP[offset|22]<<8 | HEAP[offset|23], - HEAP[offset|24]<<24 | HEAP[offset|25]<<16 | HEAP[offset|26]<<8 | HEAP[offset|27], - HEAP[offset|28]<<24 | HEAP[offset|29]<<16 | HEAP[offset|30]<<8 | HEAP[offset|31], - HEAP[offset|32]<<24 | HEAP[offset|33]<<16 | HEAP[offset|34]<<8 | HEAP[offset|35], - HEAP[offset|36]<<24 | HEAP[offset|37]<<16 | HEAP[offset|38]<<8 | HEAP[offset|39], - HEAP[offset|40]<<24 | HEAP[offset|41]<<16 | HEAP[offset|42]<<8 | HEAP[offset|43], - HEAP[offset|44]<<24 | HEAP[offset|45]<<16 | HEAP[offset|46]<<8 | HEAP[offset|47], - HEAP[offset|48]<<24 | HEAP[offset|49]<<16 | HEAP[offset|50]<<8 | HEAP[offset|51], - HEAP[offset|52]<<24 | HEAP[offset|53]<<16 | HEAP[offset|54]<<8 | HEAP[offset|55], - HEAP[offset|56]<<24 | HEAP[offset|57]<<16 | HEAP[offset|58]<<8 | HEAP[offset|59], - HEAP[offset|60]<<24 | HEAP[offset|61]<<16 | HEAP[offset|62]<<8 | HEAP[offset|63] - ); - } - - // offset — multiple of 32 - function _state_to_heap ( output ) { - output = output|0; - - HEAP[output|0] = H0>>>24; - HEAP[output|1] = H0>>>16&255; - HEAP[output|2] = H0>>>8&255; - HEAP[output|3] = H0&255; - HEAP[output|4] = H1>>>24; - HEAP[output|5] = H1>>>16&255; - HEAP[output|6] = H1>>>8&255; - HEAP[output|7] = H1&255; - HEAP[output|8] = H2>>>24; - HEAP[output|9] = H2>>>16&255; - HEAP[output|10] = H2>>>8&255; - HEAP[output|11] = H2&255; - HEAP[output|12] = H3>>>24; - HEAP[output|13] = H3>>>16&255; - HEAP[output|14] = H3>>>8&255; - HEAP[output|15] = H3&255; - HEAP[output|16] = H4>>>24; - HEAP[output|17] = H4>>>16&255; - HEAP[output|18] = H4>>>8&255; - HEAP[output|19] = H4&255; - HEAP[output|20] = H5>>>24; - HEAP[output|21] = H5>>>16&255; - HEAP[output|22] = H5>>>8&255; - HEAP[output|23] = H5&255; - HEAP[output|24] = H6>>>24; - HEAP[output|25] = H6>>>16&255; - HEAP[output|26] = H6>>>8&255; - HEAP[output|27] = H6&255; - HEAP[output|28] = H7>>>24; - HEAP[output|29] = H7>>>16&255; - HEAP[output|30] = H7>>>8&255; - HEAP[output|31] = H7&255; - } - - function reset () { - H0 = 0x6a09e667; - H1 = 0xbb67ae85; - H2 = 0x3c6ef372; - H3 = 0xa54ff53a; - H4 = 0x510e527f; - H5 = 0x9b05688c; - H6 = 0x1f83d9ab; - H7 = 0x5be0cd19; - TOTAL0 = TOTAL1 = 0; - } - - function init ( h0, h1, h2, h3, h4, h5, h6, h7, total0, total1 ) { - h0 = h0|0; - h1 = h1|0; - h2 = h2|0; - h3 = h3|0; - h4 = h4|0; - h5 = h5|0; - h6 = h6|0; - h7 = h7|0; - total0 = total0|0; - total1 = total1|0; - - H0 = h0; - H1 = h1; - H2 = h2; - H3 = h3; - H4 = h4; - H5 = h5; - H6 = h6; - H7 = h7; - TOTAL0 = total0; - TOTAL1 = total1; - } - - // offset — multiple of 64 - function process ( offset, length ) { - offset = offset|0; - length = length|0; - - var hashed = 0; - - if ( offset & 63 ) - return -1; - - while ( (length|0) >= 64 ) { - _core_heap(offset); - - offset = ( offset + 64 )|0; - length = ( length - 64 )|0; - - hashed = ( hashed + 64 )|0; - } - - TOTAL0 = ( TOTAL0 + hashed )|0; - if ( TOTAL0>>>0 < hashed>>>0 ) TOTAL1 = ( TOTAL1 + 1 )|0; - - return hashed|0; - } - - // offset — multiple of 64 - // output — multiple of 32 - function finish ( offset, length, output ) { - offset = offset|0; - length = length|0; - output = output|0; - - var hashed = 0, - i = 0; - - if ( offset & 63 ) - return -1; - - if ( ~output ) - if ( output & 31 ) - return -1; - - if ( (length|0) >= 64 ) { - hashed = process( offset, length )|0; - if ( (hashed|0) == -1 ) - return -1; - - offset = ( offset + hashed )|0; - length = ( length - hashed )|0; - } - - hashed = ( hashed + length )|0; - TOTAL0 = ( TOTAL0 + length )|0; - if ( TOTAL0>>>0 < length>>>0 ) TOTAL1 = ( TOTAL1 + 1 )|0; - - HEAP[offset|length] = 0x80; - - if ( (length|0) >= 56 ) { - for ( i = (length+1)|0; (i|0) < 64; i = (i+1)|0 ) - HEAP[offset|i] = 0x00; - - _core_heap(offset); - - length = 0; - - HEAP[offset|0] = 0; - } - - for ( i = (length+1)|0; (i|0) < 59; i = (i+1)|0 ) - HEAP[offset|i] = 0; - - HEAP[offset|56] = TOTAL1>>>21&255; - HEAP[offset|57] = TOTAL1>>>13&255; - HEAP[offset|58] = TOTAL1>>>5&255; - HEAP[offset|59] = TOTAL1<<3&255 | TOTAL0>>>29; - HEAP[offset|60] = TOTAL0>>>21&255; - HEAP[offset|61] = TOTAL0>>>13&255; - HEAP[offset|62] = TOTAL0>>>5&255; - HEAP[offset|63] = TOTAL0<<3&255; - _core_heap(offset); - - if ( ~output ) - _state_to_heap(output); - - return hashed|0; - } - - function hmac_reset () { - H0 = I0; - H1 = I1; - H2 = I2; - H3 = I3; - H4 = I4; - H5 = I5; - H6 = I6; - H7 = I7; - TOTAL0 = 64; - TOTAL1 = 0; - } - - function _hmac_opad () { - H0 = O0; - H1 = O1; - H2 = O2; - H3 = O3; - H4 = O4; - H5 = O5; - H6 = O6; - H7 = O7; - TOTAL0 = 64; - TOTAL1 = 0; - } - - function hmac_init ( p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15 ) { - p0 = p0|0; - p1 = p1|0; - p2 = p2|0; - p3 = p3|0; - p4 = p4|0; - p5 = p5|0; - p6 = p6|0; - p7 = p7|0; - p8 = p8|0; - p9 = p9|0; - p10 = p10|0; - p11 = p11|0; - p12 = p12|0; - p13 = p13|0; - p14 = p14|0; - p15 = p15|0; - - // opad - reset(); - _core( - p0 ^ 0x5c5c5c5c, - p1 ^ 0x5c5c5c5c, - p2 ^ 0x5c5c5c5c, - p3 ^ 0x5c5c5c5c, - p4 ^ 0x5c5c5c5c, - p5 ^ 0x5c5c5c5c, - p6 ^ 0x5c5c5c5c, - p7 ^ 0x5c5c5c5c, - p8 ^ 0x5c5c5c5c, - p9 ^ 0x5c5c5c5c, - p10 ^ 0x5c5c5c5c, - p11 ^ 0x5c5c5c5c, - p12 ^ 0x5c5c5c5c, - p13 ^ 0x5c5c5c5c, - p14 ^ 0x5c5c5c5c, - p15 ^ 0x5c5c5c5c - ); - O0 = H0; - O1 = H1; - O2 = H2; - O3 = H3; - O4 = H4; - O5 = H5; - O6 = H6; - O7 = H7; - - // ipad - reset(); - _core( - p0 ^ 0x36363636, - p1 ^ 0x36363636, - p2 ^ 0x36363636, - p3 ^ 0x36363636, - p4 ^ 0x36363636, - p5 ^ 0x36363636, - p6 ^ 0x36363636, - p7 ^ 0x36363636, - p8 ^ 0x36363636, - p9 ^ 0x36363636, - p10 ^ 0x36363636, - p11 ^ 0x36363636, - p12 ^ 0x36363636, - p13 ^ 0x36363636, - p14 ^ 0x36363636, - p15 ^ 0x36363636 - ); - I0 = H0; - I1 = H1; - I2 = H2; - I3 = H3; - I4 = H4; - I5 = H5; - I6 = H6; - I7 = H7; - - TOTAL0 = 64; - TOTAL1 = 0; - } - - // offset — multiple of 64 - // output — multiple of 32 - function hmac_finish ( offset, length, output ) { - offset = offset|0; - length = length|0; - output = output|0; - - var t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0, - hashed = 0; - - if ( offset & 63 ) - return -1; - - if ( ~output ) - if ( output & 31 ) - return -1; - - hashed = finish( offset, length, -1 )|0; - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; - - _hmac_opad(); - _core( t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768 ); - - if ( ~output ) - _state_to_heap(output); - - return hashed|0; - } - - // salt is assumed to be already processed - // offset — multiple of 64 - // output — multiple of 32 - function pbkdf2_generate_block ( offset, length, block, count, output ) { - offset = offset|0; - length = length|0; - block = block|0; - count = count|0; - output = output|0; - - var h0 = 0, h1 = 0, h2 = 0, h3 = 0, h4 = 0, h5 = 0, h6 = 0, h7 = 0, - t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0; - - if ( offset & 63 ) - return -1; - - if ( ~output ) - if ( output & 31 ) - return -1; - - // pad block number into heap - // FIXME probable OOB write - HEAP[(offset+length)|0] = block>>>24; - HEAP[(offset+length+1)|0] = block>>>16&255; - HEAP[(offset+length+2)|0] = block>>>8&255; - HEAP[(offset+length+3)|0] = block&255; - - // finish first iteration - hmac_finish( offset, (length+4)|0, -1 )|0; - h0 = t0 = H0, h1 = t1 = H1, h2 = t2 = H2, h3 = t3 = H3, h4 = t4 = H4, h5 = t5 = H5, h6 = t6 = H6, h7 = t7 = H7; - count = (count-1)|0; - - // perform the rest iterations - while ( (count|0) > 0 ) { - hmac_reset(); - _core( t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768 ); - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; - - _hmac_opad(); - _core( t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768 ); - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; - - h0 = h0 ^ H0; - h1 = h1 ^ H1; - h2 = h2 ^ H2; - h3 = h3 ^ H3; - h4 = h4 ^ H4; - h5 = h5 ^ H5; - h6 = h6 ^ H6; - h7 = h7 ^ H7; - - count = (count-1)|0; - } - - H0 = h0; - H1 = h1; - H2 = h2; - H3 = h3; - H4 = h4; - H5 = h5; - H6 = h6; - H7 = h7; - - if ( ~output ) - _state_to_heap(output); - - return 0; - } - - return { - // SHA256 - reset: reset, - init: init, - process: process, - finish: finish, - - // HMAC-SHA256 - hmac_reset: hmac_reset, - hmac_init: hmac_init, - hmac_finish: hmac_finish, - - // PBKDF2-HMAC-SHA256 - pbkdf2_generate_block: pbkdf2_generate_block - } - }; - - const _sha256_block_size = 64; - const _sha256_hash_size = 32; - const heap_pool$2 = []; - const asm_pool$2 = []; - class Sha256 extends Hash { - constructor() { - super(); - this.NAME = 'sha256'; - this.BLOCK_SIZE = _sha256_block_size; - this.HASH_SIZE = _sha256_hash_size; - this.acquire_asm(); - } - acquire_asm() { - if (this.heap === undefined || this.asm === undefined) { - this.heap = heap_pool$2.pop() || _heap_init(); - this.asm = asm_pool$2.pop() || sha256_asm({ Uint8Array: Uint8Array }, null, this.heap.buffer); - this.reset(); - } - return { heap: this.heap, asm: this.asm }; - } - release_asm() { - if (this.heap !== undefined && this.asm !== undefined) { - heap_pool$2.push(this.heap); - asm_pool$2.push(this.asm); - } - this.heap = undefined; - this.asm = undefined; - } - static bytes(data) { - return new Sha256().process(data).finish().result; - } - } - Sha256.NAME = 'sha256'; - - var minimalisticAssert = assert; - - function assert(val, msg) { - if (!val) - throw new Error(msg || 'Assertion failed'); - } - - assert.equal = function assertEqual(l, r, msg) { - if (l != r) - throw new Error(msg || ('Assertion failed: ' + l + ' != ' + r)); - }; - - var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; - - function createCommonjsModule(fn, module) { - return module = { exports: {} }, fn(module, module.exports), module.exports; - } - - function commonjsRequire () { - throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs'); - } - - var inherits_browser = createCommonjsModule(function (module) { - if (typeof Object.create === 'function') { - // implementation from standard node.js 'util' module - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor; - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }); - }; - } else { - // old school shim for old browsers - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor; - var TempCtor = function () {}; - TempCtor.prototype = superCtor.prototype; - ctor.prototype = new TempCtor(); - ctor.prototype.constructor = ctor; - }; - } - }); - - var inherits_1 = inherits_browser; - - function toArray(msg, enc) { - if (Array.isArray(msg)) - return msg.slice(); - if (!msg) - return []; - var res = []; - if (typeof msg === 'string') { - if (!enc) { - for (var i = 0; i < msg.length; i++) { - var c = msg.charCodeAt(i); - var hi = c >> 8; - var lo = c & 0xff; - if (hi) - res.push(hi, lo); - else - res.push(lo); - } - } else if (enc === 'hex') { - msg = msg.replace(/[^a-z0-9]+/ig, ''); - if (msg.length % 2 !== 0) - msg = '0' + msg; - for (i = 0; i < msg.length; i += 2) - res.push(parseInt(msg[i] + msg[i + 1], 16)); - } - } else { - for (i = 0; i < msg.length; i++) - res[i] = msg[i] | 0; - } - return res; - } - var toArray_1 = toArray; - - function toHex(msg) { - var res = ''; - for (var i = 0; i < msg.length; i++) - res += zero2(msg[i].toString(16)); - return res; - } - var toHex_1 = toHex; - - function htonl(w) { - var res = (w >>> 24) | - ((w >>> 8) & 0xff00) | - ((w << 8) & 0xff0000) | - ((w & 0xff) << 24); - return res >>> 0; - } - var htonl_1 = htonl; - - function toHex32(msg, endian) { - var res = ''; - for (var i = 0; i < msg.length; i++) { - var w = msg[i]; - if (endian === 'little') - w = htonl(w); - res += zero8(w.toString(16)); - } - return res; - } - var toHex32_1 = toHex32; - - function zero2(word) { - if (word.length === 1) - return '0' + word; - else - return word; - } - var zero2_1 = zero2; - - function zero8(word) { - if (word.length === 7) - return '0' + word; - else if (word.length === 6) - return '00' + word; - else if (word.length === 5) - return '000' + word; - else if (word.length === 4) - return '0000' + word; - else if (word.length === 3) - return '00000' + word; - else if (word.length === 2) - return '000000' + word; - else if (word.length === 1) - return '0000000' + word; - else - return word; - } - var zero8_1 = zero8; - - function join32(msg, start, end, endian) { - var len = end - start; - minimalisticAssert(len % 4 === 0); - var res = new Array(len / 4); - for (var i = 0, k = start; i < res.length; i++, k += 4) { - var w; - if (endian === 'big') - w = (msg[k] << 24) | (msg[k + 1] << 16) | (msg[k + 2] << 8) | msg[k + 3]; - else - w = (msg[k + 3] << 24) | (msg[k + 2] << 16) | (msg[k + 1] << 8) | msg[k]; - res[i] = w >>> 0; - } - return res; - } - var join32_1 = join32; - - function split32(msg, endian) { - var res = new Array(msg.length * 4); - for (var i = 0, k = 0; i < msg.length; i++, k += 4) { - var m = msg[i]; - if (endian === 'big') { - res[k] = m >>> 24; - res[k + 1] = (m >>> 16) & 0xff; - res[k + 2] = (m >>> 8) & 0xff; - res[k + 3] = m & 0xff; - } else { - res[k + 3] = m >>> 24; - res[k + 2] = (m >>> 16) & 0xff; - res[k + 1] = (m >>> 8) & 0xff; - res[k] = m & 0xff; - } - } - return res; - } - var split32_1 = split32; - - function rotr32(w, b) { - return (w >>> b) | (w << (32 - b)); - } - var rotr32_1 = rotr32; - - function rotl32(w, b) { - return (w << b) | (w >>> (32 - b)); - } - var rotl32_1 = rotl32; - - function sum32(a, b) { - return (a + b) >>> 0; - } - var sum32_1 = sum32; - - function sum32_3(a, b, c) { - return (a + b + c) >>> 0; - } - var sum32_3_1 = sum32_3; - - function sum32_4(a, b, c, d) { - return (a + b + c + d) >>> 0; - } - var sum32_4_1 = sum32_4; - - function sum32_5(a, b, c, d, e) { - return (a + b + c + d + e) >>> 0; - } - var sum32_5_1 = sum32_5; - - function sum64(buf, pos, ah, al) { - var bh = buf[pos]; - var bl = buf[pos + 1]; - - var lo = (al + bl) >>> 0; - var hi = (lo < al ? 1 : 0) + ah + bh; - buf[pos] = hi >>> 0; - buf[pos + 1] = lo; - } - var sum64_1 = sum64; - - function sum64_hi(ah, al, bh, bl) { - var lo = (al + bl) >>> 0; - var hi = (lo < al ? 1 : 0) + ah + bh; - return hi >>> 0; - } - var sum64_hi_1 = sum64_hi; - - function sum64_lo(ah, al, bh, bl) { - var lo = al + bl; - return lo >>> 0; - } - var sum64_lo_1 = sum64_lo; - - function sum64_4_hi(ah, al, bh, bl, ch, cl, dh, dl) { - var carry = 0; - var lo = al; - lo = (lo + bl) >>> 0; - carry += lo < al ? 1 : 0; - lo = (lo + cl) >>> 0; - carry += lo < cl ? 1 : 0; - lo = (lo + dl) >>> 0; - carry += lo < dl ? 1 : 0; - - var hi = ah + bh + ch + dh + carry; - return hi >>> 0; - } - var sum64_4_hi_1 = sum64_4_hi; - - function sum64_4_lo(ah, al, bh, bl, ch, cl, dh, dl) { - var lo = al + bl + cl + dl; - return lo >>> 0; - } - var sum64_4_lo_1 = sum64_4_lo; - - function sum64_5_hi(ah, al, bh, bl, ch, cl, dh, dl, eh, el) { - var carry = 0; - var lo = al; - lo = (lo + bl) >>> 0; - carry += lo < al ? 1 : 0; - lo = (lo + cl) >>> 0; - carry += lo < cl ? 1 : 0; - lo = (lo + dl) >>> 0; - carry += lo < dl ? 1 : 0; - lo = (lo + el) >>> 0; - carry += lo < el ? 1 : 0; - - var hi = ah + bh + ch + dh + eh + carry; - return hi >>> 0; - } - var sum64_5_hi_1 = sum64_5_hi; - - function sum64_5_lo(ah, al, bh, bl, ch, cl, dh, dl, eh, el) { - var lo = al + bl + cl + dl + el; - - return lo >>> 0; - } - var sum64_5_lo_1 = sum64_5_lo; - - function rotr64_hi(ah, al, num) { - var r = (al << (32 - num)) | (ah >>> num); - return r >>> 0; - } - var rotr64_hi_1 = rotr64_hi; - - function rotr64_lo(ah, al, num) { - var r = (ah << (32 - num)) | (al >>> num); - return r >>> 0; - } - var rotr64_lo_1 = rotr64_lo; - - function shr64_hi(ah, al, num) { - return ah >>> num; - } - var shr64_hi_1 = shr64_hi; - - function shr64_lo(ah, al, num) { - var r = (ah << (32 - num)) | (al >>> num); - return r >>> 0; - } - var shr64_lo_1 = shr64_lo; - - var utils = { - inherits: inherits_1, - toArray: toArray_1, - toHex: toHex_1, - htonl: htonl_1, - toHex32: toHex32_1, - zero2: zero2_1, - zero8: zero8_1, - join32: join32_1, - split32: split32_1, - rotr32: rotr32_1, - rotl32: rotl32_1, - sum32: sum32_1, - sum32_3: sum32_3_1, - sum32_4: sum32_4_1, - sum32_5: sum32_5_1, - sum64: sum64_1, - sum64_hi: sum64_hi_1, - sum64_lo: sum64_lo_1, - sum64_4_hi: sum64_4_hi_1, - sum64_4_lo: sum64_4_lo_1, - sum64_5_hi: sum64_5_hi_1, - sum64_5_lo: sum64_5_lo_1, - rotr64_hi: rotr64_hi_1, - rotr64_lo: rotr64_lo_1, - shr64_hi: shr64_hi_1, - shr64_lo: shr64_lo_1 - }; - - function BlockHash() { - this.pending = null; - this.pendingTotal = 0; - this.blockSize = this.constructor.blockSize; - this.outSize = this.constructor.outSize; - this.hmacStrength = this.constructor.hmacStrength; - this.padLength = this.constructor.padLength / 8; - this.endian = 'big'; - - this._delta8 = this.blockSize / 8; - this._delta32 = this.blockSize / 32; - } - var BlockHash_1 = BlockHash; - - BlockHash.prototype.update = function update(msg, enc) { - // Convert message to array, pad it, and join into 32bit blocks - msg = utils.toArray(msg, enc); - if (!this.pending) - this.pending = msg; - else - this.pending = this.pending.concat(msg); - this.pendingTotal += msg.length; - - // Enough data, try updating - if (this.pending.length >= this._delta8) { - msg = this.pending; - - // Process pending data in blocks - var r = msg.length % this._delta8; - this.pending = msg.slice(msg.length - r, msg.length); - if (this.pending.length === 0) - this.pending = null; - - msg = utils.join32(msg, 0, msg.length - r, this.endian); - for (var i = 0; i < msg.length; i += this._delta32) - this._update(msg, i, i + this._delta32); - } - - return this; - }; - - BlockHash.prototype.digest = function digest(enc) { - this.update(this._pad()); - minimalisticAssert(this.pending === null); - - return this._digest(enc); - }; - - BlockHash.prototype._pad = function pad() { - var len = this.pendingTotal; - var bytes = this._delta8; - var k = bytes - ((len + this.padLength) % bytes); - var res = new Array(k + this.padLength); - res[0] = 0x80; - for (var i = 1; i < k; i++) - res[i] = 0; - - // Append length - len <<= 3; - if (this.endian === 'big') { - for (var t = 8; t < this.padLength; t++) - res[i++] = 0; - - res[i++] = 0; - res[i++] = 0; - res[i++] = 0; - res[i++] = 0; - res[i++] = (len >>> 24) & 0xff; - res[i++] = (len >>> 16) & 0xff; - res[i++] = (len >>> 8) & 0xff; - res[i++] = len & 0xff; - } else { - res[i++] = len & 0xff; - res[i++] = (len >>> 8) & 0xff; - res[i++] = (len >>> 16) & 0xff; - res[i++] = (len >>> 24) & 0xff; - res[i++] = 0; - res[i++] = 0; - res[i++] = 0; - res[i++] = 0; - - for (t = 8; t < this.padLength; t++) - res[i++] = 0; - } - - return res; - }; - - var common = { - BlockHash: BlockHash_1 - }; - - var rotr32$1 = utils.rotr32; - - function ft_1(s, x, y, z) { - if (s === 0) - return ch32(x, y, z); - if (s === 1 || s === 3) - return p32(x, y, z); - if (s === 2) - return maj32(x, y, z); - } - var ft_1_1 = ft_1; - - function ch32(x, y, z) { - return (x & y) ^ ((~x) & z); - } - var ch32_1 = ch32; - - function maj32(x, y, z) { - return (x & y) ^ (x & z) ^ (y & z); - } - var maj32_1 = maj32; - - function p32(x, y, z) { - return x ^ y ^ z; - } - var p32_1 = p32; - - function s0_256(x) { - return rotr32$1(x, 2) ^ rotr32$1(x, 13) ^ rotr32$1(x, 22); - } - var s0_256_1 = s0_256; - - function s1_256(x) { - return rotr32$1(x, 6) ^ rotr32$1(x, 11) ^ rotr32$1(x, 25); - } - var s1_256_1 = s1_256; - - function g0_256(x) { - return rotr32$1(x, 7) ^ rotr32$1(x, 18) ^ (x >>> 3); - } - var g0_256_1 = g0_256; - - function g1_256(x) { - return rotr32$1(x, 17) ^ rotr32$1(x, 19) ^ (x >>> 10); - } - var g1_256_1 = g1_256; - - var common$1 = { - ft_1: ft_1_1, - ch32: ch32_1, - maj32: maj32_1, - p32: p32_1, - s0_256: s0_256_1, - s1_256: s1_256_1, - g0_256: g0_256_1, - g1_256: g1_256_1 - }; - - var sum32$1 = utils.sum32; - var sum32_4$1 = utils.sum32_4; - var sum32_5$1 = utils.sum32_5; - var ch32$1 = common$1.ch32; - var maj32$1 = common$1.maj32; - var s0_256$1 = common$1.s0_256; - var s1_256$1 = common$1.s1_256; - var g0_256$1 = common$1.g0_256; - var g1_256$1 = common$1.g1_256; - - var BlockHash$1 = common.BlockHash; - - var sha256_K = [ - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 - ]; - - function SHA256() { - if (!(this instanceof SHA256)) - return new SHA256(); - - BlockHash$1.call(this); - this.h = [ - 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, - 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 - ]; - this.k = sha256_K; - this.W = new Array(64); - } - utils.inherits(SHA256, BlockHash$1); - var _256 = SHA256; - - SHA256.blockSize = 512; - SHA256.outSize = 256; - SHA256.hmacStrength = 192; - SHA256.padLength = 64; - - SHA256.prototype._update = function _update(msg, start) { - var W = this.W; - - for (var i = 0; i < 16; i++) - W[i] = msg[start + i]; - for (; i < W.length; i++) - W[i] = sum32_4$1(g1_256$1(W[i - 2]), W[i - 7], g0_256$1(W[i - 15]), W[i - 16]); - - var a = this.h[0]; - var b = this.h[1]; - var c = this.h[2]; - var d = this.h[3]; - var e = this.h[4]; - var f = this.h[5]; - var g = this.h[6]; - var h = this.h[7]; - - minimalisticAssert(this.k.length === W.length); - for (i = 0; i < W.length; i++) { - var T1 = sum32_5$1(h, s1_256$1(e), ch32$1(e, f, g), this.k[i], W[i]); - var T2 = sum32$1(s0_256$1(a), maj32$1(a, b, c)); - h = g; - g = f; - f = e; - e = sum32$1(d, T1); - d = c; - c = b; - b = a; - a = sum32$1(T1, T2); - } - - this.h[0] = sum32$1(this.h[0], a); - this.h[1] = sum32$1(this.h[1], b); - this.h[2] = sum32$1(this.h[2], c); - this.h[3] = sum32$1(this.h[3], d); - this.h[4] = sum32$1(this.h[4], e); - this.h[5] = sum32$1(this.h[5], f); - this.h[6] = sum32$1(this.h[6], g); - this.h[7] = sum32$1(this.h[7], h); - }; - - SHA256.prototype._digest = function digest(enc) { - if (enc === 'hex') - return utils.toHex32(this.h, 'big'); - else - return utils.split32(this.h, 'big'); - }; - - function SHA224() { - if (!(this instanceof SHA224)) - return new SHA224(); - - _256.call(this); - this.h = [ - 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, - 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 ]; - } - utils.inherits(SHA224, _256); - var _224 = SHA224; - - SHA224.blockSize = 512; - SHA224.outSize = 224; - SHA224.hmacStrength = 192; - SHA224.padLength = 64; - - SHA224.prototype._digest = function digest(enc) { - // Just truncate output - if (enc === 'hex') - return utils.toHex32(this.h.slice(0, 7), 'big'); - else - return utils.split32(this.h.slice(0, 7), 'big'); - }; - - var rotr64_hi$1 = utils.rotr64_hi; - var rotr64_lo$1 = utils.rotr64_lo; - var shr64_hi$1 = utils.shr64_hi; - var shr64_lo$1 = utils.shr64_lo; - var sum64$1 = utils.sum64; - var sum64_hi$1 = utils.sum64_hi; - var sum64_lo$1 = utils.sum64_lo; - var sum64_4_hi$1 = utils.sum64_4_hi; - var sum64_4_lo$1 = utils.sum64_4_lo; - var sum64_5_hi$1 = utils.sum64_5_hi; - var sum64_5_lo$1 = utils.sum64_5_lo; - - var BlockHash$2 = common.BlockHash; - - var sha512_K = [ - 0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd, - 0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc, - 0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019, - 0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118, - 0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe, - 0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2, - 0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1, - 0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694, - 0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3, - 0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65, - 0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483, - 0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5, - 0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210, - 0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4, - 0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725, - 0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70, - 0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926, - 0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df, - 0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8, - 0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b, - 0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001, - 0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30, - 0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910, - 0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8, - 0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53, - 0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8, - 0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb, - 0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3, - 0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60, - 0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec, - 0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9, - 0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b, - 0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207, - 0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178, - 0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6, - 0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b, - 0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493, - 0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c, - 0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a, - 0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817 - ]; - - function SHA512() { - if (!(this instanceof SHA512)) - return new SHA512(); - - BlockHash$2.call(this); - this.h = [ - 0x6a09e667, 0xf3bcc908, - 0xbb67ae85, 0x84caa73b, - 0x3c6ef372, 0xfe94f82b, - 0xa54ff53a, 0x5f1d36f1, - 0x510e527f, 0xade682d1, - 0x9b05688c, 0x2b3e6c1f, - 0x1f83d9ab, 0xfb41bd6b, - 0x5be0cd19, 0x137e2179 ]; - this.k = sha512_K; - this.W = new Array(160); - } - utils.inherits(SHA512, BlockHash$2); - var _512 = SHA512; - - SHA512.blockSize = 1024; - SHA512.outSize = 512; - SHA512.hmacStrength = 192; - SHA512.padLength = 128; - - SHA512.prototype._prepareBlock = function _prepareBlock(msg, start) { - var W = this.W; - - // 32 x 32bit words - for (var i = 0; i < 32; i++) - W[i] = msg[start + i]; - for (; i < W.length; i += 2) { - var c0_hi = g1_512_hi(W[i - 4], W[i - 3]); // i - 2 - var c0_lo = g1_512_lo(W[i - 4], W[i - 3]); - var c1_hi = W[i - 14]; // i - 7 - var c1_lo = W[i - 13]; - var c2_hi = g0_512_hi(W[i - 30], W[i - 29]); // i - 15 - var c2_lo = g0_512_lo(W[i - 30], W[i - 29]); - var c3_hi = W[i - 32]; // i - 16 - var c3_lo = W[i - 31]; - - W[i] = sum64_4_hi$1( - c0_hi, c0_lo, - c1_hi, c1_lo, - c2_hi, c2_lo, - c3_hi, c3_lo); - W[i + 1] = sum64_4_lo$1( - c0_hi, c0_lo, - c1_hi, c1_lo, - c2_hi, c2_lo, - c3_hi, c3_lo); - } - }; - - SHA512.prototype._update = function _update(msg, start) { - this._prepareBlock(msg, start); - - var W = this.W; - - var ah = this.h[0]; - var al = this.h[1]; - var bh = this.h[2]; - var bl = this.h[3]; - var ch = this.h[4]; - var cl = this.h[5]; - var dh = this.h[6]; - var dl = this.h[7]; - var eh = this.h[8]; - var el = this.h[9]; - var fh = this.h[10]; - var fl = this.h[11]; - var gh = this.h[12]; - var gl = this.h[13]; - var hh = this.h[14]; - var hl = this.h[15]; - - minimalisticAssert(this.k.length === W.length); - for (var i = 0; i < W.length; i += 2) { - var c0_hi = hh; - var c0_lo = hl; - var c1_hi = s1_512_hi(eh, el); - var c1_lo = s1_512_lo(eh, el); - var c2_hi = ch64_hi(eh, el, fh, fl, gh); - var c2_lo = ch64_lo(eh, el, fh, fl, gh, gl); - var c3_hi = this.k[i]; - var c3_lo = this.k[i + 1]; - var c4_hi = W[i]; - var c4_lo = W[i + 1]; - - var T1_hi = sum64_5_hi$1( - c0_hi, c0_lo, - c1_hi, c1_lo, - c2_hi, c2_lo, - c3_hi, c3_lo, - c4_hi, c4_lo); - var T1_lo = sum64_5_lo$1( - c0_hi, c0_lo, - c1_hi, c1_lo, - c2_hi, c2_lo, - c3_hi, c3_lo, - c4_hi, c4_lo); - - c0_hi = s0_512_hi(ah, al); - c0_lo = s0_512_lo(ah, al); - c1_hi = maj64_hi(ah, al, bh, bl, ch); - c1_lo = maj64_lo(ah, al, bh, bl, ch, cl); - - var T2_hi = sum64_hi$1(c0_hi, c0_lo, c1_hi, c1_lo); - var T2_lo = sum64_lo$1(c0_hi, c0_lo, c1_hi, c1_lo); - - hh = gh; - hl = gl; - - gh = fh; - gl = fl; - - fh = eh; - fl = el; - - eh = sum64_hi$1(dh, dl, T1_hi, T1_lo); - el = sum64_lo$1(dl, dl, T1_hi, T1_lo); - - dh = ch; - dl = cl; - - ch = bh; - cl = bl; - - bh = ah; - bl = al; - - ah = sum64_hi$1(T1_hi, T1_lo, T2_hi, T2_lo); - al = sum64_lo$1(T1_hi, T1_lo, T2_hi, T2_lo); - } - - sum64$1(this.h, 0, ah, al); - sum64$1(this.h, 2, bh, bl); - sum64$1(this.h, 4, ch, cl); - sum64$1(this.h, 6, dh, dl); - sum64$1(this.h, 8, eh, el); - sum64$1(this.h, 10, fh, fl); - sum64$1(this.h, 12, gh, gl); - sum64$1(this.h, 14, hh, hl); - }; - - SHA512.prototype._digest = function digest(enc) { - if (enc === 'hex') - return utils.toHex32(this.h, 'big'); - else - return utils.split32(this.h, 'big'); - }; - - function ch64_hi(xh, xl, yh, yl, zh) { - var r = (xh & yh) ^ ((~xh) & zh); - if (r < 0) - r += 0x100000000; - return r; - } - - function ch64_lo(xh, xl, yh, yl, zh, zl) { - var r = (xl & yl) ^ ((~xl) & zl); - if (r < 0) - r += 0x100000000; - return r; - } - - function maj64_hi(xh, xl, yh, yl, zh) { - var r = (xh & yh) ^ (xh & zh) ^ (yh & zh); - if (r < 0) - r += 0x100000000; - return r; - } - - function maj64_lo(xh, xl, yh, yl, zh, zl) { - var r = (xl & yl) ^ (xl & zl) ^ (yl & zl); - if (r < 0) - r += 0x100000000; - return r; - } - - function s0_512_hi(xh, xl) { - var c0_hi = rotr64_hi$1(xh, xl, 28); - var c1_hi = rotr64_hi$1(xl, xh, 2); // 34 - var c2_hi = rotr64_hi$1(xl, xh, 7); // 39 - - var r = c0_hi ^ c1_hi ^ c2_hi; - if (r < 0) - r += 0x100000000; - return r; - } - - function s0_512_lo(xh, xl) { - var c0_lo = rotr64_lo$1(xh, xl, 28); - var c1_lo = rotr64_lo$1(xl, xh, 2); // 34 - var c2_lo = rotr64_lo$1(xl, xh, 7); // 39 - - var r = c0_lo ^ c1_lo ^ c2_lo; - if (r < 0) - r += 0x100000000; - return r; - } - - function s1_512_hi(xh, xl) { - var c0_hi = rotr64_hi$1(xh, xl, 14); - var c1_hi = rotr64_hi$1(xh, xl, 18); - var c2_hi = rotr64_hi$1(xl, xh, 9); // 41 - - var r = c0_hi ^ c1_hi ^ c2_hi; - if (r < 0) - r += 0x100000000; - return r; - } - - function s1_512_lo(xh, xl) { - var c0_lo = rotr64_lo$1(xh, xl, 14); - var c1_lo = rotr64_lo$1(xh, xl, 18); - var c2_lo = rotr64_lo$1(xl, xh, 9); // 41 - - var r = c0_lo ^ c1_lo ^ c2_lo; - if (r < 0) - r += 0x100000000; - return r; - } - - function g0_512_hi(xh, xl) { - var c0_hi = rotr64_hi$1(xh, xl, 1); - var c1_hi = rotr64_hi$1(xh, xl, 8); - var c2_hi = shr64_hi$1(xh, xl, 7); - - var r = c0_hi ^ c1_hi ^ c2_hi; - if (r < 0) - r += 0x100000000; - return r; - } - - function g0_512_lo(xh, xl) { - var c0_lo = rotr64_lo$1(xh, xl, 1); - var c1_lo = rotr64_lo$1(xh, xl, 8); - var c2_lo = shr64_lo$1(xh, xl, 7); - - var r = c0_lo ^ c1_lo ^ c2_lo; - if (r < 0) - r += 0x100000000; - return r; - } - - function g1_512_hi(xh, xl) { - var c0_hi = rotr64_hi$1(xh, xl, 19); - var c1_hi = rotr64_hi$1(xl, xh, 29); // 61 - var c2_hi = shr64_hi$1(xh, xl, 6); - - var r = c0_hi ^ c1_hi ^ c2_hi; - if (r < 0) - r += 0x100000000; - return r; - } - - function g1_512_lo(xh, xl) { - var c0_lo = rotr64_lo$1(xh, xl, 19); - var c1_lo = rotr64_lo$1(xl, xh, 29); // 61 - var c2_lo = shr64_lo$1(xh, xl, 6); - - var r = c0_lo ^ c1_lo ^ c2_lo; - if (r < 0) - r += 0x100000000; - return r; - } - - function SHA384() { - if (!(this instanceof SHA384)) - return new SHA384(); - - _512.call(this); - this.h = [ - 0xcbbb9d5d, 0xc1059ed8, - 0x629a292a, 0x367cd507, - 0x9159015a, 0x3070dd17, - 0x152fecd8, 0xf70e5939, - 0x67332667, 0xffc00b31, - 0x8eb44a87, 0x68581511, - 0xdb0c2e0d, 0x64f98fa7, - 0x47b5481d, 0xbefa4fa4 ]; - } - utils.inherits(SHA384, _512); - var _384 = SHA384; - - SHA384.blockSize = 1024; - SHA384.outSize = 384; - SHA384.hmacStrength = 192; - SHA384.padLength = 128; - - SHA384.prototype._digest = function digest(enc) { - if (enc === 'hex') - return utils.toHex32(this.h.slice(0, 12), 'big'); - else - return utils.split32(this.h.slice(0, 12), 'big'); - }; - - var rotl32$1 = utils.rotl32; - var sum32$2 = utils.sum32; - var sum32_3$1 = utils.sum32_3; - var sum32_4$2 = utils.sum32_4; - var BlockHash$3 = common.BlockHash; - - function RIPEMD160() { - if (!(this instanceof RIPEMD160)) - return new RIPEMD160(); - - BlockHash$3.call(this); - - this.h = [ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 ]; - this.endian = 'little'; - } - utils.inherits(RIPEMD160, BlockHash$3); - var ripemd160 = RIPEMD160; - - RIPEMD160.blockSize = 512; - RIPEMD160.outSize = 160; - RIPEMD160.hmacStrength = 192; - RIPEMD160.padLength = 64; - - RIPEMD160.prototype._update = function update(msg, start) { - var A = this.h[0]; - var B = this.h[1]; - var C = this.h[2]; - var D = this.h[3]; - var E = this.h[4]; - var Ah = A; - var Bh = B; - var Ch = C; - var Dh = D; - var Eh = E; - for (var j = 0; j < 80; j++) { - var T = sum32$2( - rotl32$1( - sum32_4$2(A, f(j, B, C, D), msg[r[j] + start], K(j)), - s[j]), - E); - A = E; - E = D; - D = rotl32$1(C, 10); - C = B; - B = T; - T = sum32$2( - rotl32$1( - sum32_4$2(Ah, f(79 - j, Bh, Ch, Dh), msg[rh[j] + start], Kh(j)), - sh[j]), - Eh); - Ah = Eh; - Eh = Dh; - Dh = rotl32$1(Ch, 10); - Ch = Bh; - Bh = T; - } - T = sum32_3$1(this.h[1], C, Dh); - this.h[1] = sum32_3$1(this.h[2], D, Eh); - this.h[2] = sum32_3$1(this.h[3], E, Ah); - this.h[3] = sum32_3$1(this.h[4], A, Bh); - this.h[4] = sum32_3$1(this.h[0], B, Ch); - this.h[0] = T; - }; - - RIPEMD160.prototype._digest = function digest(enc) { - if (enc === 'hex') - return utils.toHex32(this.h, 'little'); - else - return utils.split32(this.h, 'little'); - }; - - function f(j, x, y, z) { - if (j <= 15) - return x ^ y ^ z; - else if (j <= 31) - return (x & y) | ((~x) & z); - else if (j <= 47) - return (x | (~y)) ^ z; - else if (j <= 63) - return (x & z) | (y & (~z)); - else - return x ^ (y | (~z)); - } - - function K(j) { - if (j <= 15) - return 0x00000000; - else if (j <= 31) - return 0x5a827999; - else if (j <= 47) - return 0x6ed9eba1; - else if (j <= 63) - return 0x8f1bbcdc; - else - return 0xa953fd4e; - } - - function Kh(j) { - if (j <= 15) - return 0x50a28be6; - else if (j <= 31) - return 0x5c4dd124; - else if (j <= 47) - return 0x6d703ef3; - else if (j <= 63) - return 0x7a6d76e9; - else - return 0x00000000; - } - - var r = [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, - 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, - 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, - 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 - ]; - - var rh = [ - 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, - 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, - 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, - 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, - 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 - ]; - - var s = [ - 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, - 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, - 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, - 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, - 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 - ]; - - var sh = [ - 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, - 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, - 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, - 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, - 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 - ]; - - var ripemd = { - ripemd160: ripemd160 - }; - - /** - * A fast MD5 JavaScript implementation - * Copyright (c) 2012 Joseph Myers - * http://www.myersdaily.org/joseph/javascript/md5-text.html - * - * Permission to use, copy, modify, and distribute this software - * and its documentation for any purposes and without - * fee is hereby granted provided that this copyright notice - * appears in all copies. - * - * Of course, this soft is provided "as is" without express or implied - * warranty of any kind. - */ - - // MD5 Digest - async function md5(entree) { - const digest = md51(util.uint8ArrayToString(entree)); - return util.hexToUint8Array(hex(digest)); - } - - function md5cycle(x, k) { - let a = x[0]; - let b = x[1]; - let c = x[2]; - let d = x[3]; - - a = ff(a, b, c, d, k[0], 7, -680876936); - d = ff(d, a, b, c, k[1], 12, -389564586); - c = ff(c, d, a, b, k[2], 17, 606105819); - b = ff(b, c, d, a, k[3], 22, -1044525330); - a = ff(a, b, c, d, k[4], 7, -176418897); - d = ff(d, a, b, c, k[5], 12, 1200080426); - c = ff(c, d, a, b, k[6], 17, -1473231341); - b = ff(b, c, d, a, k[7], 22, -45705983); - a = ff(a, b, c, d, k[8], 7, 1770035416); - d = ff(d, a, b, c, k[9], 12, -1958414417); - c = ff(c, d, a, b, k[10], 17, -42063); - b = ff(b, c, d, a, k[11], 22, -1990404162); - a = ff(a, b, c, d, k[12], 7, 1804603682); - d = ff(d, a, b, c, k[13], 12, -40341101); - c = ff(c, d, a, b, k[14], 17, -1502002290); - b = ff(b, c, d, a, k[15], 22, 1236535329); - - a = gg(a, b, c, d, k[1], 5, -165796510); - d = gg(d, a, b, c, k[6], 9, -1069501632); - c = gg(c, d, a, b, k[11], 14, 643717713); - b = gg(b, c, d, a, k[0], 20, -373897302); - a = gg(a, b, c, d, k[5], 5, -701558691); - d = gg(d, a, b, c, k[10], 9, 38016083); - c = gg(c, d, a, b, k[15], 14, -660478335); - b = gg(b, c, d, a, k[4], 20, -405537848); - a = gg(a, b, c, d, k[9], 5, 568446438); - d = gg(d, a, b, c, k[14], 9, -1019803690); - c = gg(c, d, a, b, k[3], 14, -187363961); - b = gg(b, c, d, a, k[8], 20, 1163531501); - a = gg(a, b, c, d, k[13], 5, -1444681467); - d = gg(d, a, b, c, k[2], 9, -51403784); - c = gg(c, d, a, b, k[7], 14, 1735328473); - b = gg(b, c, d, a, k[12], 20, -1926607734); - - a = hh(a, b, c, d, k[5], 4, -378558); - d = hh(d, a, b, c, k[8], 11, -2022574463); - c = hh(c, d, a, b, k[11], 16, 1839030562); - b = hh(b, c, d, a, k[14], 23, -35309556); - a = hh(a, b, c, d, k[1], 4, -1530992060); - d = hh(d, a, b, c, k[4], 11, 1272893353); - c = hh(c, d, a, b, k[7], 16, -155497632); - b = hh(b, c, d, a, k[10], 23, -1094730640); - a = hh(a, b, c, d, k[13], 4, 681279174); - d = hh(d, a, b, c, k[0], 11, -358537222); - c = hh(c, d, a, b, k[3], 16, -722521979); - b = hh(b, c, d, a, k[6], 23, 76029189); - a = hh(a, b, c, d, k[9], 4, -640364487); - d = hh(d, a, b, c, k[12], 11, -421815835); - c = hh(c, d, a, b, k[15], 16, 530742520); - b = hh(b, c, d, a, k[2], 23, -995338651); - - a = ii(a, b, c, d, k[0], 6, -198630844); - d = ii(d, a, b, c, k[7], 10, 1126891415); - c = ii(c, d, a, b, k[14], 15, -1416354905); - b = ii(b, c, d, a, k[5], 21, -57434055); - a = ii(a, b, c, d, k[12], 6, 1700485571); - d = ii(d, a, b, c, k[3], 10, -1894986606); - c = ii(c, d, a, b, k[10], 15, -1051523); - b = ii(b, c, d, a, k[1], 21, -2054922799); - a = ii(a, b, c, d, k[8], 6, 1873313359); - d = ii(d, a, b, c, k[15], 10, -30611744); - c = ii(c, d, a, b, k[6], 15, -1560198380); - b = ii(b, c, d, a, k[13], 21, 1309151649); - a = ii(a, b, c, d, k[4], 6, -145523070); - d = ii(d, a, b, c, k[11], 10, -1120210379); - c = ii(c, d, a, b, k[2], 15, 718787259); - b = ii(b, c, d, a, k[9], 21, -343485551); - - x[0] = add32(a, x[0]); - x[1] = add32(b, x[1]); - x[2] = add32(c, x[2]); - x[3] = add32(d, x[3]); - } - - function cmn(q, a, b, x, s, t) { - a = add32(add32(a, q), add32(x, t)); - return add32((a << s) | (a >>> (32 - s)), b); - } - - function ff(a, b, c, d, x, s, t) { - return cmn((b & c) | ((~b) & d), a, b, x, s, t); - } - - function gg(a, b, c, d, x, s, t) { - return cmn((b & d) | (c & (~d)), a, b, x, s, t); - } - - function hh(a, b, c, d, x, s, t) { - return cmn(b ^ c ^ d, a, b, x, s, t); - } - - function ii(a, b, c, d, x, s, t) { - return cmn(c ^ (b | (~d)), a, b, x, s, t); - } - - function md51(s) { - const n = s.length; - const state = [1732584193, -271733879, -1732584194, 271733878]; - let i; - for (i = 64; i <= s.length; i += 64) { - md5cycle(state, md5blk(s.substring(i - 64, i))); - } - s = s.substring(i - 64); - const tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; - for (i = 0; i < s.length; i++) { - tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3); - } - tail[i >> 2] |= 0x80 << ((i % 4) << 3); - if (i > 55) { - md5cycle(state, tail); - for (i = 0; i < 16; i++) { - tail[i] = 0; - } - } - tail[14] = n * 8; - md5cycle(state, tail); - return state; - } - - /* there needs to be support for Unicode here, - * unless we pretend that we can redefine the MD-5 - * algorithm for multi-byte characters (perhaps - * by adding every four 16-bit characters and - * shortening the sum to 32 bits). Otherwise - * I suggest performing MD-5 as if every character - * was two bytes--e.g., 0040 0025 = @%--but then - * how will an ordinary MD-5 sum be matched? - * There is no way to standardize text to something - * like UTF-8 before transformation; speed cost is - * utterly prohibitive. The JavaScript standard - * itself needs to look at this: it should start - * providing access to strings as preformed UTF-8 - * 8-bit unsigned value arrays. - */ - function md5blk(s) { /* I figured global was faster. */ - const md5blks = []; - let i; /* Andy King said do it this way. */ - for (i = 0; i < 64; i += 4) { - md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << - 24); - } - return md5blks; - } - - const hex_chr = '0123456789abcdef'.split(''); - - function rhex(n) { - let s = ''; - let j = 0; - for (; j < 4; j++) { - s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F]; - } - return s; - } - - function hex(x) { - for (let i = 0; i < x.length; i++) { - x[i] = rhex(x[i]); - } - return x.join(''); - } - - /* this function is much faster, - so if possible we use it. Some IEs - are the only ones I know of that - need the idiotic second function, - generated by an if clause. */ - - function add32(a, b) { - return (a + b) & 0xFFFFFFFF; - } - - /** - * @fileoverview Provides an interface to hashing functions available in Node.js or external libraries. - * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} - * @see {@link https://github.com/indutny/hash.js|hash.js} - * @module crypto/hash - * @private - */ - - const webCrypto = util.getWebCrypto(); - const nodeCrypto = util.getNodeCrypto(); - - function nodeHash(type) { - return async function (data) { - const shasum = nodeCrypto.createHash(type); - return transform(data, value => { - shasum.update(value); - }, () => new Uint8Array(shasum.digest())); - }; - } - - function hashjsHash(hash, webCryptoHash) { - return async function(data, config = defaultConfig) { - if (isArrayStream(data)) { - data = await readToEnd(data); - } - if (!util.isStream(data) && webCrypto && webCryptoHash && data.length >= config.minBytesForWebCrypto) { - return new Uint8Array(await webCrypto.digest(webCryptoHash, data)); - } - const hashInstance = hash(); - return transform(data, value => { - hashInstance.update(value); - }, () => new Uint8Array(hashInstance.digest())); - }; - } - - function asmcryptoHash(hash, webCryptoHash) { - return async function(data, config = defaultConfig) { - if (isArrayStream(data)) { - data = await readToEnd(data); - } - if (util.isStream(data)) { - const hashInstance = new hash(); - return transform(data, value => { - hashInstance.process(value); - }, () => hashInstance.finish().result); - } else if (webCrypto && webCryptoHash && data.length >= config.minBytesForWebCrypto) { - return new Uint8Array(await webCrypto.digest(webCryptoHash, data)); - } else { - return hash.bytes(data); - } - }; - } - - let hashFunctions; - if (nodeCrypto) { // Use Node native crypto for all hash functions - hashFunctions = { - md5: nodeHash('md5'), - sha1: nodeHash('sha1'), - sha224: nodeHash('sha224'), - sha256: nodeHash('sha256'), - sha384: nodeHash('sha384'), - sha512: nodeHash('sha512'), - ripemd: nodeHash('ripemd160') - }; - } else { // Use JS fallbacks - hashFunctions = { - md5: md5, - sha1: asmcryptoHash(Sha1, (!navigator.userAgent || navigator.userAgent.indexOf('Edge') === -1) && 'SHA-1'), - sha224: hashjsHash(_224), - sha256: asmcryptoHash(Sha256, 'SHA-256'), - sha384: hashjsHash(_384, 'SHA-384'), - sha512: hashjsHash(_512, 'SHA-512'), // asmcrypto sha512 is huge. - ripemd: hashjsHash(ripemd160) - }; - } - - var hash = { - - /** @see module:md5 */ - md5: hashFunctions.md5, - /** @see asmCrypto */ - sha1: hashFunctions.sha1, - /** @see hash.js */ - sha224: hashFunctions.sha224, - /** @see asmCrypto */ - sha256: hashFunctions.sha256, - /** @see hash.js */ - sha384: hashFunctions.sha384, - /** @see asmCrypto */ - sha512: hashFunctions.sha512, - /** @see hash.js */ - ripemd: hashFunctions.ripemd, - - /** - * Create a hash on the specified data using the specified algorithm - * @param {module:enums.hash} algo - Hash algorithm type (see {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}) - * @param {Uint8Array} data - Data to be hashed - * @returns {Promise} Hash value. - */ - digest: function(algo, data) { - switch (algo) { - case enums.hash.md5: - return this.md5(data); - case enums.hash.sha1: - return this.sha1(data); - case enums.hash.ripemd: - return this.ripemd(data); - case enums.hash.sha256: - return this.sha256(data); - case enums.hash.sha384: - return this.sha384(data); - case enums.hash.sha512: - return this.sha512(data); - case enums.hash.sha224: - return this.sha224(data); - default: - throw new Error('Invalid hash function.'); - } - }, - - /** - * Returns the hash size in bytes of the specified hash algorithm type - * @param {module:enums.hash} algo - Hash algorithm type (See {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}) - * @returns {Integer} Size in bytes of the resulting hash. - */ - getHashByteLength: function(algo) { - switch (algo) { - case enums.hash.md5: - return 16; - case enums.hash.sha1: - case enums.hash.ripemd: - return 20; - case enums.hash.sha256: - return 32; - case enums.hash.sha384: - return 48; - case enums.hash.sha512: - return 64; - case enums.hash.sha224: - return 28; - default: - throw new Error('Invalid hash algorithm.'); - } - } - }; - - class AES_CFB { - static encrypt(data, key, iv) { - return new AES_CFB(key, iv).encrypt(data); - } - static decrypt(data, key, iv) { - return new AES_CFB(key, iv).decrypt(data); - } - constructor(key, iv, aes) { - this.aes = aes ? aes : new AES(key, iv, true, 'CFB'); - delete this.aes.padding; - } - encrypt(data) { - const r1 = this.aes.AES_Encrypt_process(data); - const r2 = this.aes.AES_Encrypt_finish(); - return joinBytes(r1, r2); - } - decrypt(data) { - const r1 = this.aes.AES_Decrypt_process(data); - const r2 = this.aes.AES_Decrypt_finish(); - return joinBytes(r1, r2); - } - } - - // Modified by ProtonTech AG - - const webCrypto$1 = util.getWebCrypto(); - const nodeCrypto$1 = util.getNodeCrypto(); - - const knownAlgos = nodeCrypto$1 ? nodeCrypto$1.getCiphers() : []; - const nodeAlgos = { - idea: knownAlgos.includes('idea-cfb') ? 'idea-cfb' : undefined, /* Unused, not implemented */ - tripledes: knownAlgos.includes('des-ede3-cfb') ? 'des-ede3-cfb' : undefined, - cast5: knownAlgos.includes('cast5-cfb') ? 'cast5-cfb' : undefined, - blowfish: knownAlgos.includes('bf-cfb') ? 'bf-cfb' : undefined, - aes128: knownAlgos.includes('aes-128-cfb') ? 'aes-128-cfb' : undefined, - aes192: knownAlgos.includes('aes-192-cfb') ? 'aes-192-cfb' : undefined, - aes256: knownAlgos.includes('aes-256-cfb') ? 'aes-256-cfb' : undefined - /* twofish is not implemented in OpenSSL */ - }; - - /** - * CFB encryption - * @param {enums.symmetric} algo - block cipher algorithm - * @param {Uint8Array} key - * @param {MaybeStream} plaintext - * @param {Uint8Array} iv - * @param {Object} config - full configuration, defaults to openpgp.config - * @returns MaybeStream - */ - async function encrypt(algo, key, plaintext, iv, config) { - const algoName = enums.read(enums.symmetric, algo); - if (util.getNodeCrypto() && nodeAlgos[algoName]) { // Node crypto library. - return nodeEncrypt(algo, key, plaintext, iv); - } - if (algoName.substr(0, 3) === 'aes') { - return aesEncrypt(algo, key, plaintext, iv, config); - } - - const cipherfn = new cipher[algoName](key); - const block_size = cipherfn.blockSize; - - const blockc = iv.slice(); - let pt = new Uint8Array(); - const process = chunk => { - if (chunk) { - pt = util.concatUint8Array([pt, chunk]); - } - const ciphertext = new Uint8Array(pt.length); - let i; - let j = 0; - while (chunk ? pt.length >= block_size : pt.length) { - const encblock = cipherfn.encrypt(blockc); - for (i = 0; i < block_size; i++) { - blockc[i] = pt[i] ^ encblock[i]; - ciphertext[j++] = blockc[i]; - } - pt = pt.subarray(block_size); - } - return ciphertext.subarray(0, j); - }; - return transform(plaintext, process, process); - } - - /** - * CFB decryption - * @param {enums.symmetric} algo - block cipher algorithm - * @param {Uint8Array} key - * @param {MaybeStream} ciphertext - * @param {Uint8Array} iv - * @returns MaybeStream - */ - async function decrypt(algo, key, ciphertext, iv) { - const algoName = enums.read(enums.symmetric, algo); - if (util.getNodeCrypto() && nodeAlgos[algoName]) { // Node crypto library. - return nodeDecrypt(algo, key, ciphertext, iv); - } - if (algoName.substr(0, 3) === 'aes') { - return aesDecrypt(algo, key, ciphertext, iv); - } - - const cipherfn = new cipher[algoName](key); - const block_size = cipherfn.blockSize; - - let blockp = iv; - let ct = new Uint8Array(); - const process = chunk => { - if (chunk) { - ct = util.concatUint8Array([ct, chunk]); - } - const plaintext = new Uint8Array(ct.length); - let i; - let j = 0; - while (chunk ? ct.length >= block_size : ct.length) { - const decblock = cipherfn.encrypt(blockp); - blockp = ct; - for (i = 0; i < block_size; i++) { - plaintext[j++] = blockp[i] ^ decblock[i]; - } - ct = ct.subarray(block_size); - } - return plaintext.subarray(0, j); - }; - return transform(ciphertext, process, process); - } - - function aesEncrypt(algo, key, pt, iv, config) { - if ( - util.getWebCrypto() && - key.length !== 24 && // Chrome doesn't support 192 bit keys, see https://www.chromium.org/blink/webcrypto#TOC-AES-support - !util.isStream(pt) && - pt.length >= 3000 * config.minBytesForWebCrypto // Default to a 3MB minimum. Chrome is pretty slow for small messages, see: https://bugs.chromium.org/p/chromium/issues/detail?id=701188#c2 - ) { // Web Crypto - return webEncrypt(algo, key, pt, iv); - } - // asm.js fallback - const cfb = new AES_CFB(key, iv); - return transform(pt, value => cfb.aes.AES_Encrypt_process(value), () => cfb.aes.AES_Encrypt_finish()); - } - - function aesDecrypt(algo, key, ct, iv) { - if (util.isStream(ct)) { - const cfb = new AES_CFB(key, iv); - return transform(ct, value => cfb.aes.AES_Decrypt_process(value), () => cfb.aes.AES_Decrypt_finish()); - } - return AES_CFB.decrypt(ct, key, iv); - } - - function xorMut(a, b) { - for (let i = 0; i < a.length; i++) { - a[i] = a[i] ^ b[i]; - } - } - - async function webEncrypt(algo, key, pt, iv) { - const ALGO = 'AES-CBC'; - const _key = await webCrypto$1.importKey('raw', key, { name: ALGO }, false, ['encrypt']); - const { blockSize } = crypto.getCipher(algo); - const cbc_pt = util.concatUint8Array([new Uint8Array(blockSize), pt]); - const ct = new Uint8Array(await webCrypto$1.encrypt({ name: ALGO, iv }, _key, cbc_pt)).subarray(0, pt.length); - xorMut(ct, pt); - return ct; - } - - function nodeEncrypt(algo, key, pt, iv) { - const algoName = enums.read(enums.symmetric, algo); - const cipherObj = new nodeCrypto$1.createCipheriv(nodeAlgos[algoName], key, iv); - return transform(pt, value => new Uint8Array(cipherObj.update(value))); - } - - function nodeDecrypt(algo, key, ct, iv) { - const algoName = enums.read(enums.symmetric, algo); - const decipherObj = new nodeCrypto$1.createDecipheriv(nodeAlgos[algoName], key, iv); - return transform(ct, value => new Uint8Array(decipherObj.update(value))); - } - - var cfb = /*#__PURE__*/Object.freeze({ - __proto__: null, - encrypt: encrypt, - decrypt: decrypt - }); - - class AES_CTR { - static encrypt(data, key, nonce) { - return new AES_CTR(key, nonce).encrypt(data); - } - static decrypt(data, key, nonce) { - return new AES_CTR(key, nonce).encrypt(data); - } - constructor(key, nonce, aes) { - this.aes = aes ? aes : new AES(key, undefined, false, 'CTR'); - delete this.aes.padding; - this.AES_CTR_set_options(nonce); - } - encrypt(data) { - const r1 = this.aes.AES_Encrypt_process(data); - const r2 = this.aes.AES_Encrypt_finish(); - return joinBytes(r1, r2); - } - decrypt(data) { - const r1 = this.aes.AES_Encrypt_process(data); - const r2 = this.aes.AES_Encrypt_finish(); - return joinBytes(r1, r2); - } - AES_CTR_set_options(nonce, counter, size) { - let { asm } = this.aes.acquire_asm(); - if (size !== undefined) { - if (size < 8 || size > 48) - throw new IllegalArgumentError('illegal counter size'); - let mask = Math.pow(2, size) - 1; - asm.set_mask(0, 0, (mask / 0x100000000) | 0, mask | 0); - } - else { - size = 48; - asm.set_mask(0, 0, 0xffff, 0xffffffff); - } - if (nonce !== undefined) { - let len = nonce.length; - if (!len || len > 16) - throw new IllegalArgumentError('illegal nonce size'); - let view = new DataView(new ArrayBuffer(16)); - new Uint8Array(view.buffer).set(nonce); - asm.set_nonce(view.getUint32(0), view.getUint32(4), view.getUint32(8), view.getUint32(12)); - } - else { - throw new Error('nonce is required'); - } - if (counter !== undefined) { - if (counter < 0 || counter >= Math.pow(2, size)) - throw new IllegalArgumentError('illegal counter value'); - asm.set_counter(0, 0, (counter / 0x100000000) | 0, counter | 0); - } - } - } - - class AES_CBC { - static encrypt(data, key, padding = true, iv) { - return new AES_CBC(key, iv, padding).encrypt(data); - } - static decrypt(data, key, padding = true, iv) { - return new AES_CBC(key, iv, padding).decrypt(data); - } - constructor(key, iv, padding = true, aes) { - this.aes = aes ? aes : new AES(key, iv, padding, 'CBC'); - } - encrypt(data) { - const r1 = this.aes.AES_Encrypt_process(data); - const r2 = this.aes.AES_Encrypt_finish(); - return joinBytes(r1, r2); - } - decrypt(data) { - const r1 = this.aes.AES_Decrypt_process(data); - const r2 = this.aes.AES_Decrypt_finish(); - return joinBytes(r1, r2); - } - } - - /** - * @fileoverview This module implements AES-CMAC on top of - * native AES-CBC using either the WebCrypto API or Node.js' crypto API. - * @module crypto/cmac - * @private - */ - - const webCrypto$2 = util.getWebCrypto(); - const nodeCrypto$2 = util.getNodeCrypto(); - - - /** - * This implementation of CMAC is based on the description of OMAC in - * http://web.cs.ucdavis.edu/~rogaway/papers/eax.pdf. As per that - * document: - * - * We have made a small modification to the OMAC algorithm as it was - * originally presented, changing one of its two constants. - * Specifically, the constant 4 at line 85 was the constant 1/2 (the - * multiplicative inverse of 2) in the original definition of OMAC [14]. - * The OMAC authors indicate that they will promulgate this modification - * [15], which slightly simplifies implementations. - */ - - const blockLength = 16; - - - /** - * xor `padding` into the end of `data`. This function implements "the - * operation xor→ [which] xors the shorter string into the end of longer - * one". Since data is always as least as long as padding, we can - * simplify the implementation. - * @param {Uint8Array} data - * @param {Uint8Array} padding - */ - function rightXORMut(data, padding) { - const offset = data.length - blockLength; - for (let i = 0; i < blockLength; i++) { - data[i + offset] ^= padding[i]; - } - return data; - } - - function pad(data, padding, padding2) { - // if |M| in {n, 2n, 3n, ...} - if (data.length && data.length % blockLength === 0) { - // then return M xor→ B, - return rightXORMut(data, padding); - } - // else return (M || 10^(n−1−(|M| mod n))) xor→ P - const padded = new Uint8Array(data.length + (blockLength - data.length % blockLength)); - padded.set(data); - padded[data.length] = 0b10000000; - return rightXORMut(padded, padding2); - } - - const zeroBlock = new Uint8Array(blockLength); - - async function CMAC(key) { - const cbc = await CBC(key); - - // L ← E_K(0^n); B ← 2L; P ← 4L - const padding = util.double(await cbc(zeroBlock)); - const padding2 = util.double(padding); - - return async function(data) { - // return CBC_K(pad(M; B, P)) - return (await cbc(pad(data, padding, padding2))).subarray(-blockLength); - }; - } - - async function CBC(key) { - if (util.getWebCrypto() && key.length !== 24) { // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support - key = await webCrypto$2.importKey('raw', key, { name: 'AES-CBC', length: key.length * 8 }, false, ['encrypt']); - return async function(pt) { - const ct = await webCrypto$2.encrypt({ name: 'AES-CBC', iv: zeroBlock, length: blockLength * 8 }, key, pt); - return new Uint8Array(ct).subarray(0, ct.byteLength - blockLength); - }; - } - if (util.getNodeCrypto()) { // Node crypto library - return async function(pt) { - const en = new nodeCrypto$2.createCipheriv('aes-' + (key.length * 8) + '-cbc', key, zeroBlock); - const ct = en.update(pt); - return new Uint8Array(ct); - }; - } - // asm.js fallback - return async function(pt) { - return AES_CBC.encrypt(pt, key, false, zeroBlock); - }; - } - - // OpenPGP.js - An OpenPGP implementation in javascript - - const webCrypto$3 = util.getWebCrypto(); - const nodeCrypto$3 = util.getNodeCrypto(); - const Buffer$1 = util.getNodeBuffer(); - - - const blockLength$1 = 16; - const ivLength = blockLength$1; - const tagLength = blockLength$1; - - const zero = new Uint8Array(blockLength$1); - const one = new Uint8Array(blockLength$1); one[blockLength$1 - 1] = 1; - const two = new Uint8Array(blockLength$1); two[blockLength$1 - 1] = 2; - - async function OMAC(key) { - const cmac = await CMAC(key); - return function(t, message) { - return cmac(util.concatUint8Array([t, message])); - }; - } - - async function CTR(key) { - if ( - util.getWebCrypto() && - key.length !== 24 && // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support - (!navigator.userAgent || navigator.userAgent.indexOf('Edge') === -1) - ) { - key = await webCrypto$3.importKey('raw', key, { name: 'AES-CTR', length: key.length * 8 }, false, ['encrypt']); - return async function(pt, iv) { - const ct = await webCrypto$3.encrypt({ name: 'AES-CTR', counter: iv, length: blockLength$1 * 8 }, key, pt); - return new Uint8Array(ct); - }; - } - if (util.getNodeCrypto()) { // Node crypto library - return async function(pt, iv) { - const en = new nodeCrypto$3.createCipheriv('aes-' + (key.length * 8) + '-ctr', key, iv); - const ct = Buffer$1.concat([en.update(pt), en.final()]); - return new Uint8Array(ct); - }; - } - // asm.js fallback - return async function(pt, iv) { - return AES_CTR.encrypt(pt, key, iv); - }; - } - - - /** - * Class to en/decrypt using EAX mode. - * @param {enums.symmetric} cipher - The symmetric cipher algorithm to use - * @param {Uint8Array} key - The encryption key - */ - async function EAX(cipher, key) { - if (cipher !== enums.symmetric.aes128 && - cipher !== enums.symmetric.aes192 && - cipher !== enums.symmetric.aes256) { - throw new Error('EAX mode supports only AES cipher'); - } - - const [ - omac, - ctr - ] = await Promise.all([ - OMAC(key), - CTR(key) - ]); - - return { - /** - * Encrypt plaintext input. - * @param {Uint8Array} plaintext - The cleartext input to be encrypted - * @param {Uint8Array} nonce - The nonce (16 bytes) - * @param {Uint8Array} adata - Associated data to sign - * @returns {Promise} The ciphertext output. - */ - encrypt: async function(plaintext, nonce, adata) { - const [ - omacNonce, - omacAdata - ] = await Promise.all([ - omac(zero, nonce), - omac(one, adata) - ]); - const ciphered = await ctr(plaintext, omacNonce); - const omacCiphered = await omac(two, ciphered); - const tag = omacCiphered; // Assumes that omac(*).length === tagLength. - for (let i = 0; i < tagLength; i++) { - tag[i] ^= omacAdata[i] ^ omacNonce[i]; - } - return util.concatUint8Array([ciphered, tag]); - }, - - /** - * Decrypt ciphertext input. - * @param {Uint8Array} ciphertext - The ciphertext input to be decrypted - * @param {Uint8Array} nonce - The nonce (16 bytes) - * @param {Uint8Array} adata - Associated data to verify - * @returns {Promise} The plaintext output. - */ - decrypt: async function(ciphertext, nonce, adata) { - if (ciphertext.length < tagLength) throw new Error('Invalid EAX ciphertext'); - const ciphered = ciphertext.subarray(0, -tagLength); - const ctTag = ciphertext.subarray(-tagLength); - const [ - omacNonce, - omacAdata, - omacCiphered - ] = await Promise.all([ - omac(zero, nonce), - omac(one, adata), - omac(two, ciphered) - ]); - const tag = omacCiphered; // Assumes that omac(*).length === tagLength. - for (let i = 0; i < tagLength; i++) { - tag[i] ^= omacAdata[i] ^ omacNonce[i]; - } - if (!util.equalsUint8Array(ctTag, tag)) throw new Error('Authentication tag mismatch'); - const plaintext = await ctr(ciphered, omacNonce); - return plaintext; - } - }; - } - - - /** - * Get EAX nonce as defined by {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.1|RFC4880bis-04, section 5.16.1}. - * @param {Uint8Array} iv - The initialization vector (16 bytes) - * @param {Uint8Array} chunkIndex - The chunk index (8 bytes) - */ - EAX.getNonce = function(iv, chunkIndex) { - const nonce = iv.slice(); - for (let i = 0; i < chunkIndex.length; i++) { - nonce[8 + i] ^= chunkIndex[i]; - } - return nonce; - }; - - EAX.blockLength = blockLength$1; - EAX.ivLength = ivLength; - EAX.tagLength = tagLength; - - // OpenPGP.js - An OpenPGP implementation in javascript - - const blockLength$2 = 16; - const ivLength$1 = 15; - - // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.2: - // While OCB [RFC7253] allows the authentication tag length to be of any - // number up to 128 bits long, this document requires a fixed - // authentication tag length of 128 bits (16 octets) for simplicity. - const tagLength$1 = 16; - - - function ntz(n) { - let ntz = 0; - for (let i = 1; (n & i) === 0; i <<= 1) { - ntz++; - } - return ntz; - } - - function xorMut$1(S, T) { - for (let i = 0; i < S.length; i++) { - S[i] ^= T[i]; - } - return S; - } - - function xor(S, T) { - return xorMut$1(S.slice(), T); - } - - const zeroBlock$1 = new Uint8Array(blockLength$2); - const one$1 = new Uint8Array([1]); - - /** - * Class to en/decrypt using OCB mode. - * @param {enums.symmetric} cipher - The symmetric cipher algorithm to use - * @param {Uint8Array} key - The encryption key - */ - async function OCB(cipher$1, key) { - - let maxNtz = 0; - let encipher; - let decipher; - let mask; - - constructKeyVariables(cipher$1, key); - - function constructKeyVariables(cipher$1, key) { - const cipherName = enums.read(enums.symmetric, cipher$1); - const aes = new cipher[cipherName](key); - encipher = aes.encrypt.bind(aes); - decipher = aes.decrypt.bind(aes); - - const mask_x = encipher(zeroBlock$1); - const mask_$ = util.double(mask_x); - mask = []; - mask[0] = util.double(mask_$); - - - mask.x = mask_x; - mask.$ = mask_$; - } - - function extendKeyVariables(text, adata) { - const newMaxNtz = util.nbits(Math.max(text.length, adata.length) / blockLength$2 | 0) - 1; - for (let i = maxNtz + 1; i <= newMaxNtz; i++) { - mask[i] = util.double(mask[i - 1]); - } - maxNtz = newMaxNtz; - } - - function hash(adata) { - if (!adata.length) { - // Fast path - return zeroBlock$1; - } - - // - // Consider A as a sequence of 128-bit blocks - // - const m = adata.length / blockLength$2 | 0; - - const offset = new Uint8Array(blockLength$2); - const sum = new Uint8Array(blockLength$2); - for (let i = 0; i < m; i++) { - xorMut$1(offset, mask[ntz(i + 1)]); - xorMut$1(sum, encipher(xor(offset, adata))); - adata = adata.subarray(blockLength$2); - } - - // - // Process any final partial block; compute final hash value - // - if (adata.length) { - xorMut$1(offset, mask.x); - - const cipherInput = new Uint8Array(blockLength$2); - cipherInput.set(adata, 0); - cipherInput[adata.length] = 0b10000000; - xorMut$1(cipherInput, offset); - - xorMut$1(sum, encipher(cipherInput)); - } - - return sum; - } - - /** - * Encrypt/decrypt data. - * @param {encipher|decipher} fn - Encryption/decryption block cipher function - * @param {Uint8Array} text - The cleartext or ciphertext (without tag) input - * @param {Uint8Array} nonce - The nonce (15 bytes) - * @param {Uint8Array} adata - Associated data to sign - * @returns {Promise} The ciphertext or plaintext output, with tag appended in both cases. - */ - function crypt(fn, text, nonce, adata) { - // - // Consider P as a sequence of 128-bit blocks - // - const m = text.length / blockLength$2 | 0; - - // - // Key-dependent variables - // - extendKeyVariables(text, adata); - - // - // Nonce-dependent and per-encryption variables - // - // Nonce = num2str(TAGLEN mod 128,7) || zeros(120-bitlen(N)) || 1 || N - // Note: We assume here that tagLength mod 16 == 0. - const paddedNonce = util.concatUint8Array([zeroBlock$1.subarray(0, ivLength$1 - nonce.length), one$1, nonce]); - // bottom = str2num(Nonce[123..128]) - const bottom = paddedNonce[blockLength$2 - 1] & 0b111111; - // Ktop = ENCIPHER(K, Nonce[1..122] || zeros(6)) - paddedNonce[blockLength$2 - 1] &= 0b11000000; - const kTop = encipher(paddedNonce); - // Stretch = Ktop || (Ktop[1..64] xor Ktop[9..72]) - const stretched = util.concatUint8Array([kTop, xor(kTop.subarray(0, 8), kTop.subarray(1, 9))]); - // Offset_0 = Stretch[1+bottom..128+bottom] - const offset = util.shiftRight(stretched.subarray(0 + (bottom >> 3), 17 + (bottom >> 3)), 8 - (bottom & 7)).subarray(1); - // Checksum_0 = zeros(128) - const checksum = new Uint8Array(blockLength$2); - - const ct = new Uint8Array(text.length + tagLength$1); - - // - // Process any whole blocks - // - let i; - let pos = 0; - for (i = 0; i < m; i++) { - // Offset_i = Offset_{i-1} xor L_{ntz(i)} - xorMut$1(offset, mask[ntz(i + 1)]); - // C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) - // P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i) - ct.set(xorMut$1(fn(xor(offset, text)), offset), pos); - // Checksum_i = Checksum_{i-1} xor P_i - xorMut$1(checksum, fn === encipher ? text : ct.subarray(pos)); - - text = text.subarray(blockLength$2); - pos += blockLength$2; - } - - // - // Process any final partial block and compute raw tag - // - if (text.length) { - // Offset_* = Offset_m xor L_* - xorMut$1(offset, mask.x); - // Pad = ENCIPHER(K, Offset_*) - const padding = encipher(offset); - // C_* = P_* xor Pad[1..bitlen(P_*)] - ct.set(xor(text, padding), pos); - - // Checksum_* = Checksum_m xor (P_* || 1 || new Uint8Array(127-bitlen(P_*))) - const xorInput = new Uint8Array(blockLength$2); - xorInput.set(fn === encipher ? text : ct.subarray(pos, -tagLength$1), 0); - xorInput[text.length] = 0b10000000; - xorMut$1(checksum, xorInput); - pos += text.length; - } - // Tag = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) xor HASH(K,A) - const tag = xorMut$1(encipher(xorMut$1(xorMut$1(checksum, offset), mask.$)), hash(adata)); - - // - // Assemble ciphertext - // - // C = C_1 || C_2 || ... || C_m || C_* || Tag[1..TAGLEN] - ct.set(tag, pos); - return ct; - } - - - return { - /** - * Encrypt plaintext input. - * @param {Uint8Array} plaintext - The cleartext input to be encrypted - * @param {Uint8Array} nonce - The nonce (15 bytes) - * @param {Uint8Array} adata - Associated data to sign - * @returns {Promise} The ciphertext output. - */ - encrypt: async function(plaintext, nonce, adata) { - return crypt(encipher, plaintext, nonce, adata); - }, - - /** - * Decrypt ciphertext input. - * @param {Uint8Array} ciphertext - The ciphertext input to be decrypted - * @param {Uint8Array} nonce - The nonce (15 bytes) - * @param {Uint8Array} adata - Associated data to sign - * @returns {Promise} The ciphertext output. - */ - decrypt: async function(ciphertext, nonce, adata) { - if (ciphertext.length < tagLength$1) throw new Error('Invalid OCB ciphertext'); - - const tag = ciphertext.subarray(-tagLength$1); - ciphertext = ciphertext.subarray(0, -tagLength$1); - - const crypted = crypt(decipher, ciphertext, nonce, adata); - // if (Tag[1..TAGLEN] == T) - if (util.equalsUint8Array(tag, crypted.subarray(-tagLength$1))) { - return crypted.subarray(0, -tagLength$1); - } - throw new Error('Authentication tag mismatch'); - } - }; - } - - - /** - * Get OCB nonce as defined by {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.2|RFC4880bis-04, section 5.16.2}. - * @param {Uint8Array} iv - The initialization vector (15 bytes) - * @param {Uint8Array} chunkIndex - The chunk index (8 bytes) - */ - OCB.getNonce = function(iv, chunkIndex) { - const nonce = iv.slice(); - for (let i = 0; i < chunkIndex.length; i++) { - nonce[7 + i] ^= chunkIndex[i]; - } - return nonce; - }; - - OCB.blockLength = blockLength$2; - OCB.ivLength = ivLength$1; - OCB.tagLength = tagLength$1; - - const _AES_GCM_data_maxLength = 68719476704; // 2^36 - 2^5 - class AES_GCM { - constructor(key, nonce, adata, tagSize = 16, aes) { - this.tagSize = tagSize; - this.gamma0 = 0; - this.counter = 1; - this.aes = aes ? aes : new AES(key, undefined, false, 'CTR'); - let { asm, heap } = this.aes.acquire_asm(); - // Init GCM - asm.gcm_init(); - // Tag size - if (this.tagSize < 4 || this.tagSize > 16) - throw new IllegalArgumentError('illegal tagSize value'); - // Nonce - const noncelen = nonce.length || 0; - const noncebuf = new Uint8Array(16); - if (noncelen !== 12) { - this._gcm_mac_process(nonce); - heap[0] = 0; - heap[1] = 0; - heap[2] = 0; - heap[3] = 0; - heap[4] = 0; - heap[5] = 0; - heap[6] = 0; - heap[7] = 0; - heap[8] = 0; - heap[9] = 0; - heap[10] = 0; - heap[11] = noncelen >>> 29; - heap[12] = (noncelen >>> 21) & 255; - heap[13] = (noncelen >>> 13) & 255; - heap[14] = (noncelen >>> 5) & 255; - heap[15] = (noncelen << 3) & 255; - asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16); - asm.get_iv(AES_asm.HEAP_DATA); - asm.set_iv(0, 0, 0, 0); - noncebuf.set(heap.subarray(0, 16)); - } - else { - noncebuf.set(nonce); - noncebuf[15] = 1; - } - const nonceview = new DataView(noncebuf.buffer); - this.gamma0 = nonceview.getUint32(12); - asm.set_nonce(nonceview.getUint32(0), nonceview.getUint32(4), nonceview.getUint32(8), 0); - asm.set_mask(0, 0, 0, 0xffffffff); - // Associated data - if (adata !== undefined) { - if (adata.length > _AES_GCM_data_maxLength) - throw new IllegalArgumentError('illegal adata length'); - if (adata.length) { - this.adata = adata; - this._gcm_mac_process(adata); - } - else { - this.adata = undefined; - } - } - else { - this.adata = undefined; - } - // Counter - if (this.counter < 1 || this.counter > 0xffffffff) - throw new RangeError('counter must be a positive 32-bit integer'); - asm.set_counter(0, 0, 0, (this.gamma0 + this.counter) | 0); - } - static encrypt(cleartext, key, nonce, adata, tagsize) { - return new AES_GCM(key, nonce, adata, tagsize).encrypt(cleartext); - } - static decrypt(ciphertext, key, nonce, adata, tagsize) { - return new AES_GCM(key, nonce, adata, tagsize).decrypt(ciphertext); - } - encrypt(data) { - return this.AES_GCM_encrypt(data); - } - decrypt(data) { - return this.AES_GCM_decrypt(data); - } - AES_GCM_Encrypt_process(data) { - let dpos = 0; - let dlen = data.length || 0; - let { asm, heap } = this.aes.acquire_asm(); - let counter = this.counter; - let pos = this.aes.pos; - let len = this.aes.len; - let rpos = 0; - let rlen = (len + dlen) & -16; - let wlen = 0; - if (((counter - 1) << 4) + len + dlen > _AES_GCM_data_maxLength) - throw new RangeError('counter overflow'); - const result = new Uint8Array(rlen); - while (dlen > 0) { - wlen = _heap_write(heap, pos + len, data, dpos, dlen); - len += wlen; - dpos += wlen; - dlen -= wlen; - wlen = asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, len); - wlen = asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, wlen); - if (wlen) - result.set(heap.subarray(pos, pos + wlen), rpos); - counter += wlen >>> 4; - rpos += wlen; - if (wlen < len) { - pos += wlen; - len -= wlen; - } - else { - pos = 0; - len = 0; - } - } - this.counter = counter; - this.aes.pos = pos; - this.aes.len = len; - return result; - } - AES_GCM_Encrypt_finish() { - let { asm, heap } = this.aes.acquire_asm(); - let counter = this.counter; - let tagSize = this.tagSize; - let adata = this.adata; - let pos = this.aes.pos; - let len = this.aes.len; - const result = new Uint8Array(len + tagSize); - asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, (len + 15) & -16); - if (len) - result.set(heap.subarray(pos, pos + len)); - let i = len; - for (; i & 15; i++) - heap[pos + i] = 0; - asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, i); - const alen = adata !== undefined ? adata.length : 0; - const clen = ((counter - 1) << 4) + len; - heap[0] = 0; - heap[1] = 0; - heap[2] = 0; - heap[3] = alen >>> 29; - heap[4] = alen >>> 21; - heap[5] = (alen >>> 13) & 255; - heap[6] = (alen >>> 5) & 255; - heap[7] = (alen << 3) & 255; - heap[8] = heap[9] = heap[10] = 0; - heap[11] = clen >>> 29; - heap[12] = (clen >>> 21) & 255; - heap[13] = (clen >>> 13) & 255; - heap[14] = (clen >>> 5) & 255; - heap[15] = (clen << 3) & 255; - asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16); - asm.get_iv(AES_asm.HEAP_DATA); - asm.set_counter(0, 0, 0, this.gamma0); - asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16); - result.set(heap.subarray(0, tagSize), len); - this.counter = 1; - this.aes.pos = 0; - this.aes.len = 0; - return result; - } - AES_GCM_Decrypt_process(data) { - let dpos = 0; - let dlen = data.length || 0; - let { asm, heap } = this.aes.acquire_asm(); - let counter = this.counter; - let tagSize = this.tagSize; - let pos = this.aes.pos; - let len = this.aes.len; - let rpos = 0; - let rlen = len + dlen > tagSize ? (len + dlen - tagSize) & -16 : 0; - let tlen = len + dlen - rlen; - let wlen = 0; - if (((counter - 1) << 4) + len + dlen > _AES_GCM_data_maxLength) - throw new RangeError('counter overflow'); - const result = new Uint8Array(rlen); - while (dlen > tlen) { - wlen = _heap_write(heap, pos + len, data, dpos, dlen - tlen); - len += wlen; - dpos += wlen; - dlen -= wlen; - wlen = asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, wlen); - wlen = asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, wlen); - if (wlen) - result.set(heap.subarray(pos, pos + wlen), rpos); - counter += wlen >>> 4; - rpos += wlen; - pos = 0; - len = 0; - } - if (dlen > 0) { - len += _heap_write(heap, 0, data, dpos, dlen); - } - this.counter = counter; - this.aes.pos = pos; - this.aes.len = len; - return result; - } - AES_GCM_Decrypt_finish() { - let { asm, heap } = this.aes.acquire_asm(); - let tagSize = this.tagSize; - let adata = this.adata; - let counter = this.counter; - let pos = this.aes.pos; - let len = this.aes.len; - let rlen = len - tagSize; - if (len < tagSize) - throw new IllegalStateError('authentication tag not found'); - const result = new Uint8Array(rlen); - const atag = new Uint8Array(heap.subarray(pos + rlen, pos + len)); - let i = rlen; - for (; i & 15; i++) - heap[pos + i] = 0; - asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, i); - asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, i); - if (rlen) - result.set(heap.subarray(pos, pos + rlen)); - const alen = adata !== undefined ? adata.length : 0; - const clen = ((counter - 1) << 4) + len - tagSize; - heap[0] = 0; - heap[1] = 0; - heap[2] = 0; - heap[3] = alen >>> 29; - heap[4] = alen >>> 21; - heap[5] = (alen >>> 13) & 255; - heap[6] = (alen >>> 5) & 255; - heap[7] = (alen << 3) & 255; - heap[8] = heap[9] = heap[10] = 0; - heap[11] = clen >>> 29; - heap[12] = (clen >>> 21) & 255; - heap[13] = (clen >>> 13) & 255; - heap[14] = (clen >>> 5) & 255; - heap[15] = (clen << 3) & 255; - asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16); - asm.get_iv(AES_asm.HEAP_DATA); - asm.set_counter(0, 0, 0, this.gamma0); - asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16); - let acheck = 0; - for (let i = 0; i < tagSize; ++i) - acheck |= atag[i] ^ heap[i]; - if (acheck) - throw new SecurityError('data integrity check failed'); - this.counter = 1; - this.aes.pos = 0; - this.aes.len = 0; - return result; - } - AES_GCM_decrypt(data) { - const result1 = this.AES_GCM_Decrypt_process(data); - const result2 = this.AES_GCM_Decrypt_finish(); - const result = new Uint8Array(result1.length + result2.length); - if (result1.length) - result.set(result1); - if (result2.length) - result.set(result2, result1.length); - return result; - } - AES_GCM_encrypt(data) { - const result1 = this.AES_GCM_Encrypt_process(data); - const result2 = this.AES_GCM_Encrypt_finish(); - const result = new Uint8Array(result1.length + result2.length); - if (result1.length) - result.set(result1); - if (result2.length) - result.set(result2, result1.length); - return result; - } - _gcm_mac_process(data) { - let { asm, heap } = this.aes.acquire_asm(); - let dpos = 0; - let dlen = data.length || 0; - let wlen = 0; - while (dlen > 0) { - wlen = _heap_write(heap, 0, data, dpos, dlen); - dpos += wlen; - dlen -= wlen; - while (wlen & 15) - heap[wlen++] = 0; - asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, wlen); - } - } - } - - // OpenPGP.js - An OpenPGP implementation in javascript - - const webCrypto$4 = util.getWebCrypto(); - const nodeCrypto$4 = util.getNodeCrypto(); - const Buffer$2 = util.getNodeBuffer(); - - const blockLength$3 = 16; - const ivLength$2 = 12; // size of the IV in bytes - const tagLength$2 = 16; // size of the tag in bytes - const ALGO = 'AES-GCM'; - - /** - * Class to en/decrypt using GCM mode. - * @param {enums.symmetric} cipher - The symmetric cipher algorithm to use - * @param {Uint8Array} key - The encryption key - */ - async function GCM(cipher, key) { - if (cipher !== enums.symmetric.aes128 && - cipher !== enums.symmetric.aes192 && - cipher !== enums.symmetric.aes256) { - throw new Error('GCM mode supports only AES cipher'); - } - - if (util.getWebCrypto() && key.length !== 24) { // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support - const _key = await webCrypto$4.importKey('raw', key, { name: ALGO }, false, ['encrypt', 'decrypt']); - - return { - encrypt: async function(pt, iv, adata = new Uint8Array()) { - if ( - !pt.length || - // iOS does not support GCM-en/decrypting empty messages - // Also, synchronous en/decryption might be faster in this case. - (!adata.length && navigator.userAgent && navigator.userAgent.indexOf('Edge') !== -1) - // Edge does not support GCM-en/decrypting without ADATA - ) { - return AES_GCM.encrypt(pt, key, iv, adata); - } - const ct = await webCrypto$4.encrypt({ name: ALGO, iv, additionalData: adata, tagLength: tagLength$2 * 8 }, _key, pt); - return new Uint8Array(ct); - }, - - decrypt: async function(ct, iv, adata = new Uint8Array()) { - if ( - ct.length === tagLength$2 || - // iOS does not support GCM-en/decrypting empty messages - // Also, synchronous en/decryption might be faster in this case. - (!adata.length && navigator.userAgent && navigator.userAgent.indexOf('Edge') !== -1) - // Edge does not support GCM-en/decrypting without ADATA - ) { - return AES_GCM.decrypt(ct, key, iv, adata); - } - const pt = await webCrypto$4.decrypt({ name: ALGO, iv, additionalData: adata, tagLength: tagLength$2 * 8 }, _key, ct); - return new Uint8Array(pt); - } - }; - } - - if (util.getNodeCrypto()) { // Node crypto library - return { - encrypt: async function(pt, iv, adata = new Uint8Array()) { - const en = new nodeCrypto$4.createCipheriv('aes-' + (key.length * 8) + '-gcm', key, iv); - en.setAAD(adata); - const ct = Buffer$2.concat([en.update(pt), en.final(), en.getAuthTag()]); // append auth tag to ciphertext - return new Uint8Array(ct); - }, - - decrypt: async function(ct, iv, adata = new Uint8Array()) { - const de = new nodeCrypto$4.createDecipheriv('aes-' + (key.length * 8) + '-gcm', key, iv); - de.setAAD(adata); - de.setAuthTag(ct.slice(ct.length - tagLength$2, ct.length)); // read auth tag at end of ciphertext - const pt = Buffer$2.concat([de.update(ct.slice(0, ct.length - tagLength$2)), de.final()]); - return new Uint8Array(pt); - } - }; - } - - return { - encrypt: async function(pt, iv, adata) { - return AES_GCM.encrypt(pt, key, iv, adata); - }, - - decrypt: async function(ct, iv, adata) { - return AES_GCM.decrypt(ct, key, iv, adata); - } - }; - } - - - /** - * Get GCM nonce. Note: this operation is not defined by the standard. - * A future version of the standard may define GCM mode differently, - * hopefully under a different ID (we use Private/Experimental algorithm - * ID 100) so that we can maintain backwards compatibility. - * @param {Uint8Array} iv - The initialization vector (12 bytes) - * @param {Uint8Array} chunkIndex - The chunk index (8 bytes) - */ - GCM.getNonce = function(iv, chunkIndex) { - const nonce = iv.slice(); - for (let i = 0; i < chunkIndex.length; i++) { - nonce[4 + i] ^= chunkIndex[i]; - } - return nonce; - }; - - GCM.blockLength = blockLength$3; - GCM.ivLength = ivLength$2; - GCM.tagLength = tagLength$2; - - /** - * @fileoverview Cipher modes - * @module crypto/mode - * @private - */ - - var mode = { - /** @see module:crypto/mode/cfb */ - cfb: cfb, - /** @see module:crypto/mode/gcm */ - gcm: GCM, - experimentalGCM: GCM, - /** @see module:crypto/mode/eax */ - eax: EAX, - /** @see module:crypto/mode/ocb */ - ocb: OCB - }; - - var naclFastLight = createCommonjsModule(function (module) { - /*jshint bitwise: false*/ - - (function(nacl) { - - // Ported in 2014 by Dmitry Chestnykh and Devi Mandiri. - // Public domain. - // - // Implementation derived from TweetNaCl version 20140427. - // See for details: http://tweetnacl.cr.yp.to/ - - var gf = function(init) { - var i, r = new Float64Array(16); - if (init) for (i = 0; i < init.length; i++) r[i] = init[i]; - return r; - }; - - // Pluggable, initialized in high-level API below. - var randombytes = function(/* x, n */) { throw new Error('no PRNG'); }; - - var _9 = new Uint8Array(32); _9[0] = 9; - - var gf0 = gf(), - gf1 = gf([1]), - _121665 = gf([0xdb41, 1]), - D = gf([0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203]), - D2 = gf([0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406]), - X = gf([0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169]), - Y = gf([0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666]), - I = gf([0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83]); - - function vn(x, xi, y, yi, n) { - var i,d = 0; - for (i = 0; i < n; i++) d |= x[xi+i]^y[yi+i]; - return (1 & ((d - 1) >>> 8)) - 1; - } - - function crypto_verify_32(x, xi, y, yi) { - return vn(x,xi,y,yi,32); - } - - function set25519(r, a) { - var i; - for (i = 0; i < 16; i++) r[i] = a[i]|0; - } - - function car25519(o) { - var i, v, c = 1; - for (i = 0; i < 16; i++) { - v = o[i] + c + 65535; - c = Math.floor(v / 65536); - o[i] = v - c * 65536; - } - o[0] += c-1 + 37 * (c-1); - } - - function sel25519(p, q, b) { - var t, c = ~(b-1); - for (var i = 0; i < 16; i++) { - t = c & (p[i] ^ q[i]); - p[i] ^= t; - q[i] ^= t; - } - } - - function pack25519(o, n) { - var i, j, b; - var m = gf(), t = gf(); - for (i = 0; i < 16; i++) t[i] = n[i]; - car25519(t); - car25519(t); - car25519(t); - for (j = 0; j < 2; j++) { - m[0] = t[0] - 0xffed; - for (i = 1; i < 15; i++) { - m[i] = t[i] - 0xffff - ((m[i-1]>>16) & 1); - m[i-1] &= 0xffff; - } - m[15] = t[15] - 0x7fff - ((m[14]>>16) & 1); - b = (m[15]>>16) & 1; - m[14] &= 0xffff; - sel25519(t, m, 1-b); - } - for (i = 0; i < 16; i++) { - o[2*i] = t[i] & 0xff; - o[2*i+1] = t[i]>>8; - } - } - - function neq25519(a, b) { - var c = new Uint8Array(32), d = new Uint8Array(32); - pack25519(c, a); - pack25519(d, b); - return crypto_verify_32(c, 0, d, 0); - } - - function par25519(a) { - var d = new Uint8Array(32); - pack25519(d, a); - return d[0] & 1; - } - - function unpack25519(o, n) { - var i; - for (i = 0; i < 16; i++) o[i] = n[2*i] + (n[2*i+1] << 8); - o[15] &= 0x7fff; - } - - function A(o, a, b) { - for (var i = 0; i < 16; i++) o[i] = a[i] + b[i]; - } - - function Z(o, a, b) { - for (var i = 0; i < 16; i++) o[i] = a[i] - b[i]; - } - - function M(o, a, b) { - var v, c, - t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0, - t8 = 0, t9 = 0, t10 = 0, t11 = 0, t12 = 0, t13 = 0, t14 = 0, t15 = 0, - t16 = 0, t17 = 0, t18 = 0, t19 = 0, t20 = 0, t21 = 0, t22 = 0, t23 = 0, - t24 = 0, t25 = 0, t26 = 0, t27 = 0, t28 = 0, t29 = 0, t30 = 0, - b0 = b[0], - b1 = b[1], - b2 = b[2], - b3 = b[3], - b4 = b[4], - b5 = b[5], - b6 = b[6], - b7 = b[7], - b8 = b[8], - b9 = b[9], - b10 = b[10], - b11 = b[11], - b12 = b[12], - b13 = b[13], - b14 = b[14], - b15 = b[15]; - - v = a[0]; - t0 += v * b0; - t1 += v * b1; - t2 += v * b2; - t3 += v * b3; - t4 += v * b4; - t5 += v * b5; - t6 += v * b6; - t7 += v * b7; - t8 += v * b8; - t9 += v * b9; - t10 += v * b10; - t11 += v * b11; - t12 += v * b12; - t13 += v * b13; - t14 += v * b14; - t15 += v * b15; - v = a[1]; - t1 += v * b0; - t2 += v * b1; - t3 += v * b2; - t4 += v * b3; - t5 += v * b4; - t6 += v * b5; - t7 += v * b6; - t8 += v * b7; - t9 += v * b8; - t10 += v * b9; - t11 += v * b10; - t12 += v * b11; - t13 += v * b12; - t14 += v * b13; - t15 += v * b14; - t16 += v * b15; - v = a[2]; - t2 += v * b0; - t3 += v * b1; - t4 += v * b2; - t5 += v * b3; - t6 += v * b4; - t7 += v * b5; - t8 += v * b6; - t9 += v * b7; - t10 += v * b8; - t11 += v * b9; - t12 += v * b10; - t13 += v * b11; - t14 += v * b12; - t15 += v * b13; - t16 += v * b14; - t17 += v * b15; - v = a[3]; - t3 += v * b0; - t4 += v * b1; - t5 += v * b2; - t6 += v * b3; - t7 += v * b4; - t8 += v * b5; - t9 += v * b6; - t10 += v * b7; - t11 += v * b8; - t12 += v * b9; - t13 += v * b10; - t14 += v * b11; - t15 += v * b12; - t16 += v * b13; - t17 += v * b14; - t18 += v * b15; - v = a[4]; - t4 += v * b0; - t5 += v * b1; - t6 += v * b2; - t7 += v * b3; - t8 += v * b4; - t9 += v * b5; - t10 += v * b6; - t11 += v * b7; - t12 += v * b8; - t13 += v * b9; - t14 += v * b10; - t15 += v * b11; - t16 += v * b12; - t17 += v * b13; - t18 += v * b14; - t19 += v * b15; - v = a[5]; - t5 += v * b0; - t6 += v * b1; - t7 += v * b2; - t8 += v * b3; - t9 += v * b4; - t10 += v * b5; - t11 += v * b6; - t12 += v * b7; - t13 += v * b8; - t14 += v * b9; - t15 += v * b10; - t16 += v * b11; - t17 += v * b12; - t18 += v * b13; - t19 += v * b14; - t20 += v * b15; - v = a[6]; - t6 += v * b0; - t7 += v * b1; - t8 += v * b2; - t9 += v * b3; - t10 += v * b4; - t11 += v * b5; - t12 += v * b6; - t13 += v * b7; - t14 += v * b8; - t15 += v * b9; - t16 += v * b10; - t17 += v * b11; - t18 += v * b12; - t19 += v * b13; - t20 += v * b14; - t21 += v * b15; - v = a[7]; - t7 += v * b0; - t8 += v * b1; - t9 += v * b2; - t10 += v * b3; - t11 += v * b4; - t12 += v * b5; - t13 += v * b6; - t14 += v * b7; - t15 += v * b8; - t16 += v * b9; - t17 += v * b10; - t18 += v * b11; - t19 += v * b12; - t20 += v * b13; - t21 += v * b14; - t22 += v * b15; - v = a[8]; - t8 += v * b0; - t9 += v * b1; - t10 += v * b2; - t11 += v * b3; - t12 += v * b4; - t13 += v * b5; - t14 += v * b6; - t15 += v * b7; - t16 += v * b8; - t17 += v * b9; - t18 += v * b10; - t19 += v * b11; - t20 += v * b12; - t21 += v * b13; - t22 += v * b14; - t23 += v * b15; - v = a[9]; - t9 += v * b0; - t10 += v * b1; - t11 += v * b2; - t12 += v * b3; - t13 += v * b4; - t14 += v * b5; - t15 += v * b6; - t16 += v * b7; - t17 += v * b8; - t18 += v * b9; - t19 += v * b10; - t20 += v * b11; - t21 += v * b12; - t22 += v * b13; - t23 += v * b14; - t24 += v * b15; - v = a[10]; - t10 += v * b0; - t11 += v * b1; - t12 += v * b2; - t13 += v * b3; - t14 += v * b4; - t15 += v * b5; - t16 += v * b6; - t17 += v * b7; - t18 += v * b8; - t19 += v * b9; - t20 += v * b10; - t21 += v * b11; - t22 += v * b12; - t23 += v * b13; - t24 += v * b14; - t25 += v * b15; - v = a[11]; - t11 += v * b0; - t12 += v * b1; - t13 += v * b2; - t14 += v * b3; - t15 += v * b4; - t16 += v * b5; - t17 += v * b6; - t18 += v * b7; - t19 += v * b8; - t20 += v * b9; - t21 += v * b10; - t22 += v * b11; - t23 += v * b12; - t24 += v * b13; - t25 += v * b14; - t26 += v * b15; - v = a[12]; - t12 += v * b0; - t13 += v * b1; - t14 += v * b2; - t15 += v * b3; - t16 += v * b4; - t17 += v * b5; - t18 += v * b6; - t19 += v * b7; - t20 += v * b8; - t21 += v * b9; - t22 += v * b10; - t23 += v * b11; - t24 += v * b12; - t25 += v * b13; - t26 += v * b14; - t27 += v * b15; - v = a[13]; - t13 += v * b0; - t14 += v * b1; - t15 += v * b2; - t16 += v * b3; - t17 += v * b4; - t18 += v * b5; - t19 += v * b6; - t20 += v * b7; - t21 += v * b8; - t22 += v * b9; - t23 += v * b10; - t24 += v * b11; - t25 += v * b12; - t26 += v * b13; - t27 += v * b14; - t28 += v * b15; - v = a[14]; - t14 += v * b0; - t15 += v * b1; - t16 += v * b2; - t17 += v * b3; - t18 += v * b4; - t19 += v * b5; - t20 += v * b6; - t21 += v * b7; - t22 += v * b8; - t23 += v * b9; - t24 += v * b10; - t25 += v * b11; - t26 += v * b12; - t27 += v * b13; - t28 += v * b14; - t29 += v * b15; - v = a[15]; - t15 += v * b0; - t16 += v * b1; - t17 += v * b2; - t18 += v * b3; - t19 += v * b4; - t20 += v * b5; - t21 += v * b6; - t22 += v * b7; - t23 += v * b8; - t24 += v * b9; - t25 += v * b10; - t26 += v * b11; - t27 += v * b12; - t28 += v * b13; - t29 += v * b14; - t30 += v * b15; - - t0 += 38 * t16; - t1 += 38 * t17; - t2 += 38 * t18; - t3 += 38 * t19; - t4 += 38 * t20; - t5 += 38 * t21; - t6 += 38 * t22; - t7 += 38 * t23; - t8 += 38 * t24; - t9 += 38 * t25; - t10 += 38 * t26; - t11 += 38 * t27; - t12 += 38 * t28; - t13 += 38 * t29; - t14 += 38 * t30; - // t15 left as is - - // first car - c = 1; - v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536; - v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536; - v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536; - v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536; - v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536; - v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536; - v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536; - v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536; - v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536; - v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536; - v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536; - v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536; - v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536; - v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536; - v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536; - v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536; - t0 += c-1 + 37 * (c-1); - - // second car - c = 1; - v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536; - v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536; - v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536; - v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536; - v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536; - v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536; - v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536; - v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536; - v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536; - v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536; - v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536; - v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536; - v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536; - v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536; - v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536; - v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536; - t0 += c-1 + 37 * (c-1); - - o[ 0] = t0; - o[ 1] = t1; - o[ 2] = t2; - o[ 3] = t3; - o[ 4] = t4; - o[ 5] = t5; - o[ 6] = t6; - o[ 7] = t7; - o[ 8] = t8; - o[ 9] = t9; - o[10] = t10; - o[11] = t11; - o[12] = t12; - o[13] = t13; - o[14] = t14; - o[15] = t15; - } - - function S(o, a) { - M(o, a, a); - } - - function inv25519(o, i) { - var c = gf(); - var a; - for (a = 0; a < 16; a++) c[a] = i[a]; - for (a = 253; a >= 0; a--) { - S(c, c); - if(a !== 2 && a !== 4) M(c, c, i); - } - for (a = 0; a < 16; a++) o[a] = c[a]; - } - - function pow2523(o, i) { - var c = gf(); - var a; - for (a = 0; a < 16; a++) c[a] = i[a]; - for (a = 250; a >= 0; a--) { - S(c, c); - if(a !== 1) M(c, c, i); - } - for (a = 0; a < 16; a++) o[a] = c[a]; - } - - function crypto_scalarmult(q, n, p) { - var z = new Uint8Array(32); - var x = new Float64Array(80), r, i; - var a = gf(), b = gf(), c = gf(), - d = gf(), e = gf(), f = gf(); - for (i = 0; i < 31; i++) z[i] = n[i]; - z[31]=(n[31]&127)|64; - z[0]&=248; - unpack25519(x,p); - for (i = 0; i < 16; i++) { - b[i]=x[i]; - d[i]=a[i]=c[i]=0; - } - a[0]=d[0]=1; - for (i=254; i>=0; --i) { - r=(z[i>>>3]>>>(i&7))&1; - sel25519(a,b,r); - sel25519(c,d,r); - A(e,a,c); - Z(a,a,c); - A(c,b,d); - Z(b,b,d); - S(d,e); - S(f,a); - M(a,c,a); - M(c,b,e); - A(e,a,c); - Z(a,a,c); - S(b,a); - Z(c,d,f); - M(a,c,_121665); - A(a,a,d); - M(c,c,a); - M(a,d,f); - M(d,b,x); - S(b,e); - sel25519(a,b,r); - sel25519(c,d,r); - } - for (i = 0; i < 16; i++) { - x[i+16]=a[i]; - x[i+32]=c[i]; - x[i+48]=b[i]; - x[i+64]=d[i]; - } - var x32 = x.subarray(32); - var x16 = x.subarray(16); - inv25519(x32,x32); - M(x16,x16,x32); - pack25519(q,x16); - return 0; - } - - function crypto_scalarmult_base(q, n) { - return crypto_scalarmult(q, n, _9); - } - - function crypto_box_keypair(y, x) { - randombytes(x, 32); - return crypto_scalarmult_base(y, x); - } - - function add(p, q) { - var a = gf(), b = gf(), c = gf(), - d = gf(), e = gf(), f = gf(), - g = gf(), h = gf(), t = gf(); - - Z(a, p[1], p[0]); - Z(t, q[1], q[0]); - M(a, a, t); - A(b, p[0], p[1]); - A(t, q[0], q[1]); - M(b, b, t); - M(c, p[3], q[3]); - M(c, c, D2); - M(d, p[2], q[2]); - A(d, d, d); - Z(e, b, a); - Z(f, d, c); - A(g, d, c); - A(h, b, a); - - M(p[0], e, f); - M(p[1], h, g); - M(p[2], g, f); - M(p[3], e, h); - } - - function cswap(p, q, b) { - var i; - for (i = 0; i < 4; i++) { - sel25519(p[i], q[i], b); - } - } - - function pack(r, p) { - var tx = gf(), ty = gf(), zi = gf(); - inv25519(zi, p[2]); - M(tx, p[0], zi); - M(ty, p[1], zi); - pack25519(r, ty); - r[31] ^= par25519(tx) << 7; - } - - function scalarmult(p, q, s) { - var b, i; - set25519(p[0], gf0); - set25519(p[1], gf1); - set25519(p[2], gf1); - set25519(p[3], gf0); - for (i = 255; i >= 0; --i) { - b = (s[(i/8)|0] >> (i&7)) & 1; - cswap(p, q, b); - add(q, p); - add(p, p); - cswap(p, q, b); - } - } - - function scalarbase(p, s) { - var q = [gf(), gf(), gf(), gf()]; - set25519(q[0], X); - set25519(q[1], Y); - set25519(q[2], gf1); - M(q[3], X, Y); - scalarmult(p, q, s); - } - - function crypto_sign_keypair(pk, sk, seeded) { - var d; - var p = [gf(), gf(), gf(), gf()]; - var i; - - if (!seeded) randombytes(sk, 32); - d = nacl.hash(sk.subarray(0, 32)); - d[0] &= 248; - d[31] &= 127; - d[31] |= 64; - - scalarbase(p, d); - pack(pk, p); - - for (i = 0; i < 32; i++) sk[i+32] = pk[i]; - return 0; - } - - var L = new Float64Array([0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10]); - - function modL(r, x) { - var carry, i, j, k; - for (i = 63; i >= 32; --i) { - carry = 0; - for (j = i - 32, k = i - 12; j < k; ++j) { - x[j] += carry - 16 * x[i] * L[j - (i - 32)]; - carry = Math.floor((x[j] + 128) / 256); - x[j] -= carry * 256; - } - x[j] += carry; - x[i] = 0; - } - carry = 0; - for (j = 0; j < 32; j++) { - x[j] += carry - (x[31] >> 4) * L[j]; - carry = x[j] >> 8; - x[j] &= 255; - } - for (j = 0; j < 32; j++) x[j] -= carry * L[j]; - for (i = 0; i < 32; i++) { - x[i+1] += x[i] >> 8; - r[i] = x[i] & 255; - } - } - - function reduce(r) { - var x = new Float64Array(64), i; - for (i = 0; i < 64; i++) x[i] = r[i]; - for (i = 0; i < 64; i++) r[i] = 0; - modL(r, x); - } - - // Note: difference from C - smlen returned, not passed as argument. - function crypto_sign(sm, m, n, sk) { - var d, h, r; - var i, j, x = new Float64Array(64); - var p = [gf(), gf(), gf(), gf()]; - - d = nacl.hash(sk.subarray(0, 32)); - d[0] &= 248; - d[31] &= 127; - d[31] |= 64; - - var smlen = n + 64; - for (i = 0; i < n; i++) sm[64 + i] = m[i]; - for (i = 0; i < 32; i++) sm[32 + i] = d[32 + i]; - - r = nacl.hash(sm.subarray(32, smlen)); - reduce(r); - scalarbase(p, r); - pack(sm, p); - - for (i = 32; i < 64; i++) sm[i] = sk[i]; - h = nacl.hash(sm.subarray(0, smlen)); - reduce(h); - - for (i = 0; i < 64; i++) x[i] = 0; - for (i = 0; i < 32; i++) x[i] = r[i]; - for (i = 0; i < 32; i++) { - for (j = 0; j < 32; j++) { - x[i+j] += h[i] * d[j]; - } - } - - modL(sm.subarray(32), x); - return smlen; - } - - function unpackneg(r, p) { - var t = gf(), chk = gf(), num = gf(), - den = gf(), den2 = gf(), den4 = gf(), - den6 = gf(); - - set25519(r[2], gf1); - unpack25519(r[1], p); - S(num, r[1]); - M(den, num, D); - Z(num, num, r[2]); - A(den, r[2], den); - - S(den2, den); - S(den4, den2); - M(den6, den4, den2); - M(t, den6, num); - M(t, t, den); - - pow2523(t, t); - M(t, t, num); - M(t, t, den); - M(t, t, den); - M(r[0], t, den); - - S(chk, r[0]); - M(chk, chk, den); - if (neq25519(chk, num)) M(r[0], r[0], I); - - S(chk, r[0]); - M(chk, chk, den); - if (neq25519(chk, num)) return -1; - - if (par25519(r[0]) === (p[31]>>7)) Z(r[0], gf0, r[0]); - - M(r[3], r[0], r[1]); - return 0; - } - - function crypto_sign_open(m, sm, n, pk) { - var i; - var t = new Uint8Array(32), h; - var p = [gf(), gf(), gf(), gf()], - q = [gf(), gf(), gf(), gf()]; - - if (n < 64) return -1; - - if (unpackneg(q, pk)) return -1; - - for (i = 0; i < n; i++) m[i] = sm[i]; - for (i = 0; i < 32; i++) m[i+32] = pk[i]; - h = nacl.hash(m.subarray(0, n)); - reduce(h); - scalarmult(p, q, h); - - scalarbase(q, sm.subarray(32)); - add(p, q); - pack(t, p); - - n -= 64; - if (crypto_verify_32(sm, 0, t, 0)) { - for (i = 0; i < n; i++) m[i] = 0; - return -1; - } - - for (i = 0; i < n; i++) m[i] = sm[i + 64]; - return n; - } - - var crypto_scalarmult_BYTES = 32, - crypto_scalarmult_SCALARBYTES = 32, - crypto_box_PUBLICKEYBYTES = 32, - crypto_box_SECRETKEYBYTES = 32, - crypto_sign_BYTES = 64, - crypto_sign_PUBLICKEYBYTES = 32, - crypto_sign_SECRETKEYBYTES = 64, - crypto_sign_SEEDBYTES = 32; - - function checkArrayTypes() { - for (var i = 0; i < arguments.length; i++) { - if (!(arguments[i] instanceof Uint8Array)) - throw new TypeError('unexpected type, use Uint8Array'); - } - } - - function cleanup(arr) { - for (var i = 0; i < arr.length; i++) arr[i] = 0; - } - - nacl.scalarMult = function(n, p) { - checkArrayTypes(n, p); - if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error('bad n size'); - if (p.length !== crypto_scalarmult_BYTES) throw new Error('bad p size'); - var q = new Uint8Array(crypto_scalarmult_BYTES); - crypto_scalarmult(q, n, p); - return q; - }; - - nacl.box = {}; - - nacl.box.keyPair = function() { - var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); - var sk = new Uint8Array(crypto_box_SECRETKEYBYTES); - crypto_box_keypair(pk, sk); - return {publicKey: pk, secretKey: sk}; - }; - - nacl.box.keyPair.fromSecretKey = function(secretKey) { - checkArrayTypes(secretKey); - if (secretKey.length !== crypto_box_SECRETKEYBYTES) - throw new Error('bad secret key size'); - var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); - crypto_scalarmult_base(pk, secretKey); - return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; - }; - - nacl.sign = function(msg, secretKey) { - checkArrayTypes(msg, secretKey); - if (secretKey.length !== crypto_sign_SECRETKEYBYTES) - throw new Error('bad secret key size'); - var signedMsg = new Uint8Array(crypto_sign_BYTES+msg.length); - crypto_sign(signedMsg, msg, msg.length, secretKey); - return signedMsg; - }; - - nacl.sign.detached = function(msg, secretKey) { - var signedMsg = nacl.sign(msg, secretKey); - var sig = new Uint8Array(crypto_sign_BYTES); - for (var i = 0; i < sig.length; i++) sig[i] = signedMsg[i]; - return sig; - }; - - nacl.sign.detached.verify = function(msg, sig, publicKey) { - checkArrayTypes(msg, sig, publicKey); - if (sig.length !== crypto_sign_BYTES) - throw new Error('bad signature size'); - if (publicKey.length !== crypto_sign_PUBLICKEYBYTES) - throw new Error('bad public key size'); - var sm = new Uint8Array(crypto_sign_BYTES + msg.length); - var m = new Uint8Array(crypto_sign_BYTES + msg.length); - var i; - for (i = 0; i < crypto_sign_BYTES; i++) sm[i] = sig[i]; - for (i = 0; i < msg.length; i++) sm[i+crypto_sign_BYTES] = msg[i]; - return (crypto_sign_open(m, sm, sm.length, publicKey) >= 0); - }; - - nacl.sign.keyPair = function() { - var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); - var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); - crypto_sign_keypair(pk, sk); - return {publicKey: pk, secretKey: sk}; - }; - - nacl.sign.keyPair.fromSecretKey = function(secretKey) { - checkArrayTypes(secretKey); - if (secretKey.length !== crypto_sign_SECRETKEYBYTES) - throw new Error('bad secret key size'); - var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); - for (var i = 0; i < pk.length; i++) pk[i] = secretKey[32+i]; - return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; - }; - - nacl.sign.keyPair.fromSeed = function(seed) { - checkArrayTypes(seed); - if (seed.length !== crypto_sign_SEEDBYTES) - throw new Error('bad seed size'); - var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); - var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); - for (var i = 0; i < 32; i++) sk[i] = seed[i]; - crypto_sign_keypair(pk, sk, true); - return {publicKey: pk, secretKey: sk}; - }; - - nacl.setPRNG = function(fn) { - randombytes = fn; - }; - - (function() { - // Initialize PRNG if environment provides CSPRNG. - // If not, methods calling randombytes will throw. - var crypto = typeof self !== 'undefined' ? (self.crypto || self.msCrypto) : null; - if (crypto && crypto.getRandomValues) { - // Browsers. - var QUOTA = 65536; - nacl.setPRNG(function(x, n) { - var i, v = new Uint8Array(n); - for (i = 0; i < n; i += QUOTA) { - crypto.getRandomValues(v.subarray(i, i + Math.min(n - i, QUOTA))); - } - for (i = 0; i < n; i++) x[i] = v[i]; - cleanup(v); - }); - } else if (typeof commonjsRequire !== 'undefined') { - // Node.js. - crypto = void('crypto'); - if (crypto && crypto.randomBytes) { - nacl.setPRNG(function(x, n) { - var i, v = crypto.randomBytes(n); - for (i = 0; i < n; i++) x[i] = v[i]; - cleanup(v); - }); - } - } - })(); - - })(module.exports ? module.exports : (self.nacl = self.nacl || {})); - }); - - // GPG4Browsers - An OpenPGP implementation in javascript - - const nodeCrypto$5 = util.getNodeCrypto(); - - /** - * Buffer for secure random numbers - */ - class RandomBuffer { - constructor() { - this.buffer = null; - this.size = null; - this.callback = null; - } - - /** - * Initialize buffer - * @param {Integer} size - size of buffer - */ - init(size, callback) { - this.buffer = new Uint8Array(size); - this.size = 0; - this.callback = callback; - } - - /** - * Concat array of secure random numbers to buffer - * @param {Uint8Array} buf - */ - set(buf) { - if (!this.buffer) { - throw new Error('RandomBuffer is not initialized'); - } - if (!(buf instanceof Uint8Array)) { - throw new Error('Invalid type: buf not an Uint8Array'); - } - const freeSpace = this.buffer.length - this.size; - if (buf.length > freeSpace) { - buf = buf.subarray(0, freeSpace); - } - // set buf with offset old size of buffer - this.buffer.set(buf, this.size); - this.size += buf.length; - } - - /** - * Take numbers out of buffer and copy to array - * @param {Uint8Array} buf - The destination array - */ - async get(buf) { - if (!this.buffer) { - throw new Error('RandomBuffer is not initialized'); - } - if (!(buf instanceof Uint8Array)) { - throw new Error('Invalid type: buf not an Uint8Array'); - } - if (this.size < buf.length) { - if (!this.callback) { - throw new Error('Random number buffer depleted'); - } - // Wait for random bytes from main context, then try again - await this.callback(); - return this.get(buf); - } - for (let i = 0; i < buf.length; i++) { - buf[i] = this.buffer[--this.size]; - // clear buffer value - this.buffer[this.size] = 0; - } - } - } - - /** - * Retrieve secure random byte array of the specified length - * @param {Integer} length - Length in bytes to generate - * @returns {Promise} Random byte array. - * @async - */ - async function getRandomBytes(length) { - const buf = new Uint8Array(length); - if (typeof crypto !== 'undefined' && crypto.getRandomValues) { - crypto.getRandomValues(buf); - } else if (nodeCrypto$5) { - const bytes = nodeCrypto$5.randomBytes(buf.length); - buf.set(bytes); - } else if (randomBuffer.buffer) { - await randomBuffer.get(buf); - } else { - throw new Error('No secure random number generator available.'); - } - return buf; - } - - /** - * Create a secure random BigInteger that is greater than or equal to min and less than max. - * @param {module:BigInteger} min - Lower bound, included - * @param {module:BigInteger} max - Upper bound, excluded - * @returns {Promise} Random BigInteger. - * @async - */ - async function getRandomBigInteger(min, max) { - const BigInteger = await util.getBigInteger(); - - if (max.lt(min)) { - throw new Error('Illegal parameter value: max <= min'); - } - - const modulus = max.sub(min); - const bytes = modulus.byteLength(); - - // Using a while loop is necessary to avoid bias introduced by the mod operation. - // However, we request 64 extra random bits so that the bias is negligible. - // Section B.1.1 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - const r = new BigInteger(await getRandomBytes(bytes + 8)); - return r.mod(modulus).add(min); - } - - const randomBuffer = new RandomBuffer(); - - var random = /*#__PURE__*/Object.freeze({ - __proto__: null, - getRandomBytes: getRandomBytes, - getRandomBigInteger: getRandomBigInteger, - randomBuffer: randomBuffer - }); - - // OpenPGP.js - An OpenPGP implementation in javascript - - /** - * Generate a probably prime random number - * @param {Integer} bits - Bit length of the prime - * @param {BigInteger} e - Optional RSA exponent to check against the prime - * @param {Integer} k - Optional number of iterations of Miller-Rabin test - * @returns BigInteger - * @async - */ - async function randomProbablePrime(bits, e, k) { - const BigInteger = await util.getBigInteger(); - const one = new BigInteger(1); - const min = one.leftShift(new BigInteger(bits - 1)); - const thirty = new BigInteger(30); - /* - * We can avoid any multiples of 3 and 5 by looking at n mod 30 - * n mod 30 = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 - * the next possible prime is mod 30: - * 1 7 7 7 7 7 7 11 11 11 11 13 13 17 17 17 17 19 19 23 23 23 23 29 29 29 29 29 29 1 - */ - const adds = [1, 6, 5, 4, 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, 3, 2, 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1, 2]; - - const n = await getRandomBigInteger(min, min.leftShift(one)); - let i = n.mod(thirty).toNumber(); - - do { - n.iadd(new BigInteger(adds[i])); - i = (i + adds[i]) % adds.length; - // If reached the maximum, go back to the minimum. - if (n.bitLength() > bits) { - n.imod(min.leftShift(one)).iadd(min); - i = n.mod(thirty).toNumber(); - } - } while (!await isProbablePrime(n, e, k)); - return n; - } - - /** - * Probabilistic primality testing - * @param {BigInteger} n - Number to test - * @param {BigInteger} e - Optional RSA exponent to check against the prime - * @param {Integer} k - Optional number of iterations of Miller-Rabin test - * @returns {boolean} - * @async - */ - async function isProbablePrime(n, e, k) { - if (e && !n.dec().gcd(e).isOne()) { - return false; - } - if (!await divisionTest(n)) { - return false; - } - if (!await fermat(n)) { - return false; - } - if (!await millerRabin(n, k)) { - return false; - } - // TODO implement the Lucas test - // See Section C.3.3 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - return true; - } - - /** - * Tests whether n is probably prime or not using Fermat's test with b = 2. - * Fails if b^(n-1) mod n != 1. - * @param {BigInteger} n - Number to test - * @param {BigInteger} b - Optional Fermat test base - * @returns {boolean} - */ - async function fermat(n, b) { - const BigInteger = await util.getBigInteger(); - b = b || new BigInteger(2); - return b.modExp(n.dec(), n).isOne(); - } - - async function divisionTest(n) { - const BigInteger = await util.getBigInteger(); - return smallPrimes.every(m => { - return n.mod(new BigInteger(m)) !== 0; - }); - } - - // https://github.com/gpg/libgcrypt/blob/master/cipher/primegen.c - const smallPrimes = [ - 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, - 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, - 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, - 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, - 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, - 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, - 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, - 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, - 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, - 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, - 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, - 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, - 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, - 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, - 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, - 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, - 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, - 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, - 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, - 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, - 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, - 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, - 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, - 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, - 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, - 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, - 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, - 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, - 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, - 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, - 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, - 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, - 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, - 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, - 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, - 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, - 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, - 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, - 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, - 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, - 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, - 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, - 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, - 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, - 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, - 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, - 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, - 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, - 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, - 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, - 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, - 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, - 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, - 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, - 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, - 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, - 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, - 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, - 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, - 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, - 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, - 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, - 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, - 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, - 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, - 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, - 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, - 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, - 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, - 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, - 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457, - 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, - 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, - 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, - 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, - 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, - 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, - 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, - 4957, 4967, 4969, 4973, 4987, 4993, 4999 - ]; - - - // Miller-Rabin - Miller Rabin algorithm for primality test - // Copyright Fedor Indutny, 2014. - // - // This software is licensed under the MIT License. - // - // Permission is hereby granted, free of charge, to any person obtaining a - // copy of this software and associated documentation files (the - // "Software"), to deal in the Software without restriction, including - // without limitation the rights to use, copy, modify, merge, publish, - // distribute, sublicense, and/or sell copies of the Software, and to permit - // persons to whom the Software is furnished to do so, subject to the - // following conditions: - // - // The above copyright notice and this permission notice shall be included - // in all copies or substantial portions of the Software. - // - // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - // USE OR OTHER DEALINGS IN THE SOFTWARE. - - // Adapted on Jan 2018 from version 4.0.1 at https://github.com/indutny/miller-rabin - - // Sample syntax for Fixed-Base Miller-Rabin: - // millerRabin(n, k, () => new BN(small_primes[Math.random() * small_primes.length | 0])) - - /** - * Tests whether n is probably prime or not using the Miller-Rabin test. - * See HAC Remark 4.28. - * @param {BigInteger} n - Number to test - * @param {Integer} k - Optional number of iterations of Miller-Rabin test - * @param {Function} rand - Optional function to generate potential witnesses - * @returns {boolean} - * @async - */ - async function millerRabin(n, k, rand) { - const BigInteger = await util.getBigInteger(); - const len = n.bitLength(); - - if (!k) { - k = Math.max(1, (len / 48) | 0); - } - - const n1 = n.dec(); // n - 1 - - // Find d and s, (n - 1) = (2 ^ s) * d; - let s = 0; - while (!n1.getBit(s)) { s++; } - const d = n.rightShift(new BigInteger(s)); - - for (; k > 0; k--) { - const a = rand ? rand() : await getRandomBigInteger(new BigInteger(2), n1); - - let x = a.modExp(d, n); - if (x.isOne() || x.equal(n1)) { - continue; - } - - let i; - for (i = 1; i < s; i++) { - x = x.mul(x).mod(n); - - if (x.isOne()) { - return false; - } - if (x.equal(n1)) { - break; - } - } - - if (i === s) { - return false; - } - } - - return true; - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - /** - * ASN1 object identifiers for hashes - * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.2} - */ - const hash_headers = []; - hash_headers[1] = [0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, - 0x10]; - hash_headers[2] = [0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14]; - hash_headers[3] = [0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14]; - hash_headers[8] = [0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, - 0x04, 0x20]; - hash_headers[9] = [0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, - 0x04, 0x30]; - hash_headers[10] = [0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, - 0x00, 0x04, 0x40]; - hash_headers[11] = [0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, - 0x00, 0x04, 0x1C]; - - /** - * Create padding with secure random data - * @private - * @param {Integer} length - Length of the padding in bytes - * @returns {Promise} Random padding. - * @async - */ - async function getPKCS1Padding(length) { - const result = new Uint8Array(length); - let count = 0; - while (count < length) { - const randomBytes = await getRandomBytes(length - count); - for (let i = 0; i < randomBytes.length; i++) { - if (randomBytes[i] !== 0) { - result[count++] = randomBytes[i]; - } - } - } - return result; - } - - /** - * Create a EME-PKCS1-v1_5 padded message - * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.1|RFC 4880 13.1.1} - * @param {Uint8Array} message - Message to be encoded - * @param {Integer} keyLength - The length in octets of the key modulus - * @returns {Promise} EME-PKCS1 padded message. - * @async - */ - async function emeEncode(message, keyLength) { - const mLength = message.length; - // length checking - if (mLength > keyLength - 11) { - throw new Error('Message too long'); - } - // Generate an octet string PS of length k - mLen - 3 consisting of - // pseudo-randomly generated nonzero octets - const PS = await getPKCS1Padding(keyLength - mLength - 3); - // Concatenate PS, the message M, and other padding to form an - // encoded message EM of length k octets as EM = 0x00 || 0x02 || PS || 0x00 || M. - const encoded = new Uint8Array(keyLength); - // 0x00 byte - encoded[1] = 2; - encoded.set(PS, 2); - // 0x00 bytes - encoded.set(message, keyLength - mLength); - return encoded; - } - - /** - * Decode a EME-PKCS1-v1_5 padded message - * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.2|RFC 4880 13.1.2} - * @param {Uint8Array} encoded - Encoded message bytes - * @param {Uint8Array} randomPayload - Data to return in case of decoding error (needed for constant-time processing) - * @returns {Uint8Array} decoded data or `randomPayload` (on error, if given) - * @throws {Error} on decoding failure, unless `randomPayload` is provided - */ - function emeDecode(encoded, randomPayload) { - // encoded format: 0x00 0x02 0x00 - let offset = 2; - let separatorNotFound = 1; - for (let j = offset; j < encoded.length; j++) { - separatorNotFound &= encoded[j] !== 0; - offset += separatorNotFound; - } - - const psLen = offset - 2; - const payload = encoded.subarray(offset + 1); // discard the 0x00 separator - const isValidPadding = encoded[0] === 0 & encoded[1] === 2 & psLen >= 8 & !separatorNotFound; - - if (randomPayload) { - return util.selectUint8Array(isValidPadding, payload, randomPayload); - } - - if (isValidPadding) { - return payload; - } - - throw new Error('Decryption error'); - } - - /** - * Create a EMSA-PKCS1-v1_5 padded message - * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.3|RFC 4880 13.1.3} - * @param {Integer} algo - Hash algorithm type used - * @param {Uint8Array} hashed - Message to be encoded - * @param {Integer} emLen - Intended length in octets of the encoded message - * @returns {Uint8Array} Encoded message. - */ - async function emsaEncode(algo, hashed, emLen) { - let i; - if (hashed.length !== hash.getHashByteLength(algo)) { - throw new Error('Invalid hash length'); - } - // produce an ASN.1 DER value for the hash function used. - // Let T be the full hash prefix - const hashPrefix = new Uint8Array(hash_headers[algo].length); - for (i = 0; i < hash_headers[algo].length; i++) { - hashPrefix[i] = hash_headers[algo][i]; - } - // and let tLen be the length in octets prefix and hashed data - const tLen = hashPrefix.length + hashed.length; - if (emLen < tLen + 11) { - throw new Error('Intended encoded message length too short'); - } - // an octet string PS consisting of emLen - tLen - 3 octets with hexadecimal value 0xFF - // The length of PS will be at least 8 octets - const PS = new Uint8Array(emLen - tLen - 3).fill(0xff); - - // Concatenate PS, the hash prefix, hashed data, and other padding to form the - // encoded message EM as EM = 0x00 || 0x01 || PS || 0x00 || prefix || hashed - const EM = new Uint8Array(emLen); - EM[1] = 0x01; - EM.set(PS, 2); - EM.set(hashPrefix, emLen - tLen); - EM.set(hashed, emLen - hashed.length); - return EM; - } - - var pkcs1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - emeEncode: emeEncode, - emeDecode: emeDecode, - emsaEncode: emsaEncode - }); - - // GPG4Browsers - An OpenPGP implementation in javascript - - const webCrypto$5 = util.getWebCrypto(); - const nodeCrypto$6 = util.getNodeCrypto(); - const asn1 = nodeCrypto$6 ? void('asn1.js') : undefined; - - /* eslint-disable no-invalid-this */ - const RSAPrivateKey = util.detectNode() ? asn1.define('RSAPrivateKey', function () { - this.seq().obj( // used for native NodeJS crypto - this.key('version').int(), // 0 - this.key('modulus').int(), // n - this.key('publicExponent').int(), // e - this.key('privateExponent').int(), // d - this.key('prime1').int(), // p - this.key('prime2').int(), // q - this.key('exponent1').int(), // dp - this.key('exponent2').int(), // dq - this.key('coefficient').int() // u - ); - }) : undefined; - - const RSAPublicKey = util.detectNode() ? asn1.define('RSAPubliceKey', function () { - this.seq().obj( // used for native NodeJS crypto - this.key('modulus').int(), // n - this.key('publicExponent').int(), // e - ); - }) : undefined; - /* eslint-enable no-invalid-this */ - - /** Create signature - * @param {module:enums.hash} hashAlgo - Hash algorithm - * @param {Uint8Array} data - Message - * @param {Uint8Array} n - RSA public modulus - * @param {Uint8Array} e - RSA public exponent - * @param {Uint8Array} d - RSA private exponent - * @param {Uint8Array} p - RSA private prime p - * @param {Uint8Array} q - RSA private prime q - * @param {Uint8Array} u - RSA private coefficient - * @param {Uint8Array} hashed - Hashed message - * @returns {Promise} RSA Signature. - * @async - */ - async function sign(hashAlgo, data, n, e, d, p, q, u, hashed) { - if (data && !util.isStream(data)) { - if (util.getWebCrypto()) { - try { - return await webSign(enums.read(enums.webHash, hashAlgo), data, n, e, d, p, q, u); - } catch (err) { - util.printDebugError(err); - } - } else if (util.getNodeCrypto()) { - return nodeSign(hashAlgo, data, n, e, d, p, q, u); - } - } - return bnSign(hashAlgo, n, d, hashed); - } - - /** - * Verify signature - * @param {module:enums.hash} hashAlgo - Hash algorithm - * @param {Uint8Array} data - Message - * @param {Uint8Array} s - Signature - * @param {Uint8Array} n - RSA public modulus - * @param {Uint8Array} e - RSA public exponent - * @param {Uint8Array} hashed - Hashed message - * @returns {Boolean} - * @async - */ - async function verify(hashAlgo, data, s, n, e, hashed) { - if (data && !util.isStream(data)) { - if (util.getWebCrypto()) { - try { - return await webVerify(enums.read(enums.webHash, hashAlgo), data, s, n, e); - } catch (err) { - util.printDebugError(err); - } - } else if (util.getNodeCrypto()) { - return nodeVerify(hashAlgo, data, s, n, e); - } - } - return bnVerify(hashAlgo, s, n, e, hashed); - } - - /** - * Encrypt message - * @param {Uint8Array} data - Message - * @param {Uint8Array} n - RSA public modulus - * @param {Uint8Array} e - RSA public exponent - * @returns {Promise} RSA Ciphertext. - * @async - */ - async function encrypt$1(data, n, e) { - if (util.getNodeCrypto()) { - return nodeEncrypt$1(data, n, e); - } - return bnEncrypt(data, n, e); - } - - /** - * Decrypt RSA message - * @param {Uint8Array} m - Message - * @param {Uint8Array} n - RSA public modulus - * @param {Uint8Array} e - RSA public exponent - * @param {Uint8Array} d - RSA private exponent - * @param {Uint8Array} p - RSA private prime p - * @param {Uint8Array} q - RSA private prime q - * @param {Uint8Array} u - RSA private coefficient - * @param {Uint8Array} randomPayload - Data to return on decryption error, instead of throwing - * (needed for constant-time processing) - * @returns {Promise} RSA Plaintext. - * @throws {Error} on decryption error, unless `randomPayload` is given - * @async - */ - async function decrypt$1(data, n, e, d, p, q, u, randomPayload) { - if (util.getNodeCrypto()) { - return nodeDecrypt$1(data, n, e, d, p, q, u, randomPayload); - } - return bnDecrypt(data, n, e, d, p, q, u, randomPayload); - } - - /** - * Generate a new random private key B bits long with public exponent E. - * - * When possible, webCrypto or nodeCrypto is used. Otherwise, primes are generated using - * 40 rounds of the Miller-Rabin probabilistic random prime generation algorithm. - * @see module:crypto/public_key/prime - * @param {Integer} bits - RSA bit length - * @param {Integer} e - RSA public exponent - * @returns {{n, e, d, - * p, q ,u: Uint8Array}} RSA public modulus, RSA public exponent, RSA private exponent, - * RSA private prime p, RSA private prime q, u = p ** -1 mod q - * @async - */ - async function generate(bits, e) { - const BigInteger = await util.getBigInteger(); - - e = new BigInteger(e); - - // Native RSA keygen using Web Crypto - if (util.getWebCrypto()) { - const keyGenOpt = { - name: 'RSASSA-PKCS1-v1_5', - modulusLength: bits, // the specified keysize in bits - publicExponent: e.toUint8Array(), // take three bytes (max 65537) for exponent - hash: { - name: 'SHA-1' // not required for actual RSA keys, but for crypto api 'sign' and 'verify' - } - }; - const keyPair = await webCrypto$5.generateKey(keyGenOpt, true, ['sign', 'verify']); - - // export the generated keys as JsonWebKey (JWK) - // https://tools.ietf.org/html/draft-ietf-jose-json-web-key-33 - const jwk = await webCrypto$5.exportKey('jwk', keyPair.privateKey); - // map JWK parameters to corresponding OpenPGP names - return { - n: b64ToUint8Array(jwk.n), - e: e.toUint8Array(), - d: b64ToUint8Array(jwk.d), - // switch p and q - p: b64ToUint8Array(jwk.q), - q: b64ToUint8Array(jwk.p), - // Since p and q are switched in places, u is the inverse of jwk.q - u: b64ToUint8Array(jwk.qi) - }; - } else if (util.getNodeCrypto() && nodeCrypto$6.generateKeyPair && RSAPrivateKey) { - const opts = { - modulusLength: bits, - publicExponent: e.toNumber(), - publicKeyEncoding: { type: 'pkcs1', format: 'der' }, - privateKeyEncoding: { type: 'pkcs1', format: 'der' } - }; - const prv = await new Promise((resolve, reject) => nodeCrypto$6.generateKeyPair('rsa', opts, (err, _, der) => { - if (err) { - reject(err); - } else { - resolve(RSAPrivateKey.decode(der, 'der')); - } - })); - /** - * OpenPGP spec differs from DER spec, DER: `u = (inverse of q) mod p`, OpenPGP: `u = (inverse of p) mod q`. - * @link https://tools.ietf.org/html/rfc3447#section-3.2 - * @link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-08#section-5.6.1 - */ - return { - n: prv.modulus.toArrayLike(Uint8Array), - e: prv.publicExponent.toArrayLike(Uint8Array), - d: prv.privateExponent.toArrayLike(Uint8Array), - // switch p and q - p: prv.prime2.toArrayLike(Uint8Array), - q: prv.prime1.toArrayLike(Uint8Array), - // Since p and q are switched in places, we can keep u as defined by DER - u: prv.coefficient.toArrayLike(Uint8Array) - }; - } - - // RSA keygen fallback using 40 iterations of the Miller-Rabin test - // See https://stackoverflow.com/a/6330138 for justification - // Also see section C.3 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST - let p; - let q; - let n; - do { - q = await randomProbablePrime(bits - (bits >> 1), e, 40); - p = await randomProbablePrime(bits >> 1, e, 40); - n = p.mul(q); - } while (n.bitLength() !== bits); - - const phi = p.dec().imul(q.dec()); - - if (q.lt(p)) { - [p, q] = [q, p]; - } - - return { - n: n.toUint8Array(), - e: e.toUint8Array(), - d: e.modInv(phi).toUint8Array(), - p: p.toUint8Array(), - q: q.toUint8Array(), - // dp: d.mod(p.subn(1)), - // dq: d.mod(q.subn(1)), - u: p.modInv(q).toUint8Array() - }; - } - - /** - * Validate RSA parameters - * @param {Uint8Array} n - RSA public modulus - * @param {Uint8Array} e - RSA public exponent - * @param {Uint8Array} d - RSA private exponent - * @param {Uint8Array} p - RSA private prime p - * @param {Uint8Array} q - RSA private prime q - * @param {Uint8Array} u - RSA inverse of p w.r.t. q - * @returns {Promise} Whether params are valid. - * @async - */ - async function validateParams(n, e, d, p, q, u) { - const BigInteger = await util.getBigInteger(); - n = new BigInteger(n); - p = new BigInteger(p); - q = new BigInteger(q); - - // expect pq = n - if (!p.mul(q).equal(n)) { - return false; - } - - const two = new BigInteger(2); - // expect p*u = 1 mod q - u = new BigInteger(u); - if (!p.mul(u).mod(q).isOne()) { - return false; - } - - e = new BigInteger(e); - d = new BigInteger(d); - /** - * In RSA pkcs#1 the exponents (d, e) are inverses modulo lcm(p-1, q-1) - * We check that [de = 1 mod (p-1)] and [de = 1 mod (q-1)] - * By CRT on coprime factors of (p-1, q-1) it follows that [de = 1 mod lcm(p-1, q-1)] - * - * We blind the multiplication with r, and check that rde = r mod lcm(p-1, q-1) - */ - const nSizeOver3 = new BigInteger(Math.floor(n.bitLength() / 3)); - const r = await getRandomBigInteger(two, two.leftShift(nSizeOver3)); // r in [ 2, 2^{|n|/3} ) < p and q - const rde = r.mul(d).mul(e); - - const areInverses = rde.mod(p.dec()).equal(r) && rde.mod(q.dec()).equal(r); - if (!areInverses) { - return false; - } - - return true; - } - - async function bnSign(hashAlgo, n, d, hashed) { - const BigInteger = await util.getBigInteger(); - n = new BigInteger(n); - const m = new BigInteger(await emsaEncode(hashAlgo, hashed, n.byteLength())); - d = new BigInteger(d); - if (m.gte(n)) { - throw new Error('Message size cannot exceed modulus size'); - } - return m.modExp(d, n).toUint8Array('be', n.byteLength()); - } - - async function webSign(hashName, data, n, e, d, p, q, u) { - /** OpenPGP keys require that p < q, and Safari Web Crypto requires that p > q. - * We swap them in privateToJWK, so it usually works out, but nevertheless, - * not all OpenPGP keys are compatible with this requirement. - * OpenPGP.js used to generate RSA keys the wrong way around (p > q), and still - * does if the underlying Web Crypto does so (e.g. old MS Edge 50% of the time). - */ - const jwk = await privateToJWK(n, e, d, p, q, u); - const algo = { - name: 'RSASSA-PKCS1-v1_5', - hash: { name: hashName } - }; - const key = await webCrypto$5.importKey('jwk', jwk, algo, false, ['sign']); - // add hash field for ms edge support - return new Uint8Array(await webCrypto$5.sign({ 'name': 'RSASSA-PKCS1-v1_5', 'hash': hashName }, key, data)); - } - - async function nodeSign(hashAlgo, data, n, e, d, p, q, u) { - const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); - const pBNum = new BN(p); - const qBNum = new BN(q); - const dBNum = new BN(d); - const dq = dBNum.mod(qBNum.subn(1)); // d mod (q-1) - const dp = dBNum.mod(pBNum.subn(1)); // d mod (p-1) - const sign = nodeCrypto$6.createSign(enums.read(enums.hash, hashAlgo)); - sign.write(data); - sign.end(); - const keyObject = { - version: 0, - modulus: new BN(n), - publicExponent: new BN(e), - privateExponent: new BN(d), - // switch p and q - prime1: new BN(q), - prime2: new BN(p), - // switch dp and dq - exponent1: dq, - exponent2: dp, - coefficient: new BN(u) - }; - if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { //from version 11.6.0 Node supports der encoded key objects - const der = RSAPrivateKey.encode(keyObject, 'der'); - return new Uint8Array(sign.sign({ key: der, format: 'der', type: 'pkcs1' })); - } - const pem = RSAPrivateKey.encode(keyObject, 'pem', { - label: 'RSA PRIVATE KEY' - }); - return new Uint8Array(sign.sign(pem)); - } - - async function bnVerify(hashAlgo, s, n, e, hashed) { - const BigInteger = await util.getBigInteger(); - n = new BigInteger(n); - s = new BigInteger(s); - e = new BigInteger(e); - if (s.gte(n)) { - throw new Error('Signature size cannot exceed modulus size'); - } - const EM1 = s.modExp(e, n).toUint8Array('be', n.byteLength()); - const EM2 = await emsaEncode(hashAlgo, hashed, n.byteLength()); - return util.equalsUint8Array(EM1, EM2); - } - - async function webVerify(hashName, data, s, n, e) { - const jwk = publicToJWK(n, e); - const key = await webCrypto$5.importKey('jwk', jwk, { - name: 'RSASSA-PKCS1-v1_5', - hash: { name: hashName } - }, false, ['verify']); - // add hash field for ms edge support - return webCrypto$5.verify({ 'name': 'RSASSA-PKCS1-v1_5', 'hash': hashName }, key, s, data); - } - - async function nodeVerify(hashAlgo, data, s, n, e) { - const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); - - const verify = nodeCrypto$6.createVerify(enums.read(enums.hash, hashAlgo)); - verify.write(data); - verify.end(); - const keyObject = { - modulus: new BN(n), - publicExponent: new BN(e) - }; - let key; - if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { //from version 11.6.0 Node supports der encoded key objects - const der = RSAPublicKey.encode(keyObject, 'der'); - key = { key: der, format: 'der', type: 'pkcs1' }; - } else { - key = RSAPublicKey.encode(keyObject, 'pem', { - label: 'RSA PUBLIC KEY' - }); - } - try { - return await verify.verify(key, s); - } catch (err) { - return false; - } - } - - async function nodeEncrypt$1(data, n, e) { - const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); - - const keyObject = { - modulus: new BN(n), - publicExponent: new BN(e) - }; - let key; - if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { - const der = RSAPublicKey.encode(keyObject, 'der'); - key = { key: der, format: 'der', type: 'pkcs1', padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; - } else { - const pem = RSAPublicKey.encode(keyObject, 'pem', { - label: 'RSA PUBLIC KEY' - }); - key = { key: pem, padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; - } - return new Uint8Array(nodeCrypto$6.publicEncrypt(key, data)); - } - - async function bnEncrypt(data, n, e) { - const BigInteger = await util.getBigInteger(); - n = new BigInteger(n); - data = new BigInteger(await emeEncode(data, n.byteLength())); - e = new BigInteger(e); - if (data.gte(n)) { - throw new Error('Message size cannot exceed modulus size'); - } - return data.modExp(e, n).toUint8Array('be', n.byteLength()); - } - - async function nodeDecrypt$1(data, n, e, d, p, q, u, randomPayload) { - const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); - - const pBNum = new BN(p); - const qBNum = new BN(q); - const dBNum = new BN(d); - const dq = dBNum.mod(qBNum.subn(1)); // d mod (q-1) - const dp = dBNum.mod(pBNum.subn(1)); // d mod (p-1) - const keyObject = { - version: 0, - modulus: new BN(n), - publicExponent: new BN(e), - privateExponent: new BN(d), - // switch p and q - prime1: new BN(q), - prime2: new BN(p), - // switch dp and dq - exponent1: dq, - exponent2: dp, - coefficient: new BN(u) - }; - let key; - if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { - const der = RSAPrivateKey.encode(keyObject, 'der'); - key = { key: der, format: 'der' , type: 'pkcs1', padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; - } else { - const pem = RSAPrivateKey.encode(keyObject, 'pem', { - label: 'RSA PRIVATE KEY' - }); - key = { key: pem, padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; - } - try { - return new Uint8Array(nodeCrypto$6.privateDecrypt(key, data)); - } catch (err) { - if (randomPayload) { - return randomPayload; - } - throw new Error('Decryption error'); - } - } - - async function bnDecrypt(data, n, e, d, p, q, u, randomPayload) { - const BigInteger = await util.getBigInteger(); - data = new BigInteger(data); - n = new BigInteger(n); - e = new BigInteger(e); - d = new BigInteger(d); - p = new BigInteger(p); - q = new BigInteger(q); - u = new BigInteger(u); - if (data.gte(n)) { - throw new Error('Data too large.'); - } - const dq = d.mod(q.dec()); // d mod (q-1) - const dp = d.mod(p.dec()); // d mod (p-1) - - const unblinder = (await getRandomBigInteger(new BigInteger(2), n)).mod(n); - const blinder = unblinder.modInv(n).modExp(e, n); - data = data.mul(blinder).mod(n); - - - const mp = data.modExp(dp, p); // data**{d mod (q-1)} mod p - const mq = data.modExp(dq, q); // data**{d mod (p-1)} mod q - const h = u.mul(mq.sub(mp)).mod(q); // u * (mq-mp) mod q (operands already < q) - - let result = h.mul(p).add(mp); // result < n due to relations above - - result = result.mul(unblinder).mod(n); - - - return emeDecode(result.toUint8Array('be', n.byteLength()), randomPayload); - } - - /** Convert Openpgp private key params to jwk key according to - * @link https://tools.ietf.org/html/rfc7517 - * @param {String} hashAlgo - * @param {Uint8Array} n - * @param {Uint8Array} e - * @param {Uint8Array} d - * @param {Uint8Array} p - * @param {Uint8Array} q - * @param {Uint8Array} u - */ - async function privateToJWK(n, e, d, p, q, u) { - const BigInteger = await util.getBigInteger(); - const pNum = new BigInteger(p); - const qNum = new BigInteger(q); - const dNum = new BigInteger(d); - - let dq = dNum.mod(qNum.dec()); // d mod (q-1) - let dp = dNum.mod(pNum.dec()); // d mod (p-1) - dp = dp.toUint8Array(); - dq = dq.toUint8Array(); - return { - kty: 'RSA', - n: uint8ArrayToB64(n, true), - e: uint8ArrayToB64(e, true), - d: uint8ArrayToB64(d, true), - // switch p and q - p: uint8ArrayToB64(q, true), - q: uint8ArrayToB64(p, true), - // switch dp and dq - dp: uint8ArrayToB64(dq, true), - dq: uint8ArrayToB64(dp, true), - qi: uint8ArrayToB64(u, true), - ext: true - }; - } - - /** Convert Openpgp key public params to jwk key according to - * @link https://tools.ietf.org/html/rfc7517 - * @param {String} hashAlgo - * @param {Uint8Array} n - * @param {Uint8Array} e - */ - function publicToJWK(n, e) { - return { - kty: 'RSA', - n: uint8ArrayToB64(n, true), - e: uint8ArrayToB64(e, true), - ext: true - }; - } - - var rsa = /*#__PURE__*/Object.freeze({ - __proto__: null, - sign: sign, - verify: verify, - encrypt: encrypt$1, - decrypt: decrypt$1, - generate: generate, - validateParams: validateParams - }); - - // GPG4Browsers - An OpenPGP implementation in javascript - - /** - * ElGamal Encryption function - * Note that in OpenPGP, the message needs to be padded with PKCS#1 (same as RSA) - * @param {Uint8Array} data - To be padded and encrypted - * @param {Uint8Array} p - * @param {Uint8Array} g - * @param {Uint8Array} y - * @returns {Promise<{ c1: Uint8Array, c2: Uint8Array }>} - * @async - */ - async function encrypt$2(data, p, g, y) { - const BigInteger = await util.getBigInteger(); - p = new BigInteger(p); - g = new BigInteger(g); - y = new BigInteger(y); - - const padded = await emeEncode(data, p.byteLength()); - const m = new BigInteger(padded); - - // OpenPGP uses a "special" version of ElGamal where g is generator of the full group Z/pZ* - // hence g has order p-1, and to avoid that k = 0 mod p-1, we need to pick k in [1, p-2] - const k = await getRandomBigInteger(new BigInteger(1), p.dec()); - return { - c1: g.modExp(k, p).toUint8Array(), - c2: y.modExp(k, p).imul(m).imod(p).toUint8Array() - }; - } - - /** - * ElGamal Encryption function - * @param {Uint8Array} c1 - * @param {Uint8Array} c2 - * @param {Uint8Array} p - * @param {Uint8Array} x - * @param {Uint8Array} randomPayload - Data to return on unpadding error, instead of throwing - * (needed for constant-time processing) - * @returns {Promise} Unpadded message. - * @throws {Error} on decryption error, unless `randomPayload` is given - * @async - */ - async function decrypt$2(c1, c2, p, x, randomPayload) { - const BigInteger = await util.getBigInteger(); - c1 = new BigInteger(c1); - c2 = new BigInteger(c2); - p = new BigInteger(p); - x = new BigInteger(x); - - const padded = c1.modExp(x, p).modInv(p).imul(c2).imod(p); - return emeDecode(padded.toUint8Array('be', p.byteLength()), randomPayload); - } - - /** - * Validate ElGamal parameters - * @param {Uint8Array} p - ElGamal prime - * @param {Uint8Array} g - ElGamal group generator - * @param {Uint8Array} y - ElGamal public key - * @param {Uint8Array} x - ElGamal private exponent - * @returns {Promise} Whether params are valid. - * @async - */ - async function validateParams$1(p, g, y, x) { - const BigInteger = await util.getBigInteger(); - p = new BigInteger(p); - g = new BigInteger(g); - y = new BigInteger(y); - - const one = new BigInteger(1); - // Check that 1 < g < p - if (g.lte(one) || g.gte(p)) { - return false; - } - - // Expect p-1 to be large - const pSize = new BigInteger(p.bitLength()); - const n1023 = new BigInteger(1023); - if (pSize.lt(n1023)) { - return false; - } - - /** - * g should have order p-1 - * Check that g ** (p-1) = 1 mod p - */ - if (!g.modExp(p.dec(), p).isOne()) { - return false; - } - - /** - * Since p-1 is not prime, g might have a smaller order that divides p-1 - * We want to make sure that the order is large enough to hinder a small subgroup attack - * - * We just check g**i != 1 for all i up to a threshold - */ - let res = g; - const i = new BigInteger(1); - const threshold = new BigInteger(2).leftShift(new BigInteger(17)); // we want order > threshold - while (i.lt(threshold)) { - res = res.mul(g).imod(p); - if (res.isOne()) { - return false; - } - i.iinc(); - } - - /** - * Re-derive public key y' = g ** x mod p - * Expect y == y' - * - * Blinded exponentiation computes g**{r(p-1) + x} to compare to y - */ - x = new BigInteger(x); - const two = new BigInteger(2); - const r = await getRandomBigInteger(two.leftShift(pSize.dec()), two.leftShift(pSize)); // draw r of same size as p-1 - const rqx = p.dec().imul(r).iadd(x); - if (!y.equal(g.modExp(rqx, p))) { - return false; - } - - return true; - } - - var elgamal = /*#__PURE__*/Object.freeze({ - __proto__: null, - encrypt: encrypt$2, - decrypt: decrypt$2, - validateParams: validateParams$1 - }); - - // OpenPGP.js - An OpenPGP implementation in javascript - - class OID { - constructor(oid) { - if (oid instanceof OID) { - this.oid = oid.oid; - } else if (util.isArray(oid) || - util.isUint8Array(oid)) { - oid = new Uint8Array(oid); - if (oid[0] === 0x06) { // DER encoded oid byte array - if (oid[1] !== oid.length - 2) { - throw new Error('Length mismatch in DER encoded oid'); - } - oid = oid.subarray(2); - } - this.oid = oid; - } else { - this.oid = ''; - } - } - - /** - * Method to read an OID object - * @param {Uint8Array} input - Where to read the OID from - * @returns {Number} Number of read bytes. - */ - read(input) { - if (input.length >= 1) { - const length = input[0]; - if (input.length >= 1 + length) { - this.oid = input.subarray(1, 1 + length); - return 1 + this.oid.length; - } - } - throw new Error('Invalid oid'); - } - - /** - * Serialize an OID object - * @returns {Uint8Array} Array with the serialized value the OID. - */ - write() { - return util.concatUint8Array([new Uint8Array([this.oid.length]), this.oid]); - } - - /** - * Serialize an OID object as a hex string - * @returns {string} String with the hex value of the OID. - */ - toHex() { - return util.uint8ArrayToHex(this.oid); - } - - /** - * If a known curve object identifier, return the canonical name of the curve - * @returns {string} String with the canonical name of the curve. - */ - getName() { - const hex = this.toHex(); - if (enums.curve[hex]) { - return enums.write(enums.curve, hex); - } else { - throw new Error('Unknown curve object identifier.'); - } - } - } - - // OpenPGP.js - An OpenPGP implementation in javascript - - function keyFromPrivate(indutnyCurve, priv) { - const keyPair = indutnyCurve.keyPair({ priv: priv }); - return keyPair; - } - - function keyFromPublic(indutnyCurve, pub) { - const keyPair = indutnyCurve.keyPair({ pub: pub }); - if (keyPair.validate().result !== true) { - throw new Error('Invalid elliptic public key'); - } - return keyPair; - } - - async function getIndutnyCurve(name) { - if (!defaultConfig.useIndutnyElliptic) { - throw new Error('This curve is only supported in the full build of OpenPGP.js'); - } - const { default: elliptic } = await Promise.resolve().then(function () { return elliptic$1; }); - return new elliptic.ec(name); - } - - // OpenPGP.js - An OpenPGP implementation in javascript - - const webCrypto$6 = util.getWebCrypto(); - const nodeCrypto$7 = util.getNodeCrypto(); - - const webCurves = { - 'p256': 'P-256', - 'p384': 'P-384', - 'p521': 'P-521' - }; - const knownCurves = nodeCrypto$7 ? nodeCrypto$7.getCurves() : []; - const nodeCurves = nodeCrypto$7 ? { - secp256k1: knownCurves.includes('secp256k1') ? 'secp256k1' : undefined, - p256: knownCurves.includes('prime256v1') ? 'prime256v1' : undefined, - p384: knownCurves.includes('secp384r1') ? 'secp384r1' : undefined, - p521: knownCurves.includes('secp521r1') ? 'secp521r1' : undefined, - ed25519: knownCurves.includes('ED25519') ? 'ED25519' : undefined, - curve25519: knownCurves.includes('X25519') ? 'X25519' : undefined, - brainpoolP256r1: knownCurves.includes('brainpoolP256r1') ? 'brainpoolP256r1' : undefined, - brainpoolP384r1: knownCurves.includes('brainpoolP384r1') ? 'brainpoolP384r1' : undefined, - brainpoolP512r1: knownCurves.includes('brainpoolP512r1') ? 'brainpoolP512r1' : undefined - } : {}; - - const curves = { - p256: { - oid: [0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07], - keyType: enums.publicKey.ecdsa, - hash: enums.hash.sha256, - cipher: enums.symmetric.aes128, - node: nodeCurves.p256, - web: webCurves.p256, - payloadSize: 32, - sharedSize: 256 - }, - p384: { - oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22], - keyType: enums.publicKey.ecdsa, - hash: enums.hash.sha384, - cipher: enums.symmetric.aes192, - node: nodeCurves.p384, - web: webCurves.p384, - payloadSize: 48, - sharedSize: 384 - }, - p521: { - oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23], - keyType: enums.publicKey.ecdsa, - hash: enums.hash.sha512, - cipher: enums.symmetric.aes256, - node: nodeCurves.p521, - web: webCurves.p521, - payloadSize: 66, - sharedSize: 528 - }, - secp256k1: { - oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x0A], - keyType: enums.publicKey.ecdsa, - hash: enums.hash.sha256, - cipher: enums.symmetric.aes128, - node: nodeCurves.secp256k1, - payloadSize: 32 - }, - ed25519: { - oid: [0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01], - keyType: enums.publicKey.eddsa, - hash: enums.hash.sha512, - node: false, // nodeCurves.ed25519 TODO - payloadSize: 32 - }, - curve25519: { - oid: [0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01], - keyType: enums.publicKey.ecdh, - hash: enums.hash.sha256, - cipher: enums.symmetric.aes128, - node: false, // nodeCurves.curve25519 TODO - payloadSize: 32 - }, - brainpoolP256r1: { - oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07], - keyType: enums.publicKey.ecdsa, - hash: enums.hash.sha256, - cipher: enums.symmetric.aes128, - node: nodeCurves.brainpoolP256r1, - payloadSize: 32 - }, - brainpoolP384r1: { - oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B], - keyType: enums.publicKey.ecdsa, - hash: enums.hash.sha384, - cipher: enums.symmetric.aes192, - node: nodeCurves.brainpoolP384r1, - payloadSize: 48 - }, - brainpoolP512r1: { - oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D], - keyType: enums.publicKey.ecdsa, - hash: enums.hash.sha512, - cipher: enums.symmetric.aes256, - node: nodeCurves.brainpoolP512r1, - payloadSize: 64 - } - }; - - class Curve { - constructor(oidOrName, params) { - try { - if (util.isArray(oidOrName) || - util.isUint8Array(oidOrName)) { - // by oid byte array - oidOrName = new OID(oidOrName); - } - if (oidOrName instanceof OID) { - // by curve OID - oidOrName = oidOrName.getName(); - } - // by curve name or oid string - this.name = enums.write(enums.curve, oidOrName); - } catch (err) { - throw new Error('Not valid curve'); - } - params = params || curves[this.name]; - - this.keyType = params.keyType; - - this.oid = params.oid; - this.hash = params.hash; - this.cipher = params.cipher; - this.node = params.node && curves[this.name]; - this.web = params.web && curves[this.name]; - this.payloadSize = params.payloadSize; - if (this.web && util.getWebCrypto()) { - this.type = 'web'; - } else if (this.node && util.getNodeCrypto()) { - this.type = 'node'; - } else if (this.name === 'curve25519') { - this.type = 'curve25519'; - } else if (this.name === 'ed25519') { - this.type = 'ed25519'; - } - } - - async genKeyPair() { - let keyPair; - switch (this.type) { - case 'web': - try { - return await webGenKeyPair(this.name); - } catch (err) { - util.printDebugError('Browser did not support generating ec key ' + err.message); - break; - } - case 'node': - return nodeGenKeyPair(this.name); - case 'curve25519': { - const privateKey = await getRandomBytes(32); - privateKey[0] = (privateKey[0] & 127) | 64; - privateKey[31] &= 248; - const secretKey = privateKey.slice().reverse(); - keyPair = naclFastLight.box.keyPair.fromSecretKey(secretKey); - const publicKey = util.concatUint8Array([new Uint8Array([0x40]), keyPair.publicKey]); - return { publicKey, privateKey }; - } - case 'ed25519': { - const privateKey = await getRandomBytes(32); - const keyPair = naclFastLight.sign.keyPair.fromSeed(privateKey); - const publicKey = util.concatUint8Array([new Uint8Array([0x40]), keyPair.publicKey]); - return { publicKey, privateKey }; - } - } - const indutnyCurve = await getIndutnyCurve(this.name); - keyPair = await indutnyCurve.genKeyPair({ - entropy: util.uint8ArrayToString(await getRandomBytes(32)) - }); - return { publicKey: new Uint8Array(keyPair.getPublic('array', false)), privateKey: keyPair.getPrivate().toArrayLike(Uint8Array) }; - } - } - - async function generate$1(curve) { - const BigInteger = await util.getBigInteger(); - - curve = new Curve(curve); - const keyPair = await curve.genKeyPair(); - const Q = new BigInteger(keyPair.publicKey).toUint8Array(); - const secret = new BigInteger(keyPair.privateKey).toUint8Array('be', curve.payloadSize); - return { - oid: curve.oid, - Q, - secret, - hash: curve.hash, - cipher: curve.cipher - }; - } - - /** - * Get preferred hash algo to use with the given curve - * @param {module:type/oid} oid - curve oid - * @returns {enums.hash} hash algorithm - */ - function getPreferredHashAlgo(oid) { - return curves[enums.write(enums.curve, oid.toHex())].hash; - } - - /** - * Validate ECDH and ECDSA parameters - * Not suitable for EdDSA (different secret key format) - * @param {module:enums.publicKey} algo - EC algorithm, to filter supported curves - * @param {module:type/oid} oid - EC object identifier - * @param {Uint8Array} Q - EC public point - * @param {Uint8Array} d - EC secret scalar - * @returns {Promise} Whether params are valid. - * @async - */ - async function validateStandardParams(algo, oid, Q, d) { - const supportedCurves = { - p256: true, - p384: true, - p521: true, - secp256k1: true, - curve25519: algo === enums.publicKey.ecdh, - brainpoolP256r1: true, - brainpoolP384r1: true, - brainpoolP512r1: true - }; - - // Check whether the given curve is supported - const curveName = oid.getName(); - if (!supportedCurves[curveName]) { - return false; - } - - if (curveName === 'curve25519') { - d = d.slice().reverse(); - // Re-derive public point Q' - const { publicKey } = naclFastLight.box.keyPair.fromSecretKey(d); - - Q = new Uint8Array(Q); - const dG = new Uint8Array([0x40, ...publicKey]); // Add public key prefix - if (!util.equalsUint8Array(dG, Q)) { - return false; - } - - return true; - } - - const curve = await getIndutnyCurve(curveName); - try { - // Parse Q and check that it is on the curve but not at infinity - Q = keyFromPublic(curve, Q).getPublic(); - } catch (validationErrors) { - return false; - } - - /** - * Re-derive public point Q' = dG from private key - * Expect Q == Q' - */ - const dG = keyFromPrivate(curve, d).getPublic(); - if (!dG.eq(Q)) { - return false; - } - - return true; - } - - ////////////////////////// - // // - // Helper functions // - // // - ////////////////////////// - - - async function webGenKeyPair(name) { - // Note: keys generated with ECDSA and ECDH are structurally equivalent - const webCryptoKey = await webCrypto$6.generateKey({ name: 'ECDSA', namedCurve: webCurves[name] }, true, ['sign', 'verify']); - - const privateKey = await webCrypto$6.exportKey('jwk', webCryptoKey.privateKey); - const publicKey = await webCrypto$6.exportKey('jwk', webCryptoKey.publicKey); - - return { - publicKey: jwkToRawPublic(publicKey), - privateKey: b64ToUint8Array(privateKey.d) - }; - } - - async function nodeGenKeyPair(name) { - // Note: ECDSA and ECDH key generation is structurally equivalent - const ecdh = nodeCrypto$7.createECDH(nodeCurves[name]); - await ecdh.generateKeys(); - return { - publicKey: new Uint8Array(ecdh.getPublicKey()), - privateKey: new Uint8Array(ecdh.getPrivateKey()) - }; - } - - ////////////////////////// - // // - // Helper functions // - // // - ////////////////////////// - - /** - * @param {JsonWebKey} jwk - key for conversion - * - * @returns {Uint8Array} Raw public key. - */ - function jwkToRawPublic(jwk) { - const bufX = b64ToUint8Array(jwk.x); - const bufY = b64ToUint8Array(jwk.y); - const publicKey = new Uint8Array(bufX.length + bufY.length + 1); - publicKey[0] = 0x04; - publicKey.set(bufX, 1); - publicKey.set(bufY, bufX.length + 1); - return publicKey; - } - - /** - * @param {Integer} payloadSize - ec payload size - * @param {String} name - curve name - * @param {Uint8Array} publicKey - public key - * - * @returns {JsonWebKey} Public key in jwk format. - */ - function rawPublicToJWK(payloadSize, name, publicKey) { - const len = payloadSize; - const bufX = publicKey.slice(1, len + 1); - const bufY = publicKey.slice(len + 1, len * 2 + 1); - // https://www.rfc-editor.org/rfc/rfc7518.txt - const jwk = { - kty: 'EC', - crv: name, - x: uint8ArrayToB64(bufX, true), - y: uint8ArrayToB64(bufY, true), - ext: true - }; - return jwk; - } - - /** - * @param {Integer} payloadSize - ec payload size - * @param {String} name - curve name - * @param {Uint8Array} publicKey - public key - * @param {Uint8Array} privateKey - private key - * - * @returns {JsonWebKey} Private key in jwk format. - */ - function privateToJWK$1(payloadSize, name, publicKey, privateKey) { - const jwk = rawPublicToJWK(payloadSize, name, publicKey); - jwk.d = uint8ArrayToB64(privateKey, true); - return jwk; - } - - // OpenPGP.js - An OpenPGP implementation in javascript - - const webCrypto$7 = util.getWebCrypto(); - const nodeCrypto$8 = util.getNodeCrypto(); - - /** - * Sign a message using the provided key - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {module:enums.hash} hashAlgo - Hash algorithm used to sign - * @param {Uint8Array} message - Message to sign - * @param {Uint8Array} publicKey - Public key - * @param {Uint8Array} privateKey - Private key used to sign the message - * @param {Uint8Array} hashed - The hashed message - * @returns {Promise<{ - * r: Uint8Array, - * s: Uint8Array - * }>} Signature of the message - * @async - */ - async function sign$1(oid, hashAlgo, message, publicKey, privateKey, hashed) { - const curve = new Curve(oid); - if (message && !util.isStream(message)) { - const keyPair = { publicKey, privateKey }; - switch (curve.type) { - case 'web': { - // If browser doesn't support a curve, we'll catch it - try { - // Need to await to make sure browser succeeds - return await webSign$1(curve, hashAlgo, message, keyPair); - } catch (err) { - // We do not fallback if the error is related to key integrity - // Unfortunaley Safari does not support p521 and throws a DataError when using it - // So we need to always fallback for that curve - if (curve.name !== 'p521' && (err.name === 'DataError' || err.name === 'OperationError')) { - throw err; - } - util.printDebugError('Browser did not support signing: ' + err.message); - } - break; - } - case 'node': { - const signature = await nodeSign$1(curve, hashAlgo, message, keyPair); - return { - r: signature.r.toArrayLike(Uint8Array), - s: signature.s.toArrayLike(Uint8Array) - }; - } - } - } - return ellipticSign(curve, hashed, privateKey); - } - - /** - * Verifies if a signature is valid for a message - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {module:enums.hash} hashAlgo - Hash algorithm used in the signature - * @param {{r: Uint8Array, - s: Uint8Array}} signature Signature to verify - * @param {Uint8Array} message - Message to verify - * @param {Uint8Array} publicKey - Public key used to verify the message - * @param {Uint8Array} hashed - The hashed message - * @returns {Boolean} - * @async - */ - async function verify$1(oid, hashAlgo, signature, message, publicKey, hashed) { - const curve = new Curve(oid); - if (message && !util.isStream(message)) { - switch (curve.type) { - case 'web': - try { - // Need to await to make sure browser succeeds - return await webVerify$1(curve, hashAlgo, signature, message, publicKey); - } catch (err) { - // We do not fallback if the error is related to key integrity - // Unfortunately Safari does not support p521 and throws a DataError when using it - // So we need to always fallback for that curve - if (curve.name !== 'p521' && (err.name === 'DataError' || err.name === 'OperationError')) { - throw err; - } - util.printDebugError('Browser did not support verifying: ' + err.message); - } - break; - case 'node': - return nodeVerify$1(curve, hashAlgo, signature, message, publicKey); - } - } - const digest = (typeof hashAlgo === 'undefined') ? message : hashed; - return ellipticVerify(curve, signature, digest, publicKey); - } - - /** - * Validate ECDSA parameters - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {Uint8Array} Q - ECDSA public point - * @param {Uint8Array} d - ECDSA secret scalar - * @returns {Promise} Whether params are valid. - * @async - */ - async function validateParams$2(oid, Q, d) { - const curve = new Curve(oid); - // Reject curves x25519 and ed25519 - if (curve.keyType !== enums.publicKey.ecdsa) { - return false; - } - - // To speed up the validation, we try to use node- or webcrypto when available - // and sign + verify a random message - switch (curve.type) { - case 'web': - case 'node': { - const message = await getRandomBytes(8); - const hashAlgo = enums.hash.sha256; - const hashed = await hash.digest(hashAlgo, message); - try { - const signature = await sign$1(oid, hashAlgo, message, Q, d, hashed); - return await verify$1(oid, hashAlgo, signature, message, Q, hashed); - } catch (err) { - return false; - } - } - default: - return validateStandardParams(enums.publicKey.ecdsa, oid, Q, d); - } - } - - - ////////////////////////// - // // - // Helper functions // - // // - ////////////////////////// - - async function ellipticSign(curve, hashed, privateKey) { - const indutnyCurve = await getIndutnyCurve(curve.name); - const key = keyFromPrivate(indutnyCurve, privateKey); - const signature = key.sign(hashed); - return { - r: signature.r.toArrayLike(Uint8Array), - s: signature.s.toArrayLike(Uint8Array) - }; - } - - async function ellipticVerify(curve, signature, digest, publicKey) { - const indutnyCurve = await getIndutnyCurve(curve.name); - const key = keyFromPublic(indutnyCurve, publicKey); - return key.verify(digest, signature); - } - - async function webSign$1(curve, hashAlgo, message, keyPair) { - const len = curve.payloadSize; - const jwk = privateToJWK$1(curve.payloadSize, webCurves[curve.name], keyPair.publicKey, keyPair.privateKey); - const key = await webCrypto$7.importKey( - 'jwk', - jwk, - { - 'name': 'ECDSA', - 'namedCurve': webCurves[curve.name], - 'hash': { name: enums.read(enums.webHash, curve.hash) } - }, - false, - ['sign'] - ); - - const signature = new Uint8Array(await webCrypto$7.sign( - { - 'name': 'ECDSA', - 'namedCurve': webCurves[curve.name], - 'hash': { name: enums.read(enums.webHash, hashAlgo) } - }, - key, - message - )); - - return { - r: signature.slice(0, len), - s: signature.slice(len, len << 1) - }; - } - - async function webVerify$1(curve, hashAlgo, { r, s }, message, publicKey) { - const jwk = rawPublicToJWK(curve.payloadSize, webCurves[curve.name], publicKey); - const key = await webCrypto$7.importKey( - 'jwk', - jwk, - { - 'name': 'ECDSA', - 'namedCurve': webCurves[curve.name], - 'hash': { name: enums.read(enums.webHash, curve.hash) } - }, - false, - ['verify'] - ); - - const signature = util.concatUint8Array([r, s]).buffer; - - return webCrypto$7.verify( - { - 'name': 'ECDSA', - 'namedCurve': webCurves[curve.name], - 'hash': { name: enums.read(enums.webHash, hashAlgo) } - }, - key, - signature, - message - ); - } - - async function nodeSign$1(curve, hashAlgo, message, keyPair) { - const sign = nodeCrypto$8.createSign(enums.read(enums.hash, hashAlgo)); - sign.write(message); - sign.end(); - const key = ECPrivateKey.encode({ - version: 1, - parameters: curve.oid, - privateKey: Array.from(keyPair.privateKey), - publicKey: { unused: 0, data: Array.from(keyPair.publicKey) } - }, 'pem', { - label: 'EC PRIVATE KEY' - }); - - return ECDSASignature.decode(sign.sign(key), 'der'); - } - - async function nodeVerify$1(curve, hashAlgo, { r, s }, message, publicKey) { - const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); - - const verify = nodeCrypto$8.createVerify(enums.read(enums.hash, hashAlgo)); - verify.write(message); - verify.end(); - const key = SubjectPublicKeyInfo.encode({ - algorithm: { - algorithm: [1, 2, 840, 10045, 2, 1], - parameters: curve.oid - }, - subjectPublicKey: { unused: 0, data: Array.from(publicKey) } - }, 'pem', { - label: 'PUBLIC KEY' - }); - const signature = ECDSASignature.encode({ - r: new BN(r), s: new BN(s) - }, 'der'); - - try { - return verify.verify(key, signature); - } catch (err) { - return false; - } - } - - // Originally written by Owen Smith https://github.com/omsmith - // Adapted on Feb 2018 from https://github.com/Brightspace/node-jwk-to-pem/ - - /* eslint-disable no-invalid-this */ - - const asn1$1 = nodeCrypto$8 ? void('asn1.js') : undefined; - - const ECDSASignature = nodeCrypto$8 ? - asn1$1.define('ECDSASignature', function() { - this.seq().obj( - this.key('r').int(), - this.key('s').int() - ); - }) : undefined; - - const ECPrivateKey = nodeCrypto$8 ? - asn1$1.define('ECPrivateKey', function() { - this.seq().obj( - this.key('version').int(), - this.key('privateKey').octstr(), - this.key('parameters').explicit(0).optional().any(), - this.key('publicKey').explicit(1).optional().bitstr() - ); - }) : undefined; - - const AlgorithmIdentifier = nodeCrypto$8 ? - asn1$1.define('AlgorithmIdentifier', function() { - this.seq().obj( - this.key('algorithm').objid(), - this.key('parameters').optional().any() - ); - }) : undefined; - - const SubjectPublicKeyInfo = nodeCrypto$8 ? - asn1$1.define('SubjectPublicKeyInfo', function() { - this.seq().obj( - this.key('algorithm').use(AlgorithmIdentifier), - this.key('subjectPublicKey').bitstr() - ); - }) : undefined; - - var ecdsa = /*#__PURE__*/Object.freeze({ - __proto__: null, - sign: sign$1, - verify: verify$1, - validateParams: validateParams$2 - }); - - // OpenPGP.js - An OpenPGP implementation in javascript - - naclFastLight.hash = bytes => new Uint8Array(_512().update(bytes).digest()); - - /** - * Sign a message using the provided key - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {module:enums.hash} hashAlgo - Hash algorithm used to sign (must be sha256 or stronger) - * @param {Uint8Array} message - Message to sign - * @param {Uint8Array} publicKey - Public key - * @param {Uint8Array} privateKey - Private key used to sign the message - * @param {Uint8Array} hashed - The hashed message - * @returns {Promise<{ - * r: Uint8Array, - * s: Uint8Array - * }>} Signature of the message - * @async - */ - async function sign$2(oid, hashAlgo, message, publicKey, privateKey, hashed) { - if (hash.getHashByteLength(hashAlgo) < hash.getHashByteLength(enums.hash.sha256)) { - // see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2 - throw new Error('Hash algorithm too weak: sha256 or stronger is required for EdDSA.'); - } - const secretKey = util.concatUint8Array([privateKey, publicKey.subarray(1)]); - const signature = naclFastLight.sign.detached(hashed, secretKey); - // EdDSA signature params are returned in little-endian format - return { - r: signature.subarray(0, 32), - s: signature.subarray(32) - }; - } - - /** - * Verifies if a signature is valid for a message - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {module:enums.hash} hashAlgo - Hash algorithm used in the signature - * @param {{r: Uint8Array, - s: Uint8Array}} signature Signature to verify the message - * @param {Uint8Array} m - Message to verify - * @param {Uint8Array} publicKey - Public key used to verify the message - * @param {Uint8Array} hashed - The hashed message - * @returns {Boolean} - * @async - */ - async function verify$2(oid, hashAlgo, { r, s }, m, publicKey, hashed) { - const signature = util.concatUint8Array([r, s]); - return naclFastLight.sign.detached.verify(hashed, signature, publicKey.subarray(1)); - } - /** - * Validate EdDSA parameters - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {Uint8Array} Q - EdDSA public point - * @param {Uint8Array} k - EdDSA secret seed - * @returns {Promise} Whether params are valid. - * @async - */ - async function validateParams$3(oid, Q, k) { - // Check whether the given curve is supported - if (oid.getName() !== 'ed25519') { - return false; - } - - /** - * Derive public point Q' = dG from private key - * and expect Q == Q' - */ - const { publicKey } = naclFastLight.sign.keyPair.fromSeed(k); - const dG = new Uint8Array([0x40, ...publicKey]); // Add public key prefix - return util.equalsUint8Array(Q, dG); - } - - var eddsa = /*#__PURE__*/Object.freeze({ - __proto__: null, - sign: sign$2, - verify: verify$2, - validateParams: validateParams$3 - }); - - // OpenPGP.js - An OpenPGP implementation in javascript - - /** - * AES key wrap - * @function - * @param {Uint8Array} key - * @param {Uint8Array} data - * @returns {Uint8Array} - */ - function wrap(key, data) { - const aes = new cipher['aes' + (key.length * 8)](key); - const IV = new Uint32Array([0xA6A6A6A6, 0xA6A6A6A6]); - const P = unpack(data); - let A = IV; - const R = P; - const n = P.length / 2; - const t = new Uint32Array([0, 0]); - let B = new Uint32Array(4); - for (let j = 0; j <= 5; ++j) { - for (let i = 0; i < n; ++i) { - t[1] = n * j + (1 + i); - // B = A - B[0] = A[0]; - B[1] = A[1]; - // B = A || R[i] - B[2] = R[2 * i]; - B[3] = R[2 * i + 1]; - // B = AES(K, B) - B = unpack(aes.encrypt(pack(B))); - // A = MSB(64, B) ^ t - A = B.subarray(0, 2); - A[0] ^= t[0]; - A[1] ^= t[1]; - // R[i] = LSB(64, B) - R[2 * i] = B[2]; - R[2 * i + 1] = B[3]; - } - } - return pack(A, R); - } - - /** - * AES key unwrap - * @function - * @param {String} key - * @param {String} data - * @returns {Uint8Array} - * @throws {Error} - */ - function unwrap(key, data) { - const aes = new cipher['aes' + (key.length * 8)](key); - const IV = new Uint32Array([0xA6A6A6A6, 0xA6A6A6A6]); - const C = unpack(data); - let A = C.subarray(0, 2); - const R = C.subarray(2); - const n = C.length / 2 - 1; - const t = new Uint32Array([0, 0]); - let B = new Uint32Array(4); - for (let j = 5; j >= 0; --j) { - for (let i = n - 1; i >= 0; --i) { - t[1] = n * j + (i + 1); - // B = A ^ t - B[0] = A[0] ^ t[0]; - B[1] = A[1] ^ t[1]; - // B = (A ^ t) || R[i] - B[2] = R[2 * i]; - B[3] = R[2 * i + 1]; - // B = AES-1(B) - B = unpack(aes.decrypt(pack(B))); - // A = MSB(64, B) - A = B.subarray(0, 2); - // R[i] = LSB(64, B) - R[2 * i] = B[2]; - R[2 * i + 1] = B[3]; - } - } - if (A[0] === IV[0] && A[1] === IV[1]) { - return pack(R); - } - throw new Error('Key Data Integrity failed'); - } - - function createArrayBuffer(data) { - if (util.isString(data)) { - const { length } = data; - const buffer = new ArrayBuffer(length); - const view = new Uint8Array(buffer); - for (let j = 0; j < length; ++j) { - view[j] = data.charCodeAt(j); - } - return buffer; - } - return new Uint8Array(data).buffer; - } - - function unpack(data) { - const { length } = data; - const buffer = createArrayBuffer(data); - const view = new DataView(buffer); - const arr = new Uint32Array(length / 4); - for (let i = 0; i < length / 4; ++i) { - arr[i] = view.getUint32(4 * i); - } - return arr; - } - - function pack() { - let length = 0; - for (let k = 0; k < arguments.length; ++k) { - length += 4 * arguments[k].length; - } - const buffer = new ArrayBuffer(length); - const view = new DataView(buffer); - let offset = 0; - for (let i = 0; i < arguments.length; ++i) { - for (let j = 0; j < arguments[i].length; ++j) { - view.setUint32(offset + 4 * j, arguments[i][j]); - } - offset += 4 * arguments[i].length; - } - return new Uint8Array(buffer); - } - - var aesKW = /*#__PURE__*/Object.freeze({ - __proto__: null, - wrap: wrap, - unwrap: unwrap - }); - - // OpenPGP.js - An OpenPGP implementation in javascript - - /** - * @fileoverview Functions to add and remove PKCS5 padding - * @see PublicKeyEncryptedSessionKeyPacket - * @module crypto/pkcs5 - * @private - */ - - /** - * Add pkcs5 padding to a message - * @param {Uint8Array} message - message to pad - * @returns {Uint8Array} Padded message. - */ - function encode$1(message) { - const c = 8 - (message.length % 8); - const padded = new Uint8Array(message.length + c).fill(c); - padded.set(message); - return padded; - } - - /** - * Remove pkcs5 padding from a message - * @param {Uint8Array} message - message to remove padding from - * @returns {Uint8Array} Message without padding. - */ - function decode$1(message) { - const len = message.length; - if (len > 0) { - const c = message[len - 1]; - if (c >= 1) { - const provided = message.subarray(len - c); - const computed = new Uint8Array(c).fill(c); - if (util.equalsUint8Array(provided, computed)) { - return message.subarray(0, len - c); - } - } - } - throw new Error('Invalid padding'); - } - - var pkcs5 = /*#__PURE__*/Object.freeze({ - __proto__: null, - encode: encode$1, - decode: decode$1 - }); - - // OpenPGP.js - An OpenPGP implementation in javascript - - class ECDHSymmetricKey { - constructor(data) { - if (typeof data === 'undefined') { - data = new Uint8Array([]); - } else if (util.isString(data)) { - data = util.stringToUint8Array(data); - } else { - data = new Uint8Array(data); - } - this.data = data; - } - - /** - * Read an ECDHSymmetricKey from an Uint8Array - * @param {Uint8Array} input - Where to read the encoded symmetric key from - * @returns {Number} Number of read bytes. - */ - read(input) { - if (input.length >= 1) { - const length = input[0]; - if (input.length >= 1 + length) { - this.data = input.subarray(1, 1 + length); - return 1 + this.data.length; - } - } - throw new Error('Invalid symmetric key'); - } - - /** - * Write an ECDHSymmetricKey as an Uint8Array - * @returns {Uint8Array} An array containing the value - */ - write() { - return util.concatUint8Array([new Uint8Array([this.data.length]), this.data]); - } - } - - // OpenPGP.js - An OpenPGP implementation in javascript - // Copyright (C) 2015-2016 Decentral - // - // This library is free software; you can redistribute it and/or - // modify it under the terms of the GNU Lesser General Public - // License as published by the Free Software Foundation; either - // version 3.0 of the License, or (at your option) any later version. - // - // This library is distributed in the hope that it will be useful, - // but WITHOUT ANY WARRANTY; without even the implied warranty of - // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - // Lesser General Public License for more details. - // - // You should have received a copy of the GNU Lesser General Public - // License along with this library; if not, write to the Free Software - // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - - /** - * Implementation of type KDF parameters - * - * {@link https://tools.ietf.org/html/rfc6637#section-7|RFC 6637 7}: - * A key derivation function (KDF) is necessary to implement the EC - * encryption. The Concatenation Key Derivation Function (Approved - * Alternative 1) [NIST-SP800-56A] with the KDF hash function that is - * SHA2-256 [FIPS-180-3] or stronger is REQUIRED. - * @module type/kdf_params - * @private - */ - - class KDFParams { - /** - * @param {enums.hash} hash - Hash algorithm - * @param {enums.symmetric} cipher - Symmetric algorithm - */ - constructor(data) { - if (data) { - const { hash, cipher } = data; - this.hash = hash; - this.cipher = cipher; - } else { - this.hash = null; - this.cipher = null; - } - } - - /** - * Read KDFParams from an Uint8Array - * @param {Uint8Array} input - Where to read the KDFParams from - * @returns {Number} Number of read bytes. - */ - read(input) { - if (input.length < 4 || input[0] !== 3 || input[1] !== 1) { - throw new Error('Cannot read KDFParams'); - } - this.hash = input[2]; - this.cipher = input[3]; - return 4; - } - - /** - * Write KDFParams to an Uint8Array - * @returns {Uint8Array} Array with the KDFParams value - */ - write() { - return new Uint8Array([3, 1, this.hash, this.cipher]); - } - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - /** - * Encrypts data using specified algorithm and public key parameters. - * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} for public key algorithms. - * @param {module:enums.publicKey} algo - Public key algorithm - * @param {Object} publicParams - Algorithm-specific public key parameters - * @param {Uint8Array} data - Data to be encrypted - * @param {Uint8Array} fingerprint - Recipient fingerprint - * @returns {Promise} Encrypted session key parameters. - * @async - */ - async function publicKeyEncrypt(algo, publicParams, data, fingerprint) { - switch (algo) { - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaEncryptSign: { - const { n, e } = publicParams; - const c = await publicKey.rsa.encrypt(data, n, e); - return { c }; - } - case enums.publicKey.elgamal: { - const { p, g, y } = publicParams; - return publicKey.elgamal.encrypt(data, p, g, y); - } - case enums.publicKey.ecdh: { - const { oid, Q, kdfParams } = publicParams; - const { publicKey: V, wrappedKey: C } = await publicKey.elliptic.ecdh.encrypt( - oid, kdfParams, data, Q, fingerprint); - return { V, C: new ECDHSymmetricKey(C) }; - } - default: - return []; - } - } - - /** - * Decrypts data using specified algorithm and private key parameters. - * See {@link https://tools.ietf.org/html/rfc4880#section-5.5.3|RFC 4880 5.5.3} - * @param {module:enums.publicKey} algo - Public key algorithm - * @param {Object} publicKeyParams - Algorithm-specific public key parameters - * @param {Object} privateKeyParams - Algorithm-specific private key parameters - * @param {Object} sessionKeyParams - Encrypted session key parameters - * @param {Uint8Array} fingerprint - Recipient fingerprint - * @param {Uint8Array} [randomPayload] - Data to return on decryption error, instead of throwing - * (needed for constant-time processing in RSA and ElGamal) - * @returns {Promise} Decrypted data. - * @throws {Error} on sensitive decryption error, unless `randomPayload` is given - * @async - */ - async function publicKeyDecrypt(algo, publicKeyParams, privateKeyParams, sessionKeyParams, fingerprint, randomPayload) { - switch (algo) { - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaEncrypt: { - const { c } = sessionKeyParams; - const { n, e } = publicKeyParams; - const { d, p, q, u } = privateKeyParams; - return publicKey.rsa.decrypt(c, n, e, d, p, q, u, randomPayload); - } - case enums.publicKey.elgamal: { - const { c1, c2 } = sessionKeyParams; - const p = publicKeyParams.p; - const x = privateKeyParams.x; - return publicKey.elgamal.decrypt(c1, c2, p, x, randomPayload); - } - case enums.publicKey.ecdh: { - const { oid, Q, kdfParams } = publicKeyParams; - const { d } = privateKeyParams; - const { V, C } = sessionKeyParams; - return publicKey.elliptic.ecdh.decrypt( - oid, kdfParams, V, C.data, Q, d, fingerprint); - } - default: - throw new Error('Invalid public key encryption algorithm.'); - } - } - - /** - * Parse public key material in binary form to get the key parameters - * @param {module:enums.publicKey} algo - The key algorithm - * @param {Uint8Array} bytes - The key material to parse - * @returns {{ read: Number, publicParams: Object }} Number of read bytes plus key parameters referenced by name. - */ - function parsePublicKeyParams(algo, bytes) { - let read = 0; - switch (algo) { - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaSign: { - const n = util.readMPI(bytes.subarray(read)); read += n.length + 2; - const e = util.readMPI(bytes.subarray(read)); read += e.length + 2; - return { read, publicParams: { n, e } }; - } - case enums.publicKey.dsa: { - const p = util.readMPI(bytes.subarray(read)); read += p.length + 2; - const q = util.readMPI(bytes.subarray(read)); read += q.length + 2; - const g = util.readMPI(bytes.subarray(read)); read += g.length + 2; - const y = util.readMPI(bytes.subarray(read)); read += y.length + 2; - return { read, publicParams: { p, q, g, y } }; - } - case enums.publicKey.elgamal: { - const p = util.readMPI(bytes.subarray(read)); read += p.length + 2; - const g = util.readMPI(bytes.subarray(read)); read += g.length + 2; - const y = util.readMPI(bytes.subarray(read)); read += y.length + 2; - return { read, publicParams: { p, g, y } }; - } - case enums.publicKey.ecdsa: { - const oid = new OID(); read += oid.read(bytes); - const Q = util.readMPI(bytes.subarray(read)); read += Q.length + 2; - return { read: read, publicParams: { oid, Q } }; - } - case enums.publicKey.eddsa: { - const oid = new OID(); read += oid.read(bytes); - let Q = util.readMPI(bytes.subarray(read)); read += Q.length + 2; - Q = util.leftPad(Q, 33); - return { read: read, publicParams: { oid, Q } }; - } - case enums.publicKey.ecdh: { - const oid = new OID(); read += oid.read(bytes); - const Q = util.readMPI(bytes.subarray(read)); read += Q.length + 2; - const kdfParams = new KDFParams(); read += kdfParams.read(bytes.subarray(read)); - return { read: read, publicParams: { oid, Q, kdfParams } }; - } - default: - throw new Error('Invalid public key encryption algorithm.'); - } - } - - /** - * Parse private key material in binary form to get the key parameters - * @param {module:enums.publicKey} algo - The key algorithm - * @param {Uint8Array} bytes - The key material to parse - * @param {Object} publicParams - (ECC only) public params, needed to format some private params - * @returns {{ read: Number, privateParams: Object }} Number of read bytes plus the key parameters referenced by name. - */ - function parsePrivateKeyParams(algo, bytes, publicParams) { - let read = 0; - switch (algo) { - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaSign: { - const d = util.readMPI(bytes.subarray(read)); read += d.length + 2; - const p = util.readMPI(bytes.subarray(read)); read += p.length + 2; - const q = util.readMPI(bytes.subarray(read)); read += q.length + 2; - const u = util.readMPI(bytes.subarray(read)); read += u.length + 2; - return { read, privateParams: { d, p, q, u } }; - } - case enums.publicKey.dsa: - case enums.publicKey.elgamal: { - const x = util.readMPI(bytes.subarray(read)); read += x.length + 2; - return { read, privateParams: { x } }; - } - case enums.publicKey.ecdsa: - case enums.publicKey.ecdh: { - const curve = new Curve(publicParams.oid); - let d = util.readMPI(bytes.subarray(read)); read += d.length + 2; - d = util.leftPad(d, curve.payloadSize); - return { read, privateParams: { d } }; - } - case enums.publicKey.eddsa: { - let seed = util.readMPI(bytes.subarray(read)); read += seed.length + 2; - seed = util.leftPad(seed, 32); - return { read, privateParams: { seed } }; - } - default: - throw new Error('Invalid public key encryption algorithm.'); - } - } - - /** Returns the types comprising the encrypted session key of an algorithm - * @param {module:enums.publicKey} algo - The key algorithm - * @param {Uint8Array} bytes - The key material to parse - * @returns {Object} The session key parameters referenced by name. - */ - function parseEncSessionKeyParams(algo, bytes) { - let read = 0; - switch (algo) { - // Algorithm-Specific Fields for RSA encrypted session keys: - // - MPI of RSA encrypted value m**e mod n. - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaEncryptSign: { - const c = util.readMPI(bytes.subarray(read)); - return { c }; - } - - // Algorithm-Specific Fields for Elgamal encrypted session keys: - // - MPI of Elgamal value g**k mod p - // - MPI of Elgamal value m * y**k mod p - case enums.publicKey.elgamal: { - const c1 = util.readMPI(bytes.subarray(read)); read += c1.length + 2; - const c2 = util.readMPI(bytes.subarray(read)); - return { c1, c2 }; - } - // Algorithm-Specific Fields for ECDH encrypted session keys: - // - MPI containing the ephemeral key used to establish the shared secret - // - ECDH Symmetric Key - case enums.publicKey.ecdh: { - const V = util.readMPI(bytes.subarray(read)); read += V.length + 2; - const C = new ECDHSymmetricKey(); C.read(bytes.subarray(read)); - return { V, C }; - } - default: - throw new Error('Invalid public key encryption algorithm.'); - } - } - - /** - * Convert params to MPI and serializes them in the proper order - * @param {module:enums.publicKey} algo - The public key algorithm - * @param {Object} params - The key parameters indexed by name - * @returns {Uint8Array} The array containing the MPIs. - */ - function serializeParams(algo, params) { - const orderedParams = Object.keys(params).map(name => { - const param = params[name]; - return util.isUint8Array(param) ? util.uint8ArrayToMPI(param) : param.write(); - }); - return util.concatUint8Array(orderedParams); - } - - /** - * Generate algorithm-specific key parameters - * @param {module:enums.publicKey} algo - The public key algorithm - * @param {Integer} bits - Bit length for RSA keys - * @param {module:type/oid} oid - Object identifier for ECC keys - * @returns {Promise<{ publicParams: {Object}, privateParams: {Object} }>} The parameters referenced by name. - * @async - */ - function generateParams(algo, bits, oid) { - switch (algo) { - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaSign: { - return publicKey.rsa.generate(bits, 65537).then(({ n, e, d, p, q, u }) => ({ - privateParams: { d, p, q, u }, - publicParams: { n, e } - })); - } - case enums.publicKey.ecdsa: - return publicKey.elliptic.generate(oid).then(({ oid, Q, secret }) => ({ - privateParams: { d: secret }, - publicParams: { oid: new OID(oid), Q } - })); - case enums.publicKey.eddsa: - return publicKey.elliptic.generate(oid).then(({ oid, Q, secret }) => ({ - privateParams: { seed: secret }, - publicParams: { oid: new OID(oid), Q } - })); - case enums.publicKey.ecdh: - return publicKey.elliptic.generate(oid).then(({ oid, Q, secret, hash, cipher }) => ({ - privateParams: { d: secret }, - publicParams: { - oid: new OID(oid), - Q, - kdfParams: new KDFParams({ hash, cipher }) - } - })); - case enums.publicKey.dsa: - case enums.publicKey.elgamal: - throw new Error('Unsupported algorithm for key generation.'); - default: - throw new Error('Invalid public key algorithm.'); - } - } - - /** - * Validate algorithm-specific key parameters - * @param {module:enums.publicKey} algo - The public key algorithm - * @param {Object} publicParams - Algorithm-specific public key parameters - * @param {Object} privateParams - Algorithm-specific private key parameters - * @returns {Promise} Whether the parameters are valid. - * @async - */ - async function validateParams$4(algo, publicParams, privateParams) { - if (!publicParams || !privateParams) { - throw new Error('Missing key parameters'); - } - switch (algo) { - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaSign: { - const { n, e } = publicParams; - const { d, p, q, u } = privateParams; - return publicKey.rsa.validateParams(n, e, d, p, q, u); - } - case enums.publicKey.dsa: { - const { p, q, g, y } = publicParams; - const { x } = privateParams; - return publicKey.dsa.validateParams(p, q, g, y, x); - } - case enums.publicKey.elgamal: { - const { p, g, y } = publicParams; - const { x } = privateParams; - return publicKey.elgamal.validateParams(p, g, y, x); - } - case enums.publicKey.ecdsa: - case enums.publicKey.ecdh: { - const algoModule = publicKey.elliptic[enums.read(enums.publicKey, algo)]; - const { oid, Q } = publicParams; - const { d } = privateParams; - return algoModule.validateParams(oid, Q, d); - } - case enums.publicKey.eddsa: { - const { oid, Q } = publicParams; - const { seed } = privateParams; - return publicKey.elliptic.eddsa.validateParams(oid, Q, seed); - } - default: - throw new Error('Invalid public key algorithm.'); - } - } - - /** - * Generates a random byte prefix for the specified algorithm - * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. - * @param {module:enums.symmetric} algo - Symmetric encryption algorithm - * @returns {Promise} Random bytes with length equal to the block size of the cipher, plus the last two bytes repeated. - * @async - */ - async function getPrefixRandom(algo) { - const { blockSize } = getCipher(algo); - const prefixrandom = await getRandomBytes(blockSize); - const repeat = new Uint8Array([prefixrandom[prefixrandom.length - 2], prefixrandom[prefixrandom.length - 1]]); - return util.concat([prefixrandom, repeat]); - } - - /** - * Generating a session key for the specified symmetric algorithm - * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. - * @param {module:enums.symmetric} algo - Symmetric encryption algorithm - * @returns {Promise} Random bytes as a string to be used as a key. - * @async - */ - function generateSessionKey(algo) { - const { keySize } = getCipher(algo); - return getRandomBytes(keySize); - } - - /** - * Get implementation of the given AEAD mode - * @param {enums.aead} algo - * @returns {Object} - * @throws {Error} on invalid algo - */ - function getAEADMode(algo) { - const algoName = enums.read(enums.aead, algo); - return mode[algoName]; - } - - /** - * Get implementation of the given cipher - * @param {enums.symmetric} algo - * @returns {Object} - * @throws {Error} on invalid algo - */ - function getCipher(algo) { - const algoName = enums.read(enums.symmetric, algo); - return cipher[algoName]; - } - - var crypto$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - publicKeyEncrypt: publicKeyEncrypt, - publicKeyDecrypt: publicKeyDecrypt, - parsePublicKeyParams: parsePublicKeyParams, - parsePrivateKeyParams: parsePrivateKeyParams, - parseEncSessionKeyParams: parseEncSessionKeyParams, - serializeParams: serializeParams, - generateParams: generateParams, - validateParams: validateParams$4, - getPrefixRandom: getPrefixRandom, - generateSessionKey: generateSessionKey, - getAEADMode: getAEADMode, - getCipher: getCipher - }); - - // OpenPGP.js - An OpenPGP implementation in javascript - - const webCrypto$8 = util.getWebCrypto(); - const nodeCrypto$9 = util.getNodeCrypto(); - - /** - * Validate ECDH parameters - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {Uint8Array} Q - ECDH public point - * @param {Uint8Array} d - ECDH secret scalar - * @returns {Promise} Whether params are valid. - * @async - */ - async function validateParams$5(oid, Q, d) { - return validateStandardParams(enums.publicKey.ecdh, oid, Q, d); - } - - // Build Param for ECDH algorithm (RFC 6637) - function buildEcdhParam(public_algo, oid, kdfParams, fingerprint) { - return util.concatUint8Array([ - oid.write(), - new Uint8Array([public_algo]), - kdfParams.write(), - util.stringToUint8Array('Anonymous Sender '), - fingerprint.subarray(0, 20) - ]); - } - - // Key Derivation Function (RFC 6637) - async function kdf(hashAlgo, X, length, param, stripLeading = false, stripTrailing = false) { - // Note: X is little endian for Curve25519, big-endian for all others. - // This is not ideal, but the RFC's are unclear - // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B - let i; - if (stripLeading) { - // Work around old go crypto bug - for (i = 0; i < X.length && X[i] === 0; i++); - X = X.subarray(i); - } - if (stripTrailing) { - // Work around old OpenPGP.js bug - for (i = X.length - 1; i >= 0 && X[i] === 0; i--); - X = X.subarray(0, i + 1); - } - const digest = await hash.digest(hashAlgo, util.concatUint8Array([ - new Uint8Array([0, 0, 0, 1]), - X, - param - ])); - return digest.subarray(0, length); - } - - /** - * Generate ECDHE ephemeral key and secret from public key - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} Q - Recipient public key - * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ - async function genPublicEphemeralKey(curve, Q) { - switch (curve.type) { - case 'curve25519': { - const d = await getRandomBytes(32); - const { secretKey, sharedKey } = await genPrivateEphemeralKey(curve, Q, null, d); - let { publicKey } = naclFastLight.box.keyPair.fromSecretKey(secretKey); - publicKey = util.concatUint8Array([new Uint8Array([0x40]), publicKey]); - return { publicKey, sharedKey }; // Note: sharedKey is little-endian here, unlike below - } - case 'web': - if (curve.web && util.getWebCrypto()) { - try { - return await webPublicEphemeralKey(curve, Q); - } catch (err) { - util.printDebugError(err); - } - } - break; - case 'node': - return nodePublicEphemeralKey(curve, Q); - } - return ellipticPublicEphemeralKey(curve, Q); - } - - /** - * Encrypt and wrap a session key - * - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {module:type/kdf_params} kdfParams - KDF params including cipher and algorithm to use - * @param {Uint8Array} data - Unpadded session key data - * @param {Uint8Array} Q - Recipient public key - * @param {Uint8Array} fingerprint - Recipient fingerprint - * @returns {Promise<{publicKey: Uint8Array, wrappedKey: Uint8Array}>} - * @async - */ - async function encrypt$3(oid, kdfParams, data, Q, fingerprint) { - const m = encode$1(data); - - const curve = new Curve(oid); - const { publicKey, sharedKey } = await genPublicEphemeralKey(curve, Q); - const param = buildEcdhParam(enums.publicKey.ecdh, oid, kdfParams, fingerprint); - const { keySize } = getCipher(kdfParams.cipher); - const Z = await kdf(kdfParams.hash, sharedKey, keySize, param); - const wrappedKey = wrap(Z, m); - return { publicKey, wrappedKey }; - } - - /** - * Generate ECDHE secret from private key and public part of ephemeral key - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} V - Public part of ephemeral key - * @param {Uint8Array} Q - Recipient public key - * @param {Uint8Array} d - Recipient private key - * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ - async function genPrivateEphemeralKey(curve, V, Q, d) { - if (d.length !== curve.payloadSize) { - const privateKey = new Uint8Array(curve.payloadSize); - privateKey.set(d, curve.payloadSize - d.length); - d = privateKey; - } - switch (curve.type) { - case 'curve25519': { - const secretKey = d.slice().reverse(); - const sharedKey = naclFastLight.scalarMult(secretKey, V.subarray(1)); - return { secretKey, sharedKey }; // Note: sharedKey is little-endian here, unlike below - } - case 'web': - if (curve.web && util.getWebCrypto()) { - try { - return await webPrivateEphemeralKey(curve, V, Q, d); - } catch (err) { - util.printDebugError(err); - } - } - break; - case 'node': - return nodePrivateEphemeralKey(curve, V, d); - } - return ellipticPrivateEphemeralKey(curve, V, d); - } - - /** - * Decrypt and unwrap the value derived from session key - * - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {module:type/kdf_params} kdfParams - KDF params including cipher and algorithm to use - * @param {Uint8Array} V - Public part of ephemeral key - * @param {Uint8Array} C - Encrypted and wrapped value derived from session key - * @param {Uint8Array} Q - Recipient public key - * @param {Uint8Array} d - Recipient private key - * @param {Uint8Array} fingerprint - Recipient fingerprint - * @returns {Promise} Value derived from session key. - * @async - */ - async function decrypt$3(oid, kdfParams, V, C, Q, d, fingerprint) { - const curve = new Curve(oid); - const { sharedKey } = await genPrivateEphemeralKey(curve, V, Q, d); - const param = buildEcdhParam(enums.publicKey.ecdh, oid, kdfParams, fingerprint); - const { keySize } = getCipher(kdfParams.cipher); - let err; - for (let i = 0; i < 3; i++) { - try { - // Work around old go crypto bug and old OpenPGP.js bug, respectively. - const Z = await kdf(kdfParams.hash, sharedKey, keySize, param, i === 1, i === 2); - return decode$1(unwrap(Z, C)); - } catch (e) { - err = e; - } - } - throw err; - } - - /** - * Generate ECDHE secret from private key and public part of ephemeral key using webCrypto - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} V - Public part of ephemeral key - * @param {Uint8Array} Q - Recipient public key - * @param {Uint8Array} d - Recipient private key - * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ - async function webPrivateEphemeralKey(curve, V, Q, d) { - const recipient = privateToJWK$1(curve.payloadSize, curve.web.web, Q, d); - let privateKey = webCrypto$8.importKey( - 'jwk', - recipient, - { - name: 'ECDH', - namedCurve: curve.web.web - }, - true, - ['deriveKey', 'deriveBits'] - ); - const jwk = rawPublicToJWK(curve.payloadSize, curve.web.web, V); - let sender = webCrypto$8.importKey( - 'jwk', - jwk, - { - name: 'ECDH', - namedCurve: curve.web.web - }, - true, - [] - ); - [privateKey, sender] = await Promise.all([privateKey, sender]); - let S = webCrypto$8.deriveBits( - { - name: 'ECDH', - namedCurve: curve.web.web, - public: sender - }, - privateKey, - curve.web.sharedSize - ); - let secret = webCrypto$8.exportKey( - 'jwk', - privateKey - ); - [S, secret] = await Promise.all([S, secret]); - const sharedKey = new Uint8Array(S); - const secretKey = b64ToUint8Array(secret.d); - return { secretKey, sharedKey }; - } - - /** - * Generate ECDHE ephemeral key and secret from public key using webCrypto - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} Q - Recipient public key - * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ - async function webPublicEphemeralKey(curve, Q) { - const jwk = rawPublicToJWK(curve.payloadSize, curve.web.web, Q); - let keyPair = webCrypto$8.generateKey( - { - name: 'ECDH', - namedCurve: curve.web.web - }, - true, - ['deriveKey', 'deriveBits'] - ); - let recipient = webCrypto$8.importKey( - 'jwk', - jwk, - { - name: 'ECDH', - namedCurve: curve.web.web - }, - false, - [] - ); - [keyPair, recipient] = await Promise.all([keyPair, recipient]); - let s = webCrypto$8.deriveBits( - { - name: 'ECDH', - namedCurve: curve.web.web, - public: recipient - }, - keyPair.privateKey, - curve.web.sharedSize - ); - let p = webCrypto$8.exportKey( - 'jwk', - keyPair.publicKey - ); - [s, p] = await Promise.all([s, p]); - const sharedKey = new Uint8Array(s); - const publicKey = new Uint8Array(jwkToRawPublic(p)); - return { publicKey, sharedKey }; - } - - /** - * Generate ECDHE secret from private key and public part of ephemeral key using indutny/elliptic - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} V - Public part of ephemeral key - * @param {Uint8Array} d - Recipient private key - * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ - async function ellipticPrivateEphemeralKey(curve, V, d) { - const indutnyCurve = await getIndutnyCurve(curve.name); - V = keyFromPublic(indutnyCurve, V); - d = keyFromPrivate(indutnyCurve, d); - const secretKey = new Uint8Array(d.getPrivate()); - const S = d.derive(V.getPublic()); - const len = indutnyCurve.curve.p.byteLength(); - const sharedKey = S.toArrayLike(Uint8Array, 'be', len); - return { secretKey, sharedKey }; - } - - /** - * Generate ECDHE ephemeral key and secret from public key using indutny/elliptic - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} Q - Recipient public key - * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ - async function ellipticPublicEphemeralKey(curve, Q) { - const indutnyCurve = await getIndutnyCurve(curve.name); - const v = await curve.genKeyPair(); - Q = keyFromPublic(indutnyCurve, Q); - const V = keyFromPrivate(indutnyCurve, v.privateKey); - const publicKey = v.publicKey; - const S = V.derive(Q.getPublic()); - const len = indutnyCurve.curve.p.byteLength(); - const sharedKey = S.toArrayLike(Uint8Array, 'be', len); - return { publicKey, sharedKey }; - } - - /** - * Generate ECDHE secret from private key and public part of ephemeral key using nodeCrypto - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} V - Public part of ephemeral key - * @param {Uint8Array} d - Recipient private key - * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ - async function nodePrivateEphemeralKey(curve, V, d) { - const recipient = nodeCrypto$9.createECDH(curve.node.node); - recipient.setPrivateKey(d); - const sharedKey = new Uint8Array(recipient.computeSecret(V)); - const secretKey = new Uint8Array(recipient.getPrivateKey()); - return { secretKey, sharedKey }; - } - - /** - * Generate ECDHE ephemeral key and secret from public key using nodeCrypto - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} Q - Recipient public key - * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ - async function nodePublicEphemeralKey(curve, Q) { - const sender = nodeCrypto$9.createECDH(curve.node.node); - sender.generateKeys(); - const sharedKey = new Uint8Array(sender.computeSecret(Q)); - const publicKey = new Uint8Array(sender.getPublicKey()); - return { publicKey, sharedKey }; - } - - var ecdh = /*#__PURE__*/Object.freeze({ - __proto__: null, - validateParams: validateParams$5, - encrypt: encrypt$3, - decrypt: decrypt$3 - }); - - // OpenPGP.js - An OpenPGP implementation in javascript - - var elliptic = /*#__PURE__*/Object.freeze({ - __proto__: null, - Curve: Curve, - ecdh: ecdh, - ecdsa: ecdsa, - eddsa: eddsa, - generate: generate$1, - getPreferredHashAlgo: getPreferredHashAlgo - }); - - // GPG4Browsers - An OpenPGP implementation in javascript - - /* - TODO regarding the hash function, read: - https://tools.ietf.org/html/rfc4880#section-13.6 - https://tools.ietf.org/html/rfc4880#section-14 - */ - - /** - * DSA Sign function - * @param {Integer} hashAlgo - * @param {Uint8Array} hashed - * @param {Uint8Array} g - * @param {Uint8Array} p - * @param {Uint8Array} q - * @param {Uint8Array} x - * @returns {Promise<{ r: Uint8Array, s: Uint8Array }>} - * @async - */ - async function sign$3(hashAlgo, hashed, g, p, q, x) { - const BigInteger = await util.getBigInteger(); - const one = new BigInteger(1); - p = new BigInteger(p); - q = new BigInteger(q); - g = new BigInteger(g); - x = new BigInteger(x); - - let k; - let r; - let s; - let t; - g = g.mod(p); - x = x.mod(q); - // If the output size of the chosen hash is larger than the number of - // bits of q, the hash result is truncated to fit by taking the number - // of leftmost bits equal to the number of bits of q. This (possibly - // truncated) hash function result is treated as a number and used - // directly in the DSA signature algorithm. - const h = new BigInteger(hashed.subarray(0, q.byteLength())).mod(q); - // FIPS-186-4, section 4.6: - // The values of r and s shall be checked to determine if r = 0 or s = 0. - // If either r = 0 or s = 0, a new value of k shall be generated, and the - // signature shall be recalculated. It is extremely unlikely that r = 0 - // or s = 0 if signatures are generated properly. - while (true) { - // See Appendix B here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - k = await getRandomBigInteger(one, q); // returns in [1, q-1] - r = g.modExp(k, p).imod(q); // (g**k mod p) mod q - if (r.isZero()) { - continue; - } - const xr = x.mul(r).imod(q); - t = h.add(xr).imod(q); // H(m) + x*r mod q - s = k.modInv(q).imul(t).imod(q); // k**-1 * (H(m) + x*r) mod q - if (s.isZero()) { - continue; - } - break; - } - return { - r: r.toUint8Array('be', q.byteLength()), - s: s.toUint8Array('be', q.byteLength()) - }; - } - - /** - * DSA Verify function - * @param {Integer} hashAlgo - * @param {Uint8Array} r - * @param {Uint8Array} s - * @param {Uint8Array} hashed - * @param {Uint8Array} g - * @param {Uint8Array} p - * @param {Uint8Array} q - * @param {Uint8Array} y - * @returns {boolean} - * @async - */ - async function verify$3(hashAlgo, r, s, hashed, g, p, q, y) { - const BigInteger = await util.getBigInteger(); - const zero = new BigInteger(0); - r = new BigInteger(r); - s = new BigInteger(s); - - p = new BigInteger(p); - q = new BigInteger(q); - g = new BigInteger(g); - y = new BigInteger(y); - - if (r.lte(zero) || r.gte(q) || - s.lte(zero) || s.gte(q)) { - util.printDebug('invalid DSA Signature'); - return false; - } - const h = new BigInteger(hashed.subarray(0, q.byteLength())).imod(q); - const w = s.modInv(q); // s**-1 mod q - if (w.isZero()) { - util.printDebug('invalid DSA Signature'); - return false; - } - - g = g.mod(p); - y = y.mod(p); - const u1 = h.mul(w).imod(q); // H(m) * w mod q - const u2 = r.mul(w).imod(q); // r * w mod q - const t1 = g.modExp(u1, p); // g**u1 mod p - const t2 = y.modExp(u2, p); // y**u2 mod p - const v = t1.mul(t2).imod(p).imod(q); // (g**u1 * y**u2 mod p) mod q - return v.equal(r); - } - - /** - * Validate DSA parameters - * @param {Uint8Array} p - DSA prime - * @param {Uint8Array} q - DSA group order - * @param {Uint8Array} g - DSA sub-group generator - * @param {Uint8Array} y - DSA public key - * @param {Uint8Array} x - DSA private key - * @returns {Promise} Whether params are valid. - * @async - */ - async function validateParams$6(p, q, g, y, x) { - const BigInteger = await util.getBigInteger(); - p = new BigInteger(p); - q = new BigInteger(q); - g = new BigInteger(g); - y = new BigInteger(y); - const one = new BigInteger(1); - // Check that 1 < g < p - if (g.lte(one) || g.gte(p)) { - return false; - } - - /** - * Check that subgroup order q divides p-1 - */ - if (!p.dec().mod(q).isZero()) { - return false; - } - - /** - * g has order q - * Check that g ** q = 1 mod p - */ - if (!g.modExp(q, p).isOne()) { - return false; - } - - /** - * Check q is large and probably prime (we mainly want to avoid small factors) - */ - const qSize = new BigInteger(q.bitLength()); - const n150 = new BigInteger(150); - if (qSize.lt(n150) || !(await isProbablePrime(q, null, 32))) { - return false; - } - - /** - * Re-derive public key y' = g ** x mod p - * Expect y == y' - * - * Blinded exponentiation computes g**{rq + x} to compare to y - */ - x = new BigInteger(x); - const two = new BigInteger(2); - const r = await getRandomBigInteger(two.leftShift(qSize.dec()), two.leftShift(qSize)); // draw r of same size as q - const rqx = q.mul(r).add(x); - if (!y.equal(g.modExp(rqx, p))) { - return false; - } - - return true; - } - - var dsa = /*#__PURE__*/Object.freeze({ - __proto__: null, - sign: sign$3, - verify: verify$3, - validateParams: validateParams$6 - }); - - /** - * @fileoverview Asymmetric cryptography functions - * @module crypto/public_key - * @private - */ - - var publicKey = { - /** @see module:crypto/public_key/rsa */ - rsa: rsa, - /** @see module:crypto/public_key/elgamal */ - elgamal: elgamal, - /** @see module:crypto/public_key/elliptic */ - elliptic: elliptic, - /** @see module:crypto/public_key/dsa */ - dsa: dsa, - /** @see tweetnacl */ - nacl: naclFastLight - }; - - /** - * @fileoverview Provides functions for asymmetric signing and signature verification - * @module crypto/signature - * @private - */ - - /** - * Parse signature in binary form to get the parameters. - * The returned values are only padded for EdDSA, since in the other cases their expected length - * depends on the key params, hence we delegate the padding to the signature verification function. - * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} - * See {@link https://tools.ietf.org/html/rfc4880#section-5.2.2|RFC 4880 5.2.2.} - * @param {module:enums.publicKey} algo - Public key algorithm - * @param {Uint8Array} signature - Data for which the signature was created - * @returns {Promise} True if signature is valid. - * @async - */ - function parseSignatureParams(algo, signature) { - let read = 0; - switch (algo) { - // Algorithm-Specific Fields for RSA signatures: - // - MPI of RSA signature value m**d mod n. - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaSign: { - const s = util.readMPI(signature.subarray(read)); - // The signature needs to be the same length as the public key modulo n. - // We pad s on signature verification, where we have access to n. - return { s }; - } - // Algorithm-Specific Fields for DSA or ECDSA signatures: - // - MPI of DSA or ECDSA value r. - // - MPI of DSA or ECDSA value s. - case enums.publicKey.dsa: - case enums.publicKey.ecdsa: - { - const r = util.readMPI(signature.subarray(read)); read += r.length + 2; - const s = util.readMPI(signature.subarray(read)); - return { r, s }; - } - // Algorithm-Specific Fields for EdDSA signatures: - // - MPI of an EC point r. - // - EdDSA value s, in MPI, in the little endian representation - case enums.publicKey.eddsa: { - // When parsing little-endian MPI data, we always need to left-pad it, as done with big-endian values: - // https://www.ietf.org/archive/id/draft-ietf-openpgp-rfc4880bis-10.html#section-3.2-9 - let r = util.readMPI(signature.subarray(read)); read += r.length + 2; - r = util.leftPad(r, 32); - let s = util.readMPI(signature.subarray(read)); - s = util.leftPad(s, 32); - return { r, s }; - } - default: - throw new Error('Invalid signature algorithm.'); - } - } - - /** - * Verifies the signature provided for data using specified algorithms and public key parameters. - * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} - * and {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4} - * for public key and hash algorithms. - * @param {module:enums.publicKey} algo - Public key algorithm - * @param {module:enums.hash} hashAlgo - Hash algorithm - * @param {Object} signature - Named algorithm-specific signature parameters - * @param {Object} publicParams - Algorithm-specific public key parameters - * @param {Uint8Array} data - Data for which the signature was created - * @param {Uint8Array} hashed - The hashed data - * @returns {Promise} True if signature is valid. - * @async - */ - async function verify$4(algo, hashAlgo, signature, publicParams, data, hashed) { - switch (algo) { - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaSign: { - const { n, e } = publicParams; - const s = util.leftPad(signature.s, n.length); // padding needed for webcrypto and node crypto - return publicKey.rsa.verify(hashAlgo, data, s, n, e, hashed); - } - case enums.publicKey.dsa: { - const { g, p, q, y } = publicParams; - const { r, s } = signature; // no need to pad, since we always handle them as BigIntegers - return publicKey.dsa.verify(hashAlgo, r, s, hashed, g, p, q, y); - } - case enums.publicKey.ecdsa: { - const { oid, Q } = publicParams; - const curveSize = new publicKey.elliptic.Curve(oid).payloadSize; - // padding needed for webcrypto - const r = util.leftPad(signature.r, curveSize); - const s = util.leftPad(signature.s, curveSize); - return publicKey.elliptic.ecdsa.verify(oid, hashAlgo, { r, s }, data, Q, hashed); - } - case enums.publicKey.eddsa: { - const { oid, Q } = publicParams; - // signature already padded on parsing - return publicKey.elliptic.eddsa.verify(oid, hashAlgo, signature, data, Q, hashed); - } - default: - throw new Error('Invalid signature algorithm.'); - } - } - - /** - * Creates a signature on data using specified algorithms and private key parameters. - * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} - * and {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4} - * for public key and hash algorithms. - * @param {module:enums.publicKey} algo - Public key algorithm - * @param {module:enums.hash} hashAlgo - Hash algorithm - * @param {Object} publicKeyParams - Algorithm-specific public and private key parameters - * @param {Object} privateKeyParams - Algorithm-specific public and private key parameters - * @param {Uint8Array} data - Data to be signed - * @param {Uint8Array} hashed - The hashed data - * @returns {Promise} Signature Object containing named signature parameters. - * @async - */ - async function sign$4(algo, hashAlgo, publicKeyParams, privateKeyParams, data, hashed) { - if (!publicKeyParams || !privateKeyParams) { - throw new Error('Missing key parameters'); - } - switch (algo) { - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaSign: { - const { n, e } = publicKeyParams; - const { d, p, q, u } = privateKeyParams; - const s = await publicKey.rsa.sign(hashAlgo, data, n, e, d, p, q, u, hashed); - return { s }; - } - case enums.publicKey.dsa: { - const { g, p, q } = publicKeyParams; - const { x } = privateKeyParams; - return publicKey.dsa.sign(hashAlgo, hashed, g, p, q, x); - } - case enums.publicKey.elgamal: { - throw new Error('Signing with Elgamal is not defined in the OpenPGP standard.'); - } - case enums.publicKey.ecdsa: { - const { oid, Q } = publicKeyParams; - const { d } = privateKeyParams; - return publicKey.elliptic.ecdsa.sign(oid, hashAlgo, data, Q, d, hashed); - } - case enums.publicKey.eddsa: { - const { oid, Q } = publicKeyParams; - const { seed } = privateKeyParams; - return publicKey.elliptic.eddsa.sign(oid, hashAlgo, data, Q, seed, hashed); - } - default: - throw new Error('Invalid signature algorithm.'); - } - } - - var signature = /*#__PURE__*/Object.freeze({ - __proto__: null, - parseSignatureParams: parseSignatureParams, - verify: verify$4, - sign: sign$4 - }); - - /** - * @fileoverview Provides access to all cryptographic primitives used in OpenPGP.js - * @see module:crypto/crypto - * @see module:crypto/signature - * @see module:crypto/public_key - * @see module:crypto/cipher - * @see module:crypto/random - * @see module:crypto/hash - * @module crypto - * @private - */ - - // TODO move cfb and gcm to cipher - const mod = { - /** @see module:crypto/cipher */ - cipher: cipher, - /** @see module:crypto/hash */ - hash: hash, - /** @see module:crypto/mode */ - mode: mode, - /** @see module:crypto/public_key */ - publicKey: publicKey, - /** @see module:crypto/signature */ - signature: signature, - /** @see module:crypto/random */ - random: random, - /** @see module:crypto/pkcs1 */ - pkcs1: pkcs1, - /** @see module:crypto/pkcs5 */ - pkcs5: pkcs5, - /** @see module:crypto/aes_kw */ - aesKW: aesKW - }; - - Object.assign(mod, crypto$1); - - var TYPED_OK = typeof Uint8Array !== "undefined" && - typeof Uint16Array !== "undefined" && - typeof Int32Array !== "undefined"; - - - // reduce buffer size, avoiding mem copy - function shrinkBuf(buf, size) { - if (buf.length === size) { - return buf; - } - if (buf.subarray) { - return buf.subarray(0, size); - } - buf.length = size; - return buf; - } - - - const fnTyped = { - arraySet: function (dest, src, src_offs, len, dest_offs) { - if (src.subarray && dest.subarray) { - dest.set(src.subarray(src_offs, src_offs + len), dest_offs); - return; - } - // Fallback to ordinary array - for (let i = 0; i < len; i++) { - dest[dest_offs + i] = src[src_offs + i]; - } - }, - // Join array of chunks to single array. - flattenChunks: function (chunks) { - let i, l, len, pos, chunk; - - // calculate data length - len = 0; - for (i = 0, l = chunks.length; i < l; i++) { - len += chunks[i].length; - } - - // join chunks - const result = new Uint8Array(len); - pos = 0; - for (i = 0, l = chunks.length; i < l; i++) { - chunk = chunks[i]; - result.set(chunk, pos); - pos += chunk.length; - } - - return result; - } - }; - - const fnUntyped = { - arraySet: function (dest, src, src_offs, len, dest_offs) { - for (let i = 0; i < len; i++) { - dest[dest_offs + i] = src[src_offs + i]; - } - }, - // Join array of chunks to single array. - flattenChunks: function (chunks) { - return [].concat.apply([], chunks); - } - }; - - - // Enable/Disable typed arrays use, for testing - // - - let Buf8 = TYPED_OK ? Uint8Array : Array; - let Buf16 = TYPED_OK ? Uint16Array : Array; - let Buf32 = TYPED_OK ? Int32Array : Array; - let flattenChunks = TYPED_OK ? fnTyped.flattenChunks : fnUntyped.flattenChunks; - let arraySet = TYPED_OK ? fnTyped.arraySet : fnUntyped.arraySet; - - // (C) 1995-2013 Jean-loup Gailly and Mark Adler - // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin - // - // This software is provided 'as-is', without any express or implied - // warranty. In no event will the authors be held liable for any damages - // arising from the use of this software. - // - // Permission is granted to anyone to use this software for any purpose, - // including commercial applications, and to alter it and redistribute it - // freely, subject to the following restrictions: - // - // 1. The origin of this software must not be misrepresented; you must not - // claim that you wrote the original software. If you use this software - // in a product, an acknowledgment in the product documentation would be - // appreciated but is not required. - // 2. Altered source versions must be plainly marked as such, and must not be - // misrepresented as being the original software. - // 3. This notice may not be removed or altered from any source distribution. - - /* Allowed flush values; see deflate() and inflate() below for details */ - const Z_NO_FLUSH = 0; - const Z_PARTIAL_FLUSH = 1; - const Z_SYNC_FLUSH = 2; - const Z_FULL_FLUSH = 3; - const Z_FINISH = 4; - const Z_BLOCK = 5; - const Z_TREES = 6; - - /* Return codes for the compression/decompression functions. Negative values - * are errors, positive values are used for special but normal events. - */ - const Z_OK = 0; - const Z_STREAM_END = 1; - const Z_NEED_DICT = 2; - const Z_STREAM_ERROR = -2; - const Z_DATA_ERROR = -3; - //export const Z_MEM_ERROR = -4; - const Z_BUF_ERROR = -5; - const Z_DEFAULT_COMPRESSION = -1; - - - const Z_FILTERED = 1; - const Z_HUFFMAN_ONLY = 2; - const Z_RLE = 3; - const Z_FIXED = 4; - const Z_DEFAULT_STRATEGY = 0; - - /* Possible values of the data_type field (though see inflate()) */ - const Z_BINARY = 0; - const Z_TEXT = 1; - //export const Z_ASCII = 1; // = Z_TEXT (deprecated) - const Z_UNKNOWN = 2; - - /* The deflate compression method */ - const Z_DEFLATED = 8; - //export const Z_NULL = null // Use -1 or null inline, depending on var type - - /*============================================================================*/ - - - function zero$1(buf) { - let len = buf.length; while (--len >= 0) { - buf[len] = 0; - } - } - - // From zutil.h - - const STORED_BLOCK = 0; - const STATIC_TREES = 1; - const DYN_TREES = 2; - /* The three kinds of block type */ - - const MIN_MATCH = 3; - const MAX_MATCH = 258; - /* The minimum and maximum match lengths */ - - // From deflate.h - /* =========================================================================== - * Internal compression state. - */ - - const LENGTH_CODES = 29; - /* number of length codes, not counting the special END_BLOCK code */ - - const LITERALS = 256; - /* number of literal bytes 0..255 */ - - const L_CODES = LITERALS + 1 + LENGTH_CODES; - /* number of Literal or Length codes, including the END_BLOCK code */ - - const D_CODES = 30; - /* number of distance codes */ - - const BL_CODES = 19; - /* number of codes used to transfer the bit lengths */ - - const HEAP_SIZE = 2 * L_CODES + 1; - /* maximum heap size */ - - const MAX_BITS = 15; - /* All codes must not exceed MAX_BITS bits */ - - const Buf_size = 16; - /* size of bit buffer in bi_buf */ - - - /* =========================================================================== - * Constants - */ - - const MAX_BL_BITS = 7; - /* Bit length codes must not exceed MAX_BL_BITS bits */ - - const END_BLOCK = 256; - /* end of block literal code */ - - const REP_3_6 = 16; - /* repeat previous bit length 3-6 times (2 bits of repeat count) */ - - const REPZ_3_10 = 17; - /* repeat a zero length 3-10 times (3 bits of repeat count) */ - - const REPZ_11_138 = 18; - /* repeat a zero length 11-138 times (7 bits of repeat count) */ - - /* eslint-disable comma-spacing,array-bracket-spacing */ - const extra_lbits = /* extra bits for each length code */ - [0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0]; - - const extra_dbits = /* extra bits for each distance code */ - [0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13]; - - const extra_blbits = /* extra bits for each bit length code */ - [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7]; - - const bl_order = - [16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]; - /* eslint-enable comma-spacing,array-bracket-spacing */ - - /* The lengths of the bit length codes are sent in order of decreasing - * probability, to avoid transmitting the lengths for unused bit length codes. - */ - - /* =========================================================================== - * Local data. These are initialized only once. - */ - - // We pre-fill arrays with 0 to avoid uninitialized gaps - - const DIST_CODE_LEN = 512; /* see definition of array dist_code below */ - - // !!!! Use flat array instead of structure, Freq = i*2, Len = i*2+1 - const static_ltree = new Array((L_CODES + 2) * 2); - zero$1(static_ltree); - /* The static literal tree. Since the bit lengths are imposed, there is no - * need for the L_CODES extra codes used during heap construction. However - * The codes 286 and 287 are needed to build a canonical tree (see _tr_init - * below). - */ - - const static_dtree = new Array(D_CODES * 2); - zero$1(static_dtree); - /* The static distance tree. (Actually a trivial tree since all codes use - * 5 bits.) - */ - - const _dist_code = new Array(DIST_CODE_LEN); - zero$1(_dist_code); - /* Distance codes. The first 256 values correspond to the distances - * 3 .. 258, the last 256 values correspond to the top 8 bits of - * the 15 bit distances. - */ - - const _length_code = new Array(MAX_MATCH - MIN_MATCH + 1); - zero$1(_length_code); - /* length code for each normalized match length (0 == MIN_MATCH) */ - - const base_length = new Array(LENGTH_CODES); - zero$1(base_length); - /* First normalized length for each code (0 = MIN_MATCH) */ - - const base_dist = new Array(D_CODES); - zero$1(base_dist); - /* First normalized distance for each code (0 = distance of 1) */ - - - function StaticTreeDesc(static_tree, extra_bits, extra_base, elems, max_length) { - - this.static_tree = static_tree; /* static tree or NULL */ - this.extra_bits = extra_bits; /* extra bits for each code or NULL */ - this.extra_base = extra_base; /* base index for extra_bits */ - this.elems = elems; /* max number of elements in the tree */ - this.max_length = max_length; /* max bit length for the codes */ - - // show if `static_tree` has data or dummy - needed for monomorphic objects - this.has_stree = static_tree && static_tree.length; - } - - - let static_l_desc; - let static_d_desc; - let static_bl_desc; - - - function TreeDesc(dyn_tree, stat_desc) { - this.dyn_tree = dyn_tree; /* the dynamic tree */ - this.max_code = 0; /* largest code with non zero frequency */ - this.stat_desc = stat_desc; /* the corresponding static tree */ - } - - - - function d_code(dist) { - return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)]; - } - - - /* =========================================================================== - * Output a short LSB first on the stream. - * IN assertion: there is enough room in pendingBuf. - */ - function put_short(s, w) { - // put_byte(s, (uch)((w) & 0xff)); - // put_byte(s, (uch)((ush)(w) >> 8)); - s.pending_buf[s.pending++] = w & 0xff; - s.pending_buf[s.pending++] = w >>> 8 & 0xff; - } - - - /* =========================================================================== - * Send a value on a given number of bits. - * IN assertion: length <= 16 and value fits in length bits. - */ - function send_bits(s, value, length) { - if (s.bi_valid > Buf_size - length) { - s.bi_buf |= value << s.bi_valid & 0xffff; - put_short(s, s.bi_buf); - s.bi_buf = value >> Buf_size - s.bi_valid; - s.bi_valid += length - Buf_size; - } else { - s.bi_buf |= value << s.bi_valid & 0xffff; - s.bi_valid += length; - } - } - - - function send_code(s, c, tree) { - send_bits(s, tree[c * 2]/*.Code*/, tree[c * 2 + 1]/*.Len*/); - } - - - /* =========================================================================== - * Reverse the first len bits of a code, using straightforward code (a faster - * method would use a table) - * IN assertion: 1 <= len <= 15 - */ - function bi_reverse(code, len) { - let res = 0; - do { - res |= code & 1; - code >>>= 1; - res <<= 1; - } while (--len > 0); - return res >>> 1; - } - - - /* =========================================================================== - * Flush the bit buffer, keeping at most 7 bits in it. - */ - function bi_flush(s) { - if (s.bi_valid === 16) { - put_short(s, s.bi_buf); - s.bi_buf = 0; - s.bi_valid = 0; - - } else if (s.bi_valid >= 8) { - s.pending_buf[s.pending++] = s.bi_buf & 0xff; - s.bi_buf >>= 8; - s.bi_valid -= 8; - } - } - - - /* =========================================================================== - * Compute the optimal bit lengths for a tree and update the total bit length - * for the current block. - * IN assertion: the fields freq and dad are set, heap[heap_max] and - * above are the tree nodes sorted by increasing frequency. - * OUT assertions: the field len is set to the optimal bit length, the - * array bl_count contains the frequencies for each bit length. - * The length opt_len is updated; static_len is also updated if stree is - * not null. - */ - function gen_bitlen(s, desc) - // deflate_state *s; - // tree_desc *desc; /* the tree descriptor */ - { - const tree = desc.dyn_tree; - const max_code = desc.max_code; - const stree = desc.stat_desc.static_tree; - const has_stree = desc.stat_desc.has_stree; - const extra = desc.stat_desc.extra_bits; - const base = desc.stat_desc.extra_base; - const max_length = desc.stat_desc.max_length; - let h; /* heap index */ - let n, m; /* iterate over the tree elements */ - let bits; /* bit length */ - let xbits; /* extra bits */ - let f; /* frequency */ - let overflow = 0; /* number of elements with bit length too large */ - - for (bits = 0; bits <= MAX_BITS; bits++) { - s.bl_count[bits] = 0; - } - - /* In a first pass, compute the optimal bit lengths (which may - * overflow in the case of the bit length tree). - */ - tree[s.heap[s.heap_max] * 2 + 1]/*.Len*/ = 0; /* root of the heap */ - - for (h = s.heap_max + 1; h < HEAP_SIZE; h++) { - n = s.heap[h]; - bits = tree[tree[n * 2 + 1]/*.Dad*/ * 2 + 1]/*.Len*/ + 1; - if (bits > max_length) { - bits = max_length; - overflow++; - } - tree[n * 2 + 1]/*.Len*/ = bits; - /* We overwrite tree[n].Dad which is no longer needed */ - - if (n > max_code) { - continue; - } /* not a leaf node */ - - s.bl_count[bits]++; - xbits = 0; - if (n >= base) { - xbits = extra[n - base]; - } - f = tree[n * 2]/*.Freq*/; - s.opt_len += f * (bits + xbits); - if (has_stree) { - s.static_len += f * (stree[n * 2 + 1]/*.Len*/ + xbits); - } - } - if (overflow === 0) { - return; - } - - // Trace((stderr,"\nbit length overflow\n")); - /* This happens for example on obj2 and pic of the Calgary corpus */ - - /* Find the first bit length which could increase: */ - do { - bits = max_length - 1; - while (s.bl_count[bits] === 0) { - bits--; - } - s.bl_count[bits]--; /* move one leaf down the tree */ - s.bl_count[bits + 1] += 2; /* move one overflow item as its brother */ - s.bl_count[max_length]--; - /* The brother of the overflow item also moves one step up, - * but this does not affect bl_count[max_length] - */ - overflow -= 2; - } while (overflow > 0); - - /* Now recompute all bit lengths, scanning in increasing frequency. - * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all - * lengths instead of fixing only the wrong ones. This idea is taken - * from 'ar' written by Haruhiko Okumura.) - */ - for (bits = max_length; bits !== 0; bits--) { - n = s.bl_count[bits]; - while (n !== 0) { - m = s.heap[--h]; - if (m > max_code) { - continue; - } - if (tree[m * 2 + 1]/*.Len*/ !== bits) { - // Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); - s.opt_len += (bits - tree[m * 2 + 1]/*.Len*/) * tree[m * 2]/*.Freq*/; - tree[m * 2 + 1]/*.Len*/ = bits; - } - n--; - } - } - } - - - /* =========================================================================== - * Generate the codes for a given tree and bit counts (which need not be - * optimal). - * IN assertion: the array bl_count contains the bit length statistics for - * the given tree and the field len is set for all tree elements. - * OUT assertion: the field code is set for all tree elements of non - * zero code length. - */ - function gen_codes(tree, max_code, bl_count) - // ct_data *tree; /* the tree to decorate */ - // int max_code; /* largest code with non zero frequency */ - // ushf *bl_count; /* number of codes at each bit length */ - { - const next_code = new Array(MAX_BITS + 1); /* next code value for each bit length */ - let code = 0; /* running code value */ - let bits; /* bit index */ - let n; /* code index */ - - /* The distribution counts are first used to generate the code values - * without bit reversal. - */ - for (bits = 1; bits <= MAX_BITS; bits++) { - next_code[bits] = code = code + bl_count[bits - 1] << 1; - } - /* Check that the bit counts in bl_count are consistent. The last code - * must be all ones. - */ - //Assert (code + bl_count[MAX_BITS]-1 == (1< length code (0..28) */ - length = 0; - for (code = 0; code < LENGTH_CODES - 1; code++) { - base_length[code] = length; - for (n = 0; n < 1 << extra_lbits[code]; n++) { - _length_code[length++] = code; - } - } - //Assert (length == 256, "tr_static_init: length != 256"); - /* Note that the length 255 (match length 258) can be represented - * in two different ways: code 284 + 5 bits or code 285, so we - * overwrite length_code[255] to use the best encoding: - */ - _length_code[length - 1] = code; - - /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ - dist = 0; - for (code = 0; code < 16; code++) { - base_dist[code] = dist; - for (n = 0; n < 1 << extra_dbits[code]; n++) { - _dist_code[dist++] = code; - } - } - //Assert (dist == 256, "tr_static_init: dist != 256"); - dist >>= 7; /* from now on, all distances are divided by 128 */ - for (; code < D_CODES; code++) { - base_dist[code] = dist << 7; - for (n = 0; n < 1 << extra_dbits[code] - 7; n++) { - _dist_code[256 + dist++] = code; - } - } - //Assert (dist == 256, "tr_static_init: 256+dist != 512"); - - /* Construct the codes of the static literal tree */ - for (bits = 0; bits <= MAX_BITS; bits++) { - bl_count[bits] = 0; - } - - n = 0; - while (n <= 143) { - static_ltree[n * 2 + 1]/*.Len*/ = 8; - n++; - bl_count[8]++; - } - while (n <= 255) { - static_ltree[n * 2 + 1]/*.Len*/ = 9; - n++; - bl_count[9]++; - } - while (n <= 279) { - static_ltree[n * 2 + 1]/*.Len*/ = 7; - n++; - bl_count[7]++; - } - while (n <= 287) { - static_ltree[n * 2 + 1]/*.Len*/ = 8; - n++; - bl_count[8]++; - } - /* Codes 286 and 287 do not exist, but we must include them in the - * tree construction to get a canonical Huffman tree (longest code - * all ones) - */ - gen_codes(static_ltree, L_CODES + 1, bl_count); - - /* The static distance tree is trivial: */ - for (n = 0; n < D_CODES; n++) { - static_dtree[n * 2 + 1]/*.Len*/ = 5; - static_dtree[n * 2]/*.Code*/ = bi_reverse(n, 5); - } - - // Now data ready and we can init static trees - static_l_desc = new StaticTreeDesc(static_ltree, extra_lbits, LITERALS + 1, L_CODES, MAX_BITS); - static_d_desc = new StaticTreeDesc(static_dtree, extra_dbits, 0, D_CODES, MAX_BITS); - static_bl_desc = new StaticTreeDesc(new Array(0), extra_blbits, 0, BL_CODES, MAX_BL_BITS); - - //static_init_done = true; - } - - - /* =========================================================================== - * Initialize a new block. - */ - function init_block(s) { - let n; /* iterates over tree elements */ - - /* Initialize the trees. */ - for (n = 0; n < L_CODES; n++) { - s.dyn_ltree[n * 2]/*.Freq*/ = 0; - } - for (n = 0; n < D_CODES; n++) { - s.dyn_dtree[n * 2]/*.Freq*/ = 0; - } - for (n = 0; n < BL_CODES; n++) { - s.bl_tree[n * 2]/*.Freq*/ = 0; - } - - s.dyn_ltree[END_BLOCK * 2]/*.Freq*/ = 1; - s.opt_len = s.static_len = 0; - s.last_lit = s.matches = 0; - } - - - /* =========================================================================== - * Flush the bit buffer and align the output on a byte boundary - */ - function bi_windup(s) { - if (s.bi_valid > 8) { - put_short(s, s.bi_buf); - } else if (s.bi_valid > 0) { - //put_byte(s, (Byte)s->bi_buf); - s.pending_buf[s.pending++] = s.bi_buf; - } - s.bi_buf = 0; - s.bi_valid = 0; - } - - /* =========================================================================== - * Copy a stored block, storing first the length and its - * one's complement if requested. - */ - function copy_block(s, buf, len, header) - //DeflateState *s; - //charf *buf; /* the input data */ - //unsigned len; /* its length */ - //int header; /* true if block header must be written */ - { - bi_windup(s); /* align on byte boundary */ - - if (header) { - put_short(s, len); - put_short(s, ~len); - } - // while (len--) { - // put_byte(s, *buf++); - // } - arraySet(s.pending_buf, s.window, buf, len, s.pending); - s.pending += len; - } - - /* =========================================================================== - * Compares to subtrees, using the tree depth as tie breaker when - * the subtrees have equal frequency. This minimizes the worst case length. - */ - function smaller(tree, n, m, depth) { - const _n2 = n * 2; - const _m2 = m * 2; - return tree[_n2]/*.Freq*/ < tree[_m2]/*.Freq*/ || - tree[_n2]/*.Freq*/ === tree[_m2]/*.Freq*/ && depth[n] <= depth[m]; - } - - /* =========================================================================== - * Restore the heap property by moving down the tree starting at node k, - * exchanging a node with the smallest of its two sons if necessary, stopping - * when the heap property is re-established (each father smaller than its - * two sons). - */ - function pqdownheap(s, tree, k) - // deflate_state *s; - // ct_data *tree; /* the tree to restore */ - // int k; /* node to move down */ - { - const v = s.heap[k]; - let j = k << 1; /* left son of k */ - while (j <= s.heap_len) { - /* Set j to the smallest of the two sons: */ - if (j < s.heap_len && - smaller(tree, s.heap[j + 1], s.heap[j], s.depth)) { - j++; - } - /* Exit if v is smaller than both sons */ - if (smaller(tree, v, s.heap[j], s.depth)) { - break; - } - - /* Exchange v with the smallest son */ - s.heap[k] = s.heap[j]; - k = j; - - /* And continue down the tree, setting j to the left son of k */ - j <<= 1; - } - s.heap[k] = v; - } - - - // inlined manually - // var SMALLEST = 1; - - /* =========================================================================== - * Send the block data compressed using the given Huffman trees - */ - function compress_block(s, ltree, dtree) - // deflate_state *s; - // const ct_data *ltree; /* literal tree */ - // const ct_data *dtree; /* distance tree */ - { - let dist; /* distance of matched string */ - let lc; /* match length or unmatched char (if dist == 0) */ - let lx = 0; /* running index in l_buf */ - let code; /* the code to send */ - let extra; /* number of extra bits to send */ - - if (s.last_lit !== 0) { - do { - dist = s.pending_buf[s.d_buf + lx * 2] << 8 | s.pending_buf[s.d_buf + lx * 2 + 1]; - lc = s.pending_buf[s.l_buf + lx]; - lx++; - - if (dist === 0) { - send_code(s, lc, ltree); /* send a literal byte */ - //Tracecv(isgraph(lc), (stderr," '%c' ", lc)); - } else { - /* Here, lc is the match length - MIN_MATCH */ - code = _length_code[lc]; - send_code(s, code + LITERALS + 1, ltree); /* send the length code */ - extra = extra_lbits[code]; - if (extra !== 0) { - lc -= base_length[code]; - send_bits(s, lc, extra); /* send the extra length bits */ - } - dist--; /* dist is now the match distance - 1 */ - code = d_code(dist); - //Assert (code < D_CODES, "bad d_code"); - - send_code(s, code, dtree); /* send the distance code */ - extra = extra_dbits[code]; - if (extra !== 0) { - dist -= base_dist[code]; - send_bits(s, dist, extra); /* send the extra distance bits */ - } - } /* literal or match pair ? */ - - /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ - //Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, - // "pendingBuf overflow"); - - } while (lx < s.last_lit); - } - - send_code(s, END_BLOCK, ltree); - } - - - /* =========================================================================== - * Construct one Huffman tree and assigns the code bit strings and lengths. - * Update the total bit length for the current block. - * IN assertion: the field freq is set for all tree elements. - * OUT assertions: the fields len and code are set to the optimal bit length - * and corresponding code. The length opt_len is updated; static_len is - * also updated if stree is not null. The field max_code is set. - */ - function build_tree(s, desc) - // deflate_state *s; - // tree_desc *desc; /* the tree descriptor */ - { - const tree = desc.dyn_tree; - const stree = desc.stat_desc.static_tree; - const has_stree = desc.stat_desc.has_stree; - const elems = desc.stat_desc.elems; - let n, m; /* iterate over heap elements */ - let max_code = -1; /* largest code with non zero frequency */ - let node; /* new node being created */ - - /* Construct the initial heap, with least frequent element in - * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. - * heap[0] is not used. - */ - s.heap_len = 0; - s.heap_max = HEAP_SIZE; - - for (n = 0; n < elems; n++) { - if (tree[n * 2]/*.Freq*/ !== 0) { - s.heap[++s.heap_len] = max_code = n; - s.depth[n] = 0; - - } else { - tree[n * 2 + 1]/*.Len*/ = 0; - } - } - - /* The pkzip format requires that at least one distance code exists, - * and that at least one bit should be sent even if there is only one - * possible code. So to avoid special checks later on we force at least - * two codes of non zero frequency. - */ - while (s.heap_len < 2) { - node = s.heap[++s.heap_len] = max_code < 2 ? ++max_code : 0; - tree[node * 2]/*.Freq*/ = 1; - s.depth[node] = 0; - s.opt_len--; - - if (has_stree) { - s.static_len -= stree[node * 2 + 1]/*.Len*/; - } - /* node is 0 or 1 so it does not have extra bits */ - } - desc.max_code = max_code; - - /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, - * establish sub-heaps of increasing lengths: - */ - for (n = s.heap_len >> 1/*int /2*/; n >= 1; n--) { - pqdownheap(s, tree, n); - } - - /* Construct the Huffman tree by repeatedly combining the least two - * frequent nodes. - */ - node = elems; /* next internal node of the tree */ - do { - //pqremove(s, tree, n); /* n = node of least frequency */ - /*** pqremove ***/ - n = s.heap[1/*SMALLEST*/]; - s.heap[1/*SMALLEST*/] = s.heap[s.heap_len--]; - pqdownheap(s, tree, 1/*SMALLEST*/); - /***/ - - m = s.heap[1/*SMALLEST*/]; /* m = node of next least frequency */ - - s.heap[--s.heap_max] = n; /* keep the nodes sorted by frequency */ - s.heap[--s.heap_max] = m; - - /* Create a new node father of n and m */ - tree[node * 2]/*.Freq*/ = tree[n * 2]/*.Freq*/ + tree[m * 2]/*.Freq*/; - s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1; - tree[n * 2 + 1]/*.Dad*/ = tree[m * 2 + 1]/*.Dad*/ = node; - - /* and insert the new node in the heap */ - s.heap[1/*SMALLEST*/] = node++; - pqdownheap(s, tree, 1/*SMALLEST*/); - - } while (s.heap_len >= 2); - - s.heap[--s.heap_max] = s.heap[1/*SMALLEST*/]; - - /* At this point, the fields freq and dad are set. We can now - * generate the bit lengths. - */ - gen_bitlen(s, desc); - - /* The field len is now set, we can generate the bit codes */ - gen_codes(tree, max_code, s.bl_count); - } - - - /* =========================================================================== - * Scan a literal or distance tree to determine the frequencies of the codes - * in the bit length tree. - */ - function scan_tree(s, tree, max_code) - // deflate_state *s; - // ct_data *tree; /* the tree to be scanned */ - // int max_code; /* and its largest code of non zero frequency */ - { - let n; /* iterates over all tree elements */ - let prevlen = -1; /* last emitted length */ - let curlen; /* length of current code */ - - let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */ - - let count = 0; /* repeat count of the current code */ - let max_count = 7; /* max repeat count */ - let min_count = 4; /* min repeat count */ - - if (nextlen === 0) { - max_count = 138; - min_count = 3; - } - tree[(max_code + 1) * 2 + 1]/*.Len*/ = 0xffff; /* guard */ - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; - nextlen = tree[(n + 1) * 2 + 1]/*.Len*/; - - if (++count < max_count && curlen === nextlen) { - continue; - - } else if (count < min_count) { - s.bl_tree[curlen * 2]/*.Freq*/ += count; - - } else if (curlen !== 0) { - - if (curlen !== prevlen) { - s.bl_tree[curlen * 2]/*.Freq*/++; - } - s.bl_tree[REP_3_6 * 2]/*.Freq*/++; - - } else if (count <= 10) { - s.bl_tree[REPZ_3_10 * 2]/*.Freq*/++; - - } else { - s.bl_tree[REPZ_11_138 * 2]/*.Freq*/++; - } - - count = 0; - prevlen = curlen; - - if (nextlen === 0) { - max_count = 138; - min_count = 3; - - } else if (curlen === nextlen) { - max_count = 6; - min_count = 3; - - } else { - max_count = 7; - min_count = 4; - } - } - } - - - /* =========================================================================== - * Send a literal or distance tree in compressed form, using the codes in - * bl_tree. - */ - function send_tree(s, tree, max_code) - // deflate_state *s; - // ct_data *tree; /* the tree to be scanned */ - // int max_code; /* and its largest code of non zero frequency */ - { - let n; /* iterates over all tree elements */ - let prevlen = -1; /* last emitted length */ - let curlen; /* length of current code */ - - let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */ - - let count = 0; /* repeat count of the current code */ - let max_count = 7; /* max repeat count */ - let min_count = 4; /* min repeat count */ - - /* tree[max_code+1].Len = -1; */ /* guard already set */ - if (nextlen === 0) { - max_count = 138; - min_count = 3; - } - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; - nextlen = tree[(n + 1) * 2 + 1]/*.Len*/; - - if (++count < max_count && curlen === nextlen) { - continue; - - } else if (count < min_count) { - do { - send_code(s, curlen, s.bl_tree); - } while (--count !== 0); - - } else if (curlen !== 0) { - if (curlen !== prevlen) { - send_code(s, curlen, s.bl_tree); - count--; - } - //Assert(count >= 3 && count <= 6, " 3_6?"); - send_code(s, REP_3_6, s.bl_tree); - send_bits(s, count - 3, 2); - - } else if (count <= 10) { - send_code(s, REPZ_3_10, s.bl_tree); - send_bits(s, count - 3, 3); - - } else { - send_code(s, REPZ_11_138, s.bl_tree); - send_bits(s, count - 11, 7); - } - - count = 0; - prevlen = curlen; - if (nextlen === 0) { - max_count = 138; - min_count = 3; - - } else if (curlen === nextlen) { - max_count = 6; - min_count = 3; - - } else { - max_count = 7; - min_count = 4; - } - } - } - - - /* =========================================================================== - * Construct the Huffman tree for the bit lengths and return the index in - * bl_order of the last bit length code to send. - */ - function build_bl_tree(s) { - let max_blindex; /* index of last bit length code of non zero freq */ - - /* Determine the bit length frequencies for literal and distance trees */ - scan_tree(s, s.dyn_ltree, s.l_desc.max_code); - scan_tree(s, s.dyn_dtree, s.d_desc.max_code); - - /* Build the bit length tree: */ - build_tree(s, s.bl_desc); - /* opt_len now includes the length of the tree representations, except - * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. - */ - - /* Determine the number of bit length codes to send. The pkzip format - * requires that at least 4 bit length codes be sent. (appnote.txt says - * 3 but the actual value used is 4.) - */ - for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) { - if (s.bl_tree[bl_order[max_blindex] * 2 + 1]/*.Len*/ !== 0) { - break; - } - } - /* Update opt_len to include the bit length tree and counts */ - s.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4; - //Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", - // s->opt_len, s->static_len)); - - return max_blindex; - } - - - /* =========================================================================== - * Send the header for a block using dynamic Huffman trees: the counts, the - * lengths of the bit length codes, the literal tree and the distance tree. - * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. - */ - function send_all_trees(s, lcodes, dcodes, blcodes) - // deflate_state *s; - // int lcodes, dcodes, blcodes; /* number of codes for each tree */ - { - let rank; /* index in bl_order */ - - //Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); - //Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, - // "too many codes"); - //Tracev((stderr, "\nbl counts: ")); - send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */ - send_bits(s, dcodes - 1, 5); - send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */ - for (rank = 0; rank < blcodes; rank++) { - //Tracev((stderr, "\nbl code %2d ", bl_order[rank])); - send_bits(s, s.bl_tree[bl_order[rank] * 2 + 1]/*.Len*/, 3); - } - //Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); - - send_tree(s, s.dyn_ltree, lcodes - 1); /* literal tree */ - //Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); - - send_tree(s, s.dyn_dtree, dcodes - 1); /* distance tree */ - //Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); - } - - - /* =========================================================================== - * Check if the data type is TEXT or BINARY, using the following algorithm: - * - TEXT if the two conditions below are satisfied: - * a) There are no non-portable control characters belonging to the - * "black list" (0..6, 14..25, 28..31). - * b) There is at least one printable character belonging to the - * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). - * - BINARY otherwise. - * - The following partially-portable control characters form a - * "gray list" that is ignored in this detection algorithm: - * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). - * IN assertion: the fields Freq of dyn_ltree are set. - */ - function detect_data_type(s) { - /* black_mask is the bit mask of black-listed bytes - * set bits 0..6, 14..25, and 28..31 - * 0xf3ffc07f = binary 11110011111111111100000001111111 - */ - let black_mask = 0xf3ffc07f; - let n; - - /* Check for non-textual ("black-listed") bytes. */ - for (n = 0; n <= 31; n++, black_mask >>>= 1) { - if (black_mask & 1 && s.dyn_ltree[n * 2]/*.Freq*/ !== 0) { - return Z_BINARY; - } - } - - /* Check for textual ("white-listed") bytes. */ - if (s.dyn_ltree[9 * 2]/*.Freq*/ !== 0 || s.dyn_ltree[10 * 2]/*.Freq*/ !== 0 || - s.dyn_ltree[13 * 2]/*.Freq*/ !== 0) { - return Z_TEXT; - } - for (n = 32; n < LITERALS; n++) { - if (s.dyn_ltree[n * 2]/*.Freq*/ !== 0) { - return Z_TEXT; - } - } - - /* There are no "black-listed" or "white-listed" bytes: - * this stream either is empty or has tolerated ("gray-listed") bytes only. - */ - return Z_BINARY; - } - - - let static_init_done = false; - - /* =========================================================================== - * Initialize the tree data structures for a new zlib stream. - */ - function _tr_init(s) { - - if (!static_init_done) { - tr_static_init(); - static_init_done = true; - } - - s.l_desc = new TreeDesc(s.dyn_ltree, static_l_desc); - s.d_desc = new TreeDesc(s.dyn_dtree, static_d_desc); - s.bl_desc = new TreeDesc(s.bl_tree, static_bl_desc); - - s.bi_buf = 0; - s.bi_valid = 0; - - /* Initialize the first block of the first file: */ - init_block(s); - } - - - /* =========================================================================== - * Send a stored block - */ - function _tr_stored_block(s, buf, stored_len, last) - //DeflateState *s; - //charf *buf; /* input block */ - //ulg stored_len; /* length of input block */ - //int last; /* one if this is the last block for a file */ - { - send_bits(s, (STORED_BLOCK << 1) + (last ? 1 : 0), 3); /* send block type */ - copy_block(s, buf, stored_len, true); /* with header */ - } - - - /* =========================================================================== - * Send one empty static block to give enough lookahead for inflate. - * This takes 10 bits, of which 7 may remain in the bit buffer. - */ - function _tr_align(s) { - send_bits(s, STATIC_TREES << 1, 3); - send_code(s, END_BLOCK, static_ltree); - bi_flush(s); - } - - - /* =========================================================================== - * Determine the best encoding for the current block: dynamic trees, static - * trees or store, and output the encoded block to the zip file. - */ - function _tr_flush_block(s, buf, stored_len, last) - //DeflateState *s; - //charf *buf; /* input block, or NULL if too old */ - //ulg stored_len; /* length of input block */ - //int last; /* one if this is the last block for a file */ - { - let opt_lenb, static_lenb; /* opt_len and static_len in bytes */ - let max_blindex = 0; /* index of last bit length code of non zero freq */ - - /* Build the Huffman trees unless a stored block is forced */ - if (s.level > 0) { - - /* Check if the file is binary or text */ - if (s.strm.data_type === Z_UNKNOWN) { - s.strm.data_type = detect_data_type(s); - } - - /* Construct the literal and distance trees */ - build_tree(s, s.l_desc); - // Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, - // s->static_len)); - - build_tree(s, s.d_desc); - // Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, - // s->static_len)); - /* At this point, opt_len and static_len are the total bit lengths of - * the compressed block data, excluding the tree representations. - */ - - /* Build the bit length tree for the above two trees, and get the index - * in bl_order of the last bit length code to send. - */ - max_blindex = build_bl_tree(s); - - /* Determine the best encoding. Compute the block lengths in bytes. */ - opt_lenb = s.opt_len + 3 + 7 >>> 3; - static_lenb = s.static_len + 3 + 7 >>> 3; - - // Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", - // opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, - // s->last_lit)); - - if (static_lenb <= opt_lenb) { - opt_lenb = static_lenb; - } - - } else { - // Assert(buf != (char*)0, "lost buf"); - opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ - } - - if (stored_len + 4 <= opt_lenb && buf !== -1) { - /* 4: two words for the lengths */ - - /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. - * Otherwise we can't have processed more than WSIZE input bytes since - * the last block flush, because compression would have been - * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to - * transform a block into a stored block. - */ - _tr_stored_block(s, buf, stored_len, last); - - } else if (s.strategy === Z_FIXED || static_lenb === opt_lenb) { - - send_bits(s, (STATIC_TREES << 1) + (last ? 1 : 0), 3); - compress_block(s, static_ltree, static_dtree); - - } else { - send_bits(s, (DYN_TREES << 1) + (last ? 1 : 0), 3); - send_all_trees(s, s.l_desc.max_code + 1, s.d_desc.max_code + 1, max_blindex + 1); - compress_block(s, s.dyn_ltree, s.dyn_dtree); - } - // Assert (s->compressed_len == s->bits_sent, "bad compressed size"); - /* The above check is made mod 2^32, for files larger than 512 MB - * and uLong implemented on 32 bits. - */ - init_block(s); - - if (last) { - bi_windup(s); - } - // Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, - // s->compressed_len-7*last)); - } - - /* =========================================================================== - * Save the match info and tally the frequency counts. Return true if - * the current block must be flushed. - */ - function _tr_tally(s, dist, lc) - // deflate_state *s; - // unsigned dist; /* distance of matched string */ - // unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ - { - //var out_length, in_length, dcode; - - s.pending_buf[s.d_buf + s.last_lit * 2] = dist >>> 8 & 0xff; - s.pending_buf[s.d_buf + s.last_lit * 2 + 1] = dist & 0xff; - - s.pending_buf[s.l_buf + s.last_lit] = lc & 0xff; - s.last_lit++; - - if (dist === 0) { - /* lc is the unmatched char */ - s.dyn_ltree[lc * 2]/*.Freq*/++; - } else { - s.matches++; - /* Here, lc is the match length - MIN_MATCH */ - dist--; /* dist = match distance - 1 */ - //Assert((ush)dist < (ush)MAX_DIST(s) && - // (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && - // (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); - - s.dyn_ltree[(_length_code[lc] + LITERALS + 1) * 2]/*.Freq*/++; - s.dyn_dtree[d_code(dist) * 2]/*.Freq*/++; - } - - // (!) This block is disabled in zlib defaults, - // don't enable it for binary compatibility - - //#ifdef TRUNCATE_BLOCK - // /* Try to guess if it is profitable to stop the current block here */ - // if ((s.last_lit & 0x1fff) === 0 && s.level > 2) { - // /* Compute an upper bound for the compressed length */ - // out_length = s.last_lit*8; - // in_length = s.strstart - s.block_start; - // - // for (dcode = 0; dcode < D_CODES; dcode++) { - // out_length += s.dyn_dtree[dcode*2]/*.Freq*/ * (5 + extra_dbits[dcode]); - // } - // out_length >>>= 3; - // //Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", - // // s->last_lit, in_length, out_length, - // // 100L - out_length*100L/in_length)); - // if (s.matches < (s.last_lit>>1)/*int /2*/ && out_length < (in_length>>1)/*int /2*/) { - // return true; - // } - // } - //#endif - - return s.last_lit === s.lit_bufsize - 1; - /* We avoid equality with lit_bufsize because of wraparound at 64K - * on 16 bit machines and because stored blocks are restricted to - * 64K-1 bytes. - */ - } - - // Note: adler32 takes 12% for level 0 and 2% for level 6. - // It isn't worth it to make additional optimizations as in original. - // Small size is preferable. - - // (C) 1995-2013 Jean-loup Gailly and Mark Adler - // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin - // - // This software is provided 'as-is', without any express or implied - // warranty. In no event will the authors be held liable for any damages - // arising from the use of this software. - // - // Permission is granted to anyone to use this software for any purpose, - // including commercial applications, and to alter it and redistribute it - // freely, subject to the following restrictions: - // - // 1. The origin of this software must not be misrepresented; you must not - // claim that you wrote the original software. If you use this software - // in a product, an acknowledgment in the product documentation would be - // appreciated but is not required. - // 2. Altered source versions must be plainly marked as such, and must not be - // misrepresented as being the original software. - // 3. This notice may not be removed or altered from any source distribution. - - function adler32(adler, buf, len, pos) { - let s1 = adler & 0xffff |0, - s2 = adler >>> 16 & 0xffff |0, - n = 0; - - while (len !== 0) { - // Set limit ~ twice less than 5552, to keep - // s2 in 31-bits, because we force signed ints. - // in other case %= will fail. - n = len > 2000 ? 2000 : len; - len -= n; - - do { - s1 = s1 + buf[pos++] |0; - s2 = s2 + s1 |0; - } while (--n); - - s1 %= 65521; - s2 %= 65521; - } - - return s1 | s2 << 16 |0; - } - - // Note: we can't get significant speed boost here. - // So write code to minimize size - no pregenerated tables - // and array tools dependencies. - - // (C) 1995-2013 Jean-loup Gailly and Mark Adler - // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin - // - // This software is provided 'as-is', without any express or implied - // warranty. In no event will the authors be held liable for any damages - // arising from the use of this software. - // - // Permission is granted to anyone to use this software for any purpose, - // including commercial applications, and to alter it and redistribute it - // freely, subject to the following restrictions: - // - // 1. The origin of this software must not be misrepresented; you must not - // claim that you wrote the original software. If you use this software - // in a product, an acknowledgment in the product documentation would be - // appreciated but is not required. - // 2. Altered source versions must be plainly marked as such, and must not be - // misrepresented as being the original software. - // 3. This notice may not be removed or altered from any source distribution. - - // Use ordinary array, since untyped makes no boost here - function makeTable() { - let c; - const table = []; - - for (let n = 0; n < 256; n++) { - c = n; - for (let k = 0; k < 8; k++) { - c = c & 1 ? 0xEDB88320 ^ c >>> 1 : c >>> 1; - } - table[n] = c; - } - - return table; - } - - // Create table on load. Just 255 signed longs. Not a problem. - const crcTable = makeTable(); - - - function crc32(crc, buf, len, pos) { - const t = crcTable, - end = pos + len; - - crc ^= -1; - - for (let i = pos; i < end; i++) { - crc = crc >>> 8 ^ t[(crc ^ buf[i]) & 0xFF]; - } - - return crc ^ -1; // >>> 0; - } - - // (C) 1995-2013 Jean-loup Gailly and Mark Adler - // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin - // - // This software is provided 'as-is', without any express or implied - // warranty. In no event will the authors be held liable for any damages - // arising from the use of this software. - // - // Permission is granted to anyone to use this software for any purpose, - // including commercial applications, and to alter it and redistribute it - // freely, subject to the following restrictions: - // - // 1. The origin of this software must not be misrepresented; you must not - // claim that you wrote the original software. If you use this software - // in a product, an acknowledgment in the product documentation would be - // appreciated but is not required. - // 2. Altered source versions must be plainly marked as such, and must not be - // misrepresented as being the original software. - // 3. This notice may not be removed or altered from any source distribution. - - var msg = { - 2: "need dictionary", /* Z_NEED_DICT 2 */ - 1: "stream end", /* Z_STREAM_END 1 */ - 0: "", /* Z_OK 0 */ - "-1": "file error", /* Z_ERRNO (-1) */ - "-2": "stream error", /* Z_STREAM_ERROR (-2) */ - "-3": "data error", /* Z_DATA_ERROR (-3) */ - "-4": "insufficient memory", /* Z_MEM_ERROR (-4) */ - "-5": "buffer error", /* Z_BUF_ERROR (-5) */ - "-6": "incompatible version" /* Z_VERSION_ERROR (-6) */ - }; - - /*============================================================================*/ - - - const MAX_MEM_LEVEL = 9; - - - const LENGTH_CODES$1 = 29; - /* number of length codes, not counting the special END_BLOCK code */ - const LITERALS$1 = 256; - /* number of literal bytes 0..255 */ - const L_CODES$1 = LITERALS$1 + 1 + LENGTH_CODES$1; - /* number of Literal or Length codes, including the END_BLOCK code */ - const D_CODES$1 = 30; - /* number of distance codes */ - const BL_CODES$1 = 19; - /* number of codes used to transfer the bit lengths */ - const HEAP_SIZE$1 = 2 * L_CODES$1 + 1; - /* maximum heap size */ - const MAX_BITS$1 = 15; - /* All codes must not exceed MAX_BITS bits */ - - const MIN_MATCH$1 = 3; - const MAX_MATCH$1 = 258; - const MIN_LOOKAHEAD = (MAX_MATCH$1 + MIN_MATCH$1 + 1); - - const PRESET_DICT = 0x20; - - const INIT_STATE = 42; - const EXTRA_STATE = 69; - const NAME_STATE = 73; - const COMMENT_STATE = 91; - const HCRC_STATE = 103; - const BUSY_STATE = 113; - const FINISH_STATE = 666; - - const BS_NEED_MORE = 1; /* block not completed, need more input or more output */ - const BS_BLOCK_DONE = 2; /* block flush performed */ - const BS_FINISH_STARTED = 3; /* finish started, need only more output at next deflate */ - const BS_FINISH_DONE = 4; /* finish done, accept no more input or output */ - - const OS_CODE = 0x03; // Unix :) . Don't detect, use this default. - - function err(strm, errorCode) { - strm.msg = msg[errorCode]; - return errorCode; - } - - function rank(f) { - return ((f) << 1) - ((f) > 4 ? 9 : 0); - } - - function zero$2(buf) { let len = buf.length; while (--len >= 0) { buf[len] = 0; } } - - - /* ========================================================================= - * Flush as much pending output as possible. All deflate() output goes - * through this function so some applications may wish to modify it - * to avoid allocating a large strm->output buffer and copying into it. - * (See also read_buf()). - */ - function flush_pending(strm) { - const s = strm.state; - - //_tr_flush_bits(s); - let len = s.pending; - if (len > strm.avail_out) { - len = strm.avail_out; - } - if (len === 0) { return; } - - arraySet(strm.output, s.pending_buf, s.pending_out, len, strm.next_out); - strm.next_out += len; - s.pending_out += len; - strm.total_out += len; - strm.avail_out -= len; - s.pending -= len; - if (s.pending === 0) { - s.pending_out = 0; - } - } - - - function flush_block_only(s, last) { - _tr_flush_block(s, (s.block_start >= 0 ? s.block_start : -1), s.strstart - s.block_start, last); - s.block_start = s.strstart; - flush_pending(s.strm); - } - - - function put_byte(s, b) { - s.pending_buf[s.pending++] = b; - } - - - /* ========================================================================= - * Put a short in the pending buffer. The 16-bit value is put in MSB order. - * IN assertion: the stream state is correct and there is enough room in - * pending_buf. - */ - function putShortMSB(s, b) { - // put_byte(s, (Byte)(b >> 8)); - // put_byte(s, (Byte)(b & 0xff)); - s.pending_buf[s.pending++] = (b >>> 8) & 0xff; - s.pending_buf[s.pending++] = b & 0xff; - } - - - /* =========================================================================== - * Read a new buffer from the current input stream, update the adler32 - * and total number of bytes read. All deflate() input goes through - * this function so some applications may wish to modify it to avoid - * allocating a large strm->input buffer and copying from it. - * (See also flush_pending()). - */ - function read_buf(strm, buf, start, size) { - let len = strm.avail_in; - - if (len > size) { len = size; } - if (len === 0) { return 0; } - - strm.avail_in -= len; - - // zmemcpy(buf, strm->next_in, len); - arraySet(buf, strm.input, strm.next_in, len, start); - if (strm.state.wrap === 1) { - strm.adler = adler32(strm.adler, buf, len, start); - } - - else if (strm.state.wrap === 2) { - strm.adler = crc32(strm.adler, buf, len, start); - } - - strm.next_in += len; - strm.total_in += len; - - return len; - } - - - /* =========================================================================== - * Set match_start to the longest match starting at the given string and - * return its length. Matches shorter or equal to prev_length are discarded, - * in which case the result is equal to prev_length and match_start is - * garbage. - * IN assertions: cur_match is the head of the hash chain for the current - * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 - * OUT assertion: the match length is not greater than s->lookahead. - */ - function longest_match(s, cur_match) { - let chain_length = s.max_chain_length; /* max hash chain length */ - let scan = s.strstart; /* current string */ - let match; /* matched string */ - let len; /* length of current match */ - let best_len = s.prev_length; /* best match length so far */ - let nice_match = s.nice_match; /* stop if match long enough */ - const limit = (s.strstart > (s.w_size - MIN_LOOKAHEAD)) ? - s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0/*NIL*/; - - const _win = s.window; // shortcut - - const wmask = s.w_mask; - const prev = s.prev; - - /* Stop when cur_match becomes <= limit. To simplify the code, - * we prevent matches with the string of window index 0. - */ - - const strend = s.strstart + MAX_MATCH$1; - let scan_end1 = _win[scan + best_len - 1]; - let scan_end = _win[scan + best_len]; - - /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - * It is easy to get rid of this optimization if necessary. - */ - // Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - - /* Do not waste too much time if we already have a good match: */ - if (s.prev_length >= s.good_match) { - chain_length >>= 2; - } - /* Do not look for matches beyond the end of the input. This is necessary - * to make deflate deterministic. - */ - if (nice_match > s.lookahead) { nice_match = s.lookahead; } - - // Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); - - do { - // Assert(cur_match < s->strstart, "no future"); - match = cur_match; - - /* Skip to next match if the match length cannot increase - * or if the match length is less than 2. Note that the checks below - * for insufficient lookahead only occur occasionally for performance - * reasons. Therefore uninitialized memory will be accessed, and - * conditional jumps will be made that depend on those values. - * However the length of the match is limited to the lookahead, so - * the output of deflate is not affected by the uninitialized values. - */ - - if (_win[match + best_len] !== scan_end || - _win[match + best_len - 1] !== scan_end1 || - _win[match] !== _win[scan] || - _win[++match] !== _win[scan + 1]) { - continue; - } - - /* The check at best_len-1 can be removed because it will be made - * again later. (This heuristic is not always a win.) - * It is not necessary to compare scan[2] and match[2] since they - * are always equal when the other bytes match, given that - * the hash keys are equal and that HASH_BITS >= 8. - */ - scan += 2; - match++; - // Assert(*scan == *match, "match[2]?"); - - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. - */ - do { - /*jshint noempty:false*/ - } while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - scan < strend); - - // Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - - len = MAX_MATCH$1 - (strend - scan); - scan = strend - MAX_MATCH$1; - - if (len > best_len) { - s.match_start = cur_match; - best_len = len; - if (len >= nice_match) { - break; - } - scan_end1 = _win[scan + best_len - 1]; - scan_end = _win[scan + best_len]; - } - } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0); - - if (best_len <= s.lookahead) { - return best_len; - } - return s.lookahead; - } - - - /* =========================================================================== - * Fill the window when the lookahead becomes insufficient. - * Updates strstart and lookahead. - * - * IN assertion: lookahead < MIN_LOOKAHEAD - * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD - * At least one byte has been read, or avail_in == 0; reads are - * performed for at least two bytes (required for the zip translate_eol - * option -- not supported here). - */ - function fill_window(s) { - const _w_size = s.w_size; - let p, n, m, more, str; - - //Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); - - do { - more = s.window_size - s.lookahead - s.strstart; - - // JS ints have 32 bit, block below not needed - /* Deal with !@#$% 64K limit: */ - //if (sizeof(int) <= 2) { - // if (more == 0 && s->strstart == 0 && s->lookahead == 0) { - // more = wsize; - // - // } else if (more == (unsigned)(-1)) { - // /* Very unlikely, but possible on 16 bit machine if - // * strstart == 0 && lookahead == 1 (input done a byte at time) - // */ - // more--; - // } - //} - - - /* If the window is almost full and there is insufficient lookahead, - * move the upper half to the lower one to make room in the upper half. - */ - if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) { - - arraySet(s.window, s.window, _w_size, _w_size, 0); - s.match_start -= _w_size; - s.strstart -= _w_size; - /* we now have strstart >= MAX_DIST */ - s.block_start -= _w_size; - - /* Slide the hash table (could be avoided with 32 bit values - at the expense of memory usage). We slide even when level == 0 - to keep the hash table consistent if we switch back to level > 0 - later. (Using level 0 permanently is not an optimal usage of - zlib, so we don't care about this pathological case.) - */ - - n = s.hash_size; - p = n; - do { - m = s.head[--p]; - s.head[p] = (m >= _w_size ? m - _w_size : 0); - } while (--n); - - n = _w_size; - p = n; - do { - m = s.prev[--p]; - s.prev[p] = (m >= _w_size ? m - _w_size : 0); - /* If n is not on any hash chain, prev[n] is garbage but - * its value will never be used. - */ - } while (--n); - - more += _w_size; - } - if (s.strm.avail_in === 0) { - break; - } - - /* If there was no sliding: - * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && - * more == window_size - lookahead - strstart - * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) - * => more >= window_size - 2*WSIZE + 2 - * In the BIG_MEM or MMAP case (not yet supported), - * window_size == input_size + MIN_LOOKAHEAD && - * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. - * Otherwise, window_size == 2*WSIZE so more >= 2. - * If there was sliding, more >= WSIZE. So in all cases, more >= 2. - */ - //Assert(more >= 2, "more < 2"); - n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more); - s.lookahead += n; - - /* Initialize the hash value now that we have some input: */ - if (s.lookahead + s.insert >= MIN_MATCH$1) { - str = s.strstart - s.insert; - s.ins_h = s.window[str]; - - /* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + 1]) & s.hash_mask; - //#if MIN_MATCH != 3 - // Call update_hash() MIN_MATCH-3 more times - //#endif - while (s.insert) { - /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH$1 - 1]) & s.hash_mask; - - s.prev[str & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = str; - str++; - s.insert--; - if (s.lookahead + s.insert < MIN_MATCH$1) { - break; - } - } - } - /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, - * but this is not important since only literal bytes will be emitted. - */ - - } while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0); - - /* If the WIN_INIT bytes after the end of the current data have never been - * written, then zero those bytes in order to avoid memory check reports of - * the use of uninitialized (or uninitialised as Julian writes) bytes by - * the longest match routines. Update the high water mark for the next - * time through here. WIN_INIT is set to MAX_MATCH since the longest match - * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. - */ - // if (s.high_water < s.window_size) { - // var curr = s.strstart + s.lookahead; - // var init = 0; - // - // if (s.high_water < curr) { - // /* Previous high water mark below current data -- zero WIN_INIT - // * bytes or up to end of window, whichever is less. - // */ - // init = s.window_size - curr; - // if (init > WIN_INIT) - // init = WIN_INIT; - // zmemzero(s->window + curr, (unsigned)init); - // s->high_water = curr + init; - // } - // else if (s->high_water < (ulg)curr + WIN_INIT) { - // /* High water mark at or above current data, but below current data - // * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up - // * to end of window, whichever is less. - // */ - // init = (ulg)curr + WIN_INIT - s->high_water; - // if (init > s->window_size - s->high_water) - // init = s->window_size - s->high_water; - // zmemzero(s->window + s->high_water, (unsigned)init); - // s->high_water += init; - // } - // } - // - // Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, - // "not enough room for search"); - } - - /* =========================================================================== - * Copy without compression as much as possible from the input stream, return - * the current block state. - * This function does not insert new strings in the dictionary since - * uncompressible data is probably not useful. This function is used - * only for the level=0 compression option. - * NOTE: this function should be optimized to avoid extra copying from - * window to pending_buf. - */ - function deflate_stored(s, flush) { - /* Stored blocks are limited to 0xffff bytes, pending_buf is limited - * to pending_buf_size, and each stored block has a 5 byte header: - */ - let max_block_size = 0xffff; - - if (max_block_size > s.pending_buf_size - 5) { - max_block_size = s.pending_buf_size - 5; - } - - /* Copy as much as possible from input to output: */ - for (; ;) { - /* Fill the window as much as possible: */ - if (s.lookahead <= 1) { - - //Assert(s->strstart < s->w_size+MAX_DIST(s) || - // s->block_start >= (long)s->w_size, "slide too late"); - // if (!(s.strstart < s.w_size + (s.w_size - MIN_LOOKAHEAD) || - // s.block_start >= s.w_size)) { - // throw new Error("slide too late"); - // } - - fill_window(s); - if (s.lookahead === 0 && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - - if (s.lookahead === 0) { - break; - } - /* flush the current block */ - } - //Assert(s->block_start >= 0L, "block gone"); - // if (s.block_start < 0) throw new Error("block gone"); - - s.strstart += s.lookahead; - s.lookahead = 0; - - /* Emit a stored block if pending_buf will be full: */ - const max_start = s.block_start + max_block_size; - - if (s.strstart === 0 || s.strstart >= max_start) { - /* strstart == 0 is possible when wraparound on 16-bit machine */ - s.lookahead = s.strstart - max_start; - s.strstart = max_start; - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - - - } - /* Flush if we may have to slide, otherwise block_start may become - * negative and the data will be gone: - */ - if (s.strstart - s.block_start >= (s.w_size - MIN_LOOKAHEAD)) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } - - s.insert = 0; - - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - - if (s.strstart > s.block_start) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - - return BS_NEED_MORE; - } - - /* =========================================================================== - * Compress as much as possible from the input stream, return the current - * block state. - * This function does not perform lazy evaluation of matches and inserts - * new strings in the dictionary only for unmatched strings or for short - * matches. It is used only for the fast compression options. - */ - function deflate_fast(s, flush) { - let hash_head; /* head of the hash chain */ - let bflush; /* set if current block must be flushed */ - - for (; ;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s.lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - if (s.lookahead === 0) { - break; /* flush the current block */ - } - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - hash_head = 0/*NIL*/; - if (s.lookahead >= MIN_MATCH$1) { - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - } - - /* Find the longest match, discarding those <= prev_length. - * At this point we have always match_length < MIN_MATCH - */ - if (hash_head !== 0/*NIL*/ && ((s.strstart - hash_head) <= (s.w_size - MIN_LOOKAHEAD))) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - s.match_length = longest_match(s, hash_head); - /* longest_match() sets match_start */ - } - if (s.match_length >= MIN_MATCH$1) { - // check_match(s, s.strstart, s.match_start, s.match_length); // for debug only - - /*** _tr_tally_dist(s, s.strstart - s.match_start, - s.match_length - MIN_MATCH, bflush); ***/ - bflush = _tr_tally(s, s.strstart - s.match_start, s.match_length - MIN_MATCH$1); - - s.lookahead -= s.match_length; - - /* Insert new strings in the hash table only if the match length - * is not too large. This saves time but degrades compression. - */ - if (s.match_length <= s.max_lazy_match/*max_insert_length*/ && s.lookahead >= MIN_MATCH$1) { - s.match_length--; /* string at strstart already in table */ - do { - s.strstart++; - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - /* strstart never exceeds WSIZE-MAX_MATCH, so there are - * always MIN_MATCH bytes ahead. - */ - } while (--s.match_length !== 0); - s.strstart++; - } else { - s.strstart += s.match_length; - s.match_length = 0; - s.ins_h = s.window[s.strstart]; - /* UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]); */ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + 1]) & s.hash_mask; - - //#if MIN_MATCH != 3 - // Call UPDATE_HASH() MIN_MATCH-3 more times - //#endif - /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not - * matter since it will be recomputed at next deflate call. - */ - } - } else { - /* No match, output a literal byte */ - //Tracevv((stderr,"%c", s.window[s.strstart])); - /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ - bflush = _tr_tally(s, 0, s.window[s.strstart]); - - s.lookahead--; - s.strstart++; - } - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } - s.insert = ((s.strstart < (MIN_MATCH$1 - 1)) ? s.strstart : MIN_MATCH$1 - 1); - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - return BS_BLOCK_DONE; - } - - /* =========================================================================== - * Same as above, but achieves better compression. We use a lazy - * evaluation for matches: a match is finally adopted only if there is - * no better match at the next window position. - */ - function deflate_slow(s, flush) { - let hash_head; /* head of hash chain */ - let bflush; /* set if current block must be flushed */ - - let max_insert; - - /* Process the input block. */ - for (; ;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s.lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - if (s.lookahead === 0) { break; } /* flush the current block */ - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - hash_head = 0/*NIL*/; - if (s.lookahead >= MIN_MATCH$1) { - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - } - - /* Find the longest match, discarding those <= prev_length. - */ - s.prev_length = s.match_length; - s.prev_match = s.match_start; - s.match_length = MIN_MATCH$1 - 1; - - if (hash_head !== 0/*NIL*/ && s.prev_length < s.max_lazy_match && - s.strstart - hash_head <= (s.w_size - MIN_LOOKAHEAD)/*MAX_DIST(s)*/) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - s.match_length = longest_match(s, hash_head); - /* longest_match() sets match_start */ - - if (s.match_length <= 5 && - (s.strategy === Z_FILTERED || (s.match_length === MIN_MATCH$1 && s.strstart - s.match_start > 4096/*TOO_FAR*/))) { - - /* If prev_match is also MIN_MATCH, match_start is garbage - * but we will ignore the current match anyway. - */ - s.match_length = MIN_MATCH$1 - 1; - } - } - /* If there was a match at the previous step and the current - * match is not better, output the previous match: - */ - if (s.prev_length >= MIN_MATCH$1 && s.match_length <= s.prev_length) { - max_insert = s.strstart + s.lookahead - MIN_MATCH$1; - /* Do not insert strings in hash table beyond this. */ - - //check_match(s, s.strstart-1, s.prev_match, s.prev_length); - - /***_tr_tally_dist(s, s.strstart - 1 - s.prev_match, - s.prev_length - MIN_MATCH, bflush);***/ - bflush = _tr_tally(s, s.strstart - 1 - s.prev_match, s.prev_length - MIN_MATCH$1); - /* Insert in hash table all strings up to the end of the match. - * strstart-1 and strstart are already inserted. If there is not - * enough lookahead, the last two strings are not inserted in - * the hash table. - */ - s.lookahead -= s.prev_length - 1; - s.prev_length -= 2; - do { - if (++s.strstart <= max_insert) { - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - } - } while (--s.prev_length !== 0); - s.match_available = 0; - s.match_length = MIN_MATCH$1 - 1; - s.strstart++; - - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - - } else if (s.match_available) { - /* If there was no match at the previous position, output a - * single literal. If there was a match but the current match - * is longer, truncate the previous match to a single literal. - */ - //Tracevv((stderr,"%c", s->window[s->strstart-1])); - /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ - bflush = _tr_tally(s, 0, s.window[s.strstart - 1]); - - if (bflush) { - /*** FLUSH_BLOCK_ONLY(s, 0) ***/ - flush_block_only(s, false); - /***/ - } - s.strstart++; - s.lookahead--; - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - } else { - /* There is no previous match to compare with, wait for - * the next step to decide. - */ - s.match_available = 1; - s.strstart++; - s.lookahead--; - } - } - //Assert (flush != Z_NO_FLUSH, "no flush?"); - if (s.match_available) { - //Tracevv((stderr,"%c", s->window[s->strstart-1])); - /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ - bflush = _tr_tally(s, 0, s.window[s.strstart - 1]); - - s.match_available = 0; - } - s.insert = s.strstart < MIN_MATCH$1 - 1 ? s.strstart : MIN_MATCH$1 - 1; - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - - return BS_BLOCK_DONE; - } - - - /* =========================================================================== - * For Z_RLE, simply look for runs of bytes, generate matches only of distance - * one. Do not maintain a hash table. (It will be regenerated if this run of - * deflate switches away from Z_RLE.) - */ - function deflate_rle(s, flush) { - let bflush; /* set if current block must be flushed */ - let prev; /* byte at distance one to match */ - let scan, strend; /* scan goes up to strend for length of run */ - - const _win = s.window; - - for (; ;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the longest run, plus one for the unrolled loop. - */ - if (s.lookahead <= MAX_MATCH$1) { - fill_window(s); - if (s.lookahead <= MAX_MATCH$1 && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - if (s.lookahead === 0) { break; } /* flush the current block */ - } - - /* See how many times the previous byte repeats */ - s.match_length = 0; - if (s.lookahead >= MIN_MATCH$1 && s.strstart > 0) { - scan = s.strstart - 1; - prev = _win[scan]; - if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) { - strend = s.strstart + MAX_MATCH$1; - do { - /*jshint noempty:false*/ - } while (prev === _win[++scan] && prev === _win[++scan] && - prev === _win[++scan] && prev === _win[++scan] && - prev === _win[++scan] && prev === _win[++scan] && - prev === _win[++scan] && prev === _win[++scan] && - scan < strend); - s.match_length = MAX_MATCH$1 - (strend - scan); - if (s.match_length > s.lookahead) { - s.match_length = s.lookahead; - } - } - //Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); - } - - /* Emit match if have run of MIN_MATCH or longer, else emit literal */ - if (s.match_length >= MIN_MATCH$1) { - //check_match(s, s.strstart, s.strstart - 1, s.match_length); - - /*** _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ***/ - bflush = _tr_tally(s, 1, s.match_length - MIN_MATCH$1); - - s.lookahead -= s.match_length; - s.strstart += s.match_length; - s.match_length = 0; - } else { - /* No match, output a literal byte */ - //Tracevv((stderr,"%c", s->window[s->strstart])); - /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ - bflush = _tr_tally(s, 0, s.window[s.strstart]); - - s.lookahead--; - s.strstart++; - } - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } - s.insert = 0; - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - return BS_BLOCK_DONE; - } - - /* =========================================================================== - * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. - * (It will be regenerated if this run of deflate switches away from Huffman.) - */ - function deflate_huff(s, flush) { - let bflush; /* set if current block must be flushed */ - - for (; ;) { - /* Make sure that we have a literal to write. */ - if (s.lookahead === 0) { - fill_window(s); - if (s.lookahead === 0) { - if (flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - break; /* flush the current block */ - } - } - - /* Output a literal byte */ - s.match_length = 0; - //Tracevv((stderr,"%c", s->window[s->strstart])); - /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ - bflush = _tr_tally(s, 0, s.window[s.strstart]); - s.lookahead--; - s.strstart++; - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } - s.insert = 0; - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - return BS_BLOCK_DONE; - } - - /* Values for max_lazy_match, good_match and max_chain_length, depending on - * the desired pack level (0..9). The values given below have been tuned to - * exclude worst case performance for pathological files. Better values may be - * found for specific files. - */ - class Config { - constructor(good_length, max_lazy, nice_length, max_chain, func) { - this.good_length = good_length; - this.max_lazy = max_lazy; - this.nice_length = nice_length; - this.max_chain = max_chain; - this.func = func; - } - } - const configuration_table = [ - /* good lazy nice chain */ - new Config(0, 0, 0, 0, deflate_stored), /* 0 store only */ - new Config(4, 4, 8, 4, deflate_fast), /* 1 max speed, no lazy matches */ - new Config(4, 5, 16, 8, deflate_fast), /* 2 */ - new Config(4, 6, 32, 32, deflate_fast), /* 3 */ - - new Config(4, 4, 16, 16, deflate_slow), /* 4 lazy matches */ - new Config(8, 16, 32, 32, deflate_slow), /* 5 */ - new Config(8, 16, 128, 128, deflate_slow), /* 6 */ - new Config(8, 32, 128, 256, deflate_slow), /* 7 */ - new Config(32, 128, 258, 1024, deflate_slow), /* 8 */ - new Config(32, 258, 258, 4096, deflate_slow) /* 9 max compression */ - ]; - - - /* =========================================================================== - * Initialize the "longest match" routines for a new zlib stream - */ - function lm_init(s) { - s.window_size = 2 * s.w_size; - - /*** CLEAR_HASH(s); ***/ - zero$2(s.head); // Fill with NIL (= 0); - - /* Set the default configuration parameters: - */ - s.max_lazy_match = configuration_table[s.level].max_lazy; - s.good_match = configuration_table[s.level].good_length; - s.nice_match = configuration_table[s.level].nice_length; - s.max_chain_length = configuration_table[s.level].max_chain; - - s.strstart = 0; - s.block_start = 0; - s.lookahead = 0; - s.insert = 0; - s.match_length = s.prev_length = MIN_MATCH$1 - 1; - s.match_available = 0; - s.ins_h = 0; - } - - class DeflateState { - constructor() { - this.strm = null; /* pointer back to this zlib stream */ - this.status = 0; /* as the name implies */ - this.pending_buf = null; /* output still pending */ - this.pending_buf_size = 0; /* size of pending_buf */ - this.pending_out = 0; /* next pending byte to output to the stream */ - this.pending = 0; /* nb of bytes in the pending buffer */ - this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ - this.gzhead = null; /* gzip header information to write */ - this.gzindex = 0; /* where in extra, name, or comment */ - this.method = Z_DEFLATED; /* can only be DEFLATED */ - this.last_flush = -1; /* value of flush param for previous deflate call */ - - this.w_size = 0; /* LZ77 window size (32K by default) */ - this.w_bits = 0; /* log2(w_size) (8..16) */ - this.w_mask = 0; /* w_size - 1 */ - - this.window = null; - /* Sliding window. Input bytes are read into the second half of the window, - * and move to the first half later to keep a dictionary of at least wSize - * bytes. With this organization, matches are limited to a distance of - * wSize-MAX_MATCH bytes, but this ensures that IO is always - * performed with a length multiple of the block size. - */ - - this.window_size = 0; - /* Actual size of window: 2*wSize, except when the user input buffer - * is directly used as sliding window. - */ - - this.prev = null; - /* Link to older string with same hash index. To limit the size of this - * array to 64K, this link is maintained only for the last 32K strings. - * An index in this array is thus a window index modulo 32K. - */ - - this.head = null; /* Heads of the hash chains or NIL. */ - - this.ins_h = 0; /* hash index of string to be inserted */ - this.hash_size = 0; /* number of elements in hash table */ - this.hash_bits = 0; /* log2(hash_size) */ - this.hash_mask = 0; /* hash_size-1 */ - - this.hash_shift = 0; - /* Number of bits by which ins_h must be shifted at each input - * step. It must be such that after MIN_MATCH steps, the oldest - * byte no longer takes part in the hash key, that is: - * hash_shift * MIN_MATCH >= hash_bits - */ - - this.block_start = 0; - /* Window position at the beginning of the current output block. Gets - * negative when the window is moved backwards. - */ - - this.match_length = 0; /* length of best match */ - this.prev_match = 0; /* previous match */ - this.match_available = 0; /* set if previous match exists */ - this.strstart = 0; /* start of string to insert */ - this.match_start = 0; /* start of matching string */ - this.lookahead = 0; /* number of valid bytes ahead in window */ - - this.prev_length = 0; - /* Length of the best match at previous step. Matches not greater than this - * are discarded. This is used in the lazy match evaluation. - */ - - this.max_chain_length = 0; - /* To speed up deflation, hash chains are never searched beyond this - * length. A higher limit improves compression ratio but degrades the - * speed. - */ - - this.max_lazy_match = 0; - /* Attempt to find a better match only when the current match is strictly - * smaller than this value. This mechanism is used only for compression - * levels >= 4. - */ - // That's alias to max_lazy_match, don't use directly - //this.max_insert_length = 0; - /* Insert new strings in the hash table only if the match length is not - * greater than this length. This saves time but degrades compression. - * max_insert_length is used only for compression levels <= 3. - */ - - this.level = 0; /* compression level (1..9) */ - this.strategy = 0; /* favor or force Huffman coding*/ - - this.good_match = 0; - /* Use a faster search when the previous match is longer than this */ - - this.nice_match = 0; /* Stop searching when current match exceeds this */ - - /* used by trees.c: */ - - /* Didn't use ct_data typedef below to suppress compiler warning */ - - // struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ - // struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ - // struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ - - // Use flat array of DOUBLE size, with interleaved fata, - // because JS does not support effective - this.dyn_ltree = new Buf16(HEAP_SIZE$1 * 2); - this.dyn_dtree = new Buf16((2 * D_CODES$1 + 1) * 2); - this.bl_tree = new Buf16((2 * BL_CODES$1 + 1) * 2); - zero$2(this.dyn_ltree); - zero$2(this.dyn_dtree); - zero$2(this.bl_tree); - - this.l_desc = null; /* desc. for literal tree */ - this.d_desc = null; /* desc. for distance tree */ - this.bl_desc = null; /* desc. for bit length tree */ - - //ush bl_count[MAX_BITS+1]; - this.bl_count = new Buf16(MAX_BITS$1 + 1); - /* number of codes at each bit length for an optimal tree */ - - //int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ - this.heap = new Buf16(2 * L_CODES$1 + 1); /* heap used to build the Huffman trees */ - zero$2(this.heap); - - this.heap_len = 0; /* number of elements in the heap */ - this.heap_max = 0; /* element of largest frequency */ - /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. - * The same heap array is used to build all trees. - */ - - this.depth = new Buf16(2 * L_CODES$1 + 1); //uch depth[2*L_CODES+1]; - zero$2(this.depth); - /* Depth of each subtree used as tie breaker for trees of equal frequency - */ - - this.l_buf = 0; /* buffer index for literals or lengths */ - - this.lit_bufsize = 0; - /* Size of match buffer for literals/lengths. There are 4 reasons for - * limiting lit_bufsize to 64K: - * - frequencies can be kept in 16 bit counters - * - if compression is not successful for the first block, all input - * data is still in the window so we can still emit a stored block even - * when input comes from standard input. (This can also be done for - * all blocks if lit_bufsize is not greater than 32K.) - * - if compression is not successful for a file smaller than 64K, we can - * even emit a stored file instead of a stored block (saving 5 bytes). - * This is applicable only for zip (not gzip or zlib). - * - creating new Huffman trees less frequently may not provide fast - * adaptation to changes in the input data statistics. (Take for - * example a binary file with poorly compressible code followed by - * a highly compressible string table.) Smaller buffer sizes give - * fast adaptation but have of course the overhead of transmitting - * trees more frequently. - * - I can't count above 4 - */ - - this.last_lit = 0; /* running index in l_buf */ - - this.d_buf = 0; - /* Buffer index for distances. To simplify the code, d_buf and l_buf have - * the same number of elements. To use different lengths, an extra flag - * array would be necessary. - */ - - this.opt_len = 0; /* bit length of current block with optimal trees */ - this.static_len = 0; /* bit length of current block with static trees */ - this.matches = 0; /* number of string matches in current block */ - this.insert = 0; /* bytes at end of window left to insert */ - - - this.bi_buf = 0; - /* Output buffer. bits are inserted starting at the bottom (least - * significant bits). - */ - this.bi_valid = 0; - /* Number of valid bits in bi_buf. All bits above the last valid bit - * are always zero. - */ - - // Used for window memory init. We safely ignore it for JS. That makes - // sense only for pointers and memory check tools. - //this.high_water = 0; - /* High water mark offset in window for initialized bytes -- bytes above - * this are set to zero in order to avoid memory check warnings when - * longest match routines access bytes past the input. This is then - * updated to the new high water mark. - */ - } - } - - function deflateResetKeep(strm) { - let s; - - if (!strm || !strm.state) { - return err(strm, Z_STREAM_ERROR); - } - - strm.total_in = strm.total_out = 0; - strm.data_type = Z_UNKNOWN; - - s = strm.state; - s.pending = 0; - s.pending_out = 0; - - if (s.wrap < 0) { - s.wrap = -s.wrap; - /* was made negative by deflate(..., Z_FINISH); */ - } - s.status = (s.wrap ? INIT_STATE : BUSY_STATE); - strm.adler = (s.wrap === 2) ? - 0 // crc32(0, Z_NULL, 0) - : - 1; // adler32(0, Z_NULL, 0) - s.last_flush = Z_NO_FLUSH; - _tr_init(s); - return Z_OK; - } - - - function deflateReset(strm) { - const ret = deflateResetKeep(strm); - if (ret === Z_OK) { - lm_init(strm.state); - } - return ret; - } - - - function deflateSetHeader(strm, head) { - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - if (strm.state.wrap !== 2) { return Z_STREAM_ERROR; } - strm.state.gzhead = head; - return Z_OK; - } - - - function deflateInit2(strm, level, method, windowBits, memLevel, strategy) { - if (!strm) { // === Z_NULL - return Z_STREAM_ERROR; - } - let wrap = 1; - - if (level === Z_DEFAULT_COMPRESSION) { - level = 6; - } - - if (windowBits < 0) { /* suppress zlib wrapper */ - wrap = 0; - windowBits = -windowBits; - } - - else if (windowBits > 15) { - wrap = 2; /* write gzip wrapper instead */ - windowBits -= 16; - } - - - if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method !== Z_DEFLATED || - windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || - strategy < 0 || strategy > Z_FIXED) { - return err(strm, Z_STREAM_ERROR); - } - - - if (windowBits === 8) { - windowBits = 9; - } - /* until 256-byte window bug fixed */ - - const s = new DeflateState(); - - strm.state = s; - s.strm = strm; - - s.wrap = wrap; - s.gzhead = null; - s.w_bits = windowBits; - s.w_size = 1 << s.w_bits; - s.w_mask = s.w_size - 1; - - s.hash_bits = memLevel + 7; - s.hash_size = 1 << s.hash_bits; - s.hash_mask = s.hash_size - 1; - s.hash_shift = ~~((s.hash_bits + MIN_MATCH$1 - 1) / MIN_MATCH$1); - s.window = new Buf8(s.w_size * 2); - s.head = new Buf16(s.hash_size); - s.prev = new Buf16(s.w_size); - - // Don't need mem init magic for JS. - //s.high_water = 0; /* nothing written to s->window yet */ - - s.lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ - - s.pending_buf_size = s.lit_bufsize * 4; - - //overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); - //s->pending_buf = (uchf *) overlay; - s.pending_buf = new Buf8(s.pending_buf_size); - - // It is offset from `s.pending_buf` (size is `s.lit_bufsize * 2`) - //s->d_buf = overlay + s->lit_bufsize/sizeof(ush); - s.d_buf = 1 * s.lit_bufsize; - - //s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; - s.l_buf = (1 + 2) * s.lit_bufsize; - - s.level = level; - s.strategy = strategy; - s.method = method; - - return deflateReset(strm); - } - - - function deflate(strm, flush) { - let old_flush, s; - let beg, val; // for gzip header write only - - if (!strm || !strm.state || - flush > Z_BLOCK || flush < 0) { - return strm ? err(strm, Z_STREAM_ERROR) : Z_STREAM_ERROR; - } - - s = strm.state; - - if (!strm.output || - (!strm.input && strm.avail_in !== 0) || - (s.status === FINISH_STATE && flush !== Z_FINISH)) { - return err(strm, (strm.avail_out === 0) ? Z_BUF_ERROR : Z_STREAM_ERROR); - } - - s.strm = strm; /* just in case */ - old_flush = s.last_flush; - s.last_flush = flush; - - /* Write the header */ - if (s.status === INIT_STATE) { - - if (s.wrap === 2) { // GZIP header - strm.adler = 0; //crc32(0L, Z_NULL, 0); - put_byte(s, 31); - put_byte(s, 139); - put_byte(s, 8); - if (!s.gzhead) { // s->gzhead == Z_NULL - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, s.level === 9 ? 2 : - (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? - 4 : 0)); - put_byte(s, OS_CODE); - s.status = BUSY_STATE; - } - else { - put_byte(s, (s.gzhead.text ? 1 : 0) + - (s.gzhead.hcrc ? 2 : 0) + - (!s.gzhead.extra ? 0 : 4) + - (!s.gzhead.name ? 0 : 8) + - (!s.gzhead.comment ? 0 : 16) - ); - put_byte(s, s.gzhead.time & 0xff); - put_byte(s, (s.gzhead.time >> 8) & 0xff); - put_byte(s, (s.gzhead.time >> 16) & 0xff); - put_byte(s, (s.gzhead.time >> 24) & 0xff); - put_byte(s, s.level === 9 ? 2 : - (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? - 4 : 0)); - put_byte(s, s.gzhead.os & 0xff); - if (s.gzhead.extra && s.gzhead.extra.length) { - put_byte(s, s.gzhead.extra.length & 0xff); - put_byte(s, (s.gzhead.extra.length >> 8) & 0xff); - } - if (s.gzhead.hcrc) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending, 0); - } - s.gzindex = 0; - s.status = EXTRA_STATE; - } - } - else // DEFLATE header - { - let header = (Z_DEFLATED + ((s.w_bits - 8) << 4)) << 8; - let level_flags = -1; - - if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) { - level_flags = 0; - } else if (s.level < 6) { - level_flags = 1; - } else if (s.level === 6) { - level_flags = 2; - } else { - level_flags = 3; - } - header |= (level_flags << 6); - if (s.strstart !== 0) { header |= PRESET_DICT; } - header += 31 - (header % 31); - - s.status = BUSY_STATE; - putShortMSB(s, header); - - /* Save the adler32 of the preset dictionary: */ - if (s.strstart !== 0) { - putShortMSB(s, strm.adler >>> 16); - putShortMSB(s, strm.adler & 0xffff); - } - strm.adler = 1; // adler32(0L, Z_NULL, 0); - } - } - - //#ifdef GZIP - if (s.status === EXTRA_STATE) { - if (s.gzhead.extra/* != Z_NULL*/) { - beg = s.pending; /* start of bytes to update crc */ - - while (s.gzindex < (s.gzhead.extra.length & 0xffff)) { - if (s.pending === s.pending_buf_size) { - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - flush_pending(strm); - beg = s.pending; - if (s.pending === s.pending_buf_size) { - break; - } - } - put_byte(s, s.gzhead.extra[s.gzindex] & 0xff); - s.gzindex++; - } - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - if (s.gzindex === s.gzhead.extra.length) { - s.gzindex = 0; - s.status = NAME_STATE; - } - } - else { - s.status = NAME_STATE; - } - } - if (s.status === NAME_STATE) { - if (s.gzhead.name/* != Z_NULL*/) { - beg = s.pending; /* start of bytes to update crc */ - //int val; - - do { - if (s.pending === s.pending_buf_size) { - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - flush_pending(strm); - beg = s.pending; - if (s.pending === s.pending_buf_size) { - val = 1; - break; - } - } - // JS specific: little magic to add zero terminator to end of string - if (s.gzindex < s.gzhead.name.length) { - val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff; - } else { - val = 0; - } - put_byte(s, val); - } while (val !== 0); - - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - if (val === 0) { - s.gzindex = 0; - s.status = COMMENT_STATE; - } - } - else { - s.status = COMMENT_STATE; - } - } - if (s.status === COMMENT_STATE) { - if (s.gzhead.comment/* != Z_NULL*/) { - beg = s.pending; /* start of bytes to update crc */ - //int val; - - do { - if (s.pending === s.pending_buf_size) { - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - flush_pending(strm); - beg = s.pending; - if (s.pending === s.pending_buf_size) { - val = 1; - break; - } - } - // JS specific: little magic to add zero terminator to end of string - if (s.gzindex < s.gzhead.comment.length) { - val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff; - } else { - val = 0; - } - put_byte(s, val); - } while (val !== 0); - - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - if (val === 0) { - s.status = HCRC_STATE; - } - } - else { - s.status = HCRC_STATE; - } - } - if (s.status === HCRC_STATE) { - if (s.gzhead.hcrc) { - if (s.pending + 2 > s.pending_buf_size) { - flush_pending(strm); - } - if (s.pending + 2 <= s.pending_buf_size) { - put_byte(s, strm.adler & 0xff); - put_byte(s, (strm.adler >> 8) & 0xff); - strm.adler = 0; //crc32(0L, Z_NULL, 0); - s.status = BUSY_STATE; - } - } - else { - s.status = BUSY_STATE; - } - } - //#endif - - /* Flush as much pending output as possible */ - if (s.pending !== 0) { - flush_pending(strm); - if (strm.avail_out === 0) { - /* Since avail_out is 0, deflate will be called again with - * more output space, but possibly with both pending and - * avail_in equal to zero. There won't be anything to do, - * but this is not an error situation so make sure we - * return OK instead of BUF_ERROR at next call of deflate: - */ - s.last_flush = -1; - return Z_OK; - } - - /* Make sure there is something to do and avoid duplicate consecutive - * flushes. For repeated and useless calls with Z_FINISH, we keep - * returning Z_STREAM_END instead of Z_BUF_ERROR. - */ - } else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) && - flush !== Z_FINISH) { - return err(strm, Z_BUF_ERROR); - } - - /* User must not provide more input after the first FINISH: */ - if (s.status === FINISH_STATE && strm.avail_in !== 0) { - return err(strm, Z_BUF_ERROR); - } - - /* Start a new block or continue the current one. - */ - if (strm.avail_in !== 0 || s.lookahead !== 0 || - (flush !== Z_NO_FLUSH && s.status !== FINISH_STATE)) { - var bstate = (s.strategy === Z_HUFFMAN_ONLY) ? deflate_huff(s, flush) : - (s.strategy === Z_RLE ? deflate_rle(s, flush) : - configuration_table[s.level].func(s, flush)); - - if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) { - s.status = FINISH_STATE; - } - if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) { - if (strm.avail_out === 0) { - s.last_flush = -1; - /* avoid BUF_ERROR next call, see above */ - } - return Z_OK; - /* If flush != Z_NO_FLUSH && avail_out == 0, the next call - * of deflate should use the same flush parameter to make sure - * that the flush is complete. So we don't have to output an - * empty block here, this will be done at next call. This also - * ensures that for a very small output buffer, we emit at most - * one empty block. - */ - } - if (bstate === BS_BLOCK_DONE) { - if (flush === Z_PARTIAL_FLUSH) { - _tr_align(s); - } - else if (flush !== Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ - - _tr_stored_block(s, 0, 0, false); - /* For a full flush, this empty block will be recognized - * as a special marker by inflate_sync(). - */ - if (flush === Z_FULL_FLUSH) { - /*** CLEAR_HASH(s); ***/ /* forget history */ - zero$2(s.head); // Fill with NIL (= 0); - - if (s.lookahead === 0) { - s.strstart = 0; - s.block_start = 0; - s.insert = 0; - } - } - } - flush_pending(strm); - if (strm.avail_out === 0) { - s.last_flush = -1; /* avoid BUF_ERROR at next call, see above */ - return Z_OK; - } - } - } - //Assert(strm->avail_out > 0, "bug2"); - //if (strm.avail_out <= 0) { throw new Error("bug2");} - - if (flush !== Z_FINISH) { return Z_OK; } - if (s.wrap <= 0) { return Z_STREAM_END; } - - /* Write the trailer */ - if (s.wrap === 2) { - put_byte(s, strm.adler & 0xff); - put_byte(s, (strm.adler >> 8) & 0xff); - put_byte(s, (strm.adler >> 16) & 0xff); - put_byte(s, (strm.adler >> 24) & 0xff); - put_byte(s, strm.total_in & 0xff); - put_byte(s, (strm.total_in >> 8) & 0xff); - put_byte(s, (strm.total_in >> 16) & 0xff); - put_byte(s, (strm.total_in >> 24) & 0xff); - } - else { - putShortMSB(s, strm.adler >>> 16); - putShortMSB(s, strm.adler & 0xffff); - } - - flush_pending(strm); - /* If avail_out is zero, the application will call deflate again - * to flush the rest. - */ - if (s.wrap > 0) { s.wrap = -s.wrap; } - /* write the trailer only once! */ - return s.pending !== 0 ? Z_OK : Z_STREAM_END; - } - - function deflateEnd(strm) { - let status; - - if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) { - return Z_STREAM_ERROR; - } - - status = strm.state.status; - if (status !== INIT_STATE && - status !== EXTRA_STATE && - status !== NAME_STATE && - status !== COMMENT_STATE && - status !== HCRC_STATE && - status !== BUSY_STATE && - status !== FINISH_STATE - ) { - return err(strm, Z_STREAM_ERROR); - } - - strm.state = null; - - return status === BUSY_STATE ? err(strm, Z_DATA_ERROR) : Z_OK; - } - - - /* ========================================================================= - * Initializes the compression dictionary from the given byte - * sequence without producing any compressed output. - */ - function deflateSetDictionary(strm, dictionary) { - let dictLength = dictionary.length; - - let s; - let str, n; - let wrap; - let avail; - let next; - let input; - let tmpDict; - - if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) { - return Z_STREAM_ERROR; - } - - s = strm.state; - wrap = s.wrap; - - if (wrap === 2 || (wrap === 1 && s.status !== INIT_STATE) || s.lookahead) { - return Z_STREAM_ERROR; - } - - /* when using zlib wrappers, compute Adler-32 for provided dictionary */ - if (wrap === 1) { - /* adler32(strm->adler, dictionary, dictLength); */ - strm.adler = adler32(strm.adler, dictionary, dictLength, 0); - } - - s.wrap = 0; /* avoid computing Adler-32 in read_buf */ - - /* if dictionary would fill window, just replace the history */ - if (dictLength >= s.w_size) { - if (wrap === 0) { /* already empty otherwise */ - /*** CLEAR_HASH(s); ***/ - zero$2(s.head); // Fill with NIL (= 0); - s.strstart = 0; - s.block_start = 0; - s.insert = 0; - } - /* use the tail */ - // dictionary = dictionary.slice(dictLength - s.w_size); - tmpDict = new Buf8(s.w_size); - arraySet(tmpDict, dictionary, dictLength - s.w_size, s.w_size, 0); - dictionary = tmpDict; - dictLength = s.w_size; - } - /* insert dictionary into window and hash */ - avail = strm.avail_in; - next = strm.next_in; - input = strm.input; - strm.avail_in = dictLength; - strm.next_in = 0; - strm.input = dictionary; - fill_window(s); - while (s.lookahead >= MIN_MATCH$1) { - str = s.strstart; - n = s.lookahead - (MIN_MATCH$1 - 1); - do { - /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH$1 - 1]) & s.hash_mask; - - s.prev[str & s.w_mask] = s.head[s.ins_h]; - - s.head[s.ins_h] = str; - str++; - } while (--n); - s.strstart = str; - s.lookahead = MIN_MATCH$1 - 1; - fill_window(s); - } - s.strstart += s.lookahead; - s.block_start = s.strstart; - s.insert = s.lookahead; - s.lookahead = 0; - s.match_length = s.prev_length = MIN_MATCH$1 - 1; - s.match_available = 0; - strm.next_in = next; - strm.input = input; - strm.avail_in = avail; - s.wrap = wrap; - return Z_OK; - } - - /* Not implemented - exports.deflateBound = deflateBound; - exports.deflateCopy = deflateCopy; - exports.deflateParams = deflateParams; - exports.deflatePending = deflatePending; - exports.deflatePrime = deflatePrime; - exports.deflateTune = deflateTune; - */ - - // String encode/decode helpers - - try { - String.fromCharCode.apply(null, [ 0 ]); - } catch (__) { - } - try { - String.fromCharCode.apply(null, new Uint8Array(1)); - } catch (__) { - } - - - // Table with utf8 lengths (calculated by first byte of sequence) - // Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS, - // because max possible codepoint is 0x10ffff - const _utf8len = new Buf8(256); - for (let q = 0; q < 256; q++) { - _utf8len[q] = q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1; - } - _utf8len[254] = _utf8len[254] = 1; // Invalid sequence start - - - // convert string to array (typed, when possible) - function string2buf (str) { - let c, c2, m_pos, i, buf_len = 0; - const str_len = str.length; - - // count binary size - for (m_pos = 0; m_pos < str_len; m_pos++) { - c = str.charCodeAt(m_pos); - if ((c & 0xfc00) === 0xd800 && m_pos + 1 < str_len) { - c2 = str.charCodeAt(m_pos + 1); - if ((c2 & 0xfc00) === 0xdc00) { - c = 0x10000 + (c - 0xd800 << 10) + (c2 - 0xdc00); - m_pos++; - } - } - buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4; - } - - // allocate buffer - const buf = new Buf8(buf_len); - - // convert - for (i = 0, m_pos = 0; i < buf_len; m_pos++) { - c = str.charCodeAt(m_pos); - if ((c & 0xfc00) === 0xd800 && m_pos + 1 < str_len) { - c2 = str.charCodeAt(m_pos + 1); - if ((c2 & 0xfc00) === 0xdc00) { - c = 0x10000 + (c - 0xd800 << 10) + (c2 - 0xdc00); - m_pos++; - } - } - if (c < 0x80) { - /* one byte */ - buf[i++] = c; - } else if (c < 0x800) { - /* two bytes */ - buf[i++] = 0xC0 | c >>> 6; - buf[i++] = 0x80 | c & 0x3f; - } else if (c < 0x10000) { - /* three bytes */ - buf[i++] = 0xE0 | c >>> 12; - buf[i++] = 0x80 | c >>> 6 & 0x3f; - buf[i++] = 0x80 | c & 0x3f; - } else { - /* four bytes */ - buf[i++] = 0xf0 | c >>> 18; - buf[i++] = 0x80 | c >>> 12 & 0x3f; - buf[i++] = 0x80 | c >>> 6 & 0x3f; - buf[i++] = 0x80 | c & 0x3f; - } - } - - return buf; - } - - - // Convert binary string (typed, when possible) - function binstring2buf (str) { - const buf = new Buf8(str.length); - for (let i = 0, len = buf.length; i < len; i++) { - buf[i] = str.charCodeAt(i); - } - return buf; - } - - // (C) 1995-2013 Jean-loup Gailly and Mark Adler - // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin - // - // This software is provided 'as-is', without any express or implied - // warranty. In no event will the authors be held liable for any damages - // arising from the use of this software. - // - // Permission is granted to anyone to use this software for any purpose, - // including commercial applications, and to alter it and redistribute it - // freely, subject to the following restrictions: - // - // 1. The origin of this software must not be misrepresented; you must not - // claim that you wrote the original software. If you use this software - // in a product, an acknowledgment in the product documentation would be - // appreciated but is not required. - // 2. Altered source versions must be plainly marked as such, and must not be - // misrepresented as being the original software. - // 3. This notice may not be removed or altered from any source distribution. - - class ZStream { - constructor() { - /* next input byte */ - this.input = null; // JS specific, because we have no pointers - this.next_in = 0; - /* number of bytes available at input */ - this.avail_in = 0; - /* total number of input bytes read so far */ - this.total_in = 0; - /* next output byte should be put there */ - this.output = null; // JS specific, because we have no pointers - this.next_out = 0; - /* remaining free space at output */ - this.avail_out = 0; - /* total number of bytes output so far */ - this.total_out = 0; - /* last error message, NULL if no error */ - this.msg = ''/*Z_NULL*/; - /* not visible by applications */ - this.state = null; - /* best guess about the data type: binary or text */ - this.data_type = 2/*Z_UNKNOWN*/; - /* adler32 value of the uncompressed data */ - this.adler = 0; - } - } - - /* ===========================================================================*/ - - - /** - * class Deflate - * - * Generic JS-style wrapper for zlib calls. If you don't need - * streaming behaviour - use more simple functions: [[deflate]], - * [[deflateRaw]] and [[gzip]]. - **/ - - /* internal - * Deflate.chunks -> Array - * - * Chunks of output data, if [[Deflate#onData]] not overridden. - **/ - - /** - * Deflate.result -> Uint8Array|Array - * - * Compressed result, generated by default [[Deflate#onData]] - * and [[Deflate#onEnd]] handlers. Filled after you push last chunk - * (call [[Deflate#push]] with `Z_FINISH` / `true` param) or if you - * push a chunk with explicit flush (call [[Deflate#push]] with - * `Z_SYNC_FLUSH` param). - **/ - - /** - * Deflate.err -> Number - * - * Error code after deflate finished. 0 (Z_OK) on success. - * You will not need it in real life, because deflate errors - * are possible only on wrong options or bad `onData` / `onEnd` - * custom handlers. - **/ - - /** - * Deflate.msg -> String - * - * Error message, if [[Deflate.err]] != 0 - **/ - - - /** - * new Deflate(options) - * - options (Object): zlib deflate options. - * - * Creates new deflator instance with specified params. Throws exception - * on bad params. Supported options: - * - * - `level` - * - `windowBits` - * - `memLevel` - * - `strategy` - * - `dictionary` - * - * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) - * for more information on these. - * - * Additional options, for internal needs: - * - * - `chunkSize` - size of generated data chunks (16K by default) - * - `raw` (Boolean) - do raw deflate - * - `gzip` (Boolean) - create gzip wrapper - * - `to` (String) - if equal to 'string', then result will be "binary string" - * (each char code [0..255]) - * - `header` (Object) - custom header for gzip - * - `text` (Boolean) - true if compressed data believed to be text - * - `time` (Number) - modification time, unix timestamp - * - `os` (Number) - operation system code - * - `extra` (Array) - array of bytes with extra data (max 65536) - * - `name` (String) - file name (binary string) - * - `comment` (String) - comment (binary string) - * - `hcrc` (Boolean) - true if header crc should be added - * - * ##### Example: - * - * ```javascript - * var pako = void('pako') - * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9]) - * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]); - * - * var deflate = new pako.Deflate({ level: 3}); - * - * deflate.push(chunk1, false); - * deflate.push(chunk2, true); // true -> last chunk - * - * if (deflate.err) { throw new Error(deflate.err); } - * - * console.log(deflate.result); - * ``` - **/ - - class Deflate { - constructor(options) { - this.options = { - level: Z_DEFAULT_COMPRESSION, - method: Z_DEFLATED, - chunkSize: 16384, - windowBits: 15, - memLevel: 8, - strategy: Z_DEFAULT_STRATEGY, - ...(options || {}) - }; - - const opt = this.options; - - if (opt.raw && (opt.windowBits > 0)) { - opt.windowBits = -opt.windowBits; - } - - else if (opt.gzip && (opt.windowBits > 0) && (opt.windowBits < 16)) { - opt.windowBits += 16; - } - - this.err = 0; // error code, if happens (0 = Z_OK) - this.msg = ''; // error message - this.ended = false; // used to avoid multiple onEnd() calls - this.chunks = []; // chunks of compressed data - - this.strm = new ZStream(); - this.strm.avail_out = 0; - - var status = deflateInit2( - this.strm, - opt.level, - opt.method, - opt.windowBits, - opt.memLevel, - opt.strategy - ); - - if (status !== Z_OK) { - throw new Error(msg[status]); - } - - if (opt.header) { - deflateSetHeader(this.strm, opt.header); - } - - if (opt.dictionary) { - let dict; - // Convert data if needed - if (typeof opt.dictionary === 'string') { - // If we need to compress text, change encoding to utf8. - dict = string2buf(opt.dictionary); - } else if (opt.dictionary instanceof ArrayBuffer) { - dict = new Uint8Array(opt.dictionary); - } else { - dict = opt.dictionary; - } - - status = deflateSetDictionary(this.strm, dict); - - if (status !== Z_OK) { - throw new Error(msg[status]); - } - - this._dict_set = true; - } - } - - /** - * Deflate#push(data[, mode]) -> Boolean - * - data (Uint8Array|Array|ArrayBuffer|String): input data. Strings will be - * converted to utf8 byte sequence. - * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. - * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH. - * - * Sends input data to deflate pipe, generating [[Deflate#onData]] calls with - * new compressed chunks. Returns `true` on success. The last data block must have - * mode Z_FINISH (or `true`). That will flush internal pending buffers and call - * [[Deflate#onEnd]]. For interim explicit flushes (without ending the stream) you - * can use mode Z_SYNC_FLUSH, keeping the compression context. - * - * On fail call [[Deflate#onEnd]] with error code and return false. - * - * We strongly recommend to use `Uint8Array` on input for best speed (output - * array format is detected automatically). Also, don't skip last param and always - * use the same type in your code (boolean or number). That will improve JS speed. - * - * For regular `Array`-s make sure all elements are [0..255]. - * - * ##### Example - * - * ```javascript - * push(chunk, false); // push one of data chunks - * ... - * push(chunk, true); // push last chunk - * ``` - **/ - push(data, mode) { - const { strm, options: { chunkSize } } = this; - var status, _mode; - - if (this.ended) { return false; } - - _mode = (mode === ~~mode) ? mode : ((mode === true) ? Z_FINISH : Z_NO_FLUSH); - - // Convert data if needed - if (typeof data === 'string') { - // If we need to compress text, change encoding to utf8. - strm.input = string2buf(data); - } else if (data instanceof ArrayBuffer) { - strm.input = new Uint8Array(data); - } else { - strm.input = data; - } - - strm.next_in = 0; - strm.avail_in = strm.input.length; - - do { - if (strm.avail_out === 0) { - strm.output = new Buf8(chunkSize); - strm.next_out = 0; - strm.avail_out = chunkSize; - } - status = deflate(strm, _mode); /* no bad return value */ - - if (status !== Z_STREAM_END && status !== Z_OK) { - this.onEnd(status); - this.ended = true; - return false; - } - if (strm.avail_out === 0 || (strm.avail_in === 0 && (_mode === Z_FINISH || _mode === Z_SYNC_FLUSH))) { - this.onData(shrinkBuf(strm.output, strm.next_out)); - } - } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== Z_STREAM_END); - - // Finalize on the last chunk. - if (_mode === Z_FINISH) { - status = deflateEnd(this.strm); - this.onEnd(status); - this.ended = true; - return status === Z_OK; - } - - // callback interim results if Z_SYNC_FLUSH. - if (_mode === Z_SYNC_FLUSH) { - this.onEnd(Z_OK); - strm.avail_out = 0; - return true; - } - - return true; - }; - /** - * Deflate#onData(chunk) -> Void - * - chunk (Uint8Array|Array|String): output data. Type of array depends - * on js engine support. When string output requested, each chunk - * will be string. - * - * By default, stores data blocks in `chunks[]` property and glue - * those in `onEnd`. Override this handler, if you need another behaviour. - **/ - onData(chunk) { - this.chunks.push(chunk); - }; - - /** - * Deflate#onEnd(status) -> Void - * - status (Number): deflate status. 0 (Z_OK) on success, - * other if not. - * - * Called once after you tell deflate that the input stream is - * complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH) - * or if an error happened. By default - join collected chunks, - * free memory and fill `results` / `err` properties. - **/ - onEnd(status) { - // On success - join - if (status === Z_OK) { - this.result = flattenChunks(this.chunks); - } - this.chunks = []; - this.err = status; - this.msg = this.strm.msg; - }; - } - - // (C) 1995-2013 Jean-loup Gailly and Mark Adler - // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin - // - // This software is provided 'as-is', without any express or implied - // warranty. In no event will the authors be held liable for any damages - // arising from the use of this software. - // - // Permission is granted to anyone to use this software for any purpose, - // including commercial applications, and to alter it and redistribute it - // freely, subject to the following restrictions: - // - // 1. The origin of this software must not be misrepresented; you must not - // claim that you wrote the original software. If you use this software - // in a product, an acknowledgment in the product documentation would be - // appreciated but is not required. - // 2. Altered source versions must be plainly marked as such, and must not be - // misrepresented as being the original software. - // 3. This notice may not be removed or altered from any source distribution. - - // See state defs from inflate.js - const BAD = 30; /* got a data error -- remain here until reset */ - const TYPE = 12; /* i: waiting for type bits, including last-flag bit */ - - /* - Decode literal, length, and distance codes and write out the resulting - literal and match bytes until either not enough input or output is - available, an end-of-block is encountered, or a data error is encountered. - When large enough input and output buffers are supplied to inflate(), for - example, a 16K input buffer and a 64K output buffer, more than 95% of the - inflate execution time is spent in this routine. - - Entry assumptions: - - state.mode === LEN - strm.avail_in >= 6 - strm.avail_out >= 258 - start >= strm.avail_out - state.bits < 8 - - On return, state.mode is one of: - - LEN -- ran out of enough output space or enough available input - TYPE -- reached end of block code, inflate() to interpret next block - BAD -- error in block data - - Notes: - - - The maximum input bits used by a length/distance pair is 15 bits for the - length code, 5 bits for the length extra, 15 bits for the distance code, - and 13 bits for the distance extra. This totals 48 bits, or six bytes. - Therefore if strm.avail_in >= 6, then there is enough input to avoid - checking for available input while decoding. - - - The maximum bytes that a single length/distance pair can output is 258 - bytes, which is the maximum length that can be coded. inflate_fast() - requires strm.avail_out >= 258 for each loop to avoid checking for - output space. - */ - function inflate_fast(strm, start) { - let _in; /* local strm.input */ - let _out; /* local strm.output */ - // Use `s_window` instead `window`, avoid conflict with instrumentation tools - let hold; /* local strm.hold */ - let bits; /* local strm.bits */ - let here; /* retrieved table entry */ - let op; /* code bits, operation, extra bits, or */ - /* window position, window bytes to copy */ - let len; /* match length, unused bytes */ - let dist; /* match distance */ - let from; /* where to copy match from */ - let from_source; - - - - /* copy state to local variables */ - const state = strm.state; - //here = state.here; - _in = strm.next_in; - const input = strm.input; - const last = _in + (strm.avail_in - 5); - _out = strm.next_out; - const output = strm.output; - const beg = _out - (start - strm.avail_out); - const end = _out + (strm.avail_out - 257); - //#ifdef INFLATE_STRICT - const dmax = state.dmax; - //#endif - const wsize = state.wsize; - const whave = state.whave; - const wnext = state.wnext; - const s_window = state.window; - hold = state.hold; - bits = state.bits; - const lcode = state.lencode; - const dcode = state.distcode; - const lmask = (1 << state.lenbits) - 1; - const dmask = (1 << state.distbits) - 1; - - - /* decode literals and length/distances until end-of-block or not enough - input data or output space */ - - top: - do { - if (bits < 15) { - hold += input[_in++] << bits; - bits += 8; - hold += input[_in++] << bits; - bits += 8; - } - - here = lcode[hold & lmask]; - - dolen: - for (;;) { // Goto emulation - op = here >>> 24/*here.bits*/; - hold >>>= op; - bits -= op; - op = here >>> 16 & 0xff/*here.op*/; - if (op === 0) { /* literal */ - //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - // "inflate: literal '%c'\n" : - // "inflate: literal 0x%02x\n", here.val)); - output[_out++] = here & 0xffff/*here.val*/; - } else if (op & 16) { /* length base */ - len = here & 0xffff/*here.val*/; - op &= 15; /* number of extra bits */ - if (op) { - if (bits < op) { - hold += input[_in++] << bits; - bits += 8; - } - len += hold & (1 << op) - 1; - hold >>>= op; - bits -= op; - } - //Tracevv((stderr, "inflate: length %u\n", len)); - if (bits < 15) { - hold += input[_in++] << bits; - bits += 8; - hold += input[_in++] << bits; - bits += 8; - } - here = dcode[hold & dmask]; - - dodist: - for (;;) { // goto emulation - op = here >>> 24/*here.bits*/; - hold >>>= op; - bits -= op; - op = here >>> 16 & 0xff/*here.op*/; - - if (op & 16) { /* distance base */ - dist = here & 0xffff/*here.val*/; - op &= 15; /* number of extra bits */ - if (bits < op) { - hold += input[_in++] << bits; - bits += 8; - if (bits < op) { - hold += input[_in++] << bits; - bits += 8; - } - } - dist += hold & (1 << op) - 1; - //#ifdef INFLATE_STRICT - if (dist > dmax) { - strm.msg = "invalid distance too far back"; - state.mode = BAD; - break top; - } - //#endif - hold >>>= op; - bits -= op; - //Tracevv((stderr, "inflate: distance %u\n", dist)); - op = _out - beg; /* max distance in output */ - if (dist > op) { /* see if copy from window */ - op = dist - op; /* distance back in window */ - if (op > whave) { - if (state.sane) { - strm.msg = "invalid distance too far back"; - state.mode = BAD; - break top; - } - - // (!) This block is disabled in zlib defaults, - // don't enable it for binary compatibility - //#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR - // if (len <= op - whave) { - // do { - // output[_out++] = 0; - // } while (--len); - // continue top; - // } - // len -= op - whave; - // do { - // output[_out++] = 0; - // } while (--op > whave); - // if (op === 0) { - // from = _out - dist; - // do { - // output[_out++] = output[from++]; - // } while (--len); - // continue top; - // } - //#endif - } - from = 0; // window index - from_source = s_window; - if (wnext === 0) { /* very common case */ - from += wsize - op; - if (op < len) { /* some from window */ - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = _out - dist; /* rest from output */ - from_source = output; - } - } else if (wnext < op) { /* wrap around window */ - from += wsize + wnext - op; - op -= wnext; - if (op < len) { /* some from end of window */ - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = 0; - if (wnext < len) { /* some from start of window */ - op = wnext; - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = _out - dist; /* rest from output */ - from_source = output; - } - } - } else { /* contiguous in window */ - from += wnext - op; - if (op < len) { /* some from window */ - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = _out - dist; /* rest from output */ - from_source = output; - } - } - while (len > 2) { - output[_out++] = from_source[from++]; - output[_out++] = from_source[from++]; - output[_out++] = from_source[from++]; - len -= 3; - } - if (len) { - output[_out++] = from_source[from++]; - if (len > 1) { - output[_out++] = from_source[from++]; - } - } - } else { - from = _out - dist; /* copy direct from output */ - do { /* minimum length is three */ - output[_out++] = output[from++]; - output[_out++] = output[from++]; - output[_out++] = output[from++]; - len -= 3; - } while (len > 2); - if (len) { - output[_out++] = output[from++]; - if (len > 1) { - output[_out++] = output[from++]; - } - } - } - } else if ((op & 64) === 0) { /* 2nd level distance code */ - here = dcode[(here & 0xffff)/*here.val*/ + (hold & (1 << op) - 1)]; - continue dodist; - } else { - strm.msg = "invalid distance code"; - state.mode = BAD; - break top; - } - - break; // need to emulate goto via "continue" - } - } else if ((op & 64) === 0) { /* 2nd level length code */ - here = lcode[(here & 0xffff)/*here.val*/ + (hold & (1 << op) - 1)]; - continue dolen; - } else if (op & 32) { /* end-of-block */ - //Tracevv((stderr, "inflate: end of block\n")); - state.mode = TYPE; - break top; - } else { - strm.msg = "invalid literal/length code"; - state.mode = BAD; - break top; - } - - break; // need to emulate goto via "continue" - } - } while (_in < last && _out < end); - - /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ - len = bits >> 3; - _in -= len; - bits -= len << 3; - hold &= (1 << bits) - 1; - - /* update state and return */ - strm.next_in = _in; - strm.next_out = _out; - strm.avail_in = _in < last ? 5 + (last - _in) : 5 - (_in - last); - strm.avail_out = _out < end ? 257 + (end - _out) : 257 - (_out - end); - state.hold = hold; - state.bits = bits; - return; - } - - const MAXBITS = 15; - const ENOUGH_LENS = 852; - const ENOUGH_DISTS = 592; - //var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); - - const CODES = 0; - const LENS = 1; - const DISTS = 2; - - const lbase = [ /* Length codes 257..285 base */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 - ]; - - const lext = [ /* Length codes 257..285 extra */ - 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78 - ]; - - const dbase = [ /* Distance codes 0..29 base */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577, 0, 0 - ]; - - const dext = [ /* Distance codes 0..29 extra */ - 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, - 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, - 28, 28, 29, 29, 64, 64 - ]; - - function inflate_table(type, lens, lens_index, codes, table, table_index, work, opts) { - const bits = opts.bits; - //here = opts.here; /* table entry for duplication */ - - let len = 0; /* a code's length in bits */ - let sym = 0; /* index of code symbols */ - let min = 0, max = 0; /* minimum and maximum code lengths */ - let root = 0; /* number of index bits for root table */ - let curr = 0; /* number of index bits for current table */ - let drop = 0; /* code bits to drop for sub-table */ - let left = 0; /* number of prefix codes available */ - let used = 0; /* code entries in table used */ - let huff = 0; /* Huffman code */ - let incr; /* for incrementing code, index */ - let fill; /* index for replicating entries */ - let low; /* low bits for current root entry */ - let next; /* next available space in table */ - let base = null; /* base value table to use */ - let base_index = 0; - // var shoextra; /* extra bits table to use */ - let end; /* use base and extra for symbol > end */ - const count = new Buf16(MAXBITS + 1); //[MAXBITS+1]; /* number of codes of each length */ - const offs = new Buf16(MAXBITS + 1); //[MAXBITS+1]; /* offsets in table for each length */ - let extra = null; - let extra_index = 0; - - let here_bits, here_op, here_val; - - /* - Process a set of code lengths to create a canonical Huffman code. The - code lengths are lens[0..codes-1]. Each length corresponds to the - symbols 0..codes-1. The Huffman code is generated by first sorting the - symbols by length from short to long, and retaining the symbol order - for codes with equal lengths. Then the code starts with all zero bits - for the first code of the shortest length, and the codes are integer - increments for the same length, and zeros are appended as the length - increases. For the deflate format, these bits are stored backwards - from their more natural integer increment ordering, and so when the - decoding tables are built in the large loop below, the integer codes - are incremented backwards. - - This routine assumes, but does not check, that all of the entries in - lens[] are in the range 0..MAXBITS. The caller must assure this. - 1..MAXBITS is interpreted as that code length. zero means that that - symbol does not occur in this code. - - The codes are sorted by computing a count of codes for each length, - creating from that a table of starting indices for each length in the - sorted table, and then entering the symbols in order in the sorted - table. The sorted table is work[], with that space being provided by - the caller. - - The length counts are used for other purposes as well, i.e. finding - the minimum and maximum length codes, determining if there are any - codes at all, checking for a valid set of lengths, and looking ahead - at length counts to determine sub-table sizes when building the - decoding tables. - */ - - /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ - for (len = 0; len <= MAXBITS; len++) { - count[len] = 0; - } - for (sym = 0; sym < codes; sym++) { - count[lens[lens_index + sym]]++; - } - - /* bound code lengths, force root to be within code lengths */ - root = bits; - for (max = MAXBITS; max >= 1; max--) { - if (count[max] !== 0) { - break; - } - } - if (root > max) { - root = max; - } - if (max === 0) { /* no symbols to code at all */ - //table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */ - //table.bits[opts.table_index] = 1; //here.bits = (var char)1; - //table.val[opts.table_index++] = 0; //here.val = (var short)0; - table[table_index++] = 1 << 24 | 64 << 16 | 0; - - - //table.op[opts.table_index] = 64; - //table.bits[opts.table_index] = 1; - //table.val[opts.table_index++] = 0; - table[table_index++] = 1 << 24 | 64 << 16 | 0; - - opts.bits = 1; - return 0; /* no symbols, but wait for decoding to report error */ - } - for (min = 1; min < max; min++) { - if (count[min] !== 0) { - break; - } - } - if (root < min) { - root = min; - } - - /* check for an over-subscribed or incomplete set of lengths */ - left = 1; - for (len = 1; len <= MAXBITS; len++) { - left <<= 1; - left -= count[len]; - if (left < 0) { - return -1; - } /* over-subscribed */ - } - if (left > 0 && (type === CODES || max !== 1)) { - return -1; /* incomplete set */ - } - - /* generate offsets into symbol table for each length for sorting */ - offs[1] = 0; - for (len = 1; len < MAXBITS; len++) { - offs[len + 1] = offs[len] + count[len]; - } - - /* sort symbols by length, by symbol order within each length */ - for (sym = 0; sym < codes; sym++) { - if (lens[lens_index + sym] !== 0) { - work[offs[lens[lens_index + sym]]++] = sym; - } - } - - /* - Create and fill in decoding tables. In this loop, the table being - filled is at next and has curr index bits. The code being used is huff - with length len. That code is converted to an index by dropping drop - bits off of the bottom. For codes where len is less than drop + curr, - those top drop + curr - len bits are incremented through all values to - fill the table with replicated entries. - - root is the number of index bits for the root table. When len exceeds - root, sub-tables are created pointed to by the root entry with an index - of the low root bits of huff. This is saved in low to check for when a - new sub-table should be started. drop is zero when the root table is - being filled, and drop is root when sub-tables are being filled. - - When a new sub-table is needed, it is necessary to look ahead in the - code lengths to determine what size sub-table is needed. The length - counts are used for this, and so count[] is decremented as codes are - entered in the tables. - - used keeps track of how many table entries have been allocated from the - provided *table space. It is checked for LENS and DIST tables against - the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in - the initial root table size constants. See the comments in inftrees.h - for more information. - - sym increments through all symbols, and the loop terminates when - all codes of length max, i.e. all codes, have been processed. This - routine permits incomplete codes, so another loop after this one fills - in the rest of the decoding tables with invalid code markers. - */ - - /* set up for code type */ - // poor man optimization - use if-else instead of switch, - // to avoid deopts in old v8 - if (type === CODES) { - base = extra = work; /* dummy value--not used */ - end = 19; - - } else if (type === LENS) { - base = lbase; - base_index -= 257; - extra = lext; - extra_index -= 257; - end = 256; - - } else { /* DISTS */ - base = dbase; - extra = dext; - end = -1; - } - - /* initialize opts for loop */ - huff = 0; /* starting code */ - sym = 0; /* starting code symbol */ - len = min; /* starting code length */ - next = table_index; /* current table to fill in */ - curr = root; /* current table index bits */ - drop = 0; /* current bits to drop from code for index */ - low = -1; /* trigger new sub-table when len > root */ - used = 1 << root; /* use root table entries */ - const mask = used - 1; /* mask for comparing low */ - - /* check available table space */ - if (type === LENS && used > ENOUGH_LENS || - type === DISTS && used > ENOUGH_DISTS) { - return 1; - } - - /* process all codes and make table entries */ - for (;;) { - /* create table entry */ - here_bits = len - drop; - if (work[sym] < end) { - here_op = 0; - here_val = work[sym]; - } else if (work[sym] > end) { - here_op = extra[extra_index + work[sym]]; - here_val = base[base_index + work[sym]]; - } else { - here_op = 32 + 64; /* end of block */ - here_val = 0; - } - - /* replicate for those indices with low len bits equal to huff */ - incr = 1 << len - drop; - fill = 1 << curr; - min = fill; /* save offset to next table */ - do { - fill -= incr; - table[next + (huff >> drop) + fill] = here_bits << 24 | here_op << 16 | here_val |0; - } while (fill !== 0); - - /* backwards increment the len-bit code huff */ - incr = 1 << len - 1; - while (huff & incr) { - incr >>= 1; - } - if (incr !== 0) { - huff &= incr - 1; - huff += incr; - } else { - huff = 0; - } - - /* go to next symbol, update count, len */ - sym++; - if (--count[len] === 0) { - if (len === max) { - break; - } - len = lens[lens_index + work[sym]]; - } - - /* create new sub-table if needed */ - if (len > root && (huff & mask) !== low) { - /* if first time, transition to sub-tables */ - if (drop === 0) { - drop = root; - } - - /* increment past last table */ - next += min; /* here min is 1 << curr */ - - /* determine length of next table */ - curr = len - drop; - left = 1 << curr; - while (curr + drop < max) { - left -= count[curr + drop]; - if (left <= 0) { - break; - } - curr++; - left <<= 1; - } - - /* check for enough space */ - used += 1 << curr; - if (type === LENS && used > ENOUGH_LENS || - type === DISTS && used > ENOUGH_DISTS) { - return 1; - } - - /* point entry in root table to sub-table */ - low = huff & mask; - /*table.op[low] = curr; - table.bits[low] = root; - table.val[low] = next - opts.table_index;*/ - table[low] = root << 24 | curr << 16 | next - table_index |0; - } - } - - /* fill in remaining table entry if code is incomplete (guaranteed to have - at most one remaining entry, since if the code is incomplete, the - maximum code length that was allowed to get this far is one bit) */ - if (huff !== 0) { - //table.op[next + huff] = 64; /* invalid code marker */ - //table.bits[next + huff] = len - drop; - //table.val[next + huff] = 0; - table[next + huff] = len - drop << 24 | 64 << 16 |0; - } - - /* set return parameters */ - //opts.table_index += used; - opts.bits = root; - return 0; - } - - const CODES$1 = 0; - const LENS$1 = 1; - const DISTS$1 = 2; - - /* STATES ====================================================================*/ - /* ===========================================================================*/ - - - const HEAD = 1; /* i: waiting for magic header */ - const FLAGS = 2; /* i: waiting for method and flags (gzip) */ - const TIME = 3; /* i: waiting for modification time (gzip) */ - const OS = 4; /* i: waiting for extra flags and operating system (gzip) */ - const EXLEN = 5; /* i: waiting for extra length (gzip) */ - const EXTRA = 6; /* i: waiting for extra bytes (gzip) */ - const NAME = 7; /* i: waiting for end of file name (gzip) */ - const COMMENT = 8; /* i: waiting for end of comment (gzip) */ - const HCRC = 9; /* i: waiting for header crc (gzip) */ - const DICTID = 10; /* i: waiting for dictionary check value */ - const DICT = 11; /* waiting for inflateSetDictionary() call */ - const TYPE$1 = 12; /* i: waiting for type bits, including last-flag bit */ - const TYPEDO = 13; /* i: same, but skip check to exit inflate on new block */ - const STORED = 14; /* i: waiting for stored size (length and complement) */ - const COPY_ = 15; /* i/o: same as COPY below, but only first time in */ - const COPY = 16; /* i/o: waiting for input or output to copy stored block */ - const TABLE = 17; /* i: waiting for dynamic block table lengths */ - const LENLENS = 18; /* i: waiting for code length code lengths */ - const CODELENS = 19; /* i: waiting for length/lit and distance code lengths */ - const LEN_ = 20; /* i: same as LEN below, but only first time in */ - const LEN = 21; /* i: waiting for length/lit/eob code */ - const LENEXT = 22; /* i: waiting for length extra bits */ - const DIST = 23; /* i: waiting for distance code */ - const DISTEXT = 24; /* i: waiting for distance extra bits */ - const MATCH = 25; /* o: waiting for output space to copy string */ - const LIT = 26; /* o: waiting for output space to write literal */ - const CHECK = 27; /* i: waiting for 32-bit check value */ - const LENGTH = 28; /* i: waiting for 32-bit length (gzip) */ - const DONE = 29; /* finished check, done -- remain here until reset */ - const BAD$1 = 30; /* got a data error -- remain here until reset */ - //const MEM = 31; /* got an inflate() memory error -- remain here until reset */ - const SYNC = 32; /* looking for synchronization bytes to restart inflate() */ - - /* ===========================================================================*/ - - - - const ENOUGH_LENS$1 = 852; - const ENOUGH_DISTS$1 = 592; - - - function zswap32(q) { - return (((q >>> 24) & 0xff) + - ((q >>> 8) & 0xff00) + - ((q & 0xff00) << 8) + - ((q & 0xff) << 24)); - } - - - class InflateState { - constructor() { - this.mode = 0; /* current inflate mode */ - this.last = false; /* true if processing last block */ - this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ - this.havedict = false; /* true if dictionary provided */ - this.flags = 0; /* gzip header method and flags (0 if zlib) */ - this.dmax = 0; /* zlib header max distance (INFLATE_STRICT) */ - this.check = 0; /* protected copy of check value */ - this.total = 0; /* protected copy of output count */ - // TODO: may be {} - this.head = null; /* where to save gzip header information */ - - /* sliding window */ - this.wbits = 0; /* log base 2 of requested window size */ - this.wsize = 0; /* window size or zero if not using window */ - this.whave = 0; /* valid bytes in the window */ - this.wnext = 0; /* window write index */ - this.window = null; /* allocated sliding window, if needed */ - - /* bit accumulator */ - this.hold = 0; /* input bit accumulator */ - this.bits = 0; /* number of bits in "in" */ - - /* for string and stored block copying */ - this.length = 0; /* literal or length of data to copy */ - this.offset = 0; /* distance back to copy string from */ - - /* for table and code decoding */ - this.extra = 0; /* extra bits needed */ - - /* fixed and dynamic code tables */ - this.lencode = null; /* starting table for length/literal codes */ - this.distcode = null; /* starting table for distance codes */ - this.lenbits = 0; /* index bits for lencode */ - this.distbits = 0; /* index bits for distcode */ - - /* dynamic table building */ - this.ncode = 0; /* number of code length code lengths */ - this.nlen = 0; /* number of length code lengths */ - this.ndist = 0; /* number of distance code lengths */ - this.have = 0; /* number of code lengths in lens[] */ - this.next = null; /* next available space in codes[] */ - - this.lens = new Buf16(320); /* temporary storage for code lengths */ - this.work = new Buf16(288); /* work area for code table building */ - - /* - because we don't have pointers in js, we use lencode and distcode directly - as buffers so we don't need codes - */ - //this.codes = new utils.Buf32(ENOUGH); /* space for code tables */ - this.lendyn = null; /* dynamic table for length/literal codes (JS specific) */ - this.distdyn = null; /* dynamic table for distance codes (JS specific) */ - this.sane = 0; /* if false, allow invalid distance too far */ - this.back = 0; /* bits back of last unprocessed length/lit */ - this.was = 0; /* initial length of match */ - } - } - - function inflateResetKeep(strm) { - let state; - - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - strm.total_in = strm.total_out = state.total = 0; - strm.msg = ''; /*Z_NULL*/ - if (state.wrap) { /* to support ill-conceived Java test suite */ - strm.adler = state.wrap & 1; - } - state.mode = HEAD; - state.last = 0; - state.havedict = 0; - state.dmax = 32768; - state.head = null/*Z_NULL*/; - state.hold = 0; - state.bits = 0; - //state.lencode = state.distcode = state.next = state.codes; - state.lencode = state.lendyn = new Buf32(ENOUGH_LENS$1); - state.distcode = state.distdyn = new Buf32(ENOUGH_DISTS$1); - - state.sane = 1; - state.back = -1; - //Tracev((stderr, "inflate: reset\n")); - return Z_OK; - } - - function inflateReset(strm) { - let state; - - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - state.wsize = 0; - state.whave = 0; - state.wnext = 0; - return inflateResetKeep(strm); - - } - - function inflateReset2(strm, windowBits) { - let wrap; - let state; - - /* get the state */ - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - - /* extract wrap request from windowBits parameter */ - if (windowBits < 0) { - wrap = 0; - windowBits = -windowBits; - } - else { - wrap = (windowBits >> 4) + 1; - if (windowBits < 48) { - windowBits &= 15; - } - } - - /* set number of window bits, free window if different */ - if (windowBits && (windowBits < 8 || windowBits > 15)) { - return Z_STREAM_ERROR; - } - if (state.window !== null && state.wbits !== windowBits) { - state.window = null; - } - - /* update state and reset the rest of it */ - state.wrap = wrap; - state.wbits = windowBits; - return inflateReset(strm); - } - - function inflateInit2(strm, windowBits) { - let ret; - let state; - - if (!strm) { return Z_STREAM_ERROR; } - //strm.msg = Z_NULL; /* in case we return an error */ - - state = new InflateState(); - - //if (state === Z_NULL) return Z_MEM_ERROR; - //Tracev((stderr, "inflate: allocated\n")); - strm.state = state; - state.window = null/*Z_NULL*/; - ret = inflateReset2(strm, windowBits); - if (ret !== Z_OK) { - strm.state = null/*Z_NULL*/; - } - return ret; - } - - - /* - Return state with length and distance decoding tables and index sizes set to - fixed code decoding. Normally this returns fixed tables from inffixed.h. - If BUILDFIXED is defined, then instead this routine builds the tables the - first time it's called, and returns those tables the first time and - thereafter. This reduces the size of the code by about 2K bytes, in - exchange for a little execution time. However, BUILDFIXED should not be - used for threaded applications, since the rewriting of the tables and virgin - may not be thread-safe. - */ - let virgin = true; - - let lenfix, distfix; // We have no pointers in JS, so keep tables separate - - function fixedtables(state) { - /* build fixed huffman tables if first call (may not be thread safe) */ - if (virgin) { - let sym; - - lenfix = new Buf32(512); - distfix = new Buf32(32); - - /* literal/length table */ - sym = 0; - while (sym < 144) { state.lens[sym++] = 8; } - while (sym < 256) { state.lens[sym++] = 9; } - while (sym < 280) { state.lens[sym++] = 7; } - while (sym < 288) { state.lens[sym++] = 8; } - - inflate_table(LENS$1, state.lens, 0, 288, lenfix, 0, state.work, { bits: 9 }); - - /* distance table */ - sym = 0; - while (sym < 32) { state.lens[sym++] = 5; } - - inflate_table(DISTS$1, state.lens, 0, 32, distfix, 0, state.work, { bits: 5 }); - - /* do this just once */ - virgin = false; - } - - state.lencode = lenfix; - state.lenbits = 9; - state.distcode = distfix; - state.distbits = 5; - } - - - /* - Update the window with the last wsize (normally 32K) bytes written before - returning. If window does not exist yet, create it. This is only called - when a window is already in use, or when output has been written during this - inflate call, but the end of the deflate stream has not been reached yet. - It is also called to create a window for dictionary data when a dictionary - is loaded. - - Providing output buffers larger than 32K to inflate() should provide a speed - advantage, since only the last 32K of output is copied to the sliding window - upon return from inflate(), and since all distances after the first 32K of - output will fall in the output data, making match copies simpler and faster. - The advantage may be dependent on the size of the processor's data caches. - */ - function updatewindow(strm, src, end, copy) { - let dist; - const state = strm.state; - - /* if it hasn't been done already, allocate space for the window */ - if (state.window === null) { - state.wsize = 1 << state.wbits; - state.wnext = 0; - state.whave = 0; - - state.window = new Buf8(state.wsize); - } - - /* copy state->wsize or less output bytes into the circular window */ - if (copy >= state.wsize) { - arraySet(state.window, src, end - state.wsize, state.wsize, 0); - state.wnext = 0; - state.whave = state.wsize; - } - else { - dist = state.wsize - state.wnext; - if (dist > copy) { - dist = copy; - } - //zmemcpy(state->window + state->wnext, end - copy, dist); - arraySet(state.window, src, end - copy, dist, state.wnext); - copy -= dist; - if (copy) { - //zmemcpy(state->window, end - copy, copy); - arraySet(state.window, src, end - copy, copy, 0); - state.wnext = copy; - state.whave = state.wsize; - } - else { - state.wnext += dist; - if (state.wnext === state.wsize) { state.wnext = 0; } - if (state.whave < state.wsize) { state.whave += dist; } - } - } - return 0; - } - - function inflate(strm, flush) { - let state; - let input, output; // input/output buffers - let next; /* next input INDEX */ - let put; /* next output INDEX */ - let have, left; /* available input and output */ - let hold; /* bit buffer */ - let bits; /* bits in bit buffer */ - let _in, _out; /* save starting available input and output */ - let copy; /* number of stored or match bytes to copy */ - let from; /* where to copy match bytes from */ - let from_source; - let here = 0; /* current decoding table entry */ - let here_bits, here_op, here_val; // paked "here" denormalized (JS specific) - //var last; /* parent table entry */ - let last_bits, last_op, last_val; // paked "last" denormalized (JS specific) - let len; /* length to copy for repeats, bits to drop */ - let ret; /* return code */ - let hbuf = new Buf8(4); /* buffer for gzip header crc calculation */ - let opts; - - let n; // temporary var for NEED_BITS - - const order = /* permutation of code lengths */ - [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ]; - - - if (!strm || !strm.state || !strm.output || - (!strm.input && strm.avail_in !== 0)) { - return Z_STREAM_ERROR; - } - - state = strm.state; - if (state.mode === TYPE$1) { state.mode = TYPEDO; } /* skip check */ - - - //--- LOAD() --- - put = strm.next_out; - output = strm.output; - left = strm.avail_out; - next = strm.next_in; - input = strm.input; - have = strm.avail_in; - hold = state.hold; - bits = state.bits; - //--- - - _in = have; - _out = left; - ret = Z_OK; - - inf_leave: // goto emulation - for (;;) { - switch (state.mode) { - case HEAD: - if (state.wrap === 0) { - state.mode = TYPEDO; - break; - } - //=== NEEDBITS(16); - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if ((state.wrap & 2) && hold === 0x8b1f) { /* gzip header */ - state.check = 0/*crc32(0L, Z_NULL, 0)*/; - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = FLAGS; - break; - } - state.flags = 0; /* expect zlib header */ - if (state.head) { - state.head.done = false; - } - if (!(state.wrap & 1) || /* check if zlib header allowed */ - (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) { - strm.msg = 'incorrect header check'; - state.mode = BAD$1; - break; - } - if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) { - strm.msg = 'unknown compression method'; - state.mode = BAD$1; - break; - } - //--- DROPBITS(4) ---// - hold >>>= 4; - bits -= 4; - //---// - len = (hold & 0x0f)/*BITS(4)*/ + 8; - if (state.wbits === 0) { - state.wbits = len; - } - else if (len > state.wbits) { - strm.msg = 'invalid window size'; - state.mode = BAD$1; - break; - } - state.dmax = 1 << len; - //Tracev((stderr, "inflate: zlib header ok\n")); - strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; - state.mode = hold & 0x200 ? DICTID : TYPE$1; - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - break; - case FLAGS: - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.flags = hold; - if ((state.flags & 0xff) !== Z_DEFLATED) { - strm.msg = 'unknown compression method'; - state.mode = BAD$1; - break; - } - if (state.flags & 0xe000) { - strm.msg = 'unknown header flags set'; - state.mode = BAD$1; - break; - } - if (state.head) { - state.head.text = ((hold >> 8) & 1); - } - if (state.flags & 0x0200) { - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = TIME; - /* falls through */ - case TIME: - //=== NEEDBITS(32); */ - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (state.head) { - state.head.time = hold; - } - if (state.flags & 0x0200) { - //=== CRC4(state.check, hold) - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - hbuf[2] = (hold >>> 16) & 0xff; - hbuf[3] = (hold >>> 24) & 0xff; - state.check = crc32(state.check, hbuf, 4, 0); - //=== - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = OS; - /* falls through */ - case OS: - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (state.head) { - state.head.xflags = (hold & 0xff); - state.head.os = (hold >> 8); - } - if (state.flags & 0x0200) { - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = EXLEN; - /* falls through */ - case EXLEN: - if (state.flags & 0x0400) { - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.length = hold; - if (state.head) { - state.head.extra_len = hold; - } - if (state.flags & 0x0200) { - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - } - else if (state.head) { - state.head.extra = null/*Z_NULL*/; - } - state.mode = EXTRA; - /* falls through */ - case EXTRA: - if (state.flags & 0x0400) { - copy = state.length; - if (copy > have) { copy = have; } - if (copy) { - if (state.head) { - len = state.head.extra_len - state.length; - if (!state.head.extra) { - // Use untyped array for more convenient processing later - state.head.extra = new Array(state.head.extra_len); - } - arraySet( - state.head.extra, - input, - next, - // extra field is limited to 65536 bytes - // - no need for additional size check - copy, - /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/ - len - ); - //zmemcpy(state.head.extra + len, next, - // len + copy > state.head.extra_max ? - // state.head.extra_max - len : copy); - } - if (state.flags & 0x0200) { - state.check = crc32(state.check, input, copy, next); - } - have -= copy; - next += copy; - state.length -= copy; - } - if (state.length) { break inf_leave; } - } - state.length = 0; - state.mode = NAME; - /* falls through */ - case NAME: - if (state.flags & 0x0800) { - if (have === 0) { break inf_leave; } - copy = 0; - do { - // TODO: 2 or 1 bytes? - len = input[next + copy++]; - /* use constant limit because in js we should not preallocate memory */ - if (state.head && len && - (state.length < 65536 /*state.head.name_max*/)) { - state.head.name += String.fromCharCode(len); - } - } while (len && copy < have); - - if (state.flags & 0x0200) { - state.check = crc32(state.check, input, copy, next); - } - have -= copy; - next += copy; - if (len) { break inf_leave; } - } - else if (state.head) { - state.head.name = null; - } - state.length = 0; - state.mode = COMMENT; - /* falls through */ - case COMMENT: - if (state.flags & 0x1000) { - if (have === 0) { break inf_leave; } - copy = 0; - do { - len = input[next + copy++]; - /* use constant limit because in js we should not preallocate memory */ - if (state.head && len && - (state.length < 65536 /*state.head.comm_max*/)) { - state.head.comment += String.fromCharCode(len); - } - } while (len && copy < have); - if (state.flags & 0x0200) { - state.check = crc32(state.check, input, copy, next); - } - have -= copy; - next += copy; - if (len) { break inf_leave; } - } - else if (state.head) { - state.head.comment = null; - } - state.mode = HCRC; - /* falls through */ - case HCRC: - if (state.flags & 0x0200) { - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (hold !== (state.check & 0xffff)) { - strm.msg = 'header crc mismatch'; - state.mode = BAD$1; - break; - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - } - if (state.head) { - state.head.hcrc = ((state.flags >> 9) & 1); - state.head.done = true; - } - strm.adler = state.check = 0; - state.mode = TYPE$1; - break; - case DICTID: - //=== NEEDBITS(32); */ - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - strm.adler = state.check = zswap32(hold); - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = DICT; - /* falls through */ - case DICT: - if (state.havedict === 0) { - //--- RESTORE() --- - strm.next_out = put; - strm.avail_out = left; - strm.next_in = next; - strm.avail_in = have; - state.hold = hold; - state.bits = bits; - //--- - return Z_NEED_DICT; - } - strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; - state.mode = TYPE$1; - /* falls through */ - case TYPE$1: - if (flush === Z_BLOCK || flush === Z_TREES) { break inf_leave; } - /* falls through */ - case TYPEDO: - if (state.last) { - //--- BYTEBITS() ---// - hold >>>= bits & 7; - bits -= bits & 7; - //---// - state.mode = CHECK; - break; - } - //=== NEEDBITS(3); */ - while (bits < 3) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.last = (hold & 0x01)/*BITS(1)*/; - //--- DROPBITS(1) ---// - hold >>>= 1; - bits -= 1; - //---// - - switch ((hold & 0x03)/*BITS(2)*/) { - case 0: /* stored block */ - //Tracev((stderr, "inflate: stored block%s\n", - // state.last ? " (last)" : "")); - state.mode = STORED; - break; - case 1: /* fixed block */ - fixedtables(state); - //Tracev((stderr, "inflate: fixed codes block%s\n", - // state.last ? " (last)" : "")); - state.mode = LEN_; /* decode codes */ - if (flush === Z_TREES) { - //--- DROPBITS(2) ---// - hold >>>= 2; - bits -= 2; - //---// - break inf_leave; - } - break; - case 2: /* dynamic block */ - //Tracev((stderr, "inflate: dynamic codes block%s\n", - // state.last ? " (last)" : "")); - state.mode = TABLE; - break; - case 3: - strm.msg = 'invalid block type'; - state.mode = BAD$1; - } - //--- DROPBITS(2) ---// - hold >>>= 2; - bits -= 2; - //---// - break; - case STORED: - //--- BYTEBITS() ---// /* go to byte boundary */ - hold >>>= bits & 7; - bits -= bits & 7; - //---// - //=== NEEDBITS(32); */ - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) { - strm.msg = 'invalid stored block lengths'; - state.mode = BAD$1; - break; - } - state.length = hold & 0xffff; - //Tracev((stderr, "inflate: stored length %u\n", - // state.length)); - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = COPY_; - if (flush === Z_TREES) { break inf_leave; } - /* falls through */ - case COPY_: - state.mode = COPY; - /* falls through */ - case COPY: - copy = state.length; - if (copy) { - if (copy > have) { copy = have; } - if (copy > left) { copy = left; } - if (copy === 0) { break inf_leave; } - //--- zmemcpy(put, next, copy); --- - arraySet(output, input, next, copy, put); - //---// - have -= copy; - next += copy; - left -= copy; - put += copy; - state.length -= copy; - break; - } - //Tracev((stderr, "inflate: stored end\n")); - state.mode = TYPE$1; - break; - case TABLE: - //=== NEEDBITS(14); */ - while (bits < 14) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257; - //--- DROPBITS(5) ---// - hold >>>= 5; - bits -= 5; - //---// - state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1; - //--- DROPBITS(5) ---// - hold >>>= 5; - bits -= 5; - //---// - state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4; - //--- DROPBITS(4) ---// - hold >>>= 4; - bits -= 4; - //---// - //#ifndef PKZIP_BUG_WORKAROUND - if (state.nlen > 286 || state.ndist > 30) { - strm.msg = 'too many length or distance symbols'; - state.mode = BAD$1; - break; - } - //#endif - //Tracev((stderr, "inflate: table sizes ok\n")); - state.have = 0; - state.mode = LENLENS; - /* falls through */ - case LENLENS: - while (state.have < state.ncode) { - //=== NEEDBITS(3); - while (bits < 3) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.lens[order[state.have++]] = (hold & 0x07);//BITS(3); - //--- DROPBITS(3) ---// - hold >>>= 3; - bits -= 3; - //---// - } - while (state.have < 19) { - state.lens[order[state.have++]] = 0; - } - // We have separate tables & no pointers. 2 commented lines below not needed. - //state.next = state.codes; - //state.lencode = state.next; - // Switch to use dynamic table - state.lencode = state.lendyn; - state.lenbits = 7; - - opts = { bits: state.lenbits }; - ret = inflate_table(CODES$1, state.lens, 0, 19, state.lencode, 0, state.work, opts); - state.lenbits = opts.bits; - - if (ret) { - strm.msg = 'invalid code lengths set'; - state.mode = BAD$1; - break; - } - //Tracev((stderr, "inflate: code lengths ok\n")); - state.have = 0; - state.mode = CODELENS; - /* falls through */ - case CODELENS: - while (state.have < state.nlen + state.ndist) { - for (;;) { - here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/ - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - if (here_val < 16) { - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - state.lens[state.have++] = here_val; - } - else { - if (here_val === 16) { - //=== NEEDBITS(here.bits + 2); - n = here_bits + 2; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - if (state.have === 0) { - strm.msg = 'invalid bit length repeat'; - state.mode = BAD$1; - break; - } - len = state.lens[state.have - 1]; - copy = 3 + (hold & 0x03);//BITS(2); - //--- DROPBITS(2) ---// - hold >>>= 2; - bits -= 2; - //---// - } - else if (here_val === 17) { - //=== NEEDBITS(here.bits + 3); - n = here_bits + 3; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - len = 0; - copy = 3 + (hold & 0x07);//BITS(3); - //--- DROPBITS(3) ---// - hold >>>= 3; - bits -= 3; - //---// - } - else { - //=== NEEDBITS(here.bits + 7); - n = here_bits + 7; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - len = 0; - copy = 11 + (hold & 0x7f);//BITS(7); - //--- DROPBITS(7) ---// - hold >>>= 7; - bits -= 7; - //---// - } - if (state.have + copy > state.nlen + state.ndist) { - strm.msg = 'invalid bit length repeat'; - state.mode = BAD$1; - break; - } - while (copy--) { - state.lens[state.have++] = len; - } - } - } - - /* handle error breaks in while */ - if (state.mode === BAD$1) { break; } - - /* check for end-of-block code (better have one) */ - if (state.lens[256] === 0) { - strm.msg = 'invalid code -- missing end-of-block'; - state.mode = BAD$1; - break; - } - - /* build code tables -- note: do not change the lenbits or distbits - values here (9 and 6) without reading the comments in inftrees.h - concerning the ENOUGH constants, which depend on those values */ - state.lenbits = 9; - - opts = { bits: state.lenbits }; - ret = inflate_table(LENS$1, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts); - // We have separate tables & no pointers. 2 commented lines below not needed. - // state.next_index = opts.table_index; - state.lenbits = opts.bits; - // state.lencode = state.next; - - if (ret) { - strm.msg = 'invalid literal/lengths set'; - state.mode = BAD$1; - break; - } - - state.distbits = 6; - //state.distcode.copy(state.codes); - // Switch to use dynamic table - state.distcode = state.distdyn; - opts = { bits: state.distbits }; - ret = inflate_table(DISTS$1, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts); - // We have separate tables & no pointers. 2 commented lines below not needed. - // state.next_index = opts.table_index; - state.distbits = opts.bits; - // state.distcode = state.next; - - if (ret) { - strm.msg = 'invalid distances set'; - state.mode = BAD$1; - break; - } - //Tracev((stderr, 'inflate: codes ok\n')); - state.mode = LEN_; - if (flush === Z_TREES) { break inf_leave; } - /* falls through */ - case LEN_: - state.mode = LEN; - /* falls through */ - case LEN: - if (have >= 6 && left >= 258) { - //--- RESTORE() --- - strm.next_out = put; - strm.avail_out = left; - strm.next_in = next; - strm.avail_in = have; - state.hold = hold; - state.bits = bits; - //--- - inflate_fast(strm, _out); - //--- LOAD() --- - put = strm.next_out; - output = strm.output; - left = strm.avail_out; - next = strm.next_in; - input = strm.input; - have = strm.avail_in; - hold = state.hold; - bits = state.bits; - //--- - - if (state.mode === TYPE$1) { - state.back = -1; - } - break; - } - state.back = 0; - for (;;) { - here = state.lencode[hold & ((1 << state.lenbits) - 1)]; /*BITS(state.lenbits)*/ - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if (here_bits <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - if (here_op && (here_op & 0xf0) === 0) { - last_bits = here_bits; - last_op = here_op; - last_val = here_val; - for (;;) { - here = state.lencode[last_val + - ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((last_bits + here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - //--- DROPBITS(last.bits) ---// - hold >>>= last_bits; - bits -= last_bits; - //---// - state.back += last_bits; - } - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - state.back += here_bits; - state.length = here_val; - if (here_op === 0) { - //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - // "inflate: literal '%c'\n" : - // "inflate: literal 0x%02x\n", here.val)); - state.mode = LIT; - break; - } - if (here_op & 32) { - //Tracevv((stderr, "inflate: end of block\n")); - state.back = -1; - state.mode = TYPE$1; - break; - } - if (here_op & 64) { - strm.msg = 'invalid literal/length code'; - state.mode = BAD$1; - break; - } - state.extra = here_op & 15; - state.mode = LENEXT; - /* falls through */ - case LENEXT: - if (state.extra) { - //=== NEEDBITS(state.extra); - n = state.extra; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.length += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; - //--- DROPBITS(state.extra) ---// - hold >>>= state.extra; - bits -= state.extra; - //---// - state.back += state.extra; - } - //Tracevv((stderr, "inflate: length %u\n", state.length)); - state.was = state.length; - state.mode = DIST; - /* falls through */ - case DIST: - for (;;) { - here = state.distcode[hold & ((1 << state.distbits) - 1)];/*BITS(state.distbits)*/ - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - if ((here_op & 0xf0) === 0) { - last_bits = here_bits; - last_op = here_op; - last_val = here_val; - for (;;) { - here = state.distcode[last_val + - ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((last_bits + here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - //--- DROPBITS(last.bits) ---// - hold >>>= last_bits; - bits -= last_bits; - //---// - state.back += last_bits; - } - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - state.back += here_bits; - if (here_op & 64) { - strm.msg = 'invalid distance code'; - state.mode = BAD$1; - break; - } - state.offset = here_val; - state.extra = (here_op) & 15; - state.mode = DISTEXT; - /* falls through */ - case DISTEXT: - if (state.extra) { - //=== NEEDBITS(state.extra); - n = state.extra; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.offset += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; - //--- DROPBITS(state.extra) ---// - hold >>>= state.extra; - bits -= state.extra; - //---// - state.back += state.extra; - } - //#ifdef INFLATE_STRICT - if (state.offset > state.dmax) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD$1; - break; - } - //#endif - //Tracevv((stderr, "inflate: distance %u\n", state.offset)); - state.mode = MATCH; - /* falls through */ - case MATCH: - if (left === 0) { break inf_leave; } - copy = _out - left; - if (state.offset > copy) { /* copy from window */ - copy = state.offset - copy; - if (copy > state.whave) { - if (state.sane) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD$1; - break; - } - // (!) This block is disabled in zlib defaults, - // don't enable it for binary compatibility - //#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR - // Trace((stderr, "inflate.c too far\n")); - // copy -= state.whave; - // if (copy > state.length) { copy = state.length; } - // if (copy > left) { copy = left; } - // left -= copy; - // state.length -= copy; - // do { - // output[put++] = 0; - // } while (--copy); - // if (state.length === 0) { state.mode = LEN; } - // break; - //#endif - } - if (copy > state.wnext) { - copy -= state.wnext; - from = state.wsize - copy; - } - else { - from = state.wnext - copy; - } - if (copy > state.length) { copy = state.length; } - from_source = state.window; - } - else { /* copy from output */ - from_source = output; - from = put - state.offset; - copy = state.length; - } - if (copy > left) { copy = left; } - left -= copy; - state.length -= copy; - do { - output[put++] = from_source[from++]; - } while (--copy); - if (state.length === 0) { state.mode = LEN; } - break; - case LIT: - if (left === 0) { break inf_leave; } - output[put++] = state.length; - left--; - state.mode = LEN; - break; - case CHECK: - if (state.wrap) { - //=== NEEDBITS(32); - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - // Use '|' instead of '+' to make sure that result is signed - hold |= input[next++] << bits; - bits += 8; - } - //===// - _out -= left; - strm.total_out += _out; - state.total += _out; - if (_out) { - strm.adler = state.check = - /*UPDATE(state.check, put - _out, _out);*/ - (state.flags ? crc32(state.check, output, _out, put - _out) : adler32(state.check, output, _out, put - _out)); - - } - _out = left; - // NB: crc32 stored as signed 32-bit int, zswap32 returns signed too - if ((state.flags ? hold : zswap32(hold)) !== state.check) { - strm.msg = 'incorrect data check'; - state.mode = BAD$1; - break; - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - //Tracev((stderr, "inflate: check matches trailer\n")); - } - state.mode = LENGTH; - /* falls through */ - case LENGTH: - if (state.wrap && state.flags) { - //=== NEEDBITS(32); - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (hold !== (state.total & 0xffffffff)) { - strm.msg = 'incorrect length check'; - state.mode = BAD$1; - break; - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - //Tracev((stderr, "inflate: length matches trailer\n")); - } - state.mode = DONE; - /* falls through */ - case DONE: - ret = Z_STREAM_END; - break inf_leave; - case BAD$1: - ret = Z_DATA_ERROR; - break inf_leave; - // case MEM: - // return Z_MEM_ERROR; - case SYNC: - /* falls through */ - default: - return Z_STREAM_ERROR; - } - } - - // inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave" - - /* - Return from inflate(), updating the total counts and the check value. - If there was no progress during the inflate() call, return a buffer - error. Call updatewindow() to create and/or update the window state. - Note: a memory error from inflate() is non-recoverable. - */ - - //--- RESTORE() --- - strm.next_out = put; - strm.avail_out = left; - strm.next_in = next; - strm.avail_in = have; - state.hold = hold; - state.bits = bits; - //--- - - if (state.wsize || (_out !== strm.avail_out && state.mode < BAD$1 && - (state.mode < CHECK || flush !== Z_FINISH))) { - if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) ; - } - _in -= strm.avail_in; - _out -= strm.avail_out; - strm.total_in += _in; - strm.total_out += _out; - state.total += _out; - if (state.wrap && _out) { - strm.adler = state.check = /*UPDATE(state.check, strm.next_out - _out, _out);*/ - (state.flags ? crc32(state.check, output, _out, strm.next_out - _out) : adler32(state.check, output, _out, strm.next_out - _out)); - } - strm.data_type = state.bits + (state.last ? 64 : 0) + - (state.mode === TYPE$1 ? 128 : 0) + - (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0); - if (((_in === 0 && _out === 0) || flush === Z_FINISH) && ret === Z_OK) { - ret = Z_BUF_ERROR; - } - return ret; - } - - function inflateEnd(strm) { - - if (!strm || !strm.state /*|| strm->zfree == (free_func)0*/) { - return Z_STREAM_ERROR; - } - - const state = strm.state; - if (state.window) { - state.window = null; - } - strm.state = null; - return Z_OK; - } - - function inflateGetHeader(strm, head) { - let state; - - /* check state */ - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR; } - - /* save header structure */ - state.head = head; - head.done = false; - return Z_OK; - } - - function inflateSetDictionary(strm, dictionary) { - const dictLength = dictionary.length; - - let state; - let dictid; - - /* check state */ - if (!strm /* == Z_NULL */ || !strm.state /* == Z_NULL */) { return Z_STREAM_ERROR; } - state = strm.state; - - if (state.wrap !== 0 && state.mode !== DICT) { - return Z_STREAM_ERROR; - } - - /* check for correct dictionary identifier */ - if (state.mode === DICT) { - dictid = 1; /* adler32(0, null, 0)*/ - /* dictid = adler32(dictid, dictionary, dictLength); */ - dictid = adler32(dictid, dictionary, dictLength, 0); - if (dictid !== state.check) { - return Z_DATA_ERROR; - } - } - /* copy dictionary to window using updatewindow(), which will amend the - existing dictionary if appropriate */ - updatewindow(strm, dictionary, dictLength, dictLength); - // if (ret) { - // state.mode = MEM; - // return Z_MEM_ERROR; - // } - state.havedict = 1; - // Tracev((stderr, "inflate: dictionary set\n")); - return Z_OK; - } - - /* Not implemented - exports.inflateCopy = inflateCopy; - exports.inflateGetDictionary = inflateGetDictionary; - exports.inflateMark = inflateMark; - exports.inflatePrime = inflatePrime; - exports.inflateSync = inflateSync; - exports.inflateSyncPoint = inflateSyncPoint; - exports.inflateUndermine = inflateUndermine; - */ - - // (C) 1995-2013 Jean-loup Gailly and Mark Adler - // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin - // - // This software is provided 'as-is', without any express or implied - // warranty. In no event will the authors be held liable for any damages - // arising from the use of this software. - // - // Permission is granted to anyone to use this software for any purpose, - // including commercial applications, and to alter it and redistribute it - // freely, subject to the following restrictions: - // - // 1. The origin of this software must not be misrepresented; you must not - // claim that you wrote the original software. If you use this software - // in a product, an acknowledgment in the product documentation would be - // appreciated but is not required. - // 2. Altered source versions must be plainly marked as such, and must not be - // misrepresented as being the original software. - // 3. This notice may not be removed or altered from any source distribution. - - class GZheader { - constructor() { - /* true if compressed data believed to be text */ - this.text = 0; - /* modification time */ - this.time = 0; - /* extra flags (not used when writing a gzip file) */ - this.xflags = 0; - /* operating system */ - this.os = 0; - /* pointer to extra field or Z_NULL if none */ - this.extra = null; - /* extra field length (valid if extra != Z_NULL) */ - this.extra_len = 0; // Actually, we don't need it in JS, - // but leave for few code modifications - - // - // Setup limits is not necessary because in js we should not preallocate memory - // for inflate use constant limit in 65536 bytes - // - - /* space at extra (only when reading header) */ - // this.extra_max = 0; - /* pointer to zero-terminated file name or Z_NULL */ - this.name = ''; - /* space at name (only when reading header) */ - // this.name_max = 0; - /* pointer to zero-terminated comment or Z_NULL */ - this.comment = ''; - /* space at comment (only when reading header) */ - // this.comm_max = 0; - /* true if there was or will be a header crc */ - this.hcrc = 0; - /* true when done reading gzip header (not used when writing a gzip file) */ - this.done = false; - } - } - - /** - * class Inflate - * - * Generic JS-style wrapper for zlib calls. If you don't need - * streaming behaviour - use more simple functions: [[inflate]] - * and [[inflateRaw]]. - **/ - - /* internal - * inflate.chunks -> Array - * - * Chunks of output data, if [[Inflate#onData]] not overridden. - **/ - - /** - * Inflate.result -> Uint8Array|Array|String - * - * Uncompressed result, generated by default [[Inflate#onData]] - * and [[Inflate#onEnd]] handlers. Filled after you push last chunk - * (call [[Inflate#push]] with `Z_FINISH` / `true` param) or if you - * push a chunk with explicit flush (call [[Inflate#push]] with - * `Z_SYNC_FLUSH` param). - **/ - - /** - * Inflate.err -> Number - * - * Error code after inflate finished. 0 (Z_OK) on success. - * Should be checked if broken data possible. - **/ - - /** - * Inflate.msg -> String - * - * Error message, if [[Inflate.err]] != 0 - **/ - - - /** - * new Inflate(options) - * - options (Object): zlib inflate options. - * - * Creates new inflator instance with specified params. Throws exception - * on bad params. Supported options: - * - * - `windowBits` - * - `dictionary` - * - * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) - * for more information on these. - * - * Additional options, for internal needs: - * - * - `chunkSize` - size of generated data chunks (16K by default) - * - `raw` (Boolean) - do raw inflate - * - `to` (String) - if equal to 'string', then result will be converted - * from utf8 to utf16 (javascript) string. When string output requested, - * chunk length can differ from `chunkSize`, depending on content. - * - * By default, when no options set, autodetect deflate/gzip data format via - * wrapper header. - * - * ##### Example: - * - * ```javascript - * var pako = void('pako') - * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9]) - * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]); - * - * var inflate = new pako.Inflate({ level: 3}); - * - * inflate.push(chunk1, false); - * inflate.push(chunk2, true); // true -> last chunk - * - * if (inflate.err) { throw new Error(inflate.err); } - * - * console.log(inflate.result); - * ``` - **/ - class Inflate { - constructor(options) { - this.options = { - chunkSize: 16384, - windowBits: 0, - ...(options || {}) - }; - - const opt = this.options; - - // Force window size for `raw` data, if not set directly, - // because we have no header for autodetect. - if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) { - opt.windowBits = -opt.windowBits; - if (opt.windowBits === 0) { opt.windowBits = -15; } - } - - // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate - if ((opt.windowBits >= 0) && (opt.windowBits < 16) && - !(options && options.windowBits)) { - opt.windowBits += 32; - } - - // Gzip header has no info about windows size, we can do autodetect only - // for deflate. So, if window size not set, force it to max when gzip possible - if ((opt.windowBits > 15) && (opt.windowBits < 48)) { - // bit 3 (16) -> gzipped data - // bit 4 (32) -> autodetect gzip/deflate - if ((opt.windowBits & 15) === 0) { - opt.windowBits |= 15; - } - } - - this.err = 0; // error code, if happens (0 = Z_OK) - this.msg = ''; // error message - this.ended = false; // used to avoid multiple onEnd() calls - this.chunks = []; // chunks of compressed data - - this.strm = new ZStream(); - this.strm.avail_out = 0; - - let status = inflateInit2( - this.strm, - opt.windowBits - ); - - if (status !== Z_OK) { - throw new Error(msg[status]); - } - - this.header = new GZheader(); - - inflateGetHeader(this.strm, this.header); - - // Setup dictionary - if (opt.dictionary) { - // Convert data if needed - if (typeof opt.dictionary === 'string') { - opt.dictionary = string2buf(opt.dictionary); - } else if (opt.dictionary instanceof ArrayBuffer) { - opt.dictionary = new Uint8Array(opt.dictionary); - } - if (opt.raw) { //In raw mode we need to set the dictionary early - status = inflateSetDictionary(this.strm, opt.dictionary); - if (status !== Z_OK) { - throw new Error(msg[status]); - } - } - } - } - /** - * Inflate#push(data[, mode]) -> Boolean - * - data (Uint8Array|Array|ArrayBuffer|String): input data - * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. - * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH. - * - * Sends input data to inflate pipe, generating [[Inflate#onData]] calls with - * new output chunks. Returns `true` on success. The last data block must have - * mode Z_FINISH (or `true`). That will flush internal pending buffers and call - * [[Inflate#onEnd]]. For interim explicit flushes (without ending the stream) you - * can use mode Z_SYNC_FLUSH, keeping the decompression context. - * - * On fail call [[Inflate#onEnd]] with error code and return false. - * - * We strongly recommend to use `Uint8Array` on input for best speed (output - * format is detected automatically). Also, don't skip last param and always - * use the same type in your code (boolean or number). That will improve JS speed. - * - * For regular `Array`-s make sure all elements are [0..255]. - * - * ##### Example - * - * ```javascript - * push(chunk, false); // push one of data chunks - * ... - * push(chunk, true); // push last chunk - * ``` - **/ - push(data, mode) { - const { strm, options: { chunkSize, dictionary } } = this; - let status, _mode; - - // Flag to properly process Z_BUF_ERROR on testing inflate call - // when we check that all output data was flushed. - let allowBufError = false; - - if (this.ended) { return false; } - _mode = (mode === ~~mode) ? mode : ((mode === true) ? Z_FINISH : Z_NO_FLUSH); - - // Convert data if needed - if (typeof data === 'string') { - // Only binary strings can be decompressed on practice - strm.input = binstring2buf(data); - } else if (data instanceof ArrayBuffer) { - strm.input = new Uint8Array(data); - } else { - strm.input = data; - } - - strm.next_in = 0; - strm.avail_in = strm.input.length; - - do { - if (strm.avail_out === 0) { - strm.output = new Buf8(chunkSize); - strm.next_out = 0; - strm.avail_out = chunkSize; - } - - status = inflate(strm, Z_NO_FLUSH); /* no bad return value */ - - if (status === Z_NEED_DICT && dictionary) { - status = inflateSetDictionary(this.strm, dictionary); - } - - if (status === Z_BUF_ERROR && allowBufError === true) { - status = Z_OK; - allowBufError = false; - } - - if (status !== Z_STREAM_END && status !== Z_OK) { - this.onEnd(status); - this.ended = true; - return false; - } - - if (strm.next_out) { - if (strm.avail_out === 0 || status === Z_STREAM_END || (strm.avail_in === 0 && (_mode === Z_FINISH || _mode === Z_SYNC_FLUSH))) { - this.onData(shrinkBuf(strm.output, strm.next_out)); - } - } - - // When no more input data, we should check that internal inflate buffers - // are flushed. The only way to do it when avail_out = 0 - run one more - // inflate pass. But if output data not exists, inflate return Z_BUF_ERROR. - // Here we set flag to process this error properly. - // - // NOTE. Deflate does not return error in this case and does not needs such - // logic. - if (strm.avail_in === 0 && strm.avail_out === 0) { - allowBufError = true; - } - - } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== Z_STREAM_END); - - if (status === Z_STREAM_END) { - _mode = Z_FINISH; - } - - // Finalize on the last chunk. - if (_mode === Z_FINISH) { - status = inflateEnd(this.strm); - this.onEnd(status); - this.ended = true; - return status === Z_OK; - } - - // callback interim results if Z_SYNC_FLUSH. - if (_mode === Z_SYNC_FLUSH) { - this.onEnd(Z_OK); - strm.avail_out = 0; - return true; - } - - return true; - }; - - /** - * Inflate#onData(chunk) -> Void - * - chunk (Uint8Array|Array|String): output data. Type of array depends - * on js engine support. When string output requested, each chunk - * will be string. - * - * By default, stores data blocks in `chunks[]` property and glue - * those in `onEnd`. Override this handler, if you need another behaviour. - **/ - onData(chunk) { - this.chunks.push(chunk); - }; - - - - /** - * Inflate#onEnd(status) -> Void - * - status (Number): inflate status. 0 (Z_OK) on success, - * other if not. - * - * Called either after you tell inflate that the input stream is - * complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH) - * or if an error happened. By default - join collected chunks, - * free memory and fill `results` / `err` properties. - **/ - onEnd(status) { - // On success - join - if (status === Z_OK) { - this.result = flattenChunks(this.chunks); - } - this.chunks = []; - this.err = status; - this.msg = this.strm.msg; - }; - } - - /* - node-bzip - a pure-javascript Node.JS module for decoding bzip2 data - - Copyright (C) 2012 Eli Skeggs - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see - http://www.gnu.org/licenses/lgpl-2.1.html - - Adapted from bzip2.js, copyright 2011 antimatter15 (antimatter15@gmail.com). - - Based on micro-bunzip by Rob Landley (rob@landley.net). - - Based on bzip2 decompression code by Julian R Seward (jseward@acm.org), - which also acknowledges contributions by Mike Burrows, David Wheeler, - Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten, - Robert Sedgewick, and Jon L. Bentley. - */ - - var BITMASK = [0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF]; - - // offset in bytes - var BitReader = function(stream) { - this.stream = stream; - this.bitOffset = 0; - this.curByte = 0; - this.hasByte = false; - }; - - BitReader.prototype._ensureByte = function() { - if (!this.hasByte) { - this.curByte = this.stream.readByte(); - this.hasByte = true; - } - }; - - // reads bits from the buffer - BitReader.prototype.read = function(bits) { - var result = 0; - while (bits > 0) { - this._ensureByte(); - var remaining = 8 - this.bitOffset; - // if we're in a byte - if (bits >= remaining) { - result <<= remaining; - result |= BITMASK[remaining] & this.curByte; - this.hasByte = false; - this.bitOffset = 0; - bits -= remaining; - } else { - result <<= bits; - var shift = remaining - bits; - result |= (this.curByte & (BITMASK[bits] << shift)) >> shift; - this.bitOffset += bits; - bits = 0; - } - } - return result; - }; - - // seek to an arbitrary point in the buffer (expressed in bits) - BitReader.prototype.seek = function(pos) { - var n_bit = pos % 8; - var n_byte = (pos - n_bit) / 8; - this.bitOffset = n_bit; - this.stream.seek(n_byte); - this.hasByte = false; - }; - - // reads 6 bytes worth of data using the read method - BitReader.prototype.pi = function() { - var buf = new Uint8Array(6), i; - for (i = 0; i < buf.length; i++) { - buf[i] = this.read(8); - } - return bufToHex(buf); - }; - - function bufToHex(buf) { - return Array.prototype.map.call(buf, x => ('00' + x.toString(16)).slice(-2)).join(''); - } - - var bitreader = BitReader; - - /* very simple input/output stream interface */ - var Stream = function() { - }; - - // input streams ////////////// - /** Returns the next byte, or -1 for EOF. */ - Stream.prototype.readByte = function() { - throw new Error("abstract method readByte() not implemented"); - }; - /** Attempts to fill the buffer; returns number of bytes read, or - * -1 for EOF. */ - Stream.prototype.read = function(buffer, bufOffset, length) { - var bytesRead = 0; - while (bytesRead < length) { - var c = this.readByte(); - if (c < 0) { // EOF - return (bytesRead===0) ? -1 : bytesRead; - } - buffer[bufOffset++] = c; - bytesRead++; - } - return bytesRead; - }; - Stream.prototype.seek = function(new_pos) { - throw new Error("abstract method seek() not implemented"); - }; - - // output streams /////////// - Stream.prototype.writeByte = function(_byte) { - throw new Error("abstract method readByte() not implemented"); - }; - Stream.prototype.write = function(buffer, bufOffset, length) { - var i; - for (i=0; i>> 0; // return an unsigned value - }; - - /** - * Update the CRC with a single byte - * @param value The value to update the CRC with - */ - this.updateCRC = function(value) { - crc = (crc << 8) ^ crc32Lookup[((crc >>> 24) ^ value) & 0xff]; - }; - - /** - * Update the CRC with a sequence of identical bytes - * @param value The value to update the CRC with - * @param count The number of bytes - */ - this.updateCRCRun = function(value, count) { - while (count-- > 0) { - crc = (crc << 8) ^ crc32Lookup[((crc >>> 24) ^ value) & 0xff]; - } - }; - }; - return CRC32; - })(); - - /* - seek-bzip - a pure-javascript module for seeking within bzip2 data - - Copyright (C) 2013 C. Scott Ananian - Copyright (C) 2012 Eli Skeggs - Copyright (C) 2011 Kevin Kwok - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see - http://www.gnu.org/licenses/lgpl-2.1.html - - Adapted from node-bzip, copyright 2012 Eli Skeggs. - Adapted from bzip2.js, copyright 2011 Kevin Kwok (antimatter15@gmail.com). - - Based on micro-bunzip by Rob Landley (rob@landley.net). - - Based on bzip2 decompression code by Julian R Seward (jseward@acm.org), - which also acknowledges contributions by Mike Burrows, David Wheeler, - Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten, - Robert Sedgewick, and Jon L. Bentley. - */ - - - - - - var MAX_HUFCODE_BITS = 20; - var MAX_SYMBOLS = 258; - var SYMBOL_RUNA = 0; - var SYMBOL_RUNB = 1; - var MIN_GROUPS = 2; - var MAX_GROUPS = 6; - var GROUP_SIZE = 50; - - var WHOLEPI = "314159265359"; - var SQRTPI = "177245385090"; - - var mtf = function(array, index) { - var src = array[index], i; - for (i = index; i > 0; i--) { - array[i] = array[i-1]; - } - array[0] = src; - return src; - }; - - var Err = { - OK: 0, - LAST_BLOCK: -1, - NOT_BZIP_DATA: -2, - UNEXPECTED_INPUT_EOF: -3, - UNEXPECTED_OUTPUT_EOF: -4, - DATA_ERROR: -5, - OUT_OF_MEMORY: -6, - OBSOLETE_INPUT: -7, - END_OF_BLOCK: -8 - }; - var ErrorMessages = {}; - ErrorMessages[Err.LAST_BLOCK] = "Bad file checksum"; - ErrorMessages[Err.NOT_BZIP_DATA] = "Not bzip data"; - ErrorMessages[Err.UNEXPECTED_INPUT_EOF] = "Unexpected input EOF"; - ErrorMessages[Err.UNEXPECTED_OUTPUT_EOF] = "Unexpected output EOF"; - ErrorMessages[Err.DATA_ERROR] = "Data error"; - ErrorMessages[Err.OUT_OF_MEMORY] = "Out of memory"; - ErrorMessages[Err.OBSOLETE_INPUT] = "Obsolete (pre 0.9.5) bzip format not supported."; - - var _throw = function(status, optDetail) { - var msg = ErrorMessages[status] || 'unknown error'; - if (optDetail) { msg += ': '+optDetail; } - var e = new TypeError(msg); - e.errorCode = status; - throw e; - }; - - var Bunzip = function(inputStream, outputStream) { - this.writePos = this.writeCurrent = this.writeCount = 0; - - this._start_bunzip(inputStream, outputStream); - }; - Bunzip.prototype._init_block = function() { - var moreBlocks = this._get_next_block(); - if ( !moreBlocks ) { - this.writeCount = -1; - return false; /* no more blocks */ - } - this.blockCRC = new crc32$1(); - return true; - }; - /* XXX micro-bunzip uses (inputStream, inputBuffer, len) as arguments */ - Bunzip.prototype._start_bunzip = function(inputStream, outputStream) { - /* Ensure that file starts with "BZh['1'-'9']." */ - var buf = new Uint8Array(4); - if (inputStream.read(buf, 0, 4) !== 4 || - String.fromCharCode(buf[0], buf[1], buf[2]) !== 'BZh') - _throw(Err.NOT_BZIP_DATA, 'bad magic'); - - var level = buf[3] - 0x30; - if (level < 1 || level > 9) - _throw(Err.NOT_BZIP_DATA, 'level out of range'); - - this.reader = new bitreader(inputStream); - - /* Fourth byte (ascii '1'-'9'), indicates block size in units of 100k of - uncompressed data. Allocate intermediate buffer for block. */ - this.dbufSize = 100000 * level; - this.nextoutput = 0; - this.outputStream = outputStream; - this.streamCRC = 0; - }; - Bunzip.prototype._get_next_block = function() { - var i, j, k; - var reader = this.reader; - // this is get_next_block() function from micro-bunzip: - /* Read in header signature and CRC, then validate signature. - (last block signature means CRC is for whole file, return now) */ - var h = reader.pi(); - if (h === SQRTPI) { // last block - return false; /* no more blocks */ - } - if (h !== WHOLEPI) - _throw(Err.NOT_BZIP_DATA); - this.targetBlockCRC = reader.read(32) >>> 0; // (convert to unsigned) - this.streamCRC = (this.targetBlockCRC ^ - ((this.streamCRC << 1) | (this.streamCRC>>>31))) >>> 0; - /* We can add support for blockRandomised if anybody complains. There was - some code for this in busybox 1.0.0-pre3, but nobody ever noticed that - it didn't actually work. */ - if (reader.read(1)) - _throw(Err.OBSOLETE_INPUT); - var origPointer = reader.read(24); - if (origPointer > this.dbufSize) - _throw(Err.DATA_ERROR, 'initial position out of bounds'); - /* mapping table: if some byte values are never used (encoding things - like ascii text), the compression code removes the gaps to have fewer - symbols to deal with, and writes a sparse bitfield indicating which - values were present. We make a translation table to convert the symbols - back to the corresponding bytes. */ - var t = reader.read(16); - var symToByte = new Uint8Array(256), symTotal = 0; - for (i = 0; i < 16; i++) { - if (t & (1 << (0xF - i))) { - var o = i * 16; - k = reader.read(16); - for (j = 0; j < 16; j++) - if (k & (1 << (0xF - j))) - symToByte[symTotal++] = o + j; - } - } - - /* How many different huffman coding groups does this block use? */ - var groupCount = reader.read(3); - if (groupCount < MIN_GROUPS || groupCount > MAX_GROUPS) - _throw(Err.DATA_ERROR); - /* nSelectors: Every GROUP_SIZE many symbols we select a new huffman coding - group. Read in the group selector list, which is stored as MTF encoded - bit runs. (MTF=Move To Front, as each value is used it's moved to the - start of the list.) */ - var nSelectors = reader.read(15); - if (nSelectors === 0) - _throw(Err.DATA_ERROR); - - var mtfSymbol = new Uint8Array(256); - for (i = 0; i < groupCount; i++) - mtfSymbol[i] = i; - - var selectors = new Uint8Array(nSelectors); // was 32768... - - for (i = 0; i < nSelectors; i++) { - /* Get next value */ - for (j = 0; reader.read(1); j++) - if (j >= groupCount) _throw(Err.DATA_ERROR); - /* Decode MTF to get the next selector */ - selectors[i] = mtf(mtfSymbol, j); - } - - /* Read the huffman coding tables for each group, which code for symTotal - literal symbols, plus two run symbols (RUNA, RUNB) */ - var symCount = symTotal + 2; - var groups = [], hufGroup; - for (j = 0; j < groupCount; j++) { - var length = new Uint8Array(symCount), temp = new Uint16Array(MAX_HUFCODE_BITS + 1); - /* Read huffman code lengths for each symbol. They're stored in - a way similar to mtf; record a starting value for the first symbol, - and an offset from the previous value for everys symbol after that. */ - t = reader.read(5); // lengths - for (i = 0; i < symCount; i++) { - for (;;) { - if (t < 1 || t > MAX_HUFCODE_BITS) _throw(Err.DATA_ERROR); - /* If first bit is 0, stop. Else second bit indicates whether - to increment or decrement the value. */ - if(!reader.read(1)) - break; - if(!reader.read(1)) - t++; - else - t--; - } - length[i] = t; - } - - /* Find largest and smallest lengths in this group */ - var minLen, maxLen; - minLen = maxLen = length[0]; - for (i = 1; i < symCount; i++) { - if (length[i] > maxLen) - maxLen = length[i]; - else if (length[i] < minLen) - minLen = length[i]; - } - - /* Calculate permute[], base[], and limit[] tables from length[]. - * - * permute[] is the lookup table for converting huffman coded symbols - * into decoded symbols. base[] is the amount to subtract from the - * value of a huffman symbol of a given length when using permute[]. - * - * limit[] indicates the largest numerical value a symbol with a given - * number of bits can have. This is how the huffman codes can vary in - * length: each code with a value>limit[length] needs another bit. - */ - hufGroup = {}; - groups.push(hufGroup); - hufGroup.permute = new Uint16Array(MAX_SYMBOLS); - hufGroup.limit = new Uint32Array(MAX_HUFCODE_BITS + 2); - hufGroup.base = new Uint32Array(MAX_HUFCODE_BITS + 1); - hufGroup.minLen = minLen; - hufGroup.maxLen = maxLen; - /* Calculate permute[]. Concurently, initialize temp[] and limit[]. */ - var pp = 0; - for (i = minLen; i <= maxLen; i++) { - temp[i] = hufGroup.limit[i] = 0; - for (t = 0; t < symCount; t++) - if (length[t] === i) - hufGroup.permute[pp++] = t; - } - /* Count symbols coded for at each bit length */ - for (i = 0; i < symCount; i++) - temp[length[i]]++; - /* Calculate limit[] (the largest symbol-coding value at each bit - * length, which is (previous limit<<1)+symbols at this level), and - * base[] (number of symbols to ignore at each bit length, which is - * limit minus the cumulative count of symbols coded for already). */ - pp = t = 0; - for (i = minLen; i < maxLen; i++) { - pp += temp[i]; - /* We read the largest possible symbol size and then unget bits - after determining how many we need, and those extra bits could - be set to anything. (They're noise from future symbols.) At - each level we're really only interested in the first few bits, - so here we set all the trailing to-be-ignored bits to 1 so they - don't affect the value>limit[length] comparison. */ - hufGroup.limit[i] = pp - 1; - pp <<= 1; - t += temp[i]; - hufGroup.base[i + 1] = pp - t; - } - hufGroup.limit[maxLen + 1] = Number.MAX_VALUE; /* Sentinal value for reading next sym. */ - hufGroup.limit[maxLen] = pp + temp[maxLen] - 1; - hufGroup.base[minLen] = 0; - } - /* We've finished reading and digesting the block header. Now read this - block's huffman coded symbols from the file and undo the huffman coding - and run length encoding, saving the result into dbuf[dbufCount++]=uc */ - - /* Initialize symbol occurrence counters and symbol Move To Front table */ - var byteCount = new Uint32Array(256); - for (i = 0; i < 256; i++) - mtfSymbol[i] = i; - /* Loop through compressed symbols. */ - var runPos = 0, dbufCount = 0, selector = 0, uc; - var dbuf = this.dbuf = new Uint32Array(this.dbufSize); - symCount = 0; - for (;;) { - /* Determine which huffman coding group to use. */ - if (!(symCount--)) { - symCount = GROUP_SIZE - 1; - if (selector >= nSelectors) { _throw(Err.DATA_ERROR); } - hufGroup = groups[selectors[selector++]]; - } - /* Read next huffman-coded symbol. */ - i = hufGroup.minLen; - j = reader.read(i); - for (;;i++) { - if (i > hufGroup.maxLen) { _throw(Err.DATA_ERROR); } - if (j <= hufGroup.limit[i]) - break; - j = (j << 1) | reader.read(1); - } - /* Huffman decode value to get nextSym (with bounds checking) */ - j -= hufGroup.base[i]; - if (j < 0 || j >= MAX_SYMBOLS) { _throw(Err.DATA_ERROR); } - var nextSym = hufGroup.permute[j]; - /* We have now decoded the symbol, which indicates either a new literal - byte, or a repeated run of the most recent literal byte. First, - check if nextSym indicates a repeated run, and if so loop collecting - how many times to repeat the last literal. */ - if (nextSym === SYMBOL_RUNA || nextSym === SYMBOL_RUNB) { - /* If this is the start of a new run, zero out counter */ - if (!runPos){ - runPos = 1; - t = 0; - } - /* Neat trick that saves 1 symbol: instead of or-ing 0 or 1 at - each bit position, add 1 or 2 instead. For example, - 1011 is 1<<0 + 1<<1 + 2<<2. 1010 is 2<<0 + 2<<1 + 1<<2. - You can make any bit pattern that way using 1 less symbol than - the basic or 0/1 method (except all bits 0, which would use no - symbols, but a run of length 0 doesn't mean anything in this - context). Thus space is saved. */ - if (nextSym === SYMBOL_RUNA) - t += runPos; - else - t += 2 * runPos; - runPos <<= 1; - continue; - } - /* When we hit the first non-run symbol after a run, we now know - how many times to repeat the last literal, so append that many - copies to our buffer of decoded symbols (dbuf) now. (The last - literal used is the one at the head of the mtfSymbol array.) */ - if (runPos){ - runPos = 0; - if (dbufCount + t > this.dbufSize) { _throw(Err.DATA_ERROR); } - uc = symToByte[mtfSymbol[0]]; - byteCount[uc] += t; - while (t--) - dbuf[dbufCount++] = uc; - } - /* Is this the terminating symbol? */ - if (nextSym > symTotal) - break; - /* At this point, nextSym indicates a new literal character. Subtract - one to get the position in the MTF array at which this literal is - currently to be found. (Note that the result can't be -1 or 0, - because 0 and 1 are RUNA and RUNB. But another instance of the - first symbol in the mtf array, position 0, would have been handled - as part of a run above. Therefore 1 unused mtf position minus - 2 non-literal nextSym values equals -1.) */ - if (dbufCount >= this.dbufSize) { _throw(Err.DATA_ERROR); } - i = nextSym - 1; - uc = mtf(mtfSymbol, i); - uc = symToByte[uc]; - /* We have our literal byte. Save it into dbuf. */ - byteCount[uc]++; - dbuf[dbufCount++] = uc; - } - /* At this point, we've read all the huffman-coded symbols (and repeated - runs) for this block from the input stream, and decoded them into the - intermediate buffer. There are dbufCount many decoded bytes in dbuf[]. - Now undo the Burrows-Wheeler transform on dbuf. - See http://dogma.net/markn/articles/bwt/bwt.htm - */ - if (origPointer < 0 || origPointer >= dbufCount) { _throw(Err.DATA_ERROR); } - /* Turn byteCount into cumulative occurrence counts of 0 to n-1. */ - j = 0; - for (i = 0; i < 256; i++) { - k = j + byteCount[i]; - byteCount[i] = j; - j = k; - } - /* Figure out what order dbuf would be in if we sorted it. */ - for (i = 0; i < dbufCount; i++) { - uc = dbuf[i] & 0xff; - dbuf[byteCount[uc]] |= (i << 8); - byteCount[uc]++; - } - /* Decode first byte by hand to initialize "previous" byte. Note that it - doesn't get output, and if the first three characters are identical - it doesn't qualify as a run (hence writeRunCountdown=5). */ - var pos = 0, current = 0, run = 0; - if (dbufCount) { - pos = dbuf[origPointer]; - current = (pos & 0xff); - pos >>= 8; - run = -1; - } - this.writePos = pos; - this.writeCurrent = current; - this.writeCount = dbufCount; - this.writeRun = run; - - return true; /* more blocks to come */ - }; - /* Undo burrows-wheeler transform on intermediate buffer to produce output. - If start_bunzip was initialized with out_fd=-1, then up to len bytes of - data are written to outbuf. Return value is number of bytes written or - error (all errors are negative numbers). If out_fd!=-1, outbuf and len - are ignored, data is written to out_fd and return is RETVAL_OK or error. - */ - Bunzip.prototype._read_bunzip = function(outputBuffer, len) { - var copies, previous, outbyte; - /* james@jamestaylor.org: writeCount goes to -1 when the buffer is fully - decoded, which results in this returning RETVAL_LAST_BLOCK, also - equal to -1... Confusing, I'm returning 0 here to indicate no - bytes written into the buffer */ - if (this.writeCount < 0) { return 0; } - var dbuf = this.dbuf, pos = this.writePos, current = this.writeCurrent; - var dbufCount = this.writeCount; this.outputsize; - var run = this.writeRun; - - while (dbufCount) { - dbufCount--; - previous = current; - pos = dbuf[pos]; - current = pos & 0xff; - pos >>= 8; - if (run++ === 3){ - copies = current; - outbyte = previous; - current = -1; - } else { - copies = 1; - outbyte = current; - } - this.blockCRC.updateCRCRun(outbyte, copies); - while (copies--) { - this.outputStream.writeByte(outbyte); - this.nextoutput++; - } - if (current != previous) - run = 0; - } - this.writeCount = dbufCount; - // check CRC - if (this.blockCRC.getCRC() !== this.targetBlockCRC) { - _throw(Err.DATA_ERROR, "Bad block CRC "+ - "(got "+this.blockCRC.getCRC().toString(16)+ - " expected "+this.targetBlockCRC.toString(16)+")"); - } - return this.nextoutput; - }; - - var coerceInputStream = function(input) { - if ('readByte' in input) { return input; } - var inputStream = new stream(); - inputStream.pos = 0; - inputStream.readByte = function() { return input[this.pos++]; }; - inputStream.seek = function(pos) { this.pos = pos; }; - inputStream.eof = function() { return this.pos >= input.length; }; - return inputStream; - }; - var coerceOutputStream = function(output) { - var outputStream = new stream(); - var resizeOk = true; - if (output) { - if (typeof(output)==='number') { - outputStream.buffer = new Uint8Array(output); - resizeOk = false; - } else if ('writeByte' in output) { - return output; - } else { - outputStream.buffer = output; - resizeOk = false; - } - } else { - outputStream.buffer = new Uint8Array(16384); - } - outputStream.pos = 0; - outputStream.writeByte = function(_byte) { - if (resizeOk && this.pos >= this.buffer.length) { - var newBuffer = new Uint8Array(this.buffer.length*2); - newBuffer.set(this.buffer); - this.buffer = newBuffer; - } - this.buffer[this.pos++] = _byte; - }; - outputStream.getBuffer = function() { - // trim buffer - if (this.pos !== this.buffer.length) { - if (!resizeOk) - throw new TypeError('outputsize does not match decoded input'); - var newBuffer = new Uint8Array(this.pos); - newBuffer.set(this.buffer.subarray(0, this.pos)); - this.buffer = newBuffer; - } - return this.buffer; - }; - outputStream._coerced = true; - return outputStream; - }; - - /* Static helper functions */ - // 'input' can be a stream or a buffer - // 'output' can be a stream or a buffer or a number (buffer size) - const decode$2 = function(input, output, multistream) { - // make a stream from a buffer, if necessary - var inputStream = coerceInputStream(input); - var outputStream = coerceOutputStream(output); - - var bz = new Bunzip(inputStream, outputStream); - while (true) { - if ('eof' in inputStream && inputStream.eof()) break; - if (bz._init_block()) { - bz._read_bunzip(); - } else { - var targetStreamCRC = bz.reader.read(32) >>> 0; // (convert to unsigned) - if (targetStreamCRC !== bz.streamCRC) { - _throw(Err.DATA_ERROR, "Bad stream CRC "+ - "(got "+bz.streamCRC.toString(16)+ - " expected "+targetStreamCRC.toString(16)+")"); - } - if (multistream && - 'eof' in inputStream && - !inputStream.eof()) { - // note that start_bunzip will also resync the bit reader to next byte - bz._start_bunzip(inputStream, outputStream); - } else break; - } - } - if ('getBuffer' in outputStream) - return outputStream.getBuffer(); - }; - const decodeBlock = function(input, pos, output) { - // make a stream from a buffer, if necessary - var inputStream = coerceInputStream(input); - var outputStream = coerceOutputStream(output); - var bz = new Bunzip(inputStream, outputStream); - bz.reader.seek(pos); - /* Fill the decode buffer for the block */ - var moreBlocks = bz._get_next_block(); - if (moreBlocks) { - /* Init the CRC for writing */ - bz.blockCRC = new crc32$1(); - - /* Zero this so the current byte from before the seek is not written */ - bz.writeCopies = 0; - - /* Decompress the block and write to stdout */ - bz._read_bunzip(); - // XXX keep writing? - } - if ('getBuffer' in outputStream) - return outputStream.getBuffer(); - }; - /* Reads bzip2 file from stream or buffer `input`, and invoke - * `callback(position, size)` once for each bzip2 block, - * where position gives the starting position (in *bits*) - * and size gives uncompressed size of the block (in *bytes*). */ - const table = function(input, callback, multistream) { - // make a stream from a buffer, if necessary - var inputStream = new stream(); - inputStream.delegate = coerceInputStream(input); - inputStream.pos = 0; - inputStream.readByte = function() { - this.pos++; - return this.delegate.readByte(); - }; - if (inputStream.delegate.eof) { - inputStream.eof = inputStream.delegate.eof.bind(inputStream.delegate); - } - var outputStream = new stream(); - outputStream.pos = 0; - outputStream.writeByte = function() { this.pos++; }; - - var bz = new Bunzip(inputStream, outputStream); - var blockSize = bz.dbufSize; - while (true) { - if ('eof' in inputStream && inputStream.eof()) break; - - var position = inputStream.pos*8 + bz.reader.bitOffset; - if (bz.reader.hasByte) { position -= 8; } - - if (bz._init_block()) { - var start = outputStream.pos; - bz._read_bunzip(); - callback(position, outputStream.pos - start); - } else { - bz.reader.read(32); // (but we ignore the crc) - if (multistream && - 'eof' in inputStream && - !inputStream.eof()) { - // note that start_bunzip will also resync the bit reader to next byte - bz._start_bunzip(inputStream, outputStream); - console.assert(bz.dbufSize === blockSize, - "shouldn't change block size within multistream file"); - } else break; - } - } - }; - - var lib = { - Bunzip, - Stream: stream, - Err, - decode: decode$2, - decodeBlock, - table - }; - var lib_4 = lib.decode; - - // GPG4Browsers - An OpenPGP implementation in javascript - - /** - * Implementation of the Literal Data Packet (Tag 11) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.9|RFC4880 5.9}: - * A Literal Data packet contains the body of a message; data that is not to be - * further interpreted. - */ - class LiteralDataPacket { - static get tag() { - return enums.packet.literalData; - } - - /** - * @param {Date} date - The creation date of the literal package - */ - constructor(date = new Date()) { - this.format = enums.literal.utf8; // default format for literal data packets - this.date = util.normalizeDate(date); - this.text = null; // textual data representation - this.data = null; // literal data representation - this.filename = ''; - } - - /** - * Set the packet data to a javascript native string, end of line - * will be normalized to \r\n and by default text is converted to UTF8 - * @param {String | ReadableStream} text - Any native javascript string - * @param {enums.literal} [format] - The format of the string of bytes - */ - setText(text, format = enums.literal.utf8) { - this.format = format; - this.text = text; - this.data = null; - } - - /** - * Returns literal data packets as native JavaScript string - * with normalized end of line to \n - * @param {Boolean} [clone] - Whether to return a clone so that getBytes/getText can be called again - * @returns {String | ReadableStream} Literal data as text. - */ - getText(clone = false) { - if (this.text === null || util.isStream(this.text)) { // Assume that this.text has been read - this.text = util.decodeUTF8(util.nativeEOL(this.getBytes(clone))); - } - return this.text; - } - - /** - * Set the packet data to value represented by the provided string of bytes. - * @param {Uint8Array | ReadableStream} bytes - The string of bytes - * @param {enums.literal} format - The format of the string of bytes - */ - setBytes(bytes, format) { - this.format = format; - this.data = bytes; - this.text = null; - } - - - /** - * Get the byte sequence representing the literal packet data - * @param {Boolean} [clone] - Whether to return a clone so that getBytes/getText can be called again - * @returns {Uint8Array | ReadableStream} A sequence of bytes. - */ - getBytes(clone = false) { - if (this.data === null) { - // encode UTF8 and normalize EOL to \r\n - this.data = util.canonicalizeEOL(util.encodeUTF8(this.text)); - } - if (clone) { - return passiveClone(this.data); - } - return this.data; - } - - - /** - * Sets the filename of the literal packet data - * @param {String} filename - Any native javascript string - */ - setFilename(filename) { - this.filename = filename; - } - - - /** - * Get the filename of the literal packet data - * @returns {String} Filename. - */ - getFilename() { - return this.filename; - } - - /** - * Parsing function for a literal data packet (tag 11). - * - * @param {Uint8Array | ReadableStream} input - Payload of a tag 11 packet - * @returns {Promise} Object representation. - * @async - */ - async read(bytes) { - await parse(bytes, async reader => { - // - A one-octet field that describes how the data is formatted. - const format = await reader.readByte(); // enums.literal - - const filename_len = await reader.readByte(); - this.filename = util.decodeUTF8(await reader.readBytes(filename_len)); - - this.date = util.readDate(await reader.readBytes(4)); - - let data = reader.remainder(); - if (isArrayStream(data)) data = await readToEnd(data); - this.setBytes(data, format); - }); - } - - /** - * Creates a Uint8Array representation of the packet, excluding the data - * - * @returns {Uint8Array} Uint8Array representation of the packet. - */ - writeHeader() { - const filename = util.encodeUTF8(this.filename); - const filename_length = new Uint8Array([filename.length]); - - const format = new Uint8Array([this.format]); - const date = util.writeDate(this.date); - - return util.concatUint8Array([format, filename_length, filename, date]); - } - - /** - * Creates a Uint8Array representation of the packet - * - * @returns {Uint8Array | ReadableStream} Uint8Array representation of the packet. - */ - write() { - const header = this.writeHeader(); - const data = this.getBytes(); - - return util.concat([header, data]); - } - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - function readSimpleLength(bytes) { - let len = 0; - let offset; - const type = bytes[0]; - - - if (type < 192) { - [len] = bytes; - offset = 1; - } else if (type < 255) { - len = ((bytes[0] - 192) << 8) + (bytes[1]) + 192; - offset = 2; - } else if (type === 255) { - len = util.readNumber(bytes.subarray(1, 1 + 4)); - offset = 5; - } - - return { - len: len, - offset: offset - }; - } - - /** - * Encodes a given integer of length to the openpgp length specifier to a - * string - * - * @param {Integer} length - The length to encode - * @returns {Uint8Array} String with openpgp length representation. - */ - function writeSimpleLength(length) { - if (length < 192) { - return new Uint8Array([length]); - } else if (length > 191 && length < 8384) { - /* - * let a = (total data packet length) - 192 let bc = two octet - * representation of a let d = b + 192 - */ - return new Uint8Array([((length - 192) >> 8) + 192, (length - 192) & 0xFF]); - } - return util.concatUint8Array([new Uint8Array([255]), util.writeNumber(length, 4)]); - } - - function writePartialLength(power) { - if (power < 0 || power > 30) { - throw new Error('Partial Length power must be between 1 and 30'); - } - return new Uint8Array([224 + power]); - } - - function writeTag(tag_type) { - /* we're only generating v4 packet headers here */ - return new Uint8Array([0xC0 | tag_type]); - } - - /** - * Writes a packet header version 4 with the given tag_type and length to a - * string - * - * @param {Integer} tag_type - Tag type - * @param {Integer} length - Length of the payload - * @returns {String} String of the header. - */ - function writeHeader(tag_type, length) { - /* we're only generating v4 packet headers here */ - return util.concatUint8Array([writeTag(tag_type), writeSimpleLength(length)]); - } - - /** - * Whether the packet type supports partial lengths per RFC4880 - * @param {Integer} tag - Tag type - * @returns {Boolean} String of the header. - */ - function supportsStreaming(tag) { - return [ - enums.packet.literalData, - enums.packet.compressedData, - enums.packet.symmetricallyEncryptedData, - enums.packet.symEncryptedIntegrityProtectedData, - enums.packet.aeadEncryptedData - ].includes(tag); - } - - /** - * Generic static Packet Parser function - * - * @param {Uint8Array | ReadableStream} input - Input stream as string - * @param {Function} callback - Function to call with the parsed packet - * @returns {Boolean} Returns false if the stream was empty and parsing is done, and true otherwise. - */ - async function readPackets(input, callback) { - const reader = getReader(input); - let writer; - let callbackReturned; - try { - const peekedBytes = await reader.peekBytes(2); - // some sanity checks - if (!peekedBytes || peekedBytes.length < 2 || (peekedBytes[0] & 0x80) === 0) { - throw new Error('Error during parsing. This message / key probably does not conform to a valid OpenPGP format.'); - } - const headerByte = await reader.readByte(); - let tag = -1; - let format = -1; - let packetLength; - - format = 0; // 0 = old format; 1 = new format - if ((headerByte & 0x40) !== 0) { - format = 1; - } - - let packetLengthType; - if (format) { - // new format header - tag = headerByte & 0x3F; // bit 5-0 - } else { - // old format header - tag = (headerByte & 0x3F) >> 2; // bit 5-2 - packetLengthType = headerByte & 0x03; // bit 1-0 - } - - const packetSupportsStreaming = supportsStreaming(tag); - let packet = null; - if (packetSupportsStreaming) { - if (util.isStream(input) === 'array') { - const arrayStream = new ArrayStream(); - writer = getWriter(arrayStream); - packet = arrayStream; - } else { - const transform = new TransformStream(); - writer = getWriter(transform.writable); - packet = transform.readable; - } - callbackReturned = callback({ tag, packet }); - } else { - packet = []; - } - - let wasPartialLength; - do { - if (!format) { - // 4.2.1. Old Format Packet Lengths - switch (packetLengthType) { - case 0: - // The packet has a one-octet length. The header is 2 octets - // long. - packetLength = await reader.readByte(); - break; - case 1: - // The packet has a two-octet length. The header is 3 octets - // long. - packetLength = (await reader.readByte() << 8) | await reader.readByte(); - break; - case 2: - // The packet has a four-octet length. The header is 5 - // octets long. - packetLength = (await reader.readByte() << 24) | (await reader.readByte() << 16) | (await reader.readByte() << - 8) | await reader.readByte(); - break; - default: - // 3 - The packet is of indeterminate length. The header is 1 - // octet long, and the implementation must determine how long - // the packet is. If the packet is in a file, this means that - // the packet extends until the end of the file. In general, - // an implementation SHOULD NOT use indeterminate-length - // packets except where the end of the data will be clear - // from the context, and even then it is better to use a - // definite length, or a new format header. The new format - // headers described below have a mechanism for precisely - // encoding data of indeterminate length. - packetLength = Infinity; - break; - } - } else { // 4.2.2. New Format Packet Lengths - // 4.2.2.1. One-Octet Lengths - const lengthByte = await reader.readByte(); - wasPartialLength = false; - if (lengthByte < 192) { - packetLength = lengthByte; - // 4.2.2.2. Two-Octet Lengths - } else if (lengthByte >= 192 && lengthByte < 224) { - packetLength = ((lengthByte - 192) << 8) + (await reader.readByte()) + 192; - // 4.2.2.4. Partial Body Lengths - } else if (lengthByte > 223 && lengthByte < 255) { - packetLength = 1 << (lengthByte & 0x1F); - wasPartialLength = true; - if (!packetSupportsStreaming) { - throw new TypeError('This packet type does not support partial lengths.'); - } - // 4.2.2.3. Five-Octet Lengths - } else { - packetLength = (await reader.readByte() << 24) | (await reader.readByte() << 16) | (await reader.readByte() << - 8) | await reader.readByte(); - } - } - if (packetLength > 0) { - let bytesRead = 0; - while (true) { - if (writer) await writer.ready; - const { done, value } = await reader.read(); - if (done) { - if (packetLength === Infinity) break; - throw new Error('Unexpected end of packet'); - } - const chunk = packetLength === Infinity ? value : value.subarray(0, packetLength - bytesRead); - if (writer) await writer.write(chunk); - else packet.push(chunk); - bytesRead += value.length; - if (bytesRead >= packetLength) { - reader.unshift(value.subarray(packetLength - bytesRead + value.length)); - break; - } - } - } - } while (wasPartialLength); - - // If this was not a packet that "supports streaming", we peek to check - // whether it is the last packet in the message. We peek 2 bytes instead - // of 1 because the beginning of this function also peeks 2 bytes, and we - // want to cut a `subarray` of the correct length into `web-stream-tools`' - // `externalBuffer` as a tiny optimization here. - // - // If it *was* a streaming packet (i.e. the data packets), we peek at the - // entire remainder of the stream, in order to forward errors in the - // remainder of the stream to the packet data. (Note that this means we - // read/peek at all signature packets before closing the literal data - // packet, for example.) This forwards MDC errors to the literal data - // stream, for example, so that they don't get lost / forgotten on - // decryptedMessage.packets.stream, which we never look at. - // - // An example of what we do when stream-parsing a message containing - // [ one-pass signature packet, literal data packet, signature packet ]: - // 1. Read the one-pass signature packet - // 2. Peek 2 bytes of the literal data packet - // 3. Parse the one-pass signature packet - // - // 4. Read the literal data packet, simultaneously stream-parsing it - // 5. Peek until the end of the message - // 6. Finish parsing the literal data packet - // - // 7. Read the signature packet again (we already peeked at it in step 5) - // 8. Peek at the end of the stream again (`peekBytes` returns undefined) - // 9. Parse the signature packet - // - // Note that this means that if there's an error in the very end of the - // stream, such as an MDC error, we throw in step 5 instead of in step 8 - // (or never), which is the point of this exercise. - const nextPacket = await reader.peekBytes(packetSupportsStreaming ? Infinity : 2); - if (writer) { - await writer.ready; - await writer.close(); - } else { - packet = util.concatUint8Array(packet); - await callback({ tag, packet }); - } - return !nextPacket || !nextPacket.length; - } catch (e) { - if (writer) { - await writer.abort(e); - return true; - } else { - throw e; - } - } finally { - if (writer) { - await callbackReturned; - } - reader.releaseLock(); - } - } - - class UnsupportedError extends Error { - constructor(...params) { - super(...params); - - if (Error.captureStackTrace) { - Error.captureStackTrace(this, UnsupportedError); - } - - this.name = 'UnsupportedError'; - } - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - // Symbol to store cryptographic validity of the signature, to avoid recomputing multiple times on verification. - const verified = Symbol('verified'); - - // GPG puts the Issuer and Signature subpackets in the unhashed area. - // Tampering with those invalidates the signature, so we still trust them and parse them. - // All other unhashed subpackets are ignored. - const allowedUnhashedSubpackets = new Set([ - enums.signatureSubpacket.issuer, - enums.signatureSubpacket.issuerFingerprint, - enums.signatureSubpacket.embeddedSignature - ]); - - /** - * Implementation of the Signature Packet (Tag 2) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.2|RFC4480 5.2}: - * A Signature packet describes a binding between some public key and - * some data. The most common signatures are a signature of a file or a - * block of text, and a signature that is a certification of a User ID. - */ - class SignaturePacket { - static get tag() { - return enums.packet.signature; - } - - constructor() { - this.version = null; - /** @type {enums.signature} */ - this.signatureType = null; - /** @type {enums.hash} */ - this.hashAlgorithm = null; - /** @type {enums.publicKey} */ - this.publicKeyAlgorithm = null; - - this.signatureData = null; - this.unhashedSubpackets = []; - this.signedHashValue = null; - - this.created = null; - this.signatureExpirationTime = null; - this.signatureNeverExpires = true; - this.exportable = null; - this.trustLevel = null; - this.trustAmount = null; - this.regularExpression = null; - this.revocable = null; - this.keyExpirationTime = null; - this.keyNeverExpires = null; - this.preferredSymmetricAlgorithms = null; - this.revocationKeyClass = null; - this.revocationKeyAlgorithm = null; - this.revocationKeyFingerprint = null; - this.issuerKeyID = new KeyID(); - this.rawNotations = []; - this.notations = {}; - this.preferredHashAlgorithms = null; - this.preferredCompressionAlgorithms = null; - this.keyServerPreferences = null; - this.preferredKeyServer = null; - this.isPrimaryUserID = null; - this.policyURI = null; - this.keyFlags = null; - this.signersUserID = null; - this.reasonForRevocationFlag = null; - this.reasonForRevocationString = null; - this.features = null; - this.signatureTargetPublicKeyAlgorithm = null; - this.signatureTargetHashAlgorithm = null; - this.signatureTargetHash = null; - this.embeddedSignature = null; - this.issuerKeyVersion = null; - this.issuerFingerprint = null; - this.preferredAEADAlgorithms = null; - - this.revoked = null; - this[verified] = null; - } - - /** - * parsing function for a signature packet (tag 2). - * @param {String} bytes - Payload of a tag 2 packet - * @returns {SignaturePacket} Object representation. - */ - read(bytes) { - let i = 0; - this.version = bytes[i++]; - - if (this.version !== 4 && this.version !== 5) { - throw new UnsupportedError(`Version ${this.version} of the signature packet is unsupported.`); - } - - this.signatureType = bytes[i++]; - this.publicKeyAlgorithm = bytes[i++]; - this.hashAlgorithm = bytes[i++]; - - // hashed subpackets - i += this.readSubPackets(bytes.subarray(i, bytes.length), true); - if (!this.created) { - throw new Error('Missing signature creation time subpacket.'); - } - - // A V4 signature hashes the packet body - // starting from its first field, the version number, through the end - // of the hashed subpacket data. Thus, the fields hashed are the - // signature version, the signature type, the public-key algorithm, the - // hash algorithm, the hashed subpacket length, and the hashed - // subpacket body. - this.signatureData = bytes.subarray(0, i); - - // unhashed subpackets - i += this.readSubPackets(bytes.subarray(i, bytes.length), false); - - // Two-octet field holding left 16 bits of signed hash value. - this.signedHashValue = bytes.subarray(i, i + 2); - i += 2; - - this.params = mod.signature.parseSignatureParams(this.publicKeyAlgorithm, bytes.subarray(i, bytes.length)); - } - - /** - * @returns {Uint8Array | ReadableStream} - */ - writeParams() { - if (this.params instanceof Promise) { - return fromAsync( - async () => mod.serializeParams(this.publicKeyAlgorithm, await this.params) - ); - } - return mod.serializeParams(this.publicKeyAlgorithm, this.params); - } - - write() { - const arr = []; - arr.push(this.signatureData); - arr.push(this.writeUnhashedSubPackets()); - arr.push(this.signedHashValue); - arr.push(this.writeParams()); - return util.concat(arr); - } - - /** - * Signs provided data. This needs to be done prior to serialization. - * @param {SecretKeyPacket} key - Private key used to sign the message. - * @param {Object} data - Contains packets to be signed. - * @param {Date} [date] - The signature creation time. - * @param {Boolean} [detached] - Whether to create a detached signature - * @throws {Error} if signing failed - * @async - */ - async sign(key, data, date = new Date(), detached = false) { - if (key.version === 5) { - this.version = 5; - } else { - this.version = 4; - } - const arr = [new Uint8Array([this.version, this.signatureType, this.publicKeyAlgorithm, this.hashAlgorithm])]; - - this.created = util.normalizeDate(date); - this.issuerKeyVersion = key.version; - this.issuerFingerprint = key.getFingerprintBytes(); - this.issuerKeyID = key.getKeyID(); - - // Add hashed subpackets - arr.push(this.writeHashedSubPackets()); - - this.signatureData = util.concat(arr); - - const toHash = this.toHash(this.signatureType, data, detached); - const hash = await this.hash(this.signatureType, data, toHash, detached); - - this.signedHashValue = slice(clone(hash), 0, 2); - const signed = async () => mod.signature.sign( - this.publicKeyAlgorithm, this.hashAlgorithm, key.publicParams, key.privateParams, toHash, await readToEnd(hash) - ); - if (util.isStream(hash)) { - this.params = signed(); - } else { - this.params = await signed(); - - // Store the fact that this signature is valid, e.g. for when we call `await - // getLatestValidSignature(this.revocationSignatures, key, data)` later. - // Note that this only holds up if the key and data passed to verify are the - // same as the ones passed to sign. - this[verified] = true; - } - } - - /** - * Creates Uint8Array of bytes of all subpacket data except Issuer and Embedded Signature subpackets - * @returns {Uint8Array} Subpacket data. - */ - writeHashedSubPackets() { - const sub = enums.signatureSubpacket; - const arr = []; - let bytes; - if (this.created === null) { - throw new Error('Missing signature creation time'); - } - arr.push(writeSubPacket(sub.signatureCreationTime, util.writeDate(this.created))); - if (this.signatureExpirationTime !== null) { - arr.push(writeSubPacket(sub.signatureExpirationTime, util.writeNumber(this.signatureExpirationTime, 4))); - } - if (this.exportable !== null) { - arr.push(writeSubPacket(sub.exportableCertification, new Uint8Array([this.exportable ? 1 : 0]))); - } - if (this.trustLevel !== null) { - bytes = new Uint8Array([this.trustLevel, this.trustAmount]); - arr.push(writeSubPacket(sub.trustSignature, bytes)); - } - if (this.regularExpression !== null) { - arr.push(writeSubPacket(sub.regularExpression, this.regularExpression)); - } - if (this.revocable !== null) { - arr.push(writeSubPacket(sub.revocable, new Uint8Array([this.revocable ? 1 : 0]))); - } - if (this.keyExpirationTime !== null) { - arr.push(writeSubPacket(sub.keyExpirationTime, util.writeNumber(this.keyExpirationTime, 4))); - } - if (this.preferredSymmetricAlgorithms !== null) { - bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredSymmetricAlgorithms)); - arr.push(writeSubPacket(sub.preferredSymmetricAlgorithms, bytes)); - } - if (this.revocationKeyClass !== null) { - bytes = new Uint8Array([this.revocationKeyClass, this.revocationKeyAlgorithm]); - bytes = util.concat([bytes, this.revocationKeyFingerprint]); - arr.push(writeSubPacket(sub.revocationKey, bytes)); - } - this.rawNotations.forEach(([{ name, value, humanReadable }]) => { - bytes = [new Uint8Array([humanReadable ? 0x80 : 0, 0, 0, 0])]; - // 2 octets of name length - bytes.push(util.writeNumber(name.length, 2)); - // 2 octets of value length - bytes.push(util.writeNumber(value.length, 2)); - bytes.push(util.stringToUint8Array(name)); - bytes.push(value); - bytes = util.concat(bytes); - arr.push(writeSubPacket(sub.notationData, bytes)); - }); - if (this.preferredHashAlgorithms !== null) { - bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredHashAlgorithms)); - arr.push(writeSubPacket(sub.preferredHashAlgorithms, bytes)); - } - if (this.preferredCompressionAlgorithms !== null) { - bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredCompressionAlgorithms)); - arr.push(writeSubPacket(sub.preferredCompressionAlgorithms, bytes)); - } - if (this.keyServerPreferences !== null) { - bytes = util.stringToUint8Array(util.uint8ArrayToString(this.keyServerPreferences)); - arr.push(writeSubPacket(sub.keyServerPreferences, bytes)); - } - if (this.preferredKeyServer !== null) { - arr.push(writeSubPacket(sub.preferredKeyServer, util.stringToUint8Array(this.preferredKeyServer))); - } - if (this.isPrimaryUserID !== null) { - arr.push(writeSubPacket(sub.primaryUserID, new Uint8Array([this.isPrimaryUserID ? 1 : 0]))); - } - if (this.policyURI !== null) { - arr.push(writeSubPacket(sub.policyURI, util.stringToUint8Array(this.policyURI))); - } - if (this.keyFlags !== null) { - bytes = util.stringToUint8Array(util.uint8ArrayToString(this.keyFlags)); - arr.push(writeSubPacket(sub.keyFlags, bytes)); - } - if (this.signersUserID !== null) { - arr.push(writeSubPacket(sub.signersUserID, util.stringToUint8Array(this.signersUserID))); - } - if (this.reasonForRevocationFlag !== null) { - bytes = util.stringToUint8Array(String.fromCharCode(this.reasonForRevocationFlag) + this.reasonForRevocationString); - arr.push(writeSubPacket(sub.reasonForRevocation, bytes)); - } - if (this.features !== null) { - bytes = util.stringToUint8Array(util.uint8ArrayToString(this.features)); - arr.push(writeSubPacket(sub.features, bytes)); - } - if (this.signatureTargetPublicKeyAlgorithm !== null) { - bytes = [new Uint8Array([this.signatureTargetPublicKeyAlgorithm, this.signatureTargetHashAlgorithm])]; - bytes.push(util.stringToUint8Array(this.signatureTargetHash)); - bytes = util.concat(bytes); - arr.push(writeSubPacket(sub.signatureTarget, bytes)); - } - if (this.preferredAEADAlgorithms !== null) { - bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredAEADAlgorithms)); - arr.push(writeSubPacket(sub.preferredAEADAlgorithms, bytes)); - } - - const result = util.concat(arr); - const length = util.writeNumber(result.length, 2); - - return util.concat([length, result]); - } - - /** - * Creates Uint8Array of bytes of Issuer and Embedded Signature subpackets - * @returns {Uint8Array} Subpacket data. - */ - writeUnhashedSubPackets() { - const sub = enums.signatureSubpacket; - const arr = []; - let bytes; - if (!this.issuerKeyID.isNull() && this.issuerKeyVersion !== 5) { - // If the version of [the] key is greater than 4, this subpacket - // MUST NOT be included in the signature. - arr.push(writeSubPacket(sub.issuer, this.issuerKeyID.write())); - } - if (this.embeddedSignature !== null) { - arr.push(writeSubPacket(sub.embeddedSignature, this.embeddedSignature.write())); - } - if (this.issuerFingerprint !== null) { - bytes = [new Uint8Array([this.issuerKeyVersion]), this.issuerFingerprint]; - bytes = util.concat(bytes); - arr.push(writeSubPacket(sub.issuerFingerprint, bytes)); - } - this.unhashedSubpackets.forEach(data => { - arr.push(writeSimpleLength(data.length)); - arr.push(data); - }); - - const result = util.concat(arr); - const length = util.writeNumber(result.length, 2); - - return util.concat([length, result]); - } - - // V4 signature sub packets - readSubPacket(bytes, hashed = true) { - let mypos = 0; - - // The leftmost bit denotes a "critical" packet - const critical = bytes[mypos] & 0x80; - const type = bytes[mypos] & 0x7F; - - if (!hashed && !allowedUnhashedSubpackets.has(type)) { - this.unhashedSubpackets.push(bytes.subarray(mypos, bytes.length)); - return; - } - - mypos++; - - // subpacket type - switch (type) { - case enums.signatureSubpacket.signatureCreationTime: - // Signature Creation Time - this.created = util.readDate(bytes.subarray(mypos, bytes.length)); - break; - case enums.signatureSubpacket.signatureExpirationTime: { - // Signature Expiration Time in seconds - const seconds = util.readNumber(bytes.subarray(mypos, bytes.length)); - - this.signatureNeverExpires = seconds === 0; - this.signatureExpirationTime = seconds; - - break; - } - case enums.signatureSubpacket.exportableCertification: - // Exportable Certification - this.exportable = bytes[mypos++] === 1; - break; - case enums.signatureSubpacket.trustSignature: - // Trust Signature - this.trustLevel = bytes[mypos++]; - this.trustAmount = bytes[mypos++]; - break; - case enums.signatureSubpacket.regularExpression: - // Regular Expression - this.regularExpression = bytes[mypos]; - break; - case enums.signatureSubpacket.revocable: - // Revocable - this.revocable = bytes[mypos++] === 1; - break; - case enums.signatureSubpacket.keyExpirationTime: { - // Key Expiration Time in seconds - const seconds = util.readNumber(bytes.subarray(mypos, bytes.length)); - - this.keyExpirationTime = seconds; - this.keyNeverExpires = seconds === 0; - - break; - } - case enums.signatureSubpacket.preferredSymmetricAlgorithms: - // Preferred Symmetric Algorithms - this.preferredSymmetricAlgorithms = [...bytes.subarray(mypos, bytes.length)]; - break; - case enums.signatureSubpacket.revocationKey: - // Revocation Key - // (1 octet of class, 1 octet of public-key algorithm ID, 20 - // octets of - // fingerprint) - this.revocationKeyClass = bytes[mypos++]; - this.revocationKeyAlgorithm = bytes[mypos++]; - this.revocationKeyFingerprint = bytes.subarray(mypos, mypos + 20); - break; - - case enums.signatureSubpacket.issuer: - // Issuer - this.issuerKeyID.read(bytes.subarray(mypos, bytes.length)); - break; - - case enums.signatureSubpacket.notationData: { - // Notation Data - const humanReadable = !!(bytes[mypos] & 0x80); - - // We extract key/value tuple from the byte stream. - mypos += 4; - const m = util.readNumber(bytes.subarray(mypos, mypos + 2)); - mypos += 2; - const n = util.readNumber(bytes.subarray(mypos, mypos + 2)); - mypos += 2; - - const name = util.uint8ArrayToString(bytes.subarray(mypos, mypos + m)); - const value = bytes.subarray(mypos + m, mypos + m + n); - - this.rawNotations.push({ name, humanReadable, value, critical }); - - if (humanReadable) { - this.notations[name] = util.uint8ArrayToString(value); - } - break; - } - case enums.signatureSubpacket.preferredHashAlgorithms: - // Preferred Hash Algorithms - this.preferredHashAlgorithms = [...bytes.subarray(mypos, bytes.length)]; - break; - case enums.signatureSubpacket.preferredCompressionAlgorithms: - // Preferred Compression Algorithms - this.preferredCompressionAlgorithms = [...bytes.subarray(mypos, bytes.length)]; - break; - case enums.signatureSubpacket.keyServerPreferences: - // Key Server Preferences - this.keyServerPreferences = [...bytes.subarray(mypos, bytes.length)]; - break; - case enums.signatureSubpacket.preferredKeyServer: - // Preferred Key Server - this.preferredKeyServer = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); - break; - case enums.signatureSubpacket.primaryUserID: - // Primary User ID - this.isPrimaryUserID = bytes[mypos++] !== 0; - break; - case enums.signatureSubpacket.policyURI: - // Policy URI - this.policyURI = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); - break; - case enums.signatureSubpacket.keyFlags: - // Key Flags - this.keyFlags = [...bytes.subarray(mypos, bytes.length)]; - break; - case enums.signatureSubpacket.signersUserID: - // Signer's User ID - this.signersUserID = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); - break; - case enums.signatureSubpacket.reasonForRevocation: - // Reason for Revocation - this.reasonForRevocationFlag = bytes[mypos++]; - this.reasonForRevocationString = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); - break; - case enums.signatureSubpacket.features: - // Features - this.features = [...bytes.subarray(mypos, bytes.length)]; - break; - case enums.signatureSubpacket.signatureTarget: { - // Signature Target - // (1 octet public-key algorithm, 1 octet hash algorithm, N octets hash) - this.signatureTargetPublicKeyAlgorithm = bytes[mypos++]; - this.signatureTargetHashAlgorithm = bytes[mypos++]; - - const len = mod.getHashByteLength(this.signatureTargetHashAlgorithm); - - this.signatureTargetHash = util.uint8ArrayToString(bytes.subarray(mypos, mypos + len)); - break; - } - case enums.signatureSubpacket.embeddedSignature: - // Embedded Signature - this.embeddedSignature = new SignaturePacket(); - this.embeddedSignature.read(bytes.subarray(mypos, bytes.length)); - break; - case enums.signatureSubpacket.issuerFingerprint: - // Issuer Fingerprint - this.issuerKeyVersion = bytes[mypos++]; - this.issuerFingerprint = bytes.subarray(mypos, bytes.length); - if (this.issuerKeyVersion === 5) { - this.issuerKeyID.read(this.issuerFingerprint); - } else { - this.issuerKeyID.read(this.issuerFingerprint.subarray(-8)); - } - break; - case enums.signatureSubpacket.preferredAEADAlgorithms: - // Preferred AEAD Algorithms - this.preferredAEADAlgorithms = [...bytes.subarray(mypos, bytes.length)]; - break; - default: { - const err = new Error(`Unknown signature subpacket type ${type}`); - if (critical) { - throw err; - } else { - util.printDebug(err); - } - } - } - } - - readSubPackets(bytes, trusted = true, config) { - // Two-octet scalar octet count for following subpacket data. - const subpacketLength = util.readNumber(bytes.subarray(0, 2)); - - let i = 2; - - // subpacket data set (zero or more subpackets) - while (i < 2 + subpacketLength) { - const len = readSimpleLength(bytes.subarray(i, bytes.length)); - i += len.offset; - - this.readSubPacket(bytes.subarray(i, i + len.len), trusted, config); - - i += len.len; - } - - return i; - } - - // Produces data to produce signature on - toSign(type, data) { - const t = enums.signature; - - switch (type) { - case t.binary: - if (data.text !== null) { - return util.encodeUTF8(data.getText(true)); - } - return data.getBytes(true); - - case t.text: { - const bytes = data.getBytes(true); - // normalize EOL to \r\n - return util.canonicalizeEOL(bytes); - } - case t.standalone: - return new Uint8Array(0); - - case t.certGeneric: - case t.certPersona: - case t.certCasual: - case t.certPositive: - case t.certRevocation: { - let packet; - let tag; - - if (data.userID) { - tag = 0xB4; - packet = data.userID; - } else if (data.userAttribute) { - tag = 0xD1; - packet = data.userAttribute; - } else { - throw new Error('Either a userID or userAttribute packet needs to be ' + - 'supplied for certification.'); - } - - const bytes = packet.write(); - - return util.concat([this.toSign(t.key, data), - new Uint8Array([tag]), - util.writeNumber(bytes.length, 4), - bytes]); - } - case t.subkeyBinding: - case t.subkeyRevocation: - case t.keyBinding: - return util.concat([this.toSign(t.key, data), this.toSign(t.key, { - key: data.bind - })]); - - case t.key: - if (data.key === undefined) { - throw new Error('Key packet is required for this signature.'); - } - return data.key.writeForHash(this.version); - - case t.keyRevocation: - return this.toSign(t.key, data); - case t.timestamp: - return new Uint8Array(0); - case t.thirdParty: - throw new Error('Not implemented'); - default: - throw new Error('Unknown signature type.'); - } - } - - calculateTrailer(data, detached) { - let length = 0; - return transform(clone(this.signatureData), value => { - length += value.length; - }, () => { - const arr = []; - if (this.version === 5 && (this.signatureType === enums.signature.binary || this.signatureType === enums.signature.text)) { - if (detached) { - arr.push(new Uint8Array(6)); - } else { - arr.push(data.writeHeader()); - } - } - arr.push(new Uint8Array([this.version, 0xFF])); - if (this.version === 5) { - arr.push(new Uint8Array(4)); - } - arr.push(util.writeNumber(length, 4)); - // For v5, this should really be writeNumber(length, 8) rather than the - // hardcoded 4 zero bytes above - return util.concat(arr); - }); - } - - toHash(signatureType, data, detached = false) { - const bytes = this.toSign(signatureType, data); - - return util.concat([bytes, this.signatureData, this.calculateTrailer(data, detached)]); - } - - async hash(signatureType, data, toHash, detached = false) { - if (!toHash) toHash = this.toHash(signatureType, data, detached); - return mod.hash.digest(this.hashAlgorithm, toHash); - } - - /** - * verifies the signature packet. Note: not all signature types are implemented - * @param {PublicSubkeyPacket|PublicKeyPacket| - * SecretSubkeyPacket|SecretKeyPacket} key - the public key to verify the signature - * @param {module:enums.signature} signatureType - Expected signature type - * @param {String|Object} data - Data which on the signature applies - * @param {Date} [date] - Use the given date instead of the current time to check for signature validity and expiration - * @param {Boolean} [detached] - Whether to verify a detached signature - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if signature validation failed - * @async - */ - async verify(key, signatureType, data, date = new Date(), detached = false, config = defaultConfig) { - if (!this.issuerKeyID.equals(key.getKeyID())) { - throw new Error('Signature was not issued by the given public key'); - } - if (this.publicKeyAlgorithm !== key.algorithm) { - throw new Error('Public key algorithm used to sign signature does not match issuer key algorithm.'); - } - - const isMessageSignature = signatureType === enums.signature.binary || signatureType === enums.signature.text; - // Cryptographic validity is cached after one successful verification. - // However, for message signatures, we always re-verify, since the passed `data` can change - const skipVerify = this[verified] && !isMessageSignature; - if (!skipVerify) { - let toHash; - let hash; - if (this.hashed) { - hash = await this.hashed; - } else { - toHash = this.toHash(signatureType, data, detached); - hash = await this.hash(signatureType, data, toHash); - } - hash = await readToEnd(hash); - if (this.signedHashValue[0] !== hash[0] || - this.signedHashValue[1] !== hash[1]) { - throw new Error('Signed digest did not match'); - } - - this.params = await this.params; - - this[verified] = await mod.signature.verify( - this.publicKeyAlgorithm, this.hashAlgorithm, this.params, key.publicParams, - toHash, hash - ); - - if (!this[verified]) { - throw new Error('Signature verification failed'); - } - } - - const normDate = util.normalizeDate(date); - if (normDate && this.created > normDate) { - throw new Error('Signature creation time is in the future'); - } - if (normDate && normDate >= this.getExpirationTime()) { - throw new Error('Signature is expired'); - } - if (config.rejectHashAlgorithms.has(this.hashAlgorithm)) { - throw new Error('Insecure hash algorithm: ' + enums.read(enums.hash, this.hashAlgorithm).toUpperCase()); - } - if (config.rejectMessageHashAlgorithms.has(this.hashAlgorithm) && - [enums.signature.binary, enums.signature.text].includes(this.signatureType)) { - throw new Error('Insecure message hash algorithm: ' + enums.read(enums.hash, this.hashAlgorithm).toUpperCase()); - } - this.rawNotations.forEach(({ name, critical }) => { - if (critical && (config.knownNotations.indexOf(name) < 0)) { - throw new Error(`Unknown critical notation: ${name}`); - } - }); - if (this.revocationKeyClass !== null) { - throw new Error('This key is intended to be revoked with an authorized key, which OpenPGP.js does not support.'); - } - } - - /** - * Verifies signature expiration date - * @param {Date} [date] - Use the given date for verification instead of the current time - * @returns {Boolean} True if expired. - */ - isExpired(date = new Date()) { - const normDate = util.normalizeDate(date); - if (normDate !== null) { - return !(this.created <= normDate && normDate < this.getExpirationTime()); - } - return false; - } - - /** - * Returns the expiration time of the signature or Infinity if signature does not expire - * @returns {Date | Infinity} Expiration time. - */ - getExpirationTime() { - return this.signatureNeverExpires ? Infinity : new Date(this.created.getTime() + this.signatureExpirationTime * 1000); - } - } - - /** - * Creates a string representation of a sub signature packet - * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.1|RFC4880 5.2.3.1} - * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.2|RFC4880 5.2.3.2} - * @param {Integer} type - Subpacket signature type. - * @param {String} data - Data to be included - * @returns {String} A string-representation of a sub signature packet. - * @private - */ - function writeSubPacket(type, data) { - const arr = []; - arr.push(writeSimpleLength(data.length + 1)); - arr.push(new Uint8Array([type])); - arr.push(data); - return util.concat(arr); - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - const VERSION = 3; - - /** - * Implementation of the One-Pass Signature Packets (Tag 4) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.4|RFC4880 5.4}: - * The One-Pass Signature packet precedes the signed data and contains - * enough information to allow the receiver to begin calculating any - * hashes needed to verify the signature. It allows the Signature - * packet to be placed at the end of the message, so that the signer - * can compute the entire signed message in one pass. - */ - class OnePassSignaturePacket { - static get tag() { - return enums.packet.onePassSignature; - } - - constructor() { - /** A one-octet version number. The current version is 3. */ - this.version = null; - /** - * A one-octet signature type. - * Signature types are described in - * {@link https://tools.ietf.org/html/rfc4880#section-5.2.1|RFC4880 Section 5.2.1}. - * @type {enums.signature} - - */ - this.signatureType = null; - /** - * A one-octet number describing the hash algorithm used. - * @see {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC4880 9.4} - * @type {enums.hash} - */ - this.hashAlgorithm = null; - /** - * A one-octet number describing the public-key algorithm used. - * @see {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC4880 9.1} - * @type {enums.publicKey} - */ - this.publicKeyAlgorithm = null; - /** An eight-octet number holding the Key ID of the signing key. */ - this.issuerKeyID = null; - /** - * A one-octet number holding a flag showing whether the signature is nested. - * A zero value indicates that the next packet is another One-Pass Signature packet - * that describes another signature to be applied to the same message data. - */ - this.flags = null; - } - - /** - * parsing function for a one-pass signature packet (tag 4). - * @param {Uint8Array} bytes - Payload of a tag 4 packet - * @returns {OnePassSignaturePacket} Object representation. - */ - read(bytes) { - let mypos = 0; - // A one-octet version number. The current version is 3. - this.version = bytes[mypos++]; - if (this.version !== VERSION) { - throw new UnsupportedError(`Version ${this.version} of the one-pass signature packet is unsupported.`); - } - - // A one-octet signature type. Signature types are described in - // Section 5.2.1. - this.signatureType = bytes[mypos++]; - - // A one-octet number describing the hash algorithm used. - this.hashAlgorithm = bytes[mypos++]; - - // A one-octet number describing the public-key algorithm used. - this.publicKeyAlgorithm = bytes[mypos++]; - - // An eight-octet number holding the Key ID of the signing key. - this.issuerKeyID = new KeyID(); - this.issuerKeyID.read(bytes.subarray(mypos, mypos + 8)); - mypos += 8; - - // A one-octet number holding a flag showing whether the signature - // is nested. A zero value indicates that the next packet is - // another One-Pass Signature packet that describes another - // signature to be applied to the same message data. - this.flags = bytes[mypos++]; - return this; - } - - /** - * creates a string representation of a one-pass signature packet - * @returns {Uint8Array} A Uint8Array representation of a one-pass signature packet. - */ - write() { - const start = new Uint8Array([VERSION, this.signatureType, this.hashAlgorithm, this.publicKeyAlgorithm]); - - const end = new Uint8Array([this.flags]); - - return util.concatUint8Array([start, this.issuerKeyID.write(), end]); - } - - calculateTrailer(...args) { - return fromAsync(async () => SignaturePacket.prototype.calculateTrailer.apply(await this.correspondingSig, args)); - } - - async verify() { - const correspondingSig = await this.correspondingSig; - if (!correspondingSig || correspondingSig.constructor.tag !== enums.packet.signature) { - throw new Error('Corresponding signature packet missing'); - } - if ( - correspondingSig.signatureType !== this.signatureType || - correspondingSig.hashAlgorithm !== this.hashAlgorithm || - correspondingSig.publicKeyAlgorithm !== this.publicKeyAlgorithm || - !correspondingSig.issuerKeyID.equals(this.issuerKeyID) - ) { - throw new Error('Corresponding signature packet does not match one-pass signature packet'); - } - correspondingSig.hashed = this.hashed; - return correspondingSig.verify.apply(correspondingSig, arguments); - } - } - - OnePassSignaturePacket.prototype.hash = SignaturePacket.prototype.hash; - OnePassSignaturePacket.prototype.toHash = SignaturePacket.prototype.toHash; - OnePassSignaturePacket.prototype.toSign = SignaturePacket.prototype.toSign; - - /** - * Instantiate a new packet given its tag - * @function newPacketFromTag - * @param {module:enums.packet} tag - Property value from {@link module:enums.packet} - * @param {Object} allowedPackets - mapping where keys are allowed packet tags, pointing to their Packet class - * @returns {Object} New packet object with type based on tag - * @throws {Error|UnsupportedError} for disallowed or unknown packets - */ - function newPacketFromTag(tag, allowedPackets) { - if (!allowedPackets[tag]) { - // distinguish between disallowed packets and unknown ones - let packetType; - try { - packetType = enums.read(enums.packet, tag); - } catch (e) { - throw new UnsupportedError(`Unknown packet type with tag: ${tag}`); - } - throw new Error(`Packet not allowed in this context: ${packetType}`); - } - return new allowedPackets[tag](); - } - - /** - * This class represents a list of openpgp packets. - * Take care when iterating over it - the packets themselves - * are stored as numerical indices. - * @extends Array - */ - class PacketList extends Array { - /** - * Parses the given binary data and returns a list of packets. - * Equivalent to calling `read` on an empty PacketList instance. - * @param {Uint8Array | ReadableStream} bytes - binary data to parse - * @param {Object} allowedPackets - mapping where keys are allowed packet tags, pointing to their Packet class - * @param {Object} [config] - full configuration, defaults to openpgp.config - * @returns {PacketList} parsed list of packets - * @throws on parsing errors - * @async - */ - static async fromBinary(bytes, allowedPackets, config = defaultConfig) { - const packets = new PacketList(); - await packets.read(bytes, allowedPackets, config); - return packets; - } - - /** - * Reads a stream of binary data and interprets it as a list of packets. - * @param {Uint8Array | ReadableStream} bytes - binary data to parse - * @param {Object} allowedPackets - mapping where keys are allowed packet tags, pointing to their Packet class - * @param {Object} [config] - full configuration, defaults to openpgp.config - * @throws on parsing errors - * @async - */ - async read(bytes, allowedPackets, config = defaultConfig) { - this.stream = transformPair(bytes, async (readable, writable) => { - const writer = getWriter(writable); - try { - while (true) { - await writer.ready; - const done = await readPackets(readable, async parsed => { - try { - if (parsed.tag === enums.packet.marker || parsed.tag === enums.packet.trust) { - // According to the spec, these packet types should be ignored and not cause parsing errors, even if not esplicitly allowed: - // - Marker packets MUST be ignored when received: https://github.com/openpgpjs/openpgpjs/issues/1145 - // - Trust packets SHOULD be ignored outside of keyrings (unsupported): https://datatracker.ietf.org/doc/html/rfc4880#section-5.10 - return; - } - const packet = newPacketFromTag(parsed.tag, allowedPackets); - packet.packets = new PacketList(); - packet.fromStream = util.isStream(parsed.packet); - await packet.read(parsed.packet, config); - await writer.write(packet); - } catch (e) { - const throwUnsupportedError = !config.ignoreUnsupportedPackets && e instanceof UnsupportedError; - const throwMalformedError = !config.ignoreMalformedPackets && !(e instanceof UnsupportedError); - if (throwUnsupportedError || throwMalformedError || supportsStreaming(parsed.tag)) { - // The packets that support streaming are the ones that contain message data. - // Those are also the ones we want to be more strict about and throw on parse errors - // (since we likely cannot process the message without these packets anyway). - await writer.abort(e); - } - util.printDebugError(e); - } - }); - if (done) { - await writer.ready; - await writer.close(); - return; - } - } - } catch (e) { - await writer.abort(e); - } - }); - - // Wait until first few packets have been read - const reader = getReader(this.stream); - while (true) { - const { done, value } = await reader.read(); - if (!done) { - this.push(value); - } else { - this.stream = null; - } - if (done || supportsStreaming(value.constructor.tag)) { - break; - } - } - reader.releaseLock(); - } - - /** - * Creates a binary representation of openpgp objects contained within the - * class instance. - * @returns {Uint8Array} A Uint8Array containing valid openpgp packets. - */ - write() { - const arr = []; - - for (let i = 0; i < this.length; i++) { - const packetbytes = this[i].write(); - if (util.isStream(packetbytes) && supportsStreaming(this[i].constructor.tag)) { - let buffer = []; - let bufferLength = 0; - const minLength = 512; - arr.push(writeTag(this[i].constructor.tag)); - arr.push(transform(packetbytes, value => { - buffer.push(value); - bufferLength += value.length; - if (bufferLength >= minLength) { - const powerOf2 = Math.min(Math.log(bufferLength) / Math.LN2 | 0, 30); - const chunkSize = 2 ** powerOf2; - const bufferConcat = util.concat([writePartialLength(powerOf2)].concat(buffer)); - buffer = [bufferConcat.subarray(1 + chunkSize)]; - bufferLength = buffer[0].length; - return bufferConcat.subarray(0, 1 + chunkSize); - } - }, () => util.concat([writeSimpleLength(bufferLength)].concat(buffer)))); - } else { - if (util.isStream(packetbytes)) { - let length = 0; - arr.push(transform(clone(packetbytes), value => { - length += value.length; - }, () => writeHeader(this[i].constructor.tag, length))); - } else { - arr.push(writeHeader(this[i].constructor.tag, packetbytes.length)); - } - arr.push(packetbytes); - } - } - - return util.concat(arr); - } - - /** - * Creates a new PacketList with all packets matching the given tag(s) - * @param {...module:enums.packet} tags - packet tags to look for - * @returns {PacketList} - */ - filterByTag(...tags) { - const filtered = new PacketList(); - - const handle = tag => packetType => tag === packetType; - - for (let i = 0; i < this.length; i++) { - if (tags.some(handle(this[i].constructor.tag))) { - filtered.push(this[i]); - } - } - - return filtered; - } - - /** - * Traverses packet list and returns first packet with matching tag - * @param {module:enums.packet} tag - The packet tag - * @returns {Packet|undefined} - */ - findPacket(tag) { - return this.find(packet => packet.constructor.tag === tag); - } - - /** - * Find indices of packets with the given tag(s) - * @param {...module:enums.packet} tags - packet tags to look for - * @returns {Integer[]} packet indices - */ - indexOfTag(...tags) { - const tagIndex = []; - const that = this; - - const handle = tag => packetType => tag === packetType; - - for (let i = 0; i < this.length; i++) { - if (tags.some(handle(that[i].constructor.tag))) { - tagIndex.push(i); - } - } - return tagIndex; - } - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - // A Compressed Data packet can contain the following packet types - const allowedPackets = /*#__PURE__*/ util.constructAllowedPackets([ - LiteralDataPacket, - OnePassSignaturePacket, - SignaturePacket - ]); - - /** - * Implementation of the Compressed Data Packet (Tag 8) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.6|RFC4880 5.6}: - * The Compressed Data packet contains compressed data. Typically, - * this packet is found as the contents of an encrypted packet, or following - * a Signature or One-Pass Signature packet, and contains a literal data packet. - */ - class CompressedDataPacket { - static get tag() { - return enums.packet.compressedData; - } - - /** - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - constructor(config = defaultConfig) { - /** - * List of packets - * @type {PacketList} - */ - this.packets = null; - /** - * Compression algorithm - * @type {enums.compression} - */ - this.algorithm = config.preferredCompressionAlgorithm; - - /** - * Compressed packet data - * @type {Uint8Array | ReadableStream} - */ - this.compressed = null; - - /** - * zip/zlib compression level, between 1 and 9 - */ - this.deflateLevel = config.deflateLevel; - } - - /** - * Parsing function for the packet. - * @param {Uint8Array | ReadableStream} bytes - Payload of a tag 8 packet - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - async read(bytes, config = defaultConfig) { - await parse(bytes, async reader => { - - // One octet that gives the algorithm used to compress the packet. - this.algorithm = await reader.readByte(); - - // Compressed data, which makes up the remainder of the packet. - this.compressed = reader.remainder(); - - await this.decompress(config); - }); - } - - - /** - * Return the compressed packet. - * @returns {Uint8Array | ReadableStream} Binary compressed packet. - */ - write() { - if (this.compressed === null) { - this.compress(); - } - - return util.concat([new Uint8Array([this.algorithm]), this.compressed]); - } - - - /** - * Decompression method for decompressing the compressed data - * read by read_packet - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - async decompress(config = defaultConfig) { - const compressionName = enums.read(enums.compression, this.algorithm); - const decompressionFn = decompress_fns[compressionName]; - if (!decompressionFn) { - throw new Error(`${compressionName} decompression not supported`); - } - - this.packets = await PacketList.fromBinary(decompressionFn(this.compressed), allowedPackets, config); - } - - /** - * Compress the packet data (member decompressedData) - */ - compress() { - const compressionName = enums.read(enums.compression, this.algorithm); - const compressionFn = compress_fns[compressionName]; - if (!compressionFn) { - throw new Error(`${compressionName} compression not supported`); - } - - this.compressed = compressionFn(this.packets.write(), this.deflateLevel); - } - } - - ////////////////////////// - // // - // Helper functions // - // // - ////////////////////////// - - - const nodeZlib = util.getNodeZlib(); - - function uncompressed(data) { - return data; - } - - function node_zlib(func, create, options = {}) { - return function (data) { - if (!util.isStream(data) || isArrayStream(data)) { - return fromAsync(() => readToEnd(data).then(data => { - return new Promise((resolve, reject) => { - func(data, options, (err, result) => { - if (err) return reject(err); - resolve(result); - }); - }); - })); - } - return nodeToWeb(webToNode(data).pipe(create(options))); - }; - } - - function pako_zlib(constructor, options = {}) { - return function(data) { - const obj = new constructor(options); - return transform(data, value => { - if (value.length) { - obj.push(value, Z_SYNC_FLUSH); - return obj.result; - } - }, () => { - if (constructor === Deflate) { - obj.push([], Z_FINISH); - return obj.result; - } - }); - }; - } - - function bzip2(func) { - return function(data) { - return fromAsync(async () => func(await readToEnd(data))); - }; - } - - const compress_fns = nodeZlib ? { - zip: /*#__PURE__*/ (compressed, level) => node_zlib(nodeZlib.deflateRaw, nodeZlib.createDeflateRaw, { level })(compressed), - zlib: /*#__PURE__*/ (compressed, level) => node_zlib(nodeZlib.deflate, nodeZlib.createDeflate, { level })(compressed) - } : { - zip: /*#__PURE__*/ (compressed, level) => pako_zlib(Deflate, { raw: true, level })(compressed), - zlib: /*#__PURE__*/ (compressed, level) => pako_zlib(Deflate, { level })(compressed) - }; - - const decompress_fns = nodeZlib ? { - uncompressed: uncompressed, - zip: /*#__PURE__*/ node_zlib(nodeZlib.inflateRaw, nodeZlib.createInflateRaw), - zlib: /*#__PURE__*/ node_zlib(nodeZlib.inflate, nodeZlib.createInflate), - bzip2: /*#__PURE__*/ bzip2(lib_4) - } : { - uncompressed: uncompressed, - zip: /*#__PURE__*/ pako_zlib(Inflate, { raw: true }), - zlib: /*#__PURE__*/ pako_zlib(Inflate), - bzip2: /*#__PURE__*/ bzip2(lib_4) - }; - - // GPG4Browsers - An OpenPGP implementation in javascript - - // A SEIP packet can contain the following packet types - const allowedPackets$1 = /*#__PURE__*/ util.constructAllowedPackets([ - LiteralDataPacket, - CompressedDataPacket, - OnePassSignaturePacket, - SignaturePacket - ]); - - const VERSION$1 = 1; // A one-octet version number of the data packet. - - /** - * Implementation of the Sym. Encrypted Integrity Protected Data Packet (Tag 18) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.13|RFC4880 5.13}: - * The Symmetrically Encrypted Integrity Protected Data packet is - * a variant of the Symmetrically Encrypted Data packet. It is a new feature - * created for OpenPGP that addresses the problem of detecting a modification to - * encrypted data. It is used in combination with a Modification Detection Code - * packet. - */ - class SymEncryptedIntegrityProtectedDataPacket { - static get tag() { - return enums.packet.symEncryptedIntegrityProtectedData; - } - - constructor() { - this.version = VERSION$1; - this.encrypted = null; - this.packets = null; - } - - async read(bytes) { - await parse(bytes, async reader => { - const version = await reader.readByte(); - // - A one-octet version number. The only currently defined value is 1. - if (version !== VERSION$1) { - throw new UnsupportedError(`Version ${version} of the SEIP packet is unsupported.`); - } - - // - Encrypted data, the output of the selected symmetric-key cipher - // operating in Cipher Feedback mode with shift amount equal to the - // block size of the cipher (CFB-n where n is the block size). - this.encrypted = reader.remainder(); - }); - } - - write() { - return util.concat([new Uint8Array([VERSION$1]), this.encrypted]); - } - - /** - * Encrypt the payload in the packet. - * @param {enums.symmetric} sessionKeyAlgorithm - The symmetric encryption algorithm to use - * @param {Uint8Array} key - The key of cipher blocksize length to be used - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} - * @throws {Error} on encryption failure - * @async - */ - async encrypt(sessionKeyAlgorithm, key, config = defaultConfig) { - const { blockSize } = mod.getCipher(sessionKeyAlgorithm); - - let bytes = this.packets.write(); - if (isArrayStream(bytes)) bytes = await readToEnd(bytes); - const prefix = await mod.getPrefixRandom(sessionKeyAlgorithm); - const mdc = new Uint8Array([0xD3, 0x14]); // modification detection code packet - - const tohash = util.concat([prefix, bytes, mdc]); - const hash = await mod.hash.sha1(passiveClone(tohash)); - const plaintext = util.concat([tohash, hash]); - - this.encrypted = await mod.mode.cfb.encrypt(sessionKeyAlgorithm, key, plaintext, new Uint8Array(blockSize), config); - return true; - } - - /** - * Decrypts the encrypted data contained in the packet. - * @param {enums.symmetric} sessionKeyAlgorithm - The selected symmetric encryption algorithm to be used - * @param {Uint8Array} key - The key of cipher blocksize length to be used - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} - * @throws {Error} on decryption failure - * @async - */ - async decrypt(sessionKeyAlgorithm, key, config = defaultConfig) { - const { blockSize } = mod.getCipher(sessionKeyAlgorithm); - let encrypted = clone(this.encrypted); - if (isArrayStream(encrypted)) encrypted = await readToEnd(encrypted); - const decrypted = await mod.mode.cfb.decrypt(sessionKeyAlgorithm, key, encrypted, new Uint8Array(blockSize)); - - // there must be a modification detection code packet as the - // last packet and everything gets hashed except the hash itself - const realHash = slice(passiveClone(decrypted), -20); - const tohash = slice(decrypted, 0, -20); - const verifyHash = Promise.all([ - readToEnd(await mod.hash.sha1(passiveClone(tohash))), - readToEnd(realHash) - ]).then(([hash, mdc]) => { - if (!util.equalsUint8Array(hash, mdc)) { - throw new Error('Modification detected.'); - } - return new Uint8Array(); - }); - const bytes = slice(tohash, blockSize + 2); // Remove random prefix - let packetbytes = slice(bytes, 0, -2); // Remove MDC packet - packetbytes = concat([packetbytes, fromAsync(() => verifyHash)]); - if (!util.isStream(encrypted) || !config.allowUnauthenticatedStream) { - packetbytes = await readToEnd(packetbytes); - } - this.packets = await PacketList.fromBinary(packetbytes, allowedPackets$1, config); - return true; - } - } - - // OpenPGP.js - An OpenPGP implementation in javascript - - // An AEAD-encrypted Data packet can contain the following packet types - const allowedPackets$2 = /*#__PURE__*/ util.constructAllowedPackets([ - LiteralDataPacket, - CompressedDataPacket, - OnePassSignaturePacket, - SignaturePacket - ]); - - const VERSION$2 = 1; // A one-octet version number of the data packet. - - /** - * Implementation of the Symmetrically Encrypted Authenticated Encryption with - * Additional Data (AEAD) Protected Data Packet - * - * {@link https://tools.ietf.org/html/draft-ford-openpgp-format-00#section-2.1}: - * AEAD Protected Data Packet - */ - class AEADEncryptedDataPacket { - static get tag() { - return enums.packet.aeadEncryptedData; - } - - constructor() { - this.version = VERSION$2; - /** @type {enums.symmetric} */ - this.cipherAlgorithm = null; - /** @type {enums.aead} */ - this.aeadAlgorithm = enums.aead.eax; - this.chunkSizeByte = null; - this.iv = null; - this.encrypted = null; - this.packets = null; - } - - /** - * Parse an encrypted payload of bytes in the order: version, IV, ciphertext (see specification) - * @param {Uint8Array | ReadableStream} bytes - * @throws {Error} on parsing failure - */ - async read(bytes) { - await parse(bytes, async reader => { - const version = await reader.readByte(); - if (version !== VERSION$2) { // The only currently defined value is 1. - throw new UnsupportedError(`Version ${version} of the AEAD-encrypted data packet is not supported.`); - } - this.cipherAlgorithm = await reader.readByte(); - this.aeadAlgorithm = await reader.readByte(); - this.chunkSizeByte = await reader.readByte(); - - const mode = mod.getAEADMode(this.aeadAlgorithm); - this.iv = await reader.readBytes(mode.ivLength); - this.encrypted = reader.remainder(); - }); - } - - /** - * Write the encrypted payload of bytes in the order: version, IV, ciphertext (see specification) - * @returns {Uint8Array | ReadableStream} The encrypted payload. - */ - write() { - return util.concat([new Uint8Array([this.version, this.cipherAlgorithm, this.aeadAlgorithm, this.chunkSizeByte]), this.iv, this.encrypted]); - } - - /** - * Decrypt the encrypted payload. - * @param {enums.symmetric} sessionKeyAlgorithm - The session key's cipher algorithm - * @param {Uint8Array} key - The session key used to encrypt the payload - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if decryption was not successful - * @async - */ - async decrypt(sessionKeyAlgorithm, key, config = defaultConfig) { - this.packets = await PacketList.fromBinary( - await this.crypt('decrypt', key, clone(this.encrypted)), - allowedPackets$2, - config - ); - } - - /** - * Encrypt the packet payload. - * @param {enums.symmetric} sessionKeyAlgorithm - The session key's cipher algorithm - * @param {Uint8Array} key - The session key used to encrypt the payload - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if encryption was not successful - * @async - */ - async encrypt(sessionKeyAlgorithm, key, config = defaultConfig) { - this.cipherAlgorithm = sessionKeyAlgorithm; - - const { ivLength } = mod.getAEADMode(this.aeadAlgorithm); - this.iv = await mod.random.getRandomBytes(ivLength); // generate new random IV - this.chunkSizeByte = config.aeadChunkSizeByte; - const data = this.packets.write(); - this.encrypted = await this.crypt('encrypt', key, data); - } - - /** - * En/decrypt the payload. - * @param {encrypt|decrypt} fn - Whether to encrypt or decrypt - * @param {Uint8Array} key - The session key used to en/decrypt the payload - * @param {Uint8Array | ReadableStream} data - The data to en/decrypt - * @returns {Promise>} - * @async - */ - async crypt(fn, key, data) { - const mode = mod.getAEADMode(this.aeadAlgorithm); - const modeInstance = await mode(this.cipherAlgorithm, key); - const tagLengthIfDecrypting = fn === 'decrypt' ? mode.tagLength : 0; - const tagLengthIfEncrypting = fn === 'encrypt' ? mode.tagLength : 0; - const chunkSize = 2 ** (this.chunkSizeByte + 6) + tagLengthIfDecrypting; // ((uint64_t)1 << (c + 6)) - const adataBuffer = new ArrayBuffer(21); - const adataArray = new Uint8Array(adataBuffer, 0, 13); - const adataTagArray = new Uint8Array(adataBuffer); - const adataView = new DataView(adataBuffer); - const chunkIndexArray = new Uint8Array(adataBuffer, 5, 8); - adataArray.set([0xC0 | AEADEncryptedDataPacket.tag, this.version, this.cipherAlgorithm, this.aeadAlgorithm, this.chunkSizeByte], 0); - let chunkIndex = 0; - let latestPromise = Promise.resolve(); - let cryptedBytes = 0; - let queuedBytes = 0; - const iv = this.iv; - return transformPair(data, async (readable, writable) => { - if (util.isStream(readable) !== 'array') { - const buffer = new TransformStream({}, { - highWaterMark: util.getHardwareConcurrency() * 2 ** (this.chunkSizeByte + 6), - size: array => array.length - }); - pipe(buffer.readable, writable); - writable = buffer.writable; - } - const reader = getReader(readable); - const writer = getWriter(writable); - try { - while (true) { - let chunk = await reader.readBytes(chunkSize + tagLengthIfDecrypting) || new Uint8Array(); - const finalChunk = chunk.subarray(chunk.length - tagLengthIfDecrypting); - chunk = chunk.subarray(0, chunk.length - tagLengthIfDecrypting); - let cryptedPromise; - let done; - if (!chunkIndex || chunk.length) { - reader.unshift(finalChunk); - cryptedPromise = modeInstance[fn](chunk, mode.getNonce(iv, chunkIndexArray), adataArray); - queuedBytes += chunk.length - tagLengthIfDecrypting + tagLengthIfEncrypting; - } else { - // After the last chunk, we either encrypt a final, empty - // data chunk to get the final authentication tag or - // validate that final authentication tag. - adataView.setInt32(13 + 4, cryptedBytes); // Should be setInt64(13, ...) - cryptedPromise = modeInstance[fn](finalChunk, mode.getNonce(iv, chunkIndexArray), adataTagArray); - queuedBytes += tagLengthIfEncrypting; - done = true; - } - cryptedBytes += chunk.length - tagLengthIfDecrypting; - // eslint-disable-next-line no-loop-func - latestPromise = latestPromise.then(() => cryptedPromise).then(async crypted => { - await writer.ready; - await writer.write(crypted); - queuedBytes -= crypted.length; - }).catch(err => writer.abort(err)); - if (done || queuedBytes > writer.desiredSize) { - await latestPromise; // Respect backpressure - } - if (!done) { - adataView.setInt32(5 + 4, ++chunkIndex); // Should be setInt64(5, ...) - } else { - await writer.close(); - break; - } - } - } catch (e) { - await writer.abort(e); - } - }); - } - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - const VERSION$3 = 3; - - /** - * Public-Key Encrypted Session Key Packets (Tag 1) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.1|RFC4880 5.1}: - * A Public-Key Encrypted Session Key packet holds the session key - * used to encrypt a message. Zero or more Public-Key Encrypted Session Key - * packets and/or Symmetric-Key Encrypted Session Key packets may precede a - * Symmetrically Encrypted Data Packet, which holds an encrypted message. The - * message is encrypted with the session key, and the session key is itself - * encrypted and stored in the Encrypted Session Key packet(s). The - * Symmetrically Encrypted Data Packet is preceded by one Public-Key Encrypted - * Session Key packet for each OpenPGP key to which the message is encrypted. - * The recipient of the message finds a session key that is encrypted to their - * public key, decrypts the session key, and then uses the session key to - * decrypt the message. - */ - class PublicKeyEncryptedSessionKeyPacket { - static get tag() { - return enums.packet.publicKeyEncryptedSessionKey; - } - - constructor() { - this.version = 3; - - this.publicKeyID = new KeyID(); - this.publicKeyAlgorithm = null; - - this.sessionKey = null; - /** - * Algorithm to encrypt the message with - * @type {enums.symmetric} - */ - this.sessionKeyAlgorithm = null; - - /** @type {Object} */ - this.encrypted = {}; - } - - /** - * Parsing function for a publickey encrypted session key packet (tag 1). - * - * @param {Uint8Array} bytes - Payload of a tag 1 packet - */ - read(bytes) { - this.version = bytes[0]; - if (this.version !== VERSION$3) { - throw new UnsupportedError(`Version ${this.version} of the PKESK packet is unsupported.`); - } - this.publicKeyID.read(bytes.subarray(1, bytes.length)); - this.publicKeyAlgorithm = bytes[9]; - this.encrypted = mod.parseEncSessionKeyParams(this.publicKeyAlgorithm, bytes.subarray(10)); - } - - /** - * Create a binary representation of a tag 1 packet - * - * @returns {Uint8Array} The Uint8Array representation. - */ - write() { - const arr = [ - new Uint8Array([this.version]), - this.publicKeyID.write(), - new Uint8Array([this.publicKeyAlgorithm]), - mod.serializeParams(this.publicKeyAlgorithm, this.encrypted) - ]; - - return util.concatUint8Array(arr); - } - - /** - * Encrypt session key packet - * @param {PublicKeyPacket} key - Public key - * @throws {Error} if encryption failed - * @async - */ - async encrypt(key) { - const data = util.concatUint8Array([ - new Uint8Array([enums.write(enums.symmetric, this.sessionKeyAlgorithm)]), - this.sessionKey, - util.writeChecksum(this.sessionKey) - ]); - const algo = enums.write(enums.publicKey, this.publicKeyAlgorithm); - this.encrypted = await mod.publicKeyEncrypt( - algo, key.publicParams, data, key.getFingerprintBytes()); - } - - /** - * Decrypts the session key (only for public key encrypted session key packets (tag 1) - * @param {SecretKeyPacket} key - decrypted private key - * @param {Object} [randomSessionKey] - Bogus session key to use in case of sensitive decryption error, or if the decrypted session key is of a different type/size. - * This is needed for constant-time processing. Expected object of the form: { sessionKey: Uint8Array, sessionKeyAlgorithm: enums.symmetric } - * @throws {Error} if decryption failed, unless `randomSessionKey` is given - * @async - */ - async decrypt(key, randomSessionKey) { - // check that session key algo matches the secret key algo - if (this.publicKeyAlgorithm !== key.algorithm) { - throw new Error('Decryption error'); - } - - const randomPayload = randomSessionKey ? util.concatUint8Array([ - new Uint8Array([randomSessionKey.sessionKeyAlgorithm]), - randomSessionKey.sessionKey, - util.writeChecksum(randomSessionKey.sessionKey) - ]) : null; - const decoded = await mod.publicKeyDecrypt(this.publicKeyAlgorithm, key.publicParams, key.privateParams, this.encrypted, key.getFingerprintBytes(), randomPayload); - const symmetricAlgoByte = decoded[0]; - const sessionKey = decoded.subarray(1, decoded.length - 2); - const checksum = decoded.subarray(decoded.length - 2); - const computedChecksum = util.writeChecksum(sessionKey); - const isValidChecksum = computedChecksum[0] === checksum[0] & computedChecksum[1] === checksum[1]; - - if (randomSessionKey) { - // We must not leak info about the validity of the decrypted checksum or cipher algo. - // The decrypted session key must be of the same algo and size as the random session key, otherwise we discard it and use the random data. - const isValidPayload = isValidChecksum & symmetricAlgoByte === randomSessionKey.sessionKeyAlgorithm & sessionKey.length === randomSessionKey.sessionKey.length; - this.sessionKeyAlgorithm = util.selectUint8(isValidPayload, symmetricAlgoByte, randomSessionKey.sessionKeyAlgorithm); - this.sessionKey = util.selectUint8Array(isValidPayload, sessionKey, randomSessionKey.sessionKey); - - } else { - const isValidPayload = isValidChecksum && enums.read(enums.symmetric, symmetricAlgoByte); - if (isValidPayload) { - this.sessionKey = sessionKey; - this.sessionKeyAlgorithm = symmetricAlgoByte; - } else { - throw new Error('Decryption error'); - } - } - } - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - class S2K { - /** - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - constructor(config = defaultConfig) { - /** - * Hash function identifier, or 0 for gnu-dummy keys - * @type {module:enums.hash | 0} - */ - this.algorithm = enums.hash.sha256; - /** - * enums.s2k identifier or 'gnu-dummy' - * @type {String} - */ - this.type = 'iterated'; - /** @type {Integer} */ - this.c = config.s2kIterationCountByte; - /** Eight bytes of salt in a binary string. - * @type {Uint8Array} - */ - this.salt = null; - } - - getCount() { - // Exponent bias, defined in RFC4880 - const expbias = 6; - - return (16 + (this.c & 15)) << ((this.c >> 4) + expbias); - } - - /** - * Parsing function for a string-to-key specifier ({@link https://tools.ietf.org/html/rfc4880#section-3.7|RFC 4880 3.7}). - * @param {Uint8Array} bytes - Payload of string-to-key specifier - * @returns {Integer} Actual length of the object. - */ - read(bytes) { - let i = 0; - this.type = enums.read(enums.s2k, bytes[i++]); - this.algorithm = bytes[i++]; - - switch (this.type) { - case 'simple': - break; - - case 'salted': - this.salt = bytes.subarray(i, i + 8); - i += 8; - break; - - case 'iterated': - this.salt = bytes.subarray(i, i + 8); - i += 8; - - // Octet 10: count, a one-octet, coded value - this.c = bytes[i++]; - break; - - case 'gnu': - if (util.uint8ArrayToString(bytes.subarray(i, i + 3)) === 'GNU') { - i += 3; // GNU - const gnuExtType = 1000 + bytes[i++]; - if (gnuExtType === 1001) { - this.type = 'gnu-dummy'; - // GnuPG extension mode 1001 -- don't write secret key at all - } else { - throw new Error('Unknown s2k gnu protection mode.'); - } - } else { - throw new Error('Unknown s2k type.'); - } - break; - - default: - throw new Error('Unknown s2k type.'); - } - - return i; - } - - /** - * Serializes s2k information - * @returns {Uint8Array} Binary representation of s2k. - */ - write() { - if (this.type === 'gnu-dummy') { - return new Uint8Array([101, 0, ...util.stringToUint8Array('GNU'), 1]); - } - const arr = [new Uint8Array([enums.write(enums.s2k, this.type), this.algorithm])]; - - switch (this.type) { - case 'simple': - break; - case 'salted': - arr.push(this.salt); - break; - case 'iterated': - arr.push(this.salt); - arr.push(new Uint8Array([this.c])); - break; - case 'gnu': - throw new Error('GNU s2k type not supported.'); - default: - throw new Error('Unknown s2k type.'); - } - - return util.concatUint8Array(arr); - } - - /** - * Produces a key using the specified passphrase and the defined - * hashAlgorithm - * @param {String} passphrase - Passphrase containing user input - * @returns {Promise} Produced key with a length corresponding to. - * hashAlgorithm hash length - * @async - */ - async produceKey(passphrase, numBytes) { - passphrase = util.encodeUTF8(passphrase); - - const arr = []; - let rlength = 0; - - let prefixlen = 0; - while (rlength < numBytes) { - let toHash; - switch (this.type) { - case 'simple': - toHash = util.concatUint8Array([new Uint8Array(prefixlen), passphrase]); - break; - case 'salted': - toHash = util.concatUint8Array([new Uint8Array(prefixlen), this.salt, passphrase]); - break; - case 'iterated': { - const data = util.concatUint8Array([this.salt, passphrase]); - let datalen = data.length; - const count = Math.max(this.getCount(), datalen); - toHash = new Uint8Array(prefixlen + count); - toHash.set(data, prefixlen); - for (let pos = prefixlen + datalen; pos < count; pos += datalen, datalen *= 2) { - toHash.copyWithin(pos, prefixlen, pos); - } - break; - } - case 'gnu': - throw new Error('GNU s2k type not supported.'); - default: - throw new Error('Unknown s2k type.'); - } - const result = await mod.hash.digest(this.algorithm, toHash); - arr.push(result); - rlength += result.length; - prefixlen++; - } - - return util.concatUint8Array(arr).subarray(0, numBytes); - } - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - /** - * Symmetric-Key Encrypted Session Key Packets (Tag 3) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.3|RFC4880 5.3}: - * The Symmetric-Key Encrypted Session Key packet holds the - * symmetric-key encryption of a session key used to encrypt a message. - * Zero or more Public-Key Encrypted Session Key packets and/or - * Symmetric-Key Encrypted Session Key packets may precede a - * Symmetrically Encrypted Data packet that holds an encrypted message. - * The message is encrypted with a session key, and the session key is - * itself encrypted and stored in the Encrypted Session Key packet or - * the Symmetric-Key Encrypted Session Key packet. - */ - class SymEncryptedSessionKeyPacket { - static get tag() { - return enums.packet.symEncryptedSessionKey; - } - - /** - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - constructor(config = defaultConfig) { - this.version = config.aeadProtect ? 5 : 4; - this.sessionKey = null; - /** - * Algorithm to encrypt the session key with - * @type {enums.symmetric} - */ - this.sessionKeyEncryptionAlgorithm = null; - /** - * Algorithm to encrypt the message with - * @type {enums.symmetric} - */ - this.sessionKeyAlgorithm = enums.symmetric.aes256; - /** - * AEAD mode to encrypt the session key with (if AEAD protection is enabled) - * @type {enums.aead} - */ - this.aeadAlgorithm = enums.write(enums.aead, config.preferredAEADAlgorithm); - this.encrypted = null; - this.s2k = null; - this.iv = null; - } - - /** - * Parsing function for a symmetric encrypted session key packet (tag 3). - * - * @param {Uint8Array} bytes - Payload of a tag 3 packet - */ - read(bytes) { - let offset = 0; - - // A one-octet version number. The only currently defined version is 4. - this.version = bytes[offset++]; - if (this.version !== 4 && this.version !== 5) { - throw new UnsupportedError(`Version ${this.version} of the SKESK packet is unsupported.`); - } - - // A one-octet number describing the symmetric algorithm used. - const algo = bytes[offset++]; - - if (this.version === 5) { - // A one-octet AEAD algorithm. - this.aeadAlgorithm = bytes[offset++]; - } - - // A string-to-key (S2K) specifier, length as defined above. - this.s2k = new S2K(); - offset += this.s2k.read(bytes.subarray(offset, bytes.length)); - - if (this.version === 5) { - const mode = mod.getAEADMode(this.aeadAlgorithm); - - // A starting initialization vector of size specified by the AEAD - // algorithm. - this.iv = bytes.subarray(offset, offset += mode.ivLength); - } - - // The encrypted session key itself, which is decrypted with the - // string-to-key object. This is optional in version 4. - if (this.version === 5 || offset < bytes.length) { - this.encrypted = bytes.subarray(offset, bytes.length); - this.sessionKeyEncryptionAlgorithm = algo; - } else { - this.sessionKeyAlgorithm = algo; - } - } - - /** - * Create a binary representation of a tag 3 packet - * - * @returns {Uint8Array} The Uint8Array representation. - */ - write() { - const algo = this.encrypted === null ? - this.sessionKeyAlgorithm : - this.sessionKeyEncryptionAlgorithm; - - let bytes; - - if (this.version === 5) { - bytes = util.concatUint8Array([new Uint8Array([this.version, algo, this.aeadAlgorithm]), this.s2k.write(), this.iv, this.encrypted]); - } else { - bytes = util.concatUint8Array([new Uint8Array([this.version, algo]), this.s2k.write()]); - - if (this.encrypted !== null) { - bytes = util.concatUint8Array([bytes, this.encrypted]); - } - } - - return bytes; - } - - /** - * Decrypts the session key with the given passphrase - * @param {String} passphrase - The passphrase in string form - * @throws {Error} if decryption was not successful - * @async - */ - async decrypt(passphrase) { - const algo = this.sessionKeyEncryptionAlgorithm !== null ? - this.sessionKeyEncryptionAlgorithm : - this.sessionKeyAlgorithm; - - const { blockSize, keySize } = mod.getCipher(algo); - const key = await this.s2k.produceKey(passphrase, keySize); - - if (this.version === 5) { - const mode = mod.getAEADMode(this.aeadAlgorithm); - const adata = new Uint8Array([0xC0 | SymEncryptedSessionKeyPacket.tag, this.version, this.sessionKeyEncryptionAlgorithm, this.aeadAlgorithm]); - const modeInstance = await mode(algo, key); - this.sessionKey = await modeInstance.decrypt(this.encrypted, this.iv, adata); - } else if (this.encrypted !== null) { - const decrypted = await mod.mode.cfb.decrypt(algo, key, this.encrypted, new Uint8Array(blockSize)); - - this.sessionKeyAlgorithm = enums.write(enums.symmetric, decrypted[0]); - this.sessionKey = decrypted.subarray(1, decrypted.length); - } else { - this.sessionKey = key; - } - } - - /** - * Encrypts the session key with the given passphrase - * @param {String} passphrase - The passphrase in string form - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if encryption was not successful - * @async - */ - async encrypt(passphrase, config = defaultConfig) { - const algo = this.sessionKeyEncryptionAlgorithm !== null ? - this.sessionKeyEncryptionAlgorithm : - this.sessionKeyAlgorithm; - - this.sessionKeyEncryptionAlgorithm = algo; - - this.s2k = new S2K(config); - this.s2k.salt = await mod.random.getRandomBytes(8); - - const { blockSize, keySize } = mod.getCipher(algo); - const encryptionKey = await this.s2k.produceKey(passphrase, keySize); - - if (this.sessionKey === null) { - this.sessionKey = await mod.generateSessionKey(this.sessionKeyAlgorithm); - } - - if (this.version === 5) { - const mode = mod.getAEADMode(this.aeadAlgorithm); - this.iv = await mod.random.getRandomBytes(mode.ivLength); // generate new random IV - const associatedData = new Uint8Array([0xC0 | SymEncryptedSessionKeyPacket.tag, this.version, this.sessionKeyEncryptionAlgorithm, this.aeadAlgorithm]); - const modeInstance = await mode(algo, encryptionKey); - this.encrypted = await modeInstance.encrypt(this.sessionKey, this.iv, associatedData); - } else { - const toEncrypt = util.concatUint8Array([ - new Uint8Array([this.sessionKeyAlgorithm]), - this.sessionKey - ]); - this.encrypted = await mod.mode.cfb.encrypt(algo, encryptionKey, toEncrypt, new Uint8Array(blockSize), config); - } - } - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - /** - * Implementation of the Key Material Packet (Tag 5,6,7,14) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.5|RFC4480 5.5}: - * A key material packet contains all the information about a public or - * private key. There are four variants of this packet type, and two - * major versions. - * - * A Public-Key packet starts a series of packets that forms an OpenPGP - * key (sometimes called an OpenPGP certificate). - */ - class PublicKeyPacket { - static get tag() { - return enums.packet.publicKey; - } - - /** - * @param {Date} [date] - Creation date - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - constructor(date = new Date(), config = defaultConfig) { - /** - * Packet version - * @type {Integer} - */ - this.version = config.v5Keys ? 5 : 4; - /** - * Key creation date. - * @type {Date} - */ - this.created = util.normalizeDate(date); - /** - * Public key algorithm. - * @type {enums.publicKey} - */ - this.algorithm = null; - /** - * Algorithm specific public params - * @type {Object} - */ - this.publicParams = null; - /** - * Time until expiration in days (V3 only) - * @type {Integer} - */ - this.expirationTimeV3 = 0; - /** - * Fingerprint bytes - * @type {Uint8Array} - */ - this.fingerprint = null; - /** - * KeyID - * @type {module:type/keyid~KeyID} - */ - this.keyID = null; - } - - /** - * Create a PublicKeyPacket from a SecretKeyPacket - * @param {SecretKeyPacket} secretKeyPacket - key packet to convert - * @returns {PublicKeyPacket} public key packet - * @static - */ - static fromSecretKeyPacket(secretKeyPacket) { - const keyPacket = new PublicKeyPacket(); - const { version, created, algorithm, publicParams, keyID, fingerprint } = secretKeyPacket; - keyPacket.version = version; - keyPacket.created = created; - keyPacket.algorithm = algorithm; - keyPacket.publicParams = publicParams; - keyPacket.keyID = keyID; - keyPacket.fingerprint = fingerprint; - return keyPacket; - } - - /** - * Internal Parser for public keys as specified in {@link https://tools.ietf.org/html/rfc4880#section-5.5.2|RFC 4880 section 5.5.2 Public-Key Packet Formats} - * @param {Uint8Array} bytes - Input array to read the packet from - * @returns {Object} This object with attributes set by the parser - * @async - */ - async read(bytes) { - let pos = 0; - // A one-octet version number (3, 4 or 5). - this.version = bytes[pos++]; - - if (this.version === 4 || this.version === 5) { - // - A four-octet number denoting the time that the key was created. - this.created = util.readDate(bytes.subarray(pos, pos + 4)); - pos += 4; - - // - A one-octet number denoting the public-key algorithm of this key. - this.algorithm = bytes[pos++]; - - if (this.version === 5) { - // - A four-octet scalar octet count for the following key material. - pos += 4; - } - - // - A series of values comprising the key material. - try { - const { read, publicParams } = mod.parsePublicKeyParams(this.algorithm, bytes.subarray(pos)); - this.publicParams = publicParams; - pos += read; - } catch (err) { - throw new Error('Error reading MPIs'); - } - - // we set the fingerprint and keyID already to make it possible to put together the key packets directly in the Key constructor - await this.computeFingerprintAndKeyID(); - return pos; - } - throw new UnsupportedError(`Version ${this.version} of the key packet is unsupported.`); - } - - /** - * Creates an OpenPGP public key packet for the given key. - * @returns {Uint8Array} Bytes encoding the public key OpenPGP packet. - */ - write() { - const arr = []; - // Version - arr.push(new Uint8Array([this.version])); - arr.push(util.writeDate(this.created)); - // A one-octet number denoting the public-key algorithm of this key - arr.push(new Uint8Array([this.algorithm])); - - const params = mod.serializeParams(this.algorithm, this.publicParams); - if (this.version === 5) { - // A four-octet scalar octet count for the following key material - arr.push(util.writeNumber(params.length, 4)); - } - // Algorithm-specific params - arr.push(params); - return util.concatUint8Array(arr); - } - - /** - * Write packet in order to be hashed; either for a signature or a fingerprint - * @param {Integer} version - target version of signature or key - */ - writeForHash(version) { - const bytes = this.writePublicKey(); - - if (version === 5) { - return util.concatUint8Array([new Uint8Array([0x9A]), util.writeNumber(bytes.length, 4), bytes]); - } - return util.concatUint8Array([new Uint8Array([0x99]), util.writeNumber(bytes.length, 2), bytes]); - } - - /** - * Check whether secret-key data is available in decrypted form. Returns null for public keys. - * @returns {Boolean|null} - */ - isDecrypted() { - return null; - } - - /** - * Returns the creation time of the key - * @returns {Date} - */ - getCreationTime() { - return this.created; - } - - /** - * Return the key ID of the key - * @returns {module:type/keyid~KeyID} The 8-byte key ID - */ - getKeyID() { - return this.keyID; - } - - /** - * Computes and set the key ID and fingerprint of the key - * @async - */ - async computeFingerprintAndKeyID() { - await this.computeFingerprint(); - this.keyID = new KeyID(); - - if (this.version === 5) { - this.keyID.read(this.fingerprint.subarray(0, 8)); - } else if (this.version === 4) { - this.keyID.read(this.fingerprint.subarray(12, 20)); - } else { - throw new Error('Unsupported key version'); - } - } - - /** - * Computes and set the fingerprint of the key - */ - async computeFingerprint() { - const toHash = this.writeForHash(this.version); - - if (this.version === 5) { - this.fingerprint = await mod.hash.sha256(toHash); - } else if (this.version === 4) { - this.fingerprint = await mod.hash.sha1(toHash); - } else { - throw new Error('Unsupported key version'); - } - } - - /** - * Returns the fingerprint of the key, as an array of bytes - * @returns {Uint8Array} A Uint8Array containing the fingerprint - */ - getFingerprintBytes() { - return this.fingerprint; - } - - /** - * Calculates and returns the fingerprint of the key, as a string - * @returns {String} A string containing the fingerprint in lowercase hex - */ - getFingerprint() { - return util.uint8ArrayToHex(this.getFingerprintBytes()); - } - - /** - * Calculates whether two keys have the same fingerprint without actually calculating the fingerprint - * @returns {Boolean} Whether the two keys have the same version and public key data. - */ - hasSameFingerprintAs(other) { - return this.version === other.version && util.equalsUint8Array(this.writePublicKey(), other.writePublicKey()); - } - - /** - * Returns algorithm information - * @returns {Object} An object of the form {algorithm: String, bits:int, curve:String}. - */ - getAlgorithmInfo() { - const result = {}; - result.algorithm = enums.read(enums.publicKey, this.algorithm); - // RSA, DSA or ElGamal public modulo - const modulo = this.publicParams.n || this.publicParams.p; - if (modulo) { - result.bits = util.uint8ArrayBitLength(modulo); - } else { - result.curve = this.publicParams.oid.getName(); - } - return result; - } - } - - /** - * Alias of read() - * @see PublicKeyPacket#read - */ - PublicKeyPacket.prototype.readPublicKey = PublicKeyPacket.prototype.read; - - /** - * Alias of write() - * @see PublicKeyPacket#write - */ - PublicKeyPacket.prototype.writePublicKey = PublicKeyPacket.prototype.write; - - // GPG4Browsers - An OpenPGP implementation in javascript - - // A SE packet can contain the following packet types - const allowedPackets$3 = /*#__PURE__*/ util.constructAllowedPackets([ - LiteralDataPacket, - CompressedDataPacket, - OnePassSignaturePacket, - SignaturePacket - ]); - - /** - * Implementation of the Symmetrically Encrypted Data Packet (Tag 9) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.7|RFC4880 5.7}: - * The Symmetrically Encrypted Data packet contains data encrypted with a - * symmetric-key algorithm. When it has been decrypted, it contains other - * packets (usually a literal data packet or compressed data packet, but in - * theory other Symmetrically Encrypted Data packets or sequences of packets - * that form whole OpenPGP messages). - */ - class SymmetricallyEncryptedDataPacket { - static get tag() { - return enums.packet.symmetricallyEncryptedData; - } - - constructor() { - /** - * Encrypted secret-key data - */ - this.encrypted = null; - /** - * Decrypted packets contained within. - * @type {PacketList} - */ - this.packets = null; - } - - read(bytes) { - this.encrypted = bytes; - } - - write() { - return this.encrypted; - } - - /** - * Decrypt the symmetrically-encrypted packet data - * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. - * @param {module:enums.symmetric} sessionKeyAlgorithm - Symmetric key algorithm to use - * @param {Uint8Array} key - The key of cipher blocksize length to be used - * @param {Object} [config] - Full configuration, defaults to openpgp.config - - * @throws {Error} if decryption was not successful - * @async - */ - async decrypt(sessionKeyAlgorithm, key, config = defaultConfig) { - // If MDC errors are not being ignored, all missing MDC packets in symmetrically encrypted data should throw an error - if (!config.allowUnauthenticatedMessages) { - throw new Error('Message is not authenticated.'); - } - - const { blockSize } = mod.getCipher(sessionKeyAlgorithm); - const encrypted = await readToEnd(clone(this.encrypted)); - const decrypted = await mod.mode.cfb.decrypt(sessionKeyAlgorithm, key, - encrypted.subarray(blockSize + 2), - encrypted.subarray(2, blockSize + 2) - ); - - this.packets = await PacketList.fromBinary(decrypted, allowedPackets$3, config); - } - - /** - * Encrypt the symmetrically-encrypted packet data - * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. - * @param {module:enums.symmetric} sessionKeyAlgorithm - Symmetric key algorithm to use - * @param {Uint8Array} key - The key of cipher blocksize length to be used - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if encryption was not successful - * @async - */ - async encrypt(sessionKeyAlgorithm, key, config = defaultConfig) { - const data = this.packets.write(); - const { blockSize } = mod.getCipher(sessionKeyAlgorithm); - - const prefix = await mod.getPrefixRandom(sessionKeyAlgorithm); - const FRE = await mod.mode.cfb.encrypt(sessionKeyAlgorithm, key, prefix, new Uint8Array(blockSize), config); - const ciphertext = await mod.mode.cfb.encrypt(sessionKeyAlgorithm, key, data, FRE.subarray(2), config); - this.encrypted = util.concat([FRE, ciphertext]); - } - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - /** - * Implementation of the strange "Marker packet" (Tag 10) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.8|RFC4880 5.8}: - * An experimental version of PGP used this packet as the Literal - * packet, but no released version of PGP generated Literal packets with this - * tag. With PGP 5.x, this packet has been reassigned and is reserved for use as - * the Marker packet. - * - * The body of this packet consists of: - * The three octets 0x50, 0x47, 0x50 (which spell "PGP" in UTF-8). - * - * Such a packet MUST be ignored when received. It may be placed at the - * beginning of a message that uses features not available in PGP - * version 2.6 in order to cause that version to report that newer - * software is necessary to process the message. - */ - class MarkerPacket { - static get tag() { - return enums.packet.marker; - } - - /** - * Parsing function for a marker data packet (tag 10). - * @param {Uint8Array} bytes - Payload of a tag 10 packet - * @returns {Boolean} whether the packet payload contains "PGP" - */ - read(bytes) { - if (bytes[0] === 0x50 && // P - bytes[1] === 0x47 && // G - bytes[2] === 0x50) { // P - return true; - } - return false; - } - - write() { - return new Uint8Array([0x50, 0x47, 0x50]); - } - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - /** - * A Public-Subkey packet (tag 14) has exactly the same format as a - * Public-Key packet, but denotes a subkey. One or more subkeys may be - * associated with a top-level key. By convention, the top-level key - * provides signature services, and the subkeys provide encryption - * services. - * @extends PublicKeyPacket - */ - class PublicSubkeyPacket extends PublicKeyPacket { - static get tag() { - return enums.packet.publicSubkey; - } - - /** - * @param {Date} [date] - Creation date - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - // eslint-disable-next-line no-useless-constructor - constructor(date, config) { - super(date, config); - } - - /** - * Create a PublicSubkeyPacket from a SecretSubkeyPacket - * @param {SecretSubkeyPacket} secretSubkeyPacket - subkey packet to convert - * @returns {SecretSubkeyPacket} public key packet - * @static - */ - static fromSecretSubkeyPacket(secretSubkeyPacket) { - const keyPacket = new PublicSubkeyPacket(); - const { version, created, algorithm, publicParams, keyID, fingerprint } = secretSubkeyPacket; - keyPacket.version = version; - keyPacket.created = created; - keyPacket.algorithm = algorithm; - keyPacket.publicParams = publicParams; - keyPacket.keyID = keyID; - keyPacket.fingerprint = fingerprint; - return keyPacket; - } - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - /** - * Implementation of the User Attribute Packet (Tag 17) - * - * The User Attribute packet is a variation of the User ID packet. It - * is capable of storing more types of data than the User ID packet, - * which is limited to text. Like the User ID packet, a User Attribute - * packet may be certified by the key owner ("self-signed") or any other - * key owner who cares to certify it. Except as noted, a User Attribute - * packet may be used anywhere that a User ID packet may be used. - * - * While User Attribute packets are not a required part of the OpenPGP - * standard, implementations SHOULD provide at least enough - * compatibility to properly handle a certification signature on the - * User Attribute packet. A simple way to do this is by treating the - * User Attribute packet as a User ID packet with opaque contents, but - * an implementation may use any method desired. - */ - class UserAttributePacket { - static get tag() { - return enums.packet.userAttribute; - } - - constructor() { - this.attributes = []; - } - - /** - * parsing function for a user attribute packet (tag 17). - * @param {Uint8Array} input - Payload of a tag 17 packet - */ - read(bytes) { - let i = 0; - while (i < bytes.length) { - const len = readSimpleLength(bytes.subarray(i, bytes.length)); - i += len.offset; - - this.attributes.push(util.uint8ArrayToString(bytes.subarray(i, i + len.len))); - i += len.len; - } - } - - /** - * Creates a binary representation of the user attribute packet - * @returns {Uint8Array} String representation. - */ - write() { - const arr = []; - for (let i = 0; i < this.attributes.length; i++) { - arr.push(writeSimpleLength(this.attributes[i].length)); - arr.push(util.stringToUint8Array(this.attributes[i])); - } - return util.concatUint8Array(arr); - } - - /** - * Compare for equality - * @param {UserAttributePacket} usrAttr - * @returns {Boolean} True if equal. - */ - equals(usrAttr) { - if (!usrAttr || !(usrAttr instanceof UserAttributePacket)) { - return false; - } - return this.attributes.every(function(attr, index) { - return attr === usrAttr.attributes[index]; - }); - } - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - /** - * A Secret-Key packet contains all the information that is found in a - * Public-Key packet, including the public-key material, but also - * includes the secret-key material after all the public-key fields. - * @extends PublicKeyPacket - */ - class SecretKeyPacket extends PublicKeyPacket { - static get tag() { - return enums.packet.secretKey; - } - - /** - * @param {Date} [date] - Creation date - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - constructor(date = new Date(), config = defaultConfig) { - super(date, config); - /** - * Secret-key data - */ - this.keyMaterial = null; - /** - * Indicates whether secret-key data is encrypted. `this.isEncrypted === false` means data is available in decrypted form. - */ - this.isEncrypted = null; - /** - * S2K usage - * @type {enums.symmetric} - */ - this.s2kUsage = 0; - /** - * S2K object - * @type {type/s2k} - */ - this.s2k = null; - /** - * Symmetric algorithm to encrypt the key with - * @type {enums.symmetric} - */ - this.symmetric = null; - /** - * AEAD algorithm to encrypt the key with (if AEAD protection is enabled) - * @type {enums.aead} - */ - this.aead = null; - /** - * Decrypted private parameters, referenced by name - * @type {Object} - */ - this.privateParams = null; - } - - // 5.5.3. Secret-Key Packet Formats - - /** - * Internal parser for private keys as specified in - * {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.5.3|RFC4880bis-04 section 5.5.3} - * @param {Uint8Array} bytes - Input string to read the packet from - * @async - */ - async read(bytes) { - // - A Public-Key or Public-Subkey packet, as described above. - let i = await this.readPublicKey(bytes); - - // - One octet indicating string-to-key usage conventions. Zero - // indicates that the secret-key data is not encrypted. 255 or 254 - // indicates that a string-to-key specifier is being given. Any - // other value is a symmetric-key encryption algorithm identifier. - this.s2kUsage = bytes[i++]; - - // - Only for a version 5 packet, a one-octet scalar octet count of - // the next 4 optional fields. - if (this.version === 5) { - i++; - } - - // - [Optional] If string-to-key usage octet was 255, 254, or 253, a - // one-octet symmetric encryption algorithm. - if (this.s2kUsage === 255 || this.s2kUsage === 254 || this.s2kUsage === 253) { - this.symmetric = bytes[i++]; - - // - [Optional] If string-to-key usage octet was 253, a one-octet - // AEAD algorithm. - if (this.s2kUsage === 253) { - this.aead = bytes[i++]; - } - - // - [Optional] If string-to-key usage octet was 255, 254, or 253, a - // string-to-key specifier. The length of the string-to-key - // specifier is implied by its type, as described above. - this.s2k = new S2K(); - i += this.s2k.read(bytes.subarray(i, bytes.length)); - - if (this.s2k.type === 'gnu-dummy') { - return; - } - } else if (this.s2kUsage) { - this.symmetric = this.s2kUsage; - } - - // - [Optional] If secret data is encrypted (string-to-key usage octet - // not zero), an Initial Vector (IV) of the same length as the - // cipher's block size. - if (this.s2kUsage) { - this.iv = bytes.subarray( - i, - i + mod.getCipher(this.symmetric).blockSize - ); - - i += this.iv.length; - } - - // - Only for a version 5 packet, a four-octet scalar octet count for - // the following key material. - if (this.version === 5) { - i += 4; - } - - // - Plain or encrypted multiprecision integers comprising the secret - // key data. These algorithm-specific fields are as described - // below. - this.keyMaterial = bytes.subarray(i); - this.isEncrypted = !!this.s2kUsage; - - if (!this.isEncrypted) { - const cleartext = this.keyMaterial.subarray(0, -2); - if (!util.equalsUint8Array(util.writeChecksum(cleartext), this.keyMaterial.subarray(-2))) { - throw new Error('Key checksum mismatch'); - } - try { - const { privateParams } = mod.parsePrivateKeyParams(this.algorithm, cleartext, this.publicParams); - this.privateParams = privateParams; - } catch (err) { - throw new Error('Error reading MPIs'); - } - } - } - - /** - * Creates an OpenPGP key packet for the given key. - * @returns {Uint8Array} A string of bytes containing the secret key OpenPGP packet. - */ - write() { - const arr = [this.writePublicKey()]; - - arr.push(new Uint8Array([this.s2kUsage])); - - const optionalFieldsArr = []; - // - [Optional] If string-to-key usage octet was 255, 254, or 253, a - // one- octet symmetric encryption algorithm. - if (this.s2kUsage === 255 || this.s2kUsage === 254 || this.s2kUsage === 253) { - optionalFieldsArr.push(this.symmetric); - - // - [Optional] If string-to-key usage octet was 253, a one-octet - // AEAD algorithm. - if (this.s2kUsage === 253) { - optionalFieldsArr.push(this.aead); - } - - // - [Optional] If string-to-key usage octet was 255, 254, or 253, a - // string-to-key specifier. The length of the string-to-key - // specifier is implied by its type, as described above. - optionalFieldsArr.push(...this.s2k.write()); - } - - // - [Optional] If secret data is encrypted (string-to-key usage octet - // not zero), an Initial Vector (IV) of the same length as the - // cipher's block size. - if (this.s2kUsage && this.s2k.type !== 'gnu-dummy') { - optionalFieldsArr.push(...this.iv); - } - - if (this.version === 5) { - arr.push(new Uint8Array([optionalFieldsArr.length])); - } - arr.push(new Uint8Array(optionalFieldsArr)); - - if (!this.isDummy()) { - if (!this.s2kUsage) { - this.keyMaterial = mod.serializeParams(this.algorithm, this.privateParams); - } - - if (this.version === 5) { - arr.push(util.writeNumber(this.keyMaterial.length, 4)); - } - arr.push(this.keyMaterial); - - if (!this.s2kUsage) { - arr.push(util.writeChecksum(this.keyMaterial)); - } - } - - return util.concatUint8Array(arr); - } - - /** - * Check whether secret-key data is available in decrypted form. - * Returns false for gnu-dummy keys and null for public keys. - * @returns {Boolean|null} - */ - isDecrypted() { - return this.isEncrypted === false; - } - - /** - * Check whether this is a gnu-dummy key - * @returns {Boolean} - */ - isDummy() { - return !!(this.s2k && this.s2k.type === 'gnu-dummy'); - } - - /** - * Remove private key material, converting the key to a dummy one. - * The resulting key cannot be used for signing/decrypting but can still verify signatures. - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - makeDummy(config = defaultConfig) { - if (this.isDummy()) { - return; - } - if (this.isDecrypted()) { - this.clearPrivateParams(); - } - this.isEncrypted = null; - this.keyMaterial = null; - this.s2k = new S2K(config); - this.s2k.algorithm = 0; - this.s2k.c = 0; - this.s2k.type = 'gnu-dummy'; - this.s2kUsage = 254; - this.symmetric = enums.symmetric.aes256; - } - - /** - * Encrypt the payload. By default, we use aes256 and iterated, salted string - * to key specifier. If the key is in a decrypted state (isEncrypted === false) - * and the passphrase is empty or undefined, the key will be set as not encrypted. - * This can be used to remove passphrase protection after calling decrypt(). - * @param {String} passphrase - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if encryption was not successful - * @async - */ - async encrypt(passphrase, config = defaultConfig) { - if (this.isDummy()) { - return; - } - - if (!this.isDecrypted()) { - throw new Error('Key packet is already encrypted'); - } - - if (this.isDecrypted() && !passphrase) { - this.s2kUsage = 0; - return; - } else if (!passphrase) { - throw new Error('The key must be decrypted before removing passphrase protection.'); - } - - this.s2k = new S2K(config); - this.s2k.salt = await mod.random.getRandomBytes(8); - const cleartext = mod.serializeParams(this.algorithm, this.privateParams); - this.symmetric = enums.symmetric.aes256; - const key = await produceEncryptionKey(this.s2k, passphrase, this.symmetric); - - const { blockSize } = mod.getCipher(this.symmetric); - this.iv = await mod.random.getRandomBytes(blockSize); - - if (config.aeadProtect) { - this.s2kUsage = 253; - this.aead = enums.aead.eax; - const mode = mod.getAEADMode(this.aead); - const modeInstance = await mode(this.symmetric, key); - this.keyMaterial = await modeInstance.encrypt(cleartext, this.iv.subarray(0, mode.ivLength), new Uint8Array()); - } else { - this.s2kUsage = 254; - this.keyMaterial = await mod.mode.cfb.encrypt(this.symmetric, key, util.concatUint8Array([ - cleartext, - await mod.hash.sha1(cleartext, config) - ]), this.iv, config); - } - } - - /** - * Decrypts the private key params which are needed to use the key. - * Successful decryption does not imply key integrity, call validate() to confirm that. - * {@link SecretKeyPacket.isDecrypted} should be false, as - * otherwise calls to this function will throw an error. - * @param {String} passphrase - The passphrase for this private key as string - * @throws {Error} if the key is already decrypted, or if decryption was not successful - * @async - */ - async decrypt(passphrase) { - if (this.isDummy()) { - return false; - } - - if (this.isDecrypted()) { - throw new Error('Key packet is already decrypted.'); - } - - let key; - if (this.s2kUsage === 254 || this.s2kUsage === 253) { - key = await produceEncryptionKey(this.s2k, passphrase, this.symmetric); - } else if (this.s2kUsage === 255) { - throw new Error('Encrypted private key is authenticated using an insecure two-byte hash'); - } else { - throw new Error('Private key is encrypted using an insecure S2K function: unsalted MD5'); - } - - let cleartext; - if (this.s2kUsage === 253) { - const mode = mod.getAEADMode(this.aead); - const modeInstance = await mode(this.symmetric, key); - try { - cleartext = await modeInstance.decrypt(this.keyMaterial, this.iv.subarray(0, mode.ivLength), new Uint8Array()); - } catch (err) { - if (err.message === 'Authentication tag mismatch') { - throw new Error('Incorrect key passphrase: ' + err.message); - } - throw err; - } - } else { - const cleartextWithHash = await mod.mode.cfb.decrypt(this.symmetric, key, this.keyMaterial, this.iv); - - cleartext = cleartextWithHash.subarray(0, -20); - const hash = await mod.hash.sha1(cleartext); - - if (!util.equalsUint8Array(hash, cleartextWithHash.subarray(-20))) { - throw new Error('Incorrect key passphrase'); - } - } - - try { - const { privateParams } = mod.parsePrivateKeyParams(this.algorithm, cleartext, this.publicParams); - this.privateParams = privateParams; - } catch (err) { - throw new Error('Error reading MPIs'); - } - this.isEncrypted = false; - this.keyMaterial = null; - this.s2kUsage = 0; - } - - /** - * Checks that the key parameters are consistent - * @throws {Error} if validation was not successful - * @async - */ - async validate() { - if (this.isDummy()) { - return; - } - - if (!this.isDecrypted()) { - throw new Error('Key is not decrypted'); - } - - let validParams; - try { - // this can throw if some parameters are undefined - validParams = await mod.validateParams(this.algorithm, this.publicParams, this.privateParams); - } catch (_) { - validParams = false; - } - if (!validParams) { - throw new Error('Key is invalid'); - } - } - - async generate(bits, curve) { - const { privateParams, publicParams } = await mod.generateParams(this.algorithm, bits, curve); - this.privateParams = privateParams; - this.publicParams = publicParams; - this.isEncrypted = false; - } - - /** - * Clear private key parameters - */ - clearPrivateParams() { - if (this.isDummy()) { - return; - } - - Object.keys(this.privateParams).forEach(name => { - const param = this.privateParams[name]; - param.fill(0); - delete this.privateParams[name]; - }); - this.privateParams = null; - this.isEncrypted = true; - } - } - - async function produceEncryptionKey(s2k, passphrase, algorithm) { - const { keySize } = mod.getCipher(algorithm); - return s2k.produceKey(passphrase, keySize); - } - - var emailAddresses = createCommonjsModule(function (module) { - // email-addresses.js - RFC 5322 email address parser - // v 3.1.0 - // - // http://tools.ietf.org/html/rfc5322 - // - // This library does not validate email addresses. - // emailAddresses attempts to parse addresses using the (fairly liberal) - // grammar specified in RFC 5322. - // - // email-addresses returns { - // ast: , - // addresses: [{ - // node: , - // name: , - // address: , - // local: , - // domain: - // }, ...] - // } - // - // emailAddresses.parseOneAddress and emailAddresses.parseAddressList - // work as you might expect. Try it out. - // - // Many thanks to Dominic Sayers and his documentation on the is_email function, - // http://code.google.com/p/isemail/ , which helped greatly in writing this parser. - - (function (global) { - - function parse5322(opts) { - - // tokenizing functions - - function inStr() { return pos < len; } - function curTok() { return parseString[pos]; } - function getPos() { return pos; } - function setPos(i) { pos = i; } - function nextTok() { pos += 1; } - function initialize() { - pos = 0; - len = parseString.length; - } - - // parser helper functions - - function o(name, value) { - return { - name: name, - tokens: value || "", - semantic: value || "", - children: [] - }; - } - - function wrap(name, ast) { - var n; - if (ast === null) { return null; } - n = o(name); - n.tokens = ast.tokens; - n.semantic = ast.semantic; - n.children.push(ast); - return n; - } - - function add(parent, child) { - if (child !== null) { - parent.tokens += child.tokens; - parent.semantic += child.semantic; - } - parent.children.push(child); - return parent; - } - - function compareToken(fxnCompare) { - var tok; - if (!inStr()) { return null; } - tok = curTok(); - if (fxnCompare(tok)) { - nextTok(); - return o('token', tok); - } - return null; - } - - function literal(lit) { - return function literalFunc() { - return wrap('literal', compareToken(function (tok) { - return tok === lit; - })); - }; - } - - function and() { - var args = arguments; - return function andFunc() { - var i, s, result, start; - start = getPos(); - s = o('and'); - for (i = 0; i < args.length; i += 1) { - result = args[i](); - if (result === null) { - setPos(start); - return null; - } - add(s, result); - } - return s; - }; - } - - function or() { - var args = arguments; - return function orFunc() { - var i, result, start; - start = getPos(); - for (i = 0; i < args.length; i += 1) { - result = args[i](); - if (result !== null) { - return result; - } - setPos(start); - } - return null; - }; - } - - function opt(prod) { - return function optFunc() { - var result, start; - start = getPos(); - result = prod(); - if (result !== null) { - return result; - } - else { - setPos(start); - return o('opt'); - } - }; - } - - function invis(prod) { - return function invisFunc() { - var result = prod(); - if (result !== null) { - result.semantic = ""; - } - return result; - }; - } - - function colwsp(prod) { - return function collapseSemanticWhitespace() { - var result = prod(); - if (result !== null && result.semantic.length > 0) { - result.semantic = " "; - } - return result; - }; - } - - function star(prod, minimum) { - return function starFunc() { - var s, result, count, start, min; - start = getPos(); - s = o('star'); - count = 0; - min = minimum === undefined ? 0 : minimum; - while ((result = prod()) !== null) { - count = count + 1; - add(s, result); - } - if (count >= min) { - return s; - } - else { - setPos(start); - return null; - } - }; - } - - // One expects names to get normalized like this: - // " First Last " -> "First Last" - // "First Last" -> "First Last" - // "First Last" -> "First Last" - function collapseWhitespace(s) { - return s.replace(/([ \t]|\r\n)+/g, ' ').replace(/^\s*/, '').replace(/\s*$/, ''); - } - - // UTF-8 pseudo-production (RFC 6532) - // RFC 6532 extends RFC 5322 productions to include UTF-8 - // using the following productions: - // UTF8-non-ascii = UTF8-2 / UTF8-3 / UTF8-4 - // UTF8-2 = - // UTF8-3 = - // UTF8-4 = - // - // For reference, the extended RFC 5322 productions are: - // VCHAR =/ UTF8-non-ascii - // ctext =/ UTF8-non-ascii - // atext =/ UTF8-non-ascii - // qtext =/ UTF8-non-ascii - // dtext =/ UTF8-non-ascii - function isUTF8NonAscii(tok) { - // In JavaScript, we just deal directly with Unicode code points, - // so we aren't checking individual bytes for UTF-8 encoding. - // Just check that the character is non-ascii. - return tok.charCodeAt(0) >= 128; - } - - - // common productions (RFC 5234) - // http://tools.ietf.org/html/rfc5234 - // B.1. Core Rules - - // CR = %x0D - // ; carriage return - function cr() { return wrap('cr', literal('\r')()); } - - // CRLF = CR LF - // ; Internet standard newline - function crlf() { return wrap('crlf', and(cr, lf)()); } - - // DQUOTE = %x22 - // ; " (Double Quote) - function dquote() { return wrap('dquote', literal('"')()); } - - // HTAB = %x09 - // ; horizontal tab - function htab() { return wrap('htab', literal('\t')()); } - - // LF = %x0A - // ; linefeed - function lf() { return wrap('lf', literal('\n')()); } - - // SP = %x20 - function sp() { return wrap('sp', literal(' ')()); } - - // VCHAR = %x21-7E - // ; visible (printing) characters - function vchar() { - return wrap('vchar', compareToken(function vcharFunc(tok) { - var code = tok.charCodeAt(0); - var accept = (0x21 <= code && code <= 0x7E); - if (opts.rfc6532) { - accept = accept || isUTF8NonAscii(tok); - } - return accept; - })); - } - - // WSP = SP / HTAB - // ; white space - function wsp() { return wrap('wsp', or(sp, htab)()); } - - - // email productions (RFC 5322) - // http://tools.ietf.org/html/rfc5322 - // 3.2.1. Quoted characters - - // quoted-pair = ("\" (VCHAR / WSP)) / obs-qp - function quotedPair() { - var qp = wrap('quoted-pair', - or( - and(literal('\\'), or(vchar, wsp)), - obsQP - )()); - if (qp === null) { return null; } - // a quoted pair will be two characters, and the "\" character - // should be semantically "invisible" (RFC 5322 3.2.1) - qp.semantic = qp.semantic[1]; - return qp; - } - - // 3.2.2. Folding White Space and Comments - - // FWS = ([*WSP CRLF] 1*WSP) / obs-FWS - function fws() { - return wrap('fws', or( - obsFws, - and( - opt(and( - star(wsp), - invis(crlf) - )), - star(wsp, 1) - ) - )()); - } - - // ctext = %d33-39 / ; Printable US-ASCII - // %d42-91 / ; characters not including - // %d93-126 / ; "(", ")", or "\" - // obs-ctext - function ctext() { - return wrap('ctext', or( - function ctextFunc1() { - return compareToken(function ctextFunc2(tok) { - var code = tok.charCodeAt(0); - var accept = - (33 <= code && code <= 39) || - (42 <= code && code <= 91) || - (93 <= code && code <= 126); - if (opts.rfc6532) { - accept = accept || isUTF8NonAscii(tok); - } - return accept; - }); - }, - obsCtext - )()); - } - - // ccontent = ctext / quoted-pair / comment - function ccontent() { - return wrap('ccontent', or(ctext, quotedPair, comment)()); - } - - // comment = "(" *([FWS] ccontent) [FWS] ")" - function comment() { - return wrap('comment', and( - literal('('), - star(and(opt(fws), ccontent)), - opt(fws), - literal(')') - )()); - } - - // CFWS = (1*([FWS] comment) [FWS]) / FWS - function cfws() { - return wrap('cfws', or( - and( - star( - and(opt(fws), comment), - 1 - ), - opt(fws) - ), - fws - )()); - } - - // 3.2.3. Atom - - //atext = ALPHA / DIGIT / ; Printable US-ASCII - // "!" / "#" / ; characters not including - // "$" / "%" / ; specials. Used for atoms. - // "&" / "'" / - // "*" / "+" / - // "-" / "/" / - // "=" / "?" / - // "^" / "_" / - // "`" / "{" / - // "|" / "}" / - // "~" - function atext() { - return wrap('atext', compareToken(function atextFunc(tok) { - var accept = - ('a' <= tok && tok <= 'z') || - ('A' <= tok && tok <= 'Z') || - ('0' <= tok && tok <= '9') || - (['!', '#', '$', '%', '&', '\'', '*', '+', '-', '/', - '=', '?', '^', '_', '`', '{', '|', '}', '~'].indexOf(tok) >= 0); - if (opts.rfc6532) { - accept = accept || isUTF8NonAscii(tok); - } - return accept; - })); - } - - // atom = [CFWS] 1*atext [CFWS] - function atom() { - return wrap('atom', and(colwsp(opt(cfws)), star(atext, 1), colwsp(opt(cfws)))()); - } - - // dot-atom-text = 1*atext *("." 1*atext) - function dotAtomText() { - var s, maybeText; - s = wrap('dot-atom-text', star(atext, 1)()); - if (s === null) { return s; } - maybeText = star(and(literal('.'), star(atext, 1)))(); - if (maybeText !== null) { - add(s, maybeText); - } - return s; - } - - // dot-atom = [CFWS] dot-atom-text [CFWS] - function dotAtom() { - return wrap('dot-atom', and(invis(opt(cfws)), dotAtomText, invis(opt(cfws)))()); - } - - // 3.2.4. Quoted Strings - - // qtext = %d33 / ; Printable US-ASCII - // %d35-91 / ; characters not including - // %d93-126 / ; "\" or the quote character - // obs-qtext - function qtext() { - return wrap('qtext', or( - function qtextFunc1() { - return compareToken(function qtextFunc2(tok) { - var code = tok.charCodeAt(0); - var accept = - (33 === code) || - (35 <= code && code <= 91) || - (93 <= code && code <= 126); - if (opts.rfc6532) { - accept = accept || isUTF8NonAscii(tok); - } - return accept; - }); - }, - obsQtext - )()); - } - - // qcontent = qtext / quoted-pair - function qcontent() { - return wrap('qcontent', or(qtext, quotedPair)()); - } - - // quoted-string = [CFWS] - // DQUOTE *([FWS] qcontent) [FWS] DQUOTE - // [CFWS] - function quotedString() { - return wrap('quoted-string', and( - invis(opt(cfws)), - invis(dquote), star(and(opt(colwsp(fws)), qcontent)), opt(invis(fws)), invis(dquote), - invis(opt(cfws)) - )()); - } - - // 3.2.5 Miscellaneous Tokens - - // word = atom / quoted-string - function word() { - return wrap('word', or(atom, quotedString)()); - } - - // phrase = 1*word / obs-phrase - function phrase() { - return wrap('phrase', or(obsPhrase, star(word, 1))()); - } - - // 3.4. Address Specification - // address = mailbox / group - function address() { - return wrap('address', or(mailbox, group)()); - } - - // mailbox = name-addr / addr-spec - function mailbox() { - return wrap('mailbox', or(nameAddr, addrSpec)()); - } - - // name-addr = [display-name] angle-addr - function nameAddr() { - return wrap('name-addr', and(opt(displayName), angleAddr)()); - } - - // angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / - // obs-angle-addr - function angleAddr() { - return wrap('angle-addr', or( - and( - invis(opt(cfws)), - literal('<'), - addrSpec, - literal('>'), - invis(opt(cfws)) - ), - obsAngleAddr - )()); - } - - // group = display-name ":" [group-list] ";" [CFWS] - function group() { - return wrap('group', and( - displayName, - literal(':'), - opt(groupList), - literal(';'), - invis(opt(cfws)) - )()); - } - - // display-name = phrase - function displayName() { - return wrap('display-name', function phraseFixedSemantic() { - var result = phrase(); - if (result !== null) { - result.semantic = collapseWhitespace(result.semantic); - } - return result; - }()); - } - - // mailbox-list = (mailbox *("," mailbox)) / obs-mbox-list - function mailboxList() { - return wrap('mailbox-list', or( - and( - mailbox, - star(and(literal(','), mailbox)) - ), - obsMboxList - )()); - } - - // address-list = (address *("," address)) / obs-addr-list - function addressList() { - return wrap('address-list', or( - and( - address, - star(and(literal(','), address)) - ), - obsAddrList - )()); - } - - // group-list = mailbox-list / CFWS / obs-group-list - function groupList() { - return wrap('group-list', or( - mailboxList, - invis(cfws), - obsGroupList - )()); - } - - // 3.4.1 Addr-Spec Specification - - // local-part = dot-atom / quoted-string / obs-local-part - function localPart() { - // note: quoted-string, dotAtom are proper subsets of obs-local-part - // so we really just have to look for obsLocalPart, if we don't care about the exact parse tree - return wrap('local-part', or(obsLocalPart, dotAtom, quotedString)()); - } - - // dtext = %d33-90 / ; Printable US-ASCII - // %d94-126 / ; characters not including - // obs-dtext ; "[", "]", or "\" - function dtext() { - return wrap('dtext', or( - function dtextFunc1() { - return compareToken(function dtextFunc2(tok) { - var code = tok.charCodeAt(0); - var accept = - (33 <= code && code <= 90) || - (94 <= code && code <= 126); - if (opts.rfc6532) { - accept = accept || isUTF8NonAscii(tok); - } - return accept; - }); - }, - obsDtext - )() - ); - } - - // domain-literal = [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS] - function domainLiteral() { - return wrap('domain-literal', and( - invis(opt(cfws)), - literal('['), - star(and(opt(fws), dtext)), - opt(fws), - literal(']'), - invis(opt(cfws)) - )()); - } - - // domain = dot-atom / domain-literal / obs-domain - function domain() { - return wrap('domain', function domainCheckTLD() { - var result = or(obsDomain, dotAtom, domainLiteral)(); - if (opts.rejectTLD) { - if (result && result.semantic && result.semantic.indexOf('.') < 0) { - return null; - } - } - // strip all whitespace from domains - if (result) { - result.semantic = result.semantic.replace(/\s+/g, ''); - } - return result; - }()); - } - - // addr-spec = local-part "@" domain - function addrSpec() { - return wrap('addr-spec', and( - localPart, literal('@'), domain - )()); - } - - // 3.6.2 Originator Fields - // Below we only parse the field body, not the name of the field - // like "From:", "Sender:", or "Reply-To:". Other libraries that - // parse email headers can parse those and defer to these productions - // for the "RFC 5322" part. - - // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields - // from = "From:" (mailbox-list / address-list) CRLF - function fromSpec() { - return wrap('from', or( - mailboxList, - addressList - )()); - } - - // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields - // sender = "Sender:" (mailbox / address) CRLF - function senderSpec() { - return wrap('sender', or( - mailbox, - address - )()); - } - - // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields - // reply-to = "Reply-To:" address-list CRLF - function replyToSpec() { - return wrap('reply-to', addressList()); - } - - // 4.1. Miscellaneous Obsolete Tokens - - // obs-NO-WS-CTL = %d1-8 / ; US-ASCII control - // %d11 / ; characters that do not - // %d12 / ; include the carriage - // %d14-31 / ; return, line feed, and - // %d127 ; white space characters - function obsNoWsCtl() { - return opts.strict ? null : wrap('obs-NO-WS-CTL', compareToken(function (tok) { - var code = tok.charCodeAt(0); - return ((1 <= code && code <= 8) || - (11 === code || 12 === code) || - (14 <= code && code <= 31) || - (127 === code)); - })); - } - - // obs-ctext = obs-NO-WS-CTL - function obsCtext() { return opts.strict ? null : wrap('obs-ctext', obsNoWsCtl()); } - - // obs-qtext = obs-NO-WS-CTL - function obsQtext() { return opts.strict ? null : wrap('obs-qtext', obsNoWsCtl()); } - - // obs-qp = "\" (%d0 / obs-NO-WS-CTL / LF / CR) - function obsQP() { - return opts.strict ? null : wrap('obs-qp', and( - literal('\\'), - or(literal('\0'), obsNoWsCtl, lf, cr) - )()); - } - - // obs-phrase = word *(word / "." / CFWS) - function obsPhrase() { - if (opts.strict ) return null; - return opts.atInDisplayName ? wrap('obs-phrase', and( - word, - star(or(word, literal('.'), literal('@'), colwsp(cfws))) - )()) : - wrap('obs-phrase', and( - word, - star(or(word, literal('.'), colwsp(cfws))) - )()); - } - - // 4.2. Obsolete Folding White Space - - // NOTE: read the errata http://www.rfc-editor.org/errata_search.php?rfc=5322&eid=1908 - // obs-FWS = 1*([CRLF] WSP) - function obsFws() { - return opts.strict ? null : wrap('obs-FWS', star( - and(invis(opt(crlf)), wsp), - 1 - )()); - } - - // 4.4. Obsolete Addressing - - // obs-angle-addr = [CFWS] "<" obs-route addr-spec ">" [CFWS] - function obsAngleAddr() { - return opts.strict ? null : wrap('obs-angle-addr', and( - invis(opt(cfws)), - literal('<'), - obsRoute, - addrSpec, - literal('>'), - invis(opt(cfws)) - )()); - } - - // obs-route = obs-domain-list ":" - function obsRoute() { - return opts.strict ? null : wrap('obs-route', and( - obsDomainList, - literal(':') - )()); - } - - // obs-domain-list = *(CFWS / ",") "@" domain - // *("," [CFWS] ["@" domain]) - function obsDomainList() { - return opts.strict ? null : wrap('obs-domain-list', and( - star(or(invis(cfws), literal(','))), - literal('@'), - domain, - star(and( - literal(','), - invis(opt(cfws)), - opt(and(literal('@'), domain)) - )) - )()); - } - - // obs-mbox-list = *([CFWS] ",") mailbox *("," [mailbox / CFWS]) - function obsMboxList() { - return opts.strict ? null : wrap('obs-mbox-list', and( - star(and( - invis(opt(cfws)), - literal(',') - )), - mailbox, - star(and( - literal(','), - opt(and( - mailbox, - invis(cfws) - )) - )) - )()); - } - - // obs-addr-list = *([CFWS] ",") address *("," [address / CFWS]) - function obsAddrList() { - return opts.strict ? null : wrap('obs-addr-list', and( - star(and( - invis(opt(cfws)), - literal(',') - )), - address, - star(and( - literal(','), - opt(and( - address, - invis(cfws) - )) - )) - )()); - } - - // obs-group-list = 1*([CFWS] ",") [CFWS] - function obsGroupList() { - return opts.strict ? null : wrap('obs-group-list', and( - star(and( - invis(opt(cfws)), - literal(',') - ), 1), - invis(opt(cfws)) - )()); - } - - // obs-local-part = word *("." word) - function obsLocalPart() { - return opts.strict ? null : wrap('obs-local-part', and(word, star(and(literal('.'), word)))()); - } - - // obs-domain = atom *("." atom) - function obsDomain() { - return opts.strict ? null : wrap('obs-domain', and(atom, star(and(literal('.'), atom)))()); - } - - // obs-dtext = obs-NO-WS-CTL / quoted-pair - function obsDtext() { - return opts.strict ? null : wrap('obs-dtext', or(obsNoWsCtl, quotedPair)()); - } - - ///////////////////////////////////////////////////// - - // ast analysis - - function findNode(name, root) { - var i, stack, node; - if (root === null || root === undefined) { return null; } - stack = [root]; - while (stack.length > 0) { - node = stack.pop(); - if (node.name === name) { - return node; - } - for (i = node.children.length - 1; i >= 0; i -= 1) { - stack.push(node.children[i]); - } - } - return null; - } - - function findAllNodes(name, root) { - var i, stack, node, result; - if (root === null || root === undefined) { return null; } - stack = [root]; - result = []; - while (stack.length > 0) { - node = stack.pop(); - if (node.name === name) { - result.push(node); - } - for (i = node.children.length - 1; i >= 0; i -= 1) { - stack.push(node.children[i]); - } - } - return result; - } - - function findAllNodesNoChildren(names, root) { - var i, stack, node, result, namesLookup; - if (root === null || root === undefined) { return null; } - stack = [root]; - result = []; - namesLookup = {}; - for (i = 0; i < names.length; i += 1) { - namesLookup[names[i]] = true; - } - - while (stack.length > 0) { - node = stack.pop(); - if (node.name in namesLookup) { - result.push(node); - // don't look at children (hence findAllNodesNoChildren) - } else { - for (i = node.children.length - 1; i >= 0; i -= 1) { - stack.push(node.children[i]); - } - } - } - return result; - } - - function giveResult(ast) { - var addresses, groupsAndMailboxes, i, groupOrMailbox, result; - if (ast === null) { - return null; - } - addresses = []; - - // An address is a 'group' (i.e. a list of mailboxes) or a 'mailbox'. - groupsAndMailboxes = findAllNodesNoChildren(['group', 'mailbox'], ast); - for (i = 0; i < groupsAndMailboxes.length; i += 1) { - groupOrMailbox = groupsAndMailboxes[i]; - if (groupOrMailbox.name === 'group') { - addresses.push(giveResultGroup(groupOrMailbox)); - } else if (groupOrMailbox.name === 'mailbox') { - addresses.push(giveResultMailbox(groupOrMailbox)); - } - } - - result = { - ast: ast, - addresses: addresses, - }; - if (opts.simple) { - result = simplifyResult(result); - } - if (opts.oneResult) { - return oneResult(result); - } - if (opts.simple) { - return result && result.addresses; - } else { - return result; - } - } - - function giveResultGroup(group) { - var i; - var groupName = findNode('display-name', group); - var groupResultMailboxes = []; - var mailboxes = findAllNodesNoChildren(['mailbox'], group); - for (i = 0; i < mailboxes.length; i += 1) { - groupResultMailboxes.push(giveResultMailbox(mailboxes[i])); - } - return { - node: group, - parts: { - name: groupName, - }, - type: group.name, // 'group' - name: grabSemantic(groupName), - addresses: groupResultMailboxes, - }; - } - - function giveResultMailbox(mailbox) { - var name = findNode('display-name', mailbox); - var aspec = findNode('addr-spec', mailbox); - var cfws = findAllNodes('cfws', mailbox); - var comments = findAllNodesNoChildren(['comment'], mailbox); - - - var local = findNode('local-part', aspec); - var domain = findNode('domain', aspec); - return { - node: mailbox, - parts: { - name: name, - address: aspec, - local: local, - domain: domain, - comments: cfws - }, - type: mailbox.name, // 'mailbox' - name: grabSemantic(name), - address: grabSemantic(aspec), - local: grabSemantic(local), - domain: grabSemantic(domain), - comments: concatComments(comments), - groupName: grabSemantic(mailbox.groupName), - }; - } - - function grabSemantic(n) { - return n !== null && n !== undefined ? n.semantic : null; - } - - function simplifyResult(result) { - var i; - if (result && result.addresses) { - for (i = 0; i < result.addresses.length; i += 1) { - delete result.addresses[i].node; - } - } - return result; - } - - function concatComments(comments) { - var result = ''; - if (comments) { - for (var i = 0; i < comments.length; i += 1) { - result += grabSemantic(comments[i]); - } - } - return result; - } - - function oneResult(result) { - if (!result) { return null; } - if (!opts.partial && result.addresses.length > 1) { return null; } - return result.addresses && result.addresses[0]; - } - - ///////////////////////////////////////////////////// - - var parseString, pos, len, parsed, startProduction; - - opts = handleOpts(opts, {}); - if (opts === null) { return null; } - - parseString = opts.input; - - startProduction = { - 'address': address, - 'address-list': addressList, - 'angle-addr': angleAddr, - 'from': fromSpec, - 'group': group, - 'mailbox': mailbox, - 'mailbox-list': mailboxList, - 'reply-to': replyToSpec, - 'sender': senderSpec, - }[opts.startAt] || addressList; - - if (!opts.strict) { - initialize(); - opts.strict = true; - parsed = startProduction(parseString); - if (opts.partial || !inStr()) { - return giveResult(parsed); - } - opts.strict = false; - } - - initialize(); - parsed = startProduction(parseString); - if (!opts.partial && inStr()) { return null; } - return giveResult(parsed); - } - - function parseOneAddressSimple(opts) { - return parse5322(handleOpts(opts, { - oneResult: true, - rfc6532: true, - simple: true, - startAt: 'address-list', - })); - } - - function parseAddressListSimple(opts) { - return parse5322(handleOpts(opts, { - rfc6532: true, - simple: true, - startAt: 'address-list', - })); - } - - function parseFromSimple(opts) { - return parse5322(handleOpts(opts, { - rfc6532: true, - simple: true, - startAt: 'from', - })); - } - - function parseSenderSimple(opts) { - return parse5322(handleOpts(opts, { - oneResult: true, - rfc6532: true, - simple: true, - startAt: 'sender', - })); - } - - function parseReplyToSimple(opts) { - return parse5322(handleOpts(opts, { - rfc6532: true, - simple: true, - startAt: 'reply-to', - })); - } - - function handleOpts(opts, defs) { - function isString(str) { - return Object.prototype.toString.call(str) === '[object String]'; - } - - function isObject(o) { - return o === Object(o); - } - - function isNullUndef(o) { - return o === null || o === undefined; - } - - var defaults, o; - - if (isString(opts)) { - opts = { input: opts }; - } else if (!isObject(opts)) { - return null; - } - - if (!isString(opts.input)) { return null; } - if (!defs) { return null; } - - defaults = { - oneResult: false, - partial: false, - rejectTLD: false, - rfc6532: false, - simple: false, - startAt: 'address-list', - strict: false, - atInDisplayName: false - }; - - for (o in defaults) { - if (isNullUndef(opts[o])) { - opts[o] = !isNullUndef(defs[o]) ? defs[o] : defaults[o]; - } - } - return opts; - } - - parse5322.parseOneAddress = parseOneAddressSimple; - parse5322.parseAddressList = parseAddressListSimple; - parse5322.parseFrom = parseFromSimple; - parse5322.parseSender = parseSenderSimple; - parse5322.parseReplyTo = parseReplyToSimple; - - { - module.exports = parse5322; - } - - }()); - }); - - // GPG4Browsers - An OpenPGP implementation in javascript - - /** - * Implementation of the User ID Packet (Tag 13) - * - * A User ID packet consists of UTF-8 text that is intended to represent - * the name and email address of the key holder. By convention, it - * includes an RFC 2822 [RFC2822] mail name-addr, but there are no - * restrictions on its content. The packet length in the header - * specifies the length of the User ID. - */ - class UserIDPacket { - static get tag() { - return enums.packet.userID; - } - - constructor() { - /** A string containing the user id. Usually in the form - * John Doe - * @type {String} - */ - this.userID = ''; - - this.name = ''; - this.email = ''; - this.comment = ''; - } - - /** - * Create UserIDPacket instance from object - * @param {Object} userID - Object specifying userID name, email and comment - * @returns {UserIDPacket} - * @static - */ - static fromObject(userID) { - if (util.isString(userID) || - (userID.name && !util.isString(userID.name)) || - (userID.email && !util.isEmailAddress(userID.email)) || - (userID.comment && !util.isString(userID.comment))) { - throw new Error('Invalid user ID format'); - } - const packet = new UserIDPacket(); - Object.assign(packet, userID); - const components = []; - if (packet.name) components.push(packet.name); - if (packet.comment) components.push(`(${packet.comment})`); - if (packet.email) components.push(`<${packet.email}>`); - packet.userID = components.join(' '); - return packet; - } - - /** - * Parsing function for a user id packet (tag 13). - * @param {Uint8Array} input - Payload of a tag 13 packet - */ - read(bytes, config = defaultConfig) { - const userID = util.decodeUTF8(bytes); - if (userID.length > config.maxUserIDLength) { - throw new Error('User ID string is too long'); - } - try { - const { name, address: email, comments } = emailAddresses.parseOneAddress({ input: userID, atInDisplayName: true }); - this.comment = comments.replace(/^\(|\)$/g, ''); - this.name = name; - this.email = email; - } catch (e) {} - this.userID = userID; - } - - /** - * Creates a binary representation of the user id packet - * @returns {Uint8Array} Binary representation. - */ - write() { - return util.encodeUTF8(this.userID); - } - - equals(otherUserID) { - return otherUserID && otherUserID.userID === this.userID; - } - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - /** - * A Secret-Subkey packet (tag 7) is the subkey analog of the Secret - * Key packet and has exactly the same format. - * @extends SecretKeyPacket - */ - class SecretSubkeyPacket extends SecretKeyPacket { - static get tag() { - return enums.packet.secretSubkey; - } - - /** - * @param {Date} [date] - Creation date - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - constructor(date = new Date(), config = defaultConfig) { - super(date, config); - } - } - - /** - * Implementation of the Trust Packet (Tag 12) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.10|RFC4880 5.10}: - * The Trust packet is used only within keyrings and is not normally - * exported. Trust packets contain data that record the user's - * specifications of which key holders are trustworthy introducers, - * along with other information that implementing software uses for - * trust information. The format of Trust packets is defined by a given - * implementation. - * - * Trust packets SHOULD NOT be emitted to output streams that are - * transferred to other users, and they SHOULD be ignored on any input - * other than local keyring files. - */ - class TrustPacket { - static get tag() { - return enums.packet.trust; - } - - /** - * Parsing function for a trust packet (tag 12). - * Currently not implemented as we ignore trust packets - */ - read() { - throw new UnsupportedError('Trust packets are not supported'); - } - - write() { - throw new UnsupportedError('Trust packets are not supported'); - } - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - // A Signature can contain the following packets - const allowedPackets$4 = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); - - /** - * Class that represents an OpenPGP signature. - */ - class Signature { - /** - * @param {PacketList} packetlist - The signature packets - */ - constructor(packetlist) { - this.packets = packetlist || new PacketList(); - } - - /** - * Returns binary encoded signature - * @returns {ReadableStream} Binary signature. - */ - write() { - return this.packets.write(); - } - - /** - * Returns ASCII armored text of signature - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {ReadableStream} ASCII armor. - */ - armor(config = defaultConfig) { - return armor(enums.armor.signature, this.write(), undefined, undefined, undefined, config); - } - - /** - * Returns an array of KeyIDs of all of the issuers who created this signature - * @returns {Array} The Key IDs of the signing keys - */ - getSigningKeyIDs() { - return this.packets.map(packet => packet.issuerKeyID); - } - } - - /** - * reads an (optionally armored) OpenPGP signature and returns a signature object - * @param {Object} options - * @param {String} [options.armoredSignature] - Armored signature to be parsed - * @param {Uint8Array} [options.binarySignature] - Binary signature to be parsed - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} New signature object. - * @async - * @static - */ - async function readSignature({ armoredSignature, binarySignature, config, ...rest }) { - config = { ...defaultConfig, ...config }; - let input = armoredSignature || binarySignature; - if (!input) { - throw new Error('readSignature: must pass options object containing `armoredSignature` or `binarySignature`'); - } - if (armoredSignature && !util.isString(armoredSignature)) { - throw new Error('readSignature: options.armoredSignature must be a string'); - } - if (binarySignature && !util.isUint8Array(binarySignature)) { - throw new Error('readSignature: options.binarySignature must be a Uint8Array'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (armoredSignature) { - const { type, data } = await unarmor(input, config); - if (type !== enums.armor.signature) { - throw new Error('Armored text not of type signature'); - } - input = data; - } - const packetlist = await PacketList.fromBinary(input, allowedPackets$4, config); - return new Signature(packetlist); - } - - /** - * @fileoverview Provides helpers methods for key module - * @module key/helper - * @private - */ - - async function generateSecretSubkey(options, config) { - const secretSubkeyPacket = new SecretSubkeyPacket(options.date, config); - secretSubkeyPacket.packets = null; - secretSubkeyPacket.algorithm = enums.write(enums.publicKey, options.algorithm); - await secretSubkeyPacket.generate(options.rsaBits, options.curve); - await secretSubkeyPacket.computeFingerprintAndKeyID(); - return secretSubkeyPacket; - } - - async function generateSecretKey(options, config) { - const secretKeyPacket = new SecretKeyPacket(options.date, config); - secretKeyPacket.packets = null; - secretKeyPacket.algorithm = enums.write(enums.publicKey, options.algorithm); - await secretKeyPacket.generate(options.rsaBits, options.curve, options.config); - await secretKeyPacket.computeFingerprintAndKeyID(); - return secretKeyPacket; - } - - /** - * Returns the valid and non-expired signature that has the latest creation date, while ignoring signatures created in the future. - * @param {Array} signatures - List of signatures - * @param {PublicKeyPacket|PublicSubkeyPacket} publicKey - Public key packet to verify the signature - * @param {Date} date - Use the given date instead of the current time - * @param {Object} config - full configuration - * @returns {Promise} The latest valid signature. - * @async - */ - async function getLatestValidSignature(signatures, publicKey, signatureType, dataToVerify, date = new Date(), config) { - let latestValid; - let exception; - for (let i = signatures.length - 1; i >= 0; i--) { - try { - if ( - (!latestValid || signatures[i].created >= latestValid.created) - ) { - await signatures[i].verify(publicKey, signatureType, dataToVerify, date, undefined, config); - latestValid = signatures[i]; - } - } catch (e) { - exception = e; - } - } - if (!latestValid) { - throw util.wrapError( - `Could not find valid ${enums.read(enums.signature, signatureType)} signature in key ${publicKey.getKeyID().toHex()}` - .replace('certGeneric ', 'self-') - .replace(/([a-z])([A-Z])/g, (_, $1, $2) => $1 + ' ' + $2.toLowerCase()) - , exception); - } - return latestValid; - } - - function isDataExpired(keyPacket, signature, date = new Date()) { - const normDate = util.normalizeDate(date); - if (normDate !== null) { - const expirationTime = getKeyExpirationTime(keyPacket, signature); - return !(keyPacket.created <= normDate && normDate < expirationTime); - } - return false; - } - - /** - * Create Binding signature to the key according to the {@link https://tools.ietf.org/html/rfc4880#section-5.2.1} - * @param {SecretSubkeyPacket} subkey - Subkey key packet - * @param {SecretKeyPacket} primaryKey - Primary key packet - * @param {Object} options - * @param {Object} config - Full configuration - */ - async function createBindingSignature(subkey, primaryKey, options, config) { - const dataToSign = {}; - dataToSign.key = primaryKey; - dataToSign.bind = subkey; - const subkeySignaturePacket = new SignaturePacket(); - subkeySignaturePacket.signatureType = enums.signature.subkeyBinding; - subkeySignaturePacket.publicKeyAlgorithm = primaryKey.algorithm; - subkeySignaturePacket.hashAlgorithm = await getPreferredHashAlgo$1(null, subkey, undefined, undefined, config); - if (options.sign) { - subkeySignaturePacket.keyFlags = [enums.keyFlags.signData]; - subkeySignaturePacket.embeddedSignature = await createSignaturePacket(dataToSign, null, subkey, { - signatureType: enums.signature.keyBinding - }, options.date, undefined, undefined, config); - } else { - subkeySignaturePacket.keyFlags = [enums.keyFlags.encryptCommunication | enums.keyFlags.encryptStorage]; - } - if (options.keyExpirationTime > 0) { - subkeySignaturePacket.keyExpirationTime = options.keyExpirationTime; - subkeySignaturePacket.keyNeverExpires = false; - } - await subkeySignaturePacket.sign(primaryKey, dataToSign, options.date); - return subkeySignaturePacket; - } - - /** - * Returns the preferred signature hash algorithm of a key - * @param {Key} [key] - The key to get preferences from - * @param {SecretKeyPacket|SecretSubkeyPacket} keyPacket - key packet used for signing - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} [userID] - User ID - * @param {Object} config - full configuration - * @returns {Promise} - * @async - */ - async function getPreferredHashAlgo$1(key, keyPacket, date = new Date(), userID = {}, config) { - let hashAlgo = config.preferredHashAlgorithm; - let prefAlgo = hashAlgo; - if (key) { - const primaryUser = await key.getPrimaryUser(date, userID, config); - if (primaryUser.selfCertification.preferredHashAlgorithms) { - [prefAlgo] = primaryUser.selfCertification.preferredHashAlgorithms; - hashAlgo = mod.hash.getHashByteLength(hashAlgo) <= mod.hash.getHashByteLength(prefAlgo) ? - prefAlgo : hashAlgo; - } - } - switch (Object.getPrototypeOf(keyPacket)) { - case SecretKeyPacket.prototype: - case PublicKeyPacket.prototype: - case SecretSubkeyPacket.prototype: - case PublicSubkeyPacket.prototype: - switch (keyPacket.algorithm) { - case enums.publicKey.ecdh: - case enums.publicKey.ecdsa: - case enums.publicKey.eddsa: - prefAlgo = mod.publicKey.elliptic.getPreferredHashAlgo(keyPacket.publicParams.oid); - } - } - return mod.hash.getHashByteLength(hashAlgo) <= mod.hash.getHashByteLength(prefAlgo) ? - prefAlgo : hashAlgo; - } - - /** - * Returns the preferred symmetric/aead/compression algorithm for a set of keys - * @param {'symmetric'|'aead'|'compression'} type - Type of preference to return - * @param {Array} [keys] - Set of keys - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Array} [userIDs] - User IDs - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} Preferred algorithm - * @async - */ - async function getPreferredAlgo(type, keys = [], date = new Date(), userIDs = [], config = defaultConfig) { - const defaultAlgo = { // these are all must-implement in rfc4880bis - 'symmetric': enums.symmetric.aes128, - 'aead': enums.aead.eax, - 'compression': enums.compression.uncompressed - }[type]; - const preferredSenderAlgo = { - 'symmetric': config.preferredSymmetricAlgorithm, - 'aead': config.preferredAEADAlgorithm, - 'compression': config.preferredCompressionAlgorithm - }[type]; - const prefPropertyName = { - 'symmetric': 'preferredSymmetricAlgorithms', - 'aead': 'preferredAEADAlgorithms', - 'compression': 'preferredCompressionAlgorithms' - }[type]; - - // if preferredSenderAlgo appears in the prefs of all recipients, we pick it - // otherwise we use the default algo - // if no keys are available, preferredSenderAlgo is returned - const senderAlgoSupport = await Promise.all(keys.map(async function(key, i) { - const primaryUser = await key.getPrimaryUser(date, userIDs[i], config); - const recipientPrefs = primaryUser.selfCertification[prefPropertyName]; - return !!recipientPrefs && recipientPrefs.indexOf(preferredSenderAlgo) >= 0; - })); - return senderAlgoSupport.every(Boolean) ? preferredSenderAlgo : defaultAlgo; - } - - /** - * Create signature packet - * @param {Object} dataToSign - Contains packets to be signed - * @param {PrivateKey} privateKey - key to get preferences from - * @param {SecretKeyPacket| - * SecretSubkeyPacket} signingKeyPacket secret key packet for signing - * @param {Object} [signatureProperties] - Properties to write on the signature packet before signing - * @param {Date} [date] - Override the creationtime of the signature - * @param {Object} [userID] - User ID - * @param {Object} [detached] - Whether to create a detached signature packet - * @param {Object} config - full configuration - * @returns {Promise} Signature packet. - */ - async function createSignaturePacket(dataToSign, privateKey, signingKeyPacket, signatureProperties, date, userID, detached = false, config) { - if (signingKeyPacket.isDummy()) { - throw new Error('Cannot sign with a gnu-dummy key.'); - } - if (!signingKeyPacket.isDecrypted()) { - throw new Error('Signing key is not decrypted.'); - } - const signaturePacket = new SignaturePacket(); - Object.assign(signaturePacket, signatureProperties); - signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm; - signaturePacket.hashAlgorithm = await getPreferredHashAlgo$1(privateKey, signingKeyPacket, date, userID, config); - await signaturePacket.sign(signingKeyPacket, dataToSign, date, detached); - return signaturePacket; - } - - /** - * Merges signatures from source[attr] to dest[attr] - * @param {Object} source - * @param {Object} dest - * @param {String} attr - * @param {Date} [date] - date to use for signature expiration check, instead of the current time - * @param {Function} [checkFn] - signature only merged if true - */ - async function mergeSignatures(source, dest, attr, date = new Date(), checkFn) { - source = source[attr]; - if (source) { - if (!dest[attr].length) { - dest[attr] = source; - } else { - await Promise.all(source.map(async function(sourceSig) { - if (!sourceSig.isExpired(date) && (!checkFn || await checkFn(sourceSig)) && - !dest[attr].some(function(destSig) { - return util.equalsUint8Array(destSig.writeParams(), sourceSig.writeParams()); - })) { - dest[attr].push(sourceSig); - } - })); - } - } - } - - /** - * Checks if a given certificate or binding signature is revoked - * @param {SecretKeyPacket| - * PublicKeyPacket} primaryKey The primary key packet - * @param {Object} dataToVerify - The data to check - * @param {Array} revocations - The revocation signatures to check - * @param {SignaturePacket} signature - The certificate or signature to check - * @param {PublicSubkeyPacket| - * SecretSubkeyPacket| - * PublicKeyPacket| - * SecretKeyPacket} key, optional The key packet to verify the signature, instead of the primary key - * @param {Date} date - Use the given date instead of the current time - * @param {Object} config - Full configuration - * @returns {Promise} True if the signature revokes the data. - * @async - */ - async function isDataRevoked(primaryKey, signatureType, dataToVerify, revocations, signature, key, date = new Date(), config) { - key = key || primaryKey; - const revocationKeyIDs = []; - await Promise.all(revocations.map(async function(revocationSignature) { - try { - if ( - // Note: a third-party revocation signature could legitimately revoke a - // self-signature if the signature has an authorized revocation key. - // However, we don't support passing authorized revocation keys, nor - // verifying such revocation signatures. Instead, we indicate an error - // when parsing a key with an authorized revocation key, and ignore - // third-party revocation signatures here. (It could also be revoking a - // third-party key certification, which should only affect - // `verifyAllCertifications`.) - !signature || revocationSignature.issuerKeyID.equals(signature.issuerKeyID) - ) { - await revocationSignature.verify( - key, signatureType, dataToVerify, config.revocationsExpire ? date : null, false, config - ); - - // TODO get an identifier of the revoked object instead - revocationKeyIDs.push(revocationSignature.issuerKeyID); - } - } catch (e) {} - })); - // TODO further verify that this is the signature that should be revoked - if (signature) { - signature.revoked = revocationKeyIDs.some(keyID => keyID.equals(signature.issuerKeyID)) ? true : - signature.revoked || false; - return signature.revoked; - } - return revocationKeyIDs.length > 0; - } - - /** - * Returns key expiration time based on the given certification signature. - * The expiration time of the signature is ignored. - * @param {PublicSubkeyPacket|PublicKeyPacket} keyPacket - key to check - * @param {SignaturePacket} signature - signature to process - * @returns {Date|Infinity} expiration time or infinity if the key does not expire - */ - function getKeyExpirationTime(keyPacket, signature) { - let expirationTime; - // check V4 expiration time - if (signature.keyNeverExpires === false) { - expirationTime = keyPacket.created.getTime() + signature.keyExpirationTime * 1000; - } - return expirationTime ? new Date(expirationTime) : Infinity; - } - - /** - * Returns whether aead is supported by all keys in the set - * @param {Array} keys - Set of keys - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Array} [userIDs] - User IDs - * @param {Object} config - full configuration - * @returns {Promise} - * @async - */ - async function isAEADSupported(keys, date = new Date(), userIDs = [], config = defaultConfig) { - let supported = true; - // TODO replace when Promise.some or Promise.any are implemented - await Promise.all(keys.map(async function(key, i) { - const primaryUser = await key.getPrimaryUser(date, userIDs[i], config); - if (!primaryUser.selfCertification.features || - !(primaryUser.selfCertification.features[0] & enums.features.aead)) { - supported = false; - } - })); - return supported; - } - - function sanitizeKeyOptions(options, subkeyDefaults = {}) { - options.type = options.type || subkeyDefaults.type; - options.curve = options.curve || subkeyDefaults.curve; - options.rsaBits = options.rsaBits || subkeyDefaults.rsaBits; - options.keyExpirationTime = options.keyExpirationTime !== undefined ? options.keyExpirationTime : subkeyDefaults.keyExpirationTime; - options.passphrase = util.isString(options.passphrase) ? options.passphrase : subkeyDefaults.passphrase; - options.date = options.date || subkeyDefaults.date; - - options.sign = options.sign || false; - - switch (options.type) { - case 'ecc': - try { - options.curve = enums.write(enums.curve, options.curve); - } catch (e) { - throw new Error('Invalid curve'); - } - if (options.curve === enums.curve.ed25519 || options.curve === enums.curve.curve25519) { - options.curve = options.sign ? enums.curve.ed25519 : enums.curve.curve25519; - } - if (options.sign) { - options.algorithm = options.curve === enums.curve.ed25519 ? enums.publicKey.eddsa : enums.publicKey.ecdsa; - } else { - options.algorithm = enums.publicKey.ecdh; - } - break; - case 'rsa': - options.algorithm = enums.publicKey.rsaEncryptSign; - break; - default: - throw new Error(`Unsupported key type ${options.type}`); - } - return options; - } - - function isValidSigningKeyPacket(keyPacket, signature) { - const keyAlgo = keyPacket.algorithm; - return keyAlgo !== enums.publicKey.rsaEncrypt && - keyAlgo !== enums.publicKey.elgamal && - keyAlgo !== enums.publicKey.ecdh && - (!signature.keyFlags || - (signature.keyFlags[0] & enums.keyFlags.signData) !== 0); - } - - function isValidEncryptionKeyPacket(keyPacket, signature) { - const keyAlgo = keyPacket.algorithm; - return keyAlgo !== enums.publicKey.dsa && - keyAlgo !== enums.publicKey.rsaSign && - keyAlgo !== enums.publicKey.ecdsa && - keyAlgo !== enums.publicKey.eddsa && - (!signature.keyFlags || - (signature.keyFlags[0] & enums.keyFlags.encryptCommunication) !== 0 || - (signature.keyFlags[0] & enums.keyFlags.encryptStorage) !== 0); - } - - function isValidDecryptionKeyPacket(signature, config) { - if (config.allowInsecureDecryptionWithSigningKeys) { - // This is only relevant for RSA keys, all other signing algorithms cannot decrypt - return true; - } - - return !signature.keyFlags || - (signature.keyFlags[0] & enums.keyFlags.encryptCommunication) !== 0 || - (signature.keyFlags[0] & enums.keyFlags.encryptStorage) !== 0; - } - - /** - * Check key against blacklisted algorithms and minimum strength requirements. - * @param {SecretKeyPacket|PublicKeyPacket| - * SecretSubkeyPacket|PublicSubkeyPacket} keyPacket - * @param {Config} config - * @throws {Error} if the key packet does not meet the requirements - */ - function checkKeyRequirements(keyPacket, config) { - const keyAlgo = enums.write(enums.publicKey, keyPacket.algorithm); - const algoInfo = keyPacket.getAlgorithmInfo(); - if (config.rejectPublicKeyAlgorithms.has(keyAlgo)) { - throw new Error(`${algoInfo.algorithm} keys are considered too weak.`); - } - switch (keyAlgo) { - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaSign: - case enums.publicKey.rsaEncrypt: - if (algoInfo.bits < config.minRSABits) { - throw new Error(`RSA keys shorter than ${config.minRSABits} bits are considered too weak.`); - } - break; - case enums.publicKey.ecdsa: - case enums.publicKey.eddsa: - case enums.publicKey.ecdh: - if (config.rejectCurves.has(algoInfo.curve)) { - throw new Error(`Support for ${algoInfo.algorithm} keys using curve ${algoInfo.curve} is disabled.`); - } - break; - } - } - - /** - * @module key/User - * @private - */ - - /** - * Class that represents an user ID or attribute packet and the relevant signatures. - * @param {UserIDPacket|UserAttributePacket} userPacket - packet containing the user info - * @param {Key} mainKey - reference to main Key object containing the primary key and subkeys that the user is associated with - */ - class User { - constructor(userPacket, mainKey) { - this.userID = userPacket.constructor.tag === enums.packet.userID ? userPacket : null; - this.userAttribute = userPacket.constructor.tag === enums.packet.userAttribute ? userPacket : null; - this.selfCertifications = []; - this.otherCertifications = []; - this.revocationSignatures = []; - this.mainKey = mainKey; - } - - /** - * Transforms structured user data to packetlist - * @returns {PacketList} - */ - toPacketList() { - const packetlist = new PacketList(); - packetlist.push(this.userID || this.userAttribute); - packetlist.push(...this.revocationSignatures); - packetlist.push(...this.selfCertifications); - packetlist.push(...this.otherCertifications); - return packetlist; - } - - /** - * Shallow clone - * @returns {User} - */ - clone() { - const user = new User(this.userID || this.userAttribute, this.mainKey); - user.selfCertifications = [...this.selfCertifications]; - user.otherCertifications = [...this.otherCertifications]; - user.revocationSignatures = [...this.revocationSignatures]; - return user; - } - - /** - * Generate third-party certifications over this user and its primary key - * @param {Array} signingKeys - Decrypted private keys for signing - * @param {Date} [date] - Date to use as creation date of the certificate, instead of the current time - * @param {Object} config - Full configuration - * @returns {Promise} New user with new certifications. - * @async - */ - async certify(signingKeys, date, config) { - const primaryKey = this.mainKey.keyPacket; - const dataToSign = { - userID: this.userID, - userAttribute: this.userAttribute, - key: primaryKey - }; - const user = new User(dataToSign.userID || dataToSign.userAttribute, this.mainKey); - user.otherCertifications = await Promise.all(signingKeys.map(async function(privateKey) { - if (!privateKey.isPrivate()) { - throw new Error('Need private key for signing'); - } - if (privateKey.hasSameFingerprintAs(primaryKey)) { - throw new Error("The user's own key can only be used for self-certifications"); - } - const signingKey = await privateKey.getSigningKey(undefined, date, undefined, config); - return createSignaturePacket(dataToSign, privateKey, signingKey.keyPacket, { - // Most OpenPGP implementations use generic certification (0x10) - signatureType: enums.signature.certGeneric, - keyFlags: [enums.keyFlags.certifyKeys | enums.keyFlags.signData] - }, date, undefined, undefined, config); - })); - await user.update(this, date, config); - return user; - } - - /** - * Checks if a given certificate of the user is revoked - * @param {SignaturePacket} certificate - The certificate to verify - * @param {PublicSubkeyPacket| - * SecretSubkeyPacket| - * PublicKeyPacket| - * SecretKeyPacket} [keyPacket] The key packet to verify the signature, instead of the primary key - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} config - Full configuration - * @returns {Promise} True if the certificate is revoked. - * @async - */ - async isRevoked(certificate, keyPacket, date = new Date(), config) { - const primaryKey = this.mainKey.keyPacket; - return isDataRevoked(primaryKey, enums.signature.certRevocation, { - key: primaryKey, - userID: this.userID, - userAttribute: this.userAttribute - }, this.revocationSignatures, certificate, keyPacket, date, config); - } - - /** - * Verifies the user certificate. - * @param {SignaturePacket} certificate - A certificate of this user - * @param {Array} verificationKeys - Array of keys to verify certificate signatures - * @param {Date} [date] - Use the given date instead of the current time - * @param {Object} config - Full configuration - * @returns {Promise} true if the certificate could be verified, or null if the verification keys do not correspond to the certificate - * @throws if the user certificate is invalid. - * @async - */ - async verifyCertificate(certificate, verificationKeys, date = new Date(), config) { - const that = this; - const primaryKey = this.mainKey.keyPacket; - const dataToVerify = { - userID: this.userID, - userAttribute: this.userAttribute, - key: primaryKey - }; - const { issuerKeyID } = certificate; - const issuerKeys = verificationKeys.filter(key => key.getKeys(issuerKeyID).length > 0); - if (issuerKeys.length === 0) { - return null; - } - await Promise.all(issuerKeys.map(async key => { - const signingKey = await key.getSigningKey(issuerKeyID, certificate.created, undefined, config); - if (certificate.revoked || await that.isRevoked(certificate, signingKey.keyPacket, date, config)) { - throw new Error('User certificate is revoked'); - } - try { - await certificate.verify(signingKey.keyPacket, enums.signature.certGeneric, dataToVerify, date, undefined, config); - } catch (e) { - throw util.wrapError('User certificate is invalid', e); - } - })); - return true; - } - - /** - * Verifies all user certificates - * @param {Array} verificationKeys - Array of keys to verify certificate signatures - * @param {Date} [date] - Use the given date instead of the current time - * @param {Object} config - Full configuration - * @returns {Promise>} List of signer's keyID and validity of signature. - * Signature validity is null if the verification keys do not correspond to the certificate. - * @async - */ - async verifyAllCertifications(verificationKeys, date = new Date(), config) { - const that = this; - const certifications = this.selfCertifications.concat(this.otherCertifications); - return Promise.all(certifications.map(async certification => ({ - keyID: certification.issuerKeyID, - valid: await that.verifyCertificate(certification, verificationKeys, date, config).catch(() => false) - }))); - } - - /** - * Verify User. Checks for existence of self signatures, revocation signatures - * and validity of self signature. - * @param {Date} date - Use the given date instead of the current time - * @param {Object} config - Full configuration - * @returns {Promise} Status of user. - * @throws {Error} if there are no valid self signatures. - * @async - */ - async verify(date = new Date(), config) { - if (!this.selfCertifications.length) { - throw new Error('No self-certifications found'); - } - const that = this; - const primaryKey = this.mainKey.keyPacket; - const dataToVerify = { - userID: this.userID, - userAttribute: this.userAttribute, - key: primaryKey - }; - // TODO replace when Promise.some or Promise.any are implemented - let exception; - for (let i = this.selfCertifications.length - 1; i >= 0; i--) { - try { - const selfCertification = this.selfCertifications[i]; - if (selfCertification.revoked || await that.isRevoked(selfCertification, undefined, date, config)) { - throw new Error('Self-certification is revoked'); - } - try { - await selfCertification.verify(primaryKey, enums.signature.certGeneric, dataToVerify, date, undefined, config); - } catch (e) { - throw util.wrapError('Self-certification is invalid', e); - } - return true; - } catch (e) { - exception = e; - } - } - throw exception; - } - - /** - * Update user with new components from specified user - * @param {User} sourceUser - Source user to merge - * @param {Date} date - Date to verify the validity of signatures - * @param {Object} config - Full configuration - * @returns {Promise} - * @async - */ - async update(sourceUser, date, config) { - const primaryKey = this.mainKey.keyPacket; - const dataToVerify = { - userID: this.userID, - userAttribute: this.userAttribute, - key: primaryKey - }; - // self signatures - await mergeSignatures(sourceUser, this, 'selfCertifications', date, async function(srcSelfSig) { - try { - await srcSelfSig.verify(primaryKey, enums.signature.certGeneric, dataToVerify, date, false, config); - return true; - } catch (e) { - return false; - } - }); - // other signatures - await mergeSignatures(sourceUser, this, 'otherCertifications', date); - // revocation signatures - await mergeSignatures(sourceUser, this, 'revocationSignatures', date, function(srcRevSig) { - return isDataRevoked(primaryKey, enums.signature.certRevocation, dataToVerify, [srcRevSig], undefined, undefined, date, config); - }); - } - } - - /** - * @module key/Subkey - * @private - */ - - /** - * Class that represents a subkey packet and the relevant signatures. - * @borrows PublicSubkeyPacket#getKeyID as Subkey#getKeyID - * @borrows PublicSubkeyPacket#getFingerprint as Subkey#getFingerprint - * @borrows PublicSubkeyPacket#hasSameFingerprintAs as Subkey#hasSameFingerprintAs - * @borrows PublicSubkeyPacket#getAlgorithmInfo as Subkey#getAlgorithmInfo - * @borrows PublicSubkeyPacket#getCreationTime as Subkey#getCreationTime - * @borrows PublicSubkeyPacket#isDecrypted as Subkey#isDecrypted - */ - class Subkey { - /** - * @param {SecretSubkeyPacket|PublicSubkeyPacket} subkeyPacket - subkey packet to hold in the Subkey - * @param {Key} mainKey - reference to main Key object, containing the primary key packet corresponding to the subkey - */ - constructor(subkeyPacket, mainKey) { - this.keyPacket = subkeyPacket; - this.bindingSignatures = []; - this.revocationSignatures = []; - this.mainKey = mainKey; - } - - /** - * Transforms structured subkey data to packetlist - * @returns {PacketList} - */ - toPacketList() { - const packetlist = new PacketList(); - packetlist.push(this.keyPacket); - packetlist.push(...this.revocationSignatures); - packetlist.push(...this.bindingSignatures); - return packetlist; - } - - /** - * Shallow clone - * @return {Subkey} - */ - clone() { - const subkey = new Subkey(this.keyPacket, this.mainKey); - subkey.bindingSignatures = [...this.bindingSignatures]; - subkey.revocationSignatures = [...this.revocationSignatures]; - return subkey; - } - - /** - * Checks if a binding signature of a subkey is revoked - * @param {SignaturePacket} signature - The binding signature to verify - * @param {PublicSubkeyPacket| - * SecretSubkeyPacket| - * PublicKeyPacket| - * SecretKeyPacket} key, optional The key to verify the signature - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} True if the binding signature is revoked. - * @async - */ - async isRevoked(signature, key, date = new Date(), config = defaultConfig) { - const primaryKey = this.mainKey.keyPacket; - return isDataRevoked( - primaryKey, enums.signature.subkeyRevocation, { - key: primaryKey, - bind: this.keyPacket - }, this.revocationSignatures, signature, key, date, config - ); - } - - /** - * Verify subkey. Checks for revocation signatures, expiration time - * and valid binding signature. - * @param {Date} date - Use the given date instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} - * @throws {Error} if the subkey is invalid. - * @async - */ - async verify(date = new Date(), config = defaultConfig) { - const primaryKey = this.mainKey.keyPacket; - const dataToVerify = { key: primaryKey, bind: this.keyPacket }; - // check subkey binding signatures - const bindingSignature = await getLatestValidSignature(this.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); - // check binding signature is not revoked - if (bindingSignature.revoked || await this.isRevoked(bindingSignature, null, date, config)) { - throw new Error('Subkey is revoked'); - } - // check for expiration time - if (isDataExpired(this.keyPacket, bindingSignature, date)) { - throw new Error('Subkey is expired'); - } - return bindingSignature; - } - - /** - * Returns the expiration time of the subkey or Infinity if key does not expire. - * Returns null if the subkey is invalid. - * @param {Date} date - Use the given date instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} - * @async - */ - async getExpirationTime(date = new Date(), config = defaultConfig) { - const primaryKey = this.mainKey.keyPacket; - const dataToVerify = { key: primaryKey, bind: this.keyPacket }; - let bindingSignature; - try { - bindingSignature = await getLatestValidSignature(this.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); - } catch (e) { - return null; - } - const keyExpiry = getKeyExpirationTime(this.keyPacket, bindingSignature); - const sigExpiry = bindingSignature.getExpirationTime(); - return keyExpiry < sigExpiry ? keyExpiry : sigExpiry; - } - - /** - * Update subkey with new components from specified subkey - * @param {Subkey} subkey - Source subkey to merge - * @param {Date} [date] - Date to verify validity of signatures - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if update failed - * @async - */ - async update(subkey, date = new Date(), config = defaultConfig) { - const primaryKey = this.mainKey.keyPacket; - if (!this.hasSameFingerprintAs(subkey)) { - throw new Error('Subkey update method: fingerprints of subkeys not equal'); - } - // key packet - if (this.keyPacket.constructor.tag === enums.packet.publicSubkey && - subkey.keyPacket.constructor.tag === enums.packet.secretSubkey) { - this.keyPacket = subkey.keyPacket; - } - // update missing binding signatures - const that = this; - const dataToVerify = { key: primaryKey, bind: that.keyPacket }; - await mergeSignatures(subkey, this, 'bindingSignatures', date, async function(srcBindSig) { - for (let i = 0; i < that.bindingSignatures.length; i++) { - if (that.bindingSignatures[i].issuerKeyID.equals(srcBindSig.issuerKeyID)) { - if (srcBindSig.created > that.bindingSignatures[i].created) { - that.bindingSignatures[i] = srcBindSig; - } - return false; - } - } - try { - await srcBindSig.verify(primaryKey, enums.signature.subkeyBinding, dataToVerify, date, undefined, config); - return true; - } catch (e) { - return false; - } - }); - // revocation signatures - await mergeSignatures(subkey, this, 'revocationSignatures', date, function(srcRevSig) { - return isDataRevoked(primaryKey, enums.signature.subkeyRevocation, dataToVerify, [srcRevSig], undefined, undefined, date, config); - }); - } - - /** - * Revokes the subkey - * @param {SecretKeyPacket} primaryKey - decrypted private primary key for revocation - * @param {Object} reasonForRevocation - optional, object indicating the reason for revocation - * @param {module:enums.reasonForRevocation} reasonForRevocation.flag optional, flag indicating the reason for revocation - * @param {String} reasonForRevocation.string optional, string explaining the reason for revocation - * @param {Date} date - optional, override the creationtime of the revocation signature - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New subkey with revocation signature. - * @async - */ - async revoke( - primaryKey, - { - flag: reasonForRevocationFlag = enums.reasonForRevocation.noReason, - string: reasonForRevocationString = '' - } = {}, - date = new Date(), - config = defaultConfig - ) { - const dataToSign = { key: primaryKey, bind: this.keyPacket }; - const subkey = new Subkey(this.keyPacket, this.mainKey); - subkey.revocationSignatures.push(await createSignaturePacket(dataToSign, null, primaryKey, { - signatureType: enums.signature.subkeyRevocation, - reasonForRevocationFlag: enums.write(enums.reasonForRevocation, reasonForRevocationFlag), - reasonForRevocationString - }, date, undefined, false, config)); - await subkey.update(this); - return subkey; - } - - hasSameFingerprintAs(other) { - return this.keyPacket.hasSameFingerprintAs(other.keyPacket || other); - } - } - - ['getKeyID', 'getFingerprint', 'getAlgorithmInfo', 'getCreationTime', 'isDecrypted'].forEach(name => { - Subkey.prototype[name] = - function() { - return this.keyPacket[name](); - }; - }); - - // GPG4Browsers - An OpenPGP implementation in javascript - - // A key revocation certificate can contain the following packets - const allowedRevocationPackets = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); - - /** - * Abstract class that represents an OpenPGP key. Must contain a primary key. - * Can contain additional subkeys, signatures, user ids, user attributes. - * @borrows PublicKeyPacket#getKeyID as Key#getKeyID - * @borrows PublicKeyPacket#getFingerprint as Key#getFingerprint - * @borrows PublicKeyPacket#hasSameFingerprintAs as Key#hasSameFingerprintAs - * @borrows PublicKeyPacket#getAlgorithmInfo as Key#getAlgorithmInfo - * @borrows PublicKeyPacket#getCreationTime as Key#getCreationTime - */ - class Key { - /** - * Transforms packetlist to structured key data - * @param {PacketList} packetlist - The packets that form a key - * @param {Set} disallowedPackets - disallowed packet tags - */ - packetListToStructure(packetlist, disallowedPackets = new Set()) { - let user; - let primaryKeyID; - let subkey; - for (const packet of packetlist) { - const tag = packet.constructor.tag; - if (disallowedPackets.has(tag)) { - throw new Error(`Unexpected packet type: ${tag}`); - } - switch (tag) { - case enums.packet.publicKey: - case enums.packet.secretKey: - if (this.keyPacket) { - throw new Error('Key block contains multiple keys'); - } - this.keyPacket = packet; - primaryKeyID = this.getKeyID(); - if (!primaryKeyID) { - throw new Error('Missing Key ID'); - } - break; - case enums.packet.userID: - case enums.packet.userAttribute: - user = new User(packet, this); - this.users.push(user); - break; - case enums.packet.publicSubkey: - case enums.packet.secretSubkey: - user = null; - subkey = new Subkey(packet, this); - this.subkeys.push(subkey); - break; - case enums.packet.signature: - switch (packet.signatureType) { - case enums.signature.certGeneric: - case enums.signature.certPersona: - case enums.signature.certCasual: - case enums.signature.certPositive: - if (!user) { - util.printDebug('Dropping certification signatures without preceding user packet'); - continue; - } - if (packet.issuerKeyID.equals(primaryKeyID)) { - user.selfCertifications.push(packet); - } else { - user.otherCertifications.push(packet); - } - break; - case enums.signature.certRevocation: - if (user) { - user.revocationSignatures.push(packet); - } else { - this.directSignatures.push(packet); - } - break; - case enums.signature.key: - this.directSignatures.push(packet); - break; - case enums.signature.subkeyBinding: - if (!subkey) { - util.printDebug('Dropping subkey binding signature without preceding subkey packet'); - continue; - } - subkey.bindingSignatures.push(packet); - break; - case enums.signature.keyRevocation: - this.revocationSignatures.push(packet); - break; - case enums.signature.subkeyRevocation: - if (!subkey) { - util.printDebug('Dropping subkey revocation signature without preceding subkey packet'); - continue; - } - subkey.revocationSignatures.push(packet); - break; - } - break; - } - } - } - - /** - * Transforms structured key data to packetlist - * @returns {PacketList} The packets that form a key. - */ - toPacketList() { - const packetlist = new PacketList(); - packetlist.push(this.keyPacket); - packetlist.push(...this.revocationSignatures); - packetlist.push(...this.directSignatures); - this.users.map(user => packetlist.push(...user.toPacketList())); - this.subkeys.map(subkey => packetlist.push(...subkey.toPacketList())); - return packetlist; - } - - /** - * Clones the key object - * @param {Boolean} [deep=false] Whether to return a deep clone - * @returns {Promise} Clone of the key. - */ - clone(deep = false) { - const key = new this.constructor(this.toPacketList()); - if (deep) { - key.getKeys().forEach(k => { - // shallow clone the key packets - k.keyPacket = Object.create( - Object.getPrototypeOf(k.keyPacket), - Object.getOwnPropertyDescriptors(k.keyPacket) - ); - if (!k.keyPacket.isDecrypted()) return; - // deep clone the private params, which are cleared during encryption - const privateParams = {}; - Object.keys(k.keyPacket.privateParams).forEach(name => { - privateParams[name] = new Uint8Array(k.keyPacket.privateParams[name]); - }); - k.keyPacket.privateParams = privateParams; - }); - } - return key; - } - - /** - * Returns an array containing all public or private subkeys matching keyID; - * If no keyID is given, returns all subkeys. - * @param {type/keyID} [keyID] - key ID to look for - * @returns {Array} array of subkeys - */ - getSubkeys(keyID = null) { - const subkeys = this.subkeys.filter(subkey => ( - !keyID || subkey.getKeyID().equals(keyID, true) - )); - return subkeys; - } - - /** - * Returns an array containing all public or private keys matching keyID. - * If no keyID is given, returns all keys, starting with the primary key. - * @param {type/keyid~KeyID} [keyID] - key ID to look for - * @returns {Array} array of keys - */ - getKeys(keyID = null) { - const keys = []; - if (!keyID || this.getKeyID().equals(keyID, true)) { - keys.push(this); - } - return keys.concat(this.getSubkeys(keyID)); - } - - /** - * Returns key IDs of all keys - * @returns {Array} - */ - getKeyIDs() { - return this.getKeys().map(key => key.getKeyID()); - } - - /** - * Returns userIDs - * @returns {Array} Array of userIDs. - */ - getUserIDs() { - return this.users.map(user => { - return user.userID ? user.userID.userID : null; - }).filter(userID => userID !== null); - } - - /** - * Returns binary encoded key - * @returns {Uint8Array} Binary key. - */ - write() { - return this.toPacketList().write(); - } - - /** - * Returns last created key or key by given keyID that is available for signing and verification - * @param {module:type/keyid~KeyID} [keyID] - key ID of a specific key to retrieve - * @param {Date} [date] - use the fiven date date to to check key validity instead of the current date - * @param {Object} [userID] - filter keys for the given user ID - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} signing key - * @throws if no valid signing key was found - * @async - */ - async getSigningKey(keyID = null, date = new Date(), userID = {}, config = defaultConfig) { - await this.verifyPrimaryKey(date, userID, config); - const primaryKey = this.keyPacket; - const subkeys = this.subkeys.slice().sort((a, b) => b.keyPacket.created - a.keyPacket.created); - let exception; - for (const subkey of subkeys) { - if (!keyID || subkey.getKeyID().equals(keyID)) { - try { - await subkey.verify(date, config); - const dataToVerify = { key: primaryKey, bind: subkey.keyPacket }; - const bindingSignature = await getLatestValidSignature( - subkey.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config - ); - if (!isValidSigningKeyPacket(subkey.keyPacket, bindingSignature)) { - continue; - } - if (!bindingSignature.embeddedSignature) { - throw new Error('Missing embedded signature'); - } - // verify embedded signature - await getLatestValidSignature( - [bindingSignature.embeddedSignature], subkey.keyPacket, enums.signature.keyBinding, dataToVerify, date, config - ); - checkKeyRequirements(subkey.keyPacket, config); - return subkey; - } catch (e) { - exception = e; - } - } - } - - try { - const primaryUser = await this.getPrimaryUser(date, userID, config); - if ((!keyID || primaryKey.getKeyID().equals(keyID)) && - isValidSigningKeyPacket(primaryKey, primaryUser.selfCertification, config)) { - checkKeyRequirements(primaryKey, config); - return this; - } - } catch (e) { - exception = e; - } - throw util.wrapError('Could not find valid signing key packet in key ' + this.getKeyID().toHex(), exception); - } - - /** - * Returns last created key or key by given keyID that is available for encryption or decryption - * @param {module:type/keyid~KeyID} [keyID] - key ID of a specific key to retrieve - * @param {Date} [date] - use the fiven date date to to check key validity instead of the current date - * @param {Object} [userID] - filter keys for the given user ID - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} encryption key - * @throws if no valid encryption key was found - * @async - */ - async getEncryptionKey(keyID, date = new Date(), userID = {}, config = defaultConfig) { - await this.verifyPrimaryKey(date, userID, config); - const primaryKey = this.keyPacket; - // V4: by convention subkeys are preferred for encryption service - const subkeys = this.subkeys.slice().sort((a, b) => b.keyPacket.created - a.keyPacket.created); - let exception; - for (const subkey of subkeys) { - if (!keyID || subkey.getKeyID().equals(keyID)) { - try { - await subkey.verify(date, config); - const dataToVerify = { key: primaryKey, bind: subkey.keyPacket }; - const bindingSignature = await getLatestValidSignature(subkey.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); - if (isValidEncryptionKeyPacket(subkey.keyPacket, bindingSignature)) { - checkKeyRequirements(subkey.keyPacket, config); - return subkey; - } - } catch (e) { - exception = e; - } - } - } - - try { - // if no valid subkey for encryption, evaluate primary key - const primaryUser = await this.getPrimaryUser(date, userID, config); - if ((!keyID || primaryKey.getKeyID().equals(keyID)) && - isValidEncryptionKeyPacket(primaryKey, primaryUser.selfCertification)) { - checkKeyRequirements(primaryKey, config); - return this; - } - } catch (e) { - exception = e; - } - throw util.wrapError('Could not find valid encryption key packet in key ' + this.getKeyID().toHex(), exception); - } - - /** - * Checks if a signature on a key is revoked - * @param {SignaturePacket} signature - The signature to verify - * @param {PublicSubkeyPacket| - * SecretSubkeyPacket| - * PublicKeyPacket| - * SecretKeyPacket} key, optional The key to verify the signature - * @param {Date} [date] - Use the given date for verification, instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} True if the certificate is revoked. - * @async - */ - async isRevoked(signature, key, date = new Date(), config = defaultConfig) { - return isDataRevoked( - this.keyPacket, enums.signature.keyRevocation, { key: this.keyPacket }, this.revocationSignatures, signature, key, date, config - ); - } - - /** - * Verify primary key. Checks for revocation signatures, expiration time - * and valid self signature. Throws if the primary key is invalid. - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} [userID] - User ID - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} If key verification failed - * @async - */ - async verifyPrimaryKey(date = new Date(), userID = {}, config = defaultConfig) { - const primaryKey = this.keyPacket; - // check for key revocation signatures - if (await this.isRevoked(null, null, date, config)) { - throw new Error('Primary key is revoked'); - } - // check for valid, unrevoked, unexpired self signature - const { selfCertification } = await this.getPrimaryUser(date, userID, config); - // check for expiration time in binding signatures - if (isDataExpired(primaryKey, selfCertification, date)) { - throw new Error('Primary key is expired'); - } - // check for expiration time in direct signatures - const directSignature = await getLatestValidSignature( - this.directSignatures, primaryKey, enums.signature.key, { key: primaryKey }, date, config - ).catch(() => {}); // invalid signatures are discarded, to avoid breaking the key - - if (directSignature && isDataExpired(primaryKey, directSignature, date)) { - throw new Error('Primary key is expired'); - } - } - - /** - * Returns the expiration date of the primary key, considering self-certifications and direct-key signatures. - * Returns `Infinity` if the key doesn't expire, or `null` if the key is revoked or invalid. - * @param {Object} [userID] - User ID to consider instead of the primary user - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} - * @async - */ - async getExpirationTime(userID, config = defaultConfig) { - let primaryKeyExpiry; - try { - const { selfCertification } = await this.getPrimaryUser(null, userID, config); - const selfSigKeyExpiry = getKeyExpirationTime(this.keyPacket, selfCertification); - const selfSigExpiry = selfCertification.getExpirationTime(); - const directSignature = await getLatestValidSignature( - this.directSignatures, this.keyPacket, enums.signature.key, { key: this.keyPacket }, null, config - ).catch(() => {}); - if (directSignature) { - const directSigKeyExpiry = getKeyExpirationTime(this.keyPacket, directSignature); - // We do not support the edge case where the direct signature expires, since it would invalidate the corresponding key expiration, - // causing a discountinous validy period for the key - primaryKeyExpiry = Math.min(selfSigKeyExpiry, selfSigExpiry, directSigKeyExpiry); - } else { - primaryKeyExpiry = selfSigKeyExpiry < selfSigExpiry ? selfSigKeyExpiry : selfSigExpiry; - } - } catch (e) { - primaryKeyExpiry = null; - } - - return util.normalizeDate(primaryKeyExpiry); - } - - - /** - * Returns primary user and most significant (latest valid) self signature - * - if multiple primary users exist, returns the one with the latest self signature - * - otherwise, returns the user with the latest self signature - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} [userID] - User ID to get instead of the primary user, if it exists - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise<{ - * user: User, - * selfCertification: SignaturePacket - * }>} The primary user and the self signature - * @async - */ - async getPrimaryUser(date = new Date(), userID = {}, config = defaultConfig) { - const primaryKey = this.keyPacket; - const users = []; - let exception; - for (let i = 0; i < this.users.length; i++) { - try { - const user = this.users[i]; - if (!user.userID) { - continue; - } - if ( - (userID.name !== undefined && user.userID.name !== userID.name) || - (userID.email !== undefined && user.userID.email !== userID.email) || - (userID.comment !== undefined && user.userID.comment !== userID.comment) - ) { - throw new Error('Could not find user that matches that user ID'); - } - const dataToVerify = { userID: user.userID, key: primaryKey }; - const selfCertification = await getLatestValidSignature(user.selfCertifications, primaryKey, enums.signature.certGeneric, dataToVerify, date, config); - users.push({ index: i, user, selfCertification }); - } catch (e) { - exception = e; - } - } - if (!users.length) { - throw exception || new Error('Could not find primary user'); - } - await Promise.all(users.map(async function (a) { - return a.user.revoked || a.user.isRevoked(a.selfCertification, null, date, config); - })); - // sort by primary user flag and signature creation time - const primaryUser = users.sort(function(a, b) { - const A = a.selfCertification; - const B = b.selfCertification; - return B.revoked - A.revoked || A.isPrimaryUserID - B.isPrimaryUserID || A.created - B.created; - }).pop(); - const { user, selfCertification: cert } = primaryUser; - if (cert.revoked || await user.isRevoked(cert, null, date, config)) { - throw new Error('Primary user is revoked'); - } - return primaryUser; - } - - /** - * Update key with new components from specified key with same key ID: - * users, subkeys, certificates are merged into the destination key, - * duplicates and expired signatures are ignored. - * - * If the source key is a private key and the destination key is public, - * a private key is returned. - * @param {Key} sourceKey - Source key to merge - * @param {Date} [date] - Date to verify validity of signatures and keys - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} updated key - * @async - */ - async update(sourceKey, date = new Date(), config = defaultConfig) { - if (!this.hasSameFingerprintAs(sourceKey)) { - throw new Error('Primary key fingerprints must be equal to update the key'); - } - if (!this.isPrivate() && sourceKey.isPrivate()) { - // check for equal subkey packets - const equal = (this.subkeys.length === sourceKey.subkeys.length) && - (this.subkeys.every(destSubkey => { - return sourceKey.subkeys.some(srcSubkey => { - return destSubkey.hasSameFingerprintAs(srcSubkey); - }); - })); - if (!equal) { - throw new Error('Cannot update public key with private key if subkeys mismatch'); - } - - return sourceKey.update(this, config); - } - // from here on, either: - // - destination key is private, source key is public - // - the keys are of the same type - // hence we don't need to convert the destination key type - const updatedKey = this.clone(); - // revocation signatures - await mergeSignatures(sourceKey, updatedKey, 'revocationSignatures', date, srcRevSig => { - return isDataRevoked(updatedKey.keyPacket, enums.signature.keyRevocation, updatedKey, [srcRevSig], null, sourceKey.keyPacket, date, config); - }); - // direct signatures - await mergeSignatures(sourceKey, updatedKey, 'directSignatures', date); - // update users - await Promise.all(sourceKey.users.map(async srcUser => { - // multiple users with the same ID/attribute are not explicitly disallowed by the spec - // hence we support them, just in case - const usersToUpdate = updatedKey.users.filter(dstUser => ( - (srcUser.userID && srcUser.userID.equals(dstUser.userID)) || - (srcUser.userAttribute && srcUser.userAttribute.equals(dstUser.userAttribute)) - )); - if (usersToUpdate.length > 0) { - await Promise.all( - usersToUpdate.map(userToUpdate => userToUpdate.update(srcUser, date, config)) - ); - } else { - const newUser = srcUser.clone(); - newUser.mainKey = updatedKey; - updatedKey.users.push(newUser); - } - })); - // update subkeys - await Promise.all(sourceKey.subkeys.map(async srcSubkey => { - // multiple subkeys with same fingerprint might be preset - const subkeysToUpdate = updatedKey.subkeys.filter(dstSubkey => ( - dstSubkey.hasSameFingerprintAs(srcSubkey) - )); - if (subkeysToUpdate.length > 0) { - await Promise.all( - subkeysToUpdate.map(subkeyToUpdate => subkeyToUpdate.update(srcSubkey, date, config)) - ); - } else { - const newSubkey = srcSubkey.clone(); - newSubkey.mainKey = updatedKey; - updatedKey.subkeys.push(newSubkey); - } - })); - - return updatedKey; - } - - /** - * Get revocation certificate from a revoked key. - * (To get a revocation certificate for an unrevoked key, call revoke() first.) - * @param {Date} date - Use the given date instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} Armored revocation certificate. - * @async - */ - async getRevocationCertificate(date = new Date(), config = defaultConfig) { - const dataToVerify = { key: this.keyPacket }; - const revocationSignature = await getLatestValidSignature(this.revocationSignatures, this.keyPacket, enums.signature.keyRevocation, dataToVerify, date, config); - const packetlist = new PacketList(); - packetlist.push(revocationSignature); - return armor(enums.armor.publicKey, packetlist.write(), null, null, 'This is a revocation certificate'); - } - - /** - * Applies a revocation certificate to a key - * This adds the first signature packet in the armored text to the key, - * if it is a valid revocation signature. - * @param {String} revocationCertificate - armored revocation certificate - * @param {Date} [date] - Date to verify the certificate - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} Revoked key. - * @async - */ - async applyRevocationCertificate(revocationCertificate, date = new Date(), config = defaultConfig) { - const input = await unarmor(revocationCertificate, config); - const packetlist = await PacketList.fromBinary(input.data, allowedRevocationPackets, config); - const revocationSignature = packetlist.findPacket(enums.packet.signature); - if (!revocationSignature || revocationSignature.signatureType !== enums.signature.keyRevocation) { - throw new Error('Could not find revocation signature packet'); - } - if (!revocationSignature.issuerKeyID.equals(this.getKeyID())) { - throw new Error('Revocation signature does not match key'); - } - try { - await revocationSignature.verify(this.keyPacket, enums.signature.keyRevocation, { key: this.keyPacket }, date, undefined, config); - } catch (e) { - throw util.wrapError('Could not verify revocation signature', e); - } - const key = this.clone(); - key.revocationSignatures.push(revocationSignature); - return key; - } - - /** - * Signs primary user of key - * @param {Array} privateKeys - decrypted private keys for signing - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} [userID] - User ID to get instead of the primary user, if it exists - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} Key with new certificate signature. - * @async - */ - async signPrimaryUser(privateKeys, date, userID, config = defaultConfig) { - const { index, user } = await this.getPrimaryUser(date, userID, config); - const userSign = await user.certify(privateKeys, date, config); - const key = this.clone(); - key.users[index] = userSign; - return key; - } - - /** - * Signs all users of key - * @param {Array} privateKeys - decrypted private keys for signing - * @param {Date} [date] - Use the given date for signing, instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} Key with new certificate signature. - * @async - */ - async signAllUsers(privateKeys, date = new Date(), config = defaultConfig) { - const key = this.clone(); - key.users = await Promise.all(this.users.map(function(user) { - return user.certify(privateKeys, date, config); - })); - return key; - } - - /** - * Verifies primary user of key - * - if no arguments are given, verifies the self certificates; - * - otherwise, verifies all certificates signed with given keys. - * @param {Array} [verificationKeys] - array of keys to verify certificate signatures, instead of the primary key - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} [userID] - User ID to get instead of the primary user, if it exists - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise>} List of signer's keyID and validity of signature. - * Signature validity is null if the verification keys do not correspond to the certificate. - * @async - */ - async verifyPrimaryUser(verificationKeys, date = new Date(), userID, config = defaultConfig) { - const primaryKey = this.keyPacket; - const { user } = await this.getPrimaryUser(date, userID, config); - const results = verificationKeys ? - await user.verifyAllCertifications(verificationKeys, date, config) : - [{ keyID: primaryKey.getKeyID(), valid: await user.verify(date, config).catch(() => false) }]; - return results; - } - - /** - * Verifies all users of key - * - if no arguments are given, verifies the self certificates; - * - otherwise, verifies all certificates signed with given keys. - * @param {Array} [verificationKeys] - array of keys to verify certificate signatures - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise>} List of userID, signer's keyID and validity of signature. - * Signature validity is null if the verification keys do not correspond to the certificate. - * @async - */ - async verifyAllUsers(verificationKeys, date = new Date(), config = defaultConfig) { - const primaryKey = this.keyPacket; - const results = []; - await Promise.all(this.users.map(async user => { - const signatures = verificationKeys ? - await user.verifyAllCertifications(verificationKeys, date, config) : - [{ keyID: primaryKey.getKeyID(), valid: await user.verify(date, config).catch(() => false) }]; - - results.push(...signatures.map( - signature => ({ - userID: user.userID.userID, - keyID: signature.keyID, - valid: signature.valid - })) - ); - })); - return results; - } - } - - ['getKeyID', 'getFingerprint', 'getAlgorithmInfo', 'getCreationTime', 'hasSameFingerprintAs'].forEach(name => { - Key.prototype[name] = - Subkey.prototype[name]; - }); - - /** - * Creates a PublicKey or PrivateKey depending on the packetlist in input - * @param {PacketList} - packets to parse - * @return {Key} parsed key - * @throws if no key packet was found - */ - function createKey(packetlist) { - for (const packet of packetlist) { - switch (packet.constructor.tag) { - case enums.packet.secretKey: - return new PrivateKey(packetlist); - case enums.packet.publicKey: - return new PublicKey(packetlist); - } - } - throw new Error('No key packet found'); - } - - // This library is free software; you can redistribute it and/or - - /** - * Class that represents an OpenPGP Public Key - */ - class PublicKey extends Key { - /** - * @param {PacketList} packetlist - The packets that form this key - */ - constructor(packetlist) { - super(); - this.keyPacket = null; - this.revocationSignatures = []; - this.directSignatures = []; - this.users = []; - this.subkeys = []; - if (packetlist) { - this.packetListToStructure(packetlist, new Set([enums.packet.secretKey, enums.packet.secretSubkey])); - if (!this.keyPacket) { - throw new Error('Invalid key: missing public-key packet'); - } - } - } - - /** - * Returns true if this is a private key - * @returns {false} - */ - isPrivate() { - return false; - } - - /** - * Returns key as public key (shallow copy) - * @returns {PublicKey} New public Key - */ - toPublic() { - return this; - } - - /** - * Returns ASCII armored text of key - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {ReadableStream} ASCII armor. - */ - armor(config = defaultConfig) { - return armor(enums.armor.publicKey, this.toPacketList().write(), undefined, undefined, undefined, config); - } - } - - /** - * Class that represents an OpenPGP Private key - */ - class PrivateKey extends PublicKey { - /** - * @param {PacketList} packetlist - The packets that form this key - */ - constructor(packetlist) { - super(); - this.packetListToStructure(packetlist, new Set([enums.packet.publicKey, enums.packet.publicSubkey])); - if (!this.keyPacket) { - throw new Error('Invalid key: missing private-key packet'); - } - } - - /** - * Returns true if this is a private key - * @returns {Boolean} - */ - isPrivate() { - return true; - } - - /** - * Returns key as public key (shallow copy) - * @returns {PublicKey} New public Key - */ - toPublic() { - const packetlist = new PacketList(); - const keyPackets = this.toPacketList(); - for (const keyPacket of keyPackets) { - switch (keyPacket.constructor.tag) { - case enums.packet.secretKey: { - const pubKeyPacket = PublicKeyPacket.fromSecretKeyPacket(keyPacket); - packetlist.push(pubKeyPacket); - break; - } - case enums.packet.secretSubkey: { - const pubSubkeyPacket = PublicSubkeyPacket.fromSecretSubkeyPacket(keyPacket); - packetlist.push(pubSubkeyPacket); - break; - } - default: - packetlist.push(keyPacket); - } - } - return new PublicKey(packetlist); - } - - /** - * Returns ASCII armored text of key - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {ReadableStream} ASCII armor. - */ - armor(config = defaultConfig) { - return armor(enums.armor.privateKey, this.toPacketList().write(), undefined, undefined, undefined, config); - } - - /** - * Returns all keys that are available for decryption, matching the keyID when given - * This is useful to retrieve keys for session key decryption - * @param {module:type/keyid~KeyID} keyID, optional - * @param {Date} date, optional - * @param {String} userID, optional - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise>} Array of decryption keys. - * @async - */ - async getDecryptionKeys(keyID, date = new Date(), userID = {}, config = defaultConfig) { - const primaryKey = this.keyPacket; - const keys = []; - for (let i = 0; i < this.subkeys.length; i++) { - if (!keyID || this.subkeys[i].getKeyID().equals(keyID, true)) { - try { - const dataToVerify = { key: primaryKey, bind: this.subkeys[i].keyPacket }; - const bindingSignature = await getLatestValidSignature(this.subkeys[i].bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); - if (isValidDecryptionKeyPacket(bindingSignature, config)) { - keys.push(this.subkeys[i]); - } - } catch (e) {} - } - } - - // evaluate primary key - const primaryUser = await this.getPrimaryUser(date, userID, config); - if ((!keyID || primaryKey.getKeyID().equals(keyID, true)) && - isValidDecryptionKeyPacket(primaryUser.selfCertification, config)) { - keys.push(this); - } - - return keys; - } - - /** - * Returns true if the primary key or any subkey is decrypted. - * A dummy key is considered encrypted. - */ - isDecrypted() { - return this.getKeys().some(({ keyPacket }) => keyPacket.isDecrypted()); - } - - /** - * Check whether the private and public primary key parameters correspond - * Together with verification of binding signatures, this guarantees key integrity - * In case of gnu-dummy primary key, it is enough to validate any signing subkeys - * otherwise all encryption subkeys are validated - * If only gnu-dummy keys are found, we cannot properly validate so we throw an error - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if validation was not successful and the key cannot be trusted - * @async - */ - async validate(config = defaultConfig) { - if (!this.isPrivate()) { - throw new Error('Cannot validate a public key'); - } - - let signingKeyPacket; - if (!this.keyPacket.isDummy()) { - signingKeyPacket = this.keyPacket; - } else { - /** - * It is enough to validate any signing keys - * since its binding signatures are also checked - */ - const signingKey = await this.getSigningKey(null, null, undefined, { ...config, rejectPublicKeyAlgorithms: new Set(), minRSABits: 0 }); - // This could again be a dummy key - if (signingKey && !signingKey.keyPacket.isDummy()) { - signingKeyPacket = signingKey.keyPacket; - } - } - - if (signingKeyPacket) { - return signingKeyPacket.validate(); - } else { - const keys = this.getKeys(); - const allDummies = keys.map(key => key.keyPacket.isDummy()).every(Boolean); - if (allDummies) { - throw new Error('Cannot validate an all-gnu-dummy key'); - } - - return Promise.all(keys.map(async key => key.keyPacket.validate())); - } - } - - /** - * Clear private key parameters - */ - clearPrivateParams() { - this.getKeys().forEach(({ keyPacket }) => { - if (keyPacket.isDecrypted()) { - keyPacket.clearPrivateParams(); - } - }); - } - - /** - * Revokes the key - * @param {Object} reasonForRevocation - optional, object indicating the reason for revocation - * @param {module:enums.reasonForRevocation} reasonForRevocation.flag optional, flag indicating the reason for revocation - * @param {String} reasonForRevocation.string optional, string explaining the reason for revocation - * @param {Date} date - optional, override the creationtime of the revocation signature - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New key with revocation signature. - * @async - */ - async revoke( - { - flag: reasonForRevocationFlag = enums.reasonForRevocation.noReason, - string: reasonForRevocationString = '' - } = {}, - date = new Date(), - config = defaultConfig - ) { - if (!this.isPrivate()) { - throw new Error('Need private key for revoking'); - } - const dataToSign = { key: this.keyPacket }; - const key = this.clone(); - key.revocationSignatures.push(await createSignaturePacket(dataToSign, null, this.keyPacket, { - signatureType: enums.signature.keyRevocation, - reasonForRevocationFlag: enums.write(enums.reasonForRevocation, reasonForRevocationFlag), - reasonForRevocationString - }, date, undefined, undefined, config)); - return key; - } - - - /** - * Generates a new OpenPGP subkey, and returns a clone of the Key object with the new subkey added. - * Supports RSA and ECC keys. Defaults to the algorithm and bit size/curve of the primary key. DSA primary keys default to RSA subkeys. - * @param {ecc|rsa} options.type The subkey algorithm: ECC or RSA - * @param {String} options.curve (optional) Elliptic curve for ECC keys - * @param {Integer} options.rsaBits (optional) Number of bits for RSA subkeys - * @param {Number} options.keyExpirationTime (optional) Number of seconds from the key creation time after which the key expires - * @param {Date} options.date (optional) Override the creation date of the key and the key signatures - * @param {Boolean} options.sign (optional) Indicates whether the subkey should sign rather than encrypt. Defaults to false - * @param {Object} options.config (optional) custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} - * @async - */ - async addSubkey(options = {}) { - const config = { ...defaultConfig, ...options.config }; - if (options.passphrase) { - throw new Error('Subkey could not be encrypted here, please encrypt whole key'); - } - if (options.rsaBits < config.minRSABits) { - throw new Error(`rsaBits should be at least ${config.minRSABits}, got: ${options.rsaBits}`); - } - const secretKeyPacket = this.keyPacket; - if (secretKeyPacket.isDummy()) { - throw new Error('Cannot add subkey to gnu-dummy primary key'); - } - if (!secretKeyPacket.isDecrypted()) { - throw new Error('Key is not decrypted'); - } - const defaultOptions = secretKeyPacket.getAlgorithmInfo(); - defaultOptions.type = defaultOptions.curve ? 'ecc' : 'rsa'; // DSA keys default to RSA - defaultOptions.rsaBits = defaultOptions.bits || 4096; - defaultOptions.curve = defaultOptions.curve || 'curve25519'; - options = sanitizeKeyOptions(options, defaultOptions); - const keyPacket = await generateSecretSubkey(options); - checkKeyRequirements(keyPacket, config); - const bindingSignature = await createBindingSignature(keyPacket, secretKeyPacket, options, config); - const packetList = this.toPacketList(); - packetList.push(keyPacket, bindingSignature); - return new PrivateKey(packetList); - } - } - - // OpenPGP.js - An OpenPGP implementation in javascript - - // A Key can contain the following packets - const allowedKeyPackets = /*#__PURE__*/ util.constructAllowedPackets([ - PublicKeyPacket, - PublicSubkeyPacket, - SecretKeyPacket, - SecretSubkeyPacket, - UserIDPacket, - UserAttributePacket, - SignaturePacket - ]); - - /** - * Generates a new OpenPGP key. Supports RSA and ECC keys. - * By default, primary and subkeys will be of same type. - * @param {ecc|rsa} options.type The primary key algorithm type: ECC or RSA - * @param {String} options.curve Elliptic curve for ECC keys - * @param {Integer} options.rsaBits Number of bits for RSA keys - * @param {Array} options.userIDs User IDs as strings or objects: 'Jo Doe ' or { name:'Jo Doe', email:'info@jo.com' } - * @param {String} options.passphrase Passphrase used to encrypt the resulting private key - * @param {Number} options.keyExpirationTime (optional) Number of seconds from the key creation time after which the key expires - * @param {Date} options.date Creation date of the key and the key signatures - * @param {Object} config - Full configuration - * @param {Array} options.subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}] - * sign parameter defaults to false, and indicates whether the subkey should sign rather than encrypt - * @returns {Promise<{{ key: PrivateKey, revocationCertificate: String }}>} - * @async - * @static - * @private - */ - async function generate$2(options, config) { - options.sign = true; // primary key is always a signing key - options = sanitizeKeyOptions(options); - options.subkeys = options.subkeys.map((subkey, index) => sanitizeKeyOptions(options.subkeys[index], options)); - let promises = [generateSecretKey(options, config)]; - promises = promises.concat(options.subkeys.map(options => generateSecretSubkey(options, config))); - const packets = await Promise.all(promises); - - const key = await wrapKeyObject(packets[0], packets.slice(1), options, config); - const revocationCertificate = await key.getRevocationCertificate(options.date, config); - key.revocationSignatures = []; - return { key, revocationCertificate }; - } - - /** - * Reformats and signs an OpenPGP key with a given User ID. Currently only supports RSA keys. - * @param {PrivateKey} options.privateKey The private key to reformat - * @param {Array} options.userIDs User IDs as strings or objects: 'Jo Doe ' or { name:'Jo Doe', email:'info@jo.com' } - * @param {String} options.passphrase Passphrase used to encrypt the resulting private key - * @param {Number} options.keyExpirationTime Number of seconds from the key creation time after which the key expires - * @param {Date} options.date Override the creation date of the key signatures - * @param {Array} options.subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}] - * @param {Object} config - Full configuration - * - * @returns {Promise<{{ key: PrivateKey, revocationCertificate: String }}>} - * @async - * @static - * @private - */ - async function reformat(options, config) { - options = sanitize(options); - const { privateKey } = options; - - if (!privateKey.isPrivate()) { - throw new Error('Cannot reformat a public key'); - } - - if (privateKey.keyPacket.isDummy()) { - throw new Error('Cannot reformat a gnu-dummy primary key'); - } - - const isDecrypted = privateKey.getKeys().every(({ keyPacket }) => keyPacket.isDecrypted()); - if (!isDecrypted) { - throw new Error('Key is not decrypted'); - } - - const secretKeyPacket = privateKey.keyPacket; - - if (!options.subkeys) { - options.subkeys = await Promise.all(privateKey.subkeys.map(async subkey => { - const secretSubkeyPacket = subkey.keyPacket; - const dataToVerify = { key: secretKeyPacket, bind: secretSubkeyPacket }; - const bindingSignature = await ( - getLatestValidSignature(subkey.bindingSignatures, secretKeyPacket, enums.signature.subkeyBinding, dataToVerify, null, config) - ).catch(() => ({})); - return { - sign: bindingSignature.keyFlags && (bindingSignature.keyFlags[0] & enums.keyFlags.signData) - }; - })); - } - - const secretSubkeyPackets = privateKey.subkeys.map(subkey => subkey.keyPacket); - if (options.subkeys.length !== secretSubkeyPackets.length) { - throw new Error('Number of subkey options does not match number of subkeys'); - } - - options.subkeys = options.subkeys.map(subkeyOptions => sanitize(subkeyOptions, options)); - - const key = await wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options, config); - const revocationCertificate = await key.getRevocationCertificate(options.date, config); - key.revocationSignatures = []; - return { key, revocationCertificate }; - - function sanitize(options, subkeyDefaults = {}) { - options.keyExpirationTime = options.keyExpirationTime || subkeyDefaults.keyExpirationTime; - options.passphrase = util.isString(options.passphrase) ? options.passphrase : subkeyDefaults.passphrase; - options.date = options.date || subkeyDefaults.date; - - return options; - } - } - - /** - * Construct PrivateKey object from the given key packets, add certification signatures and set passphrase protection - * The new key includes a revocation certificate that must be removed before returning the key, otherwise the key is considered revoked. - * @param {SecretKeyPacket} secretKeyPacket - * @param {SecretSubkeyPacket} secretSubkeyPackets - * @param {Object} options - * @param {Object} config - Full configuration - * @returns {PrivateKey} - */ - async function wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options, config) { - // set passphrase protection - if (options.passphrase) { - await secretKeyPacket.encrypt(options.passphrase, config); - } - - await Promise.all(secretSubkeyPackets.map(async function(secretSubkeyPacket, index) { - const subkeyPassphrase = options.subkeys[index].passphrase; - if (subkeyPassphrase) { - await secretSubkeyPacket.encrypt(subkeyPassphrase, config); - } - })); - - const packetlist = new PacketList(); - packetlist.push(secretKeyPacket); - - await Promise.all(options.userIDs.map(async function(userID, index) { - function createPreferredAlgos(algos, preferredAlgo) { - return [preferredAlgo, ...algos.filter(algo => algo !== preferredAlgo)]; - } - - const userIDPacket = UserIDPacket.fromObject(userID); - const dataToSign = {}; - dataToSign.userID = userIDPacket; - dataToSign.key = secretKeyPacket; - const signaturePacket = new SignaturePacket(); - signaturePacket.signatureType = enums.signature.certGeneric; - signaturePacket.publicKeyAlgorithm = secretKeyPacket.algorithm; - signaturePacket.hashAlgorithm = await getPreferredHashAlgo$1(null, secretKeyPacket, undefined, undefined, config); - signaturePacket.keyFlags = [enums.keyFlags.certifyKeys | enums.keyFlags.signData]; - signaturePacket.preferredSymmetricAlgorithms = createPreferredAlgos([ - // prefer aes256, aes128, then aes192 (no WebCrypto support: https://www.chromium.org/blink/webcrypto#TOC-AES-support) - enums.symmetric.aes256, - enums.symmetric.aes128, - enums.symmetric.aes192 - ], config.preferredSymmetricAlgorithm); - if (config.aeadProtect) { - signaturePacket.preferredAEADAlgorithms = createPreferredAlgos([ - enums.aead.eax, - enums.aead.ocb - ], config.preferredAEADAlgorithm); - } - signaturePacket.preferredHashAlgorithms = createPreferredAlgos([ - // prefer fast asm.js implementations (SHA-256) - enums.hash.sha256, - enums.hash.sha512 - ], config.preferredHashAlgorithm); - signaturePacket.preferredCompressionAlgorithms = createPreferredAlgos([ - enums.compression.zlib, - enums.compression.zip, - enums.compression.uncompressed - ], config.preferredCompressionAlgorithm); - if (index === 0) { - signaturePacket.isPrimaryUserID = true; - } - // integrity protection always enabled - signaturePacket.features = [0]; - signaturePacket.features[0] |= enums.features.modificationDetection; - if (config.aeadProtect) { - signaturePacket.features[0] |= enums.features.aead; - } - if (config.v5Keys) { - signaturePacket.features[0] |= enums.features.v5Keys; - } - if (options.keyExpirationTime > 0) { - signaturePacket.keyExpirationTime = options.keyExpirationTime; - signaturePacket.keyNeverExpires = false; - } - await signaturePacket.sign(secretKeyPacket, dataToSign, options.date); - - return { userIDPacket, signaturePacket }; - })).then(list => { - list.forEach(({ userIDPacket, signaturePacket }) => { - packetlist.push(userIDPacket); - packetlist.push(signaturePacket); - }); - }); - - await Promise.all(secretSubkeyPackets.map(async function(secretSubkeyPacket, index) { - const subkeyOptions = options.subkeys[index]; - const subkeySignaturePacket = await createBindingSignature(secretSubkeyPacket, secretKeyPacket, subkeyOptions, config); - return { secretSubkeyPacket, subkeySignaturePacket }; - })).then(packets => { - packets.forEach(({ secretSubkeyPacket, subkeySignaturePacket }) => { - packetlist.push(secretSubkeyPacket); - packetlist.push(subkeySignaturePacket); - }); - }); - - // Add revocation signature packet for creating a revocation certificate. - // This packet should be removed before returning the key. - const dataToSign = { key: secretKeyPacket }; - packetlist.push(await createSignaturePacket(dataToSign, null, secretKeyPacket, { - signatureType: enums.signature.keyRevocation, - reasonForRevocationFlag: enums.reasonForRevocation.noReason, - reasonForRevocationString: '' - }, options.date, undefined, undefined, config)); - - if (options.passphrase) { - secretKeyPacket.clearPrivateParams(); - } - - await Promise.all(secretSubkeyPackets.map(async function(secretSubkeyPacket, index) { - const subkeyPassphrase = options.subkeys[index].passphrase; - if (subkeyPassphrase) { - secretSubkeyPacket.clearPrivateParams(); - } - })); - - return new PrivateKey(packetlist); - } - - /** - * Reads an (optionally armored) OpenPGP key and returns a key object - * @param {Object} options - * @param {String} [options.armoredKey] - Armored key to be parsed - * @param {Uint8Array} [options.binaryKey] - Binary key to be parsed - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} Key object. - * @async - * @static - */ - async function readKey({ armoredKey, binaryKey, config, ...rest }) { - config = { ...defaultConfig, ...config }; - if (!armoredKey && !binaryKey) { - throw new Error('readKey: must pass options object containing `armoredKey` or `binaryKey`'); - } - if (armoredKey && !util.isString(armoredKey)) { - throw new Error('readKey: options.armoredKey must be a string'); - } - if (binaryKey && !util.isUint8Array(binaryKey)) { - throw new Error('readKey: options.binaryKey must be a Uint8Array'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - let input; - if (armoredKey) { - const { type, data } = await unarmor(armoredKey, config); - if (!(type === enums.armor.publicKey || type === enums.armor.privateKey)) { - throw new Error('Armored text not of type key'); - } - input = data; - } else { - input = binaryKey; - } - const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); - return createKey(packetlist); - } - - /** - * Reads an (optionally armored) OpenPGP private key and returns a PrivateKey object - * @param {Object} options - * @param {String} [options.armoredKey] - Armored key to be parsed - * @param {Uint8Array} [options.binaryKey] - Binary key to be parsed - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} Key object. - * @async - * @static - */ - async function readPrivateKey({ armoredKey, binaryKey, config, ...rest }) { - config = { ...defaultConfig, ...config }; - if (!armoredKey && !binaryKey) { - throw new Error('readPrivateKey: must pass options object containing `armoredKey` or `binaryKey`'); - } - if (armoredKey && !util.isString(armoredKey)) { - throw new Error('readPrivateKey: options.armoredKey must be a string'); - } - if (binaryKey && !util.isUint8Array(binaryKey)) { - throw new Error('readPrivateKey: options.binaryKey must be a Uint8Array'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - let input; - if (armoredKey) { - const { type, data } = await unarmor(armoredKey, config); - if (!(type === enums.armor.privateKey)) { - throw new Error('Armored text not of type private key'); - } - input = data; - } else { - input = binaryKey; - } - const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); - return new PrivateKey(packetlist); - } - - /** - * Reads an (optionally armored) OpenPGP key block and returns a list of key objects - * @param {Object} options - * @param {String} [options.armoredKeys] - Armored keys to be parsed - * @param {Uint8Array} [options.binaryKeys] - Binary keys to be parsed - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise>} Key objects. - * @async - * @static - */ - async function readKeys({ armoredKeys, binaryKeys, config, ...rest }) { - config = { ...defaultConfig, ...config }; - let input = armoredKeys || binaryKeys; - if (!input) { - throw new Error('readKeys: must pass options object containing `armoredKeys` or `binaryKeys`'); - } - if (armoredKeys && !util.isString(armoredKeys)) { - throw new Error('readKeys: options.armoredKeys must be a string'); - } - if (binaryKeys && !util.isUint8Array(binaryKeys)) { - throw new Error('readKeys: options.binaryKeys must be a Uint8Array'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (armoredKeys) { - const { type, data } = await unarmor(armoredKeys, config); - if (type !== enums.armor.publicKey && type !== enums.armor.privateKey) { - throw new Error('Armored text not of type key'); - } - input = data; - } - const keys = []; - const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); - const keyIndex = packetlist.indexOfTag(enums.packet.publicKey, enums.packet.secretKey); - if (keyIndex.length === 0) { - throw new Error('No key packet found'); - } - for (let i = 0; i < keyIndex.length; i++) { - const oneKeyList = packetlist.slice(keyIndex[i], keyIndex[i + 1]); - const newKey = createKey(oneKeyList); - keys.push(newKey); - } - return keys; - } - - /** - * Reads an (optionally armored) OpenPGP private key block and returns a list of PrivateKey objects - * @param {Object} options - * @param {String} [options.armoredKeys] - Armored keys to be parsed - * @param {Uint8Array} [options.binaryKeys] - Binary keys to be parsed - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise>} Key objects. - * @async - * @static - */ - async function readPrivateKeys({ armoredKeys, binaryKeys, config }) { - config = { ...defaultConfig, ...config }; - let input = armoredKeys || binaryKeys; - if (!input) { - throw new Error('readPrivateKeys: must pass options object containing `armoredKeys` or `binaryKeys`'); - } - if (armoredKeys && !util.isString(armoredKeys)) { - throw new Error('readPrivateKeys: options.armoredKeys must be a string'); - } - if (binaryKeys && !util.isUint8Array(binaryKeys)) { - throw new Error('readPrivateKeys: options.binaryKeys must be a Uint8Array'); - } - if (armoredKeys) { - const { type, data } = await unarmor(armoredKeys, config); - if (type !== enums.armor.privateKey) { - throw new Error('Armored text not of type private key'); - } - input = data; - } - const keys = []; - const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); - const keyIndex = packetlist.indexOfTag(enums.packet.secretKey); - if (keyIndex.length === 0) { - throw new Error('No secret key packet found'); - } - for (let i = 0; i < keyIndex.length; i++) { - const oneKeyList = packetlist.slice(keyIndex[i], keyIndex[i + 1]); - const newKey = new PrivateKey(oneKeyList); - keys.push(newKey); - } - return keys; - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - // A Message can contain the following packets - const allowedMessagePackets = /*#__PURE__*/ util.constructAllowedPackets([ - LiteralDataPacket, - CompressedDataPacket, - AEADEncryptedDataPacket, - SymEncryptedIntegrityProtectedDataPacket, - SymmetricallyEncryptedDataPacket, - PublicKeyEncryptedSessionKeyPacket, - SymEncryptedSessionKeyPacket, - OnePassSignaturePacket, - SignaturePacket - ]); - // A SKESK packet can contain the following packets - const allowedSymSessionKeyPackets = /*#__PURE__*/ util.constructAllowedPackets([SymEncryptedSessionKeyPacket]); - // A detached signature can contain the following packets - const allowedDetachedSignaturePackets = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); - - /** - * Class that represents an OpenPGP message. - * Can be an encrypted message, signed message, compressed message or literal message - * See {@link https://tools.ietf.org/html/rfc4880#section-11.3} - */ - class Message { - /** - * @param {PacketList} packetlist - The packets that form this message - */ - constructor(packetlist) { - this.packets = packetlist || new PacketList(); - } - - /** - * Returns the key IDs of the keys to which the session key is encrypted - * @returns {Array} Array of keyID objects. - */ - getEncryptionKeyIDs() { - const keyIDs = []; - const pkESKeyPacketlist = this.packets.filterByTag(enums.packet.publicKeyEncryptedSessionKey); - pkESKeyPacketlist.forEach(function(packet) { - keyIDs.push(packet.publicKeyID); - }); - return keyIDs; - } - - /** - * Returns the key IDs of the keys that signed the message - * @returns {Array} Array of keyID objects. - */ - getSigningKeyIDs() { - const msg = this.unwrapCompressed(); - // search for one pass signatures - const onePassSigList = msg.packets.filterByTag(enums.packet.onePassSignature); - if (onePassSigList.length > 0) { - return onePassSigList.map(packet => packet.issuerKeyID); - } - // if nothing found look for signature packets - const signatureList = msg.packets.filterByTag(enums.packet.signature); - return signatureList.map(packet => packet.issuerKeyID); - } - - /** - * Decrypt the message. Either a private key, a session key, or a password must be specified. - * @param {Array} [decryptionKeys] - Private keys with decrypted secret data - * @param {Array} [passwords] - Passwords used to decrypt - * @param {Array} [sessionKeys] - Session keys in the form: { data:Uint8Array, algorithm:String, [aeadAlgorithm:String] } - * @param {Date} [date] - Use the given date for key verification instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New message with decrypted content. - * @async - */ - async decrypt(decryptionKeys, passwords, sessionKeys, date = new Date(), config = defaultConfig) { - const sessionKeyObjects = sessionKeys || await this.decryptSessionKeys(decryptionKeys, passwords, date, config); - - const symEncryptedPacketlist = this.packets.filterByTag( - enums.packet.symmetricallyEncryptedData, - enums.packet.symEncryptedIntegrityProtectedData, - enums.packet.aeadEncryptedData - ); - - if (symEncryptedPacketlist.length === 0) { - return this; - } - - const symEncryptedPacket = symEncryptedPacketlist[0]; - let exception = null; - const decryptedPromise = Promise.all(sessionKeyObjects.map(async ({ algorithm: algorithmName, data }) => { - if (!util.isUint8Array(data) || !util.isString(algorithmName)) { - throw new Error('Invalid session key for decryption.'); - } - - try { - const algo = enums.write(enums.symmetric, algorithmName); - await symEncryptedPacket.decrypt(algo, data, config); - } catch (e) { - util.printDebugError(e); - exception = e; - } - })); - // We don't await stream.cancel here because it only returns when the other copy is canceled too. - cancel(symEncryptedPacket.encrypted); // Don't keep copy of encrypted data in memory. - symEncryptedPacket.encrypted = null; - await decryptedPromise; - - if (!symEncryptedPacket.packets || !symEncryptedPacket.packets.length) { - throw exception || new Error('Decryption failed.'); - } - - const resultMsg = new Message(symEncryptedPacket.packets); - symEncryptedPacket.packets = new PacketList(); // remove packets after decryption - - return resultMsg; - } - - /** - * Decrypt encrypted session keys either with private keys or passwords. - * @param {Array} [decryptionKeys] - Private keys with decrypted secret data - * @param {Array} [passwords] - Passwords used to decrypt - * @param {Date} [date] - Use the given date for key verification, instead of current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise>} array of object with potential sessionKey, algorithm pairs - * @async - */ - async decryptSessionKeys(decryptionKeys, passwords, date = new Date(), config = defaultConfig) { - let decryptedSessionKeyPackets = []; - - let exception; - if (passwords) { - const skeskPackets = this.packets.filterByTag(enums.packet.symEncryptedSessionKey); - if (skeskPackets.length === 0) { - throw new Error('No symmetrically encrypted session key packet found.'); - } - await Promise.all(passwords.map(async function(password, i) { - let packets; - if (i) { - packets = await PacketList.fromBinary(skeskPackets.write(), allowedSymSessionKeyPackets, config); - } else { - packets = skeskPackets; - } - await Promise.all(packets.map(async function(skeskPacket) { - try { - await skeskPacket.decrypt(password); - decryptedSessionKeyPackets.push(skeskPacket); - } catch (err) { - util.printDebugError(err); - } - })); - })); - } else if (decryptionKeys) { - const pkeskPackets = this.packets.filterByTag(enums.packet.publicKeyEncryptedSessionKey); - if (pkeskPackets.length === 0) { - throw new Error('No public key encrypted session key packet found.'); - } - await Promise.all(pkeskPackets.map(async function(pkeskPacket) { - await Promise.all(decryptionKeys.map(async function(decryptionKey) { - let algos = [ - enums.symmetric.aes256, // Old OpenPGP.js default fallback - enums.symmetric.aes128, // RFC4880bis fallback - enums.symmetric.tripledes, // RFC4880 fallback - enums.symmetric.cast5 // Golang OpenPGP fallback - ]; - try { - const primaryUser = await decryptionKey.getPrimaryUser(date, undefined, config); // TODO: Pass userID from somewhere. - if (primaryUser.selfCertification.preferredSymmetricAlgorithms) { - algos = algos.concat(primaryUser.selfCertification.preferredSymmetricAlgorithms); - } - } catch (e) {} - - // do not check key expiration to allow decryption of old messages - const decryptionKeyPackets = (await decryptionKey.getDecryptionKeys(pkeskPacket.publicKeyID, null, undefined, config)).map(key => key.keyPacket); - await Promise.all(decryptionKeyPackets.map(async function(decryptionKeyPacket) { - if (!decryptionKeyPacket || decryptionKeyPacket.isDummy()) { - return; - } - if (!decryptionKeyPacket.isDecrypted()) { - throw new Error('Decryption key is not decrypted.'); - } - - // To hinder CCA attacks against PKCS1, we carry out a constant-time decryption flow if the `constantTimePKCS1Decryption` config option is set. - const doConstantTimeDecryption = config.constantTimePKCS1Decryption && ( - pkeskPacket.publicKeyAlgorithm === enums.publicKey.rsaEncrypt || - pkeskPacket.publicKeyAlgorithm === enums.publicKey.rsaEncryptSign || - pkeskPacket.publicKeyAlgorithm === enums.publicKey.rsaSign || - pkeskPacket.publicKeyAlgorithm === enums.publicKey.elgamal - ); - - if (doConstantTimeDecryption) { - // The goal is to not reveal whether PKESK decryption (specifically the PKCS1 decoding step) failed, hence, we always proceed to decrypt the message, - // either with the successfully decrypted session key, or with a randomly generated one. - // Since the SEIP/AEAD's symmetric algorithm and key size are stored in the encrypted portion of the PKESK, and the execution flow cannot depend on - // the decrypted payload, we always assume the message to be encrypted with one of the symmetric algorithms specified in `config.constantTimePKCS1DecryptionSupportedSymmetricAlgorithms`: - // - If the PKESK decryption succeeds, and the session key cipher is in the supported set, then we try to decrypt the data with the decrypted session key as well as with the - // randomly generated keys of the remaining key types. - // - If the PKESK decryptions fails, or if it succeeds but support for the cipher is not enabled, then we discard the session key and try to decrypt the data using only the randomly - // generated session keys. - // NB: as a result, if the data is encrypted with a non-suported cipher, decryption will always fail. - - const serialisedPKESK = pkeskPacket.write(); // make copies to be able to decrypt the PKESK packet multiple times - await Promise.all(Array.from(config.constantTimePKCS1DecryptionSupportedSymmetricAlgorithms).map(async sessionKeyAlgorithm => { - const pkeskPacketCopy = new PublicKeyEncryptedSessionKeyPacket(); - pkeskPacketCopy.read(serialisedPKESK); - const randomSessionKey = { - sessionKeyAlgorithm, - sessionKey: await mod.generateSessionKey(sessionKeyAlgorithm) - }; - try { - await pkeskPacketCopy.decrypt(decryptionKeyPacket, randomSessionKey); - decryptedSessionKeyPackets.push(pkeskPacketCopy); - } catch (err) { - // `decrypt` can still throw some non-security-sensitive errors - util.printDebugError(err); - exception = err; - } - })); - - } else { - try { - await pkeskPacket.decrypt(decryptionKeyPacket); - if (!algos.includes(enums.write(enums.symmetric, pkeskPacket.sessionKeyAlgorithm))) { - throw new Error('A non-preferred symmetric algorithm was used.'); - } - decryptedSessionKeyPackets.push(pkeskPacket); - } catch (err) { - util.printDebugError(err); - exception = err; - } - } - })); - })); - cancel(pkeskPacket.encrypted); // Don't keep copy of encrypted data in memory. - pkeskPacket.encrypted = null; - })); - } else { - throw new Error('No key or password specified.'); - } - - if (decryptedSessionKeyPackets.length > 0) { - // Return only unique session keys - if (decryptedSessionKeyPackets.length > 1) { - const seen = new Set(); - decryptedSessionKeyPackets = decryptedSessionKeyPackets.filter(item => { - const k = item.sessionKeyAlgorithm + util.uint8ArrayToString(item.sessionKey); - if (seen.has(k)) { - return false; - } - seen.add(k); - return true; - }); - } - - return decryptedSessionKeyPackets.map(packet => ({ - data: packet.sessionKey, - algorithm: enums.read(enums.symmetric, packet.sessionKeyAlgorithm) - })); - } - throw exception || new Error('Session key decryption failed.'); - } - - /** - * Get literal data that is the body of the message - * @returns {(Uint8Array|null)} Literal body of the message as Uint8Array. - */ - getLiteralData() { - const msg = this.unwrapCompressed(); - const literal = msg.packets.findPacket(enums.packet.literalData); - return (literal && literal.getBytes()) || null; - } - - /** - * Get filename from literal data packet - * @returns {(String|null)} Filename of literal data packet as string. - */ - getFilename() { - const msg = this.unwrapCompressed(); - const literal = msg.packets.findPacket(enums.packet.literalData); - return (literal && literal.getFilename()) || null; - } - - /** - * Get literal data as text - * @returns {(String|null)} Literal body of the message interpreted as text. - */ - getText() { - const msg = this.unwrapCompressed(); - const literal = msg.packets.findPacket(enums.packet.literalData); - if (literal) { - return literal.getText(); - } - return null; - } - - /** - * Generate a new session key object, taking the algorithm preferences of the passed encryption keys into account, if any. - * @param {Array} [encryptionKeys] - Public key(s) to select algorithm preferences for - * @param {Date} [date] - Date to select algorithm preferences at - * @param {Array} [userIDs] - User IDs to select algorithm preferences for - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise<{ data: Uint8Array, algorithm: String, aeadAlgorithm: undefined|String }>} Object with session key data and algorithms. - * @async - */ - static async generateSessionKey(encryptionKeys = [], date = new Date(), userIDs = [], config = defaultConfig) { - const algo = await getPreferredAlgo('symmetric', encryptionKeys, date, userIDs, config); - const algorithmName = enums.read(enums.symmetric, algo); - const aeadAlgorithmName = config.aeadProtect && await isAEADSupported(encryptionKeys, date, userIDs, config) ? - enums.read(enums.aead, await getPreferredAlgo('aead', encryptionKeys, date, userIDs, config)) : - undefined; - - const sessionKeyData = await mod.generateSessionKey(algo); - return { data: sessionKeyData, algorithm: algorithmName, aeadAlgorithm: aeadAlgorithmName }; - } - - /** - * Encrypt the message either with public keys, passwords, or both at once. - * @param {Array} [encryptionKeys] - Public key(s) for message encryption - * @param {Array} [passwords] - Password(s) for message encryption - * @param {Object} [sessionKey] - Session key in the form: { data:Uint8Array, algorithm:String, [aeadAlgorithm:String] } - * @param {Boolean} [wildcard] - Use a key ID of 0 instead of the public key IDs - * @param {Array} [encryptionKeyIDs] - Array of key IDs to use for encryption. Each encryptionKeyIDs[i] corresponds to keys[i] - * @param {Date} [date] - Override the creation date of the literal package - * @param {Array} [userIDs] - User IDs to encrypt for, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }] - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New message with encrypted content. - * @async - */ - async encrypt(encryptionKeys, passwords, sessionKey, wildcard = false, encryptionKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { - if (sessionKey) { - if (!util.isUint8Array(sessionKey.data) || !util.isString(sessionKey.algorithm)) { - throw new Error('Invalid session key for encryption.'); - } - } else if (encryptionKeys && encryptionKeys.length) { - sessionKey = await Message.generateSessionKey(encryptionKeys, date, userIDs, config); - } else if (passwords && passwords.length) { - sessionKey = await Message.generateSessionKey(undefined, undefined, undefined, config); - } else { - throw new Error('No keys, passwords, or session key provided.'); - } - - const { data: sessionKeyData, algorithm: algorithmName, aeadAlgorithm: aeadAlgorithmName } = sessionKey; - - const msg = await Message.encryptSessionKey(sessionKeyData, algorithmName, aeadAlgorithmName, encryptionKeys, passwords, wildcard, encryptionKeyIDs, date, userIDs, config); - - let symEncryptedPacket; - if (aeadAlgorithmName) { - symEncryptedPacket = new AEADEncryptedDataPacket(); - symEncryptedPacket.aeadAlgorithm = enums.write(enums.aead, aeadAlgorithmName); - } else { - symEncryptedPacket = new SymEncryptedIntegrityProtectedDataPacket(); - } - symEncryptedPacket.packets = this.packets; - - const algorithm = enums.write(enums.symmetric, algorithmName); - await symEncryptedPacket.encrypt(algorithm, sessionKeyData, config); - - msg.packets.push(symEncryptedPacket); - symEncryptedPacket.packets = new PacketList(); // remove packets after encryption - return msg; - } - - /** - * Encrypt a session key either with public keys, passwords, or both at once. - * @param {Uint8Array} sessionKey - session key for encryption - * @param {String} algorithmName - session key algorithm - * @param {String} [aeadAlgorithmName] - AEAD algorithm, e.g. 'eax' or 'ocb' - * @param {Array} [encryptionKeys] - Public key(s) for message encryption - * @param {Array} [passwords] - For message encryption - * @param {Boolean} [wildcard] - Use a key ID of 0 instead of the public key IDs - * @param {Array} [encryptionKeyIDs] - Array of key IDs to use for encryption. Each encryptionKeyIDs[i] corresponds to encryptionKeys[i] - * @param {Date} [date] - Override the date - * @param {Array} [userIDs] - User IDs to encrypt for, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }] - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New message with encrypted content. - * @async - */ - static async encryptSessionKey(sessionKey, algorithmName, aeadAlgorithmName, encryptionKeys, passwords, wildcard = false, encryptionKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { - const packetlist = new PacketList(); - const algorithm = enums.write(enums.symmetric, algorithmName); - const aeadAlgorithm = aeadAlgorithmName && enums.write(enums.aead, aeadAlgorithmName); - - if (encryptionKeys) { - const results = await Promise.all(encryptionKeys.map(async function(primaryKey, i) { - const encryptionKey = await primaryKey.getEncryptionKey(encryptionKeyIDs[i], date, userIDs, config); - const pkESKeyPacket = new PublicKeyEncryptedSessionKeyPacket(); - pkESKeyPacket.publicKeyID = wildcard ? KeyID.wildcard() : encryptionKey.getKeyID(); - pkESKeyPacket.publicKeyAlgorithm = encryptionKey.keyPacket.algorithm; - pkESKeyPacket.sessionKey = sessionKey; - pkESKeyPacket.sessionKeyAlgorithm = algorithm; - await pkESKeyPacket.encrypt(encryptionKey.keyPacket); - delete pkESKeyPacket.sessionKey; // delete plaintext session key after encryption - return pkESKeyPacket; - })); - packetlist.push(...results); - } - if (passwords) { - const testDecrypt = async function(keyPacket, password) { - try { - await keyPacket.decrypt(password); - return 1; - } catch (e) { - return 0; - } - }; - - const sum = (accumulator, currentValue) => accumulator + currentValue; - - const encryptPassword = async function(sessionKey, algorithm, aeadAlgorithm, password) { - const symEncryptedSessionKeyPacket = new SymEncryptedSessionKeyPacket(config); - symEncryptedSessionKeyPacket.sessionKey = sessionKey; - symEncryptedSessionKeyPacket.sessionKeyAlgorithm = algorithm; - if (aeadAlgorithm) { - symEncryptedSessionKeyPacket.aeadAlgorithm = aeadAlgorithm; - } - await symEncryptedSessionKeyPacket.encrypt(password, config); - - if (config.passwordCollisionCheck) { - const results = await Promise.all(passwords.map(pwd => testDecrypt(symEncryptedSessionKeyPacket, pwd))); - if (results.reduce(sum) !== 1) { - return encryptPassword(sessionKey, algorithm, password); - } - } - - delete symEncryptedSessionKeyPacket.sessionKey; // delete plaintext session key after encryption - return symEncryptedSessionKeyPacket; - }; - - const results = await Promise.all(passwords.map(pwd => encryptPassword(sessionKey, algorithm, aeadAlgorithm, pwd))); - packetlist.push(...results); - } - - return new Message(packetlist); - } - - /** - * Sign the message (the literal data packet of the message) - * @param {Array} signingKeys - private keys with decrypted secret key data for signing - * @param {Signature} [signature] - Any existing detached signature to add to the message - * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] - * @param {Date} [date] - Override the creation time of the signature - * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New message with signed content. - * @async - */ - async sign(signingKeys = [], signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { - const packetlist = new PacketList(); - - const literalDataPacket = this.packets.findPacket(enums.packet.literalData); - if (!literalDataPacket) { - throw new Error('No literal data packet to sign.'); - } - - let i; - let existingSigPacketlist; - // If data packet was created from Uint8Array, use binary, otherwise use text - const signatureType = literalDataPacket.text === null ? - enums.signature.binary : enums.signature.text; - - if (signature) { - existingSigPacketlist = signature.packets.filterByTag(enums.packet.signature); - for (i = existingSigPacketlist.length - 1; i >= 0; i--) { - const signaturePacket = existingSigPacketlist[i]; - const onePassSig = new OnePassSignaturePacket(); - onePassSig.signatureType = signaturePacket.signatureType; - onePassSig.hashAlgorithm = signaturePacket.hashAlgorithm; - onePassSig.publicKeyAlgorithm = signaturePacket.publicKeyAlgorithm; - onePassSig.issuerKeyID = signaturePacket.issuerKeyID; - if (!signingKeys.length && i === 0) { - onePassSig.flags = 1; - } - packetlist.push(onePassSig); - } - } - - await Promise.all(Array.from(signingKeys).reverse().map(async function (primaryKey, i) { - if (!primaryKey.isPrivate()) { - throw new Error('Need private key for signing'); - } - const signingKeyID = signingKeyIDs[signingKeys.length - 1 - i]; - const signingKey = await primaryKey.getSigningKey(signingKeyID, date, userIDs, config); - const onePassSig = new OnePassSignaturePacket(); - onePassSig.signatureType = signatureType; - onePassSig.hashAlgorithm = await getPreferredHashAlgo$1(primaryKey, signingKey.keyPacket, date, userIDs, config); - onePassSig.publicKeyAlgorithm = signingKey.keyPacket.algorithm; - onePassSig.issuerKeyID = signingKey.getKeyID(); - if (i === signingKeys.length - 1) { - onePassSig.flags = 1; - } - return onePassSig; - })).then(onePassSignatureList => { - onePassSignatureList.forEach(onePassSig => packetlist.push(onePassSig)); - }); - - packetlist.push(literalDataPacket); - packetlist.push(...(await createSignaturePackets(literalDataPacket, signingKeys, signature, signingKeyIDs, date, userIDs, false, config))); - - return new Message(packetlist); - } - - /** - * Compresses the message (the literal and -if signed- signature data packets of the message) - * @param {module:enums.compression} algo - compression algorithm - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Message} New message with compressed content. - */ - compress(algo, config = defaultConfig) { - if (algo === enums.compression.uncompressed) { - return this; - } - - const compressed = new CompressedDataPacket(config); - compressed.algorithm = algo; - compressed.packets = this.packets; - - const packetList = new PacketList(); - packetList.push(compressed); - - return new Message(packetList); - } - - /** - * Create a detached signature for the message (the literal data packet of the message) - * @param {Array} signingKeys - private keys with decrypted secret key data for signing - * @param {Signature} [signature] - Any existing detached signature - * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] - * @param {Date} [date] - Override the creation time of the signature - * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New detached signature of message content. - * @async - */ - async signDetached(signingKeys = [], signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { - const literalDataPacket = this.packets.findPacket(enums.packet.literalData); - if (!literalDataPacket) { - throw new Error('No literal data packet to sign.'); - } - return new Signature(await createSignaturePackets(literalDataPacket, signingKeys, signature, signingKeyIDs, date, userIDs, true, config)); - } - - /** - * Verify message signatures - * @param {Array} verificationKeys - Array of public keys to verify signatures - * @param {Date} [date] - Verify the signature against the given date, i.e. check signature creation time < date < expiration time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise, - * verified: Promise - * }>>} List of signer's keyID and validity of signatures. - * @async - */ - async verify(verificationKeys, date = new Date(), config = defaultConfig) { - const msg = this.unwrapCompressed(); - const literalDataList = msg.packets.filterByTag(enums.packet.literalData); - if (literalDataList.length !== 1) { - throw new Error('Can only verify message with one literal data packet.'); - } - if (isArrayStream(msg.packets.stream)) { - msg.packets.push(...await readToEnd(msg.packets.stream, _ => _ || [])); - } - const onePassSigList = msg.packets.filterByTag(enums.packet.onePassSignature).reverse(); - const signatureList = msg.packets.filterByTag(enums.packet.signature); - if (onePassSigList.length && !signatureList.length && util.isStream(msg.packets.stream) && !isArrayStream(msg.packets.stream)) { - await Promise.all(onePassSigList.map(async onePassSig => { - onePassSig.correspondingSig = new Promise((resolve, reject) => { - onePassSig.correspondingSigResolve = resolve; - onePassSig.correspondingSigReject = reject; - }); - onePassSig.signatureData = fromAsync(async () => (await onePassSig.correspondingSig).signatureData); - onePassSig.hashed = readToEnd(await onePassSig.hash(onePassSig.signatureType, literalDataList[0], undefined, false)); - onePassSig.hashed.catch(() => {}); - })); - msg.packets.stream = transformPair(msg.packets.stream, async (readable, writable) => { - const reader = getReader(readable); - const writer = getWriter(writable); - try { - for (let i = 0; i < onePassSigList.length; i++) { - const { value: signature } = await reader.read(); - onePassSigList[i].correspondingSigResolve(signature); - } - await reader.readToEnd(); - await writer.ready; - await writer.close(); - } catch (e) { - onePassSigList.forEach(onePassSig => { - onePassSig.correspondingSigReject(e); - }); - await writer.abort(e); - } - }); - return createVerificationObjects(onePassSigList, literalDataList, verificationKeys, date, false, config); - } - return createVerificationObjects(signatureList, literalDataList, verificationKeys, date, false, config); - } - - /** - * Verify detached message signature - * @param {Array} verificationKeys - Array of public keys to verify signatures - * @param {Signature} signature - * @param {Date} date - Verify the signature against the given date, i.e. check signature creation time < date < expiration time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise, - * verified: Promise - * }>>} List of signer's keyID and validity of signature. - * @async - */ - verifyDetached(signature, verificationKeys, date = new Date(), config = defaultConfig) { - const msg = this.unwrapCompressed(); - const literalDataList = msg.packets.filterByTag(enums.packet.literalData); - if (literalDataList.length !== 1) { - throw new Error('Can only verify message with one literal data packet.'); - } - const signatureList = signature.packets; - return createVerificationObjects(signatureList, literalDataList, verificationKeys, date, true, config); - } - - /** - * Unwrap compressed message - * @returns {Message} Message Content of compressed message. - */ - unwrapCompressed() { - const compressed = this.packets.filterByTag(enums.packet.compressedData); - if (compressed.length) { - return new Message(compressed[0].packets); - } - return this; - } - - /** - * Append signature to unencrypted message object - * @param {String|Uint8Array} detachedSignature - The detached ASCII-armored or Uint8Array PGP signature - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - async appendSignature(detachedSignature, config = defaultConfig) { - await this.packets.read( - util.isUint8Array(detachedSignature) ? detachedSignature : (await unarmor(detachedSignature)).data, - allowedDetachedSignaturePackets, - config - ); - } - - /** - * Returns binary encoded message - * @returns {ReadableStream} Binary message. - */ - write() { - return this.packets.write(); - } - - /** - * Returns ASCII armored text of message - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {ReadableStream} ASCII armor. - */ - armor(config = defaultConfig) { - return armor(enums.armor.message, this.write(), null, null, null, config); - } - } - - /** - * Create signature packets for the message - * @param {LiteralDataPacket} literalDataPacket - the literal data packet to sign - * @param {Array} [signingKeys] - private keys with decrypted secret key data for signing - * @param {Signature} [signature] - Any existing detached signature to append - * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] - * @param {Date} [date] - Override the creationtime of the signature - * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] - * @param {Boolean} [detached] - Whether to create detached signature packets - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} List of signature packets. - * @async - * @private - */ - async function createSignaturePackets(literalDataPacket, signingKeys, signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], detached = false, config = defaultConfig) { - const packetlist = new PacketList(); - - // If data packet was created from Uint8Array, use binary, otherwise use text - const signatureType = literalDataPacket.text === null ? - enums.signature.binary : enums.signature.text; - - await Promise.all(signingKeys.map(async (primaryKey, i) => { - const userID = userIDs[i]; - if (!primaryKey.isPrivate()) { - throw new Error('Need private key for signing'); - } - const signingKey = await primaryKey.getSigningKey(signingKeyIDs[i], date, userID, config); - return createSignaturePacket(literalDataPacket, primaryKey, signingKey.keyPacket, { signatureType }, date, userID, detached, config); - })).then(signatureList => { - packetlist.push(...signatureList); - }); - - if (signature) { - const existingSigPacketlist = signature.packets.filterByTag(enums.packet.signature); - packetlist.push(...existingSigPacketlist); - } - return packetlist; - } - - /** - * Create object containing signer's keyID and validity of signature - * @param {SignaturePacket} signature - Signature packet - * @param {Array} literalDataList - Array of literal data packets - * @param {Array} verificationKeys - Array of public keys to verify signatures - * @param {Date} [date] - Check signature validity with respect to the given date - * @param {Boolean} [detached] - Whether to verify detached signature packets - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise<{ - * keyID: module:type/keyid~KeyID, - * signature: Promise, - * verified: Promise - * }>} signer's keyID and validity of signature - * @async - * @private - */ - async function createVerificationObject(signature, literalDataList, verificationKeys, date = new Date(), detached = false, config = defaultConfig) { - let primaryKey; - let unverifiedSigningKey; - - for (const key of verificationKeys) { - const issuerKeys = key.getKeys(signature.issuerKeyID); - if (issuerKeys.length > 0) { - primaryKey = key; - unverifiedSigningKey = issuerKeys[0]; - break; - } - } - - const isOnePassSignature = signature instanceof OnePassSignaturePacket; - const signaturePacketPromise = isOnePassSignature ? signature.correspondingSig : signature; - - const verifiedSig = { - keyID: signature.issuerKeyID, - verified: (async () => { - if (!unverifiedSigningKey) { - throw new Error(`Could not find signing key with key ID ${signature.issuerKeyID.toHex()}`); - } - - await signature.verify(unverifiedSigningKey.keyPacket, signature.signatureType, literalDataList[0], date, detached, config); - const signaturePacket = await signaturePacketPromise; - if (unverifiedSigningKey.getCreationTime() > signaturePacket.created) { - throw new Error('Key is newer than the signature'); - } - // We pass the signature creation time to check whether the key was expired at the time of signing. - // We check this after signature verification because for streamed one-pass signatures, the creation time is not available before - try { - await primaryKey.getSigningKey(unverifiedSigningKey.getKeyID(), signaturePacket.created, undefined, config); - } catch (e) { - // If a key was reformatted then the self-signatures of the signing key might be in the future compared to the message signature, - // making the key invalid at the time of signing. - // However, if the key is valid at the given `date`, we still allow using it provided the relevant `config` setting is enabled. - // Note: we do not support the edge case of a key that was reformatted and it has expired. - if (config.allowInsecureVerificationWithReformattedKeys && e.message.match(/Signature creation time is in the future/)) { - await primaryKey.getSigningKey(unverifiedSigningKey.getKeyID(), date, undefined, config); - } else { - throw e; - } - } - return true; - })(), - signature: (async () => { - const signaturePacket = await signaturePacketPromise; - const packetlist = new PacketList(); - signaturePacket && packetlist.push(signaturePacket); - return new Signature(packetlist); - })() - }; - - // Mark potential promise rejections as "handled". This is needed because in - // some cases, we reject them before the user has a reasonable chance to - // handle them (e.g. `await readToEnd(result.data); await result.verified` and - // the data stream errors). - verifiedSig.signature.catch(() => {}); - verifiedSig.verified.catch(() => {}); - - return verifiedSig; - } - - /** - * Create list of objects containing signer's keyID and validity of signature - * @param {Array} signatureList - Array of signature packets - * @param {Array} literalDataList - Array of literal data packets - * @param {Array} verificationKeys - Array of public keys to verify signatures - * @param {Date} date - Verify the signature against the given date, - * i.e. check signature creation time < date < expiration time - * @param {Boolean} [detached] - Whether to verify detached signature packets - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise, - * verified: Promise - * }>>} list of signer's keyID and validity of signatures (one entry per signature packet in input) - * @async - * @private - */ - async function createVerificationObjects(signatureList, literalDataList, verificationKeys, date = new Date(), detached = false, config = defaultConfig) { - return Promise.all(signatureList.filter(function(signature) { - return ['text', 'binary'].includes(enums.read(enums.signature, signature.signatureType)); - }).map(async function(signature) { - return createVerificationObject(signature, literalDataList, verificationKeys, date, detached, config); - })); - } - - /** - * Reads an (optionally armored) OpenPGP message and returns a Message object - * @param {Object} options - * @param {String | ReadableStream} [options.armoredMessage] - Armored message to be parsed - * @param {Uint8Array | ReadableStream} [options.binaryMessage] - Binary to be parsed - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} New message object. - * @async - * @static - */ - async function readMessage({ armoredMessage, binaryMessage, config, ...rest }) { - config = { ...defaultConfig, ...config }; - let input = armoredMessage || binaryMessage; - if (!input) { - throw new Error('readMessage: must pass options object containing `armoredMessage` or `binaryMessage`'); - } - if (armoredMessage && !util.isString(armoredMessage) && !util.isStream(armoredMessage)) { - throw new Error('readMessage: options.armoredMessage must be a string or stream'); - } - if (binaryMessage && !util.isUint8Array(binaryMessage) && !util.isStream(binaryMessage)) { - throw new Error('readMessage: options.binaryMessage must be a Uint8Array or stream'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - const streamType = util.isStream(input); - if (streamType) { - await loadStreamsPonyfill(); - input = toStream(input); - } - if (armoredMessage) { - const { type, data } = await unarmor(input, config); - if (type !== enums.armor.message) { - throw new Error('Armored text not of type message'); - } - input = data; - } - const packetlist = await PacketList.fromBinary(input, allowedMessagePackets, config); - const message = new Message(packetlist); - message.fromStream = streamType; - return message; - } - - /** - * Creates new message object from text or binary data. - * @param {Object} options - * @param {String | ReadableStream} [options.text] - The text message contents - * @param {Uint8Array | ReadableStream} [options.binary] - The binary message contents - * @param {String} [options.filename=""] - Name of the file (if any) - * @param {Date} [options.date=current date] - Date of the message, or modification date of the file - * @param {'utf8'|'binary'|'text'|'mime'} [options.format='utf8' if text is passed, 'binary' otherwise] - Data packet type - * @returns {Promise} New message object. - * @async - * @static - */ - async function createMessage({ text, binary, filename, date = new Date(), format = text !== undefined ? 'utf8' : 'binary', ...rest }) { - let input = text !== undefined ? text : binary; - if (input === undefined) { - throw new Error('createMessage: must pass options object containing `text` or `binary`'); - } - if (text && !util.isString(text) && !util.isStream(text)) { - throw new Error('createMessage: options.text must be a string or stream'); - } - if (binary && !util.isUint8Array(binary) && !util.isStream(binary)) { - throw new Error('createMessage: options.binary must be a Uint8Array or stream'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - const streamType = util.isStream(input); - if (streamType) { - await loadStreamsPonyfill(); - input = toStream(input); - } - const literalDataPacket = new LiteralDataPacket(date); - if (text !== undefined) { - literalDataPacket.setText(input, enums.write(enums.literal, format)); - } else { - literalDataPacket.setBytes(input, enums.write(enums.literal, format)); - } - if (filename !== undefined) { - literalDataPacket.setFilename(filename); - } - const literalDataPacketlist = new PacketList(); - literalDataPacketlist.push(literalDataPacket); - const message = new Message(literalDataPacketlist); - message.fromStream = streamType; - return message; - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - // A Cleartext message can contain the following packets - const allowedPackets$5 = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); - - /** - * Class that represents an OpenPGP cleartext signed message. - * See {@link https://tools.ietf.org/html/rfc4880#section-7} - */ - class CleartextMessage { - /** - * @param {String} text - The cleartext of the signed message - * @param {Signature} signature - The detached signature or an empty signature for unsigned messages - */ - constructor(text, signature) { - // normalize EOL to canonical form - this.text = util.removeTrailingSpaces(text).replace(/\r?\n/g, '\r\n'); - if (signature && !(signature instanceof Signature)) { - throw new Error('Invalid signature input'); - } - this.signature = signature || new Signature(new PacketList()); - } - - /** - * Returns the key IDs of the keys that signed the cleartext message - * @returns {Array} Array of keyID objects. - */ - getSigningKeyIDs() { - const keyIDs = []; - const signatureList = this.signature.packets; - signatureList.forEach(function(packet) { - keyIDs.push(packet.issuerKeyID); - }); - return keyIDs; - } - - /** - * Sign the cleartext message - * @param {Array} privateKeys - private keys with decrypted secret key data for signing - * @param {Signature} [signature] - Any existing detached signature - * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to privateKeys[i] - * @param {Date} [date] - The creation time of the signature that should be created - * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New cleartext message with signed content. - * @async - */ - async sign(privateKeys, signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { - const literalDataPacket = new LiteralDataPacket(); - literalDataPacket.setText(this.text); - const newSignature = new Signature(await createSignaturePackets(literalDataPacket, privateKeys, signature, signingKeyIDs, date, userIDs, true, config)); - return new CleartextMessage(this.text, newSignature); - } - - /** - * Verify signatures of cleartext signed message - * @param {Array} keys - Array of keys to verify signatures - * @param {Date} [date] - Verify the signature against the given date, i.e. check signature creation time < date < expiration time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise, - * verified: Promise - * }>>} List of signer's keyID and validity of signature. - * @async - */ - verify(keys, date = new Date(), config = defaultConfig) { - const signatureList = this.signature.packets; - const literalDataPacket = new LiteralDataPacket(); - // we assume that cleartext signature is generated based on UTF8 cleartext - literalDataPacket.setText(this.text); - return createVerificationObjects(signatureList, [literalDataPacket], keys, date, true, config); - } - - /** - * Get cleartext - * @returns {String} Cleartext of message. - */ - getText() { - // normalize end of line to \n - return this.text.replace(/\r\n/g, '\n'); - } - - /** - * Returns ASCII armored text of cleartext signed message - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {String | ReadableStream} ASCII armor. - */ - armor(config = defaultConfig) { - let hashes = this.signature.packets.map(function(packet) { - return enums.read(enums.hash, packet.hashAlgorithm).toUpperCase(); - }); - hashes = hashes.filter(function(item, i, ar) { return ar.indexOf(item) === i; }); - const body = { - hash: hashes.join(), - text: this.text, - data: this.signature.packets.write() - }; - return armor(enums.armor.signed, body, undefined, undefined, undefined, config); - } - } - - /** - * Reads an OpenPGP cleartext signed message and returns a CleartextMessage object - * @param {Object} options - * @param {String} options.cleartextMessage - Text to be parsed - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} New cleartext message object. - * @async - * @static - */ - async function readCleartextMessage({ cleartextMessage, config, ...rest }) { - config = { ...defaultConfig, ...config }; - if (!cleartextMessage) { - throw new Error('readCleartextMessage: must pass options object containing `cleartextMessage`'); - } - if (!util.isString(cleartextMessage)) { - throw new Error('readCleartextMessage: options.cleartextMessage must be a string'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - const input = await unarmor(cleartextMessage); - if (input.type !== enums.armor.signed) { - throw new Error('No cleartext signed message.'); - } - const packetlist = await PacketList.fromBinary(input.data, allowedPackets$5, config); - verifyHeaders$1(input.headers, packetlist); - const signature = new Signature(packetlist); - return new CleartextMessage(input.text, signature); - } - - /** - * Compare hash algorithm specified in the armor header with signatures - * @param {Array} headers - Armor headers - * @param {PacketList} packetlist - The packetlist with signature packets - * @private - */ - function verifyHeaders$1(headers, packetlist) { - const checkHashAlgos = function(hashAlgos) { - const check = packet => algo => packet.hashAlgorithm === algo; - - for (let i = 0; i < packetlist.length; i++) { - if (packetlist[i].constructor.tag === enums.packet.signature && !hashAlgos.some(check(packetlist[i]))) { - return false; - } - } - return true; - }; - - let oneHeader = null; - let hashAlgos = []; - headers.forEach(function(header) { - oneHeader = header.match(/Hash: (.+)/); // get header value - if (oneHeader) { - oneHeader = oneHeader[1].replace(/\s/g, ''); // remove whitespace - oneHeader = oneHeader.split(','); - oneHeader = oneHeader.map(function(hash) { - hash = hash.toLowerCase(); - try { - return enums.write(enums.hash, hash); - } catch (e) { - throw new Error('Unknown hash algorithm in armor header: ' + hash); - } - }); - hashAlgos = hashAlgos.concat(oneHeader); - } else { - throw new Error('Only "Hash" header allowed in cleartext signed message'); - } - }); - - if (!hashAlgos.length && !checkHashAlgos([enums.hash.md5])) { - throw new Error('If no "Hash" header in cleartext signed message, then only MD5 signatures allowed'); - } else if (hashAlgos.length && !checkHashAlgos(hashAlgos)) { - throw new Error('Hash algorithm mismatch in armor header and signature'); - } - } - - /** - * Creates a new CleartextMessage object from text - * @param {Object} options - * @param {String} options.text - * @static - * @async - */ - async function createCleartextMessage({ text, ...rest }) { - if (!text) { - throw new Error('createCleartextMessage: must pass options object containing `text`'); - } - if (!util.isString(text)) { - throw new Error('createCleartextMessage: options.text must be a string'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - return new CleartextMessage(text); - } - - // OpenPGP.js - An OpenPGP implementation in javascript - - - ////////////////////// - // // - // Key handling // - // // - ////////////////////// - - - /** - * Generates a new OpenPGP key pair. Supports RSA and ECC keys. By default, primary and subkeys will be of same type. - * The generated primary key will have signing capabilities. By default, one subkey with encryption capabilities is also generated. - * @param {Object} options - * @param {Object|Array} options.userIDs - User IDs as objects: `{ name: 'Jo Doe', email: 'info@jo.com' }` - * @param {'ecc'|'rsa'} [options.type='ecc'] - The primary key algorithm type: ECC (default) or RSA - * @param {String} [options.passphrase=(not protected)] - The passphrase used to encrypt the generated private key. If omitted, the key won't be encrypted. - * @param {Number} [options.rsaBits=4096] - Number of bits for RSA keys - * @param {String} [options.curve='curve25519'] - Elliptic curve for ECC keys: - * curve25519 (default), p256, p384, p521, secp256k1, - * brainpoolP256r1, brainpoolP384r1, or brainpoolP512r1 - * @param {Date} [options.date=current date] - Override the creation date of the key and the key signatures - * @param {Number} [options.keyExpirationTime=0 (never expires)] - Number of seconds from the key creation time after which the key expires - * @param {Array} [options.subkeys=a single encryption subkey] - Options for each subkey e.g. `[{sign: true, passphrase: '123'}]` - * default to main key options, except for `sign` parameter that defaults to false, and indicates whether the subkey should sign rather than encrypt - * @param {'armored'|'binary'|'object'} [options.format='armored'] - format of the output keys - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} The generated key object in the form: - * { privateKey:PrivateKey|Uint8Array|String, publicKey:PublicKey|Uint8Array|String, revocationCertificate:String } - * @async - * @static - */ - async function generateKey({ userIDs = [], passphrase = '', type = 'ecc', rsaBits = 4096, curve = 'curve25519', keyExpirationTime = 0, date = new Date(), subkeys = [{}], format = 'armored', config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - userIDs = toArray$1(userIDs); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (userIDs.length === 0) { - throw new Error('UserIDs are required for key generation'); - } - if (type === 'rsa' && rsaBits < config.minRSABits) { - throw new Error(`rsaBits should be at least ${config.minRSABits}, got: ${rsaBits}`); - } - - const options = { userIDs, passphrase, type, rsaBits, curve, keyExpirationTime, date, subkeys }; - - try { - const { key, revocationCertificate } = await generate$2(options, config); - key.getKeys().forEach(({ keyPacket }) => checkKeyRequirements(keyPacket, config)); - - return { - privateKey: formatObject(key, format, config), - publicKey: formatObject(key.toPublic(), format, config), - revocationCertificate - }; - } catch (err) { - throw util.wrapError('Error generating keypair', err); - } - } - - /** - * Reformats signature packets for a key and rewraps key object. - * @param {Object} options - * @param {PrivateKey} options.privateKey - Private key to reformat - * @param {Object|Array} options.userIDs - User IDs as objects: `{ name: 'Jo Doe', email: 'info@jo.com' }` - * @param {String} [options.passphrase=(not protected)] - The passphrase used to encrypt the reformatted private key. If omitted, the key won't be encrypted. - * @param {Number} [options.keyExpirationTime=0 (never expires)] - Number of seconds from the key creation time after which the key expires - * @param {Date} [options.date] - Override the creation date of the key signatures. If the key was previously used to sign messages, it is recommended - * to set the same date as the key creation time to ensure that old message signatures will still be verifiable using the reformatted key. - * @param {'armored'|'binary'|'object'} [options.format='armored'] - format of the output keys - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} The generated key object in the form: - * { privateKey:PrivateKey|Uint8Array|String, publicKey:PublicKey|Uint8Array|String, revocationCertificate:String } - * @async - * @static - */ - async function reformatKey({ privateKey, userIDs = [], passphrase = '', keyExpirationTime = 0, date, format = 'armored', config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - userIDs = toArray$1(userIDs); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (userIDs.length === 0) { - throw new Error('UserIDs are required for key reformat'); - } - const options = { privateKey, userIDs, passphrase, keyExpirationTime, date }; - - try { - const { key: reformattedKey, revocationCertificate } = await reformat(options, config); - - return { - privateKey: formatObject(reformattedKey, format, config), - publicKey: formatObject(reformattedKey.toPublic(), format, config), - revocationCertificate - }; - } catch (err) { - throw util.wrapError('Error reformatting keypair', err); - } - } - - /** - * Revokes a key. Requires either a private key or a revocation certificate. - * If a revocation certificate is passed, the reasonForRevocation parameter will be ignored. - * @param {Object} options - * @param {Key} options.key - Public or private key to revoke - * @param {String} [options.revocationCertificate] - Revocation certificate to revoke the key with - * @param {Object} [options.reasonForRevocation] - Object indicating the reason for revocation - * @param {module:enums.reasonForRevocation} [options.reasonForRevocation.flag=[noReason]{@link module:enums.reasonForRevocation}] - Flag indicating the reason for revocation - * @param {String} [options.reasonForRevocation.string=""] - String explaining the reason for revocation - * @param {Date} [options.date] - Use the given date instead of the current time to verify validity of revocation certificate (if provided), or as creation time of the revocation signature - * @param {'armored'|'binary'|'object'} [options.format='armored'] - format of the output key(s) - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} The revoked key in the form: - * { privateKey:PrivateKey|Uint8Array|String, publicKey:PublicKey|Uint8Array|String } if private key is passed, or - * { privateKey: null, publicKey:PublicKey|Uint8Array|String } otherwise - * @async - * @static - */ - async function revokeKey({ key, revocationCertificate, reasonForRevocation, date = new Date(), format = 'armored', config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - try { - const revokedKey = revocationCertificate ? - await key.applyRevocationCertificate(revocationCertificate, date, config) : - await key.revoke(reasonForRevocation, date, config); - - return revokedKey.isPrivate() ? { - privateKey: formatObject(revokedKey, format, config), - publicKey: formatObject(revokedKey.toPublic(), format, config) - } : { - privateKey: null, - publicKey: formatObject(revokedKey, format, config) - }; - } catch (err) { - throw util.wrapError('Error revoking key', err); - } - } - - /** - * Unlock a private key with the given passphrase. - * This method does not change the original key. - * @param {Object} options - * @param {PrivateKey} options.privateKey - The private key to decrypt - * @param {String|Array} options.passphrase - The user's passphrase(s) - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} The unlocked key object. - * @async - */ - async function decryptKey({ privateKey, passphrase, config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (!privateKey.isPrivate()) { - throw new Error('Cannot decrypt a public key'); - } - const clonedPrivateKey = privateKey.clone(true); - const passphrases = util.isArray(passphrase) ? passphrase : [passphrase]; - - try { - await Promise.all(clonedPrivateKey.getKeys().map(key => ( - // try to decrypt each key with any of the given passphrases - util.anyPromise(passphrases.map(passphrase => key.keyPacket.decrypt(passphrase))) - ))); - - await clonedPrivateKey.validate(config); - return clonedPrivateKey; - } catch (err) { - clonedPrivateKey.clearPrivateParams(); - throw util.wrapError('Error decrypting private key', err); - } - } - - /** - * Lock a private key with the given passphrase. - * This method does not change the original key. - * @param {Object} options - * @param {PrivateKey} options.privateKey - The private key to encrypt - * @param {String|Array} options.passphrase - If multiple passphrases, they should be in the same order as the packets each should encrypt - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} The locked key object. - * @async - */ - async function encryptKey({ privateKey, passphrase, config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (!privateKey.isPrivate()) { - throw new Error('Cannot encrypt a public key'); - } - const clonedPrivateKey = privateKey.clone(true); - - const keys = clonedPrivateKey.getKeys(); - const passphrases = util.isArray(passphrase) ? passphrase : new Array(keys.length).fill(passphrase); - if (passphrases.length !== keys.length) { - throw new Error('Invalid number of passphrases given for key encryption'); - } - - try { - await Promise.all(keys.map(async (key, i) => { - const { keyPacket } = key; - await keyPacket.encrypt(passphrases[i], config); - keyPacket.clearPrivateParams(); - })); - return clonedPrivateKey; - } catch (err) { - clonedPrivateKey.clearPrivateParams(); - throw util.wrapError('Error encrypting private key', err); - } - } - - - /////////////////////////////////////////// - // // - // Message encryption and decryption // - // // - /////////////////////////////////////////// - - - /** - * Encrypts a message using public keys, passwords or both at once. At least one of `encryptionKeys` or `passwords` - * must be specified. If signing keys are specified, those will be used to sign the message. - * @param {Object} options - * @param {Message} options.message - Message to be encrypted as created by {@link createMessage} - * @param {PublicKey|PublicKey[]} [options.encryptionKeys] - Array of keys or single key, used to encrypt the message - * @param {PrivateKey|PrivateKey[]} [options.signingKeys] - Private keys for signing. If omitted message will not be signed - * @param {String|String[]} [options.passwords] - Array of passwords or a single password to encrypt the message - * @param {Object} [options.sessionKey] - Session key in the form: `{ data:Uint8Array, algorithm:String }` - * @param {'armored'|'binary'|'object'} [options.format='armored'] - Format of the returned message - * @param {Signature} [options.signature] - A detached signature to add to the encrypted message - * @param {Boolean} [options.wildcard=false] - Use a key ID of 0 instead of the public key IDs - * @param {KeyID|KeyID[]} [options.signingKeyIDs=latest-created valid signing (sub)keys] - Array of key IDs to use for signing. Each `signingKeyIDs[i]` corresponds to `signingKeys[i]` - * @param {KeyID|KeyID[]} [options.encryptionKeyIDs=latest-created valid encryption (sub)keys] - Array of key IDs to use for encryption. Each `encryptionKeyIDs[i]` corresponds to `encryptionKeys[i]` - * @param {Date} [options.date=current date] - Override the creation date of the message signature - * @param {Object|Object[]} [options.signingUserIDs=primary user IDs] - Array of user IDs to sign with, one per key in `signingKeys`, e.g. `[{ name: 'Steve Sender', email: 'steve@openpgp.org' }]` - * @param {Object|Object[]} [options.encryptionUserIDs=primary user IDs] - Array of user IDs to encrypt for, one per key in `encryptionKeys`, e.g. `[{ name: 'Robert Receiver', email: 'robert@openpgp.org' }]` - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise|MaybeStream>} Encrypted message (string if `armor` was true, the default; Uint8Array if `armor` was false). - * @async - * @static - */ - async function encrypt$4({ message, encryptionKeys, signingKeys, passwords, sessionKey, format = 'armored', signature = null, wildcard = false, signingKeyIDs = [], encryptionKeyIDs = [], date = new Date(), signingUserIDs = [], encryptionUserIDs = [], config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - checkMessage(message); checkOutputMessageFormat(format); - encryptionKeys = toArray$1(encryptionKeys); signingKeys = toArray$1(signingKeys); passwords = toArray$1(passwords); - signingKeyIDs = toArray$1(signingKeyIDs); encryptionKeyIDs = toArray$1(encryptionKeyIDs); signingUserIDs = toArray$1(signingUserIDs); encryptionUserIDs = toArray$1(encryptionUserIDs); - if (rest.detached) { - throw new Error("The `detached` option has been removed from openpgp.encrypt, separately call openpgp.sign instead. Don't forget to remove the `privateKeys` option as well."); - } - if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.encrypt, pass `encryptionKeys` instead'); - if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.encrypt, pass `signingKeys` instead'); - if (rest.armor !== undefined) throw new Error('The `armor` option has been removed from openpgp.encrypt, pass `format` instead.'); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (!signingKeys) { - signingKeys = []; - } - const streaming = message.fromStream; - try { - if (signingKeys.length || signature) { // sign the message only if signing keys or signature is specified - message = await message.sign(signingKeys, signature, signingKeyIDs, date, signingUserIDs, config); - } - message = message.compress( - await getPreferredAlgo('compression', encryptionKeys, date, encryptionUserIDs, config), - config - ); - message = await message.encrypt(encryptionKeys, passwords, sessionKey, wildcard, encryptionKeyIDs, date, encryptionUserIDs, config); - if (format === 'object') return message; - // serialize data - const armor = format === 'armored'; - const data = armor ? message.armor(config) : message.write(); - return convertStream(data, streaming, armor ? 'utf8' : 'binary'); - } catch (err) { - throw util.wrapError('Error encrypting message', err); - } - } - - /** - * Decrypts a message with the user's private key, a session key or a password. - * One of `decryptionKeys`, `sessionkeys` or `passwords` must be specified (passing a combination of these options is not supported). - * @param {Object} options - * @param {Message} options.message - The message object with the encrypted data - * @param {PrivateKey|PrivateKey[]} [options.decryptionKeys] - Private keys with decrypted secret key data or session key - * @param {String|String[]} [options.passwords] - Passwords to decrypt the message - * @param {Object|Object[]} [options.sessionKeys] - Session keys in the form: { data:Uint8Array, algorithm:String } - * @param {PublicKey|PublicKey[]} [options.verificationKeys] - Array of public keys or single key, to verify signatures - * @param {Boolean} [options.expectSigned=false] - If true, data decryption fails if the message is not signed with the provided publicKeys - * @param {'utf8'|'binary'} [options.format='utf8'] - Whether to return data as a string(Stream) or Uint8Array(Stream). If 'utf8' (the default), also normalize newlines. - * @param {Signature} [options.signature] - Detached signature for verification - * @param {Date} [options.date=current date] - Use the given date for verification instead of the current time - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} Object containing decrypted and verified message in the form: - * - * { - * data: MaybeStream, (if format was 'utf8', the default) - * data: MaybeStream, (if format was 'binary') - * filename: String, - * signatures: [ - * { - * keyID: module:type/keyid~KeyID, - * verified: Promise, - * signature: Promise - * }, ... - * ] - * } - * - * where `signatures` contains a separate entry for each signature packet found in the input message. - * @async - * @static - */ - async function decrypt$4({ message, decryptionKeys, passwords, sessionKeys, verificationKeys, expectSigned = false, format = 'utf8', signature = null, date = new Date(), config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - checkMessage(message); verificationKeys = toArray$1(verificationKeys); decryptionKeys = toArray$1(decryptionKeys); passwords = toArray$1(passwords); sessionKeys = toArray$1(sessionKeys); - if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.decrypt, pass `decryptionKeys` instead'); - if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.decrypt, pass `verificationKeys` instead'); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - try { - const decrypted = await message.decrypt(decryptionKeys, passwords, sessionKeys, date, config); - if (!verificationKeys) { - verificationKeys = []; - } - - const result = {}; - result.signatures = signature ? await decrypted.verifyDetached(signature, verificationKeys, date, config) : await decrypted.verify(verificationKeys, date, config); - result.data = format === 'binary' ? decrypted.getLiteralData() : decrypted.getText(); - result.filename = decrypted.getFilename(); - linkStreams(result, message); - if (expectSigned) { - if (verificationKeys.length === 0) { - throw new Error('Verification keys are required to verify message signatures'); - } - if (result.signatures.length === 0) { - throw new Error('Message is not signed'); - } - result.data = concat([ - result.data, - fromAsync(async () => { - await util.anyPromise(result.signatures.map(sig => sig.verified)); - }) - ]); - } - result.data = await convertStream(result.data, message.fromStream, format); - return result; - } catch (err) { - throw util.wrapError('Error decrypting message', err); - } - } - - - ////////////////////////////////////////// - // // - // Message signing and verification // - // // - ////////////////////////////////////////// - - - /** - * Signs a message. - * @param {Object} options - * @param {CleartextMessage|Message} options.message - (cleartext) message to be signed - * @param {PrivateKey|PrivateKey[]} options.signingKeys - Array of keys or single key with decrypted secret key data to sign cleartext - * @param {'armored'|'binary'|'object'} [options.format='armored'] - Format of the returned message - * @param {Boolean} [options.detached=false] - If the return value should contain a detached signature - * @param {KeyID|KeyID[]} [options.signingKeyIDs=latest-created valid signing (sub)keys] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] - * @param {Date} [options.date=current date] - Override the creation date of the signature - * @param {Object|Object[]} [options.signingUserIDs=primary user IDs] - Array of user IDs to sign with, one per key in `signingKeys`, e.g. `[{ name: 'Steve Sender', email: 'steve@openpgp.org' }]` - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise>} Signed message (string if `armor` was true, the default; Uint8Array if `armor` was false). - * @async - * @static - */ - async function sign$5({ message, signingKeys, format = 'armored', detached = false, signingKeyIDs = [], date = new Date(), signingUserIDs = [], config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - checkCleartextOrMessage(message); checkOutputMessageFormat(format); - signingKeys = toArray$1(signingKeys); signingKeyIDs = toArray$1(signingKeyIDs); signingUserIDs = toArray$1(signingUserIDs); - - if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.sign, pass `signingKeys` instead'); - if (rest.armor !== undefined) throw new Error('The `armor` option has been removed from openpgp.sign, pass `format` instead.'); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (message instanceof CleartextMessage && format === 'binary') throw new Error('Cannot return signed cleartext message in binary format'); - if (message instanceof CleartextMessage && detached) throw new Error('Cannot detach-sign a cleartext message'); - - if (!signingKeys || signingKeys.length === 0) { - throw new Error('No signing keys provided'); - } - - try { - let signature; - if (detached) { - signature = await message.signDetached(signingKeys, undefined, signingKeyIDs, date, signingUserIDs, config); - } else { - signature = await message.sign(signingKeys, undefined, signingKeyIDs, date, signingUserIDs, config); - } - if (format === 'object') return signature; - - const armor = format === 'armored'; - signature = armor ? signature.armor(config) : signature.write(); - if (detached) { - signature = transformPair(message.packets.write(), async (readable, writable) => { - await Promise.all([ - pipe(signature, writable), - readToEnd(readable).catch(() => {}) - ]); - }); - } - return convertStream(signature, message.fromStream, armor ? 'utf8' : 'binary'); - } catch (err) { - throw util.wrapError('Error signing message', err); - } - } - - /** - * Verifies signatures of cleartext signed message - * @param {Object} options - * @param {CleartextMessage|Message} options.message - (cleartext) message object with signatures - * @param {PublicKey|PublicKey[]} options.verificationKeys - Array of publicKeys or single key, to verify signatures - * @param {Boolean} [options.expectSigned=false] - If true, verification throws if the message is not signed with the provided publicKeys - * @param {'utf8'|'binary'} [options.format='utf8'] - Whether to return data as a string(Stream) or Uint8Array(Stream). If 'utf8' (the default), also normalize newlines. - * @param {Signature} [options.signature] - Detached signature for verification - * @param {Date} [options.date=current date] - Use the given date for verification instead of the current time - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} Object containing verified message in the form: - * - * { - * data: MaybeStream, (if `message` was a CleartextMessage) - * data: MaybeStream, (if `message` was a Message) - * signatures: [ - * { - * keyID: module:type/keyid~KeyID, - * verified: Promise, - * signature: Promise - * }, ... - * ] - * } - * - * where `signatures` contains a separate entry for each signature packet found in the input message. - * @async - * @static - */ - async function verify$5({ message, verificationKeys, expectSigned = false, format = 'utf8', signature = null, date = new Date(), config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - checkCleartextOrMessage(message); verificationKeys = toArray$1(verificationKeys); - if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.verify, pass `verificationKeys` instead'); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (message instanceof CleartextMessage && format === 'binary') throw new Error("Can't return cleartext message data as binary"); - if (message instanceof CleartextMessage && signature) throw new Error("Can't verify detached cleartext signature"); - - try { - const result = {}; - if (signature) { - result.signatures = await message.verifyDetached(signature, verificationKeys, date, config); - } else { - result.signatures = await message.verify(verificationKeys, date, config); - } - result.data = format === 'binary' ? message.getLiteralData() : message.getText(); - if (message.fromStream) linkStreams(result, message); - if (expectSigned) { - if (result.signatures.length === 0) { - throw new Error('Message is not signed'); - } - result.data = concat([ - result.data, - fromAsync(async () => { - await util.anyPromise(result.signatures.map(sig => sig.verified)); - }) - ]); - } - result.data = await convertStream(result.data, message.fromStream, format); - return result; - } catch (err) { - throw util.wrapError('Error verifying signed message', err); - } - } - - - /////////////////////////////////////////////// - // // - // Session key encryption and decryption // - // // - /////////////////////////////////////////////// - - /** - * Generate a new session key object, taking the algorithm preferences of the passed public keys into account. - * @param {Object} options - * @param {PublicKey|PublicKey[]} options.encryptionKeys - Array of public keys or single key used to select algorithm preferences for - * @param {Date} [options.date=current date] - Date to select algorithm preferences at - * @param {Object|Object[]} [options.encryptionUserIDs=primary user IDs] - User IDs to select algorithm preferences for - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise<{ data: Uint8Array, algorithm: String }>} Object with session key data and algorithm. - * @async - * @static - */ - async function generateSessionKey$1({ encryptionKeys, date = new Date(), encryptionUserIDs = [], config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - encryptionKeys = toArray$1(encryptionKeys); encryptionUserIDs = toArray$1(encryptionUserIDs); - if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.generateSessionKey, pass `encryptionKeys` instead'); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - try { - const sessionKeys = await Message.generateSessionKey(encryptionKeys, date, encryptionUserIDs, config); - return sessionKeys; - } catch (err) { - throw util.wrapError('Error generating session key', err); - } - } - - /** - * Encrypt a symmetric session key with public keys, passwords, or both at once. - * At least one of `encryptionKeys` or `passwords` must be specified. - * @param {Object} options - * @param {Uint8Array} options.data - The session key to be encrypted e.g. 16 random bytes (for aes128) - * @param {String} options.algorithm - Algorithm of the symmetric session key e.g. 'aes128' or 'aes256' - * @param {String} [options.aeadAlgorithm] - AEAD algorithm, e.g. 'eax' or 'ocb' - * @param {PublicKey|PublicKey[]} [options.encryptionKeys] - Array of public keys or single key, used to encrypt the key - * @param {String|String[]} [options.passwords] - Passwords for the message - * @param {'armored'|'binary'} [options.format='armored'] - Format of the returned value - * @param {Boolean} [options.wildcard=false] - Use a key ID of 0 instead of the public key IDs - * @param {KeyID|KeyID[]} [options.encryptionKeyIDs=latest-created valid encryption (sub)keys] - Array of key IDs to use for encryption. Each encryptionKeyIDs[i] corresponds to encryptionKeys[i] - * @param {Date} [options.date=current date] - Override the date - * @param {Object|Object[]} [options.encryptionUserIDs=primary user IDs] - Array of user IDs to encrypt for, one per key in `encryptionKeys`, e.g. `[{ name: 'Phil Zimmermann', email: 'phil@openpgp.org' }]` - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} Encrypted session keys (string if `armor` was true, the default; Uint8Array if `armor` was false). - * @async - * @static - */ - async function encryptSessionKey({ data, algorithm, aeadAlgorithm, encryptionKeys, passwords, format = 'armored', wildcard = false, encryptionKeyIDs = [], date = new Date(), encryptionUserIDs = [], config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - checkBinary(data); checkString(algorithm, 'algorithm'); checkOutputMessageFormat(format); - encryptionKeys = toArray$1(encryptionKeys); passwords = toArray$1(passwords); encryptionKeyIDs = toArray$1(encryptionKeyIDs); encryptionUserIDs = toArray$1(encryptionUserIDs); - if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.encryptSessionKey, pass `encryptionKeys` instead'); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - try { - const message = await Message.encryptSessionKey(data, algorithm, aeadAlgorithm, encryptionKeys, passwords, wildcard, encryptionKeyIDs, date, encryptionUserIDs, config); - return formatObject(message, format, config); - } catch (err) { - throw util.wrapError('Error encrypting session key', err); - } - } - - /** - * Decrypt symmetric session keys using private keys or passwords (not both). - * One of `decryptionKeys` or `passwords` must be specified. - * @param {Object} options - * @param {Message} options.message - A message object containing the encrypted session key packets - * @param {PrivateKey|PrivateKey[]} [options.decryptionKeys] - Private keys with decrypted secret key data - * @param {String|String[]} [options.passwords] - Passwords to decrypt the session key - * @param {Date} [options.date] - Date to use for key verification instead of the current time - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} Array of decrypted session key, algorithm pairs in the form: - * { data:Uint8Array, algorithm:String } - * @throws if no session key could be found or decrypted - * @async - * @static - */ - async function decryptSessionKeys({ message, decryptionKeys, passwords, date = new Date(), config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - checkMessage(message); decryptionKeys = toArray$1(decryptionKeys); passwords = toArray$1(passwords); - if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.decryptSessionKeys, pass `decryptionKeys` instead'); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - try { - const sessionKeys = await message.decryptSessionKeys(decryptionKeys, passwords, date, config); - return sessionKeys; - } catch (err) { - throw util.wrapError('Error decrypting session keys', err); - } - } - - - ////////////////////////// - // // - // Helper functions // - // // - ////////////////////////// - - - /** - * Input validation - * @private - */ - function checkString(data, name) { - if (!util.isString(data)) { - throw new Error('Parameter [' + (name || 'data') + '] must be of type String'); - } - } - function checkBinary(data, name) { - if (!util.isUint8Array(data)) { - throw new Error('Parameter [' + (name || 'data') + '] must be of type Uint8Array'); - } - } - function checkMessage(message) { - if (!(message instanceof Message)) { - throw new Error('Parameter [message] needs to be of type Message'); - } - } - function checkCleartextOrMessage(message) { - if (!(message instanceof CleartextMessage) && !(message instanceof Message)) { - throw new Error('Parameter [message] needs to be of type Message or CleartextMessage'); - } - } - function checkOutputMessageFormat(format) { - if (format !== 'armored' && format !== 'binary' && format !== 'object') { - throw new Error(`Unsupported format ${format}`); - } - } - const defaultConfigPropsCount = Object.keys(defaultConfig).length; - function checkConfig(config) { - const inputConfigProps = Object.keys(config); - if (inputConfigProps.length !== defaultConfigPropsCount) { - for (const inputProp of inputConfigProps) { - if (defaultConfig[inputProp] === undefined) { - throw new Error(`Unknown config property: ${inputProp}`); - } - } - } - } - - /** - * Normalize parameter to an array if it is not undefined. - * @param {Object} param - the parameter to be normalized - * @returns {Array|undefined} The resulting array or undefined. - * @private - */ - function toArray$1(param) { - if (param && !util.isArray(param)) { - param = [param]; - } - return param; - } - - /** - * Convert data to or from Stream - * @param {Object} data - the data to convert - * @param {'web'|'ponyfill'|'node'|false} streaming - Whether to return a ReadableStream, and of what type - * @param {'utf8'|'binary'} [encoding] - How to return data in Node Readable streams - * @returns {Promise} The data in the respective format. - * @async - * @private - */ - async function convertStream(data, streaming, encoding = 'utf8') { - const streamType = util.isStream(data); - if (streamType === 'array') { - return readToEnd(data); - } - if (streaming === 'node') { - data = webToNode(data); - if (encoding !== 'binary') data.setEncoding(encoding); - return data; - } - if (streaming === 'web' && streamType === 'ponyfill') { - return toNativeReadable(data); - } - return data; - } - - /** - * Link result.data to the message stream for cancellation. - * Also, forward errors in the message to result.data. - * @param {Object} result - the data to convert - * @param {Message} message - message object - * @returns {Object} - * @private - */ - function linkStreams(result, message) { - result.data = transformPair(message.packets.stream, async (readable, writable) => { - await pipe(result.data, writable, { - preventClose: true - }); - const writer = getWriter(writable); - try { - // Forward errors in the message stream to result.data. - await readToEnd(readable, _ => _); - await writer.close(); - } catch (e) { - await writer.abort(e); - } - }); - } - - /** - * Convert the object to the given format - * @param {Key|Message} object - * @param {'armored'|'binary'|'object'} format - * @param {Object} config - Full configuration - * @returns {String|Uint8Array|Object} - */ - function formatObject(object, format, config) { - switch (format) { - case 'object': - return object; - case 'armored': - return object.armor(config); - case 'binary': - return object.write(); - default: - throw new Error(`Unsupported format ${format}`); - } - } - - /** - * web-streams-polyfill v3.0.3 - */ - /// - const SymbolPolyfill = typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol' ? - Symbol : - description => `Symbol(${description})`; - - /// - function noop() { - return undefined; - } - function getGlobals() { - if (typeof self !== 'undefined') { - return self; - } - else if (typeof window !== 'undefined') { - return window; - } - else if (typeof global !== 'undefined') { - return global; - } - return undefined; - } - const globals = getGlobals(); - - function typeIsObject(x) { - return (typeof x === 'object' && x !== null) || typeof x === 'function'; - } - const rethrowAssertionErrorRejection = noop; - - const originalPromise = Promise; - const originalPromiseThen = Promise.prototype.then; - const originalPromiseResolve = Promise.resolve.bind(originalPromise); - const originalPromiseReject = Promise.reject.bind(originalPromise); - function newPromise(executor) { - return new originalPromise(executor); - } - function promiseResolvedWith(value) { - return originalPromiseResolve(value); - } - function promiseRejectedWith(reason) { - return originalPromiseReject(reason); - } - function PerformPromiseThen(promise, onFulfilled, onRejected) { - // There doesn't appear to be any way to correctly emulate the behaviour from JavaScript, so this is just an - // approximation. - return originalPromiseThen.call(promise, onFulfilled, onRejected); - } - function uponPromise(promise, onFulfilled, onRejected) { - PerformPromiseThen(PerformPromiseThen(promise, onFulfilled, onRejected), undefined, rethrowAssertionErrorRejection); - } - function uponFulfillment(promise, onFulfilled) { - uponPromise(promise, onFulfilled); - } - function uponRejection(promise, onRejected) { - uponPromise(promise, undefined, onRejected); - } - function transformPromiseWith(promise, fulfillmentHandler, rejectionHandler) { - return PerformPromiseThen(promise, fulfillmentHandler, rejectionHandler); - } - function setPromiseIsHandledToTrue(promise) { - PerformPromiseThen(promise, undefined, rethrowAssertionErrorRejection); - } - const queueMicrotask = (() => { - const globalQueueMicrotask = globals && globals.queueMicrotask; - if (typeof globalQueueMicrotask === 'function') { - return globalQueueMicrotask; - } - const resolvedPromise = promiseResolvedWith(undefined); - return (fn) => PerformPromiseThen(resolvedPromise, fn); - })(); - function reflectCall(F, V, args) { - if (typeof F !== 'function') { - throw new TypeError('Argument is not a function'); - } - return Function.prototype.apply.call(F, V, args); - } - function promiseCall(F, V, args) { - try { - return promiseResolvedWith(reflectCall(F, V, args)); - } - catch (value) { - return promiseRejectedWith(value); - } - } - - // Original from Chromium - // https://chromium.googlesource.com/chromium/src/+/0aee4434a4dba42a42abaea9bfbc0cd196a63bc1/third_party/blink/renderer/core/streams/SimpleQueue.js - const QUEUE_MAX_ARRAY_SIZE = 16384; - /** - * Simple queue structure. - * - * Avoids scalability issues with using a packed array directly by using - * multiple arrays in a linked list and keeping the array size bounded. - */ - class SimpleQueue { - constructor() { - this._cursor = 0; - this._size = 0; - // _front and _back are always defined. - this._front = { - _elements: [], - _next: undefined - }; - this._back = this._front; - // The cursor is used to avoid calling Array.shift(). - // It contains the index of the front element of the array inside the - // front-most node. It is always in the range [0, QUEUE_MAX_ARRAY_SIZE). - this._cursor = 0; - // When there is only one node, size === elements.length - cursor. - this._size = 0; - } - get length() { - return this._size; - } - // For exception safety, this method is structured in order: - // 1. Read state - // 2. Calculate required state mutations - // 3. Perform state mutations - push(element) { - const oldBack = this._back; - let newBack = oldBack; - if (oldBack._elements.length === QUEUE_MAX_ARRAY_SIZE - 1) { - newBack = { - _elements: [], - _next: undefined - }; - } - // push() is the mutation most likely to throw an exception, so it - // goes first. - oldBack._elements.push(element); - if (newBack !== oldBack) { - this._back = newBack; - oldBack._next = newBack; - } - ++this._size; - } - // Like push(), shift() follows the read -> calculate -> mutate pattern for - // exception safety. - shift() { // must not be called on an empty queue - const oldFront = this._front; - let newFront = oldFront; - const oldCursor = this._cursor; - let newCursor = oldCursor + 1; - const elements = oldFront._elements; - const element = elements[oldCursor]; - if (newCursor === QUEUE_MAX_ARRAY_SIZE) { - newFront = oldFront._next; - newCursor = 0; - } - // No mutations before this point. - --this._size; - this._cursor = newCursor; - if (oldFront !== newFront) { - this._front = newFront; - } - // Permit shifted element to be garbage collected. - elements[oldCursor] = undefined; - return element; - } - // The tricky thing about forEach() is that it can be called - // re-entrantly. The queue may be mutated inside the callback. It is easy to - // see that push() within the callback has no negative effects since the end - // of the queue is checked for on every iteration. If shift() is called - // repeatedly within the callback then the next iteration may return an - // element that has been removed. In this case the callback will be called - // with undefined values until we either "catch up" with elements that still - // exist or reach the back of the queue. - forEach(callback) { - let i = this._cursor; - let node = this._front; - let elements = node._elements; - while (i !== elements.length || node._next !== undefined) { - if (i === elements.length) { - node = node._next; - elements = node._elements; - i = 0; - if (elements.length === 0) { - break; - } - } - callback(elements[i]); - ++i; - } - } - // Return the element that would be returned if shift() was called now, - // without modifying the queue. - peek() { // must not be called on an empty queue - const front = this._front; - const cursor = this._cursor; - return front._elements[cursor]; - } - } - - function ReadableStreamReaderGenericInitialize(reader, stream) { - reader._ownerReadableStream = stream; - stream._reader = reader; - if (stream._state === 'readable') { - defaultReaderClosedPromiseInitialize(reader); - } - else if (stream._state === 'closed') { - defaultReaderClosedPromiseInitializeAsResolved(reader); - } - else { - defaultReaderClosedPromiseInitializeAsRejected(reader, stream._storedError); - } - } - // A client of ReadableStreamDefaultReader and ReadableStreamBYOBReader may use these functions directly to bypass state - // check. - function ReadableStreamReaderGenericCancel(reader, reason) { - const stream = reader._ownerReadableStream; - return ReadableStreamCancel(stream, reason); - } - function ReadableStreamReaderGenericRelease(reader) { - if (reader._ownerReadableStream._state === 'readable') { - defaultReaderClosedPromiseReject(reader, new TypeError(`Reader was released and can no longer be used to monitor the stream's closedness`)); - } - else { - defaultReaderClosedPromiseResetToRejected(reader, new TypeError(`Reader was released and can no longer be used to monitor the stream's closedness`)); - } - reader._ownerReadableStream._reader = undefined; - reader._ownerReadableStream = undefined; - } - // Helper functions for the readers. - function readerLockException(name) { - return new TypeError('Cannot ' + name + ' a stream using a released reader'); - } - // Helper functions for the ReadableStreamDefaultReader. - function defaultReaderClosedPromiseInitialize(reader) { - reader._closedPromise = newPromise((resolve, reject) => { - reader._closedPromise_resolve = resolve; - reader._closedPromise_reject = reject; - }); - } - function defaultReaderClosedPromiseInitializeAsRejected(reader, reason) { - defaultReaderClosedPromiseInitialize(reader); - defaultReaderClosedPromiseReject(reader, reason); - } - function defaultReaderClosedPromiseInitializeAsResolved(reader) { - defaultReaderClosedPromiseInitialize(reader); - defaultReaderClosedPromiseResolve(reader); - } - function defaultReaderClosedPromiseReject(reader, reason) { - if (reader._closedPromise_reject === undefined) { - return; - } - setPromiseIsHandledToTrue(reader._closedPromise); - reader._closedPromise_reject(reason); - reader._closedPromise_resolve = undefined; - reader._closedPromise_reject = undefined; - } - function defaultReaderClosedPromiseResetToRejected(reader, reason) { - defaultReaderClosedPromiseInitializeAsRejected(reader, reason); - } - function defaultReaderClosedPromiseResolve(reader) { - if (reader._closedPromise_resolve === undefined) { - return; - } - reader._closedPromise_resolve(undefined); - reader._closedPromise_resolve = undefined; - reader._closedPromise_reject = undefined; - } - - const AbortSteps = SymbolPolyfill('[[AbortSteps]]'); - const ErrorSteps = SymbolPolyfill('[[ErrorSteps]]'); - const CancelSteps = SymbolPolyfill('[[CancelSteps]]'); - const PullSteps = SymbolPolyfill('[[PullSteps]]'); - - /// - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isFinite#Polyfill - const NumberIsFinite = Number.isFinite || function (x) { - return typeof x === 'number' && isFinite(x); - }; - - /// - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc#Polyfill - const MathTrunc = Math.trunc || function (v) { - return v < 0 ? Math.ceil(v) : Math.floor(v); - }; - - // https://heycam.github.io/webidl/#idl-dictionaries - function isDictionary(x) { - return typeof x === 'object' || typeof x === 'function'; - } - function assertDictionary(obj, context) { - if (obj !== undefined && !isDictionary(obj)) { - throw new TypeError(`${context} is not an object.`); - } - } - // https://heycam.github.io/webidl/#idl-callback-functions - function assertFunction(x, context) { - if (typeof x !== 'function') { - throw new TypeError(`${context} is not a function.`); - } - } - // https://heycam.github.io/webidl/#idl-object - function isObject(x) { - return (typeof x === 'object' && x !== null) || typeof x === 'function'; - } - function assertObject(x, context) { - if (!isObject(x)) { - throw new TypeError(`${context} is not an object.`); - } - } - function assertRequiredArgument(x, position, context) { - if (x === undefined) { - throw new TypeError(`Parameter ${position} is required in '${context}'.`); - } - } - function assertRequiredField(x, field, context) { - if (x === undefined) { - throw new TypeError(`${field} is required in '${context}'.`); - } - } - // https://heycam.github.io/webidl/#idl-unrestricted-double - function convertUnrestrictedDouble(value) { - return Number(value); - } - function censorNegativeZero(x) { - return x === 0 ? 0 : x; - } - function integerPart(x) { - return censorNegativeZero(MathTrunc(x)); - } - // https://heycam.github.io/webidl/#idl-unsigned-long-long - function convertUnsignedLongLongWithEnforceRange(value, context) { - const lowerBound = 0; - const upperBound = Number.MAX_SAFE_INTEGER; - let x = Number(value); - x = censorNegativeZero(x); - if (!NumberIsFinite(x)) { - throw new TypeError(`${context} is not a finite number`); - } - x = integerPart(x); - if (x < lowerBound || x > upperBound) { - throw new TypeError(`${context} is outside the accepted range of ${lowerBound} to ${upperBound}, inclusive`); - } - if (!NumberIsFinite(x) || x === 0) { - return 0; - } - // TODO Use BigInt if supported? - // let xBigInt = BigInt(integerPart(x)); - // xBigInt = BigInt.asUintN(64, xBigInt); - // return Number(xBigInt); - return x; - } - - function assertReadableStream(x, context) { - if (!IsReadableStream(x)) { - throw new TypeError(`${context} is not a ReadableStream.`); - } - } - - // Abstract operations for the ReadableStream. - function AcquireReadableStreamDefaultReader(stream) { - return new ReadableStreamDefaultReader(stream); - } - // ReadableStream API exposed for controllers. - function ReadableStreamAddReadRequest(stream, readRequest) { - stream._reader._readRequests.push(readRequest); - } - function ReadableStreamFulfillReadRequest(stream, chunk, done) { - const reader = stream._reader; - const readRequest = reader._readRequests.shift(); - if (done) { - readRequest._closeSteps(); - } - else { - readRequest._chunkSteps(chunk); - } - } - function ReadableStreamGetNumReadRequests(stream) { - return stream._reader._readRequests.length; - } - function ReadableStreamHasDefaultReader(stream) { - const reader = stream._reader; - if (reader === undefined) { - return false; - } - if (!IsReadableStreamDefaultReader(reader)) { - return false; - } - return true; - } - /** - * A default reader vended by a {@link ReadableStream}. - * - * @public - */ - class ReadableStreamDefaultReader { - constructor(stream) { - assertRequiredArgument(stream, 1, 'ReadableStreamDefaultReader'); - assertReadableStream(stream, 'First parameter'); - if (IsReadableStreamLocked(stream)) { - throw new TypeError('This stream has already been locked for exclusive reading by another reader'); - } - ReadableStreamReaderGenericInitialize(this, stream); - this._readRequests = new SimpleQueue(); - } - /** - * Returns a promise that will be fulfilled when the stream becomes closed, - * or rejected if the stream ever errors or the reader's lock is released before the stream finishes closing. - */ - get closed() { - if (!IsReadableStreamDefaultReader(this)) { - return promiseRejectedWith(defaultReaderBrandCheckException('closed')); - } - return this._closedPromise; - } - /** - * If the reader is active, behaves the same as {@link ReadableStream.cancel | stream.cancel(reason)}. - */ - cancel(reason = undefined) { - if (!IsReadableStreamDefaultReader(this)) { - return promiseRejectedWith(defaultReaderBrandCheckException('cancel')); - } - if (this._ownerReadableStream === undefined) { - return promiseRejectedWith(readerLockException('cancel')); - } - return ReadableStreamReaderGenericCancel(this, reason); - } - /** - * Returns a promise that allows access to the next chunk from the stream's internal queue, if available. - * - * If reading a chunk causes the queue to become empty, more data will be pulled from the underlying source. - */ - read() { - if (!IsReadableStreamDefaultReader(this)) { - return promiseRejectedWith(defaultReaderBrandCheckException('read')); - } - if (this._ownerReadableStream === undefined) { - return promiseRejectedWith(readerLockException('read from')); - } - let resolvePromise; - let rejectPromise; - const promise = newPromise((resolve, reject) => { - resolvePromise = resolve; - rejectPromise = reject; - }); - const readRequest = { - _chunkSteps: chunk => resolvePromise({ value: chunk, done: false }), - _closeSteps: () => resolvePromise({ value: undefined, done: true }), - _errorSteps: e => rejectPromise(e) - }; - ReadableStreamDefaultReaderRead(this, readRequest); - return promise; - } - /** - * Releases the reader's lock on the corresponding stream. After the lock is released, the reader is no longer active. - * If the associated stream is errored when the lock is released, the reader will appear errored in the same way - * from now on; otherwise, the reader will appear closed. - * - * A reader's lock cannot be released while it still has a pending read request, i.e., if a promise returned by - * the reader's {@link ReadableStreamDefaultReader.read | read()} method has not yet been settled. Attempting to - * do so will throw a `TypeError` and leave the reader locked to the stream. - */ - releaseLock() { - if (!IsReadableStreamDefaultReader(this)) { - throw defaultReaderBrandCheckException('releaseLock'); - } - if (this._ownerReadableStream === undefined) { - return; - } - if (this._readRequests.length > 0) { - throw new TypeError('Tried to release a reader lock when that reader has pending read() calls un-settled'); - } - ReadableStreamReaderGenericRelease(this); - } - } - Object.defineProperties(ReadableStreamDefaultReader.prototype, { - cancel: { enumerable: true }, - read: { enumerable: true }, - releaseLock: { enumerable: true }, - closed: { enumerable: true } - }); - if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(ReadableStreamDefaultReader.prototype, SymbolPolyfill.toStringTag, { - value: 'ReadableStreamDefaultReader', - configurable: true - }); - } - // Abstract operations for the readers. - function IsReadableStreamDefaultReader(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_readRequests')) { - return false; - } - return true; - } - function ReadableStreamDefaultReaderRead(reader, readRequest) { - const stream = reader._ownerReadableStream; - stream._disturbed = true; - if (stream._state === 'closed') { - readRequest._closeSteps(); - } - else if (stream._state === 'errored') { - readRequest._errorSteps(stream._storedError); - } - else { - stream._readableStreamController[PullSteps](readRequest); - } - } - // Helper functions for the ReadableStreamDefaultReader. - function defaultReaderBrandCheckException(name) { - return new TypeError(`ReadableStreamDefaultReader.prototype.${name} can only be used on a ReadableStreamDefaultReader`); - } - - /// - let AsyncIteratorPrototype; - if (typeof SymbolPolyfill.asyncIterator === 'symbol') { - // We're running inside a ES2018+ environment, but we're compiling to an older syntax. - // We cannot access %AsyncIteratorPrototype% without non-ES2018 syntax, but we can re-create it. - AsyncIteratorPrototype = { - // 25.1.3.1 %AsyncIteratorPrototype% [ @@asyncIterator ] ( ) - // https://tc39.github.io/ecma262/#sec-asynciteratorprototype-asynciterator - [SymbolPolyfill.asyncIterator]() { - return this; - } - }; - Object.defineProperty(AsyncIteratorPrototype, SymbolPolyfill.asyncIterator, { enumerable: false }); - } - - /// - class ReadableStreamAsyncIteratorImpl { - constructor(reader, preventCancel) { - this._ongoingPromise = undefined; - this._isFinished = false; - this._reader = reader; - this._preventCancel = preventCancel; - } - next() { - const nextSteps = () => this._nextSteps(); - this._ongoingPromise = this._ongoingPromise ? - transformPromiseWith(this._ongoingPromise, nextSteps, nextSteps) : - nextSteps(); - return this._ongoingPromise; - } - return(value) { - const returnSteps = () => this._returnSteps(value); - return this._ongoingPromise ? - transformPromiseWith(this._ongoingPromise, returnSteps, returnSteps) : - returnSteps(); - } - _nextSteps() { - if (this._isFinished) { - return Promise.resolve({ value: undefined, done: true }); - } - const reader = this._reader; - if (reader._ownerReadableStream === undefined) { - return promiseRejectedWith(readerLockException('iterate')); - } - let resolvePromise; - let rejectPromise; - const promise = newPromise((resolve, reject) => { - resolvePromise = resolve; - rejectPromise = reject; - }); - const readRequest = { - _chunkSteps: chunk => { - this._ongoingPromise = undefined; - // This needs to be delayed by one microtask, otherwise we stop pulling too early which breaks a test. - // FIXME Is this a bug in the specification, or in the test? - queueMicrotask(() => resolvePromise({ value: chunk, done: false })); - }, - _closeSteps: () => { - this._ongoingPromise = undefined; - this._isFinished = true; - ReadableStreamReaderGenericRelease(reader); - resolvePromise({ value: undefined, done: true }); - }, - _errorSteps: reason => { - this._ongoingPromise = undefined; - this._isFinished = true; - ReadableStreamReaderGenericRelease(reader); - rejectPromise(reason); - } - }; - ReadableStreamDefaultReaderRead(reader, readRequest); - return promise; - } - _returnSteps(value) { - if (this._isFinished) { - return Promise.resolve({ value, done: true }); - } - this._isFinished = true; - const reader = this._reader; - if (reader._ownerReadableStream === undefined) { - return promiseRejectedWith(readerLockException('finish iterating')); - } - if (!this._preventCancel) { - const result = ReadableStreamReaderGenericCancel(reader, value); - ReadableStreamReaderGenericRelease(reader); - return transformPromiseWith(result, () => ({ value, done: true })); - } - ReadableStreamReaderGenericRelease(reader); - return promiseResolvedWith({ value, done: true }); - } - } - const ReadableStreamAsyncIteratorPrototype = { - next() { - if (!IsReadableStreamAsyncIterator(this)) { - return promiseRejectedWith(streamAsyncIteratorBrandCheckException('next')); - } - return this._asyncIteratorImpl.next(); - }, - return(value) { - if (!IsReadableStreamAsyncIterator(this)) { - return promiseRejectedWith(streamAsyncIteratorBrandCheckException('return')); - } - return this._asyncIteratorImpl.return(value); - } - }; - if (AsyncIteratorPrototype !== undefined) { - Object.setPrototypeOf(ReadableStreamAsyncIteratorPrototype, AsyncIteratorPrototype); - } - // Abstract operations for the ReadableStream. - function AcquireReadableStreamAsyncIterator(stream, preventCancel) { - const reader = AcquireReadableStreamDefaultReader(stream); - const impl = new ReadableStreamAsyncIteratorImpl(reader, preventCancel); - const iterator = Object.create(ReadableStreamAsyncIteratorPrototype); - iterator._asyncIteratorImpl = impl; - return iterator; - } - function IsReadableStreamAsyncIterator(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_asyncIteratorImpl')) { - return false; - } - return true; - } - // Helper functions for the ReadableStream. - function streamAsyncIteratorBrandCheckException(name) { - return new TypeError(`ReadableStreamAsyncIterator.${name} can only be used on a ReadableSteamAsyncIterator`); - } - - /// - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN#Polyfill - const NumberIsNaN = Number.isNaN || function (x) { - // eslint-disable-next-line no-self-compare - return x !== x; - }; - - function IsFiniteNonNegativeNumber(v) { - if (!IsNonNegativeNumber(v)) { - return false; - } - if (v === Infinity) { - return false; - } - return true; - } - function IsNonNegativeNumber(v) { - if (typeof v !== 'number') { - return false; - } - if (NumberIsNaN(v)) { - return false; - } - if (v < 0) { - return false; - } - return true; - } - - function DequeueValue(container) { - const pair = container._queue.shift(); - container._queueTotalSize -= pair.size; - if (container._queueTotalSize < 0) { - container._queueTotalSize = 0; - } - return pair.value; - } - function EnqueueValueWithSize(container, value, size) { - size = Number(size); - if (!IsFiniteNonNegativeNumber(size)) { - throw new RangeError('Size must be a finite, non-NaN, non-negative number.'); - } - container._queue.push({ value, size }); - container._queueTotalSize += size; - } - function PeekQueueValue(container) { - const pair = container._queue.peek(); - return pair.value; - } - function ResetQueue(container) { - container._queue = new SimpleQueue(); - container._queueTotalSize = 0; - } - - function CreateArrayFromList(elements) { - // We use arrays to represent lists, so this is basically a no-op. - // Do a slice though just in case we happen to depend on the unique-ness. - return elements.slice(); - } - function CopyDataBlockBytes(dest, destOffset, src, srcOffset, n) { - new Uint8Array(dest).set(new Uint8Array(src, srcOffset, n), destOffset); - } - // Not implemented correctly - function TransferArrayBuffer(O) { - return O; - } - // Not implemented correctly - function IsDetachedBuffer(O) { - return false; - } - - /** - * A pull-into request in a {@link ReadableByteStreamController}. - * - * @public - */ - class ReadableStreamBYOBRequest { - constructor() { - throw new TypeError('Illegal constructor'); - } - /** - * Returns the view for writing in to, or `null` if the BYOB request has already been responded to. - */ - get view() { - if (!IsReadableStreamBYOBRequest(this)) { - throw byobRequestBrandCheckException('view'); - } - return this._view; - } - respond(bytesWritten) { - if (!IsReadableStreamBYOBRequest(this)) { - throw byobRequestBrandCheckException('respond'); - } - assertRequiredArgument(bytesWritten, 1, 'respond'); - bytesWritten = convertUnsignedLongLongWithEnforceRange(bytesWritten, 'First parameter'); - if (this._associatedReadableByteStreamController === undefined) { - throw new TypeError('This BYOB request has been invalidated'); - } - if (IsDetachedBuffer(this._view.buffer)) ; - ReadableByteStreamControllerRespond(this._associatedReadableByteStreamController, bytesWritten); - } - respondWithNewView(view) { - if (!IsReadableStreamBYOBRequest(this)) { - throw byobRequestBrandCheckException('respondWithNewView'); - } - assertRequiredArgument(view, 1, 'respondWithNewView'); - if (!ArrayBuffer.isView(view)) { - throw new TypeError('You can only respond with array buffer views'); - } - if (view.byteLength === 0) { - throw new TypeError('chunk must have non-zero byteLength'); - } - if (view.buffer.byteLength === 0) { - throw new TypeError(`chunk's buffer must have non-zero byteLength`); - } - if (this._associatedReadableByteStreamController === undefined) { - throw new TypeError('This BYOB request has been invalidated'); - } - ReadableByteStreamControllerRespondWithNewView(this._associatedReadableByteStreamController, view); - } - } - Object.defineProperties(ReadableStreamBYOBRequest.prototype, { - respond: { enumerable: true }, - respondWithNewView: { enumerable: true }, - view: { enumerable: true } - }); - if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(ReadableStreamBYOBRequest.prototype, SymbolPolyfill.toStringTag, { - value: 'ReadableStreamBYOBRequest', - configurable: true - }); - } - /** - * Allows control of a {@link ReadableStream | readable byte stream}'s state and internal queue. - * - * @public - */ - class ReadableByteStreamController { - constructor() { - throw new TypeError('Illegal constructor'); - } - /** - * Returns the current BYOB pull request, or `null` if there isn't one. - */ - get byobRequest() { - if (!IsReadableByteStreamController(this)) { - throw byteStreamControllerBrandCheckException('byobRequest'); - } - if (this._byobRequest === null && this._pendingPullIntos.length > 0) { - const firstDescriptor = this._pendingPullIntos.peek(); - const view = new Uint8Array(firstDescriptor.buffer, firstDescriptor.byteOffset + firstDescriptor.bytesFilled, firstDescriptor.byteLength - firstDescriptor.bytesFilled); - const byobRequest = Object.create(ReadableStreamBYOBRequest.prototype); - SetUpReadableStreamBYOBRequest(byobRequest, this, view); - this._byobRequest = byobRequest; - } - return this._byobRequest; - } - /** - * Returns the desired size to fill the controlled stream's internal queue. It can be negative, if the queue is - * over-full. An underlying byte source ought to use this information to determine when and how to apply backpressure. - */ - get desiredSize() { - if (!IsReadableByteStreamController(this)) { - throw byteStreamControllerBrandCheckException('desiredSize'); - } - return ReadableByteStreamControllerGetDesiredSize(this); - } - /** - * Closes the controlled readable stream. Consumers will still be able to read any previously-enqueued chunks from - * the stream, but once those are read, the stream will become closed. - */ - close() { - if (!IsReadableByteStreamController(this)) { - throw byteStreamControllerBrandCheckException('close'); - } - if (this._closeRequested) { - throw new TypeError('The stream has already been closed; do not close it again!'); - } - const state = this._controlledReadableByteStream._state; - if (state !== 'readable') { - throw new TypeError(`The stream (in ${state} state) is not in the readable state and cannot be closed`); - } - ReadableByteStreamControllerClose(this); - } - enqueue(chunk) { - if (!IsReadableByteStreamController(this)) { - throw byteStreamControllerBrandCheckException('enqueue'); - } - assertRequiredArgument(chunk, 1, 'enqueue'); - if (!ArrayBuffer.isView(chunk)) { - throw new TypeError('chunk must be an array buffer view'); - } - if (chunk.byteLength === 0) { - throw new TypeError('chunk must have non-zero byteLength'); - } - if (chunk.buffer.byteLength === 0) { - throw new TypeError(`chunk's buffer must have non-zero byteLength`); - } - if (this._closeRequested) { - throw new TypeError('stream is closed or draining'); - } - const state = this._controlledReadableByteStream._state; - if (state !== 'readable') { - throw new TypeError(`The stream (in ${state} state) is not in the readable state and cannot be enqueued to`); - } - ReadableByteStreamControllerEnqueue(this, chunk); - } - /** - * Errors the controlled readable stream, making all future interactions with it fail with the given error `e`. - */ - error(e = undefined) { - if (!IsReadableByteStreamController(this)) { - throw byteStreamControllerBrandCheckException('error'); - } - ReadableByteStreamControllerError(this, e); - } - /** @internal */ - [CancelSteps](reason) { - if (this._pendingPullIntos.length > 0) { - const firstDescriptor = this._pendingPullIntos.peek(); - firstDescriptor.bytesFilled = 0; - } - ResetQueue(this); - const result = this._cancelAlgorithm(reason); - ReadableByteStreamControllerClearAlgorithms(this); - return result; - } - /** @internal */ - [PullSteps](readRequest) { - const stream = this._controlledReadableByteStream; - if (this._queueTotalSize > 0) { - const entry = this._queue.shift(); - this._queueTotalSize -= entry.byteLength; - ReadableByteStreamControllerHandleQueueDrain(this); - const view = new Uint8Array(entry.buffer, entry.byteOffset, entry.byteLength); - readRequest._chunkSteps(view); - return; - } - const autoAllocateChunkSize = this._autoAllocateChunkSize; - if (autoAllocateChunkSize !== undefined) { - let buffer; - try { - buffer = new ArrayBuffer(autoAllocateChunkSize); - } - catch (bufferE) { - readRequest._errorSteps(bufferE); - return; - } - const pullIntoDescriptor = { - buffer, - byteOffset: 0, - byteLength: autoAllocateChunkSize, - bytesFilled: 0, - elementSize: 1, - viewConstructor: Uint8Array, - readerType: 'default' - }; - this._pendingPullIntos.push(pullIntoDescriptor); - } - ReadableStreamAddReadRequest(stream, readRequest); - ReadableByteStreamControllerCallPullIfNeeded(this); - } - } - Object.defineProperties(ReadableByteStreamController.prototype, { - close: { enumerable: true }, - enqueue: { enumerable: true }, - error: { enumerable: true }, - byobRequest: { enumerable: true }, - desiredSize: { enumerable: true } - }); - if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(ReadableByteStreamController.prototype, SymbolPolyfill.toStringTag, { - value: 'ReadableByteStreamController', - configurable: true - }); - } - // Abstract operations for the ReadableByteStreamController. - function IsReadableByteStreamController(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_controlledReadableByteStream')) { - return false; - } - return true; - } - function IsReadableStreamBYOBRequest(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_associatedReadableByteStreamController')) { - return false; - } - return true; - } - function ReadableByteStreamControllerCallPullIfNeeded(controller) { - const shouldPull = ReadableByteStreamControllerShouldCallPull(controller); - if (!shouldPull) { - return; - } - if (controller._pulling) { - controller._pullAgain = true; - return; - } - controller._pulling = true; - // TODO: Test controller argument - const pullPromise = controller._pullAlgorithm(); - uponPromise(pullPromise, () => { - controller._pulling = false; - if (controller._pullAgain) { - controller._pullAgain = false; - ReadableByteStreamControllerCallPullIfNeeded(controller); - } - }, e => { - ReadableByteStreamControllerError(controller, e); - }); - } - function ReadableByteStreamControllerClearPendingPullIntos(controller) { - ReadableByteStreamControllerInvalidateBYOBRequest(controller); - controller._pendingPullIntos = new SimpleQueue(); - } - function ReadableByteStreamControllerCommitPullIntoDescriptor(stream, pullIntoDescriptor) { - let done = false; - if (stream._state === 'closed') { - done = true; - } - const filledView = ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor); - if (pullIntoDescriptor.readerType === 'default') { - ReadableStreamFulfillReadRequest(stream, filledView, done); - } - else { - ReadableStreamFulfillReadIntoRequest(stream, filledView, done); - } - } - function ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor) { - const bytesFilled = pullIntoDescriptor.bytesFilled; - const elementSize = pullIntoDescriptor.elementSize; - return new pullIntoDescriptor.viewConstructor(pullIntoDescriptor.buffer, pullIntoDescriptor.byteOffset, bytesFilled / elementSize); - } - function ReadableByteStreamControllerEnqueueChunkToQueue(controller, buffer, byteOffset, byteLength) { - controller._queue.push({ buffer, byteOffset, byteLength }); - controller._queueTotalSize += byteLength; - } - function ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor) { - const elementSize = pullIntoDescriptor.elementSize; - const currentAlignedBytes = pullIntoDescriptor.bytesFilled - pullIntoDescriptor.bytesFilled % elementSize; - const maxBytesToCopy = Math.min(controller._queueTotalSize, pullIntoDescriptor.byteLength - pullIntoDescriptor.bytesFilled); - const maxBytesFilled = pullIntoDescriptor.bytesFilled + maxBytesToCopy; - const maxAlignedBytes = maxBytesFilled - maxBytesFilled % elementSize; - let totalBytesToCopyRemaining = maxBytesToCopy; - let ready = false; - if (maxAlignedBytes > currentAlignedBytes) { - totalBytesToCopyRemaining = maxAlignedBytes - pullIntoDescriptor.bytesFilled; - ready = true; - } - const queue = controller._queue; - while (totalBytesToCopyRemaining > 0) { - const headOfQueue = queue.peek(); - const bytesToCopy = Math.min(totalBytesToCopyRemaining, headOfQueue.byteLength); - const destStart = pullIntoDescriptor.byteOffset + pullIntoDescriptor.bytesFilled; - CopyDataBlockBytes(pullIntoDescriptor.buffer, destStart, headOfQueue.buffer, headOfQueue.byteOffset, bytesToCopy); - if (headOfQueue.byteLength === bytesToCopy) { - queue.shift(); - } - else { - headOfQueue.byteOffset += bytesToCopy; - headOfQueue.byteLength -= bytesToCopy; - } - controller._queueTotalSize -= bytesToCopy; - ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, bytesToCopy, pullIntoDescriptor); - totalBytesToCopyRemaining -= bytesToCopy; - } - return ready; - } - function ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, size, pullIntoDescriptor) { - ReadableByteStreamControllerInvalidateBYOBRequest(controller); - pullIntoDescriptor.bytesFilled += size; - } - function ReadableByteStreamControllerHandleQueueDrain(controller) { - if (controller._queueTotalSize === 0 && controller._closeRequested) { - ReadableByteStreamControllerClearAlgorithms(controller); - ReadableStreamClose(controller._controlledReadableByteStream); - } - else { - ReadableByteStreamControllerCallPullIfNeeded(controller); - } - } - function ReadableByteStreamControllerInvalidateBYOBRequest(controller) { - if (controller._byobRequest === null) { - return; - } - controller._byobRequest._associatedReadableByteStreamController = undefined; - controller._byobRequest._view = null; - controller._byobRequest = null; - } - function ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller) { - while (controller._pendingPullIntos.length > 0) { - if (controller._queueTotalSize === 0) { - return; - } - const pullIntoDescriptor = controller._pendingPullIntos.peek(); - if (ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor)) { - ReadableByteStreamControllerShiftPendingPullInto(controller); - ReadableByteStreamControllerCommitPullIntoDescriptor(controller._controlledReadableByteStream, pullIntoDescriptor); - } - } - } - function ReadableByteStreamControllerPullInto(controller, view, readIntoRequest) { - const stream = controller._controlledReadableByteStream; - let elementSize = 1; - if (view.constructor !== DataView) { - elementSize = view.constructor.BYTES_PER_ELEMENT; - } - const ctor = view.constructor; - const buffer = TransferArrayBuffer(view.buffer); - const pullIntoDescriptor = { - buffer, - byteOffset: view.byteOffset, - byteLength: view.byteLength, - bytesFilled: 0, - elementSize, - viewConstructor: ctor, - readerType: 'byob' - }; - if (controller._pendingPullIntos.length > 0) { - controller._pendingPullIntos.push(pullIntoDescriptor); - // No ReadableByteStreamControllerCallPullIfNeeded() call since: - // - No change happens on desiredSize - // - The source has already been notified of that there's at least 1 pending read(view) - ReadableStreamAddReadIntoRequest(stream, readIntoRequest); - return; - } - if (stream._state === 'closed') { - const emptyView = new ctor(pullIntoDescriptor.buffer, pullIntoDescriptor.byteOffset, 0); - readIntoRequest._closeSteps(emptyView); - return; - } - if (controller._queueTotalSize > 0) { - if (ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor)) { - const filledView = ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor); - ReadableByteStreamControllerHandleQueueDrain(controller); - readIntoRequest._chunkSteps(filledView); - return; - } - if (controller._closeRequested) { - const e = new TypeError('Insufficient bytes to fill elements in the given buffer'); - ReadableByteStreamControllerError(controller, e); - readIntoRequest._errorSteps(e); - return; - } - } - controller._pendingPullIntos.push(pullIntoDescriptor); - ReadableStreamAddReadIntoRequest(stream, readIntoRequest); - ReadableByteStreamControllerCallPullIfNeeded(controller); - } - function ReadableByteStreamControllerRespondInClosedState(controller, firstDescriptor) { - firstDescriptor.buffer = TransferArrayBuffer(firstDescriptor.buffer); - const stream = controller._controlledReadableByteStream; - if (ReadableStreamHasBYOBReader(stream)) { - while (ReadableStreamGetNumReadIntoRequests(stream) > 0) { - const pullIntoDescriptor = ReadableByteStreamControllerShiftPendingPullInto(controller); - ReadableByteStreamControllerCommitPullIntoDescriptor(stream, pullIntoDescriptor); - } - } - } - function ReadableByteStreamControllerRespondInReadableState(controller, bytesWritten, pullIntoDescriptor) { - if (pullIntoDescriptor.bytesFilled + bytesWritten > pullIntoDescriptor.byteLength) { - throw new RangeError('bytesWritten out of range'); - } - ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, bytesWritten, pullIntoDescriptor); - if (pullIntoDescriptor.bytesFilled < pullIntoDescriptor.elementSize) { - // TODO: Figure out whether we should detach the buffer or not here. - return; - } - ReadableByteStreamControllerShiftPendingPullInto(controller); - const remainderSize = pullIntoDescriptor.bytesFilled % pullIntoDescriptor.elementSize; - if (remainderSize > 0) { - const end = pullIntoDescriptor.byteOffset + pullIntoDescriptor.bytesFilled; - const remainder = pullIntoDescriptor.buffer.slice(end - remainderSize, end); - ReadableByteStreamControllerEnqueueChunkToQueue(controller, remainder, 0, remainder.byteLength); - } - pullIntoDescriptor.buffer = TransferArrayBuffer(pullIntoDescriptor.buffer); - pullIntoDescriptor.bytesFilled -= remainderSize; - ReadableByteStreamControllerCommitPullIntoDescriptor(controller._controlledReadableByteStream, pullIntoDescriptor); - ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller); - } - function ReadableByteStreamControllerRespondInternal(controller, bytesWritten) { - const firstDescriptor = controller._pendingPullIntos.peek(); - const state = controller._controlledReadableByteStream._state; - if (state === 'closed') { - if (bytesWritten !== 0) { - throw new TypeError('bytesWritten must be 0 when calling respond() on a closed stream'); - } - ReadableByteStreamControllerRespondInClosedState(controller, firstDescriptor); - } - else { - ReadableByteStreamControllerRespondInReadableState(controller, bytesWritten, firstDescriptor); - } - ReadableByteStreamControllerCallPullIfNeeded(controller); - } - function ReadableByteStreamControllerShiftPendingPullInto(controller) { - const descriptor = controller._pendingPullIntos.shift(); - ReadableByteStreamControllerInvalidateBYOBRequest(controller); - return descriptor; - } - function ReadableByteStreamControllerShouldCallPull(controller) { - const stream = controller._controlledReadableByteStream; - if (stream._state !== 'readable') { - return false; - } - if (controller._closeRequested) { - return false; - } - if (!controller._started) { - return false; - } - if (ReadableStreamHasDefaultReader(stream) && ReadableStreamGetNumReadRequests(stream) > 0) { - return true; - } - if (ReadableStreamHasBYOBReader(stream) && ReadableStreamGetNumReadIntoRequests(stream) > 0) { - return true; - } - const desiredSize = ReadableByteStreamControllerGetDesiredSize(controller); - if (desiredSize > 0) { - return true; - } - return false; - } - function ReadableByteStreamControllerClearAlgorithms(controller) { - controller._pullAlgorithm = undefined; - controller._cancelAlgorithm = undefined; - } - // A client of ReadableByteStreamController may use these functions directly to bypass state check. - function ReadableByteStreamControllerClose(controller) { - const stream = controller._controlledReadableByteStream; - if (controller._closeRequested || stream._state !== 'readable') { - return; - } - if (controller._queueTotalSize > 0) { - controller._closeRequested = true; - return; - } - if (controller._pendingPullIntos.length > 0) { - const firstPendingPullInto = controller._pendingPullIntos.peek(); - if (firstPendingPullInto.bytesFilled > 0) { - const e = new TypeError('Insufficient bytes to fill elements in the given buffer'); - ReadableByteStreamControllerError(controller, e); - throw e; - } - } - ReadableByteStreamControllerClearAlgorithms(controller); - ReadableStreamClose(stream); - } - function ReadableByteStreamControllerEnqueue(controller, chunk) { - const stream = controller._controlledReadableByteStream; - if (controller._closeRequested || stream._state !== 'readable') { - return; - } - const buffer = chunk.buffer; - const byteOffset = chunk.byteOffset; - const byteLength = chunk.byteLength; - const transferredBuffer = TransferArrayBuffer(buffer); - if (ReadableStreamHasDefaultReader(stream)) { - if (ReadableStreamGetNumReadRequests(stream) === 0) { - ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength); - } - else { - const transferredView = new Uint8Array(transferredBuffer, byteOffset, byteLength); - ReadableStreamFulfillReadRequest(stream, transferredView, false); - } - } - else if (ReadableStreamHasBYOBReader(stream)) { - // TODO: Ideally in this branch detaching should happen only if the buffer is not consumed fully. - ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength); - ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller); - } - else { - ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength); - } - ReadableByteStreamControllerCallPullIfNeeded(controller); - } - function ReadableByteStreamControllerError(controller, e) { - const stream = controller._controlledReadableByteStream; - if (stream._state !== 'readable') { - return; - } - ReadableByteStreamControllerClearPendingPullIntos(controller); - ResetQueue(controller); - ReadableByteStreamControllerClearAlgorithms(controller); - ReadableStreamError(stream, e); - } - function ReadableByteStreamControllerGetDesiredSize(controller) { - const state = controller._controlledReadableByteStream._state; - if (state === 'errored') { - return null; - } - if (state === 'closed') { - return 0; - } - return controller._strategyHWM - controller._queueTotalSize; - } - function ReadableByteStreamControllerRespond(controller, bytesWritten) { - bytesWritten = Number(bytesWritten); - if (!IsFiniteNonNegativeNumber(bytesWritten)) { - throw new RangeError('bytesWritten must be a finite'); - } - ReadableByteStreamControllerRespondInternal(controller, bytesWritten); - } - function ReadableByteStreamControllerRespondWithNewView(controller, view) { - const firstDescriptor = controller._pendingPullIntos.peek(); - if (firstDescriptor.byteOffset + firstDescriptor.bytesFilled !== view.byteOffset) { - throw new RangeError('The region specified by view does not match byobRequest'); - } - if (firstDescriptor.byteLength !== view.byteLength) { - throw new RangeError('The buffer of view has different capacity than byobRequest'); - } - firstDescriptor.buffer = view.buffer; - ReadableByteStreamControllerRespondInternal(controller, view.byteLength); - } - function SetUpReadableByteStreamController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, autoAllocateChunkSize) { - controller._controlledReadableByteStream = stream; - controller._pullAgain = false; - controller._pulling = false; - controller._byobRequest = null; - // Need to set the slots so that the assert doesn't fire. In the spec the slots already exist implicitly. - controller._queue = controller._queueTotalSize = undefined; - ResetQueue(controller); - controller._closeRequested = false; - controller._started = false; - controller._strategyHWM = highWaterMark; - controller._pullAlgorithm = pullAlgorithm; - controller._cancelAlgorithm = cancelAlgorithm; - controller._autoAllocateChunkSize = autoAllocateChunkSize; - controller._pendingPullIntos = new SimpleQueue(); - stream._readableStreamController = controller; - const startResult = startAlgorithm(); - uponPromise(promiseResolvedWith(startResult), () => { - controller._started = true; - ReadableByteStreamControllerCallPullIfNeeded(controller); - }, r => { - ReadableByteStreamControllerError(controller, r); - }); - } - function SetUpReadableByteStreamControllerFromUnderlyingSource(stream, underlyingByteSource, highWaterMark) { - const controller = Object.create(ReadableByteStreamController.prototype); - let startAlgorithm = () => undefined; - let pullAlgorithm = () => promiseResolvedWith(undefined); - let cancelAlgorithm = () => promiseResolvedWith(undefined); - if (underlyingByteSource.start !== undefined) { - startAlgorithm = () => underlyingByteSource.start(controller); - } - if (underlyingByteSource.pull !== undefined) { - pullAlgorithm = () => underlyingByteSource.pull(controller); - } - if (underlyingByteSource.cancel !== undefined) { - cancelAlgorithm = reason => underlyingByteSource.cancel(reason); - } - const autoAllocateChunkSize = underlyingByteSource.autoAllocateChunkSize; - if (autoAllocateChunkSize === 0) { - throw new TypeError('autoAllocateChunkSize must be greater than 0'); - } - SetUpReadableByteStreamController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, autoAllocateChunkSize); - } - function SetUpReadableStreamBYOBRequest(request, controller, view) { - request._associatedReadableByteStreamController = controller; - request._view = view; - } - // Helper functions for the ReadableStreamBYOBRequest. - function byobRequestBrandCheckException(name) { - return new TypeError(`ReadableStreamBYOBRequest.prototype.${name} can only be used on a ReadableStreamBYOBRequest`); - } - // Helper functions for the ReadableByteStreamController. - function byteStreamControllerBrandCheckException(name) { - return new TypeError(`ReadableByteStreamController.prototype.${name} can only be used on a ReadableByteStreamController`); - } - - // Abstract operations for the ReadableStream. - function AcquireReadableStreamBYOBReader(stream) { - return new ReadableStreamBYOBReader(stream); - } - // ReadableStream API exposed for controllers. - function ReadableStreamAddReadIntoRequest(stream, readIntoRequest) { - stream._reader._readIntoRequests.push(readIntoRequest); - } - function ReadableStreamFulfillReadIntoRequest(stream, chunk, done) { - const reader = stream._reader; - const readIntoRequest = reader._readIntoRequests.shift(); - if (done) { - readIntoRequest._closeSteps(chunk); - } - else { - readIntoRequest._chunkSteps(chunk); - } - } - function ReadableStreamGetNumReadIntoRequests(stream) { - return stream._reader._readIntoRequests.length; - } - function ReadableStreamHasBYOBReader(stream) { - const reader = stream._reader; - if (reader === undefined) { - return false; - } - if (!IsReadableStreamBYOBReader(reader)) { - return false; - } - return true; - } - /** - * A BYOB reader vended by a {@link ReadableStream}. - * - * @public - */ - class ReadableStreamBYOBReader { - constructor(stream) { - assertRequiredArgument(stream, 1, 'ReadableStreamBYOBReader'); - assertReadableStream(stream, 'First parameter'); - if (IsReadableStreamLocked(stream)) { - throw new TypeError('This stream has already been locked for exclusive reading by another reader'); - } - if (!IsReadableByteStreamController(stream._readableStreamController)) { - throw new TypeError('Cannot construct a ReadableStreamBYOBReader for a stream not constructed with a byte ' + - 'source'); - } - ReadableStreamReaderGenericInitialize(this, stream); - this._readIntoRequests = new SimpleQueue(); - } - /** - * Returns a promise that will be fulfilled when the stream becomes closed, or rejected if the stream ever errors or - * the reader's lock is released before the stream finishes closing. - */ - get closed() { - if (!IsReadableStreamBYOBReader(this)) { - return promiseRejectedWith(byobReaderBrandCheckException('closed')); - } - return this._closedPromise; - } - /** - * If the reader is active, behaves the same as {@link ReadableStream.cancel | stream.cancel(reason)}. - */ - cancel(reason = undefined) { - if (!IsReadableStreamBYOBReader(this)) { - return promiseRejectedWith(byobReaderBrandCheckException('cancel')); - } - if (this._ownerReadableStream === undefined) { - return promiseRejectedWith(readerLockException('cancel')); - } - return ReadableStreamReaderGenericCancel(this, reason); - } - /** - * Attempts to reads bytes into view, and returns a promise resolved with the result. - * - * If reading a chunk causes the queue to become empty, more data will be pulled from the underlying source. - */ - read(view) { - if (!IsReadableStreamBYOBReader(this)) { - return promiseRejectedWith(byobReaderBrandCheckException('read')); - } - if (!ArrayBuffer.isView(view)) { - return promiseRejectedWith(new TypeError('view must be an array buffer view')); - } - if (view.byteLength === 0) { - return promiseRejectedWith(new TypeError('view must have non-zero byteLength')); - } - if (view.buffer.byteLength === 0) { - return promiseRejectedWith(new TypeError(`view's buffer must have non-zero byteLength`)); - } - if (this._ownerReadableStream === undefined) { - return promiseRejectedWith(readerLockException('read from')); - } - let resolvePromise; - let rejectPromise; - const promise = newPromise((resolve, reject) => { - resolvePromise = resolve; - rejectPromise = reject; - }); - const readIntoRequest = { - _chunkSteps: chunk => resolvePromise({ value: chunk, done: false }), - _closeSteps: chunk => resolvePromise({ value: chunk, done: true }), - _errorSteps: e => rejectPromise(e) - }; - ReadableStreamBYOBReaderRead(this, view, readIntoRequest); - return promise; - } - /** - * Releases the reader's lock on the corresponding stream. After the lock is released, the reader is no longer active. - * If the associated stream is errored when the lock is released, the reader will appear errored in the same way - * from now on; otherwise, the reader will appear closed. - * - * A reader's lock cannot be released while it still has a pending read request, i.e., if a promise returned by - * the reader's {@link ReadableStreamBYOBReader.read | read()} method has not yet been settled. Attempting to - * do so will throw a `TypeError` and leave the reader locked to the stream. - */ - releaseLock() { - if (!IsReadableStreamBYOBReader(this)) { - throw byobReaderBrandCheckException('releaseLock'); - } - if (this._ownerReadableStream === undefined) { - return; - } - if (this._readIntoRequests.length > 0) { - throw new TypeError('Tried to release a reader lock when that reader has pending read() calls un-settled'); - } - ReadableStreamReaderGenericRelease(this); - } - } - Object.defineProperties(ReadableStreamBYOBReader.prototype, { - cancel: { enumerable: true }, - read: { enumerable: true }, - releaseLock: { enumerable: true }, - closed: { enumerable: true } - }); - if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(ReadableStreamBYOBReader.prototype, SymbolPolyfill.toStringTag, { - value: 'ReadableStreamBYOBReader', - configurable: true - }); - } - // Abstract operations for the readers. - function IsReadableStreamBYOBReader(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_readIntoRequests')) { - return false; - } - return true; - } - function ReadableStreamBYOBReaderRead(reader, view, readIntoRequest) { - const stream = reader._ownerReadableStream; - stream._disturbed = true; - if (stream._state === 'errored') { - readIntoRequest._errorSteps(stream._storedError); - } - else { - ReadableByteStreamControllerPullInto(stream._readableStreamController, view, readIntoRequest); - } - } - // Helper functions for the ReadableStreamBYOBReader. - function byobReaderBrandCheckException(name) { - return new TypeError(`ReadableStreamBYOBReader.prototype.${name} can only be used on a ReadableStreamBYOBReader`); - } - - function ExtractHighWaterMark(strategy, defaultHWM) { - const { highWaterMark } = strategy; - if (highWaterMark === undefined) { - return defaultHWM; - } - if (NumberIsNaN(highWaterMark) || highWaterMark < 0) { - throw new RangeError('Invalid highWaterMark'); - } - return highWaterMark; - } - function ExtractSizeAlgorithm(strategy) { - const { size } = strategy; - if (!size) { - return () => 1; - } - return size; - } - - function convertQueuingStrategy(init, context) { - assertDictionary(init, context); - const highWaterMark = init === null || init === void 0 ? void 0 : init.highWaterMark; - const size = init === null || init === void 0 ? void 0 : init.size; - return { - highWaterMark: highWaterMark === undefined ? undefined : convertUnrestrictedDouble(highWaterMark), - size: size === undefined ? undefined : convertQueuingStrategySize(size, `${context} has member 'size' that`) - }; - } - function convertQueuingStrategySize(fn, context) { - assertFunction(fn, context); - return chunk => convertUnrestrictedDouble(fn(chunk)); - } - - function convertUnderlyingSink(original, context) { - assertDictionary(original, context); - const abort = original === null || original === void 0 ? void 0 : original.abort; - const close = original === null || original === void 0 ? void 0 : original.close; - const start = original === null || original === void 0 ? void 0 : original.start; - const type = original === null || original === void 0 ? void 0 : original.type; - const write = original === null || original === void 0 ? void 0 : original.write; - return { - abort: abort === undefined ? - undefined : - convertUnderlyingSinkAbortCallback(abort, original, `${context} has member 'abort' that`), - close: close === undefined ? - undefined : - convertUnderlyingSinkCloseCallback(close, original, `${context} has member 'close' that`), - start: start === undefined ? - undefined : - convertUnderlyingSinkStartCallback(start, original, `${context} has member 'start' that`), - write: write === undefined ? - undefined : - convertUnderlyingSinkWriteCallback(write, original, `${context} has member 'write' that`), - type - }; - } - function convertUnderlyingSinkAbortCallback(fn, original, context) { - assertFunction(fn, context); - return (reason) => promiseCall(fn, original, [reason]); - } - function convertUnderlyingSinkCloseCallback(fn, original, context) { - assertFunction(fn, context); - return () => promiseCall(fn, original, []); - } - function convertUnderlyingSinkStartCallback(fn, original, context) { - assertFunction(fn, context); - return (controller) => reflectCall(fn, original, [controller]); - } - function convertUnderlyingSinkWriteCallback(fn, original, context) { - assertFunction(fn, context); - return (chunk, controller) => promiseCall(fn, original, [chunk, controller]); - } - - function assertWritableStream(x, context) { - if (!IsWritableStream(x)) { - throw new TypeError(`${context} is not a WritableStream.`); - } - } - - /** - * A writable stream represents a destination for data, into which you can write. - * - * @public - */ - class WritableStream$1 { - constructor(rawUnderlyingSink = {}, rawStrategy = {}) { - if (rawUnderlyingSink === undefined) { - rawUnderlyingSink = null; - } - else { - assertObject(rawUnderlyingSink, 'First parameter'); - } - const strategy = convertQueuingStrategy(rawStrategy, 'Second parameter'); - const underlyingSink = convertUnderlyingSink(rawUnderlyingSink, 'First parameter'); - InitializeWritableStream(this); - const type = underlyingSink.type; - if (type !== undefined) { - throw new RangeError('Invalid type is specified'); - } - const sizeAlgorithm = ExtractSizeAlgorithm(strategy); - const highWaterMark = ExtractHighWaterMark(strategy, 1); - SetUpWritableStreamDefaultControllerFromUnderlyingSink(this, underlyingSink, highWaterMark, sizeAlgorithm); - } - /** - * Returns whether or not the writable stream is locked to a writer. - */ - get locked() { - if (!IsWritableStream(this)) { - throw streamBrandCheckException$2('locked'); - } - return IsWritableStreamLocked(this); - } - /** - * Aborts the stream, signaling that the producer can no longer successfully write to the stream and it is to be - * immediately moved to an errored state, with any queued-up writes discarded. This will also execute any abort - * mechanism of the underlying sink. - * - * The returned promise will fulfill if the stream shuts down successfully, or reject if the underlying sink signaled - * that there was an error doing so. Additionally, it will reject with a `TypeError` (without attempting to cancel - * the stream) if the stream is currently locked. - */ - abort(reason = undefined) { - if (!IsWritableStream(this)) { - return promiseRejectedWith(streamBrandCheckException$2('abort')); - } - if (IsWritableStreamLocked(this)) { - return promiseRejectedWith(new TypeError('Cannot abort a stream that already has a writer')); - } - return WritableStreamAbort(this, reason); - } - /** - * Closes the stream. The underlying sink will finish processing any previously-written chunks, before invoking its - * close behavior. During this time any further attempts to write will fail (without erroring the stream). - * - * The method returns a promise that will fulfill if all remaining chunks are successfully written and the stream - * successfully closes, or rejects if an error is encountered during this process. Additionally, it will reject with - * a `TypeError` (without attempting to cancel the stream) if the stream is currently locked. - */ - close() { - if (!IsWritableStream(this)) { - return promiseRejectedWith(streamBrandCheckException$2('close')); - } - if (IsWritableStreamLocked(this)) { - return promiseRejectedWith(new TypeError('Cannot close a stream that already has a writer')); - } - if (WritableStreamCloseQueuedOrInFlight(this)) { - return promiseRejectedWith(new TypeError('Cannot close an already-closing stream')); - } - return WritableStreamClose(this); - } - /** - * Creates a {@link WritableStreamDefaultWriter | writer} and locks the stream to the new writer. While the stream - * is locked, no other writer can be acquired until this one is released. - * - * This functionality is especially useful for creating abstractions that desire the ability to write to a stream - * without interruption or interleaving. By getting a writer for the stream, you can ensure nobody else can write at - * the same time, which would cause the resulting written data to be unpredictable and probably useless. - */ - getWriter() { - if (!IsWritableStream(this)) { - throw streamBrandCheckException$2('getWriter'); - } - return AcquireWritableStreamDefaultWriter(this); - } - } - Object.defineProperties(WritableStream$1.prototype, { - abort: { enumerable: true }, - close: { enumerable: true }, - getWriter: { enumerable: true }, - locked: { enumerable: true } - }); - if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(WritableStream$1.prototype, SymbolPolyfill.toStringTag, { - value: 'WritableStream', - configurable: true - }); - } - // Abstract operations for the WritableStream. - function AcquireWritableStreamDefaultWriter(stream) { - return new WritableStreamDefaultWriter(stream); - } - // Throws if and only if startAlgorithm throws. - function CreateWritableStream(startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark = 1, sizeAlgorithm = () => 1) { - const stream = Object.create(WritableStream$1.prototype); - InitializeWritableStream(stream); - const controller = Object.create(WritableStreamDefaultController.prototype); - SetUpWritableStreamDefaultController(stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark, sizeAlgorithm); - return stream; - } - function InitializeWritableStream(stream) { - stream._state = 'writable'; - // The error that will be reported by new method calls once the state becomes errored. Only set when [[state]] is - // 'erroring' or 'errored'. May be set to an undefined value. - stream._storedError = undefined; - stream._writer = undefined; - // Initialize to undefined first because the constructor of the controller checks this - // variable to validate the caller. - stream._writableStreamController = undefined; - // This queue is placed here instead of the writer class in order to allow for passing a writer to the next data - // producer without waiting for the queued writes to finish. - stream._writeRequests = new SimpleQueue(); - // Write requests are removed from _writeRequests when write() is called on the underlying sink. This prevents - // them from being erroneously rejected on error. If a write() call is in-flight, the request is stored here. - stream._inFlightWriteRequest = undefined; - // The promise that was returned from writer.close(). Stored here because it may be fulfilled after the writer - // has been detached. - stream._closeRequest = undefined; - // Close request is removed from _closeRequest when close() is called on the underlying sink. This prevents it - // from being erroneously rejected on error. If a close() call is in-flight, the request is stored here. - stream._inFlightCloseRequest = undefined; - // The promise that was returned from writer.abort(). This may also be fulfilled after the writer has detached. - stream._pendingAbortRequest = undefined; - // The backpressure signal set by the controller. - stream._backpressure = false; - } - function IsWritableStream(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_writableStreamController')) { - return false; - } - return true; - } - function IsWritableStreamLocked(stream) { - if (stream._writer === undefined) { - return false; - } - return true; - } - function WritableStreamAbort(stream, reason) { - const state = stream._state; - if (state === 'closed' || state === 'errored') { - return promiseResolvedWith(undefined); - } - if (stream._pendingAbortRequest !== undefined) { - return stream._pendingAbortRequest._promise; - } - let wasAlreadyErroring = false; - if (state === 'erroring') { - wasAlreadyErroring = true; - // reason will not be used, so don't keep a reference to it. - reason = undefined; - } - const promise = newPromise((resolve, reject) => { - stream._pendingAbortRequest = { - _promise: undefined, - _resolve: resolve, - _reject: reject, - _reason: reason, - _wasAlreadyErroring: wasAlreadyErroring - }; - }); - stream._pendingAbortRequest._promise = promise; - if (!wasAlreadyErroring) { - WritableStreamStartErroring(stream, reason); - } - return promise; - } - function WritableStreamClose(stream) { - const state = stream._state; - if (state === 'closed' || state === 'errored') { - return promiseRejectedWith(new TypeError(`The stream (in ${state} state) is not in the writable state and cannot be closed`)); - } - const promise = newPromise((resolve, reject) => { - const closeRequest = { - _resolve: resolve, - _reject: reject - }; - stream._closeRequest = closeRequest; - }); - const writer = stream._writer; - if (writer !== undefined && stream._backpressure && state === 'writable') { - defaultWriterReadyPromiseResolve(writer); - } - WritableStreamDefaultControllerClose(stream._writableStreamController); - return promise; - } - // WritableStream API exposed for controllers. - function WritableStreamAddWriteRequest(stream) { - const promise = newPromise((resolve, reject) => { - const writeRequest = { - _resolve: resolve, - _reject: reject - }; - stream._writeRequests.push(writeRequest); - }); - return promise; - } - function WritableStreamDealWithRejection(stream, error) { - const state = stream._state; - if (state === 'writable') { - WritableStreamStartErroring(stream, error); - return; - } - WritableStreamFinishErroring(stream); - } - function WritableStreamStartErroring(stream, reason) { - const controller = stream._writableStreamController; - stream._state = 'erroring'; - stream._storedError = reason; - const writer = stream._writer; - if (writer !== undefined) { - WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, reason); - } - if (!WritableStreamHasOperationMarkedInFlight(stream) && controller._started) { - WritableStreamFinishErroring(stream); - } - } - function WritableStreamFinishErroring(stream) { - stream._state = 'errored'; - stream._writableStreamController[ErrorSteps](); - const storedError = stream._storedError; - stream._writeRequests.forEach(writeRequest => { - writeRequest._reject(storedError); - }); - stream._writeRequests = new SimpleQueue(); - if (stream._pendingAbortRequest === undefined) { - WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); - return; - } - const abortRequest = stream._pendingAbortRequest; - stream._pendingAbortRequest = undefined; - if (abortRequest._wasAlreadyErroring) { - abortRequest._reject(storedError); - WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); - return; - } - const promise = stream._writableStreamController[AbortSteps](abortRequest._reason); - uponPromise(promise, () => { - abortRequest._resolve(); - WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); - }, (reason) => { - abortRequest._reject(reason); - WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); - }); - } - function WritableStreamFinishInFlightWrite(stream) { - stream._inFlightWriteRequest._resolve(undefined); - stream._inFlightWriteRequest = undefined; - } - function WritableStreamFinishInFlightWriteWithError(stream, error) { - stream._inFlightWriteRequest._reject(error); - stream._inFlightWriteRequest = undefined; - WritableStreamDealWithRejection(stream, error); - } - function WritableStreamFinishInFlightClose(stream) { - stream._inFlightCloseRequest._resolve(undefined); - stream._inFlightCloseRequest = undefined; - const state = stream._state; - if (state === 'erroring') { - // The error was too late to do anything, so it is ignored. - stream._storedError = undefined; - if (stream._pendingAbortRequest !== undefined) { - stream._pendingAbortRequest._resolve(); - stream._pendingAbortRequest = undefined; - } - } - stream._state = 'closed'; - const writer = stream._writer; - if (writer !== undefined) { - defaultWriterClosedPromiseResolve(writer); - } - } - function WritableStreamFinishInFlightCloseWithError(stream, error) { - stream._inFlightCloseRequest._reject(error); - stream._inFlightCloseRequest = undefined; - // Never execute sink abort() after sink close(). - if (stream._pendingAbortRequest !== undefined) { - stream._pendingAbortRequest._reject(error); - stream._pendingAbortRequest = undefined; - } - WritableStreamDealWithRejection(stream, error); - } - // TODO(ricea): Fix alphabetical order. - function WritableStreamCloseQueuedOrInFlight(stream) { - if (stream._closeRequest === undefined && stream._inFlightCloseRequest === undefined) { - return false; - } - return true; - } - function WritableStreamHasOperationMarkedInFlight(stream) { - if (stream._inFlightWriteRequest === undefined && stream._inFlightCloseRequest === undefined) { - return false; - } - return true; - } - function WritableStreamMarkCloseRequestInFlight(stream) { - stream._inFlightCloseRequest = stream._closeRequest; - stream._closeRequest = undefined; - } - function WritableStreamMarkFirstWriteRequestInFlight(stream) { - stream._inFlightWriteRequest = stream._writeRequests.shift(); - } - function WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream) { - if (stream._closeRequest !== undefined) { - stream._closeRequest._reject(stream._storedError); - stream._closeRequest = undefined; - } - const writer = stream._writer; - if (writer !== undefined) { - defaultWriterClosedPromiseReject(writer, stream._storedError); - } - } - function WritableStreamUpdateBackpressure(stream, backpressure) { - const writer = stream._writer; - if (writer !== undefined && backpressure !== stream._backpressure) { - if (backpressure) { - defaultWriterReadyPromiseReset(writer); - } - else { - defaultWriterReadyPromiseResolve(writer); - } - } - stream._backpressure = backpressure; - } - /** - * A default writer vended by a {@link WritableStream}. - * - * @public - */ - class WritableStreamDefaultWriter { - constructor(stream) { - assertRequiredArgument(stream, 1, 'WritableStreamDefaultWriter'); - assertWritableStream(stream, 'First parameter'); - if (IsWritableStreamLocked(stream)) { - throw new TypeError('This stream has already been locked for exclusive writing by another writer'); - } - this._ownerWritableStream = stream; - stream._writer = this; - const state = stream._state; - if (state === 'writable') { - if (!WritableStreamCloseQueuedOrInFlight(stream) && stream._backpressure) { - defaultWriterReadyPromiseInitialize(this); - } - else { - defaultWriterReadyPromiseInitializeAsResolved(this); - } - defaultWriterClosedPromiseInitialize(this); - } - else if (state === 'erroring') { - defaultWriterReadyPromiseInitializeAsRejected(this, stream._storedError); - defaultWriterClosedPromiseInitialize(this); - } - else if (state === 'closed') { - defaultWriterReadyPromiseInitializeAsResolved(this); - defaultWriterClosedPromiseInitializeAsResolved(this); - } - else { - const storedError = stream._storedError; - defaultWriterReadyPromiseInitializeAsRejected(this, storedError); - defaultWriterClosedPromiseInitializeAsRejected(this, storedError); - } - } - /** - * Returns a promise that will be fulfilled when the stream becomes closed, or rejected if the stream ever errors or - * the writer’s lock is released before the stream finishes closing. - */ - get closed() { - if (!IsWritableStreamDefaultWriter(this)) { - return promiseRejectedWith(defaultWriterBrandCheckException('closed')); - } - return this._closedPromise; - } - /** - * Returns the desired size to fill the stream’s internal queue. It can be negative, if the queue is over-full. - * A producer can use this information to determine the right amount of data to write. - * - * It will be `null` if the stream cannot be successfully written to (due to either being errored, or having an abort - * queued up). It will return zero if the stream is closed. And the getter will throw an exception if invoked when - * the writer’s lock is released. - */ - get desiredSize() { - if (!IsWritableStreamDefaultWriter(this)) { - throw defaultWriterBrandCheckException('desiredSize'); - } - if (this._ownerWritableStream === undefined) { - throw defaultWriterLockException('desiredSize'); - } - return WritableStreamDefaultWriterGetDesiredSize(this); - } - /** - * Returns a promise that will be fulfilled when the desired size to fill the stream’s internal queue transitions - * from non-positive to positive, signaling that it is no longer applying backpressure. Once the desired size dips - * back to zero or below, the getter will return a new promise that stays pending until the next transition. - * - * If the stream becomes errored or aborted, or the writer’s lock is released, the returned promise will become - * rejected. - */ - get ready() { - if (!IsWritableStreamDefaultWriter(this)) { - return promiseRejectedWith(defaultWriterBrandCheckException('ready')); - } - return this._readyPromise; - } - /** - * If the reader is active, behaves the same as {@link WritableStream.abort | stream.abort(reason)}. - */ - abort(reason = undefined) { - if (!IsWritableStreamDefaultWriter(this)) { - return promiseRejectedWith(defaultWriterBrandCheckException('abort')); - } - if (this._ownerWritableStream === undefined) { - return promiseRejectedWith(defaultWriterLockException('abort')); - } - return WritableStreamDefaultWriterAbort(this, reason); - } - /** - * If the reader is active, behaves the same as {@link WritableStream.close | stream.close()}. - */ - close() { - if (!IsWritableStreamDefaultWriter(this)) { - return promiseRejectedWith(defaultWriterBrandCheckException('close')); - } - const stream = this._ownerWritableStream; - if (stream === undefined) { - return promiseRejectedWith(defaultWriterLockException('close')); - } - if (WritableStreamCloseQueuedOrInFlight(stream)) { - return promiseRejectedWith(new TypeError('Cannot close an already-closing stream')); - } - return WritableStreamDefaultWriterClose(this); - } - /** - * Releases the writer’s lock on the corresponding stream. After the lock is released, the writer is no longer active. - * If the associated stream is errored when the lock is released, the writer will appear errored in the same way from - * now on; otherwise, the writer will appear closed. - * - * Note that the lock can still be released even if some ongoing writes have not yet finished (i.e. even if the - * promises returned from previous calls to {@link WritableStreamDefaultWriter.write | write()} have not yet settled). - * It’s not necessary to hold the lock on the writer for the duration of the write; the lock instead simply prevents - * other producers from writing in an interleaved manner. - */ - releaseLock() { - if (!IsWritableStreamDefaultWriter(this)) { - throw defaultWriterBrandCheckException('releaseLock'); - } - const stream = this._ownerWritableStream; - if (stream === undefined) { - return; - } - WritableStreamDefaultWriterRelease(this); - } - write(chunk = undefined) { - if (!IsWritableStreamDefaultWriter(this)) { - return promiseRejectedWith(defaultWriterBrandCheckException('write')); - } - if (this._ownerWritableStream === undefined) { - return promiseRejectedWith(defaultWriterLockException('write to')); - } - return WritableStreamDefaultWriterWrite(this, chunk); - } - } - Object.defineProperties(WritableStreamDefaultWriter.prototype, { - abort: { enumerable: true }, - close: { enumerable: true }, - releaseLock: { enumerable: true }, - write: { enumerable: true }, - closed: { enumerable: true }, - desiredSize: { enumerable: true }, - ready: { enumerable: true } - }); - if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(WritableStreamDefaultWriter.prototype, SymbolPolyfill.toStringTag, { - value: 'WritableStreamDefaultWriter', - configurable: true - }); - } - // Abstract operations for the WritableStreamDefaultWriter. - function IsWritableStreamDefaultWriter(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_ownerWritableStream')) { - return false; - } - return true; - } - // A client of WritableStreamDefaultWriter may use these functions directly to bypass state check. - function WritableStreamDefaultWriterAbort(writer, reason) { - const stream = writer._ownerWritableStream; - return WritableStreamAbort(stream, reason); - } - function WritableStreamDefaultWriterClose(writer) { - const stream = writer._ownerWritableStream; - return WritableStreamClose(stream); - } - function WritableStreamDefaultWriterCloseWithErrorPropagation(writer) { - const stream = writer._ownerWritableStream; - const state = stream._state; - if (WritableStreamCloseQueuedOrInFlight(stream) || state === 'closed') { - return promiseResolvedWith(undefined); - } - if (state === 'errored') { - return promiseRejectedWith(stream._storedError); - } - return WritableStreamDefaultWriterClose(writer); - } - function WritableStreamDefaultWriterEnsureClosedPromiseRejected(writer, error) { - if (writer._closedPromiseState === 'pending') { - defaultWriterClosedPromiseReject(writer, error); - } - else { - defaultWriterClosedPromiseResetToRejected(writer, error); - } - } - function WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, error) { - if (writer._readyPromiseState === 'pending') { - defaultWriterReadyPromiseReject(writer, error); - } - else { - defaultWriterReadyPromiseResetToRejected(writer, error); - } - } - function WritableStreamDefaultWriterGetDesiredSize(writer) { - const stream = writer._ownerWritableStream; - const state = stream._state; - if (state === 'errored' || state === 'erroring') { - return null; - } - if (state === 'closed') { - return 0; - } - return WritableStreamDefaultControllerGetDesiredSize(stream._writableStreamController); - } - function WritableStreamDefaultWriterRelease(writer) { - const stream = writer._ownerWritableStream; - const releasedError = new TypeError(`Writer was released and can no longer be used to monitor the stream's closedness`); - WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, releasedError); - // The state transitions to "errored" before the sink abort() method runs, but the writer.closed promise is not - // rejected until afterwards. This means that simply testing state will not work. - WritableStreamDefaultWriterEnsureClosedPromiseRejected(writer, releasedError); - stream._writer = undefined; - writer._ownerWritableStream = undefined; - } - function WritableStreamDefaultWriterWrite(writer, chunk) { - const stream = writer._ownerWritableStream; - const controller = stream._writableStreamController; - const chunkSize = WritableStreamDefaultControllerGetChunkSize(controller, chunk); - if (stream !== writer._ownerWritableStream) { - return promiseRejectedWith(defaultWriterLockException('write to')); - } - const state = stream._state; - if (state === 'errored') { - return promiseRejectedWith(stream._storedError); - } - if (WritableStreamCloseQueuedOrInFlight(stream) || state === 'closed') { - return promiseRejectedWith(new TypeError('The stream is closing or closed and cannot be written to')); - } - if (state === 'erroring') { - return promiseRejectedWith(stream._storedError); - } - const promise = WritableStreamAddWriteRequest(stream); - WritableStreamDefaultControllerWrite(controller, chunk, chunkSize); - return promise; - } - const closeSentinel = {}; - /** - * Allows control of a {@link WritableStream | writable stream}'s state and internal queue. - * - * @public - */ - class WritableStreamDefaultController { - constructor() { - throw new TypeError('Illegal constructor'); - } - /** - * Closes the controlled writable stream, making all future interactions with it fail with the given error `e`. - * - * This method is rarely used, since usually it suffices to return a rejected promise from one of the underlying - * sink's methods. However, it can be useful for suddenly shutting down a stream in response to an event outside the - * normal lifecycle of interactions with the underlying sink. - */ - error(e = undefined) { - if (!IsWritableStreamDefaultController(this)) { - throw new TypeError('WritableStreamDefaultController.prototype.error can only be used on a WritableStreamDefaultController'); - } - const state = this._controlledWritableStream._state; - if (state !== 'writable') { - // The stream is closed, errored or will be soon. The sink can't do anything useful if it gets an error here, so - // just treat it as a no-op. - return; - } - WritableStreamDefaultControllerError(this, e); - } - /** @internal */ - [AbortSteps](reason) { - const result = this._abortAlgorithm(reason); - WritableStreamDefaultControllerClearAlgorithms(this); - return result; - } - /** @internal */ - [ErrorSteps]() { - ResetQueue(this); - } - } - Object.defineProperties(WritableStreamDefaultController.prototype, { - error: { enumerable: true } - }); - if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(WritableStreamDefaultController.prototype, SymbolPolyfill.toStringTag, { - value: 'WritableStreamDefaultController', - configurable: true - }); - } - // Abstract operations implementing interface required by the WritableStream. - function IsWritableStreamDefaultController(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_controlledWritableStream')) { - return false; - } - return true; - } - function SetUpWritableStreamDefaultController(stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark, sizeAlgorithm) { - controller._controlledWritableStream = stream; - stream._writableStreamController = controller; - // Need to set the slots so that the assert doesn't fire. In the spec the slots already exist implicitly. - controller._queue = undefined; - controller._queueTotalSize = undefined; - ResetQueue(controller); - controller._started = false; - controller._strategySizeAlgorithm = sizeAlgorithm; - controller._strategyHWM = highWaterMark; - controller._writeAlgorithm = writeAlgorithm; - controller._closeAlgorithm = closeAlgorithm; - controller._abortAlgorithm = abortAlgorithm; - const backpressure = WritableStreamDefaultControllerGetBackpressure(controller); - WritableStreamUpdateBackpressure(stream, backpressure); - const startResult = startAlgorithm(); - const startPromise = promiseResolvedWith(startResult); - uponPromise(startPromise, () => { - controller._started = true; - WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); - }, r => { - controller._started = true; - WritableStreamDealWithRejection(stream, r); - }); - } - function SetUpWritableStreamDefaultControllerFromUnderlyingSink(stream, underlyingSink, highWaterMark, sizeAlgorithm) { - const controller = Object.create(WritableStreamDefaultController.prototype); - let startAlgorithm = () => undefined; - let writeAlgorithm = () => promiseResolvedWith(undefined); - let closeAlgorithm = () => promiseResolvedWith(undefined); - let abortAlgorithm = () => promiseResolvedWith(undefined); - if (underlyingSink.start !== undefined) { - startAlgorithm = () => underlyingSink.start(controller); - } - if (underlyingSink.write !== undefined) { - writeAlgorithm = chunk => underlyingSink.write(chunk, controller); - } - if (underlyingSink.close !== undefined) { - closeAlgorithm = () => underlyingSink.close(); - } - if (underlyingSink.abort !== undefined) { - abortAlgorithm = reason => underlyingSink.abort(reason); - } - SetUpWritableStreamDefaultController(stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark, sizeAlgorithm); - } - // ClearAlgorithms may be called twice. Erroring the same stream in multiple ways will often result in redundant calls. - function WritableStreamDefaultControllerClearAlgorithms(controller) { - controller._writeAlgorithm = undefined; - controller._closeAlgorithm = undefined; - controller._abortAlgorithm = undefined; - controller._strategySizeAlgorithm = undefined; - } - function WritableStreamDefaultControllerClose(controller) { - EnqueueValueWithSize(controller, closeSentinel, 0); - WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); - } - function WritableStreamDefaultControllerGetChunkSize(controller, chunk) { - try { - return controller._strategySizeAlgorithm(chunk); - } - catch (chunkSizeE) { - WritableStreamDefaultControllerErrorIfNeeded(controller, chunkSizeE); - return 1; - } - } - function WritableStreamDefaultControllerGetDesiredSize(controller) { - return controller._strategyHWM - controller._queueTotalSize; - } - function WritableStreamDefaultControllerWrite(controller, chunk, chunkSize) { - try { - EnqueueValueWithSize(controller, chunk, chunkSize); - } - catch (enqueueE) { - WritableStreamDefaultControllerErrorIfNeeded(controller, enqueueE); - return; - } - const stream = controller._controlledWritableStream; - if (!WritableStreamCloseQueuedOrInFlight(stream) && stream._state === 'writable') { - const backpressure = WritableStreamDefaultControllerGetBackpressure(controller); - WritableStreamUpdateBackpressure(stream, backpressure); - } - WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); - } - // Abstract operations for the WritableStreamDefaultController. - function WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller) { - const stream = controller._controlledWritableStream; - if (!controller._started) { - return; - } - if (stream._inFlightWriteRequest !== undefined) { - return; - } - const state = stream._state; - if (state === 'erroring') { - WritableStreamFinishErroring(stream); - return; - } - if (controller._queue.length === 0) { - return; - } - const value = PeekQueueValue(controller); - if (value === closeSentinel) { - WritableStreamDefaultControllerProcessClose(controller); - } - else { - WritableStreamDefaultControllerProcessWrite(controller, value); - } - } - function WritableStreamDefaultControllerErrorIfNeeded(controller, error) { - if (controller._controlledWritableStream._state === 'writable') { - WritableStreamDefaultControllerError(controller, error); - } - } - function WritableStreamDefaultControllerProcessClose(controller) { - const stream = controller._controlledWritableStream; - WritableStreamMarkCloseRequestInFlight(stream); - DequeueValue(controller); - const sinkClosePromise = controller._closeAlgorithm(); - WritableStreamDefaultControllerClearAlgorithms(controller); - uponPromise(sinkClosePromise, () => { - WritableStreamFinishInFlightClose(stream); - }, reason => { - WritableStreamFinishInFlightCloseWithError(stream, reason); - }); - } - function WritableStreamDefaultControllerProcessWrite(controller, chunk) { - const stream = controller._controlledWritableStream; - WritableStreamMarkFirstWriteRequestInFlight(stream); - const sinkWritePromise = controller._writeAlgorithm(chunk); - uponPromise(sinkWritePromise, () => { - WritableStreamFinishInFlightWrite(stream); - const state = stream._state; - DequeueValue(controller); - if (!WritableStreamCloseQueuedOrInFlight(stream) && state === 'writable') { - const backpressure = WritableStreamDefaultControllerGetBackpressure(controller); - WritableStreamUpdateBackpressure(stream, backpressure); - } - WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); - }, reason => { - if (stream._state === 'writable') { - WritableStreamDefaultControllerClearAlgorithms(controller); - } - WritableStreamFinishInFlightWriteWithError(stream, reason); - }); - } - function WritableStreamDefaultControllerGetBackpressure(controller) { - const desiredSize = WritableStreamDefaultControllerGetDesiredSize(controller); - return desiredSize <= 0; - } - // A client of WritableStreamDefaultController may use these functions directly to bypass state check. - function WritableStreamDefaultControllerError(controller, error) { - const stream = controller._controlledWritableStream; - WritableStreamDefaultControllerClearAlgorithms(controller); - WritableStreamStartErroring(stream, error); - } - // Helper functions for the WritableStream. - function streamBrandCheckException$2(name) { - return new TypeError(`WritableStream.prototype.${name} can only be used on a WritableStream`); - } - // Helper functions for the WritableStreamDefaultWriter. - function defaultWriterBrandCheckException(name) { - return new TypeError(`WritableStreamDefaultWriter.prototype.${name} can only be used on a WritableStreamDefaultWriter`); - } - function defaultWriterLockException(name) { - return new TypeError('Cannot ' + name + ' a stream using a released writer'); - } - function defaultWriterClosedPromiseInitialize(writer) { - writer._closedPromise = newPromise((resolve, reject) => { - writer._closedPromise_resolve = resolve; - writer._closedPromise_reject = reject; - writer._closedPromiseState = 'pending'; - }); - } - function defaultWriterClosedPromiseInitializeAsRejected(writer, reason) { - defaultWriterClosedPromiseInitialize(writer); - defaultWriterClosedPromiseReject(writer, reason); - } - function defaultWriterClosedPromiseInitializeAsResolved(writer) { - defaultWriterClosedPromiseInitialize(writer); - defaultWriterClosedPromiseResolve(writer); - } - function defaultWriterClosedPromiseReject(writer, reason) { - if (writer._closedPromise_reject === undefined) { - return; - } - setPromiseIsHandledToTrue(writer._closedPromise); - writer._closedPromise_reject(reason); - writer._closedPromise_resolve = undefined; - writer._closedPromise_reject = undefined; - writer._closedPromiseState = 'rejected'; - } - function defaultWriterClosedPromiseResetToRejected(writer, reason) { - defaultWriterClosedPromiseInitializeAsRejected(writer, reason); - } - function defaultWriterClosedPromiseResolve(writer) { - if (writer._closedPromise_resolve === undefined) { - return; - } - writer._closedPromise_resolve(undefined); - writer._closedPromise_resolve = undefined; - writer._closedPromise_reject = undefined; - writer._closedPromiseState = 'resolved'; - } - function defaultWriterReadyPromiseInitialize(writer) { - writer._readyPromise = newPromise((resolve, reject) => { - writer._readyPromise_resolve = resolve; - writer._readyPromise_reject = reject; - }); - writer._readyPromiseState = 'pending'; - } - function defaultWriterReadyPromiseInitializeAsRejected(writer, reason) { - defaultWriterReadyPromiseInitialize(writer); - defaultWriterReadyPromiseReject(writer, reason); - } - function defaultWriterReadyPromiseInitializeAsResolved(writer) { - defaultWriterReadyPromiseInitialize(writer); - defaultWriterReadyPromiseResolve(writer); - } - function defaultWriterReadyPromiseReject(writer, reason) { - if (writer._readyPromise_reject === undefined) { - return; - } - setPromiseIsHandledToTrue(writer._readyPromise); - writer._readyPromise_reject(reason); - writer._readyPromise_resolve = undefined; - writer._readyPromise_reject = undefined; - writer._readyPromiseState = 'rejected'; - } - function defaultWriterReadyPromiseReset(writer) { - defaultWriterReadyPromiseInitialize(writer); - } - function defaultWriterReadyPromiseResetToRejected(writer, reason) { - defaultWriterReadyPromiseInitializeAsRejected(writer, reason); - } - function defaultWriterReadyPromiseResolve(writer) { - if (writer._readyPromise_resolve === undefined) { - return; - } - writer._readyPromise_resolve(undefined); - writer._readyPromise_resolve = undefined; - writer._readyPromise_reject = undefined; - writer._readyPromiseState = 'fulfilled'; - } - - function isAbortSignal(value) { - if (typeof value !== 'object' || value === null) { - return false; - } - try { - return typeof value.aborted === 'boolean'; - } - catch (_a) { - // AbortSignal.prototype.aborted throws if its brand check fails - return false; - } - } - - /// - const NativeDOMException = typeof DOMException !== 'undefined' ? DOMException : undefined; - - /// - function isDOMExceptionConstructor(ctor) { - if (!(typeof ctor === 'function' || typeof ctor === 'object')) { - return false; - } - try { - new ctor(); - return true; - } - catch (_a) { - return false; - } - } - function createDOMExceptionPolyfill() { - // eslint-disable-next-line no-shadow - const ctor = function DOMException(message, name) { - this.message = message || ''; - this.name = name || 'Error'; - if (Error.captureStackTrace) { - Error.captureStackTrace(this, this.constructor); - } - }; - ctor.prototype = Object.create(Error.prototype); - Object.defineProperty(ctor.prototype, 'constructor', { value: ctor, writable: true, configurable: true }); - return ctor; - } - // eslint-disable-next-line no-redeclare - const DOMException$1 = isDOMExceptionConstructor(NativeDOMException) ? NativeDOMException : createDOMExceptionPolyfill(); - - function ReadableStreamPipeTo(source, dest, preventClose, preventAbort, preventCancel, signal) { - const reader = AcquireReadableStreamDefaultReader(source); - const writer = AcquireWritableStreamDefaultWriter(dest); - source._disturbed = true; - let shuttingDown = false; - // This is used to keep track of the spec's requirement that we wait for ongoing writes during shutdown. - let currentWrite = promiseResolvedWith(undefined); - return newPromise((resolve, reject) => { - let abortAlgorithm; - if (signal !== undefined) { - abortAlgorithm = () => { - const error = new DOMException$1('Aborted', 'AbortError'); - const actions = []; - if (!preventAbort) { - actions.push(() => { - if (dest._state === 'writable') { - return WritableStreamAbort(dest, error); - } - return promiseResolvedWith(undefined); - }); - } - if (!preventCancel) { - actions.push(() => { - if (source._state === 'readable') { - return ReadableStreamCancel(source, error); - } - return promiseResolvedWith(undefined); - }); - } - shutdownWithAction(() => Promise.all(actions.map(action => action())), true, error); - }; - if (signal.aborted) { - abortAlgorithm(); - return; - } - signal.addEventListener('abort', abortAlgorithm); - } - // Using reader and writer, read all chunks from this and write them to dest - // - Backpressure must be enforced - // - Shutdown must stop all activity - function pipeLoop() { - return newPromise((resolveLoop, rejectLoop) => { - function next(done) { - if (done) { - resolveLoop(); - } - else { - // Use `PerformPromiseThen` instead of `uponPromise` to avoid - // adding unnecessary `.catch(rethrowAssertionErrorRejection)` handlers - PerformPromiseThen(pipeStep(), next, rejectLoop); - } - } - next(false); - }); - } - function pipeStep() { - if (shuttingDown) { - return promiseResolvedWith(true); - } - return PerformPromiseThen(writer._readyPromise, () => { - return newPromise((resolveRead, rejectRead) => { - ReadableStreamDefaultReaderRead(reader, { - _chunkSteps: chunk => { - currentWrite = PerformPromiseThen(WritableStreamDefaultWriterWrite(writer, chunk), undefined, noop); - resolveRead(false); - }, - _closeSteps: () => resolveRead(true), - _errorSteps: rejectRead - }); - }); - }); - } - // Errors must be propagated forward - isOrBecomesErrored(source, reader._closedPromise, storedError => { - if (!preventAbort) { - shutdownWithAction(() => WritableStreamAbort(dest, storedError), true, storedError); - } - else { - shutdown(true, storedError); - } - }); - // Errors must be propagated backward - isOrBecomesErrored(dest, writer._closedPromise, storedError => { - if (!preventCancel) { - shutdownWithAction(() => ReadableStreamCancel(source, storedError), true, storedError); - } - else { - shutdown(true, storedError); - } - }); - // Closing must be propagated forward - isOrBecomesClosed(source, reader._closedPromise, () => { - if (!preventClose) { - shutdownWithAction(() => WritableStreamDefaultWriterCloseWithErrorPropagation(writer)); - } - else { - shutdown(); - } - }); - // Closing must be propagated backward - if (WritableStreamCloseQueuedOrInFlight(dest) || dest._state === 'closed') { - const destClosed = new TypeError('the destination writable stream closed before all data could be piped to it'); - if (!preventCancel) { - shutdownWithAction(() => ReadableStreamCancel(source, destClosed), true, destClosed); - } - else { - shutdown(true, destClosed); - } - } - setPromiseIsHandledToTrue(pipeLoop()); - function waitForWritesToFinish() { - // Another write may have started while we were waiting on this currentWrite, so we have to be sure to wait - // for that too. - const oldCurrentWrite = currentWrite; - return PerformPromiseThen(currentWrite, () => oldCurrentWrite !== currentWrite ? waitForWritesToFinish() : undefined); - } - function isOrBecomesErrored(stream, promise, action) { - if (stream._state === 'errored') { - action(stream._storedError); - } - else { - uponRejection(promise, action); - } - } - function isOrBecomesClosed(stream, promise, action) { - if (stream._state === 'closed') { - action(); - } - else { - uponFulfillment(promise, action); - } - } - function shutdownWithAction(action, originalIsError, originalError) { - if (shuttingDown) { - return; - } - shuttingDown = true; - if (dest._state === 'writable' && !WritableStreamCloseQueuedOrInFlight(dest)) { - uponFulfillment(waitForWritesToFinish(), doTheRest); - } - else { - doTheRest(); - } - function doTheRest() { - uponPromise(action(), () => finalize(originalIsError, originalError), newError => finalize(true, newError)); - } - } - function shutdown(isError, error) { - if (shuttingDown) { - return; - } - shuttingDown = true; - if (dest._state === 'writable' && !WritableStreamCloseQueuedOrInFlight(dest)) { - uponFulfillment(waitForWritesToFinish(), () => finalize(isError, error)); - } - else { - finalize(isError, error); - } - } - function finalize(isError, error) { - WritableStreamDefaultWriterRelease(writer); - ReadableStreamReaderGenericRelease(reader); - if (signal !== undefined) { - signal.removeEventListener('abort', abortAlgorithm); - } - if (isError) { - reject(error); - } - else { - resolve(undefined); - } - } - }); - } - - /** - * Allows control of a {@link ReadableStream | readable stream}'s state and internal queue. - * - * @public - */ - class ReadableStreamDefaultController { - constructor() { - throw new TypeError('Illegal constructor'); - } - /** - * Returns the desired size to fill the controlled stream's internal queue. It can be negative, if the queue is - * over-full. An underlying source ought to use this information to determine when and how to apply backpressure. - */ - get desiredSize() { - if (!IsReadableStreamDefaultController(this)) { - throw defaultControllerBrandCheckException$1('desiredSize'); - } - return ReadableStreamDefaultControllerGetDesiredSize(this); - } - /** - * Closes the controlled readable stream. Consumers will still be able to read any previously-enqueued chunks from - * the stream, but once those are read, the stream will become closed. - */ - close() { - if (!IsReadableStreamDefaultController(this)) { - throw defaultControllerBrandCheckException$1('close'); - } - if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(this)) { - throw new TypeError('The stream is not in a state that permits close'); - } - ReadableStreamDefaultControllerClose(this); - } - enqueue(chunk = undefined) { - if (!IsReadableStreamDefaultController(this)) { - throw defaultControllerBrandCheckException$1('enqueue'); - } - if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(this)) { - throw new TypeError('The stream is not in a state that permits enqueue'); - } - return ReadableStreamDefaultControllerEnqueue(this, chunk); - } - /** - * Errors the controlled readable stream, making all future interactions with it fail with the given error `e`. - */ - error(e = undefined) { - if (!IsReadableStreamDefaultController(this)) { - throw defaultControllerBrandCheckException$1('error'); - } - ReadableStreamDefaultControllerError(this, e); - } - /** @internal */ - [CancelSteps](reason) { - ResetQueue(this); - const result = this._cancelAlgorithm(reason); - ReadableStreamDefaultControllerClearAlgorithms(this); - return result; - } - /** @internal */ - [PullSteps](readRequest) { - const stream = this._controlledReadableStream; - if (this._queue.length > 0) { - const chunk = DequeueValue(this); - if (this._closeRequested && this._queue.length === 0) { - ReadableStreamDefaultControllerClearAlgorithms(this); - ReadableStreamClose(stream); - } - else { - ReadableStreamDefaultControllerCallPullIfNeeded(this); - } - readRequest._chunkSteps(chunk); - } - else { - ReadableStreamAddReadRequest(stream, readRequest); - ReadableStreamDefaultControllerCallPullIfNeeded(this); - } - } - } - Object.defineProperties(ReadableStreamDefaultController.prototype, { - close: { enumerable: true }, - enqueue: { enumerable: true }, - error: { enumerable: true }, - desiredSize: { enumerable: true } - }); - if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(ReadableStreamDefaultController.prototype, SymbolPolyfill.toStringTag, { - value: 'ReadableStreamDefaultController', - configurable: true - }); - } - // Abstract operations for the ReadableStreamDefaultController. - function IsReadableStreamDefaultController(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_controlledReadableStream')) { - return false; - } - return true; - } - function ReadableStreamDefaultControllerCallPullIfNeeded(controller) { - const shouldPull = ReadableStreamDefaultControllerShouldCallPull(controller); - if (!shouldPull) { - return; - } - if (controller._pulling) { - controller._pullAgain = true; - return; - } - controller._pulling = true; - const pullPromise = controller._pullAlgorithm(); - uponPromise(pullPromise, () => { - controller._pulling = false; - if (controller._pullAgain) { - controller._pullAgain = false; - ReadableStreamDefaultControllerCallPullIfNeeded(controller); - } - }, e => { - ReadableStreamDefaultControllerError(controller, e); - }); - } - function ReadableStreamDefaultControllerShouldCallPull(controller) { - const stream = controller._controlledReadableStream; - if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(controller)) { - return false; - } - if (!controller._started) { - return false; - } - if (IsReadableStreamLocked(stream) && ReadableStreamGetNumReadRequests(stream) > 0) { - return true; - } - const desiredSize = ReadableStreamDefaultControllerGetDesiredSize(controller); - if (desiredSize > 0) { - return true; - } - return false; - } - function ReadableStreamDefaultControllerClearAlgorithms(controller) { - controller._pullAlgorithm = undefined; - controller._cancelAlgorithm = undefined; - controller._strategySizeAlgorithm = undefined; - } - // A client of ReadableStreamDefaultController may use these functions directly to bypass state check. - function ReadableStreamDefaultControllerClose(controller) { - if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(controller)) { - return; - } - const stream = controller._controlledReadableStream; - controller._closeRequested = true; - if (controller._queue.length === 0) { - ReadableStreamDefaultControllerClearAlgorithms(controller); - ReadableStreamClose(stream); - } - } - function ReadableStreamDefaultControllerEnqueue(controller, chunk) { - if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(controller)) { - return; - } - const stream = controller._controlledReadableStream; - if (IsReadableStreamLocked(stream) && ReadableStreamGetNumReadRequests(stream) > 0) { - ReadableStreamFulfillReadRequest(stream, chunk, false); - } - else { - let chunkSize; - try { - chunkSize = controller._strategySizeAlgorithm(chunk); - } - catch (chunkSizeE) { - ReadableStreamDefaultControllerError(controller, chunkSizeE); - throw chunkSizeE; - } - try { - EnqueueValueWithSize(controller, chunk, chunkSize); - } - catch (enqueueE) { - ReadableStreamDefaultControllerError(controller, enqueueE); - throw enqueueE; - } - } - ReadableStreamDefaultControllerCallPullIfNeeded(controller); - } - function ReadableStreamDefaultControllerError(controller, e) { - const stream = controller._controlledReadableStream; - if (stream._state !== 'readable') { - return; - } - ResetQueue(controller); - ReadableStreamDefaultControllerClearAlgorithms(controller); - ReadableStreamError(stream, e); - } - function ReadableStreamDefaultControllerGetDesiredSize(controller) { - const state = controller._controlledReadableStream._state; - if (state === 'errored') { - return null; - } - if (state === 'closed') { - return 0; - } - return controller._strategyHWM - controller._queueTotalSize; - } - // This is used in the implementation of TransformStream. - function ReadableStreamDefaultControllerHasBackpressure(controller) { - if (ReadableStreamDefaultControllerShouldCallPull(controller)) { - return false; - } - return true; - } - function ReadableStreamDefaultControllerCanCloseOrEnqueue(controller) { - const state = controller._controlledReadableStream._state; - if (!controller._closeRequested && state === 'readable') { - return true; - } - return false; - } - function SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm) { - controller._controlledReadableStream = stream; - controller._queue = undefined; - controller._queueTotalSize = undefined; - ResetQueue(controller); - controller._started = false; - controller._closeRequested = false; - controller._pullAgain = false; - controller._pulling = false; - controller._strategySizeAlgorithm = sizeAlgorithm; - controller._strategyHWM = highWaterMark; - controller._pullAlgorithm = pullAlgorithm; - controller._cancelAlgorithm = cancelAlgorithm; - stream._readableStreamController = controller; - const startResult = startAlgorithm(); - uponPromise(promiseResolvedWith(startResult), () => { - controller._started = true; - ReadableStreamDefaultControllerCallPullIfNeeded(controller); - }, r => { - ReadableStreamDefaultControllerError(controller, r); - }); - } - function SetUpReadableStreamDefaultControllerFromUnderlyingSource(stream, underlyingSource, highWaterMark, sizeAlgorithm) { - const controller = Object.create(ReadableStreamDefaultController.prototype); - let startAlgorithm = () => undefined; - let pullAlgorithm = () => promiseResolvedWith(undefined); - let cancelAlgorithm = () => promiseResolvedWith(undefined); - if (underlyingSource.start !== undefined) { - startAlgorithm = () => underlyingSource.start(controller); - } - if (underlyingSource.pull !== undefined) { - pullAlgorithm = () => underlyingSource.pull(controller); - } - if (underlyingSource.cancel !== undefined) { - cancelAlgorithm = reason => underlyingSource.cancel(reason); - } - SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm); - } - // Helper functions for the ReadableStreamDefaultController. - function defaultControllerBrandCheckException$1(name) { - return new TypeError(`ReadableStreamDefaultController.prototype.${name} can only be used on a ReadableStreamDefaultController`); - } - - function ReadableStreamTee(stream, cloneForBranch2) { - const reader = AcquireReadableStreamDefaultReader(stream); - let reading = false; - let canceled1 = false; - let canceled2 = false; - let reason1; - let reason2; - let branch1; - let branch2; - let resolveCancelPromise; - const cancelPromise = newPromise(resolve => { - resolveCancelPromise = resolve; - }); - function pullAlgorithm() { - if (reading) { - return promiseResolvedWith(undefined); - } - reading = true; - const readRequest = { - _chunkSteps: value => { - // This needs to be delayed a microtask because it takes at least a microtask to detect errors (using - // reader._closedPromise below), and we want errors in stream to error both branches immediately. We cannot let - // successful synchronously-available reads get ahead of asynchronously-available errors. - queueMicrotask(() => { - reading = false; - const value1 = value; - const value2 = value; - // There is no way to access the cloning code right now in the reference implementation. - // If we add one then we'll need an implementation for serializable objects. - // if (!canceled2 && cloneForBranch2) { - // value2 = StructuredDeserialize(StructuredSerialize(value2)); - // } - if (!canceled1) { - ReadableStreamDefaultControllerEnqueue(branch1._readableStreamController, value1); - } - if (!canceled2) { - ReadableStreamDefaultControllerEnqueue(branch2._readableStreamController, value2); - } - }); - }, - _closeSteps: () => { - reading = false; - if (!canceled1) { - ReadableStreamDefaultControllerClose(branch1._readableStreamController); - } - if (!canceled2) { - ReadableStreamDefaultControllerClose(branch2._readableStreamController); - } - if (!canceled1 || !canceled2) { - resolveCancelPromise(undefined); - } - }, - _errorSteps: () => { - reading = false; - } - }; - ReadableStreamDefaultReaderRead(reader, readRequest); - return promiseResolvedWith(undefined); - } - function cancel1Algorithm(reason) { - canceled1 = true; - reason1 = reason; - if (canceled2) { - const compositeReason = CreateArrayFromList([reason1, reason2]); - const cancelResult = ReadableStreamCancel(stream, compositeReason); - resolveCancelPromise(cancelResult); - } - return cancelPromise; - } - function cancel2Algorithm(reason) { - canceled2 = true; - reason2 = reason; - if (canceled1) { - const compositeReason = CreateArrayFromList([reason1, reason2]); - const cancelResult = ReadableStreamCancel(stream, compositeReason); - resolveCancelPromise(cancelResult); - } - return cancelPromise; - } - function startAlgorithm() { - // do nothing - } - branch1 = CreateReadableStream(startAlgorithm, pullAlgorithm, cancel1Algorithm); - branch2 = CreateReadableStream(startAlgorithm, pullAlgorithm, cancel2Algorithm); - uponRejection(reader._closedPromise, (r) => { - ReadableStreamDefaultControllerError(branch1._readableStreamController, r); - ReadableStreamDefaultControllerError(branch2._readableStreamController, r); - if (!canceled1 || !canceled2) { - resolveCancelPromise(undefined); - } - }); - return [branch1, branch2]; - } - - function convertUnderlyingDefaultOrByteSource(source, context) { - assertDictionary(source, context); - const original = source; - const autoAllocateChunkSize = original === null || original === void 0 ? void 0 : original.autoAllocateChunkSize; - const cancel = original === null || original === void 0 ? void 0 : original.cancel; - const pull = original === null || original === void 0 ? void 0 : original.pull; - const start = original === null || original === void 0 ? void 0 : original.start; - const type = original === null || original === void 0 ? void 0 : original.type; - return { - autoAllocateChunkSize: autoAllocateChunkSize === undefined ? - undefined : - convertUnsignedLongLongWithEnforceRange(autoAllocateChunkSize, `${context} has member 'autoAllocateChunkSize' that`), - cancel: cancel === undefined ? - undefined : - convertUnderlyingSourceCancelCallback(cancel, original, `${context} has member 'cancel' that`), - pull: pull === undefined ? - undefined : - convertUnderlyingSourcePullCallback(pull, original, `${context} has member 'pull' that`), - start: start === undefined ? - undefined : - convertUnderlyingSourceStartCallback(start, original, `${context} has member 'start' that`), - type: type === undefined ? undefined : convertReadableStreamType(type, `${context} has member 'type' that`) - }; - } - function convertUnderlyingSourceCancelCallback(fn, original, context) { - assertFunction(fn, context); - return (reason) => promiseCall(fn, original, [reason]); - } - function convertUnderlyingSourcePullCallback(fn, original, context) { - assertFunction(fn, context); - return (controller) => promiseCall(fn, original, [controller]); - } - function convertUnderlyingSourceStartCallback(fn, original, context) { - assertFunction(fn, context); - return (controller) => reflectCall(fn, original, [controller]); - } - function convertReadableStreamType(type, context) { - type = `${type}`; - if (type !== 'bytes') { - throw new TypeError(`${context} '${type}' is not a valid enumeration value for ReadableStreamType`); - } - return type; - } - - function convertReaderOptions(options, context) { - assertDictionary(options, context); - const mode = options === null || options === void 0 ? void 0 : options.mode; - return { - mode: mode === undefined ? undefined : convertReadableStreamReaderMode(mode, `${context} has member 'mode' that`) - }; - } - function convertReadableStreamReaderMode(mode, context) { - mode = `${mode}`; - if (mode !== 'byob') { - throw new TypeError(`${context} '${mode}' is not a valid enumeration value for ReadableStreamReaderMode`); - } - return mode; - } - - function convertIteratorOptions(options, context) { - assertDictionary(options, context); - const preventCancel = options === null || options === void 0 ? void 0 : options.preventCancel; - return { preventCancel: Boolean(preventCancel) }; - } - - function convertPipeOptions(options, context) { - assertDictionary(options, context); - const preventAbort = options === null || options === void 0 ? void 0 : options.preventAbort; - const preventCancel = options === null || options === void 0 ? void 0 : options.preventCancel; - const preventClose = options === null || options === void 0 ? void 0 : options.preventClose; - const signal = options === null || options === void 0 ? void 0 : options.signal; - if (signal !== undefined) { - assertAbortSignal(signal, `${context} has member 'signal' that`); - } - return { - preventAbort: Boolean(preventAbort), - preventCancel: Boolean(preventCancel), - preventClose: Boolean(preventClose), - signal - }; - } - function assertAbortSignal(signal, context) { - if (!isAbortSignal(signal)) { - throw new TypeError(`${context} is not an AbortSignal.`); - } - } - - function convertReadableWritablePair(pair, context) { - assertDictionary(pair, context); - const readable = pair === null || pair === void 0 ? void 0 : pair.readable; - assertRequiredField(readable, 'readable', 'ReadableWritablePair'); - assertReadableStream(readable, `${context} has member 'readable' that`); - const writable = pair === null || pair === void 0 ? void 0 : pair.writable; - assertRequiredField(writable, 'writable', 'ReadableWritablePair'); - assertWritableStream(writable, `${context} has member 'writable' that`); - return { readable, writable }; - } - - /** - * A readable stream represents a source of data, from which you can read. - * - * @public - */ - class ReadableStream$1 { - constructor(rawUnderlyingSource = {}, rawStrategy = {}) { - if (rawUnderlyingSource === undefined) { - rawUnderlyingSource = null; - } - else { - assertObject(rawUnderlyingSource, 'First parameter'); - } - const strategy = convertQueuingStrategy(rawStrategy, 'Second parameter'); - const underlyingSource = convertUnderlyingDefaultOrByteSource(rawUnderlyingSource, 'First parameter'); - InitializeReadableStream(this); - if (underlyingSource.type === 'bytes') { - if (strategy.size !== undefined) { - throw new RangeError('The strategy for a byte stream cannot have a size function'); - } - const highWaterMark = ExtractHighWaterMark(strategy, 0); - SetUpReadableByteStreamControllerFromUnderlyingSource(this, underlyingSource, highWaterMark); - } - else { - const sizeAlgorithm = ExtractSizeAlgorithm(strategy); - const highWaterMark = ExtractHighWaterMark(strategy, 1); - SetUpReadableStreamDefaultControllerFromUnderlyingSource(this, underlyingSource, highWaterMark, sizeAlgorithm); - } - } - /** - * Whether or not the readable stream is locked to a {@link ReadableStreamDefaultReader | reader}. - */ - get locked() { - if (!IsReadableStream(this)) { - throw streamBrandCheckException$1('locked'); - } - return IsReadableStreamLocked(this); - } - /** - * Cancels the stream, signaling a loss of interest in the stream by a consumer. - * - * The supplied `reason` argument will be given to the underlying source's {@link UnderlyingSource.cancel | cancel()} - * method, which might or might not use it. - */ - cancel(reason = undefined) { - if (!IsReadableStream(this)) { - return promiseRejectedWith(streamBrandCheckException$1('cancel')); - } - if (IsReadableStreamLocked(this)) { - return promiseRejectedWith(new TypeError('Cannot cancel a stream that already has a reader')); - } - return ReadableStreamCancel(this, reason); - } - getReader(rawOptions = undefined) { - if (!IsReadableStream(this)) { - throw streamBrandCheckException$1('getReader'); - } - const options = convertReaderOptions(rawOptions, 'First parameter'); - if (options.mode === undefined) { - return AcquireReadableStreamDefaultReader(this); - } - return AcquireReadableStreamBYOBReader(this); - } - pipeThrough(rawTransform, rawOptions = {}) { - if (!IsReadableStream(this)) { - throw streamBrandCheckException$1('pipeThrough'); - } - assertRequiredArgument(rawTransform, 1, 'pipeThrough'); - const transform = convertReadableWritablePair(rawTransform, 'First parameter'); - const options = convertPipeOptions(rawOptions, 'Second parameter'); - if (IsReadableStreamLocked(this)) { - throw new TypeError('ReadableStream.prototype.pipeThrough cannot be used on a locked ReadableStream'); - } - if (IsWritableStreamLocked(transform.writable)) { - throw new TypeError('ReadableStream.prototype.pipeThrough cannot be used on a locked WritableStream'); - } - const promise = ReadableStreamPipeTo(this, transform.writable, options.preventClose, options.preventAbort, options.preventCancel, options.signal); - setPromiseIsHandledToTrue(promise); - return transform.readable; - } - pipeTo(destination, rawOptions = {}) { - if (!IsReadableStream(this)) { - return promiseRejectedWith(streamBrandCheckException$1('pipeTo')); - } - if (destination === undefined) { - return promiseRejectedWith(`Parameter 1 is required in 'pipeTo'.`); - } - if (!IsWritableStream(destination)) { - return promiseRejectedWith(new TypeError(`ReadableStream.prototype.pipeTo's first argument must be a WritableStream`)); - } - let options; - try { - options = convertPipeOptions(rawOptions, 'Second parameter'); - } - catch (e) { - return promiseRejectedWith(e); - } - if (IsReadableStreamLocked(this)) { - return promiseRejectedWith(new TypeError('ReadableStream.prototype.pipeTo cannot be used on a locked ReadableStream')); - } - if (IsWritableStreamLocked(destination)) { - return promiseRejectedWith(new TypeError('ReadableStream.prototype.pipeTo cannot be used on a locked WritableStream')); - } - return ReadableStreamPipeTo(this, destination, options.preventClose, options.preventAbort, options.preventCancel, options.signal); - } - /** - * Tees this readable stream, returning a two-element array containing the two resulting branches as - * new {@link ReadableStream} instances. - * - * Teeing a stream will lock it, preventing any other consumer from acquiring a reader. - * To cancel the stream, cancel both of the resulting branches; a composite cancellation reason will then be - * propagated to the stream's underlying source. - * - * Note that the chunks seen in each branch will be the same object. If the chunks are not immutable, - * this could allow interference between the two branches. - */ - tee() { - if (!IsReadableStream(this)) { - throw streamBrandCheckException$1('tee'); - } - const branches = ReadableStreamTee(this); - return CreateArrayFromList(branches); - } - values(rawOptions = undefined) { - if (!IsReadableStream(this)) { - throw streamBrandCheckException$1('values'); - } - const options = convertIteratorOptions(rawOptions, 'First parameter'); - return AcquireReadableStreamAsyncIterator(this, options.preventCancel); - } - } - Object.defineProperties(ReadableStream$1.prototype, { - cancel: { enumerable: true }, - getReader: { enumerable: true }, - pipeThrough: { enumerable: true }, - pipeTo: { enumerable: true }, - tee: { enumerable: true }, - values: { enumerable: true }, - locked: { enumerable: true } - }); - if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(ReadableStream$1.prototype, SymbolPolyfill.toStringTag, { - value: 'ReadableStream', - configurable: true - }); - } - if (typeof SymbolPolyfill.asyncIterator === 'symbol') { - Object.defineProperty(ReadableStream$1.prototype, SymbolPolyfill.asyncIterator, { - value: ReadableStream$1.prototype.values, - writable: true, - configurable: true - }); - } - // Abstract operations for the ReadableStream. - // Throws if and only if startAlgorithm throws. - function CreateReadableStream(startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark = 1, sizeAlgorithm = () => 1) { - const stream = Object.create(ReadableStream$1.prototype); - InitializeReadableStream(stream); - const controller = Object.create(ReadableStreamDefaultController.prototype); - SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm); - return stream; - } - function InitializeReadableStream(stream) { - stream._state = 'readable'; - stream._reader = undefined; - stream._storedError = undefined; - stream._disturbed = false; - } - function IsReadableStream(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_readableStreamController')) { - return false; - } - return true; - } - function IsReadableStreamLocked(stream) { - if (stream._reader === undefined) { - return false; - } - return true; - } - // ReadableStream API exposed for controllers. - function ReadableStreamCancel(stream, reason) { - stream._disturbed = true; - if (stream._state === 'closed') { - return promiseResolvedWith(undefined); - } - if (stream._state === 'errored') { - return promiseRejectedWith(stream._storedError); - } - ReadableStreamClose(stream); - const sourceCancelPromise = stream._readableStreamController[CancelSteps](reason); - return transformPromiseWith(sourceCancelPromise, noop); - } - function ReadableStreamClose(stream) { - stream._state = 'closed'; - const reader = stream._reader; - if (reader === undefined) { - return; - } - defaultReaderClosedPromiseResolve(reader); - if (IsReadableStreamDefaultReader(reader)) { - reader._readRequests.forEach(readRequest => { - readRequest._closeSteps(); - }); - reader._readRequests = new SimpleQueue(); - } - } - function ReadableStreamError(stream, e) { - stream._state = 'errored'; - stream._storedError = e; - const reader = stream._reader; - if (reader === undefined) { - return; - } - defaultReaderClosedPromiseReject(reader, e); - if (IsReadableStreamDefaultReader(reader)) { - reader._readRequests.forEach(readRequest => { - readRequest._errorSteps(e); - }); - reader._readRequests = new SimpleQueue(); - } - else { - reader._readIntoRequests.forEach(readIntoRequest => { - readIntoRequest._errorSteps(e); - }); - reader._readIntoRequests = new SimpleQueue(); - } - } - // Helper functions for the ReadableStream. - function streamBrandCheckException$1(name) { - return new TypeError(`ReadableStream.prototype.${name} can only be used on a ReadableStream`); - } - - function convertQueuingStrategyInit(init, context) { - assertDictionary(init, context); - const highWaterMark = init === null || init === void 0 ? void 0 : init.highWaterMark; - assertRequiredField(highWaterMark, 'highWaterMark', 'QueuingStrategyInit'); - return { - highWaterMark: convertUnrestrictedDouble(highWaterMark) - }; - } - - const byteLengthSizeFunction = function size(chunk) { - return chunk.byteLength; - }; - /** - * A queuing strategy that counts the number of bytes in each chunk. - * - * @public - */ - class ByteLengthQueuingStrategy { - constructor(options) { - assertRequiredArgument(options, 1, 'ByteLengthQueuingStrategy'); - options = convertQueuingStrategyInit(options, 'First parameter'); - this._byteLengthQueuingStrategyHighWaterMark = options.highWaterMark; - } - /** - * Returns the high water mark provided to the constructor. - */ - get highWaterMark() { - if (!IsByteLengthQueuingStrategy(this)) { - throw byteLengthBrandCheckException('highWaterMark'); - } - return this._byteLengthQueuingStrategyHighWaterMark; - } - /** - * Measures the size of `chunk` by returning the value of its `byteLength` property. - */ - get size() { - if (!IsByteLengthQueuingStrategy(this)) { - throw byteLengthBrandCheckException('size'); - } - return byteLengthSizeFunction; - } - } - Object.defineProperties(ByteLengthQueuingStrategy.prototype, { - highWaterMark: { enumerable: true }, - size: { enumerable: true } - }); - if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(ByteLengthQueuingStrategy.prototype, SymbolPolyfill.toStringTag, { - value: 'ByteLengthQueuingStrategy', - configurable: true - }); - } - // Helper functions for the ByteLengthQueuingStrategy. - function byteLengthBrandCheckException(name) { - return new TypeError(`ByteLengthQueuingStrategy.prototype.${name} can only be used on a ByteLengthQueuingStrategy`); - } - function IsByteLengthQueuingStrategy(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_byteLengthQueuingStrategyHighWaterMark')) { - return false; - } - return true; - } - - const countSizeFunction = function size() { - return 1; - }; - /** - * A queuing strategy that counts the number of chunks. - * - * @public - */ - class CountQueuingStrategy { - constructor(options) { - assertRequiredArgument(options, 1, 'CountQueuingStrategy'); - options = convertQueuingStrategyInit(options, 'First parameter'); - this._countQueuingStrategyHighWaterMark = options.highWaterMark; - } - /** - * Returns the high water mark provided to the constructor. - */ - get highWaterMark() { - if (!IsCountQueuingStrategy(this)) { - throw countBrandCheckException('highWaterMark'); - } - return this._countQueuingStrategyHighWaterMark; - } - /** - * Measures the size of `chunk` by always returning 1. - * This ensures that the total queue size is a count of the number of chunks in the queue. - */ - get size() { - if (!IsCountQueuingStrategy(this)) { - throw countBrandCheckException('size'); - } - return countSizeFunction; - } - } - Object.defineProperties(CountQueuingStrategy.prototype, { - highWaterMark: { enumerable: true }, - size: { enumerable: true } - }); - if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(CountQueuingStrategy.prototype, SymbolPolyfill.toStringTag, { - value: 'CountQueuingStrategy', - configurable: true - }); - } - // Helper functions for the CountQueuingStrategy. - function countBrandCheckException(name) { - return new TypeError(`CountQueuingStrategy.prototype.${name} can only be used on a CountQueuingStrategy`); - } - function IsCountQueuingStrategy(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_countQueuingStrategyHighWaterMark')) { - return false; - } - return true; - } - - function convertTransformer(original, context) { - assertDictionary(original, context); - const flush = original === null || original === void 0 ? void 0 : original.flush; - const readableType = original === null || original === void 0 ? void 0 : original.readableType; - const start = original === null || original === void 0 ? void 0 : original.start; - const transform = original === null || original === void 0 ? void 0 : original.transform; - const writableType = original === null || original === void 0 ? void 0 : original.writableType; - return { - flush: flush === undefined ? - undefined : - convertTransformerFlushCallback(flush, original, `${context} has member 'flush' that`), - readableType, - start: start === undefined ? - undefined : - convertTransformerStartCallback(start, original, `${context} has member 'start' that`), - transform: transform === undefined ? - undefined : - convertTransformerTransformCallback(transform, original, `${context} has member 'transform' that`), - writableType - }; - } - function convertTransformerFlushCallback(fn, original, context) { - assertFunction(fn, context); - return (controller) => promiseCall(fn, original, [controller]); - } - function convertTransformerStartCallback(fn, original, context) { - assertFunction(fn, context); - return (controller) => reflectCall(fn, original, [controller]); - } - function convertTransformerTransformCallback(fn, original, context) { - assertFunction(fn, context); - return (chunk, controller) => promiseCall(fn, original, [chunk, controller]); - } - - // Class TransformStream - /** - * A transform stream consists of a pair of streams: a {@link WritableStream | writable stream}, - * known as its writable side, and a {@link ReadableStream | readable stream}, known as its readable side. - * In a manner specific to the transform stream in question, writes to the writable side result in new data being - * made available for reading from the readable side. - * - * @public - */ - class TransformStream$1 { - constructor(rawTransformer = {}, rawWritableStrategy = {}, rawReadableStrategy = {}) { - if (rawTransformer === undefined) { - rawTransformer = null; - } - const writableStrategy = convertQueuingStrategy(rawWritableStrategy, 'Second parameter'); - const readableStrategy = convertQueuingStrategy(rawReadableStrategy, 'Third parameter'); - const transformer = convertTransformer(rawTransformer, 'First parameter'); - if (transformer.readableType !== undefined) { - throw new RangeError('Invalid readableType specified'); - } - if (transformer.writableType !== undefined) { - throw new RangeError('Invalid writableType specified'); - } - const readableHighWaterMark = ExtractHighWaterMark(readableStrategy, 0); - const readableSizeAlgorithm = ExtractSizeAlgorithm(readableStrategy); - const writableHighWaterMark = ExtractHighWaterMark(writableStrategy, 1); - const writableSizeAlgorithm = ExtractSizeAlgorithm(writableStrategy); - let startPromise_resolve; - const startPromise = newPromise(resolve => { - startPromise_resolve = resolve; - }); - InitializeTransformStream(this, startPromise, writableHighWaterMark, writableSizeAlgorithm, readableHighWaterMark, readableSizeAlgorithm); - SetUpTransformStreamDefaultControllerFromTransformer(this, transformer); - if (transformer.start !== undefined) { - startPromise_resolve(transformer.start(this._transformStreamController)); - } - else { - startPromise_resolve(undefined); - } - } - /** - * The readable side of the transform stream. - */ - get readable() { - if (!IsTransformStream(this)) { - throw streamBrandCheckException('readable'); - } - return this._readable; - } - /** - * The writable side of the transform stream. - */ - get writable() { - if (!IsTransformStream(this)) { - throw streamBrandCheckException('writable'); - } - return this._writable; - } - } - Object.defineProperties(TransformStream$1.prototype, { - readable: { enumerable: true }, - writable: { enumerable: true } - }); - if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(TransformStream$1.prototype, SymbolPolyfill.toStringTag, { - value: 'TransformStream', - configurable: true - }); - } - function InitializeTransformStream(stream, startPromise, writableHighWaterMark, writableSizeAlgorithm, readableHighWaterMark, readableSizeAlgorithm) { - function startAlgorithm() { - return startPromise; - } - function writeAlgorithm(chunk) { - return TransformStreamDefaultSinkWriteAlgorithm(stream, chunk); - } - function abortAlgorithm(reason) { - return TransformStreamDefaultSinkAbortAlgorithm(stream, reason); - } - function closeAlgorithm() { - return TransformStreamDefaultSinkCloseAlgorithm(stream); - } - stream._writable = CreateWritableStream(startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, writableHighWaterMark, writableSizeAlgorithm); - function pullAlgorithm() { - return TransformStreamDefaultSourcePullAlgorithm(stream); - } - function cancelAlgorithm(reason) { - TransformStreamErrorWritableAndUnblockWrite(stream, reason); - return promiseResolvedWith(undefined); - } - stream._readable = CreateReadableStream(startAlgorithm, pullAlgorithm, cancelAlgorithm, readableHighWaterMark, readableSizeAlgorithm); - // The [[backpressure]] slot is set to undefined so that it can be initialised by TransformStreamSetBackpressure. - stream._backpressure = undefined; - stream._backpressureChangePromise = undefined; - stream._backpressureChangePromise_resolve = undefined; - TransformStreamSetBackpressure(stream, true); - stream._transformStreamController = undefined; - } - function IsTransformStream(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_transformStreamController')) { - return false; - } - return true; - } - // This is a no-op if both sides are already errored. - function TransformStreamError(stream, e) { - ReadableStreamDefaultControllerError(stream._readable._readableStreamController, e); - TransformStreamErrorWritableAndUnblockWrite(stream, e); - } - function TransformStreamErrorWritableAndUnblockWrite(stream, e) { - TransformStreamDefaultControllerClearAlgorithms(stream._transformStreamController); - WritableStreamDefaultControllerErrorIfNeeded(stream._writable._writableStreamController, e); - if (stream._backpressure) { - // Pretend that pull() was called to permit any pending write() calls to complete. TransformStreamSetBackpressure() - // cannot be called from enqueue() or pull() once the ReadableStream is errored, so this will will be the final time - // _backpressure is set. - TransformStreamSetBackpressure(stream, false); - } - } - function TransformStreamSetBackpressure(stream, backpressure) { - // Passes also when called during construction. - if (stream._backpressureChangePromise !== undefined) { - stream._backpressureChangePromise_resolve(); - } - stream._backpressureChangePromise = newPromise(resolve => { - stream._backpressureChangePromise_resolve = resolve; - }); - stream._backpressure = backpressure; - } - // Class TransformStreamDefaultController - /** - * Allows control of the {@link ReadableStream} and {@link WritableStream} of the associated {@link TransformStream}. - * - * @public - */ - class TransformStreamDefaultController { - constructor() { - throw new TypeError('Illegal constructor'); - } - /** - * Returns the desired size to fill the readable side’s internal queue. It can be negative, if the queue is over-full. - */ - get desiredSize() { - if (!IsTransformStreamDefaultController(this)) { - throw defaultControllerBrandCheckException('desiredSize'); - } - const readableController = this._controlledTransformStream._readable._readableStreamController; - return ReadableStreamDefaultControllerGetDesiredSize(readableController); - } - enqueue(chunk = undefined) { - if (!IsTransformStreamDefaultController(this)) { - throw defaultControllerBrandCheckException('enqueue'); - } - TransformStreamDefaultControllerEnqueue(this, chunk); - } - /** - * Errors both the readable side and the writable side of the controlled transform stream, making all future - * interactions with it fail with the given error `e`. Any chunks queued for transformation will be discarded. - */ - error(reason = undefined) { - if (!IsTransformStreamDefaultController(this)) { - throw defaultControllerBrandCheckException('error'); - } - TransformStreamDefaultControllerError(this, reason); - } - /** - * Closes the readable side and errors the writable side of the controlled transform stream. This is useful when the - * transformer only needs to consume a portion of the chunks written to the writable side. - */ - terminate() { - if (!IsTransformStreamDefaultController(this)) { - throw defaultControllerBrandCheckException('terminate'); - } - TransformStreamDefaultControllerTerminate(this); - } - } - Object.defineProperties(TransformStreamDefaultController.prototype, { - enqueue: { enumerable: true }, - error: { enumerable: true }, - terminate: { enumerable: true }, - desiredSize: { enumerable: true } - }); - if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(TransformStreamDefaultController.prototype, SymbolPolyfill.toStringTag, { - value: 'TransformStreamDefaultController', - configurable: true - }); - } - // Transform Stream Default Controller Abstract Operations - function IsTransformStreamDefaultController(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_controlledTransformStream')) { - return false; - } - return true; - } - function SetUpTransformStreamDefaultController(stream, controller, transformAlgorithm, flushAlgorithm) { - controller._controlledTransformStream = stream; - stream._transformStreamController = controller; - controller._transformAlgorithm = transformAlgorithm; - controller._flushAlgorithm = flushAlgorithm; - } - function SetUpTransformStreamDefaultControllerFromTransformer(stream, transformer) { - const controller = Object.create(TransformStreamDefaultController.prototype); - let transformAlgorithm = (chunk) => { - try { - TransformStreamDefaultControllerEnqueue(controller, chunk); - return promiseResolvedWith(undefined); - } - catch (transformResultE) { - return promiseRejectedWith(transformResultE); - } - }; - let flushAlgorithm = () => promiseResolvedWith(undefined); - if (transformer.transform !== undefined) { - transformAlgorithm = chunk => transformer.transform(chunk, controller); - } - if (transformer.flush !== undefined) { - flushAlgorithm = () => transformer.flush(controller); - } - SetUpTransformStreamDefaultController(stream, controller, transformAlgorithm, flushAlgorithm); - } - function TransformStreamDefaultControllerClearAlgorithms(controller) { - controller._transformAlgorithm = undefined; - controller._flushAlgorithm = undefined; - } - function TransformStreamDefaultControllerEnqueue(controller, chunk) { - const stream = controller._controlledTransformStream; - const readableController = stream._readable._readableStreamController; - if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(readableController)) { - throw new TypeError('Readable side is not in a state that permits enqueue'); - } - // We throttle transform invocations based on the backpressure of the ReadableStream, but we still - // accept TransformStreamDefaultControllerEnqueue() calls. - try { - ReadableStreamDefaultControllerEnqueue(readableController, chunk); - } - catch (e) { - // This happens when readableStrategy.size() throws. - TransformStreamErrorWritableAndUnblockWrite(stream, e); - throw stream._readable._storedError; - } - const backpressure = ReadableStreamDefaultControllerHasBackpressure(readableController); - if (backpressure !== stream._backpressure) { - TransformStreamSetBackpressure(stream, true); - } - } - function TransformStreamDefaultControllerError(controller, e) { - TransformStreamError(controller._controlledTransformStream, e); - } - function TransformStreamDefaultControllerPerformTransform(controller, chunk) { - const transformPromise = controller._transformAlgorithm(chunk); - return transformPromiseWith(transformPromise, undefined, r => { - TransformStreamError(controller._controlledTransformStream, r); - throw r; - }); - } - function TransformStreamDefaultControllerTerminate(controller) { - const stream = controller._controlledTransformStream; - const readableController = stream._readable._readableStreamController; - ReadableStreamDefaultControllerClose(readableController); - const error = new TypeError('TransformStream terminated'); - TransformStreamErrorWritableAndUnblockWrite(stream, error); - } - // TransformStreamDefaultSink Algorithms - function TransformStreamDefaultSinkWriteAlgorithm(stream, chunk) { - const controller = stream._transformStreamController; - if (stream._backpressure) { - const backpressureChangePromise = stream._backpressureChangePromise; - return transformPromiseWith(backpressureChangePromise, () => { - const writable = stream._writable; - const state = writable._state; - if (state === 'erroring') { - throw writable._storedError; - } - return TransformStreamDefaultControllerPerformTransform(controller, chunk); - }); - } - return TransformStreamDefaultControllerPerformTransform(controller, chunk); - } - function TransformStreamDefaultSinkAbortAlgorithm(stream, reason) { - // abort() is not called synchronously, so it is possible for abort() to be called when the stream is already - // errored. - TransformStreamError(stream, reason); - return promiseResolvedWith(undefined); - } - function TransformStreamDefaultSinkCloseAlgorithm(stream) { - // stream._readable cannot change after construction, so caching it across a call to user code is safe. - const readable = stream._readable; - const controller = stream._transformStreamController; - const flushPromise = controller._flushAlgorithm(); - TransformStreamDefaultControllerClearAlgorithms(controller); - // Return a promise that is fulfilled with undefined on success. - return transformPromiseWith(flushPromise, () => { - if (readable._state === 'errored') { - throw readable._storedError; - } - ReadableStreamDefaultControllerClose(readable._readableStreamController); - }, r => { - TransformStreamError(stream, r); - throw readable._storedError; - }); - } - // TransformStreamDefaultSource Algorithms - function TransformStreamDefaultSourcePullAlgorithm(stream) { - // Invariant. Enforced by the promises returned by start() and pull(). - TransformStreamSetBackpressure(stream, false); - // Prevent the next pull() call until there is backpressure. - return stream._backpressureChangePromise; - } - // Helper functions for the TransformStreamDefaultController. - function defaultControllerBrandCheckException(name) { - return new TypeError(`TransformStreamDefaultController.prototype.${name} can only be used on a TransformStreamDefaultController`); - } - // Helper functions for the TransformStream. - function streamBrandCheckException(name) { - return new TypeError(`TransformStream.prototype.${name} can only be used on a TransformStream`); - } - - var ponyfill_es6 = /*#__PURE__*/Object.freeze({ - __proto__: null, - ByteLengthQueuingStrategy: ByteLengthQueuingStrategy, - CountQueuingStrategy: CountQueuingStrategy, - ReadableByteStreamController: ReadableByteStreamController, - ReadableStream: ReadableStream$1, - ReadableStreamBYOBReader: ReadableStreamBYOBReader, - ReadableStreamBYOBRequest: ReadableStreamBYOBRequest, - ReadableStreamDefaultController: ReadableStreamDefaultController, - ReadableStreamDefaultReader: ReadableStreamDefaultReader, - TransformStream: TransformStream$1, - TransformStreamDefaultController: TransformStreamDefaultController, - WritableStream: WritableStream$1, - WritableStreamDefaultController: WritableStreamDefaultController, - WritableStreamDefaultWriter: WritableStreamDefaultWriter - }); - - /*! ***************************************************************************** - Copyright (c) Microsoft Corporation. - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. - ***************************************************************************** */ - /* global Reflect, Promise */ - - var extendStatics = function(d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - - function __extends(d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - } - - function assert$1(test) { - if (!test) { - throw new TypeError('Assertion failed'); - } - } - - function noop$1() { - return; - } - function typeIsObject$1(x) { - return (typeof x === 'object' && x !== null) || typeof x === 'function'; - } - - function isStreamConstructor(ctor) { - if (typeof ctor !== 'function') { - return false; - } - var startCalled = false; - try { - new ctor({ - start: function () { - startCalled = true; - } - }); - } - catch (e) { - // ignore - } - return startCalled; - } - function isReadableStream(readable) { - if (!typeIsObject$1(readable)) { - return false; - } - if (typeof readable.getReader !== 'function') { - return false; - } - return true; - } - function isReadableStreamConstructor(ctor) { - if (!isStreamConstructor(ctor)) { - return false; - } - if (!isReadableStream(new ctor())) { - return false; - } - return true; - } - function isWritableStream(writable) { - if (!typeIsObject$1(writable)) { - return false; - } - if (typeof writable.getWriter !== 'function') { - return false; - } - return true; - } - function isWritableStreamConstructor(ctor) { - if (!isStreamConstructor(ctor)) { - return false; - } - if (!isWritableStream(new ctor())) { - return false; - } - return true; - } - function isTransformStream(transform) { - if (!typeIsObject$1(transform)) { - return false; - } - if (!isReadableStream(transform.readable)) { - return false; - } - if (!isWritableStream(transform.writable)) { - return false; - } - return true; - } - function isTransformStreamConstructor(ctor) { - if (!isStreamConstructor(ctor)) { - return false; - } - if (!isTransformStream(new ctor())) { - return false; - } - return true; - } - function supportsByobReader(readable) { - try { - var reader = readable.getReader({ mode: 'byob' }); - reader.releaseLock(); - return true; - } - catch (_a) { - return false; - } - } - function supportsByteSource(ctor) { - try { - new ctor({ type: 'bytes' }); - return true; - } - catch (_a) { - return false; - } - } - - function createReadableStreamWrapper(ctor) { - assert$1(isReadableStreamConstructor(ctor)); - var byteSourceSupported = supportsByteSource(ctor); - return function (readable, _a) { - var _b = _a === void 0 ? {} : _a, type = _b.type; - type = parseReadableType(type); - if (type === 'bytes' && !byteSourceSupported) { - type = undefined; - } - if (readable.constructor === ctor) { - if (type !== 'bytes' || supportsByobReader(readable)) { - return readable; - } - } - if (type === 'bytes') { - var source = createWrappingReadableSource(readable, { type: type }); - return new ctor(source); - } - else { - var source = createWrappingReadableSource(readable); - return new ctor(source); - } - }; - } - function createWrappingReadableSource(readable, _a) { - var _b = _a === void 0 ? {} : _a, type = _b.type; - assert$1(isReadableStream(readable)); - assert$1(readable.locked === false); - type = parseReadableType(type); - var source; - if (type === 'bytes') { - source = new WrappingReadableByteStreamSource(readable); - } - else { - source = new WrappingReadableStreamDefaultSource(readable); - } - return source; - } - function parseReadableType(type) { - var typeString = String(type); - if (typeString === 'bytes') { - return typeString; - } - else if (type === undefined) { - return type; - } - else { - throw new RangeError('Invalid type is specified'); - } - } - var AbstractWrappingReadableStreamSource = /** @class */ (function () { - function AbstractWrappingReadableStreamSource(underlyingStream) { - this._underlyingReader = undefined; - this._readerMode = undefined; - this._readableStreamController = undefined; - this._pendingRead = undefined; - this._underlyingStream = underlyingStream; - // always keep a reader attached to detect close/error - this._attachDefaultReader(); - } - AbstractWrappingReadableStreamSource.prototype.start = function (controller) { - this._readableStreamController = controller; - }; - AbstractWrappingReadableStreamSource.prototype.cancel = function (reason) { - assert$1(this._underlyingReader !== undefined); - return this._underlyingReader.cancel(reason); - }; - AbstractWrappingReadableStreamSource.prototype._attachDefaultReader = function () { - if (this._readerMode === "default" /* DEFAULT */) { - return; - } - this._detachReader(); - var reader = this._underlyingStream.getReader(); - this._readerMode = "default" /* DEFAULT */; - this._attachReader(reader); - }; - AbstractWrappingReadableStreamSource.prototype._attachReader = function (reader) { - var _this = this; - assert$1(this._underlyingReader === undefined); - this._underlyingReader = reader; - var closed = this._underlyingReader.closed; - if (!closed) { - return; - } - closed - .then(function () { return _this._finishPendingRead(); }) - .then(function () { - if (reader === _this._underlyingReader) { - _this._readableStreamController.close(); - } - }, function (reason) { - if (reader === _this._underlyingReader) { - _this._readableStreamController.error(reason); - } - }) - .catch(noop$1); - }; - AbstractWrappingReadableStreamSource.prototype._detachReader = function () { - if (this._underlyingReader === undefined) { - return; - } - this._underlyingReader.releaseLock(); - this._underlyingReader = undefined; - this._readerMode = undefined; - }; - AbstractWrappingReadableStreamSource.prototype._pullWithDefaultReader = function () { - var _this = this; - this._attachDefaultReader(); - // TODO Backpressure? - var read = this._underlyingReader.read() - .then(function (result) { - var controller = _this._readableStreamController; - if (result.done) { - _this._tryClose(); - } - else { - controller.enqueue(result.value); - } - }); - this._setPendingRead(read); - return read; - }; - AbstractWrappingReadableStreamSource.prototype._tryClose = function () { - try { - this._readableStreamController.close(); - } - catch (_a) { - // already errored or closed - } - }; - AbstractWrappingReadableStreamSource.prototype._setPendingRead = function (readPromise) { - var _this = this; - var pendingRead; - var finishRead = function () { - if (_this._pendingRead === pendingRead) { - _this._pendingRead = undefined; - } - }; - this._pendingRead = pendingRead = readPromise.then(finishRead, finishRead); - }; - AbstractWrappingReadableStreamSource.prototype._finishPendingRead = function () { - var _this = this; - if (!this._pendingRead) { - return undefined; - } - var afterRead = function () { return _this._finishPendingRead(); }; - return this._pendingRead.then(afterRead, afterRead); - }; - return AbstractWrappingReadableStreamSource; - }()); - var WrappingReadableStreamDefaultSource = /** @class */ (function (_super) { - __extends(WrappingReadableStreamDefaultSource, _super); - function WrappingReadableStreamDefaultSource() { - return _super !== null && _super.apply(this, arguments) || this; - } - WrappingReadableStreamDefaultSource.prototype.pull = function () { - return this._pullWithDefaultReader(); - }; - return WrappingReadableStreamDefaultSource; - }(AbstractWrappingReadableStreamSource)); - function toUint8Array(view) { - return new Uint8Array(view.buffer, view.byteOffset, view.byteLength); - } - function copyArrayBufferView(from, to) { - var fromArray = toUint8Array(from); - var toArray = toUint8Array(to); - toArray.set(fromArray, 0); - } - var WrappingReadableByteStreamSource = /** @class */ (function (_super) { - __extends(WrappingReadableByteStreamSource, _super); - function WrappingReadableByteStreamSource(underlyingStream) { - var _this = this; - var supportsByob = supportsByobReader(underlyingStream); - _this = _super.call(this, underlyingStream) || this; - _this._supportsByob = supportsByob; - return _this; - } - Object.defineProperty(WrappingReadableByteStreamSource.prototype, "type", { - get: function () { - return 'bytes'; - }, - enumerable: false, - configurable: true - }); - WrappingReadableByteStreamSource.prototype._attachByobReader = function () { - if (this._readerMode === "byob" /* BYOB */) { - return; - } - assert$1(this._supportsByob); - this._detachReader(); - var reader = this._underlyingStream.getReader({ mode: 'byob' }); - this._readerMode = "byob" /* BYOB */; - this._attachReader(reader); - }; - WrappingReadableByteStreamSource.prototype.pull = function () { - if (this._supportsByob) { - var byobRequest = this._readableStreamController.byobRequest; - if (byobRequest) { - return this._pullWithByobRequest(byobRequest); - } - } - return this._pullWithDefaultReader(); - }; - WrappingReadableByteStreamSource.prototype._pullWithByobRequest = function (byobRequest) { - var _this = this; - this._attachByobReader(); - // reader.read(view) detaches the input view, therefore we cannot pass byobRequest.view directly - // create a separate buffer to read into, then copy that to byobRequest.view - var buffer = new Uint8Array(byobRequest.view.byteLength); - // TODO Backpressure? - var read = this._underlyingReader.read(buffer) - .then(function (result) { - _this._readableStreamController; - if (result.done) { - _this._tryClose(); - byobRequest.respond(0); - } - else { - copyArrayBufferView(result.value, byobRequest.view); - byobRequest.respond(result.value.byteLength); - } - }); - this._setPendingRead(read); - return read; - }; - return WrappingReadableByteStreamSource; - }(AbstractWrappingReadableStreamSource)); - - function createWritableStreamWrapper(ctor) { - assert$1(isWritableStreamConstructor(ctor)); - return function (writable) { - if (writable.constructor === ctor) { - return writable; - } - var sink = createWrappingWritableSink(writable); - return new ctor(sink); - }; - } - function createWrappingWritableSink(writable) { - assert$1(isWritableStream(writable)); - assert$1(writable.locked === false); - var writer = writable.getWriter(); - return new WrappingWritableStreamSink(writer); - } - var WrappingWritableStreamSink = /** @class */ (function () { - function WrappingWritableStreamSink(underlyingWriter) { - var _this = this; - this._writableStreamController = undefined; - this._pendingWrite = undefined; - this._state = "writable" /* WRITABLE */; - this._storedError = undefined; - this._underlyingWriter = underlyingWriter; - this._errorPromise = new Promise(function (resolve, reject) { - _this._errorPromiseReject = reject; - }); - this._errorPromise.catch(noop$1); - } - WrappingWritableStreamSink.prototype.start = function (controller) { - var _this = this; - this._writableStreamController = controller; - this._underlyingWriter.closed - .then(function () { - _this._state = "closed" /* CLOSED */; - }) - .catch(function (reason) { return _this._finishErroring(reason); }); - }; - WrappingWritableStreamSink.prototype.write = function (chunk) { - var _this = this; - var writer = this._underlyingWriter; - // Detect past errors - if (writer.desiredSize === null) { - return writer.ready; - } - var writeRequest = writer.write(chunk); - // Detect future errors - writeRequest.catch(function (reason) { return _this._finishErroring(reason); }); - writer.ready.catch(function (reason) { return _this._startErroring(reason); }); - // Reject write when errored - var write = Promise.race([writeRequest, this._errorPromise]); - this._setPendingWrite(write); - return write; - }; - WrappingWritableStreamSink.prototype.close = function () { - var _this = this; - if (this._pendingWrite === undefined) { - return this._underlyingWriter.close(); - } - return this._finishPendingWrite().then(function () { return _this.close(); }); - }; - WrappingWritableStreamSink.prototype.abort = function (reason) { - if (this._state === "errored" /* ERRORED */) { - return undefined; - } - var writer = this._underlyingWriter; - return writer.abort(reason); - }; - WrappingWritableStreamSink.prototype._setPendingWrite = function (writePromise) { - var _this = this; - var pendingWrite; - var finishWrite = function () { - if (_this._pendingWrite === pendingWrite) { - _this._pendingWrite = undefined; - } - }; - this._pendingWrite = pendingWrite = writePromise.then(finishWrite, finishWrite); - }; - WrappingWritableStreamSink.prototype._finishPendingWrite = function () { - var _this = this; - if (this._pendingWrite === undefined) { - return Promise.resolve(); - } - var afterWrite = function () { return _this._finishPendingWrite(); }; - return this._pendingWrite.then(afterWrite, afterWrite); - }; - WrappingWritableStreamSink.prototype._startErroring = function (reason) { - var _this = this; - if (this._state === "writable" /* WRITABLE */) { - this._state = "erroring" /* ERRORING */; - this._storedError = reason; - var afterWrite = function () { return _this._finishErroring(reason); }; - if (this._pendingWrite === undefined) { - afterWrite(); - } - else { - this._finishPendingWrite().then(afterWrite, afterWrite); - } - this._writableStreamController.error(reason); - } - }; - WrappingWritableStreamSink.prototype._finishErroring = function (reason) { - if (this._state === "writable" /* WRITABLE */) { - this._startErroring(reason); - } - if (this._state === "erroring" /* ERRORING */) { - this._state = "errored" /* ERRORED */; - this._errorPromiseReject(this._storedError); - } - }; - return WrappingWritableStreamSink; - }()); - - function createTransformStreamWrapper(ctor) { - assert$1(isTransformStreamConstructor(ctor)); - return function (transform) { - if (transform.constructor === ctor) { - return transform; - } - var transformer = createWrappingTransformer(transform); - return new ctor(transformer); - }; - } - function createWrappingTransformer(transform) { - assert$1(isTransformStream(transform)); - var readable = transform.readable, writable = transform.writable; - assert$1(readable.locked === false); - assert$1(writable.locked === false); - var reader = readable.getReader(); - var writer; - try { - writer = writable.getWriter(); - } - catch (e) { - reader.releaseLock(); // do not leak reader - throw e; - } - return new WrappingTransformStreamTransformer(reader, writer); - } - var WrappingTransformStreamTransformer = /** @class */ (function () { - function WrappingTransformStreamTransformer(reader, writer) { - var _this = this; - this._transformStreamController = undefined; - this._onRead = function (result) { - if (result.done) { - return; - } - _this._transformStreamController.enqueue(result.value); - return _this._reader.read().then(_this._onRead); - }; - this._onError = function (reason) { - _this._flushReject(reason); - _this._transformStreamController.error(reason); - _this._reader.cancel(reason).catch(noop$1); - _this._writer.abort(reason).catch(noop$1); - }; - this._onTerminate = function () { - _this._flushResolve(); - _this._transformStreamController.terminate(); - var error = new TypeError('TransformStream terminated'); - _this._writer.abort(error).catch(noop$1); - }; - this._reader = reader; - this._writer = writer; - this._flushPromise = new Promise(function (resolve, reject) { - _this._flushResolve = resolve; - _this._flushReject = reject; - }); - } - WrappingTransformStreamTransformer.prototype.start = function (controller) { - this._transformStreamController = controller; - this._reader.read() - .then(this._onRead) - .then(this._onTerminate, this._onError); - var readerClosed = this._reader.closed; - if (readerClosed) { - readerClosed - .then(this._onTerminate, this._onError); - } - }; - WrappingTransformStreamTransformer.prototype.transform = function (chunk) { - return this._writer.write(chunk); - }; - WrappingTransformStreamTransformer.prototype.flush = function () { - var _this = this; - return this._writer.close() - .then(function () { return _this._flushPromise; }); - }; - return WrappingTransformStreamTransformer; - }()); - - var webStreamsAdapter = /*#__PURE__*/Object.freeze({ - __proto__: null, - createReadableStreamWrapper: createReadableStreamWrapper, - createTransformStreamWrapper: createTransformStreamWrapper, - createWrappingReadableSource: createWrappingReadableSource, - createWrappingTransformer: createWrappingTransformer, - createWrappingWritableSink: createWrappingWritableSink, - createWritableStreamWrapper: createWritableStreamWrapper - }); - - var bn = createCommonjsModule(function (module) { - (function (module, exports) { - - // Utils - function assert (val, msg) { - if (!val) throw new Error(msg || 'Assertion failed'); - } - - // Could use `inherits` module, but don't want to move from single file - // architecture yet. - function inherits (ctor, superCtor) { - ctor.super_ = superCtor; - var TempCtor = function () {}; - TempCtor.prototype = superCtor.prototype; - ctor.prototype = new TempCtor(); - ctor.prototype.constructor = ctor; - } - - // BN - - function BN (number, base, endian) { - if (BN.isBN(number)) { - return number; - } - - this.negative = 0; - this.words = null; - this.length = 0; - - // Reduction context - this.red = null; - - if (number !== null) { - if (base === 'le' || base === 'be') { - endian = base; - base = 10; - } - - this._init(number || 0, base || 10, endian || 'be'); - } - } - if (typeof module === 'object') { - module.exports = BN; - } else { - exports.BN = BN; - } - - BN.BN = BN; - BN.wordSize = 26; - - var Buffer; - try { - Buffer = void('buffer').Buffer; - } catch (e) { - } - - BN.isBN = function isBN (num) { - if (num instanceof BN) { - return true; - } - - return num !== null && typeof num === 'object' && - num.constructor.wordSize === BN.wordSize && Array.isArray(num.words); - }; - - BN.max = function max (left, right) { - if (left.cmp(right) > 0) return left; - return right; - }; - - BN.min = function min (left, right) { - if (left.cmp(right) < 0) return left; - return right; - }; - - BN.prototype._init = function init (number, base, endian) { - if (typeof number === 'number') { - return this._initNumber(number, base, endian); - } - - if (typeof number === 'object') { - return this._initArray(number, base, endian); - } - - if (base === 'hex') { - base = 16; - } - assert(base === (base | 0) && base >= 2 && base <= 36); - - number = number.toString().replace(/\s+/g, ''); - var start = 0; - if (number[0] === '-') { - start++; - } - - if (base === 16) { - this._parseHex(number, start); - } else { - this._parseBase(number, base, start); - } - - if (number[0] === '-') { - this.negative = 1; - } - - this.strip(); - - if (endian !== 'le') return; - - this._initArray(this.toArray(), base, endian); - }; - - BN.prototype._initNumber = function _initNumber (number, base, endian) { - if (number < 0) { - this.negative = 1; - number = -number; - } - if (number < 0x4000000) { - this.words = [ number & 0x3ffffff ]; - this.length = 1; - } else if (number < 0x10000000000000) { - this.words = [ - number & 0x3ffffff, - (number / 0x4000000) & 0x3ffffff - ]; - this.length = 2; - } else { - assert(number < 0x20000000000000); // 2 ^ 53 (unsafe) - this.words = [ - number & 0x3ffffff, - (number / 0x4000000) & 0x3ffffff, - 1 - ]; - this.length = 3; - } - - if (endian !== 'le') return; - - // Reverse the bytes - this._initArray(this.toArray(), base, endian); - }; - - BN.prototype._initArray = function _initArray (number, base, endian) { - // Perhaps a Uint8Array - assert(typeof number.length === 'number'); - if (number.length <= 0) { - this.words = [ 0 ]; - this.length = 1; - return this; - } - - this.length = Math.ceil(number.length / 3); - this.words = new Array(this.length); - for (var i = 0; i < this.length; i++) { - this.words[i] = 0; - } - - var j, w; - var off = 0; - if (endian === 'be') { - for (i = number.length - 1, j = 0; i >= 0; i -= 3) { - w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16); - this.words[j] |= (w << off) & 0x3ffffff; - this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; - off += 24; - if (off >= 26) { - off -= 26; - j++; - } - } - } else if (endian === 'le') { - for (i = 0, j = 0; i < number.length; i += 3) { - w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16); - this.words[j] |= (w << off) & 0x3ffffff; - this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; - off += 24; - if (off >= 26) { - off -= 26; - j++; - } - } - } - return this.strip(); - }; - - function parseHex (str, start, end) { - var r = 0; - var len = Math.min(str.length, end); - for (var i = start; i < len; i++) { - var c = str.charCodeAt(i) - 48; - - r <<= 4; - - // 'a' - 'f' - if (c >= 49 && c <= 54) { - r |= c - 49 + 0xa; - - // 'A' - 'F' - } else if (c >= 17 && c <= 22) { - r |= c - 17 + 0xa; - - // '0' - '9' - } else { - r |= c & 0xf; - } - } - return r; - } - - BN.prototype._parseHex = function _parseHex (number, start) { - // Create possibly bigger array to ensure that it fits the number - this.length = Math.ceil((number.length - start) / 6); - this.words = new Array(this.length); - for (var i = 0; i < this.length; i++) { - this.words[i] = 0; - } - - var j, w; - // Scan 24-bit chunks and add them to the number - var off = 0; - for (i = number.length - 6, j = 0; i >= start; i -= 6) { - w = parseHex(number, i, i + 6); - this.words[j] |= (w << off) & 0x3ffffff; - // NOTE: `0x3fffff` is intentional here, 26bits max shift + 24bit hex limb - this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; - off += 24; - if (off >= 26) { - off -= 26; - j++; - } - } - if (i + 6 !== start) { - w = parseHex(number, start, i + 6); - this.words[j] |= (w << off) & 0x3ffffff; - this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; - } - this.strip(); - }; - - function parseBase (str, start, end, mul) { - var r = 0; - var len = Math.min(str.length, end); - for (var i = start; i < len; i++) { - var c = str.charCodeAt(i) - 48; - - r *= mul; - - // 'a' - if (c >= 49) { - r += c - 49 + 0xa; - - // 'A' - } else if (c >= 17) { - r += c - 17 + 0xa; - - // '0' - '9' - } else { - r += c; - } - } - return r; - } - - BN.prototype._parseBase = function _parseBase (number, base, start) { - // Initialize as zero - this.words = [ 0 ]; - this.length = 1; - - // Find length of limb in base - for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) { - limbLen++; - } - limbLen--; - limbPow = (limbPow / base) | 0; - - var total = number.length - start; - var mod = total % limbLen; - var end = Math.min(total, total - mod) + start; - - var word = 0; - for (var i = start; i < end; i += limbLen) { - word = parseBase(number, i, i + limbLen, base); - - this.imuln(limbPow); - if (this.words[0] + word < 0x4000000) { - this.words[0] += word; - } else { - this._iaddn(word); - } - } - - if (mod !== 0) { - var pow = 1; - word = parseBase(number, i, number.length, base); - - for (i = 0; i < mod; i++) { - pow *= base; - } - - this.imuln(pow); - if (this.words[0] + word < 0x4000000) { - this.words[0] += word; - } else { - this._iaddn(word); - } - } - }; - - BN.prototype.copy = function copy (dest) { - dest.words = new Array(this.length); - for (var i = 0; i < this.length; i++) { - dest.words[i] = this.words[i]; - } - dest.length = this.length; - dest.negative = this.negative; - dest.red = this.red; - }; - - BN.prototype.clone = function clone () { - var r = new BN(null); - this.copy(r); - return r; - }; - - BN.prototype._expand = function _expand (size) { - while (this.length < size) { - this.words[this.length++] = 0; - } - return this; - }; - - // Remove leading `0` from `this` - BN.prototype.strip = function strip () { - while (this.length > 1 && this.words[this.length - 1] === 0) { - this.length--; - } - return this._normSign(); - }; - - BN.prototype._normSign = function _normSign () { - // -0 = 0 - if (this.length === 1 && this.words[0] === 0) { - this.negative = 0; - } - return this; - }; - - BN.prototype.inspect = function inspect () { - return (this.red ? ''; - }; - - /* - - var zeros = []; - var groupSizes = []; - var groupBases = []; - - var s = ''; - var i = -1; - while (++i < BN.wordSize) { - zeros[i] = s; - s += '0'; - } - groupSizes[0] = 0; - groupSizes[1] = 0; - groupBases[0] = 0; - groupBases[1] = 0; - var base = 2 - 1; - while (++base < 36 + 1) { - var groupSize = 0; - var groupBase = 1; - while (groupBase < (1 << BN.wordSize) / base) { - groupBase *= base; - groupSize += 1; - } - groupSizes[base] = groupSize; - groupBases[base] = groupBase; - } - - */ - - var zeros = [ - '', - '0', - '00', - '000', - '0000', - '00000', - '000000', - '0000000', - '00000000', - '000000000', - '0000000000', - '00000000000', - '000000000000', - '0000000000000', - '00000000000000', - '000000000000000', - '0000000000000000', - '00000000000000000', - '000000000000000000', - '0000000000000000000', - '00000000000000000000', - '000000000000000000000', - '0000000000000000000000', - '00000000000000000000000', - '000000000000000000000000', - '0000000000000000000000000' - ]; - - var groupSizes = [ - 0, 0, - 25, 16, 12, 11, 10, 9, 8, - 8, 7, 7, 7, 7, 6, 6, - 6, 6, 6, 6, 6, 5, 5, - 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5 - ]; - - var groupBases = [ - 0, 0, - 33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216, - 43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625, - 16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632, - 6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149, - 24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176 - ]; - - BN.prototype.toString = function toString (base, padding) { - base = base || 10; - padding = padding | 0 || 1; - - var out; - if (base === 16 || base === 'hex') { - out = ''; - var off = 0; - var carry = 0; - for (var i = 0; i < this.length; i++) { - var w = this.words[i]; - var word = (((w << off) | carry) & 0xffffff).toString(16); - carry = (w >>> (24 - off)) & 0xffffff; - if (carry !== 0 || i !== this.length - 1) { - out = zeros[6 - word.length] + word + out; - } else { - out = word + out; - } - off += 2; - if (off >= 26) { - off -= 26; - i--; - } - } - if (carry !== 0) { - out = carry.toString(16) + out; - } - while (out.length % padding !== 0) { - out = '0' + out; - } - if (this.negative !== 0) { - out = '-' + out; - } - return out; - } - - if (base === (base | 0) && base >= 2 && base <= 36) { - // var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base)); - var groupSize = groupSizes[base]; - // var groupBase = Math.pow(base, groupSize); - var groupBase = groupBases[base]; - out = ''; - var c = this.clone(); - c.negative = 0; - while (!c.isZero()) { - var r = c.modn(groupBase).toString(base); - c = c.idivn(groupBase); - - if (!c.isZero()) { - out = zeros[groupSize - r.length] + r + out; - } else { - out = r + out; - } - } - if (this.isZero()) { - out = '0' + out; - } - while (out.length % padding !== 0) { - out = '0' + out; - } - if (this.negative !== 0) { - out = '-' + out; - } - return out; - } - - assert(false, 'Base should be between 2 and 36'); - }; - - BN.prototype.toNumber = function toNumber () { - var ret = this.words[0]; - if (this.length === 2) { - ret += this.words[1] * 0x4000000; - } else if (this.length === 3 && this.words[2] === 0x01) { - // NOTE: at this stage it is known that the top bit is set - ret += 0x10000000000000 + (this.words[1] * 0x4000000); - } else if (this.length > 2) { - assert(false, 'Number can only safely store up to 53 bits'); - } - return (this.negative !== 0) ? -ret : ret; - }; - - BN.prototype.toJSON = function toJSON () { - return this.toString(16); - }; - - BN.prototype.toBuffer = function toBuffer (endian, length) { - assert(typeof Buffer !== 'undefined'); - return this.toArrayLike(Buffer, endian, length); - }; - - BN.prototype.toArray = function toArray (endian, length) { - return this.toArrayLike(Array, endian, length); - }; - - BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) { - var byteLength = this.byteLength(); - var reqLength = length || Math.max(1, byteLength); - assert(byteLength <= reqLength, 'byte array longer than desired length'); - assert(reqLength > 0, 'Requested array length <= 0'); - - this.strip(); - var littleEndian = endian === 'le'; - var res = new ArrayType(reqLength); - - var b, i; - var q = this.clone(); - if (!littleEndian) { - // Assume big-endian - for (i = 0; i < reqLength - byteLength; i++) { - res[i] = 0; - } - - for (i = 0; !q.isZero(); i++) { - b = q.andln(0xff); - q.iushrn(8); - - res[reqLength - i - 1] = b; - } - } else { - for (i = 0; !q.isZero(); i++) { - b = q.andln(0xff); - q.iushrn(8); - - res[i] = b; - } - - for (; i < reqLength; i++) { - res[i] = 0; - } - } - - return res; - }; - - if (Math.clz32) { - BN.prototype._countBits = function _countBits (w) { - return 32 - Math.clz32(w); - }; - } else { - BN.prototype._countBits = function _countBits (w) { - var t = w; - var r = 0; - if (t >= 0x1000) { - r += 13; - t >>>= 13; - } - if (t >= 0x40) { - r += 7; - t >>>= 7; - } - if (t >= 0x8) { - r += 4; - t >>>= 4; - } - if (t >= 0x02) { - r += 2; - t >>>= 2; - } - return r + t; - }; - } - - BN.prototype._zeroBits = function _zeroBits (w) { - // Short-cut - if (w === 0) return 26; - - var t = w; - var r = 0; - if ((t & 0x1fff) === 0) { - r += 13; - t >>>= 13; - } - if ((t & 0x7f) === 0) { - r += 7; - t >>>= 7; - } - if ((t & 0xf) === 0) { - r += 4; - t >>>= 4; - } - if ((t & 0x3) === 0) { - r += 2; - t >>>= 2; - } - if ((t & 0x1) === 0) { - r++; - } - return r; - }; - - // Return number of used bits in a BN - BN.prototype.bitLength = function bitLength () { - var w = this.words[this.length - 1]; - var hi = this._countBits(w); - return (this.length - 1) * 26 + hi; - }; - - function toBitArray (num) { - var w = new Array(num.bitLength()); - - for (var bit = 0; bit < w.length; bit++) { - var off = (bit / 26) | 0; - var wbit = bit % 26; - - w[bit] = (num.words[off] & (1 << wbit)) >>> wbit; - } - - return w; - } - - // Number of trailing zero bits - BN.prototype.zeroBits = function zeroBits () { - if (this.isZero()) return 0; - - var r = 0; - for (var i = 0; i < this.length; i++) { - var b = this._zeroBits(this.words[i]); - r += b; - if (b !== 26) break; - } - return r; - }; - - BN.prototype.byteLength = function byteLength () { - return Math.ceil(this.bitLength() / 8); - }; - - BN.prototype.toTwos = function toTwos (width) { - if (this.negative !== 0) { - return this.abs().inotn(width).iaddn(1); - } - return this.clone(); - }; - - BN.prototype.fromTwos = function fromTwos (width) { - if (this.testn(width - 1)) { - return this.notn(width).iaddn(1).ineg(); - } - return this.clone(); - }; - - BN.prototype.isNeg = function isNeg () { - return this.negative !== 0; - }; - - // Return negative clone of `this` - BN.prototype.neg = function neg () { - return this.clone().ineg(); - }; - - BN.prototype.ineg = function ineg () { - if (!this.isZero()) { - this.negative ^= 1; - } - - return this; - }; - - // Or `num` with `this` in-place - BN.prototype.iuor = function iuor (num) { - while (this.length < num.length) { - this.words[this.length++] = 0; - } - - for (var i = 0; i < num.length; i++) { - this.words[i] = this.words[i] | num.words[i]; - } - - return this.strip(); - }; - - BN.prototype.ior = function ior (num) { - assert((this.negative | num.negative) === 0); - return this.iuor(num); - }; - - // Or `num` with `this` - BN.prototype.or = function or (num) { - if (this.length > num.length) return this.clone().ior(num); - return num.clone().ior(this); - }; - - BN.prototype.uor = function uor (num) { - if (this.length > num.length) return this.clone().iuor(num); - return num.clone().iuor(this); - }; - - // And `num` with `this` in-place - BN.prototype.iuand = function iuand (num) { - // b = min-length(num, this) - var b; - if (this.length > num.length) { - b = num; - } else { - b = this; - } - - for (var i = 0; i < b.length; i++) { - this.words[i] = this.words[i] & num.words[i]; - } - - this.length = b.length; - - return this.strip(); - }; - - BN.prototype.iand = function iand (num) { - assert((this.negative | num.negative) === 0); - return this.iuand(num); - }; - - // And `num` with `this` - BN.prototype.and = function and (num) { - if (this.length > num.length) return this.clone().iand(num); - return num.clone().iand(this); - }; - - BN.prototype.uand = function uand (num) { - if (this.length > num.length) return this.clone().iuand(num); - return num.clone().iuand(this); - }; - - // Xor `num` with `this` in-place - BN.prototype.iuxor = function iuxor (num) { - // a.length > b.length - var a; - var b; - if (this.length > num.length) { - a = this; - b = num; - } else { - a = num; - b = this; - } - - for (var i = 0; i < b.length; i++) { - this.words[i] = a.words[i] ^ b.words[i]; - } - - if (this !== a) { - for (; i < a.length; i++) { - this.words[i] = a.words[i]; - } - } - - this.length = a.length; - - return this.strip(); - }; - - BN.prototype.ixor = function ixor (num) { - assert((this.negative | num.negative) === 0); - return this.iuxor(num); - }; - - // Xor `num` with `this` - BN.prototype.xor = function xor (num) { - if (this.length > num.length) return this.clone().ixor(num); - return num.clone().ixor(this); - }; - - BN.prototype.uxor = function uxor (num) { - if (this.length > num.length) return this.clone().iuxor(num); - return num.clone().iuxor(this); - }; - - // Not ``this`` with ``width`` bitwidth - BN.prototype.inotn = function inotn (width) { - assert(typeof width === 'number' && width >= 0); - - var bytesNeeded = Math.ceil(width / 26) | 0; - var bitsLeft = width % 26; - - // Extend the buffer with leading zeroes - this._expand(bytesNeeded); - - if (bitsLeft > 0) { - bytesNeeded--; - } - - // Handle complete words - for (var i = 0; i < bytesNeeded; i++) { - this.words[i] = ~this.words[i] & 0x3ffffff; - } - - // Handle the residue - if (bitsLeft > 0) { - this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft)); - } - - // And remove leading zeroes - return this.strip(); - }; - - BN.prototype.notn = function notn (width) { - return this.clone().inotn(width); - }; - - // Set `bit` of `this` - BN.prototype.setn = function setn (bit, val) { - assert(typeof bit === 'number' && bit >= 0); - - var off = (bit / 26) | 0; - var wbit = bit % 26; - - this._expand(off + 1); - - if (val) { - this.words[off] = this.words[off] | (1 << wbit); - } else { - this.words[off] = this.words[off] & ~(1 << wbit); - } - - return this.strip(); - }; - - // Add `num` to `this` in-place - BN.prototype.iadd = function iadd (num) { - var r; - - // negative + positive - if (this.negative !== 0 && num.negative === 0) { - this.negative = 0; - r = this.isub(num); - this.negative ^= 1; - return this._normSign(); - - // positive + negative - } else if (this.negative === 0 && num.negative !== 0) { - num.negative = 0; - r = this.isub(num); - num.negative = 1; - return r._normSign(); - } - - // a.length > b.length - var a, b; - if (this.length > num.length) { - a = this; - b = num; - } else { - a = num; - b = this; - } - - var carry = 0; - for (var i = 0; i < b.length; i++) { - r = (a.words[i] | 0) + (b.words[i] | 0) + carry; - this.words[i] = r & 0x3ffffff; - carry = r >>> 26; - } - for (; carry !== 0 && i < a.length; i++) { - r = (a.words[i] | 0) + carry; - this.words[i] = r & 0x3ffffff; - carry = r >>> 26; - } - - this.length = a.length; - if (carry !== 0) { - this.words[this.length] = carry; - this.length++; - // Copy the rest of the words - } else if (a !== this) { - for (; i < a.length; i++) { - this.words[i] = a.words[i]; - } - } - - return this; - }; - - // Add `num` to `this` - BN.prototype.add = function add (num) { - var res; - if (num.negative !== 0 && this.negative === 0) { - num.negative = 0; - res = this.sub(num); - num.negative ^= 1; - return res; - } else if (num.negative === 0 && this.negative !== 0) { - this.negative = 0; - res = num.sub(this); - this.negative = 1; - return res; - } - - if (this.length > num.length) return this.clone().iadd(num); - - return num.clone().iadd(this); - }; - - // Subtract `num` from `this` in-place - BN.prototype.isub = function isub (num) { - // this - (-num) = this + num - if (num.negative !== 0) { - num.negative = 0; - var r = this.iadd(num); - num.negative = 1; - return r._normSign(); - - // -this - num = -(this + num) - } else if (this.negative !== 0) { - this.negative = 0; - this.iadd(num); - this.negative = 1; - return this._normSign(); - } - - // At this point both numbers are positive - var cmp = this.cmp(num); - - // Optimization - zeroify - if (cmp === 0) { - this.negative = 0; - this.length = 1; - this.words[0] = 0; - return this; - } - - // a > b - var a, b; - if (cmp > 0) { - a = this; - b = num; - } else { - a = num; - b = this; - } - - var carry = 0; - for (var i = 0; i < b.length; i++) { - r = (a.words[i] | 0) - (b.words[i] | 0) + carry; - carry = r >> 26; - this.words[i] = r & 0x3ffffff; - } - for (; carry !== 0 && i < a.length; i++) { - r = (a.words[i] | 0) + carry; - carry = r >> 26; - this.words[i] = r & 0x3ffffff; - } - - // Copy rest of the words - if (carry === 0 && i < a.length && a !== this) { - for (; i < a.length; i++) { - this.words[i] = a.words[i]; - } - } - - this.length = Math.max(this.length, i); - - if (a !== this) { - this.negative = 1; - } - - return this.strip(); - }; - - // Subtract `num` from `this` - BN.prototype.sub = function sub (num) { - return this.clone().isub(num); - }; - - function smallMulTo (self, num, out) { - out.negative = num.negative ^ self.negative; - var len = (self.length + num.length) | 0; - out.length = len; - len = (len - 1) | 0; - - // Peel one iteration (compiler can't do it, because of code complexity) - var a = self.words[0] | 0; - var b = num.words[0] | 0; - var r = a * b; - - var lo = r & 0x3ffffff; - var carry = (r / 0x4000000) | 0; - out.words[0] = lo; - - for (var k = 1; k < len; k++) { - // Sum all words with the same `i + j = k` and accumulate `ncarry`, - // note that ncarry could be >= 0x3ffffff - var ncarry = carry >>> 26; - var rword = carry & 0x3ffffff; - var maxJ = Math.min(k, num.length - 1); - for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { - var i = (k - j) | 0; - a = self.words[i] | 0; - b = num.words[j] | 0; - r = a * b + rword; - ncarry += (r / 0x4000000) | 0; - rword = r & 0x3ffffff; - } - out.words[k] = rword | 0; - carry = ncarry | 0; - } - if (carry !== 0) { - out.words[k] = carry | 0; - } else { - out.length--; - } - - return out.strip(); - } - - // TODO(indutny): it may be reasonable to omit it for users who don't need - // to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit - // multiplication (like elliptic secp256k1). - var comb10MulTo = function comb10MulTo (self, num, out) { - var a = self.words; - var b = num.words; - var o = out.words; - var c = 0; - var lo; - var mid; - var hi; - var a0 = a[0] | 0; - var al0 = a0 & 0x1fff; - var ah0 = a0 >>> 13; - var a1 = a[1] | 0; - var al1 = a1 & 0x1fff; - var ah1 = a1 >>> 13; - var a2 = a[2] | 0; - var al2 = a2 & 0x1fff; - var ah2 = a2 >>> 13; - var a3 = a[3] | 0; - var al3 = a3 & 0x1fff; - var ah3 = a3 >>> 13; - var a4 = a[4] | 0; - var al4 = a4 & 0x1fff; - var ah4 = a4 >>> 13; - var a5 = a[5] | 0; - var al5 = a5 & 0x1fff; - var ah5 = a5 >>> 13; - var a6 = a[6] | 0; - var al6 = a6 & 0x1fff; - var ah6 = a6 >>> 13; - var a7 = a[7] | 0; - var al7 = a7 & 0x1fff; - var ah7 = a7 >>> 13; - var a8 = a[8] | 0; - var al8 = a8 & 0x1fff; - var ah8 = a8 >>> 13; - var a9 = a[9] | 0; - var al9 = a9 & 0x1fff; - var ah9 = a9 >>> 13; - var b0 = b[0] | 0; - var bl0 = b0 & 0x1fff; - var bh0 = b0 >>> 13; - var b1 = b[1] | 0; - var bl1 = b1 & 0x1fff; - var bh1 = b1 >>> 13; - var b2 = b[2] | 0; - var bl2 = b2 & 0x1fff; - var bh2 = b2 >>> 13; - var b3 = b[3] | 0; - var bl3 = b3 & 0x1fff; - var bh3 = b3 >>> 13; - var b4 = b[4] | 0; - var bl4 = b4 & 0x1fff; - var bh4 = b4 >>> 13; - var b5 = b[5] | 0; - var bl5 = b5 & 0x1fff; - var bh5 = b5 >>> 13; - var b6 = b[6] | 0; - var bl6 = b6 & 0x1fff; - var bh6 = b6 >>> 13; - var b7 = b[7] | 0; - var bl7 = b7 & 0x1fff; - var bh7 = b7 >>> 13; - var b8 = b[8] | 0; - var bl8 = b8 & 0x1fff; - var bh8 = b8 >>> 13; - var b9 = b[9] | 0; - var bl9 = b9 & 0x1fff; - var bh9 = b9 >>> 13; - - out.negative = self.negative ^ num.negative; - out.length = 19; - /* k = 0 */ - lo = Math.imul(al0, bl0); - mid = Math.imul(al0, bh0); - mid = (mid + Math.imul(ah0, bl0)) | 0; - hi = Math.imul(ah0, bh0); - var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0; - w0 &= 0x3ffffff; - /* k = 1 */ - lo = Math.imul(al1, bl0); - mid = Math.imul(al1, bh0); - mid = (mid + Math.imul(ah1, bl0)) | 0; - hi = Math.imul(ah1, bh0); - lo = (lo + Math.imul(al0, bl1)) | 0; - mid = (mid + Math.imul(al0, bh1)) | 0; - mid = (mid + Math.imul(ah0, bl1)) | 0; - hi = (hi + Math.imul(ah0, bh1)) | 0; - var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0; - w1 &= 0x3ffffff; - /* k = 2 */ - lo = Math.imul(al2, bl0); - mid = Math.imul(al2, bh0); - mid = (mid + Math.imul(ah2, bl0)) | 0; - hi = Math.imul(ah2, bh0); - lo = (lo + Math.imul(al1, bl1)) | 0; - mid = (mid + Math.imul(al1, bh1)) | 0; - mid = (mid + Math.imul(ah1, bl1)) | 0; - hi = (hi + Math.imul(ah1, bh1)) | 0; - lo = (lo + Math.imul(al0, bl2)) | 0; - mid = (mid + Math.imul(al0, bh2)) | 0; - mid = (mid + Math.imul(ah0, bl2)) | 0; - hi = (hi + Math.imul(ah0, bh2)) | 0; - var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0; - w2 &= 0x3ffffff; - /* k = 3 */ - lo = Math.imul(al3, bl0); - mid = Math.imul(al3, bh0); - mid = (mid + Math.imul(ah3, bl0)) | 0; - hi = Math.imul(ah3, bh0); - lo = (lo + Math.imul(al2, bl1)) | 0; - mid = (mid + Math.imul(al2, bh1)) | 0; - mid = (mid + Math.imul(ah2, bl1)) | 0; - hi = (hi + Math.imul(ah2, bh1)) | 0; - lo = (lo + Math.imul(al1, bl2)) | 0; - mid = (mid + Math.imul(al1, bh2)) | 0; - mid = (mid + Math.imul(ah1, bl2)) | 0; - hi = (hi + Math.imul(ah1, bh2)) | 0; - lo = (lo + Math.imul(al0, bl3)) | 0; - mid = (mid + Math.imul(al0, bh3)) | 0; - mid = (mid + Math.imul(ah0, bl3)) | 0; - hi = (hi + Math.imul(ah0, bh3)) | 0; - var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0; - w3 &= 0x3ffffff; - /* k = 4 */ - lo = Math.imul(al4, bl0); - mid = Math.imul(al4, bh0); - mid = (mid + Math.imul(ah4, bl0)) | 0; - hi = Math.imul(ah4, bh0); - lo = (lo + Math.imul(al3, bl1)) | 0; - mid = (mid + Math.imul(al3, bh1)) | 0; - mid = (mid + Math.imul(ah3, bl1)) | 0; - hi = (hi + Math.imul(ah3, bh1)) | 0; - lo = (lo + Math.imul(al2, bl2)) | 0; - mid = (mid + Math.imul(al2, bh2)) | 0; - mid = (mid + Math.imul(ah2, bl2)) | 0; - hi = (hi + Math.imul(ah2, bh2)) | 0; - lo = (lo + Math.imul(al1, bl3)) | 0; - mid = (mid + Math.imul(al1, bh3)) | 0; - mid = (mid + Math.imul(ah1, bl3)) | 0; - hi = (hi + Math.imul(ah1, bh3)) | 0; - lo = (lo + Math.imul(al0, bl4)) | 0; - mid = (mid + Math.imul(al0, bh4)) | 0; - mid = (mid + Math.imul(ah0, bl4)) | 0; - hi = (hi + Math.imul(ah0, bh4)) | 0; - var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0; - w4 &= 0x3ffffff; - /* k = 5 */ - lo = Math.imul(al5, bl0); - mid = Math.imul(al5, bh0); - mid = (mid + Math.imul(ah5, bl0)) | 0; - hi = Math.imul(ah5, bh0); - lo = (lo + Math.imul(al4, bl1)) | 0; - mid = (mid + Math.imul(al4, bh1)) | 0; - mid = (mid + Math.imul(ah4, bl1)) | 0; - hi = (hi + Math.imul(ah4, bh1)) | 0; - lo = (lo + Math.imul(al3, bl2)) | 0; - mid = (mid + Math.imul(al3, bh2)) | 0; - mid = (mid + Math.imul(ah3, bl2)) | 0; - hi = (hi + Math.imul(ah3, bh2)) | 0; - lo = (lo + Math.imul(al2, bl3)) | 0; - mid = (mid + Math.imul(al2, bh3)) | 0; - mid = (mid + Math.imul(ah2, bl3)) | 0; - hi = (hi + Math.imul(ah2, bh3)) | 0; - lo = (lo + Math.imul(al1, bl4)) | 0; - mid = (mid + Math.imul(al1, bh4)) | 0; - mid = (mid + Math.imul(ah1, bl4)) | 0; - hi = (hi + Math.imul(ah1, bh4)) | 0; - lo = (lo + Math.imul(al0, bl5)) | 0; - mid = (mid + Math.imul(al0, bh5)) | 0; - mid = (mid + Math.imul(ah0, bl5)) | 0; - hi = (hi + Math.imul(ah0, bh5)) | 0; - var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0; - w5 &= 0x3ffffff; - /* k = 6 */ - lo = Math.imul(al6, bl0); - mid = Math.imul(al6, bh0); - mid = (mid + Math.imul(ah6, bl0)) | 0; - hi = Math.imul(ah6, bh0); - lo = (lo + Math.imul(al5, bl1)) | 0; - mid = (mid + Math.imul(al5, bh1)) | 0; - mid = (mid + Math.imul(ah5, bl1)) | 0; - hi = (hi + Math.imul(ah5, bh1)) | 0; - lo = (lo + Math.imul(al4, bl2)) | 0; - mid = (mid + Math.imul(al4, bh2)) | 0; - mid = (mid + Math.imul(ah4, bl2)) | 0; - hi = (hi + Math.imul(ah4, bh2)) | 0; - lo = (lo + Math.imul(al3, bl3)) | 0; - mid = (mid + Math.imul(al3, bh3)) | 0; - mid = (mid + Math.imul(ah3, bl3)) | 0; - hi = (hi + Math.imul(ah3, bh3)) | 0; - lo = (lo + Math.imul(al2, bl4)) | 0; - mid = (mid + Math.imul(al2, bh4)) | 0; - mid = (mid + Math.imul(ah2, bl4)) | 0; - hi = (hi + Math.imul(ah2, bh4)) | 0; - lo = (lo + Math.imul(al1, bl5)) | 0; - mid = (mid + Math.imul(al1, bh5)) | 0; - mid = (mid + Math.imul(ah1, bl5)) | 0; - hi = (hi + Math.imul(ah1, bh5)) | 0; - lo = (lo + Math.imul(al0, bl6)) | 0; - mid = (mid + Math.imul(al0, bh6)) | 0; - mid = (mid + Math.imul(ah0, bl6)) | 0; - hi = (hi + Math.imul(ah0, bh6)) | 0; - var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0; - w6 &= 0x3ffffff; - /* k = 7 */ - lo = Math.imul(al7, bl0); - mid = Math.imul(al7, bh0); - mid = (mid + Math.imul(ah7, bl0)) | 0; - hi = Math.imul(ah7, bh0); - lo = (lo + Math.imul(al6, bl1)) | 0; - mid = (mid + Math.imul(al6, bh1)) | 0; - mid = (mid + Math.imul(ah6, bl1)) | 0; - hi = (hi + Math.imul(ah6, bh1)) | 0; - lo = (lo + Math.imul(al5, bl2)) | 0; - mid = (mid + Math.imul(al5, bh2)) | 0; - mid = (mid + Math.imul(ah5, bl2)) | 0; - hi = (hi + Math.imul(ah5, bh2)) | 0; - lo = (lo + Math.imul(al4, bl3)) | 0; - mid = (mid + Math.imul(al4, bh3)) | 0; - mid = (mid + Math.imul(ah4, bl3)) | 0; - hi = (hi + Math.imul(ah4, bh3)) | 0; - lo = (lo + Math.imul(al3, bl4)) | 0; - mid = (mid + Math.imul(al3, bh4)) | 0; - mid = (mid + Math.imul(ah3, bl4)) | 0; - hi = (hi + Math.imul(ah3, bh4)) | 0; - lo = (lo + Math.imul(al2, bl5)) | 0; - mid = (mid + Math.imul(al2, bh5)) | 0; - mid = (mid + Math.imul(ah2, bl5)) | 0; - hi = (hi + Math.imul(ah2, bh5)) | 0; - lo = (lo + Math.imul(al1, bl6)) | 0; - mid = (mid + Math.imul(al1, bh6)) | 0; - mid = (mid + Math.imul(ah1, bl6)) | 0; - hi = (hi + Math.imul(ah1, bh6)) | 0; - lo = (lo + Math.imul(al0, bl7)) | 0; - mid = (mid + Math.imul(al0, bh7)) | 0; - mid = (mid + Math.imul(ah0, bl7)) | 0; - hi = (hi + Math.imul(ah0, bh7)) | 0; - var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0; - w7 &= 0x3ffffff; - /* k = 8 */ - lo = Math.imul(al8, bl0); - mid = Math.imul(al8, bh0); - mid = (mid + Math.imul(ah8, bl0)) | 0; - hi = Math.imul(ah8, bh0); - lo = (lo + Math.imul(al7, bl1)) | 0; - mid = (mid + Math.imul(al7, bh1)) | 0; - mid = (mid + Math.imul(ah7, bl1)) | 0; - hi = (hi + Math.imul(ah7, bh1)) | 0; - lo = (lo + Math.imul(al6, bl2)) | 0; - mid = (mid + Math.imul(al6, bh2)) | 0; - mid = (mid + Math.imul(ah6, bl2)) | 0; - hi = (hi + Math.imul(ah6, bh2)) | 0; - lo = (lo + Math.imul(al5, bl3)) | 0; - mid = (mid + Math.imul(al5, bh3)) | 0; - mid = (mid + Math.imul(ah5, bl3)) | 0; - hi = (hi + Math.imul(ah5, bh3)) | 0; - lo = (lo + Math.imul(al4, bl4)) | 0; - mid = (mid + Math.imul(al4, bh4)) | 0; - mid = (mid + Math.imul(ah4, bl4)) | 0; - hi = (hi + Math.imul(ah4, bh4)) | 0; - lo = (lo + Math.imul(al3, bl5)) | 0; - mid = (mid + Math.imul(al3, bh5)) | 0; - mid = (mid + Math.imul(ah3, bl5)) | 0; - hi = (hi + Math.imul(ah3, bh5)) | 0; - lo = (lo + Math.imul(al2, bl6)) | 0; - mid = (mid + Math.imul(al2, bh6)) | 0; - mid = (mid + Math.imul(ah2, bl6)) | 0; - hi = (hi + Math.imul(ah2, bh6)) | 0; - lo = (lo + Math.imul(al1, bl7)) | 0; - mid = (mid + Math.imul(al1, bh7)) | 0; - mid = (mid + Math.imul(ah1, bl7)) | 0; - hi = (hi + Math.imul(ah1, bh7)) | 0; - lo = (lo + Math.imul(al0, bl8)) | 0; - mid = (mid + Math.imul(al0, bh8)) | 0; - mid = (mid + Math.imul(ah0, bl8)) | 0; - hi = (hi + Math.imul(ah0, bh8)) | 0; - var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0; - w8 &= 0x3ffffff; - /* k = 9 */ - lo = Math.imul(al9, bl0); - mid = Math.imul(al9, bh0); - mid = (mid + Math.imul(ah9, bl0)) | 0; - hi = Math.imul(ah9, bh0); - lo = (lo + Math.imul(al8, bl1)) | 0; - mid = (mid + Math.imul(al8, bh1)) | 0; - mid = (mid + Math.imul(ah8, bl1)) | 0; - hi = (hi + Math.imul(ah8, bh1)) | 0; - lo = (lo + Math.imul(al7, bl2)) | 0; - mid = (mid + Math.imul(al7, bh2)) | 0; - mid = (mid + Math.imul(ah7, bl2)) | 0; - hi = (hi + Math.imul(ah7, bh2)) | 0; - lo = (lo + Math.imul(al6, bl3)) | 0; - mid = (mid + Math.imul(al6, bh3)) | 0; - mid = (mid + Math.imul(ah6, bl3)) | 0; - hi = (hi + Math.imul(ah6, bh3)) | 0; - lo = (lo + Math.imul(al5, bl4)) | 0; - mid = (mid + Math.imul(al5, bh4)) | 0; - mid = (mid + Math.imul(ah5, bl4)) | 0; - hi = (hi + Math.imul(ah5, bh4)) | 0; - lo = (lo + Math.imul(al4, bl5)) | 0; - mid = (mid + Math.imul(al4, bh5)) | 0; - mid = (mid + Math.imul(ah4, bl5)) | 0; - hi = (hi + Math.imul(ah4, bh5)) | 0; - lo = (lo + Math.imul(al3, bl6)) | 0; - mid = (mid + Math.imul(al3, bh6)) | 0; - mid = (mid + Math.imul(ah3, bl6)) | 0; - hi = (hi + Math.imul(ah3, bh6)) | 0; - lo = (lo + Math.imul(al2, bl7)) | 0; - mid = (mid + Math.imul(al2, bh7)) | 0; - mid = (mid + Math.imul(ah2, bl7)) | 0; - hi = (hi + Math.imul(ah2, bh7)) | 0; - lo = (lo + Math.imul(al1, bl8)) | 0; - mid = (mid + Math.imul(al1, bh8)) | 0; - mid = (mid + Math.imul(ah1, bl8)) | 0; - hi = (hi + Math.imul(ah1, bh8)) | 0; - lo = (lo + Math.imul(al0, bl9)) | 0; - mid = (mid + Math.imul(al0, bh9)) | 0; - mid = (mid + Math.imul(ah0, bl9)) | 0; - hi = (hi + Math.imul(ah0, bh9)) | 0; - var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0; - w9 &= 0x3ffffff; - /* k = 10 */ - lo = Math.imul(al9, bl1); - mid = Math.imul(al9, bh1); - mid = (mid + Math.imul(ah9, bl1)) | 0; - hi = Math.imul(ah9, bh1); - lo = (lo + Math.imul(al8, bl2)) | 0; - mid = (mid + Math.imul(al8, bh2)) | 0; - mid = (mid + Math.imul(ah8, bl2)) | 0; - hi = (hi + Math.imul(ah8, bh2)) | 0; - lo = (lo + Math.imul(al7, bl3)) | 0; - mid = (mid + Math.imul(al7, bh3)) | 0; - mid = (mid + Math.imul(ah7, bl3)) | 0; - hi = (hi + Math.imul(ah7, bh3)) | 0; - lo = (lo + Math.imul(al6, bl4)) | 0; - mid = (mid + Math.imul(al6, bh4)) | 0; - mid = (mid + Math.imul(ah6, bl4)) | 0; - hi = (hi + Math.imul(ah6, bh4)) | 0; - lo = (lo + Math.imul(al5, bl5)) | 0; - mid = (mid + Math.imul(al5, bh5)) | 0; - mid = (mid + Math.imul(ah5, bl5)) | 0; - hi = (hi + Math.imul(ah5, bh5)) | 0; - lo = (lo + Math.imul(al4, bl6)) | 0; - mid = (mid + Math.imul(al4, bh6)) | 0; - mid = (mid + Math.imul(ah4, bl6)) | 0; - hi = (hi + Math.imul(ah4, bh6)) | 0; - lo = (lo + Math.imul(al3, bl7)) | 0; - mid = (mid + Math.imul(al3, bh7)) | 0; - mid = (mid + Math.imul(ah3, bl7)) | 0; - hi = (hi + Math.imul(ah3, bh7)) | 0; - lo = (lo + Math.imul(al2, bl8)) | 0; - mid = (mid + Math.imul(al2, bh8)) | 0; - mid = (mid + Math.imul(ah2, bl8)) | 0; - hi = (hi + Math.imul(ah2, bh8)) | 0; - lo = (lo + Math.imul(al1, bl9)) | 0; - mid = (mid + Math.imul(al1, bh9)) | 0; - mid = (mid + Math.imul(ah1, bl9)) | 0; - hi = (hi + Math.imul(ah1, bh9)) | 0; - var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0; - w10 &= 0x3ffffff; - /* k = 11 */ - lo = Math.imul(al9, bl2); - mid = Math.imul(al9, bh2); - mid = (mid + Math.imul(ah9, bl2)) | 0; - hi = Math.imul(ah9, bh2); - lo = (lo + Math.imul(al8, bl3)) | 0; - mid = (mid + Math.imul(al8, bh3)) | 0; - mid = (mid + Math.imul(ah8, bl3)) | 0; - hi = (hi + Math.imul(ah8, bh3)) | 0; - lo = (lo + Math.imul(al7, bl4)) | 0; - mid = (mid + Math.imul(al7, bh4)) | 0; - mid = (mid + Math.imul(ah7, bl4)) | 0; - hi = (hi + Math.imul(ah7, bh4)) | 0; - lo = (lo + Math.imul(al6, bl5)) | 0; - mid = (mid + Math.imul(al6, bh5)) | 0; - mid = (mid + Math.imul(ah6, bl5)) | 0; - hi = (hi + Math.imul(ah6, bh5)) | 0; - lo = (lo + Math.imul(al5, bl6)) | 0; - mid = (mid + Math.imul(al5, bh6)) | 0; - mid = (mid + Math.imul(ah5, bl6)) | 0; - hi = (hi + Math.imul(ah5, bh6)) | 0; - lo = (lo + Math.imul(al4, bl7)) | 0; - mid = (mid + Math.imul(al4, bh7)) | 0; - mid = (mid + Math.imul(ah4, bl7)) | 0; - hi = (hi + Math.imul(ah4, bh7)) | 0; - lo = (lo + Math.imul(al3, bl8)) | 0; - mid = (mid + Math.imul(al3, bh8)) | 0; - mid = (mid + Math.imul(ah3, bl8)) | 0; - hi = (hi + Math.imul(ah3, bh8)) | 0; - lo = (lo + Math.imul(al2, bl9)) | 0; - mid = (mid + Math.imul(al2, bh9)) | 0; - mid = (mid + Math.imul(ah2, bl9)) | 0; - hi = (hi + Math.imul(ah2, bh9)) | 0; - var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0; - w11 &= 0x3ffffff; - /* k = 12 */ - lo = Math.imul(al9, bl3); - mid = Math.imul(al9, bh3); - mid = (mid + Math.imul(ah9, bl3)) | 0; - hi = Math.imul(ah9, bh3); - lo = (lo + Math.imul(al8, bl4)) | 0; - mid = (mid + Math.imul(al8, bh4)) | 0; - mid = (mid + Math.imul(ah8, bl4)) | 0; - hi = (hi + Math.imul(ah8, bh4)) | 0; - lo = (lo + Math.imul(al7, bl5)) | 0; - mid = (mid + Math.imul(al7, bh5)) | 0; - mid = (mid + Math.imul(ah7, bl5)) | 0; - hi = (hi + Math.imul(ah7, bh5)) | 0; - lo = (lo + Math.imul(al6, bl6)) | 0; - mid = (mid + Math.imul(al6, bh6)) | 0; - mid = (mid + Math.imul(ah6, bl6)) | 0; - hi = (hi + Math.imul(ah6, bh6)) | 0; - lo = (lo + Math.imul(al5, bl7)) | 0; - mid = (mid + Math.imul(al5, bh7)) | 0; - mid = (mid + Math.imul(ah5, bl7)) | 0; - hi = (hi + Math.imul(ah5, bh7)) | 0; - lo = (lo + Math.imul(al4, bl8)) | 0; - mid = (mid + Math.imul(al4, bh8)) | 0; - mid = (mid + Math.imul(ah4, bl8)) | 0; - hi = (hi + Math.imul(ah4, bh8)) | 0; - lo = (lo + Math.imul(al3, bl9)) | 0; - mid = (mid + Math.imul(al3, bh9)) | 0; - mid = (mid + Math.imul(ah3, bl9)) | 0; - hi = (hi + Math.imul(ah3, bh9)) | 0; - var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0; - w12 &= 0x3ffffff; - /* k = 13 */ - lo = Math.imul(al9, bl4); - mid = Math.imul(al9, bh4); - mid = (mid + Math.imul(ah9, bl4)) | 0; - hi = Math.imul(ah9, bh4); - lo = (lo + Math.imul(al8, bl5)) | 0; - mid = (mid + Math.imul(al8, bh5)) | 0; - mid = (mid + Math.imul(ah8, bl5)) | 0; - hi = (hi + Math.imul(ah8, bh5)) | 0; - lo = (lo + Math.imul(al7, bl6)) | 0; - mid = (mid + Math.imul(al7, bh6)) | 0; - mid = (mid + Math.imul(ah7, bl6)) | 0; - hi = (hi + Math.imul(ah7, bh6)) | 0; - lo = (lo + Math.imul(al6, bl7)) | 0; - mid = (mid + Math.imul(al6, bh7)) | 0; - mid = (mid + Math.imul(ah6, bl7)) | 0; - hi = (hi + Math.imul(ah6, bh7)) | 0; - lo = (lo + Math.imul(al5, bl8)) | 0; - mid = (mid + Math.imul(al5, bh8)) | 0; - mid = (mid + Math.imul(ah5, bl8)) | 0; - hi = (hi + Math.imul(ah5, bh8)) | 0; - lo = (lo + Math.imul(al4, bl9)) | 0; - mid = (mid + Math.imul(al4, bh9)) | 0; - mid = (mid + Math.imul(ah4, bl9)) | 0; - hi = (hi + Math.imul(ah4, bh9)) | 0; - var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0; - w13 &= 0x3ffffff; - /* k = 14 */ - lo = Math.imul(al9, bl5); - mid = Math.imul(al9, bh5); - mid = (mid + Math.imul(ah9, bl5)) | 0; - hi = Math.imul(ah9, bh5); - lo = (lo + Math.imul(al8, bl6)) | 0; - mid = (mid + Math.imul(al8, bh6)) | 0; - mid = (mid + Math.imul(ah8, bl6)) | 0; - hi = (hi + Math.imul(ah8, bh6)) | 0; - lo = (lo + Math.imul(al7, bl7)) | 0; - mid = (mid + Math.imul(al7, bh7)) | 0; - mid = (mid + Math.imul(ah7, bl7)) | 0; - hi = (hi + Math.imul(ah7, bh7)) | 0; - lo = (lo + Math.imul(al6, bl8)) | 0; - mid = (mid + Math.imul(al6, bh8)) | 0; - mid = (mid + Math.imul(ah6, bl8)) | 0; - hi = (hi + Math.imul(ah6, bh8)) | 0; - lo = (lo + Math.imul(al5, bl9)) | 0; - mid = (mid + Math.imul(al5, bh9)) | 0; - mid = (mid + Math.imul(ah5, bl9)) | 0; - hi = (hi + Math.imul(ah5, bh9)) | 0; - var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0; - w14 &= 0x3ffffff; - /* k = 15 */ - lo = Math.imul(al9, bl6); - mid = Math.imul(al9, bh6); - mid = (mid + Math.imul(ah9, bl6)) | 0; - hi = Math.imul(ah9, bh6); - lo = (lo + Math.imul(al8, bl7)) | 0; - mid = (mid + Math.imul(al8, bh7)) | 0; - mid = (mid + Math.imul(ah8, bl7)) | 0; - hi = (hi + Math.imul(ah8, bh7)) | 0; - lo = (lo + Math.imul(al7, bl8)) | 0; - mid = (mid + Math.imul(al7, bh8)) | 0; - mid = (mid + Math.imul(ah7, bl8)) | 0; - hi = (hi + Math.imul(ah7, bh8)) | 0; - lo = (lo + Math.imul(al6, bl9)) | 0; - mid = (mid + Math.imul(al6, bh9)) | 0; - mid = (mid + Math.imul(ah6, bl9)) | 0; - hi = (hi + Math.imul(ah6, bh9)) | 0; - var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0; - w15 &= 0x3ffffff; - /* k = 16 */ - lo = Math.imul(al9, bl7); - mid = Math.imul(al9, bh7); - mid = (mid + Math.imul(ah9, bl7)) | 0; - hi = Math.imul(ah9, bh7); - lo = (lo + Math.imul(al8, bl8)) | 0; - mid = (mid + Math.imul(al8, bh8)) | 0; - mid = (mid + Math.imul(ah8, bl8)) | 0; - hi = (hi + Math.imul(ah8, bh8)) | 0; - lo = (lo + Math.imul(al7, bl9)) | 0; - mid = (mid + Math.imul(al7, bh9)) | 0; - mid = (mid + Math.imul(ah7, bl9)) | 0; - hi = (hi + Math.imul(ah7, bh9)) | 0; - var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0; - w16 &= 0x3ffffff; - /* k = 17 */ - lo = Math.imul(al9, bl8); - mid = Math.imul(al9, bh8); - mid = (mid + Math.imul(ah9, bl8)) | 0; - hi = Math.imul(ah9, bh8); - lo = (lo + Math.imul(al8, bl9)) | 0; - mid = (mid + Math.imul(al8, bh9)) | 0; - mid = (mid + Math.imul(ah8, bl9)) | 0; - hi = (hi + Math.imul(ah8, bh9)) | 0; - var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0; - w17 &= 0x3ffffff; - /* k = 18 */ - lo = Math.imul(al9, bl9); - mid = Math.imul(al9, bh9); - mid = (mid + Math.imul(ah9, bl9)) | 0; - hi = Math.imul(ah9, bh9); - var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0; - w18 &= 0x3ffffff; - o[0] = w0; - o[1] = w1; - o[2] = w2; - o[3] = w3; - o[4] = w4; - o[5] = w5; - o[6] = w6; - o[7] = w7; - o[8] = w8; - o[9] = w9; - o[10] = w10; - o[11] = w11; - o[12] = w12; - o[13] = w13; - o[14] = w14; - o[15] = w15; - o[16] = w16; - o[17] = w17; - o[18] = w18; - if (c !== 0) { - o[19] = c; - out.length++; - } - return out; - }; - - // Polyfill comb - if (!Math.imul) { - comb10MulTo = smallMulTo; - } - - function bigMulTo (self, num, out) { - out.negative = num.negative ^ self.negative; - out.length = self.length + num.length; - - var carry = 0; - var hncarry = 0; - for (var k = 0; k < out.length - 1; k++) { - // Sum all words with the same `i + j = k` and accumulate `ncarry`, - // note that ncarry could be >= 0x3ffffff - var ncarry = hncarry; - hncarry = 0; - var rword = carry & 0x3ffffff; - var maxJ = Math.min(k, num.length - 1); - for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { - var i = k - j; - var a = self.words[i] | 0; - var b = num.words[j] | 0; - var r = a * b; - - var lo = r & 0x3ffffff; - ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0; - lo = (lo + rword) | 0; - rword = lo & 0x3ffffff; - ncarry = (ncarry + (lo >>> 26)) | 0; - - hncarry += ncarry >>> 26; - ncarry &= 0x3ffffff; - } - out.words[k] = rword; - carry = ncarry; - ncarry = hncarry; - } - if (carry !== 0) { - out.words[k] = carry; - } else { - out.length--; - } - - return out.strip(); - } - - function jumboMulTo (self, num, out) { - var fftm = new FFTM(); - return fftm.mulp(self, num, out); - } - - BN.prototype.mulTo = function mulTo (num, out) { - var res; - var len = this.length + num.length; - if (this.length === 10 && num.length === 10) { - res = comb10MulTo(this, num, out); - } else if (len < 63) { - res = smallMulTo(this, num, out); - } else if (len < 1024) { - res = bigMulTo(this, num, out); - } else { - res = jumboMulTo(this, num, out); - } - - return res; - }; - - // Cooley-Tukey algorithm for FFT - // slightly revisited to rely on looping instead of recursion - - function FFTM (x, y) { - this.x = x; - this.y = y; - } - - FFTM.prototype.makeRBT = function makeRBT (N) { - var t = new Array(N); - var l = BN.prototype._countBits(N) - 1; - for (var i = 0; i < N; i++) { - t[i] = this.revBin(i, l, N); - } - - return t; - }; - - // Returns binary-reversed representation of `x` - FFTM.prototype.revBin = function revBin (x, l, N) { - if (x === 0 || x === N - 1) return x; - - var rb = 0; - for (var i = 0; i < l; i++) { - rb |= (x & 1) << (l - i - 1); - x >>= 1; - } - - return rb; - }; - - // Performs "tweedling" phase, therefore 'emulating' - // behaviour of the recursive algorithm - FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) { - for (var i = 0; i < N; i++) { - rtws[i] = rws[rbt[i]]; - itws[i] = iws[rbt[i]]; - } - }; - - FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) { - this.permute(rbt, rws, iws, rtws, itws, N); - - for (var s = 1; s < N; s <<= 1) { - var l = s << 1; - - var rtwdf = Math.cos(2 * Math.PI / l); - var itwdf = Math.sin(2 * Math.PI / l); - - for (var p = 0; p < N; p += l) { - var rtwdf_ = rtwdf; - var itwdf_ = itwdf; - - for (var j = 0; j < s; j++) { - var re = rtws[p + j]; - var ie = itws[p + j]; - - var ro = rtws[p + j + s]; - var io = itws[p + j + s]; - - var rx = rtwdf_ * ro - itwdf_ * io; - - io = rtwdf_ * io + itwdf_ * ro; - ro = rx; - - rtws[p + j] = re + ro; - itws[p + j] = ie + io; - - rtws[p + j + s] = re - ro; - itws[p + j + s] = ie - io; - - /* jshint maxdepth : false */ - if (j !== l) { - rx = rtwdf * rtwdf_ - itwdf * itwdf_; - - itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_; - rtwdf_ = rx; - } - } - } - } - }; - - FFTM.prototype.guessLen13b = function guessLen13b (n, m) { - var N = Math.max(m, n) | 1; - var odd = N & 1; - var i = 0; - for (N = N / 2 | 0; N; N = N >>> 1) { - i++; - } - - return 1 << i + 1 + odd; - }; - - FFTM.prototype.conjugate = function conjugate (rws, iws, N) { - if (N <= 1) return; - - for (var i = 0; i < N / 2; i++) { - var t = rws[i]; - - rws[i] = rws[N - i - 1]; - rws[N - i - 1] = t; - - t = iws[i]; - - iws[i] = -iws[N - i - 1]; - iws[N - i - 1] = -t; - } - }; - - FFTM.prototype.normalize13b = function normalize13b (ws, N) { - var carry = 0; - for (var i = 0; i < N / 2; i++) { - var w = Math.round(ws[2 * i + 1] / N) * 0x2000 + - Math.round(ws[2 * i] / N) + - carry; - - ws[i] = w & 0x3ffffff; - - if (w < 0x4000000) { - carry = 0; - } else { - carry = w / 0x4000000 | 0; - } - } - - return ws; - }; - - FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) { - var carry = 0; - for (var i = 0; i < len; i++) { - carry = carry + (ws[i] | 0); - - rws[2 * i] = carry & 0x1fff; carry = carry >>> 13; - rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13; - } - - // Pad with zeroes - for (i = 2 * len; i < N; ++i) { - rws[i] = 0; - } - - assert(carry === 0); - assert((carry & ~0x1fff) === 0); - }; - - FFTM.prototype.stub = function stub (N) { - var ph = new Array(N); - for (var i = 0; i < N; i++) { - ph[i] = 0; - } - - return ph; - }; - - FFTM.prototype.mulp = function mulp (x, y, out) { - var N = 2 * this.guessLen13b(x.length, y.length); - - var rbt = this.makeRBT(N); - - var _ = this.stub(N); - - var rws = new Array(N); - var rwst = new Array(N); - var iwst = new Array(N); - - var nrws = new Array(N); - var nrwst = new Array(N); - var niwst = new Array(N); - - var rmws = out.words; - rmws.length = N; - - this.convert13b(x.words, x.length, rws, N); - this.convert13b(y.words, y.length, nrws, N); - - this.transform(rws, _, rwst, iwst, N, rbt); - this.transform(nrws, _, nrwst, niwst, N, rbt); - - for (var i = 0; i < N; i++) { - var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i]; - iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i]; - rwst[i] = rx; - } - - this.conjugate(rwst, iwst, N); - this.transform(rwst, iwst, rmws, _, N, rbt); - this.conjugate(rmws, _, N); - this.normalize13b(rmws, N); - - out.negative = x.negative ^ y.negative; - out.length = x.length + y.length; - return out.strip(); - }; - - // Multiply `this` by `num` - BN.prototype.mul = function mul (num) { - var out = new BN(null); - out.words = new Array(this.length + num.length); - return this.mulTo(num, out); - }; - - // Multiply employing FFT - BN.prototype.mulf = function mulf (num) { - var out = new BN(null); - out.words = new Array(this.length + num.length); - return jumboMulTo(this, num, out); - }; - - // In-place Multiplication - BN.prototype.imul = function imul (num) { - return this.clone().mulTo(num, this); - }; - - BN.prototype.imuln = function imuln (num) { - assert(typeof num === 'number'); - assert(num < 0x4000000); - - // Carry - var carry = 0; - for (var i = 0; i < this.length; i++) { - var w = (this.words[i] | 0) * num; - var lo = (w & 0x3ffffff) + (carry & 0x3ffffff); - carry >>= 26; - carry += (w / 0x4000000) | 0; - // NOTE: lo is 27bit maximum - carry += lo >>> 26; - this.words[i] = lo & 0x3ffffff; - } - - if (carry !== 0) { - this.words[i] = carry; - this.length++; - } - - return this; - }; - - BN.prototype.muln = function muln (num) { - return this.clone().imuln(num); - }; - - // `this` * `this` - BN.prototype.sqr = function sqr () { - return this.mul(this); - }; - - // `this` * `this` in-place - BN.prototype.isqr = function isqr () { - return this.imul(this.clone()); - }; - - // Math.pow(`this`, `num`) - BN.prototype.pow = function pow (num) { - var w = toBitArray(num); - if (w.length === 0) return new BN(1); - - // Skip leading zeroes - var res = this; - for (var i = 0; i < w.length; i++, res = res.sqr()) { - if (w[i] !== 0) break; - } - - if (++i < w.length) { - for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) { - if (w[i] === 0) continue; - - res = res.mul(q); - } - } - - return res; - }; - - // Shift-left in-place - BN.prototype.iushln = function iushln (bits) { - assert(typeof bits === 'number' && bits >= 0); - var r = bits % 26; - var s = (bits - r) / 26; - var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r); - var i; - - if (r !== 0) { - var carry = 0; - - for (i = 0; i < this.length; i++) { - var newCarry = this.words[i] & carryMask; - var c = ((this.words[i] | 0) - newCarry) << r; - this.words[i] = c | carry; - carry = newCarry >>> (26 - r); - } - - if (carry) { - this.words[i] = carry; - this.length++; - } - } - - if (s !== 0) { - for (i = this.length - 1; i >= 0; i--) { - this.words[i + s] = this.words[i]; - } - - for (i = 0; i < s; i++) { - this.words[i] = 0; - } - - this.length += s; - } - - return this.strip(); - }; - - BN.prototype.ishln = function ishln (bits) { - // TODO(indutny): implement me - assert(this.negative === 0); - return this.iushln(bits); - }; - - // Shift-right in-place - // NOTE: `hint` is a lowest bit before trailing zeroes - // NOTE: if `extended` is present - it will be filled with destroyed bits - BN.prototype.iushrn = function iushrn (bits, hint, extended) { - assert(typeof bits === 'number' && bits >= 0); - var h; - if (hint) { - h = (hint - (hint % 26)) / 26; - } else { - h = 0; - } - - var r = bits % 26; - var s = Math.min((bits - r) / 26, this.length); - var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); - var maskedWords = extended; - - h -= s; - h = Math.max(0, h); - - // Extended mode, copy masked part - if (maskedWords) { - for (var i = 0; i < s; i++) { - maskedWords.words[i] = this.words[i]; - } - maskedWords.length = s; - } - - if (s === 0) ; else if (this.length > s) { - this.length -= s; - for (i = 0; i < this.length; i++) { - this.words[i] = this.words[i + s]; - } - } else { - this.words[0] = 0; - this.length = 1; - } - - var carry = 0; - for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) { - var word = this.words[i] | 0; - this.words[i] = (carry << (26 - r)) | (word >>> r); - carry = word & mask; - } - - // Push carried bits as a mask - if (maskedWords && carry !== 0) { - maskedWords.words[maskedWords.length++] = carry; - } - - if (this.length === 0) { - this.words[0] = 0; - this.length = 1; - } - - return this.strip(); - }; - - BN.prototype.ishrn = function ishrn (bits, hint, extended) { - // TODO(indutny): implement me - assert(this.negative === 0); - return this.iushrn(bits, hint, extended); - }; - - // Shift-left - BN.prototype.shln = function shln (bits) { - return this.clone().ishln(bits); - }; - - BN.prototype.ushln = function ushln (bits) { - return this.clone().iushln(bits); - }; - - // Shift-right - BN.prototype.shrn = function shrn (bits) { - return this.clone().ishrn(bits); - }; - - BN.prototype.ushrn = function ushrn (bits) { - return this.clone().iushrn(bits); - }; - - // Test if n bit is set - BN.prototype.testn = function testn (bit) { - assert(typeof bit === 'number' && bit >= 0); - var r = bit % 26; - var s = (bit - r) / 26; - var q = 1 << r; - - // Fast case: bit is much higher than all existing words - if (this.length <= s) return false; - - // Check bit and return - var w = this.words[s]; - - return !!(w & q); - }; - - // Return only lowers bits of number (in-place) - BN.prototype.imaskn = function imaskn (bits) { - assert(typeof bits === 'number' && bits >= 0); - var r = bits % 26; - var s = (bits - r) / 26; - - assert(this.negative === 0, 'imaskn works only with positive numbers'); - - if (this.length <= s) { - return this; - } - - if (r !== 0) { - s++; - } - this.length = Math.min(s, this.length); - - if (r !== 0) { - var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); - this.words[this.length - 1] &= mask; - } - - return this.strip(); - }; - - // Return only lowers bits of number - BN.prototype.maskn = function maskn (bits) { - return this.clone().imaskn(bits); - }; - - // Add plain number `num` to `this` - BN.prototype.iaddn = function iaddn (num) { - assert(typeof num === 'number'); - assert(num < 0x4000000); - if (num < 0) return this.isubn(-num); - - // Possible sign change - if (this.negative !== 0) { - if (this.length === 1 && (this.words[0] | 0) < num) { - this.words[0] = num - (this.words[0] | 0); - this.negative = 0; - return this; - } - - this.negative = 0; - this.isubn(num); - this.negative = 1; - return this; - } - - // Add without checks - return this._iaddn(num); - }; - - BN.prototype._iaddn = function _iaddn (num) { - this.words[0] += num; - - // Carry - for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) { - this.words[i] -= 0x4000000; - if (i === this.length - 1) { - this.words[i + 1] = 1; - } else { - this.words[i + 1]++; - } - } - this.length = Math.max(this.length, i + 1); - - return this; - }; - - // Subtract plain number `num` from `this` - BN.prototype.isubn = function isubn (num) { - assert(typeof num === 'number'); - assert(num < 0x4000000); - if (num < 0) return this.iaddn(-num); - - if (this.negative !== 0) { - this.negative = 0; - this.iaddn(num); - this.negative = 1; - return this; - } - - this.words[0] -= num; - - if (this.length === 1 && this.words[0] < 0) { - this.words[0] = -this.words[0]; - this.negative = 1; - } else { - // Carry - for (var i = 0; i < this.length && this.words[i] < 0; i++) { - this.words[i] += 0x4000000; - this.words[i + 1] -= 1; - } - } - - return this.strip(); - }; - - BN.prototype.addn = function addn (num) { - return this.clone().iaddn(num); - }; - - BN.prototype.subn = function subn (num) { - return this.clone().isubn(num); - }; - - BN.prototype.iabs = function iabs () { - this.negative = 0; - - return this; - }; - - BN.prototype.abs = function abs () { - return this.clone().iabs(); - }; - - BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) { - var len = num.length + shift; - var i; - - this._expand(len); - - var w; - var carry = 0; - for (i = 0; i < num.length; i++) { - w = (this.words[i + shift] | 0) + carry; - var right = (num.words[i] | 0) * mul; - w -= right & 0x3ffffff; - carry = (w >> 26) - ((right / 0x4000000) | 0); - this.words[i + shift] = w & 0x3ffffff; - } - for (; i < this.length - shift; i++) { - w = (this.words[i + shift] | 0) + carry; - carry = w >> 26; - this.words[i + shift] = w & 0x3ffffff; - } - - if (carry === 0) return this.strip(); - - // Subtraction overflow - assert(carry === -1); - carry = 0; - for (i = 0; i < this.length; i++) { - w = -(this.words[i] | 0) + carry; - carry = w >> 26; - this.words[i] = w & 0x3ffffff; - } - this.negative = 1; - - return this.strip(); - }; - - BN.prototype._wordDiv = function _wordDiv (num, mode) { - var shift = this.length - num.length; - - var a = this.clone(); - var b = num; - - // Normalize - var bhi = b.words[b.length - 1] | 0; - var bhiBits = this._countBits(bhi); - shift = 26 - bhiBits; - if (shift !== 0) { - b = b.ushln(shift); - a.iushln(shift); - bhi = b.words[b.length - 1] | 0; - } - - // Initialize quotient - var m = a.length - b.length; - var q; - - if (mode !== 'mod') { - q = new BN(null); - q.length = m + 1; - q.words = new Array(q.length); - for (var i = 0; i < q.length; i++) { - q.words[i] = 0; - } - } - - var diff = a.clone()._ishlnsubmul(b, 1, m); - if (diff.negative === 0) { - a = diff; - if (q) { - q.words[m] = 1; - } - } - - for (var j = m - 1; j >= 0; j--) { - var qj = (a.words[b.length + j] | 0) * 0x4000000 + - (a.words[b.length + j - 1] | 0); - - // NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max - // (0x7ffffff) - qj = Math.min((qj / bhi) | 0, 0x3ffffff); - - a._ishlnsubmul(b, qj, j); - while (a.negative !== 0) { - qj--; - a.negative = 0; - a._ishlnsubmul(b, 1, j); - if (!a.isZero()) { - a.negative ^= 1; - } - } - if (q) { - q.words[j] = qj; - } - } - if (q) { - q.strip(); - } - a.strip(); - - // Denormalize - if (mode !== 'div' && shift !== 0) { - a.iushrn(shift); - } - - return { - div: q || null, - mod: a - }; - }; - - // NOTE: 1) `mode` can be set to `mod` to request mod only, - // to `div` to request div only, or be absent to - // request both div & mod - // 2) `positive` is true if unsigned mod is requested - BN.prototype.divmod = function divmod (num, mode, positive) { - assert(!num.isZero()); - - if (this.isZero()) { - return { - div: new BN(0), - mod: new BN(0) - }; - } - - var div, mod, res; - if (this.negative !== 0 && num.negative === 0) { - res = this.neg().divmod(num, mode); - - if (mode !== 'mod') { - div = res.div.neg(); - } - - if (mode !== 'div') { - mod = res.mod.neg(); - if (positive && mod.negative !== 0) { - mod.iadd(num); - } - } - - return { - div: div, - mod: mod - }; - } - - if (this.negative === 0 && num.negative !== 0) { - res = this.divmod(num.neg(), mode); - - if (mode !== 'mod') { - div = res.div.neg(); - } - - return { - div: div, - mod: res.mod - }; - } - - if ((this.negative & num.negative) !== 0) { - res = this.neg().divmod(num.neg(), mode); - - if (mode !== 'div') { - mod = res.mod.neg(); - if (positive && mod.negative !== 0) { - mod.isub(num); - } - } - - return { - div: res.div, - mod: mod - }; - } - - // Both numbers are positive at this point - - // Strip both numbers to approximate shift value - if (num.length > this.length || this.cmp(num) < 0) { - return { - div: new BN(0), - mod: this - }; - } - - // Very short reduction - if (num.length === 1) { - if (mode === 'div') { - return { - div: this.divn(num.words[0]), - mod: null - }; - } - - if (mode === 'mod') { - return { - div: null, - mod: new BN(this.modn(num.words[0])) - }; - } - - return { - div: this.divn(num.words[0]), - mod: new BN(this.modn(num.words[0])) - }; - } - - return this._wordDiv(num, mode); - }; - - // Find `this` / `num` - BN.prototype.div = function div (num) { - return this.divmod(num, 'div', false).div; - }; - - // Find `this` % `num` - BN.prototype.mod = function mod (num) { - return this.divmod(num, 'mod', false).mod; - }; - - BN.prototype.umod = function umod (num) { - return this.divmod(num, 'mod', true).mod; - }; - - // Find Round(`this` / `num`) - BN.prototype.divRound = function divRound (num) { - var dm = this.divmod(num); - - // Fast case - exact division - if (dm.mod.isZero()) return dm.div; - - var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod; - - var half = num.ushrn(1); - var r2 = num.andln(1); - var cmp = mod.cmp(half); - - // Round down - if (cmp < 0 || r2 === 1 && cmp === 0) return dm.div; - - // Round up - return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1); - }; - - BN.prototype.modn = function modn (num) { - assert(num <= 0x3ffffff); - var p = (1 << 26) % num; - - var acc = 0; - for (var i = this.length - 1; i >= 0; i--) { - acc = (p * acc + (this.words[i] | 0)) % num; - } - - return acc; - }; - - // In-place division by number - BN.prototype.idivn = function idivn (num) { - assert(num <= 0x3ffffff); - - var carry = 0; - for (var i = this.length - 1; i >= 0; i--) { - var w = (this.words[i] | 0) + carry * 0x4000000; - this.words[i] = (w / num) | 0; - carry = w % num; - } - - return this.strip(); - }; - - BN.prototype.divn = function divn (num) { - return this.clone().idivn(num); - }; - - BN.prototype.egcd = function egcd (p) { - assert(p.negative === 0); - assert(!p.isZero()); - - var x = this; - var y = p.clone(); - - if (x.negative !== 0) { - x = x.umod(p); - } else { - x = x.clone(); - } - - // A * x + B * y = x - var A = new BN(1); - var B = new BN(0); - - // C * x + D * y = y - var C = new BN(0); - var D = new BN(1); - - var g = 0; - - while (x.isEven() && y.isEven()) { - x.iushrn(1); - y.iushrn(1); - ++g; - } - - var yp = y.clone(); - var xp = x.clone(); - - while (!x.isZero()) { - for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1); - if (i > 0) { - x.iushrn(i); - while (i-- > 0) { - if (A.isOdd() || B.isOdd()) { - A.iadd(yp); - B.isub(xp); - } - - A.iushrn(1); - B.iushrn(1); - } - } - - for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); - if (j > 0) { - y.iushrn(j); - while (j-- > 0) { - if (C.isOdd() || D.isOdd()) { - C.iadd(yp); - D.isub(xp); - } - - C.iushrn(1); - D.iushrn(1); - } - } - - if (x.cmp(y) >= 0) { - x.isub(y); - A.isub(C); - B.isub(D); - } else { - y.isub(x); - C.isub(A); - D.isub(B); - } - } - - return { - a: C, - b: D, - gcd: y.iushln(g) - }; - }; - - // This is reduced incarnation of the binary EEA - // above, designated to invert members of the - // _prime_ fields F(p) at a maximal speed - BN.prototype._invmp = function _invmp (p) { - assert(p.negative === 0); - assert(!p.isZero()); - - var a = this; - var b = p.clone(); - - if (a.negative !== 0) { - a = a.umod(p); - } else { - a = a.clone(); - } - - var x1 = new BN(1); - var x2 = new BN(0); - - var delta = b.clone(); - - while (a.cmpn(1) > 0 && b.cmpn(1) > 0) { - for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1); - if (i > 0) { - a.iushrn(i); - while (i-- > 0) { - if (x1.isOdd()) { - x1.iadd(delta); - } - - x1.iushrn(1); - } - } - - for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); - if (j > 0) { - b.iushrn(j); - while (j-- > 0) { - if (x2.isOdd()) { - x2.iadd(delta); - } - - x2.iushrn(1); - } - } - - if (a.cmp(b) >= 0) { - a.isub(b); - x1.isub(x2); - } else { - b.isub(a); - x2.isub(x1); - } - } - - var res; - if (a.cmpn(1) === 0) { - res = x1; - } else { - res = x2; - } - - if (res.cmpn(0) < 0) { - res.iadd(p); - } - - return res; - }; - - BN.prototype.gcd = function gcd (num) { - if (this.isZero()) return num.abs(); - if (num.isZero()) return this.abs(); - - var a = this.clone(); - var b = num.clone(); - a.negative = 0; - b.negative = 0; - - // Remove common factor of two - for (var shift = 0; a.isEven() && b.isEven(); shift++) { - a.iushrn(1); - b.iushrn(1); - } - - do { - while (a.isEven()) { - a.iushrn(1); - } - while (b.isEven()) { - b.iushrn(1); - } - - var r = a.cmp(b); - if (r < 0) { - // Swap `a` and `b` to make `a` always bigger than `b` - var t = a; - a = b; - b = t; - } else if (r === 0 || b.cmpn(1) === 0) { - break; - } - - a.isub(b); - } while (true); - - return b.iushln(shift); - }; - - // Invert number in the field F(num) - BN.prototype.invm = function invm (num) { - return this.egcd(num).a.umod(num); - }; - - BN.prototype.isEven = function isEven () { - return (this.words[0] & 1) === 0; - }; - - BN.prototype.isOdd = function isOdd () { - return (this.words[0] & 1) === 1; - }; - - // And first word and num - BN.prototype.andln = function andln (num) { - return this.words[0] & num; - }; - - // Increment at the bit position in-line - BN.prototype.bincn = function bincn (bit) { - assert(typeof bit === 'number'); - var r = bit % 26; - var s = (bit - r) / 26; - var q = 1 << r; - - // Fast case: bit is much higher than all existing words - if (this.length <= s) { - this._expand(s + 1); - this.words[s] |= q; - return this; - } - - // Add bit and propagate, if needed - var carry = q; - for (var i = s; carry !== 0 && i < this.length; i++) { - var w = this.words[i] | 0; - w += carry; - carry = w >>> 26; - w &= 0x3ffffff; - this.words[i] = w; - } - if (carry !== 0) { - this.words[i] = carry; - this.length++; - } - return this; - }; - - BN.prototype.isZero = function isZero () { - return this.length === 1 && this.words[0] === 0; - }; - - BN.prototype.cmpn = function cmpn (num) { - var negative = num < 0; - - if (this.negative !== 0 && !negative) return -1; - if (this.negative === 0 && negative) return 1; - - this.strip(); - - var res; - if (this.length > 1) { - res = 1; - } else { - if (negative) { - num = -num; - } - - assert(num <= 0x3ffffff, 'Number is too big'); - - var w = this.words[0] | 0; - res = w === num ? 0 : w < num ? -1 : 1; - } - if (this.negative !== 0) return -res | 0; - return res; - }; - - // Compare two numbers and return: - // 1 - if `this` > `num` - // 0 - if `this` == `num` - // -1 - if `this` < `num` - BN.prototype.cmp = function cmp (num) { - if (this.negative !== 0 && num.negative === 0) return -1; - if (this.negative === 0 && num.negative !== 0) return 1; - - var res = this.ucmp(num); - if (this.negative !== 0) return -res | 0; - return res; - }; - - // Unsigned comparison - BN.prototype.ucmp = function ucmp (num) { - // At this point both numbers have the same sign - if (this.length > num.length) return 1; - if (this.length < num.length) return -1; - - var res = 0; - for (var i = this.length - 1; i >= 0; i--) { - var a = this.words[i] | 0; - var b = num.words[i] | 0; - - if (a === b) continue; - if (a < b) { - res = -1; - } else if (a > b) { - res = 1; - } - break; - } - return res; - }; - - BN.prototype.gtn = function gtn (num) { - return this.cmpn(num) === 1; - }; - - BN.prototype.gt = function gt (num) { - return this.cmp(num) === 1; - }; - - BN.prototype.gten = function gten (num) { - return this.cmpn(num) >= 0; - }; - - BN.prototype.gte = function gte (num) { - return this.cmp(num) >= 0; - }; - - BN.prototype.ltn = function ltn (num) { - return this.cmpn(num) === -1; - }; - - BN.prototype.lt = function lt (num) { - return this.cmp(num) === -1; - }; - - BN.prototype.lten = function lten (num) { - return this.cmpn(num) <= 0; - }; - - BN.prototype.lte = function lte (num) { - return this.cmp(num) <= 0; - }; - - BN.prototype.eqn = function eqn (num) { - return this.cmpn(num) === 0; - }; - - BN.prototype.eq = function eq (num) { - return this.cmp(num) === 0; - }; - - // - // A reduce context, could be using montgomery or something better, depending - // on the `m` itself. - // - BN.red = function red (num) { - return new Red(num); - }; - - BN.prototype.toRed = function toRed (ctx) { - assert(!this.red, 'Already a number in reduction context'); - assert(this.negative === 0, 'red works only with positives'); - return ctx.convertTo(this)._forceRed(ctx); - }; - - BN.prototype.fromRed = function fromRed () { - assert(this.red, 'fromRed works only with numbers in reduction context'); - return this.red.convertFrom(this); - }; - - BN.prototype._forceRed = function _forceRed (ctx) { - this.red = ctx; - return this; - }; - - BN.prototype.forceRed = function forceRed (ctx) { - assert(!this.red, 'Already a number in reduction context'); - return this._forceRed(ctx); - }; - - BN.prototype.redAdd = function redAdd (num) { - assert(this.red, 'redAdd works only with red numbers'); - return this.red.add(this, num); - }; - - BN.prototype.redIAdd = function redIAdd (num) { - assert(this.red, 'redIAdd works only with red numbers'); - return this.red.iadd(this, num); - }; - - BN.prototype.redSub = function redSub (num) { - assert(this.red, 'redSub works only with red numbers'); - return this.red.sub(this, num); - }; - - BN.prototype.redISub = function redISub (num) { - assert(this.red, 'redISub works only with red numbers'); - return this.red.isub(this, num); - }; - - BN.prototype.redShl = function redShl (num) { - assert(this.red, 'redShl works only with red numbers'); - return this.red.shl(this, num); - }; - - BN.prototype.redMul = function redMul (num) { - assert(this.red, 'redMul works only with red numbers'); - this.red._verify2(this, num); - return this.red.mul(this, num); - }; - - BN.prototype.redIMul = function redIMul (num) { - assert(this.red, 'redMul works only with red numbers'); - this.red._verify2(this, num); - return this.red.imul(this, num); - }; - - BN.prototype.redSqr = function redSqr () { - assert(this.red, 'redSqr works only with red numbers'); - this.red._verify1(this); - return this.red.sqr(this); - }; - - BN.prototype.redISqr = function redISqr () { - assert(this.red, 'redISqr works only with red numbers'); - this.red._verify1(this); - return this.red.isqr(this); - }; - - // Square root over p - BN.prototype.redSqrt = function redSqrt () { - assert(this.red, 'redSqrt works only with red numbers'); - this.red._verify1(this); - return this.red.sqrt(this); - }; - - BN.prototype.redInvm = function redInvm () { - assert(this.red, 'redInvm works only with red numbers'); - this.red._verify1(this); - return this.red.invm(this); - }; - - // Return negative clone of `this` % `red modulo` - BN.prototype.redNeg = function redNeg () { - assert(this.red, 'redNeg works only with red numbers'); - this.red._verify1(this); - return this.red.neg(this); - }; - - BN.prototype.redPow = function redPow (num) { - assert(this.red && !num.red, 'redPow(normalNum)'); - this.red._verify1(this); - return this.red.pow(this, num); - }; - - // Prime numbers with efficient reduction - var primes = { - k256: null, - p224: null, - p192: null, - p25519: null - }; - - // Pseudo-Mersenne prime - function MPrime (name, p) { - // P = 2 ^ N - K - this.name = name; - this.p = new BN(p, 16); - this.n = this.p.bitLength(); - this.k = new BN(1).iushln(this.n).isub(this.p); - - this.tmp = this._tmp(); - } - - MPrime.prototype._tmp = function _tmp () { - var tmp = new BN(null); - tmp.words = new Array(Math.ceil(this.n / 13)); - return tmp; - }; - - MPrime.prototype.ireduce = function ireduce (num) { - // Assumes that `num` is less than `P^2` - // num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P) - var r = num; - var rlen; - - do { - this.split(r, this.tmp); - r = this.imulK(r); - r = r.iadd(this.tmp); - rlen = r.bitLength(); - } while (rlen > this.n); - - var cmp = rlen < this.n ? -1 : r.ucmp(this.p); - if (cmp === 0) { - r.words[0] = 0; - r.length = 1; - } else if (cmp > 0) { - r.isub(this.p); - } else { - r.strip(); - } - - return r; - }; - - MPrime.prototype.split = function split (input, out) { - input.iushrn(this.n, 0, out); - }; - - MPrime.prototype.imulK = function imulK (num) { - return num.imul(this.k); - }; - - function K256 () { - MPrime.call( - this, - 'k256', - 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f'); - } - inherits(K256, MPrime); - - K256.prototype.split = function split (input, output) { - // 256 = 9 * 26 + 22 - var mask = 0x3fffff; - - var outLen = Math.min(input.length, 9); - for (var i = 0; i < outLen; i++) { - output.words[i] = input.words[i]; - } - output.length = outLen; - - if (input.length <= 9) { - input.words[0] = 0; - input.length = 1; - return; - } - - // Shift by 9 limbs - var prev = input.words[9]; - output.words[output.length++] = prev & mask; - - for (i = 10; i < input.length; i++) { - var next = input.words[i] | 0; - input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22); - prev = next; - } - prev >>>= 22; - input.words[i - 10] = prev; - if (prev === 0 && input.length > 10) { - input.length -= 10; - } else { - input.length -= 9; - } - }; - - K256.prototype.imulK = function imulK (num) { - // K = 0x1000003d1 = [ 0x40, 0x3d1 ] - num.words[num.length] = 0; - num.words[num.length + 1] = 0; - num.length += 2; - - // bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390 - var lo = 0; - for (var i = 0; i < num.length; i++) { - var w = num.words[i] | 0; - lo += w * 0x3d1; - num.words[i] = lo & 0x3ffffff; - lo = w * 0x40 + ((lo / 0x4000000) | 0); - } - - // Fast length reduction - if (num.words[num.length - 1] === 0) { - num.length--; - if (num.words[num.length - 1] === 0) { - num.length--; - } - } - return num; - }; - - function P224 () { - MPrime.call( - this, - 'p224', - 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001'); - } - inherits(P224, MPrime); - - function P192 () { - MPrime.call( - this, - 'p192', - 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff'); - } - inherits(P192, MPrime); - - function P25519 () { - // 2 ^ 255 - 19 - MPrime.call( - this, - '25519', - '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed'); - } - inherits(P25519, MPrime); - - P25519.prototype.imulK = function imulK (num) { - // K = 0x13 - var carry = 0; - for (var i = 0; i < num.length; i++) { - var hi = (num.words[i] | 0) * 0x13 + carry; - var lo = hi & 0x3ffffff; - hi >>>= 26; - - num.words[i] = lo; - carry = hi; - } - if (carry !== 0) { - num.words[num.length++] = carry; - } - return num; - }; - - // Exported mostly for testing purposes, use plain name instead - BN._prime = function prime (name) { - // Cached version of prime - if (primes[name]) return primes[name]; - - var prime; - if (name === 'k256') { - prime = new K256(); - } else if (name === 'p224') { - prime = new P224(); - } else if (name === 'p192') { - prime = new P192(); - } else if (name === 'p25519') { - prime = new P25519(); - } else { - throw new Error('Unknown prime ' + name); - } - primes[name] = prime; - - return prime; - }; - - // - // Base reduction engine - // - function Red (m) { - if (typeof m === 'string') { - var prime = BN._prime(m); - this.m = prime.p; - this.prime = prime; - } else { - assert(m.gtn(1), 'modulus must be greater than 1'); - this.m = m; - this.prime = null; - } - } - - Red.prototype._verify1 = function _verify1 (a) { - assert(a.negative === 0, 'red works only with positives'); - assert(a.red, 'red works only with red numbers'); - }; - - Red.prototype._verify2 = function _verify2 (a, b) { - assert((a.negative | b.negative) === 0, 'red works only with positives'); - assert(a.red && a.red === b.red, - 'red works only with red numbers'); - }; - - Red.prototype.imod = function imod (a) { - if (this.prime) return this.prime.ireduce(a)._forceRed(this); - return a.umod(this.m)._forceRed(this); - }; - - Red.prototype.neg = function neg (a) { - if (a.isZero()) { - return a.clone(); - } - - return this.m.sub(a)._forceRed(this); - }; - - Red.prototype.add = function add (a, b) { - this._verify2(a, b); - - var res = a.add(b); - if (res.cmp(this.m) >= 0) { - res.isub(this.m); - } - return res._forceRed(this); - }; - - Red.prototype.iadd = function iadd (a, b) { - this._verify2(a, b); - - var res = a.iadd(b); - if (res.cmp(this.m) >= 0) { - res.isub(this.m); - } - return res; - }; - - Red.prototype.sub = function sub (a, b) { - this._verify2(a, b); - - var res = a.sub(b); - if (res.cmpn(0) < 0) { - res.iadd(this.m); - } - return res._forceRed(this); - }; - - Red.prototype.isub = function isub (a, b) { - this._verify2(a, b); - - var res = a.isub(b); - if (res.cmpn(0) < 0) { - res.iadd(this.m); - } - return res; - }; - - Red.prototype.shl = function shl (a, num) { - this._verify1(a); - return this.imod(a.ushln(num)); - }; - - Red.prototype.imul = function imul (a, b) { - this._verify2(a, b); - return this.imod(a.imul(b)); - }; - - Red.prototype.mul = function mul (a, b) { - this._verify2(a, b); - return this.imod(a.mul(b)); - }; - - Red.prototype.isqr = function isqr (a) { - return this.imul(a, a.clone()); - }; - - Red.prototype.sqr = function sqr (a) { - return this.mul(a, a); - }; - - Red.prototype.sqrt = function sqrt (a) { - if (a.isZero()) return a.clone(); - - var mod3 = this.m.andln(3); - assert(mod3 % 2 === 1); - - // Fast case - if (mod3 === 3) { - var pow = this.m.add(new BN(1)).iushrn(2); - return this.pow(a, pow); - } - - // Tonelli-Shanks algorithm (Totally unoptimized and slow) - // - // Find Q and S, that Q * 2 ^ S = (P - 1) - var q = this.m.subn(1); - var s = 0; - while (!q.isZero() && q.andln(1) === 0) { - s++; - q.iushrn(1); - } - assert(!q.isZero()); - - var one = new BN(1).toRed(this); - var nOne = one.redNeg(); - - // Find quadratic non-residue - // NOTE: Max is such because of generalized Riemann hypothesis. - var lpow = this.m.subn(1).iushrn(1); - var z = this.m.bitLength(); - z = new BN(2 * z * z).toRed(this); - - while (this.pow(z, lpow).cmp(nOne) !== 0) { - z.redIAdd(nOne); - } - - var c = this.pow(z, q); - var r = this.pow(a, q.addn(1).iushrn(1)); - var t = this.pow(a, q); - var m = s; - while (t.cmp(one) !== 0) { - var tmp = t; - for (var i = 0; tmp.cmp(one) !== 0; i++) { - tmp = tmp.redSqr(); - } - assert(i < m); - var b = this.pow(c, new BN(1).iushln(m - i - 1)); - - r = r.redMul(b); - c = b.redSqr(); - t = t.redMul(c); - m = i; - } - - return r; - }; - - Red.prototype.invm = function invm (a) { - var inv = a._invmp(this.m); - if (inv.negative !== 0) { - inv.negative = 0; - return this.imod(inv).redNeg(); - } else { - return this.imod(inv); - } - }; - - Red.prototype.pow = function pow (a, num) { - if (num.isZero()) return new BN(1).toRed(this); - if (num.cmpn(1) === 0) return a.clone(); - - var windowSize = 4; - var wnd = new Array(1 << windowSize); - wnd[0] = new BN(1).toRed(this); - wnd[1] = a; - for (var i = 2; i < wnd.length; i++) { - wnd[i] = this.mul(wnd[i - 1], a); - } - - var res = wnd[0]; - var current = 0; - var currentLen = 0; - var start = num.bitLength() % 26; - if (start === 0) { - start = 26; - } - - for (i = num.length - 1; i >= 0; i--) { - var word = num.words[i]; - for (var j = start - 1; j >= 0; j--) { - var bit = (word >> j) & 1; - if (res !== wnd[0]) { - res = this.sqr(res); - } - - if (bit === 0 && current === 0) { - currentLen = 0; - continue; - } - - current <<= 1; - current |= bit; - currentLen++; - if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue; - - res = this.mul(res, wnd[current]); - currentLen = 0; - current = 0; - } - start = 26; - } - - return res; - }; - - Red.prototype.convertTo = function convertTo (num) { - var r = num.umod(this.m); - - return r === num ? r.clone() : r; - }; - - Red.prototype.convertFrom = function convertFrom (num) { - var res = num.clone(); - res.red = null; - return res; - }; - - // - // Montgomery method engine - // - - BN.mont = function mont (num) { - return new Mont(num); - }; - - function Mont (m) { - Red.call(this, m); - - this.shift = this.m.bitLength(); - if (this.shift % 26 !== 0) { - this.shift += 26 - (this.shift % 26); - } - - this.r = new BN(1).iushln(this.shift); - this.r2 = this.imod(this.r.sqr()); - this.rinv = this.r._invmp(this.m); - - this.minv = this.rinv.mul(this.r).isubn(1).div(this.m); - this.minv = this.minv.umod(this.r); - this.minv = this.r.sub(this.minv); - } - inherits(Mont, Red); - - Mont.prototype.convertTo = function convertTo (num) { - return this.imod(num.ushln(this.shift)); - }; - - Mont.prototype.convertFrom = function convertFrom (num) { - var r = this.imod(num.mul(this.rinv)); - r.red = null; - return r; - }; - - Mont.prototype.imul = function imul (a, b) { - if (a.isZero() || b.isZero()) { - a.words[0] = 0; - a.length = 1; - return a; - } - - var t = a.imul(b); - var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); - var u = t.isub(c).iushrn(this.shift); - var res = u; - - if (u.cmp(this.m) >= 0) { - res = u.isub(this.m); - } else if (u.cmpn(0) < 0) { - res = u.iadd(this.m); - } - - return res._forceRed(this); - }; - - Mont.prototype.mul = function mul (a, b) { - if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this); - - var t = a.mul(b); - var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); - var u = t.isub(c).iushrn(this.shift); - var res = u; - if (u.cmp(this.m) >= 0) { - res = u.isub(this.m); - } else if (u.cmpn(0) < 0) { - res = u.iadd(this.m); - } - - return res._forceRed(this); - }; - - Mont.prototype.invm = function invm (a) { - // (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R - var res = this.imod(a._invmp(this.m).mul(this.r2)); - return res._forceRed(this); - }; - })(module, commonjsGlobal); - }); - - var bn$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - 'default': bn, - __moduleExports: bn - }); - - /** - * @fileoverview - * BigInteger implementation of basic operations - * Wrapper of bn.js library (wwww.github.com/indutny/bn.js) - * @module biginteger/bn - * @private - */ - - /** - * @private - */ - class BigInteger$1 { - /** - * Get a BigInteger (input must be big endian for strings and arrays) - * @param {Number|String|Uint8Array} n - Value to convert - * @throws {Error} on undefined input - */ - constructor(n) { - if (n === undefined) { - throw new Error('Invalid BigInteger input'); - } - - this.value = new bn(n); - } - - clone() { - const clone = new BigInteger$1(null); - this.value.copy(clone.value); - return clone; - } - - /** - * BigInteger increment in place - */ - iinc() { - this.value.iadd(new bn(1)); - return this; - } - - /** - * BigInteger increment - * @returns {BigInteger} this + 1. - */ - inc() { - return this.clone().iinc(); - } - - /** - * BigInteger decrement in place - */ - idec() { - this.value.isub(new bn(1)); - return this; - } - - /** - * BigInteger decrement - * @returns {BigInteger} this - 1. - */ - dec() { - return this.clone().idec(); - } - - - /** - * BigInteger addition in place - * @param {BigInteger} x - Value to add - */ - iadd(x) { - this.value.iadd(x.value); - return this; - } - - /** - * BigInteger addition - * @param {BigInteger} x - Value to add - * @returns {BigInteger} this + x. - */ - add(x) { - return this.clone().iadd(x); - } - - /** - * BigInteger subtraction in place - * @param {BigInteger} x - Value to subtract - */ - isub(x) { - this.value.isub(x.value); - return this; - } - - /** - * BigInteger subtraction - * @param {BigInteger} x - Value to subtract - * @returns {BigInteger} this - x. - */ - sub(x) { - return this.clone().isub(x); - } - - /** - * BigInteger multiplication in place - * @param {BigInteger} x - Value to multiply - */ - imul(x) { - this.value.imul(x.value); - return this; - } - - /** - * BigInteger multiplication - * @param {BigInteger} x - Value to multiply - * @returns {BigInteger} this * x. - */ - mul(x) { - return this.clone().imul(x); - } - - /** - * Compute value modulo m, in place - * @param {BigInteger} m - Modulo - */ - imod(m) { - this.value = this.value.umod(m.value); - return this; - } - - /** - * Compute value modulo m - * @param {BigInteger} m - Modulo - * @returns {BigInteger} this mod m. - */ - mod(m) { - return this.clone().imod(m); - } - - /** - * Compute modular exponentiation - * Much faster than this.exp(e).mod(n) - * @param {BigInteger} e - Exponent - * @param {BigInteger} n - Modulo - * @returns {BigInteger} this ** e mod n. - */ - modExp(e, n) { - // We use either Montgomery or normal reduction context - // Montgomery requires coprime n and R (montogmery multiplier) - // bn.js picks R as power of 2, so n must be odd - const nred = n.isEven() ? bn.red(n.value) : bn.mont(n.value); - const x = this.clone(); - x.value = x.value.toRed(nred).redPow(e.value).fromRed(); - return x; - } - - /** - * Compute the inverse of this value modulo n - * Note: this and and n must be relatively prime - * @param {BigInteger} n - Modulo - * @returns {BigInteger} x such that this*x = 1 mod n - * @throws {Error} if the inverse does not exist - */ - modInv(n) { - // invm returns a wrong result if the inverse does not exist - if (!this.gcd(n).isOne()) { - throw new Error('Inverse does not exist'); - } - return new BigInteger$1(this.value.invm(n.value)); - } - - /** - * Compute greatest common divisor between this and n - * @param {BigInteger} n - Operand - * @returns {BigInteger} gcd - */ - gcd(n) { - return new BigInteger$1(this.value.gcd(n.value)); - } - - /** - * Shift this to the left by x, in place - * @param {BigInteger} x - Shift value - */ - ileftShift(x) { - this.value.ishln(x.value.toNumber()); - return this; - } - - /** - * Shift this to the left by x - * @param {BigInteger} x - Shift value - * @returns {BigInteger} this << x. - */ - leftShift(x) { - return this.clone().ileftShift(x); - } - - /** - * Shift this to the right by x, in place - * @param {BigInteger} x - Shift value - */ - irightShift(x) { - this.value.ishrn(x.value.toNumber()); - return this; - } - - /** - * Shift this to the right by x - * @param {BigInteger} x - Shift value - * @returns {BigInteger} this >> x. - */ - rightShift(x) { - return this.clone().irightShift(x); - } - - /** - * Whether this value is equal to x - * @param {BigInteger} x - * @returns {Boolean} - */ - equal(x) { - return this.value.eq(x.value); - } - - /** - * Whether this value is less than x - * @param {BigInteger} x - * @returns {Boolean} - */ - lt(x) { - return this.value.lt(x.value); - } - - /** - * Whether this value is less than or equal to x - * @param {BigInteger} x - * @returns {Boolean} - */ - lte(x) { - return this.value.lte(x.value); - } - - /** - * Whether this value is greater than x - * @param {BigInteger} x - * @returns {Boolean} - */ - gt(x) { - return this.value.gt(x.value); - } - - /** - * Whether this value is greater than or equal to x - * @param {BigInteger} x - * @returns {Boolean} - */ - gte(x) { - return this.value.gte(x.value); - } - - isZero() { - return this.value.isZero(); - } - - isOne() { - return this.value.eq(new bn(1)); - } - - isNegative() { - return this.value.isNeg(); - } - - isEven() { - return this.value.isEven(); - } - - abs() { - const res = this.clone(); - res.value = res.value.abs(); - return res; - } - - /** - * Get this value as a string - * @returns {String} this value. - */ - toString() { - return this.value.toString(); - } - - /** - * Get this value as an exact Number (max 53 bits) - * Fails if this value is too large - * @returns {Number} - */ - toNumber() { - return this.value.toNumber(); - } - - /** - * Get value of i-th bit - * @param {Number} i - Bit index - * @returns {Number} Bit value. - */ - getBit(i) { - return this.value.testn(i) ? 1 : 0; - } - - /** - * Compute bit length - * @returns {Number} Bit length. - */ - bitLength() { - return this.value.bitLength(); - } - - /** - * Compute byte length - * @returns {Number} Byte length. - */ - byteLength() { - return this.value.byteLength(); - } - - /** - * Get Uint8Array representation of this number - * @param {String} endian - Endianess of output array (defaults to 'be') - * @param {Number} length - Of output array - * @returns {Uint8Array} - */ - toUint8Array(endian = 'be', length) { - return this.value.toArrayLike(Uint8Array, endian, length); - } - } - - var bn_interface = /*#__PURE__*/Object.freeze({ - __proto__: null, - 'default': BigInteger$1 - }); - - var utils_1 = createCommonjsModule(function (module, exports) { - - var utils = exports; - - function toArray(msg, enc) { - if (Array.isArray(msg)) - return msg.slice(); - if (!msg) - return []; - var res = []; - if (typeof msg !== 'string') { - for (var i = 0; i < msg.length; i++) - res[i] = msg[i] | 0; - return res; - } - if (enc === 'hex') { - msg = msg.replace(/[^a-z0-9]+/ig, ''); - if (msg.length % 2 !== 0) - msg = '0' + msg; - for (var i = 0; i < msg.length; i += 2) - res.push(parseInt(msg[i] + msg[i + 1], 16)); - } else { - for (var i = 0; i < msg.length; i++) { - var c = msg.charCodeAt(i); - var hi = c >> 8; - var lo = c & 0xff; - if (hi) - res.push(hi, lo); - else - res.push(lo); - } - } - return res; - } - utils.toArray = toArray; - - function zero2(word) { - if (word.length === 1) - return '0' + word; - else - return word; - } - utils.zero2 = zero2; - - function toHex(msg) { - var res = ''; - for (var i = 0; i < msg.length; i++) - res += zero2(msg[i].toString(16)); - return res; - } - utils.toHex = toHex; - - utils.encode = function encode(arr, enc) { - if (enc === 'hex') - return toHex(arr); - else - return arr; - }; - }); - - var utils_1$1 = createCommonjsModule(function (module, exports) { - - var utils = exports; - - - - - utils.assert = minimalisticAssert; - utils.toArray = utils_1.toArray; - utils.zero2 = utils_1.zero2; - utils.toHex = utils_1.toHex; - utils.encode = utils_1.encode; - - // Represent num in a w-NAF form - function getNAF(num, w) { - var naf = []; - var ws = 1 << (w + 1); - var k = num.clone(); - while (k.cmpn(1) >= 0) { - var z; - if (k.isOdd()) { - var mod = k.andln(ws - 1); - if (mod > (ws >> 1) - 1) - z = (ws >> 1) - mod; - else - z = mod; - k.isubn(z); - } else { - z = 0; - } - naf.push(z); - - // Optimization, shift by word if possible - var shift = (k.cmpn(0) !== 0 && k.andln(ws - 1) === 0) ? (w + 1) : 1; - for (var i = 1; i < shift; i++) - naf.push(0); - k.iushrn(shift); - } - - return naf; - } - utils.getNAF = getNAF; - - // Represent k1, k2 in a Joint Sparse Form - function getJSF(k1, k2) { - var jsf = [ - [], - [] - ]; - - k1 = k1.clone(); - k2 = k2.clone(); - var d1 = 0; - var d2 = 0; - while (k1.cmpn(-d1) > 0 || k2.cmpn(-d2) > 0) { - - // First phase - var m14 = (k1.andln(3) + d1) & 3; - var m24 = (k2.andln(3) + d2) & 3; - if (m14 === 3) - m14 = -1; - if (m24 === 3) - m24 = -1; - var u1; - if ((m14 & 1) === 0) { - u1 = 0; - } else { - var m8 = (k1.andln(7) + d1) & 7; - if ((m8 === 3 || m8 === 5) && m24 === 2) - u1 = -m14; - else - u1 = m14; - } - jsf[0].push(u1); - - var u2; - if ((m24 & 1) === 0) { - u2 = 0; - } else { - var m8 = (k2.andln(7) + d2) & 7; - if ((m8 === 3 || m8 === 5) && m14 === 2) - u2 = -m24; - else - u2 = m24; - } - jsf[1].push(u2); - - // Second phase - if (2 * d1 === u1 + 1) - d1 = 1 - d1; - if (2 * d2 === u2 + 1) - d2 = 1 - d2; - k1.iushrn(1); - k2.iushrn(1); - } - - return jsf; - } - utils.getJSF = getJSF; - - function cachedProperty(obj, name, computer) { - var key = '_' + name; - obj.prototype[name] = function cachedProperty() { - return this[key] !== undefined ? this[key] : - this[key] = computer.call(this); - }; - } - utils.cachedProperty = cachedProperty; - - function parseBytes(bytes) { - return typeof bytes === 'string' ? utils.toArray(bytes, 'hex') : - bytes; - } - utils.parseBytes = parseBytes; - - function intFromLE(bytes) { - return new bn(bytes, 'hex', 'le'); - } - utils.intFromLE = intFromLE; - }); - - var r$1; - - var brorand = function rand(len) { - if (!r$1) - r$1 = new Rand(null); - - return r$1.generate(len); - }; - - function Rand(rand) { - this.rand = rand; - } - var Rand_1 = Rand; - - Rand.prototype.generate = function generate(len) { - return this._rand(len); - }; - - // Emulate crypto API using randy - Rand.prototype._rand = function _rand(n) { - if (this.rand.getBytes) - return this.rand.getBytes(n); - - var res = new Uint8Array(n); - for (var i = 0; i < res.length; i++) - res[i] = this.rand.getByte(); - return res; - }; - - if (typeof self === 'object') { - if (self.crypto && self.crypto.getRandomValues) { - // Modern browsers - Rand.prototype._rand = function _rand(n) { - var arr = new Uint8Array(n); - self.crypto.getRandomValues(arr); - return arr; - }; - } else if (self.msCrypto && self.msCrypto.getRandomValues) { - // IE - Rand.prototype._rand = function _rand(n) { - var arr = new Uint8Array(n); - self.msCrypto.getRandomValues(arr); - return arr; - }; - - // Safari's WebWorkers do not have `crypto` - } else if (typeof window === 'object') { - // Old junk - Rand.prototype._rand = function() { - throw new Error('Not implemented yet'); - }; - } - } else { - // Node.js or Web worker with no crypto support - try { - var crypto$2 = void('crypto'); - if (typeof crypto$2.randomBytes !== 'function') - throw new Error('Not supported'); - - Rand.prototype._rand = function _rand(n) { - return crypto$2.randomBytes(n); - }; - } catch (e) { - } - } - brorand.Rand = Rand_1; - - var getNAF = utils_1$1.getNAF; - var getJSF = utils_1$1.getJSF; - var assert$2 = utils_1$1.assert; - - function BaseCurve(type, conf) { - this.type = type; - this.p = new bn(conf.p, 16); - - // Use Montgomery, when there is no fast reduction for the prime - this.red = conf.prime ? bn.red(conf.prime) : bn.mont(this.p); - - // Useful for many curves - this.zero = new bn(0).toRed(this.red); - this.one = new bn(1).toRed(this.red); - this.two = new bn(2).toRed(this.red); - - // Curve configuration, optional - this.n = conf.n && new bn(conf.n, 16); - this.g = conf.g && this.pointFromJSON(conf.g, conf.gRed); - - // Temporary arrays - this._wnafT1 = new Array(4); - this._wnafT2 = new Array(4); - this._wnafT3 = new Array(4); - this._wnafT4 = new Array(4); - - // Generalized Greg Maxwell's trick - var adjustCount = this.n && this.p.div(this.n); - if (!adjustCount || adjustCount.cmpn(100) > 0) { - this.redN = null; - } else { - this._maxwellTrick = true; - this.redN = this.n.toRed(this.red); - } - } - var base = BaseCurve; - - BaseCurve.prototype.point = function point() { - throw new Error('Not implemented'); - }; - - BaseCurve.prototype.validate = function validate() { - throw new Error('Not implemented'); - }; - - BaseCurve.prototype._fixedNafMul = function _fixedNafMul(p, k) { - assert$2(p.precomputed); - var doubles = p._getDoubles(); - - var naf = getNAF(k, 1); - var I = (1 << (doubles.step + 1)) - (doubles.step % 2 === 0 ? 2 : 1); - I /= 3; - - // Translate into more windowed form - var repr = []; - for (var j = 0; j < naf.length; j += doubles.step) { - var nafW = 0; - for (var k = j + doubles.step - 1; k >= j; k--) - nafW = (nafW << 1) + naf[k]; - repr.push(nafW); - } - - var a = this.jpoint(null, null, null); - var b = this.jpoint(null, null, null); - for (var i = I; i > 0; i--) { - for (var j = 0; j < repr.length; j++) { - var nafW = repr[j]; - if (nafW === i) - b = b.mixedAdd(doubles.points[j]); - else if (nafW === -i) - b = b.mixedAdd(doubles.points[j].neg()); - } - a = a.add(b); - } - return a.toP(); - }; - - BaseCurve.prototype._wnafMul = function _wnafMul(p, k) { - var w = 4; - - // Precompute window - var nafPoints = p._getNAFPoints(w); - w = nafPoints.wnd; - var wnd = nafPoints.points; - - // Get NAF form - var naf = getNAF(k, w); - - // Add `this`*(N+1) for every w-NAF index - var acc = this.jpoint(null, null, null); - for (var i = naf.length - 1; i >= 0; i--) { - // Count zeroes - for (var k = 0; i >= 0 && naf[i] === 0; i--) - k++; - if (i >= 0) - k++; - acc = acc.dblp(k); - - if (i < 0) - break; - var z = naf[i]; - assert$2(z !== 0); - if (p.type === 'affine') { - // J +- P - if (z > 0) - acc = acc.mixedAdd(wnd[(z - 1) >> 1]); - else - acc = acc.mixedAdd(wnd[(-z - 1) >> 1].neg()); - } else { - // J +- J - if (z > 0) - acc = acc.add(wnd[(z - 1) >> 1]); - else - acc = acc.add(wnd[(-z - 1) >> 1].neg()); - } - } - return p.type === 'affine' ? acc.toP() : acc; - }; - - BaseCurve.prototype._wnafMulAdd = function _wnafMulAdd(defW, - points, - coeffs, - len, - jacobianResult) { - var wndWidth = this._wnafT1; - var wnd = this._wnafT2; - var naf = this._wnafT3; - - // Fill all arrays - var max = 0; - for (var i = 0; i < len; i++) { - var p = points[i]; - var nafPoints = p._getNAFPoints(defW); - wndWidth[i] = nafPoints.wnd; - wnd[i] = nafPoints.points; - } - - // Comb small window NAFs - for (var i = len - 1; i >= 1; i -= 2) { - var a = i - 1; - var b = i; - if (wndWidth[a] !== 1 || wndWidth[b] !== 1) { - naf[a] = getNAF(coeffs[a], wndWidth[a]); - naf[b] = getNAF(coeffs[b], wndWidth[b]); - max = Math.max(naf[a].length, max); - max = Math.max(naf[b].length, max); - continue; - } - - var comb = [ - points[a], /* 1 */ - null, /* 3 */ - null, /* 5 */ - points[b] /* 7 */ - ]; - - // Try to avoid Projective points, if possible - if (points[a].y.cmp(points[b].y) === 0) { - comb[1] = points[a].add(points[b]); - comb[2] = points[a].toJ().mixedAdd(points[b].neg()); - } else if (points[a].y.cmp(points[b].y.redNeg()) === 0) { - comb[1] = points[a].toJ().mixedAdd(points[b]); - comb[2] = points[a].add(points[b].neg()); - } else { - comb[1] = points[a].toJ().mixedAdd(points[b]); - comb[2] = points[a].toJ().mixedAdd(points[b].neg()); - } - - var index = [ - -3, /* -1 -1 */ - -1, /* -1 0 */ - -5, /* -1 1 */ - -7, /* 0 -1 */ - 0, /* 0 0 */ - 7, /* 0 1 */ - 5, /* 1 -1 */ - 1, /* 1 0 */ - 3 /* 1 1 */ - ]; - - var jsf = getJSF(coeffs[a], coeffs[b]); - max = Math.max(jsf[0].length, max); - naf[a] = new Array(max); - naf[b] = new Array(max); - for (var j = 0; j < max; j++) { - var ja = jsf[0][j] | 0; - var jb = jsf[1][j] | 0; - - naf[a][j] = index[(ja + 1) * 3 + (jb + 1)]; - naf[b][j] = 0; - wnd[a] = comb; - } - } - - var acc = this.jpoint(null, null, null); - var tmp = this._wnafT4; - for (var i = max; i >= 0; i--) { - var k = 0; - - while (i >= 0) { - var zero = true; - for (var j = 0; j < len; j++) { - tmp[j] = naf[j][i] | 0; - if (tmp[j] !== 0) - zero = false; - } - if (!zero) - break; - k++; - i--; - } - if (i >= 0) - k++; - acc = acc.dblp(k); - if (i < 0) - break; - - for (var j = 0; j < len; j++) { - var z = tmp[j]; - var p; - if (z === 0) - continue; - else if (z > 0) - p = wnd[j][(z - 1) >> 1]; - else if (z < 0) - p = wnd[j][(-z - 1) >> 1].neg(); - - if (p.type === 'affine') - acc = acc.mixedAdd(p); - else - acc = acc.add(p); - } - } - // Zeroify references - for (var i = 0; i < len; i++) - wnd[i] = null; - - if (jacobianResult) - return acc; - else - return acc.toP(); - }; - - function BasePoint(curve, type) { - this.curve = curve; - this.type = type; - this.precomputed = null; - } - BaseCurve.BasePoint = BasePoint; - - BasePoint.prototype.eq = function eq(/*other*/) { - throw new Error('Not implemented'); - }; - - BasePoint.prototype.validate = function validate() { - return this.curve.validate(this); - }; - - BaseCurve.prototype.decodePoint = function decodePoint(bytes, enc) { - bytes = utils_1$1.toArray(bytes, enc); - - var len = this.p.byteLength(); - - // uncompressed, hybrid-odd, hybrid-even - if ((bytes[0] === 0x04 || bytes[0] === 0x06 || bytes[0] === 0x07) && - bytes.length - 1 === 2 * len) { - if (bytes[0] === 0x06) - assert$2(bytes[bytes.length - 1] % 2 === 0); - else if (bytes[0] === 0x07) - assert$2(bytes[bytes.length - 1] % 2 === 1); - - var res = this.point(bytes.slice(1, 1 + len), - bytes.slice(1 + len, 1 + 2 * len)); - - return res; - } else if ((bytes[0] === 0x02 || bytes[0] === 0x03) && - bytes.length - 1 === len) { - return this.pointFromX(bytes.slice(1, 1 + len), bytes[0] === 0x03); - } - throw new Error('Unknown point format'); - }; - - BasePoint.prototype.encodeCompressed = function encodeCompressed(enc) { - return this.encode(enc, true); - }; - - BasePoint.prototype._encode = function _encode(compact) { - var len = this.curve.p.byteLength(); - var x = this.getX().toArray('be', len); - - if (compact) - return [ this.getY().isEven() ? 0x02 : 0x03 ].concat(x); - - return [ 0x04 ].concat(x, this.getY().toArray('be', len)) ; - }; - - BasePoint.prototype.encode = function encode(enc, compact) { - return utils_1$1.encode(this._encode(compact), enc); - }; - - BasePoint.prototype.precompute = function precompute(power) { - if (this.precomputed) - return this; - - var precomputed = { - doubles: null, - naf: null, - beta: null - }; - precomputed.naf = this._getNAFPoints(8); - precomputed.doubles = this._getDoubles(4, power); - precomputed.beta = this._getBeta(); - this.precomputed = precomputed; - - return this; - }; - - BasePoint.prototype._hasDoubles = function _hasDoubles(k) { - if (!this.precomputed) - return false; - - var doubles = this.precomputed.doubles; - if (!doubles) - return false; - - return doubles.points.length >= Math.ceil((k.bitLength() + 1) / doubles.step); - }; - - BasePoint.prototype._getDoubles = function _getDoubles(step, power) { - if (this.precomputed && this.precomputed.doubles) - return this.precomputed.doubles; - - var doubles = [ this ]; - var acc = this; - for (var i = 0; i < power; i += step) { - for (var j = 0; j < step; j++) - acc = acc.dbl(); - doubles.push(acc); - } - return { - step: step, - points: doubles - }; - }; - - BasePoint.prototype._getNAFPoints = function _getNAFPoints(wnd) { - if (this.precomputed && this.precomputed.naf) - return this.precomputed.naf; - - var res = [ this ]; - var max = (1 << wnd) - 1; - var dbl = max === 1 ? null : this.dbl(); - for (var i = 1; i < max; i++) - res[i] = res[i - 1].add(dbl); - return { - wnd: wnd, - points: res - }; - }; - - BasePoint.prototype._getBeta = function _getBeta() { - return null; - }; - - BasePoint.prototype.dblp = function dblp(k) { - var r = this; - for (var i = 0; i < k; i++) - r = r.dbl(); - return r; - }; - - var assert$3 = utils_1$1.assert; - - function ShortCurve(conf) { - base.call(this, 'short', conf); - - this.a = new bn(conf.a, 16).toRed(this.red); - this.b = new bn(conf.b, 16).toRed(this.red); - this.tinv = this.two.redInvm(); - - this.zeroA = this.a.fromRed().cmpn(0) === 0; - this.threeA = this.a.fromRed().sub(this.p).cmpn(-3) === 0; - - // If the curve is endomorphic, precalculate beta and lambda - this.endo = this._getEndomorphism(conf); - this._endoWnafT1 = new Array(4); - this._endoWnafT2 = new Array(4); - } - inherits_browser(ShortCurve, base); - var short_1 = ShortCurve; - - ShortCurve.prototype._getEndomorphism = function _getEndomorphism(conf) { - // No efficient endomorphism - if (!this.zeroA || !this.g || !this.n || this.p.modn(3) !== 1) - return; - - // Compute beta and lambda, that lambda * P = (beta * Px; Py) - var beta; - var lambda; - if (conf.beta) { - beta = new bn(conf.beta, 16).toRed(this.red); - } else { - var betas = this._getEndoRoots(this.p); - // Choose the smallest beta - beta = betas[0].cmp(betas[1]) < 0 ? betas[0] : betas[1]; - beta = beta.toRed(this.red); - } - if (conf.lambda) { - lambda = new bn(conf.lambda, 16); - } else { - // Choose the lambda that is matching selected beta - var lambdas = this._getEndoRoots(this.n); - if (this.g.mul(lambdas[0]).x.cmp(this.g.x.redMul(beta)) === 0) { - lambda = lambdas[0]; - } else { - lambda = lambdas[1]; - assert$3(this.g.mul(lambda).x.cmp(this.g.x.redMul(beta)) === 0); - } - } - - // Get basis vectors, used for balanced length-two representation - var basis; - if (conf.basis) { - basis = conf.basis.map(function(vec) { - return { - a: new bn(vec.a, 16), - b: new bn(vec.b, 16) - }; - }); - } else { - basis = this._getEndoBasis(lambda); - } - - return { - beta: beta, - lambda: lambda, - basis: basis - }; - }; - - ShortCurve.prototype._getEndoRoots = function _getEndoRoots(num) { - // Find roots of for x^2 + x + 1 in F - // Root = (-1 +- Sqrt(-3)) / 2 - // - var red = num === this.p ? this.red : bn.mont(num); - var tinv = new bn(2).toRed(red).redInvm(); - var ntinv = tinv.redNeg(); - - var s = new bn(3).toRed(red).redNeg().redSqrt().redMul(tinv); - - var l1 = ntinv.redAdd(s).fromRed(); - var l2 = ntinv.redSub(s).fromRed(); - return [ l1, l2 ]; - }; - - ShortCurve.prototype._getEndoBasis = function _getEndoBasis(lambda) { - // aprxSqrt >= sqrt(this.n) - var aprxSqrt = this.n.ushrn(Math.floor(this.n.bitLength() / 2)); - - // 3.74 - // Run EGCD, until r(L + 1) < aprxSqrt - var u = lambda; - var v = this.n.clone(); - var x1 = new bn(1); - var y1 = new bn(0); - var x2 = new bn(0); - var y2 = new bn(1); - - // NOTE: all vectors are roots of: a + b * lambda = 0 (mod n) - var a0; - var b0; - // First vector - var a1; - var b1; - // Second vector - var a2; - var b2; - - var prevR; - var i = 0; - var r; - var x; - while (u.cmpn(0) !== 0) { - var q = v.div(u); - r = v.sub(q.mul(u)); - x = x2.sub(q.mul(x1)); - var y = y2.sub(q.mul(y1)); - - if (!a1 && r.cmp(aprxSqrt) < 0) { - a0 = prevR.neg(); - b0 = x1; - a1 = r.neg(); - b1 = x; - } else if (a1 && ++i === 2) { - break; - } - prevR = r; - - v = u; - u = r; - x2 = x1; - x1 = x; - y2 = y1; - y1 = y; - } - a2 = r.neg(); - b2 = x; - - var len1 = a1.sqr().add(b1.sqr()); - var len2 = a2.sqr().add(b2.sqr()); - if (len2.cmp(len1) >= 0) { - a2 = a0; - b2 = b0; - } - - // Normalize signs - if (a1.negative) { - a1 = a1.neg(); - b1 = b1.neg(); - } - if (a2.negative) { - a2 = a2.neg(); - b2 = b2.neg(); - } - - return [ - { a: a1, b: b1 }, - { a: a2, b: b2 } - ]; - }; - - ShortCurve.prototype._endoSplit = function _endoSplit(k) { - var basis = this.endo.basis; - var v1 = basis[0]; - var v2 = basis[1]; - - var c1 = v2.b.mul(k).divRound(this.n); - var c2 = v1.b.neg().mul(k).divRound(this.n); - - var p1 = c1.mul(v1.a); - var p2 = c2.mul(v2.a); - var q1 = c1.mul(v1.b); - var q2 = c2.mul(v2.b); - - // Calculate answer - var k1 = k.sub(p1).sub(p2); - var k2 = q1.add(q2).neg(); - return { k1: k1, k2: k2 }; - }; - - ShortCurve.prototype.pointFromX = function pointFromX(x, odd) { - x = new bn(x, 16); - if (!x.red) - x = x.toRed(this.red); - - var y2 = x.redSqr().redMul(x).redIAdd(x.redMul(this.a)).redIAdd(this.b); - var y = y2.redSqrt(); - if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) - throw new Error('invalid point'); - - // XXX Is there any way to tell if the number is odd without converting it - // to non-red form? - var isOdd = y.fromRed().isOdd(); - if (odd && !isOdd || !odd && isOdd) - y = y.redNeg(); - - return this.point(x, y); - }; - - ShortCurve.prototype.validate = function validate(point) { - if (point.inf) - return true; - - var x = point.x; - var y = point.y; - - var ax = this.a.redMul(x); - var rhs = x.redSqr().redMul(x).redIAdd(ax).redIAdd(this.b); - return y.redSqr().redISub(rhs).cmpn(0) === 0; - }; - - ShortCurve.prototype._endoWnafMulAdd = - function _endoWnafMulAdd(points, coeffs, jacobianResult) { - var npoints = this._endoWnafT1; - var ncoeffs = this._endoWnafT2; - for (var i = 0; i < points.length; i++) { - var split = this._endoSplit(coeffs[i]); - var p = points[i]; - var beta = p._getBeta(); - - if (split.k1.negative) { - split.k1.ineg(); - p = p.neg(true); - } - if (split.k2.negative) { - split.k2.ineg(); - beta = beta.neg(true); - } - - npoints[i * 2] = p; - npoints[i * 2 + 1] = beta; - ncoeffs[i * 2] = split.k1; - ncoeffs[i * 2 + 1] = split.k2; - } - var res = this._wnafMulAdd(1, npoints, ncoeffs, i * 2, jacobianResult); - - // Clean-up references to points and coefficients - for (var j = 0; j < i * 2; j++) { - npoints[j] = null; - ncoeffs[j] = null; - } - return res; - }; - - function Point(curve, x, y, isRed) { - base.BasePoint.call(this, curve, 'affine'); - if (x === null && y === null) { - this.x = null; - this.y = null; - this.inf = true; - } else { - this.x = new bn(x, 16); - this.y = new bn(y, 16); - // Force redgomery representation when loading from JSON - if (isRed) { - this.x.forceRed(this.curve.red); - this.y.forceRed(this.curve.red); - } - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.y.red) - this.y = this.y.toRed(this.curve.red); - this.inf = false; - } - } - inherits_browser(Point, base.BasePoint); - - ShortCurve.prototype.point = function point(x, y, isRed) { - return new Point(this, x, y, isRed); - }; - - ShortCurve.prototype.pointFromJSON = function pointFromJSON(obj, red) { - return Point.fromJSON(this, obj, red); - }; - - Point.prototype._getBeta = function _getBeta() { - if (!this.curve.endo) - return; - - var pre = this.precomputed; - if (pre && pre.beta) - return pre.beta; - - var beta = this.curve.point(this.x.redMul(this.curve.endo.beta), this.y); - if (pre) { - var curve = this.curve; - var endoMul = function(p) { - return curve.point(p.x.redMul(curve.endo.beta), p.y); - }; - pre.beta = beta; - beta.precomputed = { - beta: null, - naf: pre.naf && { - wnd: pre.naf.wnd, - points: pre.naf.points.map(endoMul) - }, - doubles: pre.doubles && { - step: pre.doubles.step, - points: pre.doubles.points.map(endoMul) - } - }; - } - return beta; - }; - - Point.prototype.toJSON = function toJSON() { - if (!this.precomputed) - return [ this.x, this.y ]; - - return [ this.x, this.y, this.precomputed && { - doubles: this.precomputed.doubles && { - step: this.precomputed.doubles.step, - points: this.precomputed.doubles.points.slice(1) - }, - naf: this.precomputed.naf && { - wnd: this.precomputed.naf.wnd, - points: this.precomputed.naf.points.slice(1) - } - } ]; - }; - - Point.fromJSON = function fromJSON(curve, obj, red) { - if (typeof obj === 'string') - obj = JSON.parse(obj); - var res = curve.point(obj[0], obj[1], red); - if (!obj[2]) - return res; - - function obj2point(obj) { - return curve.point(obj[0], obj[1], red); - } - - var pre = obj[2]; - res.precomputed = { - beta: null, - doubles: pre.doubles && { - step: pre.doubles.step, - points: [ res ].concat(pre.doubles.points.map(obj2point)) - }, - naf: pre.naf && { - wnd: pre.naf.wnd, - points: [ res ].concat(pre.naf.points.map(obj2point)) - } - }; - return res; - }; - - Point.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; - }; - - Point.prototype.isInfinity = function isInfinity() { - return this.inf; - }; - - Point.prototype.add = function add(p) { - // O + P = P - if (this.inf) - return p; - - // P + O = P - if (p.inf) - return this; - - // P + P = 2P - if (this.eq(p)) - return this.dbl(); - - // P + (-P) = O - if (this.neg().eq(p)) - return this.curve.point(null, null); - - // P + Q = O - if (this.x.cmp(p.x) === 0) - return this.curve.point(null, null); - - var c = this.y.redSub(p.y); - if (c.cmpn(0) !== 0) - c = c.redMul(this.x.redSub(p.x).redInvm()); - var nx = c.redSqr().redISub(this.x).redISub(p.x); - var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); - return this.curve.point(nx, ny); - }; - - Point.prototype.dbl = function dbl() { - if (this.inf) - return this; - - // 2P = O - var ys1 = this.y.redAdd(this.y); - if (ys1.cmpn(0) === 0) - return this.curve.point(null, null); - - var a = this.curve.a; - - var x2 = this.x.redSqr(); - var dyinv = ys1.redInvm(); - var c = x2.redAdd(x2).redIAdd(x2).redIAdd(a).redMul(dyinv); - - var nx = c.redSqr().redISub(this.x.redAdd(this.x)); - var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); - return this.curve.point(nx, ny); - }; - - Point.prototype.getX = function getX() { - return this.x.fromRed(); - }; - - Point.prototype.getY = function getY() { - return this.y.fromRed(); - }; - - Point.prototype.mul = function mul(k) { - k = new bn(k, 16); - if (this.isInfinity()) - return this; - else if (this._hasDoubles(k)) - return this.curve._fixedNafMul(this, k); - else if (this.curve.endo) - return this.curve._endoWnafMulAdd([ this ], [ k ]); - else - return this.curve._wnafMul(this, k); - }; - - Point.prototype.mulAdd = function mulAdd(k1, p2, k2) { - var points = [ this, p2 ]; - var coeffs = [ k1, k2 ]; - if (this.curve.endo) - return this.curve._endoWnafMulAdd(points, coeffs); - else - return this.curve._wnafMulAdd(1, points, coeffs, 2); - }; - - Point.prototype.jmulAdd = function jmulAdd(k1, p2, k2) { - var points = [ this, p2 ]; - var coeffs = [ k1, k2 ]; - if (this.curve.endo) - return this.curve._endoWnafMulAdd(points, coeffs, true); - else - return this.curve._wnafMulAdd(1, points, coeffs, 2, true); - }; - - Point.prototype.eq = function eq(p) { - return this === p || - this.inf === p.inf && - (this.inf || this.x.cmp(p.x) === 0 && this.y.cmp(p.y) === 0); - }; - - Point.prototype.neg = function neg(_precompute) { - if (this.inf) - return this; - - var res = this.curve.point(this.x, this.y.redNeg()); - if (_precompute && this.precomputed) { - var pre = this.precomputed; - var negate = function(p) { - return p.neg(); - }; - res.precomputed = { - naf: pre.naf && { - wnd: pre.naf.wnd, - points: pre.naf.points.map(negate) - }, - doubles: pre.doubles && { - step: pre.doubles.step, - points: pre.doubles.points.map(negate) - } - }; - } - return res; - }; - - Point.prototype.toJ = function toJ() { - if (this.inf) - return this.curve.jpoint(null, null, null); - - var res = this.curve.jpoint(this.x, this.y, this.curve.one); - return res; - }; - - function JPoint(curve, x, y, z) { - base.BasePoint.call(this, curve, 'jacobian'); - if (x === null && y === null && z === null) { - this.x = this.curve.one; - this.y = this.curve.one; - this.z = new bn(0); - } else { - this.x = new bn(x, 16); - this.y = new bn(y, 16); - this.z = new bn(z, 16); - } - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.y.red) - this.y = this.y.toRed(this.curve.red); - if (!this.z.red) - this.z = this.z.toRed(this.curve.red); - - this.zOne = this.z === this.curve.one; - } - inherits_browser(JPoint, base.BasePoint); - - ShortCurve.prototype.jpoint = function jpoint(x, y, z) { - return new JPoint(this, x, y, z); - }; - - JPoint.prototype.toP = function toP() { - if (this.isInfinity()) - return this.curve.point(null, null); - - var zinv = this.z.redInvm(); - var zinv2 = zinv.redSqr(); - var ax = this.x.redMul(zinv2); - var ay = this.y.redMul(zinv2).redMul(zinv); - - return this.curve.point(ax, ay); - }; - - JPoint.prototype.neg = function neg() { - return this.curve.jpoint(this.x, this.y.redNeg(), this.z); - }; - - JPoint.prototype.add = function add(p) { - // O + P = P - if (this.isInfinity()) - return p; - - // P + O = P - if (p.isInfinity()) - return this; - - // 12M + 4S + 7A - var pz2 = p.z.redSqr(); - var z2 = this.z.redSqr(); - var u1 = this.x.redMul(pz2); - var u2 = p.x.redMul(z2); - var s1 = this.y.redMul(pz2.redMul(p.z)); - var s2 = p.y.redMul(z2.redMul(this.z)); - - var h = u1.redSub(u2); - var r = s1.redSub(s2); - if (h.cmpn(0) === 0) { - if (r.cmpn(0) !== 0) - return this.curve.jpoint(null, null, null); - else - return this.dbl(); - } - - var h2 = h.redSqr(); - var h3 = h2.redMul(h); - var v = u1.redMul(h2); - - var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); - var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); - var nz = this.z.redMul(p.z).redMul(h); - - return this.curve.jpoint(nx, ny, nz); - }; - - JPoint.prototype.mixedAdd = function mixedAdd(p) { - // O + P = P - if (this.isInfinity()) - return p.toJ(); - - // P + O = P - if (p.isInfinity()) - return this; - - // 8M + 3S + 7A - var z2 = this.z.redSqr(); - var u1 = this.x; - var u2 = p.x.redMul(z2); - var s1 = this.y; - var s2 = p.y.redMul(z2).redMul(this.z); - - var h = u1.redSub(u2); - var r = s1.redSub(s2); - if (h.cmpn(0) === 0) { - if (r.cmpn(0) !== 0) - return this.curve.jpoint(null, null, null); - else - return this.dbl(); - } - - var h2 = h.redSqr(); - var h3 = h2.redMul(h); - var v = u1.redMul(h2); - - var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); - var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); - var nz = this.z.redMul(h); - - return this.curve.jpoint(nx, ny, nz); - }; - - JPoint.prototype.dblp = function dblp(pow) { - if (pow === 0) - return this; - if (this.isInfinity()) - return this; - if (!pow) - return this.dbl(); - - if (this.curve.zeroA || this.curve.threeA) { - var r = this; - for (var i = 0; i < pow; i++) - r = r.dbl(); - return r; - } - - // 1M + 2S + 1A + N * (4S + 5M + 8A) - // N = 1 => 6M + 6S + 9A - var a = this.curve.a; - var tinv = this.curve.tinv; - - var jx = this.x; - var jy = this.y; - var jz = this.z; - var jz4 = jz.redSqr().redSqr(); - - // Reuse results - var jyd = jy.redAdd(jy); - for (var i = 0; i < pow; i++) { - var jx2 = jx.redSqr(); - var jyd2 = jyd.redSqr(); - var jyd4 = jyd2.redSqr(); - var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); - - var t1 = jx.redMul(jyd2); - var nx = c.redSqr().redISub(t1.redAdd(t1)); - var t2 = t1.redISub(nx); - var dny = c.redMul(t2); - dny = dny.redIAdd(dny).redISub(jyd4); - var nz = jyd.redMul(jz); - if (i + 1 < pow) - jz4 = jz4.redMul(jyd4); - - jx = nx; - jz = nz; - jyd = dny; - } - - return this.curve.jpoint(jx, jyd.redMul(tinv), jz); - }; - - JPoint.prototype.dbl = function dbl() { - if (this.isInfinity()) - return this; - - if (this.curve.zeroA) - return this._zeroDbl(); - else if (this.curve.threeA) - return this._threeDbl(); - else - return this._dbl(); - }; - - JPoint.prototype._zeroDbl = function _zeroDbl() { - var nx; - var ny; - var nz; - // Z = 1 - if (this.zOne) { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html - // #doubling-mdbl-2007-bl - // 1M + 5S + 14A - - // XX = X1^2 - var xx = this.x.redSqr(); - // YY = Y1^2 - var yy = this.y.redSqr(); - // YYYY = YY^2 - var yyyy = yy.redSqr(); - // S = 2 * ((X1 + YY)^2 - XX - YYYY) - var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); - s = s.redIAdd(s); - // M = 3 * XX + a; a = 0 - var m = xx.redAdd(xx).redIAdd(xx); - // T = M ^ 2 - 2*S - var t = m.redSqr().redISub(s).redISub(s); - - // 8 * YYYY - var yyyy8 = yyyy.redIAdd(yyyy); - yyyy8 = yyyy8.redIAdd(yyyy8); - yyyy8 = yyyy8.redIAdd(yyyy8); - - // X3 = T - nx = t; - // Y3 = M * (S - T) - 8 * YYYY - ny = m.redMul(s.redISub(t)).redISub(yyyy8); - // Z3 = 2*Y1 - nz = this.y.redAdd(this.y); - } else { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html - // #doubling-dbl-2009-l - // 2M + 5S + 13A - - // A = X1^2 - var a = this.x.redSqr(); - // B = Y1^2 - var b = this.y.redSqr(); - // C = B^2 - var c = b.redSqr(); - // D = 2 * ((X1 + B)^2 - A - C) - var d = this.x.redAdd(b).redSqr().redISub(a).redISub(c); - d = d.redIAdd(d); - // E = 3 * A - var e = a.redAdd(a).redIAdd(a); - // F = E^2 - var f = e.redSqr(); - - // 8 * C - var c8 = c.redIAdd(c); - c8 = c8.redIAdd(c8); - c8 = c8.redIAdd(c8); - - // X3 = F - 2 * D - nx = f.redISub(d).redISub(d); - // Y3 = E * (D - X3) - 8 * C - ny = e.redMul(d.redISub(nx)).redISub(c8); - // Z3 = 2 * Y1 * Z1 - nz = this.y.redMul(this.z); - nz = nz.redIAdd(nz); - } - - return this.curve.jpoint(nx, ny, nz); - }; - - JPoint.prototype._threeDbl = function _threeDbl() { - var nx; - var ny; - var nz; - // Z = 1 - if (this.zOne) { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html - // #doubling-mdbl-2007-bl - // 1M + 5S + 15A - - // XX = X1^2 - var xx = this.x.redSqr(); - // YY = Y1^2 - var yy = this.y.redSqr(); - // YYYY = YY^2 - var yyyy = yy.redSqr(); - // S = 2 * ((X1 + YY)^2 - XX - YYYY) - var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); - s = s.redIAdd(s); - // M = 3 * XX + a - var m = xx.redAdd(xx).redIAdd(xx).redIAdd(this.curve.a); - // T = M^2 - 2 * S - var t = m.redSqr().redISub(s).redISub(s); - // X3 = T - nx = t; - // Y3 = M * (S - T) - 8 * YYYY - var yyyy8 = yyyy.redIAdd(yyyy); - yyyy8 = yyyy8.redIAdd(yyyy8); - yyyy8 = yyyy8.redIAdd(yyyy8); - ny = m.redMul(s.redISub(t)).redISub(yyyy8); - // Z3 = 2 * Y1 - nz = this.y.redAdd(this.y); - } else { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b - // 3M + 5S - - // delta = Z1^2 - var delta = this.z.redSqr(); - // gamma = Y1^2 - var gamma = this.y.redSqr(); - // beta = X1 * gamma - var beta = this.x.redMul(gamma); - // alpha = 3 * (X1 - delta) * (X1 + delta) - var alpha = this.x.redSub(delta).redMul(this.x.redAdd(delta)); - alpha = alpha.redAdd(alpha).redIAdd(alpha); - // X3 = alpha^2 - 8 * beta - var beta4 = beta.redIAdd(beta); - beta4 = beta4.redIAdd(beta4); - var beta8 = beta4.redAdd(beta4); - nx = alpha.redSqr().redISub(beta8); - // Z3 = (Y1 + Z1)^2 - gamma - delta - nz = this.y.redAdd(this.z).redSqr().redISub(gamma).redISub(delta); - // Y3 = alpha * (4 * beta - X3) - 8 * gamma^2 - var ggamma8 = gamma.redSqr(); - ggamma8 = ggamma8.redIAdd(ggamma8); - ggamma8 = ggamma8.redIAdd(ggamma8); - ggamma8 = ggamma8.redIAdd(ggamma8); - ny = alpha.redMul(beta4.redISub(nx)).redISub(ggamma8); - } - - return this.curve.jpoint(nx, ny, nz); - }; - - JPoint.prototype._dbl = function _dbl() { - var a = this.curve.a; - - // 4M + 6S + 10A - var jx = this.x; - var jy = this.y; - var jz = this.z; - var jz4 = jz.redSqr().redSqr(); - - var jx2 = jx.redSqr(); - var jy2 = jy.redSqr(); - - var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); - - var jxd4 = jx.redAdd(jx); - jxd4 = jxd4.redIAdd(jxd4); - var t1 = jxd4.redMul(jy2); - var nx = c.redSqr().redISub(t1.redAdd(t1)); - var t2 = t1.redISub(nx); - - var jyd8 = jy2.redSqr(); - jyd8 = jyd8.redIAdd(jyd8); - jyd8 = jyd8.redIAdd(jyd8); - jyd8 = jyd8.redIAdd(jyd8); - var ny = c.redMul(t2).redISub(jyd8); - var nz = jy.redAdd(jy).redMul(jz); - - return this.curve.jpoint(nx, ny, nz); - }; - - JPoint.prototype.trpl = function trpl() { - if (!this.curve.zeroA) - return this.dbl().add(this); - - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#tripling-tpl-2007-bl - // 5M + 10S + ... - - // XX = X1^2 - var xx = this.x.redSqr(); - // YY = Y1^2 - var yy = this.y.redSqr(); - // ZZ = Z1^2 - var zz = this.z.redSqr(); - // YYYY = YY^2 - var yyyy = yy.redSqr(); - // M = 3 * XX + a * ZZ2; a = 0 - var m = xx.redAdd(xx).redIAdd(xx); - // MM = M^2 - var mm = m.redSqr(); - // E = 6 * ((X1 + YY)^2 - XX - YYYY) - MM - var e = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); - e = e.redIAdd(e); - e = e.redAdd(e).redIAdd(e); - e = e.redISub(mm); - // EE = E^2 - var ee = e.redSqr(); - // T = 16*YYYY - var t = yyyy.redIAdd(yyyy); - t = t.redIAdd(t); - t = t.redIAdd(t); - t = t.redIAdd(t); - // U = (M + E)^2 - MM - EE - T - var u = m.redIAdd(e).redSqr().redISub(mm).redISub(ee).redISub(t); - // X3 = 4 * (X1 * EE - 4 * YY * U) - var yyu4 = yy.redMul(u); - yyu4 = yyu4.redIAdd(yyu4); - yyu4 = yyu4.redIAdd(yyu4); - var nx = this.x.redMul(ee).redISub(yyu4); - nx = nx.redIAdd(nx); - nx = nx.redIAdd(nx); - // Y3 = 8 * Y1 * (U * (T - U) - E * EE) - var ny = this.y.redMul(u.redMul(t.redISub(u)).redISub(e.redMul(ee))); - ny = ny.redIAdd(ny); - ny = ny.redIAdd(ny); - ny = ny.redIAdd(ny); - // Z3 = (Z1 + E)^2 - ZZ - EE - var nz = this.z.redAdd(e).redSqr().redISub(zz).redISub(ee); - - return this.curve.jpoint(nx, ny, nz); - }; - - JPoint.prototype.mul = function mul(k, kbase) { - k = new bn(k, kbase); - - return this.curve._wnafMul(this, k); - }; - - JPoint.prototype.eq = function eq(p) { - if (p.type === 'affine') - return this.eq(p.toJ()); - - if (this === p) - return true; - - // x1 * z2^2 == x2 * z1^2 - var z2 = this.z.redSqr(); - var pz2 = p.z.redSqr(); - if (this.x.redMul(pz2).redISub(p.x.redMul(z2)).cmpn(0) !== 0) - return false; - - // y1 * z2^3 == y2 * z1^3 - var z3 = z2.redMul(this.z); - var pz3 = pz2.redMul(p.z); - return this.y.redMul(pz3).redISub(p.y.redMul(z3)).cmpn(0) === 0; - }; - - JPoint.prototype.eqXToP = function eqXToP(x) { - var zs = this.z.redSqr(); - var rx = x.toRed(this.curve.red).redMul(zs); - if (this.x.cmp(rx) === 0) - return true; - - var xc = x.clone(); - var t = this.curve.redN.redMul(zs); - for (;;) { - xc.iadd(this.curve.n); - if (xc.cmp(this.curve.p) >= 0) - return false; - - rx.redIAdd(t); - if (this.x.cmp(rx) === 0) - return true; - } - }; - - JPoint.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; - }; - - JPoint.prototype.isInfinity = function isInfinity() { - // XXX This code assumes that zero is always zero in red - return this.z.cmpn(0) === 0; - }; - - function MontCurve(conf) { - base.call(this, 'mont', conf); - - this.a = new bn(conf.a, 16).toRed(this.red); - this.b = new bn(conf.b, 16).toRed(this.red); - this.i4 = new bn(4).toRed(this.red).redInvm(); - this.two = new bn(2).toRed(this.red); - // Note: this implementation is according to the original paper - // by P. Montgomery, NOT the one by D. J. Bernstein. - this.a24 = this.i4.redMul(this.a.redAdd(this.two)); - } - inherits_browser(MontCurve, base); - var mont = MontCurve; - - MontCurve.prototype.validate = function validate(point) { - var x = point.normalize().x; - var x2 = x.redSqr(); - var rhs = x2.redMul(x).redAdd(x2.redMul(this.a)).redAdd(x); - var y = rhs.redSqrt(); - - return y.redSqr().cmp(rhs) === 0; - }; - - function Point$1(curve, x, z) { - base.BasePoint.call(this, curve, 'projective'); - if (x === null && z === null) { - this.x = this.curve.one; - this.z = this.curve.zero; - } else { - this.x = new bn(x, 16); - this.z = new bn(z, 16); - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.z.red) - this.z = this.z.toRed(this.curve.red); - } - } - inherits_browser(Point$1, base.BasePoint); - - MontCurve.prototype.decodePoint = function decodePoint(bytes, enc) { - var bytes = utils_1$1.toArray(bytes, enc); - - // TODO Curve448 - // Montgomery curve points must be represented in the compressed format - // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B - if (bytes.length === 33 && bytes[0] === 0x40) - bytes = bytes.slice(1, 33).reverse(); // point must be little-endian - if (bytes.length !== 32) - throw new Error('Unknown point compression format'); - return this.point(bytes, 1); - }; - - MontCurve.prototype.point = function point(x, z) { - return new Point$1(this, x, z); - }; - - MontCurve.prototype.pointFromJSON = function pointFromJSON(obj) { - return Point$1.fromJSON(this, obj); - }; - - Point$1.prototype.precompute = function precompute() { - // No-op - }; - - Point$1.prototype._encode = function _encode(compact) { - var len = this.curve.p.byteLength(); - - // Note: the output should always be little-endian - // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B - if (compact) { - return [ 0x40 ].concat(this.getX().toArray('le', len)); - } else { - return this.getX().toArray('be', len); - } - }; - - Point$1.fromJSON = function fromJSON(curve, obj) { - return new Point$1(curve, obj[0], obj[1] || curve.one); - }; - - Point$1.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; - }; - - Point$1.prototype.isInfinity = function isInfinity() { - // XXX This code assumes that zero is always zero in red - return this.z.cmpn(0) === 0; - }; - - Point$1.prototype.dbl = function dbl() { - // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#doubling-dbl-1987-m-3 - // 2M + 2S + 4A - - // A = X1 + Z1 - var a = this.x.redAdd(this.z); - // AA = A^2 - var aa = a.redSqr(); - // B = X1 - Z1 - var b = this.x.redSub(this.z); - // BB = B^2 - var bb = b.redSqr(); - // C = AA - BB - var c = aa.redSub(bb); - // X3 = AA * BB - var nx = aa.redMul(bb); - // Z3 = C * (BB + A24 * C) - var nz = c.redMul(bb.redAdd(this.curve.a24.redMul(c))); - return this.curve.point(nx, nz); - }; - - Point$1.prototype.add = function add() { - throw new Error('Not supported on Montgomery curve'); - }; - - Point$1.prototype.diffAdd = function diffAdd(p, diff) { - // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#diffadd-dadd-1987-m-3 - // 4M + 2S + 6A - - // A = X2 + Z2 - var a = this.x.redAdd(this.z); - // B = X2 - Z2 - var b = this.x.redSub(this.z); - // C = X3 + Z3 - var c = p.x.redAdd(p.z); - // D = X3 - Z3 - var d = p.x.redSub(p.z); - // DA = D * A - var da = d.redMul(a); - // CB = C * B - var cb = c.redMul(b); - // X5 = Z1 * (DA + CB)^2 - var nx = diff.z.redMul(da.redAdd(cb).redSqr()); - // Z5 = X1 * (DA - CB)^2 - var nz = diff.x.redMul(da.redISub(cb).redSqr()); - return this.curve.point(nx, nz); - }; - - Point$1.prototype.mul = function mul(k) { - k = new bn(k, 16); - - var t = k.clone(); - var a = this; // (N / 2) * Q + Q - var b = this.curve.point(null, null); // (N / 2) * Q - var c = this; // Q - - for (var bits = []; t.cmpn(0) !== 0; t.iushrn(1)) - bits.push(t.andln(1)); - - for (var i = bits.length - 1; i >= 0; i--) { - if (bits[i] === 0) { - // N * Q + Q = ((N / 2) * Q + Q)) + (N / 2) * Q - a = a.diffAdd(b, c); - // N * Q = 2 * ((N / 2) * Q + Q)) - b = b.dbl(); - } else { - // N * Q = ((N / 2) * Q + Q) + ((N / 2) * Q) - b = a.diffAdd(b, c); - // N * Q + Q = 2 * ((N / 2) * Q + Q) - a = a.dbl(); - } - } - return b; - }; - - Point$1.prototype.mulAdd = function mulAdd() { - throw new Error('Not supported on Montgomery curve'); - }; - - Point$1.prototype.jumlAdd = function jumlAdd() { - throw new Error('Not supported on Montgomery curve'); - }; - - Point$1.prototype.eq = function eq(other) { - return this.getX().cmp(other.getX()) === 0; - }; - - Point$1.prototype.normalize = function normalize() { - this.x = this.x.redMul(this.z.redInvm()); - this.z = this.curve.one; - return this; - }; - - Point$1.prototype.getX = function getX() { - // Normalize coordinates - this.normalize(); - - return this.x.fromRed(); - }; - - var assert$4 = utils_1$1.assert; - - function EdwardsCurve(conf) { - // NOTE: Important as we are creating point in Base.call() - this.twisted = (conf.a | 0) !== 1; - this.mOneA = this.twisted && (conf.a | 0) === -1; - this.extended = this.mOneA; - - base.call(this, 'edwards', conf); - - this.a = new bn(conf.a, 16).umod(this.red.m); - this.a = this.a.toRed(this.red); - this.c = new bn(conf.c, 16).toRed(this.red); - this.c2 = this.c.redSqr(); - this.d = new bn(conf.d, 16).toRed(this.red); - this.dd = this.d.redAdd(this.d); - - assert$4(!this.twisted || this.c.fromRed().cmpn(1) === 0); - this.oneC = (conf.c | 0) === 1; - } - inherits_browser(EdwardsCurve, base); - var edwards = EdwardsCurve; - - EdwardsCurve.prototype._mulA = function _mulA(num) { - if (this.mOneA) - return num.redNeg(); - else - return this.a.redMul(num); - }; - - EdwardsCurve.prototype._mulC = function _mulC(num) { - if (this.oneC) - return num; - else - return this.c.redMul(num); - }; - - // Just for compatibility with Short curve - EdwardsCurve.prototype.jpoint = function jpoint(x, y, z, t) { - return this.point(x, y, z, t); - }; - - EdwardsCurve.prototype.pointFromX = function pointFromX(x, odd) { - x = new bn(x, 16); - if (!x.red) - x = x.toRed(this.red); - - var x2 = x.redSqr(); - var rhs = this.c2.redSub(this.a.redMul(x2)); - var lhs = this.one.redSub(this.c2.redMul(this.d).redMul(x2)); - - var y2 = rhs.redMul(lhs.redInvm()); - var y = y2.redSqrt(); - if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) - throw new Error('invalid point'); - - var isOdd = y.fromRed().isOdd(); - if (odd && !isOdd || !odd && isOdd) - y = y.redNeg(); - - return this.point(x, y); - }; - - EdwardsCurve.prototype.pointFromY = function pointFromY(y, odd) { - y = new bn(y, 16); - if (!y.red) - y = y.toRed(this.red); - - // x^2 = (y^2 - c^2) / (c^2 d y^2 - a) - var y2 = y.redSqr(); - var lhs = y2.redSub(this.c2); - var rhs = y2.redMul(this.d).redMul(this.c2).redSub(this.a); - var x2 = lhs.redMul(rhs.redInvm()); - - if (x2.cmp(this.zero) === 0) { - if (odd) - throw new Error('invalid point'); - else - return this.point(this.zero, y); - } - - var x = x2.redSqrt(); - if (x.redSqr().redSub(x2).cmp(this.zero) !== 0) - throw new Error('invalid point'); - - if (x.fromRed().isOdd() !== odd) - x = x.redNeg(); - - return this.point(x, y); - }; - - EdwardsCurve.prototype.validate = function validate(point) { - if (point.isInfinity()) - return true; - - // Curve: A * X^2 + Y^2 = C^2 * (1 + D * X^2 * Y^2) - point.normalize(); - - var x2 = point.x.redSqr(); - var y2 = point.y.redSqr(); - var lhs = x2.redMul(this.a).redAdd(y2); - var rhs = this.c2.redMul(this.one.redAdd(this.d.redMul(x2).redMul(y2))); - - return lhs.cmp(rhs) === 0; - }; - - function Point$2(curve, x, y, z, t) { - base.BasePoint.call(this, curve, 'projective'); - if (x === null && y === null && z === null) { - this.x = this.curve.zero; - this.y = this.curve.one; - this.z = this.curve.one; - this.t = this.curve.zero; - this.zOne = true; - } else { - this.x = new bn(x, 16); - this.y = new bn(y, 16); - this.z = z ? new bn(z, 16) : this.curve.one; - this.t = t && new bn(t, 16); - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.y.red) - this.y = this.y.toRed(this.curve.red); - if (!this.z.red) - this.z = this.z.toRed(this.curve.red); - if (this.t && !this.t.red) - this.t = this.t.toRed(this.curve.red); - this.zOne = this.z === this.curve.one; - - // Use extended coordinates - if (this.curve.extended && !this.t) { - this.t = this.x.redMul(this.y); - if (!this.zOne) - this.t = this.t.redMul(this.z.redInvm()); - } - } - } - inherits_browser(Point$2, base.BasePoint); - - EdwardsCurve.prototype.pointFromJSON = function pointFromJSON(obj) { - return Point$2.fromJSON(this, obj); - }; - - EdwardsCurve.prototype.point = function point(x, y, z, t) { - return new Point$2(this, x, y, z, t); - }; - - Point$2.fromJSON = function fromJSON(curve, obj) { - return new Point$2(curve, obj[0], obj[1], obj[2]); - }; - - Point$2.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; - }; - - Point$2.prototype.isInfinity = function isInfinity() { - // XXX This code assumes that zero is always zero in red - return this.x.cmpn(0) === 0 && - (this.y.cmp(this.z) === 0 || - (this.zOne && this.y.cmp(this.curve.c) === 0)); - }; - - Point$2.prototype._extDbl = function _extDbl() { - // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html - // #doubling-dbl-2008-hwcd - // 4M + 4S - - // A = X1^2 - var a = this.x.redSqr(); - // B = Y1^2 - var b = this.y.redSqr(); - // C = 2 * Z1^2 - var c = this.z.redSqr(); - c = c.redIAdd(c); - // D = a * A - var d = this.curve._mulA(a); - // E = (X1 + Y1)^2 - A - B - var e = this.x.redAdd(this.y).redSqr().redISub(a).redISub(b); - // G = D + B - var g = d.redAdd(b); - // F = G - C - var f = g.redSub(c); - // H = D - B - var h = d.redSub(b); - // X3 = E * F - var nx = e.redMul(f); - // Y3 = G * H - var ny = g.redMul(h); - // T3 = E * H - var nt = e.redMul(h); - // Z3 = F * G - var nz = f.redMul(g); - return this.curve.point(nx, ny, nz, nt); - }; - - Point$2.prototype._projDbl = function _projDbl() { - // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html - // #doubling-dbl-2008-bbjlp - // #doubling-dbl-2007-bl - // and others - // Generally 3M + 4S or 2M + 4S - - // B = (X1 + Y1)^2 - var b = this.x.redAdd(this.y).redSqr(); - // C = X1^2 - var c = this.x.redSqr(); - // D = Y1^2 - var d = this.y.redSqr(); - - var nx; - var ny; - var nz; - if (this.curve.twisted) { - // E = a * C - var e = this.curve._mulA(c); - // F = E + D - var f = e.redAdd(d); - if (this.zOne) { - // X3 = (B - C - D) * (F - 2) - nx = b.redSub(c).redSub(d).redMul(f.redSub(this.curve.two)); - // Y3 = F * (E - D) - ny = f.redMul(e.redSub(d)); - // Z3 = F^2 - 2 * F - nz = f.redSqr().redSub(f).redSub(f); - } else { - // H = Z1^2 - var h = this.z.redSqr(); - // J = F - 2 * H - var j = f.redSub(h).redISub(h); - // X3 = (B-C-D)*J - nx = b.redSub(c).redISub(d).redMul(j); - // Y3 = F * (E - D) - ny = f.redMul(e.redSub(d)); - // Z3 = F * J - nz = f.redMul(j); - } - } else { - // E = C + D - var e = c.redAdd(d); - // H = (c * Z1)^2 - var h = this.curve._mulC(this.z).redSqr(); - // J = E - 2 * H - var j = e.redSub(h).redSub(h); - // X3 = c * (B - E) * J - nx = this.curve._mulC(b.redISub(e)).redMul(j); - // Y3 = c * E * (C - D) - ny = this.curve._mulC(e).redMul(c.redISub(d)); - // Z3 = E * J - nz = e.redMul(j); - } - return this.curve.point(nx, ny, nz); - }; - - Point$2.prototype.dbl = function dbl() { - if (this.isInfinity()) - return this; - - // Double in extended coordinates - if (this.curve.extended) - return this._extDbl(); - else - return this._projDbl(); - }; - - Point$2.prototype._extAdd = function _extAdd(p) { - // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html - // #addition-add-2008-hwcd-3 - // 8M - - // A = (Y1 - X1) * (Y2 - X2) - var a = this.y.redSub(this.x).redMul(p.y.redSub(p.x)); - // B = (Y1 + X1) * (Y2 + X2) - var b = this.y.redAdd(this.x).redMul(p.y.redAdd(p.x)); - // C = T1 * k * T2 - var c = this.t.redMul(this.curve.dd).redMul(p.t); - // D = Z1 * 2 * Z2 - var d = this.z.redMul(p.z.redAdd(p.z)); - // E = B - A - var e = b.redSub(a); - // F = D - C - var f = d.redSub(c); - // G = D + C - var g = d.redAdd(c); - // H = B + A - var h = b.redAdd(a); - // X3 = E * F - var nx = e.redMul(f); - // Y3 = G * H - var ny = g.redMul(h); - // T3 = E * H - var nt = e.redMul(h); - // Z3 = F * G - var nz = f.redMul(g); - return this.curve.point(nx, ny, nz, nt); - }; - - Point$2.prototype._projAdd = function _projAdd(p) { - // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html - // #addition-add-2008-bbjlp - // #addition-add-2007-bl - // 10M + 1S - - // A = Z1 * Z2 - var a = this.z.redMul(p.z); - // B = A^2 - var b = a.redSqr(); - // C = X1 * X2 - var c = this.x.redMul(p.x); - // D = Y1 * Y2 - var d = this.y.redMul(p.y); - // E = d * C * D - var e = this.curve.d.redMul(c).redMul(d); - // F = B - E - var f = b.redSub(e); - // G = B + E - var g = b.redAdd(e); - // X3 = A * F * ((X1 + Y1) * (X2 + Y2) - C - D) - var tmp = this.x.redAdd(this.y).redMul(p.x.redAdd(p.y)).redISub(c).redISub(d); - var nx = a.redMul(f).redMul(tmp); - var ny; - var nz; - if (this.curve.twisted) { - // Y3 = A * G * (D - a * C) - ny = a.redMul(g).redMul(d.redSub(this.curve._mulA(c))); - // Z3 = F * G - nz = f.redMul(g); - } else { - // Y3 = A * G * (D - C) - ny = a.redMul(g).redMul(d.redSub(c)); - // Z3 = c * F * G - nz = this.curve._mulC(f).redMul(g); - } - return this.curve.point(nx, ny, nz); - }; - - Point$2.prototype.add = function add(p) { - if (this.isInfinity()) - return p; - if (p.isInfinity()) - return this; - - if (this.curve.extended) - return this._extAdd(p); - else - return this._projAdd(p); - }; - - Point$2.prototype.mul = function mul(k) { - if (this._hasDoubles(k)) - return this.curve._fixedNafMul(this, k); - else - return this.curve._wnafMul(this, k); - }; - - Point$2.prototype.mulAdd = function mulAdd(k1, p, k2) { - return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, false); - }; - - Point$2.prototype.jmulAdd = function jmulAdd(k1, p, k2) { - return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, true); - }; - - Point$2.prototype.normalize = function normalize() { - if (this.zOne) - return this; - - // Normalize coordinates - var zi = this.z.redInvm(); - this.x = this.x.redMul(zi); - this.y = this.y.redMul(zi); - if (this.t) - this.t = this.t.redMul(zi); - this.z = this.curve.one; - this.zOne = true; - return this; - }; - - Point$2.prototype.neg = function neg() { - return this.curve.point(this.x.redNeg(), - this.y, - this.z, - this.t && this.t.redNeg()); - }; - - Point$2.prototype.getX = function getX() { - this.normalize(); - return this.x.fromRed(); - }; - - Point$2.prototype.getY = function getY() { - this.normalize(); - return this.y.fromRed(); - }; - - Point$2.prototype.eq = function eq(other) { - return this === other || - this.getX().cmp(other.getX()) === 0 && - this.getY().cmp(other.getY()) === 0; - }; - - Point$2.prototype.eqXToP = function eqXToP(x) { - var rx = x.toRed(this.curve.red).redMul(this.z); - if (this.x.cmp(rx) === 0) - return true; - - var xc = x.clone(); - var t = this.curve.redN.redMul(this.z); - for (;;) { - xc.iadd(this.curve.n); - if (xc.cmp(this.curve.p) >= 0) - return false; - - rx.redIAdd(t); - if (this.x.cmp(rx) === 0) - return true; - } - }; - - // Compatibility with BaseCurve - Point$2.prototype.toP = Point$2.prototype.normalize; - Point$2.prototype.mixedAdd = Point$2.prototype.add; - - var curve_1 = createCommonjsModule(function (module, exports) { - - var curve = exports; - - curve.base = base; - curve.short = short_1; - curve.mont = mont; - curve.edwards = edwards; - }); - - var rotl32$2 = utils.rotl32; - var sum32$3 = utils.sum32; - var sum32_5$2 = utils.sum32_5; - var ft_1$1 = common$1.ft_1; - var BlockHash$4 = common.BlockHash; - - var sha1_K = [ - 0x5A827999, 0x6ED9EBA1, - 0x8F1BBCDC, 0xCA62C1D6 - ]; - - function SHA1() { - if (!(this instanceof SHA1)) - return new SHA1(); - - BlockHash$4.call(this); - this.h = [ - 0x67452301, 0xefcdab89, 0x98badcfe, - 0x10325476, 0xc3d2e1f0 ]; - this.W = new Array(80); - } - - utils.inherits(SHA1, BlockHash$4); - var _1 = SHA1; - - SHA1.blockSize = 512; - SHA1.outSize = 160; - SHA1.hmacStrength = 80; - SHA1.padLength = 64; - - SHA1.prototype._update = function _update(msg, start) { - var W = this.W; - - for (var i = 0; i < 16; i++) - W[i] = msg[start + i]; - - for(; i < W.length; i++) - W[i] = rotl32$2(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1); - - var a = this.h[0]; - var b = this.h[1]; - var c = this.h[2]; - var d = this.h[3]; - var e = this.h[4]; - - for (i = 0; i < W.length; i++) { - var s = ~~(i / 20); - var t = sum32_5$2(rotl32$2(a, 5), ft_1$1(s, b, c, d), e, W[i], sha1_K[s]); - e = d; - d = c; - c = rotl32$2(b, 30); - b = a; - a = t; - } - - this.h[0] = sum32$3(this.h[0], a); - this.h[1] = sum32$3(this.h[1], b); - this.h[2] = sum32$3(this.h[2], c); - this.h[3] = sum32$3(this.h[3], d); - this.h[4] = sum32$3(this.h[4], e); - }; - - SHA1.prototype._digest = function digest(enc) { - if (enc === 'hex') - return utils.toHex32(this.h, 'big'); - else - return utils.split32(this.h, 'big'); - }; - - var sha1 = _1; - var sha224 = _224; - var sha256 = _256; - var sha384 = _384; - var sha512 = _512; - - var sha = { - sha1: sha1, - sha224: sha224, - sha256: sha256, - sha384: sha384, - sha512: sha512 - }; - - function Hmac(hash, key, enc) { - if (!(this instanceof Hmac)) - return new Hmac(hash, key, enc); - this.Hash = hash; - this.blockSize = hash.blockSize / 8; - this.outSize = hash.outSize / 8; - this.inner = null; - this.outer = null; - - this._init(utils.toArray(key, enc)); - } - var hmac = Hmac; - - Hmac.prototype._init = function init(key) { - // Shorten key, if needed - if (key.length > this.blockSize) - key = new this.Hash().update(key).digest(); - minimalisticAssert(key.length <= this.blockSize); - - // Add padding to key - for (var i = key.length; i < this.blockSize; i++) - key.push(0); - - for (i = 0; i < key.length; i++) - key[i] ^= 0x36; - this.inner = new this.Hash().update(key); - - // 0x36 ^ 0x5c = 0x6a - for (i = 0; i < key.length; i++) - key[i] ^= 0x6a; - this.outer = new this.Hash().update(key); - }; - - Hmac.prototype.update = function update(msg, enc) { - this.inner.update(msg, enc); - return this; - }; - - Hmac.prototype.digest = function digest(enc) { - this.outer.update(this.inner.digest()); - return this.outer.digest(enc); - }; - - var hash_1 = createCommonjsModule(function (module, exports) { - var hash = exports; - - hash.utils = utils; - hash.common = common; - hash.sha = sha; - hash.ripemd = ripemd; - hash.hmac = hmac; - - // Proxy hash functions to the main object - hash.sha1 = hash.sha.sha1; - hash.sha256 = hash.sha.sha256; - hash.sha224 = hash.sha.sha224; - hash.sha384 = hash.sha.sha384; - hash.sha512 = hash.sha.sha512; - hash.ripemd160 = hash.ripemd.ripemd160; - }); - - var secp256k1 = { - doubles: { - step: 4, - points: [ - [ - 'e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a', - 'f7e3507399e595929db99f34f57937101296891e44d23f0be1f32cce69616821' - ], - [ - '8282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508', - '11f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf' - ], - [ - '175e159f728b865a72f99cc6c6fc846de0b93833fd2222ed73fce5b551e5b739', - 'd3506e0d9e3c79eba4ef97a51ff71f5eacb5955add24345c6efa6ffee9fed695' - ], - [ - '363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640', - '4e273adfc732221953b445397f3363145b9a89008199ecb62003c7f3bee9de9' - ], - [ - '8b4b5f165df3c2be8c6244b5b745638843e4a781a15bcd1b69f79a55dffdf80c', - '4aad0a6f68d308b4b3fbd7813ab0da04f9e336546162ee56b3eff0c65fd4fd36' - ], - [ - '723cbaa6e5db996d6bf771c00bd548c7b700dbffa6c0e77bcb6115925232fcda', - '96e867b5595cc498a921137488824d6e2660a0653779494801dc069d9eb39f5f' - ], - [ - 'eebfa4d493bebf98ba5feec812c2d3b50947961237a919839a533eca0e7dd7fa', - '5d9a8ca3970ef0f269ee7edaf178089d9ae4cdc3a711f712ddfd4fdae1de8999' - ], - [ - '100f44da696e71672791d0a09b7bde459f1215a29b3c03bfefd7835b39a48db0', - 'cdd9e13192a00b772ec8f3300c090666b7ff4a18ff5195ac0fbd5cd62bc65a09' - ], - [ - 'e1031be262c7ed1b1dc9227a4a04c017a77f8d4464f3b3852c8acde6e534fd2d', - '9d7061928940405e6bb6a4176597535af292dd419e1ced79a44f18f29456a00d' - ], - [ - 'feea6cae46d55b530ac2839f143bd7ec5cf8b266a41d6af52d5e688d9094696d', - 'e57c6b6c97dce1bab06e4e12bf3ecd5c981c8957cc41442d3155debf18090088' - ], - [ - 'da67a91d91049cdcb367be4be6ffca3cfeed657d808583de33fa978bc1ec6cb1', - '9bacaa35481642bc41f463f7ec9780e5dec7adc508f740a17e9ea8e27a68be1d' - ], - [ - '53904faa0b334cdda6e000935ef22151ec08d0f7bb11069f57545ccc1a37b7c0', - '5bc087d0bc80106d88c9eccac20d3c1c13999981e14434699dcb096b022771c8' - ], - [ - '8e7bcd0bd35983a7719cca7764ca906779b53a043a9b8bcaeff959f43ad86047', - '10b7770b2a3da4b3940310420ca9514579e88e2e47fd68b3ea10047e8460372a' - ], - [ - '385eed34c1cdff21e6d0818689b81bde71a7f4f18397e6690a841e1599c43862', - '283bebc3e8ea23f56701de19e9ebf4576b304eec2086dc8cc0458fe5542e5453' - ], - [ - '6f9d9b803ecf191637c73a4413dfa180fddf84a5947fbc9c606ed86c3fac3a7', - '7c80c68e603059ba69b8e2a30e45c4d47ea4dd2f5c281002d86890603a842160' - ], - [ - '3322d401243c4e2582a2147c104d6ecbf774d163db0f5e5313b7e0e742d0e6bd', - '56e70797e9664ef5bfb019bc4ddaf9b72805f63ea2873af624f3a2e96c28b2a0' - ], - [ - '85672c7d2de0b7da2bd1770d89665868741b3f9af7643397721d74d28134ab83', - '7c481b9b5b43b2eb6374049bfa62c2e5e77f17fcc5298f44c8e3094f790313a6' - ], - [ - '948bf809b1988a46b06c9f1919413b10f9226c60f668832ffd959af60c82a0a', - '53a562856dcb6646dc6b74c5d1c3418c6d4dff08c97cd2bed4cb7f88d8c8e589' - ], - [ - '6260ce7f461801c34f067ce0f02873a8f1b0e44dfc69752accecd819f38fd8e8', - 'bc2da82b6fa5b571a7f09049776a1ef7ecd292238051c198c1a84e95b2b4ae17' - ], - [ - 'e5037de0afc1d8d43d8348414bbf4103043ec8f575bfdc432953cc8d2037fa2d', - '4571534baa94d3b5f9f98d09fb990bddbd5f5b03ec481f10e0e5dc841d755bda' - ], - [ - 'e06372b0f4a207adf5ea905e8f1771b4e7e8dbd1c6a6c5b725866a0ae4fce725', - '7a908974bce18cfe12a27bb2ad5a488cd7484a7787104870b27034f94eee31dd' - ], - [ - '213c7a715cd5d45358d0bbf9dc0ce02204b10bdde2a3f58540ad6908d0559754', - '4b6dad0b5ae462507013ad06245ba190bb4850f5f36a7eeddff2c27534b458f2' - ], - [ - '4e7c272a7af4b34e8dbb9352a5419a87e2838c70adc62cddf0cc3a3b08fbd53c', - '17749c766c9d0b18e16fd09f6def681b530b9614bff7dd33e0b3941817dcaae6' - ], - [ - 'fea74e3dbe778b1b10f238ad61686aa5c76e3db2be43057632427e2840fb27b6', - '6e0568db9b0b13297cf674deccb6af93126b596b973f7b77701d3db7f23cb96f' - ], - [ - '76e64113f677cf0e10a2570d599968d31544e179b760432952c02a4417bdde39', - 'c90ddf8dee4e95cf577066d70681f0d35e2a33d2b56d2032b4b1752d1901ac01' - ], - [ - 'c738c56b03b2abe1e8281baa743f8f9a8f7cc643df26cbee3ab150242bcbb891', - '893fb578951ad2537f718f2eacbfbbbb82314eef7880cfe917e735d9699a84c3' - ], - [ - 'd895626548b65b81e264c7637c972877d1d72e5f3a925014372e9f6588f6c14b', - 'febfaa38f2bc7eae728ec60818c340eb03428d632bb067e179363ed75d7d991f' - ], - [ - 'b8da94032a957518eb0f6433571e8761ceffc73693e84edd49150a564f676e03', - '2804dfa44805a1e4d7c99cc9762808b092cc584d95ff3b511488e4e74efdf6e7' - ], - [ - 'e80fea14441fb33a7d8adab9475d7fab2019effb5156a792f1a11778e3c0df5d', - 'eed1de7f638e00771e89768ca3ca94472d155e80af322ea9fcb4291b6ac9ec78' - ], - [ - 'a301697bdfcd704313ba48e51d567543f2a182031efd6915ddc07bbcc4e16070', - '7370f91cfb67e4f5081809fa25d40f9b1735dbf7c0a11a130c0d1a041e177ea1' - ], - [ - '90ad85b389d6b936463f9d0512678de208cc330b11307fffab7ac63e3fb04ed4', - 'e507a3620a38261affdcbd9427222b839aefabe1582894d991d4d48cb6ef150' - ], - [ - '8f68b9d2f63b5f339239c1ad981f162ee88c5678723ea3351b7b444c9ec4c0da', - '662a9f2dba063986de1d90c2b6be215dbbea2cfe95510bfdf23cbf79501fff82' - ], - [ - 'e4f3fb0176af85d65ff99ff9198c36091f48e86503681e3e6686fd5053231e11', - '1e63633ad0ef4f1c1661a6d0ea02b7286cc7e74ec951d1c9822c38576feb73bc' - ], - [ - '8c00fa9b18ebf331eb961537a45a4266c7034f2f0d4e1d0716fb6eae20eae29e', - 'efa47267fea521a1a9dc343a3736c974c2fadafa81e36c54e7d2a4c66702414b' - ], - [ - 'e7a26ce69dd4829f3e10cec0a9e98ed3143d084f308b92c0997fddfc60cb3e41', - '2a758e300fa7984b471b006a1aafbb18d0a6b2c0420e83e20e8a9421cf2cfd51' - ], - [ - 'b6459e0ee3662ec8d23540c223bcbdc571cbcb967d79424f3cf29eb3de6b80ef', - '67c876d06f3e06de1dadf16e5661db3c4b3ae6d48e35b2ff30bf0b61a71ba45' - ], - [ - 'd68a80c8280bb840793234aa118f06231d6f1fc67e73c5a5deda0f5b496943e8', - 'db8ba9fff4b586d00c4b1f9177b0e28b5b0e7b8f7845295a294c84266b133120' - ], - [ - '324aed7df65c804252dc0270907a30b09612aeb973449cea4095980fc28d3d5d', - '648a365774b61f2ff130c0c35aec1f4f19213b0c7e332843967224af96ab7c84' - ], - [ - '4df9c14919cde61f6d51dfdbe5fee5dceec4143ba8d1ca888e8bd373fd054c96', - '35ec51092d8728050974c23a1d85d4b5d506cdc288490192ebac06cad10d5d' - ], - [ - '9c3919a84a474870faed8a9c1cc66021523489054d7f0308cbfc99c8ac1f98cd', - 'ddb84f0f4a4ddd57584f044bf260e641905326f76c64c8e6be7e5e03d4fc599d' - ], - [ - '6057170b1dd12fdf8de05f281d8e06bb91e1493a8b91d4cc5a21382120a959e5', - '9a1af0b26a6a4807add9a2daf71df262465152bc3ee24c65e899be932385a2a8' - ], - [ - 'a576df8e23a08411421439a4518da31880cef0fba7d4df12b1a6973eecb94266', - '40a6bf20e76640b2c92b97afe58cd82c432e10a7f514d9f3ee8be11ae1b28ec8' - ], - [ - '7778a78c28dec3e30a05fe9629de8c38bb30d1f5cf9a3a208f763889be58ad71', - '34626d9ab5a5b22ff7098e12f2ff580087b38411ff24ac563b513fc1fd9f43ac' - ], - [ - '928955ee637a84463729fd30e7afd2ed5f96274e5ad7e5cb09eda9c06d903ac', - 'c25621003d3f42a827b78a13093a95eeac3d26efa8a8d83fc5180e935bcd091f' - ], - [ - '85d0fef3ec6db109399064f3a0e3b2855645b4a907ad354527aae75163d82751', - '1f03648413a38c0be29d496e582cf5663e8751e96877331582c237a24eb1f962' - ], - [ - 'ff2b0dce97eece97c1c9b6041798b85dfdfb6d8882da20308f5404824526087e', - '493d13fef524ba188af4c4dc54d07936c7b7ed6fb90e2ceb2c951e01f0c29907' - ], - [ - '827fbbe4b1e880ea9ed2b2e6301b212b57f1ee148cd6dd28780e5e2cf856e241', - 'c60f9c923c727b0b71bef2c67d1d12687ff7a63186903166d605b68baec293ec' - ], - [ - 'eaa649f21f51bdbae7be4ae34ce6e5217a58fdce7f47f9aa7f3b58fa2120e2b3', - 'be3279ed5bbbb03ac69a80f89879aa5a01a6b965f13f7e59d47a5305ba5ad93d' - ], - [ - 'e4a42d43c5cf169d9391df6decf42ee541b6d8f0c9a137401e23632dda34d24f', - '4d9f92e716d1c73526fc99ccfb8ad34ce886eedfa8d8e4f13a7f7131deba9414' - ], - [ - '1ec80fef360cbdd954160fadab352b6b92b53576a88fea4947173b9d4300bf19', - 'aeefe93756b5340d2f3a4958a7abbf5e0146e77f6295a07b671cdc1cc107cefd' - ], - [ - '146a778c04670c2f91b00af4680dfa8bce3490717d58ba889ddb5928366642be', - 'b318e0ec3354028add669827f9d4b2870aaa971d2f7e5ed1d0b297483d83efd0' - ], - [ - 'fa50c0f61d22e5f07e3acebb1aa07b128d0012209a28b9776d76a8793180eef9', - '6b84c6922397eba9b72cd2872281a68a5e683293a57a213b38cd8d7d3f4f2811' - ], - [ - 'da1d61d0ca721a11b1a5bf6b7d88e8421a288ab5d5bba5220e53d32b5f067ec2', - '8157f55a7c99306c79c0766161c91e2966a73899d279b48a655fba0f1ad836f1' - ], - [ - 'a8e282ff0c9706907215ff98e8fd416615311de0446f1e062a73b0610d064e13', - '7f97355b8db81c09abfb7f3c5b2515888b679a3e50dd6bd6cef7c73111f4cc0c' - ], - [ - '174a53b9c9a285872d39e56e6913cab15d59b1fa512508c022f382de8319497c', - 'ccc9dc37abfc9c1657b4155f2c47f9e6646b3a1d8cb9854383da13ac079afa73' - ], - [ - '959396981943785c3d3e57edf5018cdbe039e730e4918b3d884fdff09475b7ba', - '2e7e552888c331dd8ba0386a4b9cd6849c653f64c8709385e9b8abf87524f2fd' - ], - [ - 'd2a63a50ae401e56d645a1153b109a8fcca0a43d561fba2dbb51340c9d82b151', - 'e82d86fb6443fcb7565aee58b2948220a70f750af484ca52d4142174dcf89405' - ], - [ - '64587e2335471eb890ee7896d7cfdc866bacbdbd3839317b3436f9b45617e073', - 'd99fcdd5bf6902e2ae96dd6447c299a185b90a39133aeab358299e5e9faf6589' - ], - [ - '8481bde0e4e4d885b3a546d3e549de042f0aa6cea250e7fd358d6c86dd45e458', - '38ee7b8cba5404dd84a25bf39cecb2ca900a79c42b262e556d64b1b59779057e' - ], - [ - '13464a57a78102aa62b6979ae817f4637ffcfed3c4b1ce30bcd6303f6caf666b', - '69be159004614580ef7e433453ccb0ca48f300a81d0942e13f495a907f6ecc27' - ], - [ - 'bc4a9df5b713fe2e9aef430bcc1dc97a0cd9ccede2f28588cada3a0d2d83f366', - 'd3a81ca6e785c06383937adf4b798caa6e8a9fbfa547b16d758d666581f33c1' - ], - [ - '8c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa', - '40a30463a3305193378fedf31f7cc0eb7ae784f0451cb9459e71dc73cbef9482' - ], - [ - '8ea9666139527a8c1dd94ce4f071fd23c8b350c5a4bb33748c4ba111faccae0', - '620efabbc8ee2782e24e7c0cfb95c5d735b783be9cf0f8e955af34a30e62b945' - ], - [ - 'dd3625faef5ba06074669716bbd3788d89bdde815959968092f76cc4eb9a9787', - '7a188fa3520e30d461da2501045731ca941461982883395937f68d00c644a573' - ], - [ - 'f710d79d9eb962297e4f6232b40e8f7feb2bc63814614d692c12de752408221e', - 'ea98e67232d3b3295d3b535532115ccac8612c721851617526ae47a9c77bfc82' - ] - ] - }, - naf: { - wnd: 7, - points: [ - [ - 'f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9', - '388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672' - ], - [ - '2f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4', - 'd8ac222636e5e3d6d4dba9dda6c9c426f788271bab0d6840dca87d3aa6ac62d6' - ], - [ - '5cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc', - '6aebca40ba255960a3178d6d861a54dba813d0b813fde7b5a5082628087264da' - ], - [ - 'acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe', - 'cc338921b0a7d9fd64380971763b61e9add888a4375f8e0f05cc262ac64f9c37' - ], - [ - '774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb', - 'd984a032eb6b5e190243dd56d7b7b365372db1e2dff9d6a8301d74c9c953c61b' - ], - [ - 'f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8', - 'ab0902e8d880a89758212eb65cdaf473a1a06da521fa91f29b5cb52db03ed81' - ], - [ - 'd7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e', - '581e2872a86c72a683842ec228cc6defea40af2bd896d3a5c504dc9ff6a26b58' - ], - [ - 'defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34', - '4211ab0694635168e997b0ead2a93daeced1f4a04a95c0f6cfb199f69e56eb77' - ], - [ - '2b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c', - '85e89bc037945d93b343083b5a1c86131a01f60c50269763b570c854e5c09b7a' - ], - [ - '352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5', - '321eb4075348f534d59c18259dda3e1f4a1b3b2e71b1039c67bd3d8bcf81998c' - ], - [ - '2fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f', - '2de1068295dd865b64569335bd5dd80181d70ecfc882648423ba76b532b7d67' - ], - [ - '9248279b09b4d68dab21a9b066edda83263c3d84e09572e269ca0cd7f5453714', - '73016f7bf234aade5d1aa71bdea2b1ff3fc0de2a887912ffe54a32ce97cb3402' - ], - [ - 'daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729', - 'a69dce4a7d6c98e8d4a1aca87ef8d7003f83c230f3afa726ab40e52290be1c55' - ], - [ - 'c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db', - '2119a460ce326cdc76c45926c982fdac0e106e861edf61c5a039063f0e0e6482' - ], - [ - '6a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4', - 'e022cf42c2bd4a708b3f5126f16a24ad8b33ba48d0423b6efd5e6348100d8a82' - ], - [ - '1697ffa6fd9de627c077e3d2fe541084ce13300b0bec1146f95ae57f0d0bd6a5', - 'b9c398f186806f5d27561506e4557433a2cf15009e498ae7adee9d63d01b2396' - ], - [ - '605bdb019981718b986d0f07e834cb0d9deb8360ffb7f61df982345ef27a7479', - '2972d2de4f8d20681a78d93ec96fe23c26bfae84fb14db43b01e1e9056b8c49' - ], - [ - '62d14dab4150bf497402fdc45a215e10dcb01c354959b10cfe31c7e9d87ff33d', - '80fc06bd8cc5b01098088a1950eed0db01aa132967ab472235f5642483b25eaf' - ], - [ - '80c60ad0040f27dade5b4b06c408e56b2c50e9f56b9b8b425e555c2f86308b6f', - '1c38303f1cc5c30f26e66bad7fe72f70a65eed4cbe7024eb1aa01f56430bd57a' - ], - [ - '7a9375ad6167ad54aa74c6348cc54d344cc5dc9487d847049d5eabb0fa03c8fb', - 'd0e3fa9eca8726909559e0d79269046bdc59ea10c70ce2b02d499ec224dc7f7' - ], - [ - 'd528ecd9b696b54c907a9ed045447a79bb408ec39b68df504bb51f459bc3ffc9', - 'eecf41253136e5f99966f21881fd656ebc4345405c520dbc063465b521409933' - ], - [ - '49370a4b5f43412ea25f514e8ecdad05266115e4a7ecb1387231808f8b45963', - '758f3f41afd6ed428b3081b0512fd62a54c3f3afbb5b6764b653052a12949c9a' - ], - [ - '77f230936ee88cbbd73df930d64702ef881d811e0e1498e2f1c13eb1fc345d74', - '958ef42a7886b6400a08266e9ba1b37896c95330d97077cbbe8eb3c7671c60d6' - ], - [ - 'f2dac991cc4ce4b9ea44887e5c7c0bce58c80074ab9d4dbaeb28531b7739f530', - 'e0dedc9b3b2f8dad4da1f32dec2531df9eb5fbeb0598e4fd1a117dba703a3c37' - ], - [ - '463b3d9f662621fb1b4be8fbbe2520125a216cdfc9dae3debcba4850c690d45b', - '5ed430d78c296c3543114306dd8622d7c622e27c970a1de31cb377b01af7307e' - ], - [ - 'f16f804244e46e2a09232d4aff3b59976b98fac14328a2d1a32496b49998f247', - 'cedabd9b82203f7e13d206fcdf4e33d92a6c53c26e5cce26d6579962c4e31df6' - ], - [ - 'caf754272dc84563b0352b7a14311af55d245315ace27c65369e15f7151d41d1', - 'cb474660ef35f5f2a41b643fa5e460575f4fa9b7962232a5c32f908318a04476' - ], - [ - '2600ca4b282cb986f85d0f1709979d8b44a09c07cb86d7c124497bc86f082120', - '4119b88753c15bd6a693b03fcddbb45d5ac6be74ab5f0ef44b0be9475a7e4b40' - ], - [ - '7635ca72d7e8432c338ec53cd12220bc01c48685e24f7dc8c602a7746998e435', - '91b649609489d613d1d5e590f78e6d74ecfc061d57048bad9e76f302c5b9c61' - ], - [ - '754e3239f325570cdbbf4a87deee8a66b7f2b33479d468fbc1a50743bf56cc18', - '673fb86e5bda30fb3cd0ed304ea49a023ee33d0197a695d0c5d98093c536683' - ], - [ - 'e3e6bd1071a1e96aff57859c82d570f0330800661d1c952f9fe2694691d9b9e8', - '59c9e0bba394e76f40c0aa58379a3cb6a5a2283993e90c4167002af4920e37f5' - ], - [ - '186b483d056a033826ae73d88f732985c4ccb1f32ba35f4b4cc47fdcf04aa6eb', - '3b952d32c67cf77e2e17446e204180ab21fb8090895138b4a4a797f86e80888b' - ], - [ - 'df9d70a6b9876ce544c98561f4be4f725442e6d2b737d9c91a8321724ce0963f', - '55eb2dafd84d6ccd5f862b785dc39d4ab157222720ef9da217b8c45cf2ba2417' - ], - [ - '5edd5cc23c51e87a497ca815d5dce0f8ab52554f849ed8995de64c5f34ce7143', - 'efae9c8dbc14130661e8cec030c89ad0c13c66c0d17a2905cdc706ab7399a868' - ], - [ - '290798c2b6476830da12fe02287e9e777aa3fba1c355b17a722d362f84614fba', - 'e38da76dcd440621988d00bcf79af25d5b29c094db2a23146d003afd41943e7a' - ], - [ - 'af3c423a95d9f5b3054754efa150ac39cd29552fe360257362dfdecef4053b45', - 'f98a3fd831eb2b749a93b0e6f35cfb40c8cd5aa667a15581bc2feded498fd9c6' - ], - [ - '766dbb24d134e745cccaa28c99bf274906bb66b26dcf98df8d2fed50d884249a', - '744b1152eacbe5e38dcc887980da38b897584a65fa06cedd2c924f97cbac5996' - ], - [ - '59dbf46f8c94759ba21277c33784f41645f7b44f6c596a58ce92e666191abe3e', - 'c534ad44175fbc300f4ea6ce648309a042ce739a7919798cd85e216c4a307f6e' - ], - [ - 'f13ada95103c4537305e691e74e9a4a8dd647e711a95e73cb62dc6018cfd87b8', - 'e13817b44ee14de663bf4bc808341f326949e21a6a75c2570778419bdaf5733d' - ], - [ - '7754b4fa0e8aced06d4167a2c59cca4cda1869c06ebadfb6488550015a88522c', - '30e93e864e669d82224b967c3020b8fa8d1e4e350b6cbcc537a48b57841163a2' - ], - [ - '948dcadf5990e048aa3874d46abef9d701858f95de8041d2a6828c99e2262519', - 'e491a42537f6e597d5d28a3224b1bc25df9154efbd2ef1d2cbba2cae5347d57e' - ], - [ - '7962414450c76c1689c7b48f8202ec37fb224cf5ac0bfa1570328a8a3d7c77ab', - '100b610ec4ffb4760d5c1fc133ef6f6b12507a051f04ac5760afa5b29db83437' - ], - [ - '3514087834964b54b15b160644d915485a16977225b8847bb0dd085137ec47ca', - 'ef0afbb2056205448e1652c48e8127fc6039e77c15c2378b7e7d15a0de293311' - ], - [ - 'd3cc30ad6b483e4bc79ce2c9dd8bc54993e947eb8df787b442943d3f7b527eaf', - '8b378a22d827278d89c5e9be8f9508ae3c2ad46290358630afb34db04eede0a4' - ], - [ - '1624d84780732860ce1c78fcbfefe08b2b29823db913f6493975ba0ff4847610', - '68651cf9b6da903e0914448c6cd9d4ca896878f5282be4c8cc06e2a404078575' - ], - [ - '733ce80da955a8a26902c95633e62a985192474b5af207da6df7b4fd5fc61cd4', - 'f5435a2bd2badf7d485a4d8b8db9fcce3e1ef8e0201e4578c54673bc1dc5ea1d' - ], - [ - '15d9441254945064cf1a1c33bbd3b49f8966c5092171e699ef258dfab81c045c', - 'd56eb30b69463e7234f5137b73b84177434800bacebfc685fc37bbe9efe4070d' - ], - [ - 'a1d0fcf2ec9de675b612136e5ce70d271c21417c9d2b8aaaac138599d0717940', - 'edd77f50bcb5a3cab2e90737309667f2641462a54070f3d519212d39c197a629' - ], - [ - 'e22fbe15c0af8ccc5780c0735f84dbe9a790badee8245c06c7ca37331cb36980', - 'a855babad5cd60c88b430a69f53a1a7a38289154964799be43d06d77d31da06' - ], - [ - '311091dd9860e8e20ee13473c1155f5f69635e394704eaa74009452246cfa9b3', - '66db656f87d1f04fffd1f04788c06830871ec5a64feee685bd80f0b1286d8374' - ], - [ - '34c1fd04d301be89b31c0442d3e6ac24883928b45a9340781867d4232ec2dbdf', - '9414685e97b1b5954bd46f730174136d57f1ceeb487443dc5321857ba73abee' - ], - [ - 'f219ea5d6b54701c1c14de5b557eb42a8d13f3abbcd08affcc2a5e6b049b8d63', - '4cb95957e83d40b0f73af4544cccf6b1f4b08d3c07b27fb8d8c2962a400766d1' - ], - [ - 'd7b8740f74a8fbaab1f683db8f45de26543a5490bca627087236912469a0b448', - 'fa77968128d9c92ee1010f337ad4717eff15db5ed3c049b3411e0315eaa4593b' - ], - [ - '32d31c222f8f6f0ef86f7c98d3a3335ead5bcd32abdd94289fe4d3091aa824bf', - '5f3032f5892156e39ccd3d7915b9e1da2e6dac9e6f26e961118d14b8462e1661' - ], - [ - '7461f371914ab32671045a155d9831ea8793d77cd59592c4340f86cbc18347b5', - '8ec0ba238b96bec0cbdddcae0aa442542eee1ff50c986ea6b39847b3cc092ff6' - ], - [ - 'ee079adb1df1860074356a25aa38206a6d716b2c3e67453d287698bad7b2b2d6', - '8dc2412aafe3be5c4c5f37e0ecc5f9f6a446989af04c4e25ebaac479ec1c8c1e' - ], - [ - '16ec93e447ec83f0467b18302ee620f7e65de331874c9dc72bfd8616ba9da6b5', - '5e4631150e62fb40d0e8c2a7ca5804a39d58186a50e497139626778e25b0674d' - ], - [ - 'eaa5f980c245f6f038978290afa70b6bd8855897f98b6aa485b96065d537bd99', - 'f65f5d3e292c2e0819a528391c994624d784869d7e6ea67fb18041024edc07dc' - ], - [ - '78c9407544ac132692ee1910a02439958ae04877151342ea96c4b6b35a49f51', - 'f3e0319169eb9b85d5404795539a5e68fa1fbd583c064d2462b675f194a3ddb4' - ], - [ - '494f4be219a1a77016dcd838431aea0001cdc8ae7a6fc688726578d9702857a5', - '42242a969283a5f339ba7f075e36ba2af925ce30d767ed6e55f4b031880d562c' - ], - [ - 'a598a8030da6d86c6bc7f2f5144ea549d28211ea58faa70ebf4c1e665c1fe9b5', - '204b5d6f84822c307e4b4a7140737aec23fc63b65b35f86a10026dbd2d864e6b' - ], - [ - 'c41916365abb2b5d09192f5f2dbeafec208f020f12570a184dbadc3e58595997', - '4f14351d0087efa49d245b328984989d5caf9450f34bfc0ed16e96b58fa9913' - ], - [ - '841d6063a586fa475a724604da03bc5b92a2e0d2e0a36acfe4c73a5514742881', - '73867f59c0659e81904f9a1c7543698e62562d6744c169ce7a36de01a8d6154' - ], - [ - '5e95bb399a6971d376026947f89bde2f282b33810928be4ded112ac4d70e20d5', - '39f23f366809085beebfc71181313775a99c9aed7d8ba38b161384c746012865' - ], - [ - '36e4641a53948fd476c39f8a99fd974e5ec07564b5315d8bf99471bca0ef2f66', - 'd2424b1b1abe4eb8164227b085c9aa9456ea13493fd563e06fd51cf5694c78fc' - ], - [ - '336581ea7bfbbb290c191a2f507a41cf5643842170e914faeab27c2c579f726', - 'ead12168595fe1be99252129b6e56b3391f7ab1410cd1e0ef3dcdcabd2fda224' - ], - [ - '8ab89816dadfd6b6a1f2634fcf00ec8403781025ed6890c4849742706bd43ede', - '6fdcef09f2f6d0a044e654aef624136f503d459c3e89845858a47a9129cdd24e' - ], - [ - '1e33f1a746c9c5778133344d9299fcaa20b0938e8acff2544bb40284b8c5fb94', - '60660257dd11b3aa9c8ed618d24edff2306d320f1d03010e33a7d2057f3b3b6' - ], - [ - '85b7c1dcb3cec1b7ee7f30ded79dd20a0ed1f4cc18cbcfcfa410361fd8f08f31', - '3d98a9cdd026dd43f39048f25a8847f4fcafad1895d7a633c6fed3c35e999511' - ], - [ - '29df9fbd8d9e46509275f4b125d6d45d7fbe9a3b878a7af872a2800661ac5f51', - 'b4c4fe99c775a606e2d8862179139ffda61dc861c019e55cd2876eb2a27d84b' - ], - [ - 'a0b1cae06b0a847a3fea6e671aaf8adfdfe58ca2f768105c8082b2e449fce252', - 'ae434102edde0958ec4b19d917a6a28e6b72da1834aff0e650f049503a296cf2' - ], - [ - '4e8ceafb9b3e9a136dc7ff67e840295b499dfb3b2133e4ba113f2e4c0e121e5', - 'cf2174118c8b6d7a4b48f6d534ce5c79422c086a63460502b827ce62a326683c' - ], - [ - 'd24a44e047e19b6f5afb81c7ca2f69080a5076689a010919f42725c2b789a33b', - '6fb8d5591b466f8fc63db50f1c0f1c69013f996887b8244d2cdec417afea8fa3' - ], - [ - 'ea01606a7a6c9cdd249fdfcfacb99584001edd28abbab77b5104e98e8e3b35d4', - '322af4908c7312b0cfbfe369f7a7b3cdb7d4494bc2823700cfd652188a3ea98d' - ], - [ - 'af8addbf2b661c8a6c6328655eb96651252007d8c5ea31be4ad196de8ce2131f', - '6749e67c029b85f52a034eafd096836b2520818680e26ac8f3dfbcdb71749700' - ], - [ - 'e3ae1974566ca06cc516d47e0fb165a674a3dabcfca15e722f0e3450f45889', - '2aeabe7e4531510116217f07bf4d07300de97e4874f81f533420a72eeb0bd6a4' - ], - [ - '591ee355313d99721cf6993ffed1e3e301993ff3ed258802075ea8ced397e246', - 'b0ea558a113c30bea60fc4775460c7901ff0b053d25ca2bdeee98f1a4be5d196' - ], - [ - '11396d55fda54c49f19aa97318d8da61fa8584e47b084945077cf03255b52984', - '998c74a8cd45ac01289d5833a7beb4744ff536b01b257be4c5767bea93ea57a4' - ], - [ - '3c5d2a1ba39c5a1790000738c9e0c40b8dcdfd5468754b6405540157e017aa7a', - 'b2284279995a34e2f9d4de7396fc18b80f9b8b9fdd270f6661f79ca4c81bd257' - ], - [ - 'cc8704b8a60a0defa3a99a7299f2e9c3fbc395afb04ac078425ef8a1793cc030', - 'bdd46039feed17881d1e0862db347f8cf395b74fc4bcdc4e940b74e3ac1f1b13' - ], - [ - 'c533e4f7ea8555aacd9777ac5cad29b97dd4defccc53ee7ea204119b2889b197', - '6f0a256bc5efdf429a2fb6242f1a43a2d9b925bb4a4b3a26bb8e0f45eb596096' - ], - [ - 'c14f8f2ccb27d6f109f6d08d03cc96a69ba8c34eec07bbcf566d48e33da6593', - 'c359d6923bb398f7fd4473e16fe1c28475b740dd098075e6c0e8649113dc3a38' - ], - [ - 'a6cbc3046bc6a450bac24789fa17115a4c9739ed75f8f21ce441f72e0b90e6ef', - '21ae7f4680e889bb130619e2c0f95a360ceb573c70603139862afd617fa9b9f' - ], - [ - '347d6d9a02c48927ebfb86c1359b1caf130a3c0267d11ce6344b39f99d43cc38', - '60ea7f61a353524d1c987f6ecec92f086d565ab687870cb12689ff1e31c74448' - ], - [ - 'da6545d2181db8d983f7dcb375ef5866d47c67b1bf31c8cf855ef7437b72656a', - '49b96715ab6878a79e78f07ce5680c5d6673051b4935bd897fea824b77dc208a' - ], - [ - 'c40747cc9d012cb1a13b8148309c6de7ec25d6945d657146b9d5994b8feb1111', - '5ca560753be2a12fc6de6caf2cb489565db936156b9514e1bb5e83037e0fa2d4' - ], - [ - '4e42c8ec82c99798ccf3a610be870e78338c7f713348bd34c8203ef4037f3502', - '7571d74ee5e0fb92a7a8b33a07783341a5492144cc54bcc40a94473693606437' - ], - [ - '3775ab7089bc6af823aba2e1af70b236d251cadb0c86743287522a1b3b0dedea', - 'be52d107bcfa09d8bcb9736a828cfa7fac8db17bf7a76a2c42ad961409018cf7' - ], - [ - 'cee31cbf7e34ec379d94fb814d3d775ad954595d1314ba8846959e3e82f74e26', - '8fd64a14c06b589c26b947ae2bcf6bfa0149ef0be14ed4d80f448a01c43b1c6d' - ], - [ - 'b4f9eaea09b6917619f6ea6a4eb5464efddb58fd45b1ebefcdc1a01d08b47986', - '39e5c9925b5a54b07433a4f18c61726f8bb131c012ca542eb24a8ac07200682a' - ], - [ - 'd4263dfc3d2df923a0179a48966d30ce84e2515afc3dccc1b77907792ebcc60e', - '62dfaf07a0f78feb30e30d6295853ce189e127760ad6cf7fae164e122a208d54' - ], - [ - '48457524820fa65a4f8d35eb6930857c0032acc0a4a2de422233eeda897612c4', - '25a748ab367979d98733c38a1fa1c2e7dc6cc07db2d60a9ae7a76aaa49bd0f77' - ], - [ - 'dfeeef1881101f2cb11644f3a2afdfc2045e19919152923f367a1767c11cceda', - 'ecfb7056cf1de042f9420bab396793c0c390bde74b4bbdff16a83ae09a9a7517' - ], - [ - '6d7ef6b17543f8373c573f44e1f389835d89bcbc6062ced36c82df83b8fae859', - 'cd450ec335438986dfefa10c57fea9bcc521a0959b2d80bbf74b190dca712d10' - ], - [ - 'e75605d59102a5a2684500d3b991f2e3f3c88b93225547035af25af66e04541f', - 'f5c54754a8f71ee540b9b48728473e314f729ac5308b06938360990e2bfad125' - ], - [ - 'eb98660f4c4dfaa06a2be453d5020bc99a0c2e60abe388457dd43fefb1ed620c', - '6cb9a8876d9cb8520609af3add26cd20a0a7cd8a9411131ce85f44100099223e' - ], - [ - '13e87b027d8514d35939f2e6892b19922154596941888336dc3563e3b8dba942', - 'fef5a3c68059a6dec5d624114bf1e91aac2b9da568d6abeb2570d55646b8adf1' - ], - [ - 'ee163026e9fd6fe017c38f06a5be6fc125424b371ce2708e7bf4491691e5764a', - '1acb250f255dd61c43d94ccc670d0f58f49ae3fa15b96623e5430da0ad6c62b2' - ], - [ - 'b268f5ef9ad51e4d78de3a750c2dc89b1e626d43505867999932e5db33af3d80', - '5f310d4b3c99b9ebb19f77d41c1dee018cf0d34fd4191614003e945a1216e423' - ], - [ - 'ff07f3118a9df035e9fad85eb6c7bfe42b02f01ca99ceea3bf7ffdba93c4750d', - '438136d603e858a3a5c440c38eccbaddc1d2942114e2eddd4740d098ced1f0d8' - ], - [ - '8d8b9855c7c052a34146fd20ffb658bea4b9f69e0d825ebec16e8c3ce2b526a1', - 'cdb559eedc2d79f926baf44fb84ea4d44bcf50fee51d7ceb30e2e7f463036758' - ], - [ - '52db0b5384dfbf05bfa9d472d7ae26dfe4b851ceca91b1eba54263180da32b63', - 'c3b997d050ee5d423ebaf66a6db9f57b3180c902875679de924b69d84a7b375' - ], - [ - 'e62f9490d3d51da6395efd24e80919cc7d0f29c3f3fa48c6fff543becbd43352', - '6d89ad7ba4876b0b22c2ca280c682862f342c8591f1daf5170e07bfd9ccafa7d' - ], - [ - '7f30ea2476b399b4957509c88f77d0191afa2ff5cb7b14fd6d8e7d65aaab1193', - 'ca5ef7d4b231c94c3b15389a5f6311e9daff7bb67b103e9880ef4bff637acaec' - ], - [ - '5098ff1e1d9f14fb46a210fada6c903fef0fb7b4a1dd1d9ac60a0361800b7a00', - '9731141d81fc8f8084d37c6e7542006b3ee1b40d60dfe5362a5b132fd17ddc0' - ], - [ - '32b78c7de9ee512a72895be6b9cbefa6e2f3c4ccce445c96b9f2c81e2778ad58', - 'ee1849f513df71e32efc3896ee28260c73bb80547ae2275ba497237794c8753c' - ], - [ - 'e2cb74fddc8e9fbcd076eef2a7c72b0ce37d50f08269dfc074b581550547a4f7', - 'd3aa2ed71c9dd2247a62df062736eb0baddea9e36122d2be8641abcb005cc4a4' - ], - [ - '8438447566d4d7bedadc299496ab357426009a35f235cb141be0d99cd10ae3a8', - 'c4e1020916980a4da5d01ac5e6ad330734ef0d7906631c4f2390426b2edd791f' - ], - [ - '4162d488b89402039b584c6fc6c308870587d9c46f660b878ab65c82c711d67e', - '67163e903236289f776f22c25fb8a3afc1732f2b84b4e95dbda47ae5a0852649' - ], - [ - '3fad3fa84caf0f34f0f89bfd2dcf54fc175d767aec3e50684f3ba4a4bf5f683d', - 'cd1bc7cb6cc407bb2f0ca647c718a730cf71872e7d0d2a53fa20efcdfe61826' - ], - [ - '674f2600a3007a00568c1a7ce05d0816c1fb84bf1370798f1c69532faeb1a86b', - '299d21f9413f33b3edf43b257004580b70db57da0b182259e09eecc69e0d38a5' - ], - [ - 'd32f4da54ade74abb81b815ad1fb3b263d82d6c692714bcff87d29bd5ee9f08f', - 'f9429e738b8e53b968e99016c059707782e14f4535359d582fc416910b3eea87' - ], - [ - '30e4e670435385556e593657135845d36fbb6931f72b08cb1ed954f1e3ce3ff6', - '462f9bce619898638499350113bbc9b10a878d35da70740dc695a559eb88db7b' - ], - [ - 'be2062003c51cc3004682904330e4dee7f3dcd10b01e580bf1971b04d4cad297', - '62188bc49d61e5428573d48a74e1c655b1c61090905682a0d5558ed72dccb9bc' - ], - [ - '93144423ace3451ed29e0fb9ac2af211cb6e84a601df5993c419859fff5df04a', - '7c10dfb164c3425f5c71a3f9d7992038f1065224f72bb9d1d902a6d13037b47c' - ], - [ - 'b015f8044f5fcbdcf21ca26d6c34fb8197829205c7b7d2a7cb66418c157b112c', - 'ab8c1e086d04e813744a655b2df8d5f83b3cdc6faa3088c1d3aea1454e3a1d5f' - ], - [ - 'd5e9e1da649d97d89e4868117a465a3a4f8a18de57a140d36b3f2af341a21b52', - '4cb04437f391ed73111a13cc1d4dd0db1693465c2240480d8955e8592f27447a' - ], - [ - 'd3ae41047dd7ca065dbf8ed77b992439983005cd72e16d6f996a5316d36966bb', - 'bd1aeb21ad22ebb22a10f0303417c6d964f8cdd7df0aca614b10dc14d125ac46' - ], - [ - '463e2763d885f958fc66cdd22800f0a487197d0a82e377b49f80af87c897b065', - 'bfefacdb0e5d0fd7df3a311a94de062b26b80c61fbc97508b79992671ef7ca7f' - ], - [ - '7985fdfd127c0567c6f53ec1bb63ec3158e597c40bfe747c83cddfc910641917', - '603c12daf3d9862ef2b25fe1de289aed24ed291e0ec6708703a5bd567f32ed03' - ], - [ - '74a1ad6b5f76e39db2dd249410eac7f99e74c59cb83d2d0ed5ff1543da7703e9', - 'cc6157ef18c9c63cd6193d83631bbea0093e0968942e8c33d5737fd790e0db08' - ], - [ - '30682a50703375f602d416664ba19b7fc9bab42c72747463a71d0896b22f6da3', - '553e04f6b018b4fa6c8f39e7f311d3176290d0e0f19ca73f17714d9977a22ff8' - ], - [ - '9e2158f0d7c0d5f26c3791efefa79597654e7a2b2464f52b1ee6c1347769ef57', - '712fcdd1b9053f09003a3481fa7762e9ffd7c8ef35a38509e2fbf2629008373' - ], - [ - '176e26989a43c9cfeba4029c202538c28172e566e3c4fce7322857f3be327d66', - 'ed8cc9d04b29eb877d270b4878dc43c19aefd31f4eee09ee7b47834c1fa4b1c3' - ], - [ - '75d46efea3771e6e68abb89a13ad747ecf1892393dfc4f1b7004788c50374da8', - '9852390a99507679fd0b86fd2b39a868d7efc22151346e1a3ca4726586a6bed8' - ], - [ - '809a20c67d64900ffb698c4c825f6d5f2310fb0451c869345b7319f645605721', - '9e994980d9917e22b76b061927fa04143d096ccc54963e6a5ebfa5f3f8e286c1' - ], - [ - '1b38903a43f7f114ed4500b4eac7083fdefece1cf29c63528d563446f972c180', - '4036edc931a60ae889353f77fd53de4a2708b26b6f5da72ad3394119daf408f9' - ] - ] - } - }; - - var curves_1 = createCommonjsModule(function (module, exports) { - - var curves = exports; - - - - - - var assert = utils_1$1.assert; - - function PresetCurve(options) { - if (options.type === 'short') - this.curve = new curve_1.short(options); - else if (options.type === 'edwards') - this.curve = new curve_1.edwards(options); - else if (options.type === 'mont') - this.curve = new curve_1.mont(options); - else throw new Error('Unknown curve type.'); - this.g = this.curve.g; - this.n = this.curve.n; - this.hash = options.hash; - - assert(this.g.validate(), 'Invalid curve'); - assert(this.g.mul(this.n).isInfinity(), 'Invalid curve, n*G != O'); - } - curves.PresetCurve = PresetCurve; - - function defineCurve(name, options) { - Object.defineProperty(curves, name, { - configurable: true, - enumerable: true, - get: function() { - var curve = new PresetCurve(options); - Object.defineProperty(curves, name, { - configurable: true, - enumerable: true, - value: curve - }); - return curve; - } - }); - } - - defineCurve('p192', { - type: 'short', - prime: 'p192', - p: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff', - a: 'ffffffff ffffffff ffffffff fffffffe ffffffff fffffffc', - b: '64210519 e59c80e7 0fa7e9ab 72243049 feb8deec c146b9b1', - n: 'ffffffff ffffffff ffffffff 99def836 146bc9b1 b4d22831', - hash: hash_1.sha256, - gRed: false, - g: [ - '188da80e b03090f6 7cbf20eb 43a18800 f4ff0afd 82ff1012', - '07192b95 ffc8da78 631011ed 6b24cdd5 73f977a1 1e794811' - ] - }); - - defineCurve('p224', { - type: 'short', - prime: 'p224', - p: 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001', - a: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff fffffffe', - b: 'b4050a85 0c04b3ab f5413256 5044b0b7 d7bfd8ba 270b3943 2355ffb4', - n: 'ffffffff ffffffff ffffffff ffff16a2 e0b8f03e 13dd2945 5c5c2a3d', - hash: hash_1.sha256, - gRed: false, - g: [ - 'b70e0cbd 6bb4bf7f 321390b9 4a03c1d3 56c21122 343280d6 115c1d21', - 'bd376388 b5f723fb 4c22dfe6 cd4375a0 5a074764 44d58199 85007e34' - ] - }); - - defineCurve('p256', { - type: 'short', - prime: null, - p: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff', - a: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff fffffffc', - b: '5ac635d8 aa3a93e7 b3ebbd55 769886bc 651d06b0 cc53b0f6 3bce3c3e 27d2604b', - n: 'ffffffff 00000000 ffffffff ffffffff bce6faad a7179e84 f3b9cac2 fc632551', - hash: hash_1.sha256, - gRed: false, - g: [ - '6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296', - '4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5' - ] - }); - - defineCurve('p384', { - type: 'short', - prime: null, - p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'fffffffe ffffffff 00000000 00000000 ffffffff', - a: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'fffffffe ffffffff 00000000 00000000 fffffffc', - b: 'b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112 0314088f ' + - '5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef', - n: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff c7634d81 ' + - 'f4372ddf 581a0db2 48b0a77a ecec196a ccc52973', - hash: hash_1.sha384, - gRed: false, - g: [ - 'aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98 59f741e0 82542a38 ' + - '5502f25d bf55296c 3a545e38 72760ab7', - '3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c e9da3113 b5f0b8c0 ' + - '0a60b1ce 1d7e819d 7a431d7c 90ea0e5f' - ] - }); - - defineCurve('p521', { - type: 'short', - prime: null, - p: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff ffffffff', - a: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff fffffffc', - b: '00000051 953eb961 8e1c9a1f 929a21a0 b68540ee a2da725b ' + - '99b315f3 b8b48991 8ef109e1 56193951 ec7e937b 1652c0bd ' + - '3bb1bf07 3573df88 3d2c34f1 ef451fd4 6b503f00', - n: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff fffffffa 51868783 bf2f966b 7fcc0148 ' + - 'f709a5d0 3bb5c9b8 899c47ae bb6fb71e 91386409', - hash: hash_1.sha512, - gRed: false, - g: [ - '000000c6 858e06b7 0404e9cd 9e3ecb66 2395b442 9c648139 ' + - '053fb521 f828af60 6b4d3dba a14b5e77 efe75928 fe1dc127 ' + - 'a2ffa8de 3348b3c1 856a429b f97e7e31 c2e5bd66', - '00000118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd9 98f54449 ' + - '579b4468 17afbd17 273e662c 97ee7299 5ef42640 c550b901 ' + - '3fad0761 353c7086 a272c240 88be9476 9fd16650' - ] - }); - - // https://tools.ietf.org/html/rfc7748#section-4.1 - defineCurve('curve25519', { - type: 'mont', - prime: 'p25519', - p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', - a: '76d06', - b: '1', - n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', - cofactor: '8', - hash: hash_1.sha256, - gRed: false, - g: [ - '9' - ] - }); - - defineCurve('ed25519', { - type: 'edwards', - prime: 'p25519', - p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', - a: '-1', - c: '1', - // -121665 * (121666^(-1)) (mod P) - d: '52036cee2b6ffe73 8cc740797779e898 00700a4d4141d8ab 75eb4dca135978a3', - n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', - cofactor: '8', - hash: hash_1.sha256, - gRed: false, - g: [ - '216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a', - // 4/5 - '6666666666666666666666666666666666666666666666666666666666666658' - ] - }); - - // https://tools.ietf.org/html/rfc5639#section-3.4 - defineCurve('brainpoolP256r1', { - type: 'short', - prime: null, - p: 'A9FB57DB A1EEA9BC 3E660A90 9D838D72 6E3BF623 D5262028 2013481D 1F6E5377', - a: '7D5A0975 FC2C3057 EEF67530 417AFFE7 FB8055C1 26DC5C6C E94A4B44 F330B5D9', - b: '26DC5C6C E94A4B44 F330B5D9 BBD77CBF 95841629 5CF7E1CE 6BCCDC18 FF8C07B6', - n: 'A9FB57DB A1EEA9BC 3E660A90 9D838D71 8C397AA3 B561A6F7 901E0E82 974856A7', - hash: hash_1.sha256, // or 384, or 512 - gRed: false, - g: [ - '8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262', - '547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997' - ] - }); - - // https://tools.ietf.org/html/rfc5639#section-3.6 - defineCurve('brainpoolP384r1', { - type: 'short', - prime: null, - p: '8CB91E82 A3386D28 0F5D6F7E 50E641DF 152F7109 ED5456B4 12B1DA19 7FB71123' + - 'ACD3A729 901D1A71 87470013 3107EC53', - a: '7BC382C6 3D8C150C 3C72080A CE05AFA0 C2BEA28E 4FB22787 139165EF BA91F90F' + - '8AA5814A 503AD4EB 04A8C7DD 22CE2826', - b: '04A8C7DD 22CE2826 8B39B554 16F0447C 2FB77DE1 07DCD2A6 2E880EA5 3EEB62D5' + - '7CB43902 95DBC994 3AB78696 FA504C11', - n: '8CB91E82 A3386D28 0F5D6F7E 50E641DF 152F7109 ED5456B3 1F166E6C AC0425A7' + - 'CF3AB6AF 6B7FC310 3B883202 E9046565', - hash: hash_1.sha384, // or 512 - gRed: false, - g: [ - '1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10' + - 'E8E826E03436D646AAEF87B2E247D4AF1E', - '8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129' + - '280E4646217791811142820341263C5315' - ] - }); - - // https://tools.ietf.org/html/rfc5639#section-3.7 - defineCurve('brainpoolP512r1', { - type: 'short', - prime: null, - p: 'AADD9DB8 DBE9C48B 3FD4E6AE 33C9FC07 CB308DB3 B3C9D20E D6639CCA 70330871' + - '7D4D9B00 9BC66842 AECDA12A E6A380E6 2881FF2F 2D82C685 28AA6056 583A48F3', - a: '7830A331 8B603B89 E2327145 AC234CC5 94CBDD8D 3DF91610 A83441CA EA9863BC' + - '2DED5D5A A8253AA1 0A2EF1C9 8B9AC8B5 7F1117A7 2BF2C7B9 E7C1AC4D 77FC94CA', - b: '3DF91610 A83441CA EA9863BC 2DED5D5A A8253AA1 0A2EF1C9 8B9AC8B5 7F1117A7' + - '2BF2C7B9 E7C1AC4D 77FC94CA DC083E67 984050B7 5EBAE5DD 2809BD63 8016F723', - n: 'AADD9DB8 DBE9C48B 3FD4E6AE 33C9FC07 CB308DB3 B3C9D20E D6639CCA 70330870' + - '553E5C41 4CA92619 41866119 7FAC1047 1DB1D381 085DDADD B5879682 9CA90069', - hash: hash_1.sha512, - gRed: false, - g: [ - '81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D009' + - '8EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822', - '7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F81' + - '11B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892' - ] - }); - - // https://en.bitcoin.it/wiki/Secp256k1 - var pre; - try { - pre = secp256k1; - } catch (e) { - pre = undefined; - } - - defineCurve('secp256k1', { - type: 'short', - prime: 'k256', - p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f', - a: '0', - b: '7', - n: 'ffffffff ffffffff ffffffff fffffffe baaedce6 af48a03b bfd25e8c d0364141', - h: '1', - hash: hash_1.sha256, - - // Precomputed endomorphism - beta: '7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee', - lambda: '5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72', - basis: [ - { - a: '3086d221a7d46bcde86c90e49284eb15', - b: '-e4437ed6010e88286f547fa90abfe4c3' - }, - { - a: '114ca50f7a8e2f3f657c1108d9d44cfd8', - b: '3086d221a7d46bcde86c90e49284eb15' - } - ], - - gRed: false, - g: [ - '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', - '483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', - pre - ] - }); - }); - - function HmacDRBG(options) { - if (!(this instanceof HmacDRBG)) - return new HmacDRBG(options); - this.hash = options.hash; - this.predResist = !!options.predResist; - - this.outLen = this.hash.outSize; - this.minEntropy = options.minEntropy || this.hash.hmacStrength; - - this._reseed = null; - this.reseedInterval = null; - this.K = null; - this.V = null; - - var entropy = utils_1.toArray(options.entropy, options.entropyEnc || 'hex'); - var nonce = utils_1.toArray(options.nonce, options.nonceEnc || 'hex'); - var pers = utils_1.toArray(options.pers, options.persEnc || 'hex'); - minimalisticAssert(entropy.length >= (this.minEntropy / 8), - 'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits'); - this._init(entropy, nonce, pers); - } - var hmacDrbg = HmacDRBG; - - HmacDRBG.prototype._init = function init(entropy, nonce, pers) { - var seed = entropy.concat(nonce).concat(pers); - - this.K = new Array(this.outLen / 8); - this.V = new Array(this.outLen / 8); - for (var i = 0; i < this.V.length; i++) { - this.K[i] = 0x00; - this.V[i] = 0x01; - } - - this._update(seed); - this._reseed = 1; - this.reseedInterval = 0x1000000000000; // 2^48 - }; - - HmacDRBG.prototype._hmac = function hmac() { - return new hash_1.hmac(this.hash, this.K); - }; - - HmacDRBG.prototype._update = function update(seed) { - var kmac = this._hmac() - .update(this.V) - .update([ 0x00 ]); - if (seed) - kmac = kmac.update(seed); - this.K = kmac.digest(); - this.V = this._hmac().update(this.V).digest(); - if (!seed) - return; - - this.K = this._hmac() - .update(this.V) - .update([ 0x01 ]) - .update(seed) - .digest(); - this.V = this._hmac().update(this.V).digest(); - }; - - HmacDRBG.prototype.reseed = function reseed(entropy, entropyEnc, add, addEnc) { - // Optional entropy enc - if (typeof entropyEnc !== 'string') { - addEnc = add; - add = entropyEnc; - entropyEnc = null; - } - - entropy = utils_1.toArray(entropy, entropyEnc); - add = utils_1.toArray(add, addEnc); - - minimalisticAssert(entropy.length >= (this.minEntropy / 8), - 'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits'); - - this._update(entropy.concat(add || [])); - this._reseed = 1; - }; - - HmacDRBG.prototype.generate = function generate(len, enc, add, addEnc) { - if (this._reseed > this.reseedInterval) - throw new Error('Reseed is required'); - - // Optional encoding - if (typeof enc !== 'string') { - addEnc = add; - add = enc; - enc = null; - } - - // Optional additional data - if (add) { - add = utils_1.toArray(add, addEnc || 'hex'); - this._update(add); - } - - var temp = []; - while (temp.length < len) { - this.V = this._hmac().update(this.V).digest(); - temp = temp.concat(this.V); - } - - var res = temp.slice(0, len); - this._update(add); - this._reseed++; - return utils_1.encode(res, enc); - }; - - var assert$5 = utils_1$1.assert; - - function KeyPair(ec, options) { - this.ec = ec; - this.priv = null; - this.pub = null; - - // KeyPair(ec, { priv: ..., pub: ... }) - if (options.priv) - this._importPrivate(options.priv, options.privEnc); - if (options.pub) - this._importPublic(options.pub, options.pubEnc); - } - var key = KeyPair; - - KeyPair.fromPublic = function fromPublic(ec, pub, enc) { - if (pub instanceof KeyPair) - return pub; - - return new KeyPair(ec, { - pub: pub, - pubEnc: enc - }); - }; - - KeyPair.fromPrivate = function fromPrivate(ec, priv, enc) { - if (priv instanceof KeyPair) - return priv; - - return new KeyPair(ec, { - priv: priv, - privEnc: enc - }); - }; - - // TODO: should not validate for X25519 - KeyPair.prototype.validate = function validate() { - var pub = this.getPublic(); - - if (pub.isInfinity()) - return { result: false, reason: 'Invalid public key' }; - if (!pub.validate()) - return { result: false, reason: 'Public key is not a point' }; - if (!pub.mul(this.ec.curve.n).isInfinity()) - return { result: false, reason: 'Public key * N != O' }; - - return { result: true, reason: null }; - }; - - KeyPair.prototype.getPublic = function getPublic(enc, compact) { - if (!this.pub) - this.pub = this.ec.g.mul(this.priv); - - if (!enc) - return this.pub; - - return this.pub.encode(enc, compact); - }; - - KeyPair.prototype.getPrivate = function getPrivate(enc) { - if (enc === 'hex') - return this.priv.toString(16, 2); - else - return this.priv; - }; - - KeyPair.prototype._importPrivate = function _importPrivate(key, enc) { - this.priv = new bn(key, enc || 16); - - // For Curve25519/Curve448 we have a specific procedure. - // TODO Curve448 - if (this.ec.curve.type === 'mont') { - var one = this.ec.curve.one; - var mask = one.ushln(255 - 3).sub(one).ushln(3); - this.priv = this.priv.or(one.ushln(255 - 1)); - this.priv = this.priv.and(mask); - } else - // Ensure that the priv won't be bigger than n, otherwise we may fail - // in fixed multiplication method - this.priv = this.priv.umod(this.ec.curve.n); - }; - - KeyPair.prototype._importPublic = function _importPublic(key, enc) { - if (key.x || key.y) { - // Montgomery points only have an `x` coordinate. - // Weierstrass/Edwards points on the other hand have both `x` and - // `y` coordinates. - if (this.ec.curve.type === 'mont') { - assert$5(key.x, 'Need x coordinate'); - } else if (this.ec.curve.type === 'short' || - this.ec.curve.type === 'edwards') { - assert$5(key.x && key.y, 'Need both x and y coordinate'); - } - this.pub = this.ec.curve.point(key.x, key.y); - return; - } - this.pub = this.ec.curve.decodePoint(key, enc); - }; - - // ECDH - KeyPair.prototype.derive = function derive(pub) { - return pub.mul(this.priv).getX(); - }; - - // ECDSA - KeyPair.prototype.sign = function sign(msg, enc, options) { - return this.ec.sign(msg, this, enc, options); - }; - - KeyPair.prototype.verify = function verify(msg, signature) { - return this.ec.verify(msg, signature, this); - }; - - KeyPair.prototype.inspect = function inspect() { - return ''; - }; - - var assert$6 = utils_1$1.assert; - - function Signature$1(options, enc) { - if (options instanceof Signature$1) - return options; - - if (this._importDER(options, enc)) - return; - - assert$6(options.r && options.s, 'Signature without r or s'); - this.r = new bn(options.r, 16); - this.s = new bn(options.s, 16); - if (options.recoveryParam === undefined) - this.recoveryParam = null; - else - this.recoveryParam = options.recoveryParam; - } - var signature$1 = Signature$1; - - function Position() { - this.place = 0; - } - - function getLength(buf, p) { - var initial = buf[p.place++]; - if (!(initial & 0x80)) { - return initial; - } - var octetLen = initial & 0xf; - var val = 0; - for (var i = 0, off = p.place; i < octetLen; i++, off++) { - val <<= 8; - val |= buf[off]; - } - p.place = off; - return val; - } - - function rmPadding(buf) { - var i = 0; - var len = buf.length - 1; - while (!buf[i] && !(buf[i + 1] & 0x80) && i < len) { - i++; - } - if (i === 0) { - return buf; - } - return buf.slice(i); - } - - Signature$1.prototype._importDER = function _importDER(data, enc) { - data = utils_1$1.toArray(data, enc); - var p = new Position(); - if (data[p.place++] !== 0x30) { - return false; - } - var len = getLength(data, p); - if ((len + p.place) !== data.length) { - return false; - } - if (data[p.place++] !== 0x02) { - return false; - } - var rlen = getLength(data, p); - var r = data.slice(p.place, rlen + p.place); - p.place += rlen; - if (data[p.place++] !== 0x02) { - return false; - } - var slen = getLength(data, p); - if (data.length !== slen + p.place) { - return false; - } - var s = data.slice(p.place, slen + p.place); - if (r[0] === 0 && (r[1] & 0x80)) { - r = r.slice(1); - } - if (s[0] === 0 && (s[1] & 0x80)) { - s = s.slice(1); - } - - this.r = new bn(r); - this.s = new bn(s); - this.recoveryParam = null; - - return true; - }; - - function constructLength(arr, len) { - if (len < 0x80) { - arr.push(len); - return; - } - var octets = 1 + (Math.log(len) / Math.LN2 >>> 3); - arr.push(octets | 0x80); - while (--octets) { - arr.push((len >>> (octets << 3)) & 0xff); - } - arr.push(len); - } - - Signature$1.prototype.toDER = function toDER(enc) { - var r = this.r.toArray(); - var s = this.s.toArray(); - - // Pad values - if (r[0] & 0x80) - r = [ 0 ].concat(r); - // Pad values - if (s[0] & 0x80) - s = [ 0 ].concat(s); - - r = rmPadding(r); - s = rmPadding(s); - - while (!s[0] && !(s[1] & 0x80)) { - s = s.slice(1); - } - var arr = [ 0x02 ]; - constructLength(arr, r.length); - arr = arr.concat(r); - arr.push(0x02); - constructLength(arr, s.length); - var backHalf = arr.concat(s); - var res = [ 0x30 ]; - constructLength(res, backHalf.length); - res = res.concat(backHalf); - return utils_1$1.encode(res, enc); - }; - - var assert$7 = utils_1$1.assert; - - - - - function EC(options) { - if (!(this instanceof EC)) - return new EC(options); - - // Shortcut `elliptic.ec(curve-name)` - if (typeof options === 'string') { - assert$7(curves_1.hasOwnProperty(options), 'Unknown curve ' + options); - - options = curves_1[options]; - } - - // Shortcut for `elliptic.ec(elliptic.curves.curveName)` - if (options instanceof curves_1.PresetCurve) - options = { curve: options }; - - this.curve = options.curve.curve; - this.n = this.curve.n; - this.nh = this.n.ushrn(1); - this.g = this.curve.g; - - // Point on curve - this.g = options.curve.g; - this.g.precompute(options.curve.n.bitLength() + 1); - - // Hash function for DRBG - this.hash = options.hash || options.curve.hash; - } - var ec = EC; - - EC.prototype.keyPair = function keyPair(options) { - return new key(this, options); - }; - - EC.prototype.keyFromPrivate = function keyFromPrivate(priv, enc) { - return key.fromPrivate(this, priv, enc); - }; - - EC.prototype.keyFromPublic = function keyFromPublic(pub, enc) { - return key.fromPublic(this, pub, enc); - }; - - EC.prototype.genKeyPair = function genKeyPair(options) { - if (!options) - options = {}; - - // Instantiate Hmac_DRBG - var drbg = new hmacDrbg({ - hash: this.hash, - pers: options.pers, - persEnc: options.persEnc || 'utf8', - entropy: options.entropy || brorand(this.hash.hmacStrength), - entropyEnc: options.entropy && options.entropyEnc || 'utf8', - nonce: this.n.toArray() - }); - - // Key generation for curve25519 is simpler - if (this.curve.type === 'mont') { - var priv = new bn(drbg.generate(32)); - return this.keyFromPrivate(priv); - } - - var bytes = this.n.byteLength(); - var ns2 = this.n.sub(new bn(2)); - do { - var priv = new bn(drbg.generate(bytes)); - if (priv.cmp(ns2) > 0) - continue; - - priv.iaddn(1); - return this.keyFromPrivate(priv); - } while (true); - }; - - EC.prototype._truncateToN = function truncateToN(msg, truncOnly, bitSize) { - bitSize = bitSize || msg.byteLength() * 8; - var delta = bitSize - this.n.bitLength(); - if (delta > 0) - msg = msg.ushrn(delta); - if (!truncOnly && msg.cmp(this.n) >= 0) - return msg.sub(this.n); - else - return msg; - }; - - EC.prototype.truncateMsg = function truncateMSG(msg) { - // Bit size is only determined correctly for Uint8Arrays and hex strings - var bitSize; - if (msg instanceof Uint8Array) { - bitSize = msg.byteLength * 8; - msg = this._truncateToN(new bn(msg, 16), false, bitSize); - } else if (typeof msg === 'string') { - bitSize = msg.length * 4; - msg = this._truncateToN(new bn(msg, 16), false, bitSize); - } else { - msg = this._truncateToN(new bn(msg, 16)); - } - return msg; - }; - - EC.prototype.sign = function sign(msg, key, enc, options) { - if (typeof enc === 'object') { - options = enc; - enc = null; - } - if (!options) - options = {}; - - key = this.keyFromPrivate(key, enc); - msg = this.truncateMsg(msg); - - // Zero-extend key to provide enough entropy - var bytes = this.n.byteLength(); - var bkey = key.getPrivate().toArray('be', bytes); - - // Zero-extend nonce to have the same byte size as N - var nonce = msg.toArray('be', bytes); - - // Instantiate Hmac_DRBG - var drbg = new hmacDrbg({ - hash: this.hash, - entropy: bkey, - nonce: nonce, - pers: options.pers, - persEnc: options.persEnc || 'utf8' - }); - - // Number of bytes to generate - var ns1 = this.n.sub(new bn(1)); - - for (var iter = 0; true; iter++) { - var k = options.k ? - options.k(iter) : - new bn(drbg.generate(this.n.byteLength())); - k = this._truncateToN(k, true); - if (k.cmpn(1) <= 0 || k.cmp(ns1) >= 0) - continue; - - var kp = this.g.mul(k); - if (kp.isInfinity()) - continue; - - var kpX = kp.getX(); - var r = kpX.umod(this.n); - if (r.cmpn(0) === 0) - continue; - - var s = k.invm(this.n).mul(r.mul(key.getPrivate()).iadd(msg)); - s = s.umod(this.n); - if (s.cmpn(0) === 0) - continue; - - var recoveryParam = (kp.getY().isOdd() ? 1 : 0) | - (kpX.cmp(r) !== 0 ? 2 : 0); - - // Use complement of `s`, if it is > `n / 2` - if (options.canonical && s.cmp(this.nh) > 0) { - s = this.n.sub(s); - recoveryParam ^= 1; - } - - return new signature$1({ r: r, s: s, recoveryParam: recoveryParam }); - } - }; - - EC.prototype.verify = function verify(msg, signature, key, enc) { - key = this.keyFromPublic(key, enc); - signature = new signature$1(signature, 'hex'); - // Fallback to the old code - var ret = this._verify(this.truncateMsg(msg), signature, key) || - this._verify(this._truncateToN(new bn(msg, 16)), signature, key); - return ret; - }; - - EC.prototype._verify = function _verify(msg, signature, key) { - // Perform primitive values validation - var r = signature.r; - var s = signature.s; - if (r.cmpn(1) < 0 || r.cmp(this.n) >= 0) - return false; - if (s.cmpn(1) < 0 || s.cmp(this.n) >= 0) - return false; - - // Validate signature - var sinv = s.invm(this.n); - var u1 = sinv.mul(msg).umod(this.n); - var u2 = sinv.mul(r).umod(this.n); - - if (!this.curve._maxwellTrick) { - var p = this.g.mulAdd(u1, key.getPublic(), u2); - if (p.isInfinity()) - return false; - - return p.getX().umod(this.n).cmp(r) === 0; - } - - // NOTE: Greg Maxwell's trick, inspired by: - // https://git.io/vad3K - - var p = this.g.jmulAdd(u1, key.getPublic(), u2); - if (p.isInfinity()) - return false; - - // Compare `p.x` of Jacobian point with `r`, - // this will do `p.x == r * p.z^2` instead of multiplying `p.x` by the - // inverse of `p.z^2` - return p.eqXToP(r); - }; - - EC.prototype.recoverPubKey = function(msg, signature, j, enc) { - assert$7((3 & j) === j, 'The recovery param is more than two bits'); - signature = new signature$1(signature, enc); - - var n = this.n; - var e = new bn(msg); - var r = signature.r; - var s = signature.s; - - // A set LSB signifies that the y-coordinate is odd - var isYOdd = j & 1; - var isSecondKey = j >> 1; - if (r.cmp(this.curve.p.umod(this.curve.n)) >= 0 && isSecondKey) - throw new Error('Unable to find sencond key candinate'); - - // 1.1. Let x = r + jn. - if (isSecondKey) - r = this.curve.pointFromX(r.add(this.curve.n), isYOdd); - else - r = this.curve.pointFromX(r, isYOdd); - - var rInv = signature.r.invm(n); - var s1 = n.sub(e).mul(rInv).umod(n); - var s2 = s.mul(rInv).umod(n); - - // 1.6.1 Compute Q = r^-1 (sR - eG) - // Q = r^-1 (sR + -eG) - return this.g.mulAdd(s1, r, s2); - }; - - EC.prototype.getKeyRecoveryParam = function(e, signature, Q, enc) { - signature = new signature$1(signature, enc); - if (signature.recoveryParam !== null) - return signature.recoveryParam; - - for (var i = 0; i < 4; i++) { - var Qprime; - try { - Qprime = this.recoverPubKey(e, signature, i); - } catch (e) { - continue; - } - - if (Qprime.eq(Q)) - return i; - } - throw new Error('Unable to find valid recovery factor'); - }; - - var assert$8 = utils_1$1.assert; - var parseBytes = utils_1$1.parseBytes; - var cachedProperty = utils_1$1.cachedProperty; - - /** - * @param {EDDSA} eddsa - instance - * @param {Object} params - public/private key parameters - * - * @param {Array} [params.secret] - secret seed bytes - * @param {Point} [params.pub] - public key point (aka `A` in eddsa terms) - * @param {Array} [params.pub] - public key point encoded as bytes - * - */ - function KeyPair$1(eddsa, params) { - this.eddsa = eddsa; - if (params.hasOwnProperty('secret')) - this._secret = parseBytes(params.secret); - if (eddsa.isPoint(params.pub)) - this._pub = params.pub; - else { - this._pubBytes = parseBytes(params.pub); - if (this._pubBytes && this._pubBytes.length === 33 && - this._pubBytes[0] === 0x40) - this._pubBytes = this._pubBytes.slice(1, 33); - if (this._pubBytes && this._pubBytes.length !== 32) - throw new Error('Unknown point compression format'); - } - } - - KeyPair$1.fromPublic = function fromPublic(eddsa, pub) { - if (pub instanceof KeyPair$1) - return pub; - return new KeyPair$1(eddsa, { pub: pub }); - }; - - KeyPair$1.fromSecret = function fromSecret(eddsa, secret) { - if (secret instanceof KeyPair$1) - return secret; - return new KeyPair$1(eddsa, { secret: secret }); - }; - - KeyPair$1.prototype.secret = function secret() { - return this._secret; - }; - - cachedProperty(KeyPair$1, 'pubBytes', function pubBytes() { - return this.eddsa.encodePoint(this.pub()); - }); - - cachedProperty(KeyPair$1, 'pub', function pub() { - if (this._pubBytes) - return this.eddsa.decodePoint(this._pubBytes); - return this.eddsa.g.mul(this.priv()); - }); - - cachedProperty(KeyPair$1, 'privBytes', function privBytes() { - var eddsa = this.eddsa; - var hash = this.hash(); - var lastIx = eddsa.encodingLength - 1; - - // https://tools.ietf.org/html/rfc8032#section-5.1.5 - var a = hash.slice(0, eddsa.encodingLength); - a[0] &= 248; - a[lastIx] &= 127; - a[lastIx] |= 64; - - return a; - }); - - cachedProperty(KeyPair$1, 'priv', function priv() { - return this.eddsa.decodeInt(this.privBytes()); - }); - - cachedProperty(KeyPair$1, 'hash', function hash() { - return this.eddsa.hash().update(this.secret()).digest(); - }); - - cachedProperty(KeyPair$1, 'messagePrefix', function messagePrefix() { - return this.hash().slice(this.eddsa.encodingLength); - }); - - KeyPair$1.prototype.sign = function sign(message) { - assert$8(this._secret, 'KeyPair can only verify'); - return this.eddsa.sign(message, this); - }; - - KeyPair$1.prototype.verify = function verify(message, sig) { - return this.eddsa.verify(message, sig, this); - }; - - KeyPair$1.prototype.getSecret = function getSecret(enc) { - assert$8(this._secret, 'KeyPair is public only'); - return utils_1$1.encode(this.secret(), enc); - }; - - KeyPair$1.prototype.getPublic = function getPublic(enc, compact) { - return utils_1$1.encode((compact ? [ 0x40 ] : []).concat(this.pubBytes()), enc); - }; - - var key$1 = KeyPair$1; - - var assert$9 = utils_1$1.assert; - var cachedProperty$1 = utils_1$1.cachedProperty; - var parseBytes$1 = utils_1$1.parseBytes; - - /** - * @param {EDDSA} eddsa - eddsa instance - * @param {Array|Object} sig - - * @param {Array|Point} [sig.R] - R point as Point or bytes - * @param {Array|bn} [sig.S] - S scalar as bn or bytes - * @param {Array} [sig.Rencoded] - R point encoded - * @param {Array} [sig.Sencoded] - S scalar encoded - */ - function Signature$2(eddsa, sig) { - this.eddsa = eddsa; - - if (typeof sig !== 'object') - sig = parseBytes$1(sig); - - if (Array.isArray(sig)) { - sig = { - R: sig.slice(0, eddsa.encodingLength), - S: sig.slice(eddsa.encodingLength) - }; - } - - assert$9(sig.R && sig.S, 'Signature without R or S'); - - if (eddsa.isPoint(sig.R)) - this._R = sig.R; - if (sig.S instanceof bn) - this._S = sig.S; - - this._Rencoded = Array.isArray(sig.R) ? sig.R : sig.Rencoded; - this._Sencoded = Array.isArray(sig.S) ? sig.S : sig.Sencoded; - } - - cachedProperty$1(Signature$2, 'S', function S() { - return this.eddsa.decodeInt(this.Sencoded()); - }); - - cachedProperty$1(Signature$2, 'R', function R() { - return this.eddsa.decodePoint(this.Rencoded()); - }); - - cachedProperty$1(Signature$2, 'Rencoded', function Rencoded() { - return this.eddsa.encodePoint(this.R()); - }); - - cachedProperty$1(Signature$2, 'Sencoded', function Sencoded() { - return this.eddsa.encodeInt(this.S()); - }); - - Signature$2.prototype.toBytes = function toBytes() { - return this.Rencoded().concat(this.Sencoded()); - }; - - Signature$2.prototype.toHex = function toHex() { - return utils_1$1.encode(this.toBytes(), 'hex').toUpperCase(); - }; - - var signature$2 = Signature$2; - - var assert$a = utils_1$1.assert; - var parseBytes$2 = utils_1$1.parseBytes; - - - - function EDDSA(curve) { - assert$a(curve === 'ed25519', 'only tested with ed25519 so far'); - - if (!(this instanceof EDDSA)) - return new EDDSA(curve); - - var curve = curves_1[curve].curve; - this.curve = curve; - this.g = curve.g; - this.g.precompute(curve.n.bitLength() + 1); - - this.pointClass = curve.point().constructor; - this.encodingLength = Math.ceil(curve.n.bitLength() / 8); - this.hash = hash_1.sha512; - } - - var eddsa$1 = EDDSA; - - /** - * @param {Array|String} message - message bytes - * @param {Array|String|KeyPair} secret - secret bytes or a keypair - * @returns {Signature} - signature - */ - EDDSA.prototype.sign = function sign(message, secret) { - message = parseBytes$2(message); - var key = this.keyFromSecret(secret); - var r = this.hashInt(key.messagePrefix(), message); - var R = this.g.mul(r); - var Rencoded = this.encodePoint(R); - var s_ = this.hashInt(Rencoded, key.pubBytes(), message) - .mul(key.priv()); - var S = r.add(s_).umod(this.curve.n); - return this.makeSignature({ R: R, S: S, Rencoded: Rencoded }); - }; - - /** - * @param {Array} message - message bytes - * @param {Array|String|Signature} sig - sig bytes - * @param {Array|String|Point|KeyPair} pub - public key - * @returns {Boolean} - true if public key matches sig of message - */ - EDDSA.prototype.verify = function verify(message, sig, pub) { - message = parseBytes$2(message); - sig = this.makeSignature(sig); - var key = this.keyFromPublic(pub); - var h = this.hashInt(sig.Rencoded(), key.pubBytes(), message); - var SG = this.g.mul(sig.S()); - var RplusAh = sig.R().add(key.pub().mul(h)); - return RplusAh.eq(SG); - }; - - EDDSA.prototype.hashInt = function hashInt() { - var hash = this.hash(); - for (var i = 0; i < arguments.length; i++) - hash.update(arguments[i]); - return utils_1$1.intFromLE(hash.digest()).umod(this.curve.n); - }; - - EDDSA.prototype.keyPair = function keyPair(options) { - return new key$1(this, options); - }; - - EDDSA.prototype.keyFromPublic = function keyFromPublic(pub) { - return key$1.fromPublic(this, pub); - }; - - EDDSA.prototype.keyFromSecret = function keyFromSecret(secret) { - return key$1.fromSecret(this, secret); - }; - - EDDSA.prototype.genKeyPair = function genKeyPair(options) { - if (!options) - options = {}; - - // Instantiate Hmac_DRBG - var drbg = new hmacDrbg({ - hash: this.hash, - pers: options.pers, - persEnc: options.persEnc || 'utf8', - entropy: options.entropy || brorand(this.hash.hmacStrength), - entropyEnc: options.entropy && options.entropyEnc || 'utf8', - nonce: this.curve.n.toArray() - }); - - return this.keyFromSecret(drbg.generate(32)); - }; - - EDDSA.prototype.makeSignature = function makeSignature(sig) { - if (sig instanceof signature$2) - return sig; - return new signature$2(this, sig); - }; - - /** - * * https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03#section-5.2 - * - * EDDSA defines methods for encoding and decoding points and integers. These are - * helper convenience methods, that pass along to utility functions implied - * parameters. - * - */ - EDDSA.prototype.encodePoint = function encodePoint(point) { - var enc = point.getY().toArray('le', this.encodingLength); - enc[this.encodingLength - 1] |= point.getX().isOdd() ? 0x80 : 0; - return enc; - }; - - EDDSA.prototype.decodePoint = function decodePoint(bytes) { - bytes = utils_1$1.parseBytes(bytes); - - var lastIx = bytes.length - 1; - var normed = bytes.slice(0, lastIx).concat(bytes[lastIx] & ~0x80); - var xIsOdd = (bytes[lastIx] & 0x80) !== 0; - - var y = utils_1$1.intFromLE(normed); - return this.curve.pointFromY(y, xIsOdd); - }; - - EDDSA.prototype.encodeInt = function encodeInt(num) { - return num.toArray('le', this.encodingLength); - }; - - EDDSA.prototype.decodeInt = function decodeInt(bytes) { - return utils_1$1.intFromLE(bytes); - }; - - EDDSA.prototype.isPoint = function isPoint(val) { - return val instanceof this.pointClass; - }; - - var elliptic_1 = createCommonjsModule(function (module, exports) { - - var elliptic = exports; - - elliptic.utils = utils_1$1; - elliptic.rand = brorand; - elliptic.curve = curve_1; - elliptic.curves = curves_1; - - // Protocols - elliptic.ec = ec; - elliptic.eddsa = eddsa$1; - }); - - var elliptic$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - 'default': elliptic_1, - __moduleExports: elliptic_1 - }); - - exports.AEADEncryptedDataPacket = AEADEncryptedDataPacket; - exports.CleartextMessage = CleartextMessage; - exports.CompressedDataPacket = CompressedDataPacket; - exports.LiteralDataPacket = LiteralDataPacket; - exports.MarkerPacket = MarkerPacket; - exports.Message = Message; - exports.OnePassSignaturePacket = OnePassSignaturePacket; - exports.PacketList = PacketList; - exports.PrivateKey = PrivateKey; - exports.PublicKey = PublicKey; - exports.PublicKeyEncryptedSessionKeyPacket = PublicKeyEncryptedSessionKeyPacket; - exports.PublicKeyPacket = PublicKeyPacket; - exports.PublicSubkeyPacket = PublicSubkeyPacket; - exports.SecretKeyPacket = SecretKeyPacket; - exports.SecretSubkeyPacket = SecretSubkeyPacket; - exports.Signature = Signature; - exports.SignaturePacket = SignaturePacket; - exports.Subkey = Subkey; - exports.SymEncryptedIntegrityProtectedDataPacket = SymEncryptedIntegrityProtectedDataPacket; - exports.SymEncryptedSessionKeyPacket = SymEncryptedSessionKeyPacket; - exports.SymmetricallyEncryptedDataPacket = SymmetricallyEncryptedDataPacket; - exports.TrustPacket = TrustPacket; - exports.UserAttributePacket = UserAttributePacket; - exports.UserIDPacket = UserIDPacket; - exports.armor = armor; - exports.config = defaultConfig; - exports.createCleartextMessage = createCleartextMessage; - exports.createMessage = createMessage; - exports.decrypt = decrypt$4; - exports.decryptKey = decryptKey; - exports.decryptSessionKeys = decryptSessionKeys; - exports.encrypt = encrypt$4; - exports.encryptKey = encryptKey; - exports.encryptSessionKey = encryptSessionKey; - exports.enums = enums; - exports.generateKey = generateKey; - exports.generateSessionKey = generateSessionKey$1; - exports.readCleartextMessage = readCleartextMessage; - exports.readKey = readKey; - exports.readKeys = readKeys; - exports.readMessage = readMessage; - exports.readPrivateKey = readPrivateKey; - exports.readPrivateKeys = readPrivateKeys; - exports.readSignature = readSignature; - exports.reformatKey = reformatKey; - exports.revokeKey = revokeKey; - exports.sign = sign$5; - exports.unarmor = unarmor; - exports.verify = verify$5; - - // -----BEGIN ADDED BY FLOWCRYPT---- - exports.Hash = Hash; - exports.Sha1 = Sha1; - exports.Sha256 = Sha256; - exports.readToEnd = readToEnd; - exports.util = util; - // -----END ADDED BY FLOWCRYPT----- - - Object.defineProperty(exports, '__esModule', { value: true }); - - return exports; - -}({})); diff --git a/Core/tooling/build.sh b/Core/tooling/build.sh index ca86f0aed..f09e71fe2 100755 --- a/Core/tooling/build.sh +++ b/Core/tooling/build.sh @@ -4,8 +4,6 @@ set -euxo pipefail # fix openpgp in node_modules cp -f source/core/types/openpgp.d.ts node_modules/openpgp -cp -f source/lib/openpgp/openpgp.js node_modules/openpgp/dist -cp -f source/lib/openpgp/node/openpgp.js node_modules/openpgp/dist/node for f in openpgp.min.js openpgp.min.js.map openpgp.min.mjs openpgp.min.mjs.map openpgp.mjs; do if [ -f node_modules/openpgp/dist/$f ]; then rm -f node_modules/openpgp/dist/$f ; fi if [ -f node_modules/openpgp/dist/node/$f ]; then rm -f node_modules/openpgp/dist/node/$f ; fi @@ -25,23 +23,27 @@ exports.util = util; dist_js=node_modules/openpgp/dist/openpgp.js tmp_js=${dist_js}.tmp -fc_added=$(grep 'BEGIN ADDED BY FLOWCRYPT' ${tmp_js} | wc -l) -if [ $fc_added = 0]; then +set +e +fc_added=$(grep 'BEGIN ADDED BY FLOWCRYPT' ${dist_js} | wc -l) +set -e +if [ $fc_added = 0 ]; then n=$(grep -n 'exports.verify' ${dist_js} | cut -f1 -d':') head -$n ${dist_js} >${tmp_js} echo "$extra_exports" >>${tmp_js} tail -n +$((n+1)) ${dist_js} >>${tmp_js} + mv -f ${tmp_js} ${dist_js} fi -mv -f ${tmp_js} ${dist_js} dist_js=node_modules/openpgp/dist/node/openpgp.js tmp_js=${dist_js}.tmp +set +e fc_added=$(grep 'BEGIN ADDED BY FLOWCRYPT' ${dist_js} | wc -l) -if [ $fc_added = 0]; then +set -e +if [ $fc_added = 0 ]; then cp -f ${dist_js} ${tmp_js} echo "$extra_exports" >>${tmp_js} + mv -f ${tmp_js} ${dist_js} fi -mv -f ${tmp_js} ${dist_js} # clean up rm -rf build/ts build/bundles build/final/* diff --git a/Core/tooling/fix-bundles.js b/Core/tooling/fix-bundles.js index 830e080fb..69346c190 100644 --- a/Core/tooling/fix-bundles.js +++ b/Core/tooling/fix-bundles.js @@ -70,7 +70,7 @@ const replace = (libSrc, regex, replacement) => { return libSrc.replace(regex, replacement); } -let openpgpLib = fs.readFileSync(`${libsDir}/openpgp/node/openpgp.js`).toString(); +let openpgpLib = fs.readFileSync('./node_modules/openpgp/dist/node/openpgp.js').toString(); const openpgpLibNodeDev = openpgpLib; // dev node runs without any host, no modifications needed /* From 827031876dfeffde044a269bfed7da2b44d93781 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 08:01:01 +0200 Subject: [PATCH 092/179] wip --- Core/package-lock.json | 45 ------------------------------------------ Core/package.json | 1 - 2 files changed, 46 deletions(-) diff --git a/Core/package-lock.json b/Core/package-lock.json index 6e27b73e7..c09ebd6a7 100644 --- a/Core/package-lock.json +++ b/Core/package-lock.json @@ -9,7 +9,6 @@ "version": "0.0.1", "license": "SEE LICENSE IN ", "dependencies": { - "@openpgp/web-stream-tools": "^0.0.9", "encoding-japanese": "^1.0.30", "openpgp": "5.1.0", "sanitize-html": "2.6.1", @@ -356,14 +355,6 @@ "node": ">=10.0.0" } }, - "node_modules/@mattiasbuelens/web-streams-adapter": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@mattiasbuelens/web-streams-adapter/-/web-streams-adapter-0.1.0.tgz", - "integrity": "sha512-oV4PyZfwJNtmFWhvlJLqYIX1Nn22ML8FZpS16ZUKv0hg7414xV1fjsGqxQzLT2dyK92TKxsJSwMOd7VNHAtPmA==", - "engines": { - "node": ">= 12" - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -399,15 +390,6 @@ "node": ">= 8" } }, - "node_modules/@openpgp/web-stream-tools": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@openpgp/web-stream-tools/-/web-stream-tools-0.0.9.tgz", - "integrity": "sha512-GEKuXpQRshUqgKH4sMcwYbHolxaUSHIowcIMd02EsnLv4q5acP0z9pRUy3kjV0ZyRPgyD0vXAy60Rf0MPKoCMw==", - "dependencies": { - "@mattiasbuelens/web-streams-adapter": "~0.1.0", - "web-streams-polyfill": "~3.0.3" - } - }, "node_modules/@types/chai": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.0.tgz", @@ -7931,14 +7913,6 @@ "node": ">=8.0" } }, - "node_modules/web-streams-polyfill": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.0.3.tgz", - "integrity": "sha512-d2H/t0eqRNM4w2WvmTdoeIvzAUSpK7JmATB8Nr2lb7nQ9BTIJVjbQ/TRFVEh2gUH1HwclPdoPtfMoFfetXaZnA==", - "engines": { - "node": ">= 8" - } - }, "node_modules/webpack": { "version": "4.46.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", @@ -8777,11 +8751,6 @@ "integrity": "sha512-ws57AidsDvREKrZKYffXddNkyaF14iHNHm8VQnZH6t99E8gczjNN0GpvcGny0imC80yQ0tHz1xVUKk/KFQSUyA==", "dev": true }, - "@mattiasbuelens/web-streams-adapter": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@mattiasbuelens/web-streams-adapter/-/web-streams-adapter-0.1.0.tgz", - "integrity": "sha512-oV4PyZfwJNtmFWhvlJLqYIX1Nn22ML8FZpS16ZUKv0hg7414xV1fjsGqxQzLT2dyK92TKxsJSwMOd7VNHAtPmA==" - }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -8808,15 +8777,6 @@ "fastq": "^1.6.0" } }, - "@openpgp/web-stream-tools": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@openpgp/web-stream-tools/-/web-stream-tools-0.0.9.tgz", - "integrity": "sha512-GEKuXpQRshUqgKH4sMcwYbHolxaUSHIowcIMd02EsnLv4q5acP0z9pRUy3kjV0ZyRPgyD0vXAy60Rf0MPKoCMw==", - "requires": { - "@mattiasbuelens/web-streams-adapter": "~0.1.0", - "web-streams-polyfill": "~3.0.3" - } - }, "@types/chai": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.0.tgz", @@ -14911,11 +14871,6 @@ "chokidar": "^2.1.8" } }, - "web-streams-polyfill": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.0.3.tgz", - "integrity": "sha512-d2H/t0eqRNM4w2WvmTdoeIvzAUSpK7JmATB8Nr2lb7nQ9BTIJVjbQ/TRFVEh2gUH1HwclPdoPtfMoFfetXaZnA==" - }, "webpack": { "version": "4.46.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", diff --git a/Core/package.json b/Core/package.json index ef1031b37..feb601e8a 100644 --- a/Core/package.json +++ b/Core/package.json @@ -3,7 +3,6 @@ "version": "0.0.1", "description": "TypeScript core for FlowCrypt iOS internal use", "dependencies": { - "@openpgp/web-stream-tools": "^0.0.9", "encoding-japanese": "^1.0.30", "openpgp": "5.1.0", "sanitize-html": "2.6.1", From 845cda575309f55f3ef1d6dd895d57b644851025 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 08:10:29 +0200 Subject: [PATCH 093/179] wip --- Core/failed_tests.txt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 Core/failed_tests.txt diff --git a/Core/failed_tests.txt b/Core/failed_tests.txt new file mode 100644 index 000000000..cc59b7d5b --- /dev/null +++ b/Core/failed_tests.txt @@ -0,0 +1,7 @@ + ✖ parseKeys Rejected promise returned by test + ✖ parseKeys - expiration and date last updated Rejected promise returned by test + ✖ parseKeys - revoked Rejected promise returned by test + ✖ generateKey Rejected promise returned by test + ✖ encryptKey Rejected promise returned by test + ✖ parseDecryptMsg compat mime-email-plain-with-pubkey Rejected promise returned by test + ✖ verify plain-text signed message that you edited after signing. This invalidates the signature. With correct key. (fail: signature mismatch) Rejected promise returned by test From c59c4bd8a9723af751efa6459cbbb508edea0b0f Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 08:12:22 +0200 Subject: [PATCH 094/179] wip --- Core/failed_tests.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Core/failed_tests.txt b/Core/failed_tests.txt index cc59b7d5b..8250b2a08 100644 --- a/Core/failed_tests.txt +++ b/Core/failed_tests.txt @@ -1,7 +1,7 @@ - ✖ parseKeys Rejected promise returned by test - ✖ parseKeys - expiration and date last updated Rejected promise returned by test - ✖ parseKeys - revoked Rejected promise returned by test - ✖ generateKey Rejected promise returned by test - ✖ encryptKey Rejected promise returned by test - ✖ parseDecryptMsg compat mime-email-plain-with-pubkey Rejected promise returned by test - ✖ verify plain-text signed message that you edited after signing. This invalidates the signature. With correct key. (fail: signature mismatch) Rejected promise returned by test +[parseKeys] Rejected promise returned by test +[parseKeys - expiration and date last updated] Rejected promise returned by test +[parseKeys - revoked] Rejected promise returned by test +[generateKey] Rejected promise returned by test +[encryptKey] Rejected promise returned by test +[parseDecryptMsg compat mime-email-plain-with-pubkey] Rejected promise returned by test +[verify plain-text signed message that you edited after signing. This invalidates the signature. With correct key. (fail: signature mismatch)] Rejected promise returned by test From 6b69d1216d0fbb1b9afe789c4822b6abe117ee4a Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 08:17:50 +0200 Subject: [PATCH 095/179] wip --- Core/source/test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/source/test.ts b/Core/source/test.ts index b67c29f65..a6c66a617 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -334,7 +334,7 @@ ava.default('isEmailValid - false', async t => { t.pass(); }); -ava.default('parseKeys', async t => { +ava.default.only('parseKeys', async t => { const { pubKeys: [pubkey] } = getKeypairs('rsa1'); const { data, json } = parseResponse(await endpoints.parseKeys({}, [Buffer.from(pubkey)])); expect(json).to.deep.equal({ From b1b82ec6abb0f6597e0a82f66ce431a0927883cd Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 08:20:28 +0200 Subject: [PATCH 096/179] wip --- Core/source/test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/Core/source/test.ts b/Core/source/test.ts index a6c66a617..e9b839333 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -336,6 +336,7 @@ ava.default('isEmailValid - false', async t => { ava.default.only('parseKeys', async t => { const { pubKeys: [pubkey] } = getKeypairs('rsa1'); + console.log(pubkey); const { data, json } = parseResponse(await endpoints.parseKeys({}, [Buffer.from(pubkey)])); expect(json).to.deep.equal({ "format": "armored", From 78a5496e72398cd625386a91c39d5d336f590bea Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 08:21:25 +0200 Subject: [PATCH 097/179] wip --- Core/test.sh | 3 +++ 1 file changed, 3 insertions(+) create mode 100755 Core/test.sh diff --git a/Core/test.sh b/Core/test.sh new file mode 100755 index 000000000..6c4316609 --- /dev/null +++ b/Core/test.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +npm run test From d8de98503edf721316f7dd4dc8793277ccb695b9 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 08:40:26 +0200 Subject: [PATCH 098/179] wip --- Core/source/core/pgp-key.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index 42ddf2bf3..656c0d17d 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -365,6 +365,9 @@ export class PgpKey { allSignatures.push(...subKey.bindingSignatures); } allSignatures.sort((a, b) => (b.created ? b.created.getTime() : 0) - (a.created ? a.created.getTime() : 0)); + console.log(`nsig=${allSignatures.length}`); + console.log(`sigs=${JSON.stringify(allSignatures)}`); + for (const sig of allSignatures) console.log(sig.verified); const newestSig = allSignatures.find(sig => sig.verified === true); if (newestSig) { return newestSig.created ? newestSig.created.getTime() : 0; From 41b64e50ae68edd456054ddcecbefa14ea2c8f6c Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 09:09:50 +0200 Subject: [PATCH 099/179] wip --- Core/source/core/pgp-key.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index 656c0d17d..c71d2a89a 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -356,18 +356,21 @@ export class PgpKey { * This is used to figure out how recently was key updated, and if one key is newer than other. */ public static lastSig = async (key: Key): Promise => { + console.log((Object as any).__oid(key)); await key.getExpirationTime(); // will force all sigs to be verified const allSignatures: SignaturePacket[] = []; for (const user of key.users) { allSignatures.push(...user.selfCertifications); + console.log(`selfcerts=${user.selfCertifications.length}`); } for (const subKey of key.subkeys) { allSignatures.push(...subKey.bindingSignatures); + console.log(`sbb=${subKey.bindingSignatures.length}`); } allSignatures.sort((a, b) => (b.created ? b.created.getTime() : 0) - (a.created ? a.created.getTime() : 0)); console.log(`nsig=${allSignatures.length}`); console.log(`sigs=${JSON.stringify(allSignatures)}`); - for (const sig of allSignatures) console.log(sig.verified); + for (const sig of allSignatures) console.log(`${(Object as any).__oid(sig)} => ${sig.verified}`); const newestSig = allSignatures.find(sig => sig.verified === true); if (newestSig) { return newestSig.created ? newestSig.created.getTime() : 0; From bb07d61a94cb8c1bffabea9803df5dc498719bc2 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 21:42:42 +0200 Subject: [PATCH 100/179] wip --- Core/tooling/build.sh | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/Core/tooling/build.sh b/Core/tooling/build.sh index f09e71fe2..44440b01d 100755 --- a/Core/tooling/build.sh +++ b/Core/tooling/build.sh @@ -45,6 +45,41 @@ if [ $fc_added = 0 ]; then mv -f ${tmp_js} ${dist_js} fi +extra_defs=" +// -----BEGIN ADDED BY FLOWCRYPT----- + +export function readToEnd(input: MaybeStream, concat?: (list: T[]) => T): Promise; + +export namespace util { + // we can't copy this from openpgp.js into our sources (i.e. util.ts) because of LGPL + function uint8ArrayToString(bytes: Uint8Array): string; + function uint8ArrayToHex(bytes: Uint8Array): string; +} + +export class Hash { + public reset(): Hash; + public process(data: Uint8Array): Hash; + public finish(): Hash; + public result: Uint8Array; +} + +export class Sha1 extends Hash {} +export class Sha256 extends Hash {} + +// -----END ADDED BY FLOWCRYPT----- +" + +dist_ts=node_modules/openpgp/openpgp.d.ts +tmp_ts=${dist_js}.tmp +set +e +fc_added=$(grep 'BEGIN ADDED BY FLOWCRYPT' ${dist_ts} | wc -l) +set -e +if [ $fc_added = 0 ]; then + cp -f ${dist_ts} ${tmp_ts} + echo "$extra_defs" >>${tmp_ts} + mv -f ${tmp_ts} ${dist_ts} +fi + # clean up rm -rf build/ts build/bundles build/final/* mkdir -p build/final From a483fd591af55125676bd490ddf7b966fd1bbf89 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 21:43:34 +0200 Subject: [PATCH 101/179] wip --- Core/source/core/types/openpgp.d.ts | 911 ---------------------------- Core/tooling/build.sh | 1 - 2 files changed, 912 deletions(-) delete mode 100644 Core/source/core/types/openpgp.d.ts diff --git a/Core/source/core/types/openpgp.d.ts b/Core/source/core/types/openpgp.d.ts deleted file mode 100644 index 066818dba..000000000 --- a/Core/source/core/types/openpgp.d.ts +++ /dev/null @@ -1,911 +0,0 @@ -/** - * Type definitions for OpenPGP.js http://openpgpjs.org/ - * - * Contributors: - * - FlowCrypt a. s. - * - Guillaume Lacasa - * - Errietta Kostala - */ - -/* ############## v5 KEY #################### */ -// The Key and PublicKey types can be used interchangably since TS cannot detect the difference, as they have the same class properties. -// The declared readKey(s) return type is Key instead of a PublicKey since it seems more obvious that a Key can be cast to a PrivateKey. -export function readKey(options: { armoredKey: string, config?: PartialConfig }): Promise; -export function readKey(options: { binaryKey: Uint8Array, config?: PartialConfig }): Promise; -export function readKeys(options: { armoredKeys: string, config?: PartialConfig }): Promise; -export function readKeys(options: { binaryKeys: Uint8Array, config?: PartialConfig }): Promise; -export function readPrivateKey(options: { armoredKey: string, config?: PartialConfig }): Promise; -export function readPrivateKey(options: { binaryKey: Uint8Array, config?: PartialConfig }): Promise; -export function readPrivateKeys(options: { armoredKeys: string, config?: PartialConfig }): Promise; -export function readPrivateKeys(options: { binaryKeys: Uint8Array, config?: PartialConfig }): Promise; -export function generateKey(options: KeyOptions & { format?: 'armored' }): Promise & { revocationCertificate: string }>; -export function generateKey(options: KeyOptions & { format: 'binary' }): Promise & { revocationCertificate: string }>; -export function generateKey(options: KeyOptions & { format: 'object' }): Promise; -export function decryptKey(options: { privateKey: PrivateKey; passphrase?: MaybeArray; config?: PartialConfig }): Promise; -export function encryptKey(options: { privateKey: PrivateKey; passphrase?: MaybeArray; config?: PartialConfig }): Promise; -export function reformatKey(options: { privateKey: PrivateKey; userIDs?: MaybeArray; passphrase?: string; keyExpirationTime?: number; date?: Date, format?: 'armored', config?: PartialConfig }): Promise & { revocationCertificate: string }>; -export function reformatKey(options: { privateKey: PrivateKey; userIDs?: MaybeArray; passphrase?: string; keyExpirationTime?: number; date?: Date, format: 'binary', config?: PartialConfig }): Promise & { revocationCertificate: string }>; -export function reformatKey(options: { privateKey: PrivateKey; userIDs?: MaybeArray; passphrase?: string; keyExpirationTime?: number; date?: Date, format: 'object', config?: PartialConfig }): Promise; -export function revokeKey(options: { key: PrivateKey, reasonForRevocation?: ReasonForRevocation, date?: Date, format?: 'armored', config?: PartialConfig }): Promise>; -export function revokeKey(options: { key: PrivateKey, reasonForRevocation?: ReasonForRevocation, date?: Date, format: 'binary', config?: PartialConfig }): Promise>; -export function revokeKey(options: { key: PrivateKey, reasonForRevocation?: ReasonForRevocation, date?: Date, format: 'object', config?: PartialConfig }): Promise; -export function revokeKey(options: { key: PrivateKey, revocationCertificate: string, date?: Date, format?: 'armored', config?: PartialConfig }): Promise>; -export function revokeKey(options: { key: PrivateKey, revocationCertificate: string, date?: Date, format: 'binary', config?: PartialConfig }): Promise>; -export function revokeKey(options: { key: PrivateKey, revocationCertificate: string, date?: Date, format: 'object', config?: PartialConfig }): Promise; -export function revokeKey(options: { key: PublicKey, revocationCertificate: string, date?: Date, format?: 'armored', config?: PartialConfig }): Promise<{ publicKey: string, privateKey: null }>; -export function revokeKey(options: { key: PublicKey, revocationCertificate: string, date?: Date, format: 'binary', config?: PartialConfig }): Promise<{ publicKey: Uint8Array, privateKey: null }>; -export function revokeKey(options: { key: PublicKey, revocationCertificate: string, date?: Date, format: 'object', config?: PartialConfig }): Promise<{ publicKey: PublicKey, privateKey: null }>; - -export abstract class Key { - public readonly keyPacket: PublicKeyPacket | SecretKeyPacket; - public subkeys: Subkey[]; // do not add/replace users directly - public users: User[]; // do not add/replace subkeys directly - public revocationSignatures: SignaturePacket[]; - public write(): Uint8Array; - public armor(config?: Config): string; - public getExpirationTime(userID?: UserID, config?: Config): Promise; - public getKeyIDs(): KeyID[]; - public getPrimaryUser(date?: Date, userID?: UserID, config?: Config): Promise; // throws on error - public getUserIDs(): string[]; - public isPrivate(): this is PrivateKey; - public toPublic(): PublicKey; - // NB: the order of the `update` declarations matters, since PublicKey includes PrivateKey - public update(sourceKey: PrivateKey, date?: Date, config?: Config): Promise; - public update(sourceKey: PublicKey, date?: Date, config?: Config): Promise; - public signPrimaryUser(privateKeys: PrivateKey[], date?: Date, userID?: UserID, config?: Config): Promise - public signAllUsers(privateKeys: PrivateKey[], date?: Date, config?: Config): Promise - public verifyPrimaryKey(date?: Date, userID?: UserID, config?: Config): Promise; // throws on error - public verifyPrimaryUser(publicKeys: PublicKey[], date?: Date, userIDs?: UserID, config?: Config): Promise<{ keyID: KeyID, valid: boolean | null }[]>; - public verifyAllUsers(publicKeys: PublicKey[], date?: Date, config?: Config): Promise<{ userID: string, keyID: KeyID, valid: boolean | null }[]>; - // -----BEGIN MODIFIED BY FLOWCRYPT----- - // Make this permanent: https://github.com/openpgpjs/openpgpjs/pull/1486 - public isRevoked(signature?: SignaturePacket, key?: AnyKeyPacket, date?: Date, config?: Config): Promise; - // -----END MODIFIED BY FLOWCRYPT----- - public getRevocationCertificate(date?: Date, config?: Config): Promise | undefined>; - public getEncryptionKey(keyID?: KeyID, date?: Date | null, userID?: UserID, config?: Config): Promise; - public getSigningKey(keyID?: KeyID, date?: Date | null, userID?: UserID, config?: Config): Promise; - public getKeys(keyID?: KeyID): (this | Subkey)[]; - public getSubkeys(keyID?: KeyID): Subkey[]; - public getFingerprint(): string; - public getCreationTime(): Date; - public getAlgorithmInfo(): AlgorithmInfo; - public getKeyID(): KeyID; - public toPacketList(): PacketList; -} - -type AllowedKeyPackets = PublicKeyPacket | PublicSubkeyPacket | SecretKeyPacket | SecretSubkeyPacket | UserIDPacket | UserAttributePacket | SignaturePacket; -export class PublicKey extends Key { - constructor(packetlist: PacketList); -} - -export class PrivateKey extends PublicKey { - constructor(packetlist: PacketList); - public revoke(reason?: ReasonForRevocation, date?: Date, config?: Config): Promise; - public isDecrypted(): boolean; - public addSubkey(options: SubkeyOptions): Promise; - public getDecryptionKeys(keyID?: KeyID, date?: Date | null, userID?: UserID, config?: Config): Promise - public update(sourceKey: PublicKey, date?: Date, config?: Config): Promise; -} - -export class Subkey { - constructor(subkeyPacket: SecretSubkeyPacket | PublicSubkeyPacket, mainKey: PublicKey); - public readonly keyPacket: SecretSubkeyPacket | PublicSubkeyPacket; - public readonly mainKey: PublicKey; - public bindingSignatures: SignaturePacket[]; - public revocationSignatures: SignaturePacket[]; - public verify(date?: Date, config?: Config): Promise; - public isDecrypted(): boolean; - public getFingerprint(): string; - public getCreationTime(): Date; - public getAlgorithmInfo(): AlgorithmInfo; - public getKeyID(): KeyID; -} - -export interface User { - userID: UserIDPacket | null; - userAttribute: UserAttributePacket | null; - selfCertifications: SignaturePacket[]; - otherCertifications: SignaturePacket[]; - revocationSignatures: SignaturePacket[]; -} - -export interface PrimaryUser { - index: number; - user: User; -} - -type AlgorithmInfo = { - algorithm: enums.publicKeyNames; - bits?: number; - curve?: EllipticCurveName; -}; - -/* ############## v5 SIG #################### */ - -export function readSignature(options: { armoredSignature: string, config?: PartialConfig }): Promise; -export function readSignature(options: { binarySignature: Uint8Array, config?: PartialConfig }): Promise; - -export class Signature { - public readonly packets: PacketList; - constructor(packetlist: PacketList); - public write(): MaybeStream; - public armor(config?: Config): string; - public getSigningKeyIDs(): Array; -} - -interface VerificationResult { - keyID: KeyID; - verified: Promise; // throws on invalid signature - signature: Promise; -} - -/* ############## v5 CLEARTEXT #################### */ - -export function readCleartextMessage(options: { cleartextMessage: string, config?: PartialConfig }): Promise; - -export function createCleartextMessage(options: { text: string }): Promise; - -/** Class that represents an OpenPGP cleartext signed message. - */ -export class CleartextMessage { - /** Returns ASCII armored text of cleartext signed message - */ - armor(config?: Config): string; - - /** Returns the key IDs of the keys that signed the cleartext message - */ - getSigningKeyIDs(): KeyID[]; - - /** Get cleartext - */ - getText(): string; - - /** Sign the cleartext message - * - * @param privateKeys private keys with decrypted secret key data for signing - */ - sign(privateKeys: PrivateKey[], signature?: Signature, signingKeyIDs?: KeyID[], date?: Date, userIDs?: UserID[], config?: Config): void; - - /** Verify signatures of cleartext signed message - * @param keys array of keys to verify signatures - */ - verify(keys: PublicKey[], date?: Date, config?: Config): Promise; -} - -/* ############## v5 MSG #################### */ -export function generateSessionKey(options: { encryptionKeys: MaybeArray, date?: Date, encryptionUserIDs?: MaybeArray, config?: PartialConfig }): Promise; -export function encryptSessionKey(options: SessionKey & { - encryptionKeys?: MaybeArray, passwords?: MaybeArray, format?: 'armored', wildcard?: boolean, encryptionKeyIDs?: MaybeArray, date?: Date, encryptionUserIDs?: MaybeArray, config?: PartialConfig -}) : Promise; -export function encryptSessionKey(options: SessionKey & { - encryptionKeys?: MaybeArray, passwords?: MaybeArray, format: 'binary', wildcard?: boolean, encryptionKeyIDs?: MaybeArray, date?: Date, encryptionUserIDs?: MaybeArray, config?: PartialConfig -}) : Promise; -export function encryptSessionKey(options: SessionKey & { - encryptionKeys?: MaybeArray, passwords?: MaybeArray, format: 'object', wildcard?: boolean, encryptionKeyIDs?: MaybeArray, date?: Date, encryptionUserIDs?: MaybeArray, config?: PartialConfig -}) : Promise>; -export function decryptSessionKeys>(options: { message: Message, decryptionKeys?: MaybeArray, passwords?: MaybeArray, date?: Date, config?: PartialConfig }): Promise; - -export function readMessage>(options: { armoredMessage: T, config?: PartialConfig }): Promise>; -export function readMessage>(options: { binaryMessage: T, config?: PartialConfig }): Promise>; - -export function createMessage>(options: { text: T, filename?: string, date?: Date, format?: enums.literalFormatNames }): Promise>; -export function createMessage>(options: { binary: T, filename?: string, date?: Date, format?: enums.literalFormatNames }): Promise>; - -export function encrypt>(options: EncryptOptions & { message: Message, format?: 'armored' }): Promise< - T extends WebStream ? WebStream : - T extends NodeStream ? NodeStream : - string ->; -export function encrypt>(options: EncryptOptions & { message: Message, format: 'binary' }): Promise< - T extends WebStream ? WebStream : - T extends NodeStream ? NodeStream : - Uint8Array ->; -export function encrypt>(options: EncryptOptions & { message: Message, format: 'object' }): Promise>; - -export function sign>(options: SignOptions & { message: Message, format?: 'armored' }): Promise< - T extends WebStream ? WebStream : - T extends NodeStream ? NodeStream : - string ->; -export function sign>(options: SignOptions & { message: Message, format: 'binary' }): Promise< - T extends WebStream ? WebStream : - T extends NodeStream ? NodeStream : - Uint8Array ->; -export function sign>(options: SignOptions & { message: Message, format: 'object' }): Promise>; -export function sign(options: SignOptions & { message: CleartextMessage, format?: 'armored' }): Promise; -export function sign(options: SignOptions & { message: CleartextMessage, format: 'object' }): Promise; - -export function decrypt>(options: DecryptOptions & { message: Message, format: 'binary' }): Promise ? WebStream : - T extends NodeStream ? NodeStream : - Uint8Array -}>; -export function decrypt>(options: DecryptOptions & { message: Message }): Promise ? WebStream : - T extends NodeStream ? NodeStream : - string -}>; - -export function verify>(options: VerifyOptions & { message: Message, format: 'binary' }): Promise ? WebStream : - T extends NodeStream ? NodeStream : - Uint8Array -}>; -export function verify>(options: VerifyOptions & { message: Message }): Promise ? WebStream : - T extends NodeStream ? NodeStream : - string -}>; - -/** Class that represents an OpenPGP message. Can be an encrypted message, signed message, compressed message or literal message - */ -export class Message> { - - public readonly packets: PacketList; - constructor(packetlist: PacketList); - - /** Returns binary representation of message - */ - public write(): MaybeStream; - - /** Returns ASCII armored text of message - */ - public armor(config?: Config): string; - - /** Decrypt the message - @param decryptionKeys array of private keys with decrypted secret data - */ - public decrypt(decryptionKeys?: PrivateKey[], passwords?: string[], sessionKeys?: SessionKey[], date?: Date, config?: Config): Promise>>; - - /** Encrypt the message - @param encryptionKeys array of public keys, used to encrypt the message - */ - public encrypt(encryptionKeys?: PublicKey[], passwords?: string[], sessionKeys?: SessionKey[], wildcard?: boolean, encryptionKeyIDs?: KeyID[], date?: Date, userIDs?: UserID[], config?: Config): Promise>>; - - /** Returns the key IDs of the keys to which the session key is encrypted - */ - public getEncryptionKeyIDs(): KeyID[]; - - /** Get literal data that is the body of the message - */ - public getLiteralData(): MaybeStream | null; - - /** Returns the key IDs of the keys that signed the message - */ - public getSigningKeyIDs(): KeyID[]; - - /** Get literal data as text - */ - public getText(): MaybeStream | null; - - public getFilename(): string | null; - - /** Sign the message (the literal data packet of the message) - @param signingKeys private keys with decrypted secret key data for signing - */ - public sign(signingKeys: PrivateKey[], signature?: Signature, signingKeyIDs?: KeyID[], date?: Date, userIDs?: UserID[], config?: Config): Promise>; - - /** Unwrap compressed message - */ - public unwrapCompressed(): Message; - - /** Verify message signatures - @param verificationKeys array of public keys to verify signatures - */ - public verify(verificationKeys: PublicKey[], date?: Date, config?: Config): Promise; - - /** - * Append signature to unencrypted message object - * @param {String|Uint8Array} detachedSignature - The detached ASCII-armored or Uint8Array PGP signature - */ - public appendSignature(detachedSignature: string | Uint8Array, config?: Config): Promise; -} - - -/* ############## v5 CONFIG #################### */ - -interface Config { - preferredHashAlgorithm: enums.hash; - preferredSymmetricAlgorithm: enums.symmetric; - preferredCompressionAlgorithm: enums.compression; - showVersion: boolean; - showComment: boolean; - deflateLevel: number; - aeadProtect: boolean; - allowUnauthenticatedMessages: boolean; - allowUnauthenticatedStream: boolean; - checksumRequired: boolean; - minRSABits: number; - passwordCollisionCheck: boolean; - revocationsExpire: boolean; - ignoreUnsupportedPackets: boolean; - ignoreMalformedPackets: boolean; - versionString: string; - commentString: string; - allowInsecureDecryptionWithSigningKeys: boolean; - constantTimePKCS1Decryption: boolean; - constantTimePKCS1DecryptionSupportedSymmetricAlgorithms: Set; - v5Keys: boolean; - preferredAEADAlgorithm: enums.aead; - aeadChunkSizeByte: number; - s2kIterationCountByte: number; - minBytesForWebCrypto: number; - maxUserIDLength: number; - knownNotations: string[]; - useIndutnyElliptic: boolean; - rejectHashAlgorithms: Set; - rejectMessageHashAlgorithms: Set; - rejectPublicKeyAlgorithms: Set; - rejectCurves: Set; -} -export var config: Config; - -// PartialConfig has the same properties as Config, but declared as optional. -// This interface is relevant for top-level functions, which accept a subset of configuration options -interface PartialConfig extends Partial {} - -/* ############## v5 PACKET #################### */ - -export abstract class BasePacket { - static readonly tag: enums.packet; - public read(bytes: Uint8Array): void; - public write(): Uint8Array; -} - -/** - * The relationship between the KeyPacket classes is modeled by considering the following: - * - A Secret (Sub)Key Packet can always be used when a Public one is expected. - * - A Subkey Packet cannot always be used when a Primary Key Packet is expected (and vice versa). - */ -export abstract class BasePublicKeyPacket extends BasePacket { - public algorithm: enums.publicKey; - public created: Date; - public version: number; - public getAlgorithmInfo(): AlgorithmInfo; - public getFingerprint(): string; - public getFingerprintBytes(): Uint8Array | null; - public hasSameFingerprintAs(other: BasePublicKeyPacket): boolean; - public getCreationTime(): Date; - public getKeyID(): KeyID; - public isDecrypted(): boolean; - public publicParams: object; - // `isSubkey` is a dummy method to ensure that Subkey packets are not accepted as Key one, and vice versa. - // The key class hierarchy is already modelled to cover this, but the concrete key packet classes - // have compatible structure and TS can't detect the difference. - protected isSubkey(): boolean; -} - -export class PublicKeyPacket extends BasePublicKeyPacket { - static readonly tag: enums.packet.publicKey; - protected isSubkey(): false; -} - -export class PublicSubkeyPacket extends BasePublicKeyPacket { - static readonly tag: enums.packet.publicSubkey; - protected isSubkey(): true; -} - -export abstract class BaseSecretKeyPacket extends BasePublicKeyPacket { - public privateParams: object | null; - public encrypt(passphrase: string, config?: Config): Promise; // throws on error - public decrypt(passphrase: string): Promise; // throws on error - public validate(): Promise; // throws on error - public isDummy(): boolean; - public makeDummy(config?: Config): void; -} - -export class SecretKeyPacket extends BaseSecretKeyPacket { - static readonly tag: enums.packet.secretKey; - protected isSubkey(): false; -} - -export class SecretSubkeyPacket extends BaseSecretKeyPacket { - static readonly tag: enums.packet.secretSubkey; - protected isSubkey(): true; -} - -export class CompressedDataPacket extends BasePacket { - static readonly tag: enums.packet.compressedData; - private compress(): void; - private decompress(config?: Config): void; -} - -export class SymEncryptedIntegrityProtectedDataPacket extends BasePacket { - static readonly tag: enums.packet.symEncryptedIntegrityProtectedData; -} - -export class AEADEncryptedDataPacket extends BasePacket { - static readonly tag: enums.packet.aeadEncryptedData; - private decrypt(sessionKeyAlgorithm: enums.symmetric, sessionKey: Uint8Array, config?: Config): void; - private encrypt(sessionKeyAlgorithm: enums.symmetric, sessionKey: Uint8Array, config?: Config): void; - private crypt(fn: Function, sessionKey: Uint8Array, data: MaybeStream): MaybeStream -} - -export class PublicKeyEncryptedSessionKeyPacket extends BasePacket { - static readonly tag: enums.packet.publicKeyEncryptedSessionKey; - private decrypt(keyPacket: SecretKeyPacket): void; // throws on error - private encrypt(keyPacket: PublicKeyPacket): void; // throws on error -} - -export class SymEncryptedSessionKey extends BasePacket { - static readonly tag: enums.packet.symEncryptedSessionKey; - private decrypt(passphrase: string): Promise; - private encrypt(passphrase: string, config?: Config): Promise; -} - -export class LiteralDataPacket extends BasePacket { - static readonly tag: enums.packet.literalData; - private getText(clone?: boolean): MaybeStream; - private getBytes(clone?: boolean): MaybeStream; - private setText(text: MaybeStream, format?: enums.literal); - private setBytes(bytes: MaybeStream, format: enums.literal); - private setFilename(filename: string); - private getFilename(): string; - private writeHeader(): Uint8Array; -} - -export class SymmetricallyEncryptedDataPacket extends BasePacket { - static readonly tag: enums.packet.symmetricallyEncryptedData; - private decrypt(sessionKeyAlgorithm: enums.symmetric, sessionKey: Uint8Array, config?: Config): void; - private encrypt(sessionKeyAlgorithm: enums.symmetric, sessionKey: Uint8Array, config?: Config): void; -} - -export class MarkerPacket extends BasePacket { - static readonly tag: enums.packet.marker; -} - -export class UserAttributePacket extends BasePacket { - static readonly tag: enums.packet.userAttribute; - private equals(packet: UserAttributePacket): boolean; -} - -export class OnePassSignaturePacket extends BasePacket { - static readonly tag: enums.packet.onePassSignature; - public correspondingSig?: Promise; - private verify: SignaturePacket['verify']; -} - -export class UserIDPacket extends BasePacket { - static readonly tag: enums.packet.userID; - public readonly name: string; - public readonly comment: string; - public readonly email: string; - public readonly userID: string; - static fromObject(userID: UserID): UserIDPacket; -} - -export class SignaturePacket extends BasePacket { - static readonly tag: enums.packet.signature; - public version: number; - public signatureType: enums.signature | null; - public hashAlgorithm: enums.hash | null; - public publicKeyAlgorithm: enums.publicKey | null; - public signatureData: null | Uint8Array; - public unhashedSubpackets: null | Uint8Array; - public signedHashValue: null | Uint8Array; - public created: Date | null; - public signatureExpirationTime: null | number; - public signatureNeverExpires: boolean; - public exportable: null | boolean; - public trustLevel: null | number; - public trustAmount: null | number; - public regularExpression: null | number; - public revocable: null | boolean; - public keyExpirationTime: null | number; - public keyNeverExpires: null | boolean; - public preferredSymmetricAlgorithms: enums.symmetric[] | null; - public revocationKeyClass: null | number; - public revocationKeyAlgorithm: null | enums.publicKey; - public revocationKeyFingerprint: null | Uint8Array; - public issuerKeyID: KeyID; - public notation: null | { [name: string]: string }; - public preferredHashAlgorithms: enums.hash[] | null; - public preferredCompressionAlgorithms: enums.compression[] | null; - public keyServerPreferences: null | number[]; - public preferredKeyServer: null | string; - public isPrimaryUserID: null | boolean; - public policyURI: null | string; - public keyFlags: Uint8Array | null; - public signersUserID: null | string; - public reasonForRevocationFlag: null | enums.reasonForRevocation; - public reasonForRevocationString: null | string; - public features: Uint8Array | null; - public signatureTargetPublicKeyAlgorithm: enums.publicKey | null; - public signatureTargetHashAlgorithm: enums.hash | null; - public signatureTargetHash: null | string; - public embeddedSignature: null | SignaturePacket; - public issuerKeyVersion: null | number; - public issuerFingerprint: null | Uint8Array; - public preferredAEADAlgorithms: enums.aead[] | null; - public verified: null | boolean; - public revoked: null | boolean; - public sign(key: AnySecretKeyPacket, data: Uint8Array, date?: Date, detached?: boolean): Promise; - public verify(key: AnyKeyPacket, signatureType: enums.signature, data: Uint8Array, date?: Date, detached?: boolean, config?: Config): Promise; // throws on error - public isExpired(date?: Date): boolean; - public getExpirationTime(): Date | typeof Infinity; -} - -export class TrustPacket extends BasePacket { - static readonly tag: enums.packet.trust; -} - -export type AnyPacket = BasePacket; -export type AnySecretKeyPacket = SecretKeyPacket | SecretSubkeyPacket; -export type AnyKeyPacket = BasePublicKeyPacket; - -type AllowedPackets = Map; // mapping to Packet classes (i.e. typeof LiteralDataPacket etc.) -export class PacketList extends Array { - static fromBinary(bytes: MaybeStream, allowedPackets: AllowedPackets, config?: Config): PacketList; // the packet types depend on`allowedPackets` - public read(bytes: MaybeStream, allowedPackets: AllowedPackets, config?: Config): void; - public write(): Uint8Array; - public filterByTag(...args: enums.packet[]): PacketList; - public indexOfTag(...tags: enums.packet[]): number[]; - public findPacket(tag: enums.packet): T | undefined; -} - -/* ############## v5 STREAM #################### */ - -type Data = Uint8Array | string; -interface BaseStream extends AsyncIterable { } -interface WebStream extends BaseStream { // copied+simplified version of ReadableStream from lib.dom.d.ts - readonly locked: boolean; getReader: Function; pipeThrough: Function; pipeTo: Function; tee: Function; - cancel(reason?: any): Promise; -} -interface NodeStream extends BaseStream { // copied+simplified version of ReadableStream from @types/node/index.d.ts - readable: boolean; pipe: Function; unpipe: Function; wrap: Function; - read(size?: number): string | Uint8Array; setEncoding(encoding: string): this; pause(): this; resume(): this; - isPaused(): boolean; unshift(chunk: string | Uint8Array): void; -} -type Stream = WebStream | NodeStream; -type MaybeStream = T | Stream; - -/* ############## v5 GENERAL #################### */ -type MaybeArray = T | Array; - -export interface UserID { name?: string; email?: string; comment?: string; } -export interface SessionKey { - data: Uint8Array; - algorithm: enums.symmetricNames; - aeadAlgorithm?: enums.aeadNames; -} - -export interface ReasonForRevocation { flag?: enums.reasonForRevocation, string?: string } - -interface EncryptOptions { - /** message to be encrypted as created by createMessage */ - message: Message>; - /** (optional) array of keys or single key, used to encrypt the message */ - encryptionKeys?: MaybeArray; - /** (optional) private keys for signing. If omitted message will not be signed */ - signingKeys?: MaybeArray; - /** (optional) array of passwords or a single password to encrypt the message */ - passwords?: MaybeArray; - /** (optional) session key */ - sessionKey?: SessionKey; - /** if the return values should be ascii armored or the message/signature objects */ - format?: 'armored' | 'binary' | 'object'; - /** (optional) if the signature should be detached (if true, signature will be added to returned object) */ - signature?: Signature; - /** (optional) encrypt as of a certain date */ - date?: Date; - /** (optional) use a key ID of 0 instead of the public key IDs */ - wildcard?: boolean; - /** (optional) Array of key IDs to use for signing. Each `signingKeyIDs[i]` corresponds to `signingKeys[i]` */ - signingKeyIDs?: MaybeArray; - /** (optional) Array of key IDs to use for encryption. Each `encryptionKeyIDs[i]` corresponds to `encryptionKeys[i]`*/ - encryptionKeyIDs?: MaybeArray; - /** (optional) Array of user IDs to sign with, e.g. { name:'Steve Sender', email:'steve@openpgp.org' } */ - signingUserIDs?: MaybeArray; - /** (optional) array of user IDs to encrypt for, e.g. { name:'Robert Receiver', email:'robert@openpgp.org' } */ - encryptionUserIDs?: MaybeArray; - config?: PartialConfig; -} - -interface DecryptOptions { - /** the message object with the encrypted data */ - message: Message>; - /** (optional) private keys with decrypted secret key data or session key */ - decryptionKeys?: MaybeArray; - /** (optional) passwords to decrypt the message */ - passwords?: MaybeArray; - /** (optional) session keys in the form: { data:Uint8Array, algorithm:String } */ - sessionKeys?: MaybeArray; - /** (optional) array of public keys or single key, to verify signatures */ - verificationKeys?: MaybeArray; - /** (optional) whether data decryption should fail if the message is not signed with the provided publicKeys */ - expectSigned?: boolean; - /** (optional) whether to return data as a string(Stream) or Uint8Array(Stream). If 'utf8' (the default), also normalize newlines. */ - format?: 'utf8' | 'binary'; - /** (optional) detached signature for verification */ - signature?: Signature; - /** (optional) use the given date for verification instead of the current time */ - date?: Date; - config?: PartialConfig; -} - -interface SignOptions { - message: CleartextMessage | Message>; - signingKeys?: MaybeArray; - format?: 'armored' | 'binary' | 'object'; - detached?: boolean; - signingKeyIDs?: MaybeArray; - date?: Date; - signingUserIDs?: MaybeArray; - config?: PartialConfig; -} - -interface VerifyOptions { - /** (cleartext) message object with signatures */ - message: CleartextMessage | Message>; - /** array of publicKeys or single key, to verify signatures */ - verificationKeys: MaybeArray; - /** (optional) whether verification should throw if the message is not signed with the provided publicKeys */ - expectSigned?: boolean; - /** (optional) whether to return data as a string(Stream) or Uint8Array(Stream). If 'utf8' (the default), also normalize newlines. */ - format?: 'utf8' | 'binary'; - /** (optional) detached signature for verification */ - signature?: Signature; - /** (optional) use the given date for verification instead of the current time */ - date?: Date; - config?: PartialConfig; -} - - -interface SerializedKeyPair { - privateKey: T; - publicKey: T; -} -interface KeyPair { - privateKey: PrivateKey; - publicKey: PublicKey; -} - -export type EllipticCurveName = 'ed25519' | 'curve25519' | 'p256' | 'p384' | 'p521' | 'secp256k1' | 'brainpoolP256r1' | 'brainpoolP384r1' | 'brainpoolP512r1'; - -interface KeyOptions { - userIDs: MaybeArray; - passphrase?: string; - type?: 'ecc' | 'rsa'; - curve?: EllipticCurveName; - rsaBits?: number; - keyExpirationTime?: number; - date?: Date; - subkeys?: SubkeyOptions[]; - format?: 'armored' | 'object' | 'binary'; - config?: PartialConfig; -} - -interface SubkeyOptions { - type?: 'ecc' | 'rsa'; - curve?: EllipticCurveName; - rsaBits?: number; - keyExpirationTime?: number; - date?: Date; - sign?: boolean; - config?: PartialConfig; -} - -export class KeyID { - bytes: string; - equals(keyID: KeyID, matchWildcard?: boolean): boolean; - toHex(): string; - static fromID(hex: string): KeyID; -} - -interface DecryptMessageResult { - data: MaybeStream; - signatures: VerificationResult[]; - filename: string; -} - -interface VerifyMessageResult { - data: MaybeStream; - signatures: VerificationResult[]; -} - - -/** - * Armor an OpenPGP binary packet block - */ -export function armor(messagetype: enums.armor, body: object, partindex: number, parttotal: number, config?: Config): string; - -/** - * DeArmor an OpenPGP armored message; verify the checksum and return the encoded bytes - */ -export function unarmor(input: string, config?: Config): Promise<{ text: string, data: Stream, type: enums.armor }>; - -/* ############## v5 ENUMS #################### */ - -export namespace enums { - function read(type: typeof armor, e: armor): armorNames; - function read(type: typeof compression, e: compression): compressionNames; - function read(type: typeof hash, e: hash): hashNames; - function read(type: typeof packet, e: packet): packetNames; - function read(type: typeof publicKey, e: publicKey): publicKeyNames; - function read(type: typeof symmetric, e: symmetric): symmetricNames; - function read(type: typeof keyStatus, e: keyStatus): keyStatusNames; - function read(type: typeof keyFlags, e: keyFlags): keyFlagsNames; - - export type armorNames = 'multipartSection' | 'multipartLast' | 'signed' | 'message' | 'publicKey' | 'privateKey'; - enum armor { - multipartSection = 0, - multipartLast = 1, - signed = 2, - message = 3, - publicKey = 4, - privateKey = 5, - signature = 6, - } - - enum reasonForRevocation { - noReason = 0, // No reason specified (key revocations or cert revocations) - keySuperseded = 1, // Key is superseded (key revocations) - keyCompromised = 2, // Key material has been compromised (key revocations) - keyRetired = 3, // Key is retired and no longer used (key revocations) - userIDInvalid = 32, // User ID information is no longer valid (cert revocations) - } - - export type compressionNames = 'uncompressed' | 'zip' | 'zlib' | 'bzip2'; - enum compression { - uncompressed = 0, - zip = 1, - zlib = 2, - bzip2 = 3, - } - - export type hashNames = 'md5' | 'sha1' | 'ripemd' | 'sha256' | 'sha384' | 'sha512' | 'sha224'; - enum hash { - md5 = 1, - sha1 = 2, - ripemd = 3, - sha256 = 8, - sha384 = 9, - sha512 = 10, - sha224 = 11, - } - - export type packetNames = 'publicKeyEncryptedSessionKey' | 'signature' | 'symEncryptedSessionKey' | 'onePassSignature' | 'secretKey' | 'publicKey' - | 'secretSubkey' | 'compressed' | 'symmetricallyEncrypted' | 'marker' | 'literal' | 'trust' | 'userID' | 'publicSubkey' | 'userAttribute' - | 'symEncryptedIntegrityProtected' | 'modificationDetectionCode' | 'AEADEncryptedDataPacket'; - enum packet { - publicKeyEncryptedSessionKey = 1, - signature = 2, - symEncryptedSessionKey = 3, - onePassSignature = 4, - secretKey = 5, - publicKey = 6, - secretSubkey = 7, - compressedData = 8, - symmetricallyEncryptedData = 9, - marker = 10, - literalData = 11, - trust = 12, - userID = 13, - publicSubkey = 14, - userAttribute = 17, - symEncryptedIntegrityProtectedData = 18, - modificationDetectionCode = 19, - aeadEncryptedData = 20, - } - - export type publicKeyNames = 'rsaEncryptSign' | 'rsaEncrypt' | 'rsaSign' | 'elgamal' | 'dsa' | 'ecdh' | 'ecdsa' | 'eddsa' | 'aedh' | 'aedsa'; - enum publicKey { - rsaEncryptSign = 1, - rsaEncrypt = 2, - rsaSign = 3, - elgamal = 16, - dsa = 17, - ecdh = 18, - ecdsa = 19, - eddsa = 22, - aedh = 23, - aedsa = 24, - } - - enum curve { - p256 = 'p256', - p384 = 'p384', - p521 = 'p521', - ed25519 = 'ed25519', - curve25519 = 'curve25519', - secp256k1 = 'secp256k1', - brainpoolP256r1 = 'brainpoolP256r1', - brainpoolP384r1 = 'brainpoolP384r1', - brainpoolP512r1 = 'brainpoolP512r1' - } - - export type symmetricNames = 'plaintext' | 'idea' | 'tripledes' | 'cast5' | 'blowfish' | 'aes128' | 'aes192' | 'aes256' | 'twofish'; - enum symmetric { - plaintext = 0, - idea = 1, - tripledes = 2, - cast5 = 3, - blowfish = 4, - aes128 = 7, - aes192 = 8, - aes256 = 9, - twofish = 10, - } - - export type keyStatusNames = 'invalid' | 'expired' | 'revoked' | 'valid' | 'noSelfCert'; - enum keyStatus { - invalid = 0, - expired = 1, - revoked = 2, - valid = 3, - noSelfCert = 4, - } - - export type keyFlagsNames = 'certifyKeys' | 'signData' | 'encryptCommunication' | 'encryptStorage' | 'splitPrivateKey' | 'authentication' - | 'sharedPrivateKey'; - enum keyFlags { - certifyKeys = 1, - signData = 2, - encryptCommunication = 4, - encryptStorage = 8, - splitPrivateKey = 16, - authentication = 32, - sharedPrivateKey = 128, - } - - enum signature { - binary = 0, - text = 1, - standalone = 2, - certGeneric = 16, - certPersona = 17, - certCasual = 18, - certPositive = 19, - certRevocation = 48, - subkeyBinding = 24, - keyBinding = 25, - key = 31, - keyRevocation = 32, - subkeyRevocation = 40, - timestamp = 64, - thirdParty = 80 - } - - export type aeadNames = 'eax' | 'ocb' | 'gcm'; - enum aead { - eax = 1, - ocb = 2, - experimentalGCM = 100 // Private algorithm - } - - export type literalFormatNames = 'utf8' | 'binary' | 'text' | 'mime' - enum literal { - binary = 98, - text = 116, - utf8 = 117, - mime = 109 - } -} - -// -----BEGIN ADDED BY FLOWCRYPT----- - -export function readToEnd(input: MaybeStream, concat?: (list: T[]) => T): Promise; - -export namespace util { - // we can't copy this from openpgp.js into our sources (i.e. util.ts) because of LGPL - function uint8ArrayToString(bytes: Uint8Array): string; - function uint8ArrayToHex(bytes: Uint8Array): string; -} - -export class Hash { - public reset(): Hash; - public process(data: Uint8Array): Hash; - public finish(): Hash; - public result: Uint8Array; -} - -export class Sha1 extends Hash {} -export class Sha256 extends Hash {} - -// -----END ADDED BY FLOWCRYPT----- diff --git a/Core/tooling/build.sh b/Core/tooling/build.sh index 44440b01d..83c6ce64e 100755 --- a/Core/tooling/build.sh +++ b/Core/tooling/build.sh @@ -3,7 +3,6 @@ set -euxo pipefail # fix openpgp in node_modules -cp -f source/core/types/openpgp.d.ts node_modules/openpgp for f in openpgp.min.js openpgp.min.js.map openpgp.min.mjs openpgp.min.mjs.map openpgp.mjs; do if [ -f node_modules/openpgp/dist/$f ]; then rm -f node_modules/openpgp/dist/$f ; fi if [ -f node_modules/openpgp/dist/node/$f ]; then rm -f node_modules/openpgp/dist/node/$f ; fi From 9562dcae0f0aed8072585b3e52775d9b30909fe7 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 21:46:52 +0200 Subject: [PATCH 102/179] wip --- Core/source/core/pgp-key.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index c71d2a89a..49a2020ae 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -369,7 +369,10 @@ export class PgpKey { } allSignatures.sort((a, b) => (b.created ? b.created.getTime() : 0) - (a.created ? a.created.getTime() : 0)); console.log(`nsig=${allSignatures.length}`); - console.log(`sigs=${JSON.stringify(allSignatures)}`); + let i = 0; + for (const sig of allSignatures) { + console.log(`sig[${i++}]=${JSON.stringify(sig)}\n`); + } for (const sig of allSignatures) console.log(`${(Object as any).__oid(sig)} => ${sig.verified}`); const newestSig = allSignatures.find(sig => sig.verified === true); if (newestSig) { From bf80cdeafddc52590d1cb2928538cffdca5cbb9d Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 22:07:35 +0200 Subject: [PATCH 103/179] wip --- Core/source/core/pgp-key.ts | 19 +++++++++++++------ Core/test.sh | 2 +- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index 49a2020ae..78a9e999e 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -356,24 +356,31 @@ export class PgpKey { * This is used to figure out how recently was key updated, and if one key is newer than other. */ public static lastSig = async (key: Key): Promise => { - console.log((Object as any).__oid(key)); + let i = 0; + console.log(`Key OUID ${(Object as any).__oid(key)}`); await key.getExpirationTime(); // will force all sigs to be verified const allSignatures: SignaturePacket[] = []; for (const user of key.users) { + i = 0; + for (const sig of user.selfCertifications) { + console.log(`user ${user.userID?.email} sig[${i++}](OUID ${(Object as any).__oid(sig)} => ${sig.verified})\n`); + } allSignatures.push(...user.selfCertifications); - console.log(`selfcerts=${user.selfCertifications.length}`); } + i = 0; for (const subKey of key.subkeys) { + i = 0; + for (const sig of subKey.bindingSignatures) { + console.log(`subkey ${subKey.getKeyID().toHex()} sig[${i++}](OUID ${(Object as any).__oid(sig)} => ${sig.verified})}\n`); + } allSignatures.push(...subKey.bindingSignatures); - console.log(`sbb=${subKey.bindingSignatures.length}`); } allSignatures.sort((a, b) => (b.created ? b.created.getTime() : 0) - (a.created ? a.created.getTime() : 0)); console.log(`nsig=${allSignatures.length}`); - let i = 0; + i = 0; for (const sig of allSignatures) { - console.log(`sig[${i++}]=${JSON.stringify(sig)}\n`); + console.log(`sig[${i++}](OUID ${(Object as any).__oid(sig)} => ${sig.verified})}\n`); } - for (const sig of allSignatures) console.log(`${(Object as any).__oid(sig)} => ${sig.verified}`); const newestSig = allSignatures.find(sig => sig.verified === true); if (newestSig) { return newestSig.created ? newestSig.created.getTime() : 0; diff --git a/Core/test.sh b/Core/test.sh index 6c4316609..6fab1674e 100755 --- a/Core/test.sh +++ b/Core/test.sh @@ -1,3 +1,3 @@ #!/bin/sh - +clear npm run test From 300e4025e8e6a7d55fa5bdd1ba0ca26efab0a60f Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 22:15:37 +0200 Subject: [PATCH 104/179] wip --- Core/{.old => .save}/openpgpv4/openpgpv4.d.ts | 0 Core/{.old => .save/openpgpv4}/openpgpv4.js | 0 Core/.save/openpgpv5/node/openpgp.js | 43578 ++++++++++++++++ Core/.save/openpgpv5/openpgp.js | 43539 +++++++++++++++ 4 files changed, 87117 insertions(+) rename Core/{.old => .save}/openpgpv4/openpgpv4.d.ts (100%) rename Core/{.old => .save/openpgpv4}/openpgpv4.js (100%) create mode 100644 Core/.save/openpgpv5/node/openpgp.js create mode 100644 Core/.save/openpgpv5/openpgp.js diff --git a/Core/.old/openpgpv4/openpgpv4.d.ts b/Core/.save/openpgpv4/openpgpv4.d.ts similarity index 100% rename from Core/.old/openpgpv4/openpgpv4.d.ts rename to Core/.save/openpgpv4/openpgpv4.d.ts diff --git a/Core/.old/openpgpv4.js b/Core/.save/openpgpv4/openpgpv4.js similarity index 100% rename from Core/.old/openpgpv4.js rename to Core/.save/openpgpv4/openpgpv4.js diff --git a/Core/.save/openpgpv5/node/openpgp.js b/Core/.save/openpgpv5/node/openpgp.js new file mode 100644 index 000000000..ee8644e5f --- /dev/null +++ b/Core/.save/openpgpv5/node/openpgp.js @@ -0,0 +1,43578 @@ +/*! OpenPGP.js v5.1.0 - 2022-01-24 - this is LGPL licensed code, see LICENSE/our website https://openpgpjs.org/ for more information. */ +'use strict'; + +const globalThis = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + +Object.defineProperty(exports, '__esModule', { value: true }); + +var buffer = require('buffer'); +var stream$1 = require('stream'); +var crypto$3 = require('crypto'); +var zlib = require('zlib'); +var os = require('os'); +var util$1 = require('util'); +var asn1$2 = require('asn1.js'); + +function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } + +var buffer__default = /*#__PURE__*/_interopDefaultLegacy(buffer); +var stream__default = /*#__PURE__*/_interopDefaultLegacy(stream$1); +var crypto__default = /*#__PURE__*/_interopDefaultLegacy(crypto$3); +var zlib__default = /*#__PURE__*/_interopDefaultLegacy(zlib); +var os__default = /*#__PURE__*/_interopDefaultLegacy(os); +var util__default = /*#__PURE__*/_interopDefaultLegacy(util$1); +var asn1__default = /*#__PURE__*/_interopDefaultLegacy(asn1$2); + +const doneWritingPromise = Symbol('doneWritingPromise'); +const doneWritingResolve = Symbol('doneWritingResolve'); +const doneWritingReject = Symbol('doneWritingReject'); + +const readingIndex = Symbol('readingIndex'); + +// inject oids +(function() { + if ( typeof Object.__oid == "undefined" ) { + var id = 0; + + Object.__oid = function(o) { + if ( typeof o.__uniqueid == "undefined" ) { + Object.defineProperty(o, "__uniqueid", { + value: ++id, + enumerable: false, + // This could go either way, depending on your + // interpretation of what an "id" is + writable: false + }); + } + + return o.__uniqueid; + }; + } +})(); + +class ArrayStream extends Array { + constructor() { + super(); + this[doneWritingPromise] = new Promise((resolve, reject) => { + this[doneWritingResolve] = resolve; + this[doneWritingReject] = reject; + }); + this[doneWritingPromise].catch(() => {}); + } +} + +ArrayStream.prototype.getReader = function() { + if (this[readingIndex] === undefined) { + this[readingIndex] = 0; + } + return { + read: async () => { + await this[doneWritingPromise]; + if (this[readingIndex] === this.length) { + return { value: undefined, done: true }; + } + return { value: this[this[readingIndex]++], done: false }; + } + }; +}; + +ArrayStream.prototype.readToEnd = async function(join) { + await this[doneWritingPromise]; + const result = join(this.slice(this[readingIndex])); + this.length = 0; + return result; +}; + +ArrayStream.prototype.clone = function() { + const clone = new ArrayStream(); + clone[doneWritingPromise] = this[doneWritingPromise].then(() => { + clone.push(...this); + }); + return clone; +}; + +/** + * Check whether data is an ArrayStream + * @param {Any} input data to check + * @returns {boolean} + */ +function isArrayStream(input) { + return input && input.getReader && Array.isArray(input); +} + +/** + * A wrapper class over the native WritableStreamDefaultWriter. + * It also lets you "write data to" array streams instead of streams. + * @class + */ +function Writer(input) { + if (!isArrayStream(input)) { + const writer = input.getWriter(); + const releaseLock = writer.releaseLock; + writer.releaseLock = () => { + writer.closed.catch(function() {}); + releaseLock.call(writer); + }; + return writer; + } + this.stream = input; +} + +/** + * Write a chunk of data. + * @returns {Promise} + * @async + */ +Writer.prototype.write = async function(chunk) { + this.stream.push(chunk); +}; + +/** + * Close the stream. + * @returns {Promise} + * @async + */ +Writer.prototype.close = async function() { + this.stream[doneWritingResolve](); +}; + +/** + * Error the stream. + * @returns {Promise} + * @async + */ +Writer.prototype.abort = async function(reason) { + this.stream[doneWritingReject](reason); + return reason; +}; + +/** + * Release the writer's lock. + * @returns {undefined} + * @async + */ +Writer.prototype.releaseLock = function() {}; + +const isNode = typeof globalThis.process === 'object' && + typeof globalThis.process.versions === 'object'; + +const NodeReadableStream = isNode && stream__default['default'].Readable; + +/** + * Check whether data is a Stream, and if so of which type + * @param {Any} input data to check + * @returns {'web'|'ponyfill'|'node'|'array'|'web-like'|false} + */ +function isStream(input) { + if (isArrayStream(input)) { + return 'array'; + } + if (globalThis.ReadableStream && globalThis.ReadableStream.prototype.isPrototypeOf(input)) { + return 'web'; + } + if (ReadableStream && ReadableStream.prototype.isPrototypeOf(input)) { + return 'ponyfill'; + } + if (NodeReadableStream && NodeReadableStream.prototype.isPrototypeOf(input)) { + return 'node'; + } + if (input && input.getReader) { + return 'web-like'; + } + return false; +} + +/** + * Check whether data is a Uint8Array + * @param {Any} input data to check + * @returns {Boolean} + */ +function isUint8Array(input) { + return Uint8Array.prototype.isPrototypeOf(input); +} + +/** + * Concat Uint8Arrays + * @param {Array} Array of Uint8Arrays to concatenate + * @returns {Uint8array} Concatenated array + */ +function concatUint8Array(arrays) { + if (arrays.length === 1) return arrays[0]; + + let totalLength = 0; + for (let i = 0; i < arrays.length; i++) { + if (!isUint8Array(arrays[i])) { + throw new Error('concatUint8Array: Data must be in the form of a Uint8Array'); + } + + totalLength += arrays[i].length; + } + + const result = new Uint8Array(totalLength); + let pos = 0; + arrays.forEach(function (element) { + result.set(element, pos); + pos += element.length; + }); + + return result; +} + +const NodeBuffer = isNode && buffer__default['default'].Buffer; +const NodeReadableStream$1 = isNode && stream__default['default'].Readable; + +/** + * Web / node stream conversion functions + * From https://github.com/gwicke/node-web-streams + */ + +let nodeToWeb; +let webToNode; + +if (NodeReadableStream$1) { + + /** + * Convert a Node Readable Stream to a Web ReadableStream + * @param {Readable} nodeStream + * @returns {ReadableStream} + */ + nodeToWeb = function(nodeStream) { + let canceled = false; + return new ReadableStream({ + start(controller) { + nodeStream.pause(); + nodeStream.on('data', chunk => { + if (canceled) { + return; + } + if (NodeBuffer.isBuffer(chunk)) { + chunk = new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength); + } + controller.enqueue(chunk); + nodeStream.pause(); + }); + nodeStream.on('end', () => { + if (canceled) { + return; + } + controller.close(); + }); + nodeStream.on('error', e => controller.error(e)); + }, + pull() { + nodeStream.resume(); + }, + cancel(reason) { + canceled = true; + nodeStream.destroy(reason); + } + }); + }; + + + class NodeReadable extends NodeReadableStream$1 { + constructor(webStream, options) { + super(options); + this._reader = getReader(webStream); + } + + async _read(size) { + try { + while (true) { + const { done, value } = await this._reader.read(); + if (done) { + this.push(null); + break; + } + if (!this.push(value) || this._cancelling) { + this._reading = false; + break; + } + } + } catch(e) { + this.emit('error', e); + } + } + + _destroy(reason) { + this._reader.cancel(reason); + } + } + + /** + * Convert a Web ReadableStream to a Node Readable Stream + * @param {ReadableStream} webStream + * @param {Object} options + * @returns {Readable} + */ + webToNode = function(webStream, options) { + return new NodeReadable(webStream, options); + }; + +} + +const doneReadingSet = new WeakSet(); +const externalBuffer = Symbol('externalBuffer'); + +/** + * A wrapper class over the native ReadableStreamDefaultReader. + * This additionally implements pushing back data on the stream, which + * lets us implement peeking and a host of convenience functions. + * It also lets you read data other than streams, such as a Uint8Array. + * @class + */ +function Reader(input) { + this.stream = input; + if (input[externalBuffer]) { + this[externalBuffer] = input[externalBuffer].slice(); + } + if (isArrayStream(input)) { + const reader = input.getReader(); + this._read = reader.read.bind(reader); + this._releaseLock = () => {}; + this._cancel = () => {}; + return; + } + let streamType = isStream(input); + if (streamType === 'node') { + input = nodeToWeb(input); + } + if (streamType) { + const reader = input.getReader(); + this._read = reader.read.bind(reader); + this._releaseLock = () => { + reader.closed.catch(function() {}); + reader.releaseLock(); + }; + this._cancel = reader.cancel.bind(reader); + return; + } + let doneReading = false; + this._read = async () => { + if (doneReading || doneReadingSet.has(input)) { + return { value: undefined, done: true }; + } + doneReading = true; + return { value: input, done: false }; + }; + this._releaseLock = () => { + if (doneReading) { + try { + doneReadingSet.add(input); + } catch(e) {} + } + }; +} + +/** + * Read a chunk of data. + * @returns {Promise} Either { done: false, value: Uint8Array | String } or { done: true, value: undefined } + * @async + */ +Reader.prototype.read = async function() { + if (this[externalBuffer] && this[externalBuffer].length) { + const value = this[externalBuffer].shift(); + return { done: false, value }; + } + return this._read(); +}; + +/** + * Allow others to read the stream. + */ +Reader.prototype.releaseLock = function() { + if (this[externalBuffer]) { + this.stream[externalBuffer] = this[externalBuffer]; + } + this._releaseLock(); +}; + +/** + * Cancel the stream. + */ +Reader.prototype.cancel = function(reason) { + return this._cancel(reason); +}; + +/** + * Read up to and including the first \n character. + * @returns {Promise} + * @async + */ +Reader.prototype.readLine = async function() { + let buffer = []; + let returnVal; + while (!returnVal) { + let { done, value } = await this.read(); + value += ''; + if (done) { + if (buffer.length) return concat(buffer); + return; + } + const lineEndIndex = value.indexOf('\n') + 1; + if (lineEndIndex) { + returnVal = concat(buffer.concat(value.substr(0, lineEndIndex))); + buffer = []; + } + if (lineEndIndex !== value.length) { + buffer.push(value.substr(lineEndIndex)); + } + } + this.unshift(...buffer); + return returnVal; +}; + +/** + * Read a single byte/character. + * @returns {Promise} + * @async + */ +Reader.prototype.readByte = async function() { + const { done, value } = await this.read(); + if (done) return; + const byte = value[0]; + this.unshift(slice(value, 1)); + return byte; +}; + +/** + * Read a specific amount of bytes/characters, unless the stream ends before that amount. + * @returns {Promise} + * @async + */ +Reader.prototype.readBytes = async function(length) { + const buffer = []; + let bufferLength = 0; + while (true) { + const { done, value } = await this.read(); + if (done) { + if (buffer.length) return concat(buffer); + return; + } + buffer.push(value); + bufferLength += value.length; + if (bufferLength >= length) { + const bufferConcat = concat(buffer); + this.unshift(slice(bufferConcat, length)); + return slice(bufferConcat, 0, length); + } + } +}; + +/** + * Peek (look ahead) a specific amount of bytes/characters, unless the stream ends before that amount. + * @returns {Promise} + * @async + */ +Reader.prototype.peekBytes = async function(length) { + const bytes = await this.readBytes(length); + this.unshift(bytes); + return bytes; +}; + +/** + * Push data to the front of the stream. + * Data must have been read in the last call to read*. + * @param {...(Uint8Array|String|Undefined)} values + */ +Reader.prototype.unshift = function(...values) { + if (!this[externalBuffer]) { + this[externalBuffer] = []; + } + if ( + values.length === 1 && isUint8Array(values[0]) && + this[externalBuffer].length && values[0].length && + this[externalBuffer][0].byteOffset >= values[0].length + ) { + this[externalBuffer][0] = new Uint8Array( + this[externalBuffer][0].buffer, + this[externalBuffer][0].byteOffset - values[0].length, + this[externalBuffer][0].byteLength + values[0].length + ); + return; + } + this[externalBuffer].unshift(...values.filter(value => value && value.length)); +}; + +/** + * Read the stream to the end and return its contents, concatenated by the join function (defaults to streams.concat). + * @param {Function} join + * @returns {Promise} the return value of join() + * @async + */ +Reader.prototype.readToEnd = async function(join=concat) { + const result = []; + while (true) { + const { done, value } = await this.read(); + if (done) break; + result.push(value); + } + return join(result); +}; + +let { ReadableStream, WritableStream, TransformStream } = globalThis; + +let toPonyfillReadable, toNativeReadable; + +async function loadStreamsPonyfill() { + if (TransformStream) { + return; + } + + const [ponyfill, adapter] = await Promise.all([ + Promise.resolve().then(function () { return ponyfill_es6; }), + Promise.resolve().then(function () { return webStreamsAdapter; }) + ]); + + ({ ReadableStream, WritableStream, TransformStream } = ponyfill); + + const { createReadableStreamWrapper } = adapter; + + if (globalThis.ReadableStream && ReadableStream !== globalThis.ReadableStream) { + toPonyfillReadable = createReadableStreamWrapper(ReadableStream); + toNativeReadable = createReadableStreamWrapper(globalThis.ReadableStream); + } +} + +const NodeBuffer$1 = isNode && buffer__default['default'].Buffer; + +/** + * Convert data to Stream + * @param {ReadableStream|Uint8array|String} input data to convert + * @returns {ReadableStream} Converted data + */ +function toStream(input) { + let streamType = isStream(input); + if (streamType === 'node') { + return nodeToWeb(input); + } + if (streamType === 'web' && toPonyfillReadable) { + return toPonyfillReadable(input); + } + if (streamType) { + return input; + } + return new ReadableStream({ + start(controller) { + controller.enqueue(input); + controller.close(); + } + }); +} + +/** + * Convert data to ArrayStream + * @param {Object} input data to convert + * @returns {ArrayStream} Converted data + */ +function toArrayStream(input) { + if (isStream(input)) { + return input; + } + const stream = new ArrayStream(); + (async () => { + const writer = getWriter(stream); + await writer.write(input); + await writer.close(); + })(); + return stream; +} + +/** + * Concat a list of Uint8Arrays, Strings or Streams + * The caller should not mix Uint8Arrays with Strings, but may mix Streams with non-Streams. + * @param {Array} Array of Uint8Arrays/Strings/Streams to concatenate + * @returns {Uint8array|String|ReadableStream} Concatenated array + */ +function concat(list) { + if (list.some(stream => isStream(stream) && !isArrayStream(stream))) { + return concatStream(list); + } + if (list.some(stream => isArrayStream(stream))) { + return concatArrayStream(list); + } + if (typeof list[0] === 'string') { + return list.join(''); + } + if (NodeBuffer$1 && NodeBuffer$1.isBuffer(list[0])) { + return NodeBuffer$1.concat(list); + } + return concatUint8Array(list); +} + +/** + * Concat a list of Streams + * @param {Array} list Array of Uint8Arrays/Strings/Streams to concatenate + * @returns {ReadableStream} Concatenated list + */ +function concatStream(list) { + list = list.map(toStream); + const transform = transformWithCancel(async function(reason) { + await Promise.all(transforms.map(stream => cancel(stream, reason))); + }); + let prev = Promise.resolve(); + const transforms = list.map((stream, i) => transformPair(stream, (readable, writable) => { + prev = prev.then(() => pipe(readable, transform.writable, { + preventClose: i !== list.length - 1 + })); + return prev; + })); + return transform.readable; +} + +/** + * Concat a list of ArrayStreams + * @param {Array} list Array of Uint8Arrays/Strings/ArrayStreams to concatenate + * @returns {ArrayStream} Concatenated streams + */ +function concatArrayStream(list) { + const result = new ArrayStream(); + let prev = Promise.resolve(); + list.forEach((stream, i) => { + prev = prev.then(() => pipe(stream, result, { + preventClose: i !== list.length - 1 + })); + return prev; + }); + return result; +} + +/** + * Get a Reader + * @param {ReadableStream|Uint8array|String} input + * @returns {Reader} + */ +function getReader(input) { + return new Reader(input); +} + +/** + * Get a Writer + * @param {WritableStream} input + * @returns {Writer} + */ +function getWriter(input) { + return new Writer(input); +} + +/** + * Pipe a readable stream to a writable stream. Don't throw on input stream errors, but forward them to the output stream. + * @param {ReadableStream|Uint8array|String} input + * @param {WritableStream} target + * @param {Object} (optional) options + * @returns {Promise} Promise indicating when piping has finished (input stream closed or errored) + * @async + */ +async function pipe(input, target, { + preventClose = false, + preventAbort = false, + preventCancel = false +} = {}) { + if (isStream(input) && !isArrayStream(input)) { + input = toStream(input); + try { + if (input[externalBuffer]) { + const writer = getWriter(target); + for (let i = 0; i < input[externalBuffer].length; i++) { + await writer.ready; + await writer.write(input[externalBuffer][i]); + } + writer.releaseLock(); + } + await input.pipeTo(target, { + preventClose, + preventAbort, + preventCancel + }); + } catch(e) {} + return; + } + input = toArrayStream(input); + const reader = getReader(input); + const writer = getWriter(target); + try { + while (true) { + await writer.ready; + const { done, value } = await reader.read(); + if (done) { + if (!preventClose) await writer.close(); + break; + } + await writer.write(value); + } + } catch (e) { + if (!preventAbort) await writer.abort(e); + } finally { + reader.releaseLock(); + writer.releaseLock(); + } +} + +/** + * Pipe a readable stream through a transform stream. + * @param {ReadableStream|Uint8array|String} input + * @param {Object} (optional) options + * @returns {ReadableStream} transformed stream + */ +function transformRaw(input, options) { + const transformStream = new TransformStream(options); + pipe(input, transformStream.writable); + return transformStream.readable; +} + +/** + * Create a cancelable TransformStream. + * @param {Function} cancel + * @returns {TransformStream} + */ +function transformWithCancel(cancel) { + let pulled = false; + let backpressureChangePromiseResolve; + let outputController; + return { + readable: new ReadableStream({ + start(controller) { + outputController = controller; + }, + pull() { + if (backpressureChangePromiseResolve) { + backpressureChangePromiseResolve(); + } else { + pulled = true; + } + }, + cancel + }, {highWaterMark: 0}), + writable: new WritableStream({ + write: async function(chunk) { + outputController.enqueue(chunk); + if (!pulled) { + await new Promise(resolve => { + backpressureChangePromiseResolve = resolve; + }); + backpressureChangePromiseResolve = null; + } else { + pulled = false; + } + }, + close: outputController.close.bind(outputController), + abort: outputController.error.bind(outputController) + }) + }; +} + +/** + * Transform a stream using helper functions which are called on each chunk, and on stream close, respectively. + * @param {ReadableStream|Uint8array|String} input + * @param {Function} process + * @param {Function} finish + * @returns {ReadableStream|Uint8array|String} + */ +function transform(input, process = () => undefined, finish = () => undefined) { + if (isArrayStream(input)) { + const output = new ArrayStream(); + (async () => { + const data = await readToEnd(input); + const result1 = process(data); + const result2 = finish(); + let result; + if (result1 !== undefined && result2 !== undefined) result = concat([result1, result2]); + else result = result1 !== undefined ? result1 : result2; + const writer = getWriter(output); + await writer.write(result); + await writer.close(); + })(); + return output; + } + if (isStream(input)) { + return transformRaw(input, { + async transform(value, controller) { + try { + const result = await process(value); + if (result !== undefined) controller.enqueue(result); + } catch(e) { + controller.error(e); + } + }, + async flush(controller) { + try { + const result = await finish(); + if (result !== undefined) controller.enqueue(result); + } catch(e) { + controller.error(e); + } + } + }); + } + const result1 = process(input); + const result2 = finish(); + if (result1 !== undefined && result2 !== undefined) return concat([result1, result2]); + return result1 !== undefined ? result1 : result2; +} + +/** + * Transform a stream using a helper function which is passed a readable and a writable stream. + * This function also maintains the possibility to cancel the input stream, + * and does so on cancelation of the output stream, despite cancelation + * normally being impossible when the input stream is being read from. + * @param {ReadableStream|Uint8array|String} input + * @param {Function} fn + * @returns {ReadableStream} + */ +function transformPair(input, fn) { + if (isStream(input) && !isArrayStream(input)) { + let incomingTransformController; + const incoming = new TransformStream({ + start(controller) { + incomingTransformController = controller; + } + }); + + const pipeDonePromise = pipe(input, incoming.writable); + + const outgoing = transformWithCancel(async function() { + incomingTransformController.error(new Error('Readable side was canceled.')); + await pipeDonePromise; + await new Promise(setTimeout); + }); + fn(incoming.readable, outgoing.writable); + return outgoing.readable; + } + input = toArrayStream(input); + const output = new ArrayStream(); + fn(input, output); + return output; +} + +/** + * Parse a stream using a helper function which is passed a Reader. + * The reader additionally has a remainder() method which returns a + * stream pointing to the remainder of input, and is linked to input + * for cancelation. + * @param {ReadableStream|Uint8array|String} input + * @param {Function} fn + * @returns {Any} the return value of fn() + */ +function parse(input, fn) { + let returnValue; + const transformed = transformPair(input, (readable, writable) => { + const reader = getReader(readable); + reader.remainder = () => { + reader.releaseLock(); + pipe(readable, writable); + return transformed; + }; + returnValue = fn(reader); + }); + return returnValue; +} + +/** + * Tee a Stream for reading it twice. The input stream can no longer be read after tee()ing. + * Reading either of the two returned streams will pull from the input stream. + * The input stream will only be canceled if both of the returned streams are canceled. + * @param {ReadableStream|Uint8array|String} input + * @returns {Array} array containing two copies of input + */ +function tee(input) { + if (isArrayStream(input)) { + throw new Error('ArrayStream cannot be tee()d, use clone() instead'); + } + if (isStream(input)) { + const teed = toStream(input).tee(); + teed[0][externalBuffer] = teed[1][externalBuffer] = input[externalBuffer]; + return teed; + } + return [slice(input), slice(input)]; +} + +/** + * Clone a Stream for reading it twice. The input stream can still be read after clone()ing. + * Reading from the clone will pull from the input stream. + * The input stream will only be canceled if both the clone and the input stream are canceled. + * @param {ReadableStream|Uint8array|String} input + * @returns {ReadableStream|Uint8array|String} cloned input + */ +function clone(input) { + if (isArrayStream(input)) { + return input.clone(); + } + if (isStream(input)) { + const teed = tee(input); + overwrite(input, teed[0]); + return teed[1]; + } + return slice(input); +} + +/** + * Clone a Stream for reading it twice. Data will arrive at the same rate as the input stream is being read. + * Reading from the clone will NOT pull from the input stream. Data only arrives when reading the input stream. + * The input stream will NOT be canceled if the clone is canceled, only if the input stream are canceled. + * If the input stream is canceled, the clone will be errored. + * @param {ReadableStream|Uint8array|String} input + * @returns {ReadableStream|Uint8array|String} cloned input + */ +function passiveClone(input) { + if (isArrayStream(input)) { + return clone(input); + } + if (isStream(input)) { + return new ReadableStream({ + start(controller) { + const transformed = transformPair(input, async (readable, writable) => { + const reader = getReader(readable); + const writer = getWriter(writable); + try { + while (true) { + await writer.ready; + const { done, value } = await reader.read(); + if (done) { + try { controller.close(); } catch(e) {} + await writer.close(); + return; + } + try { controller.enqueue(value); } catch(e) {} + await writer.write(value); + } + } catch(e) { + controller.error(e); + await writer.abort(e); + } + }); + overwrite(input, transformed); + } + }); + } + return slice(input); +} + +/** + * Modify a stream object to point to a different stream object. + * This is used internally by clone() and passiveClone() to provide an abstraction over tee(). + * @param {ReadableStream} input + * @param {ReadableStream} clone + */ +function overwrite(input, clone) { + // Overwrite input.getReader, input.locked, etc to point to clone + Object.entries(Object.getOwnPropertyDescriptors(input.constructor.prototype)).forEach(([name, descriptor]) => { + if (name === 'constructor') { + return; + } + if (descriptor.value) { + descriptor.value = descriptor.value.bind(clone); + } else { + descriptor.get = descriptor.get.bind(clone); + } + Object.defineProperty(input, name, descriptor); + }); +} + +/** + * Return a stream pointing to a part of the input stream. + * @param {ReadableStream|Uint8array|String} input + * @returns {ReadableStream|Uint8array|String} clone + */ +function slice(input, begin=0, end=Infinity) { + if (isArrayStream(input)) { + throw new Error('Not implemented'); + } + if (isStream(input)) { + if (begin >= 0 && end >= 0) { + let bytesRead = 0; + return transformRaw(input, { + transform(value, controller) { + if (bytesRead < end) { + if (bytesRead + value.length >= begin) { + controller.enqueue(slice(value, Math.max(begin - bytesRead, 0), end - bytesRead)); + } + bytesRead += value.length; + } else { + controller.terminate(); + } + } + }); + } + if (begin < 0 && (end < 0 || end === Infinity)) { + let lastBytes = []; + return transform(input, value => { + if (value.length >= -begin) lastBytes = [value]; + else lastBytes.push(value); + }, () => slice(concat(lastBytes), begin, end)); + } + if (begin === 0 && end < 0) { + let lastBytes; + return transform(input, value => { + const returnValue = lastBytes ? concat([lastBytes, value]) : value; + if (returnValue.length >= -end) { + lastBytes = slice(returnValue, end); + return slice(returnValue, begin, end); + } else { + lastBytes = returnValue; + } + }); + } + console.warn(`stream.slice(input, ${begin}, ${end}) not implemented efficiently.`); + return fromAsync(async () => slice(await readToEnd(input), begin, end)); + } + if (input[externalBuffer]) { + input = concat(input[externalBuffer].concat([input])); + } + if (isUint8Array(input) && !(NodeBuffer$1 && NodeBuffer$1.isBuffer(input))) { + if (end === Infinity) end = input.length; + return input.subarray(begin, end); + } + return input.slice(begin, end); +} + +/** + * Read a stream to the end and return its contents, concatenated by the join function (defaults to concat). + * @param {ReadableStream|Uint8array|String} input + * @param {Function} join + * @returns {Promise} the return value of join() + * @async + */ +async function readToEnd(input, join=concat) { + if (isArrayStream(input)) { + return input.readToEnd(join); + } + if (isStream(input)) { + return getReader(input).readToEnd(join); + } + return input; +} + +/** + * Cancel a stream. + * @param {ReadableStream|Uint8array|String} input + * @param {Any} reason + * @returns {Promise} indicates when the stream has been canceled + * @async + */ +async function cancel(input, reason) { + if (isStream(input)) { + if (input.cancel) { + return input.cancel(reason); + } + if (input.destroy) { + input.destroy(reason); + await new Promise(setTimeout); + return reason; + } + } +} + +/** + * Convert an async function to an ArrayStream. When the function returns, its return value is written to the stream. + * @param {Function} fn + * @returns {ArrayStream} + */ +function fromAsync(fn) { + const arrayStream = new ArrayStream(); + (async () => { + const writer = getWriter(arrayStream); + try { + await writer.write(await fn()); + await writer.close(); + } catch (e) { + await writer.abort(e); + } + })(); + return arrayStream; +} + +/* eslint-disable new-cap */ + +/** + * @fileoverview + * BigInteger implementation of basic operations + * that wraps the native BigInt library. + * Operations are not constant time, + * but we try and limit timing leakage where we can + * @module biginteger/native + * @private + */ + +/** + * @private + */ +class BigInteger { + /** + * Get a BigInteger (input must be big endian for strings and arrays) + * @param {Number|String|Uint8Array} n - Value to convert + * @throws {Error} on null or undefined input + */ + constructor(n) { + if (n === undefined) { + throw new Error('Invalid BigInteger input'); + } + + if (n instanceof Uint8Array) { + const bytes = n; + const hex = new Array(bytes.length); + for (let i = 0; i < bytes.length; i++) { + const hexByte = bytes[i].toString(16); + hex[i] = (bytes[i] <= 0xF) ? ('0' + hexByte) : hexByte; + } + this.value = BigInt('0x0' + hex.join('')); + } else { + this.value = BigInt(n); + } + } + + clone() { + return new BigInteger(this.value); + } + + /** + * BigInteger increment in place + */ + iinc() { + this.value++; + return this; + } + + /** + * BigInteger increment + * @returns {BigInteger} this + 1. + */ + inc() { + return this.clone().iinc(); + } + + /** + * BigInteger decrement in place + */ + idec() { + this.value--; + return this; + } + + /** + * BigInteger decrement + * @returns {BigInteger} this - 1. + */ + dec() { + return this.clone().idec(); + } + + /** + * BigInteger addition in place + * @param {BigInteger} x - Value to add + */ + iadd(x) { + this.value += x.value; + return this; + } + + /** + * BigInteger addition + * @param {BigInteger} x - Value to add + * @returns {BigInteger} this + x. + */ + add(x) { + return this.clone().iadd(x); + } + + /** + * BigInteger subtraction in place + * @param {BigInteger} x - Value to subtract + */ + isub(x) { + this.value -= x.value; + return this; + } + + /** + * BigInteger subtraction + * @param {BigInteger} x - Value to subtract + * @returns {BigInteger} this - x. + */ + sub(x) { + return this.clone().isub(x); + } + + /** + * BigInteger multiplication in place + * @param {BigInteger} x - Value to multiply + */ + imul(x) { + this.value *= x.value; + return this; + } + + /** + * BigInteger multiplication + * @param {BigInteger} x - Value to multiply + * @returns {BigInteger} this * x. + */ + mul(x) { + return this.clone().imul(x); + } + + /** + * Compute value modulo m, in place + * @param {BigInteger} m - Modulo + */ + imod(m) { + this.value %= m.value; + if (this.isNegative()) { + this.iadd(m); + } + return this; + } + + /** + * Compute value modulo m + * @param {BigInteger} m - Modulo + * @returns {BigInteger} this mod m. + */ + mod(m) { + return this.clone().imod(m); + } + + /** + * Compute modular exponentiation using square and multiply + * @param {BigInteger} e - Exponent + * @param {BigInteger} n - Modulo + * @returns {BigInteger} this ** e mod n. + */ + modExp(e, n) { + if (n.isZero()) throw Error('Modulo cannot be zero'); + if (n.isOne()) return new BigInteger(0); + if (e.isNegative()) throw Error('Unsopported negative exponent'); + + let exp = e.value; + let x = this.value; + + x %= n.value; + let r = BigInt(1); + while (exp > BigInt(0)) { + const lsb = exp & BigInt(1); + exp >>= BigInt(1); // e / 2 + // Always compute multiplication step, to reduce timing leakage + const rx = (r * x) % n.value; + // Update r only if lsb is 1 (odd exponent) + r = lsb ? rx : r; + x = (x * x) % n.value; // Square + } + return new BigInteger(r); + } + + + /** + * Compute the inverse of this value modulo n + * Note: this and and n must be relatively prime + * @param {BigInteger} n - Modulo + * @returns {BigInteger} x such that this*x = 1 mod n + * @throws {Error} if the inverse does not exist + */ + modInv(n) { + const { gcd, x } = this._egcd(n); + if (!gcd.isOne()) { + throw new Error('Inverse does not exist'); + } + return x.add(n).mod(n); + } + + /** + * Extended Eucleadian algorithm (http://anh.cs.luc.edu/331/notes/xgcd.pdf) + * Given a = this and b, compute (x, y) such that ax + by = gdc(a, b) + * @param {BigInteger} b - Second operand + * @returns {{ gcd, x, y: BigInteger }} + */ + _egcd(b) { + let x = BigInt(0); + let y = BigInt(1); + let xPrev = BigInt(1); + let yPrev = BigInt(0); + + let a = this.value; + b = b.value; + + while (b !== BigInt(0)) { + const q = a / b; + let tmp = x; + x = xPrev - q * x; + xPrev = tmp; + + tmp = y; + y = yPrev - q * y; + yPrev = tmp; + + tmp = b; + b = a % b; + a = tmp; + } + + return { + x: new BigInteger(xPrev), + y: new BigInteger(yPrev), + gcd: new BigInteger(a) + }; + } + + /** + * Compute greatest common divisor between this and n + * @param {BigInteger} b - Operand + * @returns {BigInteger} gcd + */ + gcd(b) { + let a = this.value; + b = b.value; + while (b !== BigInt(0)) { + const tmp = b; + b = a % b; + a = tmp; + } + return new BigInteger(a); + } + + /** + * Shift this to the left by x, in place + * @param {BigInteger} x - Shift value + */ + ileftShift(x) { + this.value <<= x.value; + return this; + } + + /** + * Shift this to the left by x + * @param {BigInteger} x - Shift value + * @returns {BigInteger} this << x. + */ + leftShift(x) { + return this.clone().ileftShift(x); + } + + /** + * Shift this to the right by x, in place + * @param {BigInteger} x - Shift value + */ + irightShift(x) { + this.value >>= x.value; + return this; + } + + /** + * Shift this to the right by x + * @param {BigInteger} x - Shift value + * @returns {BigInteger} this >> x. + */ + rightShift(x) { + return this.clone().irightShift(x); + } + + /** + * Whether this value is equal to x + * @param {BigInteger} x + * @returns {Boolean} + */ + equal(x) { + return this.value === x.value; + } + + /** + * Whether this value is less than x + * @param {BigInteger} x + * @returns {Boolean} + */ + lt(x) { + return this.value < x.value; + } + + /** + * Whether this value is less than or equal to x + * @param {BigInteger} x + * @returns {Boolean} + */ + lte(x) { + return this.value <= x.value; + } + + /** + * Whether this value is greater than x + * @param {BigInteger} x + * @returns {Boolean} + */ + gt(x) { + return this.value > x.value; + } + + /** + * Whether this value is greater than or equal to x + * @param {BigInteger} x + * @returns {Boolean} + */ + gte(x) { + return this.value >= x.value; + } + + isZero() { + return this.value === BigInt(0); + } + + isOne() { + return this.value === BigInt(1); + } + + isNegative() { + return this.value < BigInt(0); + } + + isEven() { + return !(this.value & BigInt(1)); + } + + abs() { + const res = this.clone(); + if (this.isNegative()) { + res.value = -res.value; + } + return res; + } + + /** + * Get this value as a string + * @returns {String} this value. + */ + toString() { + return this.value.toString(); + } + + /** + * Get this value as an exact Number (max 53 bits) + * Fails if this value is too large + * @returns {Number} + */ + toNumber() { + const number = Number(this.value); + if (number > Number.MAX_SAFE_INTEGER) { + // We throw and error to conform with the bn.js implementation + throw new Error('Number can only safely store up to 53 bits'); + } + return number; + } + + /** + * Get value of i-th bit + * @param {Number} i - Bit index + * @returns {Number} Bit value. + */ + getBit(i) { + const bit = (this.value >> BigInt(i)) & BigInt(1); + return (bit === BigInt(0)) ? 0 : 1; + } + + /** + * Compute bit length + * @returns {Number} Bit length. + */ + bitLength() { + const zero = new BigInteger(0); + const one = new BigInteger(1); + const negOne = new BigInteger(-1); + + // -1n >> -1n is -1n + // 1n >> 1n is 0n + const target = this.isNegative() ? negOne : zero; + let bitlen = 1; + const tmp = this.clone(); + while (!tmp.irightShift(one).equal(target)) { + bitlen++; + } + return bitlen; + } + + /** + * Compute byte length + * @returns {Number} Byte length. + */ + byteLength() { + const zero = new BigInteger(0); + const negOne = new BigInteger(-1); + + const target = this.isNegative() ? negOne : zero; + const eight = new BigInteger(8); + let len = 1; + const tmp = this.clone(); + while (!tmp.irightShift(eight).equal(target)) { + len++; + } + return len; + } + + /** + * Get Uint8Array representation of this number + * @param {String} endian - Endianess of output array (defaults to 'be') + * @param {Number} length - Of output array + * @returns {Uint8Array} + */ + toUint8Array(endian = 'be', length) { + // we get and parse the hex string (https://coolaj86.com/articles/convert-js-bigints-to-typedarrays/) + // this is faster than shift+mod iterations + let hex = this.value.toString(16); + if (hex.length % 2 === 1) { + hex = '0' + hex; + } + + const rawLength = hex.length / 2; + const bytes = new Uint8Array(length || rawLength); + // parse hex + const offset = length ? (length - rawLength) : 0; + let i = 0; + while (i < rawLength) { + bytes[i + offset] = parseInt(hex.slice(2 * i, 2 * i + 2), 16); + i++; + } + + if (endian !== 'be') { + bytes.reverse(); + } + + return bytes; + } +} + +async function getBigInteger() { + if (util.detectBigInt()) { + return BigInteger; + } else { + const { default: BigInteger } = await Promise.resolve().then(function () { return bn_interface; }); + return BigInteger; + } +} + +const debugMode = (() => { + try { + return process.env.NODE_ENV === 'development'; // eslint-disable-line no-process-env + } catch (e) {} + return false; +})(); + +const util = { + isString: function(data) { + return typeof data === 'string' || String.prototype.isPrototypeOf(data); + }, + + isArray: function(data) { + return Array.prototype.isPrototypeOf(data); + }, + + isUint8Array: isUint8Array, + + isStream: isStream, + + readNumber: function (bytes) { + let n = 0; + for (let i = 0; i < bytes.length; i++) { + n += (256 ** i) * bytes[bytes.length - 1 - i]; + } + return n; + }, + + writeNumber: function (n, bytes) { + const b = new Uint8Array(bytes); + for (let i = 0; i < bytes; i++) { + b[i] = (n >> (8 * (bytes - i - 1))) & 0xFF; + } + + return b; + }, + + readDate: function (bytes) { + const n = util.readNumber(bytes); + const d = new Date(n * 1000); + return d; + }, + + writeDate: function (time) { + const numeric = Math.floor(time.getTime() / 1000); + + return util.writeNumber(numeric, 4); + }, + + normalizeDate: function (time = Date.now()) { + return time === null || time === Infinity ? time : new Date(Math.floor(+time / 1000) * 1000); + }, + + /** + * Read one MPI from bytes in input + * @param {Uint8Array} bytes - Input data to parse + * @returns {Uint8Array} Parsed MPI. + */ + readMPI: function (bytes) { + const bits = (bytes[0] << 8) | bytes[1]; + const bytelen = (bits + 7) >>> 3; + return bytes.subarray(2, 2 + bytelen); + }, + + /** + * Left-pad Uint8Array to length by adding 0x0 bytes + * @param {Uint8Array} bytes - Data to pad + * @param {Number} length - Padded length + * @returns {Uint8Array} Padded bytes. + */ + leftPad(bytes, length) { + const padded = new Uint8Array(length); + const offset = length - bytes.length; + padded.set(bytes, offset); + return padded; + }, + + /** + * Convert a Uint8Array to an MPI-formatted Uint8Array. + * @param {Uint8Array} bin - An array of 8-bit integers to convert + * @returns {Uint8Array} MPI-formatted Uint8Array. + */ + uint8ArrayToMPI: function (bin) { + const bitSize = util.uint8ArrayBitLength(bin); + if (bitSize === 0) { + throw new Error('Zero MPI'); + } + const stripped = bin.subarray(bin.length - Math.ceil(bitSize / 8)); + const prefix = new Uint8Array([(bitSize & 0xFF00) >> 8, bitSize & 0xFF]); + return util.concatUint8Array([prefix, stripped]); + }, + + /** + * Return bit length of the input data + * @param {Uint8Array} bin input data (big endian) + * @returns bit length + */ + uint8ArrayBitLength: function (bin) { + let i; // index of leading non-zero byte + for (i = 0; i < bin.length; i++) if (bin[i] !== 0) break; + if (i === bin.length) { + return 0; + } + const stripped = bin.subarray(i); + return (stripped.length - 1) * 8 + util.nbits(stripped[0]); + }, + + /** + * Convert a hex string to an array of 8-bit integers + * @param {String} hex - A hex string to convert + * @returns {Uint8Array} An array of 8-bit integers. + */ + hexToUint8Array: function (hex) { + const result = new Uint8Array(hex.length >> 1); + for (let k = 0; k < hex.length >> 1; k++) { + result[k] = parseInt(hex.substr(k << 1, 2), 16); + } + return result; + }, + + /** + * Convert an array of 8-bit integers to a hex string + * @param {Uint8Array} bytes - Array of 8-bit integers to convert + * @returns {String} Hexadecimal representation of the array. + */ + uint8ArrayToHex: function (bytes) { + const r = []; + const e = bytes.length; + let c = 0; + let h; + while (c < e) { + h = bytes[c++].toString(16); + while (h.length < 2) { + h = '0' + h; + } + r.push('' + h); + } + return r.join(''); + }, + + /** + * Convert a string to an array of 8-bit integers + * @param {String} str - String to convert + * @returns {Uint8Array} An array of 8-bit integers. + */ + stringToUint8Array: function (str) { + return transform(str, str => { + if (!util.isString(str)) { + throw new Error('stringToUint8Array: Data must be in the form of a string'); + } + + const result = new Uint8Array(str.length); + for (let i = 0; i < str.length; i++) { + result[i] = str.charCodeAt(i); + } + return result; + }); + }, + + /** + * Convert an array of 8-bit integers to a string + * @param {Uint8Array} bytes - An array of 8-bit integers to convert + * @returns {String} String representation of the array. + */ + uint8ArrayToString: function (bytes) { + bytes = new Uint8Array(bytes); + const result = []; + const bs = 1 << 14; + const j = bytes.length; + + for (let i = 0; i < j; i += bs) { + result.push(String.fromCharCode.apply(String, bytes.subarray(i, i + bs < j ? i + bs : j))); + } + return result.join(''); + }, + + /** + * Convert a native javascript string to a Uint8Array of utf8 bytes + * @param {String|ReadableStream} str - The string to convert + * @returns {Uint8Array|ReadableStream} A valid squence of utf8 bytes. + */ + encodeUTF8: function (str) { + const encoder = new TextEncoder('utf-8'); + // eslint-disable-next-line no-inner-declarations + function process(value, lastChunk = false) { + return encoder.encode(value, { stream: !lastChunk }); + } + return transform(str, process, () => process('', true)); + }, + + /** + * Convert a Uint8Array of utf8 bytes to a native javascript string + * @param {Uint8Array|ReadableStream} utf8 - A valid squence of utf8 bytes + * @returns {String|ReadableStream} A native javascript string. + */ + decodeUTF8: function (utf8) { + const decoder = new TextDecoder('utf-8'); + // eslint-disable-next-line no-inner-declarations + function process(value, lastChunk = false) { + return decoder.decode(value, { stream: !lastChunk }); + } + return transform(utf8, process, () => process(new Uint8Array(), true)); + }, + + /** + * Concat a list of Uint8Arrays, Strings or Streams + * The caller must not mix Uint8Arrays with Strings, but may mix Streams with non-Streams. + * @param {Array} Array - Of Uint8Arrays/Strings/Streams to concatenate + * @returns {Uint8Array|String|ReadableStream} Concatenated array. + */ + concat: concat, + + /** + * Concat Uint8Arrays + * @param {Array} Array - Of Uint8Arrays to concatenate + * @returns {Uint8Array} Concatenated array. + */ + concatUint8Array: concatUint8Array, + + /** + * Check Uint8Array equality + * @param {Uint8Array} array1 - First array + * @param {Uint8Array} array2 - Second array + * @returns {Boolean} Equality. + */ + equalsUint8Array: function (array1, array2) { + if (!util.isUint8Array(array1) || !util.isUint8Array(array2)) { + throw new Error('Data must be in the form of a Uint8Array'); + } + + if (array1.length !== array2.length) { + return false; + } + + for (let i = 0; i < array1.length; i++) { + if (array1[i] !== array2[i]) { + return false; + } + } + return true; + }, + + /** + * Calculates a 16bit sum of a Uint8Array by adding each character + * codes modulus 65535 + * @param {Uint8Array} Uint8Array - To create a sum of + * @returns {Uint8Array} 2 bytes containing the sum of all charcodes % 65535. + */ + writeChecksum: function (text) { + let s = 0; + for (let i = 0; i < text.length; i++) { + s = (s + text[i]) & 0xFFFF; + } + return util.writeNumber(s, 2); + }, + + /** + * Helper function to print a debug message. Debug + * messages are only printed if + * @param {String} str - String of the debug message + */ + printDebug: function (str) { + if (debugMode) { + console.log(str); + } + }, + + /** + * Helper function to print a debug error. Debug + * messages are only printed if + * @param {String} str - String of the debug message + */ + printDebugError: function (error) { + if (debugMode) { + console.error(error); + } + }, + + // returns bit length of the integer x + nbits: function (x) { + let r = 1; + let t = x >>> 16; + if (t !== 0) { + x = t; + r += 16; + } + t = x >> 8; + if (t !== 0) { + x = t; + r += 8; + } + t = x >> 4; + if (t !== 0) { + x = t; + r += 4; + } + t = x >> 2; + if (t !== 0) { + x = t; + r += 2; + } + t = x >> 1; + if (t !== 0) { + x = t; + r += 1; + } + return r; + }, + + /** + * If S[1] == 0, then double(S) == (S[2..128] || 0); + * otherwise, double(S) == (S[2..128] || 0) xor + * (zeros(120) || 10000111). + * + * Both OCB and EAX (through CMAC) require this function to be constant-time. + * + * @param {Uint8Array} data + */ + double: function(data) { + const doubleVar = new Uint8Array(data.length); + const last = data.length - 1; + for (let i = 0; i < last; i++) { + doubleVar[i] = (data[i] << 1) ^ (data[i + 1] >> 7); + } + doubleVar[last] = (data[last] << 1) ^ ((data[0] >> 7) * 0x87); + return doubleVar; + }, + + /** + * Shift a Uint8Array to the right by n bits + * @param {Uint8Array} array - The array to shift + * @param {Integer} bits - Amount of bits to shift (MUST be smaller + * than 8) + * @returns {String} Resulting array. + */ + shiftRight: function (array, bits) { + if (bits) { + for (let i = array.length - 1; i >= 0; i--) { + array[i] >>= bits; + if (i > 0) { + array[i] |= (array[i - 1] << (8 - bits)); + } + } + } + return array; + }, + + /** + * Get native Web Cryptography api, only the current version of the spec. + * @returns {Object} The SubtleCrypto api or 'undefined'. + */ + getWebCrypto: function() { + return typeof globalThis !== 'undefined' && globalThis.crypto && globalThis.crypto.subtle; + }, + + /** + * Detect Node.js runtime. + */ + detectNode: function() { + return typeof globalThis.process === 'object' && + typeof globalThis.process.versions === 'object'; + }, + + /** + * Detect native BigInt support + */ + detectBigInt: () => typeof BigInt !== 'undefined', + + /** + * Get BigInteger class + * It wraps the native BigInt type if it's available + * Otherwise it relies on bn.js + * @returns {BigInteger} + * @async + */ + getBigInteger, + + /** + * Get native Node.js crypto api. + * @returns {Object} The crypto module or 'undefined'. + */ + getNodeCrypto: function() { + return crypto__default['default']; + }, + + getNodeZlib: function() { + return zlib__default['default']; + }, + + /** + * Get native Node.js Buffer constructor. This should be used since + * Buffer is not available under browserify. + * @returns {Function} The Buffer constructor or 'undefined'. + */ + getNodeBuffer: function() { + return (buffer__default['default'] || {}).Buffer; + }, + + getHardwareConcurrency: function() { + if (util.detectNode()) { + const os = os__default['default']; + return os.cpus().length; + } + + return navigator.hardwareConcurrency || 1; + }, + + isEmailAddress: function(data) { + if (!util.isString(data)) { + return false; + } + const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+([a-zA-Z]{2,}|xn--[a-zA-Z\-0-9]+)))$/; + return re.test(data); + }, + + /** + * Normalize line endings to + * Support any encoding where CR=0x0D, LF=0x0A + */ + canonicalizeEOL: function(data) { + const CR = 13; + const LF = 10; + let carryOverCR = false; + + return transform(data, bytes => { + if (carryOverCR) { + bytes = util.concatUint8Array([new Uint8Array([CR]), bytes]); + } + + if (bytes[bytes.length - 1] === CR) { + carryOverCR = true; + bytes = bytes.subarray(0, -1); + } else { + carryOverCR = false; + } + + let index; + const indices = []; + for (let i = 0; ; i = index) { + index = bytes.indexOf(LF, i) + 1; + if (index) { + if (bytes[index - 2] !== CR) indices.push(index); + } else { + break; + } + } + if (!indices.length) { + return bytes; + } + + const normalized = new Uint8Array(bytes.length + indices.length); + let j = 0; + for (let i = 0; i < indices.length; i++) { + const sub = bytes.subarray(indices[i - 1] || 0, indices[i]); + normalized.set(sub, j); + j += sub.length; + normalized[j - 1] = CR; + normalized[j] = LF; + j++; + } + normalized.set(bytes.subarray(indices[indices.length - 1] || 0), j); + return normalized; + }, () => (carryOverCR ? new Uint8Array([CR]) : undefined)); + }, + + /** + * Convert line endings from canonicalized to native + * Support any encoding where CR=0x0D, LF=0x0A + */ + nativeEOL: function(data) { + const CR = 13; + const LF = 10; + let carryOverCR = false; + + return transform(data, bytes => { + if (carryOverCR && bytes[0] !== LF) { + bytes = util.concatUint8Array([new Uint8Array([CR]), bytes]); + } else { + bytes = new Uint8Array(bytes); // Don't mutate passed bytes + } + + if (bytes[bytes.length - 1] === CR) { + carryOverCR = true; + bytes = bytes.subarray(0, -1); + } else { + carryOverCR = false; + } + + let index; + let j = 0; + for (let i = 0; i !== bytes.length; i = index) { + index = bytes.indexOf(CR, i) + 1; + if (!index) index = bytes.length; + const last = index - (bytes[index] === LF ? 1 : 0); + if (i) bytes.copyWithin(j, i, last); + j += last - i; + } + return bytes.subarray(0, j); + }, () => (carryOverCR ? new Uint8Array([CR]) : undefined)); + }, + + /** + * Remove trailing spaces and tabs from each line + */ + removeTrailingSpaces: function(text) { + return text.split('\n').map(line => { + let i = line.length - 1; + for (; i >= 0 && (line[i] === ' ' || line[i] === '\t'); i--); + return line.substr(0, i + 1); + }).join('\n'); + }, + + wrapError: function(message, error) { + if (!error) { + return new Error(message); + } + + // update error message + try { + error.message = message + ': ' + error.message; + } catch (e) {} + + return error; + }, + + /** + * Map allowed packet tags to corresponding classes + * Meant to be used to format `allowedPacket` for Packetlist.read + * @param {Array} allowedClasses + * @returns {Object} map from enum.packet to corresponding *Packet class + */ + constructAllowedPackets: function(allowedClasses) { + const map = {}; + allowedClasses.forEach(PacketClass => { + if (!PacketClass.tag) { + throw new Error('Invalid input: expected a packet class'); + } + map[PacketClass.tag] = PacketClass; + }); + return map; + }, + + /** + * Return a Promise that will resolve as soon as one of the promises in input resolves + * or will reject if all input promises all rejected + * (similar to Promise.any, but with slightly different error handling) + * @param {Array} promises + * @return {Promise} Promise resolving to the result of the fastest fulfilled promise + * or rejected with the Error of the last resolved Promise (if all promises are rejected) + */ + anyPromise: function(promises) { + return new Promise(async (resolve, reject) => { + let exception; + await Promise.all(promises.map(async promise => { + try { + resolve(await promise); + } catch (e) { + exception = e; + } + })); + reject(exception); + }); + }, + + /** + * Return either `a` or `b` based on `cond`, in algorithmic constant time. + * @param {Boolean} cond + * @param {Uint8Array} a + * @param {Uint8Array} b + * @returns `a` if `cond` is true, `b` otherwise + */ + selectUint8Array: function(cond, a, b) { + const length = Math.max(a.length, b.length); + const result = new Uint8Array(length); + let end = 0; + for (let i = 0; i < result.length; i++) { + result[i] = (a[i] & (256 - cond)) | (b[i] & (255 + cond)); + end += (cond & i < a.length) | ((1 - cond) & i < b.length); + } + return result.subarray(0, end); + }, + /** + * Return either `a` or `b` based on `cond`, in algorithmic constant time. + * NB: it only supports `a, b` with values between 0-255. + * @param {Boolean} cond + * @param {Uint8} a + * @param {Uint8} b + * @returns `a` if `cond` is true, `b` otherwise + */ + selectUint8: function(cond, a, b) { + return (a & (256 - cond)) | (b & (255 + cond)); + } +}; + +/* OpenPGP radix-64/base64 string encoding/decoding + * Copyright 2005 Herbert Hanewinkel, www.haneWIN.de + * version 1.0, check www.haneWIN.de for the latest version + * + * This software is provided as-is, without express or implied warranty. + * Permission to use, copy, modify, distribute or sell this software, with or + * without fee, for any purpose and by any individual or organization, is hereby + * granted, provided that the above copyright notice and this paragraph appear + * in all copies. Distribution as a part of an application or binary must + * include the above copyright notice in the documentation and/or other materials + * provided with the application or distribution. + */ + +const Buffer = util.getNodeBuffer(); + +let encodeChunk; +let decodeChunk; +if (Buffer) { + encodeChunk = buf => Buffer.from(buf).toString('base64'); + decodeChunk = str => { + const b = Buffer.from(str, 'base64'); + return new Uint8Array(b.buffer, b.byteOffset, b.byteLength); + }; +} else { + encodeChunk = buf => btoa(util.uint8ArrayToString(buf)); + decodeChunk = str => util.stringToUint8Array(atob(str)); +} + +/** + * Convert binary array to radix-64 + * @param {Uint8Array | ReadableStream} data - Uint8Array to convert + * @returns {String | ReadableStream} Radix-64 version of input string. + * @static + */ +function encode(data) { + let buf = new Uint8Array(); + return transform(data, value => { + buf = util.concatUint8Array([buf, value]); + const r = []; + const bytesPerLine = 45; // 60 chars per line * (3 bytes / 4 chars of base64). + const lines = Math.floor(buf.length / bytesPerLine); + const bytes = lines * bytesPerLine; + const encoded = encodeChunk(buf.subarray(0, bytes)); + for (let i = 0; i < lines; i++) { + r.push(encoded.substr(i * 60, 60)); + r.push('\n'); + } + buf = buf.subarray(bytes); + return r.join(''); + }, () => (buf.length ? encodeChunk(buf) + '\n' : '')); +} + +/** + * Convert radix-64 to binary array + * @param {String | ReadableStream} data - Radix-64 string to convert + * @returns {Uint8Array | ReadableStream} Binary array version of input string. + * @static + */ +function decode(data) { + let buf = ''; + return transform(data, value => { + buf += value; + + // Count how many whitespace characters there are in buf + let spaces = 0; + const spacechars = [' ', '\t', '\r', '\n']; + for (let i = 0; i < spacechars.length; i++) { + const spacechar = spacechars[i]; + for (let pos = buf.indexOf(spacechar); pos !== -1; pos = buf.indexOf(spacechar, pos + 1)) { + spaces++; + } + } + + // Backtrack until we have 4n non-whitespace characters + // that we can safely base64-decode + let length = buf.length; + for (; length > 0 && (length - spaces) % 4 !== 0; length--) { + if (spacechars.includes(buf[length])) spaces--; + } + + const decoded = decodeChunk(buf.substr(0, length)); + buf = buf.substr(length); + return decoded; + }, () => decodeChunk(buf)); +} + +/** + * Convert a Base-64 encoded string an array of 8-bit integer + * + * Note: accepts both Radix-64 and URL-safe strings + * @param {String} base64 - Base-64 encoded string to convert + * @returns {Uint8Array} An array of 8-bit integers. + */ +function b64ToUint8Array(base64) { + return decode(base64.replace(/-/g, '+').replace(/_/g, '/')); +} + +/** + * Convert an array of 8-bit integer to a Base-64 encoded string + * @param {Uint8Array} bytes - An array of 8-bit integers to convert + * @param {bool} url - If true, output is URL-safe + * @returns {String} Base-64 encoded string. + */ +function uint8ArrayToB64(bytes, url) { + let encoded = encode(bytes).replace(/[\r\n]/g, ''); + if (url) { + encoded = encoded.replace(/[+]/g, '-').replace(/[/]/g, '_').replace(/[=]/g, ''); + } + return encoded; +} + +/** + * @module enums + */ + +const byValue = Symbol('byValue'); + +var enums = { + + /** Maps curve names under various standards to one + * @see {@link https://wiki.gnupg.org/ECC|ECC - GnuPG wiki} + * @enum {String} + * @readonly + */ + curve: { + /** NIST P-256 Curve */ + 'p256': 'p256', + 'P-256': 'p256', + 'secp256r1': 'p256', + 'prime256v1': 'p256', + '1.2.840.10045.3.1.7': 'p256', + '2a8648ce3d030107': 'p256', + '2A8648CE3D030107': 'p256', + + /** NIST P-384 Curve */ + 'p384': 'p384', + 'P-384': 'p384', + 'secp384r1': 'p384', + '1.3.132.0.34': 'p384', + '2b81040022': 'p384', + '2B81040022': 'p384', + + /** NIST P-521 Curve */ + 'p521': 'p521', + 'P-521': 'p521', + 'secp521r1': 'p521', + '1.3.132.0.35': 'p521', + '2b81040023': 'p521', + '2B81040023': 'p521', + + /** SECG SECP256k1 Curve */ + 'secp256k1': 'secp256k1', + '1.3.132.0.10': 'secp256k1', + '2b8104000a': 'secp256k1', + '2B8104000A': 'secp256k1', + + /** Ed25519 */ + 'ED25519': 'ed25519', + 'ed25519': 'ed25519', + 'Ed25519': 'ed25519', + '1.3.6.1.4.1.11591.15.1': 'ed25519', + '2b06010401da470f01': 'ed25519', + '2B06010401DA470F01': 'ed25519', + + /** Curve25519 */ + 'X25519': 'curve25519', + 'cv25519': 'curve25519', + 'curve25519': 'curve25519', + 'Curve25519': 'curve25519', + '1.3.6.1.4.1.3029.1.5.1': 'curve25519', + '2b060104019755010501': 'curve25519', + '2B060104019755010501': 'curve25519', + + /** BrainpoolP256r1 Curve */ + 'brainpoolP256r1': 'brainpoolP256r1', + '1.3.36.3.3.2.8.1.1.7': 'brainpoolP256r1', + '2b2403030208010107': 'brainpoolP256r1', + '2B2403030208010107': 'brainpoolP256r1', + + /** BrainpoolP384r1 Curve */ + 'brainpoolP384r1': 'brainpoolP384r1', + '1.3.36.3.3.2.8.1.1.11': 'brainpoolP384r1', + '2b240303020801010b': 'brainpoolP384r1', + '2B240303020801010B': 'brainpoolP384r1', + + /** BrainpoolP512r1 Curve */ + 'brainpoolP512r1': 'brainpoolP512r1', + '1.3.36.3.3.2.8.1.1.13': 'brainpoolP512r1', + '2b240303020801010d': 'brainpoolP512r1', + '2B240303020801010D': 'brainpoolP512r1' + }, + + /** A string to key specifier type + * @enum {Integer} + * @readonly + */ + s2k: { + simple: 0, + salted: 1, + iterated: 3, + gnu: 101 + }, + + /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-9.1|RFC4880bis-04, section 9.1} + * @enum {Integer} + * @readonly + */ + publicKey: { + /** RSA (Encrypt or Sign) [HAC] */ + rsaEncryptSign: 1, + /** RSA (Encrypt only) [HAC] */ + rsaEncrypt: 2, + /** RSA (Sign only) [HAC] */ + rsaSign: 3, + /** Elgamal (Encrypt only) [ELGAMAL] [HAC] */ + elgamal: 16, + /** DSA (Sign only) [FIPS186] [HAC] */ + dsa: 17, + /** ECDH (Encrypt only) [RFC6637] */ + ecdh: 18, + /** ECDSA (Sign only) [RFC6637] */ + ecdsa: 19, + /** EdDSA (Sign only) + * [{@link https://tools.ietf.org/html/draft-koch-eddsa-for-openpgp-04|Draft RFC}] */ + eddsa: 22, + /** Reserved for AEDH */ + aedh: 23, + /** Reserved for AEDSA */ + aedsa: 24 + }, + + /** {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC4880, section 9.2} + * @enum {Integer} + * @readonly + */ + symmetric: { + plaintext: 0, + /** Not implemented! */ + idea: 1, + tripledes: 2, + cast5: 3, + blowfish: 4, + aes128: 7, + aes192: 8, + aes256: 9, + twofish: 10 + }, + + /** {@link https://tools.ietf.org/html/rfc4880#section-9.3|RFC4880, section 9.3} + * @enum {Integer} + * @readonly + */ + compression: { + uncompressed: 0, + /** RFC1951 */ + zip: 1, + /** RFC1950 */ + zlib: 2, + bzip2: 3 + }, + + /** {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC4880, section 9.4} + * @enum {Integer} + * @readonly + */ + hash: { + md5: 1, + sha1: 2, + ripemd: 3, + sha256: 8, + sha384: 9, + sha512: 10, + sha224: 11 + }, + + /** A list of hash names as accepted by webCrypto functions. + * {@link https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest|Parameters, algo} + * @enum {String} + */ + webHash: { + 'SHA-1': 2, + 'SHA-256': 8, + 'SHA-384': 9, + 'SHA-512': 10 + }, + + /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-9.6|RFC4880bis-04, section 9.6} + * @enum {Integer} + * @readonly + */ + aead: { + eax: 1, + ocb: 2, + experimentalGCM: 100 // Private algorithm + }, + + /** A list of packet types and numeric tags associated with them. + * @enum {Integer} + * @readonly + */ + packet: { + publicKeyEncryptedSessionKey: 1, + signature: 2, + symEncryptedSessionKey: 3, + onePassSignature: 4, + secretKey: 5, + publicKey: 6, + secretSubkey: 7, + compressedData: 8, + symmetricallyEncryptedData: 9, + marker: 10, + literalData: 11, + trust: 12, + userID: 13, + publicSubkey: 14, + userAttribute: 17, + symEncryptedIntegrityProtectedData: 18, + modificationDetectionCode: 19, + aeadEncryptedData: 20 // see IETF draft: https://tools.ietf.org/html/draft-ford-openpgp-format-00#section-2.1 + }, + + /** Data types in the literal packet + * @enum {Integer} + * @readonly + */ + literal: { + /** Binary data 'b' */ + binary: 'b'.charCodeAt(), + /** Text data 't' */ + text: 't'.charCodeAt(), + /** Utf8 data 'u' */ + utf8: 'u'.charCodeAt(), + /** MIME message body part 'm' */ + mime: 'm'.charCodeAt() + }, + + + /** One pass signature packet type + * @enum {Integer} + * @readonly + */ + signature: { + /** 0x00: Signature of a binary document. */ + binary: 0, + /** 0x01: Signature of a canonical text document. + * + * Canonicalyzing the document by converting line endings. */ + text: 1, + /** 0x02: Standalone signature. + * + * This signature is a signature of only its own subpacket contents. + * It is calculated identically to a signature over a zero-lengh + * binary document. Note that it doesn't make sense to have a V3 + * standalone signature. */ + standalone: 2, + /** 0x10: Generic certification of a User ID and Public-Key packet. + * + * The issuer of this certification does not make any particular + * assertion as to how well the certifier has checked that the owner + * of the key is in fact the person described by the User ID. */ + certGeneric: 16, + /** 0x11: Persona certification of a User ID and Public-Key packet. + * + * The issuer of this certification has not done any verification of + * the claim that the owner of this key is the User ID specified. */ + certPersona: 17, + /** 0x12: Casual certification of a User ID and Public-Key packet. + * + * The issuer of this certification has done some casual + * verification of the claim of identity. */ + certCasual: 18, + /** 0x13: Positive certification of a User ID and Public-Key packet. + * + * The issuer of this certification has done substantial + * verification of the claim of identity. + * + * Most OpenPGP implementations make their "key signatures" as 0x10 + * certifications. Some implementations can issue 0x11-0x13 + * certifications, but few differentiate between the types. */ + certPositive: 19, + /** 0x30: Certification revocation signature + * + * This signature revokes an earlier User ID certification signature + * (signature class 0x10 through 0x13) or direct-key signature + * (0x1F). It should be issued by the same key that issued the + * revoked signature or an authorized revocation key. The signature + * is computed over the same data as the certificate that it + * revokes, and should have a later creation date than that + * certificate. */ + certRevocation: 48, + /** 0x18: Subkey Binding Signature + * + * This signature is a statement by the top-level signing key that + * indicates that it owns the subkey. This signature is calculated + * directly on the primary key and subkey, and not on any User ID or + * other packets. A signature that binds a signing subkey MUST have + * an Embedded Signature subpacket in this binding signature that + * contains a 0x19 signature made by the signing subkey on the + * primary key and subkey. */ + subkeyBinding: 24, + /** 0x19: Primary Key Binding Signature + * + * This signature is a statement by a signing subkey, indicating + * that it is owned by the primary key and subkey. This signature + * is calculated the same way as a 0x18 signature: directly on the + * primary key and subkey, and not on any User ID or other packets. + * + * When a signature is made over a key, the hash data starts with the + * octet 0x99, followed by a two-octet length of the key, and then body + * of the key packet. (Note that this is an old-style packet header for + * a key packet with two-octet length.) A subkey binding signature + * (type 0x18) or primary key binding signature (type 0x19) then hashes + * the subkey using the same format as the main key (also using 0x99 as + * the first octet). */ + keyBinding: 25, + /** 0x1F: Signature directly on a key + * + * This signature is calculated directly on a key. It binds the + * information in the Signature subpackets to the key, and is + * appropriate to be used for subpackets that provide information + * about the key, such as the Revocation Key subpacket. It is also + * appropriate for statements that non-self certifiers want to make + * about the key itself, rather than the binding between a key and a + * name. */ + key: 31, + /** 0x20: Key revocation signature + * + * The signature is calculated directly on the key being revoked. A + * revoked key is not to be used. Only revocation signatures by the + * key being revoked, or by an authorized revocation key, should be + * considered valid revocation signatures.a */ + keyRevocation: 32, + /** 0x28: Subkey revocation signature + * + * The signature is calculated directly on the subkey being revoked. + * A revoked subkey is not to be used. Only revocation signatures + * by the top-level signature key that is bound to this subkey, or + * by an authorized revocation key, should be considered valid + * revocation signatures. + * + * Key revocation signatures (types 0x20 and 0x28) + * hash only the key being revoked. */ + subkeyRevocation: 40, + /** 0x40: Timestamp signature. + * This signature is only meaningful for the timestamp contained in + * it. */ + timestamp: 64, + /** 0x50: Third-Party Confirmation signature. + * + * This signature is a signature over some other OpenPGP Signature + * packet(s). It is analogous to a notary seal on the signed data. + * A third-party signature SHOULD include Signature Target + * subpacket(s) to give easy identification. Note that we really do + * mean SHOULD. There are plausible uses for this (such as a blind + * party that only sees the signature, not the key or source + * document) that cannot include a target subpacket. */ + thirdParty: 80 + }, + + /** Signature subpacket type + * @enum {Integer} + * @readonly + */ + signatureSubpacket: { + signatureCreationTime: 2, + signatureExpirationTime: 3, + exportableCertification: 4, + trustSignature: 5, + regularExpression: 6, + revocable: 7, + keyExpirationTime: 9, + placeholderBackwardsCompatibility: 10, + preferredSymmetricAlgorithms: 11, + revocationKey: 12, + issuer: 16, + notationData: 20, + preferredHashAlgorithms: 21, + preferredCompressionAlgorithms: 22, + keyServerPreferences: 23, + preferredKeyServer: 24, + primaryUserID: 25, + policyURI: 26, + keyFlags: 27, + signersUserID: 28, + reasonForRevocation: 29, + features: 30, + signatureTarget: 31, + embeddedSignature: 32, + issuerFingerprint: 33, + preferredAEADAlgorithms: 34 + }, + + /** Key flags + * @enum {Integer} + * @readonly + */ + keyFlags: { + /** 0x01 - This key may be used to certify other keys. */ + certifyKeys: 1, + /** 0x02 - This key may be used to sign data. */ + signData: 2, + /** 0x04 - This key may be used to encrypt communications. */ + encryptCommunication: 4, + /** 0x08 - This key may be used to encrypt storage. */ + encryptStorage: 8, + /** 0x10 - The private component of this key may have been split + * by a secret-sharing mechanism. */ + splitPrivateKey: 16, + /** 0x20 - This key may be used for authentication. */ + authentication: 32, + /** 0x80 - The private component of this key may be in the + * possession of more than one person. */ + sharedPrivateKey: 128 + }, + + /** Armor type + * @enum {Integer} + * @readonly + */ + armor: { + multipartSection: 0, + multipartLast: 1, + signed: 2, + message: 3, + publicKey: 4, + privateKey: 5, + signature: 6 + }, + + /** {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.23|RFC4880, section 5.2.3.23} + * @enum {Integer} + * @readonly + */ + reasonForRevocation: { + /** No reason specified (key revocations or cert revocations) */ + noReason: 0, + /** Key is superseded (key revocations) */ + keySuperseded: 1, + /** Key material has been compromised (key revocations) */ + keyCompromised: 2, + /** Key is retired and no longer used (key revocations) */ + keyRetired: 3, + /** User ID information is no longer valid (cert revocations) */ + userIDInvalid: 32 + }, + + /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.2.3.25|RFC4880bis-04, section 5.2.3.25} + * @enum {Integer} + * @readonly + */ + features: { + /** 0x01 - Modification Detection (packets 18 and 19) */ + modificationDetection: 1, + /** 0x02 - AEAD Encrypted Data Packet (packet 20) and version 5 + * Symmetric-Key Encrypted Session Key Packets (packet 3) */ + aead: 2, + /** 0x04 - Version 5 Public-Key Packet format and corresponding new + * fingerprint format */ + v5Keys: 4 + }, + + /** + * Asserts validity of given value and converts from string/integer to integer. + * @param {Object} type target enum type + * @param {String|Integer} e value to check and/or convert + * @returns {Integer} enum value if it exists + * @throws {Error} if the value is invalid + */ + write: function(type, e) { + if (typeof e === 'number') { + e = this.read(type, e); + } + + if (type[e] !== undefined) { + return type[e]; + } + + throw new Error('Invalid enum value.'); + }, + + /** + * Converts enum integer value to the corresponding string, if it exists. + * @param {Object} type target enum type + * @param {Integer} e value to convert + * @returns {String} name of enum value if it exists + * @throws {Error} if the value is invalid + */ + read: function(type, e) { + if (!type[byValue]) { + type[byValue] = []; + Object.entries(type).forEach(([key, value]) => { + type[byValue][value] = key; + }); + } + + if (type[byValue][e] !== undefined) { + return type[byValue][e]; + } + + throw new Error('Invalid enum value.'); + } +}; + +// GPG4Browsers - An OpenPGP implementation in javascript + +var defaultConfig = { + /** + * @memberof module:config + * @property {Integer} preferredHashAlgorithm Default hash algorithm {@link module:enums.hash} + */ + preferredHashAlgorithm: enums.hash.sha256, + /** + * @memberof module:config + * @property {Integer} preferredSymmetricAlgorithm Default encryption cipher {@link module:enums.symmetric} + */ + preferredSymmetricAlgorithm: enums.symmetric.aes256, + /** + * @memberof module:config + * @property {Integer} compression Default compression algorithm {@link module:enums.compression} + */ + preferredCompressionAlgorithm: enums.compression.uncompressed, + /** + * @memberof module:config + * @property {Integer} deflateLevel Default zip/zlib compression level, between 1 and 9 + */ + deflateLevel: 6, + + /** + * Use Authenticated Encryption with Additional Data (AEAD) protection for symmetric encryption. + * Note: not all OpenPGP implementations are compatible with this option. + * **FUTURE OPENPGP.JS VERSIONS MAY BREAK COMPATIBILITY WHEN USING THIS OPTION** + * @see {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-07|RFC4880bis-07} + * @memberof module:config + * @property {Boolean} aeadProtect + */ + aeadProtect: false, + /** + * Default Authenticated Encryption with Additional Data (AEAD) encryption mode + * Only has an effect when aeadProtect is set to true. + * @memberof module:config + * @property {Integer} preferredAEADAlgorithm Default AEAD mode {@link module:enums.aead} + */ + preferredAEADAlgorithm: enums.aead.eax, + /** + * Chunk Size Byte for Authenticated Encryption with Additional Data (AEAD) mode + * Only has an effect when aeadProtect is set to true. + * Must be an integer value from 0 to 56. + * @memberof module:config + * @property {Integer} aeadChunkSizeByte + */ + aeadChunkSizeByte: 12, + /** + * Use V5 keys. + * Note: not all OpenPGP implementations are compatible with this option. + * **FUTURE OPENPGP.JS VERSIONS MAY BREAK COMPATIBILITY WHEN USING THIS OPTION** + * @memberof module:config + * @property {Boolean} v5Keys + */ + v5Keys: false, + /** + * {@link https://tools.ietf.org/html/rfc4880#section-3.7.1.3|RFC4880 3.7.1.3}: + * Iteration Count Byte for S2K (String to Key) + * @memberof module:config + * @property {Integer} s2kIterationCountByte + */ + s2kIterationCountByte: 224, + /** + * Allow decryption of messages without integrity protection. + * This is an **insecure** setting: + * - message modifications cannot be detected, thus processing the decrypted data is potentially unsafe. + * - it enables downgrade attacks against integrity-protected messages. + * @memberof module:config + * @property {Boolean} allowUnauthenticatedMessages + */ + allowUnauthenticatedMessages: false, + /** + * Allow streaming unauthenticated data before its integrity has been checked. + * This setting is **insecure** if the partially decrypted message is processed further or displayed to the user. + * @memberof module:config + * @property {Boolean} allowUnauthenticatedStream + */ + allowUnauthenticatedStream: false, + /** + * @memberof module:config + * @property {Boolean} checksumRequired Do not throw error when armor is missing a checksum + */ + checksumRequired: false, + /** + * Minimum RSA key size allowed for key generation and message signing, verification and encryption. + * The default is 2047 since due to a bug, previous versions of OpenPGP.js could generate 2047-bit keys instead of 2048-bit ones. + * @memberof module:config + * @property {Number} minRSABits + */ + minRSABits: 2047, + /** + * Work-around for rare GPG decryption bug when encrypting with multiple passwords. + * **Slower and slightly less secure** + * @memberof module:config + * @property {Boolean} passwordCollisionCheck + */ + passwordCollisionCheck: false, + /** + * @memberof module:config + * @property {Boolean} revocationsExpire If true, expired revocation signatures are ignored + */ + revocationsExpire: false, + /** + * Allow decryption using RSA keys without `encrypt` flag. + * This setting is potentially insecure, but it is needed to get around an old openpgpjs bug + * where key flags were ignored when selecting a key for encryption. + * @memberof module:config + * @property {Boolean} allowInsecureDecryptionWithSigningKeys + */ + allowInsecureDecryptionWithSigningKeys: false, + /** + * Allow verification of message signatures with keys whose validity at the time of signing cannot be determined. + * Instead, a verification key will also be consider valid as long as it is valid at the current time. + * This setting is potentially insecure, but it is needed to verify messages signed with keys that were later reformatted, + * and have self-signature's creation date that does not match the primary key creation date. + * @memberof module:config + * @property {Boolean} allowInsecureDecryptionWithSigningKeys + */ + allowInsecureVerificationWithReformattedKeys: false, + + /** + * Enable constant-time decryption of RSA- and ElGamal-encrypted session keys, to hinder Bleichenbacher-like attacks (https://link.springer.com/chapter/10.1007/BFb0055716). + * This setting has measurable performance impact and it is only helpful in application scenarios where both of the following conditions apply: + * - new/incoming messages are automatically decrypted (without user interaction); + * - an attacker can determine how long it takes to decrypt each message (e.g. due to decryption errors being logged remotely). + * See also `constantTimePKCS1DecryptionSupportedSymmetricAlgorithms`. + * @memberof module:config + * @property {Boolean} constantTimePKCS1Decryption + */ + constantTimePKCS1Decryption: false, + /** + * This setting is only meaningful if `constantTimePKCS1Decryption` is enabled. + * Decryption of RSA- and ElGamal-encrypted session keys of symmetric algorithms different from the ones specified here will fail. + * However, the more algorithms are added, the slower the decryption procedure becomes. + * @memberof module:config + * @property {Set} constantTimePKCS1DecryptionSupportedSymmetricAlgorithms {@link module:enums.symmetric} + */ + constantTimePKCS1DecryptionSupportedSymmetricAlgorithms: new Set([enums.symmetric.aes128, enums.symmetric.aes192, enums.symmetric.aes256]), + + /** + * @memberof module:config + * @property {Integer} minBytesForWebCrypto The minimum amount of bytes for which to use native WebCrypto APIs when available + */ + minBytesForWebCrypto: 1000, + /** + * @memberof module:config + * @property {Boolean} ignoreUnsupportedPackets Ignore unsupported/unrecognizable packets on parsing instead of throwing an error + */ + ignoreUnsupportedPackets: true, + /** + * @memberof module:config + * @property {Boolean} ignoreMalformedPackets Ignore malformed packets on parsing instead of throwing an error + */ + ignoreMalformedPackets: false, + /** + * @memberof module:config + * @property {Boolean} showVersion Whether to include {@link module:config/config.versionString} in armored messages + */ + showVersion: false, + /** + * @memberof module:config + * @property {Boolean} showComment Whether to include {@link module:config/config.commentString} in armored messages + */ + showComment: false, + /** + * @memberof module:config + * @property {String} versionString A version string to be included in armored messages + */ + versionString: 'OpenPGP.js 5.1.0', + /** + * @memberof module:config + * @property {String} commentString A comment string to be included in armored messages + */ + commentString: 'https://openpgpjs.org', + + /** + * Max userID string length (used for parsing) + * @memberof module:config + * @property {Integer} maxUserIDLength + */ + maxUserIDLength: 1024 * 5, + /** + * Contains notatations that are considered "known". Known notations do not trigger + * validation error when the notation is marked as critical. + * @memberof module:config + * @property {Array} knownNotations + */ + knownNotations: ['preferred-email-encoding@pgp.com', 'pka-address@gnupg.org'], + /** + * Whether to use the indutny/elliptic library for curves (other than Curve25519) that are not supported by the available native crypto API. + * When false, certain standard curves will not be supported (depending on the platform). + * Note: the indutny/elliptic curve library is not designed to be constant time. + * @memberof module:config + * @property {Boolean} useIndutnyElliptic + */ + useIndutnyElliptic: true, + /** + * Reject insecure hash algorithms + * @memberof module:config + * @property {Set} rejectHashAlgorithms {@link module:enums.hash} + */ + rejectHashAlgorithms: new Set([enums.hash.md5, enums.hash.ripemd]), + /** + * Reject insecure message hash algorithms + * @memberof module:config + * @property {Set} rejectMessageHashAlgorithms {@link module:enums.hash} + */ + rejectMessageHashAlgorithms: new Set([enums.hash.md5, enums.hash.ripemd, enums.hash.sha1]), + /** + * Reject insecure public key algorithms for key generation and message encryption, signing or verification + * @memberof module:config + * @property {Set} rejectPublicKeyAlgorithms {@link module:enums.publicKey} + */ + rejectPublicKeyAlgorithms: new Set([enums.publicKey.elgamal, enums.publicKey.dsa]), + /** + * Reject non-standard curves for key generation, message encryption, signing or verification + * @memberof module:config + * @property {Set} rejectCurves {@link module:enums.curve} + */ + rejectCurves: new Set([enums.curve.brainpoolP256r1, enums.curve.brainpoolP384r1, enums.curve.brainpoolP512r1, enums.curve.secp256k1]) +}; + +// GPG4Browsers - An OpenPGP implementation in javascript + +/** + * Finds out which Ascii Armoring type is used. Throws error if unknown type. + * @param {String} text - ascii armored text + * @returns {Integer} 0 = MESSAGE PART n of m. + * 1 = MESSAGE PART n + * 2 = SIGNED MESSAGE + * 3 = PGP MESSAGE + * 4 = PUBLIC KEY BLOCK + * 5 = PRIVATE KEY BLOCK + * 6 = SIGNATURE + * @private + */ +function getType(text) { + const reHeader = /^-----BEGIN PGP (MESSAGE, PART \d+\/\d+|MESSAGE, PART \d+|SIGNED MESSAGE|MESSAGE|PUBLIC KEY BLOCK|PRIVATE KEY BLOCK|SIGNATURE)-----$/m; + + const header = text.match(reHeader); + + if (!header) { + throw new Error('Unknown ASCII armor type'); + } + + // BEGIN PGP MESSAGE, PART X/Y + // Used for multi-part messages, where the armor is split amongst Y + // parts, and this is the Xth part out of Y. + if (/MESSAGE, PART \d+\/\d+/.test(header[1])) { + return enums.armor.multipartSection; + } else + // BEGIN PGP MESSAGE, PART X + // Used for multi-part messages, where this is the Xth part of an + // unspecified number of parts. Requires the MESSAGE-ID Armor + // Header to be used. + if (/MESSAGE, PART \d+/.test(header[1])) { + return enums.armor.multipartLast; + } else + // BEGIN PGP SIGNED MESSAGE + if (/SIGNED MESSAGE/.test(header[1])) { + return enums.armor.signed; + } else + // BEGIN PGP MESSAGE + // Used for signed, encrypted, or compressed files. + if (/MESSAGE/.test(header[1])) { + return enums.armor.message; + } else + // BEGIN PGP PUBLIC KEY BLOCK + // Used for armoring public keys. + if (/PUBLIC KEY BLOCK/.test(header[1])) { + return enums.armor.publicKey; + } else + // BEGIN PGP PRIVATE KEY BLOCK + // Used for armoring private keys. + if (/PRIVATE KEY BLOCK/.test(header[1])) { + return enums.armor.privateKey; + } else + // BEGIN PGP SIGNATURE + // Used for detached signatures, OpenPGP/MIME signatures, and + // cleartext signatures. Note that PGP 2.x uses BEGIN PGP MESSAGE + // for detached signatures. + if (/SIGNATURE/.test(header[1])) { + return enums.armor.signature; + } +} + +/** + * Add additional information to the armor version of an OpenPGP binary + * packet block. + * @author Alex + * @version 2011-12-16 + * @param {String} [customComment] - Additional comment to add to the armored string + * @returns {String} The header information. + * @private + */ +function addheader(customComment, config) { + let result = ''; + if (config.showVersion) { + result += 'Version: ' + config.versionString + '\n'; + } + if (config.showComment) { + result += 'Comment: ' + config.commentString + '\n'; + } + if (customComment) { + result += 'Comment: ' + customComment + '\n'; + } + result += '\n'; + return result; +} + + +/** + * Calculates a checksum over the given data and returns it base64 encoded + * @param {String | ReadableStream} data - Data to create a CRC-24 checksum for + * @returns {String | ReadableStream} Base64 encoded checksum. + * @private + */ +function getCheckSum(data) { + const crc = createcrc24(data); + return encode(crc); +} + +// https://create.stephan-brumme.com/crc32/#slicing-by-8-overview + +const crc_table = [ + new Array(0xFF), + new Array(0xFF), + new Array(0xFF), + new Array(0xFF) +]; + +for (let i = 0; i <= 0xFF; i++) { + let crc = i << 16; + for (let j = 0; j < 8; j++) { + crc = (crc << 1) ^ ((crc & 0x800000) !== 0 ? 0x864CFB : 0); + } + crc_table[0][i] = + ((crc & 0xFF0000) >> 16) | + (crc & 0x00FF00) | + ((crc & 0x0000FF) << 16); +} +for (let i = 0; i <= 0xFF; i++) { + crc_table[1][i] = (crc_table[0][i] >> 8) ^ crc_table[0][crc_table[0][i] & 0xFF]; +} +for (let i = 0; i <= 0xFF; i++) { + crc_table[2][i] = (crc_table[1][i] >> 8) ^ crc_table[0][crc_table[1][i] & 0xFF]; +} +for (let i = 0; i <= 0xFF; i++) { + crc_table[3][i] = (crc_table[2][i] >> 8) ^ crc_table[0][crc_table[2][i] & 0xFF]; +} + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView#Endianness +const isLittleEndian = (function() { + const buffer = new ArrayBuffer(2); + new DataView(buffer).setInt16(0, 0xFF, true /* littleEndian */); + // Int16Array uses the platform's endianness. + return new Int16Array(buffer)[0] === 0xFF; +}()); + +/** + * Internal function to calculate a CRC-24 checksum over a given string (data) + * @param {String | ReadableStream} input - Data to create a CRC-24 checksum for + * @returns {Uint8Array | ReadableStream} The CRC-24 checksum. + * @private + */ +function createcrc24(input) { + let crc = 0xCE04B7; + return transform(input, value => { + const len32 = isLittleEndian ? Math.floor(value.length / 4) : 0; + const arr32 = new Uint32Array(value.buffer, value.byteOffset, len32); + for (let i = 0; i < len32; i++) { + crc ^= arr32[i]; + crc = + crc_table[0][(crc >> 24) & 0xFF] ^ + crc_table[1][(crc >> 16) & 0xFF] ^ + crc_table[2][(crc >> 8) & 0xFF] ^ + crc_table[3][(crc >> 0) & 0xFF]; + } + for (let i = len32 * 4; i < value.length; i++) { + crc = (crc >> 8) ^ crc_table[0][(crc & 0xFF) ^ value[i]]; + } + }, () => new Uint8Array([crc, crc >> 8, crc >> 16])); +} + +/** + * Verify armored headers. RFC4880, section 6.3: "OpenPGP should consider improperly formatted + * Armor Headers to be corruption of the ASCII Armor." + * @private + * @param {Array} headers - Armor headers + */ +function verifyHeaders(headers) { + for (let i = 0; i < headers.length; i++) { + if (!/^([^\s:]|[^\s:][^:]*[^\s:]): .+$/.test(headers[i])) { + throw new Error('Improperly formatted armor header: ' + headers[i]); + } + if (!/^(Version|Comment|MessageID|Hash|Charset): .+$/.test(headers[i])) { + util.printDebugError(new Error('Unknown header: ' + headers[i])); + } + } +} + +/** + * Splits a message into two parts, the body and the checksum. This is an internal function + * @param {String} text - OpenPGP armored message part + * @returns {Object} An object with attribute "body" containing the body. + * and an attribute "checksum" containing the checksum. + * @private + */ +function splitChecksum(text) { + let body = text; + let checksum = ''; + + const lastEquals = text.lastIndexOf('='); + + if (lastEquals >= 0 && lastEquals !== text.length - 1) { // '=' as the last char means no checksum + body = text.slice(0, lastEquals); + checksum = text.slice(lastEquals + 1).substr(0, 4); + } + + return { body: body, checksum: checksum }; +} + +/** + * Dearmor an OpenPGP armored message; verify the checksum and return + * the encoded bytes + * @param {String} input - OpenPGP armored message + * @returns {Promise} An object with attribute "text" containing the message text, + * an attribute "data" containing a stream of bytes and "type" for the ASCII armor type + * @async + * @static + */ +function unarmor(input, config = defaultConfig) { + return new Promise(async (resolve, reject) => { + try { + const reSplit = /^-----[^-]+-----$/m; + const reEmptyLine = /^[ \f\r\t\u00a0\u2000-\u200a\u202f\u205f\u3000]*$/; + + let type; + const headers = []; + let lastHeaders = headers; + let headersDone; + let text = []; + let textDone; + let checksum; + let data = decode(transformPair(input, async (readable, writable) => { + const reader = getReader(readable); + try { + while (true) { + let line = await reader.readLine(); + if (line === undefined) { + throw new Error('Misformed armored text'); + } + // remove trailing whitespace at end of lines + line = util.removeTrailingSpaces(line.replace(/[\r\n]/g, '')); + if (!type) { + if (reSplit.test(line)) { + type = getType(line); + } + } else if (!headersDone) { + if (reSplit.test(line)) { + reject(new Error('Mandatory blank line missing between armor headers and armor data')); + } + if (!reEmptyLine.test(line)) { + lastHeaders.push(line); + } else { + verifyHeaders(lastHeaders); + headersDone = true; + if (textDone || type !== 2) { + resolve({ text, data, headers, type }); + break; + } + } + } else if (!textDone && type === 2) { + if (!reSplit.test(line)) { + // Reverse dash-escaping for msg + text.push(line.replace(/^- /, '')); + } else { + text = text.join('\r\n'); + textDone = true; + verifyHeaders(lastHeaders); + lastHeaders = []; + headersDone = false; + } + } + } + } catch (e) { + reject(e); + return; + } + const writer = getWriter(writable); + try { + while (true) { + await writer.ready; + const { done, value } = await reader.read(); + if (done) { + throw new Error('Misformed armored text'); + } + const line = value + ''; + if (line.indexOf('=') === -1 && line.indexOf('-') === -1) { + await writer.write(line); + } else { + let remainder = await reader.readToEnd(); + if (!remainder.length) remainder = ''; + remainder = line + remainder; + remainder = util.removeTrailingSpaces(remainder.replace(/\r/g, '')); + const parts = remainder.split(reSplit); + if (parts.length === 1) { + throw new Error('Misformed armored text'); + } + const split = splitChecksum(parts[0].slice(0, -1)); + checksum = split.checksum; + await writer.write(split.body); + break; + } + } + await writer.ready; + await writer.close(); + } catch (e) { + await writer.abort(e); + } + })); + data = transformPair(data, async (readable, writable) => { + const checksumVerified = readToEnd(getCheckSum(passiveClone(readable))); + checksumVerified.catch(() => {}); + await pipe(readable, writable, { + preventClose: true + }); + const writer = getWriter(writable); + try { + const checksumVerifiedString = (await checksumVerified).replace('\n', ''); + if (checksum !== checksumVerifiedString && (checksum || config.checksumRequired)) { + throw new Error('Ascii armor integrity check failed'); + } + await writer.ready; + await writer.close(); + } catch (e) { + await writer.abort(e); + } + }); + } catch (e) { + reject(e); + } + }).then(async result => { + if (isArrayStream(result.data)) { + result.data = await readToEnd(result.data); + } + return result; + }); +} + + +/** + * Armor an OpenPGP binary packet block + * @param {module:enums.armor} messageType - Type of the message + * @param {Uint8Array | ReadableStream} body - The message body to armor + * @param {Integer} [partIndex] + * @param {Integer} [partTotal] + * @param {String} [customComment] - Additional comment to add to the armored string + * @returns {String | ReadableStream} Armored text. + * @static + */ +function armor(messageType, body, partIndex, partTotal, customComment, config = defaultConfig) { + let text; + let hash; + if (messageType === enums.armor.signed) { + text = body.text; + hash = body.hash; + body = body.data; + } + const bodyClone = passiveClone(body); + const result = []; + switch (messageType) { + case enums.armor.multipartSection: + result.push('-----BEGIN PGP MESSAGE, PART ' + partIndex + '/' + partTotal + '-----\n'); + result.push(addheader(customComment, config)); + result.push(encode(body)); + result.push('=', getCheckSum(bodyClone)); + result.push('-----END PGP MESSAGE, PART ' + partIndex + '/' + partTotal + '-----\n'); + break; + case enums.armor.multipartLast: + result.push('-----BEGIN PGP MESSAGE, PART ' + partIndex + '-----\n'); + result.push(addheader(customComment, config)); + result.push(encode(body)); + result.push('=', getCheckSum(bodyClone)); + result.push('-----END PGP MESSAGE, PART ' + partIndex + '-----\n'); + break; + case enums.armor.signed: + result.push('\n-----BEGIN PGP SIGNED MESSAGE-----\n'); + result.push('Hash: ' + hash + '\n\n'); + result.push(text.replace(/^-/mg, '- -')); + result.push('\n-----BEGIN PGP SIGNATURE-----\n'); + result.push(addheader(customComment, config)); + result.push(encode(body)); + result.push('=', getCheckSum(bodyClone)); + result.push('-----END PGP SIGNATURE-----\n'); + break; + case enums.armor.message: + result.push('-----BEGIN PGP MESSAGE-----\n'); + result.push(addheader(customComment, config)); + result.push(encode(body)); + result.push('=', getCheckSum(bodyClone)); + result.push('-----END PGP MESSAGE-----\n'); + break; + case enums.armor.publicKey: + result.push('-----BEGIN PGP PUBLIC KEY BLOCK-----\n'); + result.push(addheader(customComment, config)); + result.push(encode(body)); + result.push('=', getCheckSum(bodyClone)); + result.push('-----END PGP PUBLIC KEY BLOCK-----\n'); + break; + case enums.armor.privateKey: + result.push('-----BEGIN PGP PRIVATE KEY BLOCK-----\n'); + result.push(addheader(customComment, config)); + result.push(encode(body)); + result.push('=', getCheckSum(bodyClone)); + result.push('-----END PGP PRIVATE KEY BLOCK-----\n'); + break; + case enums.armor.signature: + result.push('-----BEGIN PGP SIGNATURE-----\n'); + result.push(addheader(customComment, config)); + result.push(encode(body)); + result.push('=', getCheckSum(bodyClone)); + result.push('-----END PGP SIGNATURE-----\n'); + break; + } + + return util.concat(result); +} + +// GPG4Browsers - An OpenPGP implementation in javascript + +/** + * Implementation of type key id + * + * {@link https://tools.ietf.org/html/rfc4880#section-3.3|RFC4880 3.3}: + * A Key ID is an eight-octet scalar that identifies a key. + * Implementations SHOULD NOT assume that Key IDs are unique. The + * section "Enhanced Key Formats" below describes how Key IDs are + * formed. + */ +class KeyID { + constructor() { + this.bytes = ''; + } + + /** + * Parsing method for a key id + * @param {Uint8Array} bytes - Input to read the key id from + */ + read(bytes) { + this.bytes = util.uint8ArrayToString(bytes.subarray(0, 8)); + } + + /** + * Serializes the Key ID + * @returns {Uint8Array} Key ID as a Uint8Array. + */ + write() { + return util.stringToUint8Array(this.bytes); + } + + /** + * Returns the Key ID represented as a hexadecimal string + * @returns {String} Key ID as a hexadecimal string. + */ + toHex() { + return util.uint8ArrayToHex(util.stringToUint8Array(this.bytes)); + } + + /** + * Checks equality of Key ID's + * @param {KeyID} keyID + * @param {Boolean} matchWildcard - Indicates whether to check if either keyID is a wildcard + */ + equals(keyID, matchWildcard = false) { + return (matchWildcard && (keyID.isWildcard() || this.isWildcard())) || this.bytes === keyID.bytes; + } + + /** + * Checks to see if the Key ID is unset + * @returns {Boolean} True if the Key ID is null. + */ + isNull() { + return this.bytes === ''; + } + + /** + * Checks to see if the Key ID is a "wildcard" Key ID (all zeros) + * @returns {Boolean} True if this is a wildcard Key ID. + */ + isWildcard() { + return /^0+$/.test(this.toHex()); + } + + static mapToHex(keyID) { + return keyID.toHex(); + } + + static fromID(hex) { + const keyID = new KeyID(); + keyID.read(util.hexToUint8Array(hex)); + return keyID; + } + + static wildcard() { + const keyID = new KeyID(); + keyID.read(new Uint8Array(8)); + return keyID; + } +} + +/** + * @file {@link http://asmjs.org Asm.js} implementation of the {@link https://en.wikipedia.org/wiki/Advanced_Encryption_Standard Advanced Encryption Standard}. + * @author Artem S Vybornov + * @license MIT + */ +var AES_asm = function () { + + /** + * Galois Field stuff init flag + */ + var ginit_done = false; + + /** + * Galois Field exponentiation and logarithm tables for 3 (the generator) + */ + var gexp3, glog3; + + /** + * Init Galois Field tables + */ + function ginit() { + gexp3 = [], + glog3 = []; + + var a = 1, c, d; + for (c = 0; c < 255; c++) { + gexp3[c] = a; + + // Multiply by three + d = a & 0x80, a <<= 1, a &= 255; + if (d === 0x80) a ^= 0x1b; + a ^= gexp3[c]; + + // Set the log table value + glog3[gexp3[c]] = c; + } + gexp3[255] = gexp3[0]; + glog3[0] = 0; + + ginit_done = true; + } + + /** + * Galois Field multiplication + * @param {number} a + * @param {number} b + * @return {number} + */ + function gmul(a, b) { + var c = gexp3[(glog3[a] + glog3[b]) % 255]; + if (a === 0 || b === 0) c = 0; + return c; + } + + /** + * Galois Field reciprocal + * @param {number} a + * @return {number} + */ + function ginv(a) { + var i = gexp3[255 - glog3[a]]; + if (a === 0) i = 0; + return i; + } + + /** + * AES stuff init flag + */ + var aes_init_done = false; + + /** + * Encryption, Decryption, S-Box and KeyTransform tables + * + * @type {number[]} + */ + var aes_sbox; + + /** + * @type {number[]} + */ + var aes_sinv; + + /** + * @type {number[][]} + */ + var aes_enc; + + /** + * @type {number[][]} + */ + var aes_dec; + + /** + * Init AES tables + */ + function aes_init() { + if (!ginit_done) ginit(); + + // Calculates AES S-Box value + function _s(a) { + var c, s, x; + s = x = ginv(a); + for (c = 0; c < 4; c++) { + s = ((s << 1) | (s >>> 7)) & 255; + x ^= s; + } + x ^= 99; + return x; + } + + // Tables + aes_sbox = [], + aes_sinv = [], + aes_enc = [[], [], [], []], + aes_dec = [[], [], [], []]; + + for (var i = 0; i < 256; i++) { + var s = _s(i); + + // S-Box and its inverse + aes_sbox[i] = s; + aes_sinv[s] = i; + + // Ecryption and Decryption tables + aes_enc[0][i] = (gmul(2, s) << 24) | (s << 16) | (s << 8) | gmul(3, s); + aes_dec[0][s] = (gmul(14, i) << 24) | (gmul(9, i) << 16) | (gmul(13, i) << 8) | gmul(11, i); + // Rotate tables + for (var t = 1; t < 4; t++) { + aes_enc[t][i] = (aes_enc[t - 1][i] >>> 8) | (aes_enc[t - 1][i] << 24); + aes_dec[t][s] = (aes_dec[t - 1][s] >>> 8) | (aes_dec[t - 1][s] << 24); + } + } + + aes_init_done = true; + } + + /** + * Asm.js module constructor. + * + *

+ * Heap buffer layout by offset: + *

+   * 0x0000   encryption key schedule
+   * 0x0400   decryption key schedule
+   * 0x0800   sbox
+   * 0x0c00   inv sbox
+   * 0x1000   encryption tables
+   * 0x2000   decryption tables
+   * 0x3000   reserved (future GCM multiplication lookup table)
+   * 0x4000   data
+   * 
+ * Don't touch anything before 0x400. + *

+ * + * @alias AES_asm + * @class + * @param foreign - ignored + * @param buffer - heap buffer to link with + */ + var wrapper = function (foreign, buffer) { + // Init AES stuff for the first time + if (!aes_init_done) aes_init(); + + // Fill up AES tables + var heap = new Uint32Array(buffer); + heap.set(aes_sbox, 0x0800 >> 2); + heap.set(aes_sinv, 0x0c00 >> 2); + for (var i = 0; i < 4; i++) { + heap.set(aes_enc[i], (0x1000 + 0x400 * i) >> 2); + heap.set(aes_dec[i], (0x2000 + 0x400 * i) >> 2); + } + + /** + * Calculate AES key schedules. + * @instance + * @memberof AES_asm + * @param {number} ks - key size, 4/6/8 (for 128/192/256-bit key correspondingly) + * @param {number} k0 - key vector components + * @param {number} k1 - key vector components + * @param {number} k2 - key vector components + * @param {number} k3 - key vector components + * @param {number} k4 - key vector components + * @param {number} k5 - key vector components + * @param {number} k6 - key vector components + * @param {number} k7 - key vector components + */ + function set_key(ks, k0, k1, k2, k3, k4, k5, k6, k7) { + var ekeys = heap.subarray(0x000, 60), + dkeys = heap.subarray(0x100, 0x100 + 60); + + // Encryption key schedule + ekeys.set([k0, k1, k2, k3, k4, k5, k6, k7]); + for (var i = ks, rcon = 1; i < 4 * ks + 28; i++) { + var k = ekeys[i - 1]; + if ((i % ks === 0) || (ks === 8 && i % ks === 4)) { + k = aes_sbox[k >>> 24] << 24 ^ aes_sbox[k >>> 16 & 255] << 16 ^ aes_sbox[k >>> 8 & 255] << 8 ^ aes_sbox[k & 255]; + } + if (i % ks === 0) { + k = (k << 8) ^ (k >>> 24) ^ (rcon << 24); + rcon = (rcon << 1) ^ ((rcon & 0x80) ? 0x1b : 0); + } + ekeys[i] = ekeys[i - ks] ^ k; + } + + // Decryption key schedule + for (var j = 0; j < i; j += 4) { + for (var jj = 0; jj < 4; jj++) { + var k = ekeys[i - (4 + j) + (4 - jj) % 4]; + if (j < 4 || j >= i - 4) { + dkeys[j + jj] = k; + } else { + dkeys[j + jj] = aes_dec[0][aes_sbox[k >>> 24]] + ^ aes_dec[1][aes_sbox[k >>> 16 & 255]] + ^ aes_dec[2][aes_sbox[k >>> 8 & 255]] + ^ aes_dec[3][aes_sbox[k & 255]]; + } + } + } + + // Set rounds number + asm.set_rounds(ks + 5); + } + + // create library object with necessary properties + var stdlib = {Uint8Array: Uint8Array, Uint32Array: Uint32Array}; + + var asm = function (stdlib, foreign, buffer) { + "use asm"; + + var S0 = 0, S1 = 0, S2 = 0, S3 = 0, + I0 = 0, I1 = 0, I2 = 0, I3 = 0, + N0 = 0, N1 = 0, N2 = 0, N3 = 0, + M0 = 0, M1 = 0, M2 = 0, M3 = 0, + H0 = 0, H1 = 0, H2 = 0, H3 = 0, + R = 0; + + var HEAP = new stdlib.Uint32Array(buffer), + DATA = new stdlib.Uint8Array(buffer); + + /** + * AES core + * @param {number} k - precomputed key schedule offset + * @param {number} s - precomputed sbox table offset + * @param {number} t - precomputed round table offset + * @param {number} r - number of inner rounds to perform + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _core(k, s, t, r, x0, x1, x2, x3) { + k = k | 0; + s = s | 0; + t = t | 0; + r = r | 0; + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + var t1 = 0, t2 = 0, t3 = 0, + y0 = 0, y1 = 0, y2 = 0, y3 = 0, + i = 0; + + t1 = t | 0x400, t2 = t | 0x800, t3 = t | 0xc00; + + // round 0 + x0 = x0 ^ HEAP[(k | 0) >> 2], + x1 = x1 ^ HEAP[(k | 4) >> 2], + x2 = x2 ^ HEAP[(k | 8) >> 2], + x3 = x3 ^ HEAP[(k | 12) >> 2]; + + // round 1..r + for (i = 16; (i | 0) <= (r << 4); i = (i + 16) | 0) { + y0 = HEAP[(t | x0 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x1 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x2 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x3 << 2 & 1020) >> 2] ^ HEAP[(k | i | 0) >> 2], + y1 = HEAP[(t | x1 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x2 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x3 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x0 << 2 & 1020) >> 2] ^ HEAP[(k | i | 4) >> 2], + y2 = HEAP[(t | x2 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x3 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x0 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x1 << 2 & 1020) >> 2] ^ HEAP[(k | i | 8) >> 2], + y3 = HEAP[(t | x3 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x0 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x1 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x2 << 2 & 1020) >> 2] ^ HEAP[(k | i | 12) >> 2]; + x0 = y0, x1 = y1, x2 = y2, x3 = y3; + } + + // final round + S0 = HEAP[(s | x0 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x1 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x2 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x3 << 2 & 1020) >> 2] ^ HEAP[(k | i | 0) >> 2], + S1 = HEAP[(s | x1 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x2 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x3 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x0 << 2 & 1020) >> 2] ^ HEAP[(k | i | 4) >> 2], + S2 = HEAP[(s | x2 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x3 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x0 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x1 << 2 & 1020) >> 2] ^ HEAP[(k | i | 8) >> 2], + S3 = HEAP[(s | x3 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x0 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x1 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x2 << 2 & 1020) >> 2] ^ HEAP[(k | i | 12) >> 2]; + } + + /** + * ECB mode encryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _ecb_enc(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + _core( + 0x0000, 0x0800, 0x1000, + R, + x0, + x1, + x2, + x3 + ); + } + + /** + * ECB mode decryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _ecb_dec(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + var t = 0; + + _core( + 0x0400, 0x0c00, 0x2000, + R, + x0, + x3, + x2, + x1 + ); + + t = S1, S1 = S3, S3 = t; + } + + + /** + * CBC mode encryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _cbc_enc(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + _core( + 0x0000, 0x0800, 0x1000, + R, + I0 ^ x0, + I1 ^ x1, + I2 ^ x2, + I3 ^ x3 + ); + + I0 = S0, + I1 = S1, + I2 = S2, + I3 = S3; + } + + /** + * CBC mode decryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _cbc_dec(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + var t = 0; + + _core( + 0x0400, 0x0c00, 0x2000, + R, + x0, + x3, + x2, + x1 + ); + + t = S1, S1 = S3, S3 = t; + + S0 = S0 ^ I0, + S1 = S1 ^ I1, + S2 = S2 ^ I2, + S3 = S3 ^ I3; + + I0 = x0, + I1 = x1, + I2 = x2, + I3 = x3; + } + + /** + * CFB mode encryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _cfb_enc(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + _core( + 0x0000, 0x0800, 0x1000, + R, + I0, + I1, + I2, + I3 + ); + + I0 = S0 = S0 ^ x0, + I1 = S1 = S1 ^ x1, + I2 = S2 = S2 ^ x2, + I3 = S3 = S3 ^ x3; + } + + + /** + * CFB mode decryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _cfb_dec(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + _core( + 0x0000, 0x0800, 0x1000, + R, + I0, + I1, + I2, + I3 + ); + + S0 = S0 ^ x0, + S1 = S1 ^ x1, + S2 = S2 ^ x2, + S3 = S3 ^ x3; + + I0 = x0, + I1 = x1, + I2 = x2, + I3 = x3; + } + + /** + * OFB mode encryption / decryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _ofb(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + _core( + 0x0000, 0x0800, 0x1000, + R, + I0, + I1, + I2, + I3 + ); + + I0 = S0, + I1 = S1, + I2 = S2, + I3 = S3; + + S0 = S0 ^ x0, + S1 = S1 ^ x1, + S2 = S2 ^ x2, + S3 = S3 ^ x3; + } + + /** + * CTR mode encryption / decryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _ctr(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + _core( + 0x0000, 0x0800, 0x1000, + R, + N0, + N1, + N2, + N3 + ); + + N3 = (~M3 & N3) | M3 & (N3 + 1); + N2 = (~M2 & N2) | M2 & (N2 + ((N3 | 0) == 0)); + N1 = (~M1 & N1) | M1 & (N1 + ((N2 | 0) == 0)); + N0 = (~M0 & N0) | M0 & (N0 + ((N1 | 0) == 0)); + + S0 = S0 ^ x0; + S1 = S1 ^ x1; + S2 = S2 ^ x2; + S3 = S3 ^ x3; + } + + /** + * GCM mode MAC calculation + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _gcm_mac(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + var y0 = 0, y1 = 0, y2 = 0, y3 = 0, + z0 = 0, z1 = 0, z2 = 0, z3 = 0, + i = 0, c = 0; + + x0 = x0 ^ I0, + x1 = x1 ^ I1, + x2 = x2 ^ I2, + x3 = x3 ^ I3; + + y0 = H0 | 0, + y1 = H1 | 0, + y2 = H2 | 0, + y3 = H3 | 0; + + for (; (i | 0) < 128; i = (i + 1) | 0) { + if (y0 >>> 31) { + z0 = z0 ^ x0, + z1 = z1 ^ x1, + z2 = z2 ^ x2, + z3 = z3 ^ x3; + } + + y0 = (y0 << 1) | (y1 >>> 31), + y1 = (y1 << 1) | (y2 >>> 31), + y2 = (y2 << 1) | (y3 >>> 31), + y3 = (y3 << 1); + + c = x3 & 1; + + x3 = (x3 >>> 1) | (x2 << 31), + x2 = (x2 >>> 1) | (x1 << 31), + x1 = (x1 >>> 1) | (x0 << 31), + x0 = (x0 >>> 1); + + if (c) x0 = x0 ^ 0xe1000000; + } + + I0 = z0, + I1 = z1, + I2 = z2, + I3 = z3; + } + + /** + * Set the internal rounds number. + * @instance + * @memberof AES_asm + * @param {number} r - number if inner AES rounds + */ + function set_rounds(r) { + r = r | 0; + R = r; + } + + /** + * Populate the internal state of the module. + * @instance + * @memberof AES_asm + * @param {number} s0 - state vector + * @param {number} s1 - state vector + * @param {number} s2 - state vector + * @param {number} s3 - state vector + */ + function set_state(s0, s1, s2, s3) { + s0 = s0 | 0; + s1 = s1 | 0; + s2 = s2 | 0; + s3 = s3 | 0; + + S0 = s0, + S1 = s1, + S2 = s2, + S3 = s3; + } + + /** + * Populate the internal iv of the module. + * @instance + * @memberof AES_asm + * @param {number} i0 - iv vector + * @param {number} i1 - iv vector + * @param {number} i2 - iv vector + * @param {number} i3 - iv vector + */ + function set_iv(i0, i1, i2, i3) { + i0 = i0 | 0; + i1 = i1 | 0; + i2 = i2 | 0; + i3 = i3 | 0; + + I0 = i0, + I1 = i1, + I2 = i2, + I3 = i3; + } + + /** + * Set nonce for CTR-family modes. + * @instance + * @memberof AES_asm + * @param {number} n0 - nonce vector + * @param {number} n1 - nonce vector + * @param {number} n2 - nonce vector + * @param {number} n3 - nonce vector + */ + function set_nonce(n0, n1, n2, n3) { + n0 = n0 | 0; + n1 = n1 | 0; + n2 = n2 | 0; + n3 = n3 | 0; + + N0 = n0, + N1 = n1, + N2 = n2, + N3 = n3; + } + + /** + * Set counter mask for CTR-family modes. + * @instance + * @memberof AES_asm + * @param {number} m0 - counter mask vector + * @param {number} m1 - counter mask vector + * @param {number} m2 - counter mask vector + * @param {number} m3 - counter mask vector + */ + function set_mask(m0, m1, m2, m3) { + m0 = m0 | 0; + m1 = m1 | 0; + m2 = m2 | 0; + m3 = m3 | 0; + + M0 = m0, + M1 = m1, + M2 = m2, + M3 = m3; + } + + /** + * Set counter for CTR-family modes. + * @instance + * @memberof AES_asm + * @param {number} c0 - counter vector + * @param {number} c1 - counter vector + * @param {number} c2 - counter vector + * @param {number} c3 - counter vector + */ + function set_counter(c0, c1, c2, c3) { + c0 = c0 | 0; + c1 = c1 | 0; + c2 = c2 | 0; + c3 = c3 | 0; + + N3 = (~M3 & N3) | M3 & c3, + N2 = (~M2 & N2) | M2 & c2, + N1 = (~M1 & N1) | M1 & c1, + N0 = (~M0 & N0) | M0 & c0; + } + + /** + * Store the internal state vector into the heap. + * @instance + * @memberof AES_asm + * @param {number} pos - offset where to put the data + * @return {number} The number of bytes have been written into the heap, always 16. + */ + function get_state(pos) { + pos = pos | 0; + + if (pos & 15) return -1; + + DATA[pos | 0] = S0 >>> 24, + DATA[pos | 1] = S0 >>> 16 & 255, + DATA[pos | 2] = S0 >>> 8 & 255, + DATA[pos | 3] = S0 & 255, + DATA[pos | 4] = S1 >>> 24, + DATA[pos | 5] = S1 >>> 16 & 255, + DATA[pos | 6] = S1 >>> 8 & 255, + DATA[pos | 7] = S1 & 255, + DATA[pos | 8] = S2 >>> 24, + DATA[pos | 9] = S2 >>> 16 & 255, + DATA[pos | 10] = S2 >>> 8 & 255, + DATA[pos | 11] = S2 & 255, + DATA[pos | 12] = S3 >>> 24, + DATA[pos | 13] = S3 >>> 16 & 255, + DATA[pos | 14] = S3 >>> 8 & 255, + DATA[pos | 15] = S3 & 255; + + return 16; + } + + /** + * Store the internal iv vector into the heap. + * @instance + * @memberof AES_asm + * @param {number} pos - offset where to put the data + * @return {number} The number of bytes have been written into the heap, always 16. + */ + function get_iv(pos) { + pos = pos | 0; + + if (pos & 15) return -1; + + DATA[pos | 0] = I0 >>> 24, + DATA[pos | 1] = I0 >>> 16 & 255, + DATA[pos | 2] = I0 >>> 8 & 255, + DATA[pos | 3] = I0 & 255, + DATA[pos | 4] = I1 >>> 24, + DATA[pos | 5] = I1 >>> 16 & 255, + DATA[pos | 6] = I1 >>> 8 & 255, + DATA[pos | 7] = I1 & 255, + DATA[pos | 8] = I2 >>> 24, + DATA[pos | 9] = I2 >>> 16 & 255, + DATA[pos | 10] = I2 >>> 8 & 255, + DATA[pos | 11] = I2 & 255, + DATA[pos | 12] = I3 >>> 24, + DATA[pos | 13] = I3 >>> 16 & 255, + DATA[pos | 14] = I3 >>> 8 & 255, + DATA[pos | 15] = I3 & 255; + + return 16; + } + + /** + * GCM initialization. + * @instance + * @memberof AES_asm + */ + function gcm_init() { + _ecb_enc(0, 0, 0, 0); + H0 = S0, + H1 = S1, + H2 = S2, + H3 = S3; + } + + /** + * Perform ciphering operation on the supplied data. + * @instance + * @memberof AES_asm + * @param {number} mode - block cipher mode (see {@link AES_asm} mode constants) + * @param {number} pos - offset of the data being processed + * @param {number} len - length of the data being processed + * @return {number} Actual amount of data have been processed. + */ + function cipher(mode, pos, len) { + mode = mode | 0; + pos = pos | 0; + len = len | 0; + + var ret = 0; + + if (pos & 15) return -1; + + while ((len | 0) >= 16) { + _cipher_modes[mode & 7]( + DATA[pos | 0] << 24 | DATA[pos | 1] << 16 | DATA[pos | 2] << 8 | DATA[pos | 3], + DATA[pos | 4] << 24 | DATA[pos | 5] << 16 | DATA[pos | 6] << 8 | DATA[pos | 7], + DATA[pos | 8] << 24 | DATA[pos | 9] << 16 | DATA[pos | 10] << 8 | DATA[pos | 11], + DATA[pos | 12] << 24 | DATA[pos | 13] << 16 | DATA[pos | 14] << 8 | DATA[pos | 15] + ); + + DATA[pos | 0] = S0 >>> 24, + DATA[pos | 1] = S0 >>> 16 & 255, + DATA[pos | 2] = S0 >>> 8 & 255, + DATA[pos | 3] = S0 & 255, + DATA[pos | 4] = S1 >>> 24, + DATA[pos | 5] = S1 >>> 16 & 255, + DATA[pos | 6] = S1 >>> 8 & 255, + DATA[pos | 7] = S1 & 255, + DATA[pos | 8] = S2 >>> 24, + DATA[pos | 9] = S2 >>> 16 & 255, + DATA[pos | 10] = S2 >>> 8 & 255, + DATA[pos | 11] = S2 & 255, + DATA[pos | 12] = S3 >>> 24, + DATA[pos | 13] = S3 >>> 16 & 255, + DATA[pos | 14] = S3 >>> 8 & 255, + DATA[pos | 15] = S3 & 255; + + ret = (ret + 16) | 0, + pos = (pos + 16) | 0, + len = (len - 16) | 0; + } + + return ret | 0; + } + + /** + * Calculates MAC of the supplied data. + * @instance + * @memberof AES_asm + * @param {number} mode - block cipher mode (see {@link AES_asm} mode constants) + * @param {number} pos - offset of the data being processed + * @param {number} len - length of the data being processed + * @return {number} Actual amount of data have been processed. + */ + function mac(mode, pos, len) { + mode = mode | 0; + pos = pos | 0; + len = len | 0; + + var ret = 0; + + if (pos & 15) return -1; + + while ((len | 0) >= 16) { + _mac_modes[mode & 1]( + DATA[pos | 0] << 24 | DATA[pos | 1] << 16 | DATA[pos | 2] << 8 | DATA[pos | 3], + DATA[pos | 4] << 24 | DATA[pos | 5] << 16 | DATA[pos | 6] << 8 | DATA[pos | 7], + DATA[pos | 8] << 24 | DATA[pos | 9] << 16 | DATA[pos | 10] << 8 | DATA[pos | 11], + DATA[pos | 12] << 24 | DATA[pos | 13] << 16 | DATA[pos | 14] << 8 | DATA[pos | 15] + ); + + ret = (ret + 16) | 0, + pos = (pos + 16) | 0, + len = (len - 16) | 0; + } + + return ret | 0; + } + + /** + * AES cipher modes table (virual methods) + */ + var _cipher_modes = [_ecb_enc, _ecb_dec, _cbc_enc, _cbc_dec, _cfb_enc, _cfb_dec, _ofb, _ctr]; + + /** + * AES MAC modes table (virual methods) + */ + var _mac_modes = [_cbc_enc, _gcm_mac]; + + /** + * Asm.js module exports + */ + return { + set_rounds: set_rounds, + set_state: set_state, + set_iv: set_iv, + set_nonce: set_nonce, + set_mask: set_mask, + set_counter: set_counter, + get_state: get_state, + get_iv: get_iv, + gcm_init: gcm_init, + cipher: cipher, + mac: mac, + }; + }(stdlib, foreign, buffer); + + asm.set_key = set_key; + + return asm; + }; + + /** + * AES enciphering mode constants + * @enum {number} + * @const + */ + wrapper.ENC = { + ECB: 0, + CBC: 2, + CFB: 4, + OFB: 6, + CTR: 7, + }, + + /** + * AES deciphering mode constants + * @enum {number} + * @const + */ + wrapper.DEC = { + ECB: 1, + CBC: 3, + CFB: 5, + OFB: 6, + CTR: 7, + }, + + /** + * AES MAC mode constants + * @enum {number} + * @const + */ + wrapper.MAC = { + CBC: 0, + GCM: 1, + }; + + /** + * Heap data offset + * @type {number} + * @const + */ + wrapper.HEAP_DATA = 0x4000; + + return wrapper; +}(); + +function is_bytes(a) { + return a instanceof Uint8Array; +} +function _heap_init(heap, heapSize) { + const size = heap ? heap.byteLength : heapSize || 65536; + if (size & 0xfff || size <= 0) + throw new Error('heap size must be a positive integer and a multiple of 4096'); + heap = heap || new Uint8Array(new ArrayBuffer(size)); + return heap; +} +function _heap_write(heap, hpos, data, dpos, dlen) { + const hlen = heap.length - hpos; + const wlen = hlen < dlen ? hlen : dlen; + heap.set(data.subarray(dpos, dpos + wlen), hpos); + return wlen; +} +function joinBytes(...arg) { + const totalLenght = arg.reduce((sum, curr) => sum + curr.length, 0); + const ret = new Uint8Array(totalLenght); + let cursor = 0; + for (let i = 0; i < arg.length; i++) { + ret.set(arg[i], cursor); + cursor += arg[i].length; + } + return ret; +} + +class IllegalStateError extends Error { + constructor(...args) { + super(...args); + } +} +class IllegalArgumentError extends Error { + constructor(...args) { + super(...args); + } +} +class SecurityError extends Error { + constructor(...args) { + super(...args); + } +} + +const heap_pool = []; +const asm_pool = []; +class AES { + constructor(key, iv, padding = true, mode, heap, asm) { + this.pos = 0; + this.len = 0; + this.mode = mode; + // The AES object state + this.pos = 0; + this.len = 0; + this.key = key; + this.iv = iv; + this.padding = padding; + // The AES "worker" + this.acquire_asm(heap, asm); + } + acquire_asm(heap, asm) { + if (this.heap === undefined || this.asm === undefined) { + this.heap = heap || heap_pool.pop() || _heap_init().subarray(AES_asm.HEAP_DATA); + this.asm = asm || asm_pool.pop() || new AES_asm(null, this.heap.buffer); + this.reset(this.key, this.iv); + } + return { heap: this.heap, asm: this.asm }; + } + release_asm() { + if (this.heap !== undefined && this.asm !== undefined) { + heap_pool.push(this.heap); + asm_pool.push(this.asm); + } + this.heap = undefined; + this.asm = undefined; + } + reset(key, iv) { + const { asm } = this.acquire_asm(); + // Key + const keylen = key.length; + if (keylen !== 16 && keylen !== 24 && keylen !== 32) + throw new IllegalArgumentError('illegal key size'); + const keyview = new DataView(key.buffer, key.byteOffset, key.byteLength); + asm.set_key(keylen >> 2, keyview.getUint32(0), keyview.getUint32(4), keyview.getUint32(8), keyview.getUint32(12), keylen > 16 ? keyview.getUint32(16) : 0, keylen > 16 ? keyview.getUint32(20) : 0, keylen > 24 ? keyview.getUint32(24) : 0, keylen > 24 ? keyview.getUint32(28) : 0); + // IV + if (iv !== undefined) { + if (iv.length !== 16) + throw new IllegalArgumentError('illegal iv size'); + let ivview = new DataView(iv.buffer, iv.byteOffset, iv.byteLength); + asm.set_iv(ivview.getUint32(0), ivview.getUint32(4), ivview.getUint32(8), ivview.getUint32(12)); + } + else { + asm.set_iv(0, 0, 0, 0); + } + } + AES_Encrypt_process(data) { + if (!is_bytes(data)) + throw new TypeError("data isn't of expected type"); + let { heap, asm } = this.acquire_asm(); + let amode = AES_asm.ENC[this.mode]; + let hpos = AES_asm.HEAP_DATA; + let pos = this.pos; + let len = this.len; + let dpos = 0; + let dlen = data.length || 0; + let rpos = 0; + let rlen = (len + dlen) & -16; + let wlen = 0; + let result = new Uint8Array(rlen); + while (dlen > 0) { + wlen = _heap_write(heap, pos + len, data, dpos, dlen); + len += wlen; + dpos += wlen; + dlen -= wlen; + wlen = asm.cipher(amode, hpos + pos, len); + if (wlen) + result.set(heap.subarray(pos, pos + wlen), rpos); + rpos += wlen; + if (wlen < len) { + pos += wlen; + len -= wlen; + } + else { + pos = 0; + len = 0; + } + } + this.pos = pos; + this.len = len; + return result; + } + AES_Encrypt_finish() { + let { heap, asm } = this.acquire_asm(); + let amode = AES_asm.ENC[this.mode]; + let hpos = AES_asm.HEAP_DATA; + let pos = this.pos; + let len = this.len; + let plen = 16 - (len % 16); + let rlen = len; + if (this.hasOwnProperty('padding')) { + if (this.padding) { + for (let p = 0; p < plen; ++p) { + heap[pos + len + p] = plen; + } + len += plen; + rlen = len; + } + else if (len % 16) { + throw new IllegalArgumentError('data length must be a multiple of the block size'); + } + } + else { + len += plen; + } + const result = new Uint8Array(rlen); + if (len) + asm.cipher(amode, hpos + pos, len); + if (rlen) + result.set(heap.subarray(pos, pos + rlen)); + this.pos = 0; + this.len = 0; + this.release_asm(); + return result; + } + AES_Decrypt_process(data) { + if (!is_bytes(data)) + throw new TypeError("data isn't of expected type"); + let { heap, asm } = this.acquire_asm(); + let amode = AES_asm.DEC[this.mode]; + let hpos = AES_asm.HEAP_DATA; + let pos = this.pos; + let len = this.len; + let dpos = 0; + let dlen = data.length || 0; + let rpos = 0; + let rlen = (len + dlen) & -16; + let plen = 0; + let wlen = 0; + if (this.padding) { + plen = len + dlen - rlen || 16; + rlen -= plen; + } + const result = new Uint8Array(rlen); + while (dlen > 0) { + wlen = _heap_write(heap, pos + len, data, dpos, dlen); + len += wlen; + dpos += wlen; + dlen -= wlen; + wlen = asm.cipher(amode, hpos + pos, len - (!dlen ? plen : 0)); + if (wlen) + result.set(heap.subarray(pos, pos + wlen), rpos); + rpos += wlen; + if (wlen < len) { + pos += wlen; + len -= wlen; + } + else { + pos = 0; + len = 0; + } + } + this.pos = pos; + this.len = len; + return result; + } + AES_Decrypt_finish() { + let { heap, asm } = this.acquire_asm(); + let amode = AES_asm.DEC[this.mode]; + let hpos = AES_asm.HEAP_DATA; + let pos = this.pos; + let len = this.len; + let rlen = len; + if (len > 0) { + if (len % 16) { + if (this.hasOwnProperty('padding')) { + throw new IllegalArgumentError('data length must be a multiple of the block size'); + } + else { + len += 16 - (len % 16); + } + } + asm.cipher(amode, hpos + pos, len); + if (this.hasOwnProperty('padding') && this.padding) { + let pad = heap[pos + rlen - 1]; + if (pad < 1 || pad > 16 || pad > rlen) + throw new SecurityError('bad padding'); + let pcheck = 0; + for (let i = pad; i > 1; i--) + pcheck |= pad ^ heap[pos + rlen - i]; + if (pcheck) + throw new SecurityError('bad padding'); + rlen -= pad; + } + } + const result = new Uint8Array(rlen); + if (rlen > 0) { + result.set(heap.subarray(pos, pos + rlen)); + } + this.pos = 0; + this.len = 0; + this.release_asm(); + return result; + } +} + +class AES_ECB { + static encrypt(data, key, padding = false) { + return new AES_ECB(key, padding).encrypt(data); + } + static decrypt(data, key, padding = false) { + return new AES_ECB(key, padding).decrypt(data); + } + constructor(key, padding = false, aes) { + this.aes = aes ? aes : new AES(key, undefined, padding, 'ECB'); + } + encrypt(data) { + const r1 = this.aes.AES_Encrypt_process(data); + const r2 = this.aes.AES_Encrypt_finish(); + return joinBytes(r1, r2); + } + decrypt(data) { + const r1 = this.aes.AES_Decrypt_process(data); + const r2 = this.aes.AES_Decrypt_finish(); + return joinBytes(r1, r2); + } +} + +/** + * Javascript AES implementation. + * This is used as fallback if the native Crypto APIs are not available. + */ +function aes(length) { + const C = function(key) { + const aesECB = new AES_ECB(key); + + this.encrypt = function(block) { + return aesECB.encrypt(block); + }; + + this.decrypt = function(block) { + return aesECB.decrypt(block); + }; + }; + + C.blockSize = C.prototype.blockSize = 16; + C.keySize = C.prototype.keySize = length / 8; + + return C; +} + +//Paul Tero, July 2001 +//http://www.tero.co.uk/des/ +// +//Optimised for performance with large blocks by Michael Hayworth, November 2001 +//http://www.netdealing.com +// +// Modified by Recurity Labs GmbH + +//THIS SOFTWARE IS PROVIDED "AS IS" AND +//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +//IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +//ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +//FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +//DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +//OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +//HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +//OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +//SUCH DAMAGE. + +//des +//this takes the key, the message, and whether to encrypt or decrypt + +function des(keys, message, encrypt, mode, iv, padding) { + //declaring this locally speeds things up a bit + const spfunction1 = [ + 0x1010400, 0, 0x10000, 0x1010404, 0x1010004, 0x10404, 0x4, 0x10000, 0x400, 0x1010400, + 0x1010404, 0x400, 0x1000404, 0x1010004, 0x1000000, 0x4, 0x404, 0x1000400, 0x1000400, 0x10400, 0x10400, 0x1010000, + 0x1010000, 0x1000404, 0x10004, 0x1000004, 0x1000004, 0x10004, 0, 0x404, 0x10404, 0x1000000, 0x10000, 0x1010404, 0x4, + 0x1010000, 0x1010400, 0x1000000, 0x1000000, 0x400, 0x1010004, 0x10000, 0x10400, 0x1000004, 0x400, 0x4, 0x1000404, + 0x10404, 0x1010404, 0x10004, 0x1010000, 0x1000404, 0x1000004, 0x404, 0x10404, 0x1010400, 0x404, 0x1000400, + 0x1000400, 0, 0x10004, 0x10400, 0, 0x1010004 + ]; + const spfunction2 = [ + -0x7fef7fe0, -0x7fff8000, 0x8000, 0x108020, 0x100000, 0x20, -0x7fefffe0, -0x7fff7fe0, + -0x7fffffe0, -0x7fef7fe0, -0x7fef8000, -0x80000000, -0x7fff8000, 0x100000, 0x20, -0x7fefffe0, 0x108000, 0x100020, + -0x7fff7fe0, 0, -0x80000000, 0x8000, 0x108020, -0x7ff00000, 0x100020, -0x7fffffe0, 0, 0x108000, 0x8020, -0x7fef8000, + -0x7ff00000, 0x8020, 0, 0x108020, -0x7fefffe0, 0x100000, -0x7fff7fe0, -0x7ff00000, -0x7fef8000, 0x8000, -0x7ff00000, + -0x7fff8000, 0x20, -0x7fef7fe0, 0x108020, 0x20, 0x8000, -0x80000000, 0x8020, -0x7fef8000, 0x100000, -0x7fffffe0, + 0x100020, -0x7fff7fe0, -0x7fffffe0, 0x100020, 0x108000, 0, -0x7fff8000, 0x8020, -0x80000000, -0x7fefffe0, + -0x7fef7fe0, 0x108000 + ]; + const spfunction3 = [ + 0x208, 0x8020200, 0, 0x8020008, 0x8000200, 0, 0x20208, 0x8000200, 0x20008, 0x8000008, + 0x8000008, 0x20000, 0x8020208, 0x20008, 0x8020000, 0x208, 0x8000000, 0x8, 0x8020200, 0x200, 0x20200, 0x8020000, + 0x8020008, 0x20208, 0x8000208, 0x20200, 0x20000, 0x8000208, 0x8, 0x8020208, 0x200, 0x8000000, 0x8020200, 0x8000000, + 0x20008, 0x208, 0x20000, 0x8020200, 0x8000200, 0, 0x200, 0x20008, 0x8020208, 0x8000200, 0x8000008, 0x200, 0, + 0x8020008, 0x8000208, 0x20000, 0x8000000, 0x8020208, 0x8, 0x20208, 0x20200, 0x8000008, 0x8020000, 0x8000208, 0x208, + 0x8020000, 0x20208, 0x8, 0x8020008, 0x20200 + ]; + const spfunction4 = [ + 0x802001, 0x2081, 0x2081, 0x80, 0x802080, 0x800081, 0x800001, 0x2001, 0, 0x802000, + 0x802000, 0x802081, 0x81, 0, 0x800080, 0x800001, 0x1, 0x2000, 0x800000, 0x802001, 0x80, 0x800000, 0x2001, 0x2080, + 0x800081, 0x1, 0x2080, 0x800080, 0x2000, 0x802080, 0x802081, 0x81, 0x800080, 0x800001, 0x802000, 0x802081, 0x81, 0, + 0, 0x802000, 0x2080, 0x800080, 0x800081, 0x1, 0x802001, 0x2081, 0x2081, 0x80, 0x802081, 0x81, 0x1, 0x2000, 0x800001, + 0x2001, 0x802080, 0x800081, 0x2001, 0x2080, 0x800000, 0x802001, 0x80, 0x800000, 0x2000, 0x802080 + ]; + const spfunction5 = [ + 0x100, 0x2080100, 0x2080000, 0x42000100, 0x80000, 0x100, 0x40000000, 0x2080000, + 0x40080100, 0x80000, 0x2000100, 0x40080100, 0x42000100, 0x42080000, 0x80100, 0x40000000, 0x2000000, 0x40080000, + 0x40080000, 0, 0x40000100, 0x42080100, 0x42080100, 0x2000100, 0x42080000, 0x40000100, 0, 0x42000000, 0x2080100, + 0x2000000, 0x42000000, 0x80100, 0x80000, 0x42000100, 0x100, 0x2000000, 0x40000000, 0x2080000, 0x42000100, + 0x40080100, 0x2000100, 0x40000000, 0x42080000, 0x2080100, 0x40080100, 0x100, 0x2000000, 0x42080000, 0x42080100, + 0x80100, 0x42000000, 0x42080100, 0x2080000, 0, 0x40080000, 0x42000000, 0x80100, 0x2000100, 0x40000100, 0x80000, 0, + 0x40080000, 0x2080100, 0x40000100 + ]; + const spfunction6 = [ + 0x20000010, 0x20400000, 0x4000, 0x20404010, 0x20400000, 0x10, 0x20404010, 0x400000, + 0x20004000, 0x404010, 0x400000, 0x20000010, 0x400010, 0x20004000, 0x20000000, 0x4010, 0, 0x400010, 0x20004010, + 0x4000, 0x404000, 0x20004010, 0x10, 0x20400010, 0x20400010, 0, 0x404010, 0x20404000, 0x4010, 0x404000, 0x20404000, + 0x20000000, 0x20004000, 0x10, 0x20400010, 0x404000, 0x20404010, 0x400000, 0x4010, 0x20000010, 0x400000, 0x20004000, + 0x20000000, 0x4010, 0x20000010, 0x20404010, 0x404000, 0x20400000, 0x404010, 0x20404000, 0, 0x20400010, 0x10, 0x4000, + 0x20400000, 0x404010, 0x4000, 0x400010, 0x20004010, 0, 0x20404000, 0x20000000, 0x400010, 0x20004010 + ]; + const spfunction7 = [ + 0x200000, 0x4200002, 0x4000802, 0, 0x800, 0x4000802, 0x200802, 0x4200800, 0x4200802, + 0x200000, 0, 0x4000002, 0x2, 0x4000000, 0x4200002, 0x802, 0x4000800, 0x200802, 0x200002, 0x4000800, 0x4000002, + 0x4200000, 0x4200800, 0x200002, 0x4200000, 0x800, 0x802, 0x4200802, 0x200800, 0x2, 0x4000000, 0x200800, 0x4000000, + 0x200800, 0x200000, 0x4000802, 0x4000802, 0x4200002, 0x4200002, 0x2, 0x200002, 0x4000000, 0x4000800, 0x200000, + 0x4200800, 0x802, 0x200802, 0x4200800, 0x802, 0x4000002, 0x4200802, 0x4200000, 0x200800, 0, 0x2, 0x4200802, 0, + 0x200802, 0x4200000, 0x800, 0x4000002, 0x4000800, 0x800, 0x200002 + ]; + const spfunction8 = [ + 0x10001040, 0x1000, 0x40000, 0x10041040, 0x10000000, 0x10001040, 0x40, 0x10000000, + 0x40040, 0x10040000, 0x10041040, 0x41000, 0x10041000, 0x41040, 0x1000, 0x40, 0x10040000, 0x10000040, 0x10001000, + 0x1040, 0x41000, 0x40040, 0x10040040, 0x10041000, 0x1040, 0, 0, 0x10040040, 0x10000040, 0x10001000, 0x41040, + 0x40000, 0x41040, 0x40000, 0x10041000, 0x1000, 0x40, 0x10040040, 0x1000, 0x41040, 0x10001000, 0x40, 0x10000040, + 0x10040000, 0x10040040, 0x10000000, 0x40000, 0x10001040, 0, 0x10041040, 0x40040, 0x10000040, 0x10040000, 0x10001000, + 0x10001040, 0, 0x10041040, 0x41000, 0x41000, 0x1040, 0x1040, 0x40040, 0x10000000, 0x10041000 + ]; + + //create the 16 or 48 subkeys we will need + let m = 0; + let i; + let j; + let temp; + let right1; + let right2; + let left; + let right; + let looping; + let cbcleft; + let cbcleft2; + let cbcright; + let cbcright2; + let endloop; + let loopinc; + let len = message.length; + + //set up the loops for single and triple des + const iterations = keys.length === 32 ? 3 : 9; //single or triple des + if (iterations === 3) { + looping = encrypt ? [0, 32, 2] : [30, -2, -2]; + } else { + looping = encrypt ? [0, 32, 2, 62, 30, -2, 64, 96, 2] : [94, 62, -2, 32, 64, 2, 30, -2, -2]; + } + + //pad the message depending on the padding parameter + //only add padding if encrypting - note that you need to use the same padding option for both encrypt and decrypt + if (encrypt) { + message = desAddPadding(message, padding); + len = message.length; + } + + //store the result here + let result = new Uint8Array(len); + let k = 0; + + if (mode === 1) { //CBC mode + cbcleft = (iv[m++] << 24) | (iv[m++] << 16) | (iv[m++] << 8) | iv[m++]; + cbcright = (iv[m++] << 24) | (iv[m++] << 16) | (iv[m++] << 8) | iv[m++]; + m = 0; + } + + //loop through each 64 bit chunk of the message + while (m < len) { + left = (message[m++] << 24) | (message[m++] << 16) | (message[m++] << 8) | message[m++]; + right = (message[m++] << 24) | (message[m++] << 16) | (message[m++] << 8) | message[m++]; + + //for Cipher Block Chaining mode, xor the message with the previous result + if (mode === 1) { + if (encrypt) { + left ^= cbcleft; + right ^= cbcright; + } else { + cbcleft2 = cbcleft; + cbcright2 = cbcright; + cbcleft = left; + cbcright = right; + } + } + + //first each 64 but chunk of the message must be permuted according to IP + temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; + right ^= temp; + left ^= (temp << 4); + temp = ((left >>> 16) ^ right) & 0x0000ffff; + right ^= temp; + left ^= (temp << 16); + temp = ((right >>> 2) ^ left) & 0x33333333; + left ^= temp; + right ^= (temp << 2); + temp = ((right >>> 8) ^ left) & 0x00ff00ff; + left ^= temp; + right ^= (temp << 8); + temp = ((left >>> 1) ^ right) & 0x55555555; + right ^= temp; + left ^= (temp << 1); + + left = ((left << 1) | (left >>> 31)); + right = ((right << 1) | (right >>> 31)); + + //do this either 1 or 3 times for each chunk of the message + for (j = 0; j < iterations; j += 3) { + endloop = looping[j + 1]; + loopinc = looping[j + 2]; + //now go through and perform the encryption or decryption + for (i = looping[j]; i !== endloop; i += loopinc) { //for efficiency + right1 = right ^ keys[i]; + right2 = ((right >>> 4) | (right << 28)) ^ keys[i + 1]; + //the result is attained by passing these bytes through the S selection functions + temp = left; + left = right; + right = temp ^ (spfunction2[(right1 >>> 24) & 0x3f] | spfunction4[(right1 >>> 16) & 0x3f] | spfunction6[(right1 >>> + 8) & 0x3f] | spfunction8[right1 & 0x3f] | spfunction1[(right2 >>> 24) & 0x3f] | spfunction3[(right2 >>> 16) & + 0x3f] | spfunction5[(right2 >>> 8) & 0x3f] | spfunction7[right2 & 0x3f]); + } + temp = left; + left = right; + right = temp; //unreverse left and right + } //for either 1 or 3 iterations + + //move then each one bit to the right + left = ((left >>> 1) | (left << 31)); + right = ((right >>> 1) | (right << 31)); + + //now perform IP-1, which is IP in the opposite direction + temp = ((left >>> 1) ^ right) & 0x55555555; + right ^= temp; + left ^= (temp << 1); + temp = ((right >>> 8) ^ left) & 0x00ff00ff; + left ^= temp; + right ^= (temp << 8); + temp = ((right >>> 2) ^ left) & 0x33333333; + left ^= temp; + right ^= (temp << 2); + temp = ((left >>> 16) ^ right) & 0x0000ffff; + right ^= temp; + left ^= (temp << 16); + temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; + right ^= temp; + left ^= (temp << 4); + + //for Cipher Block Chaining mode, xor the message with the previous result + if (mode === 1) { + if (encrypt) { + cbcleft = left; + cbcright = right; + } else { + left ^= cbcleft2; + right ^= cbcright2; + } + } + + result[k++] = (left >>> 24); + result[k++] = ((left >>> 16) & 0xff); + result[k++] = ((left >>> 8) & 0xff); + result[k++] = (left & 0xff); + result[k++] = (right >>> 24); + result[k++] = ((right >>> 16) & 0xff); + result[k++] = ((right >>> 8) & 0xff); + result[k++] = (right & 0xff); + } //for every 8 characters, or 64 bits in the message + + //only remove padding if decrypting - note that you need to use the same padding option for both encrypt and decrypt + if (!encrypt) { + result = desRemovePadding(result, padding); + } + + return result; +} //end of des + + +//desCreateKeys +//this takes as input a 64 bit key (even though only 56 bits are used) +//as an array of 2 integers, and returns 16 48 bit keys + +function desCreateKeys(key) { + //declaring this locally speeds things up a bit + const pc2bytes0 = [ + 0, 0x4, 0x20000000, 0x20000004, 0x10000, 0x10004, 0x20010000, 0x20010004, 0x200, 0x204, + 0x20000200, 0x20000204, 0x10200, 0x10204, 0x20010200, 0x20010204 + ]; + const pc2bytes1 = [ + 0, 0x1, 0x100000, 0x100001, 0x4000000, 0x4000001, 0x4100000, 0x4100001, 0x100, 0x101, 0x100100, + 0x100101, 0x4000100, 0x4000101, 0x4100100, 0x4100101 + ]; + const pc2bytes2 = [ + 0, 0x8, 0x800, 0x808, 0x1000000, 0x1000008, 0x1000800, 0x1000808, 0, 0x8, 0x800, 0x808, + 0x1000000, 0x1000008, 0x1000800, 0x1000808 + ]; + const pc2bytes3 = [ + 0, 0x200000, 0x8000000, 0x8200000, 0x2000, 0x202000, 0x8002000, 0x8202000, 0x20000, 0x220000, + 0x8020000, 0x8220000, 0x22000, 0x222000, 0x8022000, 0x8222000 + ]; + const pc2bytes4 = [ + 0, 0x40000, 0x10, 0x40010, 0, 0x40000, 0x10, 0x40010, 0x1000, 0x41000, 0x1010, 0x41010, 0x1000, + 0x41000, 0x1010, 0x41010 + ]; + const pc2bytes5 = [ + 0, 0x400, 0x20, 0x420, 0, 0x400, 0x20, 0x420, 0x2000000, 0x2000400, 0x2000020, 0x2000420, + 0x2000000, 0x2000400, 0x2000020, 0x2000420 + ]; + const pc2bytes6 = [ + 0, 0x10000000, 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002, 0, 0x10000000, + 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002 + ]; + const pc2bytes7 = [ + 0, 0x10000, 0x800, 0x10800, 0x20000000, 0x20010000, 0x20000800, 0x20010800, 0x20000, 0x30000, + 0x20800, 0x30800, 0x20020000, 0x20030000, 0x20020800, 0x20030800 + ]; + const pc2bytes8 = [ + 0, 0x40000, 0, 0x40000, 0x2, 0x40002, 0x2, 0x40002, 0x2000000, 0x2040000, 0x2000000, 0x2040000, + 0x2000002, 0x2040002, 0x2000002, 0x2040002 + ]; + const pc2bytes9 = [ + 0, 0x10000000, 0x8, 0x10000008, 0, 0x10000000, 0x8, 0x10000008, 0x400, 0x10000400, 0x408, + 0x10000408, 0x400, 0x10000400, 0x408, 0x10000408 + ]; + const pc2bytes10 = [ + 0, 0x20, 0, 0x20, 0x100000, 0x100020, 0x100000, 0x100020, 0x2000, 0x2020, 0x2000, 0x2020, + 0x102000, 0x102020, 0x102000, 0x102020 + ]; + const pc2bytes11 = [ + 0, 0x1000000, 0x200, 0x1000200, 0x200000, 0x1200000, 0x200200, 0x1200200, 0x4000000, 0x5000000, + 0x4000200, 0x5000200, 0x4200000, 0x5200000, 0x4200200, 0x5200200 + ]; + const pc2bytes12 = [ + 0, 0x1000, 0x8000000, 0x8001000, 0x80000, 0x81000, 0x8080000, 0x8081000, 0x10, 0x1010, + 0x8000010, 0x8001010, 0x80010, 0x81010, 0x8080010, 0x8081010 + ]; + const pc2bytes13 = [0, 0x4, 0x100, 0x104, 0, 0x4, 0x100, 0x104, 0x1, 0x5, 0x101, 0x105, 0x1, 0x5, 0x101, 0x105]; + + //how many iterations (1 for des, 3 for triple des) + const iterations = key.length > 8 ? 3 : 1; //changed by Paul 16/6/2007 to use Triple DES for 9+ byte keys + //stores the return keys + const keys = new Array(32 * iterations); + //now define the left shifts which need to be done + const shifts = [0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0]; + //other variables + let lefttemp; + let righttemp; + let m = 0; + let n = 0; + let temp; + + for (let j = 0; j < iterations; j++) { //either 1 or 3 iterations + let left = (key[m++] << 24) | (key[m++] << 16) | (key[m++] << 8) | key[m++]; + let right = (key[m++] << 24) | (key[m++] << 16) | (key[m++] << 8) | key[m++]; + + temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; + right ^= temp; + left ^= (temp << 4); + temp = ((right >>> -16) ^ left) & 0x0000ffff; + left ^= temp; + right ^= (temp << -16); + temp = ((left >>> 2) ^ right) & 0x33333333; + right ^= temp; + left ^= (temp << 2); + temp = ((right >>> -16) ^ left) & 0x0000ffff; + left ^= temp; + right ^= (temp << -16); + temp = ((left >>> 1) ^ right) & 0x55555555; + right ^= temp; + left ^= (temp << 1); + temp = ((right >>> 8) ^ left) & 0x00ff00ff; + left ^= temp; + right ^= (temp << 8); + temp = ((left >>> 1) ^ right) & 0x55555555; + right ^= temp; + left ^= (temp << 1); + + //the right side needs to be shifted and to get the last four bits of the left side + temp = (left << 8) | ((right >>> 20) & 0x000000f0); + //left needs to be put upside down + left = (right << 24) | ((right << 8) & 0xff0000) | ((right >>> 8) & 0xff00) | ((right >>> 24) & 0xf0); + right = temp; + + //now go through and perform these shifts on the left and right keys + for (let i = 0; i < shifts.length; i++) { + //shift the keys either one or two bits to the left + if (shifts[i]) { + left = (left << 2) | (left >>> 26); + right = (right << 2) | (right >>> 26); + } else { + left = (left << 1) | (left >>> 27); + right = (right << 1) | (right >>> 27); + } + left &= -0xf; + right &= -0xf; + + //now apply PC-2, in such a way that E is easier when encrypting or decrypting + //this conversion will look like PC-2 except only the last 6 bits of each byte are used + //rather than 48 consecutive bits and the order of lines will be according to + //how the S selection functions will be applied: S2, S4, S6, S8, S1, S3, S5, S7 + lefttemp = pc2bytes0[left >>> 28] | pc2bytes1[(left >>> 24) & 0xf] | pc2bytes2[(left >>> 20) & 0xf] | pc2bytes3[( + left >>> 16) & 0xf] | pc2bytes4[(left >>> 12) & 0xf] | pc2bytes5[(left >>> 8) & 0xf] | pc2bytes6[(left >>> 4) & + 0xf]; + righttemp = pc2bytes7[right >>> 28] | pc2bytes8[(right >>> 24) & 0xf] | pc2bytes9[(right >>> 20) & 0xf] | + pc2bytes10[(right >>> 16) & 0xf] | pc2bytes11[(right >>> 12) & 0xf] | pc2bytes12[(right >>> 8) & 0xf] | + pc2bytes13[(right >>> 4) & 0xf]; + temp = ((righttemp >>> 16) ^ lefttemp) & 0x0000ffff; + keys[n++] = lefttemp ^ temp; + keys[n++] = righttemp ^ (temp << 16); + } + } //for each iterations + //return the keys we've created + return keys; +} //end of desCreateKeys + + +function desAddPadding(message, padding) { + const padLength = 8 - (message.length % 8); + + let pad; + if (padding === 2 && (padLength < 8)) { //pad the message with spaces + pad = ' '.charCodeAt(0); + } else if (padding === 1) { //PKCS7 padding + pad = padLength; + } else if (!padding && (padLength < 8)) { //pad the message out with null bytes + pad = 0; + } else if (padLength === 8) { + return message; + } else { + throw new Error('des: invalid padding'); + } + + const paddedMessage = new Uint8Array(message.length + padLength); + for (let i = 0; i < message.length; i++) { + paddedMessage[i] = message[i]; + } + for (let j = 0; j < padLength; j++) { + paddedMessage[message.length + j] = pad; + } + + return paddedMessage; +} + +function desRemovePadding(message, padding) { + let padLength = null; + let pad; + if (padding === 2) { // space padded + pad = ' '.charCodeAt(0); + } else if (padding === 1) { // PKCS7 + padLength = message[message.length - 1]; + } else if (!padding) { // null padding + pad = 0; + } else { + throw new Error('des: invalid padding'); + } + + if (!padLength) { + padLength = 1; + while (message[message.length - padLength] === pad) { + padLength++; + } + padLength--; + } + + return message.subarray(0, message.length - padLength); +} + +// added by Recurity Labs + +function TripleDES(key) { + this.key = []; + + for (let i = 0; i < 3; i++) { + this.key.push(new Uint8Array(key.subarray(i * 8, (i * 8) + 8))); + } + + this.encrypt = function(block) { + return des( + desCreateKeys(this.key[2]), + des( + desCreateKeys(this.key[1]), + des( + desCreateKeys(this.key[0]), + block, true, 0, null, null + ), + false, 0, null, null + ), true, 0, null, null + ); + }; +} + +TripleDES.keySize = TripleDES.prototype.keySize = 24; +TripleDES.blockSize = TripleDES.prototype.blockSize = 8; + +// This is "original" DES + +function DES(key) { + this.key = key; + + this.encrypt = function(block, padding) { + const keys = desCreateKeys(this.key); + return des(keys, block, true, 0, null, padding); + }; + + this.decrypt = function(block, padding) { + const keys = desCreateKeys(this.key); + return des(keys, block, false, 0, null, padding); + }; +} + +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Copyright 2010 pjacobs@xeekr.com . All rights reserved. + +// Modified by Recurity Labs GmbH + +// fixed/modified by Herbert Hanewinkel, www.haneWIN.de +// check www.haneWIN.de for the latest version + +// cast5.js is a Javascript implementation of CAST-128, as defined in RFC 2144. +// CAST-128 is a common OpenPGP cipher. + + +// CAST5 constructor + +function OpenPGPSymEncCAST5() { + this.BlockSize = 8; + this.KeySize = 16; + + this.setKey = function(key) { + this.masking = new Array(16); + this.rotate = new Array(16); + + this.reset(); + + if (key.length === this.KeySize) { + this.keySchedule(key); + } else { + throw new Error('CAST-128: keys must be 16 bytes'); + } + return true; + }; + + this.reset = function() { + for (let i = 0; i < 16; i++) { + this.masking[i] = 0; + this.rotate[i] = 0; + } + }; + + this.getBlockSize = function() { + return this.BlockSize; + }; + + this.encrypt = function(src) { + const dst = new Array(src.length); + + for (let i = 0; i < src.length; i += 8) { + let l = (src[i] << 24) | (src[i + 1] << 16) | (src[i + 2] << 8) | src[i + 3]; + let r = (src[i + 4] << 24) | (src[i + 5] << 16) | (src[i + 6] << 8) | src[i + 7]; + let t; + + t = r; + r = l ^ f1(r, this.masking[0], this.rotate[0]); + l = t; + t = r; + r = l ^ f2(r, this.masking[1], this.rotate[1]); + l = t; + t = r; + r = l ^ f3(r, this.masking[2], this.rotate[2]); + l = t; + t = r; + r = l ^ f1(r, this.masking[3], this.rotate[3]); + l = t; + + t = r; + r = l ^ f2(r, this.masking[4], this.rotate[4]); + l = t; + t = r; + r = l ^ f3(r, this.masking[5], this.rotate[5]); + l = t; + t = r; + r = l ^ f1(r, this.masking[6], this.rotate[6]); + l = t; + t = r; + r = l ^ f2(r, this.masking[7], this.rotate[7]); + l = t; + + t = r; + r = l ^ f3(r, this.masking[8], this.rotate[8]); + l = t; + t = r; + r = l ^ f1(r, this.masking[9], this.rotate[9]); + l = t; + t = r; + r = l ^ f2(r, this.masking[10], this.rotate[10]); + l = t; + t = r; + r = l ^ f3(r, this.masking[11], this.rotate[11]); + l = t; + + t = r; + r = l ^ f1(r, this.masking[12], this.rotate[12]); + l = t; + t = r; + r = l ^ f2(r, this.masking[13], this.rotate[13]); + l = t; + t = r; + r = l ^ f3(r, this.masking[14], this.rotate[14]); + l = t; + t = r; + r = l ^ f1(r, this.masking[15], this.rotate[15]); + l = t; + + dst[i] = (r >>> 24) & 255; + dst[i + 1] = (r >>> 16) & 255; + dst[i + 2] = (r >>> 8) & 255; + dst[i + 3] = r & 255; + dst[i + 4] = (l >>> 24) & 255; + dst[i + 5] = (l >>> 16) & 255; + dst[i + 6] = (l >>> 8) & 255; + dst[i + 7] = l & 255; + } + + return dst; + }; + + this.decrypt = function(src) { + const dst = new Array(src.length); + + for (let i = 0; i < src.length; i += 8) { + let l = (src[i] << 24) | (src[i + 1] << 16) | (src[i + 2] << 8) | src[i + 3]; + let r = (src[i + 4] << 24) | (src[i + 5] << 16) | (src[i + 6] << 8) | src[i + 7]; + let t; + + t = r; + r = l ^ f1(r, this.masking[15], this.rotate[15]); + l = t; + t = r; + r = l ^ f3(r, this.masking[14], this.rotate[14]); + l = t; + t = r; + r = l ^ f2(r, this.masking[13], this.rotate[13]); + l = t; + t = r; + r = l ^ f1(r, this.masking[12], this.rotate[12]); + l = t; + + t = r; + r = l ^ f3(r, this.masking[11], this.rotate[11]); + l = t; + t = r; + r = l ^ f2(r, this.masking[10], this.rotate[10]); + l = t; + t = r; + r = l ^ f1(r, this.masking[9], this.rotate[9]); + l = t; + t = r; + r = l ^ f3(r, this.masking[8], this.rotate[8]); + l = t; + + t = r; + r = l ^ f2(r, this.masking[7], this.rotate[7]); + l = t; + t = r; + r = l ^ f1(r, this.masking[6], this.rotate[6]); + l = t; + t = r; + r = l ^ f3(r, this.masking[5], this.rotate[5]); + l = t; + t = r; + r = l ^ f2(r, this.masking[4], this.rotate[4]); + l = t; + + t = r; + r = l ^ f1(r, this.masking[3], this.rotate[3]); + l = t; + t = r; + r = l ^ f3(r, this.masking[2], this.rotate[2]); + l = t; + t = r; + r = l ^ f2(r, this.masking[1], this.rotate[1]); + l = t; + t = r; + r = l ^ f1(r, this.masking[0], this.rotate[0]); + l = t; + + dst[i] = (r >>> 24) & 255; + dst[i + 1] = (r >>> 16) & 255; + dst[i + 2] = (r >>> 8) & 255; + dst[i + 3] = r & 255; + dst[i + 4] = (l >>> 24) & 255; + dst[i + 5] = (l >> 16) & 255; + dst[i + 6] = (l >> 8) & 255; + dst[i + 7] = l & 255; + } + + return dst; + }; + const scheduleA = new Array(4); + + scheduleA[0] = new Array(4); + scheduleA[0][0] = [4, 0, 0xd, 0xf, 0xc, 0xe, 0x8]; + scheduleA[0][1] = [5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa]; + scheduleA[0][2] = [6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9]; + scheduleA[0][3] = [7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb]; + + scheduleA[1] = new Array(4); + scheduleA[1][0] = [0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0]; + scheduleA[1][1] = [1, 4, 0, 2, 1, 3, 16 + 2]; + scheduleA[1][2] = [2, 5, 7, 6, 5, 4, 16 + 1]; + scheduleA[1][3] = [3, 7, 0xa, 9, 0xb, 8, 16 + 3]; + + scheduleA[2] = new Array(4); + scheduleA[2][0] = [4, 0, 0xd, 0xf, 0xc, 0xe, 8]; + scheduleA[2][1] = [5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa]; + scheduleA[2][2] = [6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9]; + scheduleA[2][3] = [7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb]; + + + scheduleA[3] = new Array(4); + scheduleA[3][0] = [0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0]; + scheduleA[3][1] = [1, 4, 0, 2, 1, 3, 16 + 2]; + scheduleA[3][2] = [2, 5, 7, 6, 5, 4, 16 + 1]; + scheduleA[3][3] = [3, 7, 0xa, 9, 0xb, 8, 16 + 3]; + + const scheduleB = new Array(4); + + scheduleB[0] = new Array(4); + scheduleB[0][0] = [16 + 8, 16 + 9, 16 + 7, 16 + 6, 16 + 2]; + scheduleB[0][1] = [16 + 0xa, 16 + 0xb, 16 + 5, 16 + 4, 16 + 6]; + scheduleB[0][2] = [16 + 0xc, 16 + 0xd, 16 + 3, 16 + 2, 16 + 9]; + scheduleB[0][3] = [16 + 0xe, 16 + 0xf, 16 + 1, 16 + 0, 16 + 0xc]; + + scheduleB[1] = new Array(4); + scheduleB[1][0] = [3, 2, 0xc, 0xd, 8]; + scheduleB[1][1] = [1, 0, 0xe, 0xf, 0xd]; + scheduleB[1][2] = [7, 6, 8, 9, 3]; + scheduleB[1][3] = [5, 4, 0xa, 0xb, 7]; + + + scheduleB[2] = new Array(4); + scheduleB[2][0] = [16 + 3, 16 + 2, 16 + 0xc, 16 + 0xd, 16 + 9]; + scheduleB[2][1] = [16 + 1, 16 + 0, 16 + 0xe, 16 + 0xf, 16 + 0xc]; + scheduleB[2][2] = [16 + 7, 16 + 6, 16 + 8, 16 + 9, 16 + 2]; + scheduleB[2][3] = [16 + 5, 16 + 4, 16 + 0xa, 16 + 0xb, 16 + 6]; + + + scheduleB[3] = new Array(4); + scheduleB[3][0] = [8, 9, 7, 6, 3]; + scheduleB[3][1] = [0xa, 0xb, 5, 4, 7]; + scheduleB[3][2] = [0xc, 0xd, 3, 2, 8]; + scheduleB[3][3] = [0xe, 0xf, 1, 0, 0xd]; + + // changed 'in' to 'inn' (in javascript 'in' is a reserved word) + this.keySchedule = function(inn) { + const t = new Array(8); + const k = new Array(32); + + let j; + + for (let i = 0; i < 4; i++) { + j = i * 4; + t[i] = (inn[j] << 24) | (inn[j + 1] << 16) | (inn[j + 2] << 8) | inn[j + 3]; + } + + const x = [6, 7, 4, 5]; + let ki = 0; + let w; + + for (let half = 0; half < 2; half++) { + for (let round = 0; round < 4; round++) { + for (j = 0; j < 4; j++) { + const a = scheduleA[round][j]; + w = t[a[1]]; + + w ^= sBox[4][(t[a[2] >>> 2] >>> (24 - 8 * (a[2] & 3))) & 0xff]; + w ^= sBox[5][(t[a[3] >>> 2] >>> (24 - 8 * (a[3] & 3))) & 0xff]; + w ^= sBox[6][(t[a[4] >>> 2] >>> (24 - 8 * (a[4] & 3))) & 0xff]; + w ^= sBox[7][(t[a[5] >>> 2] >>> (24 - 8 * (a[5] & 3))) & 0xff]; + w ^= sBox[x[j]][(t[a[6] >>> 2] >>> (24 - 8 * (a[6] & 3))) & 0xff]; + t[a[0]] = w; + } + + for (j = 0; j < 4; j++) { + const b = scheduleB[round][j]; + w = sBox[4][(t[b[0] >>> 2] >>> (24 - 8 * (b[0] & 3))) & 0xff]; + + w ^= sBox[5][(t[b[1] >>> 2] >>> (24 - 8 * (b[1] & 3))) & 0xff]; + w ^= sBox[6][(t[b[2] >>> 2] >>> (24 - 8 * (b[2] & 3))) & 0xff]; + w ^= sBox[7][(t[b[3] >>> 2] >>> (24 - 8 * (b[3] & 3))) & 0xff]; + w ^= sBox[4 + j][(t[b[4] >>> 2] >>> (24 - 8 * (b[4] & 3))) & 0xff]; + k[ki] = w; + ki++; + } + } + } + + for (let i = 0; i < 16; i++) { + this.masking[i] = k[i]; + this.rotate[i] = k[16 + i] & 0x1f; + } + }; + + // These are the three 'f' functions. See RFC 2144, section 2.2. + + function f1(d, m, r) { + const t = m + d; + const I = (t << r) | (t >>> (32 - r)); + return ((sBox[0][I >>> 24] ^ sBox[1][(I >>> 16) & 255]) - sBox[2][(I >>> 8) & 255]) + sBox[3][I & 255]; + } + + function f2(d, m, r) { + const t = m ^ d; + const I = (t << r) | (t >>> (32 - r)); + return ((sBox[0][I >>> 24] - sBox[1][(I >>> 16) & 255]) + sBox[2][(I >>> 8) & 255]) ^ sBox[3][I & 255]; + } + + function f3(d, m, r) { + const t = m - d; + const I = (t << r) | (t >>> (32 - r)); + return ((sBox[0][I >>> 24] + sBox[1][(I >>> 16) & 255]) ^ sBox[2][(I >>> 8) & 255]) - sBox[3][I & 255]; + } + + const sBox = new Array(8); + sBox[0] = [ + 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949, + 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, + 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, + 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0, + 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, + 0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935, + 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d, + 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, + 0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe, + 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3, + 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, + 0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291, + 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779, + 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, + 0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, + 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d, + 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, + 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, + 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c, + 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, + 0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d, + 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96, + 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, + 0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, + 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, + 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, + 0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, + 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872, + 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, + 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, + 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9, + 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf + ]; + + sBox[1] = [ + 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651, + 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, + 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, + 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806, + 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, + 0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359, + 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b, + 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, + 0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34, + 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb, + 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, + 0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860, + 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b, + 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, + 0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, + 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, + 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, + 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, + 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f, + 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, + 0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6, + 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58, + 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, + 0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, + 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6, + 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, + 0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6, + 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f, + 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, + 0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, + 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9, + 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1 + ]; + + sBox[2] = [ + 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90, + 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, + 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, + 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240, + 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, + 0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, + 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71, + 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, + 0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, + 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15, + 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, + 0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176, + 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148, + 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, + 0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, + 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e, + 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, + 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, + 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a, + 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, + 0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, + 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5, + 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, + 0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536, + 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, + 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, + 0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69, + 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, + 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, + 0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, + 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a, + 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783 + ]; + + sBox[3] = [ + 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1, + 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, + 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, + 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121, + 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, + 0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, + 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb, + 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, + 0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d, + 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6, + 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, + 0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003, + 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, + 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, + 0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, + 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a, + 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, + 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, + 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26, + 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, + 0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7, + 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417, + 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, + 0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2, + 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, + 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, + 0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, + 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, + 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, + 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, + 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282, + 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2 + ]; + + sBox[4] = [ + 0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f, + 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, + 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, + 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02, + 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, + 0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7, + 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9, + 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, + 0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774, + 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655, + 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, + 0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910, + 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1, + 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, + 0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, + 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f, + 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, + 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, + 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3, + 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, + 0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4, + 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2, + 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, + 0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5, + 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, + 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, + 0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801, + 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, + 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, + 0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, + 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8, + 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4 + ]; + + sBox[5] = [ + 0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac, + 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, + 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, + 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98, + 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, + 0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3, + 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd, + 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, + 0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9, + 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54, + 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, + 0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc, + 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf, + 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, + 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, + 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289, + 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, + 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, + 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b, + 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, + 0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13, + 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976, + 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, + 0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891, + 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da, + 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, + 0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084, + 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25, + 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, + 0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, + 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd, + 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f + ]; + + sBox[6] = [ + 0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f, + 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, + 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, + 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19, + 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, + 0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516, + 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88, + 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, + 0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756, + 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, + 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, + 0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688, + 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28, + 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, + 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, + 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, + 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, + 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, + 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566, + 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, + 0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962, + 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e, + 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, + 0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c, + 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, + 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, + 0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be, + 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767, + 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, + 0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, + 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c, + 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3 + ]; + + sBox[7] = [ + 0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5, + 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, + 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, + 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d, + 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, + 0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862, + 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc, + 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, + 0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e, + 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039, + 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, + 0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42, + 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5, + 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, + 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, + 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c, + 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, + 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, + 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70, + 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, + 0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c, + 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3, + 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, + 0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101, + 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f, + 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, + 0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a, + 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c, + 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, + 0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, + 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82, + 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e + ]; +} + +function CAST5(key) { + this.cast5 = new OpenPGPSymEncCAST5(); + this.cast5.setKey(key); + + this.encrypt = function(block) { + return this.cast5.encrypt(block); + }; +} + +CAST5.blockSize = CAST5.prototype.blockSize = 8; +CAST5.keySize = CAST5.prototype.keySize = 16; + +/* eslint-disable no-mixed-operators, no-fallthrough */ + + +/* Modified by Recurity Labs GmbH + * + * Cipher.js + * A block-cipher algorithm implementation on JavaScript + * See Cipher.readme.txt for further information. + * + * Copyright(c) 2009 Atsushi Oka [ http://oka.nu/ ] + * This script file is distributed under the LGPL + * + * ACKNOWLEDGMENT + * + * The main subroutines are written by Michiel van Everdingen. + * + * Michiel van Everdingen + * http://home.versatel.nl/MAvanEverdingen/index.html + * + * All rights for these routines are reserved to Michiel van Everdingen. + * + */ + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//Math +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +const MAXINT = 0xFFFFFFFF; + +function rotw(w, n) { + return (w << n | w >>> (32 - n)) & MAXINT; +} + +function getW(a, i) { + return a[i] | a[i + 1] << 8 | a[i + 2] << 16 | a[i + 3] << 24; +} + +function setW(a, i, w) { + a.splice(i, 4, w & 0xFF, (w >>> 8) & 0xFF, (w >>> 16) & 0xFF, (w >>> 24) & 0xFF); +} + +function getB(x, n) { + return (x >>> (n * 8)) & 0xFF; +} + +// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Twofish +// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +function createTwofish() { + // + let keyBytes = null; + let dataBytes = null; + let dataOffset = -1; + // var dataLength = -1; + // var idx2 = -1; + // + + let tfsKey = []; + let tfsM = [ + [], + [], + [], + [] + ]; + + function tfsInit(key) { + keyBytes = key; + let i; + let a; + let b; + let c; + let d; + const meKey = []; + const moKey = []; + const inKey = []; + let kLen; + const sKey = []; + let f01; + let f5b; + let fef; + + const q0 = [ + [8, 1, 7, 13, 6, 15, 3, 2, 0, 11, 5, 9, 14, 12, 10, 4], + [2, 8, 11, 13, 15, 7, 6, 14, 3, 1, 9, 4, 0, 10, 12, 5] + ]; + const q1 = [ + [14, 12, 11, 8, 1, 2, 3, 5, 15, 4, 10, 6, 7, 0, 9, 13], + [1, 14, 2, 11, 4, 12, 3, 7, 6, 13, 10, 5, 15, 9, 0, 8] + ]; + const q2 = [ + [11, 10, 5, 14, 6, 13, 9, 0, 12, 8, 15, 3, 2, 4, 7, 1], + [4, 12, 7, 5, 1, 6, 9, 10, 0, 14, 13, 8, 2, 11, 3, 15] + ]; + const q3 = [ + [13, 7, 15, 4, 1, 2, 6, 14, 9, 11, 3, 0, 8, 5, 12, 10], + [11, 9, 5, 1, 12, 3, 13, 14, 6, 4, 7, 15, 2, 0, 8, 10] + ]; + const ror4 = [0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15]; + const ashx = [0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 5, 14, 7]; + const q = [ + [], + [] + ]; + const m = [ + [], + [], + [], + [] + ]; + + function ffm5b(x) { + return x ^ (x >> 2) ^ [0, 90, 180, 238][x & 3]; + } + + function ffmEf(x) { + return x ^ (x >> 1) ^ (x >> 2) ^ [0, 238, 180, 90][x & 3]; + } + + function mdsRem(p, q) { + let i; + let t; + let u; + for (i = 0; i < 8; i++) { + t = q >>> 24; + q = ((q << 8) & MAXINT) | p >>> 24; + p = (p << 8) & MAXINT; + u = t << 1; + if (t & 128) { + u ^= 333; + } + q ^= t ^ (u << 16); + u ^= t >>> 1; + if (t & 1) { + u ^= 166; + } + q ^= u << 24 | u << 8; + } + return q; + } + + function qp(n, x) { + const a = x >> 4; + const b = x & 15; + const c = q0[n][a ^ b]; + const d = q1[n][ror4[b] ^ ashx[a]]; + return q3[n][ror4[d] ^ ashx[c]] << 4 | q2[n][c ^ d]; + } + + function hFun(x, key) { + let a = getB(x, 0); + let b = getB(x, 1); + let c = getB(x, 2); + let d = getB(x, 3); + switch (kLen) { + case 4: + a = q[1][a] ^ getB(key[3], 0); + b = q[0][b] ^ getB(key[3], 1); + c = q[0][c] ^ getB(key[3], 2); + d = q[1][d] ^ getB(key[3], 3); + case 3: + a = q[1][a] ^ getB(key[2], 0); + b = q[1][b] ^ getB(key[2], 1); + c = q[0][c] ^ getB(key[2], 2); + d = q[0][d] ^ getB(key[2], 3); + case 2: + a = q[0][q[0][a] ^ getB(key[1], 0)] ^ getB(key[0], 0); + b = q[0][q[1][b] ^ getB(key[1], 1)] ^ getB(key[0], 1); + c = q[1][q[0][c] ^ getB(key[1], 2)] ^ getB(key[0], 2); + d = q[1][q[1][d] ^ getB(key[1], 3)] ^ getB(key[0], 3); + } + return m[0][a] ^ m[1][b] ^ m[2][c] ^ m[3][d]; + } + + keyBytes = keyBytes.slice(0, 32); + i = keyBytes.length; + while (i !== 16 && i !== 24 && i !== 32) { + keyBytes[i++] = 0; + } + + for (i = 0; i < keyBytes.length; i += 4) { + inKey[i >> 2] = getW(keyBytes, i); + } + for (i = 0; i < 256; i++) { + q[0][i] = qp(0, i); + q[1][i] = qp(1, i); + } + for (i = 0; i < 256; i++) { + f01 = q[1][i]; + f5b = ffm5b(f01); + fef = ffmEf(f01); + m[0][i] = f01 + (f5b << 8) + (fef << 16) + (fef << 24); + m[2][i] = f5b + (fef << 8) + (f01 << 16) + (fef << 24); + f01 = q[0][i]; + f5b = ffm5b(f01); + fef = ffmEf(f01); + m[1][i] = fef + (fef << 8) + (f5b << 16) + (f01 << 24); + m[3][i] = f5b + (f01 << 8) + (fef << 16) + (f5b << 24); + } + + kLen = inKey.length / 2; + for (i = 0; i < kLen; i++) { + a = inKey[i + i]; + meKey[i] = a; + b = inKey[i + i + 1]; + moKey[i] = b; + sKey[kLen - i - 1] = mdsRem(a, b); + } + for (i = 0; i < 40; i += 2) { + a = 0x1010101 * i; + b = a + 0x1010101; + a = hFun(a, meKey); + b = rotw(hFun(b, moKey), 8); + tfsKey[i] = (a + b) & MAXINT; + tfsKey[i + 1] = rotw(a + 2 * b, 9); + } + for (i = 0; i < 256; i++) { + a = b = c = d = i; + switch (kLen) { + case 4: + a = q[1][a] ^ getB(sKey[3], 0); + b = q[0][b] ^ getB(sKey[3], 1); + c = q[0][c] ^ getB(sKey[3], 2); + d = q[1][d] ^ getB(sKey[3], 3); + case 3: + a = q[1][a] ^ getB(sKey[2], 0); + b = q[1][b] ^ getB(sKey[2], 1); + c = q[0][c] ^ getB(sKey[2], 2); + d = q[0][d] ^ getB(sKey[2], 3); + case 2: + tfsM[0][i] = m[0][q[0][q[0][a] ^ getB(sKey[1], 0)] ^ getB(sKey[0], 0)]; + tfsM[1][i] = m[1][q[0][q[1][b] ^ getB(sKey[1], 1)] ^ getB(sKey[0], 1)]; + tfsM[2][i] = m[2][q[1][q[0][c] ^ getB(sKey[1], 2)] ^ getB(sKey[0], 2)]; + tfsM[3][i] = m[3][q[1][q[1][d] ^ getB(sKey[1], 3)] ^ getB(sKey[0], 3)]; + } + } + } + + function tfsG0(x) { + return tfsM[0][getB(x, 0)] ^ tfsM[1][getB(x, 1)] ^ tfsM[2][getB(x, 2)] ^ tfsM[3][getB(x, 3)]; + } + + function tfsG1(x) { + return tfsM[0][getB(x, 3)] ^ tfsM[1][getB(x, 0)] ^ tfsM[2][getB(x, 1)] ^ tfsM[3][getB(x, 2)]; + } + + function tfsFrnd(r, blk) { + let a = tfsG0(blk[0]); + let b = tfsG1(blk[1]); + blk[2] = rotw(blk[2] ^ (a + b + tfsKey[4 * r + 8]) & MAXINT, 31); + blk[3] = rotw(blk[3], 1) ^ (a + 2 * b + tfsKey[4 * r + 9]) & MAXINT; + a = tfsG0(blk[2]); + b = tfsG1(blk[3]); + blk[0] = rotw(blk[0] ^ (a + b + tfsKey[4 * r + 10]) & MAXINT, 31); + blk[1] = rotw(blk[1], 1) ^ (a + 2 * b + tfsKey[4 * r + 11]) & MAXINT; + } + + function tfsIrnd(i, blk) { + let a = tfsG0(blk[0]); + let b = tfsG1(blk[1]); + blk[2] = rotw(blk[2], 1) ^ (a + b + tfsKey[4 * i + 10]) & MAXINT; + blk[3] = rotw(blk[3] ^ (a + 2 * b + tfsKey[4 * i + 11]) & MAXINT, 31); + a = tfsG0(blk[2]); + b = tfsG1(blk[3]); + blk[0] = rotw(blk[0], 1) ^ (a + b + tfsKey[4 * i + 8]) & MAXINT; + blk[1] = rotw(blk[1] ^ (a + 2 * b + tfsKey[4 * i + 9]) & MAXINT, 31); + } + + function tfsClose() { + tfsKey = []; + tfsM = [ + [], + [], + [], + [] + ]; + } + + function tfsEncrypt(data, offset) { + dataBytes = data; + dataOffset = offset; + const blk = [getW(dataBytes, dataOffset) ^ tfsKey[0], + getW(dataBytes, dataOffset + 4) ^ tfsKey[1], + getW(dataBytes, dataOffset + 8) ^ tfsKey[2], + getW(dataBytes, dataOffset + 12) ^ tfsKey[3]]; + for (let j = 0; j < 8; j++) { + tfsFrnd(j, blk); + } + setW(dataBytes, dataOffset, blk[2] ^ tfsKey[4]); + setW(dataBytes, dataOffset + 4, blk[3] ^ tfsKey[5]); + setW(dataBytes, dataOffset + 8, blk[0] ^ tfsKey[6]); + setW(dataBytes, dataOffset + 12, blk[1] ^ tfsKey[7]); + dataOffset += 16; + return dataBytes; + } + + function tfsDecrypt(data, offset) { + dataBytes = data; + dataOffset = offset; + const blk = [getW(dataBytes, dataOffset) ^ tfsKey[4], + getW(dataBytes, dataOffset + 4) ^ tfsKey[5], + getW(dataBytes, dataOffset + 8) ^ tfsKey[6], + getW(dataBytes, dataOffset + 12) ^ tfsKey[7]]; + for (let j = 7; j >= 0; j--) { + tfsIrnd(j, blk); + } + setW(dataBytes, dataOffset, blk[2] ^ tfsKey[0]); + setW(dataBytes, dataOffset + 4, blk[3] ^ tfsKey[1]); + setW(dataBytes, dataOffset + 8, blk[0] ^ tfsKey[2]); + setW(dataBytes, dataOffset + 12, blk[1] ^ tfsKey[3]); + dataOffset += 16; + } + + // added by Recurity Labs + + function tfsFinal() { + return dataBytes; + } + + return { + name: 'twofish', + blocksize: 128 / 8, + open: tfsInit, + close: tfsClose, + encrypt: tfsEncrypt, + decrypt: tfsDecrypt, + // added by Recurity Labs + finalize: tfsFinal + }; +} + +// added by Recurity Labs + +function TF(key) { + this.tf = createTwofish(); + this.tf.open(Array.from(key), 0); + + this.encrypt = function(block) { + return this.tf.encrypt(Array.from(block), 0); + }; +} + +TF.keySize = TF.prototype.keySize = 32; +TF.blockSize = TF.prototype.blockSize = 16; + +/* Modified by Recurity Labs GmbH + * + * Originally written by nklein software (nklein.com) + */ + +/* + * Javascript implementation based on Bruce Schneier's reference implementation. + * + * + * The constructor doesn't do much of anything. It's just here + * so we can start defining properties and methods and such. + */ +function Blowfish() {} + +/* + * Declare the block size so that protocols know what size + * Initialization Vector (IV) they will need. + */ +Blowfish.prototype.BLOCKSIZE = 8; + +/* + * These are the default SBOXES. + */ +Blowfish.prototype.SBOXES = [ + [ + 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, + 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, + 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658, + 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, + 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, + 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, + 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6, + 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, + 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, + 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, + 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, + 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, + 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, + 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, + 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, + 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, + 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, + 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, + 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, + 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, + 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, + 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, + 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, + 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, + 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, + 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, + 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8, + 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, + 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, + 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, + 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, + 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, + 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, + 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, + 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, + 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, + 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, + 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, + 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, + 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, + 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, + 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, + 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a + ], + [ + 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, + 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, + 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, + 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, + 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, + 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, + 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, + 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, + 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, + 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, + 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, + 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, + 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, + 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, + 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, + 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, + 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, + 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, + 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, + 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, + 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, + 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, + 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, + 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, + 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, + 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, + 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, + 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, + 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, + 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, + 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, + 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, + 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, + 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, + 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, + 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, + 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, + 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, + 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, + 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, + 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, + 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, + 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7 + ], + [ + 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, + 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, + 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, + 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, + 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, + 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, + 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, + 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, + 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, + 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, + 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, + 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, + 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, + 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, + 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, + 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, + 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, + 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, + 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74, + 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, + 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, + 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, + 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, + 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, + 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, + 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, + 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, + 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, + 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, + 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, + 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, + 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, + 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, + 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, + 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, + 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, + 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, + 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, + 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, + 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, + 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, + 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, + 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0 + ], + [ + 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, + 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, + 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, + 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, + 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, + 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, + 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, + 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, + 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, + 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, + 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, + 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, + 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, + 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, + 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5, + 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, + 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, + 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, + 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd, + 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, + 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, + 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, + 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc, + 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, + 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, + 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, + 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, + 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, + 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, + 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, + 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, + 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, + 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, + 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, + 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623, + 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, + 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, + 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, + 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3, + 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, + 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, + 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, + 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 + ] +]; + +//* +//* This is the default PARRAY +//* +Blowfish.prototype.PARRAY = [ + 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, + 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, + 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b +]; + +//* +//* This is the number of rounds the cipher will go +//* +Blowfish.prototype.NN = 16; + +//* +//* This function is needed to get rid of problems +//* with the high-bit getting set. If we don't do +//* this, then sometimes ( aa & 0x00FFFFFFFF ) is not +//* equal to ( bb & 0x00FFFFFFFF ) even when they +//* agree bit-for-bit for the first 32 bits. +//* +Blowfish.prototype._clean = function(xx) { + if (xx < 0) { + const yy = xx & 0x7FFFFFFF; + xx = yy + 0x80000000; + } + return xx; +}; + +//* +//* This is the mixing function that uses the sboxes +//* +Blowfish.prototype._F = function(xx) { + let yy; + + const dd = xx & 0x00FF; + xx >>>= 8; + const cc = xx & 0x00FF; + xx >>>= 8; + const bb = xx & 0x00FF; + xx >>>= 8; + const aa = xx & 0x00FF; + + yy = this.sboxes[0][aa] + this.sboxes[1][bb]; + yy ^= this.sboxes[2][cc]; + yy += this.sboxes[3][dd]; + + return yy; +}; + +//* +//* This method takes an array with two values, left and right +//* and does NN rounds of Blowfish on them. +//* +Blowfish.prototype._encryptBlock = function(vals) { + let dataL = vals[0]; + let dataR = vals[1]; + + let ii; + + for (ii = 0; ii < this.NN; ++ii) { + dataL ^= this.parray[ii]; + dataR = this._F(dataL) ^ dataR; + + const tmp = dataL; + dataL = dataR; + dataR = tmp; + } + + dataL ^= this.parray[this.NN + 0]; + dataR ^= this.parray[this.NN + 1]; + + vals[0] = this._clean(dataR); + vals[1] = this._clean(dataL); +}; + +//* +//* This method takes a vector of numbers and turns them +//* into long words so that they can be processed by the +//* real algorithm. +//* +//* Maybe I should make the real algorithm above take a vector +//* instead. That will involve more looping, but it won't require +//* the F() method to deconstruct the vector. +//* +Blowfish.prototype.encryptBlock = function(vector) { + let ii; + const vals = [0, 0]; + const off = this.BLOCKSIZE / 2; + for (ii = 0; ii < this.BLOCKSIZE / 2; ++ii) { + vals[0] = (vals[0] << 8) | (vector[ii + 0] & 0x00FF); + vals[1] = (vals[1] << 8) | (vector[ii + off] & 0x00FF); + } + + this._encryptBlock(vals); + + const ret = []; + for (ii = 0; ii < this.BLOCKSIZE / 2; ++ii) { + ret[ii + 0] = ((vals[0] >>> (24 - 8 * (ii))) & 0x00FF); + ret[ii + off] = ((vals[1] >>> (24 - 8 * (ii))) & 0x00FF); + // vals[ 0 ] = ( vals[ 0 ] >>> 8 ); + // vals[ 1 ] = ( vals[ 1 ] >>> 8 ); + } + + return ret; +}; + +//* +//* This method takes an array with two values, left and right +//* and undoes NN rounds of Blowfish on them. +//* +Blowfish.prototype._decryptBlock = function(vals) { + let dataL = vals[0]; + let dataR = vals[1]; + + let ii; + + for (ii = this.NN + 1; ii > 1; --ii) { + dataL ^= this.parray[ii]; + dataR = this._F(dataL) ^ dataR; + + const tmp = dataL; + dataL = dataR; + dataR = tmp; + } + + dataL ^= this.parray[1]; + dataR ^= this.parray[0]; + + vals[0] = this._clean(dataR); + vals[1] = this._clean(dataL); +}; + +//* +//* This method takes a key array and initializes the +//* sboxes and parray for this encryption. +//* +Blowfish.prototype.init = function(key) { + let ii; + let jj = 0; + + this.parray = []; + for (ii = 0; ii < this.NN + 2; ++ii) { + let data = 0x00000000; + for (let kk = 0; kk < 4; ++kk) { + data = (data << 8) | (key[jj] & 0x00FF); + if (++jj >= key.length) { + jj = 0; + } + } + this.parray[ii] = this.PARRAY[ii] ^ data; + } + + this.sboxes = []; + for (ii = 0; ii < 4; ++ii) { + this.sboxes[ii] = []; + for (jj = 0; jj < 256; ++jj) { + this.sboxes[ii][jj] = this.SBOXES[ii][jj]; + } + } + + const vals = [0x00000000, 0x00000000]; + + for (ii = 0; ii < this.NN + 2; ii += 2) { + this._encryptBlock(vals); + this.parray[ii + 0] = vals[0]; + this.parray[ii + 1] = vals[1]; + } + + for (ii = 0; ii < 4; ++ii) { + for (jj = 0; jj < 256; jj += 2) { + this._encryptBlock(vals); + this.sboxes[ii][jj + 0] = vals[0]; + this.sboxes[ii][jj + 1] = vals[1]; + } + } +}; + +// added by Recurity Labs +function BF(key) { + this.bf = new Blowfish(); + this.bf.init(key); + + this.encrypt = function(block) { + return this.bf.encryptBlock(block); + }; +} + +BF.keySize = BF.prototype.keySize = 16; +BF.blockSize = BF.prototype.blockSize = 8; + +/** + * @fileoverview Symmetric cryptography functions + * @module crypto/cipher + * @private + */ + +/** + * AES-128 encryption and decryption (ID 7) + * @function + * @param {String} key - 128-bit key + * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} + * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} + * @returns {Object} + */ +const aes128 = aes(128); +/** + * AES-128 Block Cipher (ID 8) + * @function + * @param {String} key - 192-bit key + * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} + * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} + * @returns {Object} + */ +const aes192 = aes(192); +/** + * AES-128 Block Cipher (ID 9) + * @function + * @param {String} key - 256-bit key + * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} + * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} + * @returns {Object} + */ +const aes256 = aes(256); +// Not in OpenPGP specifications +const des$1 = DES; +/** + * Triple DES Block Cipher (ID 2) + * @function + * @param {String} key - 192-bit key + * @see {@link https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-67r2.pdf|NIST SP 800-67} + * @returns {Object} + */ +const tripledes = TripleDES; +/** + * CAST-128 Block Cipher (ID 3) + * @function + * @param {String} key - 128-bit key + * @see {@link https://tools.ietf.org/html/rfc2144|The CAST-128 Encryption Algorithm} + * @returns {Object} + */ +const cast5 = CAST5; +/** + * Twofish Block Cipher (ID 10) + * @function + * @param {String} key - 256-bit key + * @see {@link https://tools.ietf.org/html/rfc4880#ref-TWOFISH|TWOFISH} + * @returns {Object} + */ +const twofish = TF; +/** + * Blowfish Block Cipher (ID 4) + * @function + * @param {String} key - 128-bit key + * @see {@link https://tools.ietf.org/html/rfc4880#ref-BLOWFISH|BLOWFISH} + * @returns {Object} + */ +const blowfish = BF; +/** + * Not implemented + * @function + * @throws {Error} + */ +const idea = function() { + throw new Error('IDEA symmetric-key algorithm not implemented'); +}; + +var cipher = /*#__PURE__*/Object.freeze({ + __proto__: null, + aes128: aes128, + aes192: aes192, + aes256: aes256, + des: des$1, + tripledes: tripledes, + cast5: cast5, + twofish: twofish, + blowfish: blowfish, + idea: idea +}); + +var sha1_asm = function ( stdlib, foreign, buffer ) { + "use asm"; + + // SHA256 state + var H0 = 0, H1 = 0, H2 = 0, H3 = 0, H4 = 0, + TOTAL0 = 0, TOTAL1 = 0; + + // HMAC state + var I0 = 0, I1 = 0, I2 = 0, I3 = 0, I4 = 0, + O0 = 0, O1 = 0, O2 = 0, O3 = 0, O4 = 0; + + // I/O buffer + var HEAP = new stdlib.Uint8Array(buffer); + + function _core ( w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15 ) { + w0 = w0|0; + w1 = w1|0; + w2 = w2|0; + w3 = w3|0; + w4 = w4|0; + w5 = w5|0; + w6 = w6|0; + w7 = w7|0; + w8 = w8|0; + w9 = w9|0; + w10 = w10|0; + w11 = w11|0; + w12 = w12|0; + w13 = w13|0; + w14 = w14|0; + w15 = w15|0; + + var a = 0, b = 0, c = 0, d = 0, e = 0, n = 0, t = 0, + w16 = 0, w17 = 0, w18 = 0, w19 = 0, + w20 = 0, w21 = 0, w22 = 0, w23 = 0, w24 = 0, w25 = 0, w26 = 0, w27 = 0, w28 = 0, w29 = 0, + w30 = 0, w31 = 0, w32 = 0, w33 = 0, w34 = 0, w35 = 0, w36 = 0, w37 = 0, w38 = 0, w39 = 0, + w40 = 0, w41 = 0, w42 = 0, w43 = 0, w44 = 0, w45 = 0, w46 = 0, w47 = 0, w48 = 0, w49 = 0, + w50 = 0, w51 = 0, w52 = 0, w53 = 0, w54 = 0, w55 = 0, w56 = 0, w57 = 0, w58 = 0, w59 = 0, + w60 = 0, w61 = 0, w62 = 0, w63 = 0, w64 = 0, w65 = 0, w66 = 0, w67 = 0, w68 = 0, w69 = 0, + w70 = 0, w71 = 0, w72 = 0, w73 = 0, w74 = 0, w75 = 0, w76 = 0, w77 = 0, w78 = 0, w79 = 0; + + a = H0; + b = H1; + c = H2; + d = H3; + e = H4; + + // 0 + t = ( w0 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 1 + t = ( w1 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 2 + t = ( w2 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 3 + t = ( w3 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 4 + t = ( w4 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 5 + t = ( w5 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 6 + t = ( w6 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 7 + t = ( w7 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 8 + t = ( w8 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 9 + t = ( w9 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 10 + t = ( w10 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 11 + t = ( w11 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 12 + t = ( w12 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 13 + t = ( w13 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 14 + t = ( w14 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 15 + t = ( w15 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 16 + n = w13 ^ w8 ^ w2 ^ w0; + w16 = (n << 1) | (n >>> 31); + t = (w16 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 17 + n = w14 ^ w9 ^ w3 ^ w1; + w17 = (n << 1) | (n >>> 31); + t = (w17 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 18 + n = w15 ^ w10 ^ w4 ^ w2; + w18 = (n << 1) | (n >>> 31); + t = (w18 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 19 + n = w16 ^ w11 ^ w5 ^ w3; + w19 = (n << 1) | (n >>> 31); + t = (w19 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 20 + n = w17 ^ w12 ^ w6 ^ w4; + w20 = (n << 1) | (n >>> 31); + t = (w20 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 21 + n = w18 ^ w13 ^ w7 ^ w5; + w21 = (n << 1) | (n >>> 31); + t = (w21 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 22 + n = w19 ^ w14 ^ w8 ^ w6; + w22 = (n << 1) | (n >>> 31); + t = (w22 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 23 + n = w20 ^ w15 ^ w9 ^ w7; + w23 = (n << 1) | (n >>> 31); + t = (w23 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 24 + n = w21 ^ w16 ^ w10 ^ w8; + w24 = (n << 1) | (n >>> 31); + t = (w24 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 25 + n = w22 ^ w17 ^ w11 ^ w9; + w25 = (n << 1) | (n >>> 31); + t = (w25 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 26 + n = w23 ^ w18 ^ w12 ^ w10; + w26 = (n << 1) | (n >>> 31); + t = (w26 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 27 + n = w24 ^ w19 ^ w13 ^ w11; + w27 = (n << 1) | (n >>> 31); + t = (w27 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 28 + n = w25 ^ w20 ^ w14 ^ w12; + w28 = (n << 1) | (n >>> 31); + t = (w28 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 29 + n = w26 ^ w21 ^ w15 ^ w13; + w29 = (n << 1) | (n >>> 31); + t = (w29 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 30 + n = w27 ^ w22 ^ w16 ^ w14; + w30 = (n << 1) | (n >>> 31); + t = (w30 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 31 + n = w28 ^ w23 ^ w17 ^ w15; + w31 = (n << 1) | (n >>> 31); + t = (w31 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 32 + n = w29 ^ w24 ^ w18 ^ w16; + w32 = (n << 1) | (n >>> 31); + t = (w32 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 33 + n = w30 ^ w25 ^ w19 ^ w17; + w33 = (n << 1) | (n >>> 31); + t = (w33 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 34 + n = w31 ^ w26 ^ w20 ^ w18; + w34 = (n << 1) | (n >>> 31); + t = (w34 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 35 + n = w32 ^ w27 ^ w21 ^ w19; + w35 = (n << 1) | (n >>> 31); + t = (w35 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 36 + n = w33 ^ w28 ^ w22 ^ w20; + w36 = (n << 1) | (n >>> 31); + t = (w36 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 37 + n = w34 ^ w29 ^ w23 ^ w21; + w37 = (n << 1) | (n >>> 31); + t = (w37 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 38 + n = w35 ^ w30 ^ w24 ^ w22; + w38 = (n << 1) | (n >>> 31); + t = (w38 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 39 + n = w36 ^ w31 ^ w25 ^ w23; + w39 = (n << 1) | (n >>> 31); + t = (w39 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 40 + n = w37 ^ w32 ^ w26 ^ w24; + w40 = (n << 1) | (n >>> 31); + t = (w40 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 41 + n = w38 ^ w33 ^ w27 ^ w25; + w41 = (n << 1) | (n >>> 31); + t = (w41 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 42 + n = w39 ^ w34 ^ w28 ^ w26; + w42 = (n << 1) | (n >>> 31); + t = (w42 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 43 + n = w40 ^ w35 ^ w29 ^ w27; + w43 = (n << 1) | (n >>> 31); + t = (w43 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 44 + n = w41 ^ w36 ^ w30 ^ w28; + w44 = (n << 1) | (n >>> 31); + t = (w44 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 45 + n = w42 ^ w37 ^ w31 ^ w29; + w45 = (n << 1) | (n >>> 31); + t = (w45 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 46 + n = w43 ^ w38 ^ w32 ^ w30; + w46 = (n << 1) | (n >>> 31); + t = (w46 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 47 + n = w44 ^ w39 ^ w33 ^ w31; + w47 = (n << 1) | (n >>> 31); + t = (w47 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 48 + n = w45 ^ w40 ^ w34 ^ w32; + w48 = (n << 1) | (n >>> 31); + t = (w48 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 49 + n = w46 ^ w41 ^ w35 ^ w33; + w49 = (n << 1) | (n >>> 31); + t = (w49 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 50 + n = w47 ^ w42 ^ w36 ^ w34; + w50 = (n << 1) | (n >>> 31); + t = (w50 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 51 + n = w48 ^ w43 ^ w37 ^ w35; + w51 = (n << 1) | (n >>> 31); + t = (w51 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 52 + n = w49 ^ w44 ^ w38 ^ w36; + w52 = (n << 1) | (n >>> 31); + t = (w52 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 53 + n = w50 ^ w45 ^ w39 ^ w37; + w53 = (n << 1) | (n >>> 31); + t = (w53 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 54 + n = w51 ^ w46 ^ w40 ^ w38; + w54 = (n << 1) | (n >>> 31); + t = (w54 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 55 + n = w52 ^ w47 ^ w41 ^ w39; + w55 = (n << 1) | (n >>> 31); + t = (w55 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 56 + n = w53 ^ w48 ^ w42 ^ w40; + w56 = (n << 1) | (n >>> 31); + t = (w56 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 57 + n = w54 ^ w49 ^ w43 ^ w41; + w57 = (n << 1) | (n >>> 31); + t = (w57 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 58 + n = w55 ^ w50 ^ w44 ^ w42; + w58 = (n << 1) | (n >>> 31); + t = (w58 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 59 + n = w56 ^ w51 ^ w45 ^ w43; + w59 = (n << 1) | (n >>> 31); + t = (w59 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 60 + n = w57 ^ w52 ^ w46 ^ w44; + w60 = (n << 1) | (n >>> 31); + t = (w60 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 61 + n = w58 ^ w53 ^ w47 ^ w45; + w61 = (n << 1) | (n >>> 31); + t = (w61 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 62 + n = w59 ^ w54 ^ w48 ^ w46; + w62 = (n << 1) | (n >>> 31); + t = (w62 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 63 + n = w60 ^ w55 ^ w49 ^ w47; + w63 = (n << 1) | (n >>> 31); + t = (w63 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 64 + n = w61 ^ w56 ^ w50 ^ w48; + w64 = (n << 1) | (n >>> 31); + t = (w64 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 65 + n = w62 ^ w57 ^ w51 ^ w49; + w65 = (n << 1) | (n >>> 31); + t = (w65 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 66 + n = w63 ^ w58 ^ w52 ^ w50; + w66 = (n << 1) | (n >>> 31); + t = (w66 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 67 + n = w64 ^ w59 ^ w53 ^ w51; + w67 = (n << 1) | (n >>> 31); + t = (w67 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 68 + n = w65 ^ w60 ^ w54 ^ w52; + w68 = (n << 1) | (n >>> 31); + t = (w68 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 69 + n = w66 ^ w61 ^ w55 ^ w53; + w69 = (n << 1) | (n >>> 31); + t = (w69 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 70 + n = w67 ^ w62 ^ w56 ^ w54; + w70 = (n << 1) | (n >>> 31); + t = (w70 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 71 + n = w68 ^ w63 ^ w57 ^ w55; + w71 = (n << 1) | (n >>> 31); + t = (w71 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 72 + n = w69 ^ w64 ^ w58 ^ w56; + w72 = (n << 1) | (n >>> 31); + t = (w72 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 73 + n = w70 ^ w65 ^ w59 ^ w57; + w73 = (n << 1) | (n >>> 31); + t = (w73 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 74 + n = w71 ^ w66 ^ w60 ^ w58; + w74 = (n << 1) | (n >>> 31); + t = (w74 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 75 + n = w72 ^ w67 ^ w61 ^ w59; + w75 = (n << 1) | (n >>> 31); + t = (w75 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 76 + n = w73 ^ w68 ^ w62 ^ w60; + w76 = (n << 1) | (n >>> 31); + t = (w76 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 77 + n = w74 ^ w69 ^ w63 ^ w61; + w77 = (n << 1) | (n >>> 31); + t = (w77 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 78 + n = w75 ^ w70 ^ w64 ^ w62; + w78 = (n << 1) | (n >>> 31); + t = (w78 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 79 + n = w76 ^ w71 ^ w65 ^ w63; + w79 = (n << 1) | (n >>> 31); + t = (w79 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + H0 = ( H0 + a )|0; + H1 = ( H1 + b )|0; + H2 = ( H2 + c )|0; + H3 = ( H3 + d )|0; + H4 = ( H4 + e )|0; + + } + + function _core_heap ( offset ) { + offset = offset|0; + + _core( + HEAP[offset|0]<<24 | HEAP[offset|1]<<16 | HEAP[offset|2]<<8 | HEAP[offset|3], + HEAP[offset|4]<<24 | HEAP[offset|5]<<16 | HEAP[offset|6]<<8 | HEAP[offset|7], + HEAP[offset|8]<<24 | HEAP[offset|9]<<16 | HEAP[offset|10]<<8 | HEAP[offset|11], + HEAP[offset|12]<<24 | HEAP[offset|13]<<16 | HEAP[offset|14]<<8 | HEAP[offset|15], + HEAP[offset|16]<<24 | HEAP[offset|17]<<16 | HEAP[offset|18]<<8 | HEAP[offset|19], + HEAP[offset|20]<<24 | HEAP[offset|21]<<16 | HEAP[offset|22]<<8 | HEAP[offset|23], + HEAP[offset|24]<<24 | HEAP[offset|25]<<16 | HEAP[offset|26]<<8 | HEAP[offset|27], + HEAP[offset|28]<<24 | HEAP[offset|29]<<16 | HEAP[offset|30]<<8 | HEAP[offset|31], + HEAP[offset|32]<<24 | HEAP[offset|33]<<16 | HEAP[offset|34]<<8 | HEAP[offset|35], + HEAP[offset|36]<<24 | HEAP[offset|37]<<16 | HEAP[offset|38]<<8 | HEAP[offset|39], + HEAP[offset|40]<<24 | HEAP[offset|41]<<16 | HEAP[offset|42]<<8 | HEAP[offset|43], + HEAP[offset|44]<<24 | HEAP[offset|45]<<16 | HEAP[offset|46]<<8 | HEAP[offset|47], + HEAP[offset|48]<<24 | HEAP[offset|49]<<16 | HEAP[offset|50]<<8 | HEAP[offset|51], + HEAP[offset|52]<<24 | HEAP[offset|53]<<16 | HEAP[offset|54]<<8 | HEAP[offset|55], + HEAP[offset|56]<<24 | HEAP[offset|57]<<16 | HEAP[offset|58]<<8 | HEAP[offset|59], + HEAP[offset|60]<<24 | HEAP[offset|61]<<16 | HEAP[offset|62]<<8 | HEAP[offset|63] + ); + } + + // offset — multiple of 32 + function _state_to_heap ( output ) { + output = output|0; + + HEAP[output|0] = H0>>>24; + HEAP[output|1] = H0>>>16&255; + HEAP[output|2] = H0>>>8&255; + HEAP[output|3] = H0&255; + HEAP[output|4] = H1>>>24; + HEAP[output|5] = H1>>>16&255; + HEAP[output|6] = H1>>>8&255; + HEAP[output|7] = H1&255; + HEAP[output|8] = H2>>>24; + HEAP[output|9] = H2>>>16&255; + HEAP[output|10] = H2>>>8&255; + HEAP[output|11] = H2&255; + HEAP[output|12] = H3>>>24; + HEAP[output|13] = H3>>>16&255; + HEAP[output|14] = H3>>>8&255; + HEAP[output|15] = H3&255; + HEAP[output|16] = H4>>>24; + HEAP[output|17] = H4>>>16&255; + HEAP[output|18] = H4>>>8&255; + HEAP[output|19] = H4&255; + } + + function reset () { + H0 = 0x67452301; + H1 = 0xefcdab89; + H2 = 0x98badcfe; + H3 = 0x10325476; + H4 = 0xc3d2e1f0; + TOTAL0 = TOTAL1 = 0; + } + + function init ( h0, h1, h2, h3, h4, total0, total1 ) { + h0 = h0|0; + h1 = h1|0; + h2 = h2|0; + h3 = h3|0; + h4 = h4|0; + total0 = total0|0; + total1 = total1|0; + + H0 = h0; + H1 = h1; + H2 = h2; + H3 = h3; + H4 = h4; + TOTAL0 = total0; + TOTAL1 = total1; + } + + // offset — multiple of 64 + function process ( offset, length ) { + offset = offset|0; + length = length|0; + + var hashed = 0; + + if ( offset & 63 ) + return -1; + + while ( (length|0) >= 64 ) { + _core_heap(offset); + + offset = ( offset + 64 )|0; + length = ( length - 64 )|0; + + hashed = ( hashed + 64 )|0; + } + + TOTAL0 = ( TOTAL0 + hashed )|0; + if ( TOTAL0>>>0 < hashed>>>0 ) TOTAL1 = ( TOTAL1 + 1 )|0; + + return hashed|0; + } + + // offset — multiple of 64 + // output — multiple of 32 + function finish ( offset, length, output ) { + offset = offset|0; + length = length|0; + output = output|0; + + var hashed = 0, + i = 0; + + if ( offset & 63 ) + return -1; + + if ( ~output ) + if ( output & 31 ) + return -1; + + if ( (length|0) >= 64 ) { + hashed = process( offset, length )|0; + if ( (hashed|0) == -1 ) + return -1; + + offset = ( offset + hashed )|0; + length = ( length - hashed )|0; + } + + hashed = ( hashed + length )|0; + TOTAL0 = ( TOTAL0 + length )|0; + if ( TOTAL0>>>0 < length>>>0 ) TOTAL1 = (TOTAL1 + 1)|0; + + HEAP[offset|length] = 0x80; + + if ( (length|0) >= 56 ) { + for ( i = (length+1)|0; (i|0) < 64; i = (i+1)|0 ) + HEAP[offset|i] = 0x00; + _core_heap(offset); + + length = 0; + + HEAP[offset|0] = 0; + } + + for ( i = (length+1)|0; (i|0) < 59; i = (i+1)|0 ) + HEAP[offset|i] = 0; + + HEAP[offset|56] = TOTAL1>>>21&255; + HEAP[offset|57] = TOTAL1>>>13&255; + HEAP[offset|58] = TOTAL1>>>5&255; + HEAP[offset|59] = TOTAL1<<3&255 | TOTAL0>>>29; + HEAP[offset|60] = TOTAL0>>>21&255; + HEAP[offset|61] = TOTAL0>>>13&255; + HEAP[offset|62] = TOTAL0>>>5&255; + HEAP[offset|63] = TOTAL0<<3&255; + _core_heap(offset); + + if ( ~output ) + _state_to_heap(output); + + return hashed|0; + } + + function hmac_reset () { + H0 = I0; + H1 = I1; + H2 = I2; + H3 = I3; + H4 = I4; + TOTAL0 = 64; + TOTAL1 = 0; + } + + function _hmac_opad () { + H0 = O0; + H1 = O1; + H2 = O2; + H3 = O3; + H4 = O4; + TOTAL0 = 64; + TOTAL1 = 0; + } + + function hmac_init ( p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15 ) { + p0 = p0|0; + p1 = p1|0; + p2 = p2|0; + p3 = p3|0; + p4 = p4|0; + p5 = p5|0; + p6 = p6|0; + p7 = p7|0; + p8 = p8|0; + p9 = p9|0; + p10 = p10|0; + p11 = p11|0; + p12 = p12|0; + p13 = p13|0; + p14 = p14|0; + p15 = p15|0; + + // opad + reset(); + _core( + p0 ^ 0x5c5c5c5c, + p1 ^ 0x5c5c5c5c, + p2 ^ 0x5c5c5c5c, + p3 ^ 0x5c5c5c5c, + p4 ^ 0x5c5c5c5c, + p5 ^ 0x5c5c5c5c, + p6 ^ 0x5c5c5c5c, + p7 ^ 0x5c5c5c5c, + p8 ^ 0x5c5c5c5c, + p9 ^ 0x5c5c5c5c, + p10 ^ 0x5c5c5c5c, + p11 ^ 0x5c5c5c5c, + p12 ^ 0x5c5c5c5c, + p13 ^ 0x5c5c5c5c, + p14 ^ 0x5c5c5c5c, + p15 ^ 0x5c5c5c5c + ); + O0 = H0; + O1 = H1; + O2 = H2; + O3 = H3; + O4 = H4; + + // ipad + reset(); + _core( + p0 ^ 0x36363636, + p1 ^ 0x36363636, + p2 ^ 0x36363636, + p3 ^ 0x36363636, + p4 ^ 0x36363636, + p5 ^ 0x36363636, + p6 ^ 0x36363636, + p7 ^ 0x36363636, + p8 ^ 0x36363636, + p9 ^ 0x36363636, + p10 ^ 0x36363636, + p11 ^ 0x36363636, + p12 ^ 0x36363636, + p13 ^ 0x36363636, + p14 ^ 0x36363636, + p15 ^ 0x36363636 + ); + I0 = H0; + I1 = H1; + I2 = H2; + I3 = H3; + I4 = H4; + + TOTAL0 = 64; + TOTAL1 = 0; + } + + // offset — multiple of 64 + // output — multiple of 32 + function hmac_finish ( offset, length, output ) { + offset = offset|0; + length = length|0; + output = output|0; + + var t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, hashed = 0; + + if ( offset & 63 ) + return -1; + + if ( ~output ) + if ( output & 31 ) + return -1; + + hashed = finish( offset, length, -1 )|0; + t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; + + _hmac_opad(); + _core( t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672 ); + + if ( ~output ) + _state_to_heap(output); + + return hashed|0; + } + + // salt is assumed to be already processed + // offset — multiple of 64 + // output — multiple of 32 + function pbkdf2_generate_block ( offset, length, block, count, output ) { + offset = offset|0; + length = length|0; + block = block|0; + count = count|0; + output = output|0; + + var h0 = 0, h1 = 0, h2 = 0, h3 = 0, h4 = 0, + t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0; + + if ( offset & 63 ) + return -1; + + if ( ~output ) + if ( output & 31 ) + return -1; + + // pad block number into heap + // FIXME probable OOB write + HEAP[(offset+length)|0] = block>>>24; + HEAP[(offset+length+1)|0] = block>>>16&255; + HEAP[(offset+length+2)|0] = block>>>8&255; + HEAP[(offset+length+3)|0] = block&255; + + // finish first iteration + hmac_finish( offset, (length+4)|0, -1 )|0; + h0 = t0 = H0, h1 = t1 = H1, h2 = t2 = H2, h3 = t3 = H3, h4 = t4 = H4; + count = (count-1)|0; + + // perform the rest iterations + while ( (count|0) > 0 ) { + hmac_reset(); + _core( t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672 ); + t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; + + _hmac_opad(); + _core( t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672 ); + t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; + + h0 = h0 ^ H0; + h1 = h1 ^ H1; + h2 = h2 ^ H2; + h3 = h3 ^ H3; + h4 = h4 ^ H4; + + count = (count-1)|0; + } + + H0 = h0; + H1 = h1; + H2 = h2; + H3 = h3; + H4 = h4; + + if ( ~output ) + _state_to_heap(output); + + return 0; + } + + return { + // SHA1 + reset: reset, + init: init, + process: process, + finish: finish, + + // HMAC-SHA1 + hmac_reset: hmac_reset, + hmac_init: hmac_init, + hmac_finish: hmac_finish, + + // PBKDF2-HMAC-SHA1 + pbkdf2_generate_block: pbkdf2_generate_block + } +}; + +class Hash { + constructor() { + this.pos = 0; + this.len = 0; + } + reset() { + const { asm } = this.acquire_asm(); + this.result = null; + this.pos = 0; + this.len = 0; + asm.reset(); + return this; + } + process(data) { + if (this.result !== null) + throw new IllegalStateError('state must be reset before processing new data'); + const { asm, heap } = this.acquire_asm(); + let hpos = this.pos; + let hlen = this.len; + let dpos = 0; + let dlen = data.length; + let wlen = 0; + while (dlen > 0) { + wlen = _heap_write(heap, hpos + hlen, data, dpos, dlen); + hlen += wlen; + dpos += wlen; + dlen -= wlen; + wlen = asm.process(hpos, hlen); + hpos += wlen; + hlen -= wlen; + if (!hlen) + hpos = 0; + } + this.pos = hpos; + this.len = hlen; + return this; + } + finish() { + if (this.result !== null) + throw new IllegalStateError('state must be reset before processing new data'); + const { asm, heap } = this.acquire_asm(); + asm.finish(this.pos, this.len, 0); + this.result = new Uint8Array(this.HASH_SIZE); + this.result.set(heap.subarray(0, this.HASH_SIZE)); + this.pos = 0; + this.len = 0; + this.release_asm(); + return this; + } +} + +const _sha1_block_size = 64; +const _sha1_hash_size = 20; +const heap_pool$1 = []; +const asm_pool$1 = []; +class Sha1 extends Hash { + constructor() { + super(); + this.NAME = 'sha1'; + this.BLOCK_SIZE = _sha1_block_size; + this.HASH_SIZE = _sha1_hash_size; + this.acquire_asm(); + } + acquire_asm() { + if (this.heap === undefined || this.asm === undefined) { + this.heap = heap_pool$1.pop() || _heap_init(); + this.asm = asm_pool$1.pop() || sha1_asm({ Uint8Array: Uint8Array }, null, this.heap.buffer); + this.reset(); + } + return { heap: this.heap, asm: this.asm }; + } + release_asm() { + if (this.heap !== undefined && this.asm !== undefined) { + heap_pool$1.push(this.heap); + asm_pool$1.push(this.asm); + } + this.heap = undefined; + this.asm = undefined; + } + static bytes(data) { + return new Sha1().process(data).finish().result; + } +} +Sha1.NAME = 'sha1'; +Sha1.heap_pool = []; +Sha1.asm_pool = []; +Sha1.asm_function = sha1_asm; + +var sha256_asm = function ( stdlib, foreign, buffer ) { + "use asm"; + + // SHA256 state + var H0 = 0, H1 = 0, H2 = 0, H3 = 0, H4 = 0, H5 = 0, H6 = 0, H7 = 0, + TOTAL0 = 0, TOTAL1 = 0; + + // HMAC state + var I0 = 0, I1 = 0, I2 = 0, I3 = 0, I4 = 0, I5 = 0, I6 = 0, I7 = 0, + O0 = 0, O1 = 0, O2 = 0, O3 = 0, O4 = 0, O5 = 0, O6 = 0, O7 = 0; + + // I/O buffer + var HEAP = new stdlib.Uint8Array(buffer); + + function _core ( w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15 ) { + w0 = w0|0; + w1 = w1|0; + w2 = w2|0; + w3 = w3|0; + w4 = w4|0; + w5 = w5|0; + w6 = w6|0; + w7 = w7|0; + w8 = w8|0; + w9 = w9|0; + w10 = w10|0; + w11 = w11|0; + w12 = w12|0; + w13 = w13|0; + w14 = w14|0; + w15 = w15|0; + + var a = 0, b = 0, c = 0, d = 0, e = 0, f = 0, g = 0, h = 0; + + a = H0; + b = H1; + c = H2; + d = H3; + e = H4; + f = H5; + g = H6; + h = H7; + + // 0 + h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x428a2f98 )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; + + // 1 + g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x71374491 )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; + + // 2 + f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0xb5c0fbcf )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; + + // 3 + e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0xe9b5dba5 )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; + + // 4 + d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x3956c25b )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; + + // 5 + c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x59f111f1 )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; + + // 6 + b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x923f82a4 )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; + + // 7 + a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0xab1c5ed5 )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; + + // 8 + h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0xd807aa98 )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; + + // 9 + g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x12835b01 )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; + + // 10 + f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x243185be )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; + + // 11 + e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x550c7dc3 )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; + + // 12 + d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x72be5d74 )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; + + // 13 + c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x80deb1fe )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; + + // 14 + b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x9bdc06a7 )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; + + // 15 + a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0xc19bf174 )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; + + // 16 + w0 = ( ( w1>>>7 ^ w1>>>18 ^ w1>>>3 ^ w1<<25 ^ w1<<14 ) + ( w14>>>17 ^ w14>>>19 ^ w14>>>10 ^ w14<<15 ^ w14<<13 ) + w0 + w9 )|0; + h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0xe49b69c1 )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; + + // 17 + w1 = ( ( w2>>>7 ^ w2>>>18 ^ w2>>>3 ^ w2<<25 ^ w2<<14 ) + ( w15>>>17 ^ w15>>>19 ^ w15>>>10 ^ w15<<15 ^ w15<<13 ) + w1 + w10 )|0; + g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0xefbe4786 )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; + + // 18 + w2 = ( ( w3>>>7 ^ w3>>>18 ^ w3>>>3 ^ w3<<25 ^ w3<<14 ) + ( w0>>>17 ^ w0>>>19 ^ w0>>>10 ^ w0<<15 ^ w0<<13 ) + w2 + w11 )|0; + f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x0fc19dc6 )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; + + // 19 + w3 = ( ( w4>>>7 ^ w4>>>18 ^ w4>>>3 ^ w4<<25 ^ w4<<14 ) + ( w1>>>17 ^ w1>>>19 ^ w1>>>10 ^ w1<<15 ^ w1<<13 ) + w3 + w12 )|0; + e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x240ca1cc )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; + + // 20 + w4 = ( ( w5>>>7 ^ w5>>>18 ^ w5>>>3 ^ w5<<25 ^ w5<<14 ) + ( w2>>>17 ^ w2>>>19 ^ w2>>>10 ^ w2<<15 ^ w2<<13 ) + w4 + w13 )|0; + d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x2de92c6f )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; + + // 21 + w5 = ( ( w6>>>7 ^ w6>>>18 ^ w6>>>3 ^ w6<<25 ^ w6<<14 ) + ( w3>>>17 ^ w3>>>19 ^ w3>>>10 ^ w3<<15 ^ w3<<13 ) + w5 + w14 )|0; + c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x4a7484aa )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; + + // 22 + w6 = ( ( w7>>>7 ^ w7>>>18 ^ w7>>>3 ^ w7<<25 ^ w7<<14 ) + ( w4>>>17 ^ w4>>>19 ^ w4>>>10 ^ w4<<15 ^ w4<<13 ) + w6 + w15 )|0; + b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x5cb0a9dc )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; + + // 23 + w7 = ( ( w8>>>7 ^ w8>>>18 ^ w8>>>3 ^ w8<<25 ^ w8<<14 ) + ( w5>>>17 ^ w5>>>19 ^ w5>>>10 ^ w5<<15 ^ w5<<13 ) + w7 + w0 )|0; + a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x76f988da )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; + + // 24 + w8 = ( ( w9>>>7 ^ w9>>>18 ^ w9>>>3 ^ w9<<25 ^ w9<<14 ) + ( w6>>>17 ^ w6>>>19 ^ w6>>>10 ^ w6<<15 ^ w6<<13 ) + w8 + w1 )|0; + h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x983e5152 )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; + + // 25 + w9 = ( ( w10>>>7 ^ w10>>>18 ^ w10>>>3 ^ w10<<25 ^ w10<<14 ) + ( w7>>>17 ^ w7>>>19 ^ w7>>>10 ^ w7<<15 ^ w7<<13 ) + w9 + w2 )|0; + g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0xa831c66d )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; + + // 26 + w10 = ( ( w11>>>7 ^ w11>>>18 ^ w11>>>3 ^ w11<<25 ^ w11<<14 ) + ( w8>>>17 ^ w8>>>19 ^ w8>>>10 ^ w8<<15 ^ w8<<13 ) + w10 + w3 )|0; + f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0xb00327c8 )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; + + // 27 + w11 = ( ( w12>>>7 ^ w12>>>18 ^ w12>>>3 ^ w12<<25 ^ w12<<14 ) + ( w9>>>17 ^ w9>>>19 ^ w9>>>10 ^ w9<<15 ^ w9<<13 ) + w11 + w4 )|0; + e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0xbf597fc7 )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; + + // 28 + w12 = ( ( w13>>>7 ^ w13>>>18 ^ w13>>>3 ^ w13<<25 ^ w13<<14 ) + ( w10>>>17 ^ w10>>>19 ^ w10>>>10 ^ w10<<15 ^ w10<<13 ) + w12 + w5 )|0; + d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0xc6e00bf3 )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; + + // 29 + w13 = ( ( w14>>>7 ^ w14>>>18 ^ w14>>>3 ^ w14<<25 ^ w14<<14 ) + ( w11>>>17 ^ w11>>>19 ^ w11>>>10 ^ w11<<15 ^ w11<<13 ) + w13 + w6 )|0; + c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0xd5a79147 )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; + + // 30 + w14 = ( ( w15>>>7 ^ w15>>>18 ^ w15>>>3 ^ w15<<25 ^ w15<<14 ) + ( w12>>>17 ^ w12>>>19 ^ w12>>>10 ^ w12<<15 ^ w12<<13 ) + w14 + w7 )|0; + b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x06ca6351 )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; + + // 31 + w15 = ( ( w0>>>7 ^ w0>>>18 ^ w0>>>3 ^ w0<<25 ^ w0<<14 ) + ( w13>>>17 ^ w13>>>19 ^ w13>>>10 ^ w13<<15 ^ w13<<13 ) + w15 + w8 )|0; + a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x14292967 )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; + + // 32 + w0 = ( ( w1>>>7 ^ w1>>>18 ^ w1>>>3 ^ w1<<25 ^ w1<<14 ) + ( w14>>>17 ^ w14>>>19 ^ w14>>>10 ^ w14<<15 ^ w14<<13 ) + w0 + w9 )|0; + h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x27b70a85 )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; + + // 33 + w1 = ( ( w2>>>7 ^ w2>>>18 ^ w2>>>3 ^ w2<<25 ^ w2<<14 ) + ( w15>>>17 ^ w15>>>19 ^ w15>>>10 ^ w15<<15 ^ w15<<13 ) + w1 + w10 )|0; + g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x2e1b2138 )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; + + // 34 + w2 = ( ( w3>>>7 ^ w3>>>18 ^ w3>>>3 ^ w3<<25 ^ w3<<14 ) + ( w0>>>17 ^ w0>>>19 ^ w0>>>10 ^ w0<<15 ^ w0<<13 ) + w2 + w11 )|0; + f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x4d2c6dfc )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; + + // 35 + w3 = ( ( w4>>>7 ^ w4>>>18 ^ w4>>>3 ^ w4<<25 ^ w4<<14 ) + ( w1>>>17 ^ w1>>>19 ^ w1>>>10 ^ w1<<15 ^ w1<<13 ) + w3 + w12 )|0; + e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x53380d13 )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; + + // 36 + w4 = ( ( w5>>>7 ^ w5>>>18 ^ w5>>>3 ^ w5<<25 ^ w5<<14 ) + ( w2>>>17 ^ w2>>>19 ^ w2>>>10 ^ w2<<15 ^ w2<<13 ) + w4 + w13 )|0; + d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x650a7354 )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; + + // 37 + w5 = ( ( w6>>>7 ^ w6>>>18 ^ w6>>>3 ^ w6<<25 ^ w6<<14 ) + ( w3>>>17 ^ w3>>>19 ^ w3>>>10 ^ w3<<15 ^ w3<<13 ) + w5 + w14 )|0; + c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x766a0abb )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; + + // 38 + w6 = ( ( w7>>>7 ^ w7>>>18 ^ w7>>>3 ^ w7<<25 ^ w7<<14 ) + ( w4>>>17 ^ w4>>>19 ^ w4>>>10 ^ w4<<15 ^ w4<<13 ) + w6 + w15 )|0; + b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x81c2c92e )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; + + // 39 + w7 = ( ( w8>>>7 ^ w8>>>18 ^ w8>>>3 ^ w8<<25 ^ w8<<14 ) + ( w5>>>17 ^ w5>>>19 ^ w5>>>10 ^ w5<<15 ^ w5<<13 ) + w7 + w0 )|0; + a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x92722c85 )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; + + // 40 + w8 = ( ( w9>>>7 ^ w9>>>18 ^ w9>>>3 ^ w9<<25 ^ w9<<14 ) + ( w6>>>17 ^ w6>>>19 ^ w6>>>10 ^ w6<<15 ^ w6<<13 ) + w8 + w1 )|0; + h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0xa2bfe8a1 )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; + + // 41 + w9 = ( ( w10>>>7 ^ w10>>>18 ^ w10>>>3 ^ w10<<25 ^ w10<<14 ) + ( w7>>>17 ^ w7>>>19 ^ w7>>>10 ^ w7<<15 ^ w7<<13 ) + w9 + w2 )|0; + g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0xa81a664b )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; + + // 42 + w10 = ( ( w11>>>7 ^ w11>>>18 ^ w11>>>3 ^ w11<<25 ^ w11<<14 ) + ( w8>>>17 ^ w8>>>19 ^ w8>>>10 ^ w8<<15 ^ w8<<13 ) + w10 + w3 )|0; + f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0xc24b8b70 )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; + + // 43 + w11 = ( ( w12>>>7 ^ w12>>>18 ^ w12>>>3 ^ w12<<25 ^ w12<<14 ) + ( w9>>>17 ^ w9>>>19 ^ w9>>>10 ^ w9<<15 ^ w9<<13 ) + w11 + w4 )|0; + e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0xc76c51a3 )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; + + // 44 + w12 = ( ( w13>>>7 ^ w13>>>18 ^ w13>>>3 ^ w13<<25 ^ w13<<14 ) + ( w10>>>17 ^ w10>>>19 ^ w10>>>10 ^ w10<<15 ^ w10<<13 ) + w12 + w5 )|0; + d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0xd192e819 )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; + + // 45 + w13 = ( ( w14>>>7 ^ w14>>>18 ^ w14>>>3 ^ w14<<25 ^ w14<<14 ) + ( w11>>>17 ^ w11>>>19 ^ w11>>>10 ^ w11<<15 ^ w11<<13 ) + w13 + w6 )|0; + c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0xd6990624 )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; + + // 46 + w14 = ( ( w15>>>7 ^ w15>>>18 ^ w15>>>3 ^ w15<<25 ^ w15<<14 ) + ( w12>>>17 ^ w12>>>19 ^ w12>>>10 ^ w12<<15 ^ w12<<13 ) + w14 + w7 )|0; + b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0xf40e3585 )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; + + // 47 + w15 = ( ( w0>>>7 ^ w0>>>18 ^ w0>>>3 ^ w0<<25 ^ w0<<14 ) + ( w13>>>17 ^ w13>>>19 ^ w13>>>10 ^ w13<<15 ^ w13<<13 ) + w15 + w8 )|0; + a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x106aa070 )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; + + // 48 + w0 = ( ( w1>>>7 ^ w1>>>18 ^ w1>>>3 ^ w1<<25 ^ w1<<14 ) + ( w14>>>17 ^ w14>>>19 ^ w14>>>10 ^ w14<<15 ^ w14<<13 ) + w0 + w9 )|0; + h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x19a4c116 )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; + + // 49 + w1 = ( ( w2>>>7 ^ w2>>>18 ^ w2>>>3 ^ w2<<25 ^ w2<<14 ) + ( w15>>>17 ^ w15>>>19 ^ w15>>>10 ^ w15<<15 ^ w15<<13 ) + w1 + w10 )|0; + g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x1e376c08 )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; + + // 50 + w2 = ( ( w3>>>7 ^ w3>>>18 ^ w3>>>3 ^ w3<<25 ^ w3<<14 ) + ( w0>>>17 ^ w0>>>19 ^ w0>>>10 ^ w0<<15 ^ w0<<13 ) + w2 + w11 )|0; + f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x2748774c )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; + + // 51 + w3 = ( ( w4>>>7 ^ w4>>>18 ^ w4>>>3 ^ w4<<25 ^ w4<<14 ) + ( w1>>>17 ^ w1>>>19 ^ w1>>>10 ^ w1<<15 ^ w1<<13 ) + w3 + w12 )|0; + e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x34b0bcb5 )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; + + // 52 + w4 = ( ( w5>>>7 ^ w5>>>18 ^ w5>>>3 ^ w5<<25 ^ w5<<14 ) + ( w2>>>17 ^ w2>>>19 ^ w2>>>10 ^ w2<<15 ^ w2<<13 ) + w4 + w13 )|0; + d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x391c0cb3 )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; + + // 53 + w5 = ( ( w6>>>7 ^ w6>>>18 ^ w6>>>3 ^ w6<<25 ^ w6<<14 ) + ( w3>>>17 ^ w3>>>19 ^ w3>>>10 ^ w3<<15 ^ w3<<13 ) + w5 + w14 )|0; + c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x4ed8aa4a )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; + + // 54 + w6 = ( ( w7>>>7 ^ w7>>>18 ^ w7>>>3 ^ w7<<25 ^ w7<<14 ) + ( w4>>>17 ^ w4>>>19 ^ w4>>>10 ^ w4<<15 ^ w4<<13 ) + w6 + w15 )|0; + b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x5b9cca4f )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; + + // 55 + w7 = ( ( w8>>>7 ^ w8>>>18 ^ w8>>>3 ^ w8<<25 ^ w8<<14 ) + ( w5>>>17 ^ w5>>>19 ^ w5>>>10 ^ w5<<15 ^ w5<<13 ) + w7 + w0 )|0; + a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x682e6ff3 )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; + + // 56 + w8 = ( ( w9>>>7 ^ w9>>>18 ^ w9>>>3 ^ w9<<25 ^ w9<<14 ) + ( w6>>>17 ^ w6>>>19 ^ w6>>>10 ^ w6<<15 ^ w6<<13 ) + w8 + w1 )|0; + h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x748f82ee )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; + + // 57 + w9 = ( ( w10>>>7 ^ w10>>>18 ^ w10>>>3 ^ w10<<25 ^ w10<<14 ) + ( w7>>>17 ^ w7>>>19 ^ w7>>>10 ^ w7<<15 ^ w7<<13 ) + w9 + w2 )|0; + g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x78a5636f )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; + + // 58 + w10 = ( ( w11>>>7 ^ w11>>>18 ^ w11>>>3 ^ w11<<25 ^ w11<<14 ) + ( w8>>>17 ^ w8>>>19 ^ w8>>>10 ^ w8<<15 ^ w8<<13 ) + w10 + w3 )|0; + f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x84c87814 )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; + + // 59 + w11 = ( ( w12>>>7 ^ w12>>>18 ^ w12>>>3 ^ w12<<25 ^ w12<<14 ) + ( w9>>>17 ^ w9>>>19 ^ w9>>>10 ^ w9<<15 ^ w9<<13 ) + w11 + w4 )|0; + e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x8cc70208 )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; + + // 60 + w12 = ( ( w13>>>7 ^ w13>>>18 ^ w13>>>3 ^ w13<<25 ^ w13<<14 ) + ( w10>>>17 ^ w10>>>19 ^ w10>>>10 ^ w10<<15 ^ w10<<13 ) + w12 + w5 )|0; + d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x90befffa )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; + + // 61 + w13 = ( ( w14>>>7 ^ w14>>>18 ^ w14>>>3 ^ w14<<25 ^ w14<<14 ) + ( w11>>>17 ^ w11>>>19 ^ w11>>>10 ^ w11<<15 ^ w11<<13 ) + w13 + w6 )|0; + c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0xa4506ceb )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; + + // 62 + w14 = ( ( w15>>>7 ^ w15>>>18 ^ w15>>>3 ^ w15<<25 ^ w15<<14 ) + ( w12>>>17 ^ w12>>>19 ^ w12>>>10 ^ w12<<15 ^ w12<<13 ) + w14 + w7 )|0; + b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0xbef9a3f7 )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; + + // 63 + w15 = ( ( w0>>>7 ^ w0>>>18 ^ w0>>>3 ^ w0<<25 ^ w0<<14 ) + ( w13>>>17 ^ w13>>>19 ^ w13>>>10 ^ w13<<15 ^ w13<<13 ) + w15 + w8 )|0; + a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0xc67178f2 )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; + + H0 = ( H0 + a )|0; + H1 = ( H1 + b )|0; + H2 = ( H2 + c )|0; + H3 = ( H3 + d )|0; + H4 = ( H4 + e )|0; + H5 = ( H5 + f )|0; + H6 = ( H6 + g )|0; + H7 = ( H7 + h )|0; + } + + function _core_heap ( offset ) { + offset = offset|0; + + _core( + HEAP[offset|0]<<24 | HEAP[offset|1]<<16 | HEAP[offset|2]<<8 | HEAP[offset|3], + HEAP[offset|4]<<24 | HEAP[offset|5]<<16 | HEAP[offset|6]<<8 | HEAP[offset|7], + HEAP[offset|8]<<24 | HEAP[offset|9]<<16 | HEAP[offset|10]<<8 | HEAP[offset|11], + HEAP[offset|12]<<24 | HEAP[offset|13]<<16 | HEAP[offset|14]<<8 | HEAP[offset|15], + HEAP[offset|16]<<24 | HEAP[offset|17]<<16 | HEAP[offset|18]<<8 | HEAP[offset|19], + HEAP[offset|20]<<24 | HEAP[offset|21]<<16 | HEAP[offset|22]<<8 | HEAP[offset|23], + HEAP[offset|24]<<24 | HEAP[offset|25]<<16 | HEAP[offset|26]<<8 | HEAP[offset|27], + HEAP[offset|28]<<24 | HEAP[offset|29]<<16 | HEAP[offset|30]<<8 | HEAP[offset|31], + HEAP[offset|32]<<24 | HEAP[offset|33]<<16 | HEAP[offset|34]<<8 | HEAP[offset|35], + HEAP[offset|36]<<24 | HEAP[offset|37]<<16 | HEAP[offset|38]<<8 | HEAP[offset|39], + HEAP[offset|40]<<24 | HEAP[offset|41]<<16 | HEAP[offset|42]<<8 | HEAP[offset|43], + HEAP[offset|44]<<24 | HEAP[offset|45]<<16 | HEAP[offset|46]<<8 | HEAP[offset|47], + HEAP[offset|48]<<24 | HEAP[offset|49]<<16 | HEAP[offset|50]<<8 | HEAP[offset|51], + HEAP[offset|52]<<24 | HEAP[offset|53]<<16 | HEAP[offset|54]<<8 | HEAP[offset|55], + HEAP[offset|56]<<24 | HEAP[offset|57]<<16 | HEAP[offset|58]<<8 | HEAP[offset|59], + HEAP[offset|60]<<24 | HEAP[offset|61]<<16 | HEAP[offset|62]<<8 | HEAP[offset|63] + ); + } + + // offset — multiple of 32 + function _state_to_heap ( output ) { + output = output|0; + + HEAP[output|0] = H0>>>24; + HEAP[output|1] = H0>>>16&255; + HEAP[output|2] = H0>>>8&255; + HEAP[output|3] = H0&255; + HEAP[output|4] = H1>>>24; + HEAP[output|5] = H1>>>16&255; + HEAP[output|6] = H1>>>8&255; + HEAP[output|7] = H1&255; + HEAP[output|8] = H2>>>24; + HEAP[output|9] = H2>>>16&255; + HEAP[output|10] = H2>>>8&255; + HEAP[output|11] = H2&255; + HEAP[output|12] = H3>>>24; + HEAP[output|13] = H3>>>16&255; + HEAP[output|14] = H3>>>8&255; + HEAP[output|15] = H3&255; + HEAP[output|16] = H4>>>24; + HEAP[output|17] = H4>>>16&255; + HEAP[output|18] = H4>>>8&255; + HEAP[output|19] = H4&255; + HEAP[output|20] = H5>>>24; + HEAP[output|21] = H5>>>16&255; + HEAP[output|22] = H5>>>8&255; + HEAP[output|23] = H5&255; + HEAP[output|24] = H6>>>24; + HEAP[output|25] = H6>>>16&255; + HEAP[output|26] = H6>>>8&255; + HEAP[output|27] = H6&255; + HEAP[output|28] = H7>>>24; + HEAP[output|29] = H7>>>16&255; + HEAP[output|30] = H7>>>8&255; + HEAP[output|31] = H7&255; + } + + function reset () { + H0 = 0x6a09e667; + H1 = 0xbb67ae85; + H2 = 0x3c6ef372; + H3 = 0xa54ff53a; + H4 = 0x510e527f; + H5 = 0x9b05688c; + H6 = 0x1f83d9ab; + H7 = 0x5be0cd19; + TOTAL0 = TOTAL1 = 0; + } + + function init ( h0, h1, h2, h3, h4, h5, h6, h7, total0, total1 ) { + h0 = h0|0; + h1 = h1|0; + h2 = h2|0; + h3 = h3|0; + h4 = h4|0; + h5 = h5|0; + h6 = h6|0; + h7 = h7|0; + total0 = total0|0; + total1 = total1|0; + + H0 = h0; + H1 = h1; + H2 = h2; + H3 = h3; + H4 = h4; + H5 = h5; + H6 = h6; + H7 = h7; + TOTAL0 = total0; + TOTAL1 = total1; + } + + // offset — multiple of 64 + function process ( offset, length ) { + offset = offset|0; + length = length|0; + + var hashed = 0; + + if ( offset & 63 ) + return -1; + + while ( (length|0) >= 64 ) { + _core_heap(offset); + + offset = ( offset + 64 )|0; + length = ( length - 64 )|0; + + hashed = ( hashed + 64 )|0; + } + + TOTAL0 = ( TOTAL0 + hashed )|0; + if ( TOTAL0>>>0 < hashed>>>0 ) TOTAL1 = ( TOTAL1 + 1 )|0; + + return hashed|0; + } + + // offset — multiple of 64 + // output — multiple of 32 + function finish ( offset, length, output ) { + offset = offset|0; + length = length|0; + output = output|0; + + var hashed = 0, + i = 0; + + if ( offset & 63 ) + return -1; + + if ( ~output ) + if ( output & 31 ) + return -1; + + if ( (length|0) >= 64 ) { + hashed = process( offset, length )|0; + if ( (hashed|0) == -1 ) + return -1; + + offset = ( offset + hashed )|0; + length = ( length - hashed )|0; + } + + hashed = ( hashed + length )|0; + TOTAL0 = ( TOTAL0 + length )|0; + if ( TOTAL0>>>0 < length>>>0 ) TOTAL1 = ( TOTAL1 + 1 )|0; + + HEAP[offset|length] = 0x80; + + if ( (length|0) >= 56 ) { + for ( i = (length+1)|0; (i|0) < 64; i = (i+1)|0 ) + HEAP[offset|i] = 0x00; + + _core_heap(offset); + + length = 0; + + HEAP[offset|0] = 0; + } + + for ( i = (length+1)|0; (i|0) < 59; i = (i+1)|0 ) + HEAP[offset|i] = 0; + + HEAP[offset|56] = TOTAL1>>>21&255; + HEAP[offset|57] = TOTAL1>>>13&255; + HEAP[offset|58] = TOTAL1>>>5&255; + HEAP[offset|59] = TOTAL1<<3&255 | TOTAL0>>>29; + HEAP[offset|60] = TOTAL0>>>21&255; + HEAP[offset|61] = TOTAL0>>>13&255; + HEAP[offset|62] = TOTAL0>>>5&255; + HEAP[offset|63] = TOTAL0<<3&255; + _core_heap(offset); + + if ( ~output ) + _state_to_heap(output); + + return hashed|0; + } + + function hmac_reset () { + H0 = I0; + H1 = I1; + H2 = I2; + H3 = I3; + H4 = I4; + H5 = I5; + H6 = I6; + H7 = I7; + TOTAL0 = 64; + TOTAL1 = 0; + } + + function _hmac_opad () { + H0 = O0; + H1 = O1; + H2 = O2; + H3 = O3; + H4 = O4; + H5 = O5; + H6 = O6; + H7 = O7; + TOTAL0 = 64; + TOTAL1 = 0; + } + + function hmac_init ( p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15 ) { + p0 = p0|0; + p1 = p1|0; + p2 = p2|0; + p3 = p3|0; + p4 = p4|0; + p5 = p5|0; + p6 = p6|0; + p7 = p7|0; + p8 = p8|0; + p9 = p9|0; + p10 = p10|0; + p11 = p11|0; + p12 = p12|0; + p13 = p13|0; + p14 = p14|0; + p15 = p15|0; + + // opad + reset(); + _core( + p0 ^ 0x5c5c5c5c, + p1 ^ 0x5c5c5c5c, + p2 ^ 0x5c5c5c5c, + p3 ^ 0x5c5c5c5c, + p4 ^ 0x5c5c5c5c, + p5 ^ 0x5c5c5c5c, + p6 ^ 0x5c5c5c5c, + p7 ^ 0x5c5c5c5c, + p8 ^ 0x5c5c5c5c, + p9 ^ 0x5c5c5c5c, + p10 ^ 0x5c5c5c5c, + p11 ^ 0x5c5c5c5c, + p12 ^ 0x5c5c5c5c, + p13 ^ 0x5c5c5c5c, + p14 ^ 0x5c5c5c5c, + p15 ^ 0x5c5c5c5c + ); + O0 = H0; + O1 = H1; + O2 = H2; + O3 = H3; + O4 = H4; + O5 = H5; + O6 = H6; + O7 = H7; + + // ipad + reset(); + _core( + p0 ^ 0x36363636, + p1 ^ 0x36363636, + p2 ^ 0x36363636, + p3 ^ 0x36363636, + p4 ^ 0x36363636, + p5 ^ 0x36363636, + p6 ^ 0x36363636, + p7 ^ 0x36363636, + p8 ^ 0x36363636, + p9 ^ 0x36363636, + p10 ^ 0x36363636, + p11 ^ 0x36363636, + p12 ^ 0x36363636, + p13 ^ 0x36363636, + p14 ^ 0x36363636, + p15 ^ 0x36363636 + ); + I0 = H0; + I1 = H1; + I2 = H2; + I3 = H3; + I4 = H4; + I5 = H5; + I6 = H6; + I7 = H7; + + TOTAL0 = 64; + TOTAL1 = 0; + } + + // offset — multiple of 64 + // output — multiple of 32 + function hmac_finish ( offset, length, output ) { + offset = offset|0; + length = length|0; + output = output|0; + + var t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0, + hashed = 0; + + if ( offset & 63 ) + return -1; + + if ( ~output ) + if ( output & 31 ) + return -1; + + hashed = finish( offset, length, -1 )|0; + t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; + + _hmac_opad(); + _core( t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768 ); + + if ( ~output ) + _state_to_heap(output); + + return hashed|0; + } + + // salt is assumed to be already processed + // offset — multiple of 64 + // output — multiple of 32 + function pbkdf2_generate_block ( offset, length, block, count, output ) { + offset = offset|0; + length = length|0; + block = block|0; + count = count|0; + output = output|0; + + var h0 = 0, h1 = 0, h2 = 0, h3 = 0, h4 = 0, h5 = 0, h6 = 0, h7 = 0, + t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0; + + if ( offset & 63 ) + return -1; + + if ( ~output ) + if ( output & 31 ) + return -1; + + // pad block number into heap + // FIXME probable OOB write + HEAP[(offset+length)|0] = block>>>24; + HEAP[(offset+length+1)|0] = block>>>16&255; + HEAP[(offset+length+2)|0] = block>>>8&255; + HEAP[(offset+length+3)|0] = block&255; + + // finish first iteration + hmac_finish( offset, (length+4)|0, -1 )|0; + h0 = t0 = H0, h1 = t1 = H1, h2 = t2 = H2, h3 = t3 = H3, h4 = t4 = H4, h5 = t5 = H5, h6 = t6 = H6, h7 = t7 = H7; + count = (count-1)|0; + + // perform the rest iterations + while ( (count|0) > 0 ) { + hmac_reset(); + _core( t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768 ); + t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; + + _hmac_opad(); + _core( t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768 ); + t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; + + h0 = h0 ^ H0; + h1 = h1 ^ H1; + h2 = h2 ^ H2; + h3 = h3 ^ H3; + h4 = h4 ^ H4; + h5 = h5 ^ H5; + h6 = h6 ^ H6; + h7 = h7 ^ H7; + + count = (count-1)|0; + } + + H0 = h0; + H1 = h1; + H2 = h2; + H3 = h3; + H4 = h4; + H5 = h5; + H6 = h6; + H7 = h7; + + if ( ~output ) + _state_to_heap(output); + + return 0; + } + + return { + // SHA256 + reset: reset, + init: init, + process: process, + finish: finish, + + // HMAC-SHA256 + hmac_reset: hmac_reset, + hmac_init: hmac_init, + hmac_finish: hmac_finish, + + // PBKDF2-HMAC-SHA256 + pbkdf2_generate_block: pbkdf2_generate_block + } +}; + +const _sha256_block_size = 64; +const _sha256_hash_size = 32; +const heap_pool$2 = []; +const asm_pool$2 = []; +class Sha256 extends Hash { + constructor() { + super(); + this.NAME = 'sha256'; + this.BLOCK_SIZE = _sha256_block_size; + this.HASH_SIZE = _sha256_hash_size; + this.acquire_asm(); + } + acquire_asm() { + if (this.heap === undefined || this.asm === undefined) { + this.heap = heap_pool$2.pop() || _heap_init(); + this.asm = asm_pool$2.pop() || sha256_asm({ Uint8Array: Uint8Array }, null, this.heap.buffer); + this.reset(); + } + return { heap: this.heap, asm: this.asm }; + } + release_asm() { + if (this.heap !== undefined && this.asm !== undefined) { + heap_pool$2.push(this.heap); + asm_pool$2.push(this.asm); + } + this.heap = undefined; + this.asm = undefined; + } + static bytes(data) { + return new Sha256().process(data).finish().result; + } +} +Sha256.NAME = 'sha256'; + +var minimalisticAssert = assert; + +function assert(val, msg) { + if (!val) + throw new Error(msg || 'Assertion failed'); +} + +assert.equal = function assertEqual(l, r, msg) { + if (l != r) + throw new Error(msg || ('Assertion failed: ' + l + ' != ' + r)); +}; + +var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + +function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; +} + +function commonjsRequire () { + throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs'); +} + +var inherits_browser = createCommonjsModule(function (module) { +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor; + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor; + var TempCtor = function () {}; + TempCtor.prototype = superCtor.prototype; + ctor.prototype = new TempCtor(); + ctor.prototype.constructor = ctor; + }; +} +}); + +var inherits = createCommonjsModule(function (module) { +try { + var util = util__default['default']; + if (typeof util.inherits !== 'function') throw ''; + module.exports = util.inherits; +} catch (e) { + module.exports = inherits_browser; +} +}); + +var inherits_1 = inherits; + +function toArray(msg, enc) { + if (Array.isArray(msg)) + return msg.slice(); + if (!msg) + return []; + var res = []; + if (typeof msg === 'string') { + if (!enc) { + for (var i = 0; i < msg.length; i++) { + var c = msg.charCodeAt(i); + var hi = c >> 8; + var lo = c & 0xff; + if (hi) + res.push(hi, lo); + else + res.push(lo); + } + } else if (enc === 'hex') { + msg = msg.replace(/[^a-z0-9]+/ig, ''); + if (msg.length % 2 !== 0) + msg = '0' + msg; + for (i = 0; i < msg.length; i += 2) + res.push(parseInt(msg[i] + msg[i + 1], 16)); + } + } else { + for (i = 0; i < msg.length; i++) + res[i] = msg[i] | 0; + } + return res; +} +var toArray_1 = toArray; + +function toHex(msg) { + var res = ''; + for (var i = 0; i < msg.length; i++) + res += zero2(msg[i].toString(16)); + return res; +} +var toHex_1 = toHex; + +function htonl(w) { + var res = (w >>> 24) | + ((w >>> 8) & 0xff00) | + ((w << 8) & 0xff0000) | + ((w & 0xff) << 24); + return res >>> 0; +} +var htonl_1 = htonl; + +function toHex32(msg, endian) { + var res = ''; + for (var i = 0; i < msg.length; i++) { + var w = msg[i]; + if (endian === 'little') + w = htonl(w); + res += zero8(w.toString(16)); + } + return res; +} +var toHex32_1 = toHex32; + +function zero2(word) { + if (word.length === 1) + return '0' + word; + else + return word; +} +var zero2_1 = zero2; + +function zero8(word) { + if (word.length === 7) + return '0' + word; + else if (word.length === 6) + return '00' + word; + else if (word.length === 5) + return '000' + word; + else if (word.length === 4) + return '0000' + word; + else if (word.length === 3) + return '00000' + word; + else if (word.length === 2) + return '000000' + word; + else if (word.length === 1) + return '0000000' + word; + else + return word; +} +var zero8_1 = zero8; + +function join32(msg, start, end, endian) { + var len = end - start; + minimalisticAssert(len % 4 === 0); + var res = new Array(len / 4); + for (var i = 0, k = start; i < res.length; i++, k += 4) { + var w; + if (endian === 'big') + w = (msg[k] << 24) | (msg[k + 1] << 16) | (msg[k + 2] << 8) | msg[k + 3]; + else + w = (msg[k + 3] << 24) | (msg[k + 2] << 16) | (msg[k + 1] << 8) | msg[k]; + res[i] = w >>> 0; + } + return res; +} +var join32_1 = join32; + +function split32(msg, endian) { + var res = new Array(msg.length * 4); + for (var i = 0, k = 0; i < msg.length; i++, k += 4) { + var m = msg[i]; + if (endian === 'big') { + res[k] = m >>> 24; + res[k + 1] = (m >>> 16) & 0xff; + res[k + 2] = (m >>> 8) & 0xff; + res[k + 3] = m & 0xff; + } else { + res[k + 3] = m >>> 24; + res[k + 2] = (m >>> 16) & 0xff; + res[k + 1] = (m >>> 8) & 0xff; + res[k] = m & 0xff; + } + } + return res; +} +var split32_1 = split32; + +function rotr32(w, b) { + return (w >>> b) | (w << (32 - b)); +} +var rotr32_1 = rotr32; + +function rotl32(w, b) { + return (w << b) | (w >>> (32 - b)); +} +var rotl32_1 = rotl32; + +function sum32(a, b) { + return (a + b) >>> 0; +} +var sum32_1 = sum32; + +function sum32_3(a, b, c) { + return (a + b + c) >>> 0; +} +var sum32_3_1 = sum32_3; + +function sum32_4(a, b, c, d) { + return (a + b + c + d) >>> 0; +} +var sum32_4_1 = sum32_4; + +function sum32_5(a, b, c, d, e) { + return (a + b + c + d + e) >>> 0; +} +var sum32_5_1 = sum32_5; + +function sum64(buf, pos, ah, al) { + var bh = buf[pos]; + var bl = buf[pos + 1]; + + var lo = (al + bl) >>> 0; + var hi = (lo < al ? 1 : 0) + ah + bh; + buf[pos] = hi >>> 0; + buf[pos + 1] = lo; +} +var sum64_1 = sum64; + +function sum64_hi(ah, al, bh, bl) { + var lo = (al + bl) >>> 0; + var hi = (lo < al ? 1 : 0) + ah + bh; + return hi >>> 0; +} +var sum64_hi_1 = sum64_hi; + +function sum64_lo(ah, al, bh, bl) { + var lo = al + bl; + return lo >>> 0; +} +var sum64_lo_1 = sum64_lo; + +function sum64_4_hi(ah, al, bh, bl, ch, cl, dh, dl) { + var carry = 0; + var lo = al; + lo = (lo + bl) >>> 0; + carry += lo < al ? 1 : 0; + lo = (lo + cl) >>> 0; + carry += lo < cl ? 1 : 0; + lo = (lo + dl) >>> 0; + carry += lo < dl ? 1 : 0; + + var hi = ah + bh + ch + dh + carry; + return hi >>> 0; +} +var sum64_4_hi_1 = sum64_4_hi; + +function sum64_4_lo(ah, al, bh, bl, ch, cl, dh, dl) { + var lo = al + bl + cl + dl; + return lo >>> 0; +} +var sum64_4_lo_1 = sum64_4_lo; + +function sum64_5_hi(ah, al, bh, bl, ch, cl, dh, dl, eh, el) { + var carry = 0; + var lo = al; + lo = (lo + bl) >>> 0; + carry += lo < al ? 1 : 0; + lo = (lo + cl) >>> 0; + carry += lo < cl ? 1 : 0; + lo = (lo + dl) >>> 0; + carry += lo < dl ? 1 : 0; + lo = (lo + el) >>> 0; + carry += lo < el ? 1 : 0; + + var hi = ah + bh + ch + dh + eh + carry; + return hi >>> 0; +} +var sum64_5_hi_1 = sum64_5_hi; + +function sum64_5_lo(ah, al, bh, bl, ch, cl, dh, dl, eh, el) { + var lo = al + bl + cl + dl + el; + + return lo >>> 0; +} +var sum64_5_lo_1 = sum64_5_lo; + +function rotr64_hi(ah, al, num) { + var r = (al << (32 - num)) | (ah >>> num); + return r >>> 0; +} +var rotr64_hi_1 = rotr64_hi; + +function rotr64_lo(ah, al, num) { + var r = (ah << (32 - num)) | (al >>> num); + return r >>> 0; +} +var rotr64_lo_1 = rotr64_lo; + +function shr64_hi(ah, al, num) { + return ah >>> num; +} +var shr64_hi_1 = shr64_hi; + +function shr64_lo(ah, al, num) { + var r = (ah << (32 - num)) | (al >>> num); + return r >>> 0; +} +var shr64_lo_1 = shr64_lo; + +var utils = { + inherits: inherits_1, + toArray: toArray_1, + toHex: toHex_1, + htonl: htonl_1, + toHex32: toHex32_1, + zero2: zero2_1, + zero8: zero8_1, + join32: join32_1, + split32: split32_1, + rotr32: rotr32_1, + rotl32: rotl32_1, + sum32: sum32_1, + sum32_3: sum32_3_1, + sum32_4: sum32_4_1, + sum32_5: sum32_5_1, + sum64: sum64_1, + sum64_hi: sum64_hi_1, + sum64_lo: sum64_lo_1, + sum64_4_hi: sum64_4_hi_1, + sum64_4_lo: sum64_4_lo_1, + sum64_5_hi: sum64_5_hi_1, + sum64_5_lo: sum64_5_lo_1, + rotr64_hi: rotr64_hi_1, + rotr64_lo: rotr64_lo_1, + shr64_hi: shr64_hi_1, + shr64_lo: shr64_lo_1 +}; + +function BlockHash() { + this.pending = null; + this.pendingTotal = 0; + this.blockSize = this.constructor.blockSize; + this.outSize = this.constructor.outSize; + this.hmacStrength = this.constructor.hmacStrength; + this.padLength = this.constructor.padLength / 8; + this.endian = 'big'; + + this._delta8 = this.blockSize / 8; + this._delta32 = this.blockSize / 32; +} +var BlockHash_1 = BlockHash; + +BlockHash.prototype.update = function update(msg, enc) { + // Convert message to array, pad it, and join into 32bit blocks + msg = utils.toArray(msg, enc); + if (!this.pending) + this.pending = msg; + else + this.pending = this.pending.concat(msg); + this.pendingTotal += msg.length; + + // Enough data, try updating + if (this.pending.length >= this._delta8) { + msg = this.pending; + + // Process pending data in blocks + var r = msg.length % this._delta8; + this.pending = msg.slice(msg.length - r, msg.length); + if (this.pending.length === 0) + this.pending = null; + + msg = utils.join32(msg, 0, msg.length - r, this.endian); + for (var i = 0; i < msg.length; i += this._delta32) + this._update(msg, i, i + this._delta32); + } + + return this; +}; + +BlockHash.prototype.digest = function digest(enc) { + this.update(this._pad()); + minimalisticAssert(this.pending === null); + + return this._digest(enc); +}; + +BlockHash.prototype._pad = function pad() { + var len = this.pendingTotal; + var bytes = this._delta8; + var k = bytes - ((len + this.padLength) % bytes); + var res = new Array(k + this.padLength); + res[0] = 0x80; + for (var i = 1; i < k; i++) + res[i] = 0; + + // Append length + len <<= 3; + if (this.endian === 'big') { + for (var t = 8; t < this.padLength; t++) + res[i++] = 0; + + res[i++] = 0; + res[i++] = 0; + res[i++] = 0; + res[i++] = 0; + res[i++] = (len >>> 24) & 0xff; + res[i++] = (len >>> 16) & 0xff; + res[i++] = (len >>> 8) & 0xff; + res[i++] = len & 0xff; + } else { + res[i++] = len & 0xff; + res[i++] = (len >>> 8) & 0xff; + res[i++] = (len >>> 16) & 0xff; + res[i++] = (len >>> 24) & 0xff; + res[i++] = 0; + res[i++] = 0; + res[i++] = 0; + res[i++] = 0; + + for (t = 8; t < this.padLength; t++) + res[i++] = 0; + } + + return res; +}; + +var common = { + BlockHash: BlockHash_1 +}; + +var rotr32$1 = utils.rotr32; + +function ft_1(s, x, y, z) { + if (s === 0) + return ch32(x, y, z); + if (s === 1 || s === 3) + return p32(x, y, z); + if (s === 2) + return maj32(x, y, z); +} +var ft_1_1 = ft_1; + +function ch32(x, y, z) { + return (x & y) ^ ((~x) & z); +} +var ch32_1 = ch32; + +function maj32(x, y, z) { + return (x & y) ^ (x & z) ^ (y & z); +} +var maj32_1 = maj32; + +function p32(x, y, z) { + return x ^ y ^ z; +} +var p32_1 = p32; + +function s0_256(x) { + return rotr32$1(x, 2) ^ rotr32$1(x, 13) ^ rotr32$1(x, 22); +} +var s0_256_1 = s0_256; + +function s1_256(x) { + return rotr32$1(x, 6) ^ rotr32$1(x, 11) ^ rotr32$1(x, 25); +} +var s1_256_1 = s1_256; + +function g0_256(x) { + return rotr32$1(x, 7) ^ rotr32$1(x, 18) ^ (x >>> 3); +} +var g0_256_1 = g0_256; + +function g1_256(x) { + return rotr32$1(x, 17) ^ rotr32$1(x, 19) ^ (x >>> 10); +} +var g1_256_1 = g1_256; + +var common$1 = { + ft_1: ft_1_1, + ch32: ch32_1, + maj32: maj32_1, + p32: p32_1, + s0_256: s0_256_1, + s1_256: s1_256_1, + g0_256: g0_256_1, + g1_256: g1_256_1 +}; + +var sum32$1 = utils.sum32; +var sum32_4$1 = utils.sum32_4; +var sum32_5$1 = utils.sum32_5; +var ch32$1 = common$1.ch32; +var maj32$1 = common$1.maj32; +var s0_256$1 = common$1.s0_256; +var s1_256$1 = common$1.s1_256; +var g0_256$1 = common$1.g0_256; +var g1_256$1 = common$1.g1_256; + +var BlockHash$1 = common.BlockHash; + +var sha256_K = [ + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +]; + +function SHA256() { + if (!(this instanceof SHA256)) + return new SHA256(); + + BlockHash$1.call(this); + this.h = [ + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 + ]; + this.k = sha256_K; + this.W = new Array(64); +} +utils.inherits(SHA256, BlockHash$1); +var _256 = SHA256; + +SHA256.blockSize = 512; +SHA256.outSize = 256; +SHA256.hmacStrength = 192; +SHA256.padLength = 64; + +SHA256.prototype._update = function _update(msg, start) { + var W = this.W; + + for (var i = 0; i < 16; i++) + W[i] = msg[start + i]; + for (; i < W.length; i++) + W[i] = sum32_4$1(g1_256$1(W[i - 2]), W[i - 7], g0_256$1(W[i - 15]), W[i - 16]); + + var a = this.h[0]; + var b = this.h[1]; + var c = this.h[2]; + var d = this.h[3]; + var e = this.h[4]; + var f = this.h[5]; + var g = this.h[6]; + var h = this.h[7]; + + minimalisticAssert(this.k.length === W.length); + for (i = 0; i < W.length; i++) { + var T1 = sum32_5$1(h, s1_256$1(e), ch32$1(e, f, g), this.k[i], W[i]); + var T2 = sum32$1(s0_256$1(a), maj32$1(a, b, c)); + h = g; + g = f; + f = e; + e = sum32$1(d, T1); + d = c; + c = b; + b = a; + a = sum32$1(T1, T2); + } + + this.h[0] = sum32$1(this.h[0], a); + this.h[1] = sum32$1(this.h[1], b); + this.h[2] = sum32$1(this.h[2], c); + this.h[3] = sum32$1(this.h[3], d); + this.h[4] = sum32$1(this.h[4], e); + this.h[5] = sum32$1(this.h[5], f); + this.h[6] = sum32$1(this.h[6], g); + this.h[7] = sum32$1(this.h[7], h); +}; + +SHA256.prototype._digest = function digest(enc) { + if (enc === 'hex') + return utils.toHex32(this.h, 'big'); + else + return utils.split32(this.h, 'big'); +}; + +function SHA224() { + if (!(this instanceof SHA224)) + return new SHA224(); + + _256.call(this); + this.h = [ + 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, + 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 ]; +} +utils.inherits(SHA224, _256); +var _224 = SHA224; + +SHA224.blockSize = 512; +SHA224.outSize = 224; +SHA224.hmacStrength = 192; +SHA224.padLength = 64; + +SHA224.prototype._digest = function digest(enc) { + // Just truncate output + if (enc === 'hex') + return utils.toHex32(this.h.slice(0, 7), 'big'); + else + return utils.split32(this.h.slice(0, 7), 'big'); +}; + +var rotr64_hi$1 = utils.rotr64_hi; +var rotr64_lo$1 = utils.rotr64_lo; +var shr64_hi$1 = utils.shr64_hi; +var shr64_lo$1 = utils.shr64_lo; +var sum64$1 = utils.sum64; +var sum64_hi$1 = utils.sum64_hi; +var sum64_lo$1 = utils.sum64_lo; +var sum64_4_hi$1 = utils.sum64_4_hi; +var sum64_4_lo$1 = utils.sum64_4_lo; +var sum64_5_hi$1 = utils.sum64_5_hi; +var sum64_5_lo$1 = utils.sum64_5_lo; + +var BlockHash$2 = common.BlockHash; + +var sha512_K = [ + 0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd, + 0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc, + 0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019, + 0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118, + 0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe, + 0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2, + 0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1, + 0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694, + 0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3, + 0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65, + 0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483, + 0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5, + 0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210, + 0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4, + 0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725, + 0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70, + 0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926, + 0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df, + 0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8, + 0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b, + 0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001, + 0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30, + 0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910, + 0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8, + 0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53, + 0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8, + 0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb, + 0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3, + 0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60, + 0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec, + 0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9, + 0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b, + 0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207, + 0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178, + 0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6, + 0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b, + 0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493, + 0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c, + 0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a, + 0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817 +]; + +function SHA512() { + if (!(this instanceof SHA512)) + return new SHA512(); + + BlockHash$2.call(this); + this.h = [ + 0x6a09e667, 0xf3bcc908, + 0xbb67ae85, 0x84caa73b, + 0x3c6ef372, 0xfe94f82b, + 0xa54ff53a, 0x5f1d36f1, + 0x510e527f, 0xade682d1, + 0x9b05688c, 0x2b3e6c1f, + 0x1f83d9ab, 0xfb41bd6b, + 0x5be0cd19, 0x137e2179 ]; + this.k = sha512_K; + this.W = new Array(160); +} +utils.inherits(SHA512, BlockHash$2); +var _512 = SHA512; + +SHA512.blockSize = 1024; +SHA512.outSize = 512; +SHA512.hmacStrength = 192; +SHA512.padLength = 128; + +SHA512.prototype._prepareBlock = function _prepareBlock(msg, start) { + var W = this.W; + + // 32 x 32bit words + for (var i = 0; i < 32; i++) + W[i] = msg[start + i]; + for (; i < W.length; i += 2) { + var c0_hi = g1_512_hi(W[i - 4], W[i - 3]); // i - 2 + var c0_lo = g1_512_lo(W[i - 4], W[i - 3]); + var c1_hi = W[i - 14]; // i - 7 + var c1_lo = W[i - 13]; + var c2_hi = g0_512_hi(W[i - 30], W[i - 29]); // i - 15 + var c2_lo = g0_512_lo(W[i - 30], W[i - 29]); + var c3_hi = W[i - 32]; // i - 16 + var c3_lo = W[i - 31]; + + W[i] = sum64_4_hi$1( + c0_hi, c0_lo, + c1_hi, c1_lo, + c2_hi, c2_lo, + c3_hi, c3_lo); + W[i + 1] = sum64_4_lo$1( + c0_hi, c0_lo, + c1_hi, c1_lo, + c2_hi, c2_lo, + c3_hi, c3_lo); + } +}; + +SHA512.prototype._update = function _update(msg, start) { + this._prepareBlock(msg, start); + + var W = this.W; + + var ah = this.h[0]; + var al = this.h[1]; + var bh = this.h[2]; + var bl = this.h[3]; + var ch = this.h[4]; + var cl = this.h[5]; + var dh = this.h[6]; + var dl = this.h[7]; + var eh = this.h[8]; + var el = this.h[9]; + var fh = this.h[10]; + var fl = this.h[11]; + var gh = this.h[12]; + var gl = this.h[13]; + var hh = this.h[14]; + var hl = this.h[15]; + + minimalisticAssert(this.k.length === W.length); + for (var i = 0; i < W.length; i += 2) { + var c0_hi = hh; + var c0_lo = hl; + var c1_hi = s1_512_hi(eh, el); + var c1_lo = s1_512_lo(eh, el); + var c2_hi = ch64_hi(eh, el, fh, fl, gh); + var c2_lo = ch64_lo(eh, el, fh, fl, gh, gl); + var c3_hi = this.k[i]; + var c3_lo = this.k[i + 1]; + var c4_hi = W[i]; + var c4_lo = W[i + 1]; + + var T1_hi = sum64_5_hi$1( + c0_hi, c0_lo, + c1_hi, c1_lo, + c2_hi, c2_lo, + c3_hi, c3_lo, + c4_hi, c4_lo); + var T1_lo = sum64_5_lo$1( + c0_hi, c0_lo, + c1_hi, c1_lo, + c2_hi, c2_lo, + c3_hi, c3_lo, + c4_hi, c4_lo); + + c0_hi = s0_512_hi(ah, al); + c0_lo = s0_512_lo(ah, al); + c1_hi = maj64_hi(ah, al, bh, bl, ch); + c1_lo = maj64_lo(ah, al, bh, bl, ch, cl); + + var T2_hi = sum64_hi$1(c0_hi, c0_lo, c1_hi, c1_lo); + var T2_lo = sum64_lo$1(c0_hi, c0_lo, c1_hi, c1_lo); + + hh = gh; + hl = gl; + + gh = fh; + gl = fl; + + fh = eh; + fl = el; + + eh = sum64_hi$1(dh, dl, T1_hi, T1_lo); + el = sum64_lo$1(dl, dl, T1_hi, T1_lo); + + dh = ch; + dl = cl; + + ch = bh; + cl = bl; + + bh = ah; + bl = al; + + ah = sum64_hi$1(T1_hi, T1_lo, T2_hi, T2_lo); + al = sum64_lo$1(T1_hi, T1_lo, T2_hi, T2_lo); + } + + sum64$1(this.h, 0, ah, al); + sum64$1(this.h, 2, bh, bl); + sum64$1(this.h, 4, ch, cl); + sum64$1(this.h, 6, dh, dl); + sum64$1(this.h, 8, eh, el); + sum64$1(this.h, 10, fh, fl); + sum64$1(this.h, 12, gh, gl); + sum64$1(this.h, 14, hh, hl); +}; + +SHA512.prototype._digest = function digest(enc) { + if (enc === 'hex') + return utils.toHex32(this.h, 'big'); + else + return utils.split32(this.h, 'big'); +}; + +function ch64_hi(xh, xl, yh, yl, zh) { + var r = (xh & yh) ^ ((~xh) & zh); + if (r < 0) + r += 0x100000000; + return r; +} + +function ch64_lo(xh, xl, yh, yl, zh, zl) { + var r = (xl & yl) ^ ((~xl) & zl); + if (r < 0) + r += 0x100000000; + return r; +} + +function maj64_hi(xh, xl, yh, yl, zh) { + var r = (xh & yh) ^ (xh & zh) ^ (yh & zh); + if (r < 0) + r += 0x100000000; + return r; +} + +function maj64_lo(xh, xl, yh, yl, zh, zl) { + var r = (xl & yl) ^ (xl & zl) ^ (yl & zl); + if (r < 0) + r += 0x100000000; + return r; +} + +function s0_512_hi(xh, xl) { + var c0_hi = rotr64_hi$1(xh, xl, 28); + var c1_hi = rotr64_hi$1(xl, xh, 2); // 34 + var c2_hi = rotr64_hi$1(xl, xh, 7); // 39 + + var r = c0_hi ^ c1_hi ^ c2_hi; + if (r < 0) + r += 0x100000000; + return r; +} + +function s0_512_lo(xh, xl) { + var c0_lo = rotr64_lo$1(xh, xl, 28); + var c1_lo = rotr64_lo$1(xl, xh, 2); // 34 + var c2_lo = rotr64_lo$1(xl, xh, 7); // 39 + + var r = c0_lo ^ c1_lo ^ c2_lo; + if (r < 0) + r += 0x100000000; + return r; +} + +function s1_512_hi(xh, xl) { + var c0_hi = rotr64_hi$1(xh, xl, 14); + var c1_hi = rotr64_hi$1(xh, xl, 18); + var c2_hi = rotr64_hi$1(xl, xh, 9); // 41 + + var r = c0_hi ^ c1_hi ^ c2_hi; + if (r < 0) + r += 0x100000000; + return r; +} + +function s1_512_lo(xh, xl) { + var c0_lo = rotr64_lo$1(xh, xl, 14); + var c1_lo = rotr64_lo$1(xh, xl, 18); + var c2_lo = rotr64_lo$1(xl, xh, 9); // 41 + + var r = c0_lo ^ c1_lo ^ c2_lo; + if (r < 0) + r += 0x100000000; + return r; +} + +function g0_512_hi(xh, xl) { + var c0_hi = rotr64_hi$1(xh, xl, 1); + var c1_hi = rotr64_hi$1(xh, xl, 8); + var c2_hi = shr64_hi$1(xh, xl, 7); + + var r = c0_hi ^ c1_hi ^ c2_hi; + if (r < 0) + r += 0x100000000; + return r; +} + +function g0_512_lo(xh, xl) { + var c0_lo = rotr64_lo$1(xh, xl, 1); + var c1_lo = rotr64_lo$1(xh, xl, 8); + var c2_lo = shr64_lo$1(xh, xl, 7); + + var r = c0_lo ^ c1_lo ^ c2_lo; + if (r < 0) + r += 0x100000000; + return r; +} + +function g1_512_hi(xh, xl) { + var c0_hi = rotr64_hi$1(xh, xl, 19); + var c1_hi = rotr64_hi$1(xl, xh, 29); // 61 + var c2_hi = shr64_hi$1(xh, xl, 6); + + var r = c0_hi ^ c1_hi ^ c2_hi; + if (r < 0) + r += 0x100000000; + return r; +} + +function g1_512_lo(xh, xl) { + var c0_lo = rotr64_lo$1(xh, xl, 19); + var c1_lo = rotr64_lo$1(xl, xh, 29); // 61 + var c2_lo = shr64_lo$1(xh, xl, 6); + + var r = c0_lo ^ c1_lo ^ c2_lo; + if (r < 0) + r += 0x100000000; + return r; +} + +function SHA384() { + if (!(this instanceof SHA384)) + return new SHA384(); + + _512.call(this); + this.h = [ + 0xcbbb9d5d, 0xc1059ed8, + 0x629a292a, 0x367cd507, + 0x9159015a, 0x3070dd17, + 0x152fecd8, 0xf70e5939, + 0x67332667, 0xffc00b31, + 0x8eb44a87, 0x68581511, + 0xdb0c2e0d, 0x64f98fa7, + 0x47b5481d, 0xbefa4fa4 ]; +} +utils.inherits(SHA384, _512); +var _384 = SHA384; + +SHA384.blockSize = 1024; +SHA384.outSize = 384; +SHA384.hmacStrength = 192; +SHA384.padLength = 128; + +SHA384.prototype._digest = function digest(enc) { + if (enc === 'hex') + return utils.toHex32(this.h.slice(0, 12), 'big'); + else + return utils.split32(this.h.slice(0, 12), 'big'); +}; + +var rotl32$1 = utils.rotl32; +var sum32$2 = utils.sum32; +var sum32_3$1 = utils.sum32_3; +var sum32_4$2 = utils.sum32_4; +var BlockHash$3 = common.BlockHash; + +function RIPEMD160() { + if (!(this instanceof RIPEMD160)) + return new RIPEMD160(); + + BlockHash$3.call(this); + + this.h = [ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 ]; + this.endian = 'little'; +} +utils.inherits(RIPEMD160, BlockHash$3); +var ripemd160 = RIPEMD160; + +RIPEMD160.blockSize = 512; +RIPEMD160.outSize = 160; +RIPEMD160.hmacStrength = 192; +RIPEMD160.padLength = 64; + +RIPEMD160.prototype._update = function update(msg, start) { + var A = this.h[0]; + var B = this.h[1]; + var C = this.h[2]; + var D = this.h[3]; + var E = this.h[4]; + var Ah = A; + var Bh = B; + var Ch = C; + var Dh = D; + var Eh = E; + for (var j = 0; j < 80; j++) { + var T = sum32$2( + rotl32$1( + sum32_4$2(A, f(j, B, C, D), msg[r[j] + start], K(j)), + s[j]), + E); + A = E; + E = D; + D = rotl32$1(C, 10); + C = B; + B = T; + T = sum32$2( + rotl32$1( + sum32_4$2(Ah, f(79 - j, Bh, Ch, Dh), msg[rh[j] + start], Kh(j)), + sh[j]), + Eh); + Ah = Eh; + Eh = Dh; + Dh = rotl32$1(Ch, 10); + Ch = Bh; + Bh = T; + } + T = sum32_3$1(this.h[1], C, Dh); + this.h[1] = sum32_3$1(this.h[2], D, Eh); + this.h[2] = sum32_3$1(this.h[3], E, Ah); + this.h[3] = sum32_3$1(this.h[4], A, Bh); + this.h[4] = sum32_3$1(this.h[0], B, Ch); + this.h[0] = T; +}; + +RIPEMD160.prototype._digest = function digest(enc) { + if (enc === 'hex') + return utils.toHex32(this.h, 'little'); + else + return utils.split32(this.h, 'little'); +}; + +function f(j, x, y, z) { + if (j <= 15) + return x ^ y ^ z; + else if (j <= 31) + return (x & y) | ((~x) & z); + else if (j <= 47) + return (x | (~y)) ^ z; + else if (j <= 63) + return (x & z) | (y & (~z)); + else + return x ^ (y | (~z)); +} + +function K(j) { + if (j <= 15) + return 0x00000000; + else if (j <= 31) + return 0x5a827999; + else if (j <= 47) + return 0x6ed9eba1; + else if (j <= 63) + return 0x8f1bbcdc; + else + return 0xa953fd4e; +} + +function Kh(j) { + if (j <= 15) + return 0x50a28be6; + else if (j <= 31) + return 0x5c4dd124; + else if (j <= 47) + return 0x6d703ef3; + else if (j <= 63) + return 0x7a6d76e9; + else + return 0x00000000; +} + +var r = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, + 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, + 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, + 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 +]; + +var rh = [ + 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, + 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, + 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, + 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, + 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 +]; + +var s = [ + 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, + 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, + 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, + 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, + 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 +]; + +var sh = [ + 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, + 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, + 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, + 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, + 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 +]; + +var ripemd = { + ripemd160: ripemd160 +}; + +/** + * A fast MD5 JavaScript implementation + * Copyright (c) 2012 Joseph Myers + * http://www.myersdaily.org/joseph/javascript/md5-text.html + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purposes and without + * fee is hereby granted provided that this copyright notice + * appears in all copies. + * + * Of course, this soft is provided "as is" without express or implied + * warranty of any kind. + */ + +// MD5 Digest +async function md5(entree) { + const digest = md51(util.uint8ArrayToString(entree)); + return util.hexToUint8Array(hex(digest)); +} + +function md5cycle(x, k) { + let a = x[0]; + let b = x[1]; + let c = x[2]; + let d = x[3]; + + a = ff(a, b, c, d, k[0], 7, -680876936); + d = ff(d, a, b, c, k[1], 12, -389564586); + c = ff(c, d, a, b, k[2], 17, 606105819); + b = ff(b, c, d, a, k[3], 22, -1044525330); + a = ff(a, b, c, d, k[4], 7, -176418897); + d = ff(d, a, b, c, k[5], 12, 1200080426); + c = ff(c, d, a, b, k[6], 17, -1473231341); + b = ff(b, c, d, a, k[7], 22, -45705983); + a = ff(a, b, c, d, k[8], 7, 1770035416); + d = ff(d, a, b, c, k[9], 12, -1958414417); + c = ff(c, d, a, b, k[10], 17, -42063); + b = ff(b, c, d, a, k[11], 22, -1990404162); + a = ff(a, b, c, d, k[12], 7, 1804603682); + d = ff(d, a, b, c, k[13], 12, -40341101); + c = ff(c, d, a, b, k[14], 17, -1502002290); + b = ff(b, c, d, a, k[15], 22, 1236535329); + + a = gg(a, b, c, d, k[1], 5, -165796510); + d = gg(d, a, b, c, k[6], 9, -1069501632); + c = gg(c, d, a, b, k[11], 14, 643717713); + b = gg(b, c, d, a, k[0], 20, -373897302); + a = gg(a, b, c, d, k[5], 5, -701558691); + d = gg(d, a, b, c, k[10], 9, 38016083); + c = gg(c, d, a, b, k[15], 14, -660478335); + b = gg(b, c, d, a, k[4], 20, -405537848); + a = gg(a, b, c, d, k[9], 5, 568446438); + d = gg(d, a, b, c, k[14], 9, -1019803690); + c = gg(c, d, a, b, k[3], 14, -187363961); + b = gg(b, c, d, a, k[8], 20, 1163531501); + a = gg(a, b, c, d, k[13], 5, -1444681467); + d = gg(d, a, b, c, k[2], 9, -51403784); + c = gg(c, d, a, b, k[7], 14, 1735328473); + b = gg(b, c, d, a, k[12], 20, -1926607734); + + a = hh(a, b, c, d, k[5], 4, -378558); + d = hh(d, a, b, c, k[8], 11, -2022574463); + c = hh(c, d, a, b, k[11], 16, 1839030562); + b = hh(b, c, d, a, k[14], 23, -35309556); + a = hh(a, b, c, d, k[1], 4, -1530992060); + d = hh(d, a, b, c, k[4], 11, 1272893353); + c = hh(c, d, a, b, k[7], 16, -155497632); + b = hh(b, c, d, a, k[10], 23, -1094730640); + a = hh(a, b, c, d, k[13], 4, 681279174); + d = hh(d, a, b, c, k[0], 11, -358537222); + c = hh(c, d, a, b, k[3], 16, -722521979); + b = hh(b, c, d, a, k[6], 23, 76029189); + a = hh(a, b, c, d, k[9], 4, -640364487); + d = hh(d, a, b, c, k[12], 11, -421815835); + c = hh(c, d, a, b, k[15], 16, 530742520); + b = hh(b, c, d, a, k[2], 23, -995338651); + + a = ii(a, b, c, d, k[0], 6, -198630844); + d = ii(d, a, b, c, k[7], 10, 1126891415); + c = ii(c, d, a, b, k[14], 15, -1416354905); + b = ii(b, c, d, a, k[5], 21, -57434055); + a = ii(a, b, c, d, k[12], 6, 1700485571); + d = ii(d, a, b, c, k[3], 10, -1894986606); + c = ii(c, d, a, b, k[10], 15, -1051523); + b = ii(b, c, d, a, k[1], 21, -2054922799); + a = ii(a, b, c, d, k[8], 6, 1873313359); + d = ii(d, a, b, c, k[15], 10, -30611744); + c = ii(c, d, a, b, k[6], 15, -1560198380); + b = ii(b, c, d, a, k[13], 21, 1309151649); + a = ii(a, b, c, d, k[4], 6, -145523070); + d = ii(d, a, b, c, k[11], 10, -1120210379); + c = ii(c, d, a, b, k[2], 15, 718787259); + b = ii(b, c, d, a, k[9], 21, -343485551); + + x[0] = add32(a, x[0]); + x[1] = add32(b, x[1]); + x[2] = add32(c, x[2]); + x[3] = add32(d, x[3]); +} + +function cmn(q, a, b, x, s, t) { + a = add32(add32(a, q), add32(x, t)); + return add32((a << s) | (a >>> (32 - s)), b); +} + +function ff(a, b, c, d, x, s, t) { + return cmn((b & c) | ((~b) & d), a, b, x, s, t); +} + +function gg(a, b, c, d, x, s, t) { + return cmn((b & d) | (c & (~d)), a, b, x, s, t); +} + +function hh(a, b, c, d, x, s, t) { + return cmn(b ^ c ^ d, a, b, x, s, t); +} + +function ii(a, b, c, d, x, s, t) { + return cmn(c ^ (b | (~d)), a, b, x, s, t); +} + +function md51(s) { + const n = s.length; + const state = [1732584193, -271733879, -1732584194, 271733878]; + let i; + for (i = 64; i <= s.length; i += 64) { + md5cycle(state, md5blk(s.substring(i - 64, i))); + } + s = s.substring(i - 64); + const tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + for (i = 0; i < s.length; i++) { + tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3); + } + tail[i >> 2] |= 0x80 << ((i % 4) << 3); + if (i > 55) { + md5cycle(state, tail); + for (i = 0; i < 16; i++) { + tail[i] = 0; + } + } + tail[14] = n * 8; + md5cycle(state, tail); + return state; +} + +/* there needs to be support for Unicode here, + * unless we pretend that we can redefine the MD-5 + * algorithm for multi-byte characters (perhaps + * by adding every four 16-bit characters and + * shortening the sum to 32 bits). Otherwise + * I suggest performing MD-5 as if every character + * was two bytes--e.g., 0040 0025 = @%--but then + * how will an ordinary MD-5 sum be matched? + * There is no way to standardize text to something + * like UTF-8 before transformation; speed cost is + * utterly prohibitive. The JavaScript standard + * itself needs to look at this: it should start + * providing access to strings as preformed UTF-8 + * 8-bit unsigned value arrays. + */ +function md5blk(s) { /* I figured global was faster. */ + const md5blks = []; + let i; /* Andy King said do it this way. */ + for (i = 0; i < 64; i += 4) { + md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << + 24); + } + return md5blks; +} + +const hex_chr = '0123456789abcdef'.split(''); + +function rhex(n) { + let s = ''; + let j = 0; + for (; j < 4; j++) { + s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F]; + } + return s; +} + +function hex(x) { + for (let i = 0; i < x.length; i++) { + x[i] = rhex(x[i]); + } + return x.join(''); +} + +/* this function is much faster, +so if possible we use it. Some IEs +are the only ones I know of that +need the idiotic second function, +generated by an if clause. */ + +function add32(a, b) { + return (a + b) & 0xFFFFFFFF; +} + +/** + * @fileoverview Provides an interface to hashing functions available in Node.js or external libraries. + * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} + * @see {@link https://github.com/indutny/hash.js|hash.js} + * @module crypto/hash + * @private + */ + +const webCrypto = util.getWebCrypto(); +const nodeCrypto = util.getNodeCrypto(); + +function nodeHash(type) { + return async function (data) { + const shasum = nodeCrypto.createHash(type); + return transform(data, value => { + shasum.update(value); + }, () => new Uint8Array(shasum.digest())); + }; +} + +function hashjsHash(hash, webCryptoHash) { + return async function(data, config = defaultConfig) { + if (isArrayStream(data)) { + data = await readToEnd(data); + } + if (!util.isStream(data) && webCrypto && webCryptoHash && data.length >= config.minBytesForWebCrypto) { + return new Uint8Array(await webCrypto.digest(webCryptoHash, data)); + } + const hashInstance = hash(); + return transform(data, value => { + hashInstance.update(value); + }, () => new Uint8Array(hashInstance.digest())); + }; +} + +function asmcryptoHash(hash, webCryptoHash) { + return async function(data, config = defaultConfig) { + if (isArrayStream(data)) { + data = await readToEnd(data); + } + if (util.isStream(data)) { + const hashInstance = new hash(); + return transform(data, value => { + hashInstance.process(value); + }, () => hashInstance.finish().result); + } else if (webCrypto && webCryptoHash && data.length >= config.minBytesForWebCrypto) { + return new Uint8Array(await webCrypto.digest(webCryptoHash, data)); + } else { + return hash.bytes(data); + } + }; +} + +let hashFunctions; +if (nodeCrypto) { // Use Node native crypto for all hash functions + hashFunctions = { + md5: nodeHash('md5'), + sha1: nodeHash('sha1'), + sha224: nodeHash('sha224'), + sha256: nodeHash('sha256'), + sha384: nodeHash('sha384'), + sha512: nodeHash('sha512'), + ripemd: nodeHash('ripemd160') + }; +} else { // Use JS fallbacks + hashFunctions = { + md5: md5, + sha1: asmcryptoHash(Sha1, (!navigator.userAgent || navigator.userAgent.indexOf('Edge') === -1) && 'SHA-1'), + sha224: hashjsHash(_224), + sha256: asmcryptoHash(Sha256, 'SHA-256'), + sha384: hashjsHash(_384, 'SHA-384'), + sha512: hashjsHash(_512, 'SHA-512'), // asmcrypto sha512 is huge. + ripemd: hashjsHash(ripemd160) + }; +} + +var hash = { + + /** @see module:md5 */ + md5: hashFunctions.md5, + /** @see asmCrypto */ + sha1: hashFunctions.sha1, + /** @see hash.js */ + sha224: hashFunctions.sha224, + /** @see asmCrypto */ + sha256: hashFunctions.sha256, + /** @see hash.js */ + sha384: hashFunctions.sha384, + /** @see asmCrypto */ + sha512: hashFunctions.sha512, + /** @see hash.js */ + ripemd: hashFunctions.ripemd, + + /** + * Create a hash on the specified data using the specified algorithm + * @param {module:enums.hash} algo - Hash algorithm type (see {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}) + * @param {Uint8Array} data - Data to be hashed + * @returns {Promise} Hash value. + */ + digest: function(algo, data) { + switch (algo) { + case enums.hash.md5: + return this.md5(data); + case enums.hash.sha1: + return this.sha1(data); + case enums.hash.ripemd: + return this.ripemd(data); + case enums.hash.sha256: + return this.sha256(data); + case enums.hash.sha384: + return this.sha384(data); + case enums.hash.sha512: + return this.sha512(data); + case enums.hash.sha224: + return this.sha224(data); + default: + throw new Error('Invalid hash function.'); + } + }, + + /** + * Returns the hash size in bytes of the specified hash algorithm type + * @param {module:enums.hash} algo - Hash algorithm type (See {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}) + * @returns {Integer} Size in bytes of the resulting hash. + */ + getHashByteLength: function(algo) { + switch (algo) { + case enums.hash.md5: + return 16; + case enums.hash.sha1: + case enums.hash.ripemd: + return 20; + case enums.hash.sha256: + return 32; + case enums.hash.sha384: + return 48; + case enums.hash.sha512: + return 64; + case enums.hash.sha224: + return 28; + default: + throw new Error('Invalid hash algorithm.'); + } + } +}; + +class AES_CFB { + static encrypt(data, key, iv) { + return new AES_CFB(key, iv).encrypt(data); + } + static decrypt(data, key, iv) { + return new AES_CFB(key, iv).decrypt(data); + } + constructor(key, iv, aes) { + this.aes = aes ? aes : new AES(key, iv, true, 'CFB'); + delete this.aes.padding; + } + encrypt(data) { + const r1 = this.aes.AES_Encrypt_process(data); + const r2 = this.aes.AES_Encrypt_finish(); + return joinBytes(r1, r2); + } + decrypt(data) { + const r1 = this.aes.AES_Decrypt_process(data); + const r2 = this.aes.AES_Decrypt_finish(); + return joinBytes(r1, r2); + } +} + +// Modified by ProtonTech AG + +const webCrypto$1 = util.getWebCrypto(); +const nodeCrypto$1 = util.getNodeCrypto(); + +const knownAlgos = nodeCrypto$1 ? nodeCrypto$1.getCiphers() : []; +const nodeAlgos = { + idea: knownAlgos.includes('idea-cfb') ? 'idea-cfb' : undefined, /* Unused, not implemented */ + tripledes: knownAlgos.includes('des-ede3-cfb') ? 'des-ede3-cfb' : undefined, + cast5: knownAlgos.includes('cast5-cfb') ? 'cast5-cfb' : undefined, + blowfish: knownAlgos.includes('bf-cfb') ? 'bf-cfb' : undefined, + aes128: knownAlgos.includes('aes-128-cfb') ? 'aes-128-cfb' : undefined, + aes192: knownAlgos.includes('aes-192-cfb') ? 'aes-192-cfb' : undefined, + aes256: knownAlgos.includes('aes-256-cfb') ? 'aes-256-cfb' : undefined + /* twofish is not implemented in OpenSSL */ +}; + +/** + * CFB encryption + * @param {enums.symmetric} algo - block cipher algorithm + * @param {Uint8Array} key + * @param {MaybeStream} plaintext + * @param {Uint8Array} iv + * @param {Object} config - full configuration, defaults to openpgp.config + * @returns MaybeStream + */ +async function encrypt(algo, key, plaintext, iv, config) { + const algoName = enums.read(enums.symmetric, algo); + if (util.getNodeCrypto() && nodeAlgos[algoName]) { // Node crypto library. + return nodeEncrypt(algo, key, plaintext, iv); + } + if (algoName.substr(0, 3) === 'aes') { + return aesEncrypt(algo, key, plaintext, iv, config); + } + + const cipherfn = new cipher[algoName](key); + const block_size = cipherfn.blockSize; + + const blockc = iv.slice(); + let pt = new Uint8Array(); + const process = chunk => { + if (chunk) { + pt = util.concatUint8Array([pt, chunk]); + } + const ciphertext = new Uint8Array(pt.length); + let i; + let j = 0; + while (chunk ? pt.length >= block_size : pt.length) { + const encblock = cipherfn.encrypt(blockc); + for (i = 0; i < block_size; i++) { + blockc[i] = pt[i] ^ encblock[i]; + ciphertext[j++] = blockc[i]; + } + pt = pt.subarray(block_size); + } + return ciphertext.subarray(0, j); + }; + return transform(plaintext, process, process); +} + +/** + * CFB decryption + * @param {enums.symmetric} algo - block cipher algorithm + * @param {Uint8Array} key + * @param {MaybeStream} ciphertext + * @param {Uint8Array} iv + * @returns MaybeStream + */ +async function decrypt(algo, key, ciphertext, iv) { + const algoName = enums.read(enums.symmetric, algo); + if (util.getNodeCrypto() && nodeAlgos[algoName]) { // Node crypto library. + return nodeDecrypt(algo, key, ciphertext, iv); + } + if (algoName.substr(0, 3) === 'aes') { + return aesDecrypt(algo, key, ciphertext, iv); + } + + const cipherfn = new cipher[algoName](key); + const block_size = cipherfn.blockSize; + + let blockp = iv; + let ct = new Uint8Array(); + const process = chunk => { + if (chunk) { + ct = util.concatUint8Array([ct, chunk]); + } + const plaintext = new Uint8Array(ct.length); + let i; + let j = 0; + while (chunk ? ct.length >= block_size : ct.length) { + const decblock = cipherfn.encrypt(blockp); + blockp = ct; + for (i = 0; i < block_size; i++) { + plaintext[j++] = blockp[i] ^ decblock[i]; + } + ct = ct.subarray(block_size); + } + return plaintext.subarray(0, j); + }; + return transform(ciphertext, process, process); +} + +function aesEncrypt(algo, key, pt, iv, config) { + if ( + util.getWebCrypto() && + key.length !== 24 && // Chrome doesn't support 192 bit keys, see https://www.chromium.org/blink/webcrypto#TOC-AES-support + !util.isStream(pt) && + pt.length >= 3000 * config.minBytesForWebCrypto // Default to a 3MB minimum. Chrome is pretty slow for small messages, see: https://bugs.chromium.org/p/chromium/issues/detail?id=701188#c2 + ) { // Web Crypto + return webEncrypt(algo, key, pt, iv); + } + // asm.js fallback + const cfb = new AES_CFB(key, iv); + return transform(pt, value => cfb.aes.AES_Encrypt_process(value), () => cfb.aes.AES_Encrypt_finish()); +} + +function aesDecrypt(algo, key, ct, iv) { + if (util.isStream(ct)) { + const cfb = new AES_CFB(key, iv); + return transform(ct, value => cfb.aes.AES_Decrypt_process(value), () => cfb.aes.AES_Decrypt_finish()); + } + return AES_CFB.decrypt(ct, key, iv); +} + +function xorMut(a, b) { + for (let i = 0; i < a.length; i++) { + a[i] = a[i] ^ b[i]; + } +} + +async function webEncrypt(algo, key, pt, iv) { + const ALGO = 'AES-CBC'; + const _key = await webCrypto$1.importKey('raw', key, { name: ALGO }, false, ['encrypt']); + const { blockSize } = crypto.getCipher(algo); + const cbc_pt = util.concatUint8Array([new Uint8Array(blockSize), pt]); + const ct = new Uint8Array(await webCrypto$1.encrypt({ name: ALGO, iv }, _key, cbc_pt)).subarray(0, pt.length); + xorMut(ct, pt); + return ct; +} + +function nodeEncrypt(algo, key, pt, iv) { + const algoName = enums.read(enums.symmetric, algo); + const cipherObj = new nodeCrypto$1.createCipheriv(nodeAlgos[algoName], key, iv); + return transform(pt, value => new Uint8Array(cipherObj.update(value))); +} + +function nodeDecrypt(algo, key, ct, iv) { + const algoName = enums.read(enums.symmetric, algo); + const decipherObj = new nodeCrypto$1.createDecipheriv(nodeAlgos[algoName], key, iv); + return transform(ct, value => new Uint8Array(decipherObj.update(value))); +} + +var cfb = /*#__PURE__*/Object.freeze({ + __proto__: null, + encrypt: encrypt, + decrypt: decrypt +}); + +class AES_CTR { + static encrypt(data, key, nonce) { + return new AES_CTR(key, nonce).encrypt(data); + } + static decrypt(data, key, nonce) { + return new AES_CTR(key, nonce).encrypt(data); + } + constructor(key, nonce, aes) { + this.aes = aes ? aes : new AES(key, undefined, false, 'CTR'); + delete this.aes.padding; + this.AES_CTR_set_options(nonce); + } + encrypt(data) { + const r1 = this.aes.AES_Encrypt_process(data); + const r2 = this.aes.AES_Encrypt_finish(); + return joinBytes(r1, r2); + } + decrypt(data) { + const r1 = this.aes.AES_Encrypt_process(data); + const r2 = this.aes.AES_Encrypt_finish(); + return joinBytes(r1, r2); + } + AES_CTR_set_options(nonce, counter, size) { + let { asm } = this.aes.acquire_asm(); + if (size !== undefined) { + if (size < 8 || size > 48) + throw new IllegalArgumentError('illegal counter size'); + let mask = Math.pow(2, size) - 1; + asm.set_mask(0, 0, (mask / 0x100000000) | 0, mask | 0); + } + else { + size = 48; + asm.set_mask(0, 0, 0xffff, 0xffffffff); + } + if (nonce !== undefined) { + let len = nonce.length; + if (!len || len > 16) + throw new IllegalArgumentError('illegal nonce size'); + let view = new DataView(new ArrayBuffer(16)); + new Uint8Array(view.buffer).set(nonce); + asm.set_nonce(view.getUint32(0), view.getUint32(4), view.getUint32(8), view.getUint32(12)); + } + else { + throw new Error('nonce is required'); + } + if (counter !== undefined) { + if (counter < 0 || counter >= Math.pow(2, size)) + throw new IllegalArgumentError('illegal counter value'); + asm.set_counter(0, 0, (counter / 0x100000000) | 0, counter | 0); + } + } +} + +class AES_CBC { + static encrypt(data, key, padding = true, iv) { + return new AES_CBC(key, iv, padding).encrypt(data); + } + static decrypt(data, key, padding = true, iv) { + return new AES_CBC(key, iv, padding).decrypt(data); + } + constructor(key, iv, padding = true, aes) { + this.aes = aes ? aes : new AES(key, iv, padding, 'CBC'); + } + encrypt(data) { + const r1 = this.aes.AES_Encrypt_process(data); + const r2 = this.aes.AES_Encrypt_finish(); + return joinBytes(r1, r2); + } + decrypt(data) { + const r1 = this.aes.AES_Decrypt_process(data); + const r2 = this.aes.AES_Decrypt_finish(); + return joinBytes(r1, r2); + } +} + +/** + * @fileoverview This module implements AES-CMAC on top of + * native AES-CBC using either the WebCrypto API or Node.js' crypto API. + * @module crypto/cmac + * @private + */ + +const webCrypto$2 = util.getWebCrypto(); +const nodeCrypto$2 = util.getNodeCrypto(); + + +/** + * This implementation of CMAC is based on the description of OMAC in + * http://web.cs.ucdavis.edu/~rogaway/papers/eax.pdf. As per that + * document: + * + * We have made a small modification to the OMAC algorithm as it was + * originally presented, changing one of its two constants. + * Specifically, the constant 4 at line 85 was the constant 1/2 (the + * multiplicative inverse of 2) in the original definition of OMAC [14]. + * The OMAC authors indicate that they will promulgate this modification + * [15], which slightly simplifies implementations. + */ + +const blockLength = 16; + + +/** + * xor `padding` into the end of `data`. This function implements "the + * operation xor→ [which] xors the shorter string into the end of longer + * one". Since data is always as least as long as padding, we can + * simplify the implementation. + * @param {Uint8Array} data + * @param {Uint8Array} padding + */ +function rightXORMut(data, padding) { + const offset = data.length - blockLength; + for (let i = 0; i < blockLength; i++) { + data[i + offset] ^= padding[i]; + } + return data; +} + +function pad(data, padding, padding2) { + // if |M| in {n, 2n, 3n, ...} + if (data.length && data.length % blockLength === 0) { + // then return M xor→ B, + return rightXORMut(data, padding); + } + // else return (M || 10^(n−1−(|M| mod n))) xor→ P + const padded = new Uint8Array(data.length + (blockLength - data.length % blockLength)); + padded.set(data); + padded[data.length] = 0b10000000; + return rightXORMut(padded, padding2); +} + +const zeroBlock = new Uint8Array(blockLength); + +async function CMAC(key) { + const cbc = await CBC(key); + + // L ← E_K(0^n); B ← 2L; P ← 4L + const padding = util.double(await cbc(zeroBlock)); + const padding2 = util.double(padding); + + return async function(data) { + // return CBC_K(pad(M; B, P)) + return (await cbc(pad(data, padding, padding2))).subarray(-blockLength); + }; +} + +async function CBC(key) { + if (util.getWebCrypto() && key.length !== 24) { // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support + key = await webCrypto$2.importKey('raw', key, { name: 'AES-CBC', length: key.length * 8 }, false, ['encrypt']); + return async function(pt) { + const ct = await webCrypto$2.encrypt({ name: 'AES-CBC', iv: zeroBlock, length: blockLength * 8 }, key, pt); + return new Uint8Array(ct).subarray(0, ct.byteLength - blockLength); + }; + } + if (util.getNodeCrypto()) { // Node crypto library + return async function(pt) { + const en = new nodeCrypto$2.createCipheriv('aes-' + (key.length * 8) + '-cbc', key, zeroBlock); + const ct = en.update(pt); + return new Uint8Array(ct); + }; + } + // asm.js fallback + return async function(pt) { + return AES_CBC.encrypt(pt, key, false, zeroBlock); + }; +} + +// OpenPGP.js - An OpenPGP implementation in javascript + +const webCrypto$3 = util.getWebCrypto(); +const nodeCrypto$3 = util.getNodeCrypto(); +const Buffer$1 = util.getNodeBuffer(); + + +const blockLength$1 = 16; +const ivLength = blockLength$1; +const tagLength = blockLength$1; + +const zero = new Uint8Array(blockLength$1); +const one = new Uint8Array(blockLength$1); one[blockLength$1 - 1] = 1; +const two = new Uint8Array(blockLength$1); two[blockLength$1 - 1] = 2; + +async function OMAC(key) { + const cmac = await CMAC(key); + return function(t, message) { + return cmac(util.concatUint8Array([t, message])); + }; +} + +async function CTR(key) { + if ( + util.getWebCrypto() && + key.length !== 24 && // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support + (!navigator.userAgent || navigator.userAgent.indexOf('Edge') === -1) + ) { + key = await webCrypto$3.importKey('raw', key, { name: 'AES-CTR', length: key.length * 8 }, false, ['encrypt']); + return async function(pt, iv) { + const ct = await webCrypto$3.encrypt({ name: 'AES-CTR', counter: iv, length: blockLength$1 * 8 }, key, pt); + return new Uint8Array(ct); + }; + } + if (util.getNodeCrypto()) { // Node crypto library + return async function(pt, iv) { + const en = new nodeCrypto$3.createCipheriv('aes-' + (key.length * 8) + '-ctr', key, iv); + const ct = Buffer$1.concat([en.update(pt), en.final()]); + return new Uint8Array(ct); + }; + } + // asm.js fallback + return async function(pt, iv) { + return AES_CTR.encrypt(pt, key, iv); + }; +} + + +/** + * Class to en/decrypt using EAX mode. + * @param {enums.symmetric} cipher - The symmetric cipher algorithm to use + * @param {Uint8Array} key - The encryption key + */ +async function EAX(cipher, key) { + if (cipher !== enums.symmetric.aes128 && + cipher !== enums.symmetric.aes192 && + cipher !== enums.symmetric.aes256) { + throw new Error('EAX mode supports only AES cipher'); + } + + const [ + omac, + ctr + ] = await Promise.all([ + OMAC(key), + CTR(key) + ]); + + return { + /** + * Encrypt plaintext input. + * @param {Uint8Array} plaintext - The cleartext input to be encrypted + * @param {Uint8Array} nonce - The nonce (16 bytes) + * @param {Uint8Array} adata - Associated data to sign + * @returns {Promise} The ciphertext output. + */ + encrypt: async function(plaintext, nonce, adata) { + const [ + omacNonce, + omacAdata + ] = await Promise.all([ + omac(zero, nonce), + omac(one, adata) + ]); + const ciphered = await ctr(plaintext, omacNonce); + const omacCiphered = await omac(two, ciphered); + const tag = omacCiphered; // Assumes that omac(*).length === tagLength. + for (let i = 0; i < tagLength; i++) { + tag[i] ^= omacAdata[i] ^ omacNonce[i]; + } + return util.concatUint8Array([ciphered, tag]); + }, + + /** + * Decrypt ciphertext input. + * @param {Uint8Array} ciphertext - The ciphertext input to be decrypted + * @param {Uint8Array} nonce - The nonce (16 bytes) + * @param {Uint8Array} adata - Associated data to verify + * @returns {Promise} The plaintext output. + */ + decrypt: async function(ciphertext, nonce, adata) { + if (ciphertext.length < tagLength) throw new Error('Invalid EAX ciphertext'); + const ciphered = ciphertext.subarray(0, -tagLength); + const ctTag = ciphertext.subarray(-tagLength); + const [ + omacNonce, + omacAdata, + omacCiphered + ] = await Promise.all([ + omac(zero, nonce), + omac(one, adata), + omac(two, ciphered) + ]); + const tag = omacCiphered; // Assumes that omac(*).length === tagLength. + for (let i = 0; i < tagLength; i++) { + tag[i] ^= omacAdata[i] ^ omacNonce[i]; + } + if (!util.equalsUint8Array(ctTag, tag)) throw new Error('Authentication tag mismatch'); + const plaintext = await ctr(ciphered, omacNonce); + return plaintext; + } + }; +} + + +/** + * Get EAX nonce as defined by {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.1|RFC4880bis-04, section 5.16.1}. + * @param {Uint8Array} iv - The initialization vector (16 bytes) + * @param {Uint8Array} chunkIndex - The chunk index (8 bytes) + */ +EAX.getNonce = function(iv, chunkIndex) { + const nonce = iv.slice(); + for (let i = 0; i < chunkIndex.length; i++) { + nonce[8 + i] ^= chunkIndex[i]; + } + return nonce; +}; + +EAX.blockLength = blockLength$1; +EAX.ivLength = ivLength; +EAX.tagLength = tagLength; + +// OpenPGP.js - An OpenPGP implementation in javascript + +const blockLength$2 = 16; +const ivLength$1 = 15; + +// https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.2: +// While OCB [RFC7253] allows the authentication tag length to be of any +// number up to 128 bits long, this document requires a fixed +// authentication tag length of 128 bits (16 octets) for simplicity. +const tagLength$1 = 16; + + +function ntz(n) { + let ntz = 0; + for (let i = 1; (n & i) === 0; i <<= 1) { + ntz++; + } + return ntz; +} + +function xorMut$1(S, T) { + for (let i = 0; i < S.length; i++) { + S[i] ^= T[i]; + } + return S; +} + +function xor(S, T) { + return xorMut$1(S.slice(), T); +} + +const zeroBlock$1 = new Uint8Array(blockLength$2); +const one$1 = new Uint8Array([1]); + +/** + * Class to en/decrypt using OCB mode. + * @param {enums.symmetric} cipher - The symmetric cipher algorithm to use + * @param {Uint8Array} key - The encryption key + */ +async function OCB(cipher$1, key) { + + let maxNtz = 0; + let encipher; + let decipher; + let mask; + + constructKeyVariables(cipher$1, key); + + function constructKeyVariables(cipher$1, key) { + const cipherName = enums.read(enums.symmetric, cipher$1); + const aes = new cipher[cipherName](key); + encipher = aes.encrypt.bind(aes); + decipher = aes.decrypt.bind(aes); + + const mask_x = encipher(zeroBlock$1); + const mask_$ = util.double(mask_x); + mask = []; + mask[0] = util.double(mask_$); + + + mask.x = mask_x; + mask.$ = mask_$; + } + + function extendKeyVariables(text, adata) { + const newMaxNtz = util.nbits(Math.max(text.length, adata.length) / blockLength$2 | 0) - 1; + for (let i = maxNtz + 1; i <= newMaxNtz; i++) { + mask[i] = util.double(mask[i - 1]); + } + maxNtz = newMaxNtz; + } + + function hash(adata) { + if (!adata.length) { + // Fast path + return zeroBlock$1; + } + + // + // Consider A as a sequence of 128-bit blocks + // + const m = adata.length / blockLength$2 | 0; + + const offset = new Uint8Array(blockLength$2); + const sum = new Uint8Array(blockLength$2); + for (let i = 0; i < m; i++) { + xorMut$1(offset, mask[ntz(i + 1)]); + xorMut$1(sum, encipher(xor(offset, adata))); + adata = adata.subarray(blockLength$2); + } + + // + // Process any final partial block; compute final hash value + // + if (adata.length) { + xorMut$1(offset, mask.x); + + const cipherInput = new Uint8Array(blockLength$2); + cipherInput.set(adata, 0); + cipherInput[adata.length] = 0b10000000; + xorMut$1(cipherInput, offset); + + xorMut$1(sum, encipher(cipherInput)); + } + + return sum; + } + + /** + * Encrypt/decrypt data. + * @param {encipher|decipher} fn - Encryption/decryption block cipher function + * @param {Uint8Array} text - The cleartext or ciphertext (without tag) input + * @param {Uint8Array} nonce - The nonce (15 bytes) + * @param {Uint8Array} adata - Associated data to sign + * @returns {Promise} The ciphertext or plaintext output, with tag appended in both cases. + */ + function crypt(fn, text, nonce, adata) { + // + // Consider P as a sequence of 128-bit blocks + // + const m = text.length / blockLength$2 | 0; + + // + // Key-dependent variables + // + extendKeyVariables(text, adata); + + // + // Nonce-dependent and per-encryption variables + // + // Nonce = num2str(TAGLEN mod 128,7) || zeros(120-bitlen(N)) || 1 || N + // Note: We assume here that tagLength mod 16 == 0. + const paddedNonce = util.concatUint8Array([zeroBlock$1.subarray(0, ivLength$1 - nonce.length), one$1, nonce]); + // bottom = str2num(Nonce[123..128]) + const bottom = paddedNonce[blockLength$2 - 1] & 0b111111; + // Ktop = ENCIPHER(K, Nonce[1..122] || zeros(6)) + paddedNonce[blockLength$2 - 1] &= 0b11000000; + const kTop = encipher(paddedNonce); + // Stretch = Ktop || (Ktop[1..64] xor Ktop[9..72]) + const stretched = util.concatUint8Array([kTop, xor(kTop.subarray(0, 8), kTop.subarray(1, 9))]); + // Offset_0 = Stretch[1+bottom..128+bottom] + const offset = util.shiftRight(stretched.subarray(0 + (bottom >> 3), 17 + (bottom >> 3)), 8 - (bottom & 7)).subarray(1); + // Checksum_0 = zeros(128) + const checksum = new Uint8Array(blockLength$2); + + const ct = new Uint8Array(text.length + tagLength$1); + + // + // Process any whole blocks + // + let i; + let pos = 0; + for (i = 0; i < m; i++) { + // Offset_i = Offset_{i-1} xor L_{ntz(i)} + xorMut$1(offset, mask[ntz(i + 1)]); + // C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) + // P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i) + ct.set(xorMut$1(fn(xor(offset, text)), offset), pos); + // Checksum_i = Checksum_{i-1} xor P_i + xorMut$1(checksum, fn === encipher ? text : ct.subarray(pos)); + + text = text.subarray(blockLength$2); + pos += blockLength$2; + } + + // + // Process any final partial block and compute raw tag + // + if (text.length) { + // Offset_* = Offset_m xor L_* + xorMut$1(offset, mask.x); + // Pad = ENCIPHER(K, Offset_*) + const padding = encipher(offset); + // C_* = P_* xor Pad[1..bitlen(P_*)] + ct.set(xor(text, padding), pos); + + // Checksum_* = Checksum_m xor (P_* || 1 || new Uint8Array(127-bitlen(P_*))) + const xorInput = new Uint8Array(blockLength$2); + xorInput.set(fn === encipher ? text : ct.subarray(pos, -tagLength$1), 0); + xorInput[text.length] = 0b10000000; + xorMut$1(checksum, xorInput); + pos += text.length; + } + // Tag = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) xor HASH(K,A) + const tag = xorMut$1(encipher(xorMut$1(xorMut$1(checksum, offset), mask.$)), hash(adata)); + + // + // Assemble ciphertext + // + // C = C_1 || C_2 || ... || C_m || C_* || Tag[1..TAGLEN] + ct.set(tag, pos); + return ct; + } + + + return { + /** + * Encrypt plaintext input. + * @param {Uint8Array} plaintext - The cleartext input to be encrypted + * @param {Uint8Array} nonce - The nonce (15 bytes) + * @param {Uint8Array} adata - Associated data to sign + * @returns {Promise} The ciphertext output. + */ + encrypt: async function(plaintext, nonce, adata) { + return crypt(encipher, plaintext, nonce, adata); + }, + + /** + * Decrypt ciphertext input. + * @param {Uint8Array} ciphertext - The ciphertext input to be decrypted + * @param {Uint8Array} nonce - The nonce (15 bytes) + * @param {Uint8Array} adata - Associated data to sign + * @returns {Promise} The ciphertext output. + */ + decrypt: async function(ciphertext, nonce, adata) { + if (ciphertext.length < tagLength$1) throw new Error('Invalid OCB ciphertext'); + + const tag = ciphertext.subarray(-tagLength$1); + ciphertext = ciphertext.subarray(0, -tagLength$1); + + const crypted = crypt(decipher, ciphertext, nonce, adata); + // if (Tag[1..TAGLEN] == T) + if (util.equalsUint8Array(tag, crypted.subarray(-tagLength$1))) { + return crypted.subarray(0, -tagLength$1); + } + throw new Error('Authentication tag mismatch'); + } + }; +} + + +/** + * Get OCB nonce as defined by {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.2|RFC4880bis-04, section 5.16.2}. + * @param {Uint8Array} iv - The initialization vector (15 bytes) + * @param {Uint8Array} chunkIndex - The chunk index (8 bytes) + */ +OCB.getNonce = function(iv, chunkIndex) { + const nonce = iv.slice(); + for (let i = 0; i < chunkIndex.length; i++) { + nonce[7 + i] ^= chunkIndex[i]; + } + return nonce; +}; + +OCB.blockLength = blockLength$2; +OCB.ivLength = ivLength$1; +OCB.tagLength = tagLength$1; + +const _AES_GCM_data_maxLength = 68719476704; // 2^36 - 2^5 +class AES_GCM { + constructor(key, nonce, adata, tagSize = 16, aes) { + this.tagSize = tagSize; + this.gamma0 = 0; + this.counter = 1; + this.aes = aes ? aes : new AES(key, undefined, false, 'CTR'); + let { asm, heap } = this.aes.acquire_asm(); + // Init GCM + asm.gcm_init(); + // Tag size + if (this.tagSize < 4 || this.tagSize > 16) + throw new IllegalArgumentError('illegal tagSize value'); + // Nonce + const noncelen = nonce.length || 0; + const noncebuf = new Uint8Array(16); + if (noncelen !== 12) { + this._gcm_mac_process(nonce); + heap[0] = 0; + heap[1] = 0; + heap[2] = 0; + heap[3] = 0; + heap[4] = 0; + heap[5] = 0; + heap[6] = 0; + heap[7] = 0; + heap[8] = 0; + heap[9] = 0; + heap[10] = 0; + heap[11] = noncelen >>> 29; + heap[12] = (noncelen >>> 21) & 255; + heap[13] = (noncelen >>> 13) & 255; + heap[14] = (noncelen >>> 5) & 255; + heap[15] = (noncelen << 3) & 255; + asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16); + asm.get_iv(AES_asm.HEAP_DATA); + asm.set_iv(0, 0, 0, 0); + noncebuf.set(heap.subarray(0, 16)); + } + else { + noncebuf.set(nonce); + noncebuf[15] = 1; + } + const nonceview = new DataView(noncebuf.buffer); + this.gamma0 = nonceview.getUint32(12); + asm.set_nonce(nonceview.getUint32(0), nonceview.getUint32(4), nonceview.getUint32(8), 0); + asm.set_mask(0, 0, 0, 0xffffffff); + // Associated data + if (adata !== undefined) { + if (adata.length > _AES_GCM_data_maxLength) + throw new IllegalArgumentError('illegal adata length'); + if (adata.length) { + this.adata = adata; + this._gcm_mac_process(adata); + } + else { + this.adata = undefined; + } + } + else { + this.adata = undefined; + } + // Counter + if (this.counter < 1 || this.counter > 0xffffffff) + throw new RangeError('counter must be a positive 32-bit integer'); + asm.set_counter(0, 0, 0, (this.gamma0 + this.counter) | 0); + } + static encrypt(cleartext, key, nonce, adata, tagsize) { + return new AES_GCM(key, nonce, adata, tagsize).encrypt(cleartext); + } + static decrypt(ciphertext, key, nonce, adata, tagsize) { + return new AES_GCM(key, nonce, adata, tagsize).decrypt(ciphertext); + } + encrypt(data) { + return this.AES_GCM_encrypt(data); + } + decrypt(data) { + return this.AES_GCM_decrypt(data); + } + AES_GCM_Encrypt_process(data) { + let dpos = 0; + let dlen = data.length || 0; + let { asm, heap } = this.aes.acquire_asm(); + let counter = this.counter; + let pos = this.aes.pos; + let len = this.aes.len; + let rpos = 0; + let rlen = (len + dlen) & -16; + let wlen = 0; + if (((counter - 1) << 4) + len + dlen > _AES_GCM_data_maxLength) + throw new RangeError('counter overflow'); + const result = new Uint8Array(rlen); + while (dlen > 0) { + wlen = _heap_write(heap, pos + len, data, dpos, dlen); + len += wlen; + dpos += wlen; + dlen -= wlen; + wlen = asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, len); + wlen = asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, wlen); + if (wlen) + result.set(heap.subarray(pos, pos + wlen), rpos); + counter += wlen >>> 4; + rpos += wlen; + if (wlen < len) { + pos += wlen; + len -= wlen; + } + else { + pos = 0; + len = 0; + } + } + this.counter = counter; + this.aes.pos = pos; + this.aes.len = len; + return result; + } + AES_GCM_Encrypt_finish() { + let { asm, heap } = this.aes.acquire_asm(); + let counter = this.counter; + let tagSize = this.tagSize; + let adata = this.adata; + let pos = this.aes.pos; + let len = this.aes.len; + const result = new Uint8Array(len + tagSize); + asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, (len + 15) & -16); + if (len) + result.set(heap.subarray(pos, pos + len)); + let i = len; + for (; i & 15; i++) + heap[pos + i] = 0; + asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, i); + const alen = adata !== undefined ? adata.length : 0; + const clen = ((counter - 1) << 4) + len; + heap[0] = 0; + heap[1] = 0; + heap[2] = 0; + heap[3] = alen >>> 29; + heap[4] = alen >>> 21; + heap[5] = (alen >>> 13) & 255; + heap[6] = (alen >>> 5) & 255; + heap[7] = (alen << 3) & 255; + heap[8] = heap[9] = heap[10] = 0; + heap[11] = clen >>> 29; + heap[12] = (clen >>> 21) & 255; + heap[13] = (clen >>> 13) & 255; + heap[14] = (clen >>> 5) & 255; + heap[15] = (clen << 3) & 255; + asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16); + asm.get_iv(AES_asm.HEAP_DATA); + asm.set_counter(0, 0, 0, this.gamma0); + asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16); + result.set(heap.subarray(0, tagSize), len); + this.counter = 1; + this.aes.pos = 0; + this.aes.len = 0; + return result; + } + AES_GCM_Decrypt_process(data) { + let dpos = 0; + let dlen = data.length || 0; + let { asm, heap } = this.aes.acquire_asm(); + let counter = this.counter; + let tagSize = this.tagSize; + let pos = this.aes.pos; + let len = this.aes.len; + let rpos = 0; + let rlen = len + dlen > tagSize ? (len + dlen - tagSize) & -16 : 0; + let tlen = len + dlen - rlen; + let wlen = 0; + if (((counter - 1) << 4) + len + dlen > _AES_GCM_data_maxLength) + throw new RangeError('counter overflow'); + const result = new Uint8Array(rlen); + while (dlen > tlen) { + wlen = _heap_write(heap, pos + len, data, dpos, dlen - tlen); + len += wlen; + dpos += wlen; + dlen -= wlen; + wlen = asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, wlen); + wlen = asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, wlen); + if (wlen) + result.set(heap.subarray(pos, pos + wlen), rpos); + counter += wlen >>> 4; + rpos += wlen; + pos = 0; + len = 0; + } + if (dlen > 0) { + len += _heap_write(heap, 0, data, dpos, dlen); + } + this.counter = counter; + this.aes.pos = pos; + this.aes.len = len; + return result; + } + AES_GCM_Decrypt_finish() { + let { asm, heap } = this.aes.acquire_asm(); + let tagSize = this.tagSize; + let adata = this.adata; + let counter = this.counter; + let pos = this.aes.pos; + let len = this.aes.len; + let rlen = len - tagSize; + if (len < tagSize) + throw new IllegalStateError('authentication tag not found'); + const result = new Uint8Array(rlen); + const atag = new Uint8Array(heap.subarray(pos + rlen, pos + len)); + let i = rlen; + for (; i & 15; i++) + heap[pos + i] = 0; + asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, i); + asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, i); + if (rlen) + result.set(heap.subarray(pos, pos + rlen)); + const alen = adata !== undefined ? adata.length : 0; + const clen = ((counter - 1) << 4) + len - tagSize; + heap[0] = 0; + heap[1] = 0; + heap[2] = 0; + heap[3] = alen >>> 29; + heap[4] = alen >>> 21; + heap[5] = (alen >>> 13) & 255; + heap[6] = (alen >>> 5) & 255; + heap[7] = (alen << 3) & 255; + heap[8] = heap[9] = heap[10] = 0; + heap[11] = clen >>> 29; + heap[12] = (clen >>> 21) & 255; + heap[13] = (clen >>> 13) & 255; + heap[14] = (clen >>> 5) & 255; + heap[15] = (clen << 3) & 255; + asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16); + asm.get_iv(AES_asm.HEAP_DATA); + asm.set_counter(0, 0, 0, this.gamma0); + asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16); + let acheck = 0; + for (let i = 0; i < tagSize; ++i) + acheck |= atag[i] ^ heap[i]; + if (acheck) + throw new SecurityError('data integrity check failed'); + this.counter = 1; + this.aes.pos = 0; + this.aes.len = 0; + return result; + } + AES_GCM_decrypt(data) { + const result1 = this.AES_GCM_Decrypt_process(data); + const result2 = this.AES_GCM_Decrypt_finish(); + const result = new Uint8Array(result1.length + result2.length); + if (result1.length) + result.set(result1); + if (result2.length) + result.set(result2, result1.length); + return result; + } + AES_GCM_encrypt(data) { + const result1 = this.AES_GCM_Encrypt_process(data); + const result2 = this.AES_GCM_Encrypt_finish(); + const result = new Uint8Array(result1.length + result2.length); + if (result1.length) + result.set(result1); + if (result2.length) + result.set(result2, result1.length); + return result; + } + _gcm_mac_process(data) { + let { asm, heap } = this.aes.acquire_asm(); + let dpos = 0; + let dlen = data.length || 0; + let wlen = 0; + while (dlen > 0) { + wlen = _heap_write(heap, 0, data, dpos, dlen); + dpos += wlen; + dlen -= wlen; + while (wlen & 15) + heap[wlen++] = 0; + asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, wlen); + } + } +} + +// OpenPGP.js - An OpenPGP implementation in javascript + +const webCrypto$4 = util.getWebCrypto(); +const nodeCrypto$4 = util.getNodeCrypto(); +const Buffer$2 = util.getNodeBuffer(); + +const blockLength$3 = 16; +const ivLength$2 = 12; // size of the IV in bytes +const tagLength$2 = 16; // size of the tag in bytes +const ALGO = 'AES-GCM'; + +/** + * Class to en/decrypt using GCM mode. + * @param {enums.symmetric} cipher - The symmetric cipher algorithm to use + * @param {Uint8Array} key - The encryption key + */ +async function GCM(cipher, key) { + if (cipher !== enums.symmetric.aes128 && + cipher !== enums.symmetric.aes192 && + cipher !== enums.symmetric.aes256) { + throw new Error('GCM mode supports only AES cipher'); + } + + if (util.getWebCrypto() && key.length !== 24) { // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support + const _key = await webCrypto$4.importKey('raw', key, { name: ALGO }, false, ['encrypt', 'decrypt']); + + return { + encrypt: async function(pt, iv, adata = new Uint8Array()) { + if ( + !pt.length || + // iOS does not support GCM-en/decrypting empty messages + // Also, synchronous en/decryption might be faster in this case. + (!adata.length && navigator.userAgent && navigator.userAgent.indexOf('Edge') !== -1) + // Edge does not support GCM-en/decrypting without ADATA + ) { + return AES_GCM.encrypt(pt, key, iv, adata); + } + const ct = await webCrypto$4.encrypt({ name: ALGO, iv, additionalData: adata, tagLength: tagLength$2 * 8 }, _key, pt); + return new Uint8Array(ct); + }, + + decrypt: async function(ct, iv, adata = new Uint8Array()) { + if ( + ct.length === tagLength$2 || + // iOS does not support GCM-en/decrypting empty messages + // Also, synchronous en/decryption might be faster in this case. + (!adata.length && navigator.userAgent && navigator.userAgent.indexOf('Edge') !== -1) + // Edge does not support GCM-en/decrypting without ADATA + ) { + return AES_GCM.decrypt(ct, key, iv, adata); + } + const pt = await webCrypto$4.decrypt({ name: ALGO, iv, additionalData: adata, tagLength: tagLength$2 * 8 }, _key, ct); + return new Uint8Array(pt); + } + }; + } + + if (util.getNodeCrypto()) { // Node crypto library + return { + encrypt: async function(pt, iv, adata = new Uint8Array()) { + const en = new nodeCrypto$4.createCipheriv('aes-' + (key.length * 8) + '-gcm', key, iv); + en.setAAD(adata); + const ct = Buffer$2.concat([en.update(pt), en.final(), en.getAuthTag()]); // append auth tag to ciphertext + return new Uint8Array(ct); + }, + + decrypt: async function(ct, iv, adata = new Uint8Array()) { + const de = new nodeCrypto$4.createDecipheriv('aes-' + (key.length * 8) + '-gcm', key, iv); + de.setAAD(adata); + de.setAuthTag(ct.slice(ct.length - tagLength$2, ct.length)); // read auth tag at end of ciphertext + const pt = Buffer$2.concat([de.update(ct.slice(0, ct.length - tagLength$2)), de.final()]); + return new Uint8Array(pt); + } + }; + } + + return { + encrypt: async function(pt, iv, adata) { + return AES_GCM.encrypt(pt, key, iv, adata); + }, + + decrypt: async function(ct, iv, adata) { + return AES_GCM.decrypt(ct, key, iv, adata); + } + }; +} + + +/** + * Get GCM nonce. Note: this operation is not defined by the standard. + * A future version of the standard may define GCM mode differently, + * hopefully under a different ID (we use Private/Experimental algorithm + * ID 100) so that we can maintain backwards compatibility. + * @param {Uint8Array} iv - The initialization vector (12 bytes) + * @param {Uint8Array} chunkIndex - The chunk index (8 bytes) + */ +GCM.getNonce = function(iv, chunkIndex) { + const nonce = iv.slice(); + for (let i = 0; i < chunkIndex.length; i++) { + nonce[4 + i] ^= chunkIndex[i]; + } + return nonce; +}; + +GCM.blockLength = blockLength$3; +GCM.ivLength = ivLength$2; +GCM.tagLength = tagLength$2; + +/** + * @fileoverview Cipher modes + * @module crypto/mode + * @private + */ + +var mode = { + /** @see module:crypto/mode/cfb */ + cfb: cfb, + /** @see module:crypto/mode/gcm */ + gcm: GCM, + experimentalGCM: GCM, + /** @see module:crypto/mode/eax */ + eax: EAX, + /** @see module:crypto/mode/ocb */ + ocb: OCB +}; + +var naclFastLight = createCommonjsModule(function (module) { +/*jshint bitwise: false*/ + +(function(nacl) { + +// Ported in 2014 by Dmitry Chestnykh and Devi Mandiri. +// Public domain. +// +// Implementation derived from TweetNaCl version 20140427. +// See for details: http://tweetnacl.cr.yp.to/ + +var gf = function(init) { + var i, r = new Float64Array(16); + if (init) for (i = 0; i < init.length; i++) r[i] = init[i]; + return r; +}; + +// Pluggable, initialized in high-level API below. +var randombytes = function(/* x, n */) { throw new Error('no PRNG'); }; + +var _9 = new Uint8Array(32); _9[0] = 9; + +var gf0 = gf(), + gf1 = gf([1]), + _121665 = gf([0xdb41, 1]), + D = gf([0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203]), + D2 = gf([0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406]), + X = gf([0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169]), + Y = gf([0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666]), + I = gf([0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83]); + +function vn(x, xi, y, yi, n) { + var i,d = 0; + for (i = 0; i < n; i++) d |= x[xi+i]^y[yi+i]; + return (1 & ((d - 1) >>> 8)) - 1; +} + +function crypto_verify_32(x, xi, y, yi) { + return vn(x,xi,y,yi,32); +} + +function set25519(r, a) { + var i; + for (i = 0; i < 16; i++) r[i] = a[i]|0; +} + +function car25519(o) { + var i, v, c = 1; + for (i = 0; i < 16; i++) { + v = o[i] + c + 65535; + c = Math.floor(v / 65536); + o[i] = v - c * 65536; + } + o[0] += c-1 + 37 * (c-1); +} + +function sel25519(p, q, b) { + var t, c = ~(b-1); + for (var i = 0; i < 16; i++) { + t = c & (p[i] ^ q[i]); + p[i] ^= t; + q[i] ^= t; + } +} + +function pack25519(o, n) { + var i, j, b; + var m = gf(), t = gf(); + for (i = 0; i < 16; i++) t[i] = n[i]; + car25519(t); + car25519(t); + car25519(t); + for (j = 0; j < 2; j++) { + m[0] = t[0] - 0xffed; + for (i = 1; i < 15; i++) { + m[i] = t[i] - 0xffff - ((m[i-1]>>16) & 1); + m[i-1] &= 0xffff; + } + m[15] = t[15] - 0x7fff - ((m[14]>>16) & 1); + b = (m[15]>>16) & 1; + m[14] &= 0xffff; + sel25519(t, m, 1-b); + } + for (i = 0; i < 16; i++) { + o[2*i] = t[i] & 0xff; + o[2*i+1] = t[i]>>8; + } +} + +function neq25519(a, b) { + var c = new Uint8Array(32), d = new Uint8Array(32); + pack25519(c, a); + pack25519(d, b); + return crypto_verify_32(c, 0, d, 0); +} + +function par25519(a) { + var d = new Uint8Array(32); + pack25519(d, a); + return d[0] & 1; +} + +function unpack25519(o, n) { + var i; + for (i = 0; i < 16; i++) o[i] = n[2*i] + (n[2*i+1] << 8); + o[15] &= 0x7fff; +} + +function A(o, a, b) { + for (var i = 0; i < 16; i++) o[i] = a[i] + b[i]; +} + +function Z(o, a, b) { + for (var i = 0; i < 16; i++) o[i] = a[i] - b[i]; +} + +function M(o, a, b) { + var v, c, + t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0, + t8 = 0, t9 = 0, t10 = 0, t11 = 0, t12 = 0, t13 = 0, t14 = 0, t15 = 0, + t16 = 0, t17 = 0, t18 = 0, t19 = 0, t20 = 0, t21 = 0, t22 = 0, t23 = 0, + t24 = 0, t25 = 0, t26 = 0, t27 = 0, t28 = 0, t29 = 0, t30 = 0, + b0 = b[0], + b1 = b[1], + b2 = b[2], + b3 = b[3], + b4 = b[4], + b5 = b[5], + b6 = b[6], + b7 = b[7], + b8 = b[8], + b9 = b[9], + b10 = b[10], + b11 = b[11], + b12 = b[12], + b13 = b[13], + b14 = b[14], + b15 = b[15]; + + v = a[0]; + t0 += v * b0; + t1 += v * b1; + t2 += v * b2; + t3 += v * b3; + t4 += v * b4; + t5 += v * b5; + t6 += v * b6; + t7 += v * b7; + t8 += v * b8; + t9 += v * b9; + t10 += v * b10; + t11 += v * b11; + t12 += v * b12; + t13 += v * b13; + t14 += v * b14; + t15 += v * b15; + v = a[1]; + t1 += v * b0; + t2 += v * b1; + t3 += v * b2; + t4 += v * b3; + t5 += v * b4; + t6 += v * b5; + t7 += v * b6; + t8 += v * b7; + t9 += v * b8; + t10 += v * b9; + t11 += v * b10; + t12 += v * b11; + t13 += v * b12; + t14 += v * b13; + t15 += v * b14; + t16 += v * b15; + v = a[2]; + t2 += v * b0; + t3 += v * b1; + t4 += v * b2; + t5 += v * b3; + t6 += v * b4; + t7 += v * b5; + t8 += v * b6; + t9 += v * b7; + t10 += v * b8; + t11 += v * b9; + t12 += v * b10; + t13 += v * b11; + t14 += v * b12; + t15 += v * b13; + t16 += v * b14; + t17 += v * b15; + v = a[3]; + t3 += v * b0; + t4 += v * b1; + t5 += v * b2; + t6 += v * b3; + t7 += v * b4; + t8 += v * b5; + t9 += v * b6; + t10 += v * b7; + t11 += v * b8; + t12 += v * b9; + t13 += v * b10; + t14 += v * b11; + t15 += v * b12; + t16 += v * b13; + t17 += v * b14; + t18 += v * b15; + v = a[4]; + t4 += v * b0; + t5 += v * b1; + t6 += v * b2; + t7 += v * b3; + t8 += v * b4; + t9 += v * b5; + t10 += v * b6; + t11 += v * b7; + t12 += v * b8; + t13 += v * b9; + t14 += v * b10; + t15 += v * b11; + t16 += v * b12; + t17 += v * b13; + t18 += v * b14; + t19 += v * b15; + v = a[5]; + t5 += v * b0; + t6 += v * b1; + t7 += v * b2; + t8 += v * b3; + t9 += v * b4; + t10 += v * b5; + t11 += v * b6; + t12 += v * b7; + t13 += v * b8; + t14 += v * b9; + t15 += v * b10; + t16 += v * b11; + t17 += v * b12; + t18 += v * b13; + t19 += v * b14; + t20 += v * b15; + v = a[6]; + t6 += v * b0; + t7 += v * b1; + t8 += v * b2; + t9 += v * b3; + t10 += v * b4; + t11 += v * b5; + t12 += v * b6; + t13 += v * b7; + t14 += v * b8; + t15 += v * b9; + t16 += v * b10; + t17 += v * b11; + t18 += v * b12; + t19 += v * b13; + t20 += v * b14; + t21 += v * b15; + v = a[7]; + t7 += v * b0; + t8 += v * b1; + t9 += v * b2; + t10 += v * b3; + t11 += v * b4; + t12 += v * b5; + t13 += v * b6; + t14 += v * b7; + t15 += v * b8; + t16 += v * b9; + t17 += v * b10; + t18 += v * b11; + t19 += v * b12; + t20 += v * b13; + t21 += v * b14; + t22 += v * b15; + v = a[8]; + t8 += v * b0; + t9 += v * b1; + t10 += v * b2; + t11 += v * b3; + t12 += v * b4; + t13 += v * b5; + t14 += v * b6; + t15 += v * b7; + t16 += v * b8; + t17 += v * b9; + t18 += v * b10; + t19 += v * b11; + t20 += v * b12; + t21 += v * b13; + t22 += v * b14; + t23 += v * b15; + v = a[9]; + t9 += v * b0; + t10 += v * b1; + t11 += v * b2; + t12 += v * b3; + t13 += v * b4; + t14 += v * b5; + t15 += v * b6; + t16 += v * b7; + t17 += v * b8; + t18 += v * b9; + t19 += v * b10; + t20 += v * b11; + t21 += v * b12; + t22 += v * b13; + t23 += v * b14; + t24 += v * b15; + v = a[10]; + t10 += v * b0; + t11 += v * b1; + t12 += v * b2; + t13 += v * b3; + t14 += v * b4; + t15 += v * b5; + t16 += v * b6; + t17 += v * b7; + t18 += v * b8; + t19 += v * b9; + t20 += v * b10; + t21 += v * b11; + t22 += v * b12; + t23 += v * b13; + t24 += v * b14; + t25 += v * b15; + v = a[11]; + t11 += v * b0; + t12 += v * b1; + t13 += v * b2; + t14 += v * b3; + t15 += v * b4; + t16 += v * b5; + t17 += v * b6; + t18 += v * b7; + t19 += v * b8; + t20 += v * b9; + t21 += v * b10; + t22 += v * b11; + t23 += v * b12; + t24 += v * b13; + t25 += v * b14; + t26 += v * b15; + v = a[12]; + t12 += v * b0; + t13 += v * b1; + t14 += v * b2; + t15 += v * b3; + t16 += v * b4; + t17 += v * b5; + t18 += v * b6; + t19 += v * b7; + t20 += v * b8; + t21 += v * b9; + t22 += v * b10; + t23 += v * b11; + t24 += v * b12; + t25 += v * b13; + t26 += v * b14; + t27 += v * b15; + v = a[13]; + t13 += v * b0; + t14 += v * b1; + t15 += v * b2; + t16 += v * b3; + t17 += v * b4; + t18 += v * b5; + t19 += v * b6; + t20 += v * b7; + t21 += v * b8; + t22 += v * b9; + t23 += v * b10; + t24 += v * b11; + t25 += v * b12; + t26 += v * b13; + t27 += v * b14; + t28 += v * b15; + v = a[14]; + t14 += v * b0; + t15 += v * b1; + t16 += v * b2; + t17 += v * b3; + t18 += v * b4; + t19 += v * b5; + t20 += v * b6; + t21 += v * b7; + t22 += v * b8; + t23 += v * b9; + t24 += v * b10; + t25 += v * b11; + t26 += v * b12; + t27 += v * b13; + t28 += v * b14; + t29 += v * b15; + v = a[15]; + t15 += v * b0; + t16 += v * b1; + t17 += v * b2; + t18 += v * b3; + t19 += v * b4; + t20 += v * b5; + t21 += v * b6; + t22 += v * b7; + t23 += v * b8; + t24 += v * b9; + t25 += v * b10; + t26 += v * b11; + t27 += v * b12; + t28 += v * b13; + t29 += v * b14; + t30 += v * b15; + + t0 += 38 * t16; + t1 += 38 * t17; + t2 += 38 * t18; + t3 += 38 * t19; + t4 += 38 * t20; + t5 += 38 * t21; + t6 += 38 * t22; + t7 += 38 * t23; + t8 += 38 * t24; + t9 += 38 * t25; + t10 += 38 * t26; + t11 += 38 * t27; + t12 += 38 * t28; + t13 += 38 * t29; + t14 += 38 * t30; + // t15 left as is + + // first car + c = 1; + v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536; + v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536; + v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536; + v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536; + v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536; + v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536; + v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536; + v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536; + v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536; + v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536; + v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536; + v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536; + v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536; + v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536; + v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536; + v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536; + t0 += c-1 + 37 * (c-1); + + // second car + c = 1; + v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536; + v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536; + v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536; + v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536; + v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536; + v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536; + v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536; + v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536; + v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536; + v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536; + v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536; + v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536; + v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536; + v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536; + v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536; + v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536; + t0 += c-1 + 37 * (c-1); + + o[ 0] = t0; + o[ 1] = t1; + o[ 2] = t2; + o[ 3] = t3; + o[ 4] = t4; + o[ 5] = t5; + o[ 6] = t6; + o[ 7] = t7; + o[ 8] = t8; + o[ 9] = t9; + o[10] = t10; + o[11] = t11; + o[12] = t12; + o[13] = t13; + o[14] = t14; + o[15] = t15; +} + +function S(o, a) { + M(o, a, a); +} + +function inv25519(o, i) { + var c = gf(); + var a; + for (a = 0; a < 16; a++) c[a] = i[a]; + for (a = 253; a >= 0; a--) { + S(c, c); + if(a !== 2 && a !== 4) M(c, c, i); + } + for (a = 0; a < 16; a++) o[a] = c[a]; +} + +function pow2523(o, i) { + var c = gf(); + var a; + for (a = 0; a < 16; a++) c[a] = i[a]; + for (a = 250; a >= 0; a--) { + S(c, c); + if(a !== 1) M(c, c, i); + } + for (a = 0; a < 16; a++) o[a] = c[a]; +} + +function crypto_scalarmult(q, n, p) { + var z = new Uint8Array(32); + var x = new Float64Array(80), r, i; + var a = gf(), b = gf(), c = gf(), + d = gf(), e = gf(), f = gf(); + for (i = 0; i < 31; i++) z[i] = n[i]; + z[31]=(n[31]&127)|64; + z[0]&=248; + unpack25519(x,p); + for (i = 0; i < 16; i++) { + b[i]=x[i]; + d[i]=a[i]=c[i]=0; + } + a[0]=d[0]=1; + for (i=254; i>=0; --i) { + r=(z[i>>>3]>>>(i&7))&1; + sel25519(a,b,r); + sel25519(c,d,r); + A(e,a,c); + Z(a,a,c); + A(c,b,d); + Z(b,b,d); + S(d,e); + S(f,a); + M(a,c,a); + M(c,b,e); + A(e,a,c); + Z(a,a,c); + S(b,a); + Z(c,d,f); + M(a,c,_121665); + A(a,a,d); + M(c,c,a); + M(a,d,f); + M(d,b,x); + S(b,e); + sel25519(a,b,r); + sel25519(c,d,r); + } + for (i = 0; i < 16; i++) { + x[i+16]=a[i]; + x[i+32]=c[i]; + x[i+48]=b[i]; + x[i+64]=d[i]; + } + var x32 = x.subarray(32); + var x16 = x.subarray(16); + inv25519(x32,x32); + M(x16,x16,x32); + pack25519(q,x16); + return 0; +} + +function crypto_scalarmult_base(q, n) { + return crypto_scalarmult(q, n, _9); +} + +function crypto_box_keypair(y, x) { + randombytes(x, 32); + return crypto_scalarmult_base(y, x); +} + +function add(p, q) { + var a = gf(), b = gf(), c = gf(), + d = gf(), e = gf(), f = gf(), + g = gf(), h = gf(), t = gf(); + + Z(a, p[1], p[0]); + Z(t, q[1], q[0]); + M(a, a, t); + A(b, p[0], p[1]); + A(t, q[0], q[1]); + M(b, b, t); + M(c, p[3], q[3]); + M(c, c, D2); + M(d, p[2], q[2]); + A(d, d, d); + Z(e, b, a); + Z(f, d, c); + A(g, d, c); + A(h, b, a); + + M(p[0], e, f); + M(p[1], h, g); + M(p[2], g, f); + M(p[3], e, h); +} + +function cswap(p, q, b) { + var i; + for (i = 0; i < 4; i++) { + sel25519(p[i], q[i], b); + } +} + +function pack(r, p) { + var tx = gf(), ty = gf(), zi = gf(); + inv25519(zi, p[2]); + M(tx, p[0], zi); + M(ty, p[1], zi); + pack25519(r, ty); + r[31] ^= par25519(tx) << 7; +} + +function scalarmult(p, q, s) { + var b, i; + set25519(p[0], gf0); + set25519(p[1], gf1); + set25519(p[2], gf1); + set25519(p[3], gf0); + for (i = 255; i >= 0; --i) { + b = (s[(i/8)|0] >> (i&7)) & 1; + cswap(p, q, b); + add(q, p); + add(p, p); + cswap(p, q, b); + } +} + +function scalarbase(p, s) { + var q = [gf(), gf(), gf(), gf()]; + set25519(q[0], X); + set25519(q[1], Y); + set25519(q[2], gf1); + M(q[3], X, Y); + scalarmult(p, q, s); +} + +function crypto_sign_keypair(pk, sk, seeded) { + var d; + var p = [gf(), gf(), gf(), gf()]; + var i; + + if (!seeded) randombytes(sk, 32); + d = nacl.hash(sk.subarray(0, 32)); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + scalarbase(p, d); + pack(pk, p); + + for (i = 0; i < 32; i++) sk[i+32] = pk[i]; + return 0; +} + +var L = new Float64Array([0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10]); + +function modL(r, x) { + var carry, i, j, k; + for (i = 63; i >= 32; --i) { + carry = 0; + for (j = i - 32, k = i - 12; j < k; ++j) { + x[j] += carry - 16 * x[i] * L[j - (i - 32)]; + carry = Math.floor((x[j] + 128) / 256); + x[j] -= carry * 256; + } + x[j] += carry; + x[i] = 0; + } + carry = 0; + for (j = 0; j < 32; j++) { + x[j] += carry - (x[31] >> 4) * L[j]; + carry = x[j] >> 8; + x[j] &= 255; + } + for (j = 0; j < 32; j++) x[j] -= carry * L[j]; + for (i = 0; i < 32; i++) { + x[i+1] += x[i] >> 8; + r[i] = x[i] & 255; + } +} + +function reduce(r) { + var x = new Float64Array(64), i; + for (i = 0; i < 64; i++) x[i] = r[i]; + for (i = 0; i < 64; i++) r[i] = 0; + modL(r, x); +} + +// Note: difference from C - smlen returned, not passed as argument. +function crypto_sign(sm, m, n, sk) { + var d, h, r; + var i, j, x = new Float64Array(64); + var p = [gf(), gf(), gf(), gf()]; + + d = nacl.hash(sk.subarray(0, 32)); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + var smlen = n + 64; + for (i = 0; i < n; i++) sm[64 + i] = m[i]; + for (i = 0; i < 32; i++) sm[32 + i] = d[32 + i]; + + r = nacl.hash(sm.subarray(32, smlen)); + reduce(r); + scalarbase(p, r); + pack(sm, p); + + for (i = 32; i < 64; i++) sm[i] = sk[i]; + h = nacl.hash(sm.subarray(0, smlen)); + reduce(h); + + for (i = 0; i < 64; i++) x[i] = 0; + for (i = 0; i < 32; i++) x[i] = r[i]; + for (i = 0; i < 32; i++) { + for (j = 0; j < 32; j++) { + x[i+j] += h[i] * d[j]; + } + } + + modL(sm.subarray(32), x); + return smlen; +} + +function unpackneg(r, p) { + var t = gf(), chk = gf(), num = gf(), + den = gf(), den2 = gf(), den4 = gf(), + den6 = gf(); + + set25519(r[2], gf1); + unpack25519(r[1], p); + S(num, r[1]); + M(den, num, D); + Z(num, num, r[2]); + A(den, r[2], den); + + S(den2, den); + S(den4, den2); + M(den6, den4, den2); + M(t, den6, num); + M(t, t, den); + + pow2523(t, t); + M(t, t, num); + M(t, t, den); + M(t, t, den); + M(r[0], t, den); + + S(chk, r[0]); + M(chk, chk, den); + if (neq25519(chk, num)) M(r[0], r[0], I); + + S(chk, r[0]); + M(chk, chk, den); + if (neq25519(chk, num)) return -1; + + if (par25519(r[0]) === (p[31]>>7)) Z(r[0], gf0, r[0]); + + M(r[3], r[0], r[1]); + return 0; +} + +function crypto_sign_open(m, sm, n, pk) { + var i; + var t = new Uint8Array(32), h; + var p = [gf(), gf(), gf(), gf()], + q = [gf(), gf(), gf(), gf()]; + + if (n < 64) return -1; + + if (unpackneg(q, pk)) return -1; + + for (i = 0; i < n; i++) m[i] = sm[i]; + for (i = 0; i < 32; i++) m[i+32] = pk[i]; + h = nacl.hash(m.subarray(0, n)); + reduce(h); + scalarmult(p, q, h); + + scalarbase(q, sm.subarray(32)); + add(p, q); + pack(t, p); + + n -= 64; + if (crypto_verify_32(sm, 0, t, 0)) { + for (i = 0; i < n; i++) m[i] = 0; + return -1; + } + + for (i = 0; i < n; i++) m[i] = sm[i + 64]; + return n; +} + +var crypto_scalarmult_BYTES = 32, + crypto_scalarmult_SCALARBYTES = 32, + crypto_box_PUBLICKEYBYTES = 32, + crypto_box_SECRETKEYBYTES = 32, + crypto_sign_BYTES = 64, + crypto_sign_PUBLICKEYBYTES = 32, + crypto_sign_SECRETKEYBYTES = 64, + crypto_sign_SEEDBYTES = 32; + +function checkArrayTypes() { + for (var i = 0; i < arguments.length; i++) { + if (!(arguments[i] instanceof Uint8Array)) + throw new TypeError('unexpected type, use Uint8Array'); + } +} + +function cleanup(arr) { + for (var i = 0; i < arr.length; i++) arr[i] = 0; +} + +nacl.scalarMult = function(n, p) { + checkArrayTypes(n, p); + if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error('bad n size'); + if (p.length !== crypto_scalarmult_BYTES) throw new Error('bad p size'); + var q = new Uint8Array(crypto_scalarmult_BYTES); + crypto_scalarmult(q, n, p); + return q; +}; + +nacl.box = {}; + +nacl.box.keyPair = function() { + var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); + var sk = new Uint8Array(crypto_box_SECRETKEYBYTES); + crypto_box_keypair(pk, sk); + return {publicKey: pk, secretKey: sk}; +}; + +nacl.box.keyPair.fromSecretKey = function(secretKey) { + checkArrayTypes(secretKey); + if (secretKey.length !== crypto_box_SECRETKEYBYTES) + throw new Error('bad secret key size'); + var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); + crypto_scalarmult_base(pk, secretKey); + return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; +}; + +nacl.sign = function(msg, secretKey) { + checkArrayTypes(msg, secretKey); + if (secretKey.length !== crypto_sign_SECRETKEYBYTES) + throw new Error('bad secret key size'); + var signedMsg = new Uint8Array(crypto_sign_BYTES+msg.length); + crypto_sign(signedMsg, msg, msg.length, secretKey); + return signedMsg; +}; + +nacl.sign.detached = function(msg, secretKey) { + var signedMsg = nacl.sign(msg, secretKey); + var sig = new Uint8Array(crypto_sign_BYTES); + for (var i = 0; i < sig.length; i++) sig[i] = signedMsg[i]; + return sig; +}; + +nacl.sign.detached.verify = function(msg, sig, publicKey) { + checkArrayTypes(msg, sig, publicKey); + if (sig.length !== crypto_sign_BYTES) + throw new Error('bad signature size'); + if (publicKey.length !== crypto_sign_PUBLICKEYBYTES) + throw new Error('bad public key size'); + var sm = new Uint8Array(crypto_sign_BYTES + msg.length); + var m = new Uint8Array(crypto_sign_BYTES + msg.length); + var i; + for (i = 0; i < crypto_sign_BYTES; i++) sm[i] = sig[i]; + for (i = 0; i < msg.length; i++) sm[i+crypto_sign_BYTES] = msg[i]; + return (crypto_sign_open(m, sm, sm.length, publicKey) >= 0); +}; + +nacl.sign.keyPair = function() { + var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); + var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); + crypto_sign_keypair(pk, sk); + return {publicKey: pk, secretKey: sk}; +}; + +nacl.sign.keyPair.fromSecretKey = function(secretKey) { + checkArrayTypes(secretKey); + if (secretKey.length !== crypto_sign_SECRETKEYBYTES) + throw new Error('bad secret key size'); + var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); + for (var i = 0; i < pk.length; i++) pk[i] = secretKey[32+i]; + return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; +}; + +nacl.sign.keyPair.fromSeed = function(seed) { + checkArrayTypes(seed); + if (seed.length !== crypto_sign_SEEDBYTES) + throw new Error('bad seed size'); + var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); + var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); + for (var i = 0; i < 32; i++) sk[i] = seed[i]; + crypto_sign_keypair(pk, sk, true); + return {publicKey: pk, secretKey: sk}; +}; + +nacl.setPRNG = function(fn) { + randombytes = fn; +}; + +(function() { + // Initialize PRNG if environment provides CSPRNG. + // If not, methods calling randombytes will throw. + var crypto = typeof self !== 'undefined' ? (self.crypto || self.msCrypto) : null; + if (crypto && crypto.getRandomValues) { + // Browsers. + var QUOTA = 65536; + nacl.setPRNG(function(x, n) { + var i, v = new Uint8Array(n); + for (i = 0; i < n; i += QUOTA) { + crypto.getRandomValues(v.subarray(i, i + Math.min(n - i, QUOTA))); + } + for (i = 0; i < n; i++) x[i] = v[i]; + cleanup(v); + }); + } else if (typeof commonjsRequire !== 'undefined') { + // Node.js. + crypto = crypto__default['default']; + if (crypto && crypto.randomBytes) { + nacl.setPRNG(function(x, n) { + var i, v = crypto.randomBytes(n); + for (i = 0; i < n; i++) x[i] = v[i]; + cleanup(v); + }); + } + } +})(); + +})(module.exports ? module.exports : (self.nacl = self.nacl || {})); +}); + +// GPG4Browsers - An OpenPGP implementation in javascript + +const nodeCrypto$5 = util.getNodeCrypto(); + +/** + * Buffer for secure random numbers + */ +class RandomBuffer { + constructor() { + this.buffer = null; + this.size = null; + this.callback = null; + } + + /** + * Initialize buffer + * @param {Integer} size - size of buffer + */ + init(size, callback) { + this.buffer = new Uint8Array(size); + this.size = 0; + this.callback = callback; + } + + /** + * Concat array of secure random numbers to buffer + * @param {Uint8Array} buf + */ + set(buf) { + if (!this.buffer) { + throw new Error('RandomBuffer is not initialized'); + } + if (!(buf instanceof Uint8Array)) { + throw new Error('Invalid type: buf not an Uint8Array'); + } + const freeSpace = this.buffer.length - this.size; + if (buf.length > freeSpace) { + buf = buf.subarray(0, freeSpace); + } + // set buf with offset old size of buffer + this.buffer.set(buf, this.size); + this.size += buf.length; + } + + /** + * Take numbers out of buffer and copy to array + * @param {Uint8Array} buf - The destination array + */ + async get(buf) { + if (!this.buffer) { + throw new Error('RandomBuffer is not initialized'); + } + if (!(buf instanceof Uint8Array)) { + throw new Error('Invalid type: buf not an Uint8Array'); + } + if (this.size < buf.length) { + if (!this.callback) { + throw new Error('Random number buffer depleted'); + } + // Wait for random bytes from main context, then try again + await this.callback(); + return this.get(buf); + } + for (let i = 0; i < buf.length; i++) { + buf[i] = this.buffer[--this.size]; + // clear buffer value + this.buffer[this.size] = 0; + } + } +} + +/** + * Retrieve secure random byte array of the specified length + * @param {Integer} length - Length in bytes to generate + * @returns {Promise} Random byte array. + * @async + */ +async function getRandomBytes(length) { + const buf = new Uint8Array(length); + if (typeof crypto !== 'undefined' && crypto.getRandomValues) { + crypto.getRandomValues(buf); + } else if (nodeCrypto$5) { + const bytes = nodeCrypto$5.randomBytes(buf.length); + buf.set(bytes); + } else if (randomBuffer.buffer) { + await randomBuffer.get(buf); + } else { + throw new Error('No secure random number generator available.'); + } + return buf; +} + +/** + * Create a secure random BigInteger that is greater than or equal to min and less than max. + * @param {module:BigInteger} min - Lower bound, included + * @param {module:BigInteger} max - Upper bound, excluded + * @returns {Promise} Random BigInteger. + * @async + */ +async function getRandomBigInteger(min, max) { + const BigInteger = await util.getBigInteger(); + + if (max.lt(min)) { + throw new Error('Illegal parameter value: max <= min'); + } + + const modulus = max.sub(min); + const bytes = modulus.byteLength(); + + // Using a while loop is necessary to avoid bias introduced by the mod operation. + // However, we request 64 extra random bits so that the bias is negligible. + // Section B.1.1 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf + const r = new BigInteger(await getRandomBytes(bytes + 8)); + return r.mod(modulus).add(min); +} + +const randomBuffer = new RandomBuffer(); + +var random = /*#__PURE__*/Object.freeze({ + __proto__: null, + getRandomBytes: getRandomBytes, + getRandomBigInteger: getRandomBigInteger, + randomBuffer: randomBuffer +}); + +// OpenPGP.js - An OpenPGP implementation in javascript + +/** + * Generate a probably prime random number + * @param {Integer} bits - Bit length of the prime + * @param {BigInteger} e - Optional RSA exponent to check against the prime + * @param {Integer} k - Optional number of iterations of Miller-Rabin test + * @returns BigInteger + * @async + */ +async function randomProbablePrime(bits, e, k) { + const BigInteger = await util.getBigInteger(); + const one = new BigInteger(1); + const min = one.leftShift(new BigInteger(bits - 1)); + const thirty = new BigInteger(30); + /* + * We can avoid any multiples of 3 and 5 by looking at n mod 30 + * n mod 30 = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 + * the next possible prime is mod 30: + * 1 7 7 7 7 7 7 11 11 11 11 13 13 17 17 17 17 19 19 23 23 23 23 29 29 29 29 29 29 1 + */ + const adds = [1, 6, 5, 4, 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, 3, 2, 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1, 2]; + + const n = await getRandomBigInteger(min, min.leftShift(one)); + let i = n.mod(thirty).toNumber(); + + do { + n.iadd(new BigInteger(adds[i])); + i = (i + adds[i]) % adds.length; + // If reached the maximum, go back to the minimum. + if (n.bitLength() > bits) { + n.imod(min.leftShift(one)).iadd(min); + i = n.mod(thirty).toNumber(); + } + } while (!await isProbablePrime(n, e, k)); + return n; +} + +/** + * Probabilistic primality testing + * @param {BigInteger} n - Number to test + * @param {BigInteger} e - Optional RSA exponent to check against the prime + * @param {Integer} k - Optional number of iterations of Miller-Rabin test + * @returns {boolean} + * @async + */ +async function isProbablePrime(n, e, k) { + if (e && !n.dec().gcd(e).isOne()) { + return false; + } + if (!await divisionTest(n)) { + return false; + } + if (!await fermat(n)) { + return false; + } + if (!await millerRabin(n, k)) { + return false; + } + // TODO implement the Lucas test + // See Section C.3.3 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf + return true; +} + +/** + * Tests whether n is probably prime or not using Fermat's test with b = 2. + * Fails if b^(n-1) mod n != 1. + * @param {BigInteger} n - Number to test + * @param {BigInteger} b - Optional Fermat test base + * @returns {boolean} + */ +async function fermat(n, b) { + const BigInteger = await util.getBigInteger(); + b = b || new BigInteger(2); + return b.modExp(n.dec(), n).isOne(); +} + +async function divisionTest(n) { + const BigInteger = await util.getBigInteger(); + return smallPrimes.every(m => { + return n.mod(new BigInteger(m)) !== 0; + }); +} + +// https://github.com/gpg/libgcrypt/blob/master/cipher/primegen.c +const smallPrimes = [ + 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, + 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, + 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, + 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, + 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, + 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, + 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, + 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, + 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, + 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, + 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, + 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, + 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, + 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, + 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, + 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, + 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, + 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, + 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, + 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, + 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, + 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, + 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, + 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, + 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, + 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, + 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, + 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, + 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, + 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, + 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, + 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, + 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, + 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, + 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, + 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, + 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, + 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, + 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, + 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, + 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, + 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, + 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, + 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, + 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, + 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, + 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, + 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, + 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, + 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, + 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, + 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, + 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, + 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, + 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, + 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, + 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, + 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, + 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, + 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, + 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, + 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, + 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, + 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, + 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, + 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, + 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, + 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, + 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, + 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, + 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457, + 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, + 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, + 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, + 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, + 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, + 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, + 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, + 4957, 4967, 4969, 4973, 4987, 4993, 4999 +]; + + +// Miller-Rabin - Miller Rabin algorithm for primality test +// Copyright Fedor Indutny, 2014. +// +// This software is licensed under the MIT License. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// Adapted on Jan 2018 from version 4.0.1 at https://github.com/indutny/miller-rabin + +// Sample syntax for Fixed-Base Miller-Rabin: +// millerRabin(n, k, () => new BN(small_primes[Math.random() * small_primes.length | 0])) + +/** + * Tests whether n is probably prime or not using the Miller-Rabin test. + * See HAC Remark 4.28. + * @param {BigInteger} n - Number to test + * @param {Integer} k - Optional number of iterations of Miller-Rabin test + * @param {Function} rand - Optional function to generate potential witnesses + * @returns {boolean} + * @async + */ +async function millerRabin(n, k, rand) { + const BigInteger = await util.getBigInteger(); + const len = n.bitLength(); + + if (!k) { + k = Math.max(1, (len / 48) | 0); + } + + const n1 = n.dec(); // n - 1 + + // Find d and s, (n - 1) = (2 ^ s) * d; + let s = 0; + while (!n1.getBit(s)) { s++; } + const d = n.rightShift(new BigInteger(s)); + + for (; k > 0; k--) { + const a = rand ? rand() : await getRandomBigInteger(new BigInteger(2), n1); + + let x = a.modExp(d, n); + if (x.isOne() || x.equal(n1)) { + continue; + } + + let i; + for (i = 1; i < s; i++) { + x = x.mul(x).mod(n); + + if (x.isOne()) { + return false; + } + if (x.equal(n1)) { + break; + } + } + + if (i === s) { + return false; + } + } + + return true; +} + +// GPG4Browsers - An OpenPGP implementation in javascript + +/** + * ASN1 object identifiers for hashes + * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.2} + */ +const hash_headers = []; +hash_headers[1] = [0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, + 0x10]; +hash_headers[2] = [0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14]; +hash_headers[3] = [0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14]; +hash_headers[8] = [0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, + 0x04, 0x20]; +hash_headers[9] = [0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, + 0x04, 0x30]; +hash_headers[10] = [0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, + 0x00, 0x04, 0x40]; +hash_headers[11] = [0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, + 0x00, 0x04, 0x1C]; + +/** + * Create padding with secure random data + * @private + * @param {Integer} length - Length of the padding in bytes + * @returns {Promise} Random padding. + * @async + */ +async function getPKCS1Padding(length) { + const result = new Uint8Array(length); + let count = 0; + while (count < length) { + const randomBytes = await getRandomBytes(length - count); + for (let i = 0; i < randomBytes.length; i++) { + if (randomBytes[i] !== 0) { + result[count++] = randomBytes[i]; + } + } + } + return result; +} + +/** + * Create a EME-PKCS1-v1_5 padded message + * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.1|RFC 4880 13.1.1} + * @param {Uint8Array} message - Message to be encoded + * @param {Integer} keyLength - The length in octets of the key modulus + * @returns {Promise} EME-PKCS1 padded message. + * @async + */ +async function emeEncode(message, keyLength) { + const mLength = message.length; + // length checking + if (mLength > keyLength - 11) { + throw new Error('Message too long'); + } + // Generate an octet string PS of length k - mLen - 3 consisting of + // pseudo-randomly generated nonzero octets + const PS = await getPKCS1Padding(keyLength - mLength - 3); + // Concatenate PS, the message M, and other padding to form an + // encoded message EM of length k octets as EM = 0x00 || 0x02 || PS || 0x00 || M. + const encoded = new Uint8Array(keyLength); + // 0x00 byte + encoded[1] = 2; + encoded.set(PS, 2); + // 0x00 bytes + encoded.set(message, keyLength - mLength); + return encoded; +} + +/** + * Decode a EME-PKCS1-v1_5 padded message + * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.2|RFC 4880 13.1.2} + * @param {Uint8Array} encoded - Encoded message bytes + * @param {Uint8Array} randomPayload - Data to return in case of decoding error (needed for constant-time processing) + * @returns {Uint8Array} decoded data or `randomPayload` (on error, if given) + * @throws {Error} on decoding failure, unless `randomPayload` is provided + */ +function emeDecode(encoded, randomPayload) { + // encoded format: 0x00 0x02 0x00 + let offset = 2; + let separatorNotFound = 1; + for (let j = offset; j < encoded.length; j++) { + separatorNotFound &= encoded[j] !== 0; + offset += separatorNotFound; + } + + const psLen = offset - 2; + const payload = encoded.subarray(offset + 1); // discard the 0x00 separator + const isValidPadding = encoded[0] === 0 & encoded[1] === 2 & psLen >= 8 & !separatorNotFound; + + if (randomPayload) { + return util.selectUint8Array(isValidPadding, payload, randomPayload); + } + + if (isValidPadding) { + return payload; + } + + throw new Error('Decryption error'); +} + +/** + * Create a EMSA-PKCS1-v1_5 padded message + * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.3|RFC 4880 13.1.3} + * @param {Integer} algo - Hash algorithm type used + * @param {Uint8Array} hashed - Message to be encoded + * @param {Integer} emLen - Intended length in octets of the encoded message + * @returns {Uint8Array} Encoded message. + */ +async function emsaEncode(algo, hashed, emLen) { + let i; + if (hashed.length !== hash.getHashByteLength(algo)) { + throw new Error('Invalid hash length'); + } + // produce an ASN.1 DER value for the hash function used. + // Let T be the full hash prefix + const hashPrefix = new Uint8Array(hash_headers[algo].length); + for (i = 0; i < hash_headers[algo].length; i++) { + hashPrefix[i] = hash_headers[algo][i]; + } + // and let tLen be the length in octets prefix and hashed data + const tLen = hashPrefix.length + hashed.length; + if (emLen < tLen + 11) { + throw new Error('Intended encoded message length too short'); + } + // an octet string PS consisting of emLen - tLen - 3 octets with hexadecimal value 0xFF + // The length of PS will be at least 8 octets + const PS = new Uint8Array(emLen - tLen - 3).fill(0xff); + + // Concatenate PS, the hash prefix, hashed data, and other padding to form the + // encoded message EM as EM = 0x00 || 0x01 || PS || 0x00 || prefix || hashed + const EM = new Uint8Array(emLen); + EM[1] = 0x01; + EM.set(PS, 2); + EM.set(hashPrefix, emLen - tLen); + EM.set(hashed, emLen - hashed.length); + return EM; +} + +var pkcs1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + emeEncode: emeEncode, + emeDecode: emeDecode, + emsaEncode: emsaEncode +}); + +const webCrypto$5 = util.getWebCrypto(); +const nodeCrypto$6 = util.getNodeCrypto(); +const asn1 = nodeCrypto$6 ? asn1__default['default'] : undefined; + +/* eslint-disable no-invalid-this */ +const RSAPrivateKey = util.detectNode() ? asn1.define('RSAPrivateKey', function () { + this.seq().obj( // used for native NodeJS crypto + this.key('version').int(), // 0 + this.key('modulus').int(), // n + this.key('publicExponent').int(), // e + this.key('privateExponent').int(), // d + this.key('prime1').int(), // p + this.key('prime2').int(), // q + this.key('exponent1').int(), // dp + this.key('exponent2').int(), // dq + this.key('coefficient').int() // u + ); +}) : undefined; + +const RSAPublicKey = util.detectNode() ? asn1.define('RSAPubliceKey', function () { + this.seq().obj( // used for native NodeJS crypto + this.key('modulus').int(), // n + this.key('publicExponent').int(), // e + ); +}) : undefined; +/* eslint-enable no-invalid-this */ + +/** Create signature + * @param {module:enums.hash} hashAlgo - Hash algorithm + * @param {Uint8Array} data - Message + * @param {Uint8Array} n - RSA public modulus + * @param {Uint8Array} e - RSA public exponent + * @param {Uint8Array} d - RSA private exponent + * @param {Uint8Array} p - RSA private prime p + * @param {Uint8Array} q - RSA private prime q + * @param {Uint8Array} u - RSA private coefficient + * @param {Uint8Array} hashed - Hashed message + * @returns {Promise} RSA Signature. + * @async + */ +async function sign(hashAlgo, data, n, e, d, p, q, u, hashed) { + if (data && !util.isStream(data)) { + if (util.getWebCrypto()) { + try { + return await webSign(enums.read(enums.webHash, hashAlgo), data, n, e, d, p, q, u); + } catch (err) { + util.printDebugError(err); + } + } else if (util.getNodeCrypto()) { + return nodeSign(hashAlgo, data, n, e, d, p, q, u); + } + } + return bnSign(hashAlgo, n, d, hashed); +} + +/** + * Verify signature + * @param {module:enums.hash} hashAlgo - Hash algorithm + * @param {Uint8Array} data - Message + * @param {Uint8Array} s - Signature + * @param {Uint8Array} n - RSA public modulus + * @param {Uint8Array} e - RSA public exponent + * @param {Uint8Array} hashed - Hashed message + * @returns {Boolean} + * @async + */ +async function verify(hashAlgo, data, s, n, e, hashed) { + if (data && !util.isStream(data)) { + if (util.getWebCrypto()) { + try { + return await webVerify(enums.read(enums.webHash, hashAlgo), data, s, n, e); + } catch (err) { + util.printDebugError(err); + } + } else if (util.getNodeCrypto()) { + return nodeVerify(hashAlgo, data, s, n, e); + } + } + return bnVerify(hashAlgo, s, n, e, hashed); +} + +/** + * Encrypt message + * @param {Uint8Array} data - Message + * @param {Uint8Array} n - RSA public modulus + * @param {Uint8Array} e - RSA public exponent + * @returns {Promise} RSA Ciphertext. + * @async + */ +async function encrypt$1(data, n, e) { + if (util.getNodeCrypto()) { + return nodeEncrypt$1(data, n, e); + } + return bnEncrypt(data, n, e); +} + +/** + * Decrypt RSA message + * @param {Uint8Array} m - Message + * @param {Uint8Array} n - RSA public modulus + * @param {Uint8Array} e - RSA public exponent + * @param {Uint8Array} d - RSA private exponent + * @param {Uint8Array} p - RSA private prime p + * @param {Uint8Array} q - RSA private prime q + * @param {Uint8Array} u - RSA private coefficient + * @param {Uint8Array} randomPayload - Data to return on decryption error, instead of throwing + * (needed for constant-time processing) + * @returns {Promise} RSA Plaintext. + * @throws {Error} on decryption error, unless `randomPayload` is given + * @async + */ +async function decrypt$1(data, n, e, d, p, q, u, randomPayload) { + if (util.getNodeCrypto()) { + return nodeDecrypt$1(data, n, e, d, p, q, u, randomPayload); + } + return bnDecrypt(data, n, e, d, p, q, u, randomPayload); +} + +/** + * Generate a new random private key B bits long with public exponent E. + * + * When possible, webCrypto or nodeCrypto is used. Otherwise, primes are generated using + * 40 rounds of the Miller-Rabin probabilistic random prime generation algorithm. + * @see module:crypto/public_key/prime + * @param {Integer} bits - RSA bit length + * @param {Integer} e - RSA public exponent + * @returns {{n, e, d, + * p, q ,u: Uint8Array}} RSA public modulus, RSA public exponent, RSA private exponent, + * RSA private prime p, RSA private prime q, u = p ** -1 mod q + * @async + */ +async function generate(bits, e) { + const BigInteger = await util.getBigInteger(); + + e = new BigInteger(e); + + // Native RSA keygen using Web Crypto + if (util.getWebCrypto()) { + const keyGenOpt = { + name: 'RSASSA-PKCS1-v1_5', + modulusLength: bits, // the specified keysize in bits + publicExponent: e.toUint8Array(), // take three bytes (max 65537) for exponent + hash: { + name: 'SHA-1' // not required for actual RSA keys, but for crypto api 'sign' and 'verify' + } + }; + const keyPair = await webCrypto$5.generateKey(keyGenOpt, true, ['sign', 'verify']); + + // export the generated keys as JsonWebKey (JWK) + // https://tools.ietf.org/html/draft-ietf-jose-json-web-key-33 + const jwk = await webCrypto$5.exportKey('jwk', keyPair.privateKey); + // map JWK parameters to corresponding OpenPGP names + return { + n: b64ToUint8Array(jwk.n), + e: e.toUint8Array(), + d: b64ToUint8Array(jwk.d), + // switch p and q + p: b64ToUint8Array(jwk.q), + q: b64ToUint8Array(jwk.p), + // Since p and q are switched in places, u is the inverse of jwk.q + u: b64ToUint8Array(jwk.qi) + }; + } else if (util.getNodeCrypto() && nodeCrypto$6.generateKeyPair && RSAPrivateKey) { + const opts = { + modulusLength: bits, + publicExponent: e.toNumber(), + publicKeyEncoding: { type: 'pkcs1', format: 'der' }, + privateKeyEncoding: { type: 'pkcs1', format: 'der' } + }; + const prv = await new Promise((resolve, reject) => nodeCrypto$6.generateKeyPair('rsa', opts, (err, _, der) => { + if (err) { + reject(err); + } else { + resolve(RSAPrivateKey.decode(der, 'der')); + } + })); + /** + * OpenPGP spec differs from DER spec, DER: `u = (inverse of q) mod p`, OpenPGP: `u = (inverse of p) mod q`. + * @link https://tools.ietf.org/html/rfc3447#section-3.2 + * @link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-08#section-5.6.1 + */ + return { + n: prv.modulus.toArrayLike(Uint8Array), + e: prv.publicExponent.toArrayLike(Uint8Array), + d: prv.privateExponent.toArrayLike(Uint8Array), + // switch p and q + p: prv.prime2.toArrayLike(Uint8Array), + q: prv.prime1.toArrayLike(Uint8Array), + // Since p and q are switched in places, we can keep u as defined by DER + u: prv.coefficient.toArrayLike(Uint8Array) + }; + } + + // RSA keygen fallback using 40 iterations of the Miller-Rabin test + // See https://stackoverflow.com/a/6330138 for justification + // Also see section C.3 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST + let p; + let q; + let n; + do { + q = await randomProbablePrime(bits - (bits >> 1), e, 40); + p = await randomProbablePrime(bits >> 1, e, 40); + n = p.mul(q); + } while (n.bitLength() !== bits); + + const phi = p.dec().imul(q.dec()); + + if (q.lt(p)) { + [p, q] = [q, p]; + } + + return { + n: n.toUint8Array(), + e: e.toUint8Array(), + d: e.modInv(phi).toUint8Array(), + p: p.toUint8Array(), + q: q.toUint8Array(), + // dp: d.mod(p.subn(1)), + // dq: d.mod(q.subn(1)), + u: p.modInv(q).toUint8Array() + }; +} + +/** + * Validate RSA parameters + * @param {Uint8Array} n - RSA public modulus + * @param {Uint8Array} e - RSA public exponent + * @param {Uint8Array} d - RSA private exponent + * @param {Uint8Array} p - RSA private prime p + * @param {Uint8Array} q - RSA private prime q + * @param {Uint8Array} u - RSA inverse of p w.r.t. q + * @returns {Promise} Whether params are valid. + * @async + */ +async function validateParams(n, e, d, p, q, u) { + const BigInteger = await util.getBigInteger(); + n = new BigInteger(n); + p = new BigInteger(p); + q = new BigInteger(q); + + // expect pq = n + if (!p.mul(q).equal(n)) { + return false; + } + + const two = new BigInteger(2); + // expect p*u = 1 mod q + u = new BigInteger(u); + if (!p.mul(u).mod(q).isOne()) { + return false; + } + + e = new BigInteger(e); + d = new BigInteger(d); + /** + * In RSA pkcs#1 the exponents (d, e) are inverses modulo lcm(p-1, q-1) + * We check that [de = 1 mod (p-1)] and [de = 1 mod (q-1)] + * By CRT on coprime factors of (p-1, q-1) it follows that [de = 1 mod lcm(p-1, q-1)] + * + * We blind the multiplication with r, and check that rde = r mod lcm(p-1, q-1) + */ + const nSizeOver3 = new BigInteger(Math.floor(n.bitLength() / 3)); + const r = await getRandomBigInteger(two, two.leftShift(nSizeOver3)); // r in [ 2, 2^{|n|/3} ) < p and q + const rde = r.mul(d).mul(e); + + const areInverses = rde.mod(p.dec()).equal(r) && rde.mod(q.dec()).equal(r); + if (!areInverses) { + return false; + } + + return true; +} + +async function bnSign(hashAlgo, n, d, hashed) { + const BigInteger = await util.getBigInteger(); + n = new BigInteger(n); + const m = new BigInteger(await emsaEncode(hashAlgo, hashed, n.byteLength())); + d = new BigInteger(d); + if (m.gte(n)) { + throw new Error('Message size cannot exceed modulus size'); + } + return m.modExp(d, n).toUint8Array('be', n.byteLength()); +} + +async function webSign(hashName, data, n, e, d, p, q, u) { + /** OpenPGP keys require that p < q, and Safari Web Crypto requires that p > q. + * We swap them in privateToJWK, so it usually works out, but nevertheless, + * not all OpenPGP keys are compatible with this requirement. + * OpenPGP.js used to generate RSA keys the wrong way around (p > q), and still + * does if the underlying Web Crypto does so (e.g. old MS Edge 50% of the time). + */ + const jwk = await privateToJWK(n, e, d, p, q, u); + const algo = { + name: 'RSASSA-PKCS1-v1_5', + hash: { name: hashName } + }; + const key = await webCrypto$5.importKey('jwk', jwk, algo, false, ['sign']); + // add hash field for ms edge support + return new Uint8Array(await webCrypto$5.sign({ 'name': 'RSASSA-PKCS1-v1_5', 'hash': hashName }, key, data)); +} + +async function nodeSign(hashAlgo, data, n, e, d, p, q, u) { + const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); + const pBNum = new BN(p); + const qBNum = new BN(q); + const dBNum = new BN(d); + const dq = dBNum.mod(qBNum.subn(1)); // d mod (q-1) + const dp = dBNum.mod(pBNum.subn(1)); // d mod (p-1) + const sign = nodeCrypto$6.createSign(enums.read(enums.hash, hashAlgo)); + sign.write(data); + sign.end(); + const keyObject = { + version: 0, + modulus: new BN(n), + publicExponent: new BN(e), + privateExponent: new BN(d), + // switch p and q + prime1: new BN(q), + prime2: new BN(p), + // switch dp and dq + exponent1: dq, + exponent2: dp, + coefficient: new BN(u) + }; + if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { //from version 11.6.0 Node supports der encoded key objects + const der = RSAPrivateKey.encode(keyObject, 'der'); + return new Uint8Array(sign.sign({ key: der, format: 'der', type: 'pkcs1' })); + } + const pem = RSAPrivateKey.encode(keyObject, 'pem', { + label: 'RSA PRIVATE KEY' + }); + return new Uint8Array(sign.sign(pem)); +} + +async function bnVerify(hashAlgo, s, n, e, hashed) { + const BigInteger = await util.getBigInteger(); + n = new BigInteger(n); + s = new BigInteger(s); + e = new BigInteger(e); + if (s.gte(n)) { + throw new Error('Signature size cannot exceed modulus size'); + } + const EM1 = s.modExp(e, n).toUint8Array('be', n.byteLength()); + const EM2 = await emsaEncode(hashAlgo, hashed, n.byteLength()); + return util.equalsUint8Array(EM1, EM2); +} + +async function webVerify(hashName, data, s, n, e) { + const jwk = publicToJWK(n, e); + const key = await webCrypto$5.importKey('jwk', jwk, { + name: 'RSASSA-PKCS1-v1_5', + hash: { name: hashName } + }, false, ['verify']); + // add hash field for ms edge support + return webCrypto$5.verify({ 'name': 'RSASSA-PKCS1-v1_5', 'hash': hashName }, key, s, data); +} + +async function nodeVerify(hashAlgo, data, s, n, e) { + const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); + + const verify = nodeCrypto$6.createVerify(enums.read(enums.hash, hashAlgo)); + verify.write(data); + verify.end(); + const keyObject = { + modulus: new BN(n), + publicExponent: new BN(e) + }; + let key; + if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { //from version 11.6.0 Node supports der encoded key objects + const der = RSAPublicKey.encode(keyObject, 'der'); + key = { key: der, format: 'der', type: 'pkcs1' }; + } else { + key = RSAPublicKey.encode(keyObject, 'pem', { + label: 'RSA PUBLIC KEY' + }); + } + try { + return await verify.verify(key, s); + } catch (err) { + return false; + } +} + +async function nodeEncrypt$1(data, n, e) { + const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); + + const keyObject = { + modulus: new BN(n), + publicExponent: new BN(e) + }; + let key; + if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { + const der = RSAPublicKey.encode(keyObject, 'der'); + key = { key: der, format: 'der', type: 'pkcs1', padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; + } else { + const pem = RSAPublicKey.encode(keyObject, 'pem', { + label: 'RSA PUBLIC KEY' + }); + key = { key: pem, padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; + } + return new Uint8Array(nodeCrypto$6.publicEncrypt(key, data)); +} + +async function bnEncrypt(data, n, e) { + const BigInteger = await util.getBigInteger(); + n = new BigInteger(n); + data = new BigInteger(await emeEncode(data, n.byteLength())); + e = new BigInteger(e); + if (data.gte(n)) { + throw new Error('Message size cannot exceed modulus size'); + } + return data.modExp(e, n).toUint8Array('be', n.byteLength()); +} + +async function nodeDecrypt$1(data, n, e, d, p, q, u, randomPayload) { + const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); + + const pBNum = new BN(p); + const qBNum = new BN(q); + const dBNum = new BN(d); + const dq = dBNum.mod(qBNum.subn(1)); // d mod (q-1) + const dp = dBNum.mod(pBNum.subn(1)); // d mod (p-1) + const keyObject = { + version: 0, + modulus: new BN(n), + publicExponent: new BN(e), + privateExponent: new BN(d), + // switch p and q + prime1: new BN(q), + prime2: new BN(p), + // switch dp and dq + exponent1: dq, + exponent2: dp, + coefficient: new BN(u) + }; + let key; + if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { + const der = RSAPrivateKey.encode(keyObject, 'der'); + key = { key: der, format: 'der' , type: 'pkcs1', padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; + } else { + const pem = RSAPrivateKey.encode(keyObject, 'pem', { + label: 'RSA PRIVATE KEY' + }); + key = { key: pem, padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; + } + try { + return new Uint8Array(nodeCrypto$6.privateDecrypt(key, data)); + } catch (err) { + if (randomPayload) { + return randomPayload; + } + throw new Error('Decryption error'); + } +} + +async function bnDecrypt(data, n, e, d, p, q, u, randomPayload) { + const BigInteger = await util.getBigInteger(); + data = new BigInteger(data); + n = new BigInteger(n); + e = new BigInteger(e); + d = new BigInteger(d); + p = new BigInteger(p); + q = new BigInteger(q); + u = new BigInteger(u); + if (data.gte(n)) { + throw new Error('Data too large.'); + } + const dq = d.mod(q.dec()); // d mod (q-1) + const dp = d.mod(p.dec()); // d mod (p-1) + + const unblinder = (await getRandomBigInteger(new BigInteger(2), n)).mod(n); + const blinder = unblinder.modInv(n).modExp(e, n); + data = data.mul(blinder).mod(n); + + + const mp = data.modExp(dp, p); // data**{d mod (q-1)} mod p + const mq = data.modExp(dq, q); // data**{d mod (p-1)} mod q + const h = u.mul(mq.sub(mp)).mod(q); // u * (mq-mp) mod q (operands already < q) + + let result = h.mul(p).add(mp); // result < n due to relations above + + result = result.mul(unblinder).mod(n); + + + return emeDecode(result.toUint8Array('be', n.byteLength()), randomPayload); +} + +/** Convert Openpgp private key params to jwk key according to + * @link https://tools.ietf.org/html/rfc7517 + * @param {String} hashAlgo + * @param {Uint8Array} n + * @param {Uint8Array} e + * @param {Uint8Array} d + * @param {Uint8Array} p + * @param {Uint8Array} q + * @param {Uint8Array} u + */ +async function privateToJWK(n, e, d, p, q, u) { + const BigInteger = await util.getBigInteger(); + const pNum = new BigInteger(p); + const qNum = new BigInteger(q); + const dNum = new BigInteger(d); + + let dq = dNum.mod(qNum.dec()); // d mod (q-1) + let dp = dNum.mod(pNum.dec()); // d mod (p-1) + dp = dp.toUint8Array(); + dq = dq.toUint8Array(); + return { + kty: 'RSA', + n: uint8ArrayToB64(n, true), + e: uint8ArrayToB64(e, true), + d: uint8ArrayToB64(d, true), + // switch p and q + p: uint8ArrayToB64(q, true), + q: uint8ArrayToB64(p, true), + // switch dp and dq + dp: uint8ArrayToB64(dq, true), + dq: uint8ArrayToB64(dp, true), + qi: uint8ArrayToB64(u, true), + ext: true + }; +} + +/** Convert Openpgp key public params to jwk key according to + * @link https://tools.ietf.org/html/rfc7517 + * @param {String} hashAlgo + * @param {Uint8Array} n + * @param {Uint8Array} e + */ +function publicToJWK(n, e) { + return { + kty: 'RSA', + n: uint8ArrayToB64(n, true), + e: uint8ArrayToB64(e, true), + ext: true + }; +} + +var rsa = /*#__PURE__*/Object.freeze({ + __proto__: null, + sign: sign, + verify: verify, + encrypt: encrypt$1, + decrypt: decrypt$1, + generate: generate, + validateParams: validateParams +}); + +// GPG4Browsers - An OpenPGP implementation in javascript + +/** + * ElGamal Encryption function + * Note that in OpenPGP, the message needs to be padded with PKCS#1 (same as RSA) + * @param {Uint8Array} data - To be padded and encrypted + * @param {Uint8Array} p + * @param {Uint8Array} g + * @param {Uint8Array} y + * @returns {Promise<{ c1: Uint8Array, c2: Uint8Array }>} + * @async + */ +async function encrypt$2(data, p, g, y) { + const BigInteger = await util.getBigInteger(); + p = new BigInteger(p); + g = new BigInteger(g); + y = new BigInteger(y); + + const padded = await emeEncode(data, p.byteLength()); + const m = new BigInteger(padded); + + // OpenPGP uses a "special" version of ElGamal where g is generator of the full group Z/pZ* + // hence g has order p-1, and to avoid that k = 0 mod p-1, we need to pick k in [1, p-2] + const k = await getRandomBigInteger(new BigInteger(1), p.dec()); + return { + c1: g.modExp(k, p).toUint8Array(), + c2: y.modExp(k, p).imul(m).imod(p).toUint8Array() + }; +} + +/** + * ElGamal Encryption function + * @param {Uint8Array} c1 + * @param {Uint8Array} c2 + * @param {Uint8Array} p + * @param {Uint8Array} x + * @param {Uint8Array} randomPayload - Data to return on unpadding error, instead of throwing + * (needed for constant-time processing) + * @returns {Promise} Unpadded message. + * @throws {Error} on decryption error, unless `randomPayload` is given + * @async + */ +async function decrypt$2(c1, c2, p, x, randomPayload) { + const BigInteger = await util.getBigInteger(); + c1 = new BigInteger(c1); + c2 = new BigInteger(c2); + p = new BigInteger(p); + x = new BigInteger(x); + + const padded = c1.modExp(x, p).modInv(p).imul(c2).imod(p); + return emeDecode(padded.toUint8Array('be', p.byteLength()), randomPayload); +} + +/** + * Validate ElGamal parameters + * @param {Uint8Array} p - ElGamal prime + * @param {Uint8Array} g - ElGamal group generator + * @param {Uint8Array} y - ElGamal public key + * @param {Uint8Array} x - ElGamal private exponent + * @returns {Promise} Whether params are valid. + * @async + */ +async function validateParams$1(p, g, y, x) { + const BigInteger = await util.getBigInteger(); + p = new BigInteger(p); + g = new BigInteger(g); + y = new BigInteger(y); + + const one = new BigInteger(1); + // Check that 1 < g < p + if (g.lte(one) || g.gte(p)) { + return false; + } + + // Expect p-1 to be large + const pSize = new BigInteger(p.bitLength()); + const n1023 = new BigInteger(1023); + if (pSize.lt(n1023)) { + return false; + } + + /** + * g should have order p-1 + * Check that g ** (p-1) = 1 mod p + */ + if (!g.modExp(p.dec(), p).isOne()) { + return false; + } + + /** + * Since p-1 is not prime, g might have a smaller order that divides p-1 + * We want to make sure that the order is large enough to hinder a small subgroup attack + * + * We just check g**i != 1 for all i up to a threshold + */ + let res = g; + const i = new BigInteger(1); + const threshold = new BigInteger(2).leftShift(new BigInteger(17)); // we want order > threshold + while (i.lt(threshold)) { + res = res.mul(g).imod(p); + if (res.isOne()) { + return false; + } + i.iinc(); + } + + /** + * Re-derive public key y' = g ** x mod p + * Expect y == y' + * + * Blinded exponentiation computes g**{r(p-1) + x} to compare to y + */ + x = new BigInteger(x); + const two = new BigInteger(2); + const r = await getRandomBigInteger(two.leftShift(pSize.dec()), two.leftShift(pSize)); // draw r of same size as p-1 + const rqx = p.dec().imul(r).iadd(x); + if (!y.equal(g.modExp(rqx, p))) { + return false; + } + + return true; +} + +var elgamal = /*#__PURE__*/Object.freeze({ + __proto__: null, + encrypt: encrypt$2, + decrypt: decrypt$2, + validateParams: validateParams$1 +}); + +// OpenPGP.js - An OpenPGP implementation in javascript + +class OID { + constructor(oid) { + if (oid instanceof OID) { + this.oid = oid.oid; + } else if (util.isArray(oid) || + util.isUint8Array(oid)) { + oid = new Uint8Array(oid); + if (oid[0] === 0x06) { // DER encoded oid byte array + if (oid[1] !== oid.length - 2) { + throw new Error('Length mismatch in DER encoded oid'); + } + oid = oid.subarray(2); + } + this.oid = oid; + } else { + this.oid = ''; + } + } + + /** + * Method to read an OID object + * @param {Uint8Array} input - Where to read the OID from + * @returns {Number} Number of read bytes. + */ + read(input) { + if (input.length >= 1) { + const length = input[0]; + if (input.length >= 1 + length) { + this.oid = input.subarray(1, 1 + length); + return 1 + this.oid.length; + } + } + throw new Error('Invalid oid'); + } + + /** + * Serialize an OID object + * @returns {Uint8Array} Array with the serialized value the OID. + */ + write() { + return util.concatUint8Array([new Uint8Array([this.oid.length]), this.oid]); + } + + /** + * Serialize an OID object as a hex string + * @returns {string} String with the hex value of the OID. + */ + toHex() { + return util.uint8ArrayToHex(this.oid); + } + + /** + * If a known curve object identifier, return the canonical name of the curve + * @returns {string} String with the canonical name of the curve. + */ + getName() { + const hex = this.toHex(); + if (enums.curve[hex]) { + return enums.write(enums.curve, hex); + } else { + throw new Error('Unknown curve object identifier.'); + } + } +} + +// OpenPGP.js - An OpenPGP implementation in javascript + +function keyFromPrivate(indutnyCurve, priv) { + const keyPair = indutnyCurve.keyPair({ priv: priv }); + return keyPair; +} + +function keyFromPublic(indutnyCurve, pub) { + const keyPair = indutnyCurve.keyPair({ pub: pub }); + if (keyPair.validate().result !== true) { + throw new Error('Invalid elliptic public key'); + } + return keyPair; +} + +async function getIndutnyCurve(name) { + if (!defaultConfig.useIndutnyElliptic) { + throw new Error('This curve is only supported in the full build of OpenPGP.js'); + } + const { default: elliptic } = await Promise.resolve().then(function () { return elliptic$1; }); + return new elliptic.ec(name); +} + +// OpenPGP.js - An OpenPGP implementation in javascript + +const webCrypto$6 = util.getWebCrypto(); +const nodeCrypto$7 = util.getNodeCrypto(); + +const webCurves = { + 'p256': 'P-256', + 'p384': 'P-384', + 'p521': 'P-521' +}; +const knownCurves = nodeCrypto$7 ? nodeCrypto$7.getCurves() : []; +const nodeCurves = nodeCrypto$7 ? { + secp256k1: knownCurves.includes('secp256k1') ? 'secp256k1' : undefined, + p256: knownCurves.includes('prime256v1') ? 'prime256v1' : undefined, + p384: knownCurves.includes('secp384r1') ? 'secp384r1' : undefined, + p521: knownCurves.includes('secp521r1') ? 'secp521r1' : undefined, + ed25519: knownCurves.includes('ED25519') ? 'ED25519' : undefined, + curve25519: knownCurves.includes('X25519') ? 'X25519' : undefined, + brainpoolP256r1: knownCurves.includes('brainpoolP256r1') ? 'brainpoolP256r1' : undefined, + brainpoolP384r1: knownCurves.includes('brainpoolP384r1') ? 'brainpoolP384r1' : undefined, + brainpoolP512r1: knownCurves.includes('brainpoolP512r1') ? 'brainpoolP512r1' : undefined +} : {}; + +const curves = { + p256: { + oid: [0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07], + keyType: enums.publicKey.ecdsa, + hash: enums.hash.sha256, + cipher: enums.symmetric.aes128, + node: nodeCurves.p256, + web: webCurves.p256, + payloadSize: 32, + sharedSize: 256 + }, + p384: { + oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22], + keyType: enums.publicKey.ecdsa, + hash: enums.hash.sha384, + cipher: enums.symmetric.aes192, + node: nodeCurves.p384, + web: webCurves.p384, + payloadSize: 48, + sharedSize: 384 + }, + p521: { + oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23], + keyType: enums.publicKey.ecdsa, + hash: enums.hash.sha512, + cipher: enums.symmetric.aes256, + node: nodeCurves.p521, + web: webCurves.p521, + payloadSize: 66, + sharedSize: 528 + }, + secp256k1: { + oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x0A], + keyType: enums.publicKey.ecdsa, + hash: enums.hash.sha256, + cipher: enums.symmetric.aes128, + node: nodeCurves.secp256k1, + payloadSize: 32 + }, + ed25519: { + oid: [0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01], + keyType: enums.publicKey.eddsa, + hash: enums.hash.sha512, + node: false, // nodeCurves.ed25519 TODO + payloadSize: 32 + }, + curve25519: { + oid: [0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01], + keyType: enums.publicKey.ecdh, + hash: enums.hash.sha256, + cipher: enums.symmetric.aes128, + node: false, // nodeCurves.curve25519 TODO + payloadSize: 32 + }, + brainpoolP256r1: { + oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07], + keyType: enums.publicKey.ecdsa, + hash: enums.hash.sha256, + cipher: enums.symmetric.aes128, + node: nodeCurves.brainpoolP256r1, + payloadSize: 32 + }, + brainpoolP384r1: { + oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B], + keyType: enums.publicKey.ecdsa, + hash: enums.hash.sha384, + cipher: enums.symmetric.aes192, + node: nodeCurves.brainpoolP384r1, + payloadSize: 48 + }, + brainpoolP512r1: { + oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D], + keyType: enums.publicKey.ecdsa, + hash: enums.hash.sha512, + cipher: enums.symmetric.aes256, + node: nodeCurves.brainpoolP512r1, + payloadSize: 64 + } +}; + +class Curve { + constructor(oidOrName, params) { + try { + if (util.isArray(oidOrName) || + util.isUint8Array(oidOrName)) { + // by oid byte array + oidOrName = new OID(oidOrName); + } + if (oidOrName instanceof OID) { + // by curve OID + oidOrName = oidOrName.getName(); + } + // by curve name or oid string + this.name = enums.write(enums.curve, oidOrName); + } catch (err) { + throw new Error('Not valid curve'); + } + params = params || curves[this.name]; + + this.keyType = params.keyType; + + this.oid = params.oid; + this.hash = params.hash; + this.cipher = params.cipher; + this.node = params.node && curves[this.name]; + this.web = params.web && curves[this.name]; + this.payloadSize = params.payloadSize; + if (this.web && util.getWebCrypto()) { + this.type = 'web'; + } else if (this.node && util.getNodeCrypto()) { + this.type = 'node'; + } else if (this.name === 'curve25519') { + this.type = 'curve25519'; + } else if (this.name === 'ed25519') { + this.type = 'ed25519'; + } + } + + async genKeyPair() { + let keyPair; + switch (this.type) { + case 'web': + try { + return await webGenKeyPair(this.name); + } catch (err) { + util.printDebugError('Browser did not support generating ec key ' + err.message); + break; + } + case 'node': + return nodeGenKeyPair(this.name); + case 'curve25519': { + const privateKey = await getRandomBytes(32); + privateKey[0] = (privateKey[0] & 127) | 64; + privateKey[31] &= 248; + const secretKey = privateKey.slice().reverse(); + keyPair = naclFastLight.box.keyPair.fromSecretKey(secretKey); + const publicKey = util.concatUint8Array([new Uint8Array([0x40]), keyPair.publicKey]); + return { publicKey, privateKey }; + } + case 'ed25519': { + const privateKey = await getRandomBytes(32); + const keyPair = naclFastLight.sign.keyPair.fromSeed(privateKey); + const publicKey = util.concatUint8Array([new Uint8Array([0x40]), keyPair.publicKey]); + return { publicKey, privateKey }; + } + } + const indutnyCurve = await getIndutnyCurve(this.name); + keyPair = await indutnyCurve.genKeyPair({ + entropy: util.uint8ArrayToString(await getRandomBytes(32)) + }); + return { publicKey: new Uint8Array(keyPair.getPublic('array', false)), privateKey: keyPair.getPrivate().toArrayLike(Uint8Array) }; + } +} + +async function generate$1(curve) { + const BigInteger = await util.getBigInteger(); + + curve = new Curve(curve); + const keyPair = await curve.genKeyPair(); + const Q = new BigInteger(keyPair.publicKey).toUint8Array(); + const secret = new BigInteger(keyPair.privateKey).toUint8Array('be', curve.payloadSize); + return { + oid: curve.oid, + Q, + secret, + hash: curve.hash, + cipher: curve.cipher + }; +} + +/** + * Get preferred hash algo to use with the given curve + * @param {module:type/oid} oid - curve oid + * @returns {enums.hash} hash algorithm + */ +function getPreferredHashAlgo(oid) { + return curves[enums.write(enums.curve, oid.toHex())].hash; +} + +/** + * Validate ECDH and ECDSA parameters + * Not suitable for EdDSA (different secret key format) + * @param {module:enums.publicKey} algo - EC algorithm, to filter supported curves + * @param {module:type/oid} oid - EC object identifier + * @param {Uint8Array} Q - EC public point + * @param {Uint8Array} d - EC secret scalar + * @returns {Promise} Whether params are valid. + * @async + */ +async function validateStandardParams(algo, oid, Q, d) { + const supportedCurves = { + p256: true, + p384: true, + p521: true, + secp256k1: true, + curve25519: algo === enums.publicKey.ecdh, + brainpoolP256r1: true, + brainpoolP384r1: true, + brainpoolP512r1: true + }; + + // Check whether the given curve is supported + const curveName = oid.getName(); + if (!supportedCurves[curveName]) { + return false; + } + + if (curveName === 'curve25519') { + d = d.slice().reverse(); + // Re-derive public point Q' + const { publicKey } = naclFastLight.box.keyPair.fromSecretKey(d); + + Q = new Uint8Array(Q); + const dG = new Uint8Array([0x40, ...publicKey]); // Add public key prefix + if (!util.equalsUint8Array(dG, Q)) { + return false; + } + + return true; + } + + const curve = await getIndutnyCurve(curveName); + try { + // Parse Q and check that it is on the curve but not at infinity + Q = keyFromPublic(curve, Q).getPublic(); + } catch (validationErrors) { + return false; + } + + /** + * Re-derive public point Q' = dG from private key + * Expect Q == Q' + */ + const dG = keyFromPrivate(curve, d).getPublic(); + if (!dG.eq(Q)) { + return false; + } + + return true; +} + +////////////////////////// +// // +// Helper functions // +// // +////////////////////////// + + +async function webGenKeyPair(name) { + // Note: keys generated with ECDSA and ECDH are structurally equivalent + const webCryptoKey = await webCrypto$6.generateKey({ name: 'ECDSA', namedCurve: webCurves[name] }, true, ['sign', 'verify']); + + const privateKey = await webCrypto$6.exportKey('jwk', webCryptoKey.privateKey); + const publicKey = await webCrypto$6.exportKey('jwk', webCryptoKey.publicKey); + + return { + publicKey: jwkToRawPublic(publicKey), + privateKey: b64ToUint8Array(privateKey.d) + }; +} + +async function nodeGenKeyPair(name) { + // Note: ECDSA and ECDH key generation is structurally equivalent + const ecdh = nodeCrypto$7.createECDH(nodeCurves[name]); + await ecdh.generateKeys(); + return { + publicKey: new Uint8Array(ecdh.getPublicKey()), + privateKey: new Uint8Array(ecdh.getPrivateKey()) + }; +} + +////////////////////////// +// // +// Helper functions // +// // +////////////////////////// + +/** + * @param {JsonWebKey} jwk - key for conversion + * + * @returns {Uint8Array} Raw public key. + */ +function jwkToRawPublic(jwk) { + const bufX = b64ToUint8Array(jwk.x); + const bufY = b64ToUint8Array(jwk.y); + const publicKey = new Uint8Array(bufX.length + bufY.length + 1); + publicKey[0] = 0x04; + publicKey.set(bufX, 1); + publicKey.set(bufY, bufX.length + 1); + return publicKey; +} + +/** + * @param {Integer} payloadSize - ec payload size + * @param {String} name - curve name + * @param {Uint8Array} publicKey - public key + * + * @returns {JsonWebKey} Public key in jwk format. + */ +function rawPublicToJWK(payloadSize, name, publicKey) { + const len = payloadSize; + const bufX = publicKey.slice(1, len + 1); + const bufY = publicKey.slice(len + 1, len * 2 + 1); + // https://www.rfc-editor.org/rfc/rfc7518.txt + const jwk = { + kty: 'EC', + crv: name, + x: uint8ArrayToB64(bufX, true), + y: uint8ArrayToB64(bufY, true), + ext: true + }; + return jwk; +} + +/** + * @param {Integer} payloadSize - ec payload size + * @param {String} name - curve name + * @param {Uint8Array} publicKey - public key + * @param {Uint8Array} privateKey - private key + * + * @returns {JsonWebKey} Private key in jwk format. + */ +function privateToJWK$1(payloadSize, name, publicKey, privateKey) { + const jwk = rawPublicToJWK(payloadSize, name, publicKey); + jwk.d = uint8ArrayToB64(privateKey, true); + return jwk; +} + +const webCrypto$7 = util.getWebCrypto(); +const nodeCrypto$8 = util.getNodeCrypto(); + +/** + * Sign a message using the provided key + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {module:enums.hash} hashAlgo - Hash algorithm used to sign + * @param {Uint8Array} message - Message to sign + * @param {Uint8Array} publicKey - Public key + * @param {Uint8Array} privateKey - Private key used to sign the message + * @param {Uint8Array} hashed - The hashed message + * @returns {Promise<{ + * r: Uint8Array, + * s: Uint8Array + * }>} Signature of the message + * @async + */ +async function sign$1(oid, hashAlgo, message, publicKey, privateKey, hashed) { + const curve = new Curve(oid); + if (message && !util.isStream(message)) { + const keyPair = { publicKey, privateKey }; + switch (curve.type) { + case 'web': { + // If browser doesn't support a curve, we'll catch it + try { + // Need to await to make sure browser succeeds + return await webSign$1(curve, hashAlgo, message, keyPair); + } catch (err) { + // We do not fallback if the error is related to key integrity + // Unfortunaley Safari does not support p521 and throws a DataError when using it + // So we need to always fallback for that curve + if (curve.name !== 'p521' && (err.name === 'DataError' || err.name === 'OperationError')) { + throw err; + } + util.printDebugError('Browser did not support signing: ' + err.message); + } + break; + } + case 'node': { + const signature = await nodeSign$1(curve, hashAlgo, message, keyPair); + return { + r: signature.r.toArrayLike(Uint8Array), + s: signature.s.toArrayLike(Uint8Array) + }; + } + } + } + return ellipticSign(curve, hashed, privateKey); +} + +/** + * Verifies if a signature is valid for a message + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {module:enums.hash} hashAlgo - Hash algorithm used in the signature + * @param {{r: Uint8Array, + s: Uint8Array}} signature Signature to verify + * @param {Uint8Array} message - Message to verify + * @param {Uint8Array} publicKey - Public key used to verify the message + * @param {Uint8Array} hashed - The hashed message + * @returns {Boolean} + * @async + */ +async function verify$1(oid, hashAlgo, signature, message, publicKey, hashed) { + const curve = new Curve(oid); + if (message && !util.isStream(message)) { + switch (curve.type) { + case 'web': + try { + // Need to await to make sure browser succeeds + return await webVerify$1(curve, hashAlgo, signature, message, publicKey); + } catch (err) { + // We do not fallback if the error is related to key integrity + // Unfortunately Safari does not support p521 and throws a DataError when using it + // So we need to always fallback for that curve + if (curve.name !== 'p521' && (err.name === 'DataError' || err.name === 'OperationError')) { + throw err; + } + util.printDebugError('Browser did not support verifying: ' + err.message); + } + break; + case 'node': + return nodeVerify$1(curve, hashAlgo, signature, message, publicKey); + } + } + const digest = (typeof hashAlgo === 'undefined') ? message : hashed; + return ellipticVerify(curve, signature, digest, publicKey); +} + +/** + * Validate ECDSA parameters + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {Uint8Array} Q - ECDSA public point + * @param {Uint8Array} d - ECDSA secret scalar + * @returns {Promise} Whether params are valid. + * @async + */ +async function validateParams$2(oid, Q, d) { + const curve = new Curve(oid); + // Reject curves x25519 and ed25519 + if (curve.keyType !== enums.publicKey.ecdsa) { + return false; + } + + // To speed up the validation, we try to use node- or webcrypto when available + // and sign + verify a random message + switch (curve.type) { + case 'web': + case 'node': { + const message = await getRandomBytes(8); + const hashAlgo = enums.hash.sha256; + const hashed = await hash.digest(hashAlgo, message); + try { + const signature = await sign$1(oid, hashAlgo, message, Q, d, hashed); + return await verify$1(oid, hashAlgo, signature, message, Q, hashed); + } catch (err) { + return false; + } + } + default: + return validateStandardParams(enums.publicKey.ecdsa, oid, Q, d); + } +} + + +////////////////////////// +// // +// Helper functions // +// // +////////////////////////// + +async function ellipticSign(curve, hashed, privateKey) { + const indutnyCurve = await getIndutnyCurve(curve.name); + const key = keyFromPrivate(indutnyCurve, privateKey); + const signature = key.sign(hashed); + return { + r: signature.r.toArrayLike(Uint8Array), + s: signature.s.toArrayLike(Uint8Array) + }; +} + +async function ellipticVerify(curve, signature, digest, publicKey) { + const indutnyCurve = await getIndutnyCurve(curve.name); + const key = keyFromPublic(indutnyCurve, publicKey); + return key.verify(digest, signature); +} + +async function webSign$1(curve, hashAlgo, message, keyPair) { + const len = curve.payloadSize; + const jwk = privateToJWK$1(curve.payloadSize, webCurves[curve.name], keyPair.publicKey, keyPair.privateKey); + const key = await webCrypto$7.importKey( + 'jwk', + jwk, + { + 'name': 'ECDSA', + 'namedCurve': webCurves[curve.name], + 'hash': { name: enums.read(enums.webHash, curve.hash) } + }, + false, + ['sign'] + ); + + const signature = new Uint8Array(await webCrypto$7.sign( + { + 'name': 'ECDSA', + 'namedCurve': webCurves[curve.name], + 'hash': { name: enums.read(enums.webHash, hashAlgo) } + }, + key, + message + )); + + return { + r: signature.slice(0, len), + s: signature.slice(len, len << 1) + }; +} + +async function webVerify$1(curve, hashAlgo, { r, s }, message, publicKey) { + const jwk = rawPublicToJWK(curve.payloadSize, webCurves[curve.name], publicKey); + const key = await webCrypto$7.importKey( + 'jwk', + jwk, + { + 'name': 'ECDSA', + 'namedCurve': webCurves[curve.name], + 'hash': { name: enums.read(enums.webHash, curve.hash) } + }, + false, + ['verify'] + ); + + const signature = util.concatUint8Array([r, s]).buffer; + + return webCrypto$7.verify( + { + 'name': 'ECDSA', + 'namedCurve': webCurves[curve.name], + 'hash': { name: enums.read(enums.webHash, hashAlgo) } + }, + key, + signature, + message + ); +} + +async function nodeSign$1(curve, hashAlgo, message, keyPair) { + const sign = nodeCrypto$8.createSign(enums.read(enums.hash, hashAlgo)); + sign.write(message); + sign.end(); + const key = ECPrivateKey.encode({ + version: 1, + parameters: curve.oid, + privateKey: Array.from(keyPair.privateKey), + publicKey: { unused: 0, data: Array.from(keyPair.publicKey) } + }, 'pem', { + label: 'EC PRIVATE KEY' + }); + + return ECDSASignature.decode(sign.sign(key), 'der'); +} + +async function nodeVerify$1(curve, hashAlgo, { r, s }, message, publicKey) { + const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); + + const verify = nodeCrypto$8.createVerify(enums.read(enums.hash, hashAlgo)); + verify.write(message); + verify.end(); + const key = SubjectPublicKeyInfo.encode({ + algorithm: { + algorithm: [1, 2, 840, 10045, 2, 1], + parameters: curve.oid + }, + subjectPublicKey: { unused: 0, data: Array.from(publicKey) } + }, 'pem', { + label: 'PUBLIC KEY' + }); + const signature = ECDSASignature.encode({ + r: new BN(r), s: new BN(s) + }, 'der'); + + try { + return verify.verify(key, signature); + } catch (err) { + return false; + } +} + +// Originally written by Owen Smith https://github.com/omsmith +// Adapted on Feb 2018 from https://github.com/Brightspace/node-jwk-to-pem/ + +/* eslint-disable no-invalid-this */ + +const asn1$1 = nodeCrypto$8 ? asn1__default['default'] : undefined; + +const ECDSASignature = nodeCrypto$8 ? + asn1$1.define('ECDSASignature', function() { + this.seq().obj( + this.key('r').int(), + this.key('s').int() + ); + }) : undefined; + +const ECPrivateKey = nodeCrypto$8 ? + asn1$1.define('ECPrivateKey', function() { + this.seq().obj( + this.key('version').int(), + this.key('privateKey').octstr(), + this.key('parameters').explicit(0).optional().any(), + this.key('publicKey').explicit(1).optional().bitstr() + ); + }) : undefined; + +const AlgorithmIdentifier = nodeCrypto$8 ? + asn1$1.define('AlgorithmIdentifier', function() { + this.seq().obj( + this.key('algorithm').objid(), + this.key('parameters').optional().any() + ); + }) : undefined; + +const SubjectPublicKeyInfo = nodeCrypto$8 ? + asn1$1.define('SubjectPublicKeyInfo', function() { + this.seq().obj( + this.key('algorithm').use(AlgorithmIdentifier), + this.key('subjectPublicKey').bitstr() + ); + }) : undefined; + +var ecdsa = /*#__PURE__*/Object.freeze({ + __proto__: null, + sign: sign$1, + verify: verify$1, + validateParams: validateParams$2 +}); + +// OpenPGP.js - An OpenPGP implementation in javascript + +naclFastLight.hash = bytes => new Uint8Array(_512().update(bytes).digest()); + +/** + * Sign a message using the provided key + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {module:enums.hash} hashAlgo - Hash algorithm used to sign (must be sha256 or stronger) + * @param {Uint8Array} message - Message to sign + * @param {Uint8Array} publicKey - Public key + * @param {Uint8Array} privateKey - Private key used to sign the message + * @param {Uint8Array} hashed - The hashed message + * @returns {Promise<{ + * r: Uint8Array, + * s: Uint8Array + * }>} Signature of the message + * @async + */ +async function sign$2(oid, hashAlgo, message, publicKey, privateKey, hashed) { + if (hash.getHashByteLength(hashAlgo) < hash.getHashByteLength(enums.hash.sha256)) { + // see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2 + throw new Error('Hash algorithm too weak: sha256 or stronger is required for EdDSA.'); + } + const secretKey = util.concatUint8Array([privateKey, publicKey.subarray(1)]); + const signature = naclFastLight.sign.detached(hashed, secretKey); + // EdDSA signature params are returned in little-endian format + return { + r: signature.subarray(0, 32), + s: signature.subarray(32) + }; +} + +/** + * Verifies if a signature is valid for a message + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {module:enums.hash} hashAlgo - Hash algorithm used in the signature + * @param {{r: Uint8Array, + s: Uint8Array}} signature Signature to verify the message + * @param {Uint8Array} m - Message to verify + * @param {Uint8Array} publicKey - Public key used to verify the message + * @param {Uint8Array} hashed - The hashed message + * @returns {Boolean} + * @async + */ +async function verify$2(oid, hashAlgo, { r, s }, m, publicKey, hashed) { + const signature = util.concatUint8Array([r, s]); + return naclFastLight.sign.detached.verify(hashed, signature, publicKey.subarray(1)); +} +/** + * Validate EdDSA parameters + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {Uint8Array} Q - EdDSA public point + * @param {Uint8Array} k - EdDSA secret seed + * @returns {Promise} Whether params are valid. + * @async + */ +async function validateParams$3(oid, Q, k) { + // Check whether the given curve is supported + if (oid.getName() !== 'ed25519') { + return false; + } + + /** + * Derive public point Q' = dG from private key + * and expect Q == Q' + */ + const { publicKey } = naclFastLight.sign.keyPair.fromSeed(k); + const dG = new Uint8Array([0x40, ...publicKey]); // Add public key prefix + return util.equalsUint8Array(Q, dG); +} + +var eddsa = /*#__PURE__*/Object.freeze({ + __proto__: null, + sign: sign$2, + verify: verify$2, + validateParams: validateParams$3 +}); + +// OpenPGP.js - An OpenPGP implementation in javascript + +/** + * AES key wrap + * @function + * @param {Uint8Array} key + * @param {Uint8Array} data + * @returns {Uint8Array} + */ +function wrap(key, data) { + const aes = new cipher['aes' + (key.length * 8)](key); + const IV = new Uint32Array([0xA6A6A6A6, 0xA6A6A6A6]); + const P = unpack(data); + let A = IV; + const R = P; + const n = P.length / 2; + const t = new Uint32Array([0, 0]); + let B = new Uint32Array(4); + for (let j = 0; j <= 5; ++j) { + for (let i = 0; i < n; ++i) { + t[1] = n * j + (1 + i); + // B = A + B[0] = A[0]; + B[1] = A[1]; + // B = A || R[i] + B[2] = R[2 * i]; + B[3] = R[2 * i + 1]; + // B = AES(K, B) + B = unpack(aes.encrypt(pack(B))); + // A = MSB(64, B) ^ t + A = B.subarray(0, 2); + A[0] ^= t[0]; + A[1] ^= t[1]; + // R[i] = LSB(64, B) + R[2 * i] = B[2]; + R[2 * i + 1] = B[3]; + } + } + return pack(A, R); +} + +/** + * AES key unwrap + * @function + * @param {String} key + * @param {String} data + * @returns {Uint8Array} + * @throws {Error} + */ +function unwrap(key, data) { + const aes = new cipher['aes' + (key.length * 8)](key); + const IV = new Uint32Array([0xA6A6A6A6, 0xA6A6A6A6]); + const C = unpack(data); + let A = C.subarray(0, 2); + const R = C.subarray(2); + const n = C.length / 2 - 1; + const t = new Uint32Array([0, 0]); + let B = new Uint32Array(4); + for (let j = 5; j >= 0; --j) { + for (let i = n - 1; i >= 0; --i) { + t[1] = n * j + (i + 1); + // B = A ^ t + B[0] = A[0] ^ t[0]; + B[1] = A[1] ^ t[1]; + // B = (A ^ t) || R[i] + B[2] = R[2 * i]; + B[3] = R[2 * i + 1]; + // B = AES-1(B) + B = unpack(aes.decrypt(pack(B))); + // A = MSB(64, B) + A = B.subarray(0, 2); + // R[i] = LSB(64, B) + R[2 * i] = B[2]; + R[2 * i + 1] = B[3]; + } + } + if (A[0] === IV[0] && A[1] === IV[1]) { + return pack(R); + } + throw new Error('Key Data Integrity failed'); +} + +function createArrayBuffer(data) { + if (util.isString(data)) { + const { length } = data; + const buffer = new ArrayBuffer(length); + const view = new Uint8Array(buffer); + for (let j = 0; j < length; ++j) { + view[j] = data.charCodeAt(j); + } + return buffer; + } + return new Uint8Array(data).buffer; +} + +function unpack(data) { + const { length } = data; + const buffer = createArrayBuffer(data); + const view = new DataView(buffer); + const arr = new Uint32Array(length / 4); + for (let i = 0; i < length / 4; ++i) { + arr[i] = view.getUint32(4 * i); + } + return arr; +} + +function pack() { + let length = 0; + for (let k = 0; k < arguments.length; ++k) { + length += 4 * arguments[k].length; + } + const buffer = new ArrayBuffer(length); + const view = new DataView(buffer); + let offset = 0; + for (let i = 0; i < arguments.length; ++i) { + for (let j = 0; j < arguments[i].length; ++j) { + view.setUint32(offset + 4 * j, arguments[i][j]); + } + offset += 4 * arguments[i].length; + } + return new Uint8Array(buffer); +} + +var aesKW = /*#__PURE__*/Object.freeze({ + __proto__: null, + wrap: wrap, + unwrap: unwrap +}); + +// OpenPGP.js - An OpenPGP implementation in javascript + +/** + * @fileoverview Functions to add and remove PKCS5 padding + * @see PublicKeyEncryptedSessionKeyPacket + * @module crypto/pkcs5 + * @private + */ + +/** + * Add pkcs5 padding to a message + * @param {Uint8Array} message - message to pad + * @returns {Uint8Array} Padded message. + */ +function encode$1(message) { + const c = 8 - (message.length % 8); + const padded = new Uint8Array(message.length + c).fill(c); + padded.set(message); + return padded; +} + +/** + * Remove pkcs5 padding from a message + * @param {Uint8Array} message - message to remove padding from + * @returns {Uint8Array} Message without padding. + */ +function decode$1(message) { + const len = message.length; + if (len > 0) { + const c = message[len - 1]; + if (c >= 1) { + const provided = message.subarray(len - c); + const computed = new Uint8Array(c).fill(c); + if (util.equalsUint8Array(provided, computed)) { + return message.subarray(0, len - c); + } + } + } + throw new Error('Invalid padding'); +} + +var pkcs5 = /*#__PURE__*/Object.freeze({ + __proto__: null, + encode: encode$1, + decode: decode$1 +}); + +// OpenPGP.js - An OpenPGP implementation in javascript + +class ECDHSymmetricKey { + constructor(data) { + if (typeof data === 'undefined') { + data = new Uint8Array([]); + } else if (util.isString(data)) { + data = util.stringToUint8Array(data); + } else { + data = new Uint8Array(data); + } + this.data = data; + } + + /** + * Read an ECDHSymmetricKey from an Uint8Array + * @param {Uint8Array} input - Where to read the encoded symmetric key from + * @returns {Number} Number of read bytes. + */ + read(input) { + if (input.length >= 1) { + const length = input[0]; + if (input.length >= 1 + length) { + this.data = input.subarray(1, 1 + length); + return 1 + this.data.length; + } + } + throw new Error('Invalid symmetric key'); + } + + /** + * Write an ECDHSymmetricKey as an Uint8Array + * @returns {Uint8Array} An array containing the value + */ + write() { + return util.concatUint8Array([new Uint8Array([this.data.length]), this.data]); + } +} + +// OpenPGP.js - An OpenPGP implementation in javascript +// Copyright (C) 2015-2016 Decentral +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3.0 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +/** + * Implementation of type KDF parameters + * + * {@link https://tools.ietf.org/html/rfc6637#section-7|RFC 6637 7}: + * A key derivation function (KDF) is necessary to implement the EC + * encryption. The Concatenation Key Derivation Function (Approved + * Alternative 1) [NIST-SP800-56A] with the KDF hash function that is + * SHA2-256 [FIPS-180-3] or stronger is REQUIRED. + * @module type/kdf_params + * @private + */ + +class KDFParams { + /** + * @param {enums.hash} hash - Hash algorithm + * @param {enums.symmetric} cipher - Symmetric algorithm + */ + constructor(data) { + if (data) { + const { hash, cipher } = data; + this.hash = hash; + this.cipher = cipher; + } else { + this.hash = null; + this.cipher = null; + } + } + + /** + * Read KDFParams from an Uint8Array + * @param {Uint8Array} input - Where to read the KDFParams from + * @returns {Number} Number of read bytes. + */ + read(input) { + if (input.length < 4 || input[0] !== 3 || input[1] !== 1) { + throw new Error('Cannot read KDFParams'); + } + this.hash = input[2]; + this.cipher = input[3]; + return 4; + } + + /** + * Write KDFParams to an Uint8Array + * @returns {Uint8Array} Array with the KDFParams value + */ + write() { + return new Uint8Array([3, 1, this.hash, this.cipher]); + } +} + +// GPG4Browsers - An OpenPGP implementation in javascript + +/** + * Encrypts data using specified algorithm and public key parameters. + * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} for public key algorithms. + * @param {module:enums.publicKey} algo - Public key algorithm + * @param {Object} publicParams - Algorithm-specific public key parameters + * @param {Uint8Array} data - Data to be encrypted + * @param {Uint8Array} fingerprint - Recipient fingerprint + * @returns {Promise} Encrypted session key parameters. + * @async + */ +async function publicKeyEncrypt(algo, publicParams, data, fingerprint) { + switch (algo) { + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaEncryptSign: { + const { n, e } = publicParams; + const c = await publicKey.rsa.encrypt(data, n, e); + return { c }; + } + case enums.publicKey.elgamal: { + const { p, g, y } = publicParams; + return publicKey.elgamal.encrypt(data, p, g, y); + } + case enums.publicKey.ecdh: { + const { oid, Q, kdfParams } = publicParams; + const { publicKey: V, wrappedKey: C } = await publicKey.elliptic.ecdh.encrypt( + oid, kdfParams, data, Q, fingerprint); + return { V, C: new ECDHSymmetricKey(C) }; + } + default: + return []; + } +} + +/** + * Decrypts data using specified algorithm and private key parameters. + * See {@link https://tools.ietf.org/html/rfc4880#section-5.5.3|RFC 4880 5.5.3} + * @param {module:enums.publicKey} algo - Public key algorithm + * @param {Object} publicKeyParams - Algorithm-specific public key parameters + * @param {Object} privateKeyParams - Algorithm-specific private key parameters + * @param {Object} sessionKeyParams - Encrypted session key parameters + * @param {Uint8Array} fingerprint - Recipient fingerprint + * @param {Uint8Array} [randomPayload] - Data to return on decryption error, instead of throwing + * (needed for constant-time processing in RSA and ElGamal) + * @returns {Promise} Decrypted data. + * @throws {Error} on sensitive decryption error, unless `randomPayload` is given + * @async + */ +async function publicKeyDecrypt(algo, publicKeyParams, privateKeyParams, sessionKeyParams, fingerprint, randomPayload) { + switch (algo) { + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaEncrypt: { + const { c } = sessionKeyParams; + const { n, e } = publicKeyParams; + const { d, p, q, u } = privateKeyParams; + return publicKey.rsa.decrypt(c, n, e, d, p, q, u, randomPayload); + } + case enums.publicKey.elgamal: { + const { c1, c2 } = sessionKeyParams; + const p = publicKeyParams.p; + const x = privateKeyParams.x; + return publicKey.elgamal.decrypt(c1, c2, p, x, randomPayload); + } + case enums.publicKey.ecdh: { + const { oid, Q, kdfParams } = publicKeyParams; + const { d } = privateKeyParams; + const { V, C } = sessionKeyParams; + return publicKey.elliptic.ecdh.decrypt( + oid, kdfParams, V, C.data, Q, d, fingerprint); + } + default: + throw new Error('Invalid public key encryption algorithm.'); + } +} + +/** + * Parse public key material in binary form to get the key parameters + * @param {module:enums.publicKey} algo - The key algorithm + * @param {Uint8Array} bytes - The key material to parse + * @returns {{ read: Number, publicParams: Object }} Number of read bytes plus key parameters referenced by name. + */ +function parsePublicKeyParams(algo, bytes) { + let read = 0; + switch (algo) { + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaSign: { + const n = util.readMPI(bytes.subarray(read)); read += n.length + 2; + const e = util.readMPI(bytes.subarray(read)); read += e.length + 2; + return { read, publicParams: { n, e } }; + } + case enums.publicKey.dsa: { + const p = util.readMPI(bytes.subarray(read)); read += p.length + 2; + const q = util.readMPI(bytes.subarray(read)); read += q.length + 2; + const g = util.readMPI(bytes.subarray(read)); read += g.length + 2; + const y = util.readMPI(bytes.subarray(read)); read += y.length + 2; + return { read, publicParams: { p, q, g, y } }; + } + case enums.publicKey.elgamal: { + const p = util.readMPI(bytes.subarray(read)); read += p.length + 2; + const g = util.readMPI(bytes.subarray(read)); read += g.length + 2; + const y = util.readMPI(bytes.subarray(read)); read += y.length + 2; + return { read, publicParams: { p, g, y } }; + } + case enums.publicKey.ecdsa: { + const oid = new OID(); read += oid.read(bytes); + const Q = util.readMPI(bytes.subarray(read)); read += Q.length + 2; + return { read: read, publicParams: { oid, Q } }; + } + case enums.publicKey.eddsa: { + const oid = new OID(); read += oid.read(bytes); + let Q = util.readMPI(bytes.subarray(read)); read += Q.length + 2; + Q = util.leftPad(Q, 33); + return { read: read, publicParams: { oid, Q } }; + } + case enums.publicKey.ecdh: { + const oid = new OID(); read += oid.read(bytes); + const Q = util.readMPI(bytes.subarray(read)); read += Q.length + 2; + const kdfParams = new KDFParams(); read += kdfParams.read(bytes.subarray(read)); + return { read: read, publicParams: { oid, Q, kdfParams } }; + } + default: + throw new Error('Invalid public key encryption algorithm.'); + } +} + +/** + * Parse private key material in binary form to get the key parameters + * @param {module:enums.publicKey} algo - The key algorithm + * @param {Uint8Array} bytes - The key material to parse + * @param {Object} publicParams - (ECC only) public params, needed to format some private params + * @returns {{ read: Number, privateParams: Object }} Number of read bytes plus the key parameters referenced by name. + */ +function parsePrivateKeyParams(algo, bytes, publicParams) { + let read = 0; + switch (algo) { + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaSign: { + const d = util.readMPI(bytes.subarray(read)); read += d.length + 2; + const p = util.readMPI(bytes.subarray(read)); read += p.length + 2; + const q = util.readMPI(bytes.subarray(read)); read += q.length + 2; + const u = util.readMPI(bytes.subarray(read)); read += u.length + 2; + return { read, privateParams: { d, p, q, u } }; + } + case enums.publicKey.dsa: + case enums.publicKey.elgamal: { + const x = util.readMPI(bytes.subarray(read)); read += x.length + 2; + return { read, privateParams: { x } }; + } + case enums.publicKey.ecdsa: + case enums.publicKey.ecdh: { + const curve = new Curve(publicParams.oid); + let d = util.readMPI(bytes.subarray(read)); read += d.length + 2; + d = util.leftPad(d, curve.payloadSize); + return { read, privateParams: { d } }; + } + case enums.publicKey.eddsa: { + let seed = util.readMPI(bytes.subarray(read)); read += seed.length + 2; + seed = util.leftPad(seed, 32); + return { read, privateParams: { seed } }; + } + default: + throw new Error('Invalid public key encryption algorithm.'); + } +} + +/** Returns the types comprising the encrypted session key of an algorithm + * @param {module:enums.publicKey} algo - The key algorithm + * @param {Uint8Array} bytes - The key material to parse + * @returns {Object} The session key parameters referenced by name. + */ +function parseEncSessionKeyParams(algo, bytes) { + let read = 0; + switch (algo) { + // Algorithm-Specific Fields for RSA encrypted session keys: + // - MPI of RSA encrypted value m**e mod n. + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaEncryptSign: { + const c = util.readMPI(bytes.subarray(read)); + return { c }; + } + + // Algorithm-Specific Fields for Elgamal encrypted session keys: + // - MPI of Elgamal value g**k mod p + // - MPI of Elgamal value m * y**k mod p + case enums.publicKey.elgamal: { + const c1 = util.readMPI(bytes.subarray(read)); read += c1.length + 2; + const c2 = util.readMPI(bytes.subarray(read)); + return { c1, c2 }; + } + // Algorithm-Specific Fields for ECDH encrypted session keys: + // - MPI containing the ephemeral key used to establish the shared secret + // - ECDH Symmetric Key + case enums.publicKey.ecdh: { + const V = util.readMPI(bytes.subarray(read)); read += V.length + 2; + const C = new ECDHSymmetricKey(); C.read(bytes.subarray(read)); + return { V, C }; + } + default: + throw new Error('Invalid public key encryption algorithm.'); + } +} + +/** + * Convert params to MPI and serializes them in the proper order + * @param {module:enums.publicKey} algo - The public key algorithm + * @param {Object} params - The key parameters indexed by name + * @returns {Uint8Array} The array containing the MPIs. + */ +function serializeParams(algo, params) { + const orderedParams = Object.keys(params).map(name => { + const param = params[name]; + return util.isUint8Array(param) ? util.uint8ArrayToMPI(param) : param.write(); + }); + return util.concatUint8Array(orderedParams); +} + +/** + * Generate algorithm-specific key parameters + * @param {module:enums.publicKey} algo - The public key algorithm + * @param {Integer} bits - Bit length for RSA keys + * @param {module:type/oid} oid - Object identifier for ECC keys + * @returns {Promise<{ publicParams: {Object}, privateParams: {Object} }>} The parameters referenced by name. + * @async + */ +function generateParams(algo, bits, oid) { + switch (algo) { + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaSign: { + return publicKey.rsa.generate(bits, 65537).then(({ n, e, d, p, q, u }) => ({ + privateParams: { d, p, q, u }, + publicParams: { n, e } + })); + } + case enums.publicKey.ecdsa: + return publicKey.elliptic.generate(oid).then(({ oid, Q, secret }) => ({ + privateParams: { d: secret }, + publicParams: { oid: new OID(oid), Q } + })); + case enums.publicKey.eddsa: + return publicKey.elliptic.generate(oid).then(({ oid, Q, secret }) => ({ + privateParams: { seed: secret }, + publicParams: { oid: new OID(oid), Q } + })); + case enums.publicKey.ecdh: + return publicKey.elliptic.generate(oid).then(({ oid, Q, secret, hash, cipher }) => ({ + privateParams: { d: secret }, + publicParams: { + oid: new OID(oid), + Q, + kdfParams: new KDFParams({ hash, cipher }) + } + })); + case enums.publicKey.dsa: + case enums.publicKey.elgamal: + throw new Error('Unsupported algorithm for key generation.'); + default: + throw new Error('Invalid public key algorithm.'); + } +} + +/** + * Validate algorithm-specific key parameters + * @param {module:enums.publicKey} algo - The public key algorithm + * @param {Object} publicParams - Algorithm-specific public key parameters + * @param {Object} privateParams - Algorithm-specific private key parameters + * @returns {Promise} Whether the parameters are valid. + * @async + */ +async function validateParams$4(algo, publicParams, privateParams) { + if (!publicParams || !privateParams) { + throw new Error('Missing key parameters'); + } + switch (algo) { + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaSign: { + const { n, e } = publicParams; + const { d, p, q, u } = privateParams; + return publicKey.rsa.validateParams(n, e, d, p, q, u); + } + case enums.publicKey.dsa: { + const { p, q, g, y } = publicParams; + const { x } = privateParams; + return publicKey.dsa.validateParams(p, q, g, y, x); + } + case enums.publicKey.elgamal: { + const { p, g, y } = publicParams; + const { x } = privateParams; + return publicKey.elgamal.validateParams(p, g, y, x); + } + case enums.publicKey.ecdsa: + case enums.publicKey.ecdh: { + const algoModule = publicKey.elliptic[enums.read(enums.publicKey, algo)]; + const { oid, Q } = publicParams; + const { d } = privateParams; + return algoModule.validateParams(oid, Q, d); + } + case enums.publicKey.eddsa: { + const { oid, Q } = publicParams; + const { seed } = privateParams; + return publicKey.elliptic.eddsa.validateParams(oid, Q, seed); + } + default: + throw new Error('Invalid public key algorithm.'); + } +} + +/** + * Generates a random byte prefix for the specified algorithm + * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. + * @param {module:enums.symmetric} algo - Symmetric encryption algorithm + * @returns {Promise} Random bytes with length equal to the block size of the cipher, plus the last two bytes repeated. + * @async + */ +async function getPrefixRandom(algo) { + const { blockSize } = getCipher(algo); + const prefixrandom = await getRandomBytes(blockSize); + const repeat = new Uint8Array([prefixrandom[prefixrandom.length - 2], prefixrandom[prefixrandom.length - 1]]); + return util.concat([prefixrandom, repeat]); +} + +/** + * Generating a session key for the specified symmetric algorithm + * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. + * @param {module:enums.symmetric} algo - Symmetric encryption algorithm + * @returns {Promise} Random bytes as a string to be used as a key. + * @async + */ +function generateSessionKey(algo) { + const { keySize } = getCipher(algo); + return getRandomBytes(keySize); +} + +/** + * Get implementation of the given AEAD mode + * @param {enums.aead} algo + * @returns {Object} + * @throws {Error} on invalid algo + */ +function getAEADMode(algo) { + const algoName = enums.read(enums.aead, algo); + return mode[algoName]; +} + +/** + * Get implementation of the given cipher + * @param {enums.symmetric} algo + * @returns {Object} + * @throws {Error} on invalid algo + */ +function getCipher(algo) { + const algoName = enums.read(enums.symmetric, algo); + return cipher[algoName]; +} + +var crypto$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + publicKeyEncrypt: publicKeyEncrypt, + publicKeyDecrypt: publicKeyDecrypt, + parsePublicKeyParams: parsePublicKeyParams, + parsePrivateKeyParams: parsePrivateKeyParams, + parseEncSessionKeyParams: parseEncSessionKeyParams, + serializeParams: serializeParams, + generateParams: generateParams, + validateParams: validateParams$4, + getPrefixRandom: getPrefixRandom, + generateSessionKey: generateSessionKey, + getAEADMode: getAEADMode, + getCipher: getCipher +}); + +// OpenPGP.js - An OpenPGP implementation in javascript + +const webCrypto$8 = util.getWebCrypto(); +const nodeCrypto$9 = util.getNodeCrypto(); + +/** + * Validate ECDH parameters + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {Uint8Array} Q - ECDH public point + * @param {Uint8Array} d - ECDH secret scalar + * @returns {Promise} Whether params are valid. + * @async + */ +async function validateParams$5(oid, Q, d) { + return validateStandardParams(enums.publicKey.ecdh, oid, Q, d); +} + +// Build Param for ECDH algorithm (RFC 6637) +function buildEcdhParam(public_algo, oid, kdfParams, fingerprint) { + return util.concatUint8Array([ + oid.write(), + new Uint8Array([public_algo]), + kdfParams.write(), + util.stringToUint8Array('Anonymous Sender '), + fingerprint.subarray(0, 20) + ]); +} + +// Key Derivation Function (RFC 6637) +async function kdf(hashAlgo, X, length, param, stripLeading = false, stripTrailing = false) { + // Note: X is little endian for Curve25519, big-endian for all others. + // This is not ideal, but the RFC's are unclear + // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B + let i; + if (stripLeading) { + // Work around old go crypto bug + for (i = 0; i < X.length && X[i] === 0; i++); + X = X.subarray(i); + } + if (stripTrailing) { + // Work around old OpenPGP.js bug + for (i = X.length - 1; i >= 0 && X[i] === 0; i--); + X = X.subarray(0, i + 1); + } + const digest = await hash.digest(hashAlgo, util.concatUint8Array([ + new Uint8Array([0, 0, 0, 1]), + X, + param + ])); + return digest.subarray(0, length); +} + +/** + * Generate ECDHE ephemeral key and secret from public key + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} Q - Recipient public key + * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ +async function genPublicEphemeralKey(curve, Q) { + switch (curve.type) { + case 'curve25519': { + const d = await getRandomBytes(32); + const { secretKey, sharedKey } = await genPrivateEphemeralKey(curve, Q, null, d); + let { publicKey } = naclFastLight.box.keyPair.fromSecretKey(secretKey); + publicKey = util.concatUint8Array([new Uint8Array([0x40]), publicKey]); + return { publicKey, sharedKey }; // Note: sharedKey is little-endian here, unlike below + } + case 'web': + if (curve.web && util.getWebCrypto()) { + try { + return await webPublicEphemeralKey(curve, Q); + } catch (err) { + util.printDebugError(err); + } + } + break; + case 'node': + return nodePublicEphemeralKey(curve, Q); + } + return ellipticPublicEphemeralKey(curve, Q); +} + +/** + * Encrypt and wrap a session key + * + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {module:type/kdf_params} kdfParams - KDF params including cipher and algorithm to use + * @param {Uint8Array} data - Unpadded session key data + * @param {Uint8Array} Q - Recipient public key + * @param {Uint8Array} fingerprint - Recipient fingerprint + * @returns {Promise<{publicKey: Uint8Array, wrappedKey: Uint8Array}>} + * @async + */ +async function encrypt$3(oid, kdfParams, data, Q, fingerprint) { + const m = encode$1(data); + + const curve = new Curve(oid); + const { publicKey, sharedKey } = await genPublicEphemeralKey(curve, Q); + const param = buildEcdhParam(enums.publicKey.ecdh, oid, kdfParams, fingerprint); + const { keySize } = getCipher(kdfParams.cipher); + const Z = await kdf(kdfParams.hash, sharedKey, keySize, param); + const wrappedKey = wrap(Z, m); + return { publicKey, wrappedKey }; +} + +/** + * Generate ECDHE secret from private key and public part of ephemeral key + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} V - Public part of ephemeral key + * @param {Uint8Array} Q - Recipient public key + * @param {Uint8Array} d - Recipient private key + * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ +async function genPrivateEphemeralKey(curve, V, Q, d) { + if (d.length !== curve.payloadSize) { + const privateKey = new Uint8Array(curve.payloadSize); + privateKey.set(d, curve.payloadSize - d.length); + d = privateKey; + } + switch (curve.type) { + case 'curve25519': { + const secretKey = d.slice().reverse(); + const sharedKey = naclFastLight.scalarMult(secretKey, V.subarray(1)); + return { secretKey, sharedKey }; // Note: sharedKey is little-endian here, unlike below + } + case 'web': + if (curve.web && util.getWebCrypto()) { + try { + return await webPrivateEphemeralKey(curve, V, Q, d); + } catch (err) { + util.printDebugError(err); + } + } + break; + case 'node': + return nodePrivateEphemeralKey(curve, V, d); + } + return ellipticPrivateEphemeralKey(curve, V, d); +} + +/** + * Decrypt and unwrap the value derived from session key + * + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {module:type/kdf_params} kdfParams - KDF params including cipher and algorithm to use + * @param {Uint8Array} V - Public part of ephemeral key + * @param {Uint8Array} C - Encrypted and wrapped value derived from session key + * @param {Uint8Array} Q - Recipient public key + * @param {Uint8Array} d - Recipient private key + * @param {Uint8Array} fingerprint - Recipient fingerprint + * @returns {Promise} Value derived from session key. + * @async + */ +async function decrypt$3(oid, kdfParams, V, C, Q, d, fingerprint) { + const curve = new Curve(oid); + const { sharedKey } = await genPrivateEphemeralKey(curve, V, Q, d); + const param = buildEcdhParam(enums.publicKey.ecdh, oid, kdfParams, fingerprint); + const { keySize } = getCipher(kdfParams.cipher); + let err; + for (let i = 0; i < 3; i++) { + try { + // Work around old go crypto bug and old OpenPGP.js bug, respectively. + const Z = await kdf(kdfParams.hash, sharedKey, keySize, param, i === 1, i === 2); + return decode$1(unwrap(Z, C)); + } catch (e) { + err = e; + } + } + throw err; +} + +/** + * Generate ECDHE secret from private key and public part of ephemeral key using webCrypto + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} V - Public part of ephemeral key + * @param {Uint8Array} Q - Recipient public key + * @param {Uint8Array} d - Recipient private key + * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ +async function webPrivateEphemeralKey(curve, V, Q, d) { + const recipient = privateToJWK$1(curve.payloadSize, curve.web.web, Q, d); + let privateKey = webCrypto$8.importKey( + 'jwk', + recipient, + { + name: 'ECDH', + namedCurve: curve.web.web + }, + true, + ['deriveKey', 'deriveBits'] + ); + const jwk = rawPublicToJWK(curve.payloadSize, curve.web.web, V); + let sender = webCrypto$8.importKey( + 'jwk', + jwk, + { + name: 'ECDH', + namedCurve: curve.web.web + }, + true, + [] + ); + [privateKey, sender] = await Promise.all([privateKey, sender]); + let S = webCrypto$8.deriveBits( + { + name: 'ECDH', + namedCurve: curve.web.web, + public: sender + }, + privateKey, + curve.web.sharedSize + ); + let secret = webCrypto$8.exportKey( + 'jwk', + privateKey + ); + [S, secret] = await Promise.all([S, secret]); + const sharedKey = new Uint8Array(S); + const secretKey = b64ToUint8Array(secret.d); + return { secretKey, sharedKey }; +} + +/** + * Generate ECDHE ephemeral key and secret from public key using webCrypto + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} Q - Recipient public key + * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ +async function webPublicEphemeralKey(curve, Q) { + const jwk = rawPublicToJWK(curve.payloadSize, curve.web.web, Q); + let keyPair = webCrypto$8.generateKey( + { + name: 'ECDH', + namedCurve: curve.web.web + }, + true, + ['deriveKey', 'deriveBits'] + ); + let recipient = webCrypto$8.importKey( + 'jwk', + jwk, + { + name: 'ECDH', + namedCurve: curve.web.web + }, + false, + [] + ); + [keyPair, recipient] = await Promise.all([keyPair, recipient]); + let s = webCrypto$8.deriveBits( + { + name: 'ECDH', + namedCurve: curve.web.web, + public: recipient + }, + keyPair.privateKey, + curve.web.sharedSize + ); + let p = webCrypto$8.exportKey( + 'jwk', + keyPair.publicKey + ); + [s, p] = await Promise.all([s, p]); + const sharedKey = new Uint8Array(s); + const publicKey = new Uint8Array(jwkToRawPublic(p)); + return { publicKey, sharedKey }; +} + +/** + * Generate ECDHE secret from private key and public part of ephemeral key using indutny/elliptic + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} V - Public part of ephemeral key + * @param {Uint8Array} d - Recipient private key + * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ +async function ellipticPrivateEphemeralKey(curve, V, d) { + const indutnyCurve = await getIndutnyCurve(curve.name); + V = keyFromPublic(indutnyCurve, V); + d = keyFromPrivate(indutnyCurve, d); + const secretKey = new Uint8Array(d.getPrivate()); + const S = d.derive(V.getPublic()); + const len = indutnyCurve.curve.p.byteLength(); + const sharedKey = S.toArrayLike(Uint8Array, 'be', len); + return { secretKey, sharedKey }; +} + +/** + * Generate ECDHE ephemeral key and secret from public key using indutny/elliptic + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} Q - Recipient public key + * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ +async function ellipticPublicEphemeralKey(curve, Q) { + const indutnyCurve = await getIndutnyCurve(curve.name); + const v = await curve.genKeyPair(); + Q = keyFromPublic(indutnyCurve, Q); + const V = keyFromPrivate(indutnyCurve, v.privateKey); + const publicKey = v.publicKey; + const S = V.derive(Q.getPublic()); + const len = indutnyCurve.curve.p.byteLength(); + const sharedKey = S.toArrayLike(Uint8Array, 'be', len); + return { publicKey, sharedKey }; +} + +/** + * Generate ECDHE secret from private key and public part of ephemeral key using nodeCrypto + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} V - Public part of ephemeral key + * @param {Uint8Array} d - Recipient private key + * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ +async function nodePrivateEphemeralKey(curve, V, d) { + const recipient = nodeCrypto$9.createECDH(curve.node.node); + recipient.setPrivateKey(d); + const sharedKey = new Uint8Array(recipient.computeSecret(V)); + const secretKey = new Uint8Array(recipient.getPrivateKey()); + return { secretKey, sharedKey }; +} + +/** + * Generate ECDHE ephemeral key and secret from public key using nodeCrypto + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} Q - Recipient public key + * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ +async function nodePublicEphemeralKey(curve, Q) { + const sender = nodeCrypto$9.createECDH(curve.node.node); + sender.generateKeys(); + const sharedKey = new Uint8Array(sender.computeSecret(Q)); + const publicKey = new Uint8Array(sender.getPublicKey()); + return { publicKey, sharedKey }; +} + +var ecdh = /*#__PURE__*/Object.freeze({ + __proto__: null, + validateParams: validateParams$5, + encrypt: encrypt$3, + decrypt: decrypt$3 +}); + +// OpenPGP.js - An OpenPGP implementation in javascript + +var elliptic = /*#__PURE__*/Object.freeze({ + __proto__: null, + Curve: Curve, + ecdh: ecdh, + ecdsa: ecdsa, + eddsa: eddsa, + generate: generate$1, + getPreferredHashAlgo: getPreferredHashAlgo +}); + +// GPG4Browsers - An OpenPGP implementation in javascript + +/* + TODO regarding the hash function, read: + https://tools.ietf.org/html/rfc4880#section-13.6 + https://tools.ietf.org/html/rfc4880#section-14 +*/ + +/** + * DSA Sign function + * @param {Integer} hashAlgo + * @param {Uint8Array} hashed + * @param {Uint8Array} g + * @param {Uint8Array} p + * @param {Uint8Array} q + * @param {Uint8Array} x + * @returns {Promise<{ r: Uint8Array, s: Uint8Array }>} + * @async + */ +async function sign$3(hashAlgo, hashed, g, p, q, x) { + const BigInteger = await util.getBigInteger(); + const one = new BigInteger(1); + p = new BigInteger(p); + q = new BigInteger(q); + g = new BigInteger(g); + x = new BigInteger(x); + + let k; + let r; + let s; + let t; + g = g.mod(p); + x = x.mod(q); + // If the output size of the chosen hash is larger than the number of + // bits of q, the hash result is truncated to fit by taking the number + // of leftmost bits equal to the number of bits of q. This (possibly + // truncated) hash function result is treated as a number and used + // directly in the DSA signature algorithm. + const h = new BigInteger(hashed.subarray(0, q.byteLength())).mod(q); + // FIPS-186-4, section 4.6: + // The values of r and s shall be checked to determine if r = 0 or s = 0. + // If either r = 0 or s = 0, a new value of k shall be generated, and the + // signature shall be recalculated. It is extremely unlikely that r = 0 + // or s = 0 if signatures are generated properly. + while (true) { + // See Appendix B here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf + k = await getRandomBigInteger(one, q); // returns in [1, q-1] + r = g.modExp(k, p).imod(q); // (g**k mod p) mod q + if (r.isZero()) { + continue; + } + const xr = x.mul(r).imod(q); + t = h.add(xr).imod(q); // H(m) + x*r mod q + s = k.modInv(q).imul(t).imod(q); // k**-1 * (H(m) + x*r) mod q + if (s.isZero()) { + continue; + } + break; + } + return { + r: r.toUint8Array('be', q.byteLength()), + s: s.toUint8Array('be', q.byteLength()) + }; +} + +/** + * DSA Verify function + * @param {Integer} hashAlgo + * @param {Uint8Array} r + * @param {Uint8Array} s + * @param {Uint8Array} hashed + * @param {Uint8Array} g + * @param {Uint8Array} p + * @param {Uint8Array} q + * @param {Uint8Array} y + * @returns {boolean} + * @async + */ +async function verify$3(hashAlgo, r, s, hashed, g, p, q, y) { + const BigInteger = await util.getBigInteger(); + const zero = new BigInteger(0); + r = new BigInteger(r); + s = new BigInteger(s); + + p = new BigInteger(p); + q = new BigInteger(q); + g = new BigInteger(g); + y = new BigInteger(y); + + if (r.lte(zero) || r.gte(q) || + s.lte(zero) || s.gte(q)) { + util.printDebug('invalid DSA Signature'); + return false; + } + const h = new BigInteger(hashed.subarray(0, q.byteLength())).imod(q); + const w = s.modInv(q); // s**-1 mod q + if (w.isZero()) { + util.printDebug('invalid DSA Signature'); + return false; + } + + g = g.mod(p); + y = y.mod(p); + const u1 = h.mul(w).imod(q); // H(m) * w mod q + const u2 = r.mul(w).imod(q); // r * w mod q + const t1 = g.modExp(u1, p); // g**u1 mod p + const t2 = y.modExp(u2, p); // y**u2 mod p + const v = t1.mul(t2).imod(p).imod(q); // (g**u1 * y**u2 mod p) mod q + return v.equal(r); +} + +/** + * Validate DSA parameters + * @param {Uint8Array} p - DSA prime + * @param {Uint8Array} q - DSA group order + * @param {Uint8Array} g - DSA sub-group generator + * @param {Uint8Array} y - DSA public key + * @param {Uint8Array} x - DSA private key + * @returns {Promise} Whether params are valid. + * @async + */ +async function validateParams$6(p, q, g, y, x) { + const BigInteger = await util.getBigInteger(); + p = new BigInteger(p); + q = new BigInteger(q); + g = new BigInteger(g); + y = new BigInteger(y); + const one = new BigInteger(1); + // Check that 1 < g < p + if (g.lte(one) || g.gte(p)) { + return false; + } + + /** + * Check that subgroup order q divides p-1 + */ + if (!p.dec().mod(q).isZero()) { + return false; + } + + /** + * g has order q + * Check that g ** q = 1 mod p + */ + if (!g.modExp(q, p).isOne()) { + return false; + } + + /** + * Check q is large and probably prime (we mainly want to avoid small factors) + */ + const qSize = new BigInteger(q.bitLength()); + const n150 = new BigInteger(150); + if (qSize.lt(n150) || !(await isProbablePrime(q, null, 32))) { + return false; + } + + /** + * Re-derive public key y' = g ** x mod p + * Expect y == y' + * + * Blinded exponentiation computes g**{rq + x} to compare to y + */ + x = new BigInteger(x); + const two = new BigInteger(2); + const r = await getRandomBigInteger(two.leftShift(qSize.dec()), two.leftShift(qSize)); // draw r of same size as q + const rqx = q.mul(r).add(x); + if (!y.equal(g.modExp(rqx, p))) { + return false; + } + + return true; +} + +var dsa = /*#__PURE__*/Object.freeze({ + __proto__: null, + sign: sign$3, + verify: verify$3, + validateParams: validateParams$6 +}); + +/** + * @fileoverview Asymmetric cryptography functions + * @module crypto/public_key + * @private + */ + +var publicKey = { + /** @see module:crypto/public_key/rsa */ + rsa: rsa, + /** @see module:crypto/public_key/elgamal */ + elgamal: elgamal, + /** @see module:crypto/public_key/elliptic */ + elliptic: elliptic, + /** @see module:crypto/public_key/dsa */ + dsa: dsa, + /** @see tweetnacl */ + nacl: naclFastLight +}; + +/** + * @fileoverview Provides functions for asymmetric signing and signature verification + * @module crypto/signature + * @private + */ + +/** + * Parse signature in binary form to get the parameters. + * The returned values are only padded for EdDSA, since in the other cases their expected length + * depends on the key params, hence we delegate the padding to the signature verification function. + * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} + * See {@link https://tools.ietf.org/html/rfc4880#section-5.2.2|RFC 4880 5.2.2.} + * @param {module:enums.publicKey} algo - Public key algorithm + * @param {Uint8Array} signature - Data for which the signature was created + * @returns {Promise} True if signature is valid. + * @async + */ +function parseSignatureParams(algo, signature) { + let read = 0; + switch (algo) { + // Algorithm-Specific Fields for RSA signatures: + // - MPI of RSA signature value m**d mod n. + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaSign: { + const s = util.readMPI(signature.subarray(read)); + // The signature needs to be the same length as the public key modulo n. + // We pad s on signature verification, where we have access to n. + return { s }; + } + // Algorithm-Specific Fields for DSA or ECDSA signatures: + // - MPI of DSA or ECDSA value r. + // - MPI of DSA or ECDSA value s. + case enums.publicKey.dsa: + case enums.publicKey.ecdsa: + { + const r = util.readMPI(signature.subarray(read)); read += r.length + 2; + const s = util.readMPI(signature.subarray(read)); + return { r, s }; + } + // Algorithm-Specific Fields for EdDSA signatures: + // - MPI of an EC point r. + // - EdDSA value s, in MPI, in the little endian representation + case enums.publicKey.eddsa: { + // When parsing little-endian MPI data, we always need to left-pad it, as done with big-endian values: + // https://www.ietf.org/archive/id/draft-ietf-openpgp-rfc4880bis-10.html#section-3.2-9 + let r = util.readMPI(signature.subarray(read)); read += r.length + 2; + r = util.leftPad(r, 32); + let s = util.readMPI(signature.subarray(read)); + s = util.leftPad(s, 32); + return { r, s }; + } + default: + throw new Error('Invalid signature algorithm.'); + } +} + +/** + * Verifies the signature provided for data using specified algorithms and public key parameters. + * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} + * and {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4} + * for public key and hash algorithms. + * @param {module:enums.publicKey} algo - Public key algorithm + * @param {module:enums.hash} hashAlgo - Hash algorithm + * @param {Object} signature - Named algorithm-specific signature parameters + * @param {Object} publicParams - Algorithm-specific public key parameters + * @param {Uint8Array} data - Data for which the signature was created + * @param {Uint8Array} hashed - The hashed data + * @returns {Promise} True if signature is valid. + * @async + */ +async function verify$4(algo, hashAlgo, signature, publicParams, data, hashed) { + switch (algo) { + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaSign: { + const { n, e } = publicParams; + const s = util.leftPad(signature.s, n.length); // padding needed for webcrypto and node crypto + return publicKey.rsa.verify(hashAlgo, data, s, n, e, hashed); + } + case enums.publicKey.dsa: { + const { g, p, q, y } = publicParams; + const { r, s } = signature; // no need to pad, since we always handle them as BigIntegers + return publicKey.dsa.verify(hashAlgo, r, s, hashed, g, p, q, y); + } + case enums.publicKey.ecdsa: { + const { oid, Q } = publicParams; + const curveSize = new publicKey.elliptic.Curve(oid).payloadSize; + // padding needed for webcrypto + const r = util.leftPad(signature.r, curveSize); + const s = util.leftPad(signature.s, curveSize); + return publicKey.elliptic.ecdsa.verify(oid, hashAlgo, { r, s }, data, Q, hashed); + } + case enums.publicKey.eddsa: { + const { oid, Q } = publicParams; + // signature already padded on parsing + return publicKey.elliptic.eddsa.verify(oid, hashAlgo, signature, data, Q, hashed); + } + default: + throw new Error('Invalid signature algorithm.'); + } +} + +/** + * Creates a signature on data using specified algorithms and private key parameters. + * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} + * and {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4} + * for public key and hash algorithms. + * @param {module:enums.publicKey} algo - Public key algorithm + * @param {module:enums.hash} hashAlgo - Hash algorithm + * @param {Object} publicKeyParams - Algorithm-specific public and private key parameters + * @param {Object} privateKeyParams - Algorithm-specific public and private key parameters + * @param {Uint8Array} data - Data to be signed + * @param {Uint8Array} hashed - The hashed data + * @returns {Promise} Signature Object containing named signature parameters. + * @async + */ +async function sign$4(algo, hashAlgo, publicKeyParams, privateKeyParams, data, hashed) { + if (!publicKeyParams || !privateKeyParams) { + throw new Error('Missing key parameters'); + } + switch (algo) { + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaSign: { + const { n, e } = publicKeyParams; + const { d, p, q, u } = privateKeyParams; + const s = await publicKey.rsa.sign(hashAlgo, data, n, e, d, p, q, u, hashed); + return { s }; + } + case enums.publicKey.dsa: { + const { g, p, q } = publicKeyParams; + const { x } = privateKeyParams; + return publicKey.dsa.sign(hashAlgo, hashed, g, p, q, x); + } + case enums.publicKey.elgamal: { + throw new Error('Signing with Elgamal is not defined in the OpenPGP standard.'); + } + case enums.publicKey.ecdsa: { + const { oid, Q } = publicKeyParams; + const { d } = privateKeyParams; + return publicKey.elliptic.ecdsa.sign(oid, hashAlgo, data, Q, d, hashed); + } + case enums.publicKey.eddsa: { + const { oid, Q } = publicKeyParams; + const { seed } = privateKeyParams; + return publicKey.elliptic.eddsa.sign(oid, hashAlgo, data, Q, seed, hashed); + } + default: + throw new Error('Invalid signature algorithm.'); + } +} + +var signature = /*#__PURE__*/Object.freeze({ + __proto__: null, + parseSignatureParams: parseSignatureParams, + verify: verify$4, + sign: sign$4 +}); + +/** + * @fileoverview Provides access to all cryptographic primitives used in OpenPGP.js + * @see module:crypto/crypto + * @see module:crypto/signature + * @see module:crypto/public_key + * @see module:crypto/cipher + * @see module:crypto/random + * @see module:crypto/hash + * @module crypto + * @private + */ + +// TODO move cfb and gcm to cipher +const mod = { + /** @see module:crypto/cipher */ + cipher: cipher, + /** @see module:crypto/hash */ + hash: hash, + /** @see module:crypto/mode */ + mode: mode, + /** @see module:crypto/public_key */ + publicKey: publicKey, + /** @see module:crypto/signature */ + signature: signature, + /** @see module:crypto/random */ + random: random, + /** @see module:crypto/pkcs1 */ + pkcs1: pkcs1, + /** @see module:crypto/pkcs5 */ + pkcs5: pkcs5, + /** @see module:crypto/aes_kw */ + aesKW: aesKW +}; + +Object.assign(mod, crypto$1); + +var TYPED_OK = typeof Uint8Array !== "undefined" && + typeof Uint16Array !== "undefined" && + typeof Int32Array !== "undefined"; + + +// reduce buffer size, avoiding mem copy +function shrinkBuf(buf, size) { + if (buf.length === size) { + return buf; + } + if (buf.subarray) { + return buf.subarray(0, size); + } + buf.length = size; + return buf; +} + + +const fnTyped = { + arraySet: function (dest, src, src_offs, len, dest_offs) { + if (src.subarray && dest.subarray) { + dest.set(src.subarray(src_offs, src_offs + len), dest_offs); + return; + } + // Fallback to ordinary array + for (let i = 0; i < len; i++) { + dest[dest_offs + i] = src[src_offs + i]; + } + }, + // Join array of chunks to single array. + flattenChunks: function (chunks) { + let i, l, len, pos, chunk; + + // calculate data length + len = 0; + for (i = 0, l = chunks.length; i < l; i++) { + len += chunks[i].length; + } + + // join chunks + const result = new Uint8Array(len); + pos = 0; + for (i = 0, l = chunks.length; i < l; i++) { + chunk = chunks[i]; + result.set(chunk, pos); + pos += chunk.length; + } + + return result; + } +}; + +const fnUntyped = { + arraySet: function (dest, src, src_offs, len, dest_offs) { + for (let i = 0; i < len; i++) { + dest[dest_offs + i] = src[src_offs + i]; + } + }, + // Join array of chunks to single array. + flattenChunks: function (chunks) { + return [].concat.apply([], chunks); + } +}; + + +// Enable/Disable typed arrays use, for testing +// + +let Buf8 = TYPED_OK ? Uint8Array : Array; +let Buf16 = TYPED_OK ? Uint16Array : Array; +let Buf32 = TYPED_OK ? Int32Array : Array; +let flattenChunks = TYPED_OK ? fnTyped.flattenChunks : fnUntyped.flattenChunks; +let arraySet = TYPED_OK ? fnTyped.arraySet : fnUntyped.arraySet; + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +/* Allowed flush values; see deflate() and inflate() below for details */ +const Z_NO_FLUSH = 0; +const Z_PARTIAL_FLUSH = 1; +const Z_SYNC_FLUSH = 2; +const Z_FULL_FLUSH = 3; +const Z_FINISH = 4; +const Z_BLOCK = 5; +const Z_TREES = 6; + +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ +const Z_OK = 0; +const Z_STREAM_END = 1; +const Z_NEED_DICT = 2; +const Z_STREAM_ERROR = -2; +const Z_DATA_ERROR = -3; +//export const Z_MEM_ERROR = -4; +const Z_BUF_ERROR = -5; +const Z_DEFAULT_COMPRESSION = -1; + + +const Z_FILTERED = 1; +const Z_HUFFMAN_ONLY = 2; +const Z_RLE = 3; +const Z_FIXED = 4; +const Z_DEFAULT_STRATEGY = 0; + +/* Possible values of the data_type field (though see inflate()) */ +const Z_BINARY = 0; +const Z_TEXT = 1; +//export const Z_ASCII = 1; // = Z_TEXT (deprecated) +const Z_UNKNOWN = 2; + +/* The deflate compression method */ +const Z_DEFLATED = 8; +//export const Z_NULL = null // Use -1 or null inline, depending on var type + +/*============================================================================*/ + + +function zero$1(buf) { + let len = buf.length; while (--len >= 0) { + buf[len] = 0; + } +} + +// From zutil.h + +const STORED_BLOCK = 0; +const STATIC_TREES = 1; +const DYN_TREES = 2; +/* The three kinds of block type */ + +const MIN_MATCH = 3; +const MAX_MATCH = 258; +/* The minimum and maximum match lengths */ + +// From deflate.h +/* =========================================================================== + * Internal compression state. + */ + +const LENGTH_CODES = 29; +/* number of length codes, not counting the special END_BLOCK code */ + +const LITERALS = 256; +/* number of literal bytes 0..255 */ + +const L_CODES = LITERALS + 1 + LENGTH_CODES; +/* number of Literal or Length codes, including the END_BLOCK code */ + +const D_CODES = 30; +/* number of distance codes */ + +const BL_CODES = 19; +/* number of codes used to transfer the bit lengths */ + +const HEAP_SIZE = 2 * L_CODES + 1; +/* maximum heap size */ + +const MAX_BITS = 15; +/* All codes must not exceed MAX_BITS bits */ + +const Buf_size = 16; +/* size of bit buffer in bi_buf */ + + +/* =========================================================================== + * Constants + */ + +const MAX_BL_BITS = 7; +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +const END_BLOCK = 256; +/* end of block literal code */ + +const REP_3_6 = 16; +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +const REPZ_3_10 = 17; +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +const REPZ_11_138 = 18; +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +/* eslint-disable comma-spacing,array-bracket-spacing */ +const extra_lbits = /* extra bits for each length code */ + [0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0]; + +const extra_dbits = /* extra bits for each distance code */ + [0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13]; + +const extra_blbits = /* extra bits for each bit length code */ + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7]; + +const bl_order = + [16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]; +/* eslint-enable comma-spacing,array-bracket-spacing */ + +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +// We pre-fill arrays with 0 to avoid uninitialized gaps + +const DIST_CODE_LEN = 512; /* see definition of array dist_code below */ + +// !!!! Use flat array instead of structure, Freq = i*2, Len = i*2+1 +const static_ltree = new Array((L_CODES + 2) * 2); +zero$1(static_ltree); +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +const static_dtree = new Array(D_CODES * 2); +zero$1(static_dtree); +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +const _dist_code = new Array(DIST_CODE_LEN); +zero$1(_dist_code); +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +const _length_code = new Array(MAX_MATCH - MIN_MATCH + 1); +zero$1(_length_code); +/* length code for each normalized match length (0 == MIN_MATCH) */ + +const base_length = new Array(LENGTH_CODES); +zero$1(base_length); +/* First normalized length for each code (0 = MIN_MATCH) */ + +const base_dist = new Array(D_CODES); +zero$1(base_dist); +/* First normalized distance for each code (0 = distance of 1) */ + + +function StaticTreeDesc(static_tree, extra_bits, extra_base, elems, max_length) { + + this.static_tree = static_tree; /* static tree or NULL */ + this.extra_bits = extra_bits; /* extra bits for each code or NULL */ + this.extra_base = extra_base; /* base index for extra_bits */ + this.elems = elems; /* max number of elements in the tree */ + this.max_length = max_length; /* max bit length for the codes */ + + // show if `static_tree` has data or dummy - needed for monomorphic objects + this.has_stree = static_tree && static_tree.length; +} + + +let static_l_desc; +let static_d_desc; +let static_bl_desc; + + +function TreeDesc(dyn_tree, stat_desc) { + this.dyn_tree = dyn_tree; /* the dynamic tree */ + this.max_code = 0; /* largest code with non zero frequency */ + this.stat_desc = stat_desc; /* the corresponding static tree */ +} + + + +function d_code(dist) { + return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)]; +} + + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +function put_short(s, w) { +// put_byte(s, (uch)((w) & 0xff)); +// put_byte(s, (uch)((ush)(w) >> 8)); + s.pending_buf[s.pending++] = w & 0xff; + s.pending_buf[s.pending++] = w >>> 8 & 0xff; +} + + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +function send_bits(s, value, length) { + if (s.bi_valid > Buf_size - length) { + s.bi_buf |= value << s.bi_valid & 0xffff; + put_short(s, s.bi_buf); + s.bi_buf = value >> Buf_size - s.bi_valid; + s.bi_valid += length - Buf_size; + } else { + s.bi_buf |= value << s.bi_valid & 0xffff; + s.bi_valid += length; + } +} + + +function send_code(s, c, tree) { + send_bits(s, tree[c * 2]/*.Code*/, tree[c * 2 + 1]/*.Len*/); +} + + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +function bi_reverse(code, len) { + let res = 0; + do { + res |= code & 1; + code >>>= 1; + res <<= 1; + } while (--len > 0); + return res >>> 1; +} + + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +function bi_flush(s) { + if (s.bi_valid === 16) { + put_short(s, s.bi_buf); + s.bi_buf = 0; + s.bi_valid = 0; + + } else if (s.bi_valid >= 8) { + s.pending_buf[s.pending++] = s.bi_buf & 0xff; + s.bi_buf >>= 8; + s.bi_valid -= 8; + } +} + + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +function gen_bitlen(s, desc) +// deflate_state *s; +// tree_desc *desc; /* the tree descriptor */ +{ + const tree = desc.dyn_tree; + const max_code = desc.max_code; + const stree = desc.stat_desc.static_tree; + const has_stree = desc.stat_desc.has_stree; + const extra = desc.stat_desc.extra_bits; + const base = desc.stat_desc.extra_base; + const max_length = desc.stat_desc.max_length; + let h; /* heap index */ + let n, m; /* iterate over the tree elements */ + let bits; /* bit length */ + let xbits; /* extra bits */ + let f; /* frequency */ + let overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) { + s.bl_count[bits] = 0; + } + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s.heap[s.heap_max] * 2 + 1]/*.Len*/ = 0; /* root of the heap */ + + for (h = s.heap_max + 1; h < HEAP_SIZE; h++) { + n = s.heap[h]; + bits = tree[tree[n * 2 + 1]/*.Dad*/ * 2 + 1]/*.Len*/ + 1; + if (bits > max_length) { + bits = max_length; + overflow++; + } + tree[n * 2 + 1]/*.Len*/ = bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) { + continue; + } /* not a leaf node */ + + s.bl_count[bits]++; + xbits = 0; + if (n >= base) { + xbits = extra[n - base]; + } + f = tree[n * 2]/*.Freq*/; + s.opt_len += f * (bits + xbits); + if (has_stree) { + s.static_len += f * (stree[n * 2 + 1]/*.Len*/ + xbits); + } + } + if (overflow === 0) { + return; + } + + // Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length - 1; + while (s.bl_count[bits] === 0) { + bits--; + } + s.bl_count[bits]--; /* move one leaf down the tree */ + s.bl_count[bits + 1] += 2; /* move one overflow item as its brother */ + s.bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits !== 0; bits--) { + n = s.bl_count[bits]; + while (n !== 0) { + m = s.heap[--h]; + if (m > max_code) { + continue; + } + if (tree[m * 2 + 1]/*.Len*/ !== bits) { + // Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s.opt_len += (bits - tree[m * 2 + 1]/*.Len*/) * tree[m * 2]/*.Freq*/; + tree[m * 2 + 1]/*.Len*/ = bits; + } + n--; + } + } +} + + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +function gen_codes(tree, max_code, bl_count) +// ct_data *tree; /* the tree to decorate */ +// int max_code; /* largest code with non zero frequency */ +// ushf *bl_count; /* number of codes at each bit length */ +{ + const next_code = new Array(MAX_BITS + 1); /* next code value for each bit length */ + let code = 0; /* running code value */ + let bits; /* bit index */ + let n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = code + bl_count[bits - 1] << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + //Assert (code + bl_count[MAX_BITS]-1 == (1< length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES - 1; code++) { + base_length[code] = length; + for (n = 0; n < 1 << extra_lbits[code]; n++) { + _length_code[length++] = code; + } + } + //Assert (length == 256, "tr_static_init: length != 256"); + /* Note that the length 255 (match length 258) can be represented + * in two different ways: code 284 + 5 bits or code 285, so we + * overwrite length_code[255] to use the best encoding: + */ + _length_code[length - 1] = code; + + /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ + dist = 0; + for (code = 0; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < 1 << extra_dbits[code]; n++) { + _dist_code[dist++] = code; + } + } + //Assert (dist == 256, "tr_static_init: dist != 256"); + dist >>= 7; /* from now on, all distances are divided by 128 */ + for (; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < 1 << extra_dbits[code] - 7; n++) { + _dist_code[256 + dist++] = code; + } + } + //Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) { + bl_count[bits] = 0; + } + + n = 0; + while (n <= 143) { + static_ltree[n * 2 + 1]/*.Len*/ = 8; + n++; + bl_count[8]++; + } + while (n <= 255) { + static_ltree[n * 2 + 1]/*.Len*/ = 9; + n++; + bl_count[9]++; + } + while (n <= 279) { + static_ltree[n * 2 + 1]/*.Len*/ = 7; + n++; + bl_count[7]++; + } + while (n <= 287) { + static_ltree[n * 2 + 1]/*.Len*/ = 8; + n++; + bl_count[8]++; + } + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes(static_ltree, L_CODES + 1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n * 2 + 1]/*.Len*/ = 5; + static_dtree[n * 2]/*.Code*/ = bi_reverse(n, 5); + } + + // Now data ready and we can init static trees + static_l_desc = new StaticTreeDesc(static_ltree, extra_lbits, LITERALS + 1, L_CODES, MAX_BITS); + static_d_desc = new StaticTreeDesc(static_dtree, extra_dbits, 0, D_CODES, MAX_BITS); + static_bl_desc = new StaticTreeDesc(new Array(0), extra_blbits, 0, BL_CODES, MAX_BL_BITS); + + //static_init_done = true; +} + + +/* =========================================================================== + * Initialize a new block. + */ +function init_block(s) { + let n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) { + s.dyn_ltree[n * 2]/*.Freq*/ = 0; + } + for (n = 0; n < D_CODES; n++) { + s.dyn_dtree[n * 2]/*.Freq*/ = 0; + } + for (n = 0; n < BL_CODES; n++) { + s.bl_tree[n * 2]/*.Freq*/ = 0; + } + + s.dyn_ltree[END_BLOCK * 2]/*.Freq*/ = 1; + s.opt_len = s.static_len = 0; + s.last_lit = s.matches = 0; +} + + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +function bi_windup(s) { + if (s.bi_valid > 8) { + put_short(s, s.bi_buf); + } else if (s.bi_valid > 0) { + //put_byte(s, (Byte)s->bi_buf); + s.pending_buf[s.pending++] = s.bi_buf; + } + s.bi_buf = 0; + s.bi_valid = 0; +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +function copy_block(s, buf, len, header) +//DeflateState *s; +//charf *buf; /* the input data */ +//unsigned len; /* its length */ +//int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + + if (header) { + put_short(s, len); + put_short(s, ~len); + } + // while (len--) { + // put_byte(s, *buf++); + // } + arraySet(s.pending_buf, s.window, buf, len, s.pending); + s.pending += len; +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +function smaller(tree, n, m, depth) { + const _n2 = n * 2; + const _m2 = m * 2; + return tree[_n2]/*.Freq*/ < tree[_m2]/*.Freq*/ || + tree[_n2]/*.Freq*/ === tree[_m2]/*.Freq*/ && depth[n] <= depth[m]; +} + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +function pqdownheap(s, tree, k) +// deflate_state *s; +// ct_data *tree; /* the tree to restore */ +// int k; /* node to move down */ +{ + const v = s.heap[k]; + let j = k << 1; /* left son of k */ + while (j <= s.heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s.heap_len && + smaller(tree, s.heap[j + 1], s.heap[j], s.depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s.heap[j], s.depth)) { + break; + } + + /* Exchange v with the smallest son */ + s.heap[k] = s.heap[j]; + k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s.heap[k] = v; +} + + +// inlined manually +// var SMALLEST = 1; + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +function compress_block(s, ltree, dtree) +// deflate_state *s; +// const ct_data *ltree; /* literal tree */ +// const ct_data *dtree; /* distance tree */ +{ + let dist; /* distance of matched string */ + let lc; /* match length or unmatched char (if dist == 0) */ + let lx = 0; /* running index in l_buf */ + let code; /* the code to send */ + let extra; /* number of extra bits to send */ + + if (s.last_lit !== 0) { + do { + dist = s.pending_buf[s.d_buf + lx * 2] << 8 | s.pending_buf[s.d_buf + lx * 2 + 1]; + lc = s.pending_buf[s.l_buf + lx]; + lx++; + + if (dist === 0) { + send_code(s, lc, ltree); /* send a literal byte */ + //Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code + LITERALS + 1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra !== 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + //Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra !== 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + //Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + // "pendingBuf overflow"); + + } while (lx < s.last_lit); + } + + send_code(s, END_BLOCK, ltree); +} + + +/* =========================================================================== + * Construct one Huffman tree and assigns the code bit strings and lengths. + * Update the total bit length for the current block. + * IN assertion: the field freq is set for all tree elements. + * OUT assertions: the fields len and code are set to the optimal bit length + * and corresponding code. The length opt_len is updated; static_len is + * also updated if stree is not null. The field max_code is set. + */ +function build_tree(s, desc) +// deflate_state *s; +// tree_desc *desc; /* the tree descriptor */ +{ + const tree = desc.dyn_tree; + const stree = desc.stat_desc.static_tree; + const has_stree = desc.stat_desc.has_stree; + const elems = desc.stat_desc.elems; + let n, m; /* iterate over heap elements */ + let max_code = -1; /* largest code with non zero frequency */ + let node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s.heap_len = 0; + s.heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n * 2]/*.Freq*/ !== 0) { + s.heap[++s.heap_len] = max_code = n; + s.depth[n] = 0; + + } else { + tree[n * 2 + 1]/*.Len*/ = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s.heap_len < 2) { + node = s.heap[++s.heap_len] = max_code < 2 ? ++max_code : 0; + tree[node * 2]/*.Freq*/ = 1; + s.depth[node] = 0; + s.opt_len--; + + if (has_stree) { + s.static_len -= stree[node * 2 + 1]/*.Len*/; + } + /* node is 0 or 1 so it does not have extra bits */ + } + desc.max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s.heap_len >> 1/*int /2*/; n >= 1; n--) { + pqdownheap(s, tree, n); + } + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + //pqremove(s, tree, n); /* n = node of least frequency */ + /*** pqremove ***/ + n = s.heap[1/*SMALLEST*/]; + s.heap[1/*SMALLEST*/] = s.heap[s.heap_len--]; + pqdownheap(s, tree, 1/*SMALLEST*/); + /***/ + + m = s.heap[1/*SMALLEST*/]; /* m = node of next least frequency */ + + s.heap[--s.heap_max] = n; /* keep the nodes sorted by frequency */ + s.heap[--s.heap_max] = m; + + /* Create a new node father of n and m */ + tree[node * 2]/*.Freq*/ = tree[n * 2]/*.Freq*/ + tree[m * 2]/*.Freq*/; + s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1; + tree[n * 2 + 1]/*.Dad*/ = tree[m * 2 + 1]/*.Dad*/ = node; + + /* and insert the new node in the heap */ + s.heap[1/*SMALLEST*/] = node++; + pqdownheap(s, tree, 1/*SMALLEST*/); + + } while (s.heap_len >= 2); + + s.heap[--s.heap_max] = s.heap[1/*SMALLEST*/]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes(tree, max_code, s.bl_count); +} + + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +function scan_tree(s, tree, max_code) +// deflate_state *s; +// ct_data *tree; /* the tree to be scanned */ +// int max_code; /* and its largest code of non zero frequency */ +{ + let n; /* iterates over all tree elements */ + let prevlen = -1; /* last emitted length */ + let curlen; /* length of current code */ + + let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */ + + let count = 0; /* repeat count of the current code */ + let max_count = 7; /* max repeat count */ + let min_count = 4; /* min repeat count */ + + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } + tree[(max_code + 1) * 2 + 1]/*.Len*/ = 0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[(n + 1) * 2 + 1]/*.Len*/; + + if (++count < max_count && curlen === nextlen) { + continue; + + } else if (count < min_count) { + s.bl_tree[curlen * 2]/*.Freq*/ += count; + + } else if (curlen !== 0) { + + if (curlen !== prevlen) { + s.bl_tree[curlen * 2]/*.Freq*/++; + } + s.bl_tree[REP_3_6 * 2]/*.Freq*/++; + + } else if (count <= 10) { + s.bl_tree[REPZ_3_10 * 2]/*.Freq*/++; + + } else { + s.bl_tree[REPZ_11_138 * 2]/*.Freq*/++; + } + + count = 0; + prevlen = curlen; + + if (nextlen === 0) { + max_count = 138; + min_count = 3; + + } else if (curlen === nextlen) { + max_count = 6; + min_count = 3; + + } else { + max_count = 7; + min_count = 4; + } + } +} + + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +function send_tree(s, tree, max_code) +// deflate_state *s; +// ct_data *tree; /* the tree to be scanned */ +// int max_code; /* and its largest code of non zero frequency */ +{ + let n; /* iterates over all tree elements */ + let prevlen = -1; /* last emitted length */ + let curlen; /* length of current code */ + + let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */ + + let count = 0; /* repeat count of the current code */ + let max_count = 7; /* max repeat count */ + let min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[(n + 1) * 2 + 1]/*.Len*/; + + if (++count < max_count && curlen === nextlen) { + continue; + + } else if (count < min_count) { + do { + send_code(s, curlen, s.bl_tree); + } while (--count !== 0); + + } else if (curlen !== 0) { + if (curlen !== prevlen) { + send_code(s, curlen, s.bl_tree); + count--; + } + //Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s.bl_tree); + send_bits(s, count - 3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s.bl_tree); + send_bits(s, count - 3, 3); + + } else { + send_code(s, REPZ_11_138, s.bl_tree); + send_bits(s, count - 11, 7); + } + + count = 0; + prevlen = curlen; + if (nextlen === 0) { + max_count = 138; + min_count = 3; + + } else if (curlen === nextlen) { + max_count = 6; + min_count = 3; + + } else { + max_count = 7; + min_count = 4; + } + } +} + + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +function build_bl_tree(s) { + let max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, s.dyn_ltree, s.l_desc.max_code); + scan_tree(s, s.dyn_dtree, s.d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, s.bl_desc); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) { + if (s.bl_tree[bl_order[max_blindex] * 2 + 1]/*.Len*/ !== 0) { + break; + } + } + /* Update opt_len to include the bit length tree and counts */ + s.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4; + //Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + // s->opt_len, s->static_len)); + + return max_blindex; +} + + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +function send_all_trees(s, lcodes, dcodes, blcodes) +// deflate_state *s; +// int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + let rank; /* index in bl_order */ + + //Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + //Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + // "too many codes"); + //Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes - 1, 5); + send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + //Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s.bl_tree[bl_order[rank] * 2 + 1]/*.Len*/, 3); + } + //Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, s.dyn_ltree, lcodes - 1); /* literal tree */ + //Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, s.dyn_dtree, dcodes - 1); /* distance tree */ + //Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + + +/* =========================================================================== + * Check if the data type is TEXT or BINARY, using the following algorithm: + * - TEXT if the two conditions below are satisfied: + * a) There are no non-portable control characters belonging to the + * "black list" (0..6, 14..25, 28..31). + * b) There is at least one printable character belonging to the + * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). + * - BINARY otherwise. + * - The following partially-portable control characters form a + * "gray list" that is ignored in this detection algorithm: + * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). + * IN assertion: the fields Freq of dyn_ltree are set. + */ +function detect_data_type(s) { + /* black_mask is the bit mask of black-listed bytes + * set bits 0..6, 14..25, and 28..31 + * 0xf3ffc07f = binary 11110011111111111100000001111111 + */ + let black_mask = 0xf3ffc07f; + let n; + + /* Check for non-textual ("black-listed") bytes. */ + for (n = 0; n <= 31; n++, black_mask >>>= 1) { + if (black_mask & 1 && s.dyn_ltree[n * 2]/*.Freq*/ !== 0) { + return Z_BINARY; + } + } + + /* Check for textual ("white-listed") bytes. */ + if (s.dyn_ltree[9 * 2]/*.Freq*/ !== 0 || s.dyn_ltree[10 * 2]/*.Freq*/ !== 0 || + s.dyn_ltree[13 * 2]/*.Freq*/ !== 0) { + return Z_TEXT; + } + for (n = 32; n < LITERALS; n++) { + if (s.dyn_ltree[n * 2]/*.Freq*/ !== 0) { + return Z_TEXT; + } + } + + /* There are no "black-listed" or "white-listed" bytes: + * this stream either is empty or has tolerated ("gray-listed") bytes only. + */ + return Z_BINARY; +} + + +let static_init_done = false; + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +function _tr_init(s) { + + if (!static_init_done) { + tr_static_init(); + static_init_done = true; + } + + s.l_desc = new TreeDesc(s.dyn_ltree, static_l_desc); + s.d_desc = new TreeDesc(s.dyn_dtree, static_d_desc); + s.bl_desc = new TreeDesc(s.bl_tree, static_bl_desc); + + s.bi_buf = 0; + s.bi_valid = 0; + + /* Initialize the first block of the first file: */ + init_block(s); +} + + +/* =========================================================================== + * Send a stored block + */ +function _tr_stored_block(s, buf, stored_len, last) +//DeflateState *s; +//charf *buf; /* input block */ +//ulg stored_len; /* length of input block */ +//int last; /* one if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK << 1) + (last ? 1 : 0), 3); /* send block type */ + copy_block(s, buf, stored_len, true); /* with header */ +} + + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + */ +function _tr_align(s) { + send_bits(s, STATIC_TREES << 1, 3); + send_code(s, END_BLOCK, static_ltree); + bi_flush(s); +} + + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +function _tr_flush_block(s, buf, stored_len, last) +//DeflateState *s; +//charf *buf; /* input block, or NULL if too old */ +//ulg stored_len; /* length of input block */ +//int last; /* one if this is the last block for a file */ +{ + let opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + let max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s.level > 0) { + + /* Check if the file is binary or text */ + if (s.strm.data_type === Z_UNKNOWN) { + s.strm.data_type = detect_data_type(s); + } + + /* Construct the literal and distance trees */ + build_tree(s, s.l_desc); + // Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + // s->static_len)); + + build_tree(s, s.d_desc); + // Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + // s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = s.opt_len + 3 + 7 >>> 3; + static_lenb = s.static_len + 3 + 7 >>> 3; + + // Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + // opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + // s->last_lit)); + + if (static_lenb <= opt_lenb) { + opt_lenb = static_lenb; + } + + } else { + // Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + + if (stored_len + 4 <= opt_lenb && buf !== -1) { + /* 4: two words for the lengths */ + + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, last); + + } else if (s.strategy === Z_FIXED || static_lenb === opt_lenb) { + + send_bits(s, (STATIC_TREES << 1) + (last ? 1 : 0), 3); + compress_block(s, static_ltree, static_dtree); + + } else { + send_bits(s, (DYN_TREES << 1) + (last ? 1 : 0), 3); + send_all_trees(s, s.l_desc.max_code + 1, s.d_desc.max_code + 1, max_blindex + 1); + compress_block(s, s.dyn_ltree, s.dyn_dtree); + } + // Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (last) { + bi_windup(s); + } + // Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + // s->compressed_len-7*last)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +function _tr_tally(s, dist, lc) +// deflate_state *s; +// unsigned dist; /* distance of matched string */ +// unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + //var out_length, in_length, dcode; + + s.pending_buf[s.d_buf + s.last_lit * 2] = dist >>> 8 & 0xff; + s.pending_buf[s.d_buf + s.last_lit * 2 + 1] = dist & 0xff; + + s.pending_buf[s.l_buf + s.last_lit] = lc & 0xff; + s.last_lit++; + + if (dist === 0) { + /* lc is the unmatched char */ + s.dyn_ltree[lc * 2]/*.Freq*/++; + } else { + s.matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + //Assert((ush)dist < (ush)MAX_DIST(s) && + // (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + // (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s.dyn_ltree[(_length_code[lc] + LITERALS + 1) * 2]/*.Freq*/++; + s.dyn_dtree[d_code(dist) * 2]/*.Freq*/++; + } + + // (!) This block is disabled in zlib defaults, + // don't enable it for binary compatibility + + //#ifdef TRUNCATE_BLOCK + // /* Try to guess if it is profitable to stop the current block here */ + // if ((s.last_lit & 0x1fff) === 0 && s.level > 2) { + // /* Compute an upper bound for the compressed length */ + // out_length = s.last_lit*8; + // in_length = s.strstart - s.block_start; + // + // for (dcode = 0; dcode < D_CODES; dcode++) { + // out_length += s.dyn_dtree[dcode*2]/*.Freq*/ * (5 + extra_dbits[dcode]); + // } + // out_length >>>= 3; + // //Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + // // s->last_lit, in_length, out_length, + // // 100L - out_length*100L/in_length)); + // if (s.matches < (s.last_lit>>1)/*int /2*/ && out_length < (in_length>>1)/*int /2*/) { + // return true; + // } + // } + //#endif + + return s.last_lit === s.lit_bufsize - 1; + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +// Note: adler32 takes 12% for level 0 and 2% for level 6. +// It isn't worth it to make additional optimizations as in original. +// Small size is preferable. + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +function adler32(adler, buf, len, pos) { + let s1 = adler & 0xffff |0, + s2 = adler >>> 16 & 0xffff |0, + n = 0; + + while (len !== 0) { + // Set limit ~ twice less than 5552, to keep + // s2 in 31-bits, because we force signed ints. + // in other case %= will fail. + n = len > 2000 ? 2000 : len; + len -= n; + + do { + s1 = s1 + buf[pos++] |0; + s2 = s2 + s1 |0; + } while (--n); + + s1 %= 65521; + s2 %= 65521; + } + + return s1 | s2 << 16 |0; +} + +// Note: we can't get significant speed boost here. +// So write code to minimize size - no pregenerated tables +// and array tools dependencies. + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +// Use ordinary array, since untyped makes no boost here +function makeTable() { + let c; + const table = []; + + for (let n = 0; n < 256; n++) { + c = n; + for (let k = 0; k < 8; k++) { + c = c & 1 ? 0xEDB88320 ^ c >>> 1 : c >>> 1; + } + table[n] = c; + } + + return table; +} + +// Create table on load. Just 255 signed longs. Not a problem. +const crcTable = makeTable(); + + +function crc32(crc, buf, len, pos) { + const t = crcTable, + end = pos + len; + + crc ^= -1; + + for (let i = pos; i < end; i++) { + crc = crc >>> 8 ^ t[(crc ^ buf[i]) & 0xFF]; + } + + return crc ^ -1; // >>> 0; +} + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +var msg = { + 2: "need dictionary", /* Z_NEED_DICT 2 */ + 1: "stream end", /* Z_STREAM_END 1 */ + 0: "", /* Z_OK 0 */ + "-1": "file error", /* Z_ERRNO (-1) */ + "-2": "stream error", /* Z_STREAM_ERROR (-2) */ + "-3": "data error", /* Z_DATA_ERROR (-3) */ + "-4": "insufficient memory", /* Z_MEM_ERROR (-4) */ + "-5": "buffer error", /* Z_BUF_ERROR (-5) */ + "-6": "incompatible version" /* Z_VERSION_ERROR (-6) */ +}; + +/*============================================================================*/ + + +const MAX_MEM_LEVEL = 9; + + +const LENGTH_CODES$1 = 29; +/* number of length codes, not counting the special END_BLOCK code */ +const LITERALS$1 = 256; +/* number of literal bytes 0..255 */ +const L_CODES$1 = LITERALS$1 + 1 + LENGTH_CODES$1; +/* number of Literal or Length codes, including the END_BLOCK code */ +const D_CODES$1 = 30; +/* number of distance codes */ +const BL_CODES$1 = 19; +/* number of codes used to transfer the bit lengths */ +const HEAP_SIZE$1 = 2 * L_CODES$1 + 1; +/* maximum heap size */ +const MAX_BITS$1 = 15; +/* All codes must not exceed MAX_BITS bits */ + +const MIN_MATCH$1 = 3; +const MAX_MATCH$1 = 258; +const MIN_LOOKAHEAD = (MAX_MATCH$1 + MIN_MATCH$1 + 1); + +const PRESET_DICT = 0x20; + +const INIT_STATE = 42; +const EXTRA_STATE = 69; +const NAME_STATE = 73; +const COMMENT_STATE = 91; +const HCRC_STATE = 103; +const BUSY_STATE = 113; +const FINISH_STATE = 666; + +const BS_NEED_MORE = 1; /* block not completed, need more input or more output */ +const BS_BLOCK_DONE = 2; /* block flush performed */ +const BS_FINISH_STARTED = 3; /* finish started, need only more output at next deflate */ +const BS_FINISH_DONE = 4; /* finish done, accept no more input or output */ + +const OS_CODE = 0x03; // Unix :) . Don't detect, use this default. + +function err(strm, errorCode) { + strm.msg = msg[errorCode]; + return errorCode; +} + +function rank(f) { + return ((f) << 1) - ((f) > 4 ? 9 : 0); +} + +function zero$2(buf) { let len = buf.length; while (--len >= 0) { buf[len] = 0; } } + + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->output buffer and copying into it. + * (See also read_buf()). + */ +function flush_pending(strm) { + const s = strm.state; + + //_tr_flush_bits(s); + let len = s.pending; + if (len > strm.avail_out) { + len = strm.avail_out; + } + if (len === 0) { return; } + + arraySet(strm.output, s.pending_buf, s.pending_out, len, strm.next_out); + strm.next_out += len; + s.pending_out += len; + strm.total_out += len; + strm.avail_out -= len; + s.pending -= len; + if (s.pending === 0) { + s.pending_out = 0; + } +} + + +function flush_block_only(s, last) { + _tr_flush_block(s, (s.block_start >= 0 ? s.block_start : -1), s.strstart - s.block_start, last); + s.block_start = s.strstart; + flush_pending(s.strm); +} + + +function put_byte(s, b) { + s.pending_buf[s.pending++] = b; +} + + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +function putShortMSB(s, b) { + // put_byte(s, (Byte)(b >> 8)); + // put_byte(s, (Byte)(b & 0xff)); + s.pending_buf[s.pending++] = (b >>> 8) & 0xff; + s.pending_buf[s.pending++] = b & 0xff; +} + + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->input buffer and copying from it. + * (See also flush_pending()). + */ +function read_buf(strm, buf, start, size) { + let len = strm.avail_in; + + if (len > size) { len = size; } + if (len === 0) { return 0; } + + strm.avail_in -= len; + + // zmemcpy(buf, strm->next_in, len); + arraySet(buf, strm.input, strm.next_in, len, start); + if (strm.state.wrap === 1) { + strm.adler = adler32(strm.adler, buf, len, start); + } + + else if (strm.state.wrap === 2) { + strm.adler = crc32(strm.adler, buf, len, start); + } + + strm.next_in += len; + strm.total_in += len; + + return len; +} + + +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +function longest_match(s, cur_match) { + let chain_length = s.max_chain_length; /* max hash chain length */ + let scan = s.strstart; /* current string */ + let match; /* matched string */ + let len; /* length of current match */ + let best_len = s.prev_length; /* best match length so far */ + let nice_match = s.nice_match; /* stop if match long enough */ + const limit = (s.strstart > (s.w_size - MIN_LOOKAHEAD)) ? + s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0/*NIL*/; + + const _win = s.window; // shortcut + + const wmask = s.w_mask; + const prev = s.prev; + + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + + const strend = s.strstart + MAX_MATCH$1; + let scan_end1 = _win[scan + best_len - 1]; + let scan_end = _win[scan + best_len]; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + // Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s.prev_length >= s.good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if (nice_match > s.lookahead) { nice_match = s.lookahead; } + + // Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + // Assert(cur_match < s->strstart, "no future"); + match = cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2. Note that the checks below + * for insufficient lookahead only occur occasionally for performance + * reasons. Therefore uninitialized memory will be accessed, and + * conditional jumps will be made that depend on those values. + * However the length of the match is limited to the lookahead, so + * the output of deflate is not affected by the uninitialized values. + */ + + if (_win[match + best_len] !== scan_end || + _win[match + best_len - 1] !== scan_end1 || + _win[match] !== _win[scan] || + _win[++match] !== _win[scan + 1]) { + continue; + } + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2; + match++; + // Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + /*jshint noempty:false*/ + } while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + scan < strend); + + // Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH$1 - (strend - scan); + scan = strend - MAX_MATCH$1; + + if (len > best_len) { + s.match_start = cur_match; + best_len = len; + if (len >= nice_match) { + break; + } + scan_end1 = _win[scan + best_len - 1]; + scan_end = _win[scan + best_len]; + } + } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0); + + if (best_len <= s.lookahead) { + return best_len; + } + return s.lookahead; +} + + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +function fill_window(s) { + const _w_size = s.w_size; + let p, n, m, more, str; + + //Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); + + do { + more = s.window_size - s.lookahead - s.strstart; + + // JS ints have 32 bit, block below not needed + /* Deal with !@#$% 64K limit: */ + //if (sizeof(int) <= 2) { + // if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + // more = wsize; + // + // } else if (more == (unsigned)(-1)) { + // /* Very unlikely, but possible on 16 bit machine if + // * strstart == 0 && lookahead == 1 (input done a byte at time) + // */ + // more--; + // } + //} + + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) { + + arraySet(s.window, s.window, _w_size, _w_size, 0); + s.match_start -= _w_size; + s.strstart -= _w_size; + /* we now have strstart >= MAX_DIST */ + s.block_start -= _w_size; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + + n = s.hash_size; + p = n; + do { + m = s.head[--p]; + s.head[p] = (m >= _w_size ? m - _w_size : 0); + } while (--n); + + n = _w_size; + p = n; + do { + m = s.prev[--p]; + s.prev[p] = (m >= _w_size ? m - _w_size : 0); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); + + more += _w_size; + } + if (s.strm.avail_in === 0) { + break; + } + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + //Assert(more >= 2, "more < 2"); + n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more); + s.lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s.lookahead + s.insert >= MIN_MATCH$1) { + str = s.strstart - s.insert; + s.ins_h = s.window[str]; + + /* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + 1]) & s.hash_mask; + //#if MIN_MATCH != 3 + // Call update_hash() MIN_MATCH-3 more times + //#endif + while (s.insert) { + /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH$1 - 1]) & s.hash_mask; + + s.prev[str & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = str; + str++; + s.insert--; + if (s.lookahead + s.insert < MIN_MATCH$1) { + break; + } + } + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0); + + /* If the WIN_INIT bytes after the end of the current data have never been + * written, then zero those bytes in order to avoid memory check reports of + * the use of uninitialized (or uninitialised as Julian writes) bytes by + * the longest match routines. Update the high water mark for the next + * time through here. WIN_INIT is set to MAX_MATCH since the longest match + * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. + */ + // if (s.high_water < s.window_size) { + // var curr = s.strstart + s.lookahead; + // var init = 0; + // + // if (s.high_water < curr) { + // /* Previous high water mark below current data -- zero WIN_INIT + // * bytes or up to end of window, whichever is less. + // */ + // init = s.window_size - curr; + // if (init > WIN_INIT) + // init = WIN_INIT; + // zmemzero(s->window + curr, (unsigned)init); + // s->high_water = curr + init; + // } + // else if (s->high_water < (ulg)curr + WIN_INIT) { + // /* High water mark at or above current data, but below current data + // * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up + // * to end of window, whichever is less. + // */ + // init = (ulg)curr + WIN_INIT - s->high_water; + // if (init > s->window_size - s->high_water) + // init = s->window_size - s->high_water; + // zmemzero(s->window + s->high_water, (unsigned)init); + // s->high_water += init; + // } + // } + // + // Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, + // "not enough room for search"); +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +function deflate_stored(s, flush) { + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + let max_block_size = 0xffff; + + if (max_block_size > s.pending_buf_size - 5) { + max_block_size = s.pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (; ;) { + /* Fill the window as much as possible: */ + if (s.lookahead <= 1) { + + //Assert(s->strstart < s->w_size+MAX_DIST(s) || + // s->block_start >= (long)s->w_size, "slide too late"); + // if (!(s.strstart < s.w_size + (s.w_size - MIN_LOOKAHEAD) || + // s.block_start >= s.w_size)) { + // throw new Error("slide too late"); + // } + + fill_window(s); + if (s.lookahead === 0 && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + + if (s.lookahead === 0) { + break; + } + /* flush the current block */ + } + //Assert(s->block_start >= 0L, "block gone"); + // if (s.block_start < 0) throw new Error("block gone"); + + s.strstart += s.lookahead; + s.lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + const max_start = s.block_start + max_block_size; + + if (s.strstart === 0 || s.strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s.lookahead = s.strstart - max_start; + s.strstart = max_start; + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + + + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s.strstart - s.block_start >= (s.w_size - MIN_LOOKAHEAD)) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + + s.insert = 0; + + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + + if (s.strstart > s.block_start) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + + return BS_NEED_MORE; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +function deflate_fast(s, flush) { + let hash_head; /* head of the hash chain */ + let bflush; /* set if current block must be flushed */ + + for (; ;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s.lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { + break; /* flush the current block */ + } + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = 0/*NIL*/; + if (s.lookahead >= MIN_MATCH$1) { + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head !== 0/*NIL*/ && ((s.strstart - hash_head) <= (s.w_size - MIN_LOOKAHEAD))) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s.match_length = longest_match(s, hash_head); + /* longest_match() sets match_start */ + } + if (s.match_length >= MIN_MATCH$1) { + // check_match(s, s.strstart, s.match_start, s.match_length); // for debug only + + /*** _tr_tally_dist(s, s.strstart - s.match_start, + s.match_length - MIN_MATCH, bflush); ***/ + bflush = _tr_tally(s, s.strstart - s.match_start, s.match_length - MIN_MATCH$1); + + s.lookahead -= s.match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ + if (s.match_length <= s.max_lazy_match/*max_insert_length*/ && s.lookahead >= MIN_MATCH$1) { + s.match_length--; /* string at strstart already in table */ + do { + s.strstart++; + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s.match_length !== 0); + s.strstart++; + } else { + s.strstart += s.match_length; + s.match_length = 0; + s.ins_h = s.window[s.strstart]; + /* UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]); */ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + 1]) & s.hash_mask; + + //#if MIN_MATCH != 3 + // Call UPDATE_HASH() MIN_MATCH-3 more times + //#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + //Tracevv((stderr,"%c", s.window[s.strstart])); + /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ + bflush = _tr_tally(s, 0, s.window[s.strstart]); + + s.lookahead--; + s.strstart++; + } + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + s.insert = ((s.strstart < (MIN_MATCH$1 - 1)) ? s.strstart : MIN_MATCH$1 - 1); + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + return BS_BLOCK_DONE; +} + +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +function deflate_slow(s, flush) { + let hash_head; /* head of hash chain */ + let bflush; /* set if current block must be flushed */ + + let max_insert; + + /* Process the input block. */ + for (; ;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s.lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { break; } /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = 0/*NIL*/; + if (s.lookahead >= MIN_MATCH$1) { + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + } + + /* Find the longest match, discarding those <= prev_length. + */ + s.prev_length = s.match_length; + s.prev_match = s.match_start; + s.match_length = MIN_MATCH$1 - 1; + + if (hash_head !== 0/*NIL*/ && s.prev_length < s.max_lazy_match && + s.strstart - hash_head <= (s.w_size - MIN_LOOKAHEAD)/*MAX_DIST(s)*/) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s.match_length = longest_match(s, hash_head); + /* longest_match() sets match_start */ + + if (s.match_length <= 5 && + (s.strategy === Z_FILTERED || (s.match_length === MIN_MATCH$1 && s.strstart - s.match_start > 4096/*TOO_FAR*/))) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s.match_length = MIN_MATCH$1 - 1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s.prev_length >= MIN_MATCH$1 && s.match_length <= s.prev_length) { + max_insert = s.strstart + s.lookahead - MIN_MATCH$1; + /* Do not insert strings in hash table beyond this. */ + + //check_match(s, s.strstart-1, s.prev_match, s.prev_length); + + /***_tr_tally_dist(s, s.strstart - 1 - s.prev_match, + s.prev_length - MIN_MATCH, bflush);***/ + bflush = _tr_tally(s, s.strstart - 1 - s.prev_match, s.prev_length - MIN_MATCH$1); + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s.lookahead -= s.prev_length - 1; + s.prev_length -= 2; + do { + if (++s.strstart <= max_insert) { + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + } + } while (--s.prev_length !== 0); + s.match_available = 0; + s.match_length = MIN_MATCH$1 - 1; + s.strstart++; + + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + + } else if (s.match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + //Tracevv((stderr,"%c", s->window[s->strstart-1])); + /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ + bflush = _tr_tally(s, 0, s.window[s.strstart - 1]); + + if (bflush) { + /*** FLUSH_BLOCK_ONLY(s, 0) ***/ + flush_block_only(s, false); + /***/ + } + s.strstart++; + s.lookahead--; + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s.match_available = 1; + s.strstart++; + s.lookahead--; + } + } + //Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s.match_available) { + //Tracevv((stderr,"%c", s->window[s->strstart-1])); + /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ + bflush = _tr_tally(s, 0, s.window[s.strstart - 1]); + + s.match_available = 0; + } + s.insert = s.strstart < MIN_MATCH$1 - 1 ? s.strstart : MIN_MATCH$1 - 1; + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + + return BS_BLOCK_DONE; +} + + +/* =========================================================================== + * For Z_RLE, simply look for runs of bytes, generate matches only of distance + * one. Do not maintain a hash table. (It will be regenerated if this run of + * deflate switches away from Z_RLE.) + */ +function deflate_rle(s, flush) { + let bflush; /* set if current block must be flushed */ + let prev; /* byte at distance one to match */ + let scan, strend; /* scan goes up to strend for length of run */ + + const _win = s.window; + + for (; ;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the longest run, plus one for the unrolled loop. + */ + if (s.lookahead <= MAX_MATCH$1) { + fill_window(s); + if (s.lookahead <= MAX_MATCH$1 && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { break; } /* flush the current block */ + } + + /* See how many times the previous byte repeats */ + s.match_length = 0; + if (s.lookahead >= MIN_MATCH$1 && s.strstart > 0) { + scan = s.strstart - 1; + prev = _win[scan]; + if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) { + strend = s.strstart + MAX_MATCH$1; + do { + /*jshint noempty:false*/ + } while (prev === _win[++scan] && prev === _win[++scan] && + prev === _win[++scan] && prev === _win[++scan] && + prev === _win[++scan] && prev === _win[++scan] && + prev === _win[++scan] && prev === _win[++scan] && + scan < strend); + s.match_length = MAX_MATCH$1 - (strend - scan); + if (s.match_length > s.lookahead) { + s.match_length = s.lookahead; + } + } + //Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); + } + + /* Emit match if have run of MIN_MATCH or longer, else emit literal */ + if (s.match_length >= MIN_MATCH$1) { + //check_match(s, s.strstart, s.strstart - 1, s.match_length); + + /*** _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ***/ + bflush = _tr_tally(s, 1, s.match_length - MIN_MATCH$1); + + s.lookahead -= s.match_length; + s.strstart += s.match_length; + s.match_length = 0; + } else { + /* No match, output a literal byte */ + //Tracevv((stderr,"%c", s->window[s->strstart])); + /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ + bflush = _tr_tally(s, 0, s.window[s.strstart]); + + s.lookahead--; + s.strstart++; + } + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + s.insert = 0; + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + return BS_BLOCK_DONE; +} + +/* =========================================================================== + * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. + * (It will be regenerated if this run of deflate switches away from Huffman.) + */ +function deflate_huff(s, flush) { + let bflush; /* set if current block must be flushed */ + + for (; ;) { + /* Make sure that we have a literal to write. */ + if (s.lookahead === 0) { + fill_window(s); + if (s.lookahead === 0) { + if (flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + break; /* flush the current block */ + } + } + + /* Output a literal byte */ + s.match_length = 0; + //Tracevv((stderr,"%c", s->window[s->strstart])); + /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ + bflush = _tr_tally(s, 0, s.window[s.strstart]); + s.lookahead--; + s.strstart++; + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + s.insert = 0; + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + return BS_BLOCK_DONE; +} + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +class Config { + constructor(good_length, max_lazy, nice_length, max_chain, func) { + this.good_length = good_length; + this.max_lazy = max_lazy; + this.nice_length = nice_length; + this.max_chain = max_chain; + this.func = func; + } +} +const configuration_table = [ + /* good lazy nice chain */ + new Config(0, 0, 0, 0, deflate_stored), /* 0 store only */ + new Config(4, 4, 8, 4, deflate_fast), /* 1 max speed, no lazy matches */ + new Config(4, 5, 16, 8, deflate_fast), /* 2 */ + new Config(4, 6, 32, 32, deflate_fast), /* 3 */ + + new Config(4, 4, 16, 16, deflate_slow), /* 4 lazy matches */ + new Config(8, 16, 32, 32, deflate_slow), /* 5 */ + new Config(8, 16, 128, 128, deflate_slow), /* 6 */ + new Config(8, 32, 128, 256, deflate_slow), /* 7 */ + new Config(32, 128, 258, 1024, deflate_slow), /* 8 */ + new Config(32, 258, 258, 4096, deflate_slow) /* 9 max compression */ +]; + + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +function lm_init(s) { + s.window_size = 2 * s.w_size; + + /*** CLEAR_HASH(s); ***/ + zero$2(s.head); // Fill with NIL (= 0); + + /* Set the default configuration parameters: + */ + s.max_lazy_match = configuration_table[s.level].max_lazy; + s.good_match = configuration_table[s.level].good_length; + s.nice_match = configuration_table[s.level].nice_length; + s.max_chain_length = configuration_table[s.level].max_chain; + + s.strstart = 0; + s.block_start = 0; + s.lookahead = 0; + s.insert = 0; + s.match_length = s.prev_length = MIN_MATCH$1 - 1; + s.match_available = 0; + s.ins_h = 0; +} + +class DeflateState { + constructor() { + this.strm = null; /* pointer back to this zlib stream */ + this.status = 0; /* as the name implies */ + this.pending_buf = null; /* output still pending */ + this.pending_buf_size = 0; /* size of pending_buf */ + this.pending_out = 0; /* next pending byte to output to the stream */ + this.pending = 0; /* nb of bytes in the pending buffer */ + this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ + this.gzhead = null; /* gzip header information to write */ + this.gzindex = 0; /* where in extra, name, or comment */ + this.method = Z_DEFLATED; /* can only be DEFLATED */ + this.last_flush = -1; /* value of flush param for previous deflate call */ + + this.w_size = 0; /* LZ77 window size (32K by default) */ + this.w_bits = 0; /* log2(w_size) (8..16) */ + this.w_mask = 0; /* w_size - 1 */ + + this.window = null; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. + */ + + this.window_size = 0; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + this.prev = null; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + this.head = null; /* Heads of the hash chains or NIL. */ + + this.ins_h = 0; /* hash index of string to be inserted */ + this.hash_size = 0; /* number of elements in hash table */ + this.hash_bits = 0; /* log2(hash_size) */ + this.hash_mask = 0; /* hash_size-1 */ + + this.hash_shift = 0; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + this.block_start = 0; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + this.match_length = 0; /* length of best match */ + this.prev_match = 0; /* previous match */ + this.match_available = 0; /* set if previous match exists */ + this.strstart = 0; /* start of string to insert */ + this.match_start = 0; /* start of matching string */ + this.lookahead = 0; /* number of valid bytes ahead in window */ + + this.prev_length = 0; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + this.max_chain_length = 0; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + this.max_lazy_match = 0; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ + // That's alias to max_lazy_match, don't use directly + //this.max_insert_length = 0; + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + this.level = 0; /* compression level (1..9) */ + this.strategy = 0; /* favor or force Huffman coding*/ + + this.good_match = 0; + /* Use a faster search when the previous match is longer than this */ + + this.nice_match = 0; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + + /* Didn't use ct_data typedef below to suppress compiler warning */ + + // struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + // struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + // struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + // Use flat array of DOUBLE size, with interleaved fata, + // because JS does not support effective + this.dyn_ltree = new Buf16(HEAP_SIZE$1 * 2); + this.dyn_dtree = new Buf16((2 * D_CODES$1 + 1) * 2); + this.bl_tree = new Buf16((2 * BL_CODES$1 + 1) * 2); + zero$2(this.dyn_ltree); + zero$2(this.dyn_dtree); + zero$2(this.bl_tree); + + this.l_desc = null; /* desc. for literal tree */ + this.d_desc = null; /* desc. for distance tree */ + this.bl_desc = null; /* desc. for bit length tree */ + + //ush bl_count[MAX_BITS+1]; + this.bl_count = new Buf16(MAX_BITS$1 + 1); + /* number of codes at each bit length for an optimal tree */ + + //int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + this.heap = new Buf16(2 * L_CODES$1 + 1); /* heap used to build the Huffman trees */ + zero$2(this.heap); + + this.heap_len = 0; /* number of elements in the heap */ + this.heap_max = 0; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + this.depth = new Buf16(2 * L_CODES$1 + 1); //uch depth[2*L_CODES+1]; + zero$2(this.depth); + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + this.l_buf = 0; /* buffer index for literals or lengths */ + + this.lit_bufsize = 0; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + this.last_lit = 0; /* running index in l_buf */ + + this.d_buf = 0; + /* Buffer index for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + this.opt_len = 0; /* bit length of current block with optimal trees */ + this.static_len = 0; /* bit length of current block with static trees */ + this.matches = 0; /* number of string matches in current block */ + this.insert = 0; /* bytes at end of window left to insert */ + + + this.bi_buf = 0; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + this.bi_valid = 0; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + + // Used for window memory init. We safely ignore it for JS. That makes + // sense only for pointers and memory check tools. + //this.high_water = 0; + /* High water mark offset in window for initialized bytes -- bytes above + * this are set to zero in order to avoid memory check warnings when + * longest match routines access bytes past the input. This is then + * updated to the new high water mark. + */ + } +} + +function deflateResetKeep(strm) { + let s; + + if (!strm || !strm.state) { + return err(strm, Z_STREAM_ERROR); + } + + strm.total_in = strm.total_out = 0; + strm.data_type = Z_UNKNOWN; + + s = strm.state; + s.pending = 0; + s.pending_out = 0; + + if (s.wrap < 0) { + s.wrap = -s.wrap; + /* was made negative by deflate(..., Z_FINISH); */ + } + s.status = (s.wrap ? INIT_STATE : BUSY_STATE); + strm.adler = (s.wrap === 2) ? + 0 // crc32(0, Z_NULL, 0) + : + 1; // adler32(0, Z_NULL, 0) + s.last_flush = Z_NO_FLUSH; + _tr_init(s); + return Z_OK; +} + + +function deflateReset(strm) { + const ret = deflateResetKeep(strm); + if (ret === Z_OK) { + lm_init(strm.state); + } + return ret; +} + + +function deflateSetHeader(strm, head) { + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + if (strm.state.wrap !== 2) { return Z_STREAM_ERROR; } + strm.state.gzhead = head; + return Z_OK; +} + + +function deflateInit2(strm, level, method, windowBits, memLevel, strategy) { + if (!strm) { // === Z_NULL + return Z_STREAM_ERROR; + } + let wrap = 1; + + if (level === Z_DEFAULT_COMPRESSION) { + level = 6; + } + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } + + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } + + + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method !== Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_FIXED) { + return err(strm, Z_STREAM_ERROR); + } + + + if (windowBits === 8) { + windowBits = 9; + } + /* until 256-byte window bug fixed */ + + const s = new DeflateState(); + + strm.state = s; + s.strm = strm; + + s.wrap = wrap; + s.gzhead = null; + s.w_bits = windowBits; + s.w_size = 1 << s.w_bits; + s.w_mask = s.w_size - 1; + + s.hash_bits = memLevel + 7; + s.hash_size = 1 << s.hash_bits; + s.hash_mask = s.hash_size - 1; + s.hash_shift = ~~((s.hash_bits + MIN_MATCH$1 - 1) / MIN_MATCH$1); + s.window = new Buf8(s.w_size * 2); + s.head = new Buf16(s.hash_size); + s.prev = new Buf16(s.w_size); + + // Don't need mem init magic for JS. + //s.high_water = 0; /* nothing written to s->window yet */ + + s.lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + s.pending_buf_size = s.lit_bufsize * 4; + + //overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + //s->pending_buf = (uchf *) overlay; + s.pending_buf = new Buf8(s.pending_buf_size); + + // It is offset from `s.pending_buf` (size is `s.lit_bufsize * 2`) + //s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s.d_buf = 1 * s.lit_bufsize; + + //s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + s.l_buf = (1 + 2) * s.lit_bufsize; + + s.level = level; + s.strategy = strategy; + s.method = method; + + return deflateReset(strm); +} + + +function deflate(strm, flush) { + let old_flush, s; + let beg, val; // for gzip header write only + + if (!strm || !strm.state || + flush > Z_BLOCK || flush < 0) { + return strm ? err(strm, Z_STREAM_ERROR) : Z_STREAM_ERROR; + } + + s = strm.state; + + if (!strm.output || + (!strm.input && strm.avail_in !== 0) || + (s.status === FINISH_STATE && flush !== Z_FINISH)) { + return err(strm, (strm.avail_out === 0) ? Z_BUF_ERROR : Z_STREAM_ERROR); + } + + s.strm = strm; /* just in case */ + old_flush = s.last_flush; + s.last_flush = flush; + + /* Write the header */ + if (s.status === INIT_STATE) { + + if (s.wrap === 2) { // GZIP header + strm.adler = 0; //crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (!s.gzhead) { // s->gzhead == Z_NULL + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s.level === 9 ? 2 : + (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s.status = BUSY_STATE; + } + else { + put_byte(s, (s.gzhead.text ? 1 : 0) + + (s.gzhead.hcrc ? 2 : 0) + + (!s.gzhead.extra ? 0 : 4) + + (!s.gzhead.name ? 0 : 8) + + (!s.gzhead.comment ? 0 : 16) + ); + put_byte(s, s.gzhead.time & 0xff); + put_byte(s, (s.gzhead.time >> 8) & 0xff); + put_byte(s, (s.gzhead.time >> 16) & 0xff); + put_byte(s, (s.gzhead.time >> 24) & 0xff); + put_byte(s, s.level === 9 ? 2 : + (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? + 4 : 0)); + put_byte(s, s.gzhead.os & 0xff); + if (s.gzhead.extra && s.gzhead.extra.length) { + put_byte(s, s.gzhead.extra.length & 0xff); + put_byte(s, (s.gzhead.extra.length >> 8) & 0xff); + } + if (s.gzhead.hcrc) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending, 0); + } + s.gzindex = 0; + s.status = EXTRA_STATE; + } + } + else // DEFLATE header + { + let header = (Z_DEFLATED + ((s.w_bits - 8) << 4)) << 8; + let level_flags = -1; + + if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) { + level_flags = 0; + } else if (s.level < 6) { + level_flags = 1; + } else if (s.level === 6) { + level_flags = 2; + } else { + level_flags = 3; + } + header |= (level_flags << 6); + if (s.strstart !== 0) { header |= PRESET_DICT; } + header += 31 - (header % 31); + + s.status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s.strstart !== 0) { + putShortMSB(s, strm.adler >>> 16); + putShortMSB(s, strm.adler & 0xffff); + } + strm.adler = 1; // adler32(0L, Z_NULL, 0); + } + } + + //#ifdef GZIP + if (s.status === EXTRA_STATE) { + if (s.gzhead.extra/* != Z_NULL*/) { + beg = s.pending; /* start of bytes to update crc */ + + while (s.gzindex < (s.gzhead.extra.length & 0xffff)) { + if (s.pending === s.pending_buf_size) { + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + flush_pending(strm); + beg = s.pending; + if (s.pending === s.pending_buf_size) { + break; + } + } + put_byte(s, s.gzhead.extra[s.gzindex] & 0xff); + s.gzindex++; + } + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + if (s.gzindex === s.gzhead.extra.length) { + s.gzindex = 0; + s.status = NAME_STATE; + } + } + else { + s.status = NAME_STATE; + } + } + if (s.status === NAME_STATE) { + if (s.gzhead.name/* != Z_NULL*/) { + beg = s.pending; /* start of bytes to update crc */ + //int val; + + do { + if (s.pending === s.pending_buf_size) { + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + flush_pending(strm); + beg = s.pending; + if (s.pending === s.pending_buf_size) { + val = 1; + break; + } + } + // JS specific: little magic to add zero terminator to end of string + if (s.gzindex < s.gzhead.name.length) { + val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff; + } else { + val = 0; + } + put_byte(s, val); + } while (val !== 0); + + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + if (val === 0) { + s.gzindex = 0; + s.status = COMMENT_STATE; + } + } + else { + s.status = COMMENT_STATE; + } + } + if (s.status === COMMENT_STATE) { + if (s.gzhead.comment/* != Z_NULL*/) { + beg = s.pending; /* start of bytes to update crc */ + //int val; + + do { + if (s.pending === s.pending_buf_size) { + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + flush_pending(strm); + beg = s.pending; + if (s.pending === s.pending_buf_size) { + val = 1; + break; + } + } + // JS specific: little magic to add zero terminator to end of string + if (s.gzindex < s.gzhead.comment.length) { + val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff; + } else { + val = 0; + } + put_byte(s, val); + } while (val !== 0); + + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + if (val === 0) { + s.status = HCRC_STATE; + } + } + else { + s.status = HCRC_STATE; + } + } + if (s.status === HCRC_STATE) { + if (s.gzhead.hcrc) { + if (s.pending + 2 > s.pending_buf_size) { + flush_pending(strm); + } + if (s.pending + 2 <= s.pending_buf_size) { + put_byte(s, strm.adler & 0xff); + put_byte(s, (strm.adler >> 8) & 0xff); + strm.adler = 0; //crc32(0L, Z_NULL, 0); + s.status = BUSY_STATE; + } + } + else { + s.status = BUSY_STATE; + } + } + //#endif + + /* Flush as much pending output as possible */ + if (s.pending !== 0) { + flush_pending(strm); + if (strm.avail_out === 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s.last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) && + flush !== Z_FINISH) { + return err(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s.status === FINISH_STATE && strm.avail_in !== 0) { + return err(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm.avail_in !== 0 || s.lookahead !== 0 || + (flush !== Z_NO_FLUSH && s.status !== FINISH_STATE)) { + var bstate = (s.strategy === Z_HUFFMAN_ONLY) ? deflate_huff(s, flush) : + (s.strategy === Z_RLE ? deflate_rle(s, flush) : + configuration_table[s.level].func(s, flush)); + + if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) { + s.status = FINISH_STATE; + } + if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) { + if (strm.avail_out === 0) { + s.last_flush = -1; + /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate === BS_BLOCK_DONE) { + if (flush === Z_PARTIAL_FLUSH) { + _tr_align(s); + } + else if (flush !== Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ + + _tr_stored_block(s, 0, 0, false); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush === Z_FULL_FLUSH) { + /*** CLEAR_HASH(s); ***/ /* forget history */ + zero$2(s.head); // Fill with NIL (= 0); + + if (s.lookahead === 0) { + s.strstart = 0; + s.block_start = 0; + s.insert = 0; + } + } + } + flush_pending(strm); + if (strm.avail_out === 0) { + s.last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + //Assert(strm->avail_out > 0, "bug2"); + //if (strm.avail_out <= 0) { throw new Error("bug2");} + + if (flush !== Z_FINISH) { return Z_OK; } + if (s.wrap <= 0) { return Z_STREAM_END; } + + /* Write the trailer */ + if (s.wrap === 2) { + put_byte(s, strm.adler & 0xff); + put_byte(s, (strm.adler >> 8) & 0xff); + put_byte(s, (strm.adler >> 16) & 0xff); + put_byte(s, (strm.adler >> 24) & 0xff); + put_byte(s, strm.total_in & 0xff); + put_byte(s, (strm.total_in >> 8) & 0xff); + put_byte(s, (strm.total_in >> 16) & 0xff); + put_byte(s, (strm.total_in >> 24) & 0xff); + } + else { + putShortMSB(s, strm.adler >>> 16); + putShortMSB(s, strm.adler & 0xffff); + } + + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s.wrap > 0) { s.wrap = -s.wrap; } + /* write the trailer only once! */ + return s.pending !== 0 ? Z_OK : Z_STREAM_END; +} + +function deflateEnd(strm) { + let status; + + if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) { + return Z_STREAM_ERROR; + } + + status = strm.state.status; + if (status !== INIT_STATE && + status !== EXTRA_STATE && + status !== NAME_STATE && + status !== COMMENT_STATE && + status !== HCRC_STATE && + status !== BUSY_STATE && + status !== FINISH_STATE + ) { + return err(strm, Z_STREAM_ERROR); + } + + strm.state = null; + + return status === BUSY_STATE ? err(strm, Z_DATA_ERROR) : Z_OK; +} + + +/* ========================================================================= + * Initializes the compression dictionary from the given byte + * sequence without producing any compressed output. + */ +function deflateSetDictionary(strm, dictionary) { + let dictLength = dictionary.length; + + let s; + let str, n; + let wrap; + let avail; + let next; + let input; + let tmpDict; + + if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) { + return Z_STREAM_ERROR; + } + + s = strm.state; + wrap = s.wrap; + + if (wrap === 2 || (wrap === 1 && s.status !== INIT_STATE) || s.lookahead) { + return Z_STREAM_ERROR; + } + + /* when using zlib wrappers, compute Adler-32 for provided dictionary */ + if (wrap === 1) { + /* adler32(strm->adler, dictionary, dictLength); */ + strm.adler = adler32(strm.adler, dictionary, dictLength, 0); + } + + s.wrap = 0; /* avoid computing Adler-32 in read_buf */ + + /* if dictionary would fill window, just replace the history */ + if (dictLength >= s.w_size) { + if (wrap === 0) { /* already empty otherwise */ + /*** CLEAR_HASH(s); ***/ + zero$2(s.head); // Fill with NIL (= 0); + s.strstart = 0; + s.block_start = 0; + s.insert = 0; + } + /* use the tail */ + // dictionary = dictionary.slice(dictLength - s.w_size); + tmpDict = new Buf8(s.w_size); + arraySet(tmpDict, dictionary, dictLength - s.w_size, s.w_size, 0); + dictionary = tmpDict; + dictLength = s.w_size; + } + /* insert dictionary into window and hash */ + avail = strm.avail_in; + next = strm.next_in; + input = strm.input; + strm.avail_in = dictLength; + strm.next_in = 0; + strm.input = dictionary; + fill_window(s); + while (s.lookahead >= MIN_MATCH$1) { + str = s.strstart; + n = s.lookahead - (MIN_MATCH$1 - 1); + do { + /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH$1 - 1]) & s.hash_mask; + + s.prev[str & s.w_mask] = s.head[s.ins_h]; + + s.head[s.ins_h] = str; + str++; + } while (--n); + s.strstart = str; + s.lookahead = MIN_MATCH$1 - 1; + fill_window(s); + } + s.strstart += s.lookahead; + s.block_start = s.strstart; + s.insert = s.lookahead; + s.lookahead = 0; + s.match_length = s.prev_length = MIN_MATCH$1 - 1; + s.match_available = 0; + strm.next_in = next; + strm.input = input; + strm.avail_in = avail; + s.wrap = wrap; + return Z_OK; +} + +/* Not implemented +exports.deflateBound = deflateBound; +exports.deflateCopy = deflateCopy; +exports.deflateParams = deflateParams; +exports.deflatePending = deflatePending; +exports.deflatePrime = deflatePrime; +exports.deflateTune = deflateTune; +*/ + +// String encode/decode helpers + +try { + String.fromCharCode.apply(null, [ 0 ]); +} catch (__) { +} +try { + String.fromCharCode.apply(null, new Uint8Array(1)); +} catch (__) { +} + + +// Table with utf8 lengths (calculated by first byte of sequence) +// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS, +// because max possible codepoint is 0x10ffff +const _utf8len = new Buf8(256); +for (let q = 0; q < 256; q++) { + _utf8len[q] = q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1; +} +_utf8len[254] = _utf8len[254] = 1; // Invalid sequence start + + +// convert string to array (typed, when possible) +function string2buf (str) { + let c, c2, m_pos, i, buf_len = 0; + const str_len = str.length; + + // count binary size + for (m_pos = 0; m_pos < str_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && m_pos + 1 < str_len) { + c2 = str.charCodeAt(m_pos + 1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + (c - 0xd800 << 10) + (c2 - 0xdc00); + m_pos++; + } + } + buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4; + } + + // allocate buffer + const buf = new Buf8(buf_len); + + // convert + for (i = 0, m_pos = 0; i < buf_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && m_pos + 1 < str_len) { + c2 = str.charCodeAt(m_pos + 1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + (c - 0xd800 << 10) + (c2 - 0xdc00); + m_pos++; + } + } + if (c < 0x80) { + /* one byte */ + buf[i++] = c; + } else if (c < 0x800) { + /* two bytes */ + buf[i++] = 0xC0 | c >>> 6; + buf[i++] = 0x80 | c & 0x3f; + } else if (c < 0x10000) { + /* three bytes */ + buf[i++] = 0xE0 | c >>> 12; + buf[i++] = 0x80 | c >>> 6 & 0x3f; + buf[i++] = 0x80 | c & 0x3f; + } else { + /* four bytes */ + buf[i++] = 0xf0 | c >>> 18; + buf[i++] = 0x80 | c >>> 12 & 0x3f; + buf[i++] = 0x80 | c >>> 6 & 0x3f; + buf[i++] = 0x80 | c & 0x3f; + } + } + + return buf; +} + + +// Convert binary string (typed, when possible) +function binstring2buf (str) { + const buf = new Buf8(str.length); + for (let i = 0, len = buf.length; i < len; i++) { + buf[i] = str.charCodeAt(i); + } + return buf; +} + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +class ZStream { + constructor() { + /* next input byte */ + this.input = null; // JS specific, because we have no pointers + this.next_in = 0; + /* number of bytes available at input */ + this.avail_in = 0; + /* total number of input bytes read so far */ + this.total_in = 0; + /* next output byte should be put there */ + this.output = null; // JS specific, because we have no pointers + this.next_out = 0; + /* remaining free space at output */ + this.avail_out = 0; + /* total number of bytes output so far */ + this.total_out = 0; + /* last error message, NULL if no error */ + this.msg = ''/*Z_NULL*/; + /* not visible by applications */ + this.state = null; + /* best guess about the data type: binary or text */ + this.data_type = 2/*Z_UNKNOWN*/; + /* adler32 value of the uncompressed data */ + this.adler = 0; + } +} + +/* ===========================================================================*/ + + +/** + * class Deflate + * + * Generic JS-style wrapper for zlib calls. If you don't need + * streaming behaviour - use more simple functions: [[deflate]], + * [[deflateRaw]] and [[gzip]]. + **/ + +/* internal + * Deflate.chunks -> Array + * + * Chunks of output data, if [[Deflate#onData]] not overridden. + **/ + +/** + * Deflate.result -> Uint8Array|Array + * + * Compressed result, generated by default [[Deflate#onData]] + * and [[Deflate#onEnd]] handlers. Filled after you push last chunk + * (call [[Deflate#push]] with `Z_FINISH` / `true` param) or if you + * push a chunk with explicit flush (call [[Deflate#push]] with + * `Z_SYNC_FLUSH` param). + **/ + +/** + * Deflate.err -> Number + * + * Error code after deflate finished. 0 (Z_OK) on success. + * You will not need it in real life, because deflate errors + * are possible only on wrong options or bad `onData` / `onEnd` + * custom handlers. + **/ + +/** + * Deflate.msg -> String + * + * Error message, if [[Deflate.err]] != 0 + **/ + + +/** + * new Deflate(options) + * - options (Object): zlib deflate options. + * + * Creates new deflator instance with specified params. Throws exception + * on bad params. Supported options: + * + * - `level` + * - `windowBits` + * - `memLevel` + * - `strategy` + * - `dictionary` + * + * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) + * for more information on these. + * + * Additional options, for internal needs: + * + * - `chunkSize` - size of generated data chunks (16K by default) + * - `raw` (Boolean) - do raw deflate + * - `gzip` (Boolean) - create gzip wrapper + * - `to` (String) - if equal to 'string', then result will be "binary string" + * (each char code [0..255]) + * - `header` (Object) - custom header for gzip + * - `text` (Boolean) - true if compressed data believed to be text + * - `time` (Number) - modification time, unix timestamp + * - `os` (Number) - operation system code + * - `extra` (Array) - array of bytes with extra data (max 65536) + * - `name` (String) - file name (binary string) + * - `comment` (String) - comment (binary string) + * - `hcrc` (Boolean) - true if header crc should be added + * + * ##### Example: + * + * ```javascript + * var pako = require('pako') + * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9]) + * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]); + * + * var deflate = new pako.Deflate({ level: 3}); + * + * deflate.push(chunk1, false); + * deflate.push(chunk2, true); // true -> last chunk + * + * if (deflate.err) { throw new Error(deflate.err); } + * + * console.log(deflate.result); + * ``` + **/ + +class Deflate { + constructor(options) { + this.options = { + level: Z_DEFAULT_COMPRESSION, + method: Z_DEFLATED, + chunkSize: 16384, + windowBits: 15, + memLevel: 8, + strategy: Z_DEFAULT_STRATEGY, + ...(options || {}) + }; + + const opt = this.options; + + if (opt.raw && (opt.windowBits > 0)) { + opt.windowBits = -opt.windowBits; + } + + else if (opt.gzip && (opt.windowBits > 0) && (opt.windowBits < 16)) { + opt.windowBits += 16; + } + + this.err = 0; // error code, if happens (0 = Z_OK) + this.msg = ''; // error message + this.ended = false; // used to avoid multiple onEnd() calls + this.chunks = []; // chunks of compressed data + + this.strm = new ZStream(); + this.strm.avail_out = 0; + + var status = deflateInit2( + this.strm, + opt.level, + opt.method, + opt.windowBits, + opt.memLevel, + opt.strategy + ); + + if (status !== Z_OK) { + throw new Error(msg[status]); + } + + if (opt.header) { + deflateSetHeader(this.strm, opt.header); + } + + if (opt.dictionary) { + let dict; + // Convert data if needed + if (typeof opt.dictionary === 'string') { + // If we need to compress text, change encoding to utf8. + dict = string2buf(opt.dictionary); + } else if (opt.dictionary instanceof ArrayBuffer) { + dict = new Uint8Array(opt.dictionary); + } else { + dict = opt.dictionary; + } + + status = deflateSetDictionary(this.strm, dict); + + if (status !== Z_OK) { + throw new Error(msg[status]); + } + + this._dict_set = true; + } + } + + /** + * Deflate#push(data[, mode]) -> Boolean + * - data (Uint8Array|Array|ArrayBuffer|String): input data. Strings will be + * converted to utf8 byte sequence. + * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. + * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH. + * + * Sends input data to deflate pipe, generating [[Deflate#onData]] calls with + * new compressed chunks. Returns `true` on success. The last data block must have + * mode Z_FINISH (or `true`). That will flush internal pending buffers and call + * [[Deflate#onEnd]]. For interim explicit flushes (without ending the stream) you + * can use mode Z_SYNC_FLUSH, keeping the compression context. + * + * On fail call [[Deflate#onEnd]] with error code and return false. + * + * We strongly recommend to use `Uint8Array` on input for best speed (output + * array format is detected automatically). Also, don't skip last param and always + * use the same type in your code (boolean or number). That will improve JS speed. + * + * For regular `Array`-s make sure all elements are [0..255]. + * + * ##### Example + * + * ```javascript + * push(chunk, false); // push one of data chunks + * ... + * push(chunk, true); // push last chunk + * ``` + **/ + push(data, mode) { + const { strm, options: { chunkSize } } = this; + var status, _mode; + + if (this.ended) { return false; } + + _mode = (mode === ~~mode) ? mode : ((mode === true) ? Z_FINISH : Z_NO_FLUSH); + + // Convert data if needed + if (typeof data === 'string') { + // If we need to compress text, change encoding to utf8. + strm.input = string2buf(data); + } else if (data instanceof ArrayBuffer) { + strm.input = new Uint8Array(data); + } else { + strm.input = data; + } + + strm.next_in = 0; + strm.avail_in = strm.input.length; + + do { + if (strm.avail_out === 0) { + strm.output = new Buf8(chunkSize); + strm.next_out = 0; + strm.avail_out = chunkSize; + } + status = deflate(strm, _mode); /* no bad return value */ + + if (status !== Z_STREAM_END && status !== Z_OK) { + this.onEnd(status); + this.ended = true; + return false; + } + if (strm.avail_out === 0 || (strm.avail_in === 0 && (_mode === Z_FINISH || _mode === Z_SYNC_FLUSH))) { + this.onData(shrinkBuf(strm.output, strm.next_out)); + } + } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== Z_STREAM_END); + + // Finalize on the last chunk. + if (_mode === Z_FINISH) { + status = deflateEnd(this.strm); + this.onEnd(status); + this.ended = true; + return status === Z_OK; + } + + // callback interim results if Z_SYNC_FLUSH. + if (_mode === Z_SYNC_FLUSH) { + this.onEnd(Z_OK); + strm.avail_out = 0; + return true; + } + + return true; + }; + /** + * Deflate#onData(chunk) -> Void + * - chunk (Uint8Array|Array|String): output data. Type of array depends + * on js engine support. When string output requested, each chunk + * will be string. + * + * By default, stores data blocks in `chunks[]` property and glue + * those in `onEnd`. Override this handler, if you need another behaviour. + **/ + onData(chunk) { + this.chunks.push(chunk); + }; + + /** + * Deflate#onEnd(status) -> Void + * - status (Number): deflate status. 0 (Z_OK) on success, + * other if not. + * + * Called once after you tell deflate that the input stream is + * complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH) + * or if an error happened. By default - join collected chunks, + * free memory and fill `results` / `err` properties. + **/ + onEnd(status) { + // On success - join + if (status === Z_OK) { + this.result = flattenChunks(this.chunks); + } + this.chunks = []; + this.err = status; + this.msg = this.strm.msg; + }; +} + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +// See state defs from inflate.js +const BAD = 30; /* got a data error -- remain here until reset */ +const TYPE = 12; /* i: waiting for type bits, including last-flag bit */ + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state.mode === LEN + strm.avail_in >= 6 + strm.avail_out >= 258 + start >= strm.avail_out + state.bits < 8 + + On return, state.mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm.avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm.avail_out >= 258 for each loop to avoid checking for + output space. + */ +function inflate_fast(strm, start) { + let _in; /* local strm.input */ + let _out; /* local strm.output */ + // Use `s_window` instead `window`, avoid conflict with instrumentation tools + let hold; /* local strm.hold */ + let bits; /* local strm.bits */ + let here; /* retrieved table entry */ + let op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + let len; /* match length, unused bytes */ + let dist; /* match distance */ + let from; /* where to copy match from */ + let from_source; + + + + /* copy state to local variables */ + const state = strm.state; + //here = state.here; + _in = strm.next_in; + const input = strm.input; + const last = _in + (strm.avail_in - 5); + _out = strm.next_out; + const output = strm.output; + const beg = _out - (start - strm.avail_out); + const end = _out + (strm.avail_out - 257); + //#ifdef INFLATE_STRICT + const dmax = state.dmax; + //#endif + const wsize = state.wsize; + const whave = state.whave; + const wnext = state.wnext; + const s_window = state.window; + hold = state.hold; + bits = state.bits; + const lcode = state.lencode; + const dcode = state.distcode; + const lmask = (1 << state.lenbits) - 1; + const dmask = (1 << state.distbits) - 1; + + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + + top: + do { + if (bits < 15) { + hold += input[_in++] << bits; + bits += 8; + hold += input[_in++] << bits; + bits += 8; + } + + here = lcode[hold & lmask]; + + dolen: + for (;;) { // Goto emulation + op = here >>> 24/*here.bits*/; + hold >>>= op; + bits -= op; + op = here >>> 16 & 0xff/*here.op*/; + if (op === 0) { /* literal */ + //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + // "inflate: literal '%c'\n" : + // "inflate: literal 0x%02x\n", here.val)); + output[_out++] = here & 0xffff/*here.val*/; + } else if (op & 16) { /* length base */ + len = here & 0xffff/*here.val*/; + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + } + len += hold & (1 << op) - 1; + hold >>>= op; + bits -= op; + } + //Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += input[_in++] << bits; + bits += 8; + hold += input[_in++] << bits; + bits += 8; + } + here = dcode[hold & dmask]; + + dodist: + for (;;) { // goto emulation + op = here >>> 24/*here.bits*/; + hold >>>= op; + bits -= op; + op = here >>> 16 & 0xff/*here.op*/; + + if (op & 16) { /* distance base */ + dist = here & 0xffff/*here.val*/; + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + } + } + dist += hold & (1 << op) - 1; + //#ifdef INFLATE_STRICT + if (dist > dmax) { + strm.msg = "invalid distance too far back"; + state.mode = BAD; + break top; + } + //#endif + hold >>>= op; + bits -= op; + //Tracevv((stderr, "inflate: distance %u\n", dist)); + op = _out - beg; /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state.sane) { + strm.msg = "invalid distance too far back"; + state.mode = BAD; + break top; + } + + // (!) This block is disabled in zlib defaults, + // don't enable it for binary compatibility + //#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + // if (len <= op - whave) { + // do { + // output[_out++] = 0; + // } while (--len); + // continue top; + // } + // len -= op - whave; + // do { + // output[_out++] = 0; + // } while (--op > whave); + // if (op === 0) { + // from = _out - dist; + // do { + // output[_out++] = output[from++]; + // } while (--len); + // continue top; + // } + //#endif + } + from = 0; // window index + from_source = s_window; + if (wnext === 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } else if (wnext < op) { /* wrap around window */ + from += wsize + wnext - op; + op -= wnext; + if (op < len) { /* some from end of window */ + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = 0; + if (wnext < len) { /* some from start of window */ + op = wnext; + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } + } else { /* contiguous in window */ + from += wnext - op; + if (op < len) { /* some from window */ + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } + while (len > 2) { + output[_out++] = from_source[from++]; + output[_out++] = from_source[from++]; + output[_out++] = from_source[from++]; + len -= 3; + } + if (len) { + output[_out++] = from_source[from++]; + if (len > 1) { + output[_out++] = from_source[from++]; + } + } + } else { + from = _out - dist; /* copy direct from output */ + do { /* minimum length is three */ + output[_out++] = output[from++]; + output[_out++] = output[from++]; + output[_out++] = output[from++]; + len -= 3; + } while (len > 2); + if (len) { + output[_out++] = output[from++]; + if (len > 1) { + output[_out++] = output[from++]; + } + } + } + } else if ((op & 64) === 0) { /* 2nd level distance code */ + here = dcode[(here & 0xffff)/*here.val*/ + (hold & (1 << op) - 1)]; + continue dodist; + } else { + strm.msg = "invalid distance code"; + state.mode = BAD; + break top; + } + + break; // need to emulate goto via "continue" + } + } else if ((op & 64) === 0) { /* 2nd level length code */ + here = lcode[(here & 0xffff)/*here.val*/ + (hold & (1 << op) - 1)]; + continue dolen; + } else if (op & 32) { /* end-of-block */ + //Tracevv((stderr, "inflate: end of block\n")); + state.mode = TYPE; + break top; + } else { + strm.msg = "invalid literal/length code"; + state.mode = BAD; + break top; + } + + break; // need to emulate goto via "continue" + } + } while (_in < last && _out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + _in -= len; + bits -= len << 3; + hold &= (1 << bits) - 1; + + /* update state and return */ + strm.next_in = _in; + strm.next_out = _out; + strm.avail_in = _in < last ? 5 + (last - _in) : 5 - (_in - last); + strm.avail_out = _out < end ? 257 + (end - _out) : 257 - (_out - end); + state.hold = hold; + state.bits = bits; + return; +} + +const MAXBITS = 15; +const ENOUGH_LENS = 852; +const ENOUGH_DISTS = 592; +//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); + +const CODES = 0; +const LENS = 1; +const DISTS = 2; + +const lbase = [ /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 +]; + +const lext = [ /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78 +]; + +const dbase = [ /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0 +]; + +const dext = [ /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64 +]; + +function inflate_table(type, lens, lens_index, codes, table, table_index, work, opts) { + const bits = opts.bits; + //here = opts.here; /* table entry for duplication */ + + let len = 0; /* a code's length in bits */ + let sym = 0; /* index of code symbols */ + let min = 0, max = 0; /* minimum and maximum code lengths */ + let root = 0; /* number of index bits for root table */ + let curr = 0; /* number of index bits for current table */ + let drop = 0; /* code bits to drop for sub-table */ + let left = 0; /* number of prefix codes available */ + let used = 0; /* code entries in table used */ + let huff = 0; /* Huffman code */ + let incr; /* for incrementing code, index */ + let fill; /* index for replicating entries */ + let low; /* low bits for current root entry */ + let next; /* next available space in table */ + let base = null; /* base value table to use */ + let base_index = 0; + // var shoextra; /* extra bits table to use */ + let end; /* use base and extra for symbol > end */ + const count = new Buf16(MAXBITS + 1); //[MAXBITS+1]; /* number of codes of each length */ + const offs = new Buf16(MAXBITS + 1); //[MAXBITS+1]; /* offsets in table for each length */ + let extra = null; + let extra_index = 0; + + let here_bits, here_op, here_val; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) { + count[len] = 0; + } + for (sym = 0; sym < codes; sym++) { + count[lens[lens_index + sym]]++; + } + + /* bound code lengths, force root to be within code lengths */ + root = bits; + for (max = MAXBITS; max >= 1; max--) { + if (count[max] !== 0) { + break; + } + } + if (root > max) { + root = max; + } + if (max === 0) { /* no symbols to code at all */ + //table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */ + //table.bits[opts.table_index] = 1; //here.bits = (var char)1; + //table.val[opts.table_index++] = 0; //here.val = (var short)0; + table[table_index++] = 1 << 24 | 64 << 16 | 0; + + + //table.op[opts.table_index] = 64; + //table.bits[opts.table_index] = 1; + //table.val[opts.table_index++] = 0; + table[table_index++] = 1 << 24 | 64 << 16 | 0; + + opts.bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min < max; min++) { + if (count[min] !== 0) { + break; + } + } + if (root < min) { + root = min; + } + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) { + return -1; + } /* over-subscribed */ + } + if (left > 0 && (type === CODES || max !== 1)) { + return -1; /* incomplete set */ + } + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) { + offs[len + 1] = offs[len] + count[len]; + } + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) { + if (lens[lens_index + sym] !== 0) { + work[offs[lens[lens_index + sym]]++] = sym; + } + } + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftrees.h + for more information. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + // poor man optimization - use if-else instead of switch, + // to avoid deopts in old v8 + if (type === CODES) { + base = extra = work; /* dummy value--not used */ + end = 19; + + } else if (type === LENS) { + base = lbase; + base_index -= 257; + extra = lext; + extra_index -= 257; + end = 256; + + } else { /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize opts for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = table_index; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = -1; /* trigger new sub-table when len > root */ + used = 1 << root; /* use root table entries */ + const mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if (type === LENS && used > ENOUGH_LENS || + type === DISTS && used > ENOUGH_DISTS) { + return 1; + } + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + here_bits = len - drop; + if (work[sym] < end) { + here_op = 0; + here_val = work[sym]; + } else if (work[sym] > end) { + here_op = extra[extra_index + work[sym]]; + here_val = base[base_index + work[sym]]; + } else { + here_op = 32 + 64; /* end of block */ + here_val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1 << len - drop; + fill = 1 << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + table[next + (huff >> drop) + fill] = here_bits << 24 | here_op << 16 | here_val |0; + } while (fill !== 0); + + /* backwards increment the len-bit code huff */ + incr = 1 << len - 1; + while (huff & incr) { + incr >>= 1; + } + if (incr !== 0) { + huff &= incr - 1; + huff += incr; + } else { + huff = 0; + } + + /* go to next symbol, update count, len */ + sym++; + if (--count[len] === 0) { + if (len === max) { + break; + } + len = lens[lens_index + work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) !== low) { + /* if first time, transition to sub-tables */ + if (drop === 0) { + drop = root; + } + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = 1 << curr; + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) { + break; + } + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1 << curr; + if (type === LENS && used > ENOUGH_LENS || + type === DISTS && used > ENOUGH_DISTS) { + return 1; + } + + /* point entry in root table to sub-table */ + low = huff & mask; + /*table.op[low] = curr; + table.bits[low] = root; + table.val[low] = next - opts.table_index;*/ + table[low] = root << 24 | curr << 16 | next - table_index |0; + } + } + + /* fill in remaining table entry if code is incomplete (guaranteed to have + at most one remaining entry, since if the code is incomplete, the + maximum code length that was allowed to get this far is one bit) */ + if (huff !== 0) { + //table.op[next + huff] = 64; /* invalid code marker */ + //table.bits[next + huff] = len - drop; + //table.val[next + huff] = 0; + table[next + huff] = len - drop << 24 | 64 << 16 |0; + } + + /* set return parameters */ + //opts.table_index += used; + opts.bits = root; + return 0; +} + +const CODES$1 = 0; +const LENS$1 = 1; +const DISTS$1 = 2; + +/* STATES ====================================================================*/ +/* ===========================================================================*/ + + +const HEAD = 1; /* i: waiting for magic header */ +const FLAGS = 2; /* i: waiting for method and flags (gzip) */ +const TIME = 3; /* i: waiting for modification time (gzip) */ +const OS = 4; /* i: waiting for extra flags and operating system (gzip) */ +const EXLEN = 5; /* i: waiting for extra length (gzip) */ +const EXTRA = 6; /* i: waiting for extra bytes (gzip) */ +const NAME = 7; /* i: waiting for end of file name (gzip) */ +const COMMENT = 8; /* i: waiting for end of comment (gzip) */ +const HCRC = 9; /* i: waiting for header crc (gzip) */ +const DICTID = 10; /* i: waiting for dictionary check value */ +const DICT = 11; /* waiting for inflateSetDictionary() call */ +const TYPE$1 = 12; /* i: waiting for type bits, including last-flag bit */ +const TYPEDO = 13; /* i: same, but skip check to exit inflate on new block */ +const STORED = 14; /* i: waiting for stored size (length and complement) */ +const COPY_ = 15; /* i/o: same as COPY below, but only first time in */ +const COPY = 16; /* i/o: waiting for input or output to copy stored block */ +const TABLE = 17; /* i: waiting for dynamic block table lengths */ +const LENLENS = 18; /* i: waiting for code length code lengths */ +const CODELENS = 19; /* i: waiting for length/lit and distance code lengths */ +const LEN_ = 20; /* i: same as LEN below, but only first time in */ +const LEN = 21; /* i: waiting for length/lit/eob code */ +const LENEXT = 22; /* i: waiting for length extra bits */ +const DIST = 23; /* i: waiting for distance code */ +const DISTEXT = 24; /* i: waiting for distance extra bits */ +const MATCH = 25; /* o: waiting for output space to copy string */ +const LIT = 26; /* o: waiting for output space to write literal */ +const CHECK = 27; /* i: waiting for 32-bit check value */ +const LENGTH = 28; /* i: waiting for 32-bit length (gzip) */ +const DONE = 29; /* finished check, done -- remain here until reset */ +const BAD$1 = 30; /* got a data error -- remain here until reset */ +//const MEM = 31; /* got an inflate() memory error -- remain here until reset */ +const SYNC = 32; /* looking for synchronization bytes to restart inflate() */ + +/* ===========================================================================*/ + + + +const ENOUGH_LENS$1 = 852; +const ENOUGH_DISTS$1 = 592; + + +function zswap32(q) { + return (((q >>> 24) & 0xff) + + ((q >>> 8) & 0xff00) + + ((q & 0xff00) << 8) + + ((q & 0xff) << 24)); +} + + +class InflateState { + constructor() { + this.mode = 0; /* current inflate mode */ + this.last = false; /* true if processing last block */ + this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ + this.havedict = false; /* true if dictionary provided */ + this.flags = 0; /* gzip header method and flags (0 if zlib) */ + this.dmax = 0; /* zlib header max distance (INFLATE_STRICT) */ + this.check = 0; /* protected copy of check value */ + this.total = 0; /* protected copy of output count */ + // TODO: may be {} + this.head = null; /* where to save gzip header information */ + + /* sliding window */ + this.wbits = 0; /* log base 2 of requested window size */ + this.wsize = 0; /* window size or zero if not using window */ + this.whave = 0; /* valid bytes in the window */ + this.wnext = 0; /* window write index */ + this.window = null; /* allocated sliding window, if needed */ + + /* bit accumulator */ + this.hold = 0; /* input bit accumulator */ + this.bits = 0; /* number of bits in "in" */ + + /* for string and stored block copying */ + this.length = 0; /* literal or length of data to copy */ + this.offset = 0; /* distance back to copy string from */ + + /* for table and code decoding */ + this.extra = 0; /* extra bits needed */ + + /* fixed and dynamic code tables */ + this.lencode = null; /* starting table for length/literal codes */ + this.distcode = null; /* starting table for distance codes */ + this.lenbits = 0; /* index bits for lencode */ + this.distbits = 0; /* index bits for distcode */ + + /* dynamic table building */ + this.ncode = 0; /* number of code length code lengths */ + this.nlen = 0; /* number of length code lengths */ + this.ndist = 0; /* number of distance code lengths */ + this.have = 0; /* number of code lengths in lens[] */ + this.next = null; /* next available space in codes[] */ + + this.lens = new Buf16(320); /* temporary storage for code lengths */ + this.work = new Buf16(288); /* work area for code table building */ + + /* + because we don't have pointers in js, we use lencode and distcode directly + as buffers so we don't need codes + */ + //this.codes = new utils.Buf32(ENOUGH); /* space for code tables */ + this.lendyn = null; /* dynamic table for length/literal codes (JS specific) */ + this.distdyn = null; /* dynamic table for distance codes (JS specific) */ + this.sane = 0; /* if false, allow invalid distance too far */ + this.back = 0; /* bits back of last unprocessed length/lit */ + this.was = 0; /* initial length of match */ + } +} + +function inflateResetKeep(strm) { + let state; + + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + strm.total_in = strm.total_out = state.total = 0; + strm.msg = ''; /*Z_NULL*/ + if (state.wrap) { /* to support ill-conceived Java test suite */ + strm.adler = state.wrap & 1; + } + state.mode = HEAD; + state.last = 0; + state.havedict = 0; + state.dmax = 32768; + state.head = null/*Z_NULL*/; + state.hold = 0; + state.bits = 0; + //state.lencode = state.distcode = state.next = state.codes; + state.lencode = state.lendyn = new Buf32(ENOUGH_LENS$1); + state.distcode = state.distdyn = new Buf32(ENOUGH_DISTS$1); + + state.sane = 1; + state.back = -1; + //Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +function inflateReset(strm) { + let state; + + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + state.wsize = 0; + state.whave = 0; + state.wnext = 0; + return inflateResetKeep(strm); + +} + +function inflateReset2(strm, windowBits) { + let wrap; + let state; + + /* get the state */ + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } + else { + wrap = (windowBits >> 4) + 1; + if (windowBits < 48) { + windowBits &= 15; + } + } + + /* set number of window bits, free window if different */ + if (windowBits && (windowBits < 8 || windowBits > 15)) { + return Z_STREAM_ERROR; + } + if (state.window !== null && state.wbits !== windowBits) { + state.window = null; + } + + /* update state and reset the rest of it */ + state.wrap = wrap; + state.wbits = windowBits; + return inflateReset(strm); +} + +function inflateInit2(strm, windowBits) { + let ret; + let state; + + if (!strm) { return Z_STREAM_ERROR; } + //strm.msg = Z_NULL; /* in case we return an error */ + + state = new InflateState(); + + //if (state === Z_NULL) return Z_MEM_ERROR; + //Tracev((stderr, "inflate: allocated\n")); + strm.state = state; + state.window = null/*Z_NULL*/; + ret = inflateReset2(strm, windowBits); + if (ret !== Z_OK) { + strm.state = null/*Z_NULL*/; + } + return ret; +} + + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +let virgin = true; + +let lenfix, distfix; // We have no pointers in JS, so keep tables separate + +function fixedtables(state) { + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + let sym; + + lenfix = new Buf32(512); + distfix = new Buf32(32); + + /* literal/length table */ + sym = 0; + while (sym < 144) { state.lens[sym++] = 8; } + while (sym < 256) { state.lens[sym++] = 9; } + while (sym < 280) { state.lens[sym++] = 7; } + while (sym < 288) { state.lens[sym++] = 8; } + + inflate_table(LENS$1, state.lens, 0, 288, lenfix, 0, state.work, { bits: 9 }); + + /* distance table */ + sym = 0; + while (sym < 32) { state.lens[sym++] = 5; } + + inflate_table(DISTS$1, state.lens, 0, 32, distfix, 0, state.work, { bits: 5 }); + + /* do this just once */ + virgin = false; + } + + state.lencode = lenfix; + state.lenbits = 9; + state.distcode = distfix; + state.distbits = 5; +} + + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +function updatewindow(strm, src, end, copy) { + let dist; + const state = strm.state; + + /* if it hasn't been done already, allocate space for the window */ + if (state.window === null) { + state.wsize = 1 << state.wbits; + state.wnext = 0; + state.whave = 0; + + state.window = new Buf8(state.wsize); + } + + /* copy state->wsize or less output bytes into the circular window */ + if (copy >= state.wsize) { + arraySet(state.window, src, end - state.wsize, state.wsize, 0); + state.wnext = 0; + state.whave = state.wsize; + } + else { + dist = state.wsize - state.wnext; + if (dist > copy) { + dist = copy; + } + //zmemcpy(state->window + state->wnext, end - copy, dist); + arraySet(state.window, src, end - copy, dist, state.wnext); + copy -= dist; + if (copy) { + //zmemcpy(state->window, end - copy, copy); + arraySet(state.window, src, end - copy, copy, 0); + state.wnext = copy; + state.whave = state.wsize; + } + else { + state.wnext += dist; + if (state.wnext === state.wsize) { state.wnext = 0; } + if (state.whave < state.wsize) { state.whave += dist; } + } + } + return 0; +} + +function inflate(strm, flush) { + let state; + let input, output; // input/output buffers + let next; /* next input INDEX */ + let put; /* next output INDEX */ + let have, left; /* available input and output */ + let hold; /* bit buffer */ + let bits; /* bits in bit buffer */ + let _in, _out; /* save starting available input and output */ + let copy; /* number of stored or match bytes to copy */ + let from; /* where to copy match bytes from */ + let from_source; + let here = 0; /* current decoding table entry */ + let here_bits, here_op, here_val; // paked "here" denormalized (JS specific) + //var last; /* parent table entry */ + let last_bits, last_op, last_val; // paked "last" denormalized (JS specific) + let len; /* length to copy for repeats, bits to drop */ + let ret; /* return code */ + let hbuf = new Buf8(4); /* buffer for gzip header crc calculation */ + let opts; + + let n; // temporary var for NEED_BITS + + const order = /* permutation of code lengths */ + [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ]; + + + if (!strm || !strm.state || !strm.output || + (!strm.input && strm.avail_in !== 0)) { + return Z_STREAM_ERROR; + } + + state = strm.state; + if (state.mode === TYPE$1) { state.mode = TYPEDO; } /* skip check */ + + + //--- LOAD() --- + put = strm.next_out; + output = strm.output; + left = strm.avail_out; + next = strm.next_in; + input = strm.input; + have = strm.avail_in; + hold = state.hold; + bits = state.bits; + //--- + + _in = have; + _out = left; + ret = Z_OK; + + inf_leave: // goto emulation + for (;;) { + switch (state.mode) { + case HEAD: + if (state.wrap === 0) { + state.mode = TYPEDO; + break; + } + //=== NEEDBITS(16); + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if ((state.wrap & 2) && hold === 0x8b1f) { /* gzip header */ + state.check = 0/*crc32(0L, Z_NULL, 0)*/; + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = FLAGS; + break; + } + state.flags = 0; /* expect zlib header */ + if (state.head) { + state.head.done = false; + } + if (!(state.wrap & 1) || /* check if zlib header allowed */ + (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) { + strm.msg = 'incorrect header check'; + state.mode = BAD$1; + break; + } + if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) { + strm.msg = 'unknown compression method'; + state.mode = BAD$1; + break; + } + //--- DROPBITS(4) ---// + hold >>>= 4; + bits -= 4; + //---// + len = (hold & 0x0f)/*BITS(4)*/ + 8; + if (state.wbits === 0) { + state.wbits = len; + } + else if (len > state.wbits) { + strm.msg = 'invalid window size'; + state.mode = BAD$1; + break; + } + state.dmax = 1 << len; + //Tracev((stderr, "inflate: zlib header ok\n")); + strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; + state.mode = hold & 0x200 ? DICTID : TYPE$1; + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + break; + case FLAGS: + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.flags = hold; + if ((state.flags & 0xff) !== Z_DEFLATED) { + strm.msg = 'unknown compression method'; + state.mode = BAD$1; + break; + } + if (state.flags & 0xe000) { + strm.msg = 'unknown header flags set'; + state.mode = BAD$1; + break; + } + if (state.head) { + state.head.text = ((hold >> 8) & 1); + } + if (state.flags & 0x0200) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = TIME; + /* falls through */ + case TIME: + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (state.head) { + state.head.time = hold; + } + if (state.flags & 0x0200) { + //=== CRC4(state.check, hold) + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + hbuf[2] = (hold >>> 16) & 0xff; + hbuf[3] = (hold >>> 24) & 0xff; + state.check = crc32(state.check, hbuf, 4, 0); + //=== + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = OS; + /* falls through */ + case OS: + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (state.head) { + state.head.xflags = (hold & 0xff); + state.head.os = (hold >> 8); + } + if (state.flags & 0x0200) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = EXLEN; + /* falls through */ + case EXLEN: + if (state.flags & 0x0400) { + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.length = hold; + if (state.head) { + state.head.extra_len = hold; + } + if (state.flags & 0x0200) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + } + else if (state.head) { + state.head.extra = null/*Z_NULL*/; + } + state.mode = EXTRA; + /* falls through */ + case EXTRA: + if (state.flags & 0x0400) { + copy = state.length; + if (copy > have) { copy = have; } + if (copy) { + if (state.head) { + len = state.head.extra_len - state.length; + if (!state.head.extra) { + // Use untyped array for more convenient processing later + state.head.extra = new Array(state.head.extra_len); + } + arraySet( + state.head.extra, + input, + next, + // extra field is limited to 65536 bytes + // - no need for additional size check + copy, + /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/ + len + ); + //zmemcpy(state.head.extra + len, next, + // len + copy > state.head.extra_max ? + // state.head.extra_max - len : copy); + } + if (state.flags & 0x0200) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + state.length -= copy; + } + if (state.length) { break inf_leave; } + } + state.length = 0; + state.mode = NAME; + /* falls through */ + case NAME: + if (state.flags & 0x0800) { + if (have === 0) { break inf_leave; } + copy = 0; + do { + // TODO: 2 or 1 bytes? + len = input[next + copy++]; + /* use constant limit because in js we should not preallocate memory */ + if (state.head && len && + (state.length < 65536 /*state.head.name_max*/)) { + state.head.name += String.fromCharCode(len); + } + } while (len && copy < have); + + if (state.flags & 0x0200) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + if (len) { break inf_leave; } + } + else if (state.head) { + state.head.name = null; + } + state.length = 0; + state.mode = COMMENT; + /* falls through */ + case COMMENT: + if (state.flags & 0x1000) { + if (have === 0) { break inf_leave; } + copy = 0; + do { + len = input[next + copy++]; + /* use constant limit because in js we should not preallocate memory */ + if (state.head && len && + (state.length < 65536 /*state.head.comm_max*/)) { + state.head.comment += String.fromCharCode(len); + } + } while (len && copy < have); + if (state.flags & 0x0200) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + if (len) { break inf_leave; } + } + else if (state.head) { + state.head.comment = null; + } + state.mode = HCRC; + /* falls through */ + case HCRC: + if (state.flags & 0x0200) { + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (hold !== (state.check & 0xffff)) { + strm.msg = 'header crc mismatch'; + state.mode = BAD$1; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + } + if (state.head) { + state.head.hcrc = ((state.flags >> 9) & 1); + state.head.done = true; + } + strm.adler = state.check = 0; + state.mode = TYPE$1; + break; + case DICTID: + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + strm.adler = state.check = zswap32(hold); + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = DICT; + /* falls through */ + case DICT: + if (state.havedict === 0) { + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + return Z_NEED_DICT; + } + strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; + state.mode = TYPE$1; + /* falls through */ + case TYPE$1: + if (flush === Z_BLOCK || flush === Z_TREES) { break inf_leave; } + /* falls through */ + case TYPEDO: + if (state.last) { + //--- BYTEBITS() ---// + hold >>>= bits & 7; + bits -= bits & 7; + //---// + state.mode = CHECK; + break; + } + //=== NEEDBITS(3); */ + while (bits < 3) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.last = (hold & 0x01)/*BITS(1)*/; + //--- DROPBITS(1) ---// + hold >>>= 1; + bits -= 1; + //---// + + switch ((hold & 0x03)/*BITS(2)*/) { + case 0: /* stored block */ + //Tracev((stderr, "inflate: stored block%s\n", + // state.last ? " (last)" : "")); + state.mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + //Tracev((stderr, "inflate: fixed codes block%s\n", + // state.last ? " (last)" : "")); + state.mode = LEN_; /* decode codes */ + if (flush === Z_TREES) { + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + break inf_leave; + } + break; + case 2: /* dynamic block */ + //Tracev((stderr, "inflate: dynamic codes block%s\n", + // state.last ? " (last)" : "")); + state.mode = TABLE; + break; + case 3: + strm.msg = 'invalid block type'; + state.mode = BAD$1; + } + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + break; + case STORED: + //--- BYTEBITS() ---// /* go to byte boundary */ + hold >>>= bits & 7; + bits -= bits & 7; + //---// + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) { + strm.msg = 'invalid stored block lengths'; + state.mode = BAD$1; + break; + } + state.length = hold & 0xffff; + //Tracev((stderr, "inflate: stored length %u\n", + // state.length)); + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = COPY_; + if (flush === Z_TREES) { break inf_leave; } + /* falls through */ + case COPY_: + state.mode = COPY; + /* falls through */ + case COPY: + copy = state.length; + if (copy) { + if (copy > have) { copy = have; } + if (copy > left) { copy = left; } + if (copy === 0) { break inf_leave; } + //--- zmemcpy(put, next, copy); --- + arraySet(output, input, next, copy, put); + //---// + have -= copy; + next += copy; + left -= copy; + put += copy; + state.length -= copy; + break; + } + //Tracev((stderr, "inflate: stored end\n")); + state.mode = TYPE$1; + break; + case TABLE: + //=== NEEDBITS(14); */ + while (bits < 14) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257; + //--- DROPBITS(5) ---// + hold >>>= 5; + bits -= 5; + //---// + state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1; + //--- DROPBITS(5) ---// + hold >>>= 5; + bits -= 5; + //---// + state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4; + //--- DROPBITS(4) ---// + hold >>>= 4; + bits -= 4; + //---// +//#ifndef PKZIP_BUG_WORKAROUND + if (state.nlen > 286 || state.ndist > 30) { + strm.msg = 'too many length or distance symbols'; + state.mode = BAD$1; + break; + } +//#endif + //Tracev((stderr, "inflate: table sizes ok\n")); + state.have = 0; + state.mode = LENLENS; + /* falls through */ + case LENLENS: + while (state.have < state.ncode) { + //=== NEEDBITS(3); + while (bits < 3) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.lens[order[state.have++]] = (hold & 0x07);//BITS(3); + //--- DROPBITS(3) ---// + hold >>>= 3; + bits -= 3; + //---// + } + while (state.have < 19) { + state.lens[order[state.have++]] = 0; + } + // We have separate tables & no pointers. 2 commented lines below not needed. + //state.next = state.codes; + //state.lencode = state.next; + // Switch to use dynamic table + state.lencode = state.lendyn; + state.lenbits = 7; + + opts = { bits: state.lenbits }; + ret = inflate_table(CODES$1, state.lens, 0, 19, state.lencode, 0, state.work, opts); + state.lenbits = opts.bits; + + if (ret) { + strm.msg = 'invalid code lengths set'; + state.mode = BAD$1; + break; + } + //Tracev((stderr, "inflate: code lengths ok\n")); + state.have = 0; + state.mode = CODELENS; + /* falls through */ + case CODELENS: + while (state.have < state.nlen + state.ndist) { + for (;;) { + here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if (here_val < 16) { + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.lens[state.have++] = here_val; + } + else { + if (here_val === 16) { + //=== NEEDBITS(here.bits + 2); + n = here_bits + 2; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + if (state.have === 0) { + strm.msg = 'invalid bit length repeat'; + state.mode = BAD$1; + break; + } + len = state.lens[state.have - 1]; + copy = 3 + (hold & 0x03);//BITS(2); + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + } + else if (here_val === 17) { + //=== NEEDBITS(here.bits + 3); + n = here_bits + 3; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + len = 0; + copy = 3 + (hold & 0x07);//BITS(3); + //--- DROPBITS(3) ---// + hold >>>= 3; + bits -= 3; + //---// + } + else { + //=== NEEDBITS(here.bits + 7); + n = here_bits + 7; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + len = 0; + copy = 11 + (hold & 0x7f);//BITS(7); + //--- DROPBITS(7) ---// + hold >>>= 7; + bits -= 7; + //---// + } + if (state.have + copy > state.nlen + state.ndist) { + strm.msg = 'invalid bit length repeat'; + state.mode = BAD$1; + break; + } + while (copy--) { + state.lens[state.have++] = len; + } + } + } + + /* handle error breaks in while */ + if (state.mode === BAD$1) { break; } + + /* check for end-of-block code (better have one) */ + if (state.lens[256] === 0) { + strm.msg = 'invalid code -- missing end-of-block'; + state.mode = BAD$1; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state.lenbits = 9; + + opts = { bits: state.lenbits }; + ret = inflate_table(LENS$1, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts); + // We have separate tables & no pointers. 2 commented lines below not needed. + // state.next_index = opts.table_index; + state.lenbits = opts.bits; + // state.lencode = state.next; + + if (ret) { + strm.msg = 'invalid literal/lengths set'; + state.mode = BAD$1; + break; + } + + state.distbits = 6; + //state.distcode.copy(state.codes); + // Switch to use dynamic table + state.distcode = state.distdyn; + opts = { bits: state.distbits }; + ret = inflate_table(DISTS$1, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts); + // We have separate tables & no pointers. 2 commented lines below not needed. + // state.next_index = opts.table_index; + state.distbits = opts.bits; + // state.distcode = state.next; + + if (ret) { + strm.msg = 'invalid distances set'; + state.mode = BAD$1; + break; + } + //Tracev((stderr, 'inflate: codes ok\n')); + state.mode = LEN_; + if (flush === Z_TREES) { break inf_leave; } + /* falls through */ + case LEN_: + state.mode = LEN; + /* falls through */ + case LEN: + if (have >= 6 && left >= 258) { + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + inflate_fast(strm, _out); + //--- LOAD() --- + put = strm.next_out; + output = strm.output; + left = strm.avail_out; + next = strm.next_in; + input = strm.input; + have = strm.avail_in; + hold = state.hold; + bits = state.bits; + //--- + + if (state.mode === TYPE$1) { + state.back = -1; + } + break; + } + state.back = 0; + for (;;) { + here = state.lencode[hold & ((1 << state.lenbits) - 1)]; /*BITS(state.lenbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if (here_bits <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if (here_op && (here_op & 0xf0) === 0) { + last_bits = here_bits; + last_op = here_op; + last_val = here_val; + for (;;) { + here = state.lencode[last_val + + ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((last_bits + here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + //--- DROPBITS(last.bits) ---// + hold >>>= last_bits; + bits -= last_bits; + //---// + state.back += last_bits; + } + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.back += here_bits; + state.length = here_val; + if (here_op === 0) { + //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + // "inflate: literal '%c'\n" : + // "inflate: literal 0x%02x\n", here.val)); + state.mode = LIT; + break; + } + if (here_op & 32) { + //Tracevv((stderr, "inflate: end of block\n")); + state.back = -1; + state.mode = TYPE$1; + break; + } + if (here_op & 64) { + strm.msg = 'invalid literal/length code'; + state.mode = BAD$1; + break; + } + state.extra = here_op & 15; + state.mode = LENEXT; + /* falls through */ + case LENEXT: + if (state.extra) { + //=== NEEDBITS(state.extra); + n = state.extra; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.length += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; + //--- DROPBITS(state.extra) ---// + hold >>>= state.extra; + bits -= state.extra; + //---// + state.back += state.extra; + } + //Tracevv((stderr, "inflate: length %u\n", state.length)); + state.was = state.length; + state.mode = DIST; + /* falls through */ + case DIST: + for (;;) { + here = state.distcode[hold & ((1 << state.distbits) - 1)];/*BITS(state.distbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if ((here_op & 0xf0) === 0) { + last_bits = here_bits; + last_op = here_op; + last_val = here_val; + for (;;) { + here = state.distcode[last_val + + ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((last_bits + here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + //--- DROPBITS(last.bits) ---// + hold >>>= last_bits; + bits -= last_bits; + //---// + state.back += last_bits; + } + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.back += here_bits; + if (here_op & 64) { + strm.msg = 'invalid distance code'; + state.mode = BAD$1; + break; + } + state.offset = here_val; + state.extra = (here_op) & 15; + state.mode = DISTEXT; + /* falls through */ + case DISTEXT: + if (state.extra) { + //=== NEEDBITS(state.extra); + n = state.extra; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.offset += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; + //--- DROPBITS(state.extra) ---// + hold >>>= state.extra; + bits -= state.extra; + //---// + state.back += state.extra; + } +//#ifdef INFLATE_STRICT + if (state.offset > state.dmax) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD$1; + break; + } +//#endif + //Tracevv((stderr, "inflate: distance %u\n", state.offset)); + state.mode = MATCH; + /* falls through */ + case MATCH: + if (left === 0) { break inf_leave; } + copy = _out - left; + if (state.offset > copy) { /* copy from window */ + copy = state.offset - copy; + if (copy > state.whave) { + if (state.sane) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD$1; + break; + } +// (!) This block is disabled in zlib defaults, +// don't enable it for binary compatibility +//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR +// Trace((stderr, "inflate.c too far\n")); +// copy -= state.whave; +// if (copy > state.length) { copy = state.length; } +// if (copy > left) { copy = left; } +// left -= copy; +// state.length -= copy; +// do { +// output[put++] = 0; +// } while (--copy); +// if (state.length === 0) { state.mode = LEN; } +// break; +//#endif + } + if (copy > state.wnext) { + copy -= state.wnext; + from = state.wsize - copy; + } + else { + from = state.wnext - copy; + } + if (copy > state.length) { copy = state.length; } + from_source = state.window; + } + else { /* copy from output */ + from_source = output; + from = put - state.offset; + copy = state.length; + } + if (copy > left) { copy = left; } + left -= copy; + state.length -= copy; + do { + output[put++] = from_source[from++]; + } while (--copy); + if (state.length === 0) { state.mode = LEN; } + break; + case LIT: + if (left === 0) { break inf_leave; } + output[put++] = state.length; + left--; + state.mode = LEN; + break; + case CHECK: + if (state.wrap) { + //=== NEEDBITS(32); + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + // Use '|' instead of '+' to make sure that result is signed + hold |= input[next++] << bits; + bits += 8; + } + //===// + _out -= left; + strm.total_out += _out; + state.total += _out; + if (_out) { + strm.adler = state.check = + /*UPDATE(state.check, put - _out, _out);*/ + (state.flags ? crc32(state.check, output, _out, put - _out) : adler32(state.check, output, _out, put - _out)); + + } + _out = left; + // NB: crc32 stored as signed 32-bit int, zswap32 returns signed too + if ((state.flags ? hold : zswap32(hold)) !== state.check) { + strm.msg = 'incorrect data check'; + state.mode = BAD$1; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + //Tracev((stderr, "inflate: check matches trailer\n")); + } + state.mode = LENGTH; + /* falls through */ + case LENGTH: + if (state.wrap && state.flags) { + //=== NEEDBITS(32); + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (hold !== (state.total & 0xffffffff)) { + strm.msg = 'incorrect length check'; + state.mode = BAD$1; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + //Tracev((stderr, "inflate: length matches trailer\n")); + } + state.mode = DONE; + /* falls through */ + case DONE: + ret = Z_STREAM_END; + break inf_leave; + case BAD$1: + ret = Z_DATA_ERROR; + break inf_leave; + // case MEM: + // return Z_MEM_ERROR; + case SYNC: + /* falls through */ + default: + return Z_STREAM_ERROR; + } + } + + // inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave" + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + + if (state.wsize || (_out !== strm.avail_out && state.mode < BAD$1 && + (state.mode < CHECK || flush !== Z_FINISH))) { + if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) ; + } + _in -= strm.avail_in; + _out -= strm.avail_out; + strm.total_in += _in; + strm.total_out += _out; + state.total += _out; + if (state.wrap && _out) { + strm.adler = state.check = /*UPDATE(state.check, strm.next_out - _out, _out);*/ + (state.flags ? crc32(state.check, output, _out, strm.next_out - _out) : adler32(state.check, output, _out, strm.next_out - _out)); + } + strm.data_type = state.bits + (state.last ? 64 : 0) + + (state.mode === TYPE$1 ? 128 : 0) + + (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0); + if (((_in === 0 && _out === 0) || flush === Z_FINISH) && ret === Z_OK) { + ret = Z_BUF_ERROR; + } + return ret; +} + +function inflateEnd(strm) { + + if (!strm || !strm.state /*|| strm->zfree == (free_func)0*/) { + return Z_STREAM_ERROR; + } + + const state = strm.state; + if (state.window) { + state.window = null; + } + strm.state = null; + return Z_OK; +} + +function inflateGetHeader(strm, head) { + let state; + + /* check state */ + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR; } + + /* save header structure */ + state.head = head; + head.done = false; + return Z_OK; +} + +function inflateSetDictionary(strm, dictionary) { + const dictLength = dictionary.length; + + let state; + let dictid; + + /* check state */ + if (!strm /* == Z_NULL */ || !strm.state /* == Z_NULL */) { return Z_STREAM_ERROR; } + state = strm.state; + + if (state.wrap !== 0 && state.mode !== DICT) { + return Z_STREAM_ERROR; + } + + /* check for correct dictionary identifier */ + if (state.mode === DICT) { + dictid = 1; /* adler32(0, null, 0)*/ + /* dictid = adler32(dictid, dictionary, dictLength); */ + dictid = adler32(dictid, dictionary, dictLength, 0); + if (dictid !== state.check) { + return Z_DATA_ERROR; + } + } + /* copy dictionary to window using updatewindow(), which will amend the + existing dictionary if appropriate */ + updatewindow(strm, dictionary, dictLength, dictLength); + // if (ret) { + // state.mode = MEM; + // return Z_MEM_ERROR; + // } + state.havedict = 1; + // Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +/* Not implemented +exports.inflateCopy = inflateCopy; +exports.inflateGetDictionary = inflateGetDictionary; +exports.inflateMark = inflateMark; +exports.inflatePrime = inflatePrime; +exports.inflateSync = inflateSync; +exports.inflateSyncPoint = inflateSyncPoint; +exports.inflateUndermine = inflateUndermine; +*/ + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +class GZheader { + constructor() { + /* true if compressed data believed to be text */ + this.text = 0; + /* modification time */ + this.time = 0; + /* extra flags (not used when writing a gzip file) */ + this.xflags = 0; + /* operating system */ + this.os = 0; + /* pointer to extra field or Z_NULL if none */ + this.extra = null; + /* extra field length (valid if extra != Z_NULL) */ + this.extra_len = 0; // Actually, we don't need it in JS, + // but leave for few code modifications + + // + // Setup limits is not necessary because in js we should not preallocate memory + // for inflate use constant limit in 65536 bytes + // + + /* space at extra (only when reading header) */ + // this.extra_max = 0; + /* pointer to zero-terminated file name or Z_NULL */ + this.name = ''; + /* space at name (only when reading header) */ + // this.name_max = 0; + /* pointer to zero-terminated comment or Z_NULL */ + this.comment = ''; + /* space at comment (only when reading header) */ + // this.comm_max = 0; + /* true if there was or will be a header crc */ + this.hcrc = 0; + /* true when done reading gzip header (not used when writing a gzip file) */ + this.done = false; + } +} + +/** + * class Inflate + * + * Generic JS-style wrapper for zlib calls. If you don't need + * streaming behaviour - use more simple functions: [[inflate]] + * and [[inflateRaw]]. + **/ + +/* internal + * inflate.chunks -> Array + * + * Chunks of output data, if [[Inflate#onData]] not overridden. + **/ + +/** + * Inflate.result -> Uint8Array|Array|String + * + * Uncompressed result, generated by default [[Inflate#onData]] + * and [[Inflate#onEnd]] handlers. Filled after you push last chunk + * (call [[Inflate#push]] with `Z_FINISH` / `true` param) or if you + * push a chunk with explicit flush (call [[Inflate#push]] with + * `Z_SYNC_FLUSH` param). + **/ + +/** + * Inflate.err -> Number + * + * Error code after inflate finished. 0 (Z_OK) on success. + * Should be checked if broken data possible. + **/ + +/** + * Inflate.msg -> String + * + * Error message, if [[Inflate.err]] != 0 + **/ + + +/** + * new Inflate(options) + * - options (Object): zlib inflate options. + * + * Creates new inflator instance with specified params. Throws exception + * on bad params. Supported options: + * + * - `windowBits` + * - `dictionary` + * + * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) + * for more information on these. + * + * Additional options, for internal needs: + * + * - `chunkSize` - size of generated data chunks (16K by default) + * - `raw` (Boolean) - do raw inflate + * - `to` (String) - if equal to 'string', then result will be converted + * from utf8 to utf16 (javascript) string. When string output requested, + * chunk length can differ from `chunkSize`, depending on content. + * + * By default, when no options set, autodetect deflate/gzip data format via + * wrapper header. + * + * ##### Example: + * + * ```javascript + * var pako = require('pako') + * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9]) + * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]); + * + * var inflate = new pako.Inflate({ level: 3}); + * + * inflate.push(chunk1, false); + * inflate.push(chunk2, true); // true -> last chunk + * + * if (inflate.err) { throw new Error(inflate.err); } + * + * console.log(inflate.result); + * ``` + **/ +class Inflate { + constructor(options) { + this.options = { + chunkSize: 16384, + windowBits: 0, + ...(options || {}) + }; + + const opt = this.options; + + // Force window size for `raw` data, if not set directly, + // because we have no header for autodetect. + if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) { + opt.windowBits = -opt.windowBits; + if (opt.windowBits === 0) { opt.windowBits = -15; } + } + + // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate + if ((opt.windowBits >= 0) && (opt.windowBits < 16) && + !(options && options.windowBits)) { + opt.windowBits += 32; + } + + // Gzip header has no info about windows size, we can do autodetect only + // for deflate. So, if window size not set, force it to max when gzip possible + if ((opt.windowBits > 15) && (opt.windowBits < 48)) { + // bit 3 (16) -> gzipped data + // bit 4 (32) -> autodetect gzip/deflate + if ((opt.windowBits & 15) === 0) { + opt.windowBits |= 15; + } + } + + this.err = 0; // error code, if happens (0 = Z_OK) + this.msg = ''; // error message + this.ended = false; // used to avoid multiple onEnd() calls + this.chunks = []; // chunks of compressed data + + this.strm = new ZStream(); + this.strm.avail_out = 0; + + let status = inflateInit2( + this.strm, + opt.windowBits + ); + + if (status !== Z_OK) { + throw new Error(msg[status]); + } + + this.header = new GZheader(); + + inflateGetHeader(this.strm, this.header); + + // Setup dictionary + if (opt.dictionary) { + // Convert data if needed + if (typeof opt.dictionary === 'string') { + opt.dictionary = string2buf(opt.dictionary); + } else if (opt.dictionary instanceof ArrayBuffer) { + opt.dictionary = new Uint8Array(opt.dictionary); + } + if (opt.raw) { //In raw mode we need to set the dictionary early + status = inflateSetDictionary(this.strm, opt.dictionary); + if (status !== Z_OK) { + throw new Error(msg[status]); + } + } + } + } + /** + * Inflate#push(data[, mode]) -> Boolean + * - data (Uint8Array|Array|ArrayBuffer|String): input data + * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. + * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH. + * + * Sends input data to inflate pipe, generating [[Inflate#onData]] calls with + * new output chunks. Returns `true` on success. The last data block must have + * mode Z_FINISH (or `true`). That will flush internal pending buffers and call + * [[Inflate#onEnd]]. For interim explicit flushes (without ending the stream) you + * can use mode Z_SYNC_FLUSH, keeping the decompression context. + * + * On fail call [[Inflate#onEnd]] with error code and return false. + * + * We strongly recommend to use `Uint8Array` on input for best speed (output + * format is detected automatically). Also, don't skip last param and always + * use the same type in your code (boolean or number). That will improve JS speed. + * + * For regular `Array`-s make sure all elements are [0..255]. + * + * ##### Example + * + * ```javascript + * push(chunk, false); // push one of data chunks + * ... + * push(chunk, true); // push last chunk + * ``` + **/ + push(data, mode) { + const { strm, options: { chunkSize, dictionary } } = this; + let status, _mode; + + // Flag to properly process Z_BUF_ERROR on testing inflate call + // when we check that all output data was flushed. + let allowBufError = false; + + if (this.ended) { return false; } + _mode = (mode === ~~mode) ? mode : ((mode === true) ? Z_FINISH : Z_NO_FLUSH); + + // Convert data if needed + if (typeof data === 'string') { + // Only binary strings can be decompressed on practice + strm.input = binstring2buf(data); + } else if (data instanceof ArrayBuffer) { + strm.input = new Uint8Array(data); + } else { + strm.input = data; + } + + strm.next_in = 0; + strm.avail_in = strm.input.length; + + do { + if (strm.avail_out === 0) { + strm.output = new Buf8(chunkSize); + strm.next_out = 0; + strm.avail_out = chunkSize; + } + + status = inflate(strm, Z_NO_FLUSH); /* no bad return value */ + + if (status === Z_NEED_DICT && dictionary) { + status = inflateSetDictionary(this.strm, dictionary); + } + + if (status === Z_BUF_ERROR && allowBufError === true) { + status = Z_OK; + allowBufError = false; + } + + if (status !== Z_STREAM_END && status !== Z_OK) { + this.onEnd(status); + this.ended = true; + return false; + } + + if (strm.next_out) { + if (strm.avail_out === 0 || status === Z_STREAM_END || (strm.avail_in === 0 && (_mode === Z_FINISH || _mode === Z_SYNC_FLUSH))) { + this.onData(shrinkBuf(strm.output, strm.next_out)); + } + } + + // When no more input data, we should check that internal inflate buffers + // are flushed. The only way to do it when avail_out = 0 - run one more + // inflate pass. But if output data not exists, inflate return Z_BUF_ERROR. + // Here we set flag to process this error properly. + // + // NOTE. Deflate does not return error in this case and does not needs such + // logic. + if (strm.avail_in === 0 && strm.avail_out === 0) { + allowBufError = true; + } + + } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== Z_STREAM_END); + + if (status === Z_STREAM_END) { + _mode = Z_FINISH; + } + + // Finalize on the last chunk. + if (_mode === Z_FINISH) { + status = inflateEnd(this.strm); + this.onEnd(status); + this.ended = true; + return status === Z_OK; + } + + // callback interim results if Z_SYNC_FLUSH. + if (_mode === Z_SYNC_FLUSH) { + this.onEnd(Z_OK); + strm.avail_out = 0; + return true; + } + + return true; + }; + + /** + * Inflate#onData(chunk) -> Void + * - chunk (Uint8Array|Array|String): output data. Type of array depends + * on js engine support. When string output requested, each chunk + * will be string. + * + * By default, stores data blocks in `chunks[]` property and glue + * those in `onEnd`. Override this handler, if you need another behaviour. + **/ + onData(chunk) { + this.chunks.push(chunk); + }; + + + + /** + * Inflate#onEnd(status) -> Void + * - status (Number): inflate status. 0 (Z_OK) on success, + * other if not. + * + * Called either after you tell inflate that the input stream is + * complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH) + * or if an error happened. By default - join collected chunks, + * free memory and fill `results` / `err` properties. + **/ + onEnd(status) { + // On success - join + if (status === Z_OK) { + this.result = flattenChunks(this.chunks); + } + this.chunks = []; + this.err = status; + this.msg = this.strm.msg; + }; +} + +/* +node-bzip - a pure-javascript Node.JS module for decoding bzip2 data + +Copyright (C) 2012 Eli Skeggs + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, see +http://www.gnu.org/licenses/lgpl-2.1.html + +Adapted from bzip2.js, copyright 2011 antimatter15 (antimatter15@gmail.com). + +Based on micro-bunzip by Rob Landley (rob@landley.net). + +Based on bzip2 decompression code by Julian R Seward (jseward@acm.org), +which also acknowledges contributions by Mike Burrows, David Wheeler, +Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten, +Robert Sedgewick, and Jon L. Bentley. +*/ + +var BITMASK = [0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF]; + +// offset in bytes +var BitReader = function(stream) { + this.stream = stream; + this.bitOffset = 0; + this.curByte = 0; + this.hasByte = false; +}; + +BitReader.prototype._ensureByte = function() { + if (!this.hasByte) { + this.curByte = this.stream.readByte(); + this.hasByte = true; + } +}; + +// reads bits from the buffer +BitReader.prototype.read = function(bits) { + var result = 0; + while (bits > 0) { + this._ensureByte(); + var remaining = 8 - this.bitOffset; + // if we're in a byte + if (bits >= remaining) { + result <<= remaining; + result |= BITMASK[remaining] & this.curByte; + this.hasByte = false; + this.bitOffset = 0; + bits -= remaining; + } else { + result <<= bits; + var shift = remaining - bits; + result |= (this.curByte & (BITMASK[bits] << shift)) >> shift; + this.bitOffset += bits; + bits = 0; + } + } + return result; +}; + +// seek to an arbitrary point in the buffer (expressed in bits) +BitReader.prototype.seek = function(pos) { + var n_bit = pos % 8; + var n_byte = (pos - n_bit) / 8; + this.bitOffset = n_bit; + this.stream.seek(n_byte); + this.hasByte = false; +}; + +// reads 6 bytes worth of data using the read method +BitReader.prototype.pi = function() { + var buf = new Uint8Array(6), i; + for (i = 0; i < buf.length; i++) { + buf[i] = this.read(8); + } + return bufToHex(buf); +}; + +function bufToHex(buf) { + return Array.prototype.map.call(buf, x => ('00' + x.toString(16)).slice(-2)).join(''); +} + +var bitreader = BitReader; + +/* very simple input/output stream interface */ +var Stream = function() { +}; + +// input streams ////////////// +/** Returns the next byte, or -1 for EOF. */ +Stream.prototype.readByte = function() { + throw new Error("abstract method readByte() not implemented"); +}; +/** Attempts to fill the buffer; returns number of bytes read, or + * -1 for EOF. */ +Stream.prototype.read = function(buffer, bufOffset, length) { + var bytesRead = 0; + while (bytesRead < length) { + var c = this.readByte(); + if (c < 0) { // EOF + return (bytesRead===0) ? -1 : bytesRead; + } + buffer[bufOffset++] = c; + bytesRead++; + } + return bytesRead; +}; +Stream.prototype.seek = function(new_pos) { + throw new Error("abstract method seek() not implemented"); +}; + +// output streams /////////// +Stream.prototype.writeByte = function(_byte) { + throw new Error("abstract method readByte() not implemented"); +}; +Stream.prototype.write = function(buffer, bufOffset, length) { + var i; + for (i=0; i>> 0; // return an unsigned value + }; + + /** + * Update the CRC with a single byte + * @param value The value to update the CRC with + */ + this.updateCRC = function(value) { + crc = (crc << 8) ^ crc32Lookup[((crc >>> 24) ^ value) & 0xff]; + }; + + /** + * Update the CRC with a sequence of identical bytes + * @param value The value to update the CRC with + * @param count The number of bytes + */ + this.updateCRCRun = function(value, count) { + while (count-- > 0) { + crc = (crc << 8) ^ crc32Lookup[((crc >>> 24) ^ value) & 0xff]; + } + }; + }; + return CRC32; +})(); + +/* +seek-bzip - a pure-javascript module for seeking within bzip2 data + +Copyright (C) 2013 C. Scott Ananian +Copyright (C) 2012 Eli Skeggs +Copyright (C) 2011 Kevin Kwok + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, see +http://www.gnu.org/licenses/lgpl-2.1.html + +Adapted from node-bzip, copyright 2012 Eli Skeggs. +Adapted from bzip2.js, copyright 2011 Kevin Kwok (antimatter15@gmail.com). + +Based on micro-bunzip by Rob Landley (rob@landley.net). + +Based on bzip2 decompression code by Julian R Seward (jseward@acm.org), +which also acknowledges contributions by Mike Burrows, David Wheeler, +Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten, +Robert Sedgewick, and Jon L. Bentley. +*/ + + + + + +var MAX_HUFCODE_BITS = 20; +var MAX_SYMBOLS = 258; +var SYMBOL_RUNA = 0; +var SYMBOL_RUNB = 1; +var MIN_GROUPS = 2; +var MAX_GROUPS = 6; +var GROUP_SIZE = 50; + +var WHOLEPI = "314159265359"; +var SQRTPI = "177245385090"; + +var mtf = function(array, index) { + var src = array[index], i; + for (i = index; i > 0; i--) { + array[i] = array[i-1]; + } + array[0] = src; + return src; +}; + +var Err = { + OK: 0, + LAST_BLOCK: -1, + NOT_BZIP_DATA: -2, + UNEXPECTED_INPUT_EOF: -3, + UNEXPECTED_OUTPUT_EOF: -4, + DATA_ERROR: -5, + OUT_OF_MEMORY: -6, + OBSOLETE_INPUT: -7, + END_OF_BLOCK: -8 +}; +var ErrorMessages = {}; +ErrorMessages[Err.LAST_BLOCK] = "Bad file checksum"; +ErrorMessages[Err.NOT_BZIP_DATA] = "Not bzip data"; +ErrorMessages[Err.UNEXPECTED_INPUT_EOF] = "Unexpected input EOF"; +ErrorMessages[Err.UNEXPECTED_OUTPUT_EOF] = "Unexpected output EOF"; +ErrorMessages[Err.DATA_ERROR] = "Data error"; +ErrorMessages[Err.OUT_OF_MEMORY] = "Out of memory"; +ErrorMessages[Err.OBSOLETE_INPUT] = "Obsolete (pre 0.9.5) bzip format not supported."; + +var _throw = function(status, optDetail) { + var msg = ErrorMessages[status] || 'unknown error'; + if (optDetail) { msg += ': '+optDetail; } + var e = new TypeError(msg); + e.errorCode = status; + throw e; +}; + +var Bunzip = function(inputStream, outputStream) { + this.writePos = this.writeCurrent = this.writeCount = 0; + + this._start_bunzip(inputStream, outputStream); +}; +Bunzip.prototype._init_block = function() { + var moreBlocks = this._get_next_block(); + if ( !moreBlocks ) { + this.writeCount = -1; + return false; /* no more blocks */ + } + this.blockCRC = new crc32$1(); + return true; +}; +/* XXX micro-bunzip uses (inputStream, inputBuffer, len) as arguments */ +Bunzip.prototype._start_bunzip = function(inputStream, outputStream) { + /* Ensure that file starts with "BZh['1'-'9']." */ + var buf = new Uint8Array(4); + if (inputStream.read(buf, 0, 4) !== 4 || + String.fromCharCode(buf[0], buf[1], buf[2]) !== 'BZh') + _throw(Err.NOT_BZIP_DATA, 'bad magic'); + + var level = buf[3] - 0x30; + if (level < 1 || level > 9) + _throw(Err.NOT_BZIP_DATA, 'level out of range'); + + this.reader = new bitreader(inputStream); + + /* Fourth byte (ascii '1'-'9'), indicates block size in units of 100k of + uncompressed data. Allocate intermediate buffer for block. */ + this.dbufSize = 100000 * level; + this.nextoutput = 0; + this.outputStream = outputStream; + this.streamCRC = 0; +}; +Bunzip.prototype._get_next_block = function() { + var i, j, k; + var reader = this.reader; + // this is get_next_block() function from micro-bunzip: + /* Read in header signature and CRC, then validate signature. + (last block signature means CRC is for whole file, return now) */ + var h = reader.pi(); + if (h === SQRTPI) { // last block + return false; /* no more blocks */ + } + if (h !== WHOLEPI) + _throw(Err.NOT_BZIP_DATA); + this.targetBlockCRC = reader.read(32) >>> 0; // (convert to unsigned) + this.streamCRC = (this.targetBlockCRC ^ + ((this.streamCRC << 1) | (this.streamCRC>>>31))) >>> 0; + /* We can add support for blockRandomised if anybody complains. There was + some code for this in busybox 1.0.0-pre3, but nobody ever noticed that + it didn't actually work. */ + if (reader.read(1)) + _throw(Err.OBSOLETE_INPUT); + var origPointer = reader.read(24); + if (origPointer > this.dbufSize) + _throw(Err.DATA_ERROR, 'initial position out of bounds'); + /* mapping table: if some byte values are never used (encoding things + like ascii text), the compression code removes the gaps to have fewer + symbols to deal with, and writes a sparse bitfield indicating which + values were present. We make a translation table to convert the symbols + back to the corresponding bytes. */ + var t = reader.read(16); + var symToByte = new Uint8Array(256), symTotal = 0; + for (i = 0; i < 16; i++) { + if (t & (1 << (0xF - i))) { + var o = i * 16; + k = reader.read(16); + for (j = 0; j < 16; j++) + if (k & (1 << (0xF - j))) + symToByte[symTotal++] = o + j; + } + } + + /* How many different huffman coding groups does this block use? */ + var groupCount = reader.read(3); + if (groupCount < MIN_GROUPS || groupCount > MAX_GROUPS) + _throw(Err.DATA_ERROR); + /* nSelectors: Every GROUP_SIZE many symbols we select a new huffman coding + group. Read in the group selector list, which is stored as MTF encoded + bit runs. (MTF=Move To Front, as each value is used it's moved to the + start of the list.) */ + var nSelectors = reader.read(15); + if (nSelectors === 0) + _throw(Err.DATA_ERROR); + + var mtfSymbol = new Uint8Array(256); + for (i = 0; i < groupCount; i++) + mtfSymbol[i] = i; + + var selectors = new Uint8Array(nSelectors); // was 32768... + + for (i = 0; i < nSelectors; i++) { + /* Get next value */ + for (j = 0; reader.read(1); j++) + if (j >= groupCount) _throw(Err.DATA_ERROR); + /* Decode MTF to get the next selector */ + selectors[i] = mtf(mtfSymbol, j); + } + + /* Read the huffman coding tables for each group, which code for symTotal + literal symbols, plus two run symbols (RUNA, RUNB) */ + var symCount = symTotal + 2; + var groups = [], hufGroup; + for (j = 0; j < groupCount; j++) { + var length = new Uint8Array(symCount), temp = new Uint16Array(MAX_HUFCODE_BITS + 1); + /* Read huffman code lengths for each symbol. They're stored in + a way similar to mtf; record a starting value for the first symbol, + and an offset from the previous value for everys symbol after that. */ + t = reader.read(5); // lengths + for (i = 0; i < symCount; i++) { + for (;;) { + if (t < 1 || t > MAX_HUFCODE_BITS) _throw(Err.DATA_ERROR); + /* If first bit is 0, stop. Else second bit indicates whether + to increment or decrement the value. */ + if(!reader.read(1)) + break; + if(!reader.read(1)) + t++; + else + t--; + } + length[i] = t; + } + + /* Find largest and smallest lengths in this group */ + var minLen, maxLen; + minLen = maxLen = length[0]; + for (i = 1; i < symCount; i++) { + if (length[i] > maxLen) + maxLen = length[i]; + else if (length[i] < minLen) + minLen = length[i]; + } + + /* Calculate permute[], base[], and limit[] tables from length[]. + * + * permute[] is the lookup table for converting huffman coded symbols + * into decoded symbols. base[] is the amount to subtract from the + * value of a huffman symbol of a given length when using permute[]. + * + * limit[] indicates the largest numerical value a symbol with a given + * number of bits can have. This is how the huffman codes can vary in + * length: each code with a value>limit[length] needs another bit. + */ + hufGroup = {}; + groups.push(hufGroup); + hufGroup.permute = new Uint16Array(MAX_SYMBOLS); + hufGroup.limit = new Uint32Array(MAX_HUFCODE_BITS + 2); + hufGroup.base = new Uint32Array(MAX_HUFCODE_BITS + 1); + hufGroup.minLen = minLen; + hufGroup.maxLen = maxLen; + /* Calculate permute[]. Concurently, initialize temp[] and limit[]. */ + var pp = 0; + for (i = minLen; i <= maxLen; i++) { + temp[i] = hufGroup.limit[i] = 0; + for (t = 0; t < symCount; t++) + if (length[t] === i) + hufGroup.permute[pp++] = t; + } + /* Count symbols coded for at each bit length */ + for (i = 0; i < symCount; i++) + temp[length[i]]++; + /* Calculate limit[] (the largest symbol-coding value at each bit + * length, which is (previous limit<<1)+symbols at this level), and + * base[] (number of symbols to ignore at each bit length, which is + * limit minus the cumulative count of symbols coded for already). */ + pp = t = 0; + for (i = minLen; i < maxLen; i++) { + pp += temp[i]; + /* We read the largest possible symbol size and then unget bits + after determining how many we need, and those extra bits could + be set to anything. (They're noise from future symbols.) At + each level we're really only interested in the first few bits, + so here we set all the trailing to-be-ignored bits to 1 so they + don't affect the value>limit[length] comparison. */ + hufGroup.limit[i] = pp - 1; + pp <<= 1; + t += temp[i]; + hufGroup.base[i + 1] = pp - t; + } + hufGroup.limit[maxLen + 1] = Number.MAX_VALUE; /* Sentinal value for reading next sym. */ + hufGroup.limit[maxLen] = pp + temp[maxLen] - 1; + hufGroup.base[minLen] = 0; + } + /* We've finished reading and digesting the block header. Now read this + block's huffman coded symbols from the file and undo the huffman coding + and run length encoding, saving the result into dbuf[dbufCount++]=uc */ + + /* Initialize symbol occurrence counters and symbol Move To Front table */ + var byteCount = new Uint32Array(256); + for (i = 0; i < 256; i++) + mtfSymbol[i] = i; + /* Loop through compressed symbols. */ + var runPos = 0, dbufCount = 0, selector = 0, uc; + var dbuf = this.dbuf = new Uint32Array(this.dbufSize); + symCount = 0; + for (;;) { + /* Determine which huffman coding group to use. */ + if (!(symCount--)) { + symCount = GROUP_SIZE - 1; + if (selector >= nSelectors) { _throw(Err.DATA_ERROR); } + hufGroup = groups[selectors[selector++]]; + } + /* Read next huffman-coded symbol. */ + i = hufGroup.minLen; + j = reader.read(i); + for (;;i++) { + if (i > hufGroup.maxLen) { _throw(Err.DATA_ERROR); } + if (j <= hufGroup.limit[i]) + break; + j = (j << 1) | reader.read(1); + } + /* Huffman decode value to get nextSym (with bounds checking) */ + j -= hufGroup.base[i]; + if (j < 0 || j >= MAX_SYMBOLS) { _throw(Err.DATA_ERROR); } + var nextSym = hufGroup.permute[j]; + /* We have now decoded the symbol, which indicates either a new literal + byte, or a repeated run of the most recent literal byte. First, + check if nextSym indicates a repeated run, and if so loop collecting + how many times to repeat the last literal. */ + if (nextSym === SYMBOL_RUNA || nextSym === SYMBOL_RUNB) { + /* If this is the start of a new run, zero out counter */ + if (!runPos){ + runPos = 1; + t = 0; + } + /* Neat trick that saves 1 symbol: instead of or-ing 0 or 1 at + each bit position, add 1 or 2 instead. For example, + 1011 is 1<<0 + 1<<1 + 2<<2. 1010 is 2<<0 + 2<<1 + 1<<2. + You can make any bit pattern that way using 1 less symbol than + the basic or 0/1 method (except all bits 0, which would use no + symbols, but a run of length 0 doesn't mean anything in this + context). Thus space is saved. */ + if (nextSym === SYMBOL_RUNA) + t += runPos; + else + t += 2 * runPos; + runPos <<= 1; + continue; + } + /* When we hit the first non-run symbol after a run, we now know + how many times to repeat the last literal, so append that many + copies to our buffer of decoded symbols (dbuf) now. (The last + literal used is the one at the head of the mtfSymbol array.) */ + if (runPos){ + runPos = 0; + if (dbufCount + t > this.dbufSize) { _throw(Err.DATA_ERROR); } + uc = symToByte[mtfSymbol[0]]; + byteCount[uc] += t; + while (t--) + dbuf[dbufCount++] = uc; + } + /* Is this the terminating symbol? */ + if (nextSym > symTotal) + break; + /* At this point, nextSym indicates a new literal character. Subtract + one to get the position in the MTF array at which this literal is + currently to be found. (Note that the result can't be -1 or 0, + because 0 and 1 are RUNA and RUNB. But another instance of the + first symbol in the mtf array, position 0, would have been handled + as part of a run above. Therefore 1 unused mtf position minus + 2 non-literal nextSym values equals -1.) */ + if (dbufCount >= this.dbufSize) { _throw(Err.DATA_ERROR); } + i = nextSym - 1; + uc = mtf(mtfSymbol, i); + uc = symToByte[uc]; + /* We have our literal byte. Save it into dbuf. */ + byteCount[uc]++; + dbuf[dbufCount++] = uc; + } + /* At this point, we've read all the huffman-coded symbols (and repeated + runs) for this block from the input stream, and decoded them into the + intermediate buffer. There are dbufCount many decoded bytes in dbuf[]. + Now undo the Burrows-Wheeler transform on dbuf. + See http://dogma.net/markn/articles/bwt/bwt.htm + */ + if (origPointer < 0 || origPointer >= dbufCount) { _throw(Err.DATA_ERROR); } + /* Turn byteCount into cumulative occurrence counts of 0 to n-1. */ + j = 0; + for (i = 0; i < 256; i++) { + k = j + byteCount[i]; + byteCount[i] = j; + j = k; + } + /* Figure out what order dbuf would be in if we sorted it. */ + for (i = 0; i < dbufCount; i++) { + uc = dbuf[i] & 0xff; + dbuf[byteCount[uc]] |= (i << 8); + byteCount[uc]++; + } + /* Decode first byte by hand to initialize "previous" byte. Note that it + doesn't get output, and if the first three characters are identical + it doesn't qualify as a run (hence writeRunCountdown=5). */ + var pos = 0, current = 0, run = 0; + if (dbufCount) { + pos = dbuf[origPointer]; + current = (pos & 0xff); + pos >>= 8; + run = -1; + } + this.writePos = pos; + this.writeCurrent = current; + this.writeCount = dbufCount; + this.writeRun = run; + + return true; /* more blocks to come */ +}; +/* Undo burrows-wheeler transform on intermediate buffer to produce output. + If start_bunzip was initialized with out_fd=-1, then up to len bytes of + data are written to outbuf. Return value is number of bytes written or + error (all errors are negative numbers). If out_fd!=-1, outbuf and len + are ignored, data is written to out_fd and return is RETVAL_OK or error. +*/ +Bunzip.prototype._read_bunzip = function(outputBuffer, len) { + var copies, previous, outbyte; + /* james@jamestaylor.org: writeCount goes to -1 when the buffer is fully + decoded, which results in this returning RETVAL_LAST_BLOCK, also + equal to -1... Confusing, I'm returning 0 here to indicate no + bytes written into the buffer */ + if (this.writeCount < 0) { return 0; } + var dbuf = this.dbuf, pos = this.writePos, current = this.writeCurrent; + var dbufCount = this.writeCount; this.outputsize; + var run = this.writeRun; + + while (dbufCount) { + dbufCount--; + previous = current; + pos = dbuf[pos]; + current = pos & 0xff; + pos >>= 8; + if (run++ === 3){ + copies = current; + outbyte = previous; + current = -1; + } else { + copies = 1; + outbyte = current; + } + this.blockCRC.updateCRCRun(outbyte, copies); + while (copies--) { + this.outputStream.writeByte(outbyte); + this.nextoutput++; + } + if (current != previous) + run = 0; + } + this.writeCount = dbufCount; + // check CRC + if (this.blockCRC.getCRC() !== this.targetBlockCRC) { + _throw(Err.DATA_ERROR, "Bad block CRC "+ + "(got "+this.blockCRC.getCRC().toString(16)+ + " expected "+this.targetBlockCRC.toString(16)+")"); + } + return this.nextoutput; +}; + +var coerceInputStream = function(input) { + if ('readByte' in input) { return input; } + var inputStream = new stream(); + inputStream.pos = 0; + inputStream.readByte = function() { return input[this.pos++]; }; + inputStream.seek = function(pos) { this.pos = pos; }; + inputStream.eof = function() { return this.pos >= input.length; }; + return inputStream; +}; +var coerceOutputStream = function(output) { + var outputStream = new stream(); + var resizeOk = true; + if (output) { + if (typeof(output)==='number') { + outputStream.buffer = new Uint8Array(output); + resizeOk = false; + } else if ('writeByte' in output) { + return output; + } else { + outputStream.buffer = output; + resizeOk = false; + } + } else { + outputStream.buffer = new Uint8Array(16384); + } + outputStream.pos = 0; + outputStream.writeByte = function(_byte) { + if (resizeOk && this.pos >= this.buffer.length) { + var newBuffer = new Uint8Array(this.buffer.length*2); + newBuffer.set(this.buffer); + this.buffer = newBuffer; + } + this.buffer[this.pos++] = _byte; + }; + outputStream.getBuffer = function() { + // trim buffer + if (this.pos !== this.buffer.length) { + if (!resizeOk) + throw new TypeError('outputsize does not match decoded input'); + var newBuffer = new Uint8Array(this.pos); + newBuffer.set(this.buffer.subarray(0, this.pos)); + this.buffer = newBuffer; + } + return this.buffer; + }; + outputStream._coerced = true; + return outputStream; +}; + +/* Static helper functions */ +// 'input' can be a stream or a buffer +// 'output' can be a stream or a buffer or a number (buffer size) +const decode$2 = function(input, output, multistream) { + // make a stream from a buffer, if necessary + var inputStream = coerceInputStream(input); + var outputStream = coerceOutputStream(output); + + var bz = new Bunzip(inputStream, outputStream); + while (true) { + if ('eof' in inputStream && inputStream.eof()) break; + if (bz._init_block()) { + bz._read_bunzip(); + } else { + var targetStreamCRC = bz.reader.read(32) >>> 0; // (convert to unsigned) + if (targetStreamCRC !== bz.streamCRC) { + _throw(Err.DATA_ERROR, "Bad stream CRC "+ + "(got "+bz.streamCRC.toString(16)+ + " expected "+targetStreamCRC.toString(16)+")"); + } + if (multistream && + 'eof' in inputStream && + !inputStream.eof()) { + // note that start_bunzip will also resync the bit reader to next byte + bz._start_bunzip(inputStream, outputStream); + } else break; + } + } + if ('getBuffer' in outputStream) + return outputStream.getBuffer(); +}; +const decodeBlock = function(input, pos, output) { + // make a stream from a buffer, if necessary + var inputStream = coerceInputStream(input); + var outputStream = coerceOutputStream(output); + var bz = new Bunzip(inputStream, outputStream); + bz.reader.seek(pos); + /* Fill the decode buffer for the block */ + var moreBlocks = bz._get_next_block(); + if (moreBlocks) { + /* Init the CRC for writing */ + bz.blockCRC = new crc32$1(); + + /* Zero this so the current byte from before the seek is not written */ + bz.writeCopies = 0; + + /* Decompress the block and write to stdout */ + bz._read_bunzip(); + // XXX keep writing? + } + if ('getBuffer' in outputStream) + return outputStream.getBuffer(); +}; +/* Reads bzip2 file from stream or buffer `input`, and invoke + * `callback(position, size)` once for each bzip2 block, + * where position gives the starting position (in *bits*) + * and size gives uncompressed size of the block (in *bytes*). */ +const table = function(input, callback, multistream) { + // make a stream from a buffer, if necessary + var inputStream = new stream(); + inputStream.delegate = coerceInputStream(input); + inputStream.pos = 0; + inputStream.readByte = function() { + this.pos++; + return this.delegate.readByte(); + }; + if (inputStream.delegate.eof) { + inputStream.eof = inputStream.delegate.eof.bind(inputStream.delegate); + } + var outputStream = new stream(); + outputStream.pos = 0; + outputStream.writeByte = function() { this.pos++; }; + + var bz = new Bunzip(inputStream, outputStream); + var blockSize = bz.dbufSize; + while (true) { + if ('eof' in inputStream && inputStream.eof()) break; + + var position = inputStream.pos*8 + bz.reader.bitOffset; + if (bz.reader.hasByte) { position -= 8; } + + if (bz._init_block()) { + var start = outputStream.pos; + bz._read_bunzip(); + callback(position, outputStream.pos - start); + } else { + bz.reader.read(32); // (but we ignore the crc) + if (multistream && + 'eof' in inputStream && + !inputStream.eof()) { + // note that start_bunzip will also resync the bit reader to next byte + bz._start_bunzip(inputStream, outputStream); + console.assert(bz.dbufSize === blockSize, + "shouldn't change block size within multistream file"); + } else break; + } + } +}; + +var lib = { + Bunzip, + Stream: stream, + Err, + decode: decode$2, + decodeBlock, + table +}; +var lib_4 = lib.decode; + +// GPG4Browsers - An OpenPGP implementation in javascript + +/** + * Implementation of the Literal Data Packet (Tag 11) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.9|RFC4880 5.9}: + * A Literal Data packet contains the body of a message; data that is not to be + * further interpreted. + */ +class LiteralDataPacket { + static get tag() { + return enums.packet.literalData; + } + + /** + * @param {Date} date - The creation date of the literal package + */ + constructor(date = new Date()) { + this.format = enums.literal.utf8; // default format for literal data packets + this.date = util.normalizeDate(date); + this.text = null; // textual data representation + this.data = null; // literal data representation + this.filename = ''; + } + + /** + * Set the packet data to a javascript native string, end of line + * will be normalized to \r\n and by default text is converted to UTF8 + * @param {String | ReadableStream} text - Any native javascript string + * @param {enums.literal} [format] - The format of the string of bytes + */ + setText(text, format = enums.literal.utf8) { + this.format = format; + this.text = text; + this.data = null; + } + + /** + * Returns literal data packets as native JavaScript string + * with normalized end of line to \n + * @param {Boolean} [clone] - Whether to return a clone so that getBytes/getText can be called again + * @returns {String | ReadableStream} Literal data as text. + */ + getText(clone = false) { + if (this.text === null || util.isStream(this.text)) { // Assume that this.text has been read + this.text = util.decodeUTF8(util.nativeEOL(this.getBytes(clone))); + } + return this.text; + } + + /** + * Set the packet data to value represented by the provided string of bytes. + * @param {Uint8Array | ReadableStream} bytes - The string of bytes + * @param {enums.literal} format - The format of the string of bytes + */ + setBytes(bytes, format) { + this.format = format; + this.data = bytes; + this.text = null; + } + + + /** + * Get the byte sequence representing the literal packet data + * @param {Boolean} [clone] - Whether to return a clone so that getBytes/getText can be called again + * @returns {Uint8Array | ReadableStream} A sequence of bytes. + */ + getBytes(clone = false) { + if (this.data === null) { + // encode UTF8 and normalize EOL to \r\n + this.data = util.canonicalizeEOL(util.encodeUTF8(this.text)); + } + if (clone) { + return passiveClone(this.data); + } + return this.data; + } + + + /** + * Sets the filename of the literal packet data + * @param {String} filename - Any native javascript string + */ + setFilename(filename) { + this.filename = filename; + } + + + /** + * Get the filename of the literal packet data + * @returns {String} Filename. + */ + getFilename() { + return this.filename; + } + + /** + * Parsing function for a literal data packet (tag 11). + * + * @param {Uint8Array | ReadableStream} input - Payload of a tag 11 packet + * @returns {Promise} Object representation. + * @async + */ + async read(bytes) { + await parse(bytes, async reader => { + // - A one-octet field that describes how the data is formatted. + const format = await reader.readByte(); // enums.literal + + const filename_len = await reader.readByte(); + this.filename = util.decodeUTF8(await reader.readBytes(filename_len)); + + this.date = util.readDate(await reader.readBytes(4)); + + let data = reader.remainder(); + if (isArrayStream(data)) data = await readToEnd(data); + this.setBytes(data, format); + }); + } + + /** + * Creates a Uint8Array representation of the packet, excluding the data + * + * @returns {Uint8Array} Uint8Array representation of the packet. + */ + writeHeader() { + const filename = util.encodeUTF8(this.filename); + const filename_length = new Uint8Array([filename.length]); + + const format = new Uint8Array([this.format]); + const date = util.writeDate(this.date); + + return util.concatUint8Array([format, filename_length, filename, date]); + } + + /** + * Creates a Uint8Array representation of the packet + * + * @returns {Uint8Array | ReadableStream} Uint8Array representation of the packet. + */ + write() { + const header = this.writeHeader(); + const data = this.getBytes(); + + return util.concat([header, data]); + } +} + +// GPG4Browsers - An OpenPGP implementation in javascript + +function readSimpleLength(bytes) { + let len = 0; + let offset; + const type = bytes[0]; + + + if (type < 192) { + [len] = bytes; + offset = 1; + } else if (type < 255) { + len = ((bytes[0] - 192) << 8) + (bytes[1]) + 192; + offset = 2; + } else if (type === 255) { + len = util.readNumber(bytes.subarray(1, 1 + 4)); + offset = 5; + } + + return { + len: len, + offset: offset + }; +} + +/** + * Encodes a given integer of length to the openpgp length specifier to a + * string + * + * @param {Integer} length - The length to encode + * @returns {Uint8Array} String with openpgp length representation. + */ +function writeSimpleLength(length) { + if (length < 192) { + return new Uint8Array([length]); + } else if (length > 191 && length < 8384) { + /* + * let a = (total data packet length) - 192 let bc = two octet + * representation of a let d = b + 192 + */ + return new Uint8Array([((length - 192) >> 8) + 192, (length - 192) & 0xFF]); + } + return util.concatUint8Array([new Uint8Array([255]), util.writeNumber(length, 4)]); +} + +function writePartialLength(power) { + if (power < 0 || power > 30) { + throw new Error('Partial Length power must be between 1 and 30'); + } + return new Uint8Array([224 + power]); +} + +function writeTag(tag_type) { + /* we're only generating v4 packet headers here */ + return new Uint8Array([0xC0 | tag_type]); +} + +/** + * Writes a packet header version 4 with the given tag_type and length to a + * string + * + * @param {Integer} tag_type - Tag type + * @param {Integer} length - Length of the payload + * @returns {String} String of the header. + */ +function writeHeader(tag_type, length) { + /* we're only generating v4 packet headers here */ + return util.concatUint8Array([writeTag(tag_type), writeSimpleLength(length)]); +} + +/** + * Whether the packet type supports partial lengths per RFC4880 + * @param {Integer} tag - Tag type + * @returns {Boolean} String of the header. + */ +function supportsStreaming(tag) { + return [ + enums.packet.literalData, + enums.packet.compressedData, + enums.packet.symmetricallyEncryptedData, + enums.packet.symEncryptedIntegrityProtectedData, + enums.packet.aeadEncryptedData + ].includes(tag); +} + +/** + * Generic static Packet Parser function + * + * @param {Uint8Array | ReadableStream} input - Input stream as string + * @param {Function} callback - Function to call with the parsed packet + * @returns {Boolean} Returns false if the stream was empty and parsing is done, and true otherwise. + */ +async function readPackets(input, callback) { + const reader = getReader(input); + let writer; + let callbackReturned; + try { + const peekedBytes = await reader.peekBytes(2); + // some sanity checks + if (!peekedBytes || peekedBytes.length < 2 || (peekedBytes[0] & 0x80) === 0) { + throw new Error('Error during parsing. This message / key probably does not conform to a valid OpenPGP format.'); + } + const headerByte = await reader.readByte(); + let tag = -1; + let format = -1; + let packetLength; + + format = 0; // 0 = old format; 1 = new format + if ((headerByte & 0x40) !== 0) { + format = 1; + } + + let packetLengthType; + if (format) { + // new format header + tag = headerByte & 0x3F; // bit 5-0 + } else { + // old format header + tag = (headerByte & 0x3F) >> 2; // bit 5-2 + packetLengthType = headerByte & 0x03; // bit 1-0 + } + + const packetSupportsStreaming = supportsStreaming(tag); + let packet = null; + if (packetSupportsStreaming) { + if (util.isStream(input) === 'array') { + const arrayStream = new ArrayStream(); + writer = getWriter(arrayStream); + packet = arrayStream; + } else { + const transform = new TransformStream(); + writer = getWriter(transform.writable); + packet = transform.readable; + } + callbackReturned = callback({ tag, packet }); + } else { + packet = []; + } + + let wasPartialLength; + do { + if (!format) { + // 4.2.1. Old Format Packet Lengths + switch (packetLengthType) { + case 0: + // The packet has a one-octet length. The header is 2 octets + // long. + packetLength = await reader.readByte(); + break; + case 1: + // The packet has a two-octet length. The header is 3 octets + // long. + packetLength = (await reader.readByte() << 8) | await reader.readByte(); + break; + case 2: + // The packet has a four-octet length. The header is 5 + // octets long. + packetLength = (await reader.readByte() << 24) | (await reader.readByte() << 16) | (await reader.readByte() << + 8) | await reader.readByte(); + break; + default: + // 3 - The packet is of indeterminate length. The header is 1 + // octet long, and the implementation must determine how long + // the packet is. If the packet is in a file, this means that + // the packet extends until the end of the file. In general, + // an implementation SHOULD NOT use indeterminate-length + // packets except where the end of the data will be clear + // from the context, and even then it is better to use a + // definite length, or a new format header. The new format + // headers described below have a mechanism for precisely + // encoding data of indeterminate length. + packetLength = Infinity; + break; + } + } else { // 4.2.2. New Format Packet Lengths + // 4.2.2.1. One-Octet Lengths + const lengthByte = await reader.readByte(); + wasPartialLength = false; + if (lengthByte < 192) { + packetLength = lengthByte; + // 4.2.2.2. Two-Octet Lengths + } else if (lengthByte >= 192 && lengthByte < 224) { + packetLength = ((lengthByte - 192) << 8) + (await reader.readByte()) + 192; + // 4.2.2.4. Partial Body Lengths + } else if (lengthByte > 223 && lengthByte < 255) { + packetLength = 1 << (lengthByte & 0x1F); + wasPartialLength = true; + if (!packetSupportsStreaming) { + throw new TypeError('This packet type does not support partial lengths.'); + } + // 4.2.2.3. Five-Octet Lengths + } else { + packetLength = (await reader.readByte() << 24) | (await reader.readByte() << 16) | (await reader.readByte() << + 8) | await reader.readByte(); + } + } + if (packetLength > 0) { + let bytesRead = 0; + while (true) { + if (writer) await writer.ready; + const { done, value } = await reader.read(); + if (done) { + if (packetLength === Infinity) break; + throw new Error('Unexpected end of packet'); + } + const chunk = packetLength === Infinity ? value : value.subarray(0, packetLength - bytesRead); + if (writer) await writer.write(chunk); + else packet.push(chunk); + bytesRead += value.length; + if (bytesRead >= packetLength) { + reader.unshift(value.subarray(packetLength - bytesRead + value.length)); + break; + } + } + } + } while (wasPartialLength); + + // If this was not a packet that "supports streaming", we peek to check + // whether it is the last packet in the message. We peek 2 bytes instead + // of 1 because the beginning of this function also peeks 2 bytes, and we + // want to cut a `subarray` of the correct length into `web-stream-tools`' + // `externalBuffer` as a tiny optimization here. + // + // If it *was* a streaming packet (i.e. the data packets), we peek at the + // entire remainder of the stream, in order to forward errors in the + // remainder of the stream to the packet data. (Note that this means we + // read/peek at all signature packets before closing the literal data + // packet, for example.) This forwards MDC errors to the literal data + // stream, for example, so that they don't get lost / forgotten on + // decryptedMessage.packets.stream, which we never look at. + // + // An example of what we do when stream-parsing a message containing + // [ one-pass signature packet, literal data packet, signature packet ]: + // 1. Read the one-pass signature packet + // 2. Peek 2 bytes of the literal data packet + // 3. Parse the one-pass signature packet + // + // 4. Read the literal data packet, simultaneously stream-parsing it + // 5. Peek until the end of the message + // 6. Finish parsing the literal data packet + // + // 7. Read the signature packet again (we already peeked at it in step 5) + // 8. Peek at the end of the stream again (`peekBytes` returns undefined) + // 9. Parse the signature packet + // + // Note that this means that if there's an error in the very end of the + // stream, such as an MDC error, we throw in step 5 instead of in step 8 + // (or never), which is the point of this exercise. + const nextPacket = await reader.peekBytes(packetSupportsStreaming ? Infinity : 2); + if (writer) { + await writer.ready; + await writer.close(); + } else { + packet = util.concatUint8Array(packet); + await callback({ tag, packet }); + } + return !nextPacket || !nextPacket.length; + } catch (e) { + if (writer) { + await writer.abort(e); + return true; + } else { + throw e; + } + } finally { + if (writer) { + await callbackReturned; + } + reader.releaseLock(); + } +} + +class UnsupportedError extends Error { + constructor(...params) { + super(...params); + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, UnsupportedError); + } + + this.name = 'UnsupportedError'; + } +} + +// GPG4Browsers - An OpenPGP implementation in javascript + +// Symbol to store cryptographic validity of the signature, to avoid recomputing multiple times on verification. +const verified = Symbol('verified'); + +// GPG puts the Issuer and Signature subpackets in the unhashed area. +// Tampering with those invalidates the signature, so we still trust them and parse them. +// All other unhashed subpackets are ignored. +const allowedUnhashedSubpackets = new Set([ + enums.signatureSubpacket.issuer, + enums.signatureSubpacket.issuerFingerprint, + enums.signatureSubpacket.embeddedSignature +]); + +/** + * Implementation of the Signature Packet (Tag 2) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.2|RFC4480 5.2}: + * A Signature packet describes a binding between some public key and + * some data. The most common signatures are a signature of a file or a + * block of text, and a signature that is a certification of a User ID. + */ +class SignaturePacket { + static get tag() { + return enums.packet.signature; + } + + constructor() { + this.version = null; + /** @type {enums.signature} */ + this.signatureType = null; + /** @type {enums.hash} */ + this.hashAlgorithm = null; + /** @type {enums.publicKey} */ + this.publicKeyAlgorithm = null; + + this.signatureData = null; + this.unhashedSubpackets = []; + this.signedHashValue = null; + + this.created = null; + this.signatureExpirationTime = null; + this.signatureNeverExpires = true; + this.exportable = null; + this.trustLevel = null; + this.trustAmount = null; + this.regularExpression = null; + this.revocable = null; + this.keyExpirationTime = null; + this.keyNeverExpires = null; + this.preferredSymmetricAlgorithms = null; + this.revocationKeyClass = null; + this.revocationKeyAlgorithm = null; + this.revocationKeyFingerprint = null; + this.issuerKeyID = new KeyID(); + this.rawNotations = []; + this.notations = {}; + this.preferredHashAlgorithms = null; + this.preferredCompressionAlgorithms = null; + this.keyServerPreferences = null; + this.preferredKeyServer = null; + this.isPrimaryUserID = null; + this.policyURI = null; + this.keyFlags = null; + this.signersUserID = null; + this.reasonForRevocationFlag = null; + this.reasonForRevocationString = null; + this.features = null; + this.signatureTargetPublicKeyAlgorithm = null; + this.signatureTargetHashAlgorithm = null; + this.signatureTargetHash = null; + this.embeddedSignature = null; + this.issuerKeyVersion = null; + this.issuerFingerprint = null; + this.preferredAEADAlgorithms = null; + + this.revoked = null; + this[verified] = null; + } + + /** + * parsing function for a signature packet (tag 2). + * @param {String} bytes - Payload of a tag 2 packet + * @returns {SignaturePacket} Object representation. + */ + read(bytes) { + let i = 0; + this.version = bytes[i++]; + + if (this.version !== 4 && this.version !== 5) { + throw new UnsupportedError(`Version ${this.version} of the signature packet is unsupported.`); + } + + this.signatureType = bytes[i++]; + this.publicKeyAlgorithm = bytes[i++]; + this.hashAlgorithm = bytes[i++]; + + // hashed subpackets + i += this.readSubPackets(bytes.subarray(i, bytes.length), true); + if (!this.created) { + throw new Error('Missing signature creation time subpacket.'); + } + + // A V4 signature hashes the packet body + // starting from its first field, the version number, through the end + // of the hashed subpacket data. Thus, the fields hashed are the + // signature version, the signature type, the public-key algorithm, the + // hash algorithm, the hashed subpacket length, and the hashed + // subpacket body. + this.signatureData = bytes.subarray(0, i); + + // unhashed subpackets + i += this.readSubPackets(bytes.subarray(i, bytes.length), false); + + // Two-octet field holding left 16 bits of signed hash value. + this.signedHashValue = bytes.subarray(i, i + 2); + i += 2; + + this.params = mod.signature.parseSignatureParams(this.publicKeyAlgorithm, bytes.subarray(i, bytes.length)); + } + + /** + * @returns {Uint8Array | ReadableStream} + */ + writeParams() { + if (this.params instanceof Promise) { + return fromAsync( + async () => mod.serializeParams(this.publicKeyAlgorithm, await this.params) + ); + } + return mod.serializeParams(this.publicKeyAlgorithm, this.params); + } + + write() { + const arr = []; + arr.push(this.signatureData); + arr.push(this.writeUnhashedSubPackets()); + arr.push(this.signedHashValue); + arr.push(this.writeParams()); + return util.concat(arr); + } + + /** + * Signs provided data. This needs to be done prior to serialization. + * @param {SecretKeyPacket} key - Private key used to sign the message. + * @param {Object} data - Contains packets to be signed. + * @param {Date} [date] - The signature creation time. + * @param {Boolean} [detached] - Whether to create a detached signature + * @throws {Error} if signing failed + * @async + */ + async sign(key, data, date = new Date(), detached = false) { + if (key.version === 5) { + this.version = 5; + } else { + this.version = 4; + } + const arr = [new Uint8Array([this.version, this.signatureType, this.publicKeyAlgorithm, this.hashAlgorithm])]; + + this.created = util.normalizeDate(date); + this.issuerKeyVersion = key.version; + this.issuerFingerprint = key.getFingerprintBytes(); + this.issuerKeyID = key.getKeyID(); + + // Add hashed subpackets + arr.push(this.writeHashedSubPackets()); + + this.signatureData = util.concat(arr); + + const toHash = this.toHash(this.signatureType, data, detached); + const hash = await this.hash(this.signatureType, data, toHash, detached); + + this.signedHashValue = slice(clone(hash), 0, 2); + const signed = async () => mod.signature.sign( + this.publicKeyAlgorithm, this.hashAlgorithm, key.publicParams, key.privateParams, toHash, await readToEnd(hash) + ); + if (util.isStream(hash)) { + this.params = signed(); + } else { + this.params = await signed(); + + // Store the fact that this signature is valid, e.g. for when we call `await + // getLatestValidSignature(this.revocationSignatures, key, data)` later. + // Note that this only holds up if the key and data passed to verify are the + // same as the ones passed to sign. + this[verified] = true; + } + } + + /** + * Creates Uint8Array of bytes of all subpacket data except Issuer and Embedded Signature subpackets + * @returns {Uint8Array} Subpacket data. + */ + writeHashedSubPackets() { + const sub = enums.signatureSubpacket; + const arr = []; + let bytes; + if (this.created === null) { + throw new Error('Missing signature creation time'); + } + arr.push(writeSubPacket(sub.signatureCreationTime, util.writeDate(this.created))); + if (this.signatureExpirationTime !== null) { + arr.push(writeSubPacket(sub.signatureExpirationTime, util.writeNumber(this.signatureExpirationTime, 4))); + } + if (this.exportable !== null) { + arr.push(writeSubPacket(sub.exportableCertification, new Uint8Array([this.exportable ? 1 : 0]))); + } + if (this.trustLevel !== null) { + bytes = new Uint8Array([this.trustLevel, this.trustAmount]); + arr.push(writeSubPacket(sub.trustSignature, bytes)); + } + if (this.regularExpression !== null) { + arr.push(writeSubPacket(sub.regularExpression, this.regularExpression)); + } + if (this.revocable !== null) { + arr.push(writeSubPacket(sub.revocable, new Uint8Array([this.revocable ? 1 : 0]))); + } + if (this.keyExpirationTime !== null) { + arr.push(writeSubPacket(sub.keyExpirationTime, util.writeNumber(this.keyExpirationTime, 4))); + } + if (this.preferredSymmetricAlgorithms !== null) { + bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredSymmetricAlgorithms)); + arr.push(writeSubPacket(sub.preferredSymmetricAlgorithms, bytes)); + } + if (this.revocationKeyClass !== null) { + bytes = new Uint8Array([this.revocationKeyClass, this.revocationKeyAlgorithm]); + bytes = util.concat([bytes, this.revocationKeyFingerprint]); + arr.push(writeSubPacket(sub.revocationKey, bytes)); + } + this.rawNotations.forEach(([{ name, value, humanReadable }]) => { + bytes = [new Uint8Array([humanReadable ? 0x80 : 0, 0, 0, 0])]; + // 2 octets of name length + bytes.push(util.writeNumber(name.length, 2)); + // 2 octets of value length + bytes.push(util.writeNumber(value.length, 2)); + bytes.push(util.stringToUint8Array(name)); + bytes.push(value); + bytes = util.concat(bytes); + arr.push(writeSubPacket(sub.notationData, bytes)); + }); + if (this.preferredHashAlgorithms !== null) { + bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredHashAlgorithms)); + arr.push(writeSubPacket(sub.preferredHashAlgorithms, bytes)); + } + if (this.preferredCompressionAlgorithms !== null) { + bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredCompressionAlgorithms)); + arr.push(writeSubPacket(sub.preferredCompressionAlgorithms, bytes)); + } + if (this.keyServerPreferences !== null) { + bytes = util.stringToUint8Array(util.uint8ArrayToString(this.keyServerPreferences)); + arr.push(writeSubPacket(sub.keyServerPreferences, bytes)); + } + if (this.preferredKeyServer !== null) { + arr.push(writeSubPacket(sub.preferredKeyServer, util.stringToUint8Array(this.preferredKeyServer))); + } + if (this.isPrimaryUserID !== null) { + arr.push(writeSubPacket(sub.primaryUserID, new Uint8Array([this.isPrimaryUserID ? 1 : 0]))); + } + if (this.policyURI !== null) { + arr.push(writeSubPacket(sub.policyURI, util.stringToUint8Array(this.policyURI))); + } + if (this.keyFlags !== null) { + bytes = util.stringToUint8Array(util.uint8ArrayToString(this.keyFlags)); + arr.push(writeSubPacket(sub.keyFlags, bytes)); + } + if (this.signersUserID !== null) { + arr.push(writeSubPacket(sub.signersUserID, util.stringToUint8Array(this.signersUserID))); + } + if (this.reasonForRevocationFlag !== null) { + bytes = util.stringToUint8Array(String.fromCharCode(this.reasonForRevocationFlag) + this.reasonForRevocationString); + arr.push(writeSubPacket(sub.reasonForRevocation, bytes)); + } + if (this.features !== null) { + bytes = util.stringToUint8Array(util.uint8ArrayToString(this.features)); + arr.push(writeSubPacket(sub.features, bytes)); + } + if (this.signatureTargetPublicKeyAlgorithm !== null) { + bytes = [new Uint8Array([this.signatureTargetPublicKeyAlgorithm, this.signatureTargetHashAlgorithm])]; + bytes.push(util.stringToUint8Array(this.signatureTargetHash)); + bytes = util.concat(bytes); + arr.push(writeSubPacket(sub.signatureTarget, bytes)); + } + if (this.preferredAEADAlgorithms !== null) { + bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredAEADAlgorithms)); + arr.push(writeSubPacket(sub.preferredAEADAlgorithms, bytes)); + } + + const result = util.concat(arr); + const length = util.writeNumber(result.length, 2); + + return util.concat([length, result]); + } + + /** + * Creates Uint8Array of bytes of Issuer and Embedded Signature subpackets + * @returns {Uint8Array} Subpacket data. + */ + writeUnhashedSubPackets() { + const sub = enums.signatureSubpacket; + const arr = []; + let bytes; + if (!this.issuerKeyID.isNull() && this.issuerKeyVersion !== 5) { + // If the version of [the] key is greater than 4, this subpacket + // MUST NOT be included in the signature. + arr.push(writeSubPacket(sub.issuer, this.issuerKeyID.write())); + } + if (this.embeddedSignature !== null) { + arr.push(writeSubPacket(sub.embeddedSignature, this.embeddedSignature.write())); + } + if (this.issuerFingerprint !== null) { + bytes = [new Uint8Array([this.issuerKeyVersion]), this.issuerFingerprint]; + bytes = util.concat(bytes); + arr.push(writeSubPacket(sub.issuerFingerprint, bytes)); + } + this.unhashedSubpackets.forEach(data => { + arr.push(writeSimpleLength(data.length)); + arr.push(data); + }); + + const result = util.concat(arr); + const length = util.writeNumber(result.length, 2); + + return util.concat([length, result]); + } + + // V4 signature sub packets + readSubPacket(bytes, hashed = true) { + let mypos = 0; + + // The leftmost bit denotes a "critical" packet + const critical = bytes[mypos] & 0x80; + const type = bytes[mypos] & 0x7F; + + if (!hashed && !allowedUnhashedSubpackets.has(type)) { + this.unhashedSubpackets.push(bytes.subarray(mypos, bytes.length)); + return; + } + + mypos++; + + // subpacket type + switch (type) { + case enums.signatureSubpacket.signatureCreationTime: + // Signature Creation Time + this.created = util.readDate(bytes.subarray(mypos, bytes.length)); + break; + case enums.signatureSubpacket.signatureExpirationTime: { + // Signature Expiration Time in seconds + const seconds = util.readNumber(bytes.subarray(mypos, bytes.length)); + + this.signatureNeverExpires = seconds === 0; + this.signatureExpirationTime = seconds; + + break; + } + case enums.signatureSubpacket.exportableCertification: + // Exportable Certification + this.exportable = bytes[mypos++] === 1; + break; + case enums.signatureSubpacket.trustSignature: + // Trust Signature + this.trustLevel = bytes[mypos++]; + this.trustAmount = bytes[mypos++]; + break; + case enums.signatureSubpacket.regularExpression: + // Regular Expression + this.regularExpression = bytes[mypos]; + break; + case enums.signatureSubpacket.revocable: + // Revocable + this.revocable = bytes[mypos++] === 1; + break; + case enums.signatureSubpacket.keyExpirationTime: { + // Key Expiration Time in seconds + const seconds = util.readNumber(bytes.subarray(mypos, bytes.length)); + + this.keyExpirationTime = seconds; + this.keyNeverExpires = seconds === 0; + + break; + } + case enums.signatureSubpacket.preferredSymmetricAlgorithms: + // Preferred Symmetric Algorithms + this.preferredSymmetricAlgorithms = [...bytes.subarray(mypos, bytes.length)]; + break; + case enums.signatureSubpacket.revocationKey: + // Revocation Key + // (1 octet of class, 1 octet of public-key algorithm ID, 20 + // octets of + // fingerprint) + this.revocationKeyClass = bytes[mypos++]; + this.revocationKeyAlgorithm = bytes[mypos++]; + this.revocationKeyFingerprint = bytes.subarray(mypos, mypos + 20); + break; + + case enums.signatureSubpacket.issuer: + // Issuer + this.issuerKeyID.read(bytes.subarray(mypos, bytes.length)); + break; + + case enums.signatureSubpacket.notationData: { + // Notation Data + const humanReadable = !!(bytes[mypos] & 0x80); + + // We extract key/value tuple from the byte stream. + mypos += 4; + const m = util.readNumber(bytes.subarray(mypos, mypos + 2)); + mypos += 2; + const n = util.readNumber(bytes.subarray(mypos, mypos + 2)); + mypos += 2; + + const name = util.uint8ArrayToString(bytes.subarray(mypos, mypos + m)); + const value = bytes.subarray(mypos + m, mypos + m + n); + + this.rawNotations.push({ name, humanReadable, value, critical }); + + if (humanReadable) { + this.notations[name] = util.uint8ArrayToString(value); + } + break; + } + case enums.signatureSubpacket.preferredHashAlgorithms: + // Preferred Hash Algorithms + this.preferredHashAlgorithms = [...bytes.subarray(mypos, bytes.length)]; + break; + case enums.signatureSubpacket.preferredCompressionAlgorithms: + // Preferred Compression Algorithms + this.preferredCompressionAlgorithms = [...bytes.subarray(mypos, bytes.length)]; + break; + case enums.signatureSubpacket.keyServerPreferences: + // Key Server Preferences + this.keyServerPreferences = [...bytes.subarray(mypos, bytes.length)]; + break; + case enums.signatureSubpacket.preferredKeyServer: + // Preferred Key Server + this.preferredKeyServer = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); + break; + case enums.signatureSubpacket.primaryUserID: + // Primary User ID + this.isPrimaryUserID = bytes[mypos++] !== 0; + break; + case enums.signatureSubpacket.policyURI: + // Policy URI + this.policyURI = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); + break; + case enums.signatureSubpacket.keyFlags: + // Key Flags + this.keyFlags = [...bytes.subarray(mypos, bytes.length)]; + break; + case enums.signatureSubpacket.signersUserID: + // Signer's User ID + this.signersUserID = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); + break; + case enums.signatureSubpacket.reasonForRevocation: + // Reason for Revocation + this.reasonForRevocationFlag = bytes[mypos++]; + this.reasonForRevocationString = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); + break; + case enums.signatureSubpacket.features: + // Features + this.features = [...bytes.subarray(mypos, bytes.length)]; + break; + case enums.signatureSubpacket.signatureTarget: { + // Signature Target + // (1 octet public-key algorithm, 1 octet hash algorithm, N octets hash) + this.signatureTargetPublicKeyAlgorithm = bytes[mypos++]; + this.signatureTargetHashAlgorithm = bytes[mypos++]; + + const len = mod.getHashByteLength(this.signatureTargetHashAlgorithm); + + this.signatureTargetHash = util.uint8ArrayToString(bytes.subarray(mypos, mypos + len)); + break; + } + case enums.signatureSubpacket.embeddedSignature: + // Embedded Signature + this.embeddedSignature = new SignaturePacket(); + this.embeddedSignature.read(bytes.subarray(mypos, bytes.length)); + break; + case enums.signatureSubpacket.issuerFingerprint: + // Issuer Fingerprint + this.issuerKeyVersion = bytes[mypos++]; + this.issuerFingerprint = bytes.subarray(mypos, bytes.length); + if (this.issuerKeyVersion === 5) { + this.issuerKeyID.read(this.issuerFingerprint); + } else { + this.issuerKeyID.read(this.issuerFingerprint.subarray(-8)); + } + break; + case enums.signatureSubpacket.preferredAEADAlgorithms: + // Preferred AEAD Algorithms + this.preferredAEADAlgorithms = [...bytes.subarray(mypos, bytes.length)]; + break; + default: { + const err = new Error(`Unknown signature subpacket type ${type}`); + if (critical) { + throw err; + } else { + util.printDebug(err); + } + } + } + } + + readSubPackets(bytes, trusted = true, config) { + // Two-octet scalar octet count for following subpacket data. + const subpacketLength = util.readNumber(bytes.subarray(0, 2)); + + let i = 2; + + // subpacket data set (zero or more subpackets) + while (i < 2 + subpacketLength) { + const len = readSimpleLength(bytes.subarray(i, bytes.length)); + i += len.offset; + + this.readSubPacket(bytes.subarray(i, i + len.len), trusted, config); + + i += len.len; + } + + return i; + } + + // Produces data to produce signature on + toSign(type, data) { + const t = enums.signature; + + switch (type) { + case t.binary: + if (data.text !== null) { + return util.encodeUTF8(data.getText(true)); + } + return data.getBytes(true); + + case t.text: { + const bytes = data.getBytes(true); + // normalize EOL to \r\n + return util.canonicalizeEOL(bytes); + } + case t.standalone: + return new Uint8Array(0); + + case t.certGeneric: + case t.certPersona: + case t.certCasual: + case t.certPositive: + case t.certRevocation: { + let packet; + let tag; + + if (data.userID) { + tag = 0xB4; + packet = data.userID; + } else if (data.userAttribute) { + tag = 0xD1; + packet = data.userAttribute; + } else { + throw new Error('Either a userID or userAttribute packet needs to be ' + + 'supplied for certification.'); + } + + const bytes = packet.write(); + + return util.concat([this.toSign(t.key, data), + new Uint8Array([tag]), + util.writeNumber(bytes.length, 4), + bytes]); + } + case t.subkeyBinding: + case t.subkeyRevocation: + case t.keyBinding: + return util.concat([this.toSign(t.key, data), this.toSign(t.key, { + key: data.bind + })]); + + case t.key: + if (data.key === undefined) { + throw new Error('Key packet is required for this signature.'); + } + return data.key.writeForHash(this.version); + + case t.keyRevocation: + return this.toSign(t.key, data); + case t.timestamp: + return new Uint8Array(0); + case t.thirdParty: + throw new Error('Not implemented'); + default: + throw new Error('Unknown signature type.'); + } + } + + calculateTrailer(data, detached) { + let length = 0; + return transform(clone(this.signatureData), value => { + length += value.length; + }, () => { + const arr = []; + if (this.version === 5 && (this.signatureType === enums.signature.binary || this.signatureType === enums.signature.text)) { + if (detached) { + arr.push(new Uint8Array(6)); + } else { + arr.push(data.writeHeader()); + } + } + arr.push(new Uint8Array([this.version, 0xFF])); + if (this.version === 5) { + arr.push(new Uint8Array(4)); + } + arr.push(util.writeNumber(length, 4)); + // For v5, this should really be writeNumber(length, 8) rather than the + // hardcoded 4 zero bytes above + return util.concat(arr); + }); + } + + toHash(signatureType, data, detached = false) { + const bytes = this.toSign(signatureType, data); + + return util.concat([bytes, this.signatureData, this.calculateTrailer(data, detached)]); + } + + async hash(signatureType, data, toHash, detached = false) { + if (!toHash) toHash = this.toHash(signatureType, data, detached); + return mod.hash.digest(this.hashAlgorithm, toHash); + } + + /** + * verifies the signature packet. Note: not all signature types are implemented + * @param {PublicSubkeyPacket|PublicKeyPacket| + * SecretSubkeyPacket|SecretKeyPacket} key - the public key to verify the signature + * @param {module:enums.signature} signatureType - Expected signature type + * @param {String|Object} data - Data which on the signature applies + * @param {Date} [date] - Use the given date instead of the current time to check for signature validity and expiration + * @param {Boolean} [detached] - Whether to verify a detached signature + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if signature validation failed + * @async + */ + async verify(key, signatureType, data, date = new Date(), detached = false, config = defaultConfig) { + if (!this.issuerKeyID.equals(key.getKeyID())) { + throw new Error('Signature was not issued by the given public key'); + } + if (this.publicKeyAlgorithm !== key.algorithm) { + throw new Error('Public key algorithm used to sign signature does not match issuer key algorithm.'); + } + + const isMessageSignature = signatureType === enums.signature.binary || signatureType === enums.signature.text; + // Cryptographic validity is cached after one successful verification. + // However, for message signatures, we always re-verify, since the passed `data` can change + const skipVerify = this.verified && !isMessageSignature; + console.log(`verify signature OUID ${Object.__oid(this)} ${this[verified]} sigtype=${signatureType}...`); + if (!skipVerify) { + let toHash; + let hash; + if (this.hashed) { + hash = await this.hashed; + } else { + toHash = this.toHash(signatureType, data, detached); + hash = await this.hash(signatureType, data, toHash); + } + hash = await readToEnd(hash); + if (this.signedHashValue[0] !== hash[0] || + this.signedHashValue[1] !== hash[1]) { + throw new Error('Signed digest did not match'); + } + + this.params = await this.params; + + this.verified = await mod.signature.verify( + this.publicKeyAlgorithm, this.hashAlgorithm, this.params, key.publicParams, + toHash, hash + ); + console.log(`verify signature OUID ${Object.__oid(this)} sigtype=${signatureType} result: ${this.verified}`); + + if (!this.verified) { + throw new Error('Signature verification failed'); + } + } + + const normDate = util.normalizeDate(date); + if (normDate && this.created > normDate) { + throw new Error('Signature creation time is in the future'); + } + if (normDate && normDate >= this.getExpirationTime()) { + throw new Error('Signature is expired'); + } + if (config.rejectHashAlgorithms.has(this.hashAlgorithm)) { + throw new Error('Insecure hash algorithm: ' + enums.read(enums.hash, this.hashAlgorithm).toUpperCase()); + } + if (config.rejectMessageHashAlgorithms.has(this.hashAlgorithm) && + [enums.signature.binary, enums.signature.text].includes(this.signatureType)) { + throw new Error('Insecure message hash algorithm: ' + enums.read(enums.hash, this.hashAlgorithm).toUpperCase()); + } + this.rawNotations.forEach(({ name, critical }) => { + if (critical && (config.knownNotations.indexOf(name) < 0)) { + throw new Error(`Unknown critical notation: ${name}`); + } + }); + if (this.revocationKeyClass !== null) { + throw new Error('This key is intended to be revoked with an authorized key, which OpenPGP.js does not support.'); + } + } + + /** + * Verifies signature expiration date + * @param {Date} [date] - Use the given date for verification instead of the current time + * @returns {Boolean} True if expired. + */ + isExpired(date = new Date()) { + const normDate = util.normalizeDate(date); + if (normDate !== null) { + return !(this.created <= normDate && normDate < this.getExpirationTime()); + } + return false; + } + + /** + * Returns the expiration time of the signature or Infinity if signature does not expire + * @returns {Date | Infinity} Expiration time. + */ + getExpirationTime() { + return this.signatureNeverExpires ? Infinity : new Date(this.created.getTime() + this.signatureExpirationTime * 1000); + } +} + +/** + * Creates a string representation of a sub signature packet + * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.1|RFC4880 5.2.3.1} + * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.2|RFC4880 5.2.3.2} + * @param {Integer} type - Subpacket signature type. + * @param {String} data - Data to be included + * @returns {String} A string-representation of a sub signature packet. + * @private + */ +function writeSubPacket(type, data) { + const arr = []; + arr.push(writeSimpleLength(data.length + 1)); + arr.push(new Uint8Array([type])); + arr.push(data); + return util.concat(arr); +} + +// GPG4Browsers - An OpenPGP implementation in javascript + +const VERSION = 3; + +/** + * Implementation of the One-Pass Signature Packets (Tag 4) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.4|RFC4880 5.4}: + * The One-Pass Signature packet precedes the signed data and contains + * enough information to allow the receiver to begin calculating any + * hashes needed to verify the signature. It allows the Signature + * packet to be placed at the end of the message, so that the signer + * can compute the entire signed message in one pass. + */ +class OnePassSignaturePacket { + static get tag() { + return enums.packet.onePassSignature; + } + + constructor() { + /** A one-octet version number. The current version is 3. */ + this.version = null; + /** + * A one-octet signature type. + * Signature types are described in + * {@link https://tools.ietf.org/html/rfc4880#section-5.2.1|RFC4880 Section 5.2.1}. + * @type {enums.signature} + + */ + this.signatureType = null; + /** + * A one-octet number describing the hash algorithm used. + * @see {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC4880 9.4} + * @type {enums.hash} + */ + this.hashAlgorithm = null; + /** + * A one-octet number describing the public-key algorithm used. + * @see {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC4880 9.1} + * @type {enums.publicKey} + */ + this.publicKeyAlgorithm = null; + /** An eight-octet number holding the Key ID of the signing key. */ + this.issuerKeyID = null; + /** + * A one-octet number holding a flag showing whether the signature is nested. + * A zero value indicates that the next packet is another One-Pass Signature packet + * that describes another signature to be applied to the same message data. + */ + this.flags = null; + } + + /** + * parsing function for a one-pass signature packet (tag 4). + * @param {Uint8Array} bytes - Payload of a tag 4 packet + * @returns {OnePassSignaturePacket} Object representation. + */ + read(bytes) { + let mypos = 0; + // A one-octet version number. The current version is 3. + this.version = bytes[mypos++]; + if (this.version !== VERSION) { + throw new UnsupportedError(`Version ${this.version} of the one-pass signature packet is unsupported.`); + } + + // A one-octet signature type. Signature types are described in + // Section 5.2.1. + this.signatureType = bytes[mypos++]; + + // A one-octet number describing the hash algorithm used. + this.hashAlgorithm = bytes[mypos++]; + + // A one-octet number describing the public-key algorithm used. + this.publicKeyAlgorithm = bytes[mypos++]; + + // An eight-octet number holding the Key ID of the signing key. + this.issuerKeyID = new KeyID(); + this.issuerKeyID.read(bytes.subarray(mypos, mypos + 8)); + mypos += 8; + + // A one-octet number holding a flag showing whether the signature + // is nested. A zero value indicates that the next packet is + // another One-Pass Signature packet that describes another + // signature to be applied to the same message data. + this.flags = bytes[mypos++]; + return this; + } + + /** + * creates a string representation of a one-pass signature packet + * @returns {Uint8Array} A Uint8Array representation of a one-pass signature packet. + */ + write() { + const start = new Uint8Array([VERSION, this.signatureType, this.hashAlgorithm, this.publicKeyAlgorithm]); + + const end = new Uint8Array([this.flags]); + + return util.concatUint8Array([start, this.issuerKeyID.write(), end]); + } + + calculateTrailer(...args) { + return fromAsync(async () => SignaturePacket.prototype.calculateTrailer.apply(await this.correspondingSig, args)); + } + + async verify() { + const correspondingSig = await this.correspondingSig; + if (!correspondingSig || correspondingSig.constructor.tag !== enums.packet.signature) { + throw new Error('Corresponding signature packet missing'); + } + if ( + correspondingSig.signatureType !== this.signatureType || + correspondingSig.hashAlgorithm !== this.hashAlgorithm || + correspondingSig.publicKeyAlgorithm !== this.publicKeyAlgorithm || + !correspondingSig.issuerKeyID.equals(this.issuerKeyID) + ) { + throw new Error('Corresponding signature packet does not match one-pass signature packet'); + } + correspondingSig.hashed = this.hashed; + return correspondingSig.verify.apply(correspondingSig, arguments); + } +} + +OnePassSignaturePacket.prototype.hash = SignaturePacket.prototype.hash; +OnePassSignaturePacket.prototype.toHash = SignaturePacket.prototype.toHash; +OnePassSignaturePacket.prototype.toSign = SignaturePacket.prototype.toSign; + +/** + * Instantiate a new packet given its tag + * @function newPacketFromTag + * @param {module:enums.packet} tag - Property value from {@link module:enums.packet} + * @param {Object} allowedPackets - mapping where keys are allowed packet tags, pointing to their Packet class + * @returns {Object} New packet object with type based on tag + * @throws {Error|UnsupportedError} for disallowed or unknown packets + */ +function newPacketFromTag(tag, allowedPackets) { + if (!allowedPackets[tag]) { + // distinguish between disallowed packets and unknown ones + let packetType; + try { + packetType = enums.read(enums.packet, tag); + } catch (e) { + throw new UnsupportedError(`Unknown packet type with tag: ${tag}`); + } + throw new Error(`Packet not allowed in this context: ${packetType}`); + } + return new allowedPackets[tag](); +} + +/** + * This class represents a list of openpgp packets. + * Take care when iterating over it - the packets themselves + * are stored as numerical indices. + * @extends Array + */ +class PacketList extends Array { + /** + * Parses the given binary data and returns a list of packets. + * Equivalent to calling `read` on an empty PacketList instance. + * @param {Uint8Array | ReadableStream} bytes - binary data to parse + * @param {Object} allowedPackets - mapping where keys are allowed packet tags, pointing to their Packet class + * @param {Object} [config] - full configuration, defaults to openpgp.config + * @returns {PacketList} parsed list of packets + * @throws on parsing errors + * @async + */ + static async fromBinary(bytes, allowedPackets, config = defaultConfig) { + const packets = new PacketList(); + await packets.read(bytes, allowedPackets, config); + return packets; + } + + /** + * Reads a stream of binary data and interprets it as a list of packets. + * @param {Uint8Array | ReadableStream} bytes - binary data to parse + * @param {Object} allowedPackets - mapping where keys are allowed packet tags, pointing to their Packet class + * @param {Object} [config] - full configuration, defaults to openpgp.config + * @throws on parsing errors + * @async + */ + async read(bytes, allowedPackets, config = defaultConfig) { + this.stream = transformPair(bytes, async (readable, writable) => { + const writer = getWriter(writable); + try { + while (true) { + await writer.ready; + const done = await readPackets(readable, async parsed => { + try { + if (parsed.tag === enums.packet.marker || parsed.tag === enums.packet.trust) { + // According to the spec, these packet types should be ignored and not cause parsing errors, even if not esplicitly allowed: + // - Marker packets MUST be ignored when received: https://github.com/openpgpjs/openpgpjs/issues/1145 + // - Trust packets SHOULD be ignored outside of keyrings (unsupported): https://datatracker.ietf.org/doc/html/rfc4880#section-5.10 + return; + } + const packet = newPacketFromTag(parsed.tag, allowedPackets); + packet.packets = new PacketList(); + packet.fromStream = util.isStream(parsed.packet); + await packet.read(parsed.packet, config); + await writer.write(packet); + } catch (e) { + const throwUnsupportedError = !config.ignoreUnsupportedPackets && e instanceof UnsupportedError; + const throwMalformedError = !config.ignoreMalformedPackets && !(e instanceof UnsupportedError); + if (throwUnsupportedError || throwMalformedError || supportsStreaming(parsed.tag)) { + // The packets that support streaming are the ones that contain message data. + // Those are also the ones we want to be more strict about and throw on parse errors + // (since we likely cannot process the message without these packets anyway). + await writer.abort(e); + } + util.printDebugError(e); + } + }); + if (done) { + await writer.ready; + await writer.close(); + return; + } + } + } catch (e) { + await writer.abort(e); + } + }); + + // Wait until first few packets have been read + const reader = getReader(this.stream); + while (true) { + const { done, value } = await reader.read(); + if (!done) { + this.push(value); + } else { + this.stream = null; + } + if (done || supportsStreaming(value.constructor.tag)) { + break; + } + } + reader.releaseLock(); + } + + /** + * Creates a binary representation of openpgp objects contained within the + * class instance. + * @returns {Uint8Array} A Uint8Array containing valid openpgp packets. + */ + write() { + const arr = []; + + for (let i = 0; i < this.length; i++) { + const packetbytes = this[i].write(); + if (util.isStream(packetbytes) && supportsStreaming(this[i].constructor.tag)) { + let buffer = []; + let bufferLength = 0; + const minLength = 512; + arr.push(writeTag(this[i].constructor.tag)); + arr.push(transform(packetbytes, value => { + buffer.push(value); + bufferLength += value.length; + if (bufferLength >= minLength) { + const powerOf2 = Math.min(Math.log(bufferLength) / Math.LN2 | 0, 30); + const chunkSize = 2 ** powerOf2; + const bufferConcat = util.concat([writePartialLength(powerOf2)].concat(buffer)); + buffer = [bufferConcat.subarray(1 + chunkSize)]; + bufferLength = buffer[0].length; + return bufferConcat.subarray(0, 1 + chunkSize); + } + }, () => util.concat([writeSimpleLength(bufferLength)].concat(buffer)))); + } else { + if (util.isStream(packetbytes)) { + let length = 0; + arr.push(transform(clone(packetbytes), value => { + length += value.length; + }, () => writeHeader(this[i].constructor.tag, length))); + } else { + arr.push(writeHeader(this[i].constructor.tag, packetbytes.length)); + } + arr.push(packetbytes); + } + } + + return util.concat(arr); + } + + /** + * Creates a new PacketList with all packets matching the given tag(s) + * @param {...module:enums.packet} tags - packet tags to look for + * @returns {PacketList} + */ + filterByTag(...tags) { + const filtered = new PacketList(); + + const handle = tag => packetType => tag === packetType; + + for (let i = 0; i < this.length; i++) { + if (tags.some(handle(this[i].constructor.tag))) { + filtered.push(this[i]); + } + } + + return filtered; + } + + /** + * Traverses packet list and returns first packet with matching tag + * @param {module:enums.packet} tag - The packet tag + * @returns {Packet|undefined} + */ + findPacket(tag) { + return this.find(packet => packet.constructor.tag === tag); + } + + /** + * Find indices of packets with the given tag(s) + * @param {...module:enums.packet} tags - packet tags to look for + * @returns {Integer[]} packet indices + */ + indexOfTag(...tags) { + const tagIndex = []; + const that = this; + + const handle = tag => packetType => tag === packetType; + + for (let i = 0; i < this.length; i++) { + if (tags.some(handle(that[i].constructor.tag))) { + tagIndex.push(i); + } + } + return tagIndex; + } +} + +// GPG4Browsers - An OpenPGP implementation in javascript + +// A Compressed Data packet can contain the following packet types +const allowedPackets = /*#__PURE__*/ util.constructAllowedPackets([ + LiteralDataPacket, + OnePassSignaturePacket, + SignaturePacket +]); + +/** + * Implementation of the Compressed Data Packet (Tag 8) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.6|RFC4880 5.6}: + * The Compressed Data packet contains compressed data. Typically, + * this packet is found as the contents of an encrypted packet, or following + * a Signature or One-Pass Signature packet, and contains a literal data packet. + */ +class CompressedDataPacket { + static get tag() { + return enums.packet.compressedData; + } + + /** + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + constructor(config = defaultConfig) { + /** + * List of packets + * @type {PacketList} + */ + this.packets = null; + /** + * Compression algorithm + * @type {enums.compression} + */ + this.algorithm = config.preferredCompressionAlgorithm; + + /** + * Compressed packet data + * @type {Uint8Array | ReadableStream} + */ + this.compressed = null; + + /** + * zip/zlib compression level, between 1 and 9 + */ + this.deflateLevel = config.deflateLevel; + } + + /** + * Parsing function for the packet. + * @param {Uint8Array | ReadableStream} bytes - Payload of a tag 8 packet + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + async read(bytes, config = defaultConfig) { + await parse(bytes, async reader => { + + // One octet that gives the algorithm used to compress the packet. + this.algorithm = await reader.readByte(); + + // Compressed data, which makes up the remainder of the packet. + this.compressed = reader.remainder(); + + await this.decompress(config); + }); + } + + + /** + * Return the compressed packet. + * @returns {Uint8Array | ReadableStream} Binary compressed packet. + */ + write() { + if (this.compressed === null) { + this.compress(); + } + + return util.concat([new Uint8Array([this.algorithm]), this.compressed]); + } + + + /** + * Decompression method for decompressing the compressed data + * read by read_packet + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + async decompress(config = defaultConfig) { + const compressionName = enums.read(enums.compression, this.algorithm); + const decompressionFn = decompress_fns[compressionName]; + if (!decompressionFn) { + throw new Error(`${compressionName} decompression not supported`); + } + + this.packets = await PacketList.fromBinary(decompressionFn(this.compressed), allowedPackets, config); + } + + /** + * Compress the packet data (member decompressedData) + */ + compress() { + const compressionName = enums.read(enums.compression, this.algorithm); + const compressionFn = compress_fns[compressionName]; + if (!compressionFn) { + throw new Error(`${compressionName} compression not supported`); + } + + this.compressed = compressionFn(this.packets.write(), this.deflateLevel); + } +} + +////////////////////////// +// // +// Helper functions // +// // +////////////////////////// + + +const nodeZlib = util.getNodeZlib(); + +function uncompressed(data) { + return data; +} + +function node_zlib(func, create, options = {}) { + return function (data) { + if (!util.isStream(data) || isArrayStream(data)) { + return fromAsync(() => readToEnd(data).then(data => { + return new Promise((resolve, reject) => { + func(data, options, (err, result) => { + if (err) return reject(err); + resolve(result); + }); + }); + })); + } + return nodeToWeb(webToNode(data).pipe(create(options))); + }; +} + +function pako_zlib(constructor, options = {}) { + return function(data) { + const obj = new constructor(options); + return transform(data, value => { + if (value.length) { + obj.push(value, Z_SYNC_FLUSH); + return obj.result; + } + }, () => { + if (constructor === Deflate) { + obj.push([], Z_FINISH); + return obj.result; + } + }); + }; +} + +function bzip2(func) { + return function(data) { + return fromAsync(async () => func(await readToEnd(data))); + }; +} + +const compress_fns = nodeZlib ? { + zip: /*#__PURE__*/ (compressed, level) => node_zlib(nodeZlib.deflateRaw, nodeZlib.createDeflateRaw, { level })(compressed), + zlib: /*#__PURE__*/ (compressed, level) => node_zlib(nodeZlib.deflate, nodeZlib.createDeflate, { level })(compressed) +} : { + zip: /*#__PURE__*/ (compressed, level) => pako_zlib(Deflate, { raw: true, level })(compressed), + zlib: /*#__PURE__*/ (compressed, level) => pako_zlib(Deflate, { level })(compressed) +}; + +const decompress_fns = nodeZlib ? { + uncompressed: uncompressed, + zip: /*#__PURE__*/ node_zlib(nodeZlib.inflateRaw, nodeZlib.createInflateRaw), + zlib: /*#__PURE__*/ node_zlib(nodeZlib.inflate, nodeZlib.createInflate), + bzip2: /*#__PURE__*/ bzip2(lib_4) +} : { + uncompressed: uncompressed, + zip: /*#__PURE__*/ pako_zlib(Inflate, { raw: true }), + zlib: /*#__PURE__*/ pako_zlib(Inflate), + bzip2: /*#__PURE__*/ bzip2(lib_4) +}; + +// GPG4Browsers - An OpenPGP implementation in javascript + +// A SEIP packet can contain the following packet types +const allowedPackets$1 = /*#__PURE__*/ util.constructAllowedPackets([ + LiteralDataPacket, + CompressedDataPacket, + OnePassSignaturePacket, + SignaturePacket +]); + +const VERSION$1 = 1; // A one-octet version number of the data packet. + +/** + * Implementation of the Sym. Encrypted Integrity Protected Data Packet (Tag 18) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.13|RFC4880 5.13}: + * The Symmetrically Encrypted Integrity Protected Data packet is + * a variant of the Symmetrically Encrypted Data packet. It is a new feature + * created for OpenPGP that addresses the problem of detecting a modification to + * encrypted data. It is used in combination with a Modification Detection Code + * packet. + */ +class SymEncryptedIntegrityProtectedDataPacket { + static get tag() { + return enums.packet.symEncryptedIntegrityProtectedData; + } + + constructor() { + this.version = VERSION$1; + this.encrypted = null; + this.packets = null; + } + + async read(bytes) { + await parse(bytes, async reader => { + const version = await reader.readByte(); + // - A one-octet version number. The only currently defined value is 1. + if (version !== VERSION$1) { + throw new UnsupportedError(`Version ${version} of the SEIP packet is unsupported.`); + } + + // - Encrypted data, the output of the selected symmetric-key cipher + // operating in Cipher Feedback mode with shift amount equal to the + // block size of the cipher (CFB-n where n is the block size). + this.encrypted = reader.remainder(); + }); + } + + write() { + return util.concat([new Uint8Array([VERSION$1]), this.encrypted]); + } + + /** + * Encrypt the payload in the packet. + * @param {enums.symmetric} sessionKeyAlgorithm - The symmetric encryption algorithm to use + * @param {Uint8Array} key - The key of cipher blocksize length to be used + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} + * @throws {Error} on encryption failure + * @async + */ + async encrypt(sessionKeyAlgorithm, key, config = defaultConfig) { + const { blockSize } = mod.getCipher(sessionKeyAlgorithm); + + let bytes = this.packets.write(); + if (isArrayStream(bytes)) bytes = await readToEnd(bytes); + const prefix = await mod.getPrefixRandom(sessionKeyAlgorithm); + const mdc = new Uint8Array([0xD3, 0x14]); // modification detection code packet + + const tohash = util.concat([prefix, bytes, mdc]); + const hash = await mod.hash.sha1(passiveClone(tohash)); + const plaintext = util.concat([tohash, hash]); + + this.encrypted = await mod.mode.cfb.encrypt(sessionKeyAlgorithm, key, plaintext, new Uint8Array(blockSize), config); + return true; + } + + /** + * Decrypts the encrypted data contained in the packet. + * @param {enums.symmetric} sessionKeyAlgorithm - The selected symmetric encryption algorithm to be used + * @param {Uint8Array} key - The key of cipher blocksize length to be used + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} + * @throws {Error} on decryption failure + * @async + */ + async decrypt(sessionKeyAlgorithm, key, config = defaultConfig) { + const { blockSize } = mod.getCipher(sessionKeyAlgorithm); + let encrypted = clone(this.encrypted); + if (isArrayStream(encrypted)) encrypted = await readToEnd(encrypted); + const decrypted = await mod.mode.cfb.decrypt(sessionKeyAlgorithm, key, encrypted, new Uint8Array(blockSize)); + + // there must be a modification detection code packet as the + // last packet and everything gets hashed except the hash itself + const realHash = slice(passiveClone(decrypted), -20); + const tohash = slice(decrypted, 0, -20); + const verifyHash = Promise.all([ + readToEnd(await mod.hash.sha1(passiveClone(tohash))), + readToEnd(realHash) + ]).then(([hash, mdc]) => { + if (!util.equalsUint8Array(hash, mdc)) { + throw new Error('Modification detected.'); + } + return new Uint8Array(); + }); + const bytes = slice(tohash, blockSize + 2); // Remove random prefix + let packetbytes = slice(bytes, 0, -2); // Remove MDC packet + packetbytes = concat([packetbytes, fromAsync(() => verifyHash)]); + if (!util.isStream(encrypted) || !config.allowUnauthenticatedStream) { + packetbytes = await readToEnd(packetbytes); + } + this.packets = await PacketList.fromBinary(packetbytes, allowedPackets$1, config); + return true; + } +} + +// OpenPGP.js - An OpenPGP implementation in javascript + +// An AEAD-encrypted Data packet can contain the following packet types +const allowedPackets$2 = /*#__PURE__*/ util.constructAllowedPackets([ + LiteralDataPacket, + CompressedDataPacket, + OnePassSignaturePacket, + SignaturePacket +]); + +const VERSION$2 = 1; // A one-octet version number of the data packet. + +/** + * Implementation of the Symmetrically Encrypted Authenticated Encryption with + * Additional Data (AEAD) Protected Data Packet + * + * {@link https://tools.ietf.org/html/draft-ford-openpgp-format-00#section-2.1}: + * AEAD Protected Data Packet + */ +class AEADEncryptedDataPacket { + static get tag() { + return enums.packet.aeadEncryptedData; + } + + constructor() { + this.version = VERSION$2; + /** @type {enums.symmetric} */ + this.cipherAlgorithm = null; + /** @type {enums.aead} */ + this.aeadAlgorithm = enums.aead.eax; + this.chunkSizeByte = null; + this.iv = null; + this.encrypted = null; + this.packets = null; + } + + /** + * Parse an encrypted payload of bytes in the order: version, IV, ciphertext (see specification) + * @param {Uint8Array | ReadableStream} bytes + * @throws {Error} on parsing failure + */ + async read(bytes) { + await parse(bytes, async reader => { + const version = await reader.readByte(); + if (version !== VERSION$2) { // The only currently defined value is 1. + throw new UnsupportedError(`Version ${version} of the AEAD-encrypted data packet is not supported.`); + } + this.cipherAlgorithm = await reader.readByte(); + this.aeadAlgorithm = await reader.readByte(); + this.chunkSizeByte = await reader.readByte(); + + const mode = mod.getAEADMode(this.aeadAlgorithm); + this.iv = await reader.readBytes(mode.ivLength); + this.encrypted = reader.remainder(); + }); + } + + /** + * Write the encrypted payload of bytes in the order: version, IV, ciphertext (see specification) + * @returns {Uint8Array | ReadableStream} The encrypted payload. + */ + write() { + return util.concat([new Uint8Array([this.version, this.cipherAlgorithm, this.aeadAlgorithm, this.chunkSizeByte]), this.iv, this.encrypted]); + } + + /** + * Decrypt the encrypted payload. + * @param {enums.symmetric} sessionKeyAlgorithm - The session key's cipher algorithm + * @param {Uint8Array} key - The session key used to encrypt the payload + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if decryption was not successful + * @async + */ + async decrypt(sessionKeyAlgorithm, key, config = defaultConfig) { + this.packets = await PacketList.fromBinary( + await this.crypt('decrypt', key, clone(this.encrypted)), + allowedPackets$2, + config + ); + } + + /** + * Encrypt the packet payload. + * @param {enums.symmetric} sessionKeyAlgorithm - The session key's cipher algorithm + * @param {Uint8Array} key - The session key used to encrypt the payload + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if encryption was not successful + * @async + */ + async encrypt(sessionKeyAlgorithm, key, config = defaultConfig) { + this.cipherAlgorithm = sessionKeyAlgorithm; + + const { ivLength } = mod.getAEADMode(this.aeadAlgorithm); + this.iv = await mod.random.getRandomBytes(ivLength); // generate new random IV + this.chunkSizeByte = config.aeadChunkSizeByte; + const data = this.packets.write(); + this.encrypted = await this.crypt('encrypt', key, data); + } + + /** + * En/decrypt the payload. + * @param {encrypt|decrypt} fn - Whether to encrypt or decrypt + * @param {Uint8Array} key - The session key used to en/decrypt the payload + * @param {Uint8Array | ReadableStream} data - The data to en/decrypt + * @returns {Promise>} + * @async + */ + async crypt(fn, key, data) { + const mode = mod.getAEADMode(this.aeadAlgorithm); + const modeInstance = await mode(this.cipherAlgorithm, key); + const tagLengthIfDecrypting = fn === 'decrypt' ? mode.tagLength : 0; + const tagLengthIfEncrypting = fn === 'encrypt' ? mode.tagLength : 0; + const chunkSize = 2 ** (this.chunkSizeByte + 6) + tagLengthIfDecrypting; // ((uint64_t)1 << (c + 6)) + const adataBuffer = new ArrayBuffer(21); + const adataArray = new Uint8Array(adataBuffer, 0, 13); + const adataTagArray = new Uint8Array(adataBuffer); + const adataView = new DataView(adataBuffer); + const chunkIndexArray = new Uint8Array(adataBuffer, 5, 8); + adataArray.set([0xC0 | AEADEncryptedDataPacket.tag, this.version, this.cipherAlgorithm, this.aeadAlgorithm, this.chunkSizeByte], 0); + let chunkIndex = 0; + let latestPromise = Promise.resolve(); + let cryptedBytes = 0; + let queuedBytes = 0; + const iv = this.iv; + return transformPair(data, async (readable, writable) => { + if (util.isStream(readable) !== 'array') { + const buffer = new TransformStream({}, { + highWaterMark: util.getHardwareConcurrency() * 2 ** (this.chunkSizeByte + 6), + size: array => array.length + }); + pipe(buffer.readable, writable); + writable = buffer.writable; + } + const reader = getReader(readable); + const writer = getWriter(writable); + try { + while (true) { + let chunk = await reader.readBytes(chunkSize + tagLengthIfDecrypting) || new Uint8Array(); + const finalChunk = chunk.subarray(chunk.length - tagLengthIfDecrypting); + chunk = chunk.subarray(0, chunk.length - tagLengthIfDecrypting); + let cryptedPromise; + let done; + if (!chunkIndex || chunk.length) { + reader.unshift(finalChunk); + cryptedPromise = modeInstance[fn](chunk, mode.getNonce(iv, chunkIndexArray), adataArray); + queuedBytes += chunk.length - tagLengthIfDecrypting + tagLengthIfEncrypting; + } else { + // After the last chunk, we either encrypt a final, empty + // data chunk to get the final authentication tag or + // validate that final authentication tag. + adataView.setInt32(13 + 4, cryptedBytes); // Should be setInt64(13, ...) + cryptedPromise = modeInstance[fn](finalChunk, mode.getNonce(iv, chunkIndexArray), adataTagArray); + queuedBytes += tagLengthIfEncrypting; + done = true; + } + cryptedBytes += chunk.length - tagLengthIfDecrypting; + // eslint-disable-next-line no-loop-func + latestPromise = latestPromise.then(() => cryptedPromise).then(async crypted => { + await writer.ready; + await writer.write(crypted); + queuedBytes -= crypted.length; + }).catch(err => writer.abort(err)); + if (done || queuedBytes > writer.desiredSize) { + await latestPromise; // Respect backpressure + } + if (!done) { + adataView.setInt32(5 + 4, ++chunkIndex); // Should be setInt64(5, ...) + } else { + await writer.close(); + break; + } + } + } catch (e) { + await writer.abort(e); + } + }); + } +} + +// GPG4Browsers - An OpenPGP implementation in javascript + +const VERSION$3 = 3; + +/** + * Public-Key Encrypted Session Key Packets (Tag 1) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.1|RFC4880 5.1}: + * A Public-Key Encrypted Session Key packet holds the session key + * used to encrypt a message. Zero or more Public-Key Encrypted Session Key + * packets and/or Symmetric-Key Encrypted Session Key packets may precede a + * Symmetrically Encrypted Data Packet, which holds an encrypted message. The + * message is encrypted with the session key, and the session key is itself + * encrypted and stored in the Encrypted Session Key packet(s). The + * Symmetrically Encrypted Data Packet is preceded by one Public-Key Encrypted + * Session Key packet for each OpenPGP key to which the message is encrypted. + * The recipient of the message finds a session key that is encrypted to their + * public key, decrypts the session key, and then uses the session key to + * decrypt the message. + */ +class PublicKeyEncryptedSessionKeyPacket { + static get tag() { + return enums.packet.publicKeyEncryptedSessionKey; + } + + constructor() { + this.version = 3; + + this.publicKeyID = new KeyID(); + this.publicKeyAlgorithm = null; + + this.sessionKey = null; + /** + * Algorithm to encrypt the message with + * @type {enums.symmetric} + */ + this.sessionKeyAlgorithm = null; + + /** @type {Object} */ + this.encrypted = {}; + } + + /** + * Parsing function for a publickey encrypted session key packet (tag 1). + * + * @param {Uint8Array} bytes - Payload of a tag 1 packet + */ + read(bytes) { + this.version = bytes[0]; + if (this.version !== VERSION$3) { + throw new UnsupportedError(`Version ${this.version} of the PKESK packet is unsupported.`); + } + this.publicKeyID.read(bytes.subarray(1, bytes.length)); + this.publicKeyAlgorithm = bytes[9]; + this.encrypted = mod.parseEncSessionKeyParams(this.publicKeyAlgorithm, bytes.subarray(10)); + } + + /** + * Create a binary representation of a tag 1 packet + * + * @returns {Uint8Array} The Uint8Array representation. + */ + write() { + const arr = [ + new Uint8Array([this.version]), + this.publicKeyID.write(), + new Uint8Array([this.publicKeyAlgorithm]), + mod.serializeParams(this.publicKeyAlgorithm, this.encrypted) + ]; + + return util.concatUint8Array(arr); + } + + /** + * Encrypt session key packet + * @param {PublicKeyPacket} key - Public key + * @throws {Error} if encryption failed + * @async + */ + async encrypt(key) { + const data = util.concatUint8Array([ + new Uint8Array([enums.write(enums.symmetric, this.sessionKeyAlgorithm)]), + this.sessionKey, + util.writeChecksum(this.sessionKey) + ]); + const algo = enums.write(enums.publicKey, this.publicKeyAlgorithm); + this.encrypted = await mod.publicKeyEncrypt( + algo, key.publicParams, data, key.getFingerprintBytes()); + } + + /** + * Decrypts the session key (only for public key encrypted session key packets (tag 1) + * @param {SecretKeyPacket} key - decrypted private key + * @param {Object} [randomSessionKey] - Bogus session key to use in case of sensitive decryption error, or if the decrypted session key is of a different type/size. + * This is needed for constant-time processing. Expected object of the form: { sessionKey: Uint8Array, sessionKeyAlgorithm: enums.symmetric } + * @throws {Error} if decryption failed, unless `randomSessionKey` is given + * @async + */ + async decrypt(key, randomSessionKey) { + // check that session key algo matches the secret key algo + if (this.publicKeyAlgorithm !== key.algorithm) { + throw new Error('Decryption error'); + } + + const randomPayload = randomSessionKey ? util.concatUint8Array([ + new Uint8Array([randomSessionKey.sessionKeyAlgorithm]), + randomSessionKey.sessionKey, + util.writeChecksum(randomSessionKey.sessionKey) + ]) : null; + const decoded = await mod.publicKeyDecrypt(this.publicKeyAlgorithm, key.publicParams, key.privateParams, this.encrypted, key.getFingerprintBytes(), randomPayload); + const symmetricAlgoByte = decoded[0]; + const sessionKey = decoded.subarray(1, decoded.length - 2); + const checksum = decoded.subarray(decoded.length - 2); + const computedChecksum = util.writeChecksum(sessionKey); + const isValidChecksum = computedChecksum[0] === checksum[0] & computedChecksum[1] === checksum[1]; + + if (randomSessionKey) { + // We must not leak info about the validity of the decrypted checksum or cipher algo. + // The decrypted session key must be of the same algo and size as the random session key, otherwise we discard it and use the random data. + const isValidPayload = isValidChecksum & symmetricAlgoByte === randomSessionKey.sessionKeyAlgorithm & sessionKey.length === randomSessionKey.sessionKey.length; + this.sessionKeyAlgorithm = util.selectUint8(isValidPayload, symmetricAlgoByte, randomSessionKey.sessionKeyAlgorithm); + this.sessionKey = util.selectUint8Array(isValidPayload, sessionKey, randomSessionKey.sessionKey); + + } else { + const isValidPayload = isValidChecksum && enums.read(enums.symmetric, symmetricAlgoByte); + if (isValidPayload) { + this.sessionKey = sessionKey; + this.sessionKeyAlgorithm = symmetricAlgoByte; + } else { + throw new Error('Decryption error'); + } + } + } +} + +// GPG4Browsers - An OpenPGP implementation in javascript + +class S2K { + /** + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + constructor(config = defaultConfig) { + /** + * Hash function identifier, or 0 for gnu-dummy keys + * @type {module:enums.hash | 0} + */ + this.algorithm = enums.hash.sha256; + /** + * enums.s2k identifier or 'gnu-dummy' + * @type {String} + */ + this.type = 'iterated'; + /** @type {Integer} */ + this.c = config.s2kIterationCountByte; + /** Eight bytes of salt in a binary string. + * @type {Uint8Array} + */ + this.salt = null; + } + + getCount() { + // Exponent bias, defined in RFC4880 + const expbias = 6; + + return (16 + (this.c & 15)) << ((this.c >> 4) + expbias); + } + + /** + * Parsing function for a string-to-key specifier ({@link https://tools.ietf.org/html/rfc4880#section-3.7|RFC 4880 3.7}). + * @param {Uint8Array} bytes - Payload of string-to-key specifier + * @returns {Integer} Actual length of the object. + */ + read(bytes) { + let i = 0; + this.type = enums.read(enums.s2k, bytes[i++]); + this.algorithm = bytes[i++]; + + switch (this.type) { + case 'simple': + break; + + case 'salted': + this.salt = bytes.subarray(i, i + 8); + i += 8; + break; + + case 'iterated': + this.salt = bytes.subarray(i, i + 8); + i += 8; + + // Octet 10: count, a one-octet, coded value + this.c = bytes[i++]; + break; + + case 'gnu': + if (util.uint8ArrayToString(bytes.subarray(i, i + 3)) === 'GNU') { + i += 3; // GNU + const gnuExtType = 1000 + bytes[i++]; + if (gnuExtType === 1001) { + this.type = 'gnu-dummy'; + // GnuPG extension mode 1001 -- don't write secret key at all + } else { + throw new Error('Unknown s2k gnu protection mode.'); + } + } else { + throw new Error('Unknown s2k type.'); + } + break; + + default: + throw new Error('Unknown s2k type.'); + } + + return i; + } + + /** + * Serializes s2k information + * @returns {Uint8Array} Binary representation of s2k. + */ + write() { + if (this.type === 'gnu-dummy') { + return new Uint8Array([101, 0, ...util.stringToUint8Array('GNU'), 1]); + } + const arr = [new Uint8Array([enums.write(enums.s2k, this.type), this.algorithm])]; + + switch (this.type) { + case 'simple': + break; + case 'salted': + arr.push(this.salt); + break; + case 'iterated': + arr.push(this.salt); + arr.push(new Uint8Array([this.c])); + break; + case 'gnu': + throw new Error('GNU s2k type not supported.'); + default: + throw new Error('Unknown s2k type.'); + } + + return util.concatUint8Array(arr); + } + + /** + * Produces a key using the specified passphrase and the defined + * hashAlgorithm + * @param {String} passphrase - Passphrase containing user input + * @returns {Promise} Produced key with a length corresponding to. + * hashAlgorithm hash length + * @async + */ + async produceKey(passphrase, numBytes) { + passphrase = util.encodeUTF8(passphrase); + + const arr = []; + let rlength = 0; + + let prefixlen = 0; + while (rlength < numBytes) { + let toHash; + switch (this.type) { + case 'simple': + toHash = util.concatUint8Array([new Uint8Array(prefixlen), passphrase]); + break; + case 'salted': + toHash = util.concatUint8Array([new Uint8Array(prefixlen), this.salt, passphrase]); + break; + case 'iterated': { + const data = util.concatUint8Array([this.salt, passphrase]); + let datalen = data.length; + const count = Math.max(this.getCount(), datalen); + toHash = new Uint8Array(prefixlen + count); + toHash.set(data, prefixlen); + for (let pos = prefixlen + datalen; pos < count; pos += datalen, datalen *= 2) { + toHash.copyWithin(pos, prefixlen, pos); + } + break; + } + case 'gnu': + throw new Error('GNU s2k type not supported.'); + default: + throw new Error('Unknown s2k type.'); + } + const result = await mod.hash.digest(this.algorithm, toHash); + arr.push(result); + rlength += result.length; + prefixlen++; + } + + return util.concatUint8Array(arr).subarray(0, numBytes); + } +} + +// GPG4Browsers - An OpenPGP implementation in javascript + +/** + * Symmetric-Key Encrypted Session Key Packets (Tag 3) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.3|RFC4880 5.3}: + * The Symmetric-Key Encrypted Session Key packet holds the + * symmetric-key encryption of a session key used to encrypt a message. + * Zero or more Public-Key Encrypted Session Key packets and/or + * Symmetric-Key Encrypted Session Key packets may precede a + * Symmetrically Encrypted Data packet that holds an encrypted message. + * The message is encrypted with a session key, and the session key is + * itself encrypted and stored in the Encrypted Session Key packet or + * the Symmetric-Key Encrypted Session Key packet. + */ +class SymEncryptedSessionKeyPacket { + static get tag() { + return enums.packet.symEncryptedSessionKey; + } + + /** + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + constructor(config = defaultConfig) { + this.version = config.aeadProtect ? 5 : 4; + this.sessionKey = null; + /** + * Algorithm to encrypt the session key with + * @type {enums.symmetric} + */ + this.sessionKeyEncryptionAlgorithm = null; + /** + * Algorithm to encrypt the message with + * @type {enums.symmetric} + */ + this.sessionKeyAlgorithm = enums.symmetric.aes256; + /** + * AEAD mode to encrypt the session key with (if AEAD protection is enabled) + * @type {enums.aead} + */ + this.aeadAlgorithm = enums.write(enums.aead, config.preferredAEADAlgorithm); + this.encrypted = null; + this.s2k = null; + this.iv = null; + } + + /** + * Parsing function for a symmetric encrypted session key packet (tag 3). + * + * @param {Uint8Array} bytes - Payload of a tag 3 packet + */ + read(bytes) { + let offset = 0; + + // A one-octet version number. The only currently defined version is 4. + this.version = bytes[offset++]; + if (this.version !== 4 && this.version !== 5) { + throw new UnsupportedError(`Version ${this.version} of the SKESK packet is unsupported.`); + } + + // A one-octet number describing the symmetric algorithm used. + const algo = bytes[offset++]; + + if (this.version === 5) { + // A one-octet AEAD algorithm. + this.aeadAlgorithm = bytes[offset++]; + } + + // A string-to-key (S2K) specifier, length as defined above. + this.s2k = new S2K(); + offset += this.s2k.read(bytes.subarray(offset, bytes.length)); + + if (this.version === 5) { + const mode = mod.getAEADMode(this.aeadAlgorithm); + + // A starting initialization vector of size specified by the AEAD + // algorithm. + this.iv = bytes.subarray(offset, offset += mode.ivLength); + } + + // The encrypted session key itself, which is decrypted with the + // string-to-key object. This is optional in version 4. + if (this.version === 5 || offset < bytes.length) { + this.encrypted = bytes.subarray(offset, bytes.length); + this.sessionKeyEncryptionAlgorithm = algo; + } else { + this.sessionKeyAlgorithm = algo; + } + } + + /** + * Create a binary representation of a tag 3 packet + * + * @returns {Uint8Array} The Uint8Array representation. + */ + write() { + const algo = this.encrypted === null ? + this.sessionKeyAlgorithm : + this.sessionKeyEncryptionAlgorithm; + + let bytes; + + if (this.version === 5) { + bytes = util.concatUint8Array([new Uint8Array([this.version, algo, this.aeadAlgorithm]), this.s2k.write(), this.iv, this.encrypted]); + } else { + bytes = util.concatUint8Array([new Uint8Array([this.version, algo]), this.s2k.write()]); + + if (this.encrypted !== null) { + bytes = util.concatUint8Array([bytes, this.encrypted]); + } + } + + return bytes; + } + + /** + * Decrypts the session key with the given passphrase + * @param {String} passphrase - The passphrase in string form + * @throws {Error} if decryption was not successful + * @async + */ + async decrypt(passphrase) { + const algo = this.sessionKeyEncryptionAlgorithm !== null ? + this.sessionKeyEncryptionAlgorithm : + this.sessionKeyAlgorithm; + + const { blockSize, keySize } = mod.getCipher(algo); + const key = await this.s2k.produceKey(passphrase, keySize); + + if (this.version === 5) { + const mode = mod.getAEADMode(this.aeadAlgorithm); + const adata = new Uint8Array([0xC0 | SymEncryptedSessionKeyPacket.tag, this.version, this.sessionKeyEncryptionAlgorithm, this.aeadAlgorithm]); + const modeInstance = await mode(algo, key); + this.sessionKey = await modeInstance.decrypt(this.encrypted, this.iv, adata); + } else if (this.encrypted !== null) { + const decrypted = await mod.mode.cfb.decrypt(algo, key, this.encrypted, new Uint8Array(blockSize)); + + this.sessionKeyAlgorithm = enums.write(enums.symmetric, decrypted[0]); + this.sessionKey = decrypted.subarray(1, decrypted.length); + } else { + this.sessionKey = key; + } + } + + /** + * Encrypts the session key with the given passphrase + * @param {String} passphrase - The passphrase in string form + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if encryption was not successful + * @async + */ + async encrypt(passphrase, config = defaultConfig) { + const algo = this.sessionKeyEncryptionAlgorithm !== null ? + this.sessionKeyEncryptionAlgorithm : + this.sessionKeyAlgorithm; + + this.sessionKeyEncryptionAlgorithm = algo; + + this.s2k = new S2K(config); + this.s2k.salt = await mod.random.getRandomBytes(8); + + const { blockSize, keySize } = mod.getCipher(algo); + const encryptionKey = await this.s2k.produceKey(passphrase, keySize); + + if (this.sessionKey === null) { + this.sessionKey = await mod.generateSessionKey(this.sessionKeyAlgorithm); + } + + if (this.version === 5) { + const mode = mod.getAEADMode(this.aeadAlgorithm); + this.iv = await mod.random.getRandomBytes(mode.ivLength); // generate new random IV + const associatedData = new Uint8Array([0xC0 | SymEncryptedSessionKeyPacket.tag, this.version, this.sessionKeyEncryptionAlgorithm, this.aeadAlgorithm]); + const modeInstance = await mode(algo, encryptionKey); + this.encrypted = await modeInstance.encrypt(this.sessionKey, this.iv, associatedData); + } else { + const toEncrypt = util.concatUint8Array([ + new Uint8Array([this.sessionKeyAlgorithm]), + this.sessionKey + ]); + this.encrypted = await mod.mode.cfb.encrypt(algo, encryptionKey, toEncrypt, new Uint8Array(blockSize), config); + } + } +} + +// GPG4Browsers - An OpenPGP implementation in javascript + +/** + * Implementation of the Key Material Packet (Tag 5,6,7,14) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.5|RFC4480 5.5}: + * A key material packet contains all the information about a public or + * private key. There are four variants of this packet type, and two + * major versions. + * + * A Public-Key packet starts a series of packets that forms an OpenPGP + * key (sometimes called an OpenPGP certificate). + */ +class PublicKeyPacket { + static get tag() { + return enums.packet.publicKey; + } + + /** + * @param {Date} [date] - Creation date + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + constructor(date = new Date(), config = defaultConfig) { + /** + * Packet version + * @type {Integer} + */ + this.version = config.v5Keys ? 5 : 4; + /** + * Key creation date. + * @type {Date} + */ + this.created = util.normalizeDate(date); + /** + * Public key algorithm. + * @type {enums.publicKey} + */ + this.algorithm = null; + /** + * Algorithm specific public params + * @type {Object} + */ + this.publicParams = null; + /** + * Time until expiration in days (V3 only) + * @type {Integer} + */ + this.expirationTimeV3 = 0; + /** + * Fingerprint bytes + * @type {Uint8Array} + */ + this.fingerprint = null; + /** + * KeyID + * @type {module:type/keyid~KeyID} + */ + this.keyID = null; + } + + /** + * Create a PublicKeyPacket from a SecretKeyPacket + * @param {SecretKeyPacket} secretKeyPacket - key packet to convert + * @returns {PublicKeyPacket} public key packet + * @static + */ + static fromSecretKeyPacket(secretKeyPacket) { + const keyPacket = new PublicKeyPacket(); + const { version, created, algorithm, publicParams, keyID, fingerprint } = secretKeyPacket; + keyPacket.version = version; + keyPacket.created = created; + keyPacket.algorithm = algorithm; + keyPacket.publicParams = publicParams; + keyPacket.keyID = keyID; + keyPacket.fingerprint = fingerprint; + return keyPacket; + } + + /** + * Internal Parser for public keys as specified in {@link https://tools.ietf.org/html/rfc4880#section-5.5.2|RFC 4880 section 5.5.2 Public-Key Packet Formats} + * @param {Uint8Array} bytes - Input array to read the packet from + * @returns {Object} This object with attributes set by the parser + * @async + */ + async read(bytes) { + let pos = 0; + // A one-octet version number (3, 4 or 5). + this.version = bytes[pos++]; + + if (this.version === 4 || this.version === 5) { + // - A four-octet number denoting the time that the key was created. + this.created = util.readDate(bytes.subarray(pos, pos + 4)); + pos += 4; + + // - A one-octet number denoting the public-key algorithm of this key. + this.algorithm = bytes[pos++]; + + if (this.version === 5) { + // - A four-octet scalar octet count for the following key material. + pos += 4; + } + + // - A series of values comprising the key material. + try { + const { read, publicParams } = mod.parsePublicKeyParams(this.algorithm, bytes.subarray(pos)); + this.publicParams = publicParams; + pos += read; + } catch (err) { + throw new Error('Error reading MPIs'); + } + + // we set the fingerprint and keyID already to make it possible to put together the key packets directly in the Key constructor + await this.computeFingerprintAndKeyID(); + return pos; + } + throw new UnsupportedError(`Version ${this.version} of the key packet is unsupported.`); + } + + /** + * Creates an OpenPGP public key packet for the given key. + * @returns {Uint8Array} Bytes encoding the public key OpenPGP packet. + */ + write() { + const arr = []; + // Version + arr.push(new Uint8Array([this.version])); + arr.push(util.writeDate(this.created)); + // A one-octet number denoting the public-key algorithm of this key + arr.push(new Uint8Array([this.algorithm])); + + const params = mod.serializeParams(this.algorithm, this.publicParams); + if (this.version === 5) { + // A four-octet scalar octet count for the following key material + arr.push(util.writeNumber(params.length, 4)); + } + // Algorithm-specific params + arr.push(params); + return util.concatUint8Array(arr); + } + + /** + * Write packet in order to be hashed; either for a signature or a fingerprint + * @param {Integer} version - target version of signature or key + */ + writeForHash(version) { + const bytes = this.writePublicKey(); + + if (version === 5) { + return util.concatUint8Array([new Uint8Array([0x9A]), util.writeNumber(bytes.length, 4), bytes]); + } + return util.concatUint8Array([new Uint8Array([0x99]), util.writeNumber(bytes.length, 2), bytes]); + } + + /** + * Check whether secret-key data is available in decrypted form. Returns null for public keys. + * @returns {Boolean|null} + */ + isDecrypted() { + return null; + } + + /** + * Returns the creation time of the key + * @returns {Date} + */ + getCreationTime() { + return this.created; + } + + /** + * Return the key ID of the key + * @returns {module:type/keyid~KeyID} The 8-byte key ID + */ + getKeyID() { + return this.keyID; + } + + /** + * Computes and set the key ID and fingerprint of the key + * @async + */ + async computeFingerprintAndKeyID() { + await this.computeFingerprint(); + this.keyID = new KeyID(); + + if (this.version === 5) { + this.keyID.read(this.fingerprint.subarray(0, 8)); + } else if (this.version === 4) { + this.keyID.read(this.fingerprint.subarray(12, 20)); + } else { + throw new Error('Unsupported key version'); + } + } + + /** + * Computes and set the fingerprint of the key + */ + async computeFingerprint() { + const toHash = this.writeForHash(this.version); + + if (this.version === 5) { + this.fingerprint = await mod.hash.sha256(toHash); + } else if (this.version === 4) { + this.fingerprint = await mod.hash.sha1(toHash); + } else { + throw new Error('Unsupported key version'); + } + } + + /** + * Returns the fingerprint of the key, as an array of bytes + * @returns {Uint8Array} A Uint8Array containing the fingerprint + */ + getFingerprintBytes() { + return this.fingerprint; + } + + /** + * Calculates and returns the fingerprint of the key, as a string + * @returns {String} A string containing the fingerprint in lowercase hex + */ + getFingerprint() { + return util.uint8ArrayToHex(this.getFingerprintBytes()); + } + + /** + * Calculates whether two keys have the same fingerprint without actually calculating the fingerprint + * @returns {Boolean} Whether the two keys have the same version and public key data. + */ + hasSameFingerprintAs(other) { + return this.version === other.version && util.equalsUint8Array(this.writePublicKey(), other.writePublicKey()); + } + + /** + * Returns algorithm information + * @returns {Object} An object of the form {algorithm: String, bits:int, curve:String}. + */ + getAlgorithmInfo() { + const result = {}; + result.algorithm = enums.read(enums.publicKey, this.algorithm); + // RSA, DSA or ElGamal public modulo + const modulo = this.publicParams.n || this.publicParams.p; + if (modulo) { + result.bits = util.uint8ArrayBitLength(modulo); + } else { + result.curve = this.publicParams.oid.getName(); + } + return result; + } +} + +/** + * Alias of read() + * @see PublicKeyPacket#read + */ +PublicKeyPacket.prototype.readPublicKey = PublicKeyPacket.prototype.read; + +/** + * Alias of write() + * @see PublicKeyPacket#write + */ +PublicKeyPacket.prototype.writePublicKey = PublicKeyPacket.prototype.write; + +// GPG4Browsers - An OpenPGP implementation in javascript + +// A SE packet can contain the following packet types +const allowedPackets$3 = /*#__PURE__*/ util.constructAllowedPackets([ + LiteralDataPacket, + CompressedDataPacket, + OnePassSignaturePacket, + SignaturePacket +]); + +/** + * Implementation of the Symmetrically Encrypted Data Packet (Tag 9) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.7|RFC4880 5.7}: + * The Symmetrically Encrypted Data packet contains data encrypted with a + * symmetric-key algorithm. When it has been decrypted, it contains other + * packets (usually a literal data packet or compressed data packet, but in + * theory other Symmetrically Encrypted Data packets or sequences of packets + * that form whole OpenPGP messages). + */ +class SymmetricallyEncryptedDataPacket { + static get tag() { + return enums.packet.symmetricallyEncryptedData; + } + + constructor() { + /** + * Encrypted secret-key data + */ + this.encrypted = null; + /** + * Decrypted packets contained within. + * @type {PacketList} + */ + this.packets = null; + } + + read(bytes) { + this.encrypted = bytes; + } + + write() { + return this.encrypted; + } + + /** + * Decrypt the symmetrically-encrypted packet data + * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. + * @param {module:enums.symmetric} sessionKeyAlgorithm - Symmetric key algorithm to use + * @param {Uint8Array} key - The key of cipher blocksize length to be used + * @param {Object} [config] - Full configuration, defaults to openpgp.config + + * @throws {Error} if decryption was not successful + * @async + */ + async decrypt(sessionKeyAlgorithm, key, config = defaultConfig) { + // If MDC errors are not being ignored, all missing MDC packets in symmetrically encrypted data should throw an error + if (!config.allowUnauthenticatedMessages) { + throw new Error('Message is not authenticated.'); + } + + const { blockSize } = mod.getCipher(sessionKeyAlgorithm); + const encrypted = await readToEnd(clone(this.encrypted)); + const decrypted = await mod.mode.cfb.decrypt(sessionKeyAlgorithm, key, + encrypted.subarray(blockSize + 2), + encrypted.subarray(2, blockSize + 2) + ); + + this.packets = await PacketList.fromBinary(decrypted, allowedPackets$3, config); + } + + /** + * Encrypt the symmetrically-encrypted packet data + * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. + * @param {module:enums.symmetric} sessionKeyAlgorithm - Symmetric key algorithm to use + * @param {Uint8Array} key - The key of cipher blocksize length to be used + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if encryption was not successful + * @async + */ + async encrypt(sessionKeyAlgorithm, key, config = defaultConfig) { + const data = this.packets.write(); + const { blockSize } = mod.getCipher(sessionKeyAlgorithm); + + const prefix = await mod.getPrefixRandom(sessionKeyAlgorithm); + const FRE = await mod.mode.cfb.encrypt(sessionKeyAlgorithm, key, prefix, new Uint8Array(blockSize), config); + const ciphertext = await mod.mode.cfb.encrypt(sessionKeyAlgorithm, key, data, FRE.subarray(2), config); + this.encrypted = util.concat([FRE, ciphertext]); + } +} + +// GPG4Browsers - An OpenPGP implementation in javascript + +/** + * Implementation of the strange "Marker packet" (Tag 10) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.8|RFC4880 5.8}: + * An experimental version of PGP used this packet as the Literal + * packet, but no released version of PGP generated Literal packets with this + * tag. With PGP 5.x, this packet has been reassigned and is reserved for use as + * the Marker packet. + * + * The body of this packet consists of: + * The three octets 0x50, 0x47, 0x50 (which spell "PGP" in UTF-8). + * + * Such a packet MUST be ignored when received. It may be placed at the + * beginning of a message that uses features not available in PGP + * version 2.6 in order to cause that version to report that newer + * software is necessary to process the message. + */ +class MarkerPacket { + static get tag() { + return enums.packet.marker; + } + + /** + * Parsing function for a marker data packet (tag 10). + * @param {Uint8Array} bytes - Payload of a tag 10 packet + * @returns {Boolean} whether the packet payload contains "PGP" + */ + read(bytes) { + if (bytes[0] === 0x50 && // P + bytes[1] === 0x47 && // G + bytes[2] === 0x50) { // P + return true; + } + return false; + } + + write() { + return new Uint8Array([0x50, 0x47, 0x50]); + } +} + +// GPG4Browsers - An OpenPGP implementation in javascript + +/** + * A Public-Subkey packet (tag 14) has exactly the same format as a + * Public-Key packet, but denotes a subkey. One or more subkeys may be + * associated with a top-level key. By convention, the top-level key + * provides signature services, and the subkeys provide encryption + * services. + * @extends PublicKeyPacket + */ +class PublicSubkeyPacket extends PublicKeyPacket { + static get tag() { + return enums.packet.publicSubkey; + } + + /** + * @param {Date} [date] - Creation date + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + // eslint-disable-next-line no-useless-constructor + constructor(date, config) { + super(date, config); + } + + /** + * Create a PublicSubkeyPacket from a SecretSubkeyPacket + * @param {SecretSubkeyPacket} secretSubkeyPacket - subkey packet to convert + * @returns {SecretSubkeyPacket} public key packet + * @static + */ + static fromSecretSubkeyPacket(secretSubkeyPacket) { + const keyPacket = new PublicSubkeyPacket(); + const { version, created, algorithm, publicParams, keyID, fingerprint } = secretSubkeyPacket; + keyPacket.version = version; + keyPacket.created = created; + keyPacket.algorithm = algorithm; + keyPacket.publicParams = publicParams; + keyPacket.keyID = keyID; + keyPacket.fingerprint = fingerprint; + return keyPacket; + } +} + +// GPG4Browsers - An OpenPGP implementation in javascript + +/** + * Implementation of the User Attribute Packet (Tag 17) + * + * The User Attribute packet is a variation of the User ID packet. It + * is capable of storing more types of data than the User ID packet, + * which is limited to text. Like the User ID packet, a User Attribute + * packet may be certified by the key owner ("self-signed") or any other + * key owner who cares to certify it. Except as noted, a User Attribute + * packet may be used anywhere that a User ID packet may be used. + * + * While User Attribute packets are not a required part of the OpenPGP + * standard, implementations SHOULD provide at least enough + * compatibility to properly handle a certification signature on the + * User Attribute packet. A simple way to do this is by treating the + * User Attribute packet as a User ID packet with opaque contents, but + * an implementation may use any method desired. + */ +class UserAttributePacket { + static get tag() { + return enums.packet.userAttribute; + } + + constructor() { + this.attributes = []; + } + + /** + * parsing function for a user attribute packet (tag 17). + * @param {Uint8Array} input - Payload of a tag 17 packet + */ + read(bytes) { + let i = 0; + while (i < bytes.length) { + const len = readSimpleLength(bytes.subarray(i, bytes.length)); + i += len.offset; + + this.attributes.push(util.uint8ArrayToString(bytes.subarray(i, i + len.len))); + i += len.len; + } + } + + /** + * Creates a binary representation of the user attribute packet + * @returns {Uint8Array} String representation. + */ + write() { + const arr = []; + for (let i = 0; i < this.attributes.length; i++) { + arr.push(writeSimpleLength(this.attributes[i].length)); + arr.push(util.stringToUint8Array(this.attributes[i])); + } + return util.concatUint8Array(arr); + } + + /** + * Compare for equality + * @param {UserAttributePacket} usrAttr + * @returns {Boolean} True if equal. + */ + equals(usrAttr) { + if (!usrAttr || !(usrAttr instanceof UserAttributePacket)) { + return false; + } + return this.attributes.every(function(attr, index) { + return attr === usrAttr.attributes[index]; + }); + } +} + +// GPG4Browsers - An OpenPGP implementation in javascript + +/** + * A Secret-Key packet contains all the information that is found in a + * Public-Key packet, including the public-key material, but also + * includes the secret-key material after all the public-key fields. + * @extends PublicKeyPacket + */ +class SecretKeyPacket extends PublicKeyPacket { + static get tag() { + return enums.packet.secretKey; + } + + /** + * @param {Date} [date] - Creation date + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + constructor(date = new Date(), config = defaultConfig) { + super(date, config); + /** + * Secret-key data + */ + this.keyMaterial = null; + /** + * Indicates whether secret-key data is encrypted. `this.isEncrypted === false` means data is available in decrypted form. + */ + this.isEncrypted = null; + /** + * S2K usage + * @type {enums.symmetric} + */ + this.s2kUsage = 0; + /** + * S2K object + * @type {type/s2k} + */ + this.s2k = null; + /** + * Symmetric algorithm to encrypt the key with + * @type {enums.symmetric} + */ + this.symmetric = null; + /** + * AEAD algorithm to encrypt the key with (if AEAD protection is enabled) + * @type {enums.aead} + */ + this.aead = null; + /** + * Decrypted private parameters, referenced by name + * @type {Object} + */ + this.privateParams = null; + } + + // 5.5.3. Secret-Key Packet Formats + + /** + * Internal parser for private keys as specified in + * {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.5.3|RFC4880bis-04 section 5.5.3} + * @param {Uint8Array} bytes - Input string to read the packet from + * @async + */ + async read(bytes) { + // - A Public-Key or Public-Subkey packet, as described above. + let i = await this.readPublicKey(bytes); + + // - One octet indicating string-to-key usage conventions. Zero + // indicates that the secret-key data is not encrypted. 255 or 254 + // indicates that a string-to-key specifier is being given. Any + // other value is a symmetric-key encryption algorithm identifier. + this.s2kUsage = bytes[i++]; + + // - Only for a version 5 packet, a one-octet scalar octet count of + // the next 4 optional fields. + if (this.version === 5) { + i++; + } + + // - [Optional] If string-to-key usage octet was 255, 254, or 253, a + // one-octet symmetric encryption algorithm. + if (this.s2kUsage === 255 || this.s2kUsage === 254 || this.s2kUsage === 253) { + this.symmetric = bytes[i++]; + + // - [Optional] If string-to-key usage octet was 253, a one-octet + // AEAD algorithm. + if (this.s2kUsage === 253) { + this.aead = bytes[i++]; + } + + // - [Optional] If string-to-key usage octet was 255, 254, or 253, a + // string-to-key specifier. The length of the string-to-key + // specifier is implied by its type, as described above. + this.s2k = new S2K(); + i += this.s2k.read(bytes.subarray(i, bytes.length)); + + if (this.s2k.type === 'gnu-dummy') { + return; + } + } else if (this.s2kUsage) { + this.symmetric = this.s2kUsage; + } + + // - [Optional] If secret data is encrypted (string-to-key usage octet + // not zero), an Initial Vector (IV) of the same length as the + // cipher's block size. + if (this.s2kUsage) { + this.iv = bytes.subarray( + i, + i + mod.getCipher(this.symmetric).blockSize + ); + + i += this.iv.length; + } + + // - Only for a version 5 packet, a four-octet scalar octet count for + // the following key material. + if (this.version === 5) { + i += 4; + } + + // - Plain or encrypted multiprecision integers comprising the secret + // key data. These algorithm-specific fields are as described + // below. + this.keyMaterial = bytes.subarray(i); + this.isEncrypted = !!this.s2kUsage; + + if (!this.isEncrypted) { + const cleartext = this.keyMaterial.subarray(0, -2); + if (!util.equalsUint8Array(util.writeChecksum(cleartext), this.keyMaterial.subarray(-2))) { + throw new Error('Key checksum mismatch'); + } + try { + const { privateParams } = mod.parsePrivateKeyParams(this.algorithm, cleartext, this.publicParams); + this.privateParams = privateParams; + } catch (err) { + throw new Error('Error reading MPIs'); + } + } + } + + /** + * Creates an OpenPGP key packet for the given key. + * @returns {Uint8Array} A string of bytes containing the secret key OpenPGP packet. + */ + write() { + const arr = [this.writePublicKey()]; + + arr.push(new Uint8Array([this.s2kUsage])); + + const optionalFieldsArr = []; + // - [Optional] If string-to-key usage octet was 255, 254, or 253, a + // one- octet symmetric encryption algorithm. + if (this.s2kUsage === 255 || this.s2kUsage === 254 || this.s2kUsage === 253) { + optionalFieldsArr.push(this.symmetric); + + // - [Optional] If string-to-key usage octet was 253, a one-octet + // AEAD algorithm. + if (this.s2kUsage === 253) { + optionalFieldsArr.push(this.aead); + } + + // - [Optional] If string-to-key usage octet was 255, 254, or 253, a + // string-to-key specifier. The length of the string-to-key + // specifier is implied by its type, as described above. + optionalFieldsArr.push(...this.s2k.write()); + } + + // - [Optional] If secret data is encrypted (string-to-key usage octet + // not zero), an Initial Vector (IV) of the same length as the + // cipher's block size. + if (this.s2kUsage && this.s2k.type !== 'gnu-dummy') { + optionalFieldsArr.push(...this.iv); + } + + if (this.version === 5) { + arr.push(new Uint8Array([optionalFieldsArr.length])); + } + arr.push(new Uint8Array(optionalFieldsArr)); + + if (!this.isDummy()) { + if (!this.s2kUsage) { + this.keyMaterial = mod.serializeParams(this.algorithm, this.privateParams); + } + + if (this.version === 5) { + arr.push(util.writeNumber(this.keyMaterial.length, 4)); + } + arr.push(this.keyMaterial); + + if (!this.s2kUsage) { + arr.push(util.writeChecksum(this.keyMaterial)); + } + } + + return util.concatUint8Array(arr); + } + + /** + * Check whether secret-key data is available in decrypted form. + * Returns false for gnu-dummy keys and null for public keys. + * @returns {Boolean|null} + */ + isDecrypted() { + return this.isEncrypted === false; + } + + /** + * Check whether this is a gnu-dummy key + * @returns {Boolean} + */ + isDummy() { + return !!(this.s2k && this.s2k.type === 'gnu-dummy'); + } + + /** + * Remove private key material, converting the key to a dummy one. + * The resulting key cannot be used for signing/decrypting but can still verify signatures. + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + makeDummy(config = defaultConfig) { + if (this.isDummy()) { + return; + } + if (this.isDecrypted()) { + this.clearPrivateParams(); + } + this.isEncrypted = null; + this.keyMaterial = null; + this.s2k = new S2K(config); + this.s2k.algorithm = 0; + this.s2k.c = 0; + this.s2k.type = 'gnu-dummy'; + this.s2kUsage = 254; + this.symmetric = enums.symmetric.aes256; + } + + /** + * Encrypt the payload. By default, we use aes256 and iterated, salted string + * to key specifier. If the key is in a decrypted state (isEncrypted === false) + * and the passphrase is empty or undefined, the key will be set as not encrypted. + * This can be used to remove passphrase protection after calling decrypt(). + * @param {String} passphrase + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if encryption was not successful + * @async + */ + async encrypt(passphrase, config = defaultConfig) { + if (this.isDummy()) { + return; + } + + if (!this.isDecrypted()) { + throw new Error('Key packet is already encrypted'); + } + + if (this.isDecrypted() && !passphrase) { + this.s2kUsage = 0; + return; + } else if (!passphrase) { + throw new Error('The key must be decrypted before removing passphrase protection.'); + } + + this.s2k = new S2K(config); + this.s2k.salt = await mod.random.getRandomBytes(8); + const cleartext = mod.serializeParams(this.algorithm, this.privateParams); + this.symmetric = enums.symmetric.aes256; + const key = await produceEncryptionKey(this.s2k, passphrase, this.symmetric); + + const { blockSize } = mod.getCipher(this.symmetric); + this.iv = await mod.random.getRandomBytes(blockSize); + + if (config.aeadProtect) { + this.s2kUsage = 253; + this.aead = enums.aead.eax; + const mode = mod.getAEADMode(this.aead); + const modeInstance = await mode(this.symmetric, key); + this.keyMaterial = await modeInstance.encrypt(cleartext, this.iv.subarray(0, mode.ivLength), new Uint8Array()); + } else { + this.s2kUsage = 254; + this.keyMaterial = await mod.mode.cfb.encrypt(this.symmetric, key, util.concatUint8Array([ + cleartext, + await mod.hash.sha1(cleartext, config) + ]), this.iv, config); + } + } + + /** + * Decrypts the private key params which are needed to use the key. + * Successful decryption does not imply key integrity, call validate() to confirm that. + * {@link SecretKeyPacket.isDecrypted} should be false, as + * otherwise calls to this function will throw an error. + * @param {String} passphrase - The passphrase for this private key as string + * @throws {Error} if the key is already decrypted, or if decryption was not successful + * @async + */ + async decrypt(passphrase) { + if (this.isDummy()) { + return false; + } + + if (this.isDecrypted()) { + throw new Error('Key packet is already decrypted.'); + } + + let key; + if (this.s2kUsage === 254 || this.s2kUsage === 253) { + key = await produceEncryptionKey(this.s2k, passphrase, this.symmetric); + } else if (this.s2kUsage === 255) { + throw new Error('Encrypted private key is authenticated using an insecure two-byte hash'); + } else { + throw new Error('Private key is encrypted using an insecure S2K function: unsalted MD5'); + } + + let cleartext; + if (this.s2kUsage === 253) { + const mode = mod.getAEADMode(this.aead); + const modeInstance = await mode(this.symmetric, key); + try { + cleartext = await modeInstance.decrypt(this.keyMaterial, this.iv.subarray(0, mode.ivLength), new Uint8Array()); + } catch (err) { + if (err.message === 'Authentication tag mismatch') { + throw new Error('Incorrect key passphrase: ' + err.message); + } + throw err; + } + } else { + const cleartextWithHash = await mod.mode.cfb.decrypt(this.symmetric, key, this.keyMaterial, this.iv); + + cleartext = cleartextWithHash.subarray(0, -20); + const hash = await mod.hash.sha1(cleartext); + + if (!util.equalsUint8Array(hash, cleartextWithHash.subarray(-20))) { + throw new Error('Incorrect key passphrase'); + } + } + + try { + const { privateParams } = mod.parsePrivateKeyParams(this.algorithm, cleartext, this.publicParams); + this.privateParams = privateParams; + } catch (err) { + throw new Error('Error reading MPIs'); + } + this.isEncrypted = false; + this.keyMaterial = null; + this.s2kUsage = 0; + } + + /** + * Checks that the key parameters are consistent + * @throws {Error} if validation was not successful + * @async + */ + async validate() { + if (this.isDummy()) { + return; + } + + if (!this.isDecrypted()) { + throw new Error('Key is not decrypted'); + } + + let validParams; + try { + // this can throw if some parameters are undefined + validParams = await mod.validateParams(this.algorithm, this.publicParams, this.privateParams); + } catch (_) { + validParams = false; + } + if (!validParams) { + throw new Error('Key is invalid'); + } + } + + async generate(bits, curve) { + const { privateParams, publicParams } = await mod.generateParams(this.algorithm, bits, curve); + this.privateParams = privateParams; + this.publicParams = publicParams; + this.isEncrypted = false; + } + + /** + * Clear private key parameters + */ + clearPrivateParams() { + if (this.isDummy()) { + return; + } + + Object.keys(this.privateParams).forEach(name => { + const param = this.privateParams[name]; + param.fill(0); + delete this.privateParams[name]; + }); + this.privateParams = null; + this.isEncrypted = true; + } +} + +async function produceEncryptionKey(s2k, passphrase, algorithm) { + const { keySize } = mod.getCipher(algorithm); + return s2k.produceKey(passphrase, keySize); +} + +var emailAddresses = createCommonjsModule(function (module) { +// email-addresses.js - RFC 5322 email address parser +// v 3.1.0 +// +// http://tools.ietf.org/html/rfc5322 +// +// This library does not validate email addresses. +// emailAddresses attempts to parse addresses using the (fairly liberal) +// grammar specified in RFC 5322. +// +// email-addresses returns { +// ast: , +// addresses: [{ +// node: , +// name: , +// address: , +// local: , +// domain: +// }, ...] +// } +// +// emailAddresses.parseOneAddress and emailAddresses.parseAddressList +// work as you might expect. Try it out. +// +// Many thanks to Dominic Sayers and his documentation on the is_email function, +// http://code.google.com/p/isemail/ , which helped greatly in writing this parser. + +(function (global) { + +function parse5322(opts) { + + // tokenizing functions + + function inStr() { return pos < len; } + function curTok() { return parseString[pos]; } + function getPos() { return pos; } + function setPos(i) { pos = i; } + function nextTok() { pos += 1; } + function initialize() { + pos = 0; + len = parseString.length; + } + + // parser helper functions + + function o(name, value) { + return { + name: name, + tokens: value || "", + semantic: value || "", + children: [] + }; + } + + function wrap(name, ast) { + var n; + if (ast === null) { return null; } + n = o(name); + n.tokens = ast.tokens; + n.semantic = ast.semantic; + n.children.push(ast); + return n; + } + + function add(parent, child) { + if (child !== null) { + parent.tokens += child.tokens; + parent.semantic += child.semantic; + } + parent.children.push(child); + return parent; + } + + function compareToken(fxnCompare) { + var tok; + if (!inStr()) { return null; } + tok = curTok(); + if (fxnCompare(tok)) { + nextTok(); + return o('token', tok); + } + return null; + } + + function literal(lit) { + return function literalFunc() { + return wrap('literal', compareToken(function (tok) { + return tok === lit; + })); + }; + } + + function and() { + var args = arguments; + return function andFunc() { + var i, s, result, start; + start = getPos(); + s = o('and'); + for (i = 0; i < args.length; i += 1) { + result = args[i](); + if (result === null) { + setPos(start); + return null; + } + add(s, result); + } + return s; + }; + } + + function or() { + var args = arguments; + return function orFunc() { + var i, result, start; + start = getPos(); + for (i = 0; i < args.length; i += 1) { + result = args[i](); + if (result !== null) { + return result; + } + setPos(start); + } + return null; + }; + } + + function opt(prod) { + return function optFunc() { + var result, start; + start = getPos(); + result = prod(); + if (result !== null) { + return result; + } + else { + setPos(start); + return o('opt'); + } + }; + } + + function invis(prod) { + return function invisFunc() { + var result = prod(); + if (result !== null) { + result.semantic = ""; + } + return result; + }; + } + + function colwsp(prod) { + return function collapseSemanticWhitespace() { + var result = prod(); + if (result !== null && result.semantic.length > 0) { + result.semantic = " "; + } + return result; + }; + } + + function star(prod, minimum) { + return function starFunc() { + var s, result, count, start, min; + start = getPos(); + s = o('star'); + count = 0; + min = minimum === undefined ? 0 : minimum; + while ((result = prod()) !== null) { + count = count + 1; + add(s, result); + } + if (count >= min) { + return s; + } + else { + setPos(start); + return null; + } + }; + } + + // One expects names to get normalized like this: + // " First Last " -> "First Last" + // "First Last" -> "First Last" + // "First Last" -> "First Last" + function collapseWhitespace(s) { + return s.replace(/([ \t]|\r\n)+/g, ' ').replace(/^\s*/, '').replace(/\s*$/, ''); + } + + // UTF-8 pseudo-production (RFC 6532) + // RFC 6532 extends RFC 5322 productions to include UTF-8 + // using the following productions: + // UTF8-non-ascii = UTF8-2 / UTF8-3 / UTF8-4 + // UTF8-2 = + // UTF8-3 = + // UTF8-4 = + // + // For reference, the extended RFC 5322 productions are: + // VCHAR =/ UTF8-non-ascii + // ctext =/ UTF8-non-ascii + // atext =/ UTF8-non-ascii + // qtext =/ UTF8-non-ascii + // dtext =/ UTF8-non-ascii + function isUTF8NonAscii(tok) { + // In JavaScript, we just deal directly with Unicode code points, + // so we aren't checking individual bytes for UTF-8 encoding. + // Just check that the character is non-ascii. + return tok.charCodeAt(0) >= 128; + } + + + // common productions (RFC 5234) + // http://tools.ietf.org/html/rfc5234 + // B.1. Core Rules + + // CR = %x0D + // ; carriage return + function cr() { return wrap('cr', literal('\r')()); } + + // CRLF = CR LF + // ; Internet standard newline + function crlf() { return wrap('crlf', and(cr, lf)()); } + + // DQUOTE = %x22 + // ; " (Double Quote) + function dquote() { return wrap('dquote', literal('"')()); } + + // HTAB = %x09 + // ; horizontal tab + function htab() { return wrap('htab', literal('\t')()); } + + // LF = %x0A + // ; linefeed + function lf() { return wrap('lf', literal('\n')()); } + + // SP = %x20 + function sp() { return wrap('sp', literal(' ')()); } + + // VCHAR = %x21-7E + // ; visible (printing) characters + function vchar() { + return wrap('vchar', compareToken(function vcharFunc(tok) { + var code = tok.charCodeAt(0); + var accept = (0x21 <= code && code <= 0x7E); + if (opts.rfc6532) { + accept = accept || isUTF8NonAscii(tok); + } + return accept; + })); + } + + // WSP = SP / HTAB + // ; white space + function wsp() { return wrap('wsp', or(sp, htab)()); } + + + // email productions (RFC 5322) + // http://tools.ietf.org/html/rfc5322 + // 3.2.1. Quoted characters + + // quoted-pair = ("\" (VCHAR / WSP)) / obs-qp + function quotedPair() { + var qp = wrap('quoted-pair', + or( + and(literal('\\'), or(vchar, wsp)), + obsQP + )()); + if (qp === null) { return null; } + // a quoted pair will be two characters, and the "\" character + // should be semantically "invisible" (RFC 5322 3.2.1) + qp.semantic = qp.semantic[1]; + return qp; + } + + // 3.2.2. Folding White Space and Comments + + // FWS = ([*WSP CRLF] 1*WSP) / obs-FWS + function fws() { + return wrap('fws', or( + obsFws, + and( + opt(and( + star(wsp), + invis(crlf) + )), + star(wsp, 1) + ) + )()); + } + + // ctext = %d33-39 / ; Printable US-ASCII + // %d42-91 / ; characters not including + // %d93-126 / ; "(", ")", or "\" + // obs-ctext + function ctext() { + return wrap('ctext', or( + function ctextFunc1() { + return compareToken(function ctextFunc2(tok) { + var code = tok.charCodeAt(0); + var accept = + (33 <= code && code <= 39) || + (42 <= code && code <= 91) || + (93 <= code && code <= 126); + if (opts.rfc6532) { + accept = accept || isUTF8NonAscii(tok); + } + return accept; + }); + }, + obsCtext + )()); + } + + // ccontent = ctext / quoted-pair / comment + function ccontent() { + return wrap('ccontent', or(ctext, quotedPair, comment)()); + } + + // comment = "(" *([FWS] ccontent) [FWS] ")" + function comment() { + return wrap('comment', and( + literal('('), + star(and(opt(fws), ccontent)), + opt(fws), + literal(')') + )()); + } + + // CFWS = (1*([FWS] comment) [FWS]) / FWS + function cfws() { + return wrap('cfws', or( + and( + star( + and(opt(fws), comment), + 1 + ), + opt(fws) + ), + fws + )()); + } + + // 3.2.3. Atom + + //atext = ALPHA / DIGIT / ; Printable US-ASCII + // "!" / "#" / ; characters not including + // "$" / "%" / ; specials. Used for atoms. + // "&" / "'" / + // "*" / "+" / + // "-" / "/" / + // "=" / "?" / + // "^" / "_" / + // "`" / "{" / + // "|" / "}" / + // "~" + function atext() { + return wrap('atext', compareToken(function atextFunc(tok) { + var accept = + ('a' <= tok && tok <= 'z') || + ('A' <= tok && tok <= 'Z') || + ('0' <= tok && tok <= '9') || + (['!', '#', '$', '%', '&', '\'', '*', '+', '-', '/', + '=', '?', '^', '_', '`', '{', '|', '}', '~'].indexOf(tok) >= 0); + if (opts.rfc6532) { + accept = accept || isUTF8NonAscii(tok); + } + return accept; + })); + } + + // atom = [CFWS] 1*atext [CFWS] + function atom() { + return wrap('atom', and(colwsp(opt(cfws)), star(atext, 1), colwsp(opt(cfws)))()); + } + + // dot-atom-text = 1*atext *("." 1*atext) + function dotAtomText() { + var s, maybeText; + s = wrap('dot-atom-text', star(atext, 1)()); + if (s === null) { return s; } + maybeText = star(and(literal('.'), star(atext, 1)))(); + if (maybeText !== null) { + add(s, maybeText); + } + return s; + } + + // dot-atom = [CFWS] dot-atom-text [CFWS] + function dotAtom() { + return wrap('dot-atom', and(invis(opt(cfws)), dotAtomText, invis(opt(cfws)))()); + } + + // 3.2.4. Quoted Strings + + // qtext = %d33 / ; Printable US-ASCII + // %d35-91 / ; characters not including + // %d93-126 / ; "\" or the quote character + // obs-qtext + function qtext() { + return wrap('qtext', or( + function qtextFunc1() { + return compareToken(function qtextFunc2(tok) { + var code = tok.charCodeAt(0); + var accept = + (33 === code) || + (35 <= code && code <= 91) || + (93 <= code && code <= 126); + if (opts.rfc6532) { + accept = accept || isUTF8NonAscii(tok); + } + return accept; + }); + }, + obsQtext + )()); + } + + // qcontent = qtext / quoted-pair + function qcontent() { + return wrap('qcontent', or(qtext, quotedPair)()); + } + + // quoted-string = [CFWS] + // DQUOTE *([FWS] qcontent) [FWS] DQUOTE + // [CFWS] + function quotedString() { + return wrap('quoted-string', and( + invis(opt(cfws)), + invis(dquote), star(and(opt(colwsp(fws)), qcontent)), opt(invis(fws)), invis(dquote), + invis(opt(cfws)) + )()); + } + + // 3.2.5 Miscellaneous Tokens + + // word = atom / quoted-string + function word() { + return wrap('word', or(atom, quotedString)()); + } + + // phrase = 1*word / obs-phrase + function phrase() { + return wrap('phrase', or(obsPhrase, star(word, 1))()); + } + + // 3.4. Address Specification + // address = mailbox / group + function address() { + return wrap('address', or(mailbox, group)()); + } + + // mailbox = name-addr / addr-spec + function mailbox() { + return wrap('mailbox', or(nameAddr, addrSpec)()); + } + + // name-addr = [display-name] angle-addr + function nameAddr() { + return wrap('name-addr', and(opt(displayName), angleAddr)()); + } + + // angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / + // obs-angle-addr + function angleAddr() { + return wrap('angle-addr', or( + and( + invis(opt(cfws)), + literal('<'), + addrSpec, + literal('>'), + invis(opt(cfws)) + ), + obsAngleAddr + )()); + } + + // group = display-name ":" [group-list] ";" [CFWS] + function group() { + return wrap('group', and( + displayName, + literal(':'), + opt(groupList), + literal(';'), + invis(opt(cfws)) + )()); + } + + // display-name = phrase + function displayName() { + return wrap('display-name', function phraseFixedSemantic() { + var result = phrase(); + if (result !== null) { + result.semantic = collapseWhitespace(result.semantic); + } + return result; + }()); + } + + // mailbox-list = (mailbox *("," mailbox)) / obs-mbox-list + function mailboxList() { + return wrap('mailbox-list', or( + and( + mailbox, + star(and(literal(','), mailbox)) + ), + obsMboxList + )()); + } + + // address-list = (address *("," address)) / obs-addr-list + function addressList() { + return wrap('address-list', or( + and( + address, + star(and(literal(','), address)) + ), + obsAddrList + )()); + } + + // group-list = mailbox-list / CFWS / obs-group-list + function groupList() { + return wrap('group-list', or( + mailboxList, + invis(cfws), + obsGroupList + )()); + } + + // 3.4.1 Addr-Spec Specification + + // local-part = dot-atom / quoted-string / obs-local-part + function localPart() { + // note: quoted-string, dotAtom are proper subsets of obs-local-part + // so we really just have to look for obsLocalPart, if we don't care about the exact parse tree + return wrap('local-part', or(obsLocalPart, dotAtom, quotedString)()); + } + + // dtext = %d33-90 / ; Printable US-ASCII + // %d94-126 / ; characters not including + // obs-dtext ; "[", "]", or "\" + function dtext() { + return wrap('dtext', or( + function dtextFunc1() { + return compareToken(function dtextFunc2(tok) { + var code = tok.charCodeAt(0); + var accept = + (33 <= code && code <= 90) || + (94 <= code && code <= 126); + if (opts.rfc6532) { + accept = accept || isUTF8NonAscii(tok); + } + return accept; + }); + }, + obsDtext + )() + ); + } + + // domain-literal = [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS] + function domainLiteral() { + return wrap('domain-literal', and( + invis(opt(cfws)), + literal('['), + star(and(opt(fws), dtext)), + opt(fws), + literal(']'), + invis(opt(cfws)) + )()); + } + + // domain = dot-atom / domain-literal / obs-domain + function domain() { + return wrap('domain', function domainCheckTLD() { + var result = or(obsDomain, dotAtom, domainLiteral)(); + if (opts.rejectTLD) { + if (result && result.semantic && result.semantic.indexOf('.') < 0) { + return null; + } + } + // strip all whitespace from domains + if (result) { + result.semantic = result.semantic.replace(/\s+/g, ''); + } + return result; + }()); + } + + // addr-spec = local-part "@" domain + function addrSpec() { + return wrap('addr-spec', and( + localPart, literal('@'), domain + )()); + } + + // 3.6.2 Originator Fields + // Below we only parse the field body, not the name of the field + // like "From:", "Sender:", or "Reply-To:". Other libraries that + // parse email headers can parse those and defer to these productions + // for the "RFC 5322" part. + + // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields + // from = "From:" (mailbox-list / address-list) CRLF + function fromSpec() { + return wrap('from', or( + mailboxList, + addressList + )()); + } + + // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields + // sender = "Sender:" (mailbox / address) CRLF + function senderSpec() { + return wrap('sender', or( + mailbox, + address + )()); + } + + // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields + // reply-to = "Reply-To:" address-list CRLF + function replyToSpec() { + return wrap('reply-to', addressList()); + } + + // 4.1. Miscellaneous Obsolete Tokens + + // obs-NO-WS-CTL = %d1-8 / ; US-ASCII control + // %d11 / ; characters that do not + // %d12 / ; include the carriage + // %d14-31 / ; return, line feed, and + // %d127 ; white space characters + function obsNoWsCtl() { + return opts.strict ? null : wrap('obs-NO-WS-CTL', compareToken(function (tok) { + var code = tok.charCodeAt(0); + return ((1 <= code && code <= 8) || + (11 === code || 12 === code) || + (14 <= code && code <= 31) || + (127 === code)); + })); + } + + // obs-ctext = obs-NO-WS-CTL + function obsCtext() { return opts.strict ? null : wrap('obs-ctext', obsNoWsCtl()); } + + // obs-qtext = obs-NO-WS-CTL + function obsQtext() { return opts.strict ? null : wrap('obs-qtext', obsNoWsCtl()); } + + // obs-qp = "\" (%d0 / obs-NO-WS-CTL / LF / CR) + function obsQP() { + return opts.strict ? null : wrap('obs-qp', and( + literal('\\'), + or(literal('\0'), obsNoWsCtl, lf, cr) + )()); + } + + // obs-phrase = word *(word / "." / CFWS) + function obsPhrase() { + if (opts.strict ) return null; + return opts.atInDisplayName ? wrap('obs-phrase', and( + word, + star(or(word, literal('.'), literal('@'), colwsp(cfws))) + )()) : + wrap('obs-phrase', and( + word, + star(or(word, literal('.'), colwsp(cfws))) + )()); + } + + // 4.2. Obsolete Folding White Space + + // NOTE: read the errata http://www.rfc-editor.org/errata_search.php?rfc=5322&eid=1908 + // obs-FWS = 1*([CRLF] WSP) + function obsFws() { + return opts.strict ? null : wrap('obs-FWS', star( + and(invis(opt(crlf)), wsp), + 1 + )()); + } + + // 4.4. Obsolete Addressing + + // obs-angle-addr = [CFWS] "<" obs-route addr-spec ">" [CFWS] + function obsAngleAddr() { + return opts.strict ? null : wrap('obs-angle-addr', and( + invis(opt(cfws)), + literal('<'), + obsRoute, + addrSpec, + literal('>'), + invis(opt(cfws)) + )()); + } + + // obs-route = obs-domain-list ":" + function obsRoute() { + return opts.strict ? null : wrap('obs-route', and( + obsDomainList, + literal(':') + )()); + } + + // obs-domain-list = *(CFWS / ",") "@" domain + // *("," [CFWS] ["@" domain]) + function obsDomainList() { + return opts.strict ? null : wrap('obs-domain-list', and( + star(or(invis(cfws), literal(','))), + literal('@'), + domain, + star(and( + literal(','), + invis(opt(cfws)), + opt(and(literal('@'), domain)) + )) + )()); + } + + // obs-mbox-list = *([CFWS] ",") mailbox *("," [mailbox / CFWS]) + function obsMboxList() { + return opts.strict ? null : wrap('obs-mbox-list', and( + star(and( + invis(opt(cfws)), + literal(',') + )), + mailbox, + star(and( + literal(','), + opt(and( + mailbox, + invis(cfws) + )) + )) + )()); + } + + // obs-addr-list = *([CFWS] ",") address *("," [address / CFWS]) + function obsAddrList() { + return opts.strict ? null : wrap('obs-addr-list', and( + star(and( + invis(opt(cfws)), + literal(',') + )), + address, + star(and( + literal(','), + opt(and( + address, + invis(cfws) + )) + )) + )()); + } + + // obs-group-list = 1*([CFWS] ",") [CFWS] + function obsGroupList() { + return opts.strict ? null : wrap('obs-group-list', and( + star(and( + invis(opt(cfws)), + literal(',') + ), 1), + invis(opt(cfws)) + )()); + } + + // obs-local-part = word *("." word) + function obsLocalPart() { + return opts.strict ? null : wrap('obs-local-part', and(word, star(and(literal('.'), word)))()); + } + + // obs-domain = atom *("." atom) + function obsDomain() { + return opts.strict ? null : wrap('obs-domain', and(atom, star(and(literal('.'), atom)))()); + } + + // obs-dtext = obs-NO-WS-CTL / quoted-pair + function obsDtext() { + return opts.strict ? null : wrap('obs-dtext', or(obsNoWsCtl, quotedPair)()); + } + + ///////////////////////////////////////////////////// + + // ast analysis + + function findNode(name, root) { + var i, stack, node; + if (root === null || root === undefined) { return null; } + stack = [root]; + while (stack.length > 0) { + node = stack.pop(); + if (node.name === name) { + return node; + } + for (i = node.children.length - 1; i >= 0; i -= 1) { + stack.push(node.children[i]); + } + } + return null; + } + + function findAllNodes(name, root) { + var i, stack, node, result; + if (root === null || root === undefined) { return null; } + stack = [root]; + result = []; + while (stack.length > 0) { + node = stack.pop(); + if (node.name === name) { + result.push(node); + } + for (i = node.children.length - 1; i >= 0; i -= 1) { + stack.push(node.children[i]); + } + } + return result; + } + + function findAllNodesNoChildren(names, root) { + var i, stack, node, result, namesLookup; + if (root === null || root === undefined) { return null; } + stack = [root]; + result = []; + namesLookup = {}; + for (i = 0; i < names.length; i += 1) { + namesLookup[names[i]] = true; + } + + while (stack.length > 0) { + node = stack.pop(); + if (node.name in namesLookup) { + result.push(node); + // don't look at children (hence findAllNodesNoChildren) + } else { + for (i = node.children.length - 1; i >= 0; i -= 1) { + stack.push(node.children[i]); + } + } + } + return result; + } + + function giveResult(ast) { + var addresses, groupsAndMailboxes, i, groupOrMailbox, result; + if (ast === null) { + return null; + } + addresses = []; + + // An address is a 'group' (i.e. a list of mailboxes) or a 'mailbox'. + groupsAndMailboxes = findAllNodesNoChildren(['group', 'mailbox'], ast); + for (i = 0; i < groupsAndMailboxes.length; i += 1) { + groupOrMailbox = groupsAndMailboxes[i]; + if (groupOrMailbox.name === 'group') { + addresses.push(giveResultGroup(groupOrMailbox)); + } else if (groupOrMailbox.name === 'mailbox') { + addresses.push(giveResultMailbox(groupOrMailbox)); + } + } + + result = { + ast: ast, + addresses: addresses, + }; + if (opts.simple) { + result = simplifyResult(result); + } + if (opts.oneResult) { + return oneResult(result); + } + if (opts.simple) { + return result && result.addresses; + } else { + return result; + } + } + + function giveResultGroup(group) { + var i; + var groupName = findNode('display-name', group); + var groupResultMailboxes = []; + var mailboxes = findAllNodesNoChildren(['mailbox'], group); + for (i = 0; i < mailboxes.length; i += 1) { + groupResultMailboxes.push(giveResultMailbox(mailboxes[i])); + } + return { + node: group, + parts: { + name: groupName, + }, + type: group.name, // 'group' + name: grabSemantic(groupName), + addresses: groupResultMailboxes, + }; + } + + function giveResultMailbox(mailbox) { + var name = findNode('display-name', mailbox); + var aspec = findNode('addr-spec', mailbox); + var cfws = findAllNodes('cfws', mailbox); + var comments = findAllNodesNoChildren(['comment'], mailbox); + + + var local = findNode('local-part', aspec); + var domain = findNode('domain', aspec); + return { + node: mailbox, + parts: { + name: name, + address: aspec, + local: local, + domain: domain, + comments: cfws + }, + type: mailbox.name, // 'mailbox' + name: grabSemantic(name), + address: grabSemantic(aspec), + local: grabSemantic(local), + domain: grabSemantic(domain), + comments: concatComments(comments), + groupName: grabSemantic(mailbox.groupName), + }; + } + + function grabSemantic(n) { + return n !== null && n !== undefined ? n.semantic : null; + } + + function simplifyResult(result) { + var i; + if (result && result.addresses) { + for (i = 0; i < result.addresses.length; i += 1) { + delete result.addresses[i].node; + } + } + return result; + } + + function concatComments(comments) { + var result = ''; + if (comments) { + for (var i = 0; i < comments.length; i += 1) { + result += grabSemantic(comments[i]); + } + } + return result; + } + + function oneResult(result) { + if (!result) { return null; } + if (!opts.partial && result.addresses.length > 1) { return null; } + return result.addresses && result.addresses[0]; + } + + ///////////////////////////////////////////////////// + + var parseString, pos, len, parsed, startProduction; + + opts = handleOpts(opts, {}); + if (opts === null) { return null; } + + parseString = opts.input; + + startProduction = { + 'address': address, + 'address-list': addressList, + 'angle-addr': angleAddr, + 'from': fromSpec, + 'group': group, + 'mailbox': mailbox, + 'mailbox-list': mailboxList, + 'reply-to': replyToSpec, + 'sender': senderSpec, + }[opts.startAt] || addressList; + + if (!opts.strict) { + initialize(); + opts.strict = true; + parsed = startProduction(parseString); + if (opts.partial || !inStr()) { + return giveResult(parsed); + } + opts.strict = false; + } + + initialize(); + parsed = startProduction(parseString); + if (!opts.partial && inStr()) { return null; } + return giveResult(parsed); +} + +function parseOneAddressSimple(opts) { + return parse5322(handleOpts(opts, { + oneResult: true, + rfc6532: true, + simple: true, + startAt: 'address-list', + })); +} + +function parseAddressListSimple(opts) { + return parse5322(handleOpts(opts, { + rfc6532: true, + simple: true, + startAt: 'address-list', + })); +} + +function parseFromSimple(opts) { + return parse5322(handleOpts(opts, { + rfc6532: true, + simple: true, + startAt: 'from', + })); +} + +function parseSenderSimple(opts) { + return parse5322(handleOpts(opts, { + oneResult: true, + rfc6532: true, + simple: true, + startAt: 'sender', + })); +} + +function parseReplyToSimple(opts) { + return parse5322(handleOpts(opts, { + rfc6532: true, + simple: true, + startAt: 'reply-to', + })); +} + +function handleOpts(opts, defs) { + function isString(str) { + return Object.prototype.toString.call(str) === '[object String]'; + } + + function isObject(o) { + return o === Object(o); + } + + function isNullUndef(o) { + return o === null || o === undefined; + } + + var defaults, o; + + if (isString(opts)) { + opts = { input: opts }; + } else if (!isObject(opts)) { + return null; + } + + if (!isString(opts.input)) { return null; } + if (!defs) { return null; } + + defaults = { + oneResult: false, + partial: false, + rejectTLD: false, + rfc6532: false, + simple: false, + startAt: 'address-list', + strict: false, + atInDisplayName: false + }; + + for (o in defaults) { + if (isNullUndef(opts[o])) { + opts[o] = !isNullUndef(defs[o]) ? defs[o] : defaults[o]; + } + } + return opts; +} + +parse5322.parseOneAddress = parseOneAddressSimple; +parse5322.parseAddressList = parseAddressListSimple; +parse5322.parseFrom = parseFromSimple; +parse5322.parseSender = parseSenderSimple; +parse5322.parseReplyTo = parseReplyToSimple; + +{ + module.exports = parse5322; +} + +}()); +}); + +// GPG4Browsers - An OpenPGP implementation in javascript + +/** + * Implementation of the User ID Packet (Tag 13) + * + * A User ID packet consists of UTF-8 text that is intended to represent + * the name and email address of the key holder. By convention, it + * includes an RFC 2822 [RFC2822] mail name-addr, but there are no + * restrictions on its content. The packet length in the header + * specifies the length of the User ID. + */ +class UserIDPacket { + static get tag() { + return enums.packet.userID; + } + + constructor() { + /** A string containing the user id. Usually in the form + * John Doe + * @type {String} + */ + this.userID = ''; + + this.name = ''; + this.email = ''; + this.comment = ''; + } + + /** + * Create UserIDPacket instance from object + * @param {Object} userID - Object specifying userID name, email and comment + * @returns {UserIDPacket} + * @static + */ + static fromObject(userID) { + if (util.isString(userID) || + (userID.name && !util.isString(userID.name)) || + (userID.email && !util.isEmailAddress(userID.email)) || + (userID.comment && !util.isString(userID.comment))) { + throw new Error('Invalid user ID format'); + } + const packet = new UserIDPacket(); + Object.assign(packet, userID); + const components = []; + if (packet.name) components.push(packet.name); + if (packet.comment) components.push(`(${packet.comment})`); + if (packet.email) components.push(`<${packet.email}>`); + packet.userID = components.join(' '); + return packet; + } + + /** + * Parsing function for a user id packet (tag 13). + * @param {Uint8Array} input - Payload of a tag 13 packet + */ + read(bytes, config = defaultConfig) { + const userID = util.decodeUTF8(bytes); + if (userID.length > config.maxUserIDLength) { + throw new Error('User ID string is too long'); + } + try { + const { name, address: email, comments } = emailAddresses.parseOneAddress({ input: userID, atInDisplayName: true }); + this.comment = comments.replace(/^\(|\)$/g, ''); + this.name = name; + this.email = email; + } catch (e) {} + this.userID = userID; + } + + /** + * Creates a binary representation of the user id packet + * @returns {Uint8Array} Binary representation. + */ + write() { + return util.encodeUTF8(this.userID); + } + + equals(otherUserID) { + return otherUserID && otherUserID.userID === this.userID; + } +} + +// GPG4Browsers - An OpenPGP implementation in javascript + +/** + * A Secret-Subkey packet (tag 7) is the subkey analog of the Secret + * Key packet and has exactly the same format. + * @extends SecretKeyPacket + */ +class SecretSubkeyPacket extends SecretKeyPacket { + static get tag() { + return enums.packet.secretSubkey; + } + + /** + * @param {Date} [date] - Creation date + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + constructor(date = new Date(), config = defaultConfig) { + super(date, config); + } +} + +/** + * Implementation of the Trust Packet (Tag 12) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.10|RFC4880 5.10}: + * The Trust packet is used only within keyrings and is not normally + * exported. Trust packets contain data that record the user's + * specifications of which key holders are trustworthy introducers, + * along with other information that implementing software uses for + * trust information. The format of Trust packets is defined by a given + * implementation. + * + * Trust packets SHOULD NOT be emitted to output streams that are + * transferred to other users, and they SHOULD be ignored on any input + * other than local keyring files. + */ +class TrustPacket { + static get tag() { + return enums.packet.trust; + } + + /** + * Parsing function for a trust packet (tag 12). + * Currently not implemented as we ignore trust packets + */ + read() { + throw new UnsupportedError('Trust packets are not supported'); + } + + write() { + throw new UnsupportedError('Trust packets are not supported'); + } +} + +// GPG4Browsers - An OpenPGP implementation in javascript + +// A Signature can contain the following packets +const allowedPackets$4 = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); + +/** + * Class that represents an OpenPGP signature. + */ +class Signature { + /** + * @param {PacketList} packetlist - The signature packets + */ + constructor(packetlist) { + this.packets = packetlist || new PacketList(); + } + + /** + * Returns binary encoded signature + * @returns {ReadableStream} Binary signature. + */ + write() { + return this.packets.write(); + } + + /** + * Returns ASCII armored text of signature + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {ReadableStream} ASCII armor. + */ + armor(config = defaultConfig) { + return armor(enums.armor.signature, this.write(), undefined, undefined, undefined, config); + } + + /** + * Returns an array of KeyIDs of all of the issuers who created this signature + * @returns {Array} The Key IDs of the signing keys + */ + getSigningKeyIDs() { + return this.packets.map(packet => packet.issuerKeyID); + } +} + +/** + * reads an (optionally armored) OpenPGP signature and returns a signature object + * @param {Object} options + * @param {String} [options.armoredSignature] - Armored signature to be parsed + * @param {Uint8Array} [options.binarySignature] - Binary signature to be parsed + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} New signature object. + * @async + * @static + */ +async function readSignature({ armoredSignature, binarySignature, config, ...rest }) { + config = { ...defaultConfig, ...config }; + let input = armoredSignature || binarySignature; + if (!input) { + throw new Error('readSignature: must pass options object containing `armoredSignature` or `binarySignature`'); + } + if (armoredSignature && !util.isString(armoredSignature)) { + throw new Error('readSignature: options.armoredSignature must be a string'); + } + if (binarySignature && !util.isUint8Array(binarySignature)) { + throw new Error('readSignature: options.binarySignature must be a Uint8Array'); + } + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + if (armoredSignature) { + const { type, data } = await unarmor(input, config); + if (type !== enums.armor.signature) { + throw new Error('Armored text not of type signature'); + } + input = data; + } + const packetlist = await PacketList.fromBinary(input, allowedPackets$4, config); + return new Signature(packetlist); +} + +/** + * @fileoverview Provides helpers methods for key module + * @module key/helper + * @private + */ + +async function generateSecretSubkey(options, config) { + const secretSubkeyPacket = new SecretSubkeyPacket(options.date, config); + secretSubkeyPacket.packets = null; + secretSubkeyPacket.algorithm = enums.write(enums.publicKey, options.algorithm); + await secretSubkeyPacket.generate(options.rsaBits, options.curve); + await secretSubkeyPacket.computeFingerprintAndKeyID(); + return secretSubkeyPacket; +} + +async function generateSecretKey(options, config) { + const secretKeyPacket = new SecretKeyPacket(options.date, config); + secretKeyPacket.packets = null; + secretKeyPacket.algorithm = enums.write(enums.publicKey, options.algorithm); + await secretKeyPacket.generate(options.rsaBits, options.curve, options.config); + await secretKeyPacket.computeFingerprintAndKeyID(); + return secretKeyPacket; +} + +/** + * Returns the valid and non-expired signature that has the latest creation date, while ignoring signatures created in the future. + * @param {Array} signatures - List of signatures + * @param {PublicKeyPacket|PublicSubkeyPacket} publicKey - Public key packet to verify the signature + * @param {Date} date - Use the given date instead of the current time + * @param {Object} config - full configuration + * @returns {Promise} The latest valid signature. + * @async + */ +async function getLatestValidSignature(signatures, publicKey, signatureType, dataToVerify, date = new Date(), config) { + let latestValid; + let exception; + for (let i = signatures.length - 1; i >= 0; i--) { + try { + if ( + (!latestValid || signatures[i].created >= latestValid.created) + ) { + await signatures[i].verify(publicKey, signatureType, dataToVerify, date, undefined, config); + latestValid = signatures[i]; + } + } catch (e) { + exception = e; + } + } + if (!latestValid) { + throw util.wrapError( + `Could not find valid ${enums.read(enums.signature, signatureType)} signature in key ${publicKey.getKeyID().toHex()}` + .replace('certGeneric ', 'self-') + .replace(/([a-z])([A-Z])/g, (_, $1, $2) => $1 + ' ' + $2.toLowerCase()) + , exception); + } + return latestValid; +} + +function isDataExpired(keyPacket, signature, date = new Date()) { + const normDate = util.normalizeDate(date); + if (normDate !== null) { + const expirationTime = getKeyExpirationTime(keyPacket, signature); + return !(keyPacket.created <= normDate && normDate < expirationTime); + } + return false; +} + +/** + * Create Binding signature to the key according to the {@link https://tools.ietf.org/html/rfc4880#section-5.2.1} + * @param {SecretSubkeyPacket} subkey - Subkey key packet + * @param {SecretKeyPacket} primaryKey - Primary key packet + * @param {Object} options + * @param {Object} config - Full configuration + */ +async function createBindingSignature(subkey, primaryKey, options, config) { + const dataToSign = {}; + dataToSign.key = primaryKey; + dataToSign.bind = subkey; + const subkeySignaturePacket = new SignaturePacket(); + subkeySignaturePacket.signatureType = enums.signature.subkeyBinding; + subkeySignaturePacket.publicKeyAlgorithm = primaryKey.algorithm; + subkeySignaturePacket.hashAlgorithm = await getPreferredHashAlgo$1(null, subkey, undefined, undefined, config); + if (options.sign) { + subkeySignaturePacket.keyFlags = [enums.keyFlags.signData]; + subkeySignaturePacket.embeddedSignature = await createSignaturePacket(dataToSign, null, subkey, { + signatureType: enums.signature.keyBinding + }, options.date, undefined, undefined, config); + } else { + subkeySignaturePacket.keyFlags = [enums.keyFlags.encryptCommunication | enums.keyFlags.encryptStorage]; + } + if (options.keyExpirationTime > 0) { + subkeySignaturePacket.keyExpirationTime = options.keyExpirationTime; + subkeySignaturePacket.keyNeverExpires = false; + } + await subkeySignaturePacket.sign(primaryKey, dataToSign, options.date); + return subkeySignaturePacket; +} + +/** + * Returns the preferred signature hash algorithm of a key + * @param {Key} [key] - The key to get preferences from + * @param {SecretKeyPacket|SecretSubkeyPacket} keyPacket - key packet used for signing + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} [userID] - User ID + * @param {Object} config - full configuration + * @returns {Promise} + * @async + */ +async function getPreferredHashAlgo$1(key, keyPacket, date = new Date(), userID = {}, config) { + let hashAlgo = config.preferredHashAlgorithm; + let prefAlgo = hashAlgo; + if (key) { + const primaryUser = await key.getPrimaryUser(date, userID, config); + if (primaryUser.selfCertification.preferredHashAlgorithms) { + [prefAlgo] = primaryUser.selfCertification.preferredHashAlgorithms; + hashAlgo = mod.hash.getHashByteLength(hashAlgo) <= mod.hash.getHashByteLength(prefAlgo) ? + prefAlgo : hashAlgo; + } + } + switch (Object.getPrototypeOf(keyPacket)) { + case SecretKeyPacket.prototype: + case PublicKeyPacket.prototype: + case SecretSubkeyPacket.prototype: + case PublicSubkeyPacket.prototype: + switch (keyPacket.algorithm) { + case enums.publicKey.ecdh: + case enums.publicKey.ecdsa: + case enums.publicKey.eddsa: + prefAlgo = mod.publicKey.elliptic.getPreferredHashAlgo(keyPacket.publicParams.oid); + } + } + return mod.hash.getHashByteLength(hashAlgo) <= mod.hash.getHashByteLength(prefAlgo) ? + prefAlgo : hashAlgo; +} + +/** + * Returns the preferred symmetric/aead/compression algorithm for a set of keys + * @param {'symmetric'|'aead'|'compression'} type - Type of preference to return + * @param {Array} [keys] - Set of keys + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Array} [userIDs] - User IDs + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} Preferred algorithm + * @async + */ +async function getPreferredAlgo(type, keys = [], date = new Date(), userIDs = [], config = defaultConfig) { + const defaultAlgo = { // these are all must-implement in rfc4880bis + 'symmetric': enums.symmetric.aes128, + 'aead': enums.aead.eax, + 'compression': enums.compression.uncompressed + }[type]; + const preferredSenderAlgo = { + 'symmetric': config.preferredSymmetricAlgorithm, + 'aead': config.preferredAEADAlgorithm, + 'compression': config.preferredCompressionAlgorithm + }[type]; + const prefPropertyName = { + 'symmetric': 'preferredSymmetricAlgorithms', + 'aead': 'preferredAEADAlgorithms', + 'compression': 'preferredCompressionAlgorithms' + }[type]; + + // if preferredSenderAlgo appears in the prefs of all recipients, we pick it + // otherwise we use the default algo + // if no keys are available, preferredSenderAlgo is returned + const senderAlgoSupport = await Promise.all(keys.map(async function(key, i) { + const primaryUser = await key.getPrimaryUser(date, userIDs[i], config); + const recipientPrefs = primaryUser.selfCertification[prefPropertyName]; + return !!recipientPrefs && recipientPrefs.indexOf(preferredSenderAlgo) >= 0; + })); + return senderAlgoSupport.every(Boolean) ? preferredSenderAlgo : defaultAlgo; +} + +/** + * Create signature packet + * @param {Object} dataToSign - Contains packets to be signed + * @param {PrivateKey} privateKey - key to get preferences from + * @param {SecretKeyPacket| + * SecretSubkeyPacket} signingKeyPacket secret key packet for signing + * @param {Object} [signatureProperties] - Properties to write on the signature packet before signing + * @param {Date} [date] - Override the creationtime of the signature + * @param {Object} [userID] - User ID + * @param {Object} [detached] - Whether to create a detached signature packet + * @param {Object} config - full configuration + * @returns {Promise} Signature packet. + */ +async function createSignaturePacket(dataToSign, privateKey, signingKeyPacket, signatureProperties, date, userID, detached = false, config) { + if (signingKeyPacket.isDummy()) { + throw new Error('Cannot sign with a gnu-dummy key.'); + } + if (!signingKeyPacket.isDecrypted()) { + throw new Error('Signing key is not decrypted.'); + } + const signaturePacket = new SignaturePacket(); + Object.assign(signaturePacket, signatureProperties); + signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm; + signaturePacket.hashAlgorithm = await getPreferredHashAlgo$1(privateKey, signingKeyPacket, date, userID, config); + await signaturePacket.sign(signingKeyPacket, dataToSign, date, detached); + return signaturePacket; +} + +/** + * Merges signatures from source[attr] to dest[attr] + * @param {Object} source + * @param {Object} dest + * @param {String} attr + * @param {Date} [date] - date to use for signature expiration check, instead of the current time + * @param {Function} [checkFn] - signature only merged if true + */ +async function mergeSignatures(source, dest, attr, date = new Date(), checkFn) { + source = source[attr]; + if (source) { + if (!dest[attr].length) { + dest[attr] = source; + } else { + await Promise.all(source.map(async function(sourceSig) { + if (!sourceSig.isExpired(date) && (!checkFn || await checkFn(sourceSig)) && + !dest[attr].some(function(destSig) { + return util.equalsUint8Array(destSig.writeParams(), sourceSig.writeParams()); + })) { + dest[attr].push(sourceSig); + } + })); + } + } +} + +/** + * Checks if a given certificate or binding signature is revoked + * @param {SecretKeyPacket| + * PublicKeyPacket} primaryKey The primary key packet + * @param {Object} dataToVerify - The data to check + * @param {Array} revocations - The revocation signatures to check + * @param {SignaturePacket} signature - The certificate or signature to check + * @param {PublicSubkeyPacket| + * SecretSubkeyPacket| + * PublicKeyPacket| + * SecretKeyPacket} key, optional The key packet to verify the signature, instead of the primary key + * @param {Date} date - Use the given date instead of the current time + * @param {Object} config - Full configuration + * @returns {Promise} True if the signature revokes the data. + * @async + */ +async function isDataRevoked(primaryKey, signatureType, dataToVerify, revocations, signature, key, date = new Date(), config) { + key = key || primaryKey; + const revocationKeyIDs = []; + await Promise.all(revocations.map(async function(revocationSignature) { + try { + if ( + // Note: a third-party revocation signature could legitimately revoke a + // self-signature if the signature has an authorized revocation key. + // However, we don't support passing authorized revocation keys, nor + // verifying such revocation signatures. Instead, we indicate an error + // when parsing a key with an authorized revocation key, and ignore + // third-party revocation signatures here. (It could also be revoking a + // third-party key certification, which should only affect + // `verifyAllCertifications`.) + !signature || revocationSignature.issuerKeyID.equals(signature.issuerKeyID) + ) { + await revocationSignature.verify( + key, signatureType, dataToVerify, config.revocationsExpire ? date : null, false, config + ); + + // TODO get an identifier of the revoked object instead + revocationKeyIDs.push(revocationSignature.issuerKeyID); + } + } catch (e) {} + })); + // TODO further verify that this is the signature that should be revoked + if (signature) { + signature.revoked = revocationKeyIDs.some(keyID => keyID.equals(signature.issuerKeyID)) ? true : + signature.revoked || false; + return signature.revoked; + } + return revocationKeyIDs.length > 0; +} + +/** + * Returns key expiration time based on the given certification signature. + * The expiration time of the signature is ignored. + * @param {PublicSubkeyPacket|PublicKeyPacket} keyPacket - key to check + * @param {SignaturePacket} signature - signature to process + * @returns {Date|Infinity} expiration time or infinity if the key does not expire + */ +function getKeyExpirationTime(keyPacket, signature) { + let expirationTime; + // check V4 expiration time + if (signature.keyNeverExpires === false) { + expirationTime = keyPacket.created.getTime() + signature.keyExpirationTime * 1000; + } + return expirationTime ? new Date(expirationTime) : Infinity; +} + +/** + * Returns whether aead is supported by all keys in the set + * @param {Array} keys - Set of keys + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Array} [userIDs] - User IDs + * @param {Object} config - full configuration + * @returns {Promise} + * @async + */ +async function isAEADSupported(keys, date = new Date(), userIDs = [], config = defaultConfig) { + let supported = true; + // TODO replace when Promise.some or Promise.any are implemented + await Promise.all(keys.map(async function(key, i) { + const primaryUser = await key.getPrimaryUser(date, userIDs[i], config); + if (!primaryUser.selfCertification.features || + !(primaryUser.selfCertification.features[0] & enums.features.aead)) { + supported = false; + } + })); + return supported; +} + +function sanitizeKeyOptions(options, subkeyDefaults = {}) { + options.type = options.type || subkeyDefaults.type; + options.curve = options.curve || subkeyDefaults.curve; + options.rsaBits = options.rsaBits || subkeyDefaults.rsaBits; + options.keyExpirationTime = options.keyExpirationTime !== undefined ? options.keyExpirationTime : subkeyDefaults.keyExpirationTime; + options.passphrase = util.isString(options.passphrase) ? options.passphrase : subkeyDefaults.passphrase; + options.date = options.date || subkeyDefaults.date; + + options.sign = options.sign || false; + + switch (options.type) { + case 'ecc': + try { + options.curve = enums.write(enums.curve, options.curve); + } catch (e) { + throw new Error('Invalid curve'); + } + if (options.curve === enums.curve.ed25519 || options.curve === enums.curve.curve25519) { + options.curve = options.sign ? enums.curve.ed25519 : enums.curve.curve25519; + } + if (options.sign) { + options.algorithm = options.curve === enums.curve.ed25519 ? enums.publicKey.eddsa : enums.publicKey.ecdsa; + } else { + options.algorithm = enums.publicKey.ecdh; + } + break; + case 'rsa': + options.algorithm = enums.publicKey.rsaEncryptSign; + break; + default: + throw new Error(`Unsupported key type ${options.type}`); + } + return options; +} + +function isValidSigningKeyPacket(keyPacket, signature) { + const keyAlgo = keyPacket.algorithm; + return keyAlgo !== enums.publicKey.rsaEncrypt && + keyAlgo !== enums.publicKey.elgamal && + keyAlgo !== enums.publicKey.ecdh && + (!signature.keyFlags || + (signature.keyFlags[0] & enums.keyFlags.signData) !== 0); +} + +function isValidEncryptionKeyPacket(keyPacket, signature) { + const keyAlgo = keyPacket.algorithm; + return keyAlgo !== enums.publicKey.dsa && + keyAlgo !== enums.publicKey.rsaSign && + keyAlgo !== enums.publicKey.ecdsa && + keyAlgo !== enums.publicKey.eddsa && + (!signature.keyFlags || + (signature.keyFlags[0] & enums.keyFlags.encryptCommunication) !== 0 || + (signature.keyFlags[0] & enums.keyFlags.encryptStorage) !== 0); +} + +function isValidDecryptionKeyPacket(signature, config) { + if (config.allowInsecureDecryptionWithSigningKeys) { + // This is only relevant for RSA keys, all other signing algorithms cannot decrypt + return true; + } + + return !signature.keyFlags || + (signature.keyFlags[0] & enums.keyFlags.encryptCommunication) !== 0 || + (signature.keyFlags[0] & enums.keyFlags.encryptStorage) !== 0; +} + +/** + * Check key against blacklisted algorithms and minimum strength requirements. + * @param {SecretKeyPacket|PublicKeyPacket| + * SecretSubkeyPacket|PublicSubkeyPacket} keyPacket + * @param {Config} config + * @throws {Error} if the key packet does not meet the requirements + */ +function checkKeyRequirements(keyPacket, config) { + const keyAlgo = enums.write(enums.publicKey, keyPacket.algorithm); + const algoInfo = keyPacket.getAlgorithmInfo(); + if (config.rejectPublicKeyAlgorithms.has(keyAlgo)) { + throw new Error(`${algoInfo.algorithm} keys are considered too weak.`); + } + switch (keyAlgo) { + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaSign: + case enums.publicKey.rsaEncrypt: + if (algoInfo.bits < config.minRSABits) { + throw new Error(`RSA keys shorter than ${config.minRSABits} bits are considered too weak.`); + } + break; + case enums.publicKey.ecdsa: + case enums.publicKey.eddsa: + case enums.publicKey.ecdh: + if (config.rejectCurves.has(algoInfo.curve)) { + throw new Error(`Support for ${algoInfo.algorithm} keys using curve ${algoInfo.curve} is disabled.`); + } + break; + } +} + +/** + * @module key/User + * @private + */ + +/** + * Class that represents an user ID or attribute packet and the relevant signatures. + * @param {UserIDPacket|UserAttributePacket} userPacket - packet containing the user info + * @param {Key} mainKey - reference to main Key object containing the primary key and subkeys that the user is associated with + */ +class User { + constructor(userPacket, mainKey) { + this.userID = userPacket.constructor.tag === enums.packet.userID ? userPacket : null; + this.userAttribute = userPacket.constructor.tag === enums.packet.userAttribute ? userPacket : null; + this.selfCertifications = []; + this.otherCertifications = []; + this.revocationSignatures = []; + this.mainKey = mainKey; + } + + /** + * Transforms structured user data to packetlist + * @returns {PacketList} + */ + toPacketList() { + const packetlist = new PacketList(); + packetlist.push(this.userID || this.userAttribute); + packetlist.push(...this.revocationSignatures); + packetlist.push(...this.selfCertifications); + packetlist.push(...this.otherCertifications); + return packetlist; + } + + /** + * Shallow clone + * @returns {User} + */ + clone() { + const user = new User(this.userID || this.userAttribute, this.mainKey); + user.selfCertifications = [...this.selfCertifications]; + user.otherCertifications = [...this.otherCertifications]; + user.revocationSignatures = [...this.revocationSignatures]; + return user; + } + + /** + * Generate third-party certifications over this user and its primary key + * @param {Array} signingKeys - Decrypted private keys for signing + * @param {Date} [date] - Date to use as creation date of the certificate, instead of the current time + * @param {Object} config - Full configuration + * @returns {Promise} New user with new certifications. + * @async + */ + async certify(signingKeys, date, config) { + const primaryKey = this.mainKey.keyPacket; + const dataToSign = { + userID: this.userID, + userAttribute: this.userAttribute, + key: primaryKey + }; + const user = new User(dataToSign.userID || dataToSign.userAttribute, this.mainKey); + user.otherCertifications = await Promise.all(signingKeys.map(async function(privateKey) { + if (!privateKey.isPrivate()) { + throw new Error('Need private key for signing'); + } + if (privateKey.hasSameFingerprintAs(primaryKey)) { + throw new Error("The user's own key can only be used for self-certifications"); + } + const signingKey = await privateKey.getSigningKey(undefined, date, undefined, config); + return createSignaturePacket(dataToSign, privateKey, signingKey.keyPacket, { + // Most OpenPGP implementations use generic certification (0x10) + signatureType: enums.signature.certGeneric, + keyFlags: [enums.keyFlags.certifyKeys | enums.keyFlags.signData] + }, date, undefined, undefined, config); + })); + await user.update(this, date, config); + return user; + } + + /** + * Checks if a given certificate of the user is revoked + * @param {SignaturePacket} certificate - The certificate to verify + * @param {PublicSubkeyPacket| + * SecretSubkeyPacket| + * PublicKeyPacket| + * SecretKeyPacket} [keyPacket] The key packet to verify the signature, instead of the primary key + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} config - Full configuration + * @returns {Promise} True if the certificate is revoked. + * @async + */ + async isRevoked(certificate, keyPacket, date = new Date(), config) { + const primaryKey = this.mainKey.keyPacket; + return isDataRevoked(primaryKey, enums.signature.certRevocation, { + key: primaryKey, + userID: this.userID, + userAttribute: this.userAttribute + }, this.revocationSignatures, certificate, keyPacket, date, config); + } + + /** + * Verifies the user certificate. + * @param {SignaturePacket} certificate - A certificate of this user + * @param {Array} verificationKeys - Array of keys to verify certificate signatures + * @param {Date} [date] - Use the given date instead of the current time + * @param {Object} config - Full configuration + * @returns {Promise} true if the certificate could be verified, or null if the verification keys do not correspond to the certificate + * @throws if the user certificate is invalid. + * @async + */ + async verifyCertificate(certificate, verificationKeys, date = new Date(), config) { + const that = this; + const primaryKey = this.mainKey.keyPacket; + const dataToVerify = { + userID: this.userID, + userAttribute: this.userAttribute, + key: primaryKey + }; + const { issuerKeyID } = certificate; + const issuerKeys = verificationKeys.filter(key => key.getKeys(issuerKeyID).length > 0); + if (issuerKeys.length === 0) { + return null; + } + await Promise.all(issuerKeys.map(async key => { + const signingKey = await key.getSigningKey(issuerKeyID, certificate.created, undefined, config); + if (certificate.revoked || await that.isRevoked(certificate, signingKey.keyPacket, date, config)) { + throw new Error('User certificate is revoked'); + } + try { + await certificate.verify(signingKey.keyPacket, enums.signature.certGeneric, dataToVerify, date, undefined, config); + } catch (e) { + throw util.wrapError('User certificate is invalid', e); + } + })); + return true; + } + + /** + * Verifies all user certificates + * @param {Array} verificationKeys - Array of keys to verify certificate signatures + * @param {Date} [date] - Use the given date instead of the current time + * @param {Object} config - Full configuration + * @returns {Promise>} List of signer's keyID and validity of signature. + * Signature validity is null if the verification keys do not correspond to the certificate. + * @async + */ + async verifyAllCertifications(verificationKeys, date = new Date(), config) { + const that = this; + const certifications = this.selfCertifications.concat(this.otherCertifications); + return Promise.all(certifications.map(async certification => ({ + keyID: certification.issuerKeyID, + valid: await that.verifyCertificate(certification, verificationKeys, date, config).catch(() => false) + }))); + } + + /** + * Verify User. Checks for existence of self signatures, revocation signatures + * and validity of self signature. + * @param {Date} date - Use the given date instead of the current time + * @param {Object} config - Full configuration + * @returns {Promise} Status of user. + * @throws {Error} if there are no valid self signatures. + * @async + */ + async verify(date = new Date(), config) { + if (!this.selfCertifications.length) { + throw new Error('No self-certifications found'); + } + const that = this; + const primaryKey = this.mainKey.keyPacket; + const dataToVerify = { + userID: this.userID, + userAttribute: this.userAttribute, + key: primaryKey + }; + // TODO replace when Promise.some or Promise.any are implemented + let exception; + for (let i = this.selfCertifications.length - 1; i >= 0; i--) { + try { + const selfCertification = this.selfCertifications[i]; + if (selfCertification.revoked || await that.isRevoked(selfCertification, undefined, date, config)) { + throw new Error('Self-certification is revoked'); + } + try { + await selfCertification.verify(primaryKey, enums.signature.certGeneric, dataToVerify, date, undefined, config); + } catch (e) { + throw util.wrapError('Self-certification is invalid', e); + } + return true; + } catch (e) { + exception = e; + } + } + throw exception; + } + + /** + * Update user with new components from specified user + * @param {User} sourceUser - Source user to merge + * @param {Date} date - Date to verify the validity of signatures + * @param {Object} config - Full configuration + * @returns {Promise} + * @async + */ + async update(sourceUser, date, config) { + const primaryKey = this.mainKey.keyPacket; + const dataToVerify = { + userID: this.userID, + userAttribute: this.userAttribute, + key: primaryKey + }; + // self signatures + await mergeSignatures(sourceUser, this, 'selfCertifications', date, async function(srcSelfSig) { + try { + await srcSelfSig.verify(primaryKey, enums.signature.certGeneric, dataToVerify, date, false, config); + return true; + } catch (e) { + return false; + } + }); + // other signatures + await mergeSignatures(sourceUser, this, 'otherCertifications', date); + // revocation signatures + await mergeSignatures(sourceUser, this, 'revocationSignatures', date, function(srcRevSig) { + return isDataRevoked(primaryKey, enums.signature.certRevocation, dataToVerify, [srcRevSig], undefined, undefined, date, config); + }); + } +} + +/** + * @module key/Subkey + * @private + */ + +/** + * Class that represents a subkey packet and the relevant signatures. + * @borrows PublicSubkeyPacket#getKeyID as Subkey#getKeyID + * @borrows PublicSubkeyPacket#getFingerprint as Subkey#getFingerprint + * @borrows PublicSubkeyPacket#hasSameFingerprintAs as Subkey#hasSameFingerprintAs + * @borrows PublicSubkeyPacket#getAlgorithmInfo as Subkey#getAlgorithmInfo + * @borrows PublicSubkeyPacket#getCreationTime as Subkey#getCreationTime + * @borrows PublicSubkeyPacket#isDecrypted as Subkey#isDecrypted + */ +class Subkey { + /** + * @param {SecretSubkeyPacket|PublicSubkeyPacket} subkeyPacket - subkey packet to hold in the Subkey + * @param {Key} mainKey - reference to main Key object, containing the primary key packet corresponding to the subkey + */ + constructor(subkeyPacket, mainKey) { + this.keyPacket = subkeyPacket; + this.bindingSignatures = []; + this.revocationSignatures = []; + this.mainKey = mainKey; + } + + /** + * Transforms structured subkey data to packetlist + * @returns {PacketList} + */ + toPacketList() { + const packetlist = new PacketList(); + packetlist.push(this.keyPacket); + packetlist.push(...this.revocationSignatures); + packetlist.push(...this.bindingSignatures); + return packetlist; + } + + /** + * Shallow clone + * @return {Subkey} + */ + clone() { + const subkey = new Subkey(this.keyPacket, this.mainKey); + subkey.bindingSignatures = [...this.bindingSignatures]; + subkey.revocationSignatures = [...this.revocationSignatures]; + return subkey; + } + + /** + * Checks if a binding signature of a subkey is revoked + * @param {SignaturePacket} signature - The binding signature to verify + * @param {PublicSubkeyPacket| + * SecretSubkeyPacket| + * PublicKeyPacket| + * SecretKeyPacket} key, optional The key to verify the signature + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} True if the binding signature is revoked. + * @async + */ + async isRevoked(signature, key, date = new Date(), config = defaultConfig) { + const primaryKey = this.mainKey.keyPacket; + return isDataRevoked( + primaryKey, enums.signature.subkeyRevocation, { + key: primaryKey, + bind: this.keyPacket + }, this.revocationSignatures, signature, key, date, config + ); + } + + /** + * Verify subkey. Checks for revocation signatures, expiration time + * and valid binding signature. + * @param {Date} date - Use the given date instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} + * @throws {Error} if the subkey is invalid. + * @async + */ + async verify(date = new Date(), config = defaultConfig) { + const primaryKey = this.mainKey.keyPacket; + const dataToVerify = { key: primaryKey, bind: this.keyPacket }; + // check subkey binding signatures + const bindingSignature = await getLatestValidSignature(this.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); + // check binding signature is not revoked + if (bindingSignature.revoked || await this.isRevoked(bindingSignature, null, date, config)) { + throw new Error('Subkey is revoked'); + } + // check for expiration time + if (isDataExpired(this.keyPacket, bindingSignature, date)) { + throw new Error('Subkey is expired'); + } + return bindingSignature; + } + + /** + * Returns the expiration time of the subkey or Infinity if key does not expire. + * Returns null if the subkey is invalid. + * @param {Date} date - Use the given date instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} + * @async + */ + async getExpirationTime(date = new Date(), config = defaultConfig) { + const primaryKey = this.mainKey.keyPacket; + const dataToVerify = { key: primaryKey, bind: this.keyPacket }; + let bindingSignature; + try { + bindingSignature = await getLatestValidSignature(this.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); + } catch (e) { + return null; + } + const keyExpiry = getKeyExpirationTime(this.keyPacket, bindingSignature); + const sigExpiry = bindingSignature.getExpirationTime(); + return keyExpiry < sigExpiry ? keyExpiry : sigExpiry; + } + + /** + * Update subkey with new components from specified subkey + * @param {Subkey} subkey - Source subkey to merge + * @param {Date} [date] - Date to verify validity of signatures + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if update failed + * @async + */ + async update(subkey, date = new Date(), config = defaultConfig) { + const primaryKey = this.mainKey.keyPacket; + if (!this.hasSameFingerprintAs(subkey)) { + throw new Error('Subkey update method: fingerprints of subkeys not equal'); + } + // key packet + if (this.keyPacket.constructor.tag === enums.packet.publicSubkey && + subkey.keyPacket.constructor.tag === enums.packet.secretSubkey) { + this.keyPacket = subkey.keyPacket; + } + // update missing binding signatures + const that = this; + const dataToVerify = { key: primaryKey, bind: that.keyPacket }; + await mergeSignatures(subkey, this, 'bindingSignatures', date, async function(srcBindSig) { + for (let i = 0; i < that.bindingSignatures.length; i++) { + if (that.bindingSignatures[i].issuerKeyID.equals(srcBindSig.issuerKeyID)) { + if (srcBindSig.created > that.bindingSignatures[i].created) { + that.bindingSignatures[i] = srcBindSig; + } + return false; + } + } + try { + await srcBindSig.verify(primaryKey, enums.signature.subkeyBinding, dataToVerify, date, undefined, config); + return true; + } catch (e) { + return false; + } + }); + // revocation signatures + await mergeSignatures(subkey, this, 'revocationSignatures', date, function(srcRevSig) { + return isDataRevoked(primaryKey, enums.signature.subkeyRevocation, dataToVerify, [srcRevSig], undefined, undefined, date, config); + }); + } + + /** + * Revokes the subkey + * @param {SecretKeyPacket} primaryKey - decrypted private primary key for revocation + * @param {Object} reasonForRevocation - optional, object indicating the reason for revocation + * @param {module:enums.reasonForRevocation} reasonForRevocation.flag optional, flag indicating the reason for revocation + * @param {String} reasonForRevocation.string optional, string explaining the reason for revocation + * @param {Date} date - optional, override the creationtime of the revocation signature + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New subkey with revocation signature. + * @async + */ + async revoke( + primaryKey, + { + flag: reasonForRevocationFlag = enums.reasonForRevocation.noReason, + string: reasonForRevocationString = '' + } = {}, + date = new Date(), + config = defaultConfig + ) { + const dataToSign = { key: primaryKey, bind: this.keyPacket }; + const subkey = new Subkey(this.keyPacket, this.mainKey); + subkey.revocationSignatures.push(await createSignaturePacket(dataToSign, null, primaryKey, { + signatureType: enums.signature.subkeyRevocation, + reasonForRevocationFlag: enums.write(enums.reasonForRevocation, reasonForRevocationFlag), + reasonForRevocationString + }, date, undefined, false, config)); + await subkey.update(this); + return subkey; + } + + hasSameFingerprintAs(other) { + return this.keyPacket.hasSameFingerprintAs(other.keyPacket || other); + } +} + +['getKeyID', 'getFingerprint', 'getAlgorithmInfo', 'getCreationTime', 'isDecrypted'].forEach(name => { + Subkey.prototype[name] = + function() { + return this.keyPacket[name](); + }; +}); + +// GPG4Browsers - An OpenPGP implementation in javascript + +// A key revocation certificate can contain the following packets +const allowedRevocationPackets = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); + +/** + * Abstract class that represents an OpenPGP key. Must contain a primary key. + * Can contain additional subkeys, signatures, user ids, user attributes. + * @borrows PublicKeyPacket#getKeyID as Key#getKeyID + * @borrows PublicKeyPacket#getFingerprint as Key#getFingerprint + * @borrows PublicKeyPacket#hasSameFingerprintAs as Key#hasSameFingerprintAs + * @borrows PublicKeyPacket#getAlgorithmInfo as Key#getAlgorithmInfo + * @borrows PublicKeyPacket#getCreationTime as Key#getCreationTime + */ +class Key { + /** + * Transforms packetlist to structured key data + * @param {PacketList} packetlist - The packets that form a key + * @param {Set} disallowedPackets - disallowed packet tags + */ + packetListToStructure(packetlist, disallowedPackets = new Set()) { + let user; + let primaryKeyID; + let subkey; + for (const packet of packetlist) { + const tag = packet.constructor.tag; + if (disallowedPackets.has(tag)) { + throw new Error(`Unexpected packet type: ${tag}`); + } + switch (tag) { + case enums.packet.publicKey: + case enums.packet.secretKey: + if (this.keyPacket) { + throw new Error('Key block contains multiple keys'); + } + this.keyPacket = packet; + primaryKeyID = this.getKeyID(); + if (!primaryKeyID) { + throw new Error('Missing Key ID'); + } + break; + case enums.packet.userID: + case enums.packet.userAttribute: + user = new User(packet, this); + this.users.push(user); + break; + case enums.packet.publicSubkey: + case enums.packet.secretSubkey: + user = null; + subkey = new Subkey(packet, this); + this.subkeys.push(subkey); + break; + case enums.packet.signature: + switch (packet.signatureType) { + case enums.signature.certGeneric: + case enums.signature.certPersona: + case enums.signature.certCasual: + case enums.signature.certPositive: + if (!user) { + util.printDebug('Dropping certification signatures without preceding user packet'); + continue; + } + if (packet.issuerKeyID.equals(primaryKeyID)) { + user.selfCertifications.push(packet); + } else { + user.otherCertifications.push(packet); + } + break; + case enums.signature.certRevocation: + if (user) { + user.revocationSignatures.push(packet); + } else { + this.directSignatures.push(packet); + } + break; + case enums.signature.key: + this.directSignatures.push(packet); + break; + case enums.signature.subkeyBinding: + if (!subkey) { + util.printDebug('Dropping subkey binding signature without preceding subkey packet'); + continue; + } + subkey.bindingSignatures.push(packet); + break; + case enums.signature.keyRevocation: + this.revocationSignatures.push(packet); + break; + case enums.signature.subkeyRevocation: + if (!subkey) { + util.printDebug('Dropping subkey revocation signature without preceding subkey packet'); + continue; + } + subkey.revocationSignatures.push(packet); + break; + } + break; + } + } + } + + /** + * Transforms structured key data to packetlist + * @returns {PacketList} The packets that form a key. + */ + toPacketList() { + const packetlist = new PacketList(); + packetlist.push(this.keyPacket); + packetlist.push(...this.revocationSignatures); + packetlist.push(...this.directSignatures); + this.users.map(user => packetlist.push(...user.toPacketList())); + this.subkeys.map(subkey => packetlist.push(...subkey.toPacketList())); + return packetlist; + } + + /** + * Clones the key object + * @param {Boolean} [deep=false] Whether to return a deep clone + * @returns {Promise} Clone of the key. + */ + clone(deep = false) { + const key = new this.constructor(this.toPacketList()); + if (deep) { + key.getKeys().forEach(k => { + // shallow clone the key packets + k.keyPacket = Object.create( + Object.getPrototypeOf(k.keyPacket), + Object.getOwnPropertyDescriptors(k.keyPacket) + ); + if (!k.keyPacket.isDecrypted()) return; + // deep clone the private params, which are cleared during encryption + const privateParams = {}; + Object.keys(k.keyPacket.privateParams).forEach(name => { + privateParams[name] = new Uint8Array(k.keyPacket.privateParams[name]); + }); + k.keyPacket.privateParams = privateParams; + }); + } + return key; + } + + /** + * Returns an array containing all public or private subkeys matching keyID; + * If no keyID is given, returns all subkeys. + * @param {type/keyID} [keyID] - key ID to look for + * @returns {Array} array of subkeys + */ + getSubkeys(keyID = null) { + const subkeys = this.subkeys.filter(subkey => ( + !keyID || subkey.getKeyID().equals(keyID, true) + )); + return subkeys; + } + + /** + * Returns an array containing all public or private keys matching keyID. + * If no keyID is given, returns all keys, starting with the primary key. + * @param {type/keyid~KeyID} [keyID] - key ID to look for + * @returns {Array} array of keys + */ + getKeys(keyID = null) { + const keys = []; + if (!keyID || this.getKeyID().equals(keyID, true)) { + keys.push(this); + } + return keys.concat(this.getSubkeys(keyID)); + } + + /** + * Returns key IDs of all keys + * @returns {Array} + */ + getKeyIDs() { + return this.getKeys().map(key => key.getKeyID()); + } + + /** + * Returns userIDs + * @returns {Array} Array of userIDs. + */ + getUserIDs() { + return this.users.map(user => { + return user.userID ? user.userID.userID : null; + }).filter(userID => userID !== null); + } + + /** + * Returns binary encoded key + * @returns {Uint8Array} Binary key. + */ + write() { + return this.toPacketList().write(); + } + + /** + * Returns last created key or key by given keyID that is available for signing and verification + * @param {module:type/keyid~KeyID} [keyID] - key ID of a specific key to retrieve + * @param {Date} [date] - use the fiven date date to to check key validity instead of the current date + * @param {Object} [userID] - filter keys for the given user ID + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} signing key + * @throws if no valid signing key was found + * @async + */ + async getSigningKey(keyID = null, date = new Date(), userID = {}, config = defaultConfig) { + await this.verifyPrimaryKey(date, userID, config); + const primaryKey = this.keyPacket; + const subkeys = this.subkeys.slice().sort((a, b) => b.keyPacket.created - a.keyPacket.created); + let exception; + for (const subkey of subkeys) { + if (!keyID || subkey.getKeyID().equals(keyID)) { + try { + await subkey.verify(date, config); + const dataToVerify = { key: primaryKey, bind: subkey.keyPacket }; + const bindingSignature = await getLatestValidSignature( + subkey.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config + ); + if (!isValidSigningKeyPacket(subkey.keyPacket, bindingSignature)) { + continue; + } + if (!bindingSignature.embeddedSignature) { + throw new Error('Missing embedded signature'); + } + // verify embedded signature + await getLatestValidSignature( + [bindingSignature.embeddedSignature], subkey.keyPacket, enums.signature.keyBinding, dataToVerify, date, config + ); + checkKeyRequirements(subkey.keyPacket, config); + return subkey; + } catch (e) { + exception = e; + } + } + } + + try { + const primaryUser = await this.getPrimaryUser(date, userID, config); + if ((!keyID || primaryKey.getKeyID().equals(keyID)) && + isValidSigningKeyPacket(primaryKey, primaryUser.selfCertification, config)) { + checkKeyRequirements(primaryKey, config); + return this; + } + } catch (e) { + exception = e; + } + throw util.wrapError('Could not find valid signing key packet in key ' + this.getKeyID().toHex(), exception); + } + + /** + * Returns last created key or key by given keyID that is available for encryption or decryption + * @param {module:type/keyid~KeyID} [keyID] - key ID of a specific key to retrieve + * @param {Date} [date] - use the fiven date date to to check key validity instead of the current date + * @param {Object} [userID] - filter keys for the given user ID + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} encryption key + * @throws if no valid encryption key was found + * @async + */ + async getEncryptionKey(keyID, date = new Date(), userID = {}, config = defaultConfig) { + await this.verifyPrimaryKey(date, userID, config); + const primaryKey = this.keyPacket; + // V4: by convention subkeys are preferred for encryption service + const subkeys = this.subkeys.slice().sort((a, b) => b.keyPacket.created - a.keyPacket.created); + let exception; + for (const subkey of subkeys) { + if (!keyID || subkey.getKeyID().equals(keyID)) { + try { + await subkey.verify(date, config); + const dataToVerify = { key: primaryKey, bind: subkey.keyPacket }; + const bindingSignature = await getLatestValidSignature(subkey.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); + if (isValidEncryptionKeyPacket(subkey.keyPacket, bindingSignature)) { + checkKeyRequirements(subkey.keyPacket, config); + return subkey; + } + } catch (e) { + exception = e; + } + } + } + + try { + // if no valid subkey for encryption, evaluate primary key + const primaryUser = await this.getPrimaryUser(date, userID, config); + if ((!keyID || primaryKey.getKeyID().equals(keyID)) && + isValidEncryptionKeyPacket(primaryKey, primaryUser.selfCertification)) { + checkKeyRequirements(primaryKey, config); + return this; + } + } catch (e) { + exception = e; + } + throw util.wrapError('Could not find valid encryption key packet in key ' + this.getKeyID().toHex(), exception); + } + + /** + * Checks if a signature on a key is revoked + * @param {SignaturePacket} signature - The signature to verify + * @param {PublicSubkeyPacket| + * SecretSubkeyPacket| + * PublicKeyPacket| + * SecretKeyPacket} key, optional The key to verify the signature + * @param {Date} [date] - Use the given date for verification, instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} True if the certificate is revoked. + * @async + */ + async isRevoked(signature, key, date = new Date(), config = defaultConfig) { + return isDataRevoked( + this.keyPacket, enums.signature.keyRevocation, { key: this.keyPacket }, this.revocationSignatures, signature, key, date, config + ); + } + + /** + * Verify primary key. Checks for revocation signatures, expiration time + * and valid self signature. Throws if the primary key is invalid. + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} [userID] - User ID + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} If key verification failed + * @async + */ + async verifyPrimaryKey(date = new Date(), userID = {}, config = defaultConfig) { + const primaryKey = this.keyPacket; + // check for key revocation signatures + if (await this.isRevoked(null, null, date, config)) { + throw new Error('Primary key is revoked'); + } + // check for valid, unrevoked, unexpired self signature + const { selfCertification } = await this.getPrimaryUser(date, userID, config); + // check for expiration time in binding signatures + if (isDataExpired(primaryKey, selfCertification, date)) { + throw new Error('Primary key is expired'); + } + // check for expiration time in direct signatures + const directSignature = await getLatestValidSignature( + this.directSignatures, primaryKey, enums.signature.key, { key: primaryKey }, date, config + ).catch(() => {}); // invalid signatures are discarded, to avoid breaking the key + + if (directSignature && isDataExpired(primaryKey, directSignature, date)) { + throw new Error('Primary key is expired'); + } + } + + /** + * Returns the expiration date of the primary key, considering self-certifications and direct-key signatures. + * Returns `Infinity` if the key doesn't expire, or `null` if the key is revoked or invalid. + * @param {Object} [userID] - User ID to consider instead of the primary user + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} + * @async + */ + async getExpirationTime(userID, config = defaultConfig) { + let primaryKeyExpiry; + try { + const { selfCertification } = await this.getPrimaryUser(null, userID, config); + const selfSigKeyExpiry = getKeyExpirationTime(this.keyPacket, selfCertification); + const selfSigExpiry = selfCertification.getExpirationTime(); + const directSignature = await getLatestValidSignature( + this.directSignatures, this.keyPacket, enums.signature.key, { key: this.keyPacket }, null, config + ).catch(() => {}); + if (directSignature) { + const directSigKeyExpiry = getKeyExpirationTime(this.keyPacket, directSignature); + // We do not support the edge case where the direct signature expires, since it would invalidate the corresponding key expiration, + // causing a discountinous validy period for the key + primaryKeyExpiry = Math.min(selfSigKeyExpiry, selfSigExpiry, directSigKeyExpiry); + } else { + primaryKeyExpiry = selfSigKeyExpiry < selfSigExpiry ? selfSigKeyExpiry : selfSigExpiry; + } + } catch (e) { + primaryKeyExpiry = null; + } + + return util.normalizeDate(primaryKeyExpiry); + } + + + /** + * Returns primary user and most significant (latest valid) self signature + * - if multiple primary users exist, returns the one with the latest self signature + * - otherwise, returns the user with the latest self signature + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} [userID] - User ID to get instead of the primary user, if it exists + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise<{ + * user: User, + * selfCertification: SignaturePacket + * }>} The primary user and the self signature + * @async + */ + async getPrimaryUser(date = new Date(), userID = {}, config = defaultConfig) { + const primaryKey = this.keyPacket; + const users = []; + let exception; + for (let i = 0; i < this.users.length; i++) { + try { + const user = this.users[i]; + if (!user.userID) { + continue; + } + if ( + (userID.name !== undefined && user.userID.name !== userID.name) || + (userID.email !== undefined && user.userID.email !== userID.email) || + (userID.comment !== undefined && user.userID.comment !== userID.comment) + ) { + throw new Error('Could not find user that matches that user ID'); + } + const dataToVerify = { userID: user.userID, key: primaryKey }; + const selfCertification = await getLatestValidSignature(user.selfCertifications, primaryKey, enums.signature.certGeneric, dataToVerify, date, config); + users.push({ index: i, user, selfCertification }); + } catch (e) { + exception = e; + } + } + if (!users.length) { + throw exception || new Error('Could not find primary user'); + } + await Promise.all(users.map(async function (a) { + return a.user.revoked || a.user.isRevoked(a.selfCertification, null, date, config); + })); + // sort by primary user flag and signature creation time + const primaryUser = users.sort(function(a, b) { + const A = a.selfCertification; + const B = b.selfCertification; + return B.revoked - A.revoked || A.isPrimaryUserID - B.isPrimaryUserID || A.created - B.created; + }).pop(); + const { user, selfCertification: cert } = primaryUser; + if (cert.revoked || await user.isRevoked(cert, null, date, config)) { + throw new Error('Primary user is revoked'); + } + return primaryUser; + } + + /** + * Update key with new components from specified key with same key ID: + * users, subkeys, certificates are merged into the destination key, + * duplicates and expired signatures are ignored. + * + * If the source key is a private key and the destination key is public, + * a private key is returned. + * @param {Key} sourceKey - Source key to merge + * @param {Date} [date] - Date to verify validity of signatures and keys + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} updated key + * @async + */ + async update(sourceKey, date = new Date(), config = defaultConfig) { + if (!this.hasSameFingerprintAs(sourceKey)) { + throw new Error('Primary key fingerprints must be equal to update the key'); + } + if (!this.isPrivate() && sourceKey.isPrivate()) { + // check for equal subkey packets + const equal = (this.subkeys.length === sourceKey.subkeys.length) && + (this.subkeys.every(destSubkey => { + return sourceKey.subkeys.some(srcSubkey => { + return destSubkey.hasSameFingerprintAs(srcSubkey); + }); + })); + if (!equal) { + throw new Error('Cannot update public key with private key if subkeys mismatch'); + } + + return sourceKey.update(this, config); + } + // from here on, either: + // - destination key is private, source key is public + // - the keys are of the same type + // hence we don't need to convert the destination key type + const updatedKey = this.clone(); + // revocation signatures + await mergeSignatures(sourceKey, updatedKey, 'revocationSignatures', date, srcRevSig => { + return isDataRevoked(updatedKey.keyPacket, enums.signature.keyRevocation, updatedKey, [srcRevSig], null, sourceKey.keyPacket, date, config); + }); + // direct signatures + await mergeSignatures(sourceKey, updatedKey, 'directSignatures', date); + // update users + await Promise.all(sourceKey.users.map(async srcUser => { + // multiple users with the same ID/attribute are not explicitly disallowed by the spec + // hence we support them, just in case + const usersToUpdate = updatedKey.users.filter(dstUser => ( + (srcUser.userID && srcUser.userID.equals(dstUser.userID)) || + (srcUser.userAttribute && srcUser.userAttribute.equals(dstUser.userAttribute)) + )); + if (usersToUpdate.length > 0) { + await Promise.all( + usersToUpdate.map(userToUpdate => userToUpdate.update(srcUser, date, config)) + ); + } else { + const newUser = srcUser.clone(); + newUser.mainKey = updatedKey; + updatedKey.users.push(newUser); + } + })); + // update subkeys + await Promise.all(sourceKey.subkeys.map(async srcSubkey => { + // multiple subkeys with same fingerprint might be preset + const subkeysToUpdate = updatedKey.subkeys.filter(dstSubkey => ( + dstSubkey.hasSameFingerprintAs(srcSubkey) + )); + if (subkeysToUpdate.length > 0) { + await Promise.all( + subkeysToUpdate.map(subkeyToUpdate => subkeyToUpdate.update(srcSubkey, date, config)) + ); + } else { + const newSubkey = srcSubkey.clone(); + newSubkey.mainKey = updatedKey; + updatedKey.subkeys.push(newSubkey); + } + })); + + return updatedKey; + } + + /** + * Get revocation certificate from a revoked key. + * (To get a revocation certificate for an unrevoked key, call revoke() first.) + * @param {Date} date - Use the given date instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} Armored revocation certificate. + * @async + */ + async getRevocationCertificate(date = new Date(), config = defaultConfig) { + const dataToVerify = { key: this.keyPacket }; + const revocationSignature = await getLatestValidSignature(this.revocationSignatures, this.keyPacket, enums.signature.keyRevocation, dataToVerify, date, config); + const packetlist = new PacketList(); + packetlist.push(revocationSignature); + return armor(enums.armor.publicKey, packetlist.write(), null, null, 'This is a revocation certificate'); + } + + /** + * Applies a revocation certificate to a key + * This adds the first signature packet in the armored text to the key, + * if it is a valid revocation signature. + * @param {String} revocationCertificate - armored revocation certificate + * @param {Date} [date] - Date to verify the certificate + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} Revoked key. + * @async + */ + async applyRevocationCertificate(revocationCertificate, date = new Date(), config = defaultConfig) { + const input = await unarmor(revocationCertificate, config); + const packetlist = await PacketList.fromBinary(input.data, allowedRevocationPackets, config); + const revocationSignature = packetlist.findPacket(enums.packet.signature); + if (!revocationSignature || revocationSignature.signatureType !== enums.signature.keyRevocation) { + throw new Error('Could not find revocation signature packet'); + } + if (!revocationSignature.issuerKeyID.equals(this.getKeyID())) { + throw new Error('Revocation signature does not match key'); + } + try { + await revocationSignature.verify(this.keyPacket, enums.signature.keyRevocation, { key: this.keyPacket }, date, undefined, config); + } catch (e) { + throw util.wrapError('Could not verify revocation signature', e); + } + const key = this.clone(); + key.revocationSignatures.push(revocationSignature); + return key; + } + + /** + * Signs primary user of key + * @param {Array} privateKeys - decrypted private keys for signing + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} [userID] - User ID to get instead of the primary user, if it exists + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} Key with new certificate signature. + * @async + */ + async signPrimaryUser(privateKeys, date, userID, config = defaultConfig) { + const { index, user } = await this.getPrimaryUser(date, userID, config); + const userSign = await user.certify(privateKeys, date, config); + const key = this.clone(); + key.users[index] = userSign; + return key; + } + + /** + * Signs all users of key + * @param {Array} privateKeys - decrypted private keys for signing + * @param {Date} [date] - Use the given date for signing, instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} Key with new certificate signature. + * @async + */ + async signAllUsers(privateKeys, date = new Date(), config = defaultConfig) { + const key = this.clone(); + key.users = await Promise.all(this.users.map(function(user) { + return user.certify(privateKeys, date, config); + })); + return key; + } + + /** + * Verifies primary user of key + * - if no arguments are given, verifies the self certificates; + * - otherwise, verifies all certificates signed with given keys. + * @param {Array} [verificationKeys] - array of keys to verify certificate signatures, instead of the primary key + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} [userID] - User ID to get instead of the primary user, if it exists + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise>} List of signer's keyID and validity of signature. + * Signature validity is null if the verification keys do not correspond to the certificate. + * @async + */ + async verifyPrimaryUser(verificationKeys, date = new Date(), userID, config = defaultConfig) { + const primaryKey = this.keyPacket; + const { user } = await this.getPrimaryUser(date, userID, config); + const results = verificationKeys ? + await user.verifyAllCertifications(verificationKeys, date, config) : + [{ keyID: primaryKey.getKeyID(), valid: await user.verify(date, config).catch(() => false) }]; + return results; + } + + /** + * Verifies all users of key + * - if no arguments are given, verifies the self certificates; + * - otherwise, verifies all certificates signed with given keys. + * @param {Array} [verificationKeys] - array of keys to verify certificate signatures + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise>} List of userID, signer's keyID and validity of signature. + * Signature validity is null if the verification keys do not correspond to the certificate. + * @async + */ + async verifyAllUsers(verificationKeys, date = new Date(), config = defaultConfig) { + const primaryKey = this.keyPacket; + const results = []; + await Promise.all(this.users.map(async user => { + const signatures = verificationKeys ? + await user.verifyAllCertifications(verificationKeys, date, config) : + [{ keyID: primaryKey.getKeyID(), valid: await user.verify(date, config).catch(() => false) }]; + + results.push(...signatures.map( + signature => ({ + userID: user.userID.userID, + keyID: signature.keyID, + valid: signature.valid + })) + ); + })); + return results; + } +} + +['getKeyID', 'getFingerprint', 'getAlgorithmInfo', 'getCreationTime', 'hasSameFingerprintAs'].forEach(name => { + Key.prototype[name] = + Subkey.prototype[name]; +}); + +/** + * Creates a PublicKey or PrivateKey depending on the packetlist in input + * @param {PacketList} - packets to parse + * @return {Key} parsed key + * @throws if no key packet was found + */ +function createKey(packetlist) { + for (const packet of packetlist) { + switch (packet.constructor.tag) { + case enums.packet.secretKey: + return new PrivateKey(packetlist); + case enums.packet.publicKey: + return new PublicKey(packetlist); + } + } + throw new Error('No key packet found'); +} + +// This library is free software; you can redistribute it and/or + +/** + * Class that represents an OpenPGP Public Key + */ +class PublicKey extends Key { + /** + * @param {PacketList} packetlist - The packets that form this key + */ + constructor(packetlist) { + super(); + this.keyPacket = null; + this.revocationSignatures = []; + this.directSignatures = []; + this.users = []; + this.subkeys = []; + if (packetlist) { + this.packetListToStructure(packetlist, new Set([enums.packet.secretKey, enums.packet.secretSubkey])); + if (!this.keyPacket) { + throw new Error('Invalid key: missing public-key packet'); + } + } + } + + /** + * Returns true if this is a private key + * @returns {false} + */ + isPrivate() { + return false; + } + + /** + * Returns key as public key (shallow copy) + * @returns {PublicKey} New public Key + */ + toPublic() { + return this; + } + + /** + * Returns ASCII armored text of key + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {ReadableStream} ASCII armor. + */ + armor(config = defaultConfig) { + return armor(enums.armor.publicKey, this.toPacketList().write(), undefined, undefined, undefined, config); + } +} + +/** + * Class that represents an OpenPGP Private key + */ +class PrivateKey extends PublicKey { + /** + * @param {PacketList} packetlist - The packets that form this key + */ + constructor(packetlist) { + super(); + this.packetListToStructure(packetlist, new Set([enums.packet.publicKey, enums.packet.publicSubkey])); + if (!this.keyPacket) { + throw new Error('Invalid key: missing private-key packet'); + } + } + + /** + * Returns true if this is a private key + * @returns {Boolean} + */ + isPrivate() { + return true; + } + + /** + * Returns key as public key (shallow copy) + * @returns {PublicKey} New public Key + */ + toPublic() { + const packetlist = new PacketList(); + const keyPackets = this.toPacketList(); + for (const keyPacket of keyPackets) { + switch (keyPacket.constructor.tag) { + case enums.packet.secretKey: { + const pubKeyPacket = PublicKeyPacket.fromSecretKeyPacket(keyPacket); + packetlist.push(pubKeyPacket); + break; + } + case enums.packet.secretSubkey: { + const pubSubkeyPacket = PublicSubkeyPacket.fromSecretSubkeyPacket(keyPacket); + packetlist.push(pubSubkeyPacket); + break; + } + default: + packetlist.push(keyPacket); + } + } + return new PublicKey(packetlist); + } + + /** + * Returns ASCII armored text of key + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {ReadableStream} ASCII armor. + */ + armor(config = defaultConfig) { + return armor(enums.armor.privateKey, this.toPacketList().write(), undefined, undefined, undefined, config); + } + + /** + * Returns all keys that are available for decryption, matching the keyID when given + * This is useful to retrieve keys for session key decryption + * @param {module:type/keyid~KeyID} keyID, optional + * @param {Date} date, optional + * @param {String} userID, optional + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise>} Array of decryption keys. + * @async + */ + async getDecryptionKeys(keyID, date = new Date(), userID = {}, config = defaultConfig) { + const primaryKey = this.keyPacket; + const keys = []; + for (let i = 0; i < this.subkeys.length; i++) { + if (!keyID || this.subkeys[i].getKeyID().equals(keyID, true)) { + try { + const dataToVerify = { key: primaryKey, bind: this.subkeys[i].keyPacket }; + const bindingSignature = await getLatestValidSignature(this.subkeys[i].bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); + if (isValidDecryptionKeyPacket(bindingSignature, config)) { + keys.push(this.subkeys[i]); + } + } catch (e) {} + } + } + + // evaluate primary key + const primaryUser = await this.getPrimaryUser(date, userID, config); + if ((!keyID || primaryKey.getKeyID().equals(keyID, true)) && + isValidDecryptionKeyPacket(primaryUser.selfCertification, config)) { + keys.push(this); + } + + return keys; + } + + /** + * Returns true if the primary key or any subkey is decrypted. + * A dummy key is considered encrypted. + */ + isDecrypted() { + return this.getKeys().some(({ keyPacket }) => keyPacket.isDecrypted()); + } + + /** + * Check whether the private and public primary key parameters correspond + * Together with verification of binding signatures, this guarantees key integrity + * In case of gnu-dummy primary key, it is enough to validate any signing subkeys + * otherwise all encryption subkeys are validated + * If only gnu-dummy keys are found, we cannot properly validate so we throw an error + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if validation was not successful and the key cannot be trusted + * @async + */ + async validate(config = defaultConfig) { + if (!this.isPrivate()) { + throw new Error('Cannot validate a public key'); + } + + let signingKeyPacket; + if (!this.keyPacket.isDummy()) { + signingKeyPacket = this.keyPacket; + } else { + /** + * It is enough to validate any signing keys + * since its binding signatures are also checked + */ + const signingKey = await this.getSigningKey(null, null, undefined, { ...config, rejectPublicKeyAlgorithms: new Set(), minRSABits: 0 }); + // This could again be a dummy key + if (signingKey && !signingKey.keyPacket.isDummy()) { + signingKeyPacket = signingKey.keyPacket; + } + } + + if (signingKeyPacket) { + return signingKeyPacket.validate(); + } else { + const keys = this.getKeys(); + const allDummies = keys.map(key => key.keyPacket.isDummy()).every(Boolean); + if (allDummies) { + throw new Error('Cannot validate an all-gnu-dummy key'); + } + + return Promise.all(keys.map(async key => key.keyPacket.validate())); + } + } + + /** + * Clear private key parameters + */ + clearPrivateParams() { + this.getKeys().forEach(({ keyPacket }) => { + if (keyPacket.isDecrypted()) { + keyPacket.clearPrivateParams(); + } + }); + } + + /** + * Revokes the key + * @param {Object} reasonForRevocation - optional, object indicating the reason for revocation + * @param {module:enums.reasonForRevocation} reasonForRevocation.flag optional, flag indicating the reason for revocation + * @param {String} reasonForRevocation.string optional, string explaining the reason for revocation + * @param {Date} date - optional, override the creationtime of the revocation signature + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New key with revocation signature. + * @async + */ + async revoke( + { + flag: reasonForRevocationFlag = enums.reasonForRevocation.noReason, + string: reasonForRevocationString = '' + } = {}, + date = new Date(), + config = defaultConfig + ) { + if (!this.isPrivate()) { + throw new Error('Need private key for revoking'); + } + const dataToSign = { key: this.keyPacket }; + const key = this.clone(); + key.revocationSignatures.push(await createSignaturePacket(dataToSign, null, this.keyPacket, { + signatureType: enums.signature.keyRevocation, + reasonForRevocationFlag: enums.write(enums.reasonForRevocation, reasonForRevocationFlag), + reasonForRevocationString + }, date, undefined, undefined, config)); + return key; + } + + + /** + * Generates a new OpenPGP subkey, and returns a clone of the Key object with the new subkey added. + * Supports RSA and ECC keys. Defaults to the algorithm and bit size/curve of the primary key. DSA primary keys default to RSA subkeys. + * @param {ecc|rsa} options.type The subkey algorithm: ECC or RSA + * @param {String} options.curve (optional) Elliptic curve for ECC keys + * @param {Integer} options.rsaBits (optional) Number of bits for RSA subkeys + * @param {Number} options.keyExpirationTime (optional) Number of seconds from the key creation time after which the key expires + * @param {Date} options.date (optional) Override the creation date of the key and the key signatures + * @param {Boolean} options.sign (optional) Indicates whether the subkey should sign rather than encrypt. Defaults to false + * @param {Object} options.config (optional) custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} + * @async + */ + async addSubkey(options = {}) { + const config = { ...defaultConfig, ...options.config }; + if (options.passphrase) { + throw new Error('Subkey could not be encrypted here, please encrypt whole key'); + } + if (options.rsaBits < config.minRSABits) { + throw new Error(`rsaBits should be at least ${config.minRSABits}, got: ${options.rsaBits}`); + } + const secretKeyPacket = this.keyPacket; + if (secretKeyPacket.isDummy()) { + throw new Error('Cannot add subkey to gnu-dummy primary key'); + } + if (!secretKeyPacket.isDecrypted()) { + throw new Error('Key is not decrypted'); + } + const defaultOptions = secretKeyPacket.getAlgorithmInfo(); + defaultOptions.type = defaultOptions.curve ? 'ecc' : 'rsa'; // DSA keys default to RSA + defaultOptions.rsaBits = defaultOptions.bits || 4096; + defaultOptions.curve = defaultOptions.curve || 'curve25519'; + options = sanitizeKeyOptions(options, defaultOptions); + const keyPacket = await generateSecretSubkey(options); + checkKeyRequirements(keyPacket, config); + const bindingSignature = await createBindingSignature(keyPacket, secretKeyPacket, options, config); + const packetList = this.toPacketList(); + packetList.push(keyPacket, bindingSignature); + return new PrivateKey(packetList); + } +} + +// OpenPGP.js - An OpenPGP implementation in javascript + +// A Key can contain the following packets +const allowedKeyPackets = /*#__PURE__*/ util.constructAllowedPackets([ + PublicKeyPacket, + PublicSubkeyPacket, + SecretKeyPacket, + SecretSubkeyPacket, + UserIDPacket, + UserAttributePacket, + SignaturePacket +]); + +/** + * Generates a new OpenPGP key. Supports RSA and ECC keys. + * By default, primary and subkeys will be of same type. + * @param {ecc|rsa} options.type The primary key algorithm type: ECC or RSA + * @param {String} options.curve Elliptic curve for ECC keys + * @param {Integer} options.rsaBits Number of bits for RSA keys + * @param {Array} options.userIDs User IDs as strings or objects: 'Jo Doe ' or { name:'Jo Doe', email:'info@jo.com' } + * @param {String} options.passphrase Passphrase used to encrypt the resulting private key + * @param {Number} options.keyExpirationTime (optional) Number of seconds from the key creation time after which the key expires + * @param {Date} options.date Creation date of the key and the key signatures + * @param {Object} config - Full configuration + * @param {Array} options.subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}] + * sign parameter defaults to false, and indicates whether the subkey should sign rather than encrypt + * @returns {Promise<{{ key: PrivateKey, revocationCertificate: String }}>} + * @async + * @static + * @private + */ +async function generate$2(options, config) { + options.sign = true; // primary key is always a signing key + options = sanitizeKeyOptions(options); + options.subkeys = options.subkeys.map((subkey, index) => sanitizeKeyOptions(options.subkeys[index], options)); + let promises = [generateSecretKey(options, config)]; + promises = promises.concat(options.subkeys.map(options => generateSecretSubkey(options, config))); + const packets = await Promise.all(promises); + + const key = await wrapKeyObject(packets[0], packets.slice(1), options, config); + const revocationCertificate = await key.getRevocationCertificate(options.date, config); + key.revocationSignatures = []; + return { key, revocationCertificate }; +} + +/** + * Reformats and signs an OpenPGP key with a given User ID. Currently only supports RSA keys. + * @param {PrivateKey} options.privateKey The private key to reformat + * @param {Array} options.userIDs User IDs as strings or objects: 'Jo Doe ' or { name:'Jo Doe', email:'info@jo.com' } + * @param {String} options.passphrase Passphrase used to encrypt the resulting private key + * @param {Number} options.keyExpirationTime Number of seconds from the key creation time after which the key expires + * @param {Date} options.date Override the creation date of the key signatures + * @param {Array} options.subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}] + * @param {Object} config - Full configuration + * + * @returns {Promise<{{ key: PrivateKey, revocationCertificate: String }}>} + * @async + * @static + * @private + */ +async function reformat(options, config) { + options = sanitize(options); + const { privateKey } = options; + + if (!privateKey.isPrivate()) { + throw new Error('Cannot reformat a public key'); + } + + if (privateKey.keyPacket.isDummy()) { + throw new Error('Cannot reformat a gnu-dummy primary key'); + } + + const isDecrypted = privateKey.getKeys().every(({ keyPacket }) => keyPacket.isDecrypted()); + if (!isDecrypted) { + throw new Error('Key is not decrypted'); + } + + const secretKeyPacket = privateKey.keyPacket; + + if (!options.subkeys) { + options.subkeys = await Promise.all(privateKey.subkeys.map(async subkey => { + const secretSubkeyPacket = subkey.keyPacket; + const dataToVerify = { key: secretKeyPacket, bind: secretSubkeyPacket }; + const bindingSignature = await ( + getLatestValidSignature(subkey.bindingSignatures, secretKeyPacket, enums.signature.subkeyBinding, dataToVerify, null, config) + ).catch(() => ({})); + return { + sign: bindingSignature.keyFlags && (bindingSignature.keyFlags[0] & enums.keyFlags.signData) + }; + })); + } + + const secretSubkeyPackets = privateKey.subkeys.map(subkey => subkey.keyPacket); + if (options.subkeys.length !== secretSubkeyPackets.length) { + throw new Error('Number of subkey options does not match number of subkeys'); + } + + options.subkeys = options.subkeys.map(subkeyOptions => sanitize(subkeyOptions, options)); + + const key = await wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options, config); + const revocationCertificate = await key.getRevocationCertificate(options.date, config); + key.revocationSignatures = []; + return { key, revocationCertificate }; + + function sanitize(options, subkeyDefaults = {}) { + options.keyExpirationTime = options.keyExpirationTime || subkeyDefaults.keyExpirationTime; + options.passphrase = util.isString(options.passphrase) ? options.passphrase : subkeyDefaults.passphrase; + options.date = options.date || subkeyDefaults.date; + + return options; + } +} + +/** + * Construct PrivateKey object from the given key packets, add certification signatures and set passphrase protection + * The new key includes a revocation certificate that must be removed before returning the key, otherwise the key is considered revoked. + * @param {SecretKeyPacket} secretKeyPacket + * @param {SecretSubkeyPacket} secretSubkeyPackets + * @param {Object} options + * @param {Object} config - Full configuration + * @returns {PrivateKey} + */ +async function wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options, config) { + // set passphrase protection + if (options.passphrase) { + await secretKeyPacket.encrypt(options.passphrase, config); + } + + await Promise.all(secretSubkeyPackets.map(async function(secretSubkeyPacket, index) { + const subkeyPassphrase = options.subkeys[index].passphrase; + if (subkeyPassphrase) { + await secretSubkeyPacket.encrypt(subkeyPassphrase, config); + } + })); + + const packetlist = new PacketList(); + packetlist.push(secretKeyPacket); + + await Promise.all(options.userIDs.map(async function(userID, index) { + function createPreferredAlgos(algos, preferredAlgo) { + return [preferredAlgo, ...algos.filter(algo => algo !== preferredAlgo)]; + } + + const userIDPacket = UserIDPacket.fromObject(userID); + const dataToSign = {}; + dataToSign.userID = userIDPacket; + dataToSign.key = secretKeyPacket; + const signaturePacket = new SignaturePacket(); + signaturePacket.signatureType = enums.signature.certGeneric; + signaturePacket.publicKeyAlgorithm = secretKeyPacket.algorithm; + signaturePacket.hashAlgorithm = await getPreferredHashAlgo$1(null, secretKeyPacket, undefined, undefined, config); + signaturePacket.keyFlags = [enums.keyFlags.certifyKeys | enums.keyFlags.signData]; + signaturePacket.preferredSymmetricAlgorithms = createPreferredAlgos([ + // prefer aes256, aes128, then aes192 (no WebCrypto support: https://www.chromium.org/blink/webcrypto#TOC-AES-support) + enums.symmetric.aes256, + enums.symmetric.aes128, + enums.symmetric.aes192 + ], config.preferredSymmetricAlgorithm); + if (config.aeadProtect) { + signaturePacket.preferredAEADAlgorithms = createPreferredAlgos([ + enums.aead.eax, + enums.aead.ocb + ], config.preferredAEADAlgorithm); + } + signaturePacket.preferredHashAlgorithms = createPreferredAlgos([ + // prefer fast asm.js implementations (SHA-256) + enums.hash.sha256, + enums.hash.sha512 + ], config.preferredHashAlgorithm); + signaturePacket.preferredCompressionAlgorithms = createPreferredAlgos([ + enums.compression.zlib, + enums.compression.zip, + enums.compression.uncompressed + ], config.preferredCompressionAlgorithm); + if (index === 0) { + signaturePacket.isPrimaryUserID = true; + } + // integrity protection always enabled + signaturePacket.features = [0]; + signaturePacket.features[0] |= enums.features.modificationDetection; + if (config.aeadProtect) { + signaturePacket.features[0] |= enums.features.aead; + } + if (config.v5Keys) { + signaturePacket.features[0] |= enums.features.v5Keys; + } + if (options.keyExpirationTime > 0) { + signaturePacket.keyExpirationTime = options.keyExpirationTime; + signaturePacket.keyNeverExpires = false; + } + await signaturePacket.sign(secretKeyPacket, dataToSign, options.date); + + return { userIDPacket, signaturePacket }; + })).then(list => { + list.forEach(({ userIDPacket, signaturePacket }) => { + packetlist.push(userIDPacket); + packetlist.push(signaturePacket); + }); + }); + + await Promise.all(secretSubkeyPackets.map(async function(secretSubkeyPacket, index) { + const subkeyOptions = options.subkeys[index]; + const subkeySignaturePacket = await createBindingSignature(secretSubkeyPacket, secretKeyPacket, subkeyOptions, config); + return { secretSubkeyPacket, subkeySignaturePacket }; + })).then(packets => { + packets.forEach(({ secretSubkeyPacket, subkeySignaturePacket }) => { + packetlist.push(secretSubkeyPacket); + packetlist.push(subkeySignaturePacket); + }); + }); + + // Add revocation signature packet for creating a revocation certificate. + // This packet should be removed before returning the key. + const dataToSign = { key: secretKeyPacket }; + packetlist.push(await createSignaturePacket(dataToSign, null, secretKeyPacket, { + signatureType: enums.signature.keyRevocation, + reasonForRevocationFlag: enums.reasonForRevocation.noReason, + reasonForRevocationString: '' + }, options.date, undefined, undefined, config)); + + if (options.passphrase) { + secretKeyPacket.clearPrivateParams(); + } + + await Promise.all(secretSubkeyPackets.map(async function(secretSubkeyPacket, index) { + const subkeyPassphrase = options.subkeys[index].passphrase; + if (subkeyPassphrase) { + secretSubkeyPacket.clearPrivateParams(); + } + })); + + return new PrivateKey(packetlist); +} + +/** + * Reads an (optionally armored) OpenPGP key and returns a key object + * @param {Object} options + * @param {String} [options.armoredKey] - Armored key to be parsed + * @param {Uint8Array} [options.binaryKey] - Binary key to be parsed + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} Key object. + * @async + * @static + */ +async function readKey({ armoredKey, binaryKey, config, ...rest }) { + config = { ...defaultConfig, ...config }; + if (!armoredKey && !binaryKey) { + throw new Error('readKey: must pass options object containing `armoredKey` or `binaryKey`'); + } + if (armoredKey && !util.isString(armoredKey)) { + throw new Error('readKey: options.armoredKey must be a string'); + } + if (binaryKey && !util.isUint8Array(binaryKey)) { + throw new Error('readKey: options.binaryKey must be a Uint8Array'); + } + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + let input; + if (armoredKey) { + const { type, data } = await unarmor(armoredKey, config); + if (!(type === enums.armor.publicKey || type === enums.armor.privateKey)) { + throw new Error('Armored text not of type key'); + } + input = data; + } else { + input = binaryKey; + } + const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); + return createKey(packetlist); +} + +/** + * Reads an (optionally armored) OpenPGP private key and returns a PrivateKey object + * @param {Object} options + * @param {String} [options.armoredKey] - Armored key to be parsed + * @param {Uint8Array} [options.binaryKey] - Binary key to be parsed + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} Key object. + * @async + * @static + */ +async function readPrivateKey({ armoredKey, binaryKey, config, ...rest }) { + config = { ...defaultConfig, ...config }; + if (!armoredKey && !binaryKey) { + throw new Error('readPrivateKey: must pass options object containing `armoredKey` or `binaryKey`'); + } + if (armoredKey && !util.isString(armoredKey)) { + throw new Error('readPrivateKey: options.armoredKey must be a string'); + } + if (binaryKey && !util.isUint8Array(binaryKey)) { + throw new Error('readPrivateKey: options.binaryKey must be a Uint8Array'); + } + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + let input; + if (armoredKey) { + const { type, data } = await unarmor(armoredKey, config); + if (!(type === enums.armor.privateKey)) { + throw new Error('Armored text not of type private key'); + } + input = data; + } else { + input = binaryKey; + } + const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); + return new PrivateKey(packetlist); +} + +/** + * Reads an (optionally armored) OpenPGP key block and returns a list of key objects + * @param {Object} options + * @param {String} [options.armoredKeys] - Armored keys to be parsed + * @param {Uint8Array} [options.binaryKeys] - Binary keys to be parsed + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise>} Key objects. + * @async + * @static + */ +async function readKeys({ armoredKeys, binaryKeys, config, ...rest }) { + config = { ...defaultConfig, ...config }; + let input = armoredKeys || binaryKeys; + if (!input) { + throw new Error('readKeys: must pass options object containing `armoredKeys` or `binaryKeys`'); + } + if (armoredKeys && !util.isString(armoredKeys)) { + throw new Error('readKeys: options.armoredKeys must be a string'); + } + if (binaryKeys && !util.isUint8Array(binaryKeys)) { + throw new Error('readKeys: options.binaryKeys must be a Uint8Array'); + } + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + if (armoredKeys) { + const { type, data } = await unarmor(armoredKeys, config); + if (type !== enums.armor.publicKey && type !== enums.armor.privateKey) { + throw new Error('Armored text not of type key'); + } + input = data; + } + const keys = []; + const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); + const keyIndex = packetlist.indexOfTag(enums.packet.publicKey, enums.packet.secretKey); + if (keyIndex.length === 0) { + throw new Error('No key packet found'); + } + for (let i = 0; i < keyIndex.length; i++) { + const oneKeyList = packetlist.slice(keyIndex[i], keyIndex[i + 1]); + const newKey = createKey(oneKeyList); + keys.push(newKey); + } + return keys; +} + +/** + * Reads an (optionally armored) OpenPGP private key block and returns a list of PrivateKey objects + * @param {Object} options + * @param {String} [options.armoredKeys] - Armored keys to be parsed + * @param {Uint8Array} [options.binaryKeys] - Binary keys to be parsed + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise>} Key objects. + * @async + * @static + */ +async function readPrivateKeys({ armoredKeys, binaryKeys, config }) { + config = { ...defaultConfig, ...config }; + let input = armoredKeys || binaryKeys; + if (!input) { + throw new Error('readPrivateKeys: must pass options object containing `armoredKeys` or `binaryKeys`'); + } + if (armoredKeys && !util.isString(armoredKeys)) { + throw new Error('readPrivateKeys: options.armoredKeys must be a string'); + } + if (binaryKeys && !util.isUint8Array(binaryKeys)) { + throw new Error('readPrivateKeys: options.binaryKeys must be a Uint8Array'); + } + if (armoredKeys) { + const { type, data } = await unarmor(armoredKeys, config); + if (type !== enums.armor.privateKey) { + throw new Error('Armored text not of type private key'); + } + input = data; + } + const keys = []; + const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); + const keyIndex = packetlist.indexOfTag(enums.packet.secretKey); + if (keyIndex.length === 0) { + throw new Error('No secret key packet found'); + } + for (let i = 0; i < keyIndex.length; i++) { + const oneKeyList = packetlist.slice(keyIndex[i], keyIndex[i + 1]); + const newKey = new PrivateKey(oneKeyList); + keys.push(newKey); + } + return keys; +} + +// GPG4Browsers - An OpenPGP implementation in javascript + +// A Message can contain the following packets +const allowedMessagePackets = /*#__PURE__*/ util.constructAllowedPackets([ + LiteralDataPacket, + CompressedDataPacket, + AEADEncryptedDataPacket, + SymEncryptedIntegrityProtectedDataPacket, + SymmetricallyEncryptedDataPacket, + PublicKeyEncryptedSessionKeyPacket, + SymEncryptedSessionKeyPacket, + OnePassSignaturePacket, + SignaturePacket +]); +// A SKESK packet can contain the following packets +const allowedSymSessionKeyPackets = /*#__PURE__*/ util.constructAllowedPackets([SymEncryptedSessionKeyPacket]); +// A detached signature can contain the following packets +const allowedDetachedSignaturePackets = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); + +/** + * Class that represents an OpenPGP message. + * Can be an encrypted message, signed message, compressed message or literal message + * See {@link https://tools.ietf.org/html/rfc4880#section-11.3} + */ +class Message { + /** + * @param {PacketList} packetlist - The packets that form this message + */ + constructor(packetlist) { + this.packets = packetlist || new PacketList(); + } + + /** + * Returns the key IDs of the keys to which the session key is encrypted + * @returns {Array} Array of keyID objects. + */ + getEncryptionKeyIDs() { + const keyIDs = []; + const pkESKeyPacketlist = this.packets.filterByTag(enums.packet.publicKeyEncryptedSessionKey); + pkESKeyPacketlist.forEach(function(packet) { + keyIDs.push(packet.publicKeyID); + }); + return keyIDs; + } + + /** + * Returns the key IDs of the keys that signed the message + * @returns {Array} Array of keyID objects. + */ + getSigningKeyIDs() { + const msg = this.unwrapCompressed(); + // search for one pass signatures + const onePassSigList = msg.packets.filterByTag(enums.packet.onePassSignature); + if (onePassSigList.length > 0) { + return onePassSigList.map(packet => packet.issuerKeyID); + } + // if nothing found look for signature packets + const signatureList = msg.packets.filterByTag(enums.packet.signature); + return signatureList.map(packet => packet.issuerKeyID); + } + + /** + * Decrypt the message. Either a private key, a session key, or a password must be specified. + * @param {Array} [decryptionKeys] - Private keys with decrypted secret data + * @param {Array} [passwords] - Passwords used to decrypt + * @param {Array} [sessionKeys] - Session keys in the form: { data:Uint8Array, algorithm:String, [aeadAlgorithm:String] } + * @param {Date} [date] - Use the given date for key verification instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New message with decrypted content. + * @async + */ + async decrypt(decryptionKeys, passwords, sessionKeys, date = new Date(), config = defaultConfig) { + const sessionKeyObjects = sessionKeys || await this.decryptSessionKeys(decryptionKeys, passwords, date, config); + + const symEncryptedPacketlist = this.packets.filterByTag( + enums.packet.symmetricallyEncryptedData, + enums.packet.symEncryptedIntegrityProtectedData, + enums.packet.aeadEncryptedData + ); + + if (symEncryptedPacketlist.length === 0) { + return this; + } + + const symEncryptedPacket = symEncryptedPacketlist[0]; + let exception = null; + const decryptedPromise = Promise.all(sessionKeyObjects.map(async ({ algorithm: algorithmName, data }) => { + if (!util.isUint8Array(data) || !util.isString(algorithmName)) { + throw new Error('Invalid session key for decryption.'); + } + + try { + const algo = enums.write(enums.symmetric, algorithmName); + await symEncryptedPacket.decrypt(algo, data, config); + } catch (e) { + util.printDebugError(e); + exception = e; + } + })); + // We don't await stream.cancel here because it only returns when the other copy is canceled too. + cancel(symEncryptedPacket.encrypted); // Don't keep copy of encrypted data in memory. + symEncryptedPacket.encrypted = null; + await decryptedPromise; + + if (!symEncryptedPacket.packets || !symEncryptedPacket.packets.length) { + throw exception || new Error('Decryption failed.'); + } + + const resultMsg = new Message(symEncryptedPacket.packets); + symEncryptedPacket.packets = new PacketList(); // remove packets after decryption + + return resultMsg; + } + + /** + * Decrypt encrypted session keys either with private keys or passwords. + * @param {Array} [decryptionKeys] - Private keys with decrypted secret data + * @param {Array} [passwords] - Passwords used to decrypt + * @param {Date} [date] - Use the given date for key verification, instead of current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise>} array of object with potential sessionKey, algorithm pairs + * @async + */ + async decryptSessionKeys(decryptionKeys, passwords, date = new Date(), config = defaultConfig) { + let decryptedSessionKeyPackets = []; + + let exception; + if (passwords) { + const skeskPackets = this.packets.filterByTag(enums.packet.symEncryptedSessionKey); + if (skeskPackets.length === 0) { + throw new Error('No symmetrically encrypted session key packet found.'); + } + await Promise.all(passwords.map(async function(password, i) { + let packets; + if (i) { + packets = await PacketList.fromBinary(skeskPackets.write(), allowedSymSessionKeyPackets, config); + } else { + packets = skeskPackets; + } + await Promise.all(packets.map(async function(skeskPacket) { + try { + await skeskPacket.decrypt(password); + decryptedSessionKeyPackets.push(skeskPacket); + } catch (err) { + util.printDebugError(err); + } + })); + })); + } else if (decryptionKeys) { + const pkeskPackets = this.packets.filterByTag(enums.packet.publicKeyEncryptedSessionKey); + if (pkeskPackets.length === 0) { + throw new Error('No public key encrypted session key packet found.'); + } + await Promise.all(pkeskPackets.map(async function(pkeskPacket) { + await Promise.all(decryptionKeys.map(async function(decryptionKey) { + let algos = [ + enums.symmetric.aes256, // Old OpenPGP.js default fallback + enums.symmetric.aes128, // RFC4880bis fallback + enums.symmetric.tripledes, // RFC4880 fallback + enums.symmetric.cast5 // Golang OpenPGP fallback + ]; + try { + const primaryUser = await decryptionKey.getPrimaryUser(date, undefined, config); // TODO: Pass userID from somewhere. + if (primaryUser.selfCertification.preferredSymmetricAlgorithms) { + algos = algos.concat(primaryUser.selfCertification.preferredSymmetricAlgorithms); + } + } catch (e) {} + + // do not check key expiration to allow decryption of old messages + const decryptionKeyPackets = (await decryptionKey.getDecryptionKeys(pkeskPacket.publicKeyID, null, undefined, config)).map(key => key.keyPacket); + await Promise.all(decryptionKeyPackets.map(async function(decryptionKeyPacket) { + if (!decryptionKeyPacket || decryptionKeyPacket.isDummy()) { + return; + } + if (!decryptionKeyPacket.isDecrypted()) { + throw new Error('Decryption key is not decrypted.'); + } + + // To hinder CCA attacks against PKCS1, we carry out a constant-time decryption flow if the `constantTimePKCS1Decryption` config option is set. + const doConstantTimeDecryption = config.constantTimePKCS1Decryption && ( + pkeskPacket.publicKeyAlgorithm === enums.publicKey.rsaEncrypt || + pkeskPacket.publicKeyAlgorithm === enums.publicKey.rsaEncryptSign || + pkeskPacket.publicKeyAlgorithm === enums.publicKey.rsaSign || + pkeskPacket.publicKeyAlgorithm === enums.publicKey.elgamal + ); + + if (doConstantTimeDecryption) { + // The goal is to not reveal whether PKESK decryption (specifically the PKCS1 decoding step) failed, hence, we always proceed to decrypt the message, + // either with the successfully decrypted session key, or with a randomly generated one. + // Since the SEIP/AEAD's symmetric algorithm and key size are stored in the encrypted portion of the PKESK, and the execution flow cannot depend on + // the decrypted payload, we always assume the message to be encrypted with one of the symmetric algorithms specified in `config.constantTimePKCS1DecryptionSupportedSymmetricAlgorithms`: + // - If the PKESK decryption succeeds, and the session key cipher is in the supported set, then we try to decrypt the data with the decrypted session key as well as with the + // randomly generated keys of the remaining key types. + // - If the PKESK decryptions fails, or if it succeeds but support for the cipher is not enabled, then we discard the session key and try to decrypt the data using only the randomly + // generated session keys. + // NB: as a result, if the data is encrypted with a non-suported cipher, decryption will always fail. + + const serialisedPKESK = pkeskPacket.write(); // make copies to be able to decrypt the PKESK packet multiple times + await Promise.all(Array.from(config.constantTimePKCS1DecryptionSupportedSymmetricAlgorithms).map(async sessionKeyAlgorithm => { + const pkeskPacketCopy = new PublicKeyEncryptedSessionKeyPacket(); + pkeskPacketCopy.read(serialisedPKESK); + const randomSessionKey = { + sessionKeyAlgorithm, + sessionKey: await mod.generateSessionKey(sessionKeyAlgorithm) + }; + try { + await pkeskPacketCopy.decrypt(decryptionKeyPacket, randomSessionKey); + decryptedSessionKeyPackets.push(pkeskPacketCopy); + } catch (err) { + // `decrypt` can still throw some non-security-sensitive errors + util.printDebugError(err); + exception = err; + } + })); + + } else { + try { + await pkeskPacket.decrypt(decryptionKeyPacket); + if (!algos.includes(enums.write(enums.symmetric, pkeskPacket.sessionKeyAlgorithm))) { + throw new Error('A non-preferred symmetric algorithm was used.'); + } + decryptedSessionKeyPackets.push(pkeskPacket); + } catch (err) { + util.printDebugError(err); + exception = err; + } + } + })); + })); + cancel(pkeskPacket.encrypted); // Don't keep copy of encrypted data in memory. + pkeskPacket.encrypted = null; + })); + } else { + throw new Error('No key or password specified.'); + } + + if (decryptedSessionKeyPackets.length > 0) { + // Return only unique session keys + if (decryptedSessionKeyPackets.length > 1) { + const seen = new Set(); + decryptedSessionKeyPackets = decryptedSessionKeyPackets.filter(item => { + const k = item.sessionKeyAlgorithm + util.uint8ArrayToString(item.sessionKey); + if (seen.has(k)) { + return false; + } + seen.add(k); + return true; + }); + } + + return decryptedSessionKeyPackets.map(packet => ({ + data: packet.sessionKey, + algorithm: enums.read(enums.symmetric, packet.sessionKeyAlgorithm) + })); + } + throw exception || new Error('Session key decryption failed.'); + } + + /** + * Get literal data that is the body of the message + * @returns {(Uint8Array|null)} Literal body of the message as Uint8Array. + */ + getLiteralData() { + const msg = this.unwrapCompressed(); + const literal = msg.packets.findPacket(enums.packet.literalData); + return (literal && literal.getBytes()) || null; + } + + /** + * Get filename from literal data packet + * @returns {(String|null)} Filename of literal data packet as string. + */ + getFilename() { + const msg = this.unwrapCompressed(); + const literal = msg.packets.findPacket(enums.packet.literalData); + return (literal && literal.getFilename()) || null; + } + + /** + * Get literal data as text + * @returns {(String|null)} Literal body of the message interpreted as text. + */ + getText() { + const msg = this.unwrapCompressed(); + const literal = msg.packets.findPacket(enums.packet.literalData); + if (literal) { + return literal.getText(); + } + return null; + } + + /** + * Generate a new session key object, taking the algorithm preferences of the passed encryption keys into account, if any. + * @param {Array} [encryptionKeys] - Public key(s) to select algorithm preferences for + * @param {Date} [date] - Date to select algorithm preferences at + * @param {Array} [userIDs] - User IDs to select algorithm preferences for + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise<{ data: Uint8Array, algorithm: String, aeadAlgorithm: undefined|String }>} Object with session key data and algorithms. + * @async + */ + static async generateSessionKey(encryptionKeys = [], date = new Date(), userIDs = [], config = defaultConfig) { + const algo = await getPreferredAlgo('symmetric', encryptionKeys, date, userIDs, config); + const algorithmName = enums.read(enums.symmetric, algo); + const aeadAlgorithmName = config.aeadProtect && await isAEADSupported(encryptionKeys, date, userIDs, config) ? + enums.read(enums.aead, await getPreferredAlgo('aead', encryptionKeys, date, userIDs, config)) : + undefined; + + const sessionKeyData = await mod.generateSessionKey(algo); + return { data: sessionKeyData, algorithm: algorithmName, aeadAlgorithm: aeadAlgorithmName }; + } + + /** + * Encrypt the message either with public keys, passwords, or both at once. + * @param {Array} [encryptionKeys] - Public key(s) for message encryption + * @param {Array} [passwords] - Password(s) for message encryption + * @param {Object} [sessionKey] - Session key in the form: { data:Uint8Array, algorithm:String, [aeadAlgorithm:String] } + * @param {Boolean} [wildcard] - Use a key ID of 0 instead of the public key IDs + * @param {Array} [encryptionKeyIDs] - Array of key IDs to use for encryption. Each encryptionKeyIDs[i] corresponds to keys[i] + * @param {Date} [date] - Override the creation date of the literal package + * @param {Array} [userIDs] - User IDs to encrypt for, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }] + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New message with encrypted content. + * @async + */ + async encrypt(encryptionKeys, passwords, sessionKey, wildcard = false, encryptionKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { + if (sessionKey) { + if (!util.isUint8Array(sessionKey.data) || !util.isString(sessionKey.algorithm)) { + throw new Error('Invalid session key for encryption.'); + } + } else if (encryptionKeys && encryptionKeys.length) { + sessionKey = await Message.generateSessionKey(encryptionKeys, date, userIDs, config); + } else if (passwords && passwords.length) { + sessionKey = await Message.generateSessionKey(undefined, undefined, undefined, config); + } else { + throw new Error('No keys, passwords, or session key provided.'); + } + + const { data: sessionKeyData, algorithm: algorithmName, aeadAlgorithm: aeadAlgorithmName } = sessionKey; + + const msg = await Message.encryptSessionKey(sessionKeyData, algorithmName, aeadAlgorithmName, encryptionKeys, passwords, wildcard, encryptionKeyIDs, date, userIDs, config); + + let symEncryptedPacket; + if (aeadAlgorithmName) { + symEncryptedPacket = new AEADEncryptedDataPacket(); + symEncryptedPacket.aeadAlgorithm = enums.write(enums.aead, aeadAlgorithmName); + } else { + symEncryptedPacket = new SymEncryptedIntegrityProtectedDataPacket(); + } + symEncryptedPacket.packets = this.packets; + + const algorithm = enums.write(enums.symmetric, algorithmName); + await symEncryptedPacket.encrypt(algorithm, sessionKeyData, config); + + msg.packets.push(symEncryptedPacket); + symEncryptedPacket.packets = new PacketList(); // remove packets after encryption + return msg; + } + + /** + * Encrypt a session key either with public keys, passwords, or both at once. + * @param {Uint8Array} sessionKey - session key for encryption + * @param {String} algorithmName - session key algorithm + * @param {String} [aeadAlgorithmName] - AEAD algorithm, e.g. 'eax' or 'ocb' + * @param {Array} [encryptionKeys] - Public key(s) for message encryption + * @param {Array} [passwords] - For message encryption + * @param {Boolean} [wildcard] - Use a key ID of 0 instead of the public key IDs + * @param {Array} [encryptionKeyIDs] - Array of key IDs to use for encryption. Each encryptionKeyIDs[i] corresponds to encryptionKeys[i] + * @param {Date} [date] - Override the date + * @param {Array} [userIDs] - User IDs to encrypt for, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }] + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New message with encrypted content. + * @async + */ + static async encryptSessionKey(sessionKey, algorithmName, aeadAlgorithmName, encryptionKeys, passwords, wildcard = false, encryptionKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { + const packetlist = new PacketList(); + const algorithm = enums.write(enums.symmetric, algorithmName); + const aeadAlgorithm = aeadAlgorithmName && enums.write(enums.aead, aeadAlgorithmName); + + if (encryptionKeys) { + const results = await Promise.all(encryptionKeys.map(async function(primaryKey, i) { + const encryptionKey = await primaryKey.getEncryptionKey(encryptionKeyIDs[i], date, userIDs, config); + const pkESKeyPacket = new PublicKeyEncryptedSessionKeyPacket(); + pkESKeyPacket.publicKeyID = wildcard ? KeyID.wildcard() : encryptionKey.getKeyID(); + pkESKeyPacket.publicKeyAlgorithm = encryptionKey.keyPacket.algorithm; + pkESKeyPacket.sessionKey = sessionKey; + pkESKeyPacket.sessionKeyAlgorithm = algorithm; + await pkESKeyPacket.encrypt(encryptionKey.keyPacket); + delete pkESKeyPacket.sessionKey; // delete plaintext session key after encryption + return pkESKeyPacket; + })); + packetlist.push(...results); + } + if (passwords) { + const testDecrypt = async function(keyPacket, password) { + try { + await keyPacket.decrypt(password); + return 1; + } catch (e) { + return 0; + } + }; + + const sum = (accumulator, currentValue) => accumulator + currentValue; + + const encryptPassword = async function(sessionKey, algorithm, aeadAlgorithm, password) { + const symEncryptedSessionKeyPacket = new SymEncryptedSessionKeyPacket(config); + symEncryptedSessionKeyPacket.sessionKey = sessionKey; + symEncryptedSessionKeyPacket.sessionKeyAlgorithm = algorithm; + if (aeadAlgorithm) { + symEncryptedSessionKeyPacket.aeadAlgorithm = aeadAlgorithm; + } + await symEncryptedSessionKeyPacket.encrypt(password, config); + + if (config.passwordCollisionCheck) { + const results = await Promise.all(passwords.map(pwd => testDecrypt(symEncryptedSessionKeyPacket, pwd))); + if (results.reduce(sum) !== 1) { + return encryptPassword(sessionKey, algorithm, password); + } + } + + delete symEncryptedSessionKeyPacket.sessionKey; // delete plaintext session key after encryption + return symEncryptedSessionKeyPacket; + }; + + const results = await Promise.all(passwords.map(pwd => encryptPassword(sessionKey, algorithm, aeadAlgorithm, pwd))); + packetlist.push(...results); + } + + return new Message(packetlist); + } + + /** + * Sign the message (the literal data packet of the message) + * @param {Array} signingKeys - private keys with decrypted secret key data for signing + * @param {Signature} [signature] - Any existing detached signature to add to the message + * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] + * @param {Date} [date] - Override the creation time of the signature + * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New message with signed content. + * @async + */ + async sign(signingKeys = [], signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { + const packetlist = new PacketList(); + + const literalDataPacket = this.packets.findPacket(enums.packet.literalData); + if (!literalDataPacket) { + throw new Error('No literal data packet to sign.'); + } + + let i; + let existingSigPacketlist; + // If data packet was created from Uint8Array, use binary, otherwise use text + const signatureType = literalDataPacket.text === null ? + enums.signature.binary : enums.signature.text; + + if (signature) { + existingSigPacketlist = signature.packets.filterByTag(enums.packet.signature); + for (i = existingSigPacketlist.length - 1; i >= 0; i--) { + const signaturePacket = existingSigPacketlist[i]; + const onePassSig = new OnePassSignaturePacket(); + onePassSig.signatureType = signaturePacket.signatureType; + onePassSig.hashAlgorithm = signaturePacket.hashAlgorithm; + onePassSig.publicKeyAlgorithm = signaturePacket.publicKeyAlgorithm; + onePassSig.issuerKeyID = signaturePacket.issuerKeyID; + if (!signingKeys.length && i === 0) { + onePassSig.flags = 1; + } + packetlist.push(onePassSig); + } + } + + await Promise.all(Array.from(signingKeys).reverse().map(async function (primaryKey, i) { + if (!primaryKey.isPrivate()) { + throw new Error('Need private key for signing'); + } + const signingKeyID = signingKeyIDs[signingKeys.length - 1 - i]; + const signingKey = await primaryKey.getSigningKey(signingKeyID, date, userIDs, config); + const onePassSig = new OnePassSignaturePacket(); + onePassSig.signatureType = signatureType; + onePassSig.hashAlgorithm = await getPreferredHashAlgo$1(primaryKey, signingKey.keyPacket, date, userIDs, config); + onePassSig.publicKeyAlgorithm = signingKey.keyPacket.algorithm; + onePassSig.issuerKeyID = signingKey.getKeyID(); + if (i === signingKeys.length - 1) { + onePassSig.flags = 1; + } + return onePassSig; + })).then(onePassSignatureList => { + onePassSignatureList.forEach(onePassSig => packetlist.push(onePassSig)); + }); + + packetlist.push(literalDataPacket); + packetlist.push(...(await createSignaturePackets(literalDataPacket, signingKeys, signature, signingKeyIDs, date, userIDs, false, config))); + + return new Message(packetlist); + } + + /** + * Compresses the message (the literal and -if signed- signature data packets of the message) + * @param {module:enums.compression} algo - compression algorithm + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Message} New message with compressed content. + */ + compress(algo, config = defaultConfig) { + if (algo === enums.compression.uncompressed) { + return this; + } + + const compressed = new CompressedDataPacket(config); + compressed.algorithm = algo; + compressed.packets = this.packets; + + const packetList = new PacketList(); + packetList.push(compressed); + + return new Message(packetList); + } + + /** + * Create a detached signature for the message (the literal data packet of the message) + * @param {Array} signingKeys - private keys with decrypted secret key data for signing + * @param {Signature} [signature] - Any existing detached signature + * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] + * @param {Date} [date] - Override the creation time of the signature + * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New detached signature of message content. + * @async + */ + async signDetached(signingKeys = [], signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { + const literalDataPacket = this.packets.findPacket(enums.packet.literalData); + if (!literalDataPacket) { + throw new Error('No literal data packet to sign.'); + } + return new Signature(await createSignaturePackets(literalDataPacket, signingKeys, signature, signingKeyIDs, date, userIDs, true, config)); + } + + /** + * Verify message signatures + * @param {Array} verificationKeys - Array of public keys to verify signatures + * @param {Date} [date] - Verify the signature against the given date, i.e. check signature creation time < date < expiration time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise, + * verified: Promise + * }>>} List of signer's keyID and validity of signatures. + * @async + */ + async verify(verificationKeys, date = new Date(), config = defaultConfig) { + const msg = this.unwrapCompressed(); + const literalDataList = msg.packets.filterByTag(enums.packet.literalData); + if (literalDataList.length !== 1) { + throw new Error('Can only verify message with one literal data packet.'); + } + if (isArrayStream(msg.packets.stream)) { + msg.packets.push(...await readToEnd(msg.packets.stream, _ => _ || [])); + } + const onePassSigList = msg.packets.filterByTag(enums.packet.onePassSignature).reverse(); + const signatureList = msg.packets.filterByTag(enums.packet.signature); + if (onePassSigList.length && !signatureList.length && util.isStream(msg.packets.stream) && !isArrayStream(msg.packets.stream)) { + await Promise.all(onePassSigList.map(async onePassSig => { + onePassSig.correspondingSig = new Promise((resolve, reject) => { + onePassSig.correspondingSigResolve = resolve; + onePassSig.correspondingSigReject = reject; + }); + onePassSig.signatureData = fromAsync(async () => (await onePassSig.correspondingSig).signatureData); + onePassSig.hashed = readToEnd(await onePassSig.hash(onePassSig.signatureType, literalDataList[0], undefined, false)); + onePassSig.hashed.catch(() => {}); + })); + msg.packets.stream = transformPair(msg.packets.stream, async (readable, writable) => { + const reader = getReader(readable); + const writer = getWriter(writable); + try { + for (let i = 0; i < onePassSigList.length; i++) { + const { value: signature } = await reader.read(); + onePassSigList[i].correspondingSigResolve(signature); + } + await reader.readToEnd(); + await writer.ready; + await writer.close(); + } catch (e) { + onePassSigList.forEach(onePassSig => { + onePassSig.correspondingSigReject(e); + }); + await writer.abort(e); + } + }); + return createVerificationObjects(onePassSigList, literalDataList, verificationKeys, date, false, config); + } + return createVerificationObjects(signatureList, literalDataList, verificationKeys, date, false, config); + } + + /** + * Verify detached message signature + * @param {Array} verificationKeys - Array of public keys to verify signatures + * @param {Signature} signature + * @param {Date} date - Verify the signature against the given date, i.e. check signature creation time < date < expiration time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise, + * verified: Promise + * }>>} List of signer's keyID and validity of signature. + * @async + */ + verifyDetached(signature, verificationKeys, date = new Date(), config = defaultConfig) { + const msg = this.unwrapCompressed(); + const literalDataList = msg.packets.filterByTag(enums.packet.literalData); + if (literalDataList.length !== 1) { + throw new Error('Can only verify message with one literal data packet.'); + } + const signatureList = signature.packets; + return createVerificationObjects(signatureList, literalDataList, verificationKeys, date, true, config); + } + + /** + * Unwrap compressed message + * @returns {Message} Message Content of compressed message. + */ + unwrapCompressed() { + const compressed = this.packets.filterByTag(enums.packet.compressedData); + if (compressed.length) { + return new Message(compressed[0].packets); + } + return this; + } + + /** + * Append signature to unencrypted message object + * @param {String|Uint8Array} detachedSignature - The detached ASCII-armored or Uint8Array PGP signature + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + async appendSignature(detachedSignature, config = defaultConfig) { + await this.packets.read( + util.isUint8Array(detachedSignature) ? detachedSignature : (await unarmor(detachedSignature)).data, + allowedDetachedSignaturePackets, + config + ); + } + + /** + * Returns binary encoded message + * @returns {ReadableStream} Binary message. + */ + write() { + return this.packets.write(); + } + + /** + * Returns ASCII armored text of message + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {ReadableStream} ASCII armor. + */ + armor(config = defaultConfig) { + return armor(enums.armor.message, this.write(), null, null, null, config); + } +} + +/** + * Create signature packets for the message + * @param {LiteralDataPacket} literalDataPacket - the literal data packet to sign + * @param {Array} [signingKeys] - private keys with decrypted secret key data for signing + * @param {Signature} [signature] - Any existing detached signature to append + * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] + * @param {Date} [date] - Override the creationtime of the signature + * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] + * @param {Boolean} [detached] - Whether to create detached signature packets + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} List of signature packets. + * @async + * @private + */ +async function createSignaturePackets(literalDataPacket, signingKeys, signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], detached = false, config = defaultConfig) { + const packetlist = new PacketList(); + + // If data packet was created from Uint8Array, use binary, otherwise use text + const signatureType = literalDataPacket.text === null ? + enums.signature.binary : enums.signature.text; + + await Promise.all(signingKeys.map(async (primaryKey, i) => { + const userID = userIDs[i]; + if (!primaryKey.isPrivate()) { + throw new Error('Need private key for signing'); + } + const signingKey = await primaryKey.getSigningKey(signingKeyIDs[i], date, userID, config); + return createSignaturePacket(literalDataPacket, primaryKey, signingKey.keyPacket, { signatureType }, date, userID, detached, config); + })).then(signatureList => { + packetlist.push(...signatureList); + }); + + if (signature) { + const existingSigPacketlist = signature.packets.filterByTag(enums.packet.signature); + packetlist.push(...existingSigPacketlist); + } + return packetlist; +} + +/** + * Create object containing signer's keyID and validity of signature + * @param {SignaturePacket} signature - Signature packet + * @param {Array} literalDataList - Array of literal data packets + * @param {Array} verificationKeys - Array of public keys to verify signatures + * @param {Date} [date] - Check signature validity with respect to the given date + * @param {Boolean} [detached] - Whether to verify detached signature packets + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise<{ + * keyID: module:type/keyid~KeyID, + * signature: Promise, + * verified: Promise + * }>} signer's keyID and validity of signature + * @async + * @private + */ +async function createVerificationObject(signature, literalDataList, verificationKeys, date = new Date(), detached = false, config = defaultConfig) { + let primaryKey; + let unverifiedSigningKey; + + for (const key of verificationKeys) { + const issuerKeys = key.getKeys(signature.issuerKeyID); + if (issuerKeys.length > 0) { + primaryKey = key; + unverifiedSigningKey = issuerKeys[0]; + break; + } + } + + const isOnePassSignature = signature instanceof OnePassSignaturePacket; + const signaturePacketPromise = isOnePassSignature ? signature.correspondingSig : signature; + + const verifiedSig = { + keyID: signature.issuerKeyID, + verified: (async () => { + if (!unverifiedSigningKey) { + throw new Error(`Could not find signing key with key ID ${signature.issuerKeyID.toHex()}`); + } + + await signature.verify(unverifiedSigningKey.keyPacket, signature.signatureType, literalDataList[0], date, detached, config); + const signaturePacket = await signaturePacketPromise; + if (unverifiedSigningKey.getCreationTime() > signaturePacket.created) { + throw new Error('Key is newer than the signature'); + } + // We pass the signature creation time to check whether the key was expired at the time of signing. + // We check this after signature verification because for streamed one-pass signatures, the creation time is not available before + try { + await primaryKey.getSigningKey(unverifiedSigningKey.getKeyID(), signaturePacket.created, undefined, config); + } catch (e) { + // If a key was reformatted then the self-signatures of the signing key might be in the future compared to the message signature, + // making the key invalid at the time of signing. + // However, if the key is valid at the given `date`, we still allow using it provided the relevant `config` setting is enabled. + // Note: we do not support the edge case of a key that was reformatted and it has expired. + if (config.allowInsecureVerificationWithReformattedKeys && e.message.match(/Signature creation time is in the future/)) { + await primaryKey.getSigningKey(unverifiedSigningKey.getKeyID(), date, undefined, config); + } else { + throw e; + } + } + return true; + })(), + signature: (async () => { + const signaturePacket = await signaturePacketPromise; + const packetlist = new PacketList(); + signaturePacket && packetlist.push(signaturePacket); + return new Signature(packetlist); + })() + }; + + // Mark potential promise rejections as "handled". This is needed because in + // some cases, we reject them before the user has a reasonable chance to + // handle them (e.g. `await readToEnd(result.data); await result.verified` and + // the data stream errors). + verifiedSig.signature.catch(() => {}); + verifiedSig.verified.catch(() => {}); + + return verifiedSig; +} + +/** + * Create list of objects containing signer's keyID and validity of signature + * @param {Array} signatureList - Array of signature packets + * @param {Array} literalDataList - Array of literal data packets + * @param {Array} verificationKeys - Array of public keys to verify signatures + * @param {Date} date - Verify the signature against the given date, + * i.e. check signature creation time < date < expiration time + * @param {Boolean} [detached] - Whether to verify detached signature packets + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise, + * verified: Promise + * }>>} list of signer's keyID and validity of signatures (one entry per signature packet in input) + * @async + * @private + */ +async function createVerificationObjects(signatureList, literalDataList, verificationKeys, date = new Date(), detached = false, config = defaultConfig) { + return Promise.all(signatureList.filter(function(signature) { + return ['text', 'binary'].includes(enums.read(enums.signature, signature.signatureType)); + }).map(async function(signature) { + return createVerificationObject(signature, literalDataList, verificationKeys, date, detached, config); + })); +} + +/** + * Reads an (optionally armored) OpenPGP message and returns a Message object + * @param {Object} options + * @param {String | ReadableStream} [options.armoredMessage] - Armored message to be parsed + * @param {Uint8Array | ReadableStream} [options.binaryMessage] - Binary to be parsed + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} New message object. + * @async + * @static + */ +async function readMessage({ armoredMessage, binaryMessage, config, ...rest }) { + config = { ...defaultConfig, ...config }; + let input = armoredMessage || binaryMessage; + if (!input) { + throw new Error('readMessage: must pass options object containing `armoredMessage` or `binaryMessage`'); + } + if (armoredMessage && !util.isString(armoredMessage) && !util.isStream(armoredMessage)) { + throw new Error('readMessage: options.armoredMessage must be a string or stream'); + } + if (binaryMessage && !util.isUint8Array(binaryMessage) && !util.isStream(binaryMessage)) { + throw new Error('readMessage: options.binaryMessage must be a Uint8Array or stream'); + } + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + const streamType = util.isStream(input); + if (streamType) { + await loadStreamsPonyfill(); + input = toStream(input); + } + if (armoredMessage) { + const { type, data } = await unarmor(input, config); + if (type !== enums.armor.message) { + throw new Error('Armored text not of type message'); + } + input = data; + } + const packetlist = await PacketList.fromBinary(input, allowedMessagePackets, config); + const message = new Message(packetlist); + message.fromStream = streamType; + return message; +} + +/** + * Creates new message object from text or binary data. + * @param {Object} options + * @param {String | ReadableStream} [options.text] - The text message contents + * @param {Uint8Array | ReadableStream} [options.binary] - The binary message contents + * @param {String} [options.filename=""] - Name of the file (if any) + * @param {Date} [options.date=current date] - Date of the message, or modification date of the file + * @param {'utf8'|'binary'|'text'|'mime'} [options.format='utf8' if text is passed, 'binary' otherwise] - Data packet type + * @returns {Promise} New message object. + * @async + * @static + */ +async function createMessage({ text, binary, filename, date = new Date(), format = text !== undefined ? 'utf8' : 'binary', ...rest }) { + let input = text !== undefined ? text : binary; + if (input === undefined) { + throw new Error('createMessage: must pass options object containing `text` or `binary`'); + } + if (text && !util.isString(text) && !util.isStream(text)) { + throw new Error('createMessage: options.text must be a string or stream'); + } + if (binary && !util.isUint8Array(binary) && !util.isStream(binary)) { + throw new Error('createMessage: options.binary must be a Uint8Array or stream'); + } + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + const streamType = util.isStream(input); + if (streamType) { + await loadStreamsPonyfill(); + input = toStream(input); + } + const literalDataPacket = new LiteralDataPacket(date); + if (text !== undefined) { + literalDataPacket.setText(input, enums.write(enums.literal, format)); + } else { + literalDataPacket.setBytes(input, enums.write(enums.literal, format)); + } + if (filename !== undefined) { + literalDataPacket.setFilename(filename); + } + const literalDataPacketlist = new PacketList(); + literalDataPacketlist.push(literalDataPacket); + const message = new Message(literalDataPacketlist); + message.fromStream = streamType; + return message; +} + +// GPG4Browsers - An OpenPGP implementation in javascript + +// A Cleartext message can contain the following packets +const allowedPackets$5 = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); + +/** + * Class that represents an OpenPGP cleartext signed message. + * See {@link https://tools.ietf.org/html/rfc4880#section-7} + */ +class CleartextMessage { + /** + * @param {String} text - The cleartext of the signed message + * @param {Signature} signature - The detached signature or an empty signature for unsigned messages + */ + constructor(text, signature) { + // normalize EOL to canonical form + this.text = util.removeTrailingSpaces(text).replace(/\r?\n/g, '\r\n'); + if (signature && !(signature instanceof Signature)) { + throw new Error('Invalid signature input'); + } + this.signature = signature || new Signature(new PacketList()); + } + + /** + * Returns the key IDs of the keys that signed the cleartext message + * @returns {Array} Array of keyID objects. + */ + getSigningKeyIDs() { + const keyIDs = []; + const signatureList = this.signature.packets; + signatureList.forEach(function(packet) { + keyIDs.push(packet.issuerKeyID); + }); + return keyIDs; + } + + /** + * Sign the cleartext message + * @param {Array} privateKeys - private keys with decrypted secret key data for signing + * @param {Signature} [signature] - Any existing detached signature + * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to privateKeys[i] + * @param {Date} [date] - The creation time of the signature that should be created + * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New cleartext message with signed content. + * @async + */ + async sign(privateKeys, signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { + const literalDataPacket = new LiteralDataPacket(); + literalDataPacket.setText(this.text); + const newSignature = new Signature(await createSignaturePackets(literalDataPacket, privateKeys, signature, signingKeyIDs, date, userIDs, true, config)); + return new CleartextMessage(this.text, newSignature); + } + + /** + * Verify signatures of cleartext signed message + * @param {Array} keys - Array of keys to verify signatures + * @param {Date} [date] - Verify the signature against the given date, i.e. check signature creation time < date < expiration time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise, + * verified: Promise + * }>>} List of signer's keyID and validity of signature. + * @async + */ + verify(keys, date = new Date(), config = defaultConfig) { + const signatureList = this.signature.packets; + const literalDataPacket = new LiteralDataPacket(); + // we assume that cleartext signature is generated based on UTF8 cleartext + literalDataPacket.setText(this.text); + return createVerificationObjects(signatureList, [literalDataPacket], keys, date, true, config); + } + + /** + * Get cleartext + * @returns {String} Cleartext of message. + */ + getText() { + // normalize end of line to \n + return this.text.replace(/\r\n/g, '\n'); + } + + /** + * Returns ASCII armored text of cleartext signed message + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {String | ReadableStream} ASCII armor. + */ + armor(config = defaultConfig) { + let hashes = this.signature.packets.map(function(packet) { + return enums.read(enums.hash, packet.hashAlgorithm).toUpperCase(); + }); + hashes = hashes.filter(function(item, i, ar) { return ar.indexOf(item) === i; }); + const body = { + hash: hashes.join(), + text: this.text, + data: this.signature.packets.write() + }; + return armor(enums.armor.signed, body, undefined, undefined, undefined, config); + } +} + +/** + * Reads an OpenPGP cleartext signed message and returns a CleartextMessage object + * @param {Object} options + * @param {String} options.cleartextMessage - Text to be parsed + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} New cleartext message object. + * @async + * @static + */ +async function readCleartextMessage({ cleartextMessage, config, ...rest }) { + config = { ...defaultConfig, ...config }; + if (!cleartextMessage) { + throw new Error('readCleartextMessage: must pass options object containing `cleartextMessage`'); + } + if (!util.isString(cleartextMessage)) { + throw new Error('readCleartextMessage: options.cleartextMessage must be a string'); + } + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + const input = await unarmor(cleartextMessage); + if (input.type !== enums.armor.signed) { + throw new Error('No cleartext signed message.'); + } + const packetlist = await PacketList.fromBinary(input.data, allowedPackets$5, config); + verifyHeaders$1(input.headers, packetlist); + const signature = new Signature(packetlist); + return new CleartextMessage(input.text, signature); +} + +/** + * Compare hash algorithm specified in the armor header with signatures + * @param {Array} headers - Armor headers + * @param {PacketList} packetlist - The packetlist with signature packets + * @private + */ +function verifyHeaders$1(headers, packetlist) { + const checkHashAlgos = function(hashAlgos) { + const check = packet => algo => packet.hashAlgorithm === algo; + + for (let i = 0; i < packetlist.length; i++) { + if (packetlist[i].constructor.tag === enums.packet.signature && !hashAlgos.some(check(packetlist[i]))) { + return false; + } + } + return true; + }; + + let oneHeader = null; + let hashAlgos = []; + headers.forEach(function(header) { + oneHeader = header.match(/Hash: (.+)/); // get header value + if (oneHeader) { + oneHeader = oneHeader[1].replace(/\s/g, ''); // remove whitespace + oneHeader = oneHeader.split(','); + oneHeader = oneHeader.map(function(hash) { + hash = hash.toLowerCase(); + try { + return enums.write(enums.hash, hash); + } catch (e) { + throw new Error('Unknown hash algorithm in armor header: ' + hash); + } + }); + hashAlgos = hashAlgos.concat(oneHeader); + } else { + throw new Error('Only "Hash" header allowed in cleartext signed message'); + } + }); + + if (!hashAlgos.length && !checkHashAlgos([enums.hash.md5])) { + throw new Error('If no "Hash" header in cleartext signed message, then only MD5 signatures allowed'); + } else if (hashAlgos.length && !checkHashAlgos(hashAlgos)) { + throw new Error('Hash algorithm mismatch in armor header and signature'); + } +} + +/** + * Creates a new CleartextMessage object from text + * @param {Object} options + * @param {String} options.text + * @static + * @async + */ +async function createCleartextMessage({ text, ...rest }) { + if (!text) { + throw new Error('createCleartextMessage: must pass options object containing `text`'); + } + if (!util.isString(text)) { + throw new Error('createCleartextMessage: options.text must be a string'); + } + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + return new CleartextMessage(text); +} + +// OpenPGP.js - An OpenPGP implementation in javascript + + +////////////////////// +// // +// Key handling // +// // +////////////////////// + + +/** + * Generates a new OpenPGP key pair. Supports RSA and ECC keys. By default, primary and subkeys will be of same type. + * The generated primary key will have signing capabilities. By default, one subkey with encryption capabilities is also generated. + * @param {Object} options + * @param {Object|Array} options.userIDs - User IDs as objects: `{ name: 'Jo Doe', email: 'info@jo.com' }` + * @param {'ecc'|'rsa'} [options.type='ecc'] - The primary key algorithm type: ECC (default) or RSA + * @param {String} [options.passphrase=(not protected)] - The passphrase used to encrypt the generated private key. If omitted, the key won't be encrypted. + * @param {Number} [options.rsaBits=4096] - Number of bits for RSA keys + * @param {String} [options.curve='curve25519'] - Elliptic curve for ECC keys: + * curve25519 (default), p256, p384, p521, secp256k1, + * brainpoolP256r1, brainpoolP384r1, or brainpoolP512r1 + * @param {Date} [options.date=current date] - Override the creation date of the key and the key signatures + * @param {Number} [options.keyExpirationTime=0 (never expires)] - Number of seconds from the key creation time after which the key expires + * @param {Array} [options.subkeys=a single encryption subkey] - Options for each subkey e.g. `[{sign: true, passphrase: '123'}]` + * default to main key options, except for `sign` parameter that defaults to false, and indicates whether the subkey should sign rather than encrypt + * @param {'armored'|'binary'|'object'} [options.format='armored'] - format of the output keys + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} The generated key object in the form: + * { privateKey:PrivateKey|Uint8Array|String, publicKey:PublicKey|Uint8Array|String, revocationCertificate:String } + * @async + * @static + */ +async function generateKey({ userIDs = [], passphrase = '', type = 'ecc', rsaBits = 4096, curve = 'curve25519', keyExpirationTime = 0, date = new Date(), subkeys = [{}], format = 'armored', config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + userIDs = toArray$1(userIDs); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + if (userIDs.length === 0) { + throw new Error('UserIDs are required for key generation'); + } + if (type === 'rsa' && rsaBits < config.minRSABits) { + throw new Error(`rsaBits should be at least ${config.minRSABits}, got: ${rsaBits}`); + } + + const options = { userIDs, passphrase, type, rsaBits, curve, keyExpirationTime, date, subkeys }; + + try { + const { key, revocationCertificate } = await generate$2(options, config); + key.getKeys().forEach(({ keyPacket }) => checkKeyRequirements(keyPacket, config)); + + return { + privateKey: formatObject(key, format, config), + publicKey: formatObject(key.toPublic(), format, config), + revocationCertificate + }; + } catch (err) { + throw util.wrapError('Error generating keypair', err); + } +} + +/** + * Reformats signature packets for a key and rewraps key object. + * @param {Object} options + * @param {PrivateKey} options.privateKey - Private key to reformat + * @param {Object|Array} options.userIDs - User IDs as objects: `{ name: 'Jo Doe', email: 'info@jo.com' }` + * @param {String} [options.passphrase=(not protected)] - The passphrase used to encrypt the reformatted private key. If omitted, the key won't be encrypted. + * @param {Number} [options.keyExpirationTime=0 (never expires)] - Number of seconds from the key creation time after which the key expires + * @param {Date} [options.date] - Override the creation date of the key signatures. If the key was previously used to sign messages, it is recommended + * to set the same date as the key creation time to ensure that old message signatures will still be verifiable using the reformatted key. + * @param {'armored'|'binary'|'object'} [options.format='armored'] - format of the output keys + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} The generated key object in the form: + * { privateKey:PrivateKey|Uint8Array|String, publicKey:PublicKey|Uint8Array|String, revocationCertificate:String } + * @async + * @static + */ +async function reformatKey({ privateKey, userIDs = [], passphrase = '', keyExpirationTime = 0, date, format = 'armored', config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + userIDs = toArray$1(userIDs); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + if (userIDs.length === 0) { + throw new Error('UserIDs are required for key reformat'); + } + const options = { privateKey, userIDs, passphrase, keyExpirationTime, date }; + + try { + const { key: reformattedKey, revocationCertificate } = await reformat(options, config); + + return { + privateKey: formatObject(reformattedKey, format, config), + publicKey: formatObject(reformattedKey.toPublic(), format, config), + revocationCertificate + }; + } catch (err) { + throw util.wrapError('Error reformatting keypair', err); + } +} + +/** + * Revokes a key. Requires either a private key or a revocation certificate. + * If a revocation certificate is passed, the reasonForRevocation parameter will be ignored. + * @param {Object} options + * @param {Key} options.key - Public or private key to revoke + * @param {String} [options.revocationCertificate] - Revocation certificate to revoke the key with + * @param {Object} [options.reasonForRevocation] - Object indicating the reason for revocation + * @param {module:enums.reasonForRevocation} [options.reasonForRevocation.flag=[noReason]{@link module:enums.reasonForRevocation}] - Flag indicating the reason for revocation + * @param {String} [options.reasonForRevocation.string=""] - String explaining the reason for revocation + * @param {Date} [options.date] - Use the given date instead of the current time to verify validity of revocation certificate (if provided), or as creation time of the revocation signature + * @param {'armored'|'binary'|'object'} [options.format='armored'] - format of the output key(s) + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} The revoked key in the form: + * { privateKey:PrivateKey|Uint8Array|String, publicKey:PublicKey|Uint8Array|String } if private key is passed, or + * { privateKey: null, publicKey:PublicKey|Uint8Array|String } otherwise + * @async + * @static + */ +async function revokeKey({ key, revocationCertificate, reasonForRevocation, date = new Date(), format = 'armored', config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + try { + const revokedKey = revocationCertificate ? + await key.applyRevocationCertificate(revocationCertificate, date, config) : + await key.revoke(reasonForRevocation, date, config); + + return revokedKey.isPrivate() ? { + privateKey: formatObject(revokedKey, format, config), + publicKey: formatObject(revokedKey.toPublic(), format, config) + } : { + privateKey: null, + publicKey: formatObject(revokedKey, format, config) + }; + } catch (err) { + throw util.wrapError('Error revoking key', err); + } +} + +/** + * Unlock a private key with the given passphrase. + * This method does not change the original key. + * @param {Object} options + * @param {PrivateKey} options.privateKey - The private key to decrypt + * @param {String|Array} options.passphrase - The user's passphrase(s) + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} The unlocked key object. + * @async + */ +async function decryptKey({ privateKey, passphrase, config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + if (!privateKey.isPrivate()) { + throw new Error('Cannot decrypt a public key'); + } + const clonedPrivateKey = privateKey.clone(true); + const passphrases = util.isArray(passphrase) ? passphrase : [passphrase]; + + try { + await Promise.all(clonedPrivateKey.getKeys().map(key => ( + // try to decrypt each key with any of the given passphrases + util.anyPromise(passphrases.map(passphrase => key.keyPacket.decrypt(passphrase))) + ))); + + await clonedPrivateKey.validate(config); + return clonedPrivateKey; + } catch (err) { + clonedPrivateKey.clearPrivateParams(); + throw util.wrapError('Error decrypting private key', err); + } +} + +/** + * Lock a private key with the given passphrase. + * This method does not change the original key. + * @param {Object} options + * @param {PrivateKey} options.privateKey - The private key to encrypt + * @param {String|Array} options.passphrase - If multiple passphrases, they should be in the same order as the packets each should encrypt + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} The locked key object. + * @async + */ +async function encryptKey({ privateKey, passphrase, config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + if (!privateKey.isPrivate()) { + throw new Error('Cannot encrypt a public key'); + } + const clonedPrivateKey = privateKey.clone(true); + + const keys = clonedPrivateKey.getKeys(); + const passphrases = util.isArray(passphrase) ? passphrase : new Array(keys.length).fill(passphrase); + if (passphrases.length !== keys.length) { + throw new Error('Invalid number of passphrases given for key encryption'); + } + + try { + await Promise.all(keys.map(async (key, i) => { + const { keyPacket } = key; + await keyPacket.encrypt(passphrases[i], config); + keyPacket.clearPrivateParams(); + })); + return clonedPrivateKey; + } catch (err) { + clonedPrivateKey.clearPrivateParams(); + throw util.wrapError('Error encrypting private key', err); + } +} + + +/////////////////////////////////////////// +// // +// Message encryption and decryption // +// // +/////////////////////////////////////////// + + +/** + * Encrypts a message using public keys, passwords or both at once. At least one of `encryptionKeys` or `passwords` + * must be specified. If signing keys are specified, those will be used to sign the message. + * @param {Object} options + * @param {Message} options.message - Message to be encrypted as created by {@link createMessage} + * @param {PublicKey|PublicKey[]} [options.encryptionKeys] - Array of keys or single key, used to encrypt the message + * @param {PrivateKey|PrivateKey[]} [options.signingKeys] - Private keys for signing. If omitted message will not be signed + * @param {String|String[]} [options.passwords] - Array of passwords or a single password to encrypt the message + * @param {Object} [options.sessionKey] - Session key in the form: `{ data:Uint8Array, algorithm:String }` + * @param {'armored'|'binary'|'object'} [options.format='armored'] - Format of the returned message + * @param {Signature} [options.signature] - A detached signature to add to the encrypted message + * @param {Boolean} [options.wildcard=false] - Use a key ID of 0 instead of the public key IDs + * @param {KeyID|KeyID[]} [options.signingKeyIDs=latest-created valid signing (sub)keys] - Array of key IDs to use for signing. Each `signingKeyIDs[i]` corresponds to `signingKeys[i]` + * @param {KeyID|KeyID[]} [options.encryptionKeyIDs=latest-created valid encryption (sub)keys] - Array of key IDs to use for encryption. Each `encryptionKeyIDs[i]` corresponds to `encryptionKeys[i]` + * @param {Date} [options.date=current date] - Override the creation date of the message signature + * @param {Object|Object[]} [options.signingUserIDs=primary user IDs] - Array of user IDs to sign with, one per key in `signingKeys`, e.g. `[{ name: 'Steve Sender', email: 'steve@openpgp.org' }]` + * @param {Object|Object[]} [options.encryptionUserIDs=primary user IDs] - Array of user IDs to encrypt for, one per key in `encryptionKeys`, e.g. `[{ name: 'Robert Receiver', email: 'robert@openpgp.org' }]` + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise|MaybeStream>} Encrypted message (string if `armor` was true, the default; Uint8Array if `armor` was false). + * @async + * @static + */ +async function encrypt$4({ message, encryptionKeys, signingKeys, passwords, sessionKey, format = 'armored', signature = null, wildcard = false, signingKeyIDs = [], encryptionKeyIDs = [], date = new Date(), signingUserIDs = [], encryptionUserIDs = [], config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + checkMessage(message); checkOutputMessageFormat(format); + encryptionKeys = toArray$1(encryptionKeys); signingKeys = toArray$1(signingKeys); passwords = toArray$1(passwords); + signingKeyIDs = toArray$1(signingKeyIDs); encryptionKeyIDs = toArray$1(encryptionKeyIDs); signingUserIDs = toArray$1(signingUserIDs); encryptionUserIDs = toArray$1(encryptionUserIDs); + if (rest.detached) { + throw new Error("The `detached` option has been removed from openpgp.encrypt, separately call openpgp.sign instead. Don't forget to remove the `privateKeys` option as well."); + } + if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.encrypt, pass `encryptionKeys` instead'); + if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.encrypt, pass `signingKeys` instead'); + if (rest.armor !== undefined) throw new Error('The `armor` option has been removed from openpgp.encrypt, pass `format` instead.'); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + if (!signingKeys) { + signingKeys = []; + } + const streaming = message.fromStream; + try { + if (signingKeys.length || signature) { // sign the message only if signing keys or signature is specified + message = await message.sign(signingKeys, signature, signingKeyIDs, date, signingUserIDs, config); + } + message = message.compress( + await getPreferredAlgo('compression', encryptionKeys, date, encryptionUserIDs, config), + config + ); + message = await message.encrypt(encryptionKeys, passwords, sessionKey, wildcard, encryptionKeyIDs, date, encryptionUserIDs, config); + if (format === 'object') return message; + // serialize data + const armor = format === 'armored'; + const data = armor ? message.armor(config) : message.write(); + return convertStream(data, streaming, armor ? 'utf8' : 'binary'); + } catch (err) { + throw util.wrapError('Error encrypting message', err); + } +} + +/** + * Decrypts a message with the user's private key, a session key or a password. + * One of `decryptionKeys`, `sessionkeys` or `passwords` must be specified (passing a combination of these options is not supported). + * @param {Object} options + * @param {Message} options.message - The message object with the encrypted data + * @param {PrivateKey|PrivateKey[]} [options.decryptionKeys] - Private keys with decrypted secret key data or session key + * @param {String|String[]} [options.passwords] - Passwords to decrypt the message + * @param {Object|Object[]} [options.sessionKeys] - Session keys in the form: { data:Uint8Array, algorithm:String } + * @param {PublicKey|PublicKey[]} [options.verificationKeys] - Array of public keys or single key, to verify signatures + * @param {Boolean} [options.expectSigned=false] - If true, data decryption fails if the message is not signed with the provided publicKeys + * @param {'utf8'|'binary'} [options.format='utf8'] - Whether to return data as a string(Stream) or Uint8Array(Stream). If 'utf8' (the default), also normalize newlines. + * @param {Signature} [options.signature] - Detached signature for verification + * @param {Date} [options.date=current date] - Use the given date for verification instead of the current time + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} Object containing decrypted and verified message in the form: + * + * { + * data: MaybeStream, (if format was 'utf8', the default) + * data: MaybeStream, (if format was 'binary') + * filename: String, + * signatures: [ + * { + * keyID: module:type/keyid~KeyID, + * verified: Promise, + * signature: Promise + * }, ... + * ] + * } + * + * where `signatures` contains a separate entry for each signature packet found in the input message. + * @async + * @static + */ +async function decrypt$4({ message, decryptionKeys, passwords, sessionKeys, verificationKeys, expectSigned = false, format = 'utf8', signature = null, date = new Date(), config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + checkMessage(message); verificationKeys = toArray$1(verificationKeys); decryptionKeys = toArray$1(decryptionKeys); passwords = toArray$1(passwords); sessionKeys = toArray$1(sessionKeys); + if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.decrypt, pass `decryptionKeys` instead'); + if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.decrypt, pass `verificationKeys` instead'); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + try { + const decrypted = await message.decrypt(decryptionKeys, passwords, sessionKeys, date, config); + if (!verificationKeys) { + verificationKeys = []; + } + + const result = {}; + result.signatures = signature ? await decrypted.verifyDetached(signature, verificationKeys, date, config) : await decrypted.verify(verificationKeys, date, config); + result.data = format === 'binary' ? decrypted.getLiteralData() : decrypted.getText(); + result.filename = decrypted.getFilename(); + linkStreams(result, message); + if (expectSigned) { + if (verificationKeys.length === 0) { + throw new Error('Verification keys are required to verify message signatures'); + } + if (result.signatures.length === 0) { + throw new Error('Message is not signed'); + } + result.data = concat([ + result.data, + fromAsync(async () => { + await util.anyPromise(result.signatures.map(sig => sig.verified)); + }) + ]); + } + result.data = await convertStream(result.data, message.fromStream, format); + return result; + } catch (err) { + throw util.wrapError('Error decrypting message', err); + } +} + + +////////////////////////////////////////// +// // +// Message signing and verification // +// // +////////////////////////////////////////// + + +/** + * Signs a message. + * @param {Object} options + * @param {CleartextMessage|Message} options.message - (cleartext) message to be signed + * @param {PrivateKey|PrivateKey[]} options.signingKeys - Array of keys or single key with decrypted secret key data to sign cleartext + * @param {'armored'|'binary'|'object'} [options.format='armored'] - Format of the returned message + * @param {Boolean} [options.detached=false] - If the return value should contain a detached signature + * @param {KeyID|KeyID[]} [options.signingKeyIDs=latest-created valid signing (sub)keys] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] + * @param {Date} [options.date=current date] - Override the creation date of the signature + * @param {Object|Object[]} [options.signingUserIDs=primary user IDs] - Array of user IDs to sign with, one per key in `signingKeys`, e.g. `[{ name: 'Steve Sender', email: 'steve@openpgp.org' }]` + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise>} Signed message (string if `armor` was true, the default; Uint8Array if `armor` was false). + * @async + * @static + */ +async function sign$5({ message, signingKeys, format = 'armored', detached = false, signingKeyIDs = [], date = new Date(), signingUserIDs = [], config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + checkCleartextOrMessage(message); checkOutputMessageFormat(format); + signingKeys = toArray$1(signingKeys); signingKeyIDs = toArray$1(signingKeyIDs); signingUserIDs = toArray$1(signingUserIDs); + + if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.sign, pass `signingKeys` instead'); + if (rest.armor !== undefined) throw new Error('The `armor` option has been removed from openpgp.sign, pass `format` instead.'); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + if (message instanceof CleartextMessage && format === 'binary') throw new Error('Cannot return signed cleartext message in binary format'); + if (message instanceof CleartextMessage && detached) throw new Error('Cannot detach-sign a cleartext message'); + + if (!signingKeys || signingKeys.length === 0) { + throw new Error('No signing keys provided'); + } + + try { + let signature; + if (detached) { + signature = await message.signDetached(signingKeys, undefined, signingKeyIDs, date, signingUserIDs, config); + } else { + signature = await message.sign(signingKeys, undefined, signingKeyIDs, date, signingUserIDs, config); + } + if (format === 'object') return signature; + + const armor = format === 'armored'; + signature = armor ? signature.armor(config) : signature.write(); + if (detached) { + signature = transformPair(message.packets.write(), async (readable, writable) => { + await Promise.all([ + pipe(signature, writable), + readToEnd(readable).catch(() => {}) + ]); + }); + } + return convertStream(signature, message.fromStream, armor ? 'utf8' : 'binary'); + } catch (err) { + throw util.wrapError('Error signing message', err); + } +} + +/** + * Verifies signatures of cleartext signed message + * @param {Object} options + * @param {CleartextMessage|Message} options.message - (cleartext) message object with signatures + * @param {PublicKey|PublicKey[]} options.verificationKeys - Array of publicKeys or single key, to verify signatures + * @param {Boolean} [options.expectSigned=false] - If true, verification throws if the message is not signed with the provided publicKeys + * @param {'utf8'|'binary'} [options.format='utf8'] - Whether to return data as a string(Stream) or Uint8Array(Stream). If 'utf8' (the default), also normalize newlines. + * @param {Signature} [options.signature] - Detached signature for verification + * @param {Date} [options.date=current date] - Use the given date for verification instead of the current time + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} Object containing verified message in the form: + * + * { + * data: MaybeStream, (if `message` was a CleartextMessage) + * data: MaybeStream, (if `message` was a Message) + * signatures: [ + * { + * keyID: module:type/keyid~KeyID, + * verified: Promise, + * signature: Promise + * }, ... + * ] + * } + * + * where `signatures` contains a separate entry for each signature packet found in the input message. + * @async + * @static + */ +async function verify$5({ message, verificationKeys, expectSigned = false, format = 'utf8', signature = null, date = new Date(), config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + checkCleartextOrMessage(message); verificationKeys = toArray$1(verificationKeys); + if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.verify, pass `verificationKeys` instead'); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + if (message instanceof CleartextMessage && format === 'binary') throw new Error("Can't return cleartext message data as binary"); + if (message instanceof CleartextMessage && signature) throw new Error("Can't verify detached cleartext signature"); + + try { + const result = {}; + if (signature) { + result.signatures = await message.verifyDetached(signature, verificationKeys, date, config); + } else { + result.signatures = await message.verify(verificationKeys, date, config); + } + result.data = format === 'binary' ? message.getLiteralData() : message.getText(); + if (message.fromStream) linkStreams(result, message); + if (expectSigned) { + if (result.signatures.length === 0) { + throw new Error('Message is not signed'); + } + result.data = concat([ + result.data, + fromAsync(async () => { + await util.anyPromise(result.signatures.map(sig => sig.verified)); + }) + ]); + } + result.data = await convertStream(result.data, message.fromStream, format); + return result; + } catch (err) { + throw util.wrapError('Error verifying signed message', err); + } +} + + +/////////////////////////////////////////////// +// // +// Session key encryption and decryption // +// // +/////////////////////////////////////////////// + +/** + * Generate a new session key object, taking the algorithm preferences of the passed public keys into account. + * @param {Object} options + * @param {PublicKey|PublicKey[]} options.encryptionKeys - Array of public keys or single key used to select algorithm preferences for + * @param {Date} [options.date=current date] - Date to select algorithm preferences at + * @param {Object|Object[]} [options.encryptionUserIDs=primary user IDs] - User IDs to select algorithm preferences for + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise<{ data: Uint8Array, algorithm: String }>} Object with session key data and algorithm. + * @async + * @static + */ +async function generateSessionKey$1({ encryptionKeys, date = new Date(), encryptionUserIDs = [], config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + encryptionKeys = toArray$1(encryptionKeys); encryptionUserIDs = toArray$1(encryptionUserIDs); + if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.generateSessionKey, pass `encryptionKeys` instead'); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + try { + const sessionKeys = await Message.generateSessionKey(encryptionKeys, date, encryptionUserIDs, config); + return sessionKeys; + } catch (err) { + throw util.wrapError('Error generating session key', err); + } +} + +/** + * Encrypt a symmetric session key with public keys, passwords, or both at once. + * At least one of `encryptionKeys` or `passwords` must be specified. + * @param {Object} options + * @param {Uint8Array} options.data - The session key to be encrypted e.g. 16 random bytes (for aes128) + * @param {String} options.algorithm - Algorithm of the symmetric session key e.g. 'aes128' or 'aes256' + * @param {String} [options.aeadAlgorithm] - AEAD algorithm, e.g. 'eax' or 'ocb' + * @param {PublicKey|PublicKey[]} [options.encryptionKeys] - Array of public keys or single key, used to encrypt the key + * @param {String|String[]} [options.passwords] - Passwords for the message + * @param {'armored'|'binary'} [options.format='armored'] - Format of the returned value + * @param {Boolean} [options.wildcard=false] - Use a key ID of 0 instead of the public key IDs + * @param {KeyID|KeyID[]} [options.encryptionKeyIDs=latest-created valid encryption (sub)keys] - Array of key IDs to use for encryption. Each encryptionKeyIDs[i] corresponds to encryptionKeys[i] + * @param {Date} [options.date=current date] - Override the date + * @param {Object|Object[]} [options.encryptionUserIDs=primary user IDs] - Array of user IDs to encrypt for, one per key in `encryptionKeys`, e.g. `[{ name: 'Phil Zimmermann', email: 'phil@openpgp.org' }]` + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} Encrypted session keys (string if `armor` was true, the default; Uint8Array if `armor` was false). + * @async + * @static + */ +async function encryptSessionKey({ data, algorithm, aeadAlgorithm, encryptionKeys, passwords, format = 'armored', wildcard = false, encryptionKeyIDs = [], date = new Date(), encryptionUserIDs = [], config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + checkBinary(data); checkString(algorithm, 'algorithm'); checkOutputMessageFormat(format); + encryptionKeys = toArray$1(encryptionKeys); passwords = toArray$1(passwords); encryptionKeyIDs = toArray$1(encryptionKeyIDs); encryptionUserIDs = toArray$1(encryptionUserIDs); + if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.encryptSessionKey, pass `encryptionKeys` instead'); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + try { + const message = await Message.encryptSessionKey(data, algorithm, aeadAlgorithm, encryptionKeys, passwords, wildcard, encryptionKeyIDs, date, encryptionUserIDs, config); + return formatObject(message, format, config); + } catch (err) { + throw util.wrapError('Error encrypting session key', err); + } +} + +/** + * Decrypt symmetric session keys using private keys or passwords (not both). + * One of `decryptionKeys` or `passwords` must be specified. + * @param {Object} options + * @param {Message} options.message - A message object containing the encrypted session key packets + * @param {PrivateKey|PrivateKey[]} [options.decryptionKeys] - Private keys with decrypted secret key data + * @param {String|String[]} [options.passwords] - Passwords to decrypt the session key + * @param {Date} [options.date] - Date to use for key verification instead of the current time + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} Array of decrypted session key, algorithm pairs in the form: + * { data:Uint8Array, algorithm:String } + * @throws if no session key could be found or decrypted + * @async + * @static + */ +async function decryptSessionKeys({ message, decryptionKeys, passwords, date = new Date(), config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + checkMessage(message); decryptionKeys = toArray$1(decryptionKeys); passwords = toArray$1(passwords); + if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.decryptSessionKeys, pass `decryptionKeys` instead'); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + try { + const sessionKeys = await message.decryptSessionKeys(decryptionKeys, passwords, date, config); + return sessionKeys; + } catch (err) { + throw util.wrapError('Error decrypting session keys', err); + } +} + + +////////////////////////// +// // +// Helper functions // +// // +////////////////////////// + + +/** + * Input validation + * @private + */ +function checkString(data, name) { + if (!util.isString(data)) { + throw new Error('Parameter [' + (name || 'data') + '] must be of type String'); + } +} +function checkBinary(data, name) { + if (!util.isUint8Array(data)) { + throw new Error('Parameter [' + (name || 'data') + '] must be of type Uint8Array'); + } +} +function checkMessage(message) { + if (!(message instanceof Message)) { + throw new Error('Parameter [message] needs to be of type Message'); + } +} +function checkCleartextOrMessage(message) { + if (!(message instanceof CleartextMessage) && !(message instanceof Message)) { + throw new Error('Parameter [message] needs to be of type Message or CleartextMessage'); + } +} +function checkOutputMessageFormat(format) { + if (format !== 'armored' && format !== 'binary' && format !== 'object') { + throw new Error(`Unsupported format ${format}`); + } +} +const defaultConfigPropsCount = Object.keys(defaultConfig).length; +function checkConfig(config) { + const inputConfigProps = Object.keys(config); + if (inputConfigProps.length !== defaultConfigPropsCount) { + for (const inputProp of inputConfigProps) { + if (defaultConfig[inputProp] === undefined) { + throw new Error(`Unknown config property: ${inputProp}`); + } + } + } +} + +/** + * Normalize parameter to an array if it is not undefined. + * @param {Object} param - the parameter to be normalized + * @returns {Array|undefined} The resulting array or undefined. + * @private + */ +function toArray$1(param) { + if (param && !util.isArray(param)) { + param = [param]; + } + return param; +} + +/** + * Convert data to or from Stream + * @param {Object} data - the data to convert + * @param {'web'|'ponyfill'|'node'|false} streaming - Whether to return a ReadableStream, and of what type + * @param {'utf8'|'binary'} [encoding] - How to return data in Node Readable streams + * @returns {Promise} The data in the respective format. + * @async + * @private + */ +async function convertStream(data, streaming, encoding = 'utf8') { + const streamType = util.isStream(data); + if (streamType === 'array') { + return readToEnd(data); + } + if (streaming === 'node') { + data = webToNode(data); + if (encoding !== 'binary') data.setEncoding(encoding); + return data; + } + if (streaming === 'web' && streamType === 'ponyfill') { + return toNativeReadable(data); + } + return data; +} + +/** + * Link result.data to the message stream for cancellation. + * Also, forward errors in the message to result.data. + * @param {Object} result - the data to convert + * @param {Message} message - message object + * @returns {Object} + * @private + */ +function linkStreams(result, message) { + result.data = transformPair(message.packets.stream, async (readable, writable) => { + await pipe(result.data, writable, { + preventClose: true + }); + const writer = getWriter(writable); + try { + // Forward errors in the message stream to result.data. + await readToEnd(readable, _ => _); + await writer.close(); + } catch (e) { + await writer.abort(e); + } + }); +} + +/** + * Convert the object to the given format + * @param {Key|Message} object + * @param {'armored'|'binary'|'object'} format + * @param {Object} config - Full configuration + * @returns {String|Uint8Array|Object} + */ +function formatObject(object, format, config) { + switch (format) { + case 'object': + return object; + case 'armored': + return object.armor(config); + case 'binary': + return object.write(); + default: + throw new Error(`Unsupported format ${format}`); + } +} + +/** + * web-streams-polyfill v3.0.3 + */ +/// +const SymbolPolyfill = typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol' ? + Symbol : + description => `Symbol(${description})`; + +/// +function noop() { + return undefined; +} +function getGlobals() { + if (typeof self !== 'undefined') { + return self; + } + else if (typeof window !== 'undefined') { + return window; + } + else if (typeof global !== 'undefined') { + return global; + } + return undefined; +} +const globals = getGlobals(); + +function typeIsObject(x) { + return (typeof x === 'object' && x !== null) || typeof x === 'function'; +} +const rethrowAssertionErrorRejection = noop; + +const originalPromise = Promise; +const originalPromiseThen = Promise.prototype.then; +const originalPromiseResolve = Promise.resolve.bind(originalPromise); +const originalPromiseReject = Promise.reject.bind(originalPromise); +function newPromise(executor) { + return new originalPromise(executor); +} +function promiseResolvedWith(value) { + return originalPromiseResolve(value); +} +function promiseRejectedWith(reason) { + return originalPromiseReject(reason); +} +function PerformPromiseThen(promise, onFulfilled, onRejected) { + // There doesn't appear to be any way to correctly emulate the behaviour from JavaScript, so this is just an + // approximation. + return originalPromiseThen.call(promise, onFulfilled, onRejected); +} +function uponPromise(promise, onFulfilled, onRejected) { + PerformPromiseThen(PerformPromiseThen(promise, onFulfilled, onRejected), undefined, rethrowAssertionErrorRejection); +} +function uponFulfillment(promise, onFulfilled) { + uponPromise(promise, onFulfilled); +} +function uponRejection(promise, onRejected) { + uponPromise(promise, undefined, onRejected); +} +function transformPromiseWith(promise, fulfillmentHandler, rejectionHandler) { + return PerformPromiseThen(promise, fulfillmentHandler, rejectionHandler); +} +function setPromiseIsHandledToTrue(promise) { + PerformPromiseThen(promise, undefined, rethrowAssertionErrorRejection); +} +const queueMicrotask = (() => { + const globalQueueMicrotask = globals && globals.queueMicrotask; + if (typeof globalQueueMicrotask === 'function') { + return globalQueueMicrotask; + } + const resolvedPromise = promiseResolvedWith(undefined); + return (fn) => PerformPromiseThen(resolvedPromise, fn); +})(); +function reflectCall(F, V, args) { + if (typeof F !== 'function') { + throw new TypeError('Argument is not a function'); + } + return Function.prototype.apply.call(F, V, args); +} +function promiseCall(F, V, args) { + try { + return promiseResolvedWith(reflectCall(F, V, args)); + } + catch (value) { + return promiseRejectedWith(value); + } +} + +// Original from Chromium +// https://chromium.googlesource.com/chromium/src/+/0aee4434a4dba42a42abaea9bfbc0cd196a63bc1/third_party/blink/renderer/core/streams/SimpleQueue.js +const QUEUE_MAX_ARRAY_SIZE = 16384; +/** + * Simple queue structure. + * + * Avoids scalability issues with using a packed array directly by using + * multiple arrays in a linked list and keeping the array size bounded. + */ +class SimpleQueue { + constructor() { + this._cursor = 0; + this._size = 0; + // _front and _back are always defined. + this._front = { + _elements: [], + _next: undefined + }; + this._back = this._front; + // The cursor is used to avoid calling Array.shift(). + // It contains the index of the front element of the array inside the + // front-most node. It is always in the range [0, QUEUE_MAX_ARRAY_SIZE). + this._cursor = 0; + // When there is only one node, size === elements.length - cursor. + this._size = 0; + } + get length() { + return this._size; + } + // For exception safety, this method is structured in order: + // 1. Read state + // 2. Calculate required state mutations + // 3. Perform state mutations + push(element) { + const oldBack = this._back; + let newBack = oldBack; + if (oldBack._elements.length === QUEUE_MAX_ARRAY_SIZE - 1) { + newBack = { + _elements: [], + _next: undefined + }; + } + // push() is the mutation most likely to throw an exception, so it + // goes first. + oldBack._elements.push(element); + if (newBack !== oldBack) { + this._back = newBack; + oldBack._next = newBack; + } + ++this._size; + } + // Like push(), shift() follows the read -> calculate -> mutate pattern for + // exception safety. + shift() { // must not be called on an empty queue + const oldFront = this._front; + let newFront = oldFront; + const oldCursor = this._cursor; + let newCursor = oldCursor + 1; + const elements = oldFront._elements; + const element = elements[oldCursor]; + if (newCursor === QUEUE_MAX_ARRAY_SIZE) { + newFront = oldFront._next; + newCursor = 0; + } + // No mutations before this point. + --this._size; + this._cursor = newCursor; + if (oldFront !== newFront) { + this._front = newFront; + } + // Permit shifted element to be garbage collected. + elements[oldCursor] = undefined; + return element; + } + // The tricky thing about forEach() is that it can be called + // re-entrantly. The queue may be mutated inside the callback. It is easy to + // see that push() within the callback has no negative effects since the end + // of the queue is checked for on every iteration. If shift() is called + // repeatedly within the callback then the next iteration may return an + // element that has been removed. In this case the callback will be called + // with undefined values until we either "catch up" with elements that still + // exist or reach the back of the queue. + forEach(callback) { + let i = this._cursor; + let node = this._front; + let elements = node._elements; + while (i !== elements.length || node._next !== undefined) { + if (i === elements.length) { + node = node._next; + elements = node._elements; + i = 0; + if (elements.length === 0) { + break; + } + } + callback(elements[i]); + ++i; + } + } + // Return the element that would be returned if shift() was called now, + // without modifying the queue. + peek() { // must not be called on an empty queue + const front = this._front; + const cursor = this._cursor; + return front._elements[cursor]; + } +} + +function ReadableStreamReaderGenericInitialize(reader, stream) { + reader._ownerReadableStream = stream; + stream._reader = reader; + if (stream._state === 'readable') { + defaultReaderClosedPromiseInitialize(reader); + } + else if (stream._state === 'closed') { + defaultReaderClosedPromiseInitializeAsResolved(reader); + } + else { + defaultReaderClosedPromiseInitializeAsRejected(reader, stream._storedError); + } +} +// A client of ReadableStreamDefaultReader and ReadableStreamBYOBReader may use these functions directly to bypass state +// check. +function ReadableStreamReaderGenericCancel(reader, reason) { + const stream = reader._ownerReadableStream; + return ReadableStreamCancel(stream, reason); +} +function ReadableStreamReaderGenericRelease(reader) { + if (reader._ownerReadableStream._state === 'readable') { + defaultReaderClosedPromiseReject(reader, new TypeError(`Reader was released and can no longer be used to monitor the stream's closedness`)); + } + else { + defaultReaderClosedPromiseResetToRejected(reader, new TypeError(`Reader was released and can no longer be used to monitor the stream's closedness`)); + } + reader._ownerReadableStream._reader = undefined; + reader._ownerReadableStream = undefined; +} +// Helper functions for the readers. +function readerLockException(name) { + return new TypeError('Cannot ' + name + ' a stream using a released reader'); +} +// Helper functions for the ReadableStreamDefaultReader. +function defaultReaderClosedPromiseInitialize(reader) { + reader._closedPromise = newPromise((resolve, reject) => { + reader._closedPromise_resolve = resolve; + reader._closedPromise_reject = reject; + }); +} +function defaultReaderClosedPromiseInitializeAsRejected(reader, reason) { + defaultReaderClosedPromiseInitialize(reader); + defaultReaderClosedPromiseReject(reader, reason); +} +function defaultReaderClosedPromiseInitializeAsResolved(reader) { + defaultReaderClosedPromiseInitialize(reader); + defaultReaderClosedPromiseResolve(reader); +} +function defaultReaderClosedPromiseReject(reader, reason) { + if (reader._closedPromise_reject === undefined) { + return; + } + setPromiseIsHandledToTrue(reader._closedPromise); + reader._closedPromise_reject(reason); + reader._closedPromise_resolve = undefined; + reader._closedPromise_reject = undefined; +} +function defaultReaderClosedPromiseResetToRejected(reader, reason) { + defaultReaderClosedPromiseInitializeAsRejected(reader, reason); +} +function defaultReaderClosedPromiseResolve(reader) { + if (reader._closedPromise_resolve === undefined) { + return; + } + reader._closedPromise_resolve(undefined); + reader._closedPromise_resolve = undefined; + reader._closedPromise_reject = undefined; +} + +const AbortSteps = SymbolPolyfill('[[AbortSteps]]'); +const ErrorSteps = SymbolPolyfill('[[ErrorSteps]]'); +const CancelSteps = SymbolPolyfill('[[CancelSteps]]'); +const PullSteps = SymbolPolyfill('[[PullSteps]]'); + +/// +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isFinite#Polyfill +const NumberIsFinite = Number.isFinite || function (x) { + return typeof x === 'number' && isFinite(x); +}; + +/// +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc#Polyfill +const MathTrunc = Math.trunc || function (v) { + return v < 0 ? Math.ceil(v) : Math.floor(v); +}; + +// https://heycam.github.io/webidl/#idl-dictionaries +function isDictionary(x) { + return typeof x === 'object' || typeof x === 'function'; +} +function assertDictionary(obj, context) { + if (obj !== undefined && !isDictionary(obj)) { + throw new TypeError(`${context} is not an object.`); + } +} +// https://heycam.github.io/webidl/#idl-callback-functions +function assertFunction(x, context) { + if (typeof x !== 'function') { + throw new TypeError(`${context} is not a function.`); + } +} +// https://heycam.github.io/webidl/#idl-object +function isObject(x) { + return (typeof x === 'object' && x !== null) || typeof x === 'function'; +} +function assertObject(x, context) { + if (!isObject(x)) { + throw new TypeError(`${context} is not an object.`); + } +} +function assertRequiredArgument(x, position, context) { + if (x === undefined) { + throw new TypeError(`Parameter ${position} is required in '${context}'.`); + } +} +function assertRequiredField(x, field, context) { + if (x === undefined) { + throw new TypeError(`${field} is required in '${context}'.`); + } +} +// https://heycam.github.io/webidl/#idl-unrestricted-double +function convertUnrestrictedDouble(value) { + return Number(value); +} +function censorNegativeZero(x) { + return x === 0 ? 0 : x; +} +function integerPart(x) { + return censorNegativeZero(MathTrunc(x)); +} +// https://heycam.github.io/webidl/#idl-unsigned-long-long +function convertUnsignedLongLongWithEnforceRange(value, context) { + const lowerBound = 0; + const upperBound = Number.MAX_SAFE_INTEGER; + let x = Number(value); + x = censorNegativeZero(x); + if (!NumberIsFinite(x)) { + throw new TypeError(`${context} is not a finite number`); + } + x = integerPart(x); + if (x < lowerBound || x > upperBound) { + throw new TypeError(`${context} is outside the accepted range of ${lowerBound} to ${upperBound}, inclusive`); + } + if (!NumberIsFinite(x) || x === 0) { + return 0; + } + // TODO Use BigInt if supported? + // let xBigInt = BigInt(integerPart(x)); + // xBigInt = BigInt.asUintN(64, xBigInt); + // return Number(xBigInt); + return x; +} + +function assertReadableStream(x, context) { + if (!IsReadableStream(x)) { + throw new TypeError(`${context} is not a ReadableStream.`); + } +} + +// Abstract operations for the ReadableStream. +function AcquireReadableStreamDefaultReader(stream) { + return new ReadableStreamDefaultReader(stream); +} +// ReadableStream API exposed for controllers. +function ReadableStreamAddReadRequest(stream, readRequest) { + stream._reader._readRequests.push(readRequest); +} +function ReadableStreamFulfillReadRequest(stream, chunk, done) { + const reader = stream._reader; + const readRequest = reader._readRequests.shift(); + if (done) { + readRequest._closeSteps(); + } + else { + readRequest._chunkSteps(chunk); + } +} +function ReadableStreamGetNumReadRequests(stream) { + return stream._reader._readRequests.length; +} +function ReadableStreamHasDefaultReader(stream) { + const reader = stream._reader; + if (reader === undefined) { + return false; + } + if (!IsReadableStreamDefaultReader(reader)) { + return false; + } + return true; +} +/** + * A default reader vended by a {@link ReadableStream}. + * + * @public + */ +class ReadableStreamDefaultReader { + constructor(stream) { + assertRequiredArgument(stream, 1, 'ReadableStreamDefaultReader'); + assertReadableStream(stream, 'First parameter'); + if (IsReadableStreamLocked(stream)) { + throw new TypeError('This stream has already been locked for exclusive reading by another reader'); + } + ReadableStreamReaderGenericInitialize(this, stream); + this._readRequests = new SimpleQueue(); + } + /** + * Returns a promise that will be fulfilled when the stream becomes closed, + * or rejected if the stream ever errors or the reader's lock is released before the stream finishes closing. + */ + get closed() { + if (!IsReadableStreamDefaultReader(this)) { + return promiseRejectedWith(defaultReaderBrandCheckException('closed')); + } + return this._closedPromise; + } + /** + * If the reader is active, behaves the same as {@link ReadableStream.cancel | stream.cancel(reason)}. + */ + cancel(reason = undefined) { + if (!IsReadableStreamDefaultReader(this)) { + return promiseRejectedWith(defaultReaderBrandCheckException('cancel')); + } + if (this._ownerReadableStream === undefined) { + return promiseRejectedWith(readerLockException('cancel')); + } + return ReadableStreamReaderGenericCancel(this, reason); + } + /** + * Returns a promise that allows access to the next chunk from the stream's internal queue, if available. + * + * If reading a chunk causes the queue to become empty, more data will be pulled from the underlying source. + */ + read() { + if (!IsReadableStreamDefaultReader(this)) { + return promiseRejectedWith(defaultReaderBrandCheckException('read')); + } + if (this._ownerReadableStream === undefined) { + return promiseRejectedWith(readerLockException('read from')); + } + let resolvePromise; + let rejectPromise; + const promise = newPromise((resolve, reject) => { + resolvePromise = resolve; + rejectPromise = reject; + }); + const readRequest = { + _chunkSteps: chunk => resolvePromise({ value: chunk, done: false }), + _closeSteps: () => resolvePromise({ value: undefined, done: true }), + _errorSteps: e => rejectPromise(e) + }; + ReadableStreamDefaultReaderRead(this, readRequest); + return promise; + } + /** + * Releases the reader's lock on the corresponding stream. After the lock is released, the reader is no longer active. + * If the associated stream is errored when the lock is released, the reader will appear errored in the same way + * from now on; otherwise, the reader will appear closed. + * + * A reader's lock cannot be released while it still has a pending read request, i.e., if a promise returned by + * the reader's {@link ReadableStreamDefaultReader.read | read()} method has not yet been settled. Attempting to + * do so will throw a `TypeError` and leave the reader locked to the stream. + */ + releaseLock() { + if (!IsReadableStreamDefaultReader(this)) { + throw defaultReaderBrandCheckException('releaseLock'); + } + if (this._ownerReadableStream === undefined) { + return; + } + if (this._readRequests.length > 0) { + throw new TypeError('Tried to release a reader lock when that reader has pending read() calls un-settled'); + } + ReadableStreamReaderGenericRelease(this); + } +} +Object.defineProperties(ReadableStreamDefaultReader.prototype, { + cancel: { enumerable: true }, + read: { enumerable: true }, + releaseLock: { enumerable: true }, + closed: { enumerable: true } +}); +if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(ReadableStreamDefaultReader.prototype, SymbolPolyfill.toStringTag, { + value: 'ReadableStreamDefaultReader', + configurable: true + }); +} +// Abstract operations for the readers. +function IsReadableStreamDefaultReader(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_readRequests')) { + return false; + } + return true; +} +function ReadableStreamDefaultReaderRead(reader, readRequest) { + const stream = reader._ownerReadableStream; + stream._disturbed = true; + if (stream._state === 'closed') { + readRequest._closeSteps(); + } + else if (stream._state === 'errored') { + readRequest._errorSteps(stream._storedError); + } + else { + stream._readableStreamController[PullSteps](readRequest); + } +} +// Helper functions for the ReadableStreamDefaultReader. +function defaultReaderBrandCheckException(name) { + return new TypeError(`ReadableStreamDefaultReader.prototype.${name} can only be used on a ReadableStreamDefaultReader`); +} + +/// +let AsyncIteratorPrototype; +if (typeof SymbolPolyfill.asyncIterator === 'symbol') { + // We're running inside a ES2018+ environment, but we're compiling to an older syntax. + // We cannot access %AsyncIteratorPrototype% without non-ES2018 syntax, but we can re-create it. + AsyncIteratorPrototype = { + // 25.1.3.1 %AsyncIteratorPrototype% [ @@asyncIterator ] ( ) + // https://tc39.github.io/ecma262/#sec-asynciteratorprototype-asynciterator + [SymbolPolyfill.asyncIterator]() { + return this; + } + }; + Object.defineProperty(AsyncIteratorPrototype, SymbolPolyfill.asyncIterator, { enumerable: false }); +} + +/// +class ReadableStreamAsyncIteratorImpl { + constructor(reader, preventCancel) { + this._ongoingPromise = undefined; + this._isFinished = false; + this._reader = reader; + this._preventCancel = preventCancel; + } + next() { + const nextSteps = () => this._nextSteps(); + this._ongoingPromise = this._ongoingPromise ? + transformPromiseWith(this._ongoingPromise, nextSteps, nextSteps) : + nextSteps(); + return this._ongoingPromise; + } + return(value) { + const returnSteps = () => this._returnSteps(value); + return this._ongoingPromise ? + transformPromiseWith(this._ongoingPromise, returnSteps, returnSteps) : + returnSteps(); + } + _nextSteps() { + if (this._isFinished) { + return Promise.resolve({ value: undefined, done: true }); + } + const reader = this._reader; + if (reader._ownerReadableStream === undefined) { + return promiseRejectedWith(readerLockException('iterate')); + } + let resolvePromise; + let rejectPromise; + const promise = newPromise((resolve, reject) => { + resolvePromise = resolve; + rejectPromise = reject; + }); + const readRequest = { + _chunkSteps: chunk => { + this._ongoingPromise = undefined; + // This needs to be delayed by one microtask, otherwise we stop pulling too early which breaks a test. + // FIXME Is this a bug in the specification, or in the test? + queueMicrotask(() => resolvePromise({ value: chunk, done: false })); + }, + _closeSteps: () => { + this._ongoingPromise = undefined; + this._isFinished = true; + ReadableStreamReaderGenericRelease(reader); + resolvePromise({ value: undefined, done: true }); + }, + _errorSteps: reason => { + this._ongoingPromise = undefined; + this._isFinished = true; + ReadableStreamReaderGenericRelease(reader); + rejectPromise(reason); + } + }; + ReadableStreamDefaultReaderRead(reader, readRequest); + return promise; + } + _returnSteps(value) { + if (this._isFinished) { + return Promise.resolve({ value, done: true }); + } + this._isFinished = true; + const reader = this._reader; + if (reader._ownerReadableStream === undefined) { + return promiseRejectedWith(readerLockException('finish iterating')); + } + if (!this._preventCancel) { + const result = ReadableStreamReaderGenericCancel(reader, value); + ReadableStreamReaderGenericRelease(reader); + return transformPromiseWith(result, () => ({ value, done: true })); + } + ReadableStreamReaderGenericRelease(reader); + return promiseResolvedWith({ value, done: true }); + } +} +const ReadableStreamAsyncIteratorPrototype = { + next() { + if (!IsReadableStreamAsyncIterator(this)) { + return promiseRejectedWith(streamAsyncIteratorBrandCheckException('next')); + } + return this._asyncIteratorImpl.next(); + }, + return(value) { + if (!IsReadableStreamAsyncIterator(this)) { + return promiseRejectedWith(streamAsyncIteratorBrandCheckException('return')); + } + return this._asyncIteratorImpl.return(value); + } +}; +if (AsyncIteratorPrototype !== undefined) { + Object.setPrototypeOf(ReadableStreamAsyncIteratorPrototype, AsyncIteratorPrototype); +} +// Abstract operations for the ReadableStream. +function AcquireReadableStreamAsyncIterator(stream, preventCancel) { + const reader = AcquireReadableStreamDefaultReader(stream); + const impl = new ReadableStreamAsyncIteratorImpl(reader, preventCancel); + const iterator = Object.create(ReadableStreamAsyncIteratorPrototype); + iterator._asyncIteratorImpl = impl; + return iterator; +} +function IsReadableStreamAsyncIterator(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_asyncIteratorImpl')) { + return false; + } + return true; +} +// Helper functions for the ReadableStream. +function streamAsyncIteratorBrandCheckException(name) { + return new TypeError(`ReadableStreamAsyncIterator.${name} can only be used on a ReadableSteamAsyncIterator`); +} + +/// +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN#Polyfill +const NumberIsNaN = Number.isNaN || function (x) { + // eslint-disable-next-line no-self-compare + return x !== x; +}; + +function IsFiniteNonNegativeNumber(v) { + if (!IsNonNegativeNumber(v)) { + return false; + } + if (v === Infinity) { + return false; + } + return true; +} +function IsNonNegativeNumber(v) { + if (typeof v !== 'number') { + return false; + } + if (NumberIsNaN(v)) { + return false; + } + if (v < 0) { + return false; + } + return true; +} + +function DequeueValue(container) { + const pair = container._queue.shift(); + container._queueTotalSize -= pair.size; + if (container._queueTotalSize < 0) { + container._queueTotalSize = 0; + } + return pair.value; +} +function EnqueueValueWithSize(container, value, size) { + size = Number(size); + if (!IsFiniteNonNegativeNumber(size)) { + throw new RangeError('Size must be a finite, non-NaN, non-negative number.'); + } + container._queue.push({ value, size }); + container._queueTotalSize += size; +} +function PeekQueueValue(container) { + const pair = container._queue.peek(); + return pair.value; +} +function ResetQueue(container) { + container._queue = new SimpleQueue(); + container._queueTotalSize = 0; +} + +function CreateArrayFromList(elements) { + // We use arrays to represent lists, so this is basically a no-op. + // Do a slice though just in case we happen to depend on the unique-ness. + return elements.slice(); +} +function CopyDataBlockBytes(dest, destOffset, src, srcOffset, n) { + new Uint8Array(dest).set(new Uint8Array(src, srcOffset, n), destOffset); +} +// Not implemented correctly +function TransferArrayBuffer(O) { + return O; +} +// Not implemented correctly +function IsDetachedBuffer(O) { + return false; +} + +/** + * A pull-into request in a {@link ReadableByteStreamController}. + * + * @public + */ +class ReadableStreamBYOBRequest { + constructor() { + throw new TypeError('Illegal constructor'); + } + /** + * Returns the view for writing in to, or `null` if the BYOB request has already been responded to. + */ + get view() { + if (!IsReadableStreamBYOBRequest(this)) { + throw byobRequestBrandCheckException('view'); + } + return this._view; + } + respond(bytesWritten) { + if (!IsReadableStreamBYOBRequest(this)) { + throw byobRequestBrandCheckException('respond'); + } + assertRequiredArgument(bytesWritten, 1, 'respond'); + bytesWritten = convertUnsignedLongLongWithEnforceRange(bytesWritten, 'First parameter'); + if (this._associatedReadableByteStreamController === undefined) { + throw new TypeError('This BYOB request has been invalidated'); + } + if (IsDetachedBuffer(this._view.buffer)) ; + ReadableByteStreamControllerRespond(this._associatedReadableByteStreamController, bytesWritten); + } + respondWithNewView(view) { + if (!IsReadableStreamBYOBRequest(this)) { + throw byobRequestBrandCheckException('respondWithNewView'); + } + assertRequiredArgument(view, 1, 'respondWithNewView'); + if (!ArrayBuffer.isView(view)) { + throw new TypeError('You can only respond with array buffer views'); + } + if (view.byteLength === 0) { + throw new TypeError('chunk must have non-zero byteLength'); + } + if (view.buffer.byteLength === 0) { + throw new TypeError(`chunk's buffer must have non-zero byteLength`); + } + if (this._associatedReadableByteStreamController === undefined) { + throw new TypeError('This BYOB request has been invalidated'); + } + ReadableByteStreamControllerRespondWithNewView(this._associatedReadableByteStreamController, view); + } +} +Object.defineProperties(ReadableStreamBYOBRequest.prototype, { + respond: { enumerable: true }, + respondWithNewView: { enumerable: true }, + view: { enumerable: true } +}); +if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(ReadableStreamBYOBRequest.prototype, SymbolPolyfill.toStringTag, { + value: 'ReadableStreamBYOBRequest', + configurable: true + }); +} +/** + * Allows control of a {@link ReadableStream | readable byte stream}'s state and internal queue. + * + * @public + */ +class ReadableByteStreamController { + constructor() { + throw new TypeError('Illegal constructor'); + } + /** + * Returns the current BYOB pull request, or `null` if there isn't one. + */ + get byobRequest() { + if (!IsReadableByteStreamController(this)) { + throw byteStreamControllerBrandCheckException('byobRequest'); + } + if (this._byobRequest === null && this._pendingPullIntos.length > 0) { + const firstDescriptor = this._pendingPullIntos.peek(); + const view = new Uint8Array(firstDescriptor.buffer, firstDescriptor.byteOffset + firstDescriptor.bytesFilled, firstDescriptor.byteLength - firstDescriptor.bytesFilled); + const byobRequest = Object.create(ReadableStreamBYOBRequest.prototype); + SetUpReadableStreamBYOBRequest(byobRequest, this, view); + this._byobRequest = byobRequest; + } + return this._byobRequest; + } + /** + * Returns the desired size to fill the controlled stream's internal queue. It can be negative, if the queue is + * over-full. An underlying byte source ought to use this information to determine when and how to apply backpressure. + */ + get desiredSize() { + if (!IsReadableByteStreamController(this)) { + throw byteStreamControllerBrandCheckException('desiredSize'); + } + return ReadableByteStreamControllerGetDesiredSize(this); + } + /** + * Closes the controlled readable stream. Consumers will still be able to read any previously-enqueued chunks from + * the stream, but once those are read, the stream will become closed. + */ + close() { + if (!IsReadableByteStreamController(this)) { + throw byteStreamControllerBrandCheckException('close'); + } + if (this._closeRequested) { + throw new TypeError('The stream has already been closed; do not close it again!'); + } + const state = this._controlledReadableByteStream._state; + if (state !== 'readable') { + throw new TypeError(`The stream (in ${state} state) is not in the readable state and cannot be closed`); + } + ReadableByteStreamControllerClose(this); + } + enqueue(chunk) { + if (!IsReadableByteStreamController(this)) { + throw byteStreamControllerBrandCheckException('enqueue'); + } + assertRequiredArgument(chunk, 1, 'enqueue'); + if (!ArrayBuffer.isView(chunk)) { + throw new TypeError('chunk must be an array buffer view'); + } + if (chunk.byteLength === 0) { + throw new TypeError('chunk must have non-zero byteLength'); + } + if (chunk.buffer.byteLength === 0) { + throw new TypeError(`chunk's buffer must have non-zero byteLength`); + } + if (this._closeRequested) { + throw new TypeError('stream is closed or draining'); + } + const state = this._controlledReadableByteStream._state; + if (state !== 'readable') { + throw new TypeError(`The stream (in ${state} state) is not in the readable state and cannot be enqueued to`); + } + ReadableByteStreamControllerEnqueue(this, chunk); + } + /** + * Errors the controlled readable stream, making all future interactions with it fail with the given error `e`. + */ + error(e = undefined) { + if (!IsReadableByteStreamController(this)) { + throw byteStreamControllerBrandCheckException('error'); + } + ReadableByteStreamControllerError(this, e); + } + /** @internal */ + [CancelSteps](reason) { + if (this._pendingPullIntos.length > 0) { + const firstDescriptor = this._pendingPullIntos.peek(); + firstDescriptor.bytesFilled = 0; + } + ResetQueue(this); + const result = this._cancelAlgorithm(reason); + ReadableByteStreamControllerClearAlgorithms(this); + return result; + } + /** @internal */ + [PullSteps](readRequest) { + const stream = this._controlledReadableByteStream; + if (this._queueTotalSize > 0) { + const entry = this._queue.shift(); + this._queueTotalSize -= entry.byteLength; + ReadableByteStreamControllerHandleQueueDrain(this); + const view = new Uint8Array(entry.buffer, entry.byteOffset, entry.byteLength); + readRequest._chunkSteps(view); + return; + } + const autoAllocateChunkSize = this._autoAllocateChunkSize; + if (autoAllocateChunkSize !== undefined) { + let buffer; + try { + buffer = new ArrayBuffer(autoAllocateChunkSize); + } + catch (bufferE) { + readRequest._errorSteps(bufferE); + return; + } + const pullIntoDescriptor = { + buffer, + byteOffset: 0, + byteLength: autoAllocateChunkSize, + bytesFilled: 0, + elementSize: 1, + viewConstructor: Uint8Array, + readerType: 'default' + }; + this._pendingPullIntos.push(pullIntoDescriptor); + } + ReadableStreamAddReadRequest(stream, readRequest); + ReadableByteStreamControllerCallPullIfNeeded(this); + } +} +Object.defineProperties(ReadableByteStreamController.prototype, { + close: { enumerable: true }, + enqueue: { enumerable: true }, + error: { enumerable: true }, + byobRequest: { enumerable: true }, + desiredSize: { enumerable: true } +}); +if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(ReadableByteStreamController.prototype, SymbolPolyfill.toStringTag, { + value: 'ReadableByteStreamController', + configurable: true + }); +} +// Abstract operations for the ReadableByteStreamController. +function IsReadableByteStreamController(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_controlledReadableByteStream')) { + return false; + } + return true; +} +function IsReadableStreamBYOBRequest(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_associatedReadableByteStreamController')) { + return false; + } + return true; +} +function ReadableByteStreamControllerCallPullIfNeeded(controller) { + const shouldPull = ReadableByteStreamControllerShouldCallPull(controller); + if (!shouldPull) { + return; + } + if (controller._pulling) { + controller._pullAgain = true; + return; + } + controller._pulling = true; + // TODO: Test controller argument + const pullPromise = controller._pullAlgorithm(); + uponPromise(pullPromise, () => { + controller._pulling = false; + if (controller._pullAgain) { + controller._pullAgain = false; + ReadableByteStreamControllerCallPullIfNeeded(controller); + } + }, e => { + ReadableByteStreamControllerError(controller, e); + }); +} +function ReadableByteStreamControllerClearPendingPullIntos(controller) { + ReadableByteStreamControllerInvalidateBYOBRequest(controller); + controller._pendingPullIntos = new SimpleQueue(); +} +function ReadableByteStreamControllerCommitPullIntoDescriptor(stream, pullIntoDescriptor) { + let done = false; + if (stream._state === 'closed') { + done = true; + } + const filledView = ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor); + if (pullIntoDescriptor.readerType === 'default') { + ReadableStreamFulfillReadRequest(stream, filledView, done); + } + else { + ReadableStreamFulfillReadIntoRequest(stream, filledView, done); + } +} +function ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor) { + const bytesFilled = pullIntoDescriptor.bytesFilled; + const elementSize = pullIntoDescriptor.elementSize; + return new pullIntoDescriptor.viewConstructor(pullIntoDescriptor.buffer, pullIntoDescriptor.byteOffset, bytesFilled / elementSize); +} +function ReadableByteStreamControllerEnqueueChunkToQueue(controller, buffer, byteOffset, byteLength) { + controller._queue.push({ buffer, byteOffset, byteLength }); + controller._queueTotalSize += byteLength; +} +function ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor) { + const elementSize = pullIntoDescriptor.elementSize; + const currentAlignedBytes = pullIntoDescriptor.bytesFilled - pullIntoDescriptor.bytesFilled % elementSize; + const maxBytesToCopy = Math.min(controller._queueTotalSize, pullIntoDescriptor.byteLength - pullIntoDescriptor.bytesFilled); + const maxBytesFilled = pullIntoDescriptor.bytesFilled + maxBytesToCopy; + const maxAlignedBytes = maxBytesFilled - maxBytesFilled % elementSize; + let totalBytesToCopyRemaining = maxBytesToCopy; + let ready = false; + if (maxAlignedBytes > currentAlignedBytes) { + totalBytesToCopyRemaining = maxAlignedBytes - pullIntoDescriptor.bytesFilled; + ready = true; + } + const queue = controller._queue; + while (totalBytesToCopyRemaining > 0) { + const headOfQueue = queue.peek(); + const bytesToCopy = Math.min(totalBytesToCopyRemaining, headOfQueue.byteLength); + const destStart = pullIntoDescriptor.byteOffset + pullIntoDescriptor.bytesFilled; + CopyDataBlockBytes(pullIntoDescriptor.buffer, destStart, headOfQueue.buffer, headOfQueue.byteOffset, bytesToCopy); + if (headOfQueue.byteLength === bytesToCopy) { + queue.shift(); + } + else { + headOfQueue.byteOffset += bytesToCopy; + headOfQueue.byteLength -= bytesToCopy; + } + controller._queueTotalSize -= bytesToCopy; + ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, bytesToCopy, pullIntoDescriptor); + totalBytesToCopyRemaining -= bytesToCopy; + } + return ready; +} +function ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, size, pullIntoDescriptor) { + ReadableByteStreamControllerInvalidateBYOBRequest(controller); + pullIntoDescriptor.bytesFilled += size; +} +function ReadableByteStreamControllerHandleQueueDrain(controller) { + if (controller._queueTotalSize === 0 && controller._closeRequested) { + ReadableByteStreamControllerClearAlgorithms(controller); + ReadableStreamClose(controller._controlledReadableByteStream); + } + else { + ReadableByteStreamControllerCallPullIfNeeded(controller); + } +} +function ReadableByteStreamControllerInvalidateBYOBRequest(controller) { + if (controller._byobRequest === null) { + return; + } + controller._byobRequest._associatedReadableByteStreamController = undefined; + controller._byobRequest._view = null; + controller._byobRequest = null; +} +function ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller) { + while (controller._pendingPullIntos.length > 0) { + if (controller._queueTotalSize === 0) { + return; + } + const pullIntoDescriptor = controller._pendingPullIntos.peek(); + if (ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor)) { + ReadableByteStreamControllerShiftPendingPullInto(controller); + ReadableByteStreamControllerCommitPullIntoDescriptor(controller._controlledReadableByteStream, pullIntoDescriptor); + } + } +} +function ReadableByteStreamControllerPullInto(controller, view, readIntoRequest) { + const stream = controller._controlledReadableByteStream; + let elementSize = 1; + if (view.constructor !== DataView) { + elementSize = view.constructor.BYTES_PER_ELEMENT; + } + const ctor = view.constructor; + const buffer = TransferArrayBuffer(view.buffer); + const pullIntoDescriptor = { + buffer, + byteOffset: view.byteOffset, + byteLength: view.byteLength, + bytesFilled: 0, + elementSize, + viewConstructor: ctor, + readerType: 'byob' + }; + if (controller._pendingPullIntos.length > 0) { + controller._pendingPullIntos.push(pullIntoDescriptor); + // No ReadableByteStreamControllerCallPullIfNeeded() call since: + // - No change happens on desiredSize + // - The source has already been notified of that there's at least 1 pending read(view) + ReadableStreamAddReadIntoRequest(stream, readIntoRequest); + return; + } + if (stream._state === 'closed') { + const emptyView = new ctor(pullIntoDescriptor.buffer, pullIntoDescriptor.byteOffset, 0); + readIntoRequest._closeSteps(emptyView); + return; + } + if (controller._queueTotalSize > 0) { + if (ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor)) { + const filledView = ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor); + ReadableByteStreamControllerHandleQueueDrain(controller); + readIntoRequest._chunkSteps(filledView); + return; + } + if (controller._closeRequested) { + const e = new TypeError('Insufficient bytes to fill elements in the given buffer'); + ReadableByteStreamControllerError(controller, e); + readIntoRequest._errorSteps(e); + return; + } + } + controller._pendingPullIntos.push(pullIntoDescriptor); + ReadableStreamAddReadIntoRequest(stream, readIntoRequest); + ReadableByteStreamControllerCallPullIfNeeded(controller); +} +function ReadableByteStreamControllerRespondInClosedState(controller, firstDescriptor) { + firstDescriptor.buffer = TransferArrayBuffer(firstDescriptor.buffer); + const stream = controller._controlledReadableByteStream; + if (ReadableStreamHasBYOBReader(stream)) { + while (ReadableStreamGetNumReadIntoRequests(stream) > 0) { + const pullIntoDescriptor = ReadableByteStreamControllerShiftPendingPullInto(controller); + ReadableByteStreamControllerCommitPullIntoDescriptor(stream, pullIntoDescriptor); + } + } +} +function ReadableByteStreamControllerRespondInReadableState(controller, bytesWritten, pullIntoDescriptor) { + if (pullIntoDescriptor.bytesFilled + bytesWritten > pullIntoDescriptor.byteLength) { + throw new RangeError('bytesWritten out of range'); + } + ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, bytesWritten, pullIntoDescriptor); + if (pullIntoDescriptor.bytesFilled < pullIntoDescriptor.elementSize) { + // TODO: Figure out whether we should detach the buffer or not here. + return; + } + ReadableByteStreamControllerShiftPendingPullInto(controller); + const remainderSize = pullIntoDescriptor.bytesFilled % pullIntoDescriptor.elementSize; + if (remainderSize > 0) { + const end = pullIntoDescriptor.byteOffset + pullIntoDescriptor.bytesFilled; + const remainder = pullIntoDescriptor.buffer.slice(end - remainderSize, end); + ReadableByteStreamControllerEnqueueChunkToQueue(controller, remainder, 0, remainder.byteLength); + } + pullIntoDescriptor.buffer = TransferArrayBuffer(pullIntoDescriptor.buffer); + pullIntoDescriptor.bytesFilled -= remainderSize; + ReadableByteStreamControllerCommitPullIntoDescriptor(controller._controlledReadableByteStream, pullIntoDescriptor); + ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller); +} +function ReadableByteStreamControllerRespondInternal(controller, bytesWritten) { + const firstDescriptor = controller._pendingPullIntos.peek(); + const state = controller._controlledReadableByteStream._state; + if (state === 'closed') { + if (bytesWritten !== 0) { + throw new TypeError('bytesWritten must be 0 when calling respond() on a closed stream'); + } + ReadableByteStreamControllerRespondInClosedState(controller, firstDescriptor); + } + else { + ReadableByteStreamControllerRespondInReadableState(controller, bytesWritten, firstDescriptor); + } + ReadableByteStreamControllerCallPullIfNeeded(controller); +} +function ReadableByteStreamControllerShiftPendingPullInto(controller) { + const descriptor = controller._pendingPullIntos.shift(); + ReadableByteStreamControllerInvalidateBYOBRequest(controller); + return descriptor; +} +function ReadableByteStreamControllerShouldCallPull(controller) { + const stream = controller._controlledReadableByteStream; + if (stream._state !== 'readable') { + return false; + } + if (controller._closeRequested) { + return false; + } + if (!controller._started) { + return false; + } + if (ReadableStreamHasDefaultReader(stream) && ReadableStreamGetNumReadRequests(stream) > 0) { + return true; + } + if (ReadableStreamHasBYOBReader(stream) && ReadableStreamGetNumReadIntoRequests(stream) > 0) { + return true; + } + const desiredSize = ReadableByteStreamControllerGetDesiredSize(controller); + if (desiredSize > 0) { + return true; + } + return false; +} +function ReadableByteStreamControllerClearAlgorithms(controller) { + controller._pullAlgorithm = undefined; + controller._cancelAlgorithm = undefined; +} +// A client of ReadableByteStreamController may use these functions directly to bypass state check. +function ReadableByteStreamControllerClose(controller) { + const stream = controller._controlledReadableByteStream; + if (controller._closeRequested || stream._state !== 'readable') { + return; + } + if (controller._queueTotalSize > 0) { + controller._closeRequested = true; + return; + } + if (controller._pendingPullIntos.length > 0) { + const firstPendingPullInto = controller._pendingPullIntos.peek(); + if (firstPendingPullInto.bytesFilled > 0) { + const e = new TypeError('Insufficient bytes to fill elements in the given buffer'); + ReadableByteStreamControllerError(controller, e); + throw e; + } + } + ReadableByteStreamControllerClearAlgorithms(controller); + ReadableStreamClose(stream); +} +function ReadableByteStreamControllerEnqueue(controller, chunk) { + const stream = controller._controlledReadableByteStream; + if (controller._closeRequested || stream._state !== 'readable') { + return; + } + const buffer = chunk.buffer; + const byteOffset = chunk.byteOffset; + const byteLength = chunk.byteLength; + const transferredBuffer = TransferArrayBuffer(buffer); + if (ReadableStreamHasDefaultReader(stream)) { + if (ReadableStreamGetNumReadRequests(stream) === 0) { + ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength); + } + else { + const transferredView = new Uint8Array(transferredBuffer, byteOffset, byteLength); + ReadableStreamFulfillReadRequest(stream, transferredView, false); + } + } + else if (ReadableStreamHasBYOBReader(stream)) { + // TODO: Ideally in this branch detaching should happen only if the buffer is not consumed fully. + ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength); + ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller); + } + else { + ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength); + } + ReadableByteStreamControllerCallPullIfNeeded(controller); +} +function ReadableByteStreamControllerError(controller, e) { + const stream = controller._controlledReadableByteStream; + if (stream._state !== 'readable') { + return; + } + ReadableByteStreamControllerClearPendingPullIntos(controller); + ResetQueue(controller); + ReadableByteStreamControllerClearAlgorithms(controller); + ReadableStreamError(stream, e); +} +function ReadableByteStreamControllerGetDesiredSize(controller) { + const state = controller._controlledReadableByteStream._state; + if (state === 'errored') { + return null; + } + if (state === 'closed') { + return 0; + } + return controller._strategyHWM - controller._queueTotalSize; +} +function ReadableByteStreamControllerRespond(controller, bytesWritten) { + bytesWritten = Number(bytesWritten); + if (!IsFiniteNonNegativeNumber(bytesWritten)) { + throw new RangeError('bytesWritten must be a finite'); + } + ReadableByteStreamControllerRespondInternal(controller, bytesWritten); +} +function ReadableByteStreamControllerRespondWithNewView(controller, view) { + const firstDescriptor = controller._pendingPullIntos.peek(); + if (firstDescriptor.byteOffset + firstDescriptor.bytesFilled !== view.byteOffset) { + throw new RangeError('The region specified by view does not match byobRequest'); + } + if (firstDescriptor.byteLength !== view.byteLength) { + throw new RangeError('The buffer of view has different capacity than byobRequest'); + } + firstDescriptor.buffer = view.buffer; + ReadableByteStreamControllerRespondInternal(controller, view.byteLength); +} +function SetUpReadableByteStreamController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, autoAllocateChunkSize) { + controller._controlledReadableByteStream = stream; + controller._pullAgain = false; + controller._pulling = false; + controller._byobRequest = null; + // Need to set the slots so that the assert doesn't fire. In the spec the slots already exist implicitly. + controller._queue = controller._queueTotalSize = undefined; + ResetQueue(controller); + controller._closeRequested = false; + controller._started = false; + controller._strategyHWM = highWaterMark; + controller._pullAlgorithm = pullAlgorithm; + controller._cancelAlgorithm = cancelAlgorithm; + controller._autoAllocateChunkSize = autoAllocateChunkSize; + controller._pendingPullIntos = new SimpleQueue(); + stream._readableStreamController = controller; + const startResult = startAlgorithm(); + uponPromise(promiseResolvedWith(startResult), () => { + controller._started = true; + ReadableByteStreamControllerCallPullIfNeeded(controller); + }, r => { + ReadableByteStreamControllerError(controller, r); + }); +} +function SetUpReadableByteStreamControllerFromUnderlyingSource(stream, underlyingByteSource, highWaterMark) { + const controller = Object.create(ReadableByteStreamController.prototype); + let startAlgorithm = () => undefined; + let pullAlgorithm = () => promiseResolvedWith(undefined); + let cancelAlgorithm = () => promiseResolvedWith(undefined); + if (underlyingByteSource.start !== undefined) { + startAlgorithm = () => underlyingByteSource.start(controller); + } + if (underlyingByteSource.pull !== undefined) { + pullAlgorithm = () => underlyingByteSource.pull(controller); + } + if (underlyingByteSource.cancel !== undefined) { + cancelAlgorithm = reason => underlyingByteSource.cancel(reason); + } + const autoAllocateChunkSize = underlyingByteSource.autoAllocateChunkSize; + if (autoAllocateChunkSize === 0) { + throw new TypeError('autoAllocateChunkSize must be greater than 0'); + } + SetUpReadableByteStreamController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, autoAllocateChunkSize); +} +function SetUpReadableStreamBYOBRequest(request, controller, view) { + request._associatedReadableByteStreamController = controller; + request._view = view; +} +// Helper functions for the ReadableStreamBYOBRequest. +function byobRequestBrandCheckException(name) { + return new TypeError(`ReadableStreamBYOBRequest.prototype.${name} can only be used on a ReadableStreamBYOBRequest`); +} +// Helper functions for the ReadableByteStreamController. +function byteStreamControllerBrandCheckException(name) { + return new TypeError(`ReadableByteStreamController.prototype.${name} can only be used on a ReadableByteStreamController`); +} + +// Abstract operations for the ReadableStream. +function AcquireReadableStreamBYOBReader(stream) { + return new ReadableStreamBYOBReader(stream); +} +// ReadableStream API exposed for controllers. +function ReadableStreamAddReadIntoRequest(stream, readIntoRequest) { + stream._reader._readIntoRequests.push(readIntoRequest); +} +function ReadableStreamFulfillReadIntoRequest(stream, chunk, done) { + const reader = stream._reader; + const readIntoRequest = reader._readIntoRequests.shift(); + if (done) { + readIntoRequest._closeSteps(chunk); + } + else { + readIntoRequest._chunkSteps(chunk); + } +} +function ReadableStreamGetNumReadIntoRequests(stream) { + return stream._reader._readIntoRequests.length; +} +function ReadableStreamHasBYOBReader(stream) { + const reader = stream._reader; + if (reader === undefined) { + return false; + } + if (!IsReadableStreamBYOBReader(reader)) { + return false; + } + return true; +} +/** + * A BYOB reader vended by a {@link ReadableStream}. + * + * @public + */ +class ReadableStreamBYOBReader { + constructor(stream) { + assertRequiredArgument(stream, 1, 'ReadableStreamBYOBReader'); + assertReadableStream(stream, 'First parameter'); + if (IsReadableStreamLocked(stream)) { + throw new TypeError('This stream has already been locked for exclusive reading by another reader'); + } + if (!IsReadableByteStreamController(stream._readableStreamController)) { + throw new TypeError('Cannot construct a ReadableStreamBYOBReader for a stream not constructed with a byte ' + + 'source'); + } + ReadableStreamReaderGenericInitialize(this, stream); + this._readIntoRequests = new SimpleQueue(); + } + /** + * Returns a promise that will be fulfilled when the stream becomes closed, or rejected if the stream ever errors or + * the reader's lock is released before the stream finishes closing. + */ + get closed() { + if (!IsReadableStreamBYOBReader(this)) { + return promiseRejectedWith(byobReaderBrandCheckException('closed')); + } + return this._closedPromise; + } + /** + * If the reader is active, behaves the same as {@link ReadableStream.cancel | stream.cancel(reason)}. + */ + cancel(reason = undefined) { + if (!IsReadableStreamBYOBReader(this)) { + return promiseRejectedWith(byobReaderBrandCheckException('cancel')); + } + if (this._ownerReadableStream === undefined) { + return promiseRejectedWith(readerLockException('cancel')); + } + return ReadableStreamReaderGenericCancel(this, reason); + } + /** + * Attempts to reads bytes into view, and returns a promise resolved with the result. + * + * If reading a chunk causes the queue to become empty, more data will be pulled from the underlying source. + */ + read(view) { + if (!IsReadableStreamBYOBReader(this)) { + return promiseRejectedWith(byobReaderBrandCheckException('read')); + } + if (!ArrayBuffer.isView(view)) { + return promiseRejectedWith(new TypeError('view must be an array buffer view')); + } + if (view.byteLength === 0) { + return promiseRejectedWith(new TypeError('view must have non-zero byteLength')); + } + if (view.buffer.byteLength === 0) { + return promiseRejectedWith(new TypeError(`view's buffer must have non-zero byteLength`)); + } + if (this._ownerReadableStream === undefined) { + return promiseRejectedWith(readerLockException('read from')); + } + let resolvePromise; + let rejectPromise; + const promise = newPromise((resolve, reject) => { + resolvePromise = resolve; + rejectPromise = reject; + }); + const readIntoRequest = { + _chunkSteps: chunk => resolvePromise({ value: chunk, done: false }), + _closeSteps: chunk => resolvePromise({ value: chunk, done: true }), + _errorSteps: e => rejectPromise(e) + }; + ReadableStreamBYOBReaderRead(this, view, readIntoRequest); + return promise; + } + /** + * Releases the reader's lock on the corresponding stream. After the lock is released, the reader is no longer active. + * If the associated stream is errored when the lock is released, the reader will appear errored in the same way + * from now on; otherwise, the reader will appear closed. + * + * A reader's lock cannot be released while it still has a pending read request, i.e., if a promise returned by + * the reader's {@link ReadableStreamBYOBReader.read | read()} method has not yet been settled. Attempting to + * do so will throw a `TypeError` and leave the reader locked to the stream. + */ + releaseLock() { + if (!IsReadableStreamBYOBReader(this)) { + throw byobReaderBrandCheckException('releaseLock'); + } + if (this._ownerReadableStream === undefined) { + return; + } + if (this._readIntoRequests.length > 0) { + throw new TypeError('Tried to release a reader lock when that reader has pending read() calls un-settled'); + } + ReadableStreamReaderGenericRelease(this); + } +} +Object.defineProperties(ReadableStreamBYOBReader.prototype, { + cancel: { enumerable: true }, + read: { enumerable: true }, + releaseLock: { enumerable: true }, + closed: { enumerable: true } +}); +if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(ReadableStreamBYOBReader.prototype, SymbolPolyfill.toStringTag, { + value: 'ReadableStreamBYOBReader', + configurable: true + }); +} +// Abstract operations for the readers. +function IsReadableStreamBYOBReader(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_readIntoRequests')) { + return false; + } + return true; +} +function ReadableStreamBYOBReaderRead(reader, view, readIntoRequest) { + const stream = reader._ownerReadableStream; + stream._disturbed = true; + if (stream._state === 'errored') { + readIntoRequest._errorSteps(stream._storedError); + } + else { + ReadableByteStreamControllerPullInto(stream._readableStreamController, view, readIntoRequest); + } +} +// Helper functions for the ReadableStreamBYOBReader. +function byobReaderBrandCheckException(name) { + return new TypeError(`ReadableStreamBYOBReader.prototype.${name} can only be used on a ReadableStreamBYOBReader`); +} + +function ExtractHighWaterMark(strategy, defaultHWM) { + const { highWaterMark } = strategy; + if (highWaterMark === undefined) { + return defaultHWM; + } + if (NumberIsNaN(highWaterMark) || highWaterMark < 0) { + throw new RangeError('Invalid highWaterMark'); + } + return highWaterMark; +} +function ExtractSizeAlgorithm(strategy) { + const { size } = strategy; + if (!size) { + return () => 1; + } + return size; +} + +function convertQueuingStrategy(init, context) { + assertDictionary(init, context); + const highWaterMark = init === null || init === void 0 ? void 0 : init.highWaterMark; + const size = init === null || init === void 0 ? void 0 : init.size; + return { + highWaterMark: highWaterMark === undefined ? undefined : convertUnrestrictedDouble(highWaterMark), + size: size === undefined ? undefined : convertQueuingStrategySize(size, `${context} has member 'size' that`) + }; +} +function convertQueuingStrategySize(fn, context) { + assertFunction(fn, context); + return chunk => convertUnrestrictedDouble(fn(chunk)); +} + +function convertUnderlyingSink(original, context) { + assertDictionary(original, context); + const abort = original === null || original === void 0 ? void 0 : original.abort; + const close = original === null || original === void 0 ? void 0 : original.close; + const start = original === null || original === void 0 ? void 0 : original.start; + const type = original === null || original === void 0 ? void 0 : original.type; + const write = original === null || original === void 0 ? void 0 : original.write; + return { + abort: abort === undefined ? + undefined : + convertUnderlyingSinkAbortCallback(abort, original, `${context} has member 'abort' that`), + close: close === undefined ? + undefined : + convertUnderlyingSinkCloseCallback(close, original, `${context} has member 'close' that`), + start: start === undefined ? + undefined : + convertUnderlyingSinkStartCallback(start, original, `${context} has member 'start' that`), + write: write === undefined ? + undefined : + convertUnderlyingSinkWriteCallback(write, original, `${context} has member 'write' that`), + type + }; +} +function convertUnderlyingSinkAbortCallback(fn, original, context) { + assertFunction(fn, context); + return (reason) => promiseCall(fn, original, [reason]); +} +function convertUnderlyingSinkCloseCallback(fn, original, context) { + assertFunction(fn, context); + return () => promiseCall(fn, original, []); +} +function convertUnderlyingSinkStartCallback(fn, original, context) { + assertFunction(fn, context); + return (controller) => reflectCall(fn, original, [controller]); +} +function convertUnderlyingSinkWriteCallback(fn, original, context) { + assertFunction(fn, context); + return (chunk, controller) => promiseCall(fn, original, [chunk, controller]); +} + +function assertWritableStream(x, context) { + if (!IsWritableStream(x)) { + throw new TypeError(`${context} is not a WritableStream.`); + } +} + +/** + * A writable stream represents a destination for data, into which you can write. + * + * @public + */ +class WritableStream$1 { + constructor(rawUnderlyingSink = {}, rawStrategy = {}) { + if (rawUnderlyingSink === undefined) { + rawUnderlyingSink = null; + } + else { + assertObject(rawUnderlyingSink, 'First parameter'); + } + const strategy = convertQueuingStrategy(rawStrategy, 'Second parameter'); + const underlyingSink = convertUnderlyingSink(rawUnderlyingSink, 'First parameter'); + InitializeWritableStream(this); + const type = underlyingSink.type; + if (type !== undefined) { + throw new RangeError('Invalid type is specified'); + } + const sizeAlgorithm = ExtractSizeAlgorithm(strategy); + const highWaterMark = ExtractHighWaterMark(strategy, 1); + SetUpWritableStreamDefaultControllerFromUnderlyingSink(this, underlyingSink, highWaterMark, sizeAlgorithm); + } + /** + * Returns whether or not the writable stream is locked to a writer. + */ + get locked() { + if (!IsWritableStream(this)) { + throw streamBrandCheckException$2('locked'); + } + return IsWritableStreamLocked(this); + } + /** + * Aborts the stream, signaling that the producer can no longer successfully write to the stream and it is to be + * immediately moved to an errored state, with any queued-up writes discarded. This will also execute any abort + * mechanism of the underlying sink. + * + * The returned promise will fulfill if the stream shuts down successfully, or reject if the underlying sink signaled + * that there was an error doing so. Additionally, it will reject with a `TypeError` (without attempting to cancel + * the stream) if the stream is currently locked. + */ + abort(reason = undefined) { + if (!IsWritableStream(this)) { + return promiseRejectedWith(streamBrandCheckException$2('abort')); + } + if (IsWritableStreamLocked(this)) { + return promiseRejectedWith(new TypeError('Cannot abort a stream that already has a writer')); + } + return WritableStreamAbort(this, reason); + } + /** + * Closes the stream. The underlying sink will finish processing any previously-written chunks, before invoking its + * close behavior. During this time any further attempts to write will fail (without erroring the stream). + * + * The method returns a promise that will fulfill if all remaining chunks are successfully written and the stream + * successfully closes, or rejects if an error is encountered during this process. Additionally, it will reject with + * a `TypeError` (without attempting to cancel the stream) if the stream is currently locked. + */ + close() { + if (!IsWritableStream(this)) { + return promiseRejectedWith(streamBrandCheckException$2('close')); + } + if (IsWritableStreamLocked(this)) { + return promiseRejectedWith(new TypeError('Cannot close a stream that already has a writer')); + } + if (WritableStreamCloseQueuedOrInFlight(this)) { + return promiseRejectedWith(new TypeError('Cannot close an already-closing stream')); + } + return WritableStreamClose(this); + } + /** + * Creates a {@link WritableStreamDefaultWriter | writer} and locks the stream to the new writer. While the stream + * is locked, no other writer can be acquired until this one is released. + * + * This functionality is especially useful for creating abstractions that desire the ability to write to a stream + * without interruption or interleaving. By getting a writer for the stream, you can ensure nobody else can write at + * the same time, which would cause the resulting written data to be unpredictable and probably useless. + */ + getWriter() { + if (!IsWritableStream(this)) { + throw streamBrandCheckException$2('getWriter'); + } + return AcquireWritableStreamDefaultWriter(this); + } +} +Object.defineProperties(WritableStream$1.prototype, { + abort: { enumerable: true }, + close: { enumerable: true }, + getWriter: { enumerable: true }, + locked: { enumerable: true } +}); +if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(WritableStream$1.prototype, SymbolPolyfill.toStringTag, { + value: 'WritableStream', + configurable: true + }); +} +// Abstract operations for the WritableStream. +function AcquireWritableStreamDefaultWriter(stream) { + return new WritableStreamDefaultWriter(stream); +} +// Throws if and only if startAlgorithm throws. +function CreateWritableStream(startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark = 1, sizeAlgorithm = () => 1) { + const stream = Object.create(WritableStream$1.prototype); + InitializeWritableStream(stream); + const controller = Object.create(WritableStreamDefaultController.prototype); + SetUpWritableStreamDefaultController(stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark, sizeAlgorithm); + return stream; +} +function InitializeWritableStream(stream) { + stream._state = 'writable'; + // The error that will be reported by new method calls once the state becomes errored. Only set when [[state]] is + // 'erroring' or 'errored'. May be set to an undefined value. + stream._storedError = undefined; + stream._writer = undefined; + // Initialize to undefined first because the constructor of the controller checks this + // variable to validate the caller. + stream._writableStreamController = undefined; + // This queue is placed here instead of the writer class in order to allow for passing a writer to the next data + // producer without waiting for the queued writes to finish. + stream._writeRequests = new SimpleQueue(); + // Write requests are removed from _writeRequests when write() is called on the underlying sink. This prevents + // them from being erroneously rejected on error. If a write() call is in-flight, the request is stored here. + stream._inFlightWriteRequest = undefined; + // The promise that was returned from writer.close(). Stored here because it may be fulfilled after the writer + // has been detached. + stream._closeRequest = undefined; + // Close request is removed from _closeRequest when close() is called on the underlying sink. This prevents it + // from being erroneously rejected on error. If a close() call is in-flight, the request is stored here. + stream._inFlightCloseRequest = undefined; + // The promise that was returned from writer.abort(). This may also be fulfilled after the writer has detached. + stream._pendingAbortRequest = undefined; + // The backpressure signal set by the controller. + stream._backpressure = false; +} +function IsWritableStream(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_writableStreamController')) { + return false; + } + return true; +} +function IsWritableStreamLocked(stream) { + if (stream._writer === undefined) { + return false; + } + return true; +} +function WritableStreamAbort(stream, reason) { + const state = stream._state; + if (state === 'closed' || state === 'errored') { + return promiseResolvedWith(undefined); + } + if (stream._pendingAbortRequest !== undefined) { + return stream._pendingAbortRequest._promise; + } + let wasAlreadyErroring = false; + if (state === 'erroring') { + wasAlreadyErroring = true; + // reason will not be used, so don't keep a reference to it. + reason = undefined; + } + const promise = newPromise((resolve, reject) => { + stream._pendingAbortRequest = { + _promise: undefined, + _resolve: resolve, + _reject: reject, + _reason: reason, + _wasAlreadyErroring: wasAlreadyErroring + }; + }); + stream._pendingAbortRequest._promise = promise; + if (!wasAlreadyErroring) { + WritableStreamStartErroring(stream, reason); + } + return promise; +} +function WritableStreamClose(stream) { + const state = stream._state; + if (state === 'closed' || state === 'errored') { + return promiseRejectedWith(new TypeError(`The stream (in ${state} state) is not in the writable state and cannot be closed`)); + } + const promise = newPromise((resolve, reject) => { + const closeRequest = { + _resolve: resolve, + _reject: reject + }; + stream._closeRequest = closeRequest; + }); + const writer = stream._writer; + if (writer !== undefined && stream._backpressure && state === 'writable') { + defaultWriterReadyPromiseResolve(writer); + } + WritableStreamDefaultControllerClose(stream._writableStreamController); + return promise; +} +// WritableStream API exposed for controllers. +function WritableStreamAddWriteRequest(stream) { + const promise = newPromise((resolve, reject) => { + const writeRequest = { + _resolve: resolve, + _reject: reject + }; + stream._writeRequests.push(writeRequest); + }); + return promise; +} +function WritableStreamDealWithRejection(stream, error) { + const state = stream._state; + if (state === 'writable') { + WritableStreamStartErroring(stream, error); + return; + } + WritableStreamFinishErroring(stream); +} +function WritableStreamStartErroring(stream, reason) { + const controller = stream._writableStreamController; + stream._state = 'erroring'; + stream._storedError = reason; + const writer = stream._writer; + if (writer !== undefined) { + WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, reason); + } + if (!WritableStreamHasOperationMarkedInFlight(stream) && controller._started) { + WritableStreamFinishErroring(stream); + } +} +function WritableStreamFinishErroring(stream) { + stream._state = 'errored'; + stream._writableStreamController[ErrorSteps](); + const storedError = stream._storedError; + stream._writeRequests.forEach(writeRequest => { + writeRequest._reject(storedError); + }); + stream._writeRequests = new SimpleQueue(); + if (stream._pendingAbortRequest === undefined) { + WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); + return; + } + const abortRequest = stream._pendingAbortRequest; + stream._pendingAbortRequest = undefined; + if (abortRequest._wasAlreadyErroring) { + abortRequest._reject(storedError); + WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); + return; + } + const promise = stream._writableStreamController[AbortSteps](abortRequest._reason); + uponPromise(promise, () => { + abortRequest._resolve(); + WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); + }, (reason) => { + abortRequest._reject(reason); + WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); + }); +} +function WritableStreamFinishInFlightWrite(stream) { + stream._inFlightWriteRequest._resolve(undefined); + stream._inFlightWriteRequest = undefined; +} +function WritableStreamFinishInFlightWriteWithError(stream, error) { + stream._inFlightWriteRequest._reject(error); + stream._inFlightWriteRequest = undefined; + WritableStreamDealWithRejection(stream, error); +} +function WritableStreamFinishInFlightClose(stream) { + stream._inFlightCloseRequest._resolve(undefined); + stream._inFlightCloseRequest = undefined; + const state = stream._state; + if (state === 'erroring') { + // The error was too late to do anything, so it is ignored. + stream._storedError = undefined; + if (stream._pendingAbortRequest !== undefined) { + stream._pendingAbortRequest._resolve(); + stream._pendingAbortRequest = undefined; + } + } + stream._state = 'closed'; + const writer = stream._writer; + if (writer !== undefined) { + defaultWriterClosedPromiseResolve(writer); + } +} +function WritableStreamFinishInFlightCloseWithError(stream, error) { + stream._inFlightCloseRequest._reject(error); + stream._inFlightCloseRequest = undefined; + // Never execute sink abort() after sink close(). + if (stream._pendingAbortRequest !== undefined) { + stream._pendingAbortRequest._reject(error); + stream._pendingAbortRequest = undefined; + } + WritableStreamDealWithRejection(stream, error); +} +// TODO(ricea): Fix alphabetical order. +function WritableStreamCloseQueuedOrInFlight(stream) { + if (stream._closeRequest === undefined && stream._inFlightCloseRequest === undefined) { + return false; + } + return true; +} +function WritableStreamHasOperationMarkedInFlight(stream) { + if (stream._inFlightWriteRequest === undefined && stream._inFlightCloseRequest === undefined) { + return false; + } + return true; +} +function WritableStreamMarkCloseRequestInFlight(stream) { + stream._inFlightCloseRequest = stream._closeRequest; + stream._closeRequest = undefined; +} +function WritableStreamMarkFirstWriteRequestInFlight(stream) { + stream._inFlightWriteRequest = stream._writeRequests.shift(); +} +function WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream) { + if (stream._closeRequest !== undefined) { + stream._closeRequest._reject(stream._storedError); + stream._closeRequest = undefined; + } + const writer = stream._writer; + if (writer !== undefined) { + defaultWriterClosedPromiseReject(writer, stream._storedError); + } +} +function WritableStreamUpdateBackpressure(stream, backpressure) { + const writer = stream._writer; + if (writer !== undefined && backpressure !== stream._backpressure) { + if (backpressure) { + defaultWriterReadyPromiseReset(writer); + } + else { + defaultWriterReadyPromiseResolve(writer); + } + } + stream._backpressure = backpressure; +} +/** + * A default writer vended by a {@link WritableStream}. + * + * @public + */ +class WritableStreamDefaultWriter { + constructor(stream) { + assertRequiredArgument(stream, 1, 'WritableStreamDefaultWriter'); + assertWritableStream(stream, 'First parameter'); + if (IsWritableStreamLocked(stream)) { + throw new TypeError('This stream has already been locked for exclusive writing by another writer'); + } + this._ownerWritableStream = stream; + stream._writer = this; + const state = stream._state; + if (state === 'writable') { + if (!WritableStreamCloseQueuedOrInFlight(stream) && stream._backpressure) { + defaultWriterReadyPromiseInitialize(this); + } + else { + defaultWriterReadyPromiseInitializeAsResolved(this); + } + defaultWriterClosedPromiseInitialize(this); + } + else if (state === 'erroring') { + defaultWriterReadyPromiseInitializeAsRejected(this, stream._storedError); + defaultWriterClosedPromiseInitialize(this); + } + else if (state === 'closed') { + defaultWriterReadyPromiseInitializeAsResolved(this); + defaultWriterClosedPromiseInitializeAsResolved(this); + } + else { + const storedError = stream._storedError; + defaultWriterReadyPromiseInitializeAsRejected(this, storedError); + defaultWriterClosedPromiseInitializeAsRejected(this, storedError); + } + } + /** + * Returns a promise that will be fulfilled when the stream becomes closed, or rejected if the stream ever errors or + * the writer’s lock is released before the stream finishes closing. + */ + get closed() { + if (!IsWritableStreamDefaultWriter(this)) { + return promiseRejectedWith(defaultWriterBrandCheckException('closed')); + } + return this._closedPromise; + } + /** + * Returns the desired size to fill the stream’s internal queue. It can be negative, if the queue is over-full. + * A producer can use this information to determine the right amount of data to write. + * + * It will be `null` if the stream cannot be successfully written to (due to either being errored, or having an abort + * queued up). It will return zero if the stream is closed. And the getter will throw an exception if invoked when + * the writer’s lock is released. + */ + get desiredSize() { + if (!IsWritableStreamDefaultWriter(this)) { + throw defaultWriterBrandCheckException('desiredSize'); + } + if (this._ownerWritableStream === undefined) { + throw defaultWriterLockException('desiredSize'); + } + return WritableStreamDefaultWriterGetDesiredSize(this); + } + /** + * Returns a promise that will be fulfilled when the desired size to fill the stream’s internal queue transitions + * from non-positive to positive, signaling that it is no longer applying backpressure. Once the desired size dips + * back to zero or below, the getter will return a new promise that stays pending until the next transition. + * + * If the stream becomes errored or aborted, or the writer’s lock is released, the returned promise will become + * rejected. + */ + get ready() { + if (!IsWritableStreamDefaultWriter(this)) { + return promiseRejectedWith(defaultWriterBrandCheckException('ready')); + } + return this._readyPromise; + } + /** + * If the reader is active, behaves the same as {@link WritableStream.abort | stream.abort(reason)}. + */ + abort(reason = undefined) { + if (!IsWritableStreamDefaultWriter(this)) { + return promiseRejectedWith(defaultWriterBrandCheckException('abort')); + } + if (this._ownerWritableStream === undefined) { + return promiseRejectedWith(defaultWriterLockException('abort')); + } + return WritableStreamDefaultWriterAbort(this, reason); + } + /** + * If the reader is active, behaves the same as {@link WritableStream.close | stream.close()}. + */ + close() { + if (!IsWritableStreamDefaultWriter(this)) { + return promiseRejectedWith(defaultWriterBrandCheckException('close')); + } + const stream = this._ownerWritableStream; + if (stream === undefined) { + return promiseRejectedWith(defaultWriterLockException('close')); + } + if (WritableStreamCloseQueuedOrInFlight(stream)) { + return promiseRejectedWith(new TypeError('Cannot close an already-closing stream')); + } + return WritableStreamDefaultWriterClose(this); + } + /** + * Releases the writer’s lock on the corresponding stream. After the lock is released, the writer is no longer active. + * If the associated stream is errored when the lock is released, the writer will appear errored in the same way from + * now on; otherwise, the writer will appear closed. + * + * Note that the lock can still be released even if some ongoing writes have not yet finished (i.e. even if the + * promises returned from previous calls to {@link WritableStreamDefaultWriter.write | write()} have not yet settled). + * It’s not necessary to hold the lock on the writer for the duration of the write; the lock instead simply prevents + * other producers from writing in an interleaved manner. + */ + releaseLock() { + if (!IsWritableStreamDefaultWriter(this)) { + throw defaultWriterBrandCheckException('releaseLock'); + } + const stream = this._ownerWritableStream; + if (stream === undefined) { + return; + } + WritableStreamDefaultWriterRelease(this); + } + write(chunk = undefined) { + if (!IsWritableStreamDefaultWriter(this)) { + return promiseRejectedWith(defaultWriterBrandCheckException('write')); + } + if (this._ownerWritableStream === undefined) { + return promiseRejectedWith(defaultWriterLockException('write to')); + } + return WritableStreamDefaultWriterWrite(this, chunk); + } +} +Object.defineProperties(WritableStreamDefaultWriter.prototype, { + abort: { enumerable: true }, + close: { enumerable: true }, + releaseLock: { enumerable: true }, + write: { enumerable: true }, + closed: { enumerable: true }, + desiredSize: { enumerable: true }, + ready: { enumerable: true } +}); +if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(WritableStreamDefaultWriter.prototype, SymbolPolyfill.toStringTag, { + value: 'WritableStreamDefaultWriter', + configurable: true + }); +} +// Abstract operations for the WritableStreamDefaultWriter. +function IsWritableStreamDefaultWriter(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_ownerWritableStream')) { + return false; + } + return true; +} +// A client of WritableStreamDefaultWriter may use these functions directly to bypass state check. +function WritableStreamDefaultWriterAbort(writer, reason) { + const stream = writer._ownerWritableStream; + return WritableStreamAbort(stream, reason); +} +function WritableStreamDefaultWriterClose(writer) { + const stream = writer._ownerWritableStream; + return WritableStreamClose(stream); +} +function WritableStreamDefaultWriterCloseWithErrorPropagation(writer) { + const stream = writer._ownerWritableStream; + const state = stream._state; + if (WritableStreamCloseQueuedOrInFlight(stream) || state === 'closed') { + return promiseResolvedWith(undefined); + } + if (state === 'errored') { + return promiseRejectedWith(stream._storedError); + } + return WritableStreamDefaultWriterClose(writer); +} +function WritableStreamDefaultWriterEnsureClosedPromiseRejected(writer, error) { + if (writer._closedPromiseState === 'pending') { + defaultWriterClosedPromiseReject(writer, error); + } + else { + defaultWriterClosedPromiseResetToRejected(writer, error); + } +} +function WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, error) { + if (writer._readyPromiseState === 'pending') { + defaultWriterReadyPromiseReject(writer, error); + } + else { + defaultWriterReadyPromiseResetToRejected(writer, error); + } +} +function WritableStreamDefaultWriterGetDesiredSize(writer) { + const stream = writer._ownerWritableStream; + const state = stream._state; + if (state === 'errored' || state === 'erroring') { + return null; + } + if (state === 'closed') { + return 0; + } + return WritableStreamDefaultControllerGetDesiredSize(stream._writableStreamController); +} +function WritableStreamDefaultWriterRelease(writer) { + const stream = writer._ownerWritableStream; + const releasedError = new TypeError(`Writer was released and can no longer be used to monitor the stream's closedness`); + WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, releasedError); + // The state transitions to "errored" before the sink abort() method runs, but the writer.closed promise is not + // rejected until afterwards. This means that simply testing state will not work. + WritableStreamDefaultWriterEnsureClosedPromiseRejected(writer, releasedError); + stream._writer = undefined; + writer._ownerWritableStream = undefined; +} +function WritableStreamDefaultWriterWrite(writer, chunk) { + const stream = writer._ownerWritableStream; + const controller = stream._writableStreamController; + const chunkSize = WritableStreamDefaultControllerGetChunkSize(controller, chunk); + if (stream !== writer._ownerWritableStream) { + return promiseRejectedWith(defaultWriterLockException('write to')); + } + const state = stream._state; + if (state === 'errored') { + return promiseRejectedWith(stream._storedError); + } + if (WritableStreamCloseQueuedOrInFlight(stream) || state === 'closed') { + return promiseRejectedWith(new TypeError('The stream is closing or closed and cannot be written to')); + } + if (state === 'erroring') { + return promiseRejectedWith(stream._storedError); + } + const promise = WritableStreamAddWriteRequest(stream); + WritableStreamDefaultControllerWrite(controller, chunk, chunkSize); + return promise; +} +const closeSentinel = {}; +/** + * Allows control of a {@link WritableStream | writable stream}'s state and internal queue. + * + * @public + */ +class WritableStreamDefaultController { + constructor() { + throw new TypeError('Illegal constructor'); + } + /** + * Closes the controlled writable stream, making all future interactions with it fail with the given error `e`. + * + * This method is rarely used, since usually it suffices to return a rejected promise from one of the underlying + * sink's methods. However, it can be useful for suddenly shutting down a stream in response to an event outside the + * normal lifecycle of interactions with the underlying sink. + */ + error(e = undefined) { + if (!IsWritableStreamDefaultController(this)) { + throw new TypeError('WritableStreamDefaultController.prototype.error can only be used on a WritableStreamDefaultController'); + } + const state = this._controlledWritableStream._state; + if (state !== 'writable') { + // The stream is closed, errored or will be soon. The sink can't do anything useful if it gets an error here, so + // just treat it as a no-op. + return; + } + WritableStreamDefaultControllerError(this, e); + } + /** @internal */ + [AbortSteps](reason) { + const result = this._abortAlgorithm(reason); + WritableStreamDefaultControllerClearAlgorithms(this); + return result; + } + /** @internal */ + [ErrorSteps]() { + ResetQueue(this); + } +} +Object.defineProperties(WritableStreamDefaultController.prototype, { + error: { enumerable: true } +}); +if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(WritableStreamDefaultController.prototype, SymbolPolyfill.toStringTag, { + value: 'WritableStreamDefaultController', + configurable: true + }); +} +// Abstract operations implementing interface required by the WritableStream. +function IsWritableStreamDefaultController(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_controlledWritableStream')) { + return false; + } + return true; +} +function SetUpWritableStreamDefaultController(stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark, sizeAlgorithm) { + controller._controlledWritableStream = stream; + stream._writableStreamController = controller; + // Need to set the slots so that the assert doesn't fire. In the spec the slots already exist implicitly. + controller._queue = undefined; + controller._queueTotalSize = undefined; + ResetQueue(controller); + controller._started = false; + controller._strategySizeAlgorithm = sizeAlgorithm; + controller._strategyHWM = highWaterMark; + controller._writeAlgorithm = writeAlgorithm; + controller._closeAlgorithm = closeAlgorithm; + controller._abortAlgorithm = abortAlgorithm; + const backpressure = WritableStreamDefaultControllerGetBackpressure(controller); + WritableStreamUpdateBackpressure(stream, backpressure); + const startResult = startAlgorithm(); + const startPromise = promiseResolvedWith(startResult); + uponPromise(startPromise, () => { + controller._started = true; + WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); + }, r => { + controller._started = true; + WritableStreamDealWithRejection(stream, r); + }); +} +function SetUpWritableStreamDefaultControllerFromUnderlyingSink(stream, underlyingSink, highWaterMark, sizeAlgorithm) { + const controller = Object.create(WritableStreamDefaultController.prototype); + let startAlgorithm = () => undefined; + let writeAlgorithm = () => promiseResolvedWith(undefined); + let closeAlgorithm = () => promiseResolvedWith(undefined); + let abortAlgorithm = () => promiseResolvedWith(undefined); + if (underlyingSink.start !== undefined) { + startAlgorithm = () => underlyingSink.start(controller); + } + if (underlyingSink.write !== undefined) { + writeAlgorithm = chunk => underlyingSink.write(chunk, controller); + } + if (underlyingSink.close !== undefined) { + closeAlgorithm = () => underlyingSink.close(); + } + if (underlyingSink.abort !== undefined) { + abortAlgorithm = reason => underlyingSink.abort(reason); + } + SetUpWritableStreamDefaultController(stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark, sizeAlgorithm); +} +// ClearAlgorithms may be called twice. Erroring the same stream in multiple ways will often result in redundant calls. +function WritableStreamDefaultControllerClearAlgorithms(controller) { + controller._writeAlgorithm = undefined; + controller._closeAlgorithm = undefined; + controller._abortAlgorithm = undefined; + controller._strategySizeAlgorithm = undefined; +} +function WritableStreamDefaultControllerClose(controller) { + EnqueueValueWithSize(controller, closeSentinel, 0); + WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); +} +function WritableStreamDefaultControllerGetChunkSize(controller, chunk) { + try { + return controller._strategySizeAlgorithm(chunk); + } + catch (chunkSizeE) { + WritableStreamDefaultControllerErrorIfNeeded(controller, chunkSizeE); + return 1; + } +} +function WritableStreamDefaultControllerGetDesiredSize(controller) { + return controller._strategyHWM - controller._queueTotalSize; +} +function WritableStreamDefaultControllerWrite(controller, chunk, chunkSize) { + try { + EnqueueValueWithSize(controller, chunk, chunkSize); + } + catch (enqueueE) { + WritableStreamDefaultControllerErrorIfNeeded(controller, enqueueE); + return; + } + const stream = controller._controlledWritableStream; + if (!WritableStreamCloseQueuedOrInFlight(stream) && stream._state === 'writable') { + const backpressure = WritableStreamDefaultControllerGetBackpressure(controller); + WritableStreamUpdateBackpressure(stream, backpressure); + } + WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); +} +// Abstract operations for the WritableStreamDefaultController. +function WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller) { + const stream = controller._controlledWritableStream; + if (!controller._started) { + return; + } + if (stream._inFlightWriteRequest !== undefined) { + return; + } + const state = stream._state; + if (state === 'erroring') { + WritableStreamFinishErroring(stream); + return; + } + if (controller._queue.length === 0) { + return; + } + const value = PeekQueueValue(controller); + if (value === closeSentinel) { + WritableStreamDefaultControllerProcessClose(controller); + } + else { + WritableStreamDefaultControllerProcessWrite(controller, value); + } +} +function WritableStreamDefaultControllerErrorIfNeeded(controller, error) { + if (controller._controlledWritableStream._state === 'writable') { + WritableStreamDefaultControllerError(controller, error); + } +} +function WritableStreamDefaultControllerProcessClose(controller) { + const stream = controller._controlledWritableStream; + WritableStreamMarkCloseRequestInFlight(stream); + DequeueValue(controller); + const sinkClosePromise = controller._closeAlgorithm(); + WritableStreamDefaultControllerClearAlgorithms(controller); + uponPromise(sinkClosePromise, () => { + WritableStreamFinishInFlightClose(stream); + }, reason => { + WritableStreamFinishInFlightCloseWithError(stream, reason); + }); +} +function WritableStreamDefaultControllerProcessWrite(controller, chunk) { + const stream = controller._controlledWritableStream; + WritableStreamMarkFirstWriteRequestInFlight(stream); + const sinkWritePromise = controller._writeAlgorithm(chunk); + uponPromise(sinkWritePromise, () => { + WritableStreamFinishInFlightWrite(stream); + const state = stream._state; + DequeueValue(controller); + if (!WritableStreamCloseQueuedOrInFlight(stream) && state === 'writable') { + const backpressure = WritableStreamDefaultControllerGetBackpressure(controller); + WritableStreamUpdateBackpressure(stream, backpressure); + } + WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); + }, reason => { + if (stream._state === 'writable') { + WritableStreamDefaultControllerClearAlgorithms(controller); + } + WritableStreamFinishInFlightWriteWithError(stream, reason); + }); +} +function WritableStreamDefaultControllerGetBackpressure(controller) { + const desiredSize = WritableStreamDefaultControllerGetDesiredSize(controller); + return desiredSize <= 0; +} +// A client of WritableStreamDefaultController may use these functions directly to bypass state check. +function WritableStreamDefaultControllerError(controller, error) { + const stream = controller._controlledWritableStream; + WritableStreamDefaultControllerClearAlgorithms(controller); + WritableStreamStartErroring(stream, error); +} +// Helper functions for the WritableStream. +function streamBrandCheckException$2(name) { + return new TypeError(`WritableStream.prototype.${name} can only be used on a WritableStream`); +} +// Helper functions for the WritableStreamDefaultWriter. +function defaultWriterBrandCheckException(name) { + return new TypeError(`WritableStreamDefaultWriter.prototype.${name} can only be used on a WritableStreamDefaultWriter`); +} +function defaultWriterLockException(name) { + return new TypeError('Cannot ' + name + ' a stream using a released writer'); +} +function defaultWriterClosedPromiseInitialize(writer) { + writer._closedPromise = newPromise((resolve, reject) => { + writer._closedPromise_resolve = resolve; + writer._closedPromise_reject = reject; + writer._closedPromiseState = 'pending'; + }); +} +function defaultWriterClosedPromiseInitializeAsRejected(writer, reason) { + defaultWriterClosedPromiseInitialize(writer); + defaultWriterClosedPromiseReject(writer, reason); +} +function defaultWriterClosedPromiseInitializeAsResolved(writer) { + defaultWriterClosedPromiseInitialize(writer); + defaultWriterClosedPromiseResolve(writer); +} +function defaultWriterClosedPromiseReject(writer, reason) { + if (writer._closedPromise_reject === undefined) { + return; + } + setPromiseIsHandledToTrue(writer._closedPromise); + writer._closedPromise_reject(reason); + writer._closedPromise_resolve = undefined; + writer._closedPromise_reject = undefined; + writer._closedPromiseState = 'rejected'; +} +function defaultWriterClosedPromiseResetToRejected(writer, reason) { + defaultWriterClosedPromiseInitializeAsRejected(writer, reason); +} +function defaultWriterClosedPromiseResolve(writer) { + if (writer._closedPromise_resolve === undefined) { + return; + } + writer._closedPromise_resolve(undefined); + writer._closedPromise_resolve = undefined; + writer._closedPromise_reject = undefined; + writer._closedPromiseState = 'resolved'; +} +function defaultWriterReadyPromiseInitialize(writer) { + writer._readyPromise = newPromise((resolve, reject) => { + writer._readyPromise_resolve = resolve; + writer._readyPromise_reject = reject; + }); + writer._readyPromiseState = 'pending'; +} +function defaultWriterReadyPromiseInitializeAsRejected(writer, reason) { + defaultWriterReadyPromiseInitialize(writer); + defaultWriterReadyPromiseReject(writer, reason); +} +function defaultWriterReadyPromiseInitializeAsResolved(writer) { + defaultWriterReadyPromiseInitialize(writer); + defaultWriterReadyPromiseResolve(writer); +} +function defaultWriterReadyPromiseReject(writer, reason) { + if (writer._readyPromise_reject === undefined) { + return; + } + setPromiseIsHandledToTrue(writer._readyPromise); + writer._readyPromise_reject(reason); + writer._readyPromise_resolve = undefined; + writer._readyPromise_reject = undefined; + writer._readyPromiseState = 'rejected'; +} +function defaultWriterReadyPromiseReset(writer) { + defaultWriterReadyPromiseInitialize(writer); +} +function defaultWriterReadyPromiseResetToRejected(writer, reason) { + defaultWriterReadyPromiseInitializeAsRejected(writer, reason); +} +function defaultWriterReadyPromiseResolve(writer) { + if (writer._readyPromise_resolve === undefined) { + return; + } + writer._readyPromise_resolve(undefined); + writer._readyPromise_resolve = undefined; + writer._readyPromise_reject = undefined; + writer._readyPromiseState = 'fulfilled'; +} + +function isAbortSignal(value) { + if (typeof value !== 'object' || value === null) { + return false; + } + try { + return typeof value.aborted === 'boolean'; + } + catch (_a) { + // AbortSignal.prototype.aborted throws if its brand check fails + return false; + } +} + +/// +const NativeDOMException = typeof DOMException !== 'undefined' ? DOMException : undefined; + +/// +function isDOMExceptionConstructor(ctor) { + if (!(typeof ctor === 'function' || typeof ctor === 'object')) { + return false; + } + try { + new ctor(); + return true; + } + catch (_a) { + return false; + } +} +function createDOMExceptionPolyfill() { + // eslint-disable-next-line no-shadow + const ctor = function DOMException(message, name) { + this.message = message || ''; + this.name = name || 'Error'; + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + }; + ctor.prototype = Object.create(Error.prototype); + Object.defineProperty(ctor.prototype, 'constructor', { value: ctor, writable: true, configurable: true }); + return ctor; +} +// eslint-disable-next-line no-redeclare +const DOMException$1 = isDOMExceptionConstructor(NativeDOMException) ? NativeDOMException : createDOMExceptionPolyfill(); + +function ReadableStreamPipeTo(source, dest, preventClose, preventAbort, preventCancel, signal) { + const reader = AcquireReadableStreamDefaultReader(source); + const writer = AcquireWritableStreamDefaultWriter(dest); + source._disturbed = true; + let shuttingDown = false; + // This is used to keep track of the spec's requirement that we wait for ongoing writes during shutdown. + let currentWrite = promiseResolvedWith(undefined); + return newPromise((resolve, reject) => { + let abortAlgorithm; + if (signal !== undefined) { + abortAlgorithm = () => { + const error = new DOMException$1('Aborted', 'AbortError'); + const actions = []; + if (!preventAbort) { + actions.push(() => { + if (dest._state === 'writable') { + return WritableStreamAbort(dest, error); + } + return promiseResolvedWith(undefined); + }); + } + if (!preventCancel) { + actions.push(() => { + if (source._state === 'readable') { + return ReadableStreamCancel(source, error); + } + return promiseResolvedWith(undefined); + }); + } + shutdownWithAction(() => Promise.all(actions.map(action => action())), true, error); + }; + if (signal.aborted) { + abortAlgorithm(); + return; + } + signal.addEventListener('abort', abortAlgorithm); + } + // Using reader and writer, read all chunks from this and write them to dest + // - Backpressure must be enforced + // - Shutdown must stop all activity + function pipeLoop() { + return newPromise((resolveLoop, rejectLoop) => { + function next(done) { + if (done) { + resolveLoop(); + } + else { + // Use `PerformPromiseThen` instead of `uponPromise` to avoid + // adding unnecessary `.catch(rethrowAssertionErrorRejection)` handlers + PerformPromiseThen(pipeStep(), next, rejectLoop); + } + } + next(false); + }); + } + function pipeStep() { + if (shuttingDown) { + return promiseResolvedWith(true); + } + return PerformPromiseThen(writer._readyPromise, () => { + return newPromise((resolveRead, rejectRead) => { + ReadableStreamDefaultReaderRead(reader, { + _chunkSteps: chunk => { + currentWrite = PerformPromiseThen(WritableStreamDefaultWriterWrite(writer, chunk), undefined, noop); + resolveRead(false); + }, + _closeSteps: () => resolveRead(true), + _errorSteps: rejectRead + }); + }); + }); + } + // Errors must be propagated forward + isOrBecomesErrored(source, reader._closedPromise, storedError => { + if (!preventAbort) { + shutdownWithAction(() => WritableStreamAbort(dest, storedError), true, storedError); + } + else { + shutdown(true, storedError); + } + }); + // Errors must be propagated backward + isOrBecomesErrored(dest, writer._closedPromise, storedError => { + if (!preventCancel) { + shutdownWithAction(() => ReadableStreamCancel(source, storedError), true, storedError); + } + else { + shutdown(true, storedError); + } + }); + // Closing must be propagated forward + isOrBecomesClosed(source, reader._closedPromise, () => { + if (!preventClose) { + shutdownWithAction(() => WritableStreamDefaultWriterCloseWithErrorPropagation(writer)); + } + else { + shutdown(); + } + }); + // Closing must be propagated backward + if (WritableStreamCloseQueuedOrInFlight(dest) || dest._state === 'closed') { + const destClosed = new TypeError('the destination writable stream closed before all data could be piped to it'); + if (!preventCancel) { + shutdownWithAction(() => ReadableStreamCancel(source, destClosed), true, destClosed); + } + else { + shutdown(true, destClosed); + } + } + setPromiseIsHandledToTrue(pipeLoop()); + function waitForWritesToFinish() { + // Another write may have started while we were waiting on this currentWrite, so we have to be sure to wait + // for that too. + const oldCurrentWrite = currentWrite; + return PerformPromiseThen(currentWrite, () => oldCurrentWrite !== currentWrite ? waitForWritesToFinish() : undefined); + } + function isOrBecomesErrored(stream, promise, action) { + if (stream._state === 'errored') { + action(stream._storedError); + } + else { + uponRejection(promise, action); + } + } + function isOrBecomesClosed(stream, promise, action) { + if (stream._state === 'closed') { + action(); + } + else { + uponFulfillment(promise, action); + } + } + function shutdownWithAction(action, originalIsError, originalError) { + if (shuttingDown) { + return; + } + shuttingDown = true; + if (dest._state === 'writable' && !WritableStreamCloseQueuedOrInFlight(dest)) { + uponFulfillment(waitForWritesToFinish(), doTheRest); + } + else { + doTheRest(); + } + function doTheRest() { + uponPromise(action(), () => finalize(originalIsError, originalError), newError => finalize(true, newError)); + } + } + function shutdown(isError, error) { + if (shuttingDown) { + return; + } + shuttingDown = true; + if (dest._state === 'writable' && !WritableStreamCloseQueuedOrInFlight(dest)) { + uponFulfillment(waitForWritesToFinish(), () => finalize(isError, error)); + } + else { + finalize(isError, error); + } + } + function finalize(isError, error) { + WritableStreamDefaultWriterRelease(writer); + ReadableStreamReaderGenericRelease(reader); + if (signal !== undefined) { + signal.removeEventListener('abort', abortAlgorithm); + } + if (isError) { + reject(error); + } + else { + resolve(undefined); + } + } + }); +} + +/** + * Allows control of a {@link ReadableStream | readable stream}'s state and internal queue. + * + * @public + */ +class ReadableStreamDefaultController { + constructor() { + throw new TypeError('Illegal constructor'); + } + /** + * Returns the desired size to fill the controlled stream's internal queue. It can be negative, if the queue is + * over-full. An underlying source ought to use this information to determine when and how to apply backpressure. + */ + get desiredSize() { + if (!IsReadableStreamDefaultController(this)) { + throw defaultControllerBrandCheckException$1('desiredSize'); + } + return ReadableStreamDefaultControllerGetDesiredSize(this); + } + /** + * Closes the controlled readable stream. Consumers will still be able to read any previously-enqueued chunks from + * the stream, but once those are read, the stream will become closed. + */ + close() { + if (!IsReadableStreamDefaultController(this)) { + throw defaultControllerBrandCheckException$1('close'); + } + if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(this)) { + throw new TypeError('The stream is not in a state that permits close'); + } + ReadableStreamDefaultControllerClose(this); + } + enqueue(chunk = undefined) { + if (!IsReadableStreamDefaultController(this)) { + throw defaultControllerBrandCheckException$1('enqueue'); + } + if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(this)) { + throw new TypeError('The stream is not in a state that permits enqueue'); + } + return ReadableStreamDefaultControllerEnqueue(this, chunk); + } + /** + * Errors the controlled readable stream, making all future interactions with it fail with the given error `e`. + */ + error(e = undefined) { + if (!IsReadableStreamDefaultController(this)) { + throw defaultControllerBrandCheckException$1('error'); + } + ReadableStreamDefaultControllerError(this, e); + } + /** @internal */ + [CancelSteps](reason) { + ResetQueue(this); + const result = this._cancelAlgorithm(reason); + ReadableStreamDefaultControllerClearAlgorithms(this); + return result; + } + /** @internal */ + [PullSteps](readRequest) { + const stream = this._controlledReadableStream; + if (this._queue.length > 0) { + const chunk = DequeueValue(this); + if (this._closeRequested && this._queue.length === 0) { + ReadableStreamDefaultControllerClearAlgorithms(this); + ReadableStreamClose(stream); + } + else { + ReadableStreamDefaultControllerCallPullIfNeeded(this); + } + readRequest._chunkSteps(chunk); + } + else { + ReadableStreamAddReadRequest(stream, readRequest); + ReadableStreamDefaultControllerCallPullIfNeeded(this); + } + } +} +Object.defineProperties(ReadableStreamDefaultController.prototype, { + close: { enumerable: true }, + enqueue: { enumerable: true }, + error: { enumerable: true }, + desiredSize: { enumerable: true } +}); +if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(ReadableStreamDefaultController.prototype, SymbolPolyfill.toStringTag, { + value: 'ReadableStreamDefaultController', + configurable: true + }); +} +// Abstract operations for the ReadableStreamDefaultController. +function IsReadableStreamDefaultController(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_controlledReadableStream')) { + return false; + } + return true; +} +function ReadableStreamDefaultControllerCallPullIfNeeded(controller) { + const shouldPull = ReadableStreamDefaultControllerShouldCallPull(controller); + if (!shouldPull) { + return; + } + if (controller._pulling) { + controller._pullAgain = true; + return; + } + controller._pulling = true; + const pullPromise = controller._pullAlgorithm(); + uponPromise(pullPromise, () => { + controller._pulling = false; + if (controller._pullAgain) { + controller._pullAgain = false; + ReadableStreamDefaultControllerCallPullIfNeeded(controller); + } + }, e => { + ReadableStreamDefaultControllerError(controller, e); + }); +} +function ReadableStreamDefaultControllerShouldCallPull(controller) { + const stream = controller._controlledReadableStream; + if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(controller)) { + return false; + } + if (!controller._started) { + return false; + } + if (IsReadableStreamLocked(stream) && ReadableStreamGetNumReadRequests(stream) > 0) { + return true; + } + const desiredSize = ReadableStreamDefaultControllerGetDesiredSize(controller); + if (desiredSize > 0) { + return true; + } + return false; +} +function ReadableStreamDefaultControllerClearAlgorithms(controller) { + controller._pullAlgorithm = undefined; + controller._cancelAlgorithm = undefined; + controller._strategySizeAlgorithm = undefined; +} +// A client of ReadableStreamDefaultController may use these functions directly to bypass state check. +function ReadableStreamDefaultControllerClose(controller) { + if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(controller)) { + return; + } + const stream = controller._controlledReadableStream; + controller._closeRequested = true; + if (controller._queue.length === 0) { + ReadableStreamDefaultControllerClearAlgorithms(controller); + ReadableStreamClose(stream); + } +} +function ReadableStreamDefaultControllerEnqueue(controller, chunk) { + if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(controller)) { + return; + } + const stream = controller._controlledReadableStream; + if (IsReadableStreamLocked(stream) && ReadableStreamGetNumReadRequests(stream) > 0) { + ReadableStreamFulfillReadRequest(stream, chunk, false); + } + else { + let chunkSize; + try { + chunkSize = controller._strategySizeAlgorithm(chunk); + } + catch (chunkSizeE) { + ReadableStreamDefaultControllerError(controller, chunkSizeE); + throw chunkSizeE; + } + try { + EnqueueValueWithSize(controller, chunk, chunkSize); + } + catch (enqueueE) { + ReadableStreamDefaultControllerError(controller, enqueueE); + throw enqueueE; + } + } + ReadableStreamDefaultControllerCallPullIfNeeded(controller); +} +function ReadableStreamDefaultControllerError(controller, e) { + const stream = controller._controlledReadableStream; + if (stream._state !== 'readable') { + return; + } + ResetQueue(controller); + ReadableStreamDefaultControllerClearAlgorithms(controller); + ReadableStreamError(stream, e); +} +function ReadableStreamDefaultControllerGetDesiredSize(controller) { + const state = controller._controlledReadableStream._state; + if (state === 'errored') { + return null; + } + if (state === 'closed') { + return 0; + } + return controller._strategyHWM - controller._queueTotalSize; +} +// This is used in the implementation of TransformStream. +function ReadableStreamDefaultControllerHasBackpressure(controller) { + if (ReadableStreamDefaultControllerShouldCallPull(controller)) { + return false; + } + return true; +} +function ReadableStreamDefaultControllerCanCloseOrEnqueue(controller) { + const state = controller._controlledReadableStream._state; + if (!controller._closeRequested && state === 'readable') { + return true; + } + return false; +} +function SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm) { + controller._controlledReadableStream = stream; + controller._queue = undefined; + controller._queueTotalSize = undefined; + ResetQueue(controller); + controller._started = false; + controller._closeRequested = false; + controller._pullAgain = false; + controller._pulling = false; + controller._strategySizeAlgorithm = sizeAlgorithm; + controller._strategyHWM = highWaterMark; + controller._pullAlgorithm = pullAlgorithm; + controller._cancelAlgorithm = cancelAlgorithm; + stream._readableStreamController = controller; + const startResult = startAlgorithm(); + uponPromise(promiseResolvedWith(startResult), () => { + controller._started = true; + ReadableStreamDefaultControllerCallPullIfNeeded(controller); + }, r => { + ReadableStreamDefaultControllerError(controller, r); + }); +} +function SetUpReadableStreamDefaultControllerFromUnderlyingSource(stream, underlyingSource, highWaterMark, sizeAlgorithm) { + const controller = Object.create(ReadableStreamDefaultController.prototype); + let startAlgorithm = () => undefined; + let pullAlgorithm = () => promiseResolvedWith(undefined); + let cancelAlgorithm = () => promiseResolvedWith(undefined); + if (underlyingSource.start !== undefined) { + startAlgorithm = () => underlyingSource.start(controller); + } + if (underlyingSource.pull !== undefined) { + pullAlgorithm = () => underlyingSource.pull(controller); + } + if (underlyingSource.cancel !== undefined) { + cancelAlgorithm = reason => underlyingSource.cancel(reason); + } + SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm); +} +// Helper functions for the ReadableStreamDefaultController. +function defaultControllerBrandCheckException$1(name) { + return new TypeError(`ReadableStreamDefaultController.prototype.${name} can only be used on a ReadableStreamDefaultController`); +} + +function ReadableStreamTee(stream, cloneForBranch2) { + const reader = AcquireReadableStreamDefaultReader(stream); + let reading = false; + let canceled1 = false; + let canceled2 = false; + let reason1; + let reason2; + let branch1; + let branch2; + let resolveCancelPromise; + const cancelPromise = newPromise(resolve => { + resolveCancelPromise = resolve; + }); + function pullAlgorithm() { + if (reading) { + return promiseResolvedWith(undefined); + } + reading = true; + const readRequest = { + _chunkSteps: value => { + // This needs to be delayed a microtask because it takes at least a microtask to detect errors (using + // reader._closedPromise below), and we want errors in stream to error both branches immediately. We cannot let + // successful synchronously-available reads get ahead of asynchronously-available errors. + queueMicrotask(() => { + reading = false; + const value1 = value; + const value2 = value; + // There is no way to access the cloning code right now in the reference implementation. + // If we add one then we'll need an implementation for serializable objects. + // if (!canceled2 && cloneForBranch2) { + // value2 = StructuredDeserialize(StructuredSerialize(value2)); + // } + if (!canceled1) { + ReadableStreamDefaultControllerEnqueue(branch1._readableStreamController, value1); + } + if (!canceled2) { + ReadableStreamDefaultControllerEnqueue(branch2._readableStreamController, value2); + } + }); + }, + _closeSteps: () => { + reading = false; + if (!canceled1) { + ReadableStreamDefaultControllerClose(branch1._readableStreamController); + } + if (!canceled2) { + ReadableStreamDefaultControllerClose(branch2._readableStreamController); + } + if (!canceled1 || !canceled2) { + resolveCancelPromise(undefined); + } + }, + _errorSteps: () => { + reading = false; + } + }; + ReadableStreamDefaultReaderRead(reader, readRequest); + return promiseResolvedWith(undefined); + } + function cancel1Algorithm(reason) { + canceled1 = true; + reason1 = reason; + if (canceled2) { + const compositeReason = CreateArrayFromList([reason1, reason2]); + const cancelResult = ReadableStreamCancel(stream, compositeReason); + resolveCancelPromise(cancelResult); + } + return cancelPromise; + } + function cancel2Algorithm(reason) { + canceled2 = true; + reason2 = reason; + if (canceled1) { + const compositeReason = CreateArrayFromList([reason1, reason2]); + const cancelResult = ReadableStreamCancel(stream, compositeReason); + resolveCancelPromise(cancelResult); + } + return cancelPromise; + } + function startAlgorithm() { + // do nothing + } + branch1 = CreateReadableStream(startAlgorithm, pullAlgorithm, cancel1Algorithm); + branch2 = CreateReadableStream(startAlgorithm, pullAlgorithm, cancel2Algorithm); + uponRejection(reader._closedPromise, (r) => { + ReadableStreamDefaultControllerError(branch1._readableStreamController, r); + ReadableStreamDefaultControllerError(branch2._readableStreamController, r); + if (!canceled1 || !canceled2) { + resolveCancelPromise(undefined); + } + }); + return [branch1, branch2]; +} + +function convertUnderlyingDefaultOrByteSource(source, context) { + assertDictionary(source, context); + const original = source; + const autoAllocateChunkSize = original === null || original === void 0 ? void 0 : original.autoAllocateChunkSize; + const cancel = original === null || original === void 0 ? void 0 : original.cancel; + const pull = original === null || original === void 0 ? void 0 : original.pull; + const start = original === null || original === void 0 ? void 0 : original.start; + const type = original === null || original === void 0 ? void 0 : original.type; + return { + autoAllocateChunkSize: autoAllocateChunkSize === undefined ? + undefined : + convertUnsignedLongLongWithEnforceRange(autoAllocateChunkSize, `${context} has member 'autoAllocateChunkSize' that`), + cancel: cancel === undefined ? + undefined : + convertUnderlyingSourceCancelCallback(cancel, original, `${context} has member 'cancel' that`), + pull: pull === undefined ? + undefined : + convertUnderlyingSourcePullCallback(pull, original, `${context} has member 'pull' that`), + start: start === undefined ? + undefined : + convertUnderlyingSourceStartCallback(start, original, `${context} has member 'start' that`), + type: type === undefined ? undefined : convertReadableStreamType(type, `${context} has member 'type' that`) + }; +} +function convertUnderlyingSourceCancelCallback(fn, original, context) { + assertFunction(fn, context); + return (reason) => promiseCall(fn, original, [reason]); +} +function convertUnderlyingSourcePullCallback(fn, original, context) { + assertFunction(fn, context); + return (controller) => promiseCall(fn, original, [controller]); +} +function convertUnderlyingSourceStartCallback(fn, original, context) { + assertFunction(fn, context); + return (controller) => reflectCall(fn, original, [controller]); +} +function convertReadableStreamType(type, context) { + type = `${type}`; + if (type !== 'bytes') { + throw new TypeError(`${context} '${type}' is not a valid enumeration value for ReadableStreamType`); + } + return type; +} + +function convertReaderOptions(options, context) { + assertDictionary(options, context); + const mode = options === null || options === void 0 ? void 0 : options.mode; + return { + mode: mode === undefined ? undefined : convertReadableStreamReaderMode(mode, `${context} has member 'mode' that`) + }; +} +function convertReadableStreamReaderMode(mode, context) { + mode = `${mode}`; + if (mode !== 'byob') { + throw new TypeError(`${context} '${mode}' is not a valid enumeration value for ReadableStreamReaderMode`); + } + return mode; +} + +function convertIteratorOptions(options, context) { + assertDictionary(options, context); + const preventCancel = options === null || options === void 0 ? void 0 : options.preventCancel; + return { preventCancel: Boolean(preventCancel) }; +} + +function convertPipeOptions(options, context) { + assertDictionary(options, context); + const preventAbort = options === null || options === void 0 ? void 0 : options.preventAbort; + const preventCancel = options === null || options === void 0 ? void 0 : options.preventCancel; + const preventClose = options === null || options === void 0 ? void 0 : options.preventClose; + const signal = options === null || options === void 0 ? void 0 : options.signal; + if (signal !== undefined) { + assertAbortSignal(signal, `${context} has member 'signal' that`); + } + return { + preventAbort: Boolean(preventAbort), + preventCancel: Boolean(preventCancel), + preventClose: Boolean(preventClose), + signal + }; +} +function assertAbortSignal(signal, context) { + if (!isAbortSignal(signal)) { + throw new TypeError(`${context} is not an AbortSignal.`); + } +} + +function convertReadableWritablePair(pair, context) { + assertDictionary(pair, context); + const readable = pair === null || pair === void 0 ? void 0 : pair.readable; + assertRequiredField(readable, 'readable', 'ReadableWritablePair'); + assertReadableStream(readable, `${context} has member 'readable' that`); + const writable = pair === null || pair === void 0 ? void 0 : pair.writable; + assertRequiredField(writable, 'writable', 'ReadableWritablePair'); + assertWritableStream(writable, `${context} has member 'writable' that`); + return { readable, writable }; +} + +/** + * A readable stream represents a source of data, from which you can read. + * + * @public + */ +class ReadableStream$1 { + constructor(rawUnderlyingSource = {}, rawStrategy = {}) { + if (rawUnderlyingSource === undefined) { + rawUnderlyingSource = null; + } + else { + assertObject(rawUnderlyingSource, 'First parameter'); + } + const strategy = convertQueuingStrategy(rawStrategy, 'Second parameter'); + const underlyingSource = convertUnderlyingDefaultOrByteSource(rawUnderlyingSource, 'First parameter'); + InitializeReadableStream(this); + if (underlyingSource.type === 'bytes') { + if (strategy.size !== undefined) { + throw new RangeError('The strategy for a byte stream cannot have a size function'); + } + const highWaterMark = ExtractHighWaterMark(strategy, 0); + SetUpReadableByteStreamControllerFromUnderlyingSource(this, underlyingSource, highWaterMark); + } + else { + const sizeAlgorithm = ExtractSizeAlgorithm(strategy); + const highWaterMark = ExtractHighWaterMark(strategy, 1); + SetUpReadableStreamDefaultControllerFromUnderlyingSource(this, underlyingSource, highWaterMark, sizeAlgorithm); + } + } + /** + * Whether or not the readable stream is locked to a {@link ReadableStreamDefaultReader | reader}. + */ + get locked() { + if (!IsReadableStream(this)) { + throw streamBrandCheckException$1('locked'); + } + return IsReadableStreamLocked(this); + } + /** + * Cancels the stream, signaling a loss of interest in the stream by a consumer. + * + * The supplied `reason` argument will be given to the underlying source's {@link UnderlyingSource.cancel | cancel()} + * method, which might or might not use it. + */ + cancel(reason = undefined) { + if (!IsReadableStream(this)) { + return promiseRejectedWith(streamBrandCheckException$1('cancel')); + } + if (IsReadableStreamLocked(this)) { + return promiseRejectedWith(new TypeError('Cannot cancel a stream that already has a reader')); + } + return ReadableStreamCancel(this, reason); + } + getReader(rawOptions = undefined) { + if (!IsReadableStream(this)) { + throw streamBrandCheckException$1('getReader'); + } + const options = convertReaderOptions(rawOptions, 'First parameter'); + if (options.mode === undefined) { + return AcquireReadableStreamDefaultReader(this); + } + return AcquireReadableStreamBYOBReader(this); + } + pipeThrough(rawTransform, rawOptions = {}) { + if (!IsReadableStream(this)) { + throw streamBrandCheckException$1('pipeThrough'); + } + assertRequiredArgument(rawTransform, 1, 'pipeThrough'); + const transform = convertReadableWritablePair(rawTransform, 'First parameter'); + const options = convertPipeOptions(rawOptions, 'Second parameter'); + if (IsReadableStreamLocked(this)) { + throw new TypeError('ReadableStream.prototype.pipeThrough cannot be used on a locked ReadableStream'); + } + if (IsWritableStreamLocked(transform.writable)) { + throw new TypeError('ReadableStream.prototype.pipeThrough cannot be used on a locked WritableStream'); + } + const promise = ReadableStreamPipeTo(this, transform.writable, options.preventClose, options.preventAbort, options.preventCancel, options.signal); + setPromiseIsHandledToTrue(promise); + return transform.readable; + } + pipeTo(destination, rawOptions = {}) { + if (!IsReadableStream(this)) { + return promiseRejectedWith(streamBrandCheckException$1('pipeTo')); + } + if (destination === undefined) { + return promiseRejectedWith(`Parameter 1 is required in 'pipeTo'.`); + } + if (!IsWritableStream(destination)) { + return promiseRejectedWith(new TypeError(`ReadableStream.prototype.pipeTo's first argument must be a WritableStream`)); + } + let options; + try { + options = convertPipeOptions(rawOptions, 'Second parameter'); + } + catch (e) { + return promiseRejectedWith(e); + } + if (IsReadableStreamLocked(this)) { + return promiseRejectedWith(new TypeError('ReadableStream.prototype.pipeTo cannot be used on a locked ReadableStream')); + } + if (IsWritableStreamLocked(destination)) { + return promiseRejectedWith(new TypeError('ReadableStream.prototype.pipeTo cannot be used on a locked WritableStream')); + } + return ReadableStreamPipeTo(this, destination, options.preventClose, options.preventAbort, options.preventCancel, options.signal); + } + /** + * Tees this readable stream, returning a two-element array containing the two resulting branches as + * new {@link ReadableStream} instances. + * + * Teeing a stream will lock it, preventing any other consumer from acquiring a reader. + * To cancel the stream, cancel both of the resulting branches; a composite cancellation reason will then be + * propagated to the stream's underlying source. + * + * Note that the chunks seen in each branch will be the same object. If the chunks are not immutable, + * this could allow interference between the two branches. + */ + tee() { + if (!IsReadableStream(this)) { + throw streamBrandCheckException$1('tee'); + } + const branches = ReadableStreamTee(this); + return CreateArrayFromList(branches); + } + values(rawOptions = undefined) { + if (!IsReadableStream(this)) { + throw streamBrandCheckException$1('values'); + } + const options = convertIteratorOptions(rawOptions, 'First parameter'); + return AcquireReadableStreamAsyncIterator(this, options.preventCancel); + } +} +Object.defineProperties(ReadableStream$1.prototype, { + cancel: { enumerable: true }, + getReader: { enumerable: true }, + pipeThrough: { enumerable: true }, + pipeTo: { enumerable: true }, + tee: { enumerable: true }, + values: { enumerable: true }, + locked: { enumerable: true } +}); +if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(ReadableStream$1.prototype, SymbolPolyfill.toStringTag, { + value: 'ReadableStream', + configurable: true + }); +} +if (typeof SymbolPolyfill.asyncIterator === 'symbol') { + Object.defineProperty(ReadableStream$1.prototype, SymbolPolyfill.asyncIterator, { + value: ReadableStream$1.prototype.values, + writable: true, + configurable: true + }); +} +// Abstract operations for the ReadableStream. +// Throws if and only if startAlgorithm throws. +function CreateReadableStream(startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark = 1, sizeAlgorithm = () => 1) { + const stream = Object.create(ReadableStream$1.prototype); + InitializeReadableStream(stream); + const controller = Object.create(ReadableStreamDefaultController.prototype); + SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm); + return stream; +} +function InitializeReadableStream(stream) { + stream._state = 'readable'; + stream._reader = undefined; + stream._storedError = undefined; + stream._disturbed = false; +} +function IsReadableStream(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_readableStreamController')) { + return false; + } + return true; +} +function IsReadableStreamLocked(stream) { + if (stream._reader === undefined) { + return false; + } + return true; +} +// ReadableStream API exposed for controllers. +function ReadableStreamCancel(stream, reason) { + stream._disturbed = true; + if (stream._state === 'closed') { + return promiseResolvedWith(undefined); + } + if (stream._state === 'errored') { + return promiseRejectedWith(stream._storedError); + } + ReadableStreamClose(stream); + const sourceCancelPromise = stream._readableStreamController[CancelSteps](reason); + return transformPromiseWith(sourceCancelPromise, noop); +} +function ReadableStreamClose(stream) { + stream._state = 'closed'; + const reader = stream._reader; + if (reader === undefined) { + return; + } + defaultReaderClosedPromiseResolve(reader); + if (IsReadableStreamDefaultReader(reader)) { + reader._readRequests.forEach(readRequest => { + readRequest._closeSteps(); + }); + reader._readRequests = new SimpleQueue(); + } +} +function ReadableStreamError(stream, e) { + stream._state = 'errored'; + stream._storedError = e; + const reader = stream._reader; + if (reader === undefined) { + return; + } + defaultReaderClosedPromiseReject(reader, e); + if (IsReadableStreamDefaultReader(reader)) { + reader._readRequests.forEach(readRequest => { + readRequest._errorSteps(e); + }); + reader._readRequests = new SimpleQueue(); + } + else { + reader._readIntoRequests.forEach(readIntoRequest => { + readIntoRequest._errorSteps(e); + }); + reader._readIntoRequests = new SimpleQueue(); + } +} +// Helper functions for the ReadableStream. +function streamBrandCheckException$1(name) { + return new TypeError(`ReadableStream.prototype.${name} can only be used on a ReadableStream`); +} + +function convertQueuingStrategyInit(init, context) { + assertDictionary(init, context); + const highWaterMark = init === null || init === void 0 ? void 0 : init.highWaterMark; + assertRequiredField(highWaterMark, 'highWaterMark', 'QueuingStrategyInit'); + return { + highWaterMark: convertUnrestrictedDouble(highWaterMark) + }; +} + +const byteLengthSizeFunction = function size(chunk) { + return chunk.byteLength; +}; +/** + * A queuing strategy that counts the number of bytes in each chunk. + * + * @public + */ +class ByteLengthQueuingStrategy { + constructor(options) { + assertRequiredArgument(options, 1, 'ByteLengthQueuingStrategy'); + options = convertQueuingStrategyInit(options, 'First parameter'); + this._byteLengthQueuingStrategyHighWaterMark = options.highWaterMark; + } + /** + * Returns the high water mark provided to the constructor. + */ + get highWaterMark() { + if (!IsByteLengthQueuingStrategy(this)) { + throw byteLengthBrandCheckException('highWaterMark'); + } + return this._byteLengthQueuingStrategyHighWaterMark; + } + /** + * Measures the size of `chunk` by returning the value of its `byteLength` property. + */ + get size() { + if (!IsByteLengthQueuingStrategy(this)) { + throw byteLengthBrandCheckException('size'); + } + return byteLengthSizeFunction; + } +} +Object.defineProperties(ByteLengthQueuingStrategy.prototype, { + highWaterMark: { enumerable: true }, + size: { enumerable: true } +}); +if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(ByteLengthQueuingStrategy.prototype, SymbolPolyfill.toStringTag, { + value: 'ByteLengthQueuingStrategy', + configurable: true + }); +} +// Helper functions for the ByteLengthQueuingStrategy. +function byteLengthBrandCheckException(name) { + return new TypeError(`ByteLengthQueuingStrategy.prototype.${name} can only be used on a ByteLengthQueuingStrategy`); +} +function IsByteLengthQueuingStrategy(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_byteLengthQueuingStrategyHighWaterMark')) { + return false; + } + return true; +} + +const countSizeFunction = function size() { + return 1; +}; +/** + * A queuing strategy that counts the number of chunks. + * + * @public + */ +class CountQueuingStrategy { + constructor(options) { + assertRequiredArgument(options, 1, 'CountQueuingStrategy'); + options = convertQueuingStrategyInit(options, 'First parameter'); + this._countQueuingStrategyHighWaterMark = options.highWaterMark; + } + /** + * Returns the high water mark provided to the constructor. + */ + get highWaterMark() { + if (!IsCountQueuingStrategy(this)) { + throw countBrandCheckException('highWaterMark'); + } + return this._countQueuingStrategyHighWaterMark; + } + /** + * Measures the size of `chunk` by always returning 1. + * This ensures that the total queue size is a count of the number of chunks in the queue. + */ + get size() { + if (!IsCountQueuingStrategy(this)) { + throw countBrandCheckException('size'); + } + return countSizeFunction; + } +} +Object.defineProperties(CountQueuingStrategy.prototype, { + highWaterMark: { enumerable: true }, + size: { enumerable: true } +}); +if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(CountQueuingStrategy.prototype, SymbolPolyfill.toStringTag, { + value: 'CountQueuingStrategy', + configurable: true + }); +} +// Helper functions for the CountQueuingStrategy. +function countBrandCheckException(name) { + return new TypeError(`CountQueuingStrategy.prototype.${name} can only be used on a CountQueuingStrategy`); +} +function IsCountQueuingStrategy(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_countQueuingStrategyHighWaterMark')) { + return false; + } + return true; +} + +function convertTransformer(original, context) { + assertDictionary(original, context); + const flush = original === null || original === void 0 ? void 0 : original.flush; + const readableType = original === null || original === void 0 ? void 0 : original.readableType; + const start = original === null || original === void 0 ? void 0 : original.start; + const transform = original === null || original === void 0 ? void 0 : original.transform; + const writableType = original === null || original === void 0 ? void 0 : original.writableType; + return { + flush: flush === undefined ? + undefined : + convertTransformerFlushCallback(flush, original, `${context} has member 'flush' that`), + readableType, + start: start === undefined ? + undefined : + convertTransformerStartCallback(start, original, `${context} has member 'start' that`), + transform: transform === undefined ? + undefined : + convertTransformerTransformCallback(transform, original, `${context} has member 'transform' that`), + writableType + }; +} +function convertTransformerFlushCallback(fn, original, context) { + assertFunction(fn, context); + return (controller) => promiseCall(fn, original, [controller]); +} +function convertTransformerStartCallback(fn, original, context) { + assertFunction(fn, context); + return (controller) => reflectCall(fn, original, [controller]); +} +function convertTransformerTransformCallback(fn, original, context) { + assertFunction(fn, context); + return (chunk, controller) => promiseCall(fn, original, [chunk, controller]); +} + +// Class TransformStream +/** + * A transform stream consists of a pair of streams: a {@link WritableStream | writable stream}, + * known as its writable side, and a {@link ReadableStream | readable stream}, known as its readable side. + * In a manner specific to the transform stream in question, writes to the writable side result in new data being + * made available for reading from the readable side. + * + * @public + */ +class TransformStream$1 { + constructor(rawTransformer = {}, rawWritableStrategy = {}, rawReadableStrategy = {}) { + if (rawTransformer === undefined) { + rawTransformer = null; + } + const writableStrategy = convertQueuingStrategy(rawWritableStrategy, 'Second parameter'); + const readableStrategy = convertQueuingStrategy(rawReadableStrategy, 'Third parameter'); + const transformer = convertTransformer(rawTransformer, 'First parameter'); + if (transformer.readableType !== undefined) { + throw new RangeError('Invalid readableType specified'); + } + if (transformer.writableType !== undefined) { + throw new RangeError('Invalid writableType specified'); + } + const readableHighWaterMark = ExtractHighWaterMark(readableStrategy, 0); + const readableSizeAlgorithm = ExtractSizeAlgorithm(readableStrategy); + const writableHighWaterMark = ExtractHighWaterMark(writableStrategy, 1); + const writableSizeAlgorithm = ExtractSizeAlgorithm(writableStrategy); + let startPromise_resolve; + const startPromise = newPromise(resolve => { + startPromise_resolve = resolve; + }); + InitializeTransformStream(this, startPromise, writableHighWaterMark, writableSizeAlgorithm, readableHighWaterMark, readableSizeAlgorithm); + SetUpTransformStreamDefaultControllerFromTransformer(this, transformer); + if (transformer.start !== undefined) { + startPromise_resolve(transformer.start(this._transformStreamController)); + } + else { + startPromise_resolve(undefined); + } + } + /** + * The readable side of the transform stream. + */ + get readable() { + if (!IsTransformStream(this)) { + throw streamBrandCheckException('readable'); + } + return this._readable; + } + /** + * The writable side of the transform stream. + */ + get writable() { + if (!IsTransformStream(this)) { + throw streamBrandCheckException('writable'); + } + return this._writable; + } +} +Object.defineProperties(TransformStream$1.prototype, { + readable: { enumerable: true }, + writable: { enumerable: true } +}); +if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(TransformStream$1.prototype, SymbolPolyfill.toStringTag, { + value: 'TransformStream', + configurable: true + }); +} +function InitializeTransformStream(stream, startPromise, writableHighWaterMark, writableSizeAlgorithm, readableHighWaterMark, readableSizeAlgorithm) { + function startAlgorithm() { + return startPromise; + } + function writeAlgorithm(chunk) { + return TransformStreamDefaultSinkWriteAlgorithm(stream, chunk); + } + function abortAlgorithm(reason) { + return TransformStreamDefaultSinkAbortAlgorithm(stream, reason); + } + function closeAlgorithm() { + return TransformStreamDefaultSinkCloseAlgorithm(stream); + } + stream._writable = CreateWritableStream(startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, writableHighWaterMark, writableSizeAlgorithm); + function pullAlgorithm() { + return TransformStreamDefaultSourcePullAlgorithm(stream); + } + function cancelAlgorithm(reason) { + TransformStreamErrorWritableAndUnblockWrite(stream, reason); + return promiseResolvedWith(undefined); + } + stream._readable = CreateReadableStream(startAlgorithm, pullAlgorithm, cancelAlgorithm, readableHighWaterMark, readableSizeAlgorithm); + // The [[backpressure]] slot is set to undefined so that it can be initialised by TransformStreamSetBackpressure. + stream._backpressure = undefined; + stream._backpressureChangePromise = undefined; + stream._backpressureChangePromise_resolve = undefined; + TransformStreamSetBackpressure(stream, true); + stream._transformStreamController = undefined; +} +function IsTransformStream(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_transformStreamController')) { + return false; + } + return true; +} +// This is a no-op if both sides are already errored. +function TransformStreamError(stream, e) { + ReadableStreamDefaultControllerError(stream._readable._readableStreamController, e); + TransformStreamErrorWritableAndUnblockWrite(stream, e); +} +function TransformStreamErrorWritableAndUnblockWrite(stream, e) { + TransformStreamDefaultControllerClearAlgorithms(stream._transformStreamController); + WritableStreamDefaultControllerErrorIfNeeded(stream._writable._writableStreamController, e); + if (stream._backpressure) { + // Pretend that pull() was called to permit any pending write() calls to complete. TransformStreamSetBackpressure() + // cannot be called from enqueue() or pull() once the ReadableStream is errored, so this will will be the final time + // _backpressure is set. + TransformStreamSetBackpressure(stream, false); + } +} +function TransformStreamSetBackpressure(stream, backpressure) { + // Passes also when called during construction. + if (stream._backpressureChangePromise !== undefined) { + stream._backpressureChangePromise_resolve(); + } + stream._backpressureChangePromise = newPromise(resolve => { + stream._backpressureChangePromise_resolve = resolve; + }); + stream._backpressure = backpressure; +} +// Class TransformStreamDefaultController +/** + * Allows control of the {@link ReadableStream} and {@link WritableStream} of the associated {@link TransformStream}. + * + * @public + */ +class TransformStreamDefaultController { + constructor() { + throw new TypeError('Illegal constructor'); + } + /** + * Returns the desired size to fill the readable side’s internal queue. It can be negative, if the queue is over-full. + */ + get desiredSize() { + if (!IsTransformStreamDefaultController(this)) { + throw defaultControllerBrandCheckException('desiredSize'); + } + const readableController = this._controlledTransformStream._readable._readableStreamController; + return ReadableStreamDefaultControllerGetDesiredSize(readableController); + } + enqueue(chunk = undefined) { + if (!IsTransformStreamDefaultController(this)) { + throw defaultControllerBrandCheckException('enqueue'); + } + TransformStreamDefaultControllerEnqueue(this, chunk); + } + /** + * Errors both the readable side and the writable side of the controlled transform stream, making all future + * interactions with it fail with the given error `e`. Any chunks queued for transformation will be discarded. + */ + error(reason = undefined) { + if (!IsTransformStreamDefaultController(this)) { + throw defaultControllerBrandCheckException('error'); + } + TransformStreamDefaultControllerError(this, reason); + } + /** + * Closes the readable side and errors the writable side of the controlled transform stream. This is useful when the + * transformer only needs to consume a portion of the chunks written to the writable side. + */ + terminate() { + if (!IsTransformStreamDefaultController(this)) { + throw defaultControllerBrandCheckException('terminate'); + } + TransformStreamDefaultControllerTerminate(this); + } +} +Object.defineProperties(TransformStreamDefaultController.prototype, { + enqueue: { enumerable: true }, + error: { enumerable: true }, + terminate: { enumerable: true }, + desiredSize: { enumerable: true } +}); +if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(TransformStreamDefaultController.prototype, SymbolPolyfill.toStringTag, { + value: 'TransformStreamDefaultController', + configurable: true + }); +} +// Transform Stream Default Controller Abstract Operations +function IsTransformStreamDefaultController(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_controlledTransformStream')) { + return false; + } + return true; +} +function SetUpTransformStreamDefaultController(stream, controller, transformAlgorithm, flushAlgorithm) { + controller._controlledTransformStream = stream; + stream._transformStreamController = controller; + controller._transformAlgorithm = transformAlgorithm; + controller._flushAlgorithm = flushAlgorithm; +} +function SetUpTransformStreamDefaultControllerFromTransformer(stream, transformer) { + const controller = Object.create(TransformStreamDefaultController.prototype); + let transformAlgorithm = (chunk) => { + try { + TransformStreamDefaultControllerEnqueue(controller, chunk); + return promiseResolvedWith(undefined); + } + catch (transformResultE) { + return promiseRejectedWith(transformResultE); + } + }; + let flushAlgorithm = () => promiseResolvedWith(undefined); + if (transformer.transform !== undefined) { + transformAlgorithm = chunk => transformer.transform(chunk, controller); + } + if (transformer.flush !== undefined) { + flushAlgorithm = () => transformer.flush(controller); + } + SetUpTransformStreamDefaultController(stream, controller, transformAlgorithm, flushAlgorithm); +} +function TransformStreamDefaultControllerClearAlgorithms(controller) { + controller._transformAlgorithm = undefined; + controller._flushAlgorithm = undefined; +} +function TransformStreamDefaultControllerEnqueue(controller, chunk) { + const stream = controller._controlledTransformStream; + const readableController = stream._readable._readableStreamController; + if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(readableController)) { + throw new TypeError('Readable side is not in a state that permits enqueue'); + } + // We throttle transform invocations based on the backpressure of the ReadableStream, but we still + // accept TransformStreamDefaultControllerEnqueue() calls. + try { + ReadableStreamDefaultControllerEnqueue(readableController, chunk); + } + catch (e) { + // This happens when readableStrategy.size() throws. + TransformStreamErrorWritableAndUnblockWrite(stream, e); + throw stream._readable._storedError; + } + const backpressure = ReadableStreamDefaultControllerHasBackpressure(readableController); + if (backpressure !== stream._backpressure) { + TransformStreamSetBackpressure(stream, true); + } +} +function TransformStreamDefaultControllerError(controller, e) { + TransformStreamError(controller._controlledTransformStream, e); +} +function TransformStreamDefaultControllerPerformTransform(controller, chunk) { + const transformPromise = controller._transformAlgorithm(chunk); + return transformPromiseWith(transformPromise, undefined, r => { + TransformStreamError(controller._controlledTransformStream, r); + throw r; + }); +} +function TransformStreamDefaultControllerTerminate(controller) { + const stream = controller._controlledTransformStream; + const readableController = stream._readable._readableStreamController; + ReadableStreamDefaultControllerClose(readableController); + const error = new TypeError('TransformStream terminated'); + TransformStreamErrorWritableAndUnblockWrite(stream, error); +} +// TransformStreamDefaultSink Algorithms +function TransformStreamDefaultSinkWriteAlgorithm(stream, chunk) { + const controller = stream._transformStreamController; + if (stream._backpressure) { + const backpressureChangePromise = stream._backpressureChangePromise; + return transformPromiseWith(backpressureChangePromise, () => { + const writable = stream._writable; + const state = writable._state; + if (state === 'erroring') { + throw writable._storedError; + } + return TransformStreamDefaultControllerPerformTransform(controller, chunk); + }); + } + return TransformStreamDefaultControllerPerformTransform(controller, chunk); +} +function TransformStreamDefaultSinkAbortAlgorithm(stream, reason) { + // abort() is not called synchronously, so it is possible for abort() to be called when the stream is already + // errored. + TransformStreamError(stream, reason); + return promiseResolvedWith(undefined); +} +function TransformStreamDefaultSinkCloseAlgorithm(stream) { + // stream._readable cannot change after construction, so caching it across a call to user code is safe. + const readable = stream._readable; + const controller = stream._transformStreamController; + const flushPromise = controller._flushAlgorithm(); + TransformStreamDefaultControllerClearAlgorithms(controller); + // Return a promise that is fulfilled with undefined on success. + return transformPromiseWith(flushPromise, () => { + if (readable._state === 'errored') { + throw readable._storedError; + } + ReadableStreamDefaultControllerClose(readable._readableStreamController); + }, r => { + TransformStreamError(stream, r); + throw readable._storedError; + }); +} +// TransformStreamDefaultSource Algorithms +function TransformStreamDefaultSourcePullAlgorithm(stream) { + // Invariant. Enforced by the promises returned by start() and pull(). + TransformStreamSetBackpressure(stream, false); + // Prevent the next pull() call until there is backpressure. + return stream._backpressureChangePromise; +} +// Helper functions for the TransformStreamDefaultController. +function defaultControllerBrandCheckException(name) { + return new TypeError(`TransformStreamDefaultController.prototype.${name} can only be used on a TransformStreamDefaultController`); +} +// Helper functions for the TransformStream. +function streamBrandCheckException(name) { + return new TypeError(`TransformStream.prototype.${name} can only be used on a TransformStream`); +} + +var ponyfill_es6 = /*#__PURE__*/Object.freeze({ + __proto__: null, + ByteLengthQueuingStrategy: ByteLengthQueuingStrategy, + CountQueuingStrategy: CountQueuingStrategy, + ReadableByteStreamController: ReadableByteStreamController, + ReadableStream: ReadableStream$1, + ReadableStreamBYOBReader: ReadableStreamBYOBReader, + ReadableStreamBYOBRequest: ReadableStreamBYOBRequest, + ReadableStreamDefaultController: ReadableStreamDefaultController, + ReadableStreamDefaultReader: ReadableStreamDefaultReader, + TransformStream: TransformStream$1, + TransformStreamDefaultController: TransformStreamDefaultController, + WritableStream: WritableStream$1, + WritableStreamDefaultController: WritableStreamDefaultController, + WritableStreamDefaultWriter: WritableStreamDefaultWriter +}); + +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */ +/* global Reflect, Promise */ + +var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); +}; + +function __extends(d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +} + +function assert$1(test) { + if (!test) { + throw new TypeError('Assertion failed'); + } +} + +function noop$1() { + return; +} +function typeIsObject$1(x) { + return (typeof x === 'object' && x !== null) || typeof x === 'function'; +} + +function isStreamConstructor(ctor) { + if (typeof ctor !== 'function') { + return false; + } + var startCalled = false; + try { + new ctor({ + start: function () { + startCalled = true; + } + }); + } + catch (e) { + // ignore + } + return startCalled; +} +function isReadableStream(readable) { + if (!typeIsObject$1(readable)) { + return false; + } + if (typeof readable.getReader !== 'function') { + return false; + } + return true; +} +function isReadableStreamConstructor(ctor) { + if (!isStreamConstructor(ctor)) { + return false; + } + if (!isReadableStream(new ctor())) { + return false; + } + return true; +} +function isWritableStream(writable) { + if (!typeIsObject$1(writable)) { + return false; + } + if (typeof writable.getWriter !== 'function') { + return false; + } + return true; +} +function isWritableStreamConstructor(ctor) { + if (!isStreamConstructor(ctor)) { + return false; + } + if (!isWritableStream(new ctor())) { + return false; + } + return true; +} +function isTransformStream(transform) { + if (!typeIsObject$1(transform)) { + return false; + } + if (!isReadableStream(transform.readable)) { + return false; + } + if (!isWritableStream(transform.writable)) { + return false; + } + return true; +} +function isTransformStreamConstructor(ctor) { + if (!isStreamConstructor(ctor)) { + return false; + } + if (!isTransformStream(new ctor())) { + return false; + } + return true; +} +function supportsByobReader(readable) { + try { + var reader = readable.getReader({ mode: 'byob' }); + reader.releaseLock(); + return true; + } + catch (_a) { + return false; + } +} +function supportsByteSource(ctor) { + try { + new ctor({ type: 'bytes' }); + return true; + } + catch (_a) { + return false; + } +} + +function createReadableStreamWrapper(ctor) { + assert$1(isReadableStreamConstructor(ctor)); + var byteSourceSupported = supportsByteSource(ctor); + return function (readable, _a) { + var _b = _a === void 0 ? {} : _a, type = _b.type; + type = parseReadableType(type); + if (type === 'bytes' && !byteSourceSupported) { + type = undefined; + } + if (readable.constructor === ctor) { + if (type !== 'bytes' || supportsByobReader(readable)) { + return readable; + } + } + if (type === 'bytes') { + var source = createWrappingReadableSource(readable, { type: type }); + return new ctor(source); + } + else { + var source = createWrappingReadableSource(readable); + return new ctor(source); + } + }; +} +function createWrappingReadableSource(readable, _a) { + var _b = _a === void 0 ? {} : _a, type = _b.type; + assert$1(isReadableStream(readable)); + assert$1(readable.locked === false); + type = parseReadableType(type); + var source; + if (type === 'bytes') { + source = new WrappingReadableByteStreamSource(readable); + } + else { + source = new WrappingReadableStreamDefaultSource(readable); + } + return source; +} +function parseReadableType(type) { + var typeString = String(type); + if (typeString === 'bytes') { + return typeString; + } + else if (type === undefined) { + return type; + } + else { + throw new RangeError('Invalid type is specified'); + } +} +var AbstractWrappingReadableStreamSource = /** @class */ (function () { + function AbstractWrappingReadableStreamSource(underlyingStream) { + this._underlyingReader = undefined; + this._readerMode = undefined; + this._readableStreamController = undefined; + this._pendingRead = undefined; + this._underlyingStream = underlyingStream; + // always keep a reader attached to detect close/error + this._attachDefaultReader(); + } + AbstractWrappingReadableStreamSource.prototype.start = function (controller) { + this._readableStreamController = controller; + }; + AbstractWrappingReadableStreamSource.prototype.cancel = function (reason) { + assert$1(this._underlyingReader !== undefined); + return this._underlyingReader.cancel(reason); + }; + AbstractWrappingReadableStreamSource.prototype._attachDefaultReader = function () { + if (this._readerMode === "default" /* DEFAULT */) { + return; + } + this._detachReader(); + var reader = this._underlyingStream.getReader(); + this._readerMode = "default" /* DEFAULT */; + this._attachReader(reader); + }; + AbstractWrappingReadableStreamSource.prototype._attachReader = function (reader) { + var _this = this; + assert$1(this._underlyingReader === undefined); + this._underlyingReader = reader; + var closed = this._underlyingReader.closed; + if (!closed) { + return; + } + closed + .then(function () { return _this._finishPendingRead(); }) + .then(function () { + if (reader === _this._underlyingReader) { + _this._readableStreamController.close(); + } + }, function (reason) { + if (reader === _this._underlyingReader) { + _this._readableStreamController.error(reason); + } + }) + .catch(noop$1); + }; + AbstractWrappingReadableStreamSource.prototype._detachReader = function () { + if (this._underlyingReader === undefined) { + return; + } + this._underlyingReader.releaseLock(); + this._underlyingReader = undefined; + this._readerMode = undefined; + }; + AbstractWrappingReadableStreamSource.prototype._pullWithDefaultReader = function () { + var _this = this; + this._attachDefaultReader(); + // TODO Backpressure? + var read = this._underlyingReader.read() + .then(function (result) { + var controller = _this._readableStreamController; + if (result.done) { + _this._tryClose(); + } + else { + controller.enqueue(result.value); + } + }); + this._setPendingRead(read); + return read; + }; + AbstractWrappingReadableStreamSource.prototype._tryClose = function () { + try { + this._readableStreamController.close(); + } + catch (_a) { + // already errored or closed + } + }; + AbstractWrappingReadableStreamSource.prototype._setPendingRead = function (readPromise) { + var _this = this; + var pendingRead; + var finishRead = function () { + if (_this._pendingRead === pendingRead) { + _this._pendingRead = undefined; + } + }; + this._pendingRead = pendingRead = readPromise.then(finishRead, finishRead); + }; + AbstractWrappingReadableStreamSource.prototype._finishPendingRead = function () { + var _this = this; + if (!this._pendingRead) { + return undefined; + } + var afterRead = function () { return _this._finishPendingRead(); }; + return this._pendingRead.then(afterRead, afterRead); + }; + return AbstractWrappingReadableStreamSource; +}()); +var WrappingReadableStreamDefaultSource = /** @class */ (function (_super) { + __extends(WrappingReadableStreamDefaultSource, _super); + function WrappingReadableStreamDefaultSource() { + return _super !== null && _super.apply(this, arguments) || this; + } + WrappingReadableStreamDefaultSource.prototype.pull = function () { + return this._pullWithDefaultReader(); + }; + return WrappingReadableStreamDefaultSource; +}(AbstractWrappingReadableStreamSource)); +function toUint8Array(view) { + return new Uint8Array(view.buffer, view.byteOffset, view.byteLength); +} +function copyArrayBufferView(from, to) { + var fromArray = toUint8Array(from); + var toArray = toUint8Array(to); + toArray.set(fromArray, 0); +} +var WrappingReadableByteStreamSource = /** @class */ (function (_super) { + __extends(WrappingReadableByteStreamSource, _super); + function WrappingReadableByteStreamSource(underlyingStream) { + var _this = this; + var supportsByob = supportsByobReader(underlyingStream); + _this = _super.call(this, underlyingStream) || this; + _this._supportsByob = supportsByob; + return _this; + } + Object.defineProperty(WrappingReadableByteStreamSource.prototype, "type", { + get: function () { + return 'bytes'; + }, + enumerable: false, + configurable: true + }); + WrappingReadableByteStreamSource.prototype._attachByobReader = function () { + if (this._readerMode === "byob" /* BYOB */) { + return; + } + assert$1(this._supportsByob); + this._detachReader(); + var reader = this._underlyingStream.getReader({ mode: 'byob' }); + this._readerMode = "byob" /* BYOB */; + this._attachReader(reader); + }; + WrappingReadableByteStreamSource.prototype.pull = function () { + if (this._supportsByob) { + var byobRequest = this._readableStreamController.byobRequest; + if (byobRequest) { + return this._pullWithByobRequest(byobRequest); + } + } + return this._pullWithDefaultReader(); + }; + WrappingReadableByteStreamSource.prototype._pullWithByobRequest = function (byobRequest) { + var _this = this; + this._attachByobReader(); + // reader.read(view) detaches the input view, therefore we cannot pass byobRequest.view directly + // create a separate buffer to read into, then copy that to byobRequest.view + var buffer = new Uint8Array(byobRequest.view.byteLength); + // TODO Backpressure? + var read = this._underlyingReader.read(buffer) + .then(function (result) { + _this._readableStreamController; + if (result.done) { + _this._tryClose(); + byobRequest.respond(0); + } + else { + copyArrayBufferView(result.value, byobRequest.view); + byobRequest.respond(result.value.byteLength); + } + }); + this._setPendingRead(read); + return read; + }; + return WrappingReadableByteStreamSource; +}(AbstractWrappingReadableStreamSource)); + +function createWritableStreamWrapper(ctor) { + assert$1(isWritableStreamConstructor(ctor)); + return function (writable) { + if (writable.constructor === ctor) { + return writable; + } + var sink = createWrappingWritableSink(writable); + return new ctor(sink); + }; +} +function createWrappingWritableSink(writable) { + assert$1(isWritableStream(writable)); + assert$1(writable.locked === false); + var writer = writable.getWriter(); + return new WrappingWritableStreamSink(writer); +} +var WrappingWritableStreamSink = /** @class */ (function () { + function WrappingWritableStreamSink(underlyingWriter) { + var _this = this; + this._writableStreamController = undefined; + this._pendingWrite = undefined; + this._state = "writable" /* WRITABLE */; + this._storedError = undefined; + this._underlyingWriter = underlyingWriter; + this._errorPromise = new Promise(function (resolve, reject) { + _this._errorPromiseReject = reject; + }); + this._errorPromise.catch(noop$1); + } + WrappingWritableStreamSink.prototype.start = function (controller) { + var _this = this; + this._writableStreamController = controller; + this._underlyingWriter.closed + .then(function () { + _this._state = "closed" /* CLOSED */; + }) + .catch(function (reason) { return _this._finishErroring(reason); }); + }; + WrappingWritableStreamSink.prototype.write = function (chunk) { + var _this = this; + var writer = this._underlyingWriter; + // Detect past errors + if (writer.desiredSize === null) { + return writer.ready; + } + var writeRequest = writer.write(chunk); + // Detect future errors + writeRequest.catch(function (reason) { return _this._finishErroring(reason); }); + writer.ready.catch(function (reason) { return _this._startErroring(reason); }); + // Reject write when errored + var write = Promise.race([writeRequest, this._errorPromise]); + this._setPendingWrite(write); + return write; + }; + WrappingWritableStreamSink.prototype.close = function () { + var _this = this; + if (this._pendingWrite === undefined) { + return this._underlyingWriter.close(); + } + return this._finishPendingWrite().then(function () { return _this.close(); }); + }; + WrappingWritableStreamSink.prototype.abort = function (reason) { + if (this._state === "errored" /* ERRORED */) { + return undefined; + } + var writer = this._underlyingWriter; + return writer.abort(reason); + }; + WrappingWritableStreamSink.prototype._setPendingWrite = function (writePromise) { + var _this = this; + var pendingWrite; + var finishWrite = function () { + if (_this._pendingWrite === pendingWrite) { + _this._pendingWrite = undefined; + } + }; + this._pendingWrite = pendingWrite = writePromise.then(finishWrite, finishWrite); + }; + WrappingWritableStreamSink.prototype._finishPendingWrite = function () { + var _this = this; + if (this._pendingWrite === undefined) { + return Promise.resolve(); + } + var afterWrite = function () { return _this._finishPendingWrite(); }; + return this._pendingWrite.then(afterWrite, afterWrite); + }; + WrappingWritableStreamSink.prototype._startErroring = function (reason) { + var _this = this; + if (this._state === "writable" /* WRITABLE */) { + this._state = "erroring" /* ERRORING */; + this._storedError = reason; + var afterWrite = function () { return _this._finishErroring(reason); }; + if (this._pendingWrite === undefined) { + afterWrite(); + } + else { + this._finishPendingWrite().then(afterWrite, afterWrite); + } + this._writableStreamController.error(reason); + } + }; + WrappingWritableStreamSink.prototype._finishErroring = function (reason) { + if (this._state === "writable" /* WRITABLE */) { + this._startErroring(reason); + } + if (this._state === "erroring" /* ERRORING */) { + this._state = "errored" /* ERRORED */; + this._errorPromiseReject(this._storedError); + } + }; + return WrappingWritableStreamSink; +}()); + +function createTransformStreamWrapper(ctor) { + assert$1(isTransformStreamConstructor(ctor)); + return function (transform) { + if (transform.constructor === ctor) { + return transform; + } + var transformer = createWrappingTransformer(transform); + return new ctor(transformer); + }; +} +function createWrappingTransformer(transform) { + assert$1(isTransformStream(transform)); + var readable = transform.readable, writable = transform.writable; + assert$1(readable.locked === false); + assert$1(writable.locked === false); + var reader = readable.getReader(); + var writer; + try { + writer = writable.getWriter(); + } + catch (e) { + reader.releaseLock(); // do not leak reader + throw e; + } + return new WrappingTransformStreamTransformer(reader, writer); +} +var WrappingTransformStreamTransformer = /** @class */ (function () { + function WrappingTransformStreamTransformer(reader, writer) { + var _this = this; + this._transformStreamController = undefined; + this._onRead = function (result) { + if (result.done) { + return; + } + _this._transformStreamController.enqueue(result.value); + return _this._reader.read().then(_this._onRead); + }; + this._onError = function (reason) { + _this._flushReject(reason); + _this._transformStreamController.error(reason); + _this._reader.cancel(reason).catch(noop$1); + _this._writer.abort(reason).catch(noop$1); + }; + this._onTerminate = function () { + _this._flushResolve(); + _this._transformStreamController.terminate(); + var error = new TypeError('TransformStream terminated'); + _this._writer.abort(error).catch(noop$1); + }; + this._reader = reader; + this._writer = writer; + this._flushPromise = new Promise(function (resolve, reject) { + _this._flushResolve = resolve; + _this._flushReject = reject; + }); + } + WrappingTransformStreamTransformer.prototype.start = function (controller) { + this._transformStreamController = controller; + this._reader.read() + .then(this._onRead) + .then(this._onTerminate, this._onError); + var readerClosed = this._reader.closed; + if (readerClosed) { + readerClosed + .then(this._onTerminate, this._onError); + } + }; + WrappingTransformStreamTransformer.prototype.transform = function (chunk) { + return this._writer.write(chunk); + }; + WrappingTransformStreamTransformer.prototype.flush = function () { + var _this = this; + return this._writer.close() + .then(function () { return _this._flushPromise; }); + }; + return WrappingTransformStreamTransformer; +}()); + +var webStreamsAdapter = /*#__PURE__*/Object.freeze({ + __proto__: null, + createReadableStreamWrapper: createReadableStreamWrapper, + createTransformStreamWrapper: createTransformStreamWrapper, + createWrappingReadableSource: createWrappingReadableSource, + createWrappingTransformer: createWrappingTransformer, + createWrappingWritableSink: createWrappingWritableSink, + createWritableStreamWrapper: createWritableStreamWrapper +}); + +var bn = createCommonjsModule(function (module) { +(function (module, exports) { + + // Utils + function assert (val, msg) { + if (!val) throw new Error(msg || 'Assertion failed'); + } + + // Could use `inherits` module, but don't want to move from single file + // architecture yet. + function inherits (ctor, superCtor) { + ctor.super_ = superCtor; + var TempCtor = function () {}; + TempCtor.prototype = superCtor.prototype; + ctor.prototype = new TempCtor(); + ctor.prototype.constructor = ctor; + } + + // BN + + function BN (number, base, endian) { + if (BN.isBN(number)) { + return number; + } + + this.negative = 0; + this.words = null; + this.length = 0; + + // Reduction context + this.red = null; + + if (number !== null) { + if (base === 'le' || base === 'be') { + endian = base; + base = 10; + } + + this._init(number || 0, base || 10, endian || 'be'); + } + } + if (typeof module === 'object') { + module.exports = BN; + } else { + exports.BN = BN; + } + + BN.BN = BN; + BN.wordSize = 26; + + var Buffer; + try { + Buffer = buffer__default['default'].Buffer; + } catch (e) { + } + + BN.isBN = function isBN (num) { + if (num instanceof BN) { + return true; + } + + return num !== null && typeof num === 'object' && + num.constructor.wordSize === BN.wordSize && Array.isArray(num.words); + }; + + BN.max = function max (left, right) { + if (left.cmp(right) > 0) return left; + return right; + }; + + BN.min = function min (left, right) { + if (left.cmp(right) < 0) return left; + return right; + }; + + BN.prototype._init = function init (number, base, endian) { + if (typeof number === 'number') { + return this._initNumber(number, base, endian); + } + + if (typeof number === 'object') { + return this._initArray(number, base, endian); + } + + if (base === 'hex') { + base = 16; + } + assert(base === (base | 0) && base >= 2 && base <= 36); + + number = number.toString().replace(/\s+/g, ''); + var start = 0; + if (number[0] === '-') { + start++; + } + + if (base === 16) { + this._parseHex(number, start); + } else { + this._parseBase(number, base, start); + } + + if (number[0] === '-') { + this.negative = 1; + } + + this.strip(); + + if (endian !== 'le') return; + + this._initArray(this.toArray(), base, endian); + }; + + BN.prototype._initNumber = function _initNumber (number, base, endian) { + if (number < 0) { + this.negative = 1; + number = -number; + } + if (number < 0x4000000) { + this.words = [ number & 0x3ffffff ]; + this.length = 1; + } else if (number < 0x10000000000000) { + this.words = [ + number & 0x3ffffff, + (number / 0x4000000) & 0x3ffffff + ]; + this.length = 2; + } else { + assert(number < 0x20000000000000); // 2 ^ 53 (unsafe) + this.words = [ + number & 0x3ffffff, + (number / 0x4000000) & 0x3ffffff, + 1 + ]; + this.length = 3; + } + + if (endian !== 'le') return; + + // Reverse the bytes + this._initArray(this.toArray(), base, endian); + }; + + BN.prototype._initArray = function _initArray (number, base, endian) { + // Perhaps a Uint8Array + assert(typeof number.length === 'number'); + if (number.length <= 0) { + this.words = [ 0 ]; + this.length = 1; + return this; + } + + this.length = Math.ceil(number.length / 3); + this.words = new Array(this.length); + for (var i = 0; i < this.length; i++) { + this.words[i] = 0; + } + + var j, w; + var off = 0; + if (endian === 'be') { + for (i = number.length - 1, j = 0; i >= 0; i -= 3) { + w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16); + this.words[j] |= (w << off) & 0x3ffffff; + this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; + off += 24; + if (off >= 26) { + off -= 26; + j++; + } + } + } else if (endian === 'le') { + for (i = 0, j = 0; i < number.length; i += 3) { + w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16); + this.words[j] |= (w << off) & 0x3ffffff; + this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; + off += 24; + if (off >= 26) { + off -= 26; + j++; + } + } + } + return this.strip(); + }; + + function parseHex (str, start, end) { + var r = 0; + var len = Math.min(str.length, end); + for (var i = start; i < len; i++) { + var c = str.charCodeAt(i) - 48; + + r <<= 4; + + // 'a' - 'f' + if (c >= 49 && c <= 54) { + r |= c - 49 + 0xa; + + // 'A' - 'F' + } else if (c >= 17 && c <= 22) { + r |= c - 17 + 0xa; + + // '0' - '9' + } else { + r |= c & 0xf; + } + } + return r; + } + + BN.prototype._parseHex = function _parseHex (number, start) { + // Create possibly bigger array to ensure that it fits the number + this.length = Math.ceil((number.length - start) / 6); + this.words = new Array(this.length); + for (var i = 0; i < this.length; i++) { + this.words[i] = 0; + } + + var j, w; + // Scan 24-bit chunks and add them to the number + var off = 0; + for (i = number.length - 6, j = 0; i >= start; i -= 6) { + w = parseHex(number, i, i + 6); + this.words[j] |= (w << off) & 0x3ffffff; + // NOTE: `0x3fffff` is intentional here, 26bits max shift + 24bit hex limb + this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; + off += 24; + if (off >= 26) { + off -= 26; + j++; + } + } + if (i + 6 !== start) { + w = parseHex(number, start, i + 6); + this.words[j] |= (w << off) & 0x3ffffff; + this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; + } + this.strip(); + }; + + function parseBase (str, start, end, mul) { + var r = 0; + var len = Math.min(str.length, end); + for (var i = start; i < len; i++) { + var c = str.charCodeAt(i) - 48; + + r *= mul; + + // 'a' + if (c >= 49) { + r += c - 49 + 0xa; + + // 'A' + } else if (c >= 17) { + r += c - 17 + 0xa; + + // '0' - '9' + } else { + r += c; + } + } + return r; + } + + BN.prototype._parseBase = function _parseBase (number, base, start) { + // Initialize as zero + this.words = [ 0 ]; + this.length = 1; + + // Find length of limb in base + for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) { + limbLen++; + } + limbLen--; + limbPow = (limbPow / base) | 0; + + var total = number.length - start; + var mod = total % limbLen; + var end = Math.min(total, total - mod) + start; + + var word = 0; + for (var i = start; i < end; i += limbLen) { + word = parseBase(number, i, i + limbLen, base); + + this.imuln(limbPow); + if (this.words[0] + word < 0x4000000) { + this.words[0] += word; + } else { + this._iaddn(word); + } + } + + if (mod !== 0) { + var pow = 1; + word = parseBase(number, i, number.length, base); + + for (i = 0; i < mod; i++) { + pow *= base; + } + + this.imuln(pow); + if (this.words[0] + word < 0x4000000) { + this.words[0] += word; + } else { + this._iaddn(word); + } + } + }; + + BN.prototype.copy = function copy (dest) { + dest.words = new Array(this.length); + for (var i = 0; i < this.length; i++) { + dest.words[i] = this.words[i]; + } + dest.length = this.length; + dest.negative = this.negative; + dest.red = this.red; + }; + + BN.prototype.clone = function clone () { + var r = new BN(null); + this.copy(r); + return r; + }; + + BN.prototype._expand = function _expand (size) { + while (this.length < size) { + this.words[this.length++] = 0; + } + return this; + }; + + // Remove leading `0` from `this` + BN.prototype.strip = function strip () { + while (this.length > 1 && this.words[this.length - 1] === 0) { + this.length--; + } + return this._normSign(); + }; + + BN.prototype._normSign = function _normSign () { + // -0 = 0 + if (this.length === 1 && this.words[0] === 0) { + this.negative = 0; + } + return this; + }; + + BN.prototype.inspect = function inspect () { + return (this.red ? ''; + }; + + /* + + var zeros = []; + var groupSizes = []; + var groupBases = []; + + var s = ''; + var i = -1; + while (++i < BN.wordSize) { + zeros[i] = s; + s += '0'; + } + groupSizes[0] = 0; + groupSizes[1] = 0; + groupBases[0] = 0; + groupBases[1] = 0; + var base = 2 - 1; + while (++base < 36 + 1) { + var groupSize = 0; + var groupBase = 1; + while (groupBase < (1 << BN.wordSize) / base) { + groupBase *= base; + groupSize += 1; + } + groupSizes[base] = groupSize; + groupBases[base] = groupBase; + } + + */ + + var zeros = [ + '', + '0', + '00', + '000', + '0000', + '00000', + '000000', + '0000000', + '00000000', + '000000000', + '0000000000', + '00000000000', + '000000000000', + '0000000000000', + '00000000000000', + '000000000000000', + '0000000000000000', + '00000000000000000', + '000000000000000000', + '0000000000000000000', + '00000000000000000000', + '000000000000000000000', + '0000000000000000000000', + '00000000000000000000000', + '000000000000000000000000', + '0000000000000000000000000' + ]; + + var groupSizes = [ + 0, 0, + 25, 16, 12, 11, 10, 9, 8, + 8, 7, 7, 7, 7, 6, 6, + 6, 6, 6, 6, 6, 5, 5, + 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5 + ]; + + var groupBases = [ + 0, 0, + 33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216, + 43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625, + 16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632, + 6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149, + 24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176 + ]; + + BN.prototype.toString = function toString (base, padding) { + base = base || 10; + padding = padding | 0 || 1; + + var out; + if (base === 16 || base === 'hex') { + out = ''; + var off = 0; + var carry = 0; + for (var i = 0; i < this.length; i++) { + var w = this.words[i]; + var word = (((w << off) | carry) & 0xffffff).toString(16); + carry = (w >>> (24 - off)) & 0xffffff; + if (carry !== 0 || i !== this.length - 1) { + out = zeros[6 - word.length] + word + out; + } else { + out = word + out; + } + off += 2; + if (off >= 26) { + off -= 26; + i--; + } + } + if (carry !== 0) { + out = carry.toString(16) + out; + } + while (out.length % padding !== 0) { + out = '0' + out; + } + if (this.negative !== 0) { + out = '-' + out; + } + return out; + } + + if (base === (base | 0) && base >= 2 && base <= 36) { + // var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base)); + var groupSize = groupSizes[base]; + // var groupBase = Math.pow(base, groupSize); + var groupBase = groupBases[base]; + out = ''; + var c = this.clone(); + c.negative = 0; + while (!c.isZero()) { + var r = c.modn(groupBase).toString(base); + c = c.idivn(groupBase); + + if (!c.isZero()) { + out = zeros[groupSize - r.length] + r + out; + } else { + out = r + out; + } + } + if (this.isZero()) { + out = '0' + out; + } + while (out.length % padding !== 0) { + out = '0' + out; + } + if (this.negative !== 0) { + out = '-' + out; + } + return out; + } + + assert(false, 'Base should be between 2 and 36'); + }; + + BN.prototype.toNumber = function toNumber () { + var ret = this.words[0]; + if (this.length === 2) { + ret += this.words[1] * 0x4000000; + } else if (this.length === 3 && this.words[2] === 0x01) { + // NOTE: at this stage it is known that the top bit is set + ret += 0x10000000000000 + (this.words[1] * 0x4000000); + } else if (this.length > 2) { + assert(false, 'Number can only safely store up to 53 bits'); + } + return (this.negative !== 0) ? -ret : ret; + }; + + BN.prototype.toJSON = function toJSON () { + return this.toString(16); + }; + + BN.prototype.toBuffer = function toBuffer (endian, length) { + assert(typeof Buffer !== 'undefined'); + return this.toArrayLike(Buffer, endian, length); + }; + + BN.prototype.toArray = function toArray (endian, length) { + return this.toArrayLike(Array, endian, length); + }; + + BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) { + var byteLength = this.byteLength(); + var reqLength = length || Math.max(1, byteLength); + assert(byteLength <= reqLength, 'byte array longer than desired length'); + assert(reqLength > 0, 'Requested array length <= 0'); + + this.strip(); + var littleEndian = endian === 'le'; + var res = new ArrayType(reqLength); + + var b, i; + var q = this.clone(); + if (!littleEndian) { + // Assume big-endian + for (i = 0; i < reqLength - byteLength; i++) { + res[i] = 0; + } + + for (i = 0; !q.isZero(); i++) { + b = q.andln(0xff); + q.iushrn(8); + + res[reqLength - i - 1] = b; + } + } else { + for (i = 0; !q.isZero(); i++) { + b = q.andln(0xff); + q.iushrn(8); + + res[i] = b; + } + + for (; i < reqLength; i++) { + res[i] = 0; + } + } + + return res; + }; + + if (Math.clz32) { + BN.prototype._countBits = function _countBits (w) { + return 32 - Math.clz32(w); + }; + } else { + BN.prototype._countBits = function _countBits (w) { + var t = w; + var r = 0; + if (t >= 0x1000) { + r += 13; + t >>>= 13; + } + if (t >= 0x40) { + r += 7; + t >>>= 7; + } + if (t >= 0x8) { + r += 4; + t >>>= 4; + } + if (t >= 0x02) { + r += 2; + t >>>= 2; + } + return r + t; + }; + } + + BN.prototype._zeroBits = function _zeroBits (w) { + // Short-cut + if (w === 0) return 26; + + var t = w; + var r = 0; + if ((t & 0x1fff) === 0) { + r += 13; + t >>>= 13; + } + if ((t & 0x7f) === 0) { + r += 7; + t >>>= 7; + } + if ((t & 0xf) === 0) { + r += 4; + t >>>= 4; + } + if ((t & 0x3) === 0) { + r += 2; + t >>>= 2; + } + if ((t & 0x1) === 0) { + r++; + } + return r; + }; + + // Return number of used bits in a BN + BN.prototype.bitLength = function bitLength () { + var w = this.words[this.length - 1]; + var hi = this._countBits(w); + return (this.length - 1) * 26 + hi; + }; + + function toBitArray (num) { + var w = new Array(num.bitLength()); + + for (var bit = 0; bit < w.length; bit++) { + var off = (bit / 26) | 0; + var wbit = bit % 26; + + w[bit] = (num.words[off] & (1 << wbit)) >>> wbit; + } + + return w; + } + + // Number of trailing zero bits + BN.prototype.zeroBits = function zeroBits () { + if (this.isZero()) return 0; + + var r = 0; + for (var i = 0; i < this.length; i++) { + var b = this._zeroBits(this.words[i]); + r += b; + if (b !== 26) break; + } + return r; + }; + + BN.prototype.byteLength = function byteLength () { + return Math.ceil(this.bitLength() / 8); + }; + + BN.prototype.toTwos = function toTwos (width) { + if (this.negative !== 0) { + return this.abs().inotn(width).iaddn(1); + } + return this.clone(); + }; + + BN.prototype.fromTwos = function fromTwos (width) { + if (this.testn(width - 1)) { + return this.notn(width).iaddn(1).ineg(); + } + return this.clone(); + }; + + BN.prototype.isNeg = function isNeg () { + return this.negative !== 0; + }; + + // Return negative clone of `this` + BN.prototype.neg = function neg () { + return this.clone().ineg(); + }; + + BN.prototype.ineg = function ineg () { + if (!this.isZero()) { + this.negative ^= 1; + } + + return this; + }; + + // Or `num` with `this` in-place + BN.prototype.iuor = function iuor (num) { + while (this.length < num.length) { + this.words[this.length++] = 0; + } + + for (var i = 0; i < num.length; i++) { + this.words[i] = this.words[i] | num.words[i]; + } + + return this.strip(); + }; + + BN.prototype.ior = function ior (num) { + assert((this.negative | num.negative) === 0); + return this.iuor(num); + }; + + // Or `num` with `this` + BN.prototype.or = function or (num) { + if (this.length > num.length) return this.clone().ior(num); + return num.clone().ior(this); + }; + + BN.prototype.uor = function uor (num) { + if (this.length > num.length) return this.clone().iuor(num); + return num.clone().iuor(this); + }; + + // And `num` with `this` in-place + BN.prototype.iuand = function iuand (num) { + // b = min-length(num, this) + var b; + if (this.length > num.length) { + b = num; + } else { + b = this; + } + + for (var i = 0; i < b.length; i++) { + this.words[i] = this.words[i] & num.words[i]; + } + + this.length = b.length; + + return this.strip(); + }; + + BN.prototype.iand = function iand (num) { + assert((this.negative | num.negative) === 0); + return this.iuand(num); + }; + + // And `num` with `this` + BN.prototype.and = function and (num) { + if (this.length > num.length) return this.clone().iand(num); + return num.clone().iand(this); + }; + + BN.prototype.uand = function uand (num) { + if (this.length > num.length) return this.clone().iuand(num); + return num.clone().iuand(this); + }; + + // Xor `num` with `this` in-place + BN.prototype.iuxor = function iuxor (num) { + // a.length > b.length + var a; + var b; + if (this.length > num.length) { + a = this; + b = num; + } else { + a = num; + b = this; + } + + for (var i = 0; i < b.length; i++) { + this.words[i] = a.words[i] ^ b.words[i]; + } + + if (this !== a) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } + } + + this.length = a.length; + + return this.strip(); + }; + + BN.prototype.ixor = function ixor (num) { + assert((this.negative | num.negative) === 0); + return this.iuxor(num); + }; + + // Xor `num` with `this` + BN.prototype.xor = function xor (num) { + if (this.length > num.length) return this.clone().ixor(num); + return num.clone().ixor(this); + }; + + BN.prototype.uxor = function uxor (num) { + if (this.length > num.length) return this.clone().iuxor(num); + return num.clone().iuxor(this); + }; + + // Not ``this`` with ``width`` bitwidth + BN.prototype.inotn = function inotn (width) { + assert(typeof width === 'number' && width >= 0); + + var bytesNeeded = Math.ceil(width / 26) | 0; + var bitsLeft = width % 26; + + // Extend the buffer with leading zeroes + this._expand(bytesNeeded); + + if (bitsLeft > 0) { + bytesNeeded--; + } + + // Handle complete words + for (var i = 0; i < bytesNeeded; i++) { + this.words[i] = ~this.words[i] & 0x3ffffff; + } + + // Handle the residue + if (bitsLeft > 0) { + this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft)); + } + + // And remove leading zeroes + return this.strip(); + }; + + BN.prototype.notn = function notn (width) { + return this.clone().inotn(width); + }; + + // Set `bit` of `this` + BN.prototype.setn = function setn (bit, val) { + assert(typeof bit === 'number' && bit >= 0); + + var off = (bit / 26) | 0; + var wbit = bit % 26; + + this._expand(off + 1); + + if (val) { + this.words[off] = this.words[off] | (1 << wbit); + } else { + this.words[off] = this.words[off] & ~(1 << wbit); + } + + return this.strip(); + }; + + // Add `num` to `this` in-place + BN.prototype.iadd = function iadd (num) { + var r; + + // negative + positive + if (this.negative !== 0 && num.negative === 0) { + this.negative = 0; + r = this.isub(num); + this.negative ^= 1; + return this._normSign(); + + // positive + negative + } else if (this.negative === 0 && num.negative !== 0) { + num.negative = 0; + r = this.isub(num); + num.negative = 1; + return r._normSign(); + } + + // a.length > b.length + var a, b; + if (this.length > num.length) { + a = this; + b = num; + } else { + a = num; + b = this; + } + + var carry = 0; + for (var i = 0; i < b.length; i++) { + r = (a.words[i] | 0) + (b.words[i] | 0) + carry; + this.words[i] = r & 0x3ffffff; + carry = r >>> 26; + } + for (; carry !== 0 && i < a.length; i++) { + r = (a.words[i] | 0) + carry; + this.words[i] = r & 0x3ffffff; + carry = r >>> 26; + } + + this.length = a.length; + if (carry !== 0) { + this.words[this.length] = carry; + this.length++; + // Copy the rest of the words + } else if (a !== this) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } + } + + return this; + }; + + // Add `num` to `this` + BN.prototype.add = function add (num) { + var res; + if (num.negative !== 0 && this.negative === 0) { + num.negative = 0; + res = this.sub(num); + num.negative ^= 1; + return res; + } else if (num.negative === 0 && this.negative !== 0) { + this.negative = 0; + res = num.sub(this); + this.negative = 1; + return res; + } + + if (this.length > num.length) return this.clone().iadd(num); + + return num.clone().iadd(this); + }; + + // Subtract `num` from `this` in-place + BN.prototype.isub = function isub (num) { + // this - (-num) = this + num + if (num.negative !== 0) { + num.negative = 0; + var r = this.iadd(num); + num.negative = 1; + return r._normSign(); + + // -this - num = -(this + num) + } else if (this.negative !== 0) { + this.negative = 0; + this.iadd(num); + this.negative = 1; + return this._normSign(); + } + + // At this point both numbers are positive + var cmp = this.cmp(num); + + // Optimization - zeroify + if (cmp === 0) { + this.negative = 0; + this.length = 1; + this.words[0] = 0; + return this; + } + + // a > b + var a, b; + if (cmp > 0) { + a = this; + b = num; + } else { + a = num; + b = this; + } + + var carry = 0; + for (var i = 0; i < b.length; i++) { + r = (a.words[i] | 0) - (b.words[i] | 0) + carry; + carry = r >> 26; + this.words[i] = r & 0x3ffffff; + } + for (; carry !== 0 && i < a.length; i++) { + r = (a.words[i] | 0) + carry; + carry = r >> 26; + this.words[i] = r & 0x3ffffff; + } + + // Copy rest of the words + if (carry === 0 && i < a.length && a !== this) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } + } + + this.length = Math.max(this.length, i); + + if (a !== this) { + this.negative = 1; + } + + return this.strip(); + }; + + // Subtract `num` from `this` + BN.prototype.sub = function sub (num) { + return this.clone().isub(num); + }; + + function smallMulTo (self, num, out) { + out.negative = num.negative ^ self.negative; + var len = (self.length + num.length) | 0; + out.length = len; + len = (len - 1) | 0; + + // Peel one iteration (compiler can't do it, because of code complexity) + var a = self.words[0] | 0; + var b = num.words[0] | 0; + var r = a * b; + + var lo = r & 0x3ffffff; + var carry = (r / 0x4000000) | 0; + out.words[0] = lo; + + for (var k = 1; k < len; k++) { + // Sum all words with the same `i + j = k` and accumulate `ncarry`, + // note that ncarry could be >= 0x3ffffff + var ncarry = carry >>> 26; + var rword = carry & 0x3ffffff; + var maxJ = Math.min(k, num.length - 1); + for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { + var i = (k - j) | 0; + a = self.words[i] | 0; + b = num.words[j] | 0; + r = a * b + rword; + ncarry += (r / 0x4000000) | 0; + rword = r & 0x3ffffff; + } + out.words[k] = rword | 0; + carry = ncarry | 0; + } + if (carry !== 0) { + out.words[k] = carry | 0; + } else { + out.length--; + } + + return out.strip(); + } + + // TODO(indutny): it may be reasonable to omit it for users who don't need + // to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit + // multiplication (like elliptic secp256k1). + var comb10MulTo = function comb10MulTo (self, num, out) { + var a = self.words; + var b = num.words; + var o = out.words; + var c = 0; + var lo; + var mid; + var hi; + var a0 = a[0] | 0; + var al0 = a0 & 0x1fff; + var ah0 = a0 >>> 13; + var a1 = a[1] | 0; + var al1 = a1 & 0x1fff; + var ah1 = a1 >>> 13; + var a2 = a[2] | 0; + var al2 = a2 & 0x1fff; + var ah2 = a2 >>> 13; + var a3 = a[3] | 0; + var al3 = a3 & 0x1fff; + var ah3 = a3 >>> 13; + var a4 = a[4] | 0; + var al4 = a4 & 0x1fff; + var ah4 = a4 >>> 13; + var a5 = a[5] | 0; + var al5 = a5 & 0x1fff; + var ah5 = a5 >>> 13; + var a6 = a[6] | 0; + var al6 = a6 & 0x1fff; + var ah6 = a6 >>> 13; + var a7 = a[7] | 0; + var al7 = a7 & 0x1fff; + var ah7 = a7 >>> 13; + var a8 = a[8] | 0; + var al8 = a8 & 0x1fff; + var ah8 = a8 >>> 13; + var a9 = a[9] | 0; + var al9 = a9 & 0x1fff; + var ah9 = a9 >>> 13; + var b0 = b[0] | 0; + var bl0 = b0 & 0x1fff; + var bh0 = b0 >>> 13; + var b1 = b[1] | 0; + var bl1 = b1 & 0x1fff; + var bh1 = b1 >>> 13; + var b2 = b[2] | 0; + var bl2 = b2 & 0x1fff; + var bh2 = b2 >>> 13; + var b3 = b[3] | 0; + var bl3 = b3 & 0x1fff; + var bh3 = b3 >>> 13; + var b4 = b[4] | 0; + var bl4 = b4 & 0x1fff; + var bh4 = b4 >>> 13; + var b5 = b[5] | 0; + var bl5 = b5 & 0x1fff; + var bh5 = b5 >>> 13; + var b6 = b[6] | 0; + var bl6 = b6 & 0x1fff; + var bh6 = b6 >>> 13; + var b7 = b[7] | 0; + var bl7 = b7 & 0x1fff; + var bh7 = b7 >>> 13; + var b8 = b[8] | 0; + var bl8 = b8 & 0x1fff; + var bh8 = b8 >>> 13; + var b9 = b[9] | 0; + var bl9 = b9 & 0x1fff; + var bh9 = b9 >>> 13; + + out.negative = self.negative ^ num.negative; + out.length = 19; + /* k = 0 */ + lo = Math.imul(al0, bl0); + mid = Math.imul(al0, bh0); + mid = (mid + Math.imul(ah0, bl0)) | 0; + hi = Math.imul(ah0, bh0); + var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0; + w0 &= 0x3ffffff; + /* k = 1 */ + lo = Math.imul(al1, bl0); + mid = Math.imul(al1, bh0); + mid = (mid + Math.imul(ah1, bl0)) | 0; + hi = Math.imul(ah1, bh0); + lo = (lo + Math.imul(al0, bl1)) | 0; + mid = (mid + Math.imul(al0, bh1)) | 0; + mid = (mid + Math.imul(ah0, bl1)) | 0; + hi = (hi + Math.imul(ah0, bh1)) | 0; + var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0; + w1 &= 0x3ffffff; + /* k = 2 */ + lo = Math.imul(al2, bl0); + mid = Math.imul(al2, bh0); + mid = (mid + Math.imul(ah2, bl0)) | 0; + hi = Math.imul(ah2, bh0); + lo = (lo + Math.imul(al1, bl1)) | 0; + mid = (mid + Math.imul(al1, bh1)) | 0; + mid = (mid + Math.imul(ah1, bl1)) | 0; + hi = (hi + Math.imul(ah1, bh1)) | 0; + lo = (lo + Math.imul(al0, bl2)) | 0; + mid = (mid + Math.imul(al0, bh2)) | 0; + mid = (mid + Math.imul(ah0, bl2)) | 0; + hi = (hi + Math.imul(ah0, bh2)) | 0; + var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0; + w2 &= 0x3ffffff; + /* k = 3 */ + lo = Math.imul(al3, bl0); + mid = Math.imul(al3, bh0); + mid = (mid + Math.imul(ah3, bl0)) | 0; + hi = Math.imul(ah3, bh0); + lo = (lo + Math.imul(al2, bl1)) | 0; + mid = (mid + Math.imul(al2, bh1)) | 0; + mid = (mid + Math.imul(ah2, bl1)) | 0; + hi = (hi + Math.imul(ah2, bh1)) | 0; + lo = (lo + Math.imul(al1, bl2)) | 0; + mid = (mid + Math.imul(al1, bh2)) | 0; + mid = (mid + Math.imul(ah1, bl2)) | 0; + hi = (hi + Math.imul(ah1, bh2)) | 0; + lo = (lo + Math.imul(al0, bl3)) | 0; + mid = (mid + Math.imul(al0, bh3)) | 0; + mid = (mid + Math.imul(ah0, bl3)) | 0; + hi = (hi + Math.imul(ah0, bh3)) | 0; + var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0; + w3 &= 0x3ffffff; + /* k = 4 */ + lo = Math.imul(al4, bl0); + mid = Math.imul(al4, bh0); + mid = (mid + Math.imul(ah4, bl0)) | 0; + hi = Math.imul(ah4, bh0); + lo = (lo + Math.imul(al3, bl1)) | 0; + mid = (mid + Math.imul(al3, bh1)) | 0; + mid = (mid + Math.imul(ah3, bl1)) | 0; + hi = (hi + Math.imul(ah3, bh1)) | 0; + lo = (lo + Math.imul(al2, bl2)) | 0; + mid = (mid + Math.imul(al2, bh2)) | 0; + mid = (mid + Math.imul(ah2, bl2)) | 0; + hi = (hi + Math.imul(ah2, bh2)) | 0; + lo = (lo + Math.imul(al1, bl3)) | 0; + mid = (mid + Math.imul(al1, bh3)) | 0; + mid = (mid + Math.imul(ah1, bl3)) | 0; + hi = (hi + Math.imul(ah1, bh3)) | 0; + lo = (lo + Math.imul(al0, bl4)) | 0; + mid = (mid + Math.imul(al0, bh4)) | 0; + mid = (mid + Math.imul(ah0, bl4)) | 0; + hi = (hi + Math.imul(ah0, bh4)) | 0; + var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0; + w4 &= 0x3ffffff; + /* k = 5 */ + lo = Math.imul(al5, bl0); + mid = Math.imul(al5, bh0); + mid = (mid + Math.imul(ah5, bl0)) | 0; + hi = Math.imul(ah5, bh0); + lo = (lo + Math.imul(al4, bl1)) | 0; + mid = (mid + Math.imul(al4, bh1)) | 0; + mid = (mid + Math.imul(ah4, bl1)) | 0; + hi = (hi + Math.imul(ah4, bh1)) | 0; + lo = (lo + Math.imul(al3, bl2)) | 0; + mid = (mid + Math.imul(al3, bh2)) | 0; + mid = (mid + Math.imul(ah3, bl2)) | 0; + hi = (hi + Math.imul(ah3, bh2)) | 0; + lo = (lo + Math.imul(al2, bl3)) | 0; + mid = (mid + Math.imul(al2, bh3)) | 0; + mid = (mid + Math.imul(ah2, bl3)) | 0; + hi = (hi + Math.imul(ah2, bh3)) | 0; + lo = (lo + Math.imul(al1, bl4)) | 0; + mid = (mid + Math.imul(al1, bh4)) | 0; + mid = (mid + Math.imul(ah1, bl4)) | 0; + hi = (hi + Math.imul(ah1, bh4)) | 0; + lo = (lo + Math.imul(al0, bl5)) | 0; + mid = (mid + Math.imul(al0, bh5)) | 0; + mid = (mid + Math.imul(ah0, bl5)) | 0; + hi = (hi + Math.imul(ah0, bh5)) | 0; + var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0; + w5 &= 0x3ffffff; + /* k = 6 */ + lo = Math.imul(al6, bl0); + mid = Math.imul(al6, bh0); + mid = (mid + Math.imul(ah6, bl0)) | 0; + hi = Math.imul(ah6, bh0); + lo = (lo + Math.imul(al5, bl1)) | 0; + mid = (mid + Math.imul(al5, bh1)) | 0; + mid = (mid + Math.imul(ah5, bl1)) | 0; + hi = (hi + Math.imul(ah5, bh1)) | 0; + lo = (lo + Math.imul(al4, bl2)) | 0; + mid = (mid + Math.imul(al4, bh2)) | 0; + mid = (mid + Math.imul(ah4, bl2)) | 0; + hi = (hi + Math.imul(ah4, bh2)) | 0; + lo = (lo + Math.imul(al3, bl3)) | 0; + mid = (mid + Math.imul(al3, bh3)) | 0; + mid = (mid + Math.imul(ah3, bl3)) | 0; + hi = (hi + Math.imul(ah3, bh3)) | 0; + lo = (lo + Math.imul(al2, bl4)) | 0; + mid = (mid + Math.imul(al2, bh4)) | 0; + mid = (mid + Math.imul(ah2, bl4)) | 0; + hi = (hi + Math.imul(ah2, bh4)) | 0; + lo = (lo + Math.imul(al1, bl5)) | 0; + mid = (mid + Math.imul(al1, bh5)) | 0; + mid = (mid + Math.imul(ah1, bl5)) | 0; + hi = (hi + Math.imul(ah1, bh5)) | 0; + lo = (lo + Math.imul(al0, bl6)) | 0; + mid = (mid + Math.imul(al0, bh6)) | 0; + mid = (mid + Math.imul(ah0, bl6)) | 0; + hi = (hi + Math.imul(ah0, bh6)) | 0; + var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0; + w6 &= 0x3ffffff; + /* k = 7 */ + lo = Math.imul(al7, bl0); + mid = Math.imul(al7, bh0); + mid = (mid + Math.imul(ah7, bl0)) | 0; + hi = Math.imul(ah7, bh0); + lo = (lo + Math.imul(al6, bl1)) | 0; + mid = (mid + Math.imul(al6, bh1)) | 0; + mid = (mid + Math.imul(ah6, bl1)) | 0; + hi = (hi + Math.imul(ah6, bh1)) | 0; + lo = (lo + Math.imul(al5, bl2)) | 0; + mid = (mid + Math.imul(al5, bh2)) | 0; + mid = (mid + Math.imul(ah5, bl2)) | 0; + hi = (hi + Math.imul(ah5, bh2)) | 0; + lo = (lo + Math.imul(al4, bl3)) | 0; + mid = (mid + Math.imul(al4, bh3)) | 0; + mid = (mid + Math.imul(ah4, bl3)) | 0; + hi = (hi + Math.imul(ah4, bh3)) | 0; + lo = (lo + Math.imul(al3, bl4)) | 0; + mid = (mid + Math.imul(al3, bh4)) | 0; + mid = (mid + Math.imul(ah3, bl4)) | 0; + hi = (hi + Math.imul(ah3, bh4)) | 0; + lo = (lo + Math.imul(al2, bl5)) | 0; + mid = (mid + Math.imul(al2, bh5)) | 0; + mid = (mid + Math.imul(ah2, bl5)) | 0; + hi = (hi + Math.imul(ah2, bh5)) | 0; + lo = (lo + Math.imul(al1, bl6)) | 0; + mid = (mid + Math.imul(al1, bh6)) | 0; + mid = (mid + Math.imul(ah1, bl6)) | 0; + hi = (hi + Math.imul(ah1, bh6)) | 0; + lo = (lo + Math.imul(al0, bl7)) | 0; + mid = (mid + Math.imul(al0, bh7)) | 0; + mid = (mid + Math.imul(ah0, bl7)) | 0; + hi = (hi + Math.imul(ah0, bh7)) | 0; + var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0; + w7 &= 0x3ffffff; + /* k = 8 */ + lo = Math.imul(al8, bl0); + mid = Math.imul(al8, bh0); + mid = (mid + Math.imul(ah8, bl0)) | 0; + hi = Math.imul(ah8, bh0); + lo = (lo + Math.imul(al7, bl1)) | 0; + mid = (mid + Math.imul(al7, bh1)) | 0; + mid = (mid + Math.imul(ah7, bl1)) | 0; + hi = (hi + Math.imul(ah7, bh1)) | 0; + lo = (lo + Math.imul(al6, bl2)) | 0; + mid = (mid + Math.imul(al6, bh2)) | 0; + mid = (mid + Math.imul(ah6, bl2)) | 0; + hi = (hi + Math.imul(ah6, bh2)) | 0; + lo = (lo + Math.imul(al5, bl3)) | 0; + mid = (mid + Math.imul(al5, bh3)) | 0; + mid = (mid + Math.imul(ah5, bl3)) | 0; + hi = (hi + Math.imul(ah5, bh3)) | 0; + lo = (lo + Math.imul(al4, bl4)) | 0; + mid = (mid + Math.imul(al4, bh4)) | 0; + mid = (mid + Math.imul(ah4, bl4)) | 0; + hi = (hi + Math.imul(ah4, bh4)) | 0; + lo = (lo + Math.imul(al3, bl5)) | 0; + mid = (mid + Math.imul(al3, bh5)) | 0; + mid = (mid + Math.imul(ah3, bl5)) | 0; + hi = (hi + Math.imul(ah3, bh5)) | 0; + lo = (lo + Math.imul(al2, bl6)) | 0; + mid = (mid + Math.imul(al2, bh6)) | 0; + mid = (mid + Math.imul(ah2, bl6)) | 0; + hi = (hi + Math.imul(ah2, bh6)) | 0; + lo = (lo + Math.imul(al1, bl7)) | 0; + mid = (mid + Math.imul(al1, bh7)) | 0; + mid = (mid + Math.imul(ah1, bl7)) | 0; + hi = (hi + Math.imul(ah1, bh7)) | 0; + lo = (lo + Math.imul(al0, bl8)) | 0; + mid = (mid + Math.imul(al0, bh8)) | 0; + mid = (mid + Math.imul(ah0, bl8)) | 0; + hi = (hi + Math.imul(ah0, bh8)) | 0; + var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0; + w8 &= 0x3ffffff; + /* k = 9 */ + lo = Math.imul(al9, bl0); + mid = Math.imul(al9, bh0); + mid = (mid + Math.imul(ah9, bl0)) | 0; + hi = Math.imul(ah9, bh0); + lo = (lo + Math.imul(al8, bl1)) | 0; + mid = (mid + Math.imul(al8, bh1)) | 0; + mid = (mid + Math.imul(ah8, bl1)) | 0; + hi = (hi + Math.imul(ah8, bh1)) | 0; + lo = (lo + Math.imul(al7, bl2)) | 0; + mid = (mid + Math.imul(al7, bh2)) | 0; + mid = (mid + Math.imul(ah7, bl2)) | 0; + hi = (hi + Math.imul(ah7, bh2)) | 0; + lo = (lo + Math.imul(al6, bl3)) | 0; + mid = (mid + Math.imul(al6, bh3)) | 0; + mid = (mid + Math.imul(ah6, bl3)) | 0; + hi = (hi + Math.imul(ah6, bh3)) | 0; + lo = (lo + Math.imul(al5, bl4)) | 0; + mid = (mid + Math.imul(al5, bh4)) | 0; + mid = (mid + Math.imul(ah5, bl4)) | 0; + hi = (hi + Math.imul(ah5, bh4)) | 0; + lo = (lo + Math.imul(al4, bl5)) | 0; + mid = (mid + Math.imul(al4, bh5)) | 0; + mid = (mid + Math.imul(ah4, bl5)) | 0; + hi = (hi + Math.imul(ah4, bh5)) | 0; + lo = (lo + Math.imul(al3, bl6)) | 0; + mid = (mid + Math.imul(al3, bh6)) | 0; + mid = (mid + Math.imul(ah3, bl6)) | 0; + hi = (hi + Math.imul(ah3, bh6)) | 0; + lo = (lo + Math.imul(al2, bl7)) | 0; + mid = (mid + Math.imul(al2, bh7)) | 0; + mid = (mid + Math.imul(ah2, bl7)) | 0; + hi = (hi + Math.imul(ah2, bh7)) | 0; + lo = (lo + Math.imul(al1, bl8)) | 0; + mid = (mid + Math.imul(al1, bh8)) | 0; + mid = (mid + Math.imul(ah1, bl8)) | 0; + hi = (hi + Math.imul(ah1, bh8)) | 0; + lo = (lo + Math.imul(al0, bl9)) | 0; + mid = (mid + Math.imul(al0, bh9)) | 0; + mid = (mid + Math.imul(ah0, bl9)) | 0; + hi = (hi + Math.imul(ah0, bh9)) | 0; + var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0; + w9 &= 0x3ffffff; + /* k = 10 */ + lo = Math.imul(al9, bl1); + mid = Math.imul(al9, bh1); + mid = (mid + Math.imul(ah9, bl1)) | 0; + hi = Math.imul(ah9, bh1); + lo = (lo + Math.imul(al8, bl2)) | 0; + mid = (mid + Math.imul(al8, bh2)) | 0; + mid = (mid + Math.imul(ah8, bl2)) | 0; + hi = (hi + Math.imul(ah8, bh2)) | 0; + lo = (lo + Math.imul(al7, bl3)) | 0; + mid = (mid + Math.imul(al7, bh3)) | 0; + mid = (mid + Math.imul(ah7, bl3)) | 0; + hi = (hi + Math.imul(ah7, bh3)) | 0; + lo = (lo + Math.imul(al6, bl4)) | 0; + mid = (mid + Math.imul(al6, bh4)) | 0; + mid = (mid + Math.imul(ah6, bl4)) | 0; + hi = (hi + Math.imul(ah6, bh4)) | 0; + lo = (lo + Math.imul(al5, bl5)) | 0; + mid = (mid + Math.imul(al5, bh5)) | 0; + mid = (mid + Math.imul(ah5, bl5)) | 0; + hi = (hi + Math.imul(ah5, bh5)) | 0; + lo = (lo + Math.imul(al4, bl6)) | 0; + mid = (mid + Math.imul(al4, bh6)) | 0; + mid = (mid + Math.imul(ah4, bl6)) | 0; + hi = (hi + Math.imul(ah4, bh6)) | 0; + lo = (lo + Math.imul(al3, bl7)) | 0; + mid = (mid + Math.imul(al3, bh7)) | 0; + mid = (mid + Math.imul(ah3, bl7)) | 0; + hi = (hi + Math.imul(ah3, bh7)) | 0; + lo = (lo + Math.imul(al2, bl8)) | 0; + mid = (mid + Math.imul(al2, bh8)) | 0; + mid = (mid + Math.imul(ah2, bl8)) | 0; + hi = (hi + Math.imul(ah2, bh8)) | 0; + lo = (lo + Math.imul(al1, bl9)) | 0; + mid = (mid + Math.imul(al1, bh9)) | 0; + mid = (mid + Math.imul(ah1, bl9)) | 0; + hi = (hi + Math.imul(ah1, bh9)) | 0; + var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0; + w10 &= 0x3ffffff; + /* k = 11 */ + lo = Math.imul(al9, bl2); + mid = Math.imul(al9, bh2); + mid = (mid + Math.imul(ah9, bl2)) | 0; + hi = Math.imul(ah9, bh2); + lo = (lo + Math.imul(al8, bl3)) | 0; + mid = (mid + Math.imul(al8, bh3)) | 0; + mid = (mid + Math.imul(ah8, bl3)) | 0; + hi = (hi + Math.imul(ah8, bh3)) | 0; + lo = (lo + Math.imul(al7, bl4)) | 0; + mid = (mid + Math.imul(al7, bh4)) | 0; + mid = (mid + Math.imul(ah7, bl4)) | 0; + hi = (hi + Math.imul(ah7, bh4)) | 0; + lo = (lo + Math.imul(al6, bl5)) | 0; + mid = (mid + Math.imul(al6, bh5)) | 0; + mid = (mid + Math.imul(ah6, bl5)) | 0; + hi = (hi + Math.imul(ah6, bh5)) | 0; + lo = (lo + Math.imul(al5, bl6)) | 0; + mid = (mid + Math.imul(al5, bh6)) | 0; + mid = (mid + Math.imul(ah5, bl6)) | 0; + hi = (hi + Math.imul(ah5, bh6)) | 0; + lo = (lo + Math.imul(al4, bl7)) | 0; + mid = (mid + Math.imul(al4, bh7)) | 0; + mid = (mid + Math.imul(ah4, bl7)) | 0; + hi = (hi + Math.imul(ah4, bh7)) | 0; + lo = (lo + Math.imul(al3, bl8)) | 0; + mid = (mid + Math.imul(al3, bh8)) | 0; + mid = (mid + Math.imul(ah3, bl8)) | 0; + hi = (hi + Math.imul(ah3, bh8)) | 0; + lo = (lo + Math.imul(al2, bl9)) | 0; + mid = (mid + Math.imul(al2, bh9)) | 0; + mid = (mid + Math.imul(ah2, bl9)) | 0; + hi = (hi + Math.imul(ah2, bh9)) | 0; + var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0; + w11 &= 0x3ffffff; + /* k = 12 */ + lo = Math.imul(al9, bl3); + mid = Math.imul(al9, bh3); + mid = (mid + Math.imul(ah9, bl3)) | 0; + hi = Math.imul(ah9, bh3); + lo = (lo + Math.imul(al8, bl4)) | 0; + mid = (mid + Math.imul(al8, bh4)) | 0; + mid = (mid + Math.imul(ah8, bl4)) | 0; + hi = (hi + Math.imul(ah8, bh4)) | 0; + lo = (lo + Math.imul(al7, bl5)) | 0; + mid = (mid + Math.imul(al7, bh5)) | 0; + mid = (mid + Math.imul(ah7, bl5)) | 0; + hi = (hi + Math.imul(ah7, bh5)) | 0; + lo = (lo + Math.imul(al6, bl6)) | 0; + mid = (mid + Math.imul(al6, bh6)) | 0; + mid = (mid + Math.imul(ah6, bl6)) | 0; + hi = (hi + Math.imul(ah6, bh6)) | 0; + lo = (lo + Math.imul(al5, bl7)) | 0; + mid = (mid + Math.imul(al5, bh7)) | 0; + mid = (mid + Math.imul(ah5, bl7)) | 0; + hi = (hi + Math.imul(ah5, bh7)) | 0; + lo = (lo + Math.imul(al4, bl8)) | 0; + mid = (mid + Math.imul(al4, bh8)) | 0; + mid = (mid + Math.imul(ah4, bl8)) | 0; + hi = (hi + Math.imul(ah4, bh8)) | 0; + lo = (lo + Math.imul(al3, bl9)) | 0; + mid = (mid + Math.imul(al3, bh9)) | 0; + mid = (mid + Math.imul(ah3, bl9)) | 0; + hi = (hi + Math.imul(ah3, bh9)) | 0; + var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0; + w12 &= 0x3ffffff; + /* k = 13 */ + lo = Math.imul(al9, bl4); + mid = Math.imul(al9, bh4); + mid = (mid + Math.imul(ah9, bl4)) | 0; + hi = Math.imul(ah9, bh4); + lo = (lo + Math.imul(al8, bl5)) | 0; + mid = (mid + Math.imul(al8, bh5)) | 0; + mid = (mid + Math.imul(ah8, bl5)) | 0; + hi = (hi + Math.imul(ah8, bh5)) | 0; + lo = (lo + Math.imul(al7, bl6)) | 0; + mid = (mid + Math.imul(al7, bh6)) | 0; + mid = (mid + Math.imul(ah7, bl6)) | 0; + hi = (hi + Math.imul(ah7, bh6)) | 0; + lo = (lo + Math.imul(al6, bl7)) | 0; + mid = (mid + Math.imul(al6, bh7)) | 0; + mid = (mid + Math.imul(ah6, bl7)) | 0; + hi = (hi + Math.imul(ah6, bh7)) | 0; + lo = (lo + Math.imul(al5, bl8)) | 0; + mid = (mid + Math.imul(al5, bh8)) | 0; + mid = (mid + Math.imul(ah5, bl8)) | 0; + hi = (hi + Math.imul(ah5, bh8)) | 0; + lo = (lo + Math.imul(al4, bl9)) | 0; + mid = (mid + Math.imul(al4, bh9)) | 0; + mid = (mid + Math.imul(ah4, bl9)) | 0; + hi = (hi + Math.imul(ah4, bh9)) | 0; + var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0; + w13 &= 0x3ffffff; + /* k = 14 */ + lo = Math.imul(al9, bl5); + mid = Math.imul(al9, bh5); + mid = (mid + Math.imul(ah9, bl5)) | 0; + hi = Math.imul(ah9, bh5); + lo = (lo + Math.imul(al8, bl6)) | 0; + mid = (mid + Math.imul(al8, bh6)) | 0; + mid = (mid + Math.imul(ah8, bl6)) | 0; + hi = (hi + Math.imul(ah8, bh6)) | 0; + lo = (lo + Math.imul(al7, bl7)) | 0; + mid = (mid + Math.imul(al7, bh7)) | 0; + mid = (mid + Math.imul(ah7, bl7)) | 0; + hi = (hi + Math.imul(ah7, bh7)) | 0; + lo = (lo + Math.imul(al6, bl8)) | 0; + mid = (mid + Math.imul(al6, bh8)) | 0; + mid = (mid + Math.imul(ah6, bl8)) | 0; + hi = (hi + Math.imul(ah6, bh8)) | 0; + lo = (lo + Math.imul(al5, bl9)) | 0; + mid = (mid + Math.imul(al5, bh9)) | 0; + mid = (mid + Math.imul(ah5, bl9)) | 0; + hi = (hi + Math.imul(ah5, bh9)) | 0; + var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0; + w14 &= 0x3ffffff; + /* k = 15 */ + lo = Math.imul(al9, bl6); + mid = Math.imul(al9, bh6); + mid = (mid + Math.imul(ah9, bl6)) | 0; + hi = Math.imul(ah9, bh6); + lo = (lo + Math.imul(al8, bl7)) | 0; + mid = (mid + Math.imul(al8, bh7)) | 0; + mid = (mid + Math.imul(ah8, bl7)) | 0; + hi = (hi + Math.imul(ah8, bh7)) | 0; + lo = (lo + Math.imul(al7, bl8)) | 0; + mid = (mid + Math.imul(al7, bh8)) | 0; + mid = (mid + Math.imul(ah7, bl8)) | 0; + hi = (hi + Math.imul(ah7, bh8)) | 0; + lo = (lo + Math.imul(al6, bl9)) | 0; + mid = (mid + Math.imul(al6, bh9)) | 0; + mid = (mid + Math.imul(ah6, bl9)) | 0; + hi = (hi + Math.imul(ah6, bh9)) | 0; + var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0; + w15 &= 0x3ffffff; + /* k = 16 */ + lo = Math.imul(al9, bl7); + mid = Math.imul(al9, bh7); + mid = (mid + Math.imul(ah9, bl7)) | 0; + hi = Math.imul(ah9, bh7); + lo = (lo + Math.imul(al8, bl8)) | 0; + mid = (mid + Math.imul(al8, bh8)) | 0; + mid = (mid + Math.imul(ah8, bl8)) | 0; + hi = (hi + Math.imul(ah8, bh8)) | 0; + lo = (lo + Math.imul(al7, bl9)) | 0; + mid = (mid + Math.imul(al7, bh9)) | 0; + mid = (mid + Math.imul(ah7, bl9)) | 0; + hi = (hi + Math.imul(ah7, bh9)) | 0; + var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0; + w16 &= 0x3ffffff; + /* k = 17 */ + lo = Math.imul(al9, bl8); + mid = Math.imul(al9, bh8); + mid = (mid + Math.imul(ah9, bl8)) | 0; + hi = Math.imul(ah9, bh8); + lo = (lo + Math.imul(al8, bl9)) | 0; + mid = (mid + Math.imul(al8, bh9)) | 0; + mid = (mid + Math.imul(ah8, bl9)) | 0; + hi = (hi + Math.imul(ah8, bh9)) | 0; + var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0; + w17 &= 0x3ffffff; + /* k = 18 */ + lo = Math.imul(al9, bl9); + mid = Math.imul(al9, bh9); + mid = (mid + Math.imul(ah9, bl9)) | 0; + hi = Math.imul(ah9, bh9); + var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0; + w18 &= 0x3ffffff; + o[0] = w0; + o[1] = w1; + o[2] = w2; + o[3] = w3; + o[4] = w4; + o[5] = w5; + o[6] = w6; + o[7] = w7; + o[8] = w8; + o[9] = w9; + o[10] = w10; + o[11] = w11; + o[12] = w12; + o[13] = w13; + o[14] = w14; + o[15] = w15; + o[16] = w16; + o[17] = w17; + o[18] = w18; + if (c !== 0) { + o[19] = c; + out.length++; + } + return out; + }; + + // Polyfill comb + if (!Math.imul) { + comb10MulTo = smallMulTo; + } + + function bigMulTo (self, num, out) { + out.negative = num.negative ^ self.negative; + out.length = self.length + num.length; + + var carry = 0; + var hncarry = 0; + for (var k = 0; k < out.length - 1; k++) { + // Sum all words with the same `i + j = k` and accumulate `ncarry`, + // note that ncarry could be >= 0x3ffffff + var ncarry = hncarry; + hncarry = 0; + var rword = carry & 0x3ffffff; + var maxJ = Math.min(k, num.length - 1); + for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { + var i = k - j; + var a = self.words[i] | 0; + var b = num.words[j] | 0; + var r = a * b; + + var lo = r & 0x3ffffff; + ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0; + lo = (lo + rword) | 0; + rword = lo & 0x3ffffff; + ncarry = (ncarry + (lo >>> 26)) | 0; + + hncarry += ncarry >>> 26; + ncarry &= 0x3ffffff; + } + out.words[k] = rword; + carry = ncarry; + ncarry = hncarry; + } + if (carry !== 0) { + out.words[k] = carry; + } else { + out.length--; + } + + return out.strip(); + } + + function jumboMulTo (self, num, out) { + var fftm = new FFTM(); + return fftm.mulp(self, num, out); + } + + BN.prototype.mulTo = function mulTo (num, out) { + var res; + var len = this.length + num.length; + if (this.length === 10 && num.length === 10) { + res = comb10MulTo(this, num, out); + } else if (len < 63) { + res = smallMulTo(this, num, out); + } else if (len < 1024) { + res = bigMulTo(this, num, out); + } else { + res = jumboMulTo(this, num, out); + } + + return res; + }; + + // Cooley-Tukey algorithm for FFT + // slightly revisited to rely on looping instead of recursion + + function FFTM (x, y) { + this.x = x; + this.y = y; + } + + FFTM.prototype.makeRBT = function makeRBT (N) { + var t = new Array(N); + var l = BN.prototype._countBits(N) - 1; + for (var i = 0; i < N; i++) { + t[i] = this.revBin(i, l, N); + } + + return t; + }; + + // Returns binary-reversed representation of `x` + FFTM.prototype.revBin = function revBin (x, l, N) { + if (x === 0 || x === N - 1) return x; + + var rb = 0; + for (var i = 0; i < l; i++) { + rb |= (x & 1) << (l - i - 1); + x >>= 1; + } + + return rb; + }; + + // Performs "tweedling" phase, therefore 'emulating' + // behaviour of the recursive algorithm + FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) { + for (var i = 0; i < N; i++) { + rtws[i] = rws[rbt[i]]; + itws[i] = iws[rbt[i]]; + } + }; + + FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) { + this.permute(rbt, rws, iws, rtws, itws, N); + + for (var s = 1; s < N; s <<= 1) { + var l = s << 1; + + var rtwdf = Math.cos(2 * Math.PI / l); + var itwdf = Math.sin(2 * Math.PI / l); + + for (var p = 0; p < N; p += l) { + var rtwdf_ = rtwdf; + var itwdf_ = itwdf; + + for (var j = 0; j < s; j++) { + var re = rtws[p + j]; + var ie = itws[p + j]; + + var ro = rtws[p + j + s]; + var io = itws[p + j + s]; + + var rx = rtwdf_ * ro - itwdf_ * io; + + io = rtwdf_ * io + itwdf_ * ro; + ro = rx; + + rtws[p + j] = re + ro; + itws[p + j] = ie + io; + + rtws[p + j + s] = re - ro; + itws[p + j + s] = ie - io; + + /* jshint maxdepth : false */ + if (j !== l) { + rx = rtwdf * rtwdf_ - itwdf * itwdf_; + + itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_; + rtwdf_ = rx; + } + } + } + } + }; + + FFTM.prototype.guessLen13b = function guessLen13b (n, m) { + var N = Math.max(m, n) | 1; + var odd = N & 1; + var i = 0; + for (N = N / 2 | 0; N; N = N >>> 1) { + i++; + } + + return 1 << i + 1 + odd; + }; + + FFTM.prototype.conjugate = function conjugate (rws, iws, N) { + if (N <= 1) return; + + for (var i = 0; i < N / 2; i++) { + var t = rws[i]; + + rws[i] = rws[N - i - 1]; + rws[N - i - 1] = t; + + t = iws[i]; + + iws[i] = -iws[N - i - 1]; + iws[N - i - 1] = -t; + } + }; + + FFTM.prototype.normalize13b = function normalize13b (ws, N) { + var carry = 0; + for (var i = 0; i < N / 2; i++) { + var w = Math.round(ws[2 * i + 1] / N) * 0x2000 + + Math.round(ws[2 * i] / N) + + carry; + + ws[i] = w & 0x3ffffff; + + if (w < 0x4000000) { + carry = 0; + } else { + carry = w / 0x4000000 | 0; + } + } + + return ws; + }; + + FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) { + var carry = 0; + for (var i = 0; i < len; i++) { + carry = carry + (ws[i] | 0); + + rws[2 * i] = carry & 0x1fff; carry = carry >>> 13; + rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13; + } + + // Pad with zeroes + for (i = 2 * len; i < N; ++i) { + rws[i] = 0; + } + + assert(carry === 0); + assert((carry & ~0x1fff) === 0); + }; + + FFTM.prototype.stub = function stub (N) { + var ph = new Array(N); + for (var i = 0; i < N; i++) { + ph[i] = 0; + } + + return ph; + }; + + FFTM.prototype.mulp = function mulp (x, y, out) { + var N = 2 * this.guessLen13b(x.length, y.length); + + var rbt = this.makeRBT(N); + + var _ = this.stub(N); + + var rws = new Array(N); + var rwst = new Array(N); + var iwst = new Array(N); + + var nrws = new Array(N); + var nrwst = new Array(N); + var niwst = new Array(N); + + var rmws = out.words; + rmws.length = N; + + this.convert13b(x.words, x.length, rws, N); + this.convert13b(y.words, y.length, nrws, N); + + this.transform(rws, _, rwst, iwst, N, rbt); + this.transform(nrws, _, nrwst, niwst, N, rbt); + + for (var i = 0; i < N; i++) { + var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i]; + iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i]; + rwst[i] = rx; + } + + this.conjugate(rwst, iwst, N); + this.transform(rwst, iwst, rmws, _, N, rbt); + this.conjugate(rmws, _, N); + this.normalize13b(rmws, N); + + out.negative = x.negative ^ y.negative; + out.length = x.length + y.length; + return out.strip(); + }; + + // Multiply `this` by `num` + BN.prototype.mul = function mul (num) { + var out = new BN(null); + out.words = new Array(this.length + num.length); + return this.mulTo(num, out); + }; + + // Multiply employing FFT + BN.prototype.mulf = function mulf (num) { + var out = new BN(null); + out.words = new Array(this.length + num.length); + return jumboMulTo(this, num, out); + }; + + // In-place Multiplication + BN.prototype.imul = function imul (num) { + return this.clone().mulTo(num, this); + }; + + BN.prototype.imuln = function imuln (num) { + assert(typeof num === 'number'); + assert(num < 0x4000000); + + // Carry + var carry = 0; + for (var i = 0; i < this.length; i++) { + var w = (this.words[i] | 0) * num; + var lo = (w & 0x3ffffff) + (carry & 0x3ffffff); + carry >>= 26; + carry += (w / 0x4000000) | 0; + // NOTE: lo is 27bit maximum + carry += lo >>> 26; + this.words[i] = lo & 0x3ffffff; + } + + if (carry !== 0) { + this.words[i] = carry; + this.length++; + } + + return this; + }; + + BN.prototype.muln = function muln (num) { + return this.clone().imuln(num); + }; + + // `this` * `this` + BN.prototype.sqr = function sqr () { + return this.mul(this); + }; + + // `this` * `this` in-place + BN.prototype.isqr = function isqr () { + return this.imul(this.clone()); + }; + + // Math.pow(`this`, `num`) + BN.prototype.pow = function pow (num) { + var w = toBitArray(num); + if (w.length === 0) return new BN(1); + + // Skip leading zeroes + var res = this; + for (var i = 0; i < w.length; i++, res = res.sqr()) { + if (w[i] !== 0) break; + } + + if (++i < w.length) { + for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) { + if (w[i] === 0) continue; + + res = res.mul(q); + } + } + + return res; + }; + + // Shift-left in-place + BN.prototype.iushln = function iushln (bits) { + assert(typeof bits === 'number' && bits >= 0); + var r = bits % 26; + var s = (bits - r) / 26; + var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r); + var i; + + if (r !== 0) { + var carry = 0; + + for (i = 0; i < this.length; i++) { + var newCarry = this.words[i] & carryMask; + var c = ((this.words[i] | 0) - newCarry) << r; + this.words[i] = c | carry; + carry = newCarry >>> (26 - r); + } + + if (carry) { + this.words[i] = carry; + this.length++; + } + } + + if (s !== 0) { + for (i = this.length - 1; i >= 0; i--) { + this.words[i + s] = this.words[i]; + } + + for (i = 0; i < s; i++) { + this.words[i] = 0; + } + + this.length += s; + } + + return this.strip(); + }; + + BN.prototype.ishln = function ishln (bits) { + // TODO(indutny): implement me + assert(this.negative === 0); + return this.iushln(bits); + }; + + // Shift-right in-place + // NOTE: `hint` is a lowest bit before trailing zeroes + // NOTE: if `extended` is present - it will be filled with destroyed bits + BN.prototype.iushrn = function iushrn (bits, hint, extended) { + assert(typeof bits === 'number' && bits >= 0); + var h; + if (hint) { + h = (hint - (hint % 26)) / 26; + } else { + h = 0; + } + + var r = bits % 26; + var s = Math.min((bits - r) / 26, this.length); + var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); + var maskedWords = extended; + + h -= s; + h = Math.max(0, h); + + // Extended mode, copy masked part + if (maskedWords) { + for (var i = 0; i < s; i++) { + maskedWords.words[i] = this.words[i]; + } + maskedWords.length = s; + } + + if (s === 0) ; else if (this.length > s) { + this.length -= s; + for (i = 0; i < this.length; i++) { + this.words[i] = this.words[i + s]; + } + } else { + this.words[0] = 0; + this.length = 1; + } + + var carry = 0; + for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) { + var word = this.words[i] | 0; + this.words[i] = (carry << (26 - r)) | (word >>> r); + carry = word & mask; + } + + // Push carried bits as a mask + if (maskedWords && carry !== 0) { + maskedWords.words[maskedWords.length++] = carry; + } + + if (this.length === 0) { + this.words[0] = 0; + this.length = 1; + } + + return this.strip(); + }; + + BN.prototype.ishrn = function ishrn (bits, hint, extended) { + // TODO(indutny): implement me + assert(this.negative === 0); + return this.iushrn(bits, hint, extended); + }; + + // Shift-left + BN.prototype.shln = function shln (bits) { + return this.clone().ishln(bits); + }; + + BN.prototype.ushln = function ushln (bits) { + return this.clone().iushln(bits); + }; + + // Shift-right + BN.prototype.shrn = function shrn (bits) { + return this.clone().ishrn(bits); + }; + + BN.prototype.ushrn = function ushrn (bits) { + return this.clone().iushrn(bits); + }; + + // Test if n bit is set + BN.prototype.testn = function testn (bit) { + assert(typeof bit === 'number' && bit >= 0); + var r = bit % 26; + var s = (bit - r) / 26; + var q = 1 << r; + + // Fast case: bit is much higher than all existing words + if (this.length <= s) return false; + + // Check bit and return + var w = this.words[s]; + + return !!(w & q); + }; + + // Return only lowers bits of number (in-place) + BN.prototype.imaskn = function imaskn (bits) { + assert(typeof bits === 'number' && bits >= 0); + var r = bits % 26; + var s = (bits - r) / 26; + + assert(this.negative === 0, 'imaskn works only with positive numbers'); + + if (this.length <= s) { + return this; + } + + if (r !== 0) { + s++; + } + this.length = Math.min(s, this.length); + + if (r !== 0) { + var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); + this.words[this.length - 1] &= mask; + } + + return this.strip(); + }; + + // Return only lowers bits of number + BN.prototype.maskn = function maskn (bits) { + return this.clone().imaskn(bits); + }; + + // Add plain number `num` to `this` + BN.prototype.iaddn = function iaddn (num) { + assert(typeof num === 'number'); + assert(num < 0x4000000); + if (num < 0) return this.isubn(-num); + + // Possible sign change + if (this.negative !== 0) { + if (this.length === 1 && (this.words[0] | 0) < num) { + this.words[0] = num - (this.words[0] | 0); + this.negative = 0; + return this; + } + + this.negative = 0; + this.isubn(num); + this.negative = 1; + return this; + } + + // Add without checks + return this._iaddn(num); + }; + + BN.prototype._iaddn = function _iaddn (num) { + this.words[0] += num; + + // Carry + for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) { + this.words[i] -= 0x4000000; + if (i === this.length - 1) { + this.words[i + 1] = 1; + } else { + this.words[i + 1]++; + } + } + this.length = Math.max(this.length, i + 1); + + return this; + }; + + // Subtract plain number `num` from `this` + BN.prototype.isubn = function isubn (num) { + assert(typeof num === 'number'); + assert(num < 0x4000000); + if (num < 0) return this.iaddn(-num); + + if (this.negative !== 0) { + this.negative = 0; + this.iaddn(num); + this.negative = 1; + return this; + } + + this.words[0] -= num; + + if (this.length === 1 && this.words[0] < 0) { + this.words[0] = -this.words[0]; + this.negative = 1; + } else { + // Carry + for (var i = 0; i < this.length && this.words[i] < 0; i++) { + this.words[i] += 0x4000000; + this.words[i + 1] -= 1; + } + } + + return this.strip(); + }; + + BN.prototype.addn = function addn (num) { + return this.clone().iaddn(num); + }; + + BN.prototype.subn = function subn (num) { + return this.clone().isubn(num); + }; + + BN.prototype.iabs = function iabs () { + this.negative = 0; + + return this; + }; + + BN.prototype.abs = function abs () { + return this.clone().iabs(); + }; + + BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) { + var len = num.length + shift; + var i; + + this._expand(len); + + var w; + var carry = 0; + for (i = 0; i < num.length; i++) { + w = (this.words[i + shift] | 0) + carry; + var right = (num.words[i] | 0) * mul; + w -= right & 0x3ffffff; + carry = (w >> 26) - ((right / 0x4000000) | 0); + this.words[i + shift] = w & 0x3ffffff; + } + for (; i < this.length - shift; i++) { + w = (this.words[i + shift] | 0) + carry; + carry = w >> 26; + this.words[i + shift] = w & 0x3ffffff; + } + + if (carry === 0) return this.strip(); + + // Subtraction overflow + assert(carry === -1); + carry = 0; + for (i = 0; i < this.length; i++) { + w = -(this.words[i] | 0) + carry; + carry = w >> 26; + this.words[i] = w & 0x3ffffff; + } + this.negative = 1; + + return this.strip(); + }; + + BN.prototype._wordDiv = function _wordDiv (num, mode) { + var shift = this.length - num.length; + + var a = this.clone(); + var b = num; + + // Normalize + var bhi = b.words[b.length - 1] | 0; + var bhiBits = this._countBits(bhi); + shift = 26 - bhiBits; + if (shift !== 0) { + b = b.ushln(shift); + a.iushln(shift); + bhi = b.words[b.length - 1] | 0; + } + + // Initialize quotient + var m = a.length - b.length; + var q; + + if (mode !== 'mod') { + q = new BN(null); + q.length = m + 1; + q.words = new Array(q.length); + for (var i = 0; i < q.length; i++) { + q.words[i] = 0; + } + } + + var diff = a.clone()._ishlnsubmul(b, 1, m); + if (diff.negative === 0) { + a = diff; + if (q) { + q.words[m] = 1; + } + } + + for (var j = m - 1; j >= 0; j--) { + var qj = (a.words[b.length + j] | 0) * 0x4000000 + + (a.words[b.length + j - 1] | 0); + + // NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max + // (0x7ffffff) + qj = Math.min((qj / bhi) | 0, 0x3ffffff); + + a._ishlnsubmul(b, qj, j); + while (a.negative !== 0) { + qj--; + a.negative = 0; + a._ishlnsubmul(b, 1, j); + if (!a.isZero()) { + a.negative ^= 1; + } + } + if (q) { + q.words[j] = qj; + } + } + if (q) { + q.strip(); + } + a.strip(); + + // Denormalize + if (mode !== 'div' && shift !== 0) { + a.iushrn(shift); + } + + return { + div: q || null, + mod: a + }; + }; + + // NOTE: 1) `mode` can be set to `mod` to request mod only, + // to `div` to request div only, or be absent to + // request both div & mod + // 2) `positive` is true if unsigned mod is requested + BN.prototype.divmod = function divmod (num, mode, positive) { + assert(!num.isZero()); + + if (this.isZero()) { + return { + div: new BN(0), + mod: new BN(0) + }; + } + + var div, mod, res; + if (this.negative !== 0 && num.negative === 0) { + res = this.neg().divmod(num, mode); + + if (mode !== 'mod') { + div = res.div.neg(); + } + + if (mode !== 'div') { + mod = res.mod.neg(); + if (positive && mod.negative !== 0) { + mod.iadd(num); + } + } + + return { + div: div, + mod: mod + }; + } + + if (this.negative === 0 && num.negative !== 0) { + res = this.divmod(num.neg(), mode); + + if (mode !== 'mod') { + div = res.div.neg(); + } + + return { + div: div, + mod: res.mod + }; + } + + if ((this.negative & num.negative) !== 0) { + res = this.neg().divmod(num.neg(), mode); + + if (mode !== 'div') { + mod = res.mod.neg(); + if (positive && mod.negative !== 0) { + mod.isub(num); + } + } + + return { + div: res.div, + mod: mod + }; + } + + // Both numbers are positive at this point + + // Strip both numbers to approximate shift value + if (num.length > this.length || this.cmp(num) < 0) { + return { + div: new BN(0), + mod: this + }; + } + + // Very short reduction + if (num.length === 1) { + if (mode === 'div') { + return { + div: this.divn(num.words[0]), + mod: null + }; + } + + if (mode === 'mod') { + return { + div: null, + mod: new BN(this.modn(num.words[0])) + }; + } + + return { + div: this.divn(num.words[0]), + mod: new BN(this.modn(num.words[0])) + }; + } + + return this._wordDiv(num, mode); + }; + + // Find `this` / `num` + BN.prototype.div = function div (num) { + return this.divmod(num, 'div', false).div; + }; + + // Find `this` % `num` + BN.prototype.mod = function mod (num) { + return this.divmod(num, 'mod', false).mod; + }; + + BN.prototype.umod = function umod (num) { + return this.divmod(num, 'mod', true).mod; + }; + + // Find Round(`this` / `num`) + BN.prototype.divRound = function divRound (num) { + var dm = this.divmod(num); + + // Fast case - exact division + if (dm.mod.isZero()) return dm.div; + + var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod; + + var half = num.ushrn(1); + var r2 = num.andln(1); + var cmp = mod.cmp(half); + + // Round down + if (cmp < 0 || r2 === 1 && cmp === 0) return dm.div; + + // Round up + return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1); + }; + + BN.prototype.modn = function modn (num) { + assert(num <= 0x3ffffff); + var p = (1 << 26) % num; + + var acc = 0; + for (var i = this.length - 1; i >= 0; i--) { + acc = (p * acc + (this.words[i] | 0)) % num; + } + + return acc; + }; + + // In-place division by number + BN.prototype.idivn = function idivn (num) { + assert(num <= 0x3ffffff); + + var carry = 0; + for (var i = this.length - 1; i >= 0; i--) { + var w = (this.words[i] | 0) + carry * 0x4000000; + this.words[i] = (w / num) | 0; + carry = w % num; + } + + return this.strip(); + }; + + BN.prototype.divn = function divn (num) { + return this.clone().idivn(num); + }; + + BN.prototype.egcd = function egcd (p) { + assert(p.negative === 0); + assert(!p.isZero()); + + var x = this; + var y = p.clone(); + + if (x.negative !== 0) { + x = x.umod(p); + } else { + x = x.clone(); + } + + // A * x + B * y = x + var A = new BN(1); + var B = new BN(0); + + // C * x + D * y = y + var C = new BN(0); + var D = new BN(1); + + var g = 0; + + while (x.isEven() && y.isEven()) { + x.iushrn(1); + y.iushrn(1); + ++g; + } + + var yp = y.clone(); + var xp = x.clone(); + + while (!x.isZero()) { + for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1); + if (i > 0) { + x.iushrn(i); + while (i-- > 0) { + if (A.isOdd() || B.isOdd()) { + A.iadd(yp); + B.isub(xp); + } + + A.iushrn(1); + B.iushrn(1); + } + } + + for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); + if (j > 0) { + y.iushrn(j); + while (j-- > 0) { + if (C.isOdd() || D.isOdd()) { + C.iadd(yp); + D.isub(xp); + } + + C.iushrn(1); + D.iushrn(1); + } + } + + if (x.cmp(y) >= 0) { + x.isub(y); + A.isub(C); + B.isub(D); + } else { + y.isub(x); + C.isub(A); + D.isub(B); + } + } + + return { + a: C, + b: D, + gcd: y.iushln(g) + }; + }; + + // This is reduced incarnation of the binary EEA + // above, designated to invert members of the + // _prime_ fields F(p) at a maximal speed + BN.prototype._invmp = function _invmp (p) { + assert(p.negative === 0); + assert(!p.isZero()); + + var a = this; + var b = p.clone(); + + if (a.negative !== 0) { + a = a.umod(p); + } else { + a = a.clone(); + } + + var x1 = new BN(1); + var x2 = new BN(0); + + var delta = b.clone(); + + while (a.cmpn(1) > 0 && b.cmpn(1) > 0) { + for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1); + if (i > 0) { + a.iushrn(i); + while (i-- > 0) { + if (x1.isOdd()) { + x1.iadd(delta); + } + + x1.iushrn(1); + } + } + + for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); + if (j > 0) { + b.iushrn(j); + while (j-- > 0) { + if (x2.isOdd()) { + x2.iadd(delta); + } + + x2.iushrn(1); + } + } + + if (a.cmp(b) >= 0) { + a.isub(b); + x1.isub(x2); + } else { + b.isub(a); + x2.isub(x1); + } + } + + var res; + if (a.cmpn(1) === 0) { + res = x1; + } else { + res = x2; + } + + if (res.cmpn(0) < 0) { + res.iadd(p); + } + + return res; + }; + + BN.prototype.gcd = function gcd (num) { + if (this.isZero()) return num.abs(); + if (num.isZero()) return this.abs(); + + var a = this.clone(); + var b = num.clone(); + a.negative = 0; + b.negative = 0; + + // Remove common factor of two + for (var shift = 0; a.isEven() && b.isEven(); shift++) { + a.iushrn(1); + b.iushrn(1); + } + + do { + while (a.isEven()) { + a.iushrn(1); + } + while (b.isEven()) { + b.iushrn(1); + } + + var r = a.cmp(b); + if (r < 0) { + // Swap `a` and `b` to make `a` always bigger than `b` + var t = a; + a = b; + b = t; + } else if (r === 0 || b.cmpn(1) === 0) { + break; + } + + a.isub(b); + } while (true); + + return b.iushln(shift); + }; + + // Invert number in the field F(num) + BN.prototype.invm = function invm (num) { + return this.egcd(num).a.umod(num); + }; + + BN.prototype.isEven = function isEven () { + return (this.words[0] & 1) === 0; + }; + + BN.prototype.isOdd = function isOdd () { + return (this.words[0] & 1) === 1; + }; + + // And first word and num + BN.prototype.andln = function andln (num) { + return this.words[0] & num; + }; + + // Increment at the bit position in-line + BN.prototype.bincn = function bincn (bit) { + assert(typeof bit === 'number'); + var r = bit % 26; + var s = (bit - r) / 26; + var q = 1 << r; + + // Fast case: bit is much higher than all existing words + if (this.length <= s) { + this._expand(s + 1); + this.words[s] |= q; + return this; + } + + // Add bit and propagate, if needed + var carry = q; + for (var i = s; carry !== 0 && i < this.length; i++) { + var w = this.words[i] | 0; + w += carry; + carry = w >>> 26; + w &= 0x3ffffff; + this.words[i] = w; + } + if (carry !== 0) { + this.words[i] = carry; + this.length++; + } + return this; + }; + + BN.prototype.isZero = function isZero () { + return this.length === 1 && this.words[0] === 0; + }; + + BN.prototype.cmpn = function cmpn (num) { + var negative = num < 0; + + if (this.negative !== 0 && !negative) return -1; + if (this.negative === 0 && negative) return 1; + + this.strip(); + + var res; + if (this.length > 1) { + res = 1; + } else { + if (negative) { + num = -num; + } + + assert(num <= 0x3ffffff, 'Number is too big'); + + var w = this.words[0] | 0; + res = w === num ? 0 : w < num ? -1 : 1; + } + if (this.negative !== 0) return -res | 0; + return res; + }; + + // Compare two numbers and return: + // 1 - if `this` > `num` + // 0 - if `this` == `num` + // -1 - if `this` < `num` + BN.prototype.cmp = function cmp (num) { + if (this.negative !== 0 && num.negative === 0) return -1; + if (this.negative === 0 && num.negative !== 0) return 1; + + var res = this.ucmp(num); + if (this.negative !== 0) return -res | 0; + return res; + }; + + // Unsigned comparison + BN.prototype.ucmp = function ucmp (num) { + // At this point both numbers have the same sign + if (this.length > num.length) return 1; + if (this.length < num.length) return -1; + + var res = 0; + for (var i = this.length - 1; i >= 0; i--) { + var a = this.words[i] | 0; + var b = num.words[i] | 0; + + if (a === b) continue; + if (a < b) { + res = -1; + } else if (a > b) { + res = 1; + } + break; + } + return res; + }; + + BN.prototype.gtn = function gtn (num) { + return this.cmpn(num) === 1; + }; + + BN.prototype.gt = function gt (num) { + return this.cmp(num) === 1; + }; + + BN.prototype.gten = function gten (num) { + return this.cmpn(num) >= 0; + }; + + BN.prototype.gte = function gte (num) { + return this.cmp(num) >= 0; + }; + + BN.prototype.ltn = function ltn (num) { + return this.cmpn(num) === -1; + }; + + BN.prototype.lt = function lt (num) { + return this.cmp(num) === -1; + }; + + BN.prototype.lten = function lten (num) { + return this.cmpn(num) <= 0; + }; + + BN.prototype.lte = function lte (num) { + return this.cmp(num) <= 0; + }; + + BN.prototype.eqn = function eqn (num) { + return this.cmpn(num) === 0; + }; + + BN.prototype.eq = function eq (num) { + return this.cmp(num) === 0; + }; + + // + // A reduce context, could be using montgomery or something better, depending + // on the `m` itself. + // + BN.red = function red (num) { + return new Red(num); + }; + + BN.prototype.toRed = function toRed (ctx) { + assert(!this.red, 'Already a number in reduction context'); + assert(this.negative === 0, 'red works only with positives'); + return ctx.convertTo(this)._forceRed(ctx); + }; + + BN.prototype.fromRed = function fromRed () { + assert(this.red, 'fromRed works only with numbers in reduction context'); + return this.red.convertFrom(this); + }; + + BN.prototype._forceRed = function _forceRed (ctx) { + this.red = ctx; + return this; + }; + + BN.prototype.forceRed = function forceRed (ctx) { + assert(!this.red, 'Already a number in reduction context'); + return this._forceRed(ctx); + }; + + BN.prototype.redAdd = function redAdd (num) { + assert(this.red, 'redAdd works only with red numbers'); + return this.red.add(this, num); + }; + + BN.prototype.redIAdd = function redIAdd (num) { + assert(this.red, 'redIAdd works only with red numbers'); + return this.red.iadd(this, num); + }; + + BN.prototype.redSub = function redSub (num) { + assert(this.red, 'redSub works only with red numbers'); + return this.red.sub(this, num); + }; + + BN.prototype.redISub = function redISub (num) { + assert(this.red, 'redISub works only with red numbers'); + return this.red.isub(this, num); + }; + + BN.prototype.redShl = function redShl (num) { + assert(this.red, 'redShl works only with red numbers'); + return this.red.shl(this, num); + }; + + BN.prototype.redMul = function redMul (num) { + assert(this.red, 'redMul works only with red numbers'); + this.red._verify2(this, num); + return this.red.mul(this, num); + }; + + BN.prototype.redIMul = function redIMul (num) { + assert(this.red, 'redMul works only with red numbers'); + this.red._verify2(this, num); + return this.red.imul(this, num); + }; + + BN.prototype.redSqr = function redSqr () { + assert(this.red, 'redSqr works only with red numbers'); + this.red._verify1(this); + return this.red.sqr(this); + }; + + BN.prototype.redISqr = function redISqr () { + assert(this.red, 'redISqr works only with red numbers'); + this.red._verify1(this); + return this.red.isqr(this); + }; + + // Square root over p + BN.prototype.redSqrt = function redSqrt () { + assert(this.red, 'redSqrt works only with red numbers'); + this.red._verify1(this); + return this.red.sqrt(this); + }; + + BN.prototype.redInvm = function redInvm () { + assert(this.red, 'redInvm works only with red numbers'); + this.red._verify1(this); + return this.red.invm(this); + }; + + // Return negative clone of `this` % `red modulo` + BN.prototype.redNeg = function redNeg () { + assert(this.red, 'redNeg works only with red numbers'); + this.red._verify1(this); + return this.red.neg(this); + }; + + BN.prototype.redPow = function redPow (num) { + assert(this.red && !num.red, 'redPow(normalNum)'); + this.red._verify1(this); + return this.red.pow(this, num); + }; + + // Prime numbers with efficient reduction + var primes = { + k256: null, + p224: null, + p192: null, + p25519: null + }; + + // Pseudo-Mersenne prime + function MPrime (name, p) { + // P = 2 ^ N - K + this.name = name; + this.p = new BN(p, 16); + this.n = this.p.bitLength(); + this.k = new BN(1).iushln(this.n).isub(this.p); + + this.tmp = this._tmp(); + } + + MPrime.prototype._tmp = function _tmp () { + var tmp = new BN(null); + tmp.words = new Array(Math.ceil(this.n / 13)); + return tmp; + }; + + MPrime.prototype.ireduce = function ireduce (num) { + // Assumes that `num` is less than `P^2` + // num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P) + var r = num; + var rlen; + + do { + this.split(r, this.tmp); + r = this.imulK(r); + r = r.iadd(this.tmp); + rlen = r.bitLength(); + } while (rlen > this.n); + + var cmp = rlen < this.n ? -1 : r.ucmp(this.p); + if (cmp === 0) { + r.words[0] = 0; + r.length = 1; + } else if (cmp > 0) { + r.isub(this.p); + } else { + r.strip(); + } + + return r; + }; + + MPrime.prototype.split = function split (input, out) { + input.iushrn(this.n, 0, out); + }; + + MPrime.prototype.imulK = function imulK (num) { + return num.imul(this.k); + }; + + function K256 () { + MPrime.call( + this, + 'k256', + 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f'); + } + inherits(K256, MPrime); + + K256.prototype.split = function split (input, output) { + // 256 = 9 * 26 + 22 + var mask = 0x3fffff; + + var outLen = Math.min(input.length, 9); + for (var i = 0; i < outLen; i++) { + output.words[i] = input.words[i]; + } + output.length = outLen; + + if (input.length <= 9) { + input.words[0] = 0; + input.length = 1; + return; + } + + // Shift by 9 limbs + var prev = input.words[9]; + output.words[output.length++] = prev & mask; + + for (i = 10; i < input.length; i++) { + var next = input.words[i] | 0; + input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22); + prev = next; + } + prev >>>= 22; + input.words[i - 10] = prev; + if (prev === 0 && input.length > 10) { + input.length -= 10; + } else { + input.length -= 9; + } + }; + + K256.prototype.imulK = function imulK (num) { + // K = 0x1000003d1 = [ 0x40, 0x3d1 ] + num.words[num.length] = 0; + num.words[num.length + 1] = 0; + num.length += 2; + + // bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390 + var lo = 0; + for (var i = 0; i < num.length; i++) { + var w = num.words[i] | 0; + lo += w * 0x3d1; + num.words[i] = lo & 0x3ffffff; + lo = w * 0x40 + ((lo / 0x4000000) | 0); + } + + // Fast length reduction + if (num.words[num.length - 1] === 0) { + num.length--; + if (num.words[num.length - 1] === 0) { + num.length--; + } + } + return num; + }; + + function P224 () { + MPrime.call( + this, + 'p224', + 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001'); + } + inherits(P224, MPrime); + + function P192 () { + MPrime.call( + this, + 'p192', + 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff'); + } + inherits(P192, MPrime); + + function P25519 () { + // 2 ^ 255 - 19 + MPrime.call( + this, + '25519', + '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed'); + } + inherits(P25519, MPrime); + + P25519.prototype.imulK = function imulK (num) { + // K = 0x13 + var carry = 0; + for (var i = 0; i < num.length; i++) { + var hi = (num.words[i] | 0) * 0x13 + carry; + var lo = hi & 0x3ffffff; + hi >>>= 26; + + num.words[i] = lo; + carry = hi; + } + if (carry !== 0) { + num.words[num.length++] = carry; + } + return num; + }; + + // Exported mostly for testing purposes, use plain name instead + BN._prime = function prime (name) { + // Cached version of prime + if (primes[name]) return primes[name]; + + var prime; + if (name === 'k256') { + prime = new K256(); + } else if (name === 'p224') { + prime = new P224(); + } else if (name === 'p192') { + prime = new P192(); + } else if (name === 'p25519') { + prime = new P25519(); + } else { + throw new Error('Unknown prime ' + name); + } + primes[name] = prime; + + return prime; + }; + + // + // Base reduction engine + // + function Red (m) { + if (typeof m === 'string') { + var prime = BN._prime(m); + this.m = prime.p; + this.prime = prime; + } else { + assert(m.gtn(1), 'modulus must be greater than 1'); + this.m = m; + this.prime = null; + } + } + + Red.prototype._verify1 = function _verify1 (a) { + assert(a.negative === 0, 'red works only with positives'); + assert(a.red, 'red works only with red numbers'); + }; + + Red.prototype._verify2 = function _verify2 (a, b) { + assert((a.negative | b.negative) === 0, 'red works only with positives'); + assert(a.red && a.red === b.red, + 'red works only with red numbers'); + }; + + Red.prototype.imod = function imod (a) { + if (this.prime) return this.prime.ireduce(a)._forceRed(this); + return a.umod(this.m)._forceRed(this); + }; + + Red.prototype.neg = function neg (a) { + if (a.isZero()) { + return a.clone(); + } + + return this.m.sub(a)._forceRed(this); + }; + + Red.prototype.add = function add (a, b) { + this._verify2(a, b); + + var res = a.add(b); + if (res.cmp(this.m) >= 0) { + res.isub(this.m); + } + return res._forceRed(this); + }; + + Red.prototype.iadd = function iadd (a, b) { + this._verify2(a, b); + + var res = a.iadd(b); + if (res.cmp(this.m) >= 0) { + res.isub(this.m); + } + return res; + }; + + Red.prototype.sub = function sub (a, b) { + this._verify2(a, b); + + var res = a.sub(b); + if (res.cmpn(0) < 0) { + res.iadd(this.m); + } + return res._forceRed(this); + }; + + Red.prototype.isub = function isub (a, b) { + this._verify2(a, b); + + var res = a.isub(b); + if (res.cmpn(0) < 0) { + res.iadd(this.m); + } + return res; + }; + + Red.prototype.shl = function shl (a, num) { + this._verify1(a); + return this.imod(a.ushln(num)); + }; + + Red.prototype.imul = function imul (a, b) { + this._verify2(a, b); + return this.imod(a.imul(b)); + }; + + Red.prototype.mul = function mul (a, b) { + this._verify2(a, b); + return this.imod(a.mul(b)); + }; + + Red.prototype.isqr = function isqr (a) { + return this.imul(a, a.clone()); + }; + + Red.prototype.sqr = function sqr (a) { + return this.mul(a, a); + }; + + Red.prototype.sqrt = function sqrt (a) { + if (a.isZero()) return a.clone(); + + var mod3 = this.m.andln(3); + assert(mod3 % 2 === 1); + + // Fast case + if (mod3 === 3) { + var pow = this.m.add(new BN(1)).iushrn(2); + return this.pow(a, pow); + } + + // Tonelli-Shanks algorithm (Totally unoptimized and slow) + // + // Find Q and S, that Q * 2 ^ S = (P - 1) + var q = this.m.subn(1); + var s = 0; + while (!q.isZero() && q.andln(1) === 0) { + s++; + q.iushrn(1); + } + assert(!q.isZero()); + + var one = new BN(1).toRed(this); + var nOne = one.redNeg(); + + // Find quadratic non-residue + // NOTE: Max is such because of generalized Riemann hypothesis. + var lpow = this.m.subn(1).iushrn(1); + var z = this.m.bitLength(); + z = new BN(2 * z * z).toRed(this); + + while (this.pow(z, lpow).cmp(nOne) !== 0) { + z.redIAdd(nOne); + } + + var c = this.pow(z, q); + var r = this.pow(a, q.addn(1).iushrn(1)); + var t = this.pow(a, q); + var m = s; + while (t.cmp(one) !== 0) { + var tmp = t; + for (var i = 0; tmp.cmp(one) !== 0; i++) { + tmp = tmp.redSqr(); + } + assert(i < m); + var b = this.pow(c, new BN(1).iushln(m - i - 1)); + + r = r.redMul(b); + c = b.redSqr(); + t = t.redMul(c); + m = i; + } + + return r; + }; + + Red.prototype.invm = function invm (a) { + var inv = a._invmp(this.m); + if (inv.negative !== 0) { + inv.negative = 0; + return this.imod(inv).redNeg(); + } else { + return this.imod(inv); + } + }; + + Red.prototype.pow = function pow (a, num) { + if (num.isZero()) return new BN(1).toRed(this); + if (num.cmpn(1) === 0) return a.clone(); + + var windowSize = 4; + var wnd = new Array(1 << windowSize); + wnd[0] = new BN(1).toRed(this); + wnd[1] = a; + for (var i = 2; i < wnd.length; i++) { + wnd[i] = this.mul(wnd[i - 1], a); + } + + var res = wnd[0]; + var current = 0; + var currentLen = 0; + var start = num.bitLength() % 26; + if (start === 0) { + start = 26; + } + + for (i = num.length - 1; i >= 0; i--) { + var word = num.words[i]; + for (var j = start - 1; j >= 0; j--) { + var bit = (word >> j) & 1; + if (res !== wnd[0]) { + res = this.sqr(res); + } + + if (bit === 0 && current === 0) { + currentLen = 0; + continue; + } + + current <<= 1; + current |= bit; + currentLen++; + if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue; + + res = this.mul(res, wnd[current]); + currentLen = 0; + current = 0; + } + start = 26; + } + + return res; + }; + + Red.prototype.convertTo = function convertTo (num) { + var r = num.umod(this.m); + + return r === num ? r.clone() : r; + }; + + Red.prototype.convertFrom = function convertFrom (num) { + var res = num.clone(); + res.red = null; + return res; + }; + + // + // Montgomery method engine + // + + BN.mont = function mont (num) { + return new Mont(num); + }; + + function Mont (m) { + Red.call(this, m); + + this.shift = this.m.bitLength(); + if (this.shift % 26 !== 0) { + this.shift += 26 - (this.shift % 26); + } + + this.r = new BN(1).iushln(this.shift); + this.r2 = this.imod(this.r.sqr()); + this.rinv = this.r._invmp(this.m); + + this.minv = this.rinv.mul(this.r).isubn(1).div(this.m); + this.minv = this.minv.umod(this.r); + this.minv = this.r.sub(this.minv); + } + inherits(Mont, Red); + + Mont.prototype.convertTo = function convertTo (num) { + return this.imod(num.ushln(this.shift)); + }; + + Mont.prototype.convertFrom = function convertFrom (num) { + var r = this.imod(num.mul(this.rinv)); + r.red = null; + return r; + }; + + Mont.prototype.imul = function imul (a, b) { + if (a.isZero() || b.isZero()) { + a.words[0] = 0; + a.length = 1; + return a; + } + + var t = a.imul(b); + var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); + var u = t.isub(c).iushrn(this.shift); + var res = u; + + if (u.cmp(this.m) >= 0) { + res = u.isub(this.m); + } else if (u.cmpn(0) < 0) { + res = u.iadd(this.m); + } + + return res._forceRed(this); + }; + + Mont.prototype.mul = function mul (a, b) { + if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this); + + var t = a.mul(b); + var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); + var u = t.isub(c).iushrn(this.shift); + var res = u; + if (u.cmp(this.m) >= 0) { + res = u.isub(this.m); + } else if (u.cmpn(0) < 0) { + res = u.iadd(this.m); + } + + return res._forceRed(this); + }; + + Mont.prototype.invm = function invm (a) { + // (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R + var res = this.imod(a._invmp(this.m).mul(this.r2)); + return res._forceRed(this); + }; +})(module, commonjsGlobal); +}); + +var bn$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + 'default': bn, + __moduleExports: bn +}); + +/** + * @fileoverview + * BigInteger implementation of basic operations + * Wrapper of bn.js library (wwww.github.com/indutny/bn.js) + * @module biginteger/bn + * @private + */ + +/** + * @private + */ +class BigInteger$1 { + /** + * Get a BigInteger (input must be big endian for strings and arrays) + * @param {Number|String|Uint8Array} n - Value to convert + * @throws {Error} on undefined input + */ + constructor(n) { + if (n === undefined) { + throw new Error('Invalid BigInteger input'); + } + + this.value = new bn(n); + } + + clone() { + const clone = new BigInteger$1(null); + this.value.copy(clone.value); + return clone; + } + + /** + * BigInteger increment in place + */ + iinc() { + this.value.iadd(new bn(1)); + return this; + } + + /** + * BigInteger increment + * @returns {BigInteger} this + 1. + */ + inc() { + return this.clone().iinc(); + } + + /** + * BigInteger decrement in place + */ + idec() { + this.value.isub(new bn(1)); + return this; + } + + /** + * BigInteger decrement + * @returns {BigInteger} this - 1. + */ + dec() { + return this.clone().idec(); + } + + + /** + * BigInteger addition in place + * @param {BigInteger} x - Value to add + */ + iadd(x) { + this.value.iadd(x.value); + return this; + } + + /** + * BigInteger addition + * @param {BigInteger} x - Value to add + * @returns {BigInteger} this + x. + */ + add(x) { + return this.clone().iadd(x); + } + + /** + * BigInteger subtraction in place + * @param {BigInteger} x - Value to subtract + */ + isub(x) { + this.value.isub(x.value); + return this; + } + + /** + * BigInteger subtraction + * @param {BigInteger} x - Value to subtract + * @returns {BigInteger} this - x. + */ + sub(x) { + return this.clone().isub(x); + } + + /** + * BigInteger multiplication in place + * @param {BigInteger} x - Value to multiply + */ + imul(x) { + this.value.imul(x.value); + return this; + } + + /** + * BigInteger multiplication + * @param {BigInteger} x - Value to multiply + * @returns {BigInteger} this * x. + */ + mul(x) { + return this.clone().imul(x); + } + + /** + * Compute value modulo m, in place + * @param {BigInteger} m - Modulo + */ + imod(m) { + this.value = this.value.umod(m.value); + return this; + } + + /** + * Compute value modulo m + * @param {BigInteger} m - Modulo + * @returns {BigInteger} this mod m. + */ + mod(m) { + return this.clone().imod(m); + } + + /** + * Compute modular exponentiation + * Much faster than this.exp(e).mod(n) + * @param {BigInteger} e - Exponent + * @param {BigInteger} n - Modulo + * @returns {BigInteger} this ** e mod n. + */ + modExp(e, n) { + // We use either Montgomery or normal reduction context + // Montgomery requires coprime n and R (montogmery multiplier) + // bn.js picks R as power of 2, so n must be odd + const nred = n.isEven() ? bn.red(n.value) : bn.mont(n.value); + const x = this.clone(); + x.value = x.value.toRed(nred).redPow(e.value).fromRed(); + return x; + } + + /** + * Compute the inverse of this value modulo n + * Note: this and and n must be relatively prime + * @param {BigInteger} n - Modulo + * @returns {BigInteger} x such that this*x = 1 mod n + * @throws {Error} if the inverse does not exist + */ + modInv(n) { + // invm returns a wrong result if the inverse does not exist + if (!this.gcd(n).isOne()) { + throw new Error('Inverse does not exist'); + } + return new BigInteger$1(this.value.invm(n.value)); + } + + /** + * Compute greatest common divisor between this and n + * @param {BigInteger} n - Operand + * @returns {BigInteger} gcd + */ + gcd(n) { + return new BigInteger$1(this.value.gcd(n.value)); + } + + /** + * Shift this to the left by x, in place + * @param {BigInteger} x - Shift value + */ + ileftShift(x) { + this.value.ishln(x.value.toNumber()); + return this; + } + + /** + * Shift this to the left by x + * @param {BigInteger} x - Shift value + * @returns {BigInteger} this << x. + */ + leftShift(x) { + return this.clone().ileftShift(x); + } + + /** + * Shift this to the right by x, in place + * @param {BigInteger} x - Shift value + */ + irightShift(x) { + this.value.ishrn(x.value.toNumber()); + return this; + } + + /** + * Shift this to the right by x + * @param {BigInteger} x - Shift value + * @returns {BigInteger} this >> x. + */ + rightShift(x) { + return this.clone().irightShift(x); + } + + /** + * Whether this value is equal to x + * @param {BigInteger} x + * @returns {Boolean} + */ + equal(x) { + return this.value.eq(x.value); + } + + /** + * Whether this value is less than x + * @param {BigInteger} x + * @returns {Boolean} + */ + lt(x) { + return this.value.lt(x.value); + } + + /** + * Whether this value is less than or equal to x + * @param {BigInteger} x + * @returns {Boolean} + */ + lte(x) { + return this.value.lte(x.value); + } + + /** + * Whether this value is greater than x + * @param {BigInteger} x + * @returns {Boolean} + */ + gt(x) { + return this.value.gt(x.value); + } + + /** + * Whether this value is greater than or equal to x + * @param {BigInteger} x + * @returns {Boolean} + */ + gte(x) { + return this.value.gte(x.value); + } + + isZero() { + return this.value.isZero(); + } + + isOne() { + return this.value.eq(new bn(1)); + } + + isNegative() { + return this.value.isNeg(); + } + + isEven() { + return this.value.isEven(); + } + + abs() { + const res = this.clone(); + res.value = res.value.abs(); + return res; + } + + /** + * Get this value as a string + * @returns {String} this value. + */ + toString() { + return this.value.toString(); + } + + /** + * Get this value as an exact Number (max 53 bits) + * Fails if this value is too large + * @returns {Number} + */ + toNumber() { + return this.value.toNumber(); + } + + /** + * Get value of i-th bit + * @param {Number} i - Bit index + * @returns {Number} Bit value. + */ + getBit(i) { + return this.value.testn(i) ? 1 : 0; + } + + /** + * Compute bit length + * @returns {Number} Bit length. + */ + bitLength() { + return this.value.bitLength(); + } + + /** + * Compute byte length + * @returns {Number} Byte length. + */ + byteLength() { + return this.value.byteLength(); + } + + /** + * Get Uint8Array representation of this number + * @param {String} endian - Endianess of output array (defaults to 'be') + * @param {Number} length - Of output array + * @returns {Uint8Array} + */ + toUint8Array(endian = 'be', length) { + return this.value.toArrayLike(Uint8Array, endian, length); + } +} + +var bn_interface = /*#__PURE__*/Object.freeze({ + __proto__: null, + 'default': BigInteger$1 +}); + +var utils_1 = createCommonjsModule(function (module, exports) { + +var utils = exports; + +function toArray(msg, enc) { + if (Array.isArray(msg)) + return msg.slice(); + if (!msg) + return []; + var res = []; + if (typeof msg !== 'string') { + for (var i = 0; i < msg.length; i++) + res[i] = msg[i] | 0; + return res; + } + if (enc === 'hex') { + msg = msg.replace(/[^a-z0-9]+/ig, ''); + if (msg.length % 2 !== 0) + msg = '0' + msg; + for (var i = 0; i < msg.length; i += 2) + res.push(parseInt(msg[i] + msg[i + 1], 16)); + } else { + for (var i = 0; i < msg.length; i++) { + var c = msg.charCodeAt(i); + var hi = c >> 8; + var lo = c & 0xff; + if (hi) + res.push(hi, lo); + else + res.push(lo); + } + } + return res; +} +utils.toArray = toArray; + +function zero2(word) { + if (word.length === 1) + return '0' + word; + else + return word; +} +utils.zero2 = zero2; + +function toHex(msg) { + var res = ''; + for (var i = 0; i < msg.length; i++) + res += zero2(msg[i].toString(16)); + return res; +} +utils.toHex = toHex; + +utils.encode = function encode(arr, enc) { + if (enc === 'hex') + return toHex(arr); + else + return arr; +}; +}); + +var utils_1$1 = createCommonjsModule(function (module, exports) { + +var utils = exports; + + + + +utils.assert = minimalisticAssert; +utils.toArray = utils_1.toArray; +utils.zero2 = utils_1.zero2; +utils.toHex = utils_1.toHex; +utils.encode = utils_1.encode; + +// Represent num in a w-NAF form +function getNAF(num, w) { + var naf = []; + var ws = 1 << (w + 1); + var k = num.clone(); + while (k.cmpn(1) >= 0) { + var z; + if (k.isOdd()) { + var mod = k.andln(ws - 1); + if (mod > (ws >> 1) - 1) + z = (ws >> 1) - mod; + else + z = mod; + k.isubn(z); + } else { + z = 0; + } + naf.push(z); + + // Optimization, shift by word if possible + var shift = (k.cmpn(0) !== 0 && k.andln(ws - 1) === 0) ? (w + 1) : 1; + for (var i = 1; i < shift; i++) + naf.push(0); + k.iushrn(shift); + } + + return naf; +} +utils.getNAF = getNAF; + +// Represent k1, k2 in a Joint Sparse Form +function getJSF(k1, k2) { + var jsf = [ + [], + [] + ]; + + k1 = k1.clone(); + k2 = k2.clone(); + var d1 = 0; + var d2 = 0; + while (k1.cmpn(-d1) > 0 || k2.cmpn(-d2) > 0) { + + // First phase + var m14 = (k1.andln(3) + d1) & 3; + var m24 = (k2.andln(3) + d2) & 3; + if (m14 === 3) + m14 = -1; + if (m24 === 3) + m24 = -1; + var u1; + if ((m14 & 1) === 0) { + u1 = 0; + } else { + var m8 = (k1.andln(7) + d1) & 7; + if ((m8 === 3 || m8 === 5) && m24 === 2) + u1 = -m14; + else + u1 = m14; + } + jsf[0].push(u1); + + var u2; + if ((m24 & 1) === 0) { + u2 = 0; + } else { + var m8 = (k2.andln(7) + d2) & 7; + if ((m8 === 3 || m8 === 5) && m14 === 2) + u2 = -m24; + else + u2 = m24; + } + jsf[1].push(u2); + + // Second phase + if (2 * d1 === u1 + 1) + d1 = 1 - d1; + if (2 * d2 === u2 + 1) + d2 = 1 - d2; + k1.iushrn(1); + k2.iushrn(1); + } + + return jsf; +} +utils.getJSF = getJSF; + +function cachedProperty(obj, name, computer) { + var key = '_' + name; + obj.prototype[name] = function cachedProperty() { + return this[key] !== undefined ? this[key] : + this[key] = computer.call(this); + }; +} +utils.cachedProperty = cachedProperty; + +function parseBytes(bytes) { + return typeof bytes === 'string' ? utils.toArray(bytes, 'hex') : + bytes; +} +utils.parseBytes = parseBytes; + +function intFromLE(bytes) { + return new bn(bytes, 'hex', 'le'); +} +utils.intFromLE = intFromLE; +}); + +var r$1; + +var brorand = function rand(len) { + if (!r$1) + r$1 = new Rand(null); + + return r$1.generate(len); +}; + +function Rand(rand) { + this.rand = rand; +} +var Rand_1 = Rand; + +Rand.prototype.generate = function generate(len) { + return this._rand(len); +}; + +// Emulate crypto API using randy +Rand.prototype._rand = function _rand(n) { + if (this.rand.getBytes) + return this.rand.getBytes(n); + + var res = new Uint8Array(n); + for (var i = 0; i < res.length; i++) + res[i] = this.rand.getByte(); + return res; +}; + +if (typeof self === 'object') { + if (self.crypto && self.crypto.getRandomValues) { + // Modern browsers + Rand.prototype._rand = function _rand(n) { + var arr = new Uint8Array(n); + self.crypto.getRandomValues(arr); + return arr; + }; + } else if (self.msCrypto && self.msCrypto.getRandomValues) { + // IE + Rand.prototype._rand = function _rand(n) { + var arr = new Uint8Array(n); + self.msCrypto.getRandomValues(arr); + return arr; + }; + + // Safari's WebWorkers do not have `crypto` + } else if (typeof window === 'object') { + // Old junk + Rand.prototype._rand = function() { + throw new Error('Not implemented yet'); + }; + } +} else { + // Node.js or Web worker with no crypto support + try { + var crypto$2 = crypto__default['default']; + if (typeof crypto$2.randomBytes !== 'function') + throw new Error('Not supported'); + + Rand.prototype._rand = function _rand(n) { + return crypto$2.randomBytes(n); + }; + } catch (e) { + } +} +brorand.Rand = Rand_1; + +var getNAF = utils_1$1.getNAF; +var getJSF = utils_1$1.getJSF; +var assert$2 = utils_1$1.assert; + +function BaseCurve(type, conf) { + this.type = type; + this.p = new bn(conf.p, 16); + + // Use Montgomery, when there is no fast reduction for the prime + this.red = conf.prime ? bn.red(conf.prime) : bn.mont(this.p); + + // Useful for many curves + this.zero = new bn(0).toRed(this.red); + this.one = new bn(1).toRed(this.red); + this.two = new bn(2).toRed(this.red); + + // Curve configuration, optional + this.n = conf.n && new bn(conf.n, 16); + this.g = conf.g && this.pointFromJSON(conf.g, conf.gRed); + + // Temporary arrays + this._wnafT1 = new Array(4); + this._wnafT2 = new Array(4); + this._wnafT3 = new Array(4); + this._wnafT4 = new Array(4); + + // Generalized Greg Maxwell's trick + var adjustCount = this.n && this.p.div(this.n); + if (!adjustCount || adjustCount.cmpn(100) > 0) { + this.redN = null; + } else { + this._maxwellTrick = true; + this.redN = this.n.toRed(this.red); + } +} +var base = BaseCurve; + +BaseCurve.prototype.point = function point() { + throw new Error('Not implemented'); +}; + +BaseCurve.prototype.validate = function validate() { + throw new Error('Not implemented'); +}; + +BaseCurve.prototype._fixedNafMul = function _fixedNafMul(p, k) { + assert$2(p.precomputed); + var doubles = p._getDoubles(); + + var naf = getNAF(k, 1); + var I = (1 << (doubles.step + 1)) - (doubles.step % 2 === 0 ? 2 : 1); + I /= 3; + + // Translate into more windowed form + var repr = []; + for (var j = 0; j < naf.length; j += doubles.step) { + var nafW = 0; + for (var k = j + doubles.step - 1; k >= j; k--) + nafW = (nafW << 1) + naf[k]; + repr.push(nafW); + } + + var a = this.jpoint(null, null, null); + var b = this.jpoint(null, null, null); + for (var i = I; i > 0; i--) { + for (var j = 0; j < repr.length; j++) { + var nafW = repr[j]; + if (nafW === i) + b = b.mixedAdd(doubles.points[j]); + else if (nafW === -i) + b = b.mixedAdd(doubles.points[j].neg()); + } + a = a.add(b); + } + return a.toP(); +}; + +BaseCurve.prototype._wnafMul = function _wnafMul(p, k) { + var w = 4; + + // Precompute window + var nafPoints = p._getNAFPoints(w); + w = nafPoints.wnd; + var wnd = nafPoints.points; + + // Get NAF form + var naf = getNAF(k, w); + + // Add `this`*(N+1) for every w-NAF index + var acc = this.jpoint(null, null, null); + for (var i = naf.length - 1; i >= 0; i--) { + // Count zeroes + for (var k = 0; i >= 0 && naf[i] === 0; i--) + k++; + if (i >= 0) + k++; + acc = acc.dblp(k); + + if (i < 0) + break; + var z = naf[i]; + assert$2(z !== 0); + if (p.type === 'affine') { + // J +- P + if (z > 0) + acc = acc.mixedAdd(wnd[(z - 1) >> 1]); + else + acc = acc.mixedAdd(wnd[(-z - 1) >> 1].neg()); + } else { + // J +- J + if (z > 0) + acc = acc.add(wnd[(z - 1) >> 1]); + else + acc = acc.add(wnd[(-z - 1) >> 1].neg()); + } + } + return p.type === 'affine' ? acc.toP() : acc; +}; + +BaseCurve.prototype._wnafMulAdd = function _wnafMulAdd(defW, + points, + coeffs, + len, + jacobianResult) { + var wndWidth = this._wnafT1; + var wnd = this._wnafT2; + var naf = this._wnafT3; + + // Fill all arrays + var max = 0; + for (var i = 0; i < len; i++) { + var p = points[i]; + var nafPoints = p._getNAFPoints(defW); + wndWidth[i] = nafPoints.wnd; + wnd[i] = nafPoints.points; + } + + // Comb small window NAFs + for (var i = len - 1; i >= 1; i -= 2) { + var a = i - 1; + var b = i; + if (wndWidth[a] !== 1 || wndWidth[b] !== 1) { + naf[a] = getNAF(coeffs[a], wndWidth[a]); + naf[b] = getNAF(coeffs[b], wndWidth[b]); + max = Math.max(naf[a].length, max); + max = Math.max(naf[b].length, max); + continue; + } + + var comb = [ + points[a], /* 1 */ + null, /* 3 */ + null, /* 5 */ + points[b] /* 7 */ + ]; + + // Try to avoid Projective points, if possible + if (points[a].y.cmp(points[b].y) === 0) { + comb[1] = points[a].add(points[b]); + comb[2] = points[a].toJ().mixedAdd(points[b].neg()); + } else if (points[a].y.cmp(points[b].y.redNeg()) === 0) { + comb[1] = points[a].toJ().mixedAdd(points[b]); + comb[2] = points[a].add(points[b].neg()); + } else { + comb[1] = points[a].toJ().mixedAdd(points[b]); + comb[2] = points[a].toJ().mixedAdd(points[b].neg()); + } + + var index = [ + -3, /* -1 -1 */ + -1, /* -1 0 */ + -5, /* -1 1 */ + -7, /* 0 -1 */ + 0, /* 0 0 */ + 7, /* 0 1 */ + 5, /* 1 -1 */ + 1, /* 1 0 */ + 3 /* 1 1 */ + ]; + + var jsf = getJSF(coeffs[a], coeffs[b]); + max = Math.max(jsf[0].length, max); + naf[a] = new Array(max); + naf[b] = new Array(max); + for (var j = 0; j < max; j++) { + var ja = jsf[0][j] | 0; + var jb = jsf[1][j] | 0; + + naf[a][j] = index[(ja + 1) * 3 + (jb + 1)]; + naf[b][j] = 0; + wnd[a] = comb; + } + } + + var acc = this.jpoint(null, null, null); + var tmp = this._wnafT4; + for (var i = max; i >= 0; i--) { + var k = 0; + + while (i >= 0) { + var zero = true; + for (var j = 0; j < len; j++) { + tmp[j] = naf[j][i] | 0; + if (tmp[j] !== 0) + zero = false; + } + if (!zero) + break; + k++; + i--; + } + if (i >= 0) + k++; + acc = acc.dblp(k); + if (i < 0) + break; + + for (var j = 0; j < len; j++) { + var z = tmp[j]; + var p; + if (z === 0) + continue; + else if (z > 0) + p = wnd[j][(z - 1) >> 1]; + else if (z < 0) + p = wnd[j][(-z - 1) >> 1].neg(); + + if (p.type === 'affine') + acc = acc.mixedAdd(p); + else + acc = acc.add(p); + } + } + // Zeroify references + for (var i = 0; i < len; i++) + wnd[i] = null; + + if (jacobianResult) + return acc; + else + return acc.toP(); +}; + +function BasePoint(curve, type) { + this.curve = curve; + this.type = type; + this.precomputed = null; +} +BaseCurve.BasePoint = BasePoint; + +BasePoint.prototype.eq = function eq(/*other*/) { + throw new Error('Not implemented'); +}; + +BasePoint.prototype.validate = function validate() { + return this.curve.validate(this); +}; + +BaseCurve.prototype.decodePoint = function decodePoint(bytes, enc) { + bytes = utils_1$1.toArray(bytes, enc); + + var len = this.p.byteLength(); + + // uncompressed, hybrid-odd, hybrid-even + if ((bytes[0] === 0x04 || bytes[0] === 0x06 || bytes[0] === 0x07) && + bytes.length - 1 === 2 * len) { + if (bytes[0] === 0x06) + assert$2(bytes[bytes.length - 1] % 2 === 0); + else if (bytes[0] === 0x07) + assert$2(bytes[bytes.length - 1] % 2 === 1); + + var res = this.point(bytes.slice(1, 1 + len), + bytes.slice(1 + len, 1 + 2 * len)); + + return res; + } else if ((bytes[0] === 0x02 || bytes[0] === 0x03) && + bytes.length - 1 === len) { + return this.pointFromX(bytes.slice(1, 1 + len), bytes[0] === 0x03); + } + throw new Error('Unknown point format'); +}; + +BasePoint.prototype.encodeCompressed = function encodeCompressed(enc) { + return this.encode(enc, true); +}; + +BasePoint.prototype._encode = function _encode(compact) { + var len = this.curve.p.byteLength(); + var x = this.getX().toArray('be', len); + + if (compact) + return [ this.getY().isEven() ? 0x02 : 0x03 ].concat(x); + + return [ 0x04 ].concat(x, this.getY().toArray('be', len)) ; +}; + +BasePoint.prototype.encode = function encode(enc, compact) { + return utils_1$1.encode(this._encode(compact), enc); +}; + +BasePoint.prototype.precompute = function precompute(power) { + if (this.precomputed) + return this; + + var precomputed = { + doubles: null, + naf: null, + beta: null + }; + precomputed.naf = this._getNAFPoints(8); + precomputed.doubles = this._getDoubles(4, power); + precomputed.beta = this._getBeta(); + this.precomputed = precomputed; + + return this; +}; + +BasePoint.prototype._hasDoubles = function _hasDoubles(k) { + if (!this.precomputed) + return false; + + var doubles = this.precomputed.doubles; + if (!doubles) + return false; + + return doubles.points.length >= Math.ceil((k.bitLength() + 1) / doubles.step); +}; + +BasePoint.prototype._getDoubles = function _getDoubles(step, power) { + if (this.precomputed && this.precomputed.doubles) + return this.precomputed.doubles; + + var doubles = [ this ]; + var acc = this; + for (var i = 0; i < power; i += step) { + for (var j = 0; j < step; j++) + acc = acc.dbl(); + doubles.push(acc); + } + return { + step: step, + points: doubles + }; +}; + +BasePoint.prototype._getNAFPoints = function _getNAFPoints(wnd) { + if (this.precomputed && this.precomputed.naf) + return this.precomputed.naf; + + var res = [ this ]; + var max = (1 << wnd) - 1; + var dbl = max === 1 ? null : this.dbl(); + for (var i = 1; i < max; i++) + res[i] = res[i - 1].add(dbl); + return { + wnd: wnd, + points: res + }; +}; + +BasePoint.prototype._getBeta = function _getBeta() { + return null; +}; + +BasePoint.prototype.dblp = function dblp(k) { + var r = this; + for (var i = 0; i < k; i++) + r = r.dbl(); + return r; +}; + +var assert$3 = utils_1$1.assert; + +function ShortCurve(conf) { + base.call(this, 'short', conf); + + this.a = new bn(conf.a, 16).toRed(this.red); + this.b = new bn(conf.b, 16).toRed(this.red); + this.tinv = this.two.redInvm(); + + this.zeroA = this.a.fromRed().cmpn(0) === 0; + this.threeA = this.a.fromRed().sub(this.p).cmpn(-3) === 0; + + // If the curve is endomorphic, precalculate beta and lambda + this.endo = this._getEndomorphism(conf); + this._endoWnafT1 = new Array(4); + this._endoWnafT2 = new Array(4); +} +inherits(ShortCurve, base); +var short_1 = ShortCurve; + +ShortCurve.prototype._getEndomorphism = function _getEndomorphism(conf) { + // No efficient endomorphism + if (!this.zeroA || !this.g || !this.n || this.p.modn(3) !== 1) + return; + + // Compute beta and lambda, that lambda * P = (beta * Px; Py) + var beta; + var lambda; + if (conf.beta) { + beta = new bn(conf.beta, 16).toRed(this.red); + } else { + var betas = this._getEndoRoots(this.p); + // Choose the smallest beta + beta = betas[0].cmp(betas[1]) < 0 ? betas[0] : betas[1]; + beta = beta.toRed(this.red); + } + if (conf.lambda) { + lambda = new bn(conf.lambda, 16); + } else { + // Choose the lambda that is matching selected beta + var lambdas = this._getEndoRoots(this.n); + if (this.g.mul(lambdas[0]).x.cmp(this.g.x.redMul(beta)) === 0) { + lambda = lambdas[0]; + } else { + lambda = lambdas[1]; + assert$3(this.g.mul(lambda).x.cmp(this.g.x.redMul(beta)) === 0); + } + } + + // Get basis vectors, used for balanced length-two representation + var basis; + if (conf.basis) { + basis = conf.basis.map(function(vec) { + return { + a: new bn(vec.a, 16), + b: new bn(vec.b, 16) + }; + }); + } else { + basis = this._getEndoBasis(lambda); + } + + return { + beta: beta, + lambda: lambda, + basis: basis + }; +}; + +ShortCurve.prototype._getEndoRoots = function _getEndoRoots(num) { + // Find roots of for x^2 + x + 1 in F + // Root = (-1 +- Sqrt(-3)) / 2 + // + var red = num === this.p ? this.red : bn.mont(num); + var tinv = new bn(2).toRed(red).redInvm(); + var ntinv = tinv.redNeg(); + + var s = new bn(3).toRed(red).redNeg().redSqrt().redMul(tinv); + + var l1 = ntinv.redAdd(s).fromRed(); + var l2 = ntinv.redSub(s).fromRed(); + return [ l1, l2 ]; +}; + +ShortCurve.prototype._getEndoBasis = function _getEndoBasis(lambda) { + // aprxSqrt >= sqrt(this.n) + var aprxSqrt = this.n.ushrn(Math.floor(this.n.bitLength() / 2)); + + // 3.74 + // Run EGCD, until r(L + 1) < aprxSqrt + var u = lambda; + var v = this.n.clone(); + var x1 = new bn(1); + var y1 = new bn(0); + var x2 = new bn(0); + var y2 = new bn(1); + + // NOTE: all vectors are roots of: a + b * lambda = 0 (mod n) + var a0; + var b0; + // First vector + var a1; + var b1; + // Second vector + var a2; + var b2; + + var prevR; + var i = 0; + var r; + var x; + while (u.cmpn(0) !== 0) { + var q = v.div(u); + r = v.sub(q.mul(u)); + x = x2.sub(q.mul(x1)); + var y = y2.sub(q.mul(y1)); + + if (!a1 && r.cmp(aprxSqrt) < 0) { + a0 = prevR.neg(); + b0 = x1; + a1 = r.neg(); + b1 = x; + } else if (a1 && ++i === 2) { + break; + } + prevR = r; + + v = u; + u = r; + x2 = x1; + x1 = x; + y2 = y1; + y1 = y; + } + a2 = r.neg(); + b2 = x; + + var len1 = a1.sqr().add(b1.sqr()); + var len2 = a2.sqr().add(b2.sqr()); + if (len2.cmp(len1) >= 0) { + a2 = a0; + b2 = b0; + } + + // Normalize signs + if (a1.negative) { + a1 = a1.neg(); + b1 = b1.neg(); + } + if (a2.negative) { + a2 = a2.neg(); + b2 = b2.neg(); + } + + return [ + { a: a1, b: b1 }, + { a: a2, b: b2 } + ]; +}; + +ShortCurve.prototype._endoSplit = function _endoSplit(k) { + var basis = this.endo.basis; + var v1 = basis[0]; + var v2 = basis[1]; + + var c1 = v2.b.mul(k).divRound(this.n); + var c2 = v1.b.neg().mul(k).divRound(this.n); + + var p1 = c1.mul(v1.a); + var p2 = c2.mul(v2.a); + var q1 = c1.mul(v1.b); + var q2 = c2.mul(v2.b); + + // Calculate answer + var k1 = k.sub(p1).sub(p2); + var k2 = q1.add(q2).neg(); + return { k1: k1, k2: k2 }; +}; + +ShortCurve.prototype.pointFromX = function pointFromX(x, odd) { + x = new bn(x, 16); + if (!x.red) + x = x.toRed(this.red); + + var y2 = x.redSqr().redMul(x).redIAdd(x.redMul(this.a)).redIAdd(this.b); + var y = y2.redSqrt(); + if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) + throw new Error('invalid point'); + + // XXX Is there any way to tell if the number is odd without converting it + // to non-red form? + var isOdd = y.fromRed().isOdd(); + if (odd && !isOdd || !odd && isOdd) + y = y.redNeg(); + + return this.point(x, y); +}; + +ShortCurve.prototype.validate = function validate(point) { + if (point.inf) + return true; + + var x = point.x; + var y = point.y; + + var ax = this.a.redMul(x); + var rhs = x.redSqr().redMul(x).redIAdd(ax).redIAdd(this.b); + return y.redSqr().redISub(rhs).cmpn(0) === 0; +}; + +ShortCurve.prototype._endoWnafMulAdd = + function _endoWnafMulAdd(points, coeffs, jacobianResult) { + var npoints = this._endoWnafT1; + var ncoeffs = this._endoWnafT2; + for (var i = 0; i < points.length; i++) { + var split = this._endoSplit(coeffs[i]); + var p = points[i]; + var beta = p._getBeta(); + + if (split.k1.negative) { + split.k1.ineg(); + p = p.neg(true); + } + if (split.k2.negative) { + split.k2.ineg(); + beta = beta.neg(true); + } + + npoints[i * 2] = p; + npoints[i * 2 + 1] = beta; + ncoeffs[i * 2] = split.k1; + ncoeffs[i * 2 + 1] = split.k2; + } + var res = this._wnafMulAdd(1, npoints, ncoeffs, i * 2, jacobianResult); + + // Clean-up references to points and coefficients + for (var j = 0; j < i * 2; j++) { + npoints[j] = null; + ncoeffs[j] = null; + } + return res; +}; + +function Point(curve, x, y, isRed) { + base.BasePoint.call(this, curve, 'affine'); + if (x === null && y === null) { + this.x = null; + this.y = null; + this.inf = true; + } else { + this.x = new bn(x, 16); + this.y = new bn(y, 16); + // Force redgomery representation when loading from JSON + if (isRed) { + this.x.forceRed(this.curve.red); + this.y.forceRed(this.curve.red); + } + if (!this.x.red) + this.x = this.x.toRed(this.curve.red); + if (!this.y.red) + this.y = this.y.toRed(this.curve.red); + this.inf = false; + } +} +inherits(Point, base.BasePoint); + +ShortCurve.prototype.point = function point(x, y, isRed) { + return new Point(this, x, y, isRed); +}; + +ShortCurve.prototype.pointFromJSON = function pointFromJSON(obj, red) { + return Point.fromJSON(this, obj, red); +}; + +Point.prototype._getBeta = function _getBeta() { + if (!this.curve.endo) + return; + + var pre = this.precomputed; + if (pre && pre.beta) + return pre.beta; + + var beta = this.curve.point(this.x.redMul(this.curve.endo.beta), this.y); + if (pre) { + var curve = this.curve; + var endoMul = function(p) { + return curve.point(p.x.redMul(curve.endo.beta), p.y); + }; + pre.beta = beta; + beta.precomputed = { + beta: null, + naf: pre.naf && { + wnd: pre.naf.wnd, + points: pre.naf.points.map(endoMul) + }, + doubles: pre.doubles && { + step: pre.doubles.step, + points: pre.doubles.points.map(endoMul) + } + }; + } + return beta; +}; + +Point.prototype.toJSON = function toJSON() { + if (!this.precomputed) + return [ this.x, this.y ]; + + return [ this.x, this.y, this.precomputed && { + doubles: this.precomputed.doubles && { + step: this.precomputed.doubles.step, + points: this.precomputed.doubles.points.slice(1) + }, + naf: this.precomputed.naf && { + wnd: this.precomputed.naf.wnd, + points: this.precomputed.naf.points.slice(1) + } + } ]; +}; + +Point.fromJSON = function fromJSON(curve, obj, red) { + if (typeof obj === 'string') + obj = JSON.parse(obj); + var res = curve.point(obj[0], obj[1], red); + if (!obj[2]) + return res; + + function obj2point(obj) { + return curve.point(obj[0], obj[1], red); + } + + var pre = obj[2]; + res.precomputed = { + beta: null, + doubles: pre.doubles && { + step: pre.doubles.step, + points: [ res ].concat(pre.doubles.points.map(obj2point)) + }, + naf: pre.naf && { + wnd: pre.naf.wnd, + points: [ res ].concat(pre.naf.points.map(obj2point)) + } + }; + return res; +}; + +Point.prototype.inspect = function inspect() { + if (this.isInfinity()) + return ''; + return ''; +}; + +Point.prototype.isInfinity = function isInfinity() { + return this.inf; +}; + +Point.prototype.add = function add(p) { + // O + P = P + if (this.inf) + return p; + + // P + O = P + if (p.inf) + return this; + + // P + P = 2P + if (this.eq(p)) + return this.dbl(); + + // P + (-P) = O + if (this.neg().eq(p)) + return this.curve.point(null, null); + + // P + Q = O + if (this.x.cmp(p.x) === 0) + return this.curve.point(null, null); + + var c = this.y.redSub(p.y); + if (c.cmpn(0) !== 0) + c = c.redMul(this.x.redSub(p.x).redInvm()); + var nx = c.redSqr().redISub(this.x).redISub(p.x); + var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); + return this.curve.point(nx, ny); +}; + +Point.prototype.dbl = function dbl() { + if (this.inf) + return this; + + // 2P = O + var ys1 = this.y.redAdd(this.y); + if (ys1.cmpn(0) === 0) + return this.curve.point(null, null); + + var a = this.curve.a; + + var x2 = this.x.redSqr(); + var dyinv = ys1.redInvm(); + var c = x2.redAdd(x2).redIAdd(x2).redIAdd(a).redMul(dyinv); + + var nx = c.redSqr().redISub(this.x.redAdd(this.x)); + var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); + return this.curve.point(nx, ny); +}; + +Point.prototype.getX = function getX() { + return this.x.fromRed(); +}; + +Point.prototype.getY = function getY() { + return this.y.fromRed(); +}; + +Point.prototype.mul = function mul(k) { + k = new bn(k, 16); + if (this.isInfinity()) + return this; + else if (this._hasDoubles(k)) + return this.curve._fixedNafMul(this, k); + else if (this.curve.endo) + return this.curve._endoWnafMulAdd([ this ], [ k ]); + else + return this.curve._wnafMul(this, k); +}; + +Point.prototype.mulAdd = function mulAdd(k1, p2, k2) { + var points = [ this, p2 ]; + var coeffs = [ k1, k2 ]; + if (this.curve.endo) + return this.curve._endoWnafMulAdd(points, coeffs); + else + return this.curve._wnafMulAdd(1, points, coeffs, 2); +}; + +Point.prototype.jmulAdd = function jmulAdd(k1, p2, k2) { + var points = [ this, p2 ]; + var coeffs = [ k1, k2 ]; + if (this.curve.endo) + return this.curve._endoWnafMulAdd(points, coeffs, true); + else + return this.curve._wnafMulAdd(1, points, coeffs, 2, true); +}; + +Point.prototype.eq = function eq(p) { + return this === p || + this.inf === p.inf && + (this.inf || this.x.cmp(p.x) === 0 && this.y.cmp(p.y) === 0); +}; + +Point.prototype.neg = function neg(_precompute) { + if (this.inf) + return this; + + var res = this.curve.point(this.x, this.y.redNeg()); + if (_precompute && this.precomputed) { + var pre = this.precomputed; + var negate = function(p) { + return p.neg(); + }; + res.precomputed = { + naf: pre.naf && { + wnd: pre.naf.wnd, + points: pre.naf.points.map(negate) + }, + doubles: pre.doubles && { + step: pre.doubles.step, + points: pre.doubles.points.map(negate) + } + }; + } + return res; +}; + +Point.prototype.toJ = function toJ() { + if (this.inf) + return this.curve.jpoint(null, null, null); + + var res = this.curve.jpoint(this.x, this.y, this.curve.one); + return res; +}; + +function JPoint(curve, x, y, z) { + base.BasePoint.call(this, curve, 'jacobian'); + if (x === null && y === null && z === null) { + this.x = this.curve.one; + this.y = this.curve.one; + this.z = new bn(0); + } else { + this.x = new bn(x, 16); + this.y = new bn(y, 16); + this.z = new bn(z, 16); + } + if (!this.x.red) + this.x = this.x.toRed(this.curve.red); + if (!this.y.red) + this.y = this.y.toRed(this.curve.red); + if (!this.z.red) + this.z = this.z.toRed(this.curve.red); + + this.zOne = this.z === this.curve.one; +} +inherits(JPoint, base.BasePoint); + +ShortCurve.prototype.jpoint = function jpoint(x, y, z) { + return new JPoint(this, x, y, z); +}; + +JPoint.prototype.toP = function toP() { + if (this.isInfinity()) + return this.curve.point(null, null); + + var zinv = this.z.redInvm(); + var zinv2 = zinv.redSqr(); + var ax = this.x.redMul(zinv2); + var ay = this.y.redMul(zinv2).redMul(zinv); + + return this.curve.point(ax, ay); +}; + +JPoint.prototype.neg = function neg() { + return this.curve.jpoint(this.x, this.y.redNeg(), this.z); +}; + +JPoint.prototype.add = function add(p) { + // O + P = P + if (this.isInfinity()) + return p; + + // P + O = P + if (p.isInfinity()) + return this; + + // 12M + 4S + 7A + var pz2 = p.z.redSqr(); + var z2 = this.z.redSqr(); + var u1 = this.x.redMul(pz2); + var u2 = p.x.redMul(z2); + var s1 = this.y.redMul(pz2.redMul(p.z)); + var s2 = p.y.redMul(z2.redMul(this.z)); + + var h = u1.redSub(u2); + var r = s1.redSub(s2); + if (h.cmpn(0) === 0) { + if (r.cmpn(0) !== 0) + return this.curve.jpoint(null, null, null); + else + return this.dbl(); + } + + var h2 = h.redSqr(); + var h3 = h2.redMul(h); + var v = u1.redMul(h2); + + var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); + var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); + var nz = this.z.redMul(p.z).redMul(h); + + return this.curve.jpoint(nx, ny, nz); +}; + +JPoint.prototype.mixedAdd = function mixedAdd(p) { + // O + P = P + if (this.isInfinity()) + return p.toJ(); + + // P + O = P + if (p.isInfinity()) + return this; + + // 8M + 3S + 7A + var z2 = this.z.redSqr(); + var u1 = this.x; + var u2 = p.x.redMul(z2); + var s1 = this.y; + var s2 = p.y.redMul(z2).redMul(this.z); + + var h = u1.redSub(u2); + var r = s1.redSub(s2); + if (h.cmpn(0) === 0) { + if (r.cmpn(0) !== 0) + return this.curve.jpoint(null, null, null); + else + return this.dbl(); + } + + var h2 = h.redSqr(); + var h3 = h2.redMul(h); + var v = u1.redMul(h2); + + var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); + var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); + var nz = this.z.redMul(h); + + return this.curve.jpoint(nx, ny, nz); +}; + +JPoint.prototype.dblp = function dblp(pow) { + if (pow === 0) + return this; + if (this.isInfinity()) + return this; + if (!pow) + return this.dbl(); + + if (this.curve.zeroA || this.curve.threeA) { + var r = this; + for (var i = 0; i < pow; i++) + r = r.dbl(); + return r; + } + + // 1M + 2S + 1A + N * (4S + 5M + 8A) + // N = 1 => 6M + 6S + 9A + var a = this.curve.a; + var tinv = this.curve.tinv; + + var jx = this.x; + var jy = this.y; + var jz = this.z; + var jz4 = jz.redSqr().redSqr(); + + // Reuse results + var jyd = jy.redAdd(jy); + for (var i = 0; i < pow; i++) { + var jx2 = jx.redSqr(); + var jyd2 = jyd.redSqr(); + var jyd4 = jyd2.redSqr(); + var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); + + var t1 = jx.redMul(jyd2); + var nx = c.redSqr().redISub(t1.redAdd(t1)); + var t2 = t1.redISub(nx); + var dny = c.redMul(t2); + dny = dny.redIAdd(dny).redISub(jyd4); + var nz = jyd.redMul(jz); + if (i + 1 < pow) + jz4 = jz4.redMul(jyd4); + + jx = nx; + jz = nz; + jyd = dny; + } + + return this.curve.jpoint(jx, jyd.redMul(tinv), jz); +}; + +JPoint.prototype.dbl = function dbl() { + if (this.isInfinity()) + return this; + + if (this.curve.zeroA) + return this._zeroDbl(); + else if (this.curve.threeA) + return this._threeDbl(); + else + return this._dbl(); +}; + +JPoint.prototype._zeroDbl = function _zeroDbl() { + var nx; + var ny; + var nz; + // Z = 1 + if (this.zOne) { + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html + // #doubling-mdbl-2007-bl + // 1M + 5S + 14A + + // XX = X1^2 + var xx = this.x.redSqr(); + // YY = Y1^2 + var yy = this.y.redSqr(); + // YYYY = YY^2 + var yyyy = yy.redSqr(); + // S = 2 * ((X1 + YY)^2 - XX - YYYY) + var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); + s = s.redIAdd(s); + // M = 3 * XX + a; a = 0 + var m = xx.redAdd(xx).redIAdd(xx); + // T = M ^ 2 - 2*S + var t = m.redSqr().redISub(s).redISub(s); + + // 8 * YYYY + var yyyy8 = yyyy.redIAdd(yyyy); + yyyy8 = yyyy8.redIAdd(yyyy8); + yyyy8 = yyyy8.redIAdd(yyyy8); + + // X3 = T + nx = t; + // Y3 = M * (S - T) - 8 * YYYY + ny = m.redMul(s.redISub(t)).redISub(yyyy8); + // Z3 = 2*Y1 + nz = this.y.redAdd(this.y); + } else { + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html + // #doubling-dbl-2009-l + // 2M + 5S + 13A + + // A = X1^2 + var a = this.x.redSqr(); + // B = Y1^2 + var b = this.y.redSqr(); + // C = B^2 + var c = b.redSqr(); + // D = 2 * ((X1 + B)^2 - A - C) + var d = this.x.redAdd(b).redSqr().redISub(a).redISub(c); + d = d.redIAdd(d); + // E = 3 * A + var e = a.redAdd(a).redIAdd(a); + // F = E^2 + var f = e.redSqr(); + + // 8 * C + var c8 = c.redIAdd(c); + c8 = c8.redIAdd(c8); + c8 = c8.redIAdd(c8); + + // X3 = F - 2 * D + nx = f.redISub(d).redISub(d); + // Y3 = E * (D - X3) - 8 * C + ny = e.redMul(d.redISub(nx)).redISub(c8); + // Z3 = 2 * Y1 * Z1 + nz = this.y.redMul(this.z); + nz = nz.redIAdd(nz); + } + + return this.curve.jpoint(nx, ny, nz); +}; + +JPoint.prototype._threeDbl = function _threeDbl() { + var nx; + var ny; + var nz; + // Z = 1 + if (this.zOne) { + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html + // #doubling-mdbl-2007-bl + // 1M + 5S + 15A + + // XX = X1^2 + var xx = this.x.redSqr(); + // YY = Y1^2 + var yy = this.y.redSqr(); + // YYYY = YY^2 + var yyyy = yy.redSqr(); + // S = 2 * ((X1 + YY)^2 - XX - YYYY) + var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); + s = s.redIAdd(s); + // M = 3 * XX + a + var m = xx.redAdd(xx).redIAdd(xx).redIAdd(this.curve.a); + // T = M^2 - 2 * S + var t = m.redSqr().redISub(s).redISub(s); + // X3 = T + nx = t; + // Y3 = M * (S - T) - 8 * YYYY + var yyyy8 = yyyy.redIAdd(yyyy); + yyyy8 = yyyy8.redIAdd(yyyy8); + yyyy8 = yyyy8.redIAdd(yyyy8); + ny = m.redMul(s.redISub(t)).redISub(yyyy8); + // Z3 = 2 * Y1 + nz = this.y.redAdd(this.y); + } else { + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b + // 3M + 5S + + // delta = Z1^2 + var delta = this.z.redSqr(); + // gamma = Y1^2 + var gamma = this.y.redSqr(); + // beta = X1 * gamma + var beta = this.x.redMul(gamma); + // alpha = 3 * (X1 - delta) * (X1 + delta) + var alpha = this.x.redSub(delta).redMul(this.x.redAdd(delta)); + alpha = alpha.redAdd(alpha).redIAdd(alpha); + // X3 = alpha^2 - 8 * beta + var beta4 = beta.redIAdd(beta); + beta4 = beta4.redIAdd(beta4); + var beta8 = beta4.redAdd(beta4); + nx = alpha.redSqr().redISub(beta8); + // Z3 = (Y1 + Z1)^2 - gamma - delta + nz = this.y.redAdd(this.z).redSqr().redISub(gamma).redISub(delta); + // Y3 = alpha * (4 * beta - X3) - 8 * gamma^2 + var ggamma8 = gamma.redSqr(); + ggamma8 = ggamma8.redIAdd(ggamma8); + ggamma8 = ggamma8.redIAdd(ggamma8); + ggamma8 = ggamma8.redIAdd(ggamma8); + ny = alpha.redMul(beta4.redISub(nx)).redISub(ggamma8); + } + + return this.curve.jpoint(nx, ny, nz); +}; + +JPoint.prototype._dbl = function _dbl() { + var a = this.curve.a; + + // 4M + 6S + 10A + var jx = this.x; + var jy = this.y; + var jz = this.z; + var jz4 = jz.redSqr().redSqr(); + + var jx2 = jx.redSqr(); + var jy2 = jy.redSqr(); + + var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); + + var jxd4 = jx.redAdd(jx); + jxd4 = jxd4.redIAdd(jxd4); + var t1 = jxd4.redMul(jy2); + var nx = c.redSqr().redISub(t1.redAdd(t1)); + var t2 = t1.redISub(nx); + + var jyd8 = jy2.redSqr(); + jyd8 = jyd8.redIAdd(jyd8); + jyd8 = jyd8.redIAdd(jyd8); + jyd8 = jyd8.redIAdd(jyd8); + var ny = c.redMul(t2).redISub(jyd8); + var nz = jy.redAdd(jy).redMul(jz); + + return this.curve.jpoint(nx, ny, nz); +}; + +JPoint.prototype.trpl = function trpl() { + if (!this.curve.zeroA) + return this.dbl().add(this); + + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#tripling-tpl-2007-bl + // 5M + 10S + ... + + // XX = X1^2 + var xx = this.x.redSqr(); + // YY = Y1^2 + var yy = this.y.redSqr(); + // ZZ = Z1^2 + var zz = this.z.redSqr(); + // YYYY = YY^2 + var yyyy = yy.redSqr(); + // M = 3 * XX + a * ZZ2; a = 0 + var m = xx.redAdd(xx).redIAdd(xx); + // MM = M^2 + var mm = m.redSqr(); + // E = 6 * ((X1 + YY)^2 - XX - YYYY) - MM + var e = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); + e = e.redIAdd(e); + e = e.redAdd(e).redIAdd(e); + e = e.redISub(mm); + // EE = E^2 + var ee = e.redSqr(); + // T = 16*YYYY + var t = yyyy.redIAdd(yyyy); + t = t.redIAdd(t); + t = t.redIAdd(t); + t = t.redIAdd(t); + // U = (M + E)^2 - MM - EE - T + var u = m.redIAdd(e).redSqr().redISub(mm).redISub(ee).redISub(t); + // X3 = 4 * (X1 * EE - 4 * YY * U) + var yyu4 = yy.redMul(u); + yyu4 = yyu4.redIAdd(yyu4); + yyu4 = yyu4.redIAdd(yyu4); + var nx = this.x.redMul(ee).redISub(yyu4); + nx = nx.redIAdd(nx); + nx = nx.redIAdd(nx); + // Y3 = 8 * Y1 * (U * (T - U) - E * EE) + var ny = this.y.redMul(u.redMul(t.redISub(u)).redISub(e.redMul(ee))); + ny = ny.redIAdd(ny); + ny = ny.redIAdd(ny); + ny = ny.redIAdd(ny); + // Z3 = (Z1 + E)^2 - ZZ - EE + var nz = this.z.redAdd(e).redSqr().redISub(zz).redISub(ee); + + return this.curve.jpoint(nx, ny, nz); +}; + +JPoint.prototype.mul = function mul(k, kbase) { + k = new bn(k, kbase); + + return this.curve._wnafMul(this, k); +}; + +JPoint.prototype.eq = function eq(p) { + if (p.type === 'affine') + return this.eq(p.toJ()); + + if (this === p) + return true; + + // x1 * z2^2 == x2 * z1^2 + var z2 = this.z.redSqr(); + var pz2 = p.z.redSqr(); + if (this.x.redMul(pz2).redISub(p.x.redMul(z2)).cmpn(0) !== 0) + return false; + + // y1 * z2^3 == y2 * z1^3 + var z3 = z2.redMul(this.z); + var pz3 = pz2.redMul(p.z); + return this.y.redMul(pz3).redISub(p.y.redMul(z3)).cmpn(0) === 0; +}; + +JPoint.prototype.eqXToP = function eqXToP(x) { + var zs = this.z.redSqr(); + var rx = x.toRed(this.curve.red).redMul(zs); + if (this.x.cmp(rx) === 0) + return true; + + var xc = x.clone(); + var t = this.curve.redN.redMul(zs); + for (;;) { + xc.iadd(this.curve.n); + if (xc.cmp(this.curve.p) >= 0) + return false; + + rx.redIAdd(t); + if (this.x.cmp(rx) === 0) + return true; + } +}; + +JPoint.prototype.inspect = function inspect() { + if (this.isInfinity()) + return ''; + return ''; +}; + +JPoint.prototype.isInfinity = function isInfinity() { + // XXX This code assumes that zero is always zero in red + return this.z.cmpn(0) === 0; +}; + +function MontCurve(conf) { + base.call(this, 'mont', conf); + + this.a = new bn(conf.a, 16).toRed(this.red); + this.b = new bn(conf.b, 16).toRed(this.red); + this.i4 = new bn(4).toRed(this.red).redInvm(); + this.two = new bn(2).toRed(this.red); + // Note: this implementation is according to the original paper + // by P. Montgomery, NOT the one by D. J. Bernstein. + this.a24 = this.i4.redMul(this.a.redAdd(this.two)); +} +inherits(MontCurve, base); +var mont = MontCurve; + +MontCurve.prototype.validate = function validate(point) { + var x = point.normalize().x; + var x2 = x.redSqr(); + var rhs = x2.redMul(x).redAdd(x2.redMul(this.a)).redAdd(x); + var y = rhs.redSqrt(); + + return y.redSqr().cmp(rhs) === 0; +}; + +function Point$1(curve, x, z) { + base.BasePoint.call(this, curve, 'projective'); + if (x === null && z === null) { + this.x = this.curve.one; + this.z = this.curve.zero; + } else { + this.x = new bn(x, 16); + this.z = new bn(z, 16); + if (!this.x.red) + this.x = this.x.toRed(this.curve.red); + if (!this.z.red) + this.z = this.z.toRed(this.curve.red); + } +} +inherits(Point$1, base.BasePoint); + +MontCurve.prototype.decodePoint = function decodePoint(bytes, enc) { + var bytes = utils_1$1.toArray(bytes, enc); + + // TODO Curve448 + // Montgomery curve points must be represented in the compressed format + // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B + if (bytes.length === 33 && bytes[0] === 0x40) + bytes = bytes.slice(1, 33).reverse(); // point must be little-endian + if (bytes.length !== 32) + throw new Error('Unknown point compression format'); + return this.point(bytes, 1); +}; + +MontCurve.prototype.point = function point(x, z) { + return new Point$1(this, x, z); +}; + +MontCurve.prototype.pointFromJSON = function pointFromJSON(obj) { + return Point$1.fromJSON(this, obj); +}; + +Point$1.prototype.precompute = function precompute() { + // No-op +}; + +Point$1.prototype._encode = function _encode(compact) { + var len = this.curve.p.byteLength(); + + // Note: the output should always be little-endian + // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B + if (compact) { + return [ 0x40 ].concat(this.getX().toArray('le', len)); + } else { + return this.getX().toArray('be', len); + } +}; + +Point$1.fromJSON = function fromJSON(curve, obj) { + return new Point$1(curve, obj[0], obj[1] || curve.one); +}; + +Point$1.prototype.inspect = function inspect() { + if (this.isInfinity()) + return ''; + return ''; +}; + +Point$1.prototype.isInfinity = function isInfinity() { + // XXX This code assumes that zero is always zero in red + return this.z.cmpn(0) === 0; +}; + +Point$1.prototype.dbl = function dbl() { + // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#doubling-dbl-1987-m-3 + // 2M + 2S + 4A + + // A = X1 + Z1 + var a = this.x.redAdd(this.z); + // AA = A^2 + var aa = a.redSqr(); + // B = X1 - Z1 + var b = this.x.redSub(this.z); + // BB = B^2 + var bb = b.redSqr(); + // C = AA - BB + var c = aa.redSub(bb); + // X3 = AA * BB + var nx = aa.redMul(bb); + // Z3 = C * (BB + A24 * C) + var nz = c.redMul(bb.redAdd(this.curve.a24.redMul(c))); + return this.curve.point(nx, nz); +}; + +Point$1.prototype.add = function add() { + throw new Error('Not supported on Montgomery curve'); +}; + +Point$1.prototype.diffAdd = function diffAdd(p, diff) { + // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#diffadd-dadd-1987-m-3 + // 4M + 2S + 6A + + // A = X2 + Z2 + var a = this.x.redAdd(this.z); + // B = X2 - Z2 + var b = this.x.redSub(this.z); + // C = X3 + Z3 + var c = p.x.redAdd(p.z); + // D = X3 - Z3 + var d = p.x.redSub(p.z); + // DA = D * A + var da = d.redMul(a); + // CB = C * B + var cb = c.redMul(b); + // X5 = Z1 * (DA + CB)^2 + var nx = diff.z.redMul(da.redAdd(cb).redSqr()); + // Z5 = X1 * (DA - CB)^2 + var nz = diff.x.redMul(da.redISub(cb).redSqr()); + return this.curve.point(nx, nz); +}; + +Point$1.prototype.mul = function mul(k) { + k = new bn(k, 16); + + var t = k.clone(); + var a = this; // (N / 2) * Q + Q + var b = this.curve.point(null, null); // (N / 2) * Q + var c = this; // Q + + for (var bits = []; t.cmpn(0) !== 0; t.iushrn(1)) + bits.push(t.andln(1)); + + for (var i = bits.length - 1; i >= 0; i--) { + if (bits[i] === 0) { + // N * Q + Q = ((N / 2) * Q + Q)) + (N / 2) * Q + a = a.diffAdd(b, c); + // N * Q = 2 * ((N / 2) * Q + Q)) + b = b.dbl(); + } else { + // N * Q = ((N / 2) * Q + Q) + ((N / 2) * Q) + b = a.diffAdd(b, c); + // N * Q + Q = 2 * ((N / 2) * Q + Q) + a = a.dbl(); + } + } + return b; +}; + +Point$1.prototype.mulAdd = function mulAdd() { + throw new Error('Not supported on Montgomery curve'); +}; + +Point$1.prototype.jumlAdd = function jumlAdd() { + throw new Error('Not supported on Montgomery curve'); +}; + +Point$1.prototype.eq = function eq(other) { + return this.getX().cmp(other.getX()) === 0; +}; + +Point$1.prototype.normalize = function normalize() { + this.x = this.x.redMul(this.z.redInvm()); + this.z = this.curve.one; + return this; +}; + +Point$1.prototype.getX = function getX() { + // Normalize coordinates + this.normalize(); + + return this.x.fromRed(); +}; + +var assert$4 = utils_1$1.assert; + +function EdwardsCurve(conf) { + // NOTE: Important as we are creating point in Base.call() + this.twisted = (conf.a | 0) !== 1; + this.mOneA = this.twisted && (conf.a | 0) === -1; + this.extended = this.mOneA; + + base.call(this, 'edwards', conf); + + this.a = new bn(conf.a, 16).umod(this.red.m); + this.a = this.a.toRed(this.red); + this.c = new bn(conf.c, 16).toRed(this.red); + this.c2 = this.c.redSqr(); + this.d = new bn(conf.d, 16).toRed(this.red); + this.dd = this.d.redAdd(this.d); + + assert$4(!this.twisted || this.c.fromRed().cmpn(1) === 0); + this.oneC = (conf.c | 0) === 1; +} +inherits(EdwardsCurve, base); +var edwards = EdwardsCurve; + +EdwardsCurve.prototype._mulA = function _mulA(num) { + if (this.mOneA) + return num.redNeg(); + else + return this.a.redMul(num); +}; + +EdwardsCurve.prototype._mulC = function _mulC(num) { + if (this.oneC) + return num; + else + return this.c.redMul(num); +}; + +// Just for compatibility with Short curve +EdwardsCurve.prototype.jpoint = function jpoint(x, y, z, t) { + return this.point(x, y, z, t); +}; + +EdwardsCurve.prototype.pointFromX = function pointFromX(x, odd) { + x = new bn(x, 16); + if (!x.red) + x = x.toRed(this.red); + + var x2 = x.redSqr(); + var rhs = this.c2.redSub(this.a.redMul(x2)); + var lhs = this.one.redSub(this.c2.redMul(this.d).redMul(x2)); + + var y2 = rhs.redMul(lhs.redInvm()); + var y = y2.redSqrt(); + if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) + throw new Error('invalid point'); + + var isOdd = y.fromRed().isOdd(); + if (odd && !isOdd || !odd && isOdd) + y = y.redNeg(); + + return this.point(x, y); +}; + +EdwardsCurve.prototype.pointFromY = function pointFromY(y, odd) { + y = new bn(y, 16); + if (!y.red) + y = y.toRed(this.red); + + // x^2 = (y^2 - c^2) / (c^2 d y^2 - a) + var y2 = y.redSqr(); + var lhs = y2.redSub(this.c2); + var rhs = y2.redMul(this.d).redMul(this.c2).redSub(this.a); + var x2 = lhs.redMul(rhs.redInvm()); + + if (x2.cmp(this.zero) === 0) { + if (odd) + throw new Error('invalid point'); + else + return this.point(this.zero, y); + } + + var x = x2.redSqrt(); + if (x.redSqr().redSub(x2).cmp(this.zero) !== 0) + throw new Error('invalid point'); + + if (x.fromRed().isOdd() !== odd) + x = x.redNeg(); + + return this.point(x, y); +}; + +EdwardsCurve.prototype.validate = function validate(point) { + if (point.isInfinity()) + return true; + + // Curve: A * X^2 + Y^2 = C^2 * (1 + D * X^2 * Y^2) + point.normalize(); + + var x2 = point.x.redSqr(); + var y2 = point.y.redSqr(); + var lhs = x2.redMul(this.a).redAdd(y2); + var rhs = this.c2.redMul(this.one.redAdd(this.d.redMul(x2).redMul(y2))); + + return lhs.cmp(rhs) === 0; +}; + +function Point$2(curve, x, y, z, t) { + base.BasePoint.call(this, curve, 'projective'); + if (x === null && y === null && z === null) { + this.x = this.curve.zero; + this.y = this.curve.one; + this.z = this.curve.one; + this.t = this.curve.zero; + this.zOne = true; + } else { + this.x = new bn(x, 16); + this.y = new bn(y, 16); + this.z = z ? new bn(z, 16) : this.curve.one; + this.t = t && new bn(t, 16); + if (!this.x.red) + this.x = this.x.toRed(this.curve.red); + if (!this.y.red) + this.y = this.y.toRed(this.curve.red); + if (!this.z.red) + this.z = this.z.toRed(this.curve.red); + if (this.t && !this.t.red) + this.t = this.t.toRed(this.curve.red); + this.zOne = this.z === this.curve.one; + + // Use extended coordinates + if (this.curve.extended && !this.t) { + this.t = this.x.redMul(this.y); + if (!this.zOne) + this.t = this.t.redMul(this.z.redInvm()); + } + } +} +inherits(Point$2, base.BasePoint); + +EdwardsCurve.prototype.pointFromJSON = function pointFromJSON(obj) { + return Point$2.fromJSON(this, obj); +}; + +EdwardsCurve.prototype.point = function point(x, y, z, t) { + return new Point$2(this, x, y, z, t); +}; + +Point$2.fromJSON = function fromJSON(curve, obj) { + return new Point$2(curve, obj[0], obj[1], obj[2]); +}; + +Point$2.prototype.inspect = function inspect() { + if (this.isInfinity()) + return ''; + return ''; +}; + +Point$2.prototype.isInfinity = function isInfinity() { + // XXX This code assumes that zero is always zero in red + return this.x.cmpn(0) === 0 && + (this.y.cmp(this.z) === 0 || + (this.zOne && this.y.cmp(this.curve.c) === 0)); +}; + +Point$2.prototype._extDbl = function _extDbl() { + // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html + // #doubling-dbl-2008-hwcd + // 4M + 4S + + // A = X1^2 + var a = this.x.redSqr(); + // B = Y1^2 + var b = this.y.redSqr(); + // C = 2 * Z1^2 + var c = this.z.redSqr(); + c = c.redIAdd(c); + // D = a * A + var d = this.curve._mulA(a); + // E = (X1 + Y1)^2 - A - B + var e = this.x.redAdd(this.y).redSqr().redISub(a).redISub(b); + // G = D + B + var g = d.redAdd(b); + // F = G - C + var f = g.redSub(c); + // H = D - B + var h = d.redSub(b); + // X3 = E * F + var nx = e.redMul(f); + // Y3 = G * H + var ny = g.redMul(h); + // T3 = E * H + var nt = e.redMul(h); + // Z3 = F * G + var nz = f.redMul(g); + return this.curve.point(nx, ny, nz, nt); +}; + +Point$2.prototype._projDbl = function _projDbl() { + // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html + // #doubling-dbl-2008-bbjlp + // #doubling-dbl-2007-bl + // and others + // Generally 3M + 4S or 2M + 4S + + // B = (X1 + Y1)^2 + var b = this.x.redAdd(this.y).redSqr(); + // C = X1^2 + var c = this.x.redSqr(); + // D = Y1^2 + var d = this.y.redSqr(); + + var nx; + var ny; + var nz; + if (this.curve.twisted) { + // E = a * C + var e = this.curve._mulA(c); + // F = E + D + var f = e.redAdd(d); + if (this.zOne) { + // X3 = (B - C - D) * (F - 2) + nx = b.redSub(c).redSub(d).redMul(f.redSub(this.curve.two)); + // Y3 = F * (E - D) + ny = f.redMul(e.redSub(d)); + // Z3 = F^2 - 2 * F + nz = f.redSqr().redSub(f).redSub(f); + } else { + // H = Z1^2 + var h = this.z.redSqr(); + // J = F - 2 * H + var j = f.redSub(h).redISub(h); + // X3 = (B-C-D)*J + nx = b.redSub(c).redISub(d).redMul(j); + // Y3 = F * (E - D) + ny = f.redMul(e.redSub(d)); + // Z3 = F * J + nz = f.redMul(j); + } + } else { + // E = C + D + var e = c.redAdd(d); + // H = (c * Z1)^2 + var h = this.curve._mulC(this.z).redSqr(); + // J = E - 2 * H + var j = e.redSub(h).redSub(h); + // X3 = c * (B - E) * J + nx = this.curve._mulC(b.redISub(e)).redMul(j); + // Y3 = c * E * (C - D) + ny = this.curve._mulC(e).redMul(c.redISub(d)); + // Z3 = E * J + nz = e.redMul(j); + } + return this.curve.point(nx, ny, nz); +}; + +Point$2.prototype.dbl = function dbl() { + if (this.isInfinity()) + return this; + + // Double in extended coordinates + if (this.curve.extended) + return this._extDbl(); + else + return this._projDbl(); +}; + +Point$2.prototype._extAdd = function _extAdd(p) { + // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html + // #addition-add-2008-hwcd-3 + // 8M + + // A = (Y1 - X1) * (Y2 - X2) + var a = this.y.redSub(this.x).redMul(p.y.redSub(p.x)); + // B = (Y1 + X1) * (Y2 + X2) + var b = this.y.redAdd(this.x).redMul(p.y.redAdd(p.x)); + // C = T1 * k * T2 + var c = this.t.redMul(this.curve.dd).redMul(p.t); + // D = Z1 * 2 * Z2 + var d = this.z.redMul(p.z.redAdd(p.z)); + // E = B - A + var e = b.redSub(a); + // F = D - C + var f = d.redSub(c); + // G = D + C + var g = d.redAdd(c); + // H = B + A + var h = b.redAdd(a); + // X3 = E * F + var nx = e.redMul(f); + // Y3 = G * H + var ny = g.redMul(h); + // T3 = E * H + var nt = e.redMul(h); + // Z3 = F * G + var nz = f.redMul(g); + return this.curve.point(nx, ny, nz, nt); +}; + +Point$2.prototype._projAdd = function _projAdd(p) { + // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html + // #addition-add-2008-bbjlp + // #addition-add-2007-bl + // 10M + 1S + + // A = Z1 * Z2 + var a = this.z.redMul(p.z); + // B = A^2 + var b = a.redSqr(); + // C = X1 * X2 + var c = this.x.redMul(p.x); + // D = Y1 * Y2 + var d = this.y.redMul(p.y); + // E = d * C * D + var e = this.curve.d.redMul(c).redMul(d); + // F = B - E + var f = b.redSub(e); + // G = B + E + var g = b.redAdd(e); + // X3 = A * F * ((X1 + Y1) * (X2 + Y2) - C - D) + var tmp = this.x.redAdd(this.y).redMul(p.x.redAdd(p.y)).redISub(c).redISub(d); + var nx = a.redMul(f).redMul(tmp); + var ny; + var nz; + if (this.curve.twisted) { + // Y3 = A * G * (D - a * C) + ny = a.redMul(g).redMul(d.redSub(this.curve._mulA(c))); + // Z3 = F * G + nz = f.redMul(g); + } else { + // Y3 = A * G * (D - C) + ny = a.redMul(g).redMul(d.redSub(c)); + // Z3 = c * F * G + nz = this.curve._mulC(f).redMul(g); + } + return this.curve.point(nx, ny, nz); +}; + +Point$2.prototype.add = function add(p) { + if (this.isInfinity()) + return p; + if (p.isInfinity()) + return this; + + if (this.curve.extended) + return this._extAdd(p); + else + return this._projAdd(p); +}; + +Point$2.prototype.mul = function mul(k) { + if (this._hasDoubles(k)) + return this.curve._fixedNafMul(this, k); + else + return this.curve._wnafMul(this, k); +}; + +Point$2.prototype.mulAdd = function mulAdd(k1, p, k2) { + return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, false); +}; + +Point$2.prototype.jmulAdd = function jmulAdd(k1, p, k2) { + return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, true); +}; + +Point$2.prototype.normalize = function normalize() { + if (this.zOne) + return this; + + // Normalize coordinates + var zi = this.z.redInvm(); + this.x = this.x.redMul(zi); + this.y = this.y.redMul(zi); + if (this.t) + this.t = this.t.redMul(zi); + this.z = this.curve.one; + this.zOne = true; + return this; +}; + +Point$2.prototype.neg = function neg() { + return this.curve.point(this.x.redNeg(), + this.y, + this.z, + this.t && this.t.redNeg()); +}; + +Point$2.prototype.getX = function getX() { + this.normalize(); + return this.x.fromRed(); +}; + +Point$2.prototype.getY = function getY() { + this.normalize(); + return this.y.fromRed(); +}; + +Point$2.prototype.eq = function eq(other) { + return this === other || + this.getX().cmp(other.getX()) === 0 && + this.getY().cmp(other.getY()) === 0; +}; + +Point$2.prototype.eqXToP = function eqXToP(x) { + var rx = x.toRed(this.curve.red).redMul(this.z); + if (this.x.cmp(rx) === 0) + return true; + + var xc = x.clone(); + var t = this.curve.redN.redMul(this.z); + for (;;) { + xc.iadd(this.curve.n); + if (xc.cmp(this.curve.p) >= 0) + return false; + + rx.redIAdd(t); + if (this.x.cmp(rx) === 0) + return true; + } +}; + +// Compatibility with BaseCurve +Point$2.prototype.toP = Point$2.prototype.normalize; +Point$2.prototype.mixedAdd = Point$2.prototype.add; + +var curve_1 = createCommonjsModule(function (module, exports) { + +var curve = exports; + +curve.base = base; +curve.short = short_1; +curve.mont = mont; +curve.edwards = edwards; +}); + +var rotl32$2 = utils.rotl32; +var sum32$3 = utils.sum32; +var sum32_5$2 = utils.sum32_5; +var ft_1$1 = common$1.ft_1; +var BlockHash$4 = common.BlockHash; + +var sha1_K = [ + 0x5A827999, 0x6ED9EBA1, + 0x8F1BBCDC, 0xCA62C1D6 +]; + +function SHA1() { + if (!(this instanceof SHA1)) + return new SHA1(); + + BlockHash$4.call(this); + this.h = [ + 0x67452301, 0xefcdab89, 0x98badcfe, + 0x10325476, 0xc3d2e1f0 ]; + this.W = new Array(80); +} + +utils.inherits(SHA1, BlockHash$4); +var _1 = SHA1; + +SHA1.blockSize = 512; +SHA1.outSize = 160; +SHA1.hmacStrength = 80; +SHA1.padLength = 64; + +SHA1.prototype._update = function _update(msg, start) { + var W = this.W; + + for (var i = 0; i < 16; i++) + W[i] = msg[start + i]; + + for(; i < W.length; i++) + W[i] = rotl32$2(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1); + + var a = this.h[0]; + var b = this.h[1]; + var c = this.h[2]; + var d = this.h[3]; + var e = this.h[4]; + + for (i = 0; i < W.length; i++) { + var s = ~~(i / 20); + var t = sum32_5$2(rotl32$2(a, 5), ft_1$1(s, b, c, d), e, W[i], sha1_K[s]); + e = d; + d = c; + c = rotl32$2(b, 30); + b = a; + a = t; + } + + this.h[0] = sum32$3(this.h[0], a); + this.h[1] = sum32$3(this.h[1], b); + this.h[2] = sum32$3(this.h[2], c); + this.h[3] = sum32$3(this.h[3], d); + this.h[4] = sum32$3(this.h[4], e); +}; + +SHA1.prototype._digest = function digest(enc) { + if (enc === 'hex') + return utils.toHex32(this.h, 'big'); + else + return utils.split32(this.h, 'big'); +}; + +var sha1 = _1; +var sha224 = _224; +var sha256 = _256; +var sha384 = _384; +var sha512 = _512; + +var sha = { + sha1: sha1, + sha224: sha224, + sha256: sha256, + sha384: sha384, + sha512: sha512 +}; + +function Hmac(hash, key, enc) { + if (!(this instanceof Hmac)) + return new Hmac(hash, key, enc); + this.Hash = hash; + this.blockSize = hash.blockSize / 8; + this.outSize = hash.outSize / 8; + this.inner = null; + this.outer = null; + + this._init(utils.toArray(key, enc)); +} +var hmac = Hmac; + +Hmac.prototype._init = function init(key) { + // Shorten key, if needed + if (key.length > this.blockSize) + key = new this.Hash().update(key).digest(); + minimalisticAssert(key.length <= this.blockSize); + + // Add padding to key + for (var i = key.length; i < this.blockSize; i++) + key.push(0); + + for (i = 0; i < key.length; i++) + key[i] ^= 0x36; + this.inner = new this.Hash().update(key); + + // 0x36 ^ 0x5c = 0x6a + for (i = 0; i < key.length; i++) + key[i] ^= 0x6a; + this.outer = new this.Hash().update(key); +}; + +Hmac.prototype.update = function update(msg, enc) { + this.inner.update(msg, enc); + return this; +}; + +Hmac.prototype.digest = function digest(enc) { + this.outer.update(this.inner.digest()); + return this.outer.digest(enc); +}; + +var hash_1 = createCommonjsModule(function (module, exports) { +var hash = exports; + +hash.utils = utils; +hash.common = common; +hash.sha = sha; +hash.ripemd = ripemd; +hash.hmac = hmac; + +// Proxy hash functions to the main object +hash.sha1 = hash.sha.sha1; +hash.sha256 = hash.sha.sha256; +hash.sha224 = hash.sha.sha224; +hash.sha384 = hash.sha.sha384; +hash.sha512 = hash.sha.sha512; +hash.ripemd160 = hash.ripemd.ripemd160; +}); + +var secp256k1 = { + doubles: { + step: 4, + points: [ + [ + 'e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a', + 'f7e3507399e595929db99f34f57937101296891e44d23f0be1f32cce69616821' + ], + [ + '8282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508', + '11f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf' + ], + [ + '175e159f728b865a72f99cc6c6fc846de0b93833fd2222ed73fce5b551e5b739', + 'd3506e0d9e3c79eba4ef97a51ff71f5eacb5955add24345c6efa6ffee9fed695' + ], + [ + '363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640', + '4e273adfc732221953b445397f3363145b9a89008199ecb62003c7f3bee9de9' + ], + [ + '8b4b5f165df3c2be8c6244b5b745638843e4a781a15bcd1b69f79a55dffdf80c', + '4aad0a6f68d308b4b3fbd7813ab0da04f9e336546162ee56b3eff0c65fd4fd36' + ], + [ + '723cbaa6e5db996d6bf771c00bd548c7b700dbffa6c0e77bcb6115925232fcda', + '96e867b5595cc498a921137488824d6e2660a0653779494801dc069d9eb39f5f' + ], + [ + 'eebfa4d493bebf98ba5feec812c2d3b50947961237a919839a533eca0e7dd7fa', + '5d9a8ca3970ef0f269ee7edaf178089d9ae4cdc3a711f712ddfd4fdae1de8999' + ], + [ + '100f44da696e71672791d0a09b7bde459f1215a29b3c03bfefd7835b39a48db0', + 'cdd9e13192a00b772ec8f3300c090666b7ff4a18ff5195ac0fbd5cd62bc65a09' + ], + [ + 'e1031be262c7ed1b1dc9227a4a04c017a77f8d4464f3b3852c8acde6e534fd2d', + '9d7061928940405e6bb6a4176597535af292dd419e1ced79a44f18f29456a00d' + ], + [ + 'feea6cae46d55b530ac2839f143bd7ec5cf8b266a41d6af52d5e688d9094696d', + 'e57c6b6c97dce1bab06e4e12bf3ecd5c981c8957cc41442d3155debf18090088' + ], + [ + 'da67a91d91049cdcb367be4be6ffca3cfeed657d808583de33fa978bc1ec6cb1', + '9bacaa35481642bc41f463f7ec9780e5dec7adc508f740a17e9ea8e27a68be1d' + ], + [ + '53904faa0b334cdda6e000935ef22151ec08d0f7bb11069f57545ccc1a37b7c0', + '5bc087d0bc80106d88c9eccac20d3c1c13999981e14434699dcb096b022771c8' + ], + [ + '8e7bcd0bd35983a7719cca7764ca906779b53a043a9b8bcaeff959f43ad86047', + '10b7770b2a3da4b3940310420ca9514579e88e2e47fd68b3ea10047e8460372a' + ], + [ + '385eed34c1cdff21e6d0818689b81bde71a7f4f18397e6690a841e1599c43862', + '283bebc3e8ea23f56701de19e9ebf4576b304eec2086dc8cc0458fe5542e5453' + ], + [ + '6f9d9b803ecf191637c73a4413dfa180fddf84a5947fbc9c606ed86c3fac3a7', + '7c80c68e603059ba69b8e2a30e45c4d47ea4dd2f5c281002d86890603a842160' + ], + [ + '3322d401243c4e2582a2147c104d6ecbf774d163db0f5e5313b7e0e742d0e6bd', + '56e70797e9664ef5bfb019bc4ddaf9b72805f63ea2873af624f3a2e96c28b2a0' + ], + [ + '85672c7d2de0b7da2bd1770d89665868741b3f9af7643397721d74d28134ab83', + '7c481b9b5b43b2eb6374049bfa62c2e5e77f17fcc5298f44c8e3094f790313a6' + ], + [ + '948bf809b1988a46b06c9f1919413b10f9226c60f668832ffd959af60c82a0a', + '53a562856dcb6646dc6b74c5d1c3418c6d4dff08c97cd2bed4cb7f88d8c8e589' + ], + [ + '6260ce7f461801c34f067ce0f02873a8f1b0e44dfc69752accecd819f38fd8e8', + 'bc2da82b6fa5b571a7f09049776a1ef7ecd292238051c198c1a84e95b2b4ae17' + ], + [ + 'e5037de0afc1d8d43d8348414bbf4103043ec8f575bfdc432953cc8d2037fa2d', + '4571534baa94d3b5f9f98d09fb990bddbd5f5b03ec481f10e0e5dc841d755bda' + ], + [ + 'e06372b0f4a207adf5ea905e8f1771b4e7e8dbd1c6a6c5b725866a0ae4fce725', + '7a908974bce18cfe12a27bb2ad5a488cd7484a7787104870b27034f94eee31dd' + ], + [ + '213c7a715cd5d45358d0bbf9dc0ce02204b10bdde2a3f58540ad6908d0559754', + '4b6dad0b5ae462507013ad06245ba190bb4850f5f36a7eeddff2c27534b458f2' + ], + [ + '4e7c272a7af4b34e8dbb9352a5419a87e2838c70adc62cddf0cc3a3b08fbd53c', + '17749c766c9d0b18e16fd09f6def681b530b9614bff7dd33e0b3941817dcaae6' + ], + [ + 'fea74e3dbe778b1b10f238ad61686aa5c76e3db2be43057632427e2840fb27b6', + '6e0568db9b0b13297cf674deccb6af93126b596b973f7b77701d3db7f23cb96f' + ], + [ + '76e64113f677cf0e10a2570d599968d31544e179b760432952c02a4417bdde39', + 'c90ddf8dee4e95cf577066d70681f0d35e2a33d2b56d2032b4b1752d1901ac01' + ], + [ + 'c738c56b03b2abe1e8281baa743f8f9a8f7cc643df26cbee3ab150242bcbb891', + '893fb578951ad2537f718f2eacbfbbbb82314eef7880cfe917e735d9699a84c3' + ], + [ + 'd895626548b65b81e264c7637c972877d1d72e5f3a925014372e9f6588f6c14b', + 'febfaa38f2bc7eae728ec60818c340eb03428d632bb067e179363ed75d7d991f' + ], + [ + 'b8da94032a957518eb0f6433571e8761ceffc73693e84edd49150a564f676e03', + '2804dfa44805a1e4d7c99cc9762808b092cc584d95ff3b511488e4e74efdf6e7' + ], + [ + 'e80fea14441fb33a7d8adab9475d7fab2019effb5156a792f1a11778e3c0df5d', + 'eed1de7f638e00771e89768ca3ca94472d155e80af322ea9fcb4291b6ac9ec78' + ], + [ + 'a301697bdfcd704313ba48e51d567543f2a182031efd6915ddc07bbcc4e16070', + '7370f91cfb67e4f5081809fa25d40f9b1735dbf7c0a11a130c0d1a041e177ea1' + ], + [ + '90ad85b389d6b936463f9d0512678de208cc330b11307fffab7ac63e3fb04ed4', + 'e507a3620a38261affdcbd9427222b839aefabe1582894d991d4d48cb6ef150' + ], + [ + '8f68b9d2f63b5f339239c1ad981f162ee88c5678723ea3351b7b444c9ec4c0da', + '662a9f2dba063986de1d90c2b6be215dbbea2cfe95510bfdf23cbf79501fff82' + ], + [ + 'e4f3fb0176af85d65ff99ff9198c36091f48e86503681e3e6686fd5053231e11', + '1e63633ad0ef4f1c1661a6d0ea02b7286cc7e74ec951d1c9822c38576feb73bc' + ], + [ + '8c00fa9b18ebf331eb961537a45a4266c7034f2f0d4e1d0716fb6eae20eae29e', + 'efa47267fea521a1a9dc343a3736c974c2fadafa81e36c54e7d2a4c66702414b' + ], + [ + 'e7a26ce69dd4829f3e10cec0a9e98ed3143d084f308b92c0997fddfc60cb3e41', + '2a758e300fa7984b471b006a1aafbb18d0a6b2c0420e83e20e8a9421cf2cfd51' + ], + [ + 'b6459e0ee3662ec8d23540c223bcbdc571cbcb967d79424f3cf29eb3de6b80ef', + '67c876d06f3e06de1dadf16e5661db3c4b3ae6d48e35b2ff30bf0b61a71ba45' + ], + [ + 'd68a80c8280bb840793234aa118f06231d6f1fc67e73c5a5deda0f5b496943e8', + 'db8ba9fff4b586d00c4b1f9177b0e28b5b0e7b8f7845295a294c84266b133120' + ], + [ + '324aed7df65c804252dc0270907a30b09612aeb973449cea4095980fc28d3d5d', + '648a365774b61f2ff130c0c35aec1f4f19213b0c7e332843967224af96ab7c84' + ], + [ + '4df9c14919cde61f6d51dfdbe5fee5dceec4143ba8d1ca888e8bd373fd054c96', + '35ec51092d8728050974c23a1d85d4b5d506cdc288490192ebac06cad10d5d' + ], + [ + '9c3919a84a474870faed8a9c1cc66021523489054d7f0308cbfc99c8ac1f98cd', + 'ddb84f0f4a4ddd57584f044bf260e641905326f76c64c8e6be7e5e03d4fc599d' + ], + [ + '6057170b1dd12fdf8de05f281d8e06bb91e1493a8b91d4cc5a21382120a959e5', + '9a1af0b26a6a4807add9a2daf71df262465152bc3ee24c65e899be932385a2a8' + ], + [ + 'a576df8e23a08411421439a4518da31880cef0fba7d4df12b1a6973eecb94266', + '40a6bf20e76640b2c92b97afe58cd82c432e10a7f514d9f3ee8be11ae1b28ec8' + ], + [ + '7778a78c28dec3e30a05fe9629de8c38bb30d1f5cf9a3a208f763889be58ad71', + '34626d9ab5a5b22ff7098e12f2ff580087b38411ff24ac563b513fc1fd9f43ac' + ], + [ + '928955ee637a84463729fd30e7afd2ed5f96274e5ad7e5cb09eda9c06d903ac', + 'c25621003d3f42a827b78a13093a95eeac3d26efa8a8d83fc5180e935bcd091f' + ], + [ + '85d0fef3ec6db109399064f3a0e3b2855645b4a907ad354527aae75163d82751', + '1f03648413a38c0be29d496e582cf5663e8751e96877331582c237a24eb1f962' + ], + [ + 'ff2b0dce97eece97c1c9b6041798b85dfdfb6d8882da20308f5404824526087e', + '493d13fef524ba188af4c4dc54d07936c7b7ed6fb90e2ceb2c951e01f0c29907' + ], + [ + '827fbbe4b1e880ea9ed2b2e6301b212b57f1ee148cd6dd28780e5e2cf856e241', + 'c60f9c923c727b0b71bef2c67d1d12687ff7a63186903166d605b68baec293ec' + ], + [ + 'eaa649f21f51bdbae7be4ae34ce6e5217a58fdce7f47f9aa7f3b58fa2120e2b3', + 'be3279ed5bbbb03ac69a80f89879aa5a01a6b965f13f7e59d47a5305ba5ad93d' + ], + [ + 'e4a42d43c5cf169d9391df6decf42ee541b6d8f0c9a137401e23632dda34d24f', + '4d9f92e716d1c73526fc99ccfb8ad34ce886eedfa8d8e4f13a7f7131deba9414' + ], + [ + '1ec80fef360cbdd954160fadab352b6b92b53576a88fea4947173b9d4300bf19', + 'aeefe93756b5340d2f3a4958a7abbf5e0146e77f6295a07b671cdc1cc107cefd' + ], + [ + '146a778c04670c2f91b00af4680dfa8bce3490717d58ba889ddb5928366642be', + 'b318e0ec3354028add669827f9d4b2870aaa971d2f7e5ed1d0b297483d83efd0' + ], + [ + 'fa50c0f61d22e5f07e3acebb1aa07b128d0012209a28b9776d76a8793180eef9', + '6b84c6922397eba9b72cd2872281a68a5e683293a57a213b38cd8d7d3f4f2811' + ], + [ + 'da1d61d0ca721a11b1a5bf6b7d88e8421a288ab5d5bba5220e53d32b5f067ec2', + '8157f55a7c99306c79c0766161c91e2966a73899d279b48a655fba0f1ad836f1' + ], + [ + 'a8e282ff0c9706907215ff98e8fd416615311de0446f1e062a73b0610d064e13', + '7f97355b8db81c09abfb7f3c5b2515888b679a3e50dd6bd6cef7c73111f4cc0c' + ], + [ + '174a53b9c9a285872d39e56e6913cab15d59b1fa512508c022f382de8319497c', + 'ccc9dc37abfc9c1657b4155f2c47f9e6646b3a1d8cb9854383da13ac079afa73' + ], + [ + '959396981943785c3d3e57edf5018cdbe039e730e4918b3d884fdff09475b7ba', + '2e7e552888c331dd8ba0386a4b9cd6849c653f64c8709385e9b8abf87524f2fd' + ], + [ + 'd2a63a50ae401e56d645a1153b109a8fcca0a43d561fba2dbb51340c9d82b151', + 'e82d86fb6443fcb7565aee58b2948220a70f750af484ca52d4142174dcf89405' + ], + [ + '64587e2335471eb890ee7896d7cfdc866bacbdbd3839317b3436f9b45617e073', + 'd99fcdd5bf6902e2ae96dd6447c299a185b90a39133aeab358299e5e9faf6589' + ], + [ + '8481bde0e4e4d885b3a546d3e549de042f0aa6cea250e7fd358d6c86dd45e458', + '38ee7b8cba5404dd84a25bf39cecb2ca900a79c42b262e556d64b1b59779057e' + ], + [ + '13464a57a78102aa62b6979ae817f4637ffcfed3c4b1ce30bcd6303f6caf666b', + '69be159004614580ef7e433453ccb0ca48f300a81d0942e13f495a907f6ecc27' + ], + [ + 'bc4a9df5b713fe2e9aef430bcc1dc97a0cd9ccede2f28588cada3a0d2d83f366', + 'd3a81ca6e785c06383937adf4b798caa6e8a9fbfa547b16d758d666581f33c1' + ], + [ + '8c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa', + '40a30463a3305193378fedf31f7cc0eb7ae784f0451cb9459e71dc73cbef9482' + ], + [ + '8ea9666139527a8c1dd94ce4f071fd23c8b350c5a4bb33748c4ba111faccae0', + '620efabbc8ee2782e24e7c0cfb95c5d735b783be9cf0f8e955af34a30e62b945' + ], + [ + 'dd3625faef5ba06074669716bbd3788d89bdde815959968092f76cc4eb9a9787', + '7a188fa3520e30d461da2501045731ca941461982883395937f68d00c644a573' + ], + [ + 'f710d79d9eb962297e4f6232b40e8f7feb2bc63814614d692c12de752408221e', + 'ea98e67232d3b3295d3b535532115ccac8612c721851617526ae47a9c77bfc82' + ] + ] + }, + naf: { + wnd: 7, + points: [ + [ + 'f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9', + '388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672' + ], + [ + '2f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4', + 'd8ac222636e5e3d6d4dba9dda6c9c426f788271bab0d6840dca87d3aa6ac62d6' + ], + [ + '5cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc', + '6aebca40ba255960a3178d6d861a54dba813d0b813fde7b5a5082628087264da' + ], + [ + 'acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe', + 'cc338921b0a7d9fd64380971763b61e9add888a4375f8e0f05cc262ac64f9c37' + ], + [ + '774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb', + 'd984a032eb6b5e190243dd56d7b7b365372db1e2dff9d6a8301d74c9c953c61b' + ], + [ + 'f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8', + 'ab0902e8d880a89758212eb65cdaf473a1a06da521fa91f29b5cb52db03ed81' + ], + [ + 'd7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e', + '581e2872a86c72a683842ec228cc6defea40af2bd896d3a5c504dc9ff6a26b58' + ], + [ + 'defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34', + '4211ab0694635168e997b0ead2a93daeced1f4a04a95c0f6cfb199f69e56eb77' + ], + [ + '2b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c', + '85e89bc037945d93b343083b5a1c86131a01f60c50269763b570c854e5c09b7a' + ], + [ + '352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5', + '321eb4075348f534d59c18259dda3e1f4a1b3b2e71b1039c67bd3d8bcf81998c' + ], + [ + '2fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f', + '2de1068295dd865b64569335bd5dd80181d70ecfc882648423ba76b532b7d67' + ], + [ + '9248279b09b4d68dab21a9b066edda83263c3d84e09572e269ca0cd7f5453714', + '73016f7bf234aade5d1aa71bdea2b1ff3fc0de2a887912ffe54a32ce97cb3402' + ], + [ + 'daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729', + 'a69dce4a7d6c98e8d4a1aca87ef8d7003f83c230f3afa726ab40e52290be1c55' + ], + [ + 'c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db', + '2119a460ce326cdc76c45926c982fdac0e106e861edf61c5a039063f0e0e6482' + ], + [ + '6a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4', + 'e022cf42c2bd4a708b3f5126f16a24ad8b33ba48d0423b6efd5e6348100d8a82' + ], + [ + '1697ffa6fd9de627c077e3d2fe541084ce13300b0bec1146f95ae57f0d0bd6a5', + 'b9c398f186806f5d27561506e4557433a2cf15009e498ae7adee9d63d01b2396' + ], + [ + '605bdb019981718b986d0f07e834cb0d9deb8360ffb7f61df982345ef27a7479', + '2972d2de4f8d20681a78d93ec96fe23c26bfae84fb14db43b01e1e9056b8c49' + ], + [ + '62d14dab4150bf497402fdc45a215e10dcb01c354959b10cfe31c7e9d87ff33d', + '80fc06bd8cc5b01098088a1950eed0db01aa132967ab472235f5642483b25eaf' + ], + [ + '80c60ad0040f27dade5b4b06c408e56b2c50e9f56b9b8b425e555c2f86308b6f', + '1c38303f1cc5c30f26e66bad7fe72f70a65eed4cbe7024eb1aa01f56430bd57a' + ], + [ + '7a9375ad6167ad54aa74c6348cc54d344cc5dc9487d847049d5eabb0fa03c8fb', + 'd0e3fa9eca8726909559e0d79269046bdc59ea10c70ce2b02d499ec224dc7f7' + ], + [ + 'd528ecd9b696b54c907a9ed045447a79bb408ec39b68df504bb51f459bc3ffc9', + 'eecf41253136e5f99966f21881fd656ebc4345405c520dbc063465b521409933' + ], + [ + '49370a4b5f43412ea25f514e8ecdad05266115e4a7ecb1387231808f8b45963', + '758f3f41afd6ed428b3081b0512fd62a54c3f3afbb5b6764b653052a12949c9a' + ], + [ + '77f230936ee88cbbd73df930d64702ef881d811e0e1498e2f1c13eb1fc345d74', + '958ef42a7886b6400a08266e9ba1b37896c95330d97077cbbe8eb3c7671c60d6' + ], + [ + 'f2dac991cc4ce4b9ea44887e5c7c0bce58c80074ab9d4dbaeb28531b7739f530', + 'e0dedc9b3b2f8dad4da1f32dec2531df9eb5fbeb0598e4fd1a117dba703a3c37' + ], + [ + '463b3d9f662621fb1b4be8fbbe2520125a216cdfc9dae3debcba4850c690d45b', + '5ed430d78c296c3543114306dd8622d7c622e27c970a1de31cb377b01af7307e' + ], + [ + 'f16f804244e46e2a09232d4aff3b59976b98fac14328a2d1a32496b49998f247', + 'cedabd9b82203f7e13d206fcdf4e33d92a6c53c26e5cce26d6579962c4e31df6' + ], + [ + 'caf754272dc84563b0352b7a14311af55d245315ace27c65369e15f7151d41d1', + 'cb474660ef35f5f2a41b643fa5e460575f4fa9b7962232a5c32f908318a04476' + ], + [ + '2600ca4b282cb986f85d0f1709979d8b44a09c07cb86d7c124497bc86f082120', + '4119b88753c15bd6a693b03fcddbb45d5ac6be74ab5f0ef44b0be9475a7e4b40' + ], + [ + '7635ca72d7e8432c338ec53cd12220bc01c48685e24f7dc8c602a7746998e435', + '91b649609489d613d1d5e590f78e6d74ecfc061d57048bad9e76f302c5b9c61' + ], + [ + '754e3239f325570cdbbf4a87deee8a66b7f2b33479d468fbc1a50743bf56cc18', + '673fb86e5bda30fb3cd0ed304ea49a023ee33d0197a695d0c5d98093c536683' + ], + [ + 'e3e6bd1071a1e96aff57859c82d570f0330800661d1c952f9fe2694691d9b9e8', + '59c9e0bba394e76f40c0aa58379a3cb6a5a2283993e90c4167002af4920e37f5' + ], + [ + '186b483d056a033826ae73d88f732985c4ccb1f32ba35f4b4cc47fdcf04aa6eb', + '3b952d32c67cf77e2e17446e204180ab21fb8090895138b4a4a797f86e80888b' + ], + [ + 'df9d70a6b9876ce544c98561f4be4f725442e6d2b737d9c91a8321724ce0963f', + '55eb2dafd84d6ccd5f862b785dc39d4ab157222720ef9da217b8c45cf2ba2417' + ], + [ + '5edd5cc23c51e87a497ca815d5dce0f8ab52554f849ed8995de64c5f34ce7143', + 'efae9c8dbc14130661e8cec030c89ad0c13c66c0d17a2905cdc706ab7399a868' + ], + [ + '290798c2b6476830da12fe02287e9e777aa3fba1c355b17a722d362f84614fba', + 'e38da76dcd440621988d00bcf79af25d5b29c094db2a23146d003afd41943e7a' + ], + [ + 'af3c423a95d9f5b3054754efa150ac39cd29552fe360257362dfdecef4053b45', + 'f98a3fd831eb2b749a93b0e6f35cfb40c8cd5aa667a15581bc2feded498fd9c6' + ], + [ + '766dbb24d134e745cccaa28c99bf274906bb66b26dcf98df8d2fed50d884249a', + '744b1152eacbe5e38dcc887980da38b897584a65fa06cedd2c924f97cbac5996' + ], + [ + '59dbf46f8c94759ba21277c33784f41645f7b44f6c596a58ce92e666191abe3e', + 'c534ad44175fbc300f4ea6ce648309a042ce739a7919798cd85e216c4a307f6e' + ], + [ + 'f13ada95103c4537305e691e74e9a4a8dd647e711a95e73cb62dc6018cfd87b8', + 'e13817b44ee14de663bf4bc808341f326949e21a6a75c2570778419bdaf5733d' + ], + [ + '7754b4fa0e8aced06d4167a2c59cca4cda1869c06ebadfb6488550015a88522c', + '30e93e864e669d82224b967c3020b8fa8d1e4e350b6cbcc537a48b57841163a2' + ], + [ + '948dcadf5990e048aa3874d46abef9d701858f95de8041d2a6828c99e2262519', + 'e491a42537f6e597d5d28a3224b1bc25df9154efbd2ef1d2cbba2cae5347d57e' + ], + [ + '7962414450c76c1689c7b48f8202ec37fb224cf5ac0bfa1570328a8a3d7c77ab', + '100b610ec4ffb4760d5c1fc133ef6f6b12507a051f04ac5760afa5b29db83437' + ], + [ + '3514087834964b54b15b160644d915485a16977225b8847bb0dd085137ec47ca', + 'ef0afbb2056205448e1652c48e8127fc6039e77c15c2378b7e7d15a0de293311' + ], + [ + 'd3cc30ad6b483e4bc79ce2c9dd8bc54993e947eb8df787b442943d3f7b527eaf', + '8b378a22d827278d89c5e9be8f9508ae3c2ad46290358630afb34db04eede0a4' + ], + [ + '1624d84780732860ce1c78fcbfefe08b2b29823db913f6493975ba0ff4847610', + '68651cf9b6da903e0914448c6cd9d4ca896878f5282be4c8cc06e2a404078575' + ], + [ + '733ce80da955a8a26902c95633e62a985192474b5af207da6df7b4fd5fc61cd4', + 'f5435a2bd2badf7d485a4d8b8db9fcce3e1ef8e0201e4578c54673bc1dc5ea1d' + ], + [ + '15d9441254945064cf1a1c33bbd3b49f8966c5092171e699ef258dfab81c045c', + 'd56eb30b69463e7234f5137b73b84177434800bacebfc685fc37bbe9efe4070d' + ], + [ + 'a1d0fcf2ec9de675b612136e5ce70d271c21417c9d2b8aaaac138599d0717940', + 'edd77f50bcb5a3cab2e90737309667f2641462a54070f3d519212d39c197a629' + ], + [ + 'e22fbe15c0af8ccc5780c0735f84dbe9a790badee8245c06c7ca37331cb36980', + 'a855babad5cd60c88b430a69f53a1a7a38289154964799be43d06d77d31da06' + ], + [ + '311091dd9860e8e20ee13473c1155f5f69635e394704eaa74009452246cfa9b3', + '66db656f87d1f04fffd1f04788c06830871ec5a64feee685bd80f0b1286d8374' + ], + [ + '34c1fd04d301be89b31c0442d3e6ac24883928b45a9340781867d4232ec2dbdf', + '9414685e97b1b5954bd46f730174136d57f1ceeb487443dc5321857ba73abee' + ], + [ + 'f219ea5d6b54701c1c14de5b557eb42a8d13f3abbcd08affcc2a5e6b049b8d63', + '4cb95957e83d40b0f73af4544cccf6b1f4b08d3c07b27fb8d8c2962a400766d1' + ], + [ + 'd7b8740f74a8fbaab1f683db8f45de26543a5490bca627087236912469a0b448', + 'fa77968128d9c92ee1010f337ad4717eff15db5ed3c049b3411e0315eaa4593b' + ], + [ + '32d31c222f8f6f0ef86f7c98d3a3335ead5bcd32abdd94289fe4d3091aa824bf', + '5f3032f5892156e39ccd3d7915b9e1da2e6dac9e6f26e961118d14b8462e1661' + ], + [ + '7461f371914ab32671045a155d9831ea8793d77cd59592c4340f86cbc18347b5', + '8ec0ba238b96bec0cbdddcae0aa442542eee1ff50c986ea6b39847b3cc092ff6' + ], + [ + 'ee079adb1df1860074356a25aa38206a6d716b2c3e67453d287698bad7b2b2d6', + '8dc2412aafe3be5c4c5f37e0ecc5f9f6a446989af04c4e25ebaac479ec1c8c1e' + ], + [ + '16ec93e447ec83f0467b18302ee620f7e65de331874c9dc72bfd8616ba9da6b5', + '5e4631150e62fb40d0e8c2a7ca5804a39d58186a50e497139626778e25b0674d' + ], + [ + 'eaa5f980c245f6f038978290afa70b6bd8855897f98b6aa485b96065d537bd99', + 'f65f5d3e292c2e0819a528391c994624d784869d7e6ea67fb18041024edc07dc' + ], + [ + '78c9407544ac132692ee1910a02439958ae04877151342ea96c4b6b35a49f51', + 'f3e0319169eb9b85d5404795539a5e68fa1fbd583c064d2462b675f194a3ddb4' + ], + [ + '494f4be219a1a77016dcd838431aea0001cdc8ae7a6fc688726578d9702857a5', + '42242a969283a5f339ba7f075e36ba2af925ce30d767ed6e55f4b031880d562c' + ], + [ + 'a598a8030da6d86c6bc7f2f5144ea549d28211ea58faa70ebf4c1e665c1fe9b5', + '204b5d6f84822c307e4b4a7140737aec23fc63b65b35f86a10026dbd2d864e6b' + ], + [ + 'c41916365abb2b5d09192f5f2dbeafec208f020f12570a184dbadc3e58595997', + '4f14351d0087efa49d245b328984989d5caf9450f34bfc0ed16e96b58fa9913' + ], + [ + '841d6063a586fa475a724604da03bc5b92a2e0d2e0a36acfe4c73a5514742881', + '73867f59c0659e81904f9a1c7543698e62562d6744c169ce7a36de01a8d6154' + ], + [ + '5e95bb399a6971d376026947f89bde2f282b33810928be4ded112ac4d70e20d5', + '39f23f366809085beebfc71181313775a99c9aed7d8ba38b161384c746012865' + ], + [ + '36e4641a53948fd476c39f8a99fd974e5ec07564b5315d8bf99471bca0ef2f66', + 'd2424b1b1abe4eb8164227b085c9aa9456ea13493fd563e06fd51cf5694c78fc' + ], + [ + '336581ea7bfbbb290c191a2f507a41cf5643842170e914faeab27c2c579f726', + 'ead12168595fe1be99252129b6e56b3391f7ab1410cd1e0ef3dcdcabd2fda224' + ], + [ + '8ab89816dadfd6b6a1f2634fcf00ec8403781025ed6890c4849742706bd43ede', + '6fdcef09f2f6d0a044e654aef624136f503d459c3e89845858a47a9129cdd24e' + ], + [ + '1e33f1a746c9c5778133344d9299fcaa20b0938e8acff2544bb40284b8c5fb94', + '60660257dd11b3aa9c8ed618d24edff2306d320f1d03010e33a7d2057f3b3b6' + ], + [ + '85b7c1dcb3cec1b7ee7f30ded79dd20a0ed1f4cc18cbcfcfa410361fd8f08f31', + '3d98a9cdd026dd43f39048f25a8847f4fcafad1895d7a633c6fed3c35e999511' + ], + [ + '29df9fbd8d9e46509275f4b125d6d45d7fbe9a3b878a7af872a2800661ac5f51', + 'b4c4fe99c775a606e2d8862179139ffda61dc861c019e55cd2876eb2a27d84b' + ], + [ + 'a0b1cae06b0a847a3fea6e671aaf8adfdfe58ca2f768105c8082b2e449fce252', + 'ae434102edde0958ec4b19d917a6a28e6b72da1834aff0e650f049503a296cf2' + ], + [ + '4e8ceafb9b3e9a136dc7ff67e840295b499dfb3b2133e4ba113f2e4c0e121e5', + 'cf2174118c8b6d7a4b48f6d534ce5c79422c086a63460502b827ce62a326683c' + ], + [ + 'd24a44e047e19b6f5afb81c7ca2f69080a5076689a010919f42725c2b789a33b', + '6fb8d5591b466f8fc63db50f1c0f1c69013f996887b8244d2cdec417afea8fa3' + ], + [ + 'ea01606a7a6c9cdd249fdfcfacb99584001edd28abbab77b5104e98e8e3b35d4', + '322af4908c7312b0cfbfe369f7a7b3cdb7d4494bc2823700cfd652188a3ea98d' + ], + [ + 'af8addbf2b661c8a6c6328655eb96651252007d8c5ea31be4ad196de8ce2131f', + '6749e67c029b85f52a034eafd096836b2520818680e26ac8f3dfbcdb71749700' + ], + [ + 'e3ae1974566ca06cc516d47e0fb165a674a3dabcfca15e722f0e3450f45889', + '2aeabe7e4531510116217f07bf4d07300de97e4874f81f533420a72eeb0bd6a4' + ], + [ + '591ee355313d99721cf6993ffed1e3e301993ff3ed258802075ea8ced397e246', + 'b0ea558a113c30bea60fc4775460c7901ff0b053d25ca2bdeee98f1a4be5d196' + ], + [ + '11396d55fda54c49f19aa97318d8da61fa8584e47b084945077cf03255b52984', + '998c74a8cd45ac01289d5833a7beb4744ff536b01b257be4c5767bea93ea57a4' + ], + [ + '3c5d2a1ba39c5a1790000738c9e0c40b8dcdfd5468754b6405540157e017aa7a', + 'b2284279995a34e2f9d4de7396fc18b80f9b8b9fdd270f6661f79ca4c81bd257' + ], + [ + 'cc8704b8a60a0defa3a99a7299f2e9c3fbc395afb04ac078425ef8a1793cc030', + 'bdd46039feed17881d1e0862db347f8cf395b74fc4bcdc4e940b74e3ac1f1b13' + ], + [ + 'c533e4f7ea8555aacd9777ac5cad29b97dd4defccc53ee7ea204119b2889b197', + '6f0a256bc5efdf429a2fb6242f1a43a2d9b925bb4a4b3a26bb8e0f45eb596096' + ], + [ + 'c14f8f2ccb27d6f109f6d08d03cc96a69ba8c34eec07bbcf566d48e33da6593', + 'c359d6923bb398f7fd4473e16fe1c28475b740dd098075e6c0e8649113dc3a38' + ], + [ + 'a6cbc3046bc6a450bac24789fa17115a4c9739ed75f8f21ce441f72e0b90e6ef', + '21ae7f4680e889bb130619e2c0f95a360ceb573c70603139862afd617fa9b9f' + ], + [ + '347d6d9a02c48927ebfb86c1359b1caf130a3c0267d11ce6344b39f99d43cc38', + '60ea7f61a353524d1c987f6ecec92f086d565ab687870cb12689ff1e31c74448' + ], + [ + 'da6545d2181db8d983f7dcb375ef5866d47c67b1bf31c8cf855ef7437b72656a', + '49b96715ab6878a79e78f07ce5680c5d6673051b4935bd897fea824b77dc208a' + ], + [ + 'c40747cc9d012cb1a13b8148309c6de7ec25d6945d657146b9d5994b8feb1111', + '5ca560753be2a12fc6de6caf2cb489565db936156b9514e1bb5e83037e0fa2d4' + ], + [ + '4e42c8ec82c99798ccf3a610be870e78338c7f713348bd34c8203ef4037f3502', + '7571d74ee5e0fb92a7a8b33a07783341a5492144cc54bcc40a94473693606437' + ], + [ + '3775ab7089bc6af823aba2e1af70b236d251cadb0c86743287522a1b3b0dedea', + 'be52d107bcfa09d8bcb9736a828cfa7fac8db17bf7a76a2c42ad961409018cf7' + ], + [ + 'cee31cbf7e34ec379d94fb814d3d775ad954595d1314ba8846959e3e82f74e26', + '8fd64a14c06b589c26b947ae2bcf6bfa0149ef0be14ed4d80f448a01c43b1c6d' + ], + [ + 'b4f9eaea09b6917619f6ea6a4eb5464efddb58fd45b1ebefcdc1a01d08b47986', + '39e5c9925b5a54b07433a4f18c61726f8bb131c012ca542eb24a8ac07200682a' + ], + [ + 'd4263dfc3d2df923a0179a48966d30ce84e2515afc3dccc1b77907792ebcc60e', + '62dfaf07a0f78feb30e30d6295853ce189e127760ad6cf7fae164e122a208d54' + ], + [ + '48457524820fa65a4f8d35eb6930857c0032acc0a4a2de422233eeda897612c4', + '25a748ab367979d98733c38a1fa1c2e7dc6cc07db2d60a9ae7a76aaa49bd0f77' + ], + [ + 'dfeeef1881101f2cb11644f3a2afdfc2045e19919152923f367a1767c11cceda', + 'ecfb7056cf1de042f9420bab396793c0c390bde74b4bbdff16a83ae09a9a7517' + ], + [ + '6d7ef6b17543f8373c573f44e1f389835d89bcbc6062ced36c82df83b8fae859', + 'cd450ec335438986dfefa10c57fea9bcc521a0959b2d80bbf74b190dca712d10' + ], + [ + 'e75605d59102a5a2684500d3b991f2e3f3c88b93225547035af25af66e04541f', + 'f5c54754a8f71ee540b9b48728473e314f729ac5308b06938360990e2bfad125' + ], + [ + 'eb98660f4c4dfaa06a2be453d5020bc99a0c2e60abe388457dd43fefb1ed620c', + '6cb9a8876d9cb8520609af3add26cd20a0a7cd8a9411131ce85f44100099223e' + ], + [ + '13e87b027d8514d35939f2e6892b19922154596941888336dc3563e3b8dba942', + 'fef5a3c68059a6dec5d624114bf1e91aac2b9da568d6abeb2570d55646b8adf1' + ], + [ + 'ee163026e9fd6fe017c38f06a5be6fc125424b371ce2708e7bf4491691e5764a', + '1acb250f255dd61c43d94ccc670d0f58f49ae3fa15b96623e5430da0ad6c62b2' + ], + [ + 'b268f5ef9ad51e4d78de3a750c2dc89b1e626d43505867999932e5db33af3d80', + '5f310d4b3c99b9ebb19f77d41c1dee018cf0d34fd4191614003e945a1216e423' + ], + [ + 'ff07f3118a9df035e9fad85eb6c7bfe42b02f01ca99ceea3bf7ffdba93c4750d', + '438136d603e858a3a5c440c38eccbaddc1d2942114e2eddd4740d098ced1f0d8' + ], + [ + '8d8b9855c7c052a34146fd20ffb658bea4b9f69e0d825ebec16e8c3ce2b526a1', + 'cdb559eedc2d79f926baf44fb84ea4d44bcf50fee51d7ceb30e2e7f463036758' + ], + [ + '52db0b5384dfbf05bfa9d472d7ae26dfe4b851ceca91b1eba54263180da32b63', + 'c3b997d050ee5d423ebaf66a6db9f57b3180c902875679de924b69d84a7b375' + ], + [ + 'e62f9490d3d51da6395efd24e80919cc7d0f29c3f3fa48c6fff543becbd43352', + '6d89ad7ba4876b0b22c2ca280c682862f342c8591f1daf5170e07bfd9ccafa7d' + ], + [ + '7f30ea2476b399b4957509c88f77d0191afa2ff5cb7b14fd6d8e7d65aaab1193', + 'ca5ef7d4b231c94c3b15389a5f6311e9daff7bb67b103e9880ef4bff637acaec' + ], + [ + '5098ff1e1d9f14fb46a210fada6c903fef0fb7b4a1dd1d9ac60a0361800b7a00', + '9731141d81fc8f8084d37c6e7542006b3ee1b40d60dfe5362a5b132fd17ddc0' + ], + [ + '32b78c7de9ee512a72895be6b9cbefa6e2f3c4ccce445c96b9f2c81e2778ad58', + 'ee1849f513df71e32efc3896ee28260c73bb80547ae2275ba497237794c8753c' + ], + [ + 'e2cb74fddc8e9fbcd076eef2a7c72b0ce37d50f08269dfc074b581550547a4f7', + 'd3aa2ed71c9dd2247a62df062736eb0baddea9e36122d2be8641abcb005cc4a4' + ], + [ + '8438447566d4d7bedadc299496ab357426009a35f235cb141be0d99cd10ae3a8', + 'c4e1020916980a4da5d01ac5e6ad330734ef0d7906631c4f2390426b2edd791f' + ], + [ + '4162d488b89402039b584c6fc6c308870587d9c46f660b878ab65c82c711d67e', + '67163e903236289f776f22c25fb8a3afc1732f2b84b4e95dbda47ae5a0852649' + ], + [ + '3fad3fa84caf0f34f0f89bfd2dcf54fc175d767aec3e50684f3ba4a4bf5f683d', + 'cd1bc7cb6cc407bb2f0ca647c718a730cf71872e7d0d2a53fa20efcdfe61826' + ], + [ + '674f2600a3007a00568c1a7ce05d0816c1fb84bf1370798f1c69532faeb1a86b', + '299d21f9413f33b3edf43b257004580b70db57da0b182259e09eecc69e0d38a5' + ], + [ + 'd32f4da54ade74abb81b815ad1fb3b263d82d6c692714bcff87d29bd5ee9f08f', + 'f9429e738b8e53b968e99016c059707782e14f4535359d582fc416910b3eea87' + ], + [ + '30e4e670435385556e593657135845d36fbb6931f72b08cb1ed954f1e3ce3ff6', + '462f9bce619898638499350113bbc9b10a878d35da70740dc695a559eb88db7b' + ], + [ + 'be2062003c51cc3004682904330e4dee7f3dcd10b01e580bf1971b04d4cad297', + '62188bc49d61e5428573d48a74e1c655b1c61090905682a0d5558ed72dccb9bc' + ], + [ + '93144423ace3451ed29e0fb9ac2af211cb6e84a601df5993c419859fff5df04a', + '7c10dfb164c3425f5c71a3f9d7992038f1065224f72bb9d1d902a6d13037b47c' + ], + [ + 'b015f8044f5fcbdcf21ca26d6c34fb8197829205c7b7d2a7cb66418c157b112c', + 'ab8c1e086d04e813744a655b2df8d5f83b3cdc6faa3088c1d3aea1454e3a1d5f' + ], + [ + 'd5e9e1da649d97d89e4868117a465a3a4f8a18de57a140d36b3f2af341a21b52', + '4cb04437f391ed73111a13cc1d4dd0db1693465c2240480d8955e8592f27447a' + ], + [ + 'd3ae41047dd7ca065dbf8ed77b992439983005cd72e16d6f996a5316d36966bb', + 'bd1aeb21ad22ebb22a10f0303417c6d964f8cdd7df0aca614b10dc14d125ac46' + ], + [ + '463e2763d885f958fc66cdd22800f0a487197d0a82e377b49f80af87c897b065', + 'bfefacdb0e5d0fd7df3a311a94de062b26b80c61fbc97508b79992671ef7ca7f' + ], + [ + '7985fdfd127c0567c6f53ec1bb63ec3158e597c40bfe747c83cddfc910641917', + '603c12daf3d9862ef2b25fe1de289aed24ed291e0ec6708703a5bd567f32ed03' + ], + [ + '74a1ad6b5f76e39db2dd249410eac7f99e74c59cb83d2d0ed5ff1543da7703e9', + 'cc6157ef18c9c63cd6193d83631bbea0093e0968942e8c33d5737fd790e0db08' + ], + [ + '30682a50703375f602d416664ba19b7fc9bab42c72747463a71d0896b22f6da3', + '553e04f6b018b4fa6c8f39e7f311d3176290d0e0f19ca73f17714d9977a22ff8' + ], + [ + '9e2158f0d7c0d5f26c3791efefa79597654e7a2b2464f52b1ee6c1347769ef57', + '712fcdd1b9053f09003a3481fa7762e9ffd7c8ef35a38509e2fbf2629008373' + ], + [ + '176e26989a43c9cfeba4029c202538c28172e566e3c4fce7322857f3be327d66', + 'ed8cc9d04b29eb877d270b4878dc43c19aefd31f4eee09ee7b47834c1fa4b1c3' + ], + [ + '75d46efea3771e6e68abb89a13ad747ecf1892393dfc4f1b7004788c50374da8', + '9852390a99507679fd0b86fd2b39a868d7efc22151346e1a3ca4726586a6bed8' + ], + [ + '809a20c67d64900ffb698c4c825f6d5f2310fb0451c869345b7319f645605721', + '9e994980d9917e22b76b061927fa04143d096ccc54963e6a5ebfa5f3f8e286c1' + ], + [ + '1b38903a43f7f114ed4500b4eac7083fdefece1cf29c63528d563446f972c180', + '4036edc931a60ae889353f77fd53de4a2708b26b6f5da72ad3394119daf408f9' + ] + ] + } +}; + +var curves_1 = createCommonjsModule(function (module, exports) { + +var curves = exports; + + + + + +var assert = utils_1$1.assert; + +function PresetCurve(options) { + if (options.type === 'short') + this.curve = new curve_1.short(options); + else if (options.type === 'edwards') + this.curve = new curve_1.edwards(options); + else if (options.type === 'mont') + this.curve = new curve_1.mont(options); + else throw new Error('Unknown curve type.'); + this.g = this.curve.g; + this.n = this.curve.n; + this.hash = options.hash; + + assert(this.g.validate(), 'Invalid curve'); + assert(this.g.mul(this.n).isInfinity(), 'Invalid curve, n*G != O'); +} +curves.PresetCurve = PresetCurve; + +function defineCurve(name, options) { + Object.defineProperty(curves, name, { + configurable: true, + enumerable: true, + get: function() { + var curve = new PresetCurve(options); + Object.defineProperty(curves, name, { + configurable: true, + enumerable: true, + value: curve + }); + return curve; + } + }); +} + +defineCurve('p192', { + type: 'short', + prime: 'p192', + p: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff', + a: 'ffffffff ffffffff ffffffff fffffffe ffffffff fffffffc', + b: '64210519 e59c80e7 0fa7e9ab 72243049 feb8deec c146b9b1', + n: 'ffffffff ffffffff ffffffff 99def836 146bc9b1 b4d22831', + hash: hash_1.sha256, + gRed: false, + g: [ + '188da80e b03090f6 7cbf20eb 43a18800 f4ff0afd 82ff1012', + '07192b95 ffc8da78 631011ed 6b24cdd5 73f977a1 1e794811' + ] +}); + +defineCurve('p224', { + type: 'short', + prime: 'p224', + p: 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001', + a: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff fffffffe', + b: 'b4050a85 0c04b3ab f5413256 5044b0b7 d7bfd8ba 270b3943 2355ffb4', + n: 'ffffffff ffffffff ffffffff ffff16a2 e0b8f03e 13dd2945 5c5c2a3d', + hash: hash_1.sha256, + gRed: false, + g: [ + 'b70e0cbd 6bb4bf7f 321390b9 4a03c1d3 56c21122 343280d6 115c1d21', + 'bd376388 b5f723fb 4c22dfe6 cd4375a0 5a074764 44d58199 85007e34' + ] +}); + +defineCurve('p256', { + type: 'short', + prime: null, + p: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff', + a: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff fffffffc', + b: '5ac635d8 aa3a93e7 b3ebbd55 769886bc 651d06b0 cc53b0f6 3bce3c3e 27d2604b', + n: 'ffffffff 00000000 ffffffff ffffffff bce6faad a7179e84 f3b9cac2 fc632551', + hash: hash_1.sha256, + gRed: false, + g: [ + '6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296', + '4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5' + ] +}); + +defineCurve('p384', { + type: 'short', + prime: null, + p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'fffffffe ffffffff 00000000 00000000 ffffffff', + a: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'fffffffe ffffffff 00000000 00000000 fffffffc', + b: 'b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112 0314088f ' + + '5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef', + n: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff c7634d81 ' + + 'f4372ddf 581a0db2 48b0a77a ecec196a ccc52973', + hash: hash_1.sha384, + gRed: false, + g: [ + 'aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98 59f741e0 82542a38 ' + + '5502f25d bf55296c 3a545e38 72760ab7', + '3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c e9da3113 b5f0b8c0 ' + + '0a60b1ce 1d7e819d 7a431d7c 90ea0e5f' + ] +}); + +defineCurve('p521', { + type: 'short', + prime: null, + p: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff ffffffff ffffffff ffffffff', + a: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff ffffffff ffffffff fffffffc', + b: '00000051 953eb961 8e1c9a1f 929a21a0 b68540ee a2da725b ' + + '99b315f3 b8b48991 8ef109e1 56193951 ec7e937b 1652c0bd ' + + '3bb1bf07 3573df88 3d2c34f1 ef451fd4 6b503f00', + n: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff fffffffa 51868783 bf2f966b 7fcc0148 ' + + 'f709a5d0 3bb5c9b8 899c47ae bb6fb71e 91386409', + hash: hash_1.sha512, + gRed: false, + g: [ + '000000c6 858e06b7 0404e9cd 9e3ecb66 2395b442 9c648139 ' + + '053fb521 f828af60 6b4d3dba a14b5e77 efe75928 fe1dc127 ' + + 'a2ffa8de 3348b3c1 856a429b f97e7e31 c2e5bd66', + '00000118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd9 98f54449 ' + + '579b4468 17afbd17 273e662c 97ee7299 5ef42640 c550b901 ' + + '3fad0761 353c7086 a272c240 88be9476 9fd16650' + ] +}); + +// https://tools.ietf.org/html/rfc7748#section-4.1 +defineCurve('curve25519', { + type: 'mont', + prime: 'p25519', + p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', + a: '76d06', + b: '1', + n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', + cofactor: '8', + hash: hash_1.sha256, + gRed: false, + g: [ + '9' + ] +}); + +defineCurve('ed25519', { + type: 'edwards', + prime: 'p25519', + p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', + a: '-1', + c: '1', + // -121665 * (121666^(-1)) (mod P) + d: '52036cee2b6ffe73 8cc740797779e898 00700a4d4141d8ab 75eb4dca135978a3', + n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', + cofactor: '8', + hash: hash_1.sha256, + gRed: false, + g: [ + '216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a', + // 4/5 + '6666666666666666666666666666666666666666666666666666666666666658' + ] +}); + +// https://tools.ietf.org/html/rfc5639#section-3.4 +defineCurve('brainpoolP256r1', { + type: 'short', + prime: null, + p: 'A9FB57DB A1EEA9BC 3E660A90 9D838D72 6E3BF623 D5262028 2013481D 1F6E5377', + a: '7D5A0975 FC2C3057 EEF67530 417AFFE7 FB8055C1 26DC5C6C E94A4B44 F330B5D9', + b: '26DC5C6C E94A4B44 F330B5D9 BBD77CBF 95841629 5CF7E1CE 6BCCDC18 FF8C07B6', + n: 'A9FB57DB A1EEA9BC 3E660A90 9D838D71 8C397AA3 B561A6F7 901E0E82 974856A7', + hash: hash_1.sha256, // or 384, or 512 + gRed: false, + g: [ + '8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262', + '547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997' + ] +}); + +// https://tools.ietf.org/html/rfc5639#section-3.6 +defineCurve('brainpoolP384r1', { + type: 'short', + prime: null, + p: '8CB91E82 A3386D28 0F5D6F7E 50E641DF 152F7109 ED5456B4 12B1DA19 7FB71123' + + 'ACD3A729 901D1A71 87470013 3107EC53', + a: '7BC382C6 3D8C150C 3C72080A CE05AFA0 C2BEA28E 4FB22787 139165EF BA91F90F' + + '8AA5814A 503AD4EB 04A8C7DD 22CE2826', + b: '04A8C7DD 22CE2826 8B39B554 16F0447C 2FB77DE1 07DCD2A6 2E880EA5 3EEB62D5' + + '7CB43902 95DBC994 3AB78696 FA504C11', + n: '8CB91E82 A3386D28 0F5D6F7E 50E641DF 152F7109 ED5456B3 1F166E6C AC0425A7' + + 'CF3AB6AF 6B7FC310 3B883202 E9046565', + hash: hash_1.sha384, // or 512 + gRed: false, + g: [ + '1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10' + + 'E8E826E03436D646AAEF87B2E247D4AF1E', + '8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129' + + '280E4646217791811142820341263C5315' + ] +}); + +// https://tools.ietf.org/html/rfc5639#section-3.7 +defineCurve('brainpoolP512r1', { + type: 'short', + prime: null, + p: 'AADD9DB8 DBE9C48B 3FD4E6AE 33C9FC07 CB308DB3 B3C9D20E D6639CCA 70330871' + + '7D4D9B00 9BC66842 AECDA12A E6A380E6 2881FF2F 2D82C685 28AA6056 583A48F3', + a: '7830A331 8B603B89 E2327145 AC234CC5 94CBDD8D 3DF91610 A83441CA EA9863BC' + + '2DED5D5A A8253AA1 0A2EF1C9 8B9AC8B5 7F1117A7 2BF2C7B9 E7C1AC4D 77FC94CA', + b: '3DF91610 A83441CA EA9863BC 2DED5D5A A8253AA1 0A2EF1C9 8B9AC8B5 7F1117A7' + + '2BF2C7B9 E7C1AC4D 77FC94CA DC083E67 984050B7 5EBAE5DD 2809BD63 8016F723', + n: 'AADD9DB8 DBE9C48B 3FD4E6AE 33C9FC07 CB308DB3 B3C9D20E D6639CCA 70330870' + + '553E5C41 4CA92619 41866119 7FAC1047 1DB1D381 085DDADD B5879682 9CA90069', + hash: hash_1.sha512, + gRed: false, + g: [ + '81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D009' + + '8EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822', + '7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F81' + + '11B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892' + ] +}); + +// https://en.bitcoin.it/wiki/Secp256k1 +var pre; +try { + pre = secp256k1; +} catch (e) { + pre = undefined; +} + +defineCurve('secp256k1', { + type: 'short', + prime: 'k256', + p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f', + a: '0', + b: '7', + n: 'ffffffff ffffffff ffffffff fffffffe baaedce6 af48a03b bfd25e8c d0364141', + h: '1', + hash: hash_1.sha256, + + // Precomputed endomorphism + beta: '7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee', + lambda: '5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72', + basis: [ + { + a: '3086d221a7d46bcde86c90e49284eb15', + b: '-e4437ed6010e88286f547fa90abfe4c3' + }, + { + a: '114ca50f7a8e2f3f657c1108d9d44cfd8', + b: '3086d221a7d46bcde86c90e49284eb15' + } + ], + + gRed: false, + g: [ + '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', + '483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', + pre + ] +}); +}); + +function HmacDRBG(options) { + if (!(this instanceof HmacDRBG)) + return new HmacDRBG(options); + this.hash = options.hash; + this.predResist = !!options.predResist; + + this.outLen = this.hash.outSize; + this.minEntropy = options.minEntropy || this.hash.hmacStrength; + + this._reseed = null; + this.reseedInterval = null; + this.K = null; + this.V = null; + + var entropy = utils_1.toArray(options.entropy, options.entropyEnc || 'hex'); + var nonce = utils_1.toArray(options.nonce, options.nonceEnc || 'hex'); + var pers = utils_1.toArray(options.pers, options.persEnc || 'hex'); + minimalisticAssert(entropy.length >= (this.minEntropy / 8), + 'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits'); + this._init(entropy, nonce, pers); +} +var hmacDrbg = HmacDRBG; + +HmacDRBG.prototype._init = function init(entropy, nonce, pers) { + var seed = entropy.concat(nonce).concat(pers); + + this.K = new Array(this.outLen / 8); + this.V = new Array(this.outLen / 8); + for (var i = 0; i < this.V.length; i++) { + this.K[i] = 0x00; + this.V[i] = 0x01; + } + + this._update(seed); + this._reseed = 1; + this.reseedInterval = 0x1000000000000; // 2^48 +}; + +HmacDRBG.prototype._hmac = function hmac() { + return new hash_1.hmac(this.hash, this.K); +}; + +HmacDRBG.prototype._update = function update(seed) { + var kmac = this._hmac() + .update(this.V) + .update([ 0x00 ]); + if (seed) + kmac = kmac.update(seed); + this.K = kmac.digest(); + this.V = this._hmac().update(this.V).digest(); + if (!seed) + return; + + this.K = this._hmac() + .update(this.V) + .update([ 0x01 ]) + .update(seed) + .digest(); + this.V = this._hmac().update(this.V).digest(); +}; + +HmacDRBG.prototype.reseed = function reseed(entropy, entropyEnc, add, addEnc) { + // Optional entropy enc + if (typeof entropyEnc !== 'string') { + addEnc = add; + add = entropyEnc; + entropyEnc = null; + } + + entropy = utils_1.toArray(entropy, entropyEnc); + add = utils_1.toArray(add, addEnc); + + minimalisticAssert(entropy.length >= (this.minEntropy / 8), + 'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits'); + + this._update(entropy.concat(add || [])); + this._reseed = 1; +}; + +HmacDRBG.prototype.generate = function generate(len, enc, add, addEnc) { + if (this._reseed > this.reseedInterval) + throw new Error('Reseed is required'); + + // Optional encoding + if (typeof enc !== 'string') { + addEnc = add; + add = enc; + enc = null; + } + + // Optional additional data + if (add) { + add = utils_1.toArray(add, addEnc || 'hex'); + this._update(add); + } + + var temp = []; + while (temp.length < len) { + this.V = this._hmac().update(this.V).digest(); + temp = temp.concat(this.V); + } + + var res = temp.slice(0, len); + this._update(add); + this._reseed++; + return utils_1.encode(res, enc); +}; + +var assert$5 = utils_1$1.assert; + +function KeyPair(ec, options) { + this.ec = ec; + this.priv = null; + this.pub = null; + + // KeyPair(ec, { priv: ..., pub: ... }) + if (options.priv) + this._importPrivate(options.priv, options.privEnc); + if (options.pub) + this._importPublic(options.pub, options.pubEnc); +} +var key = KeyPair; + +KeyPair.fromPublic = function fromPublic(ec, pub, enc) { + if (pub instanceof KeyPair) + return pub; + + return new KeyPair(ec, { + pub: pub, + pubEnc: enc + }); +}; + +KeyPair.fromPrivate = function fromPrivate(ec, priv, enc) { + if (priv instanceof KeyPair) + return priv; + + return new KeyPair(ec, { + priv: priv, + privEnc: enc + }); +}; + +// TODO: should not validate for X25519 +KeyPair.prototype.validate = function validate() { + var pub = this.getPublic(); + + if (pub.isInfinity()) + return { result: false, reason: 'Invalid public key' }; + if (!pub.validate()) + return { result: false, reason: 'Public key is not a point' }; + if (!pub.mul(this.ec.curve.n).isInfinity()) + return { result: false, reason: 'Public key * N != O' }; + + return { result: true, reason: null }; +}; + +KeyPair.prototype.getPublic = function getPublic(enc, compact) { + if (!this.pub) + this.pub = this.ec.g.mul(this.priv); + + if (!enc) + return this.pub; + + return this.pub.encode(enc, compact); +}; + +KeyPair.prototype.getPrivate = function getPrivate(enc) { + if (enc === 'hex') + return this.priv.toString(16, 2); + else + return this.priv; +}; + +KeyPair.prototype._importPrivate = function _importPrivate(key, enc) { + this.priv = new bn(key, enc || 16); + + // For Curve25519/Curve448 we have a specific procedure. + // TODO Curve448 + if (this.ec.curve.type === 'mont') { + var one = this.ec.curve.one; + var mask = one.ushln(255 - 3).sub(one).ushln(3); + this.priv = this.priv.or(one.ushln(255 - 1)); + this.priv = this.priv.and(mask); + } else + // Ensure that the priv won't be bigger than n, otherwise we may fail + // in fixed multiplication method + this.priv = this.priv.umod(this.ec.curve.n); +}; + +KeyPair.prototype._importPublic = function _importPublic(key, enc) { + if (key.x || key.y) { + // Montgomery points only have an `x` coordinate. + // Weierstrass/Edwards points on the other hand have both `x` and + // `y` coordinates. + if (this.ec.curve.type === 'mont') { + assert$5(key.x, 'Need x coordinate'); + } else if (this.ec.curve.type === 'short' || + this.ec.curve.type === 'edwards') { + assert$5(key.x && key.y, 'Need both x and y coordinate'); + } + this.pub = this.ec.curve.point(key.x, key.y); + return; + } + this.pub = this.ec.curve.decodePoint(key, enc); +}; + +// ECDH +KeyPair.prototype.derive = function derive(pub) { + return pub.mul(this.priv).getX(); +}; + +// ECDSA +KeyPair.prototype.sign = function sign(msg, enc, options) { + return this.ec.sign(msg, this, enc, options); +}; + +KeyPair.prototype.verify = function verify(msg, signature) { + return this.ec.verify(msg, signature, this); +}; + +KeyPair.prototype.inspect = function inspect() { + return ''; +}; + +var assert$6 = utils_1$1.assert; + +function Signature$1(options, enc) { + if (options instanceof Signature$1) + return options; + + if (this._importDER(options, enc)) + return; + + assert$6(options.r && options.s, 'Signature without r or s'); + this.r = new bn(options.r, 16); + this.s = new bn(options.s, 16); + if (options.recoveryParam === undefined) + this.recoveryParam = null; + else + this.recoveryParam = options.recoveryParam; +} +var signature$1 = Signature$1; + +function Position() { + this.place = 0; +} + +function getLength(buf, p) { + var initial = buf[p.place++]; + if (!(initial & 0x80)) { + return initial; + } + var octetLen = initial & 0xf; + var val = 0; + for (var i = 0, off = p.place; i < octetLen; i++, off++) { + val <<= 8; + val |= buf[off]; + } + p.place = off; + return val; +} + +function rmPadding(buf) { + var i = 0; + var len = buf.length - 1; + while (!buf[i] && !(buf[i + 1] & 0x80) && i < len) { + i++; + } + if (i === 0) { + return buf; + } + return buf.slice(i); +} + +Signature$1.prototype._importDER = function _importDER(data, enc) { + data = utils_1$1.toArray(data, enc); + var p = new Position(); + if (data[p.place++] !== 0x30) { + return false; + } + var len = getLength(data, p); + if ((len + p.place) !== data.length) { + return false; + } + if (data[p.place++] !== 0x02) { + return false; + } + var rlen = getLength(data, p); + var r = data.slice(p.place, rlen + p.place); + p.place += rlen; + if (data[p.place++] !== 0x02) { + return false; + } + var slen = getLength(data, p); + if (data.length !== slen + p.place) { + return false; + } + var s = data.slice(p.place, slen + p.place); + if (r[0] === 0 && (r[1] & 0x80)) { + r = r.slice(1); + } + if (s[0] === 0 && (s[1] & 0x80)) { + s = s.slice(1); + } + + this.r = new bn(r); + this.s = new bn(s); + this.recoveryParam = null; + + return true; +}; + +function constructLength(arr, len) { + if (len < 0x80) { + arr.push(len); + return; + } + var octets = 1 + (Math.log(len) / Math.LN2 >>> 3); + arr.push(octets | 0x80); + while (--octets) { + arr.push((len >>> (octets << 3)) & 0xff); + } + arr.push(len); +} + +Signature$1.prototype.toDER = function toDER(enc) { + var r = this.r.toArray(); + var s = this.s.toArray(); + + // Pad values + if (r[0] & 0x80) + r = [ 0 ].concat(r); + // Pad values + if (s[0] & 0x80) + s = [ 0 ].concat(s); + + r = rmPadding(r); + s = rmPadding(s); + + while (!s[0] && !(s[1] & 0x80)) { + s = s.slice(1); + } + var arr = [ 0x02 ]; + constructLength(arr, r.length); + arr = arr.concat(r); + arr.push(0x02); + constructLength(arr, s.length); + var backHalf = arr.concat(s); + var res = [ 0x30 ]; + constructLength(res, backHalf.length); + res = res.concat(backHalf); + return utils_1$1.encode(res, enc); +}; + +var assert$7 = utils_1$1.assert; + + + + +function EC(options) { + if (!(this instanceof EC)) + return new EC(options); + + // Shortcut `elliptic.ec(curve-name)` + if (typeof options === 'string') { + assert$7(curves_1.hasOwnProperty(options), 'Unknown curve ' + options); + + options = curves_1[options]; + } + + // Shortcut for `elliptic.ec(elliptic.curves.curveName)` + if (options instanceof curves_1.PresetCurve) + options = { curve: options }; + + this.curve = options.curve.curve; + this.n = this.curve.n; + this.nh = this.n.ushrn(1); + this.g = this.curve.g; + + // Point on curve + this.g = options.curve.g; + this.g.precompute(options.curve.n.bitLength() + 1); + + // Hash function for DRBG + this.hash = options.hash || options.curve.hash; +} +var ec = EC; + +EC.prototype.keyPair = function keyPair(options) { + return new key(this, options); +}; + +EC.prototype.keyFromPrivate = function keyFromPrivate(priv, enc) { + return key.fromPrivate(this, priv, enc); +}; + +EC.prototype.keyFromPublic = function keyFromPublic(pub, enc) { + return key.fromPublic(this, pub, enc); +}; + +EC.prototype.genKeyPair = function genKeyPair(options) { + if (!options) + options = {}; + + // Instantiate Hmac_DRBG + var drbg = new hmacDrbg({ + hash: this.hash, + pers: options.pers, + persEnc: options.persEnc || 'utf8', + entropy: options.entropy || brorand(this.hash.hmacStrength), + entropyEnc: options.entropy && options.entropyEnc || 'utf8', + nonce: this.n.toArray() + }); + + // Key generation for curve25519 is simpler + if (this.curve.type === 'mont') { + var priv = new bn(drbg.generate(32)); + return this.keyFromPrivate(priv); + } + + var bytes = this.n.byteLength(); + var ns2 = this.n.sub(new bn(2)); + do { + var priv = new bn(drbg.generate(bytes)); + if (priv.cmp(ns2) > 0) + continue; + + priv.iaddn(1); + return this.keyFromPrivate(priv); + } while (true); +}; + +EC.prototype._truncateToN = function truncateToN(msg, truncOnly, bitSize) { + bitSize = bitSize || msg.byteLength() * 8; + var delta = bitSize - this.n.bitLength(); + if (delta > 0) + msg = msg.ushrn(delta); + if (!truncOnly && msg.cmp(this.n) >= 0) + return msg.sub(this.n); + else + return msg; +}; + +EC.prototype.truncateMsg = function truncateMSG(msg) { + // Bit size is only determined correctly for Uint8Arrays and hex strings + var bitSize; + if (msg instanceof Uint8Array) { + bitSize = msg.byteLength * 8; + msg = this._truncateToN(new bn(msg, 16), false, bitSize); + } else if (typeof msg === 'string') { + bitSize = msg.length * 4; + msg = this._truncateToN(new bn(msg, 16), false, bitSize); + } else { + msg = this._truncateToN(new bn(msg, 16)); + } + return msg; +}; + +EC.prototype.sign = function sign(msg, key, enc, options) { + if (typeof enc === 'object') { + options = enc; + enc = null; + } + if (!options) + options = {}; + + key = this.keyFromPrivate(key, enc); + msg = this.truncateMsg(msg); + + // Zero-extend key to provide enough entropy + var bytes = this.n.byteLength(); + var bkey = key.getPrivate().toArray('be', bytes); + + // Zero-extend nonce to have the same byte size as N + var nonce = msg.toArray('be', bytes); + + // Instantiate Hmac_DRBG + var drbg = new hmacDrbg({ + hash: this.hash, + entropy: bkey, + nonce: nonce, + pers: options.pers, + persEnc: options.persEnc || 'utf8' + }); + + // Number of bytes to generate + var ns1 = this.n.sub(new bn(1)); + + for (var iter = 0; true; iter++) { + var k = options.k ? + options.k(iter) : + new bn(drbg.generate(this.n.byteLength())); + k = this._truncateToN(k, true); + if (k.cmpn(1) <= 0 || k.cmp(ns1) >= 0) + continue; + + var kp = this.g.mul(k); + if (kp.isInfinity()) + continue; + + var kpX = kp.getX(); + var r = kpX.umod(this.n); + if (r.cmpn(0) === 0) + continue; + + var s = k.invm(this.n).mul(r.mul(key.getPrivate()).iadd(msg)); + s = s.umod(this.n); + if (s.cmpn(0) === 0) + continue; + + var recoveryParam = (kp.getY().isOdd() ? 1 : 0) | + (kpX.cmp(r) !== 0 ? 2 : 0); + + // Use complement of `s`, if it is > `n / 2` + if (options.canonical && s.cmp(this.nh) > 0) { + s = this.n.sub(s); + recoveryParam ^= 1; + } + + return new signature$1({ r: r, s: s, recoveryParam: recoveryParam }); + } +}; + +EC.prototype.verify = function verify(msg, signature, key, enc) { + key = this.keyFromPublic(key, enc); + signature = new signature$1(signature, 'hex'); + // Fallback to the old code + var ret = this._verify(this.truncateMsg(msg), signature, key) || + this._verify(this._truncateToN(new bn(msg, 16)), signature, key); + return ret; +}; + +EC.prototype._verify = function _verify(msg, signature, key) { + // Perform primitive values validation + var r = signature.r; + var s = signature.s; + if (r.cmpn(1) < 0 || r.cmp(this.n) >= 0) + return false; + if (s.cmpn(1) < 0 || s.cmp(this.n) >= 0) + return false; + + // Validate signature + var sinv = s.invm(this.n); + var u1 = sinv.mul(msg).umod(this.n); + var u2 = sinv.mul(r).umod(this.n); + + if (!this.curve._maxwellTrick) { + var p = this.g.mulAdd(u1, key.getPublic(), u2); + if (p.isInfinity()) + return false; + + return p.getX().umod(this.n).cmp(r) === 0; + } + + // NOTE: Greg Maxwell's trick, inspired by: + // https://git.io/vad3K + + var p = this.g.jmulAdd(u1, key.getPublic(), u2); + if (p.isInfinity()) + return false; + + // Compare `p.x` of Jacobian point with `r`, + // this will do `p.x == r * p.z^2` instead of multiplying `p.x` by the + // inverse of `p.z^2` + return p.eqXToP(r); +}; + +EC.prototype.recoverPubKey = function(msg, signature, j, enc) { + assert$7((3 & j) === j, 'The recovery param is more than two bits'); + signature = new signature$1(signature, enc); + + var n = this.n; + var e = new bn(msg); + var r = signature.r; + var s = signature.s; + + // A set LSB signifies that the y-coordinate is odd + var isYOdd = j & 1; + var isSecondKey = j >> 1; + if (r.cmp(this.curve.p.umod(this.curve.n)) >= 0 && isSecondKey) + throw new Error('Unable to find sencond key candinate'); + + // 1.1. Let x = r + jn. + if (isSecondKey) + r = this.curve.pointFromX(r.add(this.curve.n), isYOdd); + else + r = this.curve.pointFromX(r, isYOdd); + + var rInv = signature.r.invm(n); + var s1 = n.sub(e).mul(rInv).umod(n); + var s2 = s.mul(rInv).umod(n); + + // 1.6.1 Compute Q = r^-1 (sR - eG) + // Q = r^-1 (sR + -eG) + return this.g.mulAdd(s1, r, s2); +}; + +EC.prototype.getKeyRecoveryParam = function(e, signature, Q, enc) { + signature = new signature$1(signature, enc); + if (signature.recoveryParam !== null) + return signature.recoveryParam; + + for (var i = 0; i < 4; i++) { + var Qprime; + try { + Qprime = this.recoverPubKey(e, signature, i); + } catch (e) { + continue; + } + + if (Qprime.eq(Q)) + return i; + } + throw new Error('Unable to find valid recovery factor'); +}; + +var assert$8 = utils_1$1.assert; +var parseBytes = utils_1$1.parseBytes; +var cachedProperty = utils_1$1.cachedProperty; + +/** +* @param {EDDSA} eddsa - instance +* @param {Object} params - public/private key parameters +* +* @param {Array} [params.secret] - secret seed bytes +* @param {Point} [params.pub] - public key point (aka `A` in eddsa terms) +* @param {Array} [params.pub] - public key point encoded as bytes +* +*/ +function KeyPair$1(eddsa, params) { + this.eddsa = eddsa; + if (params.hasOwnProperty('secret')) + this._secret = parseBytes(params.secret); + if (eddsa.isPoint(params.pub)) + this._pub = params.pub; + else { + this._pubBytes = parseBytes(params.pub); + if (this._pubBytes && this._pubBytes.length === 33 && + this._pubBytes[0] === 0x40) + this._pubBytes = this._pubBytes.slice(1, 33); + if (this._pubBytes && this._pubBytes.length !== 32) + throw new Error('Unknown point compression format'); + } +} + +KeyPair$1.fromPublic = function fromPublic(eddsa, pub) { + if (pub instanceof KeyPair$1) + return pub; + return new KeyPair$1(eddsa, { pub: pub }); +}; + +KeyPair$1.fromSecret = function fromSecret(eddsa, secret) { + if (secret instanceof KeyPair$1) + return secret; + return new KeyPair$1(eddsa, { secret: secret }); +}; + +KeyPair$1.prototype.secret = function secret() { + return this._secret; +}; + +cachedProperty(KeyPair$1, 'pubBytes', function pubBytes() { + return this.eddsa.encodePoint(this.pub()); +}); + +cachedProperty(KeyPair$1, 'pub', function pub() { + if (this._pubBytes) + return this.eddsa.decodePoint(this._pubBytes); + return this.eddsa.g.mul(this.priv()); +}); + +cachedProperty(KeyPair$1, 'privBytes', function privBytes() { + var eddsa = this.eddsa; + var hash = this.hash(); + var lastIx = eddsa.encodingLength - 1; + + // https://tools.ietf.org/html/rfc8032#section-5.1.5 + var a = hash.slice(0, eddsa.encodingLength); + a[0] &= 248; + a[lastIx] &= 127; + a[lastIx] |= 64; + + return a; +}); + +cachedProperty(KeyPair$1, 'priv', function priv() { + return this.eddsa.decodeInt(this.privBytes()); +}); + +cachedProperty(KeyPair$1, 'hash', function hash() { + return this.eddsa.hash().update(this.secret()).digest(); +}); + +cachedProperty(KeyPair$1, 'messagePrefix', function messagePrefix() { + return this.hash().slice(this.eddsa.encodingLength); +}); + +KeyPair$1.prototype.sign = function sign(message) { + assert$8(this._secret, 'KeyPair can only verify'); + return this.eddsa.sign(message, this); +}; + +KeyPair$1.prototype.verify = function verify(message, sig) { + return this.eddsa.verify(message, sig, this); +}; + +KeyPair$1.prototype.getSecret = function getSecret(enc) { + assert$8(this._secret, 'KeyPair is public only'); + return utils_1$1.encode(this.secret(), enc); +}; + +KeyPair$1.prototype.getPublic = function getPublic(enc, compact) { + return utils_1$1.encode((compact ? [ 0x40 ] : []).concat(this.pubBytes()), enc); +}; + +var key$1 = KeyPair$1; + +var assert$9 = utils_1$1.assert; +var cachedProperty$1 = utils_1$1.cachedProperty; +var parseBytes$1 = utils_1$1.parseBytes; + +/** +* @param {EDDSA} eddsa - eddsa instance +* @param {Array|Object} sig - +* @param {Array|Point} [sig.R] - R point as Point or bytes +* @param {Array|bn} [sig.S] - S scalar as bn or bytes +* @param {Array} [sig.Rencoded] - R point encoded +* @param {Array} [sig.Sencoded] - S scalar encoded +*/ +function Signature$2(eddsa, sig) { + this.eddsa = eddsa; + + if (typeof sig !== 'object') + sig = parseBytes$1(sig); + + if (Array.isArray(sig)) { + sig = { + R: sig.slice(0, eddsa.encodingLength), + S: sig.slice(eddsa.encodingLength) + }; + } + + assert$9(sig.R && sig.S, 'Signature without R or S'); + + if (eddsa.isPoint(sig.R)) + this._R = sig.R; + if (sig.S instanceof bn) + this._S = sig.S; + + this._Rencoded = Array.isArray(sig.R) ? sig.R : sig.Rencoded; + this._Sencoded = Array.isArray(sig.S) ? sig.S : sig.Sencoded; +} + +cachedProperty$1(Signature$2, 'S', function S() { + return this.eddsa.decodeInt(this.Sencoded()); +}); + +cachedProperty$1(Signature$2, 'R', function R() { + return this.eddsa.decodePoint(this.Rencoded()); +}); + +cachedProperty$1(Signature$2, 'Rencoded', function Rencoded() { + return this.eddsa.encodePoint(this.R()); +}); + +cachedProperty$1(Signature$2, 'Sencoded', function Sencoded() { + return this.eddsa.encodeInt(this.S()); +}); + +Signature$2.prototype.toBytes = function toBytes() { + return this.Rencoded().concat(this.Sencoded()); +}; + +Signature$2.prototype.toHex = function toHex() { + return utils_1$1.encode(this.toBytes(), 'hex').toUpperCase(); +}; + +var signature$2 = Signature$2; + +var assert$a = utils_1$1.assert; +var parseBytes$2 = utils_1$1.parseBytes; + + + +function EDDSA(curve) { + assert$a(curve === 'ed25519', 'only tested with ed25519 so far'); + + if (!(this instanceof EDDSA)) + return new EDDSA(curve); + + var curve = curves_1[curve].curve; + this.curve = curve; + this.g = curve.g; + this.g.precompute(curve.n.bitLength() + 1); + + this.pointClass = curve.point().constructor; + this.encodingLength = Math.ceil(curve.n.bitLength() / 8); + this.hash = hash_1.sha512; +} + +var eddsa$1 = EDDSA; + +/** +* @param {Array|String} message - message bytes +* @param {Array|String|KeyPair} secret - secret bytes or a keypair +* @returns {Signature} - signature +*/ +EDDSA.prototype.sign = function sign(message, secret) { + message = parseBytes$2(message); + var key = this.keyFromSecret(secret); + var r = this.hashInt(key.messagePrefix(), message); + var R = this.g.mul(r); + var Rencoded = this.encodePoint(R); + var s_ = this.hashInt(Rencoded, key.pubBytes(), message) + .mul(key.priv()); + var S = r.add(s_).umod(this.curve.n); + return this.makeSignature({ R: R, S: S, Rencoded: Rencoded }); +}; + +/** +* @param {Array} message - message bytes +* @param {Array|String|Signature} sig - sig bytes +* @param {Array|String|Point|KeyPair} pub - public key +* @returns {Boolean} - true if public key matches sig of message +*/ +EDDSA.prototype.verify = function verify(message, sig, pub) { + message = parseBytes$2(message); + sig = this.makeSignature(sig); + var key = this.keyFromPublic(pub); + var h = this.hashInt(sig.Rencoded(), key.pubBytes(), message); + var SG = this.g.mul(sig.S()); + var RplusAh = sig.R().add(key.pub().mul(h)); + return RplusAh.eq(SG); +}; + +EDDSA.prototype.hashInt = function hashInt() { + var hash = this.hash(); + for (var i = 0; i < arguments.length; i++) + hash.update(arguments[i]); + return utils_1$1.intFromLE(hash.digest()).umod(this.curve.n); +}; + +EDDSA.prototype.keyPair = function keyPair(options) { + return new key$1(this, options); +}; + +EDDSA.prototype.keyFromPublic = function keyFromPublic(pub) { + return key$1.fromPublic(this, pub); +}; + +EDDSA.prototype.keyFromSecret = function keyFromSecret(secret) { + return key$1.fromSecret(this, secret); +}; + +EDDSA.prototype.genKeyPair = function genKeyPair(options) { + if (!options) + options = {}; + + // Instantiate Hmac_DRBG + var drbg = new hmacDrbg({ + hash: this.hash, + pers: options.pers, + persEnc: options.persEnc || 'utf8', + entropy: options.entropy || brorand(this.hash.hmacStrength), + entropyEnc: options.entropy && options.entropyEnc || 'utf8', + nonce: this.curve.n.toArray() + }); + + return this.keyFromSecret(drbg.generate(32)); +}; + +EDDSA.prototype.makeSignature = function makeSignature(sig) { + if (sig instanceof signature$2) + return sig; + return new signature$2(this, sig); +}; + +/** +* * https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03#section-5.2 +* +* EDDSA defines methods for encoding and decoding points and integers. These are +* helper convenience methods, that pass along to utility functions implied +* parameters. +* +*/ +EDDSA.prototype.encodePoint = function encodePoint(point) { + var enc = point.getY().toArray('le', this.encodingLength); + enc[this.encodingLength - 1] |= point.getX().isOdd() ? 0x80 : 0; + return enc; +}; + +EDDSA.prototype.decodePoint = function decodePoint(bytes) { + bytes = utils_1$1.parseBytes(bytes); + + var lastIx = bytes.length - 1; + var normed = bytes.slice(0, lastIx).concat(bytes[lastIx] & ~0x80); + var xIsOdd = (bytes[lastIx] & 0x80) !== 0; + + var y = utils_1$1.intFromLE(normed); + return this.curve.pointFromY(y, xIsOdd); +}; + +EDDSA.prototype.encodeInt = function encodeInt(num) { + return num.toArray('le', this.encodingLength); +}; + +EDDSA.prototype.decodeInt = function decodeInt(bytes) { + return utils_1$1.intFromLE(bytes); +}; + +EDDSA.prototype.isPoint = function isPoint(val) { + return val instanceof this.pointClass; +}; + +var elliptic_1 = createCommonjsModule(function (module, exports) { + +var elliptic = exports; + +elliptic.utils = utils_1$1; +elliptic.rand = brorand; +elliptic.curve = curve_1; +elliptic.curves = curves_1; + +// Protocols +elliptic.ec = ec; +elliptic.eddsa = eddsa$1; +}); + +var elliptic$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + 'default': elliptic_1, + __moduleExports: elliptic_1 +}); + +exports.AEADEncryptedDataPacket = AEADEncryptedDataPacket; +exports.CleartextMessage = CleartextMessage; +exports.CompressedDataPacket = CompressedDataPacket; +exports.LiteralDataPacket = LiteralDataPacket; +exports.MarkerPacket = MarkerPacket; +exports.Message = Message; +exports.OnePassSignaturePacket = OnePassSignaturePacket; +exports.PacketList = PacketList; +exports.PrivateKey = PrivateKey; +exports.PublicKey = PublicKey; +exports.PublicKeyEncryptedSessionKeyPacket = PublicKeyEncryptedSessionKeyPacket; +exports.PublicKeyPacket = PublicKeyPacket; +exports.PublicSubkeyPacket = PublicSubkeyPacket; +exports.SecretKeyPacket = SecretKeyPacket; +exports.SecretSubkeyPacket = SecretSubkeyPacket; +exports.Signature = Signature; +exports.SignaturePacket = SignaturePacket; +exports.Subkey = Subkey; +exports.SymEncryptedIntegrityProtectedDataPacket = SymEncryptedIntegrityProtectedDataPacket; +exports.SymEncryptedSessionKeyPacket = SymEncryptedSessionKeyPacket; +exports.SymmetricallyEncryptedDataPacket = SymmetricallyEncryptedDataPacket; +exports.TrustPacket = TrustPacket; +exports.UserAttributePacket = UserAttributePacket; +exports.UserIDPacket = UserIDPacket; +exports.armor = armor; +exports.config = defaultConfig; +exports.createCleartextMessage = createCleartextMessage; +exports.createMessage = createMessage; +exports.decrypt = decrypt$4; +exports.decryptKey = decryptKey; +exports.decryptSessionKeys = decryptSessionKeys; +exports.encrypt = encrypt$4; +exports.encryptKey = encryptKey; +exports.encryptSessionKey = encryptSessionKey; +exports.enums = enums; +exports.generateKey = generateKey; +exports.generateSessionKey = generateSessionKey$1; +exports.readCleartextMessage = readCleartextMessage; +exports.readKey = readKey; +exports.readKeys = readKeys; +exports.readMessage = readMessage; +exports.readPrivateKey = readPrivateKey; +exports.readPrivateKeys = readPrivateKeys; +exports.readSignature = readSignature; +exports.reformatKey = reformatKey; +exports.revokeKey = revokeKey; +exports.sign = sign$5; +exports.unarmor = unarmor; +exports.verify = verify$5; + +// -----BEGIN ADDED BY FLOWCRYPT---- +exports.Hash = Hash; +exports.Sha1 = Sha1; +exports.Sha256 = Sha256; +exports.readToEnd = readToEnd; +exports.util = util; +// -----END ADDED BY FLOWCRYPT----- + diff --git a/Core/.save/openpgpv5/openpgp.js b/Core/.save/openpgpv5/openpgp.js new file mode 100644 index 000000000..965b44b2a --- /dev/null +++ b/Core/.save/openpgpv5/openpgp.js @@ -0,0 +1,43539 @@ +/*! OpenPGP.js v5.1.0 - 2022-01-24 - this is LGPL licensed code, see LICENSE/our website https://openpgpjs.org/ for more information. */ +var openpgp = (function (exports) { + 'use strict'; + + const globalThis = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + + const doneWritingPromise = Symbol('doneWritingPromise'); + const doneWritingResolve = Symbol('doneWritingResolve'); + const doneWritingReject = Symbol('doneWritingReject'); + + const readingIndex = Symbol('readingIndex'); + + class ArrayStream extends Array { + constructor() { + super(); + this[doneWritingPromise] = new Promise((resolve, reject) => { + this[doneWritingResolve] = resolve; + this[doneWritingReject] = reject; + }); + this[doneWritingPromise].catch(() => {}); + } + } + + ArrayStream.prototype.getReader = function() { + if (this[readingIndex] === undefined) { + this[readingIndex] = 0; + } + return { + read: async () => { + await this[doneWritingPromise]; + if (this[readingIndex] === this.length) { + return { value: undefined, done: true }; + } + return { value: this[this[readingIndex]++], done: false }; + } + }; + }; + + ArrayStream.prototype.readToEnd = async function(join) { + await this[doneWritingPromise]; + const result = join(this.slice(this[readingIndex])); + this.length = 0; + return result; + }; + + ArrayStream.prototype.clone = function() { + const clone = new ArrayStream(); + clone[doneWritingPromise] = this[doneWritingPromise].then(() => { + clone.push(...this); + }); + return clone; + }; + + /** + * Check whether data is an ArrayStream + * @param {Any} input data to check + * @returns {boolean} + */ + function isArrayStream(input) { + return input && input.getReader && Array.isArray(input); + } + + /** + * A wrapper class over the native WritableStreamDefaultWriter. + * It also lets you "write data to" array streams instead of streams. + * @class + */ + function Writer(input) { + if (!isArrayStream(input)) { + const writer = input.getWriter(); + const releaseLock = writer.releaseLock; + writer.releaseLock = () => { + writer.closed.catch(function() {}); + releaseLock.call(writer); + }; + return writer; + } + this.stream = input; + } + + /** + * Write a chunk of data. + * @returns {Promise} + * @async + */ + Writer.prototype.write = async function(chunk) { + this.stream.push(chunk); + }; + + /** + * Close the stream. + * @returns {Promise} + * @async + */ + Writer.prototype.close = async function() { + this.stream[doneWritingResolve](); + }; + + /** + * Error the stream. + * @returns {Promise} + * @async + */ + Writer.prototype.abort = async function(reason) { + this.stream[doneWritingReject](reason); + return reason; + }; + + /** + * Release the writer's lock. + * @returns {undefined} + * @async + */ + Writer.prototype.releaseLock = function() {}; + + const isNode = typeof globalThis.process === 'object' && + typeof globalThis.process.versions === 'object'; + + const NodeReadableStream = isNode && void('stream').Readable; + + /** + * Check whether data is a Stream, and if so of which type + * @param {Any} input data to check + * @returns {'web'|'ponyfill'|'node'|'array'|'web-like'|false} + */ + function isStream(input) { + if (isArrayStream(input)) { + return 'array'; + } + if (globalThis.ReadableStream && globalThis.ReadableStream.prototype.isPrototypeOf(input)) { + return 'web'; + } + if (ReadableStream && ReadableStream.prototype.isPrototypeOf(input)) { + return 'ponyfill'; + } + if (NodeReadableStream && NodeReadableStream.prototype.isPrototypeOf(input)) { + return 'node'; + } + if (input && input.getReader) { + return 'web-like'; + } + return false; + } + + /** + * Check whether data is a Uint8Array + * @param {Any} input data to check + * @returns {Boolean} + */ + function isUint8Array(input) { + return Uint8Array.prototype.isPrototypeOf(input); + } + + /** + * Concat Uint8Arrays + * @param {Array} Array of Uint8Arrays to concatenate + * @returns {Uint8array} Concatenated array + */ + function concatUint8Array(arrays) { + if (arrays.length === 1) return arrays[0]; + + let totalLength = 0; + for (let i = 0; i < arrays.length; i++) { + if (!isUint8Array(arrays[i])) { + throw new Error('concatUint8Array: Data must be in the form of a Uint8Array'); + } + + totalLength += arrays[i].length; + } + + const result = new Uint8Array(totalLength); + let pos = 0; + arrays.forEach(function (element) { + result.set(element, pos); + pos += element.length; + }); + + return result; + } + + const NodeBuffer = isNode && void('buffer').Buffer; + const NodeReadableStream$1 = isNode && void('stream').Readable; + + /** + * Web / node stream conversion functions + * From https://github.com/gwicke/node-web-streams + */ + + let nodeToWeb; + let webToNode; + + if (NodeReadableStream$1) { + + /** + * Convert a Node Readable Stream to a Web ReadableStream + * @param {Readable} nodeStream + * @returns {ReadableStream} + */ + nodeToWeb = function(nodeStream) { + let canceled = false; + return new ReadableStream({ + start(controller) { + nodeStream.pause(); + nodeStream.on('data', chunk => { + if (canceled) { + return; + } + if (NodeBuffer.isBuffer(chunk)) { + chunk = new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength); + } + controller.enqueue(chunk); + nodeStream.pause(); + }); + nodeStream.on('end', () => { + if (canceled) { + return; + } + controller.close(); + }); + nodeStream.on('error', e => controller.error(e)); + }, + pull() { + nodeStream.resume(); + }, + cancel(reason) { + canceled = true; + nodeStream.destroy(reason); + } + }); + }; + + + class NodeReadable extends NodeReadableStream$1 { + constructor(webStream, options) { + super(options); + this._reader = getReader(webStream); + } + + async _read(size) { + try { + while (true) { + const { done, value } = await this._reader.read(); + if (done) { + this.push(null); + break; + } + if (!this.push(value) || this._cancelling) { + this._reading = false; + break; + } + } + } catch(e) { + this.emit('error', e); + } + } + + _destroy(reason) { + this._reader.cancel(reason); + } + } + + /** + * Convert a Web ReadableStream to a Node Readable Stream + * @param {ReadableStream} webStream + * @param {Object} options + * @returns {Readable} + */ + webToNode = function(webStream, options) { + return new NodeReadable(webStream, options); + }; + + } + + const doneReadingSet = new WeakSet(); + const externalBuffer = Symbol('externalBuffer'); + + /** + * A wrapper class over the native ReadableStreamDefaultReader. + * This additionally implements pushing back data on the stream, which + * lets us implement peeking and a host of convenience functions. + * It also lets you read data other than streams, such as a Uint8Array. + * @class + */ + function Reader(input) { + this.stream = input; + if (input[externalBuffer]) { + this[externalBuffer] = input[externalBuffer].slice(); + } + if (isArrayStream(input)) { + const reader = input.getReader(); + this._read = reader.read.bind(reader); + this._releaseLock = () => {}; + this._cancel = () => {}; + return; + } + let streamType = isStream(input); + if (streamType === 'node') { + input = nodeToWeb(input); + } + if (streamType) { + const reader = input.getReader(); + this._read = reader.read.bind(reader); + this._releaseLock = () => { + reader.closed.catch(function() {}); + reader.releaseLock(); + }; + this._cancel = reader.cancel.bind(reader); + return; + } + let doneReading = false; + this._read = async () => { + if (doneReading || doneReadingSet.has(input)) { + return { value: undefined, done: true }; + } + doneReading = true; + return { value: input, done: false }; + }; + this._releaseLock = () => { + if (doneReading) { + try { + doneReadingSet.add(input); + } catch(e) {} + } + }; + } + + /** + * Read a chunk of data. + * @returns {Promise} Either { done: false, value: Uint8Array | String } or { done: true, value: undefined } + * @async + */ + Reader.prototype.read = async function() { + if (this[externalBuffer] && this[externalBuffer].length) { + const value = this[externalBuffer].shift(); + return { done: false, value }; + } + return this._read(); + }; + + /** + * Allow others to read the stream. + */ + Reader.prototype.releaseLock = function() { + if (this[externalBuffer]) { + this.stream[externalBuffer] = this[externalBuffer]; + } + this._releaseLock(); + }; + + /** + * Cancel the stream. + */ + Reader.prototype.cancel = function(reason) { + return this._cancel(reason); + }; + + /** + * Read up to and including the first \n character. + * @returns {Promise} + * @async + */ + Reader.prototype.readLine = async function() { + let buffer = []; + let returnVal; + while (!returnVal) { + let { done, value } = await this.read(); + value += ''; + if (done) { + if (buffer.length) return concat(buffer); + return; + } + const lineEndIndex = value.indexOf('\n') + 1; + if (lineEndIndex) { + returnVal = concat(buffer.concat(value.substr(0, lineEndIndex))); + buffer = []; + } + if (lineEndIndex !== value.length) { + buffer.push(value.substr(lineEndIndex)); + } + } + this.unshift(...buffer); + return returnVal; + }; + + /** + * Read a single byte/character. + * @returns {Promise} + * @async + */ + Reader.prototype.readByte = async function() { + const { done, value } = await this.read(); + if (done) return; + const byte = value[0]; + this.unshift(slice(value, 1)); + return byte; + }; + + /** + * Read a specific amount of bytes/characters, unless the stream ends before that amount. + * @returns {Promise} + * @async + */ + Reader.prototype.readBytes = async function(length) { + const buffer = []; + let bufferLength = 0; + while (true) { + const { done, value } = await this.read(); + if (done) { + if (buffer.length) return concat(buffer); + return; + } + buffer.push(value); + bufferLength += value.length; + if (bufferLength >= length) { + const bufferConcat = concat(buffer); + this.unshift(slice(bufferConcat, length)); + return slice(bufferConcat, 0, length); + } + } + }; + + /** + * Peek (look ahead) a specific amount of bytes/characters, unless the stream ends before that amount. + * @returns {Promise} + * @async + */ + Reader.prototype.peekBytes = async function(length) { + const bytes = await this.readBytes(length); + this.unshift(bytes); + return bytes; + }; + + /** + * Push data to the front of the stream. + * Data must have been read in the last call to read*. + * @param {...(Uint8Array|String|Undefined)} values + */ + Reader.prototype.unshift = function(...values) { + if (!this[externalBuffer]) { + this[externalBuffer] = []; + } + if ( + values.length === 1 && isUint8Array(values[0]) && + this[externalBuffer].length && values[0].length && + this[externalBuffer][0].byteOffset >= values[0].length + ) { + this[externalBuffer][0] = new Uint8Array( + this[externalBuffer][0].buffer, + this[externalBuffer][0].byteOffset - values[0].length, + this[externalBuffer][0].byteLength + values[0].length + ); + return; + } + this[externalBuffer].unshift(...values.filter(value => value && value.length)); + }; + + /** + * Read the stream to the end and return its contents, concatenated by the join function (defaults to streams.concat). + * @param {Function} join + * @returns {Promise} the return value of join() + * @async + */ + Reader.prototype.readToEnd = async function(join=concat) { + const result = []; + while (true) { + const { done, value } = await this.read(); + if (done) break; + result.push(value); + } + return join(result); + }; + + let { ReadableStream, WritableStream, TransformStream } = globalThis; + + let toPonyfillReadable, toNativeReadable; + + async function loadStreamsPonyfill() { + if (TransformStream) { + return; + } + + const [ponyfill, adapter] = await Promise.all([ + Promise.resolve().then(function () { return ponyfill_es6; }), + Promise.resolve().then(function () { return webStreamsAdapter; }) + ]); + + ({ ReadableStream, WritableStream, TransformStream } = ponyfill); + + const { createReadableStreamWrapper } = adapter; + + if (globalThis.ReadableStream && ReadableStream !== globalThis.ReadableStream) { + toPonyfillReadable = createReadableStreamWrapper(ReadableStream); + toNativeReadable = createReadableStreamWrapper(globalThis.ReadableStream); + } + } + + const NodeBuffer$1 = isNode && void('buffer').Buffer; + + /** + * Convert data to Stream + * @param {ReadableStream|Uint8array|String} input data to convert + * @returns {ReadableStream} Converted data + */ + function toStream(input) { + let streamType = isStream(input); + if (streamType === 'node') { + return nodeToWeb(input); + } + if (streamType === 'web' && toPonyfillReadable) { + return toPonyfillReadable(input); + } + if (streamType) { + return input; + } + return new ReadableStream({ + start(controller) { + controller.enqueue(input); + controller.close(); + } + }); + } + + /** + * Convert data to ArrayStream + * @param {Object} input data to convert + * @returns {ArrayStream} Converted data + */ + function toArrayStream(input) { + if (isStream(input)) { + return input; + } + const stream = new ArrayStream(); + (async () => { + const writer = getWriter(stream); + await writer.write(input); + await writer.close(); + })(); + return stream; + } + + /** + * Concat a list of Uint8Arrays, Strings or Streams + * The caller should not mix Uint8Arrays with Strings, but may mix Streams with non-Streams. + * @param {Array} Array of Uint8Arrays/Strings/Streams to concatenate + * @returns {Uint8array|String|ReadableStream} Concatenated array + */ + function concat(list) { + if (list.some(stream => isStream(stream) && !isArrayStream(stream))) { + return concatStream(list); + } + if (list.some(stream => isArrayStream(stream))) { + return concatArrayStream(list); + } + if (typeof list[0] === 'string') { + return list.join(''); + } + if (NodeBuffer$1 && NodeBuffer$1.isBuffer(list[0])) { + return NodeBuffer$1.concat(list); + } + return concatUint8Array(list); + } + + /** + * Concat a list of Streams + * @param {Array} list Array of Uint8Arrays/Strings/Streams to concatenate + * @returns {ReadableStream} Concatenated list + */ + function concatStream(list) { + list = list.map(toStream); + const transform = transformWithCancel(async function(reason) { + await Promise.all(transforms.map(stream => cancel(stream, reason))); + }); + let prev = Promise.resolve(); + const transforms = list.map((stream, i) => transformPair(stream, (readable, writable) => { + prev = prev.then(() => pipe(readable, transform.writable, { + preventClose: i !== list.length - 1 + })); + return prev; + })); + return transform.readable; + } + + /** + * Concat a list of ArrayStreams + * @param {Array} list Array of Uint8Arrays/Strings/ArrayStreams to concatenate + * @returns {ArrayStream} Concatenated streams + */ + function concatArrayStream(list) { + const result = new ArrayStream(); + let prev = Promise.resolve(); + list.forEach((stream, i) => { + prev = prev.then(() => pipe(stream, result, { + preventClose: i !== list.length - 1 + })); + return prev; + }); + return result; + } + + /** + * Get a Reader + * @param {ReadableStream|Uint8array|String} input + * @returns {Reader} + */ + function getReader(input) { + return new Reader(input); + } + + /** + * Get a Writer + * @param {WritableStream} input + * @returns {Writer} + */ + function getWriter(input) { + return new Writer(input); + } + + /** + * Pipe a readable stream to a writable stream. Don't throw on input stream errors, but forward them to the output stream. + * @param {ReadableStream|Uint8array|String} input + * @param {WritableStream} target + * @param {Object} (optional) options + * @returns {Promise} Promise indicating when piping has finished (input stream closed or errored) + * @async + */ + async function pipe(input, target, { + preventClose = false, + preventAbort = false, + preventCancel = false + } = {}) { + if (isStream(input) && !isArrayStream(input)) { + input = toStream(input); + try { + if (input[externalBuffer]) { + const writer = getWriter(target); + for (let i = 0; i < input[externalBuffer].length; i++) { + await writer.ready; + await writer.write(input[externalBuffer][i]); + } + writer.releaseLock(); + } + await input.pipeTo(target, { + preventClose, + preventAbort, + preventCancel + }); + } catch(e) {} + return; + } + input = toArrayStream(input); + const reader = getReader(input); + const writer = getWriter(target); + try { + while (true) { + await writer.ready; + const { done, value } = await reader.read(); + if (done) { + if (!preventClose) await writer.close(); + break; + } + await writer.write(value); + } + } catch (e) { + if (!preventAbort) await writer.abort(e); + } finally { + reader.releaseLock(); + writer.releaseLock(); + } + } + + /** + * Pipe a readable stream through a transform stream. + * @param {ReadableStream|Uint8array|String} input + * @param {Object} (optional) options + * @returns {ReadableStream} transformed stream + */ + function transformRaw(input, options) { + const transformStream = new TransformStream(options); + pipe(input, transformStream.writable); + return transformStream.readable; + } + + /** + * Create a cancelable TransformStream. + * @param {Function} cancel + * @returns {TransformStream} + */ + function transformWithCancel(cancel) { + let pulled = false; + let backpressureChangePromiseResolve; + let outputController; + return { + readable: new ReadableStream({ + start(controller) { + outputController = controller; + }, + pull() { + if (backpressureChangePromiseResolve) { + backpressureChangePromiseResolve(); + } else { + pulled = true; + } + }, + cancel + }, {highWaterMark: 0}), + writable: new WritableStream({ + write: async function(chunk) { + outputController.enqueue(chunk); + if (!pulled) { + await new Promise(resolve => { + backpressureChangePromiseResolve = resolve; + }); + backpressureChangePromiseResolve = null; + } else { + pulled = false; + } + }, + close: outputController.close.bind(outputController), + abort: outputController.error.bind(outputController) + }) + }; + } + + /** + * Transform a stream using helper functions which are called on each chunk, and on stream close, respectively. + * @param {ReadableStream|Uint8array|String} input + * @param {Function} process + * @param {Function} finish + * @returns {ReadableStream|Uint8array|String} + */ + function transform(input, process = () => undefined, finish = () => undefined) { + if (isArrayStream(input)) { + const output = new ArrayStream(); + (async () => { + const data = await readToEnd(input); + const result1 = process(data); + const result2 = finish(); + let result; + if (result1 !== undefined && result2 !== undefined) result = concat([result1, result2]); + else result = result1 !== undefined ? result1 : result2; + const writer = getWriter(output); + await writer.write(result); + await writer.close(); + })(); + return output; + } + if (isStream(input)) { + return transformRaw(input, { + async transform(value, controller) { + try { + const result = await process(value); + if (result !== undefined) controller.enqueue(result); + } catch(e) { + controller.error(e); + } + }, + async flush(controller) { + try { + const result = await finish(); + if (result !== undefined) controller.enqueue(result); + } catch(e) { + controller.error(e); + } + } + }); + } + const result1 = process(input); + const result2 = finish(); + if (result1 !== undefined && result2 !== undefined) return concat([result1, result2]); + return result1 !== undefined ? result1 : result2; + } + + /** + * Transform a stream using a helper function which is passed a readable and a writable stream. + * This function also maintains the possibility to cancel the input stream, + * and does so on cancelation of the output stream, despite cancelation + * normally being impossible when the input stream is being read from. + * @param {ReadableStream|Uint8array|String} input + * @param {Function} fn + * @returns {ReadableStream} + */ + function transformPair(input, fn) { + if (isStream(input) && !isArrayStream(input)) { + let incomingTransformController; + const incoming = new TransformStream({ + start(controller) { + incomingTransformController = controller; + } + }); + + const pipeDonePromise = pipe(input, incoming.writable); + + const outgoing = transformWithCancel(async function() { + incomingTransformController.error(new Error('Readable side was canceled.')); + await pipeDonePromise; + await new Promise(setTimeout); + }); + fn(incoming.readable, outgoing.writable); + return outgoing.readable; + } + input = toArrayStream(input); + const output = new ArrayStream(); + fn(input, output); + return output; + } + + /** + * Parse a stream using a helper function which is passed a Reader. + * The reader additionally has a remainder() method which returns a + * stream pointing to the remainder of input, and is linked to input + * for cancelation. + * @param {ReadableStream|Uint8array|String} input + * @param {Function} fn + * @returns {Any} the return value of fn() + */ + function parse(input, fn) { + let returnValue; + const transformed = transformPair(input, (readable, writable) => { + const reader = getReader(readable); + reader.remainder = () => { + reader.releaseLock(); + pipe(readable, writable); + return transformed; + }; + returnValue = fn(reader); + }); + return returnValue; + } + + /** + * Tee a Stream for reading it twice. The input stream can no longer be read after tee()ing. + * Reading either of the two returned streams will pull from the input stream. + * The input stream will only be canceled if both of the returned streams are canceled. + * @param {ReadableStream|Uint8array|String} input + * @returns {Array} array containing two copies of input + */ + function tee(input) { + if (isArrayStream(input)) { + throw new Error('ArrayStream cannot be tee()d, use clone() instead'); + } + if (isStream(input)) { + const teed = toStream(input).tee(); + teed[0][externalBuffer] = teed[1][externalBuffer] = input[externalBuffer]; + return teed; + } + return [slice(input), slice(input)]; + } + + /** + * Clone a Stream for reading it twice. The input stream can still be read after clone()ing. + * Reading from the clone will pull from the input stream. + * The input stream will only be canceled if both the clone and the input stream are canceled. + * @param {ReadableStream|Uint8array|String} input + * @returns {ReadableStream|Uint8array|String} cloned input + */ + function clone(input) { + if (isArrayStream(input)) { + return input.clone(); + } + if (isStream(input)) { + const teed = tee(input); + overwrite(input, teed[0]); + return teed[1]; + } + return slice(input); + } + + /** + * Clone a Stream for reading it twice. Data will arrive at the same rate as the input stream is being read. + * Reading from the clone will NOT pull from the input stream. Data only arrives when reading the input stream. + * The input stream will NOT be canceled if the clone is canceled, only if the input stream are canceled. + * If the input stream is canceled, the clone will be errored. + * @param {ReadableStream|Uint8array|String} input + * @returns {ReadableStream|Uint8array|String} cloned input + */ + function passiveClone(input) { + if (isArrayStream(input)) { + return clone(input); + } + if (isStream(input)) { + return new ReadableStream({ + start(controller) { + const transformed = transformPair(input, async (readable, writable) => { + const reader = getReader(readable); + const writer = getWriter(writable); + try { + while (true) { + await writer.ready; + const { done, value } = await reader.read(); + if (done) { + try { controller.close(); } catch(e) {} + await writer.close(); + return; + } + try { controller.enqueue(value); } catch(e) {} + await writer.write(value); + } + } catch(e) { + controller.error(e); + await writer.abort(e); + } + }); + overwrite(input, transformed); + } + }); + } + return slice(input); + } + + /** + * Modify a stream object to point to a different stream object. + * This is used internally by clone() and passiveClone() to provide an abstraction over tee(). + * @param {ReadableStream} input + * @param {ReadableStream} clone + */ + function overwrite(input, clone) { + // Overwrite input.getReader, input.locked, etc to point to clone + Object.entries(Object.getOwnPropertyDescriptors(input.constructor.prototype)).forEach(([name, descriptor]) => { + if (name === 'constructor') { + return; + } + if (descriptor.value) { + descriptor.value = descriptor.value.bind(clone); + } else { + descriptor.get = descriptor.get.bind(clone); + } + Object.defineProperty(input, name, descriptor); + }); + } + + /** + * Return a stream pointing to a part of the input stream. + * @param {ReadableStream|Uint8array|String} input + * @returns {ReadableStream|Uint8array|String} clone + */ + function slice(input, begin=0, end=Infinity) { + if (isArrayStream(input)) { + throw new Error('Not implemented'); + } + if (isStream(input)) { + if (begin >= 0 && end >= 0) { + let bytesRead = 0; + return transformRaw(input, { + transform(value, controller) { + if (bytesRead < end) { + if (bytesRead + value.length >= begin) { + controller.enqueue(slice(value, Math.max(begin - bytesRead, 0), end - bytesRead)); + } + bytesRead += value.length; + } else { + controller.terminate(); + } + } + }); + } + if (begin < 0 && (end < 0 || end === Infinity)) { + let lastBytes = []; + return transform(input, value => { + if (value.length >= -begin) lastBytes = [value]; + else lastBytes.push(value); + }, () => slice(concat(lastBytes), begin, end)); + } + if (begin === 0 && end < 0) { + let lastBytes; + return transform(input, value => { + const returnValue = lastBytes ? concat([lastBytes, value]) : value; + if (returnValue.length >= -end) { + lastBytes = slice(returnValue, end); + return slice(returnValue, begin, end); + } else { + lastBytes = returnValue; + } + }); + } + console.warn(`stream.slice(input, ${begin}, ${end}) not implemented efficiently.`); + return fromAsync(async () => slice(await readToEnd(input), begin, end)); + } + if (input[externalBuffer]) { + input = concat(input[externalBuffer].concat([input])); + } + if (isUint8Array(input) && !(NodeBuffer$1 && NodeBuffer$1.isBuffer(input))) { + if (end === Infinity) end = input.length; + return input.subarray(begin, end); + } + return input.slice(begin, end); + } + + /** + * Read a stream to the end and return its contents, concatenated by the join function (defaults to concat). + * @param {ReadableStream|Uint8array|String} input + * @param {Function} join + * @returns {Promise} the return value of join() + * @async + */ + async function readToEnd(input, join=concat) { + if (isArrayStream(input)) { + return input.readToEnd(join); + } + if (isStream(input)) { + return getReader(input).readToEnd(join); + } + return input; + } + + /** + * Cancel a stream. + * @param {ReadableStream|Uint8array|String} input + * @param {Any} reason + * @returns {Promise} indicates when the stream has been canceled + * @async + */ + async function cancel(input, reason) { + if (isStream(input)) { + if (input.cancel) { + return input.cancel(reason); + } + if (input.destroy) { + input.destroy(reason); + await new Promise(setTimeout); + return reason; + } + } + } + + /** + * Convert an async function to an ArrayStream. When the function returns, its return value is written to the stream. + * @param {Function} fn + * @returns {ArrayStream} + */ + function fromAsync(fn) { + const arrayStream = new ArrayStream(); + (async () => { + const writer = getWriter(arrayStream); + try { + await writer.write(await fn()); + await writer.close(); + } catch (e) { + await writer.abort(e); + } + })(); + return arrayStream; + } + + /* eslint-disable new-cap */ + + /** + * @fileoverview + * BigInteger implementation of basic operations + * that wraps the native BigInt library. + * Operations are not constant time, + * but we try and limit timing leakage where we can + * @module biginteger/native + * @private + */ + + /** + * @private + */ + class BigInteger { + /** + * Get a BigInteger (input must be big endian for strings and arrays) + * @param {Number|String|Uint8Array} n - Value to convert + * @throws {Error} on null or undefined input + */ + constructor(n) { + if (n === undefined) { + throw new Error('Invalid BigInteger input'); + } + + if (n instanceof Uint8Array) { + const bytes = n; + const hex = new Array(bytes.length); + for (let i = 0; i < bytes.length; i++) { + const hexByte = bytes[i].toString(16); + hex[i] = (bytes[i] <= 0xF) ? ('0' + hexByte) : hexByte; + } + this.value = BigInt('0x0' + hex.join('')); + } else { + this.value = BigInt(n); + } + } + + clone() { + return new BigInteger(this.value); + } + + /** + * BigInteger increment in place + */ + iinc() { + this.value++; + return this; + } + + /** + * BigInteger increment + * @returns {BigInteger} this + 1. + */ + inc() { + return this.clone().iinc(); + } + + /** + * BigInteger decrement in place + */ + idec() { + this.value--; + return this; + } + + /** + * BigInteger decrement + * @returns {BigInteger} this - 1. + */ + dec() { + return this.clone().idec(); + } + + /** + * BigInteger addition in place + * @param {BigInteger} x - Value to add + */ + iadd(x) { + this.value += x.value; + return this; + } + + /** + * BigInteger addition + * @param {BigInteger} x - Value to add + * @returns {BigInteger} this + x. + */ + add(x) { + return this.clone().iadd(x); + } + + /** + * BigInteger subtraction in place + * @param {BigInteger} x - Value to subtract + */ + isub(x) { + this.value -= x.value; + return this; + } + + /** + * BigInteger subtraction + * @param {BigInteger} x - Value to subtract + * @returns {BigInteger} this - x. + */ + sub(x) { + return this.clone().isub(x); + } + + /** + * BigInteger multiplication in place + * @param {BigInteger} x - Value to multiply + */ + imul(x) { + this.value *= x.value; + return this; + } + + /** + * BigInteger multiplication + * @param {BigInteger} x - Value to multiply + * @returns {BigInteger} this * x. + */ + mul(x) { + return this.clone().imul(x); + } + + /** + * Compute value modulo m, in place + * @param {BigInteger} m - Modulo + */ + imod(m) { + this.value %= m.value; + if (this.isNegative()) { + this.iadd(m); + } + return this; + } + + /** + * Compute value modulo m + * @param {BigInteger} m - Modulo + * @returns {BigInteger} this mod m. + */ + mod(m) { + return this.clone().imod(m); + } + + /** + * Compute modular exponentiation using square and multiply + * @param {BigInteger} e - Exponent + * @param {BigInteger} n - Modulo + * @returns {BigInteger} this ** e mod n. + */ + modExp(e, n) { + if (n.isZero()) throw Error('Modulo cannot be zero'); + if (n.isOne()) return new BigInteger(0); + if (e.isNegative()) throw Error('Unsopported negative exponent'); + + let exp = e.value; + let x = this.value; + + x %= n.value; + let r = BigInt(1); + while (exp > BigInt(0)) { + const lsb = exp & BigInt(1); + exp >>= BigInt(1); // e / 2 + // Always compute multiplication step, to reduce timing leakage + const rx = (r * x) % n.value; + // Update r only if lsb is 1 (odd exponent) + r = lsb ? rx : r; + x = (x * x) % n.value; // Square + } + return new BigInteger(r); + } + + + /** + * Compute the inverse of this value modulo n + * Note: this and and n must be relatively prime + * @param {BigInteger} n - Modulo + * @returns {BigInteger} x such that this*x = 1 mod n + * @throws {Error} if the inverse does not exist + */ + modInv(n) { + const { gcd, x } = this._egcd(n); + if (!gcd.isOne()) { + throw new Error('Inverse does not exist'); + } + return x.add(n).mod(n); + } + + /** + * Extended Eucleadian algorithm (http://anh.cs.luc.edu/331/notes/xgcd.pdf) + * Given a = this and b, compute (x, y) such that ax + by = gdc(a, b) + * @param {BigInteger} b - Second operand + * @returns {{ gcd, x, y: BigInteger }} + */ + _egcd(b) { + let x = BigInt(0); + let y = BigInt(1); + let xPrev = BigInt(1); + let yPrev = BigInt(0); + + let a = this.value; + b = b.value; + + while (b !== BigInt(0)) { + const q = a / b; + let tmp = x; + x = xPrev - q * x; + xPrev = tmp; + + tmp = y; + y = yPrev - q * y; + yPrev = tmp; + + tmp = b; + b = a % b; + a = tmp; + } + + return { + x: new BigInteger(xPrev), + y: new BigInteger(yPrev), + gcd: new BigInteger(a) + }; + } + + /** + * Compute greatest common divisor between this and n + * @param {BigInteger} b - Operand + * @returns {BigInteger} gcd + */ + gcd(b) { + let a = this.value; + b = b.value; + while (b !== BigInt(0)) { + const tmp = b; + b = a % b; + a = tmp; + } + return new BigInteger(a); + } + + /** + * Shift this to the left by x, in place + * @param {BigInteger} x - Shift value + */ + ileftShift(x) { + this.value <<= x.value; + return this; + } + + /** + * Shift this to the left by x + * @param {BigInteger} x - Shift value + * @returns {BigInteger} this << x. + */ + leftShift(x) { + return this.clone().ileftShift(x); + } + + /** + * Shift this to the right by x, in place + * @param {BigInteger} x - Shift value + */ + irightShift(x) { + this.value >>= x.value; + return this; + } + + /** + * Shift this to the right by x + * @param {BigInteger} x - Shift value + * @returns {BigInteger} this >> x. + */ + rightShift(x) { + return this.clone().irightShift(x); + } + + /** + * Whether this value is equal to x + * @param {BigInteger} x + * @returns {Boolean} + */ + equal(x) { + return this.value === x.value; + } + + /** + * Whether this value is less than x + * @param {BigInteger} x + * @returns {Boolean} + */ + lt(x) { + return this.value < x.value; + } + + /** + * Whether this value is less than or equal to x + * @param {BigInteger} x + * @returns {Boolean} + */ + lte(x) { + return this.value <= x.value; + } + + /** + * Whether this value is greater than x + * @param {BigInteger} x + * @returns {Boolean} + */ + gt(x) { + return this.value > x.value; + } + + /** + * Whether this value is greater than or equal to x + * @param {BigInteger} x + * @returns {Boolean} + */ + gte(x) { + return this.value >= x.value; + } + + isZero() { + return this.value === BigInt(0); + } + + isOne() { + return this.value === BigInt(1); + } + + isNegative() { + return this.value < BigInt(0); + } + + isEven() { + return !(this.value & BigInt(1)); + } + + abs() { + const res = this.clone(); + if (this.isNegative()) { + res.value = -res.value; + } + return res; + } + + /** + * Get this value as a string + * @returns {String} this value. + */ + toString() { + return this.value.toString(); + } + + /** + * Get this value as an exact Number (max 53 bits) + * Fails if this value is too large + * @returns {Number} + */ + toNumber() { + const number = Number(this.value); + if (number > Number.MAX_SAFE_INTEGER) { + // We throw and error to conform with the bn.js implementation + throw new Error('Number can only safely store up to 53 bits'); + } + return number; + } + + /** + * Get value of i-th bit + * @param {Number} i - Bit index + * @returns {Number} Bit value. + */ + getBit(i) { + const bit = (this.value >> BigInt(i)) & BigInt(1); + return (bit === BigInt(0)) ? 0 : 1; + } + + /** + * Compute bit length + * @returns {Number} Bit length. + */ + bitLength() { + const zero = new BigInteger(0); + const one = new BigInteger(1); + const negOne = new BigInteger(-1); + + // -1n >> -1n is -1n + // 1n >> 1n is 0n + const target = this.isNegative() ? negOne : zero; + let bitlen = 1; + const tmp = this.clone(); + while (!tmp.irightShift(one).equal(target)) { + bitlen++; + } + return bitlen; + } + + /** + * Compute byte length + * @returns {Number} Byte length. + */ + byteLength() { + const zero = new BigInteger(0); + const negOne = new BigInteger(-1); + + const target = this.isNegative() ? negOne : zero; + const eight = new BigInteger(8); + let len = 1; + const tmp = this.clone(); + while (!tmp.irightShift(eight).equal(target)) { + len++; + } + return len; + } + + /** + * Get Uint8Array representation of this number + * @param {String} endian - Endianess of output array (defaults to 'be') + * @param {Number} length - Of output array + * @returns {Uint8Array} + */ + toUint8Array(endian = 'be', length) { + // we get and parse the hex string (https://coolaj86.com/articles/convert-js-bigints-to-typedarrays/) + // this is faster than shift+mod iterations + let hex = this.value.toString(16); + if (hex.length % 2 === 1) { + hex = '0' + hex; + } + + const rawLength = hex.length / 2; + const bytes = new Uint8Array(length || rawLength); + // parse hex + const offset = length ? (length - rawLength) : 0; + let i = 0; + while (i < rawLength) { + bytes[i + offset] = parseInt(hex.slice(2 * i, 2 * i + 2), 16); + i++; + } + + if (endian !== 'be') { + bytes.reverse(); + } + + return bytes; + } + } + + async function getBigInteger() { + if (util.detectBigInt()) { + return BigInteger; + } else { + const { default: BigInteger } = await Promise.resolve().then(function () { return bn_interface; }); + return BigInteger; + } + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + const debugMode = (() => { + try { + return process.env.NODE_ENV === 'development'; // eslint-disable-line no-process-env + } catch (e) {} + return false; + })(); + + const util = { + isString: function(data) { + return typeof data === 'string' || String.prototype.isPrototypeOf(data); + }, + + isArray: function(data) { + return Array.prototype.isPrototypeOf(data); + }, + + isUint8Array: isUint8Array, + + isStream: isStream, + + readNumber: function (bytes) { + let n = 0; + for (let i = 0; i < bytes.length; i++) { + n += (256 ** i) * bytes[bytes.length - 1 - i]; + } + return n; + }, + + writeNumber: function (n, bytes) { + const b = new Uint8Array(bytes); + for (let i = 0; i < bytes; i++) { + b[i] = (n >> (8 * (bytes - i - 1))) & 0xFF; + } + + return b; + }, + + readDate: function (bytes) { + const n = util.readNumber(bytes); + const d = new Date(n * 1000); + return d; + }, + + writeDate: function (time) { + const numeric = Math.floor(time.getTime() / 1000); + + return util.writeNumber(numeric, 4); + }, + + normalizeDate: function (time = Date.now()) { + return time === null || time === Infinity ? time : new Date(Math.floor(+time / 1000) * 1000); + }, + + /** + * Read one MPI from bytes in input + * @param {Uint8Array} bytes - Input data to parse + * @returns {Uint8Array} Parsed MPI. + */ + readMPI: function (bytes) { + const bits = (bytes[0] << 8) | bytes[1]; + const bytelen = (bits + 7) >>> 3; + return bytes.subarray(2, 2 + bytelen); + }, + + /** + * Left-pad Uint8Array to length by adding 0x0 bytes + * @param {Uint8Array} bytes - Data to pad + * @param {Number} length - Padded length + * @returns {Uint8Array} Padded bytes. + */ + leftPad(bytes, length) { + const padded = new Uint8Array(length); + const offset = length - bytes.length; + padded.set(bytes, offset); + return padded; + }, + + /** + * Convert a Uint8Array to an MPI-formatted Uint8Array. + * @param {Uint8Array} bin - An array of 8-bit integers to convert + * @returns {Uint8Array} MPI-formatted Uint8Array. + */ + uint8ArrayToMPI: function (bin) { + const bitSize = util.uint8ArrayBitLength(bin); + if (bitSize === 0) { + throw new Error('Zero MPI'); + } + const stripped = bin.subarray(bin.length - Math.ceil(bitSize / 8)); + const prefix = new Uint8Array([(bitSize & 0xFF00) >> 8, bitSize & 0xFF]); + return util.concatUint8Array([prefix, stripped]); + }, + + /** + * Return bit length of the input data + * @param {Uint8Array} bin input data (big endian) + * @returns bit length + */ + uint8ArrayBitLength: function (bin) { + let i; // index of leading non-zero byte + for (i = 0; i < bin.length; i++) if (bin[i] !== 0) break; + if (i === bin.length) { + return 0; + } + const stripped = bin.subarray(i); + return (stripped.length - 1) * 8 + util.nbits(stripped[0]); + }, + + /** + * Convert a hex string to an array of 8-bit integers + * @param {String} hex - A hex string to convert + * @returns {Uint8Array} An array of 8-bit integers. + */ + hexToUint8Array: function (hex) { + const result = new Uint8Array(hex.length >> 1); + for (let k = 0; k < hex.length >> 1; k++) { + result[k] = parseInt(hex.substr(k << 1, 2), 16); + } + return result; + }, + + /** + * Convert an array of 8-bit integers to a hex string + * @param {Uint8Array} bytes - Array of 8-bit integers to convert + * @returns {String} Hexadecimal representation of the array. + */ + uint8ArrayToHex: function (bytes) { + const r = []; + const e = bytes.length; + let c = 0; + let h; + while (c < e) { + h = bytes[c++].toString(16); + while (h.length < 2) { + h = '0' + h; + } + r.push('' + h); + } + return r.join(''); + }, + + /** + * Convert a string to an array of 8-bit integers + * @param {String} str - String to convert + * @returns {Uint8Array} An array of 8-bit integers. + */ + stringToUint8Array: function (str) { + return transform(str, str => { + if (!util.isString(str)) { + throw new Error('stringToUint8Array: Data must be in the form of a string'); + } + + const result = new Uint8Array(str.length); + for (let i = 0; i < str.length; i++) { + result[i] = str.charCodeAt(i); + } + return result; + }); + }, + + /** + * Convert an array of 8-bit integers to a string + * @param {Uint8Array} bytes - An array of 8-bit integers to convert + * @returns {String} String representation of the array. + */ + uint8ArrayToString: function (bytes) { + bytes = new Uint8Array(bytes); + const result = []; + const bs = 1 << 14; + const j = bytes.length; + + for (let i = 0; i < j; i += bs) { + result.push(String.fromCharCode.apply(String, bytes.subarray(i, i + bs < j ? i + bs : j))); + } + return result.join(''); + }, + + /** + * Convert a native javascript string to a Uint8Array of utf8 bytes + * @param {String|ReadableStream} str - The string to convert + * @returns {Uint8Array|ReadableStream} A valid squence of utf8 bytes. + */ + encodeUTF8: function (str) { + const encoder = new TextEncoder('utf-8'); + // eslint-disable-next-line no-inner-declarations + function process(value, lastChunk = false) { + return encoder.encode(value, { stream: !lastChunk }); + } + return transform(str, process, () => process('', true)); + }, + + /** + * Convert a Uint8Array of utf8 bytes to a native javascript string + * @param {Uint8Array|ReadableStream} utf8 - A valid squence of utf8 bytes + * @returns {String|ReadableStream} A native javascript string. + */ + decodeUTF8: function (utf8) { + const decoder = new TextDecoder('utf-8'); + // eslint-disable-next-line no-inner-declarations + function process(value, lastChunk = false) { + return decoder.decode(value, { stream: !lastChunk }); + } + return transform(utf8, process, () => process(new Uint8Array(), true)); + }, + + /** + * Concat a list of Uint8Arrays, Strings or Streams + * The caller must not mix Uint8Arrays with Strings, but may mix Streams with non-Streams. + * @param {Array} Array - Of Uint8Arrays/Strings/Streams to concatenate + * @returns {Uint8Array|String|ReadableStream} Concatenated array. + */ + concat: concat, + + /** + * Concat Uint8Arrays + * @param {Array} Array - Of Uint8Arrays to concatenate + * @returns {Uint8Array} Concatenated array. + */ + concatUint8Array: concatUint8Array, + + /** + * Check Uint8Array equality + * @param {Uint8Array} array1 - First array + * @param {Uint8Array} array2 - Second array + * @returns {Boolean} Equality. + */ + equalsUint8Array: function (array1, array2) { + if (!util.isUint8Array(array1) || !util.isUint8Array(array2)) { + throw new Error('Data must be in the form of a Uint8Array'); + } + + if (array1.length !== array2.length) { + return false; + } + + for (let i = 0; i < array1.length; i++) { + if (array1[i] !== array2[i]) { + return false; + } + } + return true; + }, + + /** + * Calculates a 16bit sum of a Uint8Array by adding each character + * codes modulus 65535 + * @param {Uint8Array} Uint8Array - To create a sum of + * @returns {Uint8Array} 2 bytes containing the sum of all charcodes % 65535. + */ + writeChecksum: function (text) { + let s = 0; + for (let i = 0; i < text.length; i++) { + s = (s + text[i]) & 0xFFFF; + } + return util.writeNumber(s, 2); + }, + + /** + * Helper function to print a debug message. Debug + * messages are only printed if + * @param {String} str - String of the debug message + */ + printDebug: function (str) { + if (debugMode) { + console.log(str); + } + }, + + /** + * Helper function to print a debug error. Debug + * messages are only printed if + * @param {String} str - String of the debug message + */ + printDebugError: function (error) { + if (debugMode) { + console.error(error); + } + }, + + // returns bit length of the integer x + nbits: function (x) { + let r = 1; + let t = x >>> 16; + if (t !== 0) { + x = t; + r += 16; + } + t = x >> 8; + if (t !== 0) { + x = t; + r += 8; + } + t = x >> 4; + if (t !== 0) { + x = t; + r += 4; + } + t = x >> 2; + if (t !== 0) { + x = t; + r += 2; + } + t = x >> 1; + if (t !== 0) { + x = t; + r += 1; + } + return r; + }, + + /** + * If S[1] == 0, then double(S) == (S[2..128] || 0); + * otherwise, double(S) == (S[2..128] || 0) xor + * (zeros(120) || 10000111). + * + * Both OCB and EAX (through CMAC) require this function to be constant-time. + * + * @param {Uint8Array} data + */ + double: function(data) { + const doubleVar = new Uint8Array(data.length); + const last = data.length - 1; + for (let i = 0; i < last; i++) { + doubleVar[i] = (data[i] << 1) ^ (data[i + 1] >> 7); + } + doubleVar[last] = (data[last] << 1) ^ ((data[0] >> 7) * 0x87); + return doubleVar; + }, + + /** + * Shift a Uint8Array to the right by n bits + * @param {Uint8Array} array - The array to shift + * @param {Integer} bits - Amount of bits to shift (MUST be smaller + * than 8) + * @returns {String} Resulting array. + */ + shiftRight: function (array, bits) { + if (bits) { + for (let i = array.length - 1; i >= 0; i--) { + array[i] >>= bits; + if (i > 0) { + array[i] |= (array[i - 1] << (8 - bits)); + } + } + } + return array; + }, + + /** + * Get native Web Cryptography api, only the current version of the spec. + * @returns {Object} The SubtleCrypto api or 'undefined'. + */ + getWebCrypto: function() { + return typeof globalThis !== 'undefined' && globalThis.crypto && globalThis.crypto.subtle; + }, + + /** + * Detect Node.js runtime. + */ + detectNode: function() { + return typeof globalThis.process === 'object' && + typeof globalThis.process.versions === 'object'; + }, + + /** + * Detect native BigInt support + */ + detectBigInt: () => typeof BigInt !== 'undefined', + + /** + * Get BigInteger class + * It wraps the native BigInt type if it's available + * Otherwise it relies on bn.js + * @returns {BigInteger} + * @async + */ + getBigInteger, + + /** + * Get native Node.js crypto api. + * @returns {Object} The crypto module or 'undefined'. + */ + getNodeCrypto: function() { + return void('crypto'); + }, + + getNodeZlib: function() { + return void('zlib'); + }, + + /** + * Get native Node.js Buffer constructor. This should be used since + * Buffer is not available under browserify. + * @returns {Function} The Buffer constructor or 'undefined'. + */ + getNodeBuffer: function() { + return ({}).Buffer; + }, + + getHardwareConcurrency: function() { + if (util.detectNode()) { + const os = void('os'); + return os.cpus().length; + } + + return navigator.hardwareConcurrency || 1; + }, + + isEmailAddress: function(data) { + if (!util.isString(data)) { + return false; + } + const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+([a-zA-Z]{2,}|xn--[a-zA-Z\-0-9]+)))$/; + return re.test(data); + }, + + /** + * Normalize line endings to + * Support any encoding where CR=0x0D, LF=0x0A + */ + canonicalizeEOL: function(data) { + const CR = 13; + const LF = 10; + let carryOverCR = false; + + return transform(data, bytes => { + if (carryOverCR) { + bytes = util.concatUint8Array([new Uint8Array([CR]), bytes]); + } + + if (bytes[bytes.length - 1] === CR) { + carryOverCR = true; + bytes = bytes.subarray(0, -1); + } else { + carryOverCR = false; + } + + let index; + const indices = []; + for (let i = 0; ; i = index) { + index = bytes.indexOf(LF, i) + 1; + if (index) { + if (bytes[index - 2] !== CR) indices.push(index); + } else { + break; + } + } + if (!indices.length) { + return bytes; + } + + const normalized = new Uint8Array(bytes.length + indices.length); + let j = 0; + for (let i = 0; i < indices.length; i++) { + const sub = bytes.subarray(indices[i - 1] || 0, indices[i]); + normalized.set(sub, j); + j += sub.length; + normalized[j - 1] = CR; + normalized[j] = LF; + j++; + } + normalized.set(bytes.subarray(indices[indices.length - 1] || 0), j); + return normalized; + }, () => (carryOverCR ? new Uint8Array([CR]) : undefined)); + }, + + /** + * Convert line endings from canonicalized to native + * Support any encoding where CR=0x0D, LF=0x0A + */ + nativeEOL: function(data) { + const CR = 13; + const LF = 10; + let carryOverCR = false; + + return transform(data, bytes => { + if (carryOverCR && bytes[0] !== LF) { + bytes = util.concatUint8Array([new Uint8Array([CR]), bytes]); + } else { + bytes = new Uint8Array(bytes); // Don't mutate passed bytes + } + + if (bytes[bytes.length - 1] === CR) { + carryOverCR = true; + bytes = bytes.subarray(0, -1); + } else { + carryOverCR = false; + } + + let index; + let j = 0; + for (let i = 0; i !== bytes.length; i = index) { + index = bytes.indexOf(CR, i) + 1; + if (!index) index = bytes.length; + const last = index - (bytes[index] === LF ? 1 : 0); + if (i) bytes.copyWithin(j, i, last); + j += last - i; + } + return bytes.subarray(0, j); + }, () => (carryOverCR ? new Uint8Array([CR]) : undefined)); + }, + + /** + * Remove trailing spaces and tabs from each line + */ + removeTrailingSpaces: function(text) { + return text.split('\n').map(line => { + let i = line.length - 1; + for (; i >= 0 && (line[i] === ' ' || line[i] === '\t'); i--); + return line.substr(0, i + 1); + }).join('\n'); + }, + + wrapError: function(message, error) { + if (!error) { + return new Error(message); + } + + // update error message + try { + error.message = message + ': ' + error.message; + } catch (e) {} + + return error; + }, + + /** + * Map allowed packet tags to corresponding classes + * Meant to be used to format `allowedPacket` for Packetlist.read + * @param {Array} allowedClasses + * @returns {Object} map from enum.packet to corresponding *Packet class + */ + constructAllowedPackets: function(allowedClasses) { + const map = {}; + allowedClasses.forEach(PacketClass => { + if (!PacketClass.tag) { + throw new Error('Invalid input: expected a packet class'); + } + map[PacketClass.tag] = PacketClass; + }); + return map; + }, + + /** + * Return a Promise that will resolve as soon as one of the promises in input resolves + * or will reject if all input promises all rejected + * (similar to Promise.any, but with slightly different error handling) + * @param {Array} promises + * @return {Promise} Promise resolving to the result of the fastest fulfilled promise + * or rejected with the Error of the last resolved Promise (if all promises are rejected) + */ + anyPromise: function(promises) { + return new Promise(async (resolve, reject) => { + let exception; + await Promise.all(promises.map(async promise => { + try { + resolve(await promise); + } catch (e) { + exception = e; + } + })); + reject(exception); + }); + }, + + /** + * Return either `a` or `b` based on `cond`, in algorithmic constant time. + * @param {Boolean} cond + * @param {Uint8Array} a + * @param {Uint8Array} b + * @returns `a` if `cond` is true, `b` otherwise + */ + selectUint8Array: function(cond, a, b) { + const length = Math.max(a.length, b.length); + const result = new Uint8Array(length); + let end = 0; + for (let i = 0; i < result.length; i++) { + result[i] = (a[i] & (256 - cond)) | (b[i] & (255 + cond)); + end += (cond & i < a.length) | ((1 - cond) & i < b.length); + } + return result.subarray(0, end); + }, + /** + * Return either `a` or `b` based on `cond`, in algorithmic constant time. + * NB: it only supports `a, b` with values between 0-255. + * @param {Boolean} cond + * @param {Uint8} a + * @param {Uint8} b + * @returns `a` if `cond` is true, `b` otherwise + */ + selectUint8: function(cond, a, b) { + return (a & (256 - cond)) | (b & (255 + cond)); + } + }; + + /* OpenPGP radix-64/base64 string encoding/decoding + * Copyright 2005 Herbert Hanewinkel, www.haneWIN.de + * version 1.0, check www.haneWIN.de for the latest version + * + * This software is provided as-is, without express or implied warranty. + * Permission to use, copy, modify, distribute or sell this software, with or + * without fee, for any purpose and by any individual or organization, is hereby + * granted, provided that the above copyright notice and this paragraph appear + * in all copies. Distribution as a part of an application or binary must + * include the above copyright notice in the documentation and/or other materials + * provided with the application or distribution. + */ + + const Buffer = util.getNodeBuffer(); + + let encodeChunk; + let decodeChunk; + if (Buffer) { + encodeChunk = buf => Buffer.from(buf).toString('base64'); + decodeChunk = str => { + const b = Buffer.from(str, 'base64'); + return new Uint8Array(b.buffer, b.byteOffset, b.byteLength); + }; + } else { + encodeChunk = buf => btoa(util.uint8ArrayToString(buf)); + decodeChunk = str => util.stringToUint8Array(atob(str)); + } + + /** + * Convert binary array to radix-64 + * @param {Uint8Array | ReadableStream} data - Uint8Array to convert + * @returns {String | ReadableStream} Radix-64 version of input string. + * @static + */ + function encode(data) { + let buf = new Uint8Array(); + return transform(data, value => { + buf = util.concatUint8Array([buf, value]); + const r = []; + const bytesPerLine = 45; // 60 chars per line * (3 bytes / 4 chars of base64). + const lines = Math.floor(buf.length / bytesPerLine); + const bytes = lines * bytesPerLine; + const encoded = encodeChunk(buf.subarray(0, bytes)); + for (let i = 0; i < lines; i++) { + r.push(encoded.substr(i * 60, 60)); + r.push('\n'); + } + buf = buf.subarray(bytes); + return r.join(''); + }, () => (buf.length ? encodeChunk(buf) + '\n' : '')); + } + + /** + * Convert radix-64 to binary array + * @param {String | ReadableStream} data - Radix-64 string to convert + * @returns {Uint8Array | ReadableStream} Binary array version of input string. + * @static + */ + function decode(data) { + let buf = ''; + return transform(data, value => { + buf += value; + + // Count how many whitespace characters there are in buf + let spaces = 0; + const spacechars = [' ', '\t', '\r', '\n']; + for (let i = 0; i < spacechars.length; i++) { + const spacechar = spacechars[i]; + for (let pos = buf.indexOf(spacechar); pos !== -1; pos = buf.indexOf(spacechar, pos + 1)) { + spaces++; + } + } + + // Backtrack until we have 4n non-whitespace characters + // that we can safely base64-decode + let length = buf.length; + for (; length > 0 && (length - spaces) % 4 !== 0; length--) { + if (spacechars.includes(buf[length])) spaces--; + } + + const decoded = decodeChunk(buf.substr(0, length)); + buf = buf.substr(length); + return decoded; + }, () => decodeChunk(buf)); + } + + /** + * Convert a Base-64 encoded string an array of 8-bit integer + * + * Note: accepts both Radix-64 and URL-safe strings + * @param {String} base64 - Base-64 encoded string to convert + * @returns {Uint8Array} An array of 8-bit integers. + */ + function b64ToUint8Array(base64) { + return decode(base64.replace(/-/g, '+').replace(/_/g, '/')); + } + + /** + * Convert an array of 8-bit integer to a Base-64 encoded string + * @param {Uint8Array} bytes - An array of 8-bit integers to convert + * @param {bool} url - If true, output is URL-safe + * @returns {String} Base-64 encoded string. + */ + function uint8ArrayToB64(bytes, url) { + let encoded = encode(bytes).replace(/[\r\n]/g, ''); + if (url) { + encoded = encoded.replace(/[+]/g, '-').replace(/[/]/g, '_').replace(/[=]/g, ''); + } + return encoded; + } + + /** + * @module enums + */ + + const byValue = Symbol('byValue'); + + var enums = { + + /** Maps curve names under various standards to one + * @see {@link https://wiki.gnupg.org/ECC|ECC - GnuPG wiki} + * @enum {String} + * @readonly + */ + curve: { + /** NIST P-256 Curve */ + 'p256': 'p256', + 'P-256': 'p256', + 'secp256r1': 'p256', + 'prime256v1': 'p256', + '1.2.840.10045.3.1.7': 'p256', + '2a8648ce3d030107': 'p256', + '2A8648CE3D030107': 'p256', + + /** NIST P-384 Curve */ + 'p384': 'p384', + 'P-384': 'p384', + 'secp384r1': 'p384', + '1.3.132.0.34': 'p384', + '2b81040022': 'p384', + '2B81040022': 'p384', + + /** NIST P-521 Curve */ + 'p521': 'p521', + 'P-521': 'p521', + 'secp521r1': 'p521', + '1.3.132.0.35': 'p521', + '2b81040023': 'p521', + '2B81040023': 'p521', + + /** SECG SECP256k1 Curve */ + 'secp256k1': 'secp256k1', + '1.3.132.0.10': 'secp256k1', + '2b8104000a': 'secp256k1', + '2B8104000A': 'secp256k1', + + /** Ed25519 */ + 'ED25519': 'ed25519', + 'ed25519': 'ed25519', + 'Ed25519': 'ed25519', + '1.3.6.1.4.1.11591.15.1': 'ed25519', + '2b06010401da470f01': 'ed25519', + '2B06010401DA470F01': 'ed25519', + + /** Curve25519 */ + 'X25519': 'curve25519', + 'cv25519': 'curve25519', + 'curve25519': 'curve25519', + 'Curve25519': 'curve25519', + '1.3.6.1.4.1.3029.1.5.1': 'curve25519', + '2b060104019755010501': 'curve25519', + '2B060104019755010501': 'curve25519', + + /** BrainpoolP256r1 Curve */ + 'brainpoolP256r1': 'brainpoolP256r1', + '1.3.36.3.3.2.8.1.1.7': 'brainpoolP256r1', + '2b2403030208010107': 'brainpoolP256r1', + '2B2403030208010107': 'brainpoolP256r1', + + /** BrainpoolP384r1 Curve */ + 'brainpoolP384r1': 'brainpoolP384r1', + '1.3.36.3.3.2.8.1.1.11': 'brainpoolP384r1', + '2b240303020801010b': 'brainpoolP384r1', + '2B240303020801010B': 'brainpoolP384r1', + + /** BrainpoolP512r1 Curve */ + 'brainpoolP512r1': 'brainpoolP512r1', + '1.3.36.3.3.2.8.1.1.13': 'brainpoolP512r1', + '2b240303020801010d': 'brainpoolP512r1', + '2B240303020801010D': 'brainpoolP512r1' + }, + + /** A string to key specifier type + * @enum {Integer} + * @readonly + */ + s2k: { + simple: 0, + salted: 1, + iterated: 3, + gnu: 101 + }, + + /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-9.1|RFC4880bis-04, section 9.1} + * @enum {Integer} + * @readonly + */ + publicKey: { + /** RSA (Encrypt or Sign) [HAC] */ + rsaEncryptSign: 1, + /** RSA (Encrypt only) [HAC] */ + rsaEncrypt: 2, + /** RSA (Sign only) [HAC] */ + rsaSign: 3, + /** Elgamal (Encrypt only) [ELGAMAL] [HAC] */ + elgamal: 16, + /** DSA (Sign only) [FIPS186] [HAC] */ + dsa: 17, + /** ECDH (Encrypt only) [RFC6637] */ + ecdh: 18, + /** ECDSA (Sign only) [RFC6637] */ + ecdsa: 19, + /** EdDSA (Sign only) + * [{@link https://tools.ietf.org/html/draft-koch-eddsa-for-openpgp-04|Draft RFC}] */ + eddsa: 22, + /** Reserved for AEDH */ + aedh: 23, + /** Reserved for AEDSA */ + aedsa: 24 + }, + + /** {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC4880, section 9.2} + * @enum {Integer} + * @readonly + */ + symmetric: { + plaintext: 0, + /** Not implemented! */ + idea: 1, + tripledes: 2, + cast5: 3, + blowfish: 4, + aes128: 7, + aes192: 8, + aes256: 9, + twofish: 10 + }, + + /** {@link https://tools.ietf.org/html/rfc4880#section-9.3|RFC4880, section 9.3} + * @enum {Integer} + * @readonly + */ + compression: { + uncompressed: 0, + /** RFC1951 */ + zip: 1, + /** RFC1950 */ + zlib: 2, + bzip2: 3 + }, + + /** {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC4880, section 9.4} + * @enum {Integer} + * @readonly + */ + hash: { + md5: 1, + sha1: 2, + ripemd: 3, + sha256: 8, + sha384: 9, + sha512: 10, + sha224: 11 + }, + + /** A list of hash names as accepted by webCrypto functions. + * {@link https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest|Parameters, algo} + * @enum {String} + */ + webHash: { + 'SHA-1': 2, + 'SHA-256': 8, + 'SHA-384': 9, + 'SHA-512': 10 + }, + + /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-9.6|RFC4880bis-04, section 9.6} + * @enum {Integer} + * @readonly + */ + aead: { + eax: 1, + ocb: 2, + experimentalGCM: 100 // Private algorithm + }, + + /** A list of packet types and numeric tags associated with them. + * @enum {Integer} + * @readonly + */ + packet: { + publicKeyEncryptedSessionKey: 1, + signature: 2, + symEncryptedSessionKey: 3, + onePassSignature: 4, + secretKey: 5, + publicKey: 6, + secretSubkey: 7, + compressedData: 8, + symmetricallyEncryptedData: 9, + marker: 10, + literalData: 11, + trust: 12, + userID: 13, + publicSubkey: 14, + userAttribute: 17, + symEncryptedIntegrityProtectedData: 18, + modificationDetectionCode: 19, + aeadEncryptedData: 20 // see IETF draft: https://tools.ietf.org/html/draft-ford-openpgp-format-00#section-2.1 + }, + + /** Data types in the literal packet + * @enum {Integer} + * @readonly + */ + literal: { + /** Binary data 'b' */ + binary: 'b'.charCodeAt(), + /** Text data 't' */ + text: 't'.charCodeAt(), + /** Utf8 data 'u' */ + utf8: 'u'.charCodeAt(), + /** MIME message body part 'm' */ + mime: 'm'.charCodeAt() + }, + + + /** One pass signature packet type + * @enum {Integer} + * @readonly + */ + signature: { + /** 0x00: Signature of a binary document. */ + binary: 0, + /** 0x01: Signature of a canonical text document. + * + * Canonicalyzing the document by converting line endings. */ + text: 1, + /** 0x02: Standalone signature. + * + * This signature is a signature of only its own subpacket contents. + * It is calculated identically to a signature over a zero-lengh + * binary document. Note that it doesn't make sense to have a V3 + * standalone signature. */ + standalone: 2, + /** 0x10: Generic certification of a User ID and Public-Key packet. + * + * The issuer of this certification does not make any particular + * assertion as to how well the certifier has checked that the owner + * of the key is in fact the person described by the User ID. */ + certGeneric: 16, + /** 0x11: Persona certification of a User ID and Public-Key packet. + * + * The issuer of this certification has not done any verification of + * the claim that the owner of this key is the User ID specified. */ + certPersona: 17, + /** 0x12: Casual certification of a User ID and Public-Key packet. + * + * The issuer of this certification has done some casual + * verification of the claim of identity. */ + certCasual: 18, + /** 0x13: Positive certification of a User ID and Public-Key packet. + * + * The issuer of this certification has done substantial + * verification of the claim of identity. + * + * Most OpenPGP implementations make their "key signatures" as 0x10 + * certifications. Some implementations can issue 0x11-0x13 + * certifications, but few differentiate between the types. */ + certPositive: 19, + /** 0x30: Certification revocation signature + * + * This signature revokes an earlier User ID certification signature + * (signature class 0x10 through 0x13) or direct-key signature + * (0x1F). It should be issued by the same key that issued the + * revoked signature or an authorized revocation key. The signature + * is computed over the same data as the certificate that it + * revokes, and should have a later creation date than that + * certificate. */ + certRevocation: 48, + /** 0x18: Subkey Binding Signature + * + * This signature is a statement by the top-level signing key that + * indicates that it owns the subkey. This signature is calculated + * directly on the primary key and subkey, and not on any User ID or + * other packets. A signature that binds a signing subkey MUST have + * an Embedded Signature subpacket in this binding signature that + * contains a 0x19 signature made by the signing subkey on the + * primary key and subkey. */ + subkeyBinding: 24, + /** 0x19: Primary Key Binding Signature + * + * This signature is a statement by a signing subkey, indicating + * that it is owned by the primary key and subkey. This signature + * is calculated the same way as a 0x18 signature: directly on the + * primary key and subkey, and not on any User ID or other packets. + * + * When a signature is made over a key, the hash data starts with the + * octet 0x99, followed by a two-octet length of the key, and then body + * of the key packet. (Note that this is an old-style packet header for + * a key packet with two-octet length.) A subkey binding signature + * (type 0x18) or primary key binding signature (type 0x19) then hashes + * the subkey using the same format as the main key (also using 0x99 as + * the first octet). */ + keyBinding: 25, + /** 0x1F: Signature directly on a key + * + * This signature is calculated directly on a key. It binds the + * information in the Signature subpackets to the key, and is + * appropriate to be used for subpackets that provide information + * about the key, such as the Revocation Key subpacket. It is also + * appropriate for statements that non-self certifiers want to make + * about the key itself, rather than the binding between a key and a + * name. */ + key: 31, + /** 0x20: Key revocation signature + * + * The signature is calculated directly on the key being revoked. A + * revoked key is not to be used. Only revocation signatures by the + * key being revoked, or by an authorized revocation key, should be + * considered valid revocation signatures.a */ + keyRevocation: 32, + /** 0x28: Subkey revocation signature + * + * The signature is calculated directly on the subkey being revoked. + * A revoked subkey is not to be used. Only revocation signatures + * by the top-level signature key that is bound to this subkey, or + * by an authorized revocation key, should be considered valid + * revocation signatures. + * + * Key revocation signatures (types 0x20 and 0x28) + * hash only the key being revoked. */ + subkeyRevocation: 40, + /** 0x40: Timestamp signature. + * This signature is only meaningful for the timestamp contained in + * it. */ + timestamp: 64, + /** 0x50: Third-Party Confirmation signature. + * + * This signature is a signature over some other OpenPGP Signature + * packet(s). It is analogous to a notary seal on the signed data. + * A third-party signature SHOULD include Signature Target + * subpacket(s) to give easy identification. Note that we really do + * mean SHOULD. There are plausible uses for this (such as a blind + * party that only sees the signature, not the key or source + * document) that cannot include a target subpacket. */ + thirdParty: 80 + }, + + /** Signature subpacket type + * @enum {Integer} + * @readonly + */ + signatureSubpacket: { + signatureCreationTime: 2, + signatureExpirationTime: 3, + exportableCertification: 4, + trustSignature: 5, + regularExpression: 6, + revocable: 7, + keyExpirationTime: 9, + placeholderBackwardsCompatibility: 10, + preferredSymmetricAlgorithms: 11, + revocationKey: 12, + issuer: 16, + notationData: 20, + preferredHashAlgorithms: 21, + preferredCompressionAlgorithms: 22, + keyServerPreferences: 23, + preferredKeyServer: 24, + primaryUserID: 25, + policyURI: 26, + keyFlags: 27, + signersUserID: 28, + reasonForRevocation: 29, + features: 30, + signatureTarget: 31, + embeddedSignature: 32, + issuerFingerprint: 33, + preferredAEADAlgorithms: 34 + }, + + /** Key flags + * @enum {Integer} + * @readonly + */ + keyFlags: { + /** 0x01 - This key may be used to certify other keys. */ + certifyKeys: 1, + /** 0x02 - This key may be used to sign data. */ + signData: 2, + /** 0x04 - This key may be used to encrypt communications. */ + encryptCommunication: 4, + /** 0x08 - This key may be used to encrypt storage. */ + encryptStorage: 8, + /** 0x10 - The private component of this key may have been split + * by a secret-sharing mechanism. */ + splitPrivateKey: 16, + /** 0x20 - This key may be used for authentication. */ + authentication: 32, + /** 0x80 - The private component of this key may be in the + * possession of more than one person. */ + sharedPrivateKey: 128 + }, + + /** Armor type + * @enum {Integer} + * @readonly + */ + armor: { + multipartSection: 0, + multipartLast: 1, + signed: 2, + message: 3, + publicKey: 4, + privateKey: 5, + signature: 6 + }, + + /** {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.23|RFC4880, section 5.2.3.23} + * @enum {Integer} + * @readonly + */ + reasonForRevocation: { + /** No reason specified (key revocations or cert revocations) */ + noReason: 0, + /** Key is superseded (key revocations) */ + keySuperseded: 1, + /** Key material has been compromised (key revocations) */ + keyCompromised: 2, + /** Key is retired and no longer used (key revocations) */ + keyRetired: 3, + /** User ID information is no longer valid (cert revocations) */ + userIDInvalid: 32 + }, + + /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.2.3.25|RFC4880bis-04, section 5.2.3.25} + * @enum {Integer} + * @readonly + */ + features: { + /** 0x01 - Modification Detection (packets 18 and 19) */ + modificationDetection: 1, + /** 0x02 - AEAD Encrypted Data Packet (packet 20) and version 5 + * Symmetric-Key Encrypted Session Key Packets (packet 3) */ + aead: 2, + /** 0x04 - Version 5 Public-Key Packet format and corresponding new + * fingerprint format */ + v5Keys: 4 + }, + + /** + * Asserts validity of given value and converts from string/integer to integer. + * @param {Object} type target enum type + * @param {String|Integer} e value to check and/or convert + * @returns {Integer} enum value if it exists + * @throws {Error} if the value is invalid + */ + write: function(type, e) { + if (typeof e === 'number') { + e = this.read(type, e); + } + + if (type[e] !== undefined) { + return type[e]; + } + + throw new Error('Invalid enum value.'); + }, + + /** + * Converts enum integer value to the corresponding string, if it exists. + * @param {Object} type target enum type + * @param {Integer} e value to convert + * @returns {String} name of enum value if it exists + * @throws {Error} if the value is invalid + */ + read: function(type, e) { + if (!type[byValue]) { + type[byValue] = []; + Object.entries(type).forEach(([key, value]) => { + type[byValue][value] = key; + }); + } + + if (type[byValue][e] !== undefined) { + return type[byValue][e]; + } + + throw new Error('Invalid enum value.'); + } + }; + + // GPG4Browsers - An OpenPGP implementation in javascript + + var defaultConfig = { + /** + * @memberof module:config + * @property {Integer} preferredHashAlgorithm Default hash algorithm {@link module:enums.hash} + */ + preferredHashAlgorithm: enums.hash.sha256, + /** + * @memberof module:config + * @property {Integer} preferredSymmetricAlgorithm Default encryption cipher {@link module:enums.symmetric} + */ + preferredSymmetricAlgorithm: enums.symmetric.aes256, + /** + * @memberof module:config + * @property {Integer} compression Default compression algorithm {@link module:enums.compression} + */ + preferredCompressionAlgorithm: enums.compression.uncompressed, + /** + * @memberof module:config + * @property {Integer} deflateLevel Default zip/zlib compression level, between 1 and 9 + */ + deflateLevel: 6, + + /** + * Use Authenticated Encryption with Additional Data (AEAD) protection for symmetric encryption. + * Note: not all OpenPGP implementations are compatible with this option. + * **FUTURE OPENPGP.JS VERSIONS MAY BREAK COMPATIBILITY WHEN USING THIS OPTION** + * @see {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-07|RFC4880bis-07} + * @memberof module:config + * @property {Boolean} aeadProtect + */ + aeadProtect: false, + /** + * Default Authenticated Encryption with Additional Data (AEAD) encryption mode + * Only has an effect when aeadProtect is set to true. + * @memberof module:config + * @property {Integer} preferredAEADAlgorithm Default AEAD mode {@link module:enums.aead} + */ + preferredAEADAlgorithm: enums.aead.eax, + /** + * Chunk Size Byte for Authenticated Encryption with Additional Data (AEAD) mode + * Only has an effect when aeadProtect is set to true. + * Must be an integer value from 0 to 56. + * @memberof module:config + * @property {Integer} aeadChunkSizeByte + */ + aeadChunkSizeByte: 12, + /** + * Use V5 keys. + * Note: not all OpenPGP implementations are compatible with this option. + * **FUTURE OPENPGP.JS VERSIONS MAY BREAK COMPATIBILITY WHEN USING THIS OPTION** + * @memberof module:config + * @property {Boolean} v5Keys + */ + v5Keys: false, + /** + * {@link https://tools.ietf.org/html/rfc4880#section-3.7.1.3|RFC4880 3.7.1.3}: + * Iteration Count Byte for S2K (String to Key) + * @memberof module:config + * @property {Integer} s2kIterationCountByte + */ + s2kIterationCountByte: 224, + /** + * Allow decryption of messages without integrity protection. + * This is an **insecure** setting: + * - message modifications cannot be detected, thus processing the decrypted data is potentially unsafe. + * - it enables downgrade attacks against integrity-protected messages. + * @memberof module:config + * @property {Boolean} allowUnauthenticatedMessages + */ + allowUnauthenticatedMessages: false, + /** + * Allow streaming unauthenticated data before its integrity has been checked. + * This setting is **insecure** if the partially decrypted message is processed further or displayed to the user. + * @memberof module:config + * @property {Boolean} allowUnauthenticatedStream + */ + allowUnauthenticatedStream: false, + /** + * @memberof module:config + * @property {Boolean} checksumRequired Do not throw error when armor is missing a checksum + */ + checksumRequired: false, + /** + * Minimum RSA key size allowed for key generation and message signing, verification and encryption. + * The default is 2047 since due to a bug, previous versions of OpenPGP.js could generate 2047-bit keys instead of 2048-bit ones. + * @memberof module:config + * @property {Number} minRSABits + */ + minRSABits: 2047, + /** + * Work-around for rare GPG decryption bug when encrypting with multiple passwords. + * **Slower and slightly less secure** + * @memberof module:config + * @property {Boolean} passwordCollisionCheck + */ + passwordCollisionCheck: false, + /** + * @memberof module:config + * @property {Boolean} revocationsExpire If true, expired revocation signatures are ignored + */ + revocationsExpire: false, + /** + * Allow decryption using RSA keys without `encrypt` flag. + * This setting is potentially insecure, but it is needed to get around an old openpgpjs bug + * where key flags were ignored when selecting a key for encryption. + * @memberof module:config + * @property {Boolean} allowInsecureDecryptionWithSigningKeys + */ + allowInsecureDecryptionWithSigningKeys: false, + /** + * Allow verification of message signatures with keys whose validity at the time of signing cannot be determined. + * Instead, a verification key will also be consider valid as long as it is valid at the current time. + * This setting is potentially insecure, but it is needed to verify messages signed with keys that were later reformatted, + * and have self-signature's creation date that does not match the primary key creation date. + * @memberof module:config + * @property {Boolean} allowInsecureDecryptionWithSigningKeys + */ + allowInsecureVerificationWithReformattedKeys: false, + + /** + * Enable constant-time decryption of RSA- and ElGamal-encrypted session keys, to hinder Bleichenbacher-like attacks (https://link.springer.com/chapter/10.1007/BFb0055716). + * This setting has measurable performance impact and it is only helpful in application scenarios where both of the following conditions apply: + * - new/incoming messages are automatically decrypted (without user interaction); + * - an attacker can determine how long it takes to decrypt each message (e.g. due to decryption errors being logged remotely). + * See also `constantTimePKCS1DecryptionSupportedSymmetricAlgorithms`. + * @memberof module:config + * @property {Boolean} constantTimePKCS1Decryption + */ + constantTimePKCS1Decryption: false, + /** + * This setting is only meaningful if `constantTimePKCS1Decryption` is enabled. + * Decryption of RSA- and ElGamal-encrypted session keys of symmetric algorithms different from the ones specified here will fail. + * However, the more algorithms are added, the slower the decryption procedure becomes. + * @memberof module:config + * @property {Set} constantTimePKCS1DecryptionSupportedSymmetricAlgorithms {@link module:enums.symmetric} + */ + constantTimePKCS1DecryptionSupportedSymmetricAlgorithms: new Set([enums.symmetric.aes128, enums.symmetric.aes192, enums.symmetric.aes256]), + + /** + * @memberof module:config + * @property {Integer} minBytesForWebCrypto The minimum amount of bytes for which to use native WebCrypto APIs when available + */ + minBytesForWebCrypto: 1000, + /** + * @memberof module:config + * @property {Boolean} ignoreUnsupportedPackets Ignore unsupported/unrecognizable packets on parsing instead of throwing an error + */ + ignoreUnsupportedPackets: true, + /** + * @memberof module:config + * @property {Boolean} ignoreMalformedPackets Ignore malformed packets on parsing instead of throwing an error + */ + ignoreMalformedPackets: false, + /** + * @memberof module:config + * @property {Boolean} showVersion Whether to include {@link module:config/config.versionString} in armored messages + */ + showVersion: false, + /** + * @memberof module:config + * @property {Boolean} showComment Whether to include {@link module:config/config.commentString} in armored messages + */ + showComment: false, + /** + * @memberof module:config + * @property {String} versionString A version string to be included in armored messages + */ + versionString: 'OpenPGP.js 5.1.0', + /** + * @memberof module:config + * @property {String} commentString A comment string to be included in armored messages + */ + commentString: 'https://openpgpjs.org', + + /** + * Max userID string length (used for parsing) + * @memberof module:config + * @property {Integer} maxUserIDLength + */ + maxUserIDLength: 1024 * 5, + /** + * Contains notatations that are considered "known". Known notations do not trigger + * validation error when the notation is marked as critical. + * @memberof module:config + * @property {Array} knownNotations + */ + knownNotations: ['preferred-email-encoding@pgp.com', 'pka-address@gnupg.org'], + /** + * Whether to use the indutny/elliptic library for curves (other than Curve25519) that are not supported by the available native crypto API. + * When false, certain standard curves will not be supported (depending on the platform). + * Note: the indutny/elliptic curve library is not designed to be constant time. + * @memberof module:config + * @property {Boolean} useIndutnyElliptic + */ + useIndutnyElliptic: true, + /** + * Reject insecure hash algorithms + * @memberof module:config + * @property {Set} rejectHashAlgorithms {@link module:enums.hash} + */ + rejectHashAlgorithms: new Set([enums.hash.md5, enums.hash.ripemd]), + /** + * Reject insecure message hash algorithms + * @memberof module:config + * @property {Set} rejectMessageHashAlgorithms {@link module:enums.hash} + */ + rejectMessageHashAlgorithms: new Set([enums.hash.md5, enums.hash.ripemd, enums.hash.sha1]), + /** + * Reject insecure public key algorithms for key generation and message encryption, signing or verification + * @memberof module:config + * @property {Set} rejectPublicKeyAlgorithms {@link module:enums.publicKey} + */ + rejectPublicKeyAlgorithms: new Set([enums.publicKey.elgamal, enums.publicKey.dsa]), + /** + * Reject non-standard curves for key generation, message encryption, signing or verification + * @memberof module:config + * @property {Set} rejectCurves {@link module:enums.curve} + */ + rejectCurves: new Set([enums.curve.brainpoolP256r1, enums.curve.brainpoolP384r1, enums.curve.brainpoolP512r1, enums.curve.secp256k1]) + }; + + // GPG4Browsers - An OpenPGP implementation in javascript + + /** + * Finds out which Ascii Armoring type is used. Throws error if unknown type. + * @param {String} text - ascii armored text + * @returns {Integer} 0 = MESSAGE PART n of m. + * 1 = MESSAGE PART n + * 2 = SIGNED MESSAGE + * 3 = PGP MESSAGE + * 4 = PUBLIC KEY BLOCK + * 5 = PRIVATE KEY BLOCK + * 6 = SIGNATURE + * @private + */ + function getType(text) { + const reHeader = /^-----BEGIN PGP (MESSAGE, PART \d+\/\d+|MESSAGE, PART \d+|SIGNED MESSAGE|MESSAGE|PUBLIC KEY BLOCK|PRIVATE KEY BLOCK|SIGNATURE)-----$/m; + + const header = text.match(reHeader); + + if (!header) { + throw new Error('Unknown ASCII armor type'); + } + + // BEGIN PGP MESSAGE, PART X/Y + // Used for multi-part messages, where the armor is split amongst Y + // parts, and this is the Xth part out of Y. + if (/MESSAGE, PART \d+\/\d+/.test(header[1])) { + return enums.armor.multipartSection; + } else + // BEGIN PGP MESSAGE, PART X + // Used for multi-part messages, where this is the Xth part of an + // unspecified number of parts. Requires the MESSAGE-ID Armor + // Header to be used. + if (/MESSAGE, PART \d+/.test(header[1])) { + return enums.armor.multipartLast; + } else + // BEGIN PGP SIGNED MESSAGE + if (/SIGNED MESSAGE/.test(header[1])) { + return enums.armor.signed; + } else + // BEGIN PGP MESSAGE + // Used for signed, encrypted, or compressed files. + if (/MESSAGE/.test(header[1])) { + return enums.armor.message; + } else + // BEGIN PGP PUBLIC KEY BLOCK + // Used for armoring public keys. + if (/PUBLIC KEY BLOCK/.test(header[1])) { + return enums.armor.publicKey; + } else + // BEGIN PGP PRIVATE KEY BLOCK + // Used for armoring private keys. + if (/PRIVATE KEY BLOCK/.test(header[1])) { + return enums.armor.privateKey; + } else + // BEGIN PGP SIGNATURE + // Used for detached signatures, OpenPGP/MIME signatures, and + // cleartext signatures. Note that PGP 2.x uses BEGIN PGP MESSAGE + // for detached signatures. + if (/SIGNATURE/.test(header[1])) { + return enums.armor.signature; + } + } + + /** + * Add additional information to the armor version of an OpenPGP binary + * packet block. + * @author Alex + * @version 2011-12-16 + * @param {String} [customComment] - Additional comment to add to the armored string + * @returns {String} The header information. + * @private + */ + function addheader(customComment, config) { + let result = ''; + if (config.showVersion) { + result += 'Version: ' + config.versionString + '\n'; + } + if (config.showComment) { + result += 'Comment: ' + config.commentString + '\n'; + } + if (customComment) { + result += 'Comment: ' + customComment + '\n'; + } + result += '\n'; + return result; + } + + + /** + * Calculates a checksum over the given data and returns it base64 encoded + * @param {String | ReadableStream} data - Data to create a CRC-24 checksum for + * @returns {String | ReadableStream} Base64 encoded checksum. + * @private + */ + function getCheckSum(data) { + const crc = createcrc24(data); + return encode(crc); + } + + // https://create.stephan-brumme.com/crc32/#slicing-by-8-overview + + const crc_table = [ + new Array(0xFF), + new Array(0xFF), + new Array(0xFF), + new Array(0xFF) + ]; + + for (let i = 0; i <= 0xFF; i++) { + let crc = i << 16; + for (let j = 0; j < 8; j++) { + crc = (crc << 1) ^ ((crc & 0x800000) !== 0 ? 0x864CFB : 0); + } + crc_table[0][i] = + ((crc & 0xFF0000) >> 16) | + (crc & 0x00FF00) | + ((crc & 0x0000FF) << 16); + } + for (let i = 0; i <= 0xFF; i++) { + crc_table[1][i] = (crc_table[0][i] >> 8) ^ crc_table[0][crc_table[0][i] & 0xFF]; + } + for (let i = 0; i <= 0xFF; i++) { + crc_table[2][i] = (crc_table[1][i] >> 8) ^ crc_table[0][crc_table[1][i] & 0xFF]; + } + for (let i = 0; i <= 0xFF; i++) { + crc_table[3][i] = (crc_table[2][i] >> 8) ^ crc_table[0][crc_table[2][i] & 0xFF]; + } + + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView#Endianness + const isLittleEndian = (function() { + const buffer = new ArrayBuffer(2); + new DataView(buffer).setInt16(0, 0xFF, true /* littleEndian */); + // Int16Array uses the platform's endianness. + return new Int16Array(buffer)[0] === 0xFF; + }()); + + /** + * Internal function to calculate a CRC-24 checksum over a given string (data) + * @param {String | ReadableStream} input - Data to create a CRC-24 checksum for + * @returns {Uint8Array | ReadableStream} The CRC-24 checksum. + * @private + */ + function createcrc24(input) { + let crc = 0xCE04B7; + return transform(input, value => { + const len32 = isLittleEndian ? Math.floor(value.length / 4) : 0; + const arr32 = new Uint32Array(value.buffer, value.byteOffset, len32); + for (let i = 0; i < len32; i++) { + crc ^= arr32[i]; + crc = + crc_table[0][(crc >> 24) & 0xFF] ^ + crc_table[1][(crc >> 16) & 0xFF] ^ + crc_table[2][(crc >> 8) & 0xFF] ^ + crc_table[3][(crc >> 0) & 0xFF]; + } + for (let i = len32 * 4; i < value.length; i++) { + crc = (crc >> 8) ^ crc_table[0][(crc & 0xFF) ^ value[i]]; + } + }, () => new Uint8Array([crc, crc >> 8, crc >> 16])); + } + + /** + * Verify armored headers. RFC4880, section 6.3: "OpenPGP should consider improperly formatted + * Armor Headers to be corruption of the ASCII Armor." + * @private + * @param {Array} headers - Armor headers + */ + function verifyHeaders(headers) { + for (let i = 0; i < headers.length; i++) { + if (!/^([^\s:]|[^\s:][^:]*[^\s:]): .+$/.test(headers[i])) { + throw new Error('Improperly formatted armor header: ' + headers[i]); + } + if (!/^(Version|Comment|MessageID|Hash|Charset): .+$/.test(headers[i])) { + util.printDebugError(new Error('Unknown header: ' + headers[i])); + } + } + } + + /** + * Splits a message into two parts, the body and the checksum. This is an internal function + * @param {String} text - OpenPGP armored message part + * @returns {Object} An object with attribute "body" containing the body. + * and an attribute "checksum" containing the checksum. + * @private + */ + function splitChecksum(text) { + let body = text; + let checksum = ''; + + const lastEquals = text.lastIndexOf('='); + + if (lastEquals >= 0 && lastEquals !== text.length - 1) { // '=' as the last char means no checksum + body = text.slice(0, lastEquals); + checksum = text.slice(lastEquals + 1).substr(0, 4); + } + + return { body: body, checksum: checksum }; + } + + /** + * Dearmor an OpenPGP armored message; verify the checksum and return + * the encoded bytes + * @param {String} input - OpenPGP armored message + * @returns {Promise} An object with attribute "text" containing the message text, + * an attribute "data" containing a stream of bytes and "type" for the ASCII armor type + * @async + * @static + */ + function unarmor(input, config = defaultConfig) { + return new Promise(async (resolve, reject) => { + try { + const reSplit = /^-----[^-]+-----$/m; + const reEmptyLine = /^[ \f\r\t\u00a0\u2000-\u200a\u202f\u205f\u3000]*$/; + + let type; + const headers = []; + let lastHeaders = headers; + let headersDone; + let text = []; + let textDone; + let checksum; + let data = decode(transformPair(input, async (readable, writable) => { + const reader = getReader(readable); + try { + while (true) { + let line = await reader.readLine(); + if (line === undefined) { + throw new Error('Misformed armored text'); + } + // remove trailing whitespace at end of lines + line = util.removeTrailingSpaces(line.replace(/[\r\n]/g, '')); + if (!type) { + if (reSplit.test(line)) { + type = getType(line); + } + } else if (!headersDone) { + if (reSplit.test(line)) { + reject(new Error('Mandatory blank line missing between armor headers and armor data')); + } + if (!reEmptyLine.test(line)) { + lastHeaders.push(line); + } else { + verifyHeaders(lastHeaders); + headersDone = true; + if (textDone || type !== 2) { + resolve({ text, data, headers, type }); + break; + } + } + } else if (!textDone && type === 2) { + if (!reSplit.test(line)) { + // Reverse dash-escaping for msg + text.push(line.replace(/^- /, '')); + } else { + text = text.join('\r\n'); + textDone = true; + verifyHeaders(lastHeaders); + lastHeaders = []; + headersDone = false; + } + } + } + } catch (e) { + reject(e); + return; + } + const writer = getWriter(writable); + try { + while (true) { + await writer.ready; + const { done, value } = await reader.read(); + if (done) { + throw new Error('Misformed armored text'); + } + const line = value + ''; + if (line.indexOf('=') === -1 && line.indexOf('-') === -1) { + await writer.write(line); + } else { + let remainder = await reader.readToEnd(); + if (!remainder.length) remainder = ''; + remainder = line + remainder; + remainder = util.removeTrailingSpaces(remainder.replace(/\r/g, '')); + const parts = remainder.split(reSplit); + if (parts.length === 1) { + throw new Error('Misformed armored text'); + } + const split = splitChecksum(parts[0].slice(0, -1)); + checksum = split.checksum; + await writer.write(split.body); + break; + } + } + await writer.ready; + await writer.close(); + } catch (e) { + await writer.abort(e); + } + })); + data = transformPair(data, async (readable, writable) => { + const checksumVerified = readToEnd(getCheckSum(passiveClone(readable))); + checksumVerified.catch(() => {}); + await pipe(readable, writable, { + preventClose: true + }); + const writer = getWriter(writable); + try { + const checksumVerifiedString = (await checksumVerified).replace('\n', ''); + if (checksum !== checksumVerifiedString && (checksum || config.checksumRequired)) { + throw new Error('Ascii armor integrity check failed'); + } + await writer.ready; + await writer.close(); + } catch (e) { + await writer.abort(e); + } + }); + } catch (e) { + reject(e); + } + }).then(async result => { + if (isArrayStream(result.data)) { + result.data = await readToEnd(result.data); + } + return result; + }); + } + + + /** + * Armor an OpenPGP binary packet block + * @param {module:enums.armor} messageType - Type of the message + * @param {Uint8Array | ReadableStream} body - The message body to armor + * @param {Integer} [partIndex] + * @param {Integer} [partTotal] + * @param {String} [customComment] - Additional comment to add to the armored string + * @returns {String | ReadableStream} Armored text. + * @static + */ + function armor(messageType, body, partIndex, partTotal, customComment, config = defaultConfig) { + let text; + let hash; + if (messageType === enums.armor.signed) { + text = body.text; + hash = body.hash; + body = body.data; + } + const bodyClone = passiveClone(body); + const result = []; + switch (messageType) { + case enums.armor.multipartSection: + result.push('-----BEGIN PGP MESSAGE, PART ' + partIndex + '/' + partTotal + '-----\n'); + result.push(addheader(customComment, config)); + result.push(encode(body)); + result.push('=', getCheckSum(bodyClone)); + result.push('-----END PGP MESSAGE, PART ' + partIndex + '/' + partTotal + '-----\n'); + break; + case enums.armor.multipartLast: + result.push('-----BEGIN PGP MESSAGE, PART ' + partIndex + '-----\n'); + result.push(addheader(customComment, config)); + result.push(encode(body)); + result.push('=', getCheckSum(bodyClone)); + result.push('-----END PGP MESSAGE, PART ' + partIndex + '-----\n'); + break; + case enums.armor.signed: + result.push('\n-----BEGIN PGP SIGNED MESSAGE-----\n'); + result.push('Hash: ' + hash + '\n\n'); + result.push(text.replace(/^-/mg, '- -')); + result.push('\n-----BEGIN PGP SIGNATURE-----\n'); + result.push(addheader(customComment, config)); + result.push(encode(body)); + result.push('=', getCheckSum(bodyClone)); + result.push('-----END PGP SIGNATURE-----\n'); + break; + case enums.armor.message: + result.push('-----BEGIN PGP MESSAGE-----\n'); + result.push(addheader(customComment, config)); + result.push(encode(body)); + result.push('=', getCheckSum(bodyClone)); + result.push('-----END PGP MESSAGE-----\n'); + break; + case enums.armor.publicKey: + result.push('-----BEGIN PGP PUBLIC KEY BLOCK-----\n'); + result.push(addheader(customComment, config)); + result.push(encode(body)); + result.push('=', getCheckSum(bodyClone)); + result.push('-----END PGP PUBLIC KEY BLOCK-----\n'); + break; + case enums.armor.privateKey: + result.push('-----BEGIN PGP PRIVATE KEY BLOCK-----\n'); + result.push(addheader(customComment, config)); + result.push(encode(body)); + result.push('=', getCheckSum(bodyClone)); + result.push('-----END PGP PRIVATE KEY BLOCK-----\n'); + break; + case enums.armor.signature: + result.push('-----BEGIN PGP SIGNATURE-----\n'); + result.push(addheader(customComment, config)); + result.push(encode(body)); + result.push('=', getCheckSum(bodyClone)); + result.push('-----END PGP SIGNATURE-----\n'); + break; + } + + return util.concat(result); + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + /** + * Implementation of type key id + * + * {@link https://tools.ietf.org/html/rfc4880#section-3.3|RFC4880 3.3}: + * A Key ID is an eight-octet scalar that identifies a key. + * Implementations SHOULD NOT assume that Key IDs are unique. The + * section "Enhanced Key Formats" below describes how Key IDs are + * formed. + */ + class KeyID { + constructor() { + this.bytes = ''; + } + + /** + * Parsing method for a key id + * @param {Uint8Array} bytes - Input to read the key id from + */ + read(bytes) { + this.bytes = util.uint8ArrayToString(bytes.subarray(0, 8)); + } + + /** + * Serializes the Key ID + * @returns {Uint8Array} Key ID as a Uint8Array. + */ + write() { + return util.stringToUint8Array(this.bytes); + } + + /** + * Returns the Key ID represented as a hexadecimal string + * @returns {String} Key ID as a hexadecimal string. + */ + toHex() { + return util.uint8ArrayToHex(util.stringToUint8Array(this.bytes)); + } + + /** + * Checks equality of Key ID's + * @param {KeyID} keyID + * @param {Boolean} matchWildcard - Indicates whether to check if either keyID is a wildcard + */ + equals(keyID, matchWildcard = false) { + return (matchWildcard && (keyID.isWildcard() || this.isWildcard())) || this.bytes === keyID.bytes; + } + + /** + * Checks to see if the Key ID is unset + * @returns {Boolean} True if the Key ID is null. + */ + isNull() { + return this.bytes === ''; + } + + /** + * Checks to see if the Key ID is a "wildcard" Key ID (all zeros) + * @returns {Boolean} True if this is a wildcard Key ID. + */ + isWildcard() { + return /^0+$/.test(this.toHex()); + } + + static mapToHex(keyID) { + return keyID.toHex(); + } + + static fromID(hex) { + const keyID = new KeyID(); + keyID.read(util.hexToUint8Array(hex)); + return keyID; + } + + static wildcard() { + const keyID = new KeyID(); + keyID.read(new Uint8Array(8)); + return keyID; + } + } + + /** + * @file {@link http://asmjs.org Asm.js} implementation of the {@link https://en.wikipedia.org/wiki/Advanced_Encryption_Standard Advanced Encryption Standard}. + * @author Artem S Vybornov + * @license MIT + */ + var AES_asm = function () { + + /** + * Galois Field stuff init flag + */ + var ginit_done = false; + + /** + * Galois Field exponentiation and logarithm tables for 3 (the generator) + */ + var gexp3, glog3; + + /** + * Init Galois Field tables + */ + function ginit() { + gexp3 = [], + glog3 = []; + + var a = 1, c, d; + for (c = 0; c < 255; c++) { + gexp3[c] = a; + + // Multiply by three + d = a & 0x80, a <<= 1, a &= 255; + if (d === 0x80) a ^= 0x1b; + a ^= gexp3[c]; + + // Set the log table value + glog3[gexp3[c]] = c; + } + gexp3[255] = gexp3[0]; + glog3[0] = 0; + + ginit_done = true; + } + + /** + * Galois Field multiplication + * @param {number} a + * @param {number} b + * @return {number} + */ + function gmul(a, b) { + var c = gexp3[(glog3[a] + glog3[b]) % 255]; + if (a === 0 || b === 0) c = 0; + return c; + } + + /** + * Galois Field reciprocal + * @param {number} a + * @return {number} + */ + function ginv(a) { + var i = gexp3[255 - glog3[a]]; + if (a === 0) i = 0; + return i; + } + + /** + * AES stuff init flag + */ + var aes_init_done = false; + + /** + * Encryption, Decryption, S-Box and KeyTransform tables + * + * @type {number[]} + */ + var aes_sbox; + + /** + * @type {number[]} + */ + var aes_sinv; + + /** + * @type {number[][]} + */ + var aes_enc; + + /** + * @type {number[][]} + */ + var aes_dec; + + /** + * Init AES tables + */ + function aes_init() { + if (!ginit_done) ginit(); + + // Calculates AES S-Box value + function _s(a) { + var c, s, x; + s = x = ginv(a); + for (c = 0; c < 4; c++) { + s = ((s << 1) | (s >>> 7)) & 255; + x ^= s; + } + x ^= 99; + return x; + } + + // Tables + aes_sbox = [], + aes_sinv = [], + aes_enc = [[], [], [], []], + aes_dec = [[], [], [], []]; + + for (var i = 0; i < 256; i++) { + var s = _s(i); + + // S-Box and its inverse + aes_sbox[i] = s; + aes_sinv[s] = i; + + // Ecryption and Decryption tables + aes_enc[0][i] = (gmul(2, s) << 24) | (s << 16) | (s << 8) | gmul(3, s); + aes_dec[0][s] = (gmul(14, i) << 24) | (gmul(9, i) << 16) | (gmul(13, i) << 8) | gmul(11, i); + // Rotate tables + for (var t = 1; t < 4; t++) { + aes_enc[t][i] = (aes_enc[t - 1][i] >>> 8) | (aes_enc[t - 1][i] << 24); + aes_dec[t][s] = (aes_dec[t - 1][s] >>> 8) | (aes_dec[t - 1][s] << 24); + } + } + + aes_init_done = true; + } + + /** + * Asm.js module constructor. + * + *

+ * Heap buffer layout by offset: + *

+     * 0x0000   encryption key schedule
+     * 0x0400   decryption key schedule
+     * 0x0800   sbox
+     * 0x0c00   inv sbox
+     * 0x1000   encryption tables
+     * 0x2000   decryption tables
+     * 0x3000   reserved (future GCM multiplication lookup table)
+     * 0x4000   data
+     * 
+ * Don't touch anything before 0x400. + *

+ * + * @alias AES_asm + * @class + * @param foreign - ignored + * @param buffer - heap buffer to link with + */ + var wrapper = function (foreign, buffer) { + // Init AES stuff for the first time + if (!aes_init_done) aes_init(); + + // Fill up AES tables + var heap = new Uint32Array(buffer); + heap.set(aes_sbox, 0x0800 >> 2); + heap.set(aes_sinv, 0x0c00 >> 2); + for (var i = 0; i < 4; i++) { + heap.set(aes_enc[i], (0x1000 + 0x400 * i) >> 2); + heap.set(aes_dec[i], (0x2000 + 0x400 * i) >> 2); + } + + /** + * Calculate AES key schedules. + * @instance + * @memberof AES_asm + * @param {number} ks - key size, 4/6/8 (for 128/192/256-bit key correspondingly) + * @param {number} k0 - key vector components + * @param {number} k1 - key vector components + * @param {number} k2 - key vector components + * @param {number} k3 - key vector components + * @param {number} k4 - key vector components + * @param {number} k5 - key vector components + * @param {number} k6 - key vector components + * @param {number} k7 - key vector components + */ + function set_key(ks, k0, k1, k2, k3, k4, k5, k6, k7) { + var ekeys = heap.subarray(0x000, 60), + dkeys = heap.subarray(0x100, 0x100 + 60); + + // Encryption key schedule + ekeys.set([k0, k1, k2, k3, k4, k5, k6, k7]); + for (var i = ks, rcon = 1; i < 4 * ks + 28; i++) { + var k = ekeys[i - 1]; + if ((i % ks === 0) || (ks === 8 && i % ks === 4)) { + k = aes_sbox[k >>> 24] << 24 ^ aes_sbox[k >>> 16 & 255] << 16 ^ aes_sbox[k >>> 8 & 255] << 8 ^ aes_sbox[k & 255]; + } + if (i % ks === 0) { + k = (k << 8) ^ (k >>> 24) ^ (rcon << 24); + rcon = (rcon << 1) ^ ((rcon & 0x80) ? 0x1b : 0); + } + ekeys[i] = ekeys[i - ks] ^ k; + } + + // Decryption key schedule + for (var j = 0; j < i; j += 4) { + for (var jj = 0; jj < 4; jj++) { + var k = ekeys[i - (4 + j) + (4 - jj) % 4]; + if (j < 4 || j >= i - 4) { + dkeys[j + jj] = k; + } else { + dkeys[j + jj] = aes_dec[0][aes_sbox[k >>> 24]] + ^ aes_dec[1][aes_sbox[k >>> 16 & 255]] + ^ aes_dec[2][aes_sbox[k >>> 8 & 255]] + ^ aes_dec[3][aes_sbox[k & 255]]; + } + } + } + + // Set rounds number + asm.set_rounds(ks + 5); + } + + // create library object with necessary properties + var stdlib = {Uint8Array: Uint8Array, Uint32Array: Uint32Array}; + + var asm = function (stdlib, foreign, buffer) { + "use asm"; + + var S0 = 0, S1 = 0, S2 = 0, S3 = 0, + I0 = 0, I1 = 0, I2 = 0, I3 = 0, + N0 = 0, N1 = 0, N2 = 0, N3 = 0, + M0 = 0, M1 = 0, M2 = 0, M3 = 0, + H0 = 0, H1 = 0, H2 = 0, H3 = 0, + R = 0; + + var HEAP = new stdlib.Uint32Array(buffer), + DATA = new stdlib.Uint8Array(buffer); + + /** + * AES core + * @param {number} k - precomputed key schedule offset + * @param {number} s - precomputed sbox table offset + * @param {number} t - precomputed round table offset + * @param {number} r - number of inner rounds to perform + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _core(k, s, t, r, x0, x1, x2, x3) { + k = k | 0; + s = s | 0; + t = t | 0; + r = r | 0; + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + var t1 = 0, t2 = 0, t3 = 0, + y0 = 0, y1 = 0, y2 = 0, y3 = 0, + i = 0; + + t1 = t | 0x400, t2 = t | 0x800, t3 = t | 0xc00; + + // round 0 + x0 = x0 ^ HEAP[(k | 0) >> 2], + x1 = x1 ^ HEAP[(k | 4) >> 2], + x2 = x2 ^ HEAP[(k | 8) >> 2], + x3 = x3 ^ HEAP[(k | 12) >> 2]; + + // round 1..r + for (i = 16; (i | 0) <= (r << 4); i = (i + 16) | 0) { + y0 = HEAP[(t | x0 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x1 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x2 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x3 << 2 & 1020) >> 2] ^ HEAP[(k | i | 0) >> 2], + y1 = HEAP[(t | x1 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x2 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x3 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x0 << 2 & 1020) >> 2] ^ HEAP[(k | i | 4) >> 2], + y2 = HEAP[(t | x2 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x3 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x0 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x1 << 2 & 1020) >> 2] ^ HEAP[(k | i | 8) >> 2], + y3 = HEAP[(t | x3 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x0 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x1 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x2 << 2 & 1020) >> 2] ^ HEAP[(k | i | 12) >> 2]; + x0 = y0, x1 = y1, x2 = y2, x3 = y3; + } + + // final round + S0 = HEAP[(s | x0 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x1 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x2 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x3 << 2 & 1020) >> 2] ^ HEAP[(k | i | 0) >> 2], + S1 = HEAP[(s | x1 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x2 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x3 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x0 << 2 & 1020) >> 2] ^ HEAP[(k | i | 4) >> 2], + S2 = HEAP[(s | x2 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x3 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x0 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x1 << 2 & 1020) >> 2] ^ HEAP[(k | i | 8) >> 2], + S3 = HEAP[(s | x3 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x0 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x1 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x2 << 2 & 1020) >> 2] ^ HEAP[(k | i | 12) >> 2]; + } + + /** + * ECB mode encryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _ecb_enc(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + _core( + 0x0000, 0x0800, 0x1000, + R, + x0, + x1, + x2, + x3 + ); + } + + /** + * ECB mode decryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _ecb_dec(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + var t = 0; + + _core( + 0x0400, 0x0c00, 0x2000, + R, + x0, + x3, + x2, + x1 + ); + + t = S1, S1 = S3, S3 = t; + } + + + /** + * CBC mode encryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _cbc_enc(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + _core( + 0x0000, 0x0800, 0x1000, + R, + I0 ^ x0, + I1 ^ x1, + I2 ^ x2, + I3 ^ x3 + ); + + I0 = S0, + I1 = S1, + I2 = S2, + I3 = S3; + } + + /** + * CBC mode decryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _cbc_dec(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + var t = 0; + + _core( + 0x0400, 0x0c00, 0x2000, + R, + x0, + x3, + x2, + x1 + ); + + t = S1, S1 = S3, S3 = t; + + S0 = S0 ^ I0, + S1 = S1 ^ I1, + S2 = S2 ^ I2, + S3 = S3 ^ I3; + + I0 = x0, + I1 = x1, + I2 = x2, + I3 = x3; + } + + /** + * CFB mode encryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _cfb_enc(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + _core( + 0x0000, 0x0800, 0x1000, + R, + I0, + I1, + I2, + I3 + ); + + I0 = S0 = S0 ^ x0, + I1 = S1 = S1 ^ x1, + I2 = S2 = S2 ^ x2, + I3 = S3 = S3 ^ x3; + } + + + /** + * CFB mode decryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _cfb_dec(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + _core( + 0x0000, 0x0800, 0x1000, + R, + I0, + I1, + I2, + I3 + ); + + S0 = S0 ^ x0, + S1 = S1 ^ x1, + S2 = S2 ^ x2, + S3 = S3 ^ x3; + + I0 = x0, + I1 = x1, + I2 = x2, + I3 = x3; + } + + /** + * OFB mode encryption / decryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _ofb(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + _core( + 0x0000, 0x0800, 0x1000, + R, + I0, + I1, + I2, + I3 + ); + + I0 = S0, + I1 = S1, + I2 = S2, + I3 = S3; + + S0 = S0 ^ x0, + S1 = S1 ^ x1, + S2 = S2 ^ x2, + S3 = S3 ^ x3; + } + + /** + * CTR mode encryption / decryption + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _ctr(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + _core( + 0x0000, 0x0800, 0x1000, + R, + N0, + N1, + N2, + N3 + ); + + N3 = (~M3 & N3) | M3 & (N3 + 1); + N2 = (~M2 & N2) | M2 & (N2 + ((N3 | 0) == 0)); + N1 = (~M1 & N1) | M1 & (N1 + ((N2 | 0) == 0)); + N0 = (~M0 & N0) | M0 & (N0 + ((N1 | 0) == 0)); + + S0 = S0 ^ x0; + S1 = S1 ^ x1; + S2 = S2 ^ x2; + S3 = S3 ^ x3; + } + + /** + * GCM mode MAC calculation + * @param {number} x0 - 128-bit input block vector + * @param {number} x1 - 128-bit input block vector + * @param {number} x2 - 128-bit input block vector + * @param {number} x3 - 128-bit input block vector + */ + function _gcm_mac(x0, x1, x2, x3) { + x0 = x0 | 0; + x1 = x1 | 0; + x2 = x2 | 0; + x3 = x3 | 0; + + var y0 = 0, y1 = 0, y2 = 0, y3 = 0, + z0 = 0, z1 = 0, z2 = 0, z3 = 0, + i = 0, c = 0; + + x0 = x0 ^ I0, + x1 = x1 ^ I1, + x2 = x2 ^ I2, + x3 = x3 ^ I3; + + y0 = H0 | 0, + y1 = H1 | 0, + y2 = H2 | 0, + y3 = H3 | 0; + + for (; (i | 0) < 128; i = (i + 1) | 0) { + if (y0 >>> 31) { + z0 = z0 ^ x0, + z1 = z1 ^ x1, + z2 = z2 ^ x2, + z3 = z3 ^ x3; + } + + y0 = (y0 << 1) | (y1 >>> 31), + y1 = (y1 << 1) | (y2 >>> 31), + y2 = (y2 << 1) | (y3 >>> 31), + y3 = (y3 << 1); + + c = x3 & 1; + + x3 = (x3 >>> 1) | (x2 << 31), + x2 = (x2 >>> 1) | (x1 << 31), + x1 = (x1 >>> 1) | (x0 << 31), + x0 = (x0 >>> 1); + + if (c) x0 = x0 ^ 0xe1000000; + } + + I0 = z0, + I1 = z1, + I2 = z2, + I3 = z3; + } + + /** + * Set the internal rounds number. + * @instance + * @memberof AES_asm + * @param {number} r - number if inner AES rounds + */ + function set_rounds(r) { + r = r | 0; + R = r; + } + + /** + * Populate the internal state of the module. + * @instance + * @memberof AES_asm + * @param {number} s0 - state vector + * @param {number} s1 - state vector + * @param {number} s2 - state vector + * @param {number} s3 - state vector + */ + function set_state(s0, s1, s2, s3) { + s0 = s0 | 0; + s1 = s1 | 0; + s2 = s2 | 0; + s3 = s3 | 0; + + S0 = s0, + S1 = s1, + S2 = s2, + S3 = s3; + } + + /** + * Populate the internal iv of the module. + * @instance + * @memberof AES_asm + * @param {number} i0 - iv vector + * @param {number} i1 - iv vector + * @param {number} i2 - iv vector + * @param {number} i3 - iv vector + */ + function set_iv(i0, i1, i2, i3) { + i0 = i0 | 0; + i1 = i1 | 0; + i2 = i2 | 0; + i3 = i3 | 0; + + I0 = i0, + I1 = i1, + I2 = i2, + I3 = i3; + } + + /** + * Set nonce for CTR-family modes. + * @instance + * @memberof AES_asm + * @param {number} n0 - nonce vector + * @param {number} n1 - nonce vector + * @param {number} n2 - nonce vector + * @param {number} n3 - nonce vector + */ + function set_nonce(n0, n1, n2, n3) { + n0 = n0 | 0; + n1 = n1 | 0; + n2 = n2 | 0; + n3 = n3 | 0; + + N0 = n0, + N1 = n1, + N2 = n2, + N3 = n3; + } + + /** + * Set counter mask for CTR-family modes. + * @instance + * @memberof AES_asm + * @param {number} m0 - counter mask vector + * @param {number} m1 - counter mask vector + * @param {number} m2 - counter mask vector + * @param {number} m3 - counter mask vector + */ + function set_mask(m0, m1, m2, m3) { + m0 = m0 | 0; + m1 = m1 | 0; + m2 = m2 | 0; + m3 = m3 | 0; + + M0 = m0, + M1 = m1, + M2 = m2, + M3 = m3; + } + + /** + * Set counter for CTR-family modes. + * @instance + * @memberof AES_asm + * @param {number} c0 - counter vector + * @param {number} c1 - counter vector + * @param {number} c2 - counter vector + * @param {number} c3 - counter vector + */ + function set_counter(c0, c1, c2, c3) { + c0 = c0 | 0; + c1 = c1 | 0; + c2 = c2 | 0; + c3 = c3 | 0; + + N3 = (~M3 & N3) | M3 & c3, + N2 = (~M2 & N2) | M2 & c2, + N1 = (~M1 & N1) | M1 & c1, + N0 = (~M0 & N0) | M0 & c0; + } + + /** + * Store the internal state vector into the heap. + * @instance + * @memberof AES_asm + * @param {number} pos - offset where to put the data + * @return {number} The number of bytes have been written into the heap, always 16. + */ + function get_state(pos) { + pos = pos | 0; + + if (pos & 15) return -1; + + DATA[pos | 0] = S0 >>> 24, + DATA[pos | 1] = S0 >>> 16 & 255, + DATA[pos | 2] = S0 >>> 8 & 255, + DATA[pos | 3] = S0 & 255, + DATA[pos | 4] = S1 >>> 24, + DATA[pos | 5] = S1 >>> 16 & 255, + DATA[pos | 6] = S1 >>> 8 & 255, + DATA[pos | 7] = S1 & 255, + DATA[pos | 8] = S2 >>> 24, + DATA[pos | 9] = S2 >>> 16 & 255, + DATA[pos | 10] = S2 >>> 8 & 255, + DATA[pos | 11] = S2 & 255, + DATA[pos | 12] = S3 >>> 24, + DATA[pos | 13] = S3 >>> 16 & 255, + DATA[pos | 14] = S3 >>> 8 & 255, + DATA[pos | 15] = S3 & 255; + + return 16; + } + + /** + * Store the internal iv vector into the heap. + * @instance + * @memberof AES_asm + * @param {number} pos - offset where to put the data + * @return {number} The number of bytes have been written into the heap, always 16. + */ + function get_iv(pos) { + pos = pos | 0; + + if (pos & 15) return -1; + + DATA[pos | 0] = I0 >>> 24, + DATA[pos | 1] = I0 >>> 16 & 255, + DATA[pos | 2] = I0 >>> 8 & 255, + DATA[pos | 3] = I0 & 255, + DATA[pos | 4] = I1 >>> 24, + DATA[pos | 5] = I1 >>> 16 & 255, + DATA[pos | 6] = I1 >>> 8 & 255, + DATA[pos | 7] = I1 & 255, + DATA[pos | 8] = I2 >>> 24, + DATA[pos | 9] = I2 >>> 16 & 255, + DATA[pos | 10] = I2 >>> 8 & 255, + DATA[pos | 11] = I2 & 255, + DATA[pos | 12] = I3 >>> 24, + DATA[pos | 13] = I3 >>> 16 & 255, + DATA[pos | 14] = I3 >>> 8 & 255, + DATA[pos | 15] = I3 & 255; + + return 16; + } + + /** + * GCM initialization. + * @instance + * @memberof AES_asm + */ + function gcm_init() { + _ecb_enc(0, 0, 0, 0); + H0 = S0, + H1 = S1, + H2 = S2, + H3 = S3; + } + + /** + * Perform ciphering operation on the supplied data. + * @instance + * @memberof AES_asm + * @param {number} mode - block cipher mode (see {@link AES_asm} mode constants) + * @param {number} pos - offset of the data being processed + * @param {number} len - length of the data being processed + * @return {number} Actual amount of data have been processed. + */ + function cipher(mode, pos, len) { + mode = mode | 0; + pos = pos | 0; + len = len | 0; + + var ret = 0; + + if (pos & 15) return -1; + + while ((len | 0) >= 16) { + _cipher_modes[mode & 7]( + DATA[pos | 0] << 24 | DATA[pos | 1] << 16 | DATA[pos | 2] << 8 | DATA[pos | 3], + DATA[pos | 4] << 24 | DATA[pos | 5] << 16 | DATA[pos | 6] << 8 | DATA[pos | 7], + DATA[pos | 8] << 24 | DATA[pos | 9] << 16 | DATA[pos | 10] << 8 | DATA[pos | 11], + DATA[pos | 12] << 24 | DATA[pos | 13] << 16 | DATA[pos | 14] << 8 | DATA[pos | 15] + ); + + DATA[pos | 0] = S0 >>> 24, + DATA[pos | 1] = S0 >>> 16 & 255, + DATA[pos | 2] = S0 >>> 8 & 255, + DATA[pos | 3] = S0 & 255, + DATA[pos | 4] = S1 >>> 24, + DATA[pos | 5] = S1 >>> 16 & 255, + DATA[pos | 6] = S1 >>> 8 & 255, + DATA[pos | 7] = S1 & 255, + DATA[pos | 8] = S2 >>> 24, + DATA[pos | 9] = S2 >>> 16 & 255, + DATA[pos | 10] = S2 >>> 8 & 255, + DATA[pos | 11] = S2 & 255, + DATA[pos | 12] = S3 >>> 24, + DATA[pos | 13] = S3 >>> 16 & 255, + DATA[pos | 14] = S3 >>> 8 & 255, + DATA[pos | 15] = S3 & 255; + + ret = (ret + 16) | 0, + pos = (pos + 16) | 0, + len = (len - 16) | 0; + } + + return ret | 0; + } + + /** + * Calculates MAC of the supplied data. + * @instance + * @memberof AES_asm + * @param {number} mode - block cipher mode (see {@link AES_asm} mode constants) + * @param {number} pos - offset of the data being processed + * @param {number} len - length of the data being processed + * @return {number} Actual amount of data have been processed. + */ + function mac(mode, pos, len) { + mode = mode | 0; + pos = pos | 0; + len = len | 0; + + var ret = 0; + + if (pos & 15) return -1; + + while ((len | 0) >= 16) { + _mac_modes[mode & 1]( + DATA[pos | 0] << 24 | DATA[pos | 1] << 16 | DATA[pos | 2] << 8 | DATA[pos | 3], + DATA[pos | 4] << 24 | DATA[pos | 5] << 16 | DATA[pos | 6] << 8 | DATA[pos | 7], + DATA[pos | 8] << 24 | DATA[pos | 9] << 16 | DATA[pos | 10] << 8 | DATA[pos | 11], + DATA[pos | 12] << 24 | DATA[pos | 13] << 16 | DATA[pos | 14] << 8 | DATA[pos | 15] + ); + + ret = (ret + 16) | 0, + pos = (pos + 16) | 0, + len = (len - 16) | 0; + } + + return ret | 0; + } + + /** + * AES cipher modes table (virual methods) + */ + var _cipher_modes = [_ecb_enc, _ecb_dec, _cbc_enc, _cbc_dec, _cfb_enc, _cfb_dec, _ofb, _ctr]; + + /** + * AES MAC modes table (virual methods) + */ + var _mac_modes = [_cbc_enc, _gcm_mac]; + + /** + * Asm.js module exports + */ + return { + set_rounds: set_rounds, + set_state: set_state, + set_iv: set_iv, + set_nonce: set_nonce, + set_mask: set_mask, + set_counter: set_counter, + get_state: get_state, + get_iv: get_iv, + gcm_init: gcm_init, + cipher: cipher, + mac: mac, + }; + }(stdlib, foreign, buffer); + + asm.set_key = set_key; + + return asm; + }; + + /** + * AES enciphering mode constants + * @enum {number} + * @const + */ + wrapper.ENC = { + ECB: 0, + CBC: 2, + CFB: 4, + OFB: 6, + CTR: 7, + }, + + /** + * AES deciphering mode constants + * @enum {number} + * @const + */ + wrapper.DEC = { + ECB: 1, + CBC: 3, + CFB: 5, + OFB: 6, + CTR: 7, + }, + + /** + * AES MAC mode constants + * @enum {number} + * @const + */ + wrapper.MAC = { + CBC: 0, + GCM: 1, + }; + + /** + * Heap data offset + * @type {number} + * @const + */ + wrapper.HEAP_DATA = 0x4000; + + return wrapper; + }(); + + function is_bytes(a) { + return a instanceof Uint8Array; + } + function _heap_init(heap, heapSize) { + const size = heap ? heap.byteLength : heapSize || 65536; + if (size & 0xfff || size <= 0) + throw new Error('heap size must be a positive integer and a multiple of 4096'); + heap = heap || new Uint8Array(new ArrayBuffer(size)); + return heap; + } + function _heap_write(heap, hpos, data, dpos, dlen) { + const hlen = heap.length - hpos; + const wlen = hlen < dlen ? hlen : dlen; + heap.set(data.subarray(dpos, dpos + wlen), hpos); + return wlen; + } + function joinBytes(...arg) { + const totalLenght = arg.reduce((sum, curr) => sum + curr.length, 0); + const ret = new Uint8Array(totalLenght); + let cursor = 0; + for (let i = 0; i < arg.length; i++) { + ret.set(arg[i], cursor); + cursor += arg[i].length; + } + return ret; + } + + class IllegalStateError extends Error { + constructor(...args) { + super(...args); + } + } + class IllegalArgumentError extends Error { + constructor(...args) { + super(...args); + } + } + class SecurityError extends Error { + constructor(...args) { + super(...args); + } + } + + const heap_pool = []; + const asm_pool = []; + class AES { + constructor(key, iv, padding = true, mode, heap, asm) { + this.pos = 0; + this.len = 0; + this.mode = mode; + // The AES object state + this.pos = 0; + this.len = 0; + this.key = key; + this.iv = iv; + this.padding = padding; + // The AES "worker" + this.acquire_asm(heap, asm); + } + acquire_asm(heap, asm) { + if (this.heap === undefined || this.asm === undefined) { + this.heap = heap || heap_pool.pop() || _heap_init().subarray(AES_asm.HEAP_DATA); + this.asm = asm || asm_pool.pop() || new AES_asm(null, this.heap.buffer); + this.reset(this.key, this.iv); + } + return { heap: this.heap, asm: this.asm }; + } + release_asm() { + if (this.heap !== undefined && this.asm !== undefined) { + heap_pool.push(this.heap); + asm_pool.push(this.asm); + } + this.heap = undefined; + this.asm = undefined; + } + reset(key, iv) { + const { asm } = this.acquire_asm(); + // Key + const keylen = key.length; + if (keylen !== 16 && keylen !== 24 && keylen !== 32) + throw new IllegalArgumentError('illegal key size'); + const keyview = new DataView(key.buffer, key.byteOffset, key.byteLength); + asm.set_key(keylen >> 2, keyview.getUint32(0), keyview.getUint32(4), keyview.getUint32(8), keyview.getUint32(12), keylen > 16 ? keyview.getUint32(16) : 0, keylen > 16 ? keyview.getUint32(20) : 0, keylen > 24 ? keyview.getUint32(24) : 0, keylen > 24 ? keyview.getUint32(28) : 0); + // IV + if (iv !== undefined) { + if (iv.length !== 16) + throw new IllegalArgumentError('illegal iv size'); + let ivview = new DataView(iv.buffer, iv.byteOffset, iv.byteLength); + asm.set_iv(ivview.getUint32(0), ivview.getUint32(4), ivview.getUint32(8), ivview.getUint32(12)); + } + else { + asm.set_iv(0, 0, 0, 0); + } + } + AES_Encrypt_process(data) { + if (!is_bytes(data)) + throw new TypeError("data isn't of expected type"); + let { heap, asm } = this.acquire_asm(); + let amode = AES_asm.ENC[this.mode]; + let hpos = AES_asm.HEAP_DATA; + let pos = this.pos; + let len = this.len; + let dpos = 0; + let dlen = data.length || 0; + let rpos = 0; + let rlen = (len + dlen) & -16; + let wlen = 0; + let result = new Uint8Array(rlen); + while (dlen > 0) { + wlen = _heap_write(heap, pos + len, data, dpos, dlen); + len += wlen; + dpos += wlen; + dlen -= wlen; + wlen = asm.cipher(amode, hpos + pos, len); + if (wlen) + result.set(heap.subarray(pos, pos + wlen), rpos); + rpos += wlen; + if (wlen < len) { + pos += wlen; + len -= wlen; + } + else { + pos = 0; + len = 0; + } + } + this.pos = pos; + this.len = len; + return result; + } + AES_Encrypt_finish() { + let { heap, asm } = this.acquire_asm(); + let amode = AES_asm.ENC[this.mode]; + let hpos = AES_asm.HEAP_DATA; + let pos = this.pos; + let len = this.len; + let plen = 16 - (len % 16); + let rlen = len; + if (this.hasOwnProperty('padding')) { + if (this.padding) { + for (let p = 0; p < plen; ++p) { + heap[pos + len + p] = plen; + } + len += plen; + rlen = len; + } + else if (len % 16) { + throw new IllegalArgumentError('data length must be a multiple of the block size'); + } + } + else { + len += plen; + } + const result = new Uint8Array(rlen); + if (len) + asm.cipher(amode, hpos + pos, len); + if (rlen) + result.set(heap.subarray(pos, pos + rlen)); + this.pos = 0; + this.len = 0; + this.release_asm(); + return result; + } + AES_Decrypt_process(data) { + if (!is_bytes(data)) + throw new TypeError("data isn't of expected type"); + let { heap, asm } = this.acquire_asm(); + let amode = AES_asm.DEC[this.mode]; + let hpos = AES_asm.HEAP_DATA; + let pos = this.pos; + let len = this.len; + let dpos = 0; + let dlen = data.length || 0; + let rpos = 0; + let rlen = (len + dlen) & -16; + let plen = 0; + let wlen = 0; + if (this.padding) { + plen = len + dlen - rlen || 16; + rlen -= plen; + } + const result = new Uint8Array(rlen); + while (dlen > 0) { + wlen = _heap_write(heap, pos + len, data, dpos, dlen); + len += wlen; + dpos += wlen; + dlen -= wlen; + wlen = asm.cipher(amode, hpos + pos, len - (!dlen ? plen : 0)); + if (wlen) + result.set(heap.subarray(pos, pos + wlen), rpos); + rpos += wlen; + if (wlen < len) { + pos += wlen; + len -= wlen; + } + else { + pos = 0; + len = 0; + } + } + this.pos = pos; + this.len = len; + return result; + } + AES_Decrypt_finish() { + let { heap, asm } = this.acquire_asm(); + let amode = AES_asm.DEC[this.mode]; + let hpos = AES_asm.HEAP_DATA; + let pos = this.pos; + let len = this.len; + let rlen = len; + if (len > 0) { + if (len % 16) { + if (this.hasOwnProperty('padding')) { + throw new IllegalArgumentError('data length must be a multiple of the block size'); + } + else { + len += 16 - (len % 16); + } + } + asm.cipher(amode, hpos + pos, len); + if (this.hasOwnProperty('padding') && this.padding) { + let pad = heap[pos + rlen - 1]; + if (pad < 1 || pad > 16 || pad > rlen) + throw new SecurityError('bad padding'); + let pcheck = 0; + for (let i = pad; i > 1; i--) + pcheck |= pad ^ heap[pos + rlen - i]; + if (pcheck) + throw new SecurityError('bad padding'); + rlen -= pad; + } + } + const result = new Uint8Array(rlen); + if (rlen > 0) { + result.set(heap.subarray(pos, pos + rlen)); + } + this.pos = 0; + this.len = 0; + this.release_asm(); + return result; + } + } + + class AES_ECB { + static encrypt(data, key, padding = false) { + return new AES_ECB(key, padding).encrypt(data); + } + static decrypt(data, key, padding = false) { + return new AES_ECB(key, padding).decrypt(data); + } + constructor(key, padding = false, aes) { + this.aes = aes ? aes : new AES(key, undefined, padding, 'ECB'); + } + encrypt(data) { + const r1 = this.aes.AES_Encrypt_process(data); + const r2 = this.aes.AES_Encrypt_finish(); + return joinBytes(r1, r2); + } + decrypt(data) { + const r1 = this.aes.AES_Decrypt_process(data); + const r2 = this.aes.AES_Decrypt_finish(); + return joinBytes(r1, r2); + } + } + + /** + * Javascript AES implementation. + * This is used as fallback if the native Crypto APIs are not available. + */ + function aes(length) { + const C = function(key) { + const aesECB = new AES_ECB(key); + + this.encrypt = function(block) { + return aesECB.encrypt(block); + }; + + this.decrypt = function(block) { + return aesECB.decrypt(block); + }; + }; + + C.blockSize = C.prototype.blockSize = 16; + C.keySize = C.prototype.keySize = length / 8; + + return C; + } + + //Paul Tero, July 2001 + //http://www.tero.co.uk/des/ + // + //Optimised for performance with large blocks by Michael Hayworth, November 2001 + //http://www.netdealing.com + // + // Modified by Recurity Labs GmbH + + //THIS SOFTWARE IS PROVIDED "AS IS" AND + //ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + //IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + //ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + //FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + //DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + //OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + //HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + //LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + //OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + //SUCH DAMAGE. + + //des + //this takes the key, the message, and whether to encrypt or decrypt + + function des(keys, message, encrypt, mode, iv, padding) { + //declaring this locally speeds things up a bit + const spfunction1 = [ + 0x1010400, 0, 0x10000, 0x1010404, 0x1010004, 0x10404, 0x4, 0x10000, 0x400, 0x1010400, + 0x1010404, 0x400, 0x1000404, 0x1010004, 0x1000000, 0x4, 0x404, 0x1000400, 0x1000400, 0x10400, 0x10400, 0x1010000, + 0x1010000, 0x1000404, 0x10004, 0x1000004, 0x1000004, 0x10004, 0, 0x404, 0x10404, 0x1000000, 0x10000, 0x1010404, 0x4, + 0x1010000, 0x1010400, 0x1000000, 0x1000000, 0x400, 0x1010004, 0x10000, 0x10400, 0x1000004, 0x400, 0x4, 0x1000404, + 0x10404, 0x1010404, 0x10004, 0x1010000, 0x1000404, 0x1000004, 0x404, 0x10404, 0x1010400, 0x404, 0x1000400, + 0x1000400, 0, 0x10004, 0x10400, 0, 0x1010004 + ]; + const spfunction2 = [ + -0x7fef7fe0, -0x7fff8000, 0x8000, 0x108020, 0x100000, 0x20, -0x7fefffe0, -0x7fff7fe0, + -0x7fffffe0, -0x7fef7fe0, -0x7fef8000, -0x80000000, -0x7fff8000, 0x100000, 0x20, -0x7fefffe0, 0x108000, 0x100020, + -0x7fff7fe0, 0, -0x80000000, 0x8000, 0x108020, -0x7ff00000, 0x100020, -0x7fffffe0, 0, 0x108000, 0x8020, -0x7fef8000, + -0x7ff00000, 0x8020, 0, 0x108020, -0x7fefffe0, 0x100000, -0x7fff7fe0, -0x7ff00000, -0x7fef8000, 0x8000, -0x7ff00000, + -0x7fff8000, 0x20, -0x7fef7fe0, 0x108020, 0x20, 0x8000, -0x80000000, 0x8020, -0x7fef8000, 0x100000, -0x7fffffe0, + 0x100020, -0x7fff7fe0, -0x7fffffe0, 0x100020, 0x108000, 0, -0x7fff8000, 0x8020, -0x80000000, -0x7fefffe0, + -0x7fef7fe0, 0x108000 + ]; + const spfunction3 = [ + 0x208, 0x8020200, 0, 0x8020008, 0x8000200, 0, 0x20208, 0x8000200, 0x20008, 0x8000008, + 0x8000008, 0x20000, 0x8020208, 0x20008, 0x8020000, 0x208, 0x8000000, 0x8, 0x8020200, 0x200, 0x20200, 0x8020000, + 0x8020008, 0x20208, 0x8000208, 0x20200, 0x20000, 0x8000208, 0x8, 0x8020208, 0x200, 0x8000000, 0x8020200, 0x8000000, + 0x20008, 0x208, 0x20000, 0x8020200, 0x8000200, 0, 0x200, 0x20008, 0x8020208, 0x8000200, 0x8000008, 0x200, 0, + 0x8020008, 0x8000208, 0x20000, 0x8000000, 0x8020208, 0x8, 0x20208, 0x20200, 0x8000008, 0x8020000, 0x8000208, 0x208, + 0x8020000, 0x20208, 0x8, 0x8020008, 0x20200 + ]; + const spfunction4 = [ + 0x802001, 0x2081, 0x2081, 0x80, 0x802080, 0x800081, 0x800001, 0x2001, 0, 0x802000, + 0x802000, 0x802081, 0x81, 0, 0x800080, 0x800001, 0x1, 0x2000, 0x800000, 0x802001, 0x80, 0x800000, 0x2001, 0x2080, + 0x800081, 0x1, 0x2080, 0x800080, 0x2000, 0x802080, 0x802081, 0x81, 0x800080, 0x800001, 0x802000, 0x802081, 0x81, 0, + 0, 0x802000, 0x2080, 0x800080, 0x800081, 0x1, 0x802001, 0x2081, 0x2081, 0x80, 0x802081, 0x81, 0x1, 0x2000, 0x800001, + 0x2001, 0x802080, 0x800081, 0x2001, 0x2080, 0x800000, 0x802001, 0x80, 0x800000, 0x2000, 0x802080 + ]; + const spfunction5 = [ + 0x100, 0x2080100, 0x2080000, 0x42000100, 0x80000, 0x100, 0x40000000, 0x2080000, + 0x40080100, 0x80000, 0x2000100, 0x40080100, 0x42000100, 0x42080000, 0x80100, 0x40000000, 0x2000000, 0x40080000, + 0x40080000, 0, 0x40000100, 0x42080100, 0x42080100, 0x2000100, 0x42080000, 0x40000100, 0, 0x42000000, 0x2080100, + 0x2000000, 0x42000000, 0x80100, 0x80000, 0x42000100, 0x100, 0x2000000, 0x40000000, 0x2080000, 0x42000100, + 0x40080100, 0x2000100, 0x40000000, 0x42080000, 0x2080100, 0x40080100, 0x100, 0x2000000, 0x42080000, 0x42080100, + 0x80100, 0x42000000, 0x42080100, 0x2080000, 0, 0x40080000, 0x42000000, 0x80100, 0x2000100, 0x40000100, 0x80000, 0, + 0x40080000, 0x2080100, 0x40000100 + ]; + const spfunction6 = [ + 0x20000010, 0x20400000, 0x4000, 0x20404010, 0x20400000, 0x10, 0x20404010, 0x400000, + 0x20004000, 0x404010, 0x400000, 0x20000010, 0x400010, 0x20004000, 0x20000000, 0x4010, 0, 0x400010, 0x20004010, + 0x4000, 0x404000, 0x20004010, 0x10, 0x20400010, 0x20400010, 0, 0x404010, 0x20404000, 0x4010, 0x404000, 0x20404000, + 0x20000000, 0x20004000, 0x10, 0x20400010, 0x404000, 0x20404010, 0x400000, 0x4010, 0x20000010, 0x400000, 0x20004000, + 0x20000000, 0x4010, 0x20000010, 0x20404010, 0x404000, 0x20400000, 0x404010, 0x20404000, 0, 0x20400010, 0x10, 0x4000, + 0x20400000, 0x404010, 0x4000, 0x400010, 0x20004010, 0, 0x20404000, 0x20000000, 0x400010, 0x20004010 + ]; + const spfunction7 = [ + 0x200000, 0x4200002, 0x4000802, 0, 0x800, 0x4000802, 0x200802, 0x4200800, 0x4200802, + 0x200000, 0, 0x4000002, 0x2, 0x4000000, 0x4200002, 0x802, 0x4000800, 0x200802, 0x200002, 0x4000800, 0x4000002, + 0x4200000, 0x4200800, 0x200002, 0x4200000, 0x800, 0x802, 0x4200802, 0x200800, 0x2, 0x4000000, 0x200800, 0x4000000, + 0x200800, 0x200000, 0x4000802, 0x4000802, 0x4200002, 0x4200002, 0x2, 0x200002, 0x4000000, 0x4000800, 0x200000, + 0x4200800, 0x802, 0x200802, 0x4200800, 0x802, 0x4000002, 0x4200802, 0x4200000, 0x200800, 0, 0x2, 0x4200802, 0, + 0x200802, 0x4200000, 0x800, 0x4000002, 0x4000800, 0x800, 0x200002 + ]; + const spfunction8 = [ + 0x10001040, 0x1000, 0x40000, 0x10041040, 0x10000000, 0x10001040, 0x40, 0x10000000, + 0x40040, 0x10040000, 0x10041040, 0x41000, 0x10041000, 0x41040, 0x1000, 0x40, 0x10040000, 0x10000040, 0x10001000, + 0x1040, 0x41000, 0x40040, 0x10040040, 0x10041000, 0x1040, 0, 0, 0x10040040, 0x10000040, 0x10001000, 0x41040, + 0x40000, 0x41040, 0x40000, 0x10041000, 0x1000, 0x40, 0x10040040, 0x1000, 0x41040, 0x10001000, 0x40, 0x10000040, + 0x10040000, 0x10040040, 0x10000000, 0x40000, 0x10001040, 0, 0x10041040, 0x40040, 0x10000040, 0x10040000, 0x10001000, + 0x10001040, 0, 0x10041040, 0x41000, 0x41000, 0x1040, 0x1040, 0x40040, 0x10000000, 0x10041000 + ]; + + //create the 16 or 48 subkeys we will need + let m = 0; + let i; + let j; + let temp; + let right1; + let right2; + let left; + let right; + let looping; + let cbcleft; + let cbcleft2; + let cbcright; + let cbcright2; + let endloop; + let loopinc; + let len = message.length; + + //set up the loops for single and triple des + const iterations = keys.length === 32 ? 3 : 9; //single or triple des + if (iterations === 3) { + looping = encrypt ? [0, 32, 2] : [30, -2, -2]; + } else { + looping = encrypt ? [0, 32, 2, 62, 30, -2, 64, 96, 2] : [94, 62, -2, 32, 64, 2, 30, -2, -2]; + } + + //pad the message depending on the padding parameter + //only add padding if encrypting - note that you need to use the same padding option for both encrypt and decrypt + if (encrypt) { + message = desAddPadding(message, padding); + len = message.length; + } + + //store the result here + let result = new Uint8Array(len); + let k = 0; + + if (mode === 1) { //CBC mode + cbcleft = (iv[m++] << 24) | (iv[m++] << 16) | (iv[m++] << 8) | iv[m++]; + cbcright = (iv[m++] << 24) | (iv[m++] << 16) | (iv[m++] << 8) | iv[m++]; + m = 0; + } + + //loop through each 64 bit chunk of the message + while (m < len) { + left = (message[m++] << 24) | (message[m++] << 16) | (message[m++] << 8) | message[m++]; + right = (message[m++] << 24) | (message[m++] << 16) | (message[m++] << 8) | message[m++]; + + //for Cipher Block Chaining mode, xor the message with the previous result + if (mode === 1) { + if (encrypt) { + left ^= cbcleft; + right ^= cbcright; + } else { + cbcleft2 = cbcleft; + cbcright2 = cbcright; + cbcleft = left; + cbcright = right; + } + } + + //first each 64 but chunk of the message must be permuted according to IP + temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; + right ^= temp; + left ^= (temp << 4); + temp = ((left >>> 16) ^ right) & 0x0000ffff; + right ^= temp; + left ^= (temp << 16); + temp = ((right >>> 2) ^ left) & 0x33333333; + left ^= temp; + right ^= (temp << 2); + temp = ((right >>> 8) ^ left) & 0x00ff00ff; + left ^= temp; + right ^= (temp << 8); + temp = ((left >>> 1) ^ right) & 0x55555555; + right ^= temp; + left ^= (temp << 1); + + left = ((left << 1) | (left >>> 31)); + right = ((right << 1) | (right >>> 31)); + + //do this either 1 or 3 times for each chunk of the message + for (j = 0; j < iterations; j += 3) { + endloop = looping[j + 1]; + loopinc = looping[j + 2]; + //now go through and perform the encryption or decryption + for (i = looping[j]; i !== endloop; i += loopinc) { //for efficiency + right1 = right ^ keys[i]; + right2 = ((right >>> 4) | (right << 28)) ^ keys[i + 1]; + //the result is attained by passing these bytes through the S selection functions + temp = left; + left = right; + right = temp ^ (spfunction2[(right1 >>> 24) & 0x3f] | spfunction4[(right1 >>> 16) & 0x3f] | spfunction6[(right1 >>> + 8) & 0x3f] | spfunction8[right1 & 0x3f] | spfunction1[(right2 >>> 24) & 0x3f] | spfunction3[(right2 >>> 16) & + 0x3f] | spfunction5[(right2 >>> 8) & 0x3f] | spfunction7[right2 & 0x3f]); + } + temp = left; + left = right; + right = temp; //unreverse left and right + } //for either 1 or 3 iterations + + //move then each one bit to the right + left = ((left >>> 1) | (left << 31)); + right = ((right >>> 1) | (right << 31)); + + //now perform IP-1, which is IP in the opposite direction + temp = ((left >>> 1) ^ right) & 0x55555555; + right ^= temp; + left ^= (temp << 1); + temp = ((right >>> 8) ^ left) & 0x00ff00ff; + left ^= temp; + right ^= (temp << 8); + temp = ((right >>> 2) ^ left) & 0x33333333; + left ^= temp; + right ^= (temp << 2); + temp = ((left >>> 16) ^ right) & 0x0000ffff; + right ^= temp; + left ^= (temp << 16); + temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; + right ^= temp; + left ^= (temp << 4); + + //for Cipher Block Chaining mode, xor the message with the previous result + if (mode === 1) { + if (encrypt) { + cbcleft = left; + cbcright = right; + } else { + left ^= cbcleft2; + right ^= cbcright2; + } + } + + result[k++] = (left >>> 24); + result[k++] = ((left >>> 16) & 0xff); + result[k++] = ((left >>> 8) & 0xff); + result[k++] = (left & 0xff); + result[k++] = (right >>> 24); + result[k++] = ((right >>> 16) & 0xff); + result[k++] = ((right >>> 8) & 0xff); + result[k++] = (right & 0xff); + } //for every 8 characters, or 64 bits in the message + + //only remove padding if decrypting - note that you need to use the same padding option for both encrypt and decrypt + if (!encrypt) { + result = desRemovePadding(result, padding); + } + + return result; + } //end of des + + + //desCreateKeys + //this takes as input a 64 bit key (even though only 56 bits are used) + //as an array of 2 integers, and returns 16 48 bit keys + + function desCreateKeys(key) { + //declaring this locally speeds things up a bit + const pc2bytes0 = [ + 0, 0x4, 0x20000000, 0x20000004, 0x10000, 0x10004, 0x20010000, 0x20010004, 0x200, 0x204, + 0x20000200, 0x20000204, 0x10200, 0x10204, 0x20010200, 0x20010204 + ]; + const pc2bytes1 = [ + 0, 0x1, 0x100000, 0x100001, 0x4000000, 0x4000001, 0x4100000, 0x4100001, 0x100, 0x101, 0x100100, + 0x100101, 0x4000100, 0x4000101, 0x4100100, 0x4100101 + ]; + const pc2bytes2 = [ + 0, 0x8, 0x800, 0x808, 0x1000000, 0x1000008, 0x1000800, 0x1000808, 0, 0x8, 0x800, 0x808, + 0x1000000, 0x1000008, 0x1000800, 0x1000808 + ]; + const pc2bytes3 = [ + 0, 0x200000, 0x8000000, 0x8200000, 0x2000, 0x202000, 0x8002000, 0x8202000, 0x20000, 0x220000, + 0x8020000, 0x8220000, 0x22000, 0x222000, 0x8022000, 0x8222000 + ]; + const pc2bytes4 = [ + 0, 0x40000, 0x10, 0x40010, 0, 0x40000, 0x10, 0x40010, 0x1000, 0x41000, 0x1010, 0x41010, 0x1000, + 0x41000, 0x1010, 0x41010 + ]; + const pc2bytes5 = [ + 0, 0x400, 0x20, 0x420, 0, 0x400, 0x20, 0x420, 0x2000000, 0x2000400, 0x2000020, 0x2000420, + 0x2000000, 0x2000400, 0x2000020, 0x2000420 + ]; + const pc2bytes6 = [ + 0, 0x10000000, 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002, 0, 0x10000000, + 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002 + ]; + const pc2bytes7 = [ + 0, 0x10000, 0x800, 0x10800, 0x20000000, 0x20010000, 0x20000800, 0x20010800, 0x20000, 0x30000, + 0x20800, 0x30800, 0x20020000, 0x20030000, 0x20020800, 0x20030800 + ]; + const pc2bytes8 = [ + 0, 0x40000, 0, 0x40000, 0x2, 0x40002, 0x2, 0x40002, 0x2000000, 0x2040000, 0x2000000, 0x2040000, + 0x2000002, 0x2040002, 0x2000002, 0x2040002 + ]; + const pc2bytes9 = [ + 0, 0x10000000, 0x8, 0x10000008, 0, 0x10000000, 0x8, 0x10000008, 0x400, 0x10000400, 0x408, + 0x10000408, 0x400, 0x10000400, 0x408, 0x10000408 + ]; + const pc2bytes10 = [ + 0, 0x20, 0, 0x20, 0x100000, 0x100020, 0x100000, 0x100020, 0x2000, 0x2020, 0x2000, 0x2020, + 0x102000, 0x102020, 0x102000, 0x102020 + ]; + const pc2bytes11 = [ + 0, 0x1000000, 0x200, 0x1000200, 0x200000, 0x1200000, 0x200200, 0x1200200, 0x4000000, 0x5000000, + 0x4000200, 0x5000200, 0x4200000, 0x5200000, 0x4200200, 0x5200200 + ]; + const pc2bytes12 = [ + 0, 0x1000, 0x8000000, 0x8001000, 0x80000, 0x81000, 0x8080000, 0x8081000, 0x10, 0x1010, + 0x8000010, 0x8001010, 0x80010, 0x81010, 0x8080010, 0x8081010 + ]; + const pc2bytes13 = [0, 0x4, 0x100, 0x104, 0, 0x4, 0x100, 0x104, 0x1, 0x5, 0x101, 0x105, 0x1, 0x5, 0x101, 0x105]; + + //how many iterations (1 for des, 3 for triple des) + const iterations = key.length > 8 ? 3 : 1; //changed by Paul 16/6/2007 to use Triple DES for 9+ byte keys + //stores the return keys + const keys = new Array(32 * iterations); + //now define the left shifts which need to be done + const shifts = [0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0]; + //other variables + let lefttemp; + let righttemp; + let m = 0; + let n = 0; + let temp; + + for (let j = 0; j < iterations; j++) { //either 1 or 3 iterations + let left = (key[m++] << 24) | (key[m++] << 16) | (key[m++] << 8) | key[m++]; + let right = (key[m++] << 24) | (key[m++] << 16) | (key[m++] << 8) | key[m++]; + + temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; + right ^= temp; + left ^= (temp << 4); + temp = ((right >>> -16) ^ left) & 0x0000ffff; + left ^= temp; + right ^= (temp << -16); + temp = ((left >>> 2) ^ right) & 0x33333333; + right ^= temp; + left ^= (temp << 2); + temp = ((right >>> -16) ^ left) & 0x0000ffff; + left ^= temp; + right ^= (temp << -16); + temp = ((left >>> 1) ^ right) & 0x55555555; + right ^= temp; + left ^= (temp << 1); + temp = ((right >>> 8) ^ left) & 0x00ff00ff; + left ^= temp; + right ^= (temp << 8); + temp = ((left >>> 1) ^ right) & 0x55555555; + right ^= temp; + left ^= (temp << 1); + + //the right side needs to be shifted and to get the last four bits of the left side + temp = (left << 8) | ((right >>> 20) & 0x000000f0); + //left needs to be put upside down + left = (right << 24) | ((right << 8) & 0xff0000) | ((right >>> 8) & 0xff00) | ((right >>> 24) & 0xf0); + right = temp; + + //now go through and perform these shifts on the left and right keys + for (let i = 0; i < shifts.length; i++) { + //shift the keys either one or two bits to the left + if (shifts[i]) { + left = (left << 2) | (left >>> 26); + right = (right << 2) | (right >>> 26); + } else { + left = (left << 1) | (left >>> 27); + right = (right << 1) | (right >>> 27); + } + left &= -0xf; + right &= -0xf; + + //now apply PC-2, in such a way that E is easier when encrypting or decrypting + //this conversion will look like PC-2 except only the last 6 bits of each byte are used + //rather than 48 consecutive bits and the order of lines will be according to + //how the S selection functions will be applied: S2, S4, S6, S8, S1, S3, S5, S7 + lefttemp = pc2bytes0[left >>> 28] | pc2bytes1[(left >>> 24) & 0xf] | pc2bytes2[(left >>> 20) & 0xf] | pc2bytes3[( + left >>> 16) & 0xf] | pc2bytes4[(left >>> 12) & 0xf] | pc2bytes5[(left >>> 8) & 0xf] | pc2bytes6[(left >>> 4) & + 0xf]; + righttemp = pc2bytes7[right >>> 28] | pc2bytes8[(right >>> 24) & 0xf] | pc2bytes9[(right >>> 20) & 0xf] | + pc2bytes10[(right >>> 16) & 0xf] | pc2bytes11[(right >>> 12) & 0xf] | pc2bytes12[(right >>> 8) & 0xf] | + pc2bytes13[(right >>> 4) & 0xf]; + temp = ((righttemp >>> 16) ^ lefttemp) & 0x0000ffff; + keys[n++] = lefttemp ^ temp; + keys[n++] = righttemp ^ (temp << 16); + } + } //for each iterations + //return the keys we've created + return keys; + } //end of desCreateKeys + + + function desAddPadding(message, padding) { + const padLength = 8 - (message.length % 8); + + let pad; + if (padding === 2 && (padLength < 8)) { //pad the message with spaces + pad = ' '.charCodeAt(0); + } else if (padding === 1) { //PKCS7 padding + pad = padLength; + } else if (!padding && (padLength < 8)) { //pad the message out with null bytes + pad = 0; + } else if (padLength === 8) { + return message; + } else { + throw new Error('des: invalid padding'); + } + + const paddedMessage = new Uint8Array(message.length + padLength); + for (let i = 0; i < message.length; i++) { + paddedMessage[i] = message[i]; + } + for (let j = 0; j < padLength; j++) { + paddedMessage[message.length + j] = pad; + } + + return paddedMessage; + } + + function desRemovePadding(message, padding) { + let padLength = null; + let pad; + if (padding === 2) { // space padded + pad = ' '.charCodeAt(0); + } else if (padding === 1) { // PKCS7 + padLength = message[message.length - 1]; + } else if (!padding) { // null padding + pad = 0; + } else { + throw new Error('des: invalid padding'); + } + + if (!padLength) { + padLength = 1; + while (message[message.length - padLength] === pad) { + padLength++; + } + padLength--; + } + + return message.subarray(0, message.length - padLength); + } + + // added by Recurity Labs + + function TripleDES(key) { + this.key = []; + + for (let i = 0; i < 3; i++) { + this.key.push(new Uint8Array(key.subarray(i * 8, (i * 8) + 8))); + } + + this.encrypt = function(block) { + return des( + desCreateKeys(this.key[2]), + des( + desCreateKeys(this.key[1]), + des( + desCreateKeys(this.key[0]), + block, true, 0, null, null + ), + false, 0, null, null + ), true, 0, null, null + ); + }; + } + + TripleDES.keySize = TripleDES.prototype.keySize = 24; + TripleDES.blockSize = TripleDES.prototype.blockSize = 8; + + // This is "original" DES + + function DES(key) { + this.key = key; + + this.encrypt = function(block, padding) { + const keys = desCreateKeys(this.key); + return des(keys, block, true, 0, null, padding); + }; + + this.decrypt = function(block, padding) { + const keys = desCreateKeys(this.key); + return des(keys, block, false, 0, null, padding); + }; + } + + // Use of this source code is governed by a BSD-style + // license that can be found in the LICENSE file. + + // Copyright 2010 pjacobs@xeekr.com . All rights reserved. + + // Modified by Recurity Labs GmbH + + // fixed/modified by Herbert Hanewinkel, www.haneWIN.de + // check www.haneWIN.de for the latest version + + // cast5.js is a Javascript implementation of CAST-128, as defined in RFC 2144. + // CAST-128 is a common OpenPGP cipher. + + + // CAST5 constructor + + function OpenPGPSymEncCAST5() { + this.BlockSize = 8; + this.KeySize = 16; + + this.setKey = function(key) { + this.masking = new Array(16); + this.rotate = new Array(16); + + this.reset(); + + if (key.length === this.KeySize) { + this.keySchedule(key); + } else { + throw new Error('CAST-128: keys must be 16 bytes'); + } + return true; + }; + + this.reset = function() { + for (let i = 0; i < 16; i++) { + this.masking[i] = 0; + this.rotate[i] = 0; + } + }; + + this.getBlockSize = function() { + return this.BlockSize; + }; + + this.encrypt = function(src) { + const dst = new Array(src.length); + + for (let i = 0; i < src.length; i += 8) { + let l = (src[i] << 24) | (src[i + 1] << 16) | (src[i + 2] << 8) | src[i + 3]; + let r = (src[i + 4] << 24) | (src[i + 5] << 16) | (src[i + 6] << 8) | src[i + 7]; + let t; + + t = r; + r = l ^ f1(r, this.masking[0], this.rotate[0]); + l = t; + t = r; + r = l ^ f2(r, this.masking[1], this.rotate[1]); + l = t; + t = r; + r = l ^ f3(r, this.masking[2], this.rotate[2]); + l = t; + t = r; + r = l ^ f1(r, this.masking[3], this.rotate[3]); + l = t; + + t = r; + r = l ^ f2(r, this.masking[4], this.rotate[4]); + l = t; + t = r; + r = l ^ f3(r, this.masking[5], this.rotate[5]); + l = t; + t = r; + r = l ^ f1(r, this.masking[6], this.rotate[6]); + l = t; + t = r; + r = l ^ f2(r, this.masking[7], this.rotate[7]); + l = t; + + t = r; + r = l ^ f3(r, this.masking[8], this.rotate[8]); + l = t; + t = r; + r = l ^ f1(r, this.masking[9], this.rotate[9]); + l = t; + t = r; + r = l ^ f2(r, this.masking[10], this.rotate[10]); + l = t; + t = r; + r = l ^ f3(r, this.masking[11], this.rotate[11]); + l = t; + + t = r; + r = l ^ f1(r, this.masking[12], this.rotate[12]); + l = t; + t = r; + r = l ^ f2(r, this.masking[13], this.rotate[13]); + l = t; + t = r; + r = l ^ f3(r, this.masking[14], this.rotate[14]); + l = t; + t = r; + r = l ^ f1(r, this.masking[15], this.rotate[15]); + l = t; + + dst[i] = (r >>> 24) & 255; + dst[i + 1] = (r >>> 16) & 255; + dst[i + 2] = (r >>> 8) & 255; + dst[i + 3] = r & 255; + dst[i + 4] = (l >>> 24) & 255; + dst[i + 5] = (l >>> 16) & 255; + dst[i + 6] = (l >>> 8) & 255; + dst[i + 7] = l & 255; + } + + return dst; + }; + + this.decrypt = function(src) { + const dst = new Array(src.length); + + for (let i = 0; i < src.length; i += 8) { + let l = (src[i] << 24) | (src[i + 1] << 16) | (src[i + 2] << 8) | src[i + 3]; + let r = (src[i + 4] << 24) | (src[i + 5] << 16) | (src[i + 6] << 8) | src[i + 7]; + let t; + + t = r; + r = l ^ f1(r, this.masking[15], this.rotate[15]); + l = t; + t = r; + r = l ^ f3(r, this.masking[14], this.rotate[14]); + l = t; + t = r; + r = l ^ f2(r, this.masking[13], this.rotate[13]); + l = t; + t = r; + r = l ^ f1(r, this.masking[12], this.rotate[12]); + l = t; + + t = r; + r = l ^ f3(r, this.masking[11], this.rotate[11]); + l = t; + t = r; + r = l ^ f2(r, this.masking[10], this.rotate[10]); + l = t; + t = r; + r = l ^ f1(r, this.masking[9], this.rotate[9]); + l = t; + t = r; + r = l ^ f3(r, this.masking[8], this.rotate[8]); + l = t; + + t = r; + r = l ^ f2(r, this.masking[7], this.rotate[7]); + l = t; + t = r; + r = l ^ f1(r, this.masking[6], this.rotate[6]); + l = t; + t = r; + r = l ^ f3(r, this.masking[5], this.rotate[5]); + l = t; + t = r; + r = l ^ f2(r, this.masking[4], this.rotate[4]); + l = t; + + t = r; + r = l ^ f1(r, this.masking[3], this.rotate[3]); + l = t; + t = r; + r = l ^ f3(r, this.masking[2], this.rotate[2]); + l = t; + t = r; + r = l ^ f2(r, this.masking[1], this.rotate[1]); + l = t; + t = r; + r = l ^ f1(r, this.masking[0], this.rotate[0]); + l = t; + + dst[i] = (r >>> 24) & 255; + dst[i + 1] = (r >>> 16) & 255; + dst[i + 2] = (r >>> 8) & 255; + dst[i + 3] = r & 255; + dst[i + 4] = (l >>> 24) & 255; + dst[i + 5] = (l >> 16) & 255; + dst[i + 6] = (l >> 8) & 255; + dst[i + 7] = l & 255; + } + + return dst; + }; + const scheduleA = new Array(4); + + scheduleA[0] = new Array(4); + scheduleA[0][0] = [4, 0, 0xd, 0xf, 0xc, 0xe, 0x8]; + scheduleA[0][1] = [5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa]; + scheduleA[0][2] = [6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9]; + scheduleA[0][3] = [7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb]; + + scheduleA[1] = new Array(4); + scheduleA[1][0] = [0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0]; + scheduleA[1][1] = [1, 4, 0, 2, 1, 3, 16 + 2]; + scheduleA[1][2] = [2, 5, 7, 6, 5, 4, 16 + 1]; + scheduleA[1][3] = [3, 7, 0xa, 9, 0xb, 8, 16 + 3]; + + scheduleA[2] = new Array(4); + scheduleA[2][0] = [4, 0, 0xd, 0xf, 0xc, 0xe, 8]; + scheduleA[2][1] = [5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa]; + scheduleA[2][2] = [6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9]; + scheduleA[2][3] = [7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb]; + + + scheduleA[3] = new Array(4); + scheduleA[3][0] = [0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0]; + scheduleA[3][1] = [1, 4, 0, 2, 1, 3, 16 + 2]; + scheduleA[3][2] = [2, 5, 7, 6, 5, 4, 16 + 1]; + scheduleA[3][3] = [3, 7, 0xa, 9, 0xb, 8, 16 + 3]; + + const scheduleB = new Array(4); + + scheduleB[0] = new Array(4); + scheduleB[0][0] = [16 + 8, 16 + 9, 16 + 7, 16 + 6, 16 + 2]; + scheduleB[0][1] = [16 + 0xa, 16 + 0xb, 16 + 5, 16 + 4, 16 + 6]; + scheduleB[0][2] = [16 + 0xc, 16 + 0xd, 16 + 3, 16 + 2, 16 + 9]; + scheduleB[0][3] = [16 + 0xe, 16 + 0xf, 16 + 1, 16 + 0, 16 + 0xc]; + + scheduleB[1] = new Array(4); + scheduleB[1][0] = [3, 2, 0xc, 0xd, 8]; + scheduleB[1][1] = [1, 0, 0xe, 0xf, 0xd]; + scheduleB[1][2] = [7, 6, 8, 9, 3]; + scheduleB[1][3] = [5, 4, 0xa, 0xb, 7]; + + + scheduleB[2] = new Array(4); + scheduleB[2][0] = [16 + 3, 16 + 2, 16 + 0xc, 16 + 0xd, 16 + 9]; + scheduleB[2][1] = [16 + 1, 16 + 0, 16 + 0xe, 16 + 0xf, 16 + 0xc]; + scheduleB[2][2] = [16 + 7, 16 + 6, 16 + 8, 16 + 9, 16 + 2]; + scheduleB[2][3] = [16 + 5, 16 + 4, 16 + 0xa, 16 + 0xb, 16 + 6]; + + + scheduleB[3] = new Array(4); + scheduleB[3][0] = [8, 9, 7, 6, 3]; + scheduleB[3][1] = [0xa, 0xb, 5, 4, 7]; + scheduleB[3][2] = [0xc, 0xd, 3, 2, 8]; + scheduleB[3][3] = [0xe, 0xf, 1, 0, 0xd]; + + // changed 'in' to 'inn' (in javascript 'in' is a reserved word) + this.keySchedule = function(inn) { + const t = new Array(8); + const k = new Array(32); + + let j; + + for (let i = 0; i < 4; i++) { + j = i * 4; + t[i] = (inn[j] << 24) | (inn[j + 1] << 16) | (inn[j + 2] << 8) | inn[j + 3]; + } + + const x = [6, 7, 4, 5]; + let ki = 0; + let w; + + for (let half = 0; half < 2; half++) { + for (let round = 0; round < 4; round++) { + for (j = 0; j < 4; j++) { + const a = scheduleA[round][j]; + w = t[a[1]]; + + w ^= sBox[4][(t[a[2] >>> 2] >>> (24 - 8 * (a[2] & 3))) & 0xff]; + w ^= sBox[5][(t[a[3] >>> 2] >>> (24 - 8 * (a[3] & 3))) & 0xff]; + w ^= sBox[6][(t[a[4] >>> 2] >>> (24 - 8 * (a[4] & 3))) & 0xff]; + w ^= sBox[7][(t[a[5] >>> 2] >>> (24 - 8 * (a[5] & 3))) & 0xff]; + w ^= sBox[x[j]][(t[a[6] >>> 2] >>> (24 - 8 * (a[6] & 3))) & 0xff]; + t[a[0]] = w; + } + + for (j = 0; j < 4; j++) { + const b = scheduleB[round][j]; + w = sBox[4][(t[b[0] >>> 2] >>> (24 - 8 * (b[0] & 3))) & 0xff]; + + w ^= sBox[5][(t[b[1] >>> 2] >>> (24 - 8 * (b[1] & 3))) & 0xff]; + w ^= sBox[6][(t[b[2] >>> 2] >>> (24 - 8 * (b[2] & 3))) & 0xff]; + w ^= sBox[7][(t[b[3] >>> 2] >>> (24 - 8 * (b[3] & 3))) & 0xff]; + w ^= sBox[4 + j][(t[b[4] >>> 2] >>> (24 - 8 * (b[4] & 3))) & 0xff]; + k[ki] = w; + ki++; + } + } + } + + for (let i = 0; i < 16; i++) { + this.masking[i] = k[i]; + this.rotate[i] = k[16 + i] & 0x1f; + } + }; + + // These are the three 'f' functions. See RFC 2144, section 2.2. + + function f1(d, m, r) { + const t = m + d; + const I = (t << r) | (t >>> (32 - r)); + return ((sBox[0][I >>> 24] ^ sBox[1][(I >>> 16) & 255]) - sBox[2][(I >>> 8) & 255]) + sBox[3][I & 255]; + } + + function f2(d, m, r) { + const t = m ^ d; + const I = (t << r) | (t >>> (32 - r)); + return ((sBox[0][I >>> 24] - sBox[1][(I >>> 16) & 255]) + sBox[2][(I >>> 8) & 255]) ^ sBox[3][I & 255]; + } + + function f3(d, m, r) { + const t = m - d; + const I = (t << r) | (t >>> (32 - r)); + return ((sBox[0][I >>> 24] + sBox[1][(I >>> 16) & 255]) ^ sBox[2][(I >>> 8) & 255]) - sBox[3][I & 255]; + } + + const sBox = new Array(8); + sBox[0] = [ + 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949, + 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, + 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, + 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0, + 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, + 0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935, + 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d, + 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, + 0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe, + 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3, + 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, + 0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291, + 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779, + 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, + 0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, + 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d, + 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, + 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, + 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c, + 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, + 0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d, + 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96, + 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, + 0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, + 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, + 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, + 0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, + 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872, + 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, + 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, + 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9, + 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf + ]; + + sBox[1] = [ + 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651, + 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, + 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, + 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806, + 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, + 0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359, + 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b, + 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, + 0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34, + 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb, + 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, + 0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860, + 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b, + 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, + 0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, + 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, + 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, + 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, + 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f, + 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, + 0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6, + 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58, + 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, + 0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, + 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6, + 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, + 0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6, + 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f, + 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, + 0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, + 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9, + 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1 + ]; + + sBox[2] = [ + 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90, + 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, + 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, + 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240, + 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, + 0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, + 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71, + 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, + 0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, + 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15, + 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, + 0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176, + 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148, + 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, + 0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, + 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e, + 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, + 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, + 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a, + 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, + 0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, + 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5, + 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, + 0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536, + 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, + 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, + 0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69, + 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, + 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, + 0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, + 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a, + 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783 + ]; + + sBox[3] = [ + 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1, + 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, + 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, + 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121, + 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, + 0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, + 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb, + 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, + 0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d, + 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6, + 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, + 0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003, + 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, + 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, + 0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, + 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a, + 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, + 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, + 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26, + 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, + 0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7, + 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417, + 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, + 0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2, + 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, + 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, + 0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, + 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, + 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, + 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, + 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282, + 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2 + ]; + + sBox[4] = [ + 0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f, + 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, + 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, + 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02, + 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, + 0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7, + 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9, + 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, + 0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774, + 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655, + 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, + 0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910, + 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1, + 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, + 0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, + 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f, + 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, + 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, + 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3, + 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, + 0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4, + 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2, + 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, + 0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5, + 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, + 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, + 0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801, + 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, + 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, + 0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, + 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8, + 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4 + ]; + + sBox[5] = [ + 0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac, + 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, + 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, + 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98, + 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, + 0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3, + 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd, + 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, + 0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9, + 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54, + 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, + 0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc, + 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf, + 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, + 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, + 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289, + 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, + 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, + 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b, + 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, + 0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13, + 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976, + 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, + 0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891, + 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da, + 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, + 0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084, + 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25, + 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, + 0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, + 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd, + 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f + ]; + + sBox[6] = [ + 0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f, + 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, + 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, + 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19, + 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, + 0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516, + 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88, + 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, + 0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756, + 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, + 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, + 0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688, + 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28, + 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, + 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, + 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, + 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, + 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, + 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566, + 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, + 0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962, + 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e, + 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, + 0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c, + 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, + 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, + 0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be, + 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767, + 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, + 0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, + 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c, + 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3 + ]; + + sBox[7] = [ + 0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5, + 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, + 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, + 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d, + 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, + 0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862, + 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc, + 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, + 0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e, + 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039, + 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, + 0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42, + 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5, + 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, + 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, + 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c, + 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, + 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, + 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70, + 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, + 0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c, + 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3, + 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, + 0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101, + 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f, + 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, + 0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a, + 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c, + 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, + 0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, + 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82, + 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e + ]; + } + + function CAST5(key) { + this.cast5 = new OpenPGPSymEncCAST5(); + this.cast5.setKey(key); + + this.encrypt = function(block) { + return this.cast5.encrypt(block); + }; + } + + CAST5.blockSize = CAST5.prototype.blockSize = 8; + CAST5.keySize = CAST5.prototype.keySize = 16; + + /* eslint-disable no-mixed-operators, no-fallthrough */ + + + /* Modified by Recurity Labs GmbH + * + * Cipher.js + * A block-cipher algorithm implementation on JavaScript + * See Cipher.readme.txt for further information. + * + * Copyright(c) 2009 Atsushi Oka [ http://oka.nu/ ] + * This script file is distributed under the LGPL + * + * ACKNOWLEDGMENT + * + * The main subroutines are written by Michiel van Everdingen. + * + * Michiel van Everdingen + * http://home.versatel.nl/MAvanEverdingen/index.html + * + * All rights for these routines are reserved to Michiel van Everdingen. + * + */ + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //Math + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + const MAXINT = 0xFFFFFFFF; + + function rotw(w, n) { + return (w << n | w >>> (32 - n)) & MAXINT; + } + + function getW(a, i) { + return a[i] | a[i + 1] << 8 | a[i + 2] << 16 | a[i + 3] << 24; + } + + function setW(a, i, w) { + a.splice(i, 4, w & 0xFF, (w >>> 8) & 0xFF, (w >>> 16) & 0xFF, (w >>> 24) & 0xFF); + } + + function getB(x, n) { + return (x >>> (n * 8)) & 0xFF; + } + + // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Twofish + // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + function createTwofish() { + // + let keyBytes = null; + let dataBytes = null; + let dataOffset = -1; + // var dataLength = -1; + // var idx2 = -1; + // + + let tfsKey = []; + let tfsM = [ + [], + [], + [], + [] + ]; + + function tfsInit(key) { + keyBytes = key; + let i; + let a; + let b; + let c; + let d; + const meKey = []; + const moKey = []; + const inKey = []; + let kLen; + const sKey = []; + let f01; + let f5b; + let fef; + + const q0 = [ + [8, 1, 7, 13, 6, 15, 3, 2, 0, 11, 5, 9, 14, 12, 10, 4], + [2, 8, 11, 13, 15, 7, 6, 14, 3, 1, 9, 4, 0, 10, 12, 5] + ]; + const q1 = [ + [14, 12, 11, 8, 1, 2, 3, 5, 15, 4, 10, 6, 7, 0, 9, 13], + [1, 14, 2, 11, 4, 12, 3, 7, 6, 13, 10, 5, 15, 9, 0, 8] + ]; + const q2 = [ + [11, 10, 5, 14, 6, 13, 9, 0, 12, 8, 15, 3, 2, 4, 7, 1], + [4, 12, 7, 5, 1, 6, 9, 10, 0, 14, 13, 8, 2, 11, 3, 15] + ]; + const q3 = [ + [13, 7, 15, 4, 1, 2, 6, 14, 9, 11, 3, 0, 8, 5, 12, 10], + [11, 9, 5, 1, 12, 3, 13, 14, 6, 4, 7, 15, 2, 0, 8, 10] + ]; + const ror4 = [0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15]; + const ashx = [0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 5, 14, 7]; + const q = [ + [], + [] + ]; + const m = [ + [], + [], + [], + [] + ]; + + function ffm5b(x) { + return x ^ (x >> 2) ^ [0, 90, 180, 238][x & 3]; + } + + function ffmEf(x) { + return x ^ (x >> 1) ^ (x >> 2) ^ [0, 238, 180, 90][x & 3]; + } + + function mdsRem(p, q) { + let i; + let t; + let u; + for (i = 0; i < 8; i++) { + t = q >>> 24; + q = ((q << 8) & MAXINT) | p >>> 24; + p = (p << 8) & MAXINT; + u = t << 1; + if (t & 128) { + u ^= 333; + } + q ^= t ^ (u << 16); + u ^= t >>> 1; + if (t & 1) { + u ^= 166; + } + q ^= u << 24 | u << 8; + } + return q; + } + + function qp(n, x) { + const a = x >> 4; + const b = x & 15; + const c = q0[n][a ^ b]; + const d = q1[n][ror4[b] ^ ashx[a]]; + return q3[n][ror4[d] ^ ashx[c]] << 4 | q2[n][c ^ d]; + } + + function hFun(x, key) { + let a = getB(x, 0); + let b = getB(x, 1); + let c = getB(x, 2); + let d = getB(x, 3); + switch (kLen) { + case 4: + a = q[1][a] ^ getB(key[3], 0); + b = q[0][b] ^ getB(key[3], 1); + c = q[0][c] ^ getB(key[3], 2); + d = q[1][d] ^ getB(key[3], 3); + case 3: + a = q[1][a] ^ getB(key[2], 0); + b = q[1][b] ^ getB(key[2], 1); + c = q[0][c] ^ getB(key[2], 2); + d = q[0][d] ^ getB(key[2], 3); + case 2: + a = q[0][q[0][a] ^ getB(key[1], 0)] ^ getB(key[0], 0); + b = q[0][q[1][b] ^ getB(key[1], 1)] ^ getB(key[0], 1); + c = q[1][q[0][c] ^ getB(key[1], 2)] ^ getB(key[0], 2); + d = q[1][q[1][d] ^ getB(key[1], 3)] ^ getB(key[0], 3); + } + return m[0][a] ^ m[1][b] ^ m[2][c] ^ m[3][d]; + } + + keyBytes = keyBytes.slice(0, 32); + i = keyBytes.length; + while (i !== 16 && i !== 24 && i !== 32) { + keyBytes[i++] = 0; + } + + for (i = 0; i < keyBytes.length; i += 4) { + inKey[i >> 2] = getW(keyBytes, i); + } + for (i = 0; i < 256; i++) { + q[0][i] = qp(0, i); + q[1][i] = qp(1, i); + } + for (i = 0; i < 256; i++) { + f01 = q[1][i]; + f5b = ffm5b(f01); + fef = ffmEf(f01); + m[0][i] = f01 + (f5b << 8) + (fef << 16) + (fef << 24); + m[2][i] = f5b + (fef << 8) + (f01 << 16) + (fef << 24); + f01 = q[0][i]; + f5b = ffm5b(f01); + fef = ffmEf(f01); + m[1][i] = fef + (fef << 8) + (f5b << 16) + (f01 << 24); + m[3][i] = f5b + (f01 << 8) + (fef << 16) + (f5b << 24); + } + + kLen = inKey.length / 2; + for (i = 0; i < kLen; i++) { + a = inKey[i + i]; + meKey[i] = a; + b = inKey[i + i + 1]; + moKey[i] = b; + sKey[kLen - i - 1] = mdsRem(a, b); + } + for (i = 0; i < 40; i += 2) { + a = 0x1010101 * i; + b = a + 0x1010101; + a = hFun(a, meKey); + b = rotw(hFun(b, moKey), 8); + tfsKey[i] = (a + b) & MAXINT; + tfsKey[i + 1] = rotw(a + 2 * b, 9); + } + for (i = 0; i < 256; i++) { + a = b = c = d = i; + switch (kLen) { + case 4: + a = q[1][a] ^ getB(sKey[3], 0); + b = q[0][b] ^ getB(sKey[3], 1); + c = q[0][c] ^ getB(sKey[3], 2); + d = q[1][d] ^ getB(sKey[3], 3); + case 3: + a = q[1][a] ^ getB(sKey[2], 0); + b = q[1][b] ^ getB(sKey[2], 1); + c = q[0][c] ^ getB(sKey[2], 2); + d = q[0][d] ^ getB(sKey[2], 3); + case 2: + tfsM[0][i] = m[0][q[0][q[0][a] ^ getB(sKey[1], 0)] ^ getB(sKey[0], 0)]; + tfsM[1][i] = m[1][q[0][q[1][b] ^ getB(sKey[1], 1)] ^ getB(sKey[0], 1)]; + tfsM[2][i] = m[2][q[1][q[0][c] ^ getB(sKey[1], 2)] ^ getB(sKey[0], 2)]; + tfsM[3][i] = m[3][q[1][q[1][d] ^ getB(sKey[1], 3)] ^ getB(sKey[0], 3)]; + } + } + } + + function tfsG0(x) { + return tfsM[0][getB(x, 0)] ^ tfsM[1][getB(x, 1)] ^ tfsM[2][getB(x, 2)] ^ tfsM[3][getB(x, 3)]; + } + + function tfsG1(x) { + return tfsM[0][getB(x, 3)] ^ tfsM[1][getB(x, 0)] ^ tfsM[2][getB(x, 1)] ^ tfsM[3][getB(x, 2)]; + } + + function tfsFrnd(r, blk) { + let a = tfsG0(blk[0]); + let b = tfsG1(blk[1]); + blk[2] = rotw(blk[2] ^ (a + b + tfsKey[4 * r + 8]) & MAXINT, 31); + blk[3] = rotw(blk[3], 1) ^ (a + 2 * b + tfsKey[4 * r + 9]) & MAXINT; + a = tfsG0(blk[2]); + b = tfsG1(blk[3]); + blk[0] = rotw(blk[0] ^ (a + b + tfsKey[4 * r + 10]) & MAXINT, 31); + blk[1] = rotw(blk[1], 1) ^ (a + 2 * b + tfsKey[4 * r + 11]) & MAXINT; + } + + function tfsIrnd(i, blk) { + let a = tfsG0(blk[0]); + let b = tfsG1(blk[1]); + blk[2] = rotw(blk[2], 1) ^ (a + b + tfsKey[4 * i + 10]) & MAXINT; + blk[3] = rotw(blk[3] ^ (a + 2 * b + tfsKey[4 * i + 11]) & MAXINT, 31); + a = tfsG0(blk[2]); + b = tfsG1(blk[3]); + blk[0] = rotw(blk[0], 1) ^ (a + b + tfsKey[4 * i + 8]) & MAXINT; + blk[1] = rotw(blk[1] ^ (a + 2 * b + tfsKey[4 * i + 9]) & MAXINT, 31); + } + + function tfsClose() { + tfsKey = []; + tfsM = [ + [], + [], + [], + [] + ]; + } + + function tfsEncrypt(data, offset) { + dataBytes = data; + dataOffset = offset; + const blk = [getW(dataBytes, dataOffset) ^ tfsKey[0], + getW(dataBytes, dataOffset + 4) ^ tfsKey[1], + getW(dataBytes, dataOffset + 8) ^ tfsKey[2], + getW(dataBytes, dataOffset + 12) ^ tfsKey[3]]; + for (let j = 0; j < 8; j++) { + tfsFrnd(j, blk); + } + setW(dataBytes, dataOffset, blk[2] ^ tfsKey[4]); + setW(dataBytes, dataOffset + 4, blk[3] ^ tfsKey[5]); + setW(dataBytes, dataOffset + 8, blk[0] ^ tfsKey[6]); + setW(dataBytes, dataOffset + 12, blk[1] ^ tfsKey[7]); + dataOffset += 16; + return dataBytes; + } + + function tfsDecrypt(data, offset) { + dataBytes = data; + dataOffset = offset; + const blk = [getW(dataBytes, dataOffset) ^ tfsKey[4], + getW(dataBytes, dataOffset + 4) ^ tfsKey[5], + getW(dataBytes, dataOffset + 8) ^ tfsKey[6], + getW(dataBytes, dataOffset + 12) ^ tfsKey[7]]; + for (let j = 7; j >= 0; j--) { + tfsIrnd(j, blk); + } + setW(dataBytes, dataOffset, blk[2] ^ tfsKey[0]); + setW(dataBytes, dataOffset + 4, blk[3] ^ tfsKey[1]); + setW(dataBytes, dataOffset + 8, blk[0] ^ tfsKey[2]); + setW(dataBytes, dataOffset + 12, blk[1] ^ tfsKey[3]); + dataOffset += 16; + } + + // added by Recurity Labs + + function tfsFinal() { + return dataBytes; + } + + return { + name: 'twofish', + blocksize: 128 / 8, + open: tfsInit, + close: tfsClose, + encrypt: tfsEncrypt, + decrypt: tfsDecrypt, + // added by Recurity Labs + finalize: tfsFinal + }; + } + + // added by Recurity Labs + + function TF(key) { + this.tf = createTwofish(); + this.tf.open(Array.from(key), 0); + + this.encrypt = function(block) { + return this.tf.encrypt(Array.from(block), 0); + }; + } + + TF.keySize = TF.prototype.keySize = 32; + TF.blockSize = TF.prototype.blockSize = 16; + + /* Modified by Recurity Labs GmbH + * + * Originally written by nklein software (nklein.com) + */ + + /* + * Javascript implementation based on Bruce Schneier's reference implementation. + * + * + * The constructor doesn't do much of anything. It's just here + * so we can start defining properties and methods and such. + */ + function Blowfish() {} + + /* + * Declare the block size so that protocols know what size + * Initialization Vector (IV) they will need. + */ + Blowfish.prototype.BLOCKSIZE = 8; + + /* + * These are the default SBOXES. + */ + Blowfish.prototype.SBOXES = [ + [ + 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, + 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, + 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658, + 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, + 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, + 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, + 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6, + 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, + 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, + 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, + 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, + 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, + 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, + 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, + 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, + 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, + 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, + 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, + 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, + 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, + 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, + 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, + 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, + 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, + 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, + 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, + 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8, + 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, + 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, + 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, + 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, + 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, + 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, + 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, + 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, + 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, + 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, + 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, + 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, + 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, + 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, + 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, + 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a + ], + [ + 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, + 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, + 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, + 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, + 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, + 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, + 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, + 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, + 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, + 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, + 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, + 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, + 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, + 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, + 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, + 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, + 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, + 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, + 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, + 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, + 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, + 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, + 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, + 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, + 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, + 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, + 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, + 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, + 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, + 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, + 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, + 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, + 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, + 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, + 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, + 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, + 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, + 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, + 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, + 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, + 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, + 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, + 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7 + ], + [ + 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, + 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, + 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, + 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, + 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, + 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, + 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, + 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, + 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, + 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, + 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, + 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, + 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, + 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, + 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, + 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, + 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, + 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, + 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74, + 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, + 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, + 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, + 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, + 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, + 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, + 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, + 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, + 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, + 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, + 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, + 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, + 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, + 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, + 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, + 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, + 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, + 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, + 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, + 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, + 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, + 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, + 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, + 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0 + ], + [ + 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, + 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, + 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, + 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, + 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, + 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, + 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, + 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, + 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, + 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, + 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, + 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, + 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, + 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, + 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5, + 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, + 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, + 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, + 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd, + 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, + 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, + 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, + 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc, + 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, + 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, + 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, + 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, + 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, + 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, + 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, + 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, + 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, + 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, + 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, + 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623, + 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, + 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, + 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, + 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3, + 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, + 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, + 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, + 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 + ] + ]; + + //* + //* This is the default PARRAY + //* + Blowfish.prototype.PARRAY = [ + 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, + 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, + 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b + ]; + + //* + //* This is the number of rounds the cipher will go + //* + Blowfish.prototype.NN = 16; + + //* + //* This function is needed to get rid of problems + //* with the high-bit getting set. If we don't do + //* this, then sometimes ( aa & 0x00FFFFFFFF ) is not + //* equal to ( bb & 0x00FFFFFFFF ) even when they + //* agree bit-for-bit for the first 32 bits. + //* + Blowfish.prototype._clean = function(xx) { + if (xx < 0) { + const yy = xx & 0x7FFFFFFF; + xx = yy + 0x80000000; + } + return xx; + }; + + //* + //* This is the mixing function that uses the sboxes + //* + Blowfish.prototype._F = function(xx) { + let yy; + + const dd = xx & 0x00FF; + xx >>>= 8; + const cc = xx & 0x00FF; + xx >>>= 8; + const bb = xx & 0x00FF; + xx >>>= 8; + const aa = xx & 0x00FF; + + yy = this.sboxes[0][aa] + this.sboxes[1][bb]; + yy ^= this.sboxes[2][cc]; + yy += this.sboxes[3][dd]; + + return yy; + }; + + //* + //* This method takes an array with two values, left and right + //* and does NN rounds of Blowfish on them. + //* + Blowfish.prototype._encryptBlock = function(vals) { + let dataL = vals[0]; + let dataR = vals[1]; + + let ii; + + for (ii = 0; ii < this.NN; ++ii) { + dataL ^= this.parray[ii]; + dataR = this._F(dataL) ^ dataR; + + const tmp = dataL; + dataL = dataR; + dataR = tmp; + } + + dataL ^= this.parray[this.NN + 0]; + dataR ^= this.parray[this.NN + 1]; + + vals[0] = this._clean(dataR); + vals[1] = this._clean(dataL); + }; + + //* + //* This method takes a vector of numbers and turns them + //* into long words so that they can be processed by the + //* real algorithm. + //* + //* Maybe I should make the real algorithm above take a vector + //* instead. That will involve more looping, but it won't require + //* the F() method to deconstruct the vector. + //* + Blowfish.prototype.encryptBlock = function(vector) { + let ii; + const vals = [0, 0]; + const off = this.BLOCKSIZE / 2; + for (ii = 0; ii < this.BLOCKSIZE / 2; ++ii) { + vals[0] = (vals[0] << 8) | (vector[ii + 0] & 0x00FF); + vals[1] = (vals[1] << 8) | (vector[ii + off] & 0x00FF); + } + + this._encryptBlock(vals); + + const ret = []; + for (ii = 0; ii < this.BLOCKSIZE / 2; ++ii) { + ret[ii + 0] = ((vals[0] >>> (24 - 8 * (ii))) & 0x00FF); + ret[ii + off] = ((vals[1] >>> (24 - 8 * (ii))) & 0x00FF); + // vals[ 0 ] = ( vals[ 0 ] >>> 8 ); + // vals[ 1 ] = ( vals[ 1 ] >>> 8 ); + } + + return ret; + }; + + //* + //* This method takes an array with two values, left and right + //* and undoes NN rounds of Blowfish on them. + //* + Blowfish.prototype._decryptBlock = function(vals) { + let dataL = vals[0]; + let dataR = vals[1]; + + let ii; + + for (ii = this.NN + 1; ii > 1; --ii) { + dataL ^= this.parray[ii]; + dataR = this._F(dataL) ^ dataR; + + const tmp = dataL; + dataL = dataR; + dataR = tmp; + } + + dataL ^= this.parray[1]; + dataR ^= this.parray[0]; + + vals[0] = this._clean(dataR); + vals[1] = this._clean(dataL); + }; + + //* + //* This method takes a key array and initializes the + //* sboxes and parray for this encryption. + //* + Blowfish.prototype.init = function(key) { + let ii; + let jj = 0; + + this.parray = []; + for (ii = 0; ii < this.NN + 2; ++ii) { + let data = 0x00000000; + for (let kk = 0; kk < 4; ++kk) { + data = (data << 8) | (key[jj] & 0x00FF); + if (++jj >= key.length) { + jj = 0; + } + } + this.parray[ii] = this.PARRAY[ii] ^ data; + } + + this.sboxes = []; + for (ii = 0; ii < 4; ++ii) { + this.sboxes[ii] = []; + for (jj = 0; jj < 256; ++jj) { + this.sboxes[ii][jj] = this.SBOXES[ii][jj]; + } + } + + const vals = [0x00000000, 0x00000000]; + + for (ii = 0; ii < this.NN + 2; ii += 2) { + this._encryptBlock(vals); + this.parray[ii + 0] = vals[0]; + this.parray[ii + 1] = vals[1]; + } + + for (ii = 0; ii < 4; ++ii) { + for (jj = 0; jj < 256; jj += 2) { + this._encryptBlock(vals); + this.sboxes[ii][jj + 0] = vals[0]; + this.sboxes[ii][jj + 1] = vals[1]; + } + } + }; + + // added by Recurity Labs + function BF(key) { + this.bf = new Blowfish(); + this.bf.init(key); + + this.encrypt = function(block) { + return this.bf.encryptBlock(block); + }; + } + + BF.keySize = BF.prototype.keySize = 16; + BF.blockSize = BF.prototype.blockSize = 8; + + /** + * @fileoverview Symmetric cryptography functions + * @module crypto/cipher + * @private + */ + + /** + * AES-128 encryption and decryption (ID 7) + * @function + * @param {String} key - 128-bit key + * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} + * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} + * @returns {Object} + */ + const aes128 = aes(128); + /** + * AES-128 Block Cipher (ID 8) + * @function + * @param {String} key - 192-bit key + * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} + * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} + * @returns {Object} + */ + const aes192 = aes(192); + /** + * AES-128 Block Cipher (ID 9) + * @function + * @param {String} key - 256-bit key + * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} + * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} + * @returns {Object} + */ + const aes256 = aes(256); + // Not in OpenPGP specifications + const des$1 = DES; + /** + * Triple DES Block Cipher (ID 2) + * @function + * @param {String} key - 192-bit key + * @see {@link https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-67r2.pdf|NIST SP 800-67} + * @returns {Object} + */ + const tripledes = TripleDES; + /** + * CAST-128 Block Cipher (ID 3) + * @function + * @param {String} key - 128-bit key + * @see {@link https://tools.ietf.org/html/rfc2144|The CAST-128 Encryption Algorithm} + * @returns {Object} + */ + const cast5 = CAST5; + /** + * Twofish Block Cipher (ID 10) + * @function + * @param {String} key - 256-bit key + * @see {@link https://tools.ietf.org/html/rfc4880#ref-TWOFISH|TWOFISH} + * @returns {Object} + */ + const twofish = TF; + /** + * Blowfish Block Cipher (ID 4) + * @function + * @param {String} key - 128-bit key + * @see {@link https://tools.ietf.org/html/rfc4880#ref-BLOWFISH|BLOWFISH} + * @returns {Object} + */ + const blowfish = BF; + /** + * Not implemented + * @function + * @throws {Error} + */ + const idea = function() { + throw new Error('IDEA symmetric-key algorithm not implemented'); + }; + + var cipher = /*#__PURE__*/Object.freeze({ + __proto__: null, + aes128: aes128, + aes192: aes192, + aes256: aes256, + des: des$1, + tripledes: tripledes, + cast5: cast5, + twofish: twofish, + blowfish: blowfish, + idea: idea + }); + + var sha1_asm = function ( stdlib, foreign, buffer ) { + "use asm"; + + // SHA256 state + var H0 = 0, H1 = 0, H2 = 0, H3 = 0, H4 = 0, + TOTAL0 = 0, TOTAL1 = 0; + + // HMAC state + var I0 = 0, I1 = 0, I2 = 0, I3 = 0, I4 = 0, + O0 = 0, O1 = 0, O2 = 0, O3 = 0, O4 = 0; + + // I/O buffer + var HEAP = new stdlib.Uint8Array(buffer); + + function _core ( w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15 ) { + w0 = w0|0; + w1 = w1|0; + w2 = w2|0; + w3 = w3|0; + w4 = w4|0; + w5 = w5|0; + w6 = w6|0; + w7 = w7|0; + w8 = w8|0; + w9 = w9|0; + w10 = w10|0; + w11 = w11|0; + w12 = w12|0; + w13 = w13|0; + w14 = w14|0; + w15 = w15|0; + + var a = 0, b = 0, c = 0, d = 0, e = 0, n = 0, t = 0, + w16 = 0, w17 = 0, w18 = 0, w19 = 0, + w20 = 0, w21 = 0, w22 = 0, w23 = 0, w24 = 0, w25 = 0, w26 = 0, w27 = 0, w28 = 0, w29 = 0, + w30 = 0, w31 = 0, w32 = 0, w33 = 0, w34 = 0, w35 = 0, w36 = 0, w37 = 0, w38 = 0, w39 = 0, + w40 = 0, w41 = 0, w42 = 0, w43 = 0, w44 = 0, w45 = 0, w46 = 0, w47 = 0, w48 = 0, w49 = 0, + w50 = 0, w51 = 0, w52 = 0, w53 = 0, w54 = 0, w55 = 0, w56 = 0, w57 = 0, w58 = 0, w59 = 0, + w60 = 0, w61 = 0, w62 = 0, w63 = 0, w64 = 0, w65 = 0, w66 = 0, w67 = 0, w68 = 0, w69 = 0, + w70 = 0, w71 = 0, w72 = 0, w73 = 0, w74 = 0, w75 = 0, w76 = 0, w77 = 0, w78 = 0, w79 = 0; + + a = H0; + b = H1; + c = H2; + d = H3; + e = H4; + + // 0 + t = ( w0 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 1 + t = ( w1 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 2 + t = ( w2 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 3 + t = ( w3 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 4 + t = ( w4 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 5 + t = ( w5 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 6 + t = ( w6 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 7 + t = ( w7 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 8 + t = ( w8 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 9 + t = ( w9 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 10 + t = ( w10 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 11 + t = ( w11 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 12 + t = ( w12 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 13 + t = ( w13 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 14 + t = ( w14 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 15 + t = ( w15 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 16 + n = w13 ^ w8 ^ w2 ^ w0; + w16 = (n << 1) | (n >>> 31); + t = (w16 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 17 + n = w14 ^ w9 ^ w3 ^ w1; + w17 = (n << 1) | (n >>> 31); + t = (w17 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 18 + n = w15 ^ w10 ^ w4 ^ w2; + w18 = (n << 1) | (n >>> 31); + t = (w18 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 19 + n = w16 ^ w11 ^ w5 ^ w3; + w19 = (n << 1) | (n >>> 31); + t = (w19 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 20 + n = w17 ^ w12 ^ w6 ^ w4; + w20 = (n << 1) | (n >>> 31); + t = (w20 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 21 + n = w18 ^ w13 ^ w7 ^ w5; + w21 = (n << 1) | (n >>> 31); + t = (w21 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 22 + n = w19 ^ w14 ^ w8 ^ w6; + w22 = (n << 1) | (n >>> 31); + t = (w22 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 23 + n = w20 ^ w15 ^ w9 ^ w7; + w23 = (n << 1) | (n >>> 31); + t = (w23 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 24 + n = w21 ^ w16 ^ w10 ^ w8; + w24 = (n << 1) | (n >>> 31); + t = (w24 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 25 + n = w22 ^ w17 ^ w11 ^ w9; + w25 = (n << 1) | (n >>> 31); + t = (w25 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 26 + n = w23 ^ w18 ^ w12 ^ w10; + w26 = (n << 1) | (n >>> 31); + t = (w26 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 27 + n = w24 ^ w19 ^ w13 ^ w11; + w27 = (n << 1) | (n >>> 31); + t = (w27 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 28 + n = w25 ^ w20 ^ w14 ^ w12; + w28 = (n << 1) | (n >>> 31); + t = (w28 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 29 + n = w26 ^ w21 ^ w15 ^ w13; + w29 = (n << 1) | (n >>> 31); + t = (w29 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 30 + n = w27 ^ w22 ^ w16 ^ w14; + w30 = (n << 1) | (n >>> 31); + t = (w30 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 31 + n = w28 ^ w23 ^ w17 ^ w15; + w31 = (n << 1) | (n >>> 31); + t = (w31 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 32 + n = w29 ^ w24 ^ w18 ^ w16; + w32 = (n << 1) | (n >>> 31); + t = (w32 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 33 + n = w30 ^ w25 ^ w19 ^ w17; + w33 = (n << 1) | (n >>> 31); + t = (w33 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 34 + n = w31 ^ w26 ^ w20 ^ w18; + w34 = (n << 1) | (n >>> 31); + t = (w34 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 35 + n = w32 ^ w27 ^ w21 ^ w19; + w35 = (n << 1) | (n >>> 31); + t = (w35 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 36 + n = w33 ^ w28 ^ w22 ^ w20; + w36 = (n << 1) | (n >>> 31); + t = (w36 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 37 + n = w34 ^ w29 ^ w23 ^ w21; + w37 = (n << 1) | (n >>> 31); + t = (w37 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 38 + n = w35 ^ w30 ^ w24 ^ w22; + w38 = (n << 1) | (n >>> 31); + t = (w38 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 39 + n = w36 ^ w31 ^ w25 ^ w23; + w39 = (n << 1) | (n >>> 31); + t = (w39 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 40 + n = w37 ^ w32 ^ w26 ^ w24; + w40 = (n << 1) | (n >>> 31); + t = (w40 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 41 + n = w38 ^ w33 ^ w27 ^ w25; + w41 = (n << 1) | (n >>> 31); + t = (w41 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 42 + n = w39 ^ w34 ^ w28 ^ w26; + w42 = (n << 1) | (n >>> 31); + t = (w42 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 43 + n = w40 ^ w35 ^ w29 ^ w27; + w43 = (n << 1) | (n >>> 31); + t = (w43 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 44 + n = w41 ^ w36 ^ w30 ^ w28; + w44 = (n << 1) | (n >>> 31); + t = (w44 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 45 + n = w42 ^ w37 ^ w31 ^ w29; + w45 = (n << 1) | (n >>> 31); + t = (w45 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 46 + n = w43 ^ w38 ^ w32 ^ w30; + w46 = (n << 1) | (n >>> 31); + t = (w46 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 47 + n = w44 ^ w39 ^ w33 ^ w31; + w47 = (n << 1) | (n >>> 31); + t = (w47 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 48 + n = w45 ^ w40 ^ w34 ^ w32; + w48 = (n << 1) | (n >>> 31); + t = (w48 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 49 + n = w46 ^ w41 ^ w35 ^ w33; + w49 = (n << 1) | (n >>> 31); + t = (w49 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 50 + n = w47 ^ w42 ^ w36 ^ w34; + w50 = (n << 1) | (n >>> 31); + t = (w50 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 51 + n = w48 ^ w43 ^ w37 ^ w35; + w51 = (n << 1) | (n >>> 31); + t = (w51 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 52 + n = w49 ^ w44 ^ w38 ^ w36; + w52 = (n << 1) | (n >>> 31); + t = (w52 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 53 + n = w50 ^ w45 ^ w39 ^ w37; + w53 = (n << 1) | (n >>> 31); + t = (w53 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 54 + n = w51 ^ w46 ^ w40 ^ w38; + w54 = (n << 1) | (n >>> 31); + t = (w54 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 55 + n = w52 ^ w47 ^ w41 ^ w39; + w55 = (n << 1) | (n >>> 31); + t = (w55 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 56 + n = w53 ^ w48 ^ w42 ^ w40; + w56 = (n << 1) | (n >>> 31); + t = (w56 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 57 + n = w54 ^ w49 ^ w43 ^ w41; + w57 = (n << 1) | (n >>> 31); + t = (w57 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 58 + n = w55 ^ w50 ^ w44 ^ w42; + w58 = (n << 1) | (n >>> 31); + t = (w58 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 59 + n = w56 ^ w51 ^ w45 ^ w43; + w59 = (n << 1) | (n >>> 31); + t = (w59 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 60 + n = w57 ^ w52 ^ w46 ^ w44; + w60 = (n << 1) | (n >>> 31); + t = (w60 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 61 + n = w58 ^ w53 ^ w47 ^ w45; + w61 = (n << 1) | (n >>> 31); + t = (w61 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 62 + n = w59 ^ w54 ^ w48 ^ w46; + w62 = (n << 1) | (n >>> 31); + t = (w62 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 63 + n = w60 ^ w55 ^ w49 ^ w47; + w63 = (n << 1) | (n >>> 31); + t = (w63 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 64 + n = w61 ^ w56 ^ w50 ^ w48; + w64 = (n << 1) | (n >>> 31); + t = (w64 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 65 + n = w62 ^ w57 ^ w51 ^ w49; + w65 = (n << 1) | (n >>> 31); + t = (w65 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 66 + n = w63 ^ w58 ^ w52 ^ w50; + w66 = (n << 1) | (n >>> 31); + t = (w66 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 67 + n = w64 ^ w59 ^ w53 ^ w51; + w67 = (n << 1) | (n >>> 31); + t = (w67 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 68 + n = w65 ^ w60 ^ w54 ^ w52; + w68 = (n << 1) | (n >>> 31); + t = (w68 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 69 + n = w66 ^ w61 ^ w55 ^ w53; + w69 = (n << 1) | (n >>> 31); + t = (w69 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 70 + n = w67 ^ w62 ^ w56 ^ w54; + w70 = (n << 1) | (n >>> 31); + t = (w70 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 71 + n = w68 ^ w63 ^ w57 ^ w55; + w71 = (n << 1) | (n >>> 31); + t = (w71 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 72 + n = w69 ^ w64 ^ w58 ^ w56; + w72 = (n << 1) | (n >>> 31); + t = (w72 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 73 + n = w70 ^ w65 ^ w59 ^ w57; + w73 = (n << 1) | (n >>> 31); + t = (w73 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 74 + n = w71 ^ w66 ^ w60 ^ w58; + w74 = (n << 1) | (n >>> 31); + t = (w74 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 75 + n = w72 ^ w67 ^ w61 ^ w59; + w75 = (n << 1) | (n >>> 31); + t = (w75 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 76 + n = w73 ^ w68 ^ w62 ^ w60; + w76 = (n << 1) | (n >>> 31); + t = (w76 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 77 + n = w74 ^ w69 ^ w63 ^ w61; + w77 = (n << 1) | (n >>> 31); + t = (w77 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 78 + n = w75 ^ w70 ^ w64 ^ w62; + w78 = (n << 1) | (n >>> 31); + t = (w78 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + // 79 + n = w76 ^ w71 ^ w65 ^ w63; + w79 = (n << 1) | (n >>> 31); + t = (w79 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; + e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; + + H0 = ( H0 + a )|0; + H1 = ( H1 + b )|0; + H2 = ( H2 + c )|0; + H3 = ( H3 + d )|0; + H4 = ( H4 + e )|0; + + } + + function _core_heap ( offset ) { + offset = offset|0; + + _core( + HEAP[offset|0]<<24 | HEAP[offset|1]<<16 | HEAP[offset|2]<<8 | HEAP[offset|3], + HEAP[offset|4]<<24 | HEAP[offset|5]<<16 | HEAP[offset|6]<<8 | HEAP[offset|7], + HEAP[offset|8]<<24 | HEAP[offset|9]<<16 | HEAP[offset|10]<<8 | HEAP[offset|11], + HEAP[offset|12]<<24 | HEAP[offset|13]<<16 | HEAP[offset|14]<<8 | HEAP[offset|15], + HEAP[offset|16]<<24 | HEAP[offset|17]<<16 | HEAP[offset|18]<<8 | HEAP[offset|19], + HEAP[offset|20]<<24 | HEAP[offset|21]<<16 | HEAP[offset|22]<<8 | HEAP[offset|23], + HEAP[offset|24]<<24 | HEAP[offset|25]<<16 | HEAP[offset|26]<<8 | HEAP[offset|27], + HEAP[offset|28]<<24 | HEAP[offset|29]<<16 | HEAP[offset|30]<<8 | HEAP[offset|31], + HEAP[offset|32]<<24 | HEAP[offset|33]<<16 | HEAP[offset|34]<<8 | HEAP[offset|35], + HEAP[offset|36]<<24 | HEAP[offset|37]<<16 | HEAP[offset|38]<<8 | HEAP[offset|39], + HEAP[offset|40]<<24 | HEAP[offset|41]<<16 | HEAP[offset|42]<<8 | HEAP[offset|43], + HEAP[offset|44]<<24 | HEAP[offset|45]<<16 | HEAP[offset|46]<<8 | HEAP[offset|47], + HEAP[offset|48]<<24 | HEAP[offset|49]<<16 | HEAP[offset|50]<<8 | HEAP[offset|51], + HEAP[offset|52]<<24 | HEAP[offset|53]<<16 | HEAP[offset|54]<<8 | HEAP[offset|55], + HEAP[offset|56]<<24 | HEAP[offset|57]<<16 | HEAP[offset|58]<<8 | HEAP[offset|59], + HEAP[offset|60]<<24 | HEAP[offset|61]<<16 | HEAP[offset|62]<<8 | HEAP[offset|63] + ); + } + + // offset — multiple of 32 + function _state_to_heap ( output ) { + output = output|0; + + HEAP[output|0] = H0>>>24; + HEAP[output|1] = H0>>>16&255; + HEAP[output|2] = H0>>>8&255; + HEAP[output|3] = H0&255; + HEAP[output|4] = H1>>>24; + HEAP[output|5] = H1>>>16&255; + HEAP[output|6] = H1>>>8&255; + HEAP[output|7] = H1&255; + HEAP[output|8] = H2>>>24; + HEAP[output|9] = H2>>>16&255; + HEAP[output|10] = H2>>>8&255; + HEAP[output|11] = H2&255; + HEAP[output|12] = H3>>>24; + HEAP[output|13] = H3>>>16&255; + HEAP[output|14] = H3>>>8&255; + HEAP[output|15] = H3&255; + HEAP[output|16] = H4>>>24; + HEAP[output|17] = H4>>>16&255; + HEAP[output|18] = H4>>>8&255; + HEAP[output|19] = H4&255; + } + + function reset () { + H0 = 0x67452301; + H1 = 0xefcdab89; + H2 = 0x98badcfe; + H3 = 0x10325476; + H4 = 0xc3d2e1f0; + TOTAL0 = TOTAL1 = 0; + } + + function init ( h0, h1, h2, h3, h4, total0, total1 ) { + h0 = h0|0; + h1 = h1|0; + h2 = h2|0; + h3 = h3|0; + h4 = h4|0; + total0 = total0|0; + total1 = total1|0; + + H0 = h0; + H1 = h1; + H2 = h2; + H3 = h3; + H4 = h4; + TOTAL0 = total0; + TOTAL1 = total1; + } + + // offset — multiple of 64 + function process ( offset, length ) { + offset = offset|0; + length = length|0; + + var hashed = 0; + + if ( offset & 63 ) + return -1; + + while ( (length|0) >= 64 ) { + _core_heap(offset); + + offset = ( offset + 64 )|0; + length = ( length - 64 )|0; + + hashed = ( hashed + 64 )|0; + } + + TOTAL0 = ( TOTAL0 + hashed )|0; + if ( TOTAL0>>>0 < hashed>>>0 ) TOTAL1 = ( TOTAL1 + 1 )|0; + + return hashed|0; + } + + // offset — multiple of 64 + // output — multiple of 32 + function finish ( offset, length, output ) { + offset = offset|0; + length = length|0; + output = output|0; + + var hashed = 0, + i = 0; + + if ( offset & 63 ) + return -1; + + if ( ~output ) + if ( output & 31 ) + return -1; + + if ( (length|0) >= 64 ) { + hashed = process( offset, length )|0; + if ( (hashed|0) == -1 ) + return -1; + + offset = ( offset + hashed )|0; + length = ( length - hashed )|0; + } + + hashed = ( hashed + length )|0; + TOTAL0 = ( TOTAL0 + length )|0; + if ( TOTAL0>>>0 < length>>>0 ) TOTAL1 = (TOTAL1 + 1)|0; + + HEAP[offset|length] = 0x80; + + if ( (length|0) >= 56 ) { + for ( i = (length+1)|0; (i|0) < 64; i = (i+1)|0 ) + HEAP[offset|i] = 0x00; + _core_heap(offset); + + length = 0; + + HEAP[offset|0] = 0; + } + + for ( i = (length+1)|0; (i|0) < 59; i = (i+1)|0 ) + HEAP[offset|i] = 0; + + HEAP[offset|56] = TOTAL1>>>21&255; + HEAP[offset|57] = TOTAL1>>>13&255; + HEAP[offset|58] = TOTAL1>>>5&255; + HEAP[offset|59] = TOTAL1<<3&255 | TOTAL0>>>29; + HEAP[offset|60] = TOTAL0>>>21&255; + HEAP[offset|61] = TOTAL0>>>13&255; + HEAP[offset|62] = TOTAL0>>>5&255; + HEAP[offset|63] = TOTAL0<<3&255; + _core_heap(offset); + + if ( ~output ) + _state_to_heap(output); + + return hashed|0; + } + + function hmac_reset () { + H0 = I0; + H1 = I1; + H2 = I2; + H3 = I3; + H4 = I4; + TOTAL0 = 64; + TOTAL1 = 0; + } + + function _hmac_opad () { + H0 = O0; + H1 = O1; + H2 = O2; + H3 = O3; + H4 = O4; + TOTAL0 = 64; + TOTAL1 = 0; + } + + function hmac_init ( p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15 ) { + p0 = p0|0; + p1 = p1|0; + p2 = p2|0; + p3 = p3|0; + p4 = p4|0; + p5 = p5|0; + p6 = p6|0; + p7 = p7|0; + p8 = p8|0; + p9 = p9|0; + p10 = p10|0; + p11 = p11|0; + p12 = p12|0; + p13 = p13|0; + p14 = p14|0; + p15 = p15|0; + + // opad + reset(); + _core( + p0 ^ 0x5c5c5c5c, + p1 ^ 0x5c5c5c5c, + p2 ^ 0x5c5c5c5c, + p3 ^ 0x5c5c5c5c, + p4 ^ 0x5c5c5c5c, + p5 ^ 0x5c5c5c5c, + p6 ^ 0x5c5c5c5c, + p7 ^ 0x5c5c5c5c, + p8 ^ 0x5c5c5c5c, + p9 ^ 0x5c5c5c5c, + p10 ^ 0x5c5c5c5c, + p11 ^ 0x5c5c5c5c, + p12 ^ 0x5c5c5c5c, + p13 ^ 0x5c5c5c5c, + p14 ^ 0x5c5c5c5c, + p15 ^ 0x5c5c5c5c + ); + O0 = H0; + O1 = H1; + O2 = H2; + O3 = H3; + O4 = H4; + + // ipad + reset(); + _core( + p0 ^ 0x36363636, + p1 ^ 0x36363636, + p2 ^ 0x36363636, + p3 ^ 0x36363636, + p4 ^ 0x36363636, + p5 ^ 0x36363636, + p6 ^ 0x36363636, + p7 ^ 0x36363636, + p8 ^ 0x36363636, + p9 ^ 0x36363636, + p10 ^ 0x36363636, + p11 ^ 0x36363636, + p12 ^ 0x36363636, + p13 ^ 0x36363636, + p14 ^ 0x36363636, + p15 ^ 0x36363636 + ); + I0 = H0; + I1 = H1; + I2 = H2; + I3 = H3; + I4 = H4; + + TOTAL0 = 64; + TOTAL1 = 0; + } + + // offset — multiple of 64 + // output — multiple of 32 + function hmac_finish ( offset, length, output ) { + offset = offset|0; + length = length|0; + output = output|0; + + var t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, hashed = 0; + + if ( offset & 63 ) + return -1; + + if ( ~output ) + if ( output & 31 ) + return -1; + + hashed = finish( offset, length, -1 )|0; + t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; + + _hmac_opad(); + _core( t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672 ); + + if ( ~output ) + _state_to_heap(output); + + return hashed|0; + } + + // salt is assumed to be already processed + // offset — multiple of 64 + // output — multiple of 32 + function pbkdf2_generate_block ( offset, length, block, count, output ) { + offset = offset|0; + length = length|0; + block = block|0; + count = count|0; + output = output|0; + + var h0 = 0, h1 = 0, h2 = 0, h3 = 0, h4 = 0, + t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0; + + if ( offset & 63 ) + return -1; + + if ( ~output ) + if ( output & 31 ) + return -1; + + // pad block number into heap + // FIXME probable OOB write + HEAP[(offset+length)|0] = block>>>24; + HEAP[(offset+length+1)|0] = block>>>16&255; + HEAP[(offset+length+2)|0] = block>>>8&255; + HEAP[(offset+length+3)|0] = block&255; + + // finish first iteration + hmac_finish( offset, (length+4)|0, -1 )|0; + h0 = t0 = H0, h1 = t1 = H1, h2 = t2 = H2, h3 = t3 = H3, h4 = t4 = H4; + count = (count-1)|0; + + // perform the rest iterations + while ( (count|0) > 0 ) { + hmac_reset(); + _core( t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672 ); + t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; + + _hmac_opad(); + _core( t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672 ); + t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; + + h0 = h0 ^ H0; + h1 = h1 ^ H1; + h2 = h2 ^ H2; + h3 = h3 ^ H3; + h4 = h4 ^ H4; + + count = (count-1)|0; + } + + H0 = h0; + H1 = h1; + H2 = h2; + H3 = h3; + H4 = h4; + + if ( ~output ) + _state_to_heap(output); + + return 0; + } + + return { + // SHA1 + reset: reset, + init: init, + process: process, + finish: finish, + + // HMAC-SHA1 + hmac_reset: hmac_reset, + hmac_init: hmac_init, + hmac_finish: hmac_finish, + + // PBKDF2-HMAC-SHA1 + pbkdf2_generate_block: pbkdf2_generate_block + } + }; + + class Hash { + constructor() { + this.pos = 0; + this.len = 0; + } + reset() { + const { asm } = this.acquire_asm(); + this.result = null; + this.pos = 0; + this.len = 0; + asm.reset(); + return this; + } + process(data) { + if (this.result !== null) + throw new IllegalStateError('state must be reset before processing new data'); + const { asm, heap } = this.acquire_asm(); + let hpos = this.pos; + let hlen = this.len; + let dpos = 0; + let dlen = data.length; + let wlen = 0; + while (dlen > 0) { + wlen = _heap_write(heap, hpos + hlen, data, dpos, dlen); + hlen += wlen; + dpos += wlen; + dlen -= wlen; + wlen = asm.process(hpos, hlen); + hpos += wlen; + hlen -= wlen; + if (!hlen) + hpos = 0; + } + this.pos = hpos; + this.len = hlen; + return this; + } + finish() { + if (this.result !== null) + throw new IllegalStateError('state must be reset before processing new data'); + const { asm, heap } = this.acquire_asm(); + asm.finish(this.pos, this.len, 0); + this.result = new Uint8Array(this.HASH_SIZE); + this.result.set(heap.subarray(0, this.HASH_SIZE)); + this.pos = 0; + this.len = 0; + this.release_asm(); + return this; + } + } + + const _sha1_block_size = 64; + const _sha1_hash_size = 20; + const heap_pool$1 = []; + const asm_pool$1 = []; + class Sha1 extends Hash { + constructor() { + super(); + this.NAME = 'sha1'; + this.BLOCK_SIZE = _sha1_block_size; + this.HASH_SIZE = _sha1_hash_size; + this.acquire_asm(); + } + acquire_asm() { + if (this.heap === undefined || this.asm === undefined) { + this.heap = heap_pool$1.pop() || _heap_init(); + this.asm = asm_pool$1.pop() || sha1_asm({ Uint8Array: Uint8Array }, null, this.heap.buffer); + this.reset(); + } + return { heap: this.heap, asm: this.asm }; + } + release_asm() { + if (this.heap !== undefined && this.asm !== undefined) { + heap_pool$1.push(this.heap); + asm_pool$1.push(this.asm); + } + this.heap = undefined; + this.asm = undefined; + } + static bytes(data) { + return new Sha1().process(data).finish().result; + } + } + Sha1.NAME = 'sha1'; + Sha1.heap_pool = []; + Sha1.asm_pool = []; + Sha1.asm_function = sha1_asm; + + var sha256_asm = function ( stdlib, foreign, buffer ) { + "use asm"; + + // SHA256 state + var H0 = 0, H1 = 0, H2 = 0, H3 = 0, H4 = 0, H5 = 0, H6 = 0, H7 = 0, + TOTAL0 = 0, TOTAL1 = 0; + + // HMAC state + var I0 = 0, I1 = 0, I2 = 0, I3 = 0, I4 = 0, I5 = 0, I6 = 0, I7 = 0, + O0 = 0, O1 = 0, O2 = 0, O3 = 0, O4 = 0, O5 = 0, O6 = 0, O7 = 0; + + // I/O buffer + var HEAP = new stdlib.Uint8Array(buffer); + + function _core ( w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15 ) { + w0 = w0|0; + w1 = w1|0; + w2 = w2|0; + w3 = w3|0; + w4 = w4|0; + w5 = w5|0; + w6 = w6|0; + w7 = w7|0; + w8 = w8|0; + w9 = w9|0; + w10 = w10|0; + w11 = w11|0; + w12 = w12|0; + w13 = w13|0; + w14 = w14|0; + w15 = w15|0; + + var a = 0, b = 0, c = 0, d = 0, e = 0, f = 0, g = 0, h = 0; + + a = H0; + b = H1; + c = H2; + d = H3; + e = H4; + f = H5; + g = H6; + h = H7; + + // 0 + h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x428a2f98 )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; + + // 1 + g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x71374491 )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; + + // 2 + f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0xb5c0fbcf )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; + + // 3 + e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0xe9b5dba5 )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; + + // 4 + d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x3956c25b )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; + + // 5 + c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x59f111f1 )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; + + // 6 + b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x923f82a4 )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; + + // 7 + a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0xab1c5ed5 )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; + + // 8 + h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0xd807aa98 )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; + + // 9 + g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x12835b01 )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; + + // 10 + f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x243185be )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; + + // 11 + e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x550c7dc3 )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; + + // 12 + d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x72be5d74 )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; + + // 13 + c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x80deb1fe )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; + + // 14 + b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x9bdc06a7 )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; + + // 15 + a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0xc19bf174 )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; + + // 16 + w0 = ( ( w1>>>7 ^ w1>>>18 ^ w1>>>3 ^ w1<<25 ^ w1<<14 ) + ( w14>>>17 ^ w14>>>19 ^ w14>>>10 ^ w14<<15 ^ w14<<13 ) + w0 + w9 )|0; + h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0xe49b69c1 )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; + + // 17 + w1 = ( ( w2>>>7 ^ w2>>>18 ^ w2>>>3 ^ w2<<25 ^ w2<<14 ) + ( w15>>>17 ^ w15>>>19 ^ w15>>>10 ^ w15<<15 ^ w15<<13 ) + w1 + w10 )|0; + g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0xefbe4786 )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; + + // 18 + w2 = ( ( w3>>>7 ^ w3>>>18 ^ w3>>>3 ^ w3<<25 ^ w3<<14 ) + ( w0>>>17 ^ w0>>>19 ^ w0>>>10 ^ w0<<15 ^ w0<<13 ) + w2 + w11 )|0; + f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x0fc19dc6 )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; + + // 19 + w3 = ( ( w4>>>7 ^ w4>>>18 ^ w4>>>3 ^ w4<<25 ^ w4<<14 ) + ( w1>>>17 ^ w1>>>19 ^ w1>>>10 ^ w1<<15 ^ w1<<13 ) + w3 + w12 )|0; + e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x240ca1cc )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; + + // 20 + w4 = ( ( w5>>>7 ^ w5>>>18 ^ w5>>>3 ^ w5<<25 ^ w5<<14 ) + ( w2>>>17 ^ w2>>>19 ^ w2>>>10 ^ w2<<15 ^ w2<<13 ) + w4 + w13 )|0; + d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x2de92c6f )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; + + // 21 + w5 = ( ( w6>>>7 ^ w6>>>18 ^ w6>>>3 ^ w6<<25 ^ w6<<14 ) + ( w3>>>17 ^ w3>>>19 ^ w3>>>10 ^ w3<<15 ^ w3<<13 ) + w5 + w14 )|0; + c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x4a7484aa )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; + + // 22 + w6 = ( ( w7>>>7 ^ w7>>>18 ^ w7>>>3 ^ w7<<25 ^ w7<<14 ) + ( w4>>>17 ^ w4>>>19 ^ w4>>>10 ^ w4<<15 ^ w4<<13 ) + w6 + w15 )|0; + b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x5cb0a9dc )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; + + // 23 + w7 = ( ( w8>>>7 ^ w8>>>18 ^ w8>>>3 ^ w8<<25 ^ w8<<14 ) + ( w5>>>17 ^ w5>>>19 ^ w5>>>10 ^ w5<<15 ^ w5<<13 ) + w7 + w0 )|0; + a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x76f988da )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; + + // 24 + w8 = ( ( w9>>>7 ^ w9>>>18 ^ w9>>>3 ^ w9<<25 ^ w9<<14 ) + ( w6>>>17 ^ w6>>>19 ^ w6>>>10 ^ w6<<15 ^ w6<<13 ) + w8 + w1 )|0; + h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x983e5152 )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; + + // 25 + w9 = ( ( w10>>>7 ^ w10>>>18 ^ w10>>>3 ^ w10<<25 ^ w10<<14 ) + ( w7>>>17 ^ w7>>>19 ^ w7>>>10 ^ w7<<15 ^ w7<<13 ) + w9 + w2 )|0; + g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0xa831c66d )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; + + // 26 + w10 = ( ( w11>>>7 ^ w11>>>18 ^ w11>>>3 ^ w11<<25 ^ w11<<14 ) + ( w8>>>17 ^ w8>>>19 ^ w8>>>10 ^ w8<<15 ^ w8<<13 ) + w10 + w3 )|0; + f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0xb00327c8 )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; + + // 27 + w11 = ( ( w12>>>7 ^ w12>>>18 ^ w12>>>3 ^ w12<<25 ^ w12<<14 ) + ( w9>>>17 ^ w9>>>19 ^ w9>>>10 ^ w9<<15 ^ w9<<13 ) + w11 + w4 )|0; + e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0xbf597fc7 )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; + + // 28 + w12 = ( ( w13>>>7 ^ w13>>>18 ^ w13>>>3 ^ w13<<25 ^ w13<<14 ) + ( w10>>>17 ^ w10>>>19 ^ w10>>>10 ^ w10<<15 ^ w10<<13 ) + w12 + w5 )|0; + d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0xc6e00bf3 )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; + + // 29 + w13 = ( ( w14>>>7 ^ w14>>>18 ^ w14>>>3 ^ w14<<25 ^ w14<<14 ) + ( w11>>>17 ^ w11>>>19 ^ w11>>>10 ^ w11<<15 ^ w11<<13 ) + w13 + w6 )|0; + c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0xd5a79147 )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; + + // 30 + w14 = ( ( w15>>>7 ^ w15>>>18 ^ w15>>>3 ^ w15<<25 ^ w15<<14 ) + ( w12>>>17 ^ w12>>>19 ^ w12>>>10 ^ w12<<15 ^ w12<<13 ) + w14 + w7 )|0; + b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x06ca6351 )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; + + // 31 + w15 = ( ( w0>>>7 ^ w0>>>18 ^ w0>>>3 ^ w0<<25 ^ w0<<14 ) + ( w13>>>17 ^ w13>>>19 ^ w13>>>10 ^ w13<<15 ^ w13<<13 ) + w15 + w8 )|0; + a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x14292967 )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; + + // 32 + w0 = ( ( w1>>>7 ^ w1>>>18 ^ w1>>>3 ^ w1<<25 ^ w1<<14 ) + ( w14>>>17 ^ w14>>>19 ^ w14>>>10 ^ w14<<15 ^ w14<<13 ) + w0 + w9 )|0; + h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x27b70a85 )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; + + // 33 + w1 = ( ( w2>>>7 ^ w2>>>18 ^ w2>>>3 ^ w2<<25 ^ w2<<14 ) + ( w15>>>17 ^ w15>>>19 ^ w15>>>10 ^ w15<<15 ^ w15<<13 ) + w1 + w10 )|0; + g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x2e1b2138 )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; + + // 34 + w2 = ( ( w3>>>7 ^ w3>>>18 ^ w3>>>3 ^ w3<<25 ^ w3<<14 ) + ( w0>>>17 ^ w0>>>19 ^ w0>>>10 ^ w0<<15 ^ w0<<13 ) + w2 + w11 )|0; + f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x4d2c6dfc )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; + + // 35 + w3 = ( ( w4>>>7 ^ w4>>>18 ^ w4>>>3 ^ w4<<25 ^ w4<<14 ) + ( w1>>>17 ^ w1>>>19 ^ w1>>>10 ^ w1<<15 ^ w1<<13 ) + w3 + w12 )|0; + e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x53380d13 )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; + + // 36 + w4 = ( ( w5>>>7 ^ w5>>>18 ^ w5>>>3 ^ w5<<25 ^ w5<<14 ) + ( w2>>>17 ^ w2>>>19 ^ w2>>>10 ^ w2<<15 ^ w2<<13 ) + w4 + w13 )|0; + d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x650a7354 )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; + + // 37 + w5 = ( ( w6>>>7 ^ w6>>>18 ^ w6>>>3 ^ w6<<25 ^ w6<<14 ) + ( w3>>>17 ^ w3>>>19 ^ w3>>>10 ^ w3<<15 ^ w3<<13 ) + w5 + w14 )|0; + c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x766a0abb )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; + + // 38 + w6 = ( ( w7>>>7 ^ w7>>>18 ^ w7>>>3 ^ w7<<25 ^ w7<<14 ) + ( w4>>>17 ^ w4>>>19 ^ w4>>>10 ^ w4<<15 ^ w4<<13 ) + w6 + w15 )|0; + b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x81c2c92e )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; + + // 39 + w7 = ( ( w8>>>7 ^ w8>>>18 ^ w8>>>3 ^ w8<<25 ^ w8<<14 ) + ( w5>>>17 ^ w5>>>19 ^ w5>>>10 ^ w5<<15 ^ w5<<13 ) + w7 + w0 )|0; + a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x92722c85 )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; + + // 40 + w8 = ( ( w9>>>7 ^ w9>>>18 ^ w9>>>3 ^ w9<<25 ^ w9<<14 ) + ( w6>>>17 ^ w6>>>19 ^ w6>>>10 ^ w6<<15 ^ w6<<13 ) + w8 + w1 )|0; + h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0xa2bfe8a1 )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; + + // 41 + w9 = ( ( w10>>>7 ^ w10>>>18 ^ w10>>>3 ^ w10<<25 ^ w10<<14 ) + ( w7>>>17 ^ w7>>>19 ^ w7>>>10 ^ w7<<15 ^ w7<<13 ) + w9 + w2 )|0; + g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0xa81a664b )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; + + // 42 + w10 = ( ( w11>>>7 ^ w11>>>18 ^ w11>>>3 ^ w11<<25 ^ w11<<14 ) + ( w8>>>17 ^ w8>>>19 ^ w8>>>10 ^ w8<<15 ^ w8<<13 ) + w10 + w3 )|0; + f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0xc24b8b70 )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; + + // 43 + w11 = ( ( w12>>>7 ^ w12>>>18 ^ w12>>>3 ^ w12<<25 ^ w12<<14 ) + ( w9>>>17 ^ w9>>>19 ^ w9>>>10 ^ w9<<15 ^ w9<<13 ) + w11 + w4 )|0; + e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0xc76c51a3 )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; + + // 44 + w12 = ( ( w13>>>7 ^ w13>>>18 ^ w13>>>3 ^ w13<<25 ^ w13<<14 ) + ( w10>>>17 ^ w10>>>19 ^ w10>>>10 ^ w10<<15 ^ w10<<13 ) + w12 + w5 )|0; + d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0xd192e819 )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; + + // 45 + w13 = ( ( w14>>>7 ^ w14>>>18 ^ w14>>>3 ^ w14<<25 ^ w14<<14 ) + ( w11>>>17 ^ w11>>>19 ^ w11>>>10 ^ w11<<15 ^ w11<<13 ) + w13 + w6 )|0; + c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0xd6990624 )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; + + // 46 + w14 = ( ( w15>>>7 ^ w15>>>18 ^ w15>>>3 ^ w15<<25 ^ w15<<14 ) + ( w12>>>17 ^ w12>>>19 ^ w12>>>10 ^ w12<<15 ^ w12<<13 ) + w14 + w7 )|0; + b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0xf40e3585 )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; + + // 47 + w15 = ( ( w0>>>7 ^ w0>>>18 ^ w0>>>3 ^ w0<<25 ^ w0<<14 ) + ( w13>>>17 ^ w13>>>19 ^ w13>>>10 ^ w13<<15 ^ w13<<13 ) + w15 + w8 )|0; + a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x106aa070 )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; + + // 48 + w0 = ( ( w1>>>7 ^ w1>>>18 ^ w1>>>3 ^ w1<<25 ^ w1<<14 ) + ( w14>>>17 ^ w14>>>19 ^ w14>>>10 ^ w14<<15 ^ w14<<13 ) + w0 + w9 )|0; + h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x19a4c116 )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; + + // 49 + w1 = ( ( w2>>>7 ^ w2>>>18 ^ w2>>>3 ^ w2<<25 ^ w2<<14 ) + ( w15>>>17 ^ w15>>>19 ^ w15>>>10 ^ w15<<15 ^ w15<<13 ) + w1 + w10 )|0; + g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x1e376c08 )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; + + // 50 + w2 = ( ( w3>>>7 ^ w3>>>18 ^ w3>>>3 ^ w3<<25 ^ w3<<14 ) + ( w0>>>17 ^ w0>>>19 ^ w0>>>10 ^ w0<<15 ^ w0<<13 ) + w2 + w11 )|0; + f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x2748774c )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; + + // 51 + w3 = ( ( w4>>>7 ^ w4>>>18 ^ w4>>>3 ^ w4<<25 ^ w4<<14 ) + ( w1>>>17 ^ w1>>>19 ^ w1>>>10 ^ w1<<15 ^ w1<<13 ) + w3 + w12 )|0; + e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x34b0bcb5 )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; + + // 52 + w4 = ( ( w5>>>7 ^ w5>>>18 ^ w5>>>3 ^ w5<<25 ^ w5<<14 ) + ( w2>>>17 ^ w2>>>19 ^ w2>>>10 ^ w2<<15 ^ w2<<13 ) + w4 + w13 )|0; + d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x391c0cb3 )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; + + // 53 + w5 = ( ( w6>>>7 ^ w6>>>18 ^ w6>>>3 ^ w6<<25 ^ w6<<14 ) + ( w3>>>17 ^ w3>>>19 ^ w3>>>10 ^ w3<<15 ^ w3<<13 ) + w5 + w14 )|0; + c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x4ed8aa4a )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; + + // 54 + w6 = ( ( w7>>>7 ^ w7>>>18 ^ w7>>>3 ^ w7<<25 ^ w7<<14 ) + ( w4>>>17 ^ w4>>>19 ^ w4>>>10 ^ w4<<15 ^ w4<<13 ) + w6 + w15 )|0; + b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x5b9cca4f )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; + + // 55 + w7 = ( ( w8>>>7 ^ w8>>>18 ^ w8>>>3 ^ w8<<25 ^ w8<<14 ) + ( w5>>>17 ^ w5>>>19 ^ w5>>>10 ^ w5<<15 ^ w5<<13 ) + w7 + w0 )|0; + a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x682e6ff3 )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; + + // 56 + w8 = ( ( w9>>>7 ^ w9>>>18 ^ w9>>>3 ^ w9<<25 ^ w9<<14 ) + ( w6>>>17 ^ w6>>>19 ^ w6>>>10 ^ w6<<15 ^ w6<<13 ) + w8 + w1 )|0; + h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x748f82ee )|0; + d = ( d + h )|0; + h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; + + // 57 + w9 = ( ( w10>>>7 ^ w10>>>18 ^ w10>>>3 ^ w10<<25 ^ w10<<14 ) + ( w7>>>17 ^ w7>>>19 ^ w7>>>10 ^ w7<<15 ^ w7<<13 ) + w9 + w2 )|0; + g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x78a5636f )|0; + c = ( c + g )|0; + g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; + + // 58 + w10 = ( ( w11>>>7 ^ w11>>>18 ^ w11>>>3 ^ w11<<25 ^ w11<<14 ) + ( w8>>>17 ^ w8>>>19 ^ w8>>>10 ^ w8<<15 ^ w8<<13 ) + w10 + w3 )|0; + f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x84c87814 )|0; + b = ( b + f )|0; + f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; + + // 59 + w11 = ( ( w12>>>7 ^ w12>>>18 ^ w12>>>3 ^ w12<<25 ^ w12<<14 ) + ( w9>>>17 ^ w9>>>19 ^ w9>>>10 ^ w9<<15 ^ w9<<13 ) + w11 + w4 )|0; + e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x8cc70208 )|0; + a = ( a + e )|0; + e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; + + // 60 + w12 = ( ( w13>>>7 ^ w13>>>18 ^ w13>>>3 ^ w13<<25 ^ w13<<14 ) + ( w10>>>17 ^ w10>>>19 ^ w10>>>10 ^ w10<<15 ^ w10<<13 ) + w12 + w5 )|0; + d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x90befffa )|0; + h = ( h + d )|0; + d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; + + // 61 + w13 = ( ( w14>>>7 ^ w14>>>18 ^ w14>>>3 ^ w14<<25 ^ w14<<14 ) + ( w11>>>17 ^ w11>>>19 ^ w11>>>10 ^ w11<<15 ^ w11<<13 ) + w13 + w6 )|0; + c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0xa4506ceb )|0; + g = ( g + c )|0; + c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; + + // 62 + w14 = ( ( w15>>>7 ^ w15>>>18 ^ w15>>>3 ^ w15<<25 ^ w15<<14 ) + ( w12>>>17 ^ w12>>>19 ^ w12>>>10 ^ w12<<15 ^ w12<<13 ) + w14 + w7 )|0; + b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0xbef9a3f7 )|0; + f = ( f + b )|0; + b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; + + // 63 + w15 = ( ( w0>>>7 ^ w0>>>18 ^ w0>>>3 ^ w0<<25 ^ w0<<14 ) + ( w13>>>17 ^ w13>>>19 ^ w13>>>10 ^ w13<<15 ^ w13<<13 ) + w15 + w8 )|0; + a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0xc67178f2 )|0; + e = ( e + a )|0; + a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; + + H0 = ( H0 + a )|0; + H1 = ( H1 + b )|0; + H2 = ( H2 + c )|0; + H3 = ( H3 + d )|0; + H4 = ( H4 + e )|0; + H5 = ( H5 + f )|0; + H6 = ( H6 + g )|0; + H7 = ( H7 + h )|0; + } + + function _core_heap ( offset ) { + offset = offset|0; + + _core( + HEAP[offset|0]<<24 | HEAP[offset|1]<<16 | HEAP[offset|2]<<8 | HEAP[offset|3], + HEAP[offset|4]<<24 | HEAP[offset|5]<<16 | HEAP[offset|6]<<8 | HEAP[offset|7], + HEAP[offset|8]<<24 | HEAP[offset|9]<<16 | HEAP[offset|10]<<8 | HEAP[offset|11], + HEAP[offset|12]<<24 | HEAP[offset|13]<<16 | HEAP[offset|14]<<8 | HEAP[offset|15], + HEAP[offset|16]<<24 | HEAP[offset|17]<<16 | HEAP[offset|18]<<8 | HEAP[offset|19], + HEAP[offset|20]<<24 | HEAP[offset|21]<<16 | HEAP[offset|22]<<8 | HEAP[offset|23], + HEAP[offset|24]<<24 | HEAP[offset|25]<<16 | HEAP[offset|26]<<8 | HEAP[offset|27], + HEAP[offset|28]<<24 | HEAP[offset|29]<<16 | HEAP[offset|30]<<8 | HEAP[offset|31], + HEAP[offset|32]<<24 | HEAP[offset|33]<<16 | HEAP[offset|34]<<8 | HEAP[offset|35], + HEAP[offset|36]<<24 | HEAP[offset|37]<<16 | HEAP[offset|38]<<8 | HEAP[offset|39], + HEAP[offset|40]<<24 | HEAP[offset|41]<<16 | HEAP[offset|42]<<8 | HEAP[offset|43], + HEAP[offset|44]<<24 | HEAP[offset|45]<<16 | HEAP[offset|46]<<8 | HEAP[offset|47], + HEAP[offset|48]<<24 | HEAP[offset|49]<<16 | HEAP[offset|50]<<8 | HEAP[offset|51], + HEAP[offset|52]<<24 | HEAP[offset|53]<<16 | HEAP[offset|54]<<8 | HEAP[offset|55], + HEAP[offset|56]<<24 | HEAP[offset|57]<<16 | HEAP[offset|58]<<8 | HEAP[offset|59], + HEAP[offset|60]<<24 | HEAP[offset|61]<<16 | HEAP[offset|62]<<8 | HEAP[offset|63] + ); + } + + // offset — multiple of 32 + function _state_to_heap ( output ) { + output = output|0; + + HEAP[output|0] = H0>>>24; + HEAP[output|1] = H0>>>16&255; + HEAP[output|2] = H0>>>8&255; + HEAP[output|3] = H0&255; + HEAP[output|4] = H1>>>24; + HEAP[output|5] = H1>>>16&255; + HEAP[output|6] = H1>>>8&255; + HEAP[output|7] = H1&255; + HEAP[output|8] = H2>>>24; + HEAP[output|9] = H2>>>16&255; + HEAP[output|10] = H2>>>8&255; + HEAP[output|11] = H2&255; + HEAP[output|12] = H3>>>24; + HEAP[output|13] = H3>>>16&255; + HEAP[output|14] = H3>>>8&255; + HEAP[output|15] = H3&255; + HEAP[output|16] = H4>>>24; + HEAP[output|17] = H4>>>16&255; + HEAP[output|18] = H4>>>8&255; + HEAP[output|19] = H4&255; + HEAP[output|20] = H5>>>24; + HEAP[output|21] = H5>>>16&255; + HEAP[output|22] = H5>>>8&255; + HEAP[output|23] = H5&255; + HEAP[output|24] = H6>>>24; + HEAP[output|25] = H6>>>16&255; + HEAP[output|26] = H6>>>8&255; + HEAP[output|27] = H6&255; + HEAP[output|28] = H7>>>24; + HEAP[output|29] = H7>>>16&255; + HEAP[output|30] = H7>>>8&255; + HEAP[output|31] = H7&255; + } + + function reset () { + H0 = 0x6a09e667; + H1 = 0xbb67ae85; + H2 = 0x3c6ef372; + H3 = 0xa54ff53a; + H4 = 0x510e527f; + H5 = 0x9b05688c; + H6 = 0x1f83d9ab; + H7 = 0x5be0cd19; + TOTAL0 = TOTAL1 = 0; + } + + function init ( h0, h1, h2, h3, h4, h5, h6, h7, total0, total1 ) { + h0 = h0|0; + h1 = h1|0; + h2 = h2|0; + h3 = h3|0; + h4 = h4|0; + h5 = h5|0; + h6 = h6|0; + h7 = h7|0; + total0 = total0|0; + total1 = total1|0; + + H0 = h0; + H1 = h1; + H2 = h2; + H3 = h3; + H4 = h4; + H5 = h5; + H6 = h6; + H7 = h7; + TOTAL0 = total0; + TOTAL1 = total1; + } + + // offset — multiple of 64 + function process ( offset, length ) { + offset = offset|0; + length = length|0; + + var hashed = 0; + + if ( offset & 63 ) + return -1; + + while ( (length|0) >= 64 ) { + _core_heap(offset); + + offset = ( offset + 64 )|0; + length = ( length - 64 )|0; + + hashed = ( hashed + 64 )|0; + } + + TOTAL0 = ( TOTAL0 + hashed )|0; + if ( TOTAL0>>>0 < hashed>>>0 ) TOTAL1 = ( TOTAL1 + 1 )|0; + + return hashed|0; + } + + // offset — multiple of 64 + // output — multiple of 32 + function finish ( offset, length, output ) { + offset = offset|0; + length = length|0; + output = output|0; + + var hashed = 0, + i = 0; + + if ( offset & 63 ) + return -1; + + if ( ~output ) + if ( output & 31 ) + return -1; + + if ( (length|0) >= 64 ) { + hashed = process( offset, length )|0; + if ( (hashed|0) == -1 ) + return -1; + + offset = ( offset + hashed )|0; + length = ( length - hashed )|0; + } + + hashed = ( hashed + length )|0; + TOTAL0 = ( TOTAL0 + length )|0; + if ( TOTAL0>>>0 < length>>>0 ) TOTAL1 = ( TOTAL1 + 1 )|0; + + HEAP[offset|length] = 0x80; + + if ( (length|0) >= 56 ) { + for ( i = (length+1)|0; (i|0) < 64; i = (i+1)|0 ) + HEAP[offset|i] = 0x00; + + _core_heap(offset); + + length = 0; + + HEAP[offset|0] = 0; + } + + for ( i = (length+1)|0; (i|0) < 59; i = (i+1)|0 ) + HEAP[offset|i] = 0; + + HEAP[offset|56] = TOTAL1>>>21&255; + HEAP[offset|57] = TOTAL1>>>13&255; + HEAP[offset|58] = TOTAL1>>>5&255; + HEAP[offset|59] = TOTAL1<<3&255 | TOTAL0>>>29; + HEAP[offset|60] = TOTAL0>>>21&255; + HEAP[offset|61] = TOTAL0>>>13&255; + HEAP[offset|62] = TOTAL0>>>5&255; + HEAP[offset|63] = TOTAL0<<3&255; + _core_heap(offset); + + if ( ~output ) + _state_to_heap(output); + + return hashed|0; + } + + function hmac_reset () { + H0 = I0; + H1 = I1; + H2 = I2; + H3 = I3; + H4 = I4; + H5 = I5; + H6 = I6; + H7 = I7; + TOTAL0 = 64; + TOTAL1 = 0; + } + + function _hmac_opad () { + H0 = O0; + H1 = O1; + H2 = O2; + H3 = O3; + H4 = O4; + H5 = O5; + H6 = O6; + H7 = O7; + TOTAL0 = 64; + TOTAL1 = 0; + } + + function hmac_init ( p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15 ) { + p0 = p0|0; + p1 = p1|0; + p2 = p2|0; + p3 = p3|0; + p4 = p4|0; + p5 = p5|0; + p6 = p6|0; + p7 = p7|0; + p8 = p8|0; + p9 = p9|0; + p10 = p10|0; + p11 = p11|0; + p12 = p12|0; + p13 = p13|0; + p14 = p14|0; + p15 = p15|0; + + // opad + reset(); + _core( + p0 ^ 0x5c5c5c5c, + p1 ^ 0x5c5c5c5c, + p2 ^ 0x5c5c5c5c, + p3 ^ 0x5c5c5c5c, + p4 ^ 0x5c5c5c5c, + p5 ^ 0x5c5c5c5c, + p6 ^ 0x5c5c5c5c, + p7 ^ 0x5c5c5c5c, + p8 ^ 0x5c5c5c5c, + p9 ^ 0x5c5c5c5c, + p10 ^ 0x5c5c5c5c, + p11 ^ 0x5c5c5c5c, + p12 ^ 0x5c5c5c5c, + p13 ^ 0x5c5c5c5c, + p14 ^ 0x5c5c5c5c, + p15 ^ 0x5c5c5c5c + ); + O0 = H0; + O1 = H1; + O2 = H2; + O3 = H3; + O4 = H4; + O5 = H5; + O6 = H6; + O7 = H7; + + // ipad + reset(); + _core( + p0 ^ 0x36363636, + p1 ^ 0x36363636, + p2 ^ 0x36363636, + p3 ^ 0x36363636, + p4 ^ 0x36363636, + p5 ^ 0x36363636, + p6 ^ 0x36363636, + p7 ^ 0x36363636, + p8 ^ 0x36363636, + p9 ^ 0x36363636, + p10 ^ 0x36363636, + p11 ^ 0x36363636, + p12 ^ 0x36363636, + p13 ^ 0x36363636, + p14 ^ 0x36363636, + p15 ^ 0x36363636 + ); + I0 = H0; + I1 = H1; + I2 = H2; + I3 = H3; + I4 = H4; + I5 = H5; + I6 = H6; + I7 = H7; + + TOTAL0 = 64; + TOTAL1 = 0; + } + + // offset — multiple of 64 + // output — multiple of 32 + function hmac_finish ( offset, length, output ) { + offset = offset|0; + length = length|0; + output = output|0; + + var t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0, + hashed = 0; + + if ( offset & 63 ) + return -1; + + if ( ~output ) + if ( output & 31 ) + return -1; + + hashed = finish( offset, length, -1 )|0; + t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; + + _hmac_opad(); + _core( t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768 ); + + if ( ~output ) + _state_to_heap(output); + + return hashed|0; + } + + // salt is assumed to be already processed + // offset — multiple of 64 + // output — multiple of 32 + function pbkdf2_generate_block ( offset, length, block, count, output ) { + offset = offset|0; + length = length|0; + block = block|0; + count = count|0; + output = output|0; + + var h0 = 0, h1 = 0, h2 = 0, h3 = 0, h4 = 0, h5 = 0, h6 = 0, h7 = 0, + t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0; + + if ( offset & 63 ) + return -1; + + if ( ~output ) + if ( output & 31 ) + return -1; + + // pad block number into heap + // FIXME probable OOB write + HEAP[(offset+length)|0] = block>>>24; + HEAP[(offset+length+1)|0] = block>>>16&255; + HEAP[(offset+length+2)|0] = block>>>8&255; + HEAP[(offset+length+3)|0] = block&255; + + // finish first iteration + hmac_finish( offset, (length+4)|0, -1 )|0; + h0 = t0 = H0, h1 = t1 = H1, h2 = t2 = H2, h3 = t3 = H3, h4 = t4 = H4, h5 = t5 = H5, h6 = t6 = H6, h7 = t7 = H7; + count = (count-1)|0; + + // perform the rest iterations + while ( (count|0) > 0 ) { + hmac_reset(); + _core( t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768 ); + t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; + + _hmac_opad(); + _core( t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768 ); + t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; + + h0 = h0 ^ H0; + h1 = h1 ^ H1; + h2 = h2 ^ H2; + h3 = h3 ^ H3; + h4 = h4 ^ H4; + h5 = h5 ^ H5; + h6 = h6 ^ H6; + h7 = h7 ^ H7; + + count = (count-1)|0; + } + + H0 = h0; + H1 = h1; + H2 = h2; + H3 = h3; + H4 = h4; + H5 = h5; + H6 = h6; + H7 = h7; + + if ( ~output ) + _state_to_heap(output); + + return 0; + } + + return { + // SHA256 + reset: reset, + init: init, + process: process, + finish: finish, + + // HMAC-SHA256 + hmac_reset: hmac_reset, + hmac_init: hmac_init, + hmac_finish: hmac_finish, + + // PBKDF2-HMAC-SHA256 + pbkdf2_generate_block: pbkdf2_generate_block + } + }; + + const _sha256_block_size = 64; + const _sha256_hash_size = 32; + const heap_pool$2 = []; + const asm_pool$2 = []; + class Sha256 extends Hash { + constructor() { + super(); + this.NAME = 'sha256'; + this.BLOCK_SIZE = _sha256_block_size; + this.HASH_SIZE = _sha256_hash_size; + this.acquire_asm(); + } + acquire_asm() { + if (this.heap === undefined || this.asm === undefined) { + this.heap = heap_pool$2.pop() || _heap_init(); + this.asm = asm_pool$2.pop() || sha256_asm({ Uint8Array: Uint8Array }, null, this.heap.buffer); + this.reset(); + } + return { heap: this.heap, asm: this.asm }; + } + release_asm() { + if (this.heap !== undefined && this.asm !== undefined) { + heap_pool$2.push(this.heap); + asm_pool$2.push(this.asm); + } + this.heap = undefined; + this.asm = undefined; + } + static bytes(data) { + return new Sha256().process(data).finish().result; + } + } + Sha256.NAME = 'sha256'; + + var minimalisticAssert = assert; + + function assert(val, msg) { + if (!val) + throw new Error(msg || 'Assertion failed'); + } + + assert.equal = function assertEqual(l, r, msg) { + if (l != r) + throw new Error(msg || ('Assertion failed: ' + l + ' != ' + r)); + }; + + var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + + function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; + } + + function commonjsRequire () { + throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs'); + } + + var inherits_browser = createCommonjsModule(function (module) { + if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor; + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; + } else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor; + var TempCtor = function () {}; + TempCtor.prototype = superCtor.prototype; + ctor.prototype = new TempCtor(); + ctor.prototype.constructor = ctor; + }; + } + }); + + var inherits_1 = inherits_browser; + + function toArray(msg, enc) { + if (Array.isArray(msg)) + return msg.slice(); + if (!msg) + return []; + var res = []; + if (typeof msg === 'string') { + if (!enc) { + for (var i = 0; i < msg.length; i++) { + var c = msg.charCodeAt(i); + var hi = c >> 8; + var lo = c & 0xff; + if (hi) + res.push(hi, lo); + else + res.push(lo); + } + } else if (enc === 'hex') { + msg = msg.replace(/[^a-z0-9]+/ig, ''); + if (msg.length % 2 !== 0) + msg = '0' + msg; + for (i = 0; i < msg.length; i += 2) + res.push(parseInt(msg[i] + msg[i + 1], 16)); + } + } else { + for (i = 0; i < msg.length; i++) + res[i] = msg[i] | 0; + } + return res; + } + var toArray_1 = toArray; + + function toHex(msg) { + var res = ''; + for (var i = 0; i < msg.length; i++) + res += zero2(msg[i].toString(16)); + return res; + } + var toHex_1 = toHex; + + function htonl(w) { + var res = (w >>> 24) | + ((w >>> 8) & 0xff00) | + ((w << 8) & 0xff0000) | + ((w & 0xff) << 24); + return res >>> 0; + } + var htonl_1 = htonl; + + function toHex32(msg, endian) { + var res = ''; + for (var i = 0; i < msg.length; i++) { + var w = msg[i]; + if (endian === 'little') + w = htonl(w); + res += zero8(w.toString(16)); + } + return res; + } + var toHex32_1 = toHex32; + + function zero2(word) { + if (word.length === 1) + return '0' + word; + else + return word; + } + var zero2_1 = zero2; + + function zero8(word) { + if (word.length === 7) + return '0' + word; + else if (word.length === 6) + return '00' + word; + else if (word.length === 5) + return '000' + word; + else if (word.length === 4) + return '0000' + word; + else if (word.length === 3) + return '00000' + word; + else if (word.length === 2) + return '000000' + word; + else if (word.length === 1) + return '0000000' + word; + else + return word; + } + var zero8_1 = zero8; + + function join32(msg, start, end, endian) { + var len = end - start; + minimalisticAssert(len % 4 === 0); + var res = new Array(len / 4); + for (var i = 0, k = start; i < res.length; i++, k += 4) { + var w; + if (endian === 'big') + w = (msg[k] << 24) | (msg[k + 1] << 16) | (msg[k + 2] << 8) | msg[k + 3]; + else + w = (msg[k + 3] << 24) | (msg[k + 2] << 16) | (msg[k + 1] << 8) | msg[k]; + res[i] = w >>> 0; + } + return res; + } + var join32_1 = join32; + + function split32(msg, endian) { + var res = new Array(msg.length * 4); + for (var i = 0, k = 0; i < msg.length; i++, k += 4) { + var m = msg[i]; + if (endian === 'big') { + res[k] = m >>> 24; + res[k + 1] = (m >>> 16) & 0xff; + res[k + 2] = (m >>> 8) & 0xff; + res[k + 3] = m & 0xff; + } else { + res[k + 3] = m >>> 24; + res[k + 2] = (m >>> 16) & 0xff; + res[k + 1] = (m >>> 8) & 0xff; + res[k] = m & 0xff; + } + } + return res; + } + var split32_1 = split32; + + function rotr32(w, b) { + return (w >>> b) | (w << (32 - b)); + } + var rotr32_1 = rotr32; + + function rotl32(w, b) { + return (w << b) | (w >>> (32 - b)); + } + var rotl32_1 = rotl32; + + function sum32(a, b) { + return (a + b) >>> 0; + } + var sum32_1 = sum32; + + function sum32_3(a, b, c) { + return (a + b + c) >>> 0; + } + var sum32_3_1 = sum32_3; + + function sum32_4(a, b, c, d) { + return (a + b + c + d) >>> 0; + } + var sum32_4_1 = sum32_4; + + function sum32_5(a, b, c, d, e) { + return (a + b + c + d + e) >>> 0; + } + var sum32_5_1 = sum32_5; + + function sum64(buf, pos, ah, al) { + var bh = buf[pos]; + var bl = buf[pos + 1]; + + var lo = (al + bl) >>> 0; + var hi = (lo < al ? 1 : 0) + ah + bh; + buf[pos] = hi >>> 0; + buf[pos + 1] = lo; + } + var sum64_1 = sum64; + + function sum64_hi(ah, al, bh, bl) { + var lo = (al + bl) >>> 0; + var hi = (lo < al ? 1 : 0) + ah + bh; + return hi >>> 0; + } + var sum64_hi_1 = sum64_hi; + + function sum64_lo(ah, al, bh, bl) { + var lo = al + bl; + return lo >>> 0; + } + var sum64_lo_1 = sum64_lo; + + function sum64_4_hi(ah, al, bh, bl, ch, cl, dh, dl) { + var carry = 0; + var lo = al; + lo = (lo + bl) >>> 0; + carry += lo < al ? 1 : 0; + lo = (lo + cl) >>> 0; + carry += lo < cl ? 1 : 0; + lo = (lo + dl) >>> 0; + carry += lo < dl ? 1 : 0; + + var hi = ah + bh + ch + dh + carry; + return hi >>> 0; + } + var sum64_4_hi_1 = sum64_4_hi; + + function sum64_4_lo(ah, al, bh, bl, ch, cl, dh, dl) { + var lo = al + bl + cl + dl; + return lo >>> 0; + } + var sum64_4_lo_1 = sum64_4_lo; + + function sum64_5_hi(ah, al, bh, bl, ch, cl, dh, dl, eh, el) { + var carry = 0; + var lo = al; + lo = (lo + bl) >>> 0; + carry += lo < al ? 1 : 0; + lo = (lo + cl) >>> 0; + carry += lo < cl ? 1 : 0; + lo = (lo + dl) >>> 0; + carry += lo < dl ? 1 : 0; + lo = (lo + el) >>> 0; + carry += lo < el ? 1 : 0; + + var hi = ah + bh + ch + dh + eh + carry; + return hi >>> 0; + } + var sum64_5_hi_1 = sum64_5_hi; + + function sum64_5_lo(ah, al, bh, bl, ch, cl, dh, dl, eh, el) { + var lo = al + bl + cl + dl + el; + + return lo >>> 0; + } + var sum64_5_lo_1 = sum64_5_lo; + + function rotr64_hi(ah, al, num) { + var r = (al << (32 - num)) | (ah >>> num); + return r >>> 0; + } + var rotr64_hi_1 = rotr64_hi; + + function rotr64_lo(ah, al, num) { + var r = (ah << (32 - num)) | (al >>> num); + return r >>> 0; + } + var rotr64_lo_1 = rotr64_lo; + + function shr64_hi(ah, al, num) { + return ah >>> num; + } + var shr64_hi_1 = shr64_hi; + + function shr64_lo(ah, al, num) { + var r = (ah << (32 - num)) | (al >>> num); + return r >>> 0; + } + var shr64_lo_1 = shr64_lo; + + var utils = { + inherits: inherits_1, + toArray: toArray_1, + toHex: toHex_1, + htonl: htonl_1, + toHex32: toHex32_1, + zero2: zero2_1, + zero8: zero8_1, + join32: join32_1, + split32: split32_1, + rotr32: rotr32_1, + rotl32: rotl32_1, + sum32: sum32_1, + sum32_3: sum32_3_1, + sum32_4: sum32_4_1, + sum32_5: sum32_5_1, + sum64: sum64_1, + sum64_hi: sum64_hi_1, + sum64_lo: sum64_lo_1, + sum64_4_hi: sum64_4_hi_1, + sum64_4_lo: sum64_4_lo_1, + sum64_5_hi: sum64_5_hi_1, + sum64_5_lo: sum64_5_lo_1, + rotr64_hi: rotr64_hi_1, + rotr64_lo: rotr64_lo_1, + shr64_hi: shr64_hi_1, + shr64_lo: shr64_lo_1 + }; + + function BlockHash() { + this.pending = null; + this.pendingTotal = 0; + this.blockSize = this.constructor.blockSize; + this.outSize = this.constructor.outSize; + this.hmacStrength = this.constructor.hmacStrength; + this.padLength = this.constructor.padLength / 8; + this.endian = 'big'; + + this._delta8 = this.blockSize / 8; + this._delta32 = this.blockSize / 32; + } + var BlockHash_1 = BlockHash; + + BlockHash.prototype.update = function update(msg, enc) { + // Convert message to array, pad it, and join into 32bit blocks + msg = utils.toArray(msg, enc); + if (!this.pending) + this.pending = msg; + else + this.pending = this.pending.concat(msg); + this.pendingTotal += msg.length; + + // Enough data, try updating + if (this.pending.length >= this._delta8) { + msg = this.pending; + + // Process pending data in blocks + var r = msg.length % this._delta8; + this.pending = msg.slice(msg.length - r, msg.length); + if (this.pending.length === 0) + this.pending = null; + + msg = utils.join32(msg, 0, msg.length - r, this.endian); + for (var i = 0; i < msg.length; i += this._delta32) + this._update(msg, i, i + this._delta32); + } + + return this; + }; + + BlockHash.prototype.digest = function digest(enc) { + this.update(this._pad()); + minimalisticAssert(this.pending === null); + + return this._digest(enc); + }; + + BlockHash.prototype._pad = function pad() { + var len = this.pendingTotal; + var bytes = this._delta8; + var k = bytes - ((len + this.padLength) % bytes); + var res = new Array(k + this.padLength); + res[0] = 0x80; + for (var i = 1; i < k; i++) + res[i] = 0; + + // Append length + len <<= 3; + if (this.endian === 'big') { + for (var t = 8; t < this.padLength; t++) + res[i++] = 0; + + res[i++] = 0; + res[i++] = 0; + res[i++] = 0; + res[i++] = 0; + res[i++] = (len >>> 24) & 0xff; + res[i++] = (len >>> 16) & 0xff; + res[i++] = (len >>> 8) & 0xff; + res[i++] = len & 0xff; + } else { + res[i++] = len & 0xff; + res[i++] = (len >>> 8) & 0xff; + res[i++] = (len >>> 16) & 0xff; + res[i++] = (len >>> 24) & 0xff; + res[i++] = 0; + res[i++] = 0; + res[i++] = 0; + res[i++] = 0; + + for (t = 8; t < this.padLength; t++) + res[i++] = 0; + } + + return res; + }; + + var common = { + BlockHash: BlockHash_1 + }; + + var rotr32$1 = utils.rotr32; + + function ft_1(s, x, y, z) { + if (s === 0) + return ch32(x, y, z); + if (s === 1 || s === 3) + return p32(x, y, z); + if (s === 2) + return maj32(x, y, z); + } + var ft_1_1 = ft_1; + + function ch32(x, y, z) { + return (x & y) ^ ((~x) & z); + } + var ch32_1 = ch32; + + function maj32(x, y, z) { + return (x & y) ^ (x & z) ^ (y & z); + } + var maj32_1 = maj32; + + function p32(x, y, z) { + return x ^ y ^ z; + } + var p32_1 = p32; + + function s0_256(x) { + return rotr32$1(x, 2) ^ rotr32$1(x, 13) ^ rotr32$1(x, 22); + } + var s0_256_1 = s0_256; + + function s1_256(x) { + return rotr32$1(x, 6) ^ rotr32$1(x, 11) ^ rotr32$1(x, 25); + } + var s1_256_1 = s1_256; + + function g0_256(x) { + return rotr32$1(x, 7) ^ rotr32$1(x, 18) ^ (x >>> 3); + } + var g0_256_1 = g0_256; + + function g1_256(x) { + return rotr32$1(x, 17) ^ rotr32$1(x, 19) ^ (x >>> 10); + } + var g1_256_1 = g1_256; + + var common$1 = { + ft_1: ft_1_1, + ch32: ch32_1, + maj32: maj32_1, + p32: p32_1, + s0_256: s0_256_1, + s1_256: s1_256_1, + g0_256: g0_256_1, + g1_256: g1_256_1 + }; + + var sum32$1 = utils.sum32; + var sum32_4$1 = utils.sum32_4; + var sum32_5$1 = utils.sum32_5; + var ch32$1 = common$1.ch32; + var maj32$1 = common$1.maj32; + var s0_256$1 = common$1.s0_256; + var s1_256$1 = common$1.s1_256; + var g0_256$1 = common$1.g0_256; + var g1_256$1 = common$1.g1_256; + + var BlockHash$1 = common.BlockHash; + + var sha256_K = [ + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 + ]; + + function SHA256() { + if (!(this instanceof SHA256)) + return new SHA256(); + + BlockHash$1.call(this); + this.h = [ + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 + ]; + this.k = sha256_K; + this.W = new Array(64); + } + utils.inherits(SHA256, BlockHash$1); + var _256 = SHA256; + + SHA256.blockSize = 512; + SHA256.outSize = 256; + SHA256.hmacStrength = 192; + SHA256.padLength = 64; + + SHA256.prototype._update = function _update(msg, start) { + var W = this.W; + + for (var i = 0; i < 16; i++) + W[i] = msg[start + i]; + for (; i < W.length; i++) + W[i] = sum32_4$1(g1_256$1(W[i - 2]), W[i - 7], g0_256$1(W[i - 15]), W[i - 16]); + + var a = this.h[0]; + var b = this.h[1]; + var c = this.h[2]; + var d = this.h[3]; + var e = this.h[4]; + var f = this.h[5]; + var g = this.h[6]; + var h = this.h[7]; + + minimalisticAssert(this.k.length === W.length); + for (i = 0; i < W.length; i++) { + var T1 = sum32_5$1(h, s1_256$1(e), ch32$1(e, f, g), this.k[i], W[i]); + var T2 = sum32$1(s0_256$1(a), maj32$1(a, b, c)); + h = g; + g = f; + f = e; + e = sum32$1(d, T1); + d = c; + c = b; + b = a; + a = sum32$1(T1, T2); + } + + this.h[0] = sum32$1(this.h[0], a); + this.h[1] = sum32$1(this.h[1], b); + this.h[2] = sum32$1(this.h[2], c); + this.h[3] = sum32$1(this.h[3], d); + this.h[4] = sum32$1(this.h[4], e); + this.h[5] = sum32$1(this.h[5], f); + this.h[6] = sum32$1(this.h[6], g); + this.h[7] = sum32$1(this.h[7], h); + }; + + SHA256.prototype._digest = function digest(enc) { + if (enc === 'hex') + return utils.toHex32(this.h, 'big'); + else + return utils.split32(this.h, 'big'); + }; + + function SHA224() { + if (!(this instanceof SHA224)) + return new SHA224(); + + _256.call(this); + this.h = [ + 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, + 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 ]; + } + utils.inherits(SHA224, _256); + var _224 = SHA224; + + SHA224.blockSize = 512; + SHA224.outSize = 224; + SHA224.hmacStrength = 192; + SHA224.padLength = 64; + + SHA224.prototype._digest = function digest(enc) { + // Just truncate output + if (enc === 'hex') + return utils.toHex32(this.h.slice(0, 7), 'big'); + else + return utils.split32(this.h.slice(0, 7), 'big'); + }; + + var rotr64_hi$1 = utils.rotr64_hi; + var rotr64_lo$1 = utils.rotr64_lo; + var shr64_hi$1 = utils.shr64_hi; + var shr64_lo$1 = utils.shr64_lo; + var sum64$1 = utils.sum64; + var sum64_hi$1 = utils.sum64_hi; + var sum64_lo$1 = utils.sum64_lo; + var sum64_4_hi$1 = utils.sum64_4_hi; + var sum64_4_lo$1 = utils.sum64_4_lo; + var sum64_5_hi$1 = utils.sum64_5_hi; + var sum64_5_lo$1 = utils.sum64_5_lo; + + var BlockHash$2 = common.BlockHash; + + var sha512_K = [ + 0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd, + 0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc, + 0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019, + 0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118, + 0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe, + 0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2, + 0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1, + 0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694, + 0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3, + 0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65, + 0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483, + 0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5, + 0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210, + 0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4, + 0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725, + 0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70, + 0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926, + 0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df, + 0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8, + 0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b, + 0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001, + 0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30, + 0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910, + 0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8, + 0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53, + 0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8, + 0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb, + 0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3, + 0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60, + 0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec, + 0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9, + 0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b, + 0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207, + 0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178, + 0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6, + 0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b, + 0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493, + 0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c, + 0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a, + 0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817 + ]; + + function SHA512() { + if (!(this instanceof SHA512)) + return new SHA512(); + + BlockHash$2.call(this); + this.h = [ + 0x6a09e667, 0xf3bcc908, + 0xbb67ae85, 0x84caa73b, + 0x3c6ef372, 0xfe94f82b, + 0xa54ff53a, 0x5f1d36f1, + 0x510e527f, 0xade682d1, + 0x9b05688c, 0x2b3e6c1f, + 0x1f83d9ab, 0xfb41bd6b, + 0x5be0cd19, 0x137e2179 ]; + this.k = sha512_K; + this.W = new Array(160); + } + utils.inherits(SHA512, BlockHash$2); + var _512 = SHA512; + + SHA512.blockSize = 1024; + SHA512.outSize = 512; + SHA512.hmacStrength = 192; + SHA512.padLength = 128; + + SHA512.prototype._prepareBlock = function _prepareBlock(msg, start) { + var W = this.W; + + // 32 x 32bit words + for (var i = 0; i < 32; i++) + W[i] = msg[start + i]; + for (; i < W.length; i += 2) { + var c0_hi = g1_512_hi(W[i - 4], W[i - 3]); // i - 2 + var c0_lo = g1_512_lo(W[i - 4], W[i - 3]); + var c1_hi = W[i - 14]; // i - 7 + var c1_lo = W[i - 13]; + var c2_hi = g0_512_hi(W[i - 30], W[i - 29]); // i - 15 + var c2_lo = g0_512_lo(W[i - 30], W[i - 29]); + var c3_hi = W[i - 32]; // i - 16 + var c3_lo = W[i - 31]; + + W[i] = sum64_4_hi$1( + c0_hi, c0_lo, + c1_hi, c1_lo, + c2_hi, c2_lo, + c3_hi, c3_lo); + W[i + 1] = sum64_4_lo$1( + c0_hi, c0_lo, + c1_hi, c1_lo, + c2_hi, c2_lo, + c3_hi, c3_lo); + } + }; + + SHA512.prototype._update = function _update(msg, start) { + this._prepareBlock(msg, start); + + var W = this.W; + + var ah = this.h[0]; + var al = this.h[1]; + var bh = this.h[2]; + var bl = this.h[3]; + var ch = this.h[4]; + var cl = this.h[5]; + var dh = this.h[6]; + var dl = this.h[7]; + var eh = this.h[8]; + var el = this.h[9]; + var fh = this.h[10]; + var fl = this.h[11]; + var gh = this.h[12]; + var gl = this.h[13]; + var hh = this.h[14]; + var hl = this.h[15]; + + minimalisticAssert(this.k.length === W.length); + for (var i = 0; i < W.length; i += 2) { + var c0_hi = hh; + var c0_lo = hl; + var c1_hi = s1_512_hi(eh, el); + var c1_lo = s1_512_lo(eh, el); + var c2_hi = ch64_hi(eh, el, fh, fl, gh); + var c2_lo = ch64_lo(eh, el, fh, fl, gh, gl); + var c3_hi = this.k[i]; + var c3_lo = this.k[i + 1]; + var c4_hi = W[i]; + var c4_lo = W[i + 1]; + + var T1_hi = sum64_5_hi$1( + c0_hi, c0_lo, + c1_hi, c1_lo, + c2_hi, c2_lo, + c3_hi, c3_lo, + c4_hi, c4_lo); + var T1_lo = sum64_5_lo$1( + c0_hi, c0_lo, + c1_hi, c1_lo, + c2_hi, c2_lo, + c3_hi, c3_lo, + c4_hi, c4_lo); + + c0_hi = s0_512_hi(ah, al); + c0_lo = s0_512_lo(ah, al); + c1_hi = maj64_hi(ah, al, bh, bl, ch); + c1_lo = maj64_lo(ah, al, bh, bl, ch, cl); + + var T2_hi = sum64_hi$1(c0_hi, c0_lo, c1_hi, c1_lo); + var T2_lo = sum64_lo$1(c0_hi, c0_lo, c1_hi, c1_lo); + + hh = gh; + hl = gl; + + gh = fh; + gl = fl; + + fh = eh; + fl = el; + + eh = sum64_hi$1(dh, dl, T1_hi, T1_lo); + el = sum64_lo$1(dl, dl, T1_hi, T1_lo); + + dh = ch; + dl = cl; + + ch = bh; + cl = bl; + + bh = ah; + bl = al; + + ah = sum64_hi$1(T1_hi, T1_lo, T2_hi, T2_lo); + al = sum64_lo$1(T1_hi, T1_lo, T2_hi, T2_lo); + } + + sum64$1(this.h, 0, ah, al); + sum64$1(this.h, 2, bh, bl); + sum64$1(this.h, 4, ch, cl); + sum64$1(this.h, 6, dh, dl); + sum64$1(this.h, 8, eh, el); + sum64$1(this.h, 10, fh, fl); + sum64$1(this.h, 12, gh, gl); + sum64$1(this.h, 14, hh, hl); + }; + + SHA512.prototype._digest = function digest(enc) { + if (enc === 'hex') + return utils.toHex32(this.h, 'big'); + else + return utils.split32(this.h, 'big'); + }; + + function ch64_hi(xh, xl, yh, yl, zh) { + var r = (xh & yh) ^ ((~xh) & zh); + if (r < 0) + r += 0x100000000; + return r; + } + + function ch64_lo(xh, xl, yh, yl, zh, zl) { + var r = (xl & yl) ^ ((~xl) & zl); + if (r < 0) + r += 0x100000000; + return r; + } + + function maj64_hi(xh, xl, yh, yl, zh) { + var r = (xh & yh) ^ (xh & zh) ^ (yh & zh); + if (r < 0) + r += 0x100000000; + return r; + } + + function maj64_lo(xh, xl, yh, yl, zh, zl) { + var r = (xl & yl) ^ (xl & zl) ^ (yl & zl); + if (r < 0) + r += 0x100000000; + return r; + } + + function s0_512_hi(xh, xl) { + var c0_hi = rotr64_hi$1(xh, xl, 28); + var c1_hi = rotr64_hi$1(xl, xh, 2); // 34 + var c2_hi = rotr64_hi$1(xl, xh, 7); // 39 + + var r = c0_hi ^ c1_hi ^ c2_hi; + if (r < 0) + r += 0x100000000; + return r; + } + + function s0_512_lo(xh, xl) { + var c0_lo = rotr64_lo$1(xh, xl, 28); + var c1_lo = rotr64_lo$1(xl, xh, 2); // 34 + var c2_lo = rotr64_lo$1(xl, xh, 7); // 39 + + var r = c0_lo ^ c1_lo ^ c2_lo; + if (r < 0) + r += 0x100000000; + return r; + } + + function s1_512_hi(xh, xl) { + var c0_hi = rotr64_hi$1(xh, xl, 14); + var c1_hi = rotr64_hi$1(xh, xl, 18); + var c2_hi = rotr64_hi$1(xl, xh, 9); // 41 + + var r = c0_hi ^ c1_hi ^ c2_hi; + if (r < 0) + r += 0x100000000; + return r; + } + + function s1_512_lo(xh, xl) { + var c0_lo = rotr64_lo$1(xh, xl, 14); + var c1_lo = rotr64_lo$1(xh, xl, 18); + var c2_lo = rotr64_lo$1(xl, xh, 9); // 41 + + var r = c0_lo ^ c1_lo ^ c2_lo; + if (r < 0) + r += 0x100000000; + return r; + } + + function g0_512_hi(xh, xl) { + var c0_hi = rotr64_hi$1(xh, xl, 1); + var c1_hi = rotr64_hi$1(xh, xl, 8); + var c2_hi = shr64_hi$1(xh, xl, 7); + + var r = c0_hi ^ c1_hi ^ c2_hi; + if (r < 0) + r += 0x100000000; + return r; + } + + function g0_512_lo(xh, xl) { + var c0_lo = rotr64_lo$1(xh, xl, 1); + var c1_lo = rotr64_lo$1(xh, xl, 8); + var c2_lo = shr64_lo$1(xh, xl, 7); + + var r = c0_lo ^ c1_lo ^ c2_lo; + if (r < 0) + r += 0x100000000; + return r; + } + + function g1_512_hi(xh, xl) { + var c0_hi = rotr64_hi$1(xh, xl, 19); + var c1_hi = rotr64_hi$1(xl, xh, 29); // 61 + var c2_hi = shr64_hi$1(xh, xl, 6); + + var r = c0_hi ^ c1_hi ^ c2_hi; + if (r < 0) + r += 0x100000000; + return r; + } + + function g1_512_lo(xh, xl) { + var c0_lo = rotr64_lo$1(xh, xl, 19); + var c1_lo = rotr64_lo$1(xl, xh, 29); // 61 + var c2_lo = shr64_lo$1(xh, xl, 6); + + var r = c0_lo ^ c1_lo ^ c2_lo; + if (r < 0) + r += 0x100000000; + return r; + } + + function SHA384() { + if (!(this instanceof SHA384)) + return new SHA384(); + + _512.call(this); + this.h = [ + 0xcbbb9d5d, 0xc1059ed8, + 0x629a292a, 0x367cd507, + 0x9159015a, 0x3070dd17, + 0x152fecd8, 0xf70e5939, + 0x67332667, 0xffc00b31, + 0x8eb44a87, 0x68581511, + 0xdb0c2e0d, 0x64f98fa7, + 0x47b5481d, 0xbefa4fa4 ]; + } + utils.inherits(SHA384, _512); + var _384 = SHA384; + + SHA384.blockSize = 1024; + SHA384.outSize = 384; + SHA384.hmacStrength = 192; + SHA384.padLength = 128; + + SHA384.prototype._digest = function digest(enc) { + if (enc === 'hex') + return utils.toHex32(this.h.slice(0, 12), 'big'); + else + return utils.split32(this.h.slice(0, 12), 'big'); + }; + + var rotl32$1 = utils.rotl32; + var sum32$2 = utils.sum32; + var sum32_3$1 = utils.sum32_3; + var sum32_4$2 = utils.sum32_4; + var BlockHash$3 = common.BlockHash; + + function RIPEMD160() { + if (!(this instanceof RIPEMD160)) + return new RIPEMD160(); + + BlockHash$3.call(this); + + this.h = [ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 ]; + this.endian = 'little'; + } + utils.inherits(RIPEMD160, BlockHash$3); + var ripemd160 = RIPEMD160; + + RIPEMD160.blockSize = 512; + RIPEMD160.outSize = 160; + RIPEMD160.hmacStrength = 192; + RIPEMD160.padLength = 64; + + RIPEMD160.prototype._update = function update(msg, start) { + var A = this.h[0]; + var B = this.h[1]; + var C = this.h[2]; + var D = this.h[3]; + var E = this.h[4]; + var Ah = A; + var Bh = B; + var Ch = C; + var Dh = D; + var Eh = E; + for (var j = 0; j < 80; j++) { + var T = sum32$2( + rotl32$1( + sum32_4$2(A, f(j, B, C, D), msg[r[j] + start], K(j)), + s[j]), + E); + A = E; + E = D; + D = rotl32$1(C, 10); + C = B; + B = T; + T = sum32$2( + rotl32$1( + sum32_4$2(Ah, f(79 - j, Bh, Ch, Dh), msg[rh[j] + start], Kh(j)), + sh[j]), + Eh); + Ah = Eh; + Eh = Dh; + Dh = rotl32$1(Ch, 10); + Ch = Bh; + Bh = T; + } + T = sum32_3$1(this.h[1], C, Dh); + this.h[1] = sum32_3$1(this.h[2], D, Eh); + this.h[2] = sum32_3$1(this.h[3], E, Ah); + this.h[3] = sum32_3$1(this.h[4], A, Bh); + this.h[4] = sum32_3$1(this.h[0], B, Ch); + this.h[0] = T; + }; + + RIPEMD160.prototype._digest = function digest(enc) { + if (enc === 'hex') + return utils.toHex32(this.h, 'little'); + else + return utils.split32(this.h, 'little'); + }; + + function f(j, x, y, z) { + if (j <= 15) + return x ^ y ^ z; + else if (j <= 31) + return (x & y) | ((~x) & z); + else if (j <= 47) + return (x | (~y)) ^ z; + else if (j <= 63) + return (x & z) | (y & (~z)); + else + return x ^ (y | (~z)); + } + + function K(j) { + if (j <= 15) + return 0x00000000; + else if (j <= 31) + return 0x5a827999; + else if (j <= 47) + return 0x6ed9eba1; + else if (j <= 63) + return 0x8f1bbcdc; + else + return 0xa953fd4e; + } + + function Kh(j) { + if (j <= 15) + return 0x50a28be6; + else if (j <= 31) + return 0x5c4dd124; + else if (j <= 47) + return 0x6d703ef3; + else if (j <= 63) + return 0x7a6d76e9; + else + return 0x00000000; + } + + var r = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, + 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, + 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, + 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 + ]; + + var rh = [ + 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, + 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, + 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, + 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, + 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 + ]; + + var s = [ + 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, + 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, + 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, + 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, + 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 + ]; + + var sh = [ + 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, + 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, + 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, + 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, + 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 + ]; + + var ripemd = { + ripemd160: ripemd160 + }; + + /** + * A fast MD5 JavaScript implementation + * Copyright (c) 2012 Joseph Myers + * http://www.myersdaily.org/joseph/javascript/md5-text.html + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purposes and without + * fee is hereby granted provided that this copyright notice + * appears in all copies. + * + * Of course, this soft is provided "as is" without express or implied + * warranty of any kind. + */ + + // MD5 Digest + async function md5(entree) { + const digest = md51(util.uint8ArrayToString(entree)); + return util.hexToUint8Array(hex(digest)); + } + + function md5cycle(x, k) { + let a = x[0]; + let b = x[1]; + let c = x[2]; + let d = x[3]; + + a = ff(a, b, c, d, k[0], 7, -680876936); + d = ff(d, a, b, c, k[1], 12, -389564586); + c = ff(c, d, a, b, k[2], 17, 606105819); + b = ff(b, c, d, a, k[3], 22, -1044525330); + a = ff(a, b, c, d, k[4], 7, -176418897); + d = ff(d, a, b, c, k[5], 12, 1200080426); + c = ff(c, d, a, b, k[6], 17, -1473231341); + b = ff(b, c, d, a, k[7], 22, -45705983); + a = ff(a, b, c, d, k[8], 7, 1770035416); + d = ff(d, a, b, c, k[9], 12, -1958414417); + c = ff(c, d, a, b, k[10], 17, -42063); + b = ff(b, c, d, a, k[11], 22, -1990404162); + a = ff(a, b, c, d, k[12], 7, 1804603682); + d = ff(d, a, b, c, k[13], 12, -40341101); + c = ff(c, d, a, b, k[14], 17, -1502002290); + b = ff(b, c, d, a, k[15], 22, 1236535329); + + a = gg(a, b, c, d, k[1], 5, -165796510); + d = gg(d, a, b, c, k[6], 9, -1069501632); + c = gg(c, d, a, b, k[11], 14, 643717713); + b = gg(b, c, d, a, k[0], 20, -373897302); + a = gg(a, b, c, d, k[5], 5, -701558691); + d = gg(d, a, b, c, k[10], 9, 38016083); + c = gg(c, d, a, b, k[15], 14, -660478335); + b = gg(b, c, d, a, k[4], 20, -405537848); + a = gg(a, b, c, d, k[9], 5, 568446438); + d = gg(d, a, b, c, k[14], 9, -1019803690); + c = gg(c, d, a, b, k[3], 14, -187363961); + b = gg(b, c, d, a, k[8], 20, 1163531501); + a = gg(a, b, c, d, k[13], 5, -1444681467); + d = gg(d, a, b, c, k[2], 9, -51403784); + c = gg(c, d, a, b, k[7], 14, 1735328473); + b = gg(b, c, d, a, k[12], 20, -1926607734); + + a = hh(a, b, c, d, k[5], 4, -378558); + d = hh(d, a, b, c, k[8], 11, -2022574463); + c = hh(c, d, a, b, k[11], 16, 1839030562); + b = hh(b, c, d, a, k[14], 23, -35309556); + a = hh(a, b, c, d, k[1], 4, -1530992060); + d = hh(d, a, b, c, k[4], 11, 1272893353); + c = hh(c, d, a, b, k[7], 16, -155497632); + b = hh(b, c, d, a, k[10], 23, -1094730640); + a = hh(a, b, c, d, k[13], 4, 681279174); + d = hh(d, a, b, c, k[0], 11, -358537222); + c = hh(c, d, a, b, k[3], 16, -722521979); + b = hh(b, c, d, a, k[6], 23, 76029189); + a = hh(a, b, c, d, k[9], 4, -640364487); + d = hh(d, a, b, c, k[12], 11, -421815835); + c = hh(c, d, a, b, k[15], 16, 530742520); + b = hh(b, c, d, a, k[2], 23, -995338651); + + a = ii(a, b, c, d, k[0], 6, -198630844); + d = ii(d, a, b, c, k[7], 10, 1126891415); + c = ii(c, d, a, b, k[14], 15, -1416354905); + b = ii(b, c, d, a, k[5], 21, -57434055); + a = ii(a, b, c, d, k[12], 6, 1700485571); + d = ii(d, a, b, c, k[3], 10, -1894986606); + c = ii(c, d, a, b, k[10], 15, -1051523); + b = ii(b, c, d, a, k[1], 21, -2054922799); + a = ii(a, b, c, d, k[8], 6, 1873313359); + d = ii(d, a, b, c, k[15], 10, -30611744); + c = ii(c, d, a, b, k[6], 15, -1560198380); + b = ii(b, c, d, a, k[13], 21, 1309151649); + a = ii(a, b, c, d, k[4], 6, -145523070); + d = ii(d, a, b, c, k[11], 10, -1120210379); + c = ii(c, d, a, b, k[2], 15, 718787259); + b = ii(b, c, d, a, k[9], 21, -343485551); + + x[0] = add32(a, x[0]); + x[1] = add32(b, x[1]); + x[2] = add32(c, x[2]); + x[3] = add32(d, x[3]); + } + + function cmn(q, a, b, x, s, t) { + a = add32(add32(a, q), add32(x, t)); + return add32((a << s) | (a >>> (32 - s)), b); + } + + function ff(a, b, c, d, x, s, t) { + return cmn((b & c) | ((~b) & d), a, b, x, s, t); + } + + function gg(a, b, c, d, x, s, t) { + return cmn((b & d) | (c & (~d)), a, b, x, s, t); + } + + function hh(a, b, c, d, x, s, t) { + return cmn(b ^ c ^ d, a, b, x, s, t); + } + + function ii(a, b, c, d, x, s, t) { + return cmn(c ^ (b | (~d)), a, b, x, s, t); + } + + function md51(s) { + const n = s.length; + const state = [1732584193, -271733879, -1732584194, 271733878]; + let i; + for (i = 64; i <= s.length; i += 64) { + md5cycle(state, md5blk(s.substring(i - 64, i))); + } + s = s.substring(i - 64); + const tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + for (i = 0; i < s.length; i++) { + tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3); + } + tail[i >> 2] |= 0x80 << ((i % 4) << 3); + if (i > 55) { + md5cycle(state, tail); + for (i = 0; i < 16; i++) { + tail[i] = 0; + } + } + tail[14] = n * 8; + md5cycle(state, tail); + return state; + } + + /* there needs to be support for Unicode here, + * unless we pretend that we can redefine the MD-5 + * algorithm for multi-byte characters (perhaps + * by adding every four 16-bit characters and + * shortening the sum to 32 bits). Otherwise + * I suggest performing MD-5 as if every character + * was two bytes--e.g., 0040 0025 = @%--but then + * how will an ordinary MD-5 sum be matched? + * There is no way to standardize text to something + * like UTF-8 before transformation; speed cost is + * utterly prohibitive. The JavaScript standard + * itself needs to look at this: it should start + * providing access to strings as preformed UTF-8 + * 8-bit unsigned value arrays. + */ + function md5blk(s) { /* I figured global was faster. */ + const md5blks = []; + let i; /* Andy King said do it this way. */ + for (i = 0; i < 64; i += 4) { + md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << + 24); + } + return md5blks; + } + + const hex_chr = '0123456789abcdef'.split(''); + + function rhex(n) { + let s = ''; + let j = 0; + for (; j < 4; j++) { + s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F]; + } + return s; + } + + function hex(x) { + for (let i = 0; i < x.length; i++) { + x[i] = rhex(x[i]); + } + return x.join(''); + } + + /* this function is much faster, + so if possible we use it. Some IEs + are the only ones I know of that + need the idiotic second function, + generated by an if clause. */ + + function add32(a, b) { + return (a + b) & 0xFFFFFFFF; + } + + /** + * @fileoverview Provides an interface to hashing functions available in Node.js or external libraries. + * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} + * @see {@link https://github.com/indutny/hash.js|hash.js} + * @module crypto/hash + * @private + */ + + const webCrypto = util.getWebCrypto(); + const nodeCrypto = util.getNodeCrypto(); + + function nodeHash(type) { + return async function (data) { + const shasum = nodeCrypto.createHash(type); + return transform(data, value => { + shasum.update(value); + }, () => new Uint8Array(shasum.digest())); + }; + } + + function hashjsHash(hash, webCryptoHash) { + return async function(data, config = defaultConfig) { + if (isArrayStream(data)) { + data = await readToEnd(data); + } + if (!util.isStream(data) && webCrypto && webCryptoHash && data.length >= config.minBytesForWebCrypto) { + return new Uint8Array(await webCrypto.digest(webCryptoHash, data)); + } + const hashInstance = hash(); + return transform(data, value => { + hashInstance.update(value); + }, () => new Uint8Array(hashInstance.digest())); + }; + } + + function asmcryptoHash(hash, webCryptoHash) { + return async function(data, config = defaultConfig) { + if (isArrayStream(data)) { + data = await readToEnd(data); + } + if (util.isStream(data)) { + const hashInstance = new hash(); + return transform(data, value => { + hashInstance.process(value); + }, () => hashInstance.finish().result); + } else if (webCrypto && webCryptoHash && data.length >= config.minBytesForWebCrypto) { + return new Uint8Array(await webCrypto.digest(webCryptoHash, data)); + } else { + return hash.bytes(data); + } + }; + } + + let hashFunctions; + if (nodeCrypto) { // Use Node native crypto for all hash functions + hashFunctions = { + md5: nodeHash('md5'), + sha1: nodeHash('sha1'), + sha224: nodeHash('sha224'), + sha256: nodeHash('sha256'), + sha384: nodeHash('sha384'), + sha512: nodeHash('sha512'), + ripemd: nodeHash('ripemd160') + }; + } else { // Use JS fallbacks + hashFunctions = { + md5: md5, + sha1: asmcryptoHash(Sha1, (!navigator.userAgent || navigator.userAgent.indexOf('Edge') === -1) && 'SHA-1'), + sha224: hashjsHash(_224), + sha256: asmcryptoHash(Sha256, 'SHA-256'), + sha384: hashjsHash(_384, 'SHA-384'), + sha512: hashjsHash(_512, 'SHA-512'), // asmcrypto sha512 is huge. + ripemd: hashjsHash(ripemd160) + }; + } + + var hash = { + + /** @see module:md5 */ + md5: hashFunctions.md5, + /** @see asmCrypto */ + sha1: hashFunctions.sha1, + /** @see hash.js */ + sha224: hashFunctions.sha224, + /** @see asmCrypto */ + sha256: hashFunctions.sha256, + /** @see hash.js */ + sha384: hashFunctions.sha384, + /** @see asmCrypto */ + sha512: hashFunctions.sha512, + /** @see hash.js */ + ripemd: hashFunctions.ripemd, + + /** + * Create a hash on the specified data using the specified algorithm + * @param {module:enums.hash} algo - Hash algorithm type (see {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}) + * @param {Uint8Array} data - Data to be hashed + * @returns {Promise} Hash value. + */ + digest: function(algo, data) { + switch (algo) { + case enums.hash.md5: + return this.md5(data); + case enums.hash.sha1: + return this.sha1(data); + case enums.hash.ripemd: + return this.ripemd(data); + case enums.hash.sha256: + return this.sha256(data); + case enums.hash.sha384: + return this.sha384(data); + case enums.hash.sha512: + return this.sha512(data); + case enums.hash.sha224: + return this.sha224(data); + default: + throw new Error('Invalid hash function.'); + } + }, + + /** + * Returns the hash size in bytes of the specified hash algorithm type + * @param {module:enums.hash} algo - Hash algorithm type (See {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}) + * @returns {Integer} Size in bytes of the resulting hash. + */ + getHashByteLength: function(algo) { + switch (algo) { + case enums.hash.md5: + return 16; + case enums.hash.sha1: + case enums.hash.ripemd: + return 20; + case enums.hash.sha256: + return 32; + case enums.hash.sha384: + return 48; + case enums.hash.sha512: + return 64; + case enums.hash.sha224: + return 28; + default: + throw new Error('Invalid hash algorithm.'); + } + } + }; + + class AES_CFB { + static encrypt(data, key, iv) { + return new AES_CFB(key, iv).encrypt(data); + } + static decrypt(data, key, iv) { + return new AES_CFB(key, iv).decrypt(data); + } + constructor(key, iv, aes) { + this.aes = aes ? aes : new AES(key, iv, true, 'CFB'); + delete this.aes.padding; + } + encrypt(data) { + const r1 = this.aes.AES_Encrypt_process(data); + const r2 = this.aes.AES_Encrypt_finish(); + return joinBytes(r1, r2); + } + decrypt(data) { + const r1 = this.aes.AES_Decrypt_process(data); + const r2 = this.aes.AES_Decrypt_finish(); + return joinBytes(r1, r2); + } + } + + // Modified by ProtonTech AG + + const webCrypto$1 = util.getWebCrypto(); + const nodeCrypto$1 = util.getNodeCrypto(); + + const knownAlgos = nodeCrypto$1 ? nodeCrypto$1.getCiphers() : []; + const nodeAlgos = { + idea: knownAlgos.includes('idea-cfb') ? 'idea-cfb' : undefined, /* Unused, not implemented */ + tripledes: knownAlgos.includes('des-ede3-cfb') ? 'des-ede3-cfb' : undefined, + cast5: knownAlgos.includes('cast5-cfb') ? 'cast5-cfb' : undefined, + blowfish: knownAlgos.includes('bf-cfb') ? 'bf-cfb' : undefined, + aes128: knownAlgos.includes('aes-128-cfb') ? 'aes-128-cfb' : undefined, + aes192: knownAlgos.includes('aes-192-cfb') ? 'aes-192-cfb' : undefined, + aes256: knownAlgos.includes('aes-256-cfb') ? 'aes-256-cfb' : undefined + /* twofish is not implemented in OpenSSL */ + }; + + /** + * CFB encryption + * @param {enums.symmetric} algo - block cipher algorithm + * @param {Uint8Array} key + * @param {MaybeStream} plaintext + * @param {Uint8Array} iv + * @param {Object} config - full configuration, defaults to openpgp.config + * @returns MaybeStream + */ + async function encrypt(algo, key, plaintext, iv, config) { + const algoName = enums.read(enums.symmetric, algo); + if (util.getNodeCrypto() && nodeAlgos[algoName]) { // Node crypto library. + return nodeEncrypt(algo, key, plaintext, iv); + } + if (algoName.substr(0, 3) === 'aes') { + return aesEncrypt(algo, key, plaintext, iv, config); + } + + const cipherfn = new cipher[algoName](key); + const block_size = cipherfn.blockSize; + + const blockc = iv.slice(); + let pt = new Uint8Array(); + const process = chunk => { + if (chunk) { + pt = util.concatUint8Array([pt, chunk]); + } + const ciphertext = new Uint8Array(pt.length); + let i; + let j = 0; + while (chunk ? pt.length >= block_size : pt.length) { + const encblock = cipherfn.encrypt(blockc); + for (i = 0; i < block_size; i++) { + blockc[i] = pt[i] ^ encblock[i]; + ciphertext[j++] = blockc[i]; + } + pt = pt.subarray(block_size); + } + return ciphertext.subarray(0, j); + }; + return transform(plaintext, process, process); + } + + /** + * CFB decryption + * @param {enums.symmetric} algo - block cipher algorithm + * @param {Uint8Array} key + * @param {MaybeStream} ciphertext + * @param {Uint8Array} iv + * @returns MaybeStream + */ + async function decrypt(algo, key, ciphertext, iv) { + const algoName = enums.read(enums.symmetric, algo); + if (util.getNodeCrypto() && nodeAlgos[algoName]) { // Node crypto library. + return nodeDecrypt(algo, key, ciphertext, iv); + } + if (algoName.substr(0, 3) === 'aes') { + return aesDecrypt(algo, key, ciphertext, iv); + } + + const cipherfn = new cipher[algoName](key); + const block_size = cipherfn.blockSize; + + let blockp = iv; + let ct = new Uint8Array(); + const process = chunk => { + if (chunk) { + ct = util.concatUint8Array([ct, chunk]); + } + const plaintext = new Uint8Array(ct.length); + let i; + let j = 0; + while (chunk ? ct.length >= block_size : ct.length) { + const decblock = cipherfn.encrypt(blockp); + blockp = ct; + for (i = 0; i < block_size; i++) { + plaintext[j++] = blockp[i] ^ decblock[i]; + } + ct = ct.subarray(block_size); + } + return plaintext.subarray(0, j); + }; + return transform(ciphertext, process, process); + } + + function aesEncrypt(algo, key, pt, iv, config) { + if ( + util.getWebCrypto() && + key.length !== 24 && // Chrome doesn't support 192 bit keys, see https://www.chromium.org/blink/webcrypto#TOC-AES-support + !util.isStream(pt) && + pt.length >= 3000 * config.minBytesForWebCrypto // Default to a 3MB minimum. Chrome is pretty slow for small messages, see: https://bugs.chromium.org/p/chromium/issues/detail?id=701188#c2 + ) { // Web Crypto + return webEncrypt(algo, key, pt, iv); + } + // asm.js fallback + const cfb = new AES_CFB(key, iv); + return transform(pt, value => cfb.aes.AES_Encrypt_process(value), () => cfb.aes.AES_Encrypt_finish()); + } + + function aesDecrypt(algo, key, ct, iv) { + if (util.isStream(ct)) { + const cfb = new AES_CFB(key, iv); + return transform(ct, value => cfb.aes.AES_Decrypt_process(value), () => cfb.aes.AES_Decrypt_finish()); + } + return AES_CFB.decrypt(ct, key, iv); + } + + function xorMut(a, b) { + for (let i = 0; i < a.length; i++) { + a[i] = a[i] ^ b[i]; + } + } + + async function webEncrypt(algo, key, pt, iv) { + const ALGO = 'AES-CBC'; + const _key = await webCrypto$1.importKey('raw', key, { name: ALGO }, false, ['encrypt']); + const { blockSize } = crypto.getCipher(algo); + const cbc_pt = util.concatUint8Array([new Uint8Array(blockSize), pt]); + const ct = new Uint8Array(await webCrypto$1.encrypt({ name: ALGO, iv }, _key, cbc_pt)).subarray(0, pt.length); + xorMut(ct, pt); + return ct; + } + + function nodeEncrypt(algo, key, pt, iv) { + const algoName = enums.read(enums.symmetric, algo); + const cipherObj = new nodeCrypto$1.createCipheriv(nodeAlgos[algoName], key, iv); + return transform(pt, value => new Uint8Array(cipherObj.update(value))); + } + + function nodeDecrypt(algo, key, ct, iv) { + const algoName = enums.read(enums.symmetric, algo); + const decipherObj = new nodeCrypto$1.createDecipheriv(nodeAlgos[algoName], key, iv); + return transform(ct, value => new Uint8Array(decipherObj.update(value))); + } + + var cfb = /*#__PURE__*/Object.freeze({ + __proto__: null, + encrypt: encrypt, + decrypt: decrypt + }); + + class AES_CTR { + static encrypt(data, key, nonce) { + return new AES_CTR(key, nonce).encrypt(data); + } + static decrypt(data, key, nonce) { + return new AES_CTR(key, nonce).encrypt(data); + } + constructor(key, nonce, aes) { + this.aes = aes ? aes : new AES(key, undefined, false, 'CTR'); + delete this.aes.padding; + this.AES_CTR_set_options(nonce); + } + encrypt(data) { + const r1 = this.aes.AES_Encrypt_process(data); + const r2 = this.aes.AES_Encrypt_finish(); + return joinBytes(r1, r2); + } + decrypt(data) { + const r1 = this.aes.AES_Encrypt_process(data); + const r2 = this.aes.AES_Encrypt_finish(); + return joinBytes(r1, r2); + } + AES_CTR_set_options(nonce, counter, size) { + let { asm } = this.aes.acquire_asm(); + if (size !== undefined) { + if (size < 8 || size > 48) + throw new IllegalArgumentError('illegal counter size'); + let mask = Math.pow(2, size) - 1; + asm.set_mask(0, 0, (mask / 0x100000000) | 0, mask | 0); + } + else { + size = 48; + asm.set_mask(0, 0, 0xffff, 0xffffffff); + } + if (nonce !== undefined) { + let len = nonce.length; + if (!len || len > 16) + throw new IllegalArgumentError('illegal nonce size'); + let view = new DataView(new ArrayBuffer(16)); + new Uint8Array(view.buffer).set(nonce); + asm.set_nonce(view.getUint32(0), view.getUint32(4), view.getUint32(8), view.getUint32(12)); + } + else { + throw new Error('nonce is required'); + } + if (counter !== undefined) { + if (counter < 0 || counter >= Math.pow(2, size)) + throw new IllegalArgumentError('illegal counter value'); + asm.set_counter(0, 0, (counter / 0x100000000) | 0, counter | 0); + } + } + } + + class AES_CBC { + static encrypt(data, key, padding = true, iv) { + return new AES_CBC(key, iv, padding).encrypt(data); + } + static decrypt(data, key, padding = true, iv) { + return new AES_CBC(key, iv, padding).decrypt(data); + } + constructor(key, iv, padding = true, aes) { + this.aes = aes ? aes : new AES(key, iv, padding, 'CBC'); + } + encrypt(data) { + const r1 = this.aes.AES_Encrypt_process(data); + const r2 = this.aes.AES_Encrypt_finish(); + return joinBytes(r1, r2); + } + decrypt(data) { + const r1 = this.aes.AES_Decrypt_process(data); + const r2 = this.aes.AES_Decrypt_finish(); + return joinBytes(r1, r2); + } + } + + /** + * @fileoverview This module implements AES-CMAC on top of + * native AES-CBC using either the WebCrypto API or Node.js' crypto API. + * @module crypto/cmac + * @private + */ + + const webCrypto$2 = util.getWebCrypto(); + const nodeCrypto$2 = util.getNodeCrypto(); + + + /** + * This implementation of CMAC is based on the description of OMAC in + * http://web.cs.ucdavis.edu/~rogaway/papers/eax.pdf. As per that + * document: + * + * We have made a small modification to the OMAC algorithm as it was + * originally presented, changing one of its two constants. + * Specifically, the constant 4 at line 85 was the constant 1/2 (the + * multiplicative inverse of 2) in the original definition of OMAC [14]. + * The OMAC authors indicate that they will promulgate this modification + * [15], which slightly simplifies implementations. + */ + + const blockLength = 16; + + + /** + * xor `padding` into the end of `data`. This function implements "the + * operation xor→ [which] xors the shorter string into the end of longer + * one". Since data is always as least as long as padding, we can + * simplify the implementation. + * @param {Uint8Array} data + * @param {Uint8Array} padding + */ + function rightXORMut(data, padding) { + const offset = data.length - blockLength; + for (let i = 0; i < blockLength; i++) { + data[i + offset] ^= padding[i]; + } + return data; + } + + function pad(data, padding, padding2) { + // if |M| in {n, 2n, 3n, ...} + if (data.length && data.length % blockLength === 0) { + // then return M xor→ B, + return rightXORMut(data, padding); + } + // else return (M || 10^(n−1−(|M| mod n))) xor→ P + const padded = new Uint8Array(data.length + (blockLength - data.length % blockLength)); + padded.set(data); + padded[data.length] = 0b10000000; + return rightXORMut(padded, padding2); + } + + const zeroBlock = new Uint8Array(blockLength); + + async function CMAC(key) { + const cbc = await CBC(key); + + // L ← E_K(0^n); B ← 2L; P ← 4L + const padding = util.double(await cbc(zeroBlock)); + const padding2 = util.double(padding); + + return async function(data) { + // return CBC_K(pad(M; B, P)) + return (await cbc(pad(data, padding, padding2))).subarray(-blockLength); + }; + } + + async function CBC(key) { + if (util.getWebCrypto() && key.length !== 24) { // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support + key = await webCrypto$2.importKey('raw', key, { name: 'AES-CBC', length: key.length * 8 }, false, ['encrypt']); + return async function(pt) { + const ct = await webCrypto$2.encrypt({ name: 'AES-CBC', iv: zeroBlock, length: blockLength * 8 }, key, pt); + return new Uint8Array(ct).subarray(0, ct.byteLength - blockLength); + }; + } + if (util.getNodeCrypto()) { // Node crypto library + return async function(pt) { + const en = new nodeCrypto$2.createCipheriv('aes-' + (key.length * 8) + '-cbc', key, zeroBlock); + const ct = en.update(pt); + return new Uint8Array(ct); + }; + } + // asm.js fallback + return async function(pt) { + return AES_CBC.encrypt(pt, key, false, zeroBlock); + }; + } + + // OpenPGP.js - An OpenPGP implementation in javascript + + const webCrypto$3 = util.getWebCrypto(); + const nodeCrypto$3 = util.getNodeCrypto(); + const Buffer$1 = util.getNodeBuffer(); + + + const blockLength$1 = 16; + const ivLength = blockLength$1; + const tagLength = blockLength$1; + + const zero = new Uint8Array(blockLength$1); + const one = new Uint8Array(blockLength$1); one[blockLength$1 - 1] = 1; + const two = new Uint8Array(blockLength$1); two[blockLength$1 - 1] = 2; + + async function OMAC(key) { + const cmac = await CMAC(key); + return function(t, message) { + return cmac(util.concatUint8Array([t, message])); + }; + } + + async function CTR(key) { + if ( + util.getWebCrypto() && + key.length !== 24 && // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support + (!navigator.userAgent || navigator.userAgent.indexOf('Edge') === -1) + ) { + key = await webCrypto$3.importKey('raw', key, { name: 'AES-CTR', length: key.length * 8 }, false, ['encrypt']); + return async function(pt, iv) { + const ct = await webCrypto$3.encrypt({ name: 'AES-CTR', counter: iv, length: blockLength$1 * 8 }, key, pt); + return new Uint8Array(ct); + }; + } + if (util.getNodeCrypto()) { // Node crypto library + return async function(pt, iv) { + const en = new nodeCrypto$3.createCipheriv('aes-' + (key.length * 8) + '-ctr', key, iv); + const ct = Buffer$1.concat([en.update(pt), en.final()]); + return new Uint8Array(ct); + }; + } + // asm.js fallback + return async function(pt, iv) { + return AES_CTR.encrypt(pt, key, iv); + }; + } + + + /** + * Class to en/decrypt using EAX mode. + * @param {enums.symmetric} cipher - The symmetric cipher algorithm to use + * @param {Uint8Array} key - The encryption key + */ + async function EAX(cipher, key) { + if (cipher !== enums.symmetric.aes128 && + cipher !== enums.symmetric.aes192 && + cipher !== enums.symmetric.aes256) { + throw new Error('EAX mode supports only AES cipher'); + } + + const [ + omac, + ctr + ] = await Promise.all([ + OMAC(key), + CTR(key) + ]); + + return { + /** + * Encrypt plaintext input. + * @param {Uint8Array} plaintext - The cleartext input to be encrypted + * @param {Uint8Array} nonce - The nonce (16 bytes) + * @param {Uint8Array} adata - Associated data to sign + * @returns {Promise} The ciphertext output. + */ + encrypt: async function(plaintext, nonce, adata) { + const [ + omacNonce, + omacAdata + ] = await Promise.all([ + omac(zero, nonce), + omac(one, adata) + ]); + const ciphered = await ctr(plaintext, omacNonce); + const omacCiphered = await omac(two, ciphered); + const tag = omacCiphered; // Assumes that omac(*).length === tagLength. + for (let i = 0; i < tagLength; i++) { + tag[i] ^= omacAdata[i] ^ omacNonce[i]; + } + return util.concatUint8Array([ciphered, tag]); + }, + + /** + * Decrypt ciphertext input. + * @param {Uint8Array} ciphertext - The ciphertext input to be decrypted + * @param {Uint8Array} nonce - The nonce (16 bytes) + * @param {Uint8Array} adata - Associated data to verify + * @returns {Promise} The plaintext output. + */ + decrypt: async function(ciphertext, nonce, adata) { + if (ciphertext.length < tagLength) throw new Error('Invalid EAX ciphertext'); + const ciphered = ciphertext.subarray(0, -tagLength); + const ctTag = ciphertext.subarray(-tagLength); + const [ + omacNonce, + omacAdata, + omacCiphered + ] = await Promise.all([ + omac(zero, nonce), + omac(one, adata), + omac(two, ciphered) + ]); + const tag = omacCiphered; // Assumes that omac(*).length === tagLength. + for (let i = 0; i < tagLength; i++) { + tag[i] ^= omacAdata[i] ^ omacNonce[i]; + } + if (!util.equalsUint8Array(ctTag, tag)) throw new Error('Authentication tag mismatch'); + const plaintext = await ctr(ciphered, omacNonce); + return plaintext; + } + }; + } + + + /** + * Get EAX nonce as defined by {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.1|RFC4880bis-04, section 5.16.1}. + * @param {Uint8Array} iv - The initialization vector (16 bytes) + * @param {Uint8Array} chunkIndex - The chunk index (8 bytes) + */ + EAX.getNonce = function(iv, chunkIndex) { + const nonce = iv.slice(); + for (let i = 0; i < chunkIndex.length; i++) { + nonce[8 + i] ^= chunkIndex[i]; + } + return nonce; + }; + + EAX.blockLength = blockLength$1; + EAX.ivLength = ivLength; + EAX.tagLength = tagLength; + + // OpenPGP.js - An OpenPGP implementation in javascript + + const blockLength$2 = 16; + const ivLength$1 = 15; + + // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.2: + // While OCB [RFC7253] allows the authentication tag length to be of any + // number up to 128 bits long, this document requires a fixed + // authentication tag length of 128 bits (16 octets) for simplicity. + const tagLength$1 = 16; + + + function ntz(n) { + let ntz = 0; + for (let i = 1; (n & i) === 0; i <<= 1) { + ntz++; + } + return ntz; + } + + function xorMut$1(S, T) { + for (let i = 0; i < S.length; i++) { + S[i] ^= T[i]; + } + return S; + } + + function xor(S, T) { + return xorMut$1(S.slice(), T); + } + + const zeroBlock$1 = new Uint8Array(blockLength$2); + const one$1 = new Uint8Array([1]); + + /** + * Class to en/decrypt using OCB mode. + * @param {enums.symmetric} cipher - The symmetric cipher algorithm to use + * @param {Uint8Array} key - The encryption key + */ + async function OCB(cipher$1, key) { + + let maxNtz = 0; + let encipher; + let decipher; + let mask; + + constructKeyVariables(cipher$1, key); + + function constructKeyVariables(cipher$1, key) { + const cipherName = enums.read(enums.symmetric, cipher$1); + const aes = new cipher[cipherName](key); + encipher = aes.encrypt.bind(aes); + decipher = aes.decrypt.bind(aes); + + const mask_x = encipher(zeroBlock$1); + const mask_$ = util.double(mask_x); + mask = []; + mask[0] = util.double(mask_$); + + + mask.x = mask_x; + mask.$ = mask_$; + } + + function extendKeyVariables(text, adata) { + const newMaxNtz = util.nbits(Math.max(text.length, adata.length) / blockLength$2 | 0) - 1; + for (let i = maxNtz + 1; i <= newMaxNtz; i++) { + mask[i] = util.double(mask[i - 1]); + } + maxNtz = newMaxNtz; + } + + function hash(adata) { + if (!adata.length) { + // Fast path + return zeroBlock$1; + } + + // + // Consider A as a sequence of 128-bit blocks + // + const m = adata.length / blockLength$2 | 0; + + const offset = new Uint8Array(blockLength$2); + const sum = new Uint8Array(blockLength$2); + for (let i = 0; i < m; i++) { + xorMut$1(offset, mask[ntz(i + 1)]); + xorMut$1(sum, encipher(xor(offset, adata))); + adata = adata.subarray(blockLength$2); + } + + // + // Process any final partial block; compute final hash value + // + if (adata.length) { + xorMut$1(offset, mask.x); + + const cipherInput = new Uint8Array(blockLength$2); + cipherInput.set(adata, 0); + cipherInput[adata.length] = 0b10000000; + xorMut$1(cipherInput, offset); + + xorMut$1(sum, encipher(cipherInput)); + } + + return sum; + } + + /** + * Encrypt/decrypt data. + * @param {encipher|decipher} fn - Encryption/decryption block cipher function + * @param {Uint8Array} text - The cleartext or ciphertext (without tag) input + * @param {Uint8Array} nonce - The nonce (15 bytes) + * @param {Uint8Array} adata - Associated data to sign + * @returns {Promise} The ciphertext or plaintext output, with tag appended in both cases. + */ + function crypt(fn, text, nonce, adata) { + // + // Consider P as a sequence of 128-bit blocks + // + const m = text.length / blockLength$2 | 0; + + // + // Key-dependent variables + // + extendKeyVariables(text, adata); + + // + // Nonce-dependent and per-encryption variables + // + // Nonce = num2str(TAGLEN mod 128,7) || zeros(120-bitlen(N)) || 1 || N + // Note: We assume here that tagLength mod 16 == 0. + const paddedNonce = util.concatUint8Array([zeroBlock$1.subarray(0, ivLength$1 - nonce.length), one$1, nonce]); + // bottom = str2num(Nonce[123..128]) + const bottom = paddedNonce[blockLength$2 - 1] & 0b111111; + // Ktop = ENCIPHER(K, Nonce[1..122] || zeros(6)) + paddedNonce[blockLength$2 - 1] &= 0b11000000; + const kTop = encipher(paddedNonce); + // Stretch = Ktop || (Ktop[1..64] xor Ktop[9..72]) + const stretched = util.concatUint8Array([kTop, xor(kTop.subarray(0, 8), kTop.subarray(1, 9))]); + // Offset_0 = Stretch[1+bottom..128+bottom] + const offset = util.shiftRight(stretched.subarray(0 + (bottom >> 3), 17 + (bottom >> 3)), 8 - (bottom & 7)).subarray(1); + // Checksum_0 = zeros(128) + const checksum = new Uint8Array(blockLength$2); + + const ct = new Uint8Array(text.length + tagLength$1); + + // + // Process any whole blocks + // + let i; + let pos = 0; + for (i = 0; i < m; i++) { + // Offset_i = Offset_{i-1} xor L_{ntz(i)} + xorMut$1(offset, mask[ntz(i + 1)]); + // C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) + // P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i) + ct.set(xorMut$1(fn(xor(offset, text)), offset), pos); + // Checksum_i = Checksum_{i-1} xor P_i + xorMut$1(checksum, fn === encipher ? text : ct.subarray(pos)); + + text = text.subarray(blockLength$2); + pos += blockLength$2; + } + + // + // Process any final partial block and compute raw tag + // + if (text.length) { + // Offset_* = Offset_m xor L_* + xorMut$1(offset, mask.x); + // Pad = ENCIPHER(K, Offset_*) + const padding = encipher(offset); + // C_* = P_* xor Pad[1..bitlen(P_*)] + ct.set(xor(text, padding), pos); + + // Checksum_* = Checksum_m xor (P_* || 1 || new Uint8Array(127-bitlen(P_*))) + const xorInput = new Uint8Array(blockLength$2); + xorInput.set(fn === encipher ? text : ct.subarray(pos, -tagLength$1), 0); + xorInput[text.length] = 0b10000000; + xorMut$1(checksum, xorInput); + pos += text.length; + } + // Tag = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) xor HASH(K,A) + const tag = xorMut$1(encipher(xorMut$1(xorMut$1(checksum, offset), mask.$)), hash(adata)); + + // + // Assemble ciphertext + // + // C = C_1 || C_2 || ... || C_m || C_* || Tag[1..TAGLEN] + ct.set(tag, pos); + return ct; + } + + + return { + /** + * Encrypt plaintext input. + * @param {Uint8Array} plaintext - The cleartext input to be encrypted + * @param {Uint8Array} nonce - The nonce (15 bytes) + * @param {Uint8Array} adata - Associated data to sign + * @returns {Promise} The ciphertext output. + */ + encrypt: async function(plaintext, nonce, adata) { + return crypt(encipher, plaintext, nonce, adata); + }, + + /** + * Decrypt ciphertext input. + * @param {Uint8Array} ciphertext - The ciphertext input to be decrypted + * @param {Uint8Array} nonce - The nonce (15 bytes) + * @param {Uint8Array} adata - Associated data to sign + * @returns {Promise} The ciphertext output. + */ + decrypt: async function(ciphertext, nonce, adata) { + if (ciphertext.length < tagLength$1) throw new Error('Invalid OCB ciphertext'); + + const tag = ciphertext.subarray(-tagLength$1); + ciphertext = ciphertext.subarray(0, -tagLength$1); + + const crypted = crypt(decipher, ciphertext, nonce, adata); + // if (Tag[1..TAGLEN] == T) + if (util.equalsUint8Array(tag, crypted.subarray(-tagLength$1))) { + return crypted.subarray(0, -tagLength$1); + } + throw new Error('Authentication tag mismatch'); + } + }; + } + + + /** + * Get OCB nonce as defined by {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.2|RFC4880bis-04, section 5.16.2}. + * @param {Uint8Array} iv - The initialization vector (15 bytes) + * @param {Uint8Array} chunkIndex - The chunk index (8 bytes) + */ + OCB.getNonce = function(iv, chunkIndex) { + const nonce = iv.slice(); + for (let i = 0; i < chunkIndex.length; i++) { + nonce[7 + i] ^= chunkIndex[i]; + } + return nonce; + }; + + OCB.blockLength = blockLength$2; + OCB.ivLength = ivLength$1; + OCB.tagLength = tagLength$1; + + const _AES_GCM_data_maxLength = 68719476704; // 2^36 - 2^5 + class AES_GCM { + constructor(key, nonce, adata, tagSize = 16, aes) { + this.tagSize = tagSize; + this.gamma0 = 0; + this.counter = 1; + this.aes = aes ? aes : new AES(key, undefined, false, 'CTR'); + let { asm, heap } = this.aes.acquire_asm(); + // Init GCM + asm.gcm_init(); + // Tag size + if (this.tagSize < 4 || this.tagSize > 16) + throw new IllegalArgumentError('illegal tagSize value'); + // Nonce + const noncelen = nonce.length || 0; + const noncebuf = new Uint8Array(16); + if (noncelen !== 12) { + this._gcm_mac_process(nonce); + heap[0] = 0; + heap[1] = 0; + heap[2] = 0; + heap[3] = 0; + heap[4] = 0; + heap[5] = 0; + heap[6] = 0; + heap[7] = 0; + heap[8] = 0; + heap[9] = 0; + heap[10] = 0; + heap[11] = noncelen >>> 29; + heap[12] = (noncelen >>> 21) & 255; + heap[13] = (noncelen >>> 13) & 255; + heap[14] = (noncelen >>> 5) & 255; + heap[15] = (noncelen << 3) & 255; + asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16); + asm.get_iv(AES_asm.HEAP_DATA); + asm.set_iv(0, 0, 0, 0); + noncebuf.set(heap.subarray(0, 16)); + } + else { + noncebuf.set(nonce); + noncebuf[15] = 1; + } + const nonceview = new DataView(noncebuf.buffer); + this.gamma0 = nonceview.getUint32(12); + asm.set_nonce(nonceview.getUint32(0), nonceview.getUint32(4), nonceview.getUint32(8), 0); + asm.set_mask(0, 0, 0, 0xffffffff); + // Associated data + if (adata !== undefined) { + if (adata.length > _AES_GCM_data_maxLength) + throw new IllegalArgumentError('illegal adata length'); + if (adata.length) { + this.adata = adata; + this._gcm_mac_process(adata); + } + else { + this.adata = undefined; + } + } + else { + this.adata = undefined; + } + // Counter + if (this.counter < 1 || this.counter > 0xffffffff) + throw new RangeError('counter must be a positive 32-bit integer'); + asm.set_counter(0, 0, 0, (this.gamma0 + this.counter) | 0); + } + static encrypt(cleartext, key, nonce, adata, tagsize) { + return new AES_GCM(key, nonce, adata, tagsize).encrypt(cleartext); + } + static decrypt(ciphertext, key, nonce, adata, tagsize) { + return new AES_GCM(key, nonce, adata, tagsize).decrypt(ciphertext); + } + encrypt(data) { + return this.AES_GCM_encrypt(data); + } + decrypt(data) { + return this.AES_GCM_decrypt(data); + } + AES_GCM_Encrypt_process(data) { + let dpos = 0; + let dlen = data.length || 0; + let { asm, heap } = this.aes.acquire_asm(); + let counter = this.counter; + let pos = this.aes.pos; + let len = this.aes.len; + let rpos = 0; + let rlen = (len + dlen) & -16; + let wlen = 0; + if (((counter - 1) << 4) + len + dlen > _AES_GCM_data_maxLength) + throw new RangeError('counter overflow'); + const result = new Uint8Array(rlen); + while (dlen > 0) { + wlen = _heap_write(heap, pos + len, data, dpos, dlen); + len += wlen; + dpos += wlen; + dlen -= wlen; + wlen = asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, len); + wlen = asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, wlen); + if (wlen) + result.set(heap.subarray(pos, pos + wlen), rpos); + counter += wlen >>> 4; + rpos += wlen; + if (wlen < len) { + pos += wlen; + len -= wlen; + } + else { + pos = 0; + len = 0; + } + } + this.counter = counter; + this.aes.pos = pos; + this.aes.len = len; + return result; + } + AES_GCM_Encrypt_finish() { + let { asm, heap } = this.aes.acquire_asm(); + let counter = this.counter; + let tagSize = this.tagSize; + let adata = this.adata; + let pos = this.aes.pos; + let len = this.aes.len; + const result = new Uint8Array(len + tagSize); + asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, (len + 15) & -16); + if (len) + result.set(heap.subarray(pos, pos + len)); + let i = len; + for (; i & 15; i++) + heap[pos + i] = 0; + asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, i); + const alen = adata !== undefined ? adata.length : 0; + const clen = ((counter - 1) << 4) + len; + heap[0] = 0; + heap[1] = 0; + heap[2] = 0; + heap[3] = alen >>> 29; + heap[4] = alen >>> 21; + heap[5] = (alen >>> 13) & 255; + heap[6] = (alen >>> 5) & 255; + heap[7] = (alen << 3) & 255; + heap[8] = heap[9] = heap[10] = 0; + heap[11] = clen >>> 29; + heap[12] = (clen >>> 21) & 255; + heap[13] = (clen >>> 13) & 255; + heap[14] = (clen >>> 5) & 255; + heap[15] = (clen << 3) & 255; + asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16); + asm.get_iv(AES_asm.HEAP_DATA); + asm.set_counter(0, 0, 0, this.gamma0); + asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16); + result.set(heap.subarray(0, tagSize), len); + this.counter = 1; + this.aes.pos = 0; + this.aes.len = 0; + return result; + } + AES_GCM_Decrypt_process(data) { + let dpos = 0; + let dlen = data.length || 0; + let { asm, heap } = this.aes.acquire_asm(); + let counter = this.counter; + let tagSize = this.tagSize; + let pos = this.aes.pos; + let len = this.aes.len; + let rpos = 0; + let rlen = len + dlen > tagSize ? (len + dlen - tagSize) & -16 : 0; + let tlen = len + dlen - rlen; + let wlen = 0; + if (((counter - 1) << 4) + len + dlen > _AES_GCM_data_maxLength) + throw new RangeError('counter overflow'); + const result = new Uint8Array(rlen); + while (dlen > tlen) { + wlen = _heap_write(heap, pos + len, data, dpos, dlen - tlen); + len += wlen; + dpos += wlen; + dlen -= wlen; + wlen = asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, wlen); + wlen = asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, wlen); + if (wlen) + result.set(heap.subarray(pos, pos + wlen), rpos); + counter += wlen >>> 4; + rpos += wlen; + pos = 0; + len = 0; + } + if (dlen > 0) { + len += _heap_write(heap, 0, data, dpos, dlen); + } + this.counter = counter; + this.aes.pos = pos; + this.aes.len = len; + return result; + } + AES_GCM_Decrypt_finish() { + let { asm, heap } = this.aes.acquire_asm(); + let tagSize = this.tagSize; + let adata = this.adata; + let counter = this.counter; + let pos = this.aes.pos; + let len = this.aes.len; + let rlen = len - tagSize; + if (len < tagSize) + throw new IllegalStateError('authentication tag not found'); + const result = new Uint8Array(rlen); + const atag = new Uint8Array(heap.subarray(pos + rlen, pos + len)); + let i = rlen; + for (; i & 15; i++) + heap[pos + i] = 0; + asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, i); + asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, i); + if (rlen) + result.set(heap.subarray(pos, pos + rlen)); + const alen = adata !== undefined ? adata.length : 0; + const clen = ((counter - 1) << 4) + len - tagSize; + heap[0] = 0; + heap[1] = 0; + heap[2] = 0; + heap[3] = alen >>> 29; + heap[4] = alen >>> 21; + heap[5] = (alen >>> 13) & 255; + heap[6] = (alen >>> 5) & 255; + heap[7] = (alen << 3) & 255; + heap[8] = heap[9] = heap[10] = 0; + heap[11] = clen >>> 29; + heap[12] = (clen >>> 21) & 255; + heap[13] = (clen >>> 13) & 255; + heap[14] = (clen >>> 5) & 255; + heap[15] = (clen << 3) & 255; + asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16); + asm.get_iv(AES_asm.HEAP_DATA); + asm.set_counter(0, 0, 0, this.gamma0); + asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16); + let acheck = 0; + for (let i = 0; i < tagSize; ++i) + acheck |= atag[i] ^ heap[i]; + if (acheck) + throw new SecurityError('data integrity check failed'); + this.counter = 1; + this.aes.pos = 0; + this.aes.len = 0; + return result; + } + AES_GCM_decrypt(data) { + const result1 = this.AES_GCM_Decrypt_process(data); + const result2 = this.AES_GCM_Decrypt_finish(); + const result = new Uint8Array(result1.length + result2.length); + if (result1.length) + result.set(result1); + if (result2.length) + result.set(result2, result1.length); + return result; + } + AES_GCM_encrypt(data) { + const result1 = this.AES_GCM_Encrypt_process(data); + const result2 = this.AES_GCM_Encrypt_finish(); + const result = new Uint8Array(result1.length + result2.length); + if (result1.length) + result.set(result1); + if (result2.length) + result.set(result2, result1.length); + return result; + } + _gcm_mac_process(data) { + let { asm, heap } = this.aes.acquire_asm(); + let dpos = 0; + let dlen = data.length || 0; + let wlen = 0; + while (dlen > 0) { + wlen = _heap_write(heap, 0, data, dpos, dlen); + dpos += wlen; + dlen -= wlen; + while (wlen & 15) + heap[wlen++] = 0; + asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, wlen); + } + } + } + + // OpenPGP.js - An OpenPGP implementation in javascript + + const webCrypto$4 = util.getWebCrypto(); + const nodeCrypto$4 = util.getNodeCrypto(); + const Buffer$2 = util.getNodeBuffer(); + + const blockLength$3 = 16; + const ivLength$2 = 12; // size of the IV in bytes + const tagLength$2 = 16; // size of the tag in bytes + const ALGO = 'AES-GCM'; + + /** + * Class to en/decrypt using GCM mode. + * @param {enums.symmetric} cipher - The symmetric cipher algorithm to use + * @param {Uint8Array} key - The encryption key + */ + async function GCM(cipher, key) { + if (cipher !== enums.symmetric.aes128 && + cipher !== enums.symmetric.aes192 && + cipher !== enums.symmetric.aes256) { + throw new Error('GCM mode supports only AES cipher'); + } + + if (util.getWebCrypto() && key.length !== 24) { // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support + const _key = await webCrypto$4.importKey('raw', key, { name: ALGO }, false, ['encrypt', 'decrypt']); + + return { + encrypt: async function(pt, iv, adata = new Uint8Array()) { + if ( + !pt.length || + // iOS does not support GCM-en/decrypting empty messages + // Also, synchronous en/decryption might be faster in this case. + (!adata.length && navigator.userAgent && navigator.userAgent.indexOf('Edge') !== -1) + // Edge does not support GCM-en/decrypting without ADATA + ) { + return AES_GCM.encrypt(pt, key, iv, adata); + } + const ct = await webCrypto$4.encrypt({ name: ALGO, iv, additionalData: adata, tagLength: tagLength$2 * 8 }, _key, pt); + return new Uint8Array(ct); + }, + + decrypt: async function(ct, iv, adata = new Uint8Array()) { + if ( + ct.length === tagLength$2 || + // iOS does not support GCM-en/decrypting empty messages + // Also, synchronous en/decryption might be faster in this case. + (!adata.length && navigator.userAgent && navigator.userAgent.indexOf('Edge') !== -1) + // Edge does not support GCM-en/decrypting without ADATA + ) { + return AES_GCM.decrypt(ct, key, iv, adata); + } + const pt = await webCrypto$4.decrypt({ name: ALGO, iv, additionalData: adata, tagLength: tagLength$2 * 8 }, _key, ct); + return new Uint8Array(pt); + } + }; + } + + if (util.getNodeCrypto()) { // Node crypto library + return { + encrypt: async function(pt, iv, adata = new Uint8Array()) { + const en = new nodeCrypto$4.createCipheriv('aes-' + (key.length * 8) + '-gcm', key, iv); + en.setAAD(adata); + const ct = Buffer$2.concat([en.update(pt), en.final(), en.getAuthTag()]); // append auth tag to ciphertext + return new Uint8Array(ct); + }, + + decrypt: async function(ct, iv, adata = new Uint8Array()) { + const de = new nodeCrypto$4.createDecipheriv('aes-' + (key.length * 8) + '-gcm', key, iv); + de.setAAD(adata); + de.setAuthTag(ct.slice(ct.length - tagLength$2, ct.length)); // read auth tag at end of ciphertext + const pt = Buffer$2.concat([de.update(ct.slice(0, ct.length - tagLength$2)), de.final()]); + return new Uint8Array(pt); + } + }; + } + + return { + encrypt: async function(pt, iv, adata) { + return AES_GCM.encrypt(pt, key, iv, adata); + }, + + decrypt: async function(ct, iv, adata) { + return AES_GCM.decrypt(ct, key, iv, adata); + } + }; + } + + + /** + * Get GCM nonce. Note: this operation is not defined by the standard. + * A future version of the standard may define GCM mode differently, + * hopefully under a different ID (we use Private/Experimental algorithm + * ID 100) so that we can maintain backwards compatibility. + * @param {Uint8Array} iv - The initialization vector (12 bytes) + * @param {Uint8Array} chunkIndex - The chunk index (8 bytes) + */ + GCM.getNonce = function(iv, chunkIndex) { + const nonce = iv.slice(); + for (let i = 0; i < chunkIndex.length; i++) { + nonce[4 + i] ^= chunkIndex[i]; + } + return nonce; + }; + + GCM.blockLength = blockLength$3; + GCM.ivLength = ivLength$2; + GCM.tagLength = tagLength$2; + + /** + * @fileoverview Cipher modes + * @module crypto/mode + * @private + */ + + var mode = { + /** @see module:crypto/mode/cfb */ + cfb: cfb, + /** @see module:crypto/mode/gcm */ + gcm: GCM, + experimentalGCM: GCM, + /** @see module:crypto/mode/eax */ + eax: EAX, + /** @see module:crypto/mode/ocb */ + ocb: OCB + }; + + var naclFastLight = createCommonjsModule(function (module) { + /*jshint bitwise: false*/ + + (function(nacl) { + + // Ported in 2014 by Dmitry Chestnykh and Devi Mandiri. + // Public domain. + // + // Implementation derived from TweetNaCl version 20140427. + // See for details: http://tweetnacl.cr.yp.to/ + + var gf = function(init) { + var i, r = new Float64Array(16); + if (init) for (i = 0; i < init.length; i++) r[i] = init[i]; + return r; + }; + + // Pluggable, initialized in high-level API below. + var randombytes = function(/* x, n */) { throw new Error('no PRNG'); }; + + var _9 = new Uint8Array(32); _9[0] = 9; + + var gf0 = gf(), + gf1 = gf([1]), + _121665 = gf([0xdb41, 1]), + D = gf([0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203]), + D2 = gf([0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406]), + X = gf([0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169]), + Y = gf([0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666]), + I = gf([0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83]); + + function vn(x, xi, y, yi, n) { + var i,d = 0; + for (i = 0; i < n; i++) d |= x[xi+i]^y[yi+i]; + return (1 & ((d - 1) >>> 8)) - 1; + } + + function crypto_verify_32(x, xi, y, yi) { + return vn(x,xi,y,yi,32); + } + + function set25519(r, a) { + var i; + for (i = 0; i < 16; i++) r[i] = a[i]|0; + } + + function car25519(o) { + var i, v, c = 1; + for (i = 0; i < 16; i++) { + v = o[i] + c + 65535; + c = Math.floor(v / 65536); + o[i] = v - c * 65536; + } + o[0] += c-1 + 37 * (c-1); + } + + function sel25519(p, q, b) { + var t, c = ~(b-1); + for (var i = 0; i < 16; i++) { + t = c & (p[i] ^ q[i]); + p[i] ^= t; + q[i] ^= t; + } + } + + function pack25519(o, n) { + var i, j, b; + var m = gf(), t = gf(); + for (i = 0; i < 16; i++) t[i] = n[i]; + car25519(t); + car25519(t); + car25519(t); + for (j = 0; j < 2; j++) { + m[0] = t[0] - 0xffed; + for (i = 1; i < 15; i++) { + m[i] = t[i] - 0xffff - ((m[i-1]>>16) & 1); + m[i-1] &= 0xffff; + } + m[15] = t[15] - 0x7fff - ((m[14]>>16) & 1); + b = (m[15]>>16) & 1; + m[14] &= 0xffff; + sel25519(t, m, 1-b); + } + for (i = 0; i < 16; i++) { + o[2*i] = t[i] & 0xff; + o[2*i+1] = t[i]>>8; + } + } + + function neq25519(a, b) { + var c = new Uint8Array(32), d = new Uint8Array(32); + pack25519(c, a); + pack25519(d, b); + return crypto_verify_32(c, 0, d, 0); + } + + function par25519(a) { + var d = new Uint8Array(32); + pack25519(d, a); + return d[0] & 1; + } + + function unpack25519(o, n) { + var i; + for (i = 0; i < 16; i++) o[i] = n[2*i] + (n[2*i+1] << 8); + o[15] &= 0x7fff; + } + + function A(o, a, b) { + for (var i = 0; i < 16; i++) o[i] = a[i] + b[i]; + } + + function Z(o, a, b) { + for (var i = 0; i < 16; i++) o[i] = a[i] - b[i]; + } + + function M(o, a, b) { + var v, c, + t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0, + t8 = 0, t9 = 0, t10 = 0, t11 = 0, t12 = 0, t13 = 0, t14 = 0, t15 = 0, + t16 = 0, t17 = 0, t18 = 0, t19 = 0, t20 = 0, t21 = 0, t22 = 0, t23 = 0, + t24 = 0, t25 = 0, t26 = 0, t27 = 0, t28 = 0, t29 = 0, t30 = 0, + b0 = b[0], + b1 = b[1], + b2 = b[2], + b3 = b[3], + b4 = b[4], + b5 = b[5], + b6 = b[6], + b7 = b[7], + b8 = b[8], + b9 = b[9], + b10 = b[10], + b11 = b[11], + b12 = b[12], + b13 = b[13], + b14 = b[14], + b15 = b[15]; + + v = a[0]; + t0 += v * b0; + t1 += v * b1; + t2 += v * b2; + t3 += v * b3; + t4 += v * b4; + t5 += v * b5; + t6 += v * b6; + t7 += v * b7; + t8 += v * b8; + t9 += v * b9; + t10 += v * b10; + t11 += v * b11; + t12 += v * b12; + t13 += v * b13; + t14 += v * b14; + t15 += v * b15; + v = a[1]; + t1 += v * b0; + t2 += v * b1; + t3 += v * b2; + t4 += v * b3; + t5 += v * b4; + t6 += v * b5; + t7 += v * b6; + t8 += v * b7; + t9 += v * b8; + t10 += v * b9; + t11 += v * b10; + t12 += v * b11; + t13 += v * b12; + t14 += v * b13; + t15 += v * b14; + t16 += v * b15; + v = a[2]; + t2 += v * b0; + t3 += v * b1; + t4 += v * b2; + t5 += v * b3; + t6 += v * b4; + t7 += v * b5; + t8 += v * b6; + t9 += v * b7; + t10 += v * b8; + t11 += v * b9; + t12 += v * b10; + t13 += v * b11; + t14 += v * b12; + t15 += v * b13; + t16 += v * b14; + t17 += v * b15; + v = a[3]; + t3 += v * b0; + t4 += v * b1; + t5 += v * b2; + t6 += v * b3; + t7 += v * b4; + t8 += v * b5; + t9 += v * b6; + t10 += v * b7; + t11 += v * b8; + t12 += v * b9; + t13 += v * b10; + t14 += v * b11; + t15 += v * b12; + t16 += v * b13; + t17 += v * b14; + t18 += v * b15; + v = a[4]; + t4 += v * b0; + t5 += v * b1; + t6 += v * b2; + t7 += v * b3; + t8 += v * b4; + t9 += v * b5; + t10 += v * b6; + t11 += v * b7; + t12 += v * b8; + t13 += v * b9; + t14 += v * b10; + t15 += v * b11; + t16 += v * b12; + t17 += v * b13; + t18 += v * b14; + t19 += v * b15; + v = a[5]; + t5 += v * b0; + t6 += v * b1; + t7 += v * b2; + t8 += v * b3; + t9 += v * b4; + t10 += v * b5; + t11 += v * b6; + t12 += v * b7; + t13 += v * b8; + t14 += v * b9; + t15 += v * b10; + t16 += v * b11; + t17 += v * b12; + t18 += v * b13; + t19 += v * b14; + t20 += v * b15; + v = a[6]; + t6 += v * b0; + t7 += v * b1; + t8 += v * b2; + t9 += v * b3; + t10 += v * b4; + t11 += v * b5; + t12 += v * b6; + t13 += v * b7; + t14 += v * b8; + t15 += v * b9; + t16 += v * b10; + t17 += v * b11; + t18 += v * b12; + t19 += v * b13; + t20 += v * b14; + t21 += v * b15; + v = a[7]; + t7 += v * b0; + t8 += v * b1; + t9 += v * b2; + t10 += v * b3; + t11 += v * b4; + t12 += v * b5; + t13 += v * b6; + t14 += v * b7; + t15 += v * b8; + t16 += v * b9; + t17 += v * b10; + t18 += v * b11; + t19 += v * b12; + t20 += v * b13; + t21 += v * b14; + t22 += v * b15; + v = a[8]; + t8 += v * b0; + t9 += v * b1; + t10 += v * b2; + t11 += v * b3; + t12 += v * b4; + t13 += v * b5; + t14 += v * b6; + t15 += v * b7; + t16 += v * b8; + t17 += v * b9; + t18 += v * b10; + t19 += v * b11; + t20 += v * b12; + t21 += v * b13; + t22 += v * b14; + t23 += v * b15; + v = a[9]; + t9 += v * b0; + t10 += v * b1; + t11 += v * b2; + t12 += v * b3; + t13 += v * b4; + t14 += v * b5; + t15 += v * b6; + t16 += v * b7; + t17 += v * b8; + t18 += v * b9; + t19 += v * b10; + t20 += v * b11; + t21 += v * b12; + t22 += v * b13; + t23 += v * b14; + t24 += v * b15; + v = a[10]; + t10 += v * b0; + t11 += v * b1; + t12 += v * b2; + t13 += v * b3; + t14 += v * b4; + t15 += v * b5; + t16 += v * b6; + t17 += v * b7; + t18 += v * b8; + t19 += v * b9; + t20 += v * b10; + t21 += v * b11; + t22 += v * b12; + t23 += v * b13; + t24 += v * b14; + t25 += v * b15; + v = a[11]; + t11 += v * b0; + t12 += v * b1; + t13 += v * b2; + t14 += v * b3; + t15 += v * b4; + t16 += v * b5; + t17 += v * b6; + t18 += v * b7; + t19 += v * b8; + t20 += v * b9; + t21 += v * b10; + t22 += v * b11; + t23 += v * b12; + t24 += v * b13; + t25 += v * b14; + t26 += v * b15; + v = a[12]; + t12 += v * b0; + t13 += v * b1; + t14 += v * b2; + t15 += v * b3; + t16 += v * b4; + t17 += v * b5; + t18 += v * b6; + t19 += v * b7; + t20 += v * b8; + t21 += v * b9; + t22 += v * b10; + t23 += v * b11; + t24 += v * b12; + t25 += v * b13; + t26 += v * b14; + t27 += v * b15; + v = a[13]; + t13 += v * b0; + t14 += v * b1; + t15 += v * b2; + t16 += v * b3; + t17 += v * b4; + t18 += v * b5; + t19 += v * b6; + t20 += v * b7; + t21 += v * b8; + t22 += v * b9; + t23 += v * b10; + t24 += v * b11; + t25 += v * b12; + t26 += v * b13; + t27 += v * b14; + t28 += v * b15; + v = a[14]; + t14 += v * b0; + t15 += v * b1; + t16 += v * b2; + t17 += v * b3; + t18 += v * b4; + t19 += v * b5; + t20 += v * b6; + t21 += v * b7; + t22 += v * b8; + t23 += v * b9; + t24 += v * b10; + t25 += v * b11; + t26 += v * b12; + t27 += v * b13; + t28 += v * b14; + t29 += v * b15; + v = a[15]; + t15 += v * b0; + t16 += v * b1; + t17 += v * b2; + t18 += v * b3; + t19 += v * b4; + t20 += v * b5; + t21 += v * b6; + t22 += v * b7; + t23 += v * b8; + t24 += v * b9; + t25 += v * b10; + t26 += v * b11; + t27 += v * b12; + t28 += v * b13; + t29 += v * b14; + t30 += v * b15; + + t0 += 38 * t16; + t1 += 38 * t17; + t2 += 38 * t18; + t3 += 38 * t19; + t4 += 38 * t20; + t5 += 38 * t21; + t6 += 38 * t22; + t7 += 38 * t23; + t8 += 38 * t24; + t9 += 38 * t25; + t10 += 38 * t26; + t11 += 38 * t27; + t12 += 38 * t28; + t13 += 38 * t29; + t14 += 38 * t30; + // t15 left as is + + // first car + c = 1; + v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536; + v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536; + v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536; + v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536; + v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536; + v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536; + v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536; + v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536; + v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536; + v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536; + v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536; + v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536; + v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536; + v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536; + v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536; + v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536; + t0 += c-1 + 37 * (c-1); + + // second car + c = 1; + v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536; + v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536; + v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536; + v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536; + v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536; + v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536; + v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536; + v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536; + v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536; + v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536; + v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536; + v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536; + v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536; + v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536; + v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536; + v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536; + t0 += c-1 + 37 * (c-1); + + o[ 0] = t0; + o[ 1] = t1; + o[ 2] = t2; + o[ 3] = t3; + o[ 4] = t4; + o[ 5] = t5; + o[ 6] = t6; + o[ 7] = t7; + o[ 8] = t8; + o[ 9] = t9; + o[10] = t10; + o[11] = t11; + o[12] = t12; + o[13] = t13; + o[14] = t14; + o[15] = t15; + } + + function S(o, a) { + M(o, a, a); + } + + function inv25519(o, i) { + var c = gf(); + var a; + for (a = 0; a < 16; a++) c[a] = i[a]; + for (a = 253; a >= 0; a--) { + S(c, c); + if(a !== 2 && a !== 4) M(c, c, i); + } + for (a = 0; a < 16; a++) o[a] = c[a]; + } + + function pow2523(o, i) { + var c = gf(); + var a; + for (a = 0; a < 16; a++) c[a] = i[a]; + for (a = 250; a >= 0; a--) { + S(c, c); + if(a !== 1) M(c, c, i); + } + for (a = 0; a < 16; a++) o[a] = c[a]; + } + + function crypto_scalarmult(q, n, p) { + var z = new Uint8Array(32); + var x = new Float64Array(80), r, i; + var a = gf(), b = gf(), c = gf(), + d = gf(), e = gf(), f = gf(); + for (i = 0; i < 31; i++) z[i] = n[i]; + z[31]=(n[31]&127)|64; + z[0]&=248; + unpack25519(x,p); + for (i = 0; i < 16; i++) { + b[i]=x[i]; + d[i]=a[i]=c[i]=0; + } + a[0]=d[0]=1; + for (i=254; i>=0; --i) { + r=(z[i>>>3]>>>(i&7))&1; + sel25519(a,b,r); + sel25519(c,d,r); + A(e,a,c); + Z(a,a,c); + A(c,b,d); + Z(b,b,d); + S(d,e); + S(f,a); + M(a,c,a); + M(c,b,e); + A(e,a,c); + Z(a,a,c); + S(b,a); + Z(c,d,f); + M(a,c,_121665); + A(a,a,d); + M(c,c,a); + M(a,d,f); + M(d,b,x); + S(b,e); + sel25519(a,b,r); + sel25519(c,d,r); + } + for (i = 0; i < 16; i++) { + x[i+16]=a[i]; + x[i+32]=c[i]; + x[i+48]=b[i]; + x[i+64]=d[i]; + } + var x32 = x.subarray(32); + var x16 = x.subarray(16); + inv25519(x32,x32); + M(x16,x16,x32); + pack25519(q,x16); + return 0; + } + + function crypto_scalarmult_base(q, n) { + return crypto_scalarmult(q, n, _9); + } + + function crypto_box_keypair(y, x) { + randombytes(x, 32); + return crypto_scalarmult_base(y, x); + } + + function add(p, q) { + var a = gf(), b = gf(), c = gf(), + d = gf(), e = gf(), f = gf(), + g = gf(), h = gf(), t = gf(); + + Z(a, p[1], p[0]); + Z(t, q[1], q[0]); + M(a, a, t); + A(b, p[0], p[1]); + A(t, q[0], q[1]); + M(b, b, t); + M(c, p[3], q[3]); + M(c, c, D2); + M(d, p[2], q[2]); + A(d, d, d); + Z(e, b, a); + Z(f, d, c); + A(g, d, c); + A(h, b, a); + + M(p[0], e, f); + M(p[1], h, g); + M(p[2], g, f); + M(p[3], e, h); + } + + function cswap(p, q, b) { + var i; + for (i = 0; i < 4; i++) { + sel25519(p[i], q[i], b); + } + } + + function pack(r, p) { + var tx = gf(), ty = gf(), zi = gf(); + inv25519(zi, p[2]); + M(tx, p[0], zi); + M(ty, p[1], zi); + pack25519(r, ty); + r[31] ^= par25519(tx) << 7; + } + + function scalarmult(p, q, s) { + var b, i; + set25519(p[0], gf0); + set25519(p[1], gf1); + set25519(p[2], gf1); + set25519(p[3], gf0); + for (i = 255; i >= 0; --i) { + b = (s[(i/8)|0] >> (i&7)) & 1; + cswap(p, q, b); + add(q, p); + add(p, p); + cswap(p, q, b); + } + } + + function scalarbase(p, s) { + var q = [gf(), gf(), gf(), gf()]; + set25519(q[0], X); + set25519(q[1], Y); + set25519(q[2], gf1); + M(q[3], X, Y); + scalarmult(p, q, s); + } + + function crypto_sign_keypair(pk, sk, seeded) { + var d; + var p = [gf(), gf(), gf(), gf()]; + var i; + + if (!seeded) randombytes(sk, 32); + d = nacl.hash(sk.subarray(0, 32)); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + scalarbase(p, d); + pack(pk, p); + + for (i = 0; i < 32; i++) sk[i+32] = pk[i]; + return 0; + } + + var L = new Float64Array([0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10]); + + function modL(r, x) { + var carry, i, j, k; + for (i = 63; i >= 32; --i) { + carry = 0; + for (j = i - 32, k = i - 12; j < k; ++j) { + x[j] += carry - 16 * x[i] * L[j - (i - 32)]; + carry = Math.floor((x[j] + 128) / 256); + x[j] -= carry * 256; + } + x[j] += carry; + x[i] = 0; + } + carry = 0; + for (j = 0; j < 32; j++) { + x[j] += carry - (x[31] >> 4) * L[j]; + carry = x[j] >> 8; + x[j] &= 255; + } + for (j = 0; j < 32; j++) x[j] -= carry * L[j]; + for (i = 0; i < 32; i++) { + x[i+1] += x[i] >> 8; + r[i] = x[i] & 255; + } + } + + function reduce(r) { + var x = new Float64Array(64), i; + for (i = 0; i < 64; i++) x[i] = r[i]; + for (i = 0; i < 64; i++) r[i] = 0; + modL(r, x); + } + + // Note: difference from C - smlen returned, not passed as argument. + function crypto_sign(sm, m, n, sk) { + var d, h, r; + var i, j, x = new Float64Array(64); + var p = [gf(), gf(), gf(), gf()]; + + d = nacl.hash(sk.subarray(0, 32)); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + var smlen = n + 64; + for (i = 0; i < n; i++) sm[64 + i] = m[i]; + for (i = 0; i < 32; i++) sm[32 + i] = d[32 + i]; + + r = nacl.hash(sm.subarray(32, smlen)); + reduce(r); + scalarbase(p, r); + pack(sm, p); + + for (i = 32; i < 64; i++) sm[i] = sk[i]; + h = nacl.hash(sm.subarray(0, smlen)); + reduce(h); + + for (i = 0; i < 64; i++) x[i] = 0; + for (i = 0; i < 32; i++) x[i] = r[i]; + for (i = 0; i < 32; i++) { + for (j = 0; j < 32; j++) { + x[i+j] += h[i] * d[j]; + } + } + + modL(sm.subarray(32), x); + return smlen; + } + + function unpackneg(r, p) { + var t = gf(), chk = gf(), num = gf(), + den = gf(), den2 = gf(), den4 = gf(), + den6 = gf(); + + set25519(r[2], gf1); + unpack25519(r[1], p); + S(num, r[1]); + M(den, num, D); + Z(num, num, r[2]); + A(den, r[2], den); + + S(den2, den); + S(den4, den2); + M(den6, den4, den2); + M(t, den6, num); + M(t, t, den); + + pow2523(t, t); + M(t, t, num); + M(t, t, den); + M(t, t, den); + M(r[0], t, den); + + S(chk, r[0]); + M(chk, chk, den); + if (neq25519(chk, num)) M(r[0], r[0], I); + + S(chk, r[0]); + M(chk, chk, den); + if (neq25519(chk, num)) return -1; + + if (par25519(r[0]) === (p[31]>>7)) Z(r[0], gf0, r[0]); + + M(r[3], r[0], r[1]); + return 0; + } + + function crypto_sign_open(m, sm, n, pk) { + var i; + var t = new Uint8Array(32), h; + var p = [gf(), gf(), gf(), gf()], + q = [gf(), gf(), gf(), gf()]; + + if (n < 64) return -1; + + if (unpackneg(q, pk)) return -1; + + for (i = 0; i < n; i++) m[i] = sm[i]; + for (i = 0; i < 32; i++) m[i+32] = pk[i]; + h = nacl.hash(m.subarray(0, n)); + reduce(h); + scalarmult(p, q, h); + + scalarbase(q, sm.subarray(32)); + add(p, q); + pack(t, p); + + n -= 64; + if (crypto_verify_32(sm, 0, t, 0)) { + for (i = 0; i < n; i++) m[i] = 0; + return -1; + } + + for (i = 0; i < n; i++) m[i] = sm[i + 64]; + return n; + } + + var crypto_scalarmult_BYTES = 32, + crypto_scalarmult_SCALARBYTES = 32, + crypto_box_PUBLICKEYBYTES = 32, + crypto_box_SECRETKEYBYTES = 32, + crypto_sign_BYTES = 64, + crypto_sign_PUBLICKEYBYTES = 32, + crypto_sign_SECRETKEYBYTES = 64, + crypto_sign_SEEDBYTES = 32; + + function checkArrayTypes() { + for (var i = 0; i < arguments.length; i++) { + if (!(arguments[i] instanceof Uint8Array)) + throw new TypeError('unexpected type, use Uint8Array'); + } + } + + function cleanup(arr) { + for (var i = 0; i < arr.length; i++) arr[i] = 0; + } + + nacl.scalarMult = function(n, p) { + checkArrayTypes(n, p); + if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error('bad n size'); + if (p.length !== crypto_scalarmult_BYTES) throw new Error('bad p size'); + var q = new Uint8Array(crypto_scalarmult_BYTES); + crypto_scalarmult(q, n, p); + return q; + }; + + nacl.box = {}; + + nacl.box.keyPair = function() { + var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); + var sk = new Uint8Array(crypto_box_SECRETKEYBYTES); + crypto_box_keypair(pk, sk); + return {publicKey: pk, secretKey: sk}; + }; + + nacl.box.keyPair.fromSecretKey = function(secretKey) { + checkArrayTypes(secretKey); + if (secretKey.length !== crypto_box_SECRETKEYBYTES) + throw new Error('bad secret key size'); + var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); + crypto_scalarmult_base(pk, secretKey); + return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; + }; + + nacl.sign = function(msg, secretKey) { + checkArrayTypes(msg, secretKey); + if (secretKey.length !== crypto_sign_SECRETKEYBYTES) + throw new Error('bad secret key size'); + var signedMsg = new Uint8Array(crypto_sign_BYTES+msg.length); + crypto_sign(signedMsg, msg, msg.length, secretKey); + return signedMsg; + }; + + nacl.sign.detached = function(msg, secretKey) { + var signedMsg = nacl.sign(msg, secretKey); + var sig = new Uint8Array(crypto_sign_BYTES); + for (var i = 0; i < sig.length; i++) sig[i] = signedMsg[i]; + return sig; + }; + + nacl.sign.detached.verify = function(msg, sig, publicKey) { + checkArrayTypes(msg, sig, publicKey); + if (sig.length !== crypto_sign_BYTES) + throw new Error('bad signature size'); + if (publicKey.length !== crypto_sign_PUBLICKEYBYTES) + throw new Error('bad public key size'); + var sm = new Uint8Array(crypto_sign_BYTES + msg.length); + var m = new Uint8Array(crypto_sign_BYTES + msg.length); + var i; + for (i = 0; i < crypto_sign_BYTES; i++) sm[i] = sig[i]; + for (i = 0; i < msg.length; i++) sm[i+crypto_sign_BYTES] = msg[i]; + return (crypto_sign_open(m, sm, sm.length, publicKey) >= 0); + }; + + nacl.sign.keyPair = function() { + var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); + var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); + crypto_sign_keypair(pk, sk); + return {publicKey: pk, secretKey: sk}; + }; + + nacl.sign.keyPair.fromSecretKey = function(secretKey) { + checkArrayTypes(secretKey); + if (secretKey.length !== crypto_sign_SECRETKEYBYTES) + throw new Error('bad secret key size'); + var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); + for (var i = 0; i < pk.length; i++) pk[i] = secretKey[32+i]; + return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; + }; + + nacl.sign.keyPair.fromSeed = function(seed) { + checkArrayTypes(seed); + if (seed.length !== crypto_sign_SEEDBYTES) + throw new Error('bad seed size'); + var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); + var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); + for (var i = 0; i < 32; i++) sk[i] = seed[i]; + crypto_sign_keypair(pk, sk, true); + return {publicKey: pk, secretKey: sk}; + }; + + nacl.setPRNG = function(fn) { + randombytes = fn; + }; + + (function() { + // Initialize PRNG if environment provides CSPRNG. + // If not, methods calling randombytes will throw. + var crypto = typeof self !== 'undefined' ? (self.crypto || self.msCrypto) : null; + if (crypto && crypto.getRandomValues) { + // Browsers. + var QUOTA = 65536; + nacl.setPRNG(function(x, n) { + var i, v = new Uint8Array(n); + for (i = 0; i < n; i += QUOTA) { + crypto.getRandomValues(v.subarray(i, i + Math.min(n - i, QUOTA))); + } + for (i = 0; i < n; i++) x[i] = v[i]; + cleanup(v); + }); + } else if (typeof commonjsRequire !== 'undefined') { + // Node.js. + crypto = void('crypto'); + if (crypto && crypto.randomBytes) { + nacl.setPRNG(function(x, n) { + var i, v = crypto.randomBytes(n); + for (i = 0; i < n; i++) x[i] = v[i]; + cleanup(v); + }); + } + } + })(); + + })(module.exports ? module.exports : (self.nacl = self.nacl || {})); + }); + + // GPG4Browsers - An OpenPGP implementation in javascript + + const nodeCrypto$5 = util.getNodeCrypto(); + + /** + * Buffer for secure random numbers + */ + class RandomBuffer { + constructor() { + this.buffer = null; + this.size = null; + this.callback = null; + } + + /** + * Initialize buffer + * @param {Integer} size - size of buffer + */ + init(size, callback) { + this.buffer = new Uint8Array(size); + this.size = 0; + this.callback = callback; + } + + /** + * Concat array of secure random numbers to buffer + * @param {Uint8Array} buf + */ + set(buf) { + if (!this.buffer) { + throw new Error('RandomBuffer is not initialized'); + } + if (!(buf instanceof Uint8Array)) { + throw new Error('Invalid type: buf not an Uint8Array'); + } + const freeSpace = this.buffer.length - this.size; + if (buf.length > freeSpace) { + buf = buf.subarray(0, freeSpace); + } + // set buf with offset old size of buffer + this.buffer.set(buf, this.size); + this.size += buf.length; + } + + /** + * Take numbers out of buffer and copy to array + * @param {Uint8Array} buf - The destination array + */ + async get(buf) { + if (!this.buffer) { + throw new Error('RandomBuffer is not initialized'); + } + if (!(buf instanceof Uint8Array)) { + throw new Error('Invalid type: buf not an Uint8Array'); + } + if (this.size < buf.length) { + if (!this.callback) { + throw new Error('Random number buffer depleted'); + } + // Wait for random bytes from main context, then try again + await this.callback(); + return this.get(buf); + } + for (let i = 0; i < buf.length; i++) { + buf[i] = this.buffer[--this.size]; + // clear buffer value + this.buffer[this.size] = 0; + } + } + } + + /** + * Retrieve secure random byte array of the specified length + * @param {Integer} length - Length in bytes to generate + * @returns {Promise} Random byte array. + * @async + */ + async function getRandomBytes(length) { + const buf = new Uint8Array(length); + if (typeof crypto !== 'undefined' && crypto.getRandomValues) { + crypto.getRandomValues(buf); + } else if (nodeCrypto$5) { + const bytes = nodeCrypto$5.randomBytes(buf.length); + buf.set(bytes); + } else if (randomBuffer.buffer) { + await randomBuffer.get(buf); + } else { + throw new Error('No secure random number generator available.'); + } + return buf; + } + + /** + * Create a secure random BigInteger that is greater than or equal to min and less than max. + * @param {module:BigInteger} min - Lower bound, included + * @param {module:BigInteger} max - Upper bound, excluded + * @returns {Promise} Random BigInteger. + * @async + */ + async function getRandomBigInteger(min, max) { + const BigInteger = await util.getBigInteger(); + + if (max.lt(min)) { + throw new Error('Illegal parameter value: max <= min'); + } + + const modulus = max.sub(min); + const bytes = modulus.byteLength(); + + // Using a while loop is necessary to avoid bias introduced by the mod operation. + // However, we request 64 extra random bits so that the bias is negligible. + // Section B.1.1 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf + const r = new BigInteger(await getRandomBytes(bytes + 8)); + return r.mod(modulus).add(min); + } + + const randomBuffer = new RandomBuffer(); + + var random = /*#__PURE__*/Object.freeze({ + __proto__: null, + getRandomBytes: getRandomBytes, + getRandomBigInteger: getRandomBigInteger, + randomBuffer: randomBuffer + }); + + // OpenPGP.js - An OpenPGP implementation in javascript + + /** + * Generate a probably prime random number + * @param {Integer} bits - Bit length of the prime + * @param {BigInteger} e - Optional RSA exponent to check against the prime + * @param {Integer} k - Optional number of iterations of Miller-Rabin test + * @returns BigInteger + * @async + */ + async function randomProbablePrime(bits, e, k) { + const BigInteger = await util.getBigInteger(); + const one = new BigInteger(1); + const min = one.leftShift(new BigInteger(bits - 1)); + const thirty = new BigInteger(30); + /* + * We can avoid any multiples of 3 and 5 by looking at n mod 30 + * n mod 30 = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 + * the next possible prime is mod 30: + * 1 7 7 7 7 7 7 11 11 11 11 13 13 17 17 17 17 19 19 23 23 23 23 29 29 29 29 29 29 1 + */ + const adds = [1, 6, 5, 4, 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, 3, 2, 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1, 2]; + + const n = await getRandomBigInteger(min, min.leftShift(one)); + let i = n.mod(thirty).toNumber(); + + do { + n.iadd(new BigInteger(adds[i])); + i = (i + adds[i]) % adds.length; + // If reached the maximum, go back to the minimum. + if (n.bitLength() > bits) { + n.imod(min.leftShift(one)).iadd(min); + i = n.mod(thirty).toNumber(); + } + } while (!await isProbablePrime(n, e, k)); + return n; + } + + /** + * Probabilistic primality testing + * @param {BigInteger} n - Number to test + * @param {BigInteger} e - Optional RSA exponent to check against the prime + * @param {Integer} k - Optional number of iterations of Miller-Rabin test + * @returns {boolean} + * @async + */ + async function isProbablePrime(n, e, k) { + if (e && !n.dec().gcd(e).isOne()) { + return false; + } + if (!await divisionTest(n)) { + return false; + } + if (!await fermat(n)) { + return false; + } + if (!await millerRabin(n, k)) { + return false; + } + // TODO implement the Lucas test + // See Section C.3.3 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf + return true; + } + + /** + * Tests whether n is probably prime or not using Fermat's test with b = 2. + * Fails if b^(n-1) mod n != 1. + * @param {BigInteger} n - Number to test + * @param {BigInteger} b - Optional Fermat test base + * @returns {boolean} + */ + async function fermat(n, b) { + const BigInteger = await util.getBigInteger(); + b = b || new BigInteger(2); + return b.modExp(n.dec(), n).isOne(); + } + + async function divisionTest(n) { + const BigInteger = await util.getBigInteger(); + return smallPrimes.every(m => { + return n.mod(new BigInteger(m)) !== 0; + }); + } + + // https://github.com/gpg/libgcrypt/blob/master/cipher/primegen.c + const smallPrimes = [ + 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, + 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, + 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, + 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, + 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, + 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, + 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, + 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, + 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, + 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, + 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, + 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, + 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, + 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, + 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, + 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, + 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, + 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, + 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, + 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, + 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, + 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, + 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, + 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, + 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, + 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, + 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, + 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, + 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, + 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, + 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, + 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, + 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, + 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, + 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, + 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, + 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, + 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, + 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, + 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, + 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, + 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, + 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, + 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, + 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, + 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, + 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, + 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, + 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, + 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, + 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, + 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, + 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, + 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, + 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, + 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, + 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, + 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, + 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, + 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, + 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, + 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, + 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, + 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, + 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, + 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, + 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, + 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, + 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, + 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, + 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457, + 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, + 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, + 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, + 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, + 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, + 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, + 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, + 4957, 4967, 4969, 4973, 4987, 4993, 4999 + ]; + + + // Miller-Rabin - Miller Rabin algorithm for primality test + // Copyright Fedor Indutny, 2014. + // + // This software is licensed under the MIT License. + // + // Permission is hereby granted, free of charge, to any person obtaining a + // copy of this software and associated documentation files (the + // "Software"), to deal in the Software without restriction, including + // without limitation the rights to use, copy, modify, merge, publish, + // distribute, sublicense, and/or sell copies of the Software, and to permit + // persons to whom the Software is furnished to do so, subject to the + // following conditions: + // + // The above copyright notice and this permission notice shall be included + // in all copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + // USE OR OTHER DEALINGS IN THE SOFTWARE. + + // Adapted on Jan 2018 from version 4.0.1 at https://github.com/indutny/miller-rabin + + // Sample syntax for Fixed-Base Miller-Rabin: + // millerRabin(n, k, () => new BN(small_primes[Math.random() * small_primes.length | 0])) + + /** + * Tests whether n is probably prime or not using the Miller-Rabin test. + * See HAC Remark 4.28. + * @param {BigInteger} n - Number to test + * @param {Integer} k - Optional number of iterations of Miller-Rabin test + * @param {Function} rand - Optional function to generate potential witnesses + * @returns {boolean} + * @async + */ + async function millerRabin(n, k, rand) { + const BigInteger = await util.getBigInteger(); + const len = n.bitLength(); + + if (!k) { + k = Math.max(1, (len / 48) | 0); + } + + const n1 = n.dec(); // n - 1 + + // Find d and s, (n - 1) = (2 ^ s) * d; + let s = 0; + while (!n1.getBit(s)) { s++; } + const d = n.rightShift(new BigInteger(s)); + + for (; k > 0; k--) { + const a = rand ? rand() : await getRandomBigInteger(new BigInteger(2), n1); + + let x = a.modExp(d, n); + if (x.isOne() || x.equal(n1)) { + continue; + } + + let i; + for (i = 1; i < s; i++) { + x = x.mul(x).mod(n); + + if (x.isOne()) { + return false; + } + if (x.equal(n1)) { + break; + } + } + + if (i === s) { + return false; + } + } + + return true; + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + /** + * ASN1 object identifiers for hashes + * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.2} + */ + const hash_headers = []; + hash_headers[1] = [0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, + 0x10]; + hash_headers[2] = [0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14]; + hash_headers[3] = [0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14]; + hash_headers[8] = [0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, + 0x04, 0x20]; + hash_headers[9] = [0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, + 0x04, 0x30]; + hash_headers[10] = [0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, + 0x00, 0x04, 0x40]; + hash_headers[11] = [0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, + 0x00, 0x04, 0x1C]; + + /** + * Create padding with secure random data + * @private + * @param {Integer} length - Length of the padding in bytes + * @returns {Promise} Random padding. + * @async + */ + async function getPKCS1Padding(length) { + const result = new Uint8Array(length); + let count = 0; + while (count < length) { + const randomBytes = await getRandomBytes(length - count); + for (let i = 0; i < randomBytes.length; i++) { + if (randomBytes[i] !== 0) { + result[count++] = randomBytes[i]; + } + } + } + return result; + } + + /** + * Create a EME-PKCS1-v1_5 padded message + * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.1|RFC 4880 13.1.1} + * @param {Uint8Array} message - Message to be encoded + * @param {Integer} keyLength - The length in octets of the key modulus + * @returns {Promise} EME-PKCS1 padded message. + * @async + */ + async function emeEncode(message, keyLength) { + const mLength = message.length; + // length checking + if (mLength > keyLength - 11) { + throw new Error('Message too long'); + } + // Generate an octet string PS of length k - mLen - 3 consisting of + // pseudo-randomly generated nonzero octets + const PS = await getPKCS1Padding(keyLength - mLength - 3); + // Concatenate PS, the message M, and other padding to form an + // encoded message EM of length k octets as EM = 0x00 || 0x02 || PS || 0x00 || M. + const encoded = new Uint8Array(keyLength); + // 0x00 byte + encoded[1] = 2; + encoded.set(PS, 2); + // 0x00 bytes + encoded.set(message, keyLength - mLength); + return encoded; + } + + /** + * Decode a EME-PKCS1-v1_5 padded message + * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.2|RFC 4880 13.1.2} + * @param {Uint8Array} encoded - Encoded message bytes + * @param {Uint8Array} randomPayload - Data to return in case of decoding error (needed for constant-time processing) + * @returns {Uint8Array} decoded data or `randomPayload` (on error, if given) + * @throws {Error} on decoding failure, unless `randomPayload` is provided + */ + function emeDecode(encoded, randomPayload) { + // encoded format: 0x00 0x02 0x00 + let offset = 2; + let separatorNotFound = 1; + for (let j = offset; j < encoded.length; j++) { + separatorNotFound &= encoded[j] !== 0; + offset += separatorNotFound; + } + + const psLen = offset - 2; + const payload = encoded.subarray(offset + 1); // discard the 0x00 separator + const isValidPadding = encoded[0] === 0 & encoded[1] === 2 & psLen >= 8 & !separatorNotFound; + + if (randomPayload) { + return util.selectUint8Array(isValidPadding, payload, randomPayload); + } + + if (isValidPadding) { + return payload; + } + + throw new Error('Decryption error'); + } + + /** + * Create a EMSA-PKCS1-v1_5 padded message + * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.3|RFC 4880 13.1.3} + * @param {Integer} algo - Hash algorithm type used + * @param {Uint8Array} hashed - Message to be encoded + * @param {Integer} emLen - Intended length in octets of the encoded message + * @returns {Uint8Array} Encoded message. + */ + async function emsaEncode(algo, hashed, emLen) { + let i; + if (hashed.length !== hash.getHashByteLength(algo)) { + throw new Error('Invalid hash length'); + } + // produce an ASN.1 DER value for the hash function used. + // Let T be the full hash prefix + const hashPrefix = new Uint8Array(hash_headers[algo].length); + for (i = 0; i < hash_headers[algo].length; i++) { + hashPrefix[i] = hash_headers[algo][i]; + } + // and let tLen be the length in octets prefix and hashed data + const tLen = hashPrefix.length + hashed.length; + if (emLen < tLen + 11) { + throw new Error('Intended encoded message length too short'); + } + // an octet string PS consisting of emLen - tLen - 3 octets with hexadecimal value 0xFF + // The length of PS will be at least 8 octets + const PS = new Uint8Array(emLen - tLen - 3).fill(0xff); + + // Concatenate PS, the hash prefix, hashed data, and other padding to form the + // encoded message EM as EM = 0x00 || 0x01 || PS || 0x00 || prefix || hashed + const EM = new Uint8Array(emLen); + EM[1] = 0x01; + EM.set(PS, 2); + EM.set(hashPrefix, emLen - tLen); + EM.set(hashed, emLen - hashed.length); + return EM; + } + + var pkcs1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + emeEncode: emeEncode, + emeDecode: emeDecode, + emsaEncode: emsaEncode + }); + + // GPG4Browsers - An OpenPGP implementation in javascript + + const webCrypto$5 = util.getWebCrypto(); + const nodeCrypto$6 = util.getNodeCrypto(); + const asn1 = nodeCrypto$6 ? void('asn1.js') : undefined; + + /* eslint-disable no-invalid-this */ + const RSAPrivateKey = util.detectNode() ? asn1.define('RSAPrivateKey', function () { + this.seq().obj( // used for native NodeJS crypto + this.key('version').int(), // 0 + this.key('modulus').int(), // n + this.key('publicExponent').int(), // e + this.key('privateExponent').int(), // d + this.key('prime1').int(), // p + this.key('prime2').int(), // q + this.key('exponent1').int(), // dp + this.key('exponent2').int(), // dq + this.key('coefficient').int() // u + ); + }) : undefined; + + const RSAPublicKey = util.detectNode() ? asn1.define('RSAPubliceKey', function () { + this.seq().obj( // used for native NodeJS crypto + this.key('modulus').int(), // n + this.key('publicExponent').int(), // e + ); + }) : undefined; + /* eslint-enable no-invalid-this */ + + /** Create signature + * @param {module:enums.hash} hashAlgo - Hash algorithm + * @param {Uint8Array} data - Message + * @param {Uint8Array} n - RSA public modulus + * @param {Uint8Array} e - RSA public exponent + * @param {Uint8Array} d - RSA private exponent + * @param {Uint8Array} p - RSA private prime p + * @param {Uint8Array} q - RSA private prime q + * @param {Uint8Array} u - RSA private coefficient + * @param {Uint8Array} hashed - Hashed message + * @returns {Promise} RSA Signature. + * @async + */ + async function sign(hashAlgo, data, n, e, d, p, q, u, hashed) { + if (data && !util.isStream(data)) { + if (util.getWebCrypto()) { + try { + return await webSign(enums.read(enums.webHash, hashAlgo), data, n, e, d, p, q, u); + } catch (err) { + util.printDebugError(err); + } + } else if (util.getNodeCrypto()) { + return nodeSign(hashAlgo, data, n, e, d, p, q, u); + } + } + return bnSign(hashAlgo, n, d, hashed); + } + + /** + * Verify signature + * @param {module:enums.hash} hashAlgo - Hash algorithm + * @param {Uint8Array} data - Message + * @param {Uint8Array} s - Signature + * @param {Uint8Array} n - RSA public modulus + * @param {Uint8Array} e - RSA public exponent + * @param {Uint8Array} hashed - Hashed message + * @returns {Boolean} + * @async + */ + async function verify(hashAlgo, data, s, n, e, hashed) { + if (data && !util.isStream(data)) { + if (util.getWebCrypto()) { + try { + return await webVerify(enums.read(enums.webHash, hashAlgo), data, s, n, e); + } catch (err) { + util.printDebugError(err); + } + } else if (util.getNodeCrypto()) { + return nodeVerify(hashAlgo, data, s, n, e); + } + } + return bnVerify(hashAlgo, s, n, e, hashed); + } + + /** + * Encrypt message + * @param {Uint8Array} data - Message + * @param {Uint8Array} n - RSA public modulus + * @param {Uint8Array} e - RSA public exponent + * @returns {Promise} RSA Ciphertext. + * @async + */ + async function encrypt$1(data, n, e) { + if (util.getNodeCrypto()) { + return nodeEncrypt$1(data, n, e); + } + return bnEncrypt(data, n, e); + } + + /** + * Decrypt RSA message + * @param {Uint8Array} m - Message + * @param {Uint8Array} n - RSA public modulus + * @param {Uint8Array} e - RSA public exponent + * @param {Uint8Array} d - RSA private exponent + * @param {Uint8Array} p - RSA private prime p + * @param {Uint8Array} q - RSA private prime q + * @param {Uint8Array} u - RSA private coefficient + * @param {Uint8Array} randomPayload - Data to return on decryption error, instead of throwing + * (needed for constant-time processing) + * @returns {Promise} RSA Plaintext. + * @throws {Error} on decryption error, unless `randomPayload` is given + * @async + */ + async function decrypt$1(data, n, e, d, p, q, u, randomPayload) { + if (util.getNodeCrypto()) { + return nodeDecrypt$1(data, n, e, d, p, q, u, randomPayload); + } + return bnDecrypt(data, n, e, d, p, q, u, randomPayload); + } + + /** + * Generate a new random private key B bits long with public exponent E. + * + * When possible, webCrypto or nodeCrypto is used. Otherwise, primes are generated using + * 40 rounds of the Miller-Rabin probabilistic random prime generation algorithm. + * @see module:crypto/public_key/prime + * @param {Integer} bits - RSA bit length + * @param {Integer} e - RSA public exponent + * @returns {{n, e, d, + * p, q ,u: Uint8Array}} RSA public modulus, RSA public exponent, RSA private exponent, + * RSA private prime p, RSA private prime q, u = p ** -1 mod q + * @async + */ + async function generate(bits, e) { + const BigInteger = await util.getBigInteger(); + + e = new BigInteger(e); + + // Native RSA keygen using Web Crypto + if (util.getWebCrypto()) { + const keyGenOpt = { + name: 'RSASSA-PKCS1-v1_5', + modulusLength: bits, // the specified keysize in bits + publicExponent: e.toUint8Array(), // take three bytes (max 65537) for exponent + hash: { + name: 'SHA-1' // not required for actual RSA keys, but for crypto api 'sign' and 'verify' + } + }; + const keyPair = await webCrypto$5.generateKey(keyGenOpt, true, ['sign', 'verify']); + + // export the generated keys as JsonWebKey (JWK) + // https://tools.ietf.org/html/draft-ietf-jose-json-web-key-33 + const jwk = await webCrypto$5.exportKey('jwk', keyPair.privateKey); + // map JWK parameters to corresponding OpenPGP names + return { + n: b64ToUint8Array(jwk.n), + e: e.toUint8Array(), + d: b64ToUint8Array(jwk.d), + // switch p and q + p: b64ToUint8Array(jwk.q), + q: b64ToUint8Array(jwk.p), + // Since p and q are switched in places, u is the inverse of jwk.q + u: b64ToUint8Array(jwk.qi) + }; + } else if (util.getNodeCrypto() && nodeCrypto$6.generateKeyPair && RSAPrivateKey) { + const opts = { + modulusLength: bits, + publicExponent: e.toNumber(), + publicKeyEncoding: { type: 'pkcs1', format: 'der' }, + privateKeyEncoding: { type: 'pkcs1', format: 'der' } + }; + const prv = await new Promise((resolve, reject) => nodeCrypto$6.generateKeyPair('rsa', opts, (err, _, der) => { + if (err) { + reject(err); + } else { + resolve(RSAPrivateKey.decode(der, 'der')); + } + })); + /** + * OpenPGP spec differs from DER spec, DER: `u = (inverse of q) mod p`, OpenPGP: `u = (inverse of p) mod q`. + * @link https://tools.ietf.org/html/rfc3447#section-3.2 + * @link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-08#section-5.6.1 + */ + return { + n: prv.modulus.toArrayLike(Uint8Array), + e: prv.publicExponent.toArrayLike(Uint8Array), + d: prv.privateExponent.toArrayLike(Uint8Array), + // switch p and q + p: prv.prime2.toArrayLike(Uint8Array), + q: prv.prime1.toArrayLike(Uint8Array), + // Since p and q are switched in places, we can keep u as defined by DER + u: prv.coefficient.toArrayLike(Uint8Array) + }; + } + + // RSA keygen fallback using 40 iterations of the Miller-Rabin test + // See https://stackoverflow.com/a/6330138 for justification + // Also see section C.3 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST + let p; + let q; + let n; + do { + q = await randomProbablePrime(bits - (bits >> 1), e, 40); + p = await randomProbablePrime(bits >> 1, e, 40); + n = p.mul(q); + } while (n.bitLength() !== bits); + + const phi = p.dec().imul(q.dec()); + + if (q.lt(p)) { + [p, q] = [q, p]; + } + + return { + n: n.toUint8Array(), + e: e.toUint8Array(), + d: e.modInv(phi).toUint8Array(), + p: p.toUint8Array(), + q: q.toUint8Array(), + // dp: d.mod(p.subn(1)), + // dq: d.mod(q.subn(1)), + u: p.modInv(q).toUint8Array() + }; + } + + /** + * Validate RSA parameters + * @param {Uint8Array} n - RSA public modulus + * @param {Uint8Array} e - RSA public exponent + * @param {Uint8Array} d - RSA private exponent + * @param {Uint8Array} p - RSA private prime p + * @param {Uint8Array} q - RSA private prime q + * @param {Uint8Array} u - RSA inverse of p w.r.t. q + * @returns {Promise} Whether params are valid. + * @async + */ + async function validateParams(n, e, d, p, q, u) { + const BigInteger = await util.getBigInteger(); + n = new BigInteger(n); + p = new BigInteger(p); + q = new BigInteger(q); + + // expect pq = n + if (!p.mul(q).equal(n)) { + return false; + } + + const two = new BigInteger(2); + // expect p*u = 1 mod q + u = new BigInteger(u); + if (!p.mul(u).mod(q).isOne()) { + return false; + } + + e = new BigInteger(e); + d = new BigInteger(d); + /** + * In RSA pkcs#1 the exponents (d, e) are inverses modulo lcm(p-1, q-1) + * We check that [de = 1 mod (p-1)] and [de = 1 mod (q-1)] + * By CRT on coprime factors of (p-1, q-1) it follows that [de = 1 mod lcm(p-1, q-1)] + * + * We blind the multiplication with r, and check that rde = r mod lcm(p-1, q-1) + */ + const nSizeOver3 = new BigInteger(Math.floor(n.bitLength() / 3)); + const r = await getRandomBigInteger(two, two.leftShift(nSizeOver3)); // r in [ 2, 2^{|n|/3} ) < p and q + const rde = r.mul(d).mul(e); + + const areInverses = rde.mod(p.dec()).equal(r) && rde.mod(q.dec()).equal(r); + if (!areInverses) { + return false; + } + + return true; + } + + async function bnSign(hashAlgo, n, d, hashed) { + const BigInteger = await util.getBigInteger(); + n = new BigInteger(n); + const m = new BigInteger(await emsaEncode(hashAlgo, hashed, n.byteLength())); + d = new BigInteger(d); + if (m.gte(n)) { + throw new Error('Message size cannot exceed modulus size'); + } + return m.modExp(d, n).toUint8Array('be', n.byteLength()); + } + + async function webSign(hashName, data, n, e, d, p, q, u) { + /** OpenPGP keys require that p < q, and Safari Web Crypto requires that p > q. + * We swap them in privateToJWK, so it usually works out, but nevertheless, + * not all OpenPGP keys are compatible with this requirement. + * OpenPGP.js used to generate RSA keys the wrong way around (p > q), and still + * does if the underlying Web Crypto does so (e.g. old MS Edge 50% of the time). + */ + const jwk = await privateToJWK(n, e, d, p, q, u); + const algo = { + name: 'RSASSA-PKCS1-v1_5', + hash: { name: hashName } + }; + const key = await webCrypto$5.importKey('jwk', jwk, algo, false, ['sign']); + // add hash field for ms edge support + return new Uint8Array(await webCrypto$5.sign({ 'name': 'RSASSA-PKCS1-v1_5', 'hash': hashName }, key, data)); + } + + async function nodeSign(hashAlgo, data, n, e, d, p, q, u) { + const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); + const pBNum = new BN(p); + const qBNum = new BN(q); + const dBNum = new BN(d); + const dq = dBNum.mod(qBNum.subn(1)); // d mod (q-1) + const dp = dBNum.mod(pBNum.subn(1)); // d mod (p-1) + const sign = nodeCrypto$6.createSign(enums.read(enums.hash, hashAlgo)); + sign.write(data); + sign.end(); + const keyObject = { + version: 0, + modulus: new BN(n), + publicExponent: new BN(e), + privateExponent: new BN(d), + // switch p and q + prime1: new BN(q), + prime2: new BN(p), + // switch dp and dq + exponent1: dq, + exponent2: dp, + coefficient: new BN(u) + }; + if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { //from version 11.6.0 Node supports der encoded key objects + const der = RSAPrivateKey.encode(keyObject, 'der'); + return new Uint8Array(sign.sign({ key: der, format: 'der', type: 'pkcs1' })); + } + const pem = RSAPrivateKey.encode(keyObject, 'pem', { + label: 'RSA PRIVATE KEY' + }); + return new Uint8Array(sign.sign(pem)); + } + + async function bnVerify(hashAlgo, s, n, e, hashed) { + const BigInteger = await util.getBigInteger(); + n = new BigInteger(n); + s = new BigInteger(s); + e = new BigInteger(e); + if (s.gte(n)) { + throw new Error('Signature size cannot exceed modulus size'); + } + const EM1 = s.modExp(e, n).toUint8Array('be', n.byteLength()); + const EM2 = await emsaEncode(hashAlgo, hashed, n.byteLength()); + return util.equalsUint8Array(EM1, EM2); + } + + async function webVerify(hashName, data, s, n, e) { + const jwk = publicToJWK(n, e); + const key = await webCrypto$5.importKey('jwk', jwk, { + name: 'RSASSA-PKCS1-v1_5', + hash: { name: hashName } + }, false, ['verify']); + // add hash field for ms edge support + return webCrypto$5.verify({ 'name': 'RSASSA-PKCS1-v1_5', 'hash': hashName }, key, s, data); + } + + async function nodeVerify(hashAlgo, data, s, n, e) { + const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); + + const verify = nodeCrypto$6.createVerify(enums.read(enums.hash, hashAlgo)); + verify.write(data); + verify.end(); + const keyObject = { + modulus: new BN(n), + publicExponent: new BN(e) + }; + let key; + if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { //from version 11.6.0 Node supports der encoded key objects + const der = RSAPublicKey.encode(keyObject, 'der'); + key = { key: der, format: 'der', type: 'pkcs1' }; + } else { + key = RSAPublicKey.encode(keyObject, 'pem', { + label: 'RSA PUBLIC KEY' + }); + } + try { + return await verify.verify(key, s); + } catch (err) { + return false; + } + } + + async function nodeEncrypt$1(data, n, e) { + const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); + + const keyObject = { + modulus: new BN(n), + publicExponent: new BN(e) + }; + let key; + if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { + const der = RSAPublicKey.encode(keyObject, 'der'); + key = { key: der, format: 'der', type: 'pkcs1', padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; + } else { + const pem = RSAPublicKey.encode(keyObject, 'pem', { + label: 'RSA PUBLIC KEY' + }); + key = { key: pem, padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; + } + return new Uint8Array(nodeCrypto$6.publicEncrypt(key, data)); + } + + async function bnEncrypt(data, n, e) { + const BigInteger = await util.getBigInteger(); + n = new BigInteger(n); + data = new BigInteger(await emeEncode(data, n.byteLength())); + e = new BigInteger(e); + if (data.gte(n)) { + throw new Error('Message size cannot exceed modulus size'); + } + return data.modExp(e, n).toUint8Array('be', n.byteLength()); + } + + async function nodeDecrypt$1(data, n, e, d, p, q, u, randomPayload) { + const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); + + const pBNum = new BN(p); + const qBNum = new BN(q); + const dBNum = new BN(d); + const dq = dBNum.mod(qBNum.subn(1)); // d mod (q-1) + const dp = dBNum.mod(pBNum.subn(1)); // d mod (p-1) + const keyObject = { + version: 0, + modulus: new BN(n), + publicExponent: new BN(e), + privateExponent: new BN(d), + // switch p and q + prime1: new BN(q), + prime2: new BN(p), + // switch dp and dq + exponent1: dq, + exponent2: dp, + coefficient: new BN(u) + }; + let key; + if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { + const der = RSAPrivateKey.encode(keyObject, 'der'); + key = { key: der, format: 'der' , type: 'pkcs1', padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; + } else { + const pem = RSAPrivateKey.encode(keyObject, 'pem', { + label: 'RSA PRIVATE KEY' + }); + key = { key: pem, padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; + } + try { + return new Uint8Array(nodeCrypto$6.privateDecrypt(key, data)); + } catch (err) { + if (randomPayload) { + return randomPayload; + } + throw new Error('Decryption error'); + } + } + + async function bnDecrypt(data, n, e, d, p, q, u, randomPayload) { + const BigInteger = await util.getBigInteger(); + data = new BigInteger(data); + n = new BigInteger(n); + e = new BigInteger(e); + d = new BigInteger(d); + p = new BigInteger(p); + q = new BigInteger(q); + u = new BigInteger(u); + if (data.gte(n)) { + throw new Error('Data too large.'); + } + const dq = d.mod(q.dec()); // d mod (q-1) + const dp = d.mod(p.dec()); // d mod (p-1) + + const unblinder = (await getRandomBigInteger(new BigInteger(2), n)).mod(n); + const blinder = unblinder.modInv(n).modExp(e, n); + data = data.mul(blinder).mod(n); + + + const mp = data.modExp(dp, p); // data**{d mod (q-1)} mod p + const mq = data.modExp(dq, q); // data**{d mod (p-1)} mod q + const h = u.mul(mq.sub(mp)).mod(q); // u * (mq-mp) mod q (operands already < q) + + let result = h.mul(p).add(mp); // result < n due to relations above + + result = result.mul(unblinder).mod(n); + + + return emeDecode(result.toUint8Array('be', n.byteLength()), randomPayload); + } + + /** Convert Openpgp private key params to jwk key according to + * @link https://tools.ietf.org/html/rfc7517 + * @param {String} hashAlgo + * @param {Uint8Array} n + * @param {Uint8Array} e + * @param {Uint8Array} d + * @param {Uint8Array} p + * @param {Uint8Array} q + * @param {Uint8Array} u + */ + async function privateToJWK(n, e, d, p, q, u) { + const BigInteger = await util.getBigInteger(); + const pNum = new BigInteger(p); + const qNum = new BigInteger(q); + const dNum = new BigInteger(d); + + let dq = dNum.mod(qNum.dec()); // d mod (q-1) + let dp = dNum.mod(pNum.dec()); // d mod (p-1) + dp = dp.toUint8Array(); + dq = dq.toUint8Array(); + return { + kty: 'RSA', + n: uint8ArrayToB64(n, true), + e: uint8ArrayToB64(e, true), + d: uint8ArrayToB64(d, true), + // switch p and q + p: uint8ArrayToB64(q, true), + q: uint8ArrayToB64(p, true), + // switch dp and dq + dp: uint8ArrayToB64(dq, true), + dq: uint8ArrayToB64(dp, true), + qi: uint8ArrayToB64(u, true), + ext: true + }; + } + + /** Convert Openpgp key public params to jwk key according to + * @link https://tools.ietf.org/html/rfc7517 + * @param {String} hashAlgo + * @param {Uint8Array} n + * @param {Uint8Array} e + */ + function publicToJWK(n, e) { + return { + kty: 'RSA', + n: uint8ArrayToB64(n, true), + e: uint8ArrayToB64(e, true), + ext: true + }; + } + + var rsa = /*#__PURE__*/Object.freeze({ + __proto__: null, + sign: sign, + verify: verify, + encrypt: encrypt$1, + decrypt: decrypt$1, + generate: generate, + validateParams: validateParams + }); + + // GPG4Browsers - An OpenPGP implementation in javascript + + /** + * ElGamal Encryption function + * Note that in OpenPGP, the message needs to be padded with PKCS#1 (same as RSA) + * @param {Uint8Array} data - To be padded and encrypted + * @param {Uint8Array} p + * @param {Uint8Array} g + * @param {Uint8Array} y + * @returns {Promise<{ c1: Uint8Array, c2: Uint8Array }>} + * @async + */ + async function encrypt$2(data, p, g, y) { + const BigInteger = await util.getBigInteger(); + p = new BigInteger(p); + g = new BigInteger(g); + y = new BigInteger(y); + + const padded = await emeEncode(data, p.byteLength()); + const m = new BigInteger(padded); + + // OpenPGP uses a "special" version of ElGamal where g is generator of the full group Z/pZ* + // hence g has order p-1, and to avoid that k = 0 mod p-1, we need to pick k in [1, p-2] + const k = await getRandomBigInteger(new BigInteger(1), p.dec()); + return { + c1: g.modExp(k, p).toUint8Array(), + c2: y.modExp(k, p).imul(m).imod(p).toUint8Array() + }; + } + + /** + * ElGamal Encryption function + * @param {Uint8Array} c1 + * @param {Uint8Array} c2 + * @param {Uint8Array} p + * @param {Uint8Array} x + * @param {Uint8Array} randomPayload - Data to return on unpadding error, instead of throwing + * (needed for constant-time processing) + * @returns {Promise} Unpadded message. + * @throws {Error} on decryption error, unless `randomPayload` is given + * @async + */ + async function decrypt$2(c1, c2, p, x, randomPayload) { + const BigInteger = await util.getBigInteger(); + c1 = new BigInteger(c1); + c2 = new BigInteger(c2); + p = new BigInteger(p); + x = new BigInteger(x); + + const padded = c1.modExp(x, p).modInv(p).imul(c2).imod(p); + return emeDecode(padded.toUint8Array('be', p.byteLength()), randomPayload); + } + + /** + * Validate ElGamal parameters + * @param {Uint8Array} p - ElGamal prime + * @param {Uint8Array} g - ElGamal group generator + * @param {Uint8Array} y - ElGamal public key + * @param {Uint8Array} x - ElGamal private exponent + * @returns {Promise} Whether params are valid. + * @async + */ + async function validateParams$1(p, g, y, x) { + const BigInteger = await util.getBigInteger(); + p = new BigInteger(p); + g = new BigInteger(g); + y = new BigInteger(y); + + const one = new BigInteger(1); + // Check that 1 < g < p + if (g.lte(one) || g.gte(p)) { + return false; + } + + // Expect p-1 to be large + const pSize = new BigInteger(p.bitLength()); + const n1023 = new BigInteger(1023); + if (pSize.lt(n1023)) { + return false; + } + + /** + * g should have order p-1 + * Check that g ** (p-1) = 1 mod p + */ + if (!g.modExp(p.dec(), p).isOne()) { + return false; + } + + /** + * Since p-1 is not prime, g might have a smaller order that divides p-1 + * We want to make sure that the order is large enough to hinder a small subgroup attack + * + * We just check g**i != 1 for all i up to a threshold + */ + let res = g; + const i = new BigInteger(1); + const threshold = new BigInteger(2).leftShift(new BigInteger(17)); // we want order > threshold + while (i.lt(threshold)) { + res = res.mul(g).imod(p); + if (res.isOne()) { + return false; + } + i.iinc(); + } + + /** + * Re-derive public key y' = g ** x mod p + * Expect y == y' + * + * Blinded exponentiation computes g**{r(p-1) + x} to compare to y + */ + x = new BigInteger(x); + const two = new BigInteger(2); + const r = await getRandomBigInteger(two.leftShift(pSize.dec()), two.leftShift(pSize)); // draw r of same size as p-1 + const rqx = p.dec().imul(r).iadd(x); + if (!y.equal(g.modExp(rqx, p))) { + return false; + } + + return true; + } + + var elgamal = /*#__PURE__*/Object.freeze({ + __proto__: null, + encrypt: encrypt$2, + decrypt: decrypt$2, + validateParams: validateParams$1 + }); + + // OpenPGP.js - An OpenPGP implementation in javascript + + class OID { + constructor(oid) { + if (oid instanceof OID) { + this.oid = oid.oid; + } else if (util.isArray(oid) || + util.isUint8Array(oid)) { + oid = new Uint8Array(oid); + if (oid[0] === 0x06) { // DER encoded oid byte array + if (oid[1] !== oid.length - 2) { + throw new Error('Length mismatch in DER encoded oid'); + } + oid = oid.subarray(2); + } + this.oid = oid; + } else { + this.oid = ''; + } + } + + /** + * Method to read an OID object + * @param {Uint8Array} input - Where to read the OID from + * @returns {Number} Number of read bytes. + */ + read(input) { + if (input.length >= 1) { + const length = input[0]; + if (input.length >= 1 + length) { + this.oid = input.subarray(1, 1 + length); + return 1 + this.oid.length; + } + } + throw new Error('Invalid oid'); + } + + /** + * Serialize an OID object + * @returns {Uint8Array} Array with the serialized value the OID. + */ + write() { + return util.concatUint8Array([new Uint8Array([this.oid.length]), this.oid]); + } + + /** + * Serialize an OID object as a hex string + * @returns {string} String with the hex value of the OID. + */ + toHex() { + return util.uint8ArrayToHex(this.oid); + } + + /** + * If a known curve object identifier, return the canonical name of the curve + * @returns {string} String with the canonical name of the curve. + */ + getName() { + const hex = this.toHex(); + if (enums.curve[hex]) { + return enums.write(enums.curve, hex); + } else { + throw new Error('Unknown curve object identifier.'); + } + } + } + + // OpenPGP.js - An OpenPGP implementation in javascript + + function keyFromPrivate(indutnyCurve, priv) { + const keyPair = indutnyCurve.keyPair({ priv: priv }); + return keyPair; + } + + function keyFromPublic(indutnyCurve, pub) { + const keyPair = indutnyCurve.keyPair({ pub: pub }); + if (keyPair.validate().result !== true) { + throw new Error('Invalid elliptic public key'); + } + return keyPair; + } + + async function getIndutnyCurve(name) { + if (!defaultConfig.useIndutnyElliptic) { + throw new Error('This curve is only supported in the full build of OpenPGP.js'); + } + const { default: elliptic } = await Promise.resolve().then(function () { return elliptic$1; }); + return new elliptic.ec(name); + } + + // OpenPGP.js - An OpenPGP implementation in javascript + + const webCrypto$6 = util.getWebCrypto(); + const nodeCrypto$7 = util.getNodeCrypto(); + + const webCurves = { + 'p256': 'P-256', + 'p384': 'P-384', + 'p521': 'P-521' + }; + const knownCurves = nodeCrypto$7 ? nodeCrypto$7.getCurves() : []; + const nodeCurves = nodeCrypto$7 ? { + secp256k1: knownCurves.includes('secp256k1') ? 'secp256k1' : undefined, + p256: knownCurves.includes('prime256v1') ? 'prime256v1' : undefined, + p384: knownCurves.includes('secp384r1') ? 'secp384r1' : undefined, + p521: knownCurves.includes('secp521r1') ? 'secp521r1' : undefined, + ed25519: knownCurves.includes('ED25519') ? 'ED25519' : undefined, + curve25519: knownCurves.includes('X25519') ? 'X25519' : undefined, + brainpoolP256r1: knownCurves.includes('brainpoolP256r1') ? 'brainpoolP256r1' : undefined, + brainpoolP384r1: knownCurves.includes('brainpoolP384r1') ? 'brainpoolP384r1' : undefined, + brainpoolP512r1: knownCurves.includes('brainpoolP512r1') ? 'brainpoolP512r1' : undefined + } : {}; + + const curves = { + p256: { + oid: [0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07], + keyType: enums.publicKey.ecdsa, + hash: enums.hash.sha256, + cipher: enums.symmetric.aes128, + node: nodeCurves.p256, + web: webCurves.p256, + payloadSize: 32, + sharedSize: 256 + }, + p384: { + oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22], + keyType: enums.publicKey.ecdsa, + hash: enums.hash.sha384, + cipher: enums.symmetric.aes192, + node: nodeCurves.p384, + web: webCurves.p384, + payloadSize: 48, + sharedSize: 384 + }, + p521: { + oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23], + keyType: enums.publicKey.ecdsa, + hash: enums.hash.sha512, + cipher: enums.symmetric.aes256, + node: nodeCurves.p521, + web: webCurves.p521, + payloadSize: 66, + sharedSize: 528 + }, + secp256k1: { + oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x0A], + keyType: enums.publicKey.ecdsa, + hash: enums.hash.sha256, + cipher: enums.symmetric.aes128, + node: nodeCurves.secp256k1, + payloadSize: 32 + }, + ed25519: { + oid: [0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01], + keyType: enums.publicKey.eddsa, + hash: enums.hash.sha512, + node: false, // nodeCurves.ed25519 TODO + payloadSize: 32 + }, + curve25519: { + oid: [0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01], + keyType: enums.publicKey.ecdh, + hash: enums.hash.sha256, + cipher: enums.symmetric.aes128, + node: false, // nodeCurves.curve25519 TODO + payloadSize: 32 + }, + brainpoolP256r1: { + oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07], + keyType: enums.publicKey.ecdsa, + hash: enums.hash.sha256, + cipher: enums.symmetric.aes128, + node: nodeCurves.brainpoolP256r1, + payloadSize: 32 + }, + brainpoolP384r1: { + oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B], + keyType: enums.publicKey.ecdsa, + hash: enums.hash.sha384, + cipher: enums.symmetric.aes192, + node: nodeCurves.brainpoolP384r1, + payloadSize: 48 + }, + brainpoolP512r1: { + oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D], + keyType: enums.publicKey.ecdsa, + hash: enums.hash.sha512, + cipher: enums.symmetric.aes256, + node: nodeCurves.brainpoolP512r1, + payloadSize: 64 + } + }; + + class Curve { + constructor(oidOrName, params) { + try { + if (util.isArray(oidOrName) || + util.isUint8Array(oidOrName)) { + // by oid byte array + oidOrName = new OID(oidOrName); + } + if (oidOrName instanceof OID) { + // by curve OID + oidOrName = oidOrName.getName(); + } + // by curve name or oid string + this.name = enums.write(enums.curve, oidOrName); + } catch (err) { + throw new Error('Not valid curve'); + } + params = params || curves[this.name]; + + this.keyType = params.keyType; + + this.oid = params.oid; + this.hash = params.hash; + this.cipher = params.cipher; + this.node = params.node && curves[this.name]; + this.web = params.web && curves[this.name]; + this.payloadSize = params.payloadSize; + if (this.web && util.getWebCrypto()) { + this.type = 'web'; + } else if (this.node && util.getNodeCrypto()) { + this.type = 'node'; + } else if (this.name === 'curve25519') { + this.type = 'curve25519'; + } else if (this.name === 'ed25519') { + this.type = 'ed25519'; + } + } + + async genKeyPair() { + let keyPair; + switch (this.type) { + case 'web': + try { + return await webGenKeyPair(this.name); + } catch (err) { + util.printDebugError('Browser did not support generating ec key ' + err.message); + break; + } + case 'node': + return nodeGenKeyPair(this.name); + case 'curve25519': { + const privateKey = await getRandomBytes(32); + privateKey[0] = (privateKey[0] & 127) | 64; + privateKey[31] &= 248; + const secretKey = privateKey.slice().reverse(); + keyPair = naclFastLight.box.keyPair.fromSecretKey(secretKey); + const publicKey = util.concatUint8Array([new Uint8Array([0x40]), keyPair.publicKey]); + return { publicKey, privateKey }; + } + case 'ed25519': { + const privateKey = await getRandomBytes(32); + const keyPair = naclFastLight.sign.keyPair.fromSeed(privateKey); + const publicKey = util.concatUint8Array([new Uint8Array([0x40]), keyPair.publicKey]); + return { publicKey, privateKey }; + } + } + const indutnyCurve = await getIndutnyCurve(this.name); + keyPair = await indutnyCurve.genKeyPair({ + entropy: util.uint8ArrayToString(await getRandomBytes(32)) + }); + return { publicKey: new Uint8Array(keyPair.getPublic('array', false)), privateKey: keyPair.getPrivate().toArrayLike(Uint8Array) }; + } + } + + async function generate$1(curve) { + const BigInteger = await util.getBigInteger(); + + curve = new Curve(curve); + const keyPair = await curve.genKeyPair(); + const Q = new BigInteger(keyPair.publicKey).toUint8Array(); + const secret = new BigInteger(keyPair.privateKey).toUint8Array('be', curve.payloadSize); + return { + oid: curve.oid, + Q, + secret, + hash: curve.hash, + cipher: curve.cipher + }; + } + + /** + * Get preferred hash algo to use with the given curve + * @param {module:type/oid} oid - curve oid + * @returns {enums.hash} hash algorithm + */ + function getPreferredHashAlgo(oid) { + return curves[enums.write(enums.curve, oid.toHex())].hash; + } + + /** + * Validate ECDH and ECDSA parameters + * Not suitable for EdDSA (different secret key format) + * @param {module:enums.publicKey} algo - EC algorithm, to filter supported curves + * @param {module:type/oid} oid - EC object identifier + * @param {Uint8Array} Q - EC public point + * @param {Uint8Array} d - EC secret scalar + * @returns {Promise} Whether params are valid. + * @async + */ + async function validateStandardParams(algo, oid, Q, d) { + const supportedCurves = { + p256: true, + p384: true, + p521: true, + secp256k1: true, + curve25519: algo === enums.publicKey.ecdh, + brainpoolP256r1: true, + brainpoolP384r1: true, + brainpoolP512r1: true + }; + + // Check whether the given curve is supported + const curveName = oid.getName(); + if (!supportedCurves[curveName]) { + return false; + } + + if (curveName === 'curve25519') { + d = d.slice().reverse(); + // Re-derive public point Q' + const { publicKey } = naclFastLight.box.keyPair.fromSecretKey(d); + + Q = new Uint8Array(Q); + const dG = new Uint8Array([0x40, ...publicKey]); // Add public key prefix + if (!util.equalsUint8Array(dG, Q)) { + return false; + } + + return true; + } + + const curve = await getIndutnyCurve(curveName); + try { + // Parse Q and check that it is on the curve but not at infinity + Q = keyFromPublic(curve, Q).getPublic(); + } catch (validationErrors) { + return false; + } + + /** + * Re-derive public point Q' = dG from private key + * Expect Q == Q' + */ + const dG = keyFromPrivate(curve, d).getPublic(); + if (!dG.eq(Q)) { + return false; + } + + return true; + } + + ////////////////////////// + // // + // Helper functions // + // // + ////////////////////////// + + + async function webGenKeyPair(name) { + // Note: keys generated with ECDSA and ECDH are structurally equivalent + const webCryptoKey = await webCrypto$6.generateKey({ name: 'ECDSA', namedCurve: webCurves[name] }, true, ['sign', 'verify']); + + const privateKey = await webCrypto$6.exportKey('jwk', webCryptoKey.privateKey); + const publicKey = await webCrypto$6.exportKey('jwk', webCryptoKey.publicKey); + + return { + publicKey: jwkToRawPublic(publicKey), + privateKey: b64ToUint8Array(privateKey.d) + }; + } + + async function nodeGenKeyPair(name) { + // Note: ECDSA and ECDH key generation is structurally equivalent + const ecdh = nodeCrypto$7.createECDH(nodeCurves[name]); + await ecdh.generateKeys(); + return { + publicKey: new Uint8Array(ecdh.getPublicKey()), + privateKey: new Uint8Array(ecdh.getPrivateKey()) + }; + } + + ////////////////////////// + // // + // Helper functions // + // // + ////////////////////////// + + /** + * @param {JsonWebKey} jwk - key for conversion + * + * @returns {Uint8Array} Raw public key. + */ + function jwkToRawPublic(jwk) { + const bufX = b64ToUint8Array(jwk.x); + const bufY = b64ToUint8Array(jwk.y); + const publicKey = new Uint8Array(bufX.length + bufY.length + 1); + publicKey[0] = 0x04; + publicKey.set(bufX, 1); + publicKey.set(bufY, bufX.length + 1); + return publicKey; + } + + /** + * @param {Integer} payloadSize - ec payload size + * @param {String} name - curve name + * @param {Uint8Array} publicKey - public key + * + * @returns {JsonWebKey} Public key in jwk format. + */ + function rawPublicToJWK(payloadSize, name, publicKey) { + const len = payloadSize; + const bufX = publicKey.slice(1, len + 1); + const bufY = publicKey.slice(len + 1, len * 2 + 1); + // https://www.rfc-editor.org/rfc/rfc7518.txt + const jwk = { + kty: 'EC', + crv: name, + x: uint8ArrayToB64(bufX, true), + y: uint8ArrayToB64(bufY, true), + ext: true + }; + return jwk; + } + + /** + * @param {Integer} payloadSize - ec payload size + * @param {String} name - curve name + * @param {Uint8Array} publicKey - public key + * @param {Uint8Array} privateKey - private key + * + * @returns {JsonWebKey} Private key in jwk format. + */ + function privateToJWK$1(payloadSize, name, publicKey, privateKey) { + const jwk = rawPublicToJWK(payloadSize, name, publicKey); + jwk.d = uint8ArrayToB64(privateKey, true); + return jwk; + } + + // OpenPGP.js - An OpenPGP implementation in javascript + + const webCrypto$7 = util.getWebCrypto(); + const nodeCrypto$8 = util.getNodeCrypto(); + + /** + * Sign a message using the provided key + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {module:enums.hash} hashAlgo - Hash algorithm used to sign + * @param {Uint8Array} message - Message to sign + * @param {Uint8Array} publicKey - Public key + * @param {Uint8Array} privateKey - Private key used to sign the message + * @param {Uint8Array} hashed - The hashed message + * @returns {Promise<{ + * r: Uint8Array, + * s: Uint8Array + * }>} Signature of the message + * @async + */ + async function sign$1(oid, hashAlgo, message, publicKey, privateKey, hashed) { + const curve = new Curve(oid); + if (message && !util.isStream(message)) { + const keyPair = { publicKey, privateKey }; + switch (curve.type) { + case 'web': { + // If browser doesn't support a curve, we'll catch it + try { + // Need to await to make sure browser succeeds + return await webSign$1(curve, hashAlgo, message, keyPair); + } catch (err) { + // We do not fallback if the error is related to key integrity + // Unfortunaley Safari does not support p521 and throws a DataError when using it + // So we need to always fallback for that curve + if (curve.name !== 'p521' && (err.name === 'DataError' || err.name === 'OperationError')) { + throw err; + } + util.printDebugError('Browser did not support signing: ' + err.message); + } + break; + } + case 'node': { + const signature = await nodeSign$1(curve, hashAlgo, message, keyPair); + return { + r: signature.r.toArrayLike(Uint8Array), + s: signature.s.toArrayLike(Uint8Array) + }; + } + } + } + return ellipticSign(curve, hashed, privateKey); + } + + /** + * Verifies if a signature is valid for a message + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {module:enums.hash} hashAlgo - Hash algorithm used in the signature + * @param {{r: Uint8Array, + s: Uint8Array}} signature Signature to verify + * @param {Uint8Array} message - Message to verify + * @param {Uint8Array} publicKey - Public key used to verify the message + * @param {Uint8Array} hashed - The hashed message + * @returns {Boolean} + * @async + */ + async function verify$1(oid, hashAlgo, signature, message, publicKey, hashed) { + const curve = new Curve(oid); + if (message && !util.isStream(message)) { + switch (curve.type) { + case 'web': + try { + // Need to await to make sure browser succeeds + return await webVerify$1(curve, hashAlgo, signature, message, publicKey); + } catch (err) { + // We do not fallback if the error is related to key integrity + // Unfortunately Safari does not support p521 and throws a DataError when using it + // So we need to always fallback for that curve + if (curve.name !== 'p521' && (err.name === 'DataError' || err.name === 'OperationError')) { + throw err; + } + util.printDebugError('Browser did not support verifying: ' + err.message); + } + break; + case 'node': + return nodeVerify$1(curve, hashAlgo, signature, message, publicKey); + } + } + const digest = (typeof hashAlgo === 'undefined') ? message : hashed; + return ellipticVerify(curve, signature, digest, publicKey); + } + + /** + * Validate ECDSA parameters + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {Uint8Array} Q - ECDSA public point + * @param {Uint8Array} d - ECDSA secret scalar + * @returns {Promise} Whether params are valid. + * @async + */ + async function validateParams$2(oid, Q, d) { + const curve = new Curve(oid); + // Reject curves x25519 and ed25519 + if (curve.keyType !== enums.publicKey.ecdsa) { + return false; + } + + // To speed up the validation, we try to use node- or webcrypto when available + // and sign + verify a random message + switch (curve.type) { + case 'web': + case 'node': { + const message = await getRandomBytes(8); + const hashAlgo = enums.hash.sha256; + const hashed = await hash.digest(hashAlgo, message); + try { + const signature = await sign$1(oid, hashAlgo, message, Q, d, hashed); + return await verify$1(oid, hashAlgo, signature, message, Q, hashed); + } catch (err) { + return false; + } + } + default: + return validateStandardParams(enums.publicKey.ecdsa, oid, Q, d); + } + } + + + ////////////////////////// + // // + // Helper functions // + // // + ////////////////////////// + + async function ellipticSign(curve, hashed, privateKey) { + const indutnyCurve = await getIndutnyCurve(curve.name); + const key = keyFromPrivate(indutnyCurve, privateKey); + const signature = key.sign(hashed); + return { + r: signature.r.toArrayLike(Uint8Array), + s: signature.s.toArrayLike(Uint8Array) + }; + } + + async function ellipticVerify(curve, signature, digest, publicKey) { + const indutnyCurve = await getIndutnyCurve(curve.name); + const key = keyFromPublic(indutnyCurve, publicKey); + return key.verify(digest, signature); + } + + async function webSign$1(curve, hashAlgo, message, keyPair) { + const len = curve.payloadSize; + const jwk = privateToJWK$1(curve.payloadSize, webCurves[curve.name], keyPair.publicKey, keyPair.privateKey); + const key = await webCrypto$7.importKey( + 'jwk', + jwk, + { + 'name': 'ECDSA', + 'namedCurve': webCurves[curve.name], + 'hash': { name: enums.read(enums.webHash, curve.hash) } + }, + false, + ['sign'] + ); + + const signature = new Uint8Array(await webCrypto$7.sign( + { + 'name': 'ECDSA', + 'namedCurve': webCurves[curve.name], + 'hash': { name: enums.read(enums.webHash, hashAlgo) } + }, + key, + message + )); + + return { + r: signature.slice(0, len), + s: signature.slice(len, len << 1) + }; + } + + async function webVerify$1(curve, hashAlgo, { r, s }, message, publicKey) { + const jwk = rawPublicToJWK(curve.payloadSize, webCurves[curve.name], publicKey); + const key = await webCrypto$7.importKey( + 'jwk', + jwk, + { + 'name': 'ECDSA', + 'namedCurve': webCurves[curve.name], + 'hash': { name: enums.read(enums.webHash, curve.hash) } + }, + false, + ['verify'] + ); + + const signature = util.concatUint8Array([r, s]).buffer; + + return webCrypto$7.verify( + { + 'name': 'ECDSA', + 'namedCurve': webCurves[curve.name], + 'hash': { name: enums.read(enums.webHash, hashAlgo) } + }, + key, + signature, + message + ); + } + + async function nodeSign$1(curve, hashAlgo, message, keyPair) { + const sign = nodeCrypto$8.createSign(enums.read(enums.hash, hashAlgo)); + sign.write(message); + sign.end(); + const key = ECPrivateKey.encode({ + version: 1, + parameters: curve.oid, + privateKey: Array.from(keyPair.privateKey), + publicKey: { unused: 0, data: Array.from(keyPair.publicKey) } + }, 'pem', { + label: 'EC PRIVATE KEY' + }); + + return ECDSASignature.decode(sign.sign(key), 'der'); + } + + async function nodeVerify$1(curve, hashAlgo, { r, s }, message, publicKey) { + const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); + + const verify = nodeCrypto$8.createVerify(enums.read(enums.hash, hashAlgo)); + verify.write(message); + verify.end(); + const key = SubjectPublicKeyInfo.encode({ + algorithm: { + algorithm: [1, 2, 840, 10045, 2, 1], + parameters: curve.oid + }, + subjectPublicKey: { unused: 0, data: Array.from(publicKey) } + }, 'pem', { + label: 'PUBLIC KEY' + }); + const signature = ECDSASignature.encode({ + r: new BN(r), s: new BN(s) + }, 'der'); + + try { + return verify.verify(key, signature); + } catch (err) { + return false; + } + } + + // Originally written by Owen Smith https://github.com/omsmith + // Adapted on Feb 2018 from https://github.com/Brightspace/node-jwk-to-pem/ + + /* eslint-disable no-invalid-this */ + + const asn1$1 = nodeCrypto$8 ? void('asn1.js') : undefined; + + const ECDSASignature = nodeCrypto$8 ? + asn1$1.define('ECDSASignature', function() { + this.seq().obj( + this.key('r').int(), + this.key('s').int() + ); + }) : undefined; + + const ECPrivateKey = nodeCrypto$8 ? + asn1$1.define('ECPrivateKey', function() { + this.seq().obj( + this.key('version').int(), + this.key('privateKey').octstr(), + this.key('parameters').explicit(0).optional().any(), + this.key('publicKey').explicit(1).optional().bitstr() + ); + }) : undefined; + + const AlgorithmIdentifier = nodeCrypto$8 ? + asn1$1.define('AlgorithmIdentifier', function() { + this.seq().obj( + this.key('algorithm').objid(), + this.key('parameters').optional().any() + ); + }) : undefined; + + const SubjectPublicKeyInfo = nodeCrypto$8 ? + asn1$1.define('SubjectPublicKeyInfo', function() { + this.seq().obj( + this.key('algorithm').use(AlgorithmIdentifier), + this.key('subjectPublicKey').bitstr() + ); + }) : undefined; + + var ecdsa = /*#__PURE__*/Object.freeze({ + __proto__: null, + sign: sign$1, + verify: verify$1, + validateParams: validateParams$2 + }); + + // OpenPGP.js - An OpenPGP implementation in javascript + + naclFastLight.hash = bytes => new Uint8Array(_512().update(bytes).digest()); + + /** + * Sign a message using the provided key + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {module:enums.hash} hashAlgo - Hash algorithm used to sign (must be sha256 or stronger) + * @param {Uint8Array} message - Message to sign + * @param {Uint8Array} publicKey - Public key + * @param {Uint8Array} privateKey - Private key used to sign the message + * @param {Uint8Array} hashed - The hashed message + * @returns {Promise<{ + * r: Uint8Array, + * s: Uint8Array + * }>} Signature of the message + * @async + */ + async function sign$2(oid, hashAlgo, message, publicKey, privateKey, hashed) { + if (hash.getHashByteLength(hashAlgo) < hash.getHashByteLength(enums.hash.sha256)) { + // see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2 + throw new Error('Hash algorithm too weak: sha256 or stronger is required for EdDSA.'); + } + const secretKey = util.concatUint8Array([privateKey, publicKey.subarray(1)]); + const signature = naclFastLight.sign.detached(hashed, secretKey); + // EdDSA signature params are returned in little-endian format + return { + r: signature.subarray(0, 32), + s: signature.subarray(32) + }; + } + + /** + * Verifies if a signature is valid for a message + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {module:enums.hash} hashAlgo - Hash algorithm used in the signature + * @param {{r: Uint8Array, + s: Uint8Array}} signature Signature to verify the message + * @param {Uint8Array} m - Message to verify + * @param {Uint8Array} publicKey - Public key used to verify the message + * @param {Uint8Array} hashed - The hashed message + * @returns {Boolean} + * @async + */ + async function verify$2(oid, hashAlgo, { r, s }, m, publicKey, hashed) { + const signature = util.concatUint8Array([r, s]); + return naclFastLight.sign.detached.verify(hashed, signature, publicKey.subarray(1)); + } + /** + * Validate EdDSA parameters + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {Uint8Array} Q - EdDSA public point + * @param {Uint8Array} k - EdDSA secret seed + * @returns {Promise} Whether params are valid. + * @async + */ + async function validateParams$3(oid, Q, k) { + // Check whether the given curve is supported + if (oid.getName() !== 'ed25519') { + return false; + } + + /** + * Derive public point Q' = dG from private key + * and expect Q == Q' + */ + const { publicKey } = naclFastLight.sign.keyPair.fromSeed(k); + const dG = new Uint8Array([0x40, ...publicKey]); // Add public key prefix + return util.equalsUint8Array(Q, dG); + } + + var eddsa = /*#__PURE__*/Object.freeze({ + __proto__: null, + sign: sign$2, + verify: verify$2, + validateParams: validateParams$3 + }); + + // OpenPGP.js - An OpenPGP implementation in javascript + + /** + * AES key wrap + * @function + * @param {Uint8Array} key + * @param {Uint8Array} data + * @returns {Uint8Array} + */ + function wrap(key, data) { + const aes = new cipher['aes' + (key.length * 8)](key); + const IV = new Uint32Array([0xA6A6A6A6, 0xA6A6A6A6]); + const P = unpack(data); + let A = IV; + const R = P; + const n = P.length / 2; + const t = new Uint32Array([0, 0]); + let B = new Uint32Array(4); + for (let j = 0; j <= 5; ++j) { + for (let i = 0; i < n; ++i) { + t[1] = n * j + (1 + i); + // B = A + B[0] = A[0]; + B[1] = A[1]; + // B = A || R[i] + B[2] = R[2 * i]; + B[3] = R[2 * i + 1]; + // B = AES(K, B) + B = unpack(aes.encrypt(pack(B))); + // A = MSB(64, B) ^ t + A = B.subarray(0, 2); + A[0] ^= t[0]; + A[1] ^= t[1]; + // R[i] = LSB(64, B) + R[2 * i] = B[2]; + R[2 * i + 1] = B[3]; + } + } + return pack(A, R); + } + + /** + * AES key unwrap + * @function + * @param {String} key + * @param {String} data + * @returns {Uint8Array} + * @throws {Error} + */ + function unwrap(key, data) { + const aes = new cipher['aes' + (key.length * 8)](key); + const IV = new Uint32Array([0xA6A6A6A6, 0xA6A6A6A6]); + const C = unpack(data); + let A = C.subarray(0, 2); + const R = C.subarray(2); + const n = C.length / 2 - 1; + const t = new Uint32Array([0, 0]); + let B = new Uint32Array(4); + for (let j = 5; j >= 0; --j) { + for (let i = n - 1; i >= 0; --i) { + t[1] = n * j + (i + 1); + // B = A ^ t + B[0] = A[0] ^ t[0]; + B[1] = A[1] ^ t[1]; + // B = (A ^ t) || R[i] + B[2] = R[2 * i]; + B[3] = R[2 * i + 1]; + // B = AES-1(B) + B = unpack(aes.decrypt(pack(B))); + // A = MSB(64, B) + A = B.subarray(0, 2); + // R[i] = LSB(64, B) + R[2 * i] = B[2]; + R[2 * i + 1] = B[3]; + } + } + if (A[0] === IV[0] && A[1] === IV[1]) { + return pack(R); + } + throw new Error('Key Data Integrity failed'); + } + + function createArrayBuffer(data) { + if (util.isString(data)) { + const { length } = data; + const buffer = new ArrayBuffer(length); + const view = new Uint8Array(buffer); + for (let j = 0; j < length; ++j) { + view[j] = data.charCodeAt(j); + } + return buffer; + } + return new Uint8Array(data).buffer; + } + + function unpack(data) { + const { length } = data; + const buffer = createArrayBuffer(data); + const view = new DataView(buffer); + const arr = new Uint32Array(length / 4); + for (let i = 0; i < length / 4; ++i) { + arr[i] = view.getUint32(4 * i); + } + return arr; + } + + function pack() { + let length = 0; + for (let k = 0; k < arguments.length; ++k) { + length += 4 * arguments[k].length; + } + const buffer = new ArrayBuffer(length); + const view = new DataView(buffer); + let offset = 0; + for (let i = 0; i < arguments.length; ++i) { + for (let j = 0; j < arguments[i].length; ++j) { + view.setUint32(offset + 4 * j, arguments[i][j]); + } + offset += 4 * arguments[i].length; + } + return new Uint8Array(buffer); + } + + var aesKW = /*#__PURE__*/Object.freeze({ + __proto__: null, + wrap: wrap, + unwrap: unwrap + }); + + // OpenPGP.js - An OpenPGP implementation in javascript + + /** + * @fileoverview Functions to add and remove PKCS5 padding + * @see PublicKeyEncryptedSessionKeyPacket + * @module crypto/pkcs5 + * @private + */ + + /** + * Add pkcs5 padding to a message + * @param {Uint8Array} message - message to pad + * @returns {Uint8Array} Padded message. + */ + function encode$1(message) { + const c = 8 - (message.length % 8); + const padded = new Uint8Array(message.length + c).fill(c); + padded.set(message); + return padded; + } + + /** + * Remove pkcs5 padding from a message + * @param {Uint8Array} message - message to remove padding from + * @returns {Uint8Array} Message without padding. + */ + function decode$1(message) { + const len = message.length; + if (len > 0) { + const c = message[len - 1]; + if (c >= 1) { + const provided = message.subarray(len - c); + const computed = new Uint8Array(c).fill(c); + if (util.equalsUint8Array(provided, computed)) { + return message.subarray(0, len - c); + } + } + } + throw new Error('Invalid padding'); + } + + var pkcs5 = /*#__PURE__*/Object.freeze({ + __proto__: null, + encode: encode$1, + decode: decode$1 + }); + + // OpenPGP.js - An OpenPGP implementation in javascript + + class ECDHSymmetricKey { + constructor(data) { + if (typeof data === 'undefined') { + data = new Uint8Array([]); + } else if (util.isString(data)) { + data = util.stringToUint8Array(data); + } else { + data = new Uint8Array(data); + } + this.data = data; + } + + /** + * Read an ECDHSymmetricKey from an Uint8Array + * @param {Uint8Array} input - Where to read the encoded symmetric key from + * @returns {Number} Number of read bytes. + */ + read(input) { + if (input.length >= 1) { + const length = input[0]; + if (input.length >= 1 + length) { + this.data = input.subarray(1, 1 + length); + return 1 + this.data.length; + } + } + throw new Error('Invalid symmetric key'); + } + + /** + * Write an ECDHSymmetricKey as an Uint8Array + * @returns {Uint8Array} An array containing the value + */ + write() { + return util.concatUint8Array([new Uint8Array([this.data.length]), this.data]); + } + } + + // OpenPGP.js - An OpenPGP implementation in javascript + // Copyright (C) 2015-2016 Decentral + // + // This library is free software; you can redistribute it and/or + // modify it under the terms of the GNU Lesser General Public + // License as published by the Free Software Foundation; either + // version 3.0 of the License, or (at your option) any later version. + // + // This library is distributed in the hope that it will be useful, + // but WITHOUT ANY WARRANTY; without even the implied warranty of + // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + // Lesser General Public License for more details. + // + // You should have received a copy of the GNU Lesser General Public + // License along with this library; if not, write to the Free Software + // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + /** + * Implementation of type KDF parameters + * + * {@link https://tools.ietf.org/html/rfc6637#section-7|RFC 6637 7}: + * A key derivation function (KDF) is necessary to implement the EC + * encryption. The Concatenation Key Derivation Function (Approved + * Alternative 1) [NIST-SP800-56A] with the KDF hash function that is + * SHA2-256 [FIPS-180-3] or stronger is REQUIRED. + * @module type/kdf_params + * @private + */ + + class KDFParams { + /** + * @param {enums.hash} hash - Hash algorithm + * @param {enums.symmetric} cipher - Symmetric algorithm + */ + constructor(data) { + if (data) { + const { hash, cipher } = data; + this.hash = hash; + this.cipher = cipher; + } else { + this.hash = null; + this.cipher = null; + } + } + + /** + * Read KDFParams from an Uint8Array + * @param {Uint8Array} input - Where to read the KDFParams from + * @returns {Number} Number of read bytes. + */ + read(input) { + if (input.length < 4 || input[0] !== 3 || input[1] !== 1) { + throw new Error('Cannot read KDFParams'); + } + this.hash = input[2]; + this.cipher = input[3]; + return 4; + } + + /** + * Write KDFParams to an Uint8Array + * @returns {Uint8Array} Array with the KDFParams value + */ + write() { + return new Uint8Array([3, 1, this.hash, this.cipher]); + } + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + /** + * Encrypts data using specified algorithm and public key parameters. + * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} for public key algorithms. + * @param {module:enums.publicKey} algo - Public key algorithm + * @param {Object} publicParams - Algorithm-specific public key parameters + * @param {Uint8Array} data - Data to be encrypted + * @param {Uint8Array} fingerprint - Recipient fingerprint + * @returns {Promise} Encrypted session key parameters. + * @async + */ + async function publicKeyEncrypt(algo, publicParams, data, fingerprint) { + switch (algo) { + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaEncryptSign: { + const { n, e } = publicParams; + const c = await publicKey.rsa.encrypt(data, n, e); + return { c }; + } + case enums.publicKey.elgamal: { + const { p, g, y } = publicParams; + return publicKey.elgamal.encrypt(data, p, g, y); + } + case enums.publicKey.ecdh: { + const { oid, Q, kdfParams } = publicParams; + const { publicKey: V, wrappedKey: C } = await publicKey.elliptic.ecdh.encrypt( + oid, kdfParams, data, Q, fingerprint); + return { V, C: new ECDHSymmetricKey(C) }; + } + default: + return []; + } + } + + /** + * Decrypts data using specified algorithm and private key parameters. + * See {@link https://tools.ietf.org/html/rfc4880#section-5.5.3|RFC 4880 5.5.3} + * @param {module:enums.publicKey} algo - Public key algorithm + * @param {Object} publicKeyParams - Algorithm-specific public key parameters + * @param {Object} privateKeyParams - Algorithm-specific private key parameters + * @param {Object} sessionKeyParams - Encrypted session key parameters + * @param {Uint8Array} fingerprint - Recipient fingerprint + * @param {Uint8Array} [randomPayload] - Data to return on decryption error, instead of throwing + * (needed for constant-time processing in RSA and ElGamal) + * @returns {Promise} Decrypted data. + * @throws {Error} on sensitive decryption error, unless `randomPayload` is given + * @async + */ + async function publicKeyDecrypt(algo, publicKeyParams, privateKeyParams, sessionKeyParams, fingerprint, randomPayload) { + switch (algo) { + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaEncrypt: { + const { c } = sessionKeyParams; + const { n, e } = publicKeyParams; + const { d, p, q, u } = privateKeyParams; + return publicKey.rsa.decrypt(c, n, e, d, p, q, u, randomPayload); + } + case enums.publicKey.elgamal: { + const { c1, c2 } = sessionKeyParams; + const p = publicKeyParams.p; + const x = privateKeyParams.x; + return publicKey.elgamal.decrypt(c1, c2, p, x, randomPayload); + } + case enums.publicKey.ecdh: { + const { oid, Q, kdfParams } = publicKeyParams; + const { d } = privateKeyParams; + const { V, C } = sessionKeyParams; + return publicKey.elliptic.ecdh.decrypt( + oid, kdfParams, V, C.data, Q, d, fingerprint); + } + default: + throw new Error('Invalid public key encryption algorithm.'); + } + } + + /** + * Parse public key material in binary form to get the key parameters + * @param {module:enums.publicKey} algo - The key algorithm + * @param {Uint8Array} bytes - The key material to parse + * @returns {{ read: Number, publicParams: Object }} Number of read bytes plus key parameters referenced by name. + */ + function parsePublicKeyParams(algo, bytes) { + let read = 0; + switch (algo) { + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaSign: { + const n = util.readMPI(bytes.subarray(read)); read += n.length + 2; + const e = util.readMPI(bytes.subarray(read)); read += e.length + 2; + return { read, publicParams: { n, e } }; + } + case enums.publicKey.dsa: { + const p = util.readMPI(bytes.subarray(read)); read += p.length + 2; + const q = util.readMPI(bytes.subarray(read)); read += q.length + 2; + const g = util.readMPI(bytes.subarray(read)); read += g.length + 2; + const y = util.readMPI(bytes.subarray(read)); read += y.length + 2; + return { read, publicParams: { p, q, g, y } }; + } + case enums.publicKey.elgamal: { + const p = util.readMPI(bytes.subarray(read)); read += p.length + 2; + const g = util.readMPI(bytes.subarray(read)); read += g.length + 2; + const y = util.readMPI(bytes.subarray(read)); read += y.length + 2; + return { read, publicParams: { p, g, y } }; + } + case enums.publicKey.ecdsa: { + const oid = new OID(); read += oid.read(bytes); + const Q = util.readMPI(bytes.subarray(read)); read += Q.length + 2; + return { read: read, publicParams: { oid, Q } }; + } + case enums.publicKey.eddsa: { + const oid = new OID(); read += oid.read(bytes); + let Q = util.readMPI(bytes.subarray(read)); read += Q.length + 2; + Q = util.leftPad(Q, 33); + return { read: read, publicParams: { oid, Q } }; + } + case enums.publicKey.ecdh: { + const oid = new OID(); read += oid.read(bytes); + const Q = util.readMPI(bytes.subarray(read)); read += Q.length + 2; + const kdfParams = new KDFParams(); read += kdfParams.read(bytes.subarray(read)); + return { read: read, publicParams: { oid, Q, kdfParams } }; + } + default: + throw new Error('Invalid public key encryption algorithm.'); + } + } + + /** + * Parse private key material in binary form to get the key parameters + * @param {module:enums.publicKey} algo - The key algorithm + * @param {Uint8Array} bytes - The key material to parse + * @param {Object} publicParams - (ECC only) public params, needed to format some private params + * @returns {{ read: Number, privateParams: Object }} Number of read bytes plus the key parameters referenced by name. + */ + function parsePrivateKeyParams(algo, bytes, publicParams) { + let read = 0; + switch (algo) { + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaSign: { + const d = util.readMPI(bytes.subarray(read)); read += d.length + 2; + const p = util.readMPI(bytes.subarray(read)); read += p.length + 2; + const q = util.readMPI(bytes.subarray(read)); read += q.length + 2; + const u = util.readMPI(bytes.subarray(read)); read += u.length + 2; + return { read, privateParams: { d, p, q, u } }; + } + case enums.publicKey.dsa: + case enums.publicKey.elgamal: { + const x = util.readMPI(bytes.subarray(read)); read += x.length + 2; + return { read, privateParams: { x } }; + } + case enums.publicKey.ecdsa: + case enums.publicKey.ecdh: { + const curve = new Curve(publicParams.oid); + let d = util.readMPI(bytes.subarray(read)); read += d.length + 2; + d = util.leftPad(d, curve.payloadSize); + return { read, privateParams: { d } }; + } + case enums.publicKey.eddsa: { + let seed = util.readMPI(bytes.subarray(read)); read += seed.length + 2; + seed = util.leftPad(seed, 32); + return { read, privateParams: { seed } }; + } + default: + throw new Error('Invalid public key encryption algorithm.'); + } + } + + /** Returns the types comprising the encrypted session key of an algorithm + * @param {module:enums.publicKey} algo - The key algorithm + * @param {Uint8Array} bytes - The key material to parse + * @returns {Object} The session key parameters referenced by name. + */ + function parseEncSessionKeyParams(algo, bytes) { + let read = 0; + switch (algo) { + // Algorithm-Specific Fields for RSA encrypted session keys: + // - MPI of RSA encrypted value m**e mod n. + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaEncryptSign: { + const c = util.readMPI(bytes.subarray(read)); + return { c }; + } + + // Algorithm-Specific Fields for Elgamal encrypted session keys: + // - MPI of Elgamal value g**k mod p + // - MPI of Elgamal value m * y**k mod p + case enums.publicKey.elgamal: { + const c1 = util.readMPI(bytes.subarray(read)); read += c1.length + 2; + const c2 = util.readMPI(bytes.subarray(read)); + return { c1, c2 }; + } + // Algorithm-Specific Fields for ECDH encrypted session keys: + // - MPI containing the ephemeral key used to establish the shared secret + // - ECDH Symmetric Key + case enums.publicKey.ecdh: { + const V = util.readMPI(bytes.subarray(read)); read += V.length + 2; + const C = new ECDHSymmetricKey(); C.read(bytes.subarray(read)); + return { V, C }; + } + default: + throw new Error('Invalid public key encryption algorithm.'); + } + } + + /** + * Convert params to MPI and serializes them in the proper order + * @param {module:enums.publicKey} algo - The public key algorithm + * @param {Object} params - The key parameters indexed by name + * @returns {Uint8Array} The array containing the MPIs. + */ + function serializeParams(algo, params) { + const orderedParams = Object.keys(params).map(name => { + const param = params[name]; + return util.isUint8Array(param) ? util.uint8ArrayToMPI(param) : param.write(); + }); + return util.concatUint8Array(orderedParams); + } + + /** + * Generate algorithm-specific key parameters + * @param {module:enums.publicKey} algo - The public key algorithm + * @param {Integer} bits - Bit length for RSA keys + * @param {module:type/oid} oid - Object identifier for ECC keys + * @returns {Promise<{ publicParams: {Object}, privateParams: {Object} }>} The parameters referenced by name. + * @async + */ + function generateParams(algo, bits, oid) { + switch (algo) { + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaSign: { + return publicKey.rsa.generate(bits, 65537).then(({ n, e, d, p, q, u }) => ({ + privateParams: { d, p, q, u }, + publicParams: { n, e } + })); + } + case enums.publicKey.ecdsa: + return publicKey.elliptic.generate(oid).then(({ oid, Q, secret }) => ({ + privateParams: { d: secret }, + publicParams: { oid: new OID(oid), Q } + })); + case enums.publicKey.eddsa: + return publicKey.elliptic.generate(oid).then(({ oid, Q, secret }) => ({ + privateParams: { seed: secret }, + publicParams: { oid: new OID(oid), Q } + })); + case enums.publicKey.ecdh: + return publicKey.elliptic.generate(oid).then(({ oid, Q, secret, hash, cipher }) => ({ + privateParams: { d: secret }, + publicParams: { + oid: new OID(oid), + Q, + kdfParams: new KDFParams({ hash, cipher }) + } + })); + case enums.publicKey.dsa: + case enums.publicKey.elgamal: + throw new Error('Unsupported algorithm for key generation.'); + default: + throw new Error('Invalid public key algorithm.'); + } + } + + /** + * Validate algorithm-specific key parameters + * @param {module:enums.publicKey} algo - The public key algorithm + * @param {Object} publicParams - Algorithm-specific public key parameters + * @param {Object} privateParams - Algorithm-specific private key parameters + * @returns {Promise} Whether the parameters are valid. + * @async + */ + async function validateParams$4(algo, publicParams, privateParams) { + if (!publicParams || !privateParams) { + throw new Error('Missing key parameters'); + } + switch (algo) { + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaSign: { + const { n, e } = publicParams; + const { d, p, q, u } = privateParams; + return publicKey.rsa.validateParams(n, e, d, p, q, u); + } + case enums.publicKey.dsa: { + const { p, q, g, y } = publicParams; + const { x } = privateParams; + return publicKey.dsa.validateParams(p, q, g, y, x); + } + case enums.publicKey.elgamal: { + const { p, g, y } = publicParams; + const { x } = privateParams; + return publicKey.elgamal.validateParams(p, g, y, x); + } + case enums.publicKey.ecdsa: + case enums.publicKey.ecdh: { + const algoModule = publicKey.elliptic[enums.read(enums.publicKey, algo)]; + const { oid, Q } = publicParams; + const { d } = privateParams; + return algoModule.validateParams(oid, Q, d); + } + case enums.publicKey.eddsa: { + const { oid, Q } = publicParams; + const { seed } = privateParams; + return publicKey.elliptic.eddsa.validateParams(oid, Q, seed); + } + default: + throw new Error('Invalid public key algorithm.'); + } + } + + /** + * Generates a random byte prefix for the specified algorithm + * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. + * @param {module:enums.symmetric} algo - Symmetric encryption algorithm + * @returns {Promise} Random bytes with length equal to the block size of the cipher, plus the last two bytes repeated. + * @async + */ + async function getPrefixRandom(algo) { + const { blockSize } = getCipher(algo); + const prefixrandom = await getRandomBytes(blockSize); + const repeat = new Uint8Array([prefixrandom[prefixrandom.length - 2], prefixrandom[prefixrandom.length - 1]]); + return util.concat([prefixrandom, repeat]); + } + + /** + * Generating a session key for the specified symmetric algorithm + * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. + * @param {module:enums.symmetric} algo - Symmetric encryption algorithm + * @returns {Promise} Random bytes as a string to be used as a key. + * @async + */ + function generateSessionKey(algo) { + const { keySize } = getCipher(algo); + return getRandomBytes(keySize); + } + + /** + * Get implementation of the given AEAD mode + * @param {enums.aead} algo + * @returns {Object} + * @throws {Error} on invalid algo + */ + function getAEADMode(algo) { + const algoName = enums.read(enums.aead, algo); + return mode[algoName]; + } + + /** + * Get implementation of the given cipher + * @param {enums.symmetric} algo + * @returns {Object} + * @throws {Error} on invalid algo + */ + function getCipher(algo) { + const algoName = enums.read(enums.symmetric, algo); + return cipher[algoName]; + } + + var crypto$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + publicKeyEncrypt: publicKeyEncrypt, + publicKeyDecrypt: publicKeyDecrypt, + parsePublicKeyParams: parsePublicKeyParams, + parsePrivateKeyParams: parsePrivateKeyParams, + parseEncSessionKeyParams: parseEncSessionKeyParams, + serializeParams: serializeParams, + generateParams: generateParams, + validateParams: validateParams$4, + getPrefixRandom: getPrefixRandom, + generateSessionKey: generateSessionKey, + getAEADMode: getAEADMode, + getCipher: getCipher + }); + + // OpenPGP.js - An OpenPGP implementation in javascript + + const webCrypto$8 = util.getWebCrypto(); + const nodeCrypto$9 = util.getNodeCrypto(); + + /** + * Validate ECDH parameters + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {Uint8Array} Q - ECDH public point + * @param {Uint8Array} d - ECDH secret scalar + * @returns {Promise} Whether params are valid. + * @async + */ + async function validateParams$5(oid, Q, d) { + return validateStandardParams(enums.publicKey.ecdh, oid, Q, d); + } + + // Build Param for ECDH algorithm (RFC 6637) + function buildEcdhParam(public_algo, oid, kdfParams, fingerprint) { + return util.concatUint8Array([ + oid.write(), + new Uint8Array([public_algo]), + kdfParams.write(), + util.stringToUint8Array('Anonymous Sender '), + fingerprint.subarray(0, 20) + ]); + } + + // Key Derivation Function (RFC 6637) + async function kdf(hashAlgo, X, length, param, stripLeading = false, stripTrailing = false) { + // Note: X is little endian for Curve25519, big-endian for all others. + // This is not ideal, but the RFC's are unclear + // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B + let i; + if (stripLeading) { + // Work around old go crypto bug + for (i = 0; i < X.length && X[i] === 0; i++); + X = X.subarray(i); + } + if (stripTrailing) { + // Work around old OpenPGP.js bug + for (i = X.length - 1; i >= 0 && X[i] === 0; i--); + X = X.subarray(0, i + 1); + } + const digest = await hash.digest(hashAlgo, util.concatUint8Array([ + new Uint8Array([0, 0, 0, 1]), + X, + param + ])); + return digest.subarray(0, length); + } + + /** + * Generate ECDHE ephemeral key and secret from public key + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} Q - Recipient public key + * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ + async function genPublicEphemeralKey(curve, Q) { + switch (curve.type) { + case 'curve25519': { + const d = await getRandomBytes(32); + const { secretKey, sharedKey } = await genPrivateEphemeralKey(curve, Q, null, d); + let { publicKey } = naclFastLight.box.keyPair.fromSecretKey(secretKey); + publicKey = util.concatUint8Array([new Uint8Array([0x40]), publicKey]); + return { publicKey, sharedKey }; // Note: sharedKey is little-endian here, unlike below + } + case 'web': + if (curve.web && util.getWebCrypto()) { + try { + return await webPublicEphemeralKey(curve, Q); + } catch (err) { + util.printDebugError(err); + } + } + break; + case 'node': + return nodePublicEphemeralKey(curve, Q); + } + return ellipticPublicEphemeralKey(curve, Q); + } + + /** + * Encrypt and wrap a session key + * + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {module:type/kdf_params} kdfParams - KDF params including cipher and algorithm to use + * @param {Uint8Array} data - Unpadded session key data + * @param {Uint8Array} Q - Recipient public key + * @param {Uint8Array} fingerprint - Recipient fingerprint + * @returns {Promise<{publicKey: Uint8Array, wrappedKey: Uint8Array}>} + * @async + */ + async function encrypt$3(oid, kdfParams, data, Q, fingerprint) { + const m = encode$1(data); + + const curve = new Curve(oid); + const { publicKey, sharedKey } = await genPublicEphemeralKey(curve, Q); + const param = buildEcdhParam(enums.publicKey.ecdh, oid, kdfParams, fingerprint); + const { keySize } = getCipher(kdfParams.cipher); + const Z = await kdf(kdfParams.hash, sharedKey, keySize, param); + const wrappedKey = wrap(Z, m); + return { publicKey, wrappedKey }; + } + + /** + * Generate ECDHE secret from private key and public part of ephemeral key + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} V - Public part of ephemeral key + * @param {Uint8Array} Q - Recipient public key + * @param {Uint8Array} d - Recipient private key + * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ + async function genPrivateEphemeralKey(curve, V, Q, d) { + if (d.length !== curve.payloadSize) { + const privateKey = new Uint8Array(curve.payloadSize); + privateKey.set(d, curve.payloadSize - d.length); + d = privateKey; + } + switch (curve.type) { + case 'curve25519': { + const secretKey = d.slice().reverse(); + const sharedKey = naclFastLight.scalarMult(secretKey, V.subarray(1)); + return { secretKey, sharedKey }; // Note: sharedKey is little-endian here, unlike below + } + case 'web': + if (curve.web && util.getWebCrypto()) { + try { + return await webPrivateEphemeralKey(curve, V, Q, d); + } catch (err) { + util.printDebugError(err); + } + } + break; + case 'node': + return nodePrivateEphemeralKey(curve, V, d); + } + return ellipticPrivateEphemeralKey(curve, V, d); + } + + /** + * Decrypt and unwrap the value derived from session key + * + * @param {module:type/oid} oid - Elliptic curve object identifier + * @param {module:type/kdf_params} kdfParams - KDF params including cipher and algorithm to use + * @param {Uint8Array} V - Public part of ephemeral key + * @param {Uint8Array} C - Encrypted and wrapped value derived from session key + * @param {Uint8Array} Q - Recipient public key + * @param {Uint8Array} d - Recipient private key + * @param {Uint8Array} fingerprint - Recipient fingerprint + * @returns {Promise} Value derived from session key. + * @async + */ + async function decrypt$3(oid, kdfParams, V, C, Q, d, fingerprint) { + const curve = new Curve(oid); + const { sharedKey } = await genPrivateEphemeralKey(curve, V, Q, d); + const param = buildEcdhParam(enums.publicKey.ecdh, oid, kdfParams, fingerprint); + const { keySize } = getCipher(kdfParams.cipher); + let err; + for (let i = 0; i < 3; i++) { + try { + // Work around old go crypto bug and old OpenPGP.js bug, respectively. + const Z = await kdf(kdfParams.hash, sharedKey, keySize, param, i === 1, i === 2); + return decode$1(unwrap(Z, C)); + } catch (e) { + err = e; + } + } + throw err; + } + + /** + * Generate ECDHE secret from private key and public part of ephemeral key using webCrypto + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} V - Public part of ephemeral key + * @param {Uint8Array} Q - Recipient public key + * @param {Uint8Array} d - Recipient private key + * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ + async function webPrivateEphemeralKey(curve, V, Q, d) { + const recipient = privateToJWK$1(curve.payloadSize, curve.web.web, Q, d); + let privateKey = webCrypto$8.importKey( + 'jwk', + recipient, + { + name: 'ECDH', + namedCurve: curve.web.web + }, + true, + ['deriveKey', 'deriveBits'] + ); + const jwk = rawPublicToJWK(curve.payloadSize, curve.web.web, V); + let sender = webCrypto$8.importKey( + 'jwk', + jwk, + { + name: 'ECDH', + namedCurve: curve.web.web + }, + true, + [] + ); + [privateKey, sender] = await Promise.all([privateKey, sender]); + let S = webCrypto$8.deriveBits( + { + name: 'ECDH', + namedCurve: curve.web.web, + public: sender + }, + privateKey, + curve.web.sharedSize + ); + let secret = webCrypto$8.exportKey( + 'jwk', + privateKey + ); + [S, secret] = await Promise.all([S, secret]); + const sharedKey = new Uint8Array(S); + const secretKey = b64ToUint8Array(secret.d); + return { secretKey, sharedKey }; + } + + /** + * Generate ECDHE ephemeral key and secret from public key using webCrypto + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} Q - Recipient public key + * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ + async function webPublicEphemeralKey(curve, Q) { + const jwk = rawPublicToJWK(curve.payloadSize, curve.web.web, Q); + let keyPair = webCrypto$8.generateKey( + { + name: 'ECDH', + namedCurve: curve.web.web + }, + true, + ['deriveKey', 'deriveBits'] + ); + let recipient = webCrypto$8.importKey( + 'jwk', + jwk, + { + name: 'ECDH', + namedCurve: curve.web.web + }, + false, + [] + ); + [keyPair, recipient] = await Promise.all([keyPair, recipient]); + let s = webCrypto$8.deriveBits( + { + name: 'ECDH', + namedCurve: curve.web.web, + public: recipient + }, + keyPair.privateKey, + curve.web.sharedSize + ); + let p = webCrypto$8.exportKey( + 'jwk', + keyPair.publicKey + ); + [s, p] = await Promise.all([s, p]); + const sharedKey = new Uint8Array(s); + const publicKey = new Uint8Array(jwkToRawPublic(p)); + return { publicKey, sharedKey }; + } + + /** + * Generate ECDHE secret from private key and public part of ephemeral key using indutny/elliptic + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} V - Public part of ephemeral key + * @param {Uint8Array} d - Recipient private key + * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ + async function ellipticPrivateEphemeralKey(curve, V, d) { + const indutnyCurve = await getIndutnyCurve(curve.name); + V = keyFromPublic(indutnyCurve, V); + d = keyFromPrivate(indutnyCurve, d); + const secretKey = new Uint8Array(d.getPrivate()); + const S = d.derive(V.getPublic()); + const len = indutnyCurve.curve.p.byteLength(); + const sharedKey = S.toArrayLike(Uint8Array, 'be', len); + return { secretKey, sharedKey }; + } + + /** + * Generate ECDHE ephemeral key and secret from public key using indutny/elliptic + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} Q - Recipient public key + * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ + async function ellipticPublicEphemeralKey(curve, Q) { + const indutnyCurve = await getIndutnyCurve(curve.name); + const v = await curve.genKeyPair(); + Q = keyFromPublic(indutnyCurve, Q); + const V = keyFromPrivate(indutnyCurve, v.privateKey); + const publicKey = v.publicKey; + const S = V.derive(Q.getPublic()); + const len = indutnyCurve.curve.p.byteLength(); + const sharedKey = S.toArrayLike(Uint8Array, 'be', len); + return { publicKey, sharedKey }; + } + + /** + * Generate ECDHE secret from private key and public part of ephemeral key using nodeCrypto + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} V - Public part of ephemeral key + * @param {Uint8Array} d - Recipient private key + * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ + async function nodePrivateEphemeralKey(curve, V, d) { + const recipient = nodeCrypto$9.createECDH(curve.node.node); + recipient.setPrivateKey(d); + const sharedKey = new Uint8Array(recipient.computeSecret(V)); + const secretKey = new Uint8Array(recipient.getPrivateKey()); + return { secretKey, sharedKey }; + } + + /** + * Generate ECDHE ephemeral key and secret from public key using nodeCrypto + * + * @param {Curve} curve - Elliptic curve object + * @param {Uint8Array} Q - Recipient public key + * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} + * @async + */ + async function nodePublicEphemeralKey(curve, Q) { + const sender = nodeCrypto$9.createECDH(curve.node.node); + sender.generateKeys(); + const sharedKey = new Uint8Array(sender.computeSecret(Q)); + const publicKey = new Uint8Array(sender.getPublicKey()); + return { publicKey, sharedKey }; + } + + var ecdh = /*#__PURE__*/Object.freeze({ + __proto__: null, + validateParams: validateParams$5, + encrypt: encrypt$3, + decrypt: decrypt$3 + }); + + // OpenPGP.js - An OpenPGP implementation in javascript + + var elliptic = /*#__PURE__*/Object.freeze({ + __proto__: null, + Curve: Curve, + ecdh: ecdh, + ecdsa: ecdsa, + eddsa: eddsa, + generate: generate$1, + getPreferredHashAlgo: getPreferredHashAlgo + }); + + // GPG4Browsers - An OpenPGP implementation in javascript + + /* + TODO regarding the hash function, read: + https://tools.ietf.org/html/rfc4880#section-13.6 + https://tools.ietf.org/html/rfc4880#section-14 + */ + + /** + * DSA Sign function + * @param {Integer} hashAlgo + * @param {Uint8Array} hashed + * @param {Uint8Array} g + * @param {Uint8Array} p + * @param {Uint8Array} q + * @param {Uint8Array} x + * @returns {Promise<{ r: Uint8Array, s: Uint8Array }>} + * @async + */ + async function sign$3(hashAlgo, hashed, g, p, q, x) { + const BigInteger = await util.getBigInteger(); + const one = new BigInteger(1); + p = new BigInteger(p); + q = new BigInteger(q); + g = new BigInteger(g); + x = new BigInteger(x); + + let k; + let r; + let s; + let t; + g = g.mod(p); + x = x.mod(q); + // If the output size of the chosen hash is larger than the number of + // bits of q, the hash result is truncated to fit by taking the number + // of leftmost bits equal to the number of bits of q. This (possibly + // truncated) hash function result is treated as a number and used + // directly in the DSA signature algorithm. + const h = new BigInteger(hashed.subarray(0, q.byteLength())).mod(q); + // FIPS-186-4, section 4.6: + // The values of r and s shall be checked to determine if r = 0 or s = 0. + // If either r = 0 or s = 0, a new value of k shall be generated, and the + // signature shall be recalculated. It is extremely unlikely that r = 0 + // or s = 0 if signatures are generated properly. + while (true) { + // See Appendix B here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf + k = await getRandomBigInteger(one, q); // returns in [1, q-1] + r = g.modExp(k, p).imod(q); // (g**k mod p) mod q + if (r.isZero()) { + continue; + } + const xr = x.mul(r).imod(q); + t = h.add(xr).imod(q); // H(m) + x*r mod q + s = k.modInv(q).imul(t).imod(q); // k**-1 * (H(m) + x*r) mod q + if (s.isZero()) { + continue; + } + break; + } + return { + r: r.toUint8Array('be', q.byteLength()), + s: s.toUint8Array('be', q.byteLength()) + }; + } + + /** + * DSA Verify function + * @param {Integer} hashAlgo + * @param {Uint8Array} r + * @param {Uint8Array} s + * @param {Uint8Array} hashed + * @param {Uint8Array} g + * @param {Uint8Array} p + * @param {Uint8Array} q + * @param {Uint8Array} y + * @returns {boolean} + * @async + */ + async function verify$3(hashAlgo, r, s, hashed, g, p, q, y) { + const BigInteger = await util.getBigInteger(); + const zero = new BigInteger(0); + r = new BigInteger(r); + s = new BigInteger(s); + + p = new BigInteger(p); + q = new BigInteger(q); + g = new BigInteger(g); + y = new BigInteger(y); + + if (r.lte(zero) || r.gte(q) || + s.lte(zero) || s.gte(q)) { + util.printDebug('invalid DSA Signature'); + return false; + } + const h = new BigInteger(hashed.subarray(0, q.byteLength())).imod(q); + const w = s.modInv(q); // s**-1 mod q + if (w.isZero()) { + util.printDebug('invalid DSA Signature'); + return false; + } + + g = g.mod(p); + y = y.mod(p); + const u1 = h.mul(w).imod(q); // H(m) * w mod q + const u2 = r.mul(w).imod(q); // r * w mod q + const t1 = g.modExp(u1, p); // g**u1 mod p + const t2 = y.modExp(u2, p); // y**u2 mod p + const v = t1.mul(t2).imod(p).imod(q); // (g**u1 * y**u2 mod p) mod q + return v.equal(r); + } + + /** + * Validate DSA parameters + * @param {Uint8Array} p - DSA prime + * @param {Uint8Array} q - DSA group order + * @param {Uint8Array} g - DSA sub-group generator + * @param {Uint8Array} y - DSA public key + * @param {Uint8Array} x - DSA private key + * @returns {Promise} Whether params are valid. + * @async + */ + async function validateParams$6(p, q, g, y, x) { + const BigInteger = await util.getBigInteger(); + p = new BigInteger(p); + q = new BigInteger(q); + g = new BigInteger(g); + y = new BigInteger(y); + const one = new BigInteger(1); + // Check that 1 < g < p + if (g.lte(one) || g.gte(p)) { + return false; + } + + /** + * Check that subgroup order q divides p-1 + */ + if (!p.dec().mod(q).isZero()) { + return false; + } + + /** + * g has order q + * Check that g ** q = 1 mod p + */ + if (!g.modExp(q, p).isOne()) { + return false; + } + + /** + * Check q is large and probably prime (we mainly want to avoid small factors) + */ + const qSize = new BigInteger(q.bitLength()); + const n150 = new BigInteger(150); + if (qSize.lt(n150) || !(await isProbablePrime(q, null, 32))) { + return false; + } + + /** + * Re-derive public key y' = g ** x mod p + * Expect y == y' + * + * Blinded exponentiation computes g**{rq + x} to compare to y + */ + x = new BigInteger(x); + const two = new BigInteger(2); + const r = await getRandomBigInteger(two.leftShift(qSize.dec()), two.leftShift(qSize)); // draw r of same size as q + const rqx = q.mul(r).add(x); + if (!y.equal(g.modExp(rqx, p))) { + return false; + } + + return true; + } + + var dsa = /*#__PURE__*/Object.freeze({ + __proto__: null, + sign: sign$3, + verify: verify$3, + validateParams: validateParams$6 + }); + + /** + * @fileoverview Asymmetric cryptography functions + * @module crypto/public_key + * @private + */ + + var publicKey = { + /** @see module:crypto/public_key/rsa */ + rsa: rsa, + /** @see module:crypto/public_key/elgamal */ + elgamal: elgamal, + /** @see module:crypto/public_key/elliptic */ + elliptic: elliptic, + /** @see module:crypto/public_key/dsa */ + dsa: dsa, + /** @see tweetnacl */ + nacl: naclFastLight + }; + + /** + * @fileoverview Provides functions for asymmetric signing and signature verification + * @module crypto/signature + * @private + */ + + /** + * Parse signature in binary form to get the parameters. + * The returned values are only padded for EdDSA, since in the other cases their expected length + * depends on the key params, hence we delegate the padding to the signature verification function. + * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} + * See {@link https://tools.ietf.org/html/rfc4880#section-5.2.2|RFC 4880 5.2.2.} + * @param {module:enums.publicKey} algo - Public key algorithm + * @param {Uint8Array} signature - Data for which the signature was created + * @returns {Promise} True if signature is valid. + * @async + */ + function parseSignatureParams(algo, signature) { + let read = 0; + switch (algo) { + // Algorithm-Specific Fields for RSA signatures: + // - MPI of RSA signature value m**d mod n. + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaSign: { + const s = util.readMPI(signature.subarray(read)); + // The signature needs to be the same length as the public key modulo n. + // We pad s on signature verification, where we have access to n. + return { s }; + } + // Algorithm-Specific Fields for DSA or ECDSA signatures: + // - MPI of DSA or ECDSA value r. + // - MPI of DSA or ECDSA value s. + case enums.publicKey.dsa: + case enums.publicKey.ecdsa: + { + const r = util.readMPI(signature.subarray(read)); read += r.length + 2; + const s = util.readMPI(signature.subarray(read)); + return { r, s }; + } + // Algorithm-Specific Fields for EdDSA signatures: + // - MPI of an EC point r. + // - EdDSA value s, in MPI, in the little endian representation + case enums.publicKey.eddsa: { + // When parsing little-endian MPI data, we always need to left-pad it, as done with big-endian values: + // https://www.ietf.org/archive/id/draft-ietf-openpgp-rfc4880bis-10.html#section-3.2-9 + let r = util.readMPI(signature.subarray(read)); read += r.length + 2; + r = util.leftPad(r, 32); + let s = util.readMPI(signature.subarray(read)); + s = util.leftPad(s, 32); + return { r, s }; + } + default: + throw new Error('Invalid signature algorithm.'); + } + } + + /** + * Verifies the signature provided for data using specified algorithms and public key parameters. + * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} + * and {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4} + * for public key and hash algorithms. + * @param {module:enums.publicKey} algo - Public key algorithm + * @param {module:enums.hash} hashAlgo - Hash algorithm + * @param {Object} signature - Named algorithm-specific signature parameters + * @param {Object} publicParams - Algorithm-specific public key parameters + * @param {Uint8Array} data - Data for which the signature was created + * @param {Uint8Array} hashed - The hashed data + * @returns {Promise} True if signature is valid. + * @async + */ + async function verify$4(algo, hashAlgo, signature, publicParams, data, hashed) { + switch (algo) { + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaSign: { + const { n, e } = publicParams; + const s = util.leftPad(signature.s, n.length); // padding needed for webcrypto and node crypto + return publicKey.rsa.verify(hashAlgo, data, s, n, e, hashed); + } + case enums.publicKey.dsa: { + const { g, p, q, y } = publicParams; + const { r, s } = signature; // no need to pad, since we always handle them as BigIntegers + return publicKey.dsa.verify(hashAlgo, r, s, hashed, g, p, q, y); + } + case enums.publicKey.ecdsa: { + const { oid, Q } = publicParams; + const curveSize = new publicKey.elliptic.Curve(oid).payloadSize; + // padding needed for webcrypto + const r = util.leftPad(signature.r, curveSize); + const s = util.leftPad(signature.s, curveSize); + return publicKey.elliptic.ecdsa.verify(oid, hashAlgo, { r, s }, data, Q, hashed); + } + case enums.publicKey.eddsa: { + const { oid, Q } = publicParams; + // signature already padded on parsing + return publicKey.elliptic.eddsa.verify(oid, hashAlgo, signature, data, Q, hashed); + } + default: + throw new Error('Invalid signature algorithm.'); + } + } + + /** + * Creates a signature on data using specified algorithms and private key parameters. + * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} + * and {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4} + * for public key and hash algorithms. + * @param {module:enums.publicKey} algo - Public key algorithm + * @param {module:enums.hash} hashAlgo - Hash algorithm + * @param {Object} publicKeyParams - Algorithm-specific public and private key parameters + * @param {Object} privateKeyParams - Algorithm-specific public and private key parameters + * @param {Uint8Array} data - Data to be signed + * @param {Uint8Array} hashed - The hashed data + * @returns {Promise} Signature Object containing named signature parameters. + * @async + */ + async function sign$4(algo, hashAlgo, publicKeyParams, privateKeyParams, data, hashed) { + if (!publicKeyParams || !privateKeyParams) { + throw new Error('Missing key parameters'); + } + switch (algo) { + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaEncrypt: + case enums.publicKey.rsaSign: { + const { n, e } = publicKeyParams; + const { d, p, q, u } = privateKeyParams; + const s = await publicKey.rsa.sign(hashAlgo, data, n, e, d, p, q, u, hashed); + return { s }; + } + case enums.publicKey.dsa: { + const { g, p, q } = publicKeyParams; + const { x } = privateKeyParams; + return publicKey.dsa.sign(hashAlgo, hashed, g, p, q, x); + } + case enums.publicKey.elgamal: { + throw new Error('Signing with Elgamal is not defined in the OpenPGP standard.'); + } + case enums.publicKey.ecdsa: { + const { oid, Q } = publicKeyParams; + const { d } = privateKeyParams; + return publicKey.elliptic.ecdsa.sign(oid, hashAlgo, data, Q, d, hashed); + } + case enums.publicKey.eddsa: { + const { oid, Q } = publicKeyParams; + const { seed } = privateKeyParams; + return publicKey.elliptic.eddsa.sign(oid, hashAlgo, data, Q, seed, hashed); + } + default: + throw new Error('Invalid signature algorithm.'); + } + } + + var signature = /*#__PURE__*/Object.freeze({ + __proto__: null, + parseSignatureParams: parseSignatureParams, + verify: verify$4, + sign: sign$4 + }); + + /** + * @fileoverview Provides access to all cryptographic primitives used in OpenPGP.js + * @see module:crypto/crypto + * @see module:crypto/signature + * @see module:crypto/public_key + * @see module:crypto/cipher + * @see module:crypto/random + * @see module:crypto/hash + * @module crypto + * @private + */ + + // TODO move cfb and gcm to cipher + const mod = { + /** @see module:crypto/cipher */ + cipher: cipher, + /** @see module:crypto/hash */ + hash: hash, + /** @see module:crypto/mode */ + mode: mode, + /** @see module:crypto/public_key */ + publicKey: publicKey, + /** @see module:crypto/signature */ + signature: signature, + /** @see module:crypto/random */ + random: random, + /** @see module:crypto/pkcs1 */ + pkcs1: pkcs1, + /** @see module:crypto/pkcs5 */ + pkcs5: pkcs5, + /** @see module:crypto/aes_kw */ + aesKW: aesKW + }; + + Object.assign(mod, crypto$1); + + var TYPED_OK = typeof Uint8Array !== "undefined" && + typeof Uint16Array !== "undefined" && + typeof Int32Array !== "undefined"; + + + // reduce buffer size, avoiding mem copy + function shrinkBuf(buf, size) { + if (buf.length === size) { + return buf; + } + if (buf.subarray) { + return buf.subarray(0, size); + } + buf.length = size; + return buf; + } + + + const fnTyped = { + arraySet: function (dest, src, src_offs, len, dest_offs) { + if (src.subarray && dest.subarray) { + dest.set(src.subarray(src_offs, src_offs + len), dest_offs); + return; + } + // Fallback to ordinary array + for (let i = 0; i < len; i++) { + dest[dest_offs + i] = src[src_offs + i]; + } + }, + // Join array of chunks to single array. + flattenChunks: function (chunks) { + let i, l, len, pos, chunk; + + // calculate data length + len = 0; + for (i = 0, l = chunks.length; i < l; i++) { + len += chunks[i].length; + } + + // join chunks + const result = new Uint8Array(len); + pos = 0; + for (i = 0, l = chunks.length; i < l; i++) { + chunk = chunks[i]; + result.set(chunk, pos); + pos += chunk.length; + } + + return result; + } + }; + + const fnUntyped = { + arraySet: function (dest, src, src_offs, len, dest_offs) { + for (let i = 0; i < len; i++) { + dest[dest_offs + i] = src[src_offs + i]; + } + }, + // Join array of chunks to single array. + flattenChunks: function (chunks) { + return [].concat.apply([], chunks); + } + }; + + + // Enable/Disable typed arrays use, for testing + // + + let Buf8 = TYPED_OK ? Uint8Array : Array; + let Buf16 = TYPED_OK ? Uint16Array : Array; + let Buf32 = TYPED_OK ? Int32Array : Array; + let flattenChunks = TYPED_OK ? fnTyped.flattenChunks : fnUntyped.flattenChunks; + let arraySet = TYPED_OK ? fnTyped.arraySet : fnUntyped.arraySet; + + // (C) 1995-2013 Jean-loup Gailly and Mark Adler + // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin + // + // This software is provided 'as-is', without any express or implied + // warranty. In no event will the authors be held liable for any damages + // arising from the use of this software. + // + // Permission is granted to anyone to use this software for any purpose, + // including commercial applications, and to alter it and redistribute it + // freely, subject to the following restrictions: + // + // 1. The origin of this software must not be misrepresented; you must not + // claim that you wrote the original software. If you use this software + // in a product, an acknowledgment in the product documentation would be + // appreciated but is not required. + // 2. Altered source versions must be plainly marked as such, and must not be + // misrepresented as being the original software. + // 3. This notice may not be removed or altered from any source distribution. + + /* Allowed flush values; see deflate() and inflate() below for details */ + const Z_NO_FLUSH = 0; + const Z_PARTIAL_FLUSH = 1; + const Z_SYNC_FLUSH = 2; + const Z_FULL_FLUSH = 3; + const Z_FINISH = 4; + const Z_BLOCK = 5; + const Z_TREES = 6; + + /* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + const Z_OK = 0; + const Z_STREAM_END = 1; + const Z_NEED_DICT = 2; + const Z_STREAM_ERROR = -2; + const Z_DATA_ERROR = -3; + //export const Z_MEM_ERROR = -4; + const Z_BUF_ERROR = -5; + const Z_DEFAULT_COMPRESSION = -1; + + + const Z_FILTERED = 1; + const Z_HUFFMAN_ONLY = 2; + const Z_RLE = 3; + const Z_FIXED = 4; + const Z_DEFAULT_STRATEGY = 0; + + /* Possible values of the data_type field (though see inflate()) */ + const Z_BINARY = 0; + const Z_TEXT = 1; + //export const Z_ASCII = 1; // = Z_TEXT (deprecated) + const Z_UNKNOWN = 2; + + /* The deflate compression method */ + const Z_DEFLATED = 8; + //export const Z_NULL = null // Use -1 or null inline, depending on var type + + /*============================================================================*/ + + + function zero$1(buf) { + let len = buf.length; while (--len >= 0) { + buf[len] = 0; + } + } + + // From zutil.h + + const STORED_BLOCK = 0; + const STATIC_TREES = 1; + const DYN_TREES = 2; + /* The three kinds of block type */ + + const MIN_MATCH = 3; + const MAX_MATCH = 258; + /* The minimum and maximum match lengths */ + + // From deflate.h + /* =========================================================================== + * Internal compression state. + */ + + const LENGTH_CODES = 29; + /* number of length codes, not counting the special END_BLOCK code */ + + const LITERALS = 256; + /* number of literal bytes 0..255 */ + + const L_CODES = LITERALS + 1 + LENGTH_CODES; + /* number of Literal or Length codes, including the END_BLOCK code */ + + const D_CODES = 30; + /* number of distance codes */ + + const BL_CODES = 19; + /* number of codes used to transfer the bit lengths */ + + const HEAP_SIZE = 2 * L_CODES + 1; + /* maximum heap size */ + + const MAX_BITS = 15; + /* All codes must not exceed MAX_BITS bits */ + + const Buf_size = 16; + /* size of bit buffer in bi_buf */ + + + /* =========================================================================== + * Constants + */ + + const MAX_BL_BITS = 7; + /* Bit length codes must not exceed MAX_BL_BITS bits */ + + const END_BLOCK = 256; + /* end of block literal code */ + + const REP_3_6 = 16; + /* repeat previous bit length 3-6 times (2 bits of repeat count) */ + + const REPZ_3_10 = 17; + /* repeat a zero length 3-10 times (3 bits of repeat count) */ + + const REPZ_11_138 = 18; + /* repeat a zero length 11-138 times (7 bits of repeat count) */ + + /* eslint-disable comma-spacing,array-bracket-spacing */ + const extra_lbits = /* extra bits for each length code */ + [0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0]; + + const extra_dbits = /* extra bits for each distance code */ + [0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13]; + + const extra_blbits = /* extra bits for each bit length code */ + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7]; + + const bl_order = + [16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]; + /* eslint-enable comma-spacing,array-bracket-spacing */ + + /* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + + /* =========================================================================== + * Local data. These are initialized only once. + */ + + // We pre-fill arrays with 0 to avoid uninitialized gaps + + const DIST_CODE_LEN = 512; /* see definition of array dist_code below */ + + // !!!! Use flat array instead of structure, Freq = i*2, Len = i*2+1 + const static_ltree = new Array((L_CODES + 2) * 2); + zero$1(static_ltree); + /* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + + const static_dtree = new Array(D_CODES * 2); + zero$1(static_dtree); + /* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + + const _dist_code = new Array(DIST_CODE_LEN); + zero$1(_dist_code); + /* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + + const _length_code = new Array(MAX_MATCH - MIN_MATCH + 1); + zero$1(_length_code); + /* length code for each normalized match length (0 == MIN_MATCH) */ + + const base_length = new Array(LENGTH_CODES); + zero$1(base_length); + /* First normalized length for each code (0 = MIN_MATCH) */ + + const base_dist = new Array(D_CODES); + zero$1(base_dist); + /* First normalized distance for each code (0 = distance of 1) */ + + + function StaticTreeDesc(static_tree, extra_bits, extra_base, elems, max_length) { + + this.static_tree = static_tree; /* static tree or NULL */ + this.extra_bits = extra_bits; /* extra bits for each code or NULL */ + this.extra_base = extra_base; /* base index for extra_bits */ + this.elems = elems; /* max number of elements in the tree */ + this.max_length = max_length; /* max bit length for the codes */ + + // show if `static_tree` has data or dummy - needed for monomorphic objects + this.has_stree = static_tree && static_tree.length; + } + + + let static_l_desc; + let static_d_desc; + let static_bl_desc; + + + function TreeDesc(dyn_tree, stat_desc) { + this.dyn_tree = dyn_tree; /* the dynamic tree */ + this.max_code = 0; /* largest code with non zero frequency */ + this.stat_desc = stat_desc; /* the corresponding static tree */ + } + + + + function d_code(dist) { + return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)]; + } + + + /* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ + function put_short(s, w) { + // put_byte(s, (uch)((w) & 0xff)); + // put_byte(s, (uch)((ush)(w) >> 8)); + s.pending_buf[s.pending++] = w & 0xff; + s.pending_buf[s.pending++] = w >>> 8 & 0xff; + } + + + /* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ + function send_bits(s, value, length) { + if (s.bi_valid > Buf_size - length) { + s.bi_buf |= value << s.bi_valid & 0xffff; + put_short(s, s.bi_buf); + s.bi_buf = value >> Buf_size - s.bi_valid; + s.bi_valid += length - Buf_size; + } else { + s.bi_buf |= value << s.bi_valid & 0xffff; + s.bi_valid += length; + } + } + + + function send_code(s, c, tree) { + send_bits(s, tree[c * 2]/*.Code*/, tree[c * 2 + 1]/*.Len*/); + } + + + /* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ + function bi_reverse(code, len) { + let res = 0; + do { + res |= code & 1; + code >>>= 1; + res <<= 1; + } while (--len > 0); + return res >>> 1; + } + + + /* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ + function bi_flush(s) { + if (s.bi_valid === 16) { + put_short(s, s.bi_buf); + s.bi_buf = 0; + s.bi_valid = 0; + + } else if (s.bi_valid >= 8) { + s.pending_buf[s.pending++] = s.bi_buf & 0xff; + s.bi_buf >>= 8; + s.bi_valid -= 8; + } + } + + + /* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ + function gen_bitlen(s, desc) + // deflate_state *s; + // tree_desc *desc; /* the tree descriptor */ + { + const tree = desc.dyn_tree; + const max_code = desc.max_code; + const stree = desc.stat_desc.static_tree; + const has_stree = desc.stat_desc.has_stree; + const extra = desc.stat_desc.extra_bits; + const base = desc.stat_desc.extra_base; + const max_length = desc.stat_desc.max_length; + let h; /* heap index */ + let n, m; /* iterate over the tree elements */ + let bits; /* bit length */ + let xbits; /* extra bits */ + let f; /* frequency */ + let overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) { + s.bl_count[bits] = 0; + } + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s.heap[s.heap_max] * 2 + 1]/*.Len*/ = 0; /* root of the heap */ + + for (h = s.heap_max + 1; h < HEAP_SIZE; h++) { + n = s.heap[h]; + bits = tree[tree[n * 2 + 1]/*.Dad*/ * 2 + 1]/*.Len*/ + 1; + if (bits > max_length) { + bits = max_length; + overflow++; + } + tree[n * 2 + 1]/*.Len*/ = bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) { + continue; + } /* not a leaf node */ + + s.bl_count[bits]++; + xbits = 0; + if (n >= base) { + xbits = extra[n - base]; + } + f = tree[n * 2]/*.Freq*/; + s.opt_len += f * (bits + xbits); + if (has_stree) { + s.static_len += f * (stree[n * 2 + 1]/*.Len*/ + xbits); + } + } + if (overflow === 0) { + return; + } + + // Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length - 1; + while (s.bl_count[bits] === 0) { + bits--; + } + s.bl_count[bits]--; /* move one leaf down the tree */ + s.bl_count[bits + 1] += 2; /* move one overflow item as its brother */ + s.bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits !== 0; bits--) { + n = s.bl_count[bits]; + while (n !== 0) { + m = s.heap[--h]; + if (m > max_code) { + continue; + } + if (tree[m * 2 + 1]/*.Len*/ !== bits) { + // Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s.opt_len += (bits - tree[m * 2 + 1]/*.Len*/) * tree[m * 2]/*.Freq*/; + tree[m * 2 + 1]/*.Len*/ = bits; + } + n--; + } + } + } + + + /* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ + function gen_codes(tree, max_code, bl_count) + // ct_data *tree; /* the tree to decorate */ + // int max_code; /* largest code with non zero frequency */ + // ushf *bl_count; /* number of codes at each bit length */ + { + const next_code = new Array(MAX_BITS + 1); /* next code value for each bit length */ + let code = 0; /* running code value */ + let bits; /* bit index */ + let n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = code + bl_count[bits - 1] << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + //Assert (code + bl_count[MAX_BITS]-1 == (1< length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES - 1; code++) { + base_length[code] = length; + for (n = 0; n < 1 << extra_lbits[code]; n++) { + _length_code[length++] = code; + } + } + //Assert (length == 256, "tr_static_init: length != 256"); + /* Note that the length 255 (match length 258) can be represented + * in two different ways: code 284 + 5 bits or code 285, so we + * overwrite length_code[255] to use the best encoding: + */ + _length_code[length - 1] = code; + + /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ + dist = 0; + for (code = 0; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < 1 << extra_dbits[code]; n++) { + _dist_code[dist++] = code; + } + } + //Assert (dist == 256, "tr_static_init: dist != 256"); + dist >>= 7; /* from now on, all distances are divided by 128 */ + for (; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < 1 << extra_dbits[code] - 7; n++) { + _dist_code[256 + dist++] = code; + } + } + //Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) { + bl_count[bits] = 0; + } + + n = 0; + while (n <= 143) { + static_ltree[n * 2 + 1]/*.Len*/ = 8; + n++; + bl_count[8]++; + } + while (n <= 255) { + static_ltree[n * 2 + 1]/*.Len*/ = 9; + n++; + bl_count[9]++; + } + while (n <= 279) { + static_ltree[n * 2 + 1]/*.Len*/ = 7; + n++; + bl_count[7]++; + } + while (n <= 287) { + static_ltree[n * 2 + 1]/*.Len*/ = 8; + n++; + bl_count[8]++; + } + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes(static_ltree, L_CODES + 1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n * 2 + 1]/*.Len*/ = 5; + static_dtree[n * 2]/*.Code*/ = bi_reverse(n, 5); + } + + // Now data ready and we can init static trees + static_l_desc = new StaticTreeDesc(static_ltree, extra_lbits, LITERALS + 1, L_CODES, MAX_BITS); + static_d_desc = new StaticTreeDesc(static_dtree, extra_dbits, 0, D_CODES, MAX_BITS); + static_bl_desc = new StaticTreeDesc(new Array(0), extra_blbits, 0, BL_CODES, MAX_BL_BITS); + + //static_init_done = true; + } + + + /* =========================================================================== + * Initialize a new block. + */ + function init_block(s) { + let n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) { + s.dyn_ltree[n * 2]/*.Freq*/ = 0; + } + for (n = 0; n < D_CODES; n++) { + s.dyn_dtree[n * 2]/*.Freq*/ = 0; + } + for (n = 0; n < BL_CODES; n++) { + s.bl_tree[n * 2]/*.Freq*/ = 0; + } + + s.dyn_ltree[END_BLOCK * 2]/*.Freq*/ = 1; + s.opt_len = s.static_len = 0; + s.last_lit = s.matches = 0; + } + + + /* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ + function bi_windup(s) { + if (s.bi_valid > 8) { + put_short(s, s.bi_buf); + } else if (s.bi_valid > 0) { + //put_byte(s, (Byte)s->bi_buf); + s.pending_buf[s.pending++] = s.bi_buf; + } + s.bi_buf = 0; + s.bi_valid = 0; + } + + /* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ + function copy_block(s, buf, len, header) + //DeflateState *s; + //charf *buf; /* the input data */ + //unsigned len; /* its length */ + //int header; /* true if block header must be written */ + { + bi_windup(s); /* align on byte boundary */ + + if (header) { + put_short(s, len); + put_short(s, ~len); + } + // while (len--) { + // put_byte(s, *buf++); + // } + arraySet(s.pending_buf, s.window, buf, len, s.pending); + s.pending += len; + } + + /* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ + function smaller(tree, n, m, depth) { + const _n2 = n * 2; + const _m2 = m * 2; + return tree[_n2]/*.Freq*/ < tree[_m2]/*.Freq*/ || + tree[_n2]/*.Freq*/ === tree[_m2]/*.Freq*/ && depth[n] <= depth[m]; + } + + /* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ + function pqdownheap(s, tree, k) + // deflate_state *s; + // ct_data *tree; /* the tree to restore */ + // int k; /* node to move down */ + { + const v = s.heap[k]; + let j = k << 1; /* left son of k */ + while (j <= s.heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s.heap_len && + smaller(tree, s.heap[j + 1], s.heap[j], s.depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s.heap[j], s.depth)) { + break; + } + + /* Exchange v with the smallest son */ + s.heap[k] = s.heap[j]; + k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s.heap[k] = v; + } + + + // inlined manually + // var SMALLEST = 1; + + /* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ + function compress_block(s, ltree, dtree) + // deflate_state *s; + // const ct_data *ltree; /* literal tree */ + // const ct_data *dtree; /* distance tree */ + { + let dist; /* distance of matched string */ + let lc; /* match length or unmatched char (if dist == 0) */ + let lx = 0; /* running index in l_buf */ + let code; /* the code to send */ + let extra; /* number of extra bits to send */ + + if (s.last_lit !== 0) { + do { + dist = s.pending_buf[s.d_buf + lx * 2] << 8 | s.pending_buf[s.d_buf + lx * 2 + 1]; + lc = s.pending_buf[s.l_buf + lx]; + lx++; + + if (dist === 0) { + send_code(s, lc, ltree); /* send a literal byte */ + //Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code + LITERALS + 1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra !== 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + //Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra !== 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + //Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + // "pendingBuf overflow"); + + } while (lx < s.last_lit); + } + + send_code(s, END_BLOCK, ltree); + } + + + /* =========================================================================== + * Construct one Huffman tree and assigns the code bit strings and lengths. + * Update the total bit length for the current block. + * IN assertion: the field freq is set for all tree elements. + * OUT assertions: the fields len and code are set to the optimal bit length + * and corresponding code. The length opt_len is updated; static_len is + * also updated if stree is not null. The field max_code is set. + */ + function build_tree(s, desc) + // deflate_state *s; + // tree_desc *desc; /* the tree descriptor */ + { + const tree = desc.dyn_tree; + const stree = desc.stat_desc.static_tree; + const has_stree = desc.stat_desc.has_stree; + const elems = desc.stat_desc.elems; + let n, m; /* iterate over heap elements */ + let max_code = -1; /* largest code with non zero frequency */ + let node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s.heap_len = 0; + s.heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n * 2]/*.Freq*/ !== 0) { + s.heap[++s.heap_len] = max_code = n; + s.depth[n] = 0; + + } else { + tree[n * 2 + 1]/*.Len*/ = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s.heap_len < 2) { + node = s.heap[++s.heap_len] = max_code < 2 ? ++max_code : 0; + tree[node * 2]/*.Freq*/ = 1; + s.depth[node] = 0; + s.opt_len--; + + if (has_stree) { + s.static_len -= stree[node * 2 + 1]/*.Len*/; + } + /* node is 0 or 1 so it does not have extra bits */ + } + desc.max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s.heap_len >> 1/*int /2*/; n >= 1; n--) { + pqdownheap(s, tree, n); + } + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + //pqremove(s, tree, n); /* n = node of least frequency */ + /*** pqremove ***/ + n = s.heap[1/*SMALLEST*/]; + s.heap[1/*SMALLEST*/] = s.heap[s.heap_len--]; + pqdownheap(s, tree, 1/*SMALLEST*/); + /***/ + + m = s.heap[1/*SMALLEST*/]; /* m = node of next least frequency */ + + s.heap[--s.heap_max] = n; /* keep the nodes sorted by frequency */ + s.heap[--s.heap_max] = m; + + /* Create a new node father of n and m */ + tree[node * 2]/*.Freq*/ = tree[n * 2]/*.Freq*/ + tree[m * 2]/*.Freq*/; + s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1; + tree[n * 2 + 1]/*.Dad*/ = tree[m * 2 + 1]/*.Dad*/ = node; + + /* and insert the new node in the heap */ + s.heap[1/*SMALLEST*/] = node++; + pqdownheap(s, tree, 1/*SMALLEST*/); + + } while (s.heap_len >= 2); + + s.heap[--s.heap_max] = s.heap[1/*SMALLEST*/]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes(tree, max_code, s.bl_count); + } + + + /* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ + function scan_tree(s, tree, max_code) + // deflate_state *s; + // ct_data *tree; /* the tree to be scanned */ + // int max_code; /* and its largest code of non zero frequency */ + { + let n; /* iterates over all tree elements */ + let prevlen = -1; /* last emitted length */ + let curlen; /* length of current code */ + + let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */ + + let count = 0; /* repeat count of the current code */ + let max_count = 7; /* max repeat count */ + let min_count = 4; /* min repeat count */ + + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } + tree[(max_code + 1) * 2 + 1]/*.Len*/ = 0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[(n + 1) * 2 + 1]/*.Len*/; + + if (++count < max_count && curlen === nextlen) { + continue; + + } else if (count < min_count) { + s.bl_tree[curlen * 2]/*.Freq*/ += count; + + } else if (curlen !== 0) { + + if (curlen !== prevlen) { + s.bl_tree[curlen * 2]/*.Freq*/++; + } + s.bl_tree[REP_3_6 * 2]/*.Freq*/++; + + } else if (count <= 10) { + s.bl_tree[REPZ_3_10 * 2]/*.Freq*/++; + + } else { + s.bl_tree[REPZ_11_138 * 2]/*.Freq*/++; + } + + count = 0; + prevlen = curlen; + + if (nextlen === 0) { + max_count = 138; + min_count = 3; + + } else if (curlen === nextlen) { + max_count = 6; + min_count = 3; + + } else { + max_count = 7; + min_count = 4; + } + } + } + + + /* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ + function send_tree(s, tree, max_code) + // deflate_state *s; + // ct_data *tree; /* the tree to be scanned */ + // int max_code; /* and its largest code of non zero frequency */ + { + let n; /* iterates over all tree elements */ + let prevlen = -1; /* last emitted length */ + let curlen; /* length of current code */ + + let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */ + + let count = 0; /* repeat count of the current code */ + let max_count = 7; /* max repeat count */ + let min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[(n + 1) * 2 + 1]/*.Len*/; + + if (++count < max_count && curlen === nextlen) { + continue; + + } else if (count < min_count) { + do { + send_code(s, curlen, s.bl_tree); + } while (--count !== 0); + + } else if (curlen !== 0) { + if (curlen !== prevlen) { + send_code(s, curlen, s.bl_tree); + count--; + } + //Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s.bl_tree); + send_bits(s, count - 3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s.bl_tree); + send_bits(s, count - 3, 3); + + } else { + send_code(s, REPZ_11_138, s.bl_tree); + send_bits(s, count - 11, 7); + } + + count = 0; + prevlen = curlen; + if (nextlen === 0) { + max_count = 138; + min_count = 3; + + } else if (curlen === nextlen) { + max_count = 6; + min_count = 3; + + } else { + max_count = 7; + min_count = 4; + } + } + } + + + /* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ + function build_bl_tree(s) { + let max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, s.dyn_ltree, s.l_desc.max_code); + scan_tree(s, s.dyn_dtree, s.d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, s.bl_desc); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) { + if (s.bl_tree[bl_order[max_blindex] * 2 + 1]/*.Len*/ !== 0) { + break; + } + } + /* Update opt_len to include the bit length tree and counts */ + s.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4; + //Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + // s->opt_len, s->static_len)); + + return max_blindex; + } + + + /* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ + function send_all_trees(s, lcodes, dcodes, blcodes) + // deflate_state *s; + // int lcodes, dcodes, blcodes; /* number of codes for each tree */ + { + let rank; /* index in bl_order */ + + //Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + //Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + // "too many codes"); + //Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes - 1, 5); + send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + //Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s.bl_tree[bl_order[rank] * 2 + 1]/*.Len*/, 3); + } + //Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, s.dyn_ltree, lcodes - 1); /* literal tree */ + //Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, s.dyn_dtree, dcodes - 1); /* distance tree */ + //Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); + } + + + /* =========================================================================== + * Check if the data type is TEXT or BINARY, using the following algorithm: + * - TEXT if the two conditions below are satisfied: + * a) There are no non-portable control characters belonging to the + * "black list" (0..6, 14..25, 28..31). + * b) There is at least one printable character belonging to the + * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). + * - BINARY otherwise. + * - The following partially-portable control characters form a + * "gray list" that is ignored in this detection algorithm: + * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). + * IN assertion: the fields Freq of dyn_ltree are set. + */ + function detect_data_type(s) { + /* black_mask is the bit mask of black-listed bytes + * set bits 0..6, 14..25, and 28..31 + * 0xf3ffc07f = binary 11110011111111111100000001111111 + */ + let black_mask = 0xf3ffc07f; + let n; + + /* Check for non-textual ("black-listed") bytes. */ + for (n = 0; n <= 31; n++, black_mask >>>= 1) { + if (black_mask & 1 && s.dyn_ltree[n * 2]/*.Freq*/ !== 0) { + return Z_BINARY; + } + } + + /* Check for textual ("white-listed") bytes. */ + if (s.dyn_ltree[9 * 2]/*.Freq*/ !== 0 || s.dyn_ltree[10 * 2]/*.Freq*/ !== 0 || + s.dyn_ltree[13 * 2]/*.Freq*/ !== 0) { + return Z_TEXT; + } + for (n = 32; n < LITERALS; n++) { + if (s.dyn_ltree[n * 2]/*.Freq*/ !== 0) { + return Z_TEXT; + } + } + + /* There are no "black-listed" or "white-listed" bytes: + * this stream either is empty or has tolerated ("gray-listed") bytes only. + */ + return Z_BINARY; + } + + + let static_init_done = false; + + /* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ + function _tr_init(s) { + + if (!static_init_done) { + tr_static_init(); + static_init_done = true; + } + + s.l_desc = new TreeDesc(s.dyn_ltree, static_l_desc); + s.d_desc = new TreeDesc(s.dyn_dtree, static_d_desc); + s.bl_desc = new TreeDesc(s.bl_tree, static_bl_desc); + + s.bi_buf = 0; + s.bi_valid = 0; + + /* Initialize the first block of the first file: */ + init_block(s); + } + + + /* =========================================================================== + * Send a stored block + */ + function _tr_stored_block(s, buf, stored_len, last) + //DeflateState *s; + //charf *buf; /* input block */ + //ulg stored_len; /* length of input block */ + //int last; /* one if this is the last block for a file */ + { + send_bits(s, (STORED_BLOCK << 1) + (last ? 1 : 0), 3); /* send block type */ + copy_block(s, buf, stored_len, true); /* with header */ + } + + + /* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + */ + function _tr_align(s) { + send_bits(s, STATIC_TREES << 1, 3); + send_code(s, END_BLOCK, static_ltree); + bi_flush(s); + } + + + /* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ + function _tr_flush_block(s, buf, stored_len, last) + //DeflateState *s; + //charf *buf; /* input block, or NULL if too old */ + //ulg stored_len; /* length of input block */ + //int last; /* one if this is the last block for a file */ + { + let opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + let max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s.level > 0) { + + /* Check if the file is binary or text */ + if (s.strm.data_type === Z_UNKNOWN) { + s.strm.data_type = detect_data_type(s); + } + + /* Construct the literal and distance trees */ + build_tree(s, s.l_desc); + // Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + // s->static_len)); + + build_tree(s, s.d_desc); + // Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + // s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = s.opt_len + 3 + 7 >>> 3; + static_lenb = s.static_len + 3 + 7 >>> 3; + + // Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + // opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + // s->last_lit)); + + if (static_lenb <= opt_lenb) { + opt_lenb = static_lenb; + } + + } else { + // Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + + if (stored_len + 4 <= opt_lenb && buf !== -1) { + /* 4: two words for the lengths */ + + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, last); + + } else if (s.strategy === Z_FIXED || static_lenb === opt_lenb) { + + send_bits(s, (STATIC_TREES << 1) + (last ? 1 : 0), 3); + compress_block(s, static_ltree, static_dtree); + + } else { + send_bits(s, (DYN_TREES << 1) + (last ? 1 : 0), 3); + send_all_trees(s, s.l_desc.max_code + 1, s.d_desc.max_code + 1, max_blindex + 1); + compress_block(s, s.dyn_ltree, s.dyn_dtree); + } + // Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (last) { + bi_windup(s); + } + // Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + // s->compressed_len-7*last)); + } + + /* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ + function _tr_tally(s, dist, lc) + // deflate_state *s; + // unsigned dist; /* distance of matched string */ + // unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ + { + //var out_length, in_length, dcode; + + s.pending_buf[s.d_buf + s.last_lit * 2] = dist >>> 8 & 0xff; + s.pending_buf[s.d_buf + s.last_lit * 2 + 1] = dist & 0xff; + + s.pending_buf[s.l_buf + s.last_lit] = lc & 0xff; + s.last_lit++; + + if (dist === 0) { + /* lc is the unmatched char */ + s.dyn_ltree[lc * 2]/*.Freq*/++; + } else { + s.matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + //Assert((ush)dist < (ush)MAX_DIST(s) && + // (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + // (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s.dyn_ltree[(_length_code[lc] + LITERALS + 1) * 2]/*.Freq*/++; + s.dyn_dtree[d_code(dist) * 2]/*.Freq*/++; + } + + // (!) This block is disabled in zlib defaults, + // don't enable it for binary compatibility + + //#ifdef TRUNCATE_BLOCK + // /* Try to guess if it is profitable to stop the current block here */ + // if ((s.last_lit & 0x1fff) === 0 && s.level > 2) { + // /* Compute an upper bound for the compressed length */ + // out_length = s.last_lit*8; + // in_length = s.strstart - s.block_start; + // + // for (dcode = 0; dcode < D_CODES; dcode++) { + // out_length += s.dyn_dtree[dcode*2]/*.Freq*/ * (5 + extra_dbits[dcode]); + // } + // out_length >>>= 3; + // //Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + // // s->last_lit, in_length, out_length, + // // 100L - out_length*100L/in_length)); + // if (s.matches < (s.last_lit>>1)/*int /2*/ && out_length < (in_length>>1)/*int /2*/) { + // return true; + // } + // } + //#endif + + return s.last_lit === s.lit_bufsize - 1; + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ + } + + // Note: adler32 takes 12% for level 0 and 2% for level 6. + // It isn't worth it to make additional optimizations as in original. + // Small size is preferable. + + // (C) 1995-2013 Jean-loup Gailly and Mark Adler + // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin + // + // This software is provided 'as-is', without any express or implied + // warranty. In no event will the authors be held liable for any damages + // arising from the use of this software. + // + // Permission is granted to anyone to use this software for any purpose, + // including commercial applications, and to alter it and redistribute it + // freely, subject to the following restrictions: + // + // 1. The origin of this software must not be misrepresented; you must not + // claim that you wrote the original software. If you use this software + // in a product, an acknowledgment in the product documentation would be + // appreciated but is not required. + // 2. Altered source versions must be plainly marked as such, and must not be + // misrepresented as being the original software. + // 3. This notice may not be removed or altered from any source distribution. + + function adler32(adler, buf, len, pos) { + let s1 = adler & 0xffff |0, + s2 = adler >>> 16 & 0xffff |0, + n = 0; + + while (len !== 0) { + // Set limit ~ twice less than 5552, to keep + // s2 in 31-bits, because we force signed ints. + // in other case %= will fail. + n = len > 2000 ? 2000 : len; + len -= n; + + do { + s1 = s1 + buf[pos++] |0; + s2 = s2 + s1 |0; + } while (--n); + + s1 %= 65521; + s2 %= 65521; + } + + return s1 | s2 << 16 |0; + } + + // Note: we can't get significant speed boost here. + // So write code to minimize size - no pregenerated tables + // and array tools dependencies. + + // (C) 1995-2013 Jean-loup Gailly and Mark Adler + // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin + // + // This software is provided 'as-is', without any express or implied + // warranty. In no event will the authors be held liable for any damages + // arising from the use of this software. + // + // Permission is granted to anyone to use this software for any purpose, + // including commercial applications, and to alter it and redistribute it + // freely, subject to the following restrictions: + // + // 1. The origin of this software must not be misrepresented; you must not + // claim that you wrote the original software. If you use this software + // in a product, an acknowledgment in the product documentation would be + // appreciated but is not required. + // 2. Altered source versions must be plainly marked as such, and must not be + // misrepresented as being the original software. + // 3. This notice may not be removed or altered from any source distribution. + + // Use ordinary array, since untyped makes no boost here + function makeTable() { + let c; + const table = []; + + for (let n = 0; n < 256; n++) { + c = n; + for (let k = 0; k < 8; k++) { + c = c & 1 ? 0xEDB88320 ^ c >>> 1 : c >>> 1; + } + table[n] = c; + } + + return table; + } + + // Create table on load. Just 255 signed longs. Not a problem. + const crcTable = makeTable(); + + + function crc32(crc, buf, len, pos) { + const t = crcTable, + end = pos + len; + + crc ^= -1; + + for (let i = pos; i < end; i++) { + crc = crc >>> 8 ^ t[(crc ^ buf[i]) & 0xFF]; + } + + return crc ^ -1; // >>> 0; + } + + // (C) 1995-2013 Jean-loup Gailly and Mark Adler + // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin + // + // This software is provided 'as-is', without any express or implied + // warranty. In no event will the authors be held liable for any damages + // arising from the use of this software. + // + // Permission is granted to anyone to use this software for any purpose, + // including commercial applications, and to alter it and redistribute it + // freely, subject to the following restrictions: + // + // 1. The origin of this software must not be misrepresented; you must not + // claim that you wrote the original software. If you use this software + // in a product, an acknowledgment in the product documentation would be + // appreciated but is not required. + // 2. Altered source versions must be plainly marked as such, and must not be + // misrepresented as being the original software. + // 3. This notice may not be removed or altered from any source distribution. + + var msg = { + 2: "need dictionary", /* Z_NEED_DICT 2 */ + 1: "stream end", /* Z_STREAM_END 1 */ + 0: "", /* Z_OK 0 */ + "-1": "file error", /* Z_ERRNO (-1) */ + "-2": "stream error", /* Z_STREAM_ERROR (-2) */ + "-3": "data error", /* Z_DATA_ERROR (-3) */ + "-4": "insufficient memory", /* Z_MEM_ERROR (-4) */ + "-5": "buffer error", /* Z_BUF_ERROR (-5) */ + "-6": "incompatible version" /* Z_VERSION_ERROR (-6) */ + }; + + /*============================================================================*/ + + + const MAX_MEM_LEVEL = 9; + + + const LENGTH_CODES$1 = 29; + /* number of length codes, not counting the special END_BLOCK code */ + const LITERALS$1 = 256; + /* number of literal bytes 0..255 */ + const L_CODES$1 = LITERALS$1 + 1 + LENGTH_CODES$1; + /* number of Literal or Length codes, including the END_BLOCK code */ + const D_CODES$1 = 30; + /* number of distance codes */ + const BL_CODES$1 = 19; + /* number of codes used to transfer the bit lengths */ + const HEAP_SIZE$1 = 2 * L_CODES$1 + 1; + /* maximum heap size */ + const MAX_BITS$1 = 15; + /* All codes must not exceed MAX_BITS bits */ + + const MIN_MATCH$1 = 3; + const MAX_MATCH$1 = 258; + const MIN_LOOKAHEAD = (MAX_MATCH$1 + MIN_MATCH$1 + 1); + + const PRESET_DICT = 0x20; + + const INIT_STATE = 42; + const EXTRA_STATE = 69; + const NAME_STATE = 73; + const COMMENT_STATE = 91; + const HCRC_STATE = 103; + const BUSY_STATE = 113; + const FINISH_STATE = 666; + + const BS_NEED_MORE = 1; /* block not completed, need more input or more output */ + const BS_BLOCK_DONE = 2; /* block flush performed */ + const BS_FINISH_STARTED = 3; /* finish started, need only more output at next deflate */ + const BS_FINISH_DONE = 4; /* finish done, accept no more input or output */ + + const OS_CODE = 0x03; // Unix :) . Don't detect, use this default. + + function err(strm, errorCode) { + strm.msg = msg[errorCode]; + return errorCode; + } + + function rank(f) { + return ((f) << 1) - ((f) > 4 ? 9 : 0); + } + + function zero$2(buf) { let len = buf.length; while (--len >= 0) { buf[len] = 0; } } + + + /* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->output buffer and copying into it. + * (See also read_buf()). + */ + function flush_pending(strm) { + const s = strm.state; + + //_tr_flush_bits(s); + let len = s.pending; + if (len > strm.avail_out) { + len = strm.avail_out; + } + if (len === 0) { return; } + + arraySet(strm.output, s.pending_buf, s.pending_out, len, strm.next_out); + strm.next_out += len; + s.pending_out += len; + strm.total_out += len; + strm.avail_out -= len; + s.pending -= len; + if (s.pending === 0) { + s.pending_out = 0; + } + } + + + function flush_block_only(s, last) { + _tr_flush_block(s, (s.block_start >= 0 ? s.block_start : -1), s.strstart - s.block_start, last); + s.block_start = s.strstart; + flush_pending(s.strm); + } + + + function put_byte(s, b) { + s.pending_buf[s.pending++] = b; + } + + + /* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ + function putShortMSB(s, b) { + // put_byte(s, (Byte)(b >> 8)); + // put_byte(s, (Byte)(b & 0xff)); + s.pending_buf[s.pending++] = (b >>> 8) & 0xff; + s.pending_buf[s.pending++] = b & 0xff; + } + + + /* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->input buffer and copying from it. + * (See also flush_pending()). + */ + function read_buf(strm, buf, start, size) { + let len = strm.avail_in; + + if (len > size) { len = size; } + if (len === 0) { return 0; } + + strm.avail_in -= len; + + // zmemcpy(buf, strm->next_in, len); + arraySet(buf, strm.input, strm.next_in, len, start); + if (strm.state.wrap === 1) { + strm.adler = adler32(strm.adler, buf, len, start); + } + + else if (strm.state.wrap === 2) { + strm.adler = crc32(strm.adler, buf, len, start); + } + + strm.next_in += len; + strm.total_in += len; + + return len; + } + + + /* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ + function longest_match(s, cur_match) { + let chain_length = s.max_chain_length; /* max hash chain length */ + let scan = s.strstart; /* current string */ + let match; /* matched string */ + let len; /* length of current match */ + let best_len = s.prev_length; /* best match length so far */ + let nice_match = s.nice_match; /* stop if match long enough */ + const limit = (s.strstart > (s.w_size - MIN_LOOKAHEAD)) ? + s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0/*NIL*/; + + const _win = s.window; // shortcut + + const wmask = s.w_mask; + const prev = s.prev; + + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + + const strend = s.strstart + MAX_MATCH$1; + let scan_end1 = _win[scan + best_len - 1]; + let scan_end = _win[scan + best_len]; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + // Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s.prev_length >= s.good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if (nice_match > s.lookahead) { nice_match = s.lookahead; } + + // Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + // Assert(cur_match < s->strstart, "no future"); + match = cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2. Note that the checks below + * for insufficient lookahead only occur occasionally for performance + * reasons. Therefore uninitialized memory will be accessed, and + * conditional jumps will be made that depend on those values. + * However the length of the match is limited to the lookahead, so + * the output of deflate is not affected by the uninitialized values. + */ + + if (_win[match + best_len] !== scan_end || + _win[match + best_len - 1] !== scan_end1 || + _win[match] !== _win[scan] || + _win[++match] !== _win[scan + 1]) { + continue; + } + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2; + match++; + // Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + /*jshint noempty:false*/ + } while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + scan < strend); + + // Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH$1 - (strend - scan); + scan = strend - MAX_MATCH$1; + + if (len > best_len) { + s.match_start = cur_match; + best_len = len; + if (len >= nice_match) { + break; + } + scan_end1 = _win[scan + best_len - 1]; + scan_end = _win[scan + best_len]; + } + } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0); + + if (best_len <= s.lookahead) { + return best_len; + } + return s.lookahead; + } + + + /* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ + function fill_window(s) { + const _w_size = s.w_size; + let p, n, m, more, str; + + //Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); + + do { + more = s.window_size - s.lookahead - s.strstart; + + // JS ints have 32 bit, block below not needed + /* Deal with !@#$% 64K limit: */ + //if (sizeof(int) <= 2) { + // if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + // more = wsize; + // + // } else if (more == (unsigned)(-1)) { + // /* Very unlikely, but possible on 16 bit machine if + // * strstart == 0 && lookahead == 1 (input done a byte at time) + // */ + // more--; + // } + //} + + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) { + + arraySet(s.window, s.window, _w_size, _w_size, 0); + s.match_start -= _w_size; + s.strstart -= _w_size; + /* we now have strstart >= MAX_DIST */ + s.block_start -= _w_size; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + + n = s.hash_size; + p = n; + do { + m = s.head[--p]; + s.head[p] = (m >= _w_size ? m - _w_size : 0); + } while (--n); + + n = _w_size; + p = n; + do { + m = s.prev[--p]; + s.prev[p] = (m >= _w_size ? m - _w_size : 0); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); + + more += _w_size; + } + if (s.strm.avail_in === 0) { + break; + } + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + //Assert(more >= 2, "more < 2"); + n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more); + s.lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s.lookahead + s.insert >= MIN_MATCH$1) { + str = s.strstart - s.insert; + s.ins_h = s.window[str]; + + /* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + 1]) & s.hash_mask; + //#if MIN_MATCH != 3 + // Call update_hash() MIN_MATCH-3 more times + //#endif + while (s.insert) { + /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH$1 - 1]) & s.hash_mask; + + s.prev[str & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = str; + str++; + s.insert--; + if (s.lookahead + s.insert < MIN_MATCH$1) { + break; + } + } + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0); + + /* If the WIN_INIT bytes after the end of the current data have never been + * written, then zero those bytes in order to avoid memory check reports of + * the use of uninitialized (or uninitialised as Julian writes) bytes by + * the longest match routines. Update the high water mark for the next + * time through here. WIN_INIT is set to MAX_MATCH since the longest match + * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. + */ + // if (s.high_water < s.window_size) { + // var curr = s.strstart + s.lookahead; + // var init = 0; + // + // if (s.high_water < curr) { + // /* Previous high water mark below current data -- zero WIN_INIT + // * bytes or up to end of window, whichever is less. + // */ + // init = s.window_size - curr; + // if (init > WIN_INIT) + // init = WIN_INIT; + // zmemzero(s->window + curr, (unsigned)init); + // s->high_water = curr + init; + // } + // else if (s->high_water < (ulg)curr + WIN_INIT) { + // /* High water mark at or above current data, but below current data + // * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up + // * to end of window, whichever is less. + // */ + // init = (ulg)curr + WIN_INIT - s->high_water; + // if (init > s->window_size - s->high_water) + // init = s->window_size - s->high_water; + // zmemzero(s->window + s->high_water, (unsigned)init); + // s->high_water += init; + // } + // } + // + // Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, + // "not enough room for search"); + } + + /* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ + function deflate_stored(s, flush) { + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + let max_block_size = 0xffff; + + if (max_block_size > s.pending_buf_size - 5) { + max_block_size = s.pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (; ;) { + /* Fill the window as much as possible: */ + if (s.lookahead <= 1) { + + //Assert(s->strstart < s->w_size+MAX_DIST(s) || + // s->block_start >= (long)s->w_size, "slide too late"); + // if (!(s.strstart < s.w_size + (s.w_size - MIN_LOOKAHEAD) || + // s.block_start >= s.w_size)) { + // throw new Error("slide too late"); + // } + + fill_window(s); + if (s.lookahead === 0 && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + + if (s.lookahead === 0) { + break; + } + /* flush the current block */ + } + //Assert(s->block_start >= 0L, "block gone"); + // if (s.block_start < 0) throw new Error("block gone"); + + s.strstart += s.lookahead; + s.lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + const max_start = s.block_start + max_block_size; + + if (s.strstart === 0 || s.strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s.lookahead = s.strstart - max_start; + s.strstart = max_start; + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + + + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s.strstart - s.block_start >= (s.w_size - MIN_LOOKAHEAD)) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + + s.insert = 0; + + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + + if (s.strstart > s.block_start) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + + return BS_NEED_MORE; + } + + /* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ + function deflate_fast(s, flush) { + let hash_head; /* head of the hash chain */ + let bflush; /* set if current block must be flushed */ + + for (; ;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s.lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { + break; /* flush the current block */ + } + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = 0/*NIL*/; + if (s.lookahead >= MIN_MATCH$1) { + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head !== 0/*NIL*/ && ((s.strstart - hash_head) <= (s.w_size - MIN_LOOKAHEAD))) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s.match_length = longest_match(s, hash_head); + /* longest_match() sets match_start */ + } + if (s.match_length >= MIN_MATCH$1) { + // check_match(s, s.strstart, s.match_start, s.match_length); // for debug only + + /*** _tr_tally_dist(s, s.strstart - s.match_start, + s.match_length - MIN_MATCH, bflush); ***/ + bflush = _tr_tally(s, s.strstart - s.match_start, s.match_length - MIN_MATCH$1); + + s.lookahead -= s.match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ + if (s.match_length <= s.max_lazy_match/*max_insert_length*/ && s.lookahead >= MIN_MATCH$1) { + s.match_length--; /* string at strstart already in table */ + do { + s.strstart++; + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s.match_length !== 0); + s.strstart++; + } else { + s.strstart += s.match_length; + s.match_length = 0; + s.ins_h = s.window[s.strstart]; + /* UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]); */ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + 1]) & s.hash_mask; + + //#if MIN_MATCH != 3 + // Call UPDATE_HASH() MIN_MATCH-3 more times + //#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + //Tracevv((stderr,"%c", s.window[s.strstart])); + /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ + bflush = _tr_tally(s, 0, s.window[s.strstart]); + + s.lookahead--; + s.strstart++; + } + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + s.insert = ((s.strstart < (MIN_MATCH$1 - 1)) ? s.strstart : MIN_MATCH$1 - 1); + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + return BS_BLOCK_DONE; + } + + /* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ + function deflate_slow(s, flush) { + let hash_head; /* head of hash chain */ + let bflush; /* set if current block must be flushed */ + + let max_insert; + + /* Process the input block. */ + for (; ;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s.lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { break; } /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = 0/*NIL*/; + if (s.lookahead >= MIN_MATCH$1) { + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + } + + /* Find the longest match, discarding those <= prev_length. + */ + s.prev_length = s.match_length; + s.prev_match = s.match_start; + s.match_length = MIN_MATCH$1 - 1; + + if (hash_head !== 0/*NIL*/ && s.prev_length < s.max_lazy_match && + s.strstart - hash_head <= (s.w_size - MIN_LOOKAHEAD)/*MAX_DIST(s)*/) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s.match_length = longest_match(s, hash_head); + /* longest_match() sets match_start */ + + if (s.match_length <= 5 && + (s.strategy === Z_FILTERED || (s.match_length === MIN_MATCH$1 && s.strstart - s.match_start > 4096/*TOO_FAR*/))) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s.match_length = MIN_MATCH$1 - 1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s.prev_length >= MIN_MATCH$1 && s.match_length <= s.prev_length) { + max_insert = s.strstart + s.lookahead - MIN_MATCH$1; + /* Do not insert strings in hash table beyond this. */ + + //check_match(s, s.strstart-1, s.prev_match, s.prev_length); + + /***_tr_tally_dist(s, s.strstart - 1 - s.prev_match, + s.prev_length - MIN_MATCH, bflush);***/ + bflush = _tr_tally(s, s.strstart - 1 - s.prev_match, s.prev_length - MIN_MATCH$1); + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s.lookahead -= s.prev_length - 1; + s.prev_length -= 2; + do { + if (++s.strstart <= max_insert) { + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + } + } while (--s.prev_length !== 0); + s.match_available = 0; + s.match_length = MIN_MATCH$1 - 1; + s.strstart++; + + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + + } else if (s.match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + //Tracevv((stderr,"%c", s->window[s->strstart-1])); + /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ + bflush = _tr_tally(s, 0, s.window[s.strstart - 1]); + + if (bflush) { + /*** FLUSH_BLOCK_ONLY(s, 0) ***/ + flush_block_only(s, false); + /***/ + } + s.strstart++; + s.lookahead--; + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s.match_available = 1; + s.strstart++; + s.lookahead--; + } + } + //Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s.match_available) { + //Tracevv((stderr,"%c", s->window[s->strstart-1])); + /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ + bflush = _tr_tally(s, 0, s.window[s.strstart - 1]); + + s.match_available = 0; + } + s.insert = s.strstart < MIN_MATCH$1 - 1 ? s.strstart : MIN_MATCH$1 - 1; + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + + return BS_BLOCK_DONE; + } + + + /* =========================================================================== + * For Z_RLE, simply look for runs of bytes, generate matches only of distance + * one. Do not maintain a hash table. (It will be regenerated if this run of + * deflate switches away from Z_RLE.) + */ + function deflate_rle(s, flush) { + let bflush; /* set if current block must be flushed */ + let prev; /* byte at distance one to match */ + let scan, strend; /* scan goes up to strend for length of run */ + + const _win = s.window; + + for (; ;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the longest run, plus one for the unrolled loop. + */ + if (s.lookahead <= MAX_MATCH$1) { + fill_window(s); + if (s.lookahead <= MAX_MATCH$1 && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { break; } /* flush the current block */ + } + + /* See how many times the previous byte repeats */ + s.match_length = 0; + if (s.lookahead >= MIN_MATCH$1 && s.strstart > 0) { + scan = s.strstart - 1; + prev = _win[scan]; + if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) { + strend = s.strstart + MAX_MATCH$1; + do { + /*jshint noempty:false*/ + } while (prev === _win[++scan] && prev === _win[++scan] && + prev === _win[++scan] && prev === _win[++scan] && + prev === _win[++scan] && prev === _win[++scan] && + prev === _win[++scan] && prev === _win[++scan] && + scan < strend); + s.match_length = MAX_MATCH$1 - (strend - scan); + if (s.match_length > s.lookahead) { + s.match_length = s.lookahead; + } + } + //Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); + } + + /* Emit match if have run of MIN_MATCH or longer, else emit literal */ + if (s.match_length >= MIN_MATCH$1) { + //check_match(s, s.strstart, s.strstart - 1, s.match_length); + + /*** _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ***/ + bflush = _tr_tally(s, 1, s.match_length - MIN_MATCH$1); + + s.lookahead -= s.match_length; + s.strstart += s.match_length; + s.match_length = 0; + } else { + /* No match, output a literal byte */ + //Tracevv((stderr,"%c", s->window[s->strstart])); + /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ + bflush = _tr_tally(s, 0, s.window[s.strstart]); + + s.lookahead--; + s.strstart++; + } + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + s.insert = 0; + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + return BS_BLOCK_DONE; + } + + /* =========================================================================== + * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. + * (It will be regenerated if this run of deflate switches away from Huffman.) + */ + function deflate_huff(s, flush) { + let bflush; /* set if current block must be flushed */ + + for (; ;) { + /* Make sure that we have a literal to write. */ + if (s.lookahead === 0) { + fill_window(s); + if (s.lookahead === 0) { + if (flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + break; /* flush the current block */ + } + } + + /* Output a literal byte */ + s.match_length = 0; + //Tracevv((stderr,"%c", s->window[s->strstart])); + /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ + bflush = _tr_tally(s, 0, s.window[s.strstart]); + s.lookahead--; + s.strstart++; + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + s.insert = 0; + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + return BS_BLOCK_DONE; + } + + /* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ + class Config { + constructor(good_length, max_lazy, nice_length, max_chain, func) { + this.good_length = good_length; + this.max_lazy = max_lazy; + this.nice_length = nice_length; + this.max_chain = max_chain; + this.func = func; + } + } + const configuration_table = [ + /* good lazy nice chain */ + new Config(0, 0, 0, 0, deflate_stored), /* 0 store only */ + new Config(4, 4, 8, 4, deflate_fast), /* 1 max speed, no lazy matches */ + new Config(4, 5, 16, 8, deflate_fast), /* 2 */ + new Config(4, 6, 32, 32, deflate_fast), /* 3 */ + + new Config(4, 4, 16, 16, deflate_slow), /* 4 lazy matches */ + new Config(8, 16, 32, 32, deflate_slow), /* 5 */ + new Config(8, 16, 128, 128, deflate_slow), /* 6 */ + new Config(8, 32, 128, 256, deflate_slow), /* 7 */ + new Config(32, 128, 258, 1024, deflate_slow), /* 8 */ + new Config(32, 258, 258, 4096, deflate_slow) /* 9 max compression */ + ]; + + + /* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ + function lm_init(s) { + s.window_size = 2 * s.w_size; + + /*** CLEAR_HASH(s); ***/ + zero$2(s.head); // Fill with NIL (= 0); + + /* Set the default configuration parameters: + */ + s.max_lazy_match = configuration_table[s.level].max_lazy; + s.good_match = configuration_table[s.level].good_length; + s.nice_match = configuration_table[s.level].nice_length; + s.max_chain_length = configuration_table[s.level].max_chain; + + s.strstart = 0; + s.block_start = 0; + s.lookahead = 0; + s.insert = 0; + s.match_length = s.prev_length = MIN_MATCH$1 - 1; + s.match_available = 0; + s.ins_h = 0; + } + + class DeflateState { + constructor() { + this.strm = null; /* pointer back to this zlib stream */ + this.status = 0; /* as the name implies */ + this.pending_buf = null; /* output still pending */ + this.pending_buf_size = 0; /* size of pending_buf */ + this.pending_out = 0; /* next pending byte to output to the stream */ + this.pending = 0; /* nb of bytes in the pending buffer */ + this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ + this.gzhead = null; /* gzip header information to write */ + this.gzindex = 0; /* where in extra, name, or comment */ + this.method = Z_DEFLATED; /* can only be DEFLATED */ + this.last_flush = -1; /* value of flush param for previous deflate call */ + + this.w_size = 0; /* LZ77 window size (32K by default) */ + this.w_bits = 0; /* log2(w_size) (8..16) */ + this.w_mask = 0; /* w_size - 1 */ + + this.window = null; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. + */ + + this.window_size = 0; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + this.prev = null; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + this.head = null; /* Heads of the hash chains or NIL. */ + + this.ins_h = 0; /* hash index of string to be inserted */ + this.hash_size = 0; /* number of elements in hash table */ + this.hash_bits = 0; /* log2(hash_size) */ + this.hash_mask = 0; /* hash_size-1 */ + + this.hash_shift = 0; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + this.block_start = 0; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + this.match_length = 0; /* length of best match */ + this.prev_match = 0; /* previous match */ + this.match_available = 0; /* set if previous match exists */ + this.strstart = 0; /* start of string to insert */ + this.match_start = 0; /* start of matching string */ + this.lookahead = 0; /* number of valid bytes ahead in window */ + + this.prev_length = 0; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + this.max_chain_length = 0; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + this.max_lazy_match = 0; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ + // That's alias to max_lazy_match, don't use directly + //this.max_insert_length = 0; + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + this.level = 0; /* compression level (1..9) */ + this.strategy = 0; /* favor or force Huffman coding*/ + + this.good_match = 0; + /* Use a faster search when the previous match is longer than this */ + + this.nice_match = 0; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + + /* Didn't use ct_data typedef below to suppress compiler warning */ + + // struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + // struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + // struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + // Use flat array of DOUBLE size, with interleaved fata, + // because JS does not support effective + this.dyn_ltree = new Buf16(HEAP_SIZE$1 * 2); + this.dyn_dtree = new Buf16((2 * D_CODES$1 + 1) * 2); + this.bl_tree = new Buf16((2 * BL_CODES$1 + 1) * 2); + zero$2(this.dyn_ltree); + zero$2(this.dyn_dtree); + zero$2(this.bl_tree); + + this.l_desc = null; /* desc. for literal tree */ + this.d_desc = null; /* desc. for distance tree */ + this.bl_desc = null; /* desc. for bit length tree */ + + //ush bl_count[MAX_BITS+1]; + this.bl_count = new Buf16(MAX_BITS$1 + 1); + /* number of codes at each bit length for an optimal tree */ + + //int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + this.heap = new Buf16(2 * L_CODES$1 + 1); /* heap used to build the Huffman trees */ + zero$2(this.heap); + + this.heap_len = 0; /* number of elements in the heap */ + this.heap_max = 0; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + this.depth = new Buf16(2 * L_CODES$1 + 1); //uch depth[2*L_CODES+1]; + zero$2(this.depth); + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + this.l_buf = 0; /* buffer index for literals or lengths */ + + this.lit_bufsize = 0; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + this.last_lit = 0; /* running index in l_buf */ + + this.d_buf = 0; + /* Buffer index for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + this.opt_len = 0; /* bit length of current block with optimal trees */ + this.static_len = 0; /* bit length of current block with static trees */ + this.matches = 0; /* number of string matches in current block */ + this.insert = 0; /* bytes at end of window left to insert */ + + + this.bi_buf = 0; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + this.bi_valid = 0; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + + // Used for window memory init. We safely ignore it for JS. That makes + // sense only for pointers and memory check tools. + //this.high_water = 0; + /* High water mark offset in window for initialized bytes -- bytes above + * this are set to zero in order to avoid memory check warnings when + * longest match routines access bytes past the input. This is then + * updated to the new high water mark. + */ + } + } + + function deflateResetKeep(strm) { + let s; + + if (!strm || !strm.state) { + return err(strm, Z_STREAM_ERROR); + } + + strm.total_in = strm.total_out = 0; + strm.data_type = Z_UNKNOWN; + + s = strm.state; + s.pending = 0; + s.pending_out = 0; + + if (s.wrap < 0) { + s.wrap = -s.wrap; + /* was made negative by deflate(..., Z_FINISH); */ + } + s.status = (s.wrap ? INIT_STATE : BUSY_STATE); + strm.adler = (s.wrap === 2) ? + 0 // crc32(0, Z_NULL, 0) + : + 1; // adler32(0, Z_NULL, 0) + s.last_flush = Z_NO_FLUSH; + _tr_init(s); + return Z_OK; + } + + + function deflateReset(strm) { + const ret = deflateResetKeep(strm); + if (ret === Z_OK) { + lm_init(strm.state); + } + return ret; + } + + + function deflateSetHeader(strm, head) { + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + if (strm.state.wrap !== 2) { return Z_STREAM_ERROR; } + strm.state.gzhead = head; + return Z_OK; + } + + + function deflateInit2(strm, level, method, windowBits, memLevel, strategy) { + if (!strm) { // === Z_NULL + return Z_STREAM_ERROR; + } + let wrap = 1; + + if (level === Z_DEFAULT_COMPRESSION) { + level = 6; + } + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } + + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } + + + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method !== Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_FIXED) { + return err(strm, Z_STREAM_ERROR); + } + + + if (windowBits === 8) { + windowBits = 9; + } + /* until 256-byte window bug fixed */ + + const s = new DeflateState(); + + strm.state = s; + s.strm = strm; + + s.wrap = wrap; + s.gzhead = null; + s.w_bits = windowBits; + s.w_size = 1 << s.w_bits; + s.w_mask = s.w_size - 1; + + s.hash_bits = memLevel + 7; + s.hash_size = 1 << s.hash_bits; + s.hash_mask = s.hash_size - 1; + s.hash_shift = ~~((s.hash_bits + MIN_MATCH$1 - 1) / MIN_MATCH$1); + s.window = new Buf8(s.w_size * 2); + s.head = new Buf16(s.hash_size); + s.prev = new Buf16(s.w_size); + + // Don't need mem init magic for JS. + //s.high_water = 0; /* nothing written to s->window yet */ + + s.lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + s.pending_buf_size = s.lit_bufsize * 4; + + //overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + //s->pending_buf = (uchf *) overlay; + s.pending_buf = new Buf8(s.pending_buf_size); + + // It is offset from `s.pending_buf` (size is `s.lit_bufsize * 2`) + //s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s.d_buf = 1 * s.lit_bufsize; + + //s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + s.l_buf = (1 + 2) * s.lit_bufsize; + + s.level = level; + s.strategy = strategy; + s.method = method; + + return deflateReset(strm); + } + + + function deflate(strm, flush) { + let old_flush, s; + let beg, val; // for gzip header write only + + if (!strm || !strm.state || + flush > Z_BLOCK || flush < 0) { + return strm ? err(strm, Z_STREAM_ERROR) : Z_STREAM_ERROR; + } + + s = strm.state; + + if (!strm.output || + (!strm.input && strm.avail_in !== 0) || + (s.status === FINISH_STATE && flush !== Z_FINISH)) { + return err(strm, (strm.avail_out === 0) ? Z_BUF_ERROR : Z_STREAM_ERROR); + } + + s.strm = strm; /* just in case */ + old_flush = s.last_flush; + s.last_flush = flush; + + /* Write the header */ + if (s.status === INIT_STATE) { + + if (s.wrap === 2) { // GZIP header + strm.adler = 0; //crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (!s.gzhead) { // s->gzhead == Z_NULL + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s.level === 9 ? 2 : + (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s.status = BUSY_STATE; + } + else { + put_byte(s, (s.gzhead.text ? 1 : 0) + + (s.gzhead.hcrc ? 2 : 0) + + (!s.gzhead.extra ? 0 : 4) + + (!s.gzhead.name ? 0 : 8) + + (!s.gzhead.comment ? 0 : 16) + ); + put_byte(s, s.gzhead.time & 0xff); + put_byte(s, (s.gzhead.time >> 8) & 0xff); + put_byte(s, (s.gzhead.time >> 16) & 0xff); + put_byte(s, (s.gzhead.time >> 24) & 0xff); + put_byte(s, s.level === 9 ? 2 : + (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? + 4 : 0)); + put_byte(s, s.gzhead.os & 0xff); + if (s.gzhead.extra && s.gzhead.extra.length) { + put_byte(s, s.gzhead.extra.length & 0xff); + put_byte(s, (s.gzhead.extra.length >> 8) & 0xff); + } + if (s.gzhead.hcrc) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending, 0); + } + s.gzindex = 0; + s.status = EXTRA_STATE; + } + } + else // DEFLATE header + { + let header = (Z_DEFLATED + ((s.w_bits - 8) << 4)) << 8; + let level_flags = -1; + + if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) { + level_flags = 0; + } else if (s.level < 6) { + level_flags = 1; + } else if (s.level === 6) { + level_flags = 2; + } else { + level_flags = 3; + } + header |= (level_flags << 6); + if (s.strstart !== 0) { header |= PRESET_DICT; } + header += 31 - (header % 31); + + s.status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s.strstart !== 0) { + putShortMSB(s, strm.adler >>> 16); + putShortMSB(s, strm.adler & 0xffff); + } + strm.adler = 1; // adler32(0L, Z_NULL, 0); + } + } + + //#ifdef GZIP + if (s.status === EXTRA_STATE) { + if (s.gzhead.extra/* != Z_NULL*/) { + beg = s.pending; /* start of bytes to update crc */ + + while (s.gzindex < (s.gzhead.extra.length & 0xffff)) { + if (s.pending === s.pending_buf_size) { + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + flush_pending(strm); + beg = s.pending; + if (s.pending === s.pending_buf_size) { + break; + } + } + put_byte(s, s.gzhead.extra[s.gzindex] & 0xff); + s.gzindex++; + } + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + if (s.gzindex === s.gzhead.extra.length) { + s.gzindex = 0; + s.status = NAME_STATE; + } + } + else { + s.status = NAME_STATE; + } + } + if (s.status === NAME_STATE) { + if (s.gzhead.name/* != Z_NULL*/) { + beg = s.pending; /* start of bytes to update crc */ + //int val; + + do { + if (s.pending === s.pending_buf_size) { + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + flush_pending(strm); + beg = s.pending; + if (s.pending === s.pending_buf_size) { + val = 1; + break; + } + } + // JS specific: little magic to add zero terminator to end of string + if (s.gzindex < s.gzhead.name.length) { + val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff; + } else { + val = 0; + } + put_byte(s, val); + } while (val !== 0); + + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + if (val === 0) { + s.gzindex = 0; + s.status = COMMENT_STATE; + } + } + else { + s.status = COMMENT_STATE; + } + } + if (s.status === COMMENT_STATE) { + if (s.gzhead.comment/* != Z_NULL*/) { + beg = s.pending; /* start of bytes to update crc */ + //int val; + + do { + if (s.pending === s.pending_buf_size) { + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + flush_pending(strm); + beg = s.pending; + if (s.pending === s.pending_buf_size) { + val = 1; + break; + } + } + // JS specific: little magic to add zero terminator to end of string + if (s.gzindex < s.gzhead.comment.length) { + val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff; + } else { + val = 0; + } + put_byte(s, val); + } while (val !== 0); + + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + if (val === 0) { + s.status = HCRC_STATE; + } + } + else { + s.status = HCRC_STATE; + } + } + if (s.status === HCRC_STATE) { + if (s.gzhead.hcrc) { + if (s.pending + 2 > s.pending_buf_size) { + flush_pending(strm); + } + if (s.pending + 2 <= s.pending_buf_size) { + put_byte(s, strm.adler & 0xff); + put_byte(s, (strm.adler >> 8) & 0xff); + strm.adler = 0; //crc32(0L, Z_NULL, 0); + s.status = BUSY_STATE; + } + } + else { + s.status = BUSY_STATE; + } + } + //#endif + + /* Flush as much pending output as possible */ + if (s.pending !== 0) { + flush_pending(strm); + if (strm.avail_out === 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s.last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) && + flush !== Z_FINISH) { + return err(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s.status === FINISH_STATE && strm.avail_in !== 0) { + return err(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm.avail_in !== 0 || s.lookahead !== 0 || + (flush !== Z_NO_FLUSH && s.status !== FINISH_STATE)) { + var bstate = (s.strategy === Z_HUFFMAN_ONLY) ? deflate_huff(s, flush) : + (s.strategy === Z_RLE ? deflate_rle(s, flush) : + configuration_table[s.level].func(s, flush)); + + if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) { + s.status = FINISH_STATE; + } + if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) { + if (strm.avail_out === 0) { + s.last_flush = -1; + /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate === BS_BLOCK_DONE) { + if (flush === Z_PARTIAL_FLUSH) { + _tr_align(s); + } + else if (flush !== Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ + + _tr_stored_block(s, 0, 0, false); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush === Z_FULL_FLUSH) { + /*** CLEAR_HASH(s); ***/ /* forget history */ + zero$2(s.head); // Fill with NIL (= 0); + + if (s.lookahead === 0) { + s.strstart = 0; + s.block_start = 0; + s.insert = 0; + } + } + } + flush_pending(strm); + if (strm.avail_out === 0) { + s.last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + //Assert(strm->avail_out > 0, "bug2"); + //if (strm.avail_out <= 0) { throw new Error("bug2");} + + if (flush !== Z_FINISH) { return Z_OK; } + if (s.wrap <= 0) { return Z_STREAM_END; } + + /* Write the trailer */ + if (s.wrap === 2) { + put_byte(s, strm.adler & 0xff); + put_byte(s, (strm.adler >> 8) & 0xff); + put_byte(s, (strm.adler >> 16) & 0xff); + put_byte(s, (strm.adler >> 24) & 0xff); + put_byte(s, strm.total_in & 0xff); + put_byte(s, (strm.total_in >> 8) & 0xff); + put_byte(s, (strm.total_in >> 16) & 0xff); + put_byte(s, (strm.total_in >> 24) & 0xff); + } + else { + putShortMSB(s, strm.adler >>> 16); + putShortMSB(s, strm.adler & 0xffff); + } + + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s.wrap > 0) { s.wrap = -s.wrap; } + /* write the trailer only once! */ + return s.pending !== 0 ? Z_OK : Z_STREAM_END; + } + + function deflateEnd(strm) { + let status; + + if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) { + return Z_STREAM_ERROR; + } + + status = strm.state.status; + if (status !== INIT_STATE && + status !== EXTRA_STATE && + status !== NAME_STATE && + status !== COMMENT_STATE && + status !== HCRC_STATE && + status !== BUSY_STATE && + status !== FINISH_STATE + ) { + return err(strm, Z_STREAM_ERROR); + } + + strm.state = null; + + return status === BUSY_STATE ? err(strm, Z_DATA_ERROR) : Z_OK; + } + + + /* ========================================================================= + * Initializes the compression dictionary from the given byte + * sequence without producing any compressed output. + */ + function deflateSetDictionary(strm, dictionary) { + let dictLength = dictionary.length; + + let s; + let str, n; + let wrap; + let avail; + let next; + let input; + let tmpDict; + + if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) { + return Z_STREAM_ERROR; + } + + s = strm.state; + wrap = s.wrap; + + if (wrap === 2 || (wrap === 1 && s.status !== INIT_STATE) || s.lookahead) { + return Z_STREAM_ERROR; + } + + /* when using zlib wrappers, compute Adler-32 for provided dictionary */ + if (wrap === 1) { + /* adler32(strm->adler, dictionary, dictLength); */ + strm.adler = adler32(strm.adler, dictionary, dictLength, 0); + } + + s.wrap = 0; /* avoid computing Adler-32 in read_buf */ + + /* if dictionary would fill window, just replace the history */ + if (dictLength >= s.w_size) { + if (wrap === 0) { /* already empty otherwise */ + /*** CLEAR_HASH(s); ***/ + zero$2(s.head); // Fill with NIL (= 0); + s.strstart = 0; + s.block_start = 0; + s.insert = 0; + } + /* use the tail */ + // dictionary = dictionary.slice(dictLength - s.w_size); + tmpDict = new Buf8(s.w_size); + arraySet(tmpDict, dictionary, dictLength - s.w_size, s.w_size, 0); + dictionary = tmpDict; + dictLength = s.w_size; + } + /* insert dictionary into window and hash */ + avail = strm.avail_in; + next = strm.next_in; + input = strm.input; + strm.avail_in = dictLength; + strm.next_in = 0; + strm.input = dictionary; + fill_window(s); + while (s.lookahead >= MIN_MATCH$1) { + str = s.strstart; + n = s.lookahead - (MIN_MATCH$1 - 1); + do { + /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH$1 - 1]) & s.hash_mask; + + s.prev[str & s.w_mask] = s.head[s.ins_h]; + + s.head[s.ins_h] = str; + str++; + } while (--n); + s.strstart = str; + s.lookahead = MIN_MATCH$1 - 1; + fill_window(s); + } + s.strstart += s.lookahead; + s.block_start = s.strstart; + s.insert = s.lookahead; + s.lookahead = 0; + s.match_length = s.prev_length = MIN_MATCH$1 - 1; + s.match_available = 0; + strm.next_in = next; + strm.input = input; + strm.avail_in = avail; + s.wrap = wrap; + return Z_OK; + } + + /* Not implemented + exports.deflateBound = deflateBound; + exports.deflateCopy = deflateCopy; + exports.deflateParams = deflateParams; + exports.deflatePending = deflatePending; + exports.deflatePrime = deflatePrime; + exports.deflateTune = deflateTune; + */ + + // String encode/decode helpers + + try { + String.fromCharCode.apply(null, [ 0 ]); + } catch (__) { + } + try { + String.fromCharCode.apply(null, new Uint8Array(1)); + } catch (__) { + } + + + // Table with utf8 lengths (calculated by first byte of sequence) + // Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS, + // because max possible codepoint is 0x10ffff + const _utf8len = new Buf8(256); + for (let q = 0; q < 256; q++) { + _utf8len[q] = q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1; + } + _utf8len[254] = _utf8len[254] = 1; // Invalid sequence start + + + // convert string to array (typed, when possible) + function string2buf (str) { + let c, c2, m_pos, i, buf_len = 0; + const str_len = str.length; + + // count binary size + for (m_pos = 0; m_pos < str_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && m_pos + 1 < str_len) { + c2 = str.charCodeAt(m_pos + 1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + (c - 0xd800 << 10) + (c2 - 0xdc00); + m_pos++; + } + } + buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4; + } + + // allocate buffer + const buf = new Buf8(buf_len); + + // convert + for (i = 0, m_pos = 0; i < buf_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && m_pos + 1 < str_len) { + c2 = str.charCodeAt(m_pos + 1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + (c - 0xd800 << 10) + (c2 - 0xdc00); + m_pos++; + } + } + if (c < 0x80) { + /* one byte */ + buf[i++] = c; + } else if (c < 0x800) { + /* two bytes */ + buf[i++] = 0xC0 | c >>> 6; + buf[i++] = 0x80 | c & 0x3f; + } else if (c < 0x10000) { + /* three bytes */ + buf[i++] = 0xE0 | c >>> 12; + buf[i++] = 0x80 | c >>> 6 & 0x3f; + buf[i++] = 0x80 | c & 0x3f; + } else { + /* four bytes */ + buf[i++] = 0xf0 | c >>> 18; + buf[i++] = 0x80 | c >>> 12 & 0x3f; + buf[i++] = 0x80 | c >>> 6 & 0x3f; + buf[i++] = 0x80 | c & 0x3f; + } + } + + return buf; + } + + + // Convert binary string (typed, when possible) + function binstring2buf (str) { + const buf = new Buf8(str.length); + for (let i = 0, len = buf.length; i < len; i++) { + buf[i] = str.charCodeAt(i); + } + return buf; + } + + // (C) 1995-2013 Jean-loup Gailly and Mark Adler + // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin + // + // This software is provided 'as-is', without any express or implied + // warranty. In no event will the authors be held liable for any damages + // arising from the use of this software. + // + // Permission is granted to anyone to use this software for any purpose, + // including commercial applications, and to alter it and redistribute it + // freely, subject to the following restrictions: + // + // 1. The origin of this software must not be misrepresented; you must not + // claim that you wrote the original software. If you use this software + // in a product, an acknowledgment in the product documentation would be + // appreciated but is not required. + // 2. Altered source versions must be plainly marked as such, and must not be + // misrepresented as being the original software. + // 3. This notice may not be removed or altered from any source distribution. + + class ZStream { + constructor() { + /* next input byte */ + this.input = null; // JS specific, because we have no pointers + this.next_in = 0; + /* number of bytes available at input */ + this.avail_in = 0; + /* total number of input bytes read so far */ + this.total_in = 0; + /* next output byte should be put there */ + this.output = null; // JS specific, because we have no pointers + this.next_out = 0; + /* remaining free space at output */ + this.avail_out = 0; + /* total number of bytes output so far */ + this.total_out = 0; + /* last error message, NULL if no error */ + this.msg = ''/*Z_NULL*/; + /* not visible by applications */ + this.state = null; + /* best guess about the data type: binary or text */ + this.data_type = 2/*Z_UNKNOWN*/; + /* adler32 value of the uncompressed data */ + this.adler = 0; + } + } + + /* ===========================================================================*/ + + + /** + * class Deflate + * + * Generic JS-style wrapper for zlib calls. If you don't need + * streaming behaviour - use more simple functions: [[deflate]], + * [[deflateRaw]] and [[gzip]]. + **/ + + /* internal + * Deflate.chunks -> Array + * + * Chunks of output data, if [[Deflate#onData]] not overridden. + **/ + + /** + * Deflate.result -> Uint8Array|Array + * + * Compressed result, generated by default [[Deflate#onData]] + * and [[Deflate#onEnd]] handlers. Filled after you push last chunk + * (call [[Deflate#push]] with `Z_FINISH` / `true` param) or if you + * push a chunk with explicit flush (call [[Deflate#push]] with + * `Z_SYNC_FLUSH` param). + **/ + + /** + * Deflate.err -> Number + * + * Error code after deflate finished. 0 (Z_OK) on success. + * You will not need it in real life, because deflate errors + * are possible only on wrong options or bad `onData` / `onEnd` + * custom handlers. + **/ + + /** + * Deflate.msg -> String + * + * Error message, if [[Deflate.err]] != 0 + **/ + + + /** + * new Deflate(options) + * - options (Object): zlib deflate options. + * + * Creates new deflator instance with specified params. Throws exception + * on bad params. Supported options: + * + * - `level` + * - `windowBits` + * - `memLevel` + * - `strategy` + * - `dictionary` + * + * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) + * for more information on these. + * + * Additional options, for internal needs: + * + * - `chunkSize` - size of generated data chunks (16K by default) + * - `raw` (Boolean) - do raw deflate + * - `gzip` (Boolean) - create gzip wrapper + * - `to` (String) - if equal to 'string', then result will be "binary string" + * (each char code [0..255]) + * - `header` (Object) - custom header for gzip + * - `text` (Boolean) - true if compressed data believed to be text + * - `time` (Number) - modification time, unix timestamp + * - `os` (Number) - operation system code + * - `extra` (Array) - array of bytes with extra data (max 65536) + * - `name` (String) - file name (binary string) + * - `comment` (String) - comment (binary string) + * - `hcrc` (Boolean) - true if header crc should be added + * + * ##### Example: + * + * ```javascript + * var pako = void('pako') + * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9]) + * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]); + * + * var deflate = new pako.Deflate({ level: 3}); + * + * deflate.push(chunk1, false); + * deflate.push(chunk2, true); // true -> last chunk + * + * if (deflate.err) { throw new Error(deflate.err); } + * + * console.log(deflate.result); + * ``` + **/ + + class Deflate { + constructor(options) { + this.options = { + level: Z_DEFAULT_COMPRESSION, + method: Z_DEFLATED, + chunkSize: 16384, + windowBits: 15, + memLevel: 8, + strategy: Z_DEFAULT_STRATEGY, + ...(options || {}) + }; + + const opt = this.options; + + if (opt.raw && (opt.windowBits > 0)) { + opt.windowBits = -opt.windowBits; + } + + else if (opt.gzip && (opt.windowBits > 0) && (opt.windowBits < 16)) { + opt.windowBits += 16; + } + + this.err = 0; // error code, if happens (0 = Z_OK) + this.msg = ''; // error message + this.ended = false; // used to avoid multiple onEnd() calls + this.chunks = []; // chunks of compressed data + + this.strm = new ZStream(); + this.strm.avail_out = 0; + + var status = deflateInit2( + this.strm, + opt.level, + opt.method, + opt.windowBits, + opt.memLevel, + opt.strategy + ); + + if (status !== Z_OK) { + throw new Error(msg[status]); + } + + if (opt.header) { + deflateSetHeader(this.strm, opt.header); + } + + if (opt.dictionary) { + let dict; + // Convert data if needed + if (typeof opt.dictionary === 'string') { + // If we need to compress text, change encoding to utf8. + dict = string2buf(opt.dictionary); + } else if (opt.dictionary instanceof ArrayBuffer) { + dict = new Uint8Array(opt.dictionary); + } else { + dict = opt.dictionary; + } + + status = deflateSetDictionary(this.strm, dict); + + if (status !== Z_OK) { + throw new Error(msg[status]); + } + + this._dict_set = true; + } + } + + /** + * Deflate#push(data[, mode]) -> Boolean + * - data (Uint8Array|Array|ArrayBuffer|String): input data. Strings will be + * converted to utf8 byte sequence. + * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. + * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH. + * + * Sends input data to deflate pipe, generating [[Deflate#onData]] calls with + * new compressed chunks. Returns `true` on success. The last data block must have + * mode Z_FINISH (or `true`). That will flush internal pending buffers and call + * [[Deflate#onEnd]]. For interim explicit flushes (without ending the stream) you + * can use mode Z_SYNC_FLUSH, keeping the compression context. + * + * On fail call [[Deflate#onEnd]] with error code and return false. + * + * We strongly recommend to use `Uint8Array` on input for best speed (output + * array format is detected automatically). Also, don't skip last param and always + * use the same type in your code (boolean or number). That will improve JS speed. + * + * For regular `Array`-s make sure all elements are [0..255]. + * + * ##### Example + * + * ```javascript + * push(chunk, false); // push one of data chunks + * ... + * push(chunk, true); // push last chunk + * ``` + **/ + push(data, mode) { + const { strm, options: { chunkSize } } = this; + var status, _mode; + + if (this.ended) { return false; } + + _mode = (mode === ~~mode) ? mode : ((mode === true) ? Z_FINISH : Z_NO_FLUSH); + + // Convert data if needed + if (typeof data === 'string') { + // If we need to compress text, change encoding to utf8. + strm.input = string2buf(data); + } else if (data instanceof ArrayBuffer) { + strm.input = new Uint8Array(data); + } else { + strm.input = data; + } + + strm.next_in = 0; + strm.avail_in = strm.input.length; + + do { + if (strm.avail_out === 0) { + strm.output = new Buf8(chunkSize); + strm.next_out = 0; + strm.avail_out = chunkSize; + } + status = deflate(strm, _mode); /* no bad return value */ + + if (status !== Z_STREAM_END && status !== Z_OK) { + this.onEnd(status); + this.ended = true; + return false; + } + if (strm.avail_out === 0 || (strm.avail_in === 0 && (_mode === Z_FINISH || _mode === Z_SYNC_FLUSH))) { + this.onData(shrinkBuf(strm.output, strm.next_out)); + } + } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== Z_STREAM_END); + + // Finalize on the last chunk. + if (_mode === Z_FINISH) { + status = deflateEnd(this.strm); + this.onEnd(status); + this.ended = true; + return status === Z_OK; + } + + // callback interim results if Z_SYNC_FLUSH. + if (_mode === Z_SYNC_FLUSH) { + this.onEnd(Z_OK); + strm.avail_out = 0; + return true; + } + + return true; + }; + /** + * Deflate#onData(chunk) -> Void + * - chunk (Uint8Array|Array|String): output data. Type of array depends + * on js engine support. When string output requested, each chunk + * will be string. + * + * By default, stores data blocks in `chunks[]` property and glue + * those in `onEnd`. Override this handler, if you need another behaviour. + **/ + onData(chunk) { + this.chunks.push(chunk); + }; + + /** + * Deflate#onEnd(status) -> Void + * - status (Number): deflate status. 0 (Z_OK) on success, + * other if not. + * + * Called once after you tell deflate that the input stream is + * complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH) + * or if an error happened. By default - join collected chunks, + * free memory and fill `results` / `err` properties. + **/ + onEnd(status) { + // On success - join + if (status === Z_OK) { + this.result = flattenChunks(this.chunks); + } + this.chunks = []; + this.err = status; + this.msg = this.strm.msg; + }; + } + + // (C) 1995-2013 Jean-loup Gailly and Mark Adler + // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin + // + // This software is provided 'as-is', without any express or implied + // warranty. In no event will the authors be held liable for any damages + // arising from the use of this software. + // + // Permission is granted to anyone to use this software for any purpose, + // including commercial applications, and to alter it and redistribute it + // freely, subject to the following restrictions: + // + // 1. The origin of this software must not be misrepresented; you must not + // claim that you wrote the original software. If you use this software + // in a product, an acknowledgment in the product documentation would be + // appreciated but is not required. + // 2. Altered source versions must be plainly marked as such, and must not be + // misrepresented as being the original software. + // 3. This notice may not be removed or altered from any source distribution. + + // See state defs from inflate.js + const BAD = 30; /* got a data error -- remain here until reset */ + const TYPE = 12; /* i: waiting for type bits, including last-flag bit */ + + /* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state.mode === LEN + strm.avail_in >= 6 + strm.avail_out >= 258 + start >= strm.avail_out + state.bits < 8 + + On return, state.mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm.avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm.avail_out >= 258 for each loop to avoid checking for + output space. + */ + function inflate_fast(strm, start) { + let _in; /* local strm.input */ + let _out; /* local strm.output */ + // Use `s_window` instead `window`, avoid conflict with instrumentation tools + let hold; /* local strm.hold */ + let bits; /* local strm.bits */ + let here; /* retrieved table entry */ + let op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + let len; /* match length, unused bytes */ + let dist; /* match distance */ + let from; /* where to copy match from */ + let from_source; + + + + /* copy state to local variables */ + const state = strm.state; + //here = state.here; + _in = strm.next_in; + const input = strm.input; + const last = _in + (strm.avail_in - 5); + _out = strm.next_out; + const output = strm.output; + const beg = _out - (start - strm.avail_out); + const end = _out + (strm.avail_out - 257); + //#ifdef INFLATE_STRICT + const dmax = state.dmax; + //#endif + const wsize = state.wsize; + const whave = state.whave; + const wnext = state.wnext; + const s_window = state.window; + hold = state.hold; + bits = state.bits; + const lcode = state.lencode; + const dcode = state.distcode; + const lmask = (1 << state.lenbits) - 1; + const dmask = (1 << state.distbits) - 1; + + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + + top: + do { + if (bits < 15) { + hold += input[_in++] << bits; + bits += 8; + hold += input[_in++] << bits; + bits += 8; + } + + here = lcode[hold & lmask]; + + dolen: + for (;;) { // Goto emulation + op = here >>> 24/*here.bits*/; + hold >>>= op; + bits -= op; + op = here >>> 16 & 0xff/*here.op*/; + if (op === 0) { /* literal */ + //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + // "inflate: literal '%c'\n" : + // "inflate: literal 0x%02x\n", here.val)); + output[_out++] = here & 0xffff/*here.val*/; + } else if (op & 16) { /* length base */ + len = here & 0xffff/*here.val*/; + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + } + len += hold & (1 << op) - 1; + hold >>>= op; + bits -= op; + } + //Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += input[_in++] << bits; + bits += 8; + hold += input[_in++] << bits; + bits += 8; + } + here = dcode[hold & dmask]; + + dodist: + for (;;) { // goto emulation + op = here >>> 24/*here.bits*/; + hold >>>= op; + bits -= op; + op = here >>> 16 & 0xff/*here.op*/; + + if (op & 16) { /* distance base */ + dist = here & 0xffff/*here.val*/; + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + } + } + dist += hold & (1 << op) - 1; + //#ifdef INFLATE_STRICT + if (dist > dmax) { + strm.msg = "invalid distance too far back"; + state.mode = BAD; + break top; + } + //#endif + hold >>>= op; + bits -= op; + //Tracevv((stderr, "inflate: distance %u\n", dist)); + op = _out - beg; /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state.sane) { + strm.msg = "invalid distance too far back"; + state.mode = BAD; + break top; + } + + // (!) This block is disabled in zlib defaults, + // don't enable it for binary compatibility + //#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + // if (len <= op - whave) { + // do { + // output[_out++] = 0; + // } while (--len); + // continue top; + // } + // len -= op - whave; + // do { + // output[_out++] = 0; + // } while (--op > whave); + // if (op === 0) { + // from = _out - dist; + // do { + // output[_out++] = output[from++]; + // } while (--len); + // continue top; + // } + //#endif + } + from = 0; // window index + from_source = s_window; + if (wnext === 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } else if (wnext < op) { /* wrap around window */ + from += wsize + wnext - op; + op -= wnext; + if (op < len) { /* some from end of window */ + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = 0; + if (wnext < len) { /* some from start of window */ + op = wnext; + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } + } else { /* contiguous in window */ + from += wnext - op; + if (op < len) { /* some from window */ + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } + while (len > 2) { + output[_out++] = from_source[from++]; + output[_out++] = from_source[from++]; + output[_out++] = from_source[from++]; + len -= 3; + } + if (len) { + output[_out++] = from_source[from++]; + if (len > 1) { + output[_out++] = from_source[from++]; + } + } + } else { + from = _out - dist; /* copy direct from output */ + do { /* minimum length is three */ + output[_out++] = output[from++]; + output[_out++] = output[from++]; + output[_out++] = output[from++]; + len -= 3; + } while (len > 2); + if (len) { + output[_out++] = output[from++]; + if (len > 1) { + output[_out++] = output[from++]; + } + } + } + } else if ((op & 64) === 0) { /* 2nd level distance code */ + here = dcode[(here & 0xffff)/*here.val*/ + (hold & (1 << op) - 1)]; + continue dodist; + } else { + strm.msg = "invalid distance code"; + state.mode = BAD; + break top; + } + + break; // need to emulate goto via "continue" + } + } else if ((op & 64) === 0) { /* 2nd level length code */ + here = lcode[(here & 0xffff)/*here.val*/ + (hold & (1 << op) - 1)]; + continue dolen; + } else if (op & 32) { /* end-of-block */ + //Tracevv((stderr, "inflate: end of block\n")); + state.mode = TYPE; + break top; + } else { + strm.msg = "invalid literal/length code"; + state.mode = BAD; + break top; + } + + break; // need to emulate goto via "continue" + } + } while (_in < last && _out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + _in -= len; + bits -= len << 3; + hold &= (1 << bits) - 1; + + /* update state and return */ + strm.next_in = _in; + strm.next_out = _out; + strm.avail_in = _in < last ? 5 + (last - _in) : 5 - (_in - last); + strm.avail_out = _out < end ? 257 + (end - _out) : 257 - (_out - end); + state.hold = hold; + state.bits = bits; + return; + } + + const MAXBITS = 15; + const ENOUGH_LENS = 852; + const ENOUGH_DISTS = 592; + //var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); + + const CODES = 0; + const LENS = 1; + const DISTS = 2; + + const lbase = [ /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 + ]; + + const lext = [ /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78 + ]; + + const dbase = [ /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0 + ]; + + const dext = [ /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64 + ]; + + function inflate_table(type, lens, lens_index, codes, table, table_index, work, opts) { + const bits = opts.bits; + //here = opts.here; /* table entry for duplication */ + + let len = 0; /* a code's length in bits */ + let sym = 0; /* index of code symbols */ + let min = 0, max = 0; /* minimum and maximum code lengths */ + let root = 0; /* number of index bits for root table */ + let curr = 0; /* number of index bits for current table */ + let drop = 0; /* code bits to drop for sub-table */ + let left = 0; /* number of prefix codes available */ + let used = 0; /* code entries in table used */ + let huff = 0; /* Huffman code */ + let incr; /* for incrementing code, index */ + let fill; /* index for replicating entries */ + let low; /* low bits for current root entry */ + let next; /* next available space in table */ + let base = null; /* base value table to use */ + let base_index = 0; + // var shoextra; /* extra bits table to use */ + let end; /* use base and extra for symbol > end */ + const count = new Buf16(MAXBITS + 1); //[MAXBITS+1]; /* number of codes of each length */ + const offs = new Buf16(MAXBITS + 1); //[MAXBITS+1]; /* offsets in table for each length */ + let extra = null; + let extra_index = 0; + + let here_bits, here_op, here_val; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) { + count[len] = 0; + } + for (sym = 0; sym < codes; sym++) { + count[lens[lens_index + sym]]++; + } + + /* bound code lengths, force root to be within code lengths */ + root = bits; + for (max = MAXBITS; max >= 1; max--) { + if (count[max] !== 0) { + break; + } + } + if (root > max) { + root = max; + } + if (max === 0) { /* no symbols to code at all */ + //table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */ + //table.bits[opts.table_index] = 1; //here.bits = (var char)1; + //table.val[opts.table_index++] = 0; //here.val = (var short)0; + table[table_index++] = 1 << 24 | 64 << 16 | 0; + + + //table.op[opts.table_index] = 64; + //table.bits[opts.table_index] = 1; + //table.val[opts.table_index++] = 0; + table[table_index++] = 1 << 24 | 64 << 16 | 0; + + opts.bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min < max; min++) { + if (count[min] !== 0) { + break; + } + } + if (root < min) { + root = min; + } + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) { + return -1; + } /* over-subscribed */ + } + if (left > 0 && (type === CODES || max !== 1)) { + return -1; /* incomplete set */ + } + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) { + offs[len + 1] = offs[len] + count[len]; + } + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) { + if (lens[lens_index + sym] !== 0) { + work[offs[lens[lens_index + sym]]++] = sym; + } + } + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftrees.h + for more information. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + // poor man optimization - use if-else instead of switch, + // to avoid deopts in old v8 + if (type === CODES) { + base = extra = work; /* dummy value--not used */ + end = 19; + + } else if (type === LENS) { + base = lbase; + base_index -= 257; + extra = lext; + extra_index -= 257; + end = 256; + + } else { /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize opts for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = table_index; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = -1; /* trigger new sub-table when len > root */ + used = 1 << root; /* use root table entries */ + const mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if (type === LENS && used > ENOUGH_LENS || + type === DISTS && used > ENOUGH_DISTS) { + return 1; + } + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + here_bits = len - drop; + if (work[sym] < end) { + here_op = 0; + here_val = work[sym]; + } else if (work[sym] > end) { + here_op = extra[extra_index + work[sym]]; + here_val = base[base_index + work[sym]]; + } else { + here_op = 32 + 64; /* end of block */ + here_val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1 << len - drop; + fill = 1 << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + table[next + (huff >> drop) + fill] = here_bits << 24 | here_op << 16 | here_val |0; + } while (fill !== 0); + + /* backwards increment the len-bit code huff */ + incr = 1 << len - 1; + while (huff & incr) { + incr >>= 1; + } + if (incr !== 0) { + huff &= incr - 1; + huff += incr; + } else { + huff = 0; + } + + /* go to next symbol, update count, len */ + sym++; + if (--count[len] === 0) { + if (len === max) { + break; + } + len = lens[lens_index + work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) !== low) { + /* if first time, transition to sub-tables */ + if (drop === 0) { + drop = root; + } + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = 1 << curr; + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) { + break; + } + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1 << curr; + if (type === LENS && used > ENOUGH_LENS || + type === DISTS && used > ENOUGH_DISTS) { + return 1; + } + + /* point entry in root table to sub-table */ + low = huff & mask; + /*table.op[low] = curr; + table.bits[low] = root; + table.val[low] = next - opts.table_index;*/ + table[low] = root << 24 | curr << 16 | next - table_index |0; + } + } + + /* fill in remaining table entry if code is incomplete (guaranteed to have + at most one remaining entry, since if the code is incomplete, the + maximum code length that was allowed to get this far is one bit) */ + if (huff !== 0) { + //table.op[next + huff] = 64; /* invalid code marker */ + //table.bits[next + huff] = len - drop; + //table.val[next + huff] = 0; + table[next + huff] = len - drop << 24 | 64 << 16 |0; + } + + /* set return parameters */ + //opts.table_index += used; + opts.bits = root; + return 0; + } + + const CODES$1 = 0; + const LENS$1 = 1; + const DISTS$1 = 2; + + /* STATES ====================================================================*/ + /* ===========================================================================*/ + + + const HEAD = 1; /* i: waiting for magic header */ + const FLAGS = 2; /* i: waiting for method and flags (gzip) */ + const TIME = 3; /* i: waiting for modification time (gzip) */ + const OS = 4; /* i: waiting for extra flags and operating system (gzip) */ + const EXLEN = 5; /* i: waiting for extra length (gzip) */ + const EXTRA = 6; /* i: waiting for extra bytes (gzip) */ + const NAME = 7; /* i: waiting for end of file name (gzip) */ + const COMMENT = 8; /* i: waiting for end of comment (gzip) */ + const HCRC = 9; /* i: waiting for header crc (gzip) */ + const DICTID = 10; /* i: waiting for dictionary check value */ + const DICT = 11; /* waiting for inflateSetDictionary() call */ + const TYPE$1 = 12; /* i: waiting for type bits, including last-flag bit */ + const TYPEDO = 13; /* i: same, but skip check to exit inflate on new block */ + const STORED = 14; /* i: waiting for stored size (length and complement) */ + const COPY_ = 15; /* i/o: same as COPY below, but only first time in */ + const COPY = 16; /* i/o: waiting for input or output to copy stored block */ + const TABLE = 17; /* i: waiting for dynamic block table lengths */ + const LENLENS = 18; /* i: waiting for code length code lengths */ + const CODELENS = 19; /* i: waiting for length/lit and distance code lengths */ + const LEN_ = 20; /* i: same as LEN below, but only first time in */ + const LEN = 21; /* i: waiting for length/lit/eob code */ + const LENEXT = 22; /* i: waiting for length extra bits */ + const DIST = 23; /* i: waiting for distance code */ + const DISTEXT = 24; /* i: waiting for distance extra bits */ + const MATCH = 25; /* o: waiting for output space to copy string */ + const LIT = 26; /* o: waiting for output space to write literal */ + const CHECK = 27; /* i: waiting for 32-bit check value */ + const LENGTH = 28; /* i: waiting for 32-bit length (gzip) */ + const DONE = 29; /* finished check, done -- remain here until reset */ + const BAD$1 = 30; /* got a data error -- remain here until reset */ + //const MEM = 31; /* got an inflate() memory error -- remain here until reset */ + const SYNC = 32; /* looking for synchronization bytes to restart inflate() */ + + /* ===========================================================================*/ + + + + const ENOUGH_LENS$1 = 852; + const ENOUGH_DISTS$1 = 592; + + + function zswap32(q) { + return (((q >>> 24) & 0xff) + + ((q >>> 8) & 0xff00) + + ((q & 0xff00) << 8) + + ((q & 0xff) << 24)); + } + + + class InflateState { + constructor() { + this.mode = 0; /* current inflate mode */ + this.last = false; /* true if processing last block */ + this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ + this.havedict = false; /* true if dictionary provided */ + this.flags = 0; /* gzip header method and flags (0 if zlib) */ + this.dmax = 0; /* zlib header max distance (INFLATE_STRICT) */ + this.check = 0; /* protected copy of check value */ + this.total = 0; /* protected copy of output count */ + // TODO: may be {} + this.head = null; /* where to save gzip header information */ + + /* sliding window */ + this.wbits = 0; /* log base 2 of requested window size */ + this.wsize = 0; /* window size or zero if not using window */ + this.whave = 0; /* valid bytes in the window */ + this.wnext = 0; /* window write index */ + this.window = null; /* allocated sliding window, if needed */ + + /* bit accumulator */ + this.hold = 0; /* input bit accumulator */ + this.bits = 0; /* number of bits in "in" */ + + /* for string and stored block copying */ + this.length = 0; /* literal or length of data to copy */ + this.offset = 0; /* distance back to copy string from */ + + /* for table and code decoding */ + this.extra = 0; /* extra bits needed */ + + /* fixed and dynamic code tables */ + this.lencode = null; /* starting table for length/literal codes */ + this.distcode = null; /* starting table for distance codes */ + this.lenbits = 0; /* index bits for lencode */ + this.distbits = 0; /* index bits for distcode */ + + /* dynamic table building */ + this.ncode = 0; /* number of code length code lengths */ + this.nlen = 0; /* number of length code lengths */ + this.ndist = 0; /* number of distance code lengths */ + this.have = 0; /* number of code lengths in lens[] */ + this.next = null; /* next available space in codes[] */ + + this.lens = new Buf16(320); /* temporary storage for code lengths */ + this.work = new Buf16(288); /* work area for code table building */ + + /* + because we don't have pointers in js, we use lencode and distcode directly + as buffers so we don't need codes + */ + //this.codes = new utils.Buf32(ENOUGH); /* space for code tables */ + this.lendyn = null; /* dynamic table for length/literal codes (JS specific) */ + this.distdyn = null; /* dynamic table for distance codes (JS specific) */ + this.sane = 0; /* if false, allow invalid distance too far */ + this.back = 0; /* bits back of last unprocessed length/lit */ + this.was = 0; /* initial length of match */ + } + } + + function inflateResetKeep(strm) { + let state; + + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + strm.total_in = strm.total_out = state.total = 0; + strm.msg = ''; /*Z_NULL*/ + if (state.wrap) { /* to support ill-conceived Java test suite */ + strm.adler = state.wrap & 1; + } + state.mode = HEAD; + state.last = 0; + state.havedict = 0; + state.dmax = 32768; + state.head = null/*Z_NULL*/; + state.hold = 0; + state.bits = 0; + //state.lencode = state.distcode = state.next = state.codes; + state.lencode = state.lendyn = new Buf32(ENOUGH_LENS$1); + state.distcode = state.distdyn = new Buf32(ENOUGH_DISTS$1); + + state.sane = 1; + state.back = -1; + //Tracev((stderr, "inflate: reset\n")); + return Z_OK; + } + + function inflateReset(strm) { + let state; + + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + state.wsize = 0; + state.whave = 0; + state.wnext = 0; + return inflateResetKeep(strm); + + } + + function inflateReset2(strm, windowBits) { + let wrap; + let state; + + /* get the state */ + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } + else { + wrap = (windowBits >> 4) + 1; + if (windowBits < 48) { + windowBits &= 15; + } + } + + /* set number of window bits, free window if different */ + if (windowBits && (windowBits < 8 || windowBits > 15)) { + return Z_STREAM_ERROR; + } + if (state.window !== null && state.wbits !== windowBits) { + state.window = null; + } + + /* update state and reset the rest of it */ + state.wrap = wrap; + state.wbits = windowBits; + return inflateReset(strm); + } + + function inflateInit2(strm, windowBits) { + let ret; + let state; + + if (!strm) { return Z_STREAM_ERROR; } + //strm.msg = Z_NULL; /* in case we return an error */ + + state = new InflateState(); + + //if (state === Z_NULL) return Z_MEM_ERROR; + //Tracev((stderr, "inflate: allocated\n")); + strm.state = state; + state.window = null/*Z_NULL*/; + ret = inflateReset2(strm, windowBits); + if (ret !== Z_OK) { + strm.state = null/*Z_NULL*/; + } + return ret; + } + + + /* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ + let virgin = true; + + let lenfix, distfix; // We have no pointers in JS, so keep tables separate + + function fixedtables(state) { + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + let sym; + + lenfix = new Buf32(512); + distfix = new Buf32(32); + + /* literal/length table */ + sym = 0; + while (sym < 144) { state.lens[sym++] = 8; } + while (sym < 256) { state.lens[sym++] = 9; } + while (sym < 280) { state.lens[sym++] = 7; } + while (sym < 288) { state.lens[sym++] = 8; } + + inflate_table(LENS$1, state.lens, 0, 288, lenfix, 0, state.work, { bits: 9 }); + + /* distance table */ + sym = 0; + while (sym < 32) { state.lens[sym++] = 5; } + + inflate_table(DISTS$1, state.lens, 0, 32, distfix, 0, state.work, { bits: 5 }); + + /* do this just once */ + virgin = false; + } + + state.lencode = lenfix; + state.lenbits = 9; + state.distcode = distfix; + state.distbits = 5; + } + + + /* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ + function updatewindow(strm, src, end, copy) { + let dist; + const state = strm.state; + + /* if it hasn't been done already, allocate space for the window */ + if (state.window === null) { + state.wsize = 1 << state.wbits; + state.wnext = 0; + state.whave = 0; + + state.window = new Buf8(state.wsize); + } + + /* copy state->wsize or less output bytes into the circular window */ + if (copy >= state.wsize) { + arraySet(state.window, src, end - state.wsize, state.wsize, 0); + state.wnext = 0; + state.whave = state.wsize; + } + else { + dist = state.wsize - state.wnext; + if (dist > copy) { + dist = copy; + } + //zmemcpy(state->window + state->wnext, end - copy, dist); + arraySet(state.window, src, end - copy, dist, state.wnext); + copy -= dist; + if (copy) { + //zmemcpy(state->window, end - copy, copy); + arraySet(state.window, src, end - copy, copy, 0); + state.wnext = copy; + state.whave = state.wsize; + } + else { + state.wnext += dist; + if (state.wnext === state.wsize) { state.wnext = 0; } + if (state.whave < state.wsize) { state.whave += dist; } + } + } + return 0; + } + + function inflate(strm, flush) { + let state; + let input, output; // input/output buffers + let next; /* next input INDEX */ + let put; /* next output INDEX */ + let have, left; /* available input and output */ + let hold; /* bit buffer */ + let bits; /* bits in bit buffer */ + let _in, _out; /* save starting available input and output */ + let copy; /* number of stored or match bytes to copy */ + let from; /* where to copy match bytes from */ + let from_source; + let here = 0; /* current decoding table entry */ + let here_bits, here_op, here_val; // paked "here" denormalized (JS specific) + //var last; /* parent table entry */ + let last_bits, last_op, last_val; // paked "last" denormalized (JS specific) + let len; /* length to copy for repeats, bits to drop */ + let ret; /* return code */ + let hbuf = new Buf8(4); /* buffer for gzip header crc calculation */ + let opts; + + let n; // temporary var for NEED_BITS + + const order = /* permutation of code lengths */ + [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ]; + + + if (!strm || !strm.state || !strm.output || + (!strm.input && strm.avail_in !== 0)) { + return Z_STREAM_ERROR; + } + + state = strm.state; + if (state.mode === TYPE$1) { state.mode = TYPEDO; } /* skip check */ + + + //--- LOAD() --- + put = strm.next_out; + output = strm.output; + left = strm.avail_out; + next = strm.next_in; + input = strm.input; + have = strm.avail_in; + hold = state.hold; + bits = state.bits; + //--- + + _in = have; + _out = left; + ret = Z_OK; + + inf_leave: // goto emulation + for (;;) { + switch (state.mode) { + case HEAD: + if (state.wrap === 0) { + state.mode = TYPEDO; + break; + } + //=== NEEDBITS(16); + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if ((state.wrap & 2) && hold === 0x8b1f) { /* gzip header */ + state.check = 0/*crc32(0L, Z_NULL, 0)*/; + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = FLAGS; + break; + } + state.flags = 0; /* expect zlib header */ + if (state.head) { + state.head.done = false; + } + if (!(state.wrap & 1) || /* check if zlib header allowed */ + (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) { + strm.msg = 'incorrect header check'; + state.mode = BAD$1; + break; + } + if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) { + strm.msg = 'unknown compression method'; + state.mode = BAD$1; + break; + } + //--- DROPBITS(4) ---// + hold >>>= 4; + bits -= 4; + //---// + len = (hold & 0x0f)/*BITS(4)*/ + 8; + if (state.wbits === 0) { + state.wbits = len; + } + else if (len > state.wbits) { + strm.msg = 'invalid window size'; + state.mode = BAD$1; + break; + } + state.dmax = 1 << len; + //Tracev((stderr, "inflate: zlib header ok\n")); + strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; + state.mode = hold & 0x200 ? DICTID : TYPE$1; + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + break; + case FLAGS: + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.flags = hold; + if ((state.flags & 0xff) !== Z_DEFLATED) { + strm.msg = 'unknown compression method'; + state.mode = BAD$1; + break; + } + if (state.flags & 0xe000) { + strm.msg = 'unknown header flags set'; + state.mode = BAD$1; + break; + } + if (state.head) { + state.head.text = ((hold >> 8) & 1); + } + if (state.flags & 0x0200) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = TIME; + /* falls through */ + case TIME: + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (state.head) { + state.head.time = hold; + } + if (state.flags & 0x0200) { + //=== CRC4(state.check, hold) + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + hbuf[2] = (hold >>> 16) & 0xff; + hbuf[3] = (hold >>> 24) & 0xff; + state.check = crc32(state.check, hbuf, 4, 0); + //=== + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = OS; + /* falls through */ + case OS: + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (state.head) { + state.head.xflags = (hold & 0xff); + state.head.os = (hold >> 8); + } + if (state.flags & 0x0200) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = EXLEN; + /* falls through */ + case EXLEN: + if (state.flags & 0x0400) { + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.length = hold; + if (state.head) { + state.head.extra_len = hold; + } + if (state.flags & 0x0200) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + } + else if (state.head) { + state.head.extra = null/*Z_NULL*/; + } + state.mode = EXTRA; + /* falls through */ + case EXTRA: + if (state.flags & 0x0400) { + copy = state.length; + if (copy > have) { copy = have; } + if (copy) { + if (state.head) { + len = state.head.extra_len - state.length; + if (!state.head.extra) { + // Use untyped array for more convenient processing later + state.head.extra = new Array(state.head.extra_len); + } + arraySet( + state.head.extra, + input, + next, + // extra field is limited to 65536 bytes + // - no need for additional size check + copy, + /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/ + len + ); + //zmemcpy(state.head.extra + len, next, + // len + copy > state.head.extra_max ? + // state.head.extra_max - len : copy); + } + if (state.flags & 0x0200) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + state.length -= copy; + } + if (state.length) { break inf_leave; } + } + state.length = 0; + state.mode = NAME; + /* falls through */ + case NAME: + if (state.flags & 0x0800) { + if (have === 0) { break inf_leave; } + copy = 0; + do { + // TODO: 2 or 1 bytes? + len = input[next + copy++]; + /* use constant limit because in js we should not preallocate memory */ + if (state.head && len && + (state.length < 65536 /*state.head.name_max*/)) { + state.head.name += String.fromCharCode(len); + } + } while (len && copy < have); + + if (state.flags & 0x0200) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + if (len) { break inf_leave; } + } + else if (state.head) { + state.head.name = null; + } + state.length = 0; + state.mode = COMMENT; + /* falls through */ + case COMMENT: + if (state.flags & 0x1000) { + if (have === 0) { break inf_leave; } + copy = 0; + do { + len = input[next + copy++]; + /* use constant limit because in js we should not preallocate memory */ + if (state.head && len && + (state.length < 65536 /*state.head.comm_max*/)) { + state.head.comment += String.fromCharCode(len); + } + } while (len && copy < have); + if (state.flags & 0x0200) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + if (len) { break inf_leave; } + } + else if (state.head) { + state.head.comment = null; + } + state.mode = HCRC; + /* falls through */ + case HCRC: + if (state.flags & 0x0200) { + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (hold !== (state.check & 0xffff)) { + strm.msg = 'header crc mismatch'; + state.mode = BAD$1; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + } + if (state.head) { + state.head.hcrc = ((state.flags >> 9) & 1); + state.head.done = true; + } + strm.adler = state.check = 0; + state.mode = TYPE$1; + break; + case DICTID: + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + strm.adler = state.check = zswap32(hold); + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = DICT; + /* falls through */ + case DICT: + if (state.havedict === 0) { + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + return Z_NEED_DICT; + } + strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; + state.mode = TYPE$1; + /* falls through */ + case TYPE$1: + if (flush === Z_BLOCK || flush === Z_TREES) { break inf_leave; } + /* falls through */ + case TYPEDO: + if (state.last) { + //--- BYTEBITS() ---// + hold >>>= bits & 7; + bits -= bits & 7; + //---// + state.mode = CHECK; + break; + } + //=== NEEDBITS(3); */ + while (bits < 3) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.last = (hold & 0x01)/*BITS(1)*/; + //--- DROPBITS(1) ---// + hold >>>= 1; + bits -= 1; + //---// + + switch ((hold & 0x03)/*BITS(2)*/) { + case 0: /* stored block */ + //Tracev((stderr, "inflate: stored block%s\n", + // state.last ? " (last)" : "")); + state.mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + //Tracev((stderr, "inflate: fixed codes block%s\n", + // state.last ? " (last)" : "")); + state.mode = LEN_; /* decode codes */ + if (flush === Z_TREES) { + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + break inf_leave; + } + break; + case 2: /* dynamic block */ + //Tracev((stderr, "inflate: dynamic codes block%s\n", + // state.last ? " (last)" : "")); + state.mode = TABLE; + break; + case 3: + strm.msg = 'invalid block type'; + state.mode = BAD$1; + } + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + break; + case STORED: + //--- BYTEBITS() ---// /* go to byte boundary */ + hold >>>= bits & 7; + bits -= bits & 7; + //---// + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) { + strm.msg = 'invalid stored block lengths'; + state.mode = BAD$1; + break; + } + state.length = hold & 0xffff; + //Tracev((stderr, "inflate: stored length %u\n", + // state.length)); + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = COPY_; + if (flush === Z_TREES) { break inf_leave; } + /* falls through */ + case COPY_: + state.mode = COPY; + /* falls through */ + case COPY: + copy = state.length; + if (copy) { + if (copy > have) { copy = have; } + if (copy > left) { copy = left; } + if (copy === 0) { break inf_leave; } + //--- zmemcpy(put, next, copy); --- + arraySet(output, input, next, copy, put); + //---// + have -= copy; + next += copy; + left -= copy; + put += copy; + state.length -= copy; + break; + } + //Tracev((stderr, "inflate: stored end\n")); + state.mode = TYPE$1; + break; + case TABLE: + //=== NEEDBITS(14); */ + while (bits < 14) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257; + //--- DROPBITS(5) ---// + hold >>>= 5; + bits -= 5; + //---// + state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1; + //--- DROPBITS(5) ---// + hold >>>= 5; + bits -= 5; + //---// + state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4; + //--- DROPBITS(4) ---// + hold >>>= 4; + bits -= 4; + //---// + //#ifndef PKZIP_BUG_WORKAROUND + if (state.nlen > 286 || state.ndist > 30) { + strm.msg = 'too many length or distance symbols'; + state.mode = BAD$1; + break; + } + //#endif + //Tracev((stderr, "inflate: table sizes ok\n")); + state.have = 0; + state.mode = LENLENS; + /* falls through */ + case LENLENS: + while (state.have < state.ncode) { + //=== NEEDBITS(3); + while (bits < 3) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.lens[order[state.have++]] = (hold & 0x07);//BITS(3); + //--- DROPBITS(3) ---// + hold >>>= 3; + bits -= 3; + //---// + } + while (state.have < 19) { + state.lens[order[state.have++]] = 0; + } + // We have separate tables & no pointers. 2 commented lines below not needed. + //state.next = state.codes; + //state.lencode = state.next; + // Switch to use dynamic table + state.lencode = state.lendyn; + state.lenbits = 7; + + opts = { bits: state.lenbits }; + ret = inflate_table(CODES$1, state.lens, 0, 19, state.lencode, 0, state.work, opts); + state.lenbits = opts.bits; + + if (ret) { + strm.msg = 'invalid code lengths set'; + state.mode = BAD$1; + break; + } + //Tracev((stderr, "inflate: code lengths ok\n")); + state.have = 0; + state.mode = CODELENS; + /* falls through */ + case CODELENS: + while (state.have < state.nlen + state.ndist) { + for (;;) { + here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if (here_val < 16) { + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.lens[state.have++] = here_val; + } + else { + if (here_val === 16) { + //=== NEEDBITS(here.bits + 2); + n = here_bits + 2; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + if (state.have === 0) { + strm.msg = 'invalid bit length repeat'; + state.mode = BAD$1; + break; + } + len = state.lens[state.have - 1]; + copy = 3 + (hold & 0x03);//BITS(2); + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + } + else if (here_val === 17) { + //=== NEEDBITS(here.bits + 3); + n = here_bits + 3; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + len = 0; + copy = 3 + (hold & 0x07);//BITS(3); + //--- DROPBITS(3) ---// + hold >>>= 3; + bits -= 3; + //---// + } + else { + //=== NEEDBITS(here.bits + 7); + n = here_bits + 7; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + len = 0; + copy = 11 + (hold & 0x7f);//BITS(7); + //--- DROPBITS(7) ---// + hold >>>= 7; + bits -= 7; + //---// + } + if (state.have + copy > state.nlen + state.ndist) { + strm.msg = 'invalid bit length repeat'; + state.mode = BAD$1; + break; + } + while (copy--) { + state.lens[state.have++] = len; + } + } + } + + /* handle error breaks in while */ + if (state.mode === BAD$1) { break; } + + /* check for end-of-block code (better have one) */ + if (state.lens[256] === 0) { + strm.msg = 'invalid code -- missing end-of-block'; + state.mode = BAD$1; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state.lenbits = 9; + + opts = { bits: state.lenbits }; + ret = inflate_table(LENS$1, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts); + // We have separate tables & no pointers. 2 commented lines below not needed. + // state.next_index = opts.table_index; + state.lenbits = opts.bits; + // state.lencode = state.next; + + if (ret) { + strm.msg = 'invalid literal/lengths set'; + state.mode = BAD$1; + break; + } + + state.distbits = 6; + //state.distcode.copy(state.codes); + // Switch to use dynamic table + state.distcode = state.distdyn; + opts = { bits: state.distbits }; + ret = inflate_table(DISTS$1, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts); + // We have separate tables & no pointers. 2 commented lines below not needed. + // state.next_index = opts.table_index; + state.distbits = opts.bits; + // state.distcode = state.next; + + if (ret) { + strm.msg = 'invalid distances set'; + state.mode = BAD$1; + break; + } + //Tracev((stderr, 'inflate: codes ok\n')); + state.mode = LEN_; + if (flush === Z_TREES) { break inf_leave; } + /* falls through */ + case LEN_: + state.mode = LEN; + /* falls through */ + case LEN: + if (have >= 6 && left >= 258) { + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + inflate_fast(strm, _out); + //--- LOAD() --- + put = strm.next_out; + output = strm.output; + left = strm.avail_out; + next = strm.next_in; + input = strm.input; + have = strm.avail_in; + hold = state.hold; + bits = state.bits; + //--- + + if (state.mode === TYPE$1) { + state.back = -1; + } + break; + } + state.back = 0; + for (;;) { + here = state.lencode[hold & ((1 << state.lenbits) - 1)]; /*BITS(state.lenbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if (here_bits <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if (here_op && (here_op & 0xf0) === 0) { + last_bits = here_bits; + last_op = here_op; + last_val = here_val; + for (;;) { + here = state.lencode[last_val + + ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((last_bits + here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + //--- DROPBITS(last.bits) ---// + hold >>>= last_bits; + bits -= last_bits; + //---// + state.back += last_bits; + } + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.back += here_bits; + state.length = here_val; + if (here_op === 0) { + //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + // "inflate: literal '%c'\n" : + // "inflate: literal 0x%02x\n", here.val)); + state.mode = LIT; + break; + } + if (here_op & 32) { + //Tracevv((stderr, "inflate: end of block\n")); + state.back = -1; + state.mode = TYPE$1; + break; + } + if (here_op & 64) { + strm.msg = 'invalid literal/length code'; + state.mode = BAD$1; + break; + } + state.extra = here_op & 15; + state.mode = LENEXT; + /* falls through */ + case LENEXT: + if (state.extra) { + //=== NEEDBITS(state.extra); + n = state.extra; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.length += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; + //--- DROPBITS(state.extra) ---// + hold >>>= state.extra; + bits -= state.extra; + //---// + state.back += state.extra; + } + //Tracevv((stderr, "inflate: length %u\n", state.length)); + state.was = state.length; + state.mode = DIST; + /* falls through */ + case DIST: + for (;;) { + here = state.distcode[hold & ((1 << state.distbits) - 1)];/*BITS(state.distbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if ((here_op & 0xf0) === 0) { + last_bits = here_bits; + last_op = here_op; + last_val = here_val; + for (;;) { + here = state.distcode[last_val + + ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((last_bits + here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + //--- DROPBITS(last.bits) ---// + hold >>>= last_bits; + bits -= last_bits; + //---// + state.back += last_bits; + } + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.back += here_bits; + if (here_op & 64) { + strm.msg = 'invalid distance code'; + state.mode = BAD$1; + break; + } + state.offset = here_val; + state.extra = (here_op) & 15; + state.mode = DISTEXT; + /* falls through */ + case DISTEXT: + if (state.extra) { + //=== NEEDBITS(state.extra); + n = state.extra; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.offset += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; + //--- DROPBITS(state.extra) ---// + hold >>>= state.extra; + bits -= state.extra; + //---// + state.back += state.extra; + } + //#ifdef INFLATE_STRICT + if (state.offset > state.dmax) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD$1; + break; + } + //#endif + //Tracevv((stderr, "inflate: distance %u\n", state.offset)); + state.mode = MATCH; + /* falls through */ + case MATCH: + if (left === 0) { break inf_leave; } + copy = _out - left; + if (state.offset > copy) { /* copy from window */ + copy = state.offset - copy; + if (copy > state.whave) { + if (state.sane) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD$1; + break; + } + // (!) This block is disabled in zlib defaults, + // don't enable it for binary compatibility + //#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + // Trace((stderr, "inflate.c too far\n")); + // copy -= state.whave; + // if (copy > state.length) { copy = state.length; } + // if (copy > left) { copy = left; } + // left -= copy; + // state.length -= copy; + // do { + // output[put++] = 0; + // } while (--copy); + // if (state.length === 0) { state.mode = LEN; } + // break; + //#endif + } + if (copy > state.wnext) { + copy -= state.wnext; + from = state.wsize - copy; + } + else { + from = state.wnext - copy; + } + if (copy > state.length) { copy = state.length; } + from_source = state.window; + } + else { /* copy from output */ + from_source = output; + from = put - state.offset; + copy = state.length; + } + if (copy > left) { copy = left; } + left -= copy; + state.length -= copy; + do { + output[put++] = from_source[from++]; + } while (--copy); + if (state.length === 0) { state.mode = LEN; } + break; + case LIT: + if (left === 0) { break inf_leave; } + output[put++] = state.length; + left--; + state.mode = LEN; + break; + case CHECK: + if (state.wrap) { + //=== NEEDBITS(32); + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + // Use '|' instead of '+' to make sure that result is signed + hold |= input[next++] << bits; + bits += 8; + } + //===// + _out -= left; + strm.total_out += _out; + state.total += _out; + if (_out) { + strm.adler = state.check = + /*UPDATE(state.check, put - _out, _out);*/ + (state.flags ? crc32(state.check, output, _out, put - _out) : adler32(state.check, output, _out, put - _out)); + + } + _out = left; + // NB: crc32 stored as signed 32-bit int, zswap32 returns signed too + if ((state.flags ? hold : zswap32(hold)) !== state.check) { + strm.msg = 'incorrect data check'; + state.mode = BAD$1; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + //Tracev((stderr, "inflate: check matches trailer\n")); + } + state.mode = LENGTH; + /* falls through */ + case LENGTH: + if (state.wrap && state.flags) { + //=== NEEDBITS(32); + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (hold !== (state.total & 0xffffffff)) { + strm.msg = 'incorrect length check'; + state.mode = BAD$1; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + //Tracev((stderr, "inflate: length matches trailer\n")); + } + state.mode = DONE; + /* falls through */ + case DONE: + ret = Z_STREAM_END; + break inf_leave; + case BAD$1: + ret = Z_DATA_ERROR; + break inf_leave; + // case MEM: + // return Z_MEM_ERROR; + case SYNC: + /* falls through */ + default: + return Z_STREAM_ERROR; + } + } + + // inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave" + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + + if (state.wsize || (_out !== strm.avail_out && state.mode < BAD$1 && + (state.mode < CHECK || flush !== Z_FINISH))) { + if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) ; + } + _in -= strm.avail_in; + _out -= strm.avail_out; + strm.total_in += _in; + strm.total_out += _out; + state.total += _out; + if (state.wrap && _out) { + strm.adler = state.check = /*UPDATE(state.check, strm.next_out - _out, _out);*/ + (state.flags ? crc32(state.check, output, _out, strm.next_out - _out) : adler32(state.check, output, _out, strm.next_out - _out)); + } + strm.data_type = state.bits + (state.last ? 64 : 0) + + (state.mode === TYPE$1 ? 128 : 0) + + (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0); + if (((_in === 0 && _out === 0) || flush === Z_FINISH) && ret === Z_OK) { + ret = Z_BUF_ERROR; + } + return ret; + } + + function inflateEnd(strm) { + + if (!strm || !strm.state /*|| strm->zfree == (free_func)0*/) { + return Z_STREAM_ERROR; + } + + const state = strm.state; + if (state.window) { + state.window = null; + } + strm.state = null; + return Z_OK; + } + + function inflateGetHeader(strm, head) { + let state; + + /* check state */ + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR; } + + /* save header structure */ + state.head = head; + head.done = false; + return Z_OK; + } + + function inflateSetDictionary(strm, dictionary) { + const dictLength = dictionary.length; + + let state; + let dictid; + + /* check state */ + if (!strm /* == Z_NULL */ || !strm.state /* == Z_NULL */) { return Z_STREAM_ERROR; } + state = strm.state; + + if (state.wrap !== 0 && state.mode !== DICT) { + return Z_STREAM_ERROR; + } + + /* check for correct dictionary identifier */ + if (state.mode === DICT) { + dictid = 1; /* adler32(0, null, 0)*/ + /* dictid = adler32(dictid, dictionary, dictLength); */ + dictid = adler32(dictid, dictionary, dictLength, 0); + if (dictid !== state.check) { + return Z_DATA_ERROR; + } + } + /* copy dictionary to window using updatewindow(), which will amend the + existing dictionary if appropriate */ + updatewindow(strm, dictionary, dictLength, dictLength); + // if (ret) { + // state.mode = MEM; + // return Z_MEM_ERROR; + // } + state.havedict = 1; + // Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; + } + + /* Not implemented + exports.inflateCopy = inflateCopy; + exports.inflateGetDictionary = inflateGetDictionary; + exports.inflateMark = inflateMark; + exports.inflatePrime = inflatePrime; + exports.inflateSync = inflateSync; + exports.inflateSyncPoint = inflateSyncPoint; + exports.inflateUndermine = inflateUndermine; + */ + + // (C) 1995-2013 Jean-loup Gailly and Mark Adler + // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin + // + // This software is provided 'as-is', without any express or implied + // warranty. In no event will the authors be held liable for any damages + // arising from the use of this software. + // + // Permission is granted to anyone to use this software for any purpose, + // including commercial applications, and to alter it and redistribute it + // freely, subject to the following restrictions: + // + // 1. The origin of this software must not be misrepresented; you must not + // claim that you wrote the original software. If you use this software + // in a product, an acknowledgment in the product documentation would be + // appreciated but is not required. + // 2. Altered source versions must be plainly marked as such, and must not be + // misrepresented as being the original software. + // 3. This notice may not be removed or altered from any source distribution. + + class GZheader { + constructor() { + /* true if compressed data believed to be text */ + this.text = 0; + /* modification time */ + this.time = 0; + /* extra flags (not used when writing a gzip file) */ + this.xflags = 0; + /* operating system */ + this.os = 0; + /* pointer to extra field or Z_NULL if none */ + this.extra = null; + /* extra field length (valid if extra != Z_NULL) */ + this.extra_len = 0; // Actually, we don't need it in JS, + // but leave for few code modifications + + // + // Setup limits is not necessary because in js we should not preallocate memory + // for inflate use constant limit in 65536 bytes + // + + /* space at extra (only when reading header) */ + // this.extra_max = 0; + /* pointer to zero-terminated file name or Z_NULL */ + this.name = ''; + /* space at name (only when reading header) */ + // this.name_max = 0; + /* pointer to zero-terminated comment or Z_NULL */ + this.comment = ''; + /* space at comment (only when reading header) */ + // this.comm_max = 0; + /* true if there was or will be a header crc */ + this.hcrc = 0; + /* true when done reading gzip header (not used when writing a gzip file) */ + this.done = false; + } + } + + /** + * class Inflate + * + * Generic JS-style wrapper for zlib calls. If you don't need + * streaming behaviour - use more simple functions: [[inflate]] + * and [[inflateRaw]]. + **/ + + /* internal + * inflate.chunks -> Array + * + * Chunks of output data, if [[Inflate#onData]] not overridden. + **/ + + /** + * Inflate.result -> Uint8Array|Array|String + * + * Uncompressed result, generated by default [[Inflate#onData]] + * and [[Inflate#onEnd]] handlers. Filled after you push last chunk + * (call [[Inflate#push]] with `Z_FINISH` / `true` param) or if you + * push a chunk with explicit flush (call [[Inflate#push]] with + * `Z_SYNC_FLUSH` param). + **/ + + /** + * Inflate.err -> Number + * + * Error code after inflate finished. 0 (Z_OK) on success. + * Should be checked if broken data possible. + **/ + + /** + * Inflate.msg -> String + * + * Error message, if [[Inflate.err]] != 0 + **/ + + + /** + * new Inflate(options) + * - options (Object): zlib inflate options. + * + * Creates new inflator instance with specified params. Throws exception + * on bad params. Supported options: + * + * - `windowBits` + * - `dictionary` + * + * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) + * for more information on these. + * + * Additional options, for internal needs: + * + * - `chunkSize` - size of generated data chunks (16K by default) + * - `raw` (Boolean) - do raw inflate + * - `to` (String) - if equal to 'string', then result will be converted + * from utf8 to utf16 (javascript) string. When string output requested, + * chunk length can differ from `chunkSize`, depending on content. + * + * By default, when no options set, autodetect deflate/gzip data format via + * wrapper header. + * + * ##### Example: + * + * ```javascript + * var pako = void('pako') + * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9]) + * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]); + * + * var inflate = new pako.Inflate({ level: 3}); + * + * inflate.push(chunk1, false); + * inflate.push(chunk2, true); // true -> last chunk + * + * if (inflate.err) { throw new Error(inflate.err); } + * + * console.log(inflate.result); + * ``` + **/ + class Inflate { + constructor(options) { + this.options = { + chunkSize: 16384, + windowBits: 0, + ...(options || {}) + }; + + const opt = this.options; + + // Force window size for `raw` data, if not set directly, + // because we have no header for autodetect. + if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) { + opt.windowBits = -opt.windowBits; + if (opt.windowBits === 0) { opt.windowBits = -15; } + } + + // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate + if ((opt.windowBits >= 0) && (opt.windowBits < 16) && + !(options && options.windowBits)) { + opt.windowBits += 32; + } + + // Gzip header has no info about windows size, we can do autodetect only + // for deflate. So, if window size not set, force it to max when gzip possible + if ((opt.windowBits > 15) && (opt.windowBits < 48)) { + // bit 3 (16) -> gzipped data + // bit 4 (32) -> autodetect gzip/deflate + if ((opt.windowBits & 15) === 0) { + opt.windowBits |= 15; + } + } + + this.err = 0; // error code, if happens (0 = Z_OK) + this.msg = ''; // error message + this.ended = false; // used to avoid multiple onEnd() calls + this.chunks = []; // chunks of compressed data + + this.strm = new ZStream(); + this.strm.avail_out = 0; + + let status = inflateInit2( + this.strm, + opt.windowBits + ); + + if (status !== Z_OK) { + throw new Error(msg[status]); + } + + this.header = new GZheader(); + + inflateGetHeader(this.strm, this.header); + + // Setup dictionary + if (opt.dictionary) { + // Convert data if needed + if (typeof opt.dictionary === 'string') { + opt.dictionary = string2buf(opt.dictionary); + } else if (opt.dictionary instanceof ArrayBuffer) { + opt.dictionary = new Uint8Array(opt.dictionary); + } + if (opt.raw) { //In raw mode we need to set the dictionary early + status = inflateSetDictionary(this.strm, opt.dictionary); + if (status !== Z_OK) { + throw new Error(msg[status]); + } + } + } + } + /** + * Inflate#push(data[, mode]) -> Boolean + * - data (Uint8Array|Array|ArrayBuffer|String): input data + * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. + * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH. + * + * Sends input data to inflate pipe, generating [[Inflate#onData]] calls with + * new output chunks. Returns `true` on success. The last data block must have + * mode Z_FINISH (or `true`). That will flush internal pending buffers and call + * [[Inflate#onEnd]]. For interim explicit flushes (without ending the stream) you + * can use mode Z_SYNC_FLUSH, keeping the decompression context. + * + * On fail call [[Inflate#onEnd]] with error code and return false. + * + * We strongly recommend to use `Uint8Array` on input for best speed (output + * format is detected automatically). Also, don't skip last param and always + * use the same type in your code (boolean or number). That will improve JS speed. + * + * For regular `Array`-s make sure all elements are [0..255]. + * + * ##### Example + * + * ```javascript + * push(chunk, false); // push one of data chunks + * ... + * push(chunk, true); // push last chunk + * ``` + **/ + push(data, mode) { + const { strm, options: { chunkSize, dictionary } } = this; + let status, _mode; + + // Flag to properly process Z_BUF_ERROR on testing inflate call + // when we check that all output data was flushed. + let allowBufError = false; + + if (this.ended) { return false; } + _mode = (mode === ~~mode) ? mode : ((mode === true) ? Z_FINISH : Z_NO_FLUSH); + + // Convert data if needed + if (typeof data === 'string') { + // Only binary strings can be decompressed on practice + strm.input = binstring2buf(data); + } else if (data instanceof ArrayBuffer) { + strm.input = new Uint8Array(data); + } else { + strm.input = data; + } + + strm.next_in = 0; + strm.avail_in = strm.input.length; + + do { + if (strm.avail_out === 0) { + strm.output = new Buf8(chunkSize); + strm.next_out = 0; + strm.avail_out = chunkSize; + } + + status = inflate(strm, Z_NO_FLUSH); /* no bad return value */ + + if (status === Z_NEED_DICT && dictionary) { + status = inflateSetDictionary(this.strm, dictionary); + } + + if (status === Z_BUF_ERROR && allowBufError === true) { + status = Z_OK; + allowBufError = false; + } + + if (status !== Z_STREAM_END && status !== Z_OK) { + this.onEnd(status); + this.ended = true; + return false; + } + + if (strm.next_out) { + if (strm.avail_out === 0 || status === Z_STREAM_END || (strm.avail_in === 0 && (_mode === Z_FINISH || _mode === Z_SYNC_FLUSH))) { + this.onData(shrinkBuf(strm.output, strm.next_out)); + } + } + + // When no more input data, we should check that internal inflate buffers + // are flushed. The only way to do it when avail_out = 0 - run one more + // inflate pass. But if output data not exists, inflate return Z_BUF_ERROR. + // Here we set flag to process this error properly. + // + // NOTE. Deflate does not return error in this case and does not needs such + // logic. + if (strm.avail_in === 0 && strm.avail_out === 0) { + allowBufError = true; + } + + } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== Z_STREAM_END); + + if (status === Z_STREAM_END) { + _mode = Z_FINISH; + } + + // Finalize on the last chunk. + if (_mode === Z_FINISH) { + status = inflateEnd(this.strm); + this.onEnd(status); + this.ended = true; + return status === Z_OK; + } + + // callback interim results if Z_SYNC_FLUSH. + if (_mode === Z_SYNC_FLUSH) { + this.onEnd(Z_OK); + strm.avail_out = 0; + return true; + } + + return true; + }; + + /** + * Inflate#onData(chunk) -> Void + * - chunk (Uint8Array|Array|String): output data. Type of array depends + * on js engine support. When string output requested, each chunk + * will be string. + * + * By default, stores data blocks in `chunks[]` property and glue + * those in `onEnd`. Override this handler, if you need another behaviour. + **/ + onData(chunk) { + this.chunks.push(chunk); + }; + + + + /** + * Inflate#onEnd(status) -> Void + * - status (Number): inflate status. 0 (Z_OK) on success, + * other if not. + * + * Called either after you tell inflate that the input stream is + * complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH) + * or if an error happened. By default - join collected chunks, + * free memory and fill `results` / `err` properties. + **/ + onEnd(status) { + // On success - join + if (status === Z_OK) { + this.result = flattenChunks(this.chunks); + } + this.chunks = []; + this.err = status; + this.msg = this.strm.msg; + }; + } + + /* + node-bzip - a pure-javascript Node.JS module for decoding bzip2 data + + Copyright (C) 2012 Eli Skeggs + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see + http://www.gnu.org/licenses/lgpl-2.1.html + + Adapted from bzip2.js, copyright 2011 antimatter15 (antimatter15@gmail.com). + + Based on micro-bunzip by Rob Landley (rob@landley.net). + + Based on bzip2 decompression code by Julian R Seward (jseward@acm.org), + which also acknowledges contributions by Mike Burrows, David Wheeler, + Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten, + Robert Sedgewick, and Jon L. Bentley. + */ + + var BITMASK = [0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF]; + + // offset in bytes + var BitReader = function(stream) { + this.stream = stream; + this.bitOffset = 0; + this.curByte = 0; + this.hasByte = false; + }; + + BitReader.prototype._ensureByte = function() { + if (!this.hasByte) { + this.curByte = this.stream.readByte(); + this.hasByte = true; + } + }; + + // reads bits from the buffer + BitReader.prototype.read = function(bits) { + var result = 0; + while (bits > 0) { + this._ensureByte(); + var remaining = 8 - this.bitOffset; + // if we're in a byte + if (bits >= remaining) { + result <<= remaining; + result |= BITMASK[remaining] & this.curByte; + this.hasByte = false; + this.bitOffset = 0; + bits -= remaining; + } else { + result <<= bits; + var shift = remaining - bits; + result |= (this.curByte & (BITMASK[bits] << shift)) >> shift; + this.bitOffset += bits; + bits = 0; + } + } + return result; + }; + + // seek to an arbitrary point in the buffer (expressed in bits) + BitReader.prototype.seek = function(pos) { + var n_bit = pos % 8; + var n_byte = (pos - n_bit) / 8; + this.bitOffset = n_bit; + this.stream.seek(n_byte); + this.hasByte = false; + }; + + // reads 6 bytes worth of data using the read method + BitReader.prototype.pi = function() { + var buf = new Uint8Array(6), i; + for (i = 0; i < buf.length; i++) { + buf[i] = this.read(8); + } + return bufToHex(buf); + }; + + function bufToHex(buf) { + return Array.prototype.map.call(buf, x => ('00' + x.toString(16)).slice(-2)).join(''); + } + + var bitreader = BitReader; + + /* very simple input/output stream interface */ + var Stream = function() { + }; + + // input streams ////////////// + /** Returns the next byte, or -1 for EOF. */ + Stream.prototype.readByte = function() { + throw new Error("abstract method readByte() not implemented"); + }; + /** Attempts to fill the buffer; returns number of bytes read, or + * -1 for EOF. */ + Stream.prototype.read = function(buffer, bufOffset, length) { + var bytesRead = 0; + while (bytesRead < length) { + var c = this.readByte(); + if (c < 0) { // EOF + return (bytesRead===0) ? -1 : bytesRead; + } + buffer[bufOffset++] = c; + bytesRead++; + } + return bytesRead; + }; + Stream.prototype.seek = function(new_pos) { + throw new Error("abstract method seek() not implemented"); + }; + + // output streams /////////// + Stream.prototype.writeByte = function(_byte) { + throw new Error("abstract method readByte() not implemented"); + }; + Stream.prototype.write = function(buffer, bufOffset, length) { + var i; + for (i=0; i>> 0; // return an unsigned value + }; + + /** + * Update the CRC with a single byte + * @param value The value to update the CRC with + */ + this.updateCRC = function(value) { + crc = (crc << 8) ^ crc32Lookup[((crc >>> 24) ^ value) & 0xff]; + }; + + /** + * Update the CRC with a sequence of identical bytes + * @param value The value to update the CRC with + * @param count The number of bytes + */ + this.updateCRCRun = function(value, count) { + while (count-- > 0) { + crc = (crc << 8) ^ crc32Lookup[((crc >>> 24) ^ value) & 0xff]; + } + }; + }; + return CRC32; + })(); + + /* + seek-bzip - a pure-javascript module for seeking within bzip2 data + + Copyright (C) 2013 C. Scott Ananian + Copyright (C) 2012 Eli Skeggs + Copyright (C) 2011 Kevin Kwok + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see + http://www.gnu.org/licenses/lgpl-2.1.html + + Adapted from node-bzip, copyright 2012 Eli Skeggs. + Adapted from bzip2.js, copyright 2011 Kevin Kwok (antimatter15@gmail.com). + + Based on micro-bunzip by Rob Landley (rob@landley.net). + + Based on bzip2 decompression code by Julian R Seward (jseward@acm.org), + which also acknowledges contributions by Mike Burrows, David Wheeler, + Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten, + Robert Sedgewick, and Jon L. Bentley. + */ + + + + + + var MAX_HUFCODE_BITS = 20; + var MAX_SYMBOLS = 258; + var SYMBOL_RUNA = 0; + var SYMBOL_RUNB = 1; + var MIN_GROUPS = 2; + var MAX_GROUPS = 6; + var GROUP_SIZE = 50; + + var WHOLEPI = "314159265359"; + var SQRTPI = "177245385090"; + + var mtf = function(array, index) { + var src = array[index], i; + for (i = index; i > 0; i--) { + array[i] = array[i-1]; + } + array[0] = src; + return src; + }; + + var Err = { + OK: 0, + LAST_BLOCK: -1, + NOT_BZIP_DATA: -2, + UNEXPECTED_INPUT_EOF: -3, + UNEXPECTED_OUTPUT_EOF: -4, + DATA_ERROR: -5, + OUT_OF_MEMORY: -6, + OBSOLETE_INPUT: -7, + END_OF_BLOCK: -8 + }; + var ErrorMessages = {}; + ErrorMessages[Err.LAST_BLOCK] = "Bad file checksum"; + ErrorMessages[Err.NOT_BZIP_DATA] = "Not bzip data"; + ErrorMessages[Err.UNEXPECTED_INPUT_EOF] = "Unexpected input EOF"; + ErrorMessages[Err.UNEXPECTED_OUTPUT_EOF] = "Unexpected output EOF"; + ErrorMessages[Err.DATA_ERROR] = "Data error"; + ErrorMessages[Err.OUT_OF_MEMORY] = "Out of memory"; + ErrorMessages[Err.OBSOLETE_INPUT] = "Obsolete (pre 0.9.5) bzip format not supported."; + + var _throw = function(status, optDetail) { + var msg = ErrorMessages[status] || 'unknown error'; + if (optDetail) { msg += ': '+optDetail; } + var e = new TypeError(msg); + e.errorCode = status; + throw e; + }; + + var Bunzip = function(inputStream, outputStream) { + this.writePos = this.writeCurrent = this.writeCount = 0; + + this._start_bunzip(inputStream, outputStream); + }; + Bunzip.prototype._init_block = function() { + var moreBlocks = this._get_next_block(); + if ( !moreBlocks ) { + this.writeCount = -1; + return false; /* no more blocks */ + } + this.blockCRC = new crc32$1(); + return true; + }; + /* XXX micro-bunzip uses (inputStream, inputBuffer, len) as arguments */ + Bunzip.prototype._start_bunzip = function(inputStream, outputStream) { + /* Ensure that file starts with "BZh['1'-'9']." */ + var buf = new Uint8Array(4); + if (inputStream.read(buf, 0, 4) !== 4 || + String.fromCharCode(buf[0], buf[1], buf[2]) !== 'BZh') + _throw(Err.NOT_BZIP_DATA, 'bad magic'); + + var level = buf[3] - 0x30; + if (level < 1 || level > 9) + _throw(Err.NOT_BZIP_DATA, 'level out of range'); + + this.reader = new bitreader(inputStream); + + /* Fourth byte (ascii '1'-'9'), indicates block size in units of 100k of + uncompressed data. Allocate intermediate buffer for block. */ + this.dbufSize = 100000 * level; + this.nextoutput = 0; + this.outputStream = outputStream; + this.streamCRC = 0; + }; + Bunzip.prototype._get_next_block = function() { + var i, j, k; + var reader = this.reader; + // this is get_next_block() function from micro-bunzip: + /* Read in header signature and CRC, then validate signature. + (last block signature means CRC is for whole file, return now) */ + var h = reader.pi(); + if (h === SQRTPI) { // last block + return false; /* no more blocks */ + } + if (h !== WHOLEPI) + _throw(Err.NOT_BZIP_DATA); + this.targetBlockCRC = reader.read(32) >>> 0; // (convert to unsigned) + this.streamCRC = (this.targetBlockCRC ^ + ((this.streamCRC << 1) | (this.streamCRC>>>31))) >>> 0; + /* We can add support for blockRandomised if anybody complains. There was + some code for this in busybox 1.0.0-pre3, but nobody ever noticed that + it didn't actually work. */ + if (reader.read(1)) + _throw(Err.OBSOLETE_INPUT); + var origPointer = reader.read(24); + if (origPointer > this.dbufSize) + _throw(Err.DATA_ERROR, 'initial position out of bounds'); + /* mapping table: if some byte values are never used (encoding things + like ascii text), the compression code removes the gaps to have fewer + symbols to deal with, and writes a sparse bitfield indicating which + values were present. We make a translation table to convert the symbols + back to the corresponding bytes. */ + var t = reader.read(16); + var symToByte = new Uint8Array(256), symTotal = 0; + for (i = 0; i < 16; i++) { + if (t & (1 << (0xF - i))) { + var o = i * 16; + k = reader.read(16); + for (j = 0; j < 16; j++) + if (k & (1 << (0xF - j))) + symToByte[symTotal++] = o + j; + } + } + + /* How many different huffman coding groups does this block use? */ + var groupCount = reader.read(3); + if (groupCount < MIN_GROUPS || groupCount > MAX_GROUPS) + _throw(Err.DATA_ERROR); + /* nSelectors: Every GROUP_SIZE many symbols we select a new huffman coding + group. Read in the group selector list, which is stored as MTF encoded + bit runs. (MTF=Move To Front, as each value is used it's moved to the + start of the list.) */ + var nSelectors = reader.read(15); + if (nSelectors === 0) + _throw(Err.DATA_ERROR); + + var mtfSymbol = new Uint8Array(256); + for (i = 0; i < groupCount; i++) + mtfSymbol[i] = i; + + var selectors = new Uint8Array(nSelectors); // was 32768... + + for (i = 0; i < nSelectors; i++) { + /* Get next value */ + for (j = 0; reader.read(1); j++) + if (j >= groupCount) _throw(Err.DATA_ERROR); + /* Decode MTF to get the next selector */ + selectors[i] = mtf(mtfSymbol, j); + } + + /* Read the huffman coding tables for each group, which code for symTotal + literal symbols, plus two run symbols (RUNA, RUNB) */ + var symCount = symTotal + 2; + var groups = [], hufGroup; + for (j = 0; j < groupCount; j++) { + var length = new Uint8Array(symCount), temp = new Uint16Array(MAX_HUFCODE_BITS + 1); + /* Read huffman code lengths for each symbol. They're stored in + a way similar to mtf; record a starting value for the first symbol, + and an offset from the previous value for everys symbol after that. */ + t = reader.read(5); // lengths + for (i = 0; i < symCount; i++) { + for (;;) { + if (t < 1 || t > MAX_HUFCODE_BITS) _throw(Err.DATA_ERROR); + /* If first bit is 0, stop. Else second bit indicates whether + to increment or decrement the value. */ + if(!reader.read(1)) + break; + if(!reader.read(1)) + t++; + else + t--; + } + length[i] = t; + } + + /* Find largest and smallest lengths in this group */ + var minLen, maxLen; + minLen = maxLen = length[0]; + for (i = 1; i < symCount; i++) { + if (length[i] > maxLen) + maxLen = length[i]; + else if (length[i] < minLen) + minLen = length[i]; + } + + /* Calculate permute[], base[], and limit[] tables from length[]. + * + * permute[] is the lookup table for converting huffman coded symbols + * into decoded symbols. base[] is the amount to subtract from the + * value of a huffman symbol of a given length when using permute[]. + * + * limit[] indicates the largest numerical value a symbol with a given + * number of bits can have. This is how the huffman codes can vary in + * length: each code with a value>limit[length] needs another bit. + */ + hufGroup = {}; + groups.push(hufGroup); + hufGroup.permute = new Uint16Array(MAX_SYMBOLS); + hufGroup.limit = new Uint32Array(MAX_HUFCODE_BITS + 2); + hufGroup.base = new Uint32Array(MAX_HUFCODE_BITS + 1); + hufGroup.minLen = minLen; + hufGroup.maxLen = maxLen; + /* Calculate permute[]. Concurently, initialize temp[] and limit[]. */ + var pp = 0; + for (i = minLen; i <= maxLen; i++) { + temp[i] = hufGroup.limit[i] = 0; + for (t = 0; t < symCount; t++) + if (length[t] === i) + hufGroup.permute[pp++] = t; + } + /* Count symbols coded for at each bit length */ + for (i = 0; i < symCount; i++) + temp[length[i]]++; + /* Calculate limit[] (the largest symbol-coding value at each bit + * length, which is (previous limit<<1)+symbols at this level), and + * base[] (number of symbols to ignore at each bit length, which is + * limit minus the cumulative count of symbols coded for already). */ + pp = t = 0; + for (i = minLen; i < maxLen; i++) { + pp += temp[i]; + /* We read the largest possible symbol size and then unget bits + after determining how many we need, and those extra bits could + be set to anything. (They're noise from future symbols.) At + each level we're really only interested in the first few bits, + so here we set all the trailing to-be-ignored bits to 1 so they + don't affect the value>limit[length] comparison. */ + hufGroup.limit[i] = pp - 1; + pp <<= 1; + t += temp[i]; + hufGroup.base[i + 1] = pp - t; + } + hufGroup.limit[maxLen + 1] = Number.MAX_VALUE; /* Sentinal value for reading next sym. */ + hufGroup.limit[maxLen] = pp + temp[maxLen] - 1; + hufGroup.base[minLen] = 0; + } + /* We've finished reading and digesting the block header. Now read this + block's huffman coded symbols from the file and undo the huffman coding + and run length encoding, saving the result into dbuf[dbufCount++]=uc */ + + /* Initialize symbol occurrence counters and symbol Move To Front table */ + var byteCount = new Uint32Array(256); + for (i = 0; i < 256; i++) + mtfSymbol[i] = i; + /* Loop through compressed symbols. */ + var runPos = 0, dbufCount = 0, selector = 0, uc; + var dbuf = this.dbuf = new Uint32Array(this.dbufSize); + symCount = 0; + for (;;) { + /* Determine which huffman coding group to use. */ + if (!(symCount--)) { + symCount = GROUP_SIZE - 1; + if (selector >= nSelectors) { _throw(Err.DATA_ERROR); } + hufGroup = groups[selectors[selector++]]; + } + /* Read next huffman-coded symbol. */ + i = hufGroup.minLen; + j = reader.read(i); + for (;;i++) { + if (i > hufGroup.maxLen) { _throw(Err.DATA_ERROR); } + if (j <= hufGroup.limit[i]) + break; + j = (j << 1) | reader.read(1); + } + /* Huffman decode value to get nextSym (with bounds checking) */ + j -= hufGroup.base[i]; + if (j < 0 || j >= MAX_SYMBOLS) { _throw(Err.DATA_ERROR); } + var nextSym = hufGroup.permute[j]; + /* We have now decoded the symbol, which indicates either a new literal + byte, or a repeated run of the most recent literal byte. First, + check if nextSym indicates a repeated run, and if so loop collecting + how many times to repeat the last literal. */ + if (nextSym === SYMBOL_RUNA || nextSym === SYMBOL_RUNB) { + /* If this is the start of a new run, zero out counter */ + if (!runPos){ + runPos = 1; + t = 0; + } + /* Neat trick that saves 1 symbol: instead of or-ing 0 or 1 at + each bit position, add 1 or 2 instead. For example, + 1011 is 1<<0 + 1<<1 + 2<<2. 1010 is 2<<0 + 2<<1 + 1<<2. + You can make any bit pattern that way using 1 less symbol than + the basic or 0/1 method (except all bits 0, which would use no + symbols, but a run of length 0 doesn't mean anything in this + context). Thus space is saved. */ + if (nextSym === SYMBOL_RUNA) + t += runPos; + else + t += 2 * runPos; + runPos <<= 1; + continue; + } + /* When we hit the first non-run symbol after a run, we now know + how many times to repeat the last literal, so append that many + copies to our buffer of decoded symbols (dbuf) now. (The last + literal used is the one at the head of the mtfSymbol array.) */ + if (runPos){ + runPos = 0; + if (dbufCount + t > this.dbufSize) { _throw(Err.DATA_ERROR); } + uc = symToByte[mtfSymbol[0]]; + byteCount[uc] += t; + while (t--) + dbuf[dbufCount++] = uc; + } + /* Is this the terminating symbol? */ + if (nextSym > symTotal) + break; + /* At this point, nextSym indicates a new literal character. Subtract + one to get the position in the MTF array at which this literal is + currently to be found. (Note that the result can't be -1 or 0, + because 0 and 1 are RUNA and RUNB. But another instance of the + first symbol in the mtf array, position 0, would have been handled + as part of a run above. Therefore 1 unused mtf position minus + 2 non-literal nextSym values equals -1.) */ + if (dbufCount >= this.dbufSize) { _throw(Err.DATA_ERROR); } + i = nextSym - 1; + uc = mtf(mtfSymbol, i); + uc = symToByte[uc]; + /* We have our literal byte. Save it into dbuf. */ + byteCount[uc]++; + dbuf[dbufCount++] = uc; + } + /* At this point, we've read all the huffman-coded symbols (and repeated + runs) for this block from the input stream, and decoded them into the + intermediate buffer. There are dbufCount many decoded bytes in dbuf[]. + Now undo the Burrows-Wheeler transform on dbuf. + See http://dogma.net/markn/articles/bwt/bwt.htm + */ + if (origPointer < 0 || origPointer >= dbufCount) { _throw(Err.DATA_ERROR); } + /* Turn byteCount into cumulative occurrence counts of 0 to n-1. */ + j = 0; + for (i = 0; i < 256; i++) { + k = j + byteCount[i]; + byteCount[i] = j; + j = k; + } + /* Figure out what order dbuf would be in if we sorted it. */ + for (i = 0; i < dbufCount; i++) { + uc = dbuf[i] & 0xff; + dbuf[byteCount[uc]] |= (i << 8); + byteCount[uc]++; + } + /* Decode first byte by hand to initialize "previous" byte. Note that it + doesn't get output, and if the first three characters are identical + it doesn't qualify as a run (hence writeRunCountdown=5). */ + var pos = 0, current = 0, run = 0; + if (dbufCount) { + pos = dbuf[origPointer]; + current = (pos & 0xff); + pos >>= 8; + run = -1; + } + this.writePos = pos; + this.writeCurrent = current; + this.writeCount = dbufCount; + this.writeRun = run; + + return true; /* more blocks to come */ + }; + /* Undo burrows-wheeler transform on intermediate buffer to produce output. + If start_bunzip was initialized with out_fd=-1, then up to len bytes of + data are written to outbuf. Return value is number of bytes written or + error (all errors are negative numbers). If out_fd!=-1, outbuf and len + are ignored, data is written to out_fd and return is RETVAL_OK or error. + */ + Bunzip.prototype._read_bunzip = function(outputBuffer, len) { + var copies, previous, outbyte; + /* james@jamestaylor.org: writeCount goes to -1 when the buffer is fully + decoded, which results in this returning RETVAL_LAST_BLOCK, also + equal to -1... Confusing, I'm returning 0 here to indicate no + bytes written into the buffer */ + if (this.writeCount < 0) { return 0; } + var dbuf = this.dbuf, pos = this.writePos, current = this.writeCurrent; + var dbufCount = this.writeCount; this.outputsize; + var run = this.writeRun; + + while (dbufCount) { + dbufCount--; + previous = current; + pos = dbuf[pos]; + current = pos & 0xff; + pos >>= 8; + if (run++ === 3){ + copies = current; + outbyte = previous; + current = -1; + } else { + copies = 1; + outbyte = current; + } + this.blockCRC.updateCRCRun(outbyte, copies); + while (copies--) { + this.outputStream.writeByte(outbyte); + this.nextoutput++; + } + if (current != previous) + run = 0; + } + this.writeCount = dbufCount; + // check CRC + if (this.blockCRC.getCRC() !== this.targetBlockCRC) { + _throw(Err.DATA_ERROR, "Bad block CRC "+ + "(got "+this.blockCRC.getCRC().toString(16)+ + " expected "+this.targetBlockCRC.toString(16)+")"); + } + return this.nextoutput; + }; + + var coerceInputStream = function(input) { + if ('readByte' in input) { return input; } + var inputStream = new stream(); + inputStream.pos = 0; + inputStream.readByte = function() { return input[this.pos++]; }; + inputStream.seek = function(pos) { this.pos = pos; }; + inputStream.eof = function() { return this.pos >= input.length; }; + return inputStream; + }; + var coerceOutputStream = function(output) { + var outputStream = new stream(); + var resizeOk = true; + if (output) { + if (typeof(output)==='number') { + outputStream.buffer = new Uint8Array(output); + resizeOk = false; + } else if ('writeByte' in output) { + return output; + } else { + outputStream.buffer = output; + resizeOk = false; + } + } else { + outputStream.buffer = new Uint8Array(16384); + } + outputStream.pos = 0; + outputStream.writeByte = function(_byte) { + if (resizeOk && this.pos >= this.buffer.length) { + var newBuffer = new Uint8Array(this.buffer.length*2); + newBuffer.set(this.buffer); + this.buffer = newBuffer; + } + this.buffer[this.pos++] = _byte; + }; + outputStream.getBuffer = function() { + // trim buffer + if (this.pos !== this.buffer.length) { + if (!resizeOk) + throw new TypeError('outputsize does not match decoded input'); + var newBuffer = new Uint8Array(this.pos); + newBuffer.set(this.buffer.subarray(0, this.pos)); + this.buffer = newBuffer; + } + return this.buffer; + }; + outputStream._coerced = true; + return outputStream; + }; + + /* Static helper functions */ + // 'input' can be a stream or a buffer + // 'output' can be a stream or a buffer or a number (buffer size) + const decode$2 = function(input, output, multistream) { + // make a stream from a buffer, if necessary + var inputStream = coerceInputStream(input); + var outputStream = coerceOutputStream(output); + + var bz = new Bunzip(inputStream, outputStream); + while (true) { + if ('eof' in inputStream && inputStream.eof()) break; + if (bz._init_block()) { + bz._read_bunzip(); + } else { + var targetStreamCRC = bz.reader.read(32) >>> 0; // (convert to unsigned) + if (targetStreamCRC !== bz.streamCRC) { + _throw(Err.DATA_ERROR, "Bad stream CRC "+ + "(got "+bz.streamCRC.toString(16)+ + " expected "+targetStreamCRC.toString(16)+")"); + } + if (multistream && + 'eof' in inputStream && + !inputStream.eof()) { + // note that start_bunzip will also resync the bit reader to next byte + bz._start_bunzip(inputStream, outputStream); + } else break; + } + } + if ('getBuffer' in outputStream) + return outputStream.getBuffer(); + }; + const decodeBlock = function(input, pos, output) { + // make a stream from a buffer, if necessary + var inputStream = coerceInputStream(input); + var outputStream = coerceOutputStream(output); + var bz = new Bunzip(inputStream, outputStream); + bz.reader.seek(pos); + /* Fill the decode buffer for the block */ + var moreBlocks = bz._get_next_block(); + if (moreBlocks) { + /* Init the CRC for writing */ + bz.blockCRC = new crc32$1(); + + /* Zero this so the current byte from before the seek is not written */ + bz.writeCopies = 0; + + /* Decompress the block and write to stdout */ + bz._read_bunzip(); + // XXX keep writing? + } + if ('getBuffer' in outputStream) + return outputStream.getBuffer(); + }; + /* Reads bzip2 file from stream or buffer `input`, and invoke + * `callback(position, size)` once for each bzip2 block, + * where position gives the starting position (in *bits*) + * and size gives uncompressed size of the block (in *bytes*). */ + const table = function(input, callback, multistream) { + // make a stream from a buffer, if necessary + var inputStream = new stream(); + inputStream.delegate = coerceInputStream(input); + inputStream.pos = 0; + inputStream.readByte = function() { + this.pos++; + return this.delegate.readByte(); + }; + if (inputStream.delegate.eof) { + inputStream.eof = inputStream.delegate.eof.bind(inputStream.delegate); + } + var outputStream = new stream(); + outputStream.pos = 0; + outputStream.writeByte = function() { this.pos++; }; + + var bz = new Bunzip(inputStream, outputStream); + var blockSize = bz.dbufSize; + while (true) { + if ('eof' in inputStream && inputStream.eof()) break; + + var position = inputStream.pos*8 + bz.reader.bitOffset; + if (bz.reader.hasByte) { position -= 8; } + + if (bz._init_block()) { + var start = outputStream.pos; + bz._read_bunzip(); + callback(position, outputStream.pos - start); + } else { + bz.reader.read(32); // (but we ignore the crc) + if (multistream && + 'eof' in inputStream && + !inputStream.eof()) { + // note that start_bunzip will also resync the bit reader to next byte + bz._start_bunzip(inputStream, outputStream); + console.assert(bz.dbufSize === blockSize, + "shouldn't change block size within multistream file"); + } else break; + } + } + }; + + var lib = { + Bunzip, + Stream: stream, + Err, + decode: decode$2, + decodeBlock, + table + }; + var lib_4 = lib.decode; + + // GPG4Browsers - An OpenPGP implementation in javascript + + /** + * Implementation of the Literal Data Packet (Tag 11) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.9|RFC4880 5.9}: + * A Literal Data packet contains the body of a message; data that is not to be + * further interpreted. + */ + class LiteralDataPacket { + static get tag() { + return enums.packet.literalData; + } + + /** + * @param {Date} date - The creation date of the literal package + */ + constructor(date = new Date()) { + this.format = enums.literal.utf8; // default format for literal data packets + this.date = util.normalizeDate(date); + this.text = null; // textual data representation + this.data = null; // literal data representation + this.filename = ''; + } + + /** + * Set the packet data to a javascript native string, end of line + * will be normalized to \r\n and by default text is converted to UTF8 + * @param {String | ReadableStream} text - Any native javascript string + * @param {enums.literal} [format] - The format of the string of bytes + */ + setText(text, format = enums.literal.utf8) { + this.format = format; + this.text = text; + this.data = null; + } + + /** + * Returns literal data packets as native JavaScript string + * with normalized end of line to \n + * @param {Boolean} [clone] - Whether to return a clone so that getBytes/getText can be called again + * @returns {String | ReadableStream} Literal data as text. + */ + getText(clone = false) { + if (this.text === null || util.isStream(this.text)) { // Assume that this.text has been read + this.text = util.decodeUTF8(util.nativeEOL(this.getBytes(clone))); + } + return this.text; + } + + /** + * Set the packet data to value represented by the provided string of bytes. + * @param {Uint8Array | ReadableStream} bytes - The string of bytes + * @param {enums.literal} format - The format of the string of bytes + */ + setBytes(bytes, format) { + this.format = format; + this.data = bytes; + this.text = null; + } + + + /** + * Get the byte sequence representing the literal packet data + * @param {Boolean} [clone] - Whether to return a clone so that getBytes/getText can be called again + * @returns {Uint8Array | ReadableStream} A sequence of bytes. + */ + getBytes(clone = false) { + if (this.data === null) { + // encode UTF8 and normalize EOL to \r\n + this.data = util.canonicalizeEOL(util.encodeUTF8(this.text)); + } + if (clone) { + return passiveClone(this.data); + } + return this.data; + } + + + /** + * Sets the filename of the literal packet data + * @param {String} filename - Any native javascript string + */ + setFilename(filename) { + this.filename = filename; + } + + + /** + * Get the filename of the literal packet data + * @returns {String} Filename. + */ + getFilename() { + return this.filename; + } + + /** + * Parsing function for a literal data packet (tag 11). + * + * @param {Uint8Array | ReadableStream} input - Payload of a tag 11 packet + * @returns {Promise} Object representation. + * @async + */ + async read(bytes) { + await parse(bytes, async reader => { + // - A one-octet field that describes how the data is formatted. + const format = await reader.readByte(); // enums.literal + + const filename_len = await reader.readByte(); + this.filename = util.decodeUTF8(await reader.readBytes(filename_len)); + + this.date = util.readDate(await reader.readBytes(4)); + + let data = reader.remainder(); + if (isArrayStream(data)) data = await readToEnd(data); + this.setBytes(data, format); + }); + } + + /** + * Creates a Uint8Array representation of the packet, excluding the data + * + * @returns {Uint8Array} Uint8Array representation of the packet. + */ + writeHeader() { + const filename = util.encodeUTF8(this.filename); + const filename_length = new Uint8Array([filename.length]); + + const format = new Uint8Array([this.format]); + const date = util.writeDate(this.date); + + return util.concatUint8Array([format, filename_length, filename, date]); + } + + /** + * Creates a Uint8Array representation of the packet + * + * @returns {Uint8Array | ReadableStream} Uint8Array representation of the packet. + */ + write() { + const header = this.writeHeader(); + const data = this.getBytes(); + + return util.concat([header, data]); + } + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + function readSimpleLength(bytes) { + let len = 0; + let offset; + const type = bytes[0]; + + + if (type < 192) { + [len] = bytes; + offset = 1; + } else if (type < 255) { + len = ((bytes[0] - 192) << 8) + (bytes[1]) + 192; + offset = 2; + } else if (type === 255) { + len = util.readNumber(bytes.subarray(1, 1 + 4)); + offset = 5; + } + + return { + len: len, + offset: offset + }; + } + + /** + * Encodes a given integer of length to the openpgp length specifier to a + * string + * + * @param {Integer} length - The length to encode + * @returns {Uint8Array} String with openpgp length representation. + */ + function writeSimpleLength(length) { + if (length < 192) { + return new Uint8Array([length]); + } else if (length > 191 && length < 8384) { + /* + * let a = (total data packet length) - 192 let bc = two octet + * representation of a let d = b + 192 + */ + return new Uint8Array([((length - 192) >> 8) + 192, (length - 192) & 0xFF]); + } + return util.concatUint8Array([new Uint8Array([255]), util.writeNumber(length, 4)]); + } + + function writePartialLength(power) { + if (power < 0 || power > 30) { + throw new Error('Partial Length power must be between 1 and 30'); + } + return new Uint8Array([224 + power]); + } + + function writeTag(tag_type) { + /* we're only generating v4 packet headers here */ + return new Uint8Array([0xC0 | tag_type]); + } + + /** + * Writes a packet header version 4 with the given tag_type and length to a + * string + * + * @param {Integer} tag_type - Tag type + * @param {Integer} length - Length of the payload + * @returns {String} String of the header. + */ + function writeHeader(tag_type, length) { + /* we're only generating v4 packet headers here */ + return util.concatUint8Array([writeTag(tag_type), writeSimpleLength(length)]); + } + + /** + * Whether the packet type supports partial lengths per RFC4880 + * @param {Integer} tag - Tag type + * @returns {Boolean} String of the header. + */ + function supportsStreaming(tag) { + return [ + enums.packet.literalData, + enums.packet.compressedData, + enums.packet.symmetricallyEncryptedData, + enums.packet.symEncryptedIntegrityProtectedData, + enums.packet.aeadEncryptedData + ].includes(tag); + } + + /** + * Generic static Packet Parser function + * + * @param {Uint8Array | ReadableStream} input - Input stream as string + * @param {Function} callback - Function to call with the parsed packet + * @returns {Boolean} Returns false if the stream was empty and parsing is done, and true otherwise. + */ + async function readPackets(input, callback) { + const reader = getReader(input); + let writer; + let callbackReturned; + try { + const peekedBytes = await reader.peekBytes(2); + // some sanity checks + if (!peekedBytes || peekedBytes.length < 2 || (peekedBytes[0] & 0x80) === 0) { + throw new Error('Error during parsing. This message / key probably does not conform to a valid OpenPGP format.'); + } + const headerByte = await reader.readByte(); + let tag = -1; + let format = -1; + let packetLength; + + format = 0; // 0 = old format; 1 = new format + if ((headerByte & 0x40) !== 0) { + format = 1; + } + + let packetLengthType; + if (format) { + // new format header + tag = headerByte & 0x3F; // bit 5-0 + } else { + // old format header + tag = (headerByte & 0x3F) >> 2; // bit 5-2 + packetLengthType = headerByte & 0x03; // bit 1-0 + } + + const packetSupportsStreaming = supportsStreaming(tag); + let packet = null; + if (packetSupportsStreaming) { + if (util.isStream(input) === 'array') { + const arrayStream = new ArrayStream(); + writer = getWriter(arrayStream); + packet = arrayStream; + } else { + const transform = new TransformStream(); + writer = getWriter(transform.writable); + packet = transform.readable; + } + callbackReturned = callback({ tag, packet }); + } else { + packet = []; + } + + let wasPartialLength; + do { + if (!format) { + // 4.2.1. Old Format Packet Lengths + switch (packetLengthType) { + case 0: + // The packet has a one-octet length. The header is 2 octets + // long. + packetLength = await reader.readByte(); + break; + case 1: + // The packet has a two-octet length. The header is 3 octets + // long. + packetLength = (await reader.readByte() << 8) | await reader.readByte(); + break; + case 2: + // The packet has a four-octet length. The header is 5 + // octets long. + packetLength = (await reader.readByte() << 24) | (await reader.readByte() << 16) | (await reader.readByte() << + 8) | await reader.readByte(); + break; + default: + // 3 - The packet is of indeterminate length. The header is 1 + // octet long, and the implementation must determine how long + // the packet is. If the packet is in a file, this means that + // the packet extends until the end of the file. In general, + // an implementation SHOULD NOT use indeterminate-length + // packets except where the end of the data will be clear + // from the context, and even then it is better to use a + // definite length, or a new format header. The new format + // headers described below have a mechanism for precisely + // encoding data of indeterminate length. + packetLength = Infinity; + break; + } + } else { // 4.2.2. New Format Packet Lengths + // 4.2.2.1. One-Octet Lengths + const lengthByte = await reader.readByte(); + wasPartialLength = false; + if (lengthByte < 192) { + packetLength = lengthByte; + // 4.2.2.2. Two-Octet Lengths + } else if (lengthByte >= 192 && lengthByte < 224) { + packetLength = ((lengthByte - 192) << 8) + (await reader.readByte()) + 192; + // 4.2.2.4. Partial Body Lengths + } else if (lengthByte > 223 && lengthByte < 255) { + packetLength = 1 << (lengthByte & 0x1F); + wasPartialLength = true; + if (!packetSupportsStreaming) { + throw new TypeError('This packet type does not support partial lengths.'); + } + // 4.2.2.3. Five-Octet Lengths + } else { + packetLength = (await reader.readByte() << 24) | (await reader.readByte() << 16) | (await reader.readByte() << + 8) | await reader.readByte(); + } + } + if (packetLength > 0) { + let bytesRead = 0; + while (true) { + if (writer) await writer.ready; + const { done, value } = await reader.read(); + if (done) { + if (packetLength === Infinity) break; + throw new Error('Unexpected end of packet'); + } + const chunk = packetLength === Infinity ? value : value.subarray(0, packetLength - bytesRead); + if (writer) await writer.write(chunk); + else packet.push(chunk); + bytesRead += value.length; + if (bytesRead >= packetLength) { + reader.unshift(value.subarray(packetLength - bytesRead + value.length)); + break; + } + } + } + } while (wasPartialLength); + + // If this was not a packet that "supports streaming", we peek to check + // whether it is the last packet in the message. We peek 2 bytes instead + // of 1 because the beginning of this function also peeks 2 bytes, and we + // want to cut a `subarray` of the correct length into `web-stream-tools`' + // `externalBuffer` as a tiny optimization here. + // + // If it *was* a streaming packet (i.e. the data packets), we peek at the + // entire remainder of the stream, in order to forward errors in the + // remainder of the stream to the packet data. (Note that this means we + // read/peek at all signature packets before closing the literal data + // packet, for example.) This forwards MDC errors to the literal data + // stream, for example, so that they don't get lost / forgotten on + // decryptedMessage.packets.stream, which we never look at. + // + // An example of what we do when stream-parsing a message containing + // [ one-pass signature packet, literal data packet, signature packet ]: + // 1. Read the one-pass signature packet + // 2. Peek 2 bytes of the literal data packet + // 3. Parse the one-pass signature packet + // + // 4. Read the literal data packet, simultaneously stream-parsing it + // 5. Peek until the end of the message + // 6. Finish parsing the literal data packet + // + // 7. Read the signature packet again (we already peeked at it in step 5) + // 8. Peek at the end of the stream again (`peekBytes` returns undefined) + // 9. Parse the signature packet + // + // Note that this means that if there's an error in the very end of the + // stream, such as an MDC error, we throw in step 5 instead of in step 8 + // (or never), which is the point of this exercise. + const nextPacket = await reader.peekBytes(packetSupportsStreaming ? Infinity : 2); + if (writer) { + await writer.ready; + await writer.close(); + } else { + packet = util.concatUint8Array(packet); + await callback({ tag, packet }); + } + return !nextPacket || !nextPacket.length; + } catch (e) { + if (writer) { + await writer.abort(e); + return true; + } else { + throw e; + } + } finally { + if (writer) { + await callbackReturned; + } + reader.releaseLock(); + } + } + + class UnsupportedError extends Error { + constructor(...params) { + super(...params); + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, UnsupportedError); + } + + this.name = 'UnsupportedError'; + } + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + // Symbol to store cryptographic validity of the signature, to avoid recomputing multiple times on verification. + const verified = Symbol('verified'); + + // GPG puts the Issuer and Signature subpackets in the unhashed area. + // Tampering with those invalidates the signature, so we still trust them and parse them. + // All other unhashed subpackets are ignored. + const allowedUnhashedSubpackets = new Set([ + enums.signatureSubpacket.issuer, + enums.signatureSubpacket.issuerFingerprint, + enums.signatureSubpacket.embeddedSignature + ]); + + /** + * Implementation of the Signature Packet (Tag 2) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.2|RFC4480 5.2}: + * A Signature packet describes a binding between some public key and + * some data. The most common signatures are a signature of a file or a + * block of text, and a signature that is a certification of a User ID. + */ + class SignaturePacket { + static get tag() { + return enums.packet.signature; + } + + constructor() { + this.version = null; + /** @type {enums.signature} */ + this.signatureType = null; + /** @type {enums.hash} */ + this.hashAlgorithm = null; + /** @type {enums.publicKey} */ + this.publicKeyAlgorithm = null; + + this.signatureData = null; + this.unhashedSubpackets = []; + this.signedHashValue = null; + + this.created = null; + this.signatureExpirationTime = null; + this.signatureNeverExpires = true; + this.exportable = null; + this.trustLevel = null; + this.trustAmount = null; + this.regularExpression = null; + this.revocable = null; + this.keyExpirationTime = null; + this.keyNeverExpires = null; + this.preferredSymmetricAlgorithms = null; + this.revocationKeyClass = null; + this.revocationKeyAlgorithm = null; + this.revocationKeyFingerprint = null; + this.issuerKeyID = new KeyID(); + this.rawNotations = []; + this.notations = {}; + this.preferredHashAlgorithms = null; + this.preferredCompressionAlgorithms = null; + this.keyServerPreferences = null; + this.preferredKeyServer = null; + this.isPrimaryUserID = null; + this.policyURI = null; + this.keyFlags = null; + this.signersUserID = null; + this.reasonForRevocationFlag = null; + this.reasonForRevocationString = null; + this.features = null; + this.signatureTargetPublicKeyAlgorithm = null; + this.signatureTargetHashAlgorithm = null; + this.signatureTargetHash = null; + this.embeddedSignature = null; + this.issuerKeyVersion = null; + this.issuerFingerprint = null; + this.preferredAEADAlgorithms = null; + + this.revoked = null; + this[verified] = null; + } + + /** + * parsing function for a signature packet (tag 2). + * @param {String} bytes - Payload of a tag 2 packet + * @returns {SignaturePacket} Object representation. + */ + read(bytes) { + let i = 0; + this.version = bytes[i++]; + + if (this.version !== 4 && this.version !== 5) { + throw new UnsupportedError(`Version ${this.version} of the signature packet is unsupported.`); + } + + this.signatureType = bytes[i++]; + this.publicKeyAlgorithm = bytes[i++]; + this.hashAlgorithm = bytes[i++]; + + // hashed subpackets + i += this.readSubPackets(bytes.subarray(i, bytes.length), true); + if (!this.created) { + throw new Error('Missing signature creation time subpacket.'); + } + + // A V4 signature hashes the packet body + // starting from its first field, the version number, through the end + // of the hashed subpacket data. Thus, the fields hashed are the + // signature version, the signature type, the public-key algorithm, the + // hash algorithm, the hashed subpacket length, and the hashed + // subpacket body. + this.signatureData = bytes.subarray(0, i); + + // unhashed subpackets + i += this.readSubPackets(bytes.subarray(i, bytes.length), false); + + // Two-octet field holding left 16 bits of signed hash value. + this.signedHashValue = bytes.subarray(i, i + 2); + i += 2; + + this.params = mod.signature.parseSignatureParams(this.publicKeyAlgorithm, bytes.subarray(i, bytes.length)); + } + + /** + * @returns {Uint8Array | ReadableStream} + */ + writeParams() { + if (this.params instanceof Promise) { + return fromAsync( + async () => mod.serializeParams(this.publicKeyAlgorithm, await this.params) + ); + } + return mod.serializeParams(this.publicKeyAlgorithm, this.params); + } + + write() { + const arr = []; + arr.push(this.signatureData); + arr.push(this.writeUnhashedSubPackets()); + arr.push(this.signedHashValue); + arr.push(this.writeParams()); + return util.concat(arr); + } + + /** + * Signs provided data. This needs to be done prior to serialization. + * @param {SecretKeyPacket} key - Private key used to sign the message. + * @param {Object} data - Contains packets to be signed. + * @param {Date} [date] - The signature creation time. + * @param {Boolean} [detached] - Whether to create a detached signature + * @throws {Error} if signing failed + * @async + */ + async sign(key, data, date = new Date(), detached = false) { + if (key.version === 5) { + this.version = 5; + } else { + this.version = 4; + } + const arr = [new Uint8Array([this.version, this.signatureType, this.publicKeyAlgorithm, this.hashAlgorithm])]; + + this.created = util.normalizeDate(date); + this.issuerKeyVersion = key.version; + this.issuerFingerprint = key.getFingerprintBytes(); + this.issuerKeyID = key.getKeyID(); + + // Add hashed subpackets + arr.push(this.writeHashedSubPackets()); + + this.signatureData = util.concat(arr); + + const toHash = this.toHash(this.signatureType, data, detached); + const hash = await this.hash(this.signatureType, data, toHash, detached); + + this.signedHashValue = slice(clone(hash), 0, 2); + const signed = async () => mod.signature.sign( + this.publicKeyAlgorithm, this.hashAlgorithm, key.publicParams, key.privateParams, toHash, await readToEnd(hash) + ); + if (util.isStream(hash)) { + this.params = signed(); + } else { + this.params = await signed(); + + // Store the fact that this signature is valid, e.g. for when we call `await + // getLatestValidSignature(this.revocationSignatures, key, data)` later. + // Note that this only holds up if the key and data passed to verify are the + // same as the ones passed to sign. + this[verified] = true; + } + } + + /** + * Creates Uint8Array of bytes of all subpacket data except Issuer and Embedded Signature subpackets + * @returns {Uint8Array} Subpacket data. + */ + writeHashedSubPackets() { + const sub = enums.signatureSubpacket; + const arr = []; + let bytes; + if (this.created === null) { + throw new Error('Missing signature creation time'); + } + arr.push(writeSubPacket(sub.signatureCreationTime, util.writeDate(this.created))); + if (this.signatureExpirationTime !== null) { + arr.push(writeSubPacket(sub.signatureExpirationTime, util.writeNumber(this.signatureExpirationTime, 4))); + } + if (this.exportable !== null) { + arr.push(writeSubPacket(sub.exportableCertification, new Uint8Array([this.exportable ? 1 : 0]))); + } + if (this.trustLevel !== null) { + bytes = new Uint8Array([this.trustLevel, this.trustAmount]); + arr.push(writeSubPacket(sub.trustSignature, bytes)); + } + if (this.regularExpression !== null) { + arr.push(writeSubPacket(sub.regularExpression, this.regularExpression)); + } + if (this.revocable !== null) { + arr.push(writeSubPacket(sub.revocable, new Uint8Array([this.revocable ? 1 : 0]))); + } + if (this.keyExpirationTime !== null) { + arr.push(writeSubPacket(sub.keyExpirationTime, util.writeNumber(this.keyExpirationTime, 4))); + } + if (this.preferredSymmetricAlgorithms !== null) { + bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredSymmetricAlgorithms)); + arr.push(writeSubPacket(sub.preferredSymmetricAlgorithms, bytes)); + } + if (this.revocationKeyClass !== null) { + bytes = new Uint8Array([this.revocationKeyClass, this.revocationKeyAlgorithm]); + bytes = util.concat([bytes, this.revocationKeyFingerprint]); + arr.push(writeSubPacket(sub.revocationKey, bytes)); + } + this.rawNotations.forEach(([{ name, value, humanReadable }]) => { + bytes = [new Uint8Array([humanReadable ? 0x80 : 0, 0, 0, 0])]; + // 2 octets of name length + bytes.push(util.writeNumber(name.length, 2)); + // 2 octets of value length + bytes.push(util.writeNumber(value.length, 2)); + bytes.push(util.stringToUint8Array(name)); + bytes.push(value); + bytes = util.concat(bytes); + arr.push(writeSubPacket(sub.notationData, bytes)); + }); + if (this.preferredHashAlgorithms !== null) { + bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredHashAlgorithms)); + arr.push(writeSubPacket(sub.preferredHashAlgorithms, bytes)); + } + if (this.preferredCompressionAlgorithms !== null) { + bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredCompressionAlgorithms)); + arr.push(writeSubPacket(sub.preferredCompressionAlgorithms, bytes)); + } + if (this.keyServerPreferences !== null) { + bytes = util.stringToUint8Array(util.uint8ArrayToString(this.keyServerPreferences)); + arr.push(writeSubPacket(sub.keyServerPreferences, bytes)); + } + if (this.preferredKeyServer !== null) { + arr.push(writeSubPacket(sub.preferredKeyServer, util.stringToUint8Array(this.preferredKeyServer))); + } + if (this.isPrimaryUserID !== null) { + arr.push(writeSubPacket(sub.primaryUserID, new Uint8Array([this.isPrimaryUserID ? 1 : 0]))); + } + if (this.policyURI !== null) { + arr.push(writeSubPacket(sub.policyURI, util.stringToUint8Array(this.policyURI))); + } + if (this.keyFlags !== null) { + bytes = util.stringToUint8Array(util.uint8ArrayToString(this.keyFlags)); + arr.push(writeSubPacket(sub.keyFlags, bytes)); + } + if (this.signersUserID !== null) { + arr.push(writeSubPacket(sub.signersUserID, util.stringToUint8Array(this.signersUserID))); + } + if (this.reasonForRevocationFlag !== null) { + bytes = util.stringToUint8Array(String.fromCharCode(this.reasonForRevocationFlag) + this.reasonForRevocationString); + arr.push(writeSubPacket(sub.reasonForRevocation, bytes)); + } + if (this.features !== null) { + bytes = util.stringToUint8Array(util.uint8ArrayToString(this.features)); + arr.push(writeSubPacket(sub.features, bytes)); + } + if (this.signatureTargetPublicKeyAlgorithm !== null) { + bytes = [new Uint8Array([this.signatureTargetPublicKeyAlgorithm, this.signatureTargetHashAlgorithm])]; + bytes.push(util.stringToUint8Array(this.signatureTargetHash)); + bytes = util.concat(bytes); + arr.push(writeSubPacket(sub.signatureTarget, bytes)); + } + if (this.preferredAEADAlgorithms !== null) { + bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredAEADAlgorithms)); + arr.push(writeSubPacket(sub.preferredAEADAlgorithms, bytes)); + } + + const result = util.concat(arr); + const length = util.writeNumber(result.length, 2); + + return util.concat([length, result]); + } + + /** + * Creates Uint8Array of bytes of Issuer and Embedded Signature subpackets + * @returns {Uint8Array} Subpacket data. + */ + writeUnhashedSubPackets() { + const sub = enums.signatureSubpacket; + const arr = []; + let bytes; + if (!this.issuerKeyID.isNull() && this.issuerKeyVersion !== 5) { + // If the version of [the] key is greater than 4, this subpacket + // MUST NOT be included in the signature. + arr.push(writeSubPacket(sub.issuer, this.issuerKeyID.write())); + } + if (this.embeddedSignature !== null) { + arr.push(writeSubPacket(sub.embeddedSignature, this.embeddedSignature.write())); + } + if (this.issuerFingerprint !== null) { + bytes = [new Uint8Array([this.issuerKeyVersion]), this.issuerFingerprint]; + bytes = util.concat(bytes); + arr.push(writeSubPacket(sub.issuerFingerprint, bytes)); + } + this.unhashedSubpackets.forEach(data => { + arr.push(writeSimpleLength(data.length)); + arr.push(data); + }); + + const result = util.concat(arr); + const length = util.writeNumber(result.length, 2); + + return util.concat([length, result]); + } + + // V4 signature sub packets + readSubPacket(bytes, hashed = true) { + let mypos = 0; + + // The leftmost bit denotes a "critical" packet + const critical = bytes[mypos] & 0x80; + const type = bytes[mypos] & 0x7F; + + if (!hashed && !allowedUnhashedSubpackets.has(type)) { + this.unhashedSubpackets.push(bytes.subarray(mypos, bytes.length)); + return; + } + + mypos++; + + // subpacket type + switch (type) { + case enums.signatureSubpacket.signatureCreationTime: + // Signature Creation Time + this.created = util.readDate(bytes.subarray(mypos, bytes.length)); + break; + case enums.signatureSubpacket.signatureExpirationTime: { + // Signature Expiration Time in seconds + const seconds = util.readNumber(bytes.subarray(mypos, bytes.length)); + + this.signatureNeverExpires = seconds === 0; + this.signatureExpirationTime = seconds; + + break; + } + case enums.signatureSubpacket.exportableCertification: + // Exportable Certification + this.exportable = bytes[mypos++] === 1; + break; + case enums.signatureSubpacket.trustSignature: + // Trust Signature + this.trustLevel = bytes[mypos++]; + this.trustAmount = bytes[mypos++]; + break; + case enums.signatureSubpacket.regularExpression: + // Regular Expression + this.regularExpression = bytes[mypos]; + break; + case enums.signatureSubpacket.revocable: + // Revocable + this.revocable = bytes[mypos++] === 1; + break; + case enums.signatureSubpacket.keyExpirationTime: { + // Key Expiration Time in seconds + const seconds = util.readNumber(bytes.subarray(mypos, bytes.length)); + + this.keyExpirationTime = seconds; + this.keyNeverExpires = seconds === 0; + + break; + } + case enums.signatureSubpacket.preferredSymmetricAlgorithms: + // Preferred Symmetric Algorithms + this.preferredSymmetricAlgorithms = [...bytes.subarray(mypos, bytes.length)]; + break; + case enums.signatureSubpacket.revocationKey: + // Revocation Key + // (1 octet of class, 1 octet of public-key algorithm ID, 20 + // octets of + // fingerprint) + this.revocationKeyClass = bytes[mypos++]; + this.revocationKeyAlgorithm = bytes[mypos++]; + this.revocationKeyFingerprint = bytes.subarray(mypos, mypos + 20); + break; + + case enums.signatureSubpacket.issuer: + // Issuer + this.issuerKeyID.read(bytes.subarray(mypos, bytes.length)); + break; + + case enums.signatureSubpacket.notationData: { + // Notation Data + const humanReadable = !!(bytes[mypos] & 0x80); + + // We extract key/value tuple from the byte stream. + mypos += 4; + const m = util.readNumber(bytes.subarray(mypos, mypos + 2)); + mypos += 2; + const n = util.readNumber(bytes.subarray(mypos, mypos + 2)); + mypos += 2; + + const name = util.uint8ArrayToString(bytes.subarray(mypos, mypos + m)); + const value = bytes.subarray(mypos + m, mypos + m + n); + + this.rawNotations.push({ name, humanReadable, value, critical }); + + if (humanReadable) { + this.notations[name] = util.uint8ArrayToString(value); + } + break; + } + case enums.signatureSubpacket.preferredHashAlgorithms: + // Preferred Hash Algorithms + this.preferredHashAlgorithms = [...bytes.subarray(mypos, bytes.length)]; + break; + case enums.signatureSubpacket.preferredCompressionAlgorithms: + // Preferred Compression Algorithms + this.preferredCompressionAlgorithms = [...bytes.subarray(mypos, bytes.length)]; + break; + case enums.signatureSubpacket.keyServerPreferences: + // Key Server Preferences + this.keyServerPreferences = [...bytes.subarray(mypos, bytes.length)]; + break; + case enums.signatureSubpacket.preferredKeyServer: + // Preferred Key Server + this.preferredKeyServer = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); + break; + case enums.signatureSubpacket.primaryUserID: + // Primary User ID + this.isPrimaryUserID = bytes[mypos++] !== 0; + break; + case enums.signatureSubpacket.policyURI: + // Policy URI + this.policyURI = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); + break; + case enums.signatureSubpacket.keyFlags: + // Key Flags + this.keyFlags = [...bytes.subarray(mypos, bytes.length)]; + break; + case enums.signatureSubpacket.signersUserID: + // Signer's User ID + this.signersUserID = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); + break; + case enums.signatureSubpacket.reasonForRevocation: + // Reason for Revocation + this.reasonForRevocationFlag = bytes[mypos++]; + this.reasonForRevocationString = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); + break; + case enums.signatureSubpacket.features: + // Features + this.features = [...bytes.subarray(mypos, bytes.length)]; + break; + case enums.signatureSubpacket.signatureTarget: { + // Signature Target + // (1 octet public-key algorithm, 1 octet hash algorithm, N octets hash) + this.signatureTargetPublicKeyAlgorithm = bytes[mypos++]; + this.signatureTargetHashAlgorithm = bytes[mypos++]; + + const len = mod.getHashByteLength(this.signatureTargetHashAlgorithm); + + this.signatureTargetHash = util.uint8ArrayToString(bytes.subarray(mypos, mypos + len)); + break; + } + case enums.signatureSubpacket.embeddedSignature: + // Embedded Signature + this.embeddedSignature = new SignaturePacket(); + this.embeddedSignature.read(bytes.subarray(mypos, bytes.length)); + break; + case enums.signatureSubpacket.issuerFingerprint: + // Issuer Fingerprint + this.issuerKeyVersion = bytes[mypos++]; + this.issuerFingerprint = bytes.subarray(mypos, bytes.length); + if (this.issuerKeyVersion === 5) { + this.issuerKeyID.read(this.issuerFingerprint); + } else { + this.issuerKeyID.read(this.issuerFingerprint.subarray(-8)); + } + break; + case enums.signatureSubpacket.preferredAEADAlgorithms: + // Preferred AEAD Algorithms + this.preferredAEADAlgorithms = [...bytes.subarray(mypos, bytes.length)]; + break; + default: { + const err = new Error(`Unknown signature subpacket type ${type}`); + if (critical) { + throw err; + } else { + util.printDebug(err); + } + } + } + } + + readSubPackets(bytes, trusted = true, config) { + // Two-octet scalar octet count for following subpacket data. + const subpacketLength = util.readNumber(bytes.subarray(0, 2)); + + let i = 2; + + // subpacket data set (zero or more subpackets) + while (i < 2 + subpacketLength) { + const len = readSimpleLength(bytes.subarray(i, bytes.length)); + i += len.offset; + + this.readSubPacket(bytes.subarray(i, i + len.len), trusted, config); + + i += len.len; + } + + return i; + } + + // Produces data to produce signature on + toSign(type, data) { + const t = enums.signature; + + switch (type) { + case t.binary: + if (data.text !== null) { + return util.encodeUTF8(data.getText(true)); + } + return data.getBytes(true); + + case t.text: { + const bytes = data.getBytes(true); + // normalize EOL to \r\n + return util.canonicalizeEOL(bytes); + } + case t.standalone: + return new Uint8Array(0); + + case t.certGeneric: + case t.certPersona: + case t.certCasual: + case t.certPositive: + case t.certRevocation: { + let packet; + let tag; + + if (data.userID) { + tag = 0xB4; + packet = data.userID; + } else if (data.userAttribute) { + tag = 0xD1; + packet = data.userAttribute; + } else { + throw new Error('Either a userID or userAttribute packet needs to be ' + + 'supplied for certification.'); + } + + const bytes = packet.write(); + + return util.concat([this.toSign(t.key, data), + new Uint8Array([tag]), + util.writeNumber(bytes.length, 4), + bytes]); + } + case t.subkeyBinding: + case t.subkeyRevocation: + case t.keyBinding: + return util.concat([this.toSign(t.key, data), this.toSign(t.key, { + key: data.bind + })]); + + case t.key: + if (data.key === undefined) { + throw new Error('Key packet is required for this signature.'); + } + return data.key.writeForHash(this.version); + + case t.keyRevocation: + return this.toSign(t.key, data); + case t.timestamp: + return new Uint8Array(0); + case t.thirdParty: + throw new Error('Not implemented'); + default: + throw new Error('Unknown signature type.'); + } + } + + calculateTrailer(data, detached) { + let length = 0; + return transform(clone(this.signatureData), value => { + length += value.length; + }, () => { + const arr = []; + if (this.version === 5 && (this.signatureType === enums.signature.binary || this.signatureType === enums.signature.text)) { + if (detached) { + arr.push(new Uint8Array(6)); + } else { + arr.push(data.writeHeader()); + } + } + arr.push(new Uint8Array([this.version, 0xFF])); + if (this.version === 5) { + arr.push(new Uint8Array(4)); + } + arr.push(util.writeNumber(length, 4)); + // For v5, this should really be writeNumber(length, 8) rather than the + // hardcoded 4 zero bytes above + return util.concat(arr); + }); + } + + toHash(signatureType, data, detached = false) { + const bytes = this.toSign(signatureType, data); + + return util.concat([bytes, this.signatureData, this.calculateTrailer(data, detached)]); + } + + async hash(signatureType, data, toHash, detached = false) { + if (!toHash) toHash = this.toHash(signatureType, data, detached); + return mod.hash.digest(this.hashAlgorithm, toHash); + } + + /** + * verifies the signature packet. Note: not all signature types are implemented + * @param {PublicSubkeyPacket|PublicKeyPacket| + * SecretSubkeyPacket|SecretKeyPacket} key - the public key to verify the signature + * @param {module:enums.signature} signatureType - Expected signature type + * @param {String|Object} data - Data which on the signature applies + * @param {Date} [date] - Use the given date instead of the current time to check for signature validity and expiration + * @param {Boolean} [detached] - Whether to verify a detached signature + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if signature validation failed + * @async + */ + async verify(key, signatureType, data, date = new Date(), detached = false, config = defaultConfig) { + if (!this.issuerKeyID.equals(key.getKeyID())) { + throw new Error('Signature was not issued by the given public key'); + } + if (this.publicKeyAlgorithm !== key.algorithm) { + throw new Error('Public key algorithm used to sign signature does not match issuer key algorithm.'); + } + + const isMessageSignature = signatureType === enums.signature.binary || signatureType === enums.signature.text; + // Cryptographic validity is cached after one successful verification. + // However, for message signatures, we always re-verify, since the passed `data` can change + const skipVerify = this.verified && !isMessageSignature; + if (!skipVerify) { + let toHash; + let hash; + if (this.hashed) { + hash = await this.hashed; + } else { + toHash = this.toHash(signatureType, data, detached); + hash = await this.hash(signatureType, data, toHash); + } + hash = await readToEnd(hash); + if (this.signedHashValue[0] !== hash[0] || + this.signedHashValue[1] !== hash[1]) { + throw new Error('Signed digest did not match'); + } + + this.params = await this.params; + + this.verified = await mod.signature.verify( + this.publicKeyAlgorithm, this.hashAlgorithm, this.params, key.publicParams, + toHash, hash + ); + + if (!this.verified) { + throw new Error('Signature verification failed'); + } + } + + const normDate = util.normalizeDate(date); + if (normDate && this.created > normDate) { + throw new Error('Signature creation time is in the future'); + } + if (normDate && normDate >= this.getExpirationTime()) { + throw new Error('Signature is expired'); + } + if (config.rejectHashAlgorithms.has(this.hashAlgorithm)) { + throw new Error('Insecure hash algorithm: ' + enums.read(enums.hash, this.hashAlgorithm).toUpperCase()); + } + if (config.rejectMessageHashAlgorithms.has(this.hashAlgorithm) && + [enums.signature.binary, enums.signature.text].includes(this.signatureType)) { + throw new Error('Insecure message hash algorithm: ' + enums.read(enums.hash, this.hashAlgorithm).toUpperCase()); + } + this.rawNotations.forEach(({ name, critical }) => { + if (critical && (config.knownNotations.indexOf(name) < 0)) { + throw new Error(`Unknown critical notation: ${name}`); + } + }); + if (this.revocationKeyClass !== null) { + throw new Error('This key is intended to be revoked with an authorized key, which OpenPGP.js does not support.'); + } + } + + /** + * Verifies signature expiration date + * @param {Date} [date] - Use the given date for verification instead of the current time + * @returns {Boolean} True if expired. + */ + isExpired(date = new Date()) { + const normDate = util.normalizeDate(date); + if (normDate !== null) { + return !(this.created <= normDate && normDate < this.getExpirationTime()); + } + return false; + } + + /** + * Returns the expiration time of the signature or Infinity if signature does not expire + * @returns {Date | Infinity} Expiration time. + */ + getExpirationTime() { + return this.signatureNeverExpires ? Infinity : new Date(this.created.getTime() + this.signatureExpirationTime * 1000); + } + } + + /** + * Creates a string representation of a sub signature packet + * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.1|RFC4880 5.2.3.1} + * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.2|RFC4880 5.2.3.2} + * @param {Integer} type - Subpacket signature type. + * @param {String} data - Data to be included + * @returns {String} A string-representation of a sub signature packet. + * @private + */ + function writeSubPacket(type, data) { + const arr = []; + arr.push(writeSimpleLength(data.length + 1)); + arr.push(new Uint8Array([type])); + arr.push(data); + return util.concat(arr); + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + const VERSION = 3; + + /** + * Implementation of the One-Pass Signature Packets (Tag 4) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.4|RFC4880 5.4}: + * The One-Pass Signature packet precedes the signed data and contains + * enough information to allow the receiver to begin calculating any + * hashes needed to verify the signature. It allows the Signature + * packet to be placed at the end of the message, so that the signer + * can compute the entire signed message in one pass. + */ + class OnePassSignaturePacket { + static get tag() { + return enums.packet.onePassSignature; + } + + constructor() { + /** A one-octet version number. The current version is 3. */ + this.version = null; + /** + * A one-octet signature type. + * Signature types are described in + * {@link https://tools.ietf.org/html/rfc4880#section-5.2.1|RFC4880 Section 5.2.1}. + * @type {enums.signature} + + */ + this.signatureType = null; + /** + * A one-octet number describing the hash algorithm used. + * @see {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC4880 9.4} + * @type {enums.hash} + */ + this.hashAlgorithm = null; + /** + * A one-octet number describing the public-key algorithm used. + * @see {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC4880 9.1} + * @type {enums.publicKey} + */ + this.publicKeyAlgorithm = null; + /** An eight-octet number holding the Key ID of the signing key. */ + this.issuerKeyID = null; + /** + * A one-octet number holding a flag showing whether the signature is nested. + * A zero value indicates that the next packet is another One-Pass Signature packet + * that describes another signature to be applied to the same message data. + */ + this.flags = null; + } + + /** + * parsing function for a one-pass signature packet (tag 4). + * @param {Uint8Array} bytes - Payload of a tag 4 packet + * @returns {OnePassSignaturePacket} Object representation. + */ + read(bytes) { + let mypos = 0; + // A one-octet version number. The current version is 3. + this.version = bytes[mypos++]; + if (this.version !== VERSION) { + throw new UnsupportedError(`Version ${this.version} of the one-pass signature packet is unsupported.`); + } + + // A one-octet signature type. Signature types are described in + // Section 5.2.1. + this.signatureType = bytes[mypos++]; + + // A one-octet number describing the hash algorithm used. + this.hashAlgorithm = bytes[mypos++]; + + // A one-octet number describing the public-key algorithm used. + this.publicKeyAlgorithm = bytes[mypos++]; + + // An eight-octet number holding the Key ID of the signing key. + this.issuerKeyID = new KeyID(); + this.issuerKeyID.read(bytes.subarray(mypos, mypos + 8)); + mypos += 8; + + // A one-octet number holding a flag showing whether the signature + // is nested. A zero value indicates that the next packet is + // another One-Pass Signature packet that describes another + // signature to be applied to the same message data. + this.flags = bytes[mypos++]; + return this; + } + + /** + * creates a string representation of a one-pass signature packet + * @returns {Uint8Array} A Uint8Array representation of a one-pass signature packet. + */ + write() { + const start = new Uint8Array([VERSION, this.signatureType, this.hashAlgorithm, this.publicKeyAlgorithm]); + + const end = new Uint8Array([this.flags]); + + return util.concatUint8Array([start, this.issuerKeyID.write(), end]); + } + + calculateTrailer(...args) { + return fromAsync(async () => SignaturePacket.prototype.calculateTrailer.apply(await this.correspondingSig, args)); + } + + async verify() { + const correspondingSig = await this.correspondingSig; + if (!correspondingSig || correspondingSig.constructor.tag !== enums.packet.signature) { + throw new Error('Corresponding signature packet missing'); + } + if ( + correspondingSig.signatureType !== this.signatureType || + correspondingSig.hashAlgorithm !== this.hashAlgorithm || + correspondingSig.publicKeyAlgorithm !== this.publicKeyAlgorithm || + !correspondingSig.issuerKeyID.equals(this.issuerKeyID) + ) { + throw new Error('Corresponding signature packet does not match one-pass signature packet'); + } + correspondingSig.hashed = this.hashed; + return correspondingSig.verify.apply(correspondingSig, arguments); + } + } + + OnePassSignaturePacket.prototype.hash = SignaturePacket.prototype.hash; + OnePassSignaturePacket.prototype.toHash = SignaturePacket.prototype.toHash; + OnePassSignaturePacket.prototype.toSign = SignaturePacket.prototype.toSign; + + /** + * Instantiate a new packet given its tag + * @function newPacketFromTag + * @param {module:enums.packet} tag - Property value from {@link module:enums.packet} + * @param {Object} allowedPackets - mapping where keys are allowed packet tags, pointing to their Packet class + * @returns {Object} New packet object with type based on tag + * @throws {Error|UnsupportedError} for disallowed or unknown packets + */ + function newPacketFromTag(tag, allowedPackets) { + if (!allowedPackets[tag]) { + // distinguish between disallowed packets and unknown ones + let packetType; + try { + packetType = enums.read(enums.packet, tag); + } catch (e) { + throw new UnsupportedError(`Unknown packet type with tag: ${tag}`); + } + throw new Error(`Packet not allowed in this context: ${packetType}`); + } + return new allowedPackets[tag](); + } + + /** + * This class represents a list of openpgp packets. + * Take care when iterating over it - the packets themselves + * are stored as numerical indices. + * @extends Array + */ + class PacketList extends Array { + /** + * Parses the given binary data and returns a list of packets. + * Equivalent to calling `read` on an empty PacketList instance. + * @param {Uint8Array | ReadableStream} bytes - binary data to parse + * @param {Object} allowedPackets - mapping where keys are allowed packet tags, pointing to their Packet class + * @param {Object} [config] - full configuration, defaults to openpgp.config + * @returns {PacketList} parsed list of packets + * @throws on parsing errors + * @async + */ + static async fromBinary(bytes, allowedPackets, config = defaultConfig) { + const packets = new PacketList(); + await packets.read(bytes, allowedPackets, config); + return packets; + } + + /** + * Reads a stream of binary data and interprets it as a list of packets. + * @param {Uint8Array | ReadableStream} bytes - binary data to parse + * @param {Object} allowedPackets - mapping where keys are allowed packet tags, pointing to their Packet class + * @param {Object} [config] - full configuration, defaults to openpgp.config + * @throws on parsing errors + * @async + */ + async read(bytes, allowedPackets, config = defaultConfig) { + this.stream = transformPair(bytes, async (readable, writable) => { + const writer = getWriter(writable); + try { + while (true) { + await writer.ready; + const done = await readPackets(readable, async parsed => { + try { + if (parsed.tag === enums.packet.marker || parsed.tag === enums.packet.trust) { + // According to the spec, these packet types should be ignored and not cause parsing errors, even if not esplicitly allowed: + // - Marker packets MUST be ignored when received: https://github.com/openpgpjs/openpgpjs/issues/1145 + // - Trust packets SHOULD be ignored outside of keyrings (unsupported): https://datatracker.ietf.org/doc/html/rfc4880#section-5.10 + return; + } + const packet = newPacketFromTag(parsed.tag, allowedPackets); + packet.packets = new PacketList(); + packet.fromStream = util.isStream(parsed.packet); + await packet.read(parsed.packet, config); + await writer.write(packet); + } catch (e) { + const throwUnsupportedError = !config.ignoreUnsupportedPackets && e instanceof UnsupportedError; + const throwMalformedError = !config.ignoreMalformedPackets && !(e instanceof UnsupportedError); + if (throwUnsupportedError || throwMalformedError || supportsStreaming(parsed.tag)) { + // The packets that support streaming are the ones that contain message data. + // Those are also the ones we want to be more strict about and throw on parse errors + // (since we likely cannot process the message without these packets anyway). + await writer.abort(e); + } + util.printDebugError(e); + } + }); + if (done) { + await writer.ready; + await writer.close(); + return; + } + } + } catch (e) { + await writer.abort(e); + } + }); + + // Wait until first few packets have been read + const reader = getReader(this.stream); + while (true) { + const { done, value } = await reader.read(); + if (!done) { + this.push(value); + } else { + this.stream = null; + } + if (done || supportsStreaming(value.constructor.tag)) { + break; + } + } + reader.releaseLock(); + } + + /** + * Creates a binary representation of openpgp objects contained within the + * class instance. + * @returns {Uint8Array} A Uint8Array containing valid openpgp packets. + */ + write() { + const arr = []; + + for (let i = 0; i < this.length; i++) { + const packetbytes = this[i].write(); + if (util.isStream(packetbytes) && supportsStreaming(this[i].constructor.tag)) { + let buffer = []; + let bufferLength = 0; + const minLength = 512; + arr.push(writeTag(this[i].constructor.tag)); + arr.push(transform(packetbytes, value => { + buffer.push(value); + bufferLength += value.length; + if (bufferLength >= minLength) { + const powerOf2 = Math.min(Math.log(bufferLength) / Math.LN2 | 0, 30); + const chunkSize = 2 ** powerOf2; + const bufferConcat = util.concat([writePartialLength(powerOf2)].concat(buffer)); + buffer = [bufferConcat.subarray(1 + chunkSize)]; + bufferLength = buffer[0].length; + return bufferConcat.subarray(0, 1 + chunkSize); + } + }, () => util.concat([writeSimpleLength(bufferLength)].concat(buffer)))); + } else { + if (util.isStream(packetbytes)) { + let length = 0; + arr.push(transform(clone(packetbytes), value => { + length += value.length; + }, () => writeHeader(this[i].constructor.tag, length))); + } else { + arr.push(writeHeader(this[i].constructor.tag, packetbytes.length)); + } + arr.push(packetbytes); + } + } + + return util.concat(arr); + } + + /** + * Creates a new PacketList with all packets matching the given tag(s) + * @param {...module:enums.packet} tags - packet tags to look for + * @returns {PacketList} + */ + filterByTag(...tags) { + const filtered = new PacketList(); + + const handle = tag => packetType => tag === packetType; + + for (let i = 0; i < this.length; i++) { + if (tags.some(handle(this[i].constructor.tag))) { + filtered.push(this[i]); + } + } + + return filtered; + } + + /** + * Traverses packet list and returns first packet with matching tag + * @param {module:enums.packet} tag - The packet tag + * @returns {Packet|undefined} + */ + findPacket(tag) { + return this.find(packet => packet.constructor.tag === tag); + } + + /** + * Find indices of packets with the given tag(s) + * @param {...module:enums.packet} tags - packet tags to look for + * @returns {Integer[]} packet indices + */ + indexOfTag(...tags) { + const tagIndex = []; + const that = this; + + const handle = tag => packetType => tag === packetType; + + for (let i = 0; i < this.length; i++) { + if (tags.some(handle(that[i].constructor.tag))) { + tagIndex.push(i); + } + } + return tagIndex; + } + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + // A Compressed Data packet can contain the following packet types + const allowedPackets = /*#__PURE__*/ util.constructAllowedPackets([ + LiteralDataPacket, + OnePassSignaturePacket, + SignaturePacket + ]); + + /** + * Implementation of the Compressed Data Packet (Tag 8) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.6|RFC4880 5.6}: + * The Compressed Data packet contains compressed data. Typically, + * this packet is found as the contents of an encrypted packet, or following + * a Signature or One-Pass Signature packet, and contains a literal data packet. + */ + class CompressedDataPacket { + static get tag() { + return enums.packet.compressedData; + } + + /** + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + constructor(config = defaultConfig) { + /** + * List of packets + * @type {PacketList} + */ + this.packets = null; + /** + * Compression algorithm + * @type {enums.compression} + */ + this.algorithm = config.preferredCompressionAlgorithm; + + /** + * Compressed packet data + * @type {Uint8Array | ReadableStream} + */ + this.compressed = null; + + /** + * zip/zlib compression level, between 1 and 9 + */ + this.deflateLevel = config.deflateLevel; + } + + /** + * Parsing function for the packet. + * @param {Uint8Array | ReadableStream} bytes - Payload of a tag 8 packet + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + async read(bytes, config = defaultConfig) { + await parse(bytes, async reader => { + + // One octet that gives the algorithm used to compress the packet. + this.algorithm = await reader.readByte(); + + // Compressed data, which makes up the remainder of the packet. + this.compressed = reader.remainder(); + + await this.decompress(config); + }); + } + + + /** + * Return the compressed packet. + * @returns {Uint8Array | ReadableStream} Binary compressed packet. + */ + write() { + if (this.compressed === null) { + this.compress(); + } + + return util.concat([new Uint8Array([this.algorithm]), this.compressed]); + } + + + /** + * Decompression method for decompressing the compressed data + * read by read_packet + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + async decompress(config = defaultConfig) { + const compressionName = enums.read(enums.compression, this.algorithm); + const decompressionFn = decompress_fns[compressionName]; + if (!decompressionFn) { + throw new Error(`${compressionName} decompression not supported`); + } + + this.packets = await PacketList.fromBinary(decompressionFn(this.compressed), allowedPackets, config); + } + + /** + * Compress the packet data (member decompressedData) + */ + compress() { + const compressionName = enums.read(enums.compression, this.algorithm); + const compressionFn = compress_fns[compressionName]; + if (!compressionFn) { + throw new Error(`${compressionName} compression not supported`); + } + + this.compressed = compressionFn(this.packets.write(), this.deflateLevel); + } + } + + ////////////////////////// + // // + // Helper functions // + // // + ////////////////////////// + + + const nodeZlib = util.getNodeZlib(); + + function uncompressed(data) { + return data; + } + + function node_zlib(func, create, options = {}) { + return function (data) { + if (!util.isStream(data) || isArrayStream(data)) { + return fromAsync(() => readToEnd(data).then(data => { + return new Promise((resolve, reject) => { + func(data, options, (err, result) => { + if (err) return reject(err); + resolve(result); + }); + }); + })); + } + return nodeToWeb(webToNode(data).pipe(create(options))); + }; + } + + function pako_zlib(constructor, options = {}) { + return function(data) { + const obj = new constructor(options); + return transform(data, value => { + if (value.length) { + obj.push(value, Z_SYNC_FLUSH); + return obj.result; + } + }, () => { + if (constructor === Deflate) { + obj.push([], Z_FINISH); + return obj.result; + } + }); + }; + } + + function bzip2(func) { + return function(data) { + return fromAsync(async () => func(await readToEnd(data))); + }; + } + + const compress_fns = nodeZlib ? { + zip: /*#__PURE__*/ (compressed, level) => node_zlib(nodeZlib.deflateRaw, nodeZlib.createDeflateRaw, { level })(compressed), + zlib: /*#__PURE__*/ (compressed, level) => node_zlib(nodeZlib.deflate, nodeZlib.createDeflate, { level })(compressed) + } : { + zip: /*#__PURE__*/ (compressed, level) => pako_zlib(Deflate, { raw: true, level })(compressed), + zlib: /*#__PURE__*/ (compressed, level) => pako_zlib(Deflate, { level })(compressed) + }; + + const decompress_fns = nodeZlib ? { + uncompressed: uncompressed, + zip: /*#__PURE__*/ node_zlib(nodeZlib.inflateRaw, nodeZlib.createInflateRaw), + zlib: /*#__PURE__*/ node_zlib(nodeZlib.inflate, nodeZlib.createInflate), + bzip2: /*#__PURE__*/ bzip2(lib_4) + } : { + uncompressed: uncompressed, + zip: /*#__PURE__*/ pako_zlib(Inflate, { raw: true }), + zlib: /*#__PURE__*/ pako_zlib(Inflate), + bzip2: /*#__PURE__*/ bzip2(lib_4) + }; + + // GPG4Browsers - An OpenPGP implementation in javascript + + // A SEIP packet can contain the following packet types + const allowedPackets$1 = /*#__PURE__*/ util.constructAllowedPackets([ + LiteralDataPacket, + CompressedDataPacket, + OnePassSignaturePacket, + SignaturePacket + ]); + + const VERSION$1 = 1; // A one-octet version number of the data packet. + + /** + * Implementation of the Sym. Encrypted Integrity Protected Data Packet (Tag 18) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.13|RFC4880 5.13}: + * The Symmetrically Encrypted Integrity Protected Data packet is + * a variant of the Symmetrically Encrypted Data packet. It is a new feature + * created for OpenPGP that addresses the problem of detecting a modification to + * encrypted data. It is used in combination with a Modification Detection Code + * packet. + */ + class SymEncryptedIntegrityProtectedDataPacket { + static get tag() { + return enums.packet.symEncryptedIntegrityProtectedData; + } + + constructor() { + this.version = VERSION$1; + this.encrypted = null; + this.packets = null; + } + + async read(bytes) { + await parse(bytes, async reader => { + const version = await reader.readByte(); + // - A one-octet version number. The only currently defined value is 1. + if (version !== VERSION$1) { + throw new UnsupportedError(`Version ${version} of the SEIP packet is unsupported.`); + } + + // - Encrypted data, the output of the selected symmetric-key cipher + // operating in Cipher Feedback mode with shift amount equal to the + // block size of the cipher (CFB-n where n is the block size). + this.encrypted = reader.remainder(); + }); + } + + write() { + return util.concat([new Uint8Array([VERSION$1]), this.encrypted]); + } + + /** + * Encrypt the payload in the packet. + * @param {enums.symmetric} sessionKeyAlgorithm - The symmetric encryption algorithm to use + * @param {Uint8Array} key - The key of cipher blocksize length to be used + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} + * @throws {Error} on encryption failure + * @async + */ + async encrypt(sessionKeyAlgorithm, key, config = defaultConfig) { + const { blockSize } = mod.getCipher(sessionKeyAlgorithm); + + let bytes = this.packets.write(); + if (isArrayStream(bytes)) bytes = await readToEnd(bytes); + const prefix = await mod.getPrefixRandom(sessionKeyAlgorithm); + const mdc = new Uint8Array([0xD3, 0x14]); // modification detection code packet + + const tohash = util.concat([prefix, bytes, mdc]); + const hash = await mod.hash.sha1(passiveClone(tohash)); + const plaintext = util.concat([tohash, hash]); + + this.encrypted = await mod.mode.cfb.encrypt(sessionKeyAlgorithm, key, plaintext, new Uint8Array(blockSize), config); + return true; + } + + /** + * Decrypts the encrypted data contained in the packet. + * @param {enums.symmetric} sessionKeyAlgorithm - The selected symmetric encryption algorithm to be used + * @param {Uint8Array} key - The key of cipher blocksize length to be used + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} + * @throws {Error} on decryption failure + * @async + */ + async decrypt(sessionKeyAlgorithm, key, config = defaultConfig) { + const { blockSize } = mod.getCipher(sessionKeyAlgorithm); + let encrypted = clone(this.encrypted); + if (isArrayStream(encrypted)) encrypted = await readToEnd(encrypted); + const decrypted = await mod.mode.cfb.decrypt(sessionKeyAlgorithm, key, encrypted, new Uint8Array(blockSize)); + + // there must be a modification detection code packet as the + // last packet and everything gets hashed except the hash itself + const realHash = slice(passiveClone(decrypted), -20); + const tohash = slice(decrypted, 0, -20); + const verifyHash = Promise.all([ + readToEnd(await mod.hash.sha1(passiveClone(tohash))), + readToEnd(realHash) + ]).then(([hash, mdc]) => { + if (!util.equalsUint8Array(hash, mdc)) { + throw new Error('Modification detected.'); + } + return new Uint8Array(); + }); + const bytes = slice(tohash, blockSize + 2); // Remove random prefix + let packetbytes = slice(bytes, 0, -2); // Remove MDC packet + packetbytes = concat([packetbytes, fromAsync(() => verifyHash)]); + if (!util.isStream(encrypted) || !config.allowUnauthenticatedStream) { + packetbytes = await readToEnd(packetbytes); + } + this.packets = await PacketList.fromBinary(packetbytes, allowedPackets$1, config); + return true; + } + } + + // OpenPGP.js - An OpenPGP implementation in javascript + + // An AEAD-encrypted Data packet can contain the following packet types + const allowedPackets$2 = /*#__PURE__*/ util.constructAllowedPackets([ + LiteralDataPacket, + CompressedDataPacket, + OnePassSignaturePacket, + SignaturePacket + ]); + + const VERSION$2 = 1; // A one-octet version number of the data packet. + + /** + * Implementation of the Symmetrically Encrypted Authenticated Encryption with + * Additional Data (AEAD) Protected Data Packet + * + * {@link https://tools.ietf.org/html/draft-ford-openpgp-format-00#section-2.1}: + * AEAD Protected Data Packet + */ + class AEADEncryptedDataPacket { + static get tag() { + return enums.packet.aeadEncryptedData; + } + + constructor() { + this.version = VERSION$2; + /** @type {enums.symmetric} */ + this.cipherAlgorithm = null; + /** @type {enums.aead} */ + this.aeadAlgorithm = enums.aead.eax; + this.chunkSizeByte = null; + this.iv = null; + this.encrypted = null; + this.packets = null; + } + + /** + * Parse an encrypted payload of bytes in the order: version, IV, ciphertext (see specification) + * @param {Uint8Array | ReadableStream} bytes + * @throws {Error} on parsing failure + */ + async read(bytes) { + await parse(bytes, async reader => { + const version = await reader.readByte(); + if (version !== VERSION$2) { // The only currently defined value is 1. + throw new UnsupportedError(`Version ${version} of the AEAD-encrypted data packet is not supported.`); + } + this.cipherAlgorithm = await reader.readByte(); + this.aeadAlgorithm = await reader.readByte(); + this.chunkSizeByte = await reader.readByte(); + + const mode = mod.getAEADMode(this.aeadAlgorithm); + this.iv = await reader.readBytes(mode.ivLength); + this.encrypted = reader.remainder(); + }); + } + + /** + * Write the encrypted payload of bytes in the order: version, IV, ciphertext (see specification) + * @returns {Uint8Array | ReadableStream} The encrypted payload. + */ + write() { + return util.concat([new Uint8Array([this.version, this.cipherAlgorithm, this.aeadAlgorithm, this.chunkSizeByte]), this.iv, this.encrypted]); + } + + /** + * Decrypt the encrypted payload. + * @param {enums.symmetric} sessionKeyAlgorithm - The session key's cipher algorithm + * @param {Uint8Array} key - The session key used to encrypt the payload + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if decryption was not successful + * @async + */ + async decrypt(sessionKeyAlgorithm, key, config = defaultConfig) { + this.packets = await PacketList.fromBinary( + await this.crypt('decrypt', key, clone(this.encrypted)), + allowedPackets$2, + config + ); + } + + /** + * Encrypt the packet payload. + * @param {enums.symmetric} sessionKeyAlgorithm - The session key's cipher algorithm + * @param {Uint8Array} key - The session key used to encrypt the payload + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if encryption was not successful + * @async + */ + async encrypt(sessionKeyAlgorithm, key, config = defaultConfig) { + this.cipherAlgorithm = sessionKeyAlgorithm; + + const { ivLength } = mod.getAEADMode(this.aeadAlgorithm); + this.iv = await mod.random.getRandomBytes(ivLength); // generate new random IV + this.chunkSizeByte = config.aeadChunkSizeByte; + const data = this.packets.write(); + this.encrypted = await this.crypt('encrypt', key, data); + } + + /** + * En/decrypt the payload. + * @param {encrypt|decrypt} fn - Whether to encrypt or decrypt + * @param {Uint8Array} key - The session key used to en/decrypt the payload + * @param {Uint8Array | ReadableStream} data - The data to en/decrypt + * @returns {Promise>} + * @async + */ + async crypt(fn, key, data) { + const mode = mod.getAEADMode(this.aeadAlgorithm); + const modeInstance = await mode(this.cipherAlgorithm, key); + const tagLengthIfDecrypting = fn === 'decrypt' ? mode.tagLength : 0; + const tagLengthIfEncrypting = fn === 'encrypt' ? mode.tagLength : 0; + const chunkSize = 2 ** (this.chunkSizeByte + 6) + tagLengthIfDecrypting; // ((uint64_t)1 << (c + 6)) + const adataBuffer = new ArrayBuffer(21); + const adataArray = new Uint8Array(adataBuffer, 0, 13); + const adataTagArray = new Uint8Array(adataBuffer); + const adataView = new DataView(adataBuffer); + const chunkIndexArray = new Uint8Array(adataBuffer, 5, 8); + adataArray.set([0xC0 | AEADEncryptedDataPacket.tag, this.version, this.cipherAlgorithm, this.aeadAlgorithm, this.chunkSizeByte], 0); + let chunkIndex = 0; + let latestPromise = Promise.resolve(); + let cryptedBytes = 0; + let queuedBytes = 0; + const iv = this.iv; + return transformPair(data, async (readable, writable) => { + if (util.isStream(readable) !== 'array') { + const buffer = new TransformStream({}, { + highWaterMark: util.getHardwareConcurrency() * 2 ** (this.chunkSizeByte + 6), + size: array => array.length + }); + pipe(buffer.readable, writable); + writable = buffer.writable; + } + const reader = getReader(readable); + const writer = getWriter(writable); + try { + while (true) { + let chunk = await reader.readBytes(chunkSize + tagLengthIfDecrypting) || new Uint8Array(); + const finalChunk = chunk.subarray(chunk.length - tagLengthIfDecrypting); + chunk = chunk.subarray(0, chunk.length - tagLengthIfDecrypting); + let cryptedPromise; + let done; + if (!chunkIndex || chunk.length) { + reader.unshift(finalChunk); + cryptedPromise = modeInstance[fn](chunk, mode.getNonce(iv, chunkIndexArray), adataArray); + queuedBytes += chunk.length - tagLengthIfDecrypting + tagLengthIfEncrypting; + } else { + // After the last chunk, we either encrypt a final, empty + // data chunk to get the final authentication tag or + // validate that final authentication tag. + adataView.setInt32(13 + 4, cryptedBytes); // Should be setInt64(13, ...) + cryptedPromise = modeInstance[fn](finalChunk, mode.getNonce(iv, chunkIndexArray), adataTagArray); + queuedBytes += tagLengthIfEncrypting; + done = true; + } + cryptedBytes += chunk.length - tagLengthIfDecrypting; + // eslint-disable-next-line no-loop-func + latestPromise = latestPromise.then(() => cryptedPromise).then(async crypted => { + await writer.ready; + await writer.write(crypted); + queuedBytes -= crypted.length; + }).catch(err => writer.abort(err)); + if (done || queuedBytes > writer.desiredSize) { + await latestPromise; // Respect backpressure + } + if (!done) { + adataView.setInt32(5 + 4, ++chunkIndex); // Should be setInt64(5, ...) + } else { + await writer.close(); + break; + } + } + } catch (e) { + await writer.abort(e); + } + }); + } + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + const VERSION$3 = 3; + + /** + * Public-Key Encrypted Session Key Packets (Tag 1) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.1|RFC4880 5.1}: + * A Public-Key Encrypted Session Key packet holds the session key + * used to encrypt a message. Zero or more Public-Key Encrypted Session Key + * packets and/or Symmetric-Key Encrypted Session Key packets may precede a + * Symmetrically Encrypted Data Packet, which holds an encrypted message. The + * message is encrypted with the session key, and the session key is itself + * encrypted and stored in the Encrypted Session Key packet(s). The + * Symmetrically Encrypted Data Packet is preceded by one Public-Key Encrypted + * Session Key packet for each OpenPGP key to which the message is encrypted. + * The recipient of the message finds a session key that is encrypted to their + * public key, decrypts the session key, and then uses the session key to + * decrypt the message. + */ + class PublicKeyEncryptedSessionKeyPacket { + static get tag() { + return enums.packet.publicKeyEncryptedSessionKey; + } + + constructor() { + this.version = 3; + + this.publicKeyID = new KeyID(); + this.publicKeyAlgorithm = null; + + this.sessionKey = null; + /** + * Algorithm to encrypt the message with + * @type {enums.symmetric} + */ + this.sessionKeyAlgorithm = null; + + /** @type {Object} */ + this.encrypted = {}; + } + + /** + * Parsing function for a publickey encrypted session key packet (tag 1). + * + * @param {Uint8Array} bytes - Payload of a tag 1 packet + */ + read(bytes) { + this.version = bytes[0]; + if (this.version !== VERSION$3) { + throw new UnsupportedError(`Version ${this.version} of the PKESK packet is unsupported.`); + } + this.publicKeyID.read(bytes.subarray(1, bytes.length)); + this.publicKeyAlgorithm = bytes[9]; + this.encrypted = mod.parseEncSessionKeyParams(this.publicKeyAlgorithm, bytes.subarray(10)); + } + + /** + * Create a binary representation of a tag 1 packet + * + * @returns {Uint8Array} The Uint8Array representation. + */ + write() { + const arr = [ + new Uint8Array([this.version]), + this.publicKeyID.write(), + new Uint8Array([this.publicKeyAlgorithm]), + mod.serializeParams(this.publicKeyAlgorithm, this.encrypted) + ]; + + return util.concatUint8Array(arr); + } + + /** + * Encrypt session key packet + * @param {PublicKeyPacket} key - Public key + * @throws {Error} if encryption failed + * @async + */ + async encrypt(key) { + const data = util.concatUint8Array([ + new Uint8Array([enums.write(enums.symmetric, this.sessionKeyAlgorithm)]), + this.sessionKey, + util.writeChecksum(this.sessionKey) + ]); + const algo = enums.write(enums.publicKey, this.publicKeyAlgorithm); + this.encrypted = await mod.publicKeyEncrypt( + algo, key.publicParams, data, key.getFingerprintBytes()); + } + + /** + * Decrypts the session key (only for public key encrypted session key packets (tag 1) + * @param {SecretKeyPacket} key - decrypted private key + * @param {Object} [randomSessionKey] - Bogus session key to use in case of sensitive decryption error, or if the decrypted session key is of a different type/size. + * This is needed for constant-time processing. Expected object of the form: { sessionKey: Uint8Array, sessionKeyAlgorithm: enums.symmetric } + * @throws {Error} if decryption failed, unless `randomSessionKey` is given + * @async + */ + async decrypt(key, randomSessionKey) { + // check that session key algo matches the secret key algo + if (this.publicKeyAlgorithm !== key.algorithm) { + throw new Error('Decryption error'); + } + + const randomPayload = randomSessionKey ? util.concatUint8Array([ + new Uint8Array([randomSessionKey.sessionKeyAlgorithm]), + randomSessionKey.sessionKey, + util.writeChecksum(randomSessionKey.sessionKey) + ]) : null; + const decoded = await mod.publicKeyDecrypt(this.publicKeyAlgorithm, key.publicParams, key.privateParams, this.encrypted, key.getFingerprintBytes(), randomPayload); + const symmetricAlgoByte = decoded[0]; + const sessionKey = decoded.subarray(1, decoded.length - 2); + const checksum = decoded.subarray(decoded.length - 2); + const computedChecksum = util.writeChecksum(sessionKey); + const isValidChecksum = computedChecksum[0] === checksum[0] & computedChecksum[1] === checksum[1]; + + if (randomSessionKey) { + // We must not leak info about the validity of the decrypted checksum or cipher algo. + // The decrypted session key must be of the same algo and size as the random session key, otherwise we discard it and use the random data. + const isValidPayload = isValidChecksum & symmetricAlgoByte === randomSessionKey.sessionKeyAlgorithm & sessionKey.length === randomSessionKey.sessionKey.length; + this.sessionKeyAlgorithm = util.selectUint8(isValidPayload, symmetricAlgoByte, randomSessionKey.sessionKeyAlgorithm); + this.sessionKey = util.selectUint8Array(isValidPayload, sessionKey, randomSessionKey.sessionKey); + + } else { + const isValidPayload = isValidChecksum && enums.read(enums.symmetric, symmetricAlgoByte); + if (isValidPayload) { + this.sessionKey = sessionKey; + this.sessionKeyAlgorithm = symmetricAlgoByte; + } else { + throw new Error('Decryption error'); + } + } + } + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + class S2K { + /** + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + constructor(config = defaultConfig) { + /** + * Hash function identifier, or 0 for gnu-dummy keys + * @type {module:enums.hash | 0} + */ + this.algorithm = enums.hash.sha256; + /** + * enums.s2k identifier or 'gnu-dummy' + * @type {String} + */ + this.type = 'iterated'; + /** @type {Integer} */ + this.c = config.s2kIterationCountByte; + /** Eight bytes of salt in a binary string. + * @type {Uint8Array} + */ + this.salt = null; + } + + getCount() { + // Exponent bias, defined in RFC4880 + const expbias = 6; + + return (16 + (this.c & 15)) << ((this.c >> 4) + expbias); + } + + /** + * Parsing function for a string-to-key specifier ({@link https://tools.ietf.org/html/rfc4880#section-3.7|RFC 4880 3.7}). + * @param {Uint8Array} bytes - Payload of string-to-key specifier + * @returns {Integer} Actual length of the object. + */ + read(bytes) { + let i = 0; + this.type = enums.read(enums.s2k, bytes[i++]); + this.algorithm = bytes[i++]; + + switch (this.type) { + case 'simple': + break; + + case 'salted': + this.salt = bytes.subarray(i, i + 8); + i += 8; + break; + + case 'iterated': + this.salt = bytes.subarray(i, i + 8); + i += 8; + + // Octet 10: count, a one-octet, coded value + this.c = bytes[i++]; + break; + + case 'gnu': + if (util.uint8ArrayToString(bytes.subarray(i, i + 3)) === 'GNU') { + i += 3; // GNU + const gnuExtType = 1000 + bytes[i++]; + if (gnuExtType === 1001) { + this.type = 'gnu-dummy'; + // GnuPG extension mode 1001 -- don't write secret key at all + } else { + throw new Error('Unknown s2k gnu protection mode.'); + } + } else { + throw new Error('Unknown s2k type.'); + } + break; + + default: + throw new Error('Unknown s2k type.'); + } + + return i; + } + + /** + * Serializes s2k information + * @returns {Uint8Array} Binary representation of s2k. + */ + write() { + if (this.type === 'gnu-dummy') { + return new Uint8Array([101, 0, ...util.stringToUint8Array('GNU'), 1]); + } + const arr = [new Uint8Array([enums.write(enums.s2k, this.type), this.algorithm])]; + + switch (this.type) { + case 'simple': + break; + case 'salted': + arr.push(this.salt); + break; + case 'iterated': + arr.push(this.salt); + arr.push(new Uint8Array([this.c])); + break; + case 'gnu': + throw new Error('GNU s2k type not supported.'); + default: + throw new Error('Unknown s2k type.'); + } + + return util.concatUint8Array(arr); + } + + /** + * Produces a key using the specified passphrase and the defined + * hashAlgorithm + * @param {String} passphrase - Passphrase containing user input + * @returns {Promise} Produced key with a length corresponding to. + * hashAlgorithm hash length + * @async + */ + async produceKey(passphrase, numBytes) { + passphrase = util.encodeUTF8(passphrase); + + const arr = []; + let rlength = 0; + + let prefixlen = 0; + while (rlength < numBytes) { + let toHash; + switch (this.type) { + case 'simple': + toHash = util.concatUint8Array([new Uint8Array(prefixlen), passphrase]); + break; + case 'salted': + toHash = util.concatUint8Array([new Uint8Array(prefixlen), this.salt, passphrase]); + break; + case 'iterated': { + const data = util.concatUint8Array([this.salt, passphrase]); + let datalen = data.length; + const count = Math.max(this.getCount(), datalen); + toHash = new Uint8Array(prefixlen + count); + toHash.set(data, prefixlen); + for (let pos = prefixlen + datalen; pos < count; pos += datalen, datalen *= 2) { + toHash.copyWithin(pos, prefixlen, pos); + } + break; + } + case 'gnu': + throw new Error('GNU s2k type not supported.'); + default: + throw new Error('Unknown s2k type.'); + } + const result = await mod.hash.digest(this.algorithm, toHash); + arr.push(result); + rlength += result.length; + prefixlen++; + } + + return util.concatUint8Array(arr).subarray(0, numBytes); + } + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + /** + * Symmetric-Key Encrypted Session Key Packets (Tag 3) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.3|RFC4880 5.3}: + * The Symmetric-Key Encrypted Session Key packet holds the + * symmetric-key encryption of a session key used to encrypt a message. + * Zero or more Public-Key Encrypted Session Key packets and/or + * Symmetric-Key Encrypted Session Key packets may precede a + * Symmetrically Encrypted Data packet that holds an encrypted message. + * The message is encrypted with a session key, and the session key is + * itself encrypted and stored in the Encrypted Session Key packet or + * the Symmetric-Key Encrypted Session Key packet. + */ + class SymEncryptedSessionKeyPacket { + static get tag() { + return enums.packet.symEncryptedSessionKey; + } + + /** + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + constructor(config = defaultConfig) { + this.version = config.aeadProtect ? 5 : 4; + this.sessionKey = null; + /** + * Algorithm to encrypt the session key with + * @type {enums.symmetric} + */ + this.sessionKeyEncryptionAlgorithm = null; + /** + * Algorithm to encrypt the message with + * @type {enums.symmetric} + */ + this.sessionKeyAlgorithm = enums.symmetric.aes256; + /** + * AEAD mode to encrypt the session key with (if AEAD protection is enabled) + * @type {enums.aead} + */ + this.aeadAlgorithm = enums.write(enums.aead, config.preferredAEADAlgorithm); + this.encrypted = null; + this.s2k = null; + this.iv = null; + } + + /** + * Parsing function for a symmetric encrypted session key packet (tag 3). + * + * @param {Uint8Array} bytes - Payload of a tag 3 packet + */ + read(bytes) { + let offset = 0; + + // A one-octet version number. The only currently defined version is 4. + this.version = bytes[offset++]; + if (this.version !== 4 && this.version !== 5) { + throw new UnsupportedError(`Version ${this.version} of the SKESK packet is unsupported.`); + } + + // A one-octet number describing the symmetric algorithm used. + const algo = bytes[offset++]; + + if (this.version === 5) { + // A one-octet AEAD algorithm. + this.aeadAlgorithm = bytes[offset++]; + } + + // A string-to-key (S2K) specifier, length as defined above. + this.s2k = new S2K(); + offset += this.s2k.read(bytes.subarray(offset, bytes.length)); + + if (this.version === 5) { + const mode = mod.getAEADMode(this.aeadAlgorithm); + + // A starting initialization vector of size specified by the AEAD + // algorithm. + this.iv = bytes.subarray(offset, offset += mode.ivLength); + } + + // The encrypted session key itself, which is decrypted with the + // string-to-key object. This is optional in version 4. + if (this.version === 5 || offset < bytes.length) { + this.encrypted = bytes.subarray(offset, bytes.length); + this.sessionKeyEncryptionAlgorithm = algo; + } else { + this.sessionKeyAlgorithm = algo; + } + } + + /** + * Create a binary representation of a tag 3 packet + * + * @returns {Uint8Array} The Uint8Array representation. + */ + write() { + const algo = this.encrypted === null ? + this.sessionKeyAlgorithm : + this.sessionKeyEncryptionAlgorithm; + + let bytes; + + if (this.version === 5) { + bytes = util.concatUint8Array([new Uint8Array([this.version, algo, this.aeadAlgorithm]), this.s2k.write(), this.iv, this.encrypted]); + } else { + bytes = util.concatUint8Array([new Uint8Array([this.version, algo]), this.s2k.write()]); + + if (this.encrypted !== null) { + bytes = util.concatUint8Array([bytes, this.encrypted]); + } + } + + return bytes; + } + + /** + * Decrypts the session key with the given passphrase + * @param {String} passphrase - The passphrase in string form + * @throws {Error} if decryption was not successful + * @async + */ + async decrypt(passphrase) { + const algo = this.sessionKeyEncryptionAlgorithm !== null ? + this.sessionKeyEncryptionAlgorithm : + this.sessionKeyAlgorithm; + + const { blockSize, keySize } = mod.getCipher(algo); + const key = await this.s2k.produceKey(passphrase, keySize); + + if (this.version === 5) { + const mode = mod.getAEADMode(this.aeadAlgorithm); + const adata = new Uint8Array([0xC0 | SymEncryptedSessionKeyPacket.tag, this.version, this.sessionKeyEncryptionAlgorithm, this.aeadAlgorithm]); + const modeInstance = await mode(algo, key); + this.sessionKey = await modeInstance.decrypt(this.encrypted, this.iv, adata); + } else if (this.encrypted !== null) { + const decrypted = await mod.mode.cfb.decrypt(algo, key, this.encrypted, new Uint8Array(blockSize)); + + this.sessionKeyAlgorithm = enums.write(enums.symmetric, decrypted[0]); + this.sessionKey = decrypted.subarray(1, decrypted.length); + } else { + this.sessionKey = key; + } + } + + /** + * Encrypts the session key with the given passphrase + * @param {String} passphrase - The passphrase in string form + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if encryption was not successful + * @async + */ + async encrypt(passphrase, config = defaultConfig) { + const algo = this.sessionKeyEncryptionAlgorithm !== null ? + this.sessionKeyEncryptionAlgorithm : + this.sessionKeyAlgorithm; + + this.sessionKeyEncryptionAlgorithm = algo; + + this.s2k = new S2K(config); + this.s2k.salt = await mod.random.getRandomBytes(8); + + const { blockSize, keySize } = mod.getCipher(algo); + const encryptionKey = await this.s2k.produceKey(passphrase, keySize); + + if (this.sessionKey === null) { + this.sessionKey = await mod.generateSessionKey(this.sessionKeyAlgorithm); + } + + if (this.version === 5) { + const mode = mod.getAEADMode(this.aeadAlgorithm); + this.iv = await mod.random.getRandomBytes(mode.ivLength); // generate new random IV + const associatedData = new Uint8Array([0xC0 | SymEncryptedSessionKeyPacket.tag, this.version, this.sessionKeyEncryptionAlgorithm, this.aeadAlgorithm]); + const modeInstance = await mode(algo, encryptionKey); + this.encrypted = await modeInstance.encrypt(this.sessionKey, this.iv, associatedData); + } else { + const toEncrypt = util.concatUint8Array([ + new Uint8Array([this.sessionKeyAlgorithm]), + this.sessionKey + ]); + this.encrypted = await mod.mode.cfb.encrypt(algo, encryptionKey, toEncrypt, new Uint8Array(blockSize), config); + } + } + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + /** + * Implementation of the Key Material Packet (Tag 5,6,7,14) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.5|RFC4480 5.5}: + * A key material packet contains all the information about a public or + * private key. There are four variants of this packet type, and two + * major versions. + * + * A Public-Key packet starts a series of packets that forms an OpenPGP + * key (sometimes called an OpenPGP certificate). + */ + class PublicKeyPacket { + static get tag() { + return enums.packet.publicKey; + } + + /** + * @param {Date} [date] - Creation date + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + constructor(date = new Date(), config = defaultConfig) { + /** + * Packet version + * @type {Integer} + */ + this.version = config.v5Keys ? 5 : 4; + /** + * Key creation date. + * @type {Date} + */ + this.created = util.normalizeDate(date); + /** + * Public key algorithm. + * @type {enums.publicKey} + */ + this.algorithm = null; + /** + * Algorithm specific public params + * @type {Object} + */ + this.publicParams = null; + /** + * Time until expiration in days (V3 only) + * @type {Integer} + */ + this.expirationTimeV3 = 0; + /** + * Fingerprint bytes + * @type {Uint8Array} + */ + this.fingerprint = null; + /** + * KeyID + * @type {module:type/keyid~KeyID} + */ + this.keyID = null; + } + + /** + * Create a PublicKeyPacket from a SecretKeyPacket + * @param {SecretKeyPacket} secretKeyPacket - key packet to convert + * @returns {PublicKeyPacket} public key packet + * @static + */ + static fromSecretKeyPacket(secretKeyPacket) { + const keyPacket = new PublicKeyPacket(); + const { version, created, algorithm, publicParams, keyID, fingerprint } = secretKeyPacket; + keyPacket.version = version; + keyPacket.created = created; + keyPacket.algorithm = algorithm; + keyPacket.publicParams = publicParams; + keyPacket.keyID = keyID; + keyPacket.fingerprint = fingerprint; + return keyPacket; + } + + /** + * Internal Parser for public keys as specified in {@link https://tools.ietf.org/html/rfc4880#section-5.5.2|RFC 4880 section 5.5.2 Public-Key Packet Formats} + * @param {Uint8Array} bytes - Input array to read the packet from + * @returns {Object} This object with attributes set by the parser + * @async + */ + async read(bytes) { + let pos = 0; + // A one-octet version number (3, 4 or 5). + this.version = bytes[pos++]; + + if (this.version === 4 || this.version === 5) { + // - A four-octet number denoting the time that the key was created. + this.created = util.readDate(bytes.subarray(pos, pos + 4)); + pos += 4; + + // - A one-octet number denoting the public-key algorithm of this key. + this.algorithm = bytes[pos++]; + + if (this.version === 5) { + // - A four-octet scalar octet count for the following key material. + pos += 4; + } + + // - A series of values comprising the key material. + try { + const { read, publicParams } = mod.parsePublicKeyParams(this.algorithm, bytes.subarray(pos)); + this.publicParams = publicParams; + pos += read; + } catch (err) { + throw new Error('Error reading MPIs'); + } + + // we set the fingerprint and keyID already to make it possible to put together the key packets directly in the Key constructor + await this.computeFingerprintAndKeyID(); + return pos; + } + throw new UnsupportedError(`Version ${this.version} of the key packet is unsupported.`); + } + + /** + * Creates an OpenPGP public key packet for the given key. + * @returns {Uint8Array} Bytes encoding the public key OpenPGP packet. + */ + write() { + const arr = []; + // Version + arr.push(new Uint8Array([this.version])); + arr.push(util.writeDate(this.created)); + // A one-octet number denoting the public-key algorithm of this key + arr.push(new Uint8Array([this.algorithm])); + + const params = mod.serializeParams(this.algorithm, this.publicParams); + if (this.version === 5) { + // A four-octet scalar octet count for the following key material + arr.push(util.writeNumber(params.length, 4)); + } + // Algorithm-specific params + arr.push(params); + return util.concatUint8Array(arr); + } + + /** + * Write packet in order to be hashed; either for a signature or a fingerprint + * @param {Integer} version - target version of signature or key + */ + writeForHash(version) { + const bytes = this.writePublicKey(); + + if (version === 5) { + return util.concatUint8Array([new Uint8Array([0x9A]), util.writeNumber(bytes.length, 4), bytes]); + } + return util.concatUint8Array([new Uint8Array([0x99]), util.writeNumber(bytes.length, 2), bytes]); + } + + /** + * Check whether secret-key data is available in decrypted form. Returns null for public keys. + * @returns {Boolean|null} + */ + isDecrypted() { + return null; + } + + /** + * Returns the creation time of the key + * @returns {Date} + */ + getCreationTime() { + return this.created; + } + + /** + * Return the key ID of the key + * @returns {module:type/keyid~KeyID} The 8-byte key ID + */ + getKeyID() { + return this.keyID; + } + + /** + * Computes and set the key ID and fingerprint of the key + * @async + */ + async computeFingerprintAndKeyID() { + await this.computeFingerprint(); + this.keyID = new KeyID(); + + if (this.version === 5) { + this.keyID.read(this.fingerprint.subarray(0, 8)); + } else if (this.version === 4) { + this.keyID.read(this.fingerprint.subarray(12, 20)); + } else { + throw new Error('Unsupported key version'); + } + } + + /** + * Computes and set the fingerprint of the key + */ + async computeFingerprint() { + const toHash = this.writeForHash(this.version); + + if (this.version === 5) { + this.fingerprint = await mod.hash.sha256(toHash); + } else if (this.version === 4) { + this.fingerprint = await mod.hash.sha1(toHash); + } else { + throw new Error('Unsupported key version'); + } + } + + /** + * Returns the fingerprint of the key, as an array of bytes + * @returns {Uint8Array} A Uint8Array containing the fingerprint + */ + getFingerprintBytes() { + return this.fingerprint; + } + + /** + * Calculates and returns the fingerprint of the key, as a string + * @returns {String} A string containing the fingerprint in lowercase hex + */ + getFingerprint() { + return util.uint8ArrayToHex(this.getFingerprintBytes()); + } + + /** + * Calculates whether two keys have the same fingerprint without actually calculating the fingerprint + * @returns {Boolean} Whether the two keys have the same version and public key data. + */ + hasSameFingerprintAs(other) { + return this.version === other.version && util.equalsUint8Array(this.writePublicKey(), other.writePublicKey()); + } + + /** + * Returns algorithm information + * @returns {Object} An object of the form {algorithm: String, bits:int, curve:String}. + */ + getAlgorithmInfo() { + const result = {}; + result.algorithm = enums.read(enums.publicKey, this.algorithm); + // RSA, DSA or ElGamal public modulo + const modulo = this.publicParams.n || this.publicParams.p; + if (modulo) { + result.bits = util.uint8ArrayBitLength(modulo); + } else { + result.curve = this.publicParams.oid.getName(); + } + return result; + } + } + + /** + * Alias of read() + * @see PublicKeyPacket#read + */ + PublicKeyPacket.prototype.readPublicKey = PublicKeyPacket.prototype.read; + + /** + * Alias of write() + * @see PublicKeyPacket#write + */ + PublicKeyPacket.prototype.writePublicKey = PublicKeyPacket.prototype.write; + + // GPG4Browsers - An OpenPGP implementation in javascript + + // A SE packet can contain the following packet types + const allowedPackets$3 = /*#__PURE__*/ util.constructAllowedPackets([ + LiteralDataPacket, + CompressedDataPacket, + OnePassSignaturePacket, + SignaturePacket + ]); + + /** + * Implementation of the Symmetrically Encrypted Data Packet (Tag 9) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.7|RFC4880 5.7}: + * The Symmetrically Encrypted Data packet contains data encrypted with a + * symmetric-key algorithm. When it has been decrypted, it contains other + * packets (usually a literal data packet or compressed data packet, but in + * theory other Symmetrically Encrypted Data packets or sequences of packets + * that form whole OpenPGP messages). + */ + class SymmetricallyEncryptedDataPacket { + static get tag() { + return enums.packet.symmetricallyEncryptedData; + } + + constructor() { + /** + * Encrypted secret-key data + */ + this.encrypted = null; + /** + * Decrypted packets contained within. + * @type {PacketList} + */ + this.packets = null; + } + + read(bytes) { + this.encrypted = bytes; + } + + write() { + return this.encrypted; + } + + /** + * Decrypt the symmetrically-encrypted packet data + * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. + * @param {module:enums.symmetric} sessionKeyAlgorithm - Symmetric key algorithm to use + * @param {Uint8Array} key - The key of cipher blocksize length to be used + * @param {Object} [config] - Full configuration, defaults to openpgp.config + + * @throws {Error} if decryption was not successful + * @async + */ + async decrypt(sessionKeyAlgorithm, key, config = defaultConfig) { + // If MDC errors are not being ignored, all missing MDC packets in symmetrically encrypted data should throw an error + if (!config.allowUnauthenticatedMessages) { + throw new Error('Message is not authenticated.'); + } + + const { blockSize } = mod.getCipher(sessionKeyAlgorithm); + const encrypted = await readToEnd(clone(this.encrypted)); + const decrypted = await mod.mode.cfb.decrypt(sessionKeyAlgorithm, key, + encrypted.subarray(blockSize + 2), + encrypted.subarray(2, blockSize + 2) + ); + + this.packets = await PacketList.fromBinary(decrypted, allowedPackets$3, config); + } + + /** + * Encrypt the symmetrically-encrypted packet data + * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. + * @param {module:enums.symmetric} sessionKeyAlgorithm - Symmetric key algorithm to use + * @param {Uint8Array} key - The key of cipher blocksize length to be used + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if encryption was not successful + * @async + */ + async encrypt(sessionKeyAlgorithm, key, config = defaultConfig) { + const data = this.packets.write(); + const { blockSize } = mod.getCipher(sessionKeyAlgorithm); + + const prefix = await mod.getPrefixRandom(sessionKeyAlgorithm); + const FRE = await mod.mode.cfb.encrypt(sessionKeyAlgorithm, key, prefix, new Uint8Array(blockSize), config); + const ciphertext = await mod.mode.cfb.encrypt(sessionKeyAlgorithm, key, data, FRE.subarray(2), config); + this.encrypted = util.concat([FRE, ciphertext]); + } + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + /** + * Implementation of the strange "Marker packet" (Tag 10) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.8|RFC4880 5.8}: + * An experimental version of PGP used this packet as the Literal + * packet, but no released version of PGP generated Literal packets with this + * tag. With PGP 5.x, this packet has been reassigned and is reserved for use as + * the Marker packet. + * + * The body of this packet consists of: + * The three octets 0x50, 0x47, 0x50 (which spell "PGP" in UTF-8). + * + * Such a packet MUST be ignored when received. It may be placed at the + * beginning of a message that uses features not available in PGP + * version 2.6 in order to cause that version to report that newer + * software is necessary to process the message. + */ + class MarkerPacket { + static get tag() { + return enums.packet.marker; + } + + /** + * Parsing function for a marker data packet (tag 10). + * @param {Uint8Array} bytes - Payload of a tag 10 packet + * @returns {Boolean} whether the packet payload contains "PGP" + */ + read(bytes) { + if (bytes[0] === 0x50 && // P + bytes[1] === 0x47 && // G + bytes[2] === 0x50) { // P + return true; + } + return false; + } + + write() { + return new Uint8Array([0x50, 0x47, 0x50]); + } + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + /** + * A Public-Subkey packet (tag 14) has exactly the same format as a + * Public-Key packet, but denotes a subkey. One or more subkeys may be + * associated with a top-level key. By convention, the top-level key + * provides signature services, and the subkeys provide encryption + * services. + * @extends PublicKeyPacket + */ + class PublicSubkeyPacket extends PublicKeyPacket { + static get tag() { + return enums.packet.publicSubkey; + } + + /** + * @param {Date} [date] - Creation date + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + // eslint-disable-next-line no-useless-constructor + constructor(date, config) { + super(date, config); + } + + /** + * Create a PublicSubkeyPacket from a SecretSubkeyPacket + * @param {SecretSubkeyPacket} secretSubkeyPacket - subkey packet to convert + * @returns {SecretSubkeyPacket} public key packet + * @static + */ + static fromSecretSubkeyPacket(secretSubkeyPacket) { + const keyPacket = new PublicSubkeyPacket(); + const { version, created, algorithm, publicParams, keyID, fingerprint } = secretSubkeyPacket; + keyPacket.version = version; + keyPacket.created = created; + keyPacket.algorithm = algorithm; + keyPacket.publicParams = publicParams; + keyPacket.keyID = keyID; + keyPacket.fingerprint = fingerprint; + return keyPacket; + } + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + /** + * Implementation of the User Attribute Packet (Tag 17) + * + * The User Attribute packet is a variation of the User ID packet. It + * is capable of storing more types of data than the User ID packet, + * which is limited to text. Like the User ID packet, a User Attribute + * packet may be certified by the key owner ("self-signed") or any other + * key owner who cares to certify it. Except as noted, a User Attribute + * packet may be used anywhere that a User ID packet may be used. + * + * While User Attribute packets are not a required part of the OpenPGP + * standard, implementations SHOULD provide at least enough + * compatibility to properly handle a certification signature on the + * User Attribute packet. A simple way to do this is by treating the + * User Attribute packet as a User ID packet with opaque contents, but + * an implementation may use any method desired. + */ + class UserAttributePacket { + static get tag() { + return enums.packet.userAttribute; + } + + constructor() { + this.attributes = []; + } + + /** + * parsing function for a user attribute packet (tag 17). + * @param {Uint8Array} input - Payload of a tag 17 packet + */ + read(bytes) { + let i = 0; + while (i < bytes.length) { + const len = readSimpleLength(bytes.subarray(i, bytes.length)); + i += len.offset; + + this.attributes.push(util.uint8ArrayToString(bytes.subarray(i, i + len.len))); + i += len.len; + } + } + + /** + * Creates a binary representation of the user attribute packet + * @returns {Uint8Array} String representation. + */ + write() { + const arr = []; + for (let i = 0; i < this.attributes.length; i++) { + arr.push(writeSimpleLength(this.attributes[i].length)); + arr.push(util.stringToUint8Array(this.attributes[i])); + } + return util.concatUint8Array(arr); + } + + /** + * Compare for equality + * @param {UserAttributePacket} usrAttr + * @returns {Boolean} True if equal. + */ + equals(usrAttr) { + if (!usrAttr || !(usrAttr instanceof UserAttributePacket)) { + return false; + } + return this.attributes.every(function(attr, index) { + return attr === usrAttr.attributes[index]; + }); + } + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + /** + * A Secret-Key packet contains all the information that is found in a + * Public-Key packet, including the public-key material, but also + * includes the secret-key material after all the public-key fields. + * @extends PublicKeyPacket + */ + class SecretKeyPacket extends PublicKeyPacket { + static get tag() { + return enums.packet.secretKey; + } + + /** + * @param {Date} [date] - Creation date + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + constructor(date = new Date(), config = defaultConfig) { + super(date, config); + /** + * Secret-key data + */ + this.keyMaterial = null; + /** + * Indicates whether secret-key data is encrypted. `this.isEncrypted === false` means data is available in decrypted form. + */ + this.isEncrypted = null; + /** + * S2K usage + * @type {enums.symmetric} + */ + this.s2kUsage = 0; + /** + * S2K object + * @type {type/s2k} + */ + this.s2k = null; + /** + * Symmetric algorithm to encrypt the key with + * @type {enums.symmetric} + */ + this.symmetric = null; + /** + * AEAD algorithm to encrypt the key with (if AEAD protection is enabled) + * @type {enums.aead} + */ + this.aead = null; + /** + * Decrypted private parameters, referenced by name + * @type {Object} + */ + this.privateParams = null; + } + + // 5.5.3. Secret-Key Packet Formats + + /** + * Internal parser for private keys as specified in + * {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.5.3|RFC4880bis-04 section 5.5.3} + * @param {Uint8Array} bytes - Input string to read the packet from + * @async + */ + async read(bytes) { + // - A Public-Key or Public-Subkey packet, as described above. + let i = await this.readPublicKey(bytes); + + // - One octet indicating string-to-key usage conventions. Zero + // indicates that the secret-key data is not encrypted. 255 or 254 + // indicates that a string-to-key specifier is being given. Any + // other value is a symmetric-key encryption algorithm identifier. + this.s2kUsage = bytes[i++]; + + // - Only for a version 5 packet, a one-octet scalar octet count of + // the next 4 optional fields. + if (this.version === 5) { + i++; + } + + // - [Optional] If string-to-key usage octet was 255, 254, or 253, a + // one-octet symmetric encryption algorithm. + if (this.s2kUsage === 255 || this.s2kUsage === 254 || this.s2kUsage === 253) { + this.symmetric = bytes[i++]; + + // - [Optional] If string-to-key usage octet was 253, a one-octet + // AEAD algorithm. + if (this.s2kUsage === 253) { + this.aead = bytes[i++]; + } + + // - [Optional] If string-to-key usage octet was 255, 254, or 253, a + // string-to-key specifier. The length of the string-to-key + // specifier is implied by its type, as described above. + this.s2k = new S2K(); + i += this.s2k.read(bytes.subarray(i, bytes.length)); + + if (this.s2k.type === 'gnu-dummy') { + return; + } + } else if (this.s2kUsage) { + this.symmetric = this.s2kUsage; + } + + // - [Optional] If secret data is encrypted (string-to-key usage octet + // not zero), an Initial Vector (IV) of the same length as the + // cipher's block size. + if (this.s2kUsage) { + this.iv = bytes.subarray( + i, + i + mod.getCipher(this.symmetric).blockSize + ); + + i += this.iv.length; + } + + // - Only for a version 5 packet, a four-octet scalar octet count for + // the following key material. + if (this.version === 5) { + i += 4; + } + + // - Plain or encrypted multiprecision integers comprising the secret + // key data. These algorithm-specific fields are as described + // below. + this.keyMaterial = bytes.subarray(i); + this.isEncrypted = !!this.s2kUsage; + + if (!this.isEncrypted) { + const cleartext = this.keyMaterial.subarray(0, -2); + if (!util.equalsUint8Array(util.writeChecksum(cleartext), this.keyMaterial.subarray(-2))) { + throw new Error('Key checksum mismatch'); + } + try { + const { privateParams } = mod.parsePrivateKeyParams(this.algorithm, cleartext, this.publicParams); + this.privateParams = privateParams; + } catch (err) { + throw new Error('Error reading MPIs'); + } + } + } + + /** + * Creates an OpenPGP key packet for the given key. + * @returns {Uint8Array} A string of bytes containing the secret key OpenPGP packet. + */ + write() { + const arr = [this.writePublicKey()]; + + arr.push(new Uint8Array([this.s2kUsage])); + + const optionalFieldsArr = []; + // - [Optional] If string-to-key usage octet was 255, 254, or 253, a + // one- octet symmetric encryption algorithm. + if (this.s2kUsage === 255 || this.s2kUsage === 254 || this.s2kUsage === 253) { + optionalFieldsArr.push(this.symmetric); + + // - [Optional] If string-to-key usage octet was 253, a one-octet + // AEAD algorithm. + if (this.s2kUsage === 253) { + optionalFieldsArr.push(this.aead); + } + + // - [Optional] If string-to-key usage octet was 255, 254, or 253, a + // string-to-key specifier. The length of the string-to-key + // specifier is implied by its type, as described above. + optionalFieldsArr.push(...this.s2k.write()); + } + + // - [Optional] If secret data is encrypted (string-to-key usage octet + // not zero), an Initial Vector (IV) of the same length as the + // cipher's block size. + if (this.s2kUsage && this.s2k.type !== 'gnu-dummy') { + optionalFieldsArr.push(...this.iv); + } + + if (this.version === 5) { + arr.push(new Uint8Array([optionalFieldsArr.length])); + } + arr.push(new Uint8Array(optionalFieldsArr)); + + if (!this.isDummy()) { + if (!this.s2kUsage) { + this.keyMaterial = mod.serializeParams(this.algorithm, this.privateParams); + } + + if (this.version === 5) { + arr.push(util.writeNumber(this.keyMaterial.length, 4)); + } + arr.push(this.keyMaterial); + + if (!this.s2kUsage) { + arr.push(util.writeChecksum(this.keyMaterial)); + } + } + + return util.concatUint8Array(arr); + } + + /** + * Check whether secret-key data is available in decrypted form. + * Returns false for gnu-dummy keys and null for public keys. + * @returns {Boolean|null} + */ + isDecrypted() { + return this.isEncrypted === false; + } + + /** + * Check whether this is a gnu-dummy key + * @returns {Boolean} + */ + isDummy() { + return !!(this.s2k && this.s2k.type === 'gnu-dummy'); + } + + /** + * Remove private key material, converting the key to a dummy one. + * The resulting key cannot be used for signing/decrypting but can still verify signatures. + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + makeDummy(config = defaultConfig) { + if (this.isDummy()) { + return; + } + if (this.isDecrypted()) { + this.clearPrivateParams(); + } + this.isEncrypted = null; + this.keyMaterial = null; + this.s2k = new S2K(config); + this.s2k.algorithm = 0; + this.s2k.c = 0; + this.s2k.type = 'gnu-dummy'; + this.s2kUsage = 254; + this.symmetric = enums.symmetric.aes256; + } + + /** + * Encrypt the payload. By default, we use aes256 and iterated, salted string + * to key specifier. If the key is in a decrypted state (isEncrypted === false) + * and the passphrase is empty or undefined, the key will be set as not encrypted. + * This can be used to remove passphrase protection after calling decrypt(). + * @param {String} passphrase + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if encryption was not successful + * @async + */ + async encrypt(passphrase, config = defaultConfig) { + if (this.isDummy()) { + return; + } + + if (!this.isDecrypted()) { + throw new Error('Key packet is already encrypted'); + } + + if (this.isDecrypted() && !passphrase) { + this.s2kUsage = 0; + return; + } else if (!passphrase) { + throw new Error('The key must be decrypted before removing passphrase protection.'); + } + + this.s2k = new S2K(config); + this.s2k.salt = await mod.random.getRandomBytes(8); + const cleartext = mod.serializeParams(this.algorithm, this.privateParams); + this.symmetric = enums.symmetric.aes256; + const key = await produceEncryptionKey(this.s2k, passphrase, this.symmetric); + + const { blockSize } = mod.getCipher(this.symmetric); + this.iv = await mod.random.getRandomBytes(blockSize); + + if (config.aeadProtect) { + this.s2kUsage = 253; + this.aead = enums.aead.eax; + const mode = mod.getAEADMode(this.aead); + const modeInstance = await mode(this.symmetric, key); + this.keyMaterial = await modeInstance.encrypt(cleartext, this.iv.subarray(0, mode.ivLength), new Uint8Array()); + } else { + this.s2kUsage = 254; + this.keyMaterial = await mod.mode.cfb.encrypt(this.symmetric, key, util.concatUint8Array([ + cleartext, + await mod.hash.sha1(cleartext, config) + ]), this.iv, config); + } + } + + /** + * Decrypts the private key params which are needed to use the key. + * Successful decryption does not imply key integrity, call validate() to confirm that. + * {@link SecretKeyPacket.isDecrypted} should be false, as + * otherwise calls to this function will throw an error. + * @param {String} passphrase - The passphrase for this private key as string + * @throws {Error} if the key is already decrypted, or if decryption was not successful + * @async + */ + async decrypt(passphrase) { + if (this.isDummy()) { + return false; + } + + if (this.isDecrypted()) { + throw new Error('Key packet is already decrypted.'); + } + + let key; + if (this.s2kUsage === 254 || this.s2kUsage === 253) { + key = await produceEncryptionKey(this.s2k, passphrase, this.symmetric); + } else if (this.s2kUsage === 255) { + throw new Error('Encrypted private key is authenticated using an insecure two-byte hash'); + } else { + throw new Error('Private key is encrypted using an insecure S2K function: unsalted MD5'); + } + + let cleartext; + if (this.s2kUsage === 253) { + const mode = mod.getAEADMode(this.aead); + const modeInstance = await mode(this.symmetric, key); + try { + cleartext = await modeInstance.decrypt(this.keyMaterial, this.iv.subarray(0, mode.ivLength), new Uint8Array()); + } catch (err) { + if (err.message === 'Authentication tag mismatch') { + throw new Error('Incorrect key passphrase: ' + err.message); + } + throw err; + } + } else { + const cleartextWithHash = await mod.mode.cfb.decrypt(this.symmetric, key, this.keyMaterial, this.iv); + + cleartext = cleartextWithHash.subarray(0, -20); + const hash = await mod.hash.sha1(cleartext); + + if (!util.equalsUint8Array(hash, cleartextWithHash.subarray(-20))) { + throw new Error('Incorrect key passphrase'); + } + } + + try { + const { privateParams } = mod.parsePrivateKeyParams(this.algorithm, cleartext, this.publicParams); + this.privateParams = privateParams; + } catch (err) { + throw new Error('Error reading MPIs'); + } + this.isEncrypted = false; + this.keyMaterial = null; + this.s2kUsage = 0; + } + + /** + * Checks that the key parameters are consistent + * @throws {Error} if validation was not successful + * @async + */ + async validate() { + if (this.isDummy()) { + return; + } + + if (!this.isDecrypted()) { + throw new Error('Key is not decrypted'); + } + + let validParams; + try { + // this can throw if some parameters are undefined + validParams = await mod.validateParams(this.algorithm, this.publicParams, this.privateParams); + } catch (_) { + validParams = false; + } + if (!validParams) { + throw new Error('Key is invalid'); + } + } + + async generate(bits, curve) { + const { privateParams, publicParams } = await mod.generateParams(this.algorithm, bits, curve); + this.privateParams = privateParams; + this.publicParams = publicParams; + this.isEncrypted = false; + } + + /** + * Clear private key parameters + */ + clearPrivateParams() { + if (this.isDummy()) { + return; + } + + Object.keys(this.privateParams).forEach(name => { + const param = this.privateParams[name]; + param.fill(0); + delete this.privateParams[name]; + }); + this.privateParams = null; + this.isEncrypted = true; + } + } + + async function produceEncryptionKey(s2k, passphrase, algorithm) { + const { keySize } = mod.getCipher(algorithm); + return s2k.produceKey(passphrase, keySize); + } + + var emailAddresses = createCommonjsModule(function (module) { + // email-addresses.js - RFC 5322 email address parser + // v 3.1.0 + // + // http://tools.ietf.org/html/rfc5322 + // + // This library does not validate email addresses. + // emailAddresses attempts to parse addresses using the (fairly liberal) + // grammar specified in RFC 5322. + // + // email-addresses returns { + // ast: , + // addresses: [{ + // node: , + // name: , + // address: , + // local: , + // domain: + // }, ...] + // } + // + // emailAddresses.parseOneAddress and emailAddresses.parseAddressList + // work as you might expect. Try it out. + // + // Many thanks to Dominic Sayers and his documentation on the is_email function, + // http://code.google.com/p/isemail/ , which helped greatly in writing this parser. + + (function (global) { + + function parse5322(opts) { + + // tokenizing functions + + function inStr() { return pos < len; } + function curTok() { return parseString[pos]; } + function getPos() { return pos; } + function setPos(i) { pos = i; } + function nextTok() { pos += 1; } + function initialize() { + pos = 0; + len = parseString.length; + } + + // parser helper functions + + function o(name, value) { + return { + name: name, + tokens: value || "", + semantic: value || "", + children: [] + }; + } + + function wrap(name, ast) { + var n; + if (ast === null) { return null; } + n = o(name); + n.tokens = ast.tokens; + n.semantic = ast.semantic; + n.children.push(ast); + return n; + } + + function add(parent, child) { + if (child !== null) { + parent.tokens += child.tokens; + parent.semantic += child.semantic; + } + parent.children.push(child); + return parent; + } + + function compareToken(fxnCompare) { + var tok; + if (!inStr()) { return null; } + tok = curTok(); + if (fxnCompare(tok)) { + nextTok(); + return o('token', tok); + } + return null; + } + + function literal(lit) { + return function literalFunc() { + return wrap('literal', compareToken(function (tok) { + return tok === lit; + })); + }; + } + + function and() { + var args = arguments; + return function andFunc() { + var i, s, result, start; + start = getPos(); + s = o('and'); + for (i = 0; i < args.length; i += 1) { + result = args[i](); + if (result === null) { + setPos(start); + return null; + } + add(s, result); + } + return s; + }; + } + + function or() { + var args = arguments; + return function orFunc() { + var i, result, start; + start = getPos(); + for (i = 0; i < args.length; i += 1) { + result = args[i](); + if (result !== null) { + return result; + } + setPos(start); + } + return null; + }; + } + + function opt(prod) { + return function optFunc() { + var result, start; + start = getPos(); + result = prod(); + if (result !== null) { + return result; + } + else { + setPos(start); + return o('opt'); + } + }; + } + + function invis(prod) { + return function invisFunc() { + var result = prod(); + if (result !== null) { + result.semantic = ""; + } + return result; + }; + } + + function colwsp(prod) { + return function collapseSemanticWhitespace() { + var result = prod(); + if (result !== null && result.semantic.length > 0) { + result.semantic = " "; + } + return result; + }; + } + + function star(prod, minimum) { + return function starFunc() { + var s, result, count, start, min; + start = getPos(); + s = o('star'); + count = 0; + min = minimum === undefined ? 0 : minimum; + while ((result = prod()) !== null) { + count = count + 1; + add(s, result); + } + if (count >= min) { + return s; + } + else { + setPos(start); + return null; + } + }; + } + + // One expects names to get normalized like this: + // " First Last " -> "First Last" + // "First Last" -> "First Last" + // "First Last" -> "First Last" + function collapseWhitespace(s) { + return s.replace(/([ \t]|\r\n)+/g, ' ').replace(/^\s*/, '').replace(/\s*$/, ''); + } + + // UTF-8 pseudo-production (RFC 6532) + // RFC 6532 extends RFC 5322 productions to include UTF-8 + // using the following productions: + // UTF8-non-ascii = UTF8-2 / UTF8-3 / UTF8-4 + // UTF8-2 = + // UTF8-3 = + // UTF8-4 = + // + // For reference, the extended RFC 5322 productions are: + // VCHAR =/ UTF8-non-ascii + // ctext =/ UTF8-non-ascii + // atext =/ UTF8-non-ascii + // qtext =/ UTF8-non-ascii + // dtext =/ UTF8-non-ascii + function isUTF8NonAscii(tok) { + // In JavaScript, we just deal directly with Unicode code points, + // so we aren't checking individual bytes for UTF-8 encoding. + // Just check that the character is non-ascii. + return tok.charCodeAt(0) >= 128; + } + + + // common productions (RFC 5234) + // http://tools.ietf.org/html/rfc5234 + // B.1. Core Rules + + // CR = %x0D + // ; carriage return + function cr() { return wrap('cr', literal('\r')()); } + + // CRLF = CR LF + // ; Internet standard newline + function crlf() { return wrap('crlf', and(cr, lf)()); } + + // DQUOTE = %x22 + // ; " (Double Quote) + function dquote() { return wrap('dquote', literal('"')()); } + + // HTAB = %x09 + // ; horizontal tab + function htab() { return wrap('htab', literal('\t')()); } + + // LF = %x0A + // ; linefeed + function lf() { return wrap('lf', literal('\n')()); } + + // SP = %x20 + function sp() { return wrap('sp', literal(' ')()); } + + // VCHAR = %x21-7E + // ; visible (printing) characters + function vchar() { + return wrap('vchar', compareToken(function vcharFunc(tok) { + var code = tok.charCodeAt(0); + var accept = (0x21 <= code && code <= 0x7E); + if (opts.rfc6532) { + accept = accept || isUTF8NonAscii(tok); + } + return accept; + })); + } + + // WSP = SP / HTAB + // ; white space + function wsp() { return wrap('wsp', or(sp, htab)()); } + + + // email productions (RFC 5322) + // http://tools.ietf.org/html/rfc5322 + // 3.2.1. Quoted characters + + // quoted-pair = ("\" (VCHAR / WSP)) / obs-qp + function quotedPair() { + var qp = wrap('quoted-pair', + or( + and(literal('\\'), or(vchar, wsp)), + obsQP + )()); + if (qp === null) { return null; } + // a quoted pair will be two characters, and the "\" character + // should be semantically "invisible" (RFC 5322 3.2.1) + qp.semantic = qp.semantic[1]; + return qp; + } + + // 3.2.2. Folding White Space and Comments + + // FWS = ([*WSP CRLF] 1*WSP) / obs-FWS + function fws() { + return wrap('fws', or( + obsFws, + and( + opt(and( + star(wsp), + invis(crlf) + )), + star(wsp, 1) + ) + )()); + } + + // ctext = %d33-39 / ; Printable US-ASCII + // %d42-91 / ; characters not including + // %d93-126 / ; "(", ")", or "\" + // obs-ctext + function ctext() { + return wrap('ctext', or( + function ctextFunc1() { + return compareToken(function ctextFunc2(tok) { + var code = tok.charCodeAt(0); + var accept = + (33 <= code && code <= 39) || + (42 <= code && code <= 91) || + (93 <= code && code <= 126); + if (opts.rfc6532) { + accept = accept || isUTF8NonAscii(tok); + } + return accept; + }); + }, + obsCtext + )()); + } + + // ccontent = ctext / quoted-pair / comment + function ccontent() { + return wrap('ccontent', or(ctext, quotedPair, comment)()); + } + + // comment = "(" *([FWS] ccontent) [FWS] ")" + function comment() { + return wrap('comment', and( + literal('('), + star(and(opt(fws), ccontent)), + opt(fws), + literal(')') + )()); + } + + // CFWS = (1*([FWS] comment) [FWS]) / FWS + function cfws() { + return wrap('cfws', or( + and( + star( + and(opt(fws), comment), + 1 + ), + opt(fws) + ), + fws + )()); + } + + // 3.2.3. Atom + + //atext = ALPHA / DIGIT / ; Printable US-ASCII + // "!" / "#" / ; characters not including + // "$" / "%" / ; specials. Used for atoms. + // "&" / "'" / + // "*" / "+" / + // "-" / "/" / + // "=" / "?" / + // "^" / "_" / + // "`" / "{" / + // "|" / "}" / + // "~" + function atext() { + return wrap('atext', compareToken(function atextFunc(tok) { + var accept = + ('a' <= tok && tok <= 'z') || + ('A' <= tok && tok <= 'Z') || + ('0' <= tok && tok <= '9') || + (['!', '#', '$', '%', '&', '\'', '*', '+', '-', '/', + '=', '?', '^', '_', '`', '{', '|', '}', '~'].indexOf(tok) >= 0); + if (opts.rfc6532) { + accept = accept || isUTF8NonAscii(tok); + } + return accept; + })); + } + + // atom = [CFWS] 1*atext [CFWS] + function atom() { + return wrap('atom', and(colwsp(opt(cfws)), star(atext, 1), colwsp(opt(cfws)))()); + } + + // dot-atom-text = 1*atext *("." 1*atext) + function dotAtomText() { + var s, maybeText; + s = wrap('dot-atom-text', star(atext, 1)()); + if (s === null) { return s; } + maybeText = star(and(literal('.'), star(atext, 1)))(); + if (maybeText !== null) { + add(s, maybeText); + } + return s; + } + + // dot-atom = [CFWS] dot-atom-text [CFWS] + function dotAtom() { + return wrap('dot-atom', and(invis(opt(cfws)), dotAtomText, invis(opt(cfws)))()); + } + + // 3.2.4. Quoted Strings + + // qtext = %d33 / ; Printable US-ASCII + // %d35-91 / ; characters not including + // %d93-126 / ; "\" or the quote character + // obs-qtext + function qtext() { + return wrap('qtext', or( + function qtextFunc1() { + return compareToken(function qtextFunc2(tok) { + var code = tok.charCodeAt(0); + var accept = + (33 === code) || + (35 <= code && code <= 91) || + (93 <= code && code <= 126); + if (opts.rfc6532) { + accept = accept || isUTF8NonAscii(tok); + } + return accept; + }); + }, + obsQtext + )()); + } + + // qcontent = qtext / quoted-pair + function qcontent() { + return wrap('qcontent', or(qtext, quotedPair)()); + } + + // quoted-string = [CFWS] + // DQUOTE *([FWS] qcontent) [FWS] DQUOTE + // [CFWS] + function quotedString() { + return wrap('quoted-string', and( + invis(opt(cfws)), + invis(dquote), star(and(opt(colwsp(fws)), qcontent)), opt(invis(fws)), invis(dquote), + invis(opt(cfws)) + )()); + } + + // 3.2.5 Miscellaneous Tokens + + // word = atom / quoted-string + function word() { + return wrap('word', or(atom, quotedString)()); + } + + // phrase = 1*word / obs-phrase + function phrase() { + return wrap('phrase', or(obsPhrase, star(word, 1))()); + } + + // 3.4. Address Specification + // address = mailbox / group + function address() { + return wrap('address', or(mailbox, group)()); + } + + // mailbox = name-addr / addr-spec + function mailbox() { + return wrap('mailbox', or(nameAddr, addrSpec)()); + } + + // name-addr = [display-name] angle-addr + function nameAddr() { + return wrap('name-addr', and(opt(displayName), angleAddr)()); + } + + // angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / + // obs-angle-addr + function angleAddr() { + return wrap('angle-addr', or( + and( + invis(opt(cfws)), + literal('<'), + addrSpec, + literal('>'), + invis(opt(cfws)) + ), + obsAngleAddr + )()); + } + + // group = display-name ":" [group-list] ";" [CFWS] + function group() { + return wrap('group', and( + displayName, + literal(':'), + opt(groupList), + literal(';'), + invis(opt(cfws)) + )()); + } + + // display-name = phrase + function displayName() { + return wrap('display-name', function phraseFixedSemantic() { + var result = phrase(); + if (result !== null) { + result.semantic = collapseWhitespace(result.semantic); + } + return result; + }()); + } + + // mailbox-list = (mailbox *("," mailbox)) / obs-mbox-list + function mailboxList() { + return wrap('mailbox-list', or( + and( + mailbox, + star(and(literal(','), mailbox)) + ), + obsMboxList + )()); + } + + // address-list = (address *("," address)) / obs-addr-list + function addressList() { + return wrap('address-list', or( + and( + address, + star(and(literal(','), address)) + ), + obsAddrList + )()); + } + + // group-list = mailbox-list / CFWS / obs-group-list + function groupList() { + return wrap('group-list', or( + mailboxList, + invis(cfws), + obsGroupList + )()); + } + + // 3.4.1 Addr-Spec Specification + + // local-part = dot-atom / quoted-string / obs-local-part + function localPart() { + // note: quoted-string, dotAtom are proper subsets of obs-local-part + // so we really just have to look for obsLocalPart, if we don't care about the exact parse tree + return wrap('local-part', or(obsLocalPart, dotAtom, quotedString)()); + } + + // dtext = %d33-90 / ; Printable US-ASCII + // %d94-126 / ; characters not including + // obs-dtext ; "[", "]", or "\" + function dtext() { + return wrap('dtext', or( + function dtextFunc1() { + return compareToken(function dtextFunc2(tok) { + var code = tok.charCodeAt(0); + var accept = + (33 <= code && code <= 90) || + (94 <= code && code <= 126); + if (opts.rfc6532) { + accept = accept || isUTF8NonAscii(tok); + } + return accept; + }); + }, + obsDtext + )() + ); + } + + // domain-literal = [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS] + function domainLiteral() { + return wrap('domain-literal', and( + invis(opt(cfws)), + literal('['), + star(and(opt(fws), dtext)), + opt(fws), + literal(']'), + invis(opt(cfws)) + )()); + } + + // domain = dot-atom / domain-literal / obs-domain + function domain() { + return wrap('domain', function domainCheckTLD() { + var result = or(obsDomain, dotAtom, domainLiteral)(); + if (opts.rejectTLD) { + if (result && result.semantic && result.semantic.indexOf('.') < 0) { + return null; + } + } + // strip all whitespace from domains + if (result) { + result.semantic = result.semantic.replace(/\s+/g, ''); + } + return result; + }()); + } + + // addr-spec = local-part "@" domain + function addrSpec() { + return wrap('addr-spec', and( + localPart, literal('@'), domain + )()); + } + + // 3.6.2 Originator Fields + // Below we only parse the field body, not the name of the field + // like "From:", "Sender:", or "Reply-To:". Other libraries that + // parse email headers can parse those and defer to these productions + // for the "RFC 5322" part. + + // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields + // from = "From:" (mailbox-list / address-list) CRLF + function fromSpec() { + return wrap('from', or( + mailboxList, + addressList + )()); + } + + // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields + // sender = "Sender:" (mailbox / address) CRLF + function senderSpec() { + return wrap('sender', or( + mailbox, + address + )()); + } + + // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields + // reply-to = "Reply-To:" address-list CRLF + function replyToSpec() { + return wrap('reply-to', addressList()); + } + + // 4.1. Miscellaneous Obsolete Tokens + + // obs-NO-WS-CTL = %d1-8 / ; US-ASCII control + // %d11 / ; characters that do not + // %d12 / ; include the carriage + // %d14-31 / ; return, line feed, and + // %d127 ; white space characters + function obsNoWsCtl() { + return opts.strict ? null : wrap('obs-NO-WS-CTL', compareToken(function (tok) { + var code = tok.charCodeAt(0); + return ((1 <= code && code <= 8) || + (11 === code || 12 === code) || + (14 <= code && code <= 31) || + (127 === code)); + })); + } + + // obs-ctext = obs-NO-WS-CTL + function obsCtext() { return opts.strict ? null : wrap('obs-ctext', obsNoWsCtl()); } + + // obs-qtext = obs-NO-WS-CTL + function obsQtext() { return opts.strict ? null : wrap('obs-qtext', obsNoWsCtl()); } + + // obs-qp = "\" (%d0 / obs-NO-WS-CTL / LF / CR) + function obsQP() { + return opts.strict ? null : wrap('obs-qp', and( + literal('\\'), + or(literal('\0'), obsNoWsCtl, lf, cr) + )()); + } + + // obs-phrase = word *(word / "." / CFWS) + function obsPhrase() { + if (opts.strict ) return null; + return opts.atInDisplayName ? wrap('obs-phrase', and( + word, + star(or(word, literal('.'), literal('@'), colwsp(cfws))) + )()) : + wrap('obs-phrase', and( + word, + star(or(word, literal('.'), colwsp(cfws))) + )()); + } + + // 4.2. Obsolete Folding White Space + + // NOTE: read the errata http://www.rfc-editor.org/errata_search.php?rfc=5322&eid=1908 + // obs-FWS = 1*([CRLF] WSP) + function obsFws() { + return opts.strict ? null : wrap('obs-FWS', star( + and(invis(opt(crlf)), wsp), + 1 + )()); + } + + // 4.4. Obsolete Addressing + + // obs-angle-addr = [CFWS] "<" obs-route addr-spec ">" [CFWS] + function obsAngleAddr() { + return opts.strict ? null : wrap('obs-angle-addr', and( + invis(opt(cfws)), + literal('<'), + obsRoute, + addrSpec, + literal('>'), + invis(opt(cfws)) + )()); + } + + // obs-route = obs-domain-list ":" + function obsRoute() { + return opts.strict ? null : wrap('obs-route', and( + obsDomainList, + literal(':') + )()); + } + + // obs-domain-list = *(CFWS / ",") "@" domain + // *("," [CFWS] ["@" domain]) + function obsDomainList() { + return opts.strict ? null : wrap('obs-domain-list', and( + star(or(invis(cfws), literal(','))), + literal('@'), + domain, + star(and( + literal(','), + invis(opt(cfws)), + opt(and(literal('@'), domain)) + )) + )()); + } + + // obs-mbox-list = *([CFWS] ",") mailbox *("," [mailbox / CFWS]) + function obsMboxList() { + return opts.strict ? null : wrap('obs-mbox-list', and( + star(and( + invis(opt(cfws)), + literal(',') + )), + mailbox, + star(and( + literal(','), + opt(and( + mailbox, + invis(cfws) + )) + )) + )()); + } + + // obs-addr-list = *([CFWS] ",") address *("," [address / CFWS]) + function obsAddrList() { + return opts.strict ? null : wrap('obs-addr-list', and( + star(and( + invis(opt(cfws)), + literal(',') + )), + address, + star(and( + literal(','), + opt(and( + address, + invis(cfws) + )) + )) + )()); + } + + // obs-group-list = 1*([CFWS] ",") [CFWS] + function obsGroupList() { + return opts.strict ? null : wrap('obs-group-list', and( + star(and( + invis(opt(cfws)), + literal(',') + ), 1), + invis(opt(cfws)) + )()); + } + + // obs-local-part = word *("." word) + function obsLocalPart() { + return opts.strict ? null : wrap('obs-local-part', and(word, star(and(literal('.'), word)))()); + } + + // obs-domain = atom *("." atom) + function obsDomain() { + return opts.strict ? null : wrap('obs-domain', and(atom, star(and(literal('.'), atom)))()); + } + + // obs-dtext = obs-NO-WS-CTL / quoted-pair + function obsDtext() { + return opts.strict ? null : wrap('obs-dtext', or(obsNoWsCtl, quotedPair)()); + } + + ///////////////////////////////////////////////////// + + // ast analysis + + function findNode(name, root) { + var i, stack, node; + if (root === null || root === undefined) { return null; } + stack = [root]; + while (stack.length > 0) { + node = stack.pop(); + if (node.name === name) { + return node; + } + for (i = node.children.length - 1; i >= 0; i -= 1) { + stack.push(node.children[i]); + } + } + return null; + } + + function findAllNodes(name, root) { + var i, stack, node, result; + if (root === null || root === undefined) { return null; } + stack = [root]; + result = []; + while (stack.length > 0) { + node = stack.pop(); + if (node.name === name) { + result.push(node); + } + for (i = node.children.length - 1; i >= 0; i -= 1) { + stack.push(node.children[i]); + } + } + return result; + } + + function findAllNodesNoChildren(names, root) { + var i, stack, node, result, namesLookup; + if (root === null || root === undefined) { return null; } + stack = [root]; + result = []; + namesLookup = {}; + for (i = 0; i < names.length; i += 1) { + namesLookup[names[i]] = true; + } + + while (stack.length > 0) { + node = stack.pop(); + if (node.name in namesLookup) { + result.push(node); + // don't look at children (hence findAllNodesNoChildren) + } else { + for (i = node.children.length - 1; i >= 0; i -= 1) { + stack.push(node.children[i]); + } + } + } + return result; + } + + function giveResult(ast) { + var addresses, groupsAndMailboxes, i, groupOrMailbox, result; + if (ast === null) { + return null; + } + addresses = []; + + // An address is a 'group' (i.e. a list of mailboxes) or a 'mailbox'. + groupsAndMailboxes = findAllNodesNoChildren(['group', 'mailbox'], ast); + for (i = 0; i < groupsAndMailboxes.length; i += 1) { + groupOrMailbox = groupsAndMailboxes[i]; + if (groupOrMailbox.name === 'group') { + addresses.push(giveResultGroup(groupOrMailbox)); + } else if (groupOrMailbox.name === 'mailbox') { + addresses.push(giveResultMailbox(groupOrMailbox)); + } + } + + result = { + ast: ast, + addresses: addresses, + }; + if (opts.simple) { + result = simplifyResult(result); + } + if (opts.oneResult) { + return oneResult(result); + } + if (opts.simple) { + return result && result.addresses; + } else { + return result; + } + } + + function giveResultGroup(group) { + var i; + var groupName = findNode('display-name', group); + var groupResultMailboxes = []; + var mailboxes = findAllNodesNoChildren(['mailbox'], group); + for (i = 0; i < mailboxes.length; i += 1) { + groupResultMailboxes.push(giveResultMailbox(mailboxes[i])); + } + return { + node: group, + parts: { + name: groupName, + }, + type: group.name, // 'group' + name: grabSemantic(groupName), + addresses: groupResultMailboxes, + }; + } + + function giveResultMailbox(mailbox) { + var name = findNode('display-name', mailbox); + var aspec = findNode('addr-spec', mailbox); + var cfws = findAllNodes('cfws', mailbox); + var comments = findAllNodesNoChildren(['comment'], mailbox); + + + var local = findNode('local-part', aspec); + var domain = findNode('domain', aspec); + return { + node: mailbox, + parts: { + name: name, + address: aspec, + local: local, + domain: domain, + comments: cfws + }, + type: mailbox.name, // 'mailbox' + name: grabSemantic(name), + address: grabSemantic(aspec), + local: grabSemantic(local), + domain: grabSemantic(domain), + comments: concatComments(comments), + groupName: grabSemantic(mailbox.groupName), + }; + } + + function grabSemantic(n) { + return n !== null && n !== undefined ? n.semantic : null; + } + + function simplifyResult(result) { + var i; + if (result && result.addresses) { + for (i = 0; i < result.addresses.length; i += 1) { + delete result.addresses[i].node; + } + } + return result; + } + + function concatComments(comments) { + var result = ''; + if (comments) { + for (var i = 0; i < comments.length; i += 1) { + result += grabSemantic(comments[i]); + } + } + return result; + } + + function oneResult(result) { + if (!result) { return null; } + if (!opts.partial && result.addresses.length > 1) { return null; } + return result.addresses && result.addresses[0]; + } + + ///////////////////////////////////////////////////// + + var parseString, pos, len, parsed, startProduction; + + opts = handleOpts(opts, {}); + if (opts === null) { return null; } + + parseString = opts.input; + + startProduction = { + 'address': address, + 'address-list': addressList, + 'angle-addr': angleAddr, + 'from': fromSpec, + 'group': group, + 'mailbox': mailbox, + 'mailbox-list': mailboxList, + 'reply-to': replyToSpec, + 'sender': senderSpec, + }[opts.startAt] || addressList; + + if (!opts.strict) { + initialize(); + opts.strict = true; + parsed = startProduction(parseString); + if (opts.partial || !inStr()) { + return giveResult(parsed); + } + opts.strict = false; + } + + initialize(); + parsed = startProduction(parseString); + if (!opts.partial && inStr()) { return null; } + return giveResult(parsed); + } + + function parseOneAddressSimple(opts) { + return parse5322(handleOpts(opts, { + oneResult: true, + rfc6532: true, + simple: true, + startAt: 'address-list', + })); + } + + function parseAddressListSimple(opts) { + return parse5322(handleOpts(opts, { + rfc6532: true, + simple: true, + startAt: 'address-list', + })); + } + + function parseFromSimple(opts) { + return parse5322(handleOpts(opts, { + rfc6532: true, + simple: true, + startAt: 'from', + })); + } + + function parseSenderSimple(opts) { + return parse5322(handleOpts(opts, { + oneResult: true, + rfc6532: true, + simple: true, + startAt: 'sender', + })); + } + + function parseReplyToSimple(opts) { + return parse5322(handleOpts(opts, { + rfc6532: true, + simple: true, + startAt: 'reply-to', + })); + } + + function handleOpts(opts, defs) { + function isString(str) { + return Object.prototype.toString.call(str) === '[object String]'; + } + + function isObject(o) { + return o === Object(o); + } + + function isNullUndef(o) { + return o === null || o === undefined; + } + + var defaults, o; + + if (isString(opts)) { + opts = { input: opts }; + } else if (!isObject(opts)) { + return null; + } + + if (!isString(opts.input)) { return null; } + if (!defs) { return null; } + + defaults = { + oneResult: false, + partial: false, + rejectTLD: false, + rfc6532: false, + simple: false, + startAt: 'address-list', + strict: false, + atInDisplayName: false + }; + + for (o in defaults) { + if (isNullUndef(opts[o])) { + opts[o] = !isNullUndef(defs[o]) ? defs[o] : defaults[o]; + } + } + return opts; + } + + parse5322.parseOneAddress = parseOneAddressSimple; + parse5322.parseAddressList = parseAddressListSimple; + parse5322.parseFrom = parseFromSimple; + parse5322.parseSender = parseSenderSimple; + parse5322.parseReplyTo = parseReplyToSimple; + + { + module.exports = parse5322; + } + + }()); + }); + + // GPG4Browsers - An OpenPGP implementation in javascript + + /** + * Implementation of the User ID Packet (Tag 13) + * + * A User ID packet consists of UTF-8 text that is intended to represent + * the name and email address of the key holder. By convention, it + * includes an RFC 2822 [RFC2822] mail name-addr, but there are no + * restrictions on its content. The packet length in the header + * specifies the length of the User ID. + */ + class UserIDPacket { + static get tag() { + return enums.packet.userID; + } + + constructor() { + /** A string containing the user id. Usually in the form + * John Doe + * @type {String} + */ + this.userID = ''; + + this.name = ''; + this.email = ''; + this.comment = ''; + } + + /** + * Create UserIDPacket instance from object + * @param {Object} userID - Object specifying userID name, email and comment + * @returns {UserIDPacket} + * @static + */ + static fromObject(userID) { + if (util.isString(userID) || + (userID.name && !util.isString(userID.name)) || + (userID.email && !util.isEmailAddress(userID.email)) || + (userID.comment && !util.isString(userID.comment))) { + throw new Error('Invalid user ID format'); + } + const packet = new UserIDPacket(); + Object.assign(packet, userID); + const components = []; + if (packet.name) components.push(packet.name); + if (packet.comment) components.push(`(${packet.comment})`); + if (packet.email) components.push(`<${packet.email}>`); + packet.userID = components.join(' '); + return packet; + } + + /** + * Parsing function for a user id packet (tag 13). + * @param {Uint8Array} input - Payload of a tag 13 packet + */ + read(bytes, config = defaultConfig) { + const userID = util.decodeUTF8(bytes); + if (userID.length > config.maxUserIDLength) { + throw new Error('User ID string is too long'); + } + try { + const { name, address: email, comments } = emailAddresses.parseOneAddress({ input: userID, atInDisplayName: true }); + this.comment = comments.replace(/^\(|\)$/g, ''); + this.name = name; + this.email = email; + } catch (e) {} + this.userID = userID; + } + + /** + * Creates a binary representation of the user id packet + * @returns {Uint8Array} Binary representation. + */ + write() { + return util.encodeUTF8(this.userID); + } + + equals(otherUserID) { + return otherUserID && otherUserID.userID === this.userID; + } + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + /** + * A Secret-Subkey packet (tag 7) is the subkey analog of the Secret + * Key packet and has exactly the same format. + * @extends SecretKeyPacket + */ + class SecretSubkeyPacket extends SecretKeyPacket { + static get tag() { + return enums.packet.secretSubkey; + } + + /** + * @param {Date} [date] - Creation date + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + constructor(date = new Date(), config = defaultConfig) { + super(date, config); + } + } + + /** + * Implementation of the Trust Packet (Tag 12) + * + * {@link https://tools.ietf.org/html/rfc4880#section-5.10|RFC4880 5.10}: + * The Trust packet is used only within keyrings and is not normally + * exported. Trust packets contain data that record the user's + * specifications of which key holders are trustworthy introducers, + * along with other information that implementing software uses for + * trust information. The format of Trust packets is defined by a given + * implementation. + * + * Trust packets SHOULD NOT be emitted to output streams that are + * transferred to other users, and they SHOULD be ignored on any input + * other than local keyring files. + */ + class TrustPacket { + static get tag() { + return enums.packet.trust; + } + + /** + * Parsing function for a trust packet (tag 12). + * Currently not implemented as we ignore trust packets + */ + read() { + throw new UnsupportedError('Trust packets are not supported'); + } + + write() { + throw new UnsupportedError('Trust packets are not supported'); + } + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + // A Signature can contain the following packets + const allowedPackets$4 = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); + + /** + * Class that represents an OpenPGP signature. + */ + class Signature { + /** + * @param {PacketList} packetlist - The signature packets + */ + constructor(packetlist) { + this.packets = packetlist || new PacketList(); + } + + /** + * Returns binary encoded signature + * @returns {ReadableStream} Binary signature. + */ + write() { + return this.packets.write(); + } + + /** + * Returns ASCII armored text of signature + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {ReadableStream} ASCII armor. + */ + armor(config = defaultConfig) { + return armor(enums.armor.signature, this.write(), undefined, undefined, undefined, config); + } + + /** + * Returns an array of KeyIDs of all of the issuers who created this signature + * @returns {Array} The Key IDs of the signing keys + */ + getSigningKeyIDs() { + return this.packets.map(packet => packet.issuerKeyID); + } + } + + /** + * reads an (optionally armored) OpenPGP signature and returns a signature object + * @param {Object} options + * @param {String} [options.armoredSignature] - Armored signature to be parsed + * @param {Uint8Array} [options.binarySignature] - Binary signature to be parsed + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} New signature object. + * @async + * @static + */ + async function readSignature({ armoredSignature, binarySignature, config, ...rest }) { + config = { ...defaultConfig, ...config }; + let input = armoredSignature || binarySignature; + if (!input) { + throw new Error('readSignature: must pass options object containing `armoredSignature` or `binarySignature`'); + } + if (armoredSignature && !util.isString(armoredSignature)) { + throw new Error('readSignature: options.armoredSignature must be a string'); + } + if (binarySignature && !util.isUint8Array(binarySignature)) { + throw new Error('readSignature: options.binarySignature must be a Uint8Array'); + } + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + if (armoredSignature) { + const { type, data } = await unarmor(input, config); + if (type !== enums.armor.signature) { + throw new Error('Armored text not of type signature'); + } + input = data; + } + const packetlist = await PacketList.fromBinary(input, allowedPackets$4, config); + return new Signature(packetlist); + } + + /** + * @fileoverview Provides helpers methods for key module + * @module key/helper + * @private + */ + + async function generateSecretSubkey(options, config) { + const secretSubkeyPacket = new SecretSubkeyPacket(options.date, config); + secretSubkeyPacket.packets = null; + secretSubkeyPacket.algorithm = enums.write(enums.publicKey, options.algorithm); + await secretSubkeyPacket.generate(options.rsaBits, options.curve); + await secretSubkeyPacket.computeFingerprintAndKeyID(); + return secretSubkeyPacket; + } + + async function generateSecretKey(options, config) { + const secretKeyPacket = new SecretKeyPacket(options.date, config); + secretKeyPacket.packets = null; + secretKeyPacket.algorithm = enums.write(enums.publicKey, options.algorithm); + await secretKeyPacket.generate(options.rsaBits, options.curve, options.config); + await secretKeyPacket.computeFingerprintAndKeyID(); + return secretKeyPacket; + } + + /** + * Returns the valid and non-expired signature that has the latest creation date, while ignoring signatures created in the future. + * @param {Array} signatures - List of signatures + * @param {PublicKeyPacket|PublicSubkeyPacket} publicKey - Public key packet to verify the signature + * @param {Date} date - Use the given date instead of the current time + * @param {Object} config - full configuration + * @returns {Promise} The latest valid signature. + * @async + */ + async function getLatestValidSignature(signatures, publicKey, signatureType, dataToVerify, date = new Date(), config) { + let latestValid; + let exception; + for (let i = signatures.length - 1; i >= 0; i--) { + try { + if ( + (!latestValid || signatures[i].created >= latestValid.created) + ) { + await signatures[i].verify(publicKey, signatureType, dataToVerify, date, undefined, config); + latestValid = signatures[i]; + } + } catch (e) { + exception = e; + } + } + if (!latestValid) { + throw util.wrapError( + `Could not find valid ${enums.read(enums.signature, signatureType)} signature in key ${publicKey.getKeyID().toHex()}` + .replace('certGeneric ', 'self-') + .replace(/([a-z])([A-Z])/g, (_, $1, $2) => $1 + ' ' + $2.toLowerCase()) + , exception); + } + return latestValid; + } + + function isDataExpired(keyPacket, signature, date = new Date()) { + const normDate = util.normalizeDate(date); + if (normDate !== null) { + const expirationTime = getKeyExpirationTime(keyPacket, signature); + return !(keyPacket.created <= normDate && normDate < expirationTime); + } + return false; + } + + /** + * Create Binding signature to the key according to the {@link https://tools.ietf.org/html/rfc4880#section-5.2.1} + * @param {SecretSubkeyPacket} subkey - Subkey key packet + * @param {SecretKeyPacket} primaryKey - Primary key packet + * @param {Object} options + * @param {Object} config - Full configuration + */ + async function createBindingSignature(subkey, primaryKey, options, config) { + const dataToSign = {}; + dataToSign.key = primaryKey; + dataToSign.bind = subkey; + const subkeySignaturePacket = new SignaturePacket(); + subkeySignaturePacket.signatureType = enums.signature.subkeyBinding; + subkeySignaturePacket.publicKeyAlgorithm = primaryKey.algorithm; + subkeySignaturePacket.hashAlgorithm = await getPreferredHashAlgo$1(null, subkey, undefined, undefined, config); + if (options.sign) { + subkeySignaturePacket.keyFlags = [enums.keyFlags.signData]; + subkeySignaturePacket.embeddedSignature = await createSignaturePacket(dataToSign, null, subkey, { + signatureType: enums.signature.keyBinding + }, options.date, undefined, undefined, config); + } else { + subkeySignaturePacket.keyFlags = [enums.keyFlags.encryptCommunication | enums.keyFlags.encryptStorage]; + } + if (options.keyExpirationTime > 0) { + subkeySignaturePacket.keyExpirationTime = options.keyExpirationTime; + subkeySignaturePacket.keyNeverExpires = false; + } + await subkeySignaturePacket.sign(primaryKey, dataToSign, options.date); + return subkeySignaturePacket; + } + + /** + * Returns the preferred signature hash algorithm of a key + * @param {Key} [key] - The key to get preferences from + * @param {SecretKeyPacket|SecretSubkeyPacket} keyPacket - key packet used for signing + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} [userID] - User ID + * @param {Object} config - full configuration + * @returns {Promise} + * @async + */ + async function getPreferredHashAlgo$1(key, keyPacket, date = new Date(), userID = {}, config) { + let hashAlgo = config.preferredHashAlgorithm; + let prefAlgo = hashAlgo; + if (key) { + const primaryUser = await key.getPrimaryUser(date, userID, config); + if (primaryUser.selfCertification.preferredHashAlgorithms) { + [prefAlgo] = primaryUser.selfCertification.preferredHashAlgorithms; + hashAlgo = mod.hash.getHashByteLength(hashAlgo) <= mod.hash.getHashByteLength(prefAlgo) ? + prefAlgo : hashAlgo; + } + } + switch (Object.getPrototypeOf(keyPacket)) { + case SecretKeyPacket.prototype: + case PublicKeyPacket.prototype: + case SecretSubkeyPacket.prototype: + case PublicSubkeyPacket.prototype: + switch (keyPacket.algorithm) { + case enums.publicKey.ecdh: + case enums.publicKey.ecdsa: + case enums.publicKey.eddsa: + prefAlgo = mod.publicKey.elliptic.getPreferredHashAlgo(keyPacket.publicParams.oid); + } + } + return mod.hash.getHashByteLength(hashAlgo) <= mod.hash.getHashByteLength(prefAlgo) ? + prefAlgo : hashAlgo; + } + + /** + * Returns the preferred symmetric/aead/compression algorithm for a set of keys + * @param {'symmetric'|'aead'|'compression'} type - Type of preference to return + * @param {Array} [keys] - Set of keys + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Array} [userIDs] - User IDs + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} Preferred algorithm + * @async + */ + async function getPreferredAlgo(type, keys = [], date = new Date(), userIDs = [], config = defaultConfig) { + const defaultAlgo = { // these are all must-implement in rfc4880bis + 'symmetric': enums.symmetric.aes128, + 'aead': enums.aead.eax, + 'compression': enums.compression.uncompressed + }[type]; + const preferredSenderAlgo = { + 'symmetric': config.preferredSymmetricAlgorithm, + 'aead': config.preferredAEADAlgorithm, + 'compression': config.preferredCompressionAlgorithm + }[type]; + const prefPropertyName = { + 'symmetric': 'preferredSymmetricAlgorithms', + 'aead': 'preferredAEADAlgorithms', + 'compression': 'preferredCompressionAlgorithms' + }[type]; + + // if preferredSenderAlgo appears in the prefs of all recipients, we pick it + // otherwise we use the default algo + // if no keys are available, preferredSenderAlgo is returned + const senderAlgoSupport = await Promise.all(keys.map(async function(key, i) { + const primaryUser = await key.getPrimaryUser(date, userIDs[i], config); + const recipientPrefs = primaryUser.selfCertification[prefPropertyName]; + return !!recipientPrefs && recipientPrefs.indexOf(preferredSenderAlgo) >= 0; + })); + return senderAlgoSupport.every(Boolean) ? preferredSenderAlgo : defaultAlgo; + } + + /** + * Create signature packet + * @param {Object} dataToSign - Contains packets to be signed + * @param {PrivateKey} privateKey - key to get preferences from + * @param {SecretKeyPacket| + * SecretSubkeyPacket} signingKeyPacket secret key packet for signing + * @param {Object} [signatureProperties] - Properties to write on the signature packet before signing + * @param {Date} [date] - Override the creationtime of the signature + * @param {Object} [userID] - User ID + * @param {Object} [detached] - Whether to create a detached signature packet + * @param {Object} config - full configuration + * @returns {Promise} Signature packet. + */ + async function createSignaturePacket(dataToSign, privateKey, signingKeyPacket, signatureProperties, date, userID, detached = false, config) { + if (signingKeyPacket.isDummy()) { + throw new Error('Cannot sign with a gnu-dummy key.'); + } + if (!signingKeyPacket.isDecrypted()) { + throw new Error('Signing key is not decrypted.'); + } + const signaturePacket = new SignaturePacket(); + Object.assign(signaturePacket, signatureProperties); + signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm; + signaturePacket.hashAlgorithm = await getPreferredHashAlgo$1(privateKey, signingKeyPacket, date, userID, config); + await signaturePacket.sign(signingKeyPacket, dataToSign, date, detached); + return signaturePacket; + } + + /** + * Merges signatures from source[attr] to dest[attr] + * @param {Object} source + * @param {Object} dest + * @param {String} attr + * @param {Date} [date] - date to use for signature expiration check, instead of the current time + * @param {Function} [checkFn] - signature only merged if true + */ + async function mergeSignatures(source, dest, attr, date = new Date(), checkFn) { + source = source[attr]; + if (source) { + if (!dest[attr].length) { + dest[attr] = source; + } else { + await Promise.all(source.map(async function(sourceSig) { + if (!sourceSig.isExpired(date) && (!checkFn || await checkFn(sourceSig)) && + !dest[attr].some(function(destSig) { + return util.equalsUint8Array(destSig.writeParams(), sourceSig.writeParams()); + })) { + dest[attr].push(sourceSig); + } + })); + } + } + } + + /** + * Checks if a given certificate or binding signature is revoked + * @param {SecretKeyPacket| + * PublicKeyPacket} primaryKey The primary key packet + * @param {Object} dataToVerify - The data to check + * @param {Array} revocations - The revocation signatures to check + * @param {SignaturePacket} signature - The certificate or signature to check + * @param {PublicSubkeyPacket| + * SecretSubkeyPacket| + * PublicKeyPacket| + * SecretKeyPacket} key, optional The key packet to verify the signature, instead of the primary key + * @param {Date} date - Use the given date instead of the current time + * @param {Object} config - Full configuration + * @returns {Promise} True if the signature revokes the data. + * @async + */ + async function isDataRevoked(primaryKey, signatureType, dataToVerify, revocations, signature, key, date = new Date(), config) { + key = key || primaryKey; + const revocationKeyIDs = []; + await Promise.all(revocations.map(async function(revocationSignature) { + try { + if ( + // Note: a third-party revocation signature could legitimately revoke a + // self-signature if the signature has an authorized revocation key. + // However, we don't support passing authorized revocation keys, nor + // verifying such revocation signatures. Instead, we indicate an error + // when parsing a key with an authorized revocation key, and ignore + // third-party revocation signatures here. (It could also be revoking a + // third-party key certification, which should only affect + // `verifyAllCertifications`.) + !signature || revocationSignature.issuerKeyID.equals(signature.issuerKeyID) + ) { + await revocationSignature.verify( + key, signatureType, dataToVerify, config.revocationsExpire ? date : null, false, config + ); + + // TODO get an identifier of the revoked object instead + revocationKeyIDs.push(revocationSignature.issuerKeyID); + } + } catch (e) {} + })); + // TODO further verify that this is the signature that should be revoked + if (signature) { + signature.revoked = revocationKeyIDs.some(keyID => keyID.equals(signature.issuerKeyID)) ? true : + signature.revoked || false; + return signature.revoked; + } + return revocationKeyIDs.length > 0; + } + + /** + * Returns key expiration time based on the given certification signature. + * The expiration time of the signature is ignored. + * @param {PublicSubkeyPacket|PublicKeyPacket} keyPacket - key to check + * @param {SignaturePacket} signature - signature to process + * @returns {Date|Infinity} expiration time or infinity if the key does not expire + */ + function getKeyExpirationTime(keyPacket, signature) { + let expirationTime; + // check V4 expiration time + if (signature.keyNeverExpires === false) { + expirationTime = keyPacket.created.getTime() + signature.keyExpirationTime * 1000; + } + return expirationTime ? new Date(expirationTime) : Infinity; + } + + /** + * Returns whether aead is supported by all keys in the set + * @param {Array} keys - Set of keys + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Array} [userIDs] - User IDs + * @param {Object} config - full configuration + * @returns {Promise} + * @async + */ + async function isAEADSupported(keys, date = new Date(), userIDs = [], config = defaultConfig) { + let supported = true; + // TODO replace when Promise.some or Promise.any are implemented + await Promise.all(keys.map(async function(key, i) { + const primaryUser = await key.getPrimaryUser(date, userIDs[i], config); + if (!primaryUser.selfCertification.features || + !(primaryUser.selfCertification.features[0] & enums.features.aead)) { + supported = false; + } + })); + return supported; + } + + function sanitizeKeyOptions(options, subkeyDefaults = {}) { + options.type = options.type || subkeyDefaults.type; + options.curve = options.curve || subkeyDefaults.curve; + options.rsaBits = options.rsaBits || subkeyDefaults.rsaBits; + options.keyExpirationTime = options.keyExpirationTime !== undefined ? options.keyExpirationTime : subkeyDefaults.keyExpirationTime; + options.passphrase = util.isString(options.passphrase) ? options.passphrase : subkeyDefaults.passphrase; + options.date = options.date || subkeyDefaults.date; + + options.sign = options.sign || false; + + switch (options.type) { + case 'ecc': + try { + options.curve = enums.write(enums.curve, options.curve); + } catch (e) { + throw new Error('Invalid curve'); + } + if (options.curve === enums.curve.ed25519 || options.curve === enums.curve.curve25519) { + options.curve = options.sign ? enums.curve.ed25519 : enums.curve.curve25519; + } + if (options.sign) { + options.algorithm = options.curve === enums.curve.ed25519 ? enums.publicKey.eddsa : enums.publicKey.ecdsa; + } else { + options.algorithm = enums.publicKey.ecdh; + } + break; + case 'rsa': + options.algorithm = enums.publicKey.rsaEncryptSign; + break; + default: + throw new Error(`Unsupported key type ${options.type}`); + } + return options; + } + + function isValidSigningKeyPacket(keyPacket, signature) { + const keyAlgo = keyPacket.algorithm; + return keyAlgo !== enums.publicKey.rsaEncrypt && + keyAlgo !== enums.publicKey.elgamal && + keyAlgo !== enums.publicKey.ecdh && + (!signature.keyFlags || + (signature.keyFlags[0] & enums.keyFlags.signData) !== 0); + } + + function isValidEncryptionKeyPacket(keyPacket, signature) { + const keyAlgo = keyPacket.algorithm; + return keyAlgo !== enums.publicKey.dsa && + keyAlgo !== enums.publicKey.rsaSign && + keyAlgo !== enums.publicKey.ecdsa && + keyAlgo !== enums.publicKey.eddsa && + (!signature.keyFlags || + (signature.keyFlags[0] & enums.keyFlags.encryptCommunication) !== 0 || + (signature.keyFlags[0] & enums.keyFlags.encryptStorage) !== 0); + } + + function isValidDecryptionKeyPacket(signature, config) { + if (config.allowInsecureDecryptionWithSigningKeys) { + // This is only relevant for RSA keys, all other signing algorithms cannot decrypt + return true; + } + + return !signature.keyFlags || + (signature.keyFlags[0] & enums.keyFlags.encryptCommunication) !== 0 || + (signature.keyFlags[0] & enums.keyFlags.encryptStorage) !== 0; + } + + /** + * Check key against blacklisted algorithms and minimum strength requirements. + * @param {SecretKeyPacket|PublicKeyPacket| + * SecretSubkeyPacket|PublicSubkeyPacket} keyPacket + * @param {Config} config + * @throws {Error} if the key packet does not meet the requirements + */ + function checkKeyRequirements(keyPacket, config) { + const keyAlgo = enums.write(enums.publicKey, keyPacket.algorithm); + const algoInfo = keyPacket.getAlgorithmInfo(); + if (config.rejectPublicKeyAlgorithms.has(keyAlgo)) { + throw new Error(`${algoInfo.algorithm} keys are considered too weak.`); + } + switch (keyAlgo) { + case enums.publicKey.rsaEncryptSign: + case enums.publicKey.rsaSign: + case enums.publicKey.rsaEncrypt: + if (algoInfo.bits < config.minRSABits) { + throw new Error(`RSA keys shorter than ${config.minRSABits} bits are considered too weak.`); + } + break; + case enums.publicKey.ecdsa: + case enums.publicKey.eddsa: + case enums.publicKey.ecdh: + if (config.rejectCurves.has(algoInfo.curve)) { + throw new Error(`Support for ${algoInfo.algorithm} keys using curve ${algoInfo.curve} is disabled.`); + } + break; + } + } + + /** + * @module key/User + * @private + */ + + /** + * Class that represents an user ID or attribute packet and the relevant signatures. + * @param {UserIDPacket|UserAttributePacket} userPacket - packet containing the user info + * @param {Key} mainKey - reference to main Key object containing the primary key and subkeys that the user is associated with + */ + class User { + constructor(userPacket, mainKey) { + this.userID = userPacket.constructor.tag === enums.packet.userID ? userPacket : null; + this.userAttribute = userPacket.constructor.tag === enums.packet.userAttribute ? userPacket : null; + this.selfCertifications = []; + this.otherCertifications = []; + this.revocationSignatures = []; + this.mainKey = mainKey; + } + + /** + * Transforms structured user data to packetlist + * @returns {PacketList} + */ + toPacketList() { + const packetlist = new PacketList(); + packetlist.push(this.userID || this.userAttribute); + packetlist.push(...this.revocationSignatures); + packetlist.push(...this.selfCertifications); + packetlist.push(...this.otherCertifications); + return packetlist; + } + + /** + * Shallow clone + * @returns {User} + */ + clone() { + const user = new User(this.userID || this.userAttribute, this.mainKey); + user.selfCertifications = [...this.selfCertifications]; + user.otherCertifications = [...this.otherCertifications]; + user.revocationSignatures = [...this.revocationSignatures]; + return user; + } + + /** + * Generate third-party certifications over this user and its primary key + * @param {Array} signingKeys - Decrypted private keys for signing + * @param {Date} [date] - Date to use as creation date of the certificate, instead of the current time + * @param {Object} config - Full configuration + * @returns {Promise} New user with new certifications. + * @async + */ + async certify(signingKeys, date, config) { + const primaryKey = this.mainKey.keyPacket; + const dataToSign = { + userID: this.userID, + userAttribute: this.userAttribute, + key: primaryKey + }; + const user = new User(dataToSign.userID || dataToSign.userAttribute, this.mainKey); + user.otherCertifications = await Promise.all(signingKeys.map(async function(privateKey) { + if (!privateKey.isPrivate()) { + throw new Error('Need private key for signing'); + } + if (privateKey.hasSameFingerprintAs(primaryKey)) { + throw new Error("The user's own key can only be used for self-certifications"); + } + const signingKey = await privateKey.getSigningKey(undefined, date, undefined, config); + return createSignaturePacket(dataToSign, privateKey, signingKey.keyPacket, { + // Most OpenPGP implementations use generic certification (0x10) + signatureType: enums.signature.certGeneric, + keyFlags: [enums.keyFlags.certifyKeys | enums.keyFlags.signData] + }, date, undefined, undefined, config); + })); + await user.update(this, date, config); + return user; + } + + /** + * Checks if a given certificate of the user is revoked + * @param {SignaturePacket} certificate - The certificate to verify + * @param {PublicSubkeyPacket| + * SecretSubkeyPacket| + * PublicKeyPacket| + * SecretKeyPacket} [keyPacket] The key packet to verify the signature, instead of the primary key + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} config - Full configuration + * @returns {Promise} True if the certificate is revoked. + * @async + */ + async isRevoked(certificate, keyPacket, date = new Date(), config) { + const primaryKey = this.mainKey.keyPacket; + return isDataRevoked(primaryKey, enums.signature.certRevocation, { + key: primaryKey, + userID: this.userID, + userAttribute: this.userAttribute + }, this.revocationSignatures, certificate, keyPacket, date, config); + } + + /** + * Verifies the user certificate. + * @param {SignaturePacket} certificate - A certificate of this user + * @param {Array} verificationKeys - Array of keys to verify certificate signatures + * @param {Date} [date] - Use the given date instead of the current time + * @param {Object} config - Full configuration + * @returns {Promise} true if the certificate could be verified, or null if the verification keys do not correspond to the certificate + * @throws if the user certificate is invalid. + * @async + */ + async verifyCertificate(certificate, verificationKeys, date = new Date(), config) { + const that = this; + const primaryKey = this.mainKey.keyPacket; + const dataToVerify = { + userID: this.userID, + userAttribute: this.userAttribute, + key: primaryKey + }; + const { issuerKeyID } = certificate; + const issuerKeys = verificationKeys.filter(key => key.getKeys(issuerKeyID).length > 0); + if (issuerKeys.length === 0) { + return null; + } + await Promise.all(issuerKeys.map(async key => { + const signingKey = await key.getSigningKey(issuerKeyID, certificate.created, undefined, config); + if (certificate.revoked || await that.isRevoked(certificate, signingKey.keyPacket, date, config)) { + throw new Error('User certificate is revoked'); + } + try { + await certificate.verify(signingKey.keyPacket, enums.signature.certGeneric, dataToVerify, date, undefined, config); + } catch (e) { + throw util.wrapError('User certificate is invalid', e); + } + })); + return true; + } + + /** + * Verifies all user certificates + * @param {Array} verificationKeys - Array of keys to verify certificate signatures + * @param {Date} [date] - Use the given date instead of the current time + * @param {Object} config - Full configuration + * @returns {Promise>} List of signer's keyID and validity of signature. + * Signature validity is null if the verification keys do not correspond to the certificate. + * @async + */ + async verifyAllCertifications(verificationKeys, date = new Date(), config) { + const that = this; + const certifications = this.selfCertifications.concat(this.otherCertifications); + return Promise.all(certifications.map(async certification => ({ + keyID: certification.issuerKeyID, + valid: await that.verifyCertificate(certification, verificationKeys, date, config).catch(() => false) + }))); + } + + /** + * Verify User. Checks for existence of self signatures, revocation signatures + * and validity of self signature. + * @param {Date} date - Use the given date instead of the current time + * @param {Object} config - Full configuration + * @returns {Promise} Status of user. + * @throws {Error} if there are no valid self signatures. + * @async + */ + async verify(date = new Date(), config) { + if (!this.selfCertifications.length) { + throw new Error('No self-certifications found'); + } + const that = this; + const primaryKey = this.mainKey.keyPacket; + const dataToVerify = { + userID: this.userID, + userAttribute: this.userAttribute, + key: primaryKey + }; + // TODO replace when Promise.some or Promise.any are implemented + let exception; + for (let i = this.selfCertifications.length - 1; i >= 0; i--) { + try { + const selfCertification = this.selfCertifications[i]; + if (selfCertification.revoked || await that.isRevoked(selfCertification, undefined, date, config)) { + throw new Error('Self-certification is revoked'); + } + try { + await selfCertification.verify(primaryKey, enums.signature.certGeneric, dataToVerify, date, undefined, config); + } catch (e) { + throw util.wrapError('Self-certification is invalid', e); + } + return true; + } catch (e) { + exception = e; + } + } + throw exception; + } + + /** + * Update user with new components from specified user + * @param {User} sourceUser - Source user to merge + * @param {Date} date - Date to verify the validity of signatures + * @param {Object} config - Full configuration + * @returns {Promise} + * @async + */ + async update(sourceUser, date, config) { + const primaryKey = this.mainKey.keyPacket; + const dataToVerify = { + userID: this.userID, + userAttribute: this.userAttribute, + key: primaryKey + }; + // self signatures + await mergeSignatures(sourceUser, this, 'selfCertifications', date, async function(srcSelfSig) { + try { + await srcSelfSig.verify(primaryKey, enums.signature.certGeneric, dataToVerify, date, false, config); + return true; + } catch (e) { + return false; + } + }); + // other signatures + await mergeSignatures(sourceUser, this, 'otherCertifications', date); + // revocation signatures + await mergeSignatures(sourceUser, this, 'revocationSignatures', date, function(srcRevSig) { + return isDataRevoked(primaryKey, enums.signature.certRevocation, dataToVerify, [srcRevSig], undefined, undefined, date, config); + }); + } + } + + /** + * @module key/Subkey + * @private + */ + + /** + * Class that represents a subkey packet and the relevant signatures. + * @borrows PublicSubkeyPacket#getKeyID as Subkey#getKeyID + * @borrows PublicSubkeyPacket#getFingerprint as Subkey#getFingerprint + * @borrows PublicSubkeyPacket#hasSameFingerprintAs as Subkey#hasSameFingerprintAs + * @borrows PublicSubkeyPacket#getAlgorithmInfo as Subkey#getAlgorithmInfo + * @borrows PublicSubkeyPacket#getCreationTime as Subkey#getCreationTime + * @borrows PublicSubkeyPacket#isDecrypted as Subkey#isDecrypted + */ + class Subkey { + /** + * @param {SecretSubkeyPacket|PublicSubkeyPacket} subkeyPacket - subkey packet to hold in the Subkey + * @param {Key} mainKey - reference to main Key object, containing the primary key packet corresponding to the subkey + */ + constructor(subkeyPacket, mainKey) { + this.keyPacket = subkeyPacket; + this.bindingSignatures = []; + this.revocationSignatures = []; + this.mainKey = mainKey; + } + + /** + * Transforms structured subkey data to packetlist + * @returns {PacketList} + */ + toPacketList() { + const packetlist = new PacketList(); + packetlist.push(this.keyPacket); + packetlist.push(...this.revocationSignatures); + packetlist.push(...this.bindingSignatures); + return packetlist; + } + + /** + * Shallow clone + * @return {Subkey} + */ + clone() { + const subkey = new Subkey(this.keyPacket, this.mainKey); + subkey.bindingSignatures = [...this.bindingSignatures]; + subkey.revocationSignatures = [...this.revocationSignatures]; + return subkey; + } + + /** + * Checks if a binding signature of a subkey is revoked + * @param {SignaturePacket} signature - The binding signature to verify + * @param {PublicSubkeyPacket| + * SecretSubkeyPacket| + * PublicKeyPacket| + * SecretKeyPacket} key, optional The key to verify the signature + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} True if the binding signature is revoked. + * @async + */ + async isRevoked(signature, key, date = new Date(), config = defaultConfig) { + const primaryKey = this.mainKey.keyPacket; + return isDataRevoked( + primaryKey, enums.signature.subkeyRevocation, { + key: primaryKey, + bind: this.keyPacket + }, this.revocationSignatures, signature, key, date, config + ); + } + + /** + * Verify subkey. Checks for revocation signatures, expiration time + * and valid binding signature. + * @param {Date} date - Use the given date instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} + * @throws {Error} if the subkey is invalid. + * @async + */ + async verify(date = new Date(), config = defaultConfig) { + const primaryKey = this.mainKey.keyPacket; + const dataToVerify = { key: primaryKey, bind: this.keyPacket }; + // check subkey binding signatures + const bindingSignature = await getLatestValidSignature(this.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); + // check binding signature is not revoked + if (bindingSignature.revoked || await this.isRevoked(bindingSignature, null, date, config)) { + throw new Error('Subkey is revoked'); + } + // check for expiration time + if (isDataExpired(this.keyPacket, bindingSignature, date)) { + throw new Error('Subkey is expired'); + } + return bindingSignature; + } + + /** + * Returns the expiration time of the subkey or Infinity if key does not expire. + * Returns null if the subkey is invalid. + * @param {Date} date - Use the given date instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} + * @async + */ + async getExpirationTime(date = new Date(), config = defaultConfig) { + const primaryKey = this.mainKey.keyPacket; + const dataToVerify = { key: primaryKey, bind: this.keyPacket }; + let bindingSignature; + try { + bindingSignature = await getLatestValidSignature(this.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); + } catch (e) { + return null; + } + const keyExpiry = getKeyExpirationTime(this.keyPacket, bindingSignature); + const sigExpiry = bindingSignature.getExpirationTime(); + return keyExpiry < sigExpiry ? keyExpiry : sigExpiry; + } + + /** + * Update subkey with new components from specified subkey + * @param {Subkey} subkey - Source subkey to merge + * @param {Date} [date] - Date to verify validity of signatures + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if update failed + * @async + */ + async update(subkey, date = new Date(), config = defaultConfig) { + const primaryKey = this.mainKey.keyPacket; + if (!this.hasSameFingerprintAs(subkey)) { + throw new Error('Subkey update method: fingerprints of subkeys not equal'); + } + // key packet + if (this.keyPacket.constructor.tag === enums.packet.publicSubkey && + subkey.keyPacket.constructor.tag === enums.packet.secretSubkey) { + this.keyPacket = subkey.keyPacket; + } + // update missing binding signatures + const that = this; + const dataToVerify = { key: primaryKey, bind: that.keyPacket }; + await mergeSignatures(subkey, this, 'bindingSignatures', date, async function(srcBindSig) { + for (let i = 0; i < that.bindingSignatures.length; i++) { + if (that.bindingSignatures[i].issuerKeyID.equals(srcBindSig.issuerKeyID)) { + if (srcBindSig.created > that.bindingSignatures[i].created) { + that.bindingSignatures[i] = srcBindSig; + } + return false; + } + } + try { + await srcBindSig.verify(primaryKey, enums.signature.subkeyBinding, dataToVerify, date, undefined, config); + return true; + } catch (e) { + return false; + } + }); + // revocation signatures + await mergeSignatures(subkey, this, 'revocationSignatures', date, function(srcRevSig) { + return isDataRevoked(primaryKey, enums.signature.subkeyRevocation, dataToVerify, [srcRevSig], undefined, undefined, date, config); + }); + } + + /** + * Revokes the subkey + * @param {SecretKeyPacket} primaryKey - decrypted private primary key for revocation + * @param {Object} reasonForRevocation - optional, object indicating the reason for revocation + * @param {module:enums.reasonForRevocation} reasonForRevocation.flag optional, flag indicating the reason for revocation + * @param {String} reasonForRevocation.string optional, string explaining the reason for revocation + * @param {Date} date - optional, override the creationtime of the revocation signature + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New subkey with revocation signature. + * @async + */ + async revoke( + primaryKey, + { + flag: reasonForRevocationFlag = enums.reasonForRevocation.noReason, + string: reasonForRevocationString = '' + } = {}, + date = new Date(), + config = defaultConfig + ) { + const dataToSign = { key: primaryKey, bind: this.keyPacket }; + const subkey = new Subkey(this.keyPacket, this.mainKey); + subkey.revocationSignatures.push(await createSignaturePacket(dataToSign, null, primaryKey, { + signatureType: enums.signature.subkeyRevocation, + reasonForRevocationFlag: enums.write(enums.reasonForRevocation, reasonForRevocationFlag), + reasonForRevocationString + }, date, undefined, false, config)); + await subkey.update(this); + return subkey; + } + + hasSameFingerprintAs(other) { + return this.keyPacket.hasSameFingerprintAs(other.keyPacket || other); + } + } + + ['getKeyID', 'getFingerprint', 'getAlgorithmInfo', 'getCreationTime', 'isDecrypted'].forEach(name => { + Subkey.prototype[name] = + function() { + return this.keyPacket[name](); + }; + }); + + // GPG4Browsers - An OpenPGP implementation in javascript + + // A key revocation certificate can contain the following packets + const allowedRevocationPackets = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); + + /** + * Abstract class that represents an OpenPGP key. Must contain a primary key. + * Can contain additional subkeys, signatures, user ids, user attributes. + * @borrows PublicKeyPacket#getKeyID as Key#getKeyID + * @borrows PublicKeyPacket#getFingerprint as Key#getFingerprint + * @borrows PublicKeyPacket#hasSameFingerprintAs as Key#hasSameFingerprintAs + * @borrows PublicKeyPacket#getAlgorithmInfo as Key#getAlgorithmInfo + * @borrows PublicKeyPacket#getCreationTime as Key#getCreationTime + */ + class Key { + /** + * Transforms packetlist to structured key data + * @param {PacketList} packetlist - The packets that form a key + * @param {Set} disallowedPackets - disallowed packet tags + */ + packetListToStructure(packetlist, disallowedPackets = new Set()) { + let user; + let primaryKeyID; + let subkey; + for (const packet of packetlist) { + const tag = packet.constructor.tag; + if (disallowedPackets.has(tag)) { + throw new Error(`Unexpected packet type: ${tag}`); + } + switch (tag) { + case enums.packet.publicKey: + case enums.packet.secretKey: + if (this.keyPacket) { + throw new Error('Key block contains multiple keys'); + } + this.keyPacket = packet; + primaryKeyID = this.getKeyID(); + if (!primaryKeyID) { + throw new Error('Missing Key ID'); + } + break; + case enums.packet.userID: + case enums.packet.userAttribute: + user = new User(packet, this); + this.users.push(user); + break; + case enums.packet.publicSubkey: + case enums.packet.secretSubkey: + user = null; + subkey = new Subkey(packet, this); + this.subkeys.push(subkey); + break; + case enums.packet.signature: + switch (packet.signatureType) { + case enums.signature.certGeneric: + case enums.signature.certPersona: + case enums.signature.certCasual: + case enums.signature.certPositive: + if (!user) { + util.printDebug('Dropping certification signatures without preceding user packet'); + continue; + } + if (packet.issuerKeyID.equals(primaryKeyID)) { + user.selfCertifications.push(packet); + } else { + user.otherCertifications.push(packet); + } + break; + case enums.signature.certRevocation: + if (user) { + user.revocationSignatures.push(packet); + } else { + this.directSignatures.push(packet); + } + break; + case enums.signature.key: + this.directSignatures.push(packet); + break; + case enums.signature.subkeyBinding: + if (!subkey) { + util.printDebug('Dropping subkey binding signature without preceding subkey packet'); + continue; + } + subkey.bindingSignatures.push(packet); + break; + case enums.signature.keyRevocation: + this.revocationSignatures.push(packet); + break; + case enums.signature.subkeyRevocation: + if (!subkey) { + util.printDebug('Dropping subkey revocation signature without preceding subkey packet'); + continue; + } + subkey.revocationSignatures.push(packet); + break; + } + break; + } + } + } + + /** + * Transforms structured key data to packetlist + * @returns {PacketList} The packets that form a key. + */ + toPacketList() { + const packetlist = new PacketList(); + packetlist.push(this.keyPacket); + packetlist.push(...this.revocationSignatures); + packetlist.push(...this.directSignatures); + this.users.map(user => packetlist.push(...user.toPacketList())); + this.subkeys.map(subkey => packetlist.push(...subkey.toPacketList())); + return packetlist; + } + + /** + * Clones the key object + * @param {Boolean} [deep=false] Whether to return a deep clone + * @returns {Promise} Clone of the key. + */ + clone(deep = false) { + const key = new this.constructor(this.toPacketList()); + if (deep) { + key.getKeys().forEach(k => { + // shallow clone the key packets + k.keyPacket = Object.create( + Object.getPrototypeOf(k.keyPacket), + Object.getOwnPropertyDescriptors(k.keyPacket) + ); + if (!k.keyPacket.isDecrypted()) return; + // deep clone the private params, which are cleared during encryption + const privateParams = {}; + Object.keys(k.keyPacket.privateParams).forEach(name => { + privateParams[name] = new Uint8Array(k.keyPacket.privateParams[name]); + }); + k.keyPacket.privateParams = privateParams; + }); + } + return key; + } + + /** + * Returns an array containing all public or private subkeys matching keyID; + * If no keyID is given, returns all subkeys. + * @param {type/keyID} [keyID] - key ID to look for + * @returns {Array} array of subkeys + */ + getSubkeys(keyID = null) { + const subkeys = this.subkeys.filter(subkey => ( + !keyID || subkey.getKeyID().equals(keyID, true) + )); + return subkeys; + } + + /** + * Returns an array containing all public or private keys matching keyID. + * If no keyID is given, returns all keys, starting with the primary key. + * @param {type/keyid~KeyID} [keyID] - key ID to look for + * @returns {Array} array of keys + */ + getKeys(keyID = null) { + const keys = []; + if (!keyID || this.getKeyID().equals(keyID, true)) { + keys.push(this); + } + return keys.concat(this.getSubkeys(keyID)); + } + + /** + * Returns key IDs of all keys + * @returns {Array} + */ + getKeyIDs() { + return this.getKeys().map(key => key.getKeyID()); + } + + /** + * Returns userIDs + * @returns {Array} Array of userIDs. + */ + getUserIDs() { + return this.users.map(user => { + return user.userID ? user.userID.userID : null; + }).filter(userID => userID !== null); + } + + /** + * Returns binary encoded key + * @returns {Uint8Array} Binary key. + */ + write() { + return this.toPacketList().write(); + } + + /** + * Returns last created key or key by given keyID that is available for signing and verification + * @param {module:type/keyid~KeyID} [keyID] - key ID of a specific key to retrieve + * @param {Date} [date] - use the fiven date date to to check key validity instead of the current date + * @param {Object} [userID] - filter keys for the given user ID + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} signing key + * @throws if no valid signing key was found + * @async + */ + async getSigningKey(keyID = null, date = new Date(), userID = {}, config = defaultConfig) { + await this.verifyPrimaryKey(date, userID, config); + const primaryKey = this.keyPacket; + const subkeys = this.subkeys.slice().sort((a, b) => b.keyPacket.created - a.keyPacket.created); + let exception; + for (const subkey of subkeys) { + if (!keyID || subkey.getKeyID().equals(keyID)) { + try { + await subkey.verify(date, config); + const dataToVerify = { key: primaryKey, bind: subkey.keyPacket }; + const bindingSignature = await getLatestValidSignature( + subkey.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config + ); + if (!isValidSigningKeyPacket(subkey.keyPacket, bindingSignature)) { + continue; + } + if (!bindingSignature.embeddedSignature) { + throw new Error('Missing embedded signature'); + } + // verify embedded signature + await getLatestValidSignature( + [bindingSignature.embeddedSignature], subkey.keyPacket, enums.signature.keyBinding, dataToVerify, date, config + ); + checkKeyRequirements(subkey.keyPacket, config); + return subkey; + } catch (e) { + exception = e; + } + } + } + + try { + const primaryUser = await this.getPrimaryUser(date, userID, config); + if ((!keyID || primaryKey.getKeyID().equals(keyID)) && + isValidSigningKeyPacket(primaryKey, primaryUser.selfCertification, config)) { + checkKeyRequirements(primaryKey, config); + return this; + } + } catch (e) { + exception = e; + } + throw util.wrapError('Could not find valid signing key packet in key ' + this.getKeyID().toHex(), exception); + } + + /** + * Returns last created key or key by given keyID that is available for encryption or decryption + * @param {module:type/keyid~KeyID} [keyID] - key ID of a specific key to retrieve + * @param {Date} [date] - use the fiven date date to to check key validity instead of the current date + * @param {Object} [userID] - filter keys for the given user ID + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} encryption key + * @throws if no valid encryption key was found + * @async + */ + async getEncryptionKey(keyID, date = new Date(), userID = {}, config = defaultConfig) { + await this.verifyPrimaryKey(date, userID, config); + const primaryKey = this.keyPacket; + // V4: by convention subkeys are preferred for encryption service + const subkeys = this.subkeys.slice().sort((a, b) => b.keyPacket.created - a.keyPacket.created); + let exception; + for (const subkey of subkeys) { + if (!keyID || subkey.getKeyID().equals(keyID)) { + try { + await subkey.verify(date, config); + const dataToVerify = { key: primaryKey, bind: subkey.keyPacket }; + const bindingSignature = await getLatestValidSignature(subkey.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); + if (isValidEncryptionKeyPacket(subkey.keyPacket, bindingSignature)) { + checkKeyRequirements(subkey.keyPacket, config); + return subkey; + } + } catch (e) { + exception = e; + } + } + } + + try { + // if no valid subkey for encryption, evaluate primary key + const primaryUser = await this.getPrimaryUser(date, userID, config); + if ((!keyID || primaryKey.getKeyID().equals(keyID)) && + isValidEncryptionKeyPacket(primaryKey, primaryUser.selfCertification)) { + checkKeyRequirements(primaryKey, config); + return this; + } + } catch (e) { + exception = e; + } + throw util.wrapError('Could not find valid encryption key packet in key ' + this.getKeyID().toHex(), exception); + } + + /** + * Checks if a signature on a key is revoked + * @param {SignaturePacket} signature - The signature to verify + * @param {PublicSubkeyPacket| + * SecretSubkeyPacket| + * PublicKeyPacket| + * SecretKeyPacket} key, optional The key to verify the signature + * @param {Date} [date] - Use the given date for verification, instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} True if the certificate is revoked. + * @async + */ + async isRevoked(signature, key, date = new Date(), config = defaultConfig) { + return isDataRevoked( + this.keyPacket, enums.signature.keyRevocation, { key: this.keyPacket }, this.revocationSignatures, signature, key, date, config + ); + } + + /** + * Verify primary key. Checks for revocation signatures, expiration time + * and valid self signature. Throws if the primary key is invalid. + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} [userID] - User ID + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} If key verification failed + * @async + */ + async verifyPrimaryKey(date = new Date(), userID = {}, config = defaultConfig) { + const primaryKey = this.keyPacket; + // check for key revocation signatures + if (await this.isRevoked(null, null, date, config)) { + throw new Error('Primary key is revoked'); + } + // check for valid, unrevoked, unexpired self signature + const { selfCertification } = await this.getPrimaryUser(date, userID, config); + // check for expiration time in binding signatures + if (isDataExpired(primaryKey, selfCertification, date)) { + throw new Error('Primary key is expired'); + } + // check for expiration time in direct signatures + const directSignature = await getLatestValidSignature( + this.directSignatures, primaryKey, enums.signature.key, { key: primaryKey }, date, config + ).catch(() => {}); // invalid signatures are discarded, to avoid breaking the key + + if (directSignature && isDataExpired(primaryKey, directSignature, date)) { + throw new Error('Primary key is expired'); + } + } + + /** + * Returns the expiration date of the primary key, considering self-certifications and direct-key signatures. + * Returns `Infinity` if the key doesn't expire, or `null` if the key is revoked or invalid. + * @param {Object} [userID] - User ID to consider instead of the primary user + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} + * @async + */ + async getExpirationTime(userID, config = defaultConfig) { + let primaryKeyExpiry; + try { + const { selfCertification } = await this.getPrimaryUser(null, userID, config); + const selfSigKeyExpiry = getKeyExpirationTime(this.keyPacket, selfCertification); + const selfSigExpiry = selfCertification.getExpirationTime(); + const directSignature = await getLatestValidSignature( + this.directSignatures, this.keyPacket, enums.signature.key, { key: this.keyPacket }, null, config + ).catch(() => {}); + if (directSignature) { + const directSigKeyExpiry = getKeyExpirationTime(this.keyPacket, directSignature); + // We do not support the edge case where the direct signature expires, since it would invalidate the corresponding key expiration, + // causing a discountinous validy period for the key + primaryKeyExpiry = Math.min(selfSigKeyExpiry, selfSigExpiry, directSigKeyExpiry); + } else { + primaryKeyExpiry = selfSigKeyExpiry < selfSigExpiry ? selfSigKeyExpiry : selfSigExpiry; + } + } catch (e) { + primaryKeyExpiry = null; + } + + return util.normalizeDate(primaryKeyExpiry); + } + + + /** + * Returns primary user and most significant (latest valid) self signature + * - if multiple primary users exist, returns the one with the latest self signature + * - otherwise, returns the user with the latest self signature + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} [userID] - User ID to get instead of the primary user, if it exists + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise<{ + * user: User, + * selfCertification: SignaturePacket + * }>} The primary user and the self signature + * @async + */ + async getPrimaryUser(date = new Date(), userID = {}, config = defaultConfig) { + const primaryKey = this.keyPacket; + const users = []; + let exception; + for (let i = 0; i < this.users.length; i++) { + try { + const user = this.users[i]; + if (!user.userID) { + continue; + } + if ( + (userID.name !== undefined && user.userID.name !== userID.name) || + (userID.email !== undefined && user.userID.email !== userID.email) || + (userID.comment !== undefined && user.userID.comment !== userID.comment) + ) { + throw new Error('Could not find user that matches that user ID'); + } + const dataToVerify = { userID: user.userID, key: primaryKey }; + const selfCertification = await getLatestValidSignature(user.selfCertifications, primaryKey, enums.signature.certGeneric, dataToVerify, date, config); + users.push({ index: i, user, selfCertification }); + } catch (e) { + exception = e; + } + } + if (!users.length) { + throw exception || new Error('Could not find primary user'); + } + await Promise.all(users.map(async function (a) { + return a.user.revoked || a.user.isRevoked(a.selfCertification, null, date, config); + })); + // sort by primary user flag and signature creation time + const primaryUser = users.sort(function(a, b) { + const A = a.selfCertification; + const B = b.selfCertification; + return B.revoked - A.revoked || A.isPrimaryUserID - B.isPrimaryUserID || A.created - B.created; + }).pop(); + const { user, selfCertification: cert } = primaryUser; + if (cert.revoked || await user.isRevoked(cert, null, date, config)) { + throw new Error('Primary user is revoked'); + } + return primaryUser; + } + + /** + * Update key with new components from specified key with same key ID: + * users, subkeys, certificates are merged into the destination key, + * duplicates and expired signatures are ignored. + * + * If the source key is a private key and the destination key is public, + * a private key is returned. + * @param {Key} sourceKey - Source key to merge + * @param {Date} [date] - Date to verify validity of signatures and keys + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} updated key + * @async + */ + async update(sourceKey, date = new Date(), config = defaultConfig) { + if (!this.hasSameFingerprintAs(sourceKey)) { + throw new Error('Primary key fingerprints must be equal to update the key'); + } + if (!this.isPrivate() && sourceKey.isPrivate()) { + // check for equal subkey packets + const equal = (this.subkeys.length === sourceKey.subkeys.length) && + (this.subkeys.every(destSubkey => { + return sourceKey.subkeys.some(srcSubkey => { + return destSubkey.hasSameFingerprintAs(srcSubkey); + }); + })); + if (!equal) { + throw new Error('Cannot update public key with private key if subkeys mismatch'); + } + + return sourceKey.update(this, config); + } + // from here on, either: + // - destination key is private, source key is public + // - the keys are of the same type + // hence we don't need to convert the destination key type + const updatedKey = this.clone(); + // revocation signatures + await mergeSignatures(sourceKey, updatedKey, 'revocationSignatures', date, srcRevSig => { + return isDataRevoked(updatedKey.keyPacket, enums.signature.keyRevocation, updatedKey, [srcRevSig], null, sourceKey.keyPacket, date, config); + }); + // direct signatures + await mergeSignatures(sourceKey, updatedKey, 'directSignatures', date); + // update users + await Promise.all(sourceKey.users.map(async srcUser => { + // multiple users with the same ID/attribute are not explicitly disallowed by the spec + // hence we support them, just in case + const usersToUpdate = updatedKey.users.filter(dstUser => ( + (srcUser.userID && srcUser.userID.equals(dstUser.userID)) || + (srcUser.userAttribute && srcUser.userAttribute.equals(dstUser.userAttribute)) + )); + if (usersToUpdate.length > 0) { + await Promise.all( + usersToUpdate.map(userToUpdate => userToUpdate.update(srcUser, date, config)) + ); + } else { + const newUser = srcUser.clone(); + newUser.mainKey = updatedKey; + updatedKey.users.push(newUser); + } + })); + // update subkeys + await Promise.all(sourceKey.subkeys.map(async srcSubkey => { + // multiple subkeys with same fingerprint might be preset + const subkeysToUpdate = updatedKey.subkeys.filter(dstSubkey => ( + dstSubkey.hasSameFingerprintAs(srcSubkey) + )); + if (subkeysToUpdate.length > 0) { + await Promise.all( + subkeysToUpdate.map(subkeyToUpdate => subkeyToUpdate.update(srcSubkey, date, config)) + ); + } else { + const newSubkey = srcSubkey.clone(); + newSubkey.mainKey = updatedKey; + updatedKey.subkeys.push(newSubkey); + } + })); + + return updatedKey; + } + + /** + * Get revocation certificate from a revoked key. + * (To get a revocation certificate for an unrevoked key, call revoke() first.) + * @param {Date} date - Use the given date instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} Armored revocation certificate. + * @async + */ + async getRevocationCertificate(date = new Date(), config = defaultConfig) { + const dataToVerify = { key: this.keyPacket }; + const revocationSignature = await getLatestValidSignature(this.revocationSignatures, this.keyPacket, enums.signature.keyRevocation, dataToVerify, date, config); + const packetlist = new PacketList(); + packetlist.push(revocationSignature); + return armor(enums.armor.publicKey, packetlist.write(), null, null, 'This is a revocation certificate'); + } + + /** + * Applies a revocation certificate to a key + * This adds the first signature packet in the armored text to the key, + * if it is a valid revocation signature. + * @param {String} revocationCertificate - armored revocation certificate + * @param {Date} [date] - Date to verify the certificate + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} Revoked key. + * @async + */ + async applyRevocationCertificate(revocationCertificate, date = new Date(), config = defaultConfig) { + const input = await unarmor(revocationCertificate, config); + const packetlist = await PacketList.fromBinary(input.data, allowedRevocationPackets, config); + const revocationSignature = packetlist.findPacket(enums.packet.signature); + if (!revocationSignature || revocationSignature.signatureType !== enums.signature.keyRevocation) { + throw new Error('Could not find revocation signature packet'); + } + if (!revocationSignature.issuerKeyID.equals(this.getKeyID())) { + throw new Error('Revocation signature does not match key'); + } + try { + await revocationSignature.verify(this.keyPacket, enums.signature.keyRevocation, { key: this.keyPacket }, date, undefined, config); + } catch (e) { + throw util.wrapError('Could not verify revocation signature', e); + } + const key = this.clone(); + key.revocationSignatures.push(revocationSignature); + return key; + } + + /** + * Signs primary user of key + * @param {Array} privateKeys - decrypted private keys for signing + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} [userID] - User ID to get instead of the primary user, if it exists + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} Key with new certificate signature. + * @async + */ + async signPrimaryUser(privateKeys, date, userID, config = defaultConfig) { + const { index, user } = await this.getPrimaryUser(date, userID, config); + const userSign = await user.certify(privateKeys, date, config); + const key = this.clone(); + key.users[index] = userSign; + return key; + } + + /** + * Signs all users of key + * @param {Array} privateKeys - decrypted private keys for signing + * @param {Date} [date] - Use the given date for signing, instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} Key with new certificate signature. + * @async + */ + async signAllUsers(privateKeys, date = new Date(), config = defaultConfig) { + const key = this.clone(); + key.users = await Promise.all(this.users.map(function(user) { + return user.certify(privateKeys, date, config); + })); + return key; + } + + /** + * Verifies primary user of key + * - if no arguments are given, verifies the self certificates; + * - otherwise, verifies all certificates signed with given keys. + * @param {Array} [verificationKeys] - array of keys to verify certificate signatures, instead of the primary key + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} [userID] - User ID to get instead of the primary user, if it exists + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise>} List of signer's keyID and validity of signature. + * Signature validity is null if the verification keys do not correspond to the certificate. + * @async + */ + async verifyPrimaryUser(verificationKeys, date = new Date(), userID, config = defaultConfig) { + const primaryKey = this.keyPacket; + const { user } = await this.getPrimaryUser(date, userID, config); + const results = verificationKeys ? + await user.verifyAllCertifications(verificationKeys, date, config) : + [{ keyID: primaryKey.getKeyID(), valid: await user.verify(date, config).catch(() => false) }]; + return results; + } + + /** + * Verifies all users of key + * - if no arguments are given, verifies the self certificates; + * - otherwise, verifies all certificates signed with given keys. + * @param {Array} [verificationKeys] - array of keys to verify certificate signatures + * @param {Date} [date] - Use the given date for verification instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise>} List of userID, signer's keyID and validity of signature. + * Signature validity is null if the verification keys do not correspond to the certificate. + * @async + */ + async verifyAllUsers(verificationKeys, date = new Date(), config = defaultConfig) { + const primaryKey = this.keyPacket; + const results = []; + await Promise.all(this.users.map(async user => { + const signatures = verificationKeys ? + await user.verifyAllCertifications(verificationKeys, date, config) : + [{ keyID: primaryKey.getKeyID(), valid: await user.verify(date, config).catch(() => false) }]; + + results.push(...signatures.map( + signature => ({ + userID: user.userID.userID, + keyID: signature.keyID, + valid: signature.valid + })) + ); + })); + return results; + } + } + + ['getKeyID', 'getFingerprint', 'getAlgorithmInfo', 'getCreationTime', 'hasSameFingerprintAs'].forEach(name => { + Key.prototype[name] = + Subkey.prototype[name]; + }); + + /** + * Creates a PublicKey or PrivateKey depending on the packetlist in input + * @param {PacketList} - packets to parse + * @return {Key} parsed key + * @throws if no key packet was found + */ + function createKey(packetlist) { + for (const packet of packetlist) { + switch (packet.constructor.tag) { + case enums.packet.secretKey: + return new PrivateKey(packetlist); + case enums.packet.publicKey: + return new PublicKey(packetlist); + } + } + throw new Error('No key packet found'); + } + + // This library is free software; you can redistribute it and/or + + /** + * Class that represents an OpenPGP Public Key + */ + class PublicKey extends Key { + /** + * @param {PacketList} packetlist - The packets that form this key + */ + constructor(packetlist) { + super(); + this.keyPacket = null; + this.revocationSignatures = []; + this.directSignatures = []; + this.users = []; + this.subkeys = []; + if (packetlist) { + this.packetListToStructure(packetlist, new Set([enums.packet.secretKey, enums.packet.secretSubkey])); + if (!this.keyPacket) { + throw new Error('Invalid key: missing public-key packet'); + } + } + } + + /** + * Returns true if this is a private key + * @returns {false} + */ + isPrivate() { + return false; + } + + /** + * Returns key as public key (shallow copy) + * @returns {PublicKey} New public Key + */ + toPublic() { + return this; + } + + /** + * Returns ASCII armored text of key + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {ReadableStream} ASCII armor. + */ + armor(config = defaultConfig) { + return armor(enums.armor.publicKey, this.toPacketList().write(), undefined, undefined, undefined, config); + } + } + + /** + * Class that represents an OpenPGP Private key + */ + class PrivateKey extends PublicKey { + /** + * @param {PacketList} packetlist - The packets that form this key + */ + constructor(packetlist) { + super(); + this.packetListToStructure(packetlist, new Set([enums.packet.publicKey, enums.packet.publicSubkey])); + if (!this.keyPacket) { + throw new Error('Invalid key: missing private-key packet'); + } + } + + /** + * Returns true if this is a private key + * @returns {Boolean} + */ + isPrivate() { + return true; + } + + /** + * Returns key as public key (shallow copy) + * @returns {PublicKey} New public Key + */ + toPublic() { + const packetlist = new PacketList(); + const keyPackets = this.toPacketList(); + for (const keyPacket of keyPackets) { + switch (keyPacket.constructor.tag) { + case enums.packet.secretKey: { + const pubKeyPacket = PublicKeyPacket.fromSecretKeyPacket(keyPacket); + packetlist.push(pubKeyPacket); + break; + } + case enums.packet.secretSubkey: { + const pubSubkeyPacket = PublicSubkeyPacket.fromSecretSubkeyPacket(keyPacket); + packetlist.push(pubSubkeyPacket); + break; + } + default: + packetlist.push(keyPacket); + } + } + return new PublicKey(packetlist); + } + + /** + * Returns ASCII armored text of key + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {ReadableStream} ASCII armor. + */ + armor(config = defaultConfig) { + return armor(enums.armor.privateKey, this.toPacketList().write(), undefined, undefined, undefined, config); + } + + /** + * Returns all keys that are available for decryption, matching the keyID when given + * This is useful to retrieve keys for session key decryption + * @param {module:type/keyid~KeyID} keyID, optional + * @param {Date} date, optional + * @param {String} userID, optional + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise>} Array of decryption keys. + * @async + */ + async getDecryptionKeys(keyID, date = new Date(), userID = {}, config = defaultConfig) { + const primaryKey = this.keyPacket; + const keys = []; + for (let i = 0; i < this.subkeys.length; i++) { + if (!keyID || this.subkeys[i].getKeyID().equals(keyID, true)) { + try { + const dataToVerify = { key: primaryKey, bind: this.subkeys[i].keyPacket }; + const bindingSignature = await getLatestValidSignature(this.subkeys[i].bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); + if (isValidDecryptionKeyPacket(bindingSignature, config)) { + keys.push(this.subkeys[i]); + } + } catch (e) {} + } + } + + // evaluate primary key + const primaryUser = await this.getPrimaryUser(date, userID, config); + if ((!keyID || primaryKey.getKeyID().equals(keyID, true)) && + isValidDecryptionKeyPacket(primaryUser.selfCertification, config)) { + keys.push(this); + } + + return keys; + } + + /** + * Returns true if the primary key or any subkey is decrypted. + * A dummy key is considered encrypted. + */ + isDecrypted() { + return this.getKeys().some(({ keyPacket }) => keyPacket.isDecrypted()); + } + + /** + * Check whether the private and public primary key parameters correspond + * Together with verification of binding signatures, this guarantees key integrity + * In case of gnu-dummy primary key, it is enough to validate any signing subkeys + * otherwise all encryption subkeys are validated + * If only gnu-dummy keys are found, we cannot properly validate so we throw an error + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @throws {Error} if validation was not successful and the key cannot be trusted + * @async + */ + async validate(config = defaultConfig) { + if (!this.isPrivate()) { + throw new Error('Cannot validate a public key'); + } + + let signingKeyPacket; + if (!this.keyPacket.isDummy()) { + signingKeyPacket = this.keyPacket; + } else { + /** + * It is enough to validate any signing keys + * since its binding signatures are also checked + */ + const signingKey = await this.getSigningKey(null, null, undefined, { ...config, rejectPublicKeyAlgorithms: new Set(), minRSABits: 0 }); + // This could again be a dummy key + if (signingKey && !signingKey.keyPacket.isDummy()) { + signingKeyPacket = signingKey.keyPacket; + } + } + + if (signingKeyPacket) { + return signingKeyPacket.validate(); + } else { + const keys = this.getKeys(); + const allDummies = keys.map(key => key.keyPacket.isDummy()).every(Boolean); + if (allDummies) { + throw new Error('Cannot validate an all-gnu-dummy key'); + } + + return Promise.all(keys.map(async key => key.keyPacket.validate())); + } + } + + /** + * Clear private key parameters + */ + clearPrivateParams() { + this.getKeys().forEach(({ keyPacket }) => { + if (keyPacket.isDecrypted()) { + keyPacket.clearPrivateParams(); + } + }); + } + + /** + * Revokes the key + * @param {Object} reasonForRevocation - optional, object indicating the reason for revocation + * @param {module:enums.reasonForRevocation} reasonForRevocation.flag optional, flag indicating the reason for revocation + * @param {String} reasonForRevocation.string optional, string explaining the reason for revocation + * @param {Date} date - optional, override the creationtime of the revocation signature + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New key with revocation signature. + * @async + */ + async revoke( + { + flag: reasonForRevocationFlag = enums.reasonForRevocation.noReason, + string: reasonForRevocationString = '' + } = {}, + date = new Date(), + config = defaultConfig + ) { + if (!this.isPrivate()) { + throw new Error('Need private key for revoking'); + } + const dataToSign = { key: this.keyPacket }; + const key = this.clone(); + key.revocationSignatures.push(await createSignaturePacket(dataToSign, null, this.keyPacket, { + signatureType: enums.signature.keyRevocation, + reasonForRevocationFlag: enums.write(enums.reasonForRevocation, reasonForRevocationFlag), + reasonForRevocationString + }, date, undefined, undefined, config)); + return key; + } + + + /** + * Generates a new OpenPGP subkey, and returns a clone of the Key object with the new subkey added. + * Supports RSA and ECC keys. Defaults to the algorithm and bit size/curve of the primary key. DSA primary keys default to RSA subkeys. + * @param {ecc|rsa} options.type The subkey algorithm: ECC or RSA + * @param {String} options.curve (optional) Elliptic curve for ECC keys + * @param {Integer} options.rsaBits (optional) Number of bits for RSA subkeys + * @param {Number} options.keyExpirationTime (optional) Number of seconds from the key creation time after which the key expires + * @param {Date} options.date (optional) Override the creation date of the key and the key signatures + * @param {Boolean} options.sign (optional) Indicates whether the subkey should sign rather than encrypt. Defaults to false + * @param {Object} options.config (optional) custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} + * @async + */ + async addSubkey(options = {}) { + const config = { ...defaultConfig, ...options.config }; + if (options.passphrase) { + throw new Error('Subkey could not be encrypted here, please encrypt whole key'); + } + if (options.rsaBits < config.minRSABits) { + throw new Error(`rsaBits should be at least ${config.minRSABits}, got: ${options.rsaBits}`); + } + const secretKeyPacket = this.keyPacket; + if (secretKeyPacket.isDummy()) { + throw new Error('Cannot add subkey to gnu-dummy primary key'); + } + if (!secretKeyPacket.isDecrypted()) { + throw new Error('Key is not decrypted'); + } + const defaultOptions = secretKeyPacket.getAlgorithmInfo(); + defaultOptions.type = defaultOptions.curve ? 'ecc' : 'rsa'; // DSA keys default to RSA + defaultOptions.rsaBits = defaultOptions.bits || 4096; + defaultOptions.curve = defaultOptions.curve || 'curve25519'; + options = sanitizeKeyOptions(options, defaultOptions); + const keyPacket = await generateSecretSubkey(options); + checkKeyRequirements(keyPacket, config); + const bindingSignature = await createBindingSignature(keyPacket, secretKeyPacket, options, config); + const packetList = this.toPacketList(); + packetList.push(keyPacket, bindingSignature); + return new PrivateKey(packetList); + } + } + + // OpenPGP.js - An OpenPGP implementation in javascript + + // A Key can contain the following packets + const allowedKeyPackets = /*#__PURE__*/ util.constructAllowedPackets([ + PublicKeyPacket, + PublicSubkeyPacket, + SecretKeyPacket, + SecretSubkeyPacket, + UserIDPacket, + UserAttributePacket, + SignaturePacket + ]); + + /** + * Generates a new OpenPGP key. Supports RSA and ECC keys. + * By default, primary and subkeys will be of same type. + * @param {ecc|rsa} options.type The primary key algorithm type: ECC or RSA + * @param {String} options.curve Elliptic curve for ECC keys + * @param {Integer} options.rsaBits Number of bits for RSA keys + * @param {Array} options.userIDs User IDs as strings or objects: 'Jo Doe ' or { name:'Jo Doe', email:'info@jo.com' } + * @param {String} options.passphrase Passphrase used to encrypt the resulting private key + * @param {Number} options.keyExpirationTime (optional) Number of seconds from the key creation time after which the key expires + * @param {Date} options.date Creation date of the key and the key signatures + * @param {Object} config - Full configuration + * @param {Array} options.subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}] + * sign parameter defaults to false, and indicates whether the subkey should sign rather than encrypt + * @returns {Promise<{{ key: PrivateKey, revocationCertificate: String }}>} + * @async + * @static + * @private + */ + async function generate$2(options, config) { + options.sign = true; // primary key is always a signing key + options = sanitizeKeyOptions(options); + options.subkeys = options.subkeys.map((subkey, index) => sanitizeKeyOptions(options.subkeys[index], options)); + let promises = [generateSecretKey(options, config)]; + promises = promises.concat(options.subkeys.map(options => generateSecretSubkey(options, config))); + const packets = await Promise.all(promises); + + const key = await wrapKeyObject(packets[0], packets.slice(1), options, config); + const revocationCertificate = await key.getRevocationCertificate(options.date, config); + key.revocationSignatures = []; + return { key, revocationCertificate }; + } + + /** + * Reformats and signs an OpenPGP key with a given User ID. Currently only supports RSA keys. + * @param {PrivateKey} options.privateKey The private key to reformat + * @param {Array} options.userIDs User IDs as strings or objects: 'Jo Doe ' or { name:'Jo Doe', email:'info@jo.com' } + * @param {String} options.passphrase Passphrase used to encrypt the resulting private key + * @param {Number} options.keyExpirationTime Number of seconds from the key creation time after which the key expires + * @param {Date} options.date Override the creation date of the key signatures + * @param {Array} options.subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}] + * @param {Object} config - Full configuration + * + * @returns {Promise<{{ key: PrivateKey, revocationCertificate: String }}>} + * @async + * @static + * @private + */ + async function reformat(options, config) { + options = sanitize(options); + const { privateKey } = options; + + if (!privateKey.isPrivate()) { + throw new Error('Cannot reformat a public key'); + } + + if (privateKey.keyPacket.isDummy()) { + throw new Error('Cannot reformat a gnu-dummy primary key'); + } + + const isDecrypted = privateKey.getKeys().every(({ keyPacket }) => keyPacket.isDecrypted()); + if (!isDecrypted) { + throw new Error('Key is not decrypted'); + } + + const secretKeyPacket = privateKey.keyPacket; + + if (!options.subkeys) { + options.subkeys = await Promise.all(privateKey.subkeys.map(async subkey => { + const secretSubkeyPacket = subkey.keyPacket; + const dataToVerify = { key: secretKeyPacket, bind: secretSubkeyPacket }; + const bindingSignature = await ( + getLatestValidSignature(subkey.bindingSignatures, secretKeyPacket, enums.signature.subkeyBinding, dataToVerify, null, config) + ).catch(() => ({})); + return { + sign: bindingSignature.keyFlags && (bindingSignature.keyFlags[0] & enums.keyFlags.signData) + }; + })); + } + + const secretSubkeyPackets = privateKey.subkeys.map(subkey => subkey.keyPacket); + if (options.subkeys.length !== secretSubkeyPackets.length) { + throw new Error('Number of subkey options does not match number of subkeys'); + } + + options.subkeys = options.subkeys.map(subkeyOptions => sanitize(subkeyOptions, options)); + + const key = await wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options, config); + const revocationCertificate = await key.getRevocationCertificate(options.date, config); + key.revocationSignatures = []; + return { key, revocationCertificate }; + + function sanitize(options, subkeyDefaults = {}) { + options.keyExpirationTime = options.keyExpirationTime || subkeyDefaults.keyExpirationTime; + options.passphrase = util.isString(options.passphrase) ? options.passphrase : subkeyDefaults.passphrase; + options.date = options.date || subkeyDefaults.date; + + return options; + } + } + + /** + * Construct PrivateKey object from the given key packets, add certification signatures and set passphrase protection + * The new key includes a revocation certificate that must be removed before returning the key, otherwise the key is considered revoked. + * @param {SecretKeyPacket} secretKeyPacket + * @param {SecretSubkeyPacket} secretSubkeyPackets + * @param {Object} options + * @param {Object} config - Full configuration + * @returns {PrivateKey} + */ + async function wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options, config) { + // set passphrase protection + if (options.passphrase) { + await secretKeyPacket.encrypt(options.passphrase, config); + } + + await Promise.all(secretSubkeyPackets.map(async function(secretSubkeyPacket, index) { + const subkeyPassphrase = options.subkeys[index].passphrase; + if (subkeyPassphrase) { + await secretSubkeyPacket.encrypt(subkeyPassphrase, config); + } + })); + + const packetlist = new PacketList(); + packetlist.push(secretKeyPacket); + + await Promise.all(options.userIDs.map(async function(userID, index) { + function createPreferredAlgos(algos, preferredAlgo) { + return [preferredAlgo, ...algos.filter(algo => algo !== preferredAlgo)]; + } + + const userIDPacket = UserIDPacket.fromObject(userID); + const dataToSign = {}; + dataToSign.userID = userIDPacket; + dataToSign.key = secretKeyPacket; + const signaturePacket = new SignaturePacket(); + signaturePacket.signatureType = enums.signature.certGeneric; + signaturePacket.publicKeyAlgorithm = secretKeyPacket.algorithm; + signaturePacket.hashAlgorithm = await getPreferredHashAlgo$1(null, secretKeyPacket, undefined, undefined, config); + signaturePacket.keyFlags = [enums.keyFlags.certifyKeys | enums.keyFlags.signData]; + signaturePacket.preferredSymmetricAlgorithms = createPreferredAlgos([ + // prefer aes256, aes128, then aes192 (no WebCrypto support: https://www.chromium.org/blink/webcrypto#TOC-AES-support) + enums.symmetric.aes256, + enums.symmetric.aes128, + enums.symmetric.aes192 + ], config.preferredSymmetricAlgorithm); + if (config.aeadProtect) { + signaturePacket.preferredAEADAlgorithms = createPreferredAlgos([ + enums.aead.eax, + enums.aead.ocb + ], config.preferredAEADAlgorithm); + } + signaturePacket.preferredHashAlgorithms = createPreferredAlgos([ + // prefer fast asm.js implementations (SHA-256) + enums.hash.sha256, + enums.hash.sha512 + ], config.preferredHashAlgorithm); + signaturePacket.preferredCompressionAlgorithms = createPreferredAlgos([ + enums.compression.zlib, + enums.compression.zip, + enums.compression.uncompressed + ], config.preferredCompressionAlgorithm); + if (index === 0) { + signaturePacket.isPrimaryUserID = true; + } + // integrity protection always enabled + signaturePacket.features = [0]; + signaturePacket.features[0] |= enums.features.modificationDetection; + if (config.aeadProtect) { + signaturePacket.features[0] |= enums.features.aead; + } + if (config.v5Keys) { + signaturePacket.features[0] |= enums.features.v5Keys; + } + if (options.keyExpirationTime > 0) { + signaturePacket.keyExpirationTime = options.keyExpirationTime; + signaturePacket.keyNeverExpires = false; + } + await signaturePacket.sign(secretKeyPacket, dataToSign, options.date); + + return { userIDPacket, signaturePacket }; + })).then(list => { + list.forEach(({ userIDPacket, signaturePacket }) => { + packetlist.push(userIDPacket); + packetlist.push(signaturePacket); + }); + }); + + await Promise.all(secretSubkeyPackets.map(async function(secretSubkeyPacket, index) { + const subkeyOptions = options.subkeys[index]; + const subkeySignaturePacket = await createBindingSignature(secretSubkeyPacket, secretKeyPacket, subkeyOptions, config); + return { secretSubkeyPacket, subkeySignaturePacket }; + })).then(packets => { + packets.forEach(({ secretSubkeyPacket, subkeySignaturePacket }) => { + packetlist.push(secretSubkeyPacket); + packetlist.push(subkeySignaturePacket); + }); + }); + + // Add revocation signature packet for creating a revocation certificate. + // This packet should be removed before returning the key. + const dataToSign = { key: secretKeyPacket }; + packetlist.push(await createSignaturePacket(dataToSign, null, secretKeyPacket, { + signatureType: enums.signature.keyRevocation, + reasonForRevocationFlag: enums.reasonForRevocation.noReason, + reasonForRevocationString: '' + }, options.date, undefined, undefined, config)); + + if (options.passphrase) { + secretKeyPacket.clearPrivateParams(); + } + + await Promise.all(secretSubkeyPackets.map(async function(secretSubkeyPacket, index) { + const subkeyPassphrase = options.subkeys[index].passphrase; + if (subkeyPassphrase) { + secretSubkeyPacket.clearPrivateParams(); + } + })); + + return new PrivateKey(packetlist); + } + + /** + * Reads an (optionally armored) OpenPGP key and returns a key object + * @param {Object} options + * @param {String} [options.armoredKey] - Armored key to be parsed + * @param {Uint8Array} [options.binaryKey] - Binary key to be parsed + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} Key object. + * @async + * @static + */ + async function readKey({ armoredKey, binaryKey, config, ...rest }) { + config = { ...defaultConfig, ...config }; + if (!armoredKey && !binaryKey) { + throw new Error('readKey: must pass options object containing `armoredKey` or `binaryKey`'); + } + if (armoredKey && !util.isString(armoredKey)) { + throw new Error('readKey: options.armoredKey must be a string'); + } + if (binaryKey && !util.isUint8Array(binaryKey)) { + throw new Error('readKey: options.binaryKey must be a Uint8Array'); + } + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + let input; + if (armoredKey) { + const { type, data } = await unarmor(armoredKey, config); + if (!(type === enums.armor.publicKey || type === enums.armor.privateKey)) { + throw new Error('Armored text not of type key'); + } + input = data; + } else { + input = binaryKey; + } + const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); + return createKey(packetlist); + } + + /** + * Reads an (optionally armored) OpenPGP private key and returns a PrivateKey object + * @param {Object} options + * @param {String} [options.armoredKey] - Armored key to be parsed + * @param {Uint8Array} [options.binaryKey] - Binary key to be parsed + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} Key object. + * @async + * @static + */ + async function readPrivateKey({ armoredKey, binaryKey, config, ...rest }) { + config = { ...defaultConfig, ...config }; + if (!armoredKey && !binaryKey) { + throw new Error('readPrivateKey: must pass options object containing `armoredKey` or `binaryKey`'); + } + if (armoredKey && !util.isString(armoredKey)) { + throw new Error('readPrivateKey: options.armoredKey must be a string'); + } + if (binaryKey && !util.isUint8Array(binaryKey)) { + throw new Error('readPrivateKey: options.binaryKey must be a Uint8Array'); + } + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + let input; + if (armoredKey) { + const { type, data } = await unarmor(armoredKey, config); + if (!(type === enums.armor.privateKey)) { + throw new Error('Armored text not of type private key'); + } + input = data; + } else { + input = binaryKey; + } + const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); + return new PrivateKey(packetlist); + } + + /** + * Reads an (optionally armored) OpenPGP key block and returns a list of key objects + * @param {Object} options + * @param {String} [options.armoredKeys] - Armored keys to be parsed + * @param {Uint8Array} [options.binaryKeys] - Binary keys to be parsed + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise>} Key objects. + * @async + * @static + */ + async function readKeys({ armoredKeys, binaryKeys, config, ...rest }) { + config = { ...defaultConfig, ...config }; + let input = armoredKeys || binaryKeys; + if (!input) { + throw new Error('readKeys: must pass options object containing `armoredKeys` or `binaryKeys`'); + } + if (armoredKeys && !util.isString(armoredKeys)) { + throw new Error('readKeys: options.armoredKeys must be a string'); + } + if (binaryKeys && !util.isUint8Array(binaryKeys)) { + throw new Error('readKeys: options.binaryKeys must be a Uint8Array'); + } + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + if (armoredKeys) { + const { type, data } = await unarmor(armoredKeys, config); + if (type !== enums.armor.publicKey && type !== enums.armor.privateKey) { + throw new Error('Armored text not of type key'); + } + input = data; + } + const keys = []; + const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); + const keyIndex = packetlist.indexOfTag(enums.packet.publicKey, enums.packet.secretKey); + if (keyIndex.length === 0) { + throw new Error('No key packet found'); + } + for (let i = 0; i < keyIndex.length; i++) { + const oneKeyList = packetlist.slice(keyIndex[i], keyIndex[i + 1]); + const newKey = createKey(oneKeyList); + keys.push(newKey); + } + return keys; + } + + /** + * Reads an (optionally armored) OpenPGP private key block and returns a list of PrivateKey objects + * @param {Object} options + * @param {String} [options.armoredKeys] - Armored keys to be parsed + * @param {Uint8Array} [options.binaryKeys] - Binary keys to be parsed + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise>} Key objects. + * @async + * @static + */ + async function readPrivateKeys({ armoredKeys, binaryKeys, config }) { + config = { ...defaultConfig, ...config }; + let input = armoredKeys || binaryKeys; + if (!input) { + throw new Error('readPrivateKeys: must pass options object containing `armoredKeys` or `binaryKeys`'); + } + if (armoredKeys && !util.isString(armoredKeys)) { + throw new Error('readPrivateKeys: options.armoredKeys must be a string'); + } + if (binaryKeys && !util.isUint8Array(binaryKeys)) { + throw new Error('readPrivateKeys: options.binaryKeys must be a Uint8Array'); + } + if (armoredKeys) { + const { type, data } = await unarmor(armoredKeys, config); + if (type !== enums.armor.privateKey) { + throw new Error('Armored text not of type private key'); + } + input = data; + } + const keys = []; + const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); + const keyIndex = packetlist.indexOfTag(enums.packet.secretKey); + if (keyIndex.length === 0) { + throw new Error('No secret key packet found'); + } + for (let i = 0; i < keyIndex.length; i++) { + const oneKeyList = packetlist.slice(keyIndex[i], keyIndex[i + 1]); + const newKey = new PrivateKey(oneKeyList); + keys.push(newKey); + } + return keys; + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + // A Message can contain the following packets + const allowedMessagePackets = /*#__PURE__*/ util.constructAllowedPackets([ + LiteralDataPacket, + CompressedDataPacket, + AEADEncryptedDataPacket, + SymEncryptedIntegrityProtectedDataPacket, + SymmetricallyEncryptedDataPacket, + PublicKeyEncryptedSessionKeyPacket, + SymEncryptedSessionKeyPacket, + OnePassSignaturePacket, + SignaturePacket + ]); + // A SKESK packet can contain the following packets + const allowedSymSessionKeyPackets = /*#__PURE__*/ util.constructAllowedPackets([SymEncryptedSessionKeyPacket]); + // A detached signature can contain the following packets + const allowedDetachedSignaturePackets = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); + + /** + * Class that represents an OpenPGP message. + * Can be an encrypted message, signed message, compressed message or literal message + * See {@link https://tools.ietf.org/html/rfc4880#section-11.3} + */ + class Message { + /** + * @param {PacketList} packetlist - The packets that form this message + */ + constructor(packetlist) { + this.packets = packetlist || new PacketList(); + } + + /** + * Returns the key IDs of the keys to which the session key is encrypted + * @returns {Array} Array of keyID objects. + */ + getEncryptionKeyIDs() { + const keyIDs = []; + const pkESKeyPacketlist = this.packets.filterByTag(enums.packet.publicKeyEncryptedSessionKey); + pkESKeyPacketlist.forEach(function(packet) { + keyIDs.push(packet.publicKeyID); + }); + return keyIDs; + } + + /** + * Returns the key IDs of the keys that signed the message + * @returns {Array} Array of keyID objects. + */ + getSigningKeyIDs() { + const msg = this.unwrapCompressed(); + // search for one pass signatures + const onePassSigList = msg.packets.filterByTag(enums.packet.onePassSignature); + if (onePassSigList.length > 0) { + return onePassSigList.map(packet => packet.issuerKeyID); + } + // if nothing found look for signature packets + const signatureList = msg.packets.filterByTag(enums.packet.signature); + return signatureList.map(packet => packet.issuerKeyID); + } + + /** + * Decrypt the message. Either a private key, a session key, or a password must be specified. + * @param {Array} [decryptionKeys] - Private keys with decrypted secret data + * @param {Array} [passwords] - Passwords used to decrypt + * @param {Array} [sessionKeys] - Session keys in the form: { data:Uint8Array, algorithm:String, [aeadAlgorithm:String] } + * @param {Date} [date] - Use the given date for key verification instead of the current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New message with decrypted content. + * @async + */ + async decrypt(decryptionKeys, passwords, sessionKeys, date = new Date(), config = defaultConfig) { + const sessionKeyObjects = sessionKeys || await this.decryptSessionKeys(decryptionKeys, passwords, date, config); + + const symEncryptedPacketlist = this.packets.filterByTag( + enums.packet.symmetricallyEncryptedData, + enums.packet.symEncryptedIntegrityProtectedData, + enums.packet.aeadEncryptedData + ); + + if (symEncryptedPacketlist.length === 0) { + return this; + } + + const symEncryptedPacket = symEncryptedPacketlist[0]; + let exception = null; + const decryptedPromise = Promise.all(sessionKeyObjects.map(async ({ algorithm: algorithmName, data }) => { + if (!util.isUint8Array(data) || !util.isString(algorithmName)) { + throw new Error('Invalid session key for decryption.'); + } + + try { + const algo = enums.write(enums.symmetric, algorithmName); + await symEncryptedPacket.decrypt(algo, data, config); + } catch (e) { + util.printDebugError(e); + exception = e; + } + })); + // We don't await stream.cancel here because it only returns when the other copy is canceled too. + cancel(symEncryptedPacket.encrypted); // Don't keep copy of encrypted data in memory. + symEncryptedPacket.encrypted = null; + await decryptedPromise; + + if (!symEncryptedPacket.packets || !symEncryptedPacket.packets.length) { + throw exception || new Error('Decryption failed.'); + } + + const resultMsg = new Message(symEncryptedPacket.packets); + symEncryptedPacket.packets = new PacketList(); // remove packets after decryption + + return resultMsg; + } + + /** + * Decrypt encrypted session keys either with private keys or passwords. + * @param {Array} [decryptionKeys] - Private keys with decrypted secret data + * @param {Array} [passwords] - Passwords used to decrypt + * @param {Date} [date] - Use the given date for key verification, instead of current time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise>} array of object with potential sessionKey, algorithm pairs + * @async + */ + async decryptSessionKeys(decryptionKeys, passwords, date = new Date(), config = defaultConfig) { + let decryptedSessionKeyPackets = []; + + let exception; + if (passwords) { + const skeskPackets = this.packets.filterByTag(enums.packet.symEncryptedSessionKey); + if (skeskPackets.length === 0) { + throw new Error('No symmetrically encrypted session key packet found.'); + } + await Promise.all(passwords.map(async function(password, i) { + let packets; + if (i) { + packets = await PacketList.fromBinary(skeskPackets.write(), allowedSymSessionKeyPackets, config); + } else { + packets = skeskPackets; + } + await Promise.all(packets.map(async function(skeskPacket) { + try { + await skeskPacket.decrypt(password); + decryptedSessionKeyPackets.push(skeskPacket); + } catch (err) { + util.printDebugError(err); + } + })); + })); + } else if (decryptionKeys) { + const pkeskPackets = this.packets.filterByTag(enums.packet.publicKeyEncryptedSessionKey); + if (pkeskPackets.length === 0) { + throw new Error('No public key encrypted session key packet found.'); + } + await Promise.all(pkeskPackets.map(async function(pkeskPacket) { + await Promise.all(decryptionKeys.map(async function(decryptionKey) { + let algos = [ + enums.symmetric.aes256, // Old OpenPGP.js default fallback + enums.symmetric.aes128, // RFC4880bis fallback + enums.symmetric.tripledes, // RFC4880 fallback + enums.symmetric.cast5 // Golang OpenPGP fallback + ]; + try { + const primaryUser = await decryptionKey.getPrimaryUser(date, undefined, config); // TODO: Pass userID from somewhere. + if (primaryUser.selfCertification.preferredSymmetricAlgorithms) { + algos = algos.concat(primaryUser.selfCertification.preferredSymmetricAlgorithms); + } + } catch (e) {} + + // do not check key expiration to allow decryption of old messages + const decryptionKeyPackets = (await decryptionKey.getDecryptionKeys(pkeskPacket.publicKeyID, null, undefined, config)).map(key => key.keyPacket); + await Promise.all(decryptionKeyPackets.map(async function(decryptionKeyPacket) { + if (!decryptionKeyPacket || decryptionKeyPacket.isDummy()) { + return; + } + if (!decryptionKeyPacket.isDecrypted()) { + throw new Error('Decryption key is not decrypted.'); + } + + // To hinder CCA attacks against PKCS1, we carry out a constant-time decryption flow if the `constantTimePKCS1Decryption` config option is set. + const doConstantTimeDecryption = config.constantTimePKCS1Decryption && ( + pkeskPacket.publicKeyAlgorithm === enums.publicKey.rsaEncrypt || + pkeskPacket.publicKeyAlgorithm === enums.publicKey.rsaEncryptSign || + pkeskPacket.publicKeyAlgorithm === enums.publicKey.rsaSign || + pkeskPacket.publicKeyAlgorithm === enums.publicKey.elgamal + ); + + if (doConstantTimeDecryption) { + // The goal is to not reveal whether PKESK decryption (specifically the PKCS1 decoding step) failed, hence, we always proceed to decrypt the message, + // either with the successfully decrypted session key, or with a randomly generated one. + // Since the SEIP/AEAD's symmetric algorithm and key size are stored in the encrypted portion of the PKESK, and the execution flow cannot depend on + // the decrypted payload, we always assume the message to be encrypted with one of the symmetric algorithms specified in `config.constantTimePKCS1DecryptionSupportedSymmetricAlgorithms`: + // - If the PKESK decryption succeeds, and the session key cipher is in the supported set, then we try to decrypt the data with the decrypted session key as well as with the + // randomly generated keys of the remaining key types. + // - If the PKESK decryptions fails, or if it succeeds but support for the cipher is not enabled, then we discard the session key and try to decrypt the data using only the randomly + // generated session keys. + // NB: as a result, if the data is encrypted with a non-suported cipher, decryption will always fail. + + const serialisedPKESK = pkeskPacket.write(); // make copies to be able to decrypt the PKESK packet multiple times + await Promise.all(Array.from(config.constantTimePKCS1DecryptionSupportedSymmetricAlgorithms).map(async sessionKeyAlgorithm => { + const pkeskPacketCopy = new PublicKeyEncryptedSessionKeyPacket(); + pkeskPacketCopy.read(serialisedPKESK); + const randomSessionKey = { + sessionKeyAlgorithm, + sessionKey: await mod.generateSessionKey(sessionKeyAlgorithm) + }; + try { + await pkeskPacketCopy.decrypt(decryptionKeyPacket, randomSessionKey); + decryptedSessionKeyPackets.push(pkeskPacketCopy); + } catch (err) { + // `decrypt` can still throw some non-security-sensitive errors + util.printDebugError(err); + exception = err; + } + })); + + } else { + try { + await pkeskPacket.decrypt(decryptionKeyPacket); + if (!algos.includes(enums.write(enums.symmetric, pkeskPacket.sessionKeyAlgorithm))) { + throw new Error('A non-preferred symmetric algorithm was used.'); + } + decryptedSessionKeyPackets.push(pkeskPacket); + } catch (err) { + util.printDebugError(err); + exception = err; + } + } + })); + })); + cancel(pkeskPacket.encrypted); // Don't keep copy of encrypted data in memory. + pkeskPacket.encrypted = null; + })); + } else { + throw new Error('No key or password specified.'); + } + + if (decryptedSessionKeyPackets.length > 0) { + // Return only unique session keys + if (decryptedSessionKeyPackets.length > 1) { + const seen = new Set(); + decryptedSessionKeyPackets = decryptedSessionKeyPackets.filter(item => { + const k = item.sessionKeyAlgorithm + util.uint8ArrayToString(item.sessionKey); + if (seen.has(k)) { + return false; + } + seen.add(k); + return true; + }); + } + + return decryptedSessionKeyPackets.map(packet => ({ + data: packet.sessionKey, + algorithm: enums.read(enums.symmetric, packet.sessionKeyAlgorithm) + })); + } + throw exception || new Error('Session key decryption failed.'); + } + + /** + * Get literal data that is the body of the message + * @returns {(Uint8Array|null)} Literal body of the message as Uint8Array. + */ + getLiteralData() { + const msg = this.unwrapCompressed(); + const literal = msg.packets.findPacket(enums.packet.literalData); + return (literal && literal.getBytes()) || null; + } + + /** + * Get filename from literal data packet + * @returns {(String|null)} Filename of literal data packet as string. + */ + getFilename() { + const msg = this.unwrapCompressed(); + const literal = msg.packets.findPacket(enums.packet.literalData); + return (literal && literal.getFilename()) || null; + } + + /** + * Get literal data as text + * @returns {(String|null)} Literal body of the message interpreted as text. + */ + getText() { + const msg = this.unwrapCompressed(); + const literal = msg.packets.findPacket(enums.packet.literalData); + if (literal) { + return literal.getText(); + } + return null; + } + + /** + * Generate a new session key object, taking the algorithm preferences of the passed encryption keys into account, if any. + * @param {Array} [encryptionKeys] - Public key(s) to select algorithm preferences for + * @param {Date} [date] - Date to select algorithm preferences at + * @param {Array} [userIDs] - User IDs to select algorithm preferences for + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise<{ data: Uint8Array, algorithm: String, aeadAlgorithm: undefined|String }>} Object with session key data and algorithms. + * @async + */ + static async generateSessionKey(encryptionKeys = [], date = new Date(), userIDs = [], config = defaultConfig) { + const algo = await getPreferredAlgo('symmetric', encryptionKeys, date, userIDs, config); + const algorithmName = enums.read(enums.symmetric, algo); + const aeadAlgorithmName = config.aeadProtect && await isAEADSupported(encryptionKeys, date, userIDs, config) ? + enums.read(enums.aead, await getPreferredAlgo('aead', encryptionKeys, date, userIDs, config)) : + undefined; + + const sessionKeyData = await mod.generateSessionKey(algo); + return { data: sessionKeyData, algorithm: algorithmName, aeadAlgorithm: aeadAlgorithmName }; + } + + /** + * Encrypt the message either with public keys, passwords, or both at once. + * @param {Array} [encryptionKeys] - Public key(s) for message encryption + * @param {Array} [passwords] - Password(s) for message encryption + * @param {Object} [sessionKey] - Session key in the form: { data:Uint8Array, algorithm:String, [aeadAlgorithm:String] } + * @param {Boolean} [wildcard] - Use a key ID of 0 instead of the public key IDs + * @param {Array} [encryptionKeyIDs] - Array of key IDs to use for encryption. Each encryptionKeyIDs[i] corresponds to keys[i] + * @param {Date} [date] - Override the creation date of the literal package + * @param {Array} [userIDs] - User IDs to encrypt for, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }] + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New message with encrypted content. + * @async + */ + async encrypt(encryptionKeys, passwords, sessionKey, wildcard = false, encryptionKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { + if (sessionKey) { + if (!util.isUint8Array(sessionKey.data) || !util.isString(sessionKey.algorithm)) { + throw new Error('Invalid session key for encryption.'); + } + } else if (encryptionKeys && encryptionKeys.length) { + sessionKey = await Message.generateSessionKey(encryptionKeys, date, userIDs, config); + } else if (passwords && passwords.length) { + sessionKey = await Message.generateSessionKey(undefined, undefined, undefined, config); + } else { + throw new Error('No keys, passwords, or session key provided.'); + } + + const { data: sessionKeyData, algorithm: algorithmName, aeadAlgorithm: aeadAlgorithmName } = sessionKey; + + const msg = await Message.encryptSessionKey(sessionKeyData, algorithmName, aeadAlgorithmName, encryptionKeys, passwords, wildcard, encryptionKeyIDs, date, userIDs, config); + + let symEncryptedPacket; + if (aeadAlgorithmName) { + symEncryptedPacket = new AEADEncryptedDataPacket(); + symEncryptedPacket.aeadAlgorithm = enums.write(enums.aead, aeadAlgorithmName); + } else { + symEncryptedPacket = new SymEncryptedIntegrityProtectedDataPacket(); + } + symEncryptedPacket.packets = this.packets; + + const algorithm = enums.write(enums.symmetric, algorithmName); + await symEncryptedPacket.encrypt(algorithm, sessionKeyData, config); + + msg.packets.push(symEncryptedPacket); + symEncryptedPacket.packets = new PacketList(); // remove packets after encryption + return msg; + } + + /** + * Encrypt a session key either with public keys, passwords, or both at once. + * @param {Uint8Array} sessionKey - session key for encryption + * @param {String} algorithmName - session key algorithm + * @param {String} [aeadAlgorithmName] - AEAD algorithm, e.g. 'eax' or 'ocb' + * @param {Array} [encryptionKeys] - Public key(s) for message encryption + * @param {Array} [passwords] - For message encryption + * @param {Boolean} [wildcard] - Use a key ID of 0 instead of the public key IDs + * @param {Array} [encryptionKeyIDs] - Array of key IDs to use for encryption. Each encryptionKeyIDs[i] corresponds to encryptionKeys[i] + * @param {Date} [date] - Override the date + * @param {Array} [userIDs] - User IDs to encrypt for, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }] + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New message with encrypted content. + * @async + */ + static async encryptSessionKey(sessionKey, algorithmName, aeadAlgorithmName, encryptionKeys, passwords, wildcard = false, encryptionKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { + const packetlist = new PacketList(); + const algorithm = enums.write(enums.symmetric, algorithmName); + const aeadAlgorithm = aeadAlgorithmName && enums.write(enums.aead, aeadAlgorithmName); + + if (encryptionKeys) { + const results = await Promise.all(encryptionKeys.map(async function(primaryKey, i) { + const encryptionKey = await primaryKey.getEncryptionKey(encryptionKeyIDs[i], date, userIDs, config); + const pkESKeyPacket = new PublicKeyEncryptedSessionKeyPacket(); + pkESKeyPacket.publicKeyID = wildcard ? KeyID.wildcard() : encryptionKey.getKeyID(); + pkESKeyPacket.publicKeyAlgorithm = encryptionKey.keyPacket.algorithm; + pkESKeyPacket.sessionKey = sessionKey; + pkESKeyPacket.sessionKeyAlgorithm = algorithm; + await pkESKeyPacket.encrypt(encryptionKey.keyPacket); + delete pkESKeyPacket.sessionKey; // delete plaintext session key after encryption + return pkESKeyPacket; + })); + packetlist.push(...results); + } + if (passwords) { + const testDecrypt = async function(keyPacket, password) { + try { + await keyPacket.decrypt(password); + return 1; + } catch (e) { + return 0; + } + }; + + const sum = (accumulator, currentValue) => accumulator + currentValue; + + const encryptPassword = async function(sessionKey, algorithm, aeadAlgorithm, password) { + const symEncryptedSessionKeyPacket = new SymEncryptedSessionKeyPacket(config); + symEncryptedSessionKeyPacket.sessionKey = sessionKey; + symEncryptedSessionKeyPacket.sessionKeyAlgorithm = algorithm; + if (aeadAlgorithm) { + symEncryptedSessionKeyPacket.aeadAlgorithm = aeadAlgorithm; + } + await symEncryptedSessionKeyPacket.encrypt(password, config); + + if (config.passwordCollisionCheck) { + const results = await Promise.all(passwords.map(pwd => testDecrypt(symEncryptedSessionKeyPacket, pwd))); + if (results.reduce(sum) !== 1) { + return encryptPassword(sessionKey, algorithm, password); + } + } + + delete symEncryptedSessionKeyPacket.sessionKey; // delete plaintext session key after encryption + return symEncryptedSessionKeyPacket; + }; + + const results = await Promise.all(passwords.map(pwd => encryptPassword(sessionKey, algorithm, aeadAlgorithm, pwd))); + packetlist.push(...results); + } + + return new Message(packetlist); + } + + /** + * Sign the message (the literal data packet of the message) + * @param {Array} signingKeys - private keys with decrypted secret key data for signing + * @param {Signature} [signature] - Any existing detached signature to add to the message + * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] + * @param {Date} [date] - Override the creation time of the signature + * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New message with signed content. + * @async + */ + async sign(signingKeys = [], signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { + const packetlist = new PacketList(); + + const literalDataPacket = this.packets.findPacket(enums.packet.literalData); + if (!literalDataPacket) { + throw new Error('No literal data packet to sign.'); + } + + let i; + let existingSigPacketlist; + // If data packet was created from Uint8Array, use binary, otherwise use text + const signatureType = literalDataPacket.text === null ? + enums.signature.binary : enums.signature.text; + + if (signature) { + existingSigPacketlist = signature.packets.filterByTag(enums.packet.signature); + for (i = existingSigPacketlist.length - 1; i >= 0; i--) { + const signaturePacket = existingSigPacketlist[i]; + const onePassSig = new OnePassSignaturePacket(); + onePassSig.signatureType = signaturePacket.signatureType; + onePassSig.hashAlgorithm = signaturePacket.hashAlgorithm; + onePassSig.publicKeyAlgorithm = signaturePacket.publicKeyAlgorithm; + onePassSig.issuerKeyID = signaturePacket.issuerKeyID; + if (!signingKeys.length && i === 0) { + onePassSig.flags = 1; + } + packetlist.push(onePassSig); + } + } + + await Promise.all(Array.from(signingKeys).reverse().map(async function (primaryKey, i) { + if (!primaryKey.isPrivate()) { + throw new Error('Need private key for signing'); + } + const signingKeyID = signingKeyIDs[signingKeys.length - 1 - i]; + const signingKey = await primaryKey.getSigningKey(signingKeyID, date, userIDs, config); + const onePassSig = new OnePassSignaturePacket(); + onePassSig.signatureType = signatureType; + onePassSig.hashAlgorithm = await getPreferredHashAlgo$1(primaryKey, signingKey.keyPacket, date, userIDs, config); + onePassSig.publicKeyAlgorithm = signingKey.keyPacket.algorithm; + onePassSig.issuerKeyID = signingKey.getKeyID(); + if (i === signingKeys.length - 1) { + onePassSig.flags = 1; + } + return onePassSig; + })).then(onePassSignatureList => { + onePassSignatureList.forEach(onePassSig => packetlist.push(onePassSig)); + }); + + packetlist.push(literalDataPacket); + packetlist.push(...(await createSignaturePackets(literalDataPacket, signingKeys, signature, signingKeyIDs, date, userIDs, false, config))); + + return new Message(packetlist); + } + + /** + * Compresses the message (the literal and -if signed- signature data packets of the message) + * @param {module:enums.compression} algo - compression algorithm + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Message} New message with compressed content. + */ + compress(algo, config = defaultConfig) { + if (algo === enums.compression.uncompressed) { + return this; + } + + const compressed = new CompressedDataPacket(config); + compressed.algorithm = algo; + compressed.packets = this.packets; + + const packetList = new PacketList(); + packetList.push(compressed); + + return new Message(packetList); + } + + /** + * Create a detached signature for the message (the literal data packet of the message) + * @param {Array} signingKeys - private keys with decrypted secret key data for signing + * @param {Signature} [signature] - Any existing detached signature + * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] + * @param {Date} [date] - Override the creation time of the signature + * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New detached signature of message content. + * @async + */ + async signDetached(signingKeys = [], signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { + const literalDataPacket = this.packets.findPacket(enums.packet.literalData); + if (!literalDataPacket) { + throw new Error('No literal data packet to sign.'); + } + return new Signature(await createSignaturePackets(literalDataPacket, signingKeys, signature, signingKeyIDs, date, userIDs, true, config)); + } + + /** + * Verify message signatures + * @param {Array} verificationKeys - Array of public keys to verify signatures + * @param {Date} [date] - Verify the signature against the given date, i.e. check signature creation time < date < expiration time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise, + * verified: Promise + * }>>} List of signer's keyID and validity of signatures. + * @async + */ + async verify(verificationKeys, date = new Date(), config = defaultConfig) { + const msg = this.unwrapCompressed(); + const literalDataList = msg.packets.filterByTag(enums.packet.literalData); + if (literalDataList.length !== 1) { + throw new Error('Can only verify message with one literal data packet.'); + } + if (isArrayStream(msg.packets.stream)) { + msg.packets.push(...await readToEnd(msg.packets.stream, _ => _ || [])); + } + const onePassSigList = msg.packets.filterByTag(enums.packet.onePassSignature).reverse(); + const signatureList = msg.packets.filterByTag(enums.packet.signature); + if (onePassSigList.length && !signatureList.length && util.isStream(msg.packets.stream) && !isArrayStream(msg.packets.stream)) { + await Promise.all(onePassSigList.map(async onePassSig => { + onePassSig.correspondingSig = new Promise((resolve, reject) => { + onePassSig.correspondingSigResolve = resolve; + onePassSig.correspondingSigReject = reject; + }); + onePassSig.signatureData = fromAsync(async () => (await onePassSig.correspondingSig).signatureData); + onePassSig.hashed = readToEnd(await onePassSig.hash(onePassSig.signatureType, literalDataList[0], undefined, false)); + onePassSig.hashed.catch(() => {}); + })); + msg.packets.stream = transformPair(msg.packets.stream, async (readable, writable) => { + const reader = getReader(readable); + const writer = getWriter(writable); + try { + for (let i = 0; i < onePassSigList.length; i++) { + const { value: signature } = await reader.read(); + onePassSigList[i].correspondingSigResolve(signature); + } + await reader.readToEnd(); + await writer.ready; + await writer.close(); + } catch (e) { + onePassSigList.forEach(onePassSig => { + onePassSig.correspondingSigReject(e); + }); + await writer.abort(e); + } + }); + return createVerificationObjects(onePassSigList, literalDataList, verificationKeys, date, false, config); + } + return createVerificationObjects(signatureList, literalDataList, verificationKeys, date, false, config); + } + + /** + * Verify detached message signature + * @param {Array} verificationKeys - Array of public keys to verify signatures + * @param {Signature} signature + * @param {Date} date - Verify the signature against the given date, i.e. check signature creation time < date < expiration time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise, + * verified: Promise + * }>>} List of signer's keyID and validity of signature. + * @async + */ + verifyDetached(signature, verificationKeys, date = new Date(), config = defaultConfig) { + const msg = this.unwrapCompressed(); + const literalDataList = msg.packets.filterByTag(enums.packet.literalData); + if (literalDataList.length !== 1) { + throw new Error('Can only verify message with one literal data packet.'); + } + const signatureList = signature.packets; + return createVerificationObjects(signatureList, literalDataList, verificationKeys, date, true, config); + } + + /** + * Unwrap compressed message + * @returns {Message} Message Content of compressed message. + */ + unwrapCompressed() { + const compressed = this.packets.filterByTag(enums.packet.compressedData); + if (compressed.length) { + return new Message(compressed[0].packets); + } + return this; + } + + /** + * Append signature to unencrypted message object + * @param {String|Uint8Array} detachedSignature - The detached ASCII-armored or Uint8Array PGP signature + * @param {Object} [config] - Full configuration, defaults to openpgp.config + */ + async appendSignature(detachedSignature, config = defaultConfig) { + await this.packets.read( + util.isUint8Array(detachedSignature) ? detachedSignature : (await unarmor(detachedSignature)).data, + allowedDetachedSignaturePackets, + config + ); + } + + /** + * Returns binary encoded message + * @returns {ReadableStream} Binary message. + */ + write() { + return this.packets.write(); + } + + /** + * Returns ASCII armored text of message + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {ReadableStream} ASCII armor. + */ + armor(config = defaultConfig) { + return armor(enums.armor.message, this.write(), null, null, null, config); + } + } + + /** + * Create signature packets for the message + * @param {LiteralDataPacket} literalDataPacket - the literal data packet to sign + * @param {Array} [signingKeys] - private keys with decrypted secret key data for signing + * @param {Signature} [signature] - Any existing detached signature to append + * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] + * @param {Date} [date] - Override the creationtime of the signature + * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] + * @param {Boolean} [detached] - Whether to create detached signature packets + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} List of signature packets. + * @async + * @private + */ + async function createSignaturePackets(literalDataPacket, signingKeys, signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], detached = false, config = defaultConfig) { + const packetlist = new PacketList(); + + // If data packet was created from Uint8Array, use binary, otherwise use text + const signatureType = literalDataPacket.text === null ? + enums.signature.binary : enums.signature.text; + + await Promise.all(signingKeys.map(async (primaryKey, i) => { + const userID = userIDs[i]; + if (!primaryKey.isPrivate()) { + throw new Error('Need private key for signing'); + } + const signingKey = await primaryKey.getSigningKey(signingKeyIDs[i], date, userID, config); + return createSignaturePacket(literalDataPacket, primaryKey, signingKey.keyPacket, { signatureType }, date, userID, detached, config); + })).then(signatureList => { + packetlist.push(...signatureList); + }); + + if (signature) { + const existingSigPacketlist = signature.packets.filterByTag(enums.packet.signature); + packetlist.push(...existingSigPacketlist); + } + return packetlist; + } + + /** + * Create object containing signer's keyID and validity of signature + * @param {SignaturePacket} signature - Signature packet + * @param {Array} literalDataList - Array of literal data packets + * @param {Array} verificationKeys - Array of public keys to verify signatures + * @param {Date} [date] - Check signature validity with respect to the given date + * @param {Boolean} [detached] - Whether to verify detached signature packets + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise<{ + * keyID: module:type/keyid~KeyID, + * signature: Promise, + * verified: Promise + * }>} signer's keyID and validity of signature + * @async + * @private + */ + async function createVerificationObject(signature, literalDataList, verificationKeys, date = new Date(), detached = false, config = defaultConfig) { + let primaryKey; + let unverifiedSigningKey; + + for (const key of verificationKeys) { + const issuerKeys = key.getKeys(signature.issuerKeyID); + if (issuerKeys.length > 0) { + primaryKey = key; + unverifiedSigningKey = issuerKeys[0]; + break; + } + } + + const isOnePassSignature = signature instanceof OnePassSignaturePacket; + const signaturePacketPromise = isOnePassSignature ? signature.correspondingSig : signature; + + const verifiedSig = { + keyID: signature.issuerKeyID, + verified: (async () => { + if (!unverifiedSigningKey) { + throw new Error(`Could not find signing key with key ID ${signature.issuerKeyID.toHex()}`); + } + + await signature.verify(unverifiedSigningKey.keyPacket, signature.signatureType, literalDataList[0], date, detached, config); + const signaturePacket = await signaturePacketPromise; + if (unverifiedSigningKey.getCreationTime() > signaturePacket.created) { + throw new Error('Key is newer than the signature'); + } + // We pass the signature creation time to check whether the key was expired at the time of signing. + // We check this after signature verification because for streamed one-pass signatures, the creation time is not available before + try { + await primaryKey.getSigningKey(unverifiedSigningKey.getKeyID(), signaturePacket.created, undefined, config); + } catch (e) { + // If a key was reformatted then the self-signatures of the signing key might be in the future compared to the message signature, + // making the key invalid at the time of signing. + // However, if the key is valid at the given `date`, we still allow using it provided the relevant `config` setting is enabled. + // Note: we do not support the edge case of a key that was reformatted and it has expired. + if (config.allowInsecureVerificationWithReformattedKeys && e.message.match(/Signature creation time is in the future/)) { + await primaryKey.getSigningKey(unverifiedSigningKey.getKeyID(), date, undefined, config); + } else { + throw e; + } + } + return true; + })(), + signature: (async () => { + const signaturePacket = await signaturePacketPromise; + const packetlist = new PacketList(); + signaturePacket && packetlist.push(signaturePacket); + return new Signature(packetlist); + })() + }; + + // Mark potential promise rejections as "handled". This is needed because in + // some cases, we reject them before the user has a reasonable chance to + // handle them (e.g. `await readToEnd(result.data); await result.verified` and + // the data stream errors). + verifiedSig.signature.catch(() => {}); + verifiedSig.verified.catch(() => {}); + + return verifiedSig; + } + + /** + * Create list of objects containing signer's keyID and validity of signature + * @param {Array} signatureList - Array of signature packets + * @param {Array} literalDataList - Array of literal data packets + * @param {Array} verificationKeys - Array of public keys to verify signatures + * @param {Date} date - Verify the signature against the given date, + * i.e. check signature creation time < date < expiration time + * @param {Boolean} [detached] - Whether to verify detached signature packets + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise, + * verified: Promise + * }>>} list of signer's keyID and validity of signatures (one entry per signature packet in input) + * @async + * @private + */ + async function createVerificationObjects(signatureList, literalDataList, verificationKeys, date = new Date(), detached = false, config = defaultConfig) { + return Promise.all(signatureList.filter(function(signature) { + return ['text', 'binary'].includes(enums.read(enums.signature, signature.signatureType)); + }).map(async function(signature) { + return createVerificationObject(signature, literalDataList, verificationKeys, date, detached, config); + })); + } + + /** + * Reads an (optionally armored) OpenPGP message and returns a Message object + * @param {Object} options + * @param {String | ReadableStream} [options.armoredMessage] - Armored message to be parsed + * @param {Uint8Array | ReadableStream} [options.binaryMessage] - Binary to be parsed + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} New message object. + * @async + * @static + */ + async function readMessage({ armoredMessage, binaryMessage, config, ...rest }) { + config = { ...defaultConfig, ...config }; + let input = armoredMessage || binaryMessage; + if (!input) { + throw new Error('readMessage: must pass options object containing `armoredMessage` or `binaryMessage`'); + } + if (armoredMessage && !util.isString(armoredMessage) && !util.isStream(armoredMessage)) { + throw new Error('readMessage: options.armoredMessage must be a string or stream'); + } + if (binaryMessage && !util.isUint8Array(binaryMessage) && !util.isStream(binaryMessage)) { + throw new Error('readMessage: options.binaryMessage must be a Uint8Array or stream'); + } + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + const streamType = util.isStream(input); + if (streamType) { + await loadStreamsPonyfill(); + input = toStream(input); + } + if (armoredMessage) { + const { type, data } = await unarmor(input, config); + if (type !== enums.armor.message) { + throw new Error('Armored text not of type message'); + } + input = data; + } + const packetlist = await PacketList.fromBinary(input, allowedMessagePackets, config); + const message = new Message(packetlist); + message.fromStream = streamType; + return message; + } + + /** + * Creates new message object from text or binary data. + * @param {Object} options + * @param {String | ReadableStream} [options.text] - The text message contents + * @param {Uint8Array | ReadableStream} [options.binary] - The binary message contents + * @param {String} [options.filename=""] - Name of the file (if any) + * @param {Date} [options.date=current date] - Date of the message, or modification date of the file + * @param {'utf8'|'binary'|'text'|'mime'} [options.format='utf8' if text is passed, 'binary' otherwise] - Data packet type + * @returns {Promise} New message object. + * @async + * @static + */ + async function createMessage({ text, binary, filename, date = new Date(), format = text !== undefined ? 'utf8' : 'binary', ...rest }) { + let input = text !== undefined ? text : binary; + if (input === undefined) { + throw new Error('createMessage: must pass options object containing `text` or `binary`'); + } + if (text && !util.isString(text) && !util.isStream(text)) { + throw new Error('createMessage: options.text must be a string or stream'); + } + if (binary && !util.isUint8Array(binary) && !util.isStream(binary)) { + throw new Error('createMessage: options.binary must be a Uint8Array or stream'); + } + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + const streamType = util.isStream(input); + if (streamType) { + await loadStreamsPonyfill(); + input = toStream(input); + } + const literalDataPacket = new LiteralDataPacket(date); + if (text !== undefined) { + literalDataPacket.setText(input, enums.write(enums.literal, format)); + } else { + literalDataPacket.setBytes(input, enums.write(enums.literal, format)); + } + if (filename !== undefined) { + literalDataPacket.setFilename(filename); + } + const literalDataPacketlist = new PacketList(); + literalDataPacketlist.push(literalDataPacket); + const message = new Message(literalDataPacketlist); + message.fromStream = streamType; + return message; + } + + // GPG4Browsers - An OpenPGP implementation in javascript + + // A Cleartext message can contain the following packets + const allowedPackets$5 = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); + + /** + * Class that represents an OpenPGP cleartext signed message. + * See {@link https://tools.ietf.org/html/rfc4880#section-7} + */ + class CleartextMessage { + /** + * @param {String} text - The cleartext of the signed message + * @param {Signature} signature - The detached signature or an empty signature for unsigned messages + */ + constructor(text, signature) { + // normalize EOL to canonical form + this.text = util.removeTrailingSpaces(text).replace(/\r?\n/g, '\r\n'); + if (signature && !(signature instanceof Signature)) { + throw new Error('Invalid signature input'); + } + this.signature = signature || new Signature(new PacketList()); + } + + /** + * Returns the key IDs of the keys that signed the cleartext message + * @returns {Array} Array of keyID objects. + */ + getSigningKeyIDs() { + const keyIDs = []; + const signatureList = this.signature.packets; + signatureList.forEach(function(packet) { + keyIDs.push(packet.issuerKeyID); + }); + return keyIDs; + } + + /** + * Sign the cleartext message + * @param {Array} privateKeys - private keys with decrypted secret key data for signing + * @param {Signature} [signature] - Any existing detached signature + * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to privateKeys[i] + * @param {Date} [date] - The creation time of the signature that should be created + * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise} New cleartext message with signed content. + * @async + */ + async sign(privateKeys, signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { + const literalDataPacket = new LiteralDataPacket(); + literalDataPacket.setText(this.text); + const newSignature = new Signature(await createSignaturePackets(literalDataPacket, privateKeys, signature, signingKeyIDs, date, userIDs, true, config)); + return new CleartextMessage(this.text, newSignature); + } + + /** + * Verify signatures of cleartext signed message + * @param {Array} keys - Array of keys to verify signatures + * @param {Date} [date] - Verify the signature against the given date, i.e. check signature creation time < date < expiration time + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {Promise, + * verified: Promise + * }>>} List of signer's keyID and validity of signature. + * @async + */ + verify(keys, date = new Date(), config = defaultConfig) { + const signatureList = this.signature.packets; + const literalDataPacket = new LiteralDataPacket(); + // we assume that cleartext signature is generated based on UTF8 cleartext + literalDataPacket.setText(this.text); + return createVerificationObjects(signatureList, [literalDataPacket], keys, date, true, config); + } + + /** + * Get cleartext + * @returns {String} Cleartext of message. + */ + getText() { + // normalize end of line to \n + return this.text.replace(/\r\n/g, '\n'); + } + + /** + * Returns ASCII armored text of cleartext signed message + * @param {Object} [config] - Full configuration, defaults to openpgp.config + * @returns {String | ReadableStream} ASCII armor. + */ + armor(config = defaultConfig) { + let hashes = this.signature.packets.map(function(packet) { + return enums.read(enums.hash, packet.hashAlgorithm).toUpperCase(); + }); + hashes = hashes.filter(function(item, i, ar) { return ar.indexOf(item) === i; }); + const body = { + hash: hashes.join(), + text: this.text, + data: this.signature.packets.write() + }; + return armor(enums.armor.signed, body, undefined, undefined, undefined, config); + } + } + + /** + * Reads an OpenPGP cleartext signed message and returns a CleartextMessage object + * @param {Object} options + * @param {String} options.cleartextMessage - Text to be parsed + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} New cleartext message object. + * @async + * @static + */ + async function readCleartextMessage({ cleartextMessage, config, ...rest }) { + config = { ...defaultConfig, ...config }; + if (!cleartextMessage) { + throw new Error('readCleartextMessage: must pass options object containing `cleartextMessage`'); + } + if (!util.isString(cleartextMessage)) { + throw new Error('readCleartextMessage: options.cleartextMessage must be a string'); + } + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + const input = await unarmor(cleartextMessage); + if (input.type !== enums.armor.signed) { + throw new Error('No cleartext signed message.'); + } + const packetlist = await PacketList.fromBinary(input.data, allowedPackets$5, config); + verifyHeaders$1(input.headers, packetlist); + const signature = new Signature(packetlist); + return new CleartextMessage(input.text, signature); + } + + /** + * Compare hash algorithm specified in the armor header with signatures + * @param {Array} headers - Armor headers + * @param {PacketList} packetlist - The packetlist with signature packets + * @private + */ + function verifyHeaders$1(headers, packetlist) { + const checkHashAlgos = function(hashAlgos) { + const check = packet => algo => packet.hashAlgorithm === algo; + + for (let i = 0; i < packetlist.length; i++) { + if (packetlist[i].constructor.tag === enums.packet.signature && !hashAlgos.some(check(packetlist[i]))) { + return false; + } + } + return true; + }; + + let oneHeader = null; + let hashAlgos = []; + headers.forEach(function(header) { + oneHeader = header.match(/Hash: (.+)/); // get header value + if (oneHeader) { + oneHeader = oneHeader[1].replace(/\s/g, ''); // remove whitespace + oneHeader = oneHeader.split(','); + oneHeader = oneHeader.map(function(hash) { + hash = hash.toLowerCase(); + try { + return enums.write(enums.hash, hash); + } catch (e) { + throw new Error('Unknown hash algorithm in armor header: ' + hash); + } + }); + hashAlgos = hashAlgos.concat(oneHeader); + } else { + throw new Error('Only "Hash" header allowed in cleartext signed message'); + } + }); + + if (!hashAlgos.length && !checkHashAlgos([enums.hash.md5])) { + throw new Error('If no "Hash" header in cleartext signed message, then only MD5 signatures allowed'); + } else if (hashAlgos.length && !checkHashAlgos(hashAlgos)) { + throw new Error('Hash algorithm mismatch in armor header and signature'); + } + } + + /** + * Creates a new CleartextMessage object from text + * @param {Object} options + * @param {String} options.text + * @static + * @async + */ + async function createCleartextMessage({ text, ...rest }) { + if (!text) { + throw new Error('createCleartextMessage: must pass options object containing `text`'); + } + if (!util.isString(text)) { + throw new Error('createCleartextMessage: options.text must be a string'); + } + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + return new CleartextMessage(text); + } + + // OpenPGP.js - An OpenPGP implementation in javascript + + + ////////////////////// + // // + // Key handling // + // // + ////////////////////// + + + /** + * Generates a new OpenPGP key pair. Supports RSA and ECC keys. By default, primary and subkeys will be of same type. + * The generated primary key will have signing capabilities. By default, one subkey with encryption capabilities is also generated. + * @param {Object} options + * @param {Object|Array} options.userIDs - User IDs as objects: `{ name: 'Jo Doe', email: 'info@jo.com' }` + * @param {'ecc'|'rsa'} [options.type='ecc'] - The primary key algorithm type: ECC (default) or RSA + * @param {String} [options.passphrase=(not protected)] - The passphrase used to encrypt the generated private key. If omitted, the key won't be encrypted. + * @param {Number} [options.rsaBits=4096] - Number of bits for RSA keys + * @param {String} [options.curve='curve25519'] - Elliptic curve for ECC keys: + * curve25519 (default), p256, p384, p521, secp256k1, + * brainpoolP256r1, brainpoolP384r1, or brainpoolP512r1 + * @param {Date} [options.date=current date] - Override the creation date of the key and the key signatures + * @param {Number} [options.keyExpirationTime=0 (never expires)] - Number of seconds from the key creation time after which the key expires + * @param {Array} [options.subkeys=a single encryption subkey] - Options for each subkey e.g. `[{sign: true, passphrase: '123'}]` + * default to main key options, except for `sign` parameter that defaults to false, and indicates whether the subkey should sign rather than encrypt + * @param {'armored'|'binary'|'object'} [options.format='armored'] - format of the output keys + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} The generated key object in the form: + * { privateKey:PrivateKey|Uint8Array|String, publicKey:PublicKey|Uint8Array|String, revocationCertificate:String } + * @async + * @static + */ + async function generateKey({ userIDs = [], passphrase = '', type = 'ecc', rsaBits = 4096, curve = 'curve25519', keyExpirationTime = 0, date = new Date(), subkeys = [{}], format = 'armored', config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + userIDs = toArray$1(userIDs); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + if (userIDs.length === 0) { + throw new Error('UserIDs are required for key generation'); + } + if (type === 'rsa' && rsaBits < config.minRSABits) { + throw new Error(`rsaBits should be at least ${config.minRSABits}, got: ${rsaBits}`); + } + + const options = { userIDs, passphrase, type, rsaBits, curve, keyExpirationTime, date, subkeys }; + + try { + const { key, revocationCertificate } = await generate$2(options, config); + key.getKeys().forEach(({ keyPacket }) => checkKeyRequirements(keyPacket, config)); + + return { + privateKey: formatObject(key, format, config), + publicKey: formatObject(key.toPublic(), format, config), + revocationCertificate + }; + } catch (err) { + throw util.wrapError('Error generating keypair', err); + } + } + + /** + * Reformats signature packets for a key and rewraps key object. + * @param {Object} options + * @param {PrivateKey} options.privateKey - Private key to reformat + * @param {Object|Array} options.userIDs - User IDs as objects: `{ name: 'Jo Doe', email: 'info@jo.com' }` + * @param {String} [options.passphrase=(not protected)] - The passphrase used to encrypt the reformatted private key. If omitted, the key won't be encrypted. + * @param {Number} [options.keyExpirationTime=0 (never expires)] - Number of seconds from the key creation time after which the key expires + * @param {Date} [options.date] - Override the creation date of the key signatures. If the key was previously used to sign messages, it is recommended + * to set the same date as the key creation time to ensure that old message signatures will still be verifiable using the reformatted key. + * @param {'armored'|'binary'|'object'} [options.format='armored'] - format of the output keys + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} The generated key object in the form: + * { privateKey:PrivateKey|Uint8Array|String, publicKey:PublicKey|Uint8Array|String, revocationCertificate:String } + * @async + * @static + */ + async function reformatKey({ privateKey, userIDs = [], passphrase = '', keyExpirationTime = 0, date, format = 'armored', config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + userIDs = toArray$1(userIDs); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + if (userIDs.length === 0) { + throw new Error('UserIDs are required for key reformat'); + } + const options = { privateKey, userIDs, passphrase, keyExpirationTime, date }; + + try { + const { key: reformattedKey, revocationCertificate } = await reformat(options, config); + + return { + privateKey: formatObject(reformattedKey, format, config), + publicKey: formatObject(reformattedKey.toPublic(), format, config), + revocationCertificate + }; + } catch (err) { + throw util.wrapError('Error reformatting keypair', err); + } + } + + /** + * Revokes a key. Requires either a private key or a revocation certificate. + * If a revocation certificate is passed, the reasonForRevocation parameter will be ignored. + * @param {Object} options + * @param {Key} options.key - Public or private key to revoke + * @param {String} [options.revocationCertificate] - Revocation certificate to revoke the key with + * @param {Object} [options.reasonForRevocation] - Object indicating the reason for revocation + * @param {module:enums.reasonForRevocation} [options.reasonForRevocation.flag=[noReason]{@link module:enums.reasonForRevocation}] - Flag indicating the reason for revocation + * @param {String} [options.reasonForRevocation.string=""] - String explaining the reason for revocation + * @param {Date} [options.date] - Use the given date instead of the current time to verify validity of revocation certificate (if provided), or as creation time of the revocation signature + * @param {'armored'|'binary'|'object'} [options.format='armored'] - format of the output key(s) + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} The revoked key in the form: + * { privateKey:PrivateKey|Uint8Array|String, publicKey:PublicKey|Uint8Array|String } if private key is passed, or + * { privateKey: null, publicKey:PublicKey|Uint8Array|String } otherwise + * @async + * @static + */ + async function revokeKey({ key, revocationCertificate, reasonForRevocation, date = new Date(), format = 'armored', config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + try { + const revokedKey = revocationCertificate ? + await key.applyRevocationCertificate(revocationCertificate, date, config) : + await key.revoke(reasonForRevocation, date, config); + + return revokedKey.isPrivate() ? { + privateKey: formatObject(revokedKey, format, config), + publicKey: formatObject(revokedKey.toPublic(), format, config) + } : { + privateKey: null, + publicKey: formatObject(revokedKey, format, config) + }; + } catch (err) { + throw util.wrapError('Error revoking key', err); + } + } + + /** + * Unlock a private key with the given passphrase. + * This method does not change the original key. + * @param {Object} options + * @param {PrivateKey} options.privateKey - The private key to decrypt + * @param {String|Array} options.passphrase - The user's passphrase(s) + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} The unlocked key object. + * @async + */ + async function decryptKey({ privateKey, passphrase, config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + if (!privateKey.isPrivate()) { + throw new Error('Cannot decrypt a public key'); + } + const clonedPrivateKey = privateKey.clone(true); + const passphrases = util.isArray(passphrase) ? passphrase : [passphrase]; + + try { + await Promise.all(clonedPrivateKey.getKeys().map(key => ( + // try to decrypt each key with any of the given passphrases + util.anyPromise(passphrases.map(passphrase => key.keyPacket.decrypt(passphrase))) + ))); + + await clonedPrivateKey.validate(config); + return clonedPrivateKey; + } catch (err) { + clonedPrivateKey.clearPrivateParams(); + throw util.wrapError('Error decrypting private key', err); + } + } + + /** + * Lock a private key with the given passphrase. + * This method does not change the original key. + * @param {Object} options + * @param {PrivateKey} options.privateKey - The private key to encrypt + * @param {String|Array} options.passphrase - If multiple passphrases, they should be in the same order as the packets each should encrypt + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} The locked key object. + * @async + */ + async function encryptKey({ privateKey, passphrase, config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + if (!privateKey.isPrivate()) { + throw new Error('Cannot encrypt a public key'); + } + const clonedPrivateKey = privateKey.clone(true); + + const keys = clonedPrivateKey.getKeys(); + const passphrases = util.isArray(passphrase) ? passphrase : new Array(keys.length).fill(passphrase); + if (passphrases.length !== keys.length) { + throw new Error('Invalid number of passphrases given for key encryption'); + } + + try { + await Promise.all(keys.map(async (key, i) => { + const { keyPacket } = key; + await keyPacket.encrypt(passphrases[i], config); + keyPacket.clearPrivateParams(); + })); + return clonedPrivateKey; + } catch (err) { + clonedPrivateKey.clearPrivateParams(); + throw util.wrapError('Error encrypting private key', err); + } + } + + + /////////////////////////////////////////// + // // + // Message encryption and decryption // + // // + /////////////////////////////////////////// + + + /** + * Encrypts a message using public keys, passwords or both at once. At least one of `encryptionKeys` or `passwords` + * must be specified. If signing keys are specified, those will be used to sign the message. + * @param {Object} options + * @param {Message} options.message - Message to be encrypted as created by {@link createMessage} + * @param {PublicKey|PublicKey[]} [options.encryptionKeys] - Array of keys or single key, used to encrypt the message + * @param {PrivateKey|PrivateKey[]} [options.signingKeys] - Private keys for signing. If omitted message will not be signed + * @param {String|String[]} [options.passwords] - Array of passwords or a single password to encrypt the message + * @param {Object} [options.sessionKey] - Session key in the form: `{ data:Uint8Array, algorithm:String }` + * @param {'armored'|'binary'|'object'} [options.format='armored'] - Format of the returned message + * @param {Signature} [options.signature] - A detached signature to add to the encrypted message + * @param {Boolean} [options.wildcard=false] - Use a key ID of 0 instead of the public key IDs + * @param {KeyID|KeyID[]} [options.signingKeyIDs=latest-created valid signing (sub)keys] - Array of key IDs to use for signing. Each `signingKeyIDs[i]` corresponds to `signingKeys[i]` + * @param {KeyID|KeyID[]} [options.encryptionKeyIDs=latest-created valid encryption (sub)keys] - Array of key IDs to use for encryption. Each `encryptionKeyIDs[i]` corresponds to `encryptionKeys[i]` + * @param {Date} [options.date=current date] - Override the creation date of the message signature + * @param {Object|Object[]} [options.signingUserIDs=primary user IDs] - Array of user IDs to sign with, one per key in `signingKeys`, e.g. `[{ name: 'Steve Sender', email: 'steve@openpgp.org' }]` + * @param {Object|Object[]} [options.encryptionUserIDs=primary user IDs] - Array of user IDs to encrypt for, one per key in `encryptionKeys`, e.g. `[{ name: 'Robert Receiver', email: 'robert@openpgp.org' }]` + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise|MaybeStream>} Encrypted message (string if `armor` was true, the default; Uint8Array if `armor` was false). + * @async + * @static + */ + async function encrypt$4({ message, encryptionKeys, signingKeys, passwords, sessionKey, format = 'armored', signature = null, wildcard = false, signingKeyIDs = [], encryptionKeyIDs = [], date = new Date(), signingUserIDs = [], encryptionUserIDs = [], config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + checkMessage(message); checkOutputMessageFormat(format); + encryptionKeys = toArray$1(encryptionKeys); signingKeys = toArray$1(signingKeys); passwords = toArray$1(passwords); + signingKeyIDs = toArray$1(signingKeyIDs); encryptionKeyIDs = toArray$1(encryptionKeyIDs); signingUserIDs = toArray$1(signingUserIDs); encryptionUserIDs = toArray$1(encryptionUserIDs); + if (rest.detached) { + throw new Error("The `detached` option has been removed from openpgp.encrypt, separately call openpgp.sign instead. Don't forget to remove the `privateKeys` option as well."); + } + if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.encrypt, pass `encryptionKeys` instead'); + if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.encrypt, pass `signingKeys` instead'); + if (rest.armor !== undefined) throw new Error('The `armor` option has been removed from openpgp.encrypt, pass `format` instead.'); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + if (!signingKeys) { + signingKeys = []; + } + const streaming = message.fromStream; + try { + if (signingKeys.length || signature) { // sign the message only if signing keys or signature is specified + message = await message.sign(signingKeys, signature, signingKeyIDs, date, signingUserIDs, config); + } + message = message.compress( + await getPreferredAlgo('compression', encryptionKeys, date, encryptionUserIDs, config), + config + ); + message = await message.encrypt(encryptionKeys, passwords, sessionKey, wildcard, encryptionKeyIDs, date, encryptionUserIDs, config); + if (format === 'object') return message; + // serialize data + const armor = format === 'armored'; + const data = armor ? message.armor(config) : message.write(); + return convertStream(data, streaming, armor ? 'utf8' : 'binary'); + } catch (err) { + throw util.wrapError('Error encrypting message', err); + } + } + + /** + * Decrypts a message with the user's private key, a session key or a password. + * One of `decryptionKeys`, `sessionkeys` or `passwords` must be specified (passing a combination of these options is not supported). + * @param {Object} options + * @param {Message} options.message - The message object with the encrypted data + * @param {PrivateKey|PrivateKey[]} [options.decryptionKeys] - Private keys with decrypted secret key data or session key + * @param {String|String[]} [options.passwords] - Passwords to decrypt the message + * @param {Object|Object[]} [options.sessionKeys] - Session keys in the form: { data:Uint8Array, algorithm:String } + * @param {PublicKey|PublicKey[]} [options.verificationKeys] - Array of public keys or single key, to verify signatures + * @param {Boolean} [options.expectSigned=false] - If true, data decryption fails if the message is not signed with the provided publicKeys + * @param {'utf8'|'binary'} [options.format='utf8'] - Whether to return data as a string(Stream) or Uint8Array(Stream). If 'utf8' (the default), also normalize newlines. + * @param {Signature} [options.signature] - Detached signature for verification + * @param {Date} [options.date=current date] - Use the given date for verification instead of the current time + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} Object containing decrypted and verified message in the form: + * + * { + * data: MaybeStream, (if format was 'utf8', the default) + * data: MaybeStream, (if format was 'binary') + * filename: String, + * signatures: [ + * { + * keyID: module:type/keyid~KeyID, + * verified: Promise, + * signature: Promise + * }, ... + * ] + * } + * + * where `signatures` contains a separate entry for each signature packet found in the input message. + * @async + * @static + */ + async function decrypt$4({ message, decryptionKeys, passwords, sessionKeys, verificationKeys, expectSigned = false, format = 'utf8', signature = null, date = new Date(), config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + checkMessage(message); verificationKeys = toArray$1(verificationKeys); decryptionKeys = toArray$1(decryptionKeys); passwords = toArray$1(passwords); sessionKeys = toArray$1(sessionKeys); + if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.decrypt, pass `decryptionKeys` instead'); + if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.decrypt, pass `verificationKeys` instead'); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + try { + const decrypted = await message.decrypt(decryptionKeys, passwords, sessionKeys, date, config); + if (!verificationKeys) { + verificationKeys = []; + } + + const result = {}; + result.signatures = signature ? await decrypted.verifyDetached(signature, verificationKeys, date, config) : await decrypted.verify(verificationKeys, date, config); + result.data = format === 'binary' ? decrypted.getLiteralData() : decrypted.getText(); + result.filename = decrypted.getFilename(); + linkStreams(result, message); + if (expectSigned) { + if (verificationKeys.length === 0) { + throw new Error('Verification keys are required to verify message signatures'); + } + if (result.signatures.length === 0) { + throw new Error('Message is not signed'); + } + result.data = concat([ + result.data, + fromAsync(async () => { + await util.anyPromise(result.signatures.map(sig => sig.verified)); + }) + ]); + } + result.data = await convertStream(result.data, message.fromStream, format); + return result; + } catch (err) { + throw util.wrapError('Error decrypting message', err); + } + } + + + ////////////////////////////////////////// + // // + // Message signing and verification // + // // + ////////////////////////////////////////// + + + /** + * Signs a message. + * @param {Object} options + * @param {CleartextMessage|Message} options.message - (cleartext) message to be signed + * @param {PrivateKey|PrivateKey[]} options.signingKeys - Array of keys or single key with decrypted secret key data to sign cleartext + * @param {'armored'|'binary'|'object'} [options.format='armored'] - Format of the returned message + * @param {Boolean} [options.detached=false] - If the return value should contain a detached signature + * @param {KeyID|KeyID[]} [options.signingKeyIDs=latest-created valid signing (sub)keys] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] + * @param {Date} [options.date=current date] - Override the creation date of the signature + * @param {Object|Object[]} [options.signingUserIDs=primary user IDs] - Array of user IDs to sign with, one per key in `signingKeys`, e.g. `[{ name: 'Steve Sender', email: 'steve@openpgp.org' }]` + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise>} Signed message (string if `armor` was true, the default; Uint8Array if `armor` was false). + * @async + * @static + */ + async function sign$5({ message, signingKeys, format = 'armored', detached = false, signingKeyIDs = [], date = new Date(), signingUserIDs = [], config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + checkCleartextOrMessage(message); checkOutputMessageFormat(format); + signingKeys = toArray$1(signingKeys); signingKeyIDs = toArray$1(signingKeyIDs); signingUserIDs = toArray$1(signingUserIDs); + + if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.sign, pass `signingKeys` instead'); + if (rest.armor !== undefined) throw new Error('The `armor` option has been removed from openpgp.sign, pass `format` instead.'); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + if (message instanceof CleartextMessage && format === 'binary') throw new Error('Cannot return signed cleartext message in binary format'); + if (message instanceof CleartextMessage && detached) throw new Error('Cannot detach-sign a cleartext message'); + + if (!signingKeys || signingKeys.length === 0) { + throw new Error('No signing keys provided'); + } + + try { + let signature; + if (detached) { + signature = await message.signDetached(signingKeys, undefined, signingKeyIDs, date, signingUserIDs, config); + } else { + signature = await message.sign(signingKeys, undefined, signingKeyIDs, date, signingUserIDs, config); + } + if (format === 'object') return signature; + + const armor = format === 'armored'; + signature = armor ? signature.armor(config) : signature.write(); + if (detached) { + signature = transformPair(message.packets.write(), async (readable, writable) => { + await Promise.all([ + pipe(signature, writable), + readToEnd(readable).catch(() => {}) + ]); + }); + } + return convertStream(signature, message.fromStream, armor ? 'utf8' : 'binary'); + } catch (err) { + throw util.wrapError('Error signing message', err); + } + } + + /** + * Verifies signatures of cleartext signed message + * @param {Object} options + * @param {CleartextMessage|Message} options.message - (cleartext) message object with signatures + * @param {PublicKey|PublicKey[]} options.verificationKeys - Array of publicKeys or single key, to verify signatures + * @param {Boolean} [options.expectSigned=false] - If true, verification throws if the message is not signed with the provided publicKeys + * @param {'utf8'|'binary'} [options.format='utf8'] - Whether to return data as a string(Stream) or Uint8Array(Stream). If 'utf8' (the default), also normalize newlines. + * @param {Signature} [options.signature] - Detached signature for verification + * @param {Date} [options.date=current date] - Use the given date for verification instead of the current time + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} Object containing verified message in the form: + * + * { + * data: MaybeStream, (if `message` was a CleartextMessage) + * data: MaybeStream, (if `message` was a Message) + * signatures: [ + * { + * keyID: module:type/keyid~KeyID, + * verified: Promise, + * signature: Promise + * }, ... + * ] + * } + * + * where `signatures` contains a separate entry for each signature packet found in the input message. + * @async + * @static + */ + async function verify$5({ message, verificationKeys, expectSigned = false, format = 'utf8', signature = null, date = new Date(), config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + checkCleartextOrMessage(message); verificationKeys = toArray$1(verificationKeys); + if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.verify, pass `verificationKeys` instead'); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + if (message instanceof CleartextMessage && format === 'binary') throw new Error("Can't return cleartext message data as binary"); + if (message instanceof CleartextMessage && signature) throw new Error("Can't verify detached cleartext signature"); + + try { + const result = {}; + if (signature) { + result.signatures = await message.verifyDetached(signature, verificationKeys, date, config); + } else { + result.signatures = await message.verify(verificationKeys, date, config); + } + result.data = format === 'binary' ? message.getLiteralData() : message.getText(); + if (message.fromStream) linkStreams(result, message); + if (expectSigned) { + if (result.signatures.length === 0) { + throw new Error('Message is not signed'); + } + result.data = concat([ + result.data, + fromAsync(async () => { + await util.anyPromise(result.signatures.map(sig => sig.verified)); + }) + ]); + } + result.data = await convertStream(result.data, message.fromStream, format); + return result; + } catch (err) { + throw util.wrapError('Error verifying signed message', err); + } + } + + + /////////////////////////////////////////////// + // // + // Session key encryption and decryption // + // // + /////////////////////////////////////////////// + + /** + * Generate a new session key object, taking the algorithm preferences of the passed public keys into account. + * @param {Object} options + * @param {PublicKey|PublicKey[]} options.encryptionKeys - Array of public keys or single key used to select algorithm preferences for + * @param {Date} [options.date=current date] - Date to select algorithm preferences at + * @param {Object|Object[]} [options.encryptionUserIDs=primary user IDs] - User IDs to select algorithm preferences for + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise<{ data: Uint8Array, algorithm: String }>} Object with session key data and algorithm. + * @async + * @static + */ + async function generateSessionKey$1({ encryptionKeys, date = new Date(), encryptionUserIDs = [], config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + encryptionKeys = toArray$1(encryptionKeys); encryptionUserIDs = toArray$1(encryptionUserIDs); + if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.generateSessionKey, pass `encryptionKeys` instead'); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + try { + const sessionKeys = await Message.generateSessionKey(encryptionKeys, date, encryptionUserIDs, config); + return sessionKeys; + } catch (err) { + throw util.wrapError('Error generating session key', err); + } + } + + /** + * Encrypt a symmetric session key with public keys, passwords, or both at once. + * At least one of `encryptionKeys` or `passwords` must be specified. + * @param {Object} options + * @param {Uint8Array} options.data - The session key to be encrypted e.g. 16 random bytes (for aes128) + * @param {String} options.algorithm - Algorithm of the symmetric session key e.g. 'aes128' or 'aes256' + * @param {String} [options.aeadAlgorithm] - AEAD algorithm, e.g. 'eax' or 'ocb' + * @param {PublicKey|PublicKey[]} [options.encryptionKeys] - Array of public keys or single key, used to encrypt the key + * @param {String|String[]} [options.passwords] - Passwords for the message + * @param {'armored'|'binary'} [options.format='armored'] - Format of the returned value + * @param {Boolean} [options.wildcard=false] - Use a key ID of 0 instead of the public key IDs + * @param {KeyID|KeyID[]} [options.encryptionKeyIDs=latest-created valid encryption (sub)keys] - Array of key IDs to use for encryption. Each encryptionKeyIDs[i] corresponds to encryptionKeys[i] + * @param {Date} [options.date=current date] - Override the date + * @param {Object|Object[]} [options.encryptionUserIDs=primary user IDs] - Array of user IDs to encrypt for, one per key in `encryptionKeys`, e.g. `[{ name: 'Phil Zimmermann', email: 'phil@openpgp.org' }]` + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} Encrypted session keys (string if `armor` was true, the default; Uint8Array if `armor` was false). + * @async + * @static + */ + async function encryptSessionKey({ data, algorithm, aeadAlgorithm, encryptionKeys, passwords, format = 'armored', wildcard = false, encryptionKeyIDs = [], date = new Date(), encryptionUserIDs = [], config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + checkBinary(data); checkString(algorithm, 'algorithm'); checkOutputMessageFormat(format); + encryptionKeys = toArray$1(encryptionKeys); passwords = toArray$1(passwords); encryptionKeyIDs = toArray$1(encryptionKeyIDs); encryptionUserIDs = toArray$1(encryptionUserIDs); + if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.encryptSessionKey, pass `encryptionKeys` instead'); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + try { + const message = await Message.encryptSessionKey(data, algorithm, aeadAlgorithm, encryptionKeys, passwords, wildcard, encryptionKeyIDs, date, encryptionUserIDs, config); + return formatObject(message, format, config); + } catch (err) { + throw util.wrapError('Error encrypting session key', err); + } + } + + /** + * Decrypt symmetric session keys using private keys or passwords (not both). + * One of `decryptionKeys` or `passwords` must be specified. + * @param {Object} options + * @param {Message} options.message - A message object containing the encrypted session key packets + * @param {PrivateKey|PrivateKey[]} [options.decryptionKeys] - Private keys with decrypted secret key data + * @param {String|String[]} [options.passwords] - Passwords to decrypt the session key + * @param {Date} [options.date] - Date to use for key verification instead of the current time + * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} + * @returns {Promise} Array of decrypted session key, algorithm pairs in the form: + * { data:Uint8Array, algorithm:String } + * @throws if no session key could be found or decrypted + * @async + * @static + */ + async function decryptSessionKeys({ message, decryptionKeys, passwords, date = new Date(), config, ...rest }) { + config = { ...defaultConfig, ...config }; checkConfig(config); + checkMessage(message); decryptionKeys = toArray$1(decryptionKeys); passwords = toArray$1(passwords); + if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.decryptSessionKeys, pass `decryptionKeys` instead'); + const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); + + try { + const sessionKeys = await message.decryptSessionKeys(decryptionKeys, passwords, date, config); + return sessionKeys; + } catch (err) { + throw util.wrapError('Error decrypting session keys', err); + } + } + + + ////////////////////////// + // // + // Helper functions // + // // + ////////////////////////// + + + /** + * Input validation + * @private + */ + function checkString(data, name) { + if (!util.isString(data)) { + throw new Error('Parameter [' + (name || 'data') + '] must be of type String'); + } + } + function checkBinary(data, name) { + if (!util.isUint8Array(data)) { + throw new Error('Parameter [' + (name || 'data') + '] must be of type Uint8Array'); + } + } + function checkMessage(message) { + if (!(message instanceof Message)) { + throw new Error('Parameter [message] needs to be of type Message'); + } + } + function checkCleartextOrMessage(message) { + if (!(message instanceof CleartextMessage) && !(message instanceof Message)) { + throw new Error('Parameter [message] needs to be of type Message or CleartextMessage'); + } + } + function checkOutputMessageFormat(format) { + if (format !== 'armored' && format !== 'binary' && format !== 'object') { + throw new Error(`Unsupported format ${format}`); + } + } + const defaultConfigPropsCount = Object.keys(defaultConfig).length; + function checkConfig(config) { + const inputConfigProps = Object.keys(config); + if (inputConfigProps.length !== defaultConfigPropsCount) { + for (const inputProp of inputConfigProps) { + if (defaultConfig[inputProp] === undefined) { + throw new Error(`Unknown config property: ${inputProp}`); + } + } + } + } + + /** + * Normalize parameter to an array if it is not undefined. + * @param {Object} param - the parameter to be normalized + * @returns {Array|undefined} The resulting array or undefined. + * @private + */ + function toArray$1(param) { + if (param && !util.isArray(param)) { + param = [param]; + } + return param; + } + + /** + * Convert data to or from Stream + * @param {Object} data - the data to convert + * @param {'web'|'ponyfill'|'node'|false} streaming - Whether to return a ReadableStream, and of what type + * @param {'utf8'|'binary'} [encoding] - How to return data in Node Readable streams + * @returns {Promise} The data in the respective format. + * @async + * @private + */ + async function convertStream(data, streaming, encoding = 'utf8') { + const streamType = util.isStream(data); + if (streamType === 'array') { + return readToEnd(data); + } + if (streaming === 'node') { + data = webToNode(data); + if (encoding !== 'binary') data.setEncoding(encoding); + return data; + } + if (streaming === 'web' && streamType === 'ponyfill') { + return toNativeReadable(data); + } + return data; + } + + /** + * Link result.data to the message stream for cancellation. + * Also, forward errors in the message to result.data. + * @param {Object} result - the data to convert + * @param {Message} message - message object + * @returns {Object} + * @private + */ + function linkStreams(result, message) { + result.data = transformPair(message.packets.stream, async (readable, writable) => { + await pipe(result.data, writable, { + preventClose: true + }); + const writer = getWriter(writable); + try { + // Forward errors in the message stream to result.data. + await readToEnd(readable, _ => _); + await writer.close(); + } catch (e) { + await writer.abort(e); + } + }); + } + + /** + * Convert the object to the given format + * @param {Key|Message} object + * @param {'armored'|'binary'|'object'} format + * @param {Object} config - Full configuration + * @returns {String|Uint8Array|Object} + */ + function formatObject(object, format, config) { + switch (format) { + case 'object': + return object; + case 'armored': + return object.armor(config); + case 'binary': + return object.write(); + default: + throw new Error(`Unsupported format ${format}`); + } + } + + /** + * web-streams-polyfill v3.0.3 + */ + /// + const SymbolPolyfill = typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol' ? + Symbol : + description => `Symbol(${description})`; + + /// + function noop() { + return undefined; + } + function getGlobals() { + if (typeof self !== 'undefined') { + return self; + } + else if (typeof window !== 'undefined') { + return window; + } + else if (typeof global !== 'undefined') { + return global; + } + return undefined; + } + const globals = getGlobals(); + + function typeIsObject(x) { + return (typeof x === 'object' && x !== null) || typeof x === 'function'; + } + const rethrowAssertionErrorRejection = noop; + + const originalPromise = Promise; + const originalPromiseThen = Promise.prototype.then; + const originalPromiseResolve = Promise.resolve.bind(originalPromise); + const originalPromiseReject = Promise.reject.bind(originalPromise); + function newPromise(executor) { + return new originalPromise(executor); + } + function promiseResolvedWith(value) { + return originalPromiseResolve(value); + } + function promiseRejectedWith(reason) { + return originalPromiseReject(reason); + } + function PerformPromiseThen(promise, onFulfilled, onRejected) { + // There doesn't appear to be any way to correctly emulate the behaviour from JavaScript, so this is just an + // approximation. + return originalPromiseThen.call(promise, onFulfilled, onRejected); + } + function uponPromise(promise, onFulfilled, onRejected) { + PerformPromiseThen(PerformPromiseThen(promise, onFulfilled, onRejected), undefined, rethrowAssertionErrorRejection); + } + function uponFulfillment(promise, onFulfilled) { + uponPromise(promise, onFulfilled); + } + function uponRejection(promise, onRejected) { + uponPromise(promise, undefined, onRejected); + } + function transformPromiseWith(promise, fulfillmentHandler, rejectionHandler) { + return PerformPromiseThen(promise, fulfillmentHandler, rejectionHandler); + } + function setPromiseIsHandledToTrue(promise) { + PerformPromiseThen(promise, undefined, rethrowAssertionErrorRejection); + } + const queueMicrotask = (() => { + const globalQueueMicrotask = globals && globals.queueMicrotask; + if (typeof globalQueueMicrotask === 'function') { + return globalQueueMicrotask; + } + const resolvedPromise = promiseResolvedWith(undefined); + return (fn) => PerformPromiseThen(resolvedPromise, fn); + })(); + function reflectCall(F, V, args) { + if (typeof F !== 'function') { + throw new TypeError('Argument is not a function'); + } + return Function.prototype.apply.call(F, V, args); + } + function promiseCall(F, V, args) { + try { + return promiseResolvedWith(reflectCall(F, V, args)); + } + catch (value) { + return promiseRejectedWith(value); + } + } + + // Original from Chromium + // https://chromium.googlesource.com/chromium/src/+/0aee4434a4dba42a42abaea9bfbc0cd196a63bc1/third_party/blink/renderer/core/streams/SimpleQueue.js + const QUEUE_MAX_ARRAY_SIZE = 16384; + /** + * Simple queue structure. + * + * Avoids scalability issues with using a packed array directly by using + * multiple arrays in a linked list and keeping the array size bounded. + */ + class SimpleQueue { + constructor() { + this._cursor = 0; + this._size = 0; + // _front and _back are always defined. + this._front = { + _elements: [], + _next: undefined + }; + this._back = this._front; + // The cursor is used to avoid calling Array.shift(). + // It contains the index of the front element of the array inside the + // front-most node. It is always in the range [0, QUEUE_MAX_ARRAY_SIZE). + this._cursor = 0; + // When there is only one node, size === elements.length - cursor. + this._size = 0; + } + get length() { + return this._size; + } + // For exception safety, this method is structured in order: + // 1. Read state + // 2. Calculate required state mutations + // 3. Perform state mutations + push(element) { + const oldBack = this._back; + let newBack = oldBack; + if (oldBack._elements.length === QUEUE_MAX_ARRAY_SIZE - 1) { + newBack = { + _elements: [], + _next: undefined + }; + } + // push() is the mutation most likely to throw an exception, so it + // goes first. + oldBack._elements.push(element); + if (newBack !== oldBack) { + this._back = newBack; + oldBack._next = newBack; + } + ++this._size; + } + // Like push(), shift() follows the read -> calculate -> mutate pattern for + // exception safety. + shift() { // must not be called on an empty queue + const oldFront = this._front; + let newFront = oldFront; + const oldCursor = this._cursor; + let newCursor = oldCursor + 1; + const elements = oldFront._elements; + const element = elements[oldCursor]; + if (newCursor === QUEUE_MAX_ARRAY_SIZE) { + newFront = oldFront._next; + newCursor = 0; + } + // No mutations before this point. + --this._size; + this._cursor = newCursor; + if (oldFront !== newFront) { + this._front = newFront; + } + // Permit shifted element to be garbage collected. + elements[oldCursor] = undefined; + return element; + } + // The tricky thing about forEach() is that it can be called + // re-entrantly. The queue may be mutated inside the callback. It is easy to + // see that push() within the callback has no negative effects since the end + // of the queue is checked for on every iteration. If shift() is called + // repeatedly within the callback then the next iteration may return an + // element that has been removed. In this case the callback will be called + // with undefined values until we either "catch up" with elements that still + // exist or reach the back of the queue. + forEach(callback) { + let i = this._cursor; + let node = this._front; + let elements = node._elements; + while (i !== elements.length || node._next !== undefined) { + if (i === elements.length) { + node = node._next; + elements = node._elements; + i = 0; + if (elements.length === 0) { + break; + } + } + callback(elements[i]); + ++i; + } + } + // Return the element that would be returned if shift() was called now, + // without modifying the queue. + peek() { // must not be called on an empty queue + const front = this._front; + const cursor = this._cursor; + return front._elements[cursor]; + } + } + + function ReadableStreamReaderGenericInitialize(reader, stream) { + reader._ownerReadableStream = stream; + stream._reader = reader; + if (stream._state === 'readable') { + defaultReaderClosedPromiseInitialize(reader); + } + else if (stream._state === 'closed') { + defaultReaderClosedPromiseInitializeAsResolved(reader); + } + else { + defaultReaderClosedPromiseInitializeAsRejected(reader, stream._storedError); + } + } + // A client of ReadableStreamDefaultReader and ReadableStreamBYOBReader may use these functions directly to bypass state + // check. + function ReadableStreamReaderGenericCancel(reader, reason) { + const stream = reader._ownerReadableStream; + return ReadableStreamCancel(stream, reason); + } + function ReadableStreamReaderGenericRelease(reader) { + if (reader._ownerReadableStream._state === 'readable') { + defaultReaderClosedPromiseReject(reader, new TypeError(`Reader was released and can no longer be used to monitor the stream's closedness`)); + } + else { + defaultReaderClosedPromiseResetToRejected(reader, new TypeError(`Reader was released and can no longer be used to monitor the stream's closedness`)); + } + reader._ownerReadableStream._reader = undefined; + reader._ownerReadableStream = undefined; + } + // Helper functions for the readers. + function readerLockException(name) { + return new TypeError('Cannot ' + name + ' a stream using a released reader'); + } + // Helper functions for the ReadableStreamDefaultReader. + function defaultReaderClosedPromiseInitialize(reader) { + reader._closedPromise = newPromise((resolve, reject) => { + reader._closedPromise_resolve = resolve; + reader._closedPromise_reject = reject; + }); + } + function defaultReaderClosedPromiseInitializeAsRejected(reader, reason) { + defaultReaderClosedPromiseInitialize(reader); + defaultReaderClosedPromiseReject(reader, reason); + } + function defaultReaderClosedPromiseInitializeAsResolved(reader) { + defaultReaderClosedPromiseInitialize(reader); + defaultReaderClosedPromiseResolve(reader); + } + function defaultReaderClosedPromiseReject(reader, reason) { + if (reader._closedPromise_reject === undefined) { + return; + } + setPromiseIsHandledToTrue(reader._closedPromise); + reader._closedPromise_reject(reason); + reader._closedPromise_resolve = undefined; + reader._closedPromise_reject = undefined; + } + function defaultReaderClosedPromiseResetToRejected(reader, reason) { + defaultReaderClosedPromiseInitializeAsRejected(reader, reason); + } + function defaultReaderClosedPromiseResolve(reader) { + if (reader._closedPromise_resolve === undefined) { + return; + } + reader._closedPromise_resolve(undefined); + reader._closedPromise_resolve = undefined; + reader._closedPromise_reject = undefined; + } + + const AbortSteps = SymbolPolyfill('[[AbortSteps]]'); + const ErrorSteps = SymbolPolyfill('[[ErrorSteps]]'); + const CancelSteps = SymbolPolyfill('[[CancelSteps]]'); + const PullSteps = SymbolPolyfill('[[PullSteps]]'); + + /// + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isFinite#Polyfill + const NumberIsFinite = Number.isFinite || function (x) { + return typeof x === 'number' && isFinite(x); + }; + + /// + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc#Polyfill + const MathTrunc = Math.trunc || function (v) { + return v < 0 ? Math.ceil(v) : Math.floor(v); + }; + + // https://heycam.github.io/webidl/#idl-dictionaries + function isDictionary(x) { + return typeof x === 'object' || typeof x === 'function'; + } + function assertDictionary(obj, context) { + if (obj !== undefined && !isDictionary(obj)) { + throw new TypeError(`${context} is not an object.`); + } + } + // https://heycam.github.io/webidl/#idl-callback-functions + function assertFunction(x, context) { + if (typeof x !== 'function') { + throw new TypeError(`${context} is not a function.`); + } + } + // https://heycam.github.io/webidl/#idl-object + function isObject(x) { + return (typeof x === 'object' && x !== null) || typeof x === 'function'; + } + function assertObject(x, context) { + if (!isObject(x)) { + throw new TypeError(`${context} is not an object.`); + } + } + function assertRequiredArgument(x, position, context) { + if (x === undefined) { + throw new TypeError(`Parameter ${position} is required in '${context}'.`); + } + } + function assertRequiredField(x, field, context) { + if (x === undefined) { + throw new TypeError(`${field} is required in '${context}'.`); + } + } + // https://heycam.github.io/webidl/#idl-unrestricted-double + function convertUnrestrictedDouble(value) { + return Number(value); + } + function censorNegativeZero(x) { + return x === 0 ? 0 : x; + } + function integerPart(x) { + return censorNegativeZero(MathTrunc(x)); + } + // https://heycam.github.io/webidl/#idl-unsigned-long-long + function convertUnsignedLongLongWithEnforceRange(value, context) { + const lowerBound = 0; + const upperBound = Number.MAX_SAFE_INTEGER; + let x = Number(value); + x = censorNegativeZero(x); + if (!NumberIsFinite(x)) { + throw new TypeError(`${context} is not a finite number`); + } + x = integerPart(x); + if (x < lowerBound || x > upperBound) { + throw new TypeError(`${context} is outside the accepted range of ${lowerBound} to ${upperBound}, inclusive`); + } + if (!NumberIsFinite(x) || x === 0) { + return 0; + } + // TODO Use BigInt if supported? + // let xBigInt = BigInt(integerPart(x)); + // xBigInt = BigInt.asUintN(64, xBigInt); + // return Number(xBigInt); + return x; + } + + function assertReadableStream(x, context) { + if (!IsReadableStream(x)) { + throw new TypeError(`${context} is not a ReadableStream.`); + } + } + + // Abstract operations for the ReadableStream. + function AcquireReadableStreamDefaultReader(stream) { + return new ReadableStreamDefaultReader(stream); + } + // ReadableStream API exposed for controllers. + function ReadableStreamAddReadRequest(stream, readRequest) { + stream._reader._readRequests.push(readRequest); + } + function ReadableStreamFulfillReadRequest(stream, chunk, done) { + const reader = stream._reader; + const readRequest = reader._readRequests.shift(); + if (done) { + readRequest._closeSteps(); + } + else { + readRequest._chunkSteps(chunk); + } + } + function ReadableStreamGetNumReadRequests(stream) { + return stream._reader._readRequests.length; + } + function ReadableStreamHasDefaultReader(stream) { + const reader = stream._reader; + if (reader === undefined) { + return false; + } + if (!IsReadableStreamDefaultReader(reader)) { + return false; + } + return true; + } + /** + * A default reader vended by a {@link ReadableStream}. + * + * @public + */ + class ReadableStreamDefaultReader { + constructor(stream) { + assertRequiredArgument(stream, 1, 'ReadableStreamDefaultReader'); + assertReadableStream(stream, 'First parameter'); + if (IsReadableStreamLocked(stream)) { + throw new TypeError('This stream has already been locked for exclusive reading by another reader'); + } + ReadableStreamReaderGenericInitialize(this, stream); + this._readRequests = new SimpleQueue(); + } + /** + * Returns a promise that will be fulfilled when the stream becomes closed, + * or rejected if the stream ever errors or the reader's lock is released before the stream finishes closing. + */ + get closed() { + if (!IsReadableStreamDefaultReader(this)) { + return promiseRejectedWith(defaultReaderBrandCheckException('closed')); + } + return this._closedPromise; + } + /** + * If the reader is active, behaves the same as {@link ReadableStream.cancel | stream.cancel(reason)}. + */ + cancel(reason = undefined) { + if (!IsReadableStreamDefaultReader(this)) { + return promiseRejectedWith(defaultReaderBrandCheckException('cancel')); + } + if (this._ownerReadableStream === undefined) { + return promiseRejectedWith(readerLockException('cancel')); + } + return ReadableStreamReaderGenericCancel(this, reason); + } + /** + * Returns a promise that allows access to the next chunk from the stream's internal queue, if available. + * + * If reading a chunk causes the queue to become empty, more data will be pulled from the underlying source. + */ + read() { + if (!IsReadableStreamDefaultReader(this)) { + return promiseRejectedWith(defaultReaderBrandCheckException('read')); + } + if (this._ownerReadableStream === undefined) { + return promiseRejectedWith(readerLockException('read from')); + } + let resolvePromise; + let rejectPromise; + const promise = newPromise((resolve, reject) => { + resolvePromise = resolve; + rejectPromise = reject; + }); + const readRequest = { + _chunkSteps: chunk => resolvePromise({ value: chunk, done: false }), + _closeSteps: () => resolvePromise({ value: undefined, done: true }), + _errorSteps: e => rejectPromise(e) + }; + ReadableStreamDefaultReaderRead(this, readRequest); + return promise; + } + /** + * Releases the reader's lock on the corresponding stream. After the lock is released, the reader is no longer active. + * If the associated stream is errored when the lock is released, the reader will appear errored in the same way + * from now on; otherwise, the reader will appear closed. + * + * A reader's lock cannot be released while it still has a pending read request, i.e., if a promise returned by + * the reader's {@link ReadableStreamDefaultReader.read | read()} method has not yet been settled. Attempting to + * do so will throw a `TypeError` and leave the reader locked to the stream. + */ + releaseLock() { + if (!IsReadableStreamDefaultReader(this)) { + throw defaultReaderBrandCheckException('releaseLock'); + } + if (this._ownerReadableStream === undefined) { + return; + } + if (this._readRequests.length > 0) { + throw new TypeError('Tried to release a reader lock when that reader has pending read() calls un-settled'); + } + ReadableStreamReaderGenericRelease(this); + } + } + Object.defineProperties(ReadableStreamDefaultReader.prototype, { + cancel: { enumerable: true }, + read: { enumerable: true }, + releaseLock: { enumerable: true }, + closed: { enumerable: true } + }); + if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(ReadableStreamDefaultReader.prototype, SymbolPolyfill.toStringTag, { + value: 'ReadableStreamDefaultReader', + configurable: true + }); + } + // Abstract operations for the readers. + function IsReadableStreamDefaultReader(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_readRequests')) { + return false; + } + return true; + } + function ReadableStreamDefaultReaderRead(reader, readRequest) { + const stream = reader._ownerReadableStream; + stream._disturbed = true; + if (stream._state === 'closed') { + readRequest._closeSteps(); + } + else if (stream._state === 'errored') { + readRequest._errorSteps(stream._storedError); + } + else { + stream._readableStreamController[PullSteps](readRequest); + } + } + // Helper functions for the ReadableStreamDefaultReader. + function defaultReaderBrandCheckException(name) { + return new TypeError(`ReadableStreamDefaultReader.prototype.${name} can only be used on a ReadableStreamDefaultReader`); + } + + /// + let AsyncIteratorPrototype; + if (typeof SymbolPolyfill.asyncIterator === 'symbol') { + // We're running inside a ES2018+ environment, but we're compiling to an older syntax. + // We cannot access %AsyncIteratorPrototype% without non-ES2018 syntax, but we can re-create it. + AsyncIteratorPrototype = { + // 25.1.3.1 %AsyncIteratorPrototype% [ @@asyncIterator ] ( ) + // https://tc39.github.io/ecma262/#sec-asynciteratorprototype-asynciterator + [SymbolPolyfill.asyncIterator]() { + return this; + } + }; + Object.defineProperty(AsyncIteratorPrototype, SymbolPolyfill.asyncIterator, { enumerable: false }); + } + + /// + class ReadableStreamAsyncIteratorImpl { + constructor(reader, preventCancel) { + this._ongoingPromise = undefined; + this._isFinished = false; + this._reader = reader; + this._preventCancel = preventCancel; + } + next() { + const nextSteps = () => this._nextSteps(); + this._ongoingPromise = this._ongoingPromise ? + transformPromiseWith(this._ongoingPromise, nextSteps, nextSteps) : + nextSteps(); + return this._ongoingPromise; + } + return(value) { + const returnSteps = () => this._returnSteps(value); + return this._ongoingPromise ? + transformPromiseWith(this._ongoingPromise, returnSteps, returnSteps) : + returnSteps(); + } + _nextSteps() { + if (this._isFinished) { + return Promise.resolve({ value: undefined, done: true }); + } + const reader = this._reader; + if (reader._ownerReadableStream === undefined) { + return promiseRejectedWith(readerLockException('iterate')); + } + let resolvePromise; + let rejectPromise; + const promise = newPromise((resolve, reject) => { + resolvePromise = resolve; + rejectPromise = reject; + }); + const readRequest = { + _chunkSteps: chunk => { + this._ongoingPromise = undefined; + // This needs to be delayed by one microtask, otherwise we stop pulling too early which breaks a test. + // FIXME Is this a bug in the specification, or in the test? + queueMicrotask(() => resolvePromise({ value: chunk, done: false })); + }, + _closeSteps: () => { + this._ongoingPromise = undefined; + this._isFinished = true; + ReadableStreamReaderGenericRelease(reader); + resolvePromise({ value: undefined, done: true }); + }, + _errorSteps: reason => { + this._ongoingPromise = undefined; + this._isFinished = true; + ReadableStreamReaderGenericRelease(reader); + rejectPromise(reason); + } + }; + ReadableStreamDefaultReaderRead(reader, readRequest); + return promise; + } + _returnSteps(value) { + if (this._isFinished) { + return Promise.resolve({ value, done: true }); + } + this._isFinished = true; + const reader = this._reader; + if (reader._ownerReadableStream === undefined) { + return promiseRejectedWith(readerLockException('finish iterating')); + } + if (!this._preventCancel) { + const result = ReadableStreamReaderGenericCancel(reader, value); + ReadableStreamReaderGenericRelease(reader); + return transformPromiseWith(result, () => ({ value, done: true })); + } + ReadableStreamReaderGenericRelease(reader); + return promiseResolvedWith({ value, done: true }); + } + } + const ReadableStreamAsyncIteratorPrototype = { + next() { + if (!IsReadableStreamAsyncIterator(this)) { + return promiseRejectedWith(streamAsyncIteratorBrandCheckException('next')); + } + return this._asyncIteratorImpl.next(); + }, + return(value) { + if (!IsReadableStreamAsyncIterator(this)) { + return promiseRejectedWith(streamAsyncIteratorBrandCheckException('return')); + } + return this._asyncIteratorImpl.return(value); + } + }; + if (AsyncIteratorPrototype !== undefined) { + Object.setPrototypeOf(ReadableStreamAsyncIteratorPrototype, AsyncIteratorPrototype); + } + // Abstract operations for the ReadableStream. + function AcquireReadableStreamAsyncIterator(stream, preventCancel) { + const reader = AcquireReadableStreamDefaultReader(stream); + const impl = new ReadableStreamAsyncIteratorImpl(reader, preventCancel); + const iterator = Object.create(ReadableStreamAsyncIteratorPrototype); + iterator._asyncIteratorImpl = impl; + return iterator; + } + function IsReadableStreamAsyncIterator(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_asyncIteratorImpl')) { + return false; + } + return true; + } + // Helper functions for the ReadableStream. + function streamAsyncIteratorBrandCheckException(name) { + return new TypeError(`ReadableStreamAsyncIterator.${name} can only be used on a ReadableSteamAsyncIterator`); + } + + /// + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN#Polyfill + const NumberIsNaN = Number.isNaN || function (x) { + // eslint-disable-next-line no-self-compare + return x !== x; + }; + + function IsFiniteNonNegativeNumber(v) { + if (!IsNonNegativeNumber(v)) { + return false; + } + if (v === Infinity) { + return false; + } + return true; + } + function IsNonNegativeNumber(v) { + if (typeof v !== 'number') { + return false; + } + if (NumberIsNaN(v)) { + return false; + } + if (v < 0) { + return false; + } + return true; + } + + function DequeueValue(container) { + const pair = container._queue.shift(); + container._queueTotalSize -= pair.size; + if (container._queueTotalSize < 0) { + container._queueTotalSize = 0; + } + return pair.value; + } + function EnqueueValueWithSize(container, value, size) { + size = Number(size); + if (!IsFiniteNonNegativeNumber(size)) { + throw new RangeError('Size must be a finite, non-NaN, non-negative number.'); + } + container._queue.push({ value, size }); + container._queueTotalSize += size; + } + function PeekQueueValue(container) { + const pair = container._queue.peek(); + return pair.value; + } + function ResetQueue(container) { + container._queue = new SimpleQueue(); + container._queueTotalSize = 0; + } + + function CreateArrayFromList(elements) { + // We use arrays to represent lists, so this is basically a no-op. + // Do a slice though just in case we happen to depend on the unique-ness. + return elements.slice(); + } + function CopyDataBlockBytes(dest, destOffset, src, srcOffset, n) { + new Uint8Array(dest).set(new Uint8Array(src, srcOffset, n), destOffset); + } + // Not implemented correctly + function TransferArrayBuffer(O) { + return O; + } + // Not implemented correctly + function IsDetachedBuffer(O) { + return false; + } + + /** + * A pull-into request in a {@link ReadableByteStreamController}. + * + * @public + */ + class ReadableStreamBYOBRequest { + constructor() { + throw new TypeError('Illegal constructor'); + } + /** + * Returns the view for writing in to, or `null` if the BYOB request has already been responded to. + */ + get view() { + if (!IsReadableStreamBYOBRequest(this)) { + throw byobRequestBrandCheckException('view'); + } + return this._view; + } + respond(bytesWritten) { + if (!IsReadableStreamBYOBRequest(this)) { + throw byobRequestBrandCheckException('respond'); + } + assertRequiredArgument(bytesWritten, 1, 'respond'); + bytesWritten = convertUnsignedLongLongWithEnforceRange(bytesWritten, 'First parameter'); + if (this._associatedReadableByteStreamController === undefined) { + throw new TypeError('This BYOB request has been invalidated'); + } + if (IsDetachedBuffer(this._view.buffer)) ; + ReadableByteStreamControllerRespond(this._associatedReadableByteStreamController, bytesWritten); + } + respondWithNewView(view) { + if (!IsReadableStreamBYOBRequest(this)) { + throw byobRequestBrandCheckException('respondWithNewView'); + } + assertRequiredArgument(view, 1, 'respondWithNewView'); + if (!ArrayBuffer.isView(view)) { + throw new TypeError('You can only respond with array buffer views'); + } + if (view.byteLength === 0) { + throw new TypeError('chunk must have non-zero byteLength'); + } + if (view.buffer.byteLength === 0) { + throw new TypeError(`chunk's buffer must have non-zero byteLength`); + } + if (this._associatedReadableByteStreamController === undefined) { + throw new TypeError('This BYOB request has been invalidated'); + } + ReadableByteStreamControllerRespondWithNewView(this._associatedReadableByteStreamController, view); + } + } + Object.defineProperties(ReadableStreamBYOBRequest.prototype, { + respond: { enumerable: true }, + respondWithNewView: { enumerable: true }, + view: { enumerable: true } + }); + if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(ReadableStreamBYOBRequest.prototype, SymbolPolyfill.toStringTag, { + value: 'ReadableStreamBYOBRequest', + configurable: true + }); + } + /** + * Allows control of a {@link ReadableStream | readable byte stream}'s state and internal queue. + * + * @public + */ + class ReadableByteStreamController { + constructor() { + throw new TypeError('Illegal constructor'); + } + /** + * Returns the current BYOB pull request, or `null` if there isn't one. + */ + get byobRequest() { + if (!IsReadableByteStreamController(this)) { + throw byteStreamControllerBrandCheckException('byobRequest'); + } + if (this._byobRequest === null && this._pendingPullIntos.length > 0) { + const firstDescriptor = this._pendingPullIntos.peek(); + const view = new Uint8Array(firstDescriptor.buffer, firstDescriptor.byteOffset + firstDescriptor.bytesFilled, firstDescriptor.byteLength - firstDescriptor.bytesFilled); + const byobRequest = Object.create(ReadableStreamBYOBRequest.prototype); + SetUpReadableStreamBYOBRequest(byobRequest, this, view); + this._byobRequest = byobRequest; + } + return this._byobRequest; + } + /** + * Returns the desired size to fill the controlled stream's internal queue. It can be negative, if the queue is + * over-full. An underlying byte source ought to use this information to determine when and how to apply backpressure. + */ + get desiredSize() { + if (!IsReadableByteStreamController(this)) { + throw byteStreamControllerBrandCheckException('desiredSize'); + } + return ReadableByteStreamControllerGetDesiredSize(this); + } + /** + * Closes the controlled readable stream. Consumers will still be able to read any previously-enqueued chunks from + * the stream, but once those are read, the stream will become closed. + */ + close() { + if (!IsReadableByteStreamController(this)) { + throw byteStreamControllerBrandCheckException('close'); + } + if (this._closeRequested) { + throw new TypeError('The stream has already been closed; do not close it again!'); + } + const state = this._controlledReadableByteStream._state; + if (state !== 'readable') { + throw new TypeError(`The stream (in ${state} state) is not in the readable state and cannot be closed`); + } + ReadableByteStreamControllerClose(this); + } + enqueue(chunk) { + if (!IsReadableByteStreamController(this)) { + throw byteStreamControllerBrandCheckException('enqueue'); + } + assertRequiredArgument(chunk, 1, 'enqueue'); + if (!ArrayBuffer.isView(chunk)) { + throw new TypeError('chunk must be an array buffer view'); + } + if (chunk.byteLength === 0) { + throw new TypeError('chunk must have non-zero byteLength'); + } + if (chunk.buffer.byteLength === 0) { + throw new TypeError(`chunk's buffer must have non-zero byteLength`); + } + if (this._closeRequested) { + throw new TypeError('stream is closed or draining'); + } + const state = this._controlledReadableByteStream._state; + if (state !== 'readable') { + throw new TypeError(`The stream (in ${state} state) is not in the readable state and cannot be enqueued to`); + } + ReadableByteStreamControllerEnqueue(this, chunk); + } + /** + * Errors the controlled readable stream, making all future interactions with it fail with the given error `e`. + */ + error(e = undefined) { + if (!IsReadableByteStreamController(this)) { + throw byteStreamControllerBrandCheckException('error'); + } + ReadableByteStreamControllerError(this, e); + } + /** @internal */ + [CancelSteps](reason) { + if (this._pendingPullIntos.length > 0) { + const firstDescriptor = this._pendingPullIntos.peek(); + firstDescriptor.bytesFilled = 0; + } + ResetQueue(this); + const result = this._cancelAlgorithm(reason); + ReadableByteStreamControllerClearAlgorithms(this); + return result; + } + /** @internal */ + [PullSteps](readRequest) { + const stream = this._controlledReadableByteStream; + if (this._queueTotalSize > 0) { + const entry = this._queue.shift(); + this._queueTotalSize -= entry.byteLength; + ReadableByteStreamControllerHandleQueueDrain(this); + const view = new Uint8Array(entry.buffer, entry.byteOffset, entry.byteLength); + readRequest._chunkSteps(view); + return; + } + const autoAllocateChunkSize = this._autoAllocateChunkSize; + if (autoAllocateChunkSize !== undefined) { + let buffer; + try { + buffer = new ArrayBuffer(autoAllocateChunkSize); + } + catch (bufferE) { + readRequest._errorSteps(bufferE); + return; + } + const pullIntoDescriptor = { + buffer, + byteOffset: 0, + byteLength: autoAllocateChunkSize, + bytesFilled: 0, + elementSize: 1, + viewConstructor: Uint8Array, + readerType: 'default' + }; + this._pendingPullIntos.push(pullIntoDescriptor); + } + ReadableStreamAddReadRequest(stream, readRequest); + ReadableByteStreamControllerCallPullIfNeeded(this); + } + } + Object.defineProperties(ReadableByteStreamController.prototype, { + close: { enumerable: true }, + enqueue: { enumerable: true }, + error: { enumerable: true }, + byobRequest: { enumerable: true }, + desiredSize: { enumerable: true } + }); + if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(ReadableByteStreamController.prototype, SymbolPolyfill.toStringTag, { + value: 'ReadableByteStreamController', + configurable: true + }); + } + // Abstract operations for the ReadableByteStreamController. + function IsReadableByteStreamController(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_controlledReadableByteStream')) { + return false; + } + return true; + } + function IsReadableStreamBYOBRequest(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_associatedReadableByteStreamController')) { + return false; + } + return true; + } + function ReadableByteStreamControllerCallPullIfNeeded(controller) { + const shouldPull = ReadableByteStreamControllerShouldCallPull(controller); + if (!shouldPull) { + return; + } + if (controller._pulling) { + controller._pullAgain = true; + return; + } + controller._pulling = true; + // TODO: Test controller argument + const pullPromise = controller._pullAlgorithm(); + uponPromise(pullPromise, () => { + controller._pulling = false; + if (controller._pullAgain) { + controller._pullAgain = false; + ReadableByteStreamControllerCallPullIfNeeded(controller); + } + }, e => { + ReadableByteStreamControllerError(controller, e); + }); + } + function ReadableByteStreamControllerClearPendingPullIntos(controller) { + ReadableByteStreamControllerInvalidateBYOBRequest(controller); + controller._pendingPullIntos = new SimpleQueue(); + } + function ReadableByteStreamControllerCommitPullIntoDescriptor(stream, pullIntoDescriptor) { + let done = false; + if (stream._state === 'closed') { + done = true; + } + const filledView = ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor); + if (pullIntoDescriptor.readerType === 'default') { + ReadableStreamFulfillReadRequest(stream, filledView, done); + } + else { + ReadableStreamFulfillReadIntoRequest(stream, filledView, done); + } + } + function ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor) { + const bytesFilled = pullIntoDescriptor.bytesFilled; + const elementSize = pullIntoDescriptor.elementSize; + return new pullIntoDescriptor.viewConstructor(pullIntoDescriptor.buffer, pullIntoDescriptor.byteOffset, bytesFilled / elementSize); + } + function ReadableByteStreamControllerEnqueueChunkToQueue(controller, buffer, byteOffset, byteLength) { + controller._queue.push({ buffer, byteOffset, byteLength }); + controller._queueTotalSize += byteLength; + } + function ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor) { + const elementSize = pullIntoDescriptor.elementSize; + const currentAlignedBytes = pullIntoDescriptor.bytesFilled - pullIntoDescriptor.bytesFilled % elementSize; + const maxBytesToCopy = Math.min(controller._queueTotalSize, pullIntoDescriptor.byteLength - pullIntoDescriptor.bytesFilled); + const maxBytesFilled = pullIntoDescriptor.bytesFilled + maxBytesToCopy; + const maxAlignedBytes = maxBytesFilled - maxBytesFilled % elementSize; + let totalBytesToCopyRemaining = maxBytesToCopy; + let ready = false; + if (maxAlignedBytes > currentAlignedBytes) { + totalBytesToCopyRemaining = maxAlignedBytes - pullIntoDescriptor.bytesFilled; + ready = true; + } + const queue = controller._queue; + while (totalBytesToCopyRemaining > 0) { + const headOfQueue = queue.peek(); + const bytesToCopy = Math.min(totalBytesToCopyRemaining, headOfQueue.byteLength); + const destStart = pullIntoDescriptor.byteOffset + pullIntoDescriptor.bytesFilled; + CopyDataBlockBytes(pullIntoDescriptor.buffer, destStart, headOfQueue.buffer, headOfQueue.byteOffset, bytesToCopy); + if (headOfQueue.byteLength === bytesToCopy) { + queue.shift(); + } + else { + headOfQueue.byteOffset += bytesToCopy; + headOfQueue.byteLength -= bytesToCopy; + } + controller._queueTotalSize -= bytesToCopy; + ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, bytesToCopy, pullIntoDescriptor); + totalBytesToCopyRemaining -= bytesToCopy; + } + return ready; + } + function ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, size, pullIntoDescriptor) { + ReadableByteStreamControllerInvalidateBYOBRequest(controller); + pullIntoDescriptor.bytesFilled += size; + } + function ReadableByteStreamControllerHandleQueueDrain(controller) { + if (controller._queueTotalSize === 0 && controller._closeRequested) { + ReadableByteStreamControllerClearAlgorithms(controller); + ReadableStreamClose(controller._controlledReadableByteStream); + } + else { + ReadableByteStreamControllerCallPullIfNeeded(controller); + } + } + function ReadableByteStreamControllerInvalidateBYOBRequest(controller) { + if (controller._byobRequest === null) { + return; + } + controller._byobRequest._associatedReadableByteStreamController = undefined; + controller._byobRequest._view = null; + controller._byobRequest = null; + } + function ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller) { + while (controller._pendingPullIntos.length > 0) { + if (controller._queueTotalSize === 0) { + return; + } + const pullIntoDescriptor = controller._pendingPullIntos.peek(); + if (ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor)) { + ReadableByteStreamControllerShiftPendingPullInto(controller); + ReadableByteStreamControllerCommitPullIntoDescriptor(controller._controlledReadableByteStream, pullIntoDescriptor); + } + } + } + function ReadableByteStreamControllerPullInto(controller, view, readIntoRequest) { + const stream = controller._controlledReadableByteStream; + let elementSize = 1; + if (view.constructor !== DataView) { + elementSize = view.constructor.BYTES_PER_ELEMENT; + } + const ctor = view.constructor; + const buffer = TransferArrayBuffer(view.buffer); + const pullIntoDescriptor = { + buffer, + byteOffset: view.byteOffset, + byteLength: view.byteLength, + bytesFilled: 0, + elementSize, + viewConstructor: ctor, + readerType: 'byob' + }; + if (controller._pendingPullIntos.length > 0) { + controller._pendingPullIntos.push(pullIntoDescriptor); + // No ReadableByteStreamControllerCallPullIfNeeded() call since: + // - No change happens on desiredSize + // - The source has already been notified of that there's at least 1 pending read(view) + ReadableStreamAddReadIntoRequest(stream, readIntoRequest); + return; + } + if (stream._state === 'closed') { + const emptyView = new ctor(pullIntoDescriptor.buffer, pullIntoDescriptor.byteOffset, 0); + readIntoRequest._closeSteps(emptyView); + return; + } + if (controller._queueTotalSize > 0) { + if (ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor)) { + const filledView = ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor); + ReadableByteStreamControllerHandleQueueDrain(controller); + readIntoRequest._chunkSteps(filledView); + return; + } + if (controller._closeRequested) { + const e = new TypeError('Insufficient bytes to fill elements in the given buffer'); + ReadableByteStreamControllerError(controller, e); + readIntoRequest._errorSteps(e); + return; + } + } + controller._pendingPullIntos.push(pullIntoDescriptor); + ReadableStreamAddReadIntoRequest(stream, readIntoRequest); + ReadableByteStreamControllerCallPullIfNeeded(controller); + } + function ReadableByteStreamControllerRespondInClosedState(controller, firstDescriptor) { + firstDescriptor.buffer = TransferArrayBuffer(firstDescriptor.buffer); + const stream = controller._controlledReadableByteStream; + if (ReadableStreamHasBYOBReader(stream)) { + while (ReadableStreamGetNumReadIntoRequests(stream) > 0) { + const pullIntoDescriptor = ReadableByteStreamControllerShiftPendingPullInto(controller); + ReadableByteStreamControllerCommitPullIntoDescriptor(stream, pullIntoDescriptor); + } + } + } + function ReadableByteStreamControllerRespondInReadableState(controller, bytesWritten, pullIntoDescriptor) { + if (pullIntoDescriptor.bytesFilled + bytesWritten > pullIntoDescriptor.byteLength) { + throw new RangeError('bytesWritten out of range'); + } + ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, bytesWritten, pullIntoDescriptor); + if (pullIntoDescriptor.bytesFilled < pullIntoDescriptor.elementSize) { + // TODO: Figure out whether we should detach the buffer or not here. + return; + } + ReadableByteStreamControllerShiftPendingPullInto(controller); + const remainderSize = pullIntoDescriptor.bytesFilled % pullIntoDescriptor.elementSize; + if (remainderSize > 0) { + const end = pullIntoDescriptor.byteOffset + pullIntoDescriptor.bytesFilled; + const remainder = pullIntoDescriptor.buffer.slice(end - remainderSize, end); + ReadableByteStreamControllerEnqueueChunkToQueue(controller, remainder, 0, remainder.byteLength); + } + pullIntoDescriptor.buffer = TransferArrayBuffer(pullIntoDescriptor.buffer); + pullIntoDescriptor.bytesFilled -= remainderSize; + ReadableByteStreamControllerCommitPullIntoDescriptor(controller._controlledReadableByteStream, pullIntoDescriptor); + ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller); + } + function ReadableByteStreamControllerRespondInternal(controller, bytesWritten) { + const firstDescriptor = controller._pendingPullIntos.peek(); + const state = controller._controlledReadableByteStream._state; + if (state === 'closed') { + if (bytesWritten !== 0) { + throw new TypeError('bytesWritten must be 0 when calling respond() on a closed stream'); + } + ReadableByteStreamControllerRespondInClosedState(controller, firstDescriptor); + } + else { + ReadableByteStreamControllerRespondInReadableState(controller, bytesWritten, firstDescriptor); + } + ReadableByteStreamControllerCallPullIfNeeded(controller); + } + function ReadableByteStreamControllerShiftPendingPullInto(controller) { + const descriptor = controller._pendingPullIntos.shift(); + ReadableByteStreamControllerInvalidateBYOBRequest(controller); + return descriptor; + } + function ReadableByteStreamControllerShouldCallPull(controller) { + const stream = controller._controlledReadableByteStream; + if (stream._state !== 'readable') { + return false; + } + if (controller._closeRequested) { + return false; + } + if (!controller._started) { + return false; + } + if (ReadableStreamHasDefaultReader(stream) && ReadableStreamGetNumReadRequests(stream) > 0) { + return true; + } + if (ReadableStreamHasBYOBReader(stream) && ReadableStreamGetNumReadIntoRequests(stream) > 0) { + return true; + } + const desiredSize = ReadableByteStreamControllerGetDesiredSize(controller); + if (desiredSize > 0) { + return true; + } + return false; + } + function ReadableByteStreamControllerClearAlgorithms(controller) { + controller._pullAlgorithm = undefined; + controller._cancelAlgorithm = undefined; + } + // A client of ReadableByteStreamController may use these functions directly to bypass state check. + function ReadableByteStreamControllerClose(controller) { + const stream = controller._controlledReadableByteStream; + if (controller._closeRequested || stream._state !== 'readable') { + return; + } + if (controller._queueTotalSize > 0) { + controller._closeRequested = true; + return; + } + if (controller._pendingPullIntos.length > 0) { + const firstPendingPullInto = controller._pendingPullIntos.peek(); + if (firstPendingPullInto.bytesFilled > 0) { + const e = new TypeError('Insufficient bytes to fill elements in the given buffer'); + ReadableByteStreamControllerError(controller, e); + throw e; + } + } + ReadableByteStreamControllerClearAlgorithms(controller); + ReadableStreamClose(stream); + } + function ReadableByteStreamControllerEnqueue(controller, chunk) { + const stream = controller._controlledReadableByteStream; + if (controller._closeRequested || stream._state !== 'readable') { + return; + } + const buffer = chunk.buffer; + const byteOffset = chunk.byteOffset; + const byteLength = chunk.byteLength; + const transferredBuffer = TransferArrayBuffer(buffer); + if (ReadableStreamHasDefaultReader(stream)) { + if (ReadableStreamGetNumReadRequests(stream) === 0) { + ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength); + } + else { + const transferredView = new Uint8Array(transferredBuffer, byteOffset, byteLength); + ReadableStreamFulfillReadRequest(stream, transferredView, false); + } + } + else if (ReadableStreamHasBYOBReader(stream)) { + // TODO: Ideally in this branch detaching should happen only if the buffer is not consumed fully. + ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength); + ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller); + } + else { + ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength); + } + ReadableByteStreamControllerCallPullIfNeeded(controller); + } + function ReadableByteStreamControllerError(controller, e) { + const stream = controller._controlledReadableByteStream; + if (stream._state !== 'readable') { + return; + } + ReadableByteStreamControllerClearPendingPullIntos(controller); + ResetQueue(controller); + ReadableByteStreamControllerClearAlgorithms(controller); + ReadableStreamError(stream, e); + } + function ReadableByteStreamControllerGetDesiredSize(controller) { + const state = controller._controlledReadableByteStream._state; + if (state === 'errored') { + return null; + } + if (state === 'closed') { + return 0; + } + return controller._strategyHWM - controller._queueTotalSize; + } + function ReadableByteStreamControllerRespond(controller, bytesWritten) { + bytesWritten = Number(bytesWritten); + if (!IsFiniteNonNegativeNumber(bytesWritten)) { + throw new RangeError('bytesWritten must be a finite'); + } + ReadableByteStreamControllerRespondInternal(controller, bytesWritten); + } + function ReadableByteStreamControllerRespondWithNewView(controller, view) { + const firstDescriptor = controller._pendingPullIntos.peek(); + if (firstDescriptor.byteOffset + firstDescriptor.bytesFilled !== view.byteOffset) { + throw new RangeError('The region specified by view does not match byobRequest'); + } + if (firstDescriptor.byteLength !== view.byteLength) { + throw new RangeError('The buffer of view has different capacity than byobRequest'); + } + firstDescriptor.buffer = view.buffer; + ReadableByteStreamControllerRespondInternal(controller, view.byteLength); + } + function SetUpReadableByteStreamController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, autoAllocateChunkSize) { + controller._controlledReadableByteStream = stream; + controller._pullAgain = false; + controller._pulling = false; + controller._byobRequest = null; + // Need to set the slots so that the assert doesn't fire. In the spec the slots already exist implicitly. + controller._queue = controller._queueTotalSize = undefined; + ResetQueue(controller); + controller._closeRequested = false; + controller._started = false; + controller._strategyHWM = highWaterMark; + controller._pullAlgorithm = pullAlgorithm; + controller._cancelAlgorithm = cancelAlgorithm; + controller._autoAllocateChunkSize = autoAllocateChunkSize; + controller._pendingPullIntos = new SimpleQueue(); + stream._readableStreamController = controller; + const startResult = startAlgorithm(); + uponPromise(promiseResolvedWith(startResult), () => { + controller._started = true; + ReadableByteStreamControllerCallPullIfNeeded(controller); + }, r => { + ReadableByteStreamControllerError(controller, r); + }); + } + function SetUpReadableByteStreamControllerFromUnderlyingSource(stream, underlyingByteSource, highWaterMark) { + const controller = Object.create(ReadableByteStreamController.prototype); + let startAlgorithm = () => undefined; + let pullAlgorithm = () => promiseResolvedWith(undefined); + let cancelAlgorithm = () => promiseResolvedWith(undefined); + if (underlyingByteSource.start !== undefined) { + startAlgorithm = () => underlyingByteSource.start(controller); + } + if (underlyingByteSource.pull !== undefined) { + pullAlgorithm = () => underlyingByteSource.pull(controller); + } + if (underlyingByteSource.cancel !== undefined) { + cancelAlgorithm = reason => underlyingByteSource.cancel(reason); + } + const autoAllocateChunkSize = underlyingByteSource.autoAllocateChunkSize; + if (autoAllocateChunkSize === 0) { + throw new TypeError('autoAllocateChunkSize must be greater than 0'); + } + SetUpReadableByteStreamController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, autoAllocateChunkSize); + } + function SetUpReadableStreamBYOBRequest(request, controller, view) { + request._associatedReadableByteStreamController = controller; + request._view = view; + } + // Helper functions for the ReadableStreamBYOBRequest. + function byobRequestBrandCheckException(name) { + return new TypeError(`ReadableStreamBYOBRequest.prototype.${name} can only be used on a ReadableStreamBYOBRequest`); + } + // Helper functions for the ReadableByteStreamController. + function byteStreamControllerBrandCheckException(name) { + return new TypeError(`ReadableByteStreamController.prototype.${name} can only be used on a ReadableByteStreamController`); + } + + // Abstract operations for the ReadableStream. + function AcquireReadableStreamBYOBReader(stream) { + return new ReadableStreamBYOBReader(stream); + } + // ReadableStream API exposed for controllers. + function ReadableStreamAddReadIntoRequest(stream, readIntoRequest) { + stream._reader._readIntoRequests.push(readIntoRequest); + } + function ReadableStreamFulfillReadIntoRequest(stream, chunk, done) { + const reader = stream._reader; + const readIntoRequest = reader._readIntoRequests.shift(); + if (done) { + readIntoRequest._closeSteps(chunk); + } + else { + readIntoRequest._chunkSteps(chunk); + } + } + function ReadableStreamGetNumReadIntoRequests(stream) { + return stream._reader._readIntoRequests.length; + } + function ReadableStreamHasBYOBReader(stream) { + const reader = stream._reader; + if (reader === undefined) { + return false; + } + if (!IsReadableStreamBYOBReader(reader)) { + return false; + } + return true; + } + /** + * A BYOB reader vended by a {@link ReadableStream}. + * + * @public + */ + class ReadableStreamBYOBReader { + constructor(stream) { + assertRequiredArgument(stream, 1, 'ReadableStreamBYOBReader'); + assertReadableStream(stream, 'First parameter'); + if (IsReadableStreamLocked(stream)) { + throw new TypeError('This stream has already been locked for exclusive reading by another reader'); + } + if (!IsReadableByteStreamController(stream._readableStreamController)) { + throw new TypeError('Cannot construct a ReadableStreamBYOBReader for a stream not constructed with a byte ' + + 'source'); + } + ReadableStreamReaderGenericInitialize(this, stream); + this._readIntoRequests = new SimpleQueue(); + } + /** + * Returns a promise that will be fulfilled when the stream becomes closed, or rejected if the stream ever errors or + * the reader's lock is released before the stream finishes closing. + */ + get closed() { + if (!IsReadableStreamBYOBReader(this)) { + return promiseRejectedWith(byobReaderBrandCheckException('closed')); + } + return this._closedPromise; + } + /** + * If the reader is active, behaves the same as {@link ReadableStream.cancel | stream.cancel(reason)}. + */ + cancel(reason = undefined) { + if (!IsReadableStreamBYOBReader(this)) { + return promiseRejectedWith(byobReaderBrandCheckException('cancel')); + } + if (this._ownerReadableStream === undefined) { + return promiseRejectedWith(readerLockException('cancel')); + } + return ReadableStreamReaderGenericCancel(this, reason); + } + /** + * Attempts to reads bytes into view, and returns a promise resolved with the result. + * + * If reading a chunk causes the queue to become empty, more data will be pulled from the underlying source. + */ + read(view) { + if (!IsReadableStreamBYOBReader(this)) { + return promiseRejectedWith(byobReaderBrandCheckException('read')); + } + if (!ArrayBuffer.isView(view)) { + return promiseRejectedWith(new TypeError('view must be an array buffer view')); + } + if (view.byteLength === 0) { + return promiseRejectedWith(new TypeError('view must have non-zero byteLength')); + } + if (view.buffer.byteLength === 0) { + return promiseRejectedWith(new TypeError(`view's buffer must have non-zero byteLength`)); + } + if (this._ownerReadableStream === undefined) { + return promiseRejectedWith(readerLockException('read from')); + } + let resolvePromise; + let rejectPromise; + const promise = newPromise((resolve, reject) => { + resolvePromise = resolve; + rejectPromise = reject; + }); + const readIntoRequest = { + _chunkSteps: chunk => resolvePromise({ value: chunk, done: false }), + _closeSteps: chunk => resolvePromise({ value: chunk, done: true }), + _errorSteps: e => rejectPromise(e) + }; + ReadableStreamBYOBReaderRead(this, view, readIntoRequest); + return promise; + } + /** + * Releases the reader's lock on the corresponding stream. After the lock is released, the reader is no longer active. + * If the associated stream is errored when the lock is released, the reader will appear errored in the same way + * from now on; otherwise, the reader will appear closed. + * + * A reader's lock cannot be released while it still has a pending read request, i.e., if a promise returned by + * the reader's {@link ReadableStreamBYOBReader.read | read()} method has not yet been settled. Attempting to + * do so will throw a `TypeError` and leave the reader locked to the stream. + */ + releaseLock() { + if (!IsReadableStreamBYOBReader(this)) { + throw byobReaderBrandCheckException('releaseLock'); + } + if (this._ownerReadableStream === undefined) { + return; + } + if (this._readIntoRequests.length > 0) { + throw new TypeError('Tried to release a reader lock when that reader has pending read() calls un-settled'); + } + ReadableStreamReaderGenericRelease(this); + } + } + Object.defineProperties(ReadableStreamBYOBReader.prototype, { + cancel: { enumerable: true }, + read: { enumerable: true }, + releaseLock: { enumerable: true }, + closed: { enumerable: true } + }); + if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(ReadableStreamBYOBReader.prototype, SymbolPolyfill.toStringTag, { + value: 'ReadableStreamBYOBReader', + configurable: true + }); + } + // Abstract operations for the readers. + function IsReadableStreamBYOBReader(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_readIntoRequests')) { + return false; + } + return true; + } + function ReadableStreamBYOBReaderRead(reader, view, readIntoRequest) { + const stream = reader._ownerReadableStream; + stream._disturbed = true; + if (stream._state === 'errored') { + readIntoRequest._errorSteps(stream._storedError); + } + else { + ReadableByteStreamControllerPullInto(stream._readableStreamController, view, readIntoRequest); + } + } + // Helper functions for the ReadableStreamBYOBReader. + function byobReaderBrandCheckException(name) { + return new TypeError(`ReadableStreamBYOBReader.prototype.${name} can only be used on a ReadableStreamBYOBReader`); + } + + function ExtractHighWaterMark(strategy, defaultHWM) { + const { highWaterMark } = strategy; + if (highWaterMark === undefined) { + return defaultHWM; + } + if (NumberIsNaN(highWaterMark) || highWaterMark < 0) { + throw new RangeError('Invalid highWaterMark'); + } + return highWaterMark; + } + function ExtractSizeAlgorithm(strategy) { + const { size } = strategy; + if (!size) { + return () => 1; + } + return size; + } + + function convertQueuingStrategy(init, context) { + assertDictionary(init, context); + const highWaterMark = init === null || init === void 0 ? void 0 : init.highWaterMark; + const size = init === null || init === void 0 ? void 0 : init.size; + return { + highWaterMark: highWaterMark === undefined ? undefined : convertUnrestrictedDouble(highWaterMark), + size: size === undefined ? undefined : convertQueuingStrategySize(size, `${context} has member 'size' that`) + }; + } + function convertQueuingStrategySize(fn, context) { + assertFunction(fn, context); + return chunk => convertUnrestrictedDouble(fn(chunk)); + } + + function convertUnderlyingSink(original, context) { + assertDictionary(original, context); + const abort = original === null || original === void 0 ? void 0 : original.abort; + const close = original === null || original === void 0 ? void 0 : original.close; + const start = original === null || original === void 0 ? void 0 : original.start; + const type = original === null || original === void 0 ? void 0 : original.type; + const write = original === null || original === void 0 ? void 0 : original.write; + return { + abort: abort === undefined ? + undefined : + convertUnderlyingSinkAbortCallback(abort, original, `${context} has member 'abort' that`), + close: close === undefined ? + undefined : + convertUnderlyingSinkCloseCallback(close, original, `${context} has member 'close' that`), + start: start === undefined ? + undefined : + convertUnderlyingSinkStartCallback(start, original, `${context} has member 'start' that`), + write: write === undefined ? + undefined : + convertUnderlyingSinkWriteCallback(write, original, `${context} has member 'write' that`), + type + }; + } + function convertUnderlyingSinkAbortCallback(fn, original, context) { + assertFunction(fn, context); + return (reason) => promiseCall(fn, original, [reason]); + } + function convertUnderlyingSinkCloseCallback(fn, original, context) { + assertFunction(fn, context); + return () => promiseCall(fn, original, []); + } + function convertUnderlyingSinkStartCallback(fn, original, context) { + assertFunction(fn, context); + return (controller) => reflectCall(fn, original, [controller]); + } + function convertUnderlyingSinkWriteCallback(fn, original, context) { + assertFunction(fn, context); + return (chunk, controller) => promiseCall(fn, original, [chunk, controller]); + } + + function assertWritableStream(x, context) { + if (!IsWritableStream(x)) { + throw new TypeError(`${context} is not a WritableStream.`); + } + } + + /** + * A writable stream represents a destination for data, into which you can write. + * + * @public + */ + class WritableStream$1 { + constructor(rawUnderlyingSink = {}, rawStrategy = {}) { + if (rawUnderlyingSink === undefined) { + rawUnderlyingSink = null; + } + else { + assertObject(rawUnderlyingSink, 'First parameter'); + } + const strategy = convertQueuingStrategy(rawStrategy, 'Second parameter'); + const underlyingSink = convertUnderlyingSink(rawUnderlyingSink, 'First parameter'); + InitializeWritableStream(this); + const type = underlyingSink.type; + if (type !== undefined) { + throw new RangeError('Invalid type is specified'); + } + const sizeAlgorithm = ExtractSizeAlgorithm(strategy); + const highWaterMark = ExtractHighWaterMark(strategy, 1); + SetUpWritableStreamDefaultControllerFromUnderlyingSink(this, underlyingSink, highWaterMark, sizeAlgorithm); + } + /** + * Returns whether or not the writable stream is locked to a writer. + */ + get locked() { + if (!IsWritableStream(this)) { + throw streamBrandCheckException$2('locked'); + } + return IsWritableStreamLocked(this); + } + /** + * Aborts the stream, signaling that the producer can no longer successfully write to the stream and it is to be + * immediately moved to an errored state, with any queued-up writes discarded. This will also execute any abort + * mechanism of the underlying sink. + * + * The returned promise will fulfill if the stream shuts down successfully, or reject if the underlying sink signaled + * that there was an error doing so. Additionally, it will reject with a `TypeError` (without attempting to cancel + * the stream) if the stream is currently locked. + */ + abort(reason = undefined) { + if (!IsWritableStream(this)) { + return promiseRejectedWith(streamBrandCheckException$2('abort')); + } + if (IsWritableStreamLocked(this)) { + return promiseRejectedWith(new TypeError('Cannot abort a stream that already has a writer')); + } + return WritableStreamAbort(this, reason); + } + /** + * Closes the stream. The underlying sink will finish processing any previously-written chunks, before invoking its + * close behavior. During this time any further attempts to write will fail (without erroring the stream). + * + * The method returns a promise that will fulfill if all remaining chunks are successfully written and the stream + * successfully closes, or rejects if an error is encountered during this process. Additionally, it will reject with + * a `TypeError` (without attempting to cancel the stream) if the stream is currently locked. + */ + close() { + if (!IsWritableStream(this)) { + return promiseRejectedWith(streamBrandCheckException$2('close')); + } + if (IsWritableStreamLocked(this)) { + return promiseRejectedWith(new TypeError('Cannot close a stream that already has a writer')); + } + if (WritableStreamCloseQueuedOrInFlight(this)) { + return promiseRejectedWith(new TypeError('Cannot close an already-closing stream')); + } + return WritableStreamClose(this); + } + /** + * Creates a {@link WritableStreamDefaultWriter | writer} and locks the stream to the new writer. While the stream + * is locked, no other writer can be acquired until this one is released. + * + * This functionality is especially useful for creating abstractions that desire the ability to write to a stream + * without interruption or interleaving. By getting a writer for the stream, you can ensure nobody else can write at + * the same time, which would cause the resulting written data to be unpredictable and probably useless. + */ + getWriter() { + if (!IsWritableStream(this)) { + throw streamBrandCheckException$2('getWriter'); + } + return AcquireWritableStreamDefaultWriter(this); + } + } + Object.defineProperties(WritableStream$1.prototype, { + abort: { enumerable: true }, + close: { enumerable: true }, + getWriter: { enumerable: true }, + locked: { enumerable: true } + }); + if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(WritableStream$1.prototype, SymbolPolyfill.toStringTag, { + value: 'WritableStream', + configurable: true + }); + } + // Abstract operations for the WritableStream. + function AcquireWritableStreamDefaultWriter(stream) { + return new WritableStreamDefaultWriter(stream); + } + // Throws if and only if startAlgorithm throws. + function CreateWritableStream(startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark = 1, sizeAlgorithm = () => 1) { + const stream = Object.create(WritableStream$1.prototype); + InitializeWritableStream(stream); + const controller = Object.create(WritableStreamDefaultController.prototype); + SetUpWritableStreamDefaultController(stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark, sizeAlgorithm); + return stream; + } + function InitializeWritableStream(stream) { + stream._state = 'writable'; + // The error that will be reported by new method calls once the state becomes errored. Only set when [[state]] is + // 'erroring' or 'errored'. May be set to an undefined value. + stream._storedError = undefined; + stream._writer = undefined; + // Initialize to undefined first because the constructor of the controller checks this + // variable to validate the caller. + stream._writableStreamController = undefined; + // This queue is placed here instead of the writer class in order to allow for passing a writer to the next data + // producer without waiting for the queued writes to finish. + stream._writeRequests = new SimpleQueue(); + // Write requests are removed from _writeRequests when write() is called on the underlying sink. This prevents + // them from being erroneously rejected on error. If a write() call is in-flight, the request is stored here. + stream._inFlightWriteRequest = undefined; + // The promise that was returned from writer.close(). Stored here because it may be fulfilled after the writer + // has been detached. + stream._closeRequest = undefined; + // Close request is removed from _closeRequest when close() is called on the underlying sink. This prevents it + // from being erroneously rejected on error. If a close() call is in-flight, the request is stored here. + stream._inFlightCloseRequest = undefined; + // The promise that was returned from writer.abort(). This may also be fulfilled after the writer has detached. + stream._pendingAbortRequest = undefined; + // The backpressure signal set by the controller. + stream._backpressure = false; + } + function IsWritableStream(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_writableStreamController')) { + return false; + } + return true; + } + function IsWritableStreamLocked(stream) { + if (stream._writer === undefined) { + return false; + } + return true; + } + function WritableStreamAbort(stream, reason) { + const state = stream._state; + if (state === 'closed' || state === 'errored') { + return promiseResolvedWith(undefined); + } + if (stream._pendingAbortRequest !== undefined) { + return stream._pendingAbortRequest._promise; + } + let wasAlreadyErroring = false; + if (state === 'erroring') { + wasAlreadyErroring = true; + // reason will not be used, so don't keep a reference to it. + reason = undefined; + } + const promise = newPromise((resolve, reject) => { + stream._pendingAbortRequest = { + _promise: undefined, + _resolve: resolve, + _reject: reject, + _reason: reason, + _wasAlreadyErroring: wasAlreadyErroring + }; + }); + stream._pendingAbortRequest._promise = promise; + if (!wasAlreadyErroring) { + WritableStreamStartErroring(stream, reason); + } + return promise; + } + function WritableStreamClose(stream) { + const state = stream._state; + if (state === 'closed' || state === 'errored') { + return promiseRejectedWith(new TypeError(`The stream (in ${state} state) is not in the writable state and cannot be closed`)); + } + const promise = newPromise((resolve, reject) => { + const closeRequest = { + _resolve: resolve, + _reject: reject + }; + stream._closeRequest = closeRequest; + }); + const writer = stream._writer; + if (writer !== undefined && stream._backpressure && state === 'writable') { + defaultWriterReadyPromiseResolve(writer); + } + WritableStreamDefaultControllerClose(stream._writableStreamController); + return promise; + } + // WritableStream API exposed for controllers. + function WritableStreamAddWriteRequest(stream) { + const promise = newPromise((resolve, reject) => { + const writeRequest = { + _resolve: resolve, + _reject: reject + }; + stream._writeRequests.push(writeRequest); + }); + return promise; + } + function WritableStreamDealWithRejection(stream, error) { + const state = stream._state; + if (state === 'writable') { + WritableStreamStartErroring(stream, error); + return; + } + WritableStreamFinishErroring(stream); + } + function WritableStreamStartErroring(stream, reason) { + const controller = stream._writableStreamController; + stream._state = 'erroring'; + stream._storedError = reason; + const writer = stream._writer; + if (writer !== undefined) { + WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, reason); + } + if (!WritableStreamHasOperationMarkedInFlight(stream) && controller._started) { + WritableStreamFinishErroring(stream); + } + } + function WritableStreamFinishErroring(stream) { + stream._state = 'errored'; + stream._writableStreamController[ErrorSteps](); + const storedError = stream._storedError; + stream._writeRequests.forEach(writeRequest => { + writeRequest._reject(storedError); + }); + stream._writeRequests = new SimpleQueue(); + if (stream._pendingAbortRequest === undefined) { + WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); + return; + } + const abortRequest = stream._pendingAbortRequest; + stream._pendingAbortRequest = undefined; + if (abortRequest._wasAlreadyErroring) { + abortRequest._reject(storedError); + WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); + return; + } + const promise = stream._writableStreamController[AbortSteps](abortRequest._reason); + uponPromise(promise, () => { + abortRequest._resolve(); + WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); + }, (reason) => { + abortRequest._reject(reason); + WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); + }); + } + function WritableStreamFinishInFlightWrite(stream) { + stream._inFlightWriteRequest._resolve(undefined); + stream._inFlightWriteRequest = undefined; + } + function WritableStreamFinishInFlightWriteWithError(stream, error) { + stream._inFlightWriteRequest._reject(error); + stream._inFlightWriteRequest = undefined; + WritableStreamDealWithRejection(stream, error); + } + function WritableStreamFinishInFlightClose(stream) { + stream._inFlightCloseRequest._resolve(undefined); + stream._inFlightCloseRequest = undefined; + const state = stream._state; + if (state === 'erroring') { + // The error was too late to do anything, so it is ignored. + stream._storedError = undefined; + if (stream._pendingAbortRequest !== undefined) { + stream._pendingAbortRequest._resolve(); + stream._pendingAbortRequest = undefined; + } + } + stream._state = 'closed'; + const writer = stream._writer; + if (writer !== undefined) { + defaultWriterClosedPromiseResolve(writer); + } + } + function WritableStreamFinishInFlightCloseWithError(stream, error) { + stream._inFlightCloseRequest._reject(error); + stream._inFlightCloseRequest = undefined; + // Never execute sink abort() after sink close(). + if (stream._pendingAbortRequest !== undefined) { + stream._pendingAbortRequest._reject(error); + stream._pendingAbortRequest = undefined; + } + WritableStreamDealWithRejection(stream, error); + } + // TODO(ricea): Fix alphabetical order. + function WritableStreamCloseQueuedOrInFlight(stream) { + if (stream._closeRequest === undefined && stream._inFlightCloseRequest === undefined) { + return false; + } + return true; + } + function WritableStreamHasOperationMarkedInFlight(stream) { + if (stream._inFlightWriteRequest === undefined && stream._inFlightCloseRequest === undefined) { + return false; + } + return true; + } + function WritableStreamMarkCloseRequestInFlight(stream) { + stream._inFlightCloseRequest = stream._closeRequest; + stream._closeRequest = undefined; + } + function WritableStreamMarkFirstWriteRequestInFlight(stream) { + stream._inFlightWriteRequest = stream._writeRequests.shift(); + } + function WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream) { + if (stream._closeRequest !== undefined) { + stream._closeRequest._reject(stream._storedError); + stream._closeRequest = undefined; + } + const writer = stream._writer; + if (writer !== undefined) { + defaultWriterClosedPromiseReject(writer, stream._storedError); + } + } + function WritableStreamUpdateBackpressure(stream, backpressure) { + const writer = stream._writer; + if (writer !== undefined && backpressure !== stream._backpressure) { + if (backpressure) { + defaultWriterReadyPromiseReset(writer); + } + else { + defaultWriterReadyPromiseResolve(writer); + } + } + stream._backpressure = backpressure; + } + /** + * A default writer vended by a {@link WritableStream}. + * + * @public + */ + class WritableStreamDefaultWriter { + constructor(stream) { + assertRequiredArgument(stream, 1, 'WritableStreamDefaultWriter'); + assertWritableStream(stream, 'First parameter'); + if (IsWritableStreamLocked(stream)) { + throw new TypeError('This stream has already been locked for exclusive writing by another writer'); + } + this._ownerWritableStream = stream; + stream._writer = this; + const state = stream._state; + if (state === 'writable') { + if (!WritableStreamCloseQueuedOrInFlight(stream) && stream._backpressure) { + defaultWriterReadyPromiseInitialize(this); + } + else { + defaultWriterReadyPromiseInitializeAsResolved(this); + } + defaultWriterClosedPromiseInitialize(this); + } + else if (state === 'erroring') { + defaultWriterReadyPromiseInitializeAsRejected(this, stream._storedError); + defaultWriterClosedPromiseInitialize(this); + } + else if (state === 'closed') { + defaultWriterReadyPromiseInitializeAsResolved(this); + defaultWriterClosedPromiseInitializeAsResolved(this); + } + else { + const storedError = stream._storedError; + defaultWriterReadyPromiseInitializeAsRejected(this, storedError); + defaultWriterClosedPromiseInitializeAsRejected(this, storedError); + } + } + /** + * Returns a promise that will be fulfilled when the stream becomes closed, or rejected if the stream ever errors or + * the writer’s lock is released before the stream finishes closing. + */ + get closed() { + if (!IsWritableStreamDefaultWriter(this)) { + return promiseRejectedWith(defaultWriterBrandCheckException('closed')); + } + return this._closedPromise; + } + /** + * Returns the desired size to fill the stream’s internal queue. It can be negative, if the queue is over-full. + * A producer can use this information to determine the right amount of data to write. + * + * It will be `null` if the stream cannot be successfully written to (due to either being errored, or having an abort + * queued up). It will return zero if the stream is closed. And the getter will throw an exception if invoked when + * the writer’s lock is released. + */ + get desiredSize() { + if (!IsWritableStreamDefaultWriter(this)) { + throw defaultWriterBrandCheckException('desiredSize'); + } + if (this._ownerWritableStream === undefined) { + throw defaultWriterLockException('desiredSize'); + } + return WritableStreamDefaultWriterGetDesiredSize(this); + } + /** + * Returns a promise that will be fulfilled when the desired size to fill the stream’s internal queue transitions + * from non-positive to positive, signaling that it is no longer applying backpressure. Once the desired size dips + * back to zero or below, the getter will return a new promise that stays pending until the next transition. + * + * If the stream becomes errored or aborted, or the writer’s lock is released, the returned promise will become + * rejected. + */ + get ready() { + if (!IsWritableStreamDefaultWriter(this)) { + return promiseRejectedWith(defaultWriterBrandCheckException('ready')); + } + return this._readyPromise; + } + /** + * If the reader is active, behaves the same as {@link WritableStream.abort | stream.abort(reason)}. + */ + abort(reason = undefined) { + if (!IsWritableStreamDefaultWriter(this)) { + return promiseRejectedWith(defaultWriterBrandCheckException('abort')); + } + if (this._ownerWritableStream === undefined) { + return promiseRejectedWith(defaultWriterLockException('abort')); + } + return WritableStreamDefaultWriterAbort(this, reason); + } + /** + * If the reader is active, behaves the same as {@link WritableStream.close | stream.close()}. + */ + close() { + if (!IsWritableStreamDefaultWriter(this)) { + return promiseRejectedWith(defaultWriterBrandCheckException('close')); + } + const stream = this._ownerWritableStream; + if (stream === undefined) { + return promiseRejectedWith(defaultWriterLockException('close')); + } + if (WritableStreamCloseQueuedOrInFlight(stream)) { + return promiseRejectedWith(new TypeError('Cannot close an already-closing stream')); + } + return WritableStreamDefaultWriterClose(this); + } + /** + * Releases the writer’s lock on the corresponding stream. After the lock is released, the writer is no longer active. + * If the associated stream is errored when the lock is released, the writer will appear errored in the same way from + * now on; otherwise, the writer will appear closed. + * + * Note that the lock can still be released even if some ongoing writes have not yet finished (i.e. even if the + * promises returned from previous calls to {@link WritableStreamDefaultWriter.write | write()} have not yet settled). + * It’s not necessary to hold the lock on the writer for the duration of the write; the lock instead simply prevents + * other producers from writing in an interleaved manner. + */ + releaseLock() { + if (!IsWritableStreamDefaultWriter(this)) { + throw defaultWriterBrandCheckException('releaseLock'); + } + const stream = this._ownerWritableStream; + if (stream === undefined) { + return; + } + WritableStreamDefaultWriterRelease(this); + } + write(chunk = undefined) { + if (!IsWritableStreamDefaultWriter(this)) { + return promiseRejectedWith(defaultWriterBrandCheckException('write')); + } + if (this._ownerWritableStream === undefined) { + return promiseRejectedWith(defaultWriterLockException('write to')); + } + return WritableStreamDefaultWriterWrite(this, chunk); + } + } + Object.defineProperties(WritableStreamDefaultWriter.prototype, { + abort: { enumerable: true }, + close: { enumerable: true }, + releaseLock: { enumerable: true }, + write: { enumerable: true }, + closed: { enumerable: true }, + desiredSize: { enumerable: true }, + ready: { enumerable: true } + }); + if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(WritableStreamDefaultWriter.prototype, SymbolPolyfill.toStringTag, { + value: 'WritableStreamDefaultWriter', + configurable: true + }); + } + // Abstract operations for the WritableStreamDefaultWriter. + function IsWritableStreamDefaultWriter(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_ownerWritableStream')) { + return false; + } + return true; + } + // A client of WritableStreamDefaultWriter may use these functions directly to bypass state check. + function WritableStreamDefaultWriterAbort(writer, reason) { + const stream = writer._ownerWritableStream; + return WritableStreamAbort(stream, reason); + } + function WritableStreamDefaultWriterClose(writer) { + const stream = writer._ownerWritableStream; + return WritableStreamClose(stream); + } + function WritableStreamDefaultWriterCloseWithErrorPropagation(writer) { + const stream = writer._ownerWritableStream; + const state = stream._state; + if (WritableStreamCloseQueuedOrInFlight(stream) || state === 'closed') { + return promiseResolvedWith(undefined); + } + if (state === 'errored') { + return promiseRejectedWith(stream._storedError); + } + return WritableStreamDefaultWriterClose(writer); + } + function WritableStreamDefaultWriterEnsureClosedPromiseRejected(writer, error) { + if (writer._closedPromiseState === 'pending') { + defaultWriterClosedPromiseReject(writer, error); + } + else { + defaultWriterClosedPromiseResetToRejected(writer, error); + } + } + function WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, error) { + if (writer._readyPromiseState === 'pending') { + defaultWriterReadyPromiseReject(writer, error); + } + else { + defaultWriterReadyPromiseResetToRejected(writer, error); + } + } + function WritableStreamDefaultWriterGetDesiredSize(writer) { + const stream = writer._ownerWritableStream; + const state = stream._state; + if (state === 'errored' || state === 'erroring') { + return null; + } + if (state === 'closed') { + return 0; + } + return WritableStreamDefaultControllerGetDesiredSize(stream._writableStreamController); + } + function WritableStreamDefaultWriterRelease(writer) { + const stream = writer._ownerWritableStream; + const releasedError = new TypeError(`Writer was released and can no longer be used to monitor the stream's closedness`); + WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, releasedError); + // The state transitions to "errored" before the sink abort() method runs, but the writer.closed promise is not + // rejected until afterwards. This means that simply testing state will not work. + WritableStreamDefaultWriterEnsureClosedPromiseRejected(writer, releasedError); + stream._writer = undefined; + writer._ownerWritableStream = undefined; + } + function WritableStreamDefaultWriterWrite(writer, chunk) { + const stream = writer._ownerWritableStream; + const controller = stream._writableStreamController; + const chunkSize = WritableStreamDefaultControllerGetChunkSize(controller, chunk); + if (stream !== writer._ownerWritableStream) { + return promiseRejectedWith(defaultWriterLockException('write to')); + } + const state = stream._state; + if (state === 'errored') { + return promiseRejectedWith(stream._storedError); + } + if (WritableStreamCloseQueuedOrInFlight(stream) || state === 'closed') { + return promiseRejectedWith(new TypeError('The stream is closing or closed and cannot be written to')); + } + if (state === 'erroring') { + return promiseRejectedWith(stream._storedError); + } + const promise = WritableStreamAddWriteRequest(stream); + WritableStreamDefaultControllerWrite(controller, chunk, chunkSize); + return promise; + } + const closeSentinel = {}; + /** + * Allows control of a {@link WritableStream | writable stream}'s state and internal queue. + * + * @public + */ + class WritableStreamDefaultController { + constructor() { + throw new TypeError('Illegal constructor'); + } + /** + * Closes the controlled writable stream, making all future interactions with it fail with the given error `e`. + * + * This method is rarely used, since usually it suffices to return a rejected promise from one of the underlying + * sink's methods. However, it can be useful for suddenly shutting down a stream in response to an event outside the + * normal lifecycle of interactions with the underlying sink. + */ + error(e = undefined) { + if (!IsWritableStreamDefaultController(this)) { + throw new TypeError('WritableStreamDefaultController.prototype.error can only be used on a WritableStreamDefaultController'); + } + const state = this._controlledWritableStream._state; + if (state !== 'writable') { + // The stream is closed, errored or will be soon. The sink can't do anything useful if it gets an error here, so + // just treat it as a no-op. + return; + } + WritableStreamDefaultControllerError(this, e); + } + /** @internal */ + [AbortSteps](reason) { + const result = this._abortAlgorithm(reason); + WritableStreamDefaultControllerClearAlgorithms(this); + return result; + } + /** @internal */ + [ErrorSteps]() { + ResetQueue(this); + } + } + Object.defineProperties(WritableStreamDefaultController.prototype, { + error: { enumerable: true } + }); + if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(WritableStreamDefaultController.prototype, SymbolPolyfill.toStringTag, { + value: 'WritableStreamDefaultController', + configurable: true + }); + } + // Abstract operations implementing interface required by the WritableStream. + function IsWritableStreamDefaultController(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_controlledWritableStream')) { + return false; + } + return true; + } + function SetUpWritableStreamDefaultController(stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark, sizeAlgorithm) { + controller._controlledWritableStream = stream; + stream._writableStreamController = controller; + // Need to set the slots so that the assert doesn't fire. In the spec the slots already exist implicitly. + controller._queue = undefined; + controller._queueTotalSize = undefined; + ResetQueue(controller); + controller._started = false; + controller._strategySizeAlgorithm = sizeAlgorithm; + controller._strategyHWM = highWaterMark; + controller._writeAlgorithm = writeAlgorithm; + controller._closeAlgorithm = closeAlgorithm; + controller._abortAlgorithm = abortAlgorithm; + const backpressure = WritableStreamDefaultControllerGetBackpressure(controller); + WritableStreamUpdateBackpressure(stream, backpressure); + const startResult = startAlgorithm(); + const startPromise = promiseResolvedWith(startResult); + uponPromise(startPromise, () => { + controller._started = true; + WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); + }, r => { + controller._started = true; + WritableStreamDealWithRejection(stream, r); + }); + } + function SetUpWritableStreamDefaultControllerFromUnderlyingSink(stream, underlyingSink, highWaterMark, sizeAlgorithm) { + const controller = Object.create(WritableStreamDefaultController.prototype); + let startAlgorithm = () => undefined; + let writeAlgorithm = () => promiseResolvedWith(undefined); + let closeAlgorithm = () => promiseResolvedWith(undefined); + let abortAlgorithm = () => promiseResolvedWith(undefined); + if (underlyingSink.start !== undefined) { + startAlgorithm = () => underlyingSink.start(controller); + } + if (underlyingSink.write !== undefined) { + writeAlgorithm = chunk => underlyingSink.write(chunk, controller); + } + if (underlyingSink.close !== undefined) { + closeAlgorithm = () => underlyingSink.close(); + } + if (underlyingSink.abort !== undefined) { + abortAlgorithm = reason => underlyingSink.abort(reason); + } + SetUpWritableStreamDefaultController(stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark, sizeAlgorithm); + } + // ClearAlgorithms may be called twice. Erroring the same stream in multiple ways will often result in redundant calls. + function WritableStreamDefaultControllerClearAlgorithms(controller) { + controller._writeAlgorithm = undefined; + controller._closeAlgorithm = undefined; + controller._abortAlgorithm = undefined; + controller._strategySizeAlgorithm = undefined; + } + function WritableStreamDefaultControllerClose(controller) { + EnqueueValueWithSize(controller, closeSentinel, 0); + WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); + } + function WritableStreamDefaultControllerGetChunkSize(controller, chunk) { + try { + return controller._strategySizeAlgorithm(chunk); + } + catch (chunkSizeE) { + WritableStreamDefaultControllerErrorIfNeeded(controller, chunkSizeE); + return 1; + } + } + function WritableStreamDefaultControllerGetDesiredSize(controller) { + return controller._strategyHWM - controller._queueTotalSize; + } + function WritableStreamDefaultControllerWrite(controller, chunk, chunkSize) { + try { + EnqueueValueWithSize(controller, chunk, chunkSize); + } + catch (enqueueE) { + WritableStreamDefaultControllerErrorIfNeeded(controller, enqueueE); + return; + } + const stream = controller._controlledWritableStream; + if (!WritableStreamCloseQueuedOrInFlight(stream) && stream._state === 'writable') { + const backpressure = WritableStreamDefaultControllerGetBackpressure(controller); + WritableStreamUpdateBackpressure(stream, backpressure); + } + WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); + } + // Abstract operations for the WritableStreamDefaultController. + function WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller) { + const stream = controller._controlledWritableStream; + if (!controller._started) { + return; + } + if (stream._inFlightWriteRequest !== undefined) { + return; + } + const state = stream._state; + if (state === 'erroring') { + WritableStreamFinishErroring(stream); + return; + } + if (controller._queue.length === 0) { + return; + } + const value = PeekQueueValue(controller); + if (value === closeSentinel) { + WritableStreamDefaultControllerProcessClose(controller); + } + else { + WritableStreamDefaultControllerProcessWrite(controller, value); + } + } + function WritableStreamDefaultControllerErrorIfNeeded(controller, error) { + if (controller._controlledWritableStream._state === 'writable') { + WritableStreamDefaultControllerError(controller, error); + } + } + function WritableStreamDefaultControllerProcessClose(controller) { + const stream = controller._controlledWritableStream; + WritableStreamMarkCloseRequestInFlight(stream); + DequeueValue(controller); + const sinkClosePromise = controller._closeAlgorithm(); + WritableStreamDefaultControllerClearAlgorithms(controller); + uponPromise(sinkClosePromise, () => { + WritableStreamFinishInFlightClose(stream); + }, reason => { + WritableStreamFinishInFlightCloseWithError(stream, reason); + }); + } + function WritableStreamDefaultControllerProcessWrite(controller, chunk) { + const stream = controller._controlledWritableStream; + WritableStreamMarkFirstWriteRequestInFlight(stream); + const sinkWritePromise = controller._writeAlgorithm(chunk); + uponPromise(sinkWritePromise, () => { + WritableStreamFinishInFlightWrite(stream); + const state = stream._state; + DequeueValue(controller); + if (!WritableStreamCloseQueuedOrInFlight(stream) && state === 'writable') { + const backpressure = WritableStreamDefaultControllerGetBackpressure(controller); + WritableStreamUpdateBackpressure(stream, backpressure); + } + WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); + }, reason => { + if (stream._state === 'writable') { + WritableStreamDefaultControllerClearAlgorithms(controller); + } + WritableStreamFinishInFlightWriteWithError(stream, reason); + }); + } + function WritableStreamDefaultControllerGetBackpressure(controller) { + const desiredSize = WritableStreamDefaultControllerGetDesiredSize(controller); + return desiredSize <= 0; + } + // A client of WritableStreamDefaultController may use these functions directly to bypass state check. + function WritableStreamDefaultControllerError(controller, error) { + const stream = controller._controlledWritableStream; + WritableStreamDefaultControllerClearAlgorithms(controller); + WritableStreamStartErroring(stream, error); + } + // Helper functions for the WritableStream. + function streamBrandCheckException$2(name) { + return new TypeError(`WritableStream.prototype.${name} can only be used on a WritableStream`); + } + // Helper functions for the WritableStreamDefaultWriter. + function defaultWriterBrandCheckException(name) { + return new TypeError(`WritableStreamDefaultWriter.prototype.${name} can only be used on a WritableStreamDefaultWriter`); + } + function defaultWriterLockException(name) { + return new TypeError('Cannot ' + name + ' a stream using a released writer'); + } + function defaultWriterClosedPromiseInitialize(writer) { + writer._closedPromise = newPromise((resolve, reject) => { + writer._closedPromise_resolve = resolve; + writer._closedPromise_reject = reject; + writer._closedPromiseState = 'pending'; + }); + } + function defaultWriterClosedPromiseInitializeAsRejected(writer, reason) { + defaultWriterClosedPromiseInitialize(writer); + defaultWriterClosedPromiseReject(writer, reason); + } + function defaultWriterClosedPromiseInitializeAsResolved(writer) { + defaultWriterClosedPromiseInitialize(writer); + defaultWriterClosedPromiseResolve(writer); + } + function defaultWriterClosedPromiseReject(writer, reason) { + if (writer._closedPromise_reject === undefined) { + return; + } + setPromiseIsHandledToTrue(writer._closedPromise); + writer._closedPromise_reject(reason); + writer._closedPromise_resolve = undefined; + writer._closedPromise_reject = undefined; + writer._closedPromiseState = 'rejected'; + } + function defaultWriterClosedPromiseResetToRejected(writer, reason) { + defaultWriterClosedPromiseInitializeAsRejected(writer, reason); + } + function defaultWriterClosedPromiseResolve(writer) { + if (writer._closedPromise_resolve === undefined) { + return; + } + writer._closedPromise_resolve(undefined); + writer._closedPromise_resolve = undefined; + writer._closedPromise_reject = undefined; + writer._closedPromiseState = 'resolved'; + } + function defaultWriterReadyPromiseInitialize(writer) { + writer._readyPromise = newPromise((resolve, reject) => { + writer._readyPromise_resolve = resolve; + writer._readyPromise_reject = reject; + }); + writer._readyPromiseState = 'pending'; + } + function defaultWriterReadyPromiseInitializeAsRejected(writer, reason) { + defaultWriterReadyPromiseInitialize(writer); + defaultWriterReadyPromiseReject(writer, reason); + } + function defaultWriterReadyPromiseInitializeAsResolved(writer) { + defaultWriterReadyPromiseInitialize(writer); + defaultWriterReadyPromiseResolve(writer); + } + function defaultWriterReadyPromiseReject(writer, reason) { + if (writer._readyPromise_reject === undefined) { + return; + } + setPromiseIsHandledToTrue(writer._readyPromise); + writer._readyPromise_reject(reason); + writer._readyPromise_resolve = undefined; + writer._readyPromise_reject = undefined; + writer._readyPromiseState = 'rejected'; + } + function defaultWriterReadyPromiseReset(writer) { + defaultWriterReadyPromiseInitialize(writer); + } + function defaultWriterReadyPromiseResetToRejected(writer, reason) { + defaultWriterReadyPromiseInitializeAsRejected(writer, reason); + } + function defaultWriterReadyPromiseResolve(writer) { + if (writer._readyPromise_resolve === undefined) { + return; + } + writer._readyPromise_resolve(undefined); + writer._readyPromise_resolve = undefined; + writer._readyPromise_reject = undefined; + writer._readyPromiseState = 'fulfilled'; + } + + function isAbortSignal(value) { + if (typeof value !== 'object' || value === null) { + return false; + } + try { + return typeof value.aborted === 'boolean'; + } + catch (_a) { + // AbortSignal.prototype.aborted throws if its brand check fails + return false; + } + } + + /// + const NativeDOMException = typeof DOMException !== 'undefined' ? DOMException : undefined; + + /// + function isDOMExceptionConstructor(ctor) { + if (!(typeof ctor === 'function' || typeof ctor === 'object')) { + return false; + } + try { + new ctor(); + return true; + } + catch (_a) { + return false; + } + } + function createDOMExceptionPolyfill() { + // eslint-disable-next-line no-shadow + const ctor = function DOMException(message, name) { + this.message = message || ''; + this.name = name || 'Error'; + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + }; + ctor.prototype = Object.create(Error.prototype); + Object.defineProperty(ctor.prototype, 'constructor', { value: ctor, writable: true, configurable: true }); + return ctor; + } + // eslint-disable-next-line no-redeclare + const DOMException$1 = isDOMExceptionConstructor(NativeDOMException) ? NativeDOMException : createDOMExceptionPolyfill(); + + function ReadableStreamPipeTo(source, dest, preventClose, preventAbort, preventCancel, signal) { + const reader = AcquireReadableStreamDefaultReader(source); + const writer = AcquireWritableStreamDefaultWriter(dest); + source._disturbed = true; + let shuttingDown = false; + // This is used to keep track of the spec's requirement that we wait for ongoing writes during shutdown. + let currentWrite = promiseResolvedWith(undefined); + return newPromise((resolve, reject) => { + let abortAlgorithm; + if (signal !== undefined) { + abortAlgorithm = () => { + const error = new DOMException$1('Aborted', 'AbortError'); + const actions = []; + if (!preventAbort) { + actions.push(() => { + if (dest._state === 'writable') { + return WritableStreamAbort(dest, error); + } + return promiseResolvedWith(undefined); + }); + } + if (!preventCancel) { + actions.push(() => { + if (source._state === 'readable') { + return ReadableStreamCancel(source, error); + } + return promiseResolvedWith(undefined); + }); + } + shutdownWithAction(() => Promise.all(actions.map(action => action())), true, error); + }; + if (signal.aborted) { + abortAlgorithm(); + return; + } + signal.addEventListener('abort', abortAlgorithm); + } + // Using reader and writer, read all chunks from this and write them to dest + // - Backpressure must be enforced + // - Shutdown must stop all activity + function pipeLoop() { + return newPromise((resolveLoop, rejectLoop) => { + function next(done) { + if (done) { + resolveLoop(); + } + else { + // Use `PerformPromiseThen` instead of `uponPromise` to avoid + // adding unnecessary `.catch(rethrowAssertionErrorRejection)` handlers + PerformPromiseThen(pipeStep(), next, rejectLoop); + } + } + next(false); + }); + } + function pipeStep() { + if (shuttingDown) { + return promiseResolvedWith(true); + } + return PerformPromiseThen(writer._readyPromise, () => { + return newPromise((resolveRead, rejectRead) => { + ReadableStreamDefaultReaderRead(reader, { + _chunkSteps: chunk => { + currentWrite = PerformPromiseThen(WritableStreamDefaultWriterWrite(writer, chunk), undefined, noop); + resolveRead(false); + }, + _closeSteps: () => resolveRead(true), + _errorSteps: rejectRead + }); + }); + }); + } + // Errors must be propagated forward + isOrBecomesErrored(source, reader._closedPromise, storedError => { + if (!preventAbort) { + shutdownWithAction(() => WritableStreamAbort(dest, storedError), true, storedError); + } + else { + shutdown(true, storedError); + } + }); + // Errors must be propagated backward + isOrBecomesErrored(dest, writer._closedPromise, storedError => { + if (!preventCancel) { + shutdownWithAction(() => ReadableStreamCancel(source, storedError), true, storedError); + } + else { + shutdown(true, storedError); + } + }); + // Closing must be propagated forward + isOrBecomesClosed(source, reader._closedPromise, () => { + if (!preventClose) { + shutdownWithAction(() => WritableStreamDefaultWriterCloseWithErrorPropagation(writer)); + } + else { + shutdown(); + } + }); + // Closing must be propagated backward + if (WritableStreamCloseQueuedOrInFlight(dest) || dest._state === 'closed') { + const destClosed = new TypeError('the destination writable stream closed before all data could be piped to it'); + if (!preventCancel) { + shutdownWithAction(() => ReadableStreamCancel(source, destClosed), true, destClosed); + } + else { + shutdown(true, destClosed); + } + } + setPromiseIsHandledToTrue(pipeLoop()); + function waitForWritesToFinish() { + // Another write may have started while we were waiting on this currentWrite, so we have to be sure to wait + // for that too. + const oldCurrentWrite = currentWrite; + return PerformPromiseThen(currentWrite, () => oldCurrentWrite !== currentWrite ? waitForWritesToFinish() : undefined); + } + function isOrBecomesErrored(stream, promise, action) { + if (stream._state === 'errored') { + action(stream._storedError); + } + else { + uponRejection(promise, action); + } + } + function isOrBecomesClosed(stream, promise, action) { + if (stream._state === 'closed') { + action(); + } + else { + uponFulfillment(promise, action); + } + } + function shutdownWithAction(action, originalIsError, originalError) { + if (shuttingDown) { + return; + } + shuttingDown = true; + if (dest._state === 'writable' && !WritableStreamCloseQueuedOrInFlight(dest)) { + uponFulfillment(waitForWritesToFinish(), doTheRest); + } + else { + doTheRest(); + } + function doTheRest() { + uponPromise(action(), () => finalize(originalIsError, originalError), newError => finalize(true, newError)); + } + } + function shutdown(isError, error) { + if (shuttingDown) { + return; + } + shuttingDown = true; + if (dest._state === 'writable' && !WritableStreamCloseQueuedOrInFlight(dest)) { + uponFulfillment(waitForWritesToFinish(), () => finalize(isError, error)); + } + else { + finalize(isError, error); + } + } + function finalize(isError, error) { + WritableStreamDefaultWriterRelease(writer); + ReadableStreamReaderGenericRelease(reader); + if (signal !== undefined) { + signal.removeEventListener('abort', abortAlgorithm); + } + if (isError) { + reject(error); + } + else { + resolve(undefined); + } + } + }); + } + + /** + * Allows control of a {@link ReadableStream | readable stream}'s state and internal queue. + * + * @public + */ + class ReadableStreamDefaultController { + constructor() { + throw new TypeError('Illegal constructor'); + } + /** + * Returns the desired size to fill the controlled stream's internal queue. It can be negative, if the queue is + * over-full. An underlying source ought to use this information to determine when and how to apply backpressure. + */ + get desiredSize() { + if (!IsReadableStreamDefaultController(this)) { + throw defaultControllerBrandCheckException$1('desiredSize'); + } + return ReadableStreamDefaultControllerGetDesiredSize(this); + } + /** + * Closes the controlled readable stream. Consumers will still be able to read any previously-enqueued chunks from + * the stream, but once those are read, the stream will become closed. + */ + close() { + if (!IsReadableStreamDefaultController(this)) { + throw defaultControllerBrandCheckException$1('close'); + } + if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(this)) { + throw new TypeError('The stream is not in a state that permits close'); + } + ReadableStreamDefaultControllerClose(this); + } + enqueue(chunk = undefined) { + if (!IsReadableStreamDefaultController(this)) { + throw defaultControllerBrandCheckException$1('enqueue'); + } + if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(this)) { + throw new TypeError('The stream is not in a state that permits enqueue'); + } + return ReadableStreamDefaultControllerEnqueue(this, chunk); + } + /** + * Errors the controlled readable stream, making all future interactions with it fail with the given error `e`. + */ + error(e = undefined) { + if (!IsReadableStreamDefaultController(this)) { + throw defaultControllerBrandCheckException$1('error'); + } + ReadableStreamDefaultControllerError(this, e); + } + /** @internal */ + [CancelSteps](reason) { + ResetQueue(this); + const result = this._cancelAlgorithm(reason); + ReadableStreamDefaultControllerClearAlgorithms(this); + return result; + } + /** @internal */ + [PullSteps](readRequest) { + const stream = this._controlledReadableStream; + if (this._queue.length > 0) { + const chunk = DequeueValue(this); + if (this._closeRequested && this._queue.length === 0) { + ReadableStreamDefaultControllerClearAlgorithms(this); + ReadableStreamClose(stream); + } + else { + ReadableStreamDefaultControllerCallPullIfNeeded(this); + } + readRequest._chunkSteps(chunk); + } + else { + ReadableStreamAddReadRequest(stream, readRequest); + ReadableStreamDefaultControllerCallPullIfNeeded(this); + } + } + } + Object.defineProperties(ReadableStreamDefaultController.prototype, { + close: { enumerable: true }, + enqueue: { enumerable: true }, + error: { enumerable: true }, + desiredSize: { enumerable: true } + }); + if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(ReadableStreamDefaultController.prototype, SymbolPolyfill.toStringTag, { + value: 'ReadableStreamDefaultController', + configurable: true + }); + } + // Abstract operations for the ReadableStreamDefaultController. + function IsReadableStreamDefaultController(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_controlledReadableStream')) { + return false; + } + return true; + } + function ReadableStreamDefaultControllerCallPullIfNeeded(controller) { + const shouldPull = ReadableStreamDefaultControllerShouldCallPull(controller); + if (!shouldPull) { + return; + } + if (controller._pulling) { + controller._pullAgain = true; + return; + } + controller._pulling = true; + const pullPromise = controller._pullAlgorithm(); + uponPromise(pullPromise, () => { + controller._pulling = false; + if (controller._pullAgain) { + controller._pullAgain = false; + ReadableStreamDefaultControllerCallPullIfNeeded(controller); + } + }, e => { + ReadableStreamDefaultControllerError(controller, e); + }); + } + function ReadableStreamDefaultControllerShouldCallPull(controller) { + const stream = controller._controlledReadableStream; + if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(controller)) { + return false; + } + if (!controller._started) { + return false; + } + if (IsReadableStreamLocked(stream) && ReadableStreamGetNumReadRequests(stream) > 0) { + return true; + } + const desiredSize = ReadableStreamDefaultControllerGetDesiredSize(controller); + if (desiredSize > 0) { + return true; + } + return false; + } + function ReadableStreamDefaultControllerClearAlgorithms(controller) { + controller._pullAlgorithm = undefined; + controller._cancelAlgorithm = undefined; + controller._strategySizeAlgorithm = undefined; + } + // A client of ReadableStreamDefaultController may use these functions directly to bypass state check. + function ReadableStreamDefaultControllerClose(controller) { + if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(controller)) { + return; + } + const stream = controller._controlledReadableStream; + controller._closeRequested = true; + if (controller._queue.length === 0) { + ReadableStreamDefaultControllerClearAlgorithms(controller); + ReadableStreamClose(stream); + } + } + function ReadableStreamDefaultControllerEnqueue(controller, chunk) { + if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(controller)) { + return; + } + const stream = controller._controlledReadableStream; + if (IsReadableStreamLocked(stream) && ReadableStreamGetNumReadRequests(stream) > 0) { + ReadableStreamFulfillReadRequest(stream, chunk, false); + } + else { + let chunkSize; + try { + chunkSize = controller._strategySizeAlgorithm(chunk); + } + catch (chunkSizeE) { + ReadableStreamDefaultControllerError(controller, chunkSizeE); + throw chunkSizeE; + } + try { + EnqueueValueWithSize(controller, chunk, chunkSize); + } + catch (enqueueE) { + ReadableStreamDefaultControllerError(controller, enqueueE); + throw enqueueE; + } + } + ReadableStreamDefaultControllerCallPullIfNeeded(controller); + } + function ReadableStreamDefaultControllerError(controller, e) { + const stream = controller._controlledReadableStream; + if (stream._state !== 'readable') { + return; + } + ResetQueue(controller); + ReadableStreamDefaultControllerClearAlgorithms(controller); + ReadableStreamError(stream, e); + } + function ReadableStreamDefaultControllerGetDesiredSize(controller) { + const state = controller._controlledReadableStream._state; + if (state === 'errored') { + return null; + } + if (state === 'closed') { + return 0; + } + return controller._strategyHWM - controller._queueTotalSize; + } + // This is used in the implementation of TransformStream. + function ReadableStreamDefaultControllerHasBackpressure(controller) { + if (ReadableStreamDefaultControllerShouldCallPull(controller)) { + return false; + } + return true; + } + function ReadableStreamDefaultControllerCanCloseOrEnqueue(controller) { + const state = controller._controlledReadableStream._state; + if (!controller._closeRequested && state === 'readable') { + return true; + } + return false; + } + function SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm) { + controller._controlledReadableStream = stream; + controller._queue = undefined; + controller._queueTotalSize = undefined; + ResetQueue(controller); + controller._started = false; + controller._closeRequested = false; + controller._pullAgain = false; + controller._pulling = false; + controller._strategySizeAlgorithm = sizeAlgorithm; + controller._strategyHWM = highWaterMark; + controller._pullAlgorithm = pullAlgorithm; + controller._cancelAlgorithm = cancelAlgorithm; + stream._readableStreamController = controller; + const startResult = startAlgorithm(); + uponPromise(promiseResolvedWith(startResult), () => { + controller._started = true; + ReadableStreamDefaultControllerCallPullIfNeeded(controller); + }, r => { + ReadableStreamDefaultControllerError(controller, r); + }); + } + function SetUpReadableStreamDefaultControllerFromUnderlyingSource(stream, underlyingSource, highWaterMark, sizeAlgorithm) { + const controller = Object.create(ReadableStreamDefaultController.prototype); + let startAlgorithm = () => undefined; + let pullAlgorithm = () => promiseResolvedWith(undefined); + let cancelAlgorithm = () => promiseResolvedWith(undefined); + if (underlyingSource.start !== undefined) { + startAlgorithm = () => underlyingSource.start(controller); + } + if (underlyingSource.pull !== undefined) { + pullAlgorithm = () => underlyingSource.pull(controller); + } + if (underlyingSource.cancel !== undefined) { + cancelAlgorithm = reason => underlyingSource.cancel(reason); + } + SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm); + } + // Helper functions for the ReadableStreamDefaultController. + function defaultControllerBrandCheckException$1(name) { + return new TypeError(`ReadableStreamDefaultController.prototype.${name} can only be used on a ReadableStreamDefaultController`); + } + + function ReadableStreamTee(stream, cloneForBranch2) { + const reader = AcquireReadableStreamDefaultReader(stream); + let reading = false; + let canceled1 = false; + let canceled2 = false; + let reason1; + let reason2; + let branch1; + let branch2; + let resolveCancelPromise; + const cancelPromise = newPromise(resolve => { + resolveCancelPromise = resolve; + }); + function pullAlgorithm() { + if (reading) { + return promiseResolvedWith(undefined); + } + reading = true; + const readRequest = { + _chunkSteps: value => { + // This needs to be delayed a microtask because it takes at least a microtask to detect errors (using + // reader._closedPromise below), and we want errors in stream to error both branches immediately. We cannot let + // successful synchronously-available reads get ahead of asynchronously-available errors. + queueMicrotask(() => { + reading = false; + const value1 = value; + const value2 = value; + // There is no way to access the cloning code right now in the reference implementation. + // If we add one then we'll need an implementation for serializable objects. + // if (!canceled2 && cloneForBranch2) { + // value2 = StructuredDeserialize(StructuredSerialize(value2)); + // } + if (!canceled1) { + ReadableStreamDefaultControllerEnqueue(branch1._readableStreamController, value1); + } + if (!canceled2) { + ReadableStreamDefaultControllerEnqueue(branch2._readableStreamController, value2); + } + }); + }, + _closeSteps: () => { + reading = false; + if (!canceled1) { + ReadableStreamDefaultControllerClose(branch1._readableStreamController); + } + if (!canceled2) { + ReadableStreamDefaultControllerClose(branch2._readableStreamController); + } + if (!canceled1 || !canceled2) { + resolveCancelPromise(undefined); + } + }, + _errorSteps: () => { + reading = false; + } + }; + ReadableStreamDefaultReaderRead(reader, readRequest); + return promiseResolvedWith(undefined); + } + function cancel1Algorithm(reason) { + canceled1 = true; + reason1 = reason; + if (canceled2) { + const compositeReason = CreateArrayFromList([reason1, reason2]); + const cancelResult = ReadableStreamCancel(stream, compositeReason); + resolveCancelPromise(cancelResult); + } + return cancelPromise; + } + function cancel2Algorithm(reason) { + canceled2 = true; + reason2 = reason; + if (canceled1) { + const compositeReason = CreateArrayFromList([reason1, reason2]); + const cancelResult = ReadableStreamCancel(stream, compositeReason); + resolveCancelPromise(cancelResult); + } + return cancelPromise; + } + function startAlgorithm() { + // do nothing + } + branch1 = CreateReadableStream(startAlgorithm, pullAlgorithm, cancel1Algorithm); + branch2 = CreateReadableStream(startAlgorithm, pullAlgorithm, cancel2Algorithm); + uponRejection(reader._closedPromise, (r) => { + ReadableStreamDefaultControllerError(branch1._readableStreamController, r); + ReadableStreamDefaultControllerError(branch2._readableStreamController, r); + if (!canceled1 || !canceled2) { + resolveCancelPromise(undefined); + } + }); + return [branch1, branch2]; + } + + function convertUnderlyingDefaultOrByteSource(source, context) { + assertDictionary(source, context); + const original = source; + const autoAllocateChunkSize = original === null || original === void 0 ? void 0 : original.autoAllocateChunkSize; + const cancel = original === null || original === void 0 ? void 0 : original.cancel; + const pull = original === null || original === void 0 ? void 0 : original.pull; + const start = original === null || original === void 0 ? void 0 : original.start; + const type = original === null || original === void 0 ? void 0 : original.type; + return { + autoAllocateChunkSize: autoAllocateChunkSize === undefined ? + undefined : + convertUnsignedLongLongWithEnforceRange(autoAllocateChunkSize, `${context} has member 'autoAllocateChunkSize' that`), + cancel: cancel === undefined ? + undefined : + convertUnderlyingSourceCancelCallback(cancel, original, `${context} has member 'cancel' that`), + pull: pull === undefined ? + undefined : + convertUnderlyingSourcePullCallback(pull, original, `${context} has member 'pull' that`), + start: start === undefined ? + undefined : + convertUnderlyingSourceStartCallback(start, original, `${context} has member 'start' that`), + type: type === undefined ? undefined : convertReadableStreamType(type, `${context} has member 'type' that`) + }; + } + function convertUnderlyingSourceCancelCallback(fn, original, context) { + assertFunction(fn, context); + return (reason) => promiseCall(fn, original, [reason]); + } + function convertUnderlyingSourcePullCallback(fn, original, context) { + assertFunction(fn, context); + return (controller) => promiseCall(fn, original, [controller]); + } + function convertUnderlyingSourceStartCallback(fn, original, context) { + assertFunction(fn, context); + return (controller) => reflectCall(fn, original, [controller]); + } + function convertReadableStreamType(type, context) { + type = `${type}`; + if (type !== 'bytes') { + throw new TypeError(`${context} '${type}' is not a valid enumeration value for ReadableStreamType`); + } + return type; + } + + function convertReaderOptions(options, context) { + assertDictionary(options, context); + const mode = options === null || options === void 0 ? void 0 : options.mode; + return { + mode: mode === undefined ? undefined : convertReadableStreamReaderMode(mode, `${context} has member 'mode' that`) + }; + } + function convertReadableStreamReaderMode(mode, context) { + mode = `${mode}`; + if (mode !== 'byob') { + throw new TypeError(`${context} '${mode}' is not a valid enumeration value for ReadableStreamReaderMode`); + } + return mode; + } + + function convertIteratorOptions(options, context) { + assertDictionary(options, context); + const preventCancel = options === null || options === void 0 ? void 0 : options.preventCancel; + return { preventCancel: Boolean(preventCancel) }; + } + + function convertPipeOptions(options, context) { + assertDictionary(options, context); + const preventAbort = options === null || options === void 0 ? void 0 : options.preventAbort; + const preventCancel = options === null || options === void 0 ? void 0 : options.preventCancel; + const preventClose = options === null || options === void 0 ? void 0 : options.preventClose; + const signal = options === null || options === void 0 ? void 0 : options.signal; + if (signal !== undefined) { + assertAbortSignal(signal, `${context} has member 'signal' that`); + } + return { + preventAbort: Boolean(preventAbort), + preventCancel: Boolean(preventCancel), + preventClose: Boolean(preventClose), + signal + }; + } + function assertAbortSignal(signal, context) { + if (!isAbortSignal(signal)) { + throw new TypeError(`${context} is not an AbortSignal.`); + } + } + + function convertReadableWritablePair(pair, context) { + assertDictionary(pair, context); + const readable = pair === null || pair === void 0 ? void 0 : pair.readable; + assertRequiredField(readable, 'readable', 'ReadableWritablePair'); + assertReadableStream(readable, `${context} has member 'readable' that`); + const writable = pair === null || pair === void 0 ? void 0 : pair.writable; + assertRequiredField(writable, 'writable', 'ReadableWritablePair'); + assertWritableStream(writable, `${context} has member 'writable' that`); + return { readable, writable }; + } + + /** + * A readable stream represents a source of data, from which you can read. + * + * @public + */ + class ReadableStream$1 { + constructor(rawUnderlyingSource = {}, rawStrategy = {}) { + if (rawUnderlyingSource === undefined) { + rawUnderlyingSource = null; + } + else { + assertObject(rawUnderlyingSource, 'First parameter'); + } + const strategy = convertQueuingStrategy(rawStrategy, 'Second parameter'); + const underlyingSource = convertUnderlyingDefaultOrByteSource(rawUnderlyingSource, 'First parameter'); + InitializeReadableStream(this); + if (underlyingSource.type === 'bytes') { + if (strategy.size !== undefined) { + throw new RangeError('The strategy for a byte stream cannot have a size function'); + } + const highWaterMark = ExtractHighWaterMark(strategy, 0); + SetUpReadableByteStreamControllerFromUnderlyingSource(this, underlyingSource, highWaterMark); + } + else { + const sizeAlgorithm = ExtractSizeAlgorithm(strategy); + const highWaterMark = ExtractHighWaterMark(strategy, 1); + SetUpReadableStreamDefaultControllerFromUnderlyingSource(this, underlyingSource, highWaterMark, sizeAlgorithm); + } + } + /** + * Whether or not the readable stream is locked to a {@link ReadableStreamDefaultReader | reader}. + */ + get locked() { + if (!IsReadableStream(this)) { + throw streamBrandCheckException$1('locked'); + } + return IsReadableStreamLocked(this); + } + /** + * Cancels the stream, signaling a loss of interest in the stream by a consumer. + * + * The supplied `reason` argument will be given to the underlying source's {@link UnderlyingSource.cancel | cancel()} + * method, which might or might not use it. + */ + cancel(reason = undefined) { + if (!IsReadableStream(this)) { + return promiseRejectedWith(streamBrandCheckException$1('cancel')); + } + if (IsReadableStreamLocked(this)) { + return promiseRejectedWith(new TypeError('Cannot cancel a stream that already has a reader')); + } + return ReadableStreamCancel(this, reason); + } + getReader(rawOptions = undefined) { + if (!IsReadableStream(this)) { + throw streamBrandCheckException$1('getReader'); + } + const options = convertReaderOptions(rawOptions, 'First parameter'); + if (options.mode === undefined) { + return AcquireReadableStreamDefaultReader(this); + } + return AcquireReadableStreamBYOBReader(this); + } + pipeThrough(rawTransform, rawOptions = {}) { + if (!IsReadableStream(this)) { + throw streamBrandCheckException$1('pipeThrough'); + } + assertRequiredArgument(rawTransform, 1, 'pipeThrough'); + const transform = convertReadableWritablePair(rawTransform, 'First parameter'); + const options = convertPipeOptions(rawOptions, 'Second parameter'); + if (IsReadableStreamLocked(this)) { + throw new TypeError('ReadableStream.prototype.pipeThrough cannot be used on a locked ReadableStream'); + } + if (IsWritableStreamLocked(transform.writable)) { + throw new TypeError('ReadableStream.prototype.pipeThrough cannot be used on a locked WritableStream'); + } + const promise = ReadableStreamPipeTo(this, transform.writable, options.preventClose, options.preventAbort, options.preventCancel, options.signal); + setPromiseIsHandledToTrue(promise); + return transform.readable; + } + pipeTo(destination, rawOptions = {}) { + if (!IsReadableStream(this)) { + return promiseRejectedWith(streamBrandCheckException$1('pipeTo')); + } + if (destination === undefined) { + return promiseRejectedWith(`Parameter 1 is required in 'pipeTo'.`); + } + if (!IsWritableStream(destination)) { + return promiseRejectedWith(new TypeError(`ReadableStream.prototype.pipeTo's first argument must be a WritableStream`)); + } + let options; + try { + options = convertPipeOptions(rawOptions, 'Second parameter'); + } + catch (e) { + return promiseRejectedWith(e); + } + if (IsReadableStreamLocked(this)) { + return promiseRejectedWith(new TypeError('ReadableStream.prototype.pipeTo cannot be used on a locked ReadableStream')); + } + if (IsWritableStreamLocked(destination)) { + return promiseRejectedWith(new TypeError('ReadableStream.prototype.pipeTo cannot be used on a locked WritableStream')); + } + return ReadableStreamPipeTo(this, destination, options.preventClose, options.preventAbort, options.preventCancel, options.signal); + } + /** + * Tees this readable stream, returning a two-element array containing the two resulting branches as + * new {@link ReadableStream} instances. + * + * Teeing a stream will lock it, preventing any other consumer from acquiring a reader. + * To cancel the stream, cancel both of the resulting branches; a composite cancellation reason will then be + * propagated to the stream's underlying source. + * + * Note that the chunks seen in each branch will be the same object. If the chunks are not immutable, + * this could allow interference between the two branches. + */ + tee() { + if (!IsReadableStream(this)) { + throw streamBrandCheckException$1('tee'); + } + const branches = ReadableStreamTee(this); + return CreateArrayFromList(branches); + } + values(rawOptions = undefined) { + if (!IsReadableStream(this)) { + throw streamBrandCheckException$1('values'); + } + const options = convertIteratorOptions(rawOptions, 'First parameter'); + return AcquireReadableStreamAsyncIterator(this, options.preventCancel); + } + } + Object.defineProperties(ReadableStream$1.prototype, { + cancel: { enumerable: true }, + getReader: { enumerable: true }, + pipeThrough: { enumerable: true }, + pipeTo: { enumerable: true }, + tee: { enumerable: true }, + values: { enumerable: true }, + locked: { enumerable: true } + }); + if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(ReadableStream$1.prototype, SymbolPolyfill.toStringTag, { + value: 'ReadableStream', + configurable: true + }); + } + if (typeof SymbolPolyfill.asyncIterator === 'symbol') { + Object.defineProperty(ReadableStream$1.prototype, SymbolPolyfill.asyncIterator, { + value: ReadableStream$1.prototype.values, + writable: true, + configurable: true + }); + } + // Abstract operations for the ReadableStream. + // Throws if and only if startAlgorithm throws. + function CreateReadableStream(startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark = 1, sizeAlgorithm = () => 1) { + const stream = Object.create(ReadableStream$1.prototype); + InitializeReadableStream(stream); + const controller = Object.create(ReadableStreamDefaultController.prototype); + SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm); + return stream; + } + function InitializeReadableStream(stream) { + stream._state = 'readable'; + stream._reader = undefined; + stream._storedError = undefined; + stream._disturbed = false; + } + function IsReadableStream(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_readableStreamController')) { + return false; + } + return true; + } + function IsReadableStreamLocked(stream) { + if (stream._reader === undefined) { + return false; + } + return true; + } + // ReadableStream API exposed for controllers. + function ReadableStreamCancel(stream, reason) { + stream._disturbed = true; + if (stream._state === 'closed') { + return promiseResolvedWith(undefined); + } + if (stream._state === 'errored') { + return promiseRejectedWith(stream._storedError); + } + ReadableStreamClose(stream); + const sourceCancelPromise = stream._readableStreamController[CancelSteps](reason); + return transformPromiseWith(sourceCancelPromise, noop); + } + function ReadableStreamClose(stream) { + stream._state = 'closed'; + const reader = stream._reader; + if (reader === undefined) { + return; + } + defaultReaderClosedPromiseResolve(reader); + if (IsReadableStreamDefaultReader(reader)) { + reader._readRequests.forEach(readRequest => { + readRequest._closeSteps(); + }); + reader._readRequests = new SimpleQueue(); + } + } + function ReadableStreamError(stream, e) { + stream._state = 'errored'; + stream._storedError = e; + const reader = stream._reader; + if (reader === undefined) { + return; + } + defaultReaderClosedPromiseReject(reader, e); + if (IsReadableStreamDefaultReader(reader)) { + reader._readRequests.forEach(readRequest => { + readRequest._errorSteps(e); + }); + reader._readRequests = new SimpleQueue(); + } + else { + reader._readIntoRequests.forEach(readIntoRequest => { + readIntoRequest._errorSteps(e); + }); + reader._readIntoRequests = new SimpleQueue(); + } + } + // Helper functions for the ReadableStream. + function streamBrandCheckException$1(name) { + return new TypeError(`ReadableStream.prototype.${name} can only be used on a ReadableStream`); + } + + function convertQueuingStrategyInit(init, context) { + assertDictionary(init, context); + const highWaterMark = init === null || init === void 0 ? void 0 : init.highWaterMark; + assertRequiredField(highWaterMark, 'highWaterMark', 'QueuingStrategyInit'); + return { + highWaterMark: convertUnrestrictedDouble(highWaterMark) + }; + } + + const byteLengthSizeFunction = function size(chunk) { + return chunk.byteLength; + }; + /** + * A queuing strategy that counts the number of bytes in each chunk. + * + * @public + */ + class ByteLengthQueuingStrategy { + constructor(options) { + assertRequiredArgument(options, 1, 'ByteLengthQueuingStrategy'); + options = convertQueuingStrategyInit(options, 'First parameter'); + this._byteLengthQueuingStrategyHighWaterMark = options.highWaterMark; + } + /** + * Returns the high water mark provided to the constructor. + */ + get highWaterMark() { + if (!IsByteLengthQueuingStrategy(this)) { + throw byteLengthBrandCheckException('highWaterMark'); + } + return this._byteLengthQueuingStrategyHighWaterMark; + } + /** + * Measures the size of `chunk` by returning the value of its `byteLength` property. + */ + get size() { + if (!IsByteLengthQueuingStrategy(this)) { + throw byteLengthBrandCheckException('size'); + } + return byteLengthSizeFunction; + } + } + Object.defineProperties(ByteLengthQueuingStrategy.prototype, { + highWaterMark: { enumerable: true }, + size: { enumerable: true } + }); + if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(ByteLengthQueuingStrategy.prototype, SymbolPolyfill.toStringTag, { + value: 'ByteLengthQueuingStrategy', + configurable: true + }); + } + // Helper functions for the ByteLengthQueuingStrategy. + function byteLengthBrandCheckException(name) { + return new TypeError(`ByteLengthQueuingStrategy.prototype.${name} can only be used on a ByteLengthQueuingStrategy`); + } + function IsByteLengthQueuingStrategy(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_byteLengthQueuingStrategyHighWaterMark')) { + return false; + } + return true; + } + + const countSizeFunction = function size() { + return 1; + }; + /** + * A queuing strategy that counts the number of chunks. + * + * @public + */ + class CountQueuingStrategy { + constructor(options) { + assertRequiredArgument(options, 1, 'CountQueuingStrategy'); + options = convertQueuingStrategyInit(options, 'First parameter'); + this._countQueuingStrategyHighWaterMark = options.highWaterMark; + } + /** + * Returns the high water mark provided to the constructor. + */ + get highWaterMark() { + if (!IsCountQueuingStrategy(this)) { + throw countBrandCheckException('highWaterMark'); + } + return this._countQueuingStrategyHighWaterMark; + } + /** + * Measures the size of `chunk` by always returning 1. + * This ensures that the total queue size is a count of the number of chunks in the queue. + */ + get size() { + if (!IsCountQueuingStrategy(this)) { + throw countBrandCheckException('size'); + } + return countSizeFunction; + } + } + Object.defineProperties(CountQueuingStrategy.prototype, { + highWaterMark: { enumerable: true }, + size: { enumerable: true } + }); + if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(CountQueuingStrategy.prototype, SymbolPolyfill.toStringTag, { + value: 'CountQueuingStrategy', + configurable: true + }); + } + // Helper functions for the CountQueuingStrategy. + function countBrandCheckException(name) { + return new TypeError(`CountQueuingStrategy.prototype.${name} can only be used on a CountQueuingStrategy`); + } + function IsCountQueuingStrategy(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_countQueuingStrategyHighWaterMark')) { + return false; + } + return true; + } + + function convertTransformer(original, context) { + assertDictionary(original, context); + const flush = original === null || original === void 0 ? void 0 : original.flush; + const readableType = original === null || original === void 0 ? void 0 : original.readableType; + const start = original === null || original === void 0 ? void 0 : original.start; + const transform = original === null || original === void 0 ? void 0 : original.transform; + const writableType = original === null || original === void 0 ? void 0 : original.writableType; + return { + flush: flush === undefined ? + undefined : + convertTransformerFlushCallback(flush, original, `${context} has member 'flush' that`), + readableType, + start: start === undefined ? + undefined : + convertTransformerStartCallback(start, original, `${context} has member 'start' that`), + transform: transform === undefined ? + undefined : + convertTransformerTransformCallback(transform, original, `${context} has member 'transform' that`), + writableType + }; + } + function convertTransformerFlushCallback(fn, original, context) { + assertFunction(fn, context); + return (controller) => promiseCall(fn, original, [controller]); + } + function convertTransformerStartCallback(fn, original, context) { + assertFunction(fn, context); + return (controller) => reflectCall(fn, original, [controller]); + } + function convertTransformerTransformCallback(fn, original, context) { + assertFunction(fn, context); + return (chunk, controller) => promiseCall(fn, original, [chunk, controller]); + } + + // Class TransformStream + /** + * A transform stream consists of a pair of streams: a {@link WritableStream | writable stream}, + * known as its writable side, and a {@link ReadableStream | readable stream}, known as its readable side. + * In a manner specific to the transform stream in question, writes to the writable side result in new data being + * made available for reading from the readable side. + * + * @public + */ + class TransformStream$1 { + constructor(rawTransformer = {}, rawWritableStrategy = {}, rawReadableStrategy = {}) { + if (rawTransformer === undefined) { + rawTransformer = null; + } + const writableStrategy = convertQueuingStrategy(rawWritableStrategy, 'Second parameter'); + const readableStrategy = convertQueuingStrategy(rawReadableStrategy, 'Third parameter'); + const transformer = convertTransformer(rawTransformer, 'First parameter'); + if (transformer.readableType !== undefined) { + throw new RangeError('Invalid readableType specified'); + } + if (transformer.writableType !== undefined) { + throw new RangeError('Invalid writableType specified'); + } + const readableHighWaterMark = ExtractHighWaterMark(readableStrategy, 0); + const readableSizeAlgorithm = ExtractSizeAlgorithm(readableStrategy); + const writableHighWaterMark = ExtractHighWaterMark(writableStrategy, 1); + const writableSizeAlgorithm = ExtractSizeAlgorithm(writableStrategy); + let startPromise_resolve; + const startPromise = newPromise(resolve => { + startPromise_resolve = resolve; + }); + InitializeTransformStream(this, startPromise, writableHighWaterMark, writableSizeAlgorithm, readableHighWaterMark, readableSizeAlgorithm); + SetUpTransformStreamDefaultControllerFromTransformer(this, transformer); + if (transformer.start !== undefined) { + startPromise_resolve(transformer.start(this._transformStreamController)); + } + else { + startPromise_resolve(undefined); + } + } + /** + * The readable side of the transform stream. + */ + get readable() { + if (!IsTransformStream(this)) { + throw streamBrandCheckException('readable'); + } + return this._readable; + } + /** + * The writable side of the transform stream. + */ + get writable() { + if (!IsTransformStream(this)) { + throw streamBrandCheckException('writable'); + } + return this._writable; + } + } + Object.defineProperties(TransformStream$1.prototype, { + readable: { enumerable: true }, + writable: { enumerable: true } + }); + if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(TransformStream$1.prototype, SymbolPolyfill.toStringTag, { + value: 'TransformStream', + configurable: true + }); + } + function InitializeTransformStream(stream, startPromise, writableHighWaterMark, writableSizeAlgorithm, readableHighWaterMark, readableSizeAlgorithm) { + function startAlgorithm() { + return startPromise; + } + function writeAlgorithm(chunk) { + return TransformStreamDefaultSinkWriteAlgorithm(stream, chunk); + } + function abortAlgorithm(reason) { + return TransformStreamDefaultSinkAbortAlgorithm(stream, reason); + } + function closeAlgorithm() { + return TransformStreamDefaultSinkCloseAlgorithm(stream); + } + stream._writable = CreateWritableStream(startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, writableHighWaterMark, writableSizeAlgorithm); + function pullAlgorithm() { + return TransformStreamDefaultSourcePullAlgorithm(stream); + } + function cancelAlgorithm(reason) { + TransformStreamErrorWritableAndUnblockWrite(stream, reason); + return promiseResolvedWith(undefined); + } + stream._readable = CreateReadableStream(startAlgorithm, pullAlgorithm, cancelAlgorithm, readableHighWaterMark, readableSizeAlgorithm); + // The [[backpressure]] slot is set to undefined so that it can be initialised by TransformStreamSetBackpressure. + stream._backpressure = undefined; + stream._backpressureChangePromise = undefined; + stream._backpressureChangePromise_resolve = undefined; + TransformStreamSetBackpressure(stream, true); + stream._transformStreamController = undefined; + } + function IsTransformStream(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_transformStreamController')) { + return false; + } + return true; + } + // This is a no-op if both sides are already errored. + function TransformStreamError(stream, e) { + ReadableStreamDefaultControllerError(stream._readable._readableStreamController, e); + TransformStreamErrorWritableAndUnblockWrite(stream, e); + } + function TransformStreamErrorWritableAndUnblockWrite(stream, e) { + TransformStreamDefaultControllerClearAlgorithms(stream._transformStreamController); + WritableStreamDefaultControllerErrorIfNeeded(stream._writable._writableStreamController, e); + if (stream._backpressure) { + // Pretend that pull() was called to permit any pending write() calls to complete. TransformStreamSetBackpressure() + // cannot be called from enqueue() or pull() once the ReadableStream is errored, so this will will be the final time + // _backpressure is set. + TransformStreamSetBackpressure(stream, false); + } + } + function TransformStreamSetBackpressure(stream, backpressure) { + // Passes also when called during construction. + if (stream._backpressureChangePromise !== undefined) { + stream._backpressureChangePromise_resolve(); + } + stream._backpressureChangePromise = newPromise(resolve => { + stream._backpressureChangePromise_resolve = resolve; + }); + stream._backpressure = backpressure; + } + // Class TransformStreamDefaultController + /** + * Allows control of the {@link ReadableStream} and {@link WritableStream} of the associated {@link TransformStream}. + * + * @public + */ + class TransformStreamDefaultController { + constructor() { + throw new TypeError('Illegal constructor'); + } + /** + * Returns the desired size to fill the readable side’s internal queue. It can be negative, if the queue is over-full. + */ + get desiredSize() { + if (!IsTransformStreamDefaultController(this)) { + throw defaultControllerBrandCheckException('desiredSize'); + } + const readableController = this._controlledTransformStream._readable._readableStreamController; + return ReadableStreamDefaultControllerGetDesiredSize(readableController); + } + enqueue(chunk = undefined) { + if (!IsTransformStreamDefaultController(this)) { + throw defaultControllerBrandCheckException('enqueue'); + } + TransformStreamDefaultControllerEnqueue(this, chunk); + } + /** + * Errors both the readable side and the writable side of the controlled transform stream, making all future + * interactions with it fail with the given error `e`. Any chunks queued for transformation will be discarded. + */ + error(reason = undefined) { + if (!IsTransformStreamDefaultController(this)) { + throw defaultControllerBrandCheckException('error'); + } + TransformStreamDefaultControllerError(this, reason); + } + /** + * Closes the readable side and errors the writable side of the controlled transform stream. This is useful when the + * transformer only needs to consume a portion of the chunks written to the writable side. + */ + terminate() { + if (!IsTransformStreamDefaultController(this)) { + throw defaultControllerBrandCheckException('terminate'); + } + TransformStreamDefaultControllerTerminate(this); + } + } + Object.defineProperties(TransformStreamDefaultController.prototype, { + enqueue: { enumerable: true }, + error: { enumerable: true }, + terminate: { enumerable: true }, + desiredSize: { enumerable: true } + }); + if (typeof SymbolPolyfill.toStringTag === 'symbol') { + Object.defineProperty(TransformStreamDefaultController.prototype, SymbolPolyfill.toStringTag, { + value: 'TransformStreamDefaultController', + configurable: true + }); + } + // Transform Stream Default Controller Abstract Operations + function IsTransformStreamDefaultController(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_controlledTransformStream')) { + return false; + } + return true; + } + function SetUpTransformStreamDefaultController(stream, controller, transformAlgorithm, flushAlgorithm) { + controller._controlledTransformStream = stream; + stream._transformStreamController = controller; + controller._transformAlgorithm = transformAlgorithm; + controller._flushAlgorithm = flushAlgorithm; + } + function SetUpTransformStreamDefaultControllerFromTransformer(stream, transformer) { + const controller = Object.create(TransformStreamDefaultController.prototype); + let transformAlgorithm = (chunk) => { + try { + TransformStreamDefaultControllerEnqueue(controller, chunk); + return promiseResolvedWith(undefined); + } + catch (transformResultE) { + return promiseRejectedWith(transformResultE); + } + }; + let flushAlgorithm = () => promiseResolvedWith(undefined); + if (transformer.transform !== undefined) { + transformAlgorithm = chunk => transformer.transform(chunk, controller); + } + if (transformer.flush !== undefined) { + flushAlgorithm = () => transformer.flush(controller); + } + SetUpTransformStreamDefaultController(stream, controller, transformAlgorithm, flushAlgorithm); + } + function TransformStreamDefaultControllerClearAlgorithms(controller) { + controller._transformAlgorithm = undefined; + controller._flushAlgorithm = undefined; + } + function TransformStreamDefaultControllerEnqueue(controller, chunk) { + const stream = controller._controlledTransformStream; + const readableController = stream._readable._readableStreamController; + if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(readableController)) { + throw new TypeError('Readable side is not in a state that permits enqueue'); + } + // We throttle transform invocations based on the backpressure of the ReadableStream, but we still + // accept TransformStreamDefaultControllerEnqueue() calls. + try { + ReadableStreamDefaultControllerEnqueue(readableController, chunk); + } + catch (e) { + // This happens when readableStrategy.size() throws. + TransformStreamErrorWritableAndUnblockWrite(stream, e); + throw stream._readable._storedError; + } + const backpressure = ReadableStreamDefaultControllerHasBackpressure(readableController); + if (backpressure !== stream._backpressure) { + TransformStreamSetBackpressure(stream, true); + } + } + function TransformStreamDefaultControllerError(controller, e) { + TransformStreamError(controller._controlledTransformStream, e); + } + function TransformStreamDefaultControllerPerformTransform(controller, chunk) { + const transformPromise = controller._transformAlgorithm(chunk); + return transformPromiseWith(transformPromise, undefined, r => { + TransformStreamError(controller._controlledTransformStream, r); + throw r; + }); + } + function TransformStreamDefaultControllerTerminate(controller) { + const stream = controller._controlledTransformStream; + const readableController = stream._readable._readableStreamController; + ReadableStreamDefaultControllerClose(readableController); + const error = new TypeError('TransformStream terminated'); + TransformStreamErrorWritableAndUnblockWrite(stream, error); + } + // TransformStreamDefaultSink Algorithms + function TransformStreamDefaultSinkWriteAlgorithm(stream, chunk) { + const controller = stream._transformStreamController; + if (stream._backpressure) { + const backpressureChangePromise = stream._backpressureChangePromise; + return transformPromiseWith(backpressureChangePromise, () => { + const writable = stream._writable; + const state = writable._state; + if (state === 'erroring') { + throw writable._storedError; + } + return TransformStreamDefaultControllerPerformTransform(controller, chunk); + }); + } + return TransformStreamDefaultControllerPerformTransform(controller, chunk); + } + function TransformStreamDefaultSinkAbortAlgorithm(stream, reason) { + // abort() is not called synchronously, so it is possible for abort() to be called when the stream is already + // errored. + TransformStreamError(stream, reason); + return promiseResolvedWith(undefined); + } + function TransformStreamDefaultSinkCloseAlgorithm(stream) { + // stream._readable cannot change after construction, so caching it across a call to user code is safe. + const readable = stream._readable; + const controller = stream._transformStreamController; + const flushPromise = controller._flushAlgorithm(); + TransformStreamDefaultControllerClearAlgorithms(controller); + // Return a promise that is fulfilled with undefined on success. + return transformPromiseWith(flushPromise, () => { + if (readable._state === 'errored') { + throw readable._storedError; + } + ReadableStreamDefaultControllerClose(readable._readableStreamController); + }, r => { + TransformStreamError(stream, r); + throw readable._storedError; + }); + } + // TransformStreamDefaultSource Algorithms + function TransformStreamDefaultSourcePullAlgorithm(stream) { + // Invariant. Enforced by the promises returned by start() and pull(). + TransformStreamSetBackpressure(stream, false); + // Prevent the next pull() call until there is backpressure. + return stream._backpressureChangePromise; + } + // Helper functions for the TransformStreamDefaultController. + function defaultControllerBrandCheckException(name) { + return new TypeError(`TransformStreamDefaultController.prototype.${name} can only be used on a TransformStreamDefaultController`); + } + // Helper functions for the TransformStream. + function streamBrandCheckException(name) { + return new TypeError(`TransformStream.prototype.${name} can only be used on a TransformStream`); + } + + var ponyfill_es6 = /*#__PURE__*/Object.freeze({ + __proto__: null, + ByteLengthQueuingStrategy: ByteLengthQueuingStrategy, + CountQueuingStrategy: CountQueuingStrategy, + ReadableByteStreamController: ReadableByteStreamController, + ReadableStream: ReadableStream$1, + ReadableStreamBYOBReader: ReadableStreamBYOBReader, + ReadableStreamBYOBRequest: ReadableStreamBYOBRequest, + ReadableStreamDefaultController: ReadableStreamDefaultController, + ReadableStreamDefaultReader: ReadableStreamDefaultReader, + TransformStream: TransformStream$1, + TransformStreamDefaultController: TransformStreamDefaultController, + WritableStream: WritableStream$1, + WritableStreamDefaultController: WritableStreamDefaultController, + WritableStreamDefaultWriter: WritableStreamDefaultWriter + }); + + /*! ***************************************************************************** + Copyright (c) Microsoft Corporation. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + PERFORMANCE OF THIS SOFTWARE. + ***************************************************************************** */ + /* global Reflect, Promise */ + + var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + + function __extends(d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + } + + function assert$1(test) { + if (!test) { + throw new TypeError('Assertion failed'); + } + } + + function noop$1() { + return; + } + function typeIsObject$1(x) { + return (typeof x === 'object' && x !== null) || typeof x === 'function'; + } + + function isStreamConstructor(ctor) { + if (typeof ctor !== 'function') { + return false; + } + var startCalled = false; + try { + new ctor({ + start: function () { + startCalled = true; + } + }); + } + catch (e) { + // ignore + } + return startCalled; + } + function isReadableStream(readable) { + if (!typeIsObject$1(readable)) { + return false; + } + if (typeof readable.getReader !== 'function') { + return false; + } + return true; + } + function isReadableStreamConstructor(ctor) { + if (!isStreamConstructor(ctor)) { + return false; + } + if (!isReadableStream(new ctor())) { + return false; + } + return true; + } + function isWritableStream(writable) { + if (!typeIsObject$1(writable)) { + return false; + } + if (typeof writable.getWriter !== 'function') { + return false; + } + return true; + } + function isWritableStreamConstructor(ctor) { + if (!isStreamConstructor(ctor)) { + return false; + } + if (!isWritableStream(new ctor())) { + return false; + } + return true; + } + function isTransformStream(transform) { + if (!typeIsObject$1(transform)) { + return false; + } + if (!isReadableStream(transform.readable)) { + return false; + } + if (!isWritableStream(transform.writable)) { + return false; + } + return true; + } + function isTransformStreamConstructor(ctor) { + if (!isStreamConstructor(ctor)) { + return false; + } + if (!isTransformStream(new ctor())) { + return false; + } + return true; + } + function supportsByobReader(readable) { + try { + var reader = readable.getReader({ mode: 'byob' }); + reader.releaseLock(); + return true; + } + catch (_a) { + return false; + } + } + function supportsByteSource(ctor) { + try { + new ctor({ type: 'bytes' }); + return true; + } + catch (_a) { + return false; + } + } + + function createReadableStreamWrapper(ctor) { + assert$1(isReadableStreamConstructor(ctor)); + var byteSourceSupported = supportsByteSource(ctor); + return function (readable, _a) { + var _b = _a === void 0 ? {} : _a, type = _b.type; + type = parseReadableType(type); + if (type === 'bytes' && !byteSourceSupported) { + type = undefined; + } + if (readable.constructor === ctor) { + if (type !== 'bytes' || supportsByobReader(readable)) { + return readable; + } + } + if (type === 'bytes') { + var source = createWrappingReadableSource(readable, { type: type }); + return new ctor(source); + } + else { + var source = createWrappingReadableSource(readable); + return new ctor(source); + } + }; + } + function createWrappingReadableSource(readable, _a) { + var _b = _a === void 0 ? {} : _a, type = _b.type; + assert$1(isReadableStream(readable)); + assert$1(readable.locked === false); + type = parseReadableType(type); + var source; + if (type === 'bytes') { + source = new WrappingReadableByteStreamSource(readable); + } + else { + source = new WrappingReadableStreamDefaultSource(readable); + } + return source; + } + function parseReadableType(type) { + var typeString = String(type); + if (typeString === 'bytes') { + return typeString; + } + else if (type === undefined) { + return type; + } + else { + throw new RangeError('Invalid type is specified'); + } + } + var AbstractWrappingReadableStreamSource = /** @class */ (function () { + function AbstractWrappingReadableStreamSource(underlyingStream) { + this._underlyingReader = undefined; + this._readerMode = undefined; + this._readableStreamController = undefined; + this._pendingRead = undefined; + this._underlyingStream = underlyingStream; + // always keep a reader attached to detect close/error + this._attachDefaultReader(); + } + AbstractWrappingReadableStreamSource.prototype.start = function (controller) { + this._readableStreamController = controller; + }; + AbstractWrappingReadableStreamSource.prototype.cancel = function (reason) { + assert$1(this._underlyingReader !== undefined); + return this._underlyingReader.cancel(reason); + }; + AbstractWrappingReadableStreamSource.prototype._attachDefaultReader = function () { + if (this._readerMode === "default" /* DEFAULT */) { + return; + } + this._detachReader(); + var reader = this._underlyingStream.getReader(); + this._readerMode = "default" /* DEFAULT */; + this._attachReader(reader); + }; + AbstractWrappingReadableStreamSource.prototype._attachReader = function (reader) { + var _this = this; + assert$1(this._underlyingReader === undefined); + this._underlyingReader = reader; + var closed = this._underlyingReader.closed; + if (!closed) { + return; + } + closed + .then(function () { return _this._finishPendingRead(); }) + .then(function () { + if (reader === _this._underlyingReader) { + _this._readableStreamController.close(); + } + }, function (reason) { + if (reader === _this._underlyingReader) { + _this._readableStreamController.error(reason); + } + }) + .catch(noop$1); + }; + AbstractWrappingReadableStreamSource.prototype._detachReader = function () { + if (this._underlyingReader === undefined) { + return; + } + this._underlyingReader.releaseLock(); + this._underlyingReader = undefined; + this._readerMode = undefined; + }; + AbstractWrappingReadableStreamSource.prototype._pullWithDefaultReader = function () { + var _this = this; + this._attachDefaultReader(); + // TODO Backpressure? + var read = this._underlyingReader.read() + .then(function (result) { + var controller = _this._readableStreamController; + if (result.done) { + _this._tryClose(); + } + else { + controller.enqueue(result.value); + } + }); + this._setPendingRead(read); + return read; + }; + AbstractWrappingReadableStreamSource.prototype._tryClose = function () { + try { + this._readableStreamController.close(); + } + catch (_a) { + // already errored or closed + } + }; + AbstractWrappingReadableStreamSource.prototype._setPendingRead = function (readPromise) { + var _this = this; + var pendingRead; + var finishRead = function () { + if (_this._pendingRead === pendingRead) { + _this._pendingRead = undefined; + } + }; + this._pendingRead = pendingRead = readPromise.then(finishRead, finishRead); + }; + AbstractWrappingReadableStreamSource.prototype._finishPendingRead = function () { + var _this = this; + if (!this._pendingRead) { + return undefined; + } + var afterRead = function () { return _this._finishPendingRead(); }; + return this._pendingRead.then(afterRead, afterRead); + }; + return AbstractWrappingReadableStreamSource; + }()); + var WrappingReadableStreamDefaultSource = /** @class */ (function (_super) { + __extends(WrappingReadableStreamDefaultSource, _super); + function WrappingReadableStreamDefaultSource() { + return _super !== null && _super.apply(this, arguments) || this; + } + WrappingReadableStreamDefaultSource.prototype.pull = function () { + return this._pullWithDefaultReader(); + }; + return WrappingReadableStreamDefaultSource; + }(AbstractWrappingReadableStreamSource)); + function toUint8Array(view) { + return new Uint8Array(view.buffer, view.byteOffset, view.byteLength); + } + function copyArrayBufferView(from, to) { + var fromArray = toUint8Array(from); + var toArray = toUint8Array(to); + toArray.set(fromArray, 0); + } + var WrappingReadableByteStreamSource = /** @class */ (function (_super) { + __extends(WrappingReadableByteStreamSource, _super); + function WrappingReadableByteStreamSource(underlyingStream) { + var _this = this; + var supportsByob = supportsByobReader(underlyingStream); + _this = _super.call(this, underlyingStream) || this; + _this._supportsByob = supportsByob; + return _this; + } + Object.defineProperty(WrappingReadableByteStreamSource.prototype, "type", { + get: function () { + return 'bytes'; + }, + enumerable: false, + configurable: true + }); + WrappingReadableByteStreamSource.prototype._attachByobReader = function () { + if (this._readerMode === "byob" /* BYOB */) { + return; + } + assert$1(this._supportsByob); + this._detachReader(); + var reader = this._underlyingStream.getReader({ mode: 'byob' }); + this._readerMode = "byob" /* BYOB */; + this._attachReader(reader); + }; + WrappingReadableByteStreamSource.prototype.pull = function () { + if (this._supportsByob) { + var byobRequest = this._readableStreamController.byobRequest; + if (byobRequest) { + return this._pullWithByobRequest(byobRequest); + } + } + return this._pullWithDefaultReader(); + }; + WrappingReadableByteStreamSource.prototype._pullWithByobRequest = function (byobRequest) { + var _this = this; + this._attachByobReader(); + // reader.read(view) detaches the input view, therefore we cannot pass byobRequest.view directly + // create a separate buffer to read into, then copy that to byobRequest.view + var buffer = new Uint8Array(byobRequest.view.byteLength); + // TODO Backpressure? + var read = this._underlyingReader.read(buffer) + .then(function (result) { + _this._readableStreamController; + if (result.done) { + _this._tryClose(); + byobRequest.respond(0); + } + else { + copyArrayBufferView(result.value, byobRequest.view); + byobRequest.respond(result.value.byteLength); + } + }); + this._setPendingRead(read); + return read; + }; + return WrappingReadableByteStreamSource; + }(AbstractWrappingReadableStreamSource)); + + function createWritableStreamWrapper(ctor) { + assert$1(isWritableStreamConstructor(ctor)); + return function (writable) { + if (writable.constructor === ctor) { + return writable; + } + var sink = createWrappingWritableSink(writable); + return new ctor(sink); + }; + } + function createWrappingWritableSink(writable) { + assert$1(isWritableStream(writable)); + assert$1(writable.locked === false); + var writer = writable.getWriter(); + return new WrappingWritableStreamSink(writer); + } + var WrappingWritableStreamSink = /** @class */ (function () { + function WrappingWritableStreamSink(underlyingWriter) { + var _this = this; + this._writableStreamController = undefined; + this._pendingWrite = undefined; + this._state = "writable" /* WRITABLE */; + this._storedError = undefined; + this._underlyingWriter = underlyingWriter; + this._errorPromise = new Promise(function (resolve, reject) { + _this._errorPromiseReject = reject; + }); + this._errorPromise.catch(noop$1); + } + WrappingWritableStreamSink.prototype.start = function (controller) { + var _this = this; + this._writableStreamController = controller; + this._underlyingWriter.closed + .then(function () { + _this._state = "closed" /* CLOSED */; + }) + .catch(function (reason) { return _this._finishErroring(reason); }); + }; + WrappingWritableStreamSink.prototype.write = function (chunk) { + var _this = this; + var writer = this._underlyingWriter; + // Detect past errors + if (writer.desiredSize === null) { + return writer.ready; + } + var writeRequest = writer.write(chunk); + // Detect future errors + writeRequest.catch(function (reason) { return _this._finishErroring(reason); }); + writer.ready.catch(function (reason) { return _this._startErroring(reason); }); + // Reject write when errored + var write = Promise.race([writeRequest, this._errorPromise]); + this._setPendingWrite(write); + return write; + }; + WrappingWritableStreamSink.prototype.close = function () { + var _this = this; + if (this._pendingWrite === undefined) { + return this._underlyingWriter.close(); + } + return this._finishPendingWrite().then(function () { return _this.close(); }); + }; + WrappingWritableStreamSink.prototype.abort = function (reason) { + if (this._state === "errored" /* ERRORED */) { + return undefined; + } + var writer = this._underlyingWriter; + return writer.abort(reason); + }; + WrappingWritableStreamSink.prototype._setPendingWrite = function (writePromise) { + var _this = this; + var pendingWrite; + var finishWrite = function () { + if (_this._pendingWrite === pendingWrite) { + _this._pendingWrite = undefined; + } + }; + this._pendingWrite = pendingWrite = writePromise.then(finishWrite, finishWrite); + }; + WrappingWritableStreamSink.prototype._finishPendingWrite = function () { + var _this = this; + if (this._pendingWrite === undefined) { + return Promise.resolve(); + } + var afterWrite = function () { return _this._finishPendingWrite(); }; + return this._pendingWrite.then(afterWrite, afterWrite); + }; + WrappingWritableStreamSink.prototype._startErroring = function (reason) { + var _this = this; + if (this._state === "writable" /* WRITABLE */) { + this._state = "erroring" /* ERRORING */; + this._storedError = reason; + var afterWrite = function () { return _this._finishErroring(reason); }; + if (this._pendingWrite === undefined) { + afterWrite(); + } + else { + this._finishPendingWrite().then(afterWrite, afterWrite); + } + this._writableStreamController.error(reason); + } + }; + WrappingWritableStreamSink.prototype._finishErroring = function (reason) { + if (this._state === "writable" /* WRITABLE */) { + this._startErroring(reason); + } + if (this._state === "erroring" /* ERRORING */) { + this._state = "errored" /* ERRORED */; + this._errorPromiseReject(this._storedError); + } + }; + return WrappingWritableStreamSink; + }()); + + function createTransformStreamWrapper(ctor) { + assert$1(isTransformStreamConstructor(ctor)); + return function (transform) { + if (transform.constructor === ctor) { + return transform; + } + var transformer = createWrappingTransformer(transform); + return new ctor(transformer); + }; + } + function createWrappingTransformer(transform) { + assert$1(isTransformStream(transform)); + var readable = transform.readable, writable = transform.writable; + assert$1(readable.locked === false); + assert$1(writable.locked === false); + var reader = readable.getReader(); + var writer; + try { + writer = writable.getWriter(); + } + catch (e) { + reader.releaseLock(); // do not leak reader + throw e; + } + return new WrappingTransformStreamTransformer(reader, writer); + } + var WrappingTransformStreamTransformer = /** @class */ (function () { + function WrappingTransformStreamTransformer(reader, writer) { + var _this = this; + this._transformStreamController = undefined; + this._onRead = function (result) { + if (result.done) { + return; + } + _this._transformStreamController.enqueue(result.value); + return _this._reader.read().then(_this._onRead); + }; + this._onError = function (reason) { + _this._flushReject(reason); + _this._transformStreamController.error(reason); + _this._reader.cancel(reason).catch(noop$1); + _this._writer.abort(reason).catch(noop$1); + }; + this._onTerminate = function () { + _this._flushResolve(); + _this._transformStreamController.terminate(); + var error = new TypeError('TransformStream terminated'); + _this._writer.abort(error).catch(noop$1); + }; + this._reader = reader; + this._writer = writer; + this._flushPromise = new Promise(function (resolve, reject) { + _this._flushResolve = resolve; + _this._flushReject = reject; + }); + } + WrappingTransformStreamTransformer.prototype.start = function (controller) { + this._transformStreamController = controller; + this._reader.read() + .then(this._onRead) + .then(this._onTerminate, this._onError); + var readerClosed = this._reader.closed; + if (readerClosed) { + readerClosed + .then(this._onTerminate, this._onError); + } + }; + WrappingTransformStreamTransformer.prototype.transform = function (chunk) { + return this._writer.write(chunk); + }; + WrappingTransformStreamTransformer.prototype.flush = function () { + var _this = this; + return this._writer.close() + .then(function () { return _this._flushPromise; }); + }; + return WrappingTransformStreamTransformer; + }()); + + var webStreamsAdapter = /*#__PURE__*/Object.freeze({ + __proto__: null, + createReadableStreamWrapper: createReadableStreamWrapper, + createTransformStreamWrapper: createTransformStreamWrapper, + createWrappingReadableSource: createWrappingReadableSource, + createWrappingTransformer: createWrappingTransformer, + createWrappingWritableSink: createWrappingWritableSink, + createWritableStreamWrapper: createWritableStreamWrapper + }); + + var bn = createCommonjsModule(function (module) { + (function (module, exports) { + + // Utils + function assert (val, msg) { + if (!val) throw new Error(msg || 'Assertion failed'); + } + + // Could use `inherits` module, but don't want to move from single file + // architecture yet. + function inherits (ctor, superCtor) { + ctor.super_ = superCtor; + var TempCtor = function () {}; + TempCtor.prototype = superCtor.prototype; + ctor.prototype = new TempCtor(); + ctor.prototype.constructor = ctor; + } + + // BN + + function BN (number, base, endian) { + if (BN.isBN(number)) { + return number; + } + + this.negative = 0; + this.words = null; + this.length = 0; + + // Reduction context + this.red = null; + + if (number !== null) { + if (base === 'le' || base === 'be') { + endian = base; + base = 10; + } + + this._init(number || 0, base || 10, endian || 'be'); + } + } + if (typeof module === 'object') { + module.exports = BN; + } else { + exports.BN = BN; + } + + BN.BN = BN; + BN.wordSize = 26; + + var Buffer; + try { + Buffer = void('buffer').Buffer; + } catch (e) { + } + + BN.isBN = function isBN (num) { + if (num instanceof BN) { + return true; + } + + return num !== null && typeof num === 'object' && + num.constructor.wordSize === BN.wordSize && Array.isArray(num.words); + }; + + BN.max = function max (left, right) { + if (left.cmp(right) > 0) return left; + return right; + }; + + BN.min = function min (left, right) { + if (left.cmp(right) < 0) return left; + return right; + }; + + BN.prototype._init = function init (number, base, endian) { + if (typeof number === 'number') { + return this._initNumber(number, base, endian); + } + + if (typeof number === 'object') { + return this._initArray(number, base, endian); + } + + if (base === 'hex') { + base = 16; + } + assert(base === (base | 0) && base >= 2 && base <= 36); + + number = number.toString().replace(/\s+/g, ''); + var start = 0; + if (number[0] === '-') { + start++; + } + + if (base === 16) { + this._parseHex(number, start); + } else { + this._parseBase(number, base, start); + } + + if (number[0] === '-') { + this.negative = 1; + } + + this.strip(); + + if (endian !== 'le') return; + + this._initArray(this.toArray(), base, endian); + }; + + BN.prototype._initNumber = function _initNumber (number, base, endian) { + if (number < 0) { + this.negative = 1; + number = -number; + } + if (number < 0x4000000) { + this.words = [ number & 0x3ffffff ]; + this.length = 1; + } else if (number < 0x10000000000000) { + this.words = [ + number & 0x3ffffff, + (number / 0x4000000) & 0x3ffffff + ]; + this.length = 2; + } else { + assert(number < 0x20000000000000); // 2 ^ 53 (unsafe) + this.words = [ + number & 0x3ffffff, + (number / 0x4000000) & 0x3ffffff, + 1 + ]; + this.length = 3; + } + + if (endian !== 'le') return; + + // Reverse the bytes + this._initArray(this.toArray(), base, endian); + }; + + BN.prototype._initArray = function _initArray (number, base, endian) { + // Perhaps a Uint8Array + assert(typeof number.length === 'number'); + if (number.length <= 0) { + this.words = [ 0 ]; + this.length = 1; + return this; + } + + this.length = Math.ceil(number.length / 3); + this.words = new Array(this.length); + for (var i = 0; i < this.length; i++) { + this.words[i] = 0; + } + + var j, w; + var off = 0; + if (endian === 'be') { + for (i = number.length - 1, j = 0; i >= 0; i -= 3) { + w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16); + this.words[j] |= (w << off) & 0x3ffffff; + this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; + off += 24; + if (off >= 26) { + off -= 26; + j++; + } + } + } else if (endian === 'le') { + for (i = 0, j = 0; i < number.length; i += 3) { + w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16); + this.words[j] |= (w << off) & 0x3ffffff; + this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; + off += 24; + if (off >= 26) { + off -= 26; + j++; + } + } + } + return this.strip(); + }; + + function parseHex (str, start, end) { + var r = 0; + var len = Math.min(str.length, end); + for (var i = start; i < len; i++) { + var c = str.charCodeAt(i) - 48; + + r <<= 4; + + // 'a' - 'f' + if (c >= 49 && c <= 54) { + r |= c - 49 + 0xa; + + // 'A' - 'F' + } else if (c >= 17 && c <= 22) { + r |= c - 17 + 0xa; + + // '0' - '9' + } else { + r |= c & 0xf; + } + } + return r; + } + + BN.prototype._parseHex = function _parseHex (number, start) { + // Create possibly bigger array to ensure that it fits the number + this.length = Math.ceil((number.length - start) / 6); + this.words = new Array(this.length); + for (var i = 0; i < this.length; i++) { + this.words[i] = 0; + } + + var j, w; + // Scan 24-bit chunks and add them to the number + var off = 0; + for (i = number.length - 6, j = 0; i >= start; i -= 6) { + w = parseHex(number, i, i + 6); + this.words[j] |= (w << off) & 0x3ffffff; + // NOTE: `0x3fffff` is intentional here, 26bits max shift + 24bit hex limb + this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; + off += 24; + if (off >= 26) { + off -= 26; + j++; + } + } + if (i + 6 !== start) { + w = parseHex(number, start, i + 6); + this.words[j] |= (w << off) & 0x3ffffff; + this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; + } + this.strip(); + }; + + function parseBase (str, start, end, mul) { + var r = 0; + var len = Math.min(str.length, end); + for (var i = start; i < len; i++) { + var c = str.charCodeAt(i) - 48; + + r *= mul; + + // 'a' + if (c >= 49) { + r += c - 49 + 0xa; + + // 'A' + } else if (c >= 17) { + r += c - 17 + 0xa; + + // '0' - '9' + } else { + r += c; + } + } + return r; + } + + BN.prototype._parseBase = function _parseBase (number, base, start) { + // Initialize as zero + this.words = [ 0 ]; + this.length = 1; + + // Find length of limb in base + for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) { + limbLen++; + } + limbLen--; + limbPow = (limbPow / base) | 0; + + var total = number.length - start; + var mod = total % limbLen; + var end = Math.min(total, total - mod) + start; + + var word = 0; + for (var i = start; i < end; i += limbLen) { + word = parseBase(number, i, i + limbLen, base); + + this.imuln(limbPow); + if (this.words[0] + word < 0x4000000) { + this.words[0] += word; + } else { + this._iaddn(word); + } + } + + if (mod !== 0) { + var pow = 1; + word = parseBase(number, i, number.length, base); + + for (i = 0; i < mod; i++) { + pow *= base; + } + + this.imuln(pow); + if (this.words[0] + word < 0x4000000) { + this.words[0] += word; + } else { + this._iaddn(word); + } + } + }; + + BN.prototype.copy = function copy (dest) { + dest.words = new Array(this.length); + for (var i = 0; i < this.length; i++) { + dest.words[i] = this.words[i]; + } + dest.length = this.length; + dest.negative = this.negative; + dest.red = this.red; + }; + + BN.prototype.clone = function clone () { + var r = new BN(null); + this.copy(r); + return r; + }; + + BN.prototype._expand = function _expand (size) { + while (this.length < size) { + this.words[this.length++] = 0; + } + return this; + }; + + // Remove leading `0` from `this` + BN.prototype.strip = function strip () { + while (this.length > 1 && this.words[this.length - 1] === 0) { + this.length--; + } + return this._normSign(); + }; + + BN.prototype._normSign = function _normSign () { + // -0 = 0 + if (this.length === 1 && this.words[0] === 0) { + this.negative = 0; + } + return this; + }; + + BN.prototype.inspect = function inspect () { + return (this.red ? ''; + }; + + /* + + var zeros = []; + var groupSizes = []; + var groupBases = []; + + var s = ''; + var i = -1; + while (++i < BN.wordSize) { + zeros[i] = s; + s += '0'; + } + groupSizes[0] = 0; + groupSizes[1] = 0; + groupBases[0] = 0; + groupBases[1] = 0; + var base = 2 - 1; + while (++base < 36 + 1) { + var groupSize = 0; + var groupBase = 1; + while (groupBase < (1 << BN.wordSize) / base) { + groupBase *= base; + groupSize += 1; + } + groupSizes[base] = groupSize; + groupBases[base] = groupBase; + } + + */ + + var zeros = [ + '', + '0', + '00', + '000', + '0000', + '00000', + '000000', + '0000000', + '00000000', + '000000000', + '0000000000', + '00000000000', + '000000000000', + '0000000000000', + '00000000000000', + '000000000000000', + '0000000000000000', + '00000000000000000', + '000000000000000000', + '0000000000000000000', + '00000000000000000000', + '000000000000000000000', + '0000000000000000000000', + '00000000000000000000000', + '000000000000000000000000', + '0000000000000000000000000' + ]; + + var groupSizes = [ + 0, 0, + 25, 16, 12, 11, 10, 9, 8, + 8, 7, 7, 7, 7, 6, 6, + 6, 6, 6, 6, 6, 5, 5, + 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5 + ]; + + var groupBases = [ + 0, 0, + 33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216, + 43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625, + 16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632, + 6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149, + 24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176 + ]; + + BN.prototype.toString = function toString (base, padding) { + base = base || 10; + padding = padding | 0 || 1; + + var out; + if (base === 16 || base === 'hex') { + out = ''; + var off = 0; + var carry = 0; + for (var i = 0; i < this.length; i++) { + var w = this.words[i]; + var word = (((w << off) | carry) & 0xffffff).toString(16); + carry = (w >>> (24 - off)) & 0xffffff; + if (carry !== 0 || i !== this.length - 1) { + out = zeros[6 - word.length] + word + out; + } else { + out = word + out; + } + off += 2; + if (off >= 26) { + off -= 26; + i--; + } + } + if (carry !== 0) { + out = carry.toString(16) + out; + } + while (out.length % padding !== 0) { + out = '0' + out; + } + if (this.negative !== 0) { + out = '-' + out; + } + return out; + } + + if (base === (base | 0) && base >= 2 && base <= 36) { + // var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base)); + var groupSize = groupSizes[base]; + // var groupBase = Math.pow(base, groupSize); + var groupBase = groupBases[base]; + out = ''; + var c = this.clone(); + c.negative = 0; + while (!c.isZero()) { + var r = c.modn(groupBase).toString(base); + c = c.idivn(groupBase); + + if (!c.isZero()) { + out = zeros[groupSize - r.length] + r + out; + } else { + out = r + out; + } + } + if (this.isZero()) { + out = '0' + out; + } + while (out.length % padding !== 0) { + out = '0' + out; + } + if (this.negative !== 0) { + out = '-' + out; + } + return out; + } + + assert(false, 'Base should be between 2 and 36'); + }; + + BN.prototype.toNumber = function toNumber () { + var ret = this.words[0]; + if (this.length === 2) { + ret += this.words[1] * 0x4000000; + } else if (this.length === 3 && this.words[2] === 0x01) { + // NOTE: at this stage it is known that the top bit is set + ret += 0x10000000000000 + (this.words[1] * 0x4000000); + } else if (this.length > 2) { + assert(false, 'Number can only safely store up to 53 bits'); + } + return (this.negative !== 0) ? -ret : ret; + }; + + BN.prototype.toJSON = function toJSON () { + return this.toString(16); + }; + + BN.prototype.toBuffer = function toBuffer (endian, length) { + assert(typeof Buffer !== 'undefined'); + return this.toArrayLike(Buffer, endian, length); + }; + + BN.prototype.toArray = function toArray (endian, length) { + return this.toArrayLike(Array, endian, length); + }; + + BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) { + var byteLength = this.byteLength(); + var reqLength = length || Math.max(1, byteLength); + assert(byteLength <= reqLength, 'byte array longer than desired length'); + assert(reqLength > 0, 'Requested array length <= 0'); + + this.strip(); + var littleEndian = endian === 'le'; + var res = new ArrayType(reqLength); + + var b, i; + var q = this.clone(); + if (!littleEndian) { + // Assume big-endian + for (i = 0; i < reqLength - byteLength; i++) { + res[i] = 0; + } + + for (i = 0; !q.isZero(); i++) { + b = q.andln(0xff); + q.iushrn(8); + + res[reqLength - i - 1] = b; + } + } else { + for (i = 0; !q.isZero(); i++) { + b = q.andln(0xff); + q.iushrn(8); + + res[i] = b; + } + + for (; i < reqLength; i++) { + res[i] = 0; + } + } + + return res; + }; + + if (Math.clz32) { + BN.prototype._countBits = function _countBits (w) { + return 32 - Math.clz32(w); + }; + } else { + BN.prototype._countBits = function _countBits (w) { + var t = w; + var r = 0; + if (t >= 0x1000) { + r += 13; + t >>>= 13; + } + if (t >= 0x40) { + r += 7; + t >>>= 7; + } + if (t >= 0x8) { + r += 4; + t >>>= 4; + } + if (t >= 0x02) { + r += 2; + t >>>= 2; + } + return r + t; + }; + } + + BN.prototype._zeroBits = function _zeroBits (w) { + // Short-cut + if (w === 0) return 26; + + var t = w; + var r = 0; + if ((t & 0x1fff) === 0) { + r += 13; + t >>>= 13; + } + if ((t & 0x7f) === 0) { + r += 7; + t >>>= 7; + } + if ((t & 0xf) === 0) { + r += 4; + t >>>= 4; + } + if ((t & 0x3) === 0) { + r += 2; + t >>>= 2; + } + if ((t & 0x1) === 0) { + r++; + } + return r; + }; + + // Return number of used bits in a BN + BN.prototype.bitLength = function bitLength () { + var w = this.words[this.length - 1]; + var hi = this._countBits(w); + return (this.length - 1) * 26 + hi; + }; + + function toBitArray (num) { + var w = new Array(num.bitLength()); + + for (var bit = 0; bit < w.length; bit++) { + var off = (bit / 26) | 0; + var wbit = bit % 26; + + w[bit] = (num.words[off] & (1 << wbit)) >>> wbit; + } + + return w; + } + + // Number of trailing zero bits + BN.prototype.zeroBits = function zeroBits () { + if (this.isZero()) return 0; + + var r = 0; + for (var i = 0; i < this.length; i++) { + var b = this._zeroBits(this.words[i]); + r += b; + if (b !== 26) break; + } + return r; + }; + + BN.prototype.byteLength = function byteLength () { + return Math.ceil(this.bitLength() / 8); + }; + + BN.prototype.toTwos = function toTwos (width) { + if (this.negative !== 0) { + return this.abs().inotn(width).iaddn(1); + } + return this.clone(); + }; + + BN.prototype.fromTwos = function fromTwos (width) { + if (this.testn(width - 1)) { + return this.notn(width).iaddn(1).ineg(); + } + return this.clone(); + }; + + BN.prototype.isNeg = function isNeg () { + return this.negative !== 0; + }; + + // Return negative clone of `this` + BN.prototype.neg = function neg () { + return this.clone().ineg(); + }; + + BN.prototype.ineg = function ineg () { + if (!this.isZero()) { + this.negative ^= 1; + } + + return this; + }; + + // Or `num` with `this` in-place + BN.prototype.iuor = function iuor (num) { + while (this.length < num.length) { + this.words[this.length++] = 0; + } + + for (var i = 0; i < num.length; i++) { + this.words[i] = this.words[i] | num.words[i]; + } + + return this.strip(); + }; + + BN.prototype.ior = function ior (num) { + assert((this.negative | num.negative) === 0); + return this.iuor(num); + }; + + // Or `num` with `this` + BN.prototype.or = function or (num) { + if (this.length > num.length) return this.clone().ior(num); + return num.clone().ior(this); + }; + + BN.prototype.uor = function uor (num) { + if (this.length > num.length) return this.clone().iuor(num); + return num.clone().iuor(this); + }; + + // And `num` with `this` in-place + BN.prototype.iuand = function iuand (num) { + // b = min-length(num, this) + var b; + if (this.length > num.length) { + b = num; + } else { + b = this; + } + + for (var i = 0; i < b.length; i++) { + this.words[i] = this.words[i] & num.words[i]; + } + + this.length = b.length; + + return this.strip(); + }; + + BN.prototype.iand = function iand (num) { + assert((this.negative | num.negative) === 0); + return this.iuand(num); + }; + + // And `num` with `this` + BN.prototype.and = function and (num) { + if (this.length > num.length) return this.clone().iand(num); + return num.clone().iand(this); + }; + + BN.prototype.uand = function uand (num) { + if (this.length > num.length) return this.clone().iuand(num); + return num.clone().iuand(this); + }; + + // Xor `num` with `this` in-place + BN.prototype.iuxor = function iuxor (num) { + // a.length > b.length + var a; + var b; + if (this.length > num.length) { + a = this; + b = num; + } else { + a = num; + b = this; + } + + for (var i = 0; i < b.length; i++) { + this.words[i] = a.words[i] ^ b.words[i]; + } + + if (this !== a) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } + } + + this.length = a.length; + + return this.strip(); + }; + + BN.prototype.ixor = function ixor (num) { + assert((this.negative | num.negative) === 0); + return this.iuxor(num); + }; + + // Xor `num` with `this` + BN.prototype.xor = function xor (num) { + if (this.length > num.length) return this.clone().ixor(num); + return num.clone().ixor(this); + }; + + BN.prototype.uxor = function uxor (num) { + if (this.length > num.length) return this.clone().iuxor(num); + return num.clone().iuxor(this); + }; + + // Not ``this`` with ``width`` bitwidth + BN.prototype.inotn = function inotn (width) { + assert(typeof width === 'number' && width >= 0); + + var bytesNeeded = Math.ceil(width / 26) | 0; + var bitsLeft = width % 26; + + // Extend the buffer with leading zeroes + this._expand(bytesNeeded); + + if (bitsLeft > 0) { + bytesNeeded--; + } + + // Handle complete words + for (var i = 0; i < bytesNeeded; i++) { + this.words[i] = ~this.words[i] & 0x3ffffff; + } + + // Handle the residue + if (bitsLeft > 0) { + this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft)); + } + + // And remove leading zeroes + return this.strip(); + }; + + BN.prototype.notn = function notn (width) { + return this.clone().inotn(width); + }; + + // Set `bit` of `this` + BN.prototype.setn = function setn (bit, val) { + assert(typeof bit === 'number' && bit >= 0); + + var off = (bit / 26) | 0; + var wbit = bit % 26; + + this._expand(off + 1); + + if (val) { + this.words[off] = this.words[off] | (1 << wbit); + } else { + this.words[off] = this.words[off] & ~(1 << wbit); + } + + return this.strip(); + }; + + // Add `num` to `this` in-place + BN.prototype.iadd = function iadd (num) { + var r; + + // negative + positive + if (this.negative !== 0 && num.negative === 0) { + this.negative = 0; + r = this.isub(num); + this.negative ^= 1; + return this._normSign(); + + // positive + negative + } else if (this.negative === 0 && num.negative !== 0) { + num.negative = 0; + r = this.isub(num); + num.negative = 1; + return r._normSign(); + } + + // a.length > b.length + var a, b; + if (this.length > num.length) { + a = this; + b = num; + } else { + a = num; + b = this; + } + + var carry = 0; + for (var i = 0; i < b.length; i++) { + r = (a.words[i] | 0) + (b.words[i] | 0) + carry; + this.words[i] = r & 0x3ffffff; + carry = r >>> 26; + } + for (; carry !== 0 && i < a.length; i++) { + r = (a.words[i] | 0) + carry; + this.words[i] = r & 0x3ffffff; + carry = r >>> 26; + } + + this.length = a.length; + if (carry !== 0) { + this.words[this.length] = carry; + this.length++; + // Copy the rest of the words + } else if (a !== this) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } + } + + return this; + }; + + // Add `num` to `this` + BN.prototype.add = function add (num) { + var res; + if (num.negative !== 0 && this.negative === 0) { + num.negative = 0; + res = this.sub(num); + num.negative ^= 1; + return res; + } else if (num.negative === 0 && this.negative !== 0) { + this.negative = 0; + res = num.sub(this); + this.negative = 1; + return res; + } + + if (this.length > num.length) return this.clone().iadd(num); + + return num.clone().iadd(this); + }; + + // Subtract `num` from `this` in-place + BN.prototype.isub = function isub (num) { + // this - (-num) = this + num + if (num.negative !== 0) { + num.negative = 0; + var r = this.iadd(num); + num.negative = 1; + return r._normSign(); + + // -this - num = -(this + num) + } else if (this.negative !== 0) { + this.negative = 0; + this.iadd(num); + this.negative = 1; + return this._normSign(); + } + + // At this point both numbers are positive + var cmp = this.cmp(num); + + // Optimization - zeroify + if (cmp === 0) { + this.negative = 0; + this.length = 1; + this.words[0] = 0; + return this; + } + + // a > b + var a, b; + if (cmp > 0) { + a = this; + b = num; + } else { + a = num; + b = this; + } + + var carry = 0; + for (var i = 0; i < b.length; i++) { + r = (a.words[i] | 0) - (b.words[i] | 0) + carry; + carry = r >> 26; + this.words[i] = r & 0x3ffffff; + } + for (; carry !== 0 && i < a.length; i++) { + r = (a.words[i] | 0) + carry; + carry = r >> 26; + this.words[i] = r & 0x3ffffff; + } + + // Copy rest of the words + if (carry === 0 && i < a.length && a !== this) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } + } + + this.length = Math.max(this.length, i); + + if (a !== this) { + this.negative = 1; + } + + return this.strip(); + }; + + // Subtract `num` from `this` + BN.prototype.sub = function sub (num) { + return this.clone().isub(num); + }; + + function smallMulTo (self, num, out) { + out.negative = num.negative ^ self.negative; + var len = (self.length + num.length) | 0; + out.length = len; + len = (len - 1) | 0; + + // Peel one iteration (compiler can't do it, because of code complexity) + var a = self.words[0] | 0; + var b = num.words[0] | 0; + var r = a * b; + + var lo = r & 0x3ffffff; + var carry = (r / 0x4000000) | 0; + out.words[0] = lo; + + for (var k = 1; k < len; k++) { + // Sum all words with the same `i + j = k` and accumulate `ncarry`, + // note that ncarry could be >= 0x3ffffff + var ncarry = carry >>> 26; + var rword = carry & 0x3ffffff; + var maxJ = Math.min(k, num.length - 1); + for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { + var i = (k - j) | 0; + a = self.words[i] | 0; + b = num.words[j] | 0; + r = a * b + rword; + ncarry += (r / 0x4000000) | 0; + rword = r & 0x3ffffff; + } + out.words[k] = rword | 0; + carry = ncarry | 0; + } + if (carry !== 0) { + out.words[k] = carry | 0; + } else { + out.length--; + } + + return out.strip(); + } + + // TODO(indutny): it may be reasonable to omit it for users who don't need + // to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit + // multiplication (like elliptic secp256k1). + var comb10MulTo = function comb10MulTo (self, num, out) { + var a = self.words; + var b = num.words; + var o = out.words; + var c = 0; + var lo; + var mid; + var hi; + var a0 = a[0] | 0; + var al0 = a0 & 0x1fff; + var ah0 = a0 >>> 13; + var a1 = a[1] | 0; + var al1 = a1 & 0x1fff; + var ah1 = a1 >>> 13; + var a2 = a[2] | 0; + var al2 = a2 & 0x1fff; + var ah2 = a2 >>> 13; + var a3 = a[3] | 0; + var al3 = a3 & 0x1fff; + var ah3 = a3 >>> 13; + var a4 = a[4] | 0; + var al4 = a4 & 0x1fff; + var ah4 = a4 >>> 13; + var a5 = a[5] | 0; + var al5 = a5 & 0x1fff; + var ah5 = a5 >>> 13; + var a6 = a[6] | 0; + var al6 = a6 & 0x1fff; + var ah6 = a6 >>> 13; + var a7 = a[7] | 0; + var al7 = a7 & 0x1fff; + var ah7 = a7 >>> 13; + var a8 = a[8] | 0; + var al8 = a8 & 0x1fff; + var ah8 = a8 >>> 13; + var a9 = a[9] | 0; + var al9 = a9 & 0x1fff; + var ah9 = a9 >>> 13; + var b0 = b[0] | 0; + var bl0 = b0 & 0x1fff; + var bh0 = b0 >>> 13; + var b1 = b[1] | 0; + var bl1 = b1 & 0x1fff; + var bh1 = b1 >>> 13; + var b2 = b[2] | 0; + var bl2 = b2 & 0x1fff; + var bh2 = b2 >>> 13; + var b3 = b[3] | 0; + var bl3 = b3 & 0x1fff; + var bh3 = b3 >>> 13; + var b4 = b[4] | 0; + var bl4 = b4 & 0x1fff; + var bh4 = b4 >>> 13; + var b5 = b[5] | 0; + var bl5 = b5 & 0x1fff; + var bh5 = b5 >>> 13; + var b6 = b[6] | 0; + var bl6 = b6 & 0x1fff; + var bh6 = b6 >>> 13; + var b7 = b[7] | 0; + var bl7 = b7 & 0x1fff; + var bh7 = b7 >>> 13; + var b8 = b[8] | 0; + var bl8 = b8 & 0x1fff; + var bh8 = b8 >>> 13; + var b9 = b[9] | 0; + var bl9 = b9 & 0x1fff; + var bh9 = b9 >>> 13; + + out.negative = self.negative ^ num.negative; + out.length = 19; + /* k = 0 */ + lo = Math.imul(al0, bl0); + mid = Math.imul(al0, bh0); + mid = (mid + Math.imul(ah0, bl0)) | 0; + hi = Math.imul(ah0, bh0); + var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0; + w0 &= 0x3ffffff; + /* k = 1 */ + lo = Math.imul(al1, bl0); + mid = Math.imul(al1, bh0); + mid = (mid + Math.imul(ah1, bl0)) | 0; + hi = Math.imul(ah1, bh0); + lo = (lo + Math.imul(al0, bl1)) | 0; + mid = (mid + Math.imul(al0, bh1)) | 0; + mid = (mid + Math.imul(ah0, bl1)) | 0; + hi = (hi + Math.imul(ah0, bh1)) | 0; + var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0; + w1 &= 0x3ffffff; + /* k = 2 */ + lo = Math.imul(al2, bl0); + mid = Math.imul(al2, bh0); + mid = (mid + Math.imul(ah2, bl0)) | 0; + hi = Math.imul(ah2, bh0); + lo = (lo + Math.imul(al1, bl1)) | 0; + mid = (mid + Math.imul(al1, bh1)) | 0; + mid = (mid + Math.imul(ah1, bl1)) | 0; + hi = (hi + Math.imul(ah1, bh1)) | 0; + lo = (lo + Math.imul(al0, bl2)) | 0; + mid = (mid + Math.imul(al0, bh2)) | 0; + mid = (mid + Math.imul(ah0, bl2)) | 0; + hi = (hi + Math.imul(ah0, bh2)) | 0; + var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0; + w2 &= 0x3ffffff; + /* k = 3 */ + lo = Math.imul(al3, bl0); + mid = Math.imul(al3, bh0); + mid = (mid + Math.imul(ah3, bl0)) | 0; + hi = Math.imul(ah3, bh0); + lo = (lo + Math.imul(al2, bl1)) | 0; + mid = (mid + Math.imul(al2, bh1)) | 0; + mid = (mid + Math.imul(ah2, bl1)) | 0; + hi = (hi + Math.imul(ah2, bh1)) | 0; + lo = (lo + Math.imul(al1, bl2)) | 0; + mid = (mid + Math.imul(al1, bh2)) | 0; + mid = (mid + Math.imul(ah1, bl2)) | 0; + hi = (hi + Math.imul(ah1, bh2)) | 0; + lo = (lo + Math.imul(al0, bl3)) | 0; + mid = (mid + Math.imul(al0, bh3)) | 0; + mid = (mid + Math.imul(ah0, bl3)) | 0; + hi = (hi + Math.imul(ah0, bh3)) | 0; + var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0; + w3 &= 0x3ffffff; + /* k = 4 */ + lo = Math.imul(al4, bl0); + mid = Math.imul(al4, bh0); + mid = (mid + Math.imul(ah4, bl0)) | 0; + hi = Math.imul(ah4, bh0); + lo = (lo + Math.imul(al3, bl1)) | 0; + mid = (mid + Math.imul(al3, bh1)) | 0; + mid = (mid + Math.imul(ah3, bl1)) | 0; + hi = (hi + Math.imul(ah3, bh1)) | 0; + lo = (lo + Math.imul(al2, bl2)) | 0; + mid = (mid + Math.imul(al2, bh2)) | 0; + mid = (mid + Math.imul(ah2, bl2)) | 0; + hi = (hi + Math.imul(ah2, bh2)) | 0; + lo = (lo + Math.imul(al1, bl3)) | 0; + mid = (mid + Math.imul(al1, bh3)) | 0; + mid = (mid + Math.imul(ah1, bl3)) | 0; + hi = (hi + Math.imul(ah1, bh3)) | 0; + lo = (lo + Math.imul(al0, bl4)) | 0; + mid = (mid + Math.imul(al0, bh4)) | 0; + mid = (mid + Math.imul(ah0, bl4)) | 0; + hi = (hi + Math.imul(ah0, bh4)) | 0; + var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0; + w4 &= 0x3ffffff; + /* k = 5 */ + lo = Math.imul(al5, bl0); + mid = Math.imul(al5, bh0); + mid = (mid + Math.imul(ah5, bl0)) | 0; + hi = Math.imul(ah5, bh0); + lo = (lo + Math.imul(al4, bl1)) | 0; + mid = (mid + Math.imul(al4, bh1)) | 0; + mid = (mid + Math.imul(ah4, bl1)) | 0; + hi = (hi + Math.imul(ah4, bh1)) | 0; + lo = (lo + Math.imul(al3, bl2)) | 0; + mid = (mid + Math.imul(al3, bh2)) | 0; + mid = (mid + Math.imul(ah3, bl2)) | 0; + hi = (hi + Math.imul(ah3, bh2)) | 0; + lo = (lo + Math.imul(al2, bl3)) | 0; + mid = (mid + Math.imul(al2, bh3)) | 0; + mid = (mid + Math.imul(ah2, bl3)) | 0; + hi = (hi + Math.imul(ah2, bh3)) | 0; + lo = (lo + Math.imul(al1, bl4)) | 0; + mid = (mid + Math.imul(al1, bh4)) | 0; + mid = (mid + Math.imul(ah1, bl4)) | 0; + hi = (hi + Math.imul(ah1, bh4)) | 0; + lo = (lo + Math.imul(al0, bl5)) | 0; + mid = (mid + Math.imul(al0, bh5)) | 0; + mid = (mid + Math.imul(ah0, bl5)) | 0; + hi = (hi + Math.imul(ah0, bh5)) | 0; + var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0; + w5 &= 0x3ffffff; + /* k = 6 */ + lo = Math.imul(al6, bl0); + mid = Math.imul(al6, bh0); + mid = (mid + Math.imul(ah6, bl0)) | 0; + hi = Math.imul(ah6, bh0); + lo = (lo + Math.imul(al5, bl1)) | 0; + mid = (mid + Math.imul(al5, bh1)) | 0; + mid = (mid + Math.imul(ah5, bl1)) | 0; + hi = (hi + Math.imul(ah5, bh1)) | 0; + lo = (lo + Math.imul(al4, bl2)) | 0; + mid = (mid + Math.imul(al4, bh2)) | 0; + mid = (mid + Math.imul(ah4, bl2)) | 0; + hi = (hi + Math.imul(ah4, bh2)) | 0; + lo = (lo + Math.imul(al3, bl3)) | 0; + mid = (mid + Math.imul(al3, bh3)) | 0; + mid = (mid + Math.imul(ah3, bl3)) | 0; + hi = (hi + Math.imul(ah3, bh3)) | 0; + lo = (lo + Math.imul(al2, bl4)) | 0; + mid = (mid + Math.imul(al2, bh4)) | 0; + mid = (mid + Math.imul(ah2, bl4)) | 0; + hi = (hi + Math.imul(ah2, bh4)) | 0; + lo = (lo + Math.imul(al1, bl5)) | 0; + mid = (mid + Math.imul(al1, bh5)) | 0; + mid = (mid + Math.imul(ah1, bl5)) | 0; + hi = (hi + Math.imul(ah1, bh5)) | 0; + lo = (lo + Math.imul(al0, bl6)) | 0; + mid = (mid + Math.imul(al0, bh6)) | 0; + mid = (mid + Math.imul(ah0, bl6)) | 0; + hi = (hi + Math.imul(ah0, bh6)) | 0; + var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0; + w6 &= 0x3ffffff; + /* k = 7 */ + lo = Math.imul(al7, bl0); + mid = Math.imul(al7, bh0); + mid = (mid + Math.imul(ah7, bl0)) | 0; + hi = Math.imul(ah7, bh0); + lo = (lo + Math.imul(al6, bl1)) | 0; + mid = (mid + Math.imul(al6, bh1)) | 0; + mid = (mid + Math.imul(ah6, bl1)) | 0; + hi = (hi + Math.imul(ah6, bh1)) | 0; + lo = (lo + Math.imul(al5, bl2)) | 0; + mid = (mid + Math.imul(al5, bh2)) | 0; + mid = (mid + Math.imul(ah5, bl2)) | 0; + hi = (hi + Math.imul(ah5, bh2)) | 0; + lo = (lo + Math.imul(al4, bl3)) | 0; + mid = (mid + Math.imul(al4, bh3)) | 0; + mid = (mid + Math.imul(ah4, bl3)) | 0; + hi = (hi + Math.imul(ah4, bh3)) | 0; + lo = (lo + Math.imul(al3, bl4)) | 0; + mid = (mid + Math.imul(al3, bh4)) | 0; + mid = (mid + Math.imul(ah3, bl4)) | 0; + hi = (hi + Math.imul(ah3, bh4)) | 0; + lo = (lo + Math.imul(al2, bl5)) | 0; + mid = (mid + Math.imul(al2, bh5)) | 0; + mid = (mid + Math.imul(ah2, bl5)) | 0; + hi = (hi + Math.imul(ah2, bh5)) | 0; + lo = (lo + Math.imul(al1, bl6)) | 0; + mid = (mid + Math.imul(al1, bh6)) | 0; + mid = (mid + Math.imul(ah1, bl6)) | 0; + hi = (hi + Math.imul(ah1, bh6)) | 0; + lo = (lo + Math.imul(al0, bl7)) | 0; + mid = (mid + Math.imul(al0, bh7)) | 0; + mid = (mid + Math.imul(ah0, bl7)) | 0; + hi = (hi + Math.imul(ah0, bh7)) | 0; + var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0; + w7 &= 0x3ffffff; + /* k = 8 */ + lo = Math.imul(al8, bl0); + mid = Math.imul(al8, bh0); + mid = (mid + Math.imul(ah8, bl0)) | 0; + hi = Math.imul(ah8, bh0); + lo = (lo + Math.imul(al7, bl1)) | 0; + mid = (mid + Math.imul(al7, bh1)) | 0; + mid = (mid + Math.imul(ah7, bl1)) | 0; + hi = (hi + Math.imul(ah7, bh1)) | 0; + lo = (lo + Math.imul(al6, bl2)) | 0; + mid = (mid + Math.imul(al6, bh2)) | 0; + mid = (mid + Math.imul(ah6, bl2)) | 0; + hi = (hi + Math.imul(ah6, bh2)) | 0; + lo = (lo + Math.imul(al5, bl3)) | 0; + mid = (mid + Math.imul(al5, bh3)) | 0; + mid = (mid + Math.imul(ah5, bl3)) | 0; + hi = (hi + Math.imul(ah5, bh3)) | 0; + lo = (lo + Math.imul(al4, bl4)) | 0; + mid = (mid + Math.imul(al4, bh4)) | 0; + mid = (mid + Math.imul(ah4, bl4)) | 0; + hi = (hi + Math.imul(ah4, bh4)) | 0; + lo = (lo + Math.imul(al3, bl5)) | 0; + mid = (mid + Math.imul(al3, bh5)) | 0; + mid = (mid + Math.imul(ah3, bl5)) | 0; + hi = (hi + Math.imul(ah3, bh5)) | 0; + lo = (lo + Math.imul(al2, bl6)) | 0; + mid = (mid + Math.imul(al2, bh6)) | 0; + mid = (mid + Math.imul(ah2, bl6)) | 0; + hi = (hi + Math.imul(ah2, bh6)) | 0; + lo = (lo + Math.imul(al1, bl7)) | 0; + mid = (mid + Math.imul(al1, bh7)) | 0; + mid = (mid + Math.imul(ah1, bl7)) | 0; + hi = (hi + Math.imul(ah1, bh7)) | 0; + lo = (lo + Math.imul(al0, bl8)) | 0; + mid = (mid + Math.imul(al0, bh8)) | 0; + mid = (mid + Math.imul(ah0, bl8)) | 0; + hi = (hi + Math.imul(ah0, bh8)) | 0; + var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0; + w8 &= 0x3ffffff; + /* k = 9 */ + lo = Math.imul(al9, bl0); + mid = Math.imul(al9, bh0); + mid = (mid + Math.imul(ah9, bl0)) | 0; + hi = Math.imul(ah9, bh0); + lo = (lo + Math.imul(al8, bl1)) | 0; + mid = (mid + Math.imul(al8, bh1)) | 0; + mid = (mid + Math.imul(ah8, bl1)) | 0; + hi = (hi + Math.imul(ah8, bh1)) | 0; + lo = (lo + Math.imul(al7, bl2)) | 0; + mid = (mid + Math.imul(al7, bh2)) | 0; + mid = (mid + Math.imul(ah7, bl2)) | 0; + hi = (hi + Math.imul(ah7, bh2)) | 0; + lo = (lo + Math.imul(al6, bl3)) | 0; + mid = (mid + Math.imul(al6, bh3)) | 0; + mid = (mid + Math.imul(ah6, bl3)) | 0; + hi = (hi + Math.imul(ah6, bh3)) | 0; + lo = (lo + Math.imul(al5, bl4)) | 0; + mid = (mid + Math.imul(al5, bh4)) | 0; + mid = (mid + Math.imul(ah5, bl4)) | 0; + hi = (hi + Math.imul(ah5, bh4)) | 0; + lo = (lo + Math.imul(al4, bl5)) | 0; + mid = (mid + Math.imul(al4, bh5)) | 0; + mid = (mid + Math.imul(ah4, bl5)) | 0; + hi = (hi + Math.imul(ah4, bh5)) | 0; + lo = (lo + Math.imul(al3, bl6)) | 0; + mid = (mid + Math.imul(al3, bh6)) | 0; + mid = (mid + Math.imul(ah3, bl6)) | 0; + hi = (hi + Math.imul(ah3, bh6)) | 0; + lo = (lo + Math.imul(al2, bl7)) | 0; + mid = (mid + Math.imul(al2, bh7)) | 0; + mid = (mid + Math.imul(ah2, bl7)) | 0; + hi = (hi + Math.imul(ah2, bh7)) | 0; + lo = (lo + Math.imul(al1, bl8)) | 0; + mid = (mid + Math.imul(al1, bh8)) | 0; + mid = (mid + Math.imul(ah1, bl8)) | 0; + hi = (hi + Math.imul(ah1, bh8)) | 0; + lo = (lo + Math.imul(al0, bl9)) | 0; + mid = (mid + Math.imul(al0, bh9)) | 0; + mid = (mid + Math.imul(ah0, bl9)) | 0; + hi = (hi + Math.imul(ah0, bh9)) | 0; + var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0; + w9 &= 0x3ffffff; + /* k = 10 */ + lo = Math.imul(al9, bl1); + mid = Math.imul(al9, bh1); + mid = (mid + Math.imul(ah9, bl1)) | 0; + hi = Math.imul(ah9, bh1); + lo = (lo + Math.imul(al8, bl2)) | 0; + mid = (mid + Math.imul(al8, bh2)) | 0; + mid = (mid + Math.imul(ah8, bl2)) | 0; + hi = (hi + Math.imul(ah8, bh2)) | 0; + lo = (lo + Math.imul(al7, bl3)) | 0; + mid = (mid + Math.imul(al7, bh3)) | 0; + mid = (mid + Math.imul(ah7, bl3)) | 0; + hi = (hi + Math.imul(ah7, bh3)) | 0; + lo = (lo + Math.imul(al6, bl4)) | 0; + mid = (mid + Math.imul(al6, bh4)) | 0; + mid = (mid + Math.imul(ah6, bl4)) | 0; + hi = (hi + Math.imul(ah6, bh4)) | 0; + lo = (lo + Math.imul(al5, bl5)) | 0; + mid = (mid + Math.imul(al5, bh5)) | 0; + mid = (mid + Math.imul(ah5, bl5)) | 0; + hi = (hi + Math.imul(ah5, bh5)) | 0; + lo = (lo + Math.imul(al4, bl6)) | 0; + mid = (mid + Math.imul(al4, bh6)) | 0; + mid = (mid + Math.imul(ah4, bl6)) | 0; + hi = (hi + Math.imul(ah4, bh6)) | 0; + lo = (lo + Math.imul(al3, bl7)) | 0; + mid = (mid + Math.imul(al3, bh7)) | 0; + mid = (mid + Math.imul(ah3, bl7)) | 0; + hi = (hi + Math.imul(ah3, bh7)) | 0; + lo = (lo + Math.imul(al2, bl8)) | 0; + mid = (mid + Math.imul(al2, bh8)) | 0; + mid = (mid + Math.imul(ah2, bl8)) | 0; + hi = (hi + Math.imul(ah2, bh8)) | 0; + lo = (lo + Math.imul(al1, bl9)) | 0; + mid = (mid + Math.imul(al1, bh9)) | 0; + mid = (mid + Math.imul(ah1, bl9)) | 0; + hi = (hi + Math.imul(ah1, bh9)) | 0; + var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0; + w10 &= 0x3ffffff; + /* k = 11 */ + lo = Math.imul(al9, bl2); + mid = Math.imul(al9, bh2); + mid = (mid + Math.imul(ah9, bl2)) | 0; + hi = Math.imul(ah9, bh2); + lo = (lo + Math.imul(al8, bl3)) | 0; + mid = (mid + Math.imul(al8, bh3)) | 0; + mid = (mid + Math.imul(ah8, bl3)) | 0; + hi = (hi + Math.imul(ah8, bh3)) | 0; + lo = (lo + Math.imul(al7, bl4)) | 0; + mid = (mid + Math.imul(al7, bh4)) | 0; + mid = (mid + Math.imul(ah7, bl4)) | 0; + hi = (hi + Math.imul(ah7, bh4)) | 0; + lo = (lo + Math.imul(al6, bl5)) | 0; + mid = (mid + Math.imul(al6, bh5)) | 0; + mid = (mid + Math.imul(ah6, bl5)) | 0; + hi = (hi + Math.imul(ah6, bh5)) | 0; + lo = (lo + Math.imul(al5, bl6)) | 0; + mid = (mid + Math.imul(al5, bh6)) | 0; + mid = (mid + Math.imul(ah5, bl6)) | 0; + hi = (hi + Math.imul(ah5, bh6)) | 0; + lo = (lo + Math.imul(al4, bl7)) | 0; + mid = (mid + Math.imul(al4, bh7)) | 0; + mid = (mid + Math.imul(ah4, bl7)) | 0; + hi = (hi + Math.imul(ah4, bh7)) | 0; + lo = (lo + Math.imul(al3, bl8)) | 0; + mid = (mid + Math.imul(al3, bh8)) | 0; + mid = (mid + Math.imul(ah3, bl8)) | 0; + hi = (hi + Math.imul(ah3, bh8)) | 0; + lo = (lo + Math.imul(al2, bl9)) | 0; + mid = (mid + Math.imul(al2, bh9)) | 0; + mid = (mid + Math.imul(ah2, bl9)) | 0; + hi = (hi + Math.imul(ah2, bh9)) | 0; + var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0; + w11 &= 0x3ffffff; + /* k = 12 */ + lo = Math.imul(al9, bl3); + mid = Math.imul(al9, bh3); + mid = (mid + Math.imul(ah9, bl3)) | 0; + hi = Math.imul(ah9, bh3); + lo = (lo + Math.imul(al8, bl4)) | 0; + mid = (mid + Math.imul(al8, bh4)) | 0; + mid = (mid + Math.imul(ah8, bl4)) | 0; + hi = (hi + Math.imul(ah8, bh4)) | 0; + lo = (lo + Math.imul(al7, bl5)) | 0; + mid = (mid + Math.imul(al7, bh5)) | 0; + mid = (mid + Math.imul(ah7, bl5)) | 0; + hi = (hi + Math.imul(ah7, bh5)) | 0; + lo = (lo + Math.imul(al6, bl6)) | 0; + mid = (mid + Math.imul(al6, bh6)) | 0; + mid = (mid + Math.imul(ah6, bl6)) | 0; + hi = (hi + Math.imul(ah6, bh6)) | 0; + lo = (lo + Math.imul(al5, bl7)) | 0; + mid = (mid + Math.imul(al5, bh7)) | 0; + mid = (mid + Math.imul(ah5, bl7)) | 0; + hi = (hi + Math.imul(ah5, bh7)) | 0; + lo = (lo + Math.imul(al4, bl8)) | 0; + mid = (mid + Math.imul(al4, bh8)) | 0; + mid = (mid + Math.imul(ah4, bl8)) | 0; + hi = (hi + Math.imul(ah4, bh8)) | 0; + lo = (lo + Math.imul(al3, bl9)) | 0; + mid = (mid + Math.imul(al3, bh9)) | 0; + mid = (mid + Math.imul(ah3, bl9)) | 0; + hi = (hi + Math.imul(ah3, bh9)) | 0; + var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0; + w12 &= 0x3ffffff; + /* k = 13 */ + lo = Math.imul(al9, bl4); + mid = Math.imul(al9, bh4); + mid = (mid + Math.imul(ah9, bl4)) | 0; + hi = Math.imul(ah9, bh4); + lo = (lo + Math.imul(al8, bl5)) | 0; + mid = (mid + Math.imul(al8, bh5)) | 0; + mid = (mid + Math.imul(ah8, bl5)) | 0; + hi = (hi + Math.imul(ah8, bh5)) | 0; + lo = (lo + Math.imul(al7, bl6)) | 0; + mid = (mid + Math.imul(al7, bh6)) | 0; + mid = (mid + Math.imul(ah7, bl6)) | 0; + hi = (hi + Math.imul(ah7, bh6)) | 0; + lo = (lo + Math.imul(al6, bl7)) | 0; + mid = (mid + Math.imul(al6, bh7)) | 0; + mid = (mid + Math.imul(ah6, bl7)) | 0; + hi = (hi + Math.imul(ah6, bh7)) | 0; + lo = (lo + Math.imul(al5, bl8)) | 0; + mid = (mid + Math.imul(al5, bh8)) | 0; + mid = (mid + Math.imul(ah5, bl8)) | 0; + hi = (hi + Math.imul(ah5, bh8)) | 0; + lo = (lo + Math.imul(al4, bl9)) | 0; + mid = (mid + Math.imul(al4, bh9)) | 0; + mid = (mid + Math.imul(ah4, bl9)) | 0; + hi = (hi + Math.imul(ah4, bh9)) | 0; + var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0; + w13 &= 0x3ffffff; + /* k = 14 */ + lo = Math.imul(al9, bl5); + mid = Math.imul(al9, bh5); + mid = (mid + Math.imul(ah9, bl5)) | 0; + hi = Math.imul(ah9, bh5); + lo = (lo + Math.imul(al8, bl6)) | 0; + mid = (mid + Math.imul(al8, bh6)) | 0; + mid = (mid + Math.imul(ah8, bl6)) | 0; + hi = (hi + Math.imul(ah8, bh6)) | 0; + lo = (lo + Math.imul(al7, bl7)) | 0; + mid = (mid + Math.imul(al7, bh7)) | 0; + mid = (mid + Math.imul(ah7, bl7)) | 0; + hi = (hi + Math.imul(ah7, bh7)) | 0; + lo = (lo + Math.imul(al6, bl8)) | 0; + mid = (mid + Math.imul(al6, bh8)) | 0; + mid = (mid + Math.imul(ah6, bl8)) | 0; + hi = (hi + Math.imul(ah6, bh8)) | 0; + lo = (lo + Math.imul(al5, bl9)) | 0; + mid = (mid + Math.imul(al5, bh9)) | 0; + mid = (mid + Math.imul(ah5, bl9)) | 0; + hi = (hi + Math.imul(ah5, bh9)) | 0; + var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0; + w14 &= 0x3ffffff; + /* k = 15 */ + lo = Math.imul(al9, bl6); + mid = Math.imul(al9, bh6); + mid = (mid + Math.imul(ah9, bl6)) | 0; + hi = Math.imul(ah9, bh6); + lo = (lo + Math.imul(al8, bl7)) | 0; + mid = (mid + Math.imul(al8, bh7)) | 0; + mid = (mid + Math.imul(ah8, bl7)) | 0; + hi = (hi + Math.imul(ah8, bh7)) | 0; + lo = (lo + Math.imul(al7, bl8)) | 0; + mid = (mid + Math.imul(al7, bh8)) | 0; + mid = (mid + Math.imul(ah7, bl8)) | 0; + hi = (hi + Math.imul(ah7, bh8)) | 0; + lo = (lo + Math.imul(al6, bl9)) | 0; + mid = (mid + Math.imul(al6, bh9)) | 0; + mid = (mid + Math.imul(ah6, bl9)) | 0; + hi = (hi + Math.imul(ah6, bh9)) | 0; + var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0; + w15 &= 0x3ffffff; + /* k = 16 */ + lo = Math.imul(al9, bl7); + mid = Math.imul(al9, bh7); + mid = (mid + Math.imul(ah9, bl7)) | 0; + hi = Math.imul(ah9, bh7); + lo = (lo + Math.imul(al8, bl8)) | 0; + mid = (mid + Math.imul(al8, bh8)) | 0; + mid = (mid + Math.imul(ah8, bl8)) | 0; + hi = (hi + Math.imul(ah8, bh8)) | 0; + lo = (lo + Math.imul(al7, bl9)) | 0; + mid = (mid + Math.imul(al7, bh9)) | 0; + mid = (mid + Math.imul(ah7, bl9)) | 0; + hi = (hi + Math.imul(ah7, bh9)) | 0; + var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0; + w16 &= 0x3ffffff; + /* k = 17 */ + lo = Math.imul(al9, bl8); + mid = Math.imul(al9, bh8); + mid = (mid + Math.imul(ah9, bl8)) | 0; + hi = Math.imul(ah9, bh8); + lo = (lo + Math.imul(al8, bl9)) | 0; + mid = (mid + Math.imul(al8, bh9)) | 0; + mid = (mid + Math.imul(ah8, bl9)) | 0; + hi = (hi + Math.imul(ah8, bh9)) | 0; + var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0; + w17 &= 0x3ffffff; + /* k = 18 */ + lo = Math.imul(al9, bl9); + mid = Math.imul(al9, bh9); + mid = (mid + Math.imul(ah9, bl9)) | 0; + hi = Math.imul(ah9, bh9); + var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0; + w18 &= 0x3ffffff; + o[0] = w0; + o[1] = w1; + o[2] = w2; + o[3] = w3; + o[4] = w4; + o[5] = w5; + o[6] = w6; + o[7] = w7; + o[8] = w8; + o[9] = w9; + o[10] = w10; + o[11] = w11; + o[12] = w12; + o[13] = w13; + o[14] = w14; + o[15] = w15; + o[16] = w16; + o[17] = w17; + o[18] = w18; + if (c !== 0) { + o[19] = c; + out.length++; + } + return out; + }; + + // Polyfill comb + if (!Math.imul) { + comb10MulTo = smallMulTo; + } + + function bigMulTo (self, num, out) { + out.negative = num.negative ^ self.negative; + out.length = self.length + num.length; + + var carry = 0; + var hncarry = 0; + for (var k = 0; k < out.length - 1; k++) { + // Sum all words with the same `i + j = k` and accumulate `ncarry`, + // note that ncarry could be >= 0x3ffffff + var ncarry = hncarry; + hncarry = 0; + var rword = carry & 0x3ffffff; + var maxJ = Math.min(k, num.length - 1); + for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { + var i = k - j; + var a = self.words[i] | 0; + var b = num.words[j] | 0; + var r = a * b; + + var lo = r & 0x3ffffff; + ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0; + lo = (lo + rword) | 0; + rword = lo & 0x3ffffff; + ncarry = (ncarry + (lo >>> 26)) | 0; + + hncarry += ncarry >>> 26; + ncarry &= 0x3ffffff; + } + out.words[k] = rword; + carry = ncarry; + ncarry = hncarry; + } + if (carry !== 0) { + out.words[k] = carry; + } else { + out.length--; + } + + return out.strip(); + } + + function jumboMulTo (self, num, out) { + var fftm = new FFTM(); + return fftm.mulp(self, num, out); + } + + BN.prototype.mulTo = function mulTo (num, out) { + var res; + var len = this.length + num.length; + if (this.length === 10 && num.length === 10) { + res = comb10MulTo(this, num, out); + } else if (len < 63) { + res = smallMulTo(this, num, out); + } else if (len < 1024) { + res = bigMulTo(this, num, out); + } else { + res = jumboMulTo(this, num, out); + } + + return res; + }; + + // Cooley-Tukey algorithm for FFT + // slightly revisited to rely on looping instead of recursion + + function FFTM (x, y) { + this.x = x; + this.y = y; + } + + FFTM.prototype.makeRBT = function makeRBT (N) { + var t = new Array(N); + var l = BN.prototype._countBits(N) - 1; + for (var i = 0; i < N; i++) { + t[i] = this.revBin(i, l, N); + } + + return t; + }; + + // Returns binary-reversed representation of `x` + FFTM.prototype.revBin = function revBin (x, l, N) { + if (x === 0 || x === N - 1) return x; + + var rb = 0; + for (var i = 0; i < l; i++) { + rb |= (x & 1) << (l - i - 1); + x >>= 1; + } + + return rb; + }; + + // Performs "tweedling" phase, therefore 'emulating' + // behaviour of the recursive algorithm + FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) { + for (var i = 0; i < N; i++) { + rtws[i] = rws[rbt[i]]; + itws[i] = iws[rbt[i]]; + } + }; + + FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) { + this.permute(rbt, rws, iws, rtws, itws, N); + + for (var s = 1; s < N; s <<= 1) { + var l = s << 1; + + var rtwdf = Math.cos(2 * Math.PI / l); + var itwdf = Math.sin(2 * Math.PI / l); + + for (var p = 0; p < N; p += l) { + var rtwdf_ = rtwdf; + var itwdf_ = itwdf; + + for (var j = 0; j < s; j++) { + var re = rtws[p + j]; + var ie = itws[p + j]; + + var ro = rtws[p + j + s]; + var io = itws[p + j + s]; + + var rx = rtwdf_ * ro - itwdf_ * io; + + io = rtwdf_ * io + itwdf_ * ro; + ro = rx; + + rtws[p + j] = re + ro; + itws[p + j] = ie + io; + + rtws[p + j + s] = re - ro; + itws[p + j + s] = ie - io; + + /* jshint maxdepth : false */ + if (j !== l) { + rx = rtwdf * rtwdf_ - itwdf * itwdf_; + + itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_; + rtwdf_ = rx; + } + } + } + } + }; + + FFTM.prototype.guessLen13b = function guessLen13b (n, m) { + var N = Math.max(m, n) | 1; + var odd = N & 1; + var i = 0; + for (N = N / 2 | 0; N; N = N >>> 1) { + i++; + } + + return 1 << i + 1 + odd; + }; + + FFTM.prototype.conjugate = function conjugate (rws, iws, N) { + if (N <= 1) return; + + for (var i = 0; i < N / 2; i++) { + var t = rws[i]; + + rws[i] = rws[N - i - 1]; + rws[N - i - 1] = t; + + t = iws[i]; + + iws[i] = -iws[N - i - 1]; + iws[N - i - 1] = -t; + } + }; + + FFTM.prototype.normalize13b = function normalize13b (ws, N) { + var carry = 0; + for (var i = 0; i < N / 2; i++) { + var w = Math.round(ws[2 * i + 1] / N) * 0x2000 + + Math.round(ws[2 * i] / N) + + carry; + + ws[i] = w & 0x3ffffff; + + if (w < 0x4000000) { + carry = 0; + } else { + carry = w / 0x4000000 | 0; + } + } + + return ws; + }; + + FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) { + var carry = 0; + for (var i = 0; i < len; i++) { + carry = carry + (ws[i] | 0); + + rws[2 * i] = carry & 0x1fff; carry = carry >>> 13; + rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13; + } + + // Pad with zeroes + for (i = 2 * len; i < N; ++i) { + rws[i] = 0; + } + + assert(carry === 0); + assert((carry & ~0x1fff) === 0); + }; + + FFTM.prototype.stub = function stub (N) { + var ph = new Array(N); + for (var i = 0; i < N; i++) { + ph[i] = 0; + } + + return ph; + }; + + FFTM.prototype.mulp = function mulp (x, y, out) { + var N = 2 * this.guessLen13b(x.length, y.length); + + var rbt = this.makeRBT(N); + + var _ = this.stub(N); + + var rws = new Array(N); + var rwst = new Array(N); + var iwst = new Array(N); + + var nrws = new Array(N); + var nrwst = new Array(N); + var niwst = new Array(N); + + var rmws = out.words; + rmws.length = N; + + this.convert13b(x.words, x.length, rws, N); + this.convert13b(y.words, y.length, nrws, N); + + this.transform(rws, _, rwst, iwst, N, rbt); + this.transform(nrws, _, nrwst, niwst, N, rbt); + + for (var i = 0; i < N; i++) { + var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i]; + iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i]; + rwst[i] = rx; + } + + this.conjugate(rwst, iwst, N); + this.transform(rwst, iwst, rmws, _, N, rbt); + this.conjugate(rmws, _, N); + this.normalize13b(rmws, N); + + out.negative = x.negative ^ y.negative; + out.length = x.length + y.length; + return out.strip(); + }; + + // Multiply `this` by `num` + BN.prototype.mul = function mul (num) { + var out = new BN(null); + out.words = new Array(this.length + num.length); + return this.mulTo(num, out); + }; + + // Multiply employing FFT + BN.prototype.mulf = function mulf (num) { + var out = new BN(null); + out.words = new Array(this.length + num.length); + return jumboMulTo(this, num, out); + }; + + // In-place Multiplication + BN.prototype.imul = function imul (num) { + return this.clone().mulTo(num, this); + }; + + BN.prototype.imuln = function imuln (num) { + assert(typeof num === 'number'); + assert(num < 0x4000000); + + // Carry + var carry = 0; + for (var i = 0; i < this.length; i++) { + var w = (this.words[i] | 0) * num; + var lo = (w & 0x3ffffff) + (carry & 0x3ffffff); + carry >>= 26; + carry += (w / 0x4000000) | 0; + // NOTE: lo is 27bit maximum + carry += lo >>> 26; + this.words[i] = lo & 0x3ffffff; + } + + if (carry !== 0) { + this.words[i] = carry; + this.length++; + } + + return this; + }; + + BN.prototype.muln = function muln (num) { + return this.clone().imuln(num); + }; + + // `this` * `this` + BN.prototype.sqr = function sqr () { + return this.mul(this); + }; + + // `this` * `this` in-place + BN.prototype.isqr = function isqr () { + return this.imul(this.clone()); + }; + + // Math.pow(`this`, `num`) + BN.prototype.pow = function pow (num) { + var w = toBitArray(num); + if (w.length === 0) return new BN(1); + + // Skip leading zeroes + var res = this; + for (var i = 0; i < w.length; i++, res = res.sqr()) { + if (w[i] !== 0) break; + } + + if (++i < w.length) { + for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) { + if (w[i] === 0) continue; + + res = res.mul(q); + } + } + + return res; + }; + + // Shift-left in-place + BN.prototype.iushln = function iushln (bits) { + assert(typeof bits === 'number' && bits >= 0); + var r = bits % 26; + var s = (bits - r) / 26; + var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r); + var i; + + if (r !== 0) { + var carry = 0; + + for (i = 0; i < this.length; i++) { + var newCarry = this.words[i] & carryMask; + var c = ((this.words[i] | 0) - newCarry) << r; + this.words[i] = c | carry; + carry = newCarry >>> (26 - r); + } + + if (carry) { + this.words[i] = carry; + this.length++; + } + } + + if (s !== 0) { + for (i = this.length - 1; i >= 0; i--) { + this.words[i + s] = this.words[i]; + } + + for (i = 0; i < s; i++) { + this.words[i] = 0; + } + + this.length += s; + } + + return this.strip(); + }; + + BN.prototype.ishln = function ishln (bits) { + // TODO(indutny): implement me + assert(this.negative === 0); + return this.iushln(bits); + }; + + // Shift-right in-place + // NOTE: `hint` is a lowest bit before trailing zeroes + // NOTE: if `extended` is present - it will be filled with destroyed bits + BN.prototype.iushrn = function iushrn (bits, hint, extended) { + assert(typeof bits === 'number' && bits >= 0); + var h; + if (hint) { + h = (hint - (hint % 26)) / 26; + } else { + h = 0; + } + + var r = bits % 26; + var s = Math.min((bits - r) / 26, this.length); + var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); + var maskedWords = extended; + + h -= s; + h = Math.max(0, h); + + // Extended mode, copy masked part + if (maskedWords) { + for (var i = 0; i < s; i++) { + maskedWords.words[i] = this.words[i]; + } + maskedWords.length = s; + } + + if (s === 0) ; else if (this.length > s) { + this.length -= s; + for (i = 0; i < this.length; i++) { + this.words[i] = this.words[i + s]; + } + } else { + this.words[0] = 0; + this.length = 1; + } + + var carry = 0; + for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) { + var word = this.words[i] | 0; + this.words[i] = (carry << (26 - r)) | (word >>> r); + carry = word & mask; + } + + // Push carried bits as a mask + if (maskedWords && carry !== 0) { + maskedWords.words[maskedWords.length++] = carry; + } + + if (this.length === 0) { + this.words[0] = 0; + this.length = 1; + } + + return this.strip(); + }; + + BN.prototype.ishrn = function ishrn (bits, hint, extended) { + // TODO(indutny): implement me + assert(this.negative === 0); + return this.iushrn(bits, hint, extended); + }; + + // Shift-left + BN.prototype.shln = function shln (bits) { + return this.clone().ishln(bits); + }; + + BN.prototype.ushln = function ushln (bits) { + return this.clone().iushln(bits); + }; + + // Shift-right + BN.prototype.shrn = function shrn (bits) { + return this.clone().ishrn(bits); + }; + + BN.prototype.ushrn = function ushrn (bits) { + return this.clone().iushrn(bits); + }; + + // Test if n bit is set + BN.prototype.testn = function testn (bit) { + assert(typeof bit === 'number' && bit >= 0); + var r = bit % 26; + var s = (bit - r) / 26; + var q = 1 << r; + + // Fast case: bit is much higher than all existing words + if (this.length <= s) return false; + + // Check bit and return + var w = this.words[s]; + + return !!(w & q); + }; + + // Return only lowers bits of number (in-place) + BN.prototype.imaskn = function imaskn (bits) { + assert(typeof bits === 'number' && bits >= 0); + var r = bits % 26; + var s = (bits - r) / 26; + + assert(this.negative === 0, 'imaskn works only with positive numbers'); + + if (this.length <= s) { + return this; + } + + if (r !== 0) { + s++; + } + this.length = Math.min(s, this.length); + + if (r !== 0) { + var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); + this.words[this.length - 1] &= mask; + } + + return this.strip(); + }; + + // Return only lowers bits of number + BN.prototype.maskn = function maskn (bits) { + return this.clone().imaskn(bits); + }; + + // Add plain number `num` to `this` + BN.prototype.iaddn = function iaddn (num) { + assert(typeof num === 'number'); + assert(num < 0x4000000); + if (num < 0) return this.isubn(-num); + + // Possible sign change + if (this.negative !== 0) { + if (this.length === 1 && (this.words[0] | 0) < num) { + this.words[0] = num - (this.words[0] | 0); + this.negative = 0; + return this; + } + + this.negative = 0; + this.isubn(num); + this.negative = 1; + return this; + } + + // Add without checks + return this._iaddn(num); + }; + + BN.prototype._iaddn = function _iaddn (num) { + this.words[0] += num; + + // Carry + for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) { + this.words[i] -= 0x4000000; + if (i === this.length - 1) { + this.words[i + 1] = 1; + } else { + this.words[i + 1]++; + } + } + this.length = Math.max(this.length, i + 1); + + return this; + }; + + // Subtract plain number `num` from `this` + BN.prototype.isubn = function isubn (num) { + assert(typeof num === 'number'); + assert(num < 0x4000000); + if (num < 0) return this.iaddn(-num); + + if (this.negative !== 0) { + this.negative = 0; + this.iaddn(num); + this.negative = 1; + return this; + } + + this.words[0] -= num; + + if (this.length === 1 && this.words[0] < 0) { + this.words[0] = -this.words[0]; + this.negative = 1; + } else { + // Carry + for (var i = 0; i < this.length && this.words[i] < 0; i++) { + this.words[i] += 0x4000000; + this.words[i + 1] -= 1; + } + } + + return this.strip(); + }; + + BN.prototype.addn = function addn (num) { + return this.clone().iaddn(num); + }; + + BN.prototype.subn = function subn (num) { + return this.clone().isubn(num); + }; + + BN.prototype.iabs = function iabs () { + this.negative = 0; + + return this; + }; + + BN.prototype.abs = function abs () { + return this.clone().iabs(); + }; + + BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) { + var len = num.length + shift; + var i; + + this._expand(len); + + var w; + var carry = 0; + for (i = 0; i < num.length; i++) { + w = (this.words[i + shift] | 0) + carry; + var right = (num.words[i] | 0) * mul; + w -= right & 0x3ffffff; + carry = (w >> 26) - ((right / 0x4000000) | 0); + this.words[i + shift] = w & 0x3ffffff; + } + for (; i < this.length - shift; i++) { + w = (this.words[i + shift] | 0) + carry; + carry = w >> 26; + this.words[i + shift] = w & 0x3ffffff; + } + + if (carry === 0) return this.strip(); + + // Subtraction overflow + assert(carry === -1); + carry = 0; + for (i = 0; i < this.length; i++) { + w = -(this.words[i] | 0) + carry; + carry = w >> 26; + this.words[i] = w & 0x3ffffff; + } + this.negative = 1; + + return this.strip(); + }; + + BN.prototype._wordDiv = function _wordDiv (num, mode) { + var shift = this.length - num.length; + + var a = this.clone(); + var b = num; + + // Normalize + var bhi = b.words[b.length - 1] | 0; + var bhiBits = this._countBits(bhi); + shift = 26 - bhiBits; + if (shift !== 0) { + b = b.ushln(shift); + a.iushln(shift); + bhi = b.words[b.length - 1] | 0; + } + + // Initialize quotient + var m = a.length - b.length; + var q; + + if (mode !== 'mod') { + q = new BN(null); + q.length = m + 1; + q.words = new Array(q.length); + for (var i = 0; i < q.length; i++) { + q.words[i] = 0; + } + } + + var diff = a.clone()._ishlnsubmul(b, 1, m); + if (diff.negative === 0) { + a = diff; + if (q) { + q.words[m] = 1; + } + } + + for (var j = m - 1; j >= 0; j--) { + var qj = (a.words[b.length + j] | 0) * 0x4000000 + + (a.words[b.length + j - 1] | 0); + + // NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max + // (0x7ffffff) + qj = Math.min((qj / bhi) | 0, 0x3ffffff); + + a._ishlnsubmul(b, qj, j); + while (a.negative !== 0) { + qj--; + a.negative = 0; + a._ishlnsubmul(b, 1, j); + if (!a.isZero()) { + a.negative ^= 1; + } + } + if (q) { + q.words[j] = qj; + } + } + if (q) { + q.strip(); + } + a.strip(); + + // Denormalize + if (mode !== 'div' && shift !== 0) { + a.iushrn(shift); + } + + return { + div: q || null, + mod: a + }; + }; + + // NOTE: 1) `mode` can be set to `mod` to request mod only, + // to `div` to request div only, or be absent to + // request both div & mod + // 2) `positive` is true if unsigned mod is requested + BN.prototype.divmod = function divmod (num, mode, positive) { + assert(!num.isZero()); + + if (this.isZero()) { + return { + div: new BN(0), + mod: new BN(0) + }; + } + + var div, mod, res; + if (this.negative !== 0 && num.negative === 0) { + res = this.neg().divmod(num, mode); + + if (mode !== 'mod') { + div = res.div.neg(); + } + + if (mode !== 'div') { + mod = res.mod.neg(); + if (positive && mod.negative !== 0) { + mod.iadd(num); + } + } + + return { + div: div, + mod: mod + }; + } + + if (this.negative === 0 && num.negative !== 0) { + res = this.divmod(num.neg(), mode); + + if (mode !== 'mod') { + div = res.div.neg(); + } + + return { + div: div, + mod: res.mod + }; + } + + if ((this.negative & num.negative) !== 0) { + res = this.neg().divmod(num.neg(), mode); + + if (mode !== 'div') { + mod = res.mod.neg(); + if (positive && mod.negative !== 0) { + mod.isub(num); + } + } + + return { + div: res.div, + mod: mod + }; + } + + // Both numbers are positive at this point + + // Strip both numbers to approximate shift value + if (num.length > this.length || this.cmp(num) < 0) { + return { + div: new BN(0), + mod: this + }; + } + + // Very short reduction + if (num.length === 1) { + if (mode === 'div') { + return { + div: this.divn(num.words[0]), + mod: null + }; + } + + if (mode === 'mod') { + return { + div: null, + mod: new BN(this.modn(num.words[0])) + }; + } + + return { + div: this.divn(num.words[0]), + mod: new BN(this.modn(num.words[0])) + }; + } + + return this._wordDiv(num, mode); + }; + + // Find `this` / `num` + BN.prototype.div = function div (num) { + return this.divmod(num, 'div', false).div; + }; + + // Find `this` % `num` + BN.prototype.mod = function mod (num) { + return this.divmod(num, 'mod', false).mod; + }; + + BN.prototype.umod = function umod (num) { + return this.divmod(num, 'mod', true).mod; + }; + + // Find Round(`this` / `num`) + BN.prototype.divRound = function divRound (num) { + var dm = this.divmod(num); + + // Fast case - exact division + if (dm.mod.isZero()) return dm.div; + + var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod; + + var half = num.ushrn(1); + var r2 = num.andln(1); + var cmp = mod.cmp(half); + + // Round down + if (cmp < 0 || r2 === 1 && cmp === 0) return dm.div; + + // Round up + return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1); + }; + + BN.prototype.modn = function modn (num) { + assert(num <= 0x3ffffff); + var p = (1 << 26) % num; + + var acc = 0; + for (var i = this.length - 1; i >= 0; i--) { + acc = (p * acc + (this.words[i] | 0)) % num; + } + + return acc; + }; + + // In-place division by number + BN.prototype.idivn = function idivn (num) { + assert(num <= 0x3ffffff); + + var carry = 0; + for (var i = this.length - 1; i >= 0; i--) { + var w = (this.words[i] | 0) + carry * 0x4000000; + this.words[i] = (w / num) | 0; + carry = w % num; + } + + return this.strip(); + }; + + BN.prototype.divn = function divn (num) { + return this.clone().idivn(num); + }; + + BN.prototype.egcd = function egcd (p) { + assert(p.negative === 0); + assert(!p.isZero()); + + var x = this; + var y = p.clone(); + + if (x.negative !== 0) { + x = x.umod(p); + } else { + x = x.clone(); + } + + // A * x + B * y = x + var A = new BN(1); + var B = new BN(0); + + // C * x + D * y = y + var C = new BN(0); + var D = new BN(1); + + var g = 0; + + while (x.isEven() && y.isEven()) { + x.iushrn(1); + y.iushrn(1); + ++g; + } + + var yp = y.clone(); + var xp = x.clone(); + + while (!x.isZero()) { + for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1); + if (i > 0) { + x.iushrn(i); + while (i-- > 0) { + if (A.isOdd() || B.isOdd()) { + A.iadd(yp); + B.isub(xp); + } + + A.iushrn(1); + B.iushrn(1); + } + } + + for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); + if (j > 0) { + y.iushrn(j); + while (j-- > 0) { + if (C.isOdd() || D.isOdd()) { + C.iadd(yp); + D.isub(xp); + } + + C.iushrn(1); + D.iushrn(1); + } + } + + if (x.cmp(y) >= 0) { + x.isub(y); + A.isub(C); + B.isub(D); + } else { + y.isub(x); + C.isub(A); + D.isub(B); + } + } + + return { + a: C, + b: D, + gcd: y.iushln(g) + }; + }; + + // This is reduced incarnation of the binary EEA + // above, designated to invert members of the + // _prime_ fields F(p) at a maximal speed + BN.prototype._invmp = function _invmp (p) { + assert(p.negative === 0); + assert(!p.isZero()); + + var a = this; + var b = p.clone(); + + if (a.negative !== 0) { + a = a.umod(p); + } else { + a = a.clone(); + } + + var x1 = new BN(1); + var x2 = new BN(0); + + var delta = b.clone(); + + while (a.cmpn(1) > 0 && b.cmpn(1) > 0) { + for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1); + if (i > 0) { + a.iushrn(i); + while (i-- > 0) { + if (x1.isOdd()) { + x1.iadd(delta); + } + + x1.iushrn(1); + } + } + + for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); + if (j > 0) { + b.iushrn(j); + while (j-- > 0) { + if (x2.isOdd()) { + x2.iadd(delta); + } + + x2.iushrn(1); + } + } + + if (a.cmp(b) >= 0) { + a.isub(b); + x1.isub(x2); + } else { + b.isub(a); + x2.isub(x1); + } + } + + var res; + if (a.cmpn(1) === 0) { + res = x1; + } else { + res = x2; + } + + if (res.cmpn(0) < 0) { + res.iadd(p); + } + + return res; + }; + + BN.prototype.gcd = function gcd (num) { + if (this.isZero()) return num.abs(); + if (num.isZero()) return this.abs(); + + var a = this.clone(); + var b = num.clone(); + a.negative = 0; + b.negative = 0; + + // Remove common factor of two + for (var shift = 0; a.isEven() && b.isEven(); shift++) { + a.iushrn(1); + b.iushrn(1); + } + + do { + while (a.isEven()) { + a.iushrn(1); + } + while (b.isEven()) { + b.iushrn(1); + } + + var r = a.cmp(b); + if (r < 0) { + // Swap `a` and `b` to make `a` always bigger than `b` + var t = a; + a = b; + b = t; + } else if (r === 0 || b.cmpn(1) === 0) { + break; + } + + a.isub(b); + } while (true); + + return b.iushln(shift); + }; + + // Invert number in the field F(num) + BN.prototype.invm = function invm (num) { + return this.egcd(num).a.umod(num); + }; + + BN.prototype.isEven = function isEven () { + return (this.words[0] & 1) === 0; + }; + + BN.prototype.isOdd = function isOdd () { + return (this.words[0] & 1) === 1; + }; + + // And first word and num + BN.prototype.andln = function andln (num) { + return this.words[0] & num; + }; + + // Increment at the bit position in-line + BN.prototype.bincn = function bincn (bit) { + assert(typeof bit === 'number'); + var r = bit % 26; + var s = (bit - r) / 26; + var q = 1 << r; + + // Fast case: bit is much higher than all existing words + if (this.length <= s) { + this._expand(s + 1); + this.words[s] |= q; + return this; + } + + // Add bit and propagate, if needed + var carry = q; + for (var i = s; carry !== 0 && i < this.length; i++) { + var w = this.words[i] | 0; + w += carry; + carry = w >>> 26; + w &= 0x3ffffff; + this.words[i] = w; + } + if (carry !== 0) { + this.words[i] = carry; + this.length++; + } + return this; + }; + + BN.prototype.isZero = function isZero () { + return this.length === 1 && this.words[0] === 0; + }; + + BN.prototype.cmpn = function cmpn (num) { + var negative = num < 0; + + if (this.negative !== 0 && !negative) return -1; + if (this.negative === 0 && negative) return 1; + + this.strip(); + + var res; + if (this.length > 1) { + res = 1; + } else { + if (negative) { + num = -num; + } + + assert(num <= 0x3ffffff, 'Number is too big'); + + var w = this.words[0] | 0; + res = w === num ? 0 : w < num ? -1 : 1; + } + if (this.negative !== 0) return -res | 0; + return res; + }; + + // Compare two numbers and return: + // 1 - if `this` > `num` + // 0 - if `this` == `num` + // -1 - if `this` < `num` + BN.prototype.cmp = function cmp (num) { + if (this.negative !== 0 && num.negative === 0) return -1; + if (this.negative === 0 && num.negative !== 0) return 1; + + var res = this.ucmp(num); + if (this.negative !== 0) return -res | 0; + return res; + }; + + // Unsigned comparison + BN.prototype.ucmp = function ucmp (num) { + // At this point both numbers have the same sign + if (this.length > num.length) return 1; + if (this.length < num.length) return -1; + + var res = 0; + for (var i = this.length - 1; i >= 0; i--) { + var a = this.words[i] | 0; + var b = num.words[i] | 0; + + if (a === b) continue; + if (a < b) { + res = -1; + } else if (a > b) { + res = 1; + } + break; + } + return res; + }; + + BN.prototype.gtn = function gtn (num) { + return this.cmpn(num) === 1; + }; + + BN.prototype.gt = function gt (num) { + return this.cmp(num) === 1; + }; + + BN.prototype.gten = function gten (num) { + return this.cmpn(num) >= 0; + }; + + BN.prototype.gte = function gte (num) { + return this.cmp(num) >= 0; + }; + + BN.prototype.ltn = function ltn (num) { + return this.cmpn(num) === -1; + }; + + BN.prototype.lt = function lt (num) { + return this.cmp(num) === -1; + }; + + BN.prototype.lten = function lten (num) { + return this.cmpn(num) <= 0; + }; + + BN.prototype.lte = function lte (num) { + return this.cmp(num) <= 0; + }; + + BN.prototype.eqn = function eqn (num) { + return this.cmpn(num) === 0; + }; + + BN.prototype.eq = function eq (num) { + return this.cmp(num) === 0; + }; + + // + // A reduce context, could be using montgomery or something better, depending + // on the `m` itself. + // + BN.red = function red (num) { + return new Red(num); + }; + + BN.prototype.toRed = function toRed (ctx) { + assert(!this.red, 'Already a number in reduction context'); + assert(this.negative === 0, 'red works only with positives'); + return ctx.convertTo(this)._forceRed(ctx); + }; + + BN.prototype.fromRed = function fromRed () { + assert(this.red, 'fromRed works only with numbers in reduction context'); + return this.red.convertFrom(this); + }; + + BN.prototype._forceRed = function _forceRed (ctx) { + this.red = ctx; + return this; + }; + + BN.prototype.forceRed = function forceRed (ctx) { + assert(!this.red, 'Already a number in reduction context'); + return this._forceRed(ctx); + }; + + BN.prototype.redAdd = function redAdd (num) { + assert(this.red, 'redAdd works only with red numbers'); + return this.red.add(this, num); + }; + + BN.prototype.redIAdd = function redIAdd (num) { + assert(this.red, 'redIAdd works only with red numbers'); + return this.red.iadd(this, num); + }; + + BN.prototype.redSub = function redSub (num) { + assert(this.red, 'redSub works only with red numbers'); + return this.red.sub(this, num); + }; + + BN.prototype.redISub = function redISub (num) { + assert(this.red, 'redISub works only with red numbers'); + return this.red.isub(this, num); + }; + + BN.prototype.redShl = function redShl (num) { + assert(this.red, 'redShl works only with red numbers'); + return this.red.shl(this, num); + }; + + BN.prototype.redMul = function redMul (num) { + assert(this.red, 'redMul works only with red numbers'); + this.red._verify2(this, num); + return this.red.mul(this, num); + }; + + BN.prototype.redIMul = function redIMul (num) { + assert(this.red, 'redMul works only with red numbers'); + this.red._verify2(this, num); + return this.red.imul(this, num); + }; + + BN.prototype.redSqr = function redSqr () { + assert(this.red, 'redSqr works only with red numbers'); + this.red._verify1(this); + return this.red.sqr(this); + }; + + BN.prototype.redISqr = function redISqr () { + assert(this.red, 'redISqr works only with red numbers'); + this.red._verify1(this); + return this.red.isqr(this); + }; + + // Square root over p + BN.prototype.redSqrt = function redSqrt () { + assert(this.red, 'redSqrt works only with red numbers'); + this.red._verify1(this); + return this.red.sqrt(this); + }; + + BN.prototype.redInvm = function redInvm () { + assert(this.red, 'redInvm works only with red numbers'); + this.red._verify1(this); + return this.red.invm(this); + }; + + // Return negative clone of `this` % `red modulo` + BN.prototype.redNeg = function redNeg () { + assert(this.red, 'redNeg works only with red numbers'); + this.red._verify1(this); + return this.red.neg(this); + }; + + BN.prototype.redPow = function redPow (num) { + assert(this.red && !num.red, 'redPow(normalNum)'); + this.red._verify1(this); + return this.red.pow(this, num); + }; + + // Prime numbers with efficient reduction + var primes = { + k256: null, + p224: null, + p192: null, + p25519: null + }; + + // Pseudo-Mersenne prime + function MPrime (name, p) { + // P = 2 ^ N - K + this.name = name; + this.p = new BN(p, 16); + this.n = this.p.bitLength(); + this.k = new BN(1).iushln(this.n).isub(this.p); + + this.tmp = this._tmp(); + } + + MPrime.prototype._tmp = function _tmp () { + var tmp = new BN(null); + tmp.words = new Array(Math.ceil(this.n / 13)); + return tmp; + }; + + MPrime.prototype.ireduce = function ireduce (num) { + // Assumes that `num` is less than `P^2` + // num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P) + var r = num; + var rlen; + + do { + this.split(r, this.tmp); + r = this.imulK(r); + r = r.iadd(this.tmp); + rlen = r.bitLength(); + } while (rlen > this.n); + + var cmp = rlen < this.n ? -1 : r.ucmp(this.p); + if (cmp === 0) { + r.words[0] = 0; + r.length = 1; + } else if (cmp > 0) { + r.isub(this.p); + } else { + r.strip(); + } + + return r; + }; + + MPrime.prototype.split = function split (input, out) { + input.iushrn(this.n, 0, out); + }; + + MPrime.prototype.imulK = function imulK (num) { + return num.imul(this.k); + }; + + function K256 () { + MPrime.call( + this, + 'k256', + 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f'); + } + inherits(K256, MPrime); + + K256.prototype.split = function split (input, output) { + // 256 = 9 * 26 + 22 + var mask = 0x3fffff; + + var outLen = Math.min(input.length, 9); + for (var i = 0; i < outLen; i++) { + output.words[i] = input.words[i]; + } + output.length = outLen; + + if (input.length <= 9) { + input.words[0] = 0; + input.length = 1; + return; + } + + // Shift by 9 limbs + var prev = input.words[9]; + output.words[output.length++] = prev & mask; + + for (i = 10; i < input.length; i++) { + var next = input.words[i] | 0; + input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22); + prev = next; + } + prev >>>= 22; + input.words[i - 10] = prev; + if (prev === 0 && input.length > 10) { + input.length -= 10; + } else { + input.length -= 9; + } + }; + + K256.prototype.imulK = function imulK (num) { + // K = 0x1000003d1 = [ 0x40, 0x3d1 ] + num.words[num.length] = 0; + num.words[num.length + 1] = 0; + num.length += 2; + + // bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390 + var lo = 0; + for (var i = 0; i < num.length; i++) { + var w = num.words[i] | 0; + lo += w * 0x3d1; + num.words[i] = lo & 0x3ffffff; + lo = w * 0x40 + ((lo / 0x4000000) | 0); + } + + // Fast length reduction + if (num.words[num.length - 1] === 0) { + num.length--; + if (num.words[num.length - 1] === 0) { + num.length--; + } + } + return num; + }; + + function P224 () { + MPrime.call( + this, + 'p224', + 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001'); + } + inherits(P224, MPrime); + + function P192 () { + MPrime.call( + this, + 'p192', + 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff'); + } + inherits(P192, MPrime); + + function P25519 () { + // 2 ^ 255 - 19 + MPrime.call( + this, + '25519', + '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed'); + } + inherits(P25519, MPrime); + + P25519.prototype.imulK = function imulK (num) { + // K = 0x13 + var carry = 0; + for (var i = 0; i < num.length; i++) { + var hi = (num.words[i] | 0) * 0x13 + carry; + var lo = hi & 0x3ffffff; + hi >>>= 26; + + num.words[i] = lo; + carry = hi; + } + if (carry !== 0) { + num.words[num.length++] = carry; + } + return num; + }; + + // Exported mostly for testing purposes, use plain name instead + BN._prime = function prime (name) { + // Cached version of prime + if (primes[name]) return primes[name]; + + var prime; + if (name === 'k256') { + prime = new K256(); + } else if (name === 'p224') { + prime = new P224(); + } else if (name === 'p192') { + prime = new P192(); + } else if (name === 'p25519') { + prime = new P25519(); + } else { + throw new Error('Unknown prime ' + name); + } + primes[name] = prime; + + return prime; + }; + + // + // Base reduction engine + // + function Red (m) { + if (typeof m === 'string') { + var prime = BN._prime(m); + this.m = prime.p; + this.prime = prime; + } else { + assert(m.gtn(1), 'modulus must be greater than 1'); + this.m = m; + this.prime = null; + } + } + + Red.prototype._verify1 = function _verify1 (a) { + assert(a.negative === 0, 'red works only with positives'); + assert(a.red, 'red works only with red numbers'); + }; + + Red.prototype._verify2 = function _verify2 (a, b) { + assert((a.negative | b.negative) === 0, 'red works only with positives'); + assert(a.red && a.red === b.red, + 'red works only with red numbers'); + }; + + Red.prototype.imod = function imod (a) { + if (this.prime) return this.prime.ireduce(a)._forceRed(this); + return a.umod(this.m)._forceRed(this); + }; + + Red.prototype.neg = function neg (a) { + if (a.isZero()) { + return a.clone(); + } + + return this.m.sub(a)._forceRed(this); + }; + + Red.prototype.add = function add (a, b) { + this._verify2(a, b); + + var res = a.add(b); + if (res.cmp(this.m) >= 0) { + res.isub(this.m); + } + return res._forceRed(this); + }; + + Red.prototype.iadd = function iadd (a, b) { + this._verify2(a, b); + + var res = a.iadd(b); + if (res.cmp(this.m) >= 0) { + res.isub(this.m); + } + return res; + }; + + Red.prototype.sub = function sub (a, b) { + this._verify2(a, b); + + var res = a.sub(b); + if (res.cmpn(0) < 0) { + res.iadd(this.m); + } + return res._forceRed(this); + }; + + Red.prototype.isub = function isub (a, b) { + this._verify2(a, b); + + var res = a.isub(b); + if (res.cmpn(0) < 0) { + res.iadd(this.m); + } + return res; + }; + + Red.prototype.shl = function shl (a, num) { + this._verify1(a); + return this.imod(a.ushln(num)); + }; + + Red.prototype.imul = function imul (a, b) { + this._verify2(a, b); + return this.imod(a.imul(b)); + }; + + Red.prototype.mul = function mul (a, b) { + this._verify2(a, b); + return this.imod(a.mul(b)); + }; + + Red.prototype.isqr = function isqr (a) { + return this.imul(a, a.clone()); + }; + + Red.prototype.sqr = function sqr (a) { + return this.mul(a, a); + }; + + Red.prototype.sqrt = function sqrt (a) { + if (a.isZero()) return a.clone(); + + var mod3 = this.m.andln(3); + assert(mod3 % 2 === 1); + + // Fast case + if (mod3 === 3) { + var pow = this.m.add(new BN(1)).iushrn(2); + return this.pow(a, pow); + } + + // Tonelli-Shanks algorithm (Totally unoptimized and slow) + // + // Find Q and S, that Q * 2 ^ S = (P - 1) + var q = this.m.subn(1); + var s = 0; + while (!q.isZero() && q.andln(1) === 0) { + s++; + q.iushrn(1); + } + assert(!q.isZero()); + + var one = new BN(1).toRed(this); + var nOne = one.redNeg(); + + // Find quadratic non-residue + // NOTE: Max is such because of generalized Riemann hypothesis. + var lpow = this.m.subn(1).iushrn(1); + var z = this.m.bitLength(); + z = new BN(2 * z * z).toRed(this); + + while (this.pow(z, lpow).cmp(nOne) !== 0) { + z.redIAdd(nOne); + } + + var c = this.pow(z, q); + var r = this.pow(a, q.addn(1).iushrn(1)); + var t = this.pow(a, q); + var m = s; + while (t.cmp(one) !== 0) { + var tmp = t; + for (var i = 0; tmp.cmp(one) !== 0; i++) { + tmp = tmp.redSqr(); + } + assert(i < m); + var b = this.pow(c, new BN(1).iushln(m - i - 1)); + + r = r.redMul(b); + c = b.redSqr(); + t = t.redMul(c); + m = i; + } + + return r; + }; + + Red.prototype.invm = function invm (a) { + var inv = a._invmp(this.m); + if (inv.negative !== 0) { + inv.negative = 0; + return this.imod(inv).redNeg(); + } else { + return this.imod(inv); + } + }; + + Red.prototype.pow = function pow (a, num) { + if (num.isZero()) return new BN(1).toRed(this); + if (num.cmpn(1) === 0) return a.clone(); + + var windowSize = 4; + var wnd = new Array(1 << windowSize); + wnd[0] = new BN(1).toRed(this); + wnd[1] = a; + for (var i = 2; i < wnd.length; i++) { + wnd[i] = this.mul(wnd[i - 1], a); + } + + var res = wnd[0]; + var current = 0; + var currentLen = 0; + var start = num.bitLength() % 26; + if (start === 0) { + start = 26; + } + + for (i = num.length - 1; i >= 0; i--) { + var word = num.words[i]; + for (var j = start - 1; j >= 0; j--) { + var bit = (word >> j) & 1; + if (res !== wnd[0]) { + res = this.sqr(res); + } + + if (bit === 0 && current === 0) { + currentLen = 0; + continue; + } + + current <<= 1; + current |= bit; + currentLen++; + if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue; + + res = this.mul(res, wnd[current]); + currentLen = 0; + current = 0; + } + start = 26; + } + + return res; + }; + + Red.prototype.convertTo = function convertTo (num) { + var r = num.umod(this.m); + + return r === num ? r.clone() : r; + }; + + Red.prototype.convertFrom = function convertFrom (num) { + var res = num.clone(); + res.red = null; + return res; + }; + + // + // Montgomery method engine + // + + BN.mont = function mont (num) { + return new Mont(num); + }; + + function Mont (m) { + Red.call(this, m); + + this.shift = this.m.bitLength(); + if (this.shift % 26 !== 0) { + this.shift += 26 - (this.shift % 26); + } + + this.r = new BN(1).iushln(this.shift); + this.r2 = this.imod(this.r.sqr()); + this.rinv = this.r._invmp(this.m); + + this.minv = this.rinv.mul(this.r).isubn(1).div(this.m); + this.minv = this.minv.umod(this.r); + this.minv = this.r.sub(this.minv); + } + inherits(Mont, Red); + + Mont.prototype.convertTo = function convertTo (num) { + return this.imod(num.ushln(this.shift)); + }; + + Mont.prototype.convertFrom = function convertFrom (num) { + var r = this.imod(num.mul(this.rinv)); + r.red = null; + return r; + }; + + Mont.prototype.imul = function imul (a, b) { + if (a.isZero() || b.isZero()) { + a.words[0] = 0; + a.length = 1; + return a; + } + + var t = a.imul(b); + var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); + var u = t.isub(c).iushrn(this.shift); + var res = u; + + if (u.cmp(this.m) >= 0) { + res = u.isub(this.m); + } else if (u.cmpn(0) < 0) { + res = u.iadd(this.m); + } + + return res._forceRed(this); + }; + + Mont.prototype.mul = function mul (a, b) { + if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this); + + var t = a.mul(b); + var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); + var u = t.isub(c).iushrn(this.shift); + var res = u; + if (u.cmp(this.m) >= 0) { + res = u.isub(this.m); + } else if (u.cmpn(0) < 0) { + res = u.iadd(this.m); + } + + return res._forceRed(this); + }; + + Mont.prototype.invm = function invm (a) { + // (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R + var res = this.imod(a._invmp(this.m).mul(this.r2)); + return res._forceRed(this); + }; + })(module, commonjsGlobal); + }); + + var bn$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + 'default': bn, + __moduleExports: bn + }); + + /** + * @fileoverview + * BigInteger implementation of basic operations + * Wrapper of bn.js library (wwww.github.com/indutny/bn.js) + * @module biginteger/bn + * @private + */ + + /** + * @private + */ + class BigInteger$1 { + /** + * Get a BigInteger (input must be big endian for strings and arrays) + * @param {Number|String|Uint8Array} n - Value to convert + * @throws {Error} on undefined input + */ + constructor(n) { + if (n === undefined) { + throw new Error('Invalid BigInteger input'); + } + + this.value = new bn(n); + } + + clone() { + const clone = new BigInteger$1(null); + this.value.copy(clone.value); + return clone; + } + + /** + * BigInteger increment in place + */ + iinc() { + this.value.iadd(new bn(1)); + return this; + } + + /** + * BigInteger increment + * @returns {BigInteger} this + 1. + */ + inc() { + return this.clone().iinc(); + } + + /** + * BigInteger decrement in place + */ + idec() { + this.value.isub(new bn(1)); + return this; + } + + /** + * BigInteger decrement + * @returns {BigInteger} this - 1. + */ + dec() { + return this.clone().idec(); + } + + + /** + * BigInteger addition in place + * @param {BigInteger} x - Value to add + */ + iadd(x) { + this.value.iadd(x.value); + return this; + } + + /** + * BigInteger addition + * @param {BigInteger} x - Value to add + * @returns {BigInteger} this + x. + */ + add(x) { + return this.clone().iadd(x); + } + + /** + * BigInteger subtraction in place + * @param {BigInteger} x - Value to subtract + */ + isub(x) { + this.value.isub(x.value); + return this; + } + + /** + * BigInteger subtraction + * @param {BigInteger} x - Value to subtract + * @returns {BigInteger} this - x. + */ + sub(x) { + return this.clone().isub(x); + } + + /** + * BigInteger multiplication in place + * @param {BigInteger} x - Value to multiply + */ + imul(x) { + this.value.imul(x.value); + return this; + } + + /** + * BigInteger multiplication + * @param {BigInteger} x - Value to multiply + * @returns {BigInteger} this * x. + */ + mul(x) { + return this.clone().imul(x); + } + + /** + * Compute value modulo m, in place + * @param {BigInteger} m - Modulo + */ + imod(m) { + this.value = this.value.umod(m.value); + return this; + } + + /** + * Compute value modulo m + * @param {BigInteger} m - Modulo + * @returns {BigInteger} this mod m. + */ + mod(m) { + return this.clone().imod(m); + } + + /** + * Compute modular exponentiation + * Much faster than this.exp(e).mod(n) + * @param {BigInteger} e - Exponent + * @param {BigInteger} n - Modulo + * @returns {BigInteger} this ** e mod n. + */ + modExp(e, n) { + // We use either Montgomery or normal reduction context + // Montgomery requires coprime n and R (montogmery multiplier) + // bn.js picks R as power of 2, so n must be odd + const nred = n.isEven() ? bn.red(n.value) : bn.mont(n.value); + const x = this.clone(); + x.value = x.value.toRed(nred).redPow(e.value).fromRed(); + return x; + } + + /** + * Compute the inverse of this value modulo n + * Note: this and and n must be relatively prime + * @param {BigInteger} n - Modulo + * @returns {BigInteger} x such that this*x = 1 mod n + * @throws {Error} if the inverse does not exist + */ + modInv(n) { + // invm returns a wrong result if the inverse does not exist + if (!this.gcd(n).isOne()) { + throw new Error('Inverse does not exist'); + } + return new BigInteger$1(this.value.invm(n.value)); + } + + /** + * Compute greatest common divisor between this and n + * @param {BigInteger} n - Operand + * @returns {BigInteger} gcd + */ + gcd(n) { + return new BigInteger$1(this.value.gcd(n.value)); + } + + /** + * Shift this to the left by x, in place + * @param {BigInteger} x - Shift value + */ + ileftShift(x) { + this.value.ishln(x.value.toNumber()); + return this; + } + + /** + * Shift this to the left by x + * @param {BigInteger} x - Shift value + * @returns {BigInteger} this << x. + */ + leftShift(x) { + return this.clone().ileftShift(x); + } + + /** + * Shift this to the right by x, in place + * @param {BigInteger} x - Shift value + */ + irightShift(x) { + this.value.ishrn(x.value.toNumber()); + return this; + } + + /** + * Shift this to the right by x + * @param {BigInteger} x - Shift value + * @returns {BigInteger} this >> x. + */ + rightShift(x) { + return this.clone().irightShift(x); + } + + /** + * Whether this value is equal to x + * @param {BigInteger} x + * @returns {Boolean} + */ + equal(x) { + return this.value.eq(x.value); + } + + /** + * Whether this value is less than x + * @param {BigInteger} x + * @returns {Boolean} + */ + lt(x) { + return this.value.lt(x.value); + } + + /** + * Whether this value is less than or equal to x + * @param {BigInteger} x + * @returns {Boolean} + */ + lte(x) { + return this.value.lte(x.value); + } + + /** + * Whether this value is greater than x + * @param {BigInteger} x + * @returns {Boolean} + */ + gt(x) { + return this.value.gt(x.value); + } + + /** + * Whether this value is greater than or equal to x + * @param {BigInteger} x + * @returns {Boolean} + */ + gte(x) { + return this.value.gte(x.value); + } + + isZero() { + return this.value.isZero(); + } + + isOne() { + return this.value.eq(new bn(1)); + } + + isNegative() { + return this.value.isNeg(); + } + + isEven() { + return this.value.isEven(); + } + + abs() { + const res = this.clone(); + res.value = res.value.abs(); + return res; + } + + /** + * Get this value as a string + * @returns {String} this value. + */ + toString() { + return this.value.toString(); + } + + /** + * Get this value as an exact Number (max 53 bits) + * Fails if this value is too large + * @returns {Number} + */ + toNumber() { + return this.value.toNumber(); + } + + /** + * Get value of i-th bit + * @param {Number} i - Bit index + * @returns {Number} Bit value. + */ + getBit(i) { + return this.value.testn(i) ? 1 : 0; + } + + /** + * Compute bit length + * @returns {Number} Bit length. + */ + bitLength() { + return this.value.bitLength(); + } + + /** + * Compute byte length + * @returns {Number} Byte length. + */ + byteLength() { + return this.value.byteLength(); + } + + /** + * Get Uint8Array representation of this number + * @param {String} endian - Endianess of output array (defaults to 'be') + * @param {Number} length - Of output array + * @returns {Uint8Array} + */ + toUint8Array(endian = 'be', length) { + return this.value.toArrayLike(Uint8Array, endian, length); + } + } + + var bn_interface = /*#__PURE__*/Object.freeze({ + __proto__: null, + 'default': BigInteger$1 + }); + + var utils_1 = createCommonjsModule(function (module, exports) { + + var utils = exports; + + function toArray(msg, enc) { + if (Array.isArray(msg)) + return msg.slice(); + if (!msg) + return []; + var res = []; + if (typeof msg !== 'string') { + for (var i = 0; i < msg.length; i++) + res[i] = msg[i] | 0; + return res; + } + if (enc === 'hex') { + msg = msg.replace(/[^a-z0-9]+/ig, ''); + if (msg.length % 2 !== 0) + msg = '0' + msg; + for (var i = 0; i < msg.length; i += 2) + res.push(parseInt(msg[i] + msg[i + 1], 16)); + } else { + for (var i = 0; i < msg.length; i++) { + var c = msg.charCodeAt(i); + var hi = c >> 8; + var lo = c & 0xff; + if (hi) + res.push(hi, lo); + else + res.push(lo); + } + } + return res; + } + utils.toArray = toArray; + + function zero2(word) { + if (word.length === 1) + return '0' + word; + else + return word; + } + utils.zero2 = zero2; + + function toHex(msg) { + var res = ''; + for (var i = 0; i < msg.length; i++) + res += zero2(msg[i].toString(16)); + return res; + } + utils.toHex = toHex; + + utils.encode = function encode(arr, enc) { + if (enc === 'hex') + return toHex(arr); + else + return arr; + }; + }); + + var utils_1$1 = createCommonjsModule(function (module, exports) { + + var utils = exports; + + + + + utils.assert = minimalisticAssert; + utils.toArray = utils_1.toArray; + utils.zero2 = utils_1.zero2; + utils.toHex = utils_1.toHex; + utils.encode = utils_1.encode; + + // Represent num in a w-NAF form + function getNAF(num, w) { + var naf = []; + var ws = 1 << (w + 1); + var k = num.clone(); + while (k.cmpn(1) >= 0) { + var z; + if (k.isOdd()) { + var mod = k.andln(ws - 1); + if (mod > (ws >> 1) - 1) + z = (ws >> 1) - mod; + else + z = mod; + k.isubn(z); + } else { + z = 0; + } + naf.push(z); + + // Optimization, shift by word if possible + var shift = (k.cmpn(0) !== 0 && k.andln(ws - 1) === 0) ? (w + 1) : 1; + for (var i = 1; i < shift; i++) + naf.push(0); + k.iushrn(shift); + } + + return naf; + } + utils.getNAF = getNAF; + + // Represent k1, k2 in a Joint Sparse Form + function getJSF(k1, k2) { + var jsf = [ + [], + [] + ]; + + k1 = k1.clone(); + k2 = k2.clone(); + var d1 = 0; + var d2 = 0; + while (k1.cmpn(-d1) > 0 || k2.cmpn(-d2) > 0) { + + // First phase + var m14 = (k1.andln(3) + d1) & 3; + var m24 = (k2.andln(3) + d2) & 3; + if (m14 === 3) + m14 = -1; + if (m24 === 3) + m24 = -1; + var u1; + if ((m14 & 1) === 0) { + u1 = 0; + } else { + var m8 = (k1.andln(7) + d1) & 7; + if ((m8 === 3 || m8 === 5) && m24 === 2) + u1 = -m14; + else + u1 = m14; + } + jsf[0].push(u1); + + var u2; + if ((m24 & 1) === 0) { + u2 = 0; + } else { + var m8 = (k2.andln(7) + d2) & 7; + if ((m8 === 3 || m8 === 5) && m14 === 2) + u2 = -m24; + else + u2 = m24; + } + jsf[1].push(u2); + + // Second phase + if (2 * d1 === u1 + 1) + d1 = 1 - d1; + if (2 * d2 === u2 + 1) + d2 = 1 - d2; + k1.iushrn(1); + k2.iushrn(1); + } + + return jsf; + } + utils.getJSF = getJSF; + + function cachedProperty(obj, name, computer) { + var key = '_' + name; + obj.prototype[name] = function cachedProperty() { + return this[key] !== undefined ? this[key] : + this[key] = computer.call(this); + }; + } + utils.cachedProperty = cachedProperty; + + function parseBytes(bytes) { + return typeof bytes === 'string' ? utils.toArray(bytes, 'hex') : + bytes; + } + utils.parseBytes = parseBytes; + + function intFromLE(bytes) { + return new bn(bytes, 'hex', 'le'); + } + utils.intFromLE = intFromLE; + }); + + var r$1; + + var brorand = function rand(len) { + if (!r$1) + r$1 = new Rand(null); + + return r$1.generate(len); + }; + + function Rand(rand) { + this.rand = rand; + } + var Rand_1 = Rand; + + Rand.prototype.generate = function generate(len) { + return this._rand(len); + }; + + // Emulate crypto API using randy + Rand.prototype._rand = function _rand(n) { + if (this.rand.getBytes) + return this.rand.getBytes(n); + + var res = new Uint8Array(n); + for (var i = 0; i < res.length; i++) + res[i] = this.rand.getByte(); + return res; + }; + + if (typeof self === 'object') { + if (self.crypto && self.crypto.getRandomValues) { + // Modern browsers + Rand.prototype._rand = function _rand(n) { + var arr = new Uint8Array(n); + self.crypto.getRandomValues(arr); + return arr; + }; + } else if (self.msCrypto && self.msCrypto.getRandomValues) { + // IE + Rand.prototype._rand = function _rand(n) { + var arr = new Uint8Array(n); + self.msCrypto.getRandomValues(arr); + return arr; + }; + + // Safari's WebWorkers do not have `crypto` + } else if (typeof window === 'object') { + // Old junk + Rand.prototype._rand = function() { + throw new Error('Not implemented yet'); + }; + } + } else { + // Node.js or Web worker with no crypto support + try { + var crypto$2 = void('crypto'); + if (typeof crypto$2.randomBytes !== 'function') + throw new Error('Not supported'); + + Rand.prototype._rand = function _rand(n) { + return crypto$2.randomBytes(n); + }; + } catch (e) { + } + } + brorand.Rand = Rand_1; + + var getNAF = utils_1$1.getNAF; + var getJSF = utils_1$1.getJSF; + var assert$2 = utils_1$1.assert; + + function BaseCurve(type, conf) { + this.type = type; + this.p = new bn(conf.p, 16); + + // Use Montgomery, when there is no fast reduction for the prime + this.red = conf.prime ? bn.red(conf.prime) : bn.mont(this.p); + + // Useful for many curves + this.zero = new bn(0).toRed(this.red); + this.one = new bn(1).toRed(this.red); + this.two = new bn(2).toRed(this.red); + + // Curve configuration, optional + this.n = conf.n && new bn(conf.n, 16); + this.g = conf.g && this.pointFromJSON(conf.g, conf.gRed); + + // Temporary arrays + this._wnafT1 = new Array(4); + this._wnafT2 = new Array(4); + this._wnafT3 = new Array(4); + this._wnafT4 = new Array(4); + + // Generalized Greg Maxwell's trick + var adjustCount = this.n && this.p.div(this.n); + if (!adjustCount || adjustCount.cmpn(100) > 0) { + this.redN = null; + } else { + this._maxwellTrick = true; + this.redN = this.n.toRed(this.red); + } + } + var base = BaseCurve; + + BaseCurve.prototype.point = function point() { + throw new Error('Not implemented'); + }; + + BaseCurve.prototype.validate = function validate() { + throw new Error('Not implemented'); + }; + + BaseCurve.prototype._fixedNafMul = function _fixedNafMul(p, k) { + assert$2(p.precomputed); + var doubles = p._getDoubles(); + + var naf = getNAF(k, 1); + var I = (1 << (doubles.step + 1)) - (doubles.step % 2 === 0 ? 2 : 1); + I /= 3; + + // Translate into more windowed form + var repr = []; + for (var j = 0; j < naf.length; j += doubles.step) { + var nafW = 0; + for (var k = j + doubles.step - 1; k >= j; k--) + nafW = (nafW << 1) + naf[k]; + repr.push(nafW); + } + + var a = this.jpoint(null, null, null); + var b = this.jpoint(null, null, null); + for (var i = I; i > 0; i--) { + for (var j = 0; j < repr.length; j++) { + var nafW = repr[j]; + if (nafW === i) + b = b.mixedAdd(doubles.points[j]); + else if (nafW === -i) + b = b.mixedAdd(doubles.points[j].neg()); + } + a = a.add(b); + } + return a.toP(); + }; + + BaseCurve.prototype._wnafMul = function _wnafMul(p, k) { + var w = 4; + + // Precompute window + var nafPoints = p._getNAFPoints(w); + w = nafPoints.wnd; + var wnd = nafPoints.points; + + // Get NAF form + var naf = getNAF(k, w); + + // Add `this`*(N+1) for every w-NAF index + var acc = this.jpoint(null, null, null); + for (var i = naf.length - 1; i >= 0; i--) { + // Count zeroes + for (var k = 0; i >= 0 && naf[i] === 0; i--) + k++; + if (i >= 0) + k++; + acc = acc.dblp(k); + + if (i < 0) + break; + var z = naf[i]; + assert$2(z !== 0); + if (p.type === 'affine') { + // J +- P + if (z > 0) + acc = acc.mixedAdd(wnd[(z - 1) >> 1]); + else + acc = acc.mixedAdd(wnd[(-z - 1) >> 1].neg()); + } else { + // J +- J + if (z > 0) + acc = acc.add(wnd[(z - 1) >> 1]); + else + acc = acc.add(wnd[(-z - 1) >> 1].neg()); + } + } + return p.type === 'affine' ? acc.toP() : acc; + }; + + BaseCurve.prototype._wnafMulAdd = function _wnafMulAdd(defW, + points, + coeffs, + len, + jacobianResult) { + var wndWidth = this._wnafT1; + var wnd = this._wnafT2; + var naf = this._wnafT3; + + // Fill all arrays + var max = 0; + for (var i = 0; i < len; i++) { + var p = points[i]; + var nafPoints = p._getNAFPoints(defW); + wndWidth[i] = nafPoints.wnd; + wnd[i] = nafPoints.points; + } + + // Comb small window NAFs + for (var i = len - 1; i >= 1; i -= 2) { + var a = i - 1; + var b = i; + if (wndWidth[a] !== 1 || wndWidth[b] !== 1) { + naf[a] = getNAF(coeffs[a], wndWidth[a]); + naf[b] = getNAF(coeffs[b], wndWidth[b]); + max = Math.max(naf[a].length, max); + max = Math.max(naf[b].length, max); + continue; + } + + var comb = [ + points[a], /* 1 */ + null, /* 3 */ + null, /* 5 */ + points[b] /* 7 */ + ]; + + // Try to avoid Projective points, if possible + if (points[a].y.cmp(points[b].y) === 0) { + comb[1] = points[a].add(points[b]); + comb[2] = points[a].toJ().mixedAdd(points[b].neg()); + } else if (points[a].y.cmp(points[b].y.redNeg()) === 0) { + comb[1] = points[a].toJ().mixedAdd(points[b]); + comb[2] = points[a].add(points[b].neg()); + } else { + comb[1] = points[a].toJ().mixedAdd(points[b]); + comb[2] = points[a].toJ().mixedAdd(points[b].neg()); + } + + var index = [ + -3, /* -1 -1 */ + -1, /* -1 0 */ + -5, /* -1 1 */ + -7, /* 0 -1 */ + 0, /* 0 0 */ + 7, /* 0 1 */ + 5, /* 1 -1 */ + 1, /* 1 0 */ + 3 /* 1 1 */ + ]; + + var jsf = getJSF(coeffs[a], coeffs[b]); + max = Math.max(jsf[0].length, max); + naf[a] = new Array(max); + naf[b] = new Array(max); + for (var j = 0; j < max; j++) { + var ja = jsf[0][j] | 0; + var jb = jsf[1][j] | 0; + + naf[a][j] = index[(ja + 1) * 3 + (jb + 1)]; + naf[b][j] = 0; + wnd[a] = comb; + } + } + + var acc = this.jpoint(null, null, null); + var tmp = this._wnafT4; + for (var i = max; i >= 0; i--) { + var k = 0; + + while (i >= 0) { + var zero = true; + for (var j = 0; j < len; j++) { + tmp[j] = naf[j][i] | 0; + if (tmp[j] !== 0) + zero = false; + } + if (!zero) + break; + k++; + i--; + } + if (i >= 0) + k++; + acc = acc.dblp(k); + if (i < 0) + break; + + for (var j = 0; j < len; j++) { + var z = tmp[j]; + var p; + if (z === 0) + continue; + else if (z > 0) + p = wnd[j][(z - 1) >> 1]; + else if (z < 0) + p = wnd[j][(-z - 1) >> 1].neg(); + + if (p.type === 'affine') + acc = acc.mixedAdd(p); + else + acc = acc.add(p); + } + } + // Zeroify references + for (var i = 0; i < len; i++) + wnd[i] = null; + + if (jacobianResult) + return acc; + else + return acc.toP(); + }; + + function BasePoint(curve, type) { + this.curve = curve; + this.type = type; + this.precomputed = null; + } + BaseCurve.BasePoint = BasePoint; + + BasePoint.prototype.eq = function eq(/*other*/) { + throw new Error('Not implemented'); + }; + + BasePoint.prototype.validate = function validate() { + return this.curve.validate(this); + }; + + BaseCurve.prototype.decodePoint = function decodePoint(bytes, enc) { + bytes = utils_1$1.toArray(bytes, enc); + + var len = this.p.byteLength(); + + // uncompressed, hybrid-odd, hybrid-even + if ((bytes[0] === 0x04 || bytes[0] === 0x06 || bytes[0] === 0x07) && + bytes.length - 1 === 2 * len) { + if (bytes[0] === 0x06) + assert$2(bytes[bytes.length - 1] % 2 === 0); + else if (bytes[0] === 0x07) + assert$2(bytes[bytes.length - 1] % 2 === 1); + + var res = this.point(bytes.slice(1, 1 + len), + bytes.slice(1 + len, 1 + 2 * len)); + + return res; + } else if ((bytes[0] === 0x02 || bytes[0] === 0x03) && + bytes.length - 1 === len) { + return this.pointFromX(bytes.slice(1, 1 + len), bytes[0] === 0x03); + } + throw new Error('Unknown point format'); + }; + + BasePoint.prototype.encodeCompressed = function encodeCompressed(enc) { + return this.encode(enc, true); + }; + + BasePoint.prototype._encode = function _encode(compact) { + var len = this.curve.p.byteLength(); + var x = this.getX().toArray('be', len); + + if (compact) + return [ this.getY().isEven() ? 0x02 : 0x03 ].concat(x); + + return [ 0x04 ].concat(x, this.getY().toArray('be', len)) ; + }; + + BasePoint.prototype.encode = function encode(enc, compact) { + return utils_1$1.encode(this._encode(compact), enc); + }; + + BasePoint.prototype.precompute = function precompute(power) { + if (this.precomputed) + return this; + + var precomputed = { + doubles: null, + naf: null, + beta: null + }; + precomputed.naf = this._getNAFPoints(8); + precomputed.doubles = this._getDoubles(4, power); + precomputed.beta = this._getBeta(); + this.precomputed = precomputed; + + return this; + }; + + BasePoint.prototype._hasDoubles = function _hasDoubles(k) { + if (!this.precomputed) + return false; + + var doubles = this.precomputed.doubles; + if (!doubles) + return false; + + return doubles.points.length >= Math.ceil((k.bitLength() + 1) / doubles.step); + }; + + BasePoint.prototype._getDoubles = function _getDoubles(step, power) { + if (this.precomputed && this.precomputed.doubles) + return this.precomputed.doubles; + + var doubles = [ this ]; + var acc = this; + for (var i = 0; i < power; i += step) { + for (var j = 0; j < step; j++) + acc = acc.dbl(); + doubles.push(acc); + } + return { + step: step, + points: doubles + }; + }; + + BasePoint.prototype._getNAFPoints = function _getNAFPoints(wnd) { + if (this.precomputed && this.precomputed.naf) + return this.precomputed.naf; + + var res = [ this ]; + var max = (1 << wnd) - 1; + var dbl = max === 1 ? null : this.dbl(); + for (var i = 1; i < max; i++) + res[i] = res[i - 1].add(dbl); + return { + wnd: wnd, + points: res + }; + }; + + BasePoint.prototype._getBeta = function _getBeta() { + return null; + }; + + BasePoint.prototype.dblp = function dblp(k) { + var r = this; + for (var i = 0; i < k; i++) + r = r.dbl(); + return r; + }; + + var assert$3 = utils_1$1.assert; + + function ShortCurve(conf) { + base.call(this, 'short', conf); + + this.a = new bn(conf.a, 16).toRed(this.red); + this.b = new bn(conf.b, 16).toRed(this.red); + this.tinv = this.two.redInvm(); + + this.zeroA = this.a.fromRed().cmpn(0) === 0; + this.threeA = this.a.fromRed().sub(this.p).cmpn(-3) === 0; + + // If the curve is endomorphic, precalculate beta and lambda + this.endo = this._getEndomorphism(conf); + this._endoWnafT1 = new Array(4); + this._endoWnafT2 = new Array(4); + } + inherits_browser(ShortCurve, base); + var short_1 = ShortCurve; + + ShortCurve.prototype._getEndomorphism = function _getEndomorphism(conf) { + // No efficient endomorphism + if (!this.zeroA || !this.g || !this.n || this.p.modn(3) !== 1) + return; + + // Compute beta and lambda, that lambda * P = (beta * Px; Py) + var beta; + var lambda; + if (conf.beta) { + beta = new bn(conf.beta, 16).toRed(this.red); + } else { + var betas = this._getEndoRoots(this.p); + // Choose the smallest beta + beta = betas[0].cmp(betas[1]) < 0 ? betas[0] : betas[1]; + beta = beta.toRed(this.red); + } + if (conf.lambda) { + lambda = new bn(conf.lambda, 16); + } else { + // Choose the lambda that is matching selected beta + var lambdas = this._getEndoRoots(this.n); + if (this.g.mul(lambdas[0]).x.cmp(this.g.x.redMul(beta)) === 0) { + lambda = lambdas[0]; + } else { + lambda = lambdas[1]; + assert$3(this.g.mul(lambda).x.cmp(this.g.x.redMul(beta)) === 0); + } + } + + // Get basis vectors, used for balanced length-two representation + var basis; + if (conf.basis) { + basis = conf.basis.map(function(vec) { + return { + a: new bn(vec.a, 16), + b: new bn(vec.b, 16) + }; + }); + } else { + basis = this._getEndoBasis(lambda); + } + + return { + beta: beta, + lambda: lambda, + basis: basis + }; + }; + + ShortCurve.prototype._getEndoRoots = function _getEndoRoots(num) { + // Find roots of for x^2 + x + 1 in F + // Root = (-1 +- Sqrt(-3)) / 2 + // + var red = num === this.p ? this.red : bn.mont(num); + var tinv = new bn(2).toRed(red).redInvm(); + var ntinv = tinv.redNeg(); + + var s = new bn(3).toRed(red).redNeg().redSqrt().redMul(tinv); + + var l1 = ntinv.redAdd(s).fromRed(); + var l2 = ntinv.redSub(s).fromRed(); + return [ l1, l2 ]; + }; + + ShortCurve.prototype._getEndoBasis = function _getEndoBasis(lambda) { + // aprxSqrt >= sqrt(this.n) + var aprxSqrt = this.n.ushrn(Math.floor(this.n.bitLength() / 2)); + + // 3.74 + // Run EGCD, until r(L + 1) < aprxSqrt + var u = lambda; + var v = this.n.clone(); + var x1 = new bn(1); + var y1 = new bn(0); + var x2 = new bn(0); + var y2 = new bn(1); + + // NOTE: all vectors are roots of: a + b * lambda = 0 (mod n) + var a0; + var b0; + // First vector + var a1; + var b1; + // Second vector + var a2; + var b2; + + var prevR; + var i = 0; + var r; + var x; + while (u.cmpn(0) !== 0) { + var q = v.div(u); + r = v.sub(q.mul(u)); + x = x2.sub(q.mul(x1)); + var y = y2.sub(q.mul(y1)); + + if (!a1 && r.cmp(aprxSqrt) < 0) { + a0 = prevR.neg(); + b0 = x1; + a1 = r.neg(); + b1 = x; + } else if (a1 && ++i === 2) { + break; + } + prevR = r; + + v = u; + u = r; + x2 = x1; + x1 = x; + y2 = y1; + y1 = y; + } + a2 = r.neg(); + b2 = x; + + var len1 = a1.sqr().add(b1.sqr()); + var len2 = a2.sqr().add(b2.sqr()); + if (len2.cmp(len1) >= 0) { + a2 = a0; + b2 = b0; + } + + // Normalize signs + if (a1.negative) { + a1 = a1.neg(); + b1 = b1.neg(); + } + if (a2.negative) { + a2 = a2.neg(); + b2 = b2.neg(); + } + + return [ + { a: a1, b: b1 }, + { a: a2, b: b2 } + ]; + }; + + ShortCurve.prototype._endoSplit = function _endoSplit(k) { + var basis = this.endo.basis; + var v1 = basis[0]; + var v2 = basis[1]; + + var c1 = v2.b.mul(k).divRound(this.n); + var c2 = v1.b.neg().mul(k).divRound(this.n); + + var p1 = c1.mul(v1.a); + var p2 = c2.mul(v2.a); + var q1 = c1.mul(v1.b); + var q2 = c2.mul(v2.b); + + // Calculate answer + var k1 = k.sub(p1).sub(p2); + var k2 = q1.add(q2).neg(); + return { k1: k1, k2: k2 }; + }; + + ShortCurve.prototype.pointFromX = function pointFromX(x, odd) { + x = new bn(x, 16); + if (!x.red) + x = x.toRed(this.red); + + var y2 = x.redSqr().redMul(x).redIAdd(x.redMul(this.a)).redIAdd(this.b); + var y = y2.redSqrt(); + if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) + throw new Error('invalid point'); + + // XXX Is there any way to tell if the number is odd without converting it + // to non-red form? + var isOdd = y.fromRed().isOdd(); + if (odd && !isOdd || !odd && isOdd) + y = y.redNeg(); + + return this.point(x, y); + }; + + ShortCurve.prototype.validate = function validate(point) { + if (point.inf) + return true; + + var x = point.x; + var y = point.y; + + var ax = this.a.redMul(x); + var rhs = x.redSqr().redMul(x).redIAdd(ax).redIAdd(this.b); + return y.redSqr().redISub(rhs).cmpn(0) === 0; + }; + + ShortCurve.prototype._endoWnafMulAdd = + function _endoWnafMulAdd(points, coeffs, jacobianResult) { + var npoints = this._endoWnafT1; + var ncoeffs = this._endoWnafT2; + for (var i = 0; i < points.length; i++) { + var split = this._endoSplit(coeffs[i]); + var p = points[i]; + var beta = p._getBeta(); + + if (split.k1.negative) { + split.k1.ineg(); + p = p.neg(true); + } + if (split.k2.negative) { + split.k2.ineg(); + beta = beta.neg(true); + } + + npoints[i * 2] = p; + npoints[i * 2 + 1] = beta; + ncoeffs[i * 2] = split.k1; + ncoeffs[i * 2 + 1] = split.k2; + } + var res = this._wnafMulAdd(1, npoints, ncoeffs, i * 2, jacobianResult); + + // Clean-up references to points and coefficients + for (var j = 0; j < i * 2; j++) { + npoints[j] = null; + ncoeffs[j] = null; + } + return res; + }; + + function Point(curve, x, y, isRed) { + base.BasePoint.call(this, curve, 'affine'); + if (x === null && y === null) { + this.x = null; + this.y = null; + this.inf = true; + } else { + this.x = new bn(x, 16); + this.y = new bn(y, 16); + // Force redgomery representation when loading from JSON + if (isRed) { + this.x.forceRed(this.curve.red); + this.y.forceRed(this.curve.red); + } + if (!this.x.red) + this.x = this.x.toRed(this.curve.red); + if (!this.y.red) + this.y = this.y.toRed(this.curve.red); + this.inf = false; + } + } + inherits_browser(Point, base.BasePoint); + + ShortCurve.prototype.point = function point(x, y, isRed) { + return new Point(this, x, y, isRed); + }; + + ShortCurve.prototype.pointFromJSON = function pointFromJSON(obj, red) { + return Point.fromJSON(this, obj, red); + }; + + Point.prototype._getBeta = function _getBeta() { + if (!this.curve.endo) + return; + + var pre = this.precomputed; + if (pre && pre.beta) + return pre.beta; + + var beta = this.curve.point(this.x.redMul(this.curve.endo.beta), this.y); + if (pre) { + var curve = this.curve; + var endoMul = function(p) { + return curve.point(p.x.redMul(curve.endo.beta), p.y); + }; + pre.beta = beta; + beta.precomputed = { + beta: null, + naf: pre.naf && { + wnd: pre.naf.wnd, + points: pre.naf.points.map(endoMul) + }, + doubles: pre.doubles && { + step: pre.doubles.step, + points: pre.doubles.points.map(endoMul) + } + }; + } + return beta; + }; + + Point.prototype.toJSON = function toJSON() { + if (!this.precomputed) + return [ this.x, this.y ]; + + return [ this.x, this.y, this.precomputed && { + doubles: this.precomputed.doubles && { + step: this.precomputed.doubles.step, + points: this.precomputed.doubles.points.slice(1) + }, + naf: this.precomputed.naf && { + wnd: this.precomputed.naf.wnd, + points: this.precomputed.naf.points.slice(1) + } + } ]; + }; + + Point.fromJSON = function fromJSON(curve, obj, red) { + if (typeof obj === 'string') + obj = JSON.parse(obj); + var res = curve.point(obj[0], obj[1], red); + if (!obj[2]) + return res; + + function obj2point(obj) { + return curve.point(obj[0], obj[1], red); + } + + var pre = obj[2]; + res.precomputed = { + beta: null, + doubles: pre.doubles && { + step: pre.doubles.step, + points: [ res ].concat(pre.doubles.points.map(obj2point)) + }, + naf: pre.naf && { + wnd: pre.naf.wnd, + points: [ res ].concat(pre.naf.points.map(obj2point)) + } + }; + return res; + }; + + Point.prototype.inspect = function inspect() { + if (this.isInfinity()) + return ''; + return ''; + }; + + Point.prototype.isInfinity = function isInfinity() { + return this.inf; + }; + + Point.prototype.add = function add(p) { + // O + P = P + if (this.inf) + return p; + + // P + O = P + if (p.inf) + return this; + + // P + P = 2P + if (this.eq(p)) + return this.dbl(); + + // P + (-P) = O + if (this.neg().eq(p)) + return this.curve.point(null, null); + + // P + Q = O + if (this.x.cmp(p.x) === 0) + return this.curve.point(null, null); + + var c = this.y.redSub(p.y); + if (c.cmpn(0) !== 0) + c = c.redMul(this.x.redSub(p.x).redInvm()); + var nx = c.redSqr().redISub(this.x).redISub(p.x); + var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); + return this.curve.point(nx, ny); + }; + + Point.prototype.dbl = function dbl() { + if (this.inf) + return this; + + // 2P = O + var ys1 = this.y.redAdd(this.y); + if (ys1.cmpn(0) === 0) + return this.curve.point(null, null); + + var a = this.curve.a; + + var x2 = this.x.redSqr(); + var dyinv = ys1.redInvm(); + var c = x2.redAdd(x2).redIAdd(x2).redIAdd(a).redMul(dyinv); + + var nx = c.redSqr().redISub(this.x.redAdd(this.x)); + var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); + return this.curve.point(nx, ny); + }; + + Point.prototype.getX = function getX() { + return this.x.fromRed(); + }; + + Point.prototype.getY = function getY() { + return this.y.fromRed(); + }; + + Point.prototype.mul = function mul(k) { + k = new bn(k, 16); + if (this.isInfinity()) + return this; + else if (this._hasDoubles(k)) + return this.curve._fixedNafMul(this, k); + else if (this.curve.endo) + return this.curve._endoWnafMulAdd([ this ], [ k ]); + else + return this.curve._wnafMul(this, k); + }; + + Point.prototype.mulAdd = function mulAdd(k1, p2, k2) { + var points = [ this, p2 ]; + var coeffs = [ k1, k2 ]; + if (this.curve.endo) + return this.curve._endoWnafMulAdd(points, coeffs); + else + return this.curve._wnafMulAdd(1, points, coeffs, 2); + }; + + Point.prototype.jmulAdd = function jmulAdd(k1, p2, k2) { + var points = [ this, p2 ]; + var coeffs = [ k1, k2 ]; + if (this.curve.endo) + return this.curve._endoWnafMulAdd(points, coeffs, true); + else + return this.curve._wnafMulAdd(1, points, coeffs, 2, true); + }; + + Point.prototype.eq = function eq(p) { + return this === p || + this.inf === p.inf && + (this.inf || this.x.cmp(p.x) === 0 && this.y.cmp(p.y) === 0); + }; + + Point.prototype.neg = function neg(_precompute) { + if (this.inf) + return this; + + var res = this.curve.point(this.x, this.y.redNeg()); + if (_precompute && this.precomputed) { + var pre = this.precomputed; + var negate = function(p) { + return p.neg(); + }; + res.precomputed = { + naf: pre.naf && { + wnd: pre.naf.wnd, + points: pre.naf.points.map(negate) + }, + doubles: pre.doubles && { + step: pre.doubles.step, + points: pre.doubles.points.map(negate) + } + }; + } + return res; + }; + + Point.prototype.toJ = function toJ() { + if (this.inf) + return this.curve.jpoint(null, null, null); + + var res = this.curve.jpoint(this.x, this.y, this.curve.one); + return res; + }; + + function JPoint(curve, x, y, z) { + base.BasePoint.call(this, curve, 'jacobian'); + if (x === null && y === null && z === null) { + this.x = this.curve.one; + this.y = this.curve.one; + this.z = new bn(0); + } else { + this.x = new bn(x, 16); + this.y = new bn(y, 16); + this.z = new bn(z, 16); + } + if (!this.x.red) + this.x = this.x.toRed(this.curve.red); + if (!this.y.red) + this.y = this.y.toRed(this.curve.red); + if (!this.z.red) + this.z = this.z.toRed(this.curve.red); + + this.zOne = this.z === this.curve.one; + } + inherits_browser(JPoint, base.BasePoint); + + ShortCurve.prototype.jpoint = function jpoint(x, y, z) { + return new JPoint(this, x, y, z); + }; + + JPoint.prototype.toP = function toP() { + if (this.isInfinity()) + return this.curve.point(null, null); + + var zinv = this.z.redInvm(); + var zinv2 = zinv.redSqr(); + var ax = this.x.redMul(zinv2); + var ay = this.y.redMul(zinv2).redMul(zinv); + + return this.curve.point(ax, ay); + }; + + JPoint.prototype.neg = function neg() { + return this.curve.jpoint(this.x, this.y.redNeg(), this.z); + }; + + JPoint.prototype.add = function add(p) { + // O + P = P + if (this.isInfinity()) + return p; + + // P + O = P + if (p.isInfinity()) + return this; + + // 12M + 4S + 7A + var pz2 = p.z.redSqr(); + var z2 = this.z.redSqr(); + var u1 = this.x.redMul(pz2); + var u2 = p.x.redMul(z2); + var s1 = this.y.redMul(pz2.redMul(p.z)); + var s2 = p.y.redMul(z2.redMul(this.z)); + + var h = u1.redSub(u2); + var r = s1.redSub(s2); + if (h.cmpn(0) === 0) { + if (r.cmpn(0) !== 0) + return this.curve.jpoint(null, null, null); + else + return this.dbl(); + } + + var h2 = h.redSqr(); + var h3 = h2.redMul(h); + var v = u1.redMul(h2); + + var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); + var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); + var nz = this.z.redMul(p.z).redMul(h); + + return this.curve.jpoint(nx, ny, nz); + }; + + JPoint.prototype.mixedAdd = function mixedAdd(p) { + // O + P = P + if (this.isInfinity()) + return p.toJ(); + + // P + O = P + if (p.isInfinity()) + return this; + + // 8M + 3S + 7A + var z2 = this.z.redSqr(); + var u1 = this.x; + var u2 = p.x.redMul(z2); + var s1 = this.y; + var s2 = p.y.redMul(z2).redMul(this.z); + + var h = u1.redSub(u2); + var r = s1.redSub(s2); + if (h.cmpn(0) === 0) { + if (r.cmpn(0) !== 0) + return this.curve.jpoint(null, null, null); + else + return this.dbl(); + } + + var h2 = h.redSqr(); + var h3 = h2.redMul(h); + var v = u1.redMul(h2); + + var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); + var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); + var nz = this.z.redMul(h); + + return this.curve.jpoint(nx, ny, nz); + }; + + JPoint.prototype.dblp = function dblp(pow) { + if (pow === 0) + return this; + if (this.isInfinity()) + return this; + if (!pow) + return this.dbl(); + + if (this.curve.zeroA || this.curve.threeA) { + var r = this; + for (var i = 0; i < pow; i++) + r = r.dbl(); + return r; + } + + // 1M + 2S + 1A + N * (4S + 5M + 8A) + // N = 1 => 6M + 6S + 9A + var a = this.curve.a; + var tinv = this.curve.tinv; + + var jx = this.x; + var jy = this.y; + var jz = this.z; + var jz4 = jz.redSqr().redSqr(); + + // Reuse results + var jyd = jy.redAdd(jy); + for (var i = 0; i < pow; i++) { + var jx2 = jx.redSqr(); + var jyd2 = jyd.redSqr(); + var jyd4 = jyd2.redSqr(); + var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); + + var t1 = jx.redMul(jyd2); + var nx = c.redSqr().redISub(t1.redAdd(t1)); + var t2 = t1.redISub(nx); + var dny = c.redMul(t2); + dny = dny.redIAdd(dny).redISub(jyd4); + var nz = jyd.redMul(jz); + if (i + 1 < pow) + jz4 = jz4.redMul(jyd4); + + jx = nx; + jz = nz; + jyd = dny; + } + + return this.curve.jpoint(jx, jyd.redMul(tinv), jz); + }; + + JPoint.prototype.dbl = function dbl() { + if (this.isInfinity()) + return this; + + if (this.curve.zeroA) + return this._zeroDbl(); + else if (this.curve.threeA) + return this._threeDbl(); + else + return this._dbl(); + }; + + JPoint.prototype._zeroDbl = function _zeroDbl() { + var nx; + var ny; + var nz; + // Z = 1 + if (this.zOne) { + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html + // #doubling-mdbl-2007-bl + // 1M + 5S + 14A + + // XX = X1^2 + var xx = this.x.redSqr(); + // YY = Y1^2 + var yy = this.y.redSqr(); + // YYYY = YY^2 + var yyyy = yy.redSqr(); + // S = 2 * ((X1 + YY)^2 - XX - YYYY) + var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); + s = s.redIAdd(s); + // M = 3 * XX + a; a = 0 + var m = xx.redAdd(xx).redIAdd(xx); + // T = M ^ 2 - 2*S + var t = m.redSqr().redISub(s).redISub(s); + + // 8 * YYYY + var yyyy8 = yyyy.redIAdd(yyyy); + yyyy8 = yyyy8.redIAdd(yyyy8); + yyyy8 = yyyy8.redIAdd(yyyy8); + + // X3 = T + nx = t; + // Y3 = M * (S - T) - 8 * YYYY + ny = m.redMul(s.redISub(t)).redISub(yyyy8); + // Z3 = 2*Y1 + nz = this.y.redAdd(this.y); + } else { + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html + // #doubling-dbl-2009-l + // 2M + 5S + 13A + + // A = X1^2 + var a = this.x.redSqr(); + // B = Y1^2 + var b = this.y.redSqr(); + // C = B^2 + var c = b.redSqr(); + // D = 2 * ((X1 + B)^2 - A - C) + var d = this.x.redAdd(b).redSqr().redISub(a).redISub(c); + d = d.redIAdd(d); + // E = 3 * A + var e = a.redAdd(a).redIAdd(a); + // F = E^2 + var f = e.redSqr(); + + // 8 * C + var c8 = c.redIAdd(c); + c8 = c8.redIAdd(c8); + c8 = c8.redIAdd(c8); + + // X3 = F - 2 * D + nx = f.redISub(d).redISub(d); + // Y3 = E * (D - X3) - 8 * C + ny = e.redMul(d.redISub(nx)).redISub(c8); + // Z3 = 2 * Y1 * Z1 + nz = this.y.redMul(this.z); + nz = nz.redIAdd(nz); + } + + return this.curve.jpoint(nx, ny, nz); + }; + + JPoint.prototype._threeDbl = function _threeDbl() { + var nx; + var ny; + var nz; + // Z = 1 + if (this.zOne) { + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html + // #doubling-mdbl-2007-bl + // 1M + 5S + 15A + + // XX = X1^2 + var xx = this.x.redSqr(); + // YY = Y1^2 + var yy = this.y.redSqr(); + // YYYY = YY^2 + var yyyy = yy.redSqr(); + // S = 2 * ((X1 + YY)^2 - XX - YYYY) + var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); + s = s.redIAdd(s); + // M = 3 * XX + a + var m = xx.redAdd(xx).redIAdd(xx).redIAdd(this.curve.a); + // T = M^2 - 2 * S + var t = m.redSqr().redISub(s).redISub(s); + // X3 = T + nx = t; + // Y3 = M * (S - T) - 8 * YYYY + var yyyy8 = yyyy.redIAdd(yyyy); + yyyy8 = yyyy8.redIAdd(yyyy8); + yyyy8 = yyyy8.redIAdd(yyyy8); + ny = m.redMul(s.redISub(t)).redISub(yyyy8); + // Z3 = 2 * Y1 + nz = this.y.redAdd(this.y); + } else { + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b + // 3M + 5S + + // delta = Z1^2 + var delta = this.z.redSqr(); + // gamma = Y1^2 + var gamma = this.y.redSqr(); + // beta = X1 * gamma + var beta = this.x.redMul(gamma); + // alpha = 3 * (X1 - delta) * (X1 + delta) + var alpha = this.x.redSub(delta).redMul(this.x.redAdd(delta)); + alpha = alpha.redAdd(alpha).redIAdd(alpha); + // X3 = alpha^2 - 8 * beta + var beta4 = beta.redIAdd(beta); + beta4 = beta4.redIAdd(beta4); + var beta8 = beta4.redAdd(beta4); + nx = alpha.redSqr().redISub(beta8); + // Z3 = (Y1 + Z1)^2 - gamma - delta + nz = this.y.redAdd(this.z).redSqr().redISub(gamma).redISub(delta); + // Y3 = alpha * (4 * beta - X3) - 8 * gamma^2 + var ggamma8 = gamma.redSqr(); + ggamma8 = ggamma8.redIAdd(ggamma8); + ggamma8 = ggamma8.redIAdd(ggamma8); + ggamma8 = ggamma8.redIAdd(ggamma8); + ny = alpha.redMul(beta4.redISub(nx)).redISub(ggamma8); + } + + return this.curve.jpoint(nx, ny, nz); + }; + + JPoint.prototype._dbl = function _dbl() { + var a = this.curve.a; + + // 4M + 6S + 10A + var jx = this.x; + var jy = this.y; + var jz = this.z; + var jz4 = jz.redSqr().redSqr(); + + var jx2 = jx.redSqr(); + var jy2 = jy.redSqr(); + + var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); + + var jxd4 = jx.redAdd(jx); + jxd4 = jxd4.redIAdd(jxd4); + var t1 = jxd4.redMul(jy2); + var nx = c.redSqr().redISub(t1.redAdd(t1)); + var t2 = t1.redISub(nx); + + var jyd8 = jy2.redSqr(); + jyd8 = jyd8.redIAdd(jyd8); + jyd8 = jyd8.redIAdd(jyd8); + jyd8 = jyd8.redIAdd(jyd8); + var ny = c.redMul(t2).redISub(jyd8); + var nz = jy.redAdd(jy).redMul(jz); + + return this.curve.jpoint(nx, ny, nz); + }; + + JPoint.prototype.trpl = function trpl() { + if (!this.curve.zeroA) + return this.dbl().add(this); + + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#tripling-tpl-2007-bl + // 5M + 10S + ... + + // XX = X1^2 + var xx = this.x.redSqr(); + // YY = Y1^2 + var yy = this.y.redSqr(); + // ZZ = Z1^2 + var zz = this.z.redSqr(); + // YYYY = YY^2 + var yyyy = yy.redSqr(); + // M = 3 * XX + a * ZZ2; a = 0 + var m = xx.redAdd(xx).redIAdd(xx); + // MM = M^2 + var mm = m.redSqr(); + // E = 6 * ((X1 + YY)^2 - XX - YYYY) - MM + var e = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); + e = e.redIAdd(e); + e = e.redAdd(e).redIAdd(e); + e = e.redISub(mm); + // EE = E^2 + var ee = e.redSqr(); + // T = 16*YYYY + var t = yyyy.redIAdd(yyyy); + t = t.redIAdd(t); + t = t.redIAdd(t); + t = t.redIAdd(t); + // U = (M + E)^2 - MM - EE - T + var u = m.redIAdd(e).redSqr().redISub(mm).redISub(ee).redISub(t); + // X3 = 4 * (X1 * EE - 4 * YY * U) + var yyu4 = yy.redMul(u); + yyu4 = yyu4.redIAdd(yyu4); + yyu4 = yyu4.redIAdd(yyu4); + var nx = this.x.redMul(ee).redISub(yyu4); + nx = nx.redIAdd(nx); + nx = nx.redIAdd(nx); + // Y3 = 8 * Y1 * (U * (T - U) - E * EE) + var ny = this.y.redMul(u.redMul(t.redISub(u)).redISub(e.redMul(ee))); + ny = ny.redIAdd(ny); + ny = ny.redIAdd(ny); + ny = ny.redIAdd(ny); + // Z3 = (Z1 + E)^2 - ZZ - EE + var nz = this.z.redAdd(e).redSqr().redISub(zz).redISub(ee); + + return this.curve.jpoint(nx, ny, nz); + }; + + JPoint.prototype.mul = function mul(k, kbase) { + k = new bn(k, kbase); + + return this.curve._wnafMul(this, k); + }; + + JPoint.prototype.eq = function eq(p) { + if (p.type === 'affine') + return this.eq(p.toJ()); + + if (this === p) + return true; + + // x1 * z2^2 == x2 * z1^2 + var z2 = this.z.redSqr(); + var pz2 = p.z.redSqr(); + if (this.x.redMul(pz2).redISub(p.x.redMul(z2)).cmpn(0) !== 0) + return false; + + // y1 * z2^3 == y2 * z1^3 + var z3 = z2.redMul(this.z); + var pz3 = pz2.redMul(p.z); + return this.y.redMul(pz3).redISub(p.y.redMul(z3)).cmpn(0) === 0; + }; + + JPoint.prototype.eqXToP = function eqXToP(x) { + var zs = this.z.redSqr(); + var rx = x.toRed(this.curve.red).redMul(zs); + if (this.x.cmp(rx) === 0) + return true; + + var xc = x.clone(); + var t = this.curve.redN.redMul(zs); + for (;;) { + xc.iadd(this.curve.n); + if (xc.cmp(this.curve.p) >= 0) + return false; + + rx.redIAdd(t); + if (this.x.cmp(rx) === 0) + return true; + } + }; + + JPoint.prototype.inspect = function inspect() { + if (this.isInfinity()) + return ''; + return ''; + }; + + JPoint.prototype.isInfinity = function isInfinity() { + // XXX This code assumes that zero is always zero in red + return this.z.cmpn(0) === 0; + }; + + function MontCurve(conf) { + base.call(this, 'mont', conf); + + this.a = new bn(conf.a, 16).toRed(this.red); + this.b = new bn(conf.b, 16).toRed(this.red); + this.i4 = new bn(4).toRed(this.red).redInvm(); + this.two = new bn(2).toRed(this.red); + // Note: this implementation is according to the original paper + // by P. Montgomery, NOT the one by D. J. Bernstein. + this.a24 = this.i4.redMul(this.a.redAdd(this.two)); + } + inherits_browser(MontCurve, base); + var mont = MontCurve; + + MontCurve.prototype.validate = function validate(point) { + var x = point.normalize().x; + var x2 = x.redSqr(); + var rhs = x2.redMul(x).redAdd(x2.redMul(this.a)).redAdd(x); + var y = rhs.redSqrt(); + + return y.redSqr().cmp(rhs) === 0; + }; + + function Point$1(curve, x, z) { + base.BasePoint.call(this, curve, 'projective'); + if (x === null && z === null) { + this.x = this.curve.one; + this.z = this.curve.zero; + } else { + this.x = new bn(x, 16); + this.z = new bn(z, 16); + if (!this.x.red) + this.x = this.x.toRed(this.curve.red); + if (!this.z.red) + this.z = this.z.toRed(this.curve.red); + } + } + inherits_browser(Point$1, base.BasePoint); + + MontCurve.prototype.decodePoint = function decodePoint(bytes, enc) { + var bytes = utils_1$1.toArray(bytes, enc); + + // TODO Curve448 + // Montgomery curve points must be represented in the compressed format + // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B + if (bytes.length === 33 && bytes[0] === 0x40) + bytes = bytes.slice(1, 33).reverse(); // point must be little-endian + if (bytes.length !== 32) + throw new Error('Unknown point compression format'); + return this.point(bytes, 1); + }; + + MontCurve.prototype.point = function point(x, z) { + return new Point$1(this, x, z); + }; + + MontCurve.prototype.pointFromJSON = function pointFromJSON(obj) { + return Point$1.fromJSON(this, obj); + }; + + Point$1.prototype.precompute = function precompute() { + // No-op + }; + + Point$1.prototype._encode = function _encode(compact) { + var len = this.curve.p.byteLength(); + + // Note: the output should always be little-endian + // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B + if (compact) { + return [ 0x40 ].concat(this.getX().toArray('le', len)); + } else { + return this.getX().toArray('be', len); + } + }; + + Point$1.fromJSON = function fromJSON(curve, obj) { + return new Point$1(curve, obj[0], obj[1] || curve.one); + }; + + Point$1.prototype.inspect = function inspect() { + if (this.isInfinity()) + return ''; + return ''; + }; + + Point$1.prototype.isInfinity = function isInfinity() { + // XXX This code assumes that zero is always zero in red + return this.z.cmpn(0) === 0; + }; + + Point$1.prototype.dbl = function dbl() { + // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#doubling-dbl-1987-m-3 + // 2M + 2S + 4A + + // A = X1 + Z1 + var a = this.x.redAdd(this.z); + // AA = A^2 + var aa = a.redSqr(); + // B = X1 - Z1 + var b = this.x.redSub(this.z); + // BB = B^2 + var bb = b.redSqr(); + // C = AA - BB + var c = aa.redSub(bb); + // X3 = AA * BB + var nx = aa.redMul(bb); + // Z3 = C * (BB + A24 * C) + var nz = c.redMul(bb.redAdd(this.curve.a24.redMul(c))); + return this.curve.point(nx, nz); + }; + + Point$1.prototype.add = function add() { + throw new Error('Not supported on Montgomery curve'); + }; + + Point$1.prototype.diffAdd = function diffAdd(p, diff) { + // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#diffadd-dadd-1987-m-3 + // 4M + 2S + 6A + + // A = X2 + Z2 + var a = this.x.redAdd(this.z); + // B = X2 - Z2 + var b = this.x.redSub(this.z); + // C = X3 + Z3 + var c = p.x.redAdd(p.z); + // D = X3 - Z3 + var d = p.x.redSub(p.z); + // DA = D * A + var da = d.redMul(a); + // CB = C * B + var cb = c.redMul(b); + // X5 = Z1 * (DA + CB)^2 + var nx = diff.z.redMul(da.redAdd(cb).redSqr()); + // Z5 = X1 * (DA - CB)^2 + var nz = diff.x.redMul(da.redISub(cb).redSqr()); + return this.curve.point(nx, nz); + }; + + Point$1.prototype.mul = function mul(k) { + k = new bn(k, 16); + + var t = k.clone(); + var a = this; // (N / 2) * Q + Q + var b = this.curve.point(null, null); // (N / 2) * Q + var c = this; // Q + + for (var bits = []; t.cmpn(0) !== 0; t.iushrn(1)) + bits.push(t.andln(1)); + + for (var i = bits.length - 1; i >= 0; i--) { + if (bits[i] === 0) { + // N * Q + Q = ((N / 2) * Q + Q)) + (N / 2) * Q + a = a.diffAdd(b, c); + // N * Q = 2 * ((N / 2) * Q + Q)) + b = b.dbl(); + } else { + // N * Q = ((N / 2) * Q + Q) + ((N / 2) * Q) + b = a.diffAdd(b, c); + // N * Q + Q = 2 * ((N / 2) * Q + Q) + a = a.dbl(); + } + } + return b; + }; + + Point$1.prototype.mulAdd = function mulAdd() { + throw new Error('Not supported on Montgomery curve'); + }; + + Point$1.prototype.jumlAdd = function jumlAdd() { + throw new Error('Not supported on Montgomery curve'); + }; + + Point$1.prototype.eq = function eq(other) { + return this.getX().cmp(other.getX()) === 0; + }; + + Point$1.prototype.normalize = function normalize() { + this.x = this.x.redMul(this.z.redInvm()); + this.z = this.curve.one; + return this; + }; + + Point$1.prototype.getX = function getX() { + // Normalize coordinates + this.normalize(); + + return this.x.fromRed(); + }; + + var assert$4 = utils_1$1.assert; + + function EdwardsCurve(conf) { + // NOTE: Important as we are creating point in Base.call() + this.twisted = (conf.a | 0) !== 1; + this.mOneA = this.twisted && (conf.a | 0) === -1; + this.extended = this.mOneA; + + base.call(this, 'edwards', conf); + + this.a = new bn(conf.a, 16).umod(this.red.m); + this.a = this.a.toRed(this.red); + this.c = new bn(conf.c, 16).toRed(this.red); + this.c2 = this.c.redSqr(); + this.d = new bn(conf.d, 16).toRed(this.red); + this.dd = this.d.redAdd(this.d); + + assert$4(!this.twisted || this.c.fromRed().cmpn(1) === 0); + this.oneC = (conf.c | 0) === 1; + } + inherits_browser(EdwardsCurve, base); + var edwards = EdwardsCurve; + + EdwardsCurve.prototype._mulA = function _mulA(num) { + if (this.mOneA) + return num.redNeg(); + else + return this.a.redMul(num); + }; + + EdwardsCurve.prototype._mulC = function _mulC(num) { + if (this.oneC) + return num; + else + return this.c.redMul(num); + }; + + // Just for compatibility with Short curve + EdwardsCurve.prototype.jpoint = function jpoint(x, y, z, t) { + return this.point(x, y, z, t); + }; + + EdwardsCurve.prototype.pointFromX = function pointFromX(x, odd) { + x = new bn(x, 16); + if (!x.red) + x = x.toRed(this.red); + + var x2 = x.redSqr(); + var rhs = this.c2.redSub(this.a.redMul(x2)); + var lhs = this.one.redSub(this.c2.redMul(this.d).redMul(x2)); + + var y2 = rhs.redMul(lhs.redInvm()); + var y = y2.redSqrt(); + if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) + throw new Error('invalid point'); + + var isOdd = y.fromRed().isOdd(); + if (odd && !isOdd || !odd && isOdd) + y = y.redNeg(); + + return this.point(x, y); + }; + + EdwardsCurve.prototype.pointFromY = function pointFromY(y, odd) { + y = new bn(y, 16); + if (!y.red) + y = y.toRed(this.red); + + // x^2 = (y^2 - c^2) / (c^2 d y^2 - a) + var y2 = y.redSqr(); + var lhs = y2.redSub(this.c2); + var rhs = y2.redMul(this.d).redMul(this.c2).redSub(this.a); + var x2 = lhs.redMul(rhs.redInvm()); + + if (x2.cmp(this.zero) === 0) { + if (odd) + throw new Error('invalid point'); + else + return this.point(this.zero, y); + } + + var x = x2.redSqrt(); + if (x.redSqr().redSub(x2).cmp(this.zero) !== 0) + throw new Error('invalid point'); + + if (x.fromRed().isOdd() !== odd) + x = x.redNeg(); + + return this.point(x, y); + }; + + EdwardsCurve.prototype.validate = function validate(point) { + if (point.isInfinity()) + return true; + + // Curve: A * X^2 + Y^2 = C^2 * (1 + D * X^2 * Y^2) + point.normalize(); + + var x2 = point.x.redSqr(); + var y2 = point.y.redSqr(); + var lhs = x2.redMul(this.a).redAdd(y2); + var rhs = this.c2.redMul(this.one.redAdd(this.d.redMul(x2).redMul(y2))); + + return lhs.cmp(rhs) === 0; + }; + + function Point$2(curve, x, y, z, t) { + base.BasePoint.call(this, curve, 'projective'); + if (x === null && y === null && z === null) { + this.x = this.curve.zero; + this.y = this.curve.one; + this.z = this.curve.one; + this.t = this.curve.zero; + this.zOne = true; + } else { + this.x = new bn(x, 16); + this.y = new bn(y, 16); + this.z = z ? new bn(z, 16) : this.curve.one; + this.t = t && new bn(t, 16); + if (!this.x.red) + this.x = this.x.toRed(this.curve.red); + if (!this.y.red) + this.y = this.y.toRed(this.curve.red); + if (!this.z.red) + this.z = this.z.toRed(this.curve.red); + if (this.t && !this.t.red) + this.t = this.t.toRed(this.curve.red); + this.zOne = this.z === this.curve.one; + + // Use extended coordinates + if (this.curve.extended && !this.t) { + this.t = this.x.redMul(this.y); + if (!this.zOne) + this.t = this.t.redMul(this.z.redInvm()); + } + } + } + inherits_browser(Point$2, base.BasePoint); + + EdwardsCurve.prototype.pointFromJSON = function pointFromJSON(obj) { + return Point$2.fromJSON(this, obj); + }; + + EdwardsCurve.prototype.point = function point(x, y, z, t) { + return new Point$2(this, x, y, z, t); + }; + + Point$2.fromJSON = function fromJSON(curve, obj) { + return new Point$2(curve, obj[0], obj[1], obj[2]); + }; + + Point$2.prototype.inspect = function inspect() { + if (this.isInfinity()) + return ''; + return ''; + }; + + Point$2.prototype.isInfinity = function isInfinity() { + // XXX This code assumes that zero is always zero in red + return this.x.cmpn(0) === 0 && + (this.y.cmp(this.z) === 0 || + (this.zOne && this.y.cmp(this.curve.c) === 0)); + }; + + Point$2.prototype._extDbl = function _extDbl() { + // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html + // #doubling-dbl-2008-hwcd + // 4M + 4S + + // A = X1^2 + var a = this.x.redSqr(); + // B = Y1^2 + var b = this.y.redSqr(); + // C = 2 * Z1^2 + var c = this.z.redSqr(); + c = c.redIAdd(c); + // D = a * A + var d = this.curve._mulA(a); + // E = (X1 + Y1)^2 - A - B + var e = this.x.redAdd(this.y).redSqr().redISub(a).redISub(b); + // G = D + B + var g = d.redAdd(b); + // F = G - C + var f = g.redSub(c); + // H = D - B + var h = d.redSub(b); + // X3 = E * F + var nx = e.redMul(f); + // Y3 = G * H + var ny = g.redMul(h); + // T3 = E * H + var nt = e.redMul(h); + // Z3 = F * G + var nz = f.redMul(g); + return this.curve.point(nx, ny, nz, nt); + }; + + Point$2.prototype._projDbl = function _projDbl() { + // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html + // #doubling-dbl-2008-bbjlp + // #doubling-dbl-2007-bl + // and others + // Generally 3M + 4S or 2M + 4S + + // B = (X1 + Y1)^2 + var b = this.x.redAdd(this.y).redSqr(); + // C = X1^2 + var c = this.x.redSqr(); + // D = Y1^2 + var d = this.y.redSqr(); + + var nx; + var ny; + var nz; + if (this.curve.twisted) { + // E = a * C + var e = this.curve._mulA(c); + // F = E + D + var f = e.redAdd(d); + if (this.zOne) { + // X3 = (B - C - D) * (F - 2) + nx = b.redSub(c).redSub(d).redMul(f.redSub(this.curve.two)); + // Y3 = F * (E - D) + ny = f.redMul(e.redSub(d)); + // Z3 = F^2 - 2 * F + nz = f.redSqr().redSub(f).redSub(f); + } else { + // H = Z1^2 + var h = this.z.redSqr(); + // J = F - 2 * H + var j = f.redSub(h).redISub(h); + // X3 = (B-C-D)*J + nx = b.redSub(c).redISub(d).redMul(j); + // Y3 = F * (E - D) + ny = f.redMul(e.redSub(d)); + // Z3 = F * J + nz = f.redMul(j); + } + } else { + // E = C + D + var e = c.redAdd(d); + // H = (c * Z1)^2 + var h = this.curve._mulC(this.z).redSqr(); + // J = E - 2 * H + var j = e.redSub(h).redSub(h); + // X3 = c * (B - E) * J + nx = this.curve._mulC(b.redISub(e)).redMul(j); + // Y3 = c * E * (C - D) + ny = this.curve._mulC(e).redMul(c.redISub(d)); + // Z3 = E * J + nz = e.redMul(j); + } + return this.curve.point(nx, ny, nz); + }; + + Point$2.prototype.dbl = function dbl() { + if (this.isInfinity()) + return this; + + // Double in extended coordinates + if (this.curve.extended) + return this._extDbl(); + else + return this._projDbl(); + }; + + Point$2.prototype._extAdd = function _extAdd(p) { + // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html + // #addition-add-2008-hwcd-3 + // 8M + + // A = (Y1 - X1) * (Y2 - X2) + var a = this.y.redSub(this.x).redMul(p.y.redSub(p.x)); + // B = (Y1 + X1) * (Y2 + X2) + var b = this.y.redAdd(this.x).redMul(p.y.redAdd(p.x)); + // C = T1 * k * T2 + var c = this.t.redMul(this.curve.dd).redMul(p.t); + // D = Z1 * 2 * Z2 + var d = this.z.redMul(p.z.redAdd(p.z)); + // E = B - A + var e = b.redSub(a); + // F = D - C + var f = d.redSub(c); + // G = D + C + var g = d.redAdd(c); + // H = B + A + var h = b.redAdd(a); + // X3 = E * F + var nx = e.redMul(f); + // Y3 = G * H + var ny = g.redMul(h); + // T3 = E * H + var nt = e.redMul(h); + // Z3 = F * G + var nz = f.redMul(g); + return this.curve.point(nx, ny, nz, nt); + }; + + Point$2.prototype._projAdd = function _projAdd(p) { + // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html + // #addition-add-2008-bbjlp + // #addition-add-2007-bl + // 10M + 1S + + // A = Z1 * Z2 + var a = this.z.redMul(p.z); + // B = A^2 + var b = a.redSqr(); + // C = X1 * X2 + var c = this.x.redMul(p.x); + // D = Y1 * Y2 + var d = this.y.redMul(p.y); + // E = d * C * D + var e = this.curve.d.redMul(c).redMul(d); + // F = B - E + var f = b.redSub(e); + // G = B + E + var g = b.redAdd(e); + // X3 = A * F * ((X1 + Y1) * (X2 + Y2) - C - D) + var tmp = this.x.redAdd(this.y).redMul(p.x.redAdd(p.y)).redISub(c).redISub(d); + var nx = a.redMul(f).redMul(tmp); + var ny; + var nz; + if (this.curve.twisted) { + // Y3 = A * G * (D - a * C) + ny = a.redMul(g).redMul(d.redSub(this.curve._mulA(c))); + // Z3 = F * G + nz = f.redMul(g); + } else { + // Y3 = A * G * (D - C) + ny = a.redMul(g).redMul(d.redSub(c)); + // Z3 = c * F * G + nz = this.curve._mulC(f).redMul(g); + } + return this.curve.point(nx, ny, nz); + }; + + Point$2.prototype.add = function add(p) { + if (this.isInfinity()) + return p; + if (p.isInfinity()) + return this; + + if (this.curve.extended) + return this._extAdd(p); + else + return this._projAdd(p); + }; + + Point$2.prototype.mul = function mul(k) { + if (this._hasDoubles(k)) + return this.curve._fixedNafMul(this, k); + else + return this.curve._wnafMul(this, k); + }; + + Point$2.prototype.mulAdd = function mulAdd(k1, p, k2) { + return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, false); + }; + + Point$2.prototype.jmulAdd = function jmulAdd(k1, p, k2) { + return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, true); + }; + + Point$2.prototype.normalize = function normalize() { + if (this.zOne) + return this; + + // Normalize coordinates + var zi = this.z.redInvm(); + this.x = this.x.redMul(zi); + this.y = this.y.redMul(zi); + if (this.t) + this.t = this.t.redMul(zi); + this.z = this.curve.one; + this.zOne = true; + return this; + }; + + Point$2.prototype.neg = function neg() { + return this.curve.point(this.x.redNeg(), + this.y, + this.z, + this.t && this.t.redNeg()); + }; + + Point$2.prototype.getX = function getX() { + this.normalize(); + return this.x.fromRed(); + }; + + Point$2.prototype.getY = function getY() { + this.normalize(); + return this.y.fromRed(); + }; + + Point$2.prototype.eq = function eq(other) { + return this === other || + this.getX().cmp(other.getX()) === 0 && + this.getY().cmp(other.getY()) === 0; + }; + + Point$2.prototype.eqXToP = function eqXToP(x) { + var rx = x.toRed(this.curve.red).redMul(this.z); + if (this.x.cmp(rx) === 0) + return true; + + var xc = x.clone(); + var t = this.curve.redN.redMul(this.z); + for (;;) { + xc.iadd(this.curve.n); + if (xc.cmp(this.curve.p) >= 0) + return false; + + rx.redIAdd(t); + if (this.x.cmp(rx) === 0) + return true; + } + }; + + // Compatibility with BaseCurve + Point$2.prototype.toP = Point$2.prototype.normalize; + Point$2.prototype.mixedAdd = Point$2.prototype.add; + + var curve_1 = createCommonjsModule(function (module, exports) { + + var curve = exports; + + curve.base = base; + curve.short = short_1; + curve.mont = mont; + curve.edwards = edwards; + }); + + var rotl32$2 = utils.rotl32; + var sum32$3 = utils.sum32; + var sum32_5$2 = utils.sum32_5; + var ft_1$1 = common$1.ft_1; + var BlockHash$4 = common.BlockHash; + + var sha1_K = [ + 0x5A827999, 0x6ED9EBA1, + 0x8F1BBCDC, 0xCA62C1D6 + ]; + + function SHA1() { + if (!(this instanceof SHA1)) + return new SHA1(); + + BlockHash$4.call(this); + this.h = [ + 0x67452301, 0xefcdab89, 0x98badcfe, + 0x10325476, 0xc3d2e1f0 ]; + this.W = new Array(80); + } + + utils.inherits(SHA1, BlockHash$4); + var _1 = SHA1; + + SHA1.blockSize = 512; + SHA1.outSize = 160; + SHA1.hmacStrength = 80; + SHA1.padLength = 64; + + SHA1.prototype._update = function _update(msg, start) { + var W = this.W; + + for (var i = 0; i < 16; i++) + W[i] = msg[start + i]; + + for(; i < W.length; i++) + W[i] = rotl32$2(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1); + + var a = this.h[0]; + var b = this.h[1]; + var c = this.h[2]; + var d = this.h[3]; + var e = this.h[4]; + + for (i = 0; i < W.length; i++) { + var s = ~~(i / 20); + var t = sum32_5$2(rotl32$2(a, 5), ft_1$1(s, b, c, d), e, W[i], sha1_K[s]); + e = d; + d = c; + c = rotl32$2(b, 30); + b = a; + a = t; + } + + this.h[0] = sum32$3(this.h[0], a); + this.h[1] = sum32$3(this.h[1], b); + this.h[2] = sum32$3(this.h[2], c); + this.h[3] = sum32$3(this.h[3], d); + this.h[4] = sum32$3(this.h[4], e); + }; + + SHA1.prototype._digest = function digest(enc) { + if (enc === 'hex') + return utils.toHex32(this.h, 'big'); + else + return utils.split32(this.h, 'big'); + }; + + var sha1 = _1; + var sha224 = _224; + var sha256 = _256; + var sha384 = _384; + var sha512 = _512; + + var sha = { + sha1: sha1, + sha224: sha224, + sha256: sha256, + sha384: sha384, + sha512: sha512 + }; + + function Hmac(hash, key, enc) { + if (!(this instanceof Hmac)) + return new Hmac(hash, key, enc); + this.Hash = hash; + this.blockSize = hash.blockSize / 8; + this.outSize = hash.outSize / 8; + this.inner = null; + this.outer = null; + + this._init(utils.toArray(key, enc)); + } + var hmac = Hmac; + + Hmac.prototype._init = function init(key) { + // Shorten key, if needed + if (key.length > this.blockSize) + key = new this.Hash().update(key).digest(); + minimalisticAssert(key.length <= this.blockSize); + + // Add padding to key + for (var i = key.length; i < this.blockSize; i++) + key.push(0); + + for (i = 0; i < key.length; i++) + key[i] ^= 0x36; + this.inner = new this.Hash().update(key); + + // 0x36 ^ 0x5c = 0x6a + for (i = 0; i < key.length; i++) + key[i] ^= 0x6a; + this.outer = new this.Hash().update(key); + }; + + Hmac.prototype.update = function update(msg, enc) { + this.inner.update(msg, enc); + return this; + }; + + Hmac.prototype.digest = function digest(enc) { + this.outer.update(this.inner.digest()); + return this.outer.digest(enc); + }; + + var hash_1 = createCommonjsModule(function (module, exports) { + var hash = exports; + + hash.utils = utils; + hash.common = common; + hash.sha = sha; + hash.ripemd = ripemd; + hash.hmac = hmac; + + // Proxy hash functions to the main object + hash.sha1 = hash.sha.sha1; + hash.sha256 = hash.sha.sha256; + hash.sha224 = hash.sha.sha224; + hash.sha384 = hash.sha.sha384; + hash.sha512 = hash.sha.sha512; + hash.ripemd160 = hash.ripemd.ripemd160; + }); + + var secp256k1 = { + doubles: { + step: 4, + points: [ + [ + 'e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a', + 'f7e3507399e595929db99f34f57937101296891e44d23f0be1f32cce69616821' + ], + [ + '8282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508', + '11f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf' + ], + [ + '175e159f728b865a72f99cc6c6fc846de0b93833fd2222ed73fce5b551e5b739', + 'd3506e0d9e3c79eba4ef97a51ff71f5eacb5955add24345c6efa6ffee9fed695' + ], + [ + '363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640', + '4e273adfc732221953b445397f3363145b9a89008199ecb62003c7f3bee9de9' + ], + [ + '8b4b5f165df3c2be8c6244b5b745638843e4a781a15bcd1b69f79a55dffdf80c', + '4aad0a6f68d308b4b3fbd7813ab0da04f9e336546162ee56b3eff0c65fd4fd36' + ], + [ + '723cbaa6e5db996d6bf771c00bd548c7b700dbffa6c0e77bcb6115925232fcda', + '96e867b5595cc498a921137488824d6e2660a0653779494801dc069d9eb39f5f' + ], + [ + 'eebfa4d493bebf98ba5feec812c2d3b50947961237a919839a533eca0e7dd7fa', + '5d9a8ca3970ef0f269ee7edaf178089d9ae4cdc3a711f712ddfd4fdae1de8999' + ], + [ + '100f44da696e71672791d0a09b7bde459f1215a29b3c03bfefd7835b39a48db0', + 'cdd9e13192a00b772ec8f3300c090666b7ff4a18ff5195ac0fbd5cd62bc65a09' + ], + [ + 'e1031be262c7ed1b1dc9227a4a04c017a77f8d4464f3b3852c8acde6e534fd2d', + '9d7061928940405e6bb6a4176597535af292dd419e1ced79a44f18f29456a00d' + ], + [ + 'feea6cae46d55b530ac2839f143bd7ec5cf8b266a41d6af52d5e688d9094696d', + 'e57c6b6c97dce1bab06e4e12bf3ecd5c981c8957cc41442d3155debf18090088' + ], + [ + 'da67a91d91049cdcb367be4be6ffca3cfeed657d808583de33fa978bc1ec6cb1', + '9bacaa35481642bc41f463f7ec9780e5dec7adc508f740a17e9ea8e27a68be1d' + ], + [ + '53904faa0b334cdda6e000935ef22151ec08d0f7bb11069f57545ccc1a37b7c0', + '5bc087d0bc80106d88c9eccac20d3c1c13999981e14434699dcb096b022771c8' + ], + [ + '8e7bcd0bd35983a7719cca7764ca906779b53a043a9b8bcaeff959f43ad86047', + '10b7770b2a3da4b3940310420ca9514579e88e2e47fd68b3ea10047e8460372a' + ], + [ + '385eed34c1cdff21e6d0818689b81bde71a7f4f18397e6690a841e1599c43862', + '283bebc3e8ea23f56701de19e9ebf4576b304eec2086dc8cc0458fe5542e5453' + ], + [ + '6f9d9b803ecf191637c73a4413dfa180fddf84a5947fbc9c606ed86c3fac3a7', + '7c80c68e603059ba69b8e2a30e45c4d47ea4dd2f5c281002d86890603a842160' + ], + [ + '3322d401243c4e2582a2147c104d6ecbf774d163db0f5e5313b7e0e742d0e6bd', + '56e70797e9664ef5bfb019bc4ddaf9b72805f63ea2873af624f3a2e96c28b2a0' + ], + [ + '85672c7d2de0b7da2bd1770d89665868741b3f9af7643397721d74d28134ab83', + '7c481b9b5b43b2eb6374049bfa62c2e5e77f17fcc5298f44c8e3094f790313a6' + ], + [ + '948bf809b1988a46b06c9f1919413b10f9226c60f668832ffd959af60c82a0a', + '53a562856dcb6646dc6b74c5d1c3418c6d4dff08c97cd2bed4cb7f88d8c8e589' + ], + [ + '6260ce7f461801c34f067ce0f02873a8f1b0e44dfc69752accecd819f38fd8e8', + 'bc2da82b6fa5b571a7f09049776a1ef7ecd292238051c198c1a84e95b2b4ae17' + ], + [ + 'e5037de0afc1d8d43d8348414bbf4103043ec8f575bfdc432953cc8d2037fa2d', + '4571534baa94d3b5f9f98d09fb990bddbd5f5b03ec481f10e0e5dc841d755bda' + ], + [ + 'e06372b0f4a207adf5ea905e8f1771b4e7e8dbd1c6a6c5b725866a0ae4fce725', + '7a908974bce18cfe12a27bb2ad5a488cd7484a7787104870b27034f94eee31dd' + ], + [ + '213c7a715cd5d45358d0bbf9dc0ce02204b10bdde2a3f58540ad6908d0559754', + '4b6dad0b5ae462507013ad06245ba190bb4850f5f36a7eeddff2c27534b458f2' + ], + [ + '4e7c272a7af4b34e8dbb9352a5419a87e2838c70adc62cddf0cc3a3b08fbd53c', + '17749c766c9d0b18e16fd09f6def681b530b9614bff7dd33e0b3941817dcaae6' + ], + [ + 'fea74e3dbe778b1b10f238ad61686aa5c76e3db2be43057632427e2840fb27b6', + '6e0568db9b0b13297cf674deccb6af93126b596b973f7b77701d3db7f23cb96f' + ], + [ + '76e64113f677cf0e10a2570d599968d31544e179b760432952c02a4417bdde39', + 'c90ddf8dee4e95cf577066d70681f0d35e2a33d2b56d2032b4b1752d1901ac01' + ], + [ + 'c738c56b03b2abe1e8281baa743f8f9a8f7cc643df26cbee3ab150242bcbb891', + '893fb578951ad2537f718f2eacbfbbbb82314eef7880cfe917e735d9699a84c3' + ], + [ + 'd895626548b65b81e264c7637c972877d1d72e5f3a925014372e9f6588f6c14b', + 'febfaa38f2bc7eae728ec60818c340eb03428d632bb067e179363ed75d7d991f' + ], + [ + 'b8da94032a957518eb0f6433571e8761ceffc73693e84edd49150a564f676e03', + '2804dfa44805a1e4d7c99cc9762808b092cc584d95ff3b511488e4e74efdf6e7' + ], + [ + 'e80fea14441fb33a7d8adab9475d7fab2019effb5156a792f1a11778e3c0df5d', + 'eed1de7f638e00771e89768ca3ca94472d155e80af322ea9fcb4291b6ac9ec78' + ], + [ + 'a301697bdfcd704313ba48e51d567543f2a182031efd6915ddc07bbcc4e16070', + '7370f91cfb67e4f5081809fa25d40f9b1735dbf7c0a11a130c0d1a041e177ea1' + ], + [ + '90ad85b389d6b936463f9d0512678de208cc330b11307fffab7ac63e3fb04ed4', + 'e507a3620a38261affdcbd9427222b839aefabe1582894d991d4d48cb6ef150' + ], + [ + '8f68b9d2f63b5f339239c1ad981f162ee88c5678723ea3351b7b444c9ec4c0da', + '662a9f2dba063986de1d90c2b6be215dbbea2cfe95510bfdf23cbf79501fff82' + ], + [ + 'e4f3fb0176af85d65ff99ff9198c36091f48e86503681e3e6686fd5053231e11', + '1e63633ad0ef4f1c1661a6d0ea02b7286cc7e74ec951d1c9822c38576feb73bc' + ], + [ + '8c00fa9b18ebf331eb961537a45a4266c7034f2f0d4e1d0716fb6eae20eae29e', + 'efa47267fea521a1a9dc343a3736c974c2fadafa81e36c54e7d2a4c66702414b' + ], + [ + 'e7a26ce69dd4829f3e10cec0a9e98ed3143d084f308b92c0997fddfc60cb3e41', + '2a758e300fa7984b471b006a1aafbb18d0a6b2c0420e83e20e8a9421cf2cfd51' + ], + [ + 'b6459e0ee3662ec8d23540c223bcbdc571cbcb967d79424f3cf29eb3de6b80ef', + '67c876d06f3e06de1dadf16e5661db3c4b3ae6d48e35b2ff30bf0b61a71ba45' + ], + [ + 'd68a80c8280bb840793234aa118f06231d6f1fc67e73c5a5deda0f5b496943e8', + 'db8ba9fff4b586d00c4b1f9177b0e28b5b0e7b8f7845295a294c84266b133120' + ], + [ + '324aed7df65c804252dc0270907a30b09612aeb973449cea4095980fc28d3d5d', + '648a365774b61f2ff130c0c35aec1f4f19213b0c7e332843967224af96ab7c84' + ], + [ + '4df9c14919cde61f6d51dfdbe5fee5dceec4143ba8d1ca888e8bd373fd054c96', + '35ec51092d8728050974c23a1d85d4b5d506cdc288490192ebac06cad10d5d' + ], + [ + '9c3919a84a474870faed8a9c1cc66021523489054d7f0308cbfc99c8ac1f98cd', + 'ddb84f0f4a4ddd57584f044bf260e641905326f76c64c8e6be7e5e03d4fc599d' + ], + [ + '6057170b1dd12fdf8de05f281d8e06bb91e1493a8b91d4cc5a21382120a959e5', + '9a1af0b26a6a4807add9a2daf71df262465152bc3ee24c65e899be932385a2a8' + ], + [ + 'a576df8e23a08411421439a4518da31880cef0fba7d4df12b1a6973eecb94266', + '40a6bf20e76640b2c92b97afe58cd82c432e10a7f514d9f3ee8be11ae1b28ec8' + ], + [ + '7778a78c28dec3e30a05fe9629de8c38bb30d1f5cf9a3a208f763889be58ad71', + '34626d9ab5a5b22ff7098e12f2ff580087b38411ff24ac563b513fc1fd9f43ac' + ], + [ + '928955ee637a84463729fd30e7afd2ed5f96274e5ad7e5cb09eda9c06d903ac', + 'c25621003d3f42a827b78a13093a95eeac3d26efa8a8d83fc5180e935bcd091f' + ], + [ + '85d0fef3ec6db109399064f3a0e3b2855645b4a907ad354527aae75163d82751', + '1f03648413a38c0be29d496e582cf5663e8751e96877331582c237a24eb1f962' + ], + [ + 'ff2b0dce97eece97c1c9b6041798b85dfdfb6d8882da20308f5404824526087e', + '493d13fef524ba188af4c4dc54d07936c7b7ed6fb90e2ceb2c951e01f0c29907' + ], + [ + '827fbbe4b1e880ea9ed2b2e6301b212b57f1ee148cd6dd28780e5e2cf856e241', + 'c60f9c923c727b0b71bef2c67d1d12687ff7a63186903166d605b68baec293ec' + ], + [ + 'eaa649f21f51bdbae7be4ae34ce6e5217a58fdce7f47f9aa7f3b58fa2120e2b3', + 'be3279ed5bbbb03ac69a80f89879aa5a01a6b965f13f7e59d47a5305ba5ad93d' + ], + [ + 'e4a42d43c5cf169d9391df6decf42ee541b6d8f0c9a137401e23632dda34d24f', + '4d9f92e716d1c73526fc99ccfb8ad34ce886eedfa8d8e4f13a7f7131deba9414' + ], + [ + '1ec80fef360cbdd954160fadab352b6b92b53576a88fea4947173b9d4300bf19', + 'aeefe93756b5340d2f3a4958a7abbf5e0146e77f6295a07b671cdc1cc107cefd' + ], + [ + '146a778c04670c2f91b00af4680dfa8bce3490717d58ba889ddb5928366642be', + 'b318e0ec3354028add669827f9d4b2870aaa971d2f7e5ed1d0b297483d83efd0' + ], + [ + 'fa50c0f61d22e5f07e3acebb1aa07b128d0012209a28b9776d76a8793180eef9', + '6b84c6922397eba9b72cd2872281a68a5e683293a57a213b38cd8d7d3f4f2811' + ], + [ + 'da1d61d0ca721a11b1a5bf6b7d88e8421a288ab5d5bba5220e53d32b5f067ec2', + '8157f55a7c99306c79c0766161c91e2966a73899d279b48a655fba0f1ad836f1' + ], + [ + 'a8e282ff0c9706907215ff98e8fd416615311de0446f1e062a73b0610d064e13', + '7f97355b8db81c09abfb7f3c5b2515888b679a3e50dd6bd6cef7c73111f4cc0c' + ], + [ + '174a53b9c9a285872d39e56e6913cab15d59b1fa512508c022f382de8319497c', + 'ccc9dc37abfc9c1657b4155f2c47f9e6646b3a1d8cb9854383da13ac079afa73' + ], + [ + '959396981943785c3d3e57edf5018cdbe039e730e4918b3d884fdff09475b7ba', + '2e7e552888c331dd8ba0386a4b9cd6849c653f64c8709385e9b8abf87524f2fd' + ], + [ + 'd2a63a50ae401e56d645a1153b109a8fcca0a43d561fba2dbb51340c9d82b151', + 'e82d86fb6443fcb7565aee58b2948220a70f750af484ca52d4142174dcf89405' + ], + [ + '64587e2335471eb890ee7896d7cfdc866bacbdbd3839317b3436f9b45617e073', + 'd99fcdd5bf6902e2ae96dd6447c299a185b90a39133aeab358299e5e9faf6589' + ], + [ + '8481bde0e4e4d885b3a546d3e549de042f0aa6cea250e7fd358d6c86dd45e458', + '38ee7b8cba5404dd84a25bf39cecb2ca900a79c42b262e556d64b1b59779057e' + ], + [ + '13464a57a78102aa62b6979ae817f4637ffcfed3c4b1ce30bcd6303f6caf666b', + '69be159004614580ef7e433453ccb0ca48f300a81d0942e13f495a907f6ecc27' + ], + [ + 'bc4a9df5b713fe2e9aef430bcc1dc97a0cd9ccede2f28588cada3a0d2d83f366', + 'd3a81ca6e785c06383937adf4b798caa6e8a9fbfa547b16d758d666581f33c1' + ], + [ + '8c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa', + '40a30463a3305193378fedf31f7cc0eb7ae784f0451cb9459e71dc73cbef9482' + ], + [ + '8ea9666139527a8c1dd94ce4f071fd23c8b350c5a4bb33748c4ba111faccae0', + '620efabbc8ee2782e24e7c0cfb95c5d735b783be9cf0f8e955af34a30e62b945' + ], + [ + 'dd3625faef5ba06074669716bbd3788d89bdde815959968092f76cc4eb9a9787', + '7a188fa3520e30d461da2501045731ca941461982883395937f68d00c644a573' + ], + [ + 'f710d79d9eb962297e4f6232b40e8f7feb2bc63814614d692c12de752408221e', + 'ea98e67232d3b3295d3b535532115ccac8612c721851617526ae47a9c77bfc82' + ] + ] + }, + naf: { + wnd: 7, + points: [ + [ + 'f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9', + '388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672' + ], + [ + '2f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4', + 'd8ac222636e5e3d6d4dba9dda6c9c426f788271bab0d6840dca87d3aa6ac62d6' + ], + [ + '5cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc', + '6aebca40ba255960a3178d6d861a54dba813d0b813fde7b5a5082628087264da' + ], + [ + 'acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe', + 'cc338921b0a7d9fd64380971763b61e9add888a4375f8e0f05cc262ac64f9c37' + ], + [ + '774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb', + 'd984a032eb6b5e190243dd56d7b7b365372db1e2dff9d6a8301d74c9c953c61b' + ], + [ + 'f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8', + 'ab0902e8d880a89758212eb65cdaf473a1a06da521fa91f29b5cb52db03ed81' + ], + [ + 'd7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e', + '581e2872a86c72a683842ec228cc6defea40af2bd896d3a5c504dc9ff6a26b58' + ], + [ + 'defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34', + '4211ab0694635168e997b0ead2a93daeced1f4a04a95c0f6cfb199f69e56eb77' + ], + [ + '2b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c', + '85e89bc037945d93b343083b5a1c86131a01f60c50269763b570c854e5c09b7a' + ], + [ + '352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5', + '321eb4075348f534d59c18259dda3e1f4a1b3b2e71b1039c67bd3d8bcf81998c' + ], + [ + '2fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f', + '2de1068295dd865b64569335bd5dd80181d70ecfc882648423ba76b532b7d67' + ], + [ + '9248279b09b4d68dab21a9b066edda83263c3d84e09572e269ca0cd7f5453714', + '73016f7bf234aade5d1aa71bdea2b1ff3fc0de2a887912ffe54a32ce97cb3402' + ], + [ + 'daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729', + 'a69dce4a7d6c98e8d4a1aca87ef8d7003f83c230f3afa726ab40e52290be1c55' + ], + [ + 'c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db', + '2119a460ce326cdc76c45926c982fdac0e106e861edf61c5a039063f0e0e6482' + ], + [ + '6a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4', + 'e022cf42c2bd4a708b3f5126f16a24ad8b33ba48d0423b6efd5e6348100d8a82' + ], + [ + '1697ffa6fd9de627c077e3d2fe541084ce13300b0bec1146f95ae57f0d0bd6a5', + 'b9c398f186806f5d27561506e4557433a2cf15009e498ae7adee9d63d01b2396' + ], + [ + '605bdb019981718b986d0f07e834cb0d9deb8360ffb7f61df982345ef27a7479', + '2972d2de4f8d20681a78d93ec96fe23c26bfae84fb14db43b01e1e9056b8c49' + ], + [ + '62d14dab4150bf497402fdc45a215e10dcb01c354959b10cfe31c7e9d87ff33d', + '80fc06bd8cc5b01098088a1950eed0db01aa132967ab472235f5642483b25eaf' + ], + [ + '80c60ad0040f27dade5b4b06c408e56b2c50e9f56b9b8b425e555c2f86308b6f', + '1c38303f1cc5c30f26e66bad7fe72f70a65eed4cbe7024eb1aa01f56430bd57a' + ], + [ + '7a9375ad6167ad54aa74c6348cc54d344cc5dc9487d847049d5eabb0fa03c8fb', + 'd0e3fa9eca8726909559e0d79269046bdc59ea10c70ce2b02d499ec224dc7f7' + ], + [ + 'd528ecd9b696b54c907a9ed045447a79bb408ec39b68df504bb51f459bc3ffc9', + 'eecf41253136e5f99966f21881fd656ebc4345405c520dbc063465b521409933' + ], + [ + '49370a4b5f43412ea25f514e8ecdad05266115e4a7ecb1387231808f8b45963', + '758f3f41afd6ed428b3081b0512fd62a54c3f3afbb5b6764b653052a12949c9a' + ], + [ + '77f230936ee88cbbd73df930d64702ef881d811e0e1498e2f1c13eb1fc345d74', + '958ef42a7886b6400a08266e9ba1b37896c95330d97077cbbe8eb3c7671c60d6' + ], + [ + 'f2dac991cc4ce4b9ea44887e5c7c0bce58c80074ab9d4dbaeb28531b7739f530', + 'e0dedc9b3b2f8dad4da1f32dec2531df9eb5fbeb0598e4fd1a117dba703a3c37' + ], + [ + '463b3d9f662621fb1b4be8fbbe2520125a216cdfc9dae3debcba4850c690d45b', + '5ed430d78c296c3543114306dd8622d7c622e27c970a1de31cb377b01af7307e' + ], + [ + 'f16f804244e46e2a09232d4aff3b59976b98fac14328a2d1a32496b49998f247', + 'cedabd9b82203f7e13d206fcdf4e33d92a6c53c26e5cce26d6579962c4e31df6' + ], + [ + 'caf754272dc84563b0352b7a14311af55d245315ace27c65369e15f7151d41d1', + 'cb474660ef35f5f2a41b643fa5e460575f4fa9b7962232a5c32f908318a04476' + ], + [ + '2600ca4b282cb986f85d0f1709979d8b44a09c07cb86d7c124497bc86f082120', + '4119b88753c15bd6a693b03fcddbb45d5ac6be74ab5f0ef44b0be9475a7e4b40' + ], + [ + '7635ca72d7e8432c338ec53cd12220bc01c48685e24f7dc8c602a7746998e435', + '91b649609489d613d1d5e590f78e6d74ecfc061d57048bad9e76f302c5b9c61' + ], + [ + '754e3239f325570cdbbf4a87deee8a66b7f2b33479d468fbc1a50743bf56cc18', + '673fb86e5bda30fb3cd0ed304ea49a023ee33d0197a695d0c5d98093c536683' + ], + [ + 'e3e6bd1071a1e96aff57859c82d570f0330800661d1c952f9fe2694691d9b9e8', + '59c9e0bba394e76f40c0aa58379a3cb6a5a2283993e90c4167002af4920e37f5' + ], + [ + '186b483d056a033826ae73d88f732985c4ccb1f32ba35f4b4cc47fdcf04aa6eb', + '3b952d32c67cf77e2e17446e204180ab21fb8090895138b4a4a797f86e80888b' + ], + [ + 'df9d70a6b9876ce544c98561f4be4f725442e6d2b737d9c91a8321724ce0963f', + '55eb2dafd84d6ccd5f862b785dc39d4ab157222720ef9da217b8c45cf2ba2417' + ], + [ + '5edd5cc23c51e87a497ca815d5dce0f8ab52554f849ed8995de64c5f34ce7143', + 'efae9c8dbc14130661e8cec030c89ad0c13c66c0d17a2905cdc706ab7399a868' + ], + [ + '290798c2b6476830da12fe02287e9e777aa3fba1c355b17a722d362f84614fba', + 'e38da76dcd440621988d00bcf79af25d5b29c094db2a23146d003afd41943e7a' + ], + [ + 'af3c423a95d9f5b3054754efa150ac39cd29552fe360257362dfdecef4053b45', + 'f98a3fd831eb2b749a93b0e6f35cfb40c8cd5aa667a15581bc2feded498fd9c6' + ], + [ + '766dbb24d134e745cccaa28c99bf274906bb66b26dcf98df8d2fed50d884249a', + '744b1152eacbe5e38dcc887980da38b897584a65fa06cedd2c924f97cbac5996' + ], + [ + '59dbf46f8c94759ba21277c33784f41645f7b44f6c596a58ce92e666191abe3e', + 'c534ad44175fbc300f4ea6ce648309a042ce739a7919798cd85e216c4a307f6e' + ], + [ + 'f13ada95103c4537305e691e74e9a4a8dd647e711a95e73cb62dc6018cfd87b8', + 'e13817b44ee14de663bf4bc808341f326949e21a6a75c2570778419bdaf5733d' + ], + [ + '7754b4fa0e8aced06d4167a2c59cca4cda1869c06ebadfb6488550015a88522c', + '30e93e864e669d82224b967c3020b8fa8d1e4e350b6cbcc537a48b57841163a2' + ], + [ + '948dcadf5990e048aa3874d46abef9d701858f95de8041d2a6828c99e2262519', + 'e491a42537f6e597d5d28a3224b1bc25df9154efbd2ef1d2cbba2cae5347d57e' + ], + [ + '7962414450c76c1689c7b48f8202ec37fb224cf5ac0bfa1570328a8a3d7c77ab', + '100b610ec4ffb4760d5c1fc133ef6f6b12507a051f04ac5760afa5b29db83437' + ], + [ + '3514087834964b54b15b160644d915485a16977225b8847bb0dd085137ec47ca', + 'ef0afbb2056205448e1652c48e8127fc6039e77c15c2378b7e7d15a0de293311' + ], + [ + 'd3cc30ad6b483e4bc79ce2c9dd8bc54993e947eb8df787b442943d3f7b527eaf', + '8b378a22d827278d89c5e9be8f9508ae3c2ad46290358630afb34db04eede0a4' + ], + [ + '1624d84780732860ce1c78fcbfefe08b2b29823db913f6493975ba0ff4847610', + '68651cf9b6da903e0914448c6cd9d4ca896878f5282be4c8cc06e2a404078575' + ], + [ + '733ce80da955a8a26902c95633e62a985192474b5af207da6df7b4fd5fc61cd4', + 'f5435a2bd2badf7d485a4d8b8db9fcce3e1ef8e0201e4578c54673bc1dc5ea1d' + ], + [ + '15d9441254945064cf1a1c33bbd3b49f8966c5092171e699ef258dfab81c045c', + 'd56eb30b69463e7234f5137b73b84177434800bacebfc685fc37bbe9efe4070d' + ], + [ + 'a1d0fcf2ec9de675b612136e5ce70d271c21417c9d2b8aaaac138599d0717940', + 'edd77f50bcb5a3cab2e90737309667f2641462a54070f3d519212d39c197a629' + ], + [ + 'e22fbe15c0af8ccc5780c0735f84dbe9a790badee8245c06c7ca37331cb36980', + 'a855babad5cd60c88b430a69f53a1a7a38289154964799be43d06d77d31da06' + ], + [ + '311091dd9860e8e20ee13473c1155f5f69635e394704eaa74009452246cfa9b3', + '66db656f87d1f04fffd1f04788c06830871ec5a64feee685bd80f0b1286d8374' + ], + [ + '34c1fd04d301be89b31c0442d3e6ac24883928b45a9340781867d4232ec2dbdf', + '9414685e97b1b5954bd46f730174136d57f1ceeb487443dc5321857ba73abee' + ], + [ + 'f219ea5d6b54701c1c14de5b557eb42a8d13f3abbcd08affcc2a5e6b049b8d63', + '4cb95957e83d40b0f73af4544cccf6b1f4b08d3c07b27fb8d8c2962a400766d1' + ], + [ + 'd7b8740f74a8fbaab1f683db8f45de26543a5490bca627087236912469a0b448', + 'fa77968128d9c92ee1010f337ad4717eff15db5ed3c049b3411e0315eaa4593b' + ], + [ + '32d31c222f8f6f0ef86f7c98d3a3335ead5bcd32abdd94289fe4d3091aa824bf', + '5f3032f5892156e39ccd3d7915b9e1da2e6dac9e6f26e961118d14b8462e1661' + ], + [ + '7461f371914ab32671045a155d9831ea8793d77cd59592c4340f86cbc18347b5', + '8ec0ba238b96bec0cbdddcae0aa442542eee1ff50c986ea6b39847b3cc092ff6' + ], + [ + 'ee079adb1df1860074356a25aa38206a6d716b2c3e67453d287698bad7b2b2d6', + '8dc2412aafe3be5c4c5f37e0ecc5f9f6a446989af04c4e25ebaac479ec1c8c1e' + ], + [ + '16ec93e447ec83f0467b18302ee620f7e65de331874c9dc72bfd8616ba9da6b5', + '5e4631150e62fb40d0e8c2a7ca5804a39d58186a50e497139626778e25b0674d' + ], + [ + 'eaa5f980c245f6f038978290afa70b6bd8855897f98b6aa485b96065d537bd99', + 'f65f5d3e292c2e0819a528391c994624d784869d7e6ea67fb18041024edc07dc' + ], + [ + '78c9407544ac132692ee1910a02439958ae04877151342ea96c4b6b35a49f51', + 'f3e0319169eb9b85d5404795539a5e68fa1fbd583c064d2462b675f194a3ddb4' + ], + [ + '494f4be219a1a77016dcd838431aea0001cdc8ae7a6fc688726578d9702857a5', + '42242a969283a5f339ba7f075e36ba2af925ce30d767ed6e55f4b031880d562c' + ], + [ + 'a598a8030da6d86c6bc7f2f5144ea549d28211ea58faa70ebf4c1e665c1fe9b5', + '204b5d6f84822c307e4b4a7140737aec23fc63b65b35f86a10026dbd2d864e6b' + ], + [ + 'c41916365abb2b5d09192f5f2dbeafec208f020f12570a184dbadc3e58595997', + '4f14351d0087efa49d245b328984989d5caf9450f34bfc0ed16e96b58fa9913' + ], + [ + '841d6063a586fa475a724604da03bc5b92a2e0d2e0a36acfe4c73a5514742881', + '73867f59c0659e81904f9a1c7543698e62562d6744c169ce7a36de01a8d6154' + ], + [ + '5e95bb399a6971d376026947f89bde2f282b33810928be4ded112ac4d70e20d5', + '39f23f366809085beebfc71181313775a99c9aed7d8ba38b161384c746012865' + ], + [ + '36e4641a53948fd476c39f8a99fd974e5ec07564b5315d8bf99471bca0ef2f66', + 'd2424b1b1abe4eb8164227b085c9aa9456ea13493fd563e06fd51cf5694c78fc' + ], + [ + '336581ea7bfbbb290c191a2f507a41cf5643842170e914faeab27c2c579f726', + 'ead12168595fe1be99252129b6e56b3391f7ab1410cd1e0ef3dcdcabd2fda224' + ], + [ + '8ab89816dadfd6b6a1f2634fcf00ec8403781025ed6890c4849742706bd43ede', + '6fdcef09f2f6d0a044e654aef624136f503d459c3e89845858a47a9129cdd24e' + ], + [ + '1e33f1a746c9c5778133344d9299fcaa20b0938e8acff2544bb40284b8c5fb94', + '60660257dd11b3aa9c8ed618d24edff2306d320f1d03010e33a7d2057f3b3b6' + ], + [ + '85b7c1dcb3cec1b7ee7f30ded79dd20a0ed1f4cc18cbcfcfa410361fd8f08f31', + '3d98a9cdd026dd43f39048f25a8847f4fcafad1895d7a633c6fed3c35e999511' + ], + [ + '29df9fbd8d9e46509275f4b125d6d45d7fbe9a3b878a7af872a2800661ac5f51', + 'b4c4fe99c775a606e2d8862179139ffda61dc861c019e55cd2876eb2a27d84b' + ], + [ + 'a0b1cae06b0a847a3fea6e671aaf8adfdfe58ca2f768105c8082b2e449fce252', + 'ae434102edde0958ec4b19d917a6a28e6b72da1834aff0e650f049503a296cf2' + ], + [ + '4e8ceafb9b3e9a136dc7ff67e840295b499dfb3b2133e4ba113f2e4c0e121e5', + 'cf2174118c8b6d7a4b48f6d534ce5c79422c086a63460502b827ce62a326683c' + ], + [ + 'd24a44e047e19b6f5afb81c7ca2f69080a5076689a010919f42725c2b789a33b', + '6fb8d5591b466f8fc63db50f1c0f1c69013f996887b8244d2cdec417afea8fa3' + ], + [ + 'ea01606a7a6c9cdd249fdfcfacb99584001edd28abbab77b5104e98e8e3b35d4', + '322af4908c7312b0cfbfe369f7a7b3cdb7d4494bc2823700cfd652188a3ea98d' + ], + [ + 'af8addbf2b661c8a6c6328655eb96651252007d8c5ea31be4ad196de8ce2131f', + '6749e67c029b85f52a034eafd096836b2520818680e26ac8f3dfbcdb71749700' + ], + [ + 'e3ae1974566ca06cc516d47e0fb165a674a3dabcfca15e722f0e3450f45889', + '2aeabe7e4531510116217f07bf4d07300de97e4874f81f533420a72eeb0bd6a4' + ], + [ + '591ee355313d99721cf6993ffed1e3e301993ff3ed258802075ea8ced397e246', + 'b0ea558a113c30bea60fc4775460c7901ff0b053d25ca2bdeee98f1a4be5d196' + ], + [ + '11396d55fda54c49f19aa97318d8da61fa8584e47b084945077cf03255b52984', + '998c74a8cd45ac01289d5833a7beb4744ff536b01b257be4c5767bea93ea57a4' + ], + [ + '3c5d2a1ba39c5a1790000738c9e0c40b8dcdfd5468754b6405540157e017aa7a', + 'b2284279995a34e2f9d4de7396fc18b80f9b8b9fdd270f6661f79ca4c81bd257' + ], + [ + 'cc8704b8a60a0defa3a99a7299f2e9c3fbc395afb04ac078425ef8a1793cc030', + 'bdd46039feed17881d1e0862db347f8cf395b74fc4bcdc4e940b74e3ac1f1b13' + ], + [ + 'c533e4f7ea8555aacd9777ac5cad29b97dd4defccc53ee7ea204119b2889b197', + '6f0a256bc5efdf429a2fb6242f1a43a2d9b925bb4a4b3a26bb8e0f45eb596096' + ], + [ + 'c14f8f2ccb27d6f109f6d08d03cc96a69ba8c34eec07bbcf566d48e33da6593', + 'c359d6923bb398f7fd4473e16fe1c28475b740dd098075e6c0e8649113dc3a38' + ], + [ + 'a6cbc3046bc6a450bac24789fa17115a4c9739ed75f8f21ce441f72e0b90e6ef', + '21ae7f4680e889bb130619e2c0f95a360ceb573c70603139862afd617fa9b9f' + ], + [ + '347d6d9a02c48927ebfb86c1359b1caf130a3c0267d11ce6344b39f99d43cc38', + '60ea7f61a353524d1c987f6ecec92f086d565ab687870cb12689ff1e31c74448' + ], + [ + 'da6545d2181db8d983f7dcb375ef5866d47c67b1bf31c8cf855ef7437b72656a', + '49b96715ab6878a79e78f07ce5680c5d6673051b4935bd897fea824b77dc208a' + ], + [ + 'c40747cc9d012cb1a13b8148309c6de7ec25d6945d657146b9d5994b8feb1111', + '5ca560753be2a12fc6de6caf2cb489565db936156b9514e1bb5e83037e0fa2d4' + ], + [ + '4e42c8ec82c99798ccf3a610be870e78338c7f713348bd34c8203ef4037f3502', + '7571d74ee5e0fb92a7a8b33a07783341a5492144cc54bcc40a94473693606437' + ], + [ + '3775ab7089bc6af823aba2e1af70b236d251cadb0c86743287522a1b3b0dedea', + 'be52d107bcfa09d8bcb9736a828cfa7fac8db17bf7a76a2c42ad961409018cf7' + ], + [ + 'cee31cbf7e34ec379d94fb814d3d775ad954595d1314ba8846959e3e82f74e26', + '8fd64a14c06b589c26b947ae2bcf6bfa0149ef0be14ed4d80f448a01c43b1c6d' + ], + [ + 'b4f9eaea09b6917619f6ea6a4eb5464efddb58fd45b1ebefcdc1a01d08b47986', + '39e5c9925b5a54b07433a4f18c61726f8bb131c012ca542eb24a8ac07200682a' + ], + [ + 'd4263dfc3d2df923a0179a48966d30ce84e2515afc3dccc1b77907792ebcc60e', + '62dfaf07a0f78feb30e30d6295853ce189e127760ad6cf7fae164e122a208d54' + ], + [ + '48457524820fa65a4f8d35eb6930857c0032acc0a4a2de422233eeda897612c4', + '25a748ab367979d98733c38a1fa1c2e7dc6cc07db2d60a9ae7a76aaa49bd0f77' + ], + [ + 'dfeeef1881101f2cb11644f3a2afdfc2045e19919152923f367a1767c11cceda', + 'ecfb7056cf1de042f9420bab396793c0c390bde74b4bbdff16a83ae09a9a7517' + ], + [ + '6d7ef6b17543f8373c573f44e1f389835d89bcbc6062ced36c82df83b8fae859', + 'cd450ec335438986dfefa10c57fea9bcc521a0959b2d80bbf74b190dca712d10' + ], + [ + 'e75605d59102a5a2684500d3b991f2e3f3c88b93225547035af25af66e04541f', + 'f5c54754a8f71ee540b9b48728473e314f729ac5308b06938360990e2bfad125' + ], + [ + 'eb98660f4c4dfaa06a2be453d5020bc99a0c2e60abe388457dd43fefb1ed620c', + '6cb9a8876d9cb8520609af3add26cd20a0a7cd8a9411131ce85f44100099223e' + ], + [ + '13e87b027d8514d35939f2e6892b19922154596941888336dc3563e3b8dba942', + 'fef5a3c68059a6dec5d624114bf1e91aac2b9da568d6abeb2570d55646b8adf1' + ], + [ + 'ee163026e9fd6fe017c38f06a5be6fc125424b371ce2708e7bf4491691e5764a', + '1acb250f255dd61c43d94ccc670d0f58f49ae3fa15b96623e5430da0ad6c62b2' + ], + [ + 'b268f5ef9ad51e4d78de3a750c2dc89b1e626d43505867999932e5db33af3d80', + '5f310d4b3c99b9ebb19f77d41c1dee018cf0d34fd4191614003e945a1216e423' + ], + [ + 'ff07f3118a9df035e9fad85eb6c7bfe42b02f01ca99ceea3bf7ffdba93c4750d', + '438136d603e858a3a5c440c38eccbaddc1d2942114e2eddd4740d098ced1f0d8' + ], + [ + '8d8b9855c7c052a34146fd20ffb658bea4b9f69e0d825ebec16e8c3ce2b526a1', + 'cdb559eedc2d79f926baf44fb84ea4d44bcf50fee51d7ceb30e2e7f463036758' + ], + [ + '52db0b5384dfbf05bfa9d472d7ae26dfe4b851ceca91b1eba54263180da32b63', + 'c3b997d050ee5d423ebaf66a6db9f57b3180c902875679de924b69d84a7b375' + ], + [ + 'e62f9490d3d51da6395efd24e80919cc7d0f29c3f3fa48c6fff543becbd43352', + '6d89ad7ba4876b0b22c2ca280c682862f342c8591f1daf5170e07bfd9ccafa7d' + ], + [ + '7f30ea2476b399b4957509c88f77d0191afa2ff5cb7b14fd6d8e7d65aaab1193', + 'ca5ef7d4b231c94c3b15389a5f6311e9daff7bb67b103e9880ef4bff637acaec' + ], + [ + '5098ff1e1d9f14fb46a210fada6c903fef0fb7b4a1dd1d9ac60a0361800b7a00', + '9731141d81fc8f8084d37c6e7542006b3ee1b40d60dfe5362a5b132fd17ddc0' + ], + [ + '32b78c7de9ee512a72895be6b9cbefa6e2f3c4ccce445c96b9f2c81e2778ad58', + 'ee1849f513df71e32efc3896ee28260c73bb80547ae2275ba497237794c8753c' + ], + [ + 'e2cb74fddc8e9fbcd076eef2a7c72b0ce37d50f08269dfc074b581550547a4f7', + 'd3aa2ed71c9dd2247a62df062736eb0baddea9e36122d2be8641abcb005cc4a4' + ], + [ + '8438447566d4d7bedadc299496ab357426009a35f235cb141be0d99cd10ae3a8', + 'c4e1020916980a4da5d01ac5e6ad330734ef0d7906631c4f2390426b2edd791f' + ], + [ + '4162d488b89402039b584c6fc6c308870587d9c46f660b878ab65c82c711d67e', + '67163e903236289f776f22c25fb8a3afc1732f2b84b4e95dbda47ae5a0852649' + ], + [ + '3fad3fa84caf0f34f0f89bfd2dcf54fc175d767aec3e50684f3ba4a4bf5f683d', + 'cd1bc7cb6cc407bb2f0ca647c718a730cf71872e7d0d2a53fa20efcdfe61826' + ], + [ + '674f2600a3007a00568c1a7ce05d0816c1fb84bf1370798f1c69532faeb1a86b', + '299d21f9413f33b3edf43b257004580b70db57da0b182259e09eecc69e0d38a5' + ], + [ + 'd32f4da54ade74abb81b815ad1fb3b263d82d6c692714bcff87d29bd5ee9f08f', + 'f9429e738b8e53b968e99016c059707782e14f4535359d582fc416910b3eea87' + ], + [ + '30e4e670435385556e593657135845d36fbb6931f72b08cb1ed954f1e3ce3ff6', + '462f9bce619898638499350113bbc9b10a878d35da70740dc695a559eb88db7b' + ], + [ + 'be2062003c51cc3004682904330e4dee7f3dcd10b01e580bf1971b04d4cad297', + '62188bc49d61e5428573d48a74e1c655b1c61090905682a0d5558ed72dccb9bc' + ], + [ + '93144423ace3451ed29e0fb9ac2af211cb6e84a601df5993c419859fff5df04a', + '7c10dfb164c3425f5c71a3f9d7992038f1065224f72bb9d1d902a6d13037b47c' + ], + [ + 'b015f8044f5fcbdcf21ca26d6c34fb8197829205c7b7d2a7cb66418c157b112c', + 'ab8c1e086d04e813744a655b2df8d5f83b3cdc6faa3088c1d3aea1454e3a1d5f' + ], + [ + 'd5e9e1da649d97d89e4868117a465a3a4f8a18de57a140d36b3f2af341a21b52', + '4cb04437f391ed73111a13cc1d4dd0db1693465c2240480d8955e8592f27447a' + ], + [ + 'd3ae41047dd7ca065dbf8ed77b992439983005cd72e16d6f996a5316d36966bb', + 'bd1aeb21ad22ebb22a10f0303417c6d964f8cdd7df0aca614b10dc14d125ac46' + ], + [ + '463e2763d885f958fc66cdd22800f0a487197d0a82e377b49f80af87c897b065', + 'bfefacdb0e5d0fd7df3a311a94de062b26b80c61fbc97508b79992671ef7ca7f' + ], + [ + '7985fdfd127c0567c6f53ec1bb63ec3158e597c40bfe747c83cddfc910641917', + '603c12daf3d9862ef2b25fe1de289aed24ed291e0ec6708703a5bd567f32ed03' + ], + [ + '74a1ad6b5f76e39db2dd249410eac7f99e74c59cb83d2d0ed5ff1543da7703e9', + 'cc6157ef18c9c63cd6193d83631bbea0093e0968942e8c33d5737fd790e0db08' + ], + [ + '30682a50703375f602d416664ba19b7fc9bab42c72747463a71d0896b22f6da3', + '553e04f6b018b4fa6c8f39e7f311d3176290d0e0f19ca73f17714d9977a22ff8' + ], + [ + '9e2158f0d7c0d5f26c3791efefa79597654e7a2b2464f52b1ee6c1347769ef57', + '712fcdd1b9053f09003a3481fa7762e9ffd7c8ef35a38509e2fbf2629008373' + ], + [ + '176e26989a43c9cfeba4029c202538c28172e566e3c4fce7322857f3be327d66', + 'ed8cc9d04b29eb877d270b4878dc43c19aefd31f4eee09ee7b47834c1fa4b1c3' + ], + [ + '75d46efea3771e6e68abb89a13ad747ecf1892393dfc4f1b7004788c50374da8', + '9852390a99507679fd0b86fd2b39a868d7efc22151346e1a3ca4726586a6bed8' + ], + [ + '809a20c67d64900ffb698c4c825f6d5f2310fb0451c869345b7319f645605721', + '9e994980d9917e22b76b061927fa04143d096ccc54963e6a5ebfa5f3f8e286c1' + ], + [ + '1b38903a43f7f114ed4500b4eac7083fdefece1cf29c63528d563446f972c180', + '4036edc931a60ae889353f77fd53de4a2708b26b6f5da72ad3394119daf408f9' + ] + ] + } + }; + + var curves_1 = createCommonjsModule(function (module, exports) { + + var curves = exports; + + + + + + var assert = utils_1$1.assert; + + function PresetCurve(options) { + if (options.type === 'short') + this.curve = new curve_1.short(options); + else if (options.type === 'edwards') + this.curve = new curve_1.edwards(options); + else if (options.type === 'mont') + this.curve = new curve_1.mont(options); + else throw new Error('Unknown curve type.'); + this.g = this.curve.g; + this.n = this.curve.n; + this.hash = options.hash; + + assert(this.g.validate(), 'Invalid curve'); + assert(this.g.mul(this.n).isInfinity(), 'Invalid curve, n*G != O'); + } + curves.PresetCurve = PresetCurve; + + function defineCurve(name, options) { + Object.defineProperty(curves, name, { + configurable: true, + enumerable: true, + get: function() { + var curve = new PresetCurve(options); + Object.defineProperty(curves, name, { + configurable: true, + enumerable: true, + value: curve + }); + return curve; + } + }); + } + + defineCurve('p192', { + type: 'short', + prime: 'p192', + p: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff', + a: 'ffffffff ffffffff ffffffff fffffffe ffffffff fffffffc', + b: '64210519 e59c80e7 0fa7e9ab 72243049 feb8deec c146b9b1', + n: 'ffffffff ffffffff ffffffff 99def836 146bc9b1 b4d22831', + hash: hash_1.sha256, + gRed: false, + g: [ + '188da80e b03090f6 7cbf20eb 43a18800 f4ff0afd 82ff1012', + '07192b95 ffc8da78 631011ed 6b24cdd5 73f977a1 1e794811' + ] + }); + + defineCurve('p224', { + type: 'short', + prime: 'p224', + p: 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001', + a: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff fffffffe', + b: 'b4050a85 0c04b3ab f5413256 5044b0b7 d7bfd8ba 270b3943 2355ffb4', + n: 'ffffffff ffffffff ffffffff ffff16a2 e0b8f03e 13dd2945 5c5c2a3d', + hash: hash_1.sha256, + gRed: false, + g: [ + 'b70e0cbd 6bb4bf7f 321390b9 4a03c1d3 56c21122 343280d6 115c1d21', + 'bd376388 b5f723fb 4c22dfe6 cd4375a0 5a074764 44d58199 85007e34' + ] + }); + + defineCurve('p256', { + type: 'short', + prime: null, + p: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff', + a: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff fffffffc', + b: '5ac635d8 aa3a93e7 b3ebbd55 769886bc 651d06b0 cc53b0f6 3bce3c3e 27d2604b', + n: 'ffffffff 00000000 ffffffff ffffffff bce6faad a7179e84 f3b9cac2 fc632551', + hash: hash_1.sha256, + gRed: false, + g: [ + '6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296', + '4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5' + ] + }); + + defineCurve('p384', { + type: 'short', + prime: null, + p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'fffffffe ffffffff 00000000 00000000 ffffffff', + a: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'fffffffe ffffffff 00000000 00000000 fffffffc', + b: 'b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112 0314088f ' + + '5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef', + n: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff c7634d81 ' + + 'f4372ddf 581a0db2 48b0a77a ecec196a ccc52973', + hash: hash_1.sha384, + gRed: false, + g: [ + 'aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98 59f741e0 82542a38 ' + + '5502f25d bf55296c 3a545e38 72760ab7', + '3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c e9da3113 b5f0b8c0 ' + + '0a60b1ce 1d7e819d 7a431d7c 90ea0e5f' + ] + }); + + defineCurve('p521', { + type: 'short', + prime: null, + p: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff ffffffff ffffffff ffffffff', + a: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff ffffffff ffffffff fffffffc', + b: '00000051 953eb961 8e1c9a1f 929a21a0 b68540ee a2da725b ' + + '99b315f3 b8b48991 8ef109e1 56193951 ec7e937b 1652c0bd ' + + '3bb1bf07 3573df88 3d2c34f1 ef451fd4 6b503f00', + n: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff fffffffa 51868783 bf2f966b 7fcc0148 ' + + 'f709a5d0 3bb5c9b8 899c47ae bb6fb71e 91386409', + hash: hash_1.sha512, + gRed: false, + g: [ + '000000c6 858e06b7 0404e9cd 9e3ecb66 2395b442 9c648139 ' + + '053fb521 f828af60 6b4d3dba a14b5e77 efe75928 fe1dc127 ' + + 'a2ffa8de 3348b3c1 856a429b f97e7e31 c2e5bd66', + '00000118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd9 98f54449 ' + + '579b4468 17afbd17 273e662c 97ee7299 5ef42640 c550b901 ' + + '3fad0761 353c7086 a272c240 88be9476 9fd16650' + ] + }); + + // https://tools.ietf.org/html/rfc7748#section-4.1 + defineCurve('curve25519', { + type: 'mont', + prime: 'p25519', + p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', + a: '76d06', + b: '1', + n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', + cofactor: '8', + hash: hash_1.sha256, + gRed: false, + g: [ + '9' + ] + }); + + defineCurve('ed25519', { + type: 'edwards', + prime: 'p25519', + p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', + a: '-1', + c: '1', + // -121665 * (121666^(-1)) (mod P) + d: '52036cee2b6ffe73 8cc740797779e898 00700a4d4141d8ab 75eb4dca135978a3', + n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', + cofactor: '8', + hash: hash_1.sha256, + gRed: false, + g: [ + '216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a', + // 4/5 + '6666666666666666666666666666666666666666666666666666666666666658' + ] + }); + + // https://tools.ietf.org/html/rfc5639#section-3.4 + defineCurve('brainpoolP256r1', { + type: 'short', + prime: null, + p: 'A9FB57DB A1EEA9BC 3E660A90 9D838D72 6E3BF623 D5262028 2013481D 1F6E5377', + a: '7D5A0975 FC2C3057 EEF67530 417AFFE7 FB8055C1 26DC5C6C E94A4B44 F330B5D9', + b: '26DC5C6C E94A4B44 F330B5D9 BBD77CBF 95841629 5CF7E1CE 6BCCDC18 FF8C07B6', + n: 'A9FB57DB A1EEA9BC 3E660A90 9D838D71 8C397AA3 B561A6F7 901E0E82 974856A7', + hash: hash_1.sha256, // or 384, or 512 + gRed: false, + g: [ + '8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262', + '547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997' + ] + }); + + // https://tools.ietf.org/html/rfc5639#section-3.6 + defineCurve('brainpoolP384r1', { + type: 'short', + prime: null, + p: '8CB91E82 A3386D28 0F5D6F7E 50E641DF 152F7109 ED5456B4 12B1DA19 7FB71123' + + 'ACD3A729 901D1A71 87470013 3107EC53', + a: '7BC382C6 3D8C150C 3C72080A CE05AFA0 C2BEA28E 4FB22787 139165EF BA91F90F' + + '8AA5814A 503AD4EB 04A8C7DD 22CE2826', + b: '04A8C7DD 22CE2826 8B39B554 16F0447C 2FB77DE1 07DCD2A6 2E880EA5 3EEB62D5' + + '7CB43902 95DBC994 3AB78696 FA504C11', + n: '8CB91E82 A3386D28 0F5D6F7E 50E641DF 152F7109 ED5456B3 1F166E6C AC0425A7' + + 'CF3AB6AF 6B7FC310 3B883202 E9046565', + hash: hash_1.sha384, // or 512 + gRed: false, + g: [ + '1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10' + + 'E8E826E03436D646AAEF87B2E247D4AF1E', + '8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129' + + '280E4646217791811142820341263C5315' + ] + }); + + // https://tools.ietf.org/html/rfc5639#section-3.7 + defineCurve('brainpoolP512r1', { + type: 'short', + prime: null, + p: 'AADD9DB8 DBE9C48B 3FD4E6AE 33C9FC07 CB308DB3 B3C9D20E D6639CCA 70330871' + + '7D4D9B00 9BC66842 AECDA12A E6A380E6 2881FF2F 2D82C685 28AA6056 583A48F3', + a: '7830A331 8B603B89 E2327145 AC234CC5 94CBDD8D 3DF91610 A83441CA EA9863BC' + + '2DED5D5A A8253AA1 0A2EF1C9 8B9AC8B5 7F1117A7 2BF2C7B9 E7C1AC4D 77FC94CA', + b: '3DF91610 A83441CA EA9863BC 2DED5D5A A8253AA1 0A2EF1C9 8B9AC8B5 7F1117A7' + + '2BF2C7B9 E7C1AC4D 77FC94CA DC083E67 984050B7 5EBAE5DD 2809BD63 8016F723', + n: 'AADD9DB8 DBE9C48B 3FD4E6AE 33C9FC07 CB308DB3 B3C9D20E D6639CCA 70330870' + + '553E5C41 4CA92619 41866119 7FAC1047 1DB1D381 085DDADD B5879682 9CA90069', + hash: hash_1.sha512, + gRed: false, + g: [ + '81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D009' + + '8EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822', + '7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F81' + + '11B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892' + ] + }); + + // https://en.bitcoin.it/wiki/Secp256k1 + var pre; + try { + pre = secp256k1; + } catch (e) { + pre = undefined; + } + + defineCurve('secp256k1', { + type: 'short', + prime: 'k256', + p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f', + a: '0', + b: '7', + n: 'ffffffff ffffffff ffffffff fffffffe baaedce6 af48a03b bfd25e8c d0364141', + h: '1', + hash: hash_1.sha256, + + // Precomputed endomorphism + beta: '7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee', + lambda: '5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72', + basis: [ + { + a: '3086d221a7d46bcde86c90e49284eb15', + b: '-e4437ed6010e88286f547fa90abfe4c3' + }, + { + a: '114ca50f7a8e2f3f657c1108d9d44cfd8', + b: '3086d221a7d46bcde86c90e49284eb15' + } + ], + + gRed: false, + g: [ + '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', + '483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', + pre + ] + }); + }); + + function HmacDRBG(options) { + if (!(this instanceof HmacDRBG)) + return new HmacDRBG(options); + this.hash = options.hash; + this.predResist = !!options.predResist; + + this.outLen = this.hash.outSize; + this.minEntropy = options.minEntropy || this.hash.hmacStrength; + + this._reseed = null; + this.reseedInterval = null; + this.K = null; + this.V = null; + + var entropy = utils_1.toArray(options.entropy, options.entropyEnc || 'hex'); + var nonce = utils_1.toArray(options.nonce, options.nonceEnc || 'hex'); + var pers = utils_1.toArray(options.pers, options.persEnc || 'hex'); + minimalisticAssert(entropy.length >= (this.minEntropy / 8), + 'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits'); + this._init(entropy, nonce, pers); + } + var hmacDrbg = HmacDRBG; + + HmacDRBG.prototype._init = function init(entropy, nonce, pers) { + var seed = entropy.concat(nonce).concat(pers); + + this.K = new Array(this.outLen / 8); + this.V = new Array(this.outLen / 8); + for (var i = 0; i < this.V.length; i++) { + this.K[i] = 0x00; + this.V[i] = 0x01; + } + + this._update(seed); + this._reseed = 1; + this.reseedInterval = 0x1000000000000; // 2^48 + }; + + HmacDRBG.prototype._hmac = function hmac() { + return new hash_1.hmac(this.hash, this.K); + }; + + HmacDRBG.prototype._update = function update(seed) { + var kmac = this._hmac() + .update(this.V) + .update([ 0x00 ]); + if (seed) + kmac = kmac.update(seed); + this.K = kmac.digest(); + this.V = this._hmac().update(this.V).digest(); + if (!seed) + return; + + this.K = this._hmac() + .update(this.V) + .update([ 0x01 ]) + .update(seed) + .digest(); + this.V = this._hmac().update(this.V).digest(); + }; + + HmacDRBG.prototype.reseed = function reseed(entropy, entropyEnc, add, addEnc) { + // Optional entropy enc + if (typeof entropyEnc !== 'string') { + addEnc = add; + add = entropyEnc; + entropyEnc = null; + } + + entropy = utils_1.toArray(entropy, entropyEnc); + add = utils_1.toArray(add, addEnc); + + minimalisticAssert(entropy.length >= (this.minEntropy / 8), + 'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits'); + + this._update(entropy.concat(add || [])); + this._reseed = 1; + }; + + HmacDRBG.prototype.generate = function generate(len, enc, add, addEnc) { + if (this._reseed > this.reseedInterval) + throw new Error('Reseed is required'); + + // Optional encoding + if (typeof enc !== 'string') { + addEnc = add; + add = enc; + enc = null; + } + + // Optional additional data + if (add) { + add = utils_1.toArray(add, addEnc || 'hex'); + this._update(add); + } + + var temp = []; + while (temp.length < len) { + this.V = this._hmac().update(this.V).digest(); + temp = temp.concat(this.V); + } + + var res = temp.slice(0, len); + this._update(add); + this._reseed++; + return utils_1.encode(res, enc); + }; + + var assert$5 = utils_1$1.assert; + + function KeyPair(ec, options) { + this.ec = ec; + this.priv = null; + this.pub = null; + + // KeyPair(ec, { priv: ..., pub: ... }) + if (options.priv) + this._importPrivate(options.priv, options.privEnc); + if (options.pub) + this._importPublic(options.pub, options.pubEnc); + } + var key = KeyPair; + + KeyPair.fromPublic = function fromPublic(ec, pub, enc) { + if (pub instanceof KeyPair) + return pub; + + return new KeyPair(ec, { + pub: pub, + pubEnc: enc + }); + }; + + KeyPair.fromPrivate = function fromPrivate(ec, priv, enc) { + if (priv instanceof KeyPair) + return priv; + + return new KeyPair(ec, { + priv: priv, + privEnc: enc + }); + }; + + // TODO: should not validate for X25519 + KeyPair.prototype.validate = function validate() { + var pub = this.getPublic(); + + if (pub.isInfinity()) + return { result: false, reason: 'Invalid public key' }; + if (!pub.validate()) + return { result: false, reason: 'Public key is not a point' }; + if (!pub.mul(this.ec.curve.n).isInfinity()) + return { result: false, reason: 'Public key * N != O' }; + + return { result: true, reason: null }; + }; + + KeyPair.prototype.getPublic = function getPublic(enc, compact) { + if (!this.pub) + this.pub = this.ec.g.mul(this.priv); + + if (!enc) + return this.pub; + + return this.pub.encode(enc, compact); + }; + + KeyPair.prototype.getPrivate = function getPrivate(enc) { + if (enc === 'hex') + return this.priv.toString(16, 2); + else + return this.priv; + }; + + KeyPair.prototype._importPrivate = function _importPrivate(key, enc) { + this.priv = new bn(key, enc || 16); + + // For Curve25519/Curve448 we have a specific procedure. + // TODO Curve448 + if (this.ec.curve.type === 'mont') { + var one = this.ec.curve.one; + var mask = one.ushln(255 - 3).sub(one).ushln(3); + this.priv = this.priv.or(one.ushln(255 - 1)); + this.priv = this.priv.and(mask); + } else + // Ensure that the priv won't be bigger than n, otherwise we may fail + // in fixed multiplication method + this.priv = this.priv.umod(this.ec.curve.n); + }; + + KeyPair.prototype._importPublic = function _importPublic(key, enc) { + if (key.x || key.y) { + // Montgomery points only have an `x` coordinate. + // Weierstrass/Edwards points on the other hand have both `x` and + // `y` coordinates. + if (this.ec.curve.type === 'mont') { + assert$5(key.x, 'Need x coordinate'); + } else if (this.ec.curve.type === 'short' || + this.ec.curve.type === 'edwards') { + assert$5(key.x && key.y, 'Need both x and y coordinate'); + } + this.pub = this.ec.curve.point(key.x, key.y); + return; + } + this.pub = this.ec.curve.decodePoint(key, enc); + }; + + // ECDH + KeyPair.prototype.derive = function derive(pub) { + return pub.mul(this.priv).getX(); + }; + + // ECDSA + KeyPair.prototype.sign = function sign(msg, enc, options) { + return this.ec.sign(msg, this, enc, options); + }; + + KeyPair.prototype.verify = function verify(msg, signature) { + return this.ec.verify(msg, signature, this); + }; + + KeyPair.prototype.inspect = function inspect() { + return ''; + }; + + var assert$6 = utils_1$1.assert; + + function Signature$1(options, enc) { + if (options instanceof Signature$1) + return options; + + if (this._importDER(options, enc)) + return; + + assert$6(options.r && options.s, 'Signature without r or s'); + this.r = new bn(options.r, 16); + this.s = new bn(options.s, 16); + if (options.recoveryParam === undefined) + this.recoveryParam = null; + else + this.recoveryParam = options.recoveryParam; + } + var signature$1 = Signature$1; + + function Position() { + this.place = 0; + } + + function getLength(buf, p) { + var initial = buf[p.place++]; + if (!(initial & 0x80)) { + return initial; + } + var octetLen = initial & 0xf; + var val = 0; + for (var i = 0, off = p.place; i < octetLen; i++, off++) { + val <<= 8; + val |= buf[off]; + } + p.place = off; + return val; + } + + function rmPadding(buf) { + var i = 0; + var len = buf.length - 1; + while (!buf[i] && !(buf[i + 1] & 0x80) && i < len) { + i++; + } + if (i === 0) { + return buf; + } + return buf.slice(i); + } + + Signature$1.prototype._importDER = function _importDER(data, enc) { + data = utils_1$1.toArray(data, enc); + var p = new Position(); + if (data[p.place++] !== 0x30) { + return false; + } + var len = getLength(data, p); + if ((len + p.place) !== data.length) { + return false; + } + if (data[p.place++] !== 0x02) { + return false; + } + var rlen = getLength(data, p); + var r = data.slice(p.place, rlen + p.place); + p.place += rlen; + if (data[p.place++] !== 0x02) { + return false; + } + var slen = getLength(data, p); + if (data.length !== slen + p.place) { + return false; + } + var s = data.slice(p.place, slen + p.place); + if (r[0] === 0 && (r[1] & 0x80)) { + r = r.slice(1); + } + if (s[0] === 0 && (s[1] & 0x80)) { + s = s.slice(1); + } + + this.r = new bn(r); + this.s = new bn(s); + this.recoveryParam = null; + + return true; + }; + + function constructLength(arr, len) { + if (len < 0x80) { + arr.push(len); + return; + } + var octets = 1 + (Math.log(len) / Math.LN2 >>> 3); + arr.push(octets | 0x80); + while (--octets) { + arr.push((len >>> (octets << 3)) & 0xff); + } + arr.push(len); + } + + Signature$1.prototype.toDER = function toDER(enc) { + var r = this.r.toArray(); + var s = this.s.toArray(); + + // Pad values + if (r[0] & 0x80) + r = [ 0 ].concat(r); + // Pad values + if (s[0] & 0x80) + s = [ 0 ].concat(s); + + r = rmPadding(r); + s = rmPadding(s); + + while (!s[0] && !(s[1] & 0x80)) { + s = s.slice(1); + } + var arr = [ 0x02 ]; + constructLength(arr, r.length); + arr = arr.concat(r); + arr.push(0x02); + constructLength(arr, s.length); + var backHalf = arr.concat(s); + var res = [ 0x30 ]; + constructLength(res, backHalf.length); + res = res.concat(backHalf); + return utils_1$1.encode(res, enc); + }; + + var assert$7 = utils_1$1.assert; + + + + + function EC(options) { + if (!(this instanceof EC)) + return new EC(options); + + // Shortcut `elliptic.ec(curve-name)` + if (typeof options === 'string') { + assert$7(curves_1.hasOwnProperty(options), 'Unknown curve ' + options); + + options = curves_1[options]; + } + + // Shortcut for `elliptic.ec(elliptic.curves.curveName)` + if (options instanceof curves_1.PresetCurve) + options = { curve: options }; + + this.curve = options.curve.curve; + this.n = this.curve.n; + this.nh = this.n.ushrn(1); + this.g = this.curve.g; + + // Point on curve + this.g = options.curve.g; + this.g.precompute(options.curve.n.bitLength() + 1); + + // Hash function for DRBG + this.hash = options.hash || options.curve.hash; + } + var ec = EC; + + EC.prototype.keyPair = function keyPair(options) { + return new key(this, options); + }; + + EC.prototype.keyFromPrivate = function keyFromPrivate(priv, enc) { + return key.fromPrivate(this, priv, enc); + }; + + EC.prototype.keyFromPublic = function keyFromPublic(pub, enc) { + return key.fromPublic(this, pub, enc); + }; + + EC.prototype.genKeyPair = function genKeyPair(options) { + if (!options) + options = {}; + + // Instantiate Hmac_DRBG + var drbg = new hmacDrbg({ + hash: this.hash, + pers: options.pers, + persEnc: options.persEnc || 'utf8', + entropy: options.entropy || brorand(this.hash.hmacStrength), + entropyEnc: options.entropy && options.entropyEnc || 'utf8', + nonce: this.n.toArray() + }); + + // Key generation for curve25519 is simpler + if (this.curve.type === 'mont') { + var priv = new bn(drbg.generate(32)); + return this.keyFromPrivate(priv); + } + + var bytes = this.n.byteLength(); + var ns2 = this.n.sub(new bn(2)); + do { + var priv = new bn(drbg.generate(bytes)); + if (priv.cmp(ns2) > 0) + continue; + + priv.iaddn(1); + return this.keyFromPrivate(priv); + } while (true); + }; + + EC.prototype._truncateToN = function truncateToN(msg, truncOnly, bitSize) { + bitSize = bitSize || msg.byteLength() * 8; + var delta = bitSize - this.n.bitLength(); + if (delta > 0) + msg = msg.ushrn(delta); + if (!truncOnly && msg.cmp(this.n) >= 0) + return msg.sub(this.n); + else + return msg; + }; + + EC.prototype.truncateMsg = function truncateMSG(msg) { + // Bit size is only determined correctly for Uint8Arrays and hex strings + var bitSize; + if (msg instanceof Uint8Array) { + bitSize = msg.byteLength * 8; + msg = this._truncateToN(new bn(msg, 16), false, bitSize); + } else if (typeof msg === 'string') { + bitSize = msg.length * 4; + msg = this._truncateToN(new bn(msg, 16), false, bitSize); + } else { + msg = this._truncateToN(new bn(msg, 16)); + } + return msg; + }; + + EC.prototype.sign = function sign(msg, key, enc, options) { + if (typeof enc === 'object') { + options = enc; + enc = null; + } + if (!options) + options = {}; + + key = this.keyFromPrivate(key, enc); + msg = this.truncateMsg(msg); + + // Zero-extend key to provide enough entropy + var bytes = this.n.byteLength(); + var bkey = key.getPrivate().toArray('be', bytes); + + // Zero-extend nonce to have the same byte size as N + var nonce = msg.toArray('be', bytes); + + // Instantiate Hmac_DRBG + var drbg = new hmacDrbg({ + hash: this.hash, + entropy: bkey, + nonce: nonce, + pers: options.pers, + persEnc: options.persEnc || 'utf8' + }); + + // Number of bytes to generate + var ns1 = this.n.sub(new bn(1)); + + for (var iter = 0; true; iter++) { + var k = options.k ? + options.k(iter) : + new bn(drbg.generate(this.n.byteLength())); + k = this._truncateToN(k, true); + if (k.cmpn(1) <= 0 || k.cmp(ns1) >= 0) + continue; + + var kp = this.g.mul(k); + if (kp.isInfinity()) + continue; + + var kpX = kp.getX(); + var r = kpX.umod(this.n); + if (r.cmpn(0) === 0) + continue; + + var s = k.invm(this.n).mul(r.mul(key.getPrivate()).iadd(msg)); + s = s.umod(this.n); + if (s.cmpn(0) === 0) + continue; + + var recoveryParam = (kp.getY().isOdd() ? 1 : 0) | + (kpX.cmp(r) !== 0 ? 2 : 0); + + // Use complement of `s`, if it is > `n / 2` + if (options.canonical && s.cmp(this.nh) > 0) { + s = this.n.sub(s); + recoveryParam ^= 1; + } + + return new signature$1({ r: r, s: s, recoveryParam: recoveryParam }); + } + }; + + EC.prototype.verify = function verify(msg, signature, key, enc) { + key = this.keyFromPublic(key, enc); + signature = new signature$1(signature, 'hex'); + // Fallback to the old code + var ret = this._verify(this.truncateMsg(msg), signature, key) || + this._verify(this._truncateToN(new bn(msg, 16)), signature, key); + return ret; + }; + + EC.prototype._verify = function _verify(msg, signature, key) { + // Perform primitive values validation + var r = signature.r; + var s = signature.s; + if (r.cmpn(1) < 0 || r.cmp(this.n) >= 0) + return false; + if (s.cmpn(1) < 0 || s.cmp(this.n) >= 0) + return false; + + // Validate signature + var sinv = s.invm(this.n); + var u1 = sinv.mul(msg).umod(this.n); + var u2 = sinv.mul(r).umod(this.n); + + if (!this.curve._maxwellTrick) { + var p = this.g.mulAdd(u1, key.getPublic(), u2); + if (p.isInfinity()) + return false; + + return p.getX().umod(this.n).cmp(r) === 0; + } + + // NOTE: Greg Maxwell's trick, inspired by: + // https://git.io/vad3K + + var p = this.g.jmulAdd(u1, key.getPublic(), u2); + if (p.isInfinity()) + return false; + + // Compare `p.x` of Jacobian point with `r`, + // this will do `p.x == r * p.z^2` instead of multiplying `p.x` by the + // inverse of `p.z^2` + return p.eqXToP(r); + }; + + EC.prototype.recoverPubKey = function(msg, signature, j, enc) { + assert$7((3 & j) === j, 'The recovery param is more than two bits'); + signature = new signature$1(signature, enc); + + var n = this.n; + var e = new bn(msg); + var r = signature.r; + var s = signature.s; + + // A set LSB signifies that the y-coordinate is odd + var isYOdd = j & 1; + var isSecondKey = j >> 1; + if (r.cmp(this.curve.p.umod(this.curve.n)) >= 0 && isSecondKey) + throw new Error('Unable to find sencond key candinate'); + + // 1.1. Let x = r + jn. + if (isSecondKey) + r = this.curve.pointFromX(r.add(this.curve.n), isYOdd); + else + r = this.curve.pointFromX(r, isYOdd); + + var rInv = signature.r.invm(n); + var s1 = n.sub(e).mul(rInv).umod(n); + var s2 = s.mul(rInv).umod(n); + + // 1.6.1 Compute Q = r^-1 (sR - eG) + // Q = r^-1 (sR + -eG) + return this.g.mulAdd(s1, r, s2); + }; + + EC.prototype.getKeyRecoveryParam = function(e, signature, Q, enc) { + signature = new signature$1(signature, enc); + if (signature.recoveryParam !== null) + return signature.recoveryParam; + + for (var i = 0; i < 4; i++) { + var Qprime; + try { + Qprime = this.recoverPubKey(e, signature, i); + } catch (e) { + continue; + } + + if (Qprime.eq(Q)) + return i; + } + throw new Error('Unable to find valid recovery factor'); + }; + + var assert$8 = utils_1$1.assert; + var parseBytes = utils_1$1.parseBytes; + var cachedProperty = utils_1$1.cachedProperty; + + /** + * @param {EDDSA} eddsa - instance + * @param {Object} params - public/private key parameters + * + * @param {Array} [params.secret] - secret seed bytes + * @param {Point} [params.pub] - public key point (aka `A` in eddsa terms) + * @param {Array} [params.pub] - public key point encoded as bytes + * + */ + function KeyPair$1(eddsa, params) { + this.eddsa = eddsa; + if (params.hasOwnProperty('secret')) + this._secret = parseBytes(params.secret); + if (eddsa.isPoint(params.pub)) + this._pub = params.pub; + else { + this._pubBytes = parseBytes(params.pub); + if (this._pubBytes && this._pubBytes.length === 33 && + this._pubBytes[0] === 0x40) + this._pubBytes = this._pubBytes.slice(1, 33); + if (this._pubBytes && this._pubBytes.length !== 32) + throw new Error('Unknown point compression format'); + } + } + + KeyPair$1.fromPublic = function fromPublic(eddsa, pub) { + if (pub instanceof KeyPair$1) + return pub; + return new KeyPair$1(eddsa, { pub: pub }); + }; + + KeyPair$1.fromSecret = function fromSecret(eddsa, secret) { + if (secret instanceof KeyPair$1) + return secret; + return new KeyPair$1(eddsa, { secret: secret }); + }; + + KeyPair$1.prototype.secret = function secret() { + return this._secret; + }; + + cachedProperty(KeyPair$1, 'pubBytes', function pubBytes() { + return this.eddsa.encodePoint(this.pub()); + }); + + cachedProperty(KeyPair$1, 'pub', function pub() { + if (this._pubBytes) + return this.eddsa.decodePoint(this._pubBytes); + return this.eddsa.g.mul(this.priv()); + }); + + cachedProperty(KeyPair$1, 'privBytes', function privBytes() { + var eddsa = this.eddsa; + var hash = this.hash(); + var lastIx = eddsa.encodingLength - 1; + + // https://tools.ietf.org/html/rfc8032#section-5.1.5 + var a = hash.slice(0, eddsa.encodingLength); + a[0] &= 248; + a[lastIx] &= 127; + a[lastIx] |= 64; + + return a; + }); + + cachedProperty(KeyPair$1, 'priv', function priv() { + return this.eddsa.decodeInt(this.privBytes()); + }); + + cachedProperty(KeyPair$1, 'hash', function hash() { + return this.eddsa.hash().update(this.secret()).digest(); + }); + + cachedProperty(KeyPair$1, 'messagePrefix', function messagePrefix() { + return this.hash().slice(this.eddsa.encodingLength); + }); + + KeyPair$1.prototype.sign = function sign(message) { + assert$8(this._secret, 'KeyPair can only verify'); + return this.eddsa.sign(message, this); + }; + + KeyPair$1.prototype.verify = function verify(message, sig) { + return this.eddsa.verify(message, sig, this); + }; + + KeyPair$1.prototype.getSecret = function getSecret(enc) { + assert$8(this._secret, 'KeyPair is public only'); + return utils_1$1.encode(this.secret(), enc); + }; + + KeyPair$1.prototype.getPublic = function getPublic(enc, compact) { + return utils_1$1.encode((compact ? [ 0x40 ] : []).concat(this.pubBytes()), enc); + }; + + var key$1 = KeyPair$1; + + var assert$9 = utils_1$1.assert; + var cachedProperty$1 = utils_1$1.cachedProperty; + var parseBytes$1 = utils_1$1.parseBytes; + + /** + * @param {EDDSA} eddsa - eddsa instance + * @param {Array|Object} sig - + * @param {Array|Point} [sig.R] - R point as Point or bytes + * @param {Array|bn} [sig.S] - S scalar as bn or bytes + * @param {Array} [sig.Rencoded] - R point encoded + * @param {Array} [sig.Sencoded] - S scalar encoded + */ + function Signature$2(eddsa, sig) { + this.eddsa = eddsa; + + if (typeof sig !== 'object') + sig = parseBytes$1(sig); + + if (Array.isArray(sig)) { + sig = { + R: sig.slice(0, eddsa.encodingLength), + S: sig.slice(eddsa.encodingLength) + }; + } + + assert$9(sig.R && sig.S, 'Signature without R or S'); + + if (eddsa.isPoint(sig.R)) + this._R = sig.R; + if (sig.S instanceof bn) + this._S = sig.S; + + this._Rencoded = Array.isArray(sig.R) ? sig.R : sig.Rencoded; + this._Sencoded = Array.isArray(sig.S) ? sig.S : sig.Sencoded; + } + + cachedProperty$1(Signature$2, 'S', function S() { + return this.eddsa.decodeInt(this.Sencoded()); + }); + + cachedProperty$1(Signature$2, 'R', function R() { + return this.eddsa.decodePoint(this.Rencoded()); + }); + + cachedProperty$1(Signature$2, 'Rencoded', function Rencoded() { + return this.eddsa.encodePoint(this.R()); + }); + + cachedProperty$1(Signature$2, 'Sencoded', function Sencoded() { + return this.eddsa.encodeInt(this.S()); + }); + + Signature$2.prototype.toBytes = function toBytes() { + return this.Rencoded().concat(this.Sencoded()); + }; + + Signature$2.prototype.toHex = function toHex() { + return utils_1$1.encode(this.toBytes(), 'hex').toUpperCase(); + }; + + var signature$2 = Signature$2; + + var assert$a = utils_1$1.assert; + var parseBytes$2 = utils_1$1.parseBytes; + + + + function EDDSA(curve) { + assert$a(curve === 'ed25519', 'only tested with ed25519 so far'); + + if (!(this instanceof EDDSA)) + return new EDDSA(curve); + + var curve = curves_1[curve].curve; + this.curve = curve; + this.g = curve.g; + this.g.precompute(curve.n.bitLength() + 1); + + this.pointClass = curve.point().constructor; + this.encodingLength = Math.ceil(curve.n.bitLength() / 8); + this.hash = hash_1.sha512; + } + + var eddsa$1 = EDDSA; + + /** + * @param {Array|String} message - message bytes + * @param {Array|String|KeyPair} secret - secret bytes or a keypair + * @returns {Signature} - signature + */ + EDDSA.prototype.sign = function sign(message, secret) { + message = parseBytes$2(message); + var key = this.keyFromSecret(secret); + var r = this.hashInt(key.messagePrefix(), message); + var R = this.g.mul(r); + var Rencoded = this.encodePoint(R); + var s_ = this.hashInt(Rencoded, key.pubBytes(), message) + .mul(key.priv()); + var S = r.add(s_).umod(this.curve.n); + return this.makeSignature({ R: R, S: S, Rencoded: Rencoded }); + }; + + /** + * @param {Array} message - message bytes + * @param {Array|String|Signature} sig - sig bytes + * @param {Array|String|Point|KeyPair} pub - public key + * @returns {Boolean} - true if public key matches sig of message + */ + EDDSA.prototype.verify = function verify(message, sig, pub) { + message = parseBytes$2(message); + sig = this.makeSignature(sig); + var key = this.keyFromPublic(pub); + var h = this.hashInt(sig.Rencoded(), key.pubBytes(), message); + var SG = this.g.mul(sig.S()); + var RplusAh = sig.R().add(key.pub().mul(h)); + return RplusAh.eq(SG); + }; + + EDDSA.prototype.hashInt = function hashInt() { + var hash = this.hash(); + for (var i = 0; i < arguments.length; i++) + hash.update(arguments[i]); + return utils_1$1.intFromLE(hash.digest()).umod(this.curve.n); + }; + + EDDSA.prototype.keyPair = function keyPair(options) { + return new key$1(this, options); + }; + + EDDSA.prototype.keyFromPublic = function keyFromPublic(pub) { + return key$1.fromPublic(this, pub); + }; + + EDDSA.prototype.keyFromSecret = function keyFromSecret(secret) { + return key$1.fromSecret(this, secret); + }; + + EDDSA.prototype.genKeyPair = function genKeyPair(options) { + if (!options) + options = {}; + + // Instantiate Hmac_DRBG + var drbg = new hmacDrbg({ + hash: this.hash, + pers: options.pers, + persEnc: options.persEnc || 'utf8', + entropy: options.entropy || brorand(this.hash.hmacStrength), + entropyEnc: options.entropy && options.entropyEnc || 'utf8', + nonce: this.curve.n.toArray() + }); + + return this.keyFromSecret(drbg.generate(32)); + }; + + EDDSA.prototype.makeSignature = function makeSignature(sig) { + if (sig instanceof signature$2) + return sig; + return new signature$2(this, sig); + }; + + /** + * * https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03#section-5.2 + * + * EDDSA defines methods for encoding and decoding points and integers. These are + * helper convenience methods, that pass along to utility functions implied + * parameters. + * + */ + EDDSA.prototype.encodePoint = function encodePoint(point) { + var enc = point.getY().toArray('le', this.encodingLength); + enc[this.encodingLength - 1] |= point.getX().isOdd() ? 0x80 : 0; + return enc; + }; + + EDDSA.prototype.decodePoint = function decodePoint(bytes) { + bytes = utils_1$1.parseBytes(bytes); + + var lastIx = bytes.length - 1; + var normed = bytes.slice(0, lastIx).concat(bytes[lastIx] & ~0x80); + var xIsOdd = (bytes[lastIx] & 0x80) !== 0; + + var y = utils_1$1.intFromLE(normed); + return this.curve.pointFromY(y, xIsOdd); + }; + + EDDSA.prototype.encodeInt = function encodeInt(num) { + return num.toArray('le', this.encodingLength); + }; + + EDDSA.prototype.decodeInt = function decodeInt(bytes) { + return utils_1$1.intFromLE(bytes); + }; + + EDDSA.prototype.isPoint = function isPoint(val) { + return val instanceof this.pointClass; + }; + + var elliptic_1 = createCommonjsModule(function (module, exports) { + + var elliptic = exports; + + elliptic.utils = utils_1$1; + elliptic.rand = brorand; + elliptic.curve = curve_1; + elliptic.curves = curves_1; + + // Protocols + elliptic.ec = ec; + elliptic.eddsa = eddsa$1; + }); + + var elliptic$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + 'default': elliptic_1, + __moduleExports: elliptic_1 + }); + + exports.AEADEncryptedDataPacket = AEADEncryptedDataPacket; + exports.CleartextMessage = CleartextMessage; + exports.CompressedDataPacket = CompressedDataPacket; + exports.LiteralDataPacket = LiteralDataPacket; + exports.MarkerPacket = MarkerPacket; + exports.Message = Message; + exports.OnePassSignaturePacket = OnePassSignaturePacket; + exports.PacketList = PacketList; + exports.PrivateKey = PrivateKey; + exports.PublicKey = PublicKey; + exports.PublicKeyEncryptedSessionKeyPacket = PublicKeyEncryptedSessionKeyPacket; + exports.PublicKeyPacket = PublicKeyPacket; + exports.PublicSubkeyPacket = PublicSubkeyPacket; + exports.SecretKeyPacket = SecretKeyPacket; + exports.SecretSubkeyPacket = SecretSubkeyPacket; + exports.Signature = Signature; + exports.SignaturePacket = SignaturePacket; + exports.Subkey = Subkey; + exports.SymEncryptedIntegrityProtectedDataPacket = SymEncryptedIntegrityProtectedDataPacket; + exports.SymEncryptedSessionKeyPacket = SymEncryptedSessionKeyPacket; + exports.SymmetricallyEncryptedDataPacket = SymmetricallyEncryptedDataPacket; + exports.TrustPacket = TrustPacket; + exports.UserAttributePacket = UserAttributePacket; + exports.UserIDPacket = UserIDPacket; + exports.armor = armor; + exports.config = defaultConfig; + exports.createCleartextMessage = createCleartextMessage; + exports.createMessage = createMessage; + exports.decrypt = decrypt$4; + exports.decryptKey = decryptKey; + exports.decryptSessionKeys = decryptSessionKeys; + exports.encrypt = encrypt$4; + exports.encryptKey = encryptKey; + exports.encryptSessionKey = encryptSessionKey; + exports.enums = enums; + exports.generateKey = generateKey; + exports.generateSessionKey = generateSessionKey$1; + exports.readCleartextMessage = readCleartextMessage; + exports.readKey = readKey; + exports.readKeys = readKeys; + exports.readMessage = readMessage; + exports.readPrivateKey = readPrivateKey; + exports.readPrivateKeys = readPrivateKeys; + exports.readSignature = readSignature; + exports.reformatKey = reformatKey; + exports.revokeKey = revokeKey; + exports.sign = sign$5; + exports.unarmor = unarmor; + exports.verify = verify$5; + +// -----BEGIN ADDED BY FLOWCRYPT---- +exports.Hash = Hash; +exports.Sha1 = Sha1; +exports.Sha256 = Sha256; +exports.readToEnd = readToEnd; +exports.util = util; +// -----END ADDED BY FLOWCRYPT----- + + + + Object.defineProperty(exports, '__esModule', { value: true }); + + return exports; + +}({})); From 2092c65300dc62c5899a3311f2e817d58b5f10ca Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 22:33:54 +0200 Subject: [PATCH 105/179] wip --- Core/source/test.ts | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/Core/source/test.ts b/Core/source/test.ts index e9b839333..9915418fd 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -338,11 +338,11 @@ ava.default.only('parseKeys', async t => { const { pubKeys: [pubkey] } = getKeypairs('rsa1'); console.log(pubkey); const { data, json } = parseResponse(await endpoints.parseKeys({}, [Buffer.from(pubkey)])); - expect(json).to.deep.equal({ + const expected = { "format": "armored", "keyDetails": [ { - "public": "-----BEGIN PGP PUBLIC KEY BLOCK-----\r\nVersion: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption\r\nComment: Seamlessly send and receive encrypted email\r\n\r\nxsBNBFwBWOEBB/9uIqBYIPDQbBqHMvGXhgnm+b2i5rNLXrrGoalrp7wYQ654\r\nZln/+ffxzttRLRiwRQAOG0z78aMDXAHRfI9d3GaRKTkhTqVY+C02E8NxgB3+\r\nmbSsF0Ui+oh1//LT1ic6ZnISCA7Q2h2U/DSAPNxDZUMu9kjh9TjkKlR81fiA\r\nlxuD05ivRxCnmZnzqZtHoUvvCqsENgRjO9a5oWpMwtdItjdRFF7UFKYpfeA+\r\nct0uUNMRVdPK7MXBEr2FdWiKN1K21dQ1pWiAwj/5cTA8hu5Jue2RcF8FcPfs\r\nniRihQkNqtLDsfY5no1B3xeSnyO2SES1bAHw8ObXZn/C/6jxFztkn4NbABEB\r\nAAHNEFRlc3QgPHRAZXN0LmNvbT7CwH8EEAEIACkFAlwBWOEGCwkHCAMCCRA6\r\nMPTMCpqPEAQVCAoCAxYCAQIZAQIbAwIeAQAKCRA6MPTMCpqPENaTB/0faBFR\r\n2k3RM7P427HyZOsZtqEPxuynsLUqmsAAup6LtPhir4CAsb5DSvgYrzC8pbrf\r\njCaodoB7hMXc8RxTbSh+vQc5Su4QwY8sqy7hyMXOGGWsRxnuZ8t8BeEJBIHy\r\nPguXIR+wYvo1eveC+NMxHhTtjoSIn/E4vW0W9j5OlFeTK7HTNCuidIE0Hk2k\r\nXnEEoNO7ztxPPxsHz9g56uMhyAhf3mqKfvUFo/FLLRBOpxLO0kk64yAMcAHm\r\nc6ZI5Fz10y48+hHEv/RFOwfub9asF5NWHltanqyiZ+kHeoaieYJFc6t7Mt3j\r\ng8qxMKTUKAEeCfHt1UJCjp/aIgJRU4JRXgYXzsBNBFwBWOEBB/9nclmx98vf\r\noSpPUccBczvuZxmqk+jY6Id+vBhBFoEhtdTSpaw/JNstf0dTXN8RCFjB0lHt\r\na51llTjSobqcFwAU54/HKDOW3qMVbvadaGILpuCMCxdMgLWlpZdYY7BApv1N\r\n9zpN+iQ2tIrvnUQ312xKOXF/W83NUJ1nTObQYNpsUZLLG2N3kz11HuBS3E9F\r\ngEOYYy1tLT53hs5btqvQ5Jp4Iw5cBoBoTAmv+dPMDKYBroBPwuFeNRIokwLT\r\nrVcxrXajxlXaGXmmGS3PZ00HXq2g7vKIqWliMLLIWFl+LlVb6O8bMeXOT1l0\r\nXSO9GlLOSMDEc7pY26vkmAjbWv7iUWHNABEBAAHCwGkEGAEIABMFAlwBWOEJ\r\nEDow9MwKmo8QAhsMAAoJEDow9MwKmo8QjTcH/1pYXyXW/rpBrDg7w/dXJCfT\r\n8+RVYlhW3kqMxbid7EB8zgGVTDr3us/ki99hc2HjsKbxUqrGBxeh3Mmui7OD\r\nCI8XFeYl7lSDbgU6mZ5J4iXzdR8LNqIib4Horlx/Y24dOuvikSUNpDtFAYfa\r\nbZwxyKa/ihZT1rS1GO3V7tdAB9BJagJqVRssF5g5GBUAX3sxQ2p62HoUxPlJ\r\nOOr4AaCc1na92xScBJL8dtBBRQ5pUZWOjb2UHp9L5QdPaBX8T9ZAieOiTlSt\r\nQxoUfCk7RU0/TnsM3KqFnDFoCzkGxKAmU4LmGtP48qV+v2Jzvl+qcmqYuKtw\r\nH6FWd+EZH07MfdEIiTI=\r\n=wXbX\r\n-----END PGP PUBLIC KEY BLOCK-----\r\n", + "public": "-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption\nComment: Seamlessly send and receive encrypted email\n\nxsBNBFwBWOEBB/9uIqBYIPDQbBqHMvGXhgnm+b2i5rNLXrrGoalrp7wYQ654\nZln/+ffxzttRLRiwRQAOG0z78aMDXAHRfI9d3GaRKTkhTqVY+C02E8NxgB3+\nmbSsF0Ui+oh1//LT1ic6ZnISCA7Q2h2U/DSAPNxDZUMu9kjh9TjkKlR81fiA\nlxuD05ivRxCnmZnzqZtHoUvvCqsENgRjO9a5oWpMwtdItjdRFF7UFKYpfeA+\nct0uUNMRVdPK7MXBEr2FdWiKN1K21dQ1pWiAwj/5cTA8hu5Jue2RcF8FcPfs\nniRihQkNqtLDsfY5no1B3xeSnyO2SES1bAHw8ObXZn/C/6jxFztkn4NbABEB\nAAHNEFRlc3QgPHRAZXN0LmNvbT7CwH8EEAEIACkFAlwBWOEGCwkHCAMCCRA6\nMPTMCpqPEAQVCAoCAxYCAQIZAQIbAwIeAQAKCRA6MPTMCpqPENaTB/0faBFR\n2k3RM7P427HyZOsZtqEPxuynsLUqmsAAup6LtPhir4CAsb5DSvgYrzC8pbrf\njCaodoB7hMXc8RxTbSh+vQc5Su4QwY8sqy7hyMXOGGWsRxnuZ8t8BeEJBIHy\nPguXIR+wYvo1eveC+NMxHhTtjoSIn/E4vW0W9j5OlFeTK7HTNCuidIE0Hk2k\nXnEEoNO7ztxPPxsHz9g56uMhyAhf3mqKfvUFo/FLLRBOpxLO0kk64yAMcAHm\nc6ZI5Fz10y48+hHEv/RFOwfub9asF5NWHltanqyiZ+kHeoaieYJFc6t7Mt3j\ng8qxMKTUKAEeCfHt1UJCjp/aIgJRU4JRXgYXzsBNBFwBWOEBB/9nclmx98vf\noSpPUccBczvuZxmqk+jY6Id+vBhBFoEhtdTSpaw/JNstf0dTXN8RCFjB0lHt\na51llTjSobqcFwAU54/HKDOW3qMVbvadaGILpuCMCxdMgLWlpZdYY7BApv1N\n9zpN+iQ2tIrvnUQ312xKOXF/W83NUJ1nTObQYNpsUZLLG2N3kz11HuBS3E9F\ngEOYYy1tLT53hs5btqvQ5Jp4Iw5cBoBoTAmv+dPMDKYBroBPwuFeNRIokwLT\nrVcxrXajxlXaGXmmGS3PZ00HXq2g7vKIqWliMLLIWFl+LlVb6O8bMeXOT1l0\nXSO9GlLOSMDEc7pY26vkmAjbWv7iUWHNABEBAAHCwGkEGAEIABMFAlwBWOEJ\nEDow9MwKmo8QAhsMAAoJEDow9MwKmo8QjTcH/1pYXyXW/rpBrDg7w/dXJCfT\n8+RVYlhW3kqMxbid7EB8zgGVTDr3us/ki99hc2HjsKbxUqrGBxeh3Mmui7OD\nCI8XFeYl7lSDbgU6mZ5J4iXzdR8LNqIib4Horlx/Y24dOuvikSUNpDtFAYfa\nbZwxyKa/ihZT1rS1GO3V7tdAB9BJagJqVRssF5g5GBUAX3sxQ2p62HoUxPlJ\nOOr4AaCc1na92xScBJL8dtBBRQ5pUZWOjb2UHp9L5QdPaBX8T9ZAieOiTlSt\nQxoUfCk7RU0/TnsM3KqFnDFoCzkGxKAmU4LmGtP48qV+v2Jzvl+qcmqYuKtw\nH6FWd+EZH07MfdEIiTI=\n=wXbX\n-----END PGP PUBLIC KEY BLOCK-----\n", "users": [ "Test " ], @@ -351,8 +351,8 @@ ava.default.only('parseKeys', async t => { { "fingerprint": "9EF2F8F36A841C0D5FAB8B0F0BAB9C018B265D22", "longid": "0BAB9C018B265D22", "shortid": "8B265D22", "keywords": "ARM FRIEND ABOUT BIND GRAPE CATTLE" } ], "algo": { - "algorithm": "rsa_encrypt_sign", - "bits": 2048, + "algorithm": "rsaEncryptSign", + "bits": 2047, "algorithmId": 1 }, "created": 1543592161, @@ -360,7 +360,11 @@ ava.default.only('parseKeys', async t => { "revoked": false } ] - }); + }; + //expect(json).to.deep.equal(expected); + expect(json.keyDetails[0].ids[0]).to.deep.equal(expected.keyDetails[0].ids[0]); + expect(json.keyDetails[0].ids[1]).to.deep.equal(expected.keyDetails[0].ids[1]); + expect(json.keyDetails[0]).to.deep.equal(expected.keyDetails[0]); expectNoData(data); t.pass(); }); @@ -372,7 +376,7 @@ ava.default('parseKeys - expiration and date last updated', async t => { "format": "armored", "keyDetails": [ { - "public": "-----BEGIN PGP PUBLIC KEY BLOCK-----\r\nVersion: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption\r\nComment: Seamlessly send and receive encrypted email\r\n\r\nxsBNBF8PcdUBCADi8no6T4Bd9Ny5COpbheBuPWEyDOedT2EVeaPrfutB1D8i\r\nCP6Rf1cUvs/qNUX/O7HQHFpgFuW2uOY4OU5cvcrwmNpOxT3pPt2cavxJMdJo\r\nfwEvloY3OfY7MCqdAj5VUcFGMhubfV810V2n5pf2FFUNTirksT6muhviMymy\r\nuWZLdh0F4WxrXEon7k3y2dZ3mI4xsG+Djttb6hj3gNr8/zNQQnTmVjB0mmpO\r\nFcGUQLTTTYMngvVMkz8/sh38trqkVGuf/M81gkbr1egnfKfGz/4NT3qQLjin\r\nnA8In2cSFS/MipIV14gTfHQAICFIMsWuW/xkaXUqygvAnyFa2nAQdgELABEB\r\nAAHNKDxhdXRvLnJlZnJlc2guZXhwaXJlZC5rZXlAcmVjaXBpZW50LmNvbT7C\r\nwJMEEAEIACYFAl8PcdUFCQAAAAEGCwkHCAMCBBUICgIEFgIBAAIZAQIbAwIe\r\nAQAhCRC+46QtmpyKyRYhBG0+CYZ1RO5ify6Sj77jpC2anIrJIvQIALG8TGMN\r\nYB4CRouMJawNCLui6Fx4Ba1ipPTaqlJPybLoe6z/WVZwAA9CmbjkCIk683pp\r\nmGQ3GXv7f8Sdk7DqhEhfZ7JtAK/Uw2VZqqIryNrrB0WV3EUHsENCOlq0YJod\r\nLqtkqgl83lCNDIkeoQwq4IyrgC8wsPgF7YMpxxQLONJvChZxSdCDjnfX3kvO\r\nZsLYFiKnNlX6wyrKAQxWnxxYhglMf0GDDyh0AJ+vOQHJ9m+oeBnA1tJ5AZU5\r\naQHvRtyWBKkYaEhljhyWr3eu1JjK4mn7/W6Rszveso33987wtIoQ66GpGcX2\r\nmh7y217y/uXz4D3X5PUEBXIbhvAPty71bnTOwE0EXw9x1QEIALdJgAsQ0Jnv\r\nLXwAKoOammWlUQmracK89v1Yc4mFnImtHDHS3pGsbx3DbNGuiz5BhXCdoPDf\r\ngMxlGmJgShy9JAhrhWFXkvsjW/7aO4bM1wU486VPKXb7Av/dcrfHH0ASj4zj\r\n/TYAeubNoxQtxHgyb13LVCW1kh4Oe6s0ac/hKtxogwEvNFY3x+4yfloHH0Ik\r\n9sbLGk0gS03bPABDHMpYk346406f5TuP6UDzb9M90i2cFxbq26svyBzBZ0vY\r\nzfMRuNsm6an0+B/wS6NLYBqsRyxwwCTdrhYS512yBzCHDYJJX0o3OJNe85/0\r\nTqEBO1prgkh3QMfw13/Oxq8PuMsyJpUAEQEAAcLAfAQYAQgADwUCXw9x1QUJ\r\nAAAAAQIbDAAhCRC+46QtmpyKyRYhBG0+CYZ1RO5ify6Sj77jpC2anIrJARgH\r\n/1KV7JBOS2ZEtO95FrLYnIqI45rRpvT1XArpBPrYLuHtDBwgMcmpiMhhKIZC\r\nFlZkR1W88ENdSkr8Nx81nW+f9JWRR6HuSyom7kOfS2Gdbfwo3bgp48DWr7K8\r\nKV/HHGuqLqd8UfPyDpsBGNx0w7tRo+8vqUbhskquLAIahYCbhEIE8zgy0fBV\r\nhXKFe1FjuFUoW29iEm0tZWX0k2PT5r1owEgDe0g/X1AXgSQyfPRFVDwE3QNJ\r\n1np/Rmygq1C+DIW2cohJOc7tO4gbl11XolsfQ+FU+HewYXy8aAEbrTSRfsff\r\nMvK6tgT9BZ3kzjOxT5ou2SdvTa0eUk8k+zv8OnJJfXA=\r\n=LPeQ\r\n-----END PGP PUBLIC KEY BLOCK-----\r\n", + "public": "-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption\nComment: Seamlessly send and receive encrypted email\n\nxsBNBF8PcdUBCADi8no6T4Bd9Ny5COpbheBuPWEyDOedT2EVeaPrfutB1D8i\nCP6Rf1cUvs/qNUX/O7HQHFpgFuW2uOY4OU5cvcrwmNpOxT3pPt2cavxJMdJo\nfwEvloY3OfY7MCqdAj5VUcFGMhubfV810V2n5pf2FFUNTirksT6muhviMymy\nuWZLdh0F4WxrXEon7k3y2dZ3mI4xsG+Djttb6hj3gNr8/zNQQnTmVjB0mmpO\nFcGUQLTTTYMngvVMkz8/sh38trqkVGuf/M81gkbr1egnfKfGz/4NT3qQLjin\nnA8In2cSFS/MipIV14gTfHQAICFIMsWuW/xkaXUqygvAnyFa2nAQdgELABEB\nAAHNKDxhdXRvLnJlZnJlc2guZXhwaXJlZC5rZXlAcmVjaXBpZW50LmNvbT7C\nwJMEEAEIACYFAl8PcdUFCQAAAAEGCwkHCAMCBBUICgIEFgIBAAIZAQIbAwIe\nAQAhCRC+46QtmpyKyRYhBG0+CYZ1RO5ify6Sj77jpC2anIrJIvQIALG8TGMN\nYB4CRouMJawNCLui6Fx4Ba1ipPTaqlJPybLoe6z/WVZwAA9CmbjkCIk683pp\nmGQ3GXv7f8Sdk7DqhEhfZ7JtAK/Uw2VZqqIryNrrB0WV3EUHsENCOlq0YJod\nLqtkqgl83lCNDIkeoQwq4IyrgC8wsPgF7YMpxxQLONJvChZxSdCDjnfX3kvO\nZsLYFiKnNlX6wyrKAQxWnxxYhglMf0GDDyh0AJ+vOQHJ9m+oeBnA1tJ5AZU5\naQHvRtyWBKkYaEhljhyWr3eu1JjK4mn7/W6Rszveso33987wtIoQ66GpGcX2\nmh7y217y/uXz4D3X5PUEBXIbhvAPty71bnTOwE0EXw9x1QEIALdJgAsQ0Jnv\nLXwAKoOammWlUQmracK89v1Yc4mFnImtHDHS3pGsbx3DbNGuiz5BhXCdoPDf\ngMxlGmJgShy9JAhrhWFXkvsjW/7aO4bM1wU486VPKXb7Av/dcrfHH0ASj4zj\n/TYAeubNoxQtxHgyb13LVCW1kh4Oe6s0ac/hKtxogwEvNFY3x+4yfloHH0Ik\n9sbLGk0gS03bPABDHMpYk346406f5TuP6UDzb9M90i2cFxbq26svyBzBZ0vY\nzfMRuNsm6an0+B/wS6NLYBqsRyxwwCTdrhYS512yBzCHDYJJX0o3OJNe85/0\nTqEBO1prgkh3QMfw13/Oxq8PuMsyJpUAEQEAAcLAfAQYAQgADwUCXw9x1QUJ\nAAAAAQIbDAAhCRC+46QtmpyKyRYhBG0+CYZ1RO5ify6Sj77jpC2anIrJARgH\n/1KV7JBOS2ZEtO95FrLYnIqI45rRpvT1XArpBPrYLuHtDBwgMcmpiMhhKIZC\nFlZkR1W88ENdSkr8Nx81nW+f9JWRR6HuSyom7kOfS2Gdbfwo3bgp48DWr7K8\nKV/HHGuqLqd8UfPyDpsBGNx0w7tRo+8vqUbhskquLAIahYCbhEIE8zgy0fBV\nhXKFe1FjuFUoW29iEm0tZWX0k2PT5r1owEgDe0g/X1AXgSQyfPRFVDwE3QNJ\n1np/Rmygq1C+DIW2cohJOc7tO4gbl11XolsfQ+FU+HewYXy8aAEbrTSRfsff\nMvK6tgT9BZ3kzjOxT5ou2SdvTa0eUk8k+zv8OnJJfXA=\n=LPeQ\n-----END PGP PUBLIC KEY BLOCK-----\n", "users": [ "" ], @@ -391,8 +395,8 @@ ava.default('parseKeys - expiration and date last updated', async t => { } ], "algo": { - "algorithm": "rsa_encrypt_sign", - "bits": 2048, + "algorithm": "rsaEncryptSign", + "bits": 2047, "algorithmId": 1 }, "created": 1594847701, @@ -413,7 +417,7 @@ ava.default('parseKeys - revoked', async t => { "format": "armored", "keyDetails": [ { - "public": "-----BEGIN PGP PUBLIC KEY BLOCK-----\r\nVersion: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption\r\nComment: Seamlessly send and receive encrypted email\r\n\r\nxjMEYW8BThYJKwYBBAHaRw8BAQdAYtEoS4d+3cwQWXcs3lvMQueypexTYai7\r\nuXQmxqyOoKrCjAQgFgoAHQUCYW8CLBYhBDkxt0E9uy+mDO+Fzl8Vl4kQoXgK\r\nACEJEF8Vl4kQoXgKFiEEOTG3QT27L6YM74XOXxWXiRCheAqk5AEApn8X3Oe7\r\nEFgdfo5lkgh6ubpmgyRUpfYHkQE2/S6K+T0BAPGs2py515aUVAgiRy7bJuoY\r\nDKKbOPL1Npd0bgenKgMGzRVyZXZvZWtkQGZsb3djcnlwdC5jb23CXgQTFgoA\r\nBgUCYW8BawAKCRBfFZeJEKF4ChD/AP9gdm4riyAzyGhD4P8ZGW3GtREk56sW\r\nRBB3A/+RUX+qbAEA3FWCs2bUl6pmasXP8QAi0/zoruZiShR2Y2mVAM3T1ATN\r\nFXJldm9rZWRAZmxvd2NyeXB0LmNvbcJeBBMWCgAGBQJhbwFrAAoJEF8Vl4kQ\r\noXgKecoBALdrD8nkptLlT8Dg4cF+3swfY1urlbdEfEvIjN60HRDLAP4w3qeS\r\nzZ+OyuqPFaw7dM2KOu4++WigtbxRpDhpQ9U8BQ==\r\n=bMwq\r\n-----END PGP PUBLIC KEY BLOCK-----\r\n", + "public": "-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption\nComment: Seamlessly send and receive encrypted email\n\nxjMEYW8BThYJKwYBBAHaRw8BAQdAYtEoS4d+3cwQWXcs3lvMQueypexTYai7\nuXQmxqyOoKrCjAQgFgoAHQUCYW8CLBYhBDkxt0E9uy+mDO+Fzl8Vl4kQoXgK\nACEJEF8Vl4kQoXgKFiEEOTG3QT27L6YM74XOXxWXiRCheAqk5AEApn8X3Oe7\nEFgdfo5lkgh6ubpmgyRUpfYHkQE2/S6K+T0BAPGs2py515aUVAgiRy7bJuoY\nDKKbOPL1Npd0bgenKgMGzRVyZXZvZWtkQGZsb3djcnlwdC5jb23CXgQTFgoA\nBgUCYW8BawAKCRBfFZeJEKF4ChD/AP9gdm4riyAzyGhD4P8ZGW3GtREk56sW\nRBB3A/+RUX+qbAEA3FWCs2bUl6pmasXP8QAi0/zoruZiShR2Y2mVAM3T1ATN\nFXJldm9rZWRAZmxvd2NyeXB0LmNvbcJeBBMWCgAGBQJhbwFrAAoJEF8Vl4kQ\noXgKecoBALdrD8nkptLlT8Dg4cF+3swfY1urlbdEfEvIjN60HRDLAP4w3qeS\nzZ+OyuqPFaw7dM2KOu4++WigtbxRpDhpQ9U8BQ==\n=bMwq\n-----END PGP PUBLIC KEY BLOCK-----\n", "users": ["revoekd@flowcrypt.com", "revoked@flowcrypt.com"], "ids": [{ "fingerprint": "3931B7413DBB2FA60CEF85CE5F15978910A1780A", "longid": "5F15978910A1780A", "shortid": "10A1780A", "keywords": "GALLERY PROTECT TIME CANDY BLEAK ACCESS" }], "algo": { "algorithm": "eddsa", "curve": "ed25519", "algorithmId": 22 }, From ab5a5528d094cc5497a608aa8e19bdec062fb899 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 22:46:32 +0200 Subject: [PATCH 106/179] wip --- Core/source/test.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Core/source/test.ts b/Core/source/test.ts index 9915418fd..378e7a781 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -342,7 +342,7 @@ ava.default.only('parseKeys', async t => { "format": "armored", "keyDetails": [ { - "public": "-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption\nComment: Seamlessly send and receive encrypted email\n\nxsBNBFwBWOEBB/9uIqBYIPDQbBqHMvGXhgnm+b2i5rNLXrrGoalrp7wYQ654\nZln/+ffxzttRLRiwRQAOG0z78aMDXAHRfI9d3GaRKTkhTqVY+C02E8NxgB3+\nmbSsF0Ui+oh1//LT1ic6ZnISCA7Q2h2U/DSAPNxDZUMu9kjh9TjkKlR81fiA\nlxuD05ivRxCnmZnzqZtHoUvvCqsENgRjO9a5oWpMwtdItjdRFF7UFKYpfeA+\nct0uUNMRVdPK7MXBEr2FdWiKN1K21dQ1pWiAwj/5cTA8hu5Jue2RcF8FcPfs\nniRihQkNqtLDsfY5no1B3xeSnyO2SES1bAHw8ObXZn/C/6jxFztkn4NbABEB\nAAHNEFRlc3QgPHRAZXN0LmNvbT7CwH8EEAEIACkFAlwBWOEGCwkHCAMCCRA6\nMPTMCpqPEAQVCAoCAxYCAQIZAQIbAwIeAQAKCRA6MPTMCpqPENaTB/0faBFR\n2k3RM7P427HyZOsZtqEPxuynsLUqmsAAup6LtPhir4CAsb5DSvgYrzC8pbrf\njCaodoB7hMXc8RxTbSh+vQc5Su4QwY8sqy7hyMXOGGWsRxnuZ8t8BeEJBIHy\nPguXIR+wYvo1eveC+NMxHhTtjoSIn/E4vW0W9j5OlFeTK7HTNCuidIE0Hk2k\nXnEEoNO7ztxPPxsHz9g56uMhyAhf3mqKfvUFo/FLLRBOpxLO0kk64yAMcAHm\nc6ZI5Fz10y48+hHEv/RFOwfub9asF5NWHltanqyiZ+kHeoaieYJFc6t7Mt3j\ng8qxMKTUKAEeCfHt1UJCjp/aIgJRU4JRXgYXzsBNBFwBWOEBB/9nclmx98vf\noSpPUccBczvuZxmqk+jY6Id+vBhBFoEhtdTSpaw/JNstf0dTXN8RCFjB0lHt\na51llTjSobqcFwAU54/HKDOW3qMVbvadaGILpuCMCxdMgLWlpZdYY7BApv1N\n9zpN+iQ2tIrvnUQ312xKOXF/W83NUJ1nTObQYNpsUZLLG2N3kz11HuBS3E9F\ngEOYYy1tLT53hs5btqvQ5Jp4Iw5cBoBoTAmv+dPMDKYBroBPwuFeNRIokwLT\nrVcxrXajxlXaGXmmGS3PZ00HXq2g7vKIqWliMLLIWFl+LlVb6O8bMeXOT1l0\nXSO9GlLOSMDEc7pY26vkmAjbWv7iUWHNABEBAAHCwGkEGAEIABMFAlwBWOEJ\nEDow9MwKmo8QAhsMAAoJEDow9MwKmo8QjTcH/1pYXyXW/rpBrDg7w/dXJCfT\n8+RVYlhW3kqMxbid7EB8zgGVTDr3us/ki99hc2HjsKbxUqrGBxeh3Mmui7OD\nCI8XFeYl7lSDbgU6mZ5J4iXzdR8LNqIib4Horlx/Y24dOuvikSUNpDtFAYfa\nbZwxyKa/ihZT1rS1GO3V7tdAB9BJagJqVRssF5g5GBUAX3sxQ2p62HoUxPlJ\nOOr4AaCc1na92xScBJL8dtBBRQ5pUZWOjb2UHp9L5QdPaBX8T9ZAieOiTlSt\nQxoUfCk7RU0/TnsM3KqFnDFoCzkGxKAmU4LmGtP48qV+v2Jzvl+qcmqYuKtw\nH6FWd+EZH07MfdEIiTI=\n=wXbX\n-----END PGP PUBLIC KEY BLOCK-----\n", + "public": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nxsBNBFwBWOEBB/9uIqBYIPDQbBqHMvGXhgnm+b2i5rNLXrrGoalrp7wYQ654\nZln/+ffxzttRLRiwRQAOG0z78aMDXAHRfI9d3GaRKTkhTqVY+C02E8NxgB3+\nmbSsF0Ui+oh1//LT1ic6ZnISCA7Q2h2U/DSAPNxDZUMu9kjh9TjkKlR81fiA\nlxuD05ivRxCnmZnzqZtHoUvvCqsENgRjO9a5oWpMwtdItjdRFF7UFKYpfeA+\nct0uUNMRVdPK7MXBEr2FdWiKN1K21dQ1pWiAwj/5cTA8hu5Jue2RcF8FcPfs\nniRihQkNqtLDsfY5no1B3xeSnyO2SES1bAHw8ObXZn/C/6jxFztkn4NbABEB\nAAHNEFRlc3QgPHRAZXN0LmNvbT7CwH8EEAEIACkFAlwBWOEGCwkHCAMCCRA6\nMPTMCpqPEAQVCAoCAxYCAQIZAQIbAwIeAQAKCRA6MPTMCpqPENaTB/0faBFR\n2k3RM7P427HyZOsZtqEPxuynsLUqmsAAup6LtPhir4CAsb5DSvgYrzC8pbrf\njCaodoB7hMXc8RxTbSh+vQc5Su4QwY8sqy7hyMXOGGWsRxnuZ8t8BeEJBIHy\nPguXIR+wYvo1eveC+NMxHhTtjoSIn/E4vW0W9j5OlFeTK7HTNCuidIE0Hk2k\nXnEEoNO7ztxPPxsHz9g56uMhyAhf3mqKfvUFo/FLLRBOpxLO0kk64yAMcAHm\nc6ZI5Fz10y48+hHEv/RFOwfub9asF5NWHltanqyiZ+kHeoaieYJFc6t7Mt3j\ng8qxMKTUKAEeCfHt1UJCjp/aIgJRU4JRXgYXzsBNBFwBWOEBB/9nclmx98vf\noSpPUccBczvuZxmqk+jY6Id+vBhBFoEhtdTSpaw/JNstf0dTXN8RCFjB0lHt\na51llTjSobqcFwAU54/HKDOW3qMVbvadaGILpuCMCxdMgLWlpZdYY7BApv1N\n9zpN+iQ2tIrvnUQ312xKOXF/W83NUJ1nTObQYNpsUZLLG2N3kz11HuBS3E9F\ngEOYYy1tLT53hs5btqvQ5Jp4Iw5cBoBoTAmv+dPMDKYBroBPwuFeNRIokwLT\nrVcxrXajxlXaGXmmGS3PZ00HXq2g7vKIqWliMLLIWFl+LlVb6O8bMeXOT1l0\nXSO9GlLOSMDEc7pY26vkmAjbWv7iUWHNABEBAAHCwGkEGAEIABMFAlwBWOEJ\nEDow9MwKmo8QAhsMAAoJEDow9MwKmo8QjTcH/1pYXyXW/rpBrDg7w/dXJCfT\n8+RVYlhW3kqMxbid7EB8zgGVTDr3us/ki99hc2HjsKbxUqrGBxeh3Mmui7OD\nCI8XFeYl7lSDbgU6mZ5J4iXzdR8LNqIib4Horlx/Y24dOuvikSUNpDtFAYfa\nbZwxyKa/ihZT1rS1GO3V7tdAB9BJagJqVRssF5g5GBUAX3sxQ2p62HoUxPlJ\nOOr4AaCc1na92xScBJL8dtBBRQ5pUZWOjb2UHp9L5QdPaBX8T9ZAieOiTlSt\nQxoUfCk7RU0/TnsM3KqFnDFoCzkGxKAmU4LmGtP48qV+v2Jzvl+qcmqYuKtw\nH6FWd+EZH07MfdEIiTI=\n=wXbX\n-----END PGP PUBLIC KEY BLOCK-----\n", "users": [ "Test " ], @@ -364,6 +364,10 @@ ava.default.only('parseKeys', async t => { //expect(json).to.deep.equal(expected); expect(json.keyDetails[0].ids[0]).to.deep.equal(expected.keyDetails[0].ids[0]); expect(json.keyDetails[0].ids[1]).to.deep.equal(expected.keyDetails[0].ids[1]); + expect(json.keyDetails[0].algo).to.deep.equal(expected.keyDetails[0].algo); + expect(json.keyDetails[0].created).to.equal(expected.keyDetails[0].created); + expect(json.keyDetails[0].lastModified).to.equal(expected.keyDetails[0].lastModified); + expect(json.keyDetails[0].public).to.equal(expected.keyDetails[0].public); expect(json.keyDetails[0]).to.deep.equal(expected.keyDetails[0]); expectNoData(data); t.pass(); @@ -376,7 +380,7 @@ ava.default('parseKeys - expiration and date last updated', async t => { "format": "armored", "keyDetails": [ { - "public": "-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption\nComment: Seamlessly send and receive encrypted email\n\nxsBNBF8PcdUBCADi8no6T4Bd9Ny5COpbheBuPWEyDOedT2EVeaPrfutB1D8i\nCP6Rf1cUvs/qNUX/O7HQHFpgFuW2uOY4OU5cvcrwmNpOxT3pPt2cavxJMdJo\nfwEvloY3OfY7MCqdAj5VUcFGMhubfV810V2n5pf2FFUNTirksT6muhviMymy\nuWZLdh0F4WxrXEon7k3y2dZ3mI4xsG+Djttb6hj3gNr8/zNQQnTmVjB0mmpO\nFcGUQLTTTYMngvVMkz8/sh38trqkVGuf/M81gkbr1egnfKfGz/4NT3qQLjin\nnA8In2cSFS/MipIV14gTfHQAICFIMsWuW/xkaXUqygvAnyFa2nAQdgELABEB\nAAHNKDxhdXRvLnJlZnJlc2guZXhwaXJlZC5rZXlAcmVjaXBpZW50LmNvbT7C\nwJMEEAEIACYFAl8PcdUFCQAAAAEGCwkHCAMCBBUICgIEFgIBAAIZAQIbAwIe\nAQAhCRC+46QtmpyKyRYhBG0+CYZ1RO5ify6Sj77jpC2anIrJIvQIALG8TGMN\nYB4CRouMJawNCLui6Fx4Ba1ipPTaqlJPybLoe6z/WVZwAA9CmbjkCIk683pp\nmGQ3GXv7f8Sdk7DqhEhfZ7JtAK/Uw2VZqqIryNrrB0WV3EUHsENCOlq0YJod\nLqtkqgl83lCNDIkeoQwq4IyrgC8wsPgF7YMpxxQLONJvChZxSdCDjnfX3kvO\nZsLYFiKnNlX6wyrKAQxWnxxYhglMf0GDDyh0AJ+vOQHJ9m+oeBnA1tJ5AZU5\naQHvRtyWBKkYaEhljhyWr3eu1JjK4mn7/W6Rszveso33987wtIoQ66GpGcX2\nmh7y217y/uXz4D3X5PUEBXIbhvAPty71bnTOwE0EXw9x1QEIALdJgAsQ0Jnv\nLXwAKoOammWlUQmracK89v1Yc4mFnImtHDHS3pGsbx3DbNGuiz5BhXCdoPDf\ngMxlGmJgShy9JAhrhWFXkvsjW/7aO4bM1wU486VPKXb7Av/dcrfHH0ASj4zj\n/TYAeubNoxQtxHgyb13LVCW1kh4Oe6s0ac/hKtxogwEvNFY3x+4yfloHH0Ik\n9sbLGk0gS03bPABDHMpYk346406f5TuP6UDzb9M90i2cFxbq26svyBzBZ0vY\nzfMRuNsm6an0+B/wS6NLYBqsRyxwwCTdrhYS512yBzCHDYJJX0o3OJNe85/0\nTqEBO1prgkh3QMfw13/Oxq8PuMsyJpUAEQEAAcLAfAQYAQgADwUCXw9x1QUJ\nAAAAAQIbDAAhCRC+46QtmpyKyRYhBG0+CYZ1RO5ify6Sj77jpC2anIrJARgH\n/1KV7JBOS2ZEtO95FrLYnIqI45rRpvT1XArpBPrYLuHtDBwgMcmpiMhhKIZC\nFlZkR1W88ENdSkr8Nx81nW+f9JWRR6HuSyom7kOfS2Gdbfwo3bgp48DWr7K8\nKV/HHGuqLqd8UfPyDpsBGNx0w7tRo+8vqUbhskquLAIahYCbhEIE8zgy0fBV\nhXKFe1FjuFUoW29iEm0tZWX0k2PT5r1owEgDe0g/X1AXgSQyfPRFVDwE3QNJ\n1np/Rmygq1C+DIW2cohJOc7tO4gbl11XolsfQ+FU+HewYXy8aAEbrTSRfsff\nMvK6tgT9BZ3kzjOxT5ou2SdvTa0eUk8k+zv8OnJJfXA=\n=LPeQ\n-----END PGP PUBLIC KEY BLOCK-----\n", + "public": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nxsBNBF8PcdUBCADi8no6T4Bd9Ny5COpbheBuPWEyDOedT2EVeaPrfutB1D8i\nCP6Rf1cUvs/qNUX/O7HQHFpgFuW2uOY4OU5cvcrwmNpOxT3pPt2cavxJMdJo\nfwEvloY3OfY7MCqdAj5VUcFGMhubfV810V2n5pf2FFUNTirksT6muhviMymy\nuWZLdh0F4WxrXEon7k3y2dZ3mI4xsG+Djttb6hj3gNr8/zNQQnTmVjB0mmpO\nFcGUQLTTTYMngvVMkz8/sh38trqkVGuf/M81gkbr1egnfKfGz/4NT3qQLjin\nnA8In2cSFS/MipIV14gTfHQAICFIMsWuW/xkaXUqygvAnyFa2nAQdgELABEB\nAAHNKDxhdXRvLnJlZnJlc2guZXhwaXJlZC5rZXlAcmVjaXBpZW50LmNvbT7C\nwJMEEAEIACYFAl8PcdUFCQAAAAEGCwkHCAMCBBUICgIEFgIBAAIZAQIbAwIe\nAQAhCRC+46QtmpyKyRYhBG0+CYZ1RO5ify6Sj77jpC2anIrJIvQIALG8TGMN\nYB4CRouMJawNCLui6Fx4Ba1ipPTaqlJPybLoe6z/WVZwAA9CmbjkCIk683pp\nmGQ3GXv7f8Sdk7DqhEhfZ7JtAK/Uw2VZqqIryNrrB0WV3EUHsENCOlq0YJod\nLqtkqgl83lCNDIkeoQwq4IyrgC8wsPgF7YMpxxQLONJvChZxSdCDjnfX3kvO\nZsLYFiKnNlX6wyrKAQxWnxxYhglMf0GDDyh0AJ+vOQHJ9m+oeBnA1tJ5AZU5\naQHvRtyWBKkYaEhljhyWr3eu1JjK4mn7/W6Rszveso33987wtIoQ66GpGcX2\nmh7y217y/uXz4D3X5PUEBXIbhvAPty71bnTOwE0EXw9x1QEIALdJgAsQ0Jnv\nLXwAKoOammWlUQmracK89v1Yc4mFnImtHDHS3pGsbx3DbNGuiz5BhXCdoPDf\ngMxlGmJgShy9JAhrhWFXkvsjW/7aO4bM1wU486VPKXb7Av/dcrfHH0ASj4zj\n/TYAeubNoxQtxHgyb13LVCW1kh4Oe6s0ac/hKtxogwEvNFY3x+4yfloHH0Ik\n9sbLGk0gS03bPABDHMpYk346406f5TuP6UDzb9M90i2cFxbq26svyBzBZ0vY\nzfMRuNsm6an0+B/wS6NLYBqsRyxwwCTdrhYS512yBzCHDYJJX0o3OJNe85/0\nTqEBO1prgkh3QMfw13/Oxq8PuMsyJpUAEQEAAcLAfAQYAQgADwUCXw9x1QUJ\nAAAAAQIbDAAhCRC+46QtmpyKyRYhBG0+CYZ1RO5ify6Sj77jpC2anIrJARgH\n/1KV7JBOS2ZEtO95FrLYnIqI45rRpvT1XArpBPrYLuHtDBwgMcmpiMhhKIZC\nFlZkR1W88ENdSkr8Nx81nW+f9JWRR6HuSyom7kOfS2Gdbfwo3bgp48DWr7K8\nKV/HHGuqLqd8UfPyDpsBGNx0w7tRo+8vqUbhskquLAIahYCbhEIE8zgy0fBV\nhXKFe1FjuFUoW29iEm0tZWX0k2PT5r1owEgDe0g/X1AXgSQyfPRFVDwE3QNJ\n1np/Rmygq1C+DIW2cohJOc7tO4gbl11XolsfQ+FU+HewYXy8aAEbrTSRfsff\nMvK6tgT9BZ3kzjOxT5ou2SdvTa0eUk8k+zv8OnJJfXA=\n=LPeQ\n-----END PGP PUBLIC KEY BLOCK-----\n", "users": [ "" ], @@ -417,7 +421,7 @@ ava.default('parseKeys - revoked', async t => { "format": "armored", "keyDetails": [ { - "public": "-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption\nComment: Seamlessly send and receive encrypted email\n\nxjMEYW8BThYJKwYBBAHaRw8BAQdAYtEoS4d+3cwQWXcs3lvMQueypexTYai7\nuXQmxqyOoKrCjAQgFgoAHQUCYW8CLBYhBDkxt0E9uy+mDO+Fzl8Vl4kQoXgK\nACEJEF8Vl4kQoXgKFiEEOTG3QT27L6YM74XOXxWXiRCheAqk5AEApn8X3Oe7\nEFgdfo5lkgh6ubpmgyRUpfYHkQE2/S6K+T0BAPGs2py515aUVAgiRy7bJuoY\nDKKbOPL1Npd0bgenKgMGzRVyZXZvZWtkQGZsb3djcnlwdC5jb23CXgQTFgoA\nBgUCYW8BawAKCRBfFZeJEKF4ChD/AP9gdm4riyAzyGhD4P8ZGW3GtREk56sW\nRBB3A/+RUX+qbAEA3FWCs2bUl6pmasXP8QAi0/zoruZiShR2Y2mVAM3T1ATN\nFXJldm9rZWRAZmxvd2NyeXB0LmNvbcJeBBMWCgAGBQJhbwFrAAoJEF8Vl4kQ\noXgKecoBALdrD8nkptLlT8Dg4cF+3swfY1urlbdEfEvIjN60HRDLAP4w3qeS\nzZ+OyuqPFaw7dM2KOu4++WigtbxRpDhpQ9U8BQ==\n=bMwq\n-----END PGP PUBLIC KEY BLOCK-----\n", + "public": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nxjMEYW8BThYJKwYBBAHaRw8BAQdAYtEoS4d+3cwQWXcs3lvMQueypexTYai7\nuXQmxqyOoKrCjAQgFgoAHQUCYW8CLBYhBDkxt0E9uy+mDO+Fzl8Vl4kQoXgK\nACEJEF8Vl4kQoXgKFiEEOTG3QT27L6YM74XOXxWXiRCheAqk5AEApn8X3Oe7\nEFgdfo5lkgh6ubpmgyRUpfYHkQE2/S6K+T0BAPGs2py515aUVAgiRy7bJuoY\nDKKbOPL1Npd0bgenKgMGzRVyZXZvZWtkQGZsb3djcnlwdC5jb23CXgQTFgoA\nBgUCYW8BawAKCRBfFZeJEKF4ChD/AP9gdm4riyAzyGhD4P8ZGW3GtREk56sW\nRBB3A/+RUX+qbAEA3FWCs2bUl6pmasXP8QAi0/zoruZiShR2Y2mVAM3T1ATN\nFXJldm9rZWRAZmxvd2NyeXB0LmNvbcJeBBMWCgAGBQJhbwFrAAoJEF8Vl4kQ\noXgKecoBALdrD8nkptLlT8Dg4cF+3swfY1urlbdEfEvIjN60HRDLAP4w3qeS\nzZ+OyuqPFaw7dM2KOu4++WigtbxRpDhpQ9U8BQ==\n=bMwq\n-----END PGP PUBLIC KEY BLOCK-----\n", "users": ["revoekd@flowcrypt.com", "revoked@flowcrypt.com"], "ids": [{ "fingerprint": "3931B7413DBB2FA60CEF85CE5F15978910A1780A", "longid": "5F15978910A1780A", "shortid": "10A1780A", "keywords": "GALLERY PROTECT TIME CANDY BLEAK ACCESS" }], "algo": { "algorithm": "eddsa", "curve": "ed25519", "algorithmId": 22 }, From d7c078f54e69dbe01915022a9b1fc017179bda89 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 22:49:13 +0200 Subject: [PATCH 107/179] wip --- Core/source/test.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Core/source/test.ts b/Core/source/test.ts index 378e7a781..b62b01573 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -334,7 +334,7 @@ ava.default('isEmailValid - false', async t => { t.pass(); }); -ava.default.only('parseKeys', async t => { +ava.default('parseKeys', async t => { const { pubKeys: [pubkey] } = getKeypairs('rsa1'); console.log(pubkey); const { data, json } = parseResponse(await endpoints.parseKeys({}, [Buffer.from(pubkey)])); @@ -361,19 +361,19 @@ ava.default.only('parseKeys', async t => { } ] }; - //expect(json).to.deep.equal(expected); - expect(json.keyDetails[0].ids[0]).to.deep.equal(expected.keyDetails[0].ids[0]); - expect(json.keyDetails[0].ids[1]).to.deep.equal(expected.keyDetails[0].ids[1]); - expect(json.keyDetails[0].algo).to.deep.equal(expected.keyDetails[0].algo); - expect(json.keyDetails[0].created).to.equal(expected.keyDetails[0].created); - expect(json.keyDetails[0].lastModified).to.equal(expected.keyDetails[0].lastModified); - expect(json.keyDetails[0].public).to.equal(expected.keyDetails[0].public); - expect(json.keyDetails[0]).to.deep.equal(expected.keyDetails[0]); + // expect(json.keyDetails[0].ids[0]).to.deep.equal(expected.keyDetails[0].ids[0]); + // expect(json.keyDetails[0].ids[1]).to.deep.equal(expected.keyDetails[0].ids[1]); + // expect(json.keyDetails[0].algo).to.deep.equal(expected.keyDetails[0].algo); + // expect(json.keyDetails[0].created).to.equal(expected.keyDetails[0].created); + // expect(json.keyDetails[0].lastModified).to.equal(expected.keyDetails[0].lastModified); + // expect(json.keyDetails[0].public).to.equal(expected.keyDetails[0].public); + // expect(json.keyDetails[0]).to.deep.equal(expected.keyDetails[0]); + expect(json).to.deep.equal(expected); expectNoData(data); t.pass(); }); -ava.default('parseKeys - expiration and date last updated', async t => { +ava.default.only('parseKeys - expiration and date last updated', async t => { const { pubKeys: [pubkey] } = getKeypairs('expired'); const { data, json } = parseResponse(await endpoints.parseKeys({}, [Buffer.from(pubkey)])); expect(json).to.deep.equal({ From cf4653b7ecec3afb0fb5e9e4a3fe6d706900d348 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 23:00:06 +0200 Subject: [PATCH 108/179] wip --- Core/.save/openpgpv5/node/openpgp.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Core/.save/openpgpv5/node/openpgp.js b/Core/.save/openpgpv5/node/openpgp.js index ee8644e5f..bfa4b8c64 100644 --- a/Core/.save/openpgpv5/node/openpgp.js +++ b/Core/.save/openpgpv5/node/openpgp.js @@ -29,6 +29,7 @@ const doneWritingReject = Symbol('doneWritingReject'); const readingIndex = Symbol('readingIndex'); +// Based on https://stackoverflow.com/a/1997811/1540501 // inject oids (function() { if ( typeof Object.__oid == "undefined" ) { From 0a4d7b7d6be475587f1770355d10f818f863fc45 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 23:17:37 +0200 Subject: [PATCH 109/179] wip --- Core/source/test.ts | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/Core/source/test.ts b/Core/source/test.ts index b62b01573..11c1ffa03 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -361,22 +361,15 @@ ava.default('parseKeys', async t => { } ] }; - // expect(json.keyDetails[0].ids[0]).to.deep.equal(expected.keyDetails[0].ids[0]); - // expect(json.keyDetails[0].ids[1]).to.deep.equal(expected.keyDetails[0].ids[1]); - // expect(json.keyDetails[0].algo).to.deep.equal(expected.keyDetails[0].algo); - // expect(json.keyDetails[0].created).to.equal(expected.keyDetails[0].created); - // expect(json.keyDetails[0].lastModified).to.equal(expected.keyDetails[0].lastModified); - // expect(json.keyDetails[0].public).to.equal(expected.keyDetails[0].public); - // expect(json.keyDetails[0]).to.deep.equal(expected.keyDetails[0]); expect(json).to.deep.equal(expected); expectNoData(data); t.pass(); }); -ava.default.only('parseKeys - expiration and date last updated', async t => { +ava.default('parseKeys - expiration and date last updated', async t => { const { pubKeys: [pubkey] } = getKeypairs('expired'); const { data, json } = parseResponse(await endpoints.parseKeys({}, [Buffer.from(pubkey)])); - expect(json).to.deep.equal({ + const expected = { "format": "armored", "keyDetails": [ { @@ -400,7 +393,7 @@ ava.default.only('parseKeys - expiration and date last updated', async t => { ], "algo": { "algorithm": "rsaEncryptSign", - "bits": 2047, + "bits": 2048, "algorithmId": 1 }, "created": 1594847701, @@ -409,12 +402,20 @@ ava.default.only('parseKeys - expiration and date last updated', async t => { "revoked": false } ] - }); + }; + //expect(json.keyDetails[0].ids[0]).to.deep.equal(expected.keyDetails[0].ids[0]); + //expect(json.keyDetails[0].ids[1]).to.deep.equal(expected.keyDetails[0].ids[1]); + //expect(json.keyDetails[0].algo).to.deep.equal(expected.keyDetails[0].algo); + //expect(json.keyDetails[0].created).to.equal(expected.keyDetails[0].created); + //expect(json.keyDetails[0].lastModified).to.equal(expected.keyDetails[0].lastModified); + //expect(json.keyDetails[0].public).to.equal(expected.keyDetails[0].public); + //expect(json.keyDetails[0]).to.deep.equal(expected.keyDetails[0]); + expect(json).to.deep.equal(expected); expectNoData(data); t.pass(); }); -ava.default('parseKeys - revoked', async t => { +ava.default.only('parseKeys - revoked', async t => { const { pubKeys: [pubkey] } = getKeypairs('revoked'); const { data, json } = parseResponse(await endpoints.parseKeys({}, [Buffer.from(pubkey)])); expect(json).to.deep.equal({ From 319e74c690a612fd900beff104b3a0d2e286565c Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 23:19:57 +0200 Subject: [PATCH 110/179] wip --- Core/failed_tests.txt | 14 +++++++------- Core/source/test.ts | 7 ++++--- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Core/failed_tests.txt b/Core/failed_tests.txt index 8250b2a08..3c31fb232 100644 --- a/Core/failed_tests.txt +++ b/Core/failed_tests.txt @@ -1,7 +1,7 @@ -[parseKeys] Rejected promise returned by test -[parseKeys - expiration and date last updated] Rejected promise returned by test -[parseKeys - revoked] Rejected promise returned by test -[generateKey] Rejected promise returned by test -[encryptKey] Rejected promise returned by test -[parseDecryptMsg compat mime-email-plain-with-pubkey] Rejected promise returned by test -[verify plain-text signed message that you edited after signing. This invalidates the signature. With correct key. (fail: signature mismatch)] Rejected promise returned by test +[+] [parseKeys] Rejected promise returned by test +[+] [parseKeys - expiration and date last updated] Rejected promise returned by test +[+] [parseKeys - revoked] Rejected promise returned by test +[.] [generateKey] Rejected promise returned by test +[.] [encryptKey] Rejected promise returned by test +[.] [parseDecryptMsg compat mime-email-plain-with-pubkey] Rejected promise returned by test +[.] [verify plain-text signed message that you edited after signing. This invalidates the signature. With correct key. (fail: signature mismatch)] Rejected promise returned by test diff --git a/Core/source/test.ts b/Core/source/test.ts index 11c1ffa03..75f0d102a 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -415,10 +415,10 @@ ava.default('parseKeys - expiration and date last updated', async t => { t.pass(); }); -ava.default.only('parseKeys - revoked', async t => { +ava.default('parseKeys - revoked', async t => { const { pubKeys: [pubkey] } = getKeypairs('revoked'); const { data, json } = parseResponse(await endpoints.parseKeys({}, [Buffer.from(pubkey)])); - expect(json).to.deep.equal({ + const expected = { "format": "armored", "keyDetails": [ { @@ -431,7 +431,8 @@ ava.default.only('parseKeys - revoked', async t => { "revoked": true } ] - }); + }; + expect(json).to.deep.equal(expected); expectNoData(data); t.pass(); }); From 86cc85bc7133c1faa3400db8cae1c8183cafa430 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 23:33:02 +0200 Subject: [PATCH 111/179] wip --- Core/failed_tests.txt | 2 +- Core/source/test.ts | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Core/failed_tests.txt b/Core/failed_tests.txt index 3c31fb232..6396831ca 100644 --- a/Core/failed_tests.txt +++ b/Core/failed_tests.txt @@ -1,7 +1,7 @@ [+] [parseKeys] Rejected promise returned by test [+] [parseKeys - expiration and date last updated] Rejected promise returned by test [+] [parseKeys - revoked] Rejected promise returned by test -[.] [generateKey] Rejected promise returned by test +[+] [generateKey] Rejected promise returned by test [.] [encryptKey] Rejected promise returned by test [.] [parseDecryptMsg compat mime-email-plain-with-pubkey] Rejected promise returned by test [.] [verify plain-text signed message that you edited after signing. This invalidates the signature. With correct key. (fail: signature mismatch)] Rejected promise returned by test diff --git a/Core/source/test.ts b/Core/source/test.ts index 75f0d102a..2b2618638 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -37,8 +37,9 @@ ava.default('generateKey', async t => { const { json, data } = parseResponse(await endpoints.generateKey({ variant: 'curve25519', passphrase: 'riruekfhydekdmdbsyd', userIds: [{ email: 'a@b.com', name: 'Him' }] })); expect(json.key.private).to.contain('-----BEGIN PGP PRIVATE KEY BLOCK-----'); expect(json.key.public).to.contain('-----BEGIN PGP PUBLIC KEY BLOCK-----'); - expect(isFullyDecrypted(json.key)).to.be.true; - expect(isFullyDecrypted(json.key)).to.be.false; + const key = await readKey({armoredKey: json.key.private}); + expect(isFullyEncrypted(key)).to.be.true; + expect(isFullyDecrypted(key)).to.be.false; expect(json.key.algo).to.deep.equal({ algorithm: 'eddsa', curve: 'ed25519', algorithmId: 22 }); expectNoData(data); t.pass(); @@ -447,7 +448,7 @@ ava.default('decryptKey', async t => { t.pass(); }); -ava.default('encryptKey', async t => { +ava.default.only('encryptKey', async t => { const passphrase = 'this is some pass phrase'; const { decrypted: [decryptedKey] } = getKeypairs('rsa1'); const { data, json } = parseResponse(await endpoints.encryptKey({ armored: decryptedKey, passphrase })); From bc351c80708a1f4ada1ff83a0021e7aee48131b7 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 23:38:31 +0200 Subject: [PATCH 112/179] wip --- Core/failed_tests.txt | 4 ++-- Core/source/test.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Core/failed_tests.txt b/Core/failed_tests.txt index 6396831ca..9cc4f5739 100644 --- a/Core/failed_tests.txt +++ b/Core/failed_tests.txt @@ -2,6 +2,6 @@ [+] [parseKeys - expiration and date last updated] Rejected promise returned by test [+] [parseKeys - revoked] Rejected promise returned by test [+] [generateKey] Rejected promise returned by test -[.] [encryptKey] Rejected promise returned by test -[.] [parseDecryptMsg compat mime-email-plain-with-pubkey] Rejected promise returned by test +[+] [encryptKey] Rejected promise returned by test +[>>>] [parseDecryptMsg compat mime-email-plain-with-pubkey] Rejected promise returned by test [.] [verify plain-text signed message that you edited after signing. This invalidates the signature. With correct key. (fail: signature mismatch)] Rejected promise returned by test diff --git a/Core/source/test.ts b/Core/source/test.ts index 2b2618638..ba6b21047 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -448,7 +448,7 @@ ava.default('decryptKey', async t => { t.pass(); }); -ava.default.only('encryptKey', async t => { +ava.default('encryptKey', async t => { const passphrase = 'this is some pass phrase'; const { decrypted: [decryptedKey] } = getKeypairs('rsa1'); const { data, json } = parseResponse(await endpoints.encryptKey({ armored: decryptedKey, passphrase })); @@ -458,7 +458,7 @@ ava.default.only('encryptKey', async t => { expect(await decryptKey({ privateKey: (encryptedKey as PrivateKey), passphrase: passphrase - })).to.be.true + })).is.not.null; expectNoData(data); t.pass(); }); @@ -624,7 +624,7 @@ ava.default('parseDecryptMsg compat mime-email-plain-html', async t => { t.pass(); }); -ava.default('parseDecryptMsg compat mime-email-plain-with-pubkey', async t => { +ava.default.only('parseDecryptMsg compat mime-email-plain-with-pubkey', async t => { const { keys } = getKeypairs('rsa1'); const { data: blocks, json: decryptJson } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true }, [await getCompatAsset('mime-email-plain-with-pubkey')])); expectData(blocks, 'msgBlocks', [ From ef592ba67d5767dab884908475f640202ba20dba Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 23:43:41 +0200 Subject: [PATCH 113/179] wip --- Core/source/test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/source/test.ts b/Core/source/test.ts index ba6b21047..a634b24da 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -631,16 +631,16 @@ ava.default.only('parseDecryptMsg compat mime-email-plain-with-pubkey', async t { rendered: true, frameColor: 'plain', htmlContent }, { "type": "publicKey", - "content": "-----BEGIN PGP PUBLIC KEY BLOCK-----\r\nVersion: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption\r\nComment: Seamlessly send and receive encrypted email\r\n\r\nxsBNBFwBWOEBB/9uIqBYIPDQbBqHMvGXhgnm+b2i5rNLXrrGoalrp7wYQ654\r\nZln/+ffxzttRLRiwRQAOG0z78aMDXAHRfI9d3GaRKTkhTqVY+C02E8NxgB3+\r\nmbSsF0Ui+oh1//LT1ic6ZnISCA7Q2h2U/DSAPNxDZUMu9kjh9TjkKlR81fiA\r\nlxuD05ivRxCnmZnzqZtHoUvvCqsENgRjO9a5oWpMwtdItjdRFF7UFKYpfeA+\r\nct0uUNMRVdPK7MXBEr2FdWiKN1K21dQ1pWiAwj/5cTA8hu5Jue2RcF8FcPfs\r\nniRihQkNqtLDsfY5no1B3xeSnyO2SES1bAHw8ObXZn/C/6jxFztkn4NbABEB\r\nAAHNEFRlc3QgPHRAZXN0LmNvbT7CwH8EEAEIACkFAlwBWOEGCwkHCAMCCRA6\r\nMPTMCpqPEAQVCAoCAxYCAQIZAQIbAwIeAQAKCRA6MPTMCpqPENaTB/0faBFR\r\n2k3RM7P427HyZOsZtqEPxuynsLUqmsAAup6LtPhir4CAsb5DSvgYrzC8pbrf\r\njCaodoB7hMXc8RxTbSh+vQc5Su4QwY8sqy7hyMXOGGWsRxnuZ8t8BeEJBIHy\r\nPguXIR+wYvo1eveC+NMxHhTtjoSIn/E4vW0W9j5OlFeTK7HTNCuidIE0Hk2k\r\nXnEEoNO7ztxPPxsHz9g56uMhyAhf3mqKfvUFo/FLLRBOpxLO0kk64yAMcAHm\r\nc6ZI5Fz10y48+hHEv/RFOwfub9asF5NWHltanqyiZ+kHeoaieYJFc6t7Mt3j\r\ng8qxMKTUKAEeCfHt1UJCjp/aIgJRU4JRXgYXzsBNBFwBWOEBB/9nclmx98vf\r\noSpPUccBczvuZxmqk+jY6Id+vBhBFoEhtdTSpaw/JNstf0dTXN8RCFjB0lHt\r\na51llTjSobqcFwAU54/HKDOW3qMVbvadaGILpuCMCxdMgLWlpZdYY7BApv1N\r\n9zpN+iQ2tIrvnUQ312xKOXF/W83NUJ1nTObQYNpsUZLLG2N3kz11HuBS3E9F\r\ngEOYYy1tLT53hs5btqvQ5Jp4Iw5cBoBoTAmv+dPMDKYBroBPwuFeNRIokwLT\r\nrVcxrXajxlXaGXmmGS3PZ00HXq2g7vKIqWliMLLIWFl+LlVb6O8bMeXOT1l0\r\nXSO9GlLOSMDEc7pY26vkmAjbWv7iUWHNABEBAAHCwGkEGAEIABMFAlwBWOEJ\r\nEDow9MwKmo8QAhsMAAoJEDow9MwKmo8QjTcH/1pYXyXW/rpBrDg7w/dXJCfT\r\n8+RVYlhW3kqMxbid7EB8zgGVTDr3us/ki99hc2HjsKbxUqrGBxeh3Mmui7OD\r\nCI8XFeYl7lSDbgU6mZ5J4iXzdR8LNqIib4Horlx/Y24dOuvikSUNpDtFAYfa\r\nbZwxyKa/ihZT1rS1GO3V7tdAB9BJagJqVRssF5g5GBUAX3sxQ2p62HoUxPlJ\r\nOOr4AaCc1na92xScBJL8dtBBRQ5pUZWOjb2UHp9L5QdPaBX8T9ZAieOiTlSt\r\nQxoUfCk7RU0/TnsM3KqFnDFoCzkGxKAmU4LmGtP48qV+v2Jzvl+qcmqYuKtw\r\nH6FWd+EZH07MfdEIiTI=\r\n=wXbX\r\n-----END PGP PUBLIC KEY BLOCK-----\r\n", + "content": "-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption\nComment: Seamlessly send and receive encrypted email\n\nxsBNBFwBWOEBB/9uIqBYIPDQbBqHMvGXhgnm+b2i5rNLXrrGoalrp7wYQ654\nZln/+ffxzttRLRiwRQAOG0z78aMDXAHRfI9d3GaRKTkhTqVY+C02E8NxgB3+\nmbSsF0Ui+oh1//LT1ic6ZnISCA7Q2h2U/DSAPNxDZUMu9kjh9TjkKlR81fiA\nlxuD05ivRxCnmZnzqZtHoUvvCqsENgRjO9a5oWpMwtdItjdRFF7UFKYpfeA+\nct0uUNMRVdPK7MXBEr2FdWiKN1K21dQ1pWiAwj/5cTA8hu5Jue2RcF8FcPfs\nniRihQkNqtLDsfY5no1B3xeSnyO2SES1bAHw8ObXZn/C/6jxFztkn4NbABEB\nAAHNEFRlc3QgPHRAZXN0LmNvbT7CwH8EEAEIACkFAlwBWOEGCwkHCAMCCRA6\nMPTMCpqPEAQVCAoCAxYCAQIZAQIbAwIeAQAKCRA6MPTMCpqPENaTB/0faBFR\n2k3RM7P427HyZOsZtqEPxuynsLUqmsAAup6LtPhir4CAsb5DSvgYrzC8pbrf\njCaodoB7hMXc8RxTbSh+vQc5Su4QwY8sqy7hyMXOGGWsRxnuZ8t8BeEJBIHy\nPguXIR+wYvo1eveC+NMxHhTtjoSIn/E4vW0W9j5OlFeTK7HTNCuidIE0Hk2k\nXnEEoNO7ztxPPxsHz9g56uMhyAhf3mqKfvUFo/FLLRBOpxLO0kk64yAMcAHm\nc6ZI5Fz10y48+hHEv/RFOwfub9asF5NWHltanqyiZ+kHeoaieYJFc6t7Mt3j\ng8qxMKTUKAEeCfHt1UJCjp/aIgJRU4JRXgYXzsBNBFwBWOEBB/9nclmx98vf\noSpPUccBczvuZxmqk+jY6Id+vBhBFoEhtdTSpaw/JNstf0dTXN8RCFjB0lHt\na51llTjSobqcFwAU54/HKDOW3qMVbvadaGILpuCMCxdMgLWlpZdYY7BApv1N\n9zpN+iQ2tIrvnUQ312xKOXF/W83NUJ1nTObQYNpsUZLLG2N3kz11HuBS3E9F\ngEOYYy1tLT53hs5btqvQ5Jp4Iw5cBoBoTAmv+dPMDKYBroBPwuFeNRIokwLT\nrVcxrXajxlXaGXmmGS3PZ00HXq2g7vKIqWliMLLIWFl+LlVb6O8bMeXOT1l0\nXSO9GlLOSMDEc7pY26vkmAjbWv7iUWHNABEBAAHCwGkEGAEIABMFAlwBWOEJ\nEDow9MwKmo8QAhsMAAoJEDow9MwKmo8QjTcH/1pYXyXW/rpBrDg7w/dXJCfT\n8+RVYlhW3kqMxbid7EB8zgGVTDr3us/ki99hc2HjsKbxUqrGBxeh3Mmui7OD\nCI8XFeYl7lSDbgU6mZ5J4iXzdR8LNqIib4Horlx/Y24dOuvikSUNpDtFAYfa\nbZwxyKa/ihZT1rS1GO3V7tdAB9BJagJqVRssF5g5GBUAX3sxQ2p62HoUxPlJ\nOOr4AaCc1na92xScBJL8dtBBRQ5pUZWOjb2UHp9L5QdPaBX8T9ZAieOiTlSt\nQxoUfCk7RU0/TnsM3KqFnDFoCzkGxKAmU4LmGtP48qV+v2Jzvl+qcmqYuKtw\nH6FWd+EZH07MfdEIiTI=\n=wXbX\n-----END PGP PUBLIC KEY BLOCK-----\n", "complete": true, "keyDetails": { - "public": "-----BEGIN PGP PUBLIC KEY BLOCK-----\r\nVersion: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption\r\nComment: Seamlessly send and receive encrypted email\r\n\r\nxsBNBFwBWOEBB/9uIqBYIPDQbBqHMvGXhgnm+b2i5rNLXrrGoalrp7wYQ654\r\nZln/+ffxzttRLRiwRQAOG0z78aMDXAHRfI9d3GaRKTkhTqVY+C02E8NxgB3+\r\nmbSsF0Ui+oh1//LT1ic6ZnISCA7Q2h2U/DSAPNxDZUMu9kjh9TjkKlR81fiA\r\nlxuD05ivRxCnmZnzqZtHoUvvCqsENgRjO9a5oWpMwtdItjdRFF7UFKYpfeA+\r\nct0uUNMRVdPK7MXBEr2FdWiKN1K21dQ1pWiAwj/5cTA8hu5Jue2RcF8FcPfs\r\nniRihQkNqtLDsfY5no1B3xeSnyO2SES1bAHw8ObXZn/C/6jxFztkn4NbABEB\r\nAAHNEFRlc3QgPHRAZXN0LmNvbT7CwH8EEAEIACkFAlwBWOEGCwkHCAMCCRA6\r\nMPTMCpqPEAQVCAoCAxYCAQIZAQIbAwIeAQAKCRA6MPTMCpqPENaTB/0faBFR\r\n2k3RM7P427HyZOsZtqEPxuynsLUqmsAAup6LtPhir4CAsb5DSvgYrzC8pbrf\r\njCaodoB7hMXc8RxTbSh+vQc5Su4QwY8sqy7hyMXOGGWsRxnuZ8t8BeEJBIHy\r\nPguXIR+wYvo1eveC+NMxHhTtjoSIn/E4vW0W9j5OlFeTK7HTNCuidIE0Hk2k\r\nXnEEoNO7ztxPPxsHz9g56uMhyAhf3mqKfvUFo/FLLRBOpxLO0kk64yAMcAHm\r\nc6ZI5Fz10y48+hHEv/RFOwfub9asF5NWHltanqyiZ+kHeoaieYJFc6t7Mt3j\r\ng8qxMKTUKAEeCfHt1UJCjp/aIgJRU4JRXgYXzsBNBFwBWOEBB/9nclmx98vf\r\noSpPUccBczvuZxmqk+jY6Id+vBhBFoEhtdTSpaw/JNstf0dTXN8RCFjB0lHt\r\na51llTjSobqcFwAU54/HKDOW3qMVbvadaGILpuCMCxdMgLWlpZdYY7BApv1N\r\n9zpN+iQ2tIrvnUQ312xKOXF/W83NUJ1nTObQYNpsUZLLG2N3kz11HuBS3E9F\r\ngEOYYy1tLT53hs5btqvQ5Jp4Iw5cBoBoTAmv+dPMDKYBroBPwuFeNRIokwLT\r\nrVcxrXajxlXaGXmmGS3PZ00HXq2g7vKIqWliMLLIWFl+LlVb6O8bMeXOT1l0\r\nXSO9GlLOSMDEc7pY26vkmAjbWv7iUWHNABEBAAHCwGkEGAEIABMFAlwBWOEJ\r\nEDow9MwKmo8QAhsMAAoJEDow9MwKmo8QjTcH/1pYXyXW/rpBrDg7w/dXJCfT\r\n8+RVYlhW3kqMxbid7EB8zgGVTDr3us/ki99hc2HjsKbxUqrGBxeh3Mmui7OD\r\nCI8XFeYl7lSDbgU6mZ5J4iXzdR8LNqIib4Horlx/Y24dOuvikSUNpDtFAYfa\r\nbZwxyKa/ihZT1rS1GO3V7tdAB9BJagJqVRssF5g5GBUAX3sxQ2p62HoUxPlJ\r\nOOr4AaCc1na92xScBJL8dtBBRQ5pUZWOjb2UHp9L5QdPaBX8T9ZAieOiTlSt\r\nQxoUfCk7RU0/TnsM3KqFnDFoCzkGxKAmU4LmGtP48qV+v2Jzvl+qcmqYuKtw\r\nH6FWd+EZH07MfdEIiTI=\r\n=wXbX\r\n-----END PGP PUBLIC KEY BLOCK-----\r\n", + "public": "-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption\nComment: Seamlessly send and receive encrypted email\n\nxsBNBFwBWOEBB/9uIqBYIPDQbBqHMvGXhgnm+b2i5rNLXrrGoalrp7wYQ654\nZln/+ffxzttRLRiwRQAOG0z78aMDXAHRfI9d3GaRKTkhTqVY+C02E8NxgB3+\nmbSsF0Ui+oh1//LT1ic6ZnISCA7Q2h2U/DSAPNxDZUMu9kjh9TjkKlR81fiA\nlxuD05ivRxCnmZnzqZtHoUvvCqsENgRjO9a5oWpMwtdItjdRFF7UFKYpfeA+\nct0uUNMRVdPK7MXBEr2FdWiKN1K21dQ1pWiAwj/5cTA8hu5Jue2RcF8FcPfs\nniRihQkNqtLDsfY5no1B3xeSnyO2SES1bAHw8ObXZn/C/6jxFztkn4NbABEB\nAAHNEFRlc3QgPHRAZXN0LmNvbT7CwH8EEAEIACkFAlwBWOEGCwkHCAMCCRA6\nMPTMCpqPEAQVCAoCAxYCAQIZAQIbAwIeAQAKCRA6MPTMCpqPENaTB/0faBFR\n2k3RM7P427HyZOsZtqEPxuynsLUqmsAAup6LtPhir4CAsb5DSvgYrzC8pbrf\njCaodoB7hMXc8RxTbSh+vQc5Su4QwY8sqy7hyMXOGGWsRxnuZ8t8BeEJBIHy\nPguXIR+wYvo1eveC+NMxHhTtjoSIn/E4vW0W9j5OlFeTK7HTNCuidIE0Hk2k\nXnEEoNO7ztxPPxsHz9g56uMhyAhf3mqKfvUFo/FLLRBOpxLO0kk64yAMcAHm\nc6ZI5Fz10y48+hHEv/RFOwfub9asF5NWHltanqyiZ+kHeoaieYJFc6t7Mt3j\ng8qxMKTUKAEeCfHt1UJCjp/aIgJRU4JRXgYXzsBNBFwBWOEBB/9nclmx98vf\noSpPUccBczvuZxmqk+jY6Id+vBhBFoEhtdTSpaw/JNstf0dTXN8RCFjB0lHt\na51llTjSobqcFwAU54/HKDOW3qMVbvadaGILpuCMCxdMgLWlpZdYY7BApv1N\n9zpN+iQ2tIrvnUQ312xKOXF/W83NUJ1nTObQYNpsUZLLG2N3kz11HuBS3E9F\ngEOYYy1tLT53hs5btqvQ5Jp4Iw5cBoBoTAmv+dPMDKYBroBPwuFeNRIokwLT\nrVcxrXajxlXaGXmmGS3PZ00HXq2g7vKIqWliMLLIWFl+LlVb6O8bMeXOT1l0\nXSO9GlLOSMDEc7pY26vkmAjbWv7iUWHNABEBAAHCwGkEGAEIABMFAlwBWOEJ\nEDow9MwKmo8QAhsMAAoJEDow9MwKmo8QjTcH/1pYXyXW/rpBrDg7w/dXJCfT\n8+RVYlhW3kqMxbid7EB8zgGVTDr3us/ki99hc2HjsKbxUqrGBxeh3Mmui7OD\nCI8XFeYl7lSDbgU6mZ5J4iXzdR8LNqIib4Horlx/Y24dOuvikSUNpDtFAYfa\nbZwxyKa/ihZT1rS1GO3V7tdAB9BJagJqVRssF5g5GBUAX3sxQ2p62HoUxPlJ\nOOr4AaCc1na92xScBJL8dtBBRQ5pUZWOjb2UHp9L5QdPaBX8T9ZAieOiTlSt\nQxoUfCk7RU0/TnsM3KqFnDFoCzkGxKAmU4LmGtP48qV+v2Jzvl+qcmqYuKtw\nH6FWd+EZH07MfdEIiTI=\n=wXbX\n-----END PGP PUBLIC KEY BLOCK-----\n", "users": ["Test "], "ids": [ { "fingerprint": "E76853E128A0D376CAE47C143A30F4CC0A9A8F10", "longid": "3A30F4CC0A9A8F10", "shortid": "0A9A8F10", "keywords": "DEMAND MARBLE CREDIT BENEFIT POTTERY CAPITAL" }, { "fingerprint": "9EF2F8F36A841C0D5FAB8B0F0BAB9C018B265D22", "longid": "0BAB9C018B265D22", "shortid": "8B265D22", "keywords": "ARM FRIEND ABOUT BIND GRAPE CATTLE" } ], - "algo": { "algorithm": "rsa_encrypt_sign", "bits": 2048, "algorithmId": 1 }, + "algo": { "algorithm": "rsaEncryptSign", "bits": 2048, "algorithmId": 1 }, "created": 1543592161, "lastModified": 1543592161, "revoked": false From f83c068df2f9116b74574628af230b782487c53c Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Wed, 9 Feb 2022 23:45:38 +0200 Subject: [PATCH 114/179] wip --- Core/source/test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/source/test.ts b/Core/source/test.ts index a634b24da..09c0a234f 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -631,10 +631,10 @@ ava.default.only('parseDecryptMsg compat mime-email-plain-with-pubkey', async t { rendered: true, frameColor: 'plain', htmlContent }, { "type": "publicKey", - "content": "-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption\nComment: Seamlessly send and receive encrypted email\n\nxsBNBFwBWOEBB/9uIqBYIPDQbBqHMvGXhgnm+b2i5rNLXrrGoalrp7wYQ654\nZln/+ffxzttRLRiwRQAOG0z78aMDXAHRfI9d3GaRKTkhTqVY+C02E8NxgB3+\nmbSsF0Ui+oh1//LT1ic6ZnISCA7Q2h2U/DSAPNxDZUMu9kjh9TjkKlR81fiA\nlxuD05ivRxCnmZnzqZtHoUvvCqsENgRjO9a5oWpMwtdItjdRFF7UFKYpfeA+\nct0uUNMRVdPK7MXBEr2FdWiKN1K21dQ1pWiAwj/5cTA8hu5Jue2RcF8FcPfs\nniRihQkNqtLDsfY5no1B3xeSnyO2SES1bAHw8ObXZn/C/6jxFztkn4NbABEB\nAAHNEFRlc3QgPHRAZXN0LmNvbT7CwH8EEAEIACkFAlwBWOEGCwkHCAMCCRA6\nMPTMCpqPEAQVCAoCAxYCAQIZAQIbAwIeAQAKCRA6MPTMCpqPENaTB/0faBFR\n2k3RM7P427HyZOsZtqEPxuynsLUqmsAAup6LtPhir4CAsb5DSvgYrzC8pbrf\njCaodoB7hMXc8RxTbSh+vQc5Su4QwY8sqy7hyMXOGGWsRxnuZ8t8BeEJBIHy\nPguXIR+wYvo1eveC+NMxHhTtjoSIn/E4vW0W9j5OlFeTK7HTNCuidIE0Hk2k\nXnEEoNO7ztxPPxsHz9g56uMhyAhf3mqKfvUFo/FLLRBOpxLO0kk64yAMcAHm\nc6ZI5Fz10y48+hHEv/RFOwfub9asF5NWHltanqyiZ+kHeoaieYJFc6t7Mt3j\ng8qxMKTUKAEeCfHt1UJCjp/aIgJRU4JRXgYXzsBNBFwBWOEBB/9nclmx98vf\noSpPUccBczvuZxmqk+jY6Id+vBhBFoEhtdTSpaw/JNstf0dTXN8RCFjB0lHt\na51llTjSobqcFwAU54/HKDOW3qMVbvadaGILpuCMCxdMgLWlpZdYY7BApv1N\n9zpN+iQ2tIrvnUQ312xKOXF/W83NUJ1nTObQYNpsUZLLG2N3kz11HuBS3E9F\ngEOYYy1tLT53hs5btqvQ5Jp4Iw5cBoBoTAmv+dPMDKYBroBPwuFeNRIokwLT\nrVcxrXajxlXaGXmmGS3PZ00HXq2g7vKIqWliMLLIWFl+LlVb6O8bMeXOT1l0\nXSO9GlLOSMDEc7pY26vkmAjbWv7iUWHNABEBAAHCwGkEGAEIABMFAlwBWOEJ\nEDow9MwKmo8QAhsMAAoJEDow9MwKmo8QjTcH/1pYXyXW/rpBrDg7w/dXJCfT\n8+RVYlhW3kqMxbid7EB8zgGVTDr3us/ki99hc2HjsKbxUqrGBxeh3Mmui7OD\nCI8XFeYl7lSDbgU6mZ5J4iXzdR8LNqIib4Horlx/Y24dOuvikSUNpDtFAYfa\nbZwxyKa/ihZT1rS1GO3V7tdAB9BJagJqVRssF5g5GBUAX3sxQ2p62HoUxPlJ\nOOr4AaCc1na92xScBJL8dtBBRQ5pUZWOjb2UHp9L5QdPaBX8T9ZAieOiTlSt\nQxoUfCk7RU0/TnsM3KqFnDFoCzkGxKAmU4LmGtP48qV+v2Jzvl+qcmqYuKtw\nH6FWd+EZH07MfdEIiTI=\n=wXbX\n-----END PGP PUBLIC KEY BLOCK-----\n", + "content": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nxsBNBFwBWOEBB/9uIqBYIPDQbBqHMvGXhgnm+b2i5rNLXrrGoalrp7wYQ654\nZln/+ffxzttRLRiwRQAOG0z78aMDXAHRfI9d3GaRKTkhTqVY+C02E8NxgB3+\nmbSsF0Ui+oh1//LT1ic6ZnISCA7Q2h2U/DSAPNxDZUMu9kjh9TjkKlR81fiA\nlxuD05ivRxCnmZnzqZtHoUvvCqsENgRjO9a5oWpMwtdItjdRFF7UFKYpfeA+\nct0uUNMRVdPK7MXBEr2FdWiKN1K21dQ1pWiAwj/5cTA8hu5Jue2RcF8FcPfs\nniRihQkNqtLDsfY5no1B3xeSnyO2SES1bAHw8ObXZn/C/6jxFztkn4NbABEB\nAAHNEFRlc3QgPHRAZXN0LmNvbT7CwH8EEAEIACkFAlwBWOEGCwkHCAMCCRA6\nMPTMCpqPEAQVCAoCAxYCAQIZAQIbAwIeAQAKCRA6MPTMCpqPENaTB/0faBFR\n2k3RM7P427HyZOsZtqEPxuynsLUqmsAAup6LtPhir4CAsb5DSvgYrzC8pbrf\njCaodoB7hMXc8RxTbSh+vQc5Su4QwY8sqy7hyMXOGGWsRxnuZ8t8BeEJBIHy\nPguXIR+wYvo1eveC+NMxHhTtjoSIn/E4vW0W9j5OlFeTK7HTNCuidIE0Hk2k\nXnEEoNO7ztxPPxsHz9g56uMhyAhf3mqKfvUFo/FLLRBOpxLO0kk64yAMcAHm\nc6ZI5Fz10y48+hHEv/RFOwfub9asF5NWHltanqyiZ+kHeoaieYJFc6t7Mt3j\ng8qxMKTUKAEeCfHt1UJCjp/aIgJRU4JRXgYXzsBNBFwBWOEBB/9nclmx98vf\noSpPUccBczvuZxmqk+jY6Id+vBhBFoEhtdTSpaw/JNstf0dTXN8RCFjB0lHt\na51llTjSobqcFwAU54/HKDOW3qMVbvadaGILpuCMCxdMgLWlpZdYY7BApv1N\n9zpN+iQ2tIrvnUQ312xKOXF/W83NUJ1nTObQYNpsUZLLG2N3kz11HuBS3E9F\ngEOYYy1tLT53hs5btqvQ5Jp4Iw5cBoBoTAmv+dPMDKYBroBPwuFeNRIokwLT\nrVcxrXajxlXaGXmmGS3PZ00HXq2g7vKIqWliMLLIWFl+LlVb6O8bMeXOT1l0\nXSO9GlLOSMDEc7pY26vkmAjbWv7iUWHNABEBAAHCwGkEGAEIABMFAlwBWOEJ\nEDow9MwKmo8QAhsMAAoJEDow9MwKmo8QjTcH/1pYXyXW/rpBrDg7w/dXJCfT\n8+RVYlhW3kqMxbid7EB8zgGVTDr3us/ki99hc2HjsKbxUqrGBxeh3Mmui7OD\nCI8XFeYl7lSDbgU6mZ5J4iXzdR8LNqIib4Horlx/Y24dOuvikSUNpDtFAYfa\nbZwxyKa/ihZT1rS1GO3V7tdAB9BJagJqVRssF5g5GBUAX3sxQ2p62HoUxPlJ\nOOr4AaCc1na92xScBJL8dtBBRQ5pUZWOjb2UHp9L5QdPaBX8T9ZAieOiTlSt\nQxoUfCk7RU0/TnsM3KqFnDFoCzkGxKAmU4LmGtP48qV+v2Jzvl+qcmqYuKtw\nH6FWd+EZH07MfdEIiTI=\n=wXbX\n-----END PGP PUBLIC KEY BLOCK-----\n", "complete": true, "keyDetails": { - "public": "-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: FlowCrypt [BUILD_REPLACEABLE_VERSION] Gmail Encryption\nComment: Seamlessly send and receive encrypted email\n\nxsBNBFwBWOEBB/9uIqBYIPDQbBqHMvGXhgnm+b2i5rNLXrrGoalrp7wYQ654\nZln/+ffxzttRLRiwRQAOG0z78aMDXAHRfI9d3GaRKTkhTqVY+C02E8NxgB3+\nmbSsF0Ui+oh1//LT1ic6ZnISCA7Q2h2U/DSAPNxDZUMu9kjh9TjkKlR81fiA\nlxuD05ivRxCnmZnzqZtHoUvvCqsENgRjO9a5oWpMwtdItjdRFF7UFKYpfeA+\nct0uUNMRVdPK7MXBEr2FdWiKN1K21dQ1pWiAwj/5cTA8hu5Jue2RcF8FcPfs\nniRihQkNqtLDsfY5no1B3xeSnyO2SES1bAHw8ObXZn/C/6jxFztkn4NbABEB\nAAHNEFRlc3QgPHRAZXN0LmNvbT7CwH8EEAEIACkFAlwBWOEGCwkHCAMCCRA6\nMPTMCpqPEAQVCAoCAxYCAQIZAQIbAwIeAQAKCRA6MPTMCpqPENaTB/0faBFR\n2k3RM7P427HyZOsZtqEPxuynsLUqmsAAup6LtPhir4CAsb5DSvgYrzC8pbrf\njCaodoB7hMXc8RxTbSh+vQc5Su4QwY8sqy7hyMXOGGWsRxnuZ8t8BeEJBIHy\nPguXIR+wYvo1eveC+NMxHhTtjoSIn/E4vW0W9j5OlFeTK7HTNCuidIE0Hk2k\nXnEEoNO7ztxPPxsHz9g56uMhyAhf3mqKfvUFo/FLLRBOpxLO0kk64yAMcAHm\nc6ZI5Fz10y48+hHEv/RFOwfub9asF5NWHltanqyiZ+kHeoaieYJFc6t7Mt3j\ng8qxMKTUKAEeCfHt1UJCjp/aIgJRU4JRXgYXzsBNBFwBWOEBB/9nclmx98vf\noSpPUccBczvuZxmqk+jY6Id+vBhBFoEhtdTSpaw/JNstf0dTXN8RCFjB0lHt\na51llTjSobqcFwAU54/HKDOW3qMVbvadaGILpuCMCxdMgLWlpZdYY7BApv1N\n9zpN+iQ2tIrvnUQ312xKOXF/W83NUJ1nTObQYNpsUZLLG2N3kz11HuBS3E9F\ngEOYYy1tLT53hs5btqvQ5Jp4Iw5cBoBoTAmv+dPMDKYBroBPwuFeNRIokwLT\nrVcxrXajxlXaGXmmGS3PZ00HXq2g7vKIqWliMLLIWFl+LlVb6O8bMeXOT1l0\nXSO9GlLOSMDEc7pY26vkmAjbWv7iUWHNABEBAAHCwGkEGAEIABMFAlwBWOEJ\nEDow9MwKmo8QAhsMAAoJEDow9MwKmo8QjTcH/1pYXyXW/rpBrDg7w/dXJCfT\n8+RVYlhW3kqMxbid7EB8zgGVTDr3us/ki99hc2HjsKbxUqrGBxeh3Mmui7OD\nCI8XFeYl7lSDbgU6mZ5J4iXzdR8LNqIib4Horlx/Y24dOuvikSUNpDtFAYfa\nbZwxyKa/ihZT1rS1GO3V7tdAB9BJagJqVRssF5g5GBUAX3sxQ2p62HoUxPlJ\nOOr4AaCc1na92xScBJL8dtBBRQ5pUZWOjb2UHp9L5QdPaBX8T9ZAieOiTlSt\nQxoUfCk7RU0/TnsM3KqFnDFoCzkGxKAmU4LmGtP48qV+v2Jzvl+qcmqYuKtw\nH6FWd+EZH07MfdEIiTI=\n=wXbX\n-----END PGP PUBLIC KEY BLOCK-----\n", + "public": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nxsBNBFwBWOEBB/9uIqBYIPDQbBqHMvGXhgnm+b2i5rNLXrrGoalrp7wYQ654\nZln/+ffxzttRLRiwRQAOG0z78aMDXAHRfI9d3GaRKTkhTqVY+C02E8NxgB3+\nmbSsF0Ui+oh1//LT1ic6ZnISCA7Q2h2U/DSAPNxDZUMu9kjh9TjkKlR81fiA\nlxuD05ivRxCnmZnzqZtHoUvvCqsENgRjO9a5oWpMwtdItjdRFF7UFKYpfeA+\nct0uUNMRVdPK7MXBEr2FdWiKN1K21dQ1pWiAwj/5cTA8hu5Jue2RcF8FcPfs\nniRihQkNqtLDsfY5no1B3xeSnyO2SES1bAHw8ObXZn/C/6jxFztkn4NbABEB\nAAHNEFRlc3QgPHRAZXN0LmNvbT7CwH8EEAEIACkFAlwBWOEGCwkHCAMCCRA6\nMPTMCpqPEAQVCAoCAxYCAQIZAQIbAwIeAQAKCRA6MPTMCpqPENaTB/0faBFR\n2k3RM7P427HyZOsZtqEPxuynsLUqmsAAup6LtPhir4CAsb5DSvgYrzC8pbrf\njCaodoB7hMXc8RxTbSh+vQc5Su4QwY8sqy7hyMXOGGWsRxnuZ8t8BeEJBIHy\nPguXIR+wYvo1eveC+NMxHhTtjoSIn/E4vW0W9j5OlFeTK7HTNCuidIE0Hk2k\nXnEEoNO7ztxPPxsHz9g56uMhyAhf3mqKfvUFo/FLLRBOpxLO0kk64yAMcAHm\nc6ZI5Fz10y48+hHEv/RFOwfub9asF5NWHltanqyiZ+kHeoaieYJFc6t7Mt3j\ng8qxMKTUKAEeCfHt1UJCjp/aIgJRU4JRXgYXzsBNBFwBWOEBB/9nclmx98vf\noSpPUccBczvuZxmqk+jY6Id+vBhBFoEhtdTSpaw/JNstf0dTXN8RCFjB0lHt\na51llTjSobqcFwAU54/HKDOW3qMVbvadaGILpuCMCxdMgLWlpZdYY7BApv1N\n9zpN+iQ2tIrvnUQ312xKOXF/W83NUJ1nTObQYNpsUZLLG2N3kz11HuBS3E9F\ngEOYYy1tLT53hs5btqvQ5Jp4Iw5cBoBoTAmv+dPMDKYBroBPwuFeNRIokwLT\nrVcxrXajxlXaGXmmGS3PZ00HXq2g7vKIqWliMLLIWFl+LlVb6O8bMeXOT1l0\nXSO9GlLOSMDEc7pY26vkmAjbWv7iUWHNABEBAAHCwGkEGAEIABMFAlwBWOEJ\nEDow9MwKmo8QAhsMAAoJEDow9MwKmo8QjTcH/1pYXyXW/rpBrDg7w/dXJCfT\n8+RVYlhW3kqMxbid7EB8zgGVTDr3us/ki99hc2HjsKbxUqrGBxeh3Mmui7OD\nCI8XFeYl7lSDbgU6mZ5J4iXzdR8LNqIib4Horlx/Y24dOuvikSUNpDtFAYfa\nbZwxyKa/ihZT1rS1GO3V7tdAB9BJagJqVRssF5g5GBUAX3sxQ2p62HoUxPlJ\nOOr4AaCc1na92xScBJL8dtBBRQ5pUZWOjb2UHp9L5QdPaBX8T9ZAieOiTlSt\nQxoUfCk7RU0/TnsM3KqFnDFoCzkGxKAmU4LmGtP48qV+v2Jzvl+qcmqYuKtw\nH6FWd+EZH07MfdEIiTI=\n=wXbX\n-----END PGP PUBLIC KEY BLOCK-----\n", "users": ["Test "], "ids": [ { "fingerprint": "E76853E128A0D376CAE47C143A30F4CC0A9A8F10", "longid": "3A30F4CC0A9A8F10", "shortid": "0A9A8F10", "keywords": "DEMAND MARBLE CREDIT BENEFIT POTTERY CAPITAL" }, From 29933e3b9dc67513e6d4006775b67b5698dca59c Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 10 Feb 2022 00:11:57 +0200 Subject: [PATCH 115/179] wip --- Core/source/test.ts | 5 +++-- Core/source/test/test-utils.ts | 8 +++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Core/source/test.ts b/Core/source/test.ts index 09c0a234f..436fc421f 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -627,7 +627,7 @@ ava.default('parseDecryptMsg compat mime-email-plain-html', async t => { ava.default.only('parseDecryptMsg compat mime-email-plain-with-pubkey', async t => { const { keys } = getKeypairs('rsa1'); const { data: blocks, json: decryptJson } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true }, [await getCompatAsset('mime-email-plain-with-pubkey')])); - expectData(blocks, 'msgBlocks', [ + const expected = [ { rendered: true, frameColor: 'plain', htmlContent }, { "type": "publicKey", @@ -646,7 +646,8 @@ ava.default.only('parseDecryptMsg compat mime-email-plain-with-pubkey', async t "revoked": false } }, - ]); + ]; + expectData(blocks, 'msgBlocks', expected); expect(decryptJson).to.deep.equal({ text, replyType: 'plain', subject: 'mime email plain with pubkey' }); t.pass(); }); diff --git a/Core/source/test/test-utils.ts b/Core/source/test/test-utils.ts index 6ad4e10fa..458ca39f9 100644 --- a/Core/source/test/test-utils.ts +++ b/Core/source/test/test-utils.ts @@ -84,9 +84,11 @@ export const expectData = (_data: Uint8Array, type?: 'armoredMsg' | 'msgBlocks' } expect(blocks.length).to.equal(expectedBlocks.length); for (let i = 0; i < expectedBlocks.length; i++) { - // if (i === 0 && blocks[i].type === 'decryptedHtml') { - // } - expect(blocks[i]).to.deep.equal(expectedBlocks[i], `block ${i} failed cmp check`); + const a = blocks[i]; + const b = expectedBlocks[i]; + if (i == 1) { + } + expect(a).to.deep.equal(b, `block ${i} failed cmp check`); } } else if (type === "binary") { expect(details).to.be.instanceOf(Buffer); From 825ee29df3ecefa990b1ee539a672c921038189f Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 10 Feb 2022 00:58:47 +0200 Subject: [PATCH 116/179] wip --- Core/source/test/test-utils.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Core/source/test/test-utils.ts b/Core/source/test/test-utils.ts index 458ca39f9..9f5560272 100644 --- a/Core/source/test/test-utils.ts +++ b/Core/source/test/test-utils.ts @@ -86,8 +86,16 @@ export const expectData = (_data: Uint8Array, type?: 'armoredMsg' | 'msgBlocks' for (let i = 0; i < expectedBlocks.length; i++) { const a = blocks[i]; const b = expectedBlocks[i]; - if (i == 1) { - } + expect(a.type).to.be.equal(b.type); + expect(a.content).to.be.equal(b.content); + expect(a.complete).to.be.equal(b.complete); + expect(a.keyDetails.public).to.be.equal(b.keyDetails.public); + expect(a.keyDetails.algo).to.be.equal(b.keyDetails.algo); + expect(a.keyDetails.created).to.deep.equal(b.keyDetails.created); + expect(a.keyDetails.lastModified).to.be.equal(b.keyDetails.lastModified); + expect(a.keyDetails.revoked).to.deep.equal(b.keyDetails.revoked); + expect(a.keyDetails.ids).to.deep.equal(b.keyDetails.ids); + expect(a.keyDetails.users).to.deep.equal(b.keyDetails.users); expect(a).to.deep.equal(b, `block ${i} failed cmp check`); } } else if (type === "binary") { From 01c591f1aff4680542873b9a3d248b3fed452f16 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 10 Feb 2022 01:08:21 +0200 Subject: [PATCH 117/179] wip --- Core/failed_tests.txt | 4 ++-- Core/source/test.ts | 6 +++--- Core/source/test/test-utils.ts | 22 ++++++++++++---------- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/Core/failed_tests.txt b/Core/failed_tests.txt index 9cc4f5739..61474662a 100644 --- a/Core/failed_tests.txt +++ b/Core/failed_tests.txt @@ -3,5 +3,5 @@ [+] [parseKeys - revoked] Rejected promise returned by test [+] [generateKey] Rejected promise returned by test [+] [encryptKey] Rejected promise returned by test -[>>>] [parseDecryptMsg compat mime-email-plain-with-pubkey] Rejected promise returned by test -[.] [verify plain-text signed message that you edited after signing. This invalidates the signature. With correct key. (fail: signature mismatch)] Rejected promise returned by test +[+] [parseDecryptMsg compat mime-email-plain-with-pubkey] Rejected promise returned by test +[>>>] [verify plain-text signed message that you edited after signing. This invalidates the signature. With correct key. (fail: signature mismatch)] Rejected promise returned by test diff --git a/Core/source/test.ts b/Core/source/test.ts index 436fc421f..a3fd8913e 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -624,7 +624,7 @@ ava.default('parseDecryptMsg compat mime-email-plain-html', async t => { t.pass(); }); -ava.default.only('parseDecryptMsg compat mime-email-plain-with-pubkey', async t => { +ava.default('parseDecryptMsg compat mime-email-plain-with-pubkey', async t => { const { keys } = getKeypairs('rsa1'); const { data: blocks, json: decryptJson } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true }, [await getCompatAsset('mime-email-plain-with-pubkey')])); const expected = [ @@ -640,7 +640,7 @@ ava.default.only('parseDecryptMsg compat mime-email-plain-with-pubkey', async t { "fingerprint": "E76853E128A0D376CAE47C143A30F4CC0A9A8F10", "longid": "3A30F4CC0A9A8F10", "shortid": "0A9A8F10", "keywords": "DEMAND MARBLE CREDIT BENEFIT POTTERY CAPITAL" }, { "fingerprint": "9EF2F8F36A841C0D5FAB8B0F0BAB9C018B265D22", "longid": "0BAB9C018B265D22", "shortid": "8B265D22", "keywords": "ARM FRIEND ABOUT BIND GRAPE CATTLE" } ], - "algo": { "algorithm": "rsaEncryptSign", "bits": 2048, "algorithmId": 1 }, + "algo": { "algorithm": "rsaEncryptSign", "bits": 2047, "algorithmId": 1 }, "created": 1543592161, "lastModified": 1543592161, "revoked": false @@ -762,7 +762,7 @@ ava.default('verify plain-text signed message by providing it wrong key (fail: c t.pass(); }); -ava.default('verify plain-text signed message that you edited after signing. This invalidates the signature. With correct key. (fail: signature mismatch)', async t => { +ava.default.only('verify plain-text signed message that you edited after signing. This invalidates the signature. With correct key. (fail: signature mismatch)', async t => { const { keys, pubKeys } = getKeypairs('rsa1'); const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-plain-signed-edited')])); expect(decryptJson.replyType).equals('plain'); diff --git a/Core/source/test/test-utils.ts b/Core/source/test/test-utils.ts index 9f5560272..33983a969 100644 --- a/Core/source/test/test-utils.ts +++ b/Core/source/test/test-utils.ts @@ -86,16 +86,18 @@ export const expectData = (_data: Uint8Array, type?: 'armoredMsg' | 'msgBlocks' for (let i = 0; i < expectedBlocks.length; i++) { const a = blocks[i]; const b = expectedBlocks[i]; - expect(a.type).to.be.equal(b.type); - expect(a.content).to.be.equal(b.content); - expect(a.complete).to.be.equal(b.complete); - expect(a.keyDetails.public).to.be.equal(b.keyDetails.public); - expect(a.keyDetails.algo).to.be.equal(b.keyDetails.algo); - expect(a.keyDetails.created).to.deep.equal(b.keyDetails.created); - expect(a.keyDetails.lastModified).to.be.equal(b.keyDetails.lastModified); - expect(a.keyDetails.revoked).to.deep.equal(b.keyDetails.revoked); - expect(a.keyDetails.ids).to.deep.equal(b.keyDetails.ids); - expect(a.keyDetails.users).to.deep.equal(b.keyDetails.users); + //if (i == 1) { + // expect(a.type).to.be.equal(b.type); + // expect(a.content).to.be.equal(b.content); + // expect(a.complete).to.be.equal(b.complete); + // expect(a.keyDetails.public).to.be.equal(b.keyDetails.public); + // expect(a.keyDetails.algo).to.deep.equal(b.keyDetails.algo); + // expect(a.keyDetails.created).to.deep.equal(b.keyDetails.created); + // expect(a.keyDetails.lastModified).to.be.equal(b.keyDetails.lastModified); + // expect(a.keyDetails.revoked).to.deep.equal(b.keyDetails.revoked); + // expect(a.keyDetails.ids).to.deep.equal(b.keyDetails.ids); + // expect(a.keyDetails.users).to.deep.equal(b.keyDetails.users); + //} expect(a).to.deep.equal(b, `block ${i} failed cmp check`); } } else if (type === "binary") { From b7d1a32ca55c7ba2895414f12bd146011a4f40fe Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 10 Feb 2022 01:13:25 +0200 Subject: [PATCH 118/179] wip --- Core/source/test.ts | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/Core/source/test.ts b/Core/source/test.ts index a3fd8913e..c7e3da97d 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -741,7 +741,9 @@ ava.default('verify plain-text signed message by providing it both correct and i const allPubKeys = []; for (const pubkey of pubKeys2) allPubKeys.push(pubkey); for (const pubkey of pubKeys) allPubKeys.push(pubkey); - const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-plain-signed')])); + const { json: decryptJson, data: decryptData } = parseResponse( + await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, + [await getCompatAsset('mime-email-plain-signed')])); expect(decryptJson.replyType).equals('plain'); expect(decryptJson.subject).equals('mime email plain signed'); const parsedDecryptData = JSON.parse(decryptData.toString()); @@ -753,7 +755,9 @@ ava.default('verify plain-text signed message by providing it both correct and i ava.default('verify plain-text signed message by providing it wrong key (fail: cannot verify)', async t => { const { keys } = getKeypairs('rsa1'); const { pubKeys: pubKeys2 } = getKeypairs('rsa2'); - const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys2 }, [await getCompatAsset('mime-email-plain-signed')])); + const { json: decryptJson, data: decryptData } = parseResponse( + await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys2 }, + [await getCompatAsset('mime-email-plain-signed')])); expect(decryptJson.replyType).equals('plain'); expect(decryptJson.subject).equals('mime email plain signed'); const parsedDecryptData = JSON.parse(decryptData.toString()); @@ -763,19 +767,28 @@ ava.default('verify plain-text signed message by providing it wrong key (fail: c }); ava.default.only('verify plain-text signed message that you edited after signing. This invalidates the signature. With correct key. (fail: signature mismatch)', async t => { + console.log(">>> 1"); const { keys, pubKeys } = getKeypairs('rsa1'); - const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-plain-signed-edited')])); + console.log(">>> 2"); + const { json: decryptJson, data: decryptData } = parseResponse( + await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, + [await getCompatAsset('mime-email-plain-signed-edited')])); + console.log(">>> 3"); expect(decryptJson.replyType).equals('plain'); expect(decryptJson.subject).equals('mime email plain signed'); + console.log(">>> 4"); const parsedDecryptData = JSON.parse(decryptData.toString()); expect(!!parsedDecryptData.verifyRes).equals(true); expect(parsedDecryptData.verifyRes.match).equals(false); + console.log(">>> 5"); t.pass(); }); ava.default('verify signed message with detached signature by providing it correct key', async t => { const { keys, pubKeys } = getKeypairs('rsa1'); - const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-plain-signed-detached')])); + const { json: decryptJson, data: decryptData } = parseResponse( + await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, + [await getCompatAsset('mime-email-plain-signed-detached')])); expect(decryptJson.replyType).equals('plain'); expect(decryptJson.subject).equals('mime email plain signed detached'); const parsedDecryptData = JSON.parse(decryptData.toString()); @@ -786,7 +799,9 @@ ava.default('verify signed message with detached signature by providing it corre ava.default('decryptErr for not integrity protected message', async t => { const { keys, pubKeys } = getKeypairs('flowcrypt.compatibility'); - const { json: decryptJson, data: decryptData } = parseResponse(await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-not-integrity-protected')])); + const { json: decryptJson, data: decryptData } = parseResponse( + await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, + [await getCompatAsset('mime-email-not-integrity-protected')])); expect(decryptJson.replyType).equals('plain'); expect(decryptJson.subject).equals('not integrity protected - should show a warning and not decrypt automatically'); const blocks = decryptData.toString().split('\n').map(block => JSON.parse(block)); From 8f0c94849b8bc3e209abe2ce85dd5df80ed6d61c Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 10 Feb 2022 01:16:28 +0200 Subject: [PATCH 119/179] wip --- Core/source/test.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Core/source/test.ts b/Core/source/test.ts index c7e3da97d..8290eaafb 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -767,18 +767,16 @@ ava.default('verify plain-text signed message by providing it wrong key (fail: c }); ava.default.only('verify plain-text signed message that you edited after signing. This invalidates the signature. With correct key. (fail: signature mismatch)', async t => { - console.log(">>> 1"); const { keys, pubKeys } = getKeypairs('rsa1'); - console.log(">>> 2"); const { json: decryptJson, data: decryptData } = parseResponse( await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, [await getCompatAsset('mime-email-plain-signed-edited')])); - console.log(">>> 3"); expect(decryptJson.replyType).equals('plain'); expect(decryptJson.subject).equals('mime email plain signed'); - console.log(">>> 4"); const parsedDecryptData = JSON.parse(decryptData.toString()); expect(!!parsedDecryptData.verifyRes).equals(true); + console.log(">>> 4"); + console.log(parsedDecryptData.verifyRes.match); expect(parsedDecryptData.verifyRes.match).equals(false); console.log(">>> 5"); t.pass(); From e77aee9c99c73fcf2dc6c2cb235bcfc72c8d47a2 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 10 Feb 2022 01:19:40 +0200 Subject: [PATCH 120/179] wip --- Core/source/test.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Core/source/test.ts b/Core/source/test.ts index 8290eaafb..b64e2786a 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -766,7 +766,7 @@ ava.default('verify plain-text signed message by providing it wrong key (fail: c t.pass(); }); -ava.default.only('verify plain-text signed message that you edited after signing. This invalidates the signature. With correct key. (fail: signature mismatch)', async t => { +ava.default('verify plain-text signed message that you edited after signing. This invalidates the signature. With correct key. (fail: signature mismatch)', async t => { const { keys, pubKeys } = getKeypairs('rsa1'); const { json: decryptJson, data: decryptData } = parseResponse( await endpoints.parseDecryptMsg({ keys, isEmail: true, verificationPubkeys: pubKeys }, @@ -775,10 +775,7 @@ ava.default.only('verify plain-text signed message that you edited after signing expect(decryptJson.subject).equals('mime email plain signed'); const parsedDecryptData = JSON.parse(decryptData.toString()); expect(!!parsedDecryptData.verifyRes).equals(true); - console.log(">>> 4"); - console.log(parsedDecryptData.verifyRes.match); - expect(parsedDecryptData.verifyRes.match).equals(false); - console.log(">>> 5"); + expect(parsedDecryptData.verifyRes.match).is.null; t.pass(); }); From 9b1b0554a6efd7f3a05558cccdb5bc8fd035297b Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 10 Feb 2022 01:21:06 +0200 Subject: [PATCH 121/179] wip --- Core/source/core/pgp-key.ts | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index 78a9e999e..42ddf2bf3 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -356,31 +356,15 @@ export class PgpKey { * This is used to figure out how recently was key updated, and if one key is newer than other. */ public static lastSig = async (key: Key): Promise => { - let i = 0; - console.log(`Key OUID ${(Object as any).__oid(key)}`); await key.getExpirationTime(); // will force all sigs to be verified const allSignatures: SignaturePacket[] = []; for (const user of key.users) { - i = 0; - for (const sig of user.selfCertifications) { - console.log(`user ${user.userID?.email} sig[${i++}](OUID ${(Object as any).__oid(sig)} => ${sig.verified})\n`); - } allSignatures.push(...user.selfCertifications); } - i = 0; for (const subKey of key.subkeys) { - i = 0; - for (const sig of subKey.bindingSignatures) { - console.log(`subkey ${subKey.getKeyID().toHex()} sig[${i++}](OUID ${(Object as any).__oid(sig)} => ${sig.verified})}\n`); - } allSignatures.push(...subKey.bindingSignatures); } allSignatures.sort((a, b) => (b.created ? b.created.getTime() : 0) - (a.created ? a.created.getTime() : 0)); - console.log(`nsig=${allSignatures.length}`); - i = 0; - for (const sig of allSignatures) { - console.log(`sig[${i++}](OUID ${(Object as any).__oid(sig)} => ${sig.verified})}\n`); - } const newestSig = allSignatures.find(sig => sig.verified === true); if (newestSig) { return newestSig.created ? newestSig.created.getTime() : 0; From a51b9e3448df4398257800819d76fa927513febf Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 10 Feb 2022 01:29:19 +0200 Subject: [PATCH 122/179] wip --- Core/tooling/build.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Core/tooling/build.sh b/Core/tooling/build.sh index 83c6ce64e..9cefd8c4c 100755 --- a/Core/tooling/build.sh +++ b/Core/tooling/build.sh @@ -7,8 +7,12 @@ for f in openpgp.min.js openpgp.min.js.map openpgp.min.mjs openpgp.min.mjs.map o if [ -f node_modules/openpgp/dist/$f ]; then rm -f node_modules/openpgp/dist/$f ; fi if [ -f node_modules/openpgp/dist/node/$f ]; then rm -f node_modules/openpgp/dist/node/$f ; fi done -sed -i 's/openpgp.min.js/openpgp.js/g' node_modules/openpgp/package.json -sed -i 's/openpgp.min.mjs/openpgp.mjs/g' node_modules/openpgp/package.json + +# MacOS/BSD sed doesn't have "-i" (see https://ss64.com/osx/sed.html) +sed 's/openpgp.min.js/openpgp.js/g' node_modules/openpgp/package.json >node_modules/openpgp/package.json.tmp +cp -f node_modules/openpgp/package.json.tmp node_modules/openpgp/package.json +sed 's/openpgp.min.mjs/openpgp.mjs/g' node_modules/openpgp/package.json >node_modules/openpgp/package.json.tmp +cp -f node_modules/openpgp/package.json.tmp node_modules/openpgp/package.json extra_exports=" // -----BEGIN ADDED BY FLOWCRYPT---- From 964e637ba25b165a6bfabf6b7d27c877ba7a7d9d Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 10 Feb 2022 01:34:33 +0200 Subject: [PATCH 123/179] fix build script --- Core/tooling/build.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/tooling/build.sh b/Core/tooling/build.sh index 9cefd8c4c..9205760de 100755 --- a/Core/tooling/build.sh +++ b/Core/tooling/build.sh @@ -73,13 +73,13 @@ export class Sha256 extends Hash {} " dist_ts=node_modules/openpgp/openpgp.d.ts -tmp_ts=${dist_js}.tmp +tmp_ts=${dist_ts}.tmp set +e fc_added=$(grep 'BEGIN ADDED BY FLOWCRYPT' ${dist_ts} | wc -l) set -e if [ $fc_added = 0 ]; then cp -f ${dist_ts} ${tmp_ts} - echo "$extra_defs" >>${tmp_ts} + echo "${extra_defs}" >>${tmp_ts} mv -f ${tmp_ts} ${dist_ts} fi From a4fa1e3bdd71d4322bc351a8df9fac6e6d9854df Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 10 Feb 2022 01:42:10 +0200 Subject: [PATCH 124/179] wip --- Core/tooling/build.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Core/tooling/build.sh b/Core/tooling/build.sh index 9205760de..04e6d50f8 100755 --- a/Core/tooling/build.sh +++ b/Core/tooling/build.sh @@ -8,7 +8,7 @@ for f in openpgp.min.js openpgp.min.js.map openpgp.min.mjs openpgp.min.mjs.map o if [ -f node_modules/openpgp/dist/node/$f ]; then rm -f node_modules/openpgp/dist/node/$f ; fi done -# MacOS/BSD sed doesn't have "-i" (see https://ss64.com/osx/sed.html) +# MacOS sed is old BSD sed w/o "-i" (see https://ss64.com/osx/sed.html) sed 's/openpgp.min.js/openpgp.js/g' node_modules/openpgp/package.json >node_modules/openpgp/package.json.tmp cp -f node_modules/openpgp/package.json.tmp node_modules/openpgp/package.json sed 's/openpgp.min.mjs/openpgp.mjs/g' node_modules/openpgp/package.json >node_modules/openpgp/package.json.tmp @@ -80,7 +80,9 @@ set -e if [ $fc_added = 0 ]; then cp -f ${dist_ts} ${tmp_ts} echo "${extra_defs}" >>${tmp_ts} - mv -f ${tmp_ts} ${dist_ts} + # MacOS sed MacOS sed is old BSD sed w/o "-i" (see https://ss64.com/osx/sed.html) + sed 's/public isRevoked(signature: SignaturePacket/public isRevoked(signature?: SignaturePacket/g' ${tmp_ts} >${tmp_ts}.tmp + mv -f ${tmp_ts}.tmp ${dist_ts} fi # clean up From 27aa8efaf1d08bc1bfd2420376b26faab8d6684b Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 10 Feb 2022 01:55:33 +0200 Subject: [PATCH 125/179] wip --- Core/.save/openpgpv4/openpgpv4.d.ts | 1131 - Core/.save/openpgpv4/openpgpv4.js | 42866 ---------------- .../lib/openpgpjs-v5/dist}/node/openpgp.js | 10 +- .../lib/openpgpjs-v5/dist}/openpgp.js | 6 +- Core/source/lib/openpgpjs-v5/openpgp.d.ts | 911 + Core/tooling/build.sh | 79 +- 6 files changed, 921 insertions(+), 44082 deletions(-) delete mode 100644 Core/.save/openpgpv4/openpgpv4.d.ts delete mode 100644 Core/.save/openpgpv4/openpgpv4.js rename Core/{.save/openpgpv5 => source/lib/openpgpjs-v5/dist}/node/openpgp.js (99%) rename Core/{.save/openpgpv5 => source/lib/openpgpjs-v5/dist}/openpgp.js (99%) create mode 100644 Core/source/lib/openpgpjs-v5/openpgp.d.ts diff --git a/Core/.save/openpgpv4/openpgpv4.d.ts b/Core/.save/openpgpv4/openpgpv4.d.ts deleted file mode 100644 index d7d13a319..000000000 --- a/Core/.save/openpgpv4/openpgpv4.d.ts +++ /dev/null @@ -1,1131 +0,0 @@ -// Type definitions for openpgpjs -// Project: http://openpgpjs.org/ -// Definitions by: Guillaume Lacasa -// Errietta Kostala -// FlowCrypt Limited -// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped - -/* tslint:disable:only-arrow-functions variable-name max-line-length no-null-keyword ban-types */ - -declare namespace OpenPGP { - - type DataPacketType = 'utf8' | 'binary' | 'text' | 'mime'; - - export interface UserId { - name?: string; - email?: string; - } - - export interface SessionKey { - data: Uint8Array; - algorithm: string; - } - - interface BaseStream { } - interface WebStream extends BaseStream { // copied+simplified version of ReadableStream from lib.dom.d.ts - readonly locked: boolean; cancel(reason?: any): Promise; getReader: Function; pipeThrough: Function; pipeTo: Function; tee: Function; - } - interface NodeStream extends BaseStream { // copied+simplified version of ReadableStream from @types/node/index.d.ts - readable: boolean; read(size?: number): string | Uint8Array; setEncoding(encoding: string): this; pause(): this; resume(): this; - isPaused(): boolean; pipe: Function; unpipe: Function; unshift(chunk: string | Uint8Array): void; wrap: Function; - } - type Stream = WebStream | NodeStream; - - /** - * EncryptArmorOptions or EncryptBinaryOptions will be used based on armor option (boolean), defaults to armoring - */ - interface BaseEncryptOptions { - /** message to be encrypted as created by openpgp.message.fromText or openpgp.message.fromBinary */ - message: message.Message; - /** (optional) array of keys or single key, used to encrypt the message */ - publicKeys?: key.Key | key.Key[]; - /** (optional) private keys for signing. If omitted message will not be signed */ - privateKeys?: key.Key | key.Key[]; - /** (optional) array of passwords or a single password to encrypt the message */ - passwords?: string | string[]; - /** (optional) session key in the form: { data:Uint8Array, algorithm:String } */ - sessionKey?: SessionKey; - /** (optional) which compression algorithm to compress the message with, defaults to what is specified in config */ - compression?: enums.compression; - /** (optional) whether to return data as a stream. Defaults to the type of stream `message` was created from, if any. */ - streaming?: 'web' | 'node' | false; - /** (optional) if the signature should be detached (if true, signature will be added to returned object) */ - detached?: boolean; - /** (optional) a detached signature to add to the encrypted message */ - signature?: signature.Signature; - /** (optional) if the unencrypted session key should be added to returned object */ - returnSessionKey?: boolean; - /** (optional) encrypt as of a certain date */ - date?: Date; - /** (optional) use a key ID of 0 instead of the public key IDs */ - wildcard?: boolean; - /** (optional) user ID to sign with, e.g. { name:'Steve Sender', email:'steve@openpgp.org' } */ - fromUserId?: UserId; - /** (optional) user ID to encrypt for, e.g. { name:'Robert Receiver', email:'robert@openpgp.org' } */ - toUserId?: UserId; - } - - export type EncryptOptions = BaseEncryptOptions | EncryptArmorOptions | EncryptBinaryOptions; - - export interface EncryptArmorOptions extends BaseEncryptOptions { - /** if the return values should be ascii armored or the message/signature objects */ - armor: true; - } - - export interface EncryptBinaryOptions extends BaseEncryptOptions { - /** if the return values should be ascii armored or the message/signature objects */ - armor: false; - } - - export namespace packet { - - export class List extends Array { - [index: number]: PACKET_TYPE; - length: number; - read(bytes: Uint8Array): void; - write(): Uint8Array; - push(...packet: PACKET_TYPE[]): number; - pop(): PACKET_TYPE; - filter(callback: (packet: PACKET_TYPE, i: number, self: List) => void): List; - filterByTag(...args: enums.packet[]): List; - forEach(callback: (packet: PACKET_TYPE, i: number, self: List) => void): void; - map(callback: (packet: PACKET_TYPE, i: number, self: List) => RETURN_TYPE): List; - // some() - // every() - // findPacket() - // indexOfTag() - // slice() - // concat() - // fromStructuredClone() - } - - function fromStructuredClone(packetClone: object): AnyPacket; - - function newPacketFromTag(tag: enums.packetNames): AnyPacket; - - class BasePacket { - tag: enums.packet; - read(bytes: Uint8Array): void; - write(): Uint8Array; - } - - class BaseKeyPacket extends BasePacket { - // fingerprint: Uint8Array|null; - not included because not recommended to use. Use getFingerprint() or getFingerprintBytes() - algorithm: enums.publicKey; - created: Date; - getBitSize(): number; - getAlgorithmInfo(): key.AlgorithmInfo; - getFingerprint(): string; - getFingerprintBytes(): Uint8Array | null; - getCreationTime(): Date; - getKeyId(): Keyid; - - version: number; - expirationTimeV3: number | null; - keyExpirationTime: number | null; - } - - class BasePrimaryKeyPacket extends BaseKeyPacket { - } - - export class Compressed extends BasePacket { - tag: enums.packet.compressed; - } - - export class SymEncryptedIntegrityProtected extends BasePacket { - tag: enums.packet.symEncryptedIntegrityProtected; - } - - export class SymEncryptedAEADProtected extends BasePacket { - tag: enums.packet.symEncryptedAEADProtected; - } - - export class PublicKeyEncryptedSessionKey extends BasePacket { - tag: enums.packet.publicKeyEncryptedSessionKey; - } - - export class SymEncryptedSessionKey extends BasePacket { - tag: enums.packet.symEncryptedSessionKey; - } - - export class Literal extends BasePacket { - tag: enums.packet.literal; - } - - export class PublicKey extends BasePrimaryKeyPacket { - tag: enums.packet.publicKey; - isDecrypted(): null; - } - - export class SymmetricallyEncrypted extends BasePacket { - tag: enums.packet.symmetricallyEncrypted; - } - - export class Marker extends BasePacket { - tag: enums.packet.marker; - } - - export class PublicSubkey extends BaseKeyPacket { - tag: enums.packet.publicSubkey; - isDecrypted(): null; - } - - export class UserAttribute extends BasePacket { - tag: enums.packet.userAttribute; - } - - export class OnePassSignature extends BasePacket { - tag: enums.packet.onePassSignature; - correspondingSig?: Promise; - } - - export class SecretKey extends BasePrimaryKeyPacket { - tag: enums.packet.secretKey; - isDecrypted(): boolean; - encrypt(passphrase: string): Promise; - decrypt(passphrase: string): Promise; - // encrypted: null | unknown[]; // Encrypted secret-key data, not meant for public use - s2k: { type: string } | null; - } - - export class Userid extends BasePacket { - tag: enums.packet.userid; - userid: string; - } - - export class SecretSubkey extends BaseKeyPacket { - tag: enums.packet.secretSubkey; - isDecrypted(): boolean; - encrypt(passphrase: string): Promise; - decrypt(passphrase: string): Promise; - // encrypted: null | unknown[]; // Encrypted secret-key data, not meant for public use - s2k: { type: string } | null; - } - - export class Signature extends BasePacket { - tag: enums.packet.signature; - version: number; - signatureType: null | number; - hashAlgorithm: null | number; - publicKeyAlgorithm: null | number; - signatureData: null | Uint8Array; - unhashedSubpackets: null | Uint8Array; - signedHashValue: null | Uint8Array; - created: Date; - signatureExpirationTime: null | number; - signatureNeverExpires: boolean; - exportable: null | boolean; - trustLevel: null | number; - trustAmount: null | number; - regularExpression: null | number; - revocable: null | boolean; - keyExpirationTime: null | number; - keyNeverExpires: null | boolean; - preferredSymmetricAlgorithms: null | number[]; - revocationKeyClass: null | number; - revocationKeyAlgorithm: null | number; - revocationKeyFingerprint: null | Uint8Array; - issuerKeyId: Keyid; - notation: null | { [name: string]: string }; - preferredHashAlgorithms: null | number[]; - preferredCompressionAlgorithms: null | number[]; - keyServerPreferences: null | number[]; - preferredKeyServer: null | string; - isPrimaryUserID: null | boolean; - policyURI: null | string; - keyFlags: null | number[]; - signersUserId: null | string; - reasonForRevocationFlag: null | number; - reasonForRevocationString: null | string; - features: null | number[]; - signatureTargetPublicKeyAlgorithm: null | number; - signatureTargetHashAlgorithm: null | number; - signatureTargetHash: null | string; - embeddedSignature: null | Signature; - issuerKeyVersion: null | number; - issuerFingerprint: null | Uint8Array; - preferredAeadAlgorithms: null | Uint8Array; - verified: null | boolean; - revoked: null | boolean; - sign(key: SecretKey | SecretSubkey, data: Uint8Array): true; - isExpired(date?: Date): boolean; - getExpirationTime(): Date | typeof Infinity; - } - - export class Trust extends BasePacket { - tag: enums.packet.trust; - } - - export type AnyPacket = Compressed | SymEncryptedIntegrityProtected | SymEncryptedAEADProtected | PublicKeyEncryptedSessionKey | SymEncryptedSessionKey | Literal - | PublicKey | SymmetricallyEncrypted | Marker | PublicSubkey | UserAttribute | OnePassSignature | SecretKey | Userid | SecretSubkey | Signature | Trust; - export type AnySecretPacket = SecretKey | SecretSubkey; - export type AnyKeyPacket = PublicKey | SecretKey | PublicSubkey | SecretSubkey; - } - - export interface EncryptArmorResult { - data: string; - signature?: string; - } - - export interface EncryptBinaryResult { - message: message.Message; - signature?: signature.Signature; - } - - export type EncryptResult = EncryptArmorResult | EncryptBinaryResult; - - export interface SignArmorResult { - data: string | Stream; - signature: string | Stream; - } - - export interface SignBinaryResult { - message: message.Message | cleartext.CleartextMessage; - signature: signature.Signature; - } - - export type SignResult = SignArmorResult | SignBinaryResult; - - export interface DecryptOptions { - /** the message object with the encrypted data */ - message: message.Message; - /** (optional) private keys with decrypted secret key data or session key */ - privateKeys?: key.Key | key.Key[]; - /** (optional) passwords to decrypt the message */ - passwords?: string | string[]; - /** (optional) session keys in the form: { data:Uint8Array, algorithm:String } */ - sessionKeys?: SessionKey | SessionKey[]; - /** (optional) array of public keys or single key, to verify signatures */ - publicKeys?: key.Key | key.Key[]; - /** (optional) whether to return data as a string(Stream) or Uint8Array(Stream). If 'utf8' (the default), also normalize newlines. */ - format?: string; - /** (optional) whether to return data as a stream. Defaults to the type of stream `message` was created from, if any. */ - streaming?: 'web' | 'node' | false; - /** (optional) detached signature for verification */ - signature?: signature.Signature; - } - - export interface SignOptions { - message: cleartext.CleartextMessage | message.Message; - privateKeys?: key.Key | key.Key[]; - armor?: boolean; - streaming?: 'web' | 'node' | false; - dataType?: DataPacketType; - detached?: boolean; - date?: Date; - fromUserId?: UserId; - } - - export interface KeyContainer { - key: key.Key; - } - - export interface KeyPair extends KeyContainer { - privateKeyArmored: string; - publicKeyArmored: string; - } - - export interface KeyOptions { - userIds: UserId[]; // generating a key with no user defined results in error - passphrase?: string; - numBits?: number; - keyExpirationTime?: number; - curve?: key.EllipticCurveName; - date?: Date; - subkeys?: KeyOptions[]; - } - - /** - * Intended for internal use with openpgp.generate() - * It's recommended that users choose openpgp.generateKey() that requires KeyOptions instead - */ - export interface FullKeyOptions { - userIds: UserId[]; - passphrase?: string; - numBits?: number; - keyExpirationTime?: number; - curve?: key.EllipticCurveName; - date?: Date; - subkeys: KeyOptions[]; // required unline KeyOptions.subkeys - } - - export interface Keyid { - bytes: string; - } - - export interface DecryptMessageResult { - data: Uint8Array | string; - signatures: signature.Signature[]; - filename: string; - } - - export interface OpenPGPWorker { - randomCallback(): void; - configure(config: any): void; - seedRandom(buffer: ArrayBuffer): void; - delegate(id: number, method: string, options: any): void; - response(event: any): void; - } - - export interface WorkerOptions { - path?: string; - n?: number; - workers?: OpenPGPWorker[]; - config?: any; - } - - export class AsyncProxy { - constructor(options: WorkerOptions); - getId(): number; - seedRandom(workerId: number, size: number): Promise; - terminate(): void; - delegate(method: string, options: any): void; - - workers: OpenPGPWorker[]; - } - - /** - * Set the path for the web worker script and create an instance of the async proxy - * @param {String} path relative path to the worker scripts, default: 'openpgp.worker.js' - * @param {Number} n number of workers to initialize - * @param {Array} workers alternative to path parameter: web workers initialized with 'openpgp.worker.js' - */ - export function initWorker(options: WorkerOptions): boolean; - - /** - * Returns a reference to the async proxy if the worker was initialized with openpgp.initWorker() - * @returns {module:worker/async_proxy.AsyncProxy|null} the async proxy or null if not initialized - */ - export function getWorker(): AsyncProxy; - - /** - * Cleanup the current instance of the web worker. - */ - export function destroyWorker(): void; - - /** - * Encrypts message text/data with public keys, passwords or both at once. At least either public keys or passwords - * must be specified. If private keys are specified, those will be used to sign the message. - * @param {EncryptOptions} options See `EncryptOptions` - * @returns {Promise} Promise of `EncryptResult` (and optionally signed message) in the form: - * {data: ASCII armored message if 'armor' is true; - * message: full Message object if 'armor' is false, signature: detached signature if 'detached' is true} - * @async - * @static - */ - export function encrypt(options: EncryptBinaryOptions): Promise; - export function encrypt(options: EncryptArmorOptions | BaseEncryptOptions): Promise; - - /** - * Signs a cleartext message. - * @param {String | Uint8Array} data cleartext input to be signed - * @param {utf8|binary|text|mime} dataType (optional) data packet type - * @param {Key|Array} privateKeys array of keys or single key with decrypted secret key data to sign cleartext - * @param {Boolean} armor (optional) if the return value should be ascii armored or the message object - * @param {Boolean} detached (optional) if the return value should contain a detached signature - * @param {Date} date (optional) override the creation date signature - * @param {Object} fromUserId (optional) user ID to sign with, e.g. { name:'Steve Sender', email:'steve@openpgp.org' } - * @returns {Promise} signed cleartext in the form: - * {data: ASCII armored message if 'armor' is true; - * message: full Message object if 'armor' is false, signature: detached signature if 'detached' is true} - * @async - * @static - */ - export function sign(options: SignOptions): Promise; - - /** - * Decrypts a message with the user's private key, a session key or a password. Either a private key; - * a session key or a password must be specified. - * @param {DecryptOptions} options see `DecryptOptions` - * @returns {Promise} Promise of `DecryptMessageResult` and verified message in the form: - * { data:Uint8Array|String, filename:String, signatures:[{ keyid:String, valid:Boolean }] } - * @async - * @static - */ - export function decrypt(options: DecryptOptions): Promise; - - /** - * Generates a new OpenPGP key pair. Supports RSA and ECC keys. Primary and subkey will be of same type. - * @param {Array} userIds array of user IDs e.g. [{ name:'Phil Zimmermann', email:'phil@openpgp.org' }] - * @param {String} passphrase (optional) The passphrase used to encrypt the resulting private key - * @param {Number} numBits (optional) number of bits for RSA keys: 2048 or 4096. - * @param {Number} keyExpirationTime (optional) The number of seconds after the key creation time that the key expires - * @param {String} curve (optional) elliptic curve for ECC keys: - * curve25519, p256, p384, p521, secp256k1; - * brainpoolP256r1, brainpoolP384r1, or brainpoolP512r1. - * @param {Date} date (optional) override the creation date of the key and the key signatures - * @param {Array} subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}] - * sign parameter defaults to false, and indicates whether the subkey should sign rather than encrypt - * @returns {Promise} The generated key object in the form: - * { key:Key, privateKeyArmored:String, publicKeyArmored:String } - * @async - * @static - */ - export function generateKey(options: KeyOptions): Promise; - - /** - * Reformats signature packets for a key and rewraps key object. - * @param {Key} privateKey private key to reformat - * @param {Array} userIds array of user IDs e.g. [{ name:'Phil Zimmermann', email:'phil@openpgp.org' }] - * @param {String} passphrase (optional) The passphrase used to encrypt the resulting private key - * @param {Number} keyExpirationTime (optional) The number of seconds after the key creation time that the key expires - * @returns {Promise} The generated key object in the form: - * { key:Key, privateKeyArmored:String, publicKeyArmored:String } - * @async - * @static - */ - export function reformatKey(options: { - privateKey: key.Key; - userIds?: (string | UserId)[]; - passphrase?: string; - keyExpirationTime?: number; - }): Promise; - - /** - * Unlock a private key with your passphrase. - * @param {Key} privateKey the private key that is to be decrypted - * @param {String|Array} passphrase the user's passphrase(s) chosen during key generation - * @returns {Promise} the unlocked key object in the form: { key:Key } - * @async - */ - export function decryptKey(options: { - privateKey: key.Key; - passphrase?: string | string[]; - }): Promise; - - export function encryptKey(options: { - privateKey: key.Key; - passphrase?: string - }): Promise; - - export namespace armor { - /** Armor an OpenPGP binary packet block - * @param messagetype type of the message - * @param body - * @param partindex - * @param parttotal - */ - function armor(messagetype: enums.armor, body: object, partindex: number, parttotal: number): string; - - /** DeArmor an OpenPGP armored message; verify the checksum and return the encoded bytes - * - * @param text OpenPGP armored message - */ - function dearmor(text: string): object; - } - - export namespace cleartext { - /** Class that represents an OpenPGP cleartext signed message. - */ - interface CleartextMessage { - /** Returns ASCII armored text of cleartext signed message - */ - armor(): string; - - /** Returns the key IDs of the keys that signed the cleartext message - */ - getSigningKeyIds(): Array; - - /** Get cleartext - */ - getText(): string; - - /** Sign the cleartext message - * - * @param privateKeys private keys with decrypted secret key data for signing - */ - sign(privateKeys: Array): void; - - /** Verify signatures of cleartext signed message - * @param keys array of keys to verify signatures - */ - verify(keys: key.Key[], date?: Date, streaming?: boolean): Promise; - } - - /** - * reads an OpenPGP cleartext signed message and returns a CleartextMessage object - * @param armoredText text to be parsed - * @returns new cleartext message object - * @async - * @static - */ - function readArmored(armoredText: string): Promise; - - function fromText(text: string): CleartextMessage; - } - - export namespace config { - let prefer_hash_algorithm: enums.hash; - let encryption_cipher: enums.symmetric; - let compression: enums.compression; - let show_version: boolean; - let show_comment: boolean; - let integrity_protect: boolean; - let debug: boolean; - let deflate_level: number; - let aead_protect: boolean; - let ignore_mdc_error: boolean; - let checksum_required: boolean; - let rsa_blinding: boolean; - let password_collision_check: boolean; - let revocations_expire: boolean; - let use_native: boolean; - let zero_copy: boolean; - let tolerant: boolean; - let versionstring: string; - let commentstring: string; - let keyserver: string; - let node_store: string; - } - - export namespace crypto { - interface Mpi { - data: number; - read(input: string): number; - write(): string; - } - - /** Generating a session key for the specified symmetric algorithm - * @param algo Algorithm to use - */ - function generateSessionKey(algo: enums.symmetric): string; - - /** generate random byte prefix as string for the specified algorithm - * @param algo Algorithm to use - */ - function getPrefixRandom(algo: enums.symmetric): string; - - /** Returns the number of integers comprising the private key of an algorithm - * @param algo The public key algorithm - */ - function getPrivateMpiCount(algo: enums.symmetric): number; - - /** Decrypts data using the specified public key multiprecision integers of the private key, the specified secretMPIs of the private key and the specified algorithm. - @param algo Algorithm to be used - @param publicMPIs Algorithm dependent multiprecision integers of the public key part of the private key - @param secretMPIs Algorithm dependent multiprecision integers of the private key used - @param data Data to be encrypted as MPI - */ - function publicKeyDecrypt(algo: enums.publicKey, publicMPIs: Array, secretMPIs: Array, data: Mpi): Mpi; - - /** Encrypts data using the specified public key multiprecision integers and the specified algorithm. - @param algo Algorithm to be used - @param publicMPIs Algorithm dependent multiprecision integers - @param data Data to be encrypted as MPI - */ - function publicKeyEncrypt(algo: enums.publicKey, publicMPIs: Array, data: Mpi): Array; - - namespace cfb { - /** This function decrypts a given plaintext using the specified blockcipher to decrypt a message - @param cipherfn the algorithm cipher class to decrypt data in one block_size encryption - @param key binary string representation of key to be used to decrypt the ciphertext. This will be passed to the cipherfn - @param ciphertext to be decrypted provided as a string - @param resync a boolean value specifying if a resync of the IV should be used or not. The encrypteddatapacket uses the "old" style with a resync. Decryption within an encryptedintegrityprotecteddata packet is not resyncing the IV. - */ - function decrypt(cipherfn: string, key: string, ciphertext: string, resync: boolean): string; - - /** This function encrypts a given with the specified prefixrandom using the specified blockcipher to encrypt a message - @param prefixrandom random bytes of block_size length provided as a string to be used in prefixing the data - @param cipherfn the algorithm cipher class to encrypt data in one block_size encryption - @param plaintext data to be encrypted provided as a string - @param key binary string representation of key to be used to encrypt the plaintext. This will be passed to the cipherfn - @param resync a boolean value specifying if a resync of the IV should be used or not. The encrypteddatapacket uses the "old" style with a resync. Encryption within an encryptedintegrityprotecteddata packet is not resyncing the IV. - */ - function encrypt(prefixrandom: string, cipherfn: string, plaintext: string, key: string, resync: boolean): string; - - /** Decrypts the prefixed data for the Modification Detection Code (MDC) computation - @param cipherfn cipherfn.encrypt Cipher function to use - @param key binary string representation of key to be used to check the mdc This will be passed to the cipherfn - @param ciphertext The encrypted data - */ - function mdc(cipherfn: object, key: string, ciphertext: string): string; - } - - namespace hash { - /** Create a hash on the specified data using the specified algorithm - @param algo Hash algorithm type - @param data Data to be hashed - */ - function digest(algo: enums.hash, data: Uint8Array): Promise; - - /** Returns the hash size in bytes of the specified hash algorithm type - @param algo Hash algorithm type - */ - function getHashByteLength(algo: enums.hash): number; - } - - namespace random { - /** Retrieve secure random byte string of the specified length - @param length Length in bytes to generate - */ - function getRandomBytes(length: number): Promise; - } - - namespace signature { - /** Create a signature on data using the specified algorithm - @param hash_algo hash Algorithm to use - @param algo Asymmetric cipher algorithm to use - @param publicMPIs Public key multiprecision integers of the private key - @param secretMPIs Private key multiprecision integers which is used to sign the data - @param data Data to be signed - */ - function sign(hash_algo: enums.hash, algo: enums.publicKey, publicMPIs: Array, secretMPIs: Array, data: string): Mpi; - - /** - @param algo public Key algorithm - @param hash_algo Hash algorithm - @param msg_MPIs Signature multiprecision integers - @param publickey_MPIs Public key multiprecision integers - @param data Data on where the signature was computed on - */ - function verify(algo: enums.publicKey, hash_algo: enums.hash, msg_MPIs: Array, publickey_MPIs: Array, data: string): boolean; - } - } - - export namespace enums { - - function read(type: typeof armor, e: armor): armorNames | string | any; - function read(type: typeof compression, e: compression): compressionNames | string | any; - function read(type: typeof hash, e: hash): hashNames | string | any; - function read(type: typeof packet, e: packet): packetNames | string | any; - function read(type: typeof publicKey, e: publicKey): publicKeyNames | string | any; - function read(type: typeof symmetric, e: symmetric): symmetricNames | string | any; - function read(type: typeof keyStatus, e: keyStatus): keyStatusNames | string | any; - function read(type: typeof keyFlags, e: keyFlags): keyFlagsNames | string | any; - - export type armorNames = 'multipart_section' | 'multipart_last' | 'signed' | 'message' | 'public_key' | 'private_key'; - enum armor { - multipart_section = 0, - multipart_last = 1, - signed = 2, - message = 3, - public_key = 4, - private_key = 5, - signature = 6, - } - - enum reasonForRevocation { - no_reason = 0, // No reason specified (key revocations or cert revocations) - key_superseded = 1, // Key is superseded (key revocations) - key_compromised = 2, // Key material has been compromised (key revocations) - key_retired = 3, // Key is retired and no longer used (key revocations) - userid_invalid = 32, // User ID information is no longer valid (cert revocations) - } - - export type compressionNames = 'uncompressed' | 'zip' | 'zlib' | 'bzip2'; - enum compression { - uncompressed = 0, - zip = 1, - zlib = 2, - bzip2 = 3, - } - - export type hashNames = 'md5' | 'sha1' | 'ripemd' | 'sha256' | 'sha384' | 'sha512' | 'sha224'; - enum hash { - md5 = 1, - sha1 = 2, - ripemd = 3, - sha256 = 8, - sha384 = 9, - sha512 = 10, - sha224 = 11, - } - - export type packetNames = 'publicKeyEncryptedSessionKey' | 'signature' | 'symEncryptedSessionKey' | 'onePassSignature' | 'secretKey' | 'publicKey' - | 'secretSubkey' | 'compressed' | 'symmetricallyEncrypted' | 'marker' | 'literal' | 'trust' | 'userid' | 'publicSubkey' | 'userAttribute' - | 'symEncryptedIntegrityProtected' | 'modificationDetectionCode' | 'symEncryptedAEADProtected'; - enum packet { - publicKeyEncryptedSessionKey = 1, - signature = 2, - symEncryptedSessionKey = 3, - onePassSignature = 4, - secretKey = 5, - publicKey = 6, - secretSubkey = 7, - compressed = 8, - symmetricallyEncrypted = 9, - marker = 10, - literal = 11, - trust = 12, - userid = 13, - publicSubkey = 14, - userAttribute = 17, - symEncryptedIntegrityProtected = 18, - modificationDetectionCode = 19, - symEncryptedAEADProtected = 20, - } - - export type publicKeyNames = 'rsa_encrypt_sign' | 'rsa_encrypt' | 'rsa_sign' | 'elgamal' | 'dsa' | 'ecdh' | 'ecdsa' | 'eddsa' | 'aedh' | 'aedsa'; - enum publicKey { - rsa_encrypt_sign = 1, - rsa_encrypt = 2, - rsa_sign = 3, - elgamal = 16, - dsa = 17, - ecdh = 18, - ecdsa = 19, - eddsa = 22, - aedh = 23, - aedsa = 24, - } - - export type symmetricNames = 'plaintext' | 'idea' | 'tripledes' | 'cast5' | 'blowfish' | 'aes128' | 'aes192' | 'aes256' | 'twofish'; - enum symmetric { - plaintext = 0, - idea = 1, - tripledes = 2, - cast5 = 3, - blowfish = 4, - aes128 = 7, - aes192 = 8, - aes256 = 9, - twofish = 10, - } - - export type keyStatusNames = 'invalid' | 'expired' | 'revoked' | 'valid' | 'no_self_cert'; - enum keyStatus { - invalid = 0, - expired = 1, - revoked = 2, - valid = 3, - no_self_cert = 4, - } - - export type keyFlagsNames = 'certify_keys' | 'sign_data' | 'encrypt_communication' | 'encrypt_storage' | 'split_private_key' | 'authentication' - | 'shared_private_key'; - enum keyFlags { - certify_keys = 1, - sign_data = 2, - encrypt_communication = 4, - encrypt_storage = 8, - split_private_key = 16, - authentication = 32, - shared_private_key = 128, - } - - } - - export namespace key { - - export type EllipticCurveName = 'curve25519' | 'p256' | 'p384' | 'p521' | 'secp256k1' | 'brainpoolP256r1' | 'brainpoolP384r1' | 'brainpoolP512r1'; - - /** Class that represents an OpenPGP key. Must contain a primary key. Can contain additional subkeys, signatures, user ids, user attributes. - */ - class Key { - constructor(packetlist: packet.List); - armor(): string; - decrypt(passphrase: string | string[], keyId?: Keyid): Promise; - encrypt(passphrase: string | string[]): Promise; - getExpirationTime(capability?: 'encrypt' | 'encrypt_sign' | 'sign' | null, keyId?: Keyid | null, userId?: UserId | null): Promise; // Returns null if `capabilities` is passed and the key does not have the specified capabilities or is revoked or invalid. - getKeyIds(): Keyid[]; - getPrimaryUser(): Promise; - getUserIds(): string[]; - isPrivate(): boolean; - isPublic(): boolean; - toPublic(): Key; - update(key: Key): void; - verifyPrimaryKey(): Promise; - isRevoked(): Promise; - revoke(reason: { flag?: enums.reasonForRevocation; string?: string; }, date?: Date): Promise; - getRevocationCertificate(): Promise | string | undefined>; - getEncryptionKey(keyid?: Keyid | null, date?: Date, userId?: UserId | null): Promise; - getSigningKey(): Promise; - getKeys(keyId?: Keyid): (Key | SubKey)[]; - // isDecrypted(): boolean; - isFullyEncrypted(): boolean; - isFullyDecrypted(): boolean; - isPacketDecrypted(keyId: Keyid): boolean; - getFingerprint(): string; - getCreationTime(): Date; - getAlgorithmInfo(): AlgorithmInfo; - getKeyId(): Keyid; - primaryKey: packet.PublicKey | packet.SecretKey; - subKeys: SubKey[]; - users: User[]; - revocationSignatures: packet.Signature[]; - keyPacket: packet.PublicKey | packet.SecretKey; - } - - class SubKey { - constructor(subKeyPacket: packet.SecretSubkey | packet.PublicSubkey); - subKey: packet.SecretSubkey | packet.PublicSubkey; - keyPacket: packet.SecretKey; - bindingSignatures: packet.Signature[]; - revocationSignatures: packet.Signature[]; - verify(primaryKey: packet.PublicKey | packet.SecretKey): Promise; - isDecrypted(): boolean; - getFingerprint(): string; - getCreationTime(): Date; - getAlgorithmInfo(): AlgorithmInfo; - getKeyId(): Keyid; - } - - export interface User { - userId: packet.Userid | null; - userAttribute: packet.UserAttribute | null; - selfCertifications: packet.Signature[]; - otherCertifications: packet.Signature[]; - revocationSignatures: packet.Signature[]; - } - - export interface PrimaryUser { - index: number; - user: User; - } - - interface KeyResult { - keys: Key[]; - err?: Error[]; - } - - type AlgorithmInfo = { - algorithm: enums.publicKeyNames; - bits: number; - }; - - /** Generates a new OpenPGP key. Currently only supports RSA keys. Primary and subkey will be of same type. - * @param options - */ - function generate(options: FullKeyOptions): Promise; - - /** Reads an OpenPGP armored text and returns one or multiple key objects - - @param armoredText text to be parsed - */ - function readArmored(armoredText: string): Promise; - - /** Reads an OpenPGP binary data and returns one or multiple key objects - - @param data to be parsed - */ - function read(data: Uint8Array): Promise; - } - - export namespace signature { - class Signature { - constructor(packetlist: packet.List); - armor(): string; - packets: packet.List; - } - - /** reads an OpenPGP armored signature and returns a signature object - - @param armoredText text to be parsed - */ - function readArmored(armoredText: string): Promise; - - /** reads an OpenPGP signature as byte array and returns a signature object - - @param input binary signature - */ - function read(input: Uint8Array): Promise; - } - - export namespace message { - /** Class that represents an OpenPGP message. Can be an encrypted message, signed message, compressed message or literal message - */ - class Message { - constructor(packetlist: packet.List); - - /** Returns ASCII armored text of message - */ - armor(): string; - - /** Decrypt the message - @param privateKey private key with decrypted secret data - */ - decrypt(privateKeys?: key.Key[] | null, passwords?: string[] | null, sessionKeys?: SessionKey[] | null, streaming?: boolean): Promise; - - /** Encrypt the message - @param keys array of keys, used to encrypt the message - */ - encrypt(keys: key.Key[]): Promise; - - /** Returns the key IDs of the keys to which the session key is encrypted - */ - getEncryptionKeyIds(): Keyid[]; - - /** Get literal data that is the body of the message - */ - getLiteralData(): Uint8Array | null | Stream; - - /** Returns the key IDs of the keys that signed the message - */ - getSigningKeyIds(): Keyid[]; - - /** Get literal data as text - */ - getText(): string | null | Stream; - - getFilename(): string | null; - - /** Sign the message (the literal data packet of the message) - @param privateKey private keys with decrypted secret key data for signing - */ - sign(privateKey: key.Key[]): Promise; - - /** Unwrap compressed message - */ - unwrapCompressed(): Message; - - /** Verify message signatures - @param keys array of keys to verify signatures - */ - verify(keys: key.Key[], date?: Date, streaming?: boolean): Promise; - - /** - * Append signature to unencrypted message object - * @param {String|Uint8Array} detachedSignature The detached ASCII-armored or Uint8Array PGP signature - */ - appendSignature(detachedSignature: string | Uint8Array): Promise; - - packets: packet.List; - } - - class SessionKey { // todo - - } - - export interface Verification { - keyid: Keyid; - verified: Promise; - signature: Promise; - } - - /** creates new message object from binary data - @param bytes - */ - function fromBinary(bytes: Uint8Array | Stream, filename?: string, date?: Date, type?: DataPacketType): Message; - - /** creates new message object from text - @param text - */ - function fromText(text: string | Stream, filename?: string, date?: Date, type?: DataPacketType): Message; - - /** reads an OpenPGP armored message and returns a message object - - @param armoredText text to be parsed - */ - function readArmored(armoredText: string | Stream): Promise; - - /** - * reads an OpenPGP message as byte array and returns a message object - * @param {Uint8Array} input binary message - * @returns {Message} new message object - * @static - */ - function read(input: Uint8Array): Promise; - } - - export class HKP { - constructor(keyServerBaseUrl?: string); - lookup(options: { keyid?: string, query?: string }): Promise; - } - - /** - * todo - some of these are outdated - check OpenPGP.js api - */ - export namespace util { - /** Convert an array of integers(0.255) to a string - @param bin An array of (binary) integers to convert - */ - function bin2str(bin: Array): string; - - /** Calculates a 16bit sum of a string by adding each character codes modulus 65535 - @param text string to create a sum of - */ - function calc_checksum(text: string): number; - - /** Convert a string of utf8 bytes to a native javascript string - @param utf8 A valid squence of utf8 bytes - */ - function decode_utf8(utf8: string): string; - - /** Convert a native javascript string to a string of utf8 bytes - param str The string to convert - */ - function encode_utf8(str: string): string; - - /** Return the algorithm type as string - */ - function get_hashAlgorithmString(): string; - - /** Get native Web Cryptography api. The default configuration is to use the api when available. But it can also be deactivated with config.useWebCrypto - */ - function getWebCrypto(): object; - - /** Helper function to print a debug message. Debug messages are only printed if - @param str string of the debug message - */ - function print_debug(str: string): void; - - /** Helper function to print a debug message. Debug messages are only printed if - @param str string of the debug message - */ - function print_debug_hexstr_dump(str: string): void; - - /** Shifting a string to n bits right - @param value The string to shift - @param bitcount Amount of bits to shift (MUST be smaller than 9) - */ - function shiftRight(value: string, bitcount: number): string; - - /** - * Convert a string to an array of 8-bit integers - * @param {String} str String to convert - * @returns {Uint8Array} An array of 8-bit integers - */ - function str_to_Uint8Array(str: string): Uint8Array; - - /** - * Convert an array of 8-bit integers to a string - * @param {Uint8Array} bytes An array of 8-bit integers to convert - * @returns {String} String representation of the array - */ - function Uint8Array_to_str(bin: Uint8Array): string; - - /** - * Convert an array of 8-bit integers to a hex string - * @param {Uint8Array} bytes Array of 8-bit integers to convert - * @returns {String} Hexadecimal representation of the array - */ - function Uint8Array_to_hex(bytes: Uint8Array): string; - - /** - * Convert a hex string to an array of 8-bit integers - * @param {String} hex A hex string to convert - * @returns {Uint8Array} An array of 8-bit integers - */ - function hex_to_Uint8Array(hex: string): Uint8Array; - - /** - * Create hex string from a binary - * @param {String} str String to convert - * @returns {String} String containing the hexadecimal values - */ - function str_to_hex(str: string): string; - - /** - * Create binary string from a hex encoded string - * @param {String} str Hex string to convert - * @returns {String} - */ - function hex_to_str(hex: string): string; - - function parseUserId(userid: string): UserId; - - function formatUserId(userid: UserId): string; - - function normalizeDate(date: Date | null): Date | null; - } - - export namespace stream { - function readToEnd(input: Stream | T, concat?: (list: T[]) => T): Promise; - // concat - // slice - // clone - // webToNode - // nodeToWeb - } - -} diff --git a/Core/.save/openpgpv4/openpgpv4.js b/Core/.save/openpgpv4/openpgpv4.js deleted file mode 100644 index 8103dee04..000000000 --- a/Core/.save/openpgpv4/openpgpv4.js +++ /dev/null @@ -1,42866 +0,0 @@ -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.openpgp = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i `Symbol(${e})`;const r = "undefined" != typeof self ? self : "undefined" != typeof window ? window : "undefined" != typeof global ? global : void 0, - o = Number.isNaN || function (e) { - return e != e; - };function n(e) { - return "object" == typeof e && null !== e || "function" == typeof e; - }function i(e, t, r) { - Object.defineProperty(e, t, { value: r, writable: !0, enumerable: !0, configurable: !0 }); - }function a(e) { - return e.slice(); - }function s(e, t, r, o, n) { - new Uint8Array(e).set(new Uint8Array(r, o, n), t); - }function l(e) { - return !1 !== function (e) { - if ("number" != typeof e) return !1;if (o(e)) return !1;if (e < 0) return !1;return !0; - }(e) && e !== 1 / 0; - }function c(e, t, r) { - if ("function" != typeof e) throw new TypeError("Argument is not a function");return Function.prototype.apply.call(e, t, r); - }function u(e, t, r, o) { - const n = e[t];if (void 0 !== n) { - if ("function" != typeof n) throw new TypeError(`${n} is not a method`);switch (r) {case 0: - return () => f(n, e, o);case 1: - return t => { - const r = [t].concat(o);return f(n, e, r); - };} - }return () => Promise.resolve(); - }function d(e, t, r) { - const o = e[t];if (void 0 !== o) return c(o, e, r); - }function f(e, t, r) { - try { - return Promise.resolve(c(e, t, r)); - } catch (e) { - return Promise.reject(e); - } - }function _(e) { - return e; - }function h(e) { - if (e = Number(e), o(e) || e < 0) throw new RangeError("highWaterMark property of a queuing strategy must be non-negative and non-NaN");return e; - }function b(e) { - if (void 0 === e) return () => 1;if ("function" != typeof e) throw new TypeError("size property of a queuing strategy must be a function");return t => e(t); - }function m(e, t, r) { - return Promise.prototype.then.call(e, t, r); - }function y(e, t, r) { - let o, n;const i = new Promise((e, t) => { - o = e, n = t; - });void 0 === r && (r = e => { - throw e; - });return function (e, t, r) { - let o = !1;const n = e => { - !1 === o && (o = !0, r(e)); - };let i = 0, - a = 0;const s = e.length, - l = new Array(s);for (const r of e) { - const e = i;m(r, r => { - l[e] = r, ++a === s && t(l); - }, n), ++i; - } - }(e, e => { - try { - const r = t(e);o(r); - } catch (e) { - n(e); - } - }, e => { - try { - const t = r(e);o(t); - } catch (e) { - n(e); - } - }), i; - }function p(e) {}function w(e) { - e && e instanceof p.AssertionError && setTimeout(() => { - throw e; - }, 0); - }function g(e) { - const t = e._queue.shift();return e._queueTotalSize -= t.size, e._queueTotalSize < 0 && (e._queueTotalSize = 0), t.value; - }function S(e, t, r) { - if (!l(r = Number(r))) throw new RangeError("Size must be a finite, non-NaN, non-negative number.");e._queue.push({ value: t, size: r }), e._queueTotalSize += r; - }function v(e) { - e._queue = [], e._queueTotalSize = 0; - }p.AssertionError = function () {};const R = t("[[AbortSteps]]"), - P = t("[[ErrorSteps]]");class WritableStream { - constructor(e = {}, t = {}) { - q(this);const r = t.size;let o = t.highWaterMark;if (void 0 !== e.type) throw new RangeError("Invalid type is specified");const n = b(r);void 0 === o && (o = 1), function (e, t, r, o) { - const n = Object.create(WritableStreamDefaultController.prototype);const i = u(t, "write", 1, [n]), - a = u(t, "close", 0, []), - s = u(t, "abort", 1, []);$(e, n, function () { - return d(t, "start", [n]); - }, i, a, s, r, o); - }(this, e, o = h(o), n); - }get locked() { - if (!1 === E(this)) throw G("locked");return C(this); - }abort(e) { - return !1 === E(this) ? Promise.reject(G("abort")) : !0 === C(this) ? Promise.reject(new TypeError("Cannot abort a stream that already has a writer")) : j(this, e); - }getWriter() { - if (!1 === E(this)) throw G("getWriter");return T(this); - } - }function T(e) { - return new WritableStreamDefaultWriter(e); - }function q(e) { - e._state = "writable", e._storedError = void 0, e._writer = void 0, e._writableStreamController = void 0, e._writeRequests = [], e._inFlightWriteRequest = void 0, e._closeRequest = void 0, e._inFlightCloseRequest = void 0, e._pendingAbortRequest = void 0, e._backpressure = !1; - }function E(e) { - return !!n(e) && !!Object.prototype.hasOwnProperty.call(e, "_writableStreamController"); - }function C(e) { - return void 0 !== e._writer; - }function j(e, t) { - const r = e._state;if ("closed" === r || "errored" === r) return Promise.resolve(void 0);if (void 0 !== e._pendingAbortRequest) return e._pendingAbortRequest._promise;let o = !1;"erroring" === r && (o = !0, t = void 0);const n = new Promise((r, n) => { - e._pendingAbortRequest = { _promise: void 0, _resolve: r, _reject: n, _reason: t, _wasAlreadyErroring: o }; - });return e._pendingAbortRequest._promise = n, !1 === o && W(e, t), n; - }function A(e, t) { - "writable" !== e._state ? B(e) : W(e, t); - }function W(e, t) { - const r = e._writableStreamController;e._state = "erroring", e._storedError = t;const o = e._writer;void 0 !== o && D(o, t), !1 === function (e) { - if (void 0 === e._inFlightWriteRequest && void 0 === e._inFlightCloseRequest) return !1;return !0; - }(e) && !0 === r._started && B(e); - }function B(e) { - e._state = "errored", e._writableStreamController[P]();const t = e._storedError;for (const r of e._writeRequests) r._reject(t);if (e._writeRequests = [], void 0 === e._pendingAbortRequest) return void z(e);const r = e._pendingAbortRequest;if (e._pendingAbortRequest = void 0, !0 === r._wasAlreadyErroring) return r._reject(t), void z(e);e._writableStreamController[R](r._reason).then(() => { - r._resolve(), z(e); - }, t => { - r._reject(t), z(e); - }); - }function O(e) { - return void 0 !== e._closeRequest || void 0 !== e._inFlightCloseRequest; - }function z(e) { - void 0 !== e._closeRequest && (e._closeRequest._reject(e._storedError), e._closeRequest = void 0);const t = e._writer;void 0 !== t && ee(t, e._storedError); - }function k(e, t) { - const r = e._writer;void 0 !== r && t !== e._backpressure && (!0 === t ? function (e) { - re(e); - }(r) : ae(r)), e._backpressure = t; - }class WritableStreamDefaultWriter { - constructor(e) { - if (!1 === E(e)) throw new TypeError("WritableStreamDefaultWriter can only be constructed with a WritableStream instance");if (!0 === C(e)) throw new TypeError("This stream has already been locked for exclusive writing by another writer");this._ownerWritableStream = e, e._writer = this;const t = e._state;if ("writable" === t) !1 === O(e) && !0 === e._backpressure ? re(this) : ne(this), X(this);else if ("erroring" === t) oe(this, e._storedError), X(this);else if ("closed" === t) ne(this), function (e) { - X(e), te(e); - }(this);else { - const t = e._storedError;oe(this, t), Z(this, t); - } - }get closed() { - return !1 === F(this) ? Promise.reject(J("closed")) : this._closedPromise; - }get desiredSize() { - if (!1 === F(this)) throw J("desiredSize");if (void 0 === this._ownerWritableStream) throw K("desiredSize");return function (e) { - const t = e._ownerWritableStream, - r = t._state;if ("errored" === r || "erroring" === r) return null;if ("closed" === r) return 0;return Q(t._writableStreamController); - }(this); - }get ready() { - return !1 === F(this) ? Promise.reject(J("ready")) : this._readyPromise; - }abort(e) { - return !1 === F(this) ? Promise.reject(J("abort")) : void 0 === this._ownerWritableStream ? Promise.reject(K("abort")) : function (e, t) { - return j(e._ownerWritableStream, t); - }(this, e); - }close() { - if (!1 === F(this)) return Promise.reject(J("close"));const e = this._ownerWritableStream;return void 0 === e ? Promise.reject(K("close")) : !0 === O(e) ? Promise.reject(new TypeError("cannot close an already-closing stream")) : L(this); - }releaseLock() { - if (!1 === F(this)) throw J("releaseLock");void 0 !== this._ownerWritableStream && M(this); - }write(e) { - return !1 === F(this) ? Promise.reject(J("write")) : void 0 === this._ownerWritableStream ? Promise.reject(K("write to")) : Y(this, e); - } - }function F(e) { - return !!n(e) && !!Object.prototype.hasOwnProperty.call(e, "_ownerWritableStream"); - }function L(e) { - const t = e._ownerWritableStream, - r = t._state;if ("closed" === r || "errored" === r) return Promise.reject(new TypeError(`The stream (in ${r} state) is not in the writable state and cannot be closed`));const o = new Promise((e, r) => { - const o = { _resolve: e, _reject: r };t._closeRequest = o; - });return !0 === t._backpressure && "writable" === r && ae(e), function (e) { - S(e, "close", 0), x(e); - }(t._writableStreamController), o; - }function I(e, t) { - "pending" === e._closedPromiseState ? ee(e, t) : function (e, t) { - Z(e, t); - }(e, t); - }function D(e, t) { - "pending" === e._readyPromiseState ? ie(e, t) : function (e, t) { - oe(e, t); - }(e, t); - }function M(e) { - const t = e._ownerWritableStream, - r = new TypeError("Writer was released and can no longer be used to monitor the stream's closedness");D(e, r), I(e, r), t._writer = void 0, e._ownerWritableStream = void 0; - }function Y(e, t) { - const r = e._ownerWritableStream, - o = r._writableStreamController, - n = function (e, t) { - try { - return e._strategySizeAlgorithm(t); - } catch (t) { - return H(e, t), 1; - } - }(o, t);if (r !== e._ownerWritableStream) return Promise.reject(K("write to"));const i = r._state;if ("errored" === i) return Promise.reject(r._storedError);if (!0 === O(r) || "closed" === i) return Promise.reject(new TypeError("The stream is closing or closed and cannot be written to"));if ("erroring" === i) return Promise.reject(r._storedError);const a = function (e) { - return new Promise((t, r) => { - const o = { _resolve: t, _reject: r };e._writeRequests.push(o); - }); - }(r);return function (e, t, r) { - const o = { chunk: t };try { - S(e, o, r); - } catch (t) { - return void H(e, t); - }const n = e._controlledWritableStream;if (!1 === O(n) && "writable" === n._state) { - const t = U(e);k(n, t); - }x(e); - }(o, t, n), a; - }class WritableStreamDefaultController { - constructor() { - throw new TypeError("WritableStreamDefaultController cannot be constructed explicitly"); - }error(e) { - if (!1 === function (e) { - if (!n(e)) return !1;if (!Object.prototype.hasOwnProperty.call(e, "_controlledWritableStream")) return !1;return !0; - }(this)) throw new TypeError("WritableStreamDefaultController.prototype.error can only be used on a WritableStreamDefaultController");"writable" === this._controlledWritableStream._state && V(this, e); - }[R](e) { - const t = this._abortAlgorithm(e);return N(this), t; - }[P]() { - v(this); - } - }function $(e, t, r, o, n, i, a, s) { - t._controlledWritableStream = e, e._writableStreamController = t, t._queue = void 0, t._queueTotalSize = void 0, v(t), t._started = !1, t._strategySizeAlgorithm = s, t._strategyHWM = a, t._writeAlgorithm = o, t._closeAlgorithm = n, t._abortAlgorithm = i;const l = U(t);k(e, l);const c = r();Promise.resolve(c).then(() => { - t._started = !0, x(t); - }, r => { - t._started = !0, A(e, r); - }).catch(w); - }function N(e) { - e._writeAlgorithm = void 0, e._closeAlgorithm = void 0, e._abortAlgorithm = void 0, e._strategySizeAlgorithm = void 0; - }function Q(e) { - return e._strategyHWM - e._queueTotalSize; - }function x(e) { - const t = e._controlledWritableStream;if (!1 === e._started) return;if (void 0 !== t._inFlightWriteRequest) return;const r = t._state;if ("closed" === r || "errored" === r) return;if ("erroring" === r) return void B(t);if (0 === e._queue.length) return;const o = function (e) { - return e._queue[0].value; - }(e);"close" === o ? function (e) { - const t = e._controlledWritableStream;(function (e) { - e._inFlightCloseRequest = e._closeRequest, e._closeRequest = void 0; - })(t), g(e);const r = e._closeAlgorithm();N(e), r.then(() => { - !function (e) { - e._inFlightCloseRequest._resolve(void 0), e._inFlightCloseRequest = void 0, "erroring" === e._state && (e._storedError = void 0, void 0 !== e._pendingAbortRequest && (e._pendingAbortRequest._resolve(), e._pendingAbortRequest = void 0)), e._state = "closed";const t = e._writer;void 0 !== t && te(t); - }(t); - }, e => { - !function (e, t) { - e._inFlightCloseRequest._reject(t), e._inFlightCloseRequest = void 0, void 0 !== e._pendingAbortRequest && (e._pendingAbortRequest._reject(t), e._pendingAbortRequest = void 0), A(e, t); - }(t, e); - }).catch(w); - }(e) : function (e, t) { - const r = e._controlledWritableStream;(function (e) { - e._inFlightWriteRequest = e._writeRequests.shift(); - })(r), e._writeAlgorithm(t).then(() => { - !function (e) { - e._inFlightWriteRequest._resolve(void 0), e._inFlightWriteRequest = void 0; - }(r);const t = r._state;if (g(e), !1 === O(r) && "writable" === t) { - const t = U(e);k(r, t); - }x(e); - }, t => { - "writable" === r._state && N(e), function (e, t) { - e._inFlightWriteRequest._reject(t), e._inFlightWriteRequest = void 0, A(e, t); - }(r, t); - }).catch(w); - }(e, o.chunk); - }function H(e, t) { - "writable" === e._controlledWritableStream._state && V(e, t); - }function U(e) { - return Q(e) <= 0; - }function V(e, t) { - const r = e._controlledWritableStream;N(e), W(r, t); - }function G(e) { - return new TypeError(`WritableStream.prototype.${e} can only be used on a WritableStream`); - }function J(e) { - return new TypeError(`WritableStreamDefaultWriter.prototype.${e} can only be used on a WritableStreamDefaultWriter`); - }function K(e) { - return new TypeError("Cannot " + e + " a stream using a released writer"); - }function X(e) { - e._closedPromise = new Promise((t, r) => { - e._closedPromise_resolve = t, e._closedPromise_reject = r, e._closedPromiseState = "pending"; - }); - }function Z(e, t) { - X(e), ee(e, t); - }function ee(e, t) { - e._closedPromise.catch(() => {}), e._closedPromise_reject(t), e._closedPromise_resolve = void 0, e._closedPromise_reject = void 0, e._closedPromiseState = "rejected"; - }function te(e) { - e._closedPromise_resolve(void 0), e._closedPromise_resolve = void 0, e._closedPromise_reject = void 0, e._closedPromiseState = "resolved"; - }function re(e) { - e._readyPromise = new Promise((t, r) => { - e._readyPromise_resolve = t, e._readyPromise_reject = r; - }), e._readyPromiseState = "pending"; - }function oe(e, t) { - re(e), ie(e, t); - }function ne(e) { - re(e), ae(e); - }function ie(e, t) { - e._readyPromise.catch(() => {}), e._readyPromise_reject(t), e._readyPromise_resolve = void 0, e._readyPromise_reject = void 0, e._readyPromiseState = "rejected"; - }function ae(e) { - e._readyPromise_resolve(void 0), e._readyPromise_resolve = void 0, e._readyPromise_reject = void 0, e._readyPromiseState = "fulfilled"; - }const se = Number.isInteger || function (e) { - return "number" == typeof e && isFinite(e) && Math.floor(e) === e; - }, - le = t("[[CancelSteps]]"), - ce = t("[[PullSteps]]");class ReadableStream { - constructor(e = {}, t = {}) { - fe(this);const r = t.size;let o = t.highWaterMark;const n = e.type;if ("bytes" === String(n)) { - if (void 0 !== r) throw new RangeError("The strategy for a byte stream cannot have a size function");void 0 === o && (o = 0), function (e, t, r) { - const o = Object.create(ReadableByteStreamController.prototype);const n = u(t, "pull", 0, [o]), - i = u(t, "cancel", 1, []);let a = t.autoAllocateChunkSize;if (void 0 !== a && (a = Number(a), !1 === se(a) || a <= 0)) throw new RangeError("autoAllocateChunkSize must be a positive integer");!function (e, t, r, o, n, i, a) { - t._controlledReadableByteStream = e, t._pullAgain = !1, t._pulling = !1, He(t), t._queue = t._queueTotalSize = void 0, v(t), t._closeRequested = !1, t._started = !1, t._strategyHWM = h(i), t._pullAlgorithm = o, t._cancelAlgorithm = n, t._autoAllocateChunkSize = a, t._pendingPullIntos = [], e._readableStreamController = t;const s = r();Promise.resolve(s).then(() => { - t._started = !0, xe(t); - }, e => { - nt(t, e); - }).catch(w); - }(e, o, function () { - return d(t, "start", [o]); - }, n, i, r, a); - }(this, e, o = h(o)); - } else { - if (void 0 !== n) throw new RangeError("Invalid type is specified");{ - const t = b(r);void 0 === o && (o = 1), function (e, t, r, o) { - const n = Object.create(ReadableStreamDefaultController.prototype);const i = u(t, "pull", 0, [n]), - a = u(t, "cancel", 1, []);$e(e, n, function () { - return d(t, "start", [n]); - }, i, a, r, o); - }(this, e, o = h(o), t); - } - } - }get locked() { - if (!1 === _e(this)) throw st("locked");return he(this); - }cancel(e) { - return !1 === _e(this) ? Promise.reject(st("cancel")) : !0 === he(this) ? Promise.reject(new TypeError("Cannot cancel a stream that already has a reader")) : pe(this, e); - }getReader({ mode: e } = {}) { - if (!1 === _e(this)) throw st("getReader");if (void 0 === e) return ue(this);if ("byob" === (e = String(e))) return function (e) { - return new ReadableStreamBYOBReader(e); - }(this);throw new RangeError("Invalid mode is specified"); - }pipeThrough({ writable: e, readable: t }, { preventClose: r, preventAbort: o, preventCancel: n, signal: i } = {}) { - if (!1 === _e(this)) throw st("pipeThrough");if (!1 === E(e)) throw new TypeError("writable argument to pipeThrough must be a WritableStream");if (!1 === _e(t)) throw new TypeError("readable argument to pipeThrough must be a ReadableStream");if (r = Boolean(r), o = Boolean(o), n = Boolean(n), void 0 !== i && !at(i)) throw new TypeError("ReadableStream.prototype.pipeThrough's signal option must be an AbortSignal");if (!0 === he(this)) throw new TypeError("ReadableStream.prototype.pipeThrough cannot be used on a locked ReadableStream");if (!0 === C(e)) throw new TypeError("ReadableStream.prototype.pipeThrough cannot be used on a locked WritableStream");return be(this, e, r, o, n, i).catch(() => {}), t; - }pipeTo(e, { preventClose: t, preventAbort: r, preventCancel: o, signal: n } = {}) { - return !1 === _e(this) ? Promise.reject(st("pipeTo")) : !1 === E(e) ? Promise.reject(new TypeError("ReadableStream.prototype.pipeTo's first argument must be a WritableStream")) : (t = Boolean(t), r = Boolean(r), o = Boolean(o), void 0 === n || at(n) ? !0 === he(this) ? Promise.reject(new TypeError("ReadableStream.prototype.pipeTo cannot be used on a locked ReadableStream")) : !0 === C(e) ? Promise.reject(new TypeError("ReadableStream.prototype.pipeTo cannot be used on a locked WritableStream")) : be(this, e, t, r, o, n) : Promise.reject(new TypeError("ReadableStream.prototype.pipeTo's signal option must be an AbortSignal"))); - }tee() { - if (!1 === _e(this)) throw st("tee");const e = function (e, t) { - const r = ue(e);let o, - n, - i, - s, - l, - c = !1, - u = !1, - d = !1;const f = new Promise(e => { - l = e; - });function _() { - return Be(r).then(e => { - const t = e.value, - r = e.done;if (!0 === r && !1 === c && (!1 === u && Le(i._readableStreamController), !1 === d && Le(s._readableStreamController), c = !0), !0 === c) return;const o = t, - n = t;!1 === u && Ie(i._readableStreamController, o), !1 === d && Ie(s._readableStreamController, n); - }); - }function h() {}return i = de(h, _, function (t) { - if (u = !0, o = t, !0 === d) { - const t = a([o, n]), - r = pe(e, t);l(r); - }return f; - }), s = de(h, _, function (t) { - if (d = !0, n = t, !0 === u) { - const t = a([o, n]), - r = pe(e, t);l(r); - }return f; - }), r._closedPromise.catch(e => { - !0 !== c && (De(i._readableStreamController, e), De(s._readableStreamController, e), c = !0); - }), [i, s]; - }(this);return a(e); - } - }function ue(e) { - return new ReadableStreamDefaultReader(e); - }function de(e, t, r, o = 1, n = () => 1) { - const i = Object.create(ReadableStream.prototype);return fe(i), $e(i, Object.create(ReadableStreamDefaultController.prototype), e, t, r, o, n), i; - }function fe(e) { - e._state = "readable", e._reader = void 0, e._storedError = void 0, e._disturbed = !1; - }function _e(e) { - return !!n(e) && !!Object.prototype.hasOwnProperty.call(e, "_readableStreamController"); - }function he(e) { - return void 0 !== e._reader; - }function be(e, t, r, o, n, i) { - const a = ue(e), - s = T(t);let l = !1, - c = Promise.resolve();return new Promise((u, d) => { - let f;if (void 0 !== i) { - if (f = () => { - const r = new DOMException("Aborted", "AbortError"), - i = [];!1 === o && i.push(() => "writable" === t._state ? j(t, r) : Promise.resolve()), !1 === n && i.push(() => "readable" === e._state ? pe(e, r) : Promise.resolve()), b(() => y(i.map(e => e()), e => e), !0, r); - }, !0 === i.aborted) return void f();i.addEventListener("abort", f); - }if (h(e, a._closedPromise, e => { - !1 === o ? b(() => j(t, e), !0, e) : m(!0, e); - }), h(t, s._closedPromise, t => { - !1 === n ? b(() => pe(e, t), !0, t) : m(!0, t); - }), function (e, t, r) { - "closed" === e._state ? r() : t.then(r).catch(w); - }(e, a._closedPromise, () => { - !1 === r ? b(() => function (e) { - const t = e._ownerWritableStream, - r = t._state;return !0 === O(t) || "closed" === r ? Promise.resolve() : "errored" === r ? Promise.reject(t._storedError) : L(e); - }(s)) : m(); - }), !0 === O(t) || "closed" === t._state) { - const t = new TypeError("the destination writable stream closed before all data could be piped to it");!1 === n ? b(() => pe(e, t), !0, t) : m(!0, t); - }function _() { - const e = c;return c.then(() => e !== c ? _() : void 0); - }function h(e, t, r) { - "errored" === e._state ? r(e._storedError) : t.catch(r).catch(w); - }function b(e, r, o) { - function n() { - e().then(() => p(r, o), e => p(!0, e)).catch(w); - }!0 !== l && (l = !0, "writable" === t._state && !1 === O(t) ? _().then(n) : n()); - }function m(e, r) { - !0 !== l && (l = !0, "writable" === t._state && !1 === O(t) ? _().then(() => p(e, r)).catch(w) : p(e, r)); - }function p(e, t) { - M(s), We(a), void 0 !== i && i.removeEventListener("abort", f), e ? d(t) : u(void 0); - }new Promise((e, t) => { - !function r(o) { - o ? e() : (!0 === l ? Promise.resolve(!0) : s._readyPromise.then(() => Be(a).then(({ value: e, done: t }) => !0 === t || (c = Y(s, e).catch(() => {}), !1)))).then(r, t); - }(!1); - }).catch(e => { - c = Promise.resolve(), w(e); - }); - }); - }function me(e, t) { - return new Promise((r, o) => { - const n = { _resolve: r, _reject: o, _forAuthorCode: t };e._reader._readIntoRequests.push(n); - }); - }function ye(e, t) { - return new Promise((r, o) => { - const n = { _resolve: r, _reject: o, _forAuthorCode: t };e._reader._readRequests.push(n); - }); - }function pe(e, t) { - if (e._disturbed = !0, "closed" === e._state) return Promise.resolve(void 0);if ("errored" === e._state) return Promise.reject(e._storedError);return we(e), e._readableStreamController[le](t).then(() => void 0); - }function we(e) { - e._state = "closed";const t = e._reader;if (void 0 !== t) { - if (Ce(t)) { - for (const _ref of t._readRequests) { - const e = _ref._resolve; - const r = _ref._forAuthorCode; - e(ge(void 0, !0, r)); - }t._readRequests = []; - }_t(t); - } - }function ge(e, t, r) { - let o = null;!0 === r && (o = Object.prototype);const n = Object.create(o);return Object.defineProperty(n, "value", { value: e, enumerable: !0, writable: !0, configurable: !0 }), Object.defineProperty(n, "done", { value: t, enumerable: !0, writable: !0, configurable: !0 }), n; - }function Se(e, t) { - e._state = "errored", e._storedError = t;const r = e._reader;if (void 0 !== r) { - if (Ce(r)) { - for (const e of r._readRequests) e._reject(t);r._readRequests = []; - } else { - for (const e of r._readIntoRequests) e._reject(t);r._readIntoRequests = []; - }ft(r, t); - } - }function ve(e, t, r) { - const o = e._reader._readRequests.shift();o._resolve(ge(t, r, o._forAuthorCode)); - }function Re(e) { - return e._reader._readIntoRequests.length; - }function Pe(e) { - return e._reader._readRequests.length; - }function Te(e) { - const t = e._reader;return void 0 !== t && !!Ee(t); - }function qe(e) { - const t = e._reader;return void 0 !== t && !!Ce(t); - }class ReadableStreamDefaultReader { - constructor(e) { - if (!1 === _e(e)) throw new TypeError("ReadableStreamDefaultReader can only be constructed with a ReadableStream instance");if (!0 === he(e)) throw new TypeError("This stream has already been locked for exclusive reading by another reader");je(this, e), this._readRequests = []; - }get closed() { - return Ce(this) ? this._closedPromise : Promise.reject(ct("closed")); - }cancel(e) { - return Ce(this) ? void 0 === this._ownerReadableStream ? Promise.reject(lt("cancel")) : Ae(this, e) : Promise.reject(ct("cancel")); - }read() { - return Ce(this) ? void 0 === this._ownerReadableStream ? Promise.reject(lt("read from")) : Be(this, !0) : Promise.reject(ct("read")); - }releaseLock() { - if (!Ce(this)) throw ct("releaseLock");if (void 0 !== this._ownerReadableStream) { - if (this._readRequests.length > 0) throw new TypeError("Tried to release a reader lock when that reader has pending read() calls un-settled");We(this); - } - } - }class ReadableStreamBYOBReader { - constructor(e) { - if (!_e(e)) throw new TypeError("ReadableStreamBYOBReader can only be constructed with a ReadableStream instance given a byte source");if (!1 === Ne(e._readableStreamController)) throw new TypeError("Cannot construct a ReadableStreamBYOBReader for a stream not constructed with a byte source");if (he(e)) throw new TypeError("This stream has already been locked for exclusive reading by another reader");je(this, e), this._readIntoRequests = []; - }get closed() { - return Ee(this) ? this._closedPromise : Promise.reject(ht("closed")); - }cancel(e) { - return Ee(this) ? void 0 === this._ownerReadableStream ? Promise.reject(lt("cancel")) : Ae(this, e) : Promise.reject(ht("cancel")); - }read(e) { - return Ee(this) ? void 0 === this._ownerReadableStream ? Promise.reject(lt("read from")) : ArrayBuffer.isView(e) ? (e.buffer, 0 === e.byteLength ? Promise.reject(new TypeError("view must have non-zero byteLength")) : function (e, t, r = !1) { - const o = e._ownerReadableStream;if (o._disturbed = !0, "errored" === o._state) return Promise.reject(o._storedError);return function (e, t, r) { - const o = e._controlledReadableByteStream;let n = 1;t.constructor !== DataView && (n = t.constructor.BYTES_PER_ELEMENT);const i = t.constructor, - a = { buffer: _(t.buffer), byteOffset: t.byteOffset, byteLength: t.byteLength, bytesFilled: 0, elementSize: n, ctor: i, readerType: "byob" };if (e._pendingPullIntos.length > 0) return e._pendingPullIntos.push(a), me(o, r);if ("closed" === o._state) { - const e = new i(a.buffer, a.byteOffset, 0);return Promise.resolve(ge(e, !0, r)); - }if (e._queueTotalSize > 0) { - if (!0 === Je(e, a)) { - const t = Ve(a);return Xe(e), Promise.resolve(ge(t, !1, r)); - }if (!0 === e._closeRequested) { - const t = new TypeError("Insufficient bytes to fill elements in the given buffer");return nt(e, t), Promise.reject(t); - } - }e._pendingPullIntos.push(a);const s = me(o, r);return xe(e), s; - }(o._readableStreamController, t, r); - }(this, e, !0)) : Promise.reject(new TypeError("view must be an array buffer view")) : Promise.reject(ht("read")); - }releaseLock() { - if (!Ee(this)) throw ht("releaseLock");if (void 0 !== this._ownerReadableStream) { - if (this._readIntoRequests.length > 0) throw new TypeError("Tried to release a reader lock when that reader has pending read() calls un-settled");We(this); - } - } - }function Ee(e) { - return !!n(e) && !!Object.prototype.hasOwnProperty.call(e, "_readIntoRequests"); - }function Ce(e) { - return !!n(e) && !!Object.prototype.hasOwnProperty.call(e, "_readRequests"); - }function je(e, t) { - e._ownerReadableStream = t, t._reader = e, "readable" === t._state ? ut(e) : "closed" === t._state ? function (e) { - ut(e), _t(e); - }(e) : dt(e, t._storedError); - }function Ae(e, t) { - return pe(e._ownerReadableStream, t); - }function We(e) { - "readable" === e._ownerReadableStream._state ? ft(e, new TypeError("Reader was released and can no longer be used to monitor the stream's closedness")) : function (e, t) { - dt(e, t); - }(e, new TypeError("Reader was released and can no longer be used to monitor the stream's closedness")), e._ownerReadableStream._reader = void 0, e._ownerReadableStream = void 0; - }function Be(e, t = !1) { - const r = e._ownerReadableStream;return r._disturbed = !0, "closed" === r._state ? Promise.resolve(ge(void 0, !0, t)) : "errored" === r._state ? Promise.reject(r._storedError) : r._readableStreamController[ce](t); - }class ReadableStreamDefaultController { - constructor() { - throw new TypeError(); - }get desiredSize() { - if (!1 === Oe(this)) throw bt("desiredSize");return Me(this); - }close() { - if (!1 === Oe(this)) throw bt("close");if (!1 === Ye(this)) throw new TypeError("The stream is not in a state that permits close");Le(this); - }enqueue(e) { - if (!1 === Oe(this)) throw bt("enqueue");if (!1 === Ye(this)) throw new TypeError("The stream is not in a state that permits enqueue");return Ie(this, e); - }error(e) { - if (!1 === Oe(this)) throw bt("error");De(this, e); - }[le](e) { - v(this);const t = this._cancelAlgorithm(e);return Fe(this), t; - }[ce](e) { - const t = this._controlledReadableStream;if (this._queue.length > 0) { - const r = g(this);return !0 === this._closeRequested && 0 === this._queue.length ? (Fe(this), we(t)) : ze(this), Promise.resolve(ge(r, !1, e)); - }const r = ye(t, e);return ze(this), r; - } - }function Oe(e) { - return !!n(e) && !!Object.prototype.hasOwnProperty.call(e, "_controlledReadableStream"); - }function ze(e) { - !1 !== ke(e) && (!0 !== e._pulling ? (e._pulling = !0, e._pullAlgorithm().then(() => { - if (e._pulling = !1, !0 === e._pullAgain) return e._pullAgain = !1, ze(e); - }, t => { - De(e, t); - }).catch(w)) : e._pullAgain = !0); - }function ke(e) { - const t = e._controlledReadableStream;return !1 !== Ye(e) && !1 !== e._started && (!0 === he(t) && Pe(t) > 0 || Me(e) > 0); - }function Fe(e) { - e._pullAlgorithm = void 0, e._cancelAlgorithm = void 0, e._strategySizeAlgorithm = void 0; - }function Le(e) { - const t = e._controlledReadableStream;e._closeRequested = !0, 0 === e._queue.length && (Fe(e), we(t)); - }function Ie(e, t) { - const r = e._controlledReadableStream;if (!0 === he(r) && Pe(r) > 0) ve(r, t, !1);else { - let r;try { - r = e._strategySizeAlgorithm(t); - } catch (t) { - throw De(e, t), t; - }try { - S(e, t, r); - } catch (t) { - throw De(e, t), t; - } - }ze(e); - }function De(e, t) { - const r = e._controlledReadableStream;"readable" === r._state && (v(e), Fe(e), Se(r, t)); - }function Me(e) { - const t = e._controlledReadableStream._state;return "errored" === t ? null : "closed" === t ? 0 : e._strategyHWM - e._queueTotalSize; - }function Ye(e) { - const t = e._controlledReadableStream._state;return !1 === e._closeRequested && "readable" === t; - }function $e(e, t, r, o, n, i, a) { - t._controlledReadableStream = e, t._queue = void 0, t._queueTotalSize = void 0, v(t), t._started = !1, t._closeRequested = !1, t._pullAgain = !1, t._pulling = !1, t._strategySizeAlgorithm = a, t._strategyHWM = i, t._pullAlgorithm = o, t._cancelAlgorithm = n, e._readableStreamController = t;const s = r();Promise.resolve(s).then(() => { - t._started = !0, ze(t); - }, e => { - De(t, e); - }).catch(w); - }class ReadableStreamBYOBRequest { - constructor() { - throw new TypeError("ReadableStreamBYOBRequest cannot be used directly"); - }get view() { - if (!1 === Qe(this)) throw mt("view");return this._view; - }respond(e) { - if (!1 === Qe(this)) throw mt("respond");if (void 0 === this._associatedReadableByteStreamController) throw new TypeError("This BYOB request has been invalidated");this._view.buffer, function (e, t) { - if (!1 === l(t = Number(t))) throw new RangeError("bytesWritten must be a finite");tt(e, t); - }(this._associatedReadableByteStreamController, e); - }respondWithNewView(e) { - if (!1 === Qe(this)) throw mt("respond");if (void 0 === this._associatedReadableByteStreamController) throw new TypeError("This BYOB request has been invalidated");if (!ArrayBuffer.isView(e)) throw new TypeError("You can only respond with array buffer views");e.buffer, function (e, t) { - const r = e._pendingPullIntos[0];if (r.byteOffset + r.bytesFilled !== t.byteOffset) throw new RangeError("The region specified by view does not match byobRequest");if (r.byteLength !== t.byteLength) throw new RangeError("The buffer of view has different capacity than byobRequest");r.buffer = t.buffer, tt(e, t.byteLength); - }(this._associatedReadableByteStreamController, e); - } - }class ReadableByteStreamController { - constructor() { - throw new TypeError("ReadableByteStreamController constructor cannot be used directly"); - }get byobRequest() { - if (!1 === Ne(this)) throw yt("byobRequest");if (void 0 === this._byobRequest && this._pendingPullIntos.length > 0) { - const e = this._pendingPullIntos[0], - t = new Uint8Array(e.buffer, e.byteOffset + e.bytesFilled, e.byteLength - e.bytesFilled), - r = Object.create(ReadableStreamBYOBRequest.prototype);!function (e, t, r) { - e._associatedReadableByteStreamController = t, e._view = r; - }(r, this, t), this._byobRequest = r; - }return this._byobRequest; - }get desiredSize() { - if (!1 === Ne(this)) throw yt("desiredSize");return it(this); - }close() { - if (!1 === Ne(this)) throw yt("close");if (!0 === this._closeRequested) throw new TypeError("The stream has already been closed; do not close it again!");const e = this._controlledReadableByteStream._state;if ("readable" !== e) throw new TypeError(`The stream (in ${e} state) is not in the readable state and cannot be closed`);!function (e) { - const t = e._controlledReadableByteStream;if (e._queueTotalSize > 0) return void (e._closeRequested = !0);if (e._pendingPullIntos.length > 0) { - const t = e._pendingPullIntos[0];if (t.bytesFilled > 0) { - const t = new TypeError("Insufficient bytes to fill elements in the given buffer");throw nt(e, t), t; - } - }ot(e), we(t); - }(this); - }enqueue(e) { - if (!1 === Ne(this)) throw yt("enqueue");if (!0 === this._closeRequested) throw new TypeError("stream is closed or draining");const t = this._controlledReadableByteStream._state;if ("readable" !== t) throw new TypeError(`The stream (in ${t} state) is not in the readable state and cannot be enqueued to`);if (!ArrayBuffer.isView(e)) throw new TypeError("You can only enqueue array buffer views when using a ReadableByteStreamController");e.buffer, function (e, t) { - const r = e._controlledReadableByteStream, - o = t.buffer, - n = t.byteOffset, - i = t.byteLength, - a = _(o);if (!0 === qe(r)) { - if (0 === Pe(r)) Ge(e, a, n, i);else { - const e = new Uint8Array(a, n, i);ve(r, e, !1); - } - } else !0 === Te(r) ? (Ge(e, a, n, i), et(e)) : Ge(e, a, n, i);xe(e); - }(this, e); - }error(e) { - if (!1 === Ne(this)) throw yt("error");nt(this, e); - }[le](e) { - if (this._pendingPullIntos.length > 0) { - this._pendingPullIntos[0].bytesFilled = 0; - }v(this);const t = this._cancelAlgorithm(e);return ot(this), t; - }[ce](e) { - const t = this._controlledReadableByteStream;if (this._queueTotalSize > 0) { - const t = this._queue.shift();let r;this._queueTotalSize -= t.byteLength, Xe(this);try { - r = new Uint8Array(t.buffer, t.byteOffset, t.byteLength); - } catch (e) { - return Promise.reject(e); - }return Promise.resolve(ge(r, !1, e)); - }const r = this._autoAllocateChunkSize;if (void 0 !== r) { - let e;try { - e = new ArrayBuffer(r); - } catch (e) { - return Promise.reject(e); - }const t = { buffer: e, byteOffset: 0, byteLength: r, bytesFilled: 0, elementSize: 1, ctor: Uint8Array, readerType: "default" };this._pendingPullIntos.push(t); - }const o = ye(t, e);return xe(this), o; - } - }function Ne(e) { - return !!n(e) && !!Object.prototype.hasOwnProperty.call(e, "_controlledReadableByteStream"); - }function Qe(e) { - return !!n(e) && !!Object.prototype.hasOwnProperty.call(e, "_associatedReadableByteStreamController"); - }function xe(e) { - !1 !== function (e) { - const t = e._controlledReadableByteStream;if ("readable" !== t._state) return !1;if (!0 === e._closeRequested) return !1;if (!1 === e._started) return !1;if (!0 === qe(t) && Pe(t) > 0) return !0;if (!0 === Te(t) && Re(t) > 0) return !0;if (it(e) > 0) return !0;return !1; - }(e) && (!0 !== e._pulling ? (e._pulling = !0, e._pullAlgorithm().then(() => { - e._pulling = !1, !0 === e._pullAgain && (e._pullAgain = !1, xe(e)); - }, t => { - nt(e, t); - }).catch(w)) : e._pullAgain = !0); - }function He(e) { - Ze(e), e._pendingPullIntos = []; - }function Ue(e, t) { - let r = !1;"closed" === e._state && (r = !0);const o = Ve(t);"default" === t.readerType ? ve(e, o, r) : function (e, t, r) { - const o = e._reader._readIntoRequests.shift();o._resolve(ge(t, r, o._forAuthorCode)); - }(e, o, r); - }function Ve(e) { - const t = e.bytesFilled, - r = e.elementSize;return new e.ctor(e.buffer, e.byteOffset, t / r); - }function Ge(e, t, r, o) { - e._queue.push({ buffer: t, byteOffset: r, byteLength: o }), e._queueTotalSize += o; - }function Je(e, t) { - const r = t.elementSize, - o = t.bytesFilled - t.bytesFilled % r, - n = Math.min(e._queueTotalSize, t.byteLength - t.bytesFilled), - i = t.bytesFilled + n, - a = i - i % r;let l = n, - c = !1;a > o && (l = a - t.bytesFilled, c = !0);const u = e._queue;for (; l > 0;) { - const r = u[0], - o = Math.min(l, r.byteLength), - n = t.byteOffset + t.bytesFilled;s(t.buffer, n, r.buffer, r.byteOffset, o), r.byteLength === o ? u.shift() : (r.byteOffset += o, r.byteLength -= o), e._queueTotalSize -= o, Ke(e, o, t), l -= o; - }return c; - }function Ke(e, t, r) { - Ze(e), r.bytesFilled += t; - }function Xe(e) { - 0 === e._queueTotalSize && !0 === e._closeRequested ? (ot(e), we(e._controlledReadableByteStream)) : xe(e); - }function Ze(e) { - void 0 !== e._byobRequest && (e._byobRequest._associatedReadableByteStreamController = void 0, e._byobRequest._view = void 0, e._byobRequest = void 0); - }function et(e) { - for (; e._pendingPullIntos.length > 0;) { - if (0 === e._queueTotalSize) return;const t = e._pendingPullIntos[0];!0 === Je(e, t) && (rt(e), Ue(e._controlledReadableByteStream, t)); - } - }function tt(e, t) { - const r = e._pendingPullIntos[0];if ("closed" === e._controlledReadableByteStream._state) { - if (0 !== t) throw new TypeError("bytesWritten must be 0 when calling respond() on a closed stream");!function (e, t) { - t.buffer = _(t.buffer);const r = e._controlledReadableByteStream;if (!0 === Te(r)) for (; Re(r) > 0;) Ue(r, rt(e)); - }(e, r); - } else !function (e, t, r) { - if (r.bytesFilled + t > r.byteLength) throw new RangeError("bytesWritten out of range");if (Ke(e, t, r), r.bytesFilled < r.elementSize) return;rt(e);const o = r.bytesFilled % r.elementSize;if (o > 0) { - const t = r.byteOffset + r.bytesFilled, - n = r.buffer.slice(t - o, t);Ge(e, n, 0, n.byteLength); - }r.buffer = _(r.buffer), r.bytesFilled -= o, Ue(e._controlledReadableByteStream, r), et(e); - }(e, t, r);xe(e); - }function rt(e) { - const t = e._pendingPullIntos.shift();return Ze(e), t; - }function ot(e) { - e._pullAlgorithm = void 0, e._cancelAlgorithm = void 0; - }function nt(e, t) { - const r = e._controlledReadableByteStream;"readable" === r._state && (He(e), v(e), ot(e), Se(r, t)); - }function it(e) { - const t = e._controlledReadableByteStream._state;return "errored" === t ? null : "closed" === t ? 0 : e._strategyHWM - e._queueTotalSize; - }function at(e) { - if ("object" != typeof e || null === e) return !1;const t = Object.getOwnPropertyDescriptor(AbortSignal.prototype, "aborted").get;try { - return t.call(e), !0; - } catch (e) { - return !1; - } - }function st(e) { - return new TypeError(`ReadableStream.prototype.${e} can only be used on a ReadableStream`); - }function lt(e) { - return new TypeError("Cannot " + e + " a stream using a released reader"); - }function ct(e) { - return new TypeError(`ReadableStreamDefaultReader.prototype.${e} can only be used on a ReadableStreamDefaultReader`); - }function ut(e) { - e._closedPromise = new Promise((t, r) => { - e._closedPromise_resolve = t, e._closedPromise_reject = r; - }); - }function dt(e, t) { - ut(e), ft(e, t); - }function ft(e, t) { - e._closedPromise.catch(() => {}), e._closedPromise_reject(t), e._closedPromise_resolve = void 0, e._closedPromise_reject = void 0; - }function _t(e) { - e._closedPromise_resolve(void 0), e._closedPromise_resolve = void 0, e._closedPromise_reject = void 0; - }function ht(e) { - return new TypeError(`ReadableStreamBYOBReader.prototype.${e} can only be used on a ReadableStreamBYOBReader`); - }function bt(e) { - return new TypeError(`ReadableStreamDefaultController.prototype.${e} can only be used on a ReadableStreamDefaultController`); - }function mt(e) { - return new TypeError(`ReadableStreamBYOBRequest.prototype.${e} can only be used on a ReadableStreamBYOBRequest`); - }function yt(e) { - return new TypeError(`ReadableByteStreamController.prototype.${e} can only be used on a ReadableByteStreamController`); - }class ByteLengthQueuingStrategy { - constructor({ highWaterMark: e }) { - i(this, "highWaterMark", e); - }size(e) { - return e.byteLength; - } - }class CountQueuingStrategy { - constructor({ highWaterMark: e }) { - i(this, "highWaterMark", e); - }size() { - return 1; - } - }class TransformStream { - constructor(e = {}, t = {}, r = {}) { - const o = t.size;let n = t.highWaterMark;const i = r.size;let a = r.highWaterMark;if (void 0 !== e.writableType) throw new RangeError("Invalid writable type specified");const s = b(o);if (void 0 === n && (n = 1), n = h(n), void 0 !== e.readableType) throw new RangeError("Invalid readable type specified");const l = b(i);let c;void 0 === a && (a = 0), a = h(a), function (e, t, r, o, n, i) { - function a() { - return t; - }e._writable = function (e, t, r, o, n = 1, i = () => 1) { - const a = Object.create(WritableStream.prototype);return q(a), $(a, Object.create(WritableStreamDefaultController.prototype), e, t, r, o, n, i), a; - }(a, function (t) { - return function (e, t) { - const r = e._transformStreamController;if (!0 === e._backpressure) { - const o = e._backpressureChangePromise;return o.then(() => { - const o = e._writable, - n = o._state;if ("erroring" === n) throw o._storedError;return Tt(r, t); - }); - }return Tt(r, t); - }(e, t); - }, function () { - return function (e) { - const t = e._readable, - r = e._transformStreamController, - o = r._flushAlgorithm();return Rt(r), o.then(() => { - if ("errored" === t._state) throw t._storedError;const e = t._readableStreamController;!0 === Ye(e) && Le(e); - }).catch(r => { - throw wt(e, r), t._storedError; - }); - }(e); - }, function (t) { - return function (e, t) { - return wt(e, t), Promise.resolve(); - }(e, t); - }, r, o), e._readable = de(a, function () { - return function (e) { - return St(e, !1), e._backpressureChangePromise; - }(e); - }, function (t) { - return gt(e, t), Promise.resolve(); - }, n, i), e._backpressure = void 0, e._backpressureChangePromise = void 0, e._backpressureChangePromise_resolve = void 0, St(e, !0), e._transformStreamController = void 0; - }(this, new Promise(e => { - c = e; - }), n, s, a, l), function (e, t) { - const r = Object.create(TransformStreamDefaultController.prototype);let o = e => { - try { - return Pt(r, e), Promise.resolve(); - } catch (e) { - return Promise.reject(e); - } - };const n = t.transform;if (void 0 !== n) { - if ("function" != typeof n) throw new TypeError("transform is not a method");o = e => f(n, t, [e, r]); - }const i = u(t, "flush", 0, [r]);!function (e, t, r, o) { - t._controlledTransformStream = e, e._transformStreamController = t, t._transformAlgorithm = r, t._flushAlgorithm = o; - }(e, r, o, i); - }(this, e);const _ = d(e, "start", [this._transformStreamController]);c(_); - }get readable() { - if (!1 === pt(this)) throw Et("readable");return this._readable; - }get writable() { - if (!1 === pt(this)) throw Et("writable");return this._writable; - } - }function pt(e) { - return !!n(e) && !!Object.prototype.hasOwnProperty.call(e, "_transformStreamController"); - }function wt(e, t) { - De(e._readable._readableStreamController, t), gt(e, t); - }function gt(e, t) { - Rt(e._transformStreamController), H(e._writable._writableStreamController, t), !0 === e._backpressure && St(e, !1); - }function St(e, t) { - void 0 !== e._backpressureChangePromise && e._backpressureChangePromise_resolve(), e._backpressureChangePromise = new Promise(t => { - e._backpressureChangePromise_resolve = t; - }), e._backpressure = t; - }class TransformStreamDefaultController { - constructor() { - throw new TypeError("TransformStreamDefaultController instances cannot be created directly"); - }get desiredSize() { - if (!1 === vt(this)) throw qt("desiredSize");return Me(this._controlledTransformStream._readable._readableStreamController); - }enqueue(e) { - if (!1 === vt(this)) throw qt("enqueue");Pt(this, e); - }error(e) { - if (!1 === vt(this)) throw qt("error");!function (e, t) { - wt(e._controlledTransformStream, t); - }(this, e); - }terminate() { - if (!1 === vt(this)) throw qt("terminate");!function (e) { - const t = e._controlledTransformStream, - r = t._readable._readableStreamController;!0 === Ye(r) && Le(r);const o = new TypeError("TransformStream terminated");gt(t, o); - }(this); - } - }function vt(e) { - return !!n(e) && !!Object.prototype.hasOwnProperty.call(e, "_controlledTransformStream"); - }function Rt(e) { - e._transformAlgorithm = void 0, e._flushAlgorithm = void 0; - }function Pt(e, t) { - const r = e._controlledTransformStream, - o = r._readable._readableStreamController;if (!1 === Ye(o)) throw new TypeError("Readable side is not in a state that permits enqueue");try { - Ie(o, t); - } catch (e) { - throw gt(r, e), r._readable._storedError; - }(function (e) { - return !0 !== ke(e); - })(o) !== r._backpressure && St(r, !0); - }function Tt(e, t) { - return e._transformAlgorithm(t).catch(t => { - throw wt(e._controlledTransformStream, t), t; - }); - }function qt(e) { - return new TypeError(`TransformStreamDefaultController.prototype.${e} can only be used on a TransformStreamDefaultController`); - }function Et(e) { - return new TypeError(`TransformStream.prototype.${e} can only be used on a TransformStream`); - }const Ct = { ReadableStream: ReadableStream, WritableStream: WritableStream, ByteLengthQueuingStrategy: ByteLengthQueuingStrategy, CountQueuingStrategy: CountQueuingStrategy, TransformStream: TransformStream };void 0 !== r && Object.assign(r, Ct), e.ReadableStream = ReadableStream, e.WritableStream = WritableStream, e.ByteLengthQueuingStrategy = ByteLengthQueuingStrategy, e.CountQueuingStrategy = CountQueuingStrategy, e.TransformStream = TransformStream, Object.defineProperty(e, "__esModule", { value: !0 }); -}); - - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],2:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -/** - * @file {@link http://asmjs.org Asm.js} implementation of the {@link https://en.wikipedia.org/wiki/Advanced_Encryption_Standard Advanced Encryption Standard}. - * @author Artem S Vybornov - * @license MIT - */ -var AES_asm = exports.AES_asm = function () { - "use strict"; - - /** - * Galois Field stuff init flag - */ - - var ginit_done = false; - - /** - * Galois Field exponentiation and logarithm tables for 3 (the generator) - */ - var gexp3, glog3; - - /** - * Init Galois Field tables - */ - function ginit() { - gexp3 = [], glog3 = []; - - var a = 1, - c, - d; - for (c = 0; c < 255; c++) { - gexp3[c] = a; - - // Multiply by three - d = a & 0x80, a <<= 1, a &= 255; - if (d === 0x80) a ^= 0x1b; - a ^= gexp3[c]; - - // Set the log table value - glog3[gexp3[c]] = c; - } - gexp3[255] = gexp3[0]; - glog3[0] = 0; - - ginit_done = true; - } - - /** - * Galois Field multiplication - * @param {number} a - * @param {number} b - * @return {number} - */ - function gmul(a, b) { - var c = gexp3[(glog3[a] + glog3[b]) % 255]; - if (a === 0 || b === 0) c = 0; - return c; - } - - /** - * Galois Field reciprocal - * @param {number} a - * @return {number} - */ - function ginv(a) { - var i = gexp3[255 - glog3[a]]; - if (a === 0) i = 0; - return i; - } - - /** - * AES stuff init flag - */ - var aes_init_done = false; - - /** - * Encryption, Decryption, S-Box and KeyTransform tables - * - * @type {number[]} - */ - var aes_sbox; - - /** - * @type {number[]} - */ - var aes_sinv; - - /** - * @type {number[][]} - */ - var aes_enc; - - /** - * @type {number[][]} - */ - var aes_dec; - - /** - * Init AES tables - */ - function aes_init() { - if (!ginit_done) ginit(); - - // Calculates AES S-Box value - function _s(a) { - var c, s, x; - s = x = ginv(a); - for (c = 0; c < 4; c++) { - s = (s << 1 | s >>> 7) & 255; - x ^= s; - } - x ^= 99; - return x; - } - - // Tables - aes_sbox = [], aes_sinv = [], aes_enc = [[], [], [], []], aes_dec = [[], [], [], []]; - - for (var i = 0; i < 256; i++) { - var s = _s(i); - - // S-Box and its inverse - aes_sbox[i] = s; - aes_sinv[s] = i; - - // Ecryption and Decryption tables - aes_enc[0][i] = gmul(2, s) << 24 | s << 16 | s << 8 | gmul(3, s); - aes_dec[0][s] = gmul(14, i) << 24 | gmul(9, i) << 16 | gmul(13, i) << 8 | gmul(11, i); - // Rotate tables - for (var t = 1; t < 4; t++) { - aes_enc[t][i] = aes_enc[t - 1][i] >>> 8 | aes_enc[t - 1][i] << 24; - aes_dec[t][s] = aes_dec[t - 1][s] >>> 8 | aes_dec[t - 1][s] << 24; - } - } - - aes_init_done = true; - } - - /** - * Asm.js module constructor. - * - *

- * Heap buffer layout by offset: - *

-   * 0x0000   encryption key schedule
-   * 0x0400   decryption key schedule
-   * 0x0800   sbox
-   * 0x0c00   inv sbox
-   * 0x1000   encryption tables
-   * 0x2000   decryption tables
-   * 0x3000   reserved (future GCM multiplication lookup table)
-   * 0x4000   data
-   * 
- * Don't touch anything before 0x400. - *

- * - * @alias AES_asm - * @class - * @param foreign - ignored - * @param buffer - heap buffer to link with - */ - var wrapper = function wrapper(foreign, buffer) { - // Init AES stuff for the first time - if (!aes_init_done) aes_init(); - - // Fill up AES tables - var heap = new Uint32Array(buffer); - heap.set(aes_sbox, 0x0800 >> 2); - heap.set(aes_sinv, 0x0c00 >> 2); - for (var i = 0; i < 4; i++) { - heap.set(aes_enc[i], 0x1000 + 0x400 * i >> 2); - heap.set(aes_dec[i], 0x2000 + 0x400 * i >> 2); - } - - /** - * Calculate AES key schedules. - * @instance - * @memberof AES_asm - * @param {number} ks - key size, 4/6/8 (for 128/192/256-bit key correspondingly) - * @param {number} k0 - key vector components - * @param {number} k1 - key vector components - * @param {number} k2 - key vector components - * @param {number} k3 - key vector components - * @param {number} k4 - key vector components - * @param {number} k5 - key vector components - * @param {number} k6 - key vector components - * @param {number} k7 - key vector components - */ - function set_key(ks, k0, k1, k2, k3, k4, k5, k6, k7) { - var ekeys = heap.subarray(0x000, 60), - dkeys = heap.subarray(0x100, 0x100 + 60); - - // Encryption key schedule - ekeys.set([k0, k1, k2, k3, k4, k5, k6, k7]); - for (var i = ks, rcon = 1; i < 4 * ks + 28; i++) { - var k = ekeys[i - 1]; - if (i % ks === 0 || ks === 8 && i % ks === 4) { - k = aes_sbox[k >>> 24] << 24 ^ aes_sbox[k >>> 16 & 255] << 16 ^ aes_sbox[k >>> 8 & 255] << 8 ^ aes_sbox[k & 255]; - } - if (i % ks === 0) { - k = k << 8 ^ k >>> 24 ^ rcon << 24; - rcon = rcon << 1 ^ (rcon & 0x80 ? 0x1b : 0); - } - ekeys[i] = ekeys[i - ks] ^ k; - } - - // Decryption key schedule - for (var j = 0; j < i; j += 4) { - for (var jj = 0; jj < 4; jj++) { - var k = ekeys[i - (4 + j) + (4 - jj) % 4]; - if (j < 4 || j >= i - 4) { - dkeys[j + jj] = k; - } else { - dkeys[j + jj] = aes_dec[0][aes_sbox[k >>> 24]] ^ aes_dec[1][aes_sbox[k >>> 16 & 255]] ^ aes_dec[2][aes_sbox[k >>> 8 & 255]] ^ aes_dec[3][aes_sbox[k & 255]]; - } - } - } - - // Set rounds number - asm.set_rounds(ks + 5); - } - - // create library object with necessary properties - var stdlib = { Uint8Array: Uint8Array, Uint32Array: Uint32Array }; - - var asm = function (stdlib, foreign, buffer) { - "use asm"; - - var S0 = 0, - S1 = 0, - S2 = 0, - S3 = 0, - I0 = 0, - I1 = 0, - I2 = 0, - I3 = 0, - N0 = 0, - N1 = 0, - N2 = 0, - N3 = 0, - M0 = 0, - M1 = 0, - M2 = 0, - M3 = 0, - H0 = 0, - H1 = 0, - H2 = 0, - H3 = 0, - R = 0; - - var HEAP = new stdlib.Uint32Array(buffer), - DATA = new stdlib.Uint8Array(buffer); - - /** - * AES core - * @param {number} k - precomputed key schedule offset - * @param {number} s - precomputed sbox table offset - * @param {number} t - precomputed round table offset - * @param {number} r - number of inner rounds to perform - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _core(k, s, t, r, x0, x1, x2, x3) { - k = k | 0; - s = s | 0; - t = t | 0; - r = r | 0; - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - var t1 = 0, - t2 = 0, - t3 = 0, - y0 = 0, - y1 = 0, - y2 = 0, - y3 = 0, - i = 0; - - t1 = t | 0x400, t2 = t | 0x800, t3 = t | 0xc00; - - // round 0 - x0 = x0 ^ HEAP[(k | 0) >> 2], x1 = x1 ^ HEAP[(k | 4) >> 2], x2 = x2 ^ HEAP[(k | 8) >> 2], x3 = x3 ^ HEAP[(k | 12) >> 2]; - - // round 1..r - for (i = 16; (i | 0) <= r << 4; i = i + 16 | 0) { - y0 = HEAP[(t | x0 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x1 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x2 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x3 << 2 & 1020) >> 2] ^ HEAP[(k | i | 0) >> 2], y1 = HEAP[(t | x1 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x2 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x3 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x0 << 2 & 1020) >> 2] ^ HEAP[(k | i | 4) >> 2], y2 = HEAP[(t | x2 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x3 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x0 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x1 << 2 & 1020) >> 2] ^ HEAP[(k | i | 8) >> 2], y3 = HEAP[(t | x3 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x0 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x1 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x2 << 2 & 1020) >> 2] ^ HEAP[(k | i | 12) >> 2]; - x0 = y0, x1 = y1, x2 = y2, x3 = y3; - } - - // final round - S0 = HEAP[(s | x0 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x1 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x2 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x3 << 2 & 1020) >> 2] ^ HEAP[(k | i | 0) >> 2], S1 = HEAP[(s | x1 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x2 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x3 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x0 << 2 & 1020) >> 2] ^ HEAP[(k | i | 4) >> 2], S2 = HEAP[(s | x2 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x3 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x0 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x1 << 2 & 1020) >> 2] ^ HEAP[(k | i | 8) >> 2], S3 = HEAP[(s | x3 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x0 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x1 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x2 << 2 & 1020) >> 2] ^ HEAP[(k | i | 12) >> 2]; - } - - /** - * ECB mode encryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _ecb_enc(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core(0x0000, 0x0800, 0x1000, R, x0, x1, x2, x3); - } - - /** - * ECB mode decryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _ecb_dec(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - var t = 0; - - _core(0x0400, 0x0c00, 0x2000, R, x0, x3, x2, x1); - - t = S1, S1 = S3, S3 = t; - } - - /** - * CBC mode encryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _cbc_enc(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core(0x0000, 0x0800, 0x1000, R, I0 ^ x0, I1 ^ x1, I2 ^ x2, I3 ^ x3); - - I0 = S0, I1 = S1, I2 = S2, I3 = S3; - } - - /** - * CBC mode decryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _cbc_dec(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - var t = 0; - - _core(0x0400, 0x0c00, 0x2000, R, x0, x3, x2, x1); - - t = S1, S1 = S3, S3 = t; - - S0 = S0 ^ I0, S1 = S1 ^ I1, S2 = S2 ^ I2, S3 = S3 ^ I3; - - I0 = x0, I1 = x1, I2 = x2, I3 = x3; - } - - /** - * CFB mode encryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _cfb_enc(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core(0x0000, 0x0800, 0x1000, R, I0, I1, I2, I3); - - I0 = S0 = S0 ^ x0, I1 = S1 = S1 ^ x1, I2 = S2 = S2 ^ x2, I3 = S3 = S3 ^ x3; - } - - /** - * CFB mode decryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _cfb_dec(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core(0x0000, 0x0800, 0x1000, R, I0, I1, I2, I3); - - S0 = S0 ^ x0, S1 = S1 ^ x1, S2 = S2 ^ x2, S3 = S3 ^ x3; - - I0 = x0, I1 = x1, I2 = x2, I3 = x3; - } - - /** - * OFB mode encryption / decryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _ofb(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core(0x0000, 0x0800, 0x1000, R, I0, I1, I2, I3); - - I0 = S0, I1 = S1, I2 = S2, I3 = S3; - - S0 = S0 ^ x0, S1 = S1 ^ x1, S2 = S2 ^ x2, S3 = S3 ^ x3; - } - - /** - * CTR mode encryption / decryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _ctr(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core(0x0000, 0x0800, 0x1000, R, N0, N1, N2, N3); - - N3 = ~M3 & N3 | M3 & N3 + 1; - N2 = ~M2 & N2 | M2 & N2 + ((N3 | 0) == 0); - N1 = ~M1 & N1 | M1 & N1 + ((N2 | 0) == 0); - N0 = ~M0 & N0 | M0 & N0 + ((N1 | 0) == 0); - - S0 = S0 ^ x0; - S1 = S1 ^ x1; - S2 = S2 ^ x2; - S3 = S3 ^ x3; - } - - /** - * GCM mode MAC calculation - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _gcm_mac(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - var y0 = 0, - y1 = 0, - y2 = 0, - y3 = 0, - z0 = 0, - z1 = 0, - z2 = 0, - z3 = 0, - i = 0, - c = 0; - - x0 = x0 ^ I0, x1 = x1 ^ I1, x2 = x2 ^ I2, x3 = x3 ^ I3; - - y0 = H0 | 0, y1 = H1 | 0, y2 = H2 | 0, y3 = H3 | 0; - - for (; (i | 0) < 128; i = i + 1 | 0) { - if (y0 >>> 31) { - z0 = z0 ^ x0, z1 = z1 ^ x1, z2 = z2 ^ x2, z3 = z3 ^ x3; - } - - y0 = y0 << 1 | y1 >>> 31, y1 = y1 << 1 | y2 >>> 31, y2 = y2 << 1 | y3 >>> 31, y3 = y3 << 1; - - c = x3 & 1; - - x3 = x3 >>> 1 | x2 << 31, x2 = x2 >>> 1 | x1 << 31, x1 = x1 >>> 1 | x0 << 31, x0 = x0 >>> 1; - - if (c) x0 = x0 ^ 0xe1000000; - } - - I0 = z0, I1 = z1, I2 = z2, I3 = z3; - } - - /** - * Set the internal rounds number. - * @instance - * @memberof AES_asm - * @param {number} r - number if inner AES rounds - */ - function set_rounds(r) { - r = r | 0; - R = r; - } - - /** - * Populate the internal state of the module. - * @instance - * @memberof AES_asm - * @param {number} s0 - state vector - * @param {number} s1 - state vector - * @param {number} s2 - state vector - * @param {number} s3 - state vector - */ - function set_state(s0, s1, s2, s3) { - s0 = s0 | 0; - s1 = s1 | 0; - s2 = s2 | 0; - s3 = s3 | 0; - - S0 = s0, S1 = s1, S2 = s2, S3 = s3; - } - - /** - * Populate the internal iv of the module. - * @instance - * @memberof AES_asm - * @param {number} i0 - iv vector - * @param {number} i1 - iv vector - * @param {number} i2 - iv vector - * @param {number} i3 - iv vector - */ - function set_iv(i0, i1, i2, i3) { - i0 = i0 | 0; - i1 = i1 | 0; - i2 = i2 | 0; - i3 = i3 | 0; - - I0 = i0, I1 = i1, I2 = i2, I3 = i3; - } - - /** - * Set nonce for CTR-family modes. - * @instance - * @memberof AES_asm - * @param {number} n0 - nonce vector - * @param {number} n1 - nonce vector - * @param {number} n2 - nonce vector - * @param {number} n3 - nonce vector - */ - function set_nonce(n0, n1, n2, n3) { - n0 = n0 | 0; - n1 = n1 | 0; - n2 = n2 | 0; - n3 = n3 | 0; - - N0 = n0, N1 = n1, N2 = n2, N3 = n3; - } - - /** - * Set counter mask for CTR-family modes. - * @instance - * @memberof AES_asm - * @param {number} m0 - counter mask vector - * @param {number} m1 - counter mask vector - * @param {number} m2 - counter mask vector - * @param {number} m3 - counter mask vector - */ - function set_mask(m0, m1, m2, m3) { - m0 = m0 | 0; - m1 = m1 | 0; - m2 = m2 | 0; - m3 = m3 | 0; - - M0 = m0, M1 = m1, M2 = m2, M3 = m3; - } - - /** - * Set counter for CTR-family modes. - * @instance - * @memberof AES_asm - * @param {number} c0 - counter vector - * @param {number} c1 - counter vector - * @param {number} c2 - counter vector - * @param {number} c3 - counter vector - */ - function set_counter(c0, c1, c2, c3) { - c0 = c0 | 0; - c1 = c1 | 0; - c2 = c2 | 0; - c3 = c3 | 0; - - N3 = ~M3 & N3 | M3 & c3, N2 = ~M2 & N2 | M2 & c2, N1 = ~M1 & N1 | M1 & c1, N0 = ~M0 & N0 | M0 & c0; - } - - /** - * Store the internal state vector into the heap. - * @instance - * @memberof AES_asm - * @param {number} pos - offset where to put the data - * @return {number} The number of bytes have been written into the heap, always 16. - */ - function get_state(pos) { - pos = pos | 0; - - if (pos & 15) return -1; - - DATA[pos | 0] = S0 >>> 24, DATA[pos | 1] = S0 >>> 16 & 255, DATA[pos | 2] = S0 >>> 8 & 255, DATA[pos | 3] = S0 & 255, DATA[pos | 4] = S1 >>> 24, DATA[pos | 5] = S1 >>> 16 & 255, DATA[pos | 6] = S1 >>> 8 & 255, DATA[pos | 7] = S1 & 255, DATA[pos | 8] = S2 >>> 24, DATA[pos | 9] = S2 >>> 16 & 255, DATA[pos | 10] = S2 >>> 8 & 255, DATA[pos | 11] = S2 & 255, DATA[pos | 12] = S3 >>> 24, DATA[pos | 13] = S3 >>> 16 & 255, DATA[pos | 14] = S3 >>> 8 & 255, DATA[pos | 15] = S3 & 255; - - return 16; - } - - /** - * Store the internal iv vector into the heap. - * @instance - * @memberof AES_asm - * @param {number} pos - offset where to put the data - * @return {number} The number of bytes have been written into the heap, always 16. - */ - function get_iv(pos) { - pos = pos | 0; - - if (pos & 15) return -1; - - DATA[pos | 0] = I0 >>> 24, DATA[pos | 1] = I0 >>> 16 & 255, DATA[pos | 2] = I0 >>> 8 & 255, DATA[pos | 3] = I0 & 255, DATA[pos | 4] = I1 >>> 24, DATA[pos | 5] = I1 >>> 16 & 255, DATA[pos | 6] = I1 >>> 8 & 255, DATA[pos | 7] = I1 & 255, DATA[pos | 8] = I2 >>> 24, DATA[pos | 9] = I2 >>> 16 & 255, DATA[pos | 10] = I2 >>> 8 & 255, DATA[pos | 11] = I2 & 255, DATA[pos | 12] = I3 >>> 24, DATA[pos | 13] = I3 >>> 16 & 255, DATA[pos | 14] = I3 >>> 8 & 255, DATA[pos | 15] = I3 & 255; - - return 16; - } - - /** - * GCM initialization. - * @instance - * @memberof AES_asm - */ - function gcm_init() { - _ecb_enc(0, 0, 0, 0); - H0 = S0, H1 = S1, H2 = S2, H3 = S3; - } - - /** - * Perform ciphering operation on the supplied data. - * @instance - * @memberof AES_asm - * @param {number} mode - block cipher mode (see {@link AES_asm} mode constants) - * @param {number} pos - offset of the data being processed - * @param {number} len - length of the data being processed - * @return {number} Actual amount of data have been processed. - */ - function cipher(mode, pos, len) { - mode = mode | 0; - pos = pos | 0; - len = len | 0; - - var ret = 0; - - if (pos & 15) return -1; - - while ((len | 0) >= 16) { - _cipher_modes[mode & 7](DATA[pos | 0] << 24 | DATA[pos | 1] << 16 | DATA[pos | 2] << 8 | DATA[pos | 3], DATA[pos | 4] << 24 | DATA[pos | 5] << 16 | DATA[pos | 6] << 8 | DATA[pos | 7], DATA[pos | 8] << 24 | DATA[pos | 9] << 16 | DATA[pos | 10] << 8 | DATA[pos | 11], DATA[pos | 12] << 24 | DATA[pos | 13] << 16 | DATA[pos | 14] << 8 | DATA[pos | 15]); - - DATA[pos | 0] = S0 >>> 24, DATA[pos | 1] = S0 >>> 16 & 255, DATA[pos | 2] = S0 >>> 8 & 255, DATA[pos | 3] = S0 & 255, DATA[pos | 4] = S1 >>> 24, DATA[pos | 5] = S1 >>> 16 & 255, DATA[pos | 6] = S1 >>> 8 & 255, DATA[pos | 7] = S1 & 255, DATA[pos | 8] = S2 >>> 24, DATA[pos | 9] = S2 >>> 16 & 255, DATA[pos | 10] = S2 >>> 8 & 255, DATA[pos | 11] = S2 & 255, DATA[pos | 12] = S3 >>> 24, DATA[pos | 13] = S3 >>> 16 & 255, DATA[pos | 14] = S3 >>> 8 & 255, DATA[pos | 15] = S3 & 255; - - ret = ret + 16 | 0, pos = pos + 16 | 0, len = len - 16 | 0; - } - - return ret | 0; - } - - /** - * Calculates MAC of the supplied data. - * @instance - * @memberof AES_asm - * @param {number} mode - block cipher mode (see {@link AES_asm} mode constants) - * @param {number} pos - offset of the data being processed - * @param {number} len - length of the data being processed - * @return {number} Actual amount of data have been processed. - */ - function mac(mode, pos, len) { - mode = mode | 0; - pos = pos | 0; - len = len | 0; - - var ret = 0; - - if (pos & 15) return -1; - - while ((len | 0) >= 16) { - _mac_modes[mode & 1](DATA[pos | 0] << 24 | DATA[pos | 1] << 16 | DATA[pos | 2] << 8 | DATA[pos | 3], DATA[pos | 4] << 24 | DATA[pos | 5] << 16 | DATA[pos | 6] << 8 | DATA[pos | 7], DATA[pos | 8] << 24 | DATA[pos | 9] << 16 | DATA[pos | 10] << 8 | DATA[pos | 11], DATA[pos | 12] << 24 | DATA[pos | 13] << 16 | DATA[pos | 14] << 8 | DATA[pos | 15]); - - ret = ret + 16 | 0, pos = pos + 16 | 0, len = len - 16 | 0; - } - - return ret | 0; - } - - /** - * AES cipher modes table (virual methods) - */ - var _cipher_modes = [_ecb_enc, _ecb_dec, _cbc_enc, _cbc_dec, _cfb_enc, _cfb_dec, _ofb, _ctr]; - - /** - * AES MAC modes table (virual methods) - */ - var _mac_modes = [_cbc_enc, _gcm_mac]; - - /** - * Asm.js module exports - */ - return { - set_rounds: set_rounds, - set_state: set_state, - set_iv: set_iv, - set_nonce: set_nonce, - set_mask: set_mask, - set_counter: set_counter, - get_state: get_state, - get_iv: get_iv, - gcm_init: gcm_init, - cipher: cipher, - mac: mac - }; - }(stdlib, foreign, buffer); - - asm.set_key = set_key; - - return asm; - }; - - /** - * AES enciphering mode constants - * @enum {number} - * @const - */ - wrapper.ENC = { - ECB: 0, - CBC: 2, - CFB: 4, - OFB: 6, - CTR: 7 - }, - - /** - * AES deciphering mode constants - * @enum {number} - * @const - */ - wrapper.DEC = { - ECB: 1, - CBC: 3, - CFB: 5, - OFB: 6, - CTR: 7 - }, - - /** - * AES MAC mode constants - * @enum {number} - * @const - */ - wrapper.MAC = { - CBC: 0, - GCM: 1 - }; - - /** - * Heap data offset - * @type {number} - * @const - */ - wrapper.HEAP_DATA = 0x4000; - - return wrapper; -}(); - -},{}],3:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.AES = undefined; - -var _aes = require('./aes.asm'); - -var _utils = require('../other/utils'); - -var _errors = require('../other/errors'); - -var heap_pool = []; -var asm_pool = []; -var AES = /** @class */function () { - function AES(key, iv, padding, mode) { - if (padding === void 0) { - padding = true; - } - this.pos = 0; - this.len = 0; - this.mode = mode; - // The AES object state - this.pos = 0; - this.len = 0; - this.key = key; - this.iv = iv; - this.padding = padding; - // The AES "worker" - this.acquire_asm(); - } - AES.prototype.acquire_asm = function () { - if (this.heap === undefined && this.asm === undefined) { - this.heap = heap_pool.pop() || (0, _utils._heap_init)().subarray(_aes.AES_asm.HEAP_DATA); - this.asm = asm_pool.pop() || (0, _aes.AES_asm)(null, this.heap.buffer); - this.reset(this.key, this.iv); - } - }; - AES.prototype.release_asm = function () { - heap_pool.push(this.heap); - ; - asm_pool.push(this.asm); - this.heap = undefined; - this.asm = undefined; - }; - AES.prototype.reset = function (key, iv) { - // Key - var keylen = key.length; - if (keylen !== 16 && keylen !== 24 && keylen !== 32) throw new _errors.IllegalArgumentError('illegal key size'); - var keyview = new DataView(key.buffer, key.byteOffset, key.byteLength); - this.asm.set_key(keylen >> 2, keyview.getUint32(0), keyview.getUint32(4), keyview.getUint32(8), keyview.getUint32(12), keylen > 16 ? keyview.getUint32(16) : 0, keylen > 16 ? keyview.getUint32(20) : 0, keylen > 24 ? keyview.getUint32(24) : 0, keylen > 24 ? keyview.getUint32(28) : 0); - // IV - if (iv !== undefined) { - if (iv.length !== 16) throw new _errors.IllegalArgumentError('illegal iv size'); - var ivview = new DataView(iv.buffer, iv.byteOffset, iv.byteLength); - this.asm.set_iv(ivview.getUint32(0), ivview.getUint32(4), ivview.getUint32(8), ivview.getUint32(12)); - } else { - this.asm.set_iv(0, 0, 0, 0); - } - }; - AES.prototype.AES_Encrypt_process = function (data) { - if (!(0, _utils.is_bytes)(data)) throw new TypeError("data isn't of expected type"); - this.acquire_asm(); - var asm = this.asm; - var heap = this.heap; - var amode = _aes.AES_asm.ENC[this.mode]; - var hpos = _aes.AES_asm.HEAP_DATA; - var pos = this.pos; - var len = this.len; - var dpos = 0; - var dlen = data.length || 0; - var rpos = 0; - var rlen = len + dlen & -16; - var wlen = 0; - var result = new Uint8Array(rlen); - while (dlen > 0) { - wlen = (0, _utils._heap_write)(heap, pos + len, data, dpos, dlen); - len += wlen; - dpos += wlen; - dlen -= wlen; - wlen = asm.cipher(amode, hpos + pos, len); - if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos); - rpos += wlen; - if (wlen < len) { - pos += wlen; - len -= wlen; - } else { - pos = 0; - len = 0; - } - } - this.pos = pos; - this.len = len; - return result; - }; - AES.prototype.AES_Encrypt_finish = function () { - this.acquire_asm(); - var asm = this.asm; - var heap = this.heap; - var amode = _aes.AES_asm.ENC[this.mode]; - var hpos = _aes.AES_asm.HEAP_DATA; - var pos = this.pos; - var len = this.len; - var plen = 16 - len % 16; - var rlen = len; - if (this.hasOwnProperty('padding')) { - if (this.padding) { - for (var p = 0; p < plen; ++p) { - heap[pos + len + p] = plen; - } - len += plen; - rlen = len; - } else if (len % 16) { - throw new _errors.IllegalArgumentError('data length must be a multiple of the block size'); - } - } else { - len += plen; - } - var result = new Uint8Array(rlen); - if (len) asm.cipher(amode, hpos + pos, len); - if (rlen) result.set(heap.subarray(pos, pos + rlen)); - this.pos = 0; - this.len = 0; - this.release_asm(); - return result; - }; - AES.prototype.AES_Decrypt_process = function (data) { - if (!(0, _utils.is_bytes)(data)) throw new TypeError("data isn't of expected type"); - this.acquire_asm(); - var asm = this.asm; - var heap = this.heap; - var amode = _aes.AES_asm.DEC[this.mode]; - var hpos = _aes.AES_asm.HEAP_DATA; - var pos = this.pos; - var len = this.len; - var dpos = 0; - var dlen = data.length || 0; - var rpos = 0; - var rlen = len + dlen & -16; - var plen = 0; - var wlen = 0; - if (this.padding) { - plen = len + dlen - rlen || 16; - rlen -= plen; - } - var result = new Uint8Array(rlen); - while (dlen > 0) { - wlen = (0, _utils._heap_write)(heap, pos + len, data, dpos, dlen); - len += wlen; - dpos += wlen; - dlen -= wlen; - wlen = asm.cipher(amode, hpos + pos, len - (!dlen ? plen : 0)); - if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos); - rpos += wlen; - if (wlen < len) { - pos += wlen; - len -= wlen; - } else { - pos = 0; - len = 0; - } - } - this.pos = pos; - this.len = len; - return result; - }; - AES.prototype.AES_Decrypt_finish = function () { - this.acquire_asm(); - var asm = this.asm; - var heap = this.heap; - var amode = _aes.AES_asm.DEC[this.mode]; - var hpos = _aes.AES_asm.HEAP_DATA; - var pos = this.pos; - var len = this.len; - var rlen = len; - if (len > 0) { - if (len % 16) { - if (this.hasOwnProperty('padding')) { - throw new _errors.IllegalArgumentError('data length must be a multiple of the block size'); - } else { - len += 16 - len % 16; - } - } - asm.cipher(amode, hpos + pos, len); - if (this.hasOwnProperty('padding') && this.padding) { - var pad = heap[pos + rlen - 1]; - if (pad < 1 || pad > 16 || pad > rlen) throw new _errors.SecurityError('bad padding'); - var pcheck = 0; - for (var i = pad; i > 1; i--) pcheck |= pad ^ heap[pos + rlen - i]; - if (pcheck) throw new _errors.SecurityError('bad padding'); - rlen -= pad; - } - } - var result = new Uint8Array(rlen); - if (rlen > 0) { - result.set(heap.subarray(pos, pos + rlen)); - } - this.pos = 0; - this.len = 0; - this.release_asm(); - return result; - }; - return AES; -}(); -exports.AES = AES; - -},{"../other/errors":14,"../other/utils":15,"./aes.asm":2}],4:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.AES_CBC = undefined; - -var _aes = require('./aes'); - -var _utils = require('../other/utils'); - -var __extends = undefined && undefined.__extends || function () { - var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) { - d.__proto__ = b; - } || function (d, b) { - for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; - }; - return function (d, b) { - extendStatics(d, b); - function __() { - this.constructor = d; - } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -}(); - -var AES_CBC = /** @class */function (_super) { - __extends(AES_CBC, _super); - function AES_CBC(key, iv, padding) { - if (padding === void 0) { - padding = true; - } - return _super.call(this, key, iv, padding, 'CBC') || this; - } - AES_CBC.encrypt = function (data, key, padding, iv) { - if (padding === void 0) { - padding = true; - } - return new AES_CBC(key, iv, padding).encrypt(data); - }; - AES_CBC.decrypt = function (data, key, padding, iv) { - if (padding === void 0) { - padding = true; - } - return new AES_CBC(key, iv, padding).decrypt(data); - }; - AES_CBC.prototype.encrypt = function (data) { - var r1 = this.AES_Encrypt_process(data); - var r2 = this.AES_Encrypt_finish(); - return (0, _utils.joinBytes)(r1, r2); - }; - AES_CBC.prototype.decrypt = function (data) { - var r1 = this.AES_Decrypt_process(data); - var r2 = this.AES_Decrypt_finish(); - return (0, _utils.joinBytes)(r1, r2); - }; - return AES_CBC; -}(_aes.AES); -exports.AES_CBC = AES_CBC; - -},{"../other/utils":15,"./aes":3}],5:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.AES_CFB = undefined; - -var _aes = require('./aes'); - -var _utils = require('../other/utils'); - -var __extends = undefined && undefined.__extends || function () { - var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) { - d.__proto__ = b; - } || function (d, b) { - for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; - }; - return function (d, b) { - extendStatics(d, b); - function __() { - this.constructor = d; - } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -}(); - -var AES_CFB = /** @class */function (_super) { - __extends(AES_CFB, _super); - function AES_CFB(key, iv) { - var _this = _super.call(this, key, iv, true, 'CFB') || this; - delete _this.padding; - return _this; - } - AES_CFB.encrypt = function (data, key, iv) { - return new AES_CFB(key, iv).encrypt(data); - }; - AES_CFB.decrypt = function (data, key, iv) { - return new AES_CFB(key, iv).decrypt(data); - }; - AES_CFB.prototype.encrypt = function (data) { - var r1 = this.AES_Encrypt_process(data); - var r2 = this.AES_Encrypt_finish(); - return (0, _utils.joinBytes)(r1, r2); - }; - AES_CFB.prototype.decrypt = function (data) { - var r1 = this.AES_Decrypt_process(data); - var r2 = this.AES_Decrypt_finish(); - return (0, _utils.joinBytes)(r1, r2); - }; - return AES_CFB; -}(_aes.AES); -exports.AES_CFB = AES_CFB; - -},{"../other/utils":15,"./aes":3}],6:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.AES_CTR = undefined; - -var _aes = require('./aes'); - -var _errors = require('../other/errors'); - -var _utils = require('../other/utils'); - -var __extends = undefined && undefined.__extends || function () { - var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) { - d.__proto__ = b; - } || function (d, b) { - for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; - }; - return function (d, b) { - extendStatics(d, b); - function __() { - this.constructor = d; - } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -}(); - -var AES_CTR = /** @class */function (_super) { - __extends(AES_CTR, _super); - function AES_CTR(key, nonce) { - var _this = _super.call(this, key, undefined, false, 'CTR') || this; - delete _this.padding; - _this.AES_CTR_set_options(nonce); - return _this; - } - AES_CTR.encrypt = function (data, key, nonce) { - return new AES_CTR(key, nonce).encrypt(data); - }; - AES_CTR.decrypt = function (data, key, nonce) { - return new AES_CTR(key, nonce).encrypt(data); - }; - AES_CTR.prototype.encrypt = function (data) { - var r1 = this.AES_Encrypt_process(data); - var r2 = this.AES_Encrypt_finish(); - return (0, _utils.joinBytes)(r1, r2); - }; - AES_CTR.prototype.decrypt = function (data) { - var r1 = this.AES_Encrypt_process(data); - var r2 = this.AES_Encrypt_finish(); - return (0, _utils.joinBytes)(r1, r2); - }; - AES_CTR.prototype.AES_CTR_set_options = function (nonce, counter, size) { - if (size !== undefined) { - if (size < 8 || size > 48) throw new _errors.IllegalArgumentError('illegal counter size'); - var mask = Math.pow(2, size) - 1; - this.asm.set_mask(0, 0, mask / 0x100000000 | 0, mask | 0); - } else { - size = 48; - this.asm.set_mask(0, 0, 0xffff, 0xffffffff); - } - if (nonce !== undefined) { - var len = nonce.length; - if (!len || len > 16) throw new _errors.IllegalArgumentError('illegal nonce size'); - var view = new DataView(new ArrayBuffer(16)); - new Uint8Array(view.buffer).set(nonce); - this.asm.set_nonce(view.getUint32(0), view.getUint32(4), view.getUint32(8), view.getUint32(12)); - } else { - throw new Error('nonce is required'); - } - if (counter !== undefined) { - if (counter < 0 || counter >= Math.pow(2, size)) throw new _errors.IllegalArgumentError('illegal counter value'); - this.asm.set_counter(0, 0, counter / 0x100000000 | 0, counter | 0); - } - }; - return AES_CTR; -}(_aes.AES); -exports.AES_CTR = AES_CTR; - -},{"../other/errors":14,"../other/utils":15,"./aes":3}],7:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.AES_ECB = undefined; - -var _aes = require('./aes'); - -var _utils = require('../other/utils'); - -var __extends = undefined && undefined.__extends || function () { - var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) { - d.__proto__ = b; - } || function (d, b) { - for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; - }; - return function (d, b) { - extendStatics(d, b); - function __() { - this.constructor = d; - } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -}(); - -var AES_ECB = /** @class */function (_super) { - __extends(AES_ECB, _super); - function AES_ECB(key, padding) { - if (padding === void 0) { - padding = false; - } - return _super.call(this, key, undefined, padding, 'ECB') || this; - } - AES_ECB.encrypt = function (data, key, padding) { - if (padding === void 0) { - padding = false; - } - return new AES_ECB(key, padding).encrypt(data); - }; - AES_ECB.decrypt = function (data, key, padding) { - if (padding === void 0) { - padding = false; - } - return new AES_ECB(key, padding).decrypt(data); - }; - AES_ECB.prototype.encrypt = function (data) { - var r1 = this.AES_Encrypt_process(data); - var r2 = this.AES_Encrypt_finish(); - return (0, _utils.joinBytes)(r1, r2); - }; - AES_ECB.prototype.decrypt = function (data) { - var r1 = this.AES_Decrypt_process(data); - var r2 = this.AES_Decrypt_finish(); - return (0, _utils.joinBytes)(r1, r2); - }; - return AES_ECB; -}(_aes.AES); -exports.AES_ECB = AES_ECB; - -},{"../other/utils":15,"./aes":3}],8:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.AES_GCM = undefined; - -var _errors = require('../other/errors'); - -var _utils = require('../other/utils'); - -var _aes = require('./aes'); - -var _aes2 = require('./aes.asm'); - -var __extends = undefined && undefined.__extends || function () { - var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) { - d.__proto__ = b; - } || function (d, b) { - for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; - }; - return function (d, b) { - extendStatics(d, b); - function __() { - this.constructor = d; - } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -}(); - -var _AES_GCM_data_maxLength = 68719476704; // 2^36 - 2^5 -var AES_GCM = /** @class */function (_super) { - __extends(AES_GCM, _super); - function AES_GCM(key, nonce, adata, tagSize) { - if (tagSize === void 0) { - tagSize = 16; - } - var _this = _super.call(this, key, undefined, false, 'CTR') || this; - _this.tagSize = tagSize; - _this.gamma0 = 0; - _this.counter = 1; - // Init GCM - _this.asm.gcm_init(); - // Tag size - if (_this.tagSize < 4 || _this.tagSize > 16) throw new _errors.IllegalArgumentError('illegal tagSize value'); - // Nonce - var noncelen = nonce.length || 0; - var noncebuf = new Uint8Array(16); - if (noncelen !== 12) { - _this._gcm_mac_process(nonce); - _this.heap[0] = 0; - _this.heap[1] = 0; - _this.heap[2] = 0; - _this.heap[3] = 0; - _this.heap[4] = 0; - _this.heap[5] = 0; - _this.heap[6] = 0; - _this.heap[7] = 0; - _this.heap[8] = 0; - _this.heap[9] = 0; - _this.heap[10] = 0; - _this.heap[11] = noncelen >>> 29; - _this.heap[12] = noncelen >>> 21 & 255; - _this.heap[13] = noncelen >>> 13 & 255; - _this.heap[14] = noncelen >>> 5 & 255; - _this.heap[15] = noncelen << 3 & 255; - _this.asm.mac(_aes2.AES_asm.MAC.GCM, _aes2.AES_asm.HEAP_DATA, 16); - _this.asm.get_iv(_aes2.AES_asm.HEAP_DATA); - _this.asm.set_iv(0, 0, 0, 0); - noncebuf.set(_this.heap.subarray(0, 16)); - } else { - noncebuf.set(nonce); - noncebuf[15] = 1; - } - var nonceview = new DataView(noncebuf.buffer); - _this.gamma0 = nonceview.getUint32(12); - _this.asm.set_nonce(nonceview.getUint32(0), nonceview.getUint32(4), nonceview.getUint32(8), 0); - _this.asm.set_mask(0, 0, 0, 0xffffffff); - // Associated data - if (adata !== undefined) { - if (adata.length > _AES_GCM_data_maxLength) throw new _errors.IllegalArgumentError('illegal adata length'); - if (adata.length) { - _this.adata = adata; - _this._gcm_mac_process(adata); - } else { - _this.adata = undefined; - } - } else { - _this.adata = undefined; - } - // Counter - if (_this.counter < 1 || _this.counter > 0xffffffff) throw new RangeError('counter must be a positive 32-bit integer'); - _this.asm.set_counter(0, 0, 0, _this.gamma0 + _this.counter | 0); - return _this; - } - AES_GCM.encrypt = function (cleartext, key, nonce, adata, tagsize) { - return new AES_GCM(key, nonce, adata, tagsize).encrypt(cleartext); - }; - AES_GCM.decrypt = function (ciphertext, key, nonce, adata, tagsize) { - return new AES_GCM(key, nonce, adata, tagsize).decrypt(ciphertext); - }; - AES_GCM.prototype.encrypt = function (data) { - return this.AES_GCM_encrypt(data); - }; - AES_GCM.prototype.decrypt = function (data) { - return this.AES_GCM_decrypt(data); - }; - AES_GCM.prototype.AES_GCM_Encrypt_process = function (data) { - var dpos = 0; - var dlen = data.length || 0; - var asm = this.asm; - var heap = this.heap; - var counter = this.counter; - var pos = this.pos; - var len = this.len; - var rpos = 0; - var rlen = len + dlen & -16; - var wlen = 0; - if ((counter - 1 << 4) + len + dlen > _AES_GCM_data_maxLength) throw new RangeError('counter overflow'); - var result = new Uint8Array(rlen); - while (dlen > 0) { - wlen = (0, _utils._heap_write)(heap, pos + len, data, dpos, dlen); - len += wlen; - dpos += wlen; - dlen -= wlen; - wlen = asm.cipher(_aes2.AES_asm.ENC.CTR, _aes2.AES_asm.HEAP_DATA + pos, len); - wlen = asm.mac(_aes2.AES_asm.MAC.GCM, _aes2.AES_asm.HEAP_DATA + pos, wlen); - if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos); - counter += wlen >>> 4; - rpos += wlen; - if (wlen < len) { - pos += wlen; - len -= wlen; - } else { - pos = 0; - len = 0; - } - } - this.counter = counter; - this.pos = pos; - this.len = len; - return result; - }; - AES_GCM.prototype.AES_GCM_Encrypt_finish = function () { - var asm = this.asm; - var heap = this.heap; - var counter = this.counter; - var tagSize = this.tagSize; - var adata = this.adata; - var pos = this.pos; - var len = this.len; - var result = new Uint8Array(len + tagSize); - asm.cipher(_aes2.AES_asm.ENC.CTR, _aes2.AES_asm.HEAP_DATA + pos, len + 15 & -16); - if (len) result.set(heap.subarray(pos, pos + len)); - var i = len; - for (; i & 15; i++) heap[pos + i] = 0; - asm.mac(_aes2.AES_asm.MAC.GCM, _aes2.AES_asm.HEAP_DATA + pos, i); - var alen = adata !== undefined ? adata.length : 0; - var clen = (counter - 1 << 4) + len; - heap[0] = 0; - heap[1] = 0; - heap[2] = 0; - heap[3] = alen >>> 29; - heap[4] = alen >>> 21; - heap[5] = alen >>> 13 & 255; - heap[6] = alen >>> 5 & 255; - heap[7] = alen << 3 & 255; - heap[8] = heap[9] = heap[10] = 0; - heap[11] = clen >>> 29; - heap[12] = clen >>> 21 & 255; - heap[13] = clen >>> 13 & 255; - heap[14] = clen >>> 5 & 255; - heap[15] = clen << 3 & 255; - asm.mac(_aes2.AES_asm.MAC.GCM, _aes2.AES_asm.HEAP_DATA, 16); - asm.get_iv(_aes2.AES_asm.HEAP_DATA); - asm.set_counter(0, 0, 0, this.gamma0); - asm.cipher(_aes2.AES_asm.ENC.CTR, _aes2.AES_asm.HEAP_DATA, 16); - result.set(heap.subarray(0, tagSize), len); - this.counter = 1; - this.pos = 0; - this.len = 0; - return result; - }; - AES_GCM.prototype.AES_GCM_Decrypt_process = function (data) { - var dpos = 0; - var dlen = data.length || 0; - var asm = this.asm; - var heap = this.heap; - var counter = this.counter; - var tagSize = this.tagSize; - var pos = this.pos; - var len = this.len; - var rpos = 0; - var rlen = len + dlen > tagSize ? len + dlen - tagSize & -16 : 0; - var tlen = len + dlen - rlen; - var wlen = 0; - if ((counter - 1 << 4) + len + dlen > _AES_GCM_data_maxLength) throw new RangeError('counter overflow'); - var result = new Uint8Array(rlen); - while (dlen > tlen) { - wlen = (0, _utils._heap_write)(heap, pos + len, data, dpos, dlen - tlen); - len += wlen; - dpos += wlen; - dlen -= wlen; - wlen = asm.mac(_aes2.AES_asm.MAC.GCM, _aes2.AES_asm.HEAP_DATA + pos, wlen); - wlen = asm.cipher(_aes2.AES_asm.DEC.CTR, _aes2.AES_asm.HEAP_DATA + pos, wlen); - if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos); - counter += wlen >>> 4; - rpos += wlen; - pos = 0; - len = 0; - } - if (dlen > 0) { - len += (0, _utils._heap_write)(heap, 0, data, dpos, dlen); - } - this.counter = counter; - this.pos = pos; - this.len = len; - return result; - }; - AES_GCM.prototype.AES_GCM_Decrypt_finish = function () { - var asm = this.asm; - var heap = this.heap; - var tagSize = this.tagSize; - var adata = this.adata; - var counter = this.counter; - var pos = this.pos; - var len = this.len; - var rlen = len - tagSize; - if (len < tagSize) throw new _errors.IllegalStateError('authentication tag not found'); - var result = new Uint8Array(rlen); - var atag = new Uint8Array(heap.subarray(pos + rlen, pos + len)); - var i = rlen; - for (; i & 15; i++) heap[pos + i] = 0; - asm.mac(_aes2.AES_asm.MAC.GCM, _aes2.AES_asm.HEAP_DATA + pos, i); - asm.cipher(_aes2.AES_asm.DEC.CTR, _aes2.AES_asm.HEAP_DATA + pos, i); - if (rlen) result.set(heap.subarray(pos, pos + rlen)); - var alen = adata !== undefined ? adata.length : 0; - var clen = (counter - 1 << 4) + len - tagSize; - heap[0] = 0; - heap[1] = 0; - heap[2] = 0; - heap[3] = alen >>> 29; - heap[4] = alen >>> 21; - heap[5] = alen >>> 13 & 255; - heap[6] = alen >>> 5 & 255; - heap[7] = alen << 3 & 255; - heap[8] = heap[9] = heap[10] = 0; - heap[11] = clen >>> 29; - heap[12] = clen >>> 21 & 255; - heap[13] = clen >>> 13 & 255; - heap[14] = clen >>> 5 & 255; - heap[15] = clen << 3 & 255; - asm.mac(_aes2.AES_asm.MAC.GCM, _aes2.AES_asm.HEAP_DATA, 16); - asm.get_iv(_aes2.AES_asm.HEAP_DATA); - asm.set_counter(0, 0, 0, this.gamma0); - asm.cipher(_aes2.AES_asm.ENC.CTR, _aes2.AES_asm.HEAP_DATA, 16); - var acheck = 0; - for (var i_1 = 0; i_1 < tagSize; ++i_1) acheck |= atag[i_1] ^ heap[i_1]; - if (acheck) throw new _errors.SecurityError('data integrity check failed'); - this.counter = 1; - this.pos = 0; - this.len = 0; - return result; - }; - AES_GCM.prototype.AES_GCM_decrypt = function (data) { - var result1 = this.AES_GCM_Decrypt_process(data); - var result2 = this.AES_GCM_Decrypt_finish(); - var result = new Uint8Array(result1.length + result2.length); - if (result1.length) result.set(result1); - if (result2.length) result.set(result2, result1.length); - return result; - }; - AES_GCM.prototype.AES_GCM_encrypt = function (data) { - var result1 = this.AES_GCM_Encrypt_process(data); - var result2 = this.AES_GCM_Encrypt_finish(); - var result = new Uint8Array(result1.length + result2.length); - if (result1.length) result.set(result1); - if (result2.length) result.set(result2, result1.length); - return result; - }; - AES_GCM.prototype._gcm_mac_process = function (data) { - var heap = this.heap; - var asm = this.asm; - var dpos = 0; - var dlen = data.length || 0; - var wlen = 0; - while (dlen > 0) { - wlen = (0, _utils._heap_write)(heap, 0, data, dpos, dlen); - dpos += wlen; - dlen -= wlen; - while (wlen & 15) heap[wlen++] = 0; - asm.mac(_aes2.AES_asm.MAC.GCM, _aes2.AES_asm.HEAP_DATA, wlen); - } - }; - return AES_GCM; -}(_aes.AES); -exports.AES_GCM = AES_GCM; - -},{"../other/errors":14,"../other/utils":15,"./aes":3,"./aes.asm":2}],9:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.Hash = undefined; - -var _utils = require('../other/utils'); - -var _errors = require('../other/errors'); - -var Hash = /** @class */function () { - function Hash() { - this.pos = 0; - this.len = 0; - this.acquire_asm(); - } - Hash.prototype.acquire_asm = function () { - if (this.heap === undefined && this.asm === undefined) { - this.heap = this.constructor.heap_pool.pop() || (0, _utils._heap_init)(); - this.asm = this.constructor.asm_pool.pop() || this.constructor.asm_function({ Uint8Array: Uint8Array }, null, this.heap.buffer); - this.reset(); - } - }; - Hash.prototype.release_asm = function () { - this.constructor.heap_pool.push(this.heap); - ; - this.constructor.asm_pool.push(this.asm); - this.heap = undefined; - this.asm = undefined; - }; - Hash.prototype.reset = function () { - this.acquire_asm(); - this.result = null; - this.pos = 0; - this.len = 0; - this.asm.reset(); - return this; - }; - Hash.prototype.process = function (data) { - if (this.result !== null) throw new _errors.IllegalStateError('state must be reset before processing new data'); - this.acquire_asm(); - var asm = this.asm; - var heap = this.heap; - var hpos = this.pos; - var hlen = this.len; - var dpos = 0; - var dlen = data.length; - var wlen = 0; - while (dlen > 0) { - wlen = (0, _utils._heap_write)(heap, hpos + hlen, data, dpos, dlen); - hlen += wlen; - dpos += wlen; - dlen -= wlen; - wlen = asm.process(hpos, hlen); - hpos += wlen; - hlen -= wlen; - if (!hlen) hpos = 0; - } - this.pos = hpos; - this.len = hlen; - return this; - }; - Hash.prototype.finish = function () { - if (this.result !== null) throw new _errors.IllegalStateError('state must be reset before processing new data'); - this.acquire_asm(); - this.asm.finish(this.pos, this.len, 0); - this.result = new Uint8Array(this.HASH_SIZE); - this.result.set(this.heap.subarray(0, this.HASH_SIZE)); - this.pos = 0; - this.len = 0; - this.release_asm(); - return this; - }; - return Hash; -}(); -exports.Hash = Hash; - -},{"../other/errors":14,"../other/utils":15}],10:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.sha1_asm = sha1_asm; -function sha1_asm(stdlib, foreign, buffer) { - "use asm"; - - // SHA256 state - - var H0 = 0, - H1 = 0, - H2 = 0, - H3 = 0, - H4 = 0, - TOTAL0 = 0, - TOTAL1 = 0; - - // HMAC state - var I0 = 0, - I1 = 0, - I2 = 0, - I3 = 0, - I4 = 0, - O0 = 0, - O1 = 0, - O2 = 0, - O3 = 0, - O4 = 0; - - // I/O buffer - var HEAP = new stdlib.Uint8Array(buffer); - - function _core(w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15) { - w0 = w0 | 0; - w1 = w1 | 0; - w2 = w2 | 0; - w3 = w3 | 0; - w4 = w4 | 0; - w5 = w5 | 0; - w6 = w6 | 0; - w7 = w7 | 0; - w8 = w8 | 0; - w9 = w9 | 0; - w10 = w10 | 0; - w11 = w11 | 0; - w12 = w12 | 0; - w13 = w13 | 0; - w14 = w14 | 0; - w15 = w15 | 0; - - var a = 0, - b = 0, - c = 0, - d = 0, - e = 0, - n = 0, - t = 0, - w16 = 0, - w17 = 0, - w18 = 0, - w19 = 0, - w20 = 0, - w21 = 0, - w22 = 0, - w23 = 0, - w24 = 0, - w25 = 0, - w26 = 0, - w27 = 0, - w28 = 0, - w29 = 0, - w30 = 0, - w31 = 0, - w32 = 0, - w33 = 0, - w34 = 0, - w35 = 0, - w36 = 0, - w37 = 0, - w38 = 0, - w39 = 0, - w40 = 0, - w41 = 0, - w42 = 0, - w43 = 0, - w44 = 0, - w45 = 0, - w46 = 0, - w47 = 0, - w48 = 0, - w49 = 0, - w50 = 0, - w51 = 0, - w52 = 0, - w53 = 0, - w54 = 0, - w55 = 0, - w56 = 0, - w57 = 0, - w58 = 0, - w59 = 0, - w60 = 0, - w61 = 0, - w62 = 0, - w63 = 0, - w64 = 0, - w65 = 0, - w66 = 0, - w67 = 0, - w68 = 0, - w69 = 0, - w70 = 0, - w71 = 0, - w72 = 0, - w73 = 0, - w74 = 0, - w75 = 0, - w76 = 0, - w77 = 0, - w78 = 0, - w79 = 0; - - a = H0; - b = H1; - c = H2; - d = H3; - e = H4; - - // 0 - t = w0 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 1 - t = w1 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 2 - t = w2 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 3 - t = w3 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 4 - t = w4 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 5 - t = w5 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 6 - t = w6 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 7 - t = w7 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 8 - t = w8 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 9 - t = w9 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 10 - t = w10 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 11 - t = w11 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 12 - t = w12 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 13 - t = w13 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 14 - t = w14 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 15 - t = w15 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 16 - n = w13 ^ w8 ^ w2 ^ w0; - w16 = n << 1 | n >>> 31; - t = w16 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 17 - n = w14 ^ w9 ^ w3 ^ w1; - w17 = n << 1 | n >>> 31; - t = w17 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 18 - n = w15 ^ w10 ^ w4 ^ w2; - w18 = n << 1 | n >>> 31; - t = w18 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 19 - n = w16 ^ w11 ^ w5 ^ w3; - w19 = n << 1 | n >>> 31; - t = w19 + (a << 5 | a >>> 27) + e + (b & c | ~b & d) + 0x5a827999 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 20 - n = w17 ^ w12 ^ w6 ^ w4; - w20 = n << 1 | n >>> 31; - t = w20 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 21 - n = w18 ^ w13 ^ w7 ^ w5; - w21 = n << 1 | n >>> 31; - t = w21 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 22 - n = w19 ^ w14 ^ w8 ^ w6; - w22 = n << 1 | n >>> 31; - t = w22 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 23 - n = w20 ^ w15 ^ w9 ^ w7; - w23 = n << 1 | n >>> 31; - t = w23 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 24 - n = w21 ^ w16 ^ w10 ^ w8; - w24 = n << 1 | n >>> 31; - t = w24 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 25 - n = w22 ^ w17 ^ w11 ^ w9; - w25 = n << 1 | n >>> 31; - t = w25 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 26 - n = w23 ^ w18 ^ w12 ^ w10; - w26 = n << 1 | n >>> 31; - t = w26 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 27 - n = w24 ^ w19 ^ w13 ^ w11; - w27 = n << 1 | n >>> 31; - t = w27 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 28 - n = w25 ^ w20 ^ w14 ^ w12; - w28 = n << 1 | n >>> 31; - t = w28 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 29 - n = w26 ^ w21 ^ w15 ^ w13; - w29 = n << 1 | n >>> 31; - t = w29 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 30 - n = w27 ^ w22 ^ w16 ^ w14; - w30 = n << 1 | n >>> 31; - t = w30 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 31 - n = w28 ^ w23 ^ w17 ^ w15; - w31 = n << 1 | n >>> 31; - t = w31 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 32 - n = w29 ^ w24 ^ w18 ^ w16; - w32 = n << 1 | n >>> 31; - t = w32 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 33 - n = w30 ^ w25 ^ w19 ^ w17; - w33 = n << 1 | n >>> 31; - t = w33 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 34 - n = w31 ^ w26 ^ w20 ^ w18; - w34 = n << 1 | n >>> 31; - t = w34 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 35 - n = w32 ^ w27 ^ w21 ^ w19; - w35 = n << 1 | n >>> 31; - t = w35 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 36 - n = w33 ^ w28 ^ w22 ^ w20; - w36 = n << 1 | n >>> 31; - t = w36 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 37 - n = w34 ^ w29 ^ w23 ^ w21; - w37 = n << 1 | n >>> 31; - t = w37 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 38 - n = w35 ^ w30 ^ w24 ^ w22; - w38 = n << 1 | n >>> 31; - t = w38 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 39 - n = w36 ^ w31 ^ w25 ^ w23; - w39 = n << 1 | n >>> 31; - t = w39 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) + 0x6ed9eba1 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 40 - n = w37 ^ w32 ^ w26 ^ w24; - w40 = n << 1 | n >>> 31; - t = w40 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 41 - n = w38 ^ w33 ^ w27 ^ w25; - w41 = n << 1 | n >>> 31; - t = w41 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 42 - n = w39 ^ w34 ^ w28 ^ w26; - w42 = n << 1 | n >>> 31; - t = w42 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 43 - n = w40 ^ w35 ^ w29 ^ w27; - w43 = n << 1 | n >>> 31; - t = w43 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 44 - n = w41 ^ w36 ^ w30 ^ w28; - w44 = n << 1 | n >>> 31; - t = w44 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 45 - n = w42 ^ w37 ^ w31 ^ w29; - w45 = n << 1 | n >>> 31; - t = w45 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 46 - n = w43 ^ w38 ^ w32 ^ w30; - w46 = n << 1 | n >>> 31; - t = w46 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 47 - n = w44 ^ w39 ^ w33 ^ w31; - w47 = n << 1 | n >>> 31; - t = w47 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 48 - n = w45 ^ w40 ^ w34 ^ w32; - w48 = n << 1 | n >>> 31; - t = w48 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 49 - n = w46 ^ w41 ^ w35 ^ w33; - w49 = n << 1 | n >>> 31; - t = w49 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 50 - n = w47 ^ w42 ^ w36 ^ w34; - w50 = n << 1 | n >>> 31; - t = w50 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 51 - n = w48 ^ w43 ^ w37 ^ w35; - w51 = n << 1 | n >>> 31; - t = w51 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 52 - n = w49 ^ w44 ^ w38 ^ w36; - w52 = n << 1 | n >>> 31; - t = w52 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 53 - n = w50 ^ w45 ^ w39 ^ w37; - w53 = n << 1 | n >>> 31; - t = w53 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 54 - n = w51 ^ w46 ^ w40 ^ w38; - w54 = n << 1 | n >>> 31; - t = w54 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 55 - n = w52 ^ w47 ^ w41 ^ w39; - w55 = n << 1 | n >>> 31; - t = w55 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 56 - n = w53 ^ w48 ^ w42 ^ w40; - w56 = n << 1 | n >>> 31; - t = w56 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 57 - n = w54 ^ w49 ^ w43 ^ w41; - w57 = n << 1 | n >>> 31; - t = w57 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 58 - n = w55 ^ w50 ^ w44 ^ w42; - w58 = n << 1 | n >>> 31; - t = w58 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 59 - n = w56 ^ w51 ^ w45 ^ w43; - w59 = n << 1 | n >>> 31; - t = w59 + (a << 5 | a >>> 27) + e + (b & c | b & d | c & d) - 0x70e44324 | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 60 - n = w57 ^ w52 ^ w46 ^ w44; - w60 = n << 1 | n >>> 31; - t = w60 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 61 - n = w58 ^ w53 ^ w47 ^ w45; - w61 = n << 1 | n >>> 31; - t = w61 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 62 - n = w59 ^ w54 ^ w48 ^ w46; - w62 = n << 1 | n >>> 31; - t = w62 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 63 - n = w60 ^ w55 ^ w49 ^ w47; - w63 = n << 1 | n >>> 31; - t = w63 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 64 - n = w61 ^ w56 ^ w50 ^ w48; - w64 = n << 1 | n >>> 31; - t = w64 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 65 - n = w62 ^ w57 ^ w51 ^ w49; - w65 = n << 1 | n >>> 31; - t = w65 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 66 - n = w63 ^ w58 ^ w52 ^ w50; - w66 = n << 1 | n >>> 31; - t = w66 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 67 - n = w64 ^ w59 ^ w53 ^ w51; - w67 = n << 1 | n >>> 31; - t = w67 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 68 - n = w65 ^ w60 ^ w54 ^ w52; - w68 = n << 1 | n >>> 31; - t = w68 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 69 - n = w66 ^ w61 ^ w55 ^ w53; - w69 = n << 1 | n >>> 31; - t = w69 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 70 - n = w67 ^ w62 ^ w56 ^ w54; - w70 = n << 1 | n >>> 31; - t = w70 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 71 - n = w68 ^ w63 ^ w57 ^ w55; - w71 = n << 1 | n >>> 31; - t = w71 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 72 - n = w69 ^ w64 ^ w58 ^ w56; - w72 = n << 1 | n >>> 31; - t = w72 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 73 - n = w70 ^ w65 ^ w59 ^ w57; - w73 = n << 1 | n >>> 31; - t = w73 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 74 - n = w71 ^ w66 ^ w60 ^ w58; - w74 = n << 1 | n >>> 31; - t = w74 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 75 - n = w72 ^ w67 ^ w61 ^ w59; - w75 = n << 1 | n >>> 31; - t = w75 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 76 - n = w73 ^ w68 ^ w62 ^ w60; - w76 = n << 1 | n >>> 31; - t = w76 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 77 - n = w74 ^ w69 ^ w63 ^ w61; - w77 = n << 1 | n >>> 31; - t = w77 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 78 - n = w75 ^ w70 ^ w64 ^ w62; - w78 = n << 1 | n >>> 31; - t = w78 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - // 79 - n = w76 ^ w71 ^ w65 ^ w63; - w79 = n << 1 | n >>> 31; - t = w79 + (a << 5 | a >>> 27) + e + (b ^ c ^ d) - 0x359d3e2a | 0; - e = d;d = c;c = b << 30 | b >>> 2;b = a;a = t; - - H0 = H0 + a | 0; - H1 = H1 + b | 0; - H2 = H2 + c | 0; - H3 = H3 + d | 0; - H4 = H4 + e | 0; - } - - function _core_heap(offset) { - offset = offset | 0; - - _core(HEAP[offset | 0] << 24 | HEAP[offset | 1] << 16 | HEAP[offset | 2] << 8 | HEAP[offset | 3], HEAP[offset | 4] << 24 | HEAP[offset | 5] << 16 | HEAP[offset | 6] << 8 | HEAP[offset | 7], HEAP[offset | 8] << 24 | HEAP[offset | 9] << 16 | HEAP[offset | 10] << 8 | HEAP[offset | 11], HEAP[offset | 12] << 24 | HEAP[offset | 13] << 16 | HEAP[offset | 14] << 8 | HEAP[offset | 15], HEAP[offset | 16] << 24 | HEAP[offset | 17] << 16 | HEAP[offset | 18] << 8 | HEAP[offset | 19], HEAP[offset | 20] << 24 | HEAP[offset | 21] << 16 | HEAP[offset | 22] << 8 | HEAP[offset | 23], HEAP[offset | 24] << 24 | HEAP[offset | 25] << 16 | HEAP[offset | 26] << 8 | HEAP[offset | 27], HEAP[offset | 28] << 24 | HEAP[offset | 29] << 16 | HEAP[offset | 30] << 8 | HEAP[offset | 31], HEAP[offset | 32] << 24 | HEAP[offset | 33] << 16 | HEAP[offset | 34] << 8 | HEAP[offset | 35], HEAP[offset | 36] << 24 | HEAP[offset | 37] << 16 | HEAP[offset | 38] << 8 | HEAP[offset | 39], HEAP[offset | 40] << 24 | HEAP[offset | 41] << 16 | HEAP[offset | 42] << 8 | HEAP[offset | 43], HEAP[offset | 44] << 24 | HEAP[offset | 45] << 16 | HEAP[offset | 46] << 8 | HEAP[offset | 47], HEAP[offset | 48] << 24 | HEAP[offset | 49] << 16 | HEAP[offset | 50] << 8 | HEAP[offset | 51], HEAP[offset | 52] << 24 | HEAP[offset | 53] << 16 | HEAP[offset | 54] << 8 | HEAP[offset | 55], HEAP[offset | 56] << 24 | HEAP[offset | 57] << 16 | HEAP[offset | 58] << 8 | HEAP[offset | 59], HEAP[offset | 60] << 24 | HEAP[offset | 61] << 16 | HEAP[offset | 62] << 8 | HEAP[offset | 63]); - } - - // offset — multiple of 32 - function _state_to_heap(output) { - output = output | 0; - - HEAP[output | 0] = H0 >>> 24; - HEAP[output | 1] = H0 >>> 16 & 255; - HEAP[output | 2] = H0 >>> 8 & 255; - HEAP[output | 3] = H0 & 255; - HEAP[output | 4] = H1 >>> 24; - HEAP[output | 5] = H1 >>> 16 & 255; - HEAP[output | 6] = H1 >>> 8 & 255; - HEAP[output | 7] = H1 & 255; - HEAP[output | 8] = H2 >>> 24; - HEAP[output | 9] = H2 >>> 16 & 255; - HEAP[output | 10] = H2 >>> 8 & 255; - HEAP[output | 11] = H2 & 255; - HEAP[output | 12] = H3 >>> 24; - HEAP[output | 13] = H3 >>> 16 & 255; - HEAP[output | 14] = H3 >>> 8 & 255; - HEAP[output | 15] = H3 & 255; - HEAP[output | 16] = H4 >>> 24; - HEAP[output | 17] = H4 >>> 16 & 255; - HEAP[output | 18] = H4 >>> 8 & 255; - HEAP[output | 19] = H4 & 255; - } - - function reset() { - H0 = 0x67452301; - H1 = 0xefcdab89; - H2 = 0x98badcfe; - H3 = 0x10325476; - H4 = 0xc3d2e1f0; - TOTAL0 = TOTAL1 = 0; - } - - function init(h0, h1, h2, h3, h4, total0, total1) { - h0 = h0 | 0; - h1 = h1 | 0; - h2 = h2 | 0; - h3 = h3 | 0; - h4 = h4 | 0; - total0 = total0 | 0; - total1 = total1 | 0; - - H0 = h0; - H1 = h1; - H2 = h2; - H3 = h3; - H4 = h4; - TOTAL0 = total0; - TOTAL1 = total1; - } - - // offset — multiple of 64 - function process(offset, length) { - offset = offset | 0; - length = length | 0; - - var hashed = 0; - - if (offset & 63) return -1; - - while ((length | 0) >= 64) { - _core_heap(offset); - - offset = offset + 64 | 0; - length = length - 64 | 0; - - hashed = hashed + 64 | 0; - } - - TOTAL0 = TOTAL0 + hashed | 0; - if (TOTAL0 >>> 0 < hashed >>> 0) TOTAL1 = TOTAL1 + 1 | 0; - - return hashed | 0; - } - - // offset — multiple of 64 - // output — multiple of 32 - function finish(offset, length, output) { - offset = offset | 0; - length = length | 0; - output = output | 0; - - var hashed = 0, - i = 0; - - if (offset & 63) return -1; - - if (~output) if (output & 31) return -1; - - if ((length | 0) >= 64) { - hashed = process(offset, length) | 0; - if ((hashed | 0) == -1) return -1; - - offset = offset + hashed | 0; - length = length - hashed | 0; - } - - hashed = hashed + length | 0; - TOTAL0 = TOTAL0 + length | 0; - if (TOTAL0 >>> 0 < length >>> 0) TOTAL1 = TOTAL1 + 1 | 0; - - HEAP[offset | length] = 0x80; - - if ((length | 0) >= 56) { - for (i = length + 1 | 0; (i | 0) < 64; i = i + 1 | 0) HEAP[offset | i] = 0x00; - _core_heap(offset); - - length = 0; - - HEAP[offset | 0] = 0; - } - - for (i = length + 1 | 0; (i | 0) < 59; i = i + 1 | 0) HEAP[offset | i] = 0; - - HEAP[offset | 56] = TOTAL1 >>> 21 & 255; - HEAP[offset | 57] = TOTAL1 >>> 13 & 255; - HEAP[offset | 58] = TOTAL1 >>> 5 & 255; - HEAP[offset | 59] = TOTAL1 << 3 & 255 | TOTAL0 >>> 29; - HEAP[offset | 60] = TOTAL0 >>> 21 & 255; - HEAP[offset | 61] = TOTAL0 >>> 13 & 255; - HEAP[offset | 62] = TOTAL0 >>> 5 & 255; - HEAP[offset | 63] = TOTAL0 << 3 & 255; - _core_heap(offset); - - if (~output) _state_to_heap(output); - - return hashed | 0; - } - - function hmac_reset() { - H0 = I0; - H1 = I1; - H2 = I2; - H3 = I3; - H4 = I4; - TOTAL0 = 64; - TOTAL1 = 0; - } - - function _hmac_opad() { - H0 = O0; - H1 = O1; - H2 = O2; - H3 = O3; - H4 = O4; - TOTAL0 = 64; - TOTAL1 = 0; - } - - function hmac_init(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15) { - p0 = p0 | 0; - p1 = p1 | 0; - p2 = p2 | 0; - p3 = p3 | 0; - p4 = p4 | 0; - p5 = p5 | 0; - p6 = p6 | 0; - p7 = p7 | 0; - p8 = p8 | 0; - p9 = p9 | 0; - p10 = p10 | 0; - p11 = p11 | 0; - p12 = p12 | 0; - p13 = p13 | 0; - p14 = p14 | 0; - p15 = p15 | 0; - - // opad - reset(); - _core(p0 ^ 0x5c5c5c5c, p1 ^ 0x5c5c5c5c, p2 ^ 0x5c5c5c5c, p3 ^ 0x5c5c5c5c, p4 ^ 0x5c5c5c5c, p5 ^ 0x5c5c5c5c, p6 ^ 0x5c5c5c5c, p7 ^ 0x5c5c5c5c, p8 ^ 0x5c5c5c5c, p9 ^ 0x5c5c5c5c, p10 ^ 0x5c5c5c5c, p11 ^ 0x5c5c5c5c, p12 ^ 0x5c5c5c5c, p13 ^ 0x5c5c5c5c, p14 ^ 0x5c5c5c5c, p15 ^ 0x5c5c5c5c); - O0 = H0; - O1 = H1; - O2 = H2; - O3 = H3; - O4 = H4; - - // ipad - reset(); - _core(p0 ^ 0x36363636, p1 ^ 0x36363636, p2 ^ 0x36363636, p3 ^ 0x36363636, p4 ^ 0x36363636, p5 ^ 0x36363636, p6 ^ 0x36363636, p7 ^ 0x36363636, p8 ^ 0x36363636, p9 ^ 0x36363636, p10 ^ 0x36363636, p11 ^ 0x36363636, p12 ^ 0x36363636, p13 ^ 0x36363636, p14 ^ 0x36363636, p15 ^ 0x36363636); - I0 = H0; - I1 = H1; - I2 = H2; - I3 = H3; - I4 = H4; - - TOTAL0 = 64; - TOTAL1 = 0; - } - - // offset — multiple of 64 - // output — multiple of 32 - function hmac_finish(offset, length, output) { - offset = offset | 0; - length = length | 0; - output = output | 0; - - var t0 = 0, - t1 = 0, - t2 = 0, - t3 = 0, - t4 = 0, - hashed = 0; - - if (offset & 63) return -1; - - if (~output) if (output & 31) return -1; - - hashed = finish(offset, length, -1) | 0; - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; - - _hmac_opad(); - _core(t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672); - - if (~output) _state_to_heap(output); - - return hashed | 0; - } - - // salt is assumed to be already processed - // offset — multiple of 64 - // output — multiple of 32 - function pbkdf2_generate_block(offset, length, block, count, output) { - offset = offset | 0; - length = length | 0; - block = block | 0; - count = count | 0; - output = output | 0; - - var h0 = 0, - h1 = 0, - h2 = 0, - h3 = 0, - h4 = 0, - t0 = 0, - t1 = 0, - t2 = 0, - t3 = 0, - t4 = 0; - - if (offset & 63) return -1; - - if (~output) if (output & 31) return -1; - - // pad block number into heap - // FIXME probable OOB write - HEAP[offset + length | 0] = block >>> 24; - HEAP[offset + length + 1 | 0] = block >>> 16 & 255; - HEAP[offset + length + 2 | 0] = block >>> 8 & 255; - HEAP[offset + length + 3 | 0] = block & 255; - - // finish first iteration - hmac_finish(offset, length + 4 | 0, -1) | 0; - h0 = t0 = H0, h1 = t1 = H1, h2 = t2 = H2, h3 = t3 = H3, h4 = t4 = H4; - count = count - 1 | 0; - - // perform the rest iterations - while ((count | 0) > 0) { - hmac_reset(); - _core(t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672); - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; - - _hmac_opad(); - _core(t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672); - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; - - h0 = h0 ^ H0; - h1 = h1 ^ H1; - h2 = h2 ^ H2; - h3 = h3 ^ H3; - h4 = h4 ^ H4; - - count = count - 1 | 0; - } - - H0 = h0; - H1 = h1; - H2 = h2; - H3 = h3; - H4 = h4; - - if (~output) _state_to_heap(output); - - return 0; - } - - return { - // SHA1 - reset: reset, - init: init, - process: process, - finish: finish, - - // HMAC-SHA1 - hmac_reset: hmac_reset, - hmac_init: hmac_init, - hmac_finish: hmac_finish, - - // PBKDF2-HMAC-SHA1 - pbkdf2_generate_block: pbkdf2_generate_block - }; -} - -},{}],11:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.Sha1 = exports._sha1_hash_size = exports._sha1_block_size = undefined; - -var _sha = require('./sha1.asm'); - -var _hash = require('../hash'); - -var __extends = undefined && undefined.__extends || function () { - var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) { - d.__proto__ = b; - } || function (d, b) { - for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; - }; - return function (d, b) { - extendStatics(d, b); - function __() { - this.constructor = d; - } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -}(); -var _sha1_block_size = exports._sha1_block_size = 64; -var _sha1_hash_size = exports._sha1_hash_size = 20; -var Sha1 = /** @class */function (_super) { - __extends(Sha1, _super); - function Sha1() { - var _this = _super !== null && _super.apply(this, arguments) || this; - _this.NAME = 'sha1'; - _this.BLOCK_SIZE = _sha1_block_size; - _this.HASH_SIZE = _sha1_hash_size; - return _this; - } - Sha1.bytes = function (data) { - return new Sha1().process(data).finish().result; - }; - Sha1.NAME = 'sha1'; - Sha1.heap_pool = []; - Sha1.asm_pool = []; - Sha1.asm_function = _sha.sha1_asm; - return Sha1; -}(_hash.Hash); -exports.Sha1 = Sha1; - -},{"../hash":9,"./sha1.asm":10}],12:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.sha256_asm = sha256_asm; -function sha256_asm(stdlib, foreign, buffer) { - "use asm"; - - // SHA256 state - - var H0 = 0, - H1 = 0, - H2 = 0, - H3 = 0, - H4 = 0, - H5 = 0, - H6 = 0, - H7 = 0, - TOTAL0 = 0, - TOTAL1 = 0; - - // HMAC state - var I0 = 0, - I1 = 0, - I2 = 0, - I3 = 0, - I4 = 0, - I5 = 0, - I6 = 0, - I7 = 0, - O0 = 0, - O1 = 0, - O2 = 0, - O3 = 0, - O4 = 0, - O5 = 0, - O6 = 0, - O7 = 0; - - // I/O buffer - var HEAP = new stdlib.Uint8Array(buffer); - - function _core(w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15) { - w0 = w0 | 0; - w1 = w1 | 0; - w2 = w2 | 0; - w3 = w3 | 0; - w4 = w4 | 0; - w5 = w5 | 0; - w6 = w6 | 0; - w7 = w7 | 0; - w8 = w8 | 0; - w9 = w9 | 0; - w10 = w10 | 0; - w11 = w11 | 0; - w12 = w12 | 0; - w13 = w13 | 0; - w14 = w14 | 0; - w15 = w15 | 0; - - var a = 0, - b = 0, - c = 0, - d = 0, - e = 0, - f = 0, - g = 0, - h = 0; - - a = H0; - b = H1; - c = H2; - d = H3; - e = H4; - f = H5; - g = H6; - h = H7; - - // 0 - h = w0 + h + (e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7) + (g ^ e & (f ^ g)) + 0x428a2f98 | 0; - d = d + h | 0; - h = h + (a & b ^ c & (a ^ b)) + (a >>> 2 ^ a >>> 13 ^ a >>> 22 ^ a << 30 ^ a << 19 ^ a << 10) | 0; - - // 1 - g = w1 + g + (d >>> 6 ^ d >>> 11 ^ d >>> 25 ^ d << 26 ^ d << 21 ^ d << 7) + (f ^ d & (e ^ f)) + 0x71374491 | 0; - c = c + g | 0; - g = g + (h & a ^ b & (h ^ a)) + (h >>> 2 ^ h >>> 13 ^ h >>> 22 ^ h << 30 ^ h << 19 ^ h << 10) | 0; - - // 2 - f = w2 + f + (c >>> 6 ^ c >>> 11 ^ c >>> 25 ^ c << 26 ^ c << 21 ^ c << 7) + (e ^ c & (d ^ e)) + 0xb5c0fbcf | 0; - b = b + f | 0; - f = f + (g & h ^ a & (g ^ h)) + (g >>> 2 ^ g >>> 13 ^ g >>> 22 ^ g << 30 ^ g << 19 ^ g << 10) | 0; - - // 3 - e = w3 + e + (b >>> 6 ^ b >>> 11 ^ b >>> 25 ^ b << 26 ^ b << 21 ^ b << 7) + (d ^ b & (c ^ d)) + 0xe9b5dba5 | 0; - a = a + e | 0; - e = e + (f & g ^ h & (f ^ g)) + (f >>> 2 ^ f >>> 13 ^ f >>> 22 ^ f << 30 ^ f << 19 ^ f << 10) | 0; - - // 4 - d = w4 + d + (a >>> 6 ^ a >>> 11 ^ a >>> 25 ^ a << 26 ^ a << 21 ^ a << 7) + (c ^ a & (b ^ c)) + 0x3956c25b | 0; - h = h + d | 0; - d = d + (e & f ^ g & (e ^ f)) + (e >>> 2 ^ e >>> 13 ^ e >>> 22 ^ e << 30 ^ e << 19 ^ e << 10) | 0; - - // 5 - c = w5 + c + (h >>> 6 ^ h >>> 11 ^ h >>> 25 ^ h << 26 ^ h << 21 ^ h << 7) + (b ^ h & (a ^ b)) + 0x59f111f1 | 0; - g = g + c | 0; - c = c + (d & e ^ f & (d ^ e)) + (d >>> 2 ^ d >>> 13 ^ d >>> 22 ^ d << 30 ^ d << 19 ^ d << 10) | 0; - - // 6 - b = w6 + b + (g >>> 6 ^ g >>> 11 ^ g >>> 25 ^ g << 26 ^ g << 21 ^ g << 7) + (a ^ g & (h ^ a)) + 0x923f82a4 | 0; - f = f + b | 0; - b = b + (c & d ^ e & (c ^ d)) + (c >>> 2 ^ c >>> 13 ^ c >>> 22 ^ c << 30 ^ c << 19 ^ c << 10) | 0; - - // 7 - a = w7 + a + (f >>> 6 ^ f >>> 11 ^ f >>> 25 ^ f << 26 ^ f << 21 ^ f << 7) + (h ^ f & (g ^ h)) + 0xab1c5ed5 | 0; - e = e + a | 0; - a = a + (b & c ^ d & (b ^ c)) + (b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10) | 0; - - // 8 - h = w8 + h + (e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7) + (g ^ e & (f ^ g)) + 0xd807aa98 | 0; - d = d + h | 0; - h = h + (a & b ^ c & (a ^ b)) + (a >>> 2 ^ a >>> 13 ^ a >>> 22 ^ a << 30 ^ a << 19 ^ a << 10) | 0; - - // 9 - g = w9 + g + (d >>> 6 ^ d >>> 11 ^ d >>> 25 ^ d << 26 ^ d << 21 ^ d << 7) + (f ^ d & (e ^ f)) + 0x12835b01 | 0; - c = c + g | 0; - g = g + (h & a ^ b & (h ^ a)) + (h >>> 2 ^ h >>> 13 ^ h >>> 22 ^ h << 30 ^ h << 19 ^ h << 10) | 0; - - // 10 - f = w10 + f + (c >>> 6 ^ c >>> 11 ^ c >>> 25 ^ c << 26 ^ c << 21 ^ c << 7) + (e ^ c & (d ^ e)) + 0x243185be | 0; - b = b + f | 0; - f = f + (g & h ^ a & (g ^ h)) + (g >>> 2 ^ g >>> 13 ^ g >>> 22 ^ g << 30 ^ g << 19 ^ g << 10) | 0; - - // 11 - e = w11 + e + (b >>> 6 ^ b >>> 11 ^ b >>> 25 ^ b << 26 ^ b << 21 ^ b << 7) + (d ^ b & (c ^ d)) + 0x550c7dc3 | 0; - a = a + e | 0; - e = e + (f & g ^ h & (f ^ g)) + (f >>> 2 ^ f >>> 13 ^ f >>> 22 ^ f << 30 ^ f << 19 ^ f << 10) | 0; - - // 12 - d = w12 + d + (a >>> 6 ^ a >>> 11 ^ a >>> 25 ^ a << 26 ^ a << 21 ^ a << 7) + (c ^ a & (b ^ c)) + 0x72be5d74 | 0; - h = h + d | 0; - d = d + (e & f ^ g & (e ^ f)) + (e >>> 2 ^ e >>> 13 ^ e >>> 22 ^ e << 30 ^ e << 19 ^ e << 10) | 0; - - // 13 - c = w13 + c + (h >>> 6 ^ h >>> 11 ^ h >>> 25 ^ h << 26 ^ h << 21 ^ h << 7) + (b ^ h & (a ^ b)) + 0x80deb1fe | 0; - g = g + c | 0; - c = c + (d & e ^ f & (d ^ e)) + (d >>> 2 ^ d >>> 13 ^ d >>> 22 ^ d << 30 ^ d << 19 ^ d << 10) | 0; - - // 14 - b = w14 + b + (g >>> 6 ^ g >>> 11 ^ g >>> 25 ^ g << 26 ^ g << 21 ^ g << 7) + (a ^ g & (h ^ a)) + 0x9bdc06a7 | 0; - f = f + b | 0; - b = b + (c & d ^ e & (c ^ d)) + (c >>> 2 ^ c >>> 13 ^ c >>> 22 ^ c << 30 ^ c << 19 ^ c << 10) | 0; - - // 15 - a = w15 + a + (f >>> 6 ^ f >>> 11 ^ f >>> 25 ^ f << 26 ^ f << 21 ^ f << 7) + (h ^ f & (g ^ h)) + 0xc19bf174 | 0; - e = e + a | 0; - a = a + (b & c ^ d & (b ^ c)) + (b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10) | 0; - - // 16 - w0 = (w1 >>> 7 ^ w1 >>> 18 ^ w1 >>> 3 ^ w1 << 25 ^ w1 << 14) + (w14 >>> 17 ^ w14 >>> 19 ^ w14 >>> 10 ^ w14 << 15 ^ w14 << 13) + w0 + w9 | 0; - h = w0 + h + (e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7) + (g ^ e & (f ^ g)) + 0xe49b69c1 | 0; - d = d + h | 0; - h = h + (a & b ^ c & (a ^ b)) + (a >>> 2 ^ a >>> 13 ^ a >>> 22 ^ a << 30 ^ a << 19 ^ a << 10) | 0; - - // 17 - w1 = (w2 >>> 7 ^ w2 >>> 18 ^ w2 >>> 3 ^ w2 << 25 ^ w2 << 14) + (w15 >>> 17 ^ w15 >>> 19 ^ w15 >>> 10 ^ w15 << 15 ^ w15 << 13) + w1 + w10 | 0; - g = w1 + g + (d >>> 6 ^ d >>> 11 ^ d >>> 25 ^ d << 26 ^ d << 21 ^ d << 7) + (f ^ d & (e ^ f)) + 0xefbe4786 | 0; - c = c + g | 0; - g = g + (h & a ^ b & (h ^ a)) + (h >>> 2 ^ h >>> 13 ^ h >>> 22 ^ h << 30 ^ h << 19 ^ h << 10) | 0; - - // 18 - w2 = (w3 >>> 7 ^ w3 >>> 18 ^ w3 >>> 3 ^ w3 << 25 ^ w3 << 14) + (w0 >>> 17 ^ w0 >>> 19 ^ w0 >>> 10 ^ w0 << 15 ^ w0 << 13) + w2 + w11 | 0; - f = w2 + f + (c >>> 6 ^ c >>> 11 ^ c >>> 25 ^ c << 26 ^ c << 21 ^ c << 7) + (e ^ c & (d ^ e)) + 0x0fc19dc6 | 0; - b = b + f | 0; - f = f + (g & h ^ a & (g ^ h)) + (g >>> 2 ^ g >>> 13 ^ g >>> 22 ^ g << 30 ^ g << 19 ^ g << 10) | 0; - - // 19 - w3 = (w4 >>> 7 ^ w4 >>> 18 ^ w4 >>> 3 ^ w4 << 25 ^ w4 << 14) + (w1 >>> 17 ^ w1 >>> 19 ^ w1 >>> 10 ^ w1 << 15 ^ w1 << 13) + w3 + w12 | 0; - e = w3 + e + (b >>> 6 ^ b >>> 11 ^ b >>> 25 ^ b << 26 ^ b << 21 ^ b << 7) + (d ^ b & (c ^ d)) + 0x240ca1cc | 0; - a = a + e | 0; - e = e + (f & g ^ h & (f ^ g)) + (f >>> 2 ^ f >>> 13 ^ f >>> 22 ^ f << 30 ^ f << 19 ^ f << 10) | 0; - - // 20 - w4 = (w5 >>> 7 ^ w5 >>> 18 ^ w5 >>> 3 ^ w5 << 25 ^ w5 << 14) + (w2 >>> 17 ^ w2 >>> 19 ^ w2 >>> 10 ^ w2 << 15 ^ w2 << 13) + w4 + w13 | 0; - d = w4 + d + (a >>> 6 ^ a >>> 11 ^ a >>> 25 ^ a << 26 ^ a << 21 ^ a << 7) + (c ^ a & (b ^ c)) + 0x2de92c6f | 0; - h = h + d | 0; - d = d + (e & f ^ g & (e ^ f)) + (e >>> 2 ^ e >>> 13 ^ e >>> 22 ^ e << 30 ^ e << 19 ^ e << 10) | 0; - - // 21 - w5 = (w6 >>> 7 ^ w6 >>> 18 ^ w6 >>> 3 ^ w6 << 25 ^ w6 << 14) + (w3 >>> 17 ^ w3 >>> 19 ^ w3 >>> 10 ^ w3 << 15 ^ w3 << 13) + w5 + w14 | 0; - c = w5 + c + (h >>> 6 ^ h >>> 11 ^ h >>> 25 ^ h << 26 ^ h << 21 ^ h << 7) + (b ^ h & (a ^ b)) + 0x4a7484aa | 0; - g = g + c | 0; - c = c + (d & e ^ f & (d ^ e)) + (d >>> 2 ^ d >>> 13 ^ d >>> 22 ^ d << 30 ^ d << 19 ^ d << 10) | 0; - - // 22 - w6 = (w7 >>> 7 ^ w7 >>> 18 ^ w7 >>> 3 ^ w7 << 25 ^ w7 << 14) + (w4 >>> 17 ^ w4 >>> 19 ^ w4 >>> 10 ^ w4 << 15 ^ w4 << 13) + w6 + w15 | 0; - b = w6 + b + (g >>> 6 ^ g >>> 11 ^ g >>> 25 ^ g << 26 ^ g << 21 ^ g << 7) + (a ^ g & (h ^ a)) + 0x5cb0a9dc | 0; - f = f + b | 0; - b = b + (c & d ^ e & (c ^ d)) + (c >>> 2 ^ c >>> 13 ^ c >>> 22 ^ c << 30 ^ c << 19 ^ c << 10) | 0; - - // 23 - w7 = (w8 >>> 7 ^ w8 >>> 18 ^ w8 >>> 3 ^ w8 << 25 ^ w8 << 14) + (w5 >>> 17 ^ w5 >>> 19 ^ w5 >>> 10 ^ w5 << 15 ^ w5 << 13) + w7 + w0 | 0; - a = w7 + a + (f >>> 6 ^ f >>> 11 ^ f >>> 25 ^ f << 26 ^ f << 21 ^ f << 7) + (h ^ f & (g ^ h)) + 0x76f988da | 0; - e = e + a | 0; - a = a + (b & c ^ d & (b ^ c)) + (b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10) | 0; - - // 24 - w8 = (w9 >>> 7 ^ w9 >>> 18 ^ w9 >>> 3 ^ w9 << 25 ^ w9 << 14) + (w6 >>> 17 ^ w6 >>> 19 ^ w6 >>> 10 ^ w6 << 15 ^ w6 << 13) + w8 + w1 | 0; - h = w8 + h + (e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7) + (g ^ e & (f ^ g)) + 0x983e5152 | 0; - d = d + h | 0; - h = h + (a & b ^ c & (a ^ b)) + (a >>> 2 ^ a >>> 13 ^ a >>> 22 ^ a << 30 ^ a << 19 ^ a << 10) | 0; - - // 25 - w9 = (w10 >>> 7 ^ w10 >>> 18 ^ w10 >>> 3 ^ w10 << 25 ^ w10 << 14) + (w7 >>> 17 ^ w7 >>> 19 ^ w7 >>> 10 ^ w7 << 15 ^ w7 << 13) + w9 + w2 | 0; - g = w9 + g + (d >>> 6 ^ d >>> 11 ^ d >>> 25 ^ d << 26 ^ d << 21 ^ d << 7) + (f ^ d & (e ^ f)) + 0xa831c66d | 0; - c = c + g | 0; - g = g + (h & a ^ b & (h ^ a)) + (h >>> 2 ^ h >>> 13 ^ h >>> 22 ^ h << 30 ^ h << 19 ^ h << 10) | 0; - - // 26 - w10 = (w11 >>> 7 ^ w11 >>> 18 ^ w11 >>> 3 ^ w11 << 25 ^ w11 << 14) + (w8 >>> 17 ^ w8 >>> 19 ^ w8 >>> 10 ^ w8 << 15 ^ w8 << 13) + w10 + w3 | 0; - f = w10 + f + (c >>> 6 ^ c >>> 11 ^ c >>> 25 ^ c << 26 ^ c << 21 ^ c << 7) + (e ^ c & (d ^ e)) + 0xb00327c8 | 0; - b = b + f | 0; - f = f + (g & h ^ a & (g ^ h)) + (g >>> 2 ^ g >>> 13 ^ g >>> 22 ^ g << 30 ^ g << 19 ^ g << 10) | 0; - - // 27 - w11 = (w12 >>> 7 ^ w12 >>> 18 ^ w12 >>> 3 ^ w12 << 25 ^ w12 << 14) + (w9 >>> 17 ^ w9 >>> 19 ^ w9 >>> 10 ^ w9 << 15 ^ w9 << 13) + w11 + w4 | 0; - e = w11 + e + (b >>> 6 ^ b >>> 11 ^ b >>> 25 ^ b << 26 ^ b << 21 ^ b << 7) + (d ^ b & (c ^ d)) + 0xbf597fc7 | 0; - a = a + e | 0; - e = e + (f & g ^ h & (f ^ g)) + (f >>> 2 ^ f >>> 13 ^ f >>> 22 ^ f << 30 ^ f << 19 ^ f << 10) | 0; - - // 28 - w12 = (w13 >>> 7 ^ w13 >>> 18 ^ w13 >>> 3 ^ w13 << 25 ^ w13 << 14) + (w10 >>> 17 ^ w10 >>> 19 ^ w10 >>> 10 ^ w10 << 15 ^ w10 << 13) + w12 + w5 | 0; - d = w12 + d + (a >>> 6 ^ a >>> 11 ^ a >>> 25 ^ a << 26 ^ a << 21 ^ a << 7) + (c ^ a & (b ^ c)) + 0xc6e00bf3 | 0; - h = h + d | 0; - d = d + (e & f ^ g & (e ^ f)) + (e >>> 2 ^ e >>> 13 ^ e >>> 22 ^ e << 30 ^ e << 19 ^ e << 10) | 0; - - // 29 - w13 = (w14 >>> 7 ^ w14 >>> 18 ^ w14 >>> 3 ^ w14 << 25 ^ w14 << 14) + (w11 >>> 17 ^ w11 >>> 19 ^ w11 >>> 10 ^ w11 << 15 ^ w11 << 13) + w13 + w6 | 0; - c = w13 + c + (h >>> 6 ^ h >>> 11 ^ h >>> 25 ^ h << 26 ^ h << 21 ^ h << 7) + (b ^ h & (a ^ b)) + 0xd5a79147 | 0; - g = g + c | 0; - c = c + (d & e ^ f & (d ^ e)) + (d >>> 2 ^ d >>> 13 ^ d >>> 22 ^ d << 30 ^ d << 19 ^ d << 10) | 0; - - // 30 - w14 = (w15 >>> 7 ^ w15 >>> 18 ^ w15 >>> 3 ^ w15 << 25 ^ w15 << 14) + (w12 >>> 17 ^ w12 >>> 19 ^ w12 >>> 10 ^ w12 << 15 ^ w12 << 13) + w14 + w7 | 0; - b = w14 + b + (g >>> 6 ^ g >>> 11 ^ g >>> 25 ^ g << 26 ^ g << 21 ^ g << 7) + (a ^ g & (h ^ a)) + 0x06ca6351 | 0; - f = f + b | 0; - b = b + (c & d ^ e & (c ^ d)) + (c >>> 2 ^ c >>> 13 ^ c >>> 22 ^ c << 30 ^ c << 19 ^ c << 10) | 0; - - // 31 - w15 = (w0 >>> 7 ^ w0 >>> 18 ^ w0 >>> 3 ^ w0 << 25 ^ w0 << 14) + (w13 >>> 17 ^ w13 >>> 19 ^ w13 >>> 10 ^ w13 << 15 ^ w13 << 13) + w15 + w8 | 0; - a = w15 + a + (f >>> 6 ^ f >>> 11 ^ f >>> 25 ^ f << 26 ^ f << 21 ^ f << 7) + (h ^ f & (g ^ h)) + 0x14292967 | 0; - e = e + a | 0; - a = a + (b & c ^ d & (b ^ c)) + (b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10) | 0; - - // 32 - w0 = (w1 >>> 7 ^ w1 >>> 18 ^ w1 >>> 3 ^ w1 << 25 ^ w1 << 14) + (w14 >>> 17 ^ w14 >>> 19 ^ w14 >>> 10 ^ w14 << 15 ^ w14 << 13) + w0 + w9 | 0; - h = w0 + h + (e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7) + (g ^ e & (f ^ g)) + 0x27b70a85 | 0; - d = d + h | 0; - h = h + (a & b ^ c & (a ^ b)) + (a >>> 2 ^ a >>> 13 ^ a >>> 22 ^ a << 30 ^ a << 19 ^ a << 10) | 0; - - // 33 - w1 = (w2 >>> 7 ^ w2 >>> 18 ^ w2 >>> 3 ^ w2 << 25 ^ w2 << 14) + (w15 >>> 17 ^ w15 >>> 19 ^ w15 >>> 10 ^ w15 << 15 ^ w15 << 13) + w1 + w10 | 0; - g = w1 + g + (d >>> 6 ^ d >>> 11 ^ d >>> 25 ^ d << 26 ^ d << 21 ^ d << 7) + (f ^ d & (e ^ f)) + 0x2e1b2138 | 0; - c = c + g | 0; - g = g + (h & a ^ b & (h ^ a)) + (h >>> 2 ^ h >>> 13 ^ h >>> 22 ^ h << 30 ^ h << 19 ^ h << 10) | 0; - - // 34 - w2 = (w3 >>> 7 ^ w3 >>> 18 ^ w3 >>> 3 ^ w3 << 25 ^ w3 << 14) + (w0 >>> 17 ^ w0 >>> 19 ^ w0 >>> 10 ^ w0 << 15 ^ w0 << 13) + w2 + w11 | 0; - f = w2 + f + (c >>> 6 ^ c >>> 11 ^ c >>> 25 ^ c << 26 ^ c << 21 ^ c << 7) + (e ^ c & (d ^ e)) + 0x4d2c6dfc | 0; - b = b + f | 0; - f = f + (g & h ^ a & (g ^ h)) + (g >>> 2 ^ g >>> 13 ^ g >>> 22 ^ g << 30 ^ g << 19 ^ g << 10) | 0; - - // 35 - w3 = (w4 >>> 7 ^ w4 >>> 18 ^ w4 >>> 3 ^ w4 << 25 ^ w4 << 14) + (w1 >>> 17 ^ w1 >>> 19 ^ w1 >>> 10 ^ w1 << 15 ^ w1 << 13) + w3 + w12 | 0; - e = w3 + e + (b >>> 6 ^ b >>> 11 ^ b >>> 25 ^ b << 26 ^ b << 21 ^ b << 7) + (d ^ b & (c ^ d)) + 0x53380d13 | 0; - a = a + e | 0; - e = e + (f & g ^ h & (f ^ g)) + (f >>> 2 ^ f >>> 13 ^ f >>> 22 ^ f << 30 ^ f << 19 ^ f << 10) | 0; - - // 36 - w4 = (w5 >>> 7 ^ w5 >>> 18 ^ w5 >>> 3 ^ w5 << 25 ^ w5 << 14) + (w2 >>> 17 ^ w2 >>> 19 ^ w2 >>> 10 ^ w2 << 15 ^ w2 << 13) + w4 + w13 | 0; - d = w4 + d + (a >>> 6 ^ a >>> 11 ^ a >>> 25 ^ a << 26 ^ a << 21 ^ a << 7) + (c ^ a & (b ^ c)) + 0x650a7354 | 0; - h = h + d | 0; - d = d + (e & f ^ g & (e ^ f)) + (e >>> 2 ^ e >>> 13 ^ e >>> 22 ^ e << 30 ^ e << 19 ^ e << 10) | 0; - - // 37 - w5 = (w6 >>> 7 ^ w6 >>> 18 ^ w6 >>> 3 ^ w6 << 25 ^ w6 << 14) + (w3 >>> 17 ^ w3 >>> 19 ^ w3 >>> 10 ^ w3 << 15 ^ w3 << 13) + w5 + w14 | 0; - c = w5 + c + (h >>> 6 ^ h >>> 11 ^ h >>> 25 ^ h << 26 ^ h << 21 ^ h << 7) + (b ^ h & (a ^ b)) + 0x766a0abb | 0; - g = g + c | 0; - c = c + (d & e ^ f & (d ^ e)) + (d >>> 2 ^ d >>> 13 ^ d >>> 22 ^ d << 30 ^ d << 19 ^ d << 10) | 0; - - // 38 - w6 = (w7 >>> 7 ^ w7 >>> 18 ^ w7 >>> 3 ^ w7 << 25 ^ w7 << 14) + (w4 >>> 17 ^ w4 >>> 19 ^ w4 >>> 10 ^ w4 << 15 ^ w4 << 13) + w6 + w15 | 0; - b = w6 + b + (g >>> 6 ^ g >>> 11 ^ g >>> 25 ^ g << 26 ^ g << 21 ^ g << 7) + (a ^ g & (h ^ a)) + 0x81c2c92e | 0; - f = f + b | 0; - b = b + (c & d ^ e & (c ^ d)) + (c >>> 2 ^ c >>> 13 ^ c >>> 22 ^ c << 30 ^ c << 19 ^ c << 10) | 0; - - // 39 - w7 = (w8 >>> 7 ^ w8 >>> 18 ^ w8 >>> 3 ^ w8 << 25 ^ w8 << 14) + (w5 >>> 17 ^ w5 >>> 19 ^ w5 >>> 10 ^ w5 << 15 ^ w5 << 13) + w7 + w0 | 0; - a = w7 + a + (f >>> 6 ^ f >>> 11 ^ f >>> 25 ^ f << 26 ^ f << 21 ^ f << 7) + (h ^ f & (g ^ h)) + 0x92722c85 | 0; - e = e + a | 0; - a = a + (b & c ^ d & (b ^ c)) + (b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10) | 0; - - // 40 - w8 = (w9 >>> 7 ^ w9 >>> 18 ^ w9 >>> 3 ^ w9 << 25 ^ w9 << 14) + (w6 >>> 17 ^ w6 >>> 19 ^ w6 >>> 10 ^ w6 << 15 ^ w6 << 13) + w8 + w1 | 0; - h = w8 + h + (e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7) + (g ^ e & (f ^ g)) + 0xa2bfe8a1 | 0; - d = d + h | 0; - h = h + (a & b ^ c & (a ^ b)) + (a >>> 2 ^ a >>> 13 ^ a >>> 22 ^ a << 30 ^ a << 19 ^ a << 10) | 0; - - // 41 - w9 = (w10 >>> 7 ^ w10 >>> 18 ^ w10 >>> 3 ^ w10 << 25 ^ w10 << 14) + (w7 >>> 17 ^ w7 >>> 19 ^ w7 >>> 10 ^ w7 << 15 ^ w7 << 13) + w9 + w2 | 0; - g = w9 + g + (d >>> 6 ^ d >>> 11 ^ d >>> 25 ^ d << 26 ^ d << 21 ^ d << 7) + (f ^ d & (e ^ f)) + 0xa81a664b | 0; - c = c + g | 0; - g = g + (h & a ^ b & (h ^ a)) + (h >>> 2 ^ h >>> 13 ^ h >>> 22 ^ h << 30 ^ h << 19 ^ h << 10) | 0; - - // 42 - w10 = (w11 >>> 7 ^ w11 >>> 18 ^ w11 >>> 3 ^ w11 << 25 ^ w11 << 14) + (w8 >>> 17 ^ w8 >>> 19 ^ w8 >>> 10 ^ w8 << 15 ^ w8 << 13) + w10 + w3 | 0; - f = w10 + f + (c >>> 6 ^ c >>> 11 ^ c >>> 25 ^ c << 26 ^ c << 21 ^ c << 7) + (e ^ c & (d ^ e)) + 0xc24b8b70 | 0; - b = b + f | 0; - f = f + (g & h ^ a & (g ^ h)) + (g >>> 2 ^ g >>> 13 ^ g >>> 22 ^ g << 30 ^ g << 19 ^ g << 10) | 0; - - // 43 - w11 = (w12 >>> 7 ^ w12 >>> 18 ^ w12 >>> 3 ^ w12 << 25 ^ w12 << 14) + (w9 >>> 17 ^ w9 >>> 19 ^ w9 >>> 10 ^ w9 << 15 ^ w9 << 13) + w11 + w4 | 0; - e = w11 + e + (b >>> 6 ^ b >>> 11 ^ b >>> 25 ^ b << 26 ^ b << 21 ^ b << 7) + (d ^ b & (c ^ d)) + 0xc76c51a3 | 0; - a = a + e | 0; - e = e + (f & g ^ h & (f ^ g)) + (f >>> 2 ^ f >>> 13 ^ f >>> 22 ^ f << 30 ^ f << 19 ^ f << 10) | 0; - - // 44 - w12 = (w13 >>> 7 ^ w13 >>> 18 ^ w13 >>> 3 ^ w13 << 25 ^ w13 << 14) + (w10 >>> 17 ^ w10 >>> 19 ^ w10 >>> 10 ^ w10 << 15 ^ w10 << 13) + w12 + w5 | 0; - d = w12 + d + (a >>> 6 ^ a >>> 11 ^ a >>> 25 ^ a << 26 ^ a << 21 ^ a << 7) + (c ^ a & (b ^ c)) + 0xd192e819 | 0; - h = h + d | 0; - d = d + (e & f ^ g & (e ^ f)) + (e >>> 2 ^ e >>> 13 ^ e >>> 22 ^ e << 30 ^ e << 19 ^ e << 10) | 0; - - // 45 - w13 = (w14 >>> 7 ^ w14 >>> 18 ^ w14 >>> 3 ^ w14 << 25 ^ w14 << 14) + (w11 >>> 17 ^ w11 >>> 19 ^ w11 >>> 10 ^ w11 << 15 ^ w11 << 13) + w13 + w6 | 0; - c = w13 + c + (h >>> 6 ^ h >>> 11 ^ h >>> 25 ^ h << 26 ^ h << 21 ^ h << 7) + (b ^ h & (a ^ b)) + 0xd6990624 | 0; - g = g + c | 0; - c = c + (d & e ^ f & (d ^ e)) + (d >>> 2 ^ d >>> 13 ^ d >>> 22 ^ d << 30 ^ d << 19 ^ d << 10) | 0; - - // 46 - w14 = (w15 >>> 7 ^ w15 >>> 18 ^ w15 >>> 3 ^ w15 << 25 ^ w15 << 14) + (w12 >>> 17 ^ w12 >>> 19 ^ w12 >>> 10 ^ w12 << 15 ^ w12 << 13) + w14 + w7 | 0; - b = w14 + b + (g >>> 6 ^ g >>> 11 ^ g >>> 25 ^ g << 26 ^ g << 21 ^ g << 7) + (a ^ g & (h ^ a)) + 0xf40e3585 | 0; - f = f + b | 0; - b = b + (c & d ^ e & (c ^ d)) + (c >>> 2 ^ c >>> 13 ^ c >>> 22 ^ c << 30 ^ c << 19 ^ c << 10) | 0; - - // 47 - w15 = (w0 >>> 7 ^ w0 >>> 18 ^ w0 >>> 3 ^ w0 << 25 ^ w0 << 14) + (w13 >>> 17 ^ w13 >>> 19 ^ w13 >>> 10 ^ w13 << 15 ^ w13 << 13) + w15 + w8 | 0; - a = w15 + a + (f >>> 6 ^ f >>> 11 ^ f >>> 25 ^ f << 26 ^ f << 21 ^ f << 7) + (h ^ f & (g ^ h)) + 0x106aa070 | 0; - e = e + a | 0; - a = a + (b & c ^ d & (b ^ c)) + (b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10) | 0; - - // 48 - w0 = (w1 >>> 7 ^ w1 >>> 18 ^ w1 >>> 3 ^ w1 << 25 ^ w1 << 14) + (w14 >>> 17 ^ w14 >>> 19 ^ w14 >>> 10 ^ w14 << 15 ^ w14 << 13) + w0 + w9 | 0; - h = w0 + h + (e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7) + (g ^ e & (f ^ g)) + 0x19a4c116 | 0; - d = d + h | 0; - h = h + (a & b ^ c & (a ^ b)) + (a >>> 2 ^ a >>> 13 ^ a >>> 22 ^ a << 30 ^ a << 19 ^ a << 10) | 0; - - // 49 - w1 = (w2 >>> 7 ^ w2 >>> 18 ^ w2 >>> 3 ^ w2 << 25 ^ w2 << 14) + (w15 >>> 17 ^ w15 >>> 19 ^ w15 >>> 10 ^ w15 << 15 ^ w15 << 13) + w1 + w10 | 0; - g = w1 + g + (d >>> 6 ^ d >>> 11 ^ d >>> 25 ^ d << 26 ^ d << 21 ^ d << 7) + (f ^ d & (e ^ f)) + 0x1e376c08 | 0; - c = c + g | 0; - g = g + (h & a ^ b & (h ^ a)) + (h >>> 2 ^ h >>> 13 ^ h >>> 22 ^ h << 30 ^ h << 19 ^ h << 10) | 0; - - // 50 - w2 = (w3 >>> 7 ^ w3 >>> 18 ^ w3 >>> 3 ^ w3 << 25 ^ w3 << 14) + (w0 >>> 17 ^ w0 >>> 19 ^ w0 >>> 10 ^ w0 << 15 ^ w0 << 13) + w2 + w11 | 0; - f = w2 + f + (c >>> 6 ^ c >>> 11 ^ c >>> 25 ^ c << 26 ^ c << 21 ^ c << 7) + (e ^ c & (d ^ e)) + 0x2748774c | 0; - b = b + f | 0; - f = f + (g & h ^ a & (g ^ h)) + (g >>> 2 ^ g >>> 13 ^ g >>> 22 ^ g << 30 ^ g << 19 ^ g << 10) | 0; - - // 51 - w3 = (w4 >>> 7 ^ w4 >>> 18 ^ w4 >>> 3 ^ w4 << 25 ^ w4 << 14) + (w1 >>> 17 ^ w1 >>> 19 ^ w1 >>> 10 ^ w1 << 15 ^ w1 << 13) + w3 + w12 | 0; - e = w3 + e + (b >>> 6 ^ b >>> 11 ^ b >>> 25 ^ b << 26 ^ b << 21 ^ b << 7) + (d ^ b & (c ^ d)) + 0x34b0bcb5 | 0; - a = a + e | 0; - e = e + (f & g ^ h & (f ^ g)) + (f >>> 2 ^ f >>> 13 ^ f >>> 22 ^ f << 30 ^ f << 19 ^ f << 10) | 0; - - // 52 - w4 = (w5 >>> 7 ^ w5 >>> 18 ^ w5 >>> 3 ^ w5 << 25 ^ w5 << 14) + (w2 >>> 17 ^ w2 >>> 19 ^ w2 >>> 10 ^ w2 << 15 ^ w2 << 13) + w4 + w13 | 0; - d = w4 + d + (a >>> 6 ^ a >>> 11 ^ a >>> 25 ^ a << 26 ^ a << 21 ^ a << 7) + (c ^ a & (b ^ c)) + 0x391c0cb3 | 0; - h = h + d | 0; - d = d + (e & f ^ g & (e ^ f)) + (e >>> 2 ^ e >>> 13 ^ e >>> 22 ^ e << 30 ^ e << 19 ^ e << 10) | 0; - - // 53 - w5 = (w6 >>> 7 ^ w6 >>> 18 ^ w6 >>> 3 ^ w6 << 25 ^ w6 << 14) + (w3 >>> 17 ^ w3 >>> 19 ^ w3 >>> 10 ^ w3 << 15 ^ w3 << 13) + w5 + w14 | 0; - c = w5 + c + (h >>> 6 ^ h >>> 11 ^ h >>> 25 ^ h << 26 ^ h << 21 ^ h << 7) + (b ^ h & (a ^ b)) + 0x4ed8aa4a | 0; - g = g + c | 0; - c = c + (d & e ^ f & (d ^ e)) + (d >>> 2 ^ d >>> 13 ^ d >>> 22 ^ d << 30 ^ d << 19 ^ d << 10) | 0; - - // 54 - w6 = (w7 >>> 7 ^ w7 >>> 18 ^ w7 >>> 3 ^ w7 << 25 ^ w7 << 14) + (w4 >>> 17 ^ w4 >>> 19 ^ w4 >>> 10 ^ w4 << 15 ^ w4 << 13) + w6 + w15 | 0; - b = w6 + b + (g >>> 6 ^ g >>> 11 ^ g >>> 25 ^ g << 26 ^ g << 21 ^ g << 7) + (a ^ g & (h ^ a)) + 0x5b9cca4f | 0; - f = f + b | 0; - b = b + (c & d ^ e & (c ^ d)) + (c >>> 2 ^ c >>> 13 ^ c >>> 22 ^ c << 30 ^ c << 19 ^ c << 10) | 0; - - // 55 - w7 = (w8 >>> 7 ^ w8 >>> 18 ^ w8 >>> 3 ^ w8 << 25 ^ w8 << 14) + (w5 >>> 17 ^ w5 >>> 19 ^ w5 >>> 10 ^ w5 << 15 ^ w5 << 13) + w7 + w0 | 0; - a = w7 + a + (f >>> 6 ^ f >>> 11 ^ f >>> 25 ^ f << 26 ^ f << 21 ^ f << 7) + (h ^ f & (g ^ h)) + 0x682e6ff3 | 0; - e = e + a | 0; - a = a + (b & c ^ d & (b ^ c)) + (b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10) | 0; - - // 56 - w8 = (w9 >>> 7 ^ w9 >>> 18 ^ w9 >>> 3 ^ w9 << 25 ^ w9 << 14) + (w6 >>> 17 ^ w6 >>> 19 ^ w6 >>> 10 ^ w6 << 15 ^ w6 << 13) + w8 + w1 | 0; - h = w8 + h + (e >>> 6 ^ e >>> 11 ^ e >>> 25 ^ e << 26 ^ e << 21 ^ e << 7) + (g ^ e & (f ^ g)) + 0x748f82ee | 0; - d = d + h | 0; - h = h + (a & b ^ c & (a ^ b)) + (a >>> 2 ^ a >>> 13 ^ a >>> 22 ^ a << 30 ^ a << 19 ^ a << 10) | 0; - - // 57 - w9 = (w10 >>> 7 ^ w10 >>> 18 ^ w10 >>> 3 ^ w10 << 25 ^ w10 << 14) + (w7 >>> 17 ^ w7 >>> 19 ^ w7 >>> 10 ^ w7 << 15 ^ w7 << 13) + w9 + w2 | 0; - g = w9 + g + (d >>> 6 ^ d >>> 11 ^ d >>> 25 ^ d << 26 ^ d << 21 ^ d << 7) + (f ^ d & (e ^ f)) + 0x78a5636f | 0; - c = c + g | 0; - g = g + (h & a ^ b & (h ^ a)) + (h >>> 2 ^ h >>> 13 ^ h >>> 22 ^ h << 30 ^ h << 19 ^ h << 10) | 0; - - // 58 - w10 = (w11 >>> 7 ^ w11 >>> 18 ^ w11 >>> 3 ^ w11 << 25 ^ w11 << 14) + (w8 >>> 17 ^ w8 >>> 19 ^ w8 >>> 10 ^ w8 << 15 ^ w8 << 13) + w10 + w3 | 0; - f = w10 + f + (c >>> 6 ^ c >>> 11 ^ c >>> 25 ^ c << 26 ^ c << 21 ^ c << 7) + (e ^ c & (d ^ e)) + 0x84c87814 | 0; - b = b + f | 0; - f = f + (g & h ^ a & (g ^ h)) + (g >>> 2 ^ g >>> 13 ^ g >>> 22 ^ g << 30 ^ g << 19 ^ g << 10) | 0; - - // 59 - w11 = (w12 >>> 7 ^ w12 >>> 18 ^ w12 >>> 3 ^ w12 << 25 ^ w12 << 14) + (w9 >>> 17 ^ w9 >>> 19 ^ w9 >>> 10 ^ w9 << 15 ^ w9 << 13) + w11 + w4 | 0; - e = w11 + e + (b >>> 6 ^ b >>> 11 ^ b >>> 25 ^ b << 26 ^ b << 21 ^ b << 7) + (d ^ b & (c ^ d)) + 0x8cc70208 | 0; - a = a + e | 0; - e = e + (f & g ^ h & (f ^ g)) + (f >>> 2 ^ f >>> 13 ^ f >>> 22 ^ f << 30 ^ f << 19 ^ f << 10) | 0; - - // 60 - w12 = (w13 >>> 7 ^ w13 >>> 18 ^ w13 >>> 3 ^ w13 << 25 ^ w13 << 14) + (w10 >>> 17 ^ w10 >>> 19 ^ w10 >>> 10 ^ w10 << 15 ^ w10 << 13) + w12 + w5 | 0; - d = w12 + d + (a >>> 6 ^ a >>> 11 ^ a >>> 25 ^ a << 26 ^ a << 21 ^ a << 7) + (c ^ a & (b ^ c)) + 0x90befffa | 0; - h = h + d | 0; - d = d + (e & f ^ g & (e ^ f)) + (e >>> 2 ^ e >>> 13 ^ e >>> 22 ^ e << 30 ^ e << 19 ^ e << 10) | 0; - - // 61 - w13 = (w14 >>> 7 ^ w14 >>> 18 ^ w14 >>> 3 ^ w14 << 25 ^ w14 << 14) + (w11 >>> 17 ^ w11 >>> 19 ^ w11 >>> 10 ^ w11 << 15 ^ w11 << 13) + w13 + w6 | 0; - c = w13 + c + (h >>> 6 ^ h >>> 11 ^ h >>> 25 ^ h << 26 ^ h << 21 ^ h << 7) + (b ^ h & (a ^ b)) + 0xa4506ceb | 0; - g = g + c | 0; - c = c + (d & e ^ f & (d ^ e)) + (d >>> 2 ^ d >>> 13 ^ d >>> 22 ^ d << 30 ^ d << 19 ^ d << 10) | 0; - - // 62 - w14 = (w15 >>> 7 ^ w15 >>> 18 ^ w15 >>> 3 ^ w15 << 25 ^ w15 << 14) + (w12 >>> 17 ^ w12 >>> 19 ^ w12 >>> 10 ^ w12 << 15 ^ w12 << 13) + w14 + w7 | 0; - b = w14 + b + (g >>> 6 ^ g >>> 11 ^ g >>> 25 ^ g << 26 ^ g << 21 ^ g << 7) + (a ^ g & (h ^ a)) + 0xbef9a3f7 | 0; - f = f + b | 0; - b = b + (c & d ^ e & (c ^ d)) + (c >>> 2 ^ c >>> 13 ^ c >>> 22 ^ c << 30 ^ c << 19 ^ c << 10) | 0; - - // 63 - w15 = (w0 >>> 7 ^ w0 >>> 18 ^ w0 >>> 3 ^ w0 << 25 ^ w0 << 14) + (w13 >>> 17 ^ w13 >>> 19 ^ w13 >>> 10 ^ w13 << 15 ^ w13 << 13) + w15 + w8 | 0; - a = w15 + a + (f >>> 6 ^ f >>> 11 ^ f >>> 25 ^ f << 26 ^ f << 21 ^ f << 7) + (h ^ f & (g ^ h)) + 0xc67178f2 | 0; - e = e + a | 0; - a = a + (b & c ^ d & (b ^ c)) + (b >>> 2 ^ b >>> 13 ^ b >>> 22 ^ b << 30 ^ b << 19 ^ b << 10) | 0; - - H0 = H0 + a | 0; - H1 = H1 + b | 0; - H2 = H2 + c | 0; - H3 = H3 + d | 0; - H4 = H4 + e | 0; - H5 = H5 + f | 0; - H6 = H6 + g | 0; - H7 = H7 + h | 0; - } - - function _core_heap(offset) { - offset = offset | 0; - - _core(HEAP[offset | 0] << 24 | HEAP[offset | 1] << 16 | HEAP[offset | 2] << 8 | HEAP[offset | 3], HEAP[offset | 4] << 24 | HEAP[offset | 5] << 16 | HEAP[offset | 6] << 8 | HEAP[offset | 7], HEAP[offset | 8] << 24 | HEAP[offset | 9] << 16 | HEAP[offset | 10] << 8 | HEAP[offset | 11], HEAP[offset | 12] << 24 | HEAP[offset | 13] << 16 | HEAP[offset | 14] << 8 | HEAP[offset | 15], HEAP[offset | 16] << 24 | HEAP[offset | 17] << 16 | HEAP[offset | 18] << 8 | HEAP[offset | 19], HEAP[offset | 20] << 24 | HEAP[offset | 21] << 16 | HEAP[offset | 22] << 8 | HEAP[offset | 23], HEAP[offset | 24] << 24 | HEAP[offset | 25] << 16 | HEAP[offset | 26] << 8 | HEAP[offset | 27], HEAP[offset | 28] << 24 | HEAP[offset | 29] << 16 | HEAP[offset | 30] << 8 | HEAP[offset | 31], HEAP[offset | 32] << 24 | HEAP[offset | 33] << 16 | HEAP[offset | 34] << 8 | HEAP[offset | 35], HEAP[offset | 36] << 24 | HEAP[offset | 37] << 16 | HEAP[offset | 38] << 8 | HEAP[offset | 39], HEAP[offset | 40] << 24 | HEAP[offset | 41] << 16 | HEAP[offset | 42] << 8 | HEAP[offset | 43], HEAP[offset | 44] << 24 | HEAP[offset | 45] << 16 | HEAP[offset | 46] << 8 | HEAP[offset | 47], HEAP[offset | 48] << 24 | HEAP[offset | 49] << 16 | HEAP[offset | 50] << 8 | HEAP[offset | 51], HEAP[offset | 52] << 24 | HEAP[offset | 53] << 16 | HEAP[offset | 54] << 8 | HEAP[offset | 55], HEAP[offset | 56] << 24 | HEAP[offset | 57] << 16 | HEAP[offset | 58] << 8 | HEAP[offset | 59], HEAP[offset | 60] << 24 | HEAP[offset | 61] << 16 | HEAP[offset | 62] << 8 | HEAP[offset | 63]); - } - - // offset — multiple of 32 - function _state_to_heap(output) { - output = output | 0; - - HEAP[output | 0] = H0 >>> 24; - HEAP[output | 1] = H0 >>> 16 & 255; - HEAP[output | 2] = H0 >>> 8 & 255; - HEAP[output | 3] = H0 & 255; - HEAP[output | 4] = H1 >>> 24; - HEAP[output | 5] = H1 >>> 16 & 255; - HEAP[output | 6] = H1 >>> 8 & 255; - HEAP[output | 7] = H1 & 255; - HEAP[output | 8] = H2 >>> 24; - HEAP[output | 9] = H2 >>> 16 & 255; - HEAP[output | 10] = H2 >>> 8 & 255; - HEAP[output | 11] = H2 & 255; - HEAP[output | 12] = H3 >>> 24; - HEAP[output | 13] = H3 >>> 16 & 255; - HEAP[output | 14] = H3 >>> 8 & 255; - HEAP[output | 15] = H3 & 255; - HEAP[output | 16] = H4 >>> 24; - HEAP[output | 17] = H4 >>> 16 & 255; - HEAP[output | 18] = H4 >>> 8 & 255; - HEAP[output | 19] = H4 & 255; - HEAP[output | 20] = H5 >>> 24; - HEAP[output | 21] = H5 >>> 16 & 255; - HEAP[output | 22] = H5 >>> 8 & 255; - HEAP[output | 23] = H5 & 255; - HEAP[output | 24] = H6 >>> 24; - HEAP[output | 25] = H6 >>> 16 & 255; - HEAP[output | 26] = H6 >>> 8 & 255; - HEAP[output | 27] = H6 & 255; - HEAP[output | 28] = H7 >>> 24; - HEAP[output | 29] = H7 >>> 16 & 255; - HEAP[output | 30] = H7 >>> 8 & 255; - HEAP[output | 31] = H7 & 255; - } - - function reset() { - H0 = 0x6a09e667; - H1 = 0xbb67ae85; - H2 = 0x3c6ef372; - H3 = 0xa54ff53a; - H4 = 0x510e527f; - H5 = 0x9b05688c; - H6 = 0x1f83d9ab; - H7 = 0x5be0cd19; - TOTAL0 = TOTAL1 = 0; - } - - function init(h0, h1, h2, h3, h4, h5, h6, h7, total0, total1) { - h0 = h0 | 0; - h1 = h1 | 0; - h2 = h2 | 0; - h3 = h3 | 0; - h4 = h4 | 0; - h5 = h5 | 0; - h6 = h6 | 0; - h7 = h7 | 0; - total0 = total0 | 0; - total1 = total1 | 0; - - H0 = h0; - H1 = h1; - H2 = h2; - H3 = h3; - H4 = h4; - H5 = h5; - H6 = h6; - H7 = h7; - TOTAL0 = total0; - TOTAL1 = total1; - } - - // offset — multiple of 64 - function process(offset, length) { - offset = offset | 0; - length = length | 0; - - var hashed = 0; - - if (offset & 63) return -1; - - while ((length | 0) >= 64) { - _core_heap(offset); - - offset = offset + 64 | 0; - length = length - 64 | 0; - - hashed = hashed + 64 | 0; - } - - TOTAL0 = TOTAL0 + hashed | 0; - if (TOTAL0 >>> 0 < hashed >>> 0) TOTAL1 = TOTAL1 + 1 | 0; - - return hashed | 0; - } - - // offset — multiple of 64 - // output — multiple of 32 - function finish(offset, length, output) { - offset = offset | 0; - length = length | 0; - output = output | 0; - - var hashed = 0, - i = 0; - - if (offset & 63) return -1; - - if (~output) if (output & 31) return -1; - - if ((length | 0) >= 64) { - hashed = process(offset, length) | 0; - if ((hashed | 0) == -1) return -1; - - offset = offset + hashed | 0; - length = length - hashed | 0; - } - - hashed = hashed + length | 0; - TOTAL0 = TOTAL0 + length | 0; - if (TOTAL0 >>> 0 < length >>> 0) TOTAL1 = TOTAL1 + 1 | 0; - - HEAP[offset | length] = 0x80; - - if ((length | 0) >= 56) { - for (i = length + 1 | 0; (i | 0) < 64; i = i + 1 | 0) HEAP[offset | i] = 0x00; - - _core_heap(offset); - - length = 0; - - HEAP[offset | 0] = 0; - } - - for (i = length + 1 | 0; (i | 0) < 59; i = i + 1 | 0) HEAP[offset | i] = 0; - - HEAP[offset | 56] = TOTAL1 >>> 21 & 255; - HEAP[offset | 57] = TOTAL1 >>> 13 & 255; - HEAP[offset | 58] = TOTAL1 >>> 5 & 255; - HEAP[offset | 59] = TOTAL1 << 3 & 255 | TOTAL0 >>> 29; - HEAP[offset | 60] = TOTAL0 >>> 21 & 255; - HEAP[offset | 61] = TOTAL0 >>> 13 & 255; - HEAP[offset | 62] = TOTAL0 >>> 5 & 255; - HEAP[offset | 63] = TOTAL0 << 3 & 255; - _core_heap(offset); - - if (~output) _state_to_heap(output); - - return hashed | 0; - } - - function hmac_reset() { - H0 = I0; - H1 = I1; - H2 = I2; - H3 = I3; - H4 = I4; - H5 = I5; - H6 = I6; - H7 = I7; - TOTAL0 = 64; - TOTAL1 = 0; - } - - function _hmac_opad() { - H0 = O0; - H1 = O1; - H2 = O2; - H3 = O3; - H4 = O4; - H5 = O5; - H6 = O6; - H7 = O7; - TOTAL0 = 64; - TOTAL1 = 0; - } - - function hmac_init(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15) { - p0 = p0 | 0; - p1 = p1 | 0; - p2 = p2 | 0; - p3 = p3 | 0; - p4 = p4 | 0; - p5 = p5 | 0; - p6 = p6 | 0; - p7 = p7 | 0; - p8 = p8 | 0; - p9 = p9 | 0; - p10 = p10 | 0; - p11 = p11 | 0; - p12 = p12 | 0; - p13 = p13 | 0; - p14 = p14 | 0; - p15 = p15 | 0; - - // opad - reset(); - _core(p0 ^ 0x5c5c5c5c, p1 ^ 0x5c5c5c5c, p2 ^ 0x5c5c5c5c, p3 ^ 0x5c5c5c5c, p4 ^ 0x5c5c5c5c, p5 ^ 0x5c5c5c5c, p6 ^ 0x5c5c5c5c, p7 ^ 0x5c5c5c5c, p8 ^ 0x5c5c5c5c, p9 ^ 0x5c5c5c5c, p10 ^ 0x5c5c5c5c, p11 ^ 0x5c5c5c5c, p12 ^ 0x5c5c5c5c, p13 ^ 0x5c5c5c5c, p14 ^ 0x5c5c5c5c, p15 ^ 0x5c5c5c5c); - O0 = H0; - O1 = H1; - O2 = H2; - O3 = H3; - O4 = H4; - O5 = H5; - O6 = H6; - O7 = H7; - - // ipad - reset(); - _core(p0 ^ 0x36363636, p1 ^ 0x36363636, p2 ^ 0x36363636, p3 ^ 0x36363636, p4 ^ 0x36363636, p5 ^ 0x36363636, p6 ^ 0x36363636, p7 ^ 0x36363636, p8 ^ 0x36363636, p9 ^ 0x36363636, p10 ^ 0x36363636, p11 ^ 0x36363636, p12 ^ 0x36363636, p13 ^ 0x36363636, p14 ^ 0x36363636, p15 ^ 0x36363636); - I0 = H0; - I1 = H1; - I2 = H2; - I3 = H3; - I4 = H4; - I5 = H5; - I6 = H6; - I7 = H7; - - TOTAL0 = 64; - TOTAL1 = 0; - } - - // offset — multiple of 64 - // output — multiple of 32 - function hmac_finish(offset, length, output) { - offset = offset | 0; - length = length | 0; - output = output | 0; - - var t0 = 0, - t1 = 0, - t2 = 0, - t3 = 0, - t4 = 0, - t5 = 0, - t6 = 0, - t7 = 0, - hashed = 0; - - if (offset & 63) return -1; - - if (~output) if (output & 31) return -1; - - hashed = finish(offset, length, -1) | 0; - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; - - _hmac_opad(); - _core(t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768); - - if (~output) _state_to_heap(output); - - return hashed | 0; - } - - // salt is assumed to be already processed - // offset — multiple of 64 - // output — multiple of 32 - function pbkdf2_generate_block(offset, length, block, count, output) { - offset = offset | 0; - length = length | 0; - block = block | 0; - count = count | 0; - output = output | 0; - - var h0 = 0, - h1 = 0, - h2 = 0, - h3 = 0, - h4 = 0, - h5 = 0, - h6 = 0, - h7 = 0, - t0 = 0, - t1 = 0, - t2 = 0, - t3 = 0, - t4 = 0, - t5 = 0, - t6 = 0, - t7 = 0; - - if (offset & 63) return -1; - - if (~output) if (output & 31) return -1; - - // pad block number into heap - // FIXME probable OOB write - HEAP[offset + length | 0] = block >>> 24; - HEAP[offset + length + 1 | 0] = block >>> 16 & 255; - HEAP[offset + length + 2 | 0] = block >>> 8 & 255; - HEAP[offset + length + 3 | 0] = block & 255; - - // finish first iteration - hmac_finish(offset, length + 4 | 0, -1) | 0; - h0 = t0 = H0, h1 = t1 = H1, h2 = t2 = H2, h3 = t3 = H3, h4 = t4 = H4, h5 = t5 = H5, h6 = t6 = H6, h7 = t7 = H7; - count = count - 1 | 0; - - // perform the rest iterations - while ((count | 0) > 0) { - hmac_reset(); - _core(t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768); - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; - - _hmac_opad(); - _core(t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768); - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; - - h0 = h0 ^ H0; - h1 = h1 ^ H1; - h2 = h2 ^ H2; - h3 = h3 ^ H3; - h4 = h4 ^ H4; - h5 = h5 ^ H5; - h6 = h6 ^ H6; - h7 = h7 ^ H7; - - count = count - 1 | 0; - } - - H0 = h0; - H1 = h1; - H2 = h2; - H3 = h3; - H4 = h4; - H5 = h5; - H6 = h6; - H7 = h7; - - if (~output) _state_to_heap(output); - - return 0; - } - - return { - // SHA256 - reset: reset, - init: init, - process: process, - finish: finish, - - // HMAC-SHA256 - hmac_reset: hmac_reset, - hmac_init: hmac_init, - hmac_finish: hmac_finish, - - // PBKDF2-HMAC-SHA256 - pbkdf2_generate_block: pbkdf2_generate_block - }; -} - -},{}],13:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.Sha256 = exports._sha256_hash_size = exports._sha256_block_size = undefined; - -var _sha = require('./sha256.asm'); - -var _hash = require('../hash'); - -var __extends = undefined && undefined.__extends || function () { - var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) { - d.__proto__ = b; - } || function (d, b) { - for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; - }; - return function (d, b) { - extendStatics(d, b); - function __() { - this.constructor = d; - } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -}(); -var _sha256_block_size = exports._sha256_block_size = 64; -var _sha256_hash_size = exports._sha256_hash_size = 32; -var Sha256 = /** @class */function (_super) { - __extends(Sha256, _super); - function Sha256() { - var _this = _super !== null && _super.apply(this, arguments) || this; - _this.NAME = 'sha256'; - _this.BLOCK_SIZE = _sha256_block_size; - _this.HASH_SIZE = _sha256_hash_size; - return _this; - } - Sha256.bytes = function (data) { - return new Sha256().process(data).finish().result; - }; - Sha256.NAME = 'sha256'; - Sha256.heap_pool = []; - Sha256.asm_pool = []; - Sha256.asm_function = _sha.sha256_asm; - return Sha256; -}(_hash.Hash); -exports.Sha256 = Sha256; - -},{"../hash":9,"./sha256.asm":12}],14:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -var __extends = undefined && undefined.__extends || function () { - var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) { - d.__proto__ = b; - } || function (d, b) { - for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; - }; - return function (d, b) { - extendStatics(d, b); - function __() { - this.constructor = d; - } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -}(); -var IllegalStateError = /** @class */function (_super) { - __extends(IllegalStateError, _super); - function IllegalStateError() { - var args = []; - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - var _this = _super.apply(this, args) || this; - Object.create(Error.prototype, { name: { value: 'IllegalStateError' } }); - return _this; - } - return IllegalStateError; -}(Error); -exports.IllegalStateError = IllegalStateError; - -var IllegalArgumentError = /** @class */function (_super) { - __extends(IllegalArgumentError, _super); - function IllegalArgumentError() { - var args = []; - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - var _this = _super.apply(this, args) || this; - Object.create(Error.prototype, { name: { value: 'IllegalArgumentError' } }); - return _this; - } - return IllegalArgumentError; -}(Error); -exports.IllegalArgumentError = IllegalArgumentError; - -var SecurityError = /** @class */function (_super) { - __extends(SecurityError, _super); - function SecurityError() { - var args = []; - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - var _this = _super.apply(this, args) || this; - Object.create(Error.prototype, { name: { value: 'SecurityError' } }); - return _this; - } - return SecurityError; -}(Error); -exports.SecurityError = SecurityError; - -},{}],15:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.string_to_bytes = string_to_bytes; -exports.hex_to_bytes = hex_to_bytes; -exports.base64_to_bytes = base64_to_bytes; -exports.bytes_to_string = bytes_to_string; -exports.bytes_to_hex = bytes_to_hex; -exports.bytes_to_base64 = bytes_to_base64; -exports.pow2_ceil = pow2_ceil; -exports.is_number = is_number; -exports.is_string = is_string; -exports.is_buffer = is_buffer; -exports.is_bytes = is_bytes; -exports.is_typed_array = is_typed_array; -exports._heap_init = _heap_init; -exports._heap_write = _heap_write; -exports.joinBytes = joinBytes; -var local_atob = typeof atob === 'undefined' ? function (str) { - return require('buffer').Buffer.from(str, 'base64').toString('binary'); -} : atob; -var local_btoa = typeof btoa === 'undefined' ? function (str) { - return require('buffer').Buffer.from(str, 'binary').toString('base64'); -} : btoa; -function string_to_bytes(str, utf8) { - if (utf8 === void 0) { - utf8 = false; - } - var len = str.length, - bytes = new Uint8Array(utf8 ? 4 * len : len); - for (var i = 0, j = 0; i < len; i++) { - var c = str.charCodeAt(i); - if (utf8 && 0xd800 <= c && c <= 0xdbff) { - if (++i >= len) throw new Error('Malformed string, low surrogate expected at position ' + i); - c = (c ^ 0xd800) << 10 | 0x10000 | str.charCodeAt(i) ^ 0xdc00; - } else if (!utf8 && c >>> 8) { - throw new Error('Wide characters are not allowed.'); - } - if (!utf8 || c <= 0x7f) { - bytes[j++] = c; - } else if (c <= 0x7ff) { - bytes[j++] = 0xc0 | c >> 6; - bytes[j++] = 0x80 | c & 0x3f; - } else if (c <= 0xffff) { - bytes[j++] = 0xe0 | c >> 12; - bytes[j++] = 0x80 | c >> 6 & 0x3f; - bytes[j++] = 0x80 | c & 0x3f; - } else { - bytes[j++] = 0xf0 | c >> 18; - bytes[j++] = 0x80 | c >> 12 & 0x3f; - bytes[j++] = 0x80 | c >> 6 & 0x3f; - bytes[j++] = 0x80 | c & 0x3f; - } - } - return bytes.subarray(0, j); -} -function hex_to_bytes(str) { - var len = str.length; - if (len & 1) { - str = '0' + str; - len++; - } - var bytes = new Uint8Array(len >> 1); - for (var i = 0; i < len; i += 2) { - bytes[i >> 1] = parseInt(str.substr(i, 2), 16); - } - return bytes; -} -function base64_to_bytes(str) { - return string_to_bytes(local_atob(str)); -} -function bytes_to_string(bytes, utf8) { - if (utf8 === void 0) { - utf8 = false; - } - var len = bytes.length, - chars = new Array(len); - for (var i = 0, j = 0; i < len; i++) { - var b = bytes[i]; - if (!utf8 || b < 128) { - chars[j++] = b; - } else if (b >= 192 && b < 224 && i + 1 < len) { - chars[j++] = (b & 0x1f) << 6 | bytes[++i] & 0x3f; - } else if (b >= 224 && b < 240 && i + 2 < len) { - chars[j++] = (b & 0xf) << 12 | (bytes[++i] & 0x3f) << 6 | bytes[++i] & 0x3f; - } else if (b >= 240 && b < 248 && i + 3 < len) { - var c = (b & 7) << 18 | (bytes[++i] & 0x3f) << 12 | (bytes[++i] & 0x3f) << 6 | bytes[++i] & 0x3f; - if (c <= 0xffff) { - chars[j++] = c; - } else { - c ^= 0x10000; - chars[j++] = 0xd800 | c >> 10; - chars[j++] = 0xdc00 | c & 0x3ff; - } - } else { - throw new Error('Malformed UTF8 character at byte offset ' + i); - } - } - var str = '', - bs = 16384; - for (var i = 0; i < j; i += bs) { - str += String.fromCharCode.apply(String, chars.slice(i, i + bs <= j ? i + bs : j)); - } - return str; -} -function bytes_to_hex(arr) { - var str = ''; - for (var i = 0; i < arr.length; i++) { - var h = (arr[i] & 0xff).toString(16); - if (h.length < 2) str += '0'; - str += h; - } - return str; -} -function bytes_to_base64(arr) { - return local_btoa(bytes_to_string(arr)); -} -function pow2_ceil(a) { - a -= 1; - a |= a >>> 1; - a |= a >>> 2; - a |= a >>> 4; - a |= a >>> 8; - a |= a >>> 16; - a += 1; - return a; -} -function is_number(a) { - return typeof a === 'number'; -} -function is_string(a) { - return typeof a === 'string'; -} -function is_buffer(a) { - return a instanceof ArrayBuffer; -} -function is_bytes(a) { - return a instanceof Uint8Array; -} -function is_typed_array(a) { - return a instanceof Int8Array || a instanceof Uint8Array || a instanceof Int16Array || a instanceof Uint16Array || a instanceof Int32Array || a instanceof Uint32Array || a instanceof Float32Array || a instanceof Float64Array; -} -function _heap_init(heap, heapSize) { - var size = heap ? heap.byteLength : heapSize || 65536; - if (size & 0xfff || size <= 0) throw new Error('heap size must be a positive integer and a multiple of 4096'); - heap = heap || new Uint8Array(new ArrayBuffer(size)); - return heap; -} -function _heap_write(heap, hpos, data, dpos, dlen) { - var hlen = heap.length - hpos; - var wlen = hlen < dlen ? hlen : dlen; - heap.set(data.subarray(dpos, dpos + wlen), hpos); - return wlen; -} -function joinBytes() { - var arg = []; - for (var _i = 0; _i < arguments.length; _i++) { - arg[_i] = arguments[_i]; - } - var totalLenght = arg.reduce(function (sum, curr) { - return sum + curr.length; - }, 0); - var ret = new Uint8Array(totalLenght); - var cursor = 0; - for (var i = 0; i < arg.length; i++) { - ret.set(arg[i], cursor); - cursor += arg[i].length; - } - return ret; -} - -},{"buffer":"buffer"}],16:[function(require,module,exports){ -(function (module, exports) { - 'use strict'; - - // Utils - function assert (val, msg) { - if (!val) throw new Error(msg || 'Assertion failed'); - } - - // Could use `inherits` module, but don't want to move from single file - // architecture yet. - function inherits (ctor, superCtor) { - ctor.super_ = superCtor; - var TempCtor = function () {}; - TempCtor.prototype = superCtor.prototype; - ctor.prototype = new TempCtor(); - ctor.prototype.constructor = ctor; - } - - // BN - - function BN (number, base, endian) { - if (BN.isBN(number)) { - return number; - } - - this.negative = 0; - this.words = null; - this.length = 0; - - // Reduction context - this.red = null; - - if (number !== null) { - if (base === 'le' || base === 'be') { - endian = base; - base = 10; - } - - this._init(number || 0, base || 10, endian || 'be'); - } - } - if (typeof module === 'object') { - module.exports = BN; - } else { - exports.BN = BN; - } - - BN.BN = BN; - BN.wordSize = 26; - - var Buffer; - try { - Buffer = require('buffer').Buffer; - } catch (e) { - } - - BN.isBN = function isBN (num) { - if (num instanceof BN) { - return true; - } - - return num !== null && typeof num === 'object' && - num.constructor.wordSize === BN.wordSize && Array.isArray(num.words); - }; - - BN.max = function max (left, right) { - if (left.cmp(right) > 0) return left; - return right; - }; - - BN.min = function min (left, right) { - if (left.cmp(right) < 0) return left; - return right; - }; - - BN.prototype._init = function init (number, base, endian) { - if (typeof number === 'number') { - return this._initNumber(number, base, endian); - } - - if (typeof number === 'object') { - return this._initArray(number, base, endian); - } - - if (base === 'hex') { - base = 16; - } - assert(base === (base | 0) && base >= 2 && base <= 36); - - number = number.toString().replace(/\s+/g, ''); - var start = 0; - if (number[0] === '-') { - start++; - } - - if (base === 16) { - this._parseHex(number, start); - } else { - this._parseBase(number, base, start); - } - - if (number[0] === '-') { - this.negative = 1; - } - - this.strip(); - - if (endian !== 'le') return; - - this._initArray(this.toArray(), base, endian); - }; - - BN.prototype._initNumber = function _initNumber (number, base, endian) { - if (number < 0) { - this.negative = 1; - number = -number; - } - if (number < 0x4000000) { - this.words = [ number & 0x3ffffff ]; - this.length = 1; - } else if (number < 0x10000000000000) { - this.words = [ - number & 0x3ffffff, - (number / 0x4000000) & 0x3ffffff - ]; - this.length = 2; - } else { - assert(number < 0x20000000000000); // 2 ^ 53 (unsafe) - this.words = [ - number & 0x3ffffff, - (number / 0x4000000) & 0x3ffffff, - 1 - ]; - this.length = 3; - } - - if (endian !== 'le') return; - - // Reverse the bytes - this._initArray(this.toArray(), base, endian); - }; - - BN.prototype._initArray = function _initArray (number, base, endian) { - // Perhaps a Uint8Array - assert(typeof number.length === 'number'); - if (number.length <= 0) { - this.words = [ 0 ]; - this.length = 1; - return this; - } - - this.length = Math.ceil(number.length / 3); - this.words = new Array(this.length); - for (var i = 0; i < this.length; i++) { - this.words[i] = 0; - } - - var j, w; - var off = 0; - if (endian === 'be') { - for (i = number.length - 1, j = 0; i >= 0; i -= 3) { - w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16); - this.words[j] |= (w << off) & 0x3ffffff; - this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; - off += 24; - if (off >= 26) { - off -= 26; - j++; - } - } - } else if (endian === 'le') { - for (i = 0, j = 0; i < number.length; i += 3) { - w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16); - this.words[j] |= (w << off) & 0x3ffffff; - this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; - off += 24; - if (off >= 26) { - off -= 26; - j++; - } - } - } - return this.strip(); - }; - - function parseHex (str, start, end) { - var r = 0; - var len = Math.min(str.length, end); - for (var i = start; i < len; i++) { - var c = str.charCodeAt(i) - 48; - - r <<= 4; - - // 'a' - 'f' - if (c >= 49 && c <= 54) { - r |= c - 49 + 0xa; - - // 'A' - 'F' - } else if (c >= 17 && c <= 22) { - r |= c - 17 + 0xa; - - // '0' - '9' - } else { - r |= c & 0xf; - } - } - return r; - } - - BN.prototype._parseHex = function _parseHex (number, start) { - // Create possibly bigger array to ensure that it fits the number - this.length = Math.ceil((number.length - start) / 6); - this.words = new Array(this.length); - for (var i = 0; i < this.length; i++) { - this.words[i] = 0; - } - - var j, w; - // Scan 24-bit chunks and add them to the number - var off = 0; - for (i = number.length - 6, j = 0; i >= start; i -= 6) { - w = parseHex(number, i, i + 6); - this.words[j] |= (w << off) & 0x3ffffff; - // NOTE: `0x3fffff` is intentional here, 26bits max shift + 24bit hex limb - this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; - off += 24; - if (off >= 26) { - off -= 26; - j++; - } - } - if (i + 6 !== start) { - w = parseHex(number, start, i + 6); - this.words[j] |= (w << off) & 0x3ffffff; - this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; - } - this.strip(); - }; - - function parseBase (str, start, end, mul) { - var r = 0; - var len = Math.min(str.length, end); - for (var i = start; i < len; i++) { - var c = str.charCodeAt(i) - 48; - - r *= mul; - - // 'a' - if (c >= 49) { - r += c - 49 + 0xa; - - // 'A' - } else if (c >= 17) { - r += c - 17 + 0xa; - - // '0' - '9' - } else { - r += c; - } - } - return r; - } - - BN.prototype._parseBase = function _parseBase (number, base, start) { - // Initialize as zero - this.words = [ 0 ]; - this.length = 1; - - // Find length of limb in base - for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) { - limbLen++; - } - limbLen--; - limbPow = (limbPow / base) | 0; - - var total = number.length - start; - var mod = total % limbLen; - var end = Math.min(total, total - mod) + start; - - var word = 0; - for (var i = start; i < end; i += limbLen) { - word = parseBase(number, i, i + limbLen, base); - - this.imuln(limbPow); - if (this.words[0] + word < 0x4000000) { - this.words[0] += word; - } else { - this._iaddn(word); - } - } - - if (mod !== 0) { - var pow = 1; - word = parseBase(number, i, number.length, base); - - for (i = 0; i < mod; i++) { - pow *= base; - } - - this.imuln(pow); - if (this.words[0] + word < 0x4000000) { - this.words[0] += word; - } else { - this._iaddn(word); - } - } - }; - - BN.prototype.copy = function copy (dest) { - dest.words = new Array(this.length); - for (var i = 0; i < this.length; i++) { - dest.words[i] = this.words[i]; - } - dest.length = this.length; - dest.negative = this.negative; - dest.red = this.red; - }; - - BN.prototype.clone = function clone () { - var r = new BN(null); - this.copy(r); - return r; - }; - - BN.prototype._expand = function _expand (size) { - while (this.length < size) { - this.words[this.length++] = 0; - } - return this; - }; - - // Remove leading `0` from `this` - BN.prototype.strip = function strip () { - while (this.length > 1 && this.words[this.length - 1] === 0) { - this.length--; - } - return this._normSign(); - }; - - BN.prototype._normSign = function _normSign () { - // -0 = 0 - if (this.length === 1 && this.words[0] === 0) { - this.negative = 0; - } - return this; - }; - - BN.prototype.inspect = function inspect () { - return (this.red ? ''; - }; - - /* - - var zeros = []; - var groupSizes = []; - var groupBases = []; - - var s = ''; - var i = -1; - while (++i < BN.wordSize) { - zeros[i] = s; - s += '0'; - } - groupSizes[0] = 0; - groupSizes[1] = 0; - groupBases[0] = 0; - groupBases[1] = 0; - var base = 2 - 1; - while (++base < 36 + 1) { - var groupSize = 0; - var groupBase = 1; - while (groupBase < (1 << BN.wordSize) / base) { - groupBase *= base; - groupSize += 1; - } - groupSizes[base] = groupSize; - groupBases[base] = groupBase; - } - - */ - - var zeros = [ - '', - '0', - '00', - '000', - '0000', - '00000', - '000000', - '0000000', - '00000000', - '000000000', - '0000000000', - '00000000000', - '000000000000', - '0000000000000', - '00000000000000', - '000000000000000', - '0000000000000000', - '00000000000000000', - '000000000000000000', - '0000000000000000000', - '00000000000000000000', - '000000000000000000000', - '0000000000000000000000', - '00000000000000000000000', - '000000000000000000000000', - '0000000000000000000000000' - ]; - - var groupSizes = [ - 0, 0, - 25, 16, 12, 11, 10, 9, 8, - 8, 7, 7, 7, 7, 6, 6, - 6, 6, 6, 6, 6, 5, 5, - 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5 - ]; - - var groupBases = [ - 0, 0, - 33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216, - 43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625, - 16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632, - 6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149, - 24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176 - ]; - - BN.prototype.toString = function toString (base, padding) { - base = base || 10; - padding = padding | 0 || 1; - - var out; - if (base === 16 || base === 'hex') { - out = ''; - var off = 0; - var carry = 0; - for (var i = 0; i < this.length; i++) { - var w = this.words[i]; - var word = (((w << off) | carry) & 0xffffff).toString(16); - carry = (w >>> (24 - off)) & 0xffffff; - if (carry !== 0 || i !== this.length - 1) { - out = zeros[6 - word.length] + word + out; - } else { - out = word + out; - } - off += 2; - if (off >= 26) { - off -= 26; - i--; - } - } - if (carry !== 0) { - out = carry.toString(16) + out; - } - while (out.length % padding !== 0) { - out = '0' + out; - } - if (this.negative !== 0) { - out = '-' + out; - } - return out; - } - - if (base === (base | 0) && base >= 2 && base <= 36) { - // var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base)); - var groupSize = groupSizes[base]; - // var groupBase = Math.pow(base, groupSize); - var groupBase = groupBases[base]; - out = ''; - var c = this.clone(); - c.negative = 0; - while (!c.isZero()) { - var r = c.modn(groupBase).toString(base); - c = c.idivn(groupBase); - - if (!c.isZero()) { - out = zeros[groupSize - r.length] + r + out; - } else { - out = r + out; - } - } - if (this.isZero()) { - out = '0' + out; - } - while (out.length % padding !== 0) { - out = '0' + out; - } - if (this.negative !== 0) { - out = '-' + out; - } - return out; - } - - assert(false, 'Base should be between 2 and 36'); - }; - - BN.prototype.toNumber = function toNumber () { - var ret = this.words[0]; - if (this.length === 2) { - ret += this.words[1] * 0x4000000; - } else if (this.length === 3 && this.words[2] === 0x01) { - // NOTE: at this stage it is known that the top bit is set - ret += 0x10000000000000 + (this.words[1] * 0x4000000); - } else if (this.length > 2) { - assert(false, 'Number can only safely store up to 53 bits'); - } - return (this.negative !== 0) ? -ret : ret; - }; - - BN.prototype.toJSON = function toJSON () { - return this.toString(16); - }; - - BN.prototype.toBuffer = function toBuffer (endian, length) { - assert(typeof Buffer !== 'undefined'); - return this.toArrayLike(Buffer, endian, length); - }; - - BN.prototype.toArray = function toArray (endian, length) { - return this.toArrayLike(Array, endian, length); - }; - - BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) { - var byteLength = this.byteLength(); - var reqLength = length || Math.max(1, byteLength); - assert(byteLength <= reqLength, 'byte array longer than desired length'); - assert(reqLength > 0, 'Requested array length <= 0'); - - this.strip(); - var littleEndian = endian === 'le'; - var res = new ArrayType(reqLength); - - var b, i; - var q = this.clone(); - if (!littleEndian) { - // Assume big-endian - for (i = 0; i < reqLength - byteLength; i++) { - res[i] = 0; - } - - for (i = 0; !q.isZero(); i++) { - b = q.andln(0xff); - q.iushrn(8); - - res[reqLength - i - 1] = b; - } - } else { - for (i = 0; !q.isZero(); i++) { - b = q.andln(0xff); - q.iushrn(8); - - res[i] = b; - } - - for (; i < reqLength; i++) { - res[i] = 0; - } - } - - return res; - }; - - if (Math.clz32) { - BN.prototype._countBits = function _countBits (w) { - return 32 - Math.clz32(w); - }; - } else { - BN.prototype._countBits = function _countBits (w) { - var t = w; - var r = 0; - if (t >= 0x1000) { - r += 13; - t >>>= 13; - } - if (t >= 0x40) { - r += 7; - t >>>= 7; - } - if (t >= 0x8) { - r += 4; - t >>>= 4; - } - if (t >= 0x02) { - r += 2; - t >>>= 2; - } - return r + t; - }; - } - - BN.prototype._zeroBits = function _zeroBits (w) { - // Short-cut - if (w === 0) return 26; - - var t = w; - var r = 0; - if ((t & 0x1fff) === 0) { - r += 13; - t >>>= 13; - } - if ((t & 0x7f) === 0) { - r += 7; - t >>>= 7; - } - if ((t & 0xf) === 0) { - r += 4; - t >>>= 4; - } - if ((t & 0x3) === 0) { - r += 2; - t >>>= 2; - } - if ((t & 0x1) === 0) { - r++; - } - return r; - }; - - // Return number of used bits in a BN - BN.prototype.bitLength = function bitLength () { - var w = this.words[this.length - 1]; - var hi = this._countBits(w); - return (this.length - 1) * 26 + hi; - }; - - function toBitArray (num) { - var w = new Array(num.bitLength()); - - for (var bit = 0; bit < w.length; bit++) { - var off = (bit / 26) | 0; - var wbit = bit % 26; - - w[bit] = (num.words[off] & (1 << wbit)) >>> wbit; - } - - return w; - } - - // Number of trailing zero bits - BN.prototype.zeroBits = function zeroBits () { - if (this.isZero()) return 0; - - var r = 0; - for (var i = 0; i < this.length; i++) { - var b = this._zeroBits(this.words[i]); - r += b; - if (b !== 26) break; - } - return r; - }; - - BN.prototype.byteLength = function byteLength () { - return Math.ceil(this.bitLength() / 8); - }; - - BN.prototype.toTwos = function toTwos (width) { - if (this.negative !== 0) { - return this.abs().inotn(width).iaddn(1); - } - return this.clone(); - }; - - BN.prototype.fromTwos = function fromTwos (width) { - if (this.testn(width - 1)) { - return this.notn(width).iaddn(1).ineg(); - } - return this.clone(); - }; - - BN.prototype.isNeg = function isNeg () { - return this.negative !== 0; - }; - - // Return negative clone of `this` - BN.prototype.neg = function neg () { - return this.clone().ineg(); - }; - - BN.prototype.ineg = function ineg () { - if (!this.isZero()) { - this.negative ^= 1; - } - - return this; - }; - - // Or `num` with `this` in-place - BN.prototype.iuor = function iuor (num) { - while (this.length < num.length) { - this.words[this.length++] = 0; - } - - for (var i = 0; i < num.length; i++) { - this.words[i] = this.words[i] | num.words[i]; - } - - return this.strip(); - }; - - BN.prototype.ior = function ior (num) { - assert((this.negative | num.negative) === 0); - return this.iuor(num); - }; - - // Or `num` with `this` - BN.prototype.or = function or (num) { - if (this.length > num.length) return this.clone().ior(num); - return num.clone().ior(this); - }; - - BN.prototype.uor = function uor (num) { - if (this.length > num.length) return this.clone().iuor(num); - return num.clone().iuor(this); - }; - - // And `num` with `this` in-place - BN.prototype.iuand = function iuand (num) { - // b = min-length(num, this) - var b; - if (this.length > num.length) { - b = num; - } else { - b = this; - } - - for (var i = 0; i < b.length; i++) { - this.words[i] = this.words[i] & num.words[i]; - } - - this.length = b.length; - - return this.strip(); - }; - - BN.prototype.iand = function iand (num) { - assert((this.negative | num.negative) === 0); - return this.iuand(num); - }; - - // And `num` with `this` - BN.prototype.and = function and (num) { - if (this.length > num.length) return this.clone().iand(num); - return num.clone().iand(this); - }; - - BN.prototype.uand = function uand (num) { - if (this.length > num.length) return this.clone().iuand(num); - return num.clone().iuand(this); - }; - - // Xor `num` with `this` in-place - BN.prototype.iuxor = function iuxor (num) { - // a.length > b.length - var a; - var b; - if (this.length > num.length) { - a = this; - b = num; - } else { - a = num; - b = this; - } - - for (var i = 0; i < b.length; i++) { - this.words[i] = a.words[i] ^ b.words[i]; - } - - if (this !== a) { - for (; i < a.length; i++) { - this.words[i] = a.words[i]; - } - } - - this.length = a.length; - - return this.strip(); - }; - - BN.prototype.ixor = function ixor (num) { - assert((this.negative | num.negative) === 0); - return this.iuxor(num); - }; - - // Xor `num` with `this` - BN.prototype.xor = function xor (num) { - if (this.length > num.length) return this.clone().ixor(num); - return num.clone().ixor(this); - }; - - BN.prototype.uxor = function uxor (num) { - if (this.length > num.length) return this.clone().iuxor(num); - return num.clone().iuxor(this); - }; - - // Not ``this`` with ``width`` bitwidth - BN.prototype.inotn = function inotn (width) { - assert(typeof width === 'number' && width >= 0); - - var bytesNeeded = Math.ceil(width / 26) | 0; - var bitsLeft = width % 26; - - // Extend the buffer with leading zeroes - this._expand(bytesNeeded); - - if (bitsLeft > 0) { - bytesNeeded--; - } - - // Handle complete words - for (var i = 0; i < bytesNeeded; i++) { - this.words[i] = ~this.words[i] & 0x3ffffff; - } - - // Handle the residue - if (bitsLeft > 0) { - this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft)); - } - - // And remove leading zeroes - return this.strip(); - }; - - BN.prototype.notn = function notn (width) { - return this.clone().inotn(width); - }; - - // Set `bit` of `this` - BN.prototype.setn = function setn (bit, val) { - assert(typeof bit === 'number' && bit >= 0); - - var off = (bit / 26) | 0; - var wbit = bit % 26; - - this._expand(off + 1); - - if (val) { - this.words[off] = this.words[off] | (1 << wbit); - } else { - this.words[off] = this.words[off] & ~(1 << wbit); - } - - return this.strip(); - }; - - // Add `num` to `this` in-place - BN.prototype.iadd = function iadd (num) { - var r; - - // negative + positive - if (this.negative !== 0 && num.negative === 0) { - this.negative = 0; - r = this.isub(num); - this.negative ^= 1; - return this._normSign(); - - // positive + negative - } else if (this.negative === 0 && num.negative !== 0) { - num.negative = 0; - r = this.isub(num); - num.negative = 1; - return r._normSign(); - } - - // a.length > b.length - var a, b; - if (this.length > num.length) { - a = this; - b = num; - } else { - a = num; - b = this; - } - - var carry = 0; - for (var i = 0; i < b.length; i++) { - r = (a.words[i] | 0) + (b.words[i] | 0) + carry; - this.words[i] = r & 0x3ffffff; - carry = r >>> 26; - } - for (; carry !== 0 && i < a.length; i++) { - r = (a.words[i] | 0) + carry; - this.words[i] = r & 0x3ffffff; - carry = r >>> 26; - } - - this.length = a.length; - if (carry !== 0) { - this.words[this.length] = carry; - this.length++; - // Copy the rest of the words - } else if (a !== this) { - for (; i < a.length; i++) { - this.words[i] = a.words[i]; - } - } - - return this; - }; - - // Add `num` to `this` - BN.prototype.add = function add (num) { - var res; - if (num.negative !== 0 && this.negative === 0) { - num.negative = 0; - res = this.sub(num); - num.negative ^= 1; - return res; - } else if (num.negative === 0 && this.negative !== 0) { - this.negative = 0; - res = num.sub(this); - this.negative = 1; - return res; - } - - if (this.length > num.length) return this.clone().iadd(num); - - return num.clone().iadd(this); - }; - - // Subtract `num` from `this` in-place - BN.prototype.isub = function isub (num) { - // this - (-num) = this + num - if (num.negative !== 0) { - num.negative = 0; - var r = this.iadd(num); - num.negative = 1; - return r._normSign(); - - // -this - num = -(this + num) - } else if (this.negative !== 0) { - this.negative = 0; - this.iadd(num); - this.negative = 1; - return this._normSign(); - } - - // At this point both numbers are positive - var cmp = this.cmp(num); - - // Optimization - zeroify - if (cmp === 0) { - this.negative = 0; - this.length = 1; - this.words[0] = 0; - return this; - } - - // a > b - var a, b; - if (cmp > 0) { - a = this; - b = num; - } else { - a = num; - b = this; - } - - var carry = 0; - for (var i = 0; i < b.length; i++) { - r = (a.words[i] | 0) - (b.words[i] | 0) + carry; - carry = r >> 26; - this.words[i] = r & 0x3ffffff; - } - for (; carry !== 0 && i < a.length; i++) { - r = (a.words[i] | 0) + carry; - carry = r >> 26; - this.words[i] = r & 0x3ffffff; - } - - // Copy rest of the words - if (carry === 0 && i < a.length && a !== this) { - for (; i < a.length; i++) { - this.words[i] = a.words[i]; - } - } - - this.length = Math.max(this.length, i); - - if (a !== this) { - this.negative = 1; - } - - return this.strip(); - }; - - // Subtract `num` from `this` - BN.prototype.sub = function sub (num) { - return this.clone().isub(num); - }; - - function smallMulTo (self, num, out) { - out.negative = num.negative ^ self.negative; - var len = (self.length + num.length) | 0; - out.length = len; - len = (len - 1) | 0; - - // Peel one iteration (compiler can't do it, because of code complexity) - var a = self.words[0] | 0; - var b = num.words[0] | 0; - var r = a * b; - - var lo = r & 0x3ffffff; - var carry = (r / 0x4000000) | 0; - out.words[0] = lo; - - for (var k = 1; k < len; k++) { - // Sum all words with the same `i + j = k` and accumulate `ncarry`, - // note that ncarry could be >= 0x3ffffff - var ncarry = carry >>> 26; - var rword = carry & 0x3ffffff; - var maxJ = Math.min(k, num.length - 1); - for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { - var i = (k - j) | 0; - a = self.words[i] | 0; - b = num.words[j] | 0; - r = a * b + rword; - ncarry += (r / 0x4000000) | 0; - rword = r & 0x3ffffff; - } - out.words[k] = rword | 0; - carry = ncarry | 0; - } - if (carry !== 0) { - out.words[k] = carry | 0; - } else { - out.length--; - } - - return out.strip(); - } - - // TODO(indutny): it may be reasonable to omit it for users who don't need - // to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit - // multiplication (like elliptic secp256k1). - var comb10MulTo = function comb10MulTo (self, num, out) { - var a = self.words; - var b = num.words; - var o = out.words; - var c = 0; - var lo; - var mid; - var hi; - var a0 = a[0] | 0; - var al0 = a0 & 0x1fff; - var ah0 = a0 >>> 13; - var a1 = a[1] | 0; - var al1 = a1 & 0x1fff; - var ah1 = a1 >>> 13; - var a2 = a[2] | 0; - var al2 = a2 & 0x1fff; - var ah2 = a2 >>> 13; - var a3 = a[3] | 0; - var al3 = a3 & 0x1fff; - var ah3 = a3 >>> 13; - var a4 = a[4] | 0; - var al4 = a4 & 0x1fff; - var ah4 = a4 >>> 13; - var a5 = a[5] | 0; - var al5 = a5 & 0x1fff; - var ah5 = a5 >>> 13; - var a6 = a[6] | 0; - var al6 = a6 & 0x1fff; - var ah6 = a6 >>> 13; - var a7 = a[7] | 0; - var al7 = a7 & 0x1fff; - var ah7 = a7 >>> 13; - var a8 = a[8] | 0; - var al8 = a8 & 0x1fff; - var ah8 = a8 >>> 13; - var a9 = a[9] | 0; - var al9 = a9 & 0x1fff; - var ah9 = a9 >>> 13; - var b0 = b[0] | 0; - var bl0 = b0 & 0x1fff; - var bh0 = b0 >>> 13; - var b1 = b[1] | 0; - var bl1 = b1 & 0x1fff; - var bh1 = b1 >>> 13; - var b2 = b[2] | 0; - var bl2 = b2 & 0x1fff; - var bh2 = b2 >>> 13; - var b3 = b[3] | 0; - var bl3 = b3 & 0x1fff; - var bh3 = b3 >>> 13; - var b4 = b[4] | 0; - var bl4 = b4 & 0x1fff; - var bh4 = b4 >>> 13; - var b5 = b[5] | 0; - var bl5 = b5 & 0x1fff; - var bh5 = b5 >>> 13; - var b6 = b[6] | 0; - var bl6 = b6 & 0x1fff; - var bh6 = b6 >>> 13; - var b7 = b[7] | 0; - var bl7 = b7 & 0x1fff; - var bh7 = b7 >>> 13; - var b8 = b[8] | 0; - var bl8 = b8 & 0x1fff; - var bh8 = b8 >>> 13; - var b9 = b[9] | 0; - var bl9 = b9 & 0x1fff; - var bh9 = b9 >>> 13; - - out.negative = self.negative ^ num.negative; - out.length = 19; - /* k = 0 */ - lo = Math.imul(al0, bl0); - mid = Math.imul(al0, bh0); - mid = (mid + Math.imul(ah0, bl0)) | 0; - hi = Math.imul(ah0, bh0); - var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0; - w0 &= 0x3ffffff; - /* k = 1 */ - lo = Math.imul(al1, bl0); - mid = Math.imul(al1, bh0); - mid = (mid + Math.imul(ah1, bl0)) | 0; - hi = Math.imul(ah1, bh0); - lo = (lo + Math.imul(al0, bl1)) | 0; - mid = (mid + Math.imul(al0, bh1)) | 0; - mid = (mid + Math.imul(ah0, bl1)) | 0; - hi = (hi + Math.imul(ah0, bh1)) | 0; - var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0; - w1 &= 0x3ffffff; - /* k = 2 */ - lo = Math.imul(al2, bl0); - mid = Math.imul(al2, bh0); - mid = (mid + Math.imul(ah2, bl0)) | 0; - hi = Math.imul(ah2, bh0); - lo = (lo + Math.imul(al1, bl1)) | 0; - mid = (mid + Math.imul(al1, bh1)) | 0; - mid = (mid + Math.imul(ah1, bl1)) | 0; - hi = (hi + Math.imul(ah1, bh1)) | 0; - lo = (lo + Math.imul(al0, bl2)) | 0; - mid = (mid + Math.imul(al0, bh2)) | 0; - mid = (mid + Math.imul(ah0, bl2)) | 0; - hi = (hi + Math.imul(ah0, bh2)) | 0; - var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0; - w2 &= 0x3ffffff; - /* k = 3 */ - lo = Math.imul(al3, bl0); - mid = Math.imul(al3, bh0); - mid = (mid + Math.imul(ah3, bl0)) | 0; - hi = Math.imul(ah3, bh0); - lo = (lo + Math.imul(al2, bl1)) | 0; - mid = (mid + Math.imul(al2, bh1)) | 0; - mid = (mid + Math.imul(ah2, bl1)) | 0; - hi = (hi + Math.imul(ah2, bh1)) | 0; - lo = (lo + Math.imul(al1, bl2)) | 0; - mid = (mid + Math.imul(al1, bh2)) | 0; - mid = (mid + Math.imul(ah1, bl2)) | 0; - hi = (hi + Math.imul(ah1, bh2)) | 0; - lo = (lo + Math.imul(al0, bl3)) | 0; - mid = (mid + Math.imul(al0, bh3)) | 0; - mid = (mid + Math.imul(ah0, bl3)) | 0; - hi = (hi + Math.imul(ah0, bh3)) | 0; - var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0; - w3 &= 0x3ffffff; - /* k = 4 */ - lo = Math.imul(al4, bl0); - mid = Math.imul(al4, bh0); - mid = (mid + Math.imul(ah4, bl0)) | 0; - hi = Math.imul(ah4, bh0); - lo = (lo + Math.imul(al3, bl1)) | 0; - mid = (mid + Math.imul(al3, bh1)) | 0; - mid = (mid + Math.imul(ah3, bl1)) | 0; - hi = (hi + Math.imul(ah3, bh1)) | 0; - lo = (lo + Math.imul(al2, bl2)) | 0; - mid = (mid + Math.imul(al2, bh2)) | 0; - mid = (mid + Math.imul(ah2, bl2)) | 0; - hi = (hi + Math.imul(ah2, bh2)) | 0; - lo = (lo + Math.imul(al1, bl3)) | 0; - mid = (mid + Math.imul(al1, bh3)) | 0; - mid = (mid + Math.imul(ah1, bl3)) | 0; - hi = (hi + Math.imul(ah1, bh3)) | 0; - lo = (lo + Math.imul(al0, bl4)) | 0; - mid = (mid + Math.imul(al0, bh4)) | 0; - mid = (mid + Math.imul(ah0, bl4)) | 0; - hi = (hi + Math.imul(ah0, bh4)) | 0; - var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0; - w4 &= 0x3ffffff; - /* k = 5 */ - lo = Math.imul(al5, bl0); - mid = Math.imul(al5, bh0); - mid = (mid + Math.imul(ah5, bl0)) | 0; - hi = Math.imul(ah5, bh0); - lo = (lo + Math.imul(al4, bl1)) | 0; - mid = (mid + Math.imul(al4, bh1)) | 0; - mid = (mid + Math.imul(ah4, bl1)) | 0; - hi = (hi + Math.imul(ah4, bh1)) | 0; - lo = (lo + Math.imul(al3, bl2)) | 0; - mid = (mid + Math.imul(al3, bh2)) | 0; - mid = (mid + Math.imul(ah3, bl2)) | 0; - hi = (hi + Math.imul(ah3, bh2)) | 0; - lo = (lo + Math.imul(al2, bl3)) | 0; - mid = (mid + Math.imul(al2, bh3)) | 0; - mid = (mid + Math.imul(ah2, bl3)) | 0; - hi = (hi + Math.imul(ah2, bh3)) | 0; - lo = (lo + Math.imul(al1, bl4)) | 0; - mid = (mid + Math.imul(al1, bh4)) | 0; - mid = (mid + Math.imul(ah1, bl4)) | 0; - hi = (hi + Math.imul(ah1, bh4)) | 0; - lo = (lo + Math.imul(al0, bl5)) | 0; - mid = (mid + Math.imul(al0, bh5)) | 0; - mid = (mid + Math.imul(ah0, bl5)) | 0; - hi = (hi + Math.imul(ah0, bh5)) | 0; - var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0; - w5 &= 0x3ffffff; - /* k = 6 */ - lo = Math.imul(al6, bl0); - mid = Math.imul(al6, bh0); - mid = (mid + Math.imul(ah6, bl0)) | 0; - hi = Math.imul(ah6, bh0); - lo = (lo + Math.imul(al5, bl1)) | 0; - mid = (mid + Math.imul(al5, bh1)) | 0; - mid = (mid + Math.imul(ah5, bl1)) | 0; - hi = (hi + Math.imul(ah5, bh1)) | 0; - lo = (lo + Math.imul(al4, bl2)) | 0; - mid = (mid + Math.imul(al4, bh2)) | 0; - mid = (mid + Math.imul(ah4, bl2)) | 0; - hi = (hi + Math.imul(ah4, bh2)) | 0; - lo = (lo + Math.imul(al3, bl3)) | 0; - mid = (mid + Math.imul(al3, bh3)) | 0; - mid = (mid + Math.imul(ah3, bl3)) | 0; - hi = (hi + Math.imul(ah3, bh3)) | 0; - lo = (lo + Math.imul(al2, bl4)) | 0; - mid = (mid + Math.imul(al2, bh4)) | 0; - mid = (mid + Math.imul(ah2, bl4)) | 0; - hi = (hi + Math.imul(ah2, bh4)) | 0; - lo = (lo + Math.imul(al1, bl5)) | 0; - mid = (mid + Math.imul(al1, bh5)) | 0; - mid = (mid + Math.imul(ah1, bl5)) | 0; - hi = (hi + Math.imul(ah1, bh5)) | 0; - lo = (lo + Math.imul(al0, bl6)) | 0; - mid = (mid + Math.imul(al0, bh6)) | 0; - mid = (mid + Math.imul(ah0, bl6)) | 0; - hi = (hi + Math.imul(ah0, bh6)) | 0; - var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0; - w6 &= 0x3ffffff; - /* k = 7 */ - lo = Math.imul(al7, bl0); - mid = Math.imul(al7, bh0); - mid = (mid + Math.imul(ah7, bl0)) | 0; - hi = Math.imul(ah7, bh0); - lo = (lo + Math.imul(al6, bl1)) | 0; - mid = (mid + Math.imul(al6, bh1)) | 0; - mid = (mid + Math.imul(ah6, bl1)) | 0; - hi = (hi + Math.imul(ah6, bh1)) | 0; - lo = (lo + Math.imul(al5, bl2)) | 0; - mid = (mid + Math.imul(al5, bh2)) | 0; - mid = (mid + Math.imul(ah5, bl2)) | 0; - hi = (hi + Math.imul(ah5, bh2)) | 0; - lo = (lo + Math.imul(al4, bl3)) | 0; - mid = (mid + Math.imul(al4, bh3)) | 0; - mid = (mid + Math.imul(ah4, bl3)) | 0; - hi = (hi + Math.imul(ah4, bh3)) | 0; - lo = (lo + Math.imul(al3, bl4)) | 0; - mid = (mid + Math.imul(al3, bh4)) | 0; - mid = (mid + Math.imul(ah3, bl4)) | 0; - hi = (hi + Math.imul(ah3, bh4)) | 0; - lo = (lo + Math.imul(al2, bl5)) | 0; - mid = (mid + Math.imul(al2, bh5)) | 0; - mid = (mid + Math.imul(ah2, bl5)) | 0; - hi = (hi + Math.imul(ah2, bh5)) | 0; - lo = (lo + Math.imul(al1, bl6)) | 0; - mid = (mid + Math.imul(al1, bh6)) | 0; - mid = (mid + Math.imul(ah1, bl6)) | 0; - hi = (hi + Math.imul(ah1, bh6)) | 0; - lo = (lo + Math.imul(al0, bl7)) | 0; - mid = (mid + Math.imul(al0, bh7)) | 0; - mid = (mid + Math.imul(ah0, bl7)) | 0; - hi = (hi + Math.imul(ah0, bh7)) | 0; - var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0; - w7 &= 0x3ffffff; - /* k = 8 */ - lo = Math.imul(al8, bl0); - mid = Math.imul(al8, bh0); - mid = (mid + Math.imul(ah8, bl0)) | 0; - hi = Math.imul(ah8, bh0); - lo = (lo + Math.imul(al7, bl1)) | 0; - mid = (mid + Math.imul(al7, bh1)) | 0; - mid = (mid + Math.imul(ah7, bl1)) | 0; - hi = (hi + Math.imul(ah7, bh1)) | 0; - lo = (lo + Math.imul(al6, bl2)) | 0; - mid = (mid + Math.imul(al6, bh2)) | 0; - mid = (mid + Math.imul(ah6, bl2)) | 0; - hi = (hi + Math.imul(ah6, bh2)) | 0; - lo = (lo + Math.imul(al5, bl3)) | 0; - mid = (mid + Math.imul(al5, bh3)) | 0; - mid = (mid + Math.imul(ah5, bl3)) | 0; - hi = (hi + Math.imul(ah5, bh3)) | 0; - lo = (lo + Math.imul(al4, bl4)) | 0; - mid = (mid + Math.imul(al4, bh4)) | 0; - mid = (mid + Math.imul(ah4, bl4)) | 0; - hi = (hi + Math.imul(ah4, bh4)) | 0; - lo = (lo + Math.imul(al3, bl5)) | 0; - mid = (mid + Math.imul(al3, bh5)) | 0; - mid = (mid + Math.imul(ah3, bl5)) | 0; - hi = (hi + Math.imul(ah3, bh5)) | 0; - lo = (lo + Math.imul(al2, bl6)) | 0; - mid = (mid + Math.imul(al2, bh6)) | 0; - mid = (mid + Math.imul(ah2, bl6)) | 0; - hi = (hi + Math.imul(ah2, bh6)) | 0; - lo = (lo + Math.imul(al1, bl7)) | 0; - mid = (mid + Math.imul(al1, bh7)) | 0; - mid = (mid + Math.imul(ah1, bl7)) | 0; - hi = (hi + Math.imul(ah1, bh7)) | 0; - lo = (lo + Math.imul(al0, bl8)) | 0; - mid = (mid + Math.imul(al0, bh8)) | 0; - mid = (mid + Math.imul(ah0, bl8)) | 0; - hi = (hi + Math.imul(ah0, bh8)) | 0; - var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0; - w8 &= 0x3ffffff; - /* k = 9 */ - lo = Math.imul(al9, bl0); - mid = Math.imul(al9, bh0); - mid = (mid + Math.imul(ah9, bl0)) | 0; - hi = Math.imul(ah9, bh0); - lo = (lo + Math.imul(al8, bl1)) | 0; - mid = (mid + Math.imul(al8, bh1)) | 0; - mid = (mid + Math.imul(ah8, bl1)) | 0; - hi = (hi + Math.imul(ah8, bh1)) | 0; - lo = (lo + Math.imul(al7, bl2)) | 0; - mid = (mid + Math.imul(al7, bh2)) | 0; - mid = (mid + Math.imul(ah7, bl2)) | 0; - hi = (hi + Math.imul(ah7, bh2)) | 0; - lo = (lo + Math.imul(al6, bl3)) | 0; - mid = (mid + Math.imul(al6, bh3)) | 0; - mid = (mid + Math.imul(ah6, bl3)) | 0; - hi = (hi + Math.imul(ah6, bh3)) | 0; - lo = (lo + Math.imul(al5, bl4)) | 0; - mid = (mid + Math.imul(al5, bh4)) | 0; - mid = (mid + Math.imul(ah5, bl4)) | 0; - hi = (hi + Math.imul(ah5, bh4)) | 0; - lo = (lo + Math.imul(al4, bl5)) | 0; - mid = (mid + Math.imul(al4, bh5)) | 0; - mid = (mid + Math.imul(ah4, bl5)) | 0; - hi = (hi + Math.imul(ah4, bh5)) | 0; - lo = (lo + Math.imul(al3, bl6)) | 0; - mid = (mid + Math.imul(al3, bh6)) | 0; - mid = (mid + Math.imul(ah3, bl6)) | 0; - hi = (hi + Math.imul(ah3, bh6)) | 0; - lo = (lo + Math.imul(al2, bl7)) | 0; - mid = (mid + Math.imul(al2, bh7)) | 0; - mid = (mid + Math.imul(ah2, bl7)) | 0; - hi = (hi + Math.imul(ah2, bh7)) | 0; - lo = (lo + Math.imul(al1, bl8)) | 0; - mid = (mid + Math.imul(al1, bh8)) | 0; - mid = (mid + Math.imul(ah1, bl8)) | 0; - hi = (hi + Math.imul(ah1, bh8)) | 0; - lo = (lo + Math.imul(al0, bl9)) | 0; - mid = (mid + Math.imul(al0, bh9)) | 0; - mid = (mid + Math.imul(ah0, bl9)) | 0; - hi = (hi + Math.imul(ah0, bh9)) | 0; - var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0; - w9 &= 0x3ffffff; - /* k = 10 */ - lo = Math.imul(al9, bl1); - mid = Math.imul(al9, bh1); - mid = (mid + Math.imul(ah9, bl1)) | 0; - hi = Math.imul(ah9, bh1); - lo = (lo + Math.imul(al8, bl2)) | 0; - mid = (mid + Math.imul(al8, bh2)) | 0; - mid = (mid + Math.imul(ah8, bl2)) | 0; - hi = (hi + Math.imul(ah8, bh2)) | 0; - lo = (lo + Math.imul(al7, bl3)) | 0; - mid = (mid + Math.imul(al7, bh3)) | 0; - mid = (mid + Math.imul(ah7, bl3)) | 0; - hi = (hi + Math.imul(ah7, bh3)) | 0; - lo = (lo + Math.imul(al6, bl4)) | 0; - mid = (mid + Math.imul(al6, bh4)) | 0; - mid = (mid + Math.imul(ah6, bl4)) | 0; - hi = (hi + Math.imul(ah6, bh4)) | 0; - lo = (lo + Math.imul(al5, bl5)) | 0; - mid = (mid + Math.imul(al5, bh5)) | 0; - mid = (mid + Math.imul(ah5, bl5)) | 0; - hi = (hi + Math.imul(ah5, bh5)) | 0; - lo = (lo + Math.imul(al4, bl6)) | 0; - mid = (mid + Math.imul(al4, bh6)) | 0; - mid = (mid + Math.imul(ah4, bl6)) | 0; - hi = (hi + Math.imul(ah4, bh6)) | 0; - lo = (lo + Math.imul(al3, bl7)) | 0; - mid = (mid + Math.imul(al3, bh7)) | 0; - mid = (mid + Math.imul(ah3, bl7)) | 0; - hi = (hi + Math.imul(ah3, bh7)) | 0; - lo = (lo + Math.imul(al2, bl8)) | 0; - mid = (mid + Math.imul(al2, bh8)) | 0; - mid = (mid + Math.imul(ah2, bl8)) | 0; - hi = (hi + Math.imul(ah2, bh8)) | 0; - lo = (lo + Math.imul(al1, bl9)) | 0; - mid = (mid + Math.imul(al1, bh9)) | 0; - mid = (mid + Math.imul(ah1, bl9)) | 0; - hi = (hi + Math.imul(ah1, bh9)) | 0; - var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0; - w10 &= 0x3ffffff; - /* k = 11 */ - lo = Math.imul(al9, bl2); - mid = Math.imul(al9, bh2); - mid = (mid + Math.imul(ah9, bl2)) | 0; - hi = Math.imul(ah9, bh2); - lo = (lo + Math.imul(al8, bl3)) | 0; - mid = (mid + Math.imul(al8, bh3)) | 0; - mid = (mid + Math.imul(ah8, bl3)) | 0; - hi = (hi + Math.imul(ah8, bh3)) | 0; - lo = (lo + Math.imul(al7, bl4)) | 0; - mid = (mid + Math.imul(al7, bh4)) | 0; - mid = (mid + Math.imul(ah7, bl4)) | 0; - hi = (hi + Math.imul(ah7, bh4)) | 0; - lo = (lo + Math.imul(al6, bl5)) | 0; - mid = (mid + Math.imul(al6, bh5)) | 0; - mid = (mid + Math.imul(ah6, bl5)) | 0; - hi = (hi + Math.imul(ah6, bh5)) | 0; - lo = (lo + Math.imul(al5, bl6)) | 0; - mid = (mid + Math.imul(al5, bh6)) | 0; - mid = (mid + Math.imul(ah5, bl6)) | 0; - hi = (hi + Math.imul(ah5, bh6)) | 0; - lo = (lo + Math.imul(al4, bl7)) | 0; - mid = (mid + Math.imul(al4, bh7)) | 0; - mid = (mid + Math.imul(ah4, bl7)) | 0; - hi = (hi + Math.imul(ah4, bh7)) | 0; - lo = (lo + Math.imul(al3, bl8)) | 0; - mid = (mid + Math.imul(al3, bh8)) | 0; - mid = (mid + Math.imul(ah3, bl8)) | 0; - hi = (hi + Math.imul(ah3, bh8)) | 0; - lo = (lo + Math.imul(al2, bl9)) | 0; - mid = (mid + Math.imul(al2, bh9)) | 0; - mid = (mid + Math.imul(ah2, bl9)) | 0; - hi = (hi + Math.imul(ah2, bh9)) | 0; - var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0; - w11 &= 0x3ffffff; - /* k = 12 */ - lo = Math.imul(al9, bl3); - mid = Math.imul(al9, bh3); - mid = (mid + Math.imul(ah9, bl3)) | 0; - hi = Math.imul(ah9, bh3); - lo = (lo + Math.imul(al8, bl4)) | 0; - mid = (mid + Math.imul(al8, bh4)) | 0; - mid = (mid + Math.imul(ah8, bl4)) | 0; - hi = (hi + Math.imul(ah8, bh4)) | 0; - lo = (lo + Math.imul(al7, bl5)) | 0; - mid = (mid + Math.imul(al7, bh5)) | 0; - mid = (mid + Math.imul(ah7, bl5)) | 0; - hi = (hi + Math.imul(ah7, bh5)) | 0; - lo = (lo + Math.imul(al6, bl6)) | 0; - mid = (mid + Math.imul(al6, bh6)) | 0; - mid = (mid + Math.imul(ah6, bl6)) | 0; - hi = (hi + Math.imul(ah6, bh6)) | 0; - lo = (lo + Math.imul(al5, bl7)) | 0; - mid = (mid + Math.imul(al5, bh7)) | 0; - mid = (mid + Math.imul(ah5, bl7)) | 0; - hi = (hi + Math.imul(ah5, bh7)) | 0; - lo = (lo + Math.imul(al4, bl8)) | 0; - mid = (mid + Math.imul(al4, bh8)) | 0; - mid = (mid + Math.imul(ah4, bl8)) | 0; - hi = (hi + Math.imul(ah4, bh8)) | 0; - lo = (lo + Math.imul(al3, bl9)) | 0; - mid = (mid + Math.imul(al3, bh9)) | 0; - mid = (mid + Math.imul(ah3, bl9)) | 0; - hi = (hi + Math.imul(ah3, bh9)) | 0; - var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0; - w12 &= 0x3ffffff; - /* k = 13 */ - lo = Math.imul(al9, bl4); - mid = Math.imul(al9, bh4); - mid = (mid + Math.imul(ah9, bl4)) | 0; - hi = Math.imul(ah9, bh4); - lo = (lo + Math.imul(al8, bl5)) | 0; - mid = (mid + Math.imul(al8, bh5)) | 0; - mid = (mid + Math.imul(ah8, bl5)) | 0; - hi = (hi + Math.imul(ah8, bh5)) | 0; - lo = (lo + Math.imul(al7, bl6)) | 0; - mid = (mid + Math.imul(al7, bh6)) | 0; - mid = (mid + Math.imul(ah7, bl6)) | 0; - hi = (hi + Math.imul(ah7, bh6)) | 0; - lo = (lo + Math.imul(al6, bl7)) | 0; - mid = (mid + Math.imul(al6, bh7)) | 0; - mid = (mid + Math.imul(ah6, bl7)) | 0; - hi = (hi + Math.imul(ah6, bh7)) | 0; - lo = (lo + Math.imul(al5, bl8)) | 0; - mid = (mid + Math.imul(al5, bh8)) | 0; - mid = (mid + Math.imul(ah5, bl8)) | 0; - hi = (hi + Math.imul(ah5, bh8)) | 0; - lo = (lo + Math.imul(al4, bl9)) | 0; - mid = (mid + Math.imul(al4, bh9)) | 0; - mid = (mid + Math.imul(ah4, bl9)) | 0; - hi = (hi + Math.imul(ah4, bh9)) | 0; - var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0; - w13 &= 0x3ffffff; - /* k = 14 */ - lo = Math.imul(al9, bl5); - mid = Math.imul(al9, bh5); - mid = (mid + Math.imul(ah9, bl5)) | 0; - hi = Math.imul(ah9, bh5); - lo = (lo + Math.imul(al8, bl6)) | 0; - mid = (mid + Math.imul(al8, bh6)) | 0; - mid = (mid + Math.imul(ah8, bl6)) | 0; - hi = (hi + Math.imul(ah8, bh6)) | 0; - lo = (lo + Math.imul(al7, bl7)) | 0; - mid = (mid + Math.imul(al7, bh7)) | 0; - mid = (mid + Math.imul(ah7, bl7)) | 0; - hi = (hi + Math.imul(ah7, bh7)) | 0; - lo = (lo + Math.imul(al6, bl8)) | 0; - mid = (mid + Math.imul(al6, bh8)) | 0; - mid = (mid + Math.imul(ah6, bl8)) | 0; - hi = (hi + Math.imul(ah6, bh8)) | 0; - lo = (lo + Math.imul(al5, bl9)) | 0; - mid = (mid + Math.imul(al5, bh9)) | 0; - mid = (mid + Math.imul(ah5, bl9)) | 0; - hi = (hi + Math.imul(ah5, bh9)) | 0; - var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0; - w14 &= 0x3ffffff; - /* k = 15 */ - lo = Math.imul(al9, bl6); - mid = Math.imul(al9, bh6); - mid = (mid + Math.imul(ah9, bl6)) | 0; - hi = Math.imul(ah9, bh6); - lo = (lo + Math.imul(al8, bl7)) | 0; - mid = (mid + Math.imul(al8, bh7)) | 0; - mid = (mid + Math.imul(ah8, bl7)) | 0; - hi = (hi + Math.imul(ah8, bh7)) | 0; - lo = (lo + Math.imul(al7, bl8)) | 0; - mid = (mid + Math.imul(al7, bh8)) | 0; - mid = (mid + Math.imul(ah7, bl8)) | 0; - hi = (hi + Math.imul(ah7, bh8)) | 0; - lo = (lo + Math.imul(al6, bl9)) | 0; - mid = (mid + Math.imul(al6, bh9)) | 0; - mid = (mid + Math.imul(ah6, bl9)) | 0; - hi = (hi + Math.imul(ah6, bh9)) | 0; - var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0; - w15 &= 0x3ffffff; - /* k = 16 */ - lo = Math.imul(al9, bl7); - mid = Math.imul(al9, bh7); - mid = (mid + Math.imul(ah9, bl7)) | 0; - hi = Math.imul(ah9, bh7); - lo = (lo + Math.imul(al8, bl8)) | 0; - mid = (mid + Math.imul(al8, bh8)) | 0; - mid = (mid + Math.imul(ah8, bl8)) | 0; - hi = (hi + Math.imul(ah8, bh8)) | 0; - lo = (lo + Math.imul(al7, bl9)) | 0; - mid = (mid + Math.imul(al7, bh9)) | 0; - mid = (mid + Math.imul(ah7, bl9)) | 0; - hi = (hi + Math.imul(ah7, bh9)) | 0; - var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0; - w16 &= 0x3ffffff; - /* k = 17 */ - lo = Math.imul(al9, bl8); - mid = Math.imul(al9, bh8); - mid = (mid + Math.imul(ah9, bl8)) | 0; - hi = Math.imul(ah9, bh8); - lo = (lo + Math.imul(al8, bl9)) | 0; - mid = (mid + Math.imul(al8, bh9)) | 0; - mid = (mid + Math.imul(ah8, bl9)) | 0; - hi = (hi + Math.imul(ah8, bh9)) | 0; - var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0; - w17 &= 0x3ffffff; - /* k = 18 */ - lo = Math.imul(al9, bl9); - mid = Math.imul(al9, bh9); - mid = (mid + Math.imul(ah9, bl9)) | 0; - hi = Math.imul(ah9, bh9); - var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0; - w18 &= 0x3ffffff; - o[0] = w0; - o[1] = w1; - o[2] = w2; - o[3] = w3; - o[4] = w4; - o[5] = w5; - o[6] = w6; - o[7] = w7; - o[8] = w8; - o[9] = w9; - o[10] = w10; - o[11] = w11; - o[12] = w12; - o[13] = w13; - o[14] = w14; - o[15] = w15; - o[16] = w16; - o[17] = w17; - o[18] = w18; - if (c !== 0) { - o[19] = c; - out.length++; - } - return out; - }; - - // Polyfill comb - if (!Math.imul) { - comb10MulTo = smallMulTo; - } - - function bigMulTo (self, num, out) { - out.negative = num.negative ^ self.negative; - out.length = self.length + num.length; - - var carry = 0; - var hncarry = 0; - for (var k = 0; k < out.length - 1; k++) { - // Sum all words with the same `i + j = k` and accumulate `ncarry`, - // note that ncarry could be >= 0x3ffffff - var ncarry = hncarry; - hncarry = 0; - var rword = carry & 0x3ffffff; - var maxJ = Math.min(k, num.length - 1); - for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { - var i = k - j; - var a = self.words[i] | 0; - var b = num.words[j] | 0; - var r = a * b; - - var lo = r & 0x3ffffff; - ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0; - lo = (lo + rword) | 0; - rword = lo & 0x3ffffff; - ncarry = (ncarry + (lo >>> 26)) | 0; - - hncarry += ncarry >>> 26; - ncarry &= 0x3ffffff; - } - out.words[k] = rword; - carry = ncarry; - ncarry = hncarry; - } - if (carry !== 0) { - out.words[k] = carry; - } else { - out.length--; - } - - return out.strip(); - } - - function jumboMulTo (self, num, out) { - var fftm = new FFTM(); - return fftm.mulp(self, num, out); - } - - BN.prototype.mulTo = function mulTo (num, out) { - var res; - var len = this.length + num.length; - if (this.length === 10 && num.length === 10) { - res = comb10MulTo(this, num, out); - } else if (len < 63) { - res = smallMulTo(this, num, out); - } else if (len < 1024) { - res = bigMulTo(this, num, out); - } else { - res = jumboMulTo(this, num, out); - } - - return res; - }; - - // Cooley-Tukey algorithm for FFT - // slightly revisited to rely on looping instead of recursion - - function FFTM (x, y) { - this.x = x; - this.y = y; - } - - FFTM.prototype.makeRBT = function makeRBT (N) { - var t = new Array(N); - var l = BN.prototype._countBits(N) - 1; - for (var i = 0; i < N; i++) { - t[i] = this.revBin(i, l, N); - } - - return t; - }; - - // Returns binary-reversed representation of `x` - FFTM.prototype.revBin = function revBin (x, l, N) { - if (x === 0 || x === N - 1) return x; - - var rb = 0; - for (var i = 0; i < l; i++) { - rb |= (x & 1) << (l - i - 1); - x >>= 1; - } - - return rb; - }; - - // Performs "tweedling" phase, therefore 'emulating' - // behaviour of the recursive algorithm - FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) { - for (var i = 0; i < N; i++) { - rtws[i] = rws[rbt[i]]; - itws[i] = iws[rbt[i]]; - } - }; - - FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) { - this.permute(rbt, rws, iws, rtws, itws, N); - - for (var s = 1; s < N; s <<= 1) { - var l = s << 1; - - var rtwdf = Math.cos(2 * Math.PI / l); - var itwdf = Math.sin(2 * Math.PI / l); - - for (var p = 0; p < N; p += l) { - var rtwdf_ = rtwdf; - var itwdf_ = itwdf; - - for (var j = 0; j < s; j++) { - var re = rtws[p + j]; - var ie = itws[p + j]; - - var ro = rtws[p + j + s]; - var io = itws[p + j + s]; - - var rx = rtwdf_ * ro - itwdf_ * io; - - io = rtwdf_ * io + itwdf_ * ro; - ro = rx; - - rtws[p + j] = re + ro; - itws[p + j] = ie + io; - - rtws[p + j + s] = re - ro; - itws[p + j + s] = ie - io; - - /* jshint maxdepth : false */ - if (j !== l) { - rx = rtwdf * rtwdf_ - itwdf * itwdf_; - - itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_; - rtwdf_ = rx; - } - } - } - } - }; - - FFTM.prototype.guessLen13b = function guessLen13b (n, m) { - var N = Math.max(m, n) | 1; - var odd = N & 1; - var i = 0; - for (N = N / 2 | 0; N; N = N >>> 1) { - i++; - } - - return 1 << i + 1 + odd; - }; - - FFTM.prototype.conjugate = function conjugate (rws, iws, N) { - if (N <= 1) return; - - for (var i = 0; i < N / 2; i++) { - var t = rws[i]; - - rws[i] = rws[N - i - 1]; - rws[N - i - 1] = t; - - t = iws[i]; - - iws[i] = -iws[N - i - 1]; - iws[N - i - 1] = -t; - } - }; - - FFTM.prototype.normalize13b = function normalize13b (ws, N) { - var carry = 0; - for (var i = 0; i < N / 2; i++) { - var w = Math.round(ws[2 * i + 1] / N) * 0x2000 + - Math.round(ws[2 * i] / N) + - carry; - - ws[i] = w & 0x3ffffff; - - if (w < 0x4000000) { - carry = 0; - } else { - carry = w / 0x4000000 | 0; - } - } - - return ws; - }; - - FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) { - var carry = 0; - for (var i = 0; i < len; i++) { - carry = carry + (ws[i] | 0); - - rws[2 * i] = carry & 0x1fff; carry = carry >>> 13; - rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13; - } - - // Pad with zeroes - for (i = 2 * len; i < N; ++i) { - rws[i] = 0; - } - - assert(carry === 0); - assert((carry & ~0x1fff) === 0); - }; - - FFTM.prototype.stub = function stub (N) { - var ph = new Array(N); - for (var i = 0; i < N; i++) { - ph[i] = 0; - } - - return ph; - }; - - FFTM.prototype.mulp = function mulp (x, y, out) { - var N = 2 * this.guessLen13b(x.length, y.length); - - var rbt = this.makeRBT(N); - - var _ = this.stub(N); - - var rws = new Array(N); - var rwst = new Array(N); - var iwst = new Array(N); - - var nrws = new Array(N); - var nrwst = new Array(N); - var niwst = new Array(N); - - var rmws = out.words; - rmws.length = N; - - this.convert13b(x.words, x.length, rws, N); - this.convert13b(y.words, y.length, nrws, N); - - this.transform(rws, _, rwst, iwst, N, rbt); - this.transform(nrws, _, nrwst, niwst, N, rbt); - - for (var i = 0; i < N; i++) { - var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i]; - iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i]; - rwst[i] = rx; - } - - this.conjugate(rwst, iwst, N); - this.transform(rwst, iwst, rmws, _, N, rbt); - this.conjugate(rmws, _, N); - this.normalize13b(rmws, N); - - out.negative = x.negative ^ y.negative; - out.length = x.length + y.length; - return out.strip(); - }; - - // Multiply `this` by `num` - BN.prototype.mul = function mul (num) { - var out = new BN(null); - out.words = new Array(this.length + num.length); - return this.mulTo(num, out); - }; - - // Multiply employing FFT - BN.prototype.mulf = function mulf (num) { - var out = new BN(null); - out.words = new Array(this.length + num.length); - return jumboMulTo(this, num, out); - }; - - // In-place Multiplication - BN.prototype.imul = function imul (num) { - return this.clone().mulTo(num, this); - }; - - BN.prototype.imuln = function imuln (num) { - assert(typeof num === 'number'); - assert(num < 0x4000000); - - // Carry - var carry = 0; - for (var i = 0; i < this.length; i++) { - var w = (this.words[i] | 0) * num; - var lo = (w & 0x3ffffff) + (carry & 0x3ffffff); - carry >>= 26; - carry += (w / 0x4000000) | 0; - // NOTE: lo is 27bit maximum - carry += lo >>> 26; - this.words[i] = lo & 0x3ffffff; - } - - if (carry !== 0) { - this.words[i] = carry; - this.length++; - } - - return this; - }; - - BN.prototype.muln = function muln (num) { - return this.clone().imuln(num); - }; - - // `this` * `this` - BN.prototype.sqr = function sqr () { - return this.mul(this); - }; - - // `this` * `this` in-place - BN.prototype.isqr = function isqr () { - return this.imul(this.clone()); - }; - - // Math.pow(`this`, `num`) - BN.prototype.pow = function pow (num) { - var w = toBitArray(num); - if (w.length === 0) return new BN(1); - - // Skip leading zeroes - var res = this; - for (var i = 0; i < w.length; i++, res = res.sqr()) { - if (w[i] !== 0) break; - } - - if (++i < w.length) { - for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) { - if (w[i] === 0) continue; - - res = res.mul(q); - } - } - - return res; - }; - - // Shift-left in-place - BN.prototype.iushln = function iushln (bits) { - assert(typeof bits === 'number' && bits >= 0); - var r = bits % 26; - var s = (bits - r) / 26; - var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r); - var i; - - if (r !== 0) { - var carry = 0; - - for (i = 0; i < this.length; i++) { - var newCarry = this.words[i] & carryMask; - var c = ((this.words[i] | 0) - newCarry) << r; - this.words[i] = c | carry; - carry = newCarry >>> (26 - r); - } - - if (carry) { - this.words[i] = carry; - this.length++; - } - } - - if (s !== 0) { - for (i = this.length - 1; i >= 0; i--) { - this.words[i + s] = this.words[i]; - } - - for (i = 0; i < s; i++) { - this.words[i] = 0; - } - - this.length += s; - } - - return this.strip(); - }; - - BN.prototype.ishln = function ishln (bits) { - // TODO(indutny): implement me - assert(this.negative === 0); - return this.iushln(bits); - }; - - // Shift-right in-place - // NOTE: `hint` is a lowest bit before trailing zeroes - // NOTE: if `extended` is present - it will be filled with destroyed bits - BN.prototype.iushrn = function iushrn (bits, hint, extended) { - assert(typeof bits === 'number' && bits >= 0); - var h; - if (hint) { - h = (hint - (hint % 26)) / 26; - } else { - h = 0; - } - - var r = bits % 26; - var s = Math.min((bits - r) / 26, this.length); - var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); - var maskedWords = extended; - - h -= s; - h = Math.max(0, h); - - // Extended mode, copy masked part - if (maskedWords) { - for (var i = 0; i < s; i++) { - maskedWords.words[i] = this.words[i]; - } - maskedWords.length = s; - } - - if (s === 0) { - // No-op, we should not move anything at all - } else if (this.length > s) { - this.length -= s; - for (i = 0; i < this.length; i++) { - this.words[i] = this.words[i + s]; - } - } else { - this.words[0] = 0; - this.length = 1; - } - - var carry = 0; - for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) { - var word = this.words[i] | 0; - this.words[i] = (carry << (26 - r)) | (word >>> r); - carry = word & mask; - } - - // Push carried bits as a mask - if (maskedWords && carry !== 0) { - maskedWords.words[maskedWords.length++] = carry; - } - - if (this.length === 0) { - this.words[0] = 0; - this.length = 1; - } - - return this.strip(); - }; - - BN.prototype.ishrn = function ishrn (bits, hint, extended) { - // TODO(indutny): implement me - assert(this.negative === 0); - return this.iushrn(bits, hint, extended); - }; - - // Shift-left - BN.prototype.shln = function shln (bits) { - return this.clone().ishln(bits); - }; - - BN.prototype.ushln = function ushln (bits) { - return this.clone().iushln(bits); - }; - - // Shift-right - BN.prototype.shrn = function shrn (bits) { - return this.clone().ishrn(bits); - }; - - BN.prototype.ushrn = function ushrn (bits) { - return this.clone().iushrn(bits); - }; - - // Test if n bit is set - BN.prototype.testn = function testn (bit) { - assert(typeof bit === 'number' && bit >= 0); - var r = bit % 26; - var s = (bit - r) / 26; - var q = 1 << r; - - // Fast case: bit is much higher than all existing words - if (this.length <= s) return false; - - // Check bit and return - var w = this.words[s]; - - return !!(w & q); - }; - - // Return only lowers bits of number (in-place) - BN.prototype.imaskn = function imaskn (bits) { - assert(typeof bits === 'number' && bits >= 0); - var r = bits % 26; - var s = (bits - r) / 26; - - assert(this.negative === 0, 'imaskn works only with positive numbers'); - - if (this.length <= s) { - return this; - } - - if (r !== 0) { - s++; - } - this.length = Math.min(s, this.length); - - if (r !== 0) { - var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); - this.words[this.length - 1] &= mask; - } - - return this.strip(); - }; - - // Return only lowers bits of number - BN.prototype.maskn = function maskn (bits) { - return this.clone().imaskn(bits); - }; - - // Add plain number `num` to `this` - BN.prototype.iaddn = function iaddn (num) { - assert(typeof num === 'number'); - assert(num < 0x4000000); - if (num < 0) return this.isubn(-num); - - // Possible sign change - if (this.negative !== 0) { - if (this.length === 1 && (this.words[0] | 0) < num) { - this.words[0] = num - (this.words[0] | 0); - this.negative = 0; - return this; - } - - this.negative = 0; - this.isubn(num); - this.negative = 1; - return this; - } - - // Add without checks - return this._iaddn(num); - }; - - BN.prototype._iaddn = function _iaddn (num) { - this.words[0] += num; - - // Carry - for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) { - this.words[i] -= 0x4000000; - if (i === this.length - 1) { - this.words[i + 1] = 1; - } else { - this.words[i + 1]++; - } - } - this.length = Math.max(this.length, i + 1); - - return this; - }; - - // Subtract plain number `num` from `this` - BN.prototype.isubn = function isubn (num) { - assert(typeof num === 'number'); - assert(num < 0x4000000); - if (num < 0) return this.iaddn(-num); - - if (this.negative !== 0) { - this.negative = 0; - this.iaddn(num); - this.negative = 1; - return this; - } - - this.words[0] -= num; - - if (this.length === 1 && this.words[0] < 0) { - this.words[0] = -this.words[0]; - this.negative = 1; - } else { - // Carry - for (var i = 0; i < this.length && this.words[i] < 0; i++) { - this.words[i] += 0x4000000; - this.words[i + 1] -= 1; - } - } - - return this.strip(); - }; - - BN.prototype.addn = function addn (num) { - return this.clone().iaddn(num); - }; - - BN.prototype.subn = function subn (num) { - return this.clone().isubn(num); - }; - - BN.prototype.iabs = function iabs () { - this.negative = 0; - - return this; - }; - - BN.prototype.abs = function abs () { - return this.clone().iabs(); - }; - - BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) { - var len = num.length + shift; - var i; - - this._expand(len); - - var w; - var carry = 0; - for (i = 0; i < num.length; i++) { - w = (this.words[i + shift] | 0) + carry; - var right = (num.words[i] | 0) * mul; - w -= right & 0x3ffffff; - carry = (w >> 26) - ((right / 0x4000000) | 0); - this.words[i + shift] = w & 0x3ffffff; - } - for (; i < this.length - shift; i++) { - w = (this.words[i + shift] | 0) + carry; - carry = w >> 26; - this.words[i + shift] = w & 0x3ffffff; - } - - if (carry === 0) return this.strip(); - - // Subtraction overflow - assert(carry === -1); - carry = 0; - for (i = 0; i < this.length; i++) { - w = -(this.words[i] | 0) + carry; - carry = w >> 26; - this.words[i] = w & 0x3ffffff; - } - this.negative = 1; - - return this.strip(); - }; - - BN.prototype._wordDiv = function _wordDiv (num, mode) { - var shift = this.length - num.length; - - var a = this.clone(); - var b = num; - - // Normalize - var bhi = b.words[b.length - 1] | 0; - var bhiBits = this._countBits(bhi); - shift = 26 - bhiBits; - if (shift !== 0) { - b = b.ushln(shift); - a.iushln(shift); - bhi = b.words[b.length - 1] | 0; - } - - // Initialize quotient - var m = a.length - b.length; - var q; - - if (mode !== 'mod') { - q = new BN(null); - q.length = m + 1; - q.words = new Array(q.length); - for (var i = 0; i < q.length; i++) { - q.words[i] = 0; - } - } - - var diff = a.clone()._ishlnsubmul(b, 1, m); - if (diff.negative === 0) { - a = diff; - if (q) { - q.words[m] = 1; - } - } - - for (var j = m - 1; j >= 0; j--) { - var qj = (a.words[b.length + j] | 0) * 0x4000000 + - (a.words[b.length + j - 1] | 0); - - // NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max - // (0x7ffffff) - qj = Math.min((qj / bhi) | 0, 0x3ffffff); - - a._ishlnsubmul(b, qj, j); - while (a.negative !== 0) { - qj--; - a.negative = 0; - a._ishlnsubmul(b, 1, j); - if (!a.isZero()) { - a.negative ^= 1; - } - } - if (q) { - q.words[j] = qj; - } - } - if (q) { - q.strip(); - } - a.strip(); - - // Denormalize - if (mode !== 'div' && shift !== 0) { - a.iushrn(shift); - } - - return { - div: q || null, - mod: a - }; - }; - - // NOTE: 1) `mode` can be set to `mod` to request mod only, - // to `div` to request div only, or be absent to - // request both div & mod - // 2) `positive` is true if unsigned mod is requested - BN.prototype.divmod = function divmod (num, mode, positive) { - assert(!num.isZero()); - - if (this.isZero()) { - return { - div: new BN(0), - mod: new BN(0) - }; - } - - var div, mod, res; - if (this.negative !== 0 && num.negative === 0) { - res = this.neg().divmod(num, mode); - - if (mode !== 'mod') { - div = res.div.neg(); - } - - if (mode !== 'div') { - mod = res.mod.neg(); - if (positive && mod.negative !== 0) { - mod.iadd(num); - } - } - - return { - div: div, - mod: mod - }; - } - - if (this.negative === 0 && num.negative !== 0) { - res = this.divmod(num.neg(), mode); - - if (mode !== 'mod') { - div = res.div.neg(); - } - - return { - div: div, - mod: res.mod - }; - } - - if ((this.negative & num.negative) !== 0) { - res = this.neg().divmod(num.neg(), mode); - - if (mode !== 'div') { - mod = res.mod.neg(); - if (positive && mod.negative !== 0) { - mod.isub(num); - } - } - - return { - div: res.div, - mod: mod - }; - } - - // Both numbers are positive at this point - - // Strip both numbers to approximate shift value - if (num.length > this.length || this.cmp(num) < 0) { - return { - div: new BN(0), - mod: this - }; - } - - // Very short reduction - if (num.length === 1) { - if (mode === 'div') { - return { - div: this.divn(num.words[0]), - mod: null - }; - } - - if (mode === 'mod') { - return { - div: null, - mod: new BN(this.modn(num.words[0])) - }; - } - - return { - div: this.divn(num.words[0]), - mod: new BN(this.modn(num.words[0])) - }; - } - - return this._wordDiv(num, mode); - }; - - // Find `this` / `num` - BN.prototype.div = function div (num) { - return this.divmod(num, 'div', false).div; - }; - - // Find `this` % `num` - BN.prototype.mod = function mod (num) { - return this.divmod(num, 'mod', false).mod; - }; - - BN.prototype.umod = function umod (num) { - return this.divmod(num, 'mod', true).mod; - }; - - // Find Round(`this` / `num`) - BN.prototype.divRound = function divRound (num) { - var dm = this.divmod(num); - - // Fast case - exact division - if (dm.mod.isZero()) return dm.div; - - var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod; - - var half = num.ushrn(1); - var r2 = num.andln(1); - var cmp = mod.cmp(half); - - // Round down - if (cmp < 0 || r2 === 1 && cmp === 0) return dm.div; - - // Round up - return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1); - }; - - BN.prototype.modn = function modn (num) { - assert(num <= 0x3ffffff); - var p = (1 << 26) % num; - - var acc = 0; - for (var i = this.length - 1; i >= 0; i--) { - acc = (p * acc + (this.words[i] | 0)) % num; - } - - return acc; - }; - - // In-place division by number - BN.prototype.idivn = function idivn (num) { - assert(num <= 0x3ffffff); - - var carry = 0; - for (var i = this.length - 1; i >= 0; i--) { - var w = (this.words[i] | 0) + carry * 0x4000000; - this.words[i] = (w / num) | 0; - carry = w % num; - } - - return this.strip(); - }; - - BN.prototype.divn = function divn (num) { - return this.clone().idivn(num); - }; - - BN.prototype.egcd = function egcd (p) { - assert(p.negative === 0); - assert(!p.isZero()); - - var x = this; - var y = p.clone(); - - if (x.negative !== 0) { - x = x.umod(p); - } else { - x = x.clone(); - } - - // A * x + B * y = x - var A = new BN(1); - var B = new BN(0); - - // C * x + D * y = y - var C = new BN(0); - var D = new BN(1); - - var g = 0; - - while (x.isEven() && y.isEven()) { - x.iushrn(1); - y.iushrn(1); - ++g; - } - - var yp = y.clone(); - var xp = x.clone(); - - while (!x.isZero()) { - for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1); - if (i > 0) { - x.iushrn(i); - while (i-- > 0) { - if (A.isOdd() || B.isOdd()) { - A.iadd(yp); - B.isub(xp); - } - - A.iushrn(1); - B.iushrn(1); - } - } - - for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); - if (j > 0) { - y.iushrn(j); - while (j-- > 0) { - if (C.isOdd() || D.isOdd()) { - C.iadd(yp); - D.isub(xp); - } - - C.iushrn(1); - D.iushrn(1); - } - } - - if (x.cmp(y) >= 0) { - x.isub(y); - A.isub(C); - B.isub(D); - } else { - y.isub(x); - C.isub(A); - D.isub(B); - } - } - - return { - a: C, - b: D, - gcd: y.iushln(g) - }; - }; - - // This is reduced incarnation of the binary EEA - // above, designated to invert members of the - // _prime_ fields F(p) at a maximal speed - BN.prototype._invmp = function _invmp (p) { - assert(p.negative === 0); - assert(!p.isZero()); - - var a = this; - var b = p.clone(); - - if (a.negative !== 0) { - a = a.umod(p); - } else { - a = a.clone(); - } - - var x1 = new BN(1); - var x2 = new BN(0); - - var delta = b.clone(); - - while (a.cmpn(1) > 0 && b.cmpn(1) > 0) { - for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1); - if (i > 0) { - a.iushrn(i); - while (i-- > 0) { - if (x1.isOdd()) { - x1.iadd(delta); - } - - x1.iushrn(1); - } - } - - for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); - if (j > 0) { - b.iushrn(j); - while (j-- > 0) { - if (x2.isOdd()) { - x2.iadd(delta); - } - - x2.iushrn(1); - } - } - - if (a.cmp(b) >= 0) { - a.isub(b); - x1.isub(x2); - } else { - b.isub(a); - x2.isub(x1); - } - } - - var res; - if (a.cmpn(1) === 0) { - res = x1; - } else { - res = x2; - } - - if (res.cmpn(0) < 0) { - res.iadd(p); - } - - return res; - }; - - BN.prototype.gcd = function gcd (num) { - if (this.isZero()) return num.abs(); - if (num.isZero()) return this.abs(); - - var a = this.clone(); - var b = num.clone(); - a.negative = 0; - b.negative = 0; - - // Remove common factor of two - for (var shift = 0; a.isEven() && b.isEven(); shift++) { - a.iushrn(1); - b.iushrn(1); - } - - do { - while (a.isEven()) { - a.iushrn(1); - } - while (b.isEven()) { - b.iushrn(1); - } - - var r = a.cmp(b); - if (r < 0) { - // Swap `a` and `b` to make `a` always bigger than `b` - var t = a; - a = b; - b = t; - } else if (r === 0 || b.cmpn(1) === 0) { - break; - } - - a.isub(b); - } while (true); - - return b.iushln(shift); - }; - - // Invert number in the field F(num) - BN.prototype.invm = function invm (num) { - return this.egcd(num).a.umod(num); - }; - - BN.prototype.isEven = function isEven () { - return (this.words[0] & 1) === 0; - }; - - BN.prototype.isOdd = function isOdd () { - return (this.words[0] & 1) === 1; - }; - - // And first word and num - BN.prototype.andln = function andln (num) { - return this.words[0] & num; - }; - - // Increment at the bit position in-line - BN.prototype.bincn = function bincn (bit) { - assert(typeof bit === 'number'); - var r = bit % 26; - var s = (bit - r) / 26; - var q = 1 << r; - - // Fast case: bit is much higher than all existing words - if (this.length <= s) { - this._expand(s + 1); - this.words[s] |= q; - return this; - } - - // Add bit and propagate, if needed - var carry = q; - for (var i = s; carry !== 0 && i < this.length; i++) { - var w = this.words[i] | 0; - w += carry; - carry = w >>> 26; - w &= 0x3ffffff; - this.words[i] = w; - } - if (carry !== 0) { - this.words[i] = carry; - this.length++; - } - return this; - }; - - BN.prototype.isZero = function isZero () { - return this.length === 1 && this.words[0] === 0; - }; - - BN.prototype.cmpn = function cmpn (num) { - var negative = num < 0; - - if (this.negative !== 0 && !negative) return -1; - if (this.negative === 0 && negative) return 1; - - this.strip(); - - var res; - if (this.length > 1) { - res = 1; - } else { - if (negative) { - num = -num; - } - - assert(num <= 0x3ffffff, 'Number is too big'); - - var w = this.words[0] | 0; - res = w === num ? 0 : w < num ? -1 : 1; - } - if (this.negative !== 0) return -res | 0; - return res; - }; - - // Compare two numbers and return: - // 1 - if `this` > `num` - // 0 - if `this` == `num` - // -1 - if `this` < `num` - BN.prototype.cmp = function cmp (num) { - if (this.negative !== 0 && num.negative === 0) return -1; - if (this.negative === 0 && num.negative !== 0) return 1; - - var res = this.ucmp(num); - if (this.negative !== 0) return -res | 0; - return res; - }; - - // Unsigned comparison - BN.prototype.ucmp = function ucmp (num) { - // At this point both numbers have the same sign - if (this.length > num.length) return 1; - if (this.length < num.length) return -1; - - var res = 0; - for (var i = this.length - 1; i >= 0; i--) { - var a = this.words[i] | 0; - var b = num.words[i] | 0; - - if (a === b) continue; - if (a < b) { - res = -1; - } else if (a > b) { - res = 1; - } - break; - } - return res; - }; - - BN.prototype.gtn = function gtn (num) { - return this.cmpn(num) === 1; - }; - - BN.prototype.gt = function gt (num) { - return this.cmp(num) === 1; - }; - - BN.prototype.gten = function gten (num) { - return this.cmpn(num) >= 0; - }; - - BN.prototype.gte = function gte (num) { - return this.cmp(num) >= 0; - }; - - BN.prototype.ltn = function ltn (num) { - return this.cmpn(num) === -1; - }; - - BN.prototype.lt = function lt (num) { - return this.cmp(num) === -1; - }; - - BN.prototype.lten = function lten (num) { - return this.cmpn(num) <= 0; - }; - - BN.prototype.lte = function lte (num) { - return this.cmp(num) <= 0; - }; - - BN.prototype.eqn = function eqn (num) { - return this.cmpn(num) === 0; - }; - - BN.prototype.eq = function eq (num) { - return this.cmp(num) === 0; - }; - - // - // A reduce context, could be using montgomery or something better, depending - // on the `m` itself. - // - BN.red = function red (num) { - return new Red(num); - }; - - BN.prototype.toRed = function toRed (ctx) { - assert(!this.red, 'Already a number in reduction context'); - assert(this.negative === 0, 'red works only with positives'); - return ctx.convertTo(this)._forceRed(ctx); - }; - - BN.prototype.fromRed = function fromRed () { - assert(this.red, 'fromRed works only with numbers in reduction context'); - return this.red.convertFrom(this); - }; - - BN.prototype._forceRed = function _forceRed (ctx) { - this.red = ctx; - return this; - }; - - BN.prototype.forceRed = function forceRed (ctx) { - assert(!this.red, 'Already a number in reduction context'); - return this._forceRed(ctx); - }; - - BN.prototype.redAdd = function redAdd (num) { - assert(this.red, 'redAdd works only with red numbers'); - return this.red.add(this, num); - }; - - BN.prototype.redIAdd = function redIAdd (num) { - assert(this.red, 'redIAdd works only with red numbers'); - return this.red.iadd(this, num); - }; - - BN.prototype.redSub = function redSub (num) { - assert(this.red, 'redSub works only with red numbers'); - return this.red.sub(this, num); - }; - - BN.prototype.redISub = function redISub (num) { - assert(this.red, 'redISub works only with red numbers'); - return this.red.isub(this, num); - }; - - BN.prototype.redShl = function redShl (num) { - assert(this.red, 'redShl works only with red numbers'); - return this.red.shl(this, num); - }; - - BN.prototype.redMul = function redMul (num) { - assert(this.red, 'redMul works only with red numbers'); - this.red._verify2(this, num); - return this.red.mul(this, num); - }; - - BN.prototype.redIMul = function redIMul (num) { - assert(this.red, 'redMul works only with red numbers'); - this.red._verify2(this, num); - return this.red.imul(this, num); - }; - - BN.prototype.redSqr = function redSqr () { - assert(this.red, 'redSqr works only with red numbers'); - this.red._verify1(this); - return this.red.sqr(this); - }; - - BN.prototype.redISqr = function redISqr () { - assert(this.red, 'redISqr works only with red numbers'); - this.red._verify1(this); - return this.red.isqr(this); - }; - - // Square root over p - BN.prototype.redSqrt = function redSqrt () { - assert(this.red, 'redSqrt works only with red numbers'); - this.red._verify1(this); - return this.red.sqrt(this); - }; - - BN.prototype.redInvm = function redInvm () { - assert(this.red, 'redInvm works only with red numbers'); - this.red._verify1(this); - return this.red.invm(this); - }; - - // Return negative clone of `this` % `red modulo` - BN.prototype.redNeg = function redNeg () { - assert(this.red, 'redNeg works only with red numbers'); - this.red._verify1(this); - return this.red.neg(this); - }; - - BN.prototype.redPow = function redPow (num) { - assert(this.red && !num.red, 'redPow(normalNum)'); - this.red._verify1(this); - return this.red.pow(this, num); - }; - - // Prime numbers with efficient reduction - var primes = { - k256: null, - p224: null, - p192: null, - p25519: null - }; - - // Pseudo-Mersenne prime - function MPrime (name, p) { - // P = 2 ^ N - K - this.name = name; - this.p = new BN(p, 16); - this.n = this.p.bitLength(); - this.k = new BN(1).iushln(this.n).isub(this.p); - - this.tmp = this._tmp(); - } - - MPrime.prototype._tmp = function _tmp () { - var tmp = new BN(null); - tmp.words = new Array(Math.ceil(this.n / 13)); - return tmp; - }; - - MPrime.prototype.ireduce = function ireduce (num) { - // Assumes that `num` is less than `P^2` - // num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P) - var r = num; - var rlen; - - do { - this.split(r, this.tmp); - r = this.imulK(r); - r = r.iadd(this.tmp); - rlen = r.bitLength(); - } while (rlen > this.n); - - var cmp = rlen < this.n ? -1 : r.ucmp(this.p); - if (cmp === 0) { - r.words[0] = 0; - r.length = 1; - } else if (cmp > 0) { - r.isub(this.p); - } else { - r.strip(); - } - - return r; - }; - - MPrime.prototype.split = function split (input, out) { - input.iushrn(this.n, 0, out); - }; - - MPrime.prototype.imulK = function imulK (num) { - return num.imul(this.k); - }; - - function K256 () { - MPrime.call( - this, - 'k256', - 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f'); - } - inherits(K256, MPrime); - - K256.prototype.split = function split (input, output) { - // 256 = 9 * 26 + 22 - var mask = 0x3fffff; - - var outLen = Math.min(input.length, 9); - for (var i = 0; i < outLen; i++) { - output.words[i] = input.words[i]; - } - output.length = outLen; - - if (input.length <= 9) { - input.words[0] = 0; - input.length = 1; - return; - } - - // Shift by 9 limbs - var prev = input.words[9]; - output.words[output.length++] = prev & mask; - - for (i = 10; i < input.length; i++) { - var next = input.words[i] | 0; - input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22); - prev = next; - } - prev >>>= 22; - input.words[i - 10] = prev; - if (prev === 0 && input.length > 10) { - input.length -= 10; - } else { - input.length -= 9; - } - }; - - K256.prototype.imulK = function imulK (num) { - // K = 0x1000003d1 = [ 0x40, 0x3d1 ] - num.words[num.length] = 0; - num.words[num.length + 1] = 0; - num.length += 2; - - // bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390 - var lo = 0; - for (var i = 0; i < num.length; i++) { - var w = num.words[i] | 0; - lo += w * 0x3d1; - num.words[i] = lo & 0x3ffffff; - lo = w * 0x40 + ((lo / 0x4000000) | 0); - } - - // Fast length reduction - if (num.words[num.length - 1] === 0) { - num.length--; - if (num.words[num.length - 1] === 0) { - num.length--; - } - } - return num; - }; - - function P224 () { - MPrime.call( - this, - 'p224', - 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001'); - } - inherits(P224, MPrime); - - function P192 () { - MPrime.call( - this, - 'p192', - 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff'); - } - inherits(P192, MPrime); - - function P25519 () { - // 2 ^ 255 - 19 - MPrime.call( - this, - '25519', - '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed'); - } - inherits(P25519, MPrime); - - P25519.prototype.imulK = function imulK (num) { - // K = 0x13 - var carry = 0; - for (var i = 0; i < num.length; i++) { - var hi = (num.words[i] | 0) * 0x13 + carry; - var lo = hi & 0x3ffffff; - hi >>>= 26; - - num.words[i] = lo; - carry = hi; - } - if (carry !== 0) { - num.words[num.length++] = carry; - } - return num; - }; - - // Exported mostly for testing purposes, use plain name instead - BN._prime = function prime (name) { - // Cached version of prime - if (primes[name]) return primes[name]; - - var prime; - if (name === 'k256') { - prime = new K256(); - } else if (name === 'p224') { - prime = new P224(); - } else if (name === 'p192') { - prime = new P192(); - } else if (name === 'p25519') { - prime = new P25519(); - } else { - throw new Error('Unknown prime ' + name); - } - primes[name] = prime; - - return prime; - }; - - // - // Base reduction engine - // - function Red (m) { - if (typeof m === 'string') { - var prime = BN._prime(m); - this.m = prime.p; - this.prime = prime; - } else { - assert(m.gtn(1), 'modulus must be greater than 1'); - this.m = m; - this.prime = null; - } - } - - Red.prototype._verify1 = function _verify1 (a) { - assert(a.negative === 0, 'red works only with positives'); - assert(a.red, 'red works only with red numbers'); - }; - - Red.prototype._verify2 = function _verify2 (a, b) { - assert((a.negative | b.negative) === 0, 'red works only with positives'); - assert(a.red && a.red === b.red, - 'red works only with red numbers'); - }; - - Red.prototype.imod = function imod (a) { - if (this.prime) return this.prime.ireduce(a)._forceRed(this); - return a.umod(this.m)._forceRed(this); - }; - - Red.prototype.neg = function neg (a) { - if (a.isZero()) { - return a.clone(); - } - - return this.m.sub(a)._forceRed(this); - }; - - Red.prototype.add = function add (a, b) { - this._verify2(a, b); - - var res = a.add(b); - if (res.cmp(this.m) >= 0) { - res.isub(this.m); - } - return res._forceRed(this); - }; - - Red.prototype.iadd = function iadd (a, b) { - this._verify2(a, b); - - var res = a.iadd(b); - if (res.cmp(this.m) >= 0) { - res.isub(this.m); - } - return res; - }; - - Red.prototype.sub = function sub (a, b) { - this._verify2(a, b); - - var res = a.sub(b); - if (res.cmpn(0) < 0) { - res.iadd(this.m); - } - return res._forceRed(this); - }; - - Red.prototype.isub = function isub (a, b) { - this._verify2(a, b); - - var res = a.isub(b); - if (res.cmpn(0) < 0) { - res.iadd(this.m); - } - return res; - }; - - Red.prototype.shl = function shl (a, num) { - this._verify1(a); - return this.imod(a.ushln(num)); - }; - - Red.prototype.imul = function imul (a, b) { - this._verify2(a, b); - return this.imod(a.imul(b)); - }; - - Red.prototype.mul = function mul (a, b) { - this._verify2(a, b); - return this.imod(a.mul(b)); - }; - - Red.prototype.isqr = function isqr (a) { - return this.imul(a, a.clone()); - }; - - Red.prototype.sqr = function sqr (a) { - return this.mul(a, a); - }; - - Red.prototype.sqrt = function sqrt (a) { - if (a.isZero()) return a.clone(); - - var mod3 = this.m.andln(3); - assert(mod3 % 2 === 1); - - // Fast case - if (mod3 === 3) { - var pow = this.m.add(new BN(1)).iushrn(2); - return this.pow(a, pow); - } - - // Tonelli-Shanks algorithm (Totally unoptimized and slow) - // - // Find Q and S, that Q * 2 ^ S = (P - 1) - var q = this.m.subn(1); - var s = 0; - while (!q.isZero() && q.andln(1) === 0) { - s++; - q.iushrn(1); - } - assert(!q.isZero()); - - var one = new BN(1).toRed(this); - var nOne = one.redNeg(); - - // Find quadratic non-residue - // NOTE: Max is such because of generalized Riemann hypothesis. - var lpow = this.m.subn(1).iushrn(1); - var z = this.m.bitLength(); - z = new BN(2 * z * z).toRed(this); - - while (this.pow(z, lpow).cmp(nOne) !== 0) { - z.redIAdd(nOne); - } - - var c = this.pow(z, q); - var r = this.pow(a, q.addn(1).iushrn(1)); - var t = this.pow(a, q); - var m = s; - while (t.cmp(one) !== 0) { - var tmp = t; - for (var i = 0; tmp.cmp(one) !== 0; i++) { - tmp = tmp.redSqr(); - } - assert(i < m); - var b = this.pow(c, new BN(1).iushln(m - i - 1)); - - r = r.redMul(b); - c = b.redSqr(); - t = t.redMul(c); - m = i; - } - - return r; - }; - - Red.prototype.invm = function invm (a) { - var inv = a._invmp(this.m); - if (inv.negative !== 0) { - inv.negative = 0; - return this.imod(inv).redNeg(); - } else { - return this.imod(inv); - } - }; - - Red.prototype.pow = function pow (a, num) { - if (num.isZero()) return new BN(1).toRed(this); - if (num.cmpn(1) === 0) return a.clone(); - - var windowSize = 4; - var wnd = new Array(1 << windowSize); - wnd[0] = new BN(1).toRed(this); - wnd[1] = a; - for (var i = 2; i < wnd.length; i++) { - wnd[i] = this.mul(wnd[i - 1], a); - } - - var res = wnd[0]; - var current = 0; - var currentLen = 0; - var start = num.bitLength() % 26; - if (start === 0) { - start = 26; - } - - for (i = num.length - 1; i >= 0; i--) { - var word = num.words[i]; - for (var j = start - 1; j >= 0; j--) { - var bit = (word >> j) & 1; - if (res !== wnd[0]) { - res = this.sqr(res); - } - - if (bit === 0 && current === 0) { - currentLen = 0; - continue; - } - - current <<= 1; - current |= bit; - currentLen++; - if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue; - - res = this.mul(res, wnd[current]); - currentLen = 0; - current = 0; - } - start = 26; - } - - return res; - }; - - Red.prototype.convertTo = function convertTo (num) { - var r = num.umod(this.m); - - return r === num ? r.clone() : r; - }; - - Red.prototype.convertFrom = function convertFrom (num) { - var res = num.clone(); - res.red = null; - return res; - }; - - // - // Montgomery method engine - // - - BN.mont = function mont (num) { - return new Mont(num); - }; - - function Mont (m) { - Red.call(this, m); - - this.shift = this.m.bitLength(); - if (this.shift % 26 !== 0) { - this.shift += 26 - (this.shift % 26); - } - - this.r = new BN(1).iushln(this.shift); - this.r2 = this.imod(this.r.sqr()); - this.rinv = this.r._invmp(this.m); - - this.minv = this.rinv.mul(this.r).isubn(1).div(this.m); - this.minv = this.minv.umod(this.r); - this.minv = this.r.sub(this.minv); - } - inherits(Mont, Red); - - Mont.prototype.convertTo = function convertTo (num) { - return this.imod(num.ushln(this.shift)); - }; - - Mont.prototype.convertFrom = function convertFrom (num) { - var r = this.imod(num.mul(this.rinv)); - r.red = null; - return r; - }; - - Mont.prototype.imul = function imul (a, b) { - if (a.isZero() || b.isZero()) { - a.words[0] = 0; - a.length = 1; - return a; - } - - var t = a.imul(b); - var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); - var u = t.isub(c).iushrn(this.shift); - var res = u; - - if (u.cmp(this.m) >= 0) { - res = u.isub(this.m); - } else if (u.cmpn(0) < 0) { - res = u.iadd(this.m); - } - - return res._forceRed(this); - }; - - Mont.prototype.mul = function mul (a, b) { - if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this); - - var t = a.mul(b); - var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); - var u = t.isub(c).iushrn(this.shift); - var res = u; - if (u.cmp(this.m) >= 0) { - res = u.isub(this.m); - } else if (u.cmpn(0) < 0) { - res = u.iadd(this.m); - } - - return res._forceRed(this); - }; - - Mont.prototype.invm = function invm (a) { - // (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R - var res = this.imod(a._invmp(this.m).mul(this.r2)); - return res._forceRed(this); - }; -})(typeof module === 'undefined' || module, this); - -},{"buffer":"buffer"}],17:[function(require,module,exports){ -var r; - -module.exports = function rand(len) { - if (!r) - r = new Rand(null); - - return r.generate(len); -}; - -function Rand(rand) { - this.rand = rand; -} -module.exports.Rand = Rand; - -Rand.prototype.generate = function generate(len) { - return this._rand(len); -}; - -// Emulate crypto API using randy -Rand.prototype._rand = function _rand(n) { - if (this.rand.getBytes) - return this.rand.getBytes(n); - - var res = new Uint8Array(n); - for (var i = 0; i < res.length; i++) - res[i] = this.rand.getByte(); - return res; -}; - -if (typeof self === 'object') { - if (self.crypto && self.crypto.getRandomValues) { - // Modern browsers - Rand.prototype._rand = function _rand(n) { - var arr = new Uint8Array(n); - self.crypto.getRandomValues(arr); - return arr; - }; - } else if (self.msCrypto && self.msCrypto.getRandomValues) { - // IE - Rand.prototype._rand = function _rand(n) { - var arr = new Uint8Array(n); - self.msCrypto.getRandomValues(arr); - return arr; - }; - - // Safari's WebWorkers do not have `crypto` - } else if (typeof window === 'object') { - // Old junk - Rand.prototype._rand = function() { - throw new Error('Not implemented yet'); - }; - } -} else { - // Node.js or Web worker with no crypto support - try { - var crypto = require('crypto'); - if (typeof crypto.randomBytes !== 'function') - throw new Error('Not supported'); - - Rand.prototype._rand = function _rand(n) { - return crypto.randomBytes(n); - }; - } catch (e) { - } -} - -},{"crypto":"crypto"}],18:[function(require,module,exports){ -'use strict'; - -var elliptic = exports; - -elliptic.utils = require('./elliptic/utils'); -elliptic.rand = require('brorand'); -elliptic.curve = require('./elliptic/curve'); -elliptic.curves = require('./elliptic/curves'); - -// Protocols -elliptic.ec = require('./elliptic/ec'); -elliptic.eddsa = require('./elliptic/eddsa'); - -},{"./elliptic/curve":21,"./elliptic/curves":24,"./elliptic/ec":25,"./elliptic/eddsa":28,"./elliptic/utils":32,"brorand":17}],19:[function(require,module,exports){ -'use strict'; - -var BN = require('bn.js'); -var elliptic = require('../../elliptic'); -var utils = elliptic.utils; -var getNAF = utils.getNAF; -var getJSF = utils.getJSF; -var assert = utils.assert; - -function BaseCurve(type, conf) { - this.type = type; - this.p = new BN(conf.p, 16); - - // Use Montgomery, when there is no fast reduction for the prime - this.red = conf.prime ? BN.red(conf.prime) : BN.mont(this.p); - - // Useful for many curves - this.zero = new BN(0).toRed(this.red); - this.one = new BN(1).toRed(this.red); - this.two = new BN(2).toRed(this.red); - - // Curve configuration, optional - this.n = conf.n && new BN(conf.n, 16); - this.g = conf.g && this.pointFromJSON(conf.g, conf.gRed); - - // Temporary arrays - this._wnafT1 = new Array(4); - this._wnafT2 = new Array(4); - this._wnafT3 = new Array(4); - this._wnafT4 = new Array(4); - - // Generalized Greg Maxwell's trick - var adjustCount = this.n && this.p.div(this.n); - if (!adjustCount || adjustCount.cmpn(100) > 0) { - this.redN = null; - } else { - this._maxwellTrick = true; - this.redN = this.n.toRed(this.red); - } -} -module.exports = BaseCurve; - -BaseCurve.prototype.point = function point() { - throw new Error('Not implemented'); -}; - -BaseCurve.prototype.validate = function validate() { - throw new Error('Not implemented'); -}; - -BaseCurve.prototype._fixedNafMul = function _fixedNafMul(p, k) { - assert(p.precomputed); - var doubles = p._getDoubles(); - - var naf = getNAF(k, 1); - var I = (1 << (doubles.step + 1)) - (doubles.step % 2 === 0 ? 2 : 1); - I /= 3; - - // Translate into more windowed form - var repr = []; - for (var j = 0; j < naf.length; j += doubles.step) { - var nafW = 0; - for (var k = j + doubles.step - 1; k >= j; k--) - nafW = (nafW << 1) + naf[k]; - repr.push(nafW); - } - - var a = this.jpoint(null, null, null); - var b = this.jpoint(null, null, null); - for (var i = I; i > 0; i--) { - for (var j = 0; j < repr.length; j++) { - var nafW = repr[j]; - if (nafW === i) - b = b.mixedAdd(doubles.points[j]); - else if (nafW === -i) - b = b.mixedAdd(doubles.points[j].neg()); - } - a = a.add(b); - } - return a.toP(); -}; - -BaseCurve.prototype._wnafMul = function _wnafMul(p, k) { - var w = 4; - - // Precompute window - var nafPoints = p._getNAFPoints(w); - w = nafPoints.wnd; - var wnd = nafPoints.points; - - // Get NAF form - var naf = getNAF(k, w); - - // Add `this`*(N+1) for every w-NAF index - var acc = this.jpoint(null, null, null); - for (var i = naf.length - 1; i >= 0; i--) { - // Count zeroes - for (var k = 0; i >= 0 && naf[i] === 0; i--) - k++; - if (i >= 0) - k++; - acc = acc.dblp(k); - - if (i < 0) - break; - var z = naf[i]; - assert(z !== 0); - if (p.type === 'affine') { - // J +- P - if (z > 0) - acc = acc.mixedAdd(wnd[(z - 1) >> 1]); - else - acc = acc.mixedAdd(wnd[(-z - 1) >> 1].neg()); - } else { - // J +- J - if (z > 0) - acc = acc.add(wnd[(z - 1) >> 1]); - else - acc = acc.add(wnd[(-z - 1) >> 1].neg()); - } - } - return p.type === 'affine' ? acc.toP() : acc; -}; - -BaseCurve.prototype._wnafMulAdd = function _wnafMulAdd(defW, - points, - coeffs, - len, - jacobianResult) { - var wndWidth = this._wnafT1; - var wnd = this._wnafT2; - var naf = this._wnafT3; - - // Fill all arrays - var max = 0; - for (var i = 0; i < len; i++) { - var p = points[i]; - var nafPoints = p._getNAFPoints(defW); - wndWidth[i] = nafPoints.wnd; - wnd[i] = nafPoints.points; - } - - // Comb small window NAFs - for (var i = len - 1; i >= 1; i -= 2) { - var a = i - 1; - var b = i; - if (wndWidth[a] !== 1 || wndWidth[b] !== 1) { - naf[a] = getNAF(coeffs[a], wndWidth[a]); - naf[b] = getNAF(coeffs[b], wndWidth[b]); - max = Math.max(naf[a].length, max); - max = Math.max(naf[b].length, max); - continue; - } - - var comb = [ - points[a], /* 1 */ - null, /* 3 */ - null, /* 5 */ - points[b] /* 7 */ - ]; - - // Try to avoid Projective points, if possible - if (points[a].y.cmp(points[b].y) === 0) { - comb[1] = points[a].add(points[b]); - comb[2] = points[a].toJ().mixedAdd(points[b].neg()); - } else if (points[a].y.cmp(points[b].y.redNeg()) === 0) { - comb[1] = points[a].toJ().mixedAdd(points[b]); - comb[2] = points[a].add(points[b].neg()); - } else { - comb[1] = points[a].toJ().mixedAdd(points[b]); - comb[2] = points[a].toJ().mixedAdd(points[b].neg()); - } - - var index = [ - -3, /* -1 -1 */ - -1, /* -1 0 */ - -5, /* -1 1 */ - -7, /* 0 -1 */ - 0, /* 0 0 */ - 7, /* 0 1 */ - 5, /* 1 -1 */ - 1, /* 1 0 */ - 3 /* 1 1 */ - ]; - - var jsf = getJSF(coeffs[a], coeffs[b]); - max = Math.max(jsf[0].length, max); - naf[a] = new Array(max); - naf[b] = new Array(max); - for (var j = 0; j < max; j++) { - var ja = jsf[0][j] | 0; - var jb = jsf[1][j] | 0; - - naf[a][j] = index[(ja + 1) * 3 + (jb + 1)]; - naf[b][j] = 0; - wnd[a] = comb; - } - } - - var acc = this.jpoint(null, null, null); - var tmp = this._wnafT4; - for (var i = max; i >= 0; i--) { - var k = 0; - - while (i >= 0) { - var zero = true; - for (var j = 0; j < len; j++) { - tmp[j] = naf[j][i] | 0; - if (tmp[j] !== 0) - zero = false; - } - if (!zero) - break; - k++; - i--; - } - if (i >= 0) - k++; - acc = acc.dblp(k); - if (i < 0) - break; - - for (var j = 0; j < len; j++) { - var z = tmp[j]; - var p; - if (z === 0) - continue; - else if (z > 0) - p = wnd[j][(z - 1) >> 1]; - else if (z < 0) - p = wnd[j][(-z - 1) >> 1].neg(); - - if (p.type === 'affine') - acc = acc.mixedAdd(p); - else - acc = acc.add(p); - } - } - // Zeroify references - for (var i = 0; i < len; i++) - wnd[i] = null; - - if (jacobianResult) - return acc; - else - return acc.toP(); -}; - -function BasePoint(curve, type) { - this.curve = curve; - this.type = type; - this.precomputed = null; -} -BaseCurve.BasePoint = BasePoint; - -BasePoint.prototype.eq = function eq(/*other*/) { - throw new Error('Not implemented'); -}; - -BasePoint.prototype.validate = function validate() { - return this.curve.validate(this); -}; - -BaseCurve.prototype.decodePoint = function decodePoint(bytes, enc) { - bytes = utils.toArray(bytes, enc); - - var len = this.p.byteLength(); - - // uncompressed, hybrid-odd, hybrid-even - if ((bytes[0] === 0x04 || bytes[0] === 0x06 || bytes[0] === 0x07) && - bytes.length - 1 === 2 * len) { - if (bytes[0] === 0x06) - assert(bytes[bytes.length - 1] % 2 === 0); - else if (bytes[0] === 0x07) - assert(bytes[bytes.length - 1] % 2 === 1); - - var res = this.point(bytes.slice(1, 1 + len), - bytes.slice(1 + len, 1 + 2 * len)); - - return res; - } else if ((bytes[0] === 0x02 || bytes[0] === 0x03) && - bytes.length - 1 === len) { - return this.pointFromX(bytes.slice(1, 1 + len), bytes[0] === 0x03); - } - throw new Error('Unknown point format'); -}; - -BasePoint.prototype.encodeCompressed = function encodeCompressed(enc) { - return this.encode(enc, true); -}; - -BasePoint.prototype._encode = function _encode(compact) { - var len = this.curve.p.byteLength(); - var x = this.getX().toArray('be', len); - - if (compact) - return [ this.getY().isEven() ? 0x02 : 0x03 ].concat(x); - - return [ 0x04 ].concat(x, this.getY().toArray('be', len)) ; -}; - -BasePoint.prototype.encode = function encode(enc, compact) { - return utils.encode(this._encode(compact), enc); -}; - -BasePoint.prototype.precompute = function precompute(power) { - if (this.precomputed) - return this; - - var precomputed = { - doubles: null, - naf: null, - beta: null - }; - precomputed.naf = this._getNAFPoints(8); - precomputed.doubles = this._getDoubles(4, power); - precomputed.beta = this._getBeta(); - this.precomputed = precomputed; - - return this; -}; - -BasePoint.prototype._hasDoubles = function _hasDoubles(k) { - if (!this.precomputed) - return false; - - var doubles = this.precomputed.doubles; - if (!doubles) - return false; - - return doubles.points.length >= Math.ceil((k.bitLength() + 1) / doubles.step); -}; - -BasePoint.prototype._getDoubles = function _getDoubles(step, power) { - if (this.precomputed && this.precomputed.doubles) - return this.precomputed.doubles; - - var doubles = [ this ]; - var acc = this; - for (var i = 0; i < power; i += step) { - for (var j = 0; j < step; j++) - acc = acc.dbl(); - doubles.push(acc); - } - return { - step: step, - points: doubles - }; -}; - -BasePoint.prototype._getNAFPoints = function _getNAFPoints(wnd) { - if (this.precomputed && this.precomputed.naf) - return this.precomputed.naf; - - var res = [ this ]; - var max = (1 << wnd) - 1; - var dbl = max === 1 ? null : this.dbl(); - for (var i = 1; i < max; i++) - res[i] = res[i - 1].add(dbl); - return { - wnd: wnd, - points: res - }; -}; - -BasePoint.prototype._getBeta = function _getBeta() { - return null; -}; - -BasePoint.prototype.dblp = function dblp(k) { - var r = this; - for (var i = 0; i < k; i++) - r = r.dbl(); - return r; -}; - -},{"../../elliptic":18,"bn.js":16}],20:[function(require,module,exports){ -'use strict'; - -var curve = require('../curve'); -var elliptic = require('../../elliptic'); -var BN = require('bn.js'); -var inherits = require('inherits'); -var Base = curve.base; - -var assert = elliptic.utils.assert; - -function EdwardsCurve(conf) { - // NOTE: Important as we are creating point in Base.call() - this.twisted = (conf.a | 0) !== 1; - this.mOneA = this.twisted && (conf.a | 0) === -1; - this.extended = this.mOneA; - - Base.call(this, 'edwards', conf); - - this.a = new BN(conf.a, 16).umod(this.red.m); - this.a = this.a.toRed(this.red); - this.c = new BN(conf.c, 16).toRed(this.red); - this.c2 = this.c.redSqr(); - this.d = new BN(conf.d, 16).toRed(this.red); - this.dd = this.d.redAdd(this.d); - - assert(!this.twisted || this.c.fromRed().cmpn(1) === 0); - this.oneC = (conf.c | 0) === 1; -} -inherits(EdwardsCurve, Base); -module.exports = EdwardsCurve; - -EdwardsCurve.prototype._mulA = function _mulA(num) { - if (this.mOneA) - return num.redNeg(); - else - return this.a.redMul(num); -}; - -EdwardsCurve.prototype._mulC = function _mulC(num) { - if (this.oneC) - return num; - else - return this.c.redMul(num); -}; - -// Just for compatibility with Short curve -EdwardsCurve.prototype.jpoint = function jpoint(x, y, z, t) { - return this.point(x, y, z, t); -}; - -EdwardsCurve.prototype.pointFromX = function pointFromX(x, odd) { - x = new BN(x, 16); - if (!x.red) - x = x.toRed(this.red); - - var x2 = x.redSqr(); - var rhs = this.c2.redSub(this.a.redMul(x2)); - var lhs = this.one.redSub(this.c2.redMul(this.d).redMul(x2)); - - var y2 = rhs.redMul(lhs.redInvm()); - var y = y2.redSqrt(); - if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) - throw new Error('invalid point'); - - var isOdd = y.fromRed().isOdd(); - if (odd && !isOdd || !odd && isOdd) - y = y.redNeg(); - - return this.point(x, y); -}; - -EdwardsCurve.prototype.pointFromY = function pointFromY(y, odd) { - y = new BN(y, 16); - if (!y.red) - y = y.toRed(this.red); - - // x^2 = (y^2 - c^2) / (c^2 d y^2 - a) - var y2 = y.redSqr(); - var lhs = y2.redSub(this.c2); - var rhs = y2.redMul(this.d).redMul(this.c2).redSub(this.a); - var x2 = lhs.redMul(rhs.redInvm()); - - if (x2.cmp(this.zero) === 0) { - if (odd) - throw new Error('invalid point'); - else - return this.point(this.zero, y); - } - - var x = x2.redSqrt(); - if (x.redSqr().redSub(x2).cmp(this.zero) !== 0) - throw new Error('invalid point'); - - if (x.fromRed().isOdd() !== odd) - x = x.redNeg(); - - return this.point(x, y); -}; - -EdwardsCurve.prototype.validate = function validate(point) { - if (point.isInfinity()) - return true; - - // Curve: A * X^2 + Y^2 = C^2 * (1 + D * X^2 * Y^2) - point.normalize(); - - var x2 = point.x.redSqr(); - var y2 = point.y.redSqr(); - var lhs = x2.redMul(this.a).redAdd(y2); - var rhs = this.c2.redMul(this.one.redAdd(this.d.redMul(x2).redMul(y2))); - - return lhs.cmp(rhs) === 0; -}; - -function Point(curve, x, y, z, t) { - Base.BasePoint.call(this, curve, 'projective'); - if (x === null && y === null && z === null) { - this.x = this.curve.zero; - this.y = this.curve.one; - this.z = this.curve.one; - this.t = this.curve.zero; - this.zOne = true; - } else { - this.x = new BN(x, 16); - this.y = new BN(y, 16); - this.z = z ? new BN(z, 16) : this.curve.one; - this.t = t && new BN(t, 16); - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.y.red) - this.y = this.y.toRed(this.curve.red); - if (!this.z.red) - this.z = this.z.toRed(this.curve.red); - if (this.t && !this.t.red) - this.t = this.t.toRed(this.curve.red); - this.zOne = this.z === this.curve.one; - - // Use extended coordinates - if (this.curve.extended && !this.t) { - this.t = this.x.redMul(this.y); - if (!this.zOne) - this.t = this.t.redMul(this.z.redInvm()); - } - } -} -inherits(Point, Base.BasePoint); - -EdwardsCurve.prototype.pointFromJSON = function pointFromJSON(obj) { - return Point.fromJSON(this, obj); -}; - -EdwardsCurve.prototype.point = function point(x, y, z, t) { - return new Point(this, x, y, z, t); -}; - -Point.fromJSON = function fromJSON(curve, obj) { - return new Point(curve, obj[0], obj[1], obj[2]); -}; - -Point.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; -}; - -Point.prototype.isInfinity = function isInfinity() { - // XXX This code assumes that zero is always zero in red - return this.x.cmpn(0) === 0 && - (this.y.cmp(this.z) === 0 || - (this.zOne && this.y.cmp(this.curve.c) === 0)); -}; - -Point.prototype._extDbl = function _extDbl() { - // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html - // #doubling-dbl-2008-hwcd - // 4M + 4S - - // A = X1^2 - var a = this.x.redSqr(); - // B = Y1^2 - var b = this.y.redSqr(); - // C = 2 * Z1^2 - var c = this.z.redSqr(); - c = c.redIAdd(c); - // D = a * A - var d = this.curve._mulA(a); - // E = (X1 + Y1)^2 - A - B - var e = this.x.redAdd(this.y).redSqr().redISub(a).redISub(b); - // G = D + B - var g = d.redAdd(b); - // F = G - C - var f = g.redSub(c); - // H = D - B - var h = d.redSub(b); - // X3 = E * F - var nx = e.redMul(f); - // Y3 = G * H - var ny = g.redMul(h); - // T3 = E * H - var nt = e.redMul(h); - // Z3 = F * G - var nz = f.redMul(g); - return this.curve.point(nx, ny, nz, nt); -}; - -Point.prototype._projDbl = function _projDbl() { - // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html - // #doubling-dbl-2008-bbjlp - // #doubling-dbl-2007-bl - // and others - // Generally 3M + 4S or 2M + 4S - - // B = (X1 + Y1)^2 - var b = this.x.redAdd(this.y).redSqr(); - // C = X1^2 - var c = this.x.redSqr(); - // D = Y1^2 - var d = this.y.redSqr(); - - var nx; - var ny; - var nz; - if (this.curve.twisted) { - // E = a * C - var e = this.curve._mulA(c); - // F = E + D - var f = e.redAdd(d); - if (this.zOne) { - // X3 = (B - C - D) * (F - 2) - nx = b.redSub(c).redSub(d).redMul(f.redSub(this.curve.two)); - // Y3 = F * (E - D) - ny = f.redMul(e.redSub(d)); - // Z3 = F^2 - 2 * F - nz = f.redSqr().redSub(f).redSub(f); - } else { - // H = Z1^2 - var h = this.z.redSqr(); - // J = F - 2 * H - var j = f.redSub(h).redISub(h); - // X3 = (B-C-D)*J - nx = b.redSub(c).redISub(d).redMul(j); - // Y3 = F * (E - D) - ny = f.redMul(e.redSub(d)); - // Z3 = F * J - nz = f.redMul(j); - } - } else { - // E = C + D - var e = c.redAdd(d); - // H = (c * Z1)^2 - var h = this.curve._mulC(this.z).redSqr(); - // J = E - 2 * H - var j = e.redSub(h).redSub(h); - // X3 = c * (B - E) * J - nx = this.curve._mulC(b.redISub(e)).redMul(j); - // Y3 = c * E * (C - D) - ny = this.curve._mulC(e).redMul(c.redISub(d)); - // Z3 = E * J - nz = e.redMul(j); - } - return this.curve.point(nx, ny, nz); -}; - -Point.prototype.dbl = function dbl() { - if (this.isInfinity()) - return this; - - // Double in extended coordinates - if (this.curve.extended) - return this._extDbl(); - else - return this._projDbl(); -}; - -Point.prototype._extAdd = function _extAdd(p) { - // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html - // #addition-add-2008-hwcd-3 - // 8M - - // A = (Y1 - X1) * (Y2 - X2) - var a = this.y.redSub(this.x).redMul(p.y.redSub(p.x)); - // B = (Y1 + X1) * (Y2 + X2) - var b = this.y.redAdd(this.x).redMul(p.y.redAdd(p.x)); - // C = T1 * k * T2 - var c = this.t.redMul(this.curve.dd).redMul(p.t); - // D = Z1 * 2 * Z2 - var d = this.z.redMul(p.z.redAdd(p.z)); - // E = B - A - var e = b.redSub(a); - // F = D - C - var f = d.redSub(c); - // G = D + C - var g = d.redAdd(c); - // H = B + A - var h = b.redAdd(a); - // X3 = E * F - var nx = e.redMul(f); - // Y3 = G * H - var ny = g.redMul(h); - // T3 = E * H - var nt = e.redMul(h); - // Z3 = F * G - var nz = f.redMul(g); - return this.curve.point(nx, ny, nz, nt); -}; - -Point.prototype._projAdd = function _projAdd(p) { - // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html - // #addition-add-2008-bbjlp - // #addition-add-2007-bl - // 10M + 1S - - // A = Z1 * Z2 - var a = this.z.redMul(p.z); - // B = A^2 - var b = a.redSqr(); - // C = X1 * X2 - var c = this.x.redMul(p.x); - // D = Y1 * Y2 - var d = this.y.redMul(p.y); - // E = d * C * D - var e = this.curve.d.redMul(c).redMul(d); - // F = B - E - var f = b.redSub(e); - // G = B + E - var g = b.redAdd(e); - // X3 = A * F * ((X1 + Y1) * (X2 + Y2) - C - D) - var tmp = this.x.redAdd(this.y).redMul(p.x.redAdd(p.y)).redISub(c).redISub(d); - var nx = a.redMul(f).redMul(tmp); - var ny; - var nz; - if (this.curve.twisted) { - // Y3 = A * G * (D - a * C) - ny = a.redMul(g).redMul(d.redSub(this.curve._mulA(c))); - // Z3 = F * G - nz = f.redMul(g); - } else { - // Y3 = A * G * (D - C) - ny = a.redMul(g).redMul(d.redSub(c)); - // Z3 = c * F * G - nz = this.curve._mulC(f).redMul(g); - } - return this.curve.point(nx, ny, nz); -}; - -Point.prototype.add = function add(p) { - if (this.isInfinity()) - return p; - if (p.isInfinity()) - return this; - - if (this.curve.extended) - return this._extAdd(p); - else - return this._projAdd(p); -}; - -Point.prototype.mul = function mul(k) { - if (this._hasDoubles(k)) - return this.curve._fixedNafMul(this, k); - else - return this.curve._wnafMul(this, k); -}; - -Point.prototype.mulAdd = function mulAdd(k1, p, k2) { - return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, false); -}; - -Point.prototype.jmulAdd = function jmulAdd(k1, p, k2) { - return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, true); -}; - -Point.prototype.normalize = function normalize() { - if (this.zOne) - return this; - - // Normalize coordinates - var zi = this.z.redInvm(); - this.x = this.x.redMul(zi); - this.y = this.y.redMul(zi); - if (this.t) - this.t = this.t.redMul(zi); - this.z = this.curve.one; - this.zOne = true; - return this; -}; - -Point.prototype.neg = function neg() { - return this.curve.point(this.x.redNeg(), - this.y, - this.z, - this.t && this.t.redNeg()); -}; - -Point.prototype.getX = function getX() { - this.normalize(); - return this.x.fromRed(); -}; - -Point.prototype.getY = function getY() { - this.normalize(); - return this.y.fromRed(); -}; - -Point.prototype.eq = function eq(other) { - return this === other || - this.getX().cmp(other.getX()) === 0 && - this.getY().cmp(other.getY()) === 0; -}; - -Point.prototype.eqXToP = function eqXToP(x) { - var rx = x.toRed(this.curve.red).redMul(this.z); - if (this.x.cmp(rx) === 0) - return true; - - var xc = x.clone(); - var t = this.curve.redN.redMul(this.z); - for (;;) { - xc.iadd(this.curve.n); - if (xc.cmp(this.curve.p) >= 0) - return false; - - rx.redIAdd(t); - if (this.x.cmp(rx) === 0) - return true; - } -}; - -// Compatibility with BaseCurve -Point.prototype.toP = Point.prototype.normalize; -Point.prototype.mixedAdd = Point.prototype.add; - -},{"../../elliptic":18,"../curve":21,"bn.js":16,"inherits":47}],21:[function(require,module,exports){ -'use strict'; - -var curve = exports; - -curve.base = require('./base'); -curve.short = require('./short'); -curve.mont = require('./mont'); -curve.edwards = require('./edwards'); - -},{"./base":19,"./edwards":20,"./mont":22,"./short":23}],22:[function(require,module,exports){ -'use strict'; - -var curve = require('../curve'); -var BN = require('bn.js'); -var inherits = require('inherits'); -var Base = curve.base; - -var elliptic = require('../../elliptic'); -var utils = elliptic.utils; - -function MontCurve(conf) { - Base.call(this, 'mont', conf); - - this.a = new BN(conf.a, 16).toRed(this.red); - this.b = new BN(conf.b, 16).toRed(this.red); - this.i4 = new BN(4).toRed(this.red).redInvm(); - this.two = new BN(2).toRed(this.red); - // Note: this implementation is according to the original paper - // by P. Montgomery, NOT the one by D. J. Bernstein. - this.a24 = this.i4.redMul(this.a.redAdd(this.two)); -} -inherits(MontCurve, Base); -module.exports = MontCurve; - -MontCurve.prototype.validate = function validate(point) { - var x = point.normalize().x; - var x2 = x.redSqr(); - var rhs = x2.redMul(x).redAdd(x2.redMul(this.a)).redAdd(x); - var y = rhs.redSqrt(); - - return y.redSqr().cmp(rhs) === 0; -}; - -function Point(curve, x, z) { - Base.BasePoint.call(this, curve, 'projective'); - if (x === null && z === null) { - this.x = this.curve.one; - this.z = this.curve.zero; - } else { - this.x = new BN(x, 16); - this.z = new BN(z, 16); - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.z.red) - this.z = this.z.toRed(this.curve.red); - } -} -inherits(Point, Base.BasePoint); - -MontCurve.prototype.decodePoint = function decodePoint(bytes, enc) { - var bytes = utils.toArray(bytes, enc); - - // TODO Curve448 - // Montgomery curve points must be represented in the compressed format - // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B - if (bytes.length === 33 && bytes[0] === 0x40) - bytes = bytes.slice(1, 33).reverse(); // point must be little-endian - if (bytes.length !== 32) - throw new Error('Unknown point compression format'); - return this.point(bytes, 1); -}; - -MontCurve.prototype.point = function point(x, z) { - return new Point(this, x, z); -}; - -MontCurve.prototype.pointFromJSON = function pointFromJSON(obj) { - return Point.fromJSON(this, obj); -}; - -Point.prototype.precompute = function precompute() { - // No-op -}; - -Point.prototype._encode = function _encode(compact) { - var len = this.curve.p.byteLength(); - - // Note: the output should always be little-endian - // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B - if (compact) { - return [ 0x40 ].concat(this.getX().toArray('le', len)); - } else { - return this.getX().toArray('be', len); - } -}; - -Point.fromJSON = function fromJSON(curve, obj) { - return new Point(curve, obj[0], obj[1] || curve.one); -}; - -Point.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; -}; - -Point.prototype.isInfinity = function isInfinity() { - // XXX This code assumes that zero is always zero in red - return this.z.cmpn(0) === 0; -}; - -Point.prototype.dbl = function dbl() { - // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#doubling-dbl-1987-m-3 - // 2M + 2S + 4A - - // A = X1 + Z1 - var a = this.x.redAdd(this.z); - // AA = A^2 - var aa = a.redSqr(); - // B = X1 - Z1 - var b = this.x.redSub(this.z); - // BB = B^2 - var bb = b.redSqr(); - // C = AA - BB - var c = aa.redSub(bb); - // X3 = AA * BB - var nx = aa.redMul(bb); - // Z3 = C * (BB + A24 * C) - var nz = c.redMul(bb.redAdd(this.curve.a24.redMul(c))); - return this.curve.point(nx, nz); -}; - -Point.prototype.add = function add() { - throw new Error('Not supported on Montgomery curve'); -}; - -Point.prototype.diffAdd = function diffAdd(p, diff) { - // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#diffadd-dadd-1987-m-3 - // 4M + 2S + 6A - - // A = X2 + Z2 - var a = this.x.redAdd(this.z); - // B = X2 - Z2 - var b = this.x.redSub(this.z); - // C = X3 + Z3 - var c = p.x.redAdd(p.z); - // D = X3 - Z3 - var d = p.x.redSub(p.z); - // DA = D * A - var da = d.redMul(a); - // CB = C * B - var cb = c.redMul(b); - // X5 = Z1 * (DA + CB)^2 - var nx = diff.z.redMul(da.redAdd(cb).redSqr()); - // Z5 = X1 * (DA - CB)^2 - var nz = diff.x.redMul(da.redISub(cb).redSqr()); - return this.curve.point(nx, nz); -}; - -Point.prototype.mul = function mul(k) { - k = new BN(k, 16); - - var t = k.clone(); - var a = this; // (N / 2) * Q + Q - var b = this.curve.point(null, null); // (N / 2) * Q - var c = this; // Q - - for (var bits = []; t.cmpn(0) !== 0; t.iushrn(1)) - bits.push(t.andln(1)); - - for (var i = bits.length - 1; i >= 0; i--) { - if (bits[i] === 0) { - // N * Q + Q = ((N / 2) * Q + Q)) + (N / 2) * Q - a = a.diffAdd(b, c); - // N * Q = 2 * ((N / 2) * Q + Q)) - b = b.dbl(); - } else { - // N * Q = ((N / 2) * Q + Q) + ((N / 2) * Q) - b = a.diffAdd(b, c); - // N * Q + Q = 2 * ((N / 2) * Q + Q) - a = a.dbl(); - } - } - return b; -}; - -Point.prototype.mulAdd = function mulAdd() { - throw new Error('Not supported on Montgomery curve'); -}; - -Point.prototype.jumlAdd = function jumlAdd() { - throw new Error('Not supported on Montgomery curve'); -}; - -Point.prototype.eq = function eq(other) { - return this.getX().cmp(other.getX()) === 0; -}; - -Point.prototype.normalize = function normalize() { - this.x = this.x.redMul(this.z.redInvm()); - this.z = this.curve.one; - return this; -}; - -Point.prototype.getX = function getX() { - // Normalize coordinates - this.normalize(); - - return this.x.fromRed(); -}; - -},{"../../elliptic":18,"../curve":21,"bn.js":16,"inherits":47}],23:[function(require,module,exports){ -'use strict'; - -var curve = require('../curve'); -var elliptic = require('../../elliptic'); -var BN = require('bn.js'); -var inherits = require('inherits'); -var Base = curve.base; - -var assert = elliptic.utils.assert; - -function ShortCurve(conf) { - Base.call(this, 'short', conf); - - this.a = new BN(conf.a, 16).toRed(this.red); - this.b = new BN(conf.b, 16).toRed(this.red); - this.tinv = this.two.redInvm(); - - this.zeroA = this.a.fromRed().cmpn(0) === 0; - this.threeA = this.a.fromRed().sub(this.p).cmpn(-3) === 0; - - // If the curve is endomorphic, precalculate beta and lambda - this.endo = this._getEndomorphism(conf); - this._endoWnafT1 = new Array(4); - this._endoWnafT2 = new Array(4); -} -inherits(ShortCurve, Base); -module.exports = ShortCurve; - -ShortCurve.prototype._getEndomorphism = function _getEndomorphism(conf) { - // No efficient endomorphism - if (!this.zeroA || !this.g || !this.n || this.p.modn(3) !== 1) - return; - - // Compute beta and lambda, that lambda * P = (beta * Px; Py) - var beta; - var lambda; - if (conf.beta) { - beta = new BN(conf.beta, 16).toRed(this.red); - } else { - var betas = this._getEndoRoots(this.p); - // Choose the smallest beta - beta = betas[0].cmp(betas[1]) < 0 ? betas[0] : betas[1]; - beta = beta.toRed(this.red); - } - if (conf.lambda) { - lambda = new BN(conf.lambda, 16); - } else { - // Choose the lambda that is matching selected beta - var lambdas = this._getEndoRoots(this.n); - if (this.g.mul(lambdas[0]).x.cmp(this.g.x.redMul(beta)) === 0) { - lambda = lambdas[0]; - } else { - lambda = lambdas[1]; - assert(this.g.mul(lambda).x.cmp(this.g.x.redMul(beta)) === 0); - } - } - - // Get basis vectors, used for balanced length-two representation - var basis; - if (conf.basis) { - basis = conf.basis.map(function(vec) { - return { - a: new BN(vec.a, 16), - b: new BN(vec.b, 16) - }; - }); - } else { - basis = this._getEndoBasis(lambda); - } - - return { - beta: beta, - lambda: lambda, - basis: basis - }; -}; - -ShortCurve.prototype._getEndoRoots = function _getEndoRoots(num) { - // Find roots of for x^2 + x + 1 in F - // Root = (-1 +- Sqrt(-3)) / 2 - // - var red = num === this.p ? this.red : BN.mont(num); - var tinv = new BN(2).toRed(red).redInvm(); - var ntinv = tinv.redNeg(); - - var s = new BN(3).toRed(red).redNeg().redSqrt().redMul(tinv); - - var l1 = ntinv.redAdd(s).fromRed(); - var l2 = ntinv.redSub(s).fromRed(); - return [ l1, l2 ]; -}; - -ShortCurve.prototype._getEndoBasis = function _getEndoBasis(lambda) { - // aprxSqrt >= sqrt(this.n) - var aprxSqrt = this.n.ushrn(Math.floor(this.n.bitLength() / 2)); - - // 3.74 - // Run EGCD, until r(L + 1) < aprxSqrt - var u = lambda; - var v = this.n.clone(); - var x1 = new BN(1); - var y1 = new BN(0); - var x2 = new BN(0); - var y2 = new BN(1); - - // NOTE: all vectors are roots of: a + b * lambda = 0 (mod n) - var a0; - var b0; - // First vector - var a1; - var b1; - // Second vector - var a2; - var b2; - - var prevR; - var i = 0; - var r; - var x; - while (u.cmpn(0) !== 0) { - var q = v.div(u); - r = v.sub(q.mul(u)); - x = x2.sub(q.mul(x1)); - var y = y2.sub(q.mul(y1)); - - if (!a1 && r.cmp(aprxSqrt) < 0) { - a0 = prevR.neg(); - b0 = x1; - a1 = r.neg(); - b1 = x; - } else if (a1 && ++i === 2) { - break; - } - prevR = r; - - v = u; - u = r; - x2 = x1; - x1 = x; - y2 = y1; - y1 = y; - } - a2 = r.neg(); - b2 = x; - - var len1 = a1.sqr().add(b1.sqr()); - var len2 = a2.sqr().add(b2.sqr()); - if (len2.cmp(len1) >= 0) { - a2 = a0; - b2 = b0; - } - - // Normalize signs - if (a1.negative) { - a1 = a1.neg(); - b1 = b1.neg(); - } - if (a2.negative) { - a2 = a2.neg(); - b2 = b2.neg(); - } - - return [ - { a: a1, b: b1 }, - { a: a2, b: b2 } - ]; -}; - -ShortCurve.prototype._endoSplit = function _endoSplit(k) { - var basis = this.endo.basis; - var v1 = basis[0]; - var v2 = basis[1]; - - var c1 = v2.b.mul(k).divRound(this.n); - var c2 = v1.b.neg().mul(k).divRound(this.n); - - var p1 = c1.mul(v1.a); - var p2 = c2.mul(v2.a); - var q1 = c1.mul(v1.b); - var q2 = c2.mul(v2.b); - - // Calculate answer - var k1 = k.sub(p1).sub(p2); - var k2 = q1.add(q2).neg(); - return { k1: k1, k2: k2 }; -}; - -ShortCurve.prototype.pointFromX = function pointFromX(x, odd) { - x = new BN(x, 16); - if (!x.red) - x = x.toRed(this.red); - - var y2 = x.redSqr().redMul(x).redIAdd(x.redMul(this.a)).redIAdd(this.b); - var y = y2.redSqrt(); - if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) - throw new Error('invalid point'); - - // XXX Is there any way to tell if the number is odd without converting it - // to non-red form? - var isOdd = y.fromRed().isOdd(); - if (odd && !isOdd || !odd && isOdd) - y = y.redNeg(); - - return this.point(x, y); -}; - -ShortCurve.prototype.validate = function validate(point) { - if (point.inf) - return true; - - var x = point.x; - var y = point.y; - - var ax = this.a.redMul(x); - var rhs = x.redSqr().redMul(x).redIAdd(ax).redIAdd(this.b); - return y.redSqr().redISub(rhs).cmpn(0) === 0; -}; - -ShortCurve.prototype._endoWnafMulAdd = - function _endoWnafMulAdd(points, coeffs, jacobianResult) { - var npoints = this._endoWnafT1; - var ncoeffs = this._endoWnafT2; - for (var i = 0; i < points.length; i++) { - var split = this._endoSplit(coeffs[i]); - var p = points[i]; - var beta = p._getBeta(); - - if (split.k1.negative) { - split.k1.ineg(); - p = p.neg(true); - } - if (split.k2.negative) { - split.k2.ineg(); - beta = beta.neg(true); - } - - npoints[i * 2] = p; - npoints[i * 2 + 1] = beta; - ncoeffs[i * 2] = split.k1; - ncoeffs[i * 2 + 1] = split.k2; - } - var res = this._wnafMulAdd(1, npoints, ncoeffs, i * 2, jacobianResult); - - // Clean-up references to points and coefficients - for (var j = 0; j < i * 2; j++) { - npoints[j] = null; - ncoeffs[j] = null; - } - return res; -}; - -function Point(curve, x, y, isRed) { - Base.BasePoint.call(this, curve, 'affine'); - if (x === null && y === null) { - this.x = null; - this.y = null; - this.inf = true; - } else { - this.x = new BN(x, 16); - this.y = new BN(y, 16); - // Force redgomery representation when loading from JSON - if (isRed) { - this.x.forceRed(this.curve.red); - this.y.forceRed(this.curve.red); - } - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.y.red) - this.y = this.y.toRed(this.curve.red); - this.inf = false; - } -} -inherits(Point, Base.BasePoint); - -ShortCurve.prototype.point = function point(x, y, isRed) { - return new Point(this, x, y, isRed); -}; - -ShortCurve.prototype.pointFromJSON = function pointFromJSON(obj, red) { - return Point.fromJSON(this, obj, red); -}; - -Point.prototype._getBeta = function _getBeta() { - if (!this.curve.endo) - return; - - var pre = this.precomputed; - if (pre && pre.beta) - return pre.beta; - - var beta = this.curve.point(this.x.redMul(this.curve.endo.beta), this.y); - if (pre) { - var curve = this.curve; - var endoMul = function(p) { - return curve.point(p.x.redMul(curve.endo.beta), p.y); - }; - pre.beta = beta; - beta.precomputed = { - beta: null, - naf: pre.naf && { - wnd: pre.naf.wnd, - points: pre.naf.points.map(endoMul) - }, - doubles: pre.doubles && { - step: pre.doubles.step, - points: pre.doubles.points.map(endoMul) - } - }; - } - return beta; -}; - -Point.prototype.toJSON = function toJSON() { - if (!this.precomputed) - return [ this.x, this.y ]; - - return [ this.x, this.y, this.precomputed && { - doubles: this.precomputed.doubles && { - step: this.precomputed.doubles.step, - points: this.precomputed.doubles.points.slice(1) - }, - naf: this.precomputed.naf && { - wnd: this.precomputed.naf.wnd, - points: this.precomputed.naf.points.slice(1) - } - } ]; -}; - -Point.fromJSON = function fromJSON(curve, obj, red) { - if (typeof obj === 'string') - obj = JSON.parse(obj); - var res = curve.point(obj[0], obj[1], red); - if (!obj[2]) - return res; - - function obj2point(obj) { - return curve.point(obj[0], obj[1], red); - } - - var pre = obj[2]; - res.precomputed = { - beta: null, - doubles: pre.doubles && { - step: pre.doubles.step, - points: [ res ].concat(pre.doubles.points.map(obj2point)) - }, - naf: pre.naf && { - wnd: pre.naf.wnd, - points: [ res ].concat(pre.naf.points.map(obj2point)) - } - }; - return res; -}; - -Point.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; -}; - -Point.prototype.isInfinity = function isInfinity() { - return this.inf; -}; - -Point.prototype.add = function add(p) { - // O + P = P - if (this.inf) - return p; - - // P + O = P - if (p.inf) - return this; - - // P + P = 2P - if (this.eq(p)) - return this.dbl(); - - // P + (-P) = O - if (this.neg().eq(p)) - return this.curve.point(null, null); - - // P + Q = O - if (this.x.cmp(p.x) === 0) - return this.curve.point(null, null); - - var c = this.y.redSub(p.y); - if (c.cmpn(0) !== 0) - c = c.redMul(this.x.redSub(p.x).redInvm()); - var nx = c.redSqr().redISub(this.x).redISub(p.x); - var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); - return this.curve.point(nx, ny); -}; - -Point.prototype.dbl = function dbl() { - if (this.inf) - return this; - - // 2P = O - var ys1 = this.y.redAdd(this.y); - if (ys1.cmpn(0) === 0) - return this.curve.point(null, null); - - var a = this.curve.a; - - var x2 = this.x.redSqr(); - var dyinv = ys1.redInvm(); - var c = x2.redAdd(x2).redIAdd(x2).redIAdd(a).redMul(dyinv); - - var nx = c.redSqr().redISub(this.x.redAdd(this.x)); - var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); - return this.curve.point(nx, ny); -}; - -Point.prototype.getX = function getX() { - return this.x.fromRed(); -}; - -Point.prototype.getY = function getY() { - return this.y.fromRed(); -}; - -Point.prototype.mul = function mul(k) { - k = new BN(k, 16); - - if (this._hasDoubles(k)) - return this.curve._fixedNafMul(this, k); - else if (this.curve.endo) - return this.curve._endoWnafMulAdd([ this ], [ k ]); - else - return this.curve._wnafMul(this, k); -}; - -Point.prototype.mulAdd = function mulAdd(k1, p2, k2) { - var points = [ this, p2 ]; - var coeffs = [ k1, k2 ]; - if (this.curve.endo) - return this.curve._endoWnafMulAdd(points, coeffs); - else - return this.curve._wnafMulAdd(1, points, coeffs, 2); -}; - -Point.prototype.jmulAdd = function jmulAdd(k1, p2, k2) { - var points = [ this, p2 ]; - var coeffs = [ k1, k2 ]; - if (this.curve.endo) - return this.curve._endoWnafMulAdd(points, coeffs, true); - else - return this.curve._wnafMulAdd(1, points, coeffs, 2, true); -}; - -Point.prototype.eq = function eq(p) { - return this === p || - this.inf === p.inf && - (this.inf || this.x.cmp(p.x) === 0 && this.y.cmp(p.y) === 0); -}; - -Point.prototype.neg = function neg(_precompute) { - if (this.inf) - return this; - - var res = this.curve.point(this.x, this.y.redNeg()); - if (_precompute && this.precomputed) { - var pre = this.precomputed; - var negate = function(p) { - return p.neg(); - }; - res.precomputed = { - naf: pre.naf && { - wnd: pre.naf.wnd, - points: pre.naf.points.map(negate) - }, - doubles: pre.doubles && { - step: pre.doubles.step, - points: pre.doubles.points.map(negate) - } - }; - } - return res; -}; - -Point.prototype.toJ = function toJ() { - if (this.inf) - return this.curve.jpoint(null, null, null); - - var res = this.curve.jpoint(this.x, this.y, this.curve.one); - return res; -}; - -function JPoint(curve, x, y, z) { - Base.BasePoint.call(this, curve, 'jacobian'); - if (x === null && y === null && z === null) { - this.x = this.curve.one; - this.y = this.curve.one; - this.z = new BN(0); - } else { - this.x = new BN(x, 16); - this.y = new BN(y, 16); - this.z = new BN(z, 16); - } - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.y.red) - this.y = this.y.toRed(this.curve.red); - if (!this.z.red) - this.z = this.z.toRed(this.curve.red); - - this.zOne = this.z === this.curve.one; -} -inherits(JPoint, Base.BasePoint); - -ShortCurve.prototype.jpoint = function jpoint(x, y, z) { - return new JPoint(this, x, y, z); -}; - -JPoint.prototype.toP = function toP() { - if (this.isInfinity()) - return this.curve.point(null, null); - - var zinv = this.z.redInvm(); - var zinv2 = zinv.redSqr(); - var ax = this.x.redMul(zinv2); - var ay = this.y.redMul(zinv2).redMul(zinv); - - return this.curve.point(ax, ay); -}; - -JPoint.prototype.neg = function neg() { - return this.curve.jpoint(this.x, this.y.redNeg(), this.z); -}; - -JPoint.prototype.add = function add(p) { - // O + P = P - if (this.isInfinity()) - return p; - - // P + O = P - if (p.isInfinity()) - return this; - - // 12M + 4S + 7A - var pz2 = p.z.redSqr(); - var z2 = this.z.redSqr(); - var u1 = this.x.redMul(pz2); - var u2 = p.x.redMul(z2); - var s1 = this.y.redMul(pz2.redMul(p.z)); - var s2 = p.y.redMul(z2.redMul(this.z)); - - var h = u1.redSub(u2); - var r = s1.redSub(s2); - if (h.cmpn(0) === 0) { - if (r.cmpn(0) !== 0) - return this.curve.jpoint(null, null, null); - else - return this.dbl(); - } - - var h2 = h.redSqr(); - var h3 = h2.redMul(h); - var v = u1.redMul(h2); - - var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); - var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); - var nz = this.z.redMul(p.z).redMul(h); - - return this.curve.jpoint(nx, ny, nz); -}; - -JPoint.prototype.mixedAdd = function mixedAdd(p) { - // O + P = P - if (this.isInfinity()) - return p.toJ(); - - // P + O = P - if (p.isInfinity()) - return this; - - // 8M + 3S + 7A - var z2 = this.z.redSqr(); - var u1 = this.x; - var u2 = p.x.redMul(z2); - var s1 = this.y; - var s2 = p.y.redMul(z2).redMul(this.z); - - var h = u1.redSub(u2); - var r = s1.redSub(s2); - if (h.cmpn(0) === 0) { - if (r.cmpn(0) !== 0) - return this.curve.jpoint(null, null, null); - else - return this.dbl(); - } - - var h2 = h.redSqr(); - var h3 = h2.redMul(h); - var v = u1.redMul(h2); - - var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); - var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); - var nz = this.z.redMul(h); - - return this.curve.jpoint(nx, ny, nz); -}; - -JPoint.prototype.dblp = function dblp(pow) { - if (pow === 0) - return this; - if (this.isInfinity()) - return this; - if (!pow) - return this.dbl(); - - if (this.curve.zeroA || this.curve.threeA) { - var r = this; - for (var i = 0; i < pow; i++) - r = r.dbl(); - return r; - } - - // 1M + 2S + 1A + N * (4S + 5M + 8A) - // N = 1 => 6M + 6S + 9A - var a = this.curve.a; - var tinv = this.curve.tinv; - - var jx = this.x; - var jy = this.y; - var jz = this.z; - var jz4 = jz.redSqr().redSqr(); - - // Reuse results - var jyd = jy.redAdd(jy); - for (var i = 0; i < pow; i++) { - var jx2 = jx.redSqr(); - var jyd2 = jyd.redSqr(); - var jyd4 = jyd2.redSqr(); - var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); - - var t1 = jx.redMul(jyd2); - var nx = c.redSqr().redISub(t1.redAdd(t1)); - var t2 = t1.redISub(nx); - var dny = c.redMul(t2); - dny = dny.redIAdd(dny).redISub(jyd4); - var nz = jyd.redMul(jz); - if (i + 1 < pow) - jz4 = jz4.redMul(jyd4); - - jx = nx; - jz = nz; - jyd = dny; - } - - return this.curve.jpoint(jx, jyd.redMul(tinv), jz); -}; - -JPoint.prototype.dbl = function dbl() { - if (this.isInfinity()) - return this; - - if (this.curve.zeroA) - return this._zeroDbl(); - else if (this.curve.threeA) - return this._threeDbl(); - else - return this._dbl(); -}; - -JPoint.prototype._zeroDbl = function _zeroDbl() { - var nx; - var ny; - var nz; - // Z = 1 - if (this.zOne) { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html - // #doubling-mdbl-2007-bl - // 1M + 5S + 14A - - // XX = X1^2 - var xx = this.x.redSqr(); - // YY = Y1^2 - var yy = this.y.redSqr(); - // YYYY = YY^2 - var yyyy = yy.redSqr(); - // S = 2 * ((X1 + YY)^2 - XX - YYYY) - var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); - s = s.redIAdd(s); - // M = 3 * XX + a; a = 0 - var m = xx.redAdd(xx).redIAdd(xx); - // T = M ^ 2 - 2*S - var t = m.redSqr().redISub(s).redISub(s); - - // 8 * YYYY - var yyyy8 = yyyy.redIAdd(yyyy); - yyyy8 = yyyy8.redIAdd(yyyy8); - yyyy8 = yyyy8.redIAdd(yyyy8); - - // X3 = T - nx = t; - // Y3 = M * (S - T) - 8 * YYYY - ny = m.redMul(s.redISub(t)).redISub(yyyy8); - // Z3 = 2*Y1 - nz = this.y.redAdd(this.y); - } else { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html - // #doubling-dbl-2009-l - // 2M + 5S + 13A - - // A = X1^2 - var a = this.x.redSqr(); - // B = Y1^2 - var b = this.y.redSqr(); - // C = B^2 - var c = b.redSqr(); - // D = 2 * ((X1 + B)^2 - A - C) - var d = this.x.redAdd(b).redSqr().redISub(a).redISub(c); - d = d.redIAdd(d); - // E = 3 * A - var e = a.redAdd(a).redIAdd(a); - // F = E^2 - var f = e.redSqr(); - - // 8 * C - var c8 = c.redIAdd(c); - c8 = c8.redIAdd(c8); - c8 = c8.redIAdd(c8); - - // X3 = F - 2 * D - nx = f.redISub(d).redISub(d); - // Y3 = E * (D - X3) - 8 * C - ny = e.redMul(d.redISub(nx)).redISub(c8); - // Z3 = 2 * Y1 * Z1 - nz = this.y.redMul(this.z); - nz = nz.redIAdd(nz); - } - - return this.curve.jpoint(nx, ny, nz); -}; - -JPoint.prototype._threeDbl = function _threeDbl() { - var nx; - var ny; - var nz; - // Z = 1 - if (this.zOne) { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html - // #doubling-mdbl-2007-bl - // 1M + 5S + 15A - - // XX = X1^2 - var xx = this.x.redSqr(); - // YY = Y1^2 - var yy = this.y.redSqr(); - // YYYY = YY^2 - var yyyy = yy.redSqr(); - // S = 2 * ((X1 + YY)^2 - XX - YYYY) - var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); - s = s.redIAdd(s); - // M = 3 * XX + a - var m = xx.redAdd(xx).redIAdd(xx).redIAdd(this.curve.a); - // T = M^2 - 2 * S - var t = m.redSqr().redISub(s).redISub(s); - // X3 = T - nx = t; - // Y3 = M * (S - T) - 8 * YYYY - var yyyy8 = yyyy.redIAdd(yyyy); - yyyy8 = yyyy8.redIAdd(yyyy8); - yyyy8 = yyyy8.redIAdd(yyyy8); - ny = m.redMul(s.redISub(t)).redISub(yyyy8); - // Z3 = 2 * Y1 - nz = this.y.redAdd(this.y); - } else { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b - // 3M + 5S - - // delta = Z1^2 - var delta = this.z.redSqr(); - // gamma = Y1^2 - var gamma = this.y.redSqr(); - // beta = X1 * gamma - var beta = this.x.redMul(gamma); - // alpha = 3 * (X1 - delta) * (X1 + delta) - var alpha = this.x.redSub(delta).redMul(this.x.redAdd(delta)); - alpha = alpha.redAdd(alpha).redIAdd(alpha); - // X3 = alpha^2 - 8 * beta - var beta4 = beta.redIAdd(beta); - beta4 = beta4.redIAdd(beta4); - var beta8 = beta4.redAdd(beta4); - nx = alpha.redSqr().redISub(beta8); - // Z3 = (Y1 + Z1)^2 - gamma - delta - nz = this.y.redAdd(this.z).redSqr().redISub(gamma).redISub(delta); - // Y3 = alpha * (4 * beta - X3) - 8 * gamma^2 - var ggamma8 = gamma.redSqr(); - ggamma8 = ggamma8.redIAdd(ggamma8); - ggamma8 = ggamma8.redIAdd(ggamma8); - ggamma8 = ggamma8.redIAdd(ggamma8); - ny = alpha.redMul(beta4.redISub(nx)).redISub(ggamma8); - } - - return this.curve.jpoint(nx, ny, nz); -}; - -JPoint.prototype._dbl = function _dbl() { - var a = this.curve.a; - - // 4M + 6S + 10A - var jx = this.x; - var jy = this.y; - var jz = this.z; - var jz4 = jz.redSqr().redSqr(); - - var jx2 = jx.redSqr(); - var jy2 = jy.redSqr(); - - var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); - - var jxd4 = jx.redAdd(jx); - jxd4 = jxd4.redIAdd(jxd4); - var t1 = jxd4.redMul(jy2); - var nx = c.redSqr().redISub(t1.redAdd(t1)); - var t2 = t1.redISub(nx); - - var jyd8 = jy2.redSqr(); - jyd8 = jyd8.redIAdd(jyd8); - jyd8 = jyd8.redIAdd(jyd8); - jyd8 = jyd8.redIAdd(jyd8); - var ny = c.redMul(t2).redISub(jyd8); - var nz = jy.redAdd(jy).redMul(jz); - - return this.curve.jpoint(nx, ny, nz); -}; - -JPoint.prototype.trpl = function trpl() { - if (!this.curve.zeroA) - return this.dbl().add(this); - - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#tripling-tpl-2007-bl - // 5M + 10S + ... - - // XX = X1^2 - var xx = this.x.redSqr(); - // YY = Y1^2 - var yy = this.y.redSqr(); - // ZZ = Z1^2 - var zz = this.z.redSqr(); - // YYYY = YY^2 - var yyyy = yy.redSqr(); - // M = 3 * XX + a * ZZ2; a = 0 - var m = xx.redAdd(xx).redIAdd(xx); - // MM = M^2 - var mm = m.redSqr(); - // E = 6 * ((X1 + YY)^2 - XX - YYYY) - MM - var e = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); - e = e.redIAdd(e); - e = e.redAdd(e).redIAdd(e); - e = e.redISub(mm); - // EE = E^2 - var ee = e.redSqr(); - // T = 16*YYYY - var t = yyyy.redIAdd(yyyy); - t = t.redIAdd(t); - t = t.redIAdd(t); - t = t.redIAdd(t); - // U = (M + E)^2 - MM - EE - T - var u = m.redIAdd(e).redSqr().redISub(mm).redISub(ee).redISub(t); - // X3 = 4 * (X1 * EE - 4 * YY * U) - var yyu4 = yy.redMul(u); - yyu4 = yyu4.redIAdd(yyu4); - yyu4 = yyu4.redIAdd(yyu4); - var nx = this.x.redMul(ee).redISub(yyu4); - nx = nx.redIAdd(nx); - nx = nx.redIAdd(nx); - // Y3 = 8 * Y1 * (U * (T - U) - E * EE) - var ny = this.y.redMul(u.redMul(t.redISub(u)).redISub(e.redMul(ee))); - ny = ny.redIAdd(ny); - ny = ny.redIAdd(ny); - ny = ny.redIAdd(ny); - // Z3 = (Z1 + E)^2 - ZZ - EE - var nz = this.z.redAdd(e).redSqr().redISub(zz).redISub(ee); - - return this.curve.jpoint(nx, ny, nz); -}; - -JPoint.prototype.mul = function mul(k, kbase) { - k = new BN(k, kbase); - - return this.curve._wnafMul(this, k); -}; - -JPoint.prototype.eq = function eq(p) { - if (p.type === 'affine') - return this.eq(p.toJ()); - - if (this === p) - return true; - - // x1 * z2^2 == x2 * z1^2 - var z2 = this.z.redSqr(); - var pz2 = p.z.redSqr(); - if (this.x.redMul(pz2).redISub(p.x.redMul(z2)).cmpn(0) !== 0) - return false; - - // y1 * z2^3 == y2 * z1^3 - var z3 = z2.redMul(this.z); - var pz3 = pz2.redMul(p.z); - return this.y.redMul(pz3).redISub(p.y.redMul(z3)).cmpn(0) === 0; -}; - -JPoint.prototype.eqXToP = function eqXToP(x) { - var zs = this.z.redSqr(); - var rx = x.toRed(this.curve.red).redMul(zs); - if (this.x.cmp(rx) === 0) - return true; - - var xc = x.clone(); - var t = this.curve.redN.redMul(zs); - for (;;) { - xc.iadd(this.curve.n); - if (xc.cmp(this.curve.p) >= 0) - return false; - - rx.redIAdd(t); - if (this.x.cmp(rx) === 0) - return true; - } -}; - -JPoint.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; -}; - -JPoint.prototype.isInfinity = function isInfinity() { - // XXX This code assumes that zero is always zero in red - return this.z.cmpn(0) === 0; -}; - -},{"../../elliptic":18,"../curve":21,"bn.js":16,"inherits":47}],24:[function(require,module,exports){ -'use strict'; - -var curves = exports; - -var hash = require('hash.js'); -var elliptic = require('../elliptic'); - -var assert = elliptic.utils.assert; - -function PresetCurve(options) { - if (options.type === 'short') - this.curve = new elliptic.curve.short(options); - else if (options.type === 'edwards') - this.curve = new elliptic.curve.edwards(options); - else if (options.type === 'mont') - this.curve = new elliptic.curve.mont(options); - else throw new Error('Unknown curve type.'); - this.g = this.curve.g; - this.n = this.curve.n; - this.hash = options.hash; - - assert(this.g.validate(), 'Invalid curve'); - assert(this.g.mul(this.n).isInfinity(), 'Invalid curve, n*G != O'); -} -curves.PresetCurve = PresetCurve; - -function defineCurve(name, options) { - Object.defineProperty(curves, name, { - configurable: true, - enumerable: true, - get: function() { - var curve = new PresetCurve(options); - Object.defineProperty(curves, name, { - configurable: true, - enumerable: true, - value: curve - }); - return curve; - } - }); -} - -defineCurve('p192', { - type: 'short', - prime: 'p192', - p: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff', - a: 'ffffffff ffffffff ffffffff fffffffe ffffffff fffffffc', - b: '64210519 e59c80e7 0fa7e9ab 72243049 feb8deec c146b9b1', - n: 'ffffffff ffffffff ffffffff 99def836 146bc9b1 b4d22831', - hash: hash.sha256, - gRed: false, - g: [ - '188da80e b03090f6 7cbf20eb 43a18800 f4ff0afd 82ff1012', - '07192b95 ffc8da78 631011ed 6b24cdd5 73f977a1 1e794811' - ] -}); - -defineCurve('p224', { - type: 'short', - prime: 'p224', - p: 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001', - a: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff fffffffe', - b: 'b4050a85 0c04b3ab f5413256 5044b0b7 d7bfd8ba 270b3943 2355ffb4', - n: 'ffffffff ffffffff ffffffff ffff16a2 e0b8f03e 13dd2945 5c5c2a3d', - hash: hash.sha256, - gRed: false, - g: [ - 'b70e0cbd 6bb4bf7f 321390b9 4a03c1d3 56c21122 343280d6 115c1d21', - 'bd376388 b5f723fb 4c22dfe6 cd4375a0 5a074764 44d58199 85007e34' - ] -}); - -defineCurve('p256', { - type: 'short', - prime: null, - p: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff', - a: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff fffffffc', - b: '5ac635d8 aa3a93e7 b3ebbd55 769886bc 651d06b0 cc53b0f6 3bce3c3e 27d2604b', - n: 'ffffffff 00000000 ffffffff ffffffff bce6faad a7179e84 f3b9cac2 fc632551', - hash: hash.sha256, - gRed: false, - g: [ - '6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296', - '4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5' - ] -}); - -defineCurve('p384', { - type: 'short', - prime: null, - p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'fffffffe ffffffff 00000000 00000000 ffffffff', - a: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'fffffffe ffffffff 00000000 00000000 fffffffc', - b: 'b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112 0314088f ' + - '5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef', - n: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff c7634d81 ' + - 'f4372ddf 581a0db2 48b0a77a ecec196a ccc52973', - hash: hash.sha384, - gRed: false, - g: [ - 'aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98 59f741e0 82542a38 ' + - '5502f25d bf55296c 3a545e38 72760ab7', - '3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c e9da3113 b5f0b8c0 ' + - '0a60b1ce 1d7e819d 7a431d7c 90ea0e5f' - ] -}); - -defineCurve('p521', { - type: 'short', - prime: null, - p: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff ffffffff', - a: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff fffffffc', - b: '00000051 953eb961 8e1c9a1f 929a21a0 b68540ee a2da725b ' + - '99b315f3 b8b48991 8ef109e1 56193951 ec7e937b 1652c0bd ' + - '3bb1bf07 3573df88 3d2c34f1 ef451fd4 6b503f00', - n: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff fffffffa 51868783 bf2f966b 7fcc0148 ' + - 'f709a5d0 3bb5c9b8 899c47ae bb6fb71e 91386409', - hash: hash.sha512, - gRed: false, - g: [ - '000000c6 858e06b7 0404e9cd 9e3ecb66 2395b442 9c648139 ' + - '053fb521 f828af60 6b4d3dba a14b5e77 efe75928 fe1dc127 ' + - 'a2ffa8de 3348b3c1 856a429b f97e7e31 c2e5bd66', - '00000118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd9 98f54449 ' + - '579b4468 17afbd17 273e662c 97ee7299 5ef42640 c550b901 ' + - '3fad0761 353c7086 a272c240 88be9476 9fd16650' - ] -}); - -// https://tools.ietf.org/html/rfc7748#section-4.1 -defineCurve('curve25519', { - type: 'mont', - prime: 'p25519', - p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', - a: '76d06', - b: '1', - n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', - cofactor: '8', - hash: hash.sha256, - gRed: false, - g: [ - '9' - ] -}); - -defineCurve('ed25519', { - type: 'edwards', - prime: 'p25519', - p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', - a: '-1', - c: '1', - // -121665 * (121666^(-1)) (mod P) - d: '52036cee2b6ffe73 8cc740797779e898 00700a4d4141d8ab 75eb4dca135978a3', - n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', - cofactor: '8', - hash: hash.sha256, - gRed: false, - g: [ - '216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a', - // 4/5 - '6666666666666666666666666666666666666666666666666666666666666658' - ] -}); - -// https://tools.ietf.org/html/rfc5639#section-3.4 -defineCurve('brainpoolP256r1', { - type: 'short', - prime: null, - p: 'A9FB57DB A1EEA9BC 3E660A90 9D838D72 6E3BF623 D5262028 2013481D 1F6E5377', - a: '7D5A0975 FC2C3057 EEF67530 417AFFE7 FB8055C1 26DC5C6C E94A4B44 F330B5D9', - b: '26DC5C6C E94A4B44 F330B5D9 BBD77CBF 95841629 5CF7E1CE 6BCCDC18 FF8C07B6', - n: 'A9FB57DB A1EEA9BC 3E660A90 9D838D71 8C397AA3 B561A6F7 901E0E82 974856A7', - hash: hash.sha256, // or 384, or 512 - gRed: false, - g: [ - '8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262', - '547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997' - ] -}); - -// https://tools.ietf.org/html/rfc5639#section-3.6 -defineCurve('brainpoolP384r1', { - type: 'short', - prime: null, - p: '8CB91E82 A3386D28 0F5D6F7E 50E641DF 152F7109 ED5456B4 12B1DA19 7FB71123' + - 'ACD3A729 901D1A71 87470013 3107EC53', - a: '7BC382C6 3D8C150C 3C72080A CE05AFA0 C2BEA28E 4FB22787 139165EF BA91F90F' + - '8AA5814A 503AD4EB 04A8C7DD 22CE2826', - b: '04A8C7DD 22CE2826 8B39B554 16F0447C 2FB77DE1 07DCD2A6 2E880EA5 3EEB62D5' + - '7CB43902 95DBC994 3AB78696 FA504C11', - n: '8CB91E82 A3386D28 0F5D6F7E 50E641DF 152F7109 ED5456B3 1F166E6C AC0425A7' + - 'CF3AB6AF 6B7FC310 3B883202 E9046565', - hash: hash.sha384, // or 512 - gRed: false, - g: [ - '1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10' + - 'E8E826E03436D646AAEF87B2E247D4AF1E', - '8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129' + - '280E4646217791811142820341263C5315' - ] -}); - -// https://tools.ietf.org/html/rfc5639#section-3.7 -defineCurve('brainpoolP512r1', { - type: 'short', - prime: null, - p: 'AADD9DB8 DBE9C48B 3FD4E6AE 33C9FC07 CB308DB3 B3C9D20E D6639CCA 70330871' + - '7D4D9B00 9BC66842 AECDA12A E6A380E6 2881FF2F 2D82C685 28AA6056 583A48F3', - a: '7830A331 8B603B89 E2327145 AC234CC5 94CBDD8D 3DF91610 A83441CA EA9863BC' + - '2DED5D5A A8253AA1 0A2EF1C9 8B9AC8B5 7F1117A7 2BF2C7B9 E7C1AC4D 77FC94CA', - b: '3DF91610 A83441CA EA9863BC 2DED5D5A A8253AA1 0A2EF1C9 8B9AC8B5 7F1117A7' + - '2BF2C7B9 E7C1AC4D 77FC94CA DC083E67 984050B7 5EBAE5DD 2809BD63 8016F723', - n: 'AADD9DB8 DBE9C48B 3FD4E6AE 33C9FC07 CB308DB3 B3C9D20E D6639CCA 70330870' + - '553E5C41 4CA92619 41866119 7FAC1047 1DB1D381 085DDADD B5879682 9CA90069', - hash: hash.sha512, - gRed: false, - g: [ - '81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D009' + - '8EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822', - '7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F81' + - '11B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892' - ] -}); - -// https://en.bitcoin.it/wiki/Secp256k1 -var pre; -try { - pre = require('./precomputed/secp256k1'); -} catch (e) { - pre = undefined; -} - -defineCurve('secp256k1', { - type: 'short', - prime: 'k256', - p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f', - a: '0', - b: '7', - n: 'ffffffff ffffffff ffffffff fffffffe baaedce6 af48a03b bfd25e8c d0364141', - h: '1', - hash: hash.sha256, - - // Precomputed endomorphism - beta: '7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee', - lambda: '5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72', - basis: [ - { - a: '3086d221a7d46bcde86c90e49284eb15', - b: '-e4437ed6010e88286f547fa90abfe4c3' - }, - { - a: '114ca50f7a8e2f3f657c1108d9d44cfd8', - b: '3086d221a7d46bcde86c90e49284eb15' - } - ], - - gRed: false, - g: [ - '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', - '483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', - pre - ] -}); - -},{"../elliptic":18,"./precomputed/secp256k1":31,"hash.js":34}],25:[function(require,module,exports){ -'use strict'; - -var BN = require('bn.js'); -var HmacDRBG = require('hmac-drbg'); -var elliptic = require('../../elliptic'); -var utils = elliptic.utils; -var assert = utils.assert; - -var KeyPair = require('./key'); -var Signature = require('./signature'); - -function EC(options) { - if (!(this instanceof EC)) - return new EC(options); - - // Shortcut `elliptic.ec(curve-name)` - if (typeof options === 'string') { - assert(elliptic.curves.hasOwnProperty(options), 'Unknown curve ' + options); - - options = elliptic.curves[options]; - } - - // Shortcut for `elliptic.ec(elliptic.curves.curveName)` - if (options instanceof elliptic.curves.PresetCurve) - options = { curve: options }; - - this.curve = options.curve.curve; - this.n = this.curve.n; - this.nh = this.n.ushrn(1); - this.g = this.curve.g; - - // Point on curve - this.g = options.curve.g; - this.g.precompute(options.curve.n.bitLength() + 1); - - // Hash function for DRBG - this.hash = options.hash || options.curve.hash; -} -module.exports = EC; - -EC.prototype.keyPair = function keyPair(options) { - return new KeyPair(this, options); -}; - -EC.prototype.keyFromPrivate = function keyFromPrivate(priv, enc) { - return KeyPair.fromPrivate(this, priv, enc); -}; - -EC.prototype.keyFromPublic = function keyFromPublic(pub, enc) { - return KeyPair.fromPublic(this, pub, enc); -}; - -EC.prototype.genKeyPair = function genKeyPair(options) { - if (!options) - options = {}; - - // Instantiate Hmac_DRBG - var drbg = new HmacDRBG({ - hash: this.hash, - pers: options.pers, - persEnc: options.persEnc || 'utf8', - entropy: options.entropy || elliptic.rand(this.hash.hmacStrength), - entropyEnc: options.entropy && options.entropyEnc || 'utf8', - nonce: this.n.toArray() - }); - - // Key generation for curve25519 is simpler - if (this.curve.type === 'mont') { - var priv = new BN(drbg.generate(32)); - return this.keyFromPrivate(priv); - } - - var bytes = this.n.byteLength(); - var ns2 = this.n.sub(new BN(2)); - do { - var priv = new BN(drbg.generate(bytes)); - if (priv.cmp(ns2) > 0) - continue; - - priv.iaddn(1); - return this.keyFromPrivate(priv); - } while (true); -}; - -EC.prototype._truncateToN = function truncateToN(msg, truncOnly) { - var delta = msg.byteLength() * 8 - this.n.bitLength(); - if (delta > 0) - msg = msg.ushrn(delta); - if (!truncOnly && msg.cmp(this.n) >= 0) - return msg.sub(this.n); - else - return msg; -}; - -EC.prototype.sign = function sign(msg, key, enc, options) { - if (typeof enc === 'object') { - options = enc; - enc = null; - } - if (!options) - options = {}; - - key = this.keyFromPrivate(key, enc); - msg = this._truncateToN(new BN(msg, 16)); - - // Zero-extend key to provide enough entropy - var bytes = this.n.byteLength(); - var bkey = key.getPrivate().toArray('be', bytes); - - // Zero-extend nonce to have the same byte size as N - var nonce = msg.toArray('be', bytes); - - // Instantiate Hmac_DRBG - var drbg = new HmacDRBG({ - hash: this.hash, - entropy: bkey, - nonce: nonce, - pers: options.pers, - persEnc: options.persEnc || 'utf8' - }); - - // Number of bytes to generate - var ns1 = this.n.sub(new BN(1)); - - for (var iter = 0; true; iter++) { - var k = options.k ? - options.k(iter) : - new BN(drbg.generate(this.n.byteLength())); - k = this._truncateToN(k, true); - if (k.cmpn(1) <= 0 || k.cmp(ns1) >= 0) - continue; - - var kp = this.g.mul(k); - if (kp.isInfinity()) - continue; - - var kpX = kp.getX(); - var r = kpX.umod(this.n); - if (r.cmpn(0) === 0) - continue; - - var s = k.invm(this.n).mul(r.mul(key.getPrivate()).iadd(msg)); - s = s.umod(this.n); - if (s.cmpn(0) === 0) - continue; - - var recoveryParam = (kp.getY().isOdd() ? 1 : 0) | - (kpX.cmp(r) !== 0 ? 2 : 0); - - // Use complement of `s`, if it is > `n / 2` - if (options.canonical && s.cmp(this.nh) > 0) { - s = this.n.sub(s); - recoveryParam ^= 1; - } - - return new Signature({ r: r, s: s, recoveryParam: recoveryParam }); - } -}; - -EC.prototype.verify = function verify(msg, signature, key, enc) { - msg = this._truncateToN(new BN(msg, 16)); - key = this.keyFromPublic(key, enc); - signature = new Signature(signature, 'hex'); - - // Perform primitive values validation - var r = signature.r; - var s = signature.s; - if (r.cmpn(1) < 0 || r.cmp(this.n) >= 0) - return false; - if (s.cmpn(1) < 0 || s.cmp(this.n) >= 0) - return false; - - // Validate signature - var sinv = s.invm(this.n); - var u1 = sinv.mul(msg).umod(this.n); - var u2 = sinv.mul(r).umod(this.n); - - if (!this.curve._maxwellTrick) { - var p = this.g.mulAdd(u1, key.getPublic(), u2); - if (p.isInfinity()) - return false; - - return p.getX().umod(this.n).cmp(r) === 0; - } - - // NOTE: Greg Maxwell's trick, inspired by: - // https://git.io/vad3K - - var p = this.g.jmulAdd(u1, key.getPublic(), u2); - if (p.isInfinity()) - return false; - - // Compare `p.x` of Jacobian point with `r`, - // this will do `p.x == r * p.z^2` instead of multiplying `p.x` by the - // inverse of `p.z^2` - return p.eqXToP(r); -}; - -EC.prototype.recoverPubKey = function(msg, signature, j, enc) { - assert((3 & j) === j, 'The recovery param is more than two bits'); - signature = new Signature(signature, enc); - - var n = this.n; - var e = new BN(msg); - var r = signature.r; - var s = signature.s; - - // A set LSB signifies that the y-coordinate is odd - var isYOdd = j & 1; - var isSecondKey = j >> 1; - if (r.cmp(this.curve.p.umod(this.curve.n)) >= 0 && isSecondKey) - throw new Error('Unable to find sencond key candinate'); - - // 1.1. Let x = r + jn. - if (isSecondKey) - r = this.curve.pointFromX(r.add(this.curve.n), isYOdd); - else - r = this.curve.pointFromX(r, isYOdd); - - var rInv = signature.r.invm(n); - var s1 = n.sub(e).mul(rInv).umod(n); - var s2 = s.mul(rInv).umod(n); - - // 1.6.1 Compute Q = r^-1 (sR - eG) - // Q = r^-1 (sR + -eG) - return this.g.mulAdd(s1, r, s2); -}; - -EC.prototype.getKeyRecoveryParam = function(e, signature, Q, enc) { - signature = new Signature(signature, enc); - if (signature.recoveryParam !== null) - return signature.recoveryParam; - - for (var i = 0; i < 4; i++) { - var Qprime; - try { - Qprime = this.recoverPubKey(e, signature, i); - } catch (e) { - continue; - } - - if (Qprime.eq(Q)) - return i; - } - throw new Error('Unable to find valid recovery factor'); -}; - -},{"../../elliptic":18,"./key":26,"./signature":27,"bn.js":16,"hmac-drbg":46}],26:[function(require,module,exports){ -'use strict'; - -var BN = require('bn.js'); -var elliptic = require('../../elliptic'); -var utils = elliptic.utils; -var assert = utils.assert; - -function KeyPair(ec, options) { - this.ec = ec; - this.priv = null; - this.pub = null; - - // KeyPair(ec, { priv: ..., pub: ... }) - if (options.priv) - this._importPrivate(options.priv, options.privEnc); - if (options.pub) - this._importPublic(options.pub, options.pubEnc); -} -module.exports = KeyPair; - -KeyPair.fromPublic = function fromPublic(ec, pub, enc) { - if (pub instanceof KeyPair) - return pub; - - return new KeyPair(ec, { - pub: pub, - pubEnc: enc - }); -}; - -KeyPair.fromPrivate = function fromPrivate(ec, priv, enc) { - if (priv instanceof KeyPair) - return priv; - - return new KeyPair(ec, { - priv: priv, - privEnc: enc - }); -}; - -// TODO: should not validate for X25519 -KeyPair.prototype.validate = function validate() { - var pub = this.getPublic(); - - if (pub.isInfinity()) - return { result: false, reason: 'Invalid public key' }; - if (!pub.validate()) - return { result: false, reason: 'Public key is not a point' }; - if (!pub.mul(this.ec.curve.n).isInfinity()) - return { result: false, reason: 'Public key * N != O' }; - - return { result: true, reason: null }; -}; - -KeyPair.prototype.getPublic = function getPublic(enc, compact) { - if (!this.pub) - this.pub = this.ec.g.mul(this.priv); - - if (!enc) - return this.pub; - - return this.pub.encode(enc, compact); -}; - -KeyPair.prototype.getPrivate = function getPrivate(enc) { - if (enc === 'hex') - return this.priv.toString(16, 2); - else - return this.priv; -}; - -KeyPair.prototype._importPrivate = function _importPrivate(key, enc) { - this.priv = new BN(key, enc || 16); - - // For Curve25519/Curve448 we have a specific procedure. - // TODO Curve448 - if (this.ec.curve.type === 'mont') { - var one = this.ec.curve.one; - var mask = one.ushln(255 - 3).sub(one).ushln(3); - this.priv = this.priv.or(one.ushln(255 - 1)); - this.priv = this.priv.and(mask); - } else - // Ensure that the priv won't be bigger than n, otherwise we may fail - // in fixed multiplication method - this.priv = this.priv.umod(this.ec.curve.n); -}; - -KeyPair.prototype._importPublic = function _importPublic(key, enc) { - if (key.x || key.y) { - // Montgomery points only have an `x` coordinate. - // Weierstrass/Edwards points on the other hand have both `x` and - // `y` coordinates. - if (this.ec.curve.type === 'mont') { - assert(key.x, 'Need x coordinate'); - } else if (this.ec.curve.type === 'short' || - this.ec.curve.type === 'edwards') { - assert(key.x && key.y, 'Need both x and y coordinate'); - } - this.pub = this.ec.curve.point(key.x, key.y); - return; - } - this.pub = this.ec.curve.decodePoint(key, enc); -}; - -// ECDH -KeyPair.prototype.derive = function derive(pub) { - return pub.mul(this.priv).getX(); -}; - -// ECDSA -KeyPair.prototype.sign = function sign(msg, enc, options) { - return this.ec.sign(msg, this, enc, options); -}; - -KeyPair.prototype.verify = function verify(msg, signature) { - return this.ec.verify(msg, signature, this); -}; - -KeyPair.prototype.inspect = function inspect() { - return ''; -}; - -},{"../../elliptic":18,"bn.js":16}],27:[function(require,module,exports){ -'use strict'; - -var BN = require('bn.js'); - -var elliptic = require('../../elliptic'); -var utils = elliptic.utils; -var assert = utils.assert; - -function Signature(options, enc) { - if (options instanceof Signature) - return options; - - if (this._importDER(options, enc)) - return; - - assert(options.r && options.s, 'Signature without r or s'); - this.r = new BN(options.r, 16); - this.s = new BN(options.s, 16); - if (options.recoveryParam === undefined) - this.recoveryParam = null; - else - this.recoveryParam = options.recoveryParam; -} -module.exports = Signature; - -function Position() { - this.place = 0; -} - -function getLength(buf, p) { - var initial = buf[p.place++]; - if (!(initial & 0x80)) { - return initial; - } - var octetLen = initial & 0xf; - var val = 0; - for (var i = 0, off = p.place; i < octetLen; i++, off++) { - val <<= 8; - val |= buf[off]; - } - p.place = off; - return val; -} - -function rmPadding(buf) { - var i = 0; - var len = buf.length - 1; - while (!buf[i] && !(buf[i + 1] & 0x80) && i < len) { - i++; - } - if (i === 0) { - return buf; - } - return buf.slice(i); -} - -Signature.prototype._importDER = function _importDER(data, enc) { - data = utils.toArray(data, enc); - var p = new Position(); - if (data[p.place++] !== 0x30) { - return false; - } - var len = getLength(data, p); - if ((len + p.place) !== data.length) { - return false; - } - if (data[p.place++] !== 0x02) { - return false; - } - var rlen = getLength(data, p); - var r = data.slice(p.place, rlen + p.place); - p.place += rlen; - if (data[p.place++] !== 0x02) { - return false; - } - var slen = getLength(data, p); - if (data.length !== slen + p.place) { - return false; - } - var s = data.slice(p.place, slen + p.place); - if (r[0] === 0 && (r[1] & 0x80)) { - r = r.slice(1); - } - if (s[0] === 0 && (s[1] & 0x80)) { - s = s.slice(1); - } - - this.r = new BN(r); - this.s = new BN(s); - this.recoveryParam = null; - - return true; -}; - -function constructLength(arr, len) { - if (len < 0x80) { - arr.push(len); - return; - } - var octets = 1 + (Math.log(len) / Math.LN2 >>> 3); - arr.push(octets | 0x80); - while (--octets) { - arr.push((len >>> (octets << 3)) & 0xff); - } - arr.push(len); -} - -Signature.prototype.toDER = function toDER(enc) { - var r = this.r.toArray(); - var s = this.s.toArray(); - - // Pad values - if (r[0] & 0x80) - r = [ 0 ].concat(r); - // Pad values - if (s[0] & 0x80) - s = [ 0 ].concat(s); - - r = rmPadding(r); - s = rmPadding(s); - - while (!s[0] && !(s[1] & 0x80)) { - s = s.slice(1); - } - var arr = [ 0x02 ]; - constructLength(arr, r.length); - arr = arr.concat(r); - arr.push(0x02); - constructLength(arr, s.length); - var backHalf = arr.concat(s); - var res = [ 0x30 ]; - constructLength(res, backHalf.length); - res = res.concat(backHalf); - return utils.encode(res, enc); -}; - -},{"../../elliptic":18,"bn.js":16}],28:[function(require,module,exports){ -'use strict'; - -var hash = require('hash.js'); -var HmacDRBG = require('hmac-drbg'); -var elliptic = require('../../elliptic'); -var utils = elliptic.utils; -var assert = utils.assert; -var parseBytes = utils.parseBytes; -var KeyPair = require('./key'); -var Signature = require('./signature'); - -function EDDSA(curve) { - assert(curve === 'ed25519', 'only tested with ed25519 so far'); - - if (!(this instanceof EDDSA)) - return new EDDSA(curve); - - var curve = elliptic.curves[curve].curve; - this.curve = curve; - this.g = curve.g; - this.g.precompute(curve.n.bitLength() + 1); - - this.pointClass = curve.point().constructor; - this.encodingLength = Math.ceil(curve.n.bitLength() / 8); - this.hash = hash.sha512; -} - -module.exports = EDDSA; - -/** -* @param {Array|String} message - message bytes -* @param {Array|String|KeyPair} secret - secret bytes or a keypair -* @returns {Signature} - signature -*/ -EDDSA.prototype.sign = function sign(message, secret) { - message = parseBytes(message); - var key = this.keyFromSecret(secret); - var r = this.hashInt(key.messagePrefix(), message); - var R = this.g.mul(r); - var Rencoded = this.encodePoint(R); - var s_ = this.hashInt(Rencoded, key.pubBytes(), message) - .mul(key.priv()); - var S = r.add(s_).umod(this.curve.n); - return this.makeSignature({ R: R, S: S, Rencoded: Rencoded }); -}; - -/** -* @param {Array} message - message bytes -* @param {Array|String|Signature} sig - sig bytes -* @param {Array|String|Point|KeyPair} pub - public key -* @returns {Boolean} - true if public key matches sig of message -*/ -EDDSA.prototype.verify = function verify(message, sig, pub) { - message = parseBytes(message); - sig = this.makeSignature(sig); - var key = this.keyFromPublic(pub); - var h = this.hashInt(sig.Rencoded(), key.pubBytes(), message); - var SG = this.g.mul(sig.S()); - var RplusAh = sig.R().add(key.pub().mul(h)); - return RplusAh.eq(SG); -}; - -EDDSA.prototype.hashInt = function hashInt() { - var hash = this.hash(); - for (var i = 0; i < arguments.length; i++) - hash.update(arguments[i]); - return utils.intFromLE(hash.digest()).umod(this.curve.n); -}; - -EDDSA.prototype.keyPair = function keyPair(options) { - return new KeyPair(this, options); -}; - -EDDSA.prototype.keyFromPublic = function keyFromPublic(pub) { - return KeyPair.fromPublic(this, pub); -}; - -EDDSA.prototype.keyFromSecret = function keyFromSecret(secret) { - return KeyPair.fromSecret(this, secret); -}; - -EDDSA.prototype.genKeyPair = function genKeyPair(options) { - if (!options) - options = {}; - - // Instantiate Hmac_DRBG - var drbg = new HmacDRBG({ - hash: this.hash, - pers: options.pers, - persEnc: options.persEnc || 'utf8', - entropy: options.entropy || elliptic.rand(this.hash.hmacStrength), - entropyEnc: options.entropy && options.entropyEnc || 'utf8', - nonce: this.curve.n.toArray() - }); - - return this.keyFromSecret(drbg.generate(32)); -}; - -EDDSA.prototype.makeSignature = function makeSignature(sig) { - if (sig instanceof Signature) - return sig; - return new Signature(this, sig); -}; - -/** -* * https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03#section-5.2 -* -* EDDSA defines methods for encoding and decoding points and integers. These are -* helper convenience methods, that pass along to utility functions implied -* parameters. -* -*/ -EDDSA.prototype.encodePoint = function encodePoint(point) { - var enc = point.getY().toArray('le', this.encodingLength); - enc[this.encodingLength - 1] |= point.getX().isOdd() ? 0x80 : 0; - return enc; -}; - -EDDSA.prototype.decodePoint = function decodePoint(bytes) { - bytes = utils.parseBytes(bytes); - - var lastIx = bytes.length - 1; - var normed = bytes.slice(0, lastIx).concat(bytes[lastIx] & ~0x80); - var xIsOdd = (bytes[lastIx] & 0x80) !== 0; - - var y = utils.intFromLE(normed); - return this.curve.pointFromY(y, xIsOdd); -}; - -EDDSA.prototype.encodeInt = function encodeInt(num) { - return num.toArray('le', this.encodingLength); -}; - -EDDSA.prototype.decodeInt = function decodeInt(bytes) { - return utils.intFromLE(bytes); -}; - -EDDSA.prototype.isPoint = function isPoint(val) { - return val instanceof this.pointClass; -}; - -},{"../../elliptic":18,"./key":29,"./signature":30,"hash.js":34,"hmac-drbg":46}],29:[function(require,module,exports){ -'use strict'; - -var elliptic = require('../../elliptic'); -var utils = elliptic.utils; -var assert = utils.assert; -var parseBytes = utils.parseBytes; -var cachedProperty = utils.cachedProperty; - -/** -* @param {EDDSA} eddsa - instance -* @param {Object} params - public/private key parameters -* -* @param {Array} [params.secret] - secret seed bytes -* @param {Point} [params.pub] - public key point (aka `A` in eddsa terms) -* @param {Array} [params.pub] - public key point encoded as bytes -* -*/ -function KeyPair(eddsa, params) { - this.eddsa = eddsa; - if (params.hasOwnProperty('secret')) - this._secret = parseBytes(params.secret); - if (eddsa.isPoint(params.pub)) - this._pub = params.pub; - else { - this._pubBytes = parseBytes(params.pub); - if (this._pubBytes && this._pubBytes.length === 33 && - this._pubBytes[0] === 0x40) - this._pubBytes = this._pubBytes.slice(1, 33); - if (this._pubBytes && this._pubBytes.length !== 32) - throw new Error('Unknown point compression format'); - } -} - -KeyPair.fromPublic = function fromPublic(eddsa, pub) { - if (pub instanceof KeyPair) - return pub; - return new KeyPair(eddsa, { pub: pub }); -}; - -KeyPair.fromSecret = function fromSecret(eddsa, secret) { - if (secret instanceof KeyPair) - return secret; - return new KeyPair(eddsa, { secret: secret }); -}; - -KeyPair.prototype.secret = function secret() { - return this._secret; -}; - -cachedProperty(KeyPair, 'pubBytes', function pubBytes() { - return this.eddsa.encodePoint(this.pub()); -}); - -cachedProperty(KeyPair, 'pub', function pub() { - if (this._pubBytes) - return this.eddsa.decodePoint(this._pubBytes); - return this.eddsa.g.mul(this.priv()); -}); - -cachedProperty(KeyPair, 'privBytes', function privBytes() { - var eddsa = this.eddsa; - var hash = this.hash(); - var lastIx = eddsa.encodingLength - 1; - - // https://tools.ietf.org/html/rfc8032#section-5.1.5 - var a = hash.slice(0, eddsa.encodingLength); - a[0] &= 248; - a[lastIx] &= 127; - a[lastIx] |= 64; - - return a; -}); - -cachedProperty(KeyPair, 'priv', function priv() { - return this.eddsa.decodeInt(this.privBytes()); -}); - -cachedProperty(KeyPair, 'hash', function hash() { - return this.eddsa.hash().update(this.secret()).digest(); -}); - -cachedProperty(KeyPair, 'messagePrefix', function messagePrefix() { - return this.hash().slice(this.eddsa.encodingLength); -}); - -KeyPair.prototype.sign = function sign(message) { - assert(this._secret, 'KeyPair can only verify'); - return this.eddsa.sign(message, this); -}; - -KeyPair.prototype.verify = function verify(message, sig) { - return this.eddsa.verify(message, sig, this); -}; - -KeyPair.prototype.getSecret = function getSecret(enc) { - assert(this._secret, 'KeyPair is public only'); - return utils.encode(this.secret(), enc); -}; - -KeyPair.prototype.getPublic = function getPublic(enc, compact) { - return utils.encode((compact ? [ 0x40 ] : []).concat(this.pubBytes()), enc); -}; - -module.exports = KeyPair; - -},{"../../elliptic":18}],30:[function(require,module,exports){ -'use strict'; - -var BN = require('bn.js'); -var elliptic = require('../../elliptic'); -var utils = elliptic.utils; -var assert = utils.assert; -var cachedProperty = utils.cachedProperty; -var parseBytes = utils.parseBytes; - -/** -* @param {EDDSA} eddsa - eddsa instance -* @param {Array|Object} sig - -* @param {Array|Point} [sig.R] - R point as Point or bytes -* @param {Array|bn} [sig.S] - S scalar as bn or bytes -* @param {Array} [sig.Rencoded] - R point encoded -* @param {Array} [sig.Sencoded] - S scalar encoded -*/ -function Signature(eddsa, sig) { - this.eddsa = eddsa; - - if (typeof sig !== 'object') - sig = parseBytes(sig); - - if (Array.isArray(sig)) { - sig = { - R: sig.slice(0, eddsa.encodingLength), - S: sig.slice(eddsa.encodingLength) - }; - } - - assert(sig.R && sig.S, 'Signature without R or S'); - - if (eddsa.isPoint(sig.R)) - this._R = sig.R; - if (sig.S instanceof BN) - this._S = sig.S; - - this._Rencoded = Array.isArray(sig.R) ? sig.R : sig.Rencoded; - this._Sencoded = Array.isArray(sig.S) ? sig.S : sig.Sencoded; -} - -cachedProperty(Signature, 'S', function S() { - return this.eddsa.decodeInt(this.Sencoded()); -}); - -cachedProperty(Signature, 'R', function R() { - return this.eddsa.decodePoint(this.Rencoded()); -}); - -cachedProperty(Signature, 'Rencoded', function Rencoded() { - return this.eddsa.encodePoint(this.R()); -}); - -cachedProperty(Signature, 'Sencoded', function Sencoded() { - return this.eddsa.encodeInt(this.S()); -}); - -Signature.prototype.toBytes = function toBytes() { - return this.Rencoded().concat(this.Sencoded()); -}; - -Signature.prototype.toHex = function toHex() { - return utils.encode(this.toBytes(), 'hex').toUpperCase(); -}; - -module.exports = Signature; - -},{"../../elliptic":18,"bn.js":16}],31:[function(require,module,exports){ -module.exports = { - doubles: { - step: 4, - points: [ - [ - 'e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a', - 'f7e3507399e595929db99f34f57937101296891e44d23f0be1f32cce69616821' - ], - [ - '8282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508', - '11f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf' - ], - [ - '175e159f728b865a72f99cc6c6fc846de0b93833fd2222ed73fce5b551e5b739', - 'd3506e0d9e3c79eba4ef97a51ff71f5eacb5955add24345c6efa6ffee9fed695' - ], - [ - '363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640', - '4e273adfc732221953b445397f3363145b9a89008199ecb62003c7f3bee9de9' - ], - [ - '8b4b5f165df3c2be8c6244b5b745638843e4a781a15bcd1b69f79a55dffdf80c', - '4aad0a6f68d308b4b3fbd7813ab0da04f9e336546162ee56b3eff0c65fd4fd36' - ], - [ - '723cbaa6e5db996d6bf771c00bd548c7b700dbffa6c0e77bcb6115925232fcda', - '96e867b5595cc498a921137488824d6e2660a0653779494801dc069d9eb39f5f' - ], - [ - 'eebfa4d493bebf98ba5feec812c2d3b50947961237a919839a533eca0e7dd7fa', - '5d9a8ca3970ef0f269ee7edaf178089d9ae4cdc3a711f712ddfd4fdae1de8999' - ], - [ - '100f44da696e71672791d0a09b7bde459f1215a29b3c03bfefd7835b39a48db0', - 'cdd9e13192a00b772ec8f3300c090666b7ff4a18ff5195ac0fbd5cd62bc65a09' - ], - [ - 'e1031be262c7ed1b1dc9227a4a04c017a77f8d4464f3b3852c8acde6e534fd2d', - '9d7061928940405e6bb6a4176597535af292dd419e1ced79a44f18f29456a00d' - ], - [ - 'feea6cae46d55b530ac2839f143bd7ec5cf8b266a41d6af52d5e688d9094696d', - 'e57c6b6c97dce1bab06e4e12bf3ecd5c981c8957cc41442d3155debf18090088' - ], - [ - 'da67a91d91049cdcb367be4be6ffca3cfeed657d808583de33fa978bc1ec6cb1', - '9bacaa35481642bc41f463f7ec9780e5dec7adc508f740a17e9ea8e27a68be1d' - ], - [ - '53904faa0b334cdda6e000935ef22151ec08d0f7bb11069f57545ccc1a37b7c0', - '5bc087d0bc80106d88c9eccac20d3c1c13999981e14434699dcb096b022771c8' - ], - [ - '8e7bcd0bd35983a7719cca7764ca906779b53a043a9b8bcaeff959f43ad86047', - '10b7770b2a3da4b3940310420ca9514579e88e2e47fd68b3ea10047e8460372a' - ], - [ - '385eed34c1cdff21e6d0818689b81bde71a7f4f18397e6690a841e1599c43862', - '283bebc3e8ea23f56701de19e9ebf4576b304eec2086dc8cc0458fe5542e5453' - ], - [ - '6f9d9b803ecf191637c73a4413dfa180fddf84a5947fbc9c606ed86c3fac3a7', - '7c80c68e603059ba69b8e2a30e45c4d47ea4dd2f5c281002d86890603a842160' - ], - [ - '3322d401243c4e2582a2147c104d6ecbf774d163db0f5e5313b7e0e742d0e6bd', - '56e70797e9664ef5bfb019bc4ddaf9b72805f63ea2873af624f3a2e96c28b2a0' - ], - [ - '85672c7d2de0b7da2bd1770d89665868741b3f9af7643397721d74d28134ab83', - '7c481b9b5b43b2eb6374049bfa62c2e5e77f17fcc5298f44c8e3094f790313a6' - ], - [ - '948bf809b1988a46b06c9f1919413b10f9226c60f668832ffd959af60c82a0a', - '53a562856dcb6646dc6b74c5d1c3418c6d4dff08c97cd2bed4cb7f88d8c8e589' - ], - [ - '6260ce7f461801c34f067ce0f02873a8f1b0e44dfc69752accecd819f38fd8e8', - 'bc2da82b6fa5b571a7f09049776a1ef7ecd292238051c198c1a84e95b2b4ae17' - ], - [ - 'e5037de0afc1d8d43d8348414bbf4103043ec8f575bfdc432953cc8d2037fa2d', - '4571534baa94d3b5f9f98d09fb990bddbd5f5b03ec481f10e0e5dc841d755bda' - ], - [ - 'e06372b0f4a207adf5ea905e8f1771b4e7e8dbd1c6a6c5b725866a0ae4fce725', - '7a908974bce18cfe12a27bb2ad5a488cd7484a7787104870b27034f94eee31dd' - ], - [ - '213c7a715cd5d45358d0bbf9dc0ce02204b10bdde2a3f58540ad6908d0559754', - '4b6dad0b5ae462507013ad06245ba190bb4850f5f36a7eeddff2c27534b458f2' - ], - [ - '4e7c272a7af4b34e8dbb9352a5419a87e2838c70adc62cddf0cc3a3b08fbd53c', - '17749c766c9d0b18e16fd09f6def681b530b9614bff7dd33e0b3941817dcaae6' - ], - [ - 'fea74e3dbe778b1b10f238ad61686aa5c76e3db2be43057632427e2840fb27b6', - '6e0568db9b0b13297cf674deccb6af93126b596b973f7b77701d3db7f23cb96f' - ], - [ - '76e64113f677cf0e10a2570d599968d31544e179b760432952c02a4417bdde39', - 'c90ddf8dee4e95cf577066d70681f0d35e2a33d2b56d2032b4b1752d1901ac01' - ], - [ - 'c738c56b03b2abe1e8281baa743f8f9a8f7cc643df26cbee3ab150242bcbb891', - '893fb578951ad2537f718f2eacbfbbbb82314eef7880cfe917e735d9699a84c3' - ], - [ - 'd895626548b65b81e264c7637c972877d1d72e5f3a925014372e9f6588f6c14b', - 'febfaa38f2bc7eae728ec60818c340eb03428d632bb067e179363ed75d7d991f' - ], - [ - 'b8da94032a957518eb0f6433571e8761ceffc73693e84edd49150a564f676e03', - '2804dfa44805a1e4d7c99cc9762808b092cc584d95ff3b511488e4e74efdf6e7' - ], - [ - 'e80fea14441fb33a7d8adab9475d7fab2019effb5156a792f1a11778e3c0df5d', - 'eed1de7f638e00771e89768ca3ca94472d155e80af322ea9fcb4291b6ac9ec78' - ], - [ - 'a301697bdfcd704313ba48e51d567543f2a182031efd6915ddc07bbcc4e16070', - '7370f91cfb67e4f5081809fa25d40f9b1735dbf7c0a11a130c0d1a041e177ea1' - ], - [ - '90ad85b389d6b936463f9d0512678de208cc330b11307fffab7ac63e3fb04ed4', - 'e507a3620a38261affdcbd9427222b839aefabe1582894d991d4d48cb6ef150' - ], - [ - '8f68b9d2f63b5f339239c1ad981f162ee88c5678723ea3351b7b444c9ec4c0da', - '662a9f2dba063986de1d90c2b6be215dbbea2cfe95510bfdf23cbf79501fff82' - ], - [ - 'e4f3fb0176af85d65ff99ff9198c36091f48e86503681e3e6686fd5053231e11', - '1e63633ad0ef4f1c1661a6d0ea02b7286cc7e74ec951d1c9822c38576feb73bc' - ], - [ - '8c00fa9b18ebf331eb961537a45a4266c7034f2f0d4e1d0716fb6eae20eae29e', - 'efa47267fea521a1a9dc343a3736c974c2fadafa81e36c54e7d2a4c66702414b' - ], - [ - 'e7a26ce69dd4829f3e10cec0a9e98ed3143d084f308b92c0997fddfc60cb3e41', - '2a758e300fa7984b471b006a1aafbb18d0a6b2c0420e83e20e8a9421cf2cfd51' - ], - [ - 'b6459e0ee3662ec8d23540c223bcbdc571cbcb967d79424f3cf29eb3de6b80ef', - '67c876d06f3e06de1dadf16e5661db3c4b3ae6d48e35b2ff30bf0b61a71ba45' - ], - [ - 'd68a80c8280bb840793234aa118f06231d6f1fc67e73c5a5deda0f5b496943e8', - 'db8ba9fff4b586d00c4b1f9177b0e28b5b0e7b8f7845295a294c84266b133120' - ], - [ - '324aed7df65c804252dc0270907a30b09612aeb973449cea4095980fc28d3d5d', - '648a365774b61f2ff130c0c35aec1f4f19213b0c7e332843967224af96ab7c84' - ], - [ - '4df9c14919cde61f6d51dfdbe5fee5dceec4143ba8d1ca888e8bd373fd054c96', - '35ec51092d8728050974c23a1d85d4b5d506cdc288490192ebac06cad10d5d' - ], - [ - '9c3919a84a474870faed8a9c1cc66021523489054d7f0308cbfc99c8ac1f98cd', - 'ddb84f0f4a4ddd57584f044bf260e641905326f76c64c8e6be7e5e03d4fc599d' - ], - [ - '6057170b1dd12fdf8de05f281d8e06bb91e1493a8b91d4cc5a21382120a959e5', - '9a1af0b26a6a4807add9a2daf71df262465152bc3ee24c65e899be932385a2a8' - ], - [ - 'a576df8e23a08411421439a4518da31880cef0fba7d4df12b1a6973eecb94266', - '40a6bf20e76640b2c92b97afe58cd82c432e10a7f514d9f3ee8be11ae1b28ec8' - ], - [ - '7778a78c28dec3e30a05fe9629de8c38bb30d1f5cf9a3a208f763889be58ad71', - '34626d9ab5a5b22ff7098e12f2ff580087b38411ff24ac563b513fc1fd9f43ac' - ], - [ - '928955ee637a84463729fd30e7afd2ed5f96274e5ad7e5cb09eda9c06d903ac', - 'c25621003d3f42a827b78a13093a95eeac3d26efa8a8d83fc5180e935bcd091f' - ], - [ - '85d0fef3ec6db109399064f3a0e3b2855645b4a907ad354527aae75163d82751', - '1f03648413a38c0be29d496e582cf5663e8751e96877331582c237a24eb1f962' - ], - [ - 'ff2b0dce97eece97c1c9b6041798b85dfdfb6d8882da20308f5404824526087e', - '493d13fef524ba188af4c4dc54d07936c7b7ed6fb90e2ceb2c951e01f0c29907' - ], - [ - '827fbbe4b1e880ea9ed2b2e6301b212b57f1ee148cd6dd28780e5e2cf856e241', - 'c60f9c923c727b0b71bef2c67d1d12687ff7a63186903166d605b68baec293ec' - ], - [ - 'eaa649f21f51bdbae7be4ae34ce6e5217a58fdce7f47f9aa7f3b58fa2120e2b3', - 'be3279ed5bbbb03ac69a80f89879aa5a01a6b965f13f7e59d47a5305ba5ad93d' - ], - [ - 'e4a42d43c5cf169d9391df6decf42ee541b6d8f0c9a137401e23632dda34d24f', - '4d9f92e716d1c73526fc99ccfb8ad34ce886eedfa8d8e4f13a7f7131deba9414' - ], - [ - '1ec80fef360cbdd954160fadab352b6b92b53576a88fea4947173b9d4300bf19', - 'aeefe93756b5340d2f3a4958a7abbf5e0146e77f6295a07b671cdc1cc107cefd' - ], - [ - '146a778c04670c2f91b00af4680dfa8bce3490717d58ba889ddb5928366642be', - 'b318e0ec3354028add669827f9d4b2870aaa971d2f7e5ed1d0b297483d83efd0' - ], - [ - 'fa50c0f61d22e5f07e3acebb1aa07b128d0012209a28b9776d76a8793180eef9', - '6b84c6922397eba9b72cd2872281a68a5e683293a57a213b38cd8d7d3f4f2811' - ], - [ - 'da1d61d0ca721a11b1a5bf6b7d88e8421a288ab5d5bba5220e53d32b5f067ec2', - '8157f55a7c99306c79c0766161c91e2966a73899d279b48a655fba0f1ad836f1' - ], - [ - 'a8e282ff0c9706907215ff98e8fd416615311de0446f1e062a73b0610d064e13', - '7f97355b8db81c09abfb7f3c5b2515888b679a3e50dd6bd6cef7c73111f4cc0c' - ], - [ - '174a53b9c9a285872d39e56e6913cab15d59b1fa512508c022f382de8319497c', - 'ccc9dc37abfc9c1657b4155f2c47f9e6646b3a1d8cb9854383da13ac079afa73' - ], - [ - '959396981943785c3d3e57edf5018cdbe039e730e4918b3d884fdff09475b7ba', - '2e7e552888c331dd8ba0386a4b9cd6849c653f64c8709385e9b8abf87524f2fd' - ], - [ - 'd2a63a50ae401e56d645a1153b109a8fcca0a43d561fba2dbb51340c9d82b151', - 'e82d86fb6443fcb7565aee58b2948220a70f750af484ca52d4142174dcf89405' - ], - [ - '64587e2335471eb890ee7896d7cfdc866bacbdbd3839317b3436f9b45617e073', - 'd99fcdd5bf6902e2ae96dd6447c299a185b90a39133aeab358299e5e9faf6589' - ], - [ - '8481bde0e4e4d885b3a546d3e549de042f0aa6cea250e7fd358d6c86dd45e458', - '38ee7b8cba5404dd84a25bf39cecb2ca900a79c42b262e556d64b1b59779057e' - ], - [ - '13464a57a78102aa62b6979ae817f4637ffcfed3c4b1ce30bcd6303f6caf666b', - '69be159004614580ef7e433453ccb0ca48f300a81d0942e13f495a907f6ecc27' - ], - [ - 'bc4a9df5b713fe2e9aef430bcc1dc97a0cd9ccede2f28588cada3a0d2d83f366', - 'd3a81ca6e785c06383937adf4b798caa6e8a9fbfa547b16d758d666581f33c1' - ], - [ - '8c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa', - '40a30463a3305193378fedf31f7cc0eb7ae784f0451cb9459e71dc73cbef9482' - ], - [ - '8ea9666139527a8c1dd94ce4f071fd23c8b350c5a4bb33748c4ba111faccae0', - '620efabbc8ee2782e24e7c0cfb95c5d735b783be9cf0f8e955af34a30e62b945' - ], - [ - 'dd3625faef5ba06074669716bbd3788d89bdde815959968092f76cc4eb9a9787', - '7a188fa3520e30d461da2501045731ca941461982883395937f68d00c644a573' - ], - [ - 'f710d79d9eb962297e4f6232b40e8f7feb2bc63814614d692c12de752408221e', - 'ea98e67232d3b3295d3b535532115ccac8612c721851617526ae47a9c77bfc82' - ] - ] - }, - naf: { - wnd: 7, - points: [ - [ - 'f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9', - '388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672' - ], - [ - '2f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4', - 'd8ac222636e5e3d6d4dba9dda6c9c426f788271bab0d6840dca87d3aa6ac62d6' - ], - [ - '5cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc', - '6aebca40ba255960a3178d6d861a54dba813d0b813fde7b5a5082628087264da' - ], - [ - 'acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe', - 'cc338921b0a7d9fd64380971763b61e9add888a4375f8e0f05cc262ac64f9c37' - ], - [ - '774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb', - 'd984a032eb6b5e190243dd56d7b7b365372db1e2dff9d6a8301d74c9c953c61b' - ], - [ - 'f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8', - 'ab0902e8d880a89758212eb65cdaf473a1a06da521fa91f29b5cb52db03ed81' - ], - [ - 'd7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e', - '581e2872a86c72a683842ec228cc6defea40af2bd896d3a5c504dc9ff6a26b58' - ], - [ - 'defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34', - '4211ab0694635168e997b0ead2a93daeced1f4a04a95c0f6cfb199f69e56eb77' - ], - [ - '2b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c', - '85e89bc037945d93b343083b5a1c86131a01f60c50269763b570c854e5c09b7a' - ], - [ - '352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5', - '321eb4075348f534d59c18259dda3e1f4a1b3b2e71b1039c67bd3d8bcf81998c' - ], - [ - '2fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f', - '2de1068295dd865b64569335bd5dd80181d70ecfc882648423ba76b532b7d67' - ], - [ - '9248279b09b4d68dab21a9b066edda83263c3d84e09572e269ca0cd7f5453714', - '73016f7bf234aade5d1aa71bdea2b1ff3fc0de2a887912ffe54a32ce97cb3402' - ], - [ - 'daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729', - 'a69dce4a7d6c98e8d4a1aca87ef8d7003f83c230f3afa726ab40e52290be1c55' - ], - [ - 'c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db', - '2119a460ce326cdc76c45926c982fdac0e106e861edf61c5a039063f0e0e6482' - ], - [ - '6a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4', - 'e022cf42c2bd4a708b3f5126f16a24ad8b33ba48d0423b6efd5e6348100d8a82' - ], - [ - '1697ffa6fd9de627c077e3d2fe541084ce13300b0bec1146f95ae57f0d0bd6a5', - 'b9c398f186806f5d27561506e4557433a2cf15009e498ae7adee9d63d01b2396' - ], - [ - '605bdb019981718b986d0f07e834cb0d9deb8360ffb7f61df982345ef27a7479', - '2972d2de4f8d20681a78d93ec96fe23c26bfae84fb14db43b01e1e9056b8c49' - ], - [ - '62d14dab4150bf497402fdc45a215e10dcb01c354959b10cfe31c7e9d87ff33d', - '80fc06bd8cc5b01098088a1950eed0db01aa132967ab472235f5642483b25eaf' - ], - [ - '80c60ad0040f27dade5b4b06c408e56b2c50e9f56b9b8b425e555c2f86308b6f', - '1c38303f1cc5c30f26e66bad7fe72f70a65eed4cbe7024eb1aa01f56430bd57a' - ], - [ - '7a9375ad6167ad54aa74c6348cc54d344cc5dc9487d847049d5eabb0fa03c8fb', - 'd0e3fa9eca8726909559e0d79269046bdc59ea10c70ce2b02d499ec224dc7f7' - ], - [ - 'd528ecd9b696b54c907a9ed045447a79bb408ec39b68df504bb51f459bc3ffc9', - 'eecf41253136e5f99966f21881fd656ebc4345405c520dbc063465b521409933' - ], - [ - '49370a4b5f43412ea25f514e8ecdad05266115e4a7ecb1387231808f8b45963', - '758f3f41afd6ed428b3081b0512fd62a54c3f3afbb5b6764b653052a12949c9a' - ], - [ - '77f230936ee88cbbd73df930d64702ef881d811e0e1498e2f1c13eb1fc345d74', - '958ef42a7886b6400a08266e9ba1b37896c95330d97077cbbe8eb3c7671c60d6' - ], - [ - 'f2dac991cc4ce4b9ea44887e5c7c0bce58c80074ab9d4dbaeb28531b7739f530', - 'e0dedc9b3b2f8dad4da1f32dec2531df9eb5fbeb0598e4fd1a117dba703a3c37' - ], - [ - '463b3d9f662621fb1b4be8fbbe2520125a216cdfc9dae3debcba4850c690d45b', - '5ed430d78c296c3543114306dd8622d7c622e27c970a1de31cb377b01af7307e' - ], - [ - 'f16f804244e46e2a09232d4aff3b59976b98fac14328a2d1a32496b49998f247', - 'cedabd9b82203f7e13d206fcdf4e33d92a6c53c26e5cce26d6579962c4e31df6' - ], - [ - 'caf754272dc84563b0352b7a14311af55d245315ace27c65369e15f7151d41d1', - 'cb474660ef35f5f2a41b643fa5e460575f4fa9b7962232a5c32f908318a04476' - ], - [ - '2600ca4b282cb986f85d0f1709979d8b44a09c07cb86d7c124497bc86f082120', - '4119b88753c15bd6a693b03fcddbb45d5ac6be74ab5f0ef44b0be9475a7e4b40' - ], - [ - '7635ca72d7e8432c338ec53cd12220bc01c48685e24f7dc8c602a7746998e435', - '91b649609489d613d1d5e590f78e6d74ecfc061d57048bad9e76f302c5b9c61' - ], - [ - '754e3239f325570cdbbf4a87deee8a66b7f2b33479d468fbc1a50743bf56cc18', - '673fb86e5bda30fb3cd0ed304ea49a023ee33d0197a695d0c5d98093c536683' - ], - [ - 'e3e6bd1071a1e96aff57859c82d570f0330800661d1c952f9fe2694691d9b9e8', - '59c9e0bba394e76f40c0aa58379a3cb6a5a2283993e90c4167002af4920e37f5' - ], - [ - '186b483d056a033826ae73d88f732985c4ccb1f32ba35f4b4cc47fdcf04aa6eb', - '3b952d32c67cf77e2e17446e204180ab21fb8090895138b4a4a797f86e80888b' - ], - [ - 'df9d70a6b9876ce544c98561f4be4f725442e6d2b737d9c91a8321724ce0963f', - '55eb2dafd84d6ccd5f862b785dc39d4ab157222720ef9da217b8c45cf2ba2417' - ], - [ - '5edd5cc23c51e87a497ca815d5dce0f8ab52554f849ed8995de64c5f34ce7143', - 'efae9c8dbc14130661e8cec030c89ad0c13c66c0d17a2905cdc706ab7399a868' - ], - [ - '290798c2b6476830da12fe02287e9e777aa3fba1c355b17a722d362f84614fba', - 'e38da76dcd440621988d00bcf79af25d5b29c094db2a23146d003afd41943e7a' - ], - [ - 'af3c423a95d9f5b3054754efa150ac39cd29552fe360257362dfdecef4053b45', - 'f98a3fd831eb2b749a93b0e6f35cfb40c8cd5aa667a15581bc2feded498fd9c6' - ], - [ - '766dbb24d134e745cccaa28c99bf274906bb66b26dcf98df8d2fed50d884249a', - '744b1152eacbe5e38dcc887980da38b897584a65fa06cedd2c924f97cbac5996' - ], - [ - '59dbf46f8c94759ba21277c33784f41645f7b44f6c596a58ce92e666191abe3e', - 'c534ad44175fbc300f4ea6ce648309a042ce739a7919798cd85e216c4a307f6e' - ], - [ - 'f13ada95103c4537305e691e74e9a4a8dd647e711a95e73cb62dc6018cfd87b8', - 'e13817b44ee14de663bf4bc808341f326949e21a6a75c2570778419bdaf5733d' - ], - [ - '7754b4fa0e8aced06d4167a2c59cca4cda1869c06ebadfb6488550015a88522c', - '30e93e864e669d82224b967c3020b8fa8d1e4e350b6cbcc537a48b57841163a2' - ], - [ - '948dcadf5990e048aa3874d46abef9d701858f95de8041d2a6828c99e2262519', - 'e491a42537f6e597d5d28a3224b1bc25df9154efbd2ef1d2cbba2cae5347d57e' - ], - [ - '7962414450c76c1689c7b48f8202ec37fb224cf5ac0bfa1570328a8a3d7c77ab', - '100b610ec4ffb4760d5c1fc133ef6f6b12507a051f04ac5760afa5b29db83437' - ], - [ - '3514087834964b54b15b160644d915485a16977225b8847bb0dd085137ec47ca', - 'ef0afbb2056205448e1652c48e8127fc6039e77c15c2378b7e7d15a0de293311' - ], - [ - 'd3cc30ad6b483e4bc79ce2c9dd8bc54993e947eb8df787b442943d3f7b527eaf', - '8b378a22d827278d89c5e9be8f9508ae3c2ad46290358630afb34db04eede0a4' - ], - [ - '1624d84780732860ce1c78fcbfefe08b2b29823db913f6493975ba0ff4847610', - '68651cf9b6da903e0914448c6cd9d4ca896878f5282be4c8cc06e2a404078575' - ], - [ - '733ce80da955a8a26902c95633e62a985192474b5af207da6df7b4fd5fc61cd4', - 'f5435a2bd2badf7d485a4d8b8db9fcce3e1ef8e0201e4578c54673bc1dc5ea1d' - ], - [ - '15d9441254945064cf1a1c33bbd3b49f8966c5092171e699ef258dfab81c045c', - 'd56eb30b69463e7234f5137b73b84177434800bacebfc685fc37bbe9efe4070d' - ], - [ - 'a1d0fcf2ec9de675b612136e5ce70d271c21417c9d2b8aaaac138599d0717940', - 'edd77f50bcb5a3cab2e90737309667f2641462a54070f3d519212d39c197a629' - ], - [ - 'e22fbe15c0af8ccc5780c0735f84dbe9a790badee8245c06c7ca37331cb36980', - 'a855babad5cd60c88b430a69f53a1a7a38289154964799be43d06d77d31da06' - ], - [ - '311091dd9860e8e20ee13473c1155f5f69635e394704eaa74009452246cfa9b3', - '66db656f87d1f04fffd1f04788c06830871ec5a64feee685bd80f0b1286d8374' - ], - [ - '34c1fd04d301be89b31c0442d3e6ac24883928b45a9340781867d4232ec2dbdf', - '9414685e97b1b5954bd46f730174136d57f1ceeb487443dc5321857ba73abee' - ], - [ - 'f219ea5d6b54701c1c14de5b557eb42a8d13f3abbcd08affcc2a5e6b049b8d63', - '4cb95957e83d40b0f73af4544cccf6b1f4b08d3c07b27fb8d8c2962a400766d1' - ], - [ - 'd7b8740f74a8fbaab1f683db8f45de26543a5490bca627087236912469a0b448', - 'fa77968128d9c92ee1010f337ad4717eff15db5ed3c049b3411e0315eaa4593b' - ], - [ - '32d31c222f8f6f0ef86f7c98d3a3335ead5bcd32abdd94289fe4d3091aa824bf', - '5f3032f5892156e39ccd3d7915b9e1da2e6dac9e6f26e961118d14b8462e1661' - ], - [ - '7461f371914ab32671045a155d9831ea8793d77cd59592c4340f86cbc18347b5', - '8ec0ba238b96bec0cbdddcae0aa442542eee1ff50c986ea6b39847b3cc092ff6' - ], - [ - 'ee079adb1df1860074356a25aa38206a6d716b2c3e67453d287698bad7b2b2d6', - '8dc2412aafe3be5c4c5f37e0ecc5f9f6a446989af04c4e25ebaac479ec1c8c1e' - ], - [ - '16ec93e447ec83f0467b18302ee620f7e65de331874c9dc72bfd8616ba9da6b5', - '5e4631150e62fb40d0e8c2a7ca5804a39d58186a50e497139626778e25b0674d' - ], - [ - 'eaa5f980c245f6f038978290afa70b6bd8855897f98b6aa485b96065d537bd99', - 'f65f5d3e292c2e0819a528391c994624d784869d7e6ea67fb18041024edc07dc' - ], - [ - '78c9407544ac132692ee1910a02439958ae04877151342ea96c4b6b35a49f51', - 'f3e0319169eb9b85d5404795539a5e68fa1fbd583c064d2462b675f194a3ddb4' - ], - [ - '494f4be219a1a77016dcd838431aea0001cdc8ae7a6fc688726578d9702857a5', - '42242a969283a5f339ba7f075e36ba2af925ce30d767ed6e55f4b031880d562c' - ], - [ - 'a598a8030da6d86c6bc7f2f5144ea549d28211ea58faa70ebf4c1e665c1fe9b5', - '204b5d6f84822c307e4b4a7140737aec23fc63b65b35f86a10026dbd2d864e6b' - ], - [ - 'c41916365abb2b5d09192f5f2dbeafec208f020f12570a184dbadc3e58595997', - '4f14351d0087efa49d245b328984989d5caf9450f34bfc0ed16e96b58fa9913' - ], - [ - '841d6063a586fa475a724604da03bc5b92a2e0d2e0a36acfe4c73a5514742881', - '73867f59c0659e81904f9a1c7543698e62562d6744c169ce7a36de01a8d6154' - ], - [ - '5e95bb399a6971d376026947f89bde2f282b33810928be4ded112ac4d70e20d5', - '39f23f366809085beebfc71181313775a99c9aed7d8ba38b161384c746012865' - ], - [ - '36e4641a53948fd476c39f8a99fd974e5ec07564b5315d8bf99471bca0ef2f66', - 'd2424b1b1abe4eb8164227b085c9aa9456ea13493fd563e06fd51cf5694c78fc' - ], - [ - '336581ea7bfbbb290c191a2f507a41cf5643842170e914faeab27c2c579f726', - 'ead12168595fe1be99252129b6e56b3391f7ab1410cd1e0ef3dcdcabd2fda224' - ], - [ - '8ab89816dadfd6b6a1f2634fcf00ec8403781025ed6890c4849742706bd43ede', - '6fdcef09f2f6d0a044e654aef624136f503d459c3e89845858a47a9129cdd24e' - ], - [ - '1e33f1a746c9c5778133344d9299fcaa20b0938e8acff2544bb40284b8c5fb94', - '60660257dd11b3aa9c8ed618d24edff2306d320f1d03010e33a7d2057f3b3b6' - ], - [ - '85b7c1dcb3cec1b7ee7f30ded79dd20a0ed1f4cc18cbcfcfa410361fd8f08f31', - '3d98a9cdd026dd43f39048f25a8847f4fcafad1895d7a633c6fed3c35e999511' - ], - [ - '29df9fbd8d9e46509275f4b125d6d45d7fbe9a3b878a7af872a2800661ac5f51', - 'b4c4fe99c775a606e2d8862179139ffda61dc861c019e55cd2876eb2a27d84b' - ], - [ - 'a0b1cae06b0a847a3fea6e671aaf8adfdfe58ca2f768105c8082b2e449fce252', - 'ae434102edde0958ec4b19d917a6a28e6b72da1834aff0e650f049503a296cf2' - ], - [ - '4e8ceafb9b3e9a136dc7ff67e840295b499dfb3b2133e4ba113f2e4c0e121e5', - 'cf2174118c8b6d7a4b48f6d534ce5c79422c086a63460502b827ce62a326683c' - ], - [ - 'd24a44e047e19b6f5afb81c7ca2f69080a5076689a010919f42725c2b789a33b', - '6fb8d5591b466f8fc63db50f1c0f1c69013f996887b8244d2cdec417afea8fa3' - ], - [ - 'ea01606a7a6c9cdd249fdfcfacb99584001edd28abbab77b5104e98e8e3b35d4', - '322af4908c7312b0cfbfe369f7a7b3cdb7d4494bc2823700cfd652188a3ea98d' - ], - [ - 'af8addbf2b661c8a6c6328655eb96651252007d8c5ea31be4ad196de8ce2131f', - '6749e67c029b85f52a034eafd096836b2520818680e26ac8f3dfbcdb71749700' - ], - [ - 'e3ae1974566ca06cc516d47e0fb165a674a3dabcfca15e722f0e3450f45889', - '2aeabe7e4531510116217f07bf4d07300de97e4874f81f533420a72eeb0bd6a4' - ], - [ - '591ee355313d99721cf6993ffed1e3e301993ff3ed258802075ea8ced397e246', - 'b0ea558a113c30bea60fc4775460c7901ff0b053d25ca2bdeee98f1a4be5d196' - ], - [ - '11396d55fda54c49f19aa97318d8da61fa8584e47b084945077cf03255b52984', - '998c74a8cd45ac01289d5833a7beb4744ff536b01b257be4c5767bea93ea57a4' - ], - [ - '3c5d2a1ba39c5a1790000738c9e0c40b8dcdfd5468754b6405540157e017aa7a', - 'b2284279995a34e2f9d4de7396fc18b80f9b8b9fdd270f6661f79ca4c81bd257' - ], - [ - 'cc8704b8a60a0defa3a99a7299f2e9c3fbc395afb04ac078425ef8a1793cc030', - 'bdd46039feed17881d1e0862db347f8cf395b74fc4bcdc4e940b74e3ac1f1b13' - ], - [ - 'c533e4f7ea8555aacd9777ac5cad29b97dd4defccc53ee7ea204119b2889b197', - '6f0a256bc5efdf429a2fb6242f1a43a2d9b925bb4a4b3a26bb8e0f45eb596096' - ], - [ - 'c14f8f2ccb27d6f109f6d08d03cc96a69ba8c34eec07bbcf566d48e33da6593', - 'c359d6923bb398f7fd4473e16fe1c28475b740dd098075e6c0e8649113dc3a38' - ], - [ - 'a6cbc3046bc6a450bac24789fa17115a4c9739ed75f8f21ce441f72e0b90e6ef', - '21ae7f4680e889bb130619e2c0f95a360ceb573c70603139862afd617fa9b9f' - ], - [ - '347d6d9a02c48927ebfb86c1359b1caf130a3c0267d11ce6344b39f99d43cc38', - '60ea7f61a353524d1c987f6ecec92f086d565ab687870cb12689ff1e31c74448' - ], - [ - 'da6545d2181db8d983f7dcb375ef5866d47c67b1bf31c8cf855ef7437b72656a', - '49b96715ab6878a79e78f07ce5680c5d6673051b4935bd897fea824b77dc208a' - ], - [ - 'c40747cc9d012cb1a13b8148309c6de7ec25d6945d657146b9d5994b8feb1111', - '5ca560753be2a12fc6de6caf2cb489565db936156b9514e1bb5e83037e0fa2d4' - ], - [ - '4e42c8ec82c99798ccf3a610be870e78338c7f713348bd34c8203ef4037f3502', - '7571d74ee5e0fb92a7a8b33a07783341a5492144cc54bcc40a94473693606437' - ], - [ - '3775ab7089bc6af823aba2e1af70b236d251cadb0c86743287522a1b3b0dedea', - 'be52d107bcfa09d8bcb9736a828cfa7fac8db17bf7a76a2c42ad961409018cf7' - ], - [ - 'cee31cbf7e34ec379d94fb814d3d775ad954595d1314ba8846959e3e82f74e26', - '8fd64a14c06b589c26b947ae2bcf6bfa0149ef0be14ed4d80f448a01c43b1c6d' - ], - [ - 'b4f9eaea09b6917619f6ea6a4eb5464efddb58fd45b1ebefcdc1a01d08b47986', - '39e5c9925b5a54b07433a4f18c61726f8bb131c012ca542eb24a8ac07200682a' - ], - [ - 'd4263dfc3d2df923a0179a48966d30ce84e2515afc3dccc1b77907792ebcc60e', - '62dfaf07a0f78feb30e30d6295853ce189e127760ad6cf7fae164e122a208d54' - ], - [ - '48457524820fa65a4f8d35eb6930857c0032acc0a4a2de422233eeda897612c4', - '25a748ab367979d98733c38a1fa1c2e7dc6cc07db2d60a9ae7a76aaa49bd0f77' - ], - [ - 'dfeeef1881101f2cb11644f3a2afdfc2045e19919152923f367a1767c11cceda', - 'ecfb7056cf1de042f9420bab396793c0c390bde74b4bbdff16a83ae09a9a7517' - ], - [ - '6d7ef6b17543f8373c573f44e1f389835d89bcbc6062ced36c82df83b8fae859', - 'cd450ec335438986dfefa10c57fea9bcc521a0959b2d80bbf74b190dca712d10' - ], - [ - 'e75605d59102a5a2684500d3b991f2e3f3c88b93225547035af25af66e04541f', - 'f5c54754a8f71ee540b9b48728473e314f729ac5308b06938360990e2bfad125' - ], - [ - 'eb98660f4c4dfaa06a2be453d5020bc99a0c2e60abe388457dd43fefb1ed620c', - '6cb9a8876d9cb8520609af3add26cd20a0a7cd8a9411131ce85f44100099223e' - ], - [ - '13e87b027d8514d35939f2e6892b19922154596941888336dc3563e3b8dba942', - 'fef5a3c68059a6dec5d624114bf1e91aac2b9da568d6abeb2570d55646b8adf1' - ], - [ - 'ee163026e9fd6fe017c38f06a5be6fc125424b371ce2708e7bf4491691e5764a', - '1acb250f255dd61c43d94ccc670d0f58f49ae3fa15b96623e5430da0ad6c62b2' - ], - [ - 'b268f5ef9ad51e4d78de3a750c2dc89b1e626d43505867999932e5db33af3d80', - '5f310d4b3c99b9ebb19f77d41c1dee018cf0d34fd4191614003e945a1216e423' - ], - [ - 'ff07f3118a9df035e9fad85eb6c7bfe42b02f01ca99ceea3bf7ffdba93c4750d', - '438136d603e858a3a5c440c38eccbaddc1d2942114e2eddd4740d098ced1f0d8' - ], - [ - '8d8b9855c7c052a34146fd20ffb658bea4b9f69e0d825ebec16e8c3ce2b526a1', - 'cdb559eedc2d79f926baf44fb84ea4d44bcf50fee51d7ceb30e2e7f463036758' - ], - [ - '52db0b5384dfbf05bfa9d472d7ae26dfe4b851ceca91b1eba54263180da32b63', - 'c3b997d050ee5d423ebaf66a6db9f57b3180c902875679de924b69d84a7b375' - ], - [ - 'e62f9490d3d51da6395efd24e80919cc7d0f29c3f3fa48c6fff543becbd43352', - '6d89ad7ba4876b0b22c2ca280c682862f342c8591f1daf5170e07bfd9ccafa7d' - ], - [ - '7f30ea2476b399b4957509c88f77d0191afa2ff5cb7b14fd6d8e7d65aaab1193', - 'ca5ef7d4b231c94c3b15389a5f6311e9daff7bb67b103e9880ef4bff637acaec' - ], - [ - '5098ff1e1d9f14fb46a210fada6c903fef0fb7b4a1dd1d9ac60a0361800b7a00', - '9731141d81fc8f8084d37c6e7542006b3ee1b40d60dfe5362a5b132fd17ddc0' - ], - [ - '32b78c7de9ee512a72895be6b9cbefa6e2f3c4ccce445c96b9f2c81e2778ad58', - 'ee1849f513df71e32efc3896ee28260c73bb80547ae2275ba497237794c8753c' - ], - [ - 'e2cb74fddc8e9fbcd076eef2a7c72b0ce37d50f08269dfc074b581550547a4f7', - 'd3aa2ed71c9dd2247a62df062736eb0baddea9e36122d2be8641abcb005cc4a4' - ], - [ - '8438447566d4d7bedadc299496ab357426009a35f235cb141be0d99cd10ae3a8', - 'c4e1020916980a4da5d01ac5e6ad330734ef0d7906631c4f2390426b2edd791f' - ], - [ - '4162d488b89402039b584c6fc6c308870587d9c46f660b878ab65c82c711d67e', - '67163e903236289f776f22c25fb8a3afc1732f2b84b4e95dbda47ae5a0852649' - ], - [ - '3fad3fa84caf0f34f0f89bfd2dcf54fc175d767aec3e50684f3ba4a4bf5f683d', - 'cd1bc7cb6cc407bb2f0ca647c718a730cf71872e7d0d2a53fa20efcdfe61826' - ], - [ - '674f2600a3007a00568c1a7ce05d0816c1fb84bf1370798f1c69532faeb1a86b', - '299d21f9413f33b3edf43b257004580b70db57da0b182259e09eecc69e0d38a5' - ], - [ - 'd32f4da54ade74abb81b815ad1fb3b263d82d6c692714bcff87d29bd5ee9f08f', - 'f9429e738b8e53b968e99016c059707782e14f4535359d582fc416910b3eea87' - ], - [ - '30e4e670435385556e593657135845d36fbb6931f72b08cb1ed954f1e3ce3ff6', - '462f9bce619898638499350113bbc9b10a878d35da70740dc695a559eb88db7b' - ], - [ - 'be2062003c51cc3004682904330e4dee7f3dcd10b01e580bf1971b04d4cad297', - '62188bc49d61e5428573d48a74e1c655b1c61090905682a0d5558ed72dccb9bc' - ], - [ - '93144423ace3451ed29e0fb9ac2af211cb6e84a601df5993c419859fff5df04a', - '7c10dfb164c3425f5c71a3f9d7992038f1065224f72bb9d1d902a6d13037b47c' - ], - [ - 'b015f8044f5fcbdcf21ca26d6c34fb8197829205c7b7d2a7cb66418c157b112c', - 'ab8c1e086d04e813744a655b2df8d5f83b3cdc6faa3088c1d3aea1454e3a1d5f' - ], - [ - 'd5e9e1da649d97d89e4868117a465a3a4f8a18de57a140d36b3f2af341a21b52', - '4cb04437f391ed73111a13cc1d4dd0db1693465c2240480d8955e8592f27447a' - ], - [ - 'd3ae41047dd7ca065dbf8ed77b992439983005cd72e16d6f996a5316d36966bb', - 'bd1aeb21ad22ebb22a10f0303417c6d964f8cdd7df0aca614b10dc14d125ac46' - ], - [ - '463e2763d885f958fc66cdd22800f0a487197d0a82e377b49f80af87c897b065', - 'bfefacdb0e5d0fd7df3a311a94de062b26b80c61fbc97508b79992671ef7ca7f' - ], - [ - '7985fdfd127c0567c6f53ec1bb63ec3158e597c40bfe747c83cddfc910641917', - '603c12daf3d9862ef2b25fe1de289aed24ed291e0ec6708703a5bd567f32ed03' - ], - [ - '74a1ad6b5f76e39db2dd249410eac7f99e74c59cb83d2d0ed5ff1543da7703e9', - 'cc6157ef18c9c63cd6193d83631bbea0093e0968942e8c33d5737fd790e0db08' - ], - [ - '30682a50703375f602d416664ba19b7fc9bab42c72747463a71d0896b22f6da3', - '553e04f6b018b4fa6c8f39e7f311d3176290d0e0f19ca73f17714d9977a22ff8' - ], - [ - '9e2158f0d7c0d5f26c3791efefa79597654e7a2b2464f52b1ee6c1347769ef57', - '712fcdd1b9053f09003a3481fa7762e9ffd7c8ef35a38509e2fbf2629008373' - ], - [ - '176e26989a43c9cfeba4029c202538c28172e566e3c4fce7322857f3be327d66', - 'ed8cc9d04b29eb877d270b4878dc43c19aefd31f4eee09ee7b47834c1fa4b1c3' - ], - [ - '75d46efea3771e6e68abb89a13ad747ecf1892393dfc4f1b7004788c50374da8', - '9852390a99507679fd0b86fd2b39a868d7efc22151346e1a3ca4726586a6bed8' - ], - [ - '809a20c67d64900ffb698c4c825f6d5f2310fb0451c869345b7319f645605721', - '9e994980d9917e22b76b061927fa04143d096ccc54963e6a5ebfa5f3f8e286c1' - ], - [ - '1b38903a43f7f114ed4500b4eac7083fdefece1cf29c63528d563446f972c180', - '4036edc931a60ae889353f77fd53de4a2708b26b6f5da72ad3394119daf408f9' - ] - ] - } -}; - -},{}],32:[function(require,module,exports){ -'use strict'; - -var utils = exports; -var BN = require('bn.js'); -var minAssert = require('minimalistic-assert'); -var minUtils = require('minimalistic-crypto-utils'); - -utils.assert = minAssert; -utils.toArray = minUtils.toArray; -utils.zero2 = minUtils.zero2; -utils.toHex = minUtils.toHex; -utils.encode = minUtils.encode; - -// Represent num in a w-NAF form -function getNAF(num, w) { - var naf = []; - var ws = 1 << (w + 1); - var k = num.clone(); - while (k.cmpn(1) >= 0) { - var z; - if (k.isOdd()) { - var mod = k.andln(ws - 1); - if (mod > (ws >> 1) - 1) - z = (ws >> 1) - mod; - else - z = mod; - k.isubn(z); - } else { - z = 0; - } - naf.push(z); - - // Optimization, shift by word if possible - var shift = (k.cmpn(0) !== 0 && k.andln(ws - 1) === 0) ? (w + 1) : 1; - for (var i = 1; i < shift; i++) - naf.push(0); - k.iushrn(shift); - } - - return naf; -} -utils.getNAF = getNAF; - -// Represent k1, k2 in a Joint Sparse Form -function getJSF(k1, k2) { - var jsf = [ - [], - [] - ]; - - k1 = k1.clone(); - k2 = k2.clone(); - var d1 = 0; - var d2 = 0; - while (k1.cmpn(-d1) > 0 || k2.cmpn(-d2) > 0) { - - // First phase - var m14 = (k1.andln(3) + d1) & 3; - var m24 = (k2.andln(3) + d2) & 3; - if (m14 === 3) - m14 = -1; - if (m24 === 3) - m24 = -1; - var u1; - if ((m14 & 1) === 0) { - u1 = 0; - } else { - var m8 = (k1.andln(7) + d1) & 7; - if ((m8 === 3 || m8 === 5) && m24 === 2) - u1 = -m14; - else - u1 = m14; - } - jsf[0].push(u1); - - var u2; - if ((m24 & 1) === 0) { - u2 = 0; - } else { - var m8 = (k2.andln(7) + d2) & 7; - if ((m8 === 3 || m8 === 5) && m14 === 2) - u2 = -m24; - else - u2 = m24; - } - jsf[1].push(u2); - - // Second phase - if (2 * d1 === u1 + 1) - d1 = 1 - d1; - if (2 * d2 === u2 + 1) - d2 = 1 - d2; - k1.iushrn(1); - k2.iushrn(1); - } - - return jsf; -} -utils.getJSF = getJSF; - -function cachedProperty(obj, name, computer) { - var key = '_' + name; - obj.prototype[name] = function cachedProperty() { - return this[key] !== undefined ? this[key] : - this[key] = computer.call(this); - }; -} -utils.cachedProperty = cachedProperty; - -function parseBytes(bytes) { - return typeof bytes === 'string' ? utils.toArray(bytes, 'hex') : - bytes; -} -utils.parseBytes = parseBytes; - -function intFromLE(bytes) { - return new BN(bytes, 'hex', 'le'); -} -utils.intFromLE = intFromLE; - - -},{"bn.js":16,"minimalistic-assert":48,"minimalistic-crypto-utils":49}],33:[function(require,module,exports){ -"use strict"; - -// email-addresses.js - RFC 5322 email address parser -// v 3.0.3 -// -// http://tools.ietf.org/html/rfc5322 -// -// This library does not validate email addresses. -// emailAddresses attempts to parse addresses using the (fairly liberal) -// grammar specified in RFC 5322. -// -// email-addresses returns { -// ast: , -// addresses: [{ -// node: , -// name: , -// address: , -// local: , -// domain: -// }, ...] -// } -// -// emailAddresses.parseOneAddress and emailAddresses.parseAddressList -// work as you might expect. Try it out. -// -// Many thanks to Dominic Sayers and his documentation on the is_email function, -// http://code.google.com/p/isemail/ , which helped greatly in writing this parser. - -(function (global) { - "use strict"; - - function parse5322(opts) { - - // tokenizing functions - - function inStr() { - return pos < len; - } - function curTok() { - return parseString[pos]; - } - function getPos() { - return pos; - } - function setPos(i) { - pos = i; - } - function nextTok() { - pos += 1; - } - function initialize() { - pos = 0; - len = parseString.length; - } - - // parser helper functions - - function o(name, value) { - return { - name: name, - tokens: value || "", - semantic: value || "", - children: [] - }; - } - - function wrap(name, ast) { - var n; - if (ast === null) { - return null; - } - n = o(name); - n.tokens = ast.tokens; - n.semantic = ast.semantic; - n.children.push(ast); - return n; - } - - function add(parent, child) { - if (child !== null) { - parent.tokens += child.tokens; - parent.semantic += child.semantic; - } - parent.children.push(child); - return parent; - } - - function compareToken(fxnCompare) { - var tok; - if (!inStr()) { - return null; - } - tok = curTok(); - if (fxnCompare(tok)) { - nextTok(); - return o('token', tok); - } - return null; - } - - function literal(lit) { - return function literalFunc() { - return wrap('literal', compareToken(function (tok) { - return tok === lit; - })); - }; - } - - function and() { - var args = arguments; - return function andFunc() { - var i, s, result, start; - start = getPos(); - s = o('and'); - for (i = 0; i < args.length; i += 1) { - result = args[i](); - if (result === null) { - setPos(start); - return null; - } - add(s, result); - } - return s; - }; - } - - function or() { - var args = arguments; - return function orFunc() { - var i, result, start; - start = getPos(); - for (i = 0; i < args.length; i += 1) { - result = args[i](); - if (result !== null) { - return result; - } - setPos(start); - } - return null; - }; - } - - function opt(prod) { - return function optFunc() { - var result, start; - start = getPos(); - result = prod(); - if (result !== null) { - return result; - } else { - setPos(start); - return o('opt'); - } - }; - } - - function invis(prod) { - return function invisFunc() { - var result = prod(); - if (result !== null) { - result.semantic = ""; - } - return result; - }; - } - - function colwsp(prod) { - return function collapseSemanticWhitespace() { - var result = prod(); - if (result !== null && result.semantic.length > 0) { - result.semantic = " "; - } - return result; - }; - } - - function star(prod, minimum) { - return function starFunc() { - var s, result, count, start, min; - start = getPos(); - s = o('star'); - count = 0; - min = minimum === undefined ? 0 : minimum; - while ((result = prod()) !== null) { - count = count + 1; - add(s, result); - } - if (count >= min) { - return s; - } else { - setPos(start); - return null; - } - }; - } - - // One expects names to get normalized like this: - // " First Last " -> "First Last" - // "First Last" -> "First Last" - // "First Last" -> "First Last" - function collapseWhitespace(s) { - return s.replace(/([ \t]|\r\n)+/g, ' ').replace(/^\s*/, '').replace(/\s*$/, ''); - } - - // UTF-8 pseudo-production (RFC 6532) - // RFC 6532 extends RFC 5322 productions to include UTF-8 - // using the following productions: - // UTF8-non-ascii = UTF8-2 / UTF8-3 / UTF8-4 - // UTF8-2 = - // UTF8-3 = - // UTF8-4 = - // - // For reference, the extended RFC 5322 productions are: - // VCHAR =/ UTF8-non-ascii - // ctext =/ UTF8-non-ascii - // atext =/ UTF8-non-ascii - // qtext =/ UTF8-non-ascii - // dtext =/ UTF8-non-ascii - function isUTF8NonAscii(tok) { - // In JavaScript, we just deal directly with Unicode code points, - // so we aren't checking individual bytes for UTF-8 encoding. - // Just check that the character is non-ascii. - return tok.charCodeAt(0) >= 128; - } - - // common productions (RFC 5234) - // http://tools.ietf.org/html/rfc5234 - // B.1. Core Rules - - // CR = %x0D - // ; carriage return - function cr() { - return wrap('cr', literal('\r')()); - } - - // CRLF = CR LF - // ; Internet standard newline - function crlf() { - return wrap('crlf', and(cr, lf)()); - } - - // DQUOTE = %x22 - // ; " (Double Quote) - function dquote() { - return wrap('dquote', literal('"')()); - } - - // HTAB = %x09 - // ; horizontal tab - function htab() { - return wrap('htab', literal('\t')()); - } - - // LF = %x0A - // ; linefeed - function lf() { - return wrap('lf', literal('\n')()); - } - - // SP = %x20 - function sp() { - return wrap('sp', literal(' ')()); - } - - // VCHAR = %x21-7E - // ; visible (printing) characters - function vchar() { - return wrap('vchar', compareToken(function vcharFunc(tok) { - var code = tok.charCodeAt(0); - var accept = 0x21 <= code && code <= 0x7E; - if (opts.rfc6532) { - accept = accept || isUTF8NonAscii(tok); - } - return accept; - })); - } - - // WSP = SP / HTAB - // ; white space - function wsp() { - return wrap('wsp', or(sp, htab)()); - } - - // email productions (RFC 5322) - // http://tools.ietf.org/html/rfc5322 - // 3.2.1. Quoted characters - - // quoted-pair = ("\" (VCHAR / WSP)) / obs-qp - function quotedPair() { - var qp = wrap('quoted-pair', or(and(literal('\\'), or(vchar, wsp)), obsQP)()); - if (qp === null) { - return null; - } - // a quoted pair will be two characters, and the "\" character - // should be semantically "invisible" (RFC 5322 3.2.1) - qp.semantic = qp.semantic[1]; - return qp; - } - - // 3.2.2. Folding White Space and Comments - - // FWS = ([*WSP CRLF] 1*WSP) / obs-FWS - function fws() { - return wrap('fws', or(obsFws, and(opt(and(star(wsp), invis(crlf))), star(wsp, 1)))()); - } - - // ctext = %d33-39 / ; Printable US-ASCII - // %d42-91 / ; characters not including - // %d93-126 / ; "(", ")", or "\" - // obs-ctext - function ctext() { - return wrap('ctext', or(function ctextFunc1() { - return compareToken(function ctextFunc2(tok) { - var code = tok.charCodeAt(0); - var accept = 33 <= code && code <= 39 || 42 <= code && code <= 91 || 93 <= code && code <= 126; - if (opts.rfc6532) { - accept = accept || isUTF8NonAscii(tok); - } - return accept; - }); - }, obsCtext)()); - } - - // ccontent = ctext / quoted-pair / comment - function ccontent() { - return wrap('ccontent', or(ctext, quotedPair, comment)()); - } - - // comment = "(" *([FWS] ccontent) [FWS] ")" - function comment() { - return wrap('comment', and(literal('('), star(and(opt(fws), ccontent)), opt(fws), literal(')'))()); - } - - // CFWS = (1*([FWS] comment) [FWS]) / FWS - function cfws() { - return wrap('cfws', or(and(star(and(opt(fws), comment), 1), opt(fws)), fws)()); - } - - // 3.2.3. Atom - - //atext = ALPHA / DIGIT / ; Printable US-ASCII - // "!" / "#" / ; characters not including - // "$" / "%" / ; specials. Used for atoms. - // "&" / "'" / - // "*" / "+" / - // "-" / "/" / - // "=" / "?" / - // "^" / "_" / - // "`" / "{" / - // "|" / "}" / - // "~" - function atext() { - return wrap('atext', compareToken(function atextFunc(tok) { - var accept = 'a' <= tok && tok <= 'z' || 'A' <= tok && tok <= 'Z' || '0' <= tok && tok <= '9' || ['!', '#', '$', '%', '&', '\'', '*', '+', '-', '/', '=', '?', '^', '_', '`', '{', '|', '}', '~'].indexOf(tok) >= 0; - if (opts.rfc6532) { - accept = accept || isUTF8NonAscii(tok); - } - return accept; - })); - } - - // atom = [CFWS] 1*atext [CFWS] - function atom() { - return wrap('atom', and(colwsp(opt(cfws)), star(atext, 1), colwsp(opt(cfws)))()); - } - - // dot-atom-text = 1*atext *("." 1*atext) - function dotAtomText() { - var s, maybeText; - s = wrap('dot-atom-text', star(atext, 1)()); - if (s === null) { - return s; - } - maybeText = star(and(literal('.'), star(atext, 1)))(); - if (maybeText !== null) { - add(s, maybeText); - } - return s; - } - - // dot-atom = [CFWS] dot-atom-text [CFWS] - function dotAtom() { - return wrap('dot-atom', and(invis(opt(cfws)), dotAtomText, invis(opt(cfws)))()); - } - - // 3.2.4. Quoted Strings - - // qtext = %d33 / ; Printable US-ASCII - // %d35-91 / ; characters not including - // %d93-126 / ; "\" or the quote character - // obs-qtext - function qtext() { - return wrap('qtext', or(function qtextFunc1() { - return compareToken(function qtextFunc2(tok) { - var code = tok.charCodeAt(0); - var accept = 33 === code || 35 <= code && code <= 91 || 93 <= code && code <= 126; - if (opts.rfc6532) { - accept = accept || isUTF8NonAscii(tok); - } - return accept; - }); - }, obsQtext)()); - } - - // qcontent = qtext / quoted-pair - function qcontent() { - return wrap('qcontent', or(qtext, quotedPair)()); - } - - // quoted-string = [CFWS] - // DQUOTE *([FWS] qcontent) [FWS] DQUOTE - // [CFWS] - function quotedString() { - return wrap('quoted-string', and(invis(opt(cfws)), invis(dquote), star(and(opt(colwsp(fws)), qcontent)), opt(invis(fws)), invis(dquote), invis(opt(cfws)))()); - } - - // 3.2.5 Miscellaneous Tokens - - // word = atom / quoted-string - function word() { - return wrap('word', or(atom, quotedString)()); - } - - // phrase = 1*word / obs-phrase - function phrase() { - return wrap('phrase', or(obsPhrase, star(word, 1))()); - } - - // 3.4. Address Specification - // address = mailbox / group - function address() { - return wrap('address', or(mailbox, group)()); - } - - // mailbox = name-addr / addr-spec - function mailbox() { - return wrap('mailbox', or(nameAddr, addrSpec)()); - } - - // name-addr = [display-name] angle-addr - function nameAddr() { - return wrap('name-addr', and(opt(displayName), angleAddr)()); - } - - // angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / - // obs-angle-addr - function angleAddr() { - return wrap('angle-addr', or(and(invis(opt(cfws)), literal('<'), addrSpec, literal('>'), invis(opt(cfws))), obsAngleAddr)()); - } - - // group = display-name ":" [group-list] ";" [CFWS] - function group() { - return wrap('group', and(displayName, literal(':'), opt(groupList), literal(';'), invis(opt(cfws)))()); - } - - // display-name = phrase - function displayName() { - return wrap('display-name', function phraseFixedSemantic() { - var result = phrase(); - if (result !== null) { - result.semantic = collapseWhitespace(result.semantic); - } - return result; - }()); - } - - // mailbox-list = (mailbox *("," mailbox)) / obs-mbox-list - function mailboxList() { - return wrap('mailbox-list', or(and(mailbox, star(and(literal(','), mailbox))), obsMboxList)()); - } - - // address-list = (address *("," address)) / obs-addr-list - function addressList() { - return wrap('address-list', or(and(address, star(and(literal(','), address))), obsAddrList)()); - } - - // group-list = mailbox-list / CFWS / obs-group-list - function groupList() { - return wrap('group-list', or(mailboxList, invis(cfws), obsGroupList)()); - } - - // 3.4.1 Addr-Spec Specification - - // local-part = dot-atom / quoted-string / obs-local-part - function localPart() { - // note: quoted-string, dotAtom are proper subsets of obs-local-part - // so we really just have to look for obsLocalPart, if we don't care about the exact parse tree - return wrap('local-part', or(obsLocalPart, dotAtom, quotedString)()); - } - - // dtext = %d33-90 / ; Printable US-ASCII - // %d94-126 / ; characters not including - // obs-dtext ; "[", "]", or "\" - function dtext() { - return wrap('dtext', or(function dtextFunc1() { - return compareToken(function dtextFunc2(tok) { - var code = tok.charCodeAt(0); - var accept = 33 <= code && code <= 90 || 94 <= code && code <= 126; - if (opts.rfc6532) { - accept = accept || isUTF8NonAscii(tok); - } - return accept; - }); - }, obsDtext)()); - } - - // domain-literal = [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS] - function domainLiteral() { - return wrap('domain-literal', and(invis(opt(cfws)), literal('['), star(and(opt(fws), dtext)), opt(fws), literal(']'), invis(opt(cfws)))()); - } - - // domain = dot-atom / domain-literal / obs-domain - function domain() { - return wrap('domain', function domainCheckTLD() { - var result = or(obsDomain, dotAtom, domainLiteral)(); - if (opts.rejectTLD) { - if (result && result.semantic && result.semantic.indexOf('.') < 0) { - return null; - } - } - // strip all whitespace from domains - if (result) { - result.semantic = result.semantic.replace(/\s+/g, ''); - } - return result; - }()); - } - - // addr-spec = local-part "@" domain - function addrSpec() { - return wrap('addr-spec', and(localPart, literal('@'), domain)()); - } - - // 3.6.2 Originator Fields - // Below we only parse the field body, not the name of the field - // like "From:", "Sender:", or "Reply-To:". Other libraries that - // parse email headers can parse those and defer to these productions - // for the "RFC 5322" part. - - // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields - // from = "From:" (mailbox-list / address-list) CRLF - function fromSpec() { - return wrap('from', or(mailboxList, addressList)()); - } - - // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields - // sender = "Sender:" (mailbox / address) CRLF - function senderSpec() { - return wrap('sender', or(mailbox, address)()); - } - - // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields - // reply-to = "Reply-To:" address-list CRLF - function replyToSpec() { - return wrap('reply-to', addressList()); - } - - // 4.1. Miscellaneous Obsolete Tokens - - // obs-NO-WS-CTL = %d1-8 / ; US-ASCII control - // %d11 / ; characters that do not - // %d12 / ; include the carriage - // %d14-31 / ; return, line feed, and - // %d127 ; white space characters - function obsNoWsCtl() { - return opts.strict ? null : wrap('obs-NO-WS-CTL', compareToken(function (tok) { - var code = tok.charCodeAt(0); - return 1 <= code && code <= 8 || 11 === code || 12 === code || 14 <= code && code <= 31 || 127 === code; - })); - } - - // obs-ctext = obs-NO-WS-CTL - function obsCtext() { - return opts.strict ? null : wrap('obs-ctext', obsNoWsCtl()); - } - - // obs-qtext = obs-NO-WS-CTL - function obsQtext() { - return opts.strict ? null : wrap('obs-qtext', obsNoWsCtl()); - } - - // obs-qp = "\" (%d0 / obs-NO-WS-CTL / LF / CR) - function obsQP() { - return opts.strict ? null : wrap('obs-qp', and(literal('\\'), or(literal('\0'), obsNoWsCtl, lf, cr))()); - } - - // obs-phrase = word *(word / "." / CFWS) - function obsPhrase() { - return opts.strict ? null : wrap('obs-phrase', and(word, star(or(word, literal('.'), literal('@'), colwsp(cfws))))()); - } - - // 4.2. Obsolete Folding White Space - - // NOTE: read the errata http://www.rfc-editor.org/errata_search.php?rfc=5322&eid=1908 - // obs-FWS = 1*([CRLF] WSP) - function obsFws() { - return opts.strict ? null : wrap('obs-FWS', star(and(invis(opt(crlf)), wsp), 1)()); - } - - // 4.4. Obsolete Addressing - - // obs-angle-addr = [CFWS] "<" obs-route addr-spec ">" [CFWS] - function obsAngleAddr() { - return opts.strict ? null : wrap('obs-angle-addr', and(invis(opt(cfws)), literal('<'), obsRoute, addrSpec, literal('>'), invis(opt(cfws)))()); - } - - // obs-route = obs-domain-list ":" - function obsRoute() { - return opts.strict ? null : wrap('obs-route', and(obsDomainList, literal(':'))()); - } - - // obs-domain-list = *(CFWS / ",") "@" domain - // *("," [CFWS] ["@" domain]) - function obsDomainList() { - return opts.strict ? null : wrap('obs-domain-list', and(star(or(invis(cfws), literal(','))), literal('@'), domain, star(and(literal(','), invis(opt(cfws)), opt(and(literal('@'), domain)))))()); - } - - // obs-mbox-list = *([CFWS] ",") mailbox *("," [mailbox / CFWS]) - function obsMboxList() { - return opts.strict ? null : wrap('obs-mbox-list', and(star(and(invis(opt(cfws)), literal(','))), mailbox, star(and(literal(','), opt(and(mailbox, invis(cfws))))))()); - } - - // obs-addr-list = *([CFWS] ",") address *("," [address / CFWS]) - function obsAddrList() { - return opts.strict ? null : wrap('obs-addr-list', and(star(and(invis(opt(cfws)), literal(','))), address, star(and(literal(','), opt(and(address, invis(cfws))))))()); - } - - // obs-group-list = 1*([CFWS] ",") [CFWS] - function obsGroupList() { - return opts.strict ? null : wrap('obs-group-list', and(star(and(invis(opt(cfws)), literal(',')), 1), invis(opt(cfws)))()); - } - - // obs-local-part = word *("." word) - function obsLocalPart() { - return opts.strict ? null : wrap('obs-local-part', and(word, star(and(literal('.'), word)))()); - } - - // obs-domain = atom *("." atom) - function obsDomain() { - return opts.strict ? null : wrap('obs-domain', and(atom, star(and(literal('.'), atom)))()); - } - - // obs-dtext = obs-NO-WS-CTL / quoted-pair - function obsDtext() { - return opts.strict ? null : wrap('obs-dtext', or(obsNoWsCtl, quotedPair)()); - } - - ///////////////////////////////////////////////////// - - // ast analysis - - function findNode(name, root) { - var i, stack, node; - if (root === null || root === undefined) { - return null; - } - stack = [root]; - while (stack.length > 0) { - node = stack.pop(); - if (node.name === name) { - return node; - } - for (i = node.children.length - 1; i >= 0; i -= 1) { - stack.push(node.children[i]); - } - } - return null; - } - - function findAllNodes(name, root) { - var i, stack, node, result; - if (root === null || root === undefined) { - return null; - } - stack = [root]; - result = []; - while (stack.length > 0) { - node = stack.pop(); - if (node.name === name) { - result.push(node); - } - for (i = node.children.length - 1; i >= 0; i -= 1) { - stack.push(node.children[i]); - } - } - return result; - } - - function findAllNodesNoChildren(names, root) { - var i, stack, node, result, namesLookup; - if (root === null || root === undefined) { - return null; - } - stack = [root]; - result = []; - namesLookup = {}; - for (i = 0; i < names.length; i += 1) { - namesLookup[names[i]] = true; - } - - while (stack.length > 0) { - node = stack.pop(); - if (node.name in namesLookup) { - result.push(node); - // don't look at children (hence findAllNodesNoChildren) - } else { - for (i = node.children.length - 1; i >= 0; i -= 1) { - stack.push(node.children[i]); - } - } - } - return result; - } - - function giveResult(ast) { - var addresses, groupsAndMailboxes, i, groupOrMailbox, result; - if (ast === null) { - return null; - } - addresses = []; - - // An address is a 'group' (i.e. a list of mailboxes) or a 'mailbox'. - groupsAndMailboxes = findAllNodesNoChildren(['group', 'mailbox'], ast); - for (i = 0; i < groupsAndMailboxes.length; i += 1) { - groupOrMailbox = groupsAndMailboxes[i]; - if (groupOrMailbox.name === 'group') { - addresses.push(giveResultGroup(groupOrMailbox)); - } else if (groupOrMailbox.name === 'mailbox') { - addresses.push(giveResultMailbox(groupOrMailbox)); - } - } - - result = { - ast: ast, - addresses: addresses - }; - if (opts.simple) { - result = simplifyResult(result); - } - if (opts.oneResult) { - return oneResult(result); - } - if (opts.simple) { - return result && result.addresses; - } else { - return result; - } - } - - function giveResultGroup(group) { - var i; - var groupName = findNode('display-name', group); - var groupResultMailboxes = []; - var mailboxes = findAllNodesNoChildren(['mailbox'], group); - for (i = 0; i < mailboxes.length; i += 1) { - groupResultMailboxes.push(giveResultMailbox(mailboxes[i])); - } - return { - node: group, - parts: { - name: groupName - }, - type: group.name, // 'group' - name: grabSemantic(groupName), - addresses: groupResultMailboxes - }; - } - - function giveResultMailbox(mailbox) { - var name = findNode('display-name', mailbox); - var aspec = findNode('addr-spec', mailbox); - var comments = findAllNodesNoChildren(['comment'], mailbox); - - var local = findNode('local-part', aspec); - var domain = findNode('domain', aspec); - return { - node: mailbox, - parts: { - name: name, - address: aspec, - local: local, - domain: domain, - comments: comments - }, - type: mailbox.name, // 'mailbox' - name: grabSemantic(name), - address: grabSemantic(aspec), - local: grabSemantic(local), - domain: grabSemantic(domain), - comments: concatComments(comments), - groupName: grabSemantic(mailbox.groupName) - }; - } - - function grabSemantic(n) { - return n !== null && n !== undefined ? n.semantic : null; - } - - function simplifyResult(result) { - var i; - if (result && result.addresses) { - for (i = 0; i < result.addresses.length; i += 1) { - delete result.addresses[i].node; - } - } - return result; - } - - function concatComments(comments) { - let result = ''; - if (comments) { - for (let i = 0; i < comments.length; i += 1) { - result += grabSemantic(comments[i]); - } - } - return result; - } - - function oneResult(result) { - if (!result) { - return null; - } - if (!opts.partial && result.addresses.length > 1) { - return null; - } - return result.addresses && result.addresses[0]; - } - - ///////////////////////////////////////////////////// - - var parseString, pos, len, parsed, startProduction; - - opts = handleOpts(opts, {}); - if (opts === null) { - return null; - } - - parseString = opts.input; - - startProduction = { - 'address': address, - 'address-list': addressList, - 'angle-addr': angleAddr, - 'from': fromSpec, - 'group': group, - 'mailbox': mailbox, - 'mailbox-list': mailboxList, - 'reply-to': replyToSpec, - 'sender': senderSpec - }[opts.startAt] || addressList; - - if (!opts.strict) { - initialize(); - opts.strict = true; - parsed = startProduction(parseString); - if (opts.partial || !inStr()) { - return giveResult(parsed); - } - opts.strict = false; - } - - initialize(); - parsed = startProduction(parseString); - if (!opts.partial && inStr()) { - return null; - } - return giveResult(parsed); - } - - function parseOneAddressSimple(opts) { - return parse5322(handleOpts(opts, { - oneResult: true, - rfc6532: true, - simple: true, - startAt: 'address-list' - })); - } - - function parseAddressListSimple(opts) { - return parse5322(handleOpts(opts, { - rfc6532: true, - simple: true, - startAt: 'address-list' - })); - } - - function parseFromSimple(opts) { - return parse5322(handleOpts(opts, { - rfc6532: true, - simple: true, - startAt: 'from' - })); - } - - function parseSenderSimple(opts) { - return parse5322(handleOpts(opts, { - oneResult: true, - rfc6532: true, - simple: true, - startAt: 'sender' - })); - } - - function parseReplyToSimple(opts) { - return parse5322(handleOpts(opts, { - rfc6532: true, - simple: true, - startAt: 'reply-to' - })); - } - - function handleOpts(opts, defs) { - function isString(str) { - return Object.prototype.toString.call(str) === '[object String]'; - } - - function isObject(o) { - return o === Object(o); - } - - function isNullUndef(o) { - return o === null || o === undefined; - } - - var defaults, o; - - if (isString(opts)) { - opts = { input: opts }; - } else if (!isObject(opts)) { - return null; - } - - if (!isString(opts.input)) { - return null; - } - if (!defs) { - return null; - } - - defaults = { - oneResult: false, - partial: false, - rejectTLD: false, - rfc6532: false, - simple: false, - startAt: 'address-list', - strict: false - }; - - for (o in defaults) { - if (isNullUndef(opts[o])) { - opts[o] = !isNullUndef(defs[o]) ? defs[o] : defaults[o]; - } - } - return opts; - } - - parse5322.parseOneAddress = parseOneAddressSimple; - parse5322.parseAddressList = parseAddressListSimple; - parse5322.parseFrom = parseFromSimple; - parse5322.parseSender = parseSenderSimple; - parse5322.parseReplyTo = parseReplyToSimple; - - if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { - module.exports = parse5322; - } else { - global.emailAddresses = parse5322; - } -})(undefined); - -},{}],34:[function(require,module,exports){ -var hash = exports; - -hash.utils = require('./hash/utils'); -hash.common = require('./hash/common'); -hash.sha = require('./hash/sha'); -hash.ripemd = require('./hash/ripemd'); -hash.hmac = require('./hash/hmac'); - -// Proxy hash functions to the main object -hash.sha1 = hash.sha.sha1; -hash.sha256 = hash.sha.sha256; -hash.sha224 = hash.sha.sha224; -hash.sha384 = hash.sha.sha384; -hash.sha512 = hash.sha.sha512; -hash.ripemd160 = hash.ripemd.ripemd160; - -},{"./hash/common":35,"./hash/hmac":36,"./hash/ripemd":37,"./hash/sha":38,"./hash/utils":45}],35:[function(require,module,exports){ -'use strict'; - -var utils = require('./utils'); -var assert = require('minimalistic-assert'); - -function BlockHash() { - this.pending = null; - this.pendingTotal = 0; - this.blockSize = this.constructor.blockSize; - this.outSize = this.constructor.outSize; - this.hmacStrength = this.constructor.hmacStrength; - this.padLength = this.constructor.padLength / 8; - this.endian = 'big'; - - this._delta8 = this.blockSize / 8; - this._delta32 = this.blockSize / 32; -} -exports.BlockHash = BlockHash; - -BlockHash.prototype.update = function update(msg, enc) { - // Convert message to array, pad it, and join into 32bit blocks - msg = utils.toArray(msg, enc); - if (!this.pending) - this.pending = msg; - else - this.pending = this.pending.concat(msg); - this.pendingTotal += msg.length; - - // Enough data, try updating - if (this.pending.length >= this._delta8) { - msg = this.pending; - - // Process pending data in blocks - var r = msg.length % this._delta8; - this.pending = msg.slice(msg.length - r, msg.length); - if (this.pending.length === 0) - this.pending = null; - - msg = utils.join32(msg, 0, msg.length - r, this.endian); - for (var i = 0; i < msg.length; i += this._delta32) - this._update(msg, i, i + this._delta32); - } - - return this; -}; - -BlockHash.prototype.digest = function digest(enc) { - this.update(this._pad()); - assert(this.pending === null); - - return this._digest(enc); -}; - -BlockHash.prototype._pad = function pad() { - var len = this.pendingTotal; - var bytes = this._delta8; - var k = bytes - ((len + this.padLength) % bytes); - var res = new Array(k + this.padLength); - res[0] = 0x80; - for (var i = 1; i < k; i++) - res[i] = 0; - - // Append length - len <<= 3; - if (this.endian === 'big') { - for (var t = 8; t < this.padLength; t++) - res[i++] = 0; - - res[i++] = 0; - res[i++] = 0; - res[i++] = 0; - res[i++] = 0; - res[i++] = (len >>> 24) & 0xff; - res[i++] = (len >>> 16) & 0xff; - res[i++] = (len >>> 8) & 0xff; - res[i++] = len & 0xff; - } else { - res[i++] = len & 0xff; - res[i++] = (len >>> 8) & 0xff; - res[i++] = (len >>> 16) & 0xff; - res[i++] = (len >>> 24) & 0xff; - res[i++] = 0; - res[i++] = 0; - res[i++] = 0; - res[i++] = 0; - - for (t = 8; t < this.padLength; t++) - res[i++] = 0; - } - - return res; -}; - -},{"./utils":45,"minimalistic-assert":48}],36:[function(require,module,exports){ -'use strict'; - -var utils = require('./utils'); -var assert = require('minimalistic-assert'); - -function Hmac(hash, key, enc) { - if (!(this instanceof Hmac)) - return new Hmac(hash, key, enc); - this.Hash = hash; - this.blockSize = hash.blockSize / 8; - this.outSize = hash.outSize / 8; - this.inner = null; - this.outer = null; - - this._init(utils.toArray(key, enc)); -} -module.exports = Hmac; - -Hmac.prototype._init = function init(key) { - // Shorten key, if needed - if (key.length > this.blockSize) - key = new this.Hash().update(key).digest(); - assert(key.length <= this.blockSize); - - // Add padding to key - for (var i = key.length; i < this.blockSize; i++) - key.push(0); - - for (i = 0; i < key.length; i++) - key[i] ^= 0x36; - this.inner = new this.Hash().update(key); - - // 0x36 ^ 0x5c = 0x6a - for (i = 0; i < key.length; i++) - key[i] ^= 0x6a; - this.outer = new this.Hash().update(key); -}; - -Hmac.prototype.update = function update(msg, enc) { - this.inner.update(msg, enc); - return this; -}; - -Hmac.prototype.digest = function digest(enc) { - this.outer.update(this.inner.digest()); - return this.outer.digest(enc); -}; - -},{"./utils":45,"minimalistic-assert":48}],37:[function(require,module,exports){ -'use strict'; - -var utils = require('./utils'); -var common = require('./common'); - -var rotl32 = utils.rotl32; -var sum32 = utils.sum32; -var sum32_3 = utils.sum32_3; -var sum32_4 = utils.sum32_4; -var BlockHash = common.BlockHash; - -function RIPEMD160() { - if (!(this instanceof RIPEMD160)) - return new RIPEMD160(); - - BlockHash.call(this); - - this.h = [ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 ]; - this.endian = 'little'; -} -utils.inherits(RIPEMD160, BlockHash); -exports.ripemd160 = RIPEMD160; - -RIPEMD160.blockSize = 512; -RIPEMD160.outSize = 160; -RIPEMD160.hmacStrength = 192; -RIPEMD160.padLength = 64; - -RIPEMD160.prototype._update = function update(msg, start) { - var A = this.h[0]; - var B = this.h[1]; - var C = this.h[2]; - var D = this.h[3]; - var E = this.h[4]; - var Ah = A; - var Bh = B; - var Ch = C; - var Dh = D; - var Eh = E; - for (var j = 0; j < 80; j++) { - var T = sum32( - rotl32( - sum32_4(A, f(j, B, C, D), msg[r[j] + start], K(j)), - s[j]), - E); - A = E; - E = D; - D = rotl32(C, 10); - C = B; - B = T; - T = sum32( - rotl32( - sum32_4(Ah, f(79 - j, Bh, Ch, Dh), msg[rh[j] + start], Kh(j)), - sh[j]), - Eh); - Ah = Eh; - Eh = Dh; - Dh = rotl32(Ch, 10); - Ch = Bh; - Bh = T; - } - T = sum32_3(this.h[1], C, Dh); - this.h[1] = sum32_3(this.h[2], D, Eh); - this.h[2] = sum32_3(this.h[3], E, Ah); - this.h[3] = sum32_3(this.h[4], A, Bh); - this.h[4] = sum32_3(this.h[0], B, Ch); - this.h[0] = T; -}; - -RIPEMD160.prototype._digest = function digest(enc) { - if (enc === 'hex') - return utils.toHex32(this.h, 'little'); - else - return utils.split32(this.h, 'little'); -}; - -function f(j, x, y, z) { - if (j <= 15) - return x ^ y ^ z; - else if (j <= 31) - return (x & y) | ((~x) & z); - else if (j <= 47) - return (x | (~y)) ^ z; - else if (j <= 63) - return (x & z) | (y & (~z)); - else - return x ^ (y | (~z)); -} - -function K(j) { - if (j <= 15) - return 0x00000000; - else if (j <= 31) - return 0x5a827999; - else if (j <= 47) - return 0x6ed9eba1; - else if (j <= 63) - return 0x8f1bbcdc; - else - return 0xa953fd4e; -} - -function Kh(j) { - if (j <= 15) - return 0x50a28be6; - else if (j <= 31) - return 0x5c4dd124; - else if (j <= 47) - return 0x6d703ef3; - else if (j <= 63) - return 0x7a6d76e9; - else - return 0x00000000; -} - -var r = [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, - 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, - 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, - 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 -]; - -var rh = [ - 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, - 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, - 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, - 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, - 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 -]; - -var s = [ - 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, - 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, - 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, - 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, - 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 -]; - -var sh = [ - 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, - 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, - 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, - 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, - 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 -]; - -},{"./common":35,"./utils":45}],38:[function(require,module,exports){ -'use strict'; - -exports.sha1 = require('./sha/1'); -exports.sha224 = require('./sha/224'); -exports.sha256 = require('./sha/256'); -exports.sha384 = require('./sha/384'); -exports.sha512 = require('./sha/512'); - -},{"./sha/1":39,"./sha/224":40,"./sha/256":41,"./sha/384":42,"./sha/512":43}],39:[function(require,module,exports){ -'use strict'; - -var utils = require('../utils'); -var common = require('../common'); -var shaCommon = require('./common'); - -var rotl32 = utils.rotl32; -var sum32 = utils.sum32; -var sum32_5 = utils.sum32_5; -var ft_1 = shaCommon.ft_1; -var BlockHash = common.BlockHash; - -var sha1_K = [ - 0x5A827999, 0x6ED9EBA1, - 0x8F1BBCDC, 0xCA62C1D6 -]; - -function SHA1() { - if (!(this instanceof SHA1)) - return new SHA1(); - - BlockHash.call(this); - this.h = [ - 0x67452301, 0xefcdab89, 0x98badcfe, - 0x10325476, 0xc3d2e1f0 ]; - this.W = new Array(80); -} - -utils.inherits(SHA1, BlockHash); -module.exports = SHA1; - -SHA1.blockSize = 512; -SHA1.outSize = 160; -SHA1.hmacStrength = 80; -SHA1.padLength = 64; - -SHA1.prototype._update = function _update(msg, start) { - var W = this.W; - - for (var i = 0; i < 16; i++) - W[i] = msg[start + i]; - - for(; i < W.length; i++) - W[i] = rotl32(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1); - - var a = this.h[0]; - var b = this.h[1]; - var c = this.h[2]; - var d = this.h[3]; - var e = this.h[4]; - - for (i = 0; i < W.length; i++) { - var s = ~~(i / 20); - var t = sum32_5(rotl32(a, 5), ft_1(s, b, c, d), e, W[i], sha1_K[s]); - e = d; - d = c; - c = rotl32(b, 30); - b = a; - a = t; - } - - this.h[0] = sum32(this.h[0], a); - this.h[1] = sum32(this.h[1], b); - this.h[2] = sum32(this.h[2], c); - this.h[3] = sum32(this.h[3], d); - this.h[4] = sum32(this.h[4], e); -}; - -SHA1.prototype._digest = function digest(enc) { - if (enc === 'hex') - return utils.toHex32(this.h, 'big'); - else - return utils.split32(this.h, 'big'); -}; - -},{"../common":35,"../utils":45,"./common":44}],40:[function(require,module,exports){ -'use strict'; - -var utils = require('../utils'); -var SHA256 = require('./256'); - -function SHA224() { - if (!(this instanceof SHA224)) - return new SHA224(); - - SHA256.call(this); - this.h = [ - 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, - 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 ]; -} -utils.inherits(SHA224, SHA256); -module.exports = SHA224; - -SHA224.blockSize = 512; -SHA224.outSize = 224; -SHA224.hmacStrength = 192; -SHA224.padLength = 64; - -SHA224.prototype._digest = function digest(enc) { - // Just truncate output - if (enc === 'hex') - return utils.toHex32(this.h.slice(0, 7), 'big'); - else - return utils.split32(this.h.slice(0, 7), 'big'); -}; - - -},{"../utils":45,"./256":41}],41:[function(require,module,exports){ -'use strict'; - -var utils = require('../utils'); -var common = require('../common'); -var shaCommon = require('./common'); -var assert = require('minimalistic-assert'); - -var sum32 = utils.sum32; -var sum32_4 = utils.sum32_4; -var sum32_5 = utils.sum32_5; -var ch32 = shaCommon.ch32; -var maj32 = shaCommon.maj32; -var s0_256 = shaCommon.s0_256; -var s1_256 = shaCommon.s1_256; -var g0_256 = shaCommon.g0_256; -var g1_256 = shaCommon.g1_256; - -var BlockHash = common.BlockHash; - -var sha256_K = [ - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -]; - -function SHA256() { - if (!(this instanceof SHA256)) - return new SHA256(); - - BlockHash.call(this); - this.h = [ - 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, - 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 - ]; - this.k = sha256_K; - this.W = new Array(64); -} -utils.inherits(SHA256, BlockHash); -module.exports = SHA256; - -SHA256.blockSize = 512; -SHA256.outSize = 256; -SHA256.hmacStrength = 192; -SHA256.padLength = 64; - -SHA256.prototype._update = function _update(msg, start) { - var W = this.W; - - for (var i = 0; i < 16; i++) - W[i] = msg[start + i]; - for (; i < W.length; i++) - W[i] = sum32_4(g1_256(W[i - 2]), W[i - 7], g0_256(W[i - 15]), W[i - 16]); - - var a = this.h[0]; - var b = this.h[1]; - var c = this.h[2]; - var d = this.h[3]; - var e = this.h[4]; - var f = this.h[5]; - var g = this.h[6]; - var h = this.h[7]; - - assert(this.k.length === W.length); - for (i = 0; i < W.length; i++) { - var T1 = sum32_5(h, s1_256(e), ch32(e, f, g), this.k[i], W[i]); - var T2 = sum32(s0_256(a), maj32(a, b, c)); - h = g; - g = f; - f = e; - e = sum32(d, T1); - d = c; - c = b; - b = a; - a = sum32(T1, T2); - } - - this.h[0] = sum32(this.h[0], a); - this.h[1] = sum32(this.h[1], b); - this.h[2] = sum32(this.h[2], c); - this.h[3] = sum32(this.h[3], d); - this.h[4] = sum32(this.h[4], e); - this.h[5] = sum32(this.h[5], f); - this.h[6] = sum32(this.h[6], g); - this.h[7] = sum32(this.h[7], h); -}; - -SHA256.prototype._digest = function digest(enc) { - if (enc === 'hex') - return utils.toHex32(this.h, 'big'); - else - return utils.split32(this.h, 'big'); -}; - -},{"../common":35,"../utils":45,"./common":44,"minimalistic-assert":48}],42:[function(require,module,exports){ -'use strict'; - -var utils = require('../utils'); - -var SHA512 = require('./512'); - -function SHA384() { - if (!(this instanceof SHA384)) - return new SHA384(); - - SHA512.call(this); - this.h = [ - 0xcbbb9d5d, 0xc1059ed8, - 0x629a292a, 0x367cd507, - 0x9159015a, 0x3070dd17, - 0x152fecd8, 0xf70e5939, - 0x67332667, 0xffc00b31, - 0x8eb44a87, 0x68581511, - 0xdb0c2e0d, 0x64f98fa7, - 0x47b5481d, 0xbefa4fa4 ]; -} -utils.inherits(SHA384, SHA512); -module.exports = SHA384; - -SHA384.blockSize = 1024; -SHA384.outSize = 384; -SHA384.hmacStrength = 192; -SHA384.padLength = 128; - -SHA384.prototype._digest = function digest(enc) { - if (enc === 'hex') - return utils.toHex32(this.h.slice(0, 12), 'big'); - else - return utils.split32(this.h.slice(0, 12), 'big'); -}; - -},{"../utils":45,"./512":43}],43:[function(require,module,exports){ -'use strict'; - -var utils = require('../utils'); -var common = require('../common'); -var assert = require('minimalistic-assert'); - -var rotr64_hi = utils.rotr64_hi; -var rotr64_lo = utils.rotr64_lo; -var shr64_hi = utils.shr64_hi; -var shr64_lo = utils.shr64_lo; -var sum64 = utils.sum64; -var sum64_hi = utils.sum64_hi; -var sum64_lo = utils.sum64_lo; -var sum64_4_hi = utils.sum64_4_hi; -var sum64_4_lo = utils.sum64_4_lo; -var sum64_5_hi = utils.sum64_5_hi; -var sum64_5_lo = utils.sum64_5_lo; - -var BlockHash = common.BlockHash; - -var sha512_K = [ - 0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd, - 0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc, - 0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019, - 0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118, - 0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe, - 0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2, - 0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1, - 0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694, - 0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3, - 0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65, - 0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483, - 0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5, - 0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210, - 0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4, - 0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725, - 0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70, - 0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926, - 0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df, - 0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8, - 0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b, - 0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001, - 0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30, - 0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910, - 0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8, - 0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53, - 0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8, - 0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb, - 0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3, - 0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60, - 0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec, - 0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9, - 0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b, - 0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207, - 0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178, - 0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6, - 0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b, - 0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493, - 0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c, - 0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a, - 0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817 -]; - -function SHA512() { - if (!(this instanceof SHA512)) - return new SHA512(); - - BlockHash.call(this); - this.h = [ - 0x6a09e667, 0xf3bcc908, - 0xbb67ae85, 0x84caa73b, - 0x3c6ef372, 0xfe94f82b, - 0xa54ff53a, 0x5f1d36f1, - 0x510e527f, 0xade682d1, - 0x9b05688c, 0x2b3e6c1f, - 0x1f83d9ab, 0xfb41bd6b, - 0x5be0cd19, 0x137e2179 ]; - this.k = sha512_K; - this.W = new Array(160); -} -utils.inherits(SHA512, BlockHash); -module.exports = SHA512; - -SHA512.blockSize = 1024; -SHA512.outSize = 512; -SHA512.hmacStrength = 192; -SHA512.padLength = 128; - -SHA512.prototype._prepareBlock = function _prepareBlock(msg, start) { - var W = this.W; - - // 32 x 32bit words - for (var i = 0; i < 32; i++) - W[i] = msg[start + i]; - for (; i < W.length; i += 2) { - var c0_hi = g1_512_hi(W[i - 4], W[i - 3]); // i - 2 - var c0_lo = g1_512_lo(W[i - 4], W[i - 3]); - var c1_hi = W[i - 14]; // i - 7 - var c1_lo = W[i - 13]; - var c2_hi = g0_512_hi(W[i - 30], W[i - 29]); // i - 15 - var c2_lo = g0_512_lo(W[i - 30], W[i - 29]); - var c3_hi = W[i - 32]; // i - 16 - var c3_lo = W[i - 31]; - - W[i] = sum64_4_hi( - c0_hi, c0_lo, - c1_hi, c1_lo, - c2_hi, c2_lo, - c3_hi, c3_lo); - W[i + 1] = sum64_4_lo( - c0_hi, c0_lo, - c1_hi, c1_lo, - c2_hi, c2_lo, - c3_hi, c3_lo); - } -}; - -SHA512.prototype._update = function _update(msg, start) { - this._prepareBlock(msg, start); - - var W = this.W; - - var ah = this.h[0]; - var al = this.h[1]; - var bh = this.h[2]; - var bl = this.h[3]; - var ch = this.h[4]; - var cl = this.h[5]; - var dh = this.h[6]; - var dl = this.h[7]; - var eh = this.h[8]; - var el = this.h[9]; - var fh = this.h[10]; - var fl = this.h[11]; - var gh = this.h[12]; - var gl = this.h[13]; - var hh = this.h[14]; - var hl = this.h[15]; - - assert(this.k.length === W.length); - for (var i = 0; i < W.length; i += 2) { - var c0_hi = hh; - var c0_lo = hl; - var c1_hi = s1_512_hi(eh, el); - var c1_lo = s1_512_lo(eh, el); - var c2_hi = ch64_hi(eh, el, fh, fl, gh, gl); - var c2_lo = ch64_lo(eh, el, fh, fl, gh, gl); - var c3_hi = this.k[i]; - var c3_lo = this.k[i + 1]; - var c4_hi = W[i]; - var c4_lo = W[i + 1]; - - var T1_hi = sum64_5_hi( - c0_hi, c0_lo, - c1_hi, c1_lo, - c2_hi, c2_lo, - c3_hi, c3_lo, - c4_hi, c4_lo); - var T1_lo = sum64_5_lo( - c0_hi, c0_lo, - c1_hi, c1_lo, - c2_hi, c2_lo, - c3_hi, c3_lo, - c4_hi, c4_lo); - - c0_hi = s0_512_hi(ah, al); - c0_lo = s0_512_lo(ah, al); - c1_hi = maj64_hi(ah, al, bh, bl, ch, cl); - c1_lo = maj64_lo(ah, al, bh, bl, ch, cl); - - var T2_hi = sum64_hi(c0_hi, c0_lo, c1_hi, c1_lo); - var T2_lo = sum64_lo(c0_hi, c0_lo, c1_hi, c1_lo); - - hh = gh; - hl = gl; - - gh = fh; - gl = fl; - - fh = eh; - fl = el; - - eh = sum64_hi(dh, dl, T1_hi, T1_lo); - el = sum64_lo(dl, dl, T1_hi, T1_lo); - - dh = ch; - dl = cl; - - ch = bh; - cl = bl; - - bh = ah; - bl = al; - - ah = sum64_hi(T1_hi, T1_lo, T2_hi, T2_lo); - al = sum64_lo(T1_hi, T1_lo, T2_hi, T2_lo); - } - - sum64(this.h, 0, ah, al); - sum64(this.h, 2, bh, bl); - sum64(this.h, 4, ch, cl); - sum64(this.h, 6, dh, dl); - sum64(this.h, 8, eh, el); - sum64(this.h, 10, fh, fl); - sum64(this.h, 12, gh, gl); - sum64(this.h, 14, hh, hl); -}; - -SHA512.prototype._digest = function digest(enc) { - if (enc === 'hex') - return utils.toHex32(this.h, 'big'); - else - return utils.split32(this.h, 'big'); -}; - -function ch64_hi(xh, xl, yh, yl, zh) { - var r = (xh & yh) ^ ((~xh) & zh); - if (r < 0) - r += 0x100000000; - return r; -} - -function ch64_lo(xh, xl, yh, yl, zh, zl) { - var r = (xl & yl) ^ ((~xl) & zl); - if (r < 0) - r += 0x100000000; - return r; -} - -function maj64_hi(xh, xl, yh, yl, zh) { - var r = (xh & yh) ^ (xh & zh) ^ (yh & zh); - if (r < 0) - r += 0x100000000; - return r; -} - -function maj64_lo(xh, xl, yh, yl, zh, zl) { - var r = (xl & yl) ^ (xl & zl) ^ (yl & zl); - if (r < 0) - r += 0x100000000; - return r; -} - -function s0_512_hi(xh, xl) { - var c0_hi = rotr64_hi(xh, xl, 28); - var c1_hi = rotr64_hi(xl, xh, 2); // 34 - var c2_hi = rotr64_hi(xl, xh, 7); // 39 - - var r = c0_hi ^ c1_hi ^ c2_hi; - if (r < 0) - r += 0x100000000; - return r; -} - -function s0_512_lo(xh, xl) { - var c0_lo = rotr64_lo(xh, xl, 28); - var c1_lo = rotr64_lo(xl, xh, 2); // 34 - var c2_lo = rotr64_lo(xl, xh, 7); // 39 - - var r = c0_lo ^ c1_lo ^ c2_lo; - if (r < 0) - r += 0x100000000; - return r; -} - -function s1_512_hi(xh, xl) { - var c0_hi = rotr64_hi(xh, xl, 14); - var c1_hi = rotr64_hi(xh, xl, 18); - var c2_hi = rotr64_hi(xl, xh, 9); // 41 - - var r = c0_hi ^ c1_hi ^ c2_hi; - if (r < 0) - r += 0x100000000; - return r; -} - -function s1_512_lo(xh, xl) { - var c0_lo = rotr64_lo(xh, xl, 14); - var c1_lo = rotr64_lo(xh, xl, 18); - var c2_lo = rotr64_lo(xl, xh, 9); // 41 - - var r = c0_lo ^ c1_lo ^ c2_lo; - if (r < 0) - r += 0x100000000; - return r; -} - -function g0_512_hi(xh, xl) { - var c0_hi = rotr64_hi(xh, xl, 1); - var c1_hi = rotr64_hi(xh, xl, 8); - var c2_hi = shr64_hi(xh, xl, 7); - - var r = c0_hi ^ c1_hi ^ c2_hi; - if (r < 0) - r += 0x100000000; - return r; -} - -function g0_512_lo(xh, xl) { - var c0_lo = rotr64_lo(xh, xl, 1); - var c1_lo = rotr64_lo(xh, xl, 8); - var c2_lo = shr64_lo(xh, xl, 7); - - var r = c0_lo ^ c1_lo ^ c2_lo; - if (r < 0) - r += 0x100000000; - return r; -} - -function g1_512_hi(xh, xl) { - var c0_hi = rotr64_hi(xh, xl, 19); - var c1_hi = rotr64_hi(xl, xh, 29); // 61 - var c2_hi = shr64_hi(xh, xl, 6); - - var r = c0_hi ^ c1_hi ^ c2_hi; - if (r < 0) - r += 0x100000000; - return r; -} - -function g1_512_lo(xh, xl) { - var c0_lo = rotr64_lo(xh, xl, 19); - var c1_lo = rotr64_lo(xl, xh, 29); // 61 - var c2_lo = shr64_lo(xh, xl, 6); - - var r = c0_lo ^ c1_lo ^ c2_lo; - if (r < 0) - r += 0x100000000; - return r; -} - -},{"../common":35,"../utils":45,"minimalistic-assert":48}],44:[function(require,module,exports){ -'use strict'; - -var utils = require('../utils'); -var rotr32 = utils.rotr32; - -function ft_1(s, x, y, z) { - if (s === 0) - return ch32(x, y, z); - if (s === 1 || s === 3) - return p32(x, y, z); - if (s === 2) - return maj32(x, y, z); -} -exports.ft_1 = ft_1; - -function ch32(x, y, z) { - return (x & y) ^ ((~x) & z); -} -exports.ch32 = ch32; - -function maj32(x, y, z) { - return (x & y) ^ (x & z) ^ (y & z); -} -exports.maj32 = maj32; - -function p32(x, y, z) { - return x ^ y ^ z; -} -exports.p32 = p32; - -function s0_256(x) { - return rotr32(x, 2) ^ rotr32(x, 13) ^ rotr32(x, 22); -} -exports.s0_256 = s0_256; - -function s1_256(x) { - return rotr32(x, 6) ^ rotr32(x, 11) ^ rotr32(x, 25); -} -exports.s1_256 = s1_256; - -function g0_256(x) { - return rotr32(x, 7) ^ rotr32(x, 18) ^ (x >>> 3); -} -exports.g0_256 = g0_256; - -function g1_256(x) { - return rotr32(x, 17) ^ rotr32(x, 19) ^ (x >>> 10); -} -exports.g1_256 = g1_256; - -},{"../utils":45}],45:[function(require,module,exports){ -'use strict'; - -var assert = require('minimalistic-assert'); -var inherits = require('inherits'); - -exports.inherits = inherits; - -function toArray(msg, enc) { - if (Array.isArray(msg)) - return msg.slice(); - if (!msg) - return []; - var res = []; - if (typeof msg === 'string') { - if (!enc) { - for (var i = 0; i < msg.length; i++) { - var c = msg.charCodeAt(i); - var hi = c >> 8; - var lo = c & 0xff; - if (hi) - res.push(hi, lo); - else - res.push(lo); - } - } else if (enc === 'hex') { - msg = msg.replace(/[^a-z0-9]+/ig, ''); - if (msg.length % 2 !== 0) - msg = '0' + msg; - for (i = 0; i < msg.length; i += 2) - res.push(parseInt(msg[i] + msg[i + 1], 16)); - } - } else { - for (i = 0; i < msg.length; i++) - res[i] = msg[i] | 0; - } - return res; -} -exports.toArray = toArray; - -function toHex(msg) { - var res = ''; - for (var i = 0; i < msg.length; i++) - res += zero2(msg[i].toString(16)); - return res; -} -exports.toHex = toHex; - -function htonl(w) { - var res = (w >>> 24) | - ((w >>> 8) & 0xff00) | - ((w << 8) & 0xff0000) | - ((w & 0xff) << 24); - return res >>> 0; -} -exports.htonl = htonl; - -function toHex32(msg, endian) { - var res = ''; - for (var i = 0; i < msg.length; i++) { - var w = msg[i]; - if (endian === 'little') - w = htonl(w); - res += zero8(w.toString(16)); - } - return res; -} -exports.toHex32 = toHex32; - -function zero2(word) { - if (word.length === 1) - return '0' + word; - else - return word; -} -exports.zero2 = zero2; - -function zero8(word) { - if (word.length === 7) - return '0' + word; - else if (word.length === 6) - return '00' + word; - else if (word.length === 5) - return '000' + word; - else if (word.length === 4) - return '0000' + word; - else if (word.length === 3) - return '00000' + word; - else if (word.length === 2) - return '000000' + word; - else if (word.length === 1) - return '0000000' + word; - else - return word; -} -exports.zero8 = zero8; - -function join32(msg, start, end, endian) { - var len = end - start; - assert(len % 4 === 0); - var res = new Array(len / 4); - for (var i = 0, k = start; i < res.length; i++, k += 4) { - var w; - if (endian === 'big') - w = (msg[k] << 24) | (msg[k + 1] << 16) | (msg[k + 2] << 8) | msg[k + 3]; - else - w = (msg[k + 3] << 24) | (msg[k + 2] << 16) | (msg[k + 1] << 8) | msg[k]; - res[i] = w >>> 0; - } - return res; -} -exports.join32 = join32; - -function split32(msg, endian) { - var res = new Array(msg.length * 4); - for (var i = 0, k = 0; i < msg.length; i++, k += 4) { - var m = msg[i]; - if (endian === 'big') { - res[k] = m >>> 24; - res[k + 1] = (m >>> 16) & 0xff; - res[k + 2] = (m >>> 8) & 0xff; - res[k + 3] = m & 0xff; - } else { - res[k + 3] = m >>> 24; - res[k + 2] = (m >>> 16) & 0xff; - res[k + 1] = (m >>> 8) & 0xff; - res[k] = m & 0xff; - } - } - return res; -} -exports.split32 = split32; - -function rotr32(w, b) { - return (w >>> b) | (w << (32 - b)); -} -exports.rotr32 = rotr32; - -function rotl32(w, b) { - return (w << b) | (w >>> (32 - b)); -} -exports.rotl32 = rotl32; - -function sum32(a, b) { - return (a + b) >>> 0; -} -exports.sum32 = sum32; - -function sum32_3(a, b, c) { - return (a + b + c) >>> 0; -} -exports.sum32_3 = sum32_3; - -function sum32_4(a, b, c, d) { - return (a + b + c + d) >>> 0; -} -exports.sum32_4 = sum32_4; - -function sum32_5(a, b, c, d, e) { - return (a + b + c + d + e) >>> 0; -} -exports.sum32_5 = sum32_5; - -function sum64(buf, pos, ah, al) { - var bh = buf[pos]; - var bl = buf[pos + 1]; - - var lo = (al + bl) >>> 0; - var hi = (lo < al ? 1 : 0) + ah + bh; - buf[pos] = hi >>> 0; - buf[pos + 1] = lo; -} -exports.sum64 = sum64; - -function sum64_hi(ah, al, bh, bl) { - var lo = (al + bl) >>> 0; - var hi = (lo < al ? 1 : 0) + ah + bh; - return hi >>> 0; -} -exports.sum64_hi = sum64_hi; - -function sum64_lo(ah, al, bh, bl) { - var lo = al + bl; - return lo >>> 0; -} -exports.sum64_lo = sum64_lo; - -function sum64_4_hi(ah, al, bh, bl, ch, cl, dh, dl) { - var carry = 0; - var lo = al; - lo = (lo + bl) >>> 0; - carry += lo < al ? 1 : 0; - lo = (lo + cl) >>> 0; - carry += lo < cl ? 1 : 0; - lo = (lo + dl) >>> 0; - carry += lo < dl ? 1 : 0; - - var hi = ah + bh + ch + dh + carry; - return hi >>> 0; -} -exports.sum64_4_hi = sum64_4_hi; - -function sum64_4_lo(ah, al, bh, bl, ch, cl, dh, dl) { - var lo = al + bl + cl + dl; - return lo >>> 0; -} -exports.sum64_4_lo = sum64_4_lo; - -function sum64_5_hi(ah, al, bh, bl, ch, cl, dh, dl, eh, el) { - var carry = 0; - var lo = al; - lo = (lo + bl) >>> 0; - carry += lo < al ? 1 : 0; - lo = (lo + cl) >>> 0; - carry += lo < cl ? 1 : 0; - lo = (lo + dl) >>> 0; - carry += lo < dl ? 1 : 0; - lo = (lo + el) >>> 0; - carry += lo < el ? 1 : 0; - - var hi = ah + bh + ch + dh + eh + carry; - return hi >>> 0; -} -exports.sum64_5_hi = sum64_5_hi; - -function sum64_5_lo(ah, al, bh, bl, ch, cl, dh, dl, eh, el) { - var lo = al + bl + cl + dl + el; - - return lo >>> 0; -} -exports.sum64_5_lo = sum64_5_lo; - -function rotr64_hi(ah, al, num) { - var r = (al << (32 - num)) | (ah >>> num); - return r >>> 0; -} -exports.rotr64_hi = rotr64_hi; - -function rotr64_lo(ah, al, num) { - var r = (ah << (32 - num)) | (al >>> num); - return r >>> 0; -} -exports.rotr64_lo = rotr64_lo; - -function shr64_hi(ah, al, num) { - return ah >>> num; -} -exports.shr64_hi = shr64_hi; - -function shr64_lo(ah, al, num) { - var r = (ah << (32 - num)) | (al >>> num); - return r >>> 0; -} -exports.shr64_lo = shr64_lo; - -},{"inherits":47,"minimalistic-assert":48}],46:[function(require,module,exports){ -'use strict'; - -var hash = require('hash.js'); -var utils = require('minimalistic-crypto-utils'); -var assert = require('minimalistic-assert'); - -function HmacDRBG(options) { - if (!(this instanceof HmacDRBG)) - return new HmacDRBG(options); - this.hash = options.hash; - this.predResist = !!options.predResist; - - this.outLen = this.hash.outSize; - this.minEntropy = options.minEntropy || this.hash.hmacStrength; - - this._reseed = null; - this.reseedInterval = null; - this.K = null; - this.V = null; - - var entropy = utils.toArray(options.entropy, options.entropyEnc || 'hex'); - var nonce = utils.toArray(options.nonce, options.nonceEnc || 'hex'); - var pers = utils.toArray(options.pers, options.persEnc || 'hex'); - assert(entropy.length >= (this.minEntropy / 8), - 'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits'); - this._init(entropy, nonce, pers); -} -module.exports = HmacDRBG; - -HmacDRBG.prototype._init = function init(entropy, nonce, pers) { - var seed = entropy.concat(nonce).concat(pers); - - this.K = new Array(this.outLen / 8); - this.V = new Array(this.outLen / 8); - for (var i = 0; i < this.V.length; i++) { - this.K[i] = 0x00; - this.V[i] = 0x01; - } - - this._update(seed); - this._reseed = 1; - this.reseedInterval = 0x1000000000000; // 2^48 -}; - -HmacDRBG.prototype._hmac = function hmac() { - return new hash.hmac(this.hash, this.K); -}; - -HmacDRBG.prototype._update = function update(seed) { - var kmac = this._hmac() - .update(this.V) - .update([ 0x00 ]); - if (seed) - kmac = kmac.update(seed); - this.K = kmac.digest(); - this.V = this._hmac().update(this.V).digest(); - if (!seed) - return; - - this.K = this._hmac() - .update(this.V) - .update([ 0x01 ]) - .update(seed) - .digest(); - this.V = this._hmac().update(this.V).digest(); -}; - -HmacDRBG.prototype.reseed = function reseed(entropy, entropyEnc, add, addEnc) { - // Optional entropy enc - if (typeof entropyEnc !== 'string') { - addEnc = add; - add = entropyEnc; - entropyEnc = null; - } - - entropy = utils.toArray(entropy, entropyEnc); - add = utils.toArray(add, addEnc); - - assert(entropy.length >= (this.minEntropy / 8), - 'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits'); - - this._update(entropy.concat(add || [])); - this._reseed = 1; -}; - -HmacDRBG.prototype.generate = function generate(len, enc, add, addEnc) { - if (this._reseed > this.reseedInterval) - throw new Error('Reseed is required'); - - // Optional encoding - if (typeof enc !== 'string') { - addEnc = add; - add = enc; - enc = null; - } - - // Optional additional data - if (add) { - add = utils.toArray(add, addEnc || 'hex'); - this._update(add); - } - - var temp = []; - while (temp.length < len) { - this.V = this._hmac().update(this.V).digest(); - temp = temp.concat(this.V); - } - - var res = temp.slice(0, len); - this._update(add); - this._reseed++; - return utils.encode(res, enc); -}; - -},{"hash.js":34,"minimalistic-assert":48,"minimalistic-crypto-utils":49}],47:[function(require,module,exports){ -if (typeof Object.create === 'function') { - // implementation from standard node.js 'util' module - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }); - }; -} else { - // old school shim for old browsers - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - var TempCtor = function () {} - TempCtor.prototype = superCtor.prototype - ctor.prototype = new TempCtor() - ctor.prototype.constructor = ctor - } -} - -},{}],48:[function(require,module,exports){ -module.exports = assert; - -function assert(val, msg) { - if (!val) - throw new Error(msg || 'Assertion failed'); -} - -assert.equal = function assertEqual(l, r, msg) { - if (l != r) - throw new Error(msg || ('Assertion failed: ' + l + ' != ' + r)); -}; - -},{}],49:[function(require,module,exports){ -'use strict'; - -var utils = exports; - -function toArray(msg, enc) { - if (Array.isArray(msg)) - return msg.slice(); - if (!msg) - return []; - var res = []; - if (typeof msg !== 'string') { - for (var i = 0; i < msg.length; i++) - res[i] = msg[i] | 0; - return res; - } - if (enc === 'hex') { - msg = msg.replace(/[^a-z0-9]+/ig, ''); - if (msg.length % 2 !== 0) - msg = '0' + msg; - for (var i = 0; i < msg.length; i += 2) - res.push(parseInt(msg[i] + msg[i + 1], 16)); - } else { - for (var i = 0; i < msg.length; i++) { - var c = msg.charCodeAt(i); - var hi = c >> 8; - var lo = c & 0xff; - if (hi) - res.push(hi, lo); - else - res.push(lo); - } - } - return res; -} -utils.toArray = toArray; - -function zero2(word) { - if (word.length === 1) - return '0' + word; - else - return word; -} -utils.zero2 = zero2; - -function toHex(msg) { - var res = ''; - for (var i = 0; i < msg.length; i++) - res += zero2(msg[i].toString(16)); - return res; -} -utils.toHex = toHex; - -utils.encode = function encode(arr, enc) { - if (enc === 'hex') - return toHex(arr); - else - return arr; -}; - -},{}],50:[function(require,module,exports){ -// Top level file is just a mixin of submodules & constants -'use strict'; - -var assign = require('./lib/utils/common').assign; - -var deflate = require('./lib/deflate'); -var inflate = require('./lib/inflate'); -var constants = require('./lib/zlib/constants'); - -var pako = {}; - -assign(pako, deflate, inflate, constants); - -module.exports = pako; - -},{"./lib/deflate":51,"./lib/inflate":52,"./lib/utils/common":53,"./lib/zlib/constants":56}],51:[function(require,module,exports){ -'use strict'; - - -var zlib_deflate = require('./zlib/deflate'); -var utils = require('./utils/common'); -var strings = require('./utils/strings'); -var msg = require('./zlib/messages'); -var ZStream = require('./zlib/zstream'); - -var toString = Object.prototype.toString; - -/* Public constants ==========================================================*/ -/* ===========================================================================*/ - -var Z_NO_FLUSH = 0; -var Z_FINISH = 4; - -var Z_OK = 0; -var Z_STREAM_END = 1; -var Z_SYNC_FLUSH = 2; - -var Z_DEFAULT_COMPRESSION = -1; - -var Z_DEFAULT_STRATEGY = 0; - -var Z_DEFLATED = 8; - -/* ===========================================================================*/ - - -/** - * class Deflate - * - * Generic JS-style wrapper for zlib calls. If you don't need - * streaming behaviour - use more simple functions: [[deflate]], - * [[deflateRaw]] and [[gzip]]. - **/ - -/* internal - * Deflate.chunks -> Array - * - * Chunks of output data, if [[Deflate#onData]] not overridden. - **/ - -/** - * Deflate.result -> Uint8Array|Array - * - * Compressed result, generated by default [[Deflate#onData]] - * and [[Deflate#onEnd]] handlers. Filled after you push last chunk - * (call [[Deflate#push]] with `Z_FINISH` / `true` param) or if you - * push a chunk with explicit flush (call [[Deflate#push]] with - * `Z_SYNC_FLUSH` param). - **/ - -/** - * Deflate.err -> Number - * - * Error code after deflate finished. 0 (Z_OK) on success. - * You will not need it in real life, because deflate errors - * are possible only on wrong options or bad `onData` / `onEnd` - * custom handlers. - **/ - -/** - * Deflate.msg -> String - * - * Error message, if [[Deflate.err]] != 0 - **/ - - -/** - * new Deflate(options) - * - options (Object): zlib deflate options. - * - * Creates new deflator instance with specified params. Throws exception - * on bad params. Supported options: - * - * - `level` - * - `windowBits` - * - `memLevel` - * - `strategy` - * - `dictionary` - * - * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) - * for more information on these. - * - * Additional options, for internal needs: - * - * - `chunkSize` - size of generated data chunks (16K by default) - * - `raw` (Boolean) - do raw deflate - * - `gzip` (Boolean) - create gzip wrapper - * - `to` (String) - if equal to 'string', then result will be "binary string" - * (each char code [0..255]) - * - `header` (Object) - custom header for gzip - * - `text` (Boolean) - true if compressed data believed to be text - * - `time` (Number) - modification time, unix timestamp - * - `os` (Number) - operation system code - * - `extra` (Array) - array of bytes with extra data (max 65536) - * - `name` (String) - file name (binary string) - * - `comment` (String) - comment (binary string) - * - `hcrc` (Boolean) - true if header crc should be added - * - * ##### Example: - * - * ```javascript - * var pako = require('pako') - * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9]) - * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]); - * - * var deflate = new pako.Deflate({ level: 3}); - * - * deflate.push(chunk1, false); - * deflate.push(chunk2, true); // true -> last chunk - * - * if (deflate.err) { throw new Error(deflate.err); } - * - * console.log(deflate.result); - * ``` - **/ -function Deflate(options) { - if (!(this instanceof Deflate)) return new Deflate(options); - - this.options = utils.assign({ - level: Z_DEFAULT_COMPRESSION, - method: Z_DEFLATED, - chunkSize: 16384, - windowBits: 15, - memLevel: 8, - strategy: Z_DEFAULT_STRATEGY, - to: '' - }, options || {}); - - var opt = this.options; - - if (opt.raw && (opt.windowBits > 0)) { - opt.windowBits = -opt.windowBits; - } - - else if (opt.gzip && (opt.windowBits > 0) && (opt.windowBits < 16)) { - opt.windowBits += 16; - } - - this.err = 0; // error code, if happens (0 = Z_OK) - this.msg = ''; // error message - this.ended = false; // used to avoid multiple onEnd() calls - this.chunks = []; // chunks of compressed data - - this.strm = new ZStream(); - this.strm.avail_out = 0; - - var status = zlib_deflate.deflateInit2( - this.strm, - opt.level, - opt.method, - opt.windowBits, - opt.memLevel, - opt.strategy - ); - - if (status !== Z_OK) { - throw new Error(msg[status]); - } - - if (opt.header) { - zlib_deflate.deflateSetHeader(this.strm, opt.header); - } - - if (opt.dictionary) { - var dict; - // Convert data if needed - if (typeof opt.dictionary === 'string') { - // If we need to compress text, change encoding to utf8. - dict = strings.string2buf(opt.dictionary); - } else if (toString.call(opt.dictionary) === '[object ArrayBuffer]') { - dict = new Uint8Array(opt.dictionary); - } else { - dict = opt.dictionary; - } - - status = zlib_deflate.deflateSetDictionary(this.strm, dict); - - if (status !== Z_OK) { - throw new Error(msg[status]); - } - - this._dict_set = true; - } -} - -/** - * Deflate#push(data[, mode]) -> Boolean - * - data (Uint8Array|Array|ArrayBuffer|String): input data. Strings will be - * converted to utf8 byte sequence. - * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. - * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH. - * - * Sends input data to deflate pipe, generating [[Deflate#onData]] calls with - * new compressed chunks. Returns `true` on success. The last data block must have - * mode Z_FINISH (or `true`). That will flush internal pending buffers and call - * [[Deflate#onEnd]]. For interim explicit flushes (without ending the stream) you - * can use mode Z_SYNC_FLUSH, keeping the compression context. - * - * On fail call [[Deflate#onEnd]] with error code and return false. - * - * We strongly recommend to use `Uint8Array` on input for best speed (output - * array format is detected automatically). Also, don't skip last param and always - * use the same type in your code (boolean or number). That will improve JS speed. - * - * For regular `Array`-s make sure all elements are [0..255]. - * - * ##### Example - * - * ```javascript - * push(chunk, false); // push one of data chunks - * ... - * push(chunk, true); // push last chunk - * ``` - **/ -Deflate.prototype.push = function (data, mode) { - var strm = this.strm; - var chunkSize = this.options.chunkSize; - var status, _mode; - - if (this.ended) { return false; } - - _mode = (mode === ~~mode) ? mode : ((mode === true) ? Z_FINISH : Z_NO_FLUSH); - - // Convert data if needed - if (typeof data === 'string') { - // If we need to compress text, change encoding to utf8. - strm.input = strings.string2buf(data); - } else if (toString.call(data) === '[object ArrayBuffer]') { - strm.input = new Uint8Array(data); - } else { - strm.input = data; - } - - strm.next_in = 0; - strm.avail_in = strm.input.length; - - do { - if (strm.avail_out === 0) { - strm.output = new utils.Buf8(chunkSize); - strm.next_out = 0; - strm.avail_out = chunkSize; - } - status = zlib_deflate.deflate(strm, _mode); /* no bad return value */ - - if (status !== Z_STREAM_END && status !== Z_OK) { - this.onEnd(status); - this.ended = true; - return false; - } - if (strm.avail_out === 0 || (strm.avail_in === 0 && (_mode === Z_FINISH || _mode === Z_SYNC_FLUSH))) { - if (this.options.to === 'string') { - this.onData(strings.buf2binstring(utils.shrinkBuf(strm.output, strm.next_out))); - } else { - this.onData(utils.shrinkBuf(strm.output, strm.next_out)); - } - } - } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== Z_STREAM_END); - - // Finalize on the last chunk. - if (_mode === Z_FINISH) { - status = zlib_deflate.deflateEnd(this.strm); - this.onEnd(status); - this.ended = true; - return status === Z_OK; - } - - // callback interim results if Z_SYNC_FLUSH. - if (_mode === Z_SYNC_FLUSH) { - this.onEnd(Z_OK); - strm.avail_out = 0; - return true; - } - - return true; -}; - - -/** - * Deflate#onData(chunk) -> Void - * - chunk (Uint8Array|Array|String): output data. Type of array depends - * on js engine support. When string output requested, each chunk - * will be string. - * - * By default, stores data blocks in `chunks[]` property and glue - * those in `onEnd`. Override this handler, if you need another behaviour. - **/ -Deflate.prototype.onData = function (chunk) { - this.chunks.push(chunk); -}; - - -/** - * Deflate#onEnd(status) -> Void - * - status (Number): deflate status. 0 (Z_OK) on success, - * other if not. - * - * Called once after you tell deflate that the input stream is - * complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH) - * or if an error happened. By default - join collected chunks, - * free memory and fill `results` / `err` properties. - **/ -Deflate.prototype.onEnd = function (status) { - // On success - join - if (status === Z_OK) { - if (this.options.to === 'string') { - this.result = this.chunks.join(''); - } else { - this.result = utils.flattenChunks(this.chunks); - } - } - this.chunks = []; - this.err = status; - this.msg = this.strm.msg; -}; - - -/** - * deflate(data[, options]) -> Uint8Array|Array|String - * - data (Uint8Array|Array|String): input data to compress. - * - options (Object): zlib deflate options. - * - * Compress `data` with deflate algorithm and `options`. - * - * Supported options are: - * - * - level - * - windowBits - * - memLevel - * - strategy - * - dictionary - * - * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) - * for more information on these. - * - * Sugar (options): - * - * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify - * negative windowBits implicitly. - * - `to` (String) - if equal to 'string', then result will be "binary string" - * (each char code [0..255]) - * - * ##### Example: - * - * ```javascript - * var pako = require('pako') - * , data = Uint8Array([1,2,3,4,5,6,7,8,9]); - * - * console.log(pako.deflate(data)); - * ``` - **/ -function deflate(input, options) { - var deflator = new Deflate(options); - - deflator.push(input, true); - - // That will never happens, if you don't cheat with options :) - if (deflator.err) { throw deflator.msg || msg[deflator.err]; } - - return deflator.result; -} - - -/** - * deflateRaw(data[, options]) -> Uint8Array|Array|String - * - data (Uint8Array|Array|String): input data to compress. - * - options (Object): zlib deflate options. - * - * The same as [[deflate]], but creates raw data, without wrapper - * (header and adler32 crc). - **/ -function deflateRaw(input, options) { - options = options || {}; - options.raw = true; - return deflate(input, options); -} - - -/** - * gzip(data[, options]) -> Uint8Array|Array|String - * - data (Uint8Array|Array|String): input data to compress. - * - options (Object): zlib deflate options. - * - * The same as [[deflate]], but create gzip wrapper instead of - * deflate one. - **/ -function gzip(input, options) { - options = options || {}; - options.gzip = true; - return deflate(input, options); -} - - -exports.Deflate = Deflate; -exports.deflate = deflate; -exports.deflateRaw = deflateRaw; -exports.gzip = gzip; - -},{"./utils/common":53,"./utils/strings":54,"./zlib/deflate":58,"./zlib/messages":63,"./zlib/zstream":65}],52:[function(require,module,exports){ -'use strict'; - - -var zlib_inflate = require('./zlib/inflate'); -var utils = require('./utils/common'); -var strings = require('./utils/strings'); -var c = require('./zlib/constants'); -var msg = require('./zlib/messages'); -var ZStream = require('./zlib/zstream'); -var GZheader = require('./zlib/gzheader'); - -var toString = Object.prototype.toString; - -/** - * class Inflate - * - * Generic JS-style wrapper for zlib calls. If you don't need - * streaming behaviour - use more simple functions: [[inflate]] - * and [[inflateRaw]]. - **/ - -/* internal - * inflate.chunks -> Array - * - * Chunks of output data, if [[Inflate#onData]] not overridden. - **/ - -/** - * Inflate.result -> Uint8Array|Array|String - * - * Uncompressed result, generated by default [[Inflate#onData]] - * and [[Inflate#onEnd]] handlers. Filled after you push last chunk - * (call [[Inflate#push]] with `Z_FINISH` / `true` param) or if you - * push a chunk with explicit flush (call [[Inflate#push]] with - * `Z_SYNC_FLUSH` param). - **/ - -/** - * Inflate.err -> Number - * - * Error code after inflate finished. 0 (Z_OK) on success. - * Should be checked if broken data possible. - **/ - -/** - * Inflate.msg -> String - * - * Error message, if [[Inflate.err]] != 0 - **/ - - -/** - * new Inflate(options) - * - options (Object): zlib inflate options. - * - * Creates new inflator instance with specified params. Throws exception - * on bad params. Supported options: - * - * - `windowBits` - * - `dictionary` - * - * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) - * for more information on these. - * - * Additional options, for internal needs: - * - * - `chunkSize` - size of generated data chunks (16K by default) - * - `raw` (Boolean) - do raw inflate - * - `to` (String) - if equal to 'string', then result will be converted - * from utf8 to utf16 (javascript) string. When string output requested, - * chunk length can differ from `chunkSize`, depending on content. - * - * By default, when no options set, autodetect deflate/gzip data format via - * wrapper header. - * - * ##### Example: - * - * ```javascript - * var pako = require('pako') - * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9]) - * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]); - * - * var inflate = new pako.Inflate({ level: 3}); - * - * inflate.push(chunk1, false); - * inflate.push(chunk2, true); // true -> last chunk - * - * if (inflate.err) { throw new Error(inflate.err); } - * - * console.log(inflate.result); - * ``` - **/ -function Inflate(options) { - if (!(this instanceof Inflate)) return new Inflate(options); - - this.options = utils.assign({ - chunkSize: 16384, - windowBits: 0, - to: '' - }, options || {}); - - var opt = this.options; - - // Force window size for `raw` data, if not set directly, - // because we have no header for autodetect. - if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) { - opt.windowBits = -opt.windowBits; - if (opt.windowBits === 0) { opt.windowBits = -15; } - } - - // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate - if ((opt.windowBits >= 0) && (opt.windowBits < 16) && - !(options && options.windowBits)) { - opt.windowBits += 32; - } - - // Gzip header has no info about windows size, we can do autodetect only - // for deflate. So, if window size not set, force it to max when gzip possible - if ((opt.windowBits > 15) && (opt.windowBits < 48)) { - // bit 3 (16) -> gzipped data - // bit 4 (32) -> autodetect gzip/deflate - if ((opt.windowBits & 15) === 0) { - opt.windowBits |= 15; - } - } - - this.err = 0; // error code, if happens (0 = Z_OK) - this.msg = ''; // error message - this.ended = false; // used to avoid multiple onEnd() calls - this.chunks = []; // chunks of compressed data - - this.strm = new ZStream(); - this.strm.avail_out = 0; - - var status = zlib_inflate.inflateInit2( - this.strm, - opt.windowBits - ); - - if (status !== c.Z_OK) { - throw new Error(msg[status]); - } - - this.header = new GZheader(); - - zlib_inflate.inflateGetHeader(this.strm, this.header); -} - -/** - * Inflate#push(data[, mode]) -> Boolean - * - data (Uint8Array|Array|ArrayBuffer|String): input data - * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. - * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH. - * - * Sends input data to inflate pipe, generating [[Inflate#onData]] calls with - * new output chunks. Returns `true` on success. The last data block must have - * mode Z_FINISH (or `true`). That will flush internal pending buffers and call - * [[Inflate#onEnd]]. For interim explicit flushes (without ending the stream) you - * can use mode Z_SYNC_FLUSH, keeping the decompression context. - * - * On fail call [[Inflate#onEnd]] with error code and return false. - * - * We strongly recommend to use `Uint8Array` on input for best speed (output - * format is detected automatically). Also, don't skip last param and always - * use the same type in your code (boolean or number). That will improve JS speed. - * - * For regular `Array`-s make sure all elements are [0..255]. - * - * ##### Example - * - * ```javascript - * push(chunk, false); // push one of data chunks - * ... - * push(chunk, true); // push last chunk - * ``` - **/ -Inflate.prototype.push = function (data, mode) { - var strm = this.strm; - var chunkSize = this.options.chunkSize; - var dictionary = this.options.dictionary; - var status, _mode; - var next_out_utf8, tail, utf8str; - var dict; - - // Flag to properly process Z_BUF_ERROR on testing inflate call - // when we check that all output data was flushed. - var allowBufError = false; - - if (this.ended) { return false; } - _mode = (mode === ~~mode) ? mode : ((mode === true) ? c.Z_FINISH : c.Z_NO_FLUSH); - - // Convert data if needed - if (typeof data === 'string') { - // Only binary strings can be decompressed on practice - strm.input = strings.binstring2buf(data); - } else if (toString.call(data) === '[object ArrayBuffer]') { - strm.input = new Uint8Array(data); - } else { - strm.input = data; - } - - strm.next_in = 0; - strm.avail_in = strm.input.length; - - do { - if (strm.avail_out === 0) { - strm.output = new utils.Buf8(chunkSize); - strm.next_out = 0; - strm.avail_out = chunkSize; - } - - status = zlib_inflate.inflate(strm, c.Z_NO_FLUSH); /* no bad return value */ - - if (status === c.Z_NEED_DICT && dictionary) { - // Convert data if needed - if (typeof dictionary === 'string') { - dict = strings.string2buf(dictionary); - } else if (toString.call(dictionary) === '[object ArrayBuffer]') { - dict = new Uint8Array(dictionary); - } else { - dict = dictionary; - } - - status = zlib_inflate.inflateSetDictionary(this.strm, dict); - - } - - if (status === c.Z_BUF_ERROR && allowBufError === true) { - status = c.Z_OK; - allowBufError = false; - } - - if (status !== c.Z_STREAM_END && status !== c.Z_OK) { - this.onEnd(status); - this.ended = true; - return false; - } - - if (strm.next_out) { - if (strm.avail_out === 0 || status === c.Z_STREAM_END || (strm.avail_in === 0 && (_mode === c.Z_FINISH || _mode === c.Z_SYNC_FLUSH))) { - - if (this.options.to === 'string') { - - next_out_utf8 = strings.utf8border(strm.output, strm.next_out); - - tail = strm.next_out - next_out_utf8; - utf8str = strings.buf2string(strm.output, next_out_utf8); - - // move tail - strm.next_out = tail; - strm.avail_out = chunkSize - tail; - if (tail) { utils.arraySet(strm.output, strm.output, next_out_utf8, tail, 0); } - - this.onData(utf8str); - - } else { - this.onData(utils.shrinkBuf(strm.output, strm.next_out)); - } - } - } - - // When no more input data, we should check that internal inflate buffers - // are flushed. The only way to do it when avail_out = 0 - run one more - // inflate pass. But if output data not exists, inflate return Z_BUF_ERROR. - // Here we set flag to process this error properly. - // - // NOTE. Deflate does not return error in this case and does not needs such - // logic. - if (strm.avail_in === 0 && strm.avail_out === 0) { - allowBufError = true; - } - - } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== c.Z_STREAM_END); - - if (status === c.Z_STREAM_END) { - _mode = c.Z_FINISH; - } - - // Finalize on the last chunk. - if (_mode === c.Z_FINISH) { - status = zlib_inflate.inflateEnd(this.strm); - this.onEnd(status); - this.ended = true; - return status === c.Z_OK; - } - - // callback interim results if Z_SYNC_FLUSH. - if (_mode === c.Z_SYNC_FLUSH) { - this.onEnd(c.Z_OK); - strm.avail_out = 0; - return true; - } - - return true; -}; - - -/** - * Inflate#onData(chunk) -> Void - * - chunk (Uint8Array|Array|String): output data. Type of array depends - * on js engine support. When string output requested, each chunk - * will be string. - * - * By default, stores data blocks in `chunks[]` property and glue - * those in `onEnd`. Override this handler, if you need another behaviour. - **/ -Inflate.prototype.onData = function (chunk) { - this.chunks.push(chunk); -}; - - -/** - * Inflate#onEnd(status) -> Void - * - status (Number): inflate status. 0 (Z_OK) on success, - * other if not. - * - * Called either after you tell inflate that the input stream is - * complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH) - * or if an error happened. By default - join collected chunks, - * free memory and fill `results` / `err` properties. - **/ -Inflate.prototype.onEnd = function (status) { - // On success - join - if (status === c.Z_OK) { - if (this.options.to === 'string') { - // Glue & convert here, until we teach pako to send - // utf8 aligned strings to onData - this.result = this.chunks.join(''); - } else { - this.result = utils.flattenChunks(this.chunks); - } - } - this.chunks = []; - this.err = status; - this.msg = this.strm.msg; -}; - - -/** - * inflate(data[, options]) -> Uint8Array|Array|String - * - data (Uint8Array|Array|String): input data to decompress. - * - options (Object): zlib inflate options. - * - * Decompress `data` with inflate/ungzip and `options`. Autodetect - * format via wrapper header by default. That's why we don't provide - * separate `ungzip` method. - * - * Supported options are: - * - * - windowBits - * - * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) - * for more information. - * - * Sugar (options): - * - * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify - * negative windowBits implicitly. - * - `to` (String) - if equal to 'string', then result will be converted - * from utf8 to utf16 (javascript) string. When string output requested, - * chunk length can differ from `chunkSize`, depending on content. - * - * - * ##### Example: - * - * ```javascript - * var pako = require('pako') - * , input = pako.deflate([1,2,3,4,5,6,7,8,9]) - * , output; - * - * try { - * output = pako.inflate(input); - * } catch (err) - * console.log(err); - * } - * ``` - **/ -function inflate(input, options) { - var inflator = new Inflate(options); - - inflator.push(input, true); - - // That will never happens, if you don't cheat with options :) - if (inflator.err) { throw inflator.msg || msg[inflator.err]; } - - return inflator.result; -} - - -/** - * inflateRaw(data[, options]) -> Uint8Array|Array|String - * - data (Uint8Array|Array|String): input data to decompress. - * - options (Object): zlib inflate options. - * - * The same as [[inflate]], but creates raw data, without wrapper - * (header and adler32 crc). - **/ -function inflateRaw(input, options) { - options = options || {}; - options.raw = true; - return inflate(input, options); -} - - -/** - * ungzip(data[, options]) -> Uint8Array|Array|String - * - data (Uint8Array|Array|String): input data to decompress. - * - options (Object): zlib inflate options. - * - * Just shortcut to [[inflate]], because it autodetects format - * by header.content. Done for convenience. - **/ - - -exports.Inflate = Inflate; -exports.inflate = inflate; -exports.inflateRaw = inflateRaw; -exports.ungzip = inflate; - -},{"./utils/common":53,"./utils/strings":54,"./zlib/constants":56,"./zlib/gzheader":59,"./zlib/inflate":61,"./zlib/messages":63,"./zlib/zstream":65}],53:[function(require,module,exports){ -'use strict'; - - -var TYPED_OK = (typeof Uint8Array !== 'undefined') && - (typeof Uint16Array !== 'undefined') && - (typeof Int32Array !== 'undefined'); - -function _has(obj, key) { - return Object.prototype.hasOwnProperty.call(obj, key); -} - -exports.assign = function (obj /*from1, from2, from3, ...*/) { - var sources = Array.prototype.slice.call(arguments, 1); - while (sources.length) { - var source = sources.shift(); - if (!source) { continue; } - - if (typeof source !== 'object') { - throw new TypeError(source + 'must be non-object'); - } - - for (var p in source) { - if (_has(source, p)) { - obj[p] = source[p]; - } - } - } - - return obj; -}; - - -// reduce buffer size, avoiding mem copy -exports.shrinkBuf = function (buf, size) { - if (buf.length === size) { return buf; } - if (buf.subarray) { return buf.subarray(0, size); } - buf.length = size; - return buf; -}; - - -var fnTyped = { - arraySet: function (dest, src, src_offs, len, dest_offs) { - if (src.subarray && dest.subarray) { - dest.set(src.subarray(src_offs, src_offs + len), dest_offs); - return; - } - // Fallback to ordinary array - for (var i = 0; i < len; i++) { - dest[dest_offs + i] = src[src_offs + i]; - } - }, - // Join array of chunks to single array. - flattenChunks: function (chunks) { - var i, l, len, pos, chunk, result; - - // calculate data length - len = 0; - for (i = 0, l = chunks.length; i < l; i++) { - len += chunks[i].length; - } - - // join chunks - result = new Uint8Array(len); - pos = 0; - for (i = 0, l = chunks.length; i < l; i++) { - chunk = chunks[i]; - result.set(chunk, pos); - pos += chunk.length; - } - - return result; - } -}; - -var fnUntyped = { - arraySet: function (dest, src, src_offs, len, dest_offs) { - for (var i = 0; i < len; i++) { - dest[dest_offs + i] = src[src_offs + i]; - } - }, - // Join array of chunks to single array. - flattenChunks: function (chunks) { - return [].concat.apply([], chunks); - } -}; - - -// Enable/Disable typed arrays use, for testing -// -exports.setTyped = function (on) { - if (on) { - exports.Buf8 = Uint8Array; - exports.Buf16 = Uint16Array; - exports.Buf32 = Int32Array; - exports.assign(exports, fnTyped); - } else { - exports.Buf8 = Array; - exports.Buf16 = Array; - exports.Buf32 = Array; - exports.assign(exports, fnUntyped); - } -}; - -exports.setTyped(TYPED_OK); - -},{}],54:[function(require,module,exports){ -// String encode/decode helpers -'use strict'; - - -var utils = require('./common'); - - -// Quick check if we can use fast array to bin string conversion -// -// - apply(Array) can fail on Android 2.2 -// - apply(Uint8Array) can fail on iOS 5.1 Safari -// -var STR_APPLY_OK = true; -var STR_APPLY_UIA_OK = true; - -try { String.fromCharCode.apply(null, [ 0 ]); } catch (__) { STR_APPLY_OK = false; } -try { String.fromCharCode.apply(null, new Uint8Array(1)); } catch (__) { STR_APPLY_UIA_OK = false; } - - -// Table with utf8 lengths (calculated by first byte of sequence) -// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS, -// because max possible codepoint is 0x10ffff -var _utf8len = new utils.Buf8(256); -for (var q = 0; q < 256; q++) { - _utf8len[q] = (q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1); -} -_utf8len[254] = _utf8len[254] = 1; // Invalid sequence start - - -// convert string to array (typed, when possible) -exports.string2buf = function (str) { - var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0; - - // count binary size - for (m_pos = 0; m_pos < str_len; m_pos++) { - c = str.charCodeAt(m_pos); - if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) { - c2 = str.charCodeAt(m_pos + 1); - if ((c2 & 0xfc00) === 0xdc00) { - c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); - m_pos++; - } - } - buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4; - } - - // allocate buffer - buf = new utils.Buf8(buf_len); - - // convert - for (i = 0, m_pos = 0; i < buf_len; m_pos++) { - c = str.charCodeAt(m_pos); - if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) { - c2 = str.charCodeAt(m_pos + 1); - if ((c2 & 0xfc00) === 0xdc00) { - c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); - m_pos++; - } - } - if (c < 0x80) { - /* one byte */ - buf[i++] = c; - } else if (c < 0x800) { - /* two bytes */ - buf[i++] = 0xC0 | (c >>> 6); - buf[i++] = 0x80 | (c & 0x3f); - } else if (c < 0x10000) { - /* three bytes */ - buf[i++] = 0xE0 | (c >>> 12); - buf[i++] = 0x80 | (c >>> 6 & 0x3f); - buf[i++] = 0x80 | (c & 0x3f); - } else { - /* four bytes */ - buf[i++] = 0xf0 | (c >>> 18); - buf[i++] = 0x80 | (c >>> 12 & 0x3f); - buf[i++] = 0x80 | (c >>> 6 & 0x3f); - buf[i++] = 0x80 | (c & 0x3f); - } - } - - return buf; -}; - -// Helper (used in 2 places) -function buf2binstring(buf, len) { - // use fallback for big arrays to avoid stack overflow - if (len < 65537) { - if ((buf.subarray && STR_APPLY_UIA_OK) || (!buf.subarray && STR_APPLY_OK)) { - return String.fromCharCode.apply(null, utils.shrinkBuf(buf, len)); - } - } - - var result = ''; - for (var i = 0; i < len; i++) { - result += String.fromCharCode(buf[i]); - } - return result; -} - - -// Convert byte array to binary string -exports.buf2binstring = function (buf) { - return buf2binstring(buf, buf.length); -}; - - -// Convert binary string (typed, when possible) -exports.binstring2buf = function (str) { - var buf = new utils.Buf8(str.length); - for (var i = 0, len = buf.length; i < len; i++) { - buf[i] = str.charCodeAt(i); - } - return buf; -}; - - -// convert array to string -exports.buf2string = function (buf, max) { - var i, out, c, c_len; - var len = max || buf.length; - - // Reserve max possible length (2 words per char) - // NB: by unknown reasons, Array is significantly faster for - // String.fromCharCode.apply than Uint16Array. - var utf16buf = new Array(len * 2); - - for (out = 0, i = 0; i < len;) { - c = buf[i++]; - // quick process ascii - if (c < 0x80) { utf16buf[out++] = c; continue; } - - c_len = _utf8len[c]; - // skip 5 & 6 byte codes - if (c_len > 4) { utf16buf[out++] = 0xfffd; i += c_len - 1; continue; } - - // apply mask on first byte - c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07; - // join the rest - while (c_len > 1 && i < len) { - c = (c << 6) | (buf[i++] & 0x3f); - c_len--; - } - - // terminated by end of string? - if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; } - - if (c < 0x10000) { - utf16buf[out++] = c; - } else { - c -= 0x10000; - utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff); - utf16buf[out++] = 0xdc00 | (c & 0x3ff); - } - } - - return buf2binstring(utf16buf, out); -}; - - -// Calculate max possible position in utf8 buffer, -// that will not break sequence. If that's not possible -// - (very small limits) return max size as is. -// -// buf[] - utf8 bytes array -// max - length limit (mandatory); -exports.utf8border = function (buf, max) { - var pos; - - max = max || buf.length; - if (max > buf.length) { max = buf.length; } - - // go back from last position, until start of sequence found - pos = max - 1; - while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; } - - // Very small and broken sequence, - // return max, because we should return something anyway. - if (pos < 0) { return max; } - - // If we came to start of buffer - that means buffer is too small, - // return max too. - if (pos === 0) { return max; } - - return (pos + _utf8len[buf[pos]] > max) ? pos : max; -}; - -},{"./common":53}],55:[function(require,module,exports){ -'use strict'; - -// Note: adler32 takes 12% for level 0 and 2% for level 6. -// It isn't worth it to make additional optimizations as in original. -// Small size is preferable. - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -function adler32(adler, buf, len, pos) { - var s1 = (adler & 0xffff) |0, - s2 = ((adler >>> 16) & 0xffff) |0, - n = 0; - - while (len !== 0) { - // Set limit ~ twice less than 5552, to keep - // s2 in 31-bits, because we force signed ints. - // in other case %= will fail. - n = len > 2000 ? 2000 : len; - len -= n; - - do { - s1 = (s1 + buf[pos++]) |0; - s2 = (s2 + s1) |0; - } while (--n); - - s1 %= 65521; - s2 %= 65521; - } - - return (s1 | (s2 << 16)) |0; -} - - -module.exports = adler32; - -},{}],56:[function(require,module,exports){ -'use strict'; - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -module.exports = { - - /* Allowed flush values; see deflate() and inflate() below for details */ - Z_NO_FLUSH: 0, - Z_PARTIAL_FLUSH: 1, - Z_SYNC_FLUSH: 2, - Z_FULL_FLUSH: 3, - Z_FINISH: 4, - Z_BLOCK: 5, - Z_TREES: 6, - - /* Return codes for the compression/decompression functions. Negative values - * are errors, positive values are used for special but normal events. - */ - Z_OK: 0, - Z_STREAM_END: 1, - Z_NEED_DICT: 2, - Z_ERRNO: -1, - Z_STREAM_ERROR: -2, - Z_DATA_ERROR: -3, - //Z_MEM_ERROR: -4, - Z_BUF_ERROR: -5, - //Z_VERSION_ERROR: -6, - - /* compression levels */ - Z_NO_COMPRESSION: 0, - Z_BEST_SPEED: 1, - Z_BEST_COMPRESSION: 9, - Z_DEFAULT_COMPRESSION: -1, - - - Z_FILTERED: 1, - Z_HUFFMAN_ONLY: 2, - Z_RLE: 3, - Z_FIXED: 4, - Z_DEFAULT_STRATEGY: 0, - - /* Possible values of the data_type field (though see inflate()) */ - Z_BINARY: 0, - Z_TEXT: 1, - //Z_ASCII: 1, // = Z_TEXT (deprecated) - Z_UNKNOWN: 2, - - /* The deflate compression method */ - Z_DEFLATED: 8 - //Z_NULL: null // Use -1 or null inline, depending on var type -}; - -},{}],57:[function(require,module,exports){ -'use strict'; - -// Note: we can't get significant speed boost here. -// So write code to minimize size - no pregenerated tables -// and array tools dependencies. - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -// Use ordinary array, since untyped makes no boost here -function makeTable() { - var c, table = []; - - for (var n = 0; n < 256; n++) { - c = n; - for (var k = 0; k < 8; k++) { - c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); - } - table[n] = c; - } - - return table; -} - -// Create table on load. Just 255 signed longs. Not a problem. -var crcTable = makeTable(); - - -function crc32(crc, buf, len, pos) { - var t = crcTable, - end = pos + len; - - crc ^= -1; - - for (var i = pos; i < end; i++) { - crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF]; - } - - return (crc ^ (-1)); // >>> 0; -} - - -module.exports = crc32; - -},{}],58:[function(require,module,exports){ -'use strict'; - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -var utils = require('../utils/common'); -var trees = require('./trees'); -var adler32 = require('./adler32'); -var crc32 = require('./crc32'); -var msg = require('./messages'); - -/* Public constants ==========================================================*/ -/* ===========================================================================*/ - - -/* Allowed flush values; see deflate() and inflate() below for details */ -var Z_NO_FLUSH = 0; -var Z_PARTIAL_FLUSH = 1; -//var Z_SYNC_FLUSH = 2; -var Z_FULL_FLUSH = 3; -var Z_FINISH = 4; -var Z_BLOCK = 5; -//var Z_TREES = 6; - - -/* Return codes for the compression/decompression functions. Negative values - * are errors, positive values are used for special but normal events. - */ -var Z_OK = 0; -var Z_STREAM_END = 1; -//var Z_NEED_DICT = 2; -//var Z_ERRNO = -1; -var Z_STREAM_ERROR = -2; -var Z_DATA_ERROR = -3; -//var Z_MEM_ERROR = -4; -var Z_BUF_ERROR = -5; -//var Z_VERSION_ERROR = -6; - - -/* compression levels */ -//var Z_NO_COMPRESSION = 0; -//var Z_BEST_SPEED = 1; -//var Z_BEST_COMPRESSION = 9; -var Z_DEFAULT_COMPRESSION = -1; - - -var Z_FILTERED = 1; -var Z_HUFFMAN_ONLY = 2; -var Z_RLE = 3; -var Z_FIXED = 4; -var Z_DEFAULT_STRATEGY = 0; - -/* Possible values of the data_type field (though see inflate()) */ -//var Z_BINARY = 0; -//var Z_TEXT = 1; -//var Z_ASCII = 1; // = Z_TEXT -var Z_UNKNOWN = 2; - - -/* The deflate compression method */ -var Z_DEFLATED = 8; - -/*============================================================================*/ - - -var MAX_MEM_LEVEL = 9; -/* Maximum value for memLevel in deflateInit2 */ -var MAX_WBITS = 15; -/* 32K LZ77 window */ -var DEF_MEM_LEVEL = 8; - - -var LENGTH_CODES = 29; -/* number of length codes, not counting the special END_BLOCK code */ -var LITERALS = 256; -/* number of literal bytes 0..255 */ -var L_CODES = LITERALS + 1 + LENGTH_CODES; -/* number of Literal or Length codes, including the END_BLOCK code */ -var D_CODES = 30; -/* number of distance codes */ -var BL_CODES = 19; -/* number of codes used to transfer the bit lengths */ -var HEAP_SIZE = 2 * L_CODES + 1; -/* maximum heap size */ -var MAX_BITS = 15; -/* All codes must not exceed MAX_BITS bits */ - -var MIN_MATCH = 3; -var MAX_MATCH = 258; -var MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1); - -var PRESET_DICT = 0x20; - -var INIT_STATE = 42; -var EXTRA_STATE = 69; -var NAME_STATE = 73; -var COMMENT_STATE = 91; -var HCRC_STATE = 103; -var BUSY_STATE = 113; -var FINISH_STATE = 666; - -var BS_NEED_MORE = 1; /* block not completed, need more input or more output */ -var BS_BLOCK_DONE = 2; /* block flush performed */ -var BS_FINISH_STARTED = 3; /* finish started, need only more output at next deflate */ -var BS_FINISH_DONE = 4; /* finish done, accept no more input or output */ - -var OS_CODE = 0x03; // Unix :) . Don't detect, use this default. - -function err(strm, errorCode) { - strm.msg = msg[errorCode]; - return errorCode; -} - -function rank(f) { - return ((f) << 1) - ((f) > 4 ? 9 : 0); -} - -function zero(buf) { var len = buf.length; while (--len >= 0) { buf[len] = 0; } } - - -/* ========================================================================= - * Flush as much pending output as possible. All deflate() output goes - * through this function so some applications may wish to modify it - * to avoid allocating a large strm->output buffer and copying into it. - * (See also read_buf()). - */ -function flush_pending(strm) { - var s = strm.state; - - //_tr_flush_bits(s); - var len = s.pending; - if (len > strm.avail_out) { - len = strm.avail_out; - } - if (len === 0) { return; } - - utils.arraySet(strm.output, s.pending_buf, s.pending_out, len, strm.next_out); - strm.next_out += len; - s.pending_out += len; - strm.total_out += len; - strm.avail_out -= len; - s.pending -= len; - if (s.pending === 0) { - s.pending_out = 0; - } -} - - -function flush_block_only(s, last) { - trees._tr_flush_block(s, (s.block_start >= 0 ? s.block_start : -1), s.strstart - s.block_start, last); - s.block_start = s.strstart; - flush_pending(s.strm); -} - - -function put_byte(s, b) { - s.pending_buf[s.pending++] = b; -} - - -/* ========================================================================= - * Put a short in the pending buffer. The 16-bit value is put in MSB order. - * IN assertion: the stream state is correct and there is enough room in - * pending_buf. - */ -function putShortMSB(s, b) { -// put_byte(s, (Byte)(b >> 8)); -// put_byte(s, (Byte)(b & 0xff)); - s.pending_buf[s.pending++] = (b >>> 8) & 0xff; - s.pending_buf[s.pending++] = b & 0xff; -} - - -/* =========================================================================== - * Read a new buffer from the current input stream, update the adler32 - * and total number of bytes read. All deflate() input goes through - * this function so some applications may wish to modify it to avoid - * allocating a large strm->input buffer and copying from it. - * (See also flush_pending()). - */ -function read_buf(strm, buf, start, size) { - var len = strm.avail_in; - - if (len > size) { len = size; } - if (len === 0) { return 0; } - - strm.avail_in -= len; - - // zmemcpy(buf, strm->next_in, len); - utils.arraySet(buf, strm.input, strm.next_in, len, start); - if (strm.state.wrap === 1) { - strm.adler = adler32(strm.adler, buf, len, start); - } - - else if (strm.state.wrap === 2) { - strm.adler = crc32(strm.adler, buf, len, start); - } - - strm.next_in += len; - strm.total_in += len; - - return len; -} - - -/* =========================================================================== - * Set match_start to the longest match starting at the given string and - * return its length. Matches shorter or equal to prev_length are discarded, - * in which case the result is equal to prev_length and match_start is - * garbage. - * IN assertions: cur_match is the head of the hash chain for the current - * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 - * OUT assertion: the match length is not greater than s->lookahead. - */ -function longest_match(s, cur_match) { - var chain_length = s.max_chain_length; /* max hash chain length */ - var scan = s.strstart; /* current string */ - var match; /* matched string */ - var len; /* length of current match */ - var best_len = s.prev_length; /* best match length so far */ - var nice_match = s.nice_match; /* stop if match long enough */ - var limit = (s.strstart > (s.w_size - MIN_LOOKAHEAD)) ? - s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0/*NIL*/; - - var _win = s.window; // shortcut - - var wmask = s.w_mask; - var prev = s.prev; - - /* Stop when cur_match becomes <= limit. To simplify the code, - * we prevent matches with the string of window index 0. - */ - - var strend = s.strstart + MAX_MATCH; - var scan_end1 = _win[scan + best_len - 1]; - var scan_end = _win[scan + best_len]; - - /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - * It is easy to get rid of this optimization if necessary. - */ - // Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - - /* Do not waste too much time if we already have a good match: */ - if (s.prev_length >= s.good_match) { - chain_length >>= 2; - } - /* Do not look for matches beyond the end of the input. This is necessary - * to make deflate deterministic. - */ - if (nice_match > s.lookahead) { nice_match = s.lookahead; } - - // Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); - - do { - // Assert(cur_match < s->strstart, "no future"); - match = cur_match; - - /* Skip to next match if the match length cannot increase - * or if the match length is less than 2. Note that the checks below - * for insufficient lookahead only occur occasionally for performance - * reasons. Therefore uninitialized memory will be accessed, and - * conditional jumps will be made that depend on those values. - * However the length of the match is limited to the lookahead, so - * the output of deflate is not affected by the uninitialized values. - */ - - if (_win[match + best_len] !== scan_end || - _win[match + best_len - 1] !== scan_end1 || - _win[match] !== _win[scan] || - _win[++match] !== _win[scan + 1]) { - continue; - } - - /* The check at best_len-1 can be removed because it will be made - * again later. (This heuristic is not always a win.) - * It is not necessary to compare scan[2] and match[2] since they - * are always equal when the other bytes match, given that - * the hash keys are equal and that HASH_BITS >= 8. - */ - scan += 2; - match++; - // Assert(*scan == *match, "match[2]?"); - - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. - */ - do { - /*jshint noempty:false*/ - } while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - scan < strend); - - // Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - - len = MAX_MATCH - (strend - scan); - scan = strend - MAX_MATCH; - - if (len > best_len) { - s.match_start = cur_match; - best_len = len; - if (len >= nice_match) { - break; - } - scan_end1 = _win[scan + best_len - 1]; - scan_end = _win[scan + best_len]; - } - } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0); - - if (best_len <= s.lookahead) { - return best_len; - } - return s.lookahead; -} - - -/* =========================================================================== - * Fill the window when the lookahead becomes insufficient. - * Updates strstart and lookahead. - * - * IN assertion: lookahead < MIN_LOOKAHEAD - * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD - * At least one byte has been read, or avail_in == 0; reads are - * performed for at least two bytes (required for the zip translate_eol - * option -- not supported here). - */ -function fill_window(s) { - var _w_size = s.w_size; - var p, n, m, more, str; - - //Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); - - do { - more = s.window_size - s.lookahead - s.strstart; - - // JS ints have 32 bit, block below not needed - /* Deal with !@#$% 64K limit: */ - //if (sizeof(int) <= 2) { - // if (more == 0 && s->strstart == 0 && s->lookahead == 0) { - // more = wsize; - // - // } else if (more == (unsigned)(-1)) { - // /* Very unlikely, but possible on 16 bit machine if - // * strstart == 0 && lookahead == 1 (input done a byte at time) - // */ - // more--; - // } - //} - - - /* If the window is almost full and there is insufficient lookahead, - * move the upper half to the lower one to make room in the upper half. - */ - if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) { - - utils.arraySet(s.window, s.window, _w_size, _w_size, 0); - s.match_start -= _w_size; - s.strstart -= _w_size; - /* we now have strstart >= MAX_DIST */ - s.block_start -= _w_size; - - /* Slide the hash table (could be avoided with 32 bit values - at the expense of memory usage). We slide even when level == 0 - to keep the hash table consistent if we switch back to level > 0 - later. (Using level 0 permanently is not an optimal usage of - zlib, so we don't care about this pathological case.) - */ - - n = s.hash_size; - p = n; - do { - m = s.head[--p]; - s.head[p] = (m >= _w_size ? m - _w_size : 0); - } while (--n); - - n = _w_size; - p = n; - do { - m = s.prev[--p]; - s.prev[p] = (m >= _w_size ? m - _w_size : 0); - /* If n is not on any hash chain, prev[n] is garbage but - * its value will never be used. - */ - } while (--n); - - more += _w_size; - } - if (s.strm.avail_in === 0) { - break; - } - - /* If there was no sliding: - * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && - * more == window_size - lookahead - strstart - * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) - * => more >= window_size - 2*WSIZE + 2 - * In the BIG_MEM or MMAP case (not yet supported), - * window_size == input_size + MIN_LOOKAHEAD && - * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. - * Otherwise, window_size == 2*WSIZE so more >= 2. - * If there was sliding, more >= WSIZE. So in all cases, more >= 2. - */ - //Assert(more >= 2, "more < 2"); - n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more); - s.lookahead += n; - - /* Initialize the hash value now that we have some input: */ - if (s.lookahead + s.insert >= MIN_MATCH) { - str = s.strstart - s.insert; - s.ins_h = s.window[str]; - - /* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + 1]) & s.hash_mask; -//#if MIN_MATCH != 3 -// Call update_hash() MIN_MATCH-3 more times -//#endif - while (s.insert) { - /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH - 1]) & s.hash_mask; - - s.prev[str & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = str; - str++; - s.insert--; - if (s.lookahead + s.insert < MIN_MATCH) { - break; - } - } - } - /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, - * but this is not important since only literal bytes will be emitted. - */ - - } while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0); - - /* If the WIN_INIT bytes after the end of the current data have never been - * written, then zero those bytes in order to avoid memory check reports of - * the use of uninitialized (or uninitialised as Julian writes) bytes by - * the longest match routines. Update the high water mark for the next - * time through here. WIN_INIT is set to MAX_MATCH since the longest match - * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. - */ -// if (s.high_water < s.window_size) { -// var curr = s.strstart + s.lookahead; -// var init = 0; -// -// if (s.high_water < curr) { -// /* Previous high water mark below current data -- zero WIN_INIT -// * bytes or up to end of window, whichever is less. -// */ -// init = s.window_size - curr; -// if (init > WIN_INIT) -// init = WIN_INIT; -// zmemzero(s->window + curr, (unsigned)init); -// s->high_water = curr + init; -// } -// else if (s->high_water < (ulg)curr + WIN_INIT) { -// /* High water mark at or above current data, but below current data -// * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up -// * to end of window, whichever is less. -// */ -// init = (ulg)curr + WIN_INIT - s->high_water; -// if (init > s->window_size - s->high_water) -// init = s->window_size - s->high_water; -// zmemzero(s->window + s->high_water, (unsigned)init); -// s->high_water += init; -// } -// } -// -// Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, -// "not enough room for search"); -} - -/* =========================================================================== - * Copy without compression as much as possible from the input stream, return - * the current block state. - * This function does not insert new strings in the dictionary since - * uncompressible data is probably not useful. This function is used - * only for the level=0 compression option. - * NOTE: this function should be optimized to avoid extra copying from - * window to pending_buf. - */ -function deflate_stored(s, flush) { - /* Stored blocks are limited to 0xffff bytes, pending_buf is limited - * to pending_buf_size, and each stored block has a 5 byte header: - */ - var max_block_size = 0xffff; - - if (max_block_size > s.pending_buf_size - 5) { - max_block_size = s.pending_buf_size - 5; - } - - /* Copy as much as possible from input to output: */ - for (;;) { - /* Fill the window as much as possible: */ - if (s.lookahead <= 1) { - - //Assert(s->strstart < s->w_size+MAX_DIST(s) || - // s->block_start >= (long)s->w_size, "slide too late"); -// if (!(s.strstart < s.w_size + (s.w_size - MIN_LOOKAHEAD) || -// s.block_start >= s.w_size)) { -// throw new Error("slide too late"); -// } - - fill_window(s); - if (s.lookahead === 0 && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - - if (s.lookahead === 0) { - break; - } - /* flush the current block */ - } - //Assert(s->block_start >= 0L, "block gone"); -// if (s.block_start < 0) throw new Error("block gone"); - - s.strstart += s.lookahead; - s.lookahead = 0; - - /* Emit a stored block if pending_buf will be full: */ - var max_start = s.block_start + max_block_size; - - if (s.strstart === 0 || s.strstart >= max_start) { - /* strstart == 0 is possible when wraparound on 16-bit machine */ - s.lookahead = s.strstart - max_start; - s.strstart = max_start; - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - - - } - /* Flush if we may have to slide, otherwise block_start may become - * negative and the data will be gone: - */ - if (s.strstart - s.block_start >= (s.w_size - MIN_LOOKAHEAD)) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } - - s.insert = 0; - - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - - if (s.strstart > s.block_start) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - - return BS_NEED_MORE; -} - -/* =========================================================================== - * Compress as much as possible from the input stream, return the current - * block state. - * This function does not perform lazy evaluation of matches and inserts - * new strings in the dictionary only for unmatched strings or for short - * matches. It is used only for the fast compression options. - */ -function deflate_fast(s, flush) { - var hash_head; /* head of the hash chain */ - var bflush; /* set if current block must be flushed */ - - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s.lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - if (s.lookahead === 0) { - break; /* flush the current block */ - } - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - hash_head = 0/*NIL*/; - if (s.lookahead >= MIN_MATCH) { - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - } - - /* Find the longest match, discarding those <= prev_length. - * At this point we have always match_length < MIN_MATCH - */ - if (hash_head !== 0/*NIL*/ && ((s.strstart - hash_head) <= (s.w_size - MIN_LOOKAHEAD))) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - s.match_length = longest_match(s, hash_head); - /* longest_match() sets match_start */ - } - if (s.match_length >= MIN_MATCH) { - // check_match(s, s.strstart, s.match_start, s.match_length); // for debug only - - /*** _tr_tally_dist(s, s.strstart - s.match_start, - s.match_length - MIN_MATCH, bflush); ***/ - bflush = trees._tr_tally(s, s.strstart - s.match_start, s.match_length - MIN_MATCH); - - s.lookahead -= s.match_length; - - /* Insert new strings in the hash table only if the match length - * is not too large. This saves time but degrades compression. - */ - if (s.match_length <= s.max_lazy_match/*max_insert_length*/ && s.lookahead >= MIN_MATCH) { - s.match_length--; /* string at strstart already in table */ - do { - s.strstart++; - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - /* strstart never exceeds WSIZE-MAX_MATCH, so there are - * always MIN_MATCH bytes ahead. - */ - } while (--s.match_length !== 0); - s.strstart++; - } else - { - s.strstart += s.match_length; - s.match_length = 0; - s.ins_h = s.window[s.strstart]; - /* UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]); */ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + 1]) & s.hash_mask; - -//#if MIN_MATCH != 3 -// Call UPDATE_HASH() MIN_MATCH-3 more times -//#endif - /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not - * matter since it will be recomputed at next deflate call. - */ - } - } else { - /* No match, output a literal byte */ - //Tracevv((stderr,"%c", s.window[s.strstart])); - /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ - bflush = trees._tr_tally(s, 0, s.window[s.strstart]); - - s.lookahead--; - s.strstart++; - } - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } - s.insert = ((s.strstart < (MIN_MATCH - 1)) ? s.strstart : MIN_MATCH - 1); - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - return BS_BLOCK_DONE; -} - -/* =========================================================================== - * Same as above, but achieves better compression. We use a lazy - * evaluation for matches: a match is finally adopted only if there is - * no better match at the next window position. - */ -function deflate_slow(s, flush) { - var hash_head; /* head of hash chain */ - var bflush; /* set if current block must be flushed */ - - var max_insert; - - /* Process the input block. */ - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s.lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - if (s.lookahead === 0) { break; } /* flush the current block */ - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - hash_head = 0/*NIL*/; - if (s.lookahead >= MIN_MATCH) { - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - } - - /* Find the longest match, discarding those <= prev_length. - */ - s.prev_length = s.match_length; - s.prev_match = s.match_start; - s.match_length = MIN_MATCH - 1; - - if (hash_head !== 0/*NIL*/ && s.prev_length < s.max_lazy_match && - s.strstart - hash_head <= (s.w_size - MIN_LOOKAHEAD)/*MAX_DIST(s)*/) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - s.match_length = longest_match(s, hash_head); - /* longest_match() sets match_start */ - - if (s.match_length <= 5 && - (s.strategy === Z_FILTERED || (s.match_length === MIN_MATCH && s.strstart - s.match_start > 4096/*TOO_FAR*/))) { - - /* If prev_match is also MIN_MATCH, match_start is garbage - * but we will ignore the current match anyway. - */ - s.match_length = MIN_MATCH - 1; - } - } - /* If there was a match at the previous step and the current - * match is not better, output the previous match: - */ - if (s.prev_length >= MIN_MATCH && s.match_length <= s.prev_length) { - max_insert = s.strstart + s.lookahead - MIN_MATCH; - /* Do not insert strings in hash table beyond this. */ - - //check_match(s, s.strstart-1, s.prev_match, s.prev_length); - - /***_tr_tally_dist(s, s.strstart - 1 - s.prev_match, - s.prev_length - MIN_MATCH, bflush);***/ - bflush = trees._tr_tally(s, s.strstart - 1 - s.prev_match, s.prev_length - MIN_MATCH); - /* Insert in hash table all strings up to the end of the match. - * strstart-1 and strstart are already inserted. If there is not - * enough lookahead, the last two strings are not inserted in - * the hash table. - */ - s.lookahead -= s.prev_length - 1; - s.prev_length -= 2; - do { - if (++s.strstart <= max_insert) { - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - } - } while (--s.prev_length !== 0); - s.match_available = 0; - s.match_length = MIN_MATCH - 1; - s.strstart++; - - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - - } else if (s.match_available) { - /* If there was no match at the previous position, output a - * single literal. If there was a match but the current match - * is longer, truncate the previous match to a single literal. - */ - //Tracevv((stderr,"%c", s->window[s->strstart-1])); - /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ - bflush = trees._tr_tally(s, 0, s.window[s.strstart - 1]); - - if (bflush) { - /*** FLUSH_BLOCK_ONLY(s, 0) ***/ - flush_block_only(s, false); - /***/ - } - s.strstart++; - s.lookahead--; - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - } else { - /* There is no previous match to compare with, wait for - * the next step to decide. - */ - s.match_available = 1; - s.strstart++; - s.lookahead--; - } - } - //Assert (flush != Z_NO_FLUSH, "no flush?"); - if (s.match_available) { - //Tracevv((stderr,"%c", s->window[s->strstart-1])); - /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ - bflush = trees._tr_tally(s, 0, s.window[s.strstart - 1]); - - s.match_available = 0; - } - s.insert = s.strstart < MIN_MATCH - 1 ? s.strstart : MIN_MATCH - 1; - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - - return BS_BLOCK_DONE; -} - - -/* =========================================================================== - * For Z_RLE, simply look for runs of bytes, generate matches only of distance - * one. Do not maintain a hash table. (It will be regenerated if this run of - * deflate switches away from Z_RLE.) - */ -function deflate_rle(s, flush) { - var bflush; /* set if current block must be flushed */ - var prev; /* byte at distance one to match */ - var scan, strend; /* scan goes up to strend for length of run */ - - var _win = s.window; - - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the longest run, plus one for the unrolled loop. - */ - if (s.lookahead <= MAX_MATCH) { - fill_window(s); - if (s.lookahead <= MAX_MATCH && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - if (s.lookahead === 0) { break; } /* flush the current block */ - } - - /* See how many times the previous byte repeats */ - s.match_length = 0; - if (s.lookahead >= MIN_MATCH && s.strstart > 0) { - scan = s.strstart - 1; - prev = _win[scan]; - if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) { - strend = s.strstart + MAX_MATCH; - do { - /*jshint noempty:false*/ - } while (prev === _win[++scan] && prev === _win[++scan] && - prev === _win[++scan] && prev === _win[++scan] && - prev === _win[++scan] && prev === _win[++scan] && - prev === _win[++scan] && prev === _win[++scan] && - scan < strend); - s.match_length = MAX_MATCH - (strend - scan); - if (s.match_length > s.lookahead) { - s.match_length = s.lookahead; - } - } - //Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); - } - - /* Emit match if have run of MIN_MATCH or longer, else emit literal */ - if (s.match_length >= MIN_MATCH) { - //check_match(s, s.strstart, s.strstart - 1, s.match_length); - - /*** _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ***/ - bflush = trees._tr_tally(s, 1, s.match_length - MIN_MATCH); - - s.lookahead -= s.match_length; - s.strstart += s.match_length; - s.match_length = 0; - } else { - /* No match, output a literal byte */ - //Tracevv((stderr,"%c", s->window[s->strstart])); - /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ - bflush = trees._tr_tally(s, 0, s.window[s.strstart]); - - s.lookahead--; - s.strstart++; - } - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } - s.insert = 0; - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - return BS_BLOCK_DONE; -} - -/* =========================================================================== - * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. - * (It will be regenerated if this run of deflate switches away from Huffman.) - */ -function deflate_huff(s, flush) { - var bflush; /* set if current block must be flushed */ - - for (;;) { - /* Make sure that we have a literal to write. */ - if (s.lookahead === 0) { - fill_window(s); - if (s.lookahead === 0) { - if (flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - break; /* flush the current block */ - } - } - - /* Output a literal byte */ - s.match_length = 0; - //Tracevv((stderr,"%c", s->window[s->strstart])); - /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ - bflush = trees._tr_tally(s, 0, s.window[s.strstart]); - s.lookahead--; - s.strstart++; - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } - s.insert = 0; - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - return BS_BLOCK_DONE; -} - -/* Values for max_lazy_match, good_match and max_chain_length, depending on - * the desired pack level (0..9). The values given below have been tuned to - * exclude worst case performance for pathological files. Better values may be - * found for specific files. - */ -function Config(good_length, max_lazy, nice_length, max_chain, func) { - this.good_length = good_length; - this.max_lazy = max_lazy; - this.nice_length = nice_length; - this.max_chain = max_chain; - this.func = func; -} - -var configuration_table; - -configuration_table = [ - /* good lazy nice chain */ - new Config(0, 0, 0, 0, deflate_stored), /* 0 store only */ - new Config(4, 4, 8, 4, deflate_fast), /* 1 max speed, no lazy matches */ - new Config(4, 5, 16, 8, deflate_fast), /* 2 */ - new Config(4, 6, 32, 32, deflate_fast), /* 3 */ - - new Config(4, 4, 16, 16, deflate_slow), /* 4 lazy matches */ - new Config(8, 16, 32, 32, deflate_slow), /* 5 */ - new Config(8, 16, 128, 128, deflate_slow), /* 6 */ - new Config(8, 32, 128, 256, deflate_slow), /* 7 */ - new Config(32, 128, 258, 1024, deflate_slow), /* 8 */ - new Config(32, 258, 258, 4096, deflate_slow) /* 9 max compression */ -]; - - -/* =========================================================================== - * Initialize the "longest match" routines for a new zlib stream - */ -function lm_init(s) { - s.window_size = 2 * s.w_size; - - /*** CLEAR_HASH(s); ***/ - zero(s.head); // Fill with NIL (= 0); - - /* Set the default configuration parameters: - */ - s.max_lazy_match = configuration_table[s.level].max_lazy; - s.good_match = configuration_table[s.level].good_length; - s.nice_match = configuration_table[s.level].nice_length; - s.max_chain_length = configuration_table[s.level].max_chain; - - s.strstart = 0; - s.block_start = 0; - s.lookahead = 0; - s.insert = 0; - s.match_length = s.prev_length = MIN_MATCH - 1; - s.match_available = 0; - s.ins_h = 0; -} - - -function DeflateState() { - this.strm = null; /* pointer back to this zlib stream */ - this.status = 0; /* as the name implies */ - this.pending_buf = null; /* output still pending */ - this.pending_buf_size = 0; /* size of pending_buf */ - this.pending_out = 0; /* next pending byte to output to the stream */ - this.pending = 0; /* nb of bytes in the pending buffer */ - this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ - this.gzhead = null; /* gzip header information to write */ - this.gzindex = 0; /* where in extra, name, or comment */ - this.method = Z_DEFLATED; /* can only be DEFLATED */ - this.last_flush = -1; /* value of flush param for previous deflate call */ - - this.w_size = 0; /* LZ77 window size (32K by default) */ - this.w_bits = 0; /* log2(w_size) (8..16) */ - this.w_mask = 0; /* w_size - 1 */ - - this.window = null; - /* Sliding window. Input bytes are read into the second half of the window, - * and move to the first half later to keep a dictionary of at least wSize - * bytes. With this organization, matches are limited to a distance of - * wSize-MAX_MATCH bytes, but this ensures that IO is always - * performed with a length multiple of the block size. - */ - - this.window_size = 0; - /* Actual size of window: 2*wSize, except when the user input buffer - * is directly used as sliding window. - */ - - this.prev = null; - /* Link to older string with same hash index. To limit the size of this - * array to 64K, this link is maintained only for the last 32K strings. - * An index in this array is thus a window index modulo 32K. - */ - - this.head = null; /* Heads of the hash chains or NIL. */ - - this.ins_h = 0; /* hash index of string to be inserted */ - this.hash_size = 0; /* number of elements in hash table */ - this.hash_bits = 0; /* log2(hash_size) */ - this.hash_mask = 0; /* hash_size-1 */ - - this.hash_shift = 0; - /* Number of bits by which ins_h must be shifted at each input - * step. It must be such that after MIN_MATCH steps, the oldest - * byte no longer takes part in the hash key, that is: - * hash_shift * MIN_MATCH >= hash_bits - */ - - this.block_start = 0; - /* Window position at the beginning of the current output block. Gets - * negative when the window is moved backwards. - */ - - this.match_length = 0; /* length of best match */ - this.prev_match = 0; /* previous match */ - this.match_available = 0; /* set if previous match exists */ - this.strstart = 0; /* start of string to insert */ - this.match_start = 0; /* start of matching string */ - this.lookahead = 0; /* number of valid bytes ahead in window */ - - this.prev_length = 0; - /* Length of the best match at previous step. Matches not greater than this - * are discarded. This is used in the lazy match evaluation. - */ - - this.max_chain_length = 0; - /* To speed up deflation, hash chains are never searched beyond this - * length. A higher limit improves compression ratio but degrades the - * speed. - */ - - this.max_lazy_match = 0; - /* Attempt to find a better match only when the current match is strictly - * smaller than this value. This mechanism is used only for compression - * levels >= 4. - */ - // That's alias to max_lazy_match, don't use directly - //this.max_insert_length = 0; - /* Insert new strings in the hash table only if the match length is not - * greater than this length. This saves time but degrades compression. - * max_insert_length is used only for compression levels <= 3. - */ - - this.level = 0; /* compression level (1..9) */ - this.strategy = 0; /* favor or force Huffman coding*/ - - this.good_match = 0; - /* Use a faster search when the previous match is longer than this */ - - this.nice_match = 0; /* Stop searching when current match exceeds this */ - - /* used by trees.c: */ - - /* Didn't use ct_data typedef below to suppress compiler warning */ - - // struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ - // struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ - // struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ - - // Use flat array of DOUBLE size, with interleaved fata, - // because JS does not support effective - this.dyn_ltree = new utils.Buf16(HEAP_SIZE * 2); - this.dyn_dtree = new utils.Buf16((2 * D_CODES + 1) * 2); - this.bl_tree = new utils.Buf16((2 * BL_CODES + 1) * 2); - zero(this.dyn_ltree); - zero(this.dyn_dtree); - zero(this.bl_tree); - - this.l_desc = null; /* desc. for literal tree */ - this.d_desc = null; /* desc. for distance tree */ - this.bl_desc = null; /* desc. for bit length tree */ - - //ush bl_count[MAX_BITS+1]; - this.bl_count = new utils.Buf16(MAX_BITS + 1); - /* number of codes at each bit length for an optimal tree */ - - //int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ - this.heap = new utils.Buf16(2 * L_CODES + 1); /* heap used to build the Huffman trees */ - zero(this.heap); - - this.heap_len = 0; /* number of elements in the heap */ - this.heap_max = 0; /* element of largest frequency */ - /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. - * The same heap array is used to build all trees. - */ - - this.depth = new utils.Buf16(2 * L_CODES + 1); //uch depth[2*L_CODES+1]; - zero(this.depth); - /* Depth of each subtree used as tie breaker for trees of equal frequency - */ - - this.l_buf = 0; /* buffer index for literals or lengths */ - - this.lit_bufsize = 0; - /* Size of match buffer for literals/lengths. There are 4 reasons for - * limiting lit_bufsize to 64K: - * - frequencies can be kept in 16 bit counters - * - if compression is not successful for the first block, all input - * data is still in the window so we can still emit a stored block even - * when input comes from standard input. (This can also be done for - * all blocks if lit_bufsize is not greater than 32K.) - * - if compression is not successful for a file smaller than 64K, we can - * even emit a stored file instead of a stored block (saving 5 bytes). - * This is applicable only for zip (not gzip or zlib). - * - creating new Huffman trees less frequently may not provide fast - * adaptation to changes in the input data statistics. (Take for - * example a binary file with poorly compressible code followed by - * a highly compressible string table.) Smaller buffer sizes give - * fast adaptation but have of course the overhead of transmitting - * trees more frequently. - * - I can't count above 4 - */ - - this.last_lit = 0; /* running index in l_buf */ - - this.d_buf = 0; - /* Buffer index for distances. To simplify the code, d_buf and l_buf have - * the same number of elements. To use different lengths, an extra flag - * array would be necessary. - */ - - this.opt_len = 0; /* bit length of current block with optimal trees */ - this.static_len = 0; /* bit length of current block with static trees */ - this.matches = 0; /* number of string matches in current block */ - this.insert = 0; /* bytes at end of window left to insert */ - - - this.bi_buf = 0; - /* Output buffer. bits are inserted starting at the bottom (least - * significant bits). - */ - this.bi_valid = 0; - /* Number of valid bits in bi_buf. All bits above the last valid bit - * are always zero. - */ - - // Used for window memory init. We safely ignore it for JS. That makes - // sense only for pointers and memory check tools. - //this.high_water = 0; - /* High water mark offset in window for initialized bytes -- bytes above - * this are set to zero in order to avoid memory check warnings when - * longest match routines access bytes past the input. This is then - * updated to the new high water mark. - */ -} - - -function deflateResetKeep(strm) { - var s; - - if (!strm || !strm.state) { - return err(strm, Z_STREAM_ERROR); - } - - strm.total_in = strm.total_out = 0; - strm.data_type = Z_UNKNOWN; - - s = strm.state; - s.pending = 0; - s.pending_out = 0; - - if (s.wrap < 0) { - s.wrap = -s.wrap; - /* was made negative by deflate(..., Z_FINISH); */ - } - s.status = (s.wrap ? INIT_STATE : BUSY_STATE); - strm.adler = (s.wrap === 2) ? - 0 // crc32(0, Z_NULL, 0) - : - 1; // adler32(0, Z_NULL, 0) - s.last_flush = Z_NO_FLUSH; - trees._tr_init(s); - return Z_OK; -} - - -function deflateReset(strm) { - var ret = deflateResetKeep(strm); - if (ret === Z_OK) { - lm_init(strm.state); - } - return ret; -} - - -function deflateSetHeader(strm, head) { - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - if (strm.state.wrap !== 2) { return Z_STREAM_ERROR; } - strm.state.gzhead = head; - return Z_OK; -} - - -function deflateInit2(strm, level, method, windowBits, memLevel, strategy) { - if (!strm) { // === Z_NULL - return Z_STREAM_ERROR; - } - var wrap = 1; - - if (level === Z_DEFAULT_COMPRESSION) { - level = 6; - } - - if (windowBits < 0) { /* suppress zlib wrapper */ - wrap = 0; - windowBits = -windowBits; - } - - else if (windowBits > 15) { - wrap = 2; /* write gzip wrapper instead */ - windowBits -= 16; - } - - - if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method !== Z_DEFLATED || - windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || - strategy < 0 || strategy > Z_FIXED) { - return err(strm, Z_STREAM_ERROR); - } - - - if (windowBits === 8) { - windowBits = 9; - } - /* until 256-byte window bug fixed */ - - var s = new DeflateState(); - - strm.state = s; - s.strm = strm; - - s.wrap = wrap; - s.gzhead = null; - s.w_bits = windowBits; - s.w_size = 1 << s.w_bits; - s.w_mask = s.w_size - 1; - - s.hash_bits = memLevel + 7; - s.hash_size = 1 << s.hash_bits; - s.hash_mask = s.hash_size - 1; - s.hash_shift = ~~((s.hash_bits + MIN_MATCH - 1) / MIN_MATCH); - - s.window = new utils.Buf8(s.w_size * 2); - s.head = new utils.Buf16(s.hash_size); - s.prev = new utils.Buf16(s.w_size); - - // Don't need mem init magic for JS. - //s.high_water = 0; /* nothing written to s->window yet */ - - s.lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ - - s.pending_buf_size = s.lit_bufsize * 4; - - //overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); - //s->pending_buf = (uchf *) overlay; - s.pending_buf = new utils.Buf8(s.pending_buf_size); - - // It is offset from `s.pending_buf` (size is `s.lit_bufsize * 2`) - //s->d_buf = overlay + s->lit_bufsize/sizeof(ush); - s.d_buf = 1 * s.lit_bufsize; - - //s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; - s.l_buf = (1 + 2) * s.lit_bufsize; - - s.level = level; - s.strategy = strategy; - s.method = method; - - return deflateReset(strm); -} - -function deflateInit(strm, level) { - return deflateInit2(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); -} - - -function deflate(strm, flush) { - var old_flush, s; - var beg, val; // for gzip header write only - - if (!strm || !strm.state || - flush > Z_BLOCK || flush < 0) { - return strm ? err(strm, Z_STREAM_ERROR) : Z_STREAM_ERROR; - } - - s = strm.state; - - if (!strm.output || - (!strm.input && strm.avail_in !== 0) || - (s.status === FINISH_STATE && flush !== Z_FINISH)) { - return err(strm, (strm.avail_out === 0) ? Z_BUF_ERROR : Z_STREAM_ERROR); - } - - s.strm = strm; /* just in case */ - old_flush = s.last_flush; - s.last_flush = flush; - - /* Write the header */ - if (s.status === INIT_STATE) { - - if (s.wrap === 2) { // GZIP header - strm.adler = 0; //crc32(0L, Z_NULL, 0); - put_byte(s, 31); - put_byte(s, 139); - put_byte(s, 8); - if (!s.gzhead) { // s->gzhead == Z_NULL - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, s.level === 9 ? 2 : - (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? - 4 : 0)); - put_byte(s, OS_CODE); - s.status = BUSY_STATE; - } - else { - put_byte(s, (s.gzhead.text ? 1 : 0) + - (s.gzhead.hcrc ? 2 : 0) + - (!s.gzhead.extra ? 0 : 4) + - (!s.gzhead.name ? 0 : 8) + - (!s.gzhead.comment ? 0 : 16) - ); - put_byte(s, s.gzhead.time & 0xff); - put_byte(s, (s.gzhead.time >> 8) & 0xff); - put_byte(s, (s.gzhead.time >> 16) & 0xff); - put_byte(s, (s.gzhead.time >> 24) & 0xff); - put_byte(s, s.level === 9 ? 2 : - (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? - 4 : 0)); - put_byte(s, s.gzhead.os & 0xff); - if (s.gzhead.extra && s.gzhead.extra.length) { - put_byte(s, s.gzhead.extra.length & 0xff); - put_byte(s, (s.gzhead.extra.length >> 8) & 0xff); - } - if (s.gzhead.hcrc) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending, 0); - } - s.gzindex = 0; - s.status = EXTRA_STATE; - } - } - else // DEFLATE header - { - var header = (Z_DEFLATED + ((s.w_bits - 8) << 4)) << 8; - var level_flags = -1; - - if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) { - level_flags = 0; - } else if (s.level < 6) { - level_flags = 1; - } else if (s.level === 6) { - level_flags = 2; - } else { - level_flags = 3; - } - header |= (level_flags << 6); - if (s.strstart !== 0) { header |= PRESET_DICT; } - header += 31 - (header % 31); - - s.status = BUSY_STATE; - putShortMSB(s, header); - - /* Save the adler32 of the preset dictionary: */ - if (s.strstart !== 0) { - putShortMSB(s, strm.adler >>> 16); - putShortMSB(s, strm.adler & 0xffff); - } - strm.adler = 1; // adler32(0L, Z_NULL, 0); - } - } - -//#ifdef GZIP - if (s.status === EXTRA_STATE) { - if (s.gzhead.extra/* != Z_NULL*/) { - beg = s.pending; /* start of bytes to update crc */ - - while (s.gzindex < (s.gzhead.extra.length & 0xffff)) { - if (s.pending === s.pending_buf_size) { - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - flush_pending(strm); - beg = s.pending; - if (s.pending === s.pending_buf_size) { - break; - } - } - put_byte(s, s.gzhead.extra[s.gzindex] & 0xff); - s.gzindex++; - } - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - if (s.gzindex === s.gzhead.extra.length) { - s.gzindex = 0; - s.status = NAME_STATE; - } - } - else { - s.status = NAME_STATE; - } - } - if (s.status === NAME_STATE) { - if (s.gzhead.name/* != Z_NULL*/) { - beg = s.pending; /* start of bytes to update crc */ - //int val; - - do { - if (s.pending === s.pending_buf_size) { - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - flush_pending(strm); - beg = s.pending; - if (s.pending === s.pending_buf_size) { - val = 1; - break; - } - } - // JS specific: little magic to add zero terminator to end of string - if (s.gzindex < s.gzhead.name.length) { - val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff; - } else { - val = 0; - } - put_byte(s, val); - } while (val !== 0); - - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - if (val === 0) { - s.gzindex = 0; - s.status = COMMENT_STATE; - } - } - else { - s.status = COMMENT_STATE; - } - } - if (s.status === COMMENT_STATE) { - if (s.gzhead.comment/* != Z_NULL*/) { - beg = s.pending; /* start of bytes to update crc */ - //int val; - - do { - if (s.pending === s.pending_buf_size) { - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - flush_pending(strm); - beg = s.pending; - if (s.pending === s.pending_buf_size) { - val = 1; - break; - } - } - // JS specific: little magic to add zero terminator to end of string - if (s.gzindex < s.gzhead.comment.length) { - val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff; - } else { - val = 0; - } - put_byte(s, val); - } while (val !== 0); - - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - if (val === 0) { - s.status = HCRC_STATE; - } - } - else { - s.status = HCRC_STATE; - } - } - if (s.status === HCRC_STATE) { - if (s.gzhead.hcrc) { - if (s.pending + 2 > s.pending_buf_size) { - flush_pending(strm); - } - if (s.pending + 2 <= s.pending_buf_size) { - put_byte(s, strm.adler & 0xff); - put_byte(s, (strm.adler >> 8) & 0xff); - strm.adler = 0; //crc32(0L, Z_NULL, 0); - s.status = BUSY_STATE; - } - } - else { - s.status = BUSY_STATE; - } - } -//#endif - - /* Flush as much pending output as possible */ - if (s.pending !== 0) { - flush_pending(strm); - if (strm.avail_out === 0) { - /* Since avail_out is 0, deflate will be called again with - * more output space, but possibly with both pending and - * avail_in equal to zero. There won't be anything to do, - * but this is not an error situation so make sure we - * return OK instead of BUF_ERROR at next call of deflate: - */ - s.last_flush = -1; - return Z_OK; - } - - /* Make sure there is something to do and avoid duplicate consecutive - * flushes. For repeated and useless calls with Z_FINISH, we keep - * returning Z_STREAM_END instead of Z_BUF_ERROR. - */ - } else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) && - flush !== Z_FINISH) { - return err(strm, Z_BUF_ERROR); - } - - /* User must not provide more input after the first FINISH: */ - if (s.status === FINISH_STATE && strm.avail_in !== 0) { - return err(strm, Z_BUF_ERROR); - } - - /* Start a new block or continue the current one. - */ - if (strm.avail_in !== 0 || s.lookahead !== 0 || - (flush !== Z_NO_FLUSH && s.status !== FINISH_STATE)) { - var bstate = (s.strategy === Z_HUFFMAN_ONLY) ? deflate_huff(s, flush) : - (s.strategy === Z_RLE ? deflate_rle(s, flush) : - configuration_table[s.level].func(s, flush)); - - if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) { - s.status = FINISH_STATE; - } - if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) { - if (strm.avail_out === 0) { - s.last_flush = -1; - /* avoid BUF_ERROR next call, see above */ - } - return Z_OK; - /* If flush != Z_NO_FLUSH && avail_out == 0, the next call - * of deflate should use the same flush parameter to make sure - * that the flush is complete. So we don't have to output an - * empty block here, this will be done at next call. This also - * ensures that for a very small output buffer, we emit at most - * one empty block. - */ - } - if (bstate === BS_BLOCK_DONE) { - if (flush === Z_PARTIAL_FLUSH) { - trees._tr_align(s); - } - else if (flush !== Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ - - trees._tr_stored_block(s, 0, 0, false); - /* For a full flush, this empty block will be recognized - * as a special marker by inflate_sync(). - */ - if (flush === Z_FULL_FLUSH) { - /*** CLEAR_HASH(s); ***/ /* forget history */ - zero(s.head); // Fill with NIL (= 0); - - if (s.lookahead === 0) { - s.strstart = 0; - s.block_start = 0; - s.insert = 0; - } - } - } - flush_pending(strm); - if (strm.avail_out === 0) { - s.last_flush = -1; /* avoid BUF_ERROR at next call, see above */ - return Z_OK; - } - } - } - //Assert(strm->avail_out > 0, "bug2"); - //if (strm.avail_out <= 0) { throw new Error("bug2");} - - if (flush !== Z_FINISH) { return Z_OK; } - if (s.wrap <= 0) { return Z_STREAM_END; } - - /* Write the trailer */ - if (s.wrap === 2) { - put_byte(s, strm.adler & 0xff); - put_byte(s, (strm.adler >> 8) & 0xff); - put_byte(s, (strm.adler >> 16) & 0xff); - put_byte(s, (strm.adler >> 24) & 0xff); - put_byte(s, strm.total_in & 0xff); - put_byte(s, (strm.total_in >> 8) & 0xff); - put_byte(s, (strm.total_in >> 16) & 0xff); - put_byte(s, (strm.total_in >> 24) & 0xff); - } - else - { - putShortMSB(s, strm.adler >>> 16); - putShortMSB(s, strm.adler & 0xffff); - } - - flush_pending(strm); - /* If avail_out is zero, the application will call deflate again - * to flush the rest. - */ - if (s.wrap > 0) { s.wrap = -s.wrap; } - /* write the trailer only once! */ - return s.pending !== 0 ? Z_OK : Z_STREAM_END; -} - -function deflateEnd(strm) { - var status; - - if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) { - return Z_STREAM_ERROR; - } - - status = strm.state.status; - if (status !== INIT_STATE && - status !== EXTRA_STATE && - status !== NAME_STATE && - status !== COMMENT_STATE && - status !== HCRC_STATE && - status !== BUSY_STATE && - status !== FINISH_STATE - ) { - return err(strm, Z_STREAM_ERROR); - } - - strm.state = null; - - return status === BUSY_STATE ? err(strm, Z_DATA_ERROR) : Z_OK; -} - - -/* ========================================================================= - * Initializes the compression dictionary from the given byte - * sequence without producing any compressed output. - */ -function deflateSetDictionary(strm, dictionary) { - var dictLength = dictionary.length; - - var s; - var str, n; - var wrap; - var avail; - var next; - var input; - var tmpDict; - - if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) { - return Z_STREAM_ERROR; - } - - s = strm.state; - wrap = s.wrap; - - if (wrap === 2 || (wrap === 1 && s.status !== INIT_STATE) || s.lookahead) { - return Z_STREAM_ERROR; - } - - /* when using zlib wrappers, compute Adler-32 for provided dictionary */ - if (wrap === 1) { - /* adler32(strm->adler, dictionary, dictLength); */ - strm.adler = adler32(strm.adler, dictionary, dictLength, 0); - } - - s.wrap = 0; /* avoid computing Adler-32 in read_buf */ - - /* if dictionary would fill window, just replace the history */ - if (dictLength >= s.w_size) { - if (wrap === 0) { /* already empty otherwise */ - /*** CLEAR_HASH(s); ***/ - zero(s.head); // Fill with NIL (= 0); - s.strstart = 0; - s.block_start = 0; - s.insert = 0; - } - /* use the tail */ - // dictionary = dictionary.slice(dictLength - s.w_size); - tmpDict = new utils.Buf8(s.w_size); - utils.arraySet(tmpDict, dictionary, dictLength - s.w_size, s.w_size, 0); - dictionary = tmpDict; - dictLength = s.w_size; - } - /* insert dictionary into window and hash */ - avail = strm.avail_in; - next = strm.next_in; - input = strm.input; - strm.avail_in = dictLength; - strm.next_in = 0; - strm.input = dictionary; - fill_window(s); - while (s.lookahead >= MIN_MATCH) { - str = s.strstart; - n = s.lookahead - (MIN_MATCH - 1); - do { - /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH - 1]) & s.hash_mask; - - s.prev[str & s.w_mask] = s.head[s.ins_h]; - - s.head[s.ins_h] = str; - str++; - } while (--n); - s.strstart = str; - s.lookahead = MIN_MATCH - 1; - fill_window(s); - } - s.strstart += s.lookahead; - s.block_start = s.strstart; - s.insert = s.lookahead; - s.lookahead = 0; - s.match_length = s.prev_length = MIN_MATCH - 1; - s.match_available = 0; - strm.next_in = next; - strm.input = input; - strm.avail_in = avail; - s.wrap = wrap; - return Z_OK; -} - - -exports.deflateInit = deflateInit; -exports.deflateInit2 = deflateInit2; -exports.deflateReset = deflateReset; -exports.deflateResetKeep = deflateResetKeep; -exports.deflateSetHeader = deflateSetHeader; -exports.deflate = deflate; -exports.deflateEnd = deflateEnd; -exports.deflateSetDictionary = deflateSetDictionary; -exports.deflateInfo = 'pako deflate (from Nodeca project)'; - -/* Not implemented -exports.deflateBound = deflateBound; -exports.deflateCopy = deflateCopy; -exports.deflateParams = deflateParams; -exports.deflatePending = deflatePending; -exports.deflatePrime = deflatePrime; -exports.deflateTune = deflateTune; -*/ - -},{"../utils/common":53,"./adler32":55,"./crc32":57,"./messages":63,"./trees":64}],59:[function(require,module,exports){ -'use strict'; - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -function GZheader() { - /* true if compressed data believed to be text */ - this.text = 0; - /* modification time */ - this.time = 0; - /* extra flags (not used when writing a gzip file) */ - this.xflags = 0; - /* operating system */ - this.os = 0; - /* pointer to extra field or Z_NULL if none */ - this.extra = null; - /* extra field length (valid if extra != Z_NULL) */ - this.extra_len = 0; // Actually, we don't need it in JS, - // but leave for few code modifications - - // - // Setup limits is not necessary because in js we should not preallocate memory - // for inflate use constant limit in 65536 bytes - // - - /* space at extra (only when reading header) */ - // this.extra_max = 0; - /* pointer to zero-terminated file name or Z_NULL */ - this.name = ''; - /* space at name (only when reading header) */ - // this.name_max = 0; - /* pointer to zero-terminated comment or Z_NULL */ - this.comment = ''; - /* space at comment (only when reading header) */ - // this.comm_max = 0; - /* true if there was or will be a header crc */ - this.hcrc = 0; - /* true when done reading gzip header (not used when writing a gzip file) */ - this.done = false; -} - -module.exports = GZheader; - -},{}],60:[function(require,module,exports){ -'use strict'; - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -// See state defs from inflate.js -var BAD = 30; /* got a data error -- remain here until reset */ -var TYPE = 12; /* i: waiting for type bits, including last-flag bit */ - -/* - Decode literal, length, and distance codes and write out the resulting - literal and match bytes until either not enough input or output is - available, an end-of-block is encountered, or a data error is encountered. - When large enough input and output buffers are supplied to inflate(), for - example, a 16K input buffer and a 64K output buffer, more than 95% of the - inflate execution time is spent in this routine. - - Entry assumptions: - - state.mode === LEN - strm.avail_in >= 6 - strm.avail_out >= 258 - start >= strm.avail_out - state.bits < 8 - - On return, state.mode is one of: - - LEN -- ran out of enough output space or enough available input - TYPE -- reached end of block code, inflate() to interpret next block - BAD -- error in block data - - Notes: - - - The maximum input bits used by a length/distance pair is 15 bits for the - length code, 5 bits for the length extra, 15 bits for the distance code, - and 13 bits for the distance extra. This totals 48 bits, or six bytes. - Therefore if strm.avail_in >= 6, then there is enough input to avoid - checking for available input while decoding. - - - The maximum bytes that a single length/distance pair can output is 258 - bytes, which is the maximum length that can be coded. inflate_fast() - requires strm.avail_out >= 258 for each loop to avoid checking for - output space. - */ -module.exports = function inflate_fast(strm, start) { - var state; - var _in; /* local strm.input */ - var last; /* have enough input while in < last */ - var _out; /* local strm.output */ - var beg; /* inflate()'s initial strm.output */ - var end; /* while out < end, enough space available */ -//#ifdef INFLATE_STRICT - var dmax; /* maximum distance from zlib header */ -//#endif - var wsize; /* window size or zero if not using window */ - var whave; /* valid bytes in the window */ - var wnext; /* window write index */ - // Use `s_window` instead `window`, avoid conflict with instrumentation tools - var s_window; /* allocated sliding window, if wsize != 0 */ - var hold; /* local strm.hold */ - var bits; /* local strm.bits */ - var lcode; /* local strm.lencode */ - var dcode; /* local strm.distcode */ - var lmask; /* mask for first level of length codes */ - var dmask; /* mask for first level of distance codes */ - var here; /* retrieved table entry */ - var op; /* code bits, operation, extra bits, or */ - /* window position, window bytes to copy */ - var len; /* match length, unused bytes */ - var dist; /* match distance */ - var from; /* where to copy match from */ - var from_source; - - - var input, output; // JS specific, because we have no pointers - - /* copy state to local variables */ - state = strm.state; - //here = state.here; - _in = strm.next_in; - input = strm.input; - last = _in + (strm.avail_in - 5); - _out = strm.next_out; - output = strm.output; - beg = _out - (start - strm.avail_out); - end = _out + (strm.avail_out - 257); -//#ifdef INFLATE_STRICT - dmax = state.dmax; -//#endif - wsize = state.wsize; - whave = state.whave; - wnext = state.wnext; - s_window = state.window; - hold = state.hold; - bits = state.bits; - lcode = state.lencode; - dcode = state.distcode; - lmask = (1 << state.lenbits) - 1; - dmask = (1 << state.distbits) - 1; - - - /* decode literals and length/distances until end-of-block or not enough - input data or output space */ - - top: - do { - if (bits < 15) { - hold += input[_in++] << bits; - bits += 8; - hold += input[_in++] << bits; - bits += 8; - } - - here = lcode[hold & lmask]; - - dolen: - for (;;) { // Goto emulation - op = here >>> 24/*here.bits*/; - hold >>>= op; - bits -= op; - op = (here >>> 16) & 0xff/*here.op*/; - if (op === 0) { /* literal */ - //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - // "inflate: literal '%c'\n" : - // "inflate: literal 0x%02x\n", here.val)); - output[_out++] = here & 0xffff/*here.val*/; - } - else if (op & 16) { /* length base */ - len = here & 0xffff/*here.val*/; - op &= 15; /* number of extra bits */ - if (op) { - if (bits < op) { - hold += input[_in++] << bits; - bits += 8; - } - len += hold & ((1 << op) - 1); - hold >>>= op; - bits -= op; - } - //Tracevv((stderr, "inflate: length %u\n", len)); - if (bits < 15) { - hold += input[_in++] << bits; - bits += 8; - hold += input[_in++] << bits; - bits += 8; - } - here = dcode[hold & dmask]; - - dodist: - for (;;) { // goto emulation - op = here >>> 24/*here.bits*/; - hold >>>= op; - bits -= op; - op = (here >>> 16) & 0xff/*here.op*/; - - if (op & 16) { /* distance base */ - dist = here & 0xffff/*here.val*/; - op &= 15; /* number of extra bits */ - if (bits < op) { - hold += input[_in++] << bits; - bits += 8; - if (bits < op) { - hold += input[_in++] << bits; - bits += 8; - } - } - dist += hold & ((1 << op) - 1); -//#ifdef INFLATE_STRICT - if (dist > dmax) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD; - break top; - } -//#endif - hold >>>= op; - bits -= op; - //Tracevv((stderr, "inflate: distance %u\n", dist)); - op = _out - beg; /* max distance in output */ - if (dist > op) { /* see if copy from window */ - op = dist - op; /* distance back in window */ - if (op > whave) { - if (state.sane) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD; - break top; - } - -// (!) This block is disabled in zlib defaults, -// don't enable it for binary compatibility -//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR -// if (len <= op - whave) { -// do { -// output[_out++] = 0; -// } while (--len); -// continue top; -// } -// len -= op - whave; -// do { -// output[_out++] = 0; -// } while (--op > whave); -// if (op === 0) { -// from = _out - dist; -// do { -// output[_out++] = output[from++]; -// } while (--len); -// continue top; -// } -//#endif - } - from = 0; // window index - from_source = s_window; - if (wnext === 0) { /* very common case */ - from += wsize - op; - if (op < len) { /* some from window */ - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = _out - dist; /* rest from output */ - from_source = output; - } - } - else if (wnext < op) { /* wrap around window */ - from += wsize + wnext - op; - op -= wnext; - if (op < len) { /* some from end of window */ - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = 0; - if (wnext < len) { /* some from start of window */ - op = wnext; - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = _out - dist; /* rest from output */ - from_source = output; - } - } - } - else { /* contiguous in window */ - from += wnext - op; - if (op < len) { /* some from window */ - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = _out - dist; /* rest from output */ - from_source = output; - } - } - while (len > 2) { - output[_out++] = from_source[from++]; - output[_out++] = from_source[from++]; - output[_out++] = from_source[from++]; - len -= 3; - } - if (len) { - output[_out++] = from_source[from++]; - if (len > 1) { - output[_out++] = from_source[from++]; - } - } - } - else { - from = _out - dist; /* copy direct from output */ - do { /* minimum length is three */ - output[_out++] = output[from++]; - output[_out++] = output[from++]; - output[_out++] = output[from++]; - len -= 3; - } while (len > 2); - if (len) { - output[_out++] = output[from++]; - if (len > 1) { - output[_out++] = output[from++]; - } - } - } - } - else if ((op & 64) === 0) { /* 2nd level distance code */ - here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))]; - continue dodist; - } - else { - strm.msg = 'invalid distance code'; - state.mode = BAD; - break top; - } - - break; // need to emulate goto via "continue" - } - } - else if ((op & 64) === 0) { /* 2nd level length code */ - here = lcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))]; - continue dolen; - } - else if (op & 32) { /* end-of-block */ - //Tracevv((stderr, "inflate: end of block\n")); - state.mode = TYPE; - break top; - } - else { - strm.msg = 'invalid literal/length code'; - state.mode = BAD; - break top; - } - - break; // need to emulate goto via "continue" - } - } while (_in < last && _out < end); - - /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ - len = bits >> 3; - _in -= len; - bits -= len << 3; - hold &= (1 << bits) - 1; - - /* update state and return */ - strm.next_in = _in; - strm.next_out = _out; - strm.avail_in = (_in < last ? 5 + (last - _in) : 5 - (_in - last)); - strm.avail_out = (_out < end ? 257 + (end - _out) : 257 - (_out - end)); - state.hold = hold; - state.bits = bits; - return; -}; - -},{}],61:[function(require,module,exports){ -'use strict'; - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -var utils = require('../utils/common'); -var adler32 = require('./adler32'); -var crc32 = require('./crc32'); -var inflate_fast = require('./inffast'); -var inflate_table = require('./inftrees'); - -var CODES = 0; -var LENS = 1; -var DISTS = 2; - -/* Public constants ==========================================================*/ -/* ===========================================================================*/ - - -/* Allowed flush values; see deflate() and inflate() below for details */ -//var Z_NO_FLUSH = 0; -//var Z_PARTIAL_FLUSH = 1; -//var Z_SYNC_FLUSH = 2; -//var Z_FULL_FLUSH = 3; -var Z_FINISH = 4; -var Z_BLOCK = 5; -var Z_TREES = 6; - - -/* Return codes for the compression/decompression functions. Negative values - * are errors, positive values are used for special but normal events. - */ -var Z_OK = 0; -var Z_STREAM_END = 1; -var Z_NEED_DICT = 2; -//var Z_ERRNO = -1; -var Z_STREAM_ERROR = -2; -var Z_DATA_ERROR = -3; -var Z_MEM_ERROR = -4; -var Z_BUF_ERROR = -5; -//var Z_VERSION_ERROR = -6; - -/* The deflate compression method */ -var Z_DEFLATED = 8; - - -/* STATES ====================================================================*/ -/* ===========================================================================*/ - - -var HEAD = 1; /* i: waiting for magic header */ -var FLAGS = 2; /* i: waiting for method and flags (gzip) */ -var TIME = 3; /* i: waiting for modification time (gzip) */ -var OS = 4; /* i: waiting for extra flags and operating system (gzip) */ -var EXLEN = 5; /* i: waiting for extra length (gzip) */ -var EXTRA = 6; /* i: waiting for extra bytes (gzip) */ -var NAME = 7; /* i: waiting for end of file name (gzip) */ -var COMMENT = 8; /* i: waiting for end of comment (gzip) */ -var HCRC = 9; /* i: waiting for header crc (gzip) */ -var DICTID = 10; /* i: waiting for dictionary check value */ -var DICT = 11; /* waiting for inflateSetDictionary() call */ -var TYPE = 12; /* i: waiting for type bits, including last-flag bit */ -var TYPEDO = 13; /* i: same, but skip check to exit inflate on new block */ -var STORED = 14; /* i: waiting for stored size (length and complement) */ -var COPY_ = 15; /* i/o: same as COPY below, but only first time in */ -var COPY = 16; /* i/o: waiting for input or output to copy stored block */ -var TABLE = 17; /* i: waiting for dynamic block table lengths */ -var LENLENS = 18; /* i: waiting for code length code lengths */ -var CODELENS = 19; /* i: waiting for length/lit and distance code lengths */ -var LEN_ = 20; /* i: same as LEN below, but only first time in */ -var LEN = 21; /* i: waiting for length/lit/eob code */ -var LENEXT = 22; /* i: waiting for length extra bits */ -var DIST = 23; /* i: waiting for distance code */ -var DISTEXT = 24; /* i: waiting for distance extra bits */ -var MATCH = 25; /* o: waiting for output space to copy string */ -var LIT = 26; /* o: waiting for output space to write literal */ -var CHECK = 27; /* i: waiting for 32-bit check value */ -var LENGTH = 28; /* i: waiting for 32-bit length (gzip) */ -var DONE = 29; /* finished check, done -- remain here until reset */ -var BAD = 30; /* got a data error -- remain here until reset */ -var MEM = 31; /* got an inflate() memory error -- remain here until reset */ -var SYNC = 32; /* looking for synchronization bytes to restart inflate() */ - -/* ===========================================================================*/ - - - -var ENOUGH_LENS = 852; -var ENOUGH_DISTS = 592; -//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); - -var MAX_WBITS = 15; -/* 32K LZ77 window */ -var DEF_WBITS = MAX_WBITS; - - -function zswap32(q) { - return (((q >>> 24) & 0xff) + - ((q >>> 8) & 0xff00) + - ((q & 0xff00) << 8) + - ((q & 0xff) << 24)); -} - - -function InflateState() { - this.mode = 0; /* current inflate mode */ - this.last = false; /* true if processing last block */ - this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ - this.havedict = false; /* true if dictionary provided */ - this.flags = 0; /* gzip header method and flags (0 if zlib) */ - this.dmax = 0; /* zlib header max distance (INFLATE_STRICT) */ - this.check = 0; /* protected copy of check value */ - this.total = 0; /* protected copy of output count */ - // TODO: may be {} - this.head = null; /* where to save gzip header information */ - - /* sliding window */ - this.wbits = 0; /* log base 2 of requested window size */ - this.wsize = 0; /* window size or zero if not using window */ - this.whave = 0; /* valid bytes in the window */ - this.wnext = 0; /* window write index */ - this.window = null; /* allocated sliding window, if needed */ - - /* bit accumulator */ - this.hold = 0; /* input bit accumulator */ - this.bits = 0; /* number of bits in "in" */ - - /* for string and stored block copying */ - this.length = 0; /* literal or length of data to copy */ - this.offset = 0; /* distance back to copy string from */ - - /* for table and code decoding */ - this.extra = 0; /* extra bits needed */ - - /* fixed and dynamic code tables */ - this.lencode = null; /* starting table for length/literal codes */ - this.distcode = null; /* starting table for distance codes */ - this.lenbits = 0; /* index bits for lencode */ - this.distbits = 0; /* index bits for distcode */ - - /* dynamic table building */ - this.ncode = 0; /* number of code length code lengths */ - this.nlen = 0; /* number of length code lengths */ - this.ndist = 0; /* number of distance code lengths */ - this.have = 0; /* number of code lengths in lens[] */ - this.next = null; /* next available space in codes[] */ - - this.lens = new utils.Buf16(320); /* temporary storage for code lengths */ - this.work = new utils.Buf16(288); /* work area for code table building */ - - /* - because we don't have pointers in js, we use lencode and distcode directly - as buffers so we don't need codes - */ - //this.codes = new utils.Buf32(ENOUGH); /* space for code tables */ - this.lendyn = null; /* dynamic table for length/literal codes (JS specific) */ - this.distdyn = null; /* dynamic table for distance codes (JS specific) */ - this.sane = 0; /* if false, allow invalid distance too far */ - this.back = 0; /* bits back of last unprocessed length/lit */ - this.was = 0; /* initial length of match */ -} - -function inflateResetKeep(strm) { - var state; - - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - strm.total_in = strm.total_out = state.total = 0; - strm.msg = ''; /*Z_NULL*/ - if (state.wrap) { /* to support ill-conceived Java test suite */ - strm.adler = state.wrap & 1; - } - state.mode = HEAD; - state.last = 0; - state.havedict = 0; - state.dmax = 32768; - state.head = null/*Z_NULL*/; - state.hold = 0; - state.bits = 0; - //state.lencode = state.distcode = state.next = state.codes; - state.lencode = state.lendyn = new utils.Buf32(ENOUGH_LENS); - state.distcode = state.distdyn = new utils.Buf32(ENOUGH_DISTS); - - state.sane = 1; - state.back = -1; - //Tracev((stderr, "inflate: reset\n")); - return Z_OK; -} - -function inflateReset(strm) { - var state; - - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - state.wsize = 0; - state.whave = 0; - state.wnext = 0; - return inflateResetKeep(strm); - -} - -function inflateReset2(strm, windowBits) { - var wrap; - var state; - - /* get the state */ - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - - /* extract wrap request from windowBits parameter */ - if (windowBits < 0) { - wrap = 0; - windowBits = -windowBits; - } - else { - wrap = (windowBits >> 4) + 1; - if (windowBits < 48) { - windowBits &= 15; - } - } - - /* set number of window bits, free window if different */ - if (windowBits && (windowBits < 8 || windowBits > 15)) { - return Z_STREAM_ERROR; - } - if (state.window !== null && state.wbits !== windowBits) { - state.window = null; - } - - /* update state and reset the rest of it */ - state.wrap = wrap; - state.wbits = windowBits; - return inflateReset(strm); -} - -function inflateInit2(strm, windowBits) { - var ret; - var state; - - if (!strm) { return Z_STREAM_ERROR; } - //strm.msg = Z_NULL; /* in case we return an error */ - - state = new InflateState(); - - //if (state === Z_NULL) return Z_MEM_ERROR; - //Tracev((stderr, "inflate: allocated\n")); - strm.state = state; - state.window = null/*Z_NULL*/; - ret = inflateReset2(strm, windowBits); - if (ret !== Z_OK) { - strm.state = null/*Z_NULL*/; - } - return ret; -} - -function inflateInit(strm) { - return inflateInit2(strm, DEF_WBITS); -} - - -/* - Return state with length and distance decoding tables and index sizes set to - fixed code decoding. Normally this returns fixed tables from inffixed.h. - If BUILDFIXED is defined, then instead this routine builds the tables the - first time it's called, and returns those tables the first time and - thereafter. This reduces the size of the code by about 2K bytes, in - exchange for a little execution time. However, BUILDFIXED should not be - used for threaded applications, since the rewriting of the tables and virgin - may not be thread-safe. - */ -var virgin = true; - -var lenfix, distfix; // We have no pointers in JS, so keep tables separate - -function fixedtables(state) { - /* build fixed huffman tables if first call (may not be thread safe) */ - if (virgin) { - var sym; - - lenfix = new utils.Buf32(512); - distfix = new utils.Buf32(32); - - /* literal/length table */ - sym = 0; - while (sym < 144) { state.lens[sym++] = 8; } - while (sym < 256) { state.lens[sym++] = 9; } - while (sym < 280) { state.lens[sym++] = 7; } - while (sym < 288) { state.lens[sym++] = 8; } - - inflate_table(LENS, state.lens, 0, 288, lenfix, 0, state.work, { bits: 9 }); - - /* distance table */ - sym = 0; - while (sym < 32) { state.lens[sym++] = 5; } - - inflate_table(DISTS, state.lens, 0, 32, distfix, 0, state.work, { bits: 5 }); - - /* do this just once */ - virgin = false; - } - - state.lencode = lenfix; - state.lenbits = 9; - state.distcode = distfix; - state.distbits = 5; -} - - -/* - Update the window with the last wsize (normally 32K) bytes written before - returning. If window does not exist yet, create it. This is only called - when a window is already in use, or when output has been written during this - inflate call, but the end of the deflate stream has not been reached yet. - It is also called to create a window for dictionary data when a dictionary - is loaded. - - Providing output buffers larger than 32K to inflate() should provide a speed - advantage, since only the last 32K of output is copied to the sliding window - upon return from inflate(), and since all distances after the first 32K of - output will fall in the output data, making match copies simpler and faster. - The advantage may be dependent on the size of the processor's data caches. - */ -function updatewindow(strm, src, end, copy) { - var dist; - var state = strm.state; - - /* if it hasn't been done already, allocate space for the window */ - if (state.window === null) { - state.wsize = 1 << state.wbits; - state.wnext = 0; - state.whave = 0; - - state.window = new utils.Buf8(state.wsize); - } - - /* copy state->wsize or less output bytes into the circular window */ - if (copy >= state.wsize) { - utils.arraySet(state.window, src, end - state.wsize, state.wsize, 0); - state.wnext = 0; - state.whave = state.wsize; - } - else { - dist = state.wsize - state.wnext; - if (dist > copy) { - dist = copy; - } - //zmemcpy(state->window + state->wnext, end - copy, dist); - utils.arraySet(state.window, src, end - copy, dist, state.wnext); - copy -= dist; - if (copy) { - //zmemcpy(state->window, end - copy, copy); - utils.arraySet(state.window, src, end - copy, copy, 0); - state.wnext = copy; - state.whave = state.wsize; - } - else { - state.wnext += dist; - if (state.wnext === state.wsize) { state.wnext = 0; } - if (state.whave < state.wsize) { state.whave += dist; } - } - } - return 0; -} - -function inflate(strm, flush) { - var state; - var input, output; // input/output buffers - var next; /* next input INDEX */ - var put; /* next output INDEX */ - var have, left; /* available input and output */ - var hold; /* bit buffer */ - var bits; /* bits in bit buffer */ - var _in, _out; /* save starting available input and output */ - var copy; /* number of stored or match bytes to copy */ - var from; /* where to copy match bytes from */ - var from_source; - var here = 0; /* current decoding table entry */ - var here_bits, here_op, here_val; // paked "here" denormalized (JS specific) - //var last; /* parent table entry */ - var last_bits, last_op, last_val; // paked "last" denormalized (JS specific) - var len; /* length to copy for repeats, bits to drop */ - var ret; /* return code */ - var hbuf = new utils.Buf8(4); /* buffer for gzip header crc calculation */ - var opts; - - var n; // temporary var for NEED_BITS - - var order = /* permutation of code lengths */ - [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ]; - - - if (!strm || !strm.state || !strm.output || - (!strm.input && strm.avail_in !== 0)) { - return Z_STREAM_ERROR; - } - - state = strm.state; - if (state.mode === TYPE) { state.mode = TYPEDO; } /* skip check */ - - - //--- LOAD() --- - put = strm.next_out; - output = strm.output; - left = strm.avail_out; - next = strm.next_in; - input = strm.input; - have = strm.avail_in; - hold = state.hold; - bits = state.bits; - //--- - - _in = have; - _out = left; - ret = Z_OK; - - inf_leave: // goto emulation - for (;;) { - switch (state.mode) { - case HEAD: - if (state.wrap === 0) { - state.mode = TYPEDO; - break; - } - //=== NEEDBITS(16); - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if ((state.wrap & 2) && hold === 0x8b1f) { /* gzip header */ - state.check = 0/*crc32(0L, Z_NULL, 0)*/; - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = FLAGS; - break; - } - state.flags = 0; /* expect zlib header */ - if (state.head) { - state.head.done = false; - } - if (!(state.wrap & 1) || /* check if zlib header allowed */ - (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) { - strm.msg = 'incorrect header check'; - state.mode = BAD; - break; - } - if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) { - strm.msg = 'unknown compression method'; - state.mode = BAD; - break; - } - //--- DROPBITS(4) ---// - hold >>>= 4; - bits -= 4; - //---// - len = (hold & 0x0f)/*BITS(4)*/ + 8; - if (state.wbits === 0) { - state.wbits = len; - } - else if (len > state.wbits) { - strm.msg = 'invalid window size'; - state.mode = BAD; - break; - } - state.dmax = 1 << len; - //Tracev((stderr, "inflate: zlib header ok\n")); - strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; - state.mode = hold & 0x200 ? DICTID : TYPE; - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - break; - case FLAGS: - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.flags = hold; - if ((state.flags & 0xff) !== Z_DEFLATED) { - strm.msg = 'unknown compression method'; - state.mode = BAD; - break; - } - if (state.flags & 0xe000) { - strm.msg = 'unknown header flags set'; - state.mode = BAD; - break; - } - if (state.head) { - state.head.text = ((hold >> 8) & 1); - } - if (state.flags & 0x0200) { - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = TIME; - /* falls through */ - case TIME: - //=== NEEDBITS(32); */ - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (state.head) { - state.head.time = hold; - } - if (state.flags & 0x0200) { - //=== CRC4(state.check, hold) - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - hbuf[2] = (hold >>> 16) & 0xff; - hbuf[3] = (hold >>> 24) & 0xff; - state.check = crc32(state.check, hbuf, 4, 0); - //=== - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = OS; - /* falls through */ - case OS: - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (state.head) { - state.head.xflags = (hold & 0xff); - state.head.os = (hold >> 8); - } - if (state.flags & 0x0200) { - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = EXLEN; - /* falls through */ - case EXLEN: - if (state.flags & 0x0400) { - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.length = hold; - if (state.head) { - state.head.extra_len = hold; - } - if (state.flags & 0x0200) { - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - } - else if (state.head) { - state.head.extra = null/*Z_NULL*/; - } - state.mode = EXTRA; - /* falls through */ - case EXTRA: - if (state.flags & 0x0400) { - copy = state.length; - if (copy > have) { copy = have; } - if (copy) { - if (state.head) { - len = state.head.extra_len - state.length; - if (!state.head.extra) { - // Use untyped array for more convenient processing later - state.head.extra = new Array(state.head.extra_len); - } - utils.arraySet( - state.head.extra, - input, - next, - // extra field is limited to 65536 bytes - // - no need for additional size check - copy, - /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/ - len - ); - //zmemcpy(state.head.extra + len, next, - // len + copy > state.head.extra_max ? - // state.head.extra_max - len : copy); - } - if (state.flags & 0x0200) { - state.check = crc32(state.check, input, copy, next); - } - have -= copy; - next += copy; - state.length -= copy; - } - if (state.length) { break inf_leave; } - } - state.length = 0; - state.mode = NAME; - /* falls through */ - case NAME: - if (state.flags & 0x0800) { - if (have === 0) { break inf_leave; } - copy = 0; - do { - // TODO: 2 or 1 bytes? - len = input[next + copy++]; - /* use constant limit because in js we should not preallocate memory */ - if (state.head && len && - (state.length < 65536 /*state.head.name_max*/)) { - state.head.name += String.fromCharCode(len); - } - } while (len && copy < have); - - if (state.flags & 0x0200) { - state.check = crc32(state.check, input, copy, next); - } - have -= copy; - next += copy; - if (len) { break inf_leave; } - } - else if (state.head) { - state.head.name = null; - } - state.length = 0; - state.mode = COMMENT; - /* falls through */ - case COMMENT: - if (state.flags & 0x1000) { - if (have === 0) { break inf_leave; } - copy = 0; - do { - len = input[next + copy++]; - /* use constant limit because in js we should not preallocate memory */ - if (state.head && len && - (state.length < 65536 /*state.head.comm_max*/)) { - state.head.comment += String.fromCharCode(len); - } - } while (len && copy < have); - if (state.flags & 0x0200) { - state.check = crc32(state.check, input, copy, next); - } - have -= copy; - next += copy; - if (len) { break inf_leave; } - } - else if (state.head) { - state.head.comment = null; - } - state.mode = HCRC; - /* falls through */ - case HCRC: - if (state.flags & 0x0200) { - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (hold !== (state.check & 0xffff)) { - strm.msg = 'header crc mismatch'; - state.mode = BAD; - break; - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - } - if (state.head) { - state.head.hcrc = ((state.flags >> 9) & 1); - state.head.done = true; - } - strm.adler = state.check = 0; - state.mode = TYPE; - break; - case DICTID: - //=== NEEDBITS(32); */ - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - strm.adler = state.check = zswap32(hold); - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = DICT; - /* falls through */ - case DICT: - if (state.havedict === 0) { - //--- RESTORE() --- - strm.next_out = put; - strm.avail_out = left; - strm.next_in = next; - strm.avail_in = have; - state.hold = hold; - state.bits = bits; - //--- - return Z_NEED_DICT; - } - strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; - state.mode = TYPE; - /* falls through */ - case TYPE: - if (flush === Z_BLOCK || flush === Z_TREES) { break inf_leave; } - /* falls through */ - case TYPEDO: - if (state.last) { - //--- BYTEBITS() ---// - hold >>>= bits & 7; - bits -= bits & 7; - //---// - state.mode = CHECK; - break; - } - //=== NEEDBITS(3); */ - while (bits < 3) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.last = (hold & 0x01)/*BITS(1)*/; - //--- DROPBITS(1) ---// - hold >>>= 1; - bits -= 1; - //---// - - switch ((hold & 0x03)/*BITS(2)*/) { - case 0: /* stored block */ - //Tracev((stderr, "inflate: stored block%s\n", - // state.last ? " (last)" : "")); - state.mode = STORED; - break; - case 1: /* fixed block */ - fixedtables(state); - //Tracev((stderr, "inflate: fixed codes block%s\n", - // state.last ? " (last)" : "")); - state.mode = LEN_; /* decode codes */ - if (flush === Z_TREES) { - //--- DROPBITS(2) ---// - hold >>>= 2; - bits -= 2; - //---// - break inf_leave; - } - break; - case 2: /* dynamic block */ - //Tracev((stderr, "inflate: dynamic codes block%s\n", - // state.last ? " (last)" : "")); - state.mode = TABLE; - break; - case 3: - strm.msg = 'invalid block type'; - state.mode = BAD; - } - //--- DROPBITS(2) ---// - hold >>>= 2; - bits -= 2; - //---// - break; - case STORED: - //--- BYTEBITS() ---// /* go to byte boundary */ - hold >>>= bits & 7; - bits -= bits & 7; - //---// - //=== NEEDBITS(32); */ - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) { - strm.msg = 'invalid stored block lengths'; - state.mode = BAD; - break; - } - state.length = hold & 0xffff; - //Tracev((stderr, "inflate: stored length %u\n", - // state.length)); - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = COPY_; - if (flush === Z_TREES) { break inf_leave; } - /* falls through */ - case COPY_: - state.mode = COPY; - /* falls through */ - case COPY: - copy = state.length; - if (copy) { - if (copy > have) { copy = have; } - if (copy > left) { copy = left; } - if (copy === 0) { break inf_leave; } - //--- zmemcpy(put, next, copy); --- - utils.arraySet(output, input, next, copy, put); - //---// - have -= copy; - next += copy; - left -= copy; - put += copy; - state.length -= copy; - break; - } - //Tracev((stderr, "inflate: stored end\n")); - state.mode = TYPE; - break; - case TABLE: - //=== NEEDBITS(14); */ - while (bits < 14) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257; - //--- DROPBITS(5) ---// - hold >>>= 5; - bits -= 5; - //---// - state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1; - //--- DROPBITS(5) ---// - hold >>>= 5; - bits -= 5; - //---// - state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4; - //--- DROPBITS(4) ---// - hold >>>= 4; - bits -= 4; - //---// -//#ifndef PKZIP_BUG_WORKAROUND - if (state.nlen > 286 || state.ndist > 30) { - strm.msg = 'too many length or distance symbols'; - state.mode = BAD; - break; - } -//#endif - //Tracev((stderr, "inflate: table sizes ok\n")); - state.have = 0; - state.mode = LENLENS; - /* falls through */ - case LENLENS: - while (state.have < state.ncode) { - //=== NEEDBITS(3); - while (bits < 3) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.lens[order[state.have++]] = (hold & 0x07);//BITS(3); - //--- DROPBITS(3) ---// - hold >>>= 3; - bits -= 3; - //---// - } - while (state.have < 19) { - state.lens[order[state.have++]] = 0; - } - // We have separate tables & no pointers. 2 commented lines below not needed. - //state.next = state.codes; - //state.lencode = state.next; - // Switch to use dynamic table - state.lencode = state.lendyn; - state.lenbits = 7; - - opts = { bits: state.lenbits }; - ret = inflate_table(CODES, state.lens, 0, 19, state.lencode, 0, state.work, opts); - state.lenbits = opts.bits; - - if (ret) { - strm.msg = 'invalid code lengths set'; - state.mode = BAD; - break; - } - //Tracev((stderr, "inflate: code lengths ok\n")); - state.have = 0; - state.mode = CODELENS; - /* falls through */ - case CODELENS: - while (state.have < state.nlen + state.ndist) { - for (;;) { - here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/ - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - if (here_val < 16) { - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - state.lens[state.have++] = here_val; - } - else { - if (here_val === 16) { - //=== NEEDBITS(here.bits + 2); - n = here_bits + 2; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - if (state.have === 0) { - strm.msg = 'invalid bit length repeat'; - state.mode = BAD; - break; - } - len = state.lens[state.have - 1]; - copy = 3 + (hold & 0x03);//BITS(2); - //--- DROPBITS(2) ---// - hold >>>= 2; - bits -= 2; - //---// - } - else if (here_val === 17) { - //=== NEEDBITS(here.bits + 3); - n = here_bits + 3; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - len = 0; - copy = 3 + (hold & 0x07);//BITS(3); - //--- DROPBITS(3) ---// - hold >>>= 3; - bits -= 3; - //---// - } - else { - //=== NEEDBITS(here.bits + 7); - n = here_bits + 7; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - len = 0; - copy = 11 + (hold & 0x7f);//BITS(7); - //--- DROPBITS(7) ---// - hold >>>= 7; - bits -= 7; - //---// - } - if (state.have + copy > state.nlen + state.ndist) { - strm.msg = 'invalid bit length repeat'; - state.mode = BAD; - break; - } - while (copy--) { - state.lens[state.have++] = len; - } - } - } - - /* handle error breaks in while */ - if (state.mode === BAD) { break; } - - /* check for end-of-block code (better have one) */ - if (state.lens[256] === 0) { - strm.msg = 'invalid code -- missing end-of-block'; - state.mode = BAD; - break; - } - - /* build code tables -- note: do not change the lenbits or distbits - values here (9 and 6) without reading the comments in inftrees.h - concerning the ENOUGH constants, which depend on those values */ - state.lenbits = 9; - - opts = { bits: state.lenbits }; - ret = inflate_table(LENS, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts); - // We have separate tables & no pointers. 2 commented lines below not needed. - // state.next_index = opts.table_index; - state.lenbits = opts.bits; - // state.lencode = state.next; - - if (ret) { - strm.msg = 'invalid literal/lengths set'; - state.mode = BAD; - break; - } - - state.distbits = 6; - //state.distcode.copy(state.codes); - // Switch to use dynamic table - state.distcode = state.distdyn; - opts = { bits: state.distbits }; - ret = inflate_table(DISTS, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts); - // We have separate tables & no pointers. 2 commented lines below not needed. - // state.next_index = opts.table_index; - state.distbits = opts.bits; - // state.distcode = state.next; - - if (ret) { - strm.msg = 'invalid distances set'; - state.mode = BAD; - break; - } - //Tracev((stderr, 'inflate: codes ok\n')); - state.mode = LEN_; - if (flush === Z_TREES) { break inf_leave; } - /* falls through */ - case LEN_: - state.mode = LEN; - /* falls through */ - case LEN: - if (have >= 6 && left >= 258) { - //--- RESTORE() --- - strm.next_out = put; - strm.avail_out = left; - strm.next_in = next; - strm.avail_in = have; - state.hold = hold; - state.bits = bits; - //--- - inflate_fast(strm, _out); - //--- LOAD() --- - put = strm.next_out; - output = strm.output; - left = strm.avail_out; - next = strm.next_in; - input = strm.input; - have = strm.avail_in; - hold = state.hold; - bits = state.bits; - //--- - - if (state.mode === TYPE) { - state.back = -1; - } - break; - } - state.back = 0; - for (;;) { - here = state.lencode[hold & ((1 << state.lenbits) - 1)]; /*BITS(state.lenbits)*/ - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if (here_bits <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - if (here_op && (here_op & 0xf0) === 0) { - last_bits = here_bits; - last_op = here_op; - last_val = here_val; - for (;;) { - here = state.lencode[last_val + - ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((last_bits + here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - //--- DROPBITS(last.bits) ---// - hold >>>= last_bits; - bits -= last_bits; - //---// - state.back += last_bits; - } - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - state.back += here_bits; - state.length = here_val; - if (here_op === 0) { - //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - // "inflate: literal '%c'\n" : - // "inflate: literal 0x%02x\n", here.val)); - state.mode = LIT; - break; - } - if (here_op & 32) { - //Tracevv((stderr, "inflate: end of block\n")); - state.back = -1; - state.mode = TYPE; - break; - } - if (here_op & 64) { - strm.msg = 'invalid literal/length code'; - state.mode = BAD; - break; - } - state.extra = here_op & 15; - state.mode = LENEXT; - /* falls through */ - case LENEXT: - if (state.extra) { - //=== NEEDBITS(state.extra); - n = state.extra; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.length += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; - //--- DROPBITS(state.extra) ---// - hold >>>= state.extra; - bits -= state.extra; - //---// - state.back += state.extra; - } - //Tracevv((stderr, "inflate: length %u\n", state.length)); - state.was = state.length; - state.mode = DIST; - /* falls through */ - case DIST: - for (;;) { - here = state.distcode[hold & ((1 << state.distbits) - 1)];/*BITS(state.distbits)*/ - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - if ((here_op & 0xf0) === 0) { - last_bits = here_bits; - last_op = here_op; - last_val = here_val; - for (;;) { - here = state.distcode[last_val + - ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((last_bits + here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - //--- DROPBITS(last.bits) ---// - hold >>>= last_bits; - bits -= last_bits; - //---// - state.back += last_bits; - } - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - state.back += here_bits; - if (here_op & 64) { - strm.msg = 'invalid distance code'; - state.mode = BAD; - break; - } - state.offset = here_val; - state.extra = (here_op) & 15; - state.mode = DISTEXT; - /* falls through */ - case DISTEXT: - if (state.extra) { - //=== NEEDBITS(state.extra); - n = state.extra; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.offset += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; - //--- DROPBITS(state.extra) ---// - hold >>>= state.extra; - bits -= state.extra; - //---// - state.back += state.extra; - } -//#ifdef INFLATE_STRICT - if (state.offset > state.dmax) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD; - break; - } -//#endif - //Tracevv((stderr, "inflate: distance %u\n", state.offset)); - state.mode = MATCH; - /* falls through */ - case MATCH: - if (left === 0) { break inf_leave; } - copy = _out - left; - if (state.offset > copy) { /* copy from window */ - copy = state.offset - copy; - if (copy > state.whave) { - if (state.sane) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD; - break; - } -// (!) This block is disabled in zlib defaults, -// don't enable it for binary compatibility -//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR -// Trace((stderr, "inflate.c too far\n")); -// copy -= state.whave; -// if (copy > state.length) { copy = state.length; } -// if (copy > left) { copy = left; } -// left -= copy; -// state.length -= copy; -// do { -// output[put++] = 0; -// } while (--copy); -// if (state.length === 0) { state.mode = LEN; } -// break; -//#endif - } - if (copy > state.wnext) { - copy -= state.wnext; - from = state.wsize - copy; - } - else { - from = state.wnext - copy; - } - if (copy > state.length) { copy = state.length; } - from_source = state.window; - } - else { /* copy from output */ - from_source = output; - from = put - state.offset; - copy = state.length; - } - if (copy > left) { copy = left; } - left -= copy; - state.length -= copy; - do { - output[put++] = from_source[from++]; - } while (--copy); - if (state.length === 0) { state.mode = LEN; } - break; - case LIT: - if (left === 0) { break inf_leave; } - output[put++] = state.length; - left--; - state.mode = LEN; - break; - case CHECK: - if (state.wrap) { - //=== NEEDBITS(32); - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - // Use '|' instead of '+' to make sure that result is signed - hold |= input[next++] << bits; - bits += 8; - } - //===// - _out -= left; - strm.total_out += _out; - state.total += _out; - if (_out) { - strm.adler = state.check = - /*UPDATE(state.check, put - _out, _out);*/ - (state.flags ? crc32(state.check, output, _out, put - _out) : adler32(state.check, output, _out, put - _out)); - - } - _out = left; - // NB: crc32 stored as signed 32-bit int, zswap32 returns signed too - if ((state.flags ? hold : zswap32(hold)) !== state.check) { - strm.msg = 'incorrect data check'; - state.mode = BAD; - break; - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - //Tracev((stderr, "inflate: check matches trailer\n")); - } - state.mode = LENGTH; - /* falls through */ - case LENGTH: - if (state.wrap && state.flags) { - //=== NEEDBITS(32); - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (hold !== (state.total & 0xffffffff)) { - strm.msg = 'incorrect length check'; - state.mode = BAD; - break; - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - //Tracev((stderr, "inflate: length matches trailer\n")); - } - state.mode = DONE; - /* falls through */ - case DONE: - ret = Z_STREAM_END; - break inf_leave; - case BAD: - ret = Z_DATA_ERROR; - break inf_leave; - case MEM: - return Z_MEM_ERROR; - case SYNC: - /* falls through */ - default: - return Z_STREAM_ERROR; - } - } - - // inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave" - - /* - Return from inflate(), updating the total counts and the check value. - If there was no progress during the inflate() call, return a buffer - error. Call updatewindow() to create and/or update the window state. - Note: a memory error from inflate() is non-recoverable. - */ - - //--- RESTORE() --- - strm.next_out = put; - strm.avail_out = left; - strm.next_in = next; - strm.avail_in = have; - state.hold = hold; - state.bits = bits; - //--- - - if (state.wsize || (_out !== strm.avail_out && state.mode < BAD && - (state.mode < CHECK || flush !== Z_FINISH))) { - if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) { - state.mode = MEM; - return Z_MEM_ERROR; - } - } - _in -= strm.avail_in; - _out -= strm.avail_out; - strm.total_in += _in; - strm.total_out += _out; - state.total += _out; - if (state.wrap && _out) { - strm.adler = state.check = /*UPDATE(state.check, strm.next_out - _out, _out);*/ - (state.flags ? crc32(state.check, output, _out, strm.next_out - _out) : adler32(state.check, output, _out, strm.next_out - _out)); - } - strm.data_type = state.bits + (state.last ? 64 : 0) + - (state.mode === TYPE ? 128 : 0) + - (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0); - if (((_in === 0 && _out === 0) || flush === Z_FINISH) && ret === Z_OK) { - ret = Z_BUF_ERROR; - } - return ret; -} - -function inflateEnd(strm) { - - if (!strm || !strm.state /*|| strm->zfree == (free_func)0*/) { - return Z_STREAM_ERROR; - } - - var state = strm.state; - if (state.window) { - state.window = null; - } - strm.state = null; - return Z_OK; -} - -function inflateGetHeader(strm, head) { - var state; - - /* check state */ - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR; } - - /* save header structure */ - state.head = head; - head.done = false; - return Z_OK; -} - -function inflateSetDictionary(strm, dictionary) { - var dictLength = dictionary.length; - - var state; - var dictid; - var ret; - - /* check state */ - if (!strm /* == Z_NULL */ || !strm.state /* == Z_NULL */) { return Z_STREAM_ERROR; } - state = strm.state; - - if (state.wrap !== 0 && state.mode !== DICT) { - return Z_STREAM_ERROR; - } - - /* check for correct dictionary identifier */ - if (state.mode === DICT) { - dictid = 1; /* adler32(0, null, 0)*/ - /* dictid = adler32(dictid, dictionary, dictLength); */ - dictid = adler32(dictid, dictionary, dictLength, 0); - if (dictid !== state.check) { - return Z_DATA_ERROR; - } - } - /* copy dictionary to window using updatewindow(), which will amend the - existing dictionary if appropriate */ - ret = updatewindow(strm, dictionary, dictLength, dictLength); - if (ret) { - state.mode = MEM; - return Z_MEM_ERROR; - } - state.havedict = 1; - // Tracev((stderr, "inflate: dictionary set\n")); - return Z_OK; -} - -exports.inflateReset = inflateReset; -exports.inflateReset2 = inflateReset2; -exports.inflateResetKeep = inflateResetKeep; -exports.inflateInit = inflateInit; -exports.inflateInit2 = inflateInit2; -exports.inflate = inflate; -exports.inflateEnd = inflateEnd; -exports.inflateGetHeader = inflateGetHeader; -exports.inflateSetDictionary = inflateSetDictionary; -exports.inflateInfo = 'pako inflate (from Nodeca project)'; - -/* Not implemented -exports.inflateCopy = inflateCopy; -exports.inflateGetDictionary = inflateGetDictionary; -exports.inflateMark = inflateMark; -exports.inflatePrime = inflatePrime; -exports.inflateSync = inflateSync; -exports.inflateSyncPoint = inflateSyncPoint; -exports.inflateUndermine = inflateUndermine; -*/ - -},{"../utils/common":53,"./adler32":55,"./crc32":57,"./inffast":60,"./inftrees":62}],62:[function(require,module,exports){ -'use strict'; - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -var utils = require('../utils/common'); - -var MAXBITS = 15; -var ENOUGH_LENS = 852; -var ENOUGH_DISTS = 592; -//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); - -var CODES = 0; -var LENS = 1; -var DISTS = 2; - -var lbase = [ /* Length codes 257..285 base */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 -]; - -var lext = [ /* Length codes 257..285 extra */ - 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78 -]; - -var dbase = [ /* Distance codes 0..29 base */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577, 0, 0 -]; - -var dext = [ /* Distance codes 0..29 extra */ - 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, - 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, - 28, 28, 29, 29, 64, 64 -]; - -module.exports = function inflate_table(type, lens, lens_index, codes, table, table_index, work, opts) -{ - var bits = opts.bits; - //here = opts.here; /* table entry for duplication */ - - var len = 0; /* a code's length in bits */ - var sym = 0; /* index of code symbols */ - var min = 0, max = 0; /* minimum and maximum code lengths */ - var root = 0; /* number of index bits for root table */ - var curr = 0; /* number of index bits for current table */ - var drop = 0; /* code bits to drop for sub-table */ - var left = 0; /* number of prefix codes available */ - var used = 0; /* code entries in table used */ - var huff = 0; /* Huffman code */ - var incr; /* for incrementing code, index */ - var fill; /* index for replicating entries */ - var low; /* low bits for current root entry */ - var mask; /* mask for low root bits */ - var next; /* next available space in table */ - var base = null; /* base value table to use */ - var base_index = 0; -// var shoextra; /* extra bits table to use */ - var end; /* use base and extra for symbol > end */ - var count = new utils.Buf16(MAXBITS + 1); //[MAXBITS+1]; /* number of codes of each length */ - var offs = new utils.Buf16(MAXBITS + 1); //[MAXBITS+1]; /* offsets in table for each length */ - var extra = null; - var extra_index = 0; - - var here_bits, here_op, here_val; - - /* - Process a set of code lengths to create a canonical Huffman code. The - code lengths are lens[0..codes-1]. Each length corresponds to the - symbols 0..codes-1. The Huffman code is generated by first sorting the - symbols by length from short to long, and retaining the symbol order - for codes with equal lengths. Then the code starts with all zero bits - for the first code of the shortest length, and the codes are integer - increments for the same length, and zeros are appended as the length - increases. For the deflate format, these bits are stored backwards - from their more natural integer increment ordering, and so when the - decoding tables are built in the large loop below, the integer codes - are incremented backwards. - - This routine assumes, but does not check, that all of the entries in - lens[] are in the range 0..MAXBITS. The caller must assure this. - 1..MAXBITS is interpreted as that code length. zero means that that - symbol does not occur in this code. - - The codes are sorted by computing a count of codes for each length, - creating from that a table of starting indices for each length in the - sorted table, and then entering the symbols in order in the sorted - table. The sorted table is work[], with that space being provided by - the caller. - - The length counts are used for other purposes as well, i.e. finding - the minimum and maximum length codes, determining if there are any - codes at all, checking for a valid set of lengths, and looking ahead - at length counts to determine sub-table sizes when building the - decoding tables. - */ - - /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ - for (len = 0; len <= MAXBITS; len++) { - count[len] = 0; - } - for (sym = 0; sym < codes; sym++) { - count[lens[lens_index + sym]]++; - } - - /* bound code lengths, force root to be within code lengths */ - root = bits; - for (max = MAXBITS; max >= 1; max--) { - if (count[max] !== 0) { break; } - } - if (root > max) { - root = max; - } - if (max === 0) { /* no symbols to code at all */ - //table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */ - //table.bits[opts.table_index] = 1; //here.bits = (var char)1; - //table.val[opts.table_index++] = 0; //here.val = (var short)0; - table[table_index++] = (1 << 24) | (64 << 16) | 0; - - - //table.op[opts.table_index] = 64; - //table.bits[opts.table_index] = 1; - //table.val[opts.table_index++] = 0; - table[table_index++] = (1 << 24) | (64 << 16) | 0; - - opts.bits = 1; - return 0; /* no symbols, but wait for decoding to report error */ - } - for (min = 1; min < max; min++) { - if (count[min] !== 0) { break; } - } - if (root < min) { - root = min; - } - - /* check for an over-subscribed or incomplete set of lengths */ - left = 1; - for (len = 1; len <= MAXBITS; len++) { - left <<= 1; - left -= count[len]; - if (left < 0) { - return -1; - } /* over-subscribed */ - } - if (left > 0 && (type === CODES || max !== 1)) { - return -1; /* incomplete set */ - } - - /* generate offsets into symbol table for each length for sorting */ - offs[1] = 0; - for (len = 1; len < MAXBITS; len++) { - offs[len + 1] = offs[len] + count[len]; - } - - /* sort symbols by length, by symbol order within each length */ - for (sym = 0; sym < codes; sym++) { - if (lens[lens_index + sym] !== 0) { - work[offs[lens[lens_index + sym]]++] = sym; - } - } - - /* - Create and fill in decoding tables. In this loop, the table being - filled is at next and has curr index bits. The code being used is huff - with length len. That code is converted to an index by dropping drop - bits off of the bottom. For codes where len is less than drop + curr, - those top drop + curr - len bits are incremented through all values to - fill the table with replicated entries. - - root is the number of index bits for the root table. When len exceeds - root, sub-tables are created pointed to by the root entry with an index - of the low root bits of huff. This is saved in low to check for when a - new sub-table should be started. drop is zero when the root table is - being filled, and drop is root when sub-tables are being filled. - - When a new sub-table is needed, it is necessary to look ahead in the - code lengths to determine what size sub-table is needed. The length - counts are used for this, and so count[] is decremented as codes are - entered in the tables. - - used keeps track of how many table entries have been allocated from the - provided *table space. It is checked for LENS and DIST tables against - the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in - the initial root table size constants. See the comments in inftrees.h - for more information. - - sym increments through all symbols, and the loop terminates when - all codes of length max, i.e. all codes, have been processed. This - routine permits incomplete codes, so another loop after this one fills - in the rest of the decoding tables with invalid code markers. - */ - - /* set up for code type */ - // poor man optimization - use if-else instead of switch, - // to avoid deopts in old v8 - if (type === CODES) { - base = extra = work; /* dummy value--not used */ - end = 19; - - } else if (type === LENS) { - base = lbase; - base_index -= 257; - extra = lext; - extra_index -= 257; - end = 256; - - } else { /* DISTS */ - base = dbase; - extra = dext; - end = -1; - } - - /* initialize opts for loop */ - huff = 0; /* starting code */ - sym = 0; /* starting code symbol */ - len = min; /* starting code length */ - next = table_index; /* current table to fill in */ - curr = root; /* current table index bits */ - drop = 0; /* current bits to drop from code for index */ - low = -1; /* trigger new sub-table when len > root */ - used = 1 << root; /* use root table entries */ - mask = used - 1; /* mask for comparing low */ - - /* check available table space */ - if ((type === LENS && used > ENOUGH_LENS) || - (type === DISTS && used > ENOUGH_DISTS)) { - return 1; - } - - /* process all codes and make table entries */ - for (;;) { - /* create table entry */ - here_bits = len - drop; - if (work[sym] < end) { - here_op = 0; - here_val = work[sym]; - } - else if (work[sym] > end) { - here_op = extra[extra_index + work[sym]]; - here_val = base[base_index + work[sym]]; - } - else { - here_op = 32 + 64; /* end of block */ - here_val = 0; - } - - /* replicate for those indices with low len bits equal to huff */ - incr = 1 << (len - drop); - fill = 1 << curr; - min = fill; /* save offset to next table */ - do { - fill -= incr; - table[next + (huff >> drop) + fill] = (here_bits << 24) | (here_op << 16) | here_val |0; - } while (fill !== 0); - - /* backwards increment the len-bit code huff */ - incr = 1 << (len - 1); - while (huff & incr) { - incr >>= 1; - } - if (incr !== 0) { - huff &= incr - 1; - huff += incr; - } else { - huff = 0; - } - - /* go to next symbol, update count, len */ - sym++; - if (--count[len] === 0) { - if (len === max) { break; } - len = lens[lens_index + work[sym]]; - } - - /* create new sub-table if needed */ - if (len > root && (huff & mask) !== low) { - /* if first time, transition to sub-tables */ - if (drop === 0) { - drop = root; - } - - /* increment past last table */ - next += min; /* here min is 1 << curr */ - - /* determine length of next table */ - curr = len - drop; - left = 1 << curr; - while (curr + drop < max) { - left -= count[curr + drop]; - if (left <= 0) { break; } - curr++; - left <<= 1; - } - - /* check for enough space */ - used += 1 << curr; - if ((type === LENS && used > ENOUGH_LENS) || - (type === DISTS && used > ENOUGH_DISTS)) { - return 1; - } - - /* point entry in root table to sub-table */ - low = huff & mask; - /*table.op[low] = curr; - table.bits[low] = root; - table.val[low] = next - opts.table_index;*/ - table[low] = (root << 24) | (curr << 16) | (next - table_index) |0; - } - } - - /* fill in remaining table entry if code is incomplete (guaranteed to have - at most one remaining entry, since if the code is incomplete, the - maximum code length that was allowed to get this far is one bit) */ - if (huff !== 0) { - //table.op[next + huff] = 64; /* invalid code marker */ - //table.bits[next + huff] = len - drop; - //table.val[next + huff] = 0; - table[next + huff] = ((len - drop) << 24) | (64 << 16) |0; - } - - /* set return parameters */ - //opts.table_index += used; - opts.bits = root; - return 0; -}; - -},{"../utils/common":53}],63:[function(require,module,exports){ -'use strict'; - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -module.exports = { - 2: 'need dictionary', /* Z_NEED_DICT 2 */ - 1: 'stream end', /* Z_STREAM_END 1 */ - 0: '', /* Z_OK 0 */ - '-1': 'file error', /* Z_ERRNO (-1) */ - '-2': 'stream error', /* Z_STREAM_ERROR (-2) */ - '-3': 'data error', /* Z_DATA_ERROR (-3) */ - '-4': 'insufficient memory', /* Z_MEM_ERROR (-4) */ - '-5': 'buffer error', /* Z_BUF_ERROR (-5) */ - '-6': 'incompatible version' /* Z_VERSION_ERROR (-6) */ -}; - -},{}],64:[function(require,module,exports){ -'use strict'; - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -var utils = require('../utils/common'); - -/* Public constants ==========================================================*/ -/* ===========================================================================*/ - - -//var Z_FILTERED = 1; -//var Z_HUFFMAN_ONLY = 2; -//var Z_RLE = 3; -var Z_FIXED = 4; -//var Z_DEFAULT_STRATEGY = 0; - -/* Possible values of the data_type field (though see inflate()) */ -var Z_BINARY = 0; -var Z_TEXT = 1; -//var Z_ASCII = 1; // = Z_TEXT -var Z_UNKNOWN = 2; - -/*============================================================================*/ - - -function zero(buf) { var len = buf.length; while (--len >= 0) { buf[len] = 0; } } - -// From zutil.h - -var STORED_BLOCK = 0; -var STATIC_TREES = 1; -var DYN_TREES = 2; -/* The three kinds of block type */ - -var MIN_MATCH = 3; -var MAX_MATCH = 258; -/* The minimum and maximum match lengths */ - -// From deflate.h -/* =========================================================================== - * Internal compression state. - */ - -var LENGTH_CODES = 29; -/* number of length codes, not counting the special END_BLOCK code */ - -var LITERALS = 256; -/* number of literal bytes 0..255 */ - -var L_CODES = LITERALS + 1 + LENGTH_CODES; -/* number of Literal or Length codes, including the END_BLOCK code */ - -var D_CODES = 30; -/* number of distance codes */ - -var BL_CODES = 19; -/* number of codes used to transfer the bit lengths */ - -var HEAP_SIZE = 2 * L_CODES + 1; -/* maximum heap size */ - -var MAX_BITS = 15; -/* All codes must not exceed MAX_BITS bits */ - -var Buf_size = 16; -/* size of bit buffer in bi_buf */ - - -/* =========================================================================== - * Constants - */ - -var MAX_BL_BITS = 7; -/* Bit length codes must not exceed MAX_BL_BITS bits */ - -var END_BLOCK = 256; -/* end of block literal code */ - -var REP_3_6 = 16; -/* repeat previous bit length 3-6 times (2 bits of repeat count) */ - -var REPZ_3_10 = 17; -/* repeat a zero length 3-10 times (3 bits of repeat count) */ - -var REPZ_11_138 = 18; -/* repeat a zero length 11-138 times (7 bits of repeat count) */ - -/* eslint-disable comma-spacing,array-bracket-spacing */ -var extra_lbits = /* extra bits for each length code */ - [0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0]; - -var extra_dbits = /* extra bits for each distance code */ - [0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13]; - -var extra_blbits = /* extra bits for each bit length code */ - [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7]; - -var bl_order = - [16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]; -/* eslint-enable comma-spacing,array-bracket-spacing */ - -/* The lengths of the bit length codes are sent in order of decreasing - * probability, to avoid transmitting the lengths for unused bit length codes. - */ - -/* =========================================================================== - * Local data. These are initialized only once. - */ - -// We pre-fill arrays with 0 to avoid uninitialized gaps - -var DIST_CODE_LEN = 512; /* see definition of array dist_code below */ - -// !!!! Use flat array instead of structure, Freq = i*2, Len = i*2+1 -var static_ltree = new Array((L_CODES + 2) * 2); -zero(static_ltree); -/* The static literal tree. Since the bit lengths are imposed, there is no - * need for the L_CODES extra codes used during heap construction. However - * The codes 286 and 287 are needed to build a canonical tree (see _tr_init - * below). - */ - -var static_dtree = new Array(D_CODES * 2); -zero(static_dtree); -/* The static distance tree. (Actually a trivial tree since all codes use - * 5 bits.) - */ - -var _dist_code = new Array(DIST_CODE_LEN); -zero(_dist_code); -/* Distance codes. The first 256 values correspond to the distances - * 3 .. 258, the last 256 values correspond to the top 8 bits of - * the 15 bit distances. - */ - -var _length_code = new Array(MAX_MATCH - MIN_MATCH + 1); -zero(_length_code); -/* length code for each normalized match length (0 == MIN_MATCH) */ - -var base_length = new Array(LENGTH_CODES); -zero(base_length); -/* First normalized length for each code (0 = MIN_MATCH) */ - -var base_dist = new Array(D_CODES); -zero(base_dist); -/* First normalized distance for each code (0 = distance of 1) */ - - -function StaticTreeDesc(static_tree, extra_bits, extra_base, elems, max_length) { - - this.static_tree = static_tree; /* static tree or NULL */ - this.extra_bits = extra_bits; /* extra bits for each code or NULL */ - this.extra_base = extra_base; /* base index for extra_bits */ - this.elems = elems; /* max number of elements in the tree */ - this.max_length = max_length; /* max bit length for the codes */ - - // show if `static_tree` has data or dummy - needed for monomorphic objects - this.has_stree = static_tree && static_tree.length; -} - - -var static_l_desc; -var static_d_desc; -var static_bl_desc; - - -function TreeDesc(dyn_tree, stat_desc) { - this.dyn_tree = dyn_tree; /* the dynamic tree */ - this.max_code = 0; /* largest code with non zero frequency */ - this.stat_desc = stat_desc; /* the corresponding static tree */ -} - - - -function d_code(dist) { - return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)]; -} - - -/* =========================================================================== - * Output a short LSB first on the stream. - * IN assertion: there is enough room in pendingBuf. - */ -function put_short(s, w) { -// put_byte(s, (uch)((w) & 0xff)); -// put_byte(s, (uch)((ush)(w) >> 8)); - s.pending_buf[s.pending++] = (w) & 0xff; - s.pending_buf[s.pending++] = (w >>> 8) & 0xff; -} - - -/* =========================================================================== - * Send a value on a given number of bits. - * IN assertion: length <= 16 and value fits in length bits. - */ -function send_bits(s, value, length) { - if (s.bi_valid > (Buf_size - length)) { - s.bi_buf |= (value << s.bi_valid) & 0xffff; - put_short(s, s.bi_buf); - s.bi_buf = value >> (Buf_size - s.bi_valid); - s.bi_valid += length - Buf_size; - } else { - s.bi_buf |= (value << s.bi_valid) & 0xffff; - s.bi_valid += length; - } -} - - -function send_code(s, c, tree) { - send_bits(s, tree[c * 2]/*.Code*/, tree[c * 2 + 1]/*.Len*/); -} - - -/* =========================================================================== - * Reverse the first len bits of a code, using straightforward code (a faster - * method would use a table) - * IN assertion: 1 <= len <= 15 - */ -function bi_reverse(code, len) { - var res = 0; - do { - res |= code & 1; - code >>>= 1; - res <<= 1; - } while (--len > 0); - return res >>> 1; -} - - -/* =========================================================================== - * Flush the bit buffer, keeping at most 7 bits in it. - */ -function bi_flush(s) { - if (s.bi_valid === 16) { - put_short(s, s.bi_buf); - s.bi_buf = 0; - s.bi_valid = 0; - - } else if (s.bi_valid >= 8) { - s.pending_buf[s.pending++] = s.bi_buf & 0xff; - s.bi_buf >>= 8; - s.bi_valid -= 8; - } -} - - -/* =========================================================================== - * Compute the optimal bit lengths for a tree and update the total bit length - * for the current block. - * IN assertion: the fields freq and dad are set, heap[heap_max] and - * above are the tree nodes sorted by increasing frequency. - * OUT assertions: the field len is set to the optimal bit length, the - * array bl_count contains the frequencies for each bit length. - * The length opt_len is updated; static_len is also updated if stree is - * not null. - */ -function gen_bitlen(s, desc) -// deflate_state *s; -// tree_desc *desc; /* the tree descriptor */ -{ - var tree = desc.dyn_tree; - var max_code = desc.max_code; - var stree = desc.stat_desc.static_tree; - var has_stree = desc.stat_desc.has_stree; - var extra = desc.stat_desc.extra_bits; - var base = desc.stat_desc.extra_base; - var max_length = desc.stat_desc.max_length; - var h; /* heap index */ - var n, m; /* iterate over the tree elements */ - var bits; /* bit length */ - var xbits; /* extra bits */ - var f; /* frequency */ - var overflow = 0; /* number of elements with bit length too large */ - - for (bits = 0; bits <= MAX_BITS; bits++) { - s.bl_count[bits] = 0; - } - - /* In a first pass, compute the optimal bit lengths (which may - * overflow in the case of the bit length tree). - */ - tree[s.heap[s.heap_max] * 2 + 1]/*.Len*/ = 0; /* root of the heap */ - - for (h = s.heap_max + 1; h < HEAP_SIZE; h++) { - n = s.heap[h]; - bits = tree[tree[n * 2 + 1]/*.Dad*/ * 2 + 1]/*.Len*/ + 1; - if (bits > max_length) { - bits = max_length; - overflow++; - } - tree[n * 2 + 1]/*.Len*/ = bits; - /* We overwrite tree[n].Dad which is no longer needed */ - - if (n > max_code) { continue; } /* not a leaf node */ - - s.bl_count[bits]++; - xbits = 0; - if (n >= base) { - xbits = extra[n - base]; - } - f = tree[n * 2]/*.Freq*/; - s.opt_len += f * (bits + xbits); - if (has_stree) { - s.static_len += f * (stree[n * 2 + 1]/*.Len*/ + xbits); - } - } - if (overflow === 0) { return; } - - // Trace((stderr,"\nbit length overflow\n")); - /* This happens for example on obj2 and pic of the Calgary corpus */ - - /* Find the first bit length which could increase: */ - do { - bits = max_length - 1; - while (s.bl_count[bits] === 0) { bits--; } - s.bl_count[bits]--; /* move one leaf down the tree */ - s.bl_count[bits + 1] += 2; /* move one overflow item as its brother */ - s.bl_count[max_length]--; - /* The brother of the overflow item also moves one step up, - * but this does not affect bl_count[max_length] - */ - overflow -= 2; - } while (overflow > 0); - - /* Now recompute all bit lengths, scanning in increasing frequency. - * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all - * lengths instead of fixing only the wrong ones. This idea is taken - * from 'ar' written by Haruhiko Okumura.) - */ - for (bits = max_length; bits !== 0; bits--) { - n = s.bl_count[bits]; - while (n !== 0) { - m = s.heap[--h]; - if (m > max_code) { continue; } - if (tree[m * 2 + 1]/*.Len*/ !== bits) { - // Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); - s.opt_len += (bits - tree[m * 2 + 1]/*.Len*/) * tree[m * 2]/*.Freq*/; - tree[m * 2 + 1]/*.Len*/ = bits; - } - n--; - } - } -} - - -/* =========================================================================== - * Generate the codes for a given tree and bit counts (which need not be - * optimal). - * IN assertion: the array bl_count contains the bit length statistics for - * the given tree and the field len is set for all tree elements. - * OUT assertion: the field code is set for all tree elements of non - * zero code length. - */ -function gen_codes(tree, max_code, bl_count) -// ct_data *tree; /* the tree to decorate */ -// int max_code; /* largest code with non zero frequency */ -// ushf *bl_count; /* number of codes at each bit length */ -{ - var next_code = new Array(MAX_BITS + 1); /* next code value for each bit length */ - var code = 0; /* running code value */ - var bits; /* bit index */ - var n; /* code index */ - - /* The distribution counts are first used to generate the code values - * without bit reversal. - */ - for (bits = 1; bits <= MAX_BITS; bits++) { - next_code[bits] = code = (code + bl_count[bits - 1]) << 1; - } - /* Check that the bit counts in bl_count are consistent. The last code - * must be all ones. - */ - //Assert (code + bl_count[MAX_BITS]-1 == (1< length code (0..28) */ - length = 0; - for (code = 0; code < LENGTH_CODES - 1; code++) { - base_length[code] = length; - for (n = 0; n < (1 << extra_lbits[code]); n++) { - _length_code[length++] = code; - } - } - //Assert (length == 256, "tr_static_init: length != 256"); - /* Note that the length 255 (match length 258) can be represented - * in two different ways: code 284 + 5 bits or code 285, so we - * overwrite length_code[255] to use the best encoding: - */ - _length_code[length - 1] = code; - - /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ - dist = 0; - for (code = 0; code < 16; code++) { - base_dist[code] = dist; - for (n = 0; n < (1 << extra_dbits[code]); n++) { - _dist_code[dist++] = code; - } - } - //Assert (dist == 256, "tr_static_init: dist != 256"); - dist >>= 7; /* from now on, all distances are divided by 128 */ - for (; code < D_CODES; code++) { - base_dist[code] = dist << 7; - for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) { - _dist_code[256 + dist++] = code; - } - } - //Assert (dist == 256, "tr_static_init: 256+dist != 512"); - - /* Construct the codes of the static literal tree */ - for (bits = 0; bits <= MAX_BITS; bits++) { - bl_count[bits] = 0; - } - - n = 0; - while (n <= 143) { - static_ltree[n * 2 + 1]/*.Len*/ = 8; - n++; - bl_count[8]++; - } - while (n <= 255) { - static_ltree[n * 2 + 1]/*.Len*/ = 9; - n++; - bl_count[9]++; - } - while (n <= 279) { - static_ltree[n * 2 + 1]/*.Len*/ = 7; - n++; - bl_count[7]++; - } - while (n <= 287) { - static_ltree[n * 2 + 1]/*.Len*/ = 8; - n++; - bl_count[8]++; - } - /* Codes 286 and 287 do not exist, but we must include them in the - * tree construction to get a canonical Huffman tree (longest code - * all ones) - */ - gen_codes(static_ltree, L_CODES + 1, bl_count); - - /* The static distance tree is trivial: */ - for (n = 0; n < D_CODES; n++) { - static_dtree[n * 2 + 1]/*.Len*/ = 5; - static_dtree[n * 2]/*.Code*/ = bi_reverse(n, 5); - } - - // Now data ready and we can init static trees - static_l_desc = new StaticTreeDesc(static_ltree, extra_lbits, LITERALS + 1, L_CODES, MAX_BITS); - static_d_desc = new StaticTreeDesc(static_dtree, extra_dbits, 0, D_CODES, MAX_BITS); - static_bl_desc = new StaticTreeDesc(new Array(0), extra_blbits, 0, BL_CODES, MAX_BL_BITS); - - //static_init_done = true; -} - - -/* =========================================================================== - * Initialize a new block. - */ -function init_block(s) { - var n; /* iterates over tree elements */ - - /* Initialize the trees. */ - for (n = 0; n < L_CODES; n++) { s.dyn_ltree[n * 2]/*.Freq*/ = 0; } - for (n = 0; n < D_CODES; n++) { s.dyn_dtree[n * 2]/*.Freq*/ = 0; } - for (n = 0; n < BL_CODES; n++) { s.bl_tree[n * 2]/*.Freq*/ = 0; } - - s.dyn_ltree[END_BLOCK * 2]/*.Freq*/ = 1; - s.opt_len = s.static_len = 0; - s.last_lit = s.matches = 0; -} - - -/* =========================================================================== - * Flush the bit buffer and align the output on a byte boundary - */ -function bi_windup(s) -{ - if (s.bi_valid > 8) { - put_short(s, s.bi_buf); - } else if (s.bi_valid > 0) { - //put_byte(s, (Byte)s->bi_buf); - s.pending_buf[s.pending++] = s.bi_buf; - } - s.bi_buf = 0; - s.bi_valid = 0; -} - -/* =========================================================================== - * Copy a stored block, storing first the length and its - * one's complement if requested. - */ -function copy_block(s, buf, len, header) -//DeflateState *s; -//charf *buf; /* the input data */ -//unsigned len; /* its length */ -//int header; /* true if block header must be written */ -{ - bi_windup(s); /* align on byte boundary */ - - if (header) { - put_short(s, len); - put_short(s, ~len); - } -// while (len--) { -// put_byte(s, *buf++); -// } - utils.arraySet(s.pending_buf, s.window, buf, len, s.pending); - s.pending += len; -} - -/* =========================================================================== - * Compares to subtrees, using the tree depth as tie breaker when - * the subtrees have equal frequency. This minimizes the worst case length. - */ -function smaller(tree, n, m, depth) { - var _n2 = n * 2; - var _m2 = m * 2; - return (tree[_n2]/*.Freq*/ < tree[_m2]/*.Freq*/ || - (tree[_n2]/*.Freq*/ === tree[_m2]/*.Freq*/ && depth[n] <= depth[m])); -} - -/* =========================================================================== - * Restore the heap property by moving down the tree starting at node k, - * exchanging a node with the smallest of its two sons if necessary, stopping - * when the heap property is re-established (each father smaller than its - * two sons). - */ -function pqdownheap(s, tree, k) -// deflate_state *s; -// ct_data *tree; /* the tree to restore */ -// int k; /* node to move down */ -{ - var v = s.heap[k]; - var j = k << 1; /* left son of k */ - while (j <= s.heap_len) { - /* Set j to the smallest of the two sons: */ - if (j < s.heap_len && - smaller(tree, s.heap[j + 1], s.heap[j], s.depth)) { - j++; - } - /* Exit if v is smaller than both sons */ - if (smaller(tree, v, s.heap[j], s.depth)) { break; } - - /* Exchange v with the smallest son */ - s.heap[k] = s.heap[j]; - k = j; - - /* And continue down the tree, setting j to the left son of k */ - j <<= 1; - } - s.heap[k] = v; -} - - -// inlined manually -// var SMALLEST = 1; - -/* =========================================================================== - * Send the block data compressed using the given Huffman trees - */ -function compress_block(s, ltree, dtree) -// deflate_state *s; -// const ct_data *ltree; /* literal tree */ -// const ct_data *dtree; /* distance tree */ -{ - var dist; /* distance of matched string */ - var lc; /* match length or unmatched char (if dist == 0) */ - var lx = 0; /* running index in l_buf */ - var code; /* the code to send */ - var extra; /* number of extra bits to send */ - - if (s.last_lit !== 0) { - do { - dist = (s.pending_buf[s.d_buf + lx * 2] << 8) | (s.pending_buf[s.d_buf + lx * 2 + 1]); - lc = s.pending_buf[s.l_buf + lx]; - lx++; - - if (dist === 0) { - send_code(s, lc, ltree); /* send a literal byte */ - //Tracecv(isgraph(lc), (stderr," '%c' ", lc)); - } else { - /* Here, lc is the match length - MIN_MATCH */ - code = _length_code[lc]; - send_code(s, code + LITERALS + 1, ltree); /* send the length code */ - extra = extra_lbits[code]; - if (extra !== 0) { - lc -= base_length[code]; - send_bits(s, lc, extra); /* send the extra length bits */ - } - dist--; /* dist is now the match distance - 1 */ - code = d_code(dist); - //Assert (code < D_CODES, "bad d_code"); - - send_code(s, code, dtree); /* send the distance code */ - extra = extra_dbits[code]; - if (extra !== 0) { - dist -= base_dist[code]; - send_bits(s, dist, extra); /* send the extra distance bits */ - } - } /* literal or match pair ? */ - - /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ - //Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, - // "pendingBuf overflow"); - - } while (lx < s.last_lit); - } - - send_code(s, END_BLOCK, ltree); -} - - -/* =========================================================================== - * Construct one Huffman tree and assigns the code bit strings and lengths. - * Update the total bit length for the current block. - * IN assertion: the field freq is set for all tree elements. - * OUT assertions: the fields len and code are set to the optimal bit length - * and corresponding code. The length opt_len is updated; static_len is - * also updated if stree is not null. The field max_code is set. - */ -function build_tree(s, desc) -// deflate_state *s; -// tree_desc *desc; /* the tree descriptor */ -{ - var tree = desc.dyn_tree; - var stree = desc.stat_desc.static_tree; - var has_stree = desc.stat_desc.has_stree; - var elems = desc.stat_desc.elems; - var n, m; /* iterate over heap elements */ - var max_code = -1; /* largest code with non zero frequency */ - var node; /* new node being created */ - - /* Construct the initial heap, with least frequent element in - * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. - * heap[0] is not used. - */ - s.heap_len = 0; - s.heap_max = HEAP_SIZE; - - for (n = 0; n < elems; n++) { - if (tree[n * 2]/*.Freq*/ !== 0) { - s.heap[++s.heap_len] = max_code = n; - s.depth[n] = 0; - - } else { - tree[n * 2 + 1]/*.Len*/ = 0; - } - } - - /* The pkzip format requires that at least one distance code exists, - * and that at least one bit should be sent even if there is only one - * possible code. So to avoid special checks later on we force at least - * two codes of non zero frequency. - */ - while (s.heap_len < 2) { - node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0); - tree[node * 2]/*.Freq*/ = 1; - s.depth[node] = 0; - s.opt_len--; - - if (has_stree) { - s.static_len -= stree[node * 2 + 1]/*.Len*/; - } - /* node is 0 or 1 so it does not have extra bits */ - } - desc.max_code = max_code; - - /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, - * establish sub-heaps of increasing lengths: - */ - for (n = (s.heap_len >> 1/*int /2*/); n >= 1; n--) { pqdownheap(s, tree, n); } - - /* Construct the Huffman tree by repeatedly combining the least two - * frequent nodes. - */ - node = elems; /* next internal node of the tree */ - do { - //pqremove(s, tree, n); /* n = node of least frequency */ - /*** pqremove ***/ - n = s.heap[1/*SMALLEST*/]; - s.heap[1/*SMALLEST*/] = s.heap[s.heap_len--]; - pqdownheap(s, tree, 1/*SMALLEST*/); - /***/ - - m = s.heap[1/*SMALLEST*/]; /* m = node of next least frequency */ - - s.heap[--s.heap_max] = n; /* keep the nodes sorted by frequency */ - s.heap[--s.heap_max] = m; - - /* Create a new node father of n and m */ - tree[node * 2]/*.Freq*/ = tree[n * 2]/*.Freq*/ + tree[m * 2]/*.Freq*/; - s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1; - tree[n * 2 + 1]/*.Dad*/ = tree[m * 2 + 1]/*.Dad*/ = node; - - /* and insert the new node in the heap */ - s.heap[1/*SMALLEST*/] = node++; - pqdownheap(s, tree, 1/*SMALLEST*/); - - } while (s.heap_len >= 2); - - s.heap[--s.heap_max] = s.heap[1/*SMALLEST*/]; - - /* At this point, the fields freq and dad are set. We can now - * generate the bit lengths. - */ - gen_bitlen(s, desc); - - /* The field len is now set, we can generate the bit codes */ - gen_codes(tree, max_code, s.bl_count); -} - - -/* =========================================================================== - * Scan a literal or distance tree to determine the frequencies of the codes - * in the bit length tree. - */ -function scan_tree(s, tree, max_code) -// deflate_state *s; -// ct_data *tree; /* the tree to be scanned */ -// int max_code; /* and its largest code of non zero frequency */ -{ - var n; /* iterates over all tree elements */ - var prevlen = -1; /* last emitted length */ - var curlen; /* length of current code */ - - var nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */ - - var count = 0; /* repeat count of the current code */ - var max_count = 7; /* max repeat count */ - var min_count = 4; /* min repeat count */ - - if (nextlen === 0) { - max_count = 138; - min_count = 3; - } - tree[(max_code + 1) * 2 + 1]/*.Len*/ = 0xffff; /* guard */ - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; - nextlen = tree[(n + 1) * 2 + 1]/*.Len*/; - - if (++count < max_count && curlen === nextlen) { - continue; - - } else if (count < min_count) { - s.bl_tree[curlen * 2]/*.Freq*/ += count; - - } else if (curlen !== 0) { - - if (curlen !== prevlen) { s.bl_tree[curlen * 2]/*.Freq*/++; } - s.bl_tree[REP_3_6 * 2]/*.Freq*/++; - - } else if (count <= 10) { - s.bl_tree[REPZ_3_10 * 2]/*.Freq*/++; - - } else { - s.bl_tree[REPZ_11_138 * 2]/*.Freq*/++; - } - - count = 0; - prevlen = curlen; - - if (nextlen === 0) { - max_count = 138; - min_count = 3; - - } else if (curlen === nextlen) { - max_count = 6; - min_count = 3; - - } else { - max_count = 7; - min_count = 4; - } - } -} - - -/* =========================================================================== - * Send a literal or distance tree in compressed form, using the codes in - * bl_tree. - */ -function send_tree(s, tree, max_code) -// deflate_state *s; -// ct_data *tree; /* the tree to be scanned */ -// int max_code; /* and its largest code of non zero frequency */ -{ - var n; /* iterates over all tree elements */ - var prevlen = -1; /* last emitted length */ - var curlen; /* length of current code */ - - var nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */ - - var count = 0; /* repeat count of the current code */ - var max_count = 7; /* max repeat count */ - var min_count = 4; /* min repeat count */ - - /* tree[max_code+1].Len = -1; */ /* guard already set */ - if (nextlen === 0) { - max_count = 138; - min_count = 3; - } - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; - nextlen = tree[(n + 1) * 2 + 1]/*.Len*/; - - if (++count < max_count && curlen === nextlen) { - continue; - - } else if (count < min_count) { - do { send_code(s, curlen, s.bl_tree); } while (--count !== 0); - - } else if (curlen !== 0) { - if (curlen !== prevlen) { - send_code(s, curlen, s.bl_tree); - count--; - } - //Assert(count >= 3 && count <= 6, " 3_6?"); - send_code(s, REP_3_6, s.bl_tree); - send_bits(s, count - 3, 2); - - } else if (count <= 10) { - send_code(s, REPZ_3_10, s.bl_tree); - send_bits(s, count - 3, 3); - - } else { - send_code(s, REPZ_11_138, s.bl_tree); - send_bits(s, count - 11, 7); - } - - count = 0; - prevlen = curlen; - if (nextlen === 0) { - max_count = 138; - min_count = 3; - - } else if (curlen === nextlen) { - max_count = 6; - min_count = 3; - - } else { - max_count = 7; - min_count = 4; - } - } -} - - -/* =========================================================================== - * Construct the Huffman tree for the bit lengths and return the index in - * bl_order of the last bit length code to send. - */ -function build_bl_tree(s) { - var max_blindex; /* index of last bit length code of non zero freq */ - - /* Determine the bit length frequencies for literal and distance trees */ - scan_tree(s, s.dyn_ltree, s.l_desc.max_code); - scan_tree(s, s.dyn_dtree, s.d_desc.max_code); - - /* Build the bit length tree: */ - build_tree(s, s.bl_desc); - /* opt_len now includes the length of the tree representations, except - * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. - */ - - /* Determine the number of bit length codes to send. The pkzip format - * requires that at least 4 bit length codes be sent. (appnote.txt says - * 3 but the actual value used is 4.) - */ - for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) { - if (s.bl_tree[bl_order[max_blindex] * 2 + 1]/*.Len*/ !== 0) { - break; - } - } - /* Update opt_len to include the bit length tree and counts */ - s.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4; - //Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", - // s->opt_len, s->static_len)); - - return max_blindex; -} - - -/* =========================================================================== - * Send the header for a block using dynamic Huffman trees: the counts, the - * lengths of the bit length codes, the literal tree and the distance tree. - * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. - */ -function send_all_trees(s, lcodes, dcodes, blcodes) -// deflate_state *s; -// int lcodes, dcodes, blcodes; /* number of codes for each tree */ -{ - var rank; /* index in bl_order */ - - //Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); - //Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, - // "too many codes"); - //Tracev((stderr, "\nbl counts: ")); - send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */ - send_bits(s, dcodes - 1, 5); - send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */ - for (rank = 0; rank < blcodes; rank++) { - //Tracev((stderr, "\nbl code %2d ", bl_order[rank])); - send_bits(s, s.bl_tree[bl_order[rank] * 2 + 1]/*.Len*/, 3); - } - //Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); - - send_tree(s, s.dyn_ltree, lcodes - 1); /* literal tree */ - //Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); - - send_tree(s, s.dyn_dtree, dcodes - 1); /* distance tree */ - //Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); -} - - -/* =========================================================================== - * Check if the data type is TEXT or BINARY, using the following algorithm: - * - TEXT if the two conditions below are satisfied: - * a) There are no non-portable control characters belonging to the - * "black list" (0..6, 14..25, 28..31). - * b) There is at least one printable character belonging to the - * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). - * - BINARY otherwise. - * - The following partially-portable control characters form a - * "gray list" that is ignored in this detection algorithm: - * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). - * IN assertion: the fields Freq of dyn_ltree are set. - */ -function detect_data_type(s) { - /* black_mask is the bit mask of black-listed bytes - * set bits 0..6, 14..25, and 28..31 - * 0xf3ffc07f = binary 11110011111111111100000001111111 - */ - var black_mask = 0xf3ffc07f; - var n; - - /* Check for non-textual ("black-listed") bytes. */ - for (n = 0; n <= 31; n++, black_mask >>>= 1) { - if ((black_mask & 1) && (s.dyn_ltree[n * 2]/*.Freq*/ !== 0)) { - return Z_BINARY; - } - } - - /* Check for textual ("white-listed") bytes. */ - if (s.dyn_ltree[9 * 2]/*.Freq*/ !== 0 || s.dyn_ltree[10 * 2]/*.Freq*/ !== 0 || - s.dyn_ltree[13 * 2]/*.Freq*/ !== 0) { - return Z_TEXT; - } - for (n = 32; n < LITERALS; n++) { - if (s.dyn_ltree[n * 2]/*.Freq*/ !== 0) { - return Z_TEXT; - } - } - - /* There are no "black-listed" or "white-listed" bytes: - * this stream either is empty or has tolerated ("gray-listed") bytes only. - */ - return Z_BINARY; -} - - -var static_init_done = false; - -/* =========================================================================== - * Initialize the tree data structures for a new zlib stream. - */ -function _tr_init(s) -{ - - if (!static_init_done) { - tr_static_init(); - static_init_done = true; - } - - s.l_desc = new TreeDesc(s.dyn_ltree, static_l_desc); - s.d_desc = new TreeDesc(s.dyn_dtree, static_d_desc); - s.bl_desc = new TreeDesc(s.bl_tree, static_bl_desc); - - s.bi_buf = 0; - s.bi_valid = 0; - - /* Initialize the first block of the first file: */ - init_block(s); -} - - -/* =========================================================================== - * Send a stored block - */ -function _tr_stored_block(s, buf, stored_len, last) -//DeflateState *s; -//charf *buf; /* input block */ -//ulg stored_len; /* length of input block */ -//int last; /* one if this is the last block for a file */ -{ - send_bits(s, (STORED_BLOCK << 1) + (last ? 1 : 0), 3); /* send block type */ - copy_block(s, buf, stored_len, true); /* with header */ -} - - -/* =========================================================================== - * Send one empty static block to give enough lookahead for inflate. - * This takes 10 bits, of which 7 may remain in the bit buffer. - */ -function _tr_align(s) { - send_bits(s, STATIC_TREES << 1, 3); - send_code(s, END_BLOCK, static_ltree); - bi_flush(s); -} - - -/* =========================================================================== - * Determine the best encoding for the current block: dynamic trees, static - * trees or store, and output the encoded block to the zip file. - */ -function _tr_flush_block(s, buf, stored_len, last) -//DeflateState *s; -//charf *buf; /* input block, or NULL if too old */ -//ulg stored_len; /* length of input block */ -//int last; /* one if this is the last block for a file */ -{ - var opt_lenb, static_lenb; /* opt_len and static_len in bytes */ - var max_blindex = 0; /* index of last bit length code of non zero freq */ - - /* Build the Huffman trees unless a stored block is forced */ - if (s.level > 0) { - - /* Check if the file is binary or text */ - if (s.strm.data_type === Z_UNKNOWN) { - s.strm.data_type = detect_data_type(s); - } - - /* Construct the literal and distance trees */ - build_tree(s, s.l_desc); - // Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, - // s->static_len)); - - build_tree(s, s.d_desc); - // Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, - // s->static_len)); - /* At this point, opt_len and static_len are the total bit lengths of - * the compressed block data, excluding the tree representations. - */ - - /* Build the bit length tree for the above two trees, and get the index - * in bl_order of the last bit length code to send. - */ - max_blindex = build_bl_tree(s); - - /* Determine the best encoding. Compute the block lengths in bytes. */ - opt_lenb = (s.opt_len + 3 + 7) >>> 3; - static_lenb = (s.static_len + 3 + 7) >>> 3; - - // Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", - // opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, - // s->last_lit)); - - if (static_lenb <= opt_lenb) { opt_lenb = static_lenb; } - - } else { - // Assert(buf != (char*)0, "lost buf"); - opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ - } - - if ((stored_len + 4 <= opt_lenb) && (buf !== -1)) { - /* 4: two words for the lengths */ - - /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. - * Otherwise we can't have processed more than WSIZE input bytes since - * the last block flush, because compression would have been - * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to - * transform a block into a stored block. - */ - _tr_stored_block(s, buf, stored_len, last); - - } else if (s.strategy === Z_FIXED || static_lenb === opt_lenb) { - - send_bits(s, (STATIC_TREES << 1) + (last ? 1 : 0), 3); - compress_block(s, static_ltree, static_dtree); - - } else { - send_bits(s, (DYN_TREES << 1) + (last ? 1 : 0), 3); - send_all_trees(s, s.l_desc.max_code + 1, s.d_desc.max_code + 1, max_blindex + 1); - compress_block(s, s.dyn_ltree, s.dyn_dtree); - } - // Assert (s->compressed_len == s->bits_sent, "bad compressed size"); - /* The above check is made mod 2^32, for files larger than 512 MB - * and uLong implemented on 32 bits. - */ - init_block(s); - - if (last) { - bi_windup(s); - } - // Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, - // s->compressed_len-7*last)); -} - -/* =========================================================================== - * Save the match info and tally the frequency counts. Return true if - * the current block must be flushed. - */ -function _tr_tally(s, dist, lc) -// deflate_state *s; -// unsigned dist; /* distance of matched string */ -// unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ -{ - //var out_length, in_length, dcode; - - s.pending_buf[s.d_buf + s.last_lit * 2] = (dist >>> 8) & 0xff; - s.pending_buf[s.d_buf + s.last_lit * 2 + 1] = dist & 0xff; - - s.pending_buf[s.l_buf + s.last_lit] = lc & 0xff; - s.last_lit++; - - if (dist === 0) { - /* lc is the unmatched char */ - s.dyn_ltree[lc * 2]/*.Freq*/++; - } else { - s.matches++; - /* Here, lc is the match length - MIN_MATCH */ - dist--; /* dist = match distance - 1 */ - //Assert((ush)dist < (ush)MAX_DIST(s) && - // (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && - // (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); - - s.dyn_ltree[(_length_code[lc] + LITERALS + 1) * 2]/*.Freq*/++; - s.dyn_dtree[d_code(dist) * 2]/*.Freq*/++; - } - -// (!) This block is disabled in zlib defaults, -// don't enable it for binary compatibility - -//#ifdef TRUNCATE_BLOCK -// /* Try to guess if it is profitable to stop the current block here */ -// if ((s.last_lit & 0x1fff) === 0 && s.level > 2) { -// /* Compute an upper bound for the compressed length */ -// out_length = s.last_lit*8; -// in_length = s.strstart - s.block_start; -// -// for (dcode = 0; dcode < D_CODES; dcode++) { -// out_length += s.dyn_dtree[dcode*2]/*.Freq*/ * (5 + extra_dbits[dcode]); -// } -// out_length >>>= 3; -// //Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", -// // s->last_lit, in_length, out_length, -// // 100L - out_length*100L/in_length)); -// if (s.matches < (s.last_lit>>1)/*int /2*/ && out_length < (in_length>>1)/*int /2*/) { -// return true; -// } -// } -//#endif - - return (s.last_lit === s.lit_bufsize - 1); - /* We avoid equality with lit_bufsize because of wraparound at 64K - * on 16 bit machines and because stored blocks are restricted to - * 64K-1 bytes. - */ -} - -exports._tr_init = _tr_init; -exports._tr_stored_block = _tr_stored_block; -exports._tr_flush_block = _tr_flush_block; -exports._tr_tally = _tr_tally; -exports._tr_align = _tr_align; - -},{"../utils/common":53}],65:[function(require,module,exports){ -'use strict'; - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -function ZStream() { - /* next input byte */ - this.input = null; // JS specific, because we have no pointers - this.next_in = 0; - /* number of bytes available at input */ - this.avail_in = 0; - /* total number of input bytes read so far */ - this.total_in = 0; - /* next output byte should be put there */ - this.output = null; // JS specific, because we have no pointers - this.next_out = 0; - /* remaining free space at output */ - this.avail_out = 0; - /* total number of bytes output so far */ - this.total_out = 0; - /* last error message, NULL if no error */ - this.msg = ''/*Z_NULL*/; - /* not visible by applications */ - this.state = null; - /* best guess about the data type: binary or text */ - this.data_type = 2/*Z_UNKNOWN*/; - /* adler32 value of the uncompressed data */ - this.adler = 0; -} - -module.exports = ZStream; - -},{}],66:[function(require,module,exports){ -// shim for using process in browser -var process = module.exports = {}; - -// cached from whatever global is present so that test runners that stub it -// don't break things. But we need to wrap it in a try catch in case it is -// wrapped in strict mode code which doesn't define any globals. It's inside a -// function because try/catches deoptimize in certain engines. - -var cachedSetTimeout; -var cachedClearTimeout; - -function defaultSetTimout() { - throw new Error('setTimeout has not been defined'); -} -function defaultClearTimeout () { - throw new Error('clearTimeout has not been defined'); -} -(function () { - try { - if (typeof setTimeout === 'function') { - cachedSetTimeout = setTimeout; - } else { - cachedSetTimeout = defaultSetTimout; - } - } catch (e) { - cachedSetTimeout = defaultSetTimout; - } - try { - if (typeof clearTimeout === 'function') { - cachedClearTimeout = clearTimeout; - } else { - cachedClearTimeout = defaultClearTimeout; - } - } catch (e) { - cachedClearTimeout = defaultClearTimeout; - } -} ()) -function runTimeout(fun) { - if (cachedSetTimeout === setTimeout) { - //normal enviroments in sane situations - return setTimeout(fun, 0); - } - // if setTimeout wasn't available but was latter defined - if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { - cachedSetTimeout = setTimeout; - return setTimeout(fun, 0); - } - try { - // when when somebody has screwed with setTimeout but no I.E. maddness - return cachedSetTimeout(fun, 0); - } catch(e){ - try { - // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally - return cachedSetTimeout.call(null, fun, 0); - } catch(e){ - // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error - return cachedSetTimeout.call(this, fun, 0); - } - } - - -} -function runClearTimeout(marker) { - if (cachedClearTimeout === clearTimeout) { - //normal enviroments in sane situations - return clearTimeout(marker); - } - // if clearTimeout wasn't available but was latter defined - if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { - cachedClearTimeout = clearTimeout; - return clearTimeout(marker); - } - try { - // when when somebody has screwed with setTimeout but no I.E. maddness - return cachedClearTimeout(marker); - } catch (e){ - try { - // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally - return cachedClearTimeout.call(null, marker); - } catch (e){ - // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. - // Some versions of I.E. have different rules for clearTimeout vs setTimeout - return cachedClearTimeout.call(this, marker); - } - } - - - -} -var queue = []; -var draining = false; -var currentQueue; -var queueIndex = -1; - -function cleanUpNextTick() { - if (!draining || !currentQueue) { - return; - } - draining = false; - if (currentQueue.length) { - queue = currentQueue.concat(queue); - } else { - queueIndex = -1; - } - if (queue.length) { - drainQueue(); - } -} - -function drainQueue() { - if (draining) { - return; - } - var timeout = runTimeout(cleanUpNextTick); - draining = true; - - var len = queue.length; - while(len) { - currentQueue = queue; - queue = []; - while (++queueIndex < len) { - if (currentQueue) { - currentQueue[queueIndex].run(); - } - } - queueIndex = -1; - len = queue.length; - } - currentQueue = null; - draining = false; - runClearTimeout(timeout); -} - -process.nextTick = function (fun) { - var args = new Array(arguments.length - 1); - if (arguments.length > 1) { - for (var i = 1; i < arguments.length; i++) { - args[i - 1] = arguments[i]; - } - } - queue.push(new Item(fun, args)); - if (queue.length === 1 && !draining) { - runTimeout(drainQueue); - } -}; - -// v8 likes predictible objects -function Item(fun, array) { - this.fun = fun; - this.array = array; -} -Item.prototype.run = function () { - this.fun.apply(null, this.array); -}; -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; -process.version = ''; // empty string to avoid regexp issues -process.versions = {}; - -function noop() {} - -process.on = noop; -process.addListener = noop; -process.once = noop; -process.off = noop; -process.removeListener = noop; -process.removeAllListeners = noop; -process.emit = noop; -process.prependListener = noop; -process.prependOnceListener = noop; - -process.listeners = function (name) { return [] } - -process.binding = function (name) { - throw new Error('process.binding is not supported'); -}; - -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); -}; -process.umask = function() { return 0; }; - -},{}],67:[function(require,module,exports){ -'use strict'; - -/* -node-bzip - a pure-javascript Node.JS module for decoding bzip2 data - -Copyright (C) 2012 Eli Skeggs - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, see -http://www.gnu.org/licenses/lgpl-2.1.html - -Adapted from bzip2.js, copyright 2011 antimatter15 (antimatter15@gmail.com). - -Based on micro-bunzip by Rob Landley (rob@landley.net). - -Based on bzip2 decompression code by Julian R Seward (jseward@acm.org), -which also acknowledges contributions by Mike Burrows, David Wheeler, -Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten, -Robert Sedgewick, and Jon L. Bentley. -*/ - -var BITMASK = [0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF]; - -// offset in bytes -var BitReader = function BitReader(stream) { - this.stream = stream; - this.bitOffset = 0; - this.curByte = 0; - this.hasByte = false; -}; - -BitReader.prototype._ensureByte = function () { - if (!this.hasByte) { - this.curByte = this.stream.readByte(); - this.hasByte = true; - } -}; - -// reads bits from the buffer -BitReader.prototype.read = function (bits) { - var result = 0; - while (bits > 0) { - this._ensureByte(); - var remaining = 8 - this.bitOffset; - // if we're in a byte - if (bits >= remaining) { - result <<= remaining; - result |= BITMASK[remaining] & this.curByte; - this.hasByte = false; - this.bitOffset = 0; - bits -= remaining; - } else { - result <<= bits; - var shift = remaining - bits; - result |= (this.curByte & BITMASK[bits] << shift) >> shift; - this.bitOffset += bits; - bits = 0; - } - } - return result; -}; - -// seek to an arbitrary point in the buffer (expressed in bits) -BitReader.prototype.seek = function (pos) { - var n_bit = pos % 8; - var n_byte = (pos - n_bit) / 8; - this.bitOffset = n_bit; - this.stream.seek(n_byte); - this.hasByte = false; -}; - -// reads 6 bytes worth of data using the read method -BitReader.prototype.pi = function () { - var buf = new Uint8Array(6), - i; - for (i = 0; i < buf.length; i++) { - buf[i] = this.read(8); - } - return bufToHex(buf); -}; - -function bufToHex(buf) { - return Array.prototype.map.call(buf, x => ('00' + x.toString(16)).slice(-2)).join(''); -} - -module.exports = BitReader; - -},{}],68:[function(require,module,exports){ -"use strict"; - -/* CRC32, used in Bzip2 implementation. - * This is a port of CRC32.java from the jbzip2 implementation at - * https://code.google.com/p/jbzip2 - * which is: - * Copyright (c) 2011 Matthew Francis - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * This JavaScript implementation is: - * Copyright (c) 2013 C. Scott Ananian - * with the same licensing terms as Matthew Francis' original implementation. - */ -module.exports = function () { - - /** - * A static CRC lookup table - */ - var crc32Lookup = new Uint32Array([0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4]); - - var CRC32 = function CRC32() { - /** - * The current CRC - */ - var crc = 0xffffffff; - - /** - * @return The current CRC - */ - this.getCRC = function () { - return ~crc >>> 0; // return an unsigned value - }; - - /** - * Update the CRC with a single byte - * @param value The value to update the CRC with - */ - this.updateCRC = function (value) { - crc = crc << 8 ^ crc32Lookup[(crc >>> 24 ^ value) & 0xff]; - }; - - /** - * Update the CRC with a sequence of identical bytes - * @param value The value to update the CRC with - * @param count The number of bytes - */ - this.updateCRCRun = function (value, count) { - while (count-- > 0) { - crc = crc << 8 ^ crc32Lookup[(crc >>> 24 ^ value) & 0xff]; - } - }; - }; - return CRC32; -}(); - -},{}],69:[function(require,module,exports){ -'use strict'; - -/* -seek-bzip - a pure-javascript module for seeking within bzip2 data - -Copyright (C) 2013 C. Scott Ananian -Copyright (C) 2012 Eli Skeggs -Copyright (C) 2011 Kevin Kwok - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, see -http://www.gnu.org/licenses/lgpl-2.1.html - -Adapted from node-bzip, copyright 2012 Eli Skeggs. -Adapted from bzip2.js, copyright 2011 Kevin Kwok (antimatter15@gmail.com). - -Based on micro-bunzip by Rob Landley (rob@landley.net). - -Based on bzip2 decompression code by Julian R Seward (jseward@acm.org), -which also acknowledges contributions by Mike Burrows, David Wheeler, -Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten, -Robert Sedgewick, and Jon L. Bentley. -*/ - -var BitReader = require('./bitreader'); -var Stream = require('./stream'); -var CRC32 = require('./crc32'); - -var MAX_HUFCODE_BITS = 20; -var MAX_SYMBOLS = 258; -var SYMBOL_RUNA = 0; -var SYMBOL_RUNB = 1; -var MIN_GROUPS = 2; -var MAX_GROUPS = 6; -var GROUP_SIZE = 50; - -var WHOLEPI = "314159265359"; -var SQRTPI = "177245385090"; - -var mtf = function mtf(array, index) { - var src = array[index], - i; - for (i = index; i > 0; i--) { - array[i] = array[i - 1]; - } - array[0] = src; - return src; -}; - -var Err = { - OK: 0, - LAST_BLOCK: -1, - NOT_BZIP_DATA: -2, - UNEXPECTED_INPUT_EOF: -3, - UNEXPECTED_OUTPUT_EOF: -4, - DATA_ERROR: -5, - OUT_OF_MEMORY: -6, - OBSOLETE_INPUT: -7, - END_OF_BLOCK: -8 -}; -var ErrorMessages = {}; -ErrorMessages[Err.LAST_BLOCK] = "Bad file checksum"; -ErrorMessages[Err.NOT_BZIP_DATA] = "Not bzip data"; -ErrorMessages[Err.UNEXPECTED_INPUT_EOF] = "Unexpected input EOF"; -ErrorMessages[Err.UNEXPECTED_OUTPUT_EOF] = "Unexpected output EOF"; -ErrorMessages[Err.DATA_ERROR] = "Data error"; -ErrorMessages[Err.OUT_OF_MEMORY] = "Out of memory"; -ErrorMessages[Err.OBSOLETE_INPUT] = "Obsolete (pre 0.9.5) bzip format not supported."; - -var _throw = function _throw(status, optDetail) { - var msg = ErrorMessages[status] || 'unknown error'; - if (optDetail) { - msg += ': ' + optDetail; - } - var e = new TypeError(msg); - e.errorCode = status; - throw e; -}; - -var Bunzip = function Bunzip(inputStream, outputStream) { - this.writePos = this.writeCurrent = this.writeCount = 0; - - this._start_bunzip(inputStream, outputStream); -}; -Bunzip.prototype._init_block = function () { - var moreBlocks = this._get_next_block(); - if (!moreBlocks) { - this.writeCount = -1; - return false; /* no more blocks */ - } - this.blockCRC = new CRC32(); - return true; -}; -/* XXX micro-bunzip uses (inputStream, inputBuffer, len) as arguments */ -Bunzip.prototype._start_bunzip = function (inputStream, outputStream) { - /* Ensure that file starts with "BZh['1'-'9']." */ - var buf = new Uint8Array(4); - if (inputStream.read(buf, 0, 4) !== 4 || String.fromCharCode(buf[0], buf[1], buf[2]) !== 'BZh') _throw(Err.NOT_BZIP_DATA, 'bad magic'); - - var level = buf[3] - 0x30; - if (level < 1 || level > 9) _throw(Err.NOT_BZIP_DATA, 'level out of range'); - - this.reader = new BitReader(inputStream); - - /* Fourth byte (ascii '1'-'9'), indicates block size in units of 100k of - uncompressed data. Allocate intermediate buffer for block. */ - this.dbufSize = 100000 * level; - this.nextoutput = 0; - this.outputStream = outputStream; - this.streamCRC = 0; -}; -Bunzip.prototype._get_next_block = function () { - var i, j, k; - var reader = this.reader; - // this is get_next_block() function from micro-bunzip: - /* Read in header signature and CRC, then validate signature. - (last block signature means CRC is for whole file, return now) */ - var h = reader.pi(); - if (h === SQRTPI) { - // last block - return false; /* no more blocks */ - } - if (h !== WHOLEPI) _throw(Err.NOT_BZIP_DATA); - this.targetBlockCRC = reader.read(32) >>> 0; // (convert to unsigned) - this.streamCRC = (this.targetBlockCRC ^ (this.streamCRC << 1 | this.streamCRC >>> 31)) >>> 0; - /* We can add support for blockRandomised if anybody complains. There was - some code for this in busybox 1.0.0-pre3, but nobody ever noticed that - it didn't actually work. */ - if (reader.read(1)) _throw(Err.OBSOLETE_INPUT); - var origPointer = reader.read(24); - if (origPointer > this.dbufSize) _throw(Err.DATA_ERROR, 'initial position out of bounds'); - /* mapping table: if some byte values are never used (encoding things - like ascii text), the compression code removes the gaps to have fewer - symbols to deal with, and writes a sparse bitfield indicating which - values were present. We make a translation table to convert the symbols - back to the corresponding bytes. */ - var t = reader.read(16); - var symToByte = new Uint8Array(256), - symTotal = 0; - for (i = 0; i < 16; i++) { - if (t & 1 << 0xF - i) { - var o = i * 16; - k = reader.read(16); - for (j = 0; j < 16; j++) if (k & 1 << 0xF - j) symToByte[symTotal++] = o + j; - } - } - - /* How many different huffman coding groups does this block use? */ - var groupCount = reader.read(3); - if (groupCount < MIN_GROUPS || groupCount > MAX_GROUPS) _throw(Err.DATA_ERROR); - /* nSelectors: Every GROUP_SIZE many symbols we select a new huffman coding - group. Read in the group selector list, which is stored as MTF encoded - bit runs. (MTF=Move To Front, as each value is used it's moved to the - start of the list.) */ - var nSelectors = reader.read(15); - if (nSelectors === 0) _throw(Err.DATA_ERROR); - - var mtfSymbol = new Uint8Array(256); - for (i = 0; i < groupCount; i++) mtfSymbol[i] = i; - - var selectors = new Uint8Array(nSelectors); // was 32768... - - for (i = 0; i < nSelectors; i++) { - /* Get next value */ - for (j = 0; reader.read(1); j++) if (j >= groupCount) _throw(Err.DATA_ERROR); - /* Decode MTF to get the next selector */ - selectors[i] = mtf(mtfSymbol, j); - } - - /* Read the huffman coding tables for each group, which code for symTotal - literal symbols, plus two run symbols (RUNA, RUNB) */ - var symCount = symTotal + 2; - var groups = [], - hufGroup; - for (j = 0; j < groupCount; j++) { - var length = new Uint8Array(symCount), - temp = new Uint16Array(MAX_HUFCODE_BITS + 1); - /* Read huffman code lengths for each symbol. They're stored in - a way similar to mtf; record a starting value for the first symbol, - and an offset from the previous value for everys symbol after that. */ - t = reader.read(5); // lengths - for (i = 0; i < symCount; i++) { - for (;;) { - if (t < 1 || t > MAX_HUFCODE_BITS) _throw(Err.DATA_ERROR); - /* If first bit is 0, stop. Else second bit indicates whether - to increment or decrement the value. */ - if (!reader.read(1)) break; - if (!reader.read(1)) t++;else t--; - } - length[i] = t; - } - - /* Find largest and smallest lengths in this group */ - var minLen, maxLen; - minLen = maxLen = length[0]; - for (i = 1; i < symCount; i++) { - if (length[i] > maxLen) maxLen = length[i];else if (length[i] < minLen) minLen = length[i]; - } - - /* Calculate permute[], base[], and limit[] tables from length[]. - * - * permute[] is the lookup table for converting huffman coded symbols - * into decoded symbols. base[] is the amount to subtract from the - * value of a huffman symbol of a given length when using permute[]. - * - * limit[] indicates the largest numerical value a symbol with a given - * number of bits can have. This is how the huffman codes can vary in - * length: each code with a value>limit[length] needs another bit. - */ - hufGroup = {}; - groups.push(hufGroup); - hufGroup.permute = new Uint16Array(MAX_SYMBOLS); - hufGroup.limit = new Uint32Array(MAX_HUFCODE_BITS + 2); - hufGroup.base = new Uint32Array(MAX_HUFCODE_BITS + 1); - hufGroup.minLen = minLen; - hufGroup.maxLen = maxLen; - /* Calculate permute[]. Concurently, initialize temp[] and limit[]. */ - var pp = 0; - for (i = minLen; i <= maxLen; i++) { - temp[i] = hufGroup.limit[i] = 0; - for (t = 0; t < symCount; t++) if (length[t] === i) hufGroup.permute[pp++] = t; - } - /* Count symbols coded for at each bit length */ - for (i = 0; i < symCount; i++) temp[length[i]]++; - /* Calculate limit[] (the largest symbol-coding value at each bit - * length, which is (previous limit<<1)+symbols at this level), and - * base[] (number of symbols to ignore at each bit length, which is - * limit minus the cumulative count of symbols coded for already). */ - pp = t = 0; - for (i = minLen; i < maxLen; i++) { - pp += temp[i]; - /* We read the largest possible symbol size and then unget bits - after determining how many we need, and those extra bits could - be set to anything. (They're noise from future symbols.) At - each level we're really only interested in the first few bits, - so here we set all the trailing to-be-ignored bits to 1 so they - don't affect the value>limit[length] comparison. */ - hufGroup.limit[i] = pp - 1; - pp <<= 1; - t += temp[i]; - hufGroup.base[i + 1] = pp - t; - } - hufGroup.limit[maxLen + 1] = Number.MAX_VALUE; /* Sentinal value for reading next sym. */ - hufGroup.limit[maxLen] = pp + temp[maxLen] - 1; - hufGroup.base[minLen] = 0; - } - /* We've finished reading and digesting the block header. Now read this - block's huffman coded symbols from the file and undo the huffman coding - and run length encoding, saving the result into dbuf[dbufCount++]=uc */ - - /* Initialize symbol occurrence counters and symbol Move To Front table */ - var byteCount = new Uint32Array(256); - for (i = 0; i < 256; i++) mtfSymbol[i] = i; - /* Loop through compressed symbols. */ - var runPos = 0, - dbufCount = 0, - selector = 0, - uc; - var dbuf = this.dbuf = new Uint32Array(this.dbufSize); - symCount = 0; - for (;;) { - /* Determine which huffman coding group to use. */ - if (!symCount--) { - symCount = GROUP_SIZE - 1; - if (selector >= nSelectors) { - _throw(Err.DATA_ERROR); - } - hufGroup = groups[selectors[selector++]]; - } - /* Read next huffman-coded symbol. */ - i = hufGroup.minLen; - j = reader.read(i); - for (;; i++) { - if (i > hufGroup.maxLen) { - _throw(Err.DATA_ERROR); - } - if (j <= hufGroup.limit[i]) break; - j = j << 1 | reader.read(1); - } - /* Huffman decode value to get nextSym (with bounds checking) */ - j -= hufGroup.base[i]; - if (j < 0 || j >= MAX_SYMBOLS) { - _throw(Err.DATA_ERROR); - } - var nextSym = hufGroup.permute[j]; - /* We have now decoded the symbol, which indicates either a new literal - byte, or a repeated run of the most recent literal byte. First, - check if nextSym indicates a repeated run, and if so loop collecting - how many times to repeat the last literal. */ - if (nextSym === SYMBOL_RUNA || nextSym === SYMBOL_RUNB) { - /* If this is the start of a new run, zero out counter */ - if (!runPos) { - runPos = 1; - t = 0; - } - /* Neat trick that saves 1 symbol: instead of or-ing 0 or 1 at - each bit position, add 1 or 2 instead. For example, - 1011 is 1<<0 + 1<<1 + 2<<2. 1010 is 2<<0 + 2<<1 + 1<<2. - You can make any bit pattern that way using 1 less symbol than - the basic or 0/1 method (except all bits 0, which would use no - symbols, but a run of length 0 doesn't mean anything in this - context). Thus space is saved. */ - if (nextSym === SYMBOL_RUNA) t += runPos;else t += 2 * runPos; - runPos <<= 1; - continue; - } - /* When we hit the first non-run symbol after a run, we now know - how many times to repeat the last literal, so append that many - copies to our buffer of decoded symbols (dbuf) now. (The last - literal used is the one at the head of the mtfSymbol array.) */ - if (runPos) { - runPos = 0; - if (dbufCount + t > this.dbufSize) { - _throw(Err.DATA_ERROR); - } - uc = symToByte[mtfSymbol[0]]; - byteCount[uc] += t; - while (t--) dbuf[dbufCount++] = uc; - } - /* Is this the terminating symbol? */ - if (nextSym > symTotal) break; - /* At this point, nextSym indicates a new literal character. Subtract - one to get the position in the MTF array at which this literal is - currently to be found. (Note that the result can't be -1 or 0, - because 0 and 1 are RUNA and RUNB. But another instance of the - first symbol in the mtf array, position 0, would have been handled - as part of a run above. Therefore 1 unused mtf position minus - 2 non-literal nextSym values equals -1.) */ - if (dbufCount >= this.dbufSize) { - _throw(Err.DATA_ERROR); - } - i = nextSym - 1; - uc = mtf(mtfSymbol, i); - uc = symToByte[uc]; - /* We have our literal byte. Save it into dbuf. */ - byteCount[uc]++; - dbuf[dbufCount++] = uc; - } - /* At this point, we've read all the huffman-coded symbols (and repeated - runs) for this block from the input stream, and decoded them into the - intermediate buffer. There are dbufCount many decoded bytes in dbuf[]. - Now undo the Burrows-Wheeler transform on dbuf. - See http://dogma.net/markn/articles/bwt/bwt.htm - */ - if (origPointer < 0 || origPointer >= dbufCount) { - _throw(Err.DATA_ERROR); - } - /* Turn byteCount into cumulative occurrence counts of 0 to n-1. */ - j = 0; - for (i = 0; i < 256; i++) { - k = j + byteCount[i]; - byteCount[i] = j; - j = k; - } - /* Figure out what order dbuf would be in if we sorted it. */ - for (i = 0; i < dbufCount; i++) { - uc = dbuf[i] & 0xff; - dbuf[byteCount[uc]] |= i << 8; - byteCount[uc]++; - } - /* Decode first byte by hand to initialize "previous" byte. Note that it - doesn't get output, and if the first three characters are identical - it doesn't qualify as a run (hence writeRunCountdown=5). */ - var pos = 0, - current = 0, - run = 0; - if (dbufCount) { - pos = dbuf[origPointer]; - current = pos & 0xff; - pos >>= 8; - run = -1; - } - this.writePos = pos; - this.writeCurrent = current; - this.writeCount = dbufCount; - this.writeRun = run; - - return true; /* more blocks to come */ -}; -/* Undo burrows-wheeler transform on intermediate buffer to produce output. - If start_bunzip was initialized with out_fd=-1, then up to len bytes of - data are written to outbuf. Return value is number of bytes written or - error (all errors are negative numbers). If out_fd!=-1, outbuf and len - are ignored, data is written to out_fd and return is RETVAL_OK or error. -*/ -Bunzip.prototype._read_bunzip = function (outputBuffer, len) { - var copies, previous, outbyte; - /* james@jamestaylor.org: writeCount goes to -1 when the buffer is fully - decoded, which results in this returning RETVAL_LAST_BLOCK, also - equal to -1... Confusing, I'm returning 0 here to indicate no - bytes written into the buffer */ - if (this.writeCount < 0) { - return 0; - } - - var gotcount = 0; - var dbuf = this.dbuf, - pos = this.writePos, - current = this.writeCurrent; - var dbufCount = this.writeCount, - outputsize = this.outputsize; - var run = this.writeRun; - - while (dbufCount) { - dbufCount--; - previous = current; - pos = dbuf[pos]; - current = pos & 0xff; - pos >>= 8; - if (run++ === 3) { - copies = current; - outbyte = previous; - current = -1; - } else { - copies = 1; - outbyte = current; - } - this.blockCRC.updateCRCRun(outbyte, copies); - while (copies--) { - this.outputStream.writeByte(outbyte); - this.nextoutput++; - } - if (current != previous) run = 0; - } - this.writeCount = dbufCount; - // check CRC - if (this.blockCRC.getCRC() !== this.targetBlockCRC) { - _throw(Err.DATA_ERROR, "Bad block CRC " + "(got " + this.blockCRC.getCRC().toString(16) + " expected " + this.targetBlockCRC.toString(16) + ")"); - } - return this.nextoutput; -}; - -var coerceInputStream = function coerceInputStream(input) { - if ('readByte' in input) { - return input; - } - var inputStream = new Stream(); - inputStream.pos = 0; - inputStream.readByte = function () { - return input[this.pos++]; - }; - inputStream.seek = function (pos) { - this.pos = pos; - }; - inputStream.eof = function () { - return this.pos >= input.length; - }; - return inputStream; -}; -var coerceOutputStream = function coerceOutputStream(output) { - var outputStream = new Stream(); - var resizeOk = true; - if (output) { - if (typeof output === 'number') { - outputStream.buffer = new Uint8Array(output); - resizeOk = false; - } else if ('writeByte' in output) { - return output; - } else { - outputStream.buffer = output; - resizeOk = false; - } - } else { - outputStream.buffer = new Uint8Array(16384); - } - outputStream.pos = 0; - outputStream.writeByte = function (_byte) { - if (resizeOk && this.pos >= this.buffer.length) { - var newBuffer = new Uint8Array(this.buffer.length * 2); - newBuffer.set(this.buffer); - this.buffer = newBuffer; - } - this.buffer[this.pos++] = _byte; - }; - outputStream.getBuffer = function () { - // trim buffer - if (this.pos !== this.buffer.length) { - if (!resizeOk) throw new TypeError('outputsize does not match decoded input'); - var newBuffer = new Uint8Array(this.pos); - newBuffer.set(this.buffer.subarray(0, this.pos)); - this.buffer = newBuffer; - } - return this.buffer; - }; - outputStream._coerced = true; - return outputStream; -}; - -/* Static helper functions */ -Bunzip.Err = Err; -// 'input' can be a stream or a buffer -// 'output' can be a stream or a buffer or a number (buffer size) -Bunzip.decode = function (input, output, multistream) { - // make a stream from a buffer, if necessary - var inputStream = coerceInputStream(input); - var outputStream = coerceOutputStream(output); - - var bz = new Bunzip(inputStream, outputStream); - while (true) { - if ('eof' in inputStream && inputStream.eof()) break; - if (bz._init_block()) { - bz._read_bunzip(); - } else { - var targetStreamCRC = bz.reader.read(32) >>> 0; // (convert to unsigned) - if (targetStreamCRC !== bz.streamCRC) { - _throw(Err.DATA_ERROR, "Bad stream CRC " + "(got " + bz.streamCRC.toString(16) + " expected " + targetStreamCRC.toString(16) + ")"); - } - if (multistream && 'eof' in inputStream && !inputStream.eof()) { - // note that start_bunzip will also resync the bit reader to next byte - bz._start_bunzip(inputStream, outputStream); - } else break; - } - } - if ('getBuffer' in outputStream) return outputStream.getBuffer(); -}; -Bunzip.decodeBlock = function (input, pos, output) { - // make a stream from a buffer, if necessary - var inputStream = coerceInputStream(input); - var outputStream = coerceOutputStream(output); - var bz = new Bunzip(inputStream, outputStream); - bz.reader.seek(pos); - /* Fill the decode buffer for the block */ - var moreBlocks = bz._get_next_block(); - if (moreBlocks) { - /* Init the CRC for writing */ - bz.blockCRC = new CRC32(); - - /* Zero this so the current byte from before the seek is not written */ - bz.writeCopies = 0; - - /* Decompress the block and write to stdout */ - bz._read_bunzip(); - // XXX keep writing? - } - if ('getBuffer' in outputStream) return outputStream.getBuffer(); -}; -/* Reads bzip2 file from stream or buffer `input`, and invoke - * `callback(position, size)` once for each bzip2 block, - * where position gives the starting position (in *bits*) - * and size gives uncompressed size of the block (in *bytes*). */ -Bunzip.table = function (input, callback, multistream) { - // make a stream from a buffer, if necessary - var inputStream = new Stream(); - inputStream.delegate = coerceInputStream(input); - inputStream.pos = 0; - inputStream.readByte = function () { - this.pos++; - return this.delegate.readByte(); - }; - if (inputStream.delegate.eof) { - inputStream.eof = inputStream.delegate.eof.bind(inputStream.delegate); - } - var outputStream = new Stream(); - outputStream.pos = 0; - outputStream.writeByte = function () { - this.pos++; - }; - - var bz = new Bunzip(inputStream, outputStream); - var blockSize = bz.dbufSize; - while (true) { - if ('eof' in inputStream && inputStream.eof()) break; - - var position = inputStream.pos * 8 + bz.reader.bitOffset; - if (bz.reader.hasByte) { - position -= 8; - } - - if (bz._init_block()) { - var start = outputStream.pos; - bz._read_bunzip(); - callback(position, outputStream.pos - start); - } else { - var crc = bz.reader.read(32); // (but we ignore the crc) - if (multistream && 'eof' in inputStream && !inputStream.eof()) { - // note that start_bunzip will also resync the bit reader to next byte - bz._start_bunzip(inputStream, outputStream); - console.assert(bz.dbufSize === blockSize, "shouldn't change block size within multistream file"); - } else break; - } - } -}; - -Bunzip.Stream = Stream; - -module.exports = Bunzip; - -},{"./bitreader":67,"./crc32":68,"./stream":70}],70:[function(require,module,exports){ -"use strict"; - -/* very simple input/output stream interface */ -var Stream = function Stream() {}; - -// input streams ////////////// -/** Returns the next byte, or -1 for EOF. */ -Stream.prototype.readByte = function () { - throw new Error("abstract method readByte() not implemented"); -}; -/** Attempts to fill the buffer; returns number of bytes read, or - * -1 for EOF. */ -Stream.prototype.read = function (buffer, bufOffset, length) { - var bytesRead = 0; - while (bytesRead < length) { - var c = this.readByte(); - if (c < 0) { - // EOF - return bytesRead === 0 ? -1 : bytesRead; - } - buffer[bufOffset++] = c; - bytesRead++; - } - return bytesRead; -}; -Stream.prototype.seek = function (new_pos) { - throw new Error("abstract method seek() not implemented"); -}; - -// output streams /////////// -Stream.prototype.writeByte = function (_byte) { - throw new Error("abstract method readByte() not implemented"); -}; -Stream.prototype.write = function (buffer, bufOffset, length) { - var i; - for (i = 0; i < length; i++) { - this.writeByte(buffer[bufOffset++]); - } - return length; -}; -Stream.prototype.flush = function () {}; - -module.exports = Stream; - -},{}],71:[function(require,module,exports){ -'use strict'; - -// This is free and unencumbered software released into the public domain. -// See LICENSE.md for more information. - -// -// Utilities -// - -/** - * @param {number} a The number to test. - * @param {number} min The minimum value in the range, inclusive. - * @param {number} max The maximum value in the range, inclusive. - * @return {boolean} True if a >= min and a <= max. - */ -function inRange(a, min, max) { - return min <= a && a <= max; -} - -/** - * @param {*} o - * @return {Object} - */ -function ToDictionary(o) { - if (o === undefined) return {}; - if (o === Object(o)) return o; - throw TypeError('Could not convert argument to dictionary'); -} - -/** - * @param {string} string Input string of UTF-16 code units. - * @return {!Array.} Code points. - */ -function stringToCodePoints(string) { - // https://heycam.github.io/webidl/#dfn-obtain-unicode - - // 1. Let S be the DOMString value. - var s = String(string); - - // 2. Let n be the length of S. - var n = s.length; - - // 3. Initialize i to 0. - var i = 0; - - // 4. Initialize U to be an empty sequence of Unicode characters. - var u = []; - - // 5. While i < n: - while (i < n) { - - // 1. Let c be the code unit in S at index i. - var c = s.charCodeAt(i); - - // 2. Depending on the value of c: - - // c < 0xD800 or c > 0xDFFF - if (c < 0xD800 || c > 0xDFFF) { - // Append to U the Unicode character with code point c. - u.push(c); - } - - // 0xDC00 ≤ c ≤ 0xDFFF - else if (0xDC00 <= c && c <= 0xDFFF) { - // Append to U a U+FFFD REPLACEMENT CHARACTER. - u.push(0xFFFD); - } - - // 0xD800 ≤ c ≤ 0xDBFF - else if (0xD800 <= c && c <= 0xDBFF) { - // 1. If i = n−1, then append to U a U+FFFD REPLACEMENT - // CHARACTER. - if (i === n - 1) { - u.push(0xFFFD); - } - // 2. Otherwise, i < n−1: - else { - // 1. Let d be the code unit in S at index i+1. - var d = string.charCodeAt(i + 1); - - // 2. If 0xDC00 ≤ d ≤ 0xDFFF, then: - if (0xDC00 <= d && d <= 0xDFFF) { - // 1. Let a be c & 0x3FF. - var a = c & 0x3FF; - - // 2. Let b be d & 0x3FF. - var b = d & 0x3FF; - - // 3. Append to U the Unicode character with code point - // 2^16+2^10*a+b. - u.push(0x10000 + (a << 10) + b); - - // 4. Set i to i+1. - i += 1; - } - - // 3. Otherwise, d < 0xDC00 or d > 0xDFFF. Append to U a - // U+FFFD REPLACEMENT CHARACTER. - else { - u.push(0xFFFD); - } - } - } - - // 3. Set i to i+1. - i += 1; - } - - // 6. Return U. - return u; -} - -/** - * @param {!Array.} code_points Array of code points. - * @return {string} string String of UTF-16 code units. - */ -function codePointsToString(code_points) { - var s = ''; - for (var i = 0; i < code_points.length; ++i) { - var cp = code_points[i]; - if (cp <= 0xFFFF) { - s += String.fromCharCode(cp); - } else { - cp -= 0x10000; - s += String.fromCharCode((cp >> 10) + 0xD800, - (cp & 0x3FF) + 0xDC00); - } - } - return s; -} - - -// -// Implementation of Encoding specification -// https://encoding.spec.whatwg.org/ -// - -// -// 3. Terminology -// - -/** - * End-of-stream is a special token that signifies no more tokens - * are in the stream. - * @const - */ var end_of_stream = -1; - -/** - * A stream represents an ordered sequence of tokens. - * - * @constructor - * @param {!(Array.|Uint8Array)} tokens Array of tokens that provide the - * stream. - */ -function Stream(tokens) { - /** @type {!Array.} */ - this.tokens = [].slice.call(tokens); -} - -Stream.prototype = { - /** - * @return {boolean} True if end-of-stream has been hit. - */ - endOfStream: function() { - return !this.tokens.length; - }, - - /** - * When a token is read from a stream, the first token in the - * stream must be returned and subsequently removed, and - * end-of-stream must be returned otherwise. - * - * @return {number} Get the next token from the stream, or - * end_of_stream. - */ - read: function() { - if (!this.tokens.length) - return end_of_stream; - return this.tokens.shift(); - }, - - /** - * When one or more tokens are prepended to a stream, those tokens - * must be inserted, in given order, before the first token in the - * stream. - * - * @param {(number|!Array.)} token The token(s) to prepend to the stream. - */ - prepend: function(token) { - if (Array.isArray(token)) { - var tokens = /**@type {!Array.}*/(token); - while (tokens.length) - this.tokens.unshift(tokens.pop()); - } else { - this.tokens.unshift(token); - } - }, - - /** - * When one or more tokens are pushed to a stream, those tokens - * must be inserted, in given order, after the last token in the - * stream. - * - * @param {(number|!Array.)} token The tokens(s) to prepend to the stream. - */ - push: function(token) { - if (Array.isArray(token)) { - var tokens = /**@type {!Array.}*/(token); - while (tokens.length) - this.tokens.push(tokens.shift()); - } else { - this.tokens.push(token); - } - } -}; - -// -// 4. Encodings -// - -// 4.1 Encoders and decoders - -/** @const */ -var finished = -1; - -/** - * @param {boolean} fatal If true, decoding errors raise an exception. - * @param {number=} opt_code_point Override the standard fallback code point. - * @return {number} The code point to insert on a decoding error. - */ -function decoderError(fatal, opt_code_point) { - if (fatal) - throw TypeError('Decoder error'); - return opt_code_point || 0xFFFD; -} - -// -// 7. API -// - -/** @const */ var DEFAULT_ENCODING = 'utf-8'; - -// 7.1 Interface TextDecoder - -/** - * @constructor - * @param {string=} encoding The label of the encoding; - * defaults to 'utf-8'. - * @param {Object=} options - */ -function TextDecoder(encoding, options) { - if (!(this instanceof TextDecoder)) { - return new TextDecoder(encoding, options); - } - encoding = encoding !== undefined ? String(encoding).toLowerCase() : DEFAULT_ENCODING; - if (encoding !== DEFAULT_ENCODING) { - throw new Error('Encoding not supported. Only utf-8 is supported'); - } - options = ToDictionary(options); - - /** @private @type {boolean} */ - this._streaming = false; - /** @private @type {boolean} */ - this._BOMseen = false; - /** @private @type {?Decoder} */ - this._decoder = null; - /** @private @type {boolean} */ - this._fatal = Boolean(options['fatal']); - /** @private @type {boolean} */ - this._ignoreBOM = Boolean(options['ignoreBOM']); - - Object.defineProperty(this, 'encoding', {value: 'utf-8'}); - Object.defineProperty(this, 'fatal', {value: this._fatal}); - Object.defineProperty(this, 'ignoreBOM', {value: this._ignoreBOM}); -} - -TextDecoder.prototype = { - /** - * @param {ArrayBufferView=} input The buffer of bytes to decode. - * @param {Object=} options - * @return {string} The decoded string. - */ - decode: function decode(input, options) { - var bytes; - if (typeof input === 'object' && input instanceof ArrayBuffer) { - bytes = new Uint8Array(input); - } else if (typeof input === 'object' && 'buffer' in input && - input.buffer instanceof ArrayBuffer) { - bytes = new Uint8Array(input.buffer, - input.byteOffset, - input.byteLength); - } else { - bytes = new Uint8Array(0); - } - - options = ToDictionary(options); - - if (!this._streaming) { - this._decoder = new UTF8Decoder({fatal: this._fatal}); - this._BOMseen = false; - } - this._streaming = Boolean(options['stream']); - - var input_stream = new Stream(bytes); - - var code_points = []; - - /** @type {?(number|!Array.)} */ - var result; - - while (!input_stream.endOfStream()) { - result = this._decoder.handler(input_stream, input_stream.read()); - if (result === finished) - break; - if (result === null) - continue; - if (Array.isArray(result)) - code_points.push.apply(code_points, /**@type {!Array.}*/(result)); - else - code_points.push(result); - } - if (!this._streaming) { - do { - result = this._decoder.handler(input_stream, input_stream.read()); - if (result === finished) - break; - if (result === null) - continue; - if (Array.isArray(result)) - code_points.push.apply(code_points, /**@type {!Array.}*/(result)); - else - code_points.push(result); - } while (!input_stream.endOfStream()); - this._decoder = null; - } - - if (code_points.length) { - // If encoding is one of utf-8, utf-16be, and utf-16le, and - // ignore BOM flag and BOM seen flag are unset, run these - // subsubsteps: - if (['utf-8'].indexOf(this.encoding) !== -1 && - !this._ignoreBOM && !this._BOMseen) { - // If token is U+FEFF, set BOM seen flag. - if (code_points[0] === 0xFEFF) { - this._BOMseen = true; - code_points.shift(); - } else { - // Otherwise, if token is not end-of-stream, set BOM seen - // flag and append token to output. - this._BOMseen = true; - } - } - } - - return codePointsToString(code_points); - } -}; - -// 7.2 Interface TextEncoder - -/** - * @constructor - * @param {string=} encoding The label of the encoding; - * defaults to 'utf-8'. - * @param {Object=} options - */ -function TextEncoder(encoding, options) { - if (!(this instanceof TextEncoder)) - return new TextEncoder(encoding, options); - encoding = encoding !== undefined ? String(encoding).toLowerCase() : DEFAULT_ENCODING; - if (encoding !== DEFAULT_ENCODING) { - throw new Error('Encoding not supported. Only utf-8 is supported'); - } - options = ToDictionary(options); - - /** @private @type {boolean} */ - this._streaming = false; - /** @private @type {?Encoder} */ - this._encoder = null; - /** @private @type {{fatal: boolean}} */ - this._options = {fatal: Boolean(options['fatal'])}; - - Object.defineProperty(this, 'encoding', {value: 'utf-8'}); -} - -TextEncoder.prototype = { - /** - * @param {string=} opt_string The string to encode. - * @param {Object=} options - * @return {Uint8Array} Encoded bytes, as a Uint8Array. - */ - encode: function encode(opt_string, options) { - opt_string = opt_string ? String(opt_string) : ''; - options = ToDictionary(options); - - // NOTE: This option is nonstandard. None of the encodings - // permitted for encoding (i.e. UTF-8, UTF-16) are stateful, - // so streaming is not necessary. - if (!this._streaming) - this._encoder = new UTF8Encoder(this._options); - this._streaming = Boolean(options['stream']); - - var bytes = []; - var input_stream = new Stream(stringToCodePoints(opt_string)); - /** @type {?(number|!Array.)} */ - var result; - while (!input_stream.endOfStream()) { - result = this._encoder.handler(input_stream, input_stream.read()); - if (result === finished) - break; - if (Array.isArray(result)) - bytes.push.apply(bytes, /**@type {!Array.}*/(result)); - else - bytes.push(result); - } - if (!this._streaming) { - while (true) { - result = this._encoder.handler(input_stream, input_stream.read()); - if (result === finished) - break; - if (Array.isArray(result)) - bytes.push.apply(bytes, /**@type {!Array.}*/(result)); - else - bytes.push(result); - } - this._encoder = null; - } - return new Uint8Array(bytes); - } -}; - -// -// 8. The encoding -// - -// 8.1 utf-8 - -/** - * @constructor - * @implements {Decoder} - * @param {{fatal: boolean}} options - */ -function UTF8Decoder(options) { - var fatal = options.fatal; - - // utf-8's decoder's has an associated utf-8 code point, utf-8 - // bytes seen, and utf-8 bytes needed (all initially 0), a utf-8 - // lower boundary (initially 0x80), and a utf-8 upper boundary - // (initially 0xBF). - var /** @type {number} */ utf8_code_point = 0, - /** @type {number} */ utf8_bytes_seen = 0, - /** @type {number} */ utf8_bytes_needed = 0, - /** @type {number} */ utf8_lower_boundary = 0x80, - /** @type {number} */ utf8_upper_boundary = 0xBF; - - /** - * @param {Stream} stream The stream of bytes being decoded. - * @param {number} bite The next byte read from the stream. - * @return {?(number|!Array.)} The next code point(s) - * decoded, or null if not enough data exists in the input - * stream to decode a complete code point. - */ - this.handler = function(stream, bite) { - // 1. If byte is end-of-stream and utf-8 bytes needed is not 0, - // set utf-8 bytes needed to 0 and return error. - if (bite === end_of_stream && utf8_bytes_needed !== 0) { - utf8_bytes_needed = 0; - return decoderError(fatal); - } - - // 2. If byte is end-of-stream, return finished. - if (bite === end_of_stream) - return finished; - - // 3. If utf-8 bytes needed is 0, based on byte: - if (utf8_bytes_needed === 0) { - - // 0x00 to 0x7F - if (inRange(bite, 0x00, 0x7F)) { - // Return a code point whose value is byte. - return bite; - } - - // 0xC2 to 0xDF - if (inRange(bite, 0xC2, 0xDF)) { - // Set utf-8 bytes needed to 1 and utf-8 code point to byte - // − 0xC0. - utf8_bytes_needed = 1; - utf8_code_point = bite - 0xC0; - } - - // 0xE0 to 0xEF - else if (inRange(bite, 0xE0, 0xEF)) { - // 1. If byte is 0xE0, set utf-8 lower boundary to 0xA0. - if (bite === 0xE0) - utf8_lower_boundary = 0xA0; - // 2. If byte is 0xED, set utf-8 upper boundary to 0x9F. - if (bite === 0xED) - utf8_upper_boundary = 0x9F; - // 3. Set utf-8 bytes needed to 2 and utf-8 code point to - // byte − 0xE0. - utf8_bytes_needed = 2; - utf8_code_point = bite - 0xE0; - } - - // 0xF0 to 0xF4 - else if (inRange(bite, 0xF0, 0xF4)) { - // 1. If byte is 0xF0, set utf-8 lower boundary to 0x90. - if (bite === 0xF0) - utf8_lower_boundary = 0x90; - // 2. If byte is 0xF4, set utf-8 upper boundary to 0x8F. - if (bite === 0xF4) - utf8_upper_boundary = 0x8F; - // 3. Set utf-8 bytes needed to 3 and utf-8 code point to - // byte − 0xF0. - utf8_bytes_needed = 3; - utf8_code_point = bite - 0xF0; - } - - // Otherwise - else { - // Return error. - return decoderError(fatal); - } - - // Then (byte is in the range 0xC2 to 0xF4) set utf-8 code - // point to utf-8 code point << (6 × utf-8 bytes needed) and - // return continue. - utf8_code_point = utf8_code_point << (6 * utf8_bytes_needed); - return null; - } - - // 4. If byte is not in the range utf-8 lower boundary to utf-8 - // upper boundary, run these substeps: - if (!inRange(bite, utf8_lower_boundary, utf8_upper_boundary)) { - - // 1. Set utf-8 code point, utf-8 bytes needed, and utf-8 - // bytes seen to 0, set utf-8 lower boundary to 0x80, and set - // utf-8 upper boundary to 0xBF. - utf8_code_point = utf8_bytes_needed = utf8_bytes_seen = 0; - utf8_lower_boundary = 0x80; - utf8_upper_boundary = 0xBF; - - // 2. Prepend byte to stream. - stream.prepend(bite); - - // 3. Return error. - return decoderError(fatal); - } - - // 5. Set utf-8 lower boundary to 0x80 and utf-8 upper boundary - // to 0xBF. - utf8_lower_boundary = 0x80; - utf8_upper_boundary = 0xBF; - - // 6. Increase utf-8 bytes seen by one and set utf-8 code point - // to utf-8 code point + (byte − 0x80) << (6 × (utf-8 bytes - // needed − utf-8 bytes seen)). - utf8_bytes_seen += 1; - utf8_code_point += (bite - 0x80) << (6 * (utf8_bytes_needed - utf8_bytes_seen)); - - // 7. If utf-8 bytes seen is not equal to utf-8 bytes needed, - // continue. - if (utf8_bytes_seen !== utf8_bytes_needed) - return null; - - // 8. Let code point be utf-8 code point. - var code_point = utf8_code_point; - - // 9. Set utf-8 code point, utf-8 bytes needed, and utf-8 bytes - // seen to 0. - utf8_code_point = utf8_bytes_needed = utf8_bytes_seen = 0; - - // 10. Return a code point whose value is code point. - return code_point; - }; -} - -/** - * @constructor - * @implements {Encoder} - * @param {{fatal: boolean}} options - */ -function UTF8Encoder(options) { - var fatal = options.fatal; - /** - * @param {Stream} stream Input stream. - * @param {number} code_point Next code point read from the stream. - * @return {(number|!Array.)} Byte(s) to emit. - */ - this.handler = function(stream, code_point) { - // 1. If code point is end-of-stream, return finished. - if (code_point === end_of_stream) - return finished; - - // 2. If code point is in the range U+0000 to U+007F, return a - // byte whose value is code point. - if (inRange(code_point, 0x0000, 0x007f)) - return code_point; - - // 3. Set count and offset based on the range code point is in: - var count, offset; - // U+0080 to U+07FF: 1 and 0xC0 - if (inRange(code_point, 0x0080, 0x07FF)) { - count = 1; - offset = 0xC0; - } - // U+0800 to U+FFFF: 2 and 0xE0 - else if (inRange(code_point, 0x0800, 0xFFFF)) { - count = 2; - offset = 0xE0; - } - // U+10000 to U+10FFFF: 3 and 0xF0 - else if (inRange(code_point, 0x10000, 0x10FFFF)) { - count = 3; - offset = 0xF0; - } - - // 4.Let bytes be a byte sequence whose first byte is (code - // point >> (6 × count)) + offset. - var bytes = [(code_point >> (6 * count)) + offset]; - - // 5. Run these substeps while count is greater than 0: - while (count > 0) { - - // 1. Set temp to code point >> (6 × (count − 1)). - var temp = code_point >> (6 * (count - 1)); - - // 2. Append to bytes 0x80 | (temp & 0x3F). - bytes.push(0x80 | (temp & 0x3F)); - - // 3. Decrease count by one. - count -= 1; - } - - // 6. Return bytes bytes, in order. - return bytes; - }; -} - -exports.TextEncoder = TextEncoder; -exports.TextDecoder = TextDecoder; -},{}],72:[function(require,module,exports){ -/*jshint bitwise: false*/ - -(function(nacl) { -'use strict'; - -// Ported in 2014 by Dmitry Chestnykh and Devi Mandiri. -// Public domain. -// -// Implementation derived from TweetNaCl version 20140427. -// See for details: http://tweetnacl.cr.yp.to/ - -var gf = function(init) { - var i, r = new Float64Array(16); - if (init) for (i = 0; i < init.length; i++) r[i] = init[i]; - return r; -}; - -// Pluggable, initialized in high-level API below. -var randombytes = function(/* x, n */) { throw new Error('no PRNG'); }; - -var _9 = new Uint8Array(32); _9[0] = 9; - -var gf0 = gf(), - gf1 = gf([1]), - _121665 = gf([0xdb41, 1]), - D = gf([0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203]), - D2 = gf([0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406]), - X = gf([0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169]), - Y = gf([0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666]), - I = gf([0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83]); - -function vn(x, xi, y, yi, n) { - var i,d = 0; - for (i = 0; i < n; i++) d |= x[xi+i]^y[yi+i]; - return (1 & ((d - 1) >>> 8)) - 1; -} - -function crypto_verify_32(x, xi, y, yi) { - return vn(x,xi,y,yi,32); -} - -function set25519(r, a) { - var i; - for (i = 0; i < 16; i++) r[i] = a[i]|0; -} - -function car25519(o) { - var i, v, c = 1; - for (i = 0; i < 16; i++) { - v = o[i] + c + 65535; - c = Math.floor(v / 65536); - o[i] = v - c * 65536; - } - o[0] += c-1 + 37 * (c-1); -} - -function sel25519(p, q, b) { - var t, c = ~(b-1); - for (var i = 0; i < 16; i++) { - t = c & (p[i] ^ q[i]); - p[i] ^= t; - q[i] ^= t; - } -} - -function pack25519(o, n) { - var i, j, b; - var m = gf(), t = gf(); - for (i = 0; i < 16; i++) t[i] = n[i]; - car25519(t); - car25519(t); - car25519(t); - for (j = 0; j < 2; j++) { - m[0] = t[0] - 0xffed; - for (i = 1; i < 15; i++) { - m[i] = t[i] - 0xffff - ((m[i-1]>>16) & 1); - m[i-1] &= 0xffff; - } - m[15] = t[15] - 0x7fff - ((m[14]>>16) & 1); - b = (m[15]>>16) & 1; - m[14] &= 0xffff; - sel25519(t, m, 1-b); - } - for (i = 0; i < 16; i++) { - o[2*i] = t[i] & 0xff; - o[2*i+1] = t[i]>>8; - } -} - -function neq25519(a, b) { - var c = new Uint8Array(32), d = new Uint8Array(32); - pack25519(c, a); - pack25519(d, b); - return crypto_verify_32(c, 0, d, 0); -} - -function par25519(a) { - var d = new Uint8Array(32); - pack25519(d, a); - return d[0] & 1; -} - -function unpack25519(o, n) { - var i; - for (i = 0; i < 16; i++) o[i] = n[2*i] + (n[2*i+1] << 8); - o[15] &= 0x7fff; -} - -function A(o, a, b) { - for (var i = 0; i < 16; i++) o[i] = a[i] + b[i]; -} - -function Z(o, a, b) { - for (var i = 0; i < 16; i++) o[i] = a[i] - b[i]; -} - -function M(o, a, b) { - var v, c, - t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0, - t8 = 0, t9 = 0, t10 = 0, t11 = 0, t12 = 0, t13 = 0, t14 = 0, t15 = 0, - t16 = 0, t17 = 0, t18 = 0, t19 = 0, t20 = 0, t21 = 0, t22 = 0, t23 = 0, - t24 = 0, t25 = 0, t26 = 0, t27 = 0, t28 = 0, t29 = 0, t30 = 0, - b0 = b[0], - b1 = b[1], - b2 = b[2], - b3 = b[3], - b4 = b[4], - b5 = b[5], - b6 = b[6], - b7 = b[7], - b8 = b[8], - b9 = b[9], - b10 = b[10], - b11 = b[11], - b12 = b[12], - b13 = b[13], - b14 = b[14], - b15 = b[15]; - - v = a[0]; - t0 += v * b0; - t1 += v * b1; - t2 += v * b2; - t3 += v * b3; - t4 += v * b4; - t5 += v * b5; - t6 += v * b6; - t7 += v * b7; - t8 += v * b8; - t9 += v * b9; - t10 += v * b10; - t11 += v * b11; - t12 += v * b12; - t13 += v * b13; - t14 += v * b14; - t15 += v * b15; - v = a[1]; - t1 += v * b0; - t2 += v * b1; - t3 += v * b2; - t4 += v * b3; - t5 += v * b4; - t6 += v * b5; - t7 += v * b6; - t8 += v * b7; - t9 += v * b8; - t10 += v * b9; - t11 += v * b10; - t12 += v * b11; - t13 += v * b12; - t14 += v * b13; - t15 += v * b14; - t16 += v * b15; - v = a[2]; - t2 += v * b0; - t3 += v * b1; - t4 += v * b2; - t5 += v * b3; - t6 += v * b4; - t7 += v * b5; - t8 += v * b6; - t9 += v * b7; - t10 += v * b8; - t11 += v * b9; - t12 += v * b10; - t13 += v * b11; - t14 += v * b12; - t15 += v * b13; - t16 += v * b14; - t17 += v * b15; - v = a[3]; - t3 += v * b0; - t4 += v * b1; - t5 += v * b2; - t6 += v * b3; - t7 += v * b4; - t8 += v * b5; - t9 += v * b6; - t10 += v * b7; - t11 += v * b8; - t12 += v * b9; - t13 += v * b10; - t14 += v * b11; - t15 += v * b12; - t16 += v * b13; - t17 += v * b14; - t18 += v * b15; - v = a[4]; - t4 += v * b0; - t5 += v * b1; - t6 += v * b2; - t7 += v * b3; - t8 += v * b4; - t9 += v * b5; - t10 += v * b6; - t11 += v * b7; - t12 += v * b8; - t13 += v * b9; - t14 += v * b10; - t15 += v * b11; - t16 += v * b12; - t17 += v * b13; - t18 += v * b14; - t19 += v * b15; - v = a[5]; - t5 += v * b0; - t6 += v * b1; - t7 += v * b2; - t8 += v * b3; - t9 += v * b4; - t10 += v * b5; - t11 += v * b6; - t12 += v * b7; - t13 += v * b8; - t14 += v * b9; - t15 += v * b10; - t16 += v * b11; - t17 += v * b12; - t18 += v * b13; - t19 += v * b14; - t20 += v * b15; - v = a[6]; - t6 += v * b0; - t7 += v * b1; - t8 += v * b2; - t9 += v * b3; - t10 += v * b4; - t11 += v * b5; - t12 += v * b6; - t13 += v * b7; - t14 += v * b8; - t15 += v * b9; - t16 += v * b10; - t17 += v * b11; - t18 += v * b12; - t19 += v * b13; - t20 += v * b14; - t21 += v * b15; - v = a[7]; - t7 += v * b0; - t8 += v * b1; - t9 += v * b2; - t10 += v * b3; - t11 += v * b4; - t12 += v * b5; - t13 += v * b6; - t14 += v * b7; - t15 += v * b8; - t16 += v * b9; - t17 += v * b10; - t18 += v * b11; - t19 += v * b12; - t20 += v * b13; - t21 += v * b14; - t22 += v * b15; - v = a[8]; - t8 += v * b0; - t9 += v * b1; - t10 += v * b2; - t11 += v * b3; - t12 += v * b4; - t13 += v * b5; - t14 += v * b6; - t15 += v * b7; - t16 += v * b8; - t17 += v * b9; - t18 += v * b10; - t19 += v * b11; - t20 += v * b12; - t21 += v * b13; - t22 += v * b14; - t23 += v * b15; - v = a[9]; - t9 += v * b0; - t10 += v * b1; - t11 += v * b2; - t12 += v * b3; - t13 += v * b4; - t14 += v * b5; - t15 += v * b6; - t16 += v * b7; - t17 += v * b8; - t18 += v * b9; - t19 += v * b10; - t20 += v * b11; - t21 += v * b12; - t22 += v * b13; - t23 += v * b14; - t24 += v * b15; - v = a[10]; - t10 += v * b0; - t11 += v * b1; - t12 += v * b2; - t13 += v * b3; - t14 += v * b4; - t15 += v * b5; - t16 += v * b6; - t17 += v * b7; - t18 += v * b8; - t19 += v * b9; - t20 += v * b10; - t21 += v * b11; - t22 += v * b12; - t23 += v * b13; - t24 += v * b14; - t25 += v * b15; - v = a[11]; - t11 += v * b0; - t12 += v * b1; - t13 += v * b2; - t14 += v * b3; - t15 += v * b4; - t16 += v * b5; - t17 += v * b6; - t18 += v * b7; - t19 += v * b8; - t20 += v * b9; - t21 += v * b10; - t22 += v * b11; - t23 += v * b12; - t24 += v * b13; - t25 += v * b14; - t26 += v * b15; - v = a[12]; - t12 += v * b0; - t13 += v * b1; - t14 += v * b2; - t15 += v * b3; - t16 += v * b4; - t17 += v * b5; - t18 += v * b6; - t19 += v * b7; - t20 += v * b8; - t21 += v * b9; - t22 += v * b10; - t23 += v * b11; - t24 += v * b12; - t25 += v * b13; - t26 += v * b14; - t27 += v * b15; - v = a[13]; - t13 += v * b0; - t14 += v * b1; - t15 += v * b2; - t16 += v * b3; - t17 += v * b4; - t18 += v * b5; - t19 += v * b6; - t20 += v * b7; - t21 += v * b8; - t22 += v * b9; - t23 += v * b10; - t24 += v * b11; - t25 += v * b12; - t26 += v * b13; - t27 += v * b14; - t28 += v * b15; - v = a[14]; - t14 += v * b0; - t15 += v * b1; - t16 += v * b2; - t17 += v * b3; - t18 += v * b4; - t19 += v * b5; - t20 += v * b6; - t21 += v * b7; - t22 += v * b8; - t23 += v * b9; - t24 += v * b10; - t25 += v * b11; - t26 += v * b12; - t27 += v * b13; - t28 += v * b14; - t29 += v * b15; - v = a[15]; - t15 += v * b0; - t16 += v * b1; - t17 += v * b2; - t18 += v * b3; - t19 += v * b4; - t20 += v * b5; - t21 += v * b6; - t22 += v * b7; - t23 += v * b8; - t24 += v * b9; - t25 += v * b10; - t26 += v * b11; - t27 += v * b12; - t28 += v * b13; - t29 += v * b14; - t30 += v * b15; - - t0 += 38 * t16; - t1 += 38 * t17; - t2 += 38 * t18; - t3 += 38 * t19; - t4 += 38 * t20; - t5 += 38 * t21; - t6 += 38 * t22; - t7 += 38 * t23; - t8 += 38 * t24; - t9 += 38 * t25; - t10 += 38 * t26; - t11 += 38 * t27; - t12 += 38 * t28; - t13 += 38 * t29; - t14 += 38 * t30; - // t15 left as is - - // first car - c = 1; - v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536; - v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536; - v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536; - v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536; - v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536; - v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536; - v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536; - v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536; - v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536; - v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536; - v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536; - v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536; - v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536; - v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536; - v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536; - v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536; - t0 += c-1 + 37 * (c-1); - - // second car - c = 1; - v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536; - v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536; - v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536; - v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536; - v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536; - v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536; - v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536; - v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536; - v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536; - v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536; - v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536; - v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536; - v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536; - v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536; - v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536; - v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536; - t0 += c-1 + 37 * (c-1); - - o[ 0] = t0; - o[ 1] = t1; - o[ 2] = t2; - o[ 3] = t3; - o[ 4] = t4; - o[ 5] = t5; - o[ 6] = t6; - o[ 7] = t7; - o[ 8] = t8; - o[ 9] = t9; - o[10] = t10; - o[11] = t11; - o[12] = t12; - o[13] = t13; - o[14] = t14; - o[15] = t15; -} - -function S(o, a) { - M(o, a, a); -} - -function inv25519(o, i) { - var c = gf(); - var a; - for (a = 0; a < 16; a++) c[a] = i[a]; - for (a = 253; a >= 0; a--) { - S(c, c); - if(a !== 2 && a !== 4) M(c, c, i); - } - for (a = 0; a < 16; a++) o[a] = c[a]; -} - -function pow2523(o, i) { - var c = gf(); - var a; - for (a = 0; a < 16; a++) c[a] = i[a]; - for (a = 250; a >= 0; a--) { - S(c, c); - if(a !== 1) M(c, c, i); - } - for (a = 0; a < 16; a++) o[a] = c[a]; -} - -function crypto_scalarmult(q, n, p) { - var z = new Uint8Array(32); - var x = new Float64Array(80), r, i; - var a = gf(), b = gf(), c = gf(), - d = gf(), e = gf(), f = gf(); - for (i = 0; i < 31; i++) z[i] = n[i]; - z[31]=(n[31]&127)|64; - z[0]&=248; - unpack25519(x,p); - for (i = 0; i < 16; i++) { - b[i]=x[i]; - d[i]=a[i]=c[i]=0; - } - a[0]=d[0]=1; - for (i=254; i>=0; --i) { - r=(z[i>>>3]>>>(i&7))&1; - sel25519(a,b,r); - sel25519(c,d,r); - A(e,a,c); - Z(a,a,c); - A(c,b,d); - Z(b,b,d); - S(d,e); - S(f,a); - M(a,c,a); - M(c,b,e); - A(e,a,c); - Z(a,a,c); - S(b,a); - Z(c,d,f); - M(a,c,_121665); - A(a,a,d); - M(c,c,a); - M(a,d,f); - M(d,b,x); - S(b,e); - sel25519(a,b,r); - sel25519(c,d,r); - } - for (i = 0; i < 16; i++) { - x[i+16]=a[i]; - x[i+32]=c[i]; - x[i+48]=b[i]; - x[i+64]=d[i]; - } - var x32 = x.subarray(32); - var x16 = x.subarray(16); - inv25519(x32,x32); - M(x16,x16,x32); - pack25519(q,x16); - return 0; -} - -function crypto_scalarmult_base(q, n) { - return crypto_scalarmult(q, n, _9); -} - -function crypto_box_keypair(y, x) { - randombytes(x, 32); - return crypto_scalarmult_base(y, x); -} - -function add(p, q) { - var a = gf(), b = gf(), c = gf(), - d = gf(), e = gf(), f = gf(), - g = gf(), h = gf(), t = gf(); - - Z(a, p[1], p[0]); - Z(t, q[1], q[0]); - M(a, a, t); - A(b, p[0], p[1]); - A(t, q[0], q[1]); - M(b, b, t); - M(c, p[3], q[3]); - M(c, c, D2); - M(d, p[2], q[2]); - A(d, d, d); - Z(e, b, a); - Z(f, d, c); - A(g, d, c); - A(h, b, a); - - M(p[0], e, f); - M(p[1], h, g); - M(p[2], g, f); - M(p[3], e, h); -} - -function cswap(p, q, b) { - var i; - for (i = 0; i < 4; i++) { - sel25519(p[i], q[i], b); - } -} - -function pack(r, p) { - var tx = gf(), ty = gf(), zi = gf(); - inv25519(zi, p[2]); - M(tx, p[0], zi); - M(ty, p[1], zi); - pack25519(r, ty); - r[31] ^= par25519(tx) << 7; -} - -function scalarmult(p, q, s) { - var b, i; - set25519(p[0], gf0); - set25519(p[1], gf1); - set25519(p[2], gf1); - set25519(p[3], gf0); - for (i = 255; i >= 0; --i) { - b = (s[(i/8)|0] >> (i&7)) & 1; - cswap(p, q, b); - add(q, p); - add(p, p); - cswap(p, q, b); - } -} - -function scalarbase(p, s) { - var q = [gf(), gf(), gf(), gf()]; - set25519(q[0], X); - set25519(q[1], Y); - set25519(q[2], gf1); - M(q[3], X, Y); - scalarmult(p, q, s); -} - -function crypto_sign_keypair(pk, sk, seeded) { - var d; - var p = [gf(), gf(), gf(), gf()]; - var i; - - if (!seeded) randombytes(sk, 32); - d = nacl.hash(sk.subarray(0, 32)); - d[0] &= 248; - d[31] &= 127; - d[31] |= 64; - - scalarbase(p, d); - pack(pk, p); - - for (i = 0; i < 32; i++) sk[i+32] = pk[i]; - return 0; -} - -var L = new Float64Array([0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10]); - -function modL(r, x) { - var carry, i, j, k; - for (i = 63; i >= 32; --i) { - carry = 0; - for (j = i - 32, k = i - 12; j < k; ++j) { - x[j] += carry - 16 * x[i] * L[j - (i - 32)]; - carry = (x[j] + 128) >> 8; - x[j] -= carry * 256; - } - x[j] += carry; - x[i] = 0; - } - carry = 0; - for (j = 0; j < 32; j++) { - x[j] += carry - (x[31] >> 4) * L[j]; - carry = x[j] >> 8; - x[j] &= 255; - } - for (j = 0; j < 32; j++) x[j] -= carry * L[j]; - for (i = 0; i < 32; i++) { - x[i+1] += x[i] >> 8; - r[i] = x[i] & 255; - } -} - -function reduce(r) { - var x = new Float64Array(64), i; - for (i = 0; i < 64; i++) x[i] = r[i]; - for (i = 0; i < 64; i++) r[i] = 0; - modL(r, x); -} - -// Note: difference from C - smlen returned, not passed as argument. -function crypto_sign(sm, m, n, sk) { - var d, h, r; - var i, j, x = new Float64Array(64); - var p = [gf(), gf(), gf(), gf()]; - - d = nacl.hash(sk.subarray(0, 32)); - d[0] &= 248; - d[31] &= 127; - d[31] |= 64; - - var smlen = n + 64; - for (i = 0; i < n; i++) sm[64 + i] = m[i]; - for (i = 0; i < 32; i++) sm[32 + i] = d[32 + i]; - - r = nacl.hash(sm.subarray(32, smlen)); - reduce(r); - scalarbase(p, r); - pack(sm, p); - - for (i = 32; i < 64; i++) sm[i] = sk[i]; - h = nacl.hash(sm.subarray(0, smlen)); - reduce(h); - - for (i = 0; i < 64; i++) x[i] = 0; - for (i = 0; i < 32; i++) x[i] = r[i]; - for (i = 0; i < 32; i++) { - for (j = 0; j < 32; j++) { - x[i+j] += h[i] * d[j]; - } - } - - modL(sm.subarray(32), x); - return smlen; -} - -function unpackneg(r, p) { - var t = gf(), chk = gf(), num = gf(), - den = gf(), den2 = gf(), den4 = gf(), - den6 = gf(); - - set25519(r[2], gf1); - unpack25519(r[1], p); - S(num, r[1]); - M(den, num, D); - Z(num, num, r[2]); - A(den, r[2], den); - - S(den2, den); - S(den4, den2); - M(den6, den4, den2); - M(t, den6, num); - M(t, t, den); - - pow2523(t, t); - M(t, t, num); - M(t, t, den); - M(t, t, den); - M(r[0], t, den); - - S(chk, r[0]); - M(chk, chk, den); - if (neq25519(chk, num)) M(r[0], r[0], I); - - S(chk, r[0]); - M(chk, chk, den); - if (neq25519(chk, num)) return -1; - - if (par25519(r[0]) === (p[31]>>7)) Z(r[0], gf0, r[0]); - - M(r[3], r[0], r[1]); - return 0; -} - -function crypto_sign_open(m, sm, n, pk) { - var i, mlen; - var t = new Uint8Array(32), h; - var p = [gf(), gf(), gf(), gf()], - q = [gf(), gf(), gf(), gf()]; - - mlen = -1; - if (n < 64) return -1; - - if (unpackneg(q, pk)) return -1; - - for (i = 0; i < n; i++) m[i] = sm[i]; - for (i = 0; i < 32; i++) m[i+32] = pk[i]; - h = nacl.hash(m.subarray(0, n)); - reduce(h); - scalarmult(p, q, h); - - scalarbase(q, sm.subarray(32)); - add(p, q); - pack(t, p); - - n -= 64; - if (crypto_verify_32(sm, 0, t, 0)) { - for (i = 0; i < n; i++) m[i] = 0; - return -1; - } - - for (i = 0; i < n; i++) m[i] = sm[i + 64]; - mlen = n; - return mlen; -} - -var crypto_scalarmult_BYTES = 32, - crypto_scalarmult_SCALARBYTES = 32, - crypto_box_PUBLICKEYBYTES = 32, - crypto_box_SECRETKEYBYTES = 32, - crypto_sign_BYTES = 64, - crypto_sign_PUBLICKEYBYTES = 32, - crypto_sign_SECRETKEYBYTES = 64, - crypto_sign_SEEDBYTES = 32; - -function checkArrayTypes() { - for (var i = 0; i < arguments.length; i++) { - if (!(arguments[i] instanceof Uint8Array)) - throw new TypeError('unexpected type, use Uint8Array'); - } -} - -function cleanup(arr) { - for (var i = 0; i < arr.length; i++) arr[i] = 0; -} - -nacl.scalarMult = function(n, p) { - checkArrayTypes(n, p); - if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error('bad n size'); - if (p.length !== crypto_scalarmult_BYTES) throw new Error('bad p size'); - var q = new Uint8Array(crypto_scalarmult_BYTES); - crypto_scalarmult(q, n, p); - return q; -}; - -nacl.box = {}; - -nacl.box.keyPair = function() { - var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); - var sk = new Uint8Array(crypto_box_SECRETKEYBYTES); - crypto_box_keypair(pk, sk); - return {publicKey: pk, secretKey: sk}; -}; - -nacl.box.keyPair.fromSecretKey = function(secretKey) { - checkArrayTypes(secretKey); - if (secretKey.length !== crypto_box_SECRETKEYBYTES) - throw new Error('bad secret key size'); - var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); - crypto_scalarmult_base(pk, secretKey); - return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; -}; - -nacl.sign = function(msg, secretKey) { - checkArrayTypes(msg, secretKey); - if (secretKey.length !== crypto_sign_SECRETKEYBYTES) - throw new Error('bad secret key size'); - var signedMsg = new Uint8Array(crypto_sign_BYTES+msg.length); - crypto_sign(signedMsg, msg, msg.length, secretKey); - return signedMsg; -}; - -nacl.sign.detached = function(msg, secretKey) { - var signedMsg = nacl.sign(msg, secretKey); - var sig = new Uint8Array(crypto_sign_BYTES); - for (var i = 0; i < sig.length; i++) sig[i] = signedMsg[i]; - return sig; -}; - -nacl.sign.detached.verify = function(msg, sig, publicKey) { - checkArrayTypes(msg, sig, publicKey); - if (sig.length !== crypto_sign_BYTES) - throw new Error('bad signature size'); - if (publicKey.length !== crypto_sign_PUBLICKEYBYTES) - throw new Error('bad public key size'); - var sm = new Uint8Array(crypto_sign_BYTES + msg.length); - var m = new Uint8Array(crypto_sign_BYTES + msg.length); - var i; - for (i = 0; i < crypto_sign_BYTES; i++) sm[i] = sig[i]; - for (i = 0; i < msg.length; i++) sm[i+crypto_sign_BYTES] = msg[i]; - return (crypto_sign_open(m, sm, sm.length, publicKey) >= 0); -}; - -nacl.sign.keyPair = function() { - var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); - var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); - crypto_sign_keypair(pk, sk); - return {publicKey: pk, secretKey: sk}; -}; - -nacl.sign.keyPair.fromSecretKey = function(secretKey) { - checkArrayTypes(secretKey); - if (secretKey.length !== crypto_sign_SECRETKEYBYTES) - throw new Error('bad secret key size'); - var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); - for (var i = 0; i < pk.length; i++) pk[i] = secretKey[32+i]; - return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; -}; - -nacl.sign.keyPair.fromSeed = function(seed) { - checkArrayTypes(seed); - if (seed.length !== crypto_sign_SEEDBYTES) - throw new Error('bad seed size'); - var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); - var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); - for (var i = 0; i < 32; i++) sk[i] = seed[i]; - crypto_sign_keypair(pk, sk, true); - return {publicKey: pk, secretKey: sk}; -}; - -nacl.setPRNG = function(fn) { - randombytes = fn; -}; - -(function() { - // Initialize PRNG if environment provides CSPRNG. - // If not, methods calling randombytes will throw. - var crypto = typeof self !== 'undefined' ? (self.crypto || self.msCrypto) : null; - if (crypto && crypto.getRandomValues) { - // Browsers. - var QUOTA = 65536; - nacl.setPRNG(function(x, n) { - var i, v = new Uint8Array(n); - for (i = 0; i < n; i += QUOTA) { - crypto.getRandomValues(v.subarray(i, i + Math.min(n - i, QUOTA))); - } - for (i = 0; i < n; i++) x[i] = v[i]; - cleanup(v); - }); - } else if (typeof require !== 'undefined') { - // Node.js. - crypto = require('crypto'); - if (crypto && crypto.randomBytes) { - nacl.setPRNG(function(x, n) { - var i, v = crypto.randomBytes(n); - for (i = 0; i < n; i++) x[i] = v[i]; - cleanup(v); - }); - } - } -})(); - -})(typeof module !== 'undefined' && module.exports ? module.exports : (self.nacl = self.nacl || {})); - -},{"crypto":"crypto"}],73:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.webToNode = exports.nodeToWeb = undefined; - -var _util = require('./util'); - -var _streams = require('./streams'); - -var _streams2 = _interopRequireDefault(_streams); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const NodeReadableStream = _util.isNode && require('stream').Readable; - -/** - * Web / node stream conversion functions - * From https://github.com/gwicke/node-web-streams - */ - -let nodeToWeb; -let webToNode; - -if (NodeReadableStream) { - - /** - * Convert a Node Readable Stream to a Web ReadableStream - * @param {Readable} nodeStream - * @returns {ReadableStream} - */ - exports.nodeToWeb = nodeToWeb = function nodeToWeb(nodeStream) { - return new ReadableStream({ - start(controller) { - nodeStream.pause(); - nodeStream.on('data', chunk => { - controller.enqueue(chunk); - nodeStream.pause(); - }); - nodeStream.on('end', () => controller.close()); - nodeStream.on('error', e => controller.error(e)); - }, - pull() { - nodeStream.resume(); - }, - cancel(reason) { - nodeStream.pause(); - if (nodeStream.cancel) { - return nodeStream.cancel(reason); - } - } - }); - }; - - class NodeReadable extends NodeReadableStream { - constructor(webStream, options) { - super(options); - this._webStream = webStream; - this._reader = _streams2.default.getReader(webStream); - this._reading = false; - this._doneReadingPromise = Promise.resolve(); - this._cancelling = false; - } - - _read(size) { - if (this._reading || this._cancelling) { - return; - } - this._reading = true; - const doRead = async () => { - try { - while (true) { - var _ref = await this._reader.read(); - - const done = _ref.done, - value = _ref.value; - - if (done) { - this.push(null); - break; - } - if (!this.push(value) || this._cancelling) { - this._reading = false; - break; - } - } - } catch (e) { - this.emit('error', e); - } - }; - this._doneReadingPromise = doRead(); - } - - async cancel(reason) { - this._cancelling = true; - await this._doneReadingPromise; - this._reader.releaseLock(); - return this._webStream.cancel(reason); - } - } - - /** - * Convert a Web ReadableStream to a Node Readable Stream - * @param {ReadableStream} webStream - * @returns {Readable} - */ - exports.webToNode = webToNode = function webToNode(webStream) { - return new NodeReadable(webStream); - }; -} - -exports.nodeToWeb = nodeToWeb; -exports.webToNode = webToNode; - -},{"./streams":75,"./util":76,"stream":"stream"}],74:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.externalBuffer = exports.Reader = undefined; - -var _streams = require('./streams'); - -var _streams2 = _interopRequireDefault(_streams); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const doneReadingSet = new WeakSet(); -const externalBuffer = Symbol('externalBuffer'); - -/** - * A wrapper class over the native ReadableStreamDefaultReader. - * This additionally implements pushing back data on the stream, which - * lets us implement peeking and a host of convenience functions. - * It also lets you read data other than streams, such as a Uint8Array. - * @class - */ -function Reader(input) { - this.stream = input; - if (input[externalBuffer]) { - this[externalBuffer] = input[externalBuffer].slice(); - } - let streamType = _streams2.default.isStream(input); - if (streamType === 'node') { - input = _streams2.default.nodeToWeb(input); - } - if (streamType) { - const reader = input.getReader(); - this._read = reader.read.bind(reader); - this._releaseLock = () => { - reader.closed.catch(function () {}); - reader.releaseLock(); - }; - return; - } - let doneReading = false; - this._read = async () => { - if (doneReading || doneReadingSet.has(input)) { - return { value: undefined, done: true }; - } - doneReading = true; - return { value: input, done: false }; - }; - this._releaseLock = () => { - if (doneReading) { - try { - doneReadingSet.add(input); - } catch (e) {} - } - }; -} - -/** - * Read a chunk of data. - * @returns {Promise} Either { done: false, value: Uint8Array | String } or { done: true, value: undefined } - * @async - */ -Reader.prototype.read = async function () { - if (this[externalBuffer] && this[externalBuffer].length) { - const value = this[externalBuffer].shift(); - return { done: false, value }; - } - return this._read(); -}; - -/** - * Allow others to read the stream. - */ -Reader.prototype.releaseLock = function () { - if (this[externalBuffer]) { - this.stream[externalBuffer] = this[externalBuffer]; - } - this._releaseLock(); -}; - -/** - * Read up to and including the first \n character. - * @returns {Promise} - * @async - */ -Reader.prototype.readLine = async function () { - let buffer = []; - let returnVal; - while (!returnVal) { - var _ref = await this.read(); - - let done = _ref.done, - value = _ref.value; - - value += ''; - if (done) { - if (buffer.length) return _streams2.default.concat(buffer); - return; - } - const lineEndIndex = value.indexOf('\n') + 1; - if (lineEndIndex) { - returnVal = _streams2.default.concat(buffer.concat(value.substr(0, lineEndIndex))); - buffer = []; - } - if (lineEndIndex !== value.length) { - buffer.push(value.substr(lineEndIndex)); - } - } - this.unshift(...buffer); - return returnVal; -}; - -/** - * Read a single byte/character. - * @returns {Promise} - * @async - */ -Reader.prototype.readByte = async function () { - var _ref2 = await this.read(); - - const done = _ref2.done, - value = _ref2.value; - - if (done) return; - const byte = value[0]; - this.unshift(_streams2.default.slice(value, 1)); - return byte; -}; - -/** - * Read a specific amount of bytes/characters, unless the stream ends before that amount. - * @returns {Promise} - * @async - */ -Reader.prototype.readBytes = async function (length) { - const buffer = []; - let bufferLength = 0; - while (true) { - var _ref3 = await this.read(); - - const done = _ref3.done, - value = _ref3.value; - - if (done) { - if (buffer.length) return _streams2.default.concat(buffer); - return; - } - buffer.push(value); - bufferLength += value.length; - if (bufferLength >= length) { - const bufferConcat = _streams2.default.concat(buffer); - this.unshift(_streams2.default.slice(bufferConcat, length)); - return _streams2.default.slice(bufferConcat, 0, length); - } - } -}; - -/** - * Peek (look ahead) a specific amount of bytes/characters, unless the stream ends before that amount. - * @returns {Promise} - * @async - */ -Reader.prototype.peekBytes = async function (length) { - const bytes = await this.readBytes(length); - this.unshift(bytes); - return bytes; -}; - -/** - * Push data to the front of the stream. - * @param {...(Uint8Array|String|Undefined)} values - */ -Reader.prototype.unshift = function (...values) { - if (!this[externalBuffer]) { - this[externalBuffer] = []; - } - this[externalBuffer].unshift(...values.filter(value => value && value.length)); -}; - -/** - * Read the stream to the end and return its contents, concatenated by the join function (defaults to streams.concat). - * @param {Function} join - * @returns {Promise} the return value of join() - * @async - */ -Reader.prototype.readToEnd = async function (join = _streams2.default.concat) { - const result = []; - while (true) { - var _ref4 = await this.read(); - - const done = _ref4.done, - value = _ref4.value; - - if (done) break; - result.push(value); - } - return join(result); -}; - -exports.Reader = Reader; -exports.externalBuffer = externalBuffer; - -},{"./streams":75}],75:[function(require,module,exports){ -(function (process){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _util = require('./util'); - -var _nodeConversions = require('./node-conversions'); - -var _reader = require('./reader'); - -const NodeBuffer = _util.isNode && require('buffer').Buffer; - -/** - * Convert data to Stream - * @param {ReadableStream|Uint8array|String} input data to convert - * @returns {ReadableStream} Converted data - */ -function toStream(input) { - let streamType = (0, _util.isStream)(input); - if (streamType === 'node') { - return (0, _nodeConversions.nodeToWeb)(input); - } else if (streamType) { - return input; - } - return new ReadableStream({ - start(controller) { - controller.enqueue(input); - controller.close(); - } - }); -} - -/** - * Concat a list of Uint8Arrays, Strings or Streams - * The caller should not mix Uint8Arrays with Strings, but may mix Streams with non-Streams. - * @param {Array} Array of Uint8Arrays/Strings/Streams to concatenate - * @returns {Uint8array|String|ReadableStream} Concatenated array - */ -function concat(list) { - if (list.some(_util.isStream)) { - return concatStream(list); - } - if (typeof list[0] === 'string') { - return list.join(''); - } - if (NodeBuffer && NodeBuffer.isBuffer(list[0])) { - return NodeBuffer.concat(list); - } - return (0, _util.concatUint8Array)(list); -} - -/** - * Concat a list of Streams - * @param {Array} list Array of Uint8Arrays/Strings/Streams to concatenate - * @returns {ReadableStream} Concatenated list - */ -function concatStream(list) { - list = list.map(toStream); - const transform = transformWithCancel(async function (reason) { - await Promise.all(transforms.map(stream => cancel(stream, reason))); - }); - let prev = Promise.resolve(); - const transforms = list.map((stream, i) => transformPair(stream, (readable, writable) => { - prev = prev.then(() => pipe(readable, transform.writable, { - preventClose: i !== list.length - 1 - })); - return prev; - })); - return transform.readable; -} - -/** - * Get a Reader - * @param {ReadableStream|Uint8array|String} input - * @returns {Reader} - */ -function getReader(input) { - return new _reader.Reader(input); -} - -/** - * Get a Writer - * @param {WritableStream} input - * @returns {WritableStreamDefaultWriter} - */ -function getWriter(input) { - const writer = input.getWriter(); - const releaseLock = writer.releaseLock; - writer.releaseLock = () => { - writer.closed.catch(function () {}); - releaseLock.call(writer); - }; - return writer; -} - -/** - * Pipe a readable stream to a writable stream. Don't throw on input stream errors, but forward them to the output stream. - * @param {ReadableStream|Uint8array|String} input - * @param {WritableStream} target - * @param {Object} (optional) options - * @returns {Promise} Promise indicating when piping has finished (input stream closed or errored) - * @async - */ -async function pipe(input, target, options) { - input = toStream(input); - try { - if (input[_reader.externalBuffer]) { - const writer = getWriter(target); - for (let i = 0; i < input[_reader.externalBuffer].length; i++) { - await writer.ready; - await writer.write(input[_reader.externalBuffer][i]); - } - writer.releaseLock(); - } - return await input.pipeTo(target, options); - } catch (e) {} -} - -/** - * Pipe a readable stream through a transform stream. - * @param {ReadableStream|Uint8array|String} input - * @param {Object} (optional) options - * @returns {ReadableStream} transformed stream - */ -function transformRaw(input, options) { - const transformStream = new TransformStream(options); - pipe(input, transformStream.writable); - return transformStream.readable; -} - -/** - * Create a cancelable TransformStream. - * @param {Function} cancel - * @returns {TransformStream} - */ -function transformWithCancel(cancel) { - let pulled = false; - let backpressureChangePromiseResolve; - let outputController; - return { - readable: new ReadableStream({ - start(controller) { - outputController = controller; - }, - pull() { - if (backpressureChangePromiseResolve) { - backpressureChangePromiseResolve(); - } else { - pulled = true; - } - }, - cancel - }, { highWaterMark: 0 }), - writable: new WritableStream({ - write: async function write(chunk) { - outputController.enqueue(chunk); - if (!pulled) { - await new Promise(resolve => { - backpressureChangePromiseResolve = resolve; - }); - backpressureChangePromiseResolve = null; - } else { - pulled = false; - } - }, - close: outputController.close.bind(outputController), - abort: outputController.error.bind(outputController) - }) - }; -} - -/** - * Transform a stream using helper functions which are called on each chunk, and on stream close, respectively. - * @param {ReadableStream|Uint8array|String} input - * @param {Function} process - * @param {Function} finish - * @returns {ReadableStream|Uint8array|String} - */ -function transform(input, process = () => undefined, finish = () => undefined) { - if ((0, _util.isStream)(input)) { - return transformRaw(input, { - async transform(value, controller) { - try { - const result = await process(value); - if (result !== undefined) controller.enqueue(result); - } catch (e) { - controller.error(e); - } - }, - async flush(controller) { - try { - const result = await finish(); - if (result !== undefined) controller.enqueue(result); - } catch (e) { - controller.error(e); - } - } - }); - } - const result1 = process(input); - const result2 = finish(); - if (result1 !== undefined && result2 !== undefined) return concat([result1, result2]); - return result1 !== undefined ? result1 : result2; -} - -/** - * Transform a stream using a helper function which is passed a readable and a writable stream. - * This function also maintains the possibility to cancel the input stream, - * and does so on cancelation of the output stream, despite cancelation - * normally being impossible when the input stream is being read from. - * @param {ReadableStream|Uint8array|String} input - * @param {Function} fn - * @returns {ReadableStream} - */ -function transformPair(input, fn) { - let incomingTransformController; - const incoming = new TransformStream({ - start(controller) { - incomingTransformController = controller; - } - }); - - const pipeDonePromise = pipe(input, incoming.writable); - - const outgoing = transformWithCancel(async function () { - incomingTransformController.error(new Error('Readable side was canceled.')); - await pipeDonePromise; - await new Promise(setTimeout); - }); - fn(incoming.readable, outgoing.writable); - return outgoing.readable; -} - -/** - * Parse a stream using a helper function which is passed a Reader. - * The reader additionally has a remainder() method which returns a - * stream pointing to the remainder of input, and is linked to input - * for cancelation. - * @param {ReadableStream|Uint8array|String} input - * @param {Function} fn - * @returns {Any} the return value of fn() - */ -function parse(input, fn) { - let returnValue; - const transformed = transformPair(input, (readable, writable) => { - const reader = getReader(readable); - reader.remainder = () => { - reader.releaseLock(); - pipe(readable, writable); - return transformed; - }; - returnValue = fn(reader); - }); - return returnValue; -} - -/** - * Tee a Stream for reading it twice. The input stream can no longer be read after tee()ing. - * Reading either of the two returned streams will pull from the input stream. - * The input stream will only be canceled if both of the returned streams are canceled. - * @param {ReadableStream|Uint8array|String} input - * @returns {Array} array containing two copies of input - */ -function tee(input) { - if ((0, _util.isStream)(input)) { - const teed = toStream(input).tee(); - teed[0][_reader.externalBuffer] = teed[1][_reader.externalBuffer] = input[_reader.externalBuffer]; - return teed; - } - return [slice(input), slice(input)]; -} - -/** - * Clone a Stream for reading it twice. The input stream can still be read after clone()ing. - * Reading from the clone will pull from the input stream. - * The input stream will only be canceled if both the clone and the input stream are canceled. - * @param {ReadableStream|Uint8array|String} input - * @returns {ReadableStream|Uint8array|String} cloned input - */ -function clone(input) { - if ((0, _util.isStream)(input)) { - const teed = tee(input); - overwrite(input, teed[0]); - return teed[1]; - } - return slice(input); -} - -/** - * Clone a Stream for reading it twice. Data will arrive at the same rate as the input stream is being read. - * Reading from the clone will NOT pull from the input stream. Data only arrives when reading the input stream. - * The input stream will NOT be canceled if the clone is canceled, only if the input stream are canceled. - * If the input stream is canceled, the clone will be errored. - * @param {ReadableStream|Uint8array|String} input - * @returns {ReadableStream|Uint8array|String} cloned input - */ -function passiveClone(input) { - if ((0, _util.isStream)(input)) { - return new ReadableStream({ - start(controller) { - const transformed = transformPair(input, async (readable, writable) => { - const reader = getReader(readable); - const writer = getWriter(writable); - try { - while (true) { - await writer.ready; - - var _ref = await reader.read(); - - const done = _ref.done, - value = _ref.value; - - if (done) { - try { - controller.close(); - } catch (e) {} - await writer.close(); - return; - } - try { - controller.enqueue(value); - } catch (e) {} - await writer.write(value); - } - } catch (e) { - controller.error(e); - await writer.abort(e); - } - }); - overwrite(input, transformed); - } - }); - } - return slice(input); -} - -/** - * Modify a stream object to point to a different stream object. - * This is used internally by clone() and passiveClone() to provide an abstraction over tee(). - * @param {ReadableStream} input - * @param {ReadableStream} clone - */ -function overwrite(input, clone) { - // Overwrite input.getReader, input.locked, etc to point to clone - Object.entries(Object.getOwnPropertyDescriptors(ReadableStream.prototype)).forEach(([name, descriptor]) => { - if (name === 'constructor') { - return; - } - if (descriptor.value) { - descriptor.value = descriptor.value.bind(clone); - } else { - descriptor.get = descriptor.get.bind(clone); - } - Object.defineProperty(input, name, descriptor); - }); -} - -/** - * Return a stream pointing to a part of the input stream. - * @param {ReadableStream|Uint8array|String} input - * @returns {ReadableStream|Uint8array|String} clone - */ -function slice(input, begin = 0, end = Infinity) { - if ((0, _util.isStream)(input)) { - if (begin >= 0 && end >= 0) { - let bytesRead = 0; - return transformRaw(input, { - transform(value, controller) { - if (bytesRead < end) { - if (bytesRead + value.length >= begin) { - controller.enqueue(slice(value, Math.max(begin - bytesRead, 0), end - bytesRead)); - } - bytesRead += value.length; - } else { - controller.terminate(); - } - } - }); - } - if (begin < 0 && (end < 0 || end === Infinity)) { - let lastBytes = []; - return transform(input, value => { - if (value.length >= -begin) lastBytes = [value];else lastBytes.push(value); - }, () => slice(concat(lastBytes), begin, end)); - } - if (begin === 0 && end < 0) { - let lastBytes; - return transform(input, value => { - const returnValue = lastBytes ? concat([lastBytes, value]) : value; - if (returnValue.length >= -end) { - lastBytes = slice(returnValue, end); - return slice(returnValue, begin, end); - } else { - lastBytes = returnValue; - } - }); - } - console.warn(`stream.slice(input, ${begin}, ${end}) not implemented efficiently.`); - return fromAsync(async () => slice((await readToEnd(input)), begin, end)); - } - if (input[_reader.externalBuffer]) { - input = concat(input[_reader.externalBuffer].concat([input])); - } - if ((0, _util.isUint8Array)(input) && !(NodeBuffer && NodeBuffer.isBuffer(input))) { - if (end === Infinity) end = input.length; - return input.subarray(begin, end); - } - return input.slice(begin, end); -} - -/** - * Read a stream to the end and return its contents, concatenated by the concat function (defaults to concat). - * @param {ReadableStream|Uint8array|String} input - * @param {Function} concat - * @returns {Promise} the return value of concat() - * @async - */ -async function readToEnd(input, concat) { - if ((0, _util.isStream)(input)) { - return getReader(input).readToEnd(concat); - } - return input; -} - -/** - * Cancel a stream. - * @param {ReadableStream|Uint8array|String} input - * @param {Any} reason - * @returns {Promise} indicates when the stream has been canceled - * @async - */ -async function cancel(input, reason) { - if ((0, _util.isStream)(input) && input.cancel) { - return input.cancel(reason); - } -} - -/** - * Convert an async function to a Stream. When the function returns, its return value is enqueued to the stream. - * @param {Function} fn - * @returns {ReadableStream} - */ -function fromAsync(fn) { - return new ReadableStream({ - pull: async controller => { - try { - controller.enqueue((await fn())); - controller.close(); - } catch (e) { - controller.error(e); - } - } - }); -} - -exports.default = { isStream: _util.isStream, isUint8Array: _util.isUint8Array, toStream, concatUint8Array: _util.concatUint8Array, concatStream, concat, getReader, getWriter, pipe, transformRaw, transform, transformPair, parse, clone, passiveClone, slice, readToEnd, cancel, fromAsync, nodeToWeb: _nodeConversions.nodeToWeb, webToNode: _nodeConversions.webToNode }; - -}).call(this,require('_process')) -},{"./node-conversions":73,"./reader":74,"./util":76,"_process":66,"buffer":"buffer"}],76:[function(require,module,exports){ -(function (global){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -const isNode = typeof global.process === 'object' && typeof global.process.versions === 'object'; - -const NodeReadableStream = isNode && require('stream').Readable; - -/** - * Check whether data is a Stream, and if so of which type - * @param {Any} input data to check - * @returns {'web'|'node'|false} - */ -function isStream(input) { - if (ReadableStream.prototype.isPrototypeOf(input)) { - return 'web'; - } - if (NodeReadableStream && NodeReadableStream.prototype.isPrototypeOf(input)) { - return 'node'; - } - return false; -} - -/** - * Check whether data is a Uint8Array - * @param {Any} input data to check - * @returns {Boolean} - */ -function isUint8Array(input) { - return Uint8Array.prototype.isPrototypeOf(input); -} - -/** - * Concat Uint8Arrays - * @param {Array} Array of Uint8Arrays to concatenate - * @returns {Uint8array} Concatenated array - */ -function concatUint8Array(arrays) { - if (arrays.length === 1) return arrays[0]; - - let totalLength = 0; - for (let i = 0; i < arrays.length; i++) { - if (!isUint8Array(arrays[i])) { - throw new Error('concatUint8Array: Data must be in the form of a Uint8Array'); - } - - totalLength += arrays[i].length; - } - - const result = new Uint8Array(totalLength); - let pos = 0; - arrays.forEach(function (element) { - result.set(element, pos); - pos += element.length; - }); - - return result; -} - -exports.isNode = isNode; -exports.isStream = isStream; -exports.isUint8Array = isUint8Array; -exports.concatUint8Array = concatUint8Array; - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"stream":"stream"}],77:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.CleartextMessage = CleartextMessage; -exports.readArmored = readArmored; -exports.fromText = fromText; - -var _armor = require('./encoding/armor'); - -var _armor2 = _interopRequireDefault(_armor); - -var _enums = require('./enums'); - -var _enums2 = _interopRequireDefault(_enums); - -var _util = require('./util'); - -var _util2 = _interopRequireDefault(_util); - -var _packet = require('./packet'); - -var _packet2 = _interopRequireDefault(_packet); - -var _signature = require('./signature'); - -var _message = require('./message'); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * @class - * @classdesc Class that represents an OpenPGP cleartext signed message. - * See {@link https://tools.ietf.org/html/rfc4880#section-7} - * @param {String} text The cleartext of the signed message - * @param {module:signature.Signature} signature The detached signature or an empty signature for unsigned messages - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @requires encoding/armor - * @requires enums - * @requires util - * @requires packet - * @requires signature - * @module cleartext - */ - -function CleartextMessage(text, signature) { - if (!(this instanceof CleartextMessage)) { - return new CleartextMessage(text, signature); - } - // normalize EOL to canonical form - this.text = _util2.default.canonicalizeEOL(_util2.default.removeTrailingSpaces(text)); - if (signature && !(signature instanceof _signature.Signature)) { - throw new Error('Invalid signature input'); - } - this.signature = signature || new _signature.Signature(new _packet2.default.List()); -} - -/** - * Returns the key IDs of the keys that signed the cleartext message - * @returns {Array} array of keyid objects - */ -CleartextMessage.prototype.getSigningKeyIds = function () { - const keyIds = []; - const signatureList = this.signature.packets; - signatureList.forEach(function (packet) { - keyIds.push(packet.issuerKeyId); - }); - return keyIds; -}; - -/** - * Sign the cleartext message - * @param {Array} privateKeys private keys with decrypted secret key data for signing - * @param {Signature} signature (optional) any existing detached signature - * @param {Date} date (optional) The creation time of the signature that should be created - * @param {Array} userIds (optional) user IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] - * @returns {Promise} new cleartext message with signed content - * @async - */ -CleartextMessage.prototype.sign = async function (privateKeys, signature = null, date = new Date(), userIds = []) { - return new CleartextMessage(this.text, (await this.signDetached(privateKeys, signature, date, userIds))); -}; - -/** - * Sign the cleartext message - * @param {Array} privateKeys private keys with decrypted secret key data for signing - * @param {Signature} signature (optional) any existing detached signature - * @param {Date} date (optional) The creation time of the signature that should be created - * @param {Array} userIds (optional) user IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] - * @returns {Promise} new detached signature of message content - * @async - */ -CleartextMessage.prototype.signDetached = async function (privateKeys, signature = null, date = new Date(), userIds = []) { - const literalDataPacket = new _packet2.default.Literal(); - literalDataPacket.setText(this.text); - - return new _signature.Signature((await (0, _message.createSignaturePackets)(literalDataPacket, privateKeys, signature, date, userIds, true))); -}; - -/** - * Verify signatures of cleartext signed message - * @param {Array} keys array of keys to verify signatures - * @param {Date} date (optional) Verify the signature against the given date, i.e. check signature creation time < date < expiration time - * @returns {Promise>} list of signer's keyid and validity of signature - * @async - */ -CleartextMessage.prototype.verify = function (keys, date = new Date()) { - return this.verifyDetached(this.signature, keys, date); -}; - -/** - * Verify signatures of cleartext signed message - * @param {Array} keys array of keys to verify signatures - * @param {Date} date (optional) Verify the signature against the given date, i.e. check signature creation time < date < expiration time - * @returns {Promise>} list of signer's keyid and validity of signature - * @async - */ -CleartextMessage.prototype.verifyDetached = function (signature, keys, date = new Date()) { - const signatureList = signature.packets; - const literalDataPacket = new _packet2.default.Literal(); - // we assume that cleartext signature is generated based on UTF8 cleartext - literalDataPacket.setText(this.text); - return (0, _message.createVerificationObjects)(signatureList, [literalDataPacket], keys, date, true); -}; - -/** - * Get cleartext - * @returns {String} cleartext of message - */ -CleartextMessage.prototype.getText = function () { - // normalize end of line to \n - return _util2.default.nativeEOL(this.text); -}; - -/** - * Returns ASCII armored text of cleartext signed message - * @returns {String | ReadableStream} ASCII armor - */ -CleartextMessage.prototype.armor = function () { - let hashes = this.signature.packets.map(function (packet) { - return _enums2.default.read(_enums2.default.hash, packet.hashAlgorithm).toUpperCase(); - }); - hashes = hashes.filter(function (item, i, ar) { - return ar.indexOf(item) === i; - }); - const body = { - hash: hashes.join(), - text: this.text, - data: this.signature.packets.write() - }; - return _armor2.default.encode(_enums2.default.armor.signed, body); -}; - -/** - * reads an OpenPGP cleartext signed message and returns a CleartextMessage object - * @param {String | ReadableStream} armoredText text to be parsed - * @returns {module:cleartext.CleartextMessage} new cleartext message object - * @async - * @static - */ -async function readArmored(armoredText) { - const input = await _armor2.default.decode(armoredText); - if (input.type !== _enums2.default.armor.signed) { - throw new Error('No cleartext signed message.'); - } - const packetlist = new _packet2.default.List(); - await packetlist.read(input.data); - verifyHeaders(input.headers, packetlist); - const signature = new _signature.Signature(packetlist); - return new CleartextMessage(input.text, signature); -} - -/** - * Compare hash algorithm specified in the armor header with signatures - * @param {Array} headers Armor headers - * @param {module:packet.List} packetlist The packetlist with signature packets - * @private - */ -function verifyHeaders(headers, packetlist) { - const checkHashAlgos = function checkHashAlgos(hashAlgos) { - const check = packet => algo => packet.hashAlgorithm === algo; - - for (let i = 0; i < packetlist.length; i++) { - if (packetlist[i].tag === _enums2.default.packet.signature && !hashAlgos.some(check(packetlist[i]))) { - return false; - } - } - return true; - }; - - let oneHeader = null; - let hashAlgos = []; - headers.forEach(function (header) { - oneHeader = header.match(/Hash: (.+)/); // get header value - if (oneHeader) { - oneHeader = oneHeader[1].replace(/\s/g, ''); // remove whitespace - oneHeader = oneHeader.split(','); - oneHeader = oneHeader.map(function (hash) { - hash = hash.toLowerCase(); - try { - return _enums2.default.write(_enums2.default.hash, hash); - } catch (e) { - throw new Error('Unknown hash algorithm in armor header: ' + hash); - } - }); - hashAlgos = hashAlgos.concat(oneHeader); - } else { - throw new Error('Only "Hash" header allowed in cleartext signed message'); - } - }); - - if (!hashAlgos.length && !checkHashAlgos([_enums2.default.hash.md5])) { - throw new Error('If no "Hash" header in cleartext signed message, then only MD5 signatures allowed'); - } else if (hashAlgos.length && !checkHashAlgos(hashAlgos)) { - throw new Error('Hash algorithm mismatch in armor header and signature'); - } -} - -/** - * Creates a new CleartextMessage object from text - * @param {String} text - * @static - */ -function fromText(text) { - return new CleartextMessage(text); -} - -},{"./encoding/armor":111,"./enums":113,"./message":120,"./packet":125,"./signature":145,"./util":152}],78:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _enums = require("../enums"); - -var _enums2 = _interopRequireDefault(_enums); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -exports.default = { - /** - * @memberof module:config - * @property {Integer} prefer_hash_algorithm Default hash algorithm {@link module:enums.hash} - */ - prefer_hash_algorithm: _enums2.default.hash.sha256, - /** - * @memberof module:config - * @property {Integer} encryption_cipher Default encryption cipher {@link module:enums.symmetric} - */ - encryption_cipher: _enums2.default.symmetric.aes256, - /** - * @memberof module:config - * @property {Integer} compression Default compression algorithm {@link module:enums.compression} - */ - compression: _enums2.default.compression.uncompressed, - /** - * @memberof module:config - * @property {Integer} deflate_level Default zip/zlib compression level, between 1 and 9 - */ - deflate_level: 6, - - /** - * Use Authenticated Encryption with Additional Data (AEAD) protection for symmetric encryption. - * **NOT INTEROPERABLE WITH OTHER OPENPGP IMPLEMENTATIONS** - * **FUTURE OPENPGP.JS VERSIONS MAY BREAK COMPATIBILITY WHEN USING THIS OPTION** - * @see {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-07|RFC4880bis-07} - * @memberof module:config - * @property {Boolean} aead_protect - */ - aead_protect: false, - /** - * Default Authenticated Encryption with Additional Data (AEAD) encryption mode - * Only has an effect when aead_protect is set to true. - * @memberof module:config - * @property {Integer} aead_mode Default AEAD mode {@link module:enums.aead} - */ - aead_mode: _enums2.default.aead.eax, - /** - * Chunk Size Byte for Authenticated Encryption with Additional Data (AEAD) mode - * Only has an effect when aead_protect is set to true. - * Must be an integer value from 0 to 56. - * @memberof module:config - * @property {Integer} aead_chunk_size_byte - */ - aead_chunk_size_byte: 12, - /** - * Use V5 keys. - * **NOT INTEROPERABLE WITH OTHER OPENPGP IMPLEMENTATIONS** - * **FUTURE OPENPGP.JS VERSIONS MAY BREAK COMPATIBILITY WHEN USING THIS OPTION** - * @memberof module:config - * @property {Boolean} v5_keys - */ - v5_keys: false, - /** - * {@link https://tools.ietf.org/html/rfc4880#section-3.7.1.3|RFC4880 3.7.1.3}: - * Iteration Count Byte for S2K (String to Key) - * @memberof module:config - * @property {Integer} s2k_iteration_count_byte - */ - s2k_iteration_count_byte: 224, - /** Use integrity protection for symmetric encryption - * @memberof module:config - * @property {Boolean} integrity_protect - */ - integrity_protect: true, - /** - * @memberof module:config - * @property {Boolean} ignore_mdc_error Fail on decrypt if message is not integrity protected - */ - ignore_mdc_error: false, - /** - * @memberof module:config - * @property {Boolean} allow_unauthenticated_stream Stream unauthenticated data before integrity has been checked - */ - allow_unauthenticated_stream: false, - /** - * @memberof module:config - * @property {Boolean} checksum_required Do not throw error when armor is missing a checksum - */ - checksum_required: false, - /** - * @memberof module:config - * @property {Boolean} rsa_blinding - */ - rsa_blinding: true, - /** - * Work-around for rare GPG decryption bug when encrypting with multiple passwords. - * **Slower and slightly less secure** - * @memberof module:config - * @property {Boolean} password_collision_check - */ - password_collision_check: false, - /** - * @memberof module:config - * @property {Boolean} revocations_expire If true, expired revocation signatures are ignored - */ - revocations_expire: false, - - /** - * @memberof module:config - * @property {Boolean} use_native Use native Node.js crypto/zlib and WebCrypto APIs when available - */ - use_native: true, - /** - * @memberof module:config - * @property {Integer} min_bytes_for_web_crypto The minimum amount of bytes for which to use native WebCrypto APIs when available - */ - min_bytes_for_web_crypto: 1000, - /** - * @memberof module:config - * @property {Boolean} Use transferable objects between the Web Worker and main thread - */ - zero_copy: false, - /** - * @memberof module:config - * @property {Boolean} debug If enabled, debug messages will be printed - */ - debug: false, - /** - * @memberof module:config - * @property {Boolean} tolerant Ignore unsupported/unrecognizable packets instead of throwing an error - */ - tolerant: true, - - /** - * @memberof module:config - * @property {Boolean} show_version Whether to include {@link module:config/config.versionstring} in armored messages - */ - show_version: true, - /** - * @memberof module:config - * @property {Boolean} show_comment Whether to include {@link module:config/config.commentstring} in armored messages - */ - show_comment: true, - /** - * @memberof module:config - * @property {String} versionstring A version string to be included in armored messages - */ - versionstring: "OpenPGP.js v4.6.0", - /** - * @memberof module:config - * @property {String} commentstring A comment string to be included in armored messages - */ - commentstring: "https://openpgpjs.org", - - /** - * @memberof module:config - * @property {String} keyserver - */ - keyserver: "https://keyserver.ubuntu.com", - /** - * @memberof module:config - * @property {String} node_store - */ - node_store: "./openpgp.store", - /** - * Max userid string length (used for parsing) - * @memberof module:config - * @property {Integer} max_userid_length - */ - max_userid_length: 1024 * 5, - /** - * Contains notatations that are considered "known". Known notations do not trigger - * validation error when the notation is marked as critical. - * @memberof module:config - * @property {Array} known_notations - */ - known_notations: ["preferred-email-encoding@pgp.com", "pka-address@gnupg.org"] -}; // GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * Global configuration values. - * @requires enums - */ - -},{"../enums":113}],79:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _config = require('./config.js'); - -Object.defineProperty(exports, 'default', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_config).default; - } -}); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -},{"./config.js":78}],80:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _cipher = require('./cipher'); - -var _cipher2 = _interopRequireDefault(_cipher); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2015-2016 Decentral -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @fileoverview Implementation of RFC 3394 AES Key Wrap & Key Unwrap funcions - * @see module:crypto/public_key/elliptic/ecdh - * @requires crypto/cipher - * @requires util - * @module crypto/aes_kw - */ - -function wrap(key, data) { - const aes = new _cipher2.default["aes" + key.length * 8](key); - const IV = new Uint32Array([0xA6A6A6A6, 0xA6A6A6A6]); - const P = unpack(data); - let A = IV; - const R = P; - const n = P.length / 2; - const t = new Uint32Array([0, 0]); - let B = new Uint32Array(4); - for (let j = 0; j <= 5; ++j) { - for (let i = 0; i < n; ++i) { - t[1] = n * j + (1 + i); - // B = A - B[0] = A[0]; - B[1] = A[1]; - // B = A || R[i] - B[2] = R[2 * i]; - B[3] = R[2 * i + 1]; - // B = AES(K, B) - B = unpack(aes.encrypt(pack(B))); - // A = MSB(64, B) ^ t - A = B.subarray(0, 2); - A[0] ^= t[0]; - A[1] ^= t[1]; - // R[i] = LSB(64, B) - R[2 * i] = B[2]; - R[2 * i + 1] = B[3]; - } - } - return pack(A, R); -} - -function unwrap(key, data) { - const aes = new _cipher2.default["aes" + key.length * 8](key); - const IV = new Uint32Array([0xA6A6A6A6, 0xA6A6A6A6]); - const C = unpack(data); - let A = C.subarray(0, 2); - const R = C.subarray(2); - const n = C.length / 2 - 1; - const t = new Uint32Array([0, 0]); - let B = new Uint32Array(4); - for (let j = 5; j >= 0; --j) { - for (let i = n - 1; i >= 0; --i) { - t[1] = n * j + (i + 1); - // B = A ^ t - B[0] = A[0] ^ t[0]; - B[1] = A[1] ^ t[1]; - // B = (A ^ t) || R[i] - B[2] = R[2 * i]; - B[3] = R[2 * i + 1]; - // B = AES-1(B) - B = unpack(aes.decrypt(pack(B))); - // A = MSB(64, B) - A = B.subarray(0, 2); - // R[i] = LSB(64, B) - R[2 * i] = B[2]; - R[2 * i + 1] = B[3]; - } - } - if (A[0] === IV[0] && A[1] === IV[1]) { - return pack(R); - } - throw new Error("Key Data Integrity failed"); -} - -function createArrayBuffer(data) { - if (_util2.default.isString(data)) { - const length = data.length; - - const buffer = new ArrayBuffer(length); - const view = new Uint8Array(buffer); - for (let j = 0; j < length; ++j) { - view[j] = data.charCodeAt(j); - } - return buffer; - } - return new Uint8Array(data).buffer; -} - -function unpack(data) { - const length = data.length; - - const buffer = createArrayBuffer(data); - const view = new DataView(buffer); - const arr = new Uint32Array(length / 4); - for (let i = 0; i < length / 4; ++i) { - arr[i] = view.getUint32(4 * i); - } - return arr; -} - -function pack() { - let length = 0; - for (let k = 0; k < arguments.length; ++k) { - length += 4 * arguments[k].length; - } - const buffer = new ArrayBuffer(length); - const view = new DataView(buffer); - let offset = 0; - for (let i = 0; i < arguments.length; ++i) { - for (let j = 0; j < arguments[i].length; ++j) { - view.setUint32(offset + 4 * j, arguments[i][j]); - } - offset += 4 * arguments[i].length; - } - return new Uint8Array(buffer); -} - -exports.default = { - /** - * AES key wrap - * @function - * @param {String} key - * @param {String} data - * @returns {Uint8Array} - */ - wrap, - /** - * AES key unwrap - * @function - * @param {String} key - * @param {String} data - * @returns {Uint8Array} - * @throws {Error} - */ - unwrap -}; - -},{"../util":152,"./cipher":86}],81:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _cfb = require('asmcrypto.js/dist_es5/aes/cfb'); - -var _webStreamTools = require('web-stream-tools'); - -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); - -var _cipher = require('./cipher'); - -var _cipher2 = _interopRequireDefault(_cipher); - -var _config = require('../config'); - -var _config2 = _interopRequireDefault(_config); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const webCrypto = _util2.default.getWebCrypto(); // Modified by ProtonTech AG - -// Modified by Recurity Labs GmbH - -// modified version of https://www.hanewin.net/encrypt/PGdecode.js: - -/* OpenPGP encryption using RSA/AES - * Copyright 2005-2006 Herbert Hanewinkel, www.haneWIN.de - * version 2.0, check www.haneWIN.de for the latest version - - * This software is provided as-is, without express or implied warranty. - * Permission to use, copy, modify, distribute or sell this software, with or - * without fee, for any purpose and by any individual or organization, is hereby - * granted, provided that the above copyright notice and this paragraph appear - * in all copies. Distribution as a part of an application or binary must - * include the above copyright notice in the documentation and/or other - * materials provided with the application or distribution. - */ - -/** - * @requires web-stream-tools - * @requires crypto/cipher - * @requires util - * @module crypto/cfb - */ - -const nodeCrypto = _util2.default.getNodeCrypto(); -const Buffer = _util2.default.getNodeBuffer(); - -exports.default = { - encrypt: function encrypt(algo, key, plaintext, iv) { - if (algo.substr(0, 3) === 'aes') { - return aesEncrypt(algo, key, plaintext, iv); - } - - const cipherfn = new _cipher2.default[algo](key); - const block_size = cipherfn.blockSize; - - let blocki = new Uint8Array(block_size); - const blockc = iv; - let pos = 0; - const ciphertext = new Uint8Array(plaintext.length); - let i; - let j = 0; - - while (plaintext.length > block_size * pos) { - const encblock = cipherfn.encrypt(blockc); - blocki = plaintext.subarray(pos * block_size, pos * block_size + block_size); - for (i = 0; i < blocki.length; i++) { - blockc[i] = blocki[i] ^ encblock[i]; - ciphertext[j++] = blockc[i]; - } - pos++; - } - return ciphertext; - }, - - decrypt: async function decrypt(algo, key, ciphertext, iv) { - if (algo.substr(0, 3) === 'aes') { - return aesDecrypt(algo, key, ciphertext, iv); - } - - ciphertext = await _webStreamTools2.default.readToEnd(ciphertext); - - const cipherfn = new _cipher2.default[algo](key); - const block_size = cipherfn.blockSize; - - let blockp = iv; - let pos = 0; - const plaintext = new Uint8Array(ciphertext.length); - const offset = 0; - let i; - let j = 0; - - while (ciphertext.length > block_size * pos) { - const decblock = cipherfn.encrypt(blockp); - blockp = ciphertext.subarray(pos * block_size + offset, pos * block_size + block_size + offset); - for (i = 0; i < blockp.length; i++) { - plaintext[j++] = blockp[i] ^ decblock[i]; - } - pos++; - } - - return plaintext; - } -}; - - -function aesEncrypt(algo, key, pt, iv) { - if (_util2.default.getWebCrypto() && key.length !== 24 && // Chrome doesn't support 192 bit keys, see https://www.chromium.org/blink/webcrypto#TOC-AES-support - !_util2.default.isStream(pt) && pt.length >= 3000 * _config2.default.min_bytes_for_web_crypto // Default to a 3MB minimum. Chrome is pretty slow for small messages, see: https://bugs.chromium.org/p/chromium/issues/detail?id=701188#c2 - ) { - // Web Crypto - return webEncrypt(algo, key, pt, iv); - } - if (nodeCrypto) { - // Node crypto library. - return nodeEncrypt(algo, key, pt, iv); - } // asm.js fallback - const cfb = new _cfb.AES_CFB(key, iv); - return _webStreamTools2.default.transform(pt, value => cfb.AES_Encrypt_process(value), () => cfb.AES_Encrypt_finish()); -} - -function aesDecrypt(algo, key, ct, iv) { - if (nodeCrypto) { - // Node crypto library. - return nodeDecrypt(algo, key, ct, iv); - } - if (_util2.default.isStream(ct)) { - const cfb = new _cfb.AES_CFB(key, iv); - return _webStreamTools2.default.transform(ct, value => cfb.AES_Decrypt_process(value), () => cfb.AES_Decrypt_finish()); - } - return _cfb.AES_CFB.decrypt(ct, key, iv); -} - -function xorMut(a, b) { - for (let i = 0; i < a.length; i++) { - a[i] = a[i] ^ b[i]; - } -} - -async function webEncrypt(algo, key, pt, iv) { - const ALGO = 'AES-CBC'; - const _key = await webCrypto.importKey('raw', key, { name: ALGO }, false, ['encrypt']); - const blockSize = _cipher2.default[algo].blockSize; - - const cbc_pt = _util2.default.concatUint8Array([new Uint8Array(blockSize), pt]); - const ct = new Uint8Array((await webCrypto.encrypt({ name: ALGO, iv }, _key, cbc_pt))).subarray(0, pt.length); - xorMut(ct, pt); - return ct; -} - -function nodeEncrypt(algo, key, pt, iv) { - key = new Buffer(key); - iv = new Buffer(iv); - const cipherObj = new nodeCrypto.createCipheriv('aes-' + algo.substr(3, 3) + '-cfb', key, iv); - return _webStreamTools2.default.transform(pt, value => new Uint8Array(cipherObj.update(new Buffer(value)))); -} - -function nodeDecrypt(algo, key, ct, iv) { - key = new Buffer(key); - iv = new Buffer(iv); - const decipherObj = new nodeCrypto.createDecipheriv('aes-' + algo.substr(3, 3) + '-cfb', key, iv); - return _webStreamTools2.default.transform(ct, value => new Uint8Array(decipherObj.update(new Buffer(value)))); -} - -},{"../config":79,"../util":152,"./cipher":86,"asmcrypto.js/dist_es5/aes/cfb":5,"web-stream-tools":75}],82:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _ecb = require('asmcrypto.js/dist_es5/aes/ecb'); - -// TODO use webCrypto or nodeCrypto when possible. -function aes(length) { - const C = function C(key) { - const aes_ecb = new _ecb.AES_ECB(key); - - this.encrypt = function (block) { - return aes_ecb.encrypt(block); - }; - - this.decrypt = function (block) { - return aes_ecb.decrypt(block); - }; - }; - - C.blockSize = C.prototype.blockSize = 16; - C.keySize = C.prototype.keySize = length / 8; - - return C; -} /** - * @requires asmcrypto.js - */ - -exports.default = aes; - -},{"asmcrypto.js/dist_es5/aes/ecb":7}],83:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -/* Modified by Recurity Labs GmbH - * - * Originally written by nklein software (nklein.com) - */ - -/* - * Javascript implementation based on Bruce Schneier's reference implementation. - * - * - * The constructor doesn't do much of anything. It's just here - * so we can start defining properties and methods and such. - */ -function Blowfish() {} - -/* - * Declare the block size so that protocols know what size - * Initialization Vector (IV) they will need. - */ -Blowfish.prototype.BLOCKSIZE = 8; - -/* - * These are the default SBOXES. - */ -Blowfish.prototype.SBOXES = [[0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a], [0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7], [0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0], [0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6]]; - -//* -//* This is the default PARRAY -//* -Blowfish.prototype.PARRAY = [0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b]; - -//* -//* This is the number of rounds the cipher will go -//* -Blowfish.prototype.NN = 16; - -//* -//* This function is needed to get rid of problems -//* with the high-bit getting set. If we don't do -//* this, then sometimes ( aa & 0x00FFFFFFFF ) is not -//* equal to ( bb & 0x00FFFFFFFF ) even when they -//* agree bit-for-bit for the first 32 bits. -//* -Blowfish.prototype._clean = function (xx) { - if (xx < 0) { - const yy = xx & 0x7FFFFFFF; - xx = yy + 0x80000000; - } - return xx; -}; - -//* -//* This is the mixing function that uses the sboxes -//* -Blowfish.prototype._F = function (xx) { - let yy; - - const dd = xx & 0x00FF; - xx >>>= 8; - const cc = xx & 0x00FF; - xx >>>= 8; - const bb = xx & 0x00FF; - xx >>>= 8; - const aa = xx & 0x00FF; - - yy = this.sboxes[0][aa] + this.sboxes[1][bb]; - yy ^= this.sboxes[2][cc]; - yy += this.sboxes[3][dd]; - - return yy; -}; - -//* -//* This method takes an array with two values, left and right -//* and does NN rounds of Blowfish on them. -//* -Blowfish.prototype._encrypt_block = function (vals) { - let dataL = vals[0]; - let dataR = vals[1]; - - let ii; - - for (ii = 0; ii < this.NN; ++ii) { - dataL ^= this.parray[ii]; - dataR = this._F(dataL) ^ dataR; - - const tmp = dataL; - dataL = dataR; - dataR = tmp; - } - - dataL ^= this.parray[this.NN + 0]; - dataR ^= this.parray[this.NN + 1]; - - vals[0] = this._clean(dataR); - vals[1] = this._clean(dataL); -}; - -//* -//* This method takes a vector of numbers and turns them -//* into long words so that they can be processed by the -//* real algorithm. -//* -//* Maybe I should make the real algorithm above take a vector -//* instead. That will involve more looping, but it won't require -//* the F() method to deconstruct the vector. -//* -Blowfish.prototype.encrypt_block = function (vector) { - let ii; - const vals = [0, 0]; - const off = this.BLOCKSIZE / 2; - for (ii = 0; ii < this.BLOCKSIZE / 2; ++ii) { - vals[0] = vals[0] << 8 | vector[ii + 0] & 0x00FF; - vals[1] = vals[1] << 8 | vector[ii + off] & 0x00FF; - } - - this._encrypt_block(vals); - - const ret = []; - for (ii = 0; ii < this.BLOCKSIZE / 2; ++ii) { - ret[ii + 0] = vals[0] >>> 24 - 8 * ii & 0x00FF; - ret[ii + off] = vals[1] >>> 24 - 8 * ii & 0x00FF; - // vals[ 0 ] = ( vals[ 0 ] >>> 8 ); - // vals[ 1 ] = ( vals[ 1 ] >>> 8 ); - } - - return ret; -}; - -//* -//* This method takes an array with two values, left and right -//* and undoes NN rounds of Blowfish on them. -//* -Blowfish.prototype._decrypt_block = function (vals) { - let dataL = vals[0]; - let dataR = vals[1]; - - let ii; - - for (ii = this.NN + 1; ii > 1; --ii) { - dataL ^= this.parray[ii]; - dataR = this._F(dataL) ^ dataR; - - const tmp = dataL; - dataL = dataR; - dataR = tmp; - } - - dataL ^= this.parray[1]; - dataR ^= this.parray[0]; - - vals[0] = this._clean(dataR); - vals[1] = this._clean(dataL); -}; - -//* -//* This method takes a key array and initializes the -//* sboxes and parray for this encryption. -//* -Blowfish.prototype.init = function (key) { - let ii; - let jj = 0; - - this.parray = []; - for (ii = 0; ii < this.NN + 2; ++ii) { - let data = 0x00000000; - for (let kk = 0; kk < 4; ++kk) { - data = data << 8 | key[jj] & 0x00FF; - if (++jj >= key.length) { - jj = 0; - } - } - this.parray[ii] = this.PARRAY[ii] ^ data; - } - - this.sboxes = []; - for (ii = 0; ii < 4; ++ii) { - this.sboxes[ii] = []; - for (jj = 0; jj < 256; ++jj) { - this.sboxes[ii][jj] = this.SBOXES[ii][jj]; - } - } - - const vals = [0x00000000, 0x00000000]; - - for (ii = 0; ii < this.NN + 2; ii += 2) { - this._encrypt_block(vals); - this.parray[ii + 0] = vals[0]; - this.parray[ii + 1] = vals[1]; - } - - for (ii = 0; ii < 4; ++ii) { - for (jj = 0; jj < 256; jj += 2) { - this._encrypt_block(vals); - this.sboxes[ii][jj + 0] = vals[0]; - this.sboxes[ii][jj + 1] = vals[1]; - } - } -}; - -// added by Recurity Labs -function BF(key) { - this.bf = new Blowfish(); - this.bf.init(key); - - this.encrypt = function (block) { - return this.bf.encrypt_block(block); - }; -} - -BF.keySize = BF.prototype.keySize = 16; -BF.blockSize = BF.prototype.blockSize = 16; - -exports.default = BF; - -},{}],84:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Copyright 2010 pjacobs@xeekr.com . All rights reserved. - -// Modified by Recurity Labs GmbH - -// fixed/modified by Herbert Hanewinkel, www.haneWIN.de -// check www.haneWIN.de for the latest version - -// cast5.js is a Javascript implementation of CAST-128, as defined in RFC 2144. -// CAST-128 is a common OpenPGP cipher. - - -// CAST5 constructor - -function OpenpgpSymencCast5() { - this.BlockSize = 8; - this.KeySize = 16; - - this.setKey = function (key) { - this.masking = new Array(16); - this.rotate = new Array(16); - - this.reset(); - - if (key.length === this.KeySize) { - this.keySchedule(key); - } else { - throw new Error('CAST-128: keys must be 16 bytes'); - } - return true; - }; - - this.reset = function () { - for (let i = 0; i < 16; i++) { - this.masking[i] = 0; - this.rotate[i] = 0; - } - }; - - this.getBlockSize = function () { - return this.BlockSize; - }; - - this.encrypt = function (src) { - const dst = new Array(src.length); - - for (let i = 0; i < src.length; i += 8) { - let l = src[i] << 24 | src[i + 1] << 16 | src[i + 2] << 8 | src[i + 3]; - let r = src[i + 4] << 24 | src[i + 5] << 16 | src[i + 6] << 8 | src[i + 7]; - let t; - - t = r; - r = l ^ f1(r, this.masking[0], this.rotate[0]); - l = t; - t = r; - r = l ^ f2(r, this.masking[1], this.rotate[1]); - l = t; - t = r; - r = l ^ f3(r, this.masking[2], this.rotate[2]); - l = t; - t = r; - r = l ^ f1(r, this.masking[3], this.rotate[3]); - l = t; - - t = r; - r = l ^ f2(r, this.masking[4], this.rotate[4]); - l = t; - t = r; - r = l ^ f3(r, this.masking[5], this.rotate[5]); - l = t; - t = r; - r = l ^ f1(r, this.masking[6], this.rotate[6]); - l = t; - t = r; - r = l ^ f2(r, this.masking[7], this.rotate[7]); - l = t; - - t = r; - r = l ^ f3(r, this.masking[8], this.rotate[8]); - l = t; - t = r; - r = l ^ f1(r, this.masking[9], this.rotate[9]); - l = t; - t = r; - r = l ^ f2(r, this.masking[10], this.rotate[10]); - l = t; - t = r; - r = l ^ f3(r, this.masking[11], this.rotate[11]); - l = t; - - t = r; - r = l ^ f1(r, this.masking[12], this.rotate[12]); - l = t; - t = r; - r = l ^ f2(r, this.masking[13], this.rotate[13]); - l = t; - t = r; - r = l ^ f3(r, this.masking[14], this.rotate[14]); - l = t; - t = r; - r = l ^ f1(r, this.masking[15], this.rotate[15]); - l = t; - - dst[i] = r >>> 24 & 255; - dst[i + 1] = r >>> 16 & 255; - dst[i + 2] = r >>> 8 & 255; - dst[i + 3] = r & 255; - dst[i + 4] = l >>> 24 & 255; - dst[i + 5] = l >>> 16 & 255; - dst[i + 6] = l >>> 8 & 255; - dst[i + 7] = l & 255; - } - - return dst; - }; - - this.decrypt = function (src) { - const dst = new Array(src.length); - - for (let i = 0; i < src.length; i += 8) { - let l = src[i] << 24 | src[i + 1] << 16 | src[i + 2] << 8 | src[i + 3]; - let r = src[i + 4] << 24 | src[i + 5] << 16 | src[i + 6] << 8 | src[i + 7]; - let t; - - t = r; - r = l ^ f1(r, this.masking[15], this.rotate[15]); - l = t; - t = r; - r = l ^ f3(r, this.masking[14], this.rotate[14]); - l = t; - t = r; - r = l ^ f2(r, this.masking[13], this.rotate[13]); - l = t; - t = r; - r = l ^ f1(r, this.masking[12], this.rotate[12]); - l = t; - - t = r; - r = l ^ f3(r, this.masking[11], this.rotate[11]); - l = t; - t = r; - r = l ^ f2(r, this.masking[10], this.rotate[10]); - l = t; - t = r; - r = l ^ f1(r, this.masking[9], this.rotate[9]); - l = t; - t = r; - r = l ^ f3(r, this.masking[8], this.rotate[8]); - l = t; - - t = r; - r = l ^ f2(r, this.masking[7], this.rotate[7]); - l = t; - t = r; - r = l ^ f1(r, this.masking[6], this.rotate[6]); - l = t; - t = r; - r = l ^ f3(r, this.masking[5], this.rotate[5]); - l = t; - t = r; - r = l ^ f2(r, this.masking[4], this.rotate[4]); - l = t; - - t = r; - r = l ^ f1(r, this.masking[3], this.rotate[3]); - l = t; - t = r; - r = l ^ f3(r, this.masking[2], this.rotate[2]); - l = t; - t = r; - r = l ^ f2(r, this.masking[1], this.rotate[1]); - l = t; - t = r; - r = l ^ f1(r, this.masking[0], this.rotate[0]); - l = t; - - dst[i] = r >>> 24 & 255; - dst[i + 1] = r >>> 16 & 255; - dst[i + 2] = r >>> 8 & 255; - dst[i + 3] = r & 255; - dst[i + 4] = l >>> 24 & 255; - dst[i + 5] = l >> 16 & 255; - dst[i + 6] = l >> 8 & 255; - dst[i + 7] = l & 255; - } - - return dst; - }; - const scheduleA = new Array(4); - - scheduleA[0] = new Array(4); - scheduleA[0][0] = [4, 0, 0xd, 0xf, 0xc, 0xe, 0x8]; - scheduleA[0][1] = [5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa]; - scheduleA[0][2] = [6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9]; - scheduleA[0][3] = [7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb]; - - scheduleA[1] = new Array(4); - scheduleA[1][0] = [0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0]; - scheduleA[1][1] = [1, 4, 0, 2, 1, 3, 16 + 2]; - scheduleA[1][2] = [2, 5, 7, 6, 5, 4, 16 + 1]; - scheduleA[1][3] = [3, 7, 0xa, 9, 0xb, 8, 16 + 3]; - - scheduleA[2] = new Array(4); - scheduleA[2][0] = [4, 0, 0xd, 0xf, 0xc, 0xe, 8]; - scheduleA[2][1] = [5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa]; - scheduleA[2][2] = [6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9]; - scheduleA[2][3] = [7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb]; - - scheduleA[3] = new Array(4); - scheduleA[3][0] = [0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0]; - scheduleA[3][1] = [1, 4, 0, 2, 1, 3, 16 + 2]; - scheduleA[3][2] = [2, 5, 7, 6, 5, 4, 16 + 1]; - scheduleA[3][3] = [3, 7, 0xa, 9, 0xb, 8, 16 + 3]; - - const scheduleB = new Array(4); - - scheduleB[0] = new Array(4); - scheduleB[0][0] = [16 + 8, 16 + 9, 16 + 7, 16 + 6, 16 + 2]; - scheduleB[0][1] = [16 + 0xa, 16 + 0xb, 16 + 5, 16 + 4, 16 + 6]; - scheduleB[0][2] = [16 + 0xc, 16 + 0xd, 16 + 3, 16 + 2, 16 + 9]; - scheduleB[0][3] = [16 + 0xe, 16 + 0xf, 16 + 1, 16 + 0, 16 + 0xc]; - - scheduleB[1] = new Array(4); - scheduleB[1][0] = [3, 2, 0xc, 0xd, 8]; - scheduleB[1][1] = [1, 0, 0xe, 0xf, 0xd]; - scheduleB[1][2] = [7, 6, 8, 9, 3]; - scheduleB[1][3] = [5, 4, 0xa, 0xb, 7]; - - scheduleB[2] = new Array(4); - scheduleB[2][0] = [16 + 3, 16 + 2, 16 + 0xc, 16 + 0xd, 16 + 9]; - scheduleB[2][1] = [16 + 1, 16 + 0, 16 + 0xe, 16 + 0xf, 16 + 0xc]; - scheduleB[2][2] = [16 + 7, 16 + 6, 16 + 8, 16 + 9, 16 + 2]; - scheduleB[2][3] = [16 + 5, 16 + 4, 16 + 0xa, 16 + 0xb, 16 + 6]; - - scheduleB[3] = new Array(4); - scheduleB[3][0] = [8, 9, 7, 6, 3]; - scheduleB[3][1] = [0xa, 0xb, 5, 4, 7]; - scheduleB[3][2] = [0xc, 0xd, 3, 2, 8]; - scheduleB[3][3] = [0xe, 0xf, 1, 0, 0xd]; - - // changed 'in' to 'inn' (in javascript 'in' is a reserved word) - this.keySchedule = function (inn) { - const t = new Array(8); - const k = new Array(32); - - let j; - - for (let i = 0; i < 4; i++) { - j = i * 4; - t[i] = inn[j] << 24 | inn[j + 1] << 16 | inn[j + 2] << 8 | inn[j + 3]; - } - - const x = [6, 7, 4, 5]; - let ki = 0; - let w; - - for (let half = 0; half < 2; half++) { - for (let round = 0; round < 4; round++) { - for (j = 0; j < 4; j++) { - const a = scheduleA[round][j]; - w = t[a[1]]; - - w ^= sBox[4][t[a[2] >>> 2] >>> 24 - 8 * (a[2] & 3) & 0xff]; - w ^= sBox[5][t[a[3] >>> 2] >>> 24 - 8 * (a[3] & 3) & 0xff]; - w ^= sBox[6][t[a[4] >>> 2] >>> 24 - 8 * (a[4] & 3) & 0xff]; - w ^= sBox[7][t[a[5] >>> 2] >>> 24 - 8 * (a[5] & 3) & 0xff]; - w ^= sBox[x[j]][t[a[6] >>> 2] >>> 24 - 8 * (a[6] & 3) & 0xff]; - t[a[0]] = w; - } - - for (j = 0; j < 4; j++) { - const b = scheduleB[round][j]; - w = sBox[4][t[b[0] >>> 2] >>> 24 - 8 * (b[0] & 3) & 0xff]; - - w ^= sBox[5][t[b[1] >>> 2] >>> 24 - 8 * (b[1] & 3) & 0xff]; - w ^= sBox[6][t[b[2] >>> 2] >>> 24 - 8 * (b[2] & 3) & 0xff]; - w ^= sBox[7][t[b[3] >>> 2] >>> 24 - 8 * (b[3] & 3) & 0xff]; - w ^= sBox[4 + j][t[b[4] >>> 2] >>> 24 - 8 * (b[4] & 3) & 0xff]; - k[ki] = w; - ki++; - } - } - } - - for (let i = 0; i < 16; i++) { - this.masking[i] = k[i]; - this.rotate[i] = k[16 + i] & 0x1f; - } - }; - - // These are the three 'f' functions. See RFC 2144, section 2.2. - - function f1(d, m, r) { - const t = m + d; - const I = t << r | t >>> 32 - r; - return (sBox[0][I >>> 24] ^ sBox[1][I >>> 16 & 255]) - sBox[2][I >>> 8 & 255] + sBox[3][I & 255]; - } - - function f2(d, m, r) { - const t = m ^ d; - const I = t << r | t >>> 32 - r; - return sBox[0][I >>> 24] - sBox[1][I >>> 16 & 255] + sBox[2][I >>> 8 & 255] ^ sBox[3][I & 255]; - } - - function f3(d, m, r) { - const t = m - d; - const I = t << r | t >>> 32 - r; - return (sBox[0][I >>> 24] + sBox[1][I >>> 16 & 255] ^ sBox[2][I >>> 8 & 255]) - sBox[3][I & 255]; - } - - const sBox = new Array(8); - sBox[0] = [0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949, 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0, 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, 0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935, 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d, 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, 0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe, 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3, 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, 0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291, 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779, 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, 0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d, 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c, 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, 0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d, 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96, 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, 0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, 0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872, 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9, 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf]; - - sBox[1] = [0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651, 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806, 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, 0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359, 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b, 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, 0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34, 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb, 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, 0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860, 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b, 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, 0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f, 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, 0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6, 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58, 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, 0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6, 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, 0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6, 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f, 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, 0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9, 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1]; - - sBox[2] = [0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90, 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240, 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, 0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71, 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, 0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15, 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, 0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176, 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148, 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, 0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e, 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a, 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, 0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5, 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, 0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536, 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, 0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69, 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, 0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a, 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783]; - - sBox[3] = [0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1, 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121, 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, 0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb, 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, 0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d, 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6, 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, 0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003, 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, 0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a, 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26, 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, 0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7, 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417, 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, 0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2, 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, 0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282, 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2]; - - sBox[4] = [0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f, 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02, 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, 0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7, 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9, 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, 0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774, 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655, 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, 0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910, 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1, 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, 0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f, 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3, 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, 0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4, 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2, 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, 0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5, 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, 0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801, 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, 0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8, 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4]; - - sBox[5] = [0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac, 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98, 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, 0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3, 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd, 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, 0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9, 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54, 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, 0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc, 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf, 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289, 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b, 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, 0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13, 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976, 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, 0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891, 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da, 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, 0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084, 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25, 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, 0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd, 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f]; - - sBox[6] = [0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f, 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19, 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, 0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516, 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88, 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, 0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756, 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, 0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688, 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28, 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566, 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, 0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962, 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e, 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, 0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c, 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, 0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be, 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767, 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, 0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c, 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3]; - - sBox[7] = [0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5, 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d, 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, 0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862, 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc, 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, 0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e, 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039, 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, 0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42, 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5, 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c, 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70, 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, 0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c, 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3, 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, 0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101, 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f, 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, 0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a, 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c, 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, 0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82, 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e]; -} - -function Cast5(key) { - this.cast5 = new OpenpgpSymencCast5(); - this.cast5.setKey(key); - - this.encrypt = function (block) { - return this.cast5.encrypt(block); - }; -} - -Cast5.blockSize = Cast5.prototype.blockSize = 8; -Cast5.keySize = Cast5.prototype.keySize = 16; - -exports.default = Cast5; - -},{}],85:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -//Paul Tero, July 2001 -//http://www.tero.co.uk/des/ -// -//Optimised for performance with large blocks by Michael Hayworth, November 2001 -//http://www.netdealing.com -// -// Modified by Recurity Labs GmbH - -//THIS SOFTWARE IS PROVIDED "AS IS" AND -//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -//FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -//DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -//OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -//HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -//OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -//SUCH DAMAGE. - -//des -//this takes the key, the message, and whether to encrypt or decrypt - -function des(keys, message, encrypt, mode, iv, padding) { - //declaring this locally speeds things up a bit - const spfunction1 = [0x1010400, 0, 0x10000, 0x1010404, 0x1010004, 0x10404, 0x4, 0x10000, 0x400, 0x1010400, 0x1010404, 0x400, 0x1000404, 0x1010004, 0x1000000, 0x4, 0x404, 0x1000400, 0x1000400, 0x10400, 0x10400, 0x1010000, 0x1010000, 0x1000404, 0x10004, 0x1000004, 0x1000004, 0x10004, 0, 0x404, 0x10404, 0x1000000, 0x10000, 0x1010404, 0x4, 0x1010000, 0x1010400, 0x1000000, 0x1000000, 0x400, 0x1010004, 0x10000, 0x10400, 0x1000004, 0x400, 0x4, 0x1000404, 0x10404, 0x1010404, 0x10004, 0x1010000, 0x1000404, 0x1000004, 0x404, 0x10404, 0x1010400, 0x404, 0x1000400, 0x1000400, 0, 0x10004, 0x10400, 0, 0x1010004]; - const spfunction2 = [-0x7fef7fe0, -0x7fff8000, 0x8000, 0x108020, 0x100000, 0x20, -0x7fefffe0, -0x7fff7fe0, -0x7fffffe0, -0x7fef7fe0, -0x7fef8000, -0x80000000, -0x7fff8000, 0x100000, 0x20, -0x7fefffe0, 0x108000, 0x100020, -0x7fff7fe0, 0, -0x80000000, 0x8000, 0x108020, -0x7ff00000, 0x100020, -0x7fffffe0, 0, 0x108000, 0x8020, -0x7fef8000, -0x7ff00000, 0x8020, 0, 0x108020, -0x7fefffe0, 0x100000, -0x7fff7fe0, -0x7ff00000, -0x7fef8000, 0x8000, -0x7ff00000, -0x7fff8000, 0x20, -0x7fef7fe0, 0x108020, 0x20, 0x8000, -0x80000000, 0x8020, -0x7fef8000, 0x100000, -0x7fffffe0, 0x100020, -0x7fff7fe0, -0x7fffffe0, 0x100020, 0x108000, 0, -0x7fff8000, 0x8020, -0x80000000, -0x7fefffe0, -0x7fef7fe0, 0x108000]; - const spfunction3 = [0x208, 0x8020200, 0, 0x8020008, 0x8000200, 0, 0x20208, 0x8000200, 0x20008, 0x8000008, 0x8000008, 0x20000, 0x8020208, 0x20008, 0x8020000, 0x208, 0x8000000, 0x8, 0x8020200, 0x200, 0x20200, 0x8020000, 0x8020008, 0x20208, 0x8000208, 0x20200, 0x20000, 0x8000208, 0x8, 0x8020208, 0x200, 0x8000000, 0x8020200, 0x8000000, 0x20008, 0x208, 0x20000, 0x8020200, 0x8000200, 0, 0x200, 0x20008, 0x8020208, 0x8000200, 0x8000008, 0x200, 0, 0x8020008, 0x8000208, 0x20000, 0x8000000, 0x8020208, 0x8, 0x20208, 0x20200, 0x8000008, 0x8020000, 0x8000208, 0x208, 0x8020000, 0x20208, 0x8, 0x8020008, 0x20200]; - const spfunction4 = [0x802001, 0x2081, 0x2081, 0x80, 0x802080, 0x800081, 0x800001, 0x2001, 0, 0x802000, 0x802000, 0x802081, 0x81, 0, 0x800080, 0x800001, 0x1, 0x2000, 0x800000, 0x802001, 0x80, 0x800000, 0x2001, 0x2080, 0x800081, 0x1, 0x2080, 0x800080, 0x2000, 0x802080, 0x802081, 0x81, 0x800080, 0x800001, 0x802000, 0x802081, 0x81, 0, 0, 0x802000, 0x2080, 0x800080, 0x800081, 0x1, 0x802001, 0x2081, 0x2081, 0x80, 0x802081, 0x81, 0x1, 0x2000, 0x800001, 0x2001, 0x802080, 0x800081, 0x2001, 0x2080, 0x800000, 0x802001, 0x80, 0x800000, 0x2000, 0x802080]; - const spfunction5 = [0x100, 0x2080100, 0x2080000, 0x42000100, 0x80000, 0x100, 0x40000000, 0x2080000, 0x40080100, 0x80000, 0x2000100, 0x40080100, 0x42000100, 0x42080000, 0x80100, 0x40000000, 0x2000000, 0x40080000, 0x40080000, 0, 0x40000100, 0x42080100, 0x42080100, 0x2000100, 0x42080000, 0x40000100, 0, 0x42000000, 0x2080100, 0x2000000, 0x42000000, 0x80100, 0x80000, 0x42000100, 0x100, 0x2000000, 0x40000000, 0x2080000, 0x42000100, 0x40080100, 0x2000100, 0x40000000, 0x42080000, 0x2080100, 0x40080100, 0x100, 0x2000000, 0x42080000, 0x42080100, 0x80100, 0x42000000, 0x42080100, 0x2080000, 0, 0x40080000, 0x42000000, 0x80100, 0x2000100, 0x40000100, 0x80000, 0, 0x40080000, 0x2080100, 0x40000100]; - const spfunction6 = [0x20000010, 0x20400000, 0x4000, 0x20404010, 0x20400000, 0x10, 0x20404010, 0x400000, 0x20004000, 0x404010, 0x400000, 0x20000010, 0x400010, 0x20004000, 0x20000000, 0x4010, 0, 0x400010, 0x20004010, 0x4000, 0x404000, 0x20004010, 0x10, 0x20400010, 0x20400010, 0, 0x404010, 0x20404000, 0x4010, 0x404000, 0x20404000, 0x20000000, 0x20004000, 0x10, 0x20400010, 0x404000, 0x20404010, 0x400000, 0x4010, 0x20000010, 0x400000, 0x20004000, 0x20000000, 0x4010, 0x20000010, 0x20404010, 0x404000, 0x20400000, 0x404010, 0x20404000, 0, 0x20400010, 0x10, 0x4000, 0x20400000, 0x404010, 0x4000, 0x400010, 0x20004010, 0, 0x20404000, 0x20000000, 0x400010, 0x20004010]; - const spfunction7 = [0x200000, 0x4200002, 0x4000802, 0, 0x800, 0x4000802, 0x200802, 0x4200800, 0x4200802, 0x200000, 0, 0x4000002, 0x2, 0x4000000, 0x4200002, 0x802, 0x4000800, 0x200802, 0x200002, 0x4000800, 0x4000002, 0x4200000, 0x4200800, 0x200002, 0x4200000, 0x800, 0x802, 0x4200802, 0x200800, 0x2, 0x4000000, 0x200800, 0x4000000, 0x200800, 0x200000, 0x4000802, 0x4000802, 0x4200002, 0x4200002, 0x2, 0x200002, 0x4000000, 0x4000800, 0x200000, 0x4200800, 0x802, 0x200802, 0x4200800, 0x802, 0x4000002, 0x4200802, 0x4200000, 0x200800, 0, 0x2, 0x4200802, 0, 0x200802, 0x4200000, 0x800, 0x4000002, 0x4000800, 0x800, 0x200002]; - const spfunction8 = [0x10001040, 0x1000, 0x40000, 0x10041040, 0x10000000, 0x10001040, 0x40, 0x10000000, 0x40040, 0x10040000, 0x10041040, 0x41000, 0x10041000, 0x41040, 0x1000, 0x40, 0x10040000, 0x10000040, 0x10001000, 0x1040, 0x41000, 0x40040, 0x10040040, 0x10041000, 0x1040, 0, 0, 0x10040040, 0x10000040, 0x10001000, 0x41040, 0x40000, 0x41040, 0x40000, 0x10041000, 0x1000, 0x40, 0x10040040, 0x1000, 0x41040, 0x10001000, 0x40, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x40000, 0x10001040, 0, 0x10041040, 0x40040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0, 0x10041040, 0x41000, 0x41000, 0x1040, 0x1040, 0x40040, 0x10000000, 0x10041000]; - - //create the 16 or 48 subkeys we will need - let m = 0; - let i; - let j; - let temp; - let right1; - let right2; - let left; - let right; - let looping; - let cbcleft; - let cbcleft2; - let cbcright; - let cbcright2; - let endloop; - let loopinc; - let len = message.length; - - //set up the loops for single and triple des - const iterations = keys.length === 32 ? 3 : 9; //single or triple des - if (iterations === 3) { - looping = encrypt ? [0, 32, 2] : [30, -2, -2]; - } else { - looping = encrypt ? [0, 32, 2, 62, 30, -2, 64, 96, 2] : [94, 62, -2, 32, 64, 2, 30, -2, -2]; - } - - //pad the message depending on the padding parameter - //only add padding if encrypting - note that you need to use the same padding option for both encrypt and decrypt - if (encrypt) { - message = des_addPadding(message, padding); - len = message.length; - } - - //store the result here - let result = new Uint8Array(len); - let k = 0; - - if (mode === 1) { - //CBC mode - cbcleft = iv[m++] << 24 | iv[m++] << 16 | iv[m++] << 8 | iv[m++]; - cbcright = iv[m++] << 24 | iv[m++] << 16 | iv[m++] << 8 | iv[m++]; - m = 0; - } - - //loop through each 64 bit chunk of the message - while (m < len) { - left = message[m++] << 24 | message[m++] << 16 | message[m++] << 8 | message[m++]; - right = message[m++] << 24 | message[m++] << 16 | message[m++] << 8 | message[m++]; - - //for Cipher Block Chaining mode, xor the message with the previous result - if (mode === 1) { - if (encrypt) { - left ^= cbcleft; - right ^= cbcright; - } else { - cbcleft2 = cbcleft; - cbcright2 = cbcright; - cbcleft = left; - cbcright = right; - } - } - - //first each 64 but chunk of the message must be permuted according to IP - temp = (left >>> 4 ^ right) & 0x0f0f0f0f; - right ^= temp; - left ^= temp << 4; - temp = (left >>> 16 ^ right) & 0x0000ffff; - right ^= temp; - left ^= temp << 16; - temp = (right >>> 2 ^ left) & 0x33333333; - left ^= temp; - right ^= temp << 2; - temp = (right >>> 8 ^ left) & 0x00ff00ff; - left ^= temp; - right ^= temp << 8; - temp = (left >>> 1 ^ right) & 0x55555555; - right ^= temp; - left ^= temp << 1; - - left = left << 1 | left >>> 31; - right = right << 1 | right >>> 31; - - //do this either 1 or 3 times for each chunk of the message - for (j = 0; j < iterations; j += 3) { - endloop = looping[j + 1]; - loopinc = looping[j + 2]; - //now go through and perform the encryption or decryption - for (i = looping[j]; i !== endloop; i += loopinc) { - //for efficiency - right1 = right ^ keys[i]; - right2 = (right >>> 4 | right << 28) ^ keys[i + 1]; - //the result is attained by passing these bytes through the S selection functions - temp = left; - left = right; - right = temp ^ (spfunction2[right1 >>> 24 & 0x3f] | spfunction4[right1 >>> 16 & 0x3f] | spfunction6[right1 >>> 8 & 0x3f] | spfunction8[right1 & 0x3f] | spfunction1[right2 >>> 24 & 0x3f] | spfunction3[right2 >>> 16 & 0x3f] | spfunction5[right2 >>> 8 & 0x3f] | spfunction7[right2 & 0x3f]); - } - temp = left; - left = right; - right = temp; //unreverse left and right - } //for either 1 or 3 iterations - - //move then each one bit to the right - left = left >>> 1 | left << 31; - right = right >>> 1 | right << 31; - - //now perform IP-1, which is IP in the opposite direction - temp = (left >>> 1 ^ right) & 0x55555555; - right ^= temp; - left ^= temp << 1; - temp = (right >>> 8 ^ left) & 0x00ff00ff; - left ^= temp; - right ^= temp << 8; - temp = (right >>> 2 ^ left) & 0x33333333; - left ^= temp; - right ^= temp << 2; - temp = (left >>> 16 ^ right) & 0x0000ffff; - right ^= temp; - left ^= temp << 16; - temp = (left >>> 4 ^ right) & 0x0f0f0f0f; - right ^= temp; - left ^= temp << 4; - - //for Cipher Block Chaining mode, xor the message with the previous result - if (mode === 1) { - if (encrypt) { - cbcleft = left; - cbcright = right; - } else { - left ^= cbcleft2; - right ^= cbcright2; - } - } - - result[k++] = left >>> 24; - result[k++] = left >>> 16 & 0xff; - result[k++] = left >>> 8 & 0xff; - result[k++] = left & 0xff; - result[k++] = right >>> 24; - result[k++] = right >>> 16 & 0xff; - result[k++] = right >>> 8 & 0xff; - result[k++] = right & 0xff; - } //for every 8 characters, or 64 bits in the message - - //only remove padding if decrypting - note that you need to use the same padding option for both encrypt and decrypt - if (!encrypt) { - result = des_removePadding(result, padding); - } - - return result; -} //end of des - - -//des_createKeys -//this takes as input a 64 bit key (even though only 56 bits are used) -//as an array of 2 integers, and returns 16 48 bit keys - -function des_createKeys(key) { - //declaring this locally speeds things up a bit - const pc2bytes0 = [0, 0x4, 0x20000000, 0x20000004, 0x10000, 0x10004, 0x20010000, 0x20010004, 0x200, 0x204, 0x20000200, 0x20000204, 0x10200, 0x10204, 0x20010200, 0x20010204]; - const pc2bytes1 = [0, 0x1, 0x100000, 0x100001, 0x4000000, 0x4000001, 0x4100000, 0x4100001, 0x100, 0x101, 0x100100, 0x100101, 0x4000100, 0x4000101, 0x4100100, 0x4100101]; - const pc2bytes2 = [0, 0x8, 0x800, 0x808, 0x1000000, 0x1000008, 0x1000800, 0x1000808, 0, 0x8, 0x800, 0x808, 0x1000000, 0x1000008, 0x1000800, 0x1000808]; - const pc2bytes3 = [0, 0x200000, 0x8000000, 0x8200000, 0x2000, 0x202000, 0x8002000, 0x8202000, 0x20000, 0x220000, 0x8020000, 0x8220000, 0x22000, 0x222000, 0x8022000, 0x8222000]; - const pc2bytes4 = [0, 0x40000, 0x10, 0x40010, 0, 0x40000, 0x10, 0x40010, 0x1000, 0x41000, 0x1010, 0x41010, 0x1000, 0x41000, 0x1010, 0x41010]; - const pc2bytes5 = [0, 0x400, 0x20, 0x420, 0, 0x400, 0x20, 0x420, 0x2000000, 0x2000400, 0x2000020, 0x2000420, 0x2000000, 0x2000400, 0x2000020, 0x2000420]; - const pc2bytes6 = [0, 0x10000000, 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002, 0, 0x10000000, 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002]; - const pc2bytes7 = [0, 0x10000, 0x800, 0x10800, 0x20000000, 0x20010000, 0x20000800, 0x20010800, 0x20000, 0x30000, 0x20800, 0x30800, 0x20020000, 0x20030000, 0x20020800, 0x20030800]; - const pc2bytes8 = [0, 0x40000, 0, 0x40000, 0x2, 0x40002, 0x2, 0x40002, 0x2000000, 0x2040000, 0x2000000, 0x2040000, 0x2000002, 0x2040002, 0x2000002, 0x2040002]; - const pc2bytes9 = [0, 0x10000000, 0x8, 0x10000008, 0, 0x10000000, 0x8, 0x10000008, 0x400, 0x10000400, 0x408, 0x10000408, 0x400, 0x10000400, 0x408, 0x10000408]; - const pc2bytes10 = [0, 0x20, 0, 0x20, 0x100000, 0x100020, 0x100000, 0x100020, 0x2000, 0x2020, 0x2000, 0x2020, 0x102000, 0x102020, 0x102000, 0x102020]; - const pc2bytes11 = [0, 0x1000000, 0x200, 0x1000200, 0x200000, 0x1200000, 0x200200, 0x1200200, 0x4000000, 0x5000000, 0x4000200, 0x5000200, 0x4200000, 0x5200000, 0x4200200, 0x5200200]; - const pc2bytes12 = [0, 0x1000, 0x8000000, 0x8001000, 0x80000, 0x81000, 0x8080000, 0x8081000, 0x10, 0x1010, 0x8000010, 0x8001010, 0x80010, 0x81010, 0x8080010, 0x8081010]; - const pc2bytes13 = [0, 0x4, 0x100, 0x104, 0, 0x4, 0x100, 0x104, 0x1, 0x5, 0x101, 0x105, 0x1, 0x5, 0x101, 0x105]; - - //how many iterations (1 for des, 3 for triple des) - const iterations = key.length > 8 ? 3 : 1; //changed by Paul 16/6/2007 to use Triple DES for 9+ byte keys - //stores the return keys - const keys = new Array(32 * iterations); - //now define the left shifts which need to be done - const shifts = [0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0]; - //other variables - let lefttemp; - let righttemp; - let m = 0; - let n = 0; - let temp; - - for (let j = 0; j < iterations; j++) { - //either 1 or 3 iterations - let left = key[m++] << 24 | key[m++] << 16 | key[m++] << 8 | key[m++]; - let right = key[m++] << 24 | key[m++] << 16 | key[m++] << 8 | key[m++]; - - temp = (left >>> 4 ^ right) & 0x0f0f0f0f; - right ^= temp; - left ^= temp << 4; - temp = (right >>> -16 ^ left) & 0x0000ffff; - left ^= temp; - right ^= temp << -16; - temp = (left >>> 2 ^ right) & 0x33333333; - right ^= temp; - left ^= temp << 2; - temp = (right >>> -16 ^ left) & 0x0000ffff; - left ^= temp; - right ^= temp << -16; - temp = (left >>> 1 ^ right) & 0x55555555; - right ^= temp; - left ^= temp << 1; - temp = (right >>> 8 ^ left) & 0x00ff00ff; - left ^= temp; - right ^= temp << 8; - temp = (left >>> 1 ^ right) & 0x55555555; - right ^= temp; - left ^= temp << 1; - - //the right side needs to be shifted and to get the last four bits of the left side - temp = left << 8 | right >>> 20 & 0x000000f0; - //left needs to be put upside down - left = right << 24 | right << 8 & 0xff0000 | right >>> 8 & 0xff00 | right >>> 24 & 0xf0; - right = temp; - - //now go through and perform these shifts on the left and right keys - for (let i = 0; i < shifts.length; i++) { - //shift the keys either one or two bits to the left - if (shifts[i]) { - left = left << 2 | left >>> 26; - right = right << 2 | right >>> 26; - } else { - left = left << 1 | left >>> 27; - right = right << 1 | right >>> 27; - } - left &= -0xf; - right &= -0xf; - - //now apply PC-2, in such a way that E is easier when encrypting or decrypting - //this conversion will look like PC-2 except only the last 6 bits of each byte are used - //rather than 48 consecutive bits and the order of lines will be according to - //how the S selection functions will be applied: S2, S4, S6, S8, S1, S3, S5, S7 - lefttemp = pc2bytes0[left >>> 28] | pc2bytes1[left >>> 24 & 0xf] | pc2bytes2[left >>> 20 & 0xf] | pc2bytes3[left >>> 16 & 0xf] | pc2bytes4[left >>> 12 & 0xf] | pc2bytes5[left >>> 8 & 0xf] | pc2bytes6[left >>> 4 & 0xf]; - righttemp = pc2bytes7[right >>> 28] | pc2bytes8[right >>> 24 & 0xf] | pc2bytes9[right >>> 20 & 0xf] | pc2bytes10[right >>> 16 & 0xf] | pc2bytes11[right >>> 12 & 0xf] | pc2bytes12[right >>> 8 & 0xf] | pc2bytes13[right >>> 4 & 0xf]; - temp = (righttemp >>> 16 ^ lefttemp) & 0x0000ffff; - keys[n++] = lefttemp ^ temp; - keys[n++] = righttemp ^ temp << 16; - } - } //for each iterations - //return the keys we've created - return keys; -} //end of des_createKeys - - -function des_addPadding(message, padding) { - const padLength = 8 - message.length % 8; - - let pad; - if (padding === 2 && padLength < 8) { - //pad the message with spaces - pad = " ".charCodeAt(0); - } else if (padding === 1) { - //PKCS7 padding - pad = padLength; - } else if (!padding && padLength < 8) { - //pad the message out with null bytes - pad = 0; - } else if (padLength === 8) { - return message; - } else { - throw new Error('des: invalid padding'); - } - - const paddedMessage = new Uint8Array(message.length + padLength); - for (let i = 0; i < message.length; i++) { - paddedMessage[i] = message[i]; - } - for (let j = 0; j < padLength; j++) { - paddedMessage[message.length + j] = pad; - } - - return paddedMessage; -} - -function des_removePadding(message, padding) { - let padLength = null; - let pad; - if (padding === 2) { - // space padded - pad = " ".charCodeAt(0); - } else if (padding === 1) { - // PKCS7 - padLength = message[message.length - 1]; - } else if (!padding) { - // null padding - pad = 0; - } else { - throw new Error('des: invalid padding'); - } - - if (!padLength) { - padLength = 1; - while (message[message.length - padLength] === pad) { - padLength++; - } - padLength--; - } - - return message.subarray(0, message.length - padLength); -} - -// added by Recurity Labs - -function TripleDES(key) { - this.key = []; - - for (let i = 0; i < 3; i++) { - this.key.push(new Uint8Array(key.subarray(i * 8, i * 8 + 8))); - } - - this.encrypt = function (block) { - return des(des_createKeys(this.key[2]), des(des_createKeys(this.key[1]), des(des_createKeys(this.key[0]), block, true, 0, null, null), false, 0, null, null), true, 0, null, null); - }; -} - -TripleDES.keySize = TripleDES.prototype.keySize = 24; -TripleDES.blockSize = TripleDES.prototype.blockSize = 8; - -// This is "original" DES - -function DES(key) { - this.key = key; - - this.encrypt = function (block, padding) { - const keys = des_createKeys(this.key); - return des(keys, block, true, 0, null, padding); - }; - - this.decrypt = function (block, padding) { - const keys = des_createKeys(this.key); - return des(keys, block, false, 0, null, padding); - }; -} - -exports.default = { DES, TripleDES }; - -},{}],86:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _aes = require('./aes'); - -var _aes2 = _interopRequireDefault(_aes); - -var _des = require('./des.js'); - -var _des2 = _interopRequireDefault(_des); - -var _cast = require('./cast5'); - -var _cast2 = _interopRequireDefault(_cast); - -var _twofish = require('./twofish'); - -var _twofish2 = _interopRequireDefault(_twofish); - -var _blowfish = require('./blowfish'); - -var _blowfish2 = _interopRequireDefault(_blowfish); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -exports.default = { - /** - * AES-128 encryption and decryption (ID 7) - * @function - * @param {String} key 128-bit key - * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} - * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} - * @returns {Object} - * @requires asmcrypto.js - */ - aes128: (0, _aes2.default)(128), - /** - * AES-128 Block Cipher (ID 8) - * @function - * @param {String} key 192-bit key - * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} - * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} - * @returns {Object} - * @requires asmcrypto.js - */ - aes192: (0, _aes2.default)(192), - /** - * AES-128 Block Cipher (ID 9) - * @function - * @param {String} key 256-bit key - * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} - * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} - * @returns {Object} - * @requires asmcrypto.js - */ - aes256: (0, _aes2.default)(256), - // Not in OpenPGP specifications - des: _des2.default.DES, - /** - * Triple DES Block Cipher (ID 2) - * @function - * @param {String} key 192-bit key - * @see {@link https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-67r2.pdf|NIST SP 800-67} - * @returns {Object} - */ - tripledes: _des2.default.TripleDES, - '3des': _des2.default.TripleDES, - /** - * CAST-128 Block Cipher (ID 3) - * @function - * @param {String} key 128-bit key - * @see {@link https://tools.ietf.org/html/rfc2144|The CAST-128 Encryption Algorithm} - * @returns {Object} - */ - cast5: _cast2.default, - /** - * Twofish Block Cipher (ID 10) - * @function - * @param {String} key 256-bit key - * @see {@link https://tools.ietf.org/html/rfc4880#ref-TWOFISH|TWOFISH} - * @returns {Object} - */ - twofish: _twofish2.default, - /** - * Blowfish Block Cipher (ID 4) - * @function - * @param {String} key 128-bit key - * @see {@link https://tools.ietf.org/html/rfc4880#ref-BLOWFISH|BLOWFISH} - * @returns {Object} - */ - blowfish: _blowfish2.default, - /** - * Not implemented - * @function - * @throws {Error} - */ - idea: function idea() { - throw new Error('IDEA symmetric-key algorithm not implemented'); - } -}; /** - * @fileoverview Symmetric cryptography functions - * @requires crypto/cipher/aes - * @requires crypto/cipher/des - * @requires crypto/cipher/cast5 - * @requires crypto/cipher/twofish - * @requires crypto/cipher/blowfish - * @module crypto/cipher - */ - -},{"./aes":82,"./blowfish":83,"./cast5":84,"./des.js":85,"./twofish":87}],87:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -/* eslint-disable no-mixed-operators, no-fallthrough */ - -/* Modified by Recurity Labs GmbH - * - * Cipher.js - * A block-cipher algorithm implementation on JavaScript - * See Cipher.readme.txt for further information. - * - * Copyright(c) 2009 Atsushi Oka [ http://oka.nu/ ] - * This script file is distributed under the LGPL - * - * ACKNOWLEDGMENT - * - * The main subroutines are written by Michiel van Everdingen. - * - * Michiel van Everdingen - * http://home.versatel.nl/MAvanEverdingen/index.html - * - * All rights for these routines are reserved to Michiel van Everdingen. - * - */ - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//Math -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -const MAXINT = 0xFFFFFFFF; - -function rotw(w, n) { - return (w << n | w >>> 32 - n) & MAXINT; -} - -function getW(a, i) { - return a[i] | a[i + 1] << 8 | a[i + 2] << 16 | a[i + 3] << 24; -} - -function setW(a, i, w) { - a.splice(i, 4, w & 0xFF, w >>> 8 & 0xFF, w >>> 16 & 0xFF, w >>> 24 & 0xFF); -} - -function getB(x, n) { - return x >>> n * 8 & 0xFF; -} - -// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Twofish -// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -function createTwofish() { - // - let keyBytes = null; - let dataBytes = null; - let dataOffset = -1; - // var dataLength = -1; - // var idx2 = -1; - // - - let tfsKey = []; - let tfsM = [[], [], [], []]; - - function tfsInit(key) { - keyBytes = key; - let i; - let a; - let b; - let c; - let d; - const meKey = []; - const moKey = []; - const inKey = []; - let kLen; - const sKey = []; - let f01; - let f5b; - let fef; - - const q0 = [[8, 1, 7, 13, 6, 15, 3, 2, 0, 11, 5, 9, 14, 12, 10, 4], [2, 8, 11, 13, 15, 7, 6, 14, 3, 1, 9, 4, 0, 10, 12, 5]]; - const q1 = [[14, 12, 11, 8, 1, 2, 3, 5, 15, 4, 10, 6, 7, 0, 9, 13], [1, 14, 2, 11, 4, 12, 3, 7, 6, 13, 10, 5, 15, 9, 0, 8]]; - const q2 = [[11, 10, 5, 14, 6, 13, 9, 0, 12, 8, 15, 3, 2, 4, 7, 1], [4, 12, 7, 5, 1, 6, 9, 10, 0, 14, 13, 8, 2, 11, 3, 15]]; - const q3 = [[13, 7, 15, 4, 1, 2, 6, 14, 9, 11, 3, 0, 8, 5, 12, 10], [11, 9, 5, 1, 12, 3, 13, 14, 6, 4, 7, 15, 2, 0, 8, 10]]; - const ror4 = [0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15]; - const ashx = [0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 5, 14, 7]; - const q = [[], []]; - const m = [[], [], [], []]; - - function ffm5b(x) { - return x ^ x >> 2 ^ [0, 90, 180, 238][x & 3]; - } - - function ffmEf(x) { - return x ^ x >> 1 ^ x >> 2 ^ [0, 238, 180, 90][x & 3]; - } - - function mdsRem(p, q) { - let i; - let t; - let u; - for (i = 0; i < 8; i++) { - t = q >>> 24; - q = q << 8 & MAXINT | p >>> 24; - p = p << 8 & MAXINT; - u = t << 1; - if (t & 128) { - u ^= 333; - } - q ^= t ^ u << 16; - u ^= t >>> 1; - if (t & 1) { - u ^= 166; - } - q ^= u << 24 | u << 8; - } - return q; - } - - function qp(n, x) { - const a = x >> 4; - const b = x & 15; - const c = q0[n][a ^ b]; - const d = q1[n][ror4[b] ^ ashx[a]]; - return q3[n][ror4[d] ^ ashx[c]] << 4 | q2[n][c ^ d]; - } - - function hFun(x, key) { - let a = getB(x, 0); - let b = getB(x, 1); - let c = getB(x, 2); - let d = getB(x, 3); - switch (kLen) { - case 4: - a = q[1][a] ^ getB(key[3], 0); - b = q[0][b] ^ getB(key[3], 1); - c = q[0][c] ^ getB(key[3], 2); - d = q[1][d] ^ getB(key[3], 3); - case 3: - a = q[1][a] ^ getB(key[2], 0); - b = q[1][b] ^ getB(key[2], 1); - c = q[0][c] ^ getB(key[2], 2); - d = q[0][d] ^ getB(key[2], 3); - case 2: - a = q[0][q[0][a] ^ getB(key[1], 0)] ^ getB(key[0], 0); - b = q[0][q[1][b] ^ getB(key[1], 1)] ^ getB(key[0], 1); - c = q[1][q[0][c] ^ getB(key[1], 2)] ^ getB(key[0], 2); - d = q[1][q[1][d] ^ getB(key[1], 3)] ^ getB(key[0], 3); - } - return m[0][a] ^ m[1][b] ^ m[2][c] ^ m[3][d]; - } - - keyBytes = keyBytes.slice(0, 32); - i = keyBytes.length; - while (i !== 16 && i !== 24 && i !== 32) { - keyBytes[i++] = 0; - } - - for (i = 0; i < keyBytes.length; i += 4) { - inKey[i >> 2] = getW(keyBytes, i); - } - for (i = 0; i < 256; i++) { - q[0][i] = qp(0, i); - q[1][i] = qp(1, i); - } - for (i = 0; i < 256; i++) { - f01 = q[1][i]; - f5b = ffm5b(f01); - fef = ffmEf(f01); - m[0][i] = f01 + (f5b << 8) + (fef << 16) + (fef << 24); - m[2][i] = f5b + (fef << 8) + (f01 << 16) + (fef << 24); - f01 = q[0][i]; - f5b = ffm5b(f01); - fef = ffmEf(f01); - m[1][i] = fef + (fef << 8) + (f5b << 16) + (f01 << 24); - m[3][i] = f5b + (f01 << 8) + (fef << 16) + (f5b << 24); - } - - kLen = inKey.length / 2; - for (i = 0; i < kLen; i++) { - a = inKey[i + i]; - meKey[i] = a; - b = inKey[i + i + 1]; - moKey[i] = b; - sKey[kLen - i - 1] = mdsRem(a, b); - } - for (i = 0; i < 40; i += 2) { - a = 0x1010101 * i; - b = a + 0x1010101; - a = hFun(a, meKey); - b = rotw(hFun(b, moKey), 8); - tfsKey[i] = a + b & MAXINT; - tfsKey[i + 1] = rotw(a + 2 * b, 9); - } - for (i = 0; i < 256; i++) { - a = b = c = d = i; - switch (kLen) { - case 4: - a = q[1][a] ^ getB(sKey[3], 0); - b = q[0][b] ^ getB(sKey[3], 1); - c = q[0][c] ^ getB(sKey[3], 2); - d = q[1][d] ^ getB(sKey[3], 3); - case 3: - a = q[1][a] ^ getB(sKey[2], 0); - b = q[1][b] ^ getB(sKey[2], 1); - c = q[0][c] ^ getB(sKey[2], 2); - d = q[0][d] ^ getB(sKey[2], 3); - case 2: - tfsM[0][i] = m[0][q[0][q[0][a] ^ getB(sKey[1], 0)] ^ getB(sKey[0], 0)]; - tfsM[1][i] = m[1][q[0][q[1][b] ^ getB(sKey[1], 1)] ^ getB(sKey[0], 1)]; - tfsM[2][i] = m[2][q[1][q[0][c] ^ getB(sKey[1], 2)] ^ getB(sKey[0], 2)]; - tfsM[3][i] = m[3][q[1][q[1][d] ^ getB(sKey[1], 3)] ^ getB(sKey[0], 3)]; - } - } - } - - function tfsG0(x) { - return tfsM[0][getB(x, 0)] ^ tfsM[1][getB(x, 1)] ^ tfsM[2][getB(x, 2)] ^ tfsM[3][getB(x, 3)]; - } - - function tfsG1(x) { - return tfsM[0][getB(x, 3)] ^ tfsM[1][getB(x, 0)] ^ tfsM[2][getB(x, 1)] ^ tfsM[3][getB(x, 2)]; - } - - function tfsFrnd(r, blk) { - let a = tfsG0(blk[0]); - let b = tfsG1(blk[1]); - blk[2] = rotw(blk[2] ^ a + b + tfsKey[4 * r + 8] & MAXINT, 31); - blk[3] = rotw(blk[3], 1) ^ a + 2 * b + tfsKey[4 * r + 9] & MAXINT; - a = tfsG0(blk[2]); - b = tfsG1(blk[3]); - blk[0] = rotw(blk[0] ^ a + b + tfsKey[4 * r + 10] & MAXINT, 31); - blk[1] = rotw(blk[1], 1) ^ a + 2 * b + tfsKey[4 * r + 11] & MAXINT; - } - - function tfsIrnd(i, blk) { - let a = tfsG0(blk[0]); - let b = tfsG1(blk[1]); - blk[2] = rotw(blk[2], 1) ^ a + b + tfsKey[4 * i + 10] & MAXINT; - blk[3] = rotw(blk[3] ^ a + 2 * b + tfsKey[4 * i + 11] & MAXINT, 31); - a = tfsG0(blk[2]); - b = tfsG1(blk[3]); - blk[0] = rotw(blk[0], 1) ^ a + b + tfsKey[4 * i + 8] & MAXINT; - blk[1] = rotw(blk[1] ^ a + 2 * b + tfsKey[4 * i + 9] & MAXINT, 31); - } - - function tfsClose() { - tfsKey = []; - tfsM = [[], [], [], []]; - } - - function tfsEncrypt(data, offset) { - dataBytes = data; - dataOffset = offset; - const blk = [getW(dataBytes, dataOffset) ^ tfsKey[0], getW(dataBytes, dataOffset + 4) ^ tfsKey[1], getW(dataBytes, dataOffset + 8) ^ tfsKey[2], getW(dataBytes, dataOffset + 12) ^ tfsKey[3]]; - for (let j = 0; j < 8; j++) { - tfsFrnd(j, blk); - } - setW(dataBytes, dataOffset, blk[2] ^ tfsKey[4]); - setW(dataBytes, dataOffset + 4, blk[3] ^ tfsKey[5]); - setW(dataBytes, dataOffset + 8, blk[0] ^ tfsKey[6]); - setW(dataBytes, dataOffset + 12, blk[1] ^ tfsKey[7]); - dataOffset += 16; - return dataBytes; - } - - function tfsDecrypt(data, offset) { - dataBytes = data; - dataOffset = offset; - const blk = [getW(dataBytes, dataOffset) ^ tfsKey[4], getW(dataBytes, dataOffset + 4) ^ tfsKey[5], getW(dataBytes, dataOffset + 8) ^ tfsKey[6], getW(dataBytes, dataOffset + 12) ^ tfsKey[7]]; - for (let j = 7; j >= 0; j--) { - tfsIrnd(j, blk); - } - setW(dataBytes, dataOffset, blk[2] ^ tfsKey[0]); - setW(dataBytes, dataOffset + 4, blk[3] ^ tfsKey[1]); - setW(dataBytes, dataOffset + 8, blk[0] ^ tfsKey[2]); - setW(dataBytes, dataOffset + 12, blk[1] ^ tfsKey[3]); - dataOffset += 16; - } - - // added by Recurity Labs - - function tfsFinal() { - return dataBytes; - } - - return { - name: "twofish", - blocksize: 128 / 8, - open: tfsInit, - close: tfsClose, - encrypt: tfsEncrypt, - decrypt: tfsDecrypt, - // added by Recurity Labs - finalize: tfsFinal - }; -} - -// added by Recurity Labs - -function TF(key) { - this.tf = createTwofish(); - this.tf.open(Array.from(key), 0); - - this.encrypt = function (block) { - return this.tf.encrypt(Array.from(block), 0); - }; -} - -TF.keySize = TF.prototype.keySize = 32; -TF.blockSize = TF.prototype.blockSize = 16; - -exports.default = TF; - -},{}],88:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _cbc = require('asmcrypto.js/dist_es5/aes/cbc'); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * @fileoverview This module implements AES-CMAC on top of - * native AES-CBC using either the WebCrypto API or Node.js' crypto API. - * @requires asmcrypto.js - * @requires util - * @module crypto/cmac - */ - -const webCrypto = _util2.default.getWebCrypto(); -const nodeCrypto = _util2.default.getNodeCrypto(); -const Buffer = _util2.default.getNodeBuffer(); - -/** - * This implementation of CMAC is based on the description of OMAC in - * http://web.cs.ucdavis.edu/~rogaway/papers/eax.pdf. As per that - * document: - * - * We have made a small modification to the OMAC algorithm as it was - * originally presented, changing one of its two constants. - * Specifically, the constant 4 at line 85 was the constant 1/2 (the - * multiplicative inverse of 2) in the original definition of OMAC [14]. - * The OMAC authors indicate that they will promulgate this modification - * [15], which slightly simplifies implementations. - */ - -const blockLength = 16; - -/** - * xor `padding` into the end of `data`. This function implements "the - * operation xor→ [which] xors the shorter string into the end of longer - * one". Since data is always as least as long as padding, we can - * simplify the implementation. - * @param {Uint8Array} data - * @param {Uint8Array} padding - */ -function rightXorMut(data, padding) { - const offset = data.length - blockLength; - for (let i = 0; i < blockLength; i++) { - data[i + offset] ^= padding[i]; - } - return data; -} - -function pad(data, padding, padding2) { - // if |M| in {n, 2n, 3n, ...} - if (data.length && data.length % blockLength === 0) { - // then return M xor→ B, - return rightXorMut(data, padding); - } - // else return (M || 10^(n−1−(|M| mod n))) xor→ P - const padded = new Uint8Array(data.length + (blockLength - data.length % blockLength)); - padded.set(data); - padded[data.length] = 0b10000000; - return rightXorMut(padded, padding2); -} - -const zeroBlock = new Uint8Array(blockLength); - -exports.default = async function CMAC(key) { - const cbc = await CBC(key); - - // L ← E_K(0^n); B ← 2L; P ← 4L - const padding = _util2.default.double((await cbc(zeroBlock))); - const padding2 = _util2.default.double(padding); - - return async function (data) { - // return CBC_K(pad(M; B, P)) - return (await cbc(pad(data, padding, padding2))).subarray(-blockLength); - }; -}; - -async function CBC(key) { - if (_util2.default.getWebCrypto() && key.length !== 24) { - // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support - key = await webCrypto.importKey('raw', key, { name: 'AES-CBC', length: key.length * 8 }, false, ['encrypt']); - return async function (pt) { - const ct = await webCrypto.encrypt({ name: 'AES-CBC', iv: zeroBlock, length: blockLength * 8 }, key, pt); - return new Uint8Array(ct).subarray(0, ct.byteLength - blockLength); - }; - } - if (_util2.default.getNodeCrypto()) { - // Node crypto library - key = new Buffer(key); - return async function (pt) { - pt = new Buffer(pt); - const en = new nodeCrypto.createCipheriv('aes-' + key.length * 8 + '-cbc', key, zeroBlock); - const ct = en.update(pt); - return new Uint8Array(ct); - }; - } - // asm.js fallback - return async function (pt) { - return _cbc.AES_CBC.encrypt(pt, key, false, zeroBlock); - }; -} - -},{"../util":152,"asmcrypto.js/dist_es5/aes/cbc":4}],89:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _bn = require('bn.js'); - -var _bn2 = _interopRequireDefault(_bn); - -var _public_key = require('./public_key'); - -var _public_key2 = _interopRequireDefault(_public_key); - -var _cipher = require('./cipher'); - -var _cipher2 = _interopRequireDefault(_cipher); - -var _random = require('./random'); - -var _random2 = _interopRequireDefault(_random); - -var _ecdh_symkey = require('../type/ecdh_symkey'); - -var _ecdh_symkey2 = _interopRequireDefault(_ecdh_symkey); - -var _kdf_params = require('../type/kdf_params'); - -var _kdf_params2 = _interopRequireDefault(_kdf_params); - -var _mpi = require('../type/mpi'); - -var _mpi2 = _interopRequireDefault(_mpi); - -var _oid = require('../type/oid'); - -var _oid2 = _interopRequireDefault(_oid); - -var _enums = require('../enums'); - -var _enums2 = _interopRequireDefault(_enums); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -// The GPG4Browsers crypto interface - -/** - * @fileoverview Provides functions for asymmetric encryption and decryption as - * well as key generation and parameter handling for all public-key cryptosystems. - * @requires bn.js - * @requires crypto/public_key - * @requires crypto/cipher - * @requires crypto/random - * @requires type/ecdh_symkey - * @requires type/kdf_params - * @requires type/mpi - * @requires type/oid - * @requires enums - * @requires util - * @module crypto/crypto - */ - -function constructParams(types, data) { - return types.map(function (type, i) { - if (data && data[i]) { - return new type(data[i]); - } - return new type(); - }); -} - -exports.default = { - /** - * Encrypts data using specified algorithm and public key parameters. - * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} for public key algorithms. - * @param {module:enums.publicKey} algo Public key algorithm - * @param {Array} pub_params Algorithm-specific public key parameters - * @param {module:type/mpi} data Data to be encrypted as MPI - * @param {String} fingerprint Recipient fingerprint - * @returns {Array} encrypted session key parameters - * @async - */ - publicKeyEncrypt: async function publicKeyEncrypt(algo, pub_params, data, fingerprint) { - const types = this.getEncSessionKeyParamTypes(algo); - switch (algo) { - case _enums2.default.publicKey.rsa_encrypt: - case _enums2.default.publicKey.rsa_encrypt_sign: - { - const m = data.toBN(); - const n = pub_params[0].toBN(); - const e = pub_params[1].toBN(); - const res = await _public_key2.default.rsa.encrypt(m, n, e); - return constructParams(types, [res]); - } - case _enums2.default.publicKey.elgamal: - { - const m = data.toBN(); - const p = pub_params[0].toBN(); - const g = pub_params[1].toBN(); - const y = pub_params[2].toBN(); - const res = await _public_key2.default.elgamal.encrypt(m, p, g, y); - return constructParams(types, [res.c1, res.c2]); - } - case _enums2.default.publicKey.ecdh: - { - const oid = pub_params[0]; - const Q = pub_params[1].toUint8Array(); - const kdf_params = pub_params[2]; - - var _ref = await _public_key2.default.elliptic.ecdh.encrypt(oid, kdf_params.cipher, kdf_params.hash, data, Q, fingerprint); - - const V = _ref.publicKey, - C = _ref.wrappedKey; - - return constructParams(types, [new _bn2.default(V), C]); - } - default: - return []; - } - }, - - /** - * Decrypts data using specified algorithm and private key parameters. - * See {@link https://tools.ietf.org/html/rfc4880#section-5.5.3|RFC 4880 5.5.3} - * @param {module:enums.publicKey} algo Public key algorithm - * @param {Array} key_params Algorithm-specific public, private key parameters - * @param {Array} - data_params encrypted session key parameters - * @param {String} fingerprint Recipient fingerprint - * @returns {BN} A BN containing the decrypted data - * @async - */ - publicKeyDecrypt: async function publicKeyDecrypt(algo, key_params, data_params, fingerprint) { - switch (algo) { - case _enums2.default.publicKey.rsa_encrypt_sign: - case _enums2.default.publicKey.rsa_encrypt: - { - const c = data_params[0].toBN(); - const n = key_params[0].toBN(); // n = pq - const e = key_params[1].toBN(); - const d = key_params[2].toBN(); // de = 1 mod (p-1)(q-1) - const p = key_params[3].toBN(); - const q = key_params[4].toBN(); - const u = key_params[5].toBN(); // p^-1 mod q - return _public_key2.default.rsa.decrypt(c, n, e, d, p, q, u); - } - case _enums2.default.publicKey.elgamal: - { - const c1 = data_params[0].toBN(); - const c2 = data_params[1].toBN(); - const p = key_params[0].toBN(); - const x = key_params[3].toBN(); - return _public_key2.default.elgamal.decrypt(c1, c2, p, x); - } - case _enums2.default.publicKey.ecdh: - { - const oid = key_params[0]; - const kdf_params = key_params[2]; - const V = data_params[0].toUint8Array(); - const C = data_params[1].data; - const Q = key_params[1].toUint8Array(); - const d = key_params[3].toUint8Array(); - return _public_key2.default.elliptic.ecdh.decrypt(oid, kdf_params.cipher, kdf_params.hash, V, C, Q, d, fingerprint); - } - default: - throw new Error('Invalid public key encryption algorithm.'); - } - }, - - /** Returns the types comprising the private key of an algorithm - * @param {String} algo The public key algorithm - * @returns {Array} The array of types - */ - getPrivKeyParamTypes: function getPrivKeyParamTypes(algo) { - switch (algo) { - // Algorithm-Specific Fields for RSA secret keys: - // - multiprecision integer (MPI) of RSA secret exponent d. - // - MPI of RSA secret prime value p. - // - MPI of RSA secret prime value q (p < q). - // - MPI of u, the multiplicative inverse of p, mod q. - case _enums2.default.publicKey.rsa_encrypt: - case _enums2.default.publicKey.rsa_encrypt_sign: - case _enums2.default.publicKey.rsa_sign: - return [_mpi2.default, _mpi2.default, _mpi2.default, _mpi2.default]; - // Algorithm-Specific Fields for Elgamal secret keys: - // - MPI of Elgamal secret exponent x. - case _enums2.default.publicKey.elgamal: - return [_mpi2.default]; - // Algorithm-Specific Fields for DSA secret keys: - // - MPI of DSA secret exponent x. - case _enums2.default.publicKey.dsa: - return [_mpi2.default]; - // Algorithm-Specific Fields for ECDSA or ECDH secret keys: - // - MPI of an integer representing the secret key. - case _enums2.default.publicKey.ecdh: - case _enums2.default.publicKey.ecdsa: - case _enums2.default.publicKey.eddsa: - return [_mpi2.default]; - default: - throw new Error('Invalid public key encryption algorithm.'); - } - }, - - /** Returns the types comprising the public key of an algorithm - * @param {String} algo The public key algorithm - * @returns {Array} The array of types - */ - getPubKeyParamTypes: function getPubKeyParamTypes(algo) { - switch (algo) { - // Algorithm-Specific Fields for RSA public keys: - // - a multiprecision integer (MPI) of RSA public modulus n; - // - an MPI of RSA public encryption exponent e. - case _enums2.default.publicKey.rsa_encrypt: - case _enums2.default.publicKey.rsa_encrypt_sign: - case _enums2.default.publicKey.rsa_sign: - return [_mpi2.default, _mpi2.default]; - // Algorithm-Specific Fields for Elgamal public keys: - // - MPI of Elgamal prime p; - // - MPI of Elgamal group generator g; - // - MPI of Elgamal public key value y (= g**x mod p where x is secret). - case _enums2.default.publicKey.elgamal: - return [_mpi2.default, _mpi2.default, _mpi2.default]; - // Algorithm-Specific Fields for DSA public keys: - // - MPI of DSA prime p; - // - MPI of DSA group order q (q is a prime divisor of p-1); - // - MPI of DSA group generator g; - // - MPI of DSA public-key value y (= g**x mod p where x is secret). - case _enums2.default.publicKey.dsa: - return [_mpi2.default, _mpi2.default, _mpi2.default, _mpi2.default]; - // Algorithm-Specific Fields for ECDSA/EdDSA public keys: - // - OID of curve; - // - MPI of EC point representing public key. - case _enums2.default.publicKey.ecdsa: - case _enums2.default.publicKey.eddsa: - return [_oid2.default, _mpi2.default]; - // Algorithm-Specific Fields for ECDH public keys: - // - OID of curve; - // - MPI of EC point representing public key. - // - KDF: variable-length field containing KDF parameters. - case _enums2.default.publicKey.ecdh: - return [_oid2.default, _mpi2.default, _kdf_params2.default]; - default: - throw new Error('Invalid public key encryption algorithm.'); - } - }, - - /** Returns the types comprising the encrypted session key of an algorithm - * @param {String} algo The public key algorithm - * @returns {Array} The array of types - */ - getEncSessionKeyParamTypes: function getEncSessionKeyParamTypes(algo) { - switch (algo) { - // Algorithm-Specific Fields for RSA encrypted session keys: - // - MPI of RSA encrypted value m**e mod n. - case _enums2.default.publicKey.rsa_encrypt: - case _enums2.default.publicKey.rsa_encrypt_sign: - return [_mpi2.default]; - - // Algorithm-Specific Fields for Elgamal encrypted session keys: - // - MPI of Elgamal value g**k mod p - // - MPI of Elgamal value m * y**k mod p - case _enums2.default.publicKey.elgamal: - return [_mpi2.default, _mpi2.default]; - // Algorithm-Specific Fields for ECDH encrypted session keys: - // - MPI containing the ephemeral key used to establish the shared secret - // - ECDH Symmetric Key - case _enums2.default.publicKey.ecdh: - return [_mpi2.default, _ecdh_symkey2.default]; - default: - throw new Error('Invalid public key encryption algorithm.'); - } - }, - - /** Generate algorithm-specific key parameters - * @param {String} algo The public key algorithm - * @param {Integer} bits Bit length for RSA keys - * @param {module:type/oid} oid Object identifier for ECC keys - * @returns {Array} The array of parameters - * @async - */ - generateParams: function generateParams(algo, bits, oid) { - const types = [].concat(this.getPubKeyParamTypes(algo), this.getPrivKeyParamTypes(algo)); - switch (algo) { - case _enums2.default.publicKey.rsa_encrypt: - case _enums2.default.publicKey.rsa_encrypt_sign: - case _enums2.default.publicKey.rsa_sign: - { - return _public_key2.default.rsa.generate(bits, "10001").then(function (keyObject) { - return constructParams(types, [keyObject.n, keyObject.e, keyObject.d, keyObject.p, keyObject.q, keyObject.u]); - }); - } - case _enums2.default.publicKey.dsa: - case _enums2.default.publicKey.elgamal: - throw new Error('Unsupported algorithm for key generation.'); - case _enums2.default.publicKey.ecdsa: - case _enums2.default.publicKey.eddsa: - return _public_key2.default.elliptic.generate(oid).then(function (keyObject) { - return constructParams(types, [keyObject.oid, keyObject.Q, keyObject.d]); - }); - case _enums2.default.publicKey.ecdh: - return _public_key2.default.elliptic.generate(oid).then(function (keyObject) { - return constructParams(types, [keyObject.oid, keyObject.Q, [keyObject.hash, keyObject.cipher], keyObject.d]); - }); - default: - throw new Error('Invalid public key algorithm.'); - } - }, - - /** - * Generates a random byte prefix for the specified algorithm - * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. - * @param {module:enums.symmetric} algo Symmetric encryption algorithm - * @returns {Uint8Array} Random bytes with length equal to the block size of the cipher, plus the last two bytes repeated. - * @async - */ - getPrefixRandom: async function getPrefixRandom(algo) { - const prefixrandom = await _random2.default.getRandomBytes(_cipher2.default[algo].blockSize); - const repeat = new Uint8Array([prefixrandom[prefixrandom.length - 2], prefixrandom[prefixrandom.length - 1]]); - return _util2.default.concat([prefixrandom, repeat]); - }, - - /** - * Generating a session key for the specified symmetric algorithm - * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. - * @param {module:enums.symmetric} algo Symmetric encryption algorithm - * @returns {Uint8Array} Random bytes as a string to be used as a key - * @async - */ - generateSessionKey: function generateSessionKey(algo) { - return _random2.default.getRandomBytes(_cipher2.default[algo].keySize); - }, - - constructParams: constructParams -}; - -},{"../enums":113,"../type/ecdh_symkey":146,"../type/kdf_params":147,"../type/mpi":149,"../type/oid":150,"../util":152,"./cipher":86,"./public_key":106,"./random":109,"bn.js":16}],90:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); // OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2018 ProtonTech AG -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @fileoverview This module implements AES-EAX en/decryption on top of - * native AES-CTR using either the WebCrypto API or Node.js' crypto API. - * @requires asmcrypto.js - * @requires crypto/cmac - * @requires util - * @module crypto/eax - */ - -var _ctr = require('asmcrypto.js/dist_es5/aes/ctr'); - -var _cmac = require('./cmac'); - -var _cmac2 = _interopRequireDefault(_cmac); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const webCrypto = _util2.default.getWebCrypto(); -const nodeCrypto = _util2.default.getNodeCrypto(); -const Buffer = _util2.default.getNodeBuffer(); - -const blockLength = 16; -const ivLength = blockLength; -const tagLength = blockLength; - -const zero = new Uint8Array(blockLength); -const one = new Uint8Array(blockLength);one[blockLength - 1] = 1; -const two = new Uint8Array(blockLength);two[blockLength - 1] = 2; - -async function OMAC(key) { - const cmac = await (0, _cmac2.default)(key); - return function (t, message) { - return cmac(_util2.default.concatUint8Array([t, message])); - }; -} - -async function CTR(key) { - if (_util2.default.getWebCrypto() && key.length !== 24 && // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support - navigator.userAgent.indexOf('Edge') === -1) { - key = await webCrypto.importKey('raw', key, { name: 'AES-CTR', length: key.length * 8 }, false, ['encrypt']); - return async function (pt, iv) { - const ct = await webCrypto.encrypt({ name: 'AES-CTR', counter: iv, length: blockLength * 8 }, key, pt); - return new Uint8Array(ct); - }; - } - if (_util2.default.getNodeCrypto()) { - // Node crypto library - key = new Buffer(key); - return async function (pt, iv) { - pt = new Buffer(pt); - iv = new Buffer(iv); - const en = new nodeCrypto.createCipheriv('aes-' + key.length * 8 + '-ctr', key, iv); - const ct = Buffer.concat([en.update(pt), en.final()]); - return new Uint8Array(ct); - }; - } - // asm.js fallback - return async function (pt, iv) { - return _ctr.AES_CTR.encrypt(pt, key, iv); - }; -} - -/** - * Class to en/decrypt using EAX mode. - * @param {String} cipher The symmetric cipher algorithm to use e.g. 'aes128' - * @param {Uint8Array} key The encryption key - */ -async function EAX(cipher, key) { - if (cipher.substr(0, 3) !== 'aes') { - throw new Error('EAX mode supports only AES cipher'); - } - - var _ref = await Promise.all([OMAC(key), CTR(key)]), - _ref2 = _slicedToArray(_ref, 2); - - const omac = _ref2[0], - ctr = _ref2[1]; - - - return { - /** - * Encrypt plaintext input. - * @param {Uint8Array} plaintext The cleartext input to be encrypted - * @param {Uint8Array} nonce The nonce (16 bytes) - * @param {Uint8Array} adata Associated data to sign - * @returns {Promise} The ciphertext output - */ - encrypt: async function encrypt(plaintext, nonce, adata) { - var _ref3 = await Promise.all([omac(zero, nonce), omac(one, adata)]), - _ref4 = _slicedToArray(_ref3, 2); - - const omacNonce = _ref4[0], - omacAdata = _ref4[1]; - - const ciphered = await ctr(plaintext, omacNonce); - const omacCiphered = await omac(two, ciphered); - const tag = omacCiphered; // Assumes that omac(*).length === tagLength. - for (let i = 0; i < tagLength; i++) { - tag[i] ^= omacAdata[i] ^ omacNonce[i]; - } - return _util2.default.concatUint8Array([ciphered, tag]); - }, - - /** - * Decrypt ciphertext input. - * @param {Uint8Array} ciphertext The ciphertext input to be decrypted - * @param {Uint8Array} nonce The nonce (16 bytes) - * @param {Uint8Array} adata Associated data to verify - * @returns {Promise} The plaintext output - */ - decrypt: async function decrypt(ciphertext, nonce, adata) { - if (ciphertext.length < tagLength) throw new Error('Invalid EAX ciphertext'); - const ciphered = ciphertext.subarray(0, -tagLength); - const ctTag = ciphertext.subarray(-tagLength); - - var _ref5 = await Promise.all([omac(zero, nonce), omac(one, adata), omac(two, ciphered)]), - _ref6 = _slicedToArray(_ref5, 3); - - const omacNonce = _ref6[0], - omacAdata = _ref6[1], - omacCiphered = _ref6[2]; - - const tag = omacCiphered; // Assumes that omac(*).length === tagLength. - for (let i = 0; i < tagLength; i++) { - tag[i] ^= omacAdata[i] ^ omacNonce[i]; - } - if (!_util2.default.equalsUint8Array(ctTag, tag)) throw new Error('Authentication tag mismatch'); - const plaintext = await ctr(ciphered, omacNonce); - return plaintext; - } - }; -} - -/** - * Get EAX nonce as defined by {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.1|RFC4880bis-04, section 5.16.1}. - * @param {Uint8Array} iv The initialization vector (16 bytes) - * @param {Uint8Array} chunkIndex The chunk index (8 bytes) - */ -EAX.getNonce = function (iv, chunkIndex) { - const nonce = iv.slice(); - for (let i = 0; i < chunkIndex.length; i++) { - nonce[8 + i] ^= chunkIndex[i]; - } - return nonce; -}; - -EAX.blockLength = blockLength; -EAX.ivLength = ivLength; -EAX.tagLength = tagLength; - -exports.default = EAX; - -},{"../util":152,"./cmac":88,"asmcrypto.js/dist_es5/aes/ctr":6}],91:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _gcm = require('asmcrypto.js/dist_es5/aes/gcm'); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2016 Tankred Hase -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @fileoverview This module wraps native AES-GCM en/decryption for both - * the WebCrypto api as well as node.js' crypto api. - * @requires asmcrypto.js - * @requires util - * @module crypto/gcm - */ - -const webCrypto = _util2.default.getWebCrypto(); // no GCM support in IE11, Safari 9 -const nodeCrypto = _util2.default.getNodeCrypto(); -const Buffer = _util2.default.getNodeBuffer(); - -const blockLength = 16; -const ivLength = 12; // size of the IV in bytes -const tagLength = 16; // size of the tag in bytes -const ALGO = 'AES-GCM'; - -/** - * Class to en/decrypt using GCM mode. - * @param {String} cipher The symmetric cipher algorithm to use e.g. 'aes128' - * @param {Uint8Array} key The encryption key - */ -async function GCM(cipher, key) { - if (cipher.substr(0, 3) !== 'aes') { - throw new Error('GCM mode supports only AES cipher'); - } - - if (_util2.default.getWebCrypto() && key.length !== 24) { - // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support - const _key = await webCrypto.importKey('raw', key, { name: ALGO }, false, ['encrypt', 'decrypt']); - - return { - encrypt: async function encrypt(pt, iv, adata = new Uint8Array()) { - if (!pt.length || - // iOS does not support GCM-en/decrypting empty messages - // Also, synchronous en/decryption might be faster in this case. - !adata.length && navigator.userAgent.indexOf('Edge') !== -1 - // Edge does not support GCM-en/decrypting without ADATA - ) { - return _gcm.AES_GCM.encrypt(pt, key, iv, adata); - } - const ct = await webCrypto.encrypt({ name: ALGO, iv, additionalData: adata, tagLength: tagLength * 8 }, _key, pt); - return new Uint8Array(ct); - }, - - decrypt: async function decrypt(ct, iv, adata = new Uint8Array()) { - if (ct.length === tagLength || - // iOS does not support GCM-en/decrypting empty messages - // Also, synchronous en/decryption might be faster in this case. - !adata.length && navigator.userAgent.indexOf('Edge') !== -1 - // Edge does not support GCM-en/decrypting without ADATA - ) { - return _gcm.AES_GCM.decrypt(ct, key, iv, adata); - } - const pt = await webCrypto.decrypt({ name: ALGO, iv, additionalData: adata, tagLength: tagLength * 8 }, _key, ct); - return new Uint8Array(pt); - } - }; - } - - if (_util2.default.getNodeCrypto()) { - // Node crypto library - key = new Buffer(key); - - return { - encrypt: async function encrypt(pt, iv, adata = new Uint8Array()) { - pt = new Buffer(pt); - iv = new Buffer(iv); - adata = new Buffer(adata); - const en = new nodeCrypto.createCipheriv('aes-' + key.length * 8 + '-gcm', key, iv); - en.setAAD(adata); - const ct = Buffer.concat([en.update(pt), en.final(), en.getAuthTag()]); // append auth tag to ciphertext - return new Uint8Array(ct); - }, - - decrypt: async function decrypt(ct, iv, adata = new Uint8Array()) { - ct = new Buffer(ct); - iv = new Buffer(iv); - adata = new Buffer(adata); - const de = new nodeCrypto.createDecipheriv('aes-' + key.length * 8 + '-gcm', key, iv); - de.setAAD(adata); - de.setAuthTag(ct.slice(ct.length - tagLength, ct.length)); // read auth tag at end of ciphertext - const pt = Buffer.concat([de.update(ct.slice(0, ct.length - tagLength)), de.final()]); - return new Uint8Array(pt); - } - }; - } - - return { - encrypt: async function encrypt(pt, iv, adata) { - return _gcm.AES_GCM.encrypt(pt, key, iv, adata); - }, - - decrypt: async function decrypt(ct, iv, adata) { - return _gcm.AES_GCM.decrypt(ct, key, iv, adata); - } - }; -} - -/** - * Get GCM nonce. Note: this operation is not defined by the standard. - * A future version of the standard may define GCM mode differently, - * hopefully under a different ID (we use Private/Experimental algorithm - * ID 100) so that we can maintain backwards compatibility. - * @param {Uint8Array} iv The initialization vector (12 bytes) - * @param {Uint8Array} chunkIndex The chunk index (8 bytes) - */ -GCM.getNonce = function (iv, chunkIndex) { - const nonce = iv.slice(); - for (let i = 0; i < chunkIndex.length; i++) { - nonce[4 + i] ^= chunkIndex[i]; - } - return nonce; -}; - -GCM.blockLength = blockLength; -GCM.ivLength = ivLength; -GCM.tagLength = tagLength; - -exports.default = GCM; - -},{"../util":152,"asmcrypto.js/dist_es5/aes/gcm":8}],92:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _sha = require('asmcrypto.js/dist_es5/hash/sha1/sha1'); - -var _sha2 = require('asmcrypto.js/dist_es5/hash/sha256/sha256'); - -var _ = require('hash.js/lib/hash/sha/224'); - -var _2 = _interopRequireDefault(_); - -var _3 = require('hash.js/lib/hash/sha/384'); - -var _4 = _interopRequireDefault(_3); - -var _5 = require('hash.js/lib/hash/sha/512'); - -var _6 = _interopRequireDefault(_5); - -var _ripemd = require('hash.js/lib/hash/ripemd'); - -var _webStreamTools = require('web-stream-tools'); - -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); - -var _md = require('./md5'); - -var _md2 = _interopRequireDefault(_md); - -var _config = require('../../config'); - -var _config2 = _interopRequireDefault(_config); - -var _util = require('../../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * @fileoverview Provides an interface to hashing functions available in Node.js or external libraries. - * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} - * @see {@link https://github.com/indutny/hash.js|hash.js} - * @requires asmcrypto.js - * @requires hash.js - * @requires web-stream-tools - * @requires crypto/hash/md5 - * @requires config - * @requires util - * @module crypto/hash - */ - -const webCrypto = _util2.default.getWebCrypto(); -const nodeCrypto = _util2.default.getNodeCrypto(); -const Buffer = _util2.default.getNodeBuffer(); - -function node_hash(type) { - return async function (data) { - const shasum = nodeCrypto.createHash(type); - return _webStreamTools2.default.transform(data, value => { - shasum.update(new Buffer(value)); - }, () => new Uint8Array(shasum.digest())); - }; -} - -function hashjs_hash(hash, webCryptoHash) { - return async function (data) { - if (!_util2.default.isStream(data) && webCrypto && webCryptoHash && data.length >= _config2.default.min_bytes_for_web_crypto) { - return new Uint8Array((await webCrypto.digest(webCryptoHash, data))); - } - const hashInstance = hash(); - return _webStreamTools2.default.transform(data, value => { - hashInstance.update(value); - }, () => new Uint8Array(hashInstance.digest())); - }; -} - -function asmcrypto_hash(hash, webCryptoHash) { - return async function (data) { - if (_util2.default.isStream(data)) { - const hashInstance = new hash(); - return _webStreamTools2.default.transform(data, value => { - hashInstance.process(value); - }, () => hashInstance.finish().result); - } else if (webCrypto && webCryptoHash && data.length >= _config2.default.min_bytes_for_web_crypto) { - return new Uint8Array((await webCrypto.digest(webCryptoHash, data))); - } else { - return hash.bytes(data); - } - }; -} - -let hash_fns; -if (nodeCrypto) { - // Use Node native crypto for all hash functions - hash_fns = { - md5: node_hash('md5'), - sha1: node_hash('sha1'), - sha224: node_hash('sha224'), - sha256: node_hash('sha256'), - sha384: node_hash('sha384'), - sha512: node_hash('sha512'), - ripemd: node_hash('ripemd160') - }; -} else { - // Use JS fallbacks - hash_fns = { - md5: _md2.default, - sha1: asmcrypto_hash(_sha.Sha1, navigator.userAgent.indexOf('Edge') === -1 && 'SHA-1'), - sha224: hashjs_hash(_2.default), - sha256: asmcrypto_hash(_sha2.Sha256, 'SHA-256'), - sha384: hashjs_hash(_4.default, 'SHA-384'), - sha512: hashjs_hash(_6.default, 'SHA-512'), // asmcrypto sha512 is huge. - ripemd: hashjs_hash(_ripemd.ripemd160) - }; -} - -exports.default = { - - /** @see module:md5 */ - md5: hash_fns.md5, - /** @see asmCrypto */ - sha1: hash_fns.sha1, - /** @see hash.js */ - sha224: hash_fns.sha224, - /** @see asmCrypto */ - sha256: hash_fns.sha256, - /** @see hash.js */ - sha384: hash_fns.sha384, - /** @see asmCrypto */ - sha512: hash_fns.sha512, - /** @see hash.js */ - ripemd: hash_fns.ripemd, - - /** - * Create a hash on the specified data using the specified algorithm - * @param {module:enums.hash} algo Hash algorithm type (see {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}) - * @param {Uint8Array} data Data to be hashed - * @returns {Promise} hash value - */ - digest: function digest(algo, data) { - switch (algo) { - case 1: - // - MD5 [HAC] - return this.md5(data); - case 2: - // - SHA-1 [FIPS180] - return this.sha1(data); - case 3: - // - RIPE-MD/160 [HAC] - return this.ripemd(data); - case 8: - // - SHA256 [FIPS180] - return this.sha256(data); - case 9: - // - SHA384 [FIPS180] - return this.sha384(data); - case 10: - // - SHA512 [FIPS180] - return this.sha512(data); - case 11: - // - SHA224 [FIPS180] - return this.sha224(data); - default: - throw new Error('Invalid hash function.'); - } - }, - - /** - * Returns the hash size in bytes of the specified hash algorithm type - * @param {module:enums.hash} algo Hash algorithm type (See {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}) - * @returns {Integer} Size in bytes of the resulting hash - */ - getHashByteLength: function getHashByteLength(algo) { - switch (algo) { - case 1: - // - MD5 [HAC] - return 16; - case 2: // - SHA-1 [FIPS180] - case 3: - // - RIPE-MD/160 [HAC] - return 20; - case 8: - // - SHA256 [FIPS180] - return 32; - case 9: - // - SHA384 [FIPS180] - return 48; - case 10: - // - SHA512 [FIPS180] - return 64; - case 11: - // - SHA224 [FIPS180] - return 28; - default: - throw new Error('Invalid hash algorithm.'); - } - } -}; - -},{"../../config":79,"../../util":152,"./md5":93,"asmcrypto.js/dist_es5/hash/sha1/sha1":11,"asmcrypto.js/dist_es5/hash/sha256/sha256":13,"hash.js/lib/hash/ripemd":37,"hash.js/lib/hash/sha/224":40,"hash.js/lib/hash/sha/384":42,"hash.js/lib/hash/sha/512":43,"web-stream-tools":75}],93:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _util = require('../../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -// MD5 Digest -async function md5(entree) { - const digest = md51(_util2.default.Uint8Array_to_str(entree)); - return _util2.default.hex_to_Uint8Array(hex(digest)); -} /** - * A fast MD5 JavaScript implementation - * Copyright (c) 2012 Joseph Myers - * http://www.myersdaily.org/joseph/javascript/md5-text.html - * - * Permission to use, copy, modify, and distribute this software - * and its documentation for any purposes and without - * fee is hereby granted provided that this copyright notice - * appears in all copies. - * - * Of course, this soft is provided "as is" without express or implied - * warranty of any kind. - */ - -/** - * @requires util - */ - -function md5cycle(x, k) { - let a = x[0]; - let b = x[1]; - let c = x[2]; - let d = x[3]; - - a = ff(a, b, c, d, k[0], 7, -680876936); - d = ff(d, a, b, c, k[1], 12, -389564586); - c = ff(c, d, a, b, k[2], 17, 606105819); - b = ff(b, c, d, a, k[3], 22, -1044525330); - a = ff(a, b, c, d, k[4], 7, -176418897); - d = ff(d, a, b, c, k[5], 12, 1200080426); - c = ff(c, d, a, b, k[6], 17, -1473231341); - b = ff(b, c, d, a, k[7], 22, -45705983); - a = ff(a, b, c, d, k[8], 7, 1770035416); - d = ff(d, a, b, c, k[9], 12, -1958414417); - c = ff(c, d, a, b, k[10], 17, -42063); - b = ff(b, c, d, a, k[11], 22, -1990404162); - a = ff(a, b, c, d, k[12], 7, 1804603682); - d = ff(d, a, b, c, k[13], 12, -40341101); - c = ff(c, d, a, b, k[14], 17, -1502002290); - b = ff(b, c, d, a, k[15], 22, 1236535329); - - a = gg(a, b, c, d, k[1], 5, -165796510); - d = gg(d, a, b, c, k[6], 9, -1069501632); - c = gg(c, d, a, b, k[11], 14, 643717713); - b = gg(b, c, d, a, k[0], 20, -373897302); - a = gg(a, b, c, d, k[5], 5, -701558691); - d = gg(d, a, b, c, k[10], 9, 38016083); - c = gg(c, d, a, b, k[15], 14, -660478335); - b = gg(b, c, d, a, k[4], 20, -405537848); - a = gg(a, b, c, d, k[9], 5, 568446438); - d = gg(d, a, b, c, k[14], 9, -1019803690); - c = gg(c, d, a, b, k[3], 14, -187363961); - b = gg(b, c, d, a, k[8], 20, 1163531501); - a = gg(a, b, c, d, k[13], 5, -1444681467); - d = gg(d, a, b, c, k[2], 9, -51403784); - c = gg(c, d, a, b, k[7], 14, 1735328473); - b = gg(b, c, d, a, k[12], 20, -1926607734); - - a = hh(a, b, c, d, k[5], 4, -378558); - d = hh(d, a, b, c, k[8], 11, -2022574463); - c = hh(c, d, a, b, k[11], 16, 1839030562); - b = hh(b, c, d, a, k[14], 23, -35309556); - a = hh(a, b, c, d, k[1], 4, -1530992060); - d = hh(d, a, b, c, k[4], 11, 1272893353); - c = hh(c, d, a, b, k[7], 16, -155497632); - b = hh(b, c, d, a, k[10], 23, -1094730640); - a = hh(a, b, c, d, k[13], 4, 681279174); - d = hh(d, a, b, c, k[0], 11, -358537222); - c = hh(c, d, a, b, k[3], 16, -722521979); - b = hh(b, c, d, a, k[6], 23, 76029189); - a = hh(a, b, c, d, k[9], 4, -640364487); - d = hh(d, a, b, c, k[12], 11, -421815835); - c = hh(c, d, a, b, k[15], 16, 530742520); - b = hh(b, c, d, a, k[2], 23, -995338651); - - a = ii(a, b, c, d, k[0], 6, -198630844); - d = ii(d, a, b, c, k[7], 10, 1126891415); - c = ii(c, d, a, b, k[14], 15, -1416354905); - b = ii(b, c, d, a, k[5], 21, -57434055); - a = ii(a, b, c, d, k[12], 6, 1700485571); - d = ii(d, a, b, c, k[3], 10, -1894986606); - c = ii(c, d, a, b, k[10], 15, -1051523); - b = ii(b, c, d, a, k[1], 21, -2054922799); - a = ii(a, b, c, d, k[8], 6, 1873313359); - d = ii(d, a, b, c, k[15], 10, -30611744); - c = ii(c, d, a, b, k[6], 15, -1560198380); - b = ii(b, c, d, a, k[13], 21, 1309151649); - a = ii(a, b, c, d, k[4], 6, -145523070); - d = ii(d, a, b, c, k[11], 10, -1120210379); - c = ii(c, d, a, b, k[2], 15, 718787259); - b = ii(b, c, d, a, k[9], 21, -343485551); - - x[0] = add32(a, x[0]); - x[1] = add32(b, x[1]); - x[2] = add32(c, x[2]); - x[3] = add32(d, x[3]); -} - -function cmn(q, a, b, x, s, t) { - a = add32(add32(a, q), add32(x, t)); - return add32(a << s | a >>> 32 - s, b); -} - -function ff(a, b, c, d, x, s, t) { - return cmn(b & c | ~b & d, a, b, x, s, t); -} - -function gg(a, b, c, d, x, s, t) { - return cmn(b & d | c & ~d, a, b, x, s, t); -} - -function hh(a, b, c, d, x, s, t) { - return cmn(b ^ c ^ d, a, b, x, s, t); -} - -function ii(a, b, c, d, x, s, t) { - return cmn(c ^ (b | ~d), a, b, x, s, t); -} - -function md51(s) { - const n = s.length; - const state = [1732584193, -271733879, -1732584194, 271733878]; - let i; - for (i = 64; i <= s.length; i += 64) { - md5cycle(state, md5blk(s.substring(i - 64, i))); - } - s = s.substring(i - 64); - const tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; - for (i = 0; i < s.length; i++) { - tail[i >> 2] |= s.charCodeAt(i) << (i % 4 << 3); - } - tail[i >> 2] |= 0x80 << (i % 4 << 3); - if (i > 55) { - md5cycle(state, tail); - for (i = 0; i < 16; i++) { - tail[i] = 0; - } - } - tail[14] = n * 8; - md5cycle(state, tail); - return state; -} - -/* there needs to be support for Unicode here, - * unless we pretend that we can redefine the MD-5 - * algorithm for multi-byte characters (perhaps - * by adding every four 16-bit characters and - * shortening the sum to 32 bits). Otherwise - * I suggest performing MD-5 as if every character - * was two bytes--e.g., 0040 0025 = @%--but then - * how will an ordinary MD-5 sum be matched? - * There is no way to standardize text to something - * like UTF-8 before transformation; speed cost is - * utterly prohibitive. The JavaScript standard - * itself needs to look at this: it should start - * providing access to strings as preformed UTF-8 - * 8-bit unsigned value arrays. - */ -function md5blk(s) { - /* I figured global was faster. */ - const md5blks = []; - let i; /* Andy King said do it this way. */ - for (i = 0; i < 64; i += 4) { - md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24); - } - return md5blks; -} - -const hex_chr = '0123456789abcdef'.split(''); - -function rhex(n) { - let s = ''; - let j = 0; - for (; j < 4; j++) { - s += hex_chr[n >> j * 8 + 4 & 0x0F] + hex_chr[n >> j * 8 & 0x0F]; - } - return s; -} - -function hex(x) { - for (let i = 0; i < x.length; i++) { - x[i] = rhex(x[i]); - } - return x.join(''); -} - -/* this function is much faster, -so if possible we use it. Some IEs -are the only ones I know of that -need the idiotic second function, -generated by an if clause. */ - -function add32(a, b) { - return a + b & 0xFFFFFFFF; -} - -exports.default = md5; - -},{"../../util":152}],94:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _cipher = require('./cipher'); - -var _cipher2 = _interopRequireDefault(_cipher); - -var _hash = require('./hash'); - -var _hash2 = _interopRequireDefault(_hash); - -var _cfb = require('./cfb'); - -var _cfb2 = _interopRequireDefault(_cfb); - -var _gcm = require('./gcm'); - -var _gcm2 = _interopRequireDefault(_gcm); - -var _eax = require('./eax'); - -var _eax2 = _interopRequireDefault(_eax); - -var _ocb = require('./ocb'); - -var _ocb2 = _interopRequireDefault(_ocb); - -var _public_key = require('./public_key'); - -var _public_key2 = _interopRequireDefault(_public_key); - -var _signature = require('./signature'); - -var _signature2 = _interopRequireDefault(_signature); - -var _random = require('./random'); - -var _random2 = _interopRequireDefault(_random); - -var _pkcs = require('./pkcs1'); - -var _pkcs2 = _interopRequireDefault(_pkcs); - -var _pkcs3 = require('./pkcs5'); - -var _pkcs4 = _interopRequireDefault(_pkcs3); - -var _crypto = require('./crypto'); - -var _crypto2 = _interopRequireDefault(_crypto); - -var _aes_kw = require('./aes_kw'); - -var _aes_kw2 = _interopRequireDefault(_aes_kw); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -// TODO move cfb and gcm to cipher -const mod = { - /** @see module:crypto/cipher */ - cipher: _cipher2.default, - /** @see module:crypto/hash */ - hash: _hash2.default, - /** @see module:crypto/cfb */ - cfb: _cfb2.default, - /** @see module:crypto/gcm */ - gcm: _gcm2.default, - experimental_gcm: _gcm2.default, - /** @see module:crypto/eax */ - eax: _eax2.default, - /** @see module:crypto/ocb */ - ocb: _ocb2.default, - /** @see module:crypto/public_key */ - publicKey: _public_key2.default, - /** @see module:crypto/signature */ - signature: _signature2.default, - /** @see module:crypto/random */ - random: _random2.default, - /** @see module:crypto/pkcs1 */ - pkcs1: _pkcs2.default, - /** @see module:crypto/pkcs5 */ - pkcs5: _pkcs4.default, - /** @see module:crypto/aes_kw */ - aes_kw: _aes_kw2.default -}; /** - * @fileoverview Provides access to all cryptographic primitives used in OpenPGP.js - * @see module:crypto/crypto - * @see module:crypto/signature - * @see module:crypto/public_key - * @see module:crypto/cipher - * @see module:crypto/random - * @see module:crypto/hash - * @module crypto - */ - -Object.assign(mod, _crypto2.default); - -exports.default = mod; - -},{"./aes_kw":80,"./cfb":81,"./cipher":86,"./crypto":89,"./eax":90,"./gcm":91,"./hash":92,"./ocb":95,"./pkcs1":96,"./pkcs5":97,"./public_key":106,"./random":109,"./signature":110}],95:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _cipher = require('./cipher'); - -var _cipher2 = _interopRequireDefault(_cipher); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2018 ProtonTech AG -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @fileoverview This module implements AES-OCB en/decryption. - * @requires crypto/cipher - * @requires util - * @module crypto/ocb - */ - -const blockLength = 16; -const ivLength = 15; - -// https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.2: -// While OCB [RFC7253] allows the authentication tag length to be of any -// number up to 128 bits long, this document requires a fixed -// authentication tag length of 128 bits (16 octets) for simplicity. -const tagLength = 16; - -function ntz(n) { - let ntz = 0; - for (let i = 1; (n & i) === 0; i <<= 1) { - ntz++; - } - return ntz; -} - -function xorMut(S, T) { - for (let i = 0; i < S.length; i++) { - S[i] ^= T[i]; - } - return S; -} - -function xor(S, T) { - return xorMut(S.slice(), T); -} - -const zeroBlock = new Uint8Array(blockLength); -const one = new Uint8Array([1]); - -/** - * Class to en/decrypt using OCB mode. - * @param {String} cipher The symmetric cipher algorithm to use e.g. 'aes128' - * @param {Uint8Array} key The encryption key - */ -async function OCB(cipher, key) { - - let maxNtz = 0; - let encipher; - let decipher; - let mask; - - constructKeyVariables(cipher, key); - - function constructKeyVariables(cipher, key) { - const aes = new _cipher2.default[cipher](key); - encipher = aes.encrypt.bind(aes); - decipher = aes.decrypt.bind(aes); - - const mask_x = encipher(zeroBlock); - const mask_$ = _util2.default.double(mask_x); - mask = []; - mask[0] = _util2.default.double(mask_$); - - mask.x = mask_x; - mask.$ = mask_$; - } - - function extendKeyVariables(text, adata) { - const newMaxNtz = _util2.default.nbits(Math.max(text.length, adata.length) / blockLength | 0) - 1; - for (let i = maxNtz + 1; i <= newMaxNtz; i++) { - mask[i] = _util2.default.double(mask[i - 1]); - } - maxNtz = newMaxNtz; - } - - function hash(adata) { - if (!adata.length) { - // Fast path - return zeroBlock; - } - - // - // Consider A as a sequence of 128-bit blocks - // - const m = adata.length / blockLength | 0; - - const offset = new Uint8Array(blockLength); - const sum = new Uint8Array(blockLength); - for (let i = 0; i < m; i++) { - xorMut(offset, mask[ntz(i + 1)]); - xorMut(sum, encipher(xor(offset, adata))); - adata = adata.subarray(blockLength); - } - - // - // Process any final partial block; compute final hash value - // - if (adata.length) { - xorMut(offset, mask.x); - - const cipherInput = new Uint8Array(blockLength); - cipherInput.set(adata, 0); - cipherInput[adata.length] = 0b10000000; - xorMut(cipherInput, offset); - - xorMut(sum, encipher(cipherInput)); - } - - return sum; - } - - /** - * Encrypt/decrypt data. - * @param {encipher|decipher} fn Encryption/decryption block cipher function - * @param {Uint8Array} text The cleartext or ciphertext (without tag) input - * @param {Uint8Array} nonce The nonce (15 bytes) - * @param {Uint8Array} adata Associated data to sign - * @returns {Promise} The ciphertext or plaintext output, with tag appended in both cases - */ - function crypt(fn, text, nonce, adata) { - // - // Consider P as a sequence of 128-bit blocks - // - const m = text.length / blockLength | 0; - - // - // Key-dependent variables - // - extendKeyVariables(text, adata); - - // - // Nonce-dependent and per-encryption variables - // - // Nonce = num2str(TAGLEN mod 128,7) || zeros(120-bitlen(N)) || 1 || N - // Note: We assume here that tagLength mod 16 == 0. - const paddedNonce = _util2.default.concatUint8Array([zeroBlock.subarray(0, ivLength - nonce.length), one, nonce]); - // bottom = str2num(Nonce[123..128]) - const bottom = paddedNonce[blockLength - 1] & 0b111111; - // Ktop = ENCIPHER(K, Nonce[1..122] || zeros(6)) - paddedNonce[blockLength - 1] &= 0b11000000; - const kTop = encipher(paddedNonce); - // Stretch = Ktop || (Ktop[1..64] xor Ktop[9..72]) - const stretched = _util2.default.concatUint8Array([kTop, xor(kTop.subarray(0, 8), kTop.subarray(1, 9))]); - // Offset_0 = Stretch[1+bottom..128+bottom] - const offset = _util2.default.shiftRight(stretched.subarray(0 + (bottom >> 3), 17 + (bottom >> 3)), 8 - (bottom & 7)).subarray(1); - // Checksum_0 = zeros(128) - const checksum = new Uint8Array(blockLength); - - const ct = new Uint8Array(text.length + tagLength); - - // - // Process any whole blocks - // - let i; - let pos = 0; - for (i = 0; i < m; i++) { - // Offset_i = Offset_{i-1} xor L_{ntz(i)} - xorMut(offset, mask[ntz(i + 1)]); - // C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) - // P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i) - ct.set(xorMut(fn(xor(offset, text)), offset), pos); - // Checksum_i = Checksum_{i-1} xor P_i - xorMut(checksum, fn === encipher ? text : ct.subarray(pos)); - - text = text.subarray(blockLength); - pos += blockLength; - } - - // - // Process any final partial block and compute raw tag - // - if (text.length) { - // Offset_* = Offset_m xor L_* - xorMut(offset, mask.x); - // Pad = ENCIPHER(K, Offset_*) - const padding = encipher(offset); - // C_* = P_* xor Pad[1..bitlen(P_*)] - ct.set(xor(text, padding), pos); - - // Checksum_* = Checksum_m xor (P_* || 1 || new Uint8Array(127-bitlen(P_*))) - const xorInput = new Uint8Array(blockLength); - xorInput.set(fn === encipher ? text : ct.subarray(pos, -tagLength), 0); - xorInput[text.length] = 0b10000000; - xorMut(checksum, xorInput); - pos += text.length; - } - // Tag = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) xor HASH(K,A) - const tag = xorMut(encipher(xorMut(xorMut(checksum, offset), mask.$)), hash(adata)); - - // - // Assemble ciphertext - // - // C = C_1 || C_2 || ... || C_m || C_* || Tag[1..TAGLEN] - ct.set(tag, pos); - return ct; - } - - return { - /** - * Encrypt plaintext input. - * @param {Uint8Array} plaintext The cleartext input to be encrypted - * @param {Uint8Array} nonce The nonce (15 bytes) - * @param {Uint8Array} adata Associated data to sign - * @returns {Promise} The ciphertext output - */ - encrypt: async function encrypt(plaintext, nonce, adata) { - return crypt(encipher, plaintext, nonce, adata); - }, - - /** - * Decrypt ciphertext input. - * @param {Uint8Array} ciphertext The ciphertext input to be decrypted - * @param {Uint8Array} nonce The nonce (15 bytes) - * @param {Uint8Array} adata Associated data to sign - * @returns {Promise} The ciphertext output - */ - decrypt: async function decrypt(ciphertext, nonce, adata) { - if (ciphertext.length < tagLength) throw new Error('Invalid OCB ciphertext'); - - const tag = ciphertext.subarray(-tagLength); - ciphertext = ciphertext.subarray(0, -tagLength); - - const crypted = crypt(decipher, ciphertext, nonce, adata); - // if (Tag[1..TAGLEN] == T) - if (_util2.default.equalsUint8Array(tag, crypted.subarray(-tagLength))) { - return crypted.subarray(0, -tagLength); - } - throw new Error('Authentication tag mismatch'); - } - }; -} - -/** - * Get OCB nonce as defined by {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.2|RFC4880bis-04, section 5.16.2}. - * @param {Uint8Array} iv The initialization vector (15 bytes) - * @param {Uint8Array} chunkIndex The chunk index (8 bytes) - */ -OCB.getNonce = function (iv, chunkIndex) { - const nonce = iv.slice(); - for (let i = 0; i < chunkIndex.length; i++) { - nonce[7 + i] ^= chunkIndex[i]; - } - return nonce; -}; - -OCB.blockLength = blockLength; -OCB.ivLength = ivLength; -OCB.tagLength = tagLength; - -exports.default = OCB; - -},{"../util":152,"./cipher":86}],96:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _random = require('./random'); - -var _random2 = _interopRequireDefault(_random); - -var _hash = require('./hash'); - -var _hash2 = _interopRequireDefault(_hash); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** @namespace */ -const eme = {}; -/** @namespace */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @fileoverview Provides EME-PKCS1-v1_5 encoding and decoding and EMSA-PKCS1-v1_5 encoding function - * @see module:crypto/public_key/rsa - * @see module:crypto/public_key/elliptic/ecdh - * @see module:packet.PublicKeyEncryptedSessionKey - * @requires crypto/random - * @requires crypto/hash - * @requires util - * @module crypto/pkcs1 - */ - -const emsa = {}; - -/** - * ASN1 object identifiers for hashes - * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.2} - */ -const hash_headers = []; -hash_headers[1] = [0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10]; -hash_headers[2] = [0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14]; -hash_headers[3] = [0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14]; -hash_headers[8] = [0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20]; -hash_headers[9] = [0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30]; -hash_headers[10] = [0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40]; -hash_headers[11] = [0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1C]; - -/** - * Create padding with secure random data - * @private - * @param {Integer} length Length of the padding in bytes - * @returns {String} Padding as string - * @async - */ -async function getPkcs1Padding(length) { - let result = ''; - while (result.length < length) { - const randomBytes = await _random2.default.getRandomBytes(length - result.length); - for (let i = 0; i < randomBytes.length; i++) { - if (randomBytes[i] !== 0) { - result += String.fromCharCode(randomBytes[i]); - } - } - } - return result; -} - -/** - * Create a EME-PKCS1-v1_5 padded message - * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.1|RFC 4880 13.1.1} - * @param {String} M message to be encoded - * @param {Integer} k the length in octets of the key modulus - * @returns {Promise} EME-PKCS1 padded message - * @async - */ -eme.encode = async function (M, k) { - const mLen = M.length; - // length checking - if (mLen > k - 11) { - throw new Error('Message too long'); - } - // Generate an octet string PS of length k - mLen - 3 consisting of - // pseudo-randomly generated nonzero octets - const PS = await getPkcs1Padding(k - mLen - 3); - // Concatenate PS, the message M, and other padding to form an - // encoded message EM of length k octets as EM = 0x00 || 0x02 || PS || 0x00 || M. - return String.fromCharCode(0) + String.fromCharCode(2) + PS + String.fromCharCode(0) + M; -}; - -/** - * Decode a EME-PKCS1-v1_5 padded message - * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.2|RFC 4880 13.1.2} - * @param {String} EM encoded message, an octet string - * @returns {String} message, an octet string - */ -eme.decode = function (EM) { - // leading zeros truncated by bn.js - if (EM.charCodeAt(0) !== 0) { - EM = String.fromCharCode(0) + EM; - } - const firstOct = EM.charCodeAt(0); - const secondOct = EM.charCodeAt(1); - let i = 2; - while (EM.charCodeAt(i) !== 0 && i < EM.length) { - i++; - } - const psLen = i - 2; - const separator = EM.charCodeAt(i++); - if (firstOct === 0 && secondOct === 2 && psLen >= 8 && separator === 0) { - return EM.substr(i); - } - throw new Error('Decryption error'); -}; - -/** - * Create a EMSA-PKCS1-v1_5 padded message - * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.3|RFC 4880 13.1.3} - * @param {Integer} algo Hash algorithm type used - * @param {Uint8Array} hashed message to be encoded - * @param {Integer} emLen intended length in octets of the encoded message - * @returns {String} encoded message - */ -emsa.encode = async function (algo, hashed, emLen) { - let i; - const H = _util2.default.Uint8Array_to_str(hashed); - if (H.length !== _hash2.default.getHashByteLength(algo)) { - throw new Error('Invalid hash length'); - } - // produce an ASN.1 DER value for the hash function used. - // Let T be the full hash prefix - let T = ''; - for (i = 0; i < hash_headers[algo].length; i++) { - T += String.fromCharCode(hash_headers[algo][i]); - } - // add hash value to prefix - T += H; - // and let tLen be the length in octets of T - const tLen = T.length; - if (emLen < tLen + 11) { - throw new Error('Intended encoded message length too short'); - } - // an octet string PS consisting of emLen - tLen - 3 octets with hexadecimal value 0xFF - // The length of PS will be at least 8 octets - let PS = ''; - for (i = 0; i < emLen - tLen - 3; i++) { - PS += String.fromCharCode(0xff); - } - // Concatenate PS, the hash prefix T, and other padding to form the - // encoded message EM as EM = 0x00 || 0x01 || PS || 0x00 || T. - const EM = String.fromCharCode(0x00) + String.fromCharCode(0x01) + PS + String.fromCharCode(0x00) + T; - return _util2.default.str_to_hex(EM); -}; - -exports.default = { eme, emsa }; - -},{"../util":152,"./hash":92,"./random":109}],97:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2015-2016 Decentral -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @fileoverview Functions to add and remove PKCS5 padding - * @see module:packet.PublicKeyEncryptedSessionKey - * @module crypto/pkcs5 - */ - -/** - * Add pkcs5 padding to a text. - * @param {String} msg Text to add padding - * @returns {String} Text with padding added - */ -function encode(msg) { - const c = 8 - msg.length % 8; - const padding = String.fromCharCode(c).repeat(c); - return msg + padding; -} - -/** - * Remove pkcs5 padding from a string. - * @param {String} msg Text to remove padding from - * @returns {String} Text with padding removed - */ -function decode(msg) { - const len = msg.length; - if (len > 0) { - const c = msg.charCodeAt(len - 1); - if (c >= 1 && c <= 8) { - const provided = msg.substr(len - c); - const computed = String.fromCharCode(c).repeat(c); - if (provided === computed) { - return msg.substr(0, len - c); - } - } - } - throw new Error('Invalid padding'); -} - -exports.default = { encode, decode }; - -},{}],98:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _bn = require('bn.js'); - -var _bn2 = _interopRequireDefault(_bn); - -var _random = require('../random'); - -var _random2 = _interopRequireDefault(_random); - -var _util = require('../../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const one = new _bn2.default(1); // GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @fileoverview A Digital signature algorithm implementation - * @requires bn.js - * @requires crypto/random - * @requires util - * @module crypto/public_key/dsa - */ - -const zero = new _bn2.default(0); - -/* - TODO regarding the hash function, read: - https://tools.ietf.org/html/rfc4880#section-13.6 - https://tools.ietf.org/html/rfc4880#section-14 -*/ - -exports.default = { - /** - * DSA Sign function - * @param {Integer} hash_algo - * @param {Uint8Array} hashed - * @param {BN} g - * @param {BN} p - * @param {BN} q - * @param {BN} x - * @returns {{ r: BN, s: BN }} - * @async - */ - sign: async function sign(hash_algo, hashed, g, p, q, x) { - let k; - let r; - let s; - let t; - const redp = new _bn2.default.red(p); - const redq = new _bn2.default.red(q); - const gred = g.toRed(redp); - const xred = x.toRed(redq); - // If the output size of the chosen hash is larger than the number of - // bits of q, the hash result is truncated to fit by taking the number - // of leftmost bits equal to the number of bits of q. This (possibly - // truncated) hash function result is treated as a number and used - // directly in the DSA signature algorithm. - const h = new _bn2.default(hashed.subarray(0, q.byteLength())).toRed(redq); - // FIPS-186-4, section 4.6: - // The values of r and s shall be checked to determine if r = 0 or s = 0. - // If either r = 0 or s = 0, a new value of k shall be generated, and the - // signature shall be recalculated. It is extremely unlikely that r = 0 - // or s = 0 if signatures are generated properly. - while (true) { - // See Appendix B here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - k = await _random2.default.getRandomBN(one, q); // returns in [1, q-1] - r = gred.redPow(k).fromRed().toRed(redq); // (g**k mod p) mod q - if (zero.cmp(r) === 0) { - continue; - } - t = h.redAdd(xred.redMul(r)); // H(m) + x*r mod q - s = k.toRed(redq).redInvm().redMul(t); // k**-1 * (H(m) + x*r) mod q - if (zero.cmp(s) === 0) { - continue; - } - break; - } - return { - r: r.toArrayLike(Uint8Array, 'be', q.byteLength()), - s: s.toArrayLike(Uint8Array, 'be', q.byteLength()) - }; - }, - - /** - * DSA Verify function - * @param {Integer} hash_algo - * @param {BN} r - * @param {BN} s - * @param {Uint8Array} hashed - * @param {BN} g - * @param {BN} p - * @param {BN} q - * @param {BN} y - * @returns BN - * @async - */ - verify: async function verify(hash_algo, r, s, hashed, g, p, q, y) { - if (zero.ucmp(r) >= 0 || r.ucmp(q) >= 0 || zero.ucmp(s) >= 0 || s.ucmp(q) >= 0) { - _util2.default.print_debug("invalid DSA Signature"); - return null; - } - const redp = new _bn2.default.red(p); - const redq = new _bn2.default.red(q); - const h = new _bn2.default(hashed.subarray(0, q.byteLength())); - const w = s.toRed(redq).redInvm(); // s**-1 mod q - if (zero.cmp(w) === 0) { - _util2.default.print_debug("invalid DSA Signature"); - return null; - } - const u1 = h.toRed(redq).redMul(w); // H(m) * w mod q - const u2 = r.toRed(redq).redMul(w); // r * w mod q - const t1 = g.toRed(redp).redPow(u1.fromRed()); // g**u1 mod p - const t2 = y.toRed(redp).redPow(u2.fromRed()); // y**u2 mod p - const v = t1.redMul(t2).fromRed().mod(q); // (g**u1 * y**u2 mod p) mod q - return v.cmp(r) === 0; - } -}; - -},{"../../util":152,"../random":109,"bn.js":16}],99:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _bn = require('bn.js'); - -var _bn2 = _interopRequireDefault(_bn); - -var _random = require('../random'); - -var _random2 = _interopRequireDefault(_random); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @fileoverview ElGamal implementation - * @requires bn.js - * @requires crypto/random - * @module crypto/public_key/elgamal - */ - -const zero = new _bn2.default(0); - -exports.default = { - /** - * ElGamal Encryption function - * @param {BN} m - * @param {BN} p - * @param {BN} g - * @param {BN} y - * @returns {{ c1: BN, c2: BN }} - * @async - */ - encrypt: async function encrypt(m, p, g, y) { - const redp = new _bn2.default.red(p); - const mred = m.toRed(redp); - const gred = g.toRed(redp); - const yred = y.toRed(redp); - // See Section 11.5 here: https://crypto.stanford.edu/~dabo/cryptobook/BonehShoup_0_4.pdf - const k = await _random2.default.getRandomBN(zero, p); // returns in [0, p-1] - return { - c1: gred.redPow(k).fromRed(), - c2: yred.redPow(k).redMul(mred).fromRed() - }; - }, - - /** - * ElGamal Encryption function - * @param {BN} c1 - * @param {BN} c2 - * @param {BN} p - * @param {BN} x - * @returns BN - * @async - */ - decrypt: async function decrypt(c1, c2, p, x) { - const redp = new _bn2.default.red(p); - const c1red = c1.toRed(redp); - const c2red = c2.toRed(redp); - return c1red.redPow(x).redInvm().redMul(c2red).fromRed(); - } -}; - -},{"../random":109,"bn.js":16}],100:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getPreferredHashAlgo = exports.generate = exports.nodeCurves = exports.webCurves = exports.curves = undefined; - -var _bn = require('bn.js'); - -var _bn2 = _interopRequireDefault(_bn); - -var _elliptic = require('elliptic'); - -var _key = require('./key'); - -var _key2 = _interopRequireDefault(_key); - -var _random = require('../../random'); - -var _random2 = _interopRequireDefault(_random); - -var _enums = require('../../../enums'); - -var _enums2 = _interopRequireDefault(_enums); - -var _util = require('../../../util'); - -var _util2 = _interopRequireDefault(_util); - -var _oid = require('../../../type/oid'); - -var _oid2 = _interopRequireDefault(_oid); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const webCrypto = _util2.default.getWebCrypto(); // OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2015-2016 Decentral -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @fileoverview Wrapper of an instance of an Elliptic Curve - * @requires bn.js - * @requires elliptic - * @requires crypto/public_key/elliptic/key - * @requires crypto/random - * @requires enums - * @requires util - * @requires type/oid - * @module crypto/public_key/elliptic/curve - */ - -const nodeCrypto = _util2.default.getNodeCrypto(); - -const webCurves = { - 'p256': 'P-256', - 'p384': 'P-384', - 'p521': 'P-521' -}; -const knownCurves = nodeCrypto ? nodeCrypto.getCurves() : []; -const nodeCurves = nodeCrypto ? { - secp256k1: knownCurves.includes('secp256k1') ? 'secp256k1' : undefined, - p256: knownCurves.includes('prime256v1') ? 'prime256v1' : undefined, - p384: knownCurves.includes('secp384r1') ? 'secp384r1' : undefined, - p521: knownCurves.includes('secp521r1') ? 'secp521r1' : undefined, - ed25519: knownCurves.includes('ED25519') ? 'ED25519' : undefined, - curve25519: knownCurves.includes('X25519') ? 'X25519' : undefined, - brainpoolP256r1: knownCurves.includes('brainpoolP256r1') ? 'brainpoolP256r1' : undefined, - brainpoolP384r1: knownCurves.includes('brainpoolP384r1') ? 'brainpoolP384r1' : undefined, - brainpoolP512r1: knownCurves.includes('brainpoolP512r1') ? 'brainpoolP512r1' : undefined -} : {}; - -const curves = { - p256: { - oid: [0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07], - keyType: _enums2.default.publicKey.ecdsa, - hash: _enums2.default.hash.sha256, - cipher: _enums2.default.symmetric.aes128, - node: nodeCurves.p256, - web: webCurves.p256, - payloadSize: 32, - sharedSize: 256 - }, - p384: { - oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22], - keyType: _enums2.default.publicKey.ecdsa, - hash: _enums2.default.hash.sha384, - cipher: _enums2.default.symmetric.aes192, - node: nodeCurves.p384, - web: webCurves.p384, - payloadSize: 48, - sharedSize: 384 - }, - p521: { - oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23], - keyType: _enums2.default.publicKey.ecdsa, - hash: _enums2.default.hash.sha512, - cipher: _enums2.default.symmetric.aes256, - node: nodeCurves.p521, - web: webCurves.p521, - payloadSize: 66, - sharedSize: 528 - }, - secp256k1: { - oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x0A], - keyType: _enums2.default.publicKey.ecdsa, - hash: _enums2.default.hash.sha256, - cipher: _enums2.default.symmetric.aes128, - node: nodeCurves.secp256k1 - }, - ed25519: { - oid: [0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01], - keyType: _enums2.default.publicKey.eddsa, - hash: _enums2.default.hash.sha512, - node: false // nodeCurves.ed25519 TODO - }, - curve25519: { - oid: [0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01], - keyType: _enums2.default.publicKey.ecdsa, - hash: _enums2.default.hash.sha256, - cipher: _enums2.default.symmetric.aes128, - node: false // nodeCurves.curve25519 TODO - }, - brainpoolP256r1: { - oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07], - keyType: _enums2.default.publicKey.ecdsa, - hash: _enums2.default.hash.sha256, - cipher: _enums2.default.symmetric.aes128, - node: nodeCurves.brainpoolP256r1 - }, - brainpoolP384r1: { - oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B], - keyType: _enums2.default.publicKey.ecdsa, - hash: _enums2.default.hash.sha384, - cipher: _enums2.default.symmetric.aes192, - node: nodeCurves.brainpoolP384r1 - }, - brainpoolP512r1: { - oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D], - keyType: _enums2.default.publicKey.ecdsa, - hash: _enums2.default.hash.sha512, - cipher: _enums2.default.symmetric.aes256, - node: nodeCurves.brainpoolP512r1 - } -}; - -/** - * @constructor - */ -function Curve(oid_or_name, params) { - try { - if (_util2.default.isArray(oid_or_name) || _util2.default.isUint8Array(oid_or_name)) { - // by oid byte array - oid_or_name = new _oid2.default(oid_or_name); - } - if (oid_or_name instanceof _oid2.default) { - // by curve OID - oid_or_name = oid_or_name.getName(); - } - // by curve name or oid string - this.name = _enums2.default.write(_enums2.default.curve, oid_or_name); - } catch (err) { - throw new Error('Not valid curve'); - } - params = params || curves[this.name]; - - this.keyType = params.keyType; - switch (this.keyType) { - case _enums2.default.publicKey.ecdsa: - this.curve = new _elliptic.ec(this.name); - break; - case _enums2.default.publicKey.eddsa: - this.curve = new _elliptic.eddsa(this.name); - break; - default: - throw new Error('Unknown elliptic key type;'); - } - - this.oid = params.oid; - this.hash = params.hash; - this.cipher = params.cipher; - this.node = params.node && curves[this.name]; - this.web = params.web && curves[this.name]; - this.payloadSize = params.payloadSize; -} - -Curve.prototype.keyFromPrivate = function (priv) { - // Not for ed25519 - return new _key2.default(this, { priv: priv }); -}; - -Curve.prototype.keyFromPublic = function (pub) { - const keyPair = new _key2.default(this, { pub: pub }); - if (this.keyType === _enums2.default.publicKey.ecdsa && keyPair.keyPair.validate().result !== true) { - throw new Error('Invalid elliptic public key'); - } - return keyPair; -}; - -Curve.prototype.genKeyPair = async function () { - let keyPair; - if (this.web && _util2.default.getWebCrypto()) { - // If browser doesn't support a curve, we'll catch it - try { - keyPair = await webGenKeyPair(this.name); - } catch (err) { - _util2.default.print_debug("Browser did not support signing: " + err.message); - } - } else if (this.node && _util2.default.getNodeCrypto()) { - keyPair = await nodeGenKeyPair(this.name); - } - - if (!keyPair || !keyPair.priv) { - // elliptic fallback - const r = await this.curve.genKeyPair({ - entropy: _util2.default.Uint8Array_to_str((await _random2.default.getRandomBytes(32))) - }); - const compact = this.curve.curve.type === 'edwards' || this.curve.curve.type === 'mont'; - if (this.keyType === _enums2.default.publicKey.eddsa) { - keyPair = { secret: r.getSecret() }; - } else { - keyPair = { pub: r.getPublic('array', compact), priv: r.getPrivate().toArray() }; - } - } - return new _key2.default(this, keyPair); -}; - -async function generate(curve) { - curve = new Curve(curve); - const keyPair = await curve.genKeyPair(); - return { - oid: curve.oid, - Q: new _bn2.default(keyPair.getPublic()), - d: new _bn2.default(keyPair.getPrivate()), - hash: curve.hash, - cipher: curve.cipher - }; -} - -function getPreferredHashAlgo(oid) { - return curves[_enums2.default.write(_enums2.default.curve, oid.toHex())].hash; -} - -exports.default = Curve; -exports.curves = curves; -exports.webCurves = webCurves; -exports.nodeCurves = nodeCurves; -exports.generate = generate; -exports.getPreferredHashAlgo = getPreferredHashAlgo; - -////////////////////////// -// // -// Helper functions // -// // -////////////////////////// - - -async function webGenKeyPair(name) { - // Note: keys generated with ECDSA and ECDH are structurally equivalent - const webCryptoKey = await webCrypto.generateKey({ name: "ECDSA", namedCurve: webCurves[name] }, true, ["sign", "verify"]); - - const privateKey = await webCrypto.exportKey("jwk", webCryptoKey.privateKey); - const publicKey = await webCrypto.exportKey("jwk", webCryptoKey.publicKey); - - return { - pub: { - x: _util2.default.b64_to_Uint8Array(publicKey.x, true), - y: _util2.default.b64_to_Uint8Array(publicKey.y, true) - }, - priv: _util2.default.b64_to_Uint8Array(privateKey.d, true) - }; -} - -async function nodeGenKeyPair(name) { - // Note: ECDSA and ECDH key generation is structurally equivalent - const ecdh = nodeCrypto.createECDH(nodeCurves[name]); - await ecdh.generateKeys(); - - return { - pub: ecdh.getPublicKey().toJSON().data, - priv: ecdh.getPrivateKey().toJSON().data - }; -} - -},{"../../../enums":113,"../../../type/oid":150,"../../../util":152,"../../random":109,"./key":105,"bn.js":16,"elliptic":18}],101:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); // OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2015-2016 Decentral -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @fileoverview Key encryption and decryption for RFC 6637 ECDH - * @requires bn.js - * @requires tweetnacl - * @requires crypto/public_key/elliptic/curve - * @requires crypto/aes_kw - * @requires crypto/cipher - * @requires crypto/hash - * @requires type/kdf_params - * @requires enums - * @requires util - * @module crypto/public_key/elliptic/ecdh - */ - -var _bn = require('bn.js'); - -var _bn2 = _interopRequireDefault(_bn); - -var _naclFastLight = require('tweetnacl/nacl-fast-light.js'); - -var _naclFastLight2 = _interopRequireDefault(_naclFastLight); - -var _curves = require('./curves'); - -var _curves2 = _interopRequireDefault(_curves); - -var _aes_kw = require('../../aes_kw'); - -var _aes_kw2 = _interopRequireDefault(_aes_kw); - -var _cipher = require('../../cipher'); - -var _cipher2 = _interopRequireDefault(_cipher); - -var _hash = require('../../hash'); - -var _hash2 = _interopRequireDefault(_hash); - -var _kdf_params = require('../../../type/kdf_params'); - -var _kdf_params2 = _interopRequireDefault(_kdf_params); - -var _enums = require('../../../enums'); - -var _enums2 = _interopRequireDefault(_enums); - -var _util = require('../../../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const webCrypto = _util2.default.getWebCrypto(); -const nodeCrypto = _util2.default.getNodeCrypto(); - -// Build Param for ECDH algorithm (RFC 6637) -function buildEcdhParam(public_algo, oid, cipher_algo, hash_algo, fingerprint) { - const kdf_params = new _kdf_params2.default([hash_algo, cipher_algo]); - return _util2.default.concatUint8Array([oid.write(), new Uint8Array([public_algo]), kdf_params.write(), _util2.default.str_to_Uint8Array("Anonymous Sender "), fingerprint.subarray(0, 20)]); -} - -// Key Derivation Function (RFC 6637) -async function kdf(hash_algo, X, length, param, stripLeading = false, stripTrailing = false) { - // Note: X is little endian for Curve25519, big-endian for all others. - // This is not ideal, but the RFC's are unclear - // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B - let i; - if (stripLeading) { - // Work around old go crypto bug - for (i = 0; i < X.length && X[i] === 0; i++); - X = X.subarray(i); - } - if (stripTrailing) { - // Work around old OpenPGP.js bug - for (i = X.length - 1; i >= 0 && X[i] === 0; i--); - X = X.subarray(0, i + 1); - } - const digest = await _hash2.default.digest(hash_algo, _util2.default.concatUint8Array([new Uint8Array([0, 0, 0, 1]), X, param])); - return digest.subarray(0, length); -} - -/** - * Generate ECDHE ephemeral key and secret from public key - * - * @param {Curve} curve Elliptic curve object - * @param {Uint8Array} Q Recipient public key - * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ -async function genPublicEphemeralKey(curve, Q) { - switch (curve.name) { - case 'curve25519': - { - var _nacl$box$keyPair = _naclFastLight2.default.box.keyPair(); - - const d = _nacl$box$keyPair.secretKey; - - var _ref = await genPrivateEphemeralKey(curve, Q, null, d); - - const secretKey = _ref.secretKey, - sharedKey = _ref.sharedKey; - - var _nacl$box$keyPair$fro = _naclFastLight2.default.box.keyPair.fromSecretKey(secretKey); - - let publicKey = _nacl$box$keyPair$fro.publicKey; - - publicKey = _util2.default.concatUint8Array([new Uint8Array([0x40]), publicKey]); - return { publicKey, sharedKey }; // Note: sharedKey is little-endian here, unlike below - } - case 'p256': - case 'p384': - case 'p521': - { - if (curve.web && _util2.default.getWebCrypto()) { - try { - return await webPublicEphemeralKey(curve, Q); - } catch (err) { - _util2.default.print_debug_error(err); - } - } - } - } - if (curve.node && nodeCrypto) { - return nodePublicEphemeralKey(curve, Q); - } - return ellipticPublicEphemeralKey(curve, Q); -} - -/** - * Encrypt and wrap a session key - * - * @param {module:type/oid} oid Elliptic curve object identifier - * @param {module:enums.symmetric} cipher_algo Symmetric cipher to use - * @param {module:enums.hash} hash_algo Hash algorithm to use - * @param {module:type/mpi} m Value derived from session key (RFC 6637) - * @param {Uint8Array} Q Recipient public key - * @param {String} fingerprint Recipient fingerprint - * @returns {Promise<{publicKey: Uint8Array, wrappedKey: Uint8Array}>} - * @async - */ -async function encrypt(oid, cipher_algo, hash_algo, m, Q, fingerprint) { - const curve = new _curves2.default(oid); - - var _ref2 = await genPublicEphemeralKey(curve, Q); - - const publicKey = _ref2.publicKey, - sharedKey = _ref2.sharedKey; - - const param = buildEcdhParam(_enums2.default.publicKey.ecdh, oid, cipher_algo, hash_algo, fingerprint); - cipher_algo = _enums2.default.read(_enums2.default.symmetric, cipher_algo); - const Z = await kdf(hash_algo, sharedKey, _cipher2.default[cipher_algo].keySize, param); - const wrappedKey = _aes_kw2.default.wrap(Z, m.toString()); - return { publicKey, wrappedKey }; -} - -/** - * Generate ECDHE secret from private key and public part of ephemeral key - * - * @param {Curve} curve Elliptic curve object - * @param {Uint8Array} V Public part of ephemeral key - * @param {Uint8Array} Q Recipient public key - * @param {Uint8Array} d Recipient private key - * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ -async function genPrivateEphemeralKey(curve, V, Q, d) { - switch (curve.name) { - case 'curve25519': - { - const one = new _bn2.default(1); - const mask = one.ushln(255 - 3).sub(one).ushln(3); - let secretKey = new _bn2.default(d); - secretKey = secretKey.or(one.ushln(255 - 1)); - secretKey = secretKey.and(mask); - secretKey = secretKey.toArrayLike(Uint8Array, 'le', 32); - const sharedKey = _naclFastLight2.default.scalarMult(secretKey, V.subarray(1)); - return { secretKey, sharedKey }; // Note: sharedKey is little-endian here, unlike below - } - case 'p256': - case 'p384': - case 'p521': - { - if (curve.web && _util2.default.getWebCrypto()) { - try { - return await webPrivateEphemeralKey(curve, V, Q, d); - } catch (err) { - _util2.default.print_debug_error(err); - } - } - } - } - if (curve.node && nodeCrypto) { - return nodePrivateEphemeralKey(curve, V, d); - } - return ellipticPrivateEphemeralKey(curve, V, d); -} - -/** - * Decrypt and unwrap the value derived from session key - * - * @param {module:type/oid} oid Elliptic curve object identifier - * @param {module:enums.symmetric} cipher_algo Symmetric cipher to use - * @param {module:enums.hash} hash_algo Hash algorithm to use - * @param {Uint8Array} V Public part of ephemeral key - * @param {Uint8Array} C Encrypted and wrapped value derived from session key - * @param {Uint8Array} Q Recipient public key - * @param {Uint8Array} d Recipient private key - * @param {String} fingerprint Recipient fingerprint - * @returns {Promise} Value derived from session key - * @async - */ -async function decrypt(oid, cipher_algo, hash_algo, V, C, Q, d, fingerprint) { - const curve = new _curves2.default(oid); - - var _ref3 = await genPrivateEphemeralKey(curve, V, Q, d); - - const sharedKey = _ref3.sharedKey; - - const param = buildEcdhParam(_enums2.default.publicKey.ecdh, oid, cipher_algo, hash_algo, fingerprint); - cipher_algo = _enums2.default.read(_enums2.default.symmetric, cipher_algo); - let err; - for (let i = 0; i < 3; i++) { - try { - // Work around old go crypto bug and old OpenPGP.js bug, respectively. - const Z = await kdf(hash_algo, sharedKey, _cipher2.default[cipher_algo].keySize, param, i === 1, i === 2); - return new _bn2.default(_aes_kw2.default.unwrap(Z, C)); - } catch (e) { - err = e; - } - } - throw err; -} - -/** - * Generate ECDHE secret from private key and public part of ephemeral key using webCrypto - * - * @param {Curve} curve Elliptic curve object - * @param {Uint8Array} V Public part of ephemeral key - * @param {Uint8Array} Q Recipient public key - * @param {Uint8Array} d Recipient private key - * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ -async function webPrivateEphemeralKey(curve, V, Q, d) { - const recipient = privateToJwk(curve.payloadSize, curve.web.web, d, Q); - let privateKey = webCrypto.importKey("jwk", recipient, { - name: "ECDH", - namedCurve: curve.web.web - }, true, ["deriveKey", "deriveBits"]); - const jwk = rawPublicToJwk(curve.payloadSize, curve.web.web, V); - let sender = webCrypto.importKey("jwk", jwk, { - name: "ECDH", - namedCurve: curve.web.web - }, true, []); - - var _ref4 = await Promise.all([privateKey, sender]); - - var _ref5 = _slicedToArray(_ref4, 2); - - privateKey = _ref5[0]; - sender = _ref5[1]; - - let S = webCrypto.deriveBits({ - name: "ECDH", - namedCurve: curve.web.web, - public: sender - }, privateKey, curve.web.sharedSize); - let secret = webCrypto.exportKey("jwk", privateKey); - - var _ref6 = await Promise.all([S, secret]); - - var _ref7 = _slicedToArray(_ref6, 2); - - S = _ref7[0]; - secret = _ref7[1]; - - const sharedKey = new Uint8Array(S); - const secretKey = _util2.default.b64_to_Uint8Array(secret.d, true); - return { secretKey, sharedKey }; -} - -/** - * Generate ECDHE ephemeral key and secret from public key using webCrypto - * - * @param {Curve} curve Elliptic curve object - * @param {Uint8Array} Q Recipient public key - * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ -async function webPublicEphemeralKey(curve, Q) { - const jwk = rawPublicToJwk(curve.payloadSize, curve.web.web, Q); - let keyPair = webCrypto.generateKey({ - name: "ECDH", - namedCurve: curve.web.web - }, true, ["deriveKey", "deriveBits"]); - let recipient = webCrypto.importKey("jwk", jwk, { - name: "ECDH", - namedCurve: curve.web.web - }, false, []); - - var _ref8 = await Promise.all([keyPair, recipient]); - - var _ref9 = _slicedToArray(_ref8, 2); - - keyPair = _ref9[0]; - recipient = _ref9[1]; - - let s = webCrypto.deriveBits({ - name: "ECDH", - namedCurve: curve.web.web, - public: recipient - }, keyPair.privateKey, curve.web.sharedSize); - let p = webCrypto.exportKey("jwk", keyPair.publicKey); - - var _ref10 = await Promise.all([s, p]); - - var _ref11 = _slicedToArray(_ref10, 2); - - s = _ref11[0]; - p = _ref11[1]; - - const sharedKey = new Uint8Array(s); - const publicKey = new Uint8Array(jwkToRawPublic(p)); - return { publicKey, sharedKey }; -} - -/** - * Generate ECDHE secret from private key and public part of ephemeral key using indutny/elliptic - * - * @param {Curve} curve Elliptic curve object - * @param {Uint8Array} V Public part of ephemeral key - * @param {Uint8Array} d Recipient private key - * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ -async function ellipticPrivateEphemeralKey(curve, V, d) { - V = curve.keyFromPublic(V); - d = curve.keyFromPrivate(d); - const secretKey = new Uint8Array(d.getPrivate()); - const S = d.derive(V); - const len = curve.curve.curve.p.byteLength(); - const sharedKey = S.toArrayLike(Uint8Array, 'be', len); - return { secretKey, sharedKey }; -} - -/** - * Generate ECDHE ephemeral key and secret from public key using indutny/elliptic - * - * @param {Curve} curve Elliptic curve object - * @param {Uint8Array} Q Recipient public key - * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ -async function ellipticPublicEphemeralKey(curve, Q) { - const v = await curve.genKeyPair(); - Q = curve.keyFromPublic(Q); - const publicKey = new Uint8Array(v.getPublic()); - const S = v.derive(Q); - const len = curve.curve.curve.p.byteLength(); - const sharedKey = S.toArrayLike(Uint8Array, 'be', len); - return { publicKey, sharedKey }; -} - -/** - * Generate ECDHE secret from private key and public part of ephemeral key using nodeCrypto - * - * @param {Curve} curve Elliptic curve object - * @param {Uint8Array} V Public part of ephemeral key - * @param {Uint8Array} d Recipient private key - * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ -async function nodePrivateEphemeralKey(curve, V, d) { - const recipient = nodeCrypto.createECDH(curve.node.node); - recipient.setPrivateKey(d); - const sharedKey = new Uint8Array(recipient.computeSecret(V)); - const secretKey = new Uint8Array(recipient.getPrivateKey()); - return { secretKey, sharedKey }; -} - -/** - * Generate ECDHE ephemeral key and secret from public key using nodeCrypto - * - * @param {Curve} curve Elliptic curve object - * @param {Uint8Array} Q Recipient public key - * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ -async function nodePublicEphemeralKey(curve, Q) { - const sender = nodeCrypto.createECDH(curve.node.node); - sender.generateKeys(); - const sharedKey = new Uint8Array(sender.computeSecret(Q)); - const publicKey = new Uint8Array(sender.getPublicKey()); - return { publicKey, sharedKey }; -} - -/** - * @param {Integer} payloadSize ec payload size - * @param {String} name curve name - * @param {Uint8Array} publicKey public key - * @returns {JsonWebKey} public key in jwk format - */ -function rawPublicToJwk(payloadSize, name, publicKey) { - const len = payloadSize; - const bufX = publicKey.slice(1, len + 1); - const bufY = publicKey.slice(len + 1, len * 2 + 1); - // https://www.rfc-editor.org/rfc/rfc7518.txt - const jwKey = { - kty: "EC", - crv: name, - x: _util2.default.Uint8Array_to_b64(bufX, true), - y: _util2.default.Uint8Array_to_b64(bufY, true), - ext: true - }; - return jwKey; -} - -/** - * @param {Integer} payloadSize ec payload size - * @param {String} name curve name - * @param {Uint8Array} publicKey public key - * @param {Uint8Array} privateKey private key - * @returns {JsonWebKey} private key in jwk format - */ -function privateToJwk(payloadSize, name, privateKey, publicKey) { - const jwk = rawPublicToJwk(payloadSize, name, publicKey); - jwk.d = _util2.default.Uint8Array_to_b64(privateKey, true); - return jwk; -} - -/** - * @param {JsonWebKey} jwk key for conversion - * @returns {Uint8Array} raw public key - */ -function jwkToRawPublic(jwk) { - const bufX = _util2.default.b64_to_Uint8Array(jwk.x); - const bufY = _util2.default.b64_to_Uint8Array(jwk.y); - const publicKey = new Uint8Array(bufX.length + bufY.length + 1); - publicKey[0] = 0x04; - publicKey.set(bufX, 1); - publicKey.set(bufY, bufX.length + 1); - return publicKey; -} - -exports.default = { encrypt, decrypt, genPublicEphemeralKey, genPrivateEphemeralKey, buildEcdhParam, kdf, webPublicEphemeralKey, webPrivateEphemeralKey, ellipticPublicEphemeralKey, ellipticPrivateEphemeralKey, nodePublicEphemeralKey, nodePrivateEphemeralKey }; - -},{"../../../enums":113,"../../../type/kdf_params":147,"../../../util":152,"../../aes_kw":80,"../../cipher":86,"../../hash":92,"./curves":100,"bn.js":16,"tweetnacl/nacl-fast-light.js":72}],102:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _curves = require('./curves'); - -var _curves2 = _interopRequireDefault(_curves); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Sign a message using the provided key - * @param {module:type/oid} oid Elliptic curve object identifier - * @param {module:enums.hash} hash_algo Hash algorithm used to sign - * @param {Uint8Array} m Message to sign - * @param {Uint8Array} d Private key used to sign the message - * @param {Uint8Array} hashed The hashed message - * @returns {{r: Uint8Array, - * s: Uint8Array}} Signature of the message - * @async - */ -async function sign(oid, hash_algo, m, d, hashed) { - const curve = new _curves2.default(oid); - const key = curve.keyFromPrivate(d); - const signature = await key.sign(m, hash_algo, hashed); - return { - r: signature.r.toArrayLike(Uint8Array), - s: signature.s.toArrayLike(Uint8Array) - }; -} - -/** - * Verifies if a signature is valid for a message - * @param {module:type/oid} oid Elliptic curve object identifier - * @param {module:enums.hash} hash_algo Hash algorithm used in the signature - * @param {{r: Uint8Array, - s: Uint8Array}} signature Signature to verify - * @param {Uint8Array} m Message to verify - * @param {Uint8Array} Q Public key used to verify the message - * @param {Uint8Array} hashed The hashed message - * @returns {Boolean} - * @async - */ -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2015-2016 Decentral -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @fileoverview Implementation of ECDSA following RFC6637 for Openpgpjs - * @requires crypto/public_key/elliptic/curve - * @module crypto/public_key/elliptic/ecdsa - */ - -async function verify(oid, hash_algo, signature, m, Q, hashed) { - const curve = new _curves2.default(oid); - const key = curve.keyFromPublic(Q); - return key.verify(m, signature, hash_algo, hashed); -} - -exports.default = { sign, verify }; - -},{"./curves":100}],103:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _ = require('hash.js/lib/hash/sha/512'); - -var _2 = _interopRequireDefault(_); - -var _naclFastLight = require('tweetnacl/nacl-fast-light.js'); - -var _naclFastLight2 = _interopRequireDefault(_naclFastLight); - -var _util = require('../../../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -_naclFastLight2.default.hash = bytes => new Uint8Array((0, _2.default)().update(bytes).digest()); - -/** - * Sign a message using the provided key - * @param {module:type/oid} oid Elliptic curve object identifier - * @param {module:enums.hash} hash_algo Hash algorithm used to sign - * @param {Uint8Array} m Message to sign - * @param {Uint8Array} d Private key used to sign - * @param {Uint8Array} hashed The hashed message - * @returns {{R: Uint8Array, - * S: Uint8Array}} Signature of the message - * @async - */ -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2018 Proton Technologies AG -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @fileoverview Implementation of EdDSA following RFC4880bis-03 for OpenPGP - * @requires hash.js - * @requires tweetnacl - * @requires crypto/public_key/elliptic/curve - * @requires util - * @module crypto/public_key/elliptic/eddsa - */ - -async function sign(oid, hash_algo, m, d, hashed) { - var _nacl$sign$keyPair$fr = _naclFastLight2.default.sign.keyPair.fromSeed(d); - - const secretKey = _nacl$sign$keyPair$fr.secretKey; - - const signature = _naclFastLight2.default.sign.detached(hashed, secretKey); - // EdDSA signature params are returned in little-endian format - return { - R: signature.subarray(0, 32), - S: signature.subarray(32) - }; -} - -/** - * Verifies if a signature is valid for a message - * @param {module:type/oid} oid Elliptic curve object identifier - * @param {module:enums.hash} hash_algo Hash algorithm used in the signature - * @param {{R: Uint8Array, - S: Uint8Array}} signature Signature to verify the message - * @param {Uint8Array} m Message to verify - * @param {Uint8Array} publicKey Public key used to verify the message - * @param {Uint8Array} hashed The hashed message - * @returns {Boolean} - * @async - */ -async function verify(oid, hash_algo, { R, S }, m, publicKey, hashed) { - const signature = _util2.default.concatUint8Array([R, S]); - return _naclFastLight2.default.sign.detached.verify(hashed, signature, publicKey.subarray(1)); -} - -exports.default = { sign, verify }; - -},{"../../../util":152,"hash.js/lib/hash/sha/512":43,"tweetnacl/nacl-fast-light.js":72}],104:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _curves = require('./curves'); - -var _curves2 = _interopRequireDefault(_curves); - -var _ecdsa = require('./ecdsa'); - -var _ecdsa2 = _interopRequireDefault(_ecdsa); - -var _eddsa = require('./eddsa'); - -var _eddsa2 = _interopRequireDefault(_eddsa); - -var _ecdh = require('./ecdh'); - -var _ecdh2 = _interopRequireDefault(_ecdh); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2015-2016 Decentral -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @fileoverview Functions to access Elliptic Curve Cryptography - * @see module:crypto/public_key/elliptic/curve - * @see module:crypto/public_key/elliptic/ecdh - * @see module:crypto/public_key/elliptic/ecdsa - * @see module:crypto/public_key/elliptic/eddsa - * @module crypto/public_key/elliptic - */ - -exports.default = { - Curve: _curves2.default, ecdh: _ecdh2.default, ecdsa: _ecdsa2.default, eddsa: _eddsa2.default, generate: _curves.generate, getPreferredHashAlgo: _curves.getPreferredHashAlgo -}; - -},{"./curves":100,"./ecdh":101,"./ecdsa":102,"./eddsa":103}],105:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _bn = require('bn.js'); - -var _bn2 = _interopRequireDefault(_bn); - -var _webStreamTools = require('web-stream-tools'); - -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); - -var _curves = require('./curves'); - -var _util = require('../../../util'); - -var _util2 = _interopRequireDefault(_util); - -var _enums = require('../../../enums'); - -var _enums2 = _interopRequireDefault(_enums); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const webCrypto = _util2.default.getWebCrypto(); // OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2015-2016 Decentral -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @fileoverview Wrapper for a KeyPair of an Elliptic Curve - * @requires bn.js - * @requires web-stream-tools - * @requires crypto/public_key/elliptic/curves - * @requires util - * @requires enums - * @requires asn1.js - * @module crypto/public_key/elliptic/key - */ - -const nodeCrypto = _util2.default.getNodeCrypto(); - -/** - * @constructor - */ -function KeyPair(curve, options) { - this.curve = curve; - this.keyType = curve.curve.type === 'edwards' ? _enums2.default.publicKey.eddsa : _enums2.default.publicKey.ecdsa; - this.keyPair = this.curve.curve.keyPair(options); -} - -KeyPair.prototype.sign = async function (message, hash_algo, hashed) { - if (message && !message.locked) { - message = await _webStreamTools2.default.readToEnd(message); - if (this.curve.web && _util2.default.getWebCrypto()) { - // If browser doesn't support a curve, we'll catch it - try { - // need to await to make sure browser succeeds - const signature = await webSign(this.curve, hash_algo, message, this.keyPair); - return signature; - } catch (err) { - _util2.default.print_debug("Browser did not support signing: " + err.message); - } - } else if (this.curve.node && _util2.default.getNodeCrypto()) { - return nodeSign(this.curve, hash_algo, message, this.keyPair); - } - } - const digest = typeof hash_algo === 'undefined' ? message : hashed; - return this.keyPair.sign(digest); -}; - -KeyPair.prototype.verify = async function (message, signature, hash_algo, hashed) { - if (message && !message.locked) { - message = await _webStreamTools2.default.readToEnd(message); - if (this.curve.web && _util2.default.getWebCrypto()) { - // If browser doesn't support a curve, we'll catch it - try { - // need to await to make sure browser succeeds - const result = await webVerify(this.curve, hash_algo, signature, message, this.keyPair.getPublic()); - return result; - } catch (err) { - _util2.default.print_debug("Browser did not support signing: " + err.message); - } - } else if (this.curve.node && _util2.default.getNodeCrypto()) { - return nodeVerify(this.curve, hash_algo, signature, message, this.keyPair.getPublic()); - } - } - const digest = typeof hash_algo === 'undefined' ? message : hashed; - return this.keyPair.verify(digest, signature); -}; - -KeyPair.prototype.derive = function (pub) { - if (this.keyType === _enums2.default.publicKey.eddsa) { - throw new Error('Key can only be used for EdDSA'); - } - return this.keyPair.derive(pub.keyPair.getPublic()); -}; - -KeyPair.prototype.getPublic = function () { - const compact = this.curve.curve.curve.type === 'edwards' || this.curve.curve.curve.type === 'mont'; - return this.keyPair.getPublic('array', compact); -}; - -KeyPair.prototype.getPrivate = function () { - if (this.curve.keyType === _enums2.default.publicKey.eddsa) { - return this.keyPair.getSecret(); - } - return this.keyPair.getPrivate().toArray(); -}; - -exports.default = KeyPair; - -////////////////////////// -// // -// Helper functions // -// // -////////////////////////// - - -async function webSign(curve, hash_algo, message, keyPair) { - const len = curve.payloadSize; - const key = await webCrypto.importKey("jwk", { - "kty": "EC", - "crv": _curves.webCurves[curve.name], - "x": _util2.default.Uint8Array_to_b64(new Uint8Array(keyPair.getPublic().getX().toArray('be', len)), true), - "y": _util2.default.Uint8Array_to_b64(new Uint8Array(keyPair.getPublic().getY().toArray('be', len)), true), - "d": _util2.default.Uint8Array_to_b64(new Uint8Array(keyPair.getPrivate().toArray('be', len)), true), - "use": "sig", - "kid": "ECDSA Private Key" - }, { - "name": "ECDSA", - "namedCurve": _curves.webCurves[curve.name], - "hash": { name: _enums2.default.read(_enums2.default.webHash, curve.hash) } - }, false, ["sign"]); - - const signature = new Uint8Array((await webCrypto.sign({ - "name": 'ECDSA', - "namedCurve": _curves.webCurves[curve.name], - "hash": { name: _enums2.default.read(_enums2.default.webHash, hash_algo) } - }, key, message))); - - return { - r: new _bn2.default(signature.slice(0, len)), - s: new _bn2.default(signature.slice(len, len << 1)) - }; -} - -async function webVerify(curve, hash_algo, { r, s }, message, publicKey) { - const len = curve.payloadSize; - const key = await webCrypto.importKey("jwk", { - "kty": "EC", - "crv": _curves.webCurves[curve.name], - "x": _util2.default.Uint8Array_to_b64(new Uint8Array(publicKey.getX().toArray('be', len)), true), - "y": _util2.default.Uint8Array_to_b64(new Uint8Array(publicKey.getY().toArray('be', len)), true), - "use": "sig", - "kid": "ECDSA Public Key" - }, { - "name": "ECDSA", - "namedCurve": _curves.webCurves[curve.name], - "hash": { name: _enums2.default.read(_enums2.default.webHash, curve.hash) } - }, false, ["verify"]); - - const signature = _util2.default.concatUint8Array([new Uint8Array(len - r.length), r, new Uint8Array(len - s.length), s]).buffer; - - return webCrypto.verify({ - "name": 'ECDSA', - "namedCurve": _curves.webCurves[curve.name], - "hash": { name: _enums2.default.read(_enums2.default.webHash, hash_algo) } - }, key, signature, message); -} - -async function nodeSign(curve, hash_algo, message, keyPair) { - const sign = nodeCrypto.createSign(_enums2.default.read(_enums2.default.hash, hash_algo)); - sign.write(message); - sign.end(); - - const key = ECPrivateKey.encode({ - version: 1, - parameters: curve.oid, - privateKey: keyPair.getPrivate().toArray(), - publicKey: { unused: 0, data: keyPair.getPublic().encode() } - }, 'pem', { - label: 'EC PRIVATE KEY' - }); - - return ECDSASignature.decode(sign.sign(key), 'der'); -} - -async function nodeVerify(curve, hash_algo, { r, s }, message, publicKey) { - const verify = nodeCrypto.createVerify(_enums2.default.read(_enums2.default.hash, hash_algo)); - verify.write(message); - verify.end(); - - const key = SubjectPublicKeyInfo.encode({ - algorithm: { - algorithm: [1, 2, 840, 10045, 2, 1], - parameters: curve.oid - }, - subjectPublicKey: { unused: 0, data: publicKey.encode() } - }, 'pem', { - label: 'PUBLIC KEY' - }); - - const signature = ECDSASignature.encode({ - r: new _bn2.default(r), s: new _bn2.default(s) - }, 'der'); - - try { - return verify.verify(key, signature); - } catch (err) { - return false; - } -} - -// Originally written by Owen Smith https://github.com/omsmith -// Adapted on Feb 2018 from https://github.com/Brightspace/node-jwk-to-pem/ - -/* eslint-disable no-invalid-this */ - -const asn1 = nodeCrypto ? require('asn1.js') : undefined; - -const ECDSASignature = nodeCrypto ? asn1.define('ECDSASignature', function () { - this.seq().obj(this.key('r').int(), this.key('s').int()); -}) : undefined; - -const ECPrivateKey = nodeCrypto ? asn1.define('ECPrivateKey', function () { - this.seq().obj(this.key('version').int(), this.key('privateKey').octstr(), this.key('parameters').explicit(0).optional().any(), this.key('publicKey').explicit(1).optional().bitstr()); -}) : undefined; - -const AlgorithmIdentifier = nodeCrypto ? asn1.define('AlgorithmIdentifier', function () { - this.seq().obj(this.key('algorithm').objid(), this.key('parameters').optional().any()); -}) : undefined; - -const SubjectPublicKeyInfo = nodeCrypto ? asn1.define('SubjectPublicKeyInfo', function () { - this.seq().obj(this.key('algorithm').use(AlgorithmIdentifier), this.key('subjectPublicKey').bitstr()); -}) : undefined; - -},{"../../../enums":113,"../../../util":152,"./curves":100,"asn1.js":"asn1.js","bn.js":16,"web-stream-tools":75}],106:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _naclFastLight = require('tweetnacl/nacl-fast-light.js'); - -var _naclFastLight2 = _interopRequireDefault(_naclFastLight); - -var _rsa = require('./rsa'); - -var _rsa2 = _interopRequireDefault(_rsa); - -var _elgamal = require('./elgamal'); - -var _elgamal2 = _interopRequireDefault(_elgamal); - -var _elliptic = require('./elliptic'); - -var _elliptic2 = _interopRequireDefault(_elliptic); - -var _dsa = require('./dsa'); - -var _dsa2 = _interopRequireDefault(_dsa); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -exports.default = { - /** @see module:crypto/public_key/rsa */ - rsa: _rsa2.default, - /** @see module:crypto/public_key/elgamal */ - elgamal: _elgamal2.default, - /** @see module:crypto/public_key/elliptic */ - elliptic: _elliptic2.default, - /** @see module:crypto/public_key/dsa */ - dsa: _dsa2.default, - /** @see tweetnacl */ - nacl: _naclFastLight2.default -}; /** - * @fileoverview Asymmetric cryptography functions - * @requires tweetnacl - * @requires crypto/public_key/dsa - * @requires crypto/public_key/elgamal - * @requires crypto/public_key/elliptic - * @requires crypto/public_key/rsa - * @module crypto/public_key - */ - -},{"./dsa":98,"./elgamal":99,"./elliptic":104,"./rsa":108,"tweetnacl/nacl-fast-light.js":72}],107:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _bn = require('bn.js'); - -var _bn2 = _interopRequireDefault(_bn); - -var _random = require('../random'); - -var _random2 = _interopRequireDefault(_random); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2018 Proton Technologies AG -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @fileoverview Algorithms for probabilistic random prime generation - * @requires bn.js - * @requires crypto/random - * @module crypto/public_key/prime - */ - -exports.default = { - randomProbablePrime, isProbablePrime, fermat, millerRabin, divisionTest -}; - -/** - * Probabilistic random number generator - * @param {Integer} bits Bit length of the prime - * @param {BN} e Optional RSA exponent to check against the prime - * @param {Integer} k Optional number of iterations of Miller-Rabin test - * @returns BN - * @async - */ - -async function randomProbablePrime(bits, e, k) { - const min = new _bn2.default(1).shln(bits - 1); - const thirty = new _bn2.default(30); - /* - * We can avoid any multiples of 3 and 5 by looking at n mod 30 - * n mod 30 = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 - * the next possible prime is mod 30: - * 1 7 7 7 7 7 7 11 11 11 11 13 13 17 17 17 17 19 19 23 23 23 23 29 29 29 29 29 29 1 - */ - const adds = [1, 6, 5, 4, 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, 3, 2, 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1, 2]; - - let n = await _random2.default.getRandomBN(min, min.shln(1)); - let i = n.mod(thirty).toNumber(); - - do { - n.iaddn(adds[i]); - i = (i + adds[i]) % adds.length; - // If reached the maximum, go back to the minimum. - if (n.bitLength() > bits) { - n = n.mod(min.shln(1)).iadd(min); - i = n.mod(thirty).toNumber(); - } - } while (!(await isProbablePrime(n, e, k))); - return n; -} - -/** - * Probabilistic primality testing - * @param {BN} n Number to test - * @param {BN} e Optional RSA exponent to check against the prime - * @param {Integer} k Optional number of iterations of Miller-Rabin test - * @returns {boolean} - * @async - */ -async function isProbablePrime(n, e, k) { - if (e && !n.subn(1).gcd(e).eqn(1)) { - return false; - } - if (!divisionTest(n)) { - return false; - } - if (!fermat(n)) { - return false; - } - if (!(await millerRabin(n, k))) { - return false; - } - // TODO implement the Lucas test - // See Section C.3.3 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - return true; -} - -/** - * Tests whether n is probably prime or not using Fermat's test with b = 2. - * Fails if b^(n-1) mod n === 1. - * @param {BN} n Number to test - * @param {Integer} b Optional Fermat test base - * @returns {boolean} - */ -function fermat(n, b) { - b = b || new _bn2.default(2); - return b.toRed(_bn2.default.mont(n)).redPow(n.subn(1)).fromRed().cmpn(1) === 0; -} - -function divisionTest(n) { - return small_primes.every(m => { - return n.modn(m) !== 0; - }); -} - -// https://github.com/gpg/libgcrypt/blob/master/cipher/primegen.c -const small_primes = [7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999]; - -// Miller-Rabin - Miller Rabin algorithm for primality test -// Copyright Fedor Indutny, 2014. -// -// This software is licensed under the MIT License. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -// Adapted on Jan 2018 from version 4.0.1 at https://github.com/indutny/miller-rabin - -// Sample syntax for Fixed-Base Miller-Rabin: -// millerRabin(n, k, () => new BN(small_primes[Math.random() * small_primes.length | 0])) - -/** - * Tests whether n is probably prime or not using the Miller-Rabin test. - * See HAC Remark 4.28. - * @param {BN} n Number to test - * @param {Integer} k Optional number of iterations of Miller-Rabin test - * @param {Function} rand Optional function to generate potential witnesses - * @returns {boolean} - * @async - */ -async function millerRabin(n, k, rand) { - const len = n.bitLength(); - const red = _bn2.default.mont(n); - const rone = new _bn2.default(1).toRed(red); - - if (!k) { - k = Math.max(1, len / 48 | 0); - } - - const n1 = n.subn(1); - const rn1 = n1.toRed(red); - - // Find d and s, (n - 1) = (2 ^ s) * d; - let s = 0; - while (!n1.testn(s)) { - s++; - } - const d = n.shrn(s); - - for (; k > 0; k--) { - const a = rand ? rand() : await _random2.default.getRandomBN(new _bn2.default(2), n1); - - let x = a.toRed(red).redPow(d); - if (x.eq(rone) || x.eq(rn1)) { - continue; - } - - let i; - for (i = 1; i < s; i++) { - x = x.redSqr(); - - if (x.eq(rone)) { - return false; - } - if (x.eq(rn1)) { - break; - } - } - - if (i === s) { - return false; - } - } - - return true; -} - -},{"../random":109,"bn.js":16}],108:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _bn = require('bn.js'); - -var _bn2 = _interopRequireDefault(_bn); - -var _prime = require('./prime'); - -var _prime2 = _interopRequireDefault(_prime); - -var _random = require('../random'); - -var _random2 = _interopRequireDefault(_random); - -var _config = require('../../config'); - -var _config2 = _interopRequireDefault(_config); - -var _util = require('../../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -// Helper for IE11 KeyOperation objects -function promisifyIE11Op(keyObj, err) { - if (typeof keyObj.then !== 'function') { - // IE11 KeyOperation - return new Promise(function (resolve, reject) { - keyObj.onerror = function () { - reject(new Error(err)); - }; - keyObj.oncomplete = function (e) { - resolve(e.target.result); - }; - }); - } - return keyObj; -} // GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @fileoverview RSA implementation - * @requires bn.js - * @requires crypto/public_key/prime - * @requires crypto/random - * @requires config - * @requires util - * @module crypto/public_key/rsa - */ - -exports.default = { - /** Create signature - * @param {BN} m message - * @param {BN} n RSA public modulus - * @param {BN} e RSA public exponent - * @param {BN} d RSA private exponent - * @returns {BN} RSA Signature - * @async - */ - sign: async function sign(m, n, e, d) { - if (n.cmp(m) <= 0) { - throw new Error('Message size cannot exceed modulus size'); - } - const nred = new _bn2.default.red(n); - return m.toRed(nred).redPow(d).toArrayLike(Uint8Array, 'be', n.byteLength()); - }, - - /** - * Verify signature - * @param {BN} s signature - * @param {BN} n RSA public modulus - * @param {BN} e RSA public exponent - * @returns {BN} - * @async - */ - verify: async function verify(s, n, e) { - if (n.cmp(s) <= 0) { - throw new Error('Signature size cannot exceed modulus size'); - } - const nred = new _bn2.default.red(n); - return s.toRed(nred).redPow(e).toArrayLike(Uint8Array, 'be', n.byteLength()); - }, - - /** - * Encrypt message - * @param {BN} m message - * @param {BN} n RSA public modulus - * @param {BN} e RSA public exponent - * @returns {BN} RSA Ciphertext - * @async - */ - encrypt: async function encrypt(m, n, e) { - if (n.cmp(m) <= 0) { - throw new Error('Message size cannot exceed modulus size'); - } - const nred = new _bn2.default.red(n); - return m.toRed(nred).redPow(e).toArrayLike(Uint8Array, 'be', n.byteLength()); - }, - - /** - * Decrypt RSA message - * @param {BN} m message - * @param {BN} n RSA public modulus - * @param {BN} e RSA public exponent - * @param {BN} d RSA private exponent - * @param {BN} p RSA private prime p - * @param {BN} q RSA private prime q - * @param {BN} u RSA private inverse of prime q - * @returns {BN} RSA Plaintext - * @async - */ - decrypt: async function decrypt(m, n, e, d, p, q, u) { - if (n.cmp(m) <= 0) { - throw new Error('Data too large.'); - } - const dq = d.mod(q.subn(1)); // d mod (q-1) - const dp = d.mod(p.subn(1)); // d mod (p-1) - const pred = new _bn2.default.red(p); - const qred = new _bn2.default.red(q); - const nred = new _bn2.default.red(n); - - let blinder; - let unblinder; - if (_config2.default.rsa_blinding) { - unblinder = (await _random2.default.getRandomBN(new _bn2.default(2), n)).toRed(nred); - blinder = unblinder.redInvm().redPow(e); - m = m.toRed(nred).redMul(blinder).fromRed(); - } - - const mp = m.toRed(pred).redPow(dp); - const mq = m.toRed(qred).redPow(dq); - const t = mq.redSub(mp.fromRed().toRed(qred)); - const h = u.toRed(qred).redMul(t).fromRed(); - - let result = h.mul(p).add(mp).toRed(nred); - - if (_config2.default.rsa_blinding) { - result = result.redMul(unblinder); - } - - return result.toArrayLike(Uint8Array, 'be', n.byteLength()); - }, - - /** - * Generate a new random private key B bits long with public exponent E. - * - * When possible, webCrypto is used. Otherwise, primes are generated using - * 40 rounds of the Miller-Rabin probabilistic random prime generation algorithm. - * @see module:crypto/public_key/prime - * @param {Integer} B RSA bit length - * @param {String} E RSA public exponent in hex string - * @returns {{n: BN, e: BN, d: BN, - * p: BN, q: BN, u: BN}} RSA public modulus, RSA public exponent, RSA private exponent, - * RSA private prime p, RSA private prime q, u = q ** -1 mod p - * @async - */ - generate: async function generate(B, E) { - let key; - E = new _bn2.default(E, 16); - const webCrypto = _util2.default.getWebCryptoAll(); - - // Native RSA keygen using Web Crypto - if (webCrypto) { - let keyPair; - let keyGenOpt; - if (window.crypto && window.crypto.subtle || window.msCrypto) { - // current standard spec - keyGenOpt = { - name: 'RSASSA-PKCS1-v1_5', - modulusLength: B, // the specified keysize in bits - publicExponent: E.toArrayLike(Uint8Array), // take three bytes (max 65537) for exponent - hash: { - name: 'SHA-1' // not required for actual RSA keys, but for crypto api 'sign' and 'verify' - } - }; - keyPair = webCrypto.generateKey(keyGenOpt, true, ['sign', 'verify']); - keyPair = await promisifyIE11Op(keyPair, 'Error generating RSA key pair.'); - } else if (window.crypto && window.crypto.webkitSubtle) { - // outdated spec implemented by old Webkit - keyGenOpt = { - name: 'RSA-OAEP', - modulusLength: B, // the specified keysize in bits - publicExponent: E.toArrayLike(Uint8Array), // take three bytes (max 65537) for exponent - hash: { - name: 'SHA-1' // not required for actual RSA keys, but for crypto api 'sign' and 'verify' - } - }; - keyPair = await webCrypto.generateKey(keyGenOpt, true, ['encrypt', 'decrypt']); - } else { - throw new Error('Unknown WebCrypto implementation'); - } - - // export the generated keys as JsonWebKey (JWK) - // https://tools.ietf.org/html/draft-ietf-jose-json-web-key-33 - let jwk = webCrypto.exportKey('jwk', keyPair.privateKey); - jwk = await promisifyIE11Op(jwk, 'Error exporting RSA key pair.'); - - // parse raw ArrayBuffer bytes to jwk/json (WebKit/Safari/IE11 quirk) - if (jwk instanceof ArrayBuffer) { - jwk = JSON.parse(String.fromCharCode.apply(null, new Uint8Array(jwk))); - } - - // map JWK parameters to BN - key = {}; - key.n = new _bn2.default(_util2.default.b64_to_Uint8Array(jwk.n)); - key.e = E; - key.d = new _bn2.default(_util2.default.b64_to_Uint8Array(jwk.d)); - key.p = new _bn2.default(_util2.default.b64_to_Uint8Array(jwk.p)); - key.q = new _bn2.default(_util2.default.b64_to_Uint8Array(jwk.q)); - key.u = key.p.invm(key.q); - return key; - } - - // RSA keygen fallback using 40 iterations of the Miller-Rabin test - // See https://stackoverflow.com/a/6330138 for justification - // Also see section C.3 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST - let p = await _prime2.default.randomProbablePrime(B - (B >> 1), E, 40); - let q = await _prime2.default.randomProbablePrime(B >> 1, E, 40); - - if (p.cmp(q) < 0) { - var _ref = [q, p]; - p = _ref[0]; - q = _ref[1]; - } - - const phi = p.subn(1).mul(q.subn(1)); - return { - n: p.mul(q), - e: E, - d: E.invm(phi), - p: p, - q: q, - // dp: d.mod(p.subn(1)), - // dq: d.mod(q.subn(1)), - u: p.invm(q) - }; - }, - - prime: _prime2.default -}; - -},{"../../config":79,"../../util":152,"../random":109,"./prime":107,"bn.js":16}],109:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _bn = require('bn.js'); - -var _bn2 = _interopRequireDefault(_bn); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -// Do not use util.getNodeCrypto because we need this regardless of use_native setting -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -// The GPG4Browsers crypto interface - -/** - * @fileoverview Provides tools for retrieving secure randomness from browsers or Node.js - * @requires bn.js - * @requires util - * @module crypto/random - */ - -const nodeCrypto = _util2.default.detectNode() && require('crypto'); - -exports.default = { - /** - * Retrieve secure random byte array of the specified length - * @param {Integer} length Length in bytes to generate - * @returns {Uint8Array} Random byte array - * @async - */ - getRandomBytes: async function getRandomBytes(length) { - const buf = new Uint8Array(length); - if (typeof window !== 'undefined' && window.crypto && window.crypto.getRandomValues) { - window.crypto.getRandomValues(buf); - } else if (typeof window !== 'undefined' && typeof window.msCrypto === 'object' && typeof window.msCrypto.getRandomValues === 'function') { - window.msCrypto.getRandomValues(buf); - } else if (nodeCrypto) { - const bytes = nodeCrypto.randomBytes(buf.length); - buf.set(bytes); - } else if (this.randomBuffer.buffer) { - await this.randomBuffer.get(buf); - } else { - throw new Error('No secure random number generator available.'); - } - return buf; - }, - - /** - * Create a secure random MPI that is greater than or equal to min and less than max. - * @param {module:type/mpi} min Lower bound, included - * @param {module:type/mpi} max Upper bound, excluded - * @returns {module:BN} Random MPI - * @async - */ - getRandomBN: async function getRandomBN(min, max) { - if (max.cmp(min) <= 0) { - throw new Error('Illegal parameter value: max <= min'); - } - - const modulus = max.sub(min); - const bytes = modulus.byteLength(); - - // Using a while loop is necessary to avoid bias introduced by the mod operation. - // However, we request 64 extra random bits so that the bias is negligible. - // Section B.1.1 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - const r = new _bn2.default((await this.getRandomBytes(bytes + 8))); - return r.mod(modulus).add(min); - }, - - randomBuffer: new RandomBuffer() -}; - -/** - * Buffer for secure random numbers - */ - -function RandomBuffer() { - this.buffer = null; - this.size = null; - this.callback = null; -} - -/** - * Initialize buffer - * @param {Integer} size size of buffer - */ -RandomBuffer.prototype.init = function (size, callback) { - this.buffer = new Uint8Array(size); - this.size = 0; - this.callback = callback; -}; - -/** - * Concat array of secure random numbers to buffer - * @param {Uint8Array} buf - */ -RandomBuffer.prototype.set = function (buf) { - if (!this.buffer) { - throw new Error('RandomBuffer is not initialized'); - } - if (!(buf instanceof Uint8Array)) { - throw new Error('Invalid type: buf not an Uint8Array'); - } - const freeSpace = this.buffer.length - this.size; - if (buf.length > freeSpace) { - buf = buf.subarray(0, freeSpace); - } - // set buf with offset old size of buffer - this.buffer.set(buf, this.size); - this.size += buf.length; -}; - -/** - * Take numbers out of buffer and copy to array - * @param {Uint8Array} buf the destination array - */ -RandomBuffer.prototype.get = async function (buf) { - if (!this.buffer) { - throw new Error('RandomBuffer is not initialized'); - } - if (!(buf instanceof Uint8Array)) { - throw new Error('Invalid type: buf not an Uint8Array'); - } - if (this.size < buf.length) { - if (!this.callback) { - throw new Error('Random number buffer depleted'); - } - // Wait for random bytes from main context, then try again - await this.callback(); - return this.get(buf); - } - for (let i = 0; i < buf.length; i++) { - buf[i] = this.buffer[--this.size]; - // clear buffer value - this.buffer[this.size] = 0; - } -}; - -},{"../util":152,"bn.js":16,"crypto":"crypto"}],110:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _bn = require('bn.js'); - -var _bn2 = _interopRequireDefault(_bn); - -var _crypto = require('./crypto'); - -var _crypto2 = _interopRequireDefault(_crypto); - -var _public_key = require('./public_key'); - -var _public_key2 = _interopRequireDefault(_public_key); - -var _pkcs = require('./pkcs1'); - -var _pkcs2 = _interopRequireDefault(_pkcs); - -var _enums = require('../enums'); - -var _enums2 = _interopRequireDefault(_enums); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * @fileoverview Provides functions for asymmetric signing and signature verification - * @requires bn.js - * @requires crypto/crypto - * @requires crypto/public_key - * @requires crypto/pkcs1 - * @requires enums - * @requires util - * @module crypto/signature -*/ - -exports.default = { - /** - * Verifies the signature provided for data using specified algorithms and public key parameters. - * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} - * and {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4} - * for public key and hash algorithms. - * @param {module:enums.publicKey} algo Public key algorithm - * @param {module:enums.hash} hash_algo Hash algorithm - * @param {Array} msg_MPIs Algorithm-specific signature parameters - * @param {Array} pub_MPIs Algorithm-specific public key parameters - * @param {Uint8Array} data Data for which the signature was created - * @param {Uint8Array} hashed The hashed data - * @returns {Boolean} True if signature is valid - * @async - */ - verify: async function verify(algo, hash_algo, msg_MPIs, pub_MPIs, data, hashed) { - const types = _crypto2.default.getPubKeyParamTypes(algo); - if (pub_MPIs.length < types.length) { - throw new Error('Missing public key parameters'); - } - switch (algo) { - case _enums2.default.publicKey.rsa_encrypt_sign: - case _enums2.default.publicKey.rsa_encrypt: - case _enums2.default.publicKey.rsa_sign: - { - const m = msg_MPIs[0].toBN(); - const n = pub_MPIs[0].toBN(); - const e = pub_MPIs[1].toBN(); - const EM = await _public_key2.default.rsa.verify(m, n, e); - const EM2 = await _pkcs2.default.emsa.encode(hash_algo, hashed, n.byteLength()); - return _util2.default.Uint8Array_to_hex(EM) === EM2; - } - case _enums2.default.publicKey.dsa: - { - const r = msg_MPIs[0].toBN(); - const s = msg_MPIs[1].toBN(); - const p = pub_MPIs[0].toBN(); - const q = pub_MPIs[1].toBN(); - const g = pub_MPIs[2].toBN(); - const y = pub_MPIs[3].toBN(); - return _public_key2.default.dsa.verify(hash_algo, r, s, hashed, g, p, q, y); - } - case _enums2.default.publicKey.ecdsa: - { - const oid = pub_MPIs[0]; - const signature = { r: msg_MPIs[0].toUint8Array(), s: msg_MPIs[1].toUint8Array() }; - const Q = pub_MPIs[1].toUint8Array(); - return _public_key2.default.elliptic.ecdsa.verify(oid, hash_algo, signature, data, Q, hashed); - } - case _enums2.default.publicKey.eddsa: - { - const oid = pub_MPIs[0]; - // EdDSA signature params are expected in little-endian format - const signature = { - R: msg_MPIs[0].toUint8Array('le', 32), - S: msg_MPIs[1].toUint8Array('le', 32) - }; - const Q = pub_MPIs[1].toUint8Array('be', 33); - return _public_key2.default.elliptic.eddsa.verify(oid, hash_algo, signature, data, Q, hashed); - } - default: - throw new Error('Invalid signature algorithm.'); - } - }, - - /** - * Creates a signature on data using specified algorithms and private key parameters. - * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} - * and {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4} - * for public key and hash algorithms. - * @param {module:enums.publicKey} algo Public key algorithm - * @param {module:enums.hash} hash_algo Hash algorithm - * @param {Array} key_params Algorithm-specific public and private key parameters - * @param {Uint8Array} data Data to be signed - * @param {Uint8Array} hashed The hashed data - * @returns {Uint8Array} Signature - * @async - */ - sign: async function sign(algo, hash_algo, key_params, data, hashed) { - const types = [].concat(_crypto2.default.getPubKeyParamTypes(algo), _crypto2.default.getPrivKeyParamTypes(algo)); - if (key_params.length < types.length) { - throw new Error('Missing private key parameters'); - } - switch (algo) { - case _enums2.default.publicKey.rsa_encrypt_sign: - case _enums2.default.publicKey.rsa_encrypt: - case _enums2.default.publicKey.rsa_sign: - { - const n = key_params[0].toBN(); - const e = key_params[1].toBN(); - const d = key_params[2].toBN(); - const m = new _bn2.default((await _pkcs2.default.emsa.encode(hash_algo, hashed, n.byteLength())), 16); - const signature = await _public_key2.default.rsa.sign(m, n, e, d); - return _util2.default.Uint8Array_to_MPI(signature); - } - case _enums2.default.publicKey.dsa: - { - const p = key_params[0].toBN(); - const q = key_params[1].toBN(); - const g = key_params[2].toBN(); - const x = key_params[4].toBN(); - const signature = await _public_key2.default.dsa.sign(hash_algo, hashed, g, p, q, x); - return _util2.default.concatUint8Array([_util2.default.Uint8Array_to_MPI(signature.r), _util2.default.Uint8Array_to_MPI(signature.s)]); - } - case _enums2.default.publicKey.elgamal: - { - throw new Error('Signing with Elgamal is not defined in the OpenPGP standard.'); - } - case _enums2.default.publicKey.ecdsa: - { - const oid = key_params[0]; - const d = key_params[2].toUint8Array(); - const signature = await _public_key2.default.elliptic.ecdsa.sign(oid, hash_algo, data, d, hashed); - return _util2.default.concatUint8Array([_util2.default.Uint8Array_to_MPI(signature.r), _util2.default.Uint8Array_to_MPI(signature.s)]); - } - case _enums2.default.publicKey.eddsa: - { - const oid = key_params[0]; - const d = key_params[2].toUint8Array('be', 32); - const signature = await _public_key2.default.elliptic.eddsa.sign(oid, hash_algo, data, d, hashed); - return _util2.default.concatUint8Array([_util2.default.Uint8Array_to_MPI(signature.R), _util2.default.Uint8Array_to_MPI(signature.S)]); - } - default: - throw new Error('Invalid signature algorithm.'); - } - } -}; - -},{"../enums":113,"../util":152,"./crypto":89,"./pkcs1":96,"./public_key":106,"bn.js":16}],111:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _webStreamTools = require('web-stream-tools'); - -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); - -var _base = require('./base64.js'); - -var _base2 = _interopRequireDefault(_base); - -var _enums = require('../enums.js'); - -var _enums2 = _interopRequireDefault(_enums); - -var _config = require('../config'); - -var _config2 = _interopRequireDefault(_config); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Finds out which Ascii Armoring type is used. Throws error if unknown type. - * @private - * @param {String} text [String] ascii armored text - * @returns {Integer} 0 = MESSAGE PART n of m - * 1 = MESSAGE PART n - * 2 = SIGNED MESSAGE - * 3 = PGP MESSAGE - * 4 = PUBLIC KEY BLOCK - * 5 = PRIVATE KEY BLOCK - * 6 = SIGNATURE - */ -function getType(text) { - const reHeader = /^-----BEGIN PGP (MESSAGE, PART \d+\/\d+|MESSAGE, PART \d+|SIGNED MESSAGE|MESSAGE|PUBLIC KEY BLOCK|PRIVATE KEY BLOCK|SIGNATURE)-----$/m; - - const header = text.match(reHeader); - - if (!header) { - throw new Error('Unknown ASCII armor type'); - } - - // BEGIN PGP MESSAGE, PART X/Y - // Used for multi-part messages, where the armor is split amongst Y - // parts, and this is the Xth part out of Y. - if (/MESSAGE, PART \d+\/\d+/.test(header[1])) { - return _enums2.default.armor.multipart_section; - } else - // BEGIN PGP MESSAGE, PART X - // Used for multi-part messages, where this is the Xth part of an - // unspecified number of parts. Requires the MESSAGE-ID Armor - // Header to be used. - if (/MESSAGE, PART \d+/.test(header[1])) { - return _enums2.default.armor.multipart_last; - } else - // BEGIN PGP SIGNED MESSAGE - if (/SIGNED MESSAGE/.test(header[1])) { - return _enums2.default.armor.signed; - } else - // BEGIN PGP MESSAGE - // Used for signed, encrypted, or compressed files. - if (/MESSAGE/.test(header[1])) { - return _enums2.default.armor.message; - } else - // BEGIN PGP PUBLIC KEY BLOCK - // Used for armoring public keys. - if (/PUBLIC KEY BLOCK/.test(header[1])) { - return _enums2.default.armor.public_key; - } else - // BEGIN PGP PRIVATE KEY BLOCK - // Used for armoring private keys. - if (/PRIVATE KEY BLOCK/.test(header[1])) { - return _enums2.default.armor.private_key; - } else - // BEGIN PGP SIGNATURE - // Used for detached signatures, OpenPGP/MIME signatures, and - // cleartext signatures. Note that PGP 2.x uses BEGIN PGP MESSAGE - // for detached signatures. - if (/SIGNATURE/.test(header[1])) { - return _enums2.default.armor.signature; - } -} - -/** - * Add additional information to the armor version of an OpenPGP binary - * packet block. - * @author Alex - * @version 2011-12-16 - * @param {String} customComment (optional) additional comment to add to the armored string - * @returns {String} The header information - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @requires web-stream-tools - * @requires encoding/base64 - * @requires enums - * @requires config - * @requires util - * @module encoding/armor - */ - -function addheader(customComment) { - let result = ""; - if (_config2.default.show_version) { - result += "Version: " + _config2.default.versionstring + '\r\n'; - } - if (_config2.default.show_comment) { - result += "Comment: " + _config2.default.commentstring + '\r\n'; - } - if (customComment) { - result += "Comment: " + customComment + '\r\n'; - } - result += '\r\n'; - return result; -} - -/** - * Calculates a checksum over the given data and returns it base64 encoded - * @param {String | ReadableStream} data Data to create a CRC-24 checksum for - * @returns {String | ReadableStream} Base64 encoded checksum - */ -function getCheckSum(data) { - const crc = createcrc24(data); - return _base2.default.encode(crc); -} - -const crc_table = [0x00000000, 0x00864cfb, 0x018ad50d, 0x010c99f6, 0x0393e6e1, 0x0315aa1a, 0x021933ec, 0x029f7f17, 0x07a18139, 0x0727cdc2, 0x062b5434, 0x06ad18cf, 0x043267d8, 0x04b42b23, 0x05b8b2d5, 0x053efe2e, 0x0fc54e89, 0x0f430272, 0x0e4f9b84, 0x0ec9d77f, 0x0c56a868, 0x0cd0e493, 0x0ddc7d65, 0x0d5a319e, 0x0864cfb0, 0x08e2834b, 0x09ee1abd, 0x09685646, 0x0bf72951, 0x0b7165aa, 0x0a7dfc5c, 0x0afbb0a7, 0x1f0cd1e9, 0x1f8a9d12, 0x1e8604e4, 0x1e00481f, 0x1c9f3708, 0x1c197bf3, 0x1d15e205, 0x1d93aefe, 0x18ad50d0, 0x182b1c2b, 0x192785dd, 0x19a1c926, 0x1b3eb631, 0x1bb8faca, 0x1ab4633c, 0x1a322fc7, 0x10c99f60, 0x104fd39b, 0x11434a6d, 0x11c50696, 0x135a7981, 0x13dc357a, 0x12d0ac8c, 0x1256e077, 0x17681e59, 0x17ee52a2, 0x16e2cb54, 0x166487af, 0x14fbf8b8, 0x147db443, 0x15712db5, 0x15f7614e, 0x3e19a3d2, 0x3e9fef29, 0x3f9376df, 0x3f153a24, 0x3d8a4533, 0x3d0c09c8, 0x3c00903e, 0x3c86dcc5, 0x39b822eb, 0x393e6e10, 0x3832f7e6, 0x38b4bb1d, 0x3a2bc40a, 0x3aad88f1, 0x3ba11107, 0x3b275dfc, 0x31dced5b, 0x315aa1a0, 0x30563856, 0x30d074ad, 0x324f0bba, 0x32c94741, 0x33c5deb7, 0x3343924c, 0x367d6c62, 0x36fb2099, 0x37f7b96f, 0x3771f594, 0x35ee8a83, 0x3568c678, 0x34645f8e, 0x34e21375, 0x2115723b, 0x21933ec0, 0x209fa736, 0x2019ebcd, 0x228694da, 0x2200d821, 0x230c41d7, 0x238a0d2c, 0x26b4f302, 0x2632bff9, 0x273e260f, 0x27b86af4, 0x252715e3, 0x25a15918, 0x24adc0ee, 0x242b8c15, 0x2ed03cb2, 0x2e567049, 0x2f5ae9bf, 0x2fdca544, 0x2d43da53, 0x2dc596a8, 0x2cc90f5e, 0x2c4f43a5, 0x2971bd8b, 0x29f7f170, 0x28fb6886, 0x287d247d, 0x2ae25b6a, 0x2a641791, 0x2b688e67, 0x2beec29c, 0x7c3347a4, 0x7cb50b5f, 0x7db992a9, 0x7d3fde52, 0x7fa0a145, 0x7f26edbe, 0x7e2a7448, 0x7eac38b3, 0x7b92c69d, 0x7b148a66, 0x7a181390, 0x7a9e5f6b, 0x7801207c, 0x78876c87, 0x798bf571, 0x790db98a, 0x73f6092d, 0x737045d6, 0x727cdc20, 0x72fa90db, 0x7065efcc, 0x70e3a337, 0x71ef3ac1, 0x7169763a, 0x74578814, 0x74d1c4ef, 0x75dd5d19, 0x755b11e2, 0x77c46ef5, 0x7742220e, 0x764ebbf8, 0x76c8f703, 0x633f964d, 0x63b9dab6, 0x62b54340, 0x62330fbb, 0x60ac70ac, 0x602a3c57, 0x6126a5a1, 0x61a0e95a, 0x649e1774, 0x64185b8f, 0x6514c279, 0x65928e82, 0x670df195, 0x678bbd6e, 0x66872498, 0x66016863, 0x6cfad8c4, 0x6c7c943f, 0x6d700dc9, 0x6df64132, 0x6f693e25, 0x6fef72de, 0x6ee3eb28, 0x6e65a7d3, 0x6b5b59fd, 0x6bdd1506, 0x6ad18cf0, 0x6a57c00b, 0x68c8bf1c, 0x684ef3e7, 0x69426a11, 0x69c426ea, 0x422ae476, 0x42aca88d, 0x43a0317b, 0x43267d80, 0x41b90297, 0x413f4e6c, 0x4033d79a, 0x40b59b61, 0x458b654f, 0x450d29b4, 0x4401b042, 0x4487fcb9, 0x461883ae, 0x469ecf55, 0x479256a3, 0x47141a58, 0x4defaaff, 0x4d69e604, 0x4c657ff2, 0x4ce33309, 0x4e7c4c1e, 0x4efa00e5, 0x4ff69913, 0x4f70d5e8, 0x4a4e2bc6, 0x4ac8673d, 0x4bc4fecb, 0x4b42b230, 0x49ddcd27, 0x495b81dc, 0x4857182a, 0x48d154d1, 0x5d26359f, 0x5da07964, 0x5cace092, 0x5c2aac69, 0x5eb5d37e, 0x5e339f85, 0x5f3f0673, 0x5fb94a88, 0x5a87b4a6, 0x5a01f85d, 0x5b0d61ab, 0x5b8b2d50, 0x59145247, 0x59921ebc, 0x589e874a, 0x5818cbb1, 0x52e37b16, 0x526537ed, 0x5369ae1b, 0x53efe2e0, 0x51709df7, 0x51f6d10c, 0x50fa48fa, 0x507c0401, 0x5542fa2f, 0x55c4b6d4, 0x54c82f22, 0x544e63d9, 0x56d11cce, 0x56575035, 0x575bc9c3, 0x57dd8538]; - -/** - * Internal function to calculate a CRC-24 checksum over a given string (data) - * @param {String | ReadableStream} data Data to create a CRC-24 checksum for - * @returns {Uint8Array | ReadableStream} The CRC-24 checksum - */ -function createcrc24(input) { - let crc = 0xB704CE; - return _webStreamTools2.default.transform(input, value => { - for (let index = 0; index < value.length; index++) { - crc = crc << 8 ^ crc_table[(crc >> 16 ^ value[index]) & 0xff]; - } - }, () => new Uint8Array([crc >> 16, crc >> 8, crc])); -} - -/** - * Verify armored headers. RFC4880, section 6.3: "OpenPGP should consider improperly formatted - * Armor Headers to be corruption of the ASCII Armor." - * @private - * @param {Array} headers Armor headers - */ -function verifyHeaders(headers) { - for (let i = 0; i < headers.length; i++) { - if (!/^([^\s:]|[^\s:][^:]*[^\s:]): .+$/.test(headers[i])) { - throw new Error('Improperly formatted armor header: ' + headers[i]); - } - if (!/^(Version|Comment|MessageID|Hash|Charset): .+$/.test(headers[i])) { - _util2.default.print_debug_error(new Error('Unknown header: ' + headers[i])); - } - } -} - -/** - * Splits a message into two parts, the body and the checksum. This is an internal function - * @param {String} text OpenPGP armored message part - * @returns {Object} An object with attribute "body" containing the body - * and an attribute "checksum" containing the checksum. - */ -function splitChecksum(text) { - let body = text; - let checksum = ""; - - const lastEquals = text.lastIndexOf("="); - - if (lastEquals >= 0 && lastEquals !== text.length - 1) { - // '=' as the last char means no checksum - body = text.slice(0, lastEquals); - checksum = text.slice(lastEquals + 1).substr(0, 4); - } - - return { body: body, checksum: checksum }; -} - -/** - * DeArmor an OpenPGP armored message; verify the checksum and return - * the encoded bytes - * @param {String} text OpenPGP armored message - * @returns {Promise} An object with attribute "text" containing the message text, - * an attribute "data" containing a stream of bytes and "type" for the ASCII armor type - * @async - * @static - */ -function dearmor(input) { - return new Promise(async (resolve, reject) => { - try { - const reSplit = /^-----[^-]+-----$/m; - const reEmptyLine = /^[ \f\r\t\u00a0\u2000-\u200a\u202f\u205f\u3000]*$/; - - let type; - const headers = []; - let lastHeaders = headers; - let headersDone; - let text = []; - let textDone; - let checksum; - let data = _base2.default.decode(_webStreamTools2.default.transformPair(input, async (readable, writable) => { - const reader = _webStreamTools2.default.getReader(readable); - try { - while (true) { - let line = await reader.readLine(); - if (line === undefined) { - throw new Error('Misformed armored text'); - } - // remove trailing whitespace at end of lines - line = _util2.default.removeTrailingSpaces(line.replace(/[\r\n]/g, '')); - if (!type) { - if (reSplit.test(line)) { - type = getType(line); - } - } else if (!headersDone) { - if (reSplit.test(line)) { - reject(new Error('Mandatory blank line missing between armor headers and armor data')); - } - if (!reEmptyLine.test(line)) { - lastHeaders.push(line); - } else { - verifyHeaders(lastHeaders); - headersDone = true; - if (textDone || type !== 2) { - resolve({ text, data, headers, type }); - break; - } - } - } else if (!textDone && type === 2) { - if (!reSplit.test(line)) { - // Reverse dash-escaping for msg - text.push(line.replace(/^- /, '')); - } else { - text = text.join('\r\n'); - textDone = true; - verifyHeaders(lastHeaders); - lastHeaders = []; - headersDone = false; - } - } - } - } catch (e) { - reject(e); - return; - } - const writer = _webStreamTools2.default.getWriter(writable); - try { - while (true) { - await writer.ready; - - var _ref = await reader.read(); - - const done = _ref.done, - value = _ref.value; - - if (done) { - throw new Error('Misformed armored text'); - } - const line = value + ''; - if (line.indexOf('=') === -1 && line.indexOf('-') === -1) { - await writer.write(line); - } else { - let remainder = await reader.readToEnd(); - if (!remainder.length) remainder = ''; - remainder = line + remainder; - remainder = _util2.default.removeTrailingSpaces(remainder.replace(/\r/g, '')); - const parts = remainder.split(reSplit); - if (parts.length === 1) { - throw new Error('Misformed armored text'); - } - const split = splitChecksum(parts[0].slice(0, -1)); - checksum = split.checksum; - await writer.write(split.body); - break; - } - } - await writer.ready; - await writer.close(); - } catch (e) { - await writer.abort(e); - } - })); - data = _webStreamTools2.default.transformPair(data, async (readable, writable) => { - const checksumVerified = getCheckSum(_webStreamTools2.default.passiveClone(readable)); - await _webStreamTools2.default.pipe(readable, writable, { - preventClose: true - }); - const writer = _webStreamTools2.default.getWriter(writable); - try { - const checksumVerifiedString = await _webStreamTools2.default.readToEnd(checksumVerified); - if (checksum !== checksumVerifiedString && (checksum || _config2.default.checksum_required)) { - throw new Error("Ascii armor integrity check on message failed: '" + checksum + "' should be '" + checksumVerifiedString + "'"); - } - await writer.ready; - await writer.close(); - } catch (e) { - await writer.abort(e); - } - }); - } catch (e) { - reject(e); - } - }); -} - -/** - * Armor an OpenPGP binary packet block - * @param {Integer} messagetype type of the message - * @param body - * @param {Integer} partindex - * @param {Integer} parttotal - * @param {String} customComment (optional) additional comment to add to the armored string - * @returns {String | ReadableStream} Armored text - * @static - */ -function armor(messagetype, body, partindex, parttotal, customComment) { - let text; - let hash; - if (messagetype === _enums2.default.armor.signed) { - text = body.text; - hash = body.hash; - body = body.data; - } - const bodyClone = _webStreamTools2.default.passiveClone(body); - const result = []; - switch (messagetype) { - case _enums2.default.armor.multipart_section: - result.push("-----BEGIN PGP MESSAGE, PART " + partindex + "/" + parttotal + "-----\r\n"); - result.push(addheader(customComment)); - result.push(_base2.default.encode(body)); - result.push("\r\n=", getCheckSum(bodyClone), "\r\n"); - result.push("-----END PGP MESSAGE, PART " + partindex + "/" + parttotal + "-----\r\n"); - break; - case _enums2.default.armor.multipart_last: - result.push("-----BEGIN PGP MESSAGE, PART " + partindex + "-----\r\n"); - result.push(addheader(customComment)); - result.push(_base2.default.encode(body)); - result.push("\r\n=", getCheckSum(bodyClone), "\r\n"); - result.push("-----END PGP MESSAGE, PART " + partindex + "-----\r\n"); - break; - case _enums2.default.armor.signed: - result.push("\r\n-----BEGIN PGP SIGNED MESSAGE-----\r\n"); - result.push("Hash: " + hash + "\r\n\r\n"); - result.push(text.replace(/^-/mg, "- -")); - result.push("\r\n-----BEGIN PGP SIGNATURE-----\r\n"); - result.push(addheader(customComment)); - result.push(_base2.default.encode(body)); - result.push("\r\n=", getCheckSum(bodyClone), "\r\n"); - result.push("-----END PGP SIGNATURE-----\r\n"); - break; - case _enums2.default.armor.message: - result.push("-----BEGIN PGP MESSAGE-----\r\n"); - result.push(addheader(customComment)); - result.push(_base2.default.encode(body)); - result.push("\r\n=", getCheckSum(bodyClone), "\r\n"); - result.push("-----END PGP MESSAGE-----\r\n"); - break; - case _enums2.default.armor.public_key: - result.push("-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n"); - result.push(addheader(customComment)); - result.push(_base2.default.encode(body)); - result.push("\r\n=", getCheckSum(bodyClone), "\r\n"); - result.push("-----END PGP PUBLIC KEY BLOCK-----\r\n"); - break; - case _enums2.default.armor.private_key: - result.push("-----BEGIN PGP PRIVATE KEY BLOCK-----\r\n"); - result.push(addheader(customComment)); - result.push(_base2.default.encode(body)); - result.push("\r\n=", getCheckSum(bodyClone), "\r\n"); - result.push("-----END PGP PRIVATE KEY BLOCK-----\r\n"); - break; - case _enums2.default.armor.signature: - result.push("-----BEGIN PGP SIGNATURE-----\r\n"); - result.push(addheader(customComment)); - result.push(_base2.default.encode(body)); - result.push("\r\n=", getCheckSum(bodyClone), "\r\n"); - result.push("-----END PGP SIGNATURE-----\r\n"); - break; - } - - return _util2.default.concat(result); -} - -exports.default = { - encode: armor, - decode: dearmor -}; - -},{"../config":79,"../enums.js":113,"../util":152,"./base64.js":112,"web-stream-tools":75}],112:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _webStreamTools = require('web-stream-tools'); - -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const b64s = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; // Standard radix-64 -/* OpenPGP radix-64/base64 string encoding/decoding - * Copyright 2005 Herbert Hanewinkel, www.haneWIN.de - * version 1.0, check www.haneWIN.de for the latest version - * - * This software is provided as-is, without express or implied warranty. - * Permission to use, copy, modify, distribute or sell this software, with or - * without fee, for any purpose and by any individual or organization, is hereby - * granted, provided that the above copyright notice and this paragraph appear - * in all copies. Distribution as a part of an application or binary must - * include the above copyright notice in the documentation and/or other materials - * provided with the application or distribution. - */ - -/** - * @requires web-stream-tools - * @module encoding/base64 - */ - -const b64u = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'; // URL-safe radix-64 - -const b64toByte = []; -for (let i = 0; i < b64s.length; i++) { - b64toByte[b64s.charCodeAt(i)] = i; -} -b64toByte[b64u.charCodeAt(62)] = 62; -b64toByte[b64u.charCodeAt(63)] = 63; - -/** - * Convert binary array to radix-64 - * @param {Uint8Array | ReadableStream} t Uint8Array to convert - * @param {bool} u if true, output is URL-safe - * @returns {String | ReadableStream} radix-64 version of input string - * @static - */ -function s2r(t, u = false) { - // TODO check btoa alternative - const b64 = u ? b64u : b64s; - let a; - let c; - - let l = 0; - let s = 0; - - return _webStreamTools2.default.transform(t, value => { - const r = []; - const tl = value.length; - for (let n = 0; n < tl; n++) { - if (l && l % 60 === 0 && !u) { - r.push("\r\n"); - } - c = value[n]; - if (s === 0) { - r.push(b64.charAt(c >> 2 & 63)); - a = (c & 3) << 4; - } else if (s === 1) { - r.push(b64.charAt(a | c >> 4 & 15)); - a = (c & 15) << 2; - } else if (s === 2) { - r.push(b64.charAt(a | c >> 6 & 3)); - l += 1; - if (l % 60 === 0 && !u) { - r.push("\r\n"); - } - r.push(b64.charAt(c & 63)); - } - l += 1; - s += 1; - if (s === 3) { - s = 0; - } - } - return r.join(''); - }, () => { - const r = []; - if (s > 0) { - r.push(b64.charAt(a)); - l += 1; - if (l % 60 === 0 && !u) { - r.push("\r\n"); - } - if (!u) { - r.push('='); - l += 1; - } - } - if (s === 1 && !u) { - if (l % 60 === 0 && !u) { - r.push("\r\n"); - } - r.push('='); - } - return r.join(''); - }); -} - -/** - * Convert radix-64 to binary array - * @param {String | ReadableStream} t radix-64 string to convert - * @param {bool} u if true, input is interpreted as URL-safe - * @returns {Uint8Array | ReadableStream} binary array version of input string - * @static - */ -function r2s(t, u) { - // TODO check atob alternative - let c; - - let s = 0; - let a = 0; - - return _webStreamTools2.default.transform(t, value => { - const tl = value.length; - const r = new Uint8Array(Math.ceil(0.75 * tl)); - let index = 0; - for (let n = 0; n < tl; n++) { - c = b64toByte[value.charCodeAt(n)]; - if (c >= 0) { - if (s) { - r[index++] = a | c >> 6 - s & 255; - } - s = s + 2 & 7; - a = c << s & 255; - } - } - return r.subarray(0, index); - }); -} - -exports.default = { - encode: s2r, - decode: r2s -}; - -},{"web-stream-tools":75}],113:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -/** - * @module enums - */ - -const byValue = Symbol('byValue'); - -exports.default = { - - /** Maps curve names under various standards to one - * @see {@link https://wiki.gnupg.org/ECC|ECC - GnuPG wiki} - * @enum {String} - * @readonly - */ - curve: { - /** NIST P-256 Curve */ - "p256": "p256", - "P-256": "p256", - "secp256r1": "p256", - "prime256v1": "p256", - "1.2.840.10045.3.1.7": "p256", - "2a8648ce3d030107": "p256", - "2A8648CE3D030107": "p256", - - /** NIST P-384 Curve */ - "p384": "p384", - "P-384": "p384", - "secp384r1": "p384", - "1.3.132.0.34": "p384", - "2b81040022": "p384", - "2B81040022": "p384", - - /** NIST P-521 Curve */ - "p521": "p521", - "P-521": "p521", - "secp521r1": "p521", - "1.3.132.0.35": "p521", - "2b81040023": "p521", - "2B81040023": "p521", - - /** SECG SECP256k1 Curve */ - "secp256k1": "secp256k1", - "1.3.132.0.10": "secp256k1", - "2b8104000a": "secp256k1", - "2B8104000A": "secp256k1", - - /** Ed25519 */ - "ED25519": "ed25519", - "ed25519": "ed25519", - "Ed25519": "ed25519", - "1.3.6.1.4.1.11591.15.1": "ed25519", - "2b06010401da470f01": "ed25519", - "2B06010401DA470F01": "ed25519", - - /** Curve25519 */ - "X25519": "curve25519", - "cv25519": "curve25519", - "curve25519": "curve25519", - "Curve25519": "curve25519", - "1.3.6.1.4.1.3029.1.5.1": "curve25519", - "2b060104019755010501": "curve25519", - "2B060104019755010501": "curve25519", - - /** BrainpoolP256r1 Curve */ - "brainpoolP256r1": "brainpoolP256r1", - "1.3.36.3.3.2.8.1.1.7": "brainpoolP256r1", - "2b2403030208010107": "brainpoolP256r1", - "2B2403030208010107": "brainpoolP256r1", - - /** BrainpoolP384r1 Curve */ - "brainpoolP384r1": "brainpoolP384r1", - "1.3.36.3.3.2.8.1.1.11": "brainpoolP384r1", - "2b240303020801010b": "brainpoolP384r1", - "2B240303020801010B": "brainpoolP384r1", - - /** BrainpoolP512r1 Curve */ - "brainpoolP512r1": "brainpoolP512r1", - "1.3.36.3.3.2.8.1.1.13": "brainpoolP512r1", - "2b240303020801010d": "brainpoolP512r1", - "2B240303020801010D": "brainpoolP512r1" - }, - - /** A string to key specifier type - * @enum {Integer} - * @readonly - */ - s2k: { - simple: 0, - salted: 1, - iterated: 3, - gnu: 101 - }, - - /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-9.1|RFC4880bis-04, section 9.1} - * @enum {Integer} - * @readonly - */ - publicKey: { - /** RSA (Encrypt or Sign) [HAC] */ - rsa_encrypt_sign: 1, - /** RSA (Encrypt only) [HAC] */ - rsa_encrypt: 2, - /** RSA (Sign only) [HAC] */ - rsa_sign: 3, - /** Elgamal (Encrypt only) [ELGAMAL] [HAC] */ - elgamal: 16, - /** DSA (Sign only) [FIPS186] [HAC] */ - dsa: 17, - /** ECDH (Encrypt only) [RFC6637] */ - ecdh: 18, - /** ECDSA (Sign only) [RFC6637] */ - ecdsa: 19, - /** EdDSA (Sign only) - * [{@link https://tools.ietf.org/html/draft-koch-eddsa-for-openpgp-04|Draft RFC}] */ - eddsa: 22, - /** Reserved for AEDH */ - aedh: 23, - /** Reserved for AEDSA */ - aedsa: 24 - }, - - /** {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC4880, section 9.2} - * @enum {Integer} - * @readonly - */ - symmetric: { - plaintext: 0, - /** Not implemented! */ - idea: 1, - '3des': 2, - tripledes: 2, - cast5: 3, - blowfish: 4, - aes128: 7, - aes192: 8, - aes256: 9, - twofish: 10 - }, - - /** {@link https://tools.ietf.org/html/rfc4880#section-9.3|RFC4880, section 9.3} - * @enum {Integer} - * @readonly - */ - compression: { - uncompressed: 0, - /** RFC1951 */ - zip: 1, - /** RFC1950 */ - zlib: 2, - bzip2: 3 - }, - - /** {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC4880, section 9.4} - * @enum {Integer} - * @readonly - */ - hash: { - md5: 1, - sha1: 2, - ripemd: 3, - sha256: 8, - sha384: 9, - sha512: 10, - sha224: 11 - }, - - /** A list of hash names as accepted by webCrypto functions. - * {@link https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest|Parameters, algo} - * @enum {String} - */ - webHash: { - 'SHA-1': 2, - 'SHA-256': 8, - 'SHA-384': 9, - 'SHA-512': 10 - }, - - /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-9.6|RFC4880bis-04, section 9.6} - * @enum {Integer} - * @readonly - */ - aead: { - eax: 1, - ocb: 2, - experimental_gcm: 100 // Private algorithm - }, - - /** A list of packet types and numeric tags associated with them. - * @enum {Integer} - * @readonly - */ - packet: { - publicKeyEncryptedSessionKey: 1, - signature: 2, - symEncryptedSessionKey: 3, - onePassSignature: 4, - secretKey: 5, - publicKey: 6, - secretSubkey: 7, - compressed: 8, - symmetricallyEncrypted: 9, - marker: 10, - literal: 11, - trust: 12, - userid: 13, - publicSubkey: 14, - userAttribute: 17, - symEncryptedIntegrityProtected: 18, - modificationDetectionCode: 19, - symEncryptedAEADProtected: 20 // see IETF draft: https://tools.ietf.org/html/draft-ford-openpgp-format-00#section-2.1 - }, - - /** Data types in the literal packet - * @enum {Integer} - * @readonly - */ - literal: { - /** Binary data 'b' */ - binary: 'b'.charCodeAt(), - /** Text data 't' */ - text: 't'.charCodeAt(), - /** Utf8 data 'u' */ - utf8: 'u'.charCodeAt(), - /** MIME message body part 'm' */ - mime: 'm'.charCodeAt() - }, - - /** One pass signature packet type - * @enum {Integer} - * @readonly - */ - signature: { - /** 0x00: Signature of a binary document. */ - binary: 0, - /** 0x01: Signature of a canonical text document. - * - * Canonicalyzing the document by converting line endings. */ - text: 1, - /** 0x02: Standalone signature. - * - * This signature is a signature of only its own subpacket contents. - * It is calculated identically to a signature over a zero-lengh - * binary document. Note that it doesn't make sense to have a V3 - * standalone signature. */ - standalone: 2, - /** 0x10: Generic certification of a User ID and Public-Key packet. - * - * The issuer of this certification does not make any particular - * assertion as to how well the certifier has checked that the owner - * of the key is in fact the person described by the User ID. */ - cert_generic: 16, - /** 0x11: Persona certification of a User ID and Public-Key packet. - * - * The issuer of this certification has not done any verification of - * the claim that the owner of this key is the User ID specified. */ - cert_persona: 17, - /** 0x12: Casual certification of a User ID and Public-Key packet. - * - * The issuer of this certification has done some casual - * verification of the claim of identity. */ - cert_casual: 18, - /** 0x13: Positive certification of a User ID and Public-Key packet. - * - * The issuer of this certification has done substantial - * verification of the claim of identity. - * - * Most OpenPGP implementations make their "key signatures" as 0x10 - * certifications. Some implementations can issue 0x11-0x13 - * certifications, but few differentiate between the types. */ - cert_positive: 19, - /** 0x30: Certification revocation signature - * - * This signature revokes an earlier User ID certification signature - * (signature class 0x10 through 0x13) or direct-key signature - * (0x1F). It should be issued by the same key that issued the - * revoked signature or an authorized revocation key. The signature - * is computed over the same data as the certificate that it - * revokes, and should have a later creation date than that - * certificate. */ - cert_revocation: 48, - /** 0x18: Subkey Binding Signature - * - * This signature is a statement by the top-level signing key that - * indicates that it owns the subkey. This signature is calculated - * directly on the primary key and subkey, and not on any User ID or - * other packets. A signature that binds a signing subkey MUST have - * an Embedded Signature subpacket in this binding signature that - * contains a 0x19 signature made by the signing subkey on the - * primary key and subkey. */ - subkey_binding: 24, - /** 0x19: Primary Key Binding Signature - * - * This signature is a statement by a signing subkey, indicating - * that it is owned by the primary key and subkey. This signature - * is calculated the same way as a 0x18 signature: directly on the - * primary key and subkey, and not on any User ID or other packets. - * - * When a signature is made over a key, the hash data starts with the - * octet 0x99, followed by a two-octet length of the key, and then body - * of the key packet. (Note that this is an old-style packet header for - * a key packet with two-octet length.) A subkey binding signature - * (type 0x18) or primary key binding signature (type 0x19) then hashes - * the subkey using the same format as the main key (also using 0x99 as - * the first octet). */ - key_binding: 25, - /** 0x1F: Signature directly on a key - * - * This signature is calculated directly on a key. It binds the - * information in the Signature subpackets to the key, and is - * appropriate to be used for subpackets that provide information - * about the key, such as the Revocation Key subpacket. It is also - * appropriate for statements that non-self certifiers want to make - * about the key itself, rather than the binding between a key and a - * name. */ - key: 31, - /** 0x20: Key revocation signature - * - * The signature is calculated directly on the key being revoked. A - * revoked key is not to be used. Only revocation signatures by the - * key being revoked, or by an authorized revocation key, should be - * considered valid revocation signatures.a */ - key_revocation: 32, - /** 0x28: Subkey revocation signature - * - * The signature is calculated directly on the subkey being revoked. - * A revoked subkey is not to be used. Only revocation signatures - * by the top-level signature key that is bound to this subkey, or - * by an authorized revocation key, should be considered valid - * revocation signatures. - * - * Key revocation signatures (types 0x20 and 0x28) - * hash only the key being revoked. */ - subkey_revocation: 40, - /** 0x40: Timestamp signature. - * This signature is only meaningful for the timestamp contained in - * it. */ - timestamp: 64, - /** 0x50: Third-Party Confirmation signature. - * - * This signature is a signature over some other OpenPGP Signature - * packet(s). It is analogous to a notary seal on the signed data. - * A third-party signature SHOULD include Signature Target - * subpacket(s) to give easy identification. Note that we really do - * mean SHOULD. There are plausible uses for this (such as a blind - * party that only sees the signature, not the key or source - * document) that cannot include a target subpacket. */ - third_party: 80 - }, - - /** Signature subpacket type - * @enum {Integer} - * @readonly - */ - signatureSubpacket: { - signature_creation_time: 2, - signature_expiration_time: 3, - exportable_certification: 4, - trust_signature: 5, - regular_expression: 6, - revocable: 7, - key_expiration_time: 9, - placeholder_backwards_compatibility: 10, - preferred_symmetric_algorithms: 11, - revocation_key: 12, - issuer: 16, - notation_data: 20, - preferred_hash_algorithms: 21, - preferred_compression_algorithms: 22, - key_server_preferences: 23, - preferred_key_server: 24, - primary_user_id: 25, - policy_uri: 26, - key_flags: 27, - signers_user_id: 28, - reason_for_revocation: 29, - features: 30, - signature_target: 31, - embedded_signature: 32, - issuer_fingerprint: 33, - preferred_aead_algorithms: 34 - }, - - /** Key flags - * @enum {Integer} - * @readonly - */ - keyFlags: { - /** 0x01 - This key may be used to certify other keys. */ - certify_keys: 1, - /** 0x02 - This key may be used to sign data. */ - sign_data: 2, - /** 0x04 - This key may be used to encrypt communications. */ - encrypt_communication: 4, - /** 0x08 - This key may be used to encrypt storage. */ - encrypt_storage: 8, - /** 0x10 - The private component of this key may have been split - * by a secret-sharing mechanism. */ - split_private_key: 16, - /** 0x20 - This key may be used for authentication. */ - authentication: 32, - /** 0x80 - The private component of this key may be in the - * possession of more than one person. */ - shared_private_key: 128 - }, - - /** Key status - * @enum {Integer} - * @readonly - */ - keyStatus: { - invalid: 0, - expired: 1, - revoked: 2, - valid: 3, - no_self_cert: 4 - }, - - /** Armor type - * @enum {Integer} - * @readonly - */ - armor: { - multipart_section: 0, - multipart_last: 1, - signed: 2, - message: 3, - public_key: 4, - private_key: 5, - signature: 6 - }, - - /** {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.23|RFC4880, section 5.2.3.23} - * @enum {Integer} - * @readonly - */ - reasonForRevocation: { - /** No reason specified (key revocations or cert revocations) */ - no_reason: 0, - /** Key is superseded (key revocations) */ - key_superseded: 1, - /** Key material has been compromised (key revocations) */ - key_compromised: 2, - /** Key is retired and no longer used (key revocations) */ - key_retired: 3, - /** User ID information is no longer valid (cert revocations) */ - userid_invalid: 32 - }, - - /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.2.3.25|RFC4880bis-04, section 5.2.3.25} - * @enum {Integer} - * @readonly - */ - features: { - /** 0x01 - Modification Detection (packets 18 and 19) */ - modification_detection: 1, - /** 0x02 - AEAD Encrypted Data Packet (packet 20) and version 5 - * Symmetric-Key Encrypted Session Key Packets (packet 3) */ - aead: 2, - /** 0x04 - Version 5 Public-Key Packet format and corresponding new - * fingerprint format */ - v5_keys: 4 - }, - - /** Asserts validity and converts from string/integer to integer. */ - write: function write(type, e) { - if (typeof e === 'number') { - e = this.read(type, e); - } - - if (type[e] !== undefined) { - return type[e]; - } - - throw new Error('Invalid enum value.'); - }, - - /** Converts from an integer to string. */ - read: function read(type, e) { - if (!type[byValue]) { - type[byValue] = []; - Object.entries(type).forEach(([key, value]) => { - type[byValue][value] = key; - }); - } - - if (type[byValue][e] !== undefined) { - return type[byValue][e]; - } - - throw new Error('Invalid enum value.'); - } - -}; - -},{}],114:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _config = require('./config'); - -var _config2 = _interopRequireDefault(_config); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Initialize the HKP client and configure it with the key server url and fetch function. - * @constructor - * @param {String} keyServerBaseUrl (optional) The HKP key server base url including - * the protocol to use, e.g. 'https://pgp.mit.edu'; defaults to - * openpgp.config.keyserver (https://keyserver.ubuntu.com) - */ -function HKP(keyServerBaseUrl) { - this._baseUrl = keyServerBaseUrl || _config2.default.keyserver; - this._fetch = typeof window !== 'undefined' ? window.fetch : require('node-fetch'); -} - -/** - * Search for a public key on the key server either by key ID or part of the user ID. - * @param {String} options.keyID The long public key ID. - * @param {String} options.query This can be any part of the key user ID such as name - * or email address. - * @returns {Promise} The ascii armored public key. - * @async - */ -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2015 Tankred Hase -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @fileoverview This class implements a client for the OpenPGP HTTP Keyserver Protocol (HKP) - * in order to lookup and upload keys on standard public key servers. - * @module hkp - */ - -HKP.prototype.lookup = function (options) { - let uri = this._baseUrl + '/pks/lookup?op=get&options=mr&search='; - const fetch = this._fetch; - - if (options.keyId) { - uri += '0x' + encodeURIComponent(options.keyId); - } else if (options.query) { - uri += encodeURIComponent(options.query); - } else { - throw new Error('You must provide a query parameter!'); - } - - return fetch(uri).then(function (response) { - if (response.status === 200) { - return response.text(); - } - }).then(function (publicKeyArmored) { - if (!publicKeyArmored || publicKeyArmored.indexOf('-----END PGP PUBLIC KEY BLOCK-----') < 0) { - return; - } - return publicKeyArmored.trim(); - }); -}; - -/** - * Upload a public key to the server. - * @param {String} publicKeyArmored An ascii armored public key to be uploaded. - * @returns {Promise} - * @async - */ -HKP.prototype.upload = function (publicKeyArmored) { - const uri = this._baseUrl + '/pks/add'; - const fetch = this._fetch; - - return fetch(uri, { - method: 'post', - headers: { - 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' - }, - body: 'keytext=' + encodeURIComponent(publicKeyArmored) - }); -}; - -exports.default = HKP; - -},{"./config":79,"node-fetch":"node-fetch"}],115:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.WKD = exports.HKP = exports.AsyncProxy = exports.Keyring = exports.crypto = exports.config = exports.enums = exports.armor = exports.stream = exports.OID = exports.KDFParams = exports.ECDHSymmetricKey = exports.Keyid = exports.S2K = exports.MPI = exports.packet = exports.util = exports.cleartext = exports.message = exports.signature = exports.key = exports.destroyWorker = exports.getWorker = exports.initWorker = exports.decryptSessionKeys = exports.encryptSessionKey = exports.decryptKey = exports.revokeKey = exports.reformatKey = exports.generateKey = exports.verify = exports.sign = exports.decrypt = exports.encrypt = undefined; - -var _openpgp = require('./openpgp'); - -Object.defineProperty(exports, 'encrypt', { - enumerable: true, - get: function get() { - return _openpgp.encrypt; - } -}); -Object.defineProperty(exports, 'decrypt', { - enumerable: true, - get: function get() { - return _openpgp.decrypt; - } -}); -Object.defineProperty(exports, 'sign', { - enumerable: true, - get: function get() { - return _openpgp.sign; - } -}); -Object.defineProperty(exports, 'verify', { - enumerable: true, - get: function get() { - return _openpgp.verify; - } -}); -Object.defineProperty(exports, 'generateKey', { - enumerable: true, - get: function get() { - return _openpgp.generateKey; - } -}); -Object.defineProperty(exports, 'reformatKey', { - enumerable: true, - get: function get() { - return _openpgp.reformatKey; - } -}); -Object.defineProperty(exports, 'revokeKey', { - enumerable: true, - get: function get() { - return _openpgp.revokeKey; - } -}); -Object.defineProperty(exports, 'decryptKey', { - enumerable: true, - get: function get() { - return _openpgp.decryptKey; - } -}); -Object.defineProperty(exports, 'encryptSessionKey', { - enumerable: true, - get: function get() { - return _openpgp.encryptSessionKey; - } -}); -Object.defineProperty(exports, 'decryptSessionKeys', { - enumerable: true, - get: function get() { - return _openpgp.decryptSessionKeys; - } -}); -Object.defineProperty(exports, 'initWorker', { - enumerable: true, - get: function get() { - return _openpgp.initWorker; - } -}); -Object.defineProperty(exports, 'getWorker', { - enumerable: true, - get: function get() { - return _openpgp.getWorker; - } -}); -Object.defineProperty(exports, 'destroyWorker', { - enumerable: true, - get: function get() { - return _openpgp.destroyWorker; - } -}); - -var _util = require('./util'); - -Object.defineProperty(exports, 'util', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_util).default; - } -}); - -var _packet = require('./packet'); - -Object.defineProperty(exports, 'packet', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_packet).default; - } -}); - -var _mpi = require('./type/mpi'); - -Object.defineProperty(exports, 'MPI', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_mpi).default; - } -}); - -var _s2k = require('./type/s2k'); - -Object.defineProperty(exports, 'S2K', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_s2k).default; - } -}); - -var _keyid = require('./type/keyid'); - -Object.defineProperty(exports, 'Keyid', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_keyid).default; - } -}); - -var _ecdh_symkey = require('./type/ecdh_symkey'); - -Object.defineProperty(exports, 'ECDHSymmetricKey', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_ecdh_symkey).default; - } -}); - -var _kdf_params = require('./type/kdf_params'); - -Object.defineProperty(exports, 'KDFParams', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_kdf_params).default; - } -}); - -var _oid = require('./type/oid'); - -Object.defineProperty(exports, 'OID', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_oid).default; - } -}); - -var _webStreamTools = require('web-stream-tools'); - -Object.defineProperty(exports, 'stream', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_webStreamTools).default; - } -}); - -var _armor = require('./encoding/armor'); - -Object.defineProperty(exports, 'armor', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_armor).default; - } -}); - -var _enums = require('./enums'); - -Object.defineProperty(exports, 'enums', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_enums).default; - } -}); - -var _config = require('./config/config'); - -Object.defineProperty(exports, 'config', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_config).default; - } -}); - -var _crypto = require('./crypto'); - -Object.defineProperty(exports, 'crypto', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_crypto).default; - } -}); - -var _keyring = require('./keyring'); - -Object.defineProperty(exports, 'Keyring', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_keyring).default; - } -}); - -var _async_proxy = require('./worker/async_proxy'); - -Object.defineProperty(exports, 'AsyncProxy', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_async_proxy).default; - } -}); - -var _hkp = require('./hkp'); - -Object.defineProperty(exports, 'HKP', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_hkp).default; - } -}); - -var _wkd = require('./wkd'); - -Object.defineProperty(exports, 'WKD', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_wkd).default; - } -}); - -var openpgp = _interopRequireWildcard(_openpgp); - -var _key = require('./key'); - -var keyMod = _interopRequireWildcard(_key); - -var _signature = require('./signature'); - -var signatureMod = _interopRequireWildcard(_signature); - -var _message = require('./message'); - -var messageMod = _interopRequireWildcard(_message); - -var _cleartext = require('./cleartext'); - -var cleartextMod = _interopRequireWildcard(_cleartext); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -exports.default = openpgp; - -/** - * Export each high level api function separately. - * Usage: - * - * import { encryptMessage } from 'openpgp.js' - * encryptMessage(keys, text) - */ -/* eslint-disable import/newline-after-import, import/first */ - -/** - * Export high level api as default. - * Usage: - * - * import openpgp from 'openpgp.js' - * openpgp.encryptMessage(keys, text) - */ - - -/** - * @see module:key - * @name module:openpgp.key - */ - -const key = exports.key = keyMod; - -/** - * @see module:signature - * @name module:openpgp.signature - */ -const signature = exports.signature = signatureMod; - -/** - * @see module:message - * @name module:openpgp.message - */ -const message = exports.message = messageMod; - -/** - * @see module:cleartext - * @name module:openpgp.cleartext - */ -const cleartext = exports.cleartext = cleartextMod; - -/** - * @see module:util - * @name module:openpgp.util - */ - -},{"./cleartext":77,"./config/config":78,"./crypto":94,"./encoding/armor":111,"./enums":113,"./hkp":114,"./key":116,"./keyring":117,"./message":120,"./openpgp":121,"./packet":125,"./signature":145,"./type/ecdh_symkey":146,"./type/kdf_params":147,"./type/keyid":148,"./type/mpi":149,"./type/oid":150,"./type/s2k":151,"./util":152,"./wkd":153,"./worker/async_proxy":154,"web-stream-tools":75}],116:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); // GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @requires encoding/armor - * @requires crypto - * @requires packet - * @requires config - * @requires enums - * @requires util - * @module key - */ - -exports.Key = Key; -exports.createSignaturePacket = createSignaturePacket; -exports.read = read; -exports.readArmored = readArmored; -exports.generate = generate; -exports.reformat = reformat; -exports.getPreferredHashAlgo = getPreferredHashAlgo; -exports.getPreferredAlgo = getPreferredAlgo; -exports.isAeadSupported = isAeadSupported; - -var _armor = require('./encoding/armor'); - -var _armor2 = _interopRequireDefault(_armor); - -var _crypto = require('./crypto'); - -var _crypto2 = _interopRequireDefault(_crypto); - -var _packet = require('./packet'); - -var _packet2 = _interopRequireDefault(_packet); - -var _config = require('./config'); - -var _config2 = _interopRequireDefault(_config); - -var _enums = require('./enums'); - -var _enums2 = _interopRequireDefault(_enums); - -var _util = require('./util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * @class - * @classdesc Class that represents an OpenPGP key. Must contain a primary key. - * Can contain additional subkeys, signatures, user ids, user attributes. - * @param {module:packet.List} packetlist The packets that form this key - * @borrows module:packet.PublicKey#getKeyId as Key#getKeyId - * @borrows module:packet.PublicKey#getFingerprint as Key#getFingerprint - * @borrows module:packet.PublicKey#hasSameFingerprintAs as Key#hasSameFingerprintAs - * @borrows module:packet.PublicKey#getAlgorithmInfo as Key#getAlgorithmInfo - * @borrows module:packet.PublicKey#getCreationTime as Key#getCreationTime - * @borrows module:packet.PublicKey#isDecrypted as Key#isDecrypted - */ -function Key(packetlist) { - if (!(this instanceof Key)) { - return new Key(packetlist); - } - // same data as in packetlist but in structured form - this.keyPacket = null; - this.revocationSignatures = []; - this.directSignatures = []; - this.users = []; - this.subKeys = []; - this.packetlist2structure(packetlist); - if (!this.keyPacket || !this.users.length) { - throw new Error('Invalid key: need at least key and user ID packet'); - } -} - -Object.defineProperty(Key.prototype, 'primaryKey', { - get() { - return this.keyPacket; - }, - configurable: true, - enumerable: true -}); - -/** - * Transforms packetlist to structured key data - * @param {module:packet.List} packetlist The packets that form a key - */ -Key.prototype.packetlist2structure = function (packetlist) { - let user; - let primaryKeyId; - let subKey; - for (let i = 0; i < packetlist.length; i++) { - switch (packetlist[i].tag) { - case _enums2.default.packet.publicKey: - case _enums2.default.packet.secretKey: - this.keyPacket = packetlist[i]; - primaryKeyId = this.getKeyId(); - break; - case _enums2.default.packet.userid: - case _enums2.default.packet.userAttribute: - user = new User(packetlist[i]); - this.users.push(user); - break; - case _enums2.default.packet.publicSubkey: - case _enums2.default.packet.secretSubkey: - user = null; - subKey = new SubKey(packetlist[i]); - this.subKeys.push(subKey); - break; - case _enums2.default.packet.signature: - switch (packetlist[i].signatureType) { - case _enums2.default.signature.cert_generic: - case _enums2.default.signature.cert_persona: - case _enums2.default.signature.cert_casual: - case _enums2.default.signature.cert_positive: - if (!user) { - _util2.default.print_debug('Dropping certification signatures without preceding user packet'); - continue; - } - if (packetlist[i].issuerKeyId.equals(primaryKeyId)) { - checkRevocationKey(packetlist[i], primaryKeyId); - user.selfCertifications.push(packetlist[i]); - } else { - user.otherCertifications.push(packetlist[i]); - } - break; - case _enums2.default.signature.cert_revocation: - if (user) { - user.revocationSignatures.push(packetlist[i]); - } else { - this.directSignatures.push(packetlist[i]); - } - break; - case _enums2.default.signature.key: - checkRevocationKey(packetlist[i], primaryKeyId); - this.directSignatures.push(packetlist[i]); - break; - case _enums2.default.signature.subkey_binding: - if (!subKey) { - _util2.default.print_debug('Dropping subkey binding signature without preceding subkey packet'); - continue; - } - checkRevocationKey(packetlist[i], primaryKeyId); - subKey.bindingSignatures.push(packetlist[i]); - break; - case _enums2.default.signature.key_revocation: - this.revocationSignatures.push(packetlist[i]); - break; - case _enums2.default.signature.subkey_revocation: - if (!subKey) { - _util2.default.print_debug('Dropping subkey revocation signature without preceding subkey packet'); - continue; - } - subKey.revocationSignatures.push(packetlist[i]); - break; - } - break; - } - } -}; - -/** - * Transforms structured key data to packetlist - * @returns {module:packet.List} The packets that form a key - */ -Key.prototype.toPacketlist = function () { - const packetlist = new _packet2.default.List(); - packetlist.push(this.keyPacket); - packetlist.concat(this.revocationSignatures); - packetlist.concat(this.directSignatures); - this.users.map(user => packetlist.concat(user.toPacketlist())); - this.subKeys.map(subKey => packetlist.concat(subKey.toPacketlist())); - return packetlist; -}; - -/** - * Returns an array containing all public or private subkeys matching keyId; - * If keyId is not present, returns all subkeys. - * @param {type/keyid} keyId - * @returns {Array} - */ -Key.prototype.getSubkeys = function (keyId = null) { - const subKeys = []; - this.subKeys.forEach(subKey => { - if (!keyId || subKey.getKeyId().equals(keyId, true)) { - subKeys.push(subKey); - } - }); - return subKeys; -}; - -/** - * Returns an array containing all public or private keys matching keyId. - * If keyId is not present, returns all keys starting with the primary key. - * @param {type/keyid} keyId - * @returns {Array} - */ -Key.prototype.getKeys = function (keyId = null) { - const keys = []; - if (!keyId || this.getKeyId().equals(keyId, true)) { - keys.push(this); - } - return keys.concat(this.getSubkeys(keyId)); -}; - -/** - * Returns key IDs of all keys - * @returns {Array} - */ -Key.prototype.getKeyIds = function () { - return this.getKeys().map(key => key.getKeyId()); -}; - -/** - * Returns userids - * @returns {Array} array of userids - */ -Key.prototype.getUserIds = function () { - return this.users.map(user => { - return user.userId ? user.userId.userid : null; - }).filter(userid => userid !== null); -}; - -/** - * Returns true if this is a public key - * @returns {Boolean} - */ -Key.prototype.isPublic = function () { - return this.keyPacket.tag === _enums2.default.packet.publicKey; -}; - -/** - * Returns true if this is a private key - * @returns {Boolean} - */ -Key.prototype.isPrivate = function () { - return this.keyPacket.tag === _enums2.default.packet.secretKey; -}; - -/** - * Returns key as public key (shallow copy) - * @returns {module:key.Key} new public Key - */ -Key.prototype.toPublic = function () { - const packetlist = new _packet2.default.List(); - const keyPackets = this.toPacketlist(); - let bytes; - let pubKeyPacket; - let pubSubkeyPacket; - for (let i = 0; i < keyPackets.length; i++) { - switch (keyPackets[i].tag) { - case _enums2.default.packet.secretKey: - bytes = keyPackets[i].writePublicKey(); - pubKeyPacket = new _packet2.default.PublicKey(); - pubKeyPacket.read(bytes); - packetlist.push(pubKeyPacket); - break; - case _enums2.default.packet.secretSubkey: - bytes = keyPackets[i].writePublicKey(); - pubSubkeyPacket = new _packet2.default.PublicSubkey(); - pubSubkeyPacket.read(bytes); - packetlist.push(pubSubkeyPacket); - break; - default: - packetlist.push(keyPackets[i]); - } - } - return new Key(packetlist); -}; - -/** - * Returns ASCII armored text of key - * @returns {ReadableStream} ASCII armor - */ -Key.prototype.armor = function () { - const type = this.isPublic() ? _enums2.default.armor.public_key : _enums2.default.armor.private_key; - return _armor2.default.encode(type, this.toPacketlist().write()); -}; - -/** - * Returns the valid and non-expired signature that has the latest creation date, while ignoring signatures created in the future. - * @param {Array} signatures List of signatures - * @param {Date} date Use the given date instead of the current time - * @returns {Promise} The latest valid signature - * @async - */ -async function getLatestValidSignature(signatures, primaryKey, signatureType, dataToVerify, date = new Date()) { - let signature; - for (let i = signatures.length - 1; i >= 0; i--) { - if ((!signature || signatures[i].created >= signature.created) && - // check binding signature is not expired (ie, check for V4 expiration time) - !signatures[i].isExpired(date) && ( - // check binding signature is verified - signatures[i].verified || (await signatures[i].verify(primaryKey, signatureType, dataToVerify)))) { - signature = signatures[i]; - } - } - return signature; -} - -/** - * Returns last created key or key by given keyId that is available for signing and verification - * @param {module:type/keyid} keyId, optional - * @param {Date} date (optional) use the given date for verification instead of the current time - * @param {Object} userId, optional user ID - * @returns {Promise} key or null if no signing key has been found - * @async - */ -Key.prototype.getSigningKey = async function (keyId = null, date = new Date(), userId = {}) { - const primaryKey = this.keyPacket; - if ((await this.verifyPrimaryKey(date, userId)) === _enums2.default.keyStatus.valid) { - const subKeys = this.subKeys.slice().sort((a, b) => b.keyPacket.created - a.keyPacket.created); - for (let i = 0; i < subKeys.length; i++) { - if (!keyId || subKeys[i].getKeyId().equals(keyId)) { - if ((await subKeys[i].verify(primaryKey, date)) === _enums2.default.keyStatus.valid) { - const dataToVerify = { key: primaryKey, bind: subKeys[i].keyPacket }; - const bindingSignature = await getLatestValidSignature(subKeys[i].bindingSignatures, primaryKey, _enums2.default.signature.subkey_binding, dataToVerify, date); - if (bindingSignature && bindingSignature.embeddedSignature && isValidSigningKeyPacket(subKeys[i].keyPacket, bindingSignature) && (await getLatestValidSignature([bindingSignature.embeddedSignature], subKeys[i].keyPacket, _enums2.default.signature.key_binding, dataToVerify, date))) { - return subKeys[i]; - } - } - } - } - const primaryUser = await this.getPrimaryUser(date, userId); - if (primaryUser && (!keyId || primaryKey.getKeyId().equals(keyId)) && isValidSigningKeyPacket(primaryKey, primaryUser.selfCertification)) { - return this; - } - } - return null; - - function isValidSigningKeyPacket(keyPacket, signature) { - if (!signature.verified || signature.revoked !== false) { - // Sanity check - throw new Error('Signature not verified'); - } - return keyPacket.algorithm !== _enums2.default.read(_enums2.default.publicKey, _enums2.default.publicKey.rsa_encrypt) && keyPacket.algorithm !== _enums2.default.read(_enums2.default.publicKey, _enums2.default.publicKey.elgamal) && keyPacket.algorithm !== _enums2.default.read(_enums2.default.publicKey, _enums2.default.publicKey.ecdh) && (!signature.keyFlags || (signature.keyFlags[0] & _enums2.default.keyFlags.sign_data) !== 0); - } -}; - -/** - * Returns last created key or key by given keyId that is available for encryption or decryption - * @param {module:type/keyid} keyId, optional - * @param {Date} date, optional - * @param {String} userId, optional - * @returns {Promise} key or null if no encryption key has been found - * @async - */ -Key.prototype.getEncryptionKey = async function (keyId, date = new Date(), userId = {}) { - const primaryKey = this.keyPacket; - if ((await this.verifyPrimaryKey(date, userId)) === _enums2.default.keyStatus.valid) { - // V4: by convention subkeys are preferred for encryption service - const subKeys = this.subKeys.slice().sort((a, b) => b.keyPacket.created - a.keyPacket.created); - for (let i = 0; i < subKeys.length; i++) { - if (!keyId || subKeys[i].getKeyId().equals(keyId)) { - if ((await subKeys[i].verify(primaryKey, date)) === _enums2.default.keyStatus.valid) { - const dataToVerify = { key: primaryKey, bind: subKeys[i].keyPacket }; - const bindingSignature = await getLatestValidSignature(subKeys[i].bindingSignatures, primaryKey, _enums2.default.signature.subkey_binding, dataToVerify, date); - if (bindingSignature && isValidEncryptionKeyPacket(subKeys[i].keyPacket, bindingSignature)) { - return subKeys[i]; - } - } - } - } - // if no valid subkey for encryption, evaluate primary key - const primaryUser = await this.getPrimaryUser(date, userId); - if (primaryUser && (!keyId || primaryKey.getKeyId().equals(keyId)) && isValidEncryptionKeyPacket(primaryKey, primaryUser.selfCertification)) { - return this; - } - } - return null; - - function isValidEncryptionKeyPacket(keyPacket, signature) { - if (!signature.verified || signature.revoked !== false) { - // Sanity check - throw new Error('Signature not verified'); - } - return keyPacket.algorithm !== _enums2.default.read(_enums2.default.publicKey, _enums2.default.publicKey.dsa) && keyPacket.algorithm !== _enums2.default.read(_enums2.default.publicKey, _enums2.default.publicKey.rsa_sign) && keyPacket.algorithm !== _enums2.default.read(_enums2.default.publicKey, _enums2.default.publicKey.ecdsa) && keyPacket.algorithm !== _enums2.default.read(_enums2.default.publicKey, _enums2.default.publicKey.eddsa) && (!signature.keyFlags || (signature.keyFlags[0] & _enums2.default.keyFlags.encrypt_communication) !== 0 || (signature.keyFlags[0] & _enums2.default.keyFlags.encrypt_storage) !== 0); - } -}; - -/** - * Encrypts all secret key and subkey packets matching keyId - * @param {String|Array} passphrases - if multiple passphrases, then should be in same order as packets each should encrypt - * @param {module:type/keyid} keyId - * @returns {Promise>} - * @async - */ -Key.prototype.encrypt = async function (passphrases, keyId = null) { - if (!this.isPrivate()) { - throw new Error("Nothing to encrypt in a public key"); - } - - const keys = this.getKeys(keyId); - passphrases = _util2.default.isArray(passphrases) ? passphrases : new Array(keys.length).fill(passphrases); - if (passphrases.length !== keys.length) { - throw new Error("Invalid number of passphrases for key"); - } - - return Promise.all(keys.map(async function (key, i) { - const keyPacket = key.keyPacket; - - await keyPacket.encrypt(passphrases[i]); - keyPacket.clearPrivateParams(); - return keyPacket; - })); -}; - -/** - * Decrypts all secret key and subkey packets matching keyId - * @param {String|Array} passphrases - * @param {module:type/keyid} keyId - * @returns {Promise} true if all matching key and subkey packets decrypted successfully - * @async - */ -Key.prototype.decrypt = async function (passphrases, keyId = null) { - if (!this.isPrivate()) { - throw new Error("Nothing to decrypt in a public key"); - } - passphrases = _util2.default.isArray(passphrases) ? passphrases : [passphrases]; - - const results = await Promise.all(this.getKeys(keyId).map(async function (key) { - let decrypted = false; - let error = null; - await Promise.all(passphrases.map(async function (passphrase) { - try { - await key.keyPacket.decrypt(passphrase); - decrypted = true; - } catch (e) { - error = e; - } - })); - if (!decrypted) { - throw error; - } - return decrypted; - })); - return results.every(result => result === true); -}; - -/** - * Checks if a signature on a key is revoked - * @param {module:packet.SecretKey| - * @param {module:packet.Signature} signature The signature to verify - * @param {module:packet.PublicSubkey| - * module:packet.SecretSubkey| - * module:packet.PublicKey| - * module:packet.SecretKey} key, optional The key to verify the signature - * @param {Date} date Use the given date instead of the current time - * @returns {Promise} True if the certificate is revoked - * @async - */ -Key.prototype.isRevoked = async function (signature, key, date = new Date()) { - return isDataRevoked(this.keyPacket, _enums2.default.signature.key_revocation, { key: this.keyPacket }, this.revocationSignatures, signature, key, date); -}; - -/** - * Verify primary key. Checks for revocation signatures, expiration time - * and valid self signature - * @param {Date} date (optional) use the given date for verification instead of the current time - * @param {Object} userId (optional) user ID - * @returns {Promise} The status of the primary key - * @async - */ -Key.prototype.verifyPrimaryKey = async function (date = new Date(), userId = {}) { - const primaryKey = this.keyPacket; - // check for key revocation signatures - if (await this.isRevoked(null, null, date)) { - return _enums2.default.keyStatus.revoked; - } - // check for at least one self signature. Self signature of user ID not mandatory - // See {@link https://tools.ietf.org/html/rfc4880#section-11.1} - if (!this.users.some(user => user.userId && user.selfCertifications.length)) { - return _enums2.default.keyStatus.no_self_cert; - } - // check for valid, unrevoked, unexpired self signature - - var _ref = (await this.getPrimaryUser(date, userId)) || {}; - - const user = _ref.user, - selfCertification = _ref.selfCertification; - - if (!user) { - return _enums2.default.keyStatus.invalid; - } - // check for expiration time - if (isDataExpired(primaryKey, selfCertification, date)) { - return _enums2.default.keyStatus.expired; - } - return _enums2.default.keyStatus.valid; -}; - -/** - * Returns the latest date when the key can be used for encrypting, signing, or both, depending on the `capabilities` paramater. - * When `capabilities` is null, defaults to returning the expiry date of the primary key. - * Returns null if `capabilities` is passed and the key does not have the specified capabilities or is revoked or invalid. - * Returns Infinity if the key doesn't expire. - * @param {encrypt|sign|encrypt_sign} capabilities, optional - * @param {module:type/keyid} keyId, optional - * @param {Object} userId, optional user ID - * @returns {Promise} - * @async - */ -Key.prototype.getExpirationTime = async function (capabilities, keyId, userId) { - const primaryUser = await this.getPrimaryUser(null, userId); - if (!primaryUser) { - throw new Error('Could not find primary user'); - } - const selfCert = primaryUser.selfCertification; - const keyExpiry = getExpirationTime(this.keyPacket, selfCert); - const sigExpiry = selfCert.getExpirationTime(); - let expiry = keyExpiry < sigExpiry ? keyExpiry : sigExpiry; - if (capabilities === 'encrypt' || capabilities === 'encrypt_sign') { - const encryptKey = (await this.getEncryptionKey(keyId, expiry, userId)) || (await this.getEncryptionKey(keyId, null, userId)); - if (!encryptKey) return null; - const encryptExpiry = await encryptKey.getExpirationTime(this.keyPacket); - if (encryptExpiry < expiry) expiry = encryptExpiry; - } - if (capabilities === 'sign' || capabilities === 'encrypt_sign') { - const signKey = (await this.getSigningKey(keyId, expiry, userId)) || (await this.getSigningKey(keyId, null, userId)); - if (!signKey) return null; - const signExpiry = await signKey.getExpirationTime(this.keyPacket); - if (signExpiry < expiry) expiry = signExpiry; - } - return expiry; -}; - -/** - * Returns primary user and most significant (latest valid) self signature - * - if multiple primary users exist, returns the one with the latest self signature - * - otherwise, returns the user with the latest self signature - * @param {Date} date (optional) use the given date for verification instead of the current time - * @param {Object} userId (optional) user ID to get instead of the primary user, if it exists - * @returns {Promise<{user: module:key.User, - * selfCertification: module:packet.Signature}>} The primary user and the self signature - * @async - */ -Key.prototype.getPrimaryUser = async function (date = new Date(), userId = {}) { - const primaryKey = this.keyPacket; - const users = []; - for (let i = 0; i < this.users.length; i++) { - const user = this.users[i]; - if (!user.userId || !((userId.name === undefined || user.userId.name === userId.name) && (userId.email === undefined || user.userId.email === userId.email) && (userId.comment === undefined || user.userId.comment === userId.comment))) continue; - const dataToVerify = { userId: user.userId, key: primaryKey }; - const selfCertification = await getLatestValidSignature(user.selfCertifications, primaryKey, _enums2.default.signature.cert_generic, dataToVerify, date); - if (!selfCertification) continue; - users.push({ index: i, user, selfCertification }); - } - if (!users.length) { - if (userId.name !== undefined || userId.email !== undefined || userId.comment !== undefined) { - throw new Error('Could not find user that matches that user ID'); - } - return null; - } - await Promise.all(users.map(async function (a) { - return a.user.revoked || a.user.isRevoked(primaryKey, a.selfCertification, null, date); - })); - // sort by primary user flag and signature creation time - const primaryUser = users.sort(function (a, b) { - const A = a.selfCertification; - const B = b.selfCertification; - return B.revoked - A.revoked || A.isPrimaryUserID - B.isPrimaryUserID || A.created - B.created; - }).pop(); - const user = primaryUser.user, - cert = primaryUser.selfCertification; - - if (cert.revoked || (await user.isRevoked(primaryKey, cert, null, date))) { - return null; - } - return primaryUser; -}; - -/** - * Update key with new components from specified key with same key ID: - * users, subkeys, certificates are merged into the destination key, - * duplicates and expired signatures are ignored. - * - * If the specified key is a private key and the destination key is public, - * the destination key is transformed to a private key. - * @param {module:key.Key} key Source key to merge - * @returns {Promise} - * @async - */ -Key.prototype.update = async function (key) { - if ((await key.verifyPrimaryKey()) === _enums2.default.keyStatus.invalid) { - return; - } - if (!this.hasSameFingerprintAs(key)) { - throw new Error('Key update method: fingerprints of keys not equal'); - } - if (this.isPublic() && key.isPrivate()) { - // check for equal subkey packets - const equal = this.subKeys.length === key.subKeys.length && this.subKeys.every(destSubKey => { - return key.subKeys.some(srcSubKey => { - return destSubKey.hasSameFingerprintAs(srcSubKey); - }); - }); - if (!equal) { - throw new Error('Cannot update public key with private key if subkey mismatch'); - } - this.keyPacket = key.keyPacket; - } - // revocation signatures - await mergeSignatures(key, this, 'revocationSignatures', srcRevSig => { - return isDataRevoked(this.keyPacket, _enums2.default.signature.key_revocation, this, [srcRevSig], null, key.keyPacket); - }); - // direct signatures - await mergeSignatures(key, this, 'directSignatures'); - // TODO replace when Promise.some or Promise.any are implemented - // users - await Promise.all(key.users.map(async srcUser => { - let found = false; - await Promise.all(this.users.map(async dstUser => { - if (srcUser.userId && dstUser.userId && srcUser.userId.userid === dstUser.userId.userid || srcUser.userAttribute && srcUser.userAttribute.equals(dstUser.userAttribute)) { - await dstUser.update(srcUser, this.keyPacket); - found = true; - } - })); - if (!found) { - this.users.push(srcUser); - } - })); - // TODO replace when Promise.some or Promise.any are implemented - // subkeys - await Promise.all(key.subKeys.map(async srcSubKey => { - let found = false; - await Promise.all(this.subKeys.map(async dstSubKey => { - if (dstSubKey.hasSameFingerprintAs(srcSubKey)) { - await dstSubKey.update(srcSubKey, this.keyPacket); - found = true; - } - })); - if (!found) { - this.subKeys.push(srcSubKey); - } - })); -}; - -/** - * Merges signatures from source[attr] to dest[attr] - * @private - * @param {Object} source - * @param {Object} dest - * @param {String} attr - * @param {Function} checkFn optional, signature only merged if true - */ -async function mergeSignatures(source, dest, attr, checkFn) { - source = source[attr]; - if (source) { - if (!dest[attr].length) { - dest[attr] = source; - } else { - await Promise.all(source.map(async function (sourceSig) { - if (!sourceSig.isExpired() && (!checkFn || (await checkFn(sourceSig))) && !dest[attr].some(function (destSig) { - return _util2.default.equalsUint8Array(destSig.signature, sourceSig.signature); - })) { - dest[attr].push(sourceSig); - } - })); - } - } -} - -/** - * Revokes the key - * @param {Object} reasonForRevocation optional, object indicating the reason for revocation - * @param {module:enums.reasonForRevocation} reasonForRevocation.flag optional, flag indicating the reason for revocation - * @param {String} reasonForRevocation.string optional, string explaining the reason for revocation - * @param {Date} date optional, override the creationtime of the revocation signature - * @returns {Promise} new key with revocation signature - * @async - */ -Key.prototype.revoke = async function ({ - flag: reasonForRevocationFlag = _enums2.default.reasonForRevocation.no_reason, - string: reasonForRevocationString = '' -} = {}, date = new Date()) { - if (this.isPublic()) { - throw new Error('Need private key for revoking'); - } - const dataToSign = { key: this.keyPacket }; - const key = new Key(this.toPacketlist()); - key.revocationSignatures.push((await createSignaturePacket(dataToSign, null, this.keyPacket, { - signatureType: _enums2.default.signature.key_revocation, - reasonForRevocationFlag: _enums2.default.write(_enums2.default.reasonForRevocation, reasonForRevocationFlag), - reasonForRevocationString - }, date))); - return key; -}; - -/** - * Get revocation certificate from a revoked key. - * (To get a revocation certificate for an unrevoked key, call revoke() first.) - * @returns {Promise} armored revocation certificate - * @async - */ -Key.prototype.getRevocationCertificate = async function () { - const dataToVerify = { key: this.keyPacket }; - const revocationSignature = await getLatestValidSignature(this.revocationSignatures, this.keyPacket, _enums2.default.signature.key_revocation, dataToVerify); - if (revocationSignature) { - const packetlist = new _packet2.default.List(); - packetlist.push(revocationSignature); - return _armor2.default.encode(_enums2.default.armor.public_key, packetlist.write(), null, null, 'This is a revocation certificate'); - } -}; - -/** - * Applies a revocation certificate to a key - * This adds the first signature packet in the armored text to the key, - * if it is a valid revocation signature. - * @param {String} revocationCertificate armored revocation certificate - * @returns {Promise} new revoked key - * @async - */ -Key.prototype.applyRevocationCertificate = async function (revocationCertificate) { - const input = await _armor2.default.decode(revocationCertificate); - const packetlist = new _packet2.default.List(); - await packetlist.read(input.data); - const revocationSignature = packetlist.findPacket(_enums2.default.packet.signature); - if (!revocationSignature || revocationSignature.signatureType !== _enums2.default.signature.key_revocation) { - throw new Error('Could not find revocation signature packet'); - } - if (!revocationSignature.issuerKeyId.equals(this.getKeyId())) { - throw new Error('Revocation signature does not match key'); - } - if (revocationSignature.isExpired()) { - throw new Error('Revocation signature is expired'); - } - if (!(await revocationSignature.verify(this.keyPacket, _enums2.default.signature.key_revocation, { key: this.keyPacket }))) { - throw new Error('Could not verify revocation signature'); - } - const key = new Key(this.toPacketlist()); - key.revocationSignatures.push(revocationSignature); - return key; -}; - -/** - * Signs primary user of key - * @param {Array} privateKey decrypted private keys for signing - * @param {Date} date (optional) use the given date for verification instead of the current time - * @param {Object} userId (optional) user ID to get instead of the primary user, if it exists - * @returns {Promise} new public key with new certificate signature - * @async - */ -Key.prototype.signPrimaryUser = async function (privateKeys, date, userId) { - var _ref2 = (await this.getPrimaryUser(date, userId)) || {}; - - const index = _ref2.index, - user = _ref2.user; - - if (!user) { - throw new Error('Could not find primary user'); - } - const userSign = await user.sign(this.keyPacket, privateKeys); - const key = new Key(this.toPacketlist()); - key.users[index] = userSign; - return key; -}; - -/** - * Signs all users of key - * @param {Array} privateKeys decrypted private keys for signing - * @returns {Promise} new public key with new certificate signature - * @async - */ -Key.prototype.signAllUsers = async function (privateKeys) { - const that = this; - const key = new Key(this.toPacketlist()); - key.users = await Promise.all(this.users.map(function (user) { - return user.sign(that.keyPacket, privateKeys); - })); - return key; -}; - -/** - * Verifies primary user of key - * - if no arguments are given, verifies the self certificates; - * - otherwise, verifies all certificates signed with given keys. - * @param {Array} keys array of keys to verify certificate signatures - * @param {Date} date (optional) use the given date for verification instead of the current time - * @param {Object} userId (optional) user ID to get instead of the primary user, if it exists - * @returns {Promise>} List of signer's keyid and validity of signature - * @async - */ -Key.prototype.verifyPrimaryUser = async function (keys, date, userId) { - const primaryKey = this.keyPacket; - - var _ref3 = (await this.getPrimaryUser(date, userId)) || {}; - - const user = _ref3.user; - - if (!user) { - throw new Error('Could not find primary user'); - } - const results = keys ? await user.verifyAllCertifications(primaryKey, keys) : [{ keyid: primaryKey.keyid, valid: (await user.verify(primaryKey)) === _enums2.default.keyStatus.valid }]; - return results; -}; - -/** - * Verifies all users of key - * - if no arguments are given, verifies the self certificates; - * - otherwise, verifies all certificates signed with given keys. - * @param {Array} keys array of keys to verify certificate signatures - * @returns {Promise>} list of userid, signer's keyid and validity of signature - * @async - */ -Key.prototype.verifyAllUsers = async function (keys) { - const results = []; - const primaryKey = this.keyPacket; - await Promise.all(this.users.map(async function (user) { - const signatures = keys ? await user.verifyAllCertifications(primaryKey, keys) : [{ keyid: primaryKey.keyid, valid: (await user.verify(primaryKey)) === _enums2.default.keyStatus.valid }]; - signatures.forEach(signature => { - results.push({ - userid: user.userId.userid, - keyid: signature.keyid, - valid: signature.valid - }); - }); - })); - return results; -}; - -/** - * @class - * @classdesc Class that represents an user ID or attribute packet and the relevant signatures. - */ -function User(userPacket) { - if (!(this instanceof User)) { - return new User(userPacket); - } - this.userId = userPacket.tag === _enums2.default.packet.userid ? userPacket : null; - this.userAttribute = userPacket.tag === _enums2.default.packet.userAttribute ? userPacket : null; - this.selfCertifications = []; - this.otherCertifications = []; - this.revocationSignatures = []; -} - -/** - * Transforms structured user data to packetlist - * @returns {module:packet.List} - */ -User.prototype.toPacketlist = function () { - const packetlist = new _packet2.default.List(); - packetlist.push(this.userId || this.userAttribute); - packetlist.concat(this.revocationSignatures); - packetlist.concat(this.selfCertifications); - packetlist.concat(this.otherCertifications); - return packetlist; -}; - -/** - * Signs user - * @param {module:packet.SecretKey| - * module:packet.PublicKey} primaryKey The primary key packet - * @param {Array} privateKeys Decrypted private keys for signing - * @returns {Promise} New user with new certificate signatures - * @async - */ -User.prototype.sign = async function (primaryKey, privateKeys) { - const dataToSign = { - userId: this.userId, - userAttribute: this.userAttribute, - key: primaryKey - }; - const user = new User(dataToSign.userId || dataToSign.userAttribute); - user.otherCertifications = await Promise.all(privateKeys.map(async function (privateKey) { - if (privateKey.isPublic()) { - throw new Error('Need private key for signing'); - } - if (privateKey.hasSameFingerprintAs(primaryKey)) { - throw new Error('Not implemented for self signing'); - } - const signingKey = await privateKey.getSigningKey(); - if (!signingKey) { - throw new Error('Could not find valid signing key packet in key ' + privateKey.getKeyId().toHex()); - } - return createSignaturePacket(dataToSign, privateKey, signingKey.keyPacket, { - // Most OpenPGP implementations use generic certification (0x10) - signatureType: _enums2.default.signature.cert_generic, - keyFlags: [_enums2.default.keyFlags.certify_keys | _enums2.default.keyFlags.sign_data] - }); - })); - await user.update(this, primaryKey); - return user; -}; - -/** - * Checks if a given certificate of the user is revoked - * @param {module:packet.SecretKey| - * module:packet.PublicKey} primaryKey The primary key packet - * @param {module:packet.Signature} certificate The certificate to verify - * @param {module:packet.PublicSubkey| - * module:packet.SecretSubkey| - * module:packet.PublicKey| - * module:packet.SecretKey} key, optional The key to verify the signature - * @param {Date} date Use the given date instead of the current time - * @returns {Promise} True if the certificate is revoked - * @async - */ -User.prototype.isRevoked = async function (primaryKey, certificate, key, date = new Date()) { - return isDataRevoked(primaryKey, _enums2.default.signature.cert_revocation, { - key: primaryKey, - userId: this.userId, - userAttribute: this.userAttribute - }, this.revocationSignatures, certificate, key, date); -}; - -/** - * Create signature packet - * @param {Object} dataToSign Contains packets to be signed - * @param {module:packet.SecretKey| - * module:packet.SecretSubkey} signingKeyPacket secret key packet for signing - * @param {Object} signatureProperties (optional) properties to write on the signature packet before signing - * @param {Date} date (optional) override the creationtime of the signature - * @param {Object} userId (optional) user ID - * @param {Object} detached (optional) whether to create a detached signature packet - * @returns {module:packet/signature} signature packet - */ -async function createSignaturePacket(dataToSign, privateKey, signingKeyPacket, signatureProperties, date, userId, detached = false) { - if (!signingKeyPacket.isDecrypted()) { - throw new Error('Private key is not decrypted.'); - } - const signaturePacket = new _packet2.default.Signature(date); - Object.assign(signaturePacket, signatureProperties); - signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm; - signaturePacket.hashAlgorithm = await getPreferredHashAlgo(privateKey, signingKeyPacket, date, userId); - await signaturePacket.sign(signingKeyPacket, dataToSign, detached); - return signaturePacket; -} - -/** - * Verifies the user certificate - * @param {module:packet.SecretKey| - * module:packet.PublicKey} primaryKey The primary key packet - * @param {module:packet.Signature} certificate A certificate of this user - * @param {Array} keys Array of keys to verify certificate signatures - * @param {Date} date Use the given date instead of the current time - * @returns {Promise} status of the certificate - * @async - */ -User.prototype.verifyCertificate = async function (primaryKey, certificate, keys, date = new Date()) { - const that = this; - const keyid = certificate.issuerKeyId; - const dataToVerify = { - userId: this.userId, - userAttribute: this.userAttribute, - key: primaryKey - }; - const results = await Promise.all(keys.map(async function (key) { - if (!key.getKeyIds().some(id => id.equals(keyid))) { - return; - } - const signingKey = await key.getSigningKey(keyid, date); - if (certificate.revoked || (await that.isRevoked(primaryKey, certificate, signingKey.keyPacket, date))) { - return _enums2.default.keyStatus.revoked; - } - if (!(certificate.verified || (await certificate.verify(signingKey.keyPacket, _enums2.default.signature.cert_generic, dataToVerify)))) { - return _enums2.default.keyStatus.invalid; - } - if (certificate.isExpired(date)) { - return _enums2.default.keyStatus.expired; - } - return _enums2.default.keyStatus.valid; - })); - return results.find(result => result !== undefined); -}; - -/** - * Verifies all user certificates - * @param {module:packet.SecretKey| - * module:packet.PublicKey} primaryKey The primary key packet - * @param {Array} keys Array of keys to verify certificate signatures - * @param {Date} date Use the given date instead of the current time - * @returns {Promise>} List of signer's keyid and validity of signature - * @async - */ -User.prototype.verifyAllCertifications = async function (primaryKey, keys, date = new Date()) { - const that = this; - const certifications = this.selfCertifications.concat(this.otherCertifications); - return Promise.all(certifications.map(async function (certification) { - const status = await that.verifyCertificate(primaryKey, certification, keys, date); - return { - keyid: certification.issuerKeyId, - valid: status === undefined ? null : status === _enums2.default.keyStatus.valid - }; - })); -}; - -/** - * Verify User. Checks for existence of self signatures, revocation signatures - * and validity of self signature - * @param {module:packet.SecretKey| - * module:packet.PublicKey} primaryKey The primary key packet - * @param {Date} date Use the given date instead of the current time - * @returns {Promise} Status of user - * @async - */ -User.prototype.verify = async function (primaryKey, date = new Date()) { - if (!this.selfCertifications.length) { - return _enums2.default.keyStatus.no_self_cert; - } - const that = this; - const dataToVerify = { - userId: this.userId, - userAttribute: this.userAttribute, - key: primaryKey - }; - // TODO replace when Promise.some or Promise.any are implemented - const results = [_enums2.default.keyStatus.invalid].concat((await Promise.all(this.selfCertifications.map(async function (selfCertification) { - if (selfCertification.revoked || (await that.isRevoked(primaryKey, selfCertification, undefined, date))) { - return _enums2.default.keyStatus.revoked; - } - if (!(selfCertification.verified || (await selfCertification.verify(primaryKey, _enums2.default.signature.cert_generic, dataToVerify)))) { - return _enums2.default.keyStatus.invalid; - } - if (selfCertification.isExpired(date)) { - return _enums2.default.keyStatus.expired; - } - return _enums2.default.keyStatus.valid; - })))); - return results.some(status => status === _enums2.default.keyStatus.valid) ? _enums2.default.keyStatus.valid : results.pop(); -}; - -/** - * Update user with new components from specified user - * @param {module:key.User} user Source user to merge - * @param {module:packet.SecretKey| - * module:packet.SecretSubkey} primaryKey primary key used for validation - * @returns {Promise} - * @async - */ -User.prototype.update = async function (user, primaryKey) { - const dataToVerify = { - userId: this.userId, - userAttribute: this.userAttribute, - key: primaryKey - }; - // self signatures - await mergeSignatures(user, this, 'selfCertifications', async function (srcSelfSig) { - return srcSelfSig.verified || srcSelfSig.verify(primaryKey, _enums2.default.signature.cert_generic, dataToVerify); - }); - // other signatures - await mergeSignatures(user, this, 'otherCertifications'); - // revocation signatures - await mergeSignatures(user, this, 'revocationSignatures', function (srcRevSig) { - return isDataRevoked(primaryKey, _enums2.default.signature.cert_revocation, dataToVerify, [srcRevSig]); - }); -}; - -/** - * @class - * @classdesc Class that represents a subkey packet and the relevant signatures. - * @borrows module:packet.PublicSubkey#getKeyId as SubKey#getKeyId - * @borrows module:packet.PublicSubkey#getFingerprint as SubKey#getFingerprint - * @borrows module:packet.PublicSubkey#hasSameFingerprintAs as SubKey#hasSameFingerprintAs - * @borrows module:packet.PublicSubkey#getAlgorithmInfo as SubKey#getAlgorithmInfo - * @borrows module:packet.PublicSubkey#getCreationTime as SubKey#getCreationTime - * @borrows module:packet.PublicSubkey#isDecrypted as SubKey#isDecrypted - */ -function SubKey(subKeyPacket) { - if (!(this instanceof SubKey)) { - return new SubKey(subKeyPacket); - } - this.keyPacket = subKeyPacket; - this.bindingSignatures = []; - this.revocationSignatures = []; -} - -/** - * Transforms structured subkey data to packetlist - * @returns {module:packet.List} - */ -SubKey.prototype.toPacketlist = function () { - const packetlist = new _packet2.default.List(); - packetlist.push(this.keyPacket); - packetlist.concat(this.revocationSignatures); - packetlist.concat(this.bindingSignatures); - return packetlist; -}; - -/** - * Checks if a binding signature of a subkey is revoked - * @param {module:packet.SecretKey| - * module:packet.PublicKey} primaryKey The primary key packet - * @param {module:packet.Signature} signature The binding signature to verify - * @param {module:packet.PublicSubkey| - * module:packet.SecretSubkey| - * module:packet.PublicKey| - * module:packet.SecretKey} key, optional The key to verify the signature - * @param {Date} date Use the given date instead of the current time - * @returns {Promise} True if the binding signature is revoked - * @async - */ -SubKey.prototype.isRevoked = async function (primaryKey, signature, key, date = new Date()) { - return isDataRevoked(primaryKey, _enums2.default.signature.subkey_revocation, { - key: primaryKey, - bind: this.keyPacket - }, this.revocationSignatures, signature, key, date); -}; - -/** - * Verify subkey. Checks for revocation signatures, expiration time - * and valid binding signature - * @param {module:packet.SecretKey| - * module:packet.PublicKey} primaryKey The primary key packet - * @param {Date} date Use the given date instead of the current time - * @returns {Promise} The status of the subkey - * @async - */ -SubKey.prototype.verify = async function (primaryKey, date = new Date()) { - const that = this; - const dataToVerify = { key: primaryKey, bind: this.keyPacket }; - // check subkey binding signatures - const bindingSignature = await getLatestValidSignature(this.bindingSignatures, primaryKey, _enums2.default.signature.subkey_binding, dataToVerify, date); - // check binding signature is verified - if (!bindingSignature) { - return _enums2.default.keyStatus.invalid; - } - // check binding signature is not revoked - if (bindingSignature.revoked || (await that.isRevoked(primaryKey, bindingSignature, null, date))) { - return _enums2.default.keyStatus.revoked; - } - // check for expiration time - if (isDataExpired(this.keyPacket, bindingSignature, date)) { - return _enums2.default.keyStatus.expired; - } - return _enums2.default.keyStatus.valid; // binding signature passed all checks -}; - -/** - * Returns the expiration time of the subkey or Infinity if key does not expire - * Returns null if the subkey is invalid. - * @param {module:packet.SecretKey| - * module:packet.PublicKey} primaryKey The primary key packet - * @param {Date} date Use the given date instead of the current time - * @returns {Promise} - * @async - */ -SubKey.prototype.getExpirationTime = async function (primaryKey, date = new Date()) { - const dataToVerify = { key: primaryKey, bind: this.keyPacket }; - const bindingSignature = await getLatestValidSignature(this.bindingSignatures, primaryKey, _enums2.default.signature.subkey_binding, dataToVerify, date); - if (!bindingSignature) return null; - const keyExpiry = getExpirationTime(this.keyPacket, bindingSignature); - const sigExpiry = bindingSignature.getExpirationTime(); - return keyExpiry < sigExpiry ? keyExpiry : sigExpiry; -}; - -/** - * Update subkey with new components from specified subkey - * @param {module:key~SubKey} subKey Source subkey to merge - * @param {module:packet.SecretKey| - module:packet.SecretSubkey} primaryKey primary key used for validation - * @returns {Promise} - * @async - */ -SubKey.prototype.update = async function (subKey, primaryKey) { - if ((await subKey.verify(primaryKey)) === _enums2.default.keyStatus.invalid) { - return; - } - if (!this.hasSameFingerprintAs(subKey)) { - throw new Error('SubKey update method: fingerprints of subkeys not equal'); - } - // key packet - if (this.keyPacket.tag === _enums2.default.packet.publicSubkey && subKey.keyPacket.tag === _enums2.default.packet.secretSubkey) { - this.keyPacket = subKey.keyPacket; - } - // update missing binding signatures - const that = this; - const dataToVerify = { key: primaryKey, bind: that.keyPacket }; - await mergeSignatures(subKey, this, 'bindingSignatures', async function (srcBindSig) { - if (!(srcBindSig.verified || (await srcBindSig.verify(primaryKey, _enums2.default.signature.subkey_binding, dataToVerify)))) { - return false; - } - for (let i = 0; i < that.bindingSignatures.length; i++) { - if (that.bindingSignatures[i].issuerKeyId.equals(srcBindSig.issuerKeyId)) { - if (srcBindSig.created > that.bindingSignatures[i].created) { - that.bindingSignatures[i] = srcBindSig; - } - return false; - } - } - return true; - }); - // revocation signatures - await mergeSignatures(subKey, this, 'revocationSignatures', function (srcRevSig) { - return isDataRevoked(primaryKey, _enums2.default.signature.subkey_revocation, dataToVerify, [srcRevSig]); - }); -}; - -/** - * Revokes the subkey - * @param {module:packet.SecretKey} primaryKey decrypted private primary key for revocation - * @param {Object} reasonForRevocation optional, object indicating the reason for revocation - * @param {module:enums.reasonForRevocation} reasonForRevocation.flag optional, flag indicating the reason for revocation - * @param {String} reasonForRevocation.string optional, string explaining the reason for revocation - * @param {Date} date optional, override the creationtime of the revocation signature - * @returns {Promise} new subkey with revocation signature - * @async - */ -SubKey.prototype.revoke = async function (primaryKey, { - flag: reasonForRevocationFlag = _enums2.default.reasonForRevocation.no_reason, - string: reasonForRevocationString = '' -} = {}, date = new Date()) { - const dataToSign = { key: primaryKey, bind: this.keyPacket }; - const subKey = new SubKey(this.keyPacket); - subKey.revocationSignatures.push((await createSignaturePacket(dataToSign, null, primaryKey, { - signatureType: _enums2.default.signature.subkey_revocation, - reasonForRevocationFlag: _enums2.default.write(_enums2.default.reasonForRevocation, reasonForRevocationFlag), - reasonForRevocationString - }, date))); - await subKey.update(this, primaryKey); - return subKey; -}; - -['getKeyId', 'getFingerprint', 'getAlgorithmInfo', 'getCreationTime', 'isDecrypted'].forEach(name => { - Key.prototype[name] = SubKey.prototype[name] = function () { - return this.keyPacket[name](); - }; -}); - -Key.prototype.hasSameFingerprintAs = SubKey.prototype.hasSameFingerprintAs = function (other) { - return this.keyPacket.hasSameFingerprintAs(other.keyPacket || other); -}; - -/** - * Reads an unarmored OpenPGP key list and returns one or multiple key objects - * @param {Uint8Array} data to be parsed - * @returns {Promise<{keys: Array, - * err: (Array|null)}>} result object with key and error arrays - * @async - * @static - */ -async function read(data) { - const result = {}; - result.keys = []; - const err = []; - try { - const packetlist = new _packet2.default.List(); - await packetlist.read(data); - const keyIndex = packetlist.indexOfTag(_enums2.default.packet.publicKey, _enums2.default.packet.secretKey); - if (keyIndex.length === 0) { - throw new Error('No key packet found'); - } - for (let i = 0; i < keyIndex.length; i++) { - const oneKeyList = packetlist.slice(keyIndex[i], keyIndex[i + 1]); - try { - const newKey = new Key(oneKeyList); - result.keys.push(newKey); - } catch (e) { - err.push(e); - } - } - } catch (e) { - err.push(e); - } - if (err.length) { - result.err = err; - } - return result; -} - -/** - * Reads an OpenPGP armored text and returns one or multiple key objects - * @param {String | ReadableStream} armoredText text to be parsed - * @returns {Promise<{keys: Array, - * err: (Array|null)}>} result object with key and error arrays - * @async - * @static - */ -async function readArmored(armoredText) { - try { - const input = await _armor2.default.decode(armoredText); - if (!(input.type === _enums2.default.armor.public_key || input.type === _enums2.default.armor.private_key)) { - throw new Error('Armored text not of type key'); - } - return read(input.data); - } catch (e) { - const result = { keys: [], err: [] }; - result.err.push(e); - return result; - } -} - -/** - * Generates a new OpenPGP key. Supports RSA and ECC keys. - * Primary and subkey will be of same type. - * @param {module:enums.publicKey} [options.keyType=module:enums.publicKey.rsa_encrypt_sign] - * To indicate what type of key to make. - * RSA is 1. See {@link https://tools.ietf.org/html/rfc4880#section-9.1} - * @param {Integer} options.numBits number of bits for the key creation. - * @param {String|Array} options.userIds - * Assumes already in form of "User Name " - * If array is used, the first userId is set as primary user Id - * @param {String} options.passphrase The passphrase used to encrypt the resulting private key - * @param {Number} [options.keyExpirationTime=0] - * The number of seconds after the key creation time that the key expires - * @param {String} curve (optional) elliptic curve for ECC keys - * @param {Date} date Override the creation date of the key and the key signatures - * @param {Array} subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}] - * sign parameter defaults to false, and indicates whether the subkey should sign rather than encrypt - * @returns {Promise} - * @async - * @static - */ -async function generate(options) { - options.sign = true; // primary key is always a signing key - options = sanitizeKeyOptions(options); - options.subkeys = options.subkeys.map(function (subkey, index) { - return sanitizeKeyOptions(options.subkeys[index], options); - }); - - let promises = [generateSecretKey(options)]; - promises = promises.concat(options.subkeys.map(generateSecretSubkey)); - return Promise.all(promises).then(packets => wrapKeyObject(packets[0], packets.slice(1), options)); - - function sanitizeKeyOptions(options, subkeyDefaults = {}) { - options.curve = options.curve || subkeyDefaults.curve; - options.numBits = options.numBits || subkeyDefaults.numBits; - options.keyExpirationTime = options.keyExpirationTime !== undefined ? options.keyExpirationTime : subkeyDefaults.keyExpirationTime; - options.passphrase = _util2.default.isString(options.passphrase) ? options.passphrase : subkeyDefaults.passphrase; - options.date = options.date || subkeyDefaults.date; - - options.sign = options.sign || false; - - if (options.curve) { - try { - options.curve = _enums2.default.write(_enums2.default.curve, options.curve); - } catch (e) { - throw new Error('Not valid curve.'); - } - if (options.curve === _enums2.default.curve.ed25519 || options.curve === _enums2.default.curve.curve25519) { - if (options.sign) { - options.algorithm = _enums2.default.publicKey.eddsa; - options.curve = _enums2.default.curve.ed25519; - } else { - options.algorithm = _enums2.default.publicKey.ecdh; - options.curve = _enums2.default.curve.curve25519; - } - } else { - if (options.sign) { - options.algorithm = _enums2.default.publicKey.ecdsa; - } else { - options.algorithm = _enums2.default.publicKey.ecdh; - } - } - } else if (options.numBits) { - options.algorithm = _enums2.default.publicKey.rsa_encrypt_sign; - } else { - throw new Error('Unrecognized key type'); - } - return options; - } - - async function generateSecretKey(options) { - const secretKeyPacket = new _packet2.default.SecretKey(options.date); - secretKeyPacket.packets = null; - secretKeyPacket.algorithm = _enums2.default.read(_enums2.default.publicKey, options.algorithm); - await secretKeyPacket.generate(options.numBits, options.curve); - return secretKeyPacket; - } - - async function generateSecretSubkey(options) { - const secretSubkeyPacket = new _packet2.default.SecretSubkey(options.date); - secretSubkeyPacket.packets = null; - secretSubkeyPacket.algorithm = _enums2.default.read(_enums2.default.publicKey, options.algorithm); - await secretSubkeyPacket.generate(options.numBits, options.curve); - return secretSubkeyPacket; - } -} - -/** - * Reformats and signs an OpenPGP key with a given User ID. Currently only supports RSA keys. - * @param {module:key.Key} options.privateKey The private key to reformat - * @param {module:enums.publicKey} [options.keyType=module:enums.publicKey.rsa_encrypt_sign] - * @param {String|Array} options.userIds - * Assumes already in form of "User Name " - * If array is used, the first userId is set as primary user Id - * @param {String} options.passphrase The passphrase used to encrypt the resulting private key - * @param {Number} [options.keyExpirationTime=0] - * The number of seconds after the key creation time that the key expires - * @param {Date} date Override the creation date of the key and the key signatures - * @param {Array} subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}] - * - * @returns {Promise} - * @async - * @static - */ -async function reformat(options) { - options = sanitizeKeyOptions(options); - - try { - const isDecrypted = options.privateKey.getKeys().every(key => key.isDecrypted()); - if (!isDecrypted) { - await options.privateKey.decrypt(); - } - } catch (err) { - throw new Error('Key not decrypted'); - } - - const packetlist = options.privateKey.toPacketlist(); - let secretKeyPacket; - const secretSubkeyPackets = []; - for (let i = 0; i < packetlist.length; i++) { - if (packetlist[i].tag === _enums2.default.packet.secretKey) { - secretKeyPacket = packetlist[i]; - } else if (packetlist[i].tag === _enums2.default.packet.secretSubkey) { - secretSubkeyPackets.push(packetlist[i]); - } - } - if (!secretKeyPacket) { - throw new Error('Key does not contain a secret key packet'); - } - - if (!options.subkeys) { - options.subkeys = await Promise.all(secretSubkeyPackets.map(async secretSubkeyPacket => ({ - sign: (await options.privateKey.getSigningKey(secretSubkeyPacket.getKeyId(), null)) && !(await options.privateKey.getEncryptionKey(secretSubkeyPacket.getKeyId(), null)) - }))); - } - - if (options.subkeys.length !== secretSubkeyPackets.length) { - throw new Error('Number of subkey options does not match number of subkeys'); - } - - options.subkeys = options.subkeys.map(function (subkey, index) { - return sanitizeKeyOptions(options.subkeys[index], options); - }); - - return wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options); - - function sanitizeKeyOptions(options, subkeyDefaults = {}) { - options.keyExpirationTime = options.keyExpirationTime || subkeyDefaults.keyExpirationTime; - options.passphrase = _util2.default.isString(options.passphrase) ? options.passphrase : subkeyDefaults.passphrase; - options.date = options.date || subkeyDefaults.date; - - return options; - } -} - -async function wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options) { - // set passphrase protection - if (options.passphrase) { - await secretKeyPacket.encrypt(options.passphrase); - } - - await Promise.all(secretSubkeyPackets.map(async function (secretSubkeyPacket, index) { - const subkeyPassphrase = options.subkeys[index].passphrase; - if (subkeyPassphrase) { - await secretSubkeyPacket.encrypt(subkeyPassphrase); - } - })); - - const packetlist = new _packet2.default.List(); - - packetlist.push(secretKeyPacket); - - await Promise.all(options.userIds.map(async function (userId, index) { - function createdPreferredAlgos(algos, configAlgo) { - if (configAlgo) { - // Not `uncompressed` / `plaintext` - const configIndex = algos.indexOf(configAlgo); - if (configIndex >= 1) { - // If it is included and not in first place, - algos.splice(configIndex, 1); // remove it. - } - if (configIndex !== 0) { - // If it was included and not in first place, or wasn't included, - algos.unshift(configAlgo); // add it to the front. - } - } - return algos; - } - - const userIdPacket = new _packet2.default.Userid(); - userIdPacket.format(userId); - - const dataToSign = {}; - dataToSign.userId = userIdPacket; - dataToSign.key = secretKeyPacket; - const signaturePacket = new _packet2.default.Signature(options.date); - signaturePacket.signatureType = _enums2.default.signature.cert_generic; - signaturePacket.publicKeyAlgorithm = secretKeyPacket.algorithm; - signaturePacket.hashAlgorithm = await getPreferredHashAlgo(null, secretKeyPacket); - signaturePacket.keyFlags = [_enums2.default.keyFlags.certify_keys | _enums2.default.keyFlags.sign_data]; - signaturePacket.preferredSymmetricAlgorithms = createdPreferredAlgos([ - // prefer aes256, aes128, then aes192 (no WebCrypto support: https://www.chromium.org/blink/webcrypto#TOC-AES-support) - _enums2.default.symmetric.aes256, _enums2.default.symmetric.aes128, _enums2.default.symmetric.aes192, _enums2.default.symmetric.cast5, _enums2.default.symmetric.tripledes], _config2.default.encryption_cipher); - if (_config2.default.aead_protect) { - signaturePacket.preferredAeadAlgorithms = createdPreferredAlgos([_enums2.default.aead.eax, _enums2.default.aead.ocb], _config2.default.aead_mode); - } - signaturePacket.preferredHashAlgorithms = createdPreferredAlgos([ - // prefer fast asm.js implementations (SHA-256). SHA-1 will not be secure much longer...move to bottom of list - _enums2.default.hash.sha256, _enums2.default.hash.sha512, _enums2.default.hash.sha1], _config2.default.prefer_hash_algorithm); - signaturePacket.preferredCompressionAlgorithms = createdPreferredAlgos([_enums2.default.compression.zlib, _enums2.default.compression.zip], _config2.default.compression); - if (index === 0) { - signaturePacket.isPrimaryUserID = true; - } - if (_config2.default.integrity_protect) { - signaturePacket.features = [0]; - signaturePacket.features[0] |= _enums2.default.features.modification_detection; - } - if (_config2.default.aead_protect) { - signaturePacket.features || (signaturePacket.features = [0]); - signaturePacket.features[0] |= _enums2.default.features.aead; - } - if (_config2.default.v5_keys) { - signaturePacket.features || (signaturePacket.features = [0]); - signaturePacket.features[0] |= _enums2.default.features.v5_keys; - } - if (options.keyExpirationTime > 0) { - signaturePacket.keyExpirationTime = options.keyExpirationTime; - signaturePacket.keyNeverExpires = false; - } - await signaturePacket.sign(secretKeyPacket, dataToSign); - - return { userIdPacket, signaturePacket }; - })).then(list => { - list.forEach(({ userIdPacket, signaturePacket }) => { - packetlist.push(userIdPacket); - packetlist.push(signaturePacket); - }); - }); - - await Promise.all(secretSubkeyPackets.map(async function (secretSubkeyPacket, index) { - const subkeyOptions = options.subkeys[index]; - const dataToSign = {}; - dataToSign.key = secretKeyPacket; - dataToSign.bind = secretSubkeyPacket; - const subkeySignaturePacket = new _packet2.default.Signature(subkeyOptions.date); - subkeySignaturePacket.signatureType = _enums2.default.signature.subkey_binding; - subkeySignaturePacket.publicKeyAlgorithm = secretKeyPacket.algorithm; - subkeySignaturePacket.hashAlgorithm = await getPreferredHashAlgo(null, secretSubkeyPacket); - if (subkeyOptions.sign) { - subkeySignaturePacket.keyFlags = [_enums2.default.keyFlags.sign_data]; - subkeySignaturePacket.embeddedSignature = await createSignaturePacket(dataToSign, null, secretSubkeyPacket, { - signatureType: _enums2.default.signature.key_binding - }, subkeyOptions.date); - } else { - subkeySignaturePacket.keyFlags = [_enums2.default.keyFlags.encrypt_communication | _enums2.default.keyFlags.encrypt_storage]; - } - if (subkeyOptions.keyExpirationTime > 0) { - subkeySignaturePacket.keyExpirationTime = subkeyOptions.keyExpirationTime; - subkeySignaturePacket.keyNeverExpires = false; - } - await subkeySignaturePacket.sign(secretKeyPacket, dataToSign); - - return { secretSubkeyPacket, subkeySignaturePacket }; - })).then(packets => { - packets.forEach(({ secretSubkeyPacket, subkeySignaturePacket }) => { - packetlist.push(secretSubkeyPacket); - packetlist.push(subkeySignaturePacket); - }); - }); - - // Add revocation signature packet for creating a revocation certificate. - // This packet should be removed before returning the key. - const dataToSign = { key: secretKeyPacket }; - packetlist.push((await createSignaturePacket(dataToSign, null, secretKeyPacket, { - signatureType: _enums2.default.signature.key_revocation, - reasonForRevocationFlag: _enums2.default.reasonForRevocation.no_reason, - reasonForRevocationString: '' - }, options.date))); - - // set passphrase protection - if (options.passphrase) { - secretKeyPacket.clearPrivateParams(); - } - - await Promise.all(secretSubkeyPackets.map(async function (secretSubkeyPacket, index) { - const subkeyPassphrase = options.subkeys[index].passphrase; - if (subkeyPassphrase) { - secretSubkeyPacket.clearPrivateParams(); - } - })); - - return new Key(packetlist); -} - -/** - * Checks if a given certificate or binding signature is revoked - * @param {module:packet.SecretKey| - * module:packet.PublicKey} primaryKey The primary key packet - * @param {Object} dataToVerify The data to check - * @param {Array} revocations The revocation signatures to check - * @param {module:packet.Signature} signature The certificate or signature to check - * @param {module:packet.PublicSubkey| - * module:packet.SecretSubkey| - * module:packet.PublicKey| - * module:packet.SecretKey} key, optional The key packet to check the signature - * @param {Date} date Use the given date instead of the current time - * @returns {Promise} True if the signature revokes the data - * @async - */ -async function isDataRevoked(primaryKey, signatureType, dataToVerify, revocations, signature, key, date = new Date()) { - key = key || primaryKey; - const normDate = _util2.default.normalizeDate(date); - const revocationKeyIds = []; - await Promise.all(revocations.map(async function (revocationSignature) { - if ( - // Note: a third-party revocation signature could legitimately revoke a - // self-signature if the signature has an authorized revocation key. - // However, we don't support passing authorized revocation keys, nor - // verifying such revocation signatures. Instead, we indicate an error - // when parsing a key with an authorized revocation key, and ignore - // third-party revocation signatures here. (It could also be revoking a - // third-party key certification, which should only affect - // `verifyAllCertifications`.) - (!signature || revocationSignature.issuerKeyId.equals(signature.issuerKeyId)) && !(_config2.default.revocations_expire && revocationSignature.isExpired(normDate)) && (revocationSignature.verified || (await revocationSignature.verify(key, signatureType, dataToVerify)))) { - // TODO get an identifier of the revoked object instead - revocationKeyIds.push(revocationSignature.issuerKeyId); - return true; - } - return false; - })); - // TODO further verify that this is the signature that should be revoked - if (signature) { - signature.revoked = revocationKeyIds.some(keyId => keyId.equals(signature.issuerKeyId)) ? true : signature.revoked || false; - return signature.revoked; - } - return revocationKeyIds.length > 0; -} - -function isDataExpired(keyPacket, signature, date = new Date()) { - const normDate = _util2.default.normalizeDate(date); - if (normDate !== null) { - const expirationTime = getExpirationTime(keyPacket, signature); - return !(keyPacket.created <= normDate && normDate <= expirationTime) || signature && signature.isExpired(date); - } - return false; -} - -function getExpirationTime(keyPacket, signature) { - let expirationTime; - // check V4 expiration time - if (signature.keyNeverExpires === false) { - expirationTime = keyPacket.created.getTime() + signature.keyExpirationTime * 1000; - } - return expirationTime ? new Date(expirationTime) : Infinity; -} - -/** - * Check if signature has revocation key sub packet (not supported by OpenPGP.js) - * and throw error if found - * @param {module:packet.Signature} signature The certificate or signature to check - * @param {type/keyid} keyId Check only certificates or signatures from a certain issuer key ID - */ -function checkRevocationKey(signature, keyId) { - if (signature.revocationKeyClass !== null && signature.issuerKeyId.equals(keyId)) { - throw new Error('This key is intended to be revoked with an authorized key, which OpenPGP.js does not support.'); - } -} - -/** - * Returns the preferred signature hash algorithm of a key - * @param {module:key.Key} key (optional) the key to get preferences from - * @param {module:packet.SecretKey|module:packet.SecretSubkey} keyPacket key packet used for signing - * @param {Date} date (optional) use the given date for verification instead of the current time - * @param {Object} userId (optional) user ID - * @returns {Promise} - * @async - */ -async function getPreferredHashAlgo(key, keyPacket, date = new Date(), userId = {}) { - let hash_algo = _config2.default.prefer_hash_algorithm; - let pref_algo = hash_algo; - if (key instanceof Key) { - const primaryUser = await key.getPrimaryUser(date, userId); - if (primaryUser && primaryUser.selfCertification.preferredHashAlgorithms) { - var _primaryUser$selfCert = _slicedToArray(primaryUser.selfCertification.preferredHashAlgorithms, 1); - - pref_algo = _primaryUser$selfCert[0]; - - hash_algo = _crypto2.default.hash.getHashByteLength(hash_algo) <= _crypto2.default.hash.getHashByteLength(pref_algo) ? pref_algo : hash_algo; - } - } - switch (Object.getPrototypeOf(keyPacket)) { - case _packet2.default.SecretKey.prototype: - case _packet2.default.PublicKey.prototype: - case _packet2.default.SecretSubkey.prototype: - case _packet2.default.PublicSubkey.prototype: - switch (keyPacket.algorithm) { - case 'ecdh': - case 'ecdsa': - case 'eddsa': - pref_algo = _crypto2.default.publicKey.elliptic.getPreferredHashAlgo(keyPacket.params[0]); - } - } - return _crypto2.default.hash.getHashByteLength(hash_algo) <= _crypto2.default.hash.getHashByteLength(pref_algo) ? pref_algo : hash_algo; -} - -/** - * Returns the preferred symmetric/aead algorithm for a set of keys - * @param {symmetric|aead} type Type of preference to return - * @param {Array} keys Set of keys - * @param {Date} date (optional) use the given date for verification instead of the current time - * @param {Array} userIds (optional) user IDs - * @returns {Promise} Preferred symmetric algorithm - * @async - */ -async function getPreferredAlgo(type, keys, date = new Date(), userIds = []) { - const prefProperty = type === 'symmetric' ? 'preferredSymmetricAlgorithms' : 'preferredAeadAlgorithms'; - const defaultAlgo = type === 'symmetric' ? _enums2.default.symmetric.aes128 : _enums2.default.aead.eax; - const prioMap = {}; - await Promise.all(keys.map(async function (key, i) { - const primaryUser = await key.getPrimaryUser(date, userIds[i]); - if (!primaryUser || !primaryUser.selfCertification[prefProperty]) { - return defaultAlgo; - } - primaryUser.selfCertification[prefProperty].forEach(function (algo, index) { - const entry = prioMap[algo] || (prioMap[algo] = { prio: 0, count: 0, algo: algo }); - entry.prio += 64 >> index; - entry.count++; - }); - })); - let prefAlgo = { prio: 0, algo: defaultAlgo }; - Object.values(prioMap).forEach(({ prio, count, algo }) => { - try { - if (algo !== _enums2.default[type].plaintext && algo !== _enums2.default[type].idea && // not implemented - _enums2.default.read(_enums2.default[type], algo) && // known algorithm - count === keys.length && // available for all keys - prio > prefAlgo.prio) { - prefAlgo = prioMap[algo]; - } - } catch (e) {} - }); - return prefAlgo.algo; -} - -/** - * Returns whether aead is supported by all keys in the set - * @param {Array} keys Set of keys - * @param {Date} date (optional) use the given date for verification instead of the current time - * @param {Array} userIds (optional) user IDs - * @returns {Promise} - * @async - */ -async function isAeadSupported(keys, date = new Date(), userIds = []) { - let supported = true; - // TODO replace when Promise.some or Promise.any are implemented - await Promise.all(keys.map(async function (key, i) { - const primaryUser = await key.getPrimaryUser(date, userIds[i]); - if (!primaryUser || !primaryUser.selfCertification.features || !(primaryUser.selfCertification.features[0] & _enums2.default.features.aead)) { - supported = false; - } - })); - return supported; -} - -},{"./config":79,"./crypto":94,"./encoding/armor":111,"./enums":113,"./packet":125,"./util":152}],117:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _keyring = require('./keyring.js'); - -var _keyring2 = _interopRequireDefault(_keyring); - -var _localstore = require('./localstore.js'); - -var _localstore2 = _interopRequireDefault(_localstore); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * @fileoverview Functions dealing with storage of the keyring. - * @see module:keyring/keyring - * @see module:keyring/localstore - * @module keyring - */ -_keyring2.default.localstore = _localstore2.default; - -exports.default = _keyring2.default; - -},{"./keyring.js":118,"./localstore.js":119}],118:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _key = require('../key'); - -var _localstore = require('./localstore'); - -var _localstore2 = _interopRequireDefault(_localstore); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Initialization routine for the keyring. - * @constructor - * @param {keyring/localstore} [storeHandler] class implementing loadPublic(), loadPrivate(), storePublic(), and storePrivate() methods - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @fileoverview Provides the Keyring class - * @requires key - * @requires keyring/localstore - * @module keyring/keyring - */ - -function Keyring(storeHandler) { - this.storeHandler = storeHandler || new _localstore2.default(); -} - -/** - * Calls the storeHandler to load the keys - * @async - */ -Keyring.prototype.load = async function () { - this.publicKeys = new KeyArray((await this.storeHandler.loadPublic())); - this.privateKeys = new KeyArray((await this.storeHandler.loadPrivate())); -}; - -/** - * Calls the storeHandler to save the keys - * @async - */ -Keyring.prototype.store = async function () { - await Promise.all([this.storeHandler.storePublic(this.publicKeys.keys), this.storeHandler.storePrivate(this.privateKeys.keys)]); -}; - -/** - * Clear the keyring - erase all the keys - */ -Keyring.prototype.clear = function () { - this.publicKeys.keys = []; - this.privateKeys.keys = []; -}; - -/** - * Searches the keyring for keys having the specified key id - * @param {String} keyId provided as string of lowercase hex number - * withouth 0x prefix (can be 16-character key ID or fingerprint) - * @param {Boolean} deep if true search also in subkeys - * @returns {Array|null} keys found or null - */ -Keyring.prototype.getKeysForId = function (keyId, deep) { - let result = []; - result = result.concat(this.publicKeys.getForId(keyId, deep) || []); - result = result.concat(this.privateKeys.getForId(keyId, deep) || []); - return result.length ? result : null; -}; - -/** - * Removes keys having the specified key id from the keyring - * @param {String} keyId provided as string of lowercase hex number - * withouth 0x prefix (can be 16-character key ID or fingerprint) - * @returns {Array|null} keys found or null - */ -Keyring.prototype.removeKeysForId = function (keyId) { - let result = []; - result = result.concat(this.publicKeys.removeForId(keyId) || []); - result = result.concat(this.privateKeys.removeForId(keyId) || []); - return result.length ? result : null; -}; - -/** - * Get all public and private keys - * @returns {Array} all keys - */ -Keyring.prototype.getAllKeys = function () { - return this.publicKeys.keys.concat(this.privateKeys.keys); -}; - -/** - * Array of keys - * @param {Array} keys The keys to store in this array - */ -function KeyArray(keys) { - this.keys = keys; -} - -/** - * Searches all keys in the KeyArray matching the address or address part of the user ids - * @param {String} email email address to search for - * @returns {Array} The public keys associated with provided email address. - */ -KeyArray.prototype.getForAddress = function (email) { - const results = []; - for (let i = 0; i < this.keys.length; i++) { - if (emailCheck(email, this.keys[i])) { - results.push(this.keys[i]); - } - } - return results; -}; - -/** - * Checks a key to see if it matches the specified email address - * @private - * @param {String} email email address to search for - * @param {module:key.Key} key The key to be checked. - * @returns {Boolean} True if the email address is defined in the specified key - */ -function emailCheck(email, key) { - email = email.toLowerCase(); - // escape email before using in regular expression - const emailEsc = email.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); - const emailRegex = new RegExp('<' + emailEsc + '>'); - const userIds = key.getUserIds(); - for (let i = 0; i < userIds.length; i++) { - const userId = userIds[i].toLowerCase(); - if (email === userId || emailRegex.test(userId)) { - return true; - } - } - return false; -} - -/** - * Checks a key to see if it matches the specified keyid - * @private - * @param {String} keyId provided as string of lowercase hex number - * withouth 0x prefix (can be 16-character key ID or fingerprint) - * @param {module:key.Key|module:key.SubKey} key The key to be checked - * @returns {Boolean} True if key has the specified keyid - */ -function keyIdCheck(keyId, key) { - if (keyId.length === 16) { - return keyId === key.getKeyId().toHex(); - } - return keyId === key.getFingerprint(); -} - -/** - * Searches the KeyArray for a key having the specified key id - * @param {String} keyId provided as string of lowercase hex number - * withouth 0x prefix (can be 16-character key ID or fingerprint) - * @param {Boolean} deep if true search also in subkeys - * @returns {module:key.Key|null} key found or null - */ -KeyArray.prototype.getForId = function (keyId, deep) { - for (let i = 0; i < this.keys.length; i++) { - if (keyIdCheck(keyId, this.keys[i])) { - return this.keys[i]; - } - if (deep && this.keys[i].subKeys.length) { - for (let j = 0; j < this.keys[i].subKeys.length; j++) { - if (keyIdCheck(keyId, this.keys[i].subKeys[j])) { - return this.keys[i]; - } - } - } - } - return null; -}; - -/** - * Imports a key from an ascii armored message - * @param {String} armored message to read the keys/key from - * @returns {Promise|null>} array of error objects or null - * @async - */ -KeyArray.prototype.importKey = async function (armored) { - const imported = await (0, _key.readArmored)(armored); - for (let i = 0; i < imported.keys.length; i++) { - const key = imported.keys[i]; - // check if key already in key array - const keyidHex = key.getKeyId().toHex(); - const keyFound = this.getForId(keyidHex); - if (keyFound) { - await keyFound.update(key); - } else { - this.push(key); - } - } - return imported.err ? imported.err : null; -}; - -/** - * Add key to KeyArray - * @param {module:key.Key} key The key that will be added to the keyring - * @returns {Number} The new length of the KeyArray - */ -KeyArray.prototype.push = function (key) { - return this.keys.push(key); -}; - -/** - * Removes a key with the specified keyid from the keyring - * @param {String} keyId provided as string of lowercase hex number - * withouth 0x prefix (can be 16-character key ID or fingerprint) - * @returns {module:key.Key|null} The key object which has been removed or null - */ -KeyArray.prototype.removeForId = function (keyId) { - for (let i = 0; i < this.keys.length; i++) { - if (keyIdCheck(keyId, this.keys[i])) { - return this.keys.splice(i, 1)[0]; - } - } - return null; -}; - -exports.default = Keyring; - -},{"../key":116,"./localstore":119}],119:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _webStreamTools = require('web-stream-tools'); - -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); - -var _config = require('../config'); - -var _config2 = _interopRequireDefault(_config); - -var _key = require('../key'); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * The class that deals with storage of the keyring. - * Currently the only option is to use HTML5 local storage. - * @constructor - * @param {String} prefix prefix for itemnames in localstore - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @fileoverview Provides the LocalStore class - * @requires web-stream-tools - * @requires config - * @requires key - * @requires util - * @module keyring/localstore - */ - -function LocalStore(prefix) { - prefix = prefix || 'openpgp-'; - this.publicKeysItem = prefix + this.publicKeysItem; - this.privateKeysItem = prefix + this.privateKeysItem; - if (typeof window !== 'undefined' && window.localStorage) { - this.storage = window.localStorage; - } else { - this.storage = new (require('node-localstorage').LocalStorage)(_config2.default.node_store); - } -} - -/* - * Declare the localstore itemnames - */ -LocalStore.prototype.publicKeysItem = 'public-keys'; -LocalStore.prototype.privateKeysItem = 'private-keys'; - -/** - * Load the public keys from HTML5 local storage. - * @returns {Array} array of keys retrieved from localstore - * @async - */ -LocalStore.prototype.loadPublic = async function () { - return loadKeys(this.storage, this.publicKeysItem); -}; - -/** - * Load the private keys from HTML5 local storage. - * @returns {Array} array of keys retrieved from localstore - * @async - */ -LocalStore.prototype.loadPrivate = async function () { - return loadKeys(this.storage, this.privateKeysItem); -}; - -async function loadKeys(storage, itemname) { - const armoredKeys = JSON.parse(storage.getItem(itemname)); - const keys = []; - if (armoredKeys !== null && armoredKeys.length !== 0) { - let key; - for (let i = 0; i < armoredKeys.length; i++) { - key = await (0, _key.readArmored)(armoredKeys[i]); - if (!key.err) { - keys.push(key.keys[0]); - } else { - _util2.default.print_debug("Error reading armored key from keyring index: " + i); - } - } - } - return keys; -} - -/** - * Saves the current state of the public keys to HTML5 local storage. - * The key array gets stringified using JSON - * @param {Array} keys array of keys to save in localstore - * @async - */ -LocalStore.prototype.storePublic = async function (keys) { - await storeKeys(this.storage, this.publicKeysItem, keys); -}; - -/** - * Saves the current state of the private keys to HTML5 local storage. - * The key array gets stringified using JSON - * @param {Array} keys array of keys to save in localstore - * @async - */ -LocalStore.prototype.storePrivate = async function (keys) { - await storeKeys(this.storage, this.privateKeysItem, keys); -}; - -async function storeKeys(storage, itemname, keys) { - if (keys.length) { - const armoredKeys = await Promise.all(keys.map(key => _webStreamTools2.default.readToEnd(key.armor()))); - storage.setItem(itemname, JSON.stringify(armoredKeys)); - } else { - storage.removeItem(itemname); - } -} - -exports.default = LocalStore; - -},{"../config":79,"../key":116,"../util":152,"node-localstorage":"node-localstorage","web-stream-tools":75}],120:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.Message = Message; -exports.encryptSessionKey = encryptSessionKey; -exports.createSignaturePackets = createSignaturePackets; -exports.createVerificationObjects = createVerificationObjects; -exports.readArmored = readArmored; -exports.read = read; -exports.fromText = fromText; -exports.fromBinary = fromBinary; - -var _webStreamTools = require('web-stream-tools'); - -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); - -var _armor = require('./encoding/armor'); - -var _armor2 = _interopRequireDefault(_armor); - -var _keyid = require('./type/keyid'); - -var _keyid2 = _interopRequireDefault(_keyid); - -var _config = require('./config'); - -var _config2 = _interopRequireDefault(_config); - -var _crypto = require('./crypto'); - -var _crypto2 = _interopRequireDefault(_crypto); - -var _enums = require('./enums'); - -var _enums2 = _interopRequireDefault(_enums); - -var _util = require('./util'); - -var _util2 = _interopRequireDefault(_util); - -var _packet = require('./packet'); - -var _packet2 = _interopRequireDefault(_packet); - -var _signature = require('./signature'); - -var _key = require('./key'); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * @class - * @classdesc Class that represents an OpenPGP message. - * Can be an encrypted message, signed message, compressed message or literal message - * @param {module:packet.List} packetlist The packets that form this message - * See {@link https://tools.ietf.org/html/rfc4880#section-11.3} - */ - -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @requires web-stream-tools - * @requires encoding/armor - * @requires type/keyid - * @requires config - * @requires crypto - * @requires enums - * @requires util - * @requires packet - * @requires signature - * @requires key - * @module message - */ - -function Message(packetlist) { - if (!(this instanceof Message)) { - return new Message(packetlist); - } - this.packets = packetlist || new _packet2.default.List(); -} - -/** - * Returns the key IDs of the keys to which the session key is encrypted - * @returns {Array} array of keyid objects - */ -Message.prototype.getEncryptionKeyIds = function () { - const keyIds = []; - const pkESKeyPacketlist = this.packets.filterByTag(_enums2.default.packet.publicKeyEncryptedSessionKey); - pkESKeyPacketlist.forEach(function (packet) { - keyIds.push(packet.publicKeyId); - }); - return keyIds; -}; - -/** - * Returns the key IDs of the keys that signed the message - * @returns {Array} array of keyid objects - */ -Message.prototype.getSigningKeyIds = function () { - const keyIds = []; - const msg = this.unwrapCompressed(); - // search for one pass signatures - const onePassSigList = msg.packets.filterByTag(_enums2.default.packet.onePassSignature); - onePassSigList.forEach(function (packet) { - keyIds.push(packet.issuerKeyId); - }); - // if nothing found look for signature packets - if (!keyIds.length) { - const signatureList = msg.packets.filterByTag(_enums2.default.packet.signature); - signatureList.forEach(function (packet) { - keyIds.push(packet.issuerKeyId); - }); - } - return keyIds; -}; - -/** - * Decrypt the message. Either a private key, a session key, or a password must be specified. - * @param {Array} privateKeys (optional) private keys with decrypted secret data - * @param {Array} passwords (optional) passwords used to decrypt - * @param {Array} sessionKeys (optional) session keys in the form: { data:Uint8Array, algorithm:String, [aeadAlgorithm:String] } - * @param {Boolean} streaming (optional) whether to process data as a stream - * @returns {Promise} new message with decrypted content - * @async - */ -Message.prototype.decrypt = async function (privateKeys, passwords, sessionKeys, streaming) { - const keyObjs = sessionKeys || (await this.decryptSessionKeys(privateKeys, passwords)); - - const symEncryptedPacketlist = this.packets.filterByTag(_enums2.default.packet.symmetricallyEncrypted, _enums2.default.packet.symEncryptedIntegrityProtected, _enums2.default.packet.symEncryptedAEADProtected); - - if (symEncryptedPacketlist.length === 0) { - return this; - } - - const symEncryptedPacket = symEncryptedPacketlist[0]; - let exception = null; - const decryptedPromise = Promise.all(keyObjs.map(async keyObj => { - if (!keyObj || !_util2.default.isUint8Array(keyObj.data) || !_util2.default.isString(keyObj.algorithm)) { - throw new Error('Invalid session key for decryption.'); - } - - try { - await symEncryptedPacket.decrypt(keyObj.algorithm, keyObj.data, streaming); - } catch (e) { - _util2.default.print_debug_error(e); - exception = e; - } - })); - // We don't await stream.cancel here because it only returns when the other copy is canceled too. - _webStreamTools2.default.cancel(symEncryptedPacket.encrypted); // Don't keep copy of encrypted data in memory. - symEncryptedPacket.encrypted = null; - await decryptedPromise; - - if (!symEncryptedPacket.packets || !symEncryptedPacket.packets.length) { - throw exception || new Error('Decryption failed.'); - } - - const resultMsg = new Message(symEncryptedPacket.packets); - symEncryptedPacket.packets = new _packet2.default.List(); // remove packets after decryption - - return resultMsg; -}; - -/** - * Decrypt encrypted session keys either with private keys or passwords. - * @param {Array} privateKeys (optional) private keys with decrypted secret data - * @param {Array} passwords (optional) passwords used to decrypt - * @returns {Promise>} array of object with potential sessionKey, algorithm pairs - * @async - */ -Message.prototype.decryptSessionKeys = async function (privateKeys, passwords) { - let keyPackets = []; - - let exception; - if (passwords) { - const symESKeyPacketlist = this.packets.filterByTag(_enums2.default.packet.symEncryptedSessionKey); - if (!symESKeyPacketlist) { - throw new Error('No symmetrically encrypted session key packet found.'); - } - await Promise.all(passwords.map(async function (password, i) { - let packets; - if (i) { - packets = new _packet2.default.List(); - await packets.read(symESKeyPacketlist.write()); - } else { - packets = symESKeyPacketlist; - } - await Promise.all(packets.map(async function (keyPacket) { - try { - await keyPacket.decrypt(password); - keyPackets.push(keyPacket); - } catch (err) { - _util2.default.print_debug_error(err); - } - })); - })); - } else if (privateKeys) { - const pkESKeyPacketlist = this.packets.filterByTag(_enums2.default.packet.publicKeyEncryptedSessionKey); - if (!pkESKeyPacketlist) { - throw new Error('No public key encrypted session key packet found.'); - } - await Promise.all(pkESKeyPacketlist.map(async function (keyPacket) { - await Promise.all(privateKeys.map(async function (privateKey) { - const primaryUser = await privateKey.getPrimaryUser(); // TODO: Pass userId from somewhere. - let algos = [_enums2.default.symmetric.aes256, // Old OpenPGP.js default fallback - _enums2.default.symmetric.aes128, // RFC4880bis fallback - _enums2.default.symmetric.tripledes, // RFC4880 fallback - _enums2.default.symmetric.cast5 // Golang OpenPGP fallback - ]; - if (primaryUser && primaryUser.selfCertification.preferredSymmetricAlgorithms) { - algos = algos.concat(primaryUser.selfCertification.preferredSymmetricAlgorithms); - } - - const privateKeyPackets = privateKey.getKeys(keyPacket.publicKeyId).map(key => key.keyPacket); - await Promise.all(privateKeyPackets.map(async function (privateKeyPacket) { - if (!privateKeyPacket) { - return; - } - if (!privateKeyPacket.isDecrypted()) { - throw new Error('Private key is not decrypted.'); - } - try { - await keyPacket.decrypt(privateKeyPacket); - if (!algos.includes(_enums2.default.write(_enums2.default.symmetric, keyPacket.sessionKeyAlgorithm))) { - throw new Error('A non-preferred symmetric algorithm was used.'); - } - keyPackets.push(keyPacket); - } catch (err) { - _util2.default.print_debug_error(err); - exception = err; - } - })); - })); - _webStreamTools2.default.cancel(keyPacket.encrypted); // Don't keep copy of encrypted data in memory. - keyPacket.encrypted = null; - })); - } else { - throw new Error('No key or password specified.'); - } - - if (keyPackets.length) { - // Return only unique session keys - if (keyPackets.length > 1) { - const seen = {}; - keyPackets = keyPackets.filter(function (item) { - const k = item.sessionKeyAlgorithm + _util2.default.Uint8Array_to_str(item.sessionKey); - if (seen.hasOwnProperty(k)) { - return false; - } - seen[k] = true; - return true; - }); - } - - return keyPackets.map(packet => ({ data: packet.sessionKey, algorithm: packet.sessionKeyAlgorithm })); - } - throw exception || new Error('Session key decryption failed.'); -}; - -/** - * Get literal data that is the body of the message - * @returns {(Uint8Array|null)} literal body of the message as Uint8Array - */ -Message.prototype.getLiteralData = function () { - const msg = this.unwrapCompressed(); - const literal = msg.packets.findPacket(_enums2.default.packet.literal); - return literal && literal.getBytes() || null; -}; - -/** - * Get filename from literal data packet - * @returns {(String|null)} filename of literal data packet as string - */ -Message.prototype.getFilename = function () { - const msg = this.unwrapCompressed(); - const literal = msg.packets.findPacket(_enums2.default.packet.literal); - return literal && literal.getFilename() || null; -}; - -/** - * Get literal data as text - * @returns {(String|null)} literal body of the message interpreted as text - */ -Message.prototype.getText = function () { - const msg = this.unwrapCompressed(); - const literal = msg.packets.findPacket(_enums2.default.packet.literal); - if (literal) { - return literal.getText(); - } - return null; -}; - -/** - * Encrypt the message either with public keys, passwords, or both at once. - * @param {Array} keys (optional) public key(s) for message encryption - * @param {Array} passwords (optional) password(s) for message encryption - * @param {Object} sessionKey (optional) session key in the form: { data:Uint8Array, algorithm:String, [aeadAlgorithm:String] } - * @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs - * @param {Date} date (optional) override the creation date of the literal package - * @param {Array} userIds (optional) user IDs to encrypt for, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }] - * @param {Boolean} streaming (optional) whether to process data as a stream - * @returns {Promise} new message with encrypted content - * @async - */ -Message.prototype.encrypt = async function (keys, passwords, sessionKey, wildcard = false, date = new Date(), userIds = [], streaming) { - let symAlgo; - let aeadAlgo; - let symEncryptedPacket; - - if (sessionKey) { - if (!_util2.default.isUint8Array(sessionKey.data) || !_util2.default.isString(sessionKey.algorithm)) { - throw new Error('Invalid session key for encryption.'); - } - symAlgo = sessionKey.algorithm; - aeadAlgo = sessionKey.aeadAlgorithm; - sessionKey = sessionKey.data; - } else if (keys && keys.length) { - symAlgo = _enums2.default.read(_enums2.default.symmetric, (await (0, _key.getPreferredAlgo)('symmetric', keys, date, userIds))); - if (_config2.default.aead_protect && (await (0, _key.isAeadSupported)(keys, date, userIds))) { - aeadAlgo = _enums2.default.read(_enums2.default.aead, (await (0, _key.getPreferredAlgo)('aead', keys, date, userIds))); - } - } else if (passwords && passwords.length) { - symAlgo = _enums2.default.read(_enums2.default.symmetric, _config2.default.encryption_cipher); - aeadAlgo = _enums2.default.read(_enums2.default.aead, _config2.default.aead_mode); - } else { - throw new Error('No keys, passwords, or session key provided.'); - } - - if (!sessionKey) { - sessionKey = await _crypto2.default.generateSessionKey(symAlgo); - } - - const msg = await encryptSessionKey(sessionKey, symAlgo, aeadAlgo, keys, passwords, wildcard, date, userIds); - - if (_config2.default.aead_protect && aeadAlgo) { - symEncryptedPacket = new _packet2.default.SymEncryptedAEADProtected(); - symEncryptedPacket.aeadAlgorithm = aeadAlgo; - } else if (_config2.default.integrity_protect) { - symEncryptedPacket = new _packet2.default.SymEncryptedIntegrityProtected(); - } else { - symEncryptedPacket = new _packet2.default.SymmetricallyEncrypted(); - } - symEncryptedPacket.packets = this.packets; - - await symEncryptedPacket.encrypt(symAlgo, sessionKey, streaming); - - msg.packets.push(symEncryptedPacket); - symEncryptedPacket.packets = new _packet2.default.List(); // remove packets after encryption - return { - message: msg, - sessionKey: { - data: sessionKey, - algorithm: symAlgo, - aeadAlgorithm: aeadAlgo - } - }; -}; - -/** - * Encrypt a session key either with public keys, passwords, or both at once. - * @param {Uint8Array} sessionKey session key for encryption - * @param {String} symAlgo session key algorithm - * @param {String} aeadAlgo (optional) aead algorithm, e.g. 'eax' or 'ocb' - * @param {Array} publicKeys (optional) public key(s) for message encryption - * @param {Array} passwords (optional) for message encryption - * @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs - * @param {Date} date (optional) override the date - * @param {Array} userIds (optional) user IDs to encrypt for, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }] - * @returns {Promise} new message with encrypted content - * @async - */ -async function encryptSessionKey(sessionKey, symAlgo, aeadAlgo, publicKeys, passwords, wildcard = false, date = new Date(), userIds = []) { - const packetlist = new _packet2.default.List(); - - if (publicKeys) { - const results = await Promise.all(publicKeys.map(async function (publicKey) { - const encryptionKey = await publicKey.getEncryptionKey(undefined, date, userIds); - if (!encryptionKey) { - throw new Error('Could not find valid key packet for encryption in key ' + publicKey.getKeyId().toHex()); - } - const pkESKeyPacket = new _packet2.default.PublicKeyEncryptedSessionKey(); - pkESKeyPacket.publicKeyId = wildcard ? _keyid2.default.wildcard() : encryptionKey.getKeyId(); - pkESKeyPacket.publicKeyAlgorithm = encryptionKey.keyPacket.algorithm; - pkESKeyPacket.sessionKey = sessionKey; - pkESKeyPacket.sessionKeyAlgorithm = symAlgo; - await pkESKeyPacket.encrypt(encryptionKey.keyPacket); - delete pkESKeyPacket.sessionKey; // delete plaintext session key after encryption - return pkESKeyPacket; - })); - packetlist.concat(results); - } - if (passwords) { - const testDecrypt = async function testDecrypt(keyPacket, password) { - try { - await keyPacket.decrypt(password); - return 1; - } catch (e) { - return 0; - } - }; - - const sum = (accumulator, currentValue) => accumulator + currentValue; - - const encryptPassword = async function encryptPassword(sessionKey, symAlgo, aeadAlgo, password) { - const symEncryptedSessionKeyPacket = new _packet2.default.SymEncryptedSessionKey(); - symEncryptedSessionKeyPacket.sessionKey = sessionKey; - symEncryptedSessionKeyPacket.sessionKeyAlgorithm = symAlgo; - if (aeadAlgo) { - symEncryptedSessionKeyPacket.aeadAlgorithm = aeadAlgo; - } - await symEncryptedSessionKeyPacket.encrypt(password); - - if (_config2.default.password_collision_check) { - const results = await Promise.all(passwords.map(pwd => testDecrypt(symEncryptedSessionKeyPacket, pwd))); - if (results.reduce(sum) !== 1) { - return encryptPassword(sessionKey, symAlgo, password); - } - } - - delete symEncryptedSessionKeyPacket.sessionKey; // delete plaintext session key after encryption - return symEncryptedSessionKeyPacket; - }; - - const results = await Promise.all(passwords.map(pwd => encryptPassword(sessionKey, symAlgo, aeadAlgo, pwd))); - packetlist.concat(results); - } - - return new Message(packetlist); -} - -/** - * Sign the message (the literal data packet of the message) - * @param {Array} privateKeys private keys with decrypted secret key data for signing - * @param {Signature} signature (optional) any existing detached signature to add to the message - * @param {Date} date (optional) override the creation time of the signature - * @param {Array} userIds (optional) user IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] - * @returns {Promise} new message with signed content - * @async - */ -Message.prototype.sign = async function (privateKeys = [], signature = null, date = new Date(), userIds = []) { - const packetlist = new _packet2.default.List(); - - const literalDataPacket = this.packets.findPacket(_enums2.default.packet.literal); - if (!literalDataPacket) { - throw new Error('No literal data packet to sign.'); - } - - let i; - let existingSigPacketlist; - // If data packet was created from Uint8Array, use binary, otherwise use text - const signatureType = literalDataPacket.text === null ? _enums2.default.signature.binary : _enums2.default.signature.text; - - if (signature) { - existingSigPacketlist = signature.packets.filterByTag(_enums2.default.packet.signature); - for (i = existingSigPacketlist.length - 1; i >= 0; i--) { - const signaturePacket = existingSigPacketlist[i]; - const onePassSig = new _packet2.default.OnePassSignature(); - onePassSig.signatureType = signaturePacket.signatureType; - onePassSig.hashAlgorithm = signaturePacket.hashAlgorithm; - onePassSig.publicKeyAlgorithm = signaturePacket.publicKeyAlgorithm; - onePassSig.issuerKeyId = signaturePacket.issuerKeyId; - if (!privateKeys.length && i === 0) { - onePassSig.flags = 1; - } - packetlist.push(onePassSig); - } - } - - await Promise.all(Array.from(privateKeys).reverse().map(async function (privateKey, i) { - if (privateKey.isPublic()) { - throw new Error('Need private key for signing'); - } - const signingKey = await privateKey.getSigningKey(undefined, date, userIds); - if (!signingKey) { - throw new Error('Could not find valid key packet for signing in key ' + privateKey.getKeyId().toHex()); - } - const onePassSig = new _packet2.default.OnePassSignature(); - onePassSig.signatureType = signatureType; - onePassSig.hashAlgorithm = await (0, _key.getPreferredHashAlgo)(privateKey, signingKey.keyPacket, date, userIds); - onePassSig.publicKeyAlgorithm = signingKey.keyPacket.algorithm; - onePassSig.issuerKeyId = signingKey.getKeyId(); - if (i === privateKeys.length - 1) { - onePassSig.flags = 1; - } - return onePassSig; - })).then(onePassSignatureList => { - onePassSignatureList.forEach(onePassSig => packetlist.push(onePassSig)); - }); - - packetlist.push(literalDataPacket); - packetlist.concat((await createSignaturePackets(literalDataPacket, privateKeys, signature, date, false))); - - return new Message(packetlist); -}; - -/** - * Compresses the message (the literal and -if signed- signature data packets of the message) - * @param {module:enums.compression} compression compression algorithm to be used - * @returns {module:message.Message} new message with compressed content - */ -Message.prototype.compress = function (compression) { - if (compression === _enums2.default.compression.uncompressed) { - return this; - } - - const compressed = new _packet2.default.Compressed(); - compressed.packets = this.packets; - compressed.algorithm = _enums2.default.read(_enums2.default.compression, compression); - - const packetList = new _packet2.default.List(); - packetList.push(compressed); - - return new Message(packetList); -}; - -/** - * Create a detached signature for the message (the literal data packet of the message) - * @param {Array} privateKeys private keys with decrypted secret key data for signing - * @param {Signature} signature (optional) any existing detached signature - * @param {Date} date (optional) override the creation time of the signature - * @param {Array} userIds (optional) user IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] - * @returns {Promise} new detached signature of message content - * @async - */ -Message.prototype.signDetached = async function (privateKeys = [], signature = null, date = new Date(), userIds = []) { - const literalDataPacket = this.packets.findPacket(_enums2.default.packet.literal); - if (!literalDataPacket) { - throw new Error('No literal data packet to sign.'); - } - return new _signature.Signature((await createSignaturePackets(literalDataPacket, privateKeys, signature, date, userIds, true))); -}; - -/** - * Create signature packets for the message - * @param {module:packet.Literal} literalDataPacket the literal data packet to sign - * @param {Array} privateKeys private keys with decrypted secret key data for signing - * @param {Signature} signature (optional) any existing detached signature to append - * @param {Date} date (optional) override the creationtime of the signature - * @param {Array} userIds (optional) user IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] - * @param {Boolean} detached (optional) whether to create detached signature packets - * @returns {Promise} list of signature packets - * @async - */ -async function createSignaturePackets(literalDataPacket, privateKeys, signature = null, date = new Date(), userIds = [], detached = false) { - const packetlist = new _packet2.default.List(); - - // If data packet was created from Uint8Array, use binary, otherwise use text - const signatureType = literalDataPacket.text === null ? _enums2.default.signature.binary : _enums2.default.signature.text; - - await Promise.all(privateKeys.map(async (privateKey, i) => { - const userId = userIds[i]; - if (privateKey.isPublic()) { - throw new Error('Need private key for signing'); - } - const signingKey = await privateKey.getSigningKey(undefined, date, userId); - if (!signingKey) { - throw new Error(`Could not find valid signing key packet in key ${privateKey.getKeyId().toHex()}`); - } - return (0, _key.createSignaturePacket)(literalDataPacket, privateKey, signingKey.keyPacket, { signatureType }, date, userId, detached); - })).then(signatureList => { - signatureList.forEach(signaturePacket => packetlist.push(signaturePacket)); - }); - - if (signature) { - const existingSigPacketlist = signature.packets.filterByTag(_enums2.default.packet.signature); - packetlist.concat(existingSigPacketlist); - } - return packetlist; -} - -/** - * Verify message signatures - * @param {Array} keys array of keys to verify signatures - * @param {Date} date (optional) Verify the signature against the given date, i.e. check signature creation time < date < expiration time - * @param {Boolean} streaming (optional) whether to process data as a stream - * @returns {Promise>} list of signer's keyid and validity of signature - * @async - */ -Message.prototype.verify = async function (keys, date = new Date(), streaming) { - const msg = this.unwrapCompressed(); - const literalDataList = msg.packets.filterByTag(_enums2.default.packet.literal); - if (literalDataList.length !== 1) { - throw new Error('Can only verify message with one literal data packet.'); - } - const onePassSigList = msg.packets.filterByTag(_enums2.default.packet.onePassSignature).reverse(); - const signatureList = msg.packets.filterByTag(_enums2.default.packet.signature); - if (onePassSigList.length && !signatureList.length && msg.packets.stream) { - await Promise.all(onePassSigList.map(async onePassSig => { - onePassSig.correspondingSig = new Promise((resolve, reject) => { - onePassSig.correspondingSigResolve = resolve; - onePassSig.correspondingSigReject = reject; - }); - onePassSig.signatureData = _webStreamTools2.default.fromAsync(async () => (await onePassSig.correspondingSig).signatureData); - onePassSig.hashed = await onePassSig.hash(onePassSig.signatureType, literalDataList[0], undefined, false, streaming); - })); - msg.packets.stream = _webStreamTools2.default.transformPair(msg.packets.stream, async (readable, writable) => { - const reader = _webStreamTools2.default.getReader(readable); - const writer = _webStreamTools2.default.getWriter(writable); - try { - for (let i = 0; i < onePassSigList.length; i++) { - var _ref = await reader.read(); - - const signature = _ref.value; - - onePassSigList[i].correspondingSigResolve(signature); - } - await reader.readToEnd(); - await writer.ready; - await writer.close(); - } catch (e) { - onePassSigList.forEach(onePassSig => { - onePassSig.correspondingSigReject(e); - }); - await writer.abort(e); - } - }); - return createVerificationObjects(onePassSigList, literalDataList, keys, date, false); - } - return createVerificationObjects(signatureList, literalDataList, keys, date, false); -}; - -/** - * Verify detached message signature - * @param {Array} keys array of keys to verify signatures - * @param {Signature} signature - * @param {Date} date Verify the signature against the given date, i.e. check signature creation time < date < expiration time - * @returns {Promise>} list of signer's keyid and validity of signature - * @async - */ -Message.prototype.verifyDetached = function (signature, keys, date = new Date()) { - const msg = this.unwrapCompressed(); - const literalDataList = msg.packets.filterByTag(_enums2.default.packet.literal); - if (literalDataList.length !== 1) { - throw new Error('Can only verify message with one literal data packet.'); - } - const signatureList = signature.packets; - return createVerificationObjects(signatureList, literalDataList, keys, date, true); -}; - -/** - * Create object containing signer's keyid and validity of signature - * @param {module:packet.Signature} signature signature packets - * @param {Array} literalDataList array of literal data packets - * @param {Array} keys array of keys to verify signatures - * @param {Date} date Verify the signature against the given date, - * i.e. check signature creation time < date < expiration time - * @param {Boolean} detached (optional) whether to verify detached signature packets - * @returns {Promise>} list of signer's keyid and validity of signature - * @async - */ -async function createVerificationObject(signature, literalDataList, keys, date = new Date(), detached = false) { - let primaryKey = null; - let signingKey = null; - await Promise.all(keys.map(async function (key) { - // Look for the unique key that matches issuerKeyId of signature - const result = await key.getSigningKey(signature.issuerKeyId, null); - if (result) { - primaryKey = key; - signingKey = result; - } - })); - - const signaturePacket = signature.correspondingSig || signature; - const verifiedSig = { - keyid: signature.issuerKeyId, - verified: (async () => { - if (!signingKey) { - return null; - } - const verified = await signature.verify(signingKey.keyPacket, signature.signatureType, literalDataList[0], detached); - const sig = await signaturePacket; - if (sig.isExpired(date) || !(sig.created >= signingKey.getCreationTime() && sig.created < (await (signingKey === primaryKey ? signingKey.getExpirationTime() : signingKey.getExpirationTime(primaryKey, date))))) { - return null; - } - return verified; - })(), - signature: (async () => { - const sig = await signaturePacket; - const packetlist = new _packet2.default.List(); - packetlist.push(sig); - return new _signature.Signature(packetlist); - })() - }; - - // Mark potential promise rejections as "handled". This is needed because in - // some cases, we reject them before the user has a reasonable chance to - // handle them (e.g. `await readToEnd(result.data); await result.verified` and - // the data stream errors). - verifiedSig.signature.catch(() => {}); - verifiedSig.verified.catch(() => {}); - - return verifiedSig; -} - -/** - * Create list of objects containing signer's keyid and validity of signature - * @param {Array} signatureList array of signature packets - * @param {Array} literalDataList array of literal data packets - * @param {Array} keys array of keys to verify signatures - * @param {Date} date Verify the signature against the given date, - * i.e. check signature creation time < date < expiration time - * @param {Boolean} detached (optional) whether to verify detached signature packets - * @returns {Promise>} list of signer's keyid and validity of signature - * @async - */ -async function createVerificationObjects(signatureList, literalDataList, keys, date = new Date(), detached = false) { - return Promise.all(signatureList.filter(function (signature) { - return ['text', 'binary'].includes(_enums2.default.read(_enums2.default.signature, signature.signatureType)); - }).map(async function (signature) { - return createVerificationObject(signature, literalDataList, keys, date, detached); - })); -} - -/** - * Unwrap compressed message - * @returns {module:message.Message} message Content of compressed message - */ -Message.prototype.unwrapCompressed = function () { - const compressed = this.packets.filterByTag(_enums2.default.packet.compressed); - if (compressed.length) { - return new Message(compressed[0].packets); - } - return this; -}; - -/** - * Append signature to unencrypted message object - * @param {String|Uint8Array} detachedSignature The detached ASCII-armored or Uint8Array PGP signature - */ -Message.prototype.appendSignature = async function (detachedSignature) { - await this.packets.read(_util2.default.isUint8Array(detachedSignature) ? detachedSignature : (await _armor2.default.decode(detachedSignature)).data); -}; - -/** - * Returns ASCII armored text of message - * @returns {ReadableStream} ASCII armor - */ -Message.prototype.armor = function () { - return _armor2.default.encode(_enums2.default.armor.message, this.packets.write()); -}; - -/** - * reads an OpenPGP armored message and returns a message object - * @param {String | ReadableStream} armoredText text to be parsed - * @returns {Promise} new message object - * @async - * @static - */ -async function readArmored(armoredText) { - //TODO how do we want to handle bad text? Exception throwing - //TODO don't accept non-message armored texts - const streamType = _util2.default.isStream(armoredText); - if (streamType === 'node') { - armoredText = _webStreamTools2.default.nodeToWeb(armoredText); - } - const input = await _armor2.default.decode(armoredText); - return read(input.data, streamType); -} - -/** - * reads an OpenPGP message as byte array and returns a message object - * @param {Uint8Array | ReadableStream} input binary message - * @param {Boolean} fromStream whether the message was created from a Stream - * @returns {Promise} new message object - * @async - * @static - */ -async function read(input, fromStream = _util2.default.isStream(input)) { - const streamType = _util2.default.isStream(input); - if (streamType === 'node') { - input = _webStreamTools2.default.nodeToWeb(input); - } - const packetlist = new _packet2.default.List(); - await packetlist.read(input, fromStream); - const message = new Message(packetlist); - message.fromStream = fromStream; - return message; -} - -/** - * creates new message object from text - * @param {String | ReadableStream} text - * @param {String} filename (optional) - * @param {Date} date (optional) - * @param {utf8|binary|text|mime} type (optional) data packet type - * @returns {module:message.Message} new message object - * @static - */ -function fromText(text, filename, date = new Date(), type = 'utf8') { - const streamType = _util2.default.isStream(text); - if (streamType === 'node') { - text = _webStreamTools2.default.nodeToWeb(text); - } - const literalDataPacket = new _packet2.default.Literal(date); - // text will be converted to UTF8 - literalDataPacket.setText(text, type); - if (filename !== undefined) { - literalDataPacket.setFilename(filename); - } - const literalDataPacketlist = new _packet2.default.List(); - literalDataPacketlist.push(literalDataPacket); - const message = new Message(literalDataPacketlist); - message.fromStream = streamType; - return message; -} - -/** - * creates new message object from binary data - * @param {Uint8Array | ReadableStream} bytes - * @param {String} filename (optional) - * @param {Date} date (optional) - * @param {utf8|binary|text|mime} type (optional) data packet type - * @returns {module:message.Message} new message object - * @static - */ -function fromBinary(bytes, filename, date = new Date(), type = 'binary') { - const streamType = _util2.default.isStream(bytes); - if (!_util2.default.isUint8Array(bytes) && !streamType) { - throw new Error('Data must be in the form of a Uint8Array or Stream'); - } - if (streamType === 'node') { - bytes = _webStreamTools2.default.nodeToWeb(bytes); - } - - const literalDataPacket = new _packet2.default.Literal(date); - literalDataPacket.setBytes(bytes, type); - if (filename !== undefined) { - literalDataPacket.setFilename(filename); - } - const literalDataPacketlist = new _packet2.default.List(); - literalDataPacketlist.push(literalDataPacket); - const message = new Message(literalDataPacketlist); - message.fromStream = streamType; - return message; -} - -},{"./config":79,"./crypto":94,"./encoding/armor":111,"./enums":113,"./key":116,"./packet":125,"./signature":145,"./type/keyid":148,"./util":152,"web-stream-tools":75}],121:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.initWorker = initWorker; -exports.getWorker = getWorker; -exports.destroyWorker = destroyWorker; -exports.generateKey = generateKey; -exports.reformatKey = reformatKey; -exports.revokeKey = revokeKey; -exports.decryptKey = decryptKey; -exports.encryptKey = encryptKey; -exports.encrypt = encrypt; -exports.decrypt = decrypt; -exports.sign = sign; -exports.verify = verify; -exports.encryptSessionKey = encryptSessionKey; -exports.decryptSessionKeys = decryptSessionKeys; - -var _webStreamTools = require('web-stream-tools'); - -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); - -var _message = require('./message'); - -var messageLib = _interopRequireWildcard(_message); - -var _cleartext = require('./cleartext'); - -var _key = require('./key'); - -var _config = require('./config/config'); - -var _config2 = _interopRequireDefault(_config); - -var _enums = require('./enums'); - -var _enums2 = _interopRequireDefault(_enums); - -require('./polyfills'); - -var _util = require('./util'); - -var _util2 = _interopRequireDefault(_util); - -var _async_proxy = require('./worker/async_proxy'); - -var _async_proxy2 = _interopRequireDefault(_async_proxy); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -////////////////////////// -// // -// Web Worker setup // -// // -////////////////////////// - - -let asyncProxy; // instance of the asyncproxy - -/** - * Set the path for the web worker script and create an instance of the async proxy - * @param {String} path relative path to the worker scripts, default: 'openpgp.worker.js' - * @param {Number} n number of workers to initialize - * @param {Array} workers alternative to path parameter: web workers initialized with 'openpgp.worker.js' - * @returns {Promise} returns a promise that resolves to true if all workers have succesfully finished loading - * @async - */ -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2016 Tankred Hase -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @fileoverview The openpgp base module should provide all of the functionality - * to consume the openpgp.js library. All additional classes are documented - * for extending and developing on top of the base library. - * @requires web-stream-tools - * @requires message - * @requires cleartext - * @requires key - * @requires config - * @requires enums - * @requires util - * @requires polyfills - * @requires worker/async_proxy - * @module openpgp - */ - -// This file intentionally has two separate file overviews so that -// a reference to this module appears at the end of doc/index.html. - -/** - * @fileoverview To view the full API documentation, start from - * {@link module:openpgp} - */ - -async function initWorker({ path = 'openpgp.worker.js', n = 1, workers = [] } = {}) { - if (workers.length || typeof window !== 'undefined' && window.Worker && window.MessageChannel) { - const proxy = new _async_proxy2.default({ path, n, workers, config: _config2.default }); - const loaded = await proxy.loaded(); - if (loaded) { - asyncProxy = proxy; - return true; - } - } - return false; -} - -/** - * Returns a reference to the async proxy if the worker was initialized with openpgp.initWorker() - * @returns {module:worker/async_proxy.AsyncProxy|null} the async proxy or null if not initialized - */ -function getWorker() { - return asyncProxy; -} - -/** - * Cleanup the current instance of the web worker. - */ -function destroyWorker() { - asyncProxy = undefined; -} - -////////////////////// -// // -// Key handling // -// // -////////////////////// - - -/** - * Generates a new OpenPGP key pair. Supports RSA and ECC keys. Primary and subkey will be of same type. - * @param {Array} userIds array of user IDs e.g. [{ name:'Phil Zimmermann', email:'phil@openpgp.org' }] - * @param {String} passphrase (optional) The passphrase used to encrypt the resulting private key - * @param {Number} numBits (optional) number of bits for RSA keys: 2048 or 4096. - * @param {Number} keyExpirationTime (optional) The number of seconds after the key creation time that the key expires - * @param {String} curve (optional) elliptic curve for ECC keys: - * curve25519, p256, p384, p521, secp256k1, - * brainpoolP256r1, brainpoolP384r1, or brainpoolP512r1. - * @param {Date} date (optional) override the creation date of the key and the key signatures - * @param {Array} subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}] - * sign parameter defaults to false, and indicates whether the subkey should sign rather than encrypt - * @returns {Promise} The generated key object in the form: - * { key:Key, privateKeyArmored:String, publicKeyArmored:String, revocationCertificate:String } - * @async - * @static - */ - -function generateKey({ userIds = [], passphrase = "", numBits = 2048, keyExpirationTime = 0, curve = "", date = new Date(), subkeys = [{}] }) { - userIds = toArray(userIds); - const options = { userIds, passphrase, numBits, keyExpirationTime, curve, date, subkeys }; - if (_util2.default.getWebCryptoAll() && numBits < 2048) { - throw new Error('numBits should be 2048 or 4096, found: ' + numBits); - } - - if (!_util2.default.getWebCryptoAll() && asyncProxy) { - // use web worker if web crypto apis are not supported - return asyncProxy.delegate('generateKey', options); - } - - return (0, _key.generate)(options).then(async key => { - const revocationCertificate = await key.getRevocationCertificate(); - key.revocationSignatures = []; - - return convertStreams({ - - key: key, - privateKeyArmored: key.armor(), - publicKeyArmored: key.toPublic().armor(), - revocationCertificate: revocationCertificate - - }); - }).catch(onError.bind(null, 'Error generating keypair')); -} - -/** - * Reformats signature packets for a key and rewraps key object. - * @param {Key} privateKey private key to reformat - * @param {Array} userIds array of user IDs e.g. [{ name:'Phil Zimmermann', email:'phil@openpgp.org' }] - * @param {String} passphrase (optional) The passphrase used to encrypt the resulting private key - * @param {Number} keyExpirationTime (optional) The number of seconds after the key creation time that the key expires - * @param {Boolean} revocationCertificate (optional) Whether the returned object should include a revocation certificate to revoke the public key - * @returns {Promise} The generated key object in the form: - * { key:Key, privateKeyArmored:String, publicKeyArmored:String, revocationCertificate:String } - * @async - * @static - */ -function reformatKey({ privateKey, userIds = [], passphrase = "", keyExpirationTime = 0, date, revocationCertificate = true }) { - userIds = toArray(userIds); - const options = { privateKey, userIds, passphrase, keyExpirationTime, date, revocationCertificate }; - if (asyncProxy) { - return asyncProxy.delegate('reformatKey', options); - } - - options.revoked = options.revocationCertificate; - - return (0, _key.reformat)(options).then(async key => { - const revocationCertificate = await key.getRevocationCertificate(); - key.revocationSignatures = []; - - return convertStreams({ - - key: key, - privateKeyArmored: key.armor(), - publicKeyArmored: key.toPublic().armor(), - revocationCertificate: revocationCertificate - - }); - }).catch(onError.bind(null, 'Error reformatting keypair')); -} - -/** - * Revokes a key. Requires either a private key or a revocation certificate. - * If a revocation certificate is passed, the reasonForRevocation parameters will be ignored. - * @param {Key} key (optional) public or private key to revoke - * @param {String} revocationCertificate (optional) revocation certificate to revoke the key with - * @param {Object} reasonForRevocation (optional) object indicating the reason for revocation - * @param {module:enums.reasonForRevocation} reasonForRevocation.flag (optional) flag indicating the reason for revocation - * @param {String} reasonForRevocation.string (optional) string explaining the reason for revocation - * @returns {Promise} The revoked key object in the form: - * { privateKey:Key, privateKeyArmored:String, publicKey:Key, publicKeyArmored:String } - * (if private key is passed) or { publicKey:Key, publicKeyArmored:String } (otherwise) - * @static - */ -function revokeKey({ - key, revocationCertificate, reasonForRevocation -} = {}) { - const options = { - key, revocationCertificate, reasonForRevocation - }; - - if (!_util2.default.getWebCryptoAll() && asyncProxy) { - // use web worker if web crypto apis are not supported - return asyncProxy.delegate('revokeKey', options); - } - - return Promise.resolve().then(() => { - if (revocationCertificate) { - return key.applyRevocationCertificate(revocationCertificate); - } else { - return key.revoke(reasonForRevocation); - } - }).then(async key => { - await convertStreams(key); - if (key.isPrivate()) { - const publicKey = key.toPublic(); - return { - privateKey: key, - privateKeyArmored: key.armor(), - publicKey: publicKey, - publicKeyArmored: publicKey.armor() - }; - } - return { - publicKey: key, - publicKeyArmored: key.armor() - }; - }).catch(onError.bind(null, 'Error revoking key')); -} - -/** - * Unlock a private key with your passphrase. - * @param {Key} privateKey the private key that is to be decrypted - * @param {String|Array} passphrase the user's passphrase(s) chosen during key generation - * @returns {Promise} the unlocked key object in the form: { key:Key } - * @async - */ -function decryptKey({ privateKey, passphrase }) { - if (asyncProxy) { - // use web worker if available - return asyncProxy.delegate('decryptKey', { privateKey, passphrase }); - } - - return Promise.resolve().then(async function () { - await privateKey.decrypt(passphrase); - - return { - key: privateKey - }; - }).catch(onError.bind(null, 'Error decrypting private key')); -} - -/** - * Lock a private key with your passphrase. - * @param {Key} privateKey the private key that is to be decrypted - * @param {String|Array} passphrase the user's passphrase(s) chosen during key generation - * @returns {Promise} the locked key object in the form: { key:Key } - * @async - */ -function encryptKey({ privateKey, passphrase }) { - if (asyncProxy) { - // use web worker if available - return asyncProxy.delegate('encryptKey', { privateKey, passphrase }); - } - - return Promise.resolve().then(async function () { - await privateKey.encrypt(passphrase); - - return { - key: privateKey - }; - }).catch(onError.bind(null, 'Error decrypting private key')); -} - -/////////////////////////////////////////// -// // -// Message encryption and decryption // -// // -/////////////////////////////////////////// - - -/** - * Encrypts message text/data with public keys, passwords or both at once. At least either public keys or passwords - * must be specified. If private keys are specified, those will be used to sign the message. - * @param {Message} message message to be encrypted as created by openpgp.message.fromText or openpgp.message.fromBinary - * @param {Key|Array} publicKeys (optional) array of keys or single key, used to encrypt the message - * @param {Key|Array} privateKeys (optional) private keys for signing. If omitted message will not be signed - * @param {String|Array} passwords (optional) array of passwords or a single password to encrypt the message - * @param {Object} sessionKey (optional) session key in the form: { data:Uint8Array, algorithm:String } - * @param {module:enums.compression} compression (optional) which compression algorithm to compress the message with, defaults to what is specified in config - * @param {Boolean} armor (optional) if the return values should be ascii armored or the message/signature objects - * @param {'web'|'node'|false} streaming (optional) whether to return data as a stream. Defaults to the type of stream `message` was created from, if any. - * @param {Boolean} detached (optional) if the signature should be detached (if true, signature will be added to returned object) - * @param {Signature} signature (optional) a detached signature to add to the encrypted message - * @param {Boolean} returnSessionKey (optional) if the unencrypted session key should be added to returned object - * @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs - * @param {Date} date (optional) override the creation date of the message signature - * @param {Array} fromUserIds (optional) array of user IDs to sign with, one per key in `privateKeys`, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] - * @param {Array} toUserIds (optional) array of user IDs to encrypt for, one per key in `publicKeys`, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }] - * @returns {Promise} Object containing encrypted (and optionally signed) message in the form: - * - * { - * data: String|ReadableStream|NodeStream, (if `armor` was true, the default) - * message: Message, (if `armor` was false) - * signature: String|ReadableStream|NodeStream, (if `detached` was true and `armor` was true) - * signature: Signature (if `detached` was true and `armor` was false) - * sessionKey: { data, algorithm, aeadAlgorithm } (if `returnSessionKey` was true) - * } - * @async - * @static - */ -function encrypt({ message, publicKeys, privateKeys, passwords, sessionKey, compression = _config2.default.compression, armor = true, streaming = message && message.fromStream, detached = false, signature = null, returnSessionKey = false, wildcard = false, date = new Date(), fromUserIds = [], toUserIds = [] }) { - checkMessage(message);publicKeys = toArray(publicKeys);privateKeys = toArray(privateKeys);passwords = toArray(passwords);fromUserIds = toArray(fromUserIds);toUserIds = toArray(toUserIds); - - if (!nativeAEAD() && asyncProxy) { - // use web worker if web crypto apis are not supported - return asyncProxy.delegate('encrypt', { message, publicKeys, privateKeys, passwords, sessionKey, compression, armor, streaming, detached, signature, returnSessionKey, wildcard, date, fromUserIds, toUserIds }); - } - const result = {}; - return Promise.resolve().then(async function () { - if (!privateKeys) { - privateKeys = []; - } - if (privateKeys.length || signature) { - // sign the message only if private keys or signature is specified - if (detached) { - const detachedSignature = await message.signDetached(privateKeys, signature, date, fromUserIds); - result.signature = armor ? detachedSignature.armor() : detachedSignature; - } else { - message = await message.sign(privateKeys, signature, date, fromUserIds); - } - } - message = message.compress(compression); - return message.encrypt(publicKeys, passwords, sessionKey, wildcard, date, toUserIds, streaming); - }).then(async encrypted => { - if (armor) { - result.data = encrypted.message.armor(); - } else { - result.message = encrypted.message; - } - if (returnSessionKey) { - result.sessionKey = encrypted.sessionKey; - } - return convertStreams(result, streaming, armor ? ['signature', 'data'] : []); - }).catch(onError.bind(null, 'Error encrypting message')); -} - -/** - * Decrypts a message with the user's private key, a session key or a password. Either a private key, - * a session key or a password must be specified. - * @param {Message} message the message object with the encrypted data - * @param {Key|Array} privateKeys (optional) private keys with decrypted secret key data or session key - * @param {String|Array} passwords (optional) passwords to decrypt the message - * @param {Object|Array} sessionKeys (optional) session keys in the form: { data:Uint8Array, algorithm:String } - * @param {Key|Array} publicKeys (optional) array of public keys or single key, to verify signatures - * @param {'utf8'|'binary'} format (optional) whether to return data as a string(Stream) or Uint8Array(Stream). If 'utf8' (the default), also normalize newlines. - * @param {'web'|'node'|false} streaming (optional) whether to return data as a stream. Defaults to the type of stream `message` was created from, if any. - * @param {Signature} signature (optional) detached signature for verification - * @param {Date} date (optional) use the given date for verification instead of the current time - * @returns {Promise} Object containing decrypted and verified message in the form: - * - * { - * data: String|ReadableStream|NodeStream, (if format was 'utf8', the default) - * data: Uint8Array|ReadableStream|NodeStream, (if format was 'binary') - * filename: String, - * signatures: [ - * { - * keyid: module:type/keyid, - * verified: Promise, - * valid: Boolean (if streaming was false) - * }, ... - * ] - * } - * @async - * @static - */ -function decrypt({ message, privateKeys, passwords, sessionKeys, publicKeys, format = 'utf8', streaming = message && message.fromStream, signature = null, date = new Date() }) { - checkMessage(message);publicKeys = toArray(publicKeys);privateKeys = toArray(privateKeys);passwords = toArray(passwords);sessionKeys = toArray(sessionKeys); - - if (!nativeAEAD() && asyncProxy) { - // use web worker if web crypto apis are not supported - return asyncProxy.delegate('decrypt', { message, privateKeys, passwords, sessionKeys, publicKeys, format, streaming, signature, date }); - } - - return message.decrypt(privateKeys, passwords, sessionKeys, streaming).then(async function (decrypted) { - if (!publicKeys) { - publicKeys = []; - } - - const result = {}; - result.signatures = signature ? await decrypted.verifyDetached(signature, publicKeys, date, streaming) : await decrypted.verify(publicKeys, date, streaming); - result.data = format === 'binary' ? decrypted.getLiteralData() : decrypted.getText(); - result.filename = decrypted.getFilename(); - if (streaming) linkStreams(result, message); - result.data = await convertStream(result.data, streaming); - if (!streaming) await prepareSignatures(result.signatures); - return result; - }).catch(onError.bind(null, 'Error decrypting message')); -} - -////////////////////////////////////////// -// // -// Message signing and verification // -// // -////////////////////////////////////////// - - -/** - * Signs a cleartext message. - * @param {CleartextMessage|Message} message (cleartext) message to be signed - * @param {Key|Array} privateKeys array of keys or single key with decrypted secret key data to sign cleartext - * @param {Boolean} armor (optional) if the return value should be ascii armored or the message object - * @param {'web'|'node'|false} streaming (optional) whether to return data as a stream. Defaults to the type of stream `message` was created from, if any. - * @param {Boolean} detached (optional) if the return value should contain a detached signature - * @param {Date} date (optional) override the creation date of the signature - * @param {Array} fromUserIds (optional) array of user IDs to sign with, one per key in `privateKeys`, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] - * @returns {Promise} Object containing signed message in the form: - * - * { - * data: String|ReadableStream|NodeStream, (if `armor` was true, the default) - * message: Message (if `armor` was false) - * } - * - * Or, if `detached` was true: - * - * { - * signature: String|ReadableStream|NodeStream, (if `armor` was true, the default) - * signature: Signature (if `armor` was false) - * } - * @async - * @static - */ -function sign({ message, privateKeys, armor = true, streaming = message && message.fromStream, detached = false, date = new Date(), fromUserIds = [] }) { - checkCleartextOrMessage(message); - privateKeys = toArray(privateKeys);fromUserIds = toArray(fromUserIds); - - if (asyncProxy) { - // use web worker if available - return asyncProxy.delegate('sign', { - message, privateKeys, armor, streaming, detached, date, fromUserIds - }); - } - - const result = {}; - return Promise.resolve().then(async function () { - if (detached) { - const signature = await message.signDetached(privateKeys, undefined, date, fromUserIds); - result.signature = armor ? signature.armor() : signature; - if (message.packets) { - result.signature = _webStreamTools2.default.transformPair(message.packets.write(), async (readable, writable) => { - await Promise.all([_webStreamTools2.default.pipe(result.signature, writable), _webStreamTools2.default.readToEnd(readable).catch(() => {})]); - }); - } - } else { - message = await message.sign(privateKeys, undefined, date, fromUserIds); - if (armor) { - result.data = message.armor(); - } else { - result.message = message; - } - } - return convertStreams(result, streaming, armor ? ['signature', 'data'] : []); - }).catch(onError.bind(null, 'Error signing cleartext message')); -} - -/** - * Verifies signatures of cleartext signed message - * @param {Key|Array} publicKeys array of publicKeys or single key, to verify signatures - * @param {CleartextMessage|Message} message (cleartext) message object with signatures - * @param {'web'|'node'|false} streaming (optional) whether to return data as a stream. Defaults to the type of stream `message` was created from, if any. - * @param {Signature} signature (optional) detached signature for verification - * @param {Date} date (optional) use the given date for verification instead of the current time - * @returns {Promise} Object containing verified message in the form: - * - * { - * data: String|ReadableStream|NodeStream, (if `message` was a CleartextMessage) - * data: Uint8Array|ReadableStream|NodeStream, (if `message` was a Message) - * signatures: [ - * { - * keyid: module:type/keyid, - * verified: Promise, - * valid: Boolean (if `streaming` was false) - * }, ... - * ] - * } - * @async - * @static - */ -function verify({ message, publicKeys, streaming = message && message.fromStream, signature = null, date = new Date() }) { - checkCleartextOrMessage(message); - publicKeys = toArray(publicKeys); - - if (asyncProxy) { - // use web worker if available - return asyncProxy.delegate('verify', { message, publicKeys, streaming, signature, date }); - } - - return Promise.resolve().then(async function () { - const result = {}; - result.signatures = signature ? await message.verifyDetached(signature, publicKeys, date, streaming) : await message.verify(publicKeys, date, streaming); - result.data = message instanceof _cleartext.CleartextMessage ? message.getText() : message.getLiteralData(); - if (streaming) linkStreams(result, message); - result.data = await convertStream(result.data, streaming); - if (!streaming) await prepareSignatures(result.signatures); - return result; - }).catch(onError.bind(null, 'Error verifying cleartext signed message')); -} - -/////////////////////////////////////////////// -// // -// Session key encryption and decryption // -// // -/////////////////////////////////////////////// - - -/** - * Encrypt a symmetric session key with public keys, passwords, or both at once. At least either public keys - * or passwords must be specified. - * @param {Uint8Array} data the session key to be encrypted e.g. 16 random bytes (for aes128) - * @param {String} algorithm algorithm of the symmetric session key e.g. 'aes128' or 'aes256' - * @param {String} aeadAlgorithm (optional) aead algorithm, e.g. 'eax' or 'ocb' - * @param {Key|Array} publicKeys (optional) array of public keys or single key, used to encrypt the key - * @param {String|Array} passwords (optional) passwords for the message - * @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs - * @param {Date} date (optional) override the date - * @param {Array} toUserIds (optional) array of user IDs to encrypt for, one per key in `publicKeys`, e.g. [{ name:'Phil Zimmermann', email:'phil@openpgp.org' }] - * @returns {Promise} the encrypted session key packets contained in a message object - * @async - * @static - */ -function encryptSessionKey({ data, algorithm, aeadAlgorithm, publicKeys, passwords, wildcard = false, date = new Date(), toUserIds = [] }) { - checkBinary(data);checkString(algorithm, 'algorithm');publicKeys = toArray(publicKeys);passwords = toArray(passwords);toUserIds = toArray(toUserIds); - - if (asyncProxy) { - // use web worker if available - return asyncProxy.delegate('encryptSessionKey', { data, algorithm, aeadAlgorithm, publicKeys, passwords, wildcard, date, toUserIds }); - } - - return Promise.resolve().then(async function () { - - return { message: await messageLib.encryptSessionKey(data, algorithm, aeadAlgorithm, publicKeys, passwords, wildcard, date, toUserIds) }; - }).catch(onError.bind(null, 'Error encrypting session key')); -} - -/** - * Decrypt symmetric session keys with a private key or password. Either a private key or - * a password must be specified. - * @param {Message} message a message object containing the encrypted session key packets - * @param {Key|Array} privateKeys (optional) private keys with decrypted secret key data - * @param {String|Array} passwords (optional) passwords to decrypt the session key - * @returns {Promise} Array of decrypted session key, algorithm pairs in form: - * { data:Uint8Array, algorithm:String } - * or 'undefined' if no key packets found - * @async - * @static - */ -function decryptSessionKeys({ message, privateKeys, passwords }) { - checkMessage(message);privateKeys = toArray(privateKeys);passwords = toArray(passwords); - - if (asyncProxy) { - // use web worker if available - return asyncProxy.delegate('decryptSessionKeys', { message, privateKeys, passwords }); - } - - return Promise.resolve().then(async function () { - - return message.decryptSessionKeys(privateKeys, passwords); - }).catch(onError.bind(null, 'Error decrypting session keys')); -} - -////////////////////////// -// // -// Helper functions // -// // -////////////////////////// - - -/** - * Input validation - */ -function checkString(data, name) { - if (!_util2.default.isString(data)) { - throw new Error('Parameter [' + (name || 'data') + '] must be of type String'); - } -} -function checkBinary(data, name) { - if (!_util2.default.isUint8Array(data)) { - throw new Error('Parameter [' + (name || 'data') + '] must be of type Uint8Array'); - } -} -function checkMessage(message) { - if (!(message instanceof messageLib.Message)) { - throw new Error('Parameter [message] needs to be of type Message'); - } -} -function checkCleartextOrMessage(message) { - if (!(message instanceof _cleartext.CleartextMessage) && !(message instanceof messageLib.Message)) { - throw new Error('Parameter [message] needs to be of type Message or CleartextMessage'); - } -} - -/** - * Normalize parameter to an array if it is not undefined. - * @param {Object} param the parameter to be normalized - * @returns {Array|undefined} the resulting array or undefined - */ -function toArray(param) { - if (param && !_util2.default.isArray(param)) { - param = [param]; - } - return param; -} - -/** - * Convert data to or from Stream - * @param {Object} data the data to convert - * @param {'web'|'node'|false} streaming (optional) whether to return a ReadableStream - * @returns {Object} the data in the respective format - */ -async function convertStream(data, streaming) { - if (!streaming && _util2.default.isStream(data)) { - return _webStreamTools2.default.readToEnd(data); - } - if (streaming && !_util2.default.isStream(data)) { - data = new ReadableStream({ - start(controller) { - controller.enqueue(data); - controller.close(); - } - }); - } - if (streaming === 'node') { - data = _webStreamTools2.default.webToNode(data); - } - return data; -} - -/** - * Convert object properties from Stream - * @param {Object} obj the data to convert - * @param {'web'|'node'|false} streaming (optional) whether to return ReadableStreams - * @param {Array} keys (optional) which keys to return as streams, if possible - * @returns {Object} the data in the respective format - */ -async function convertStreams(obj, streaming, keys = []) { - if (Object.prototype.isPrototypeOf(obj) && !Uint8Array.prototype.isPrototypeOf(obj)) { - await Promise.all(Object.entries(obj).map(async ([key, value]) => { - // recursively search all children - if (_util2.default.isStream(value) || keys.includes(key)) { - obj[key] = await convertStream(value, streaming); - } else { - await convertStreams(obj[key], streaming); - } - })); - } - return obj; -} - -/** - * Link result.data to the message stream for cancellation. - * @param {Object} result the data to convert - * @param {Message} message message object - * @returns {Object} - */ -function linkStreams(result, message) { - result.data = _webStreamTools2.default.transformPair(message.packets.stream, async (readable, writable) => { - await _webStreamTools2.default.pipe(result.data, writable); - }); -} - -/** - * Wait until signature objects have been verified - * @param {Object} signatures list of signatures - */ -async function prepareSignatures(signatures) { - await Promise.all(signatures.map(async signature => { - signature.signature = await signature.signature; - try { - signature.valid = await signature.verified; - } catch (e) { - signature.valid = null; - signature.error = e; - _util2.default.print_debug_error(e); - } - })); -} - -/** - * Global error handler that logs the stack trace and rethrows a high lvl error message. - * @param {String} message A human readable high level error Message - * @param {Error} error The internal error that caused the failure - */ -function onError(message, error) { - // log the stack trace - _util2.default.print_debug_error(error); - - // update error message - try { - error.message = message + ': ' + error.message; - } catch (e) {} - - throw error; -} - -/** - * Check for native AEAD support and configuration by the user. Only - * browsers that implement the current WebCrypto specification support - * native GCM. Native EAX is built on CTR and CBC, which current - * browsers support. OCB and CFB are not natively supported. - * @returns {Boolean} If authenticated encryption should be used - */ -function nativeAEAD() { - return _config2.default.aead_protect && (_config2.default.aead_mode === _enums2.default.aead.eax || _config2.default.aead_mode === _enums2.default.aead.experimental_gcm) && _util2.default.getWebCrypto(); -} - -},{"./cleartext":77,"./config/config":78,"./enums":113,"./key":116,"./message":120,"./polyfills":144,"./util":152,"./worker/async_proxy":154,"web-stream-tools":75}],122:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.Trust = exports.Signature = exports.SecretSubkey = exports.Userid = exports.SecretKey = exports.OnePassSignature = exports.UserAttribute = exports.PublicSubkey = exports.Marker = exports.SymmetricallyEncrypted = exports.PublicKey = exports.Literal = exports.SymEncryptedSessionKey = exports.PublicKeyEncryptedSessionKey = exports.SymEncryptedAEADProtected = exports.SymEncryptedIntegrityProtected = exports.Compressed = undefined; - -var _compressed = require('./compressed.js'); - -Object.defineProperty(exports, 'Compressed', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_compressed).default; - } -}); - -var _sym_encrypted_integrity_protected = require('./sym_encrypted_integrity_protected.js'); - -Object.defineProperty(exports, 'SymEncryptedIntegrityProtected', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_sym_encrypted_integrity_protected).default; - } -}); - -var _sym_encrypted_aead_protected = require('./sym_encrypted_aead_protected.js'); - -Object.defineProperty(exports, 'SymEncryptedAEADProtected', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_sym_encrypted_aead_protected).default; - } -}); - -var _public_key_encrypted_session_key = require('./public_key_encrypted_session_key.js'); - -Object.defineProperty(exports, 'PublicKeyEncryptedSessionKey', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_public_key_encrypted_session_key).default; - } -}); - -var _sym_encrypted_session_key = require('./sym_encrypted_session_key.js'); - -Object.defineProperty(exports, 'SymEncryptedSessionKey', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_sym_encrypted_session_key).default; - } -}); - -var _literal = require('./literal.js'); - -Object.defineProperty(exports, 'Literal', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_literal).default; - } -}); - -var _public_key = require('./public_key.js'); - -Object.defineProperty(exports, 'PublicKey', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_public_key).default; - } -}); - -var _symmetrically_encrypted = require('./symmetrically_encrypted.js'); - -Object.defineProperty(exports, 'SymmetricallyEncrypted', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_symmetrically_encrypted).default; - } -}); - -var _marker = require('./marker.js'); - -Object.defineProperty(exports, 'Marker', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_marker).default; - } -}); - -var _public_subkey = require('./public_subkey.js'); - -Object.defineProperty(exports, 'PublicSubkey', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_public_subkey).default; - } -}); - -var _user_attribute = require('./user_attribute.js'); - -Object.defineProperty(exports, 'UserAttribute', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_user_attribute).default; - } -}); - -var _one_pass_signature = require('./one_pass_signature.js'); - -Object.defineProperty(exports, 'OnePassSignature', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_one_pass_signature).default; - } -}); - -var _secret_key = require('./secret_key.js'); - -Object.defineProperty(exports, 'SecretKey', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_secret_key).default; - } -}); - -var _userid = require('./userid.js'); - -Object.defineProperty(exports, 'Userid', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_userid).default; - } -}); - -var _secret_subkey = require('./secret_subkey.js'); - -Object.defineProperty(exports, 'SecretSubkey', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_secret_subkey).default; - } -}); - -var _signature = require('./signature.js'); - -Object.defineProperty(exports, 'Signature', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_signature).default; - } -}); - -var _trust = require('./trust.js'); - -Object.defineProperty(exports, 'Trust', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_trust).default; - } -}); -exports.newPacketFromTag = newPacketFromTag; -exports.fromStructuredClone = fromStructuredClone; - -var _enums = require('../enums.js'); - -var _enums2 = _interopRequireDefault(_enums); - -var _all_packets = require('./all_packets.js'); - -var packets = _interopRequireWildcard(_all_packets); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Allocate a new packet - * @function newPacketFromTag - * @memberof module:packet - * @param {String} tag property name from {@link module:enums.packet} - * @returns {Object} new packet object with type based on tag - */ -function newPacketFromTag(tag) { - return new packets[packetClassFromTagName(tag)](); -} - -/** - * Allocate a new packet from structured packet clone - * @see {@link https://w3c.github.io/html/infrastructure.html#safe-passing-of-structured-data} - * @function fromStructuredClone - * @memberof module:packet - * @param {Object} packetClone packet clone - * @returns {Object} new packet object with data from packet clone - */ -function fromStructuredClone(packetClone) { - const tagName = _enums2.default.read(_enums2.default.packet, packetClone.tag); - const packet = newPacketFromTag(tagName); - Object.assign(packet, packetClone); - if (packet.postCloneTypeFix) { - packet.postCloneTypeFix(); - } - return packet; -} - -/** - * Convert tag name to class name - * @param {String} tag property name from {@link module:enums.packet} - * @returns {String} - * @private - */ -function packetClassFromTagName(tag) { - return tag.substr(0, 1).toUpperCase() + tag.substr(1); -} - -},{"../enums.js":113,"./all_packets.js":122,"./compressed.js":124,"./literal.js":126,"./marker.js":127,"./one_pass_signature.js":128,"./public_key.js":131,"./public_key_encrypted_session_key.js":132,"./public_subkey.js":133,"./secret_key.js":134,"./secret_subkey.js":135,"./signature.js":136,"./sym_encrypted_aead_protected.js":137,"./sym_encrypted_integrity_protected.js":138,"./sym_encrypted_session_key.js":139,"./symmetrically_encrypted.js":140,"./trust.js":141,"./user_attribute.js":142,"./userid.js":143}],123:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.clonePackets = clonePackets; -exports.parseClonedPackets = parseClonedPackets; - -var _webStreamTools = require('web-stream-tools'); - -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); - -var _key = require('../key'); - -var _message = require('../message'); - -var _cleartext = require('../cleartext'); - -var _signature = require('../signature'); - -var _packetlist = require('./packetlist'); - -var _packetlist2 = _interopRequireDefault(_packetlist); - -var _keyid = require('../type/keyid'); - -var _keyid2 = _interopRequireDefault(_keyid); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -////////////////////////////// -// // -// List --> Clone // -// // -////////////////////////////// - - -/** - * Create a packetlist from the correspoding object types. - * @param {Object} options the object passed to and from the web worker - * @returns {Object} a mutated version of the options optject - */ -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2015 Tankred Hase -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @fileoverview This module implements packet list cloning required to - * pass certain object types between the web worker and main thread using - * the structured cloning algorithm. - * @module packet/clone - */ - -function clonePackets(options) { - if (options.publicKeys) { - options.publicKeys = options.publicKeys.map(key => key.toPacketlist()); - } - if (options.privateKeys) { - options.privateKeys = options.privateKeys.map(key => key.toPacketlist()); - } - if (options.privateKey) { - options.privateKey = options.privateKey.toPacketlist(); - } - if (options.key) { - options.key = options.key.toPacketlist(); - } - if (options.message) { - //could be either a Message or CleartextMessage object - if (options.message instanceof _message.Message) { - options.message = options.message.packets; - } else if (options.message instanceof _cleartext.CleartextMessage) { - options.message = { text: options.message.text, signature: options.message.signature.packets }; - } - } - if (options.signature && options.signature instanceof _signature.Signature) { - options.signature = options.signature.packets; - } - if (options.signatures) { - options.signatures.forEach(verificationObjectToClone); - } - return options; -} - -function verificationObjectToClone(verObject) { - const verified = verObject.verified; - verObject.verified = _webStreamTools2.default.fromAsync(() => verified); - if (verObject.signature instanceof Promise) { - const signature = verObject.signature; - verObject.signature = _webStreamTools2.default.fromAsync(async () => { - const packets = (await signature).packets; - try { - await verified; - delete packets[0].signature; - } catch (e) {} - return packets; - }); - } else { - verObject.signature = verObject.signature.packets; - } - if (verObject.error) { - verObject.error = verObject.error.message; - } - return verObject; -} - -////////////////////////////// -// // -// Clone --> List // -// // -////////////////////////////// - - -/** - * Creates an object with the correct prototype from a corresponding packetlist. - * @param {Object} options the object passed to and from the web worker - * @param {String} method the public api function name to be delegated to the worker - * @returns {Object} a mutated version of the options optject - */ -function parseClonedPackets(options) { - if (options.publicKeys) { - options.publicKeys = options.publicKeys.map(packetlistCloneToKey); - } - if (options.privateKeys) { - options.privateKeys = options.privateKeys.map(packetlistCloneToKey); - } - if (options.privateKey) { - options.privateKey = packetlistCloneToKey(options.privateKey); - } - if (options.key) { - options.key = packetlistCloneToKey(options.key); - } - if (options.message && options.message.signature) { - options.message = packetlistCloneToCleartextMessage(options.message); - } else if (options.message) { - options.message = packetlistCloneToMessage(options.message); - } - if (options.signatures) { - options.signatures = options.signatures.map(packetlistCloneToSignatures); - } - if (options.signature) { - options.signature = packetlistCloneToSignature(options.signature); - } - return options; -} - -function packetlistCloneToKey(clone) { - const packetlist = _packetlist2.default.fromStructuredClone(clone); - return new _key.Key(packetlist); -} - -function packetlistCloneToMessage(clone) { - const packetlist = _packetlist2.default.fromStructuredClone(clone); - return new _message.Message(packetlist); -} - -function packetlistCloneToCleartextMessage(clone) { - const packetlist = _packetlist2.default.fromStructuredClone(clone.signature); - return new _cleartext.CleartextMessage(clone.text, new _signature.Signature(packetlist)); -} - -//verification objects -function packetlistCloneToSignatures(clone) { - clone.keyid = _keyid2.default.fromClone(clone.keyid); - if (_util2.default.isStream(clone.signature)) { - clone.signature = _webStreamTools2.default.readToEnd(clone.signature, ([signature]) => new _signature.Signature(_packetlist2.default.fromStructuredClone(signature))); - clone.signature.catch(() => {}); - } else { - clone.signature = new _signature.Signature(_packetlist2.default.fromStructuredClone(clone.signature)); - } - clone.verified = _webStreamTools2.default.readToEnd(clone.verified, ([verified]) => verified); - clone.verified.catch(() => {}); - if (clone.error) { - clone.error = new Error(clone.error); - } - return clone; -} - -function packetlistCloneToSignature(clone) { - if (_util2.default.isString(clone) || _util2.default.isStream(clone)) { - //signature is armored - return clone; - } - const packetlist = _packetlist2.default.fromStructuredClone(clone); - return new _signature.Signature(packetlist); -} - -},{"../cleartext":77,"../key":116,"../message":120,"../signature":145,"../type/keyid":148,"../util":152,"./packetlist":130,"web-stream-tools":75}],124:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _pako = require('pako'); - -var _pako2 = _interopRequireDefault(_pako); - -var _seekBzip = require('seek-bzip'); - -var _seekBzip2 = _interopRequireDefault(_seekBzip); - -var _webStreamTools = require('web-stream-tools'); - -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); - -var _config = require('../config'); - -var _config2 = _interopRequireDefault(_config); - -var _enums = require('../enums'); - -var _enums2 = _interopRequireDefault(_enums); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Implementation of the Compressed Data Packet (Tag 8) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.6|RFC4880 5.6}: - * The Compressed Data packet contains compressed data. Typically, - * this packet is found as the contents of an encrypted packet, or following - * a Signature or One-Pass Signature packet, and contains a literal data packet. - * @memberof module:packet - * @constructor - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @requires web-stream-tools - * @requires pako - * @requires config - * @requires enums - * @requires util - * @requires compression/bzip2 - */ - -function Compressed() { - /** - * Packet type - * @type {module:enums.packet} - */ - this.tag = _enums2.default.packet.compressed; - /** - * List of packets - * @type {module:packet.List} - */ - this.packets = null; - /** - * Compression algorithm - * @type {compression} - */ - this.algorithm = 'zip'; - - /** - * Compressed packet data - * @type {Uint8Array | ReadableStream} - */ - this.compressed = null; -} - -/** - * Parsing function for the packet. - * @param {Uint8Array | ReadableStream} bytes Payload of a tag 8 packet - */ -Compressed.prototype.read = async function (bytes, streaming) { - await _webStreamTools2.default.parse(bytes, async reader => { - - // One octet that gives the algorithm used to compress the packet. - this.algorithm = _enums2.default.read(_enums2.default.compression, (await reader.readByte())); - - // Compressed data, which makes up the remainder of the packet. - this.compressed = reader.remainder(); - - await this.decompress(streaming); - }); -}; - -/** - * Return the compressed packet. - * @returns {Uint8Array | ReadableStream} binary compressed packet - */ -Compressed.prototype.write = function () { - if (this.compressed === null) { - this.compress(); - } - - return _util2.default.concat([new Uint8Array([_enums2.default.write(_enums2.default.compression, this.algorithm)]), this.compressed]); -}; - -/** - * Decompression method for decompressing the compressed data - * read by read_packet - */ -Compressed.prototype.decompress = async function (streaming) { - - if (!decompress_fns[this.algorithm]) { - throw new Error(this.algorithm + ' decompression not supported'); - } - - await this.packets.read(decompress_fns[this.algorithm](this.compressed), streaming); -}; - -/** - * Compress the packet data (member decompressedData) - */ -Compressed.prototype.compress = function () { - - if (!compress_fns[this.algorithm]) { - throw new Error(this.algorithm + ' compression not supported'); - } - - this.compressed = compress_fns[this.algorithm](this.packets.write()); -}; - -exports.default = Compressed; - -////////////////////////// -// // -// Helper functions // -// // -////////////////////////// - - -const nodeZlib = _util2.default.getNodeZlib(); - -function node_zlib(func, options = {}) { - return function (data) { - return _webStreamTools2.default.nodeToWeb(_webStreamTools2.default.webToNode(data).pipe(func(options))); - }; -} - -function pako_zlib(constructor, options = {}) { - return function (data) { - const obj = new constructor(options); - return _webStreamTools2.default.transform(data, value => { - if (value.length) { - obj.push(value, _pako2.default.Z_SYNC_FLUSH); - return obj.result; - } - }, () => { - if (constructor === _pako2.default.Deflate) { - obj.push([], _pako2.default.Z_FINISH); - return obj.result; - } - }); - }; -} - -function bzip2(func) { - return function (data) { - return _webStreamTools2.default.fromAsync(async () => func((await _webStreamTools2.default.readToEnd(data)))); - }; -} - -let compress_fns; -let decompress_fns; -if (nodeZlib) { - // Use Node native zlib for DEFLATE compression/decompression - compress_fns = { - zip: node_zlib(nodeZlib.createDeflateRaw, { level: _config2.default.deflate_level }), - zlib: node_zlib(nodeZlib.createDeflate, { level: _config2.default.deflate_level }) - }; - - decompress_fns = { - zip: node_zlib(nodeZlib.createInflateRaw), - zlib: node_zlib(nodeZlib.createInflate), - bzip2: bzip2(_seekBzip2.default.decode) - }; -} else { - // Use JS fallbacks - compress_fns = { - zip: pako_zlib(_pako2.default.Deflate, { raw: true, level: _config2.default.deflate_level }), - zlib: pako_zlib(_pako2.default.Deflate, { level: _config2.default.deflate_level }) - }; - - decompress_fns = { - zip: pako_zlib(_pako2.default.Inflate, { raw: true }), - zlib: pako_zlib(_pako2.default.Inflate), - bzip2: bzip2(_seekBzip2.default.decode) - }; -} - -},{"../config":79,"../enums":113,"../util":152,"pako":50,"seek-bzip":69,"web-stream-tools":75}],125:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _all_packets = require('./all_packets'); - -var packets = _interopRequireWildcard(_all_packets); - -var _clone = require('./clone'); - -var clone = _interopRequireWildcard(_clone); - -var _packetlist = require('./packetlist'); - -var _packetlist2 = _interopRequireDefault(_packetlist); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -const mod = { - List: _packetlist2.default, - clone -}; /** - * @fileoverview OpenPGP packet types - * @see module:packet/all_packets - * @see module:packet/clone - * @see module:packet.List - * @module packet - */ - -Object.assign(mod, packets); - -exports.default = mod; - -},{"./all_packets":122,"./clone":123,"./packetlist":130}],126:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _webStreamTools = require('web-stream-tools'); - -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); - -var _enums = require('../enums'); - -var _enums2 = _interopRequireDefault(_enums); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Implementation of the Literal Data Packet (Tag 11) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.9|RFC4880 5.9}: - * A Literal Data packet contains the body of a message; data that is not to be - * further interpreted. - * @param {Date} date the creation date of the literal package - * @memberof module:packet - * @constructor - */ -function Literal(date = new Date()) { - this.tag = _enums2.default.packet.literal; - this.format = 'utf8'; // default format for literal data packets - this.date = _util2.default.normalizeDate(date); - this.text = null; // textual data representation - this.data = null; // literal data representation - this.filename = 'msg.txt'; -} - -/** - * Set the packet data to a javascript native string, end of line - * will be normalized to \r\n and by default text is converted to UTF8 - * @param {String | ReadableStream} text Any native javascript string - * @param {utf8|binary|text|mime} format (optional) The format of the string of bytes - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @requires web-stream-tools - * @requires enums - * @requires util - */ - -Literal.prototype.setText = function (text, format = 'utf8') { - this.format = format; - this.text = text; - this.data = null; -}; - -/** - * Returns literal data packets as native JavaScript string - * with normalized end of line to \n - * @param {Boolean} clone (optional) Whether to return a clone so that getBytes/getText can be called again - * @returns {String | ReadableStream} literal data as text - */ -Literal.prototype.getText = function (clone = false) { - if (this.text === null || _util2.default.isStream(this.text)) { - // Assume that this.text has been read - this.text = _util2.default.nativeEOL(_util2.default.decode_utf8(this.getBytes(clone))); - } - return this.text; -}; - -/** - * Set the packet data to value represented by the provided string of bytes. - * @param {Uint8Array | ReadableStream} bytes The string of bytes - * @param {utf8|binary|text|mime} format The format of the string of bytes - */ -Literal.prototype.setBytes = function (bytes, format) { - this.format = format; - this.data = bytes; - this.text = null; -}; - -/** - * Get the byte sequence representing the literal packet data - * @param {Boolean} clone (optional) Whether to return a clone so that getBytes/getText can be called again - * @returns {Uint8Array | ReadableStream} A sequence of bytes - */ -Literal.prototype.getBytes = function (clone = false) { - if (this.data === null) { - // normalize EOL to \r\n and encode UTF8 - this.data = _util2.default.encode_utf8(_util2.default.canonicalizeEOL(this.text)); - } - if (clone) { - return _webStreamTools2.default.passiveClone(this.data); - } - return this.data; -}; - -/** - * Sets the filename of the literal packet data - * @param {String} filename Any native javascript string - */ -Literal.prototype.setFilename = function (filename) { - this.filename = filename; -}; - -/** - * Get the filename of the literal packet data - * @returns {String} filename - */ -Literal.prototype.getFilename = function () { - return this.filename; -}; - -/** - * Parsing function for a literal data packet (tag 11). - * - * @param {Uint8Array | ReadableStream} input Payload of a tag 11 packet - * @returns {module:packet.Literal} object representation - */ -Literal.prototype.read = async function (bytes) { - await _webStreamTools2.default.parse(bytes, async reader => { - // - A one-octet field that describes how the data is formatted. - const format = _enums2.default.read(_enums2.default.literal, (await reader.readByte())); - - const filename_len = await reader.readByte(); - this.filename = _util2.default.decode_utf8((await reader.readBytes(filename_len))); - - this.date = _util2.default.readDate((await reader.readBytes(4))); - - const data = reader.remainder(); - - this.setBytes(data, format); - }); -}; - -/** - * Creates a Uint8Array representation of the packet, excluding the data - * - * @returns {Uint8Array} Uint8Array representation of the packet - */ -Literal.prototype.writeHeader = function () { - const filename = _util2.default.encode_utf8(this.filename); - const filename_length = new Uint8Array([filename.length]); - - const format = new Uint8Array([_enums2.default.write(_enums2.default.literal, this.format)]); - const date = _util2.default.writeDate(this.date); - - return _util2.default.concatUint8Array([format, filename_length, filename, date]); -}; - -/** - * Creates a Uint8Array representation of the packet - * - * @returns {Uint8Array | ReadableStream} Uint8Array representation of the packet - */ -Literal.prototype.write = function () { - const header = this.writeHeader(); - const data = this.getBytes(); - - return _util2.default.concat([header, data]); -}; - -exports.default = Literal; - -},{"../enums":113,"../util":152,"web-stream-tools":75}],127:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _enums = require('../enums'); - -var _enums2 = _interopRequireDefault(_enums); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Implementation of the strange "Marker packet" (Tag 10) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.8|RFC4880 5.8}: - * An experimental version of PGP used this packet as the Literal - * packet, but no released version of PGP generated Literal packets with this - * tag. With PGP 5.x, this packet has been reassigned and is reserved for use as - * the Marker packet. - * - * Such a packet MUST be ignored when received. - * @memberof module:packet - * @constructor - */ -function Marker() { - this.tag = _enums2.default.packet.marker; -} - -/** - * Parsing function for a literal data packet (tag 10). - * - * @param {String} input Payload of a tag 10 packet - * @param {Integer} position - * Position to start reading from the input string - * @param {Integer} len - * Length of the packet or the remaining length of - * input at position - * @returns {module:packet.Marker} Object representation - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @requires enums - */ - -Marker.prototype.read = function (bytes) { - if (bytes[0] === 0x50 && // P - bytes[1] === 0x47 && // G - bytes[2] === 0x50) { - // P - return true; - } - // marker packet does not contain "PGP" - return false; -}; - -exports.default = Marker; - -},{"../enums":113}],128:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _webStreamTools = require('web-stream-tools'); - -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); - -var _signature = require('./signature'); - -var _signature2 = _interopRequireDefault(_signature); - -var _keyid = require('../type/keyid'); - -var _keyid2 = _interopRequireDefault(_keyid); - -var _enums = require('../enums'); - -var _enums2 = _interopRequireDefault(_enums); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Implementation of the One-Pass Signature Packets (Tag 4) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.4|RFC4880 5.4}: - * The One-Pass Signature packet precedes the signed data and contains - * enough information to allow the receiver to begin calculating any - * hashes needed to verify the signature. It allows the Signature - * packet to be placed at the end of the message, so that the signer - * can compute the entire signed message in one pass. - * @memberof module:packet - * @constructor - */ -function OnePassSignature() { - /** - * Packet type - * @type {module:enums.packet} - */ - this.tag = _enums2.default.packet.onePassSignature; - /** A one-octet version number. The current version is 3. */ - this.version = null; - /** - * A one-octet signature type. - * Signature types are described in - * {@link https://tools.ietf.org/html/rfc4880#section-5.2.1|RFC4880 Section 5.2.1}. - */ - this.signatureType = null; - /** - * A one-octet number describing the hash algorithm used. - * @see {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC4880 9.4} - */ - this.hashAlgorithm = null; - /** - * A one-octet number describing the public-key algorithm used. - * @see {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC4880 9.1} - */ - this.publicKeyAlgorithm = null; - /** An eight-octet number holding the Key ID of the signing key. */ - this.issuerKeyId = null; - /** - * A one-octet number holding a flag showing whether the signature is nested. - * A zero value indicates that the next packet is another One-Pass Signature packet - * that describes another signature to be applied to the same message data. - */ - this.flags = null; -} - -/** - * parsing function for a one-pass signature packet (tag 4). - * @param {Uint8Array} bytes payload of a tag 4 packet - * @returns {module:packet.OnePassSignature} object representation - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @requires web-stream-tools - * @requires packet/signature - * @requires type/keyid - * @requires enums - * @requires util - */ - -OnePassSignature.prototype.read = function (bytes) { - let mypos = 0; - // A one-octet version number. The current version is 3. - this.version = bytes[mypos++]; - - // A one-octet signature type. Signature types are described in - // Section 5.2.1. - this.signatureType = bytes[mypos++]; - - // A one-octet number describing the hash algorithm used. - this.hashAlgorithm = bytes[mypos++]; - - // A one-octet number describing the public-key algorithm used. - this.publicKeyAlgorithm = bytes[mypos++]; - - // An eight-octet number holding the Key ID of the signing key. - this.issuerKeyId = new _keyid2.default(); - this.issuerKeyId.read(bytes.subarray(mypos, mypos + 8)); - mypos += 8; - - // A one-octet number holding a flag showing whether the signature - // is nested. A zero value indicates that the next packet is - // another One-Pass Signature packet that describes another - // signature to be applied to the same message data. - this.flags = bytes[mypos++]; - return this; -}; - -/** - * creates a string representation of a one-pass signature packet - * @returns {Uint8Array} a Uint8Array representation of a one-pass signature packet - */ -OnePassSignature.prototype.write = function () { - const start = new Uint8Array([3, _enums2.default.write(_enums2.default.signature, this.signatureType), _enums2.default.write(_enums2.default.hash, this.hashAlgorithm), _enums2.default.write(_enums2.default.publicKey, this.publicKeyAlgorithm)]); - - const end = new Uint8Array([this.flags]); - - return _util2.default.concatUint8Array([start, this.issuerKeyId.write(), end]); -}; - -/** - * Fix custom types after cloning - */ -OnePassSignature.prototype.postCloneTypeFix = function () { - this.issuerKeyId = _keyid2.default.fromClone(this.issuerKeyId); -}; - -OnePassSignature.prototype.hash = _signature2.default.prototype.hash; -OnePassSignature.prototype.toHash = _signature2.default.prototype.toHash; -OnePassSignature.prototype.toSign = _signature2.default.prototype.toSign; -OnePassSignature.prototype.calculateTrailer = function (...args) { - return _webStreamTools2.default.fromAsync(async () => (await this.correspondingSig).calculateTrailer(...args)); -}; - -OnePassSignature.prototype.verify = async function () { - const correspondingSig = await this.correspondingSig; - if (!correspondingSig || correspondingSig.tag !== _enums2.default.packet.signature) { - throw new Error('Corresponding signature packet missing'); - } - if (correspondingSig.signatureType !== this.signatureType || correspondingSig.hashAlgorithm !== this.hashAlgorithm || correspondingSig.publicKeyAlgorithm !== this.publicKeyAlgorithm || !correspondingSig.issuerKeyId.equals(this.issuerKeyId)) { - throw new Error('Corresponding signature packet does not match one-pass signature packet'); - } - correspondingSig.hashed = this.hashed; - return correspondingSig.verify.apply(correspondingSig, arguments); -}; - -exports.default = OnePassSignature; - -},{"../enums":113,"../type/keyid":148,"../util":152,"./signature":136,"web-stream-tools":75}],129:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); // GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/* eslint-disable callback-return */ - -/** - * @fileoverview Functions for reading and writing packets - * @requires web-stream-tools - * @requires enums - * @requires util - * @module packet/packet - */ - -var _webStreamTools = require('web-stream-tools'); - -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); - -var _enums = require('../enums'); - -var _enums2 = _interopRequireDefault(_enums); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -exports.default = { - readSimpleLength: function readSimpleLength(bytes) { - let len = 0; - let offset; - const type = bytes[0]; - - if (type < 192) { - var _bytes = _slicedToArray(bytes, 1); - - len = _bytes[0]; - - offset = 1; - } else if (type < 255) { - len = (bytes[0] - 192 << 8) + bytes[1] + 192; - offset = 2; - } else if (type === 255) { - len = _util2.default.readNumber(bytes.subarray(1, 1 + 4)); - offset = 5; - } - - return { - len: len, - offset: offset - }; - }, - - /** - * Encodes a given integer of length to the openpgp length specifier to a - * string - * - * @param {Integer} length The length to encode - * @returns {Uint8Array} String with openpgp length representation - */ - writeSimpleLength: function writeSimpleLength(length) { - if (length < 192) { - return new Uint8Array([length]); - } else if (length > 191 && length < 8384) { - /* - * let a = (total data packet length) - 192 let bc = two octet - * representation of a let d = b + 192 - */ - return new Uint8Array([(length - 192 >> 8) + 192, length - 192 & 0xFF]); - } - return _util2.default.concatUint8Array([new Uint8Array([255]), _util2.default.writeNumber(length, 4)]); - }, - - writePartialLength: function writePartialLength(power) { - if (power < 0 || power > 30) { - throw new Error('Partial Length power must be between 1 and 30'); - } - return new Uint8Array([224 + power]); - }, - - writeTag: function writeTag(tag_type) { - /* we're only generating v4 packet headers here */ - return new Uint8Array([0xC0 | tag_type]); - }, - - /** - * Writes a packet header version 4 with the given tag_type and length to a - * string - * - * @param {Integer} tag_type Tag type - * @param {Integer} length Length of the payload - * @returns {String} String of the header - */ - writeHeader: function writeHeader(tag_type, length) { - /* we're only generating v4 packet headers here */ - return _util2.default.concatUint8Array([this.writeTag(tag_type), this.writeSimpleLength(length)]); - }, - - /** - * Whether the packet type supports partial lengths per RFC4880 - * @param {Integer} tag_type Tag type - * @returns {Boolean} String of the header - */ - supportsStreaming: function supportsStreaming(tag_type) { - return [_enums2.default.packet.literal, _enums2.default.packet.compressed, _enums2.default.packet.symmetricallyEncrypted, _enums2.default.packet.symEncryptedIntegrityProtected, _enums2.default.packet.symEncryptedAEADProtected].includes(tag_type); - }, - - /** - * Generic static Packet Parser function - * - * @param {Uint8Array | ReadableStream} input Input stream as string - * @param {Function} callback Function to call with the parsed packet - * @returns {Boolean} Returns false if the stream was empty and parsing is done, and true otherwise. - */ - read: async function read(input, streaming, callback) { - const reader = _webStreamTools2.default.getReader(input); - let writer; - let callbackReturned; - try { - const peekedBytes = await reader.peekBytes(2); - // some sanity checks - if (!peekedBytes || peekedBytes.length < 2 || (peekedBytes[0] & 0x80) === 0) { - throw new Error("Error during parsing. This message / key probably does not conform to a valid OpenPGP format."); - } - const headerByte = await reader.readByte(); - let tag = -1; - let format = -1; - let packet_length; - - format = 0; // 0 = old format; 1 = new format - if ((headerByte & 0x40) !== 0) { - format = 1; - } - - let packet_length_type; - if (format) { - // new format header - tag = headerByte & 0x3F; // bit 5-0 - } else { - // old format header - tag = (headerByte & 0x3F) >> 2; // bit 5-2 - packet_length_type = headerByte & 0x03; // bit 1-0 - } - - const supportsStreaming = this.supportsStreaming(tag); - let packet = null; - if (streaming && supportsStreaming) { - const transform = new TransformStream(); - writer = _webStreamTools2.default.getWriter(transform.writable); - packet = transform.readable; - callbackReturned = callback({ tag, packet }); - } else { - packet = []; - } - - let wasPartialLength; - do { - if (!format) { - // 4.2.1. Old Format Packet Lengths - switch (packet_length_type) { - case 0: - // The packet has a one-octet length. The header is 2 octets - // long. - packet_length = await reader.readByte(); - break; - case 1: - // The packet has a two-octet length. The header is 3 octets - // long. - packet_length = (await reader.readByte()) << 8 | (await reader.readByte()); - break; - case 2: - // The packet has a four-octet length. The header is 5 - // octets long. - packet_length = (await reader.readByte()) << 24 | (await reader.readByte()) << 16 | (await reader.readByte()) << 8 | (await reader.readByte()); - break; - default: - // 3 - The packet is of indeterminate length. The header is 1 - // octet long, and the implementation must determine how long - // the packet is. If the packet is in a file, this means that - // the packet extends until the end of the file. In general, - // an implementation SHOULD NOT use indeterminate-length - // packets except where the end of the data will be clear - // from the context, and even then it is better to use a - // definite length, or a new format header. The new format - // headers described below have a mechanism for precisely - // encoding data of indeterminate length. - packet_length = Infinity; - break; - } - } else { - // 4.2.2. New Format Packet Lengths - // 4.2.2.1. One-Octet Lengths - const lengthByte = await reader.readByte(); - wasPartialLength = false; - if (lengthByte < 192) { - packet_length = lengthByte; - // 4.2.2.2. Two-Octet Lengths - } else if (lengthByte >= 192 && lengthByte < 224) { - packet_length = (lengthByte - 192 << 8) + (await reader.readByte()) + 192; - // 4.2.2.4. Partial Body Lengths - } else if (lengthByte > 223 && lengthByte < 255) { - packet_length = 1 << (lengthByte & 0x1F); - wasPartialLength = true; - if (!supportsStreaming) { - throw new TypeError('This packet type does not support partial lengths.'); - } - // 4.2.2.3. Five-Octet Lengths - } else { - packet_length = (await reader.readByte()) << 24 | (await reader.readByte()) << 16 | (await reader.readByte()) << 8 | (await reader.readByte()); - } - } - if (packet_length > 0) { - let bytesRead = 0; - while (true) { - if (writer) await writer.ready; - - var _ref = await reader.read(); - - const done = _ref.done, - value = _ref.value; - - if (done) { - if (packet_length === Infinity) break; - throw new Error('Unexpected end of packet'); - } - const chunk = packet_length === Infinity ? value : value.subarray(0, packet_length - bytesRead); - if (writer) await writer.write(chunk);else packet.push(chunk); - bytesRead += value.length; - if (bytesRead >= packet_length) { - reader.unshift(value.subarray(packet_length - bytesRead + value.length)); - break; - } - } - } - } while (wasPartialLength); - - // If this was not a packet that "supports streaming", we peek to check - // whether it is the last packet in the message. We peek 2 bytes instead - // of 1 because the beginning of this function also peeks 2 bytes, and we - // want to cut a `subarray` of the correct length into `web-stream-tools`' - // `externalBuffer` as a tiny optimization here. - // - // If it *was* a streaming packet (i.e. the data packets), we peek at the - // entire remainder of the stream, in order to forward errors in the - // remainder of the stream to the packet data. (Note that this means we - // read/peek at all signature packets before closing the literal data - // packet, for example.) This forwards armor checksum errors to the - // encrypted data stream, for example, so that they don't get lost / - // forgotten on encryptedMessage.packets.stream, which we never look at. - // - // Note that subsequent packet parsing errors could still end up there if - // `config.tolerant` is set to false, or on malformed messages with - // multiple data packets, but usually it shouldn't happen. - // - // An example of what we do when stream-parsing a message containing - // [ one-pass signature packet, literal data packet, signature packet ]: - // 1. Read the one-pass signature packet - // 2. Peek 2 bytes of the literal data packet - // 3. Parse the one-pass signature packet - // - // 4. Read the literal data packet, simultaneously stream-parsing it - // 5. Peek until the end of the message - // 6. Finish parsing the literal data packet - // - // 7. Read the signature packet again (we already peeked at it in step 5) - // 8. Peek at the end of the stream again (`peekBytes` returns undefined) - // 9. Parse the signature packet - // - // Note that this means that if there's an error in the very end of the - // stream, such as an MDC error, we throw in step 5 instead of in step 8 - // (or never), which is the point of this exercise. - const nextPacket = await reader.peekBytes(supportsStreaming ? Infinity : 2); - if (writer) { - await writer.ready; - await writer.close(); - } else { - packet = _util2.default.concatUint8Array(packet); - await callback({ tag, packet }); - } - return !nextPacket || !nextPacket.length; - } catch (e) { - if (writer) { - await writer.abort(e); - return true; - } else { - throw e; - } - } finally { - if (writer) { - await callbackReturned; - } - reader.releaseLock(); - } - } -}; - -},{"../enums":113,"../util":152,"web-stream-tools":75}],130:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _webStreamTools = require('web-stream-tools'); - -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); - -var _all_packets = require('./all_packets'); - -var packets = _interopRequireWildcard(_all_packets); - -var _packet = require('./packet'); - -var _packet2 = _interopRequireDefault(_packet); - -var _config = require('../config'); - -var _config2 = _interopRequireDefault(_config); - -var _enums = require('../enums'); - -var _enums2 = _interopRequireDefault(_enums); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * This class represents a list of openpgp packets. - * Take care when iterating over it - the packets themselves - * are stored as numerical indices. - * @memberof module:packet - * @constructor - * @extends Array - */ -/* eslint-disable callback-return */ -/** - * @requires web-stream-tools - * @requires packet/all_packets - * @requires packet/packet - * @requires config - * @requires enums - * @requires util - */ - -function List() { - /** - * The number of packets contained within the list. - * @readonly - * @type {Integer} - */ - this.length = 0; -} - -List.prototype = []; - -/** - * Reads a stream of binary data and interprents it as a list of packets. - * @param {Uint8Array | ReadableStream} A Uint8Array of bytes. - */ -List.prototype.read = async function (bytes, streaming) { - this.stream = _webStreamTools2.default.transformPair(bytes, async (readable, writable) => { - const writer = _webStreamTools2.default.getWriter(writable); - try { - while (true) { - await writer.ready; - const done = await _packet2.default.read(readable, streaming, async parsed => { - try { - const tag = _enums2.default.read(_enums2.default.packet, parsed.tag); - const packet = packets.newPacketFromTag(tag); - packet.packets = new List(); - packet.fromStream = _util2.default.isStream(parsed.packet); - await packet.read(parsed.packet, streaming); - await writer.write(packet); - } catch (e) { - if (!_config2.default.tolerant || _packet2.default.supportsStreaming(parsed.tag)) { - // The packets that support streaming are the ones that contain - // message data. Those are also the ones we want to be more strict - // about and throw on parse errors for. - await writer.abort(e); - } - _util2.default.print_debug_error(e); - } - }); - if (done) { - await writer.ready; - await writer.close(); - return; - } - } - } catch (e) { - await writer.abort(e); - } - }); - - // Wait until first few packets have been read - const reader = _webStreamTools2.default.getReader(this.stream); - while (true) { - var _ref = await reader.read(); - - const done = _ref.done, - value = _ref.value; - - if (!done) { - this.push(value); - } else { - this.stream = null; - } - if (done || _packet2.default.supportsStreaming(value.tag)) { - break; - } - } - reader.releaseLock(); -}; - -/** - * Creates a binary representation of openpgp objects contained within the - * class instance. - * @returns {Uint8Array} A Uint8Array containing valid openpgp packets. - */ -List.prototype.write = function () { - const arr = []; - - for (let i = 0; i < this.length; i++) { - const packetbytes = this[i].write(); - if (_util2.default.isStream(packetbytes) && _packet2.default.supportsStreaming(this[i].tag)) { - let buffer = []; - let bufferLength = 0; - const minLength = 512; - arr.push(_packet2.default.writeTag(this[i].tag)); - arr.push(_webStreamTools2.default.transform(packetbytes, value => { - buffer.push(value); - bufferLength += value.length; - if (bufferLength >= minLength) { - const powerOf2 = Math.min(Math.log(bufferLength) / Math.LN2 | 0, 30); - const chunkSize = 2 ** powerOf2; - const bufferConcat = _util2.default.concat([_packet2.default.writePartialLength(powerOf2)].concat(buffer)); - buffer = [bufferConcat.subarray(1 + chunkSize)]; - bufferLength = buffer[0].length; - return bufferConcat.subarray(0, 1 + chunkSize); - } - }, () => _util2.default.concat([_packet2.default.writeSimpleLength(bufferLength)].concat(buffer)))); - } else { - if (_util2.default.isStream(packetbytes)) { - let length = 0; - arr.push(_webStreamTools2.default.transform(_webStreamTools2.default.clone(packetbytes), value => { - length += value.length; - }, () => _packet2.default.writeHeader(this[i].tag, length))); - } else { - arr.push(_packet2.default.writeHeader(this[i].tag, packetbytes.length)); - } - arr.push(packetbytes); - } - } - - return _util2.default.concat(arr); -}; - -/** - * Adds a packet to the list. This is the only supported method of doing so; - * writing to packetlist[i] directly will result in an error. - * @param {Object} packet Packet to push - */ -List.prototype.push = function (packet) { - if (!packet) { - return; - } - - packet.packets = packet.packets || new List(); - - this[this.length] = packet; - this.length++; -}; - -/** - * Creates a new PacketList with all packets from the given types - */ -List.prototype.filterByTag = function (...args) { - const filtered = new List(); - - const handle = tag => packetType => tag === packetType; - - for (let i = 0; i < this.length; i++) { - if (args.some(handle(this[i].tag))) { - filtered.push(this[i]); - } - } - - return filtered; -}; - -/** - * Traverses packet tree and returns first matching packet - * @param {module:enums.packet} type The packet type - * @returns {module:packet/packet|undefined} - */ -List.prototype.findPacket = function (type) { - return this.find(packet => packet.tag === type); -}; - -/** - * Returns array of found indices by tag - */ -List.prototype.indexOfTag = function (...args) { - const tagIndex = []; - const that = this; - - const handle = tag => packetType => tag === packetType; - - for (let i = 0; i < this.length; i++) { - if (args.some(handle(that[i].tag))) { - tagIndex.push(i); - } - } - return tagIndex; -}; - -/** - * Concatenates packetlist or array of packets - */ -List.prototype.concat = function (packetlist) { - if (packetlist) { - for (let i = 0; i < packetlist.length; i++) { - this.push(packetlist[i]); - } - } - return this; -}; - -/** - * Allocate a new packetlist from structured packetlist clone - * See {@link https://w3c.github.io/html/infrastructure.html#safe-passing-of-structured-data} - * @param {Object} packetClone packetlist clone - * @returns {Object} new packetlist object with data from packetlist clone - */ -List.fromStructuredClone = function (packetlistClone) { - const packetlist = new List(); - for (let i = 0; i < packetlistClone.length; i++) { - const packet = packets.fromStructuredClone(packetlistClone[i]); - packetlist.push(packet); - if (packet.embeddedSignature) { - packet.embeddedSignature = packets.fromStructuredClone(packet.embeddedSignature); - } - if (packet.packets.length !== 0) { - packet.packets = this.fromStructuredClone(packet.packets); - } else { - packet.packets = new List(); - } - } - if (packetlistClone.stream) { - packetlist.stream = _webStreamTools2.default.transform(packetlistClone.stream, packet => packets.fromStructuredClone(packet)); - } - return packetlist; -}; - -exports.default = List; - -},{"../config":79,"../enums":113,"../util":152,"./all_packets":122,"./packet":129,"web-stream-tools":75}],131:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _sha = require('asmcrypto.js/dist_es5/hash/sha1/sha1'); - -var _sha2 = require('asmcrypto.js/dist_es5/hash/sha256/sha256'); - -var _keyid = require('../type/keyid'); - -var _keyid2 = _interopRequireDefault(_keyid); - -var _mpi = require('../type/mpi'); - -var _mpi2 = _interopRequireDefault(_mpi); - -var _config = require('../config'); - -var _config2 = _interopRequireDefault(_config); - -var _crypto = require('../crypto'); - -var _crypto2 = _interopRequireDefault(_crypto); - -var _enums = require('../enums'); - -var _enums2 = _interopRequireDefault(_enums); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Implementation of the Key Material Packet (Tag 5,6,7,14) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.5|RFC4480 5.5}: - * A key material packet contains all the information about a public or - * private key. There are four variants of this packet type, and two - * major versions. - * - * A Public-Key packet starts a series of packets that forms an OpenPGP - * key (sometimes called an OpenPGP certificate). - * @memberof module:packet - * @constructor - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @requires type/keyid - * @requires type/mpi - * @requires config - * @requires crypto - * @requires enums - * @requires util - */ - -function PublicKey(date = new Date()) { - /** - * Packet type - * @type {module:enums.packet} - */ - this.tag = _enums2.default.packet.publicKey; - /** - * Packet version - * @type {Integer} - */ - this.version = _config2.default.v5_keys ? 5 : 4; - /** - * Key creation date. - * @type {Date} - */ - this.created = _util2.default.normalizeDate(date); - /** - * Public key algorithm. - * @type {String} - */ - this.algorithm = null; - /** - * Algorithm specific params - * @type {Array} - */ - this.params = []; - /** - * Time until expiration in days (V3 only) - * @type {Integer} - */ - this.expirationTimeV3 = 0; - /** - * Fingerprint in lowercase hex - * @type {String} - */ - this.fingerprint = null; - /** - * Keyid - * @type {module:type/keyid} - */ - this.keyid = null; -} - -/** - * Internal Parser for public keys as specified in {@link https://tools.ietf.org/html/rfc4880#section-5.5.2|RFC 4880 section 5.5.2 Public-Key Packet Formats} - * called by read_tag<num> - * @param {Uint8Array} bytes Input array to read the packet from - * @returns {Object} This object with attributes set by the parser - */ -PublicKey.prototype.read = function (bytes) { - let pos = 0; - // A one-octet version number (3, 4 or 5). - this.version = bytes[pos++]; - - if (this.version === 4 || this.version === 5) { - // - A four-octet number denoting the time that the key was created. - this.created = _util2.default.readDate(bytes.subarray(pos, pos + 4)); - pos += 4; - - // - A one-octet number denoting the public-key algorithm of this key. - this.algorithm = _enums2.default.read(_enums2.default.publicKey, bytes[pos++]); - const algo = _enums2.default.write(_enums2.default.publicKey, this.algorithm); - - if (this.version === 5) { - // - A four-octet scalar octet count for the following key material. - pos += 4; - } - - // - A series of values comprising the key material. This is - // algorithm-specific and described in section XXXX. - const types = _crypto2.default.getPubKeyParamTypes(algo); - this.params = _crypto2.default.constructParams(types); - - for (let i = 0; i < types.length && pos < bytes.length; i++) { - pos += this.params[i].read(bytes.subarray(pos, bytes.length)); - if (pos > bytes.length) { - throw new Error('Error reading MPI @:' + pos); - } - } - - return pos; - } - throw new Error('Version ' + this.version + ' of the key packet is unsupported.'); -}; - -/** - * Alias of read() - * @see module:packet.PublicKey#read - */ -PublicKey.prototype.readPublicKey = PublicKey.prototype.read; - -/** - * Same as write_private_key, but has less information because of - * public key. - * @returns {Uint8Array} OpenPGP packet body contents, - */ -PublicKey.prototype.write = function () { - const arr = []; - // Version - arr.push(new Uint8Array([this.version])); - arr.push(_util2.default.writeDate(this.created)); - // A one-octet number denoting the public-key algorithm of this key - const algo = _enums2.default.write(_enums2.default.publicKey, this.algorithm); - arr.push(new Uint8Array([algo])); - - const paramCount = _crypto2.default.getPubKeyParamTypes(algo).length; - const params = _util2.default.concatUint8Array(this.params.slice(0, paramCount).map(param => param.write())); - if (this.version === 5) { - // A four-octet scalar octet count for the following key material - arr.push(_util2.default.writeNumber(params.length, 4)); - } - // Algorithm-specific params - arr.push(params); - return _util2.default.concatUint8Array(arr); -}; - -/** - * Alias of write() - * @see module:packet.PublicKey#write - */ -PublicKey.prototype.writePublicKey = PublicKey.prototype.write; - -/** - * Write packet in order to be hashed; either for a signature or a fingerprint. - */ -PublicKey.prototype.writeForHash = function (version) { - const bytes = this.writePublicKey(); - - if (version === 5) { - return _util2.default.concatUint8Array([new Uint8Array([0x9A]), _util2.default.writeNumber(bytes.length, 4), bytes]); - } - return _util2.default.concatUint8Array([new Uint8Array([0x99]), _util2.default.writeNumber(bytes.length, 2), bytes]); -}; - -/** - * Check whether secret-key data is available in decrypted form. Returns null for public keys. - * @returns {Boolean|null} - */ -PublicKey.prototype.isDecrypted = function () { - return null; -}; - -/** - * Returns the creation time of the key - * @returns {Date} - */ -PublicKey.prototype.getCreationTime = function () { - return this.created; -}; - -/** - * Calculates the key id of the key - * @returns {String} A 8 byte key id - */ -PublicKey.prototype.getKeyId = function () { - if (this.keyid) { - return this.keyid; - } - this.keyid = new _keyid2.default(); - if (this.version === 5) { - this.keyid.read(_util2.default.hex_to_Uint8Array(this.getFingerprint()).subarray(0, 8)); - } else if (this.version === 4) { - this.keyid.read(_util2.default.hex_to_Uint8Array(this.getFingerprint()).subarray(12, 20)); - } - return this.keyid; -}; - -/** - * Calculates the fingerprint of the key - * @returns {Uint8Array} A Uint8Array containing the fingerprint - */ -PublicKey.prototype.getFingerprintBytes = function () { - if (this.fingerprint) { - return this.fingerprint; - } - const toHash = this.writeForHash(this.version); - if (this.version === 5) { - this.fingerprint = _sha2.Sha256.bytes(toHash); - } else if (this.version === 4) { - this.fingerprint = _sha.Sha1.bytes(toHash); - } - return this.fingerprint; -}; - -/** - * Calculates the fingerprint of the key - * @returns {String} A string containing the fingerprint in lowercase hex - */ -PublicKey.prototype.getFingerprint = function () { - return _util2.default.Uint8Array_to_hex(this.getFingerprintBytes()); -}; - -/** - * Calculates whether two keys have the same fingerprint without actually calculating the fingerprint - * @returns {Boolean} Whether the two keys have the same version and public key data - */ -PublicKey.prototype.hasSameFingerprintAs = function (other) { - return this.version === other.version && _util2.default.equalsUint8Array(this.writePublicKey(), other.writePublicKey()); -}; - -/** - * Returns algorithm information - * @returns {Object} An object of the form {algorithm: String, bits:int, curve:String} - */ -PublicKey.prototype.getAlgorithmInfo = function () { - const result = {}; - result.algorithm = this.algorithm; - if (this.params[0] instanceof _mpi2.default) { - result.bits = this.params[0].byteLength() * 8; - } else { - result.curve = this.params[0].getName(); - } - return result; -}; - -/** - * Fix custom types after cloning - */ -PublicKey.prototype.postCloneTypeFix = function () { - const algo = _enums2.default.write(_enums2.default.publicKey, this.algorithm); - const types = _crypto2.default.getPubKeyParamTypes(algo); - for (let i = 0; i < types.length; i++) { - const param = this.params[i]; - this.params[i] = types[i].fromClone(param); - } - if (this.keyid) { - this.keyid = _keyid2.default.fromClone(this.keyid); - } -}; - -exports.default = PublicKey; - -},{"../config":79,"../crypto":94,"../enums":113,"../type/keyid":148,"../type/mpi":149,"../util":152,"asmcrypto.js/dist_es5/hash/sha1/sha1":11,"asmcrypto.js/dist_es5/hash/sha256/sha256":13}],132:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _keyid = require('../type/keyid'); - -var _keyid2 = _interopRequireDefault(_keyid); - -var _mpi = require('../type/mpi'); - -var _mpi2 = _interopRequireDefault(_mpi); - -var _crypto = require('../crypto'); - -var _crypto2 = _interopRequireDefault(_crypto); - -var _enums = require('../enums'); - -var _enums2 = _interopRequireDefault(_enums); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Public-Key Encrypted Session Key Packets (Tag 1) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.1|RFC4880 5.1}: - * A Public-Key Encrypted Session Key packet holds the session key - * used to encrypt a message. Zero or more Public-Key Encrypted Session Key - * packets and/or Symmetric-Key Encrypted Session Key packets may precede a - * Symmetrically Encrypted Data Packet, which holds an encrypted message. The - * message is encrypted with the session key, and the session key is itself - * encrypted and stored in the Encrypted Session Key packet(s). The - * Symmetrically Encrypted Data Packet is preceded by one Public-Key Encrypted - * Session Key packet for each OpenPGP key to which the message is encrypted. - * The recipient of the message finds a session key that is encrypted to their - * public key, decrypts the session key, and then uses the session key to - * decrypt the message. - * @memberof module:packet - * @constructor - */ -function PublicKeyEncryptedSessionKey() { - this.tag = _enums2.default.packet.publicKeyEncryptedSessionKey; - this.version = 3; - - this.publicKeyId = new _keyid2.default(); - this.publicKeyAlgorithm = null; - - this.sessionKey = null; - this.sessionKeyAlgorithm = null; - - /** @type {Array} */ - this.encrypted = []; -} - -/** - * Parsing function for a publickey encrypted session key packet (tag 1). - * - * @param {Uint8Array} input Payload of a tag 1 packet - * @param {Integer} position Position to start reading from the input string - * @param {Integer} len Length of the packet or the remaining length of - * input at position - * @returns {module:packet.PublicKeyEncryptedSessionKey} Object representation - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @requires type/keyid - * @requires type/mpi - * @requires crypto - * @requires enums - * @requires util - */ - -PublicKeyEncryptedSessionKey.prototype.read = function (bytes) { - this.version = bytes[0]; - this.publicKeyId.read(bytes.subarray(1, bytes.length)); - this.publicKeyAlgorithm = _enums2.default.read(_enums2.default.publicKey, bytes[9]); - - let i = 10; - - const algo = _enums2.default.write(_enums2.default.publicKey, this.publicKeyAlgorithm); - const types = _crypto2.default.getEncSessionKeyParamTypes(algo); - this.encrypted = _crypto2.default.constructParams(types); - - for (let j = 0; j < types.length; j++) { - i += this.encrypted[j].read(bytes.subarray(i, bytes.length)); - } -}; - -/** - * Create a string representation of a tag 1 packet - * - * @returns {Uint8Array} The Uint8Array representation - */ -PublicKeyEncryptedSessionKey.prototype.write = function () { - const arr = [new Uint8Array([this.version]), this.publicKeyId.write(), new Uint8Array([_enums2.default.write(_enums2.default.publicKey, this.publicKeyAlgorithm)])]; - - for (let i = 0; i < this.encrypted.length; i++) { - arr.push(this.encrypted[i].write()); - } - - return _util2.default.concatUint8Array(arr); -}; - -/** - * Encrypt session key packet - * @param {module:packet.PublicKey} key Public key - * @returns {Promise} - * @async - */ -PublicKeyEncryptedSessionKey.prototype.encrypt = async function (key) { - let data = String.fromCharCode(_enums2.default.write(_enums2.default.symmetric, this.sessionKeyAlgorithm)); - - data += _util2.default.Uint8Array_to_str(this.sessionKey); - data += _util2.default.Uint8Array_to_str(_util2.default.write_checksum(this.sessionKey)); - - let toEncrypt; - const algo = _enums2.default.write(_enums2.default.publicKey, this.publicKeyAlgorithm); - if (algo === _enums2.default.publicKey.ecdh) { - toEncrypt = new _mpi2.default(_crypto2.default.pkcs5.encode(data)); - } else { - toEncrypt = new _mpi2.default((await _crypto2.default.pkcs1.eme.encode(data, key.params[0].byteLength()))); - } - - this.encrypted = await _crypto2.default.publicKeyEncrypt(algo, key.params, toEncrypt, key.getFingerprintBytes()); - return true; -}; - -/** - * Decrypts the session key (only for public key encrypted session key - * packets (tag 1) - * - * @param {module:packet.SecretKey} key - * Private key with secret params unlocked - * @returns {Promise} - * @async - */ -PublicKeyEncryptedSessionKey.prototype.decrypt = async function (key) { - const algo = _enums2.default.write(_enums2.default.publicKey, this.publicKeyAlgorithm); - const result = new _mpi2.default((await _crypto2.default.publicKeyDecrypt(algo, key.params, this.encrypted, key.getFingerprintBytes()))); - - let checksum; - let decoded; - if (algo === _enums2.default.publicKey.ecdh) { - decoded = _crypto2.default.pkcs5.decode(result.toString()); - checksum = _util2.default.str_to_Uint8Array(decoded.substr(decoded.length - 2)); - } else { - decoded = _crypto2.default.pkcs1.eme.decode(result.toString()); - checksum = result.toUint8Array().slice(result.byteLength() - 2); - } - - key = _util2.default.str_to_Uint8Array(decoded.substring(1, decoded.length - 2)); - - if (!_util2.default.equalsUint8Array(checksum, _util2.default.write_checksum(key))) { - throw new Error('Decryption error'); - } else { - this.sessionKey = key; - this.sessionKeyAlgorithm = _enums2.default.read(_enums2.default.symmetric, decoded.charCodeAt(0)); - } - return true; -}; - -/** - * Fix custom types after cloning - */ -PublicKeyEncryptedSessionKey.prototype.postCloneTypeFix = function () { - this.publicKeyId = _keyid2.default.fromClone(this.publicKeyId); - const algo = _enums2.default.write(_enums2.default.publicKey, this.publicKeyAlgorithm); - const types = _crypto2.default.getEncSessionKeyParamTypes(algo); - for (let i = 0; i < this.encrypted.length; i++) { - this.encrypted[i] = types[i].fromClone(this.encrypted[i]); - } -}; - -exports.default = PublicKeyEncryptedSessionKey; - -},{"../crypto":94,"../enums":113,"../type/keyid":148,"../type/mpi":149,"../util":152}],133:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _public_key = require('./public_key'); - -var _public_key2 = _interopRequireDefault(_public_key); - -var _enums = require('../enums'); - -var _enums2 = _interopRequireDefault(_enums); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * A Public-Subkey packet (tag 14) has exactly the same format as a - * Public-Key packet, but denotes a subkey. One or more subkeys may be - * associated with a top-level key. By convention, the top-level key - * provides signature services, and the subkeys provide encryption - * services. - * @memberof module:packet - * @constructor - * @extends module:packet.PublicKey - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @requires packet/public_key - * @requires enums - */ - -function PublicSubkey() { - _public_key2.default.call(this); - this.tag = _enums2.default.packet.publicSubkey; -} - -PublicSubkey.prototype = new _public_key2.default(); -PublicSubkey.prototype.constructor = PublicSubkey; - -exports.default = PublicSubkey; - -},{"../enums":113,"./public_key":131}],134:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _public_key = require('./public_key'); - -var _public_key2 = _interopRequireDefault(_public_key); - -var _keyid = require('../type/keyid.js'); - -var _keyid2 = _interopRequireDefault(_keyid); - -var _s2k = require('../type/s2k'); - -var _s2k2 = _interopRequireDefault(_s2k); - -var _crypto = require('../crypto'); - -var _crypto2 = _interopRequireDefault(_crypto); - -var _enums = require('../enums'); - -var _enums2 = _interopRequireDefault(_enums); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * A Secret-Key packet contains all the information that is found in a - * Public-Key packet, including the public-key material, but also - * includes the secret-key material after all the public-key fields. - * @memberof module:packet - * @constructor - * @extends module:packet.PublicKey - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @requires packet/public_key - * @requires type/keyid - * @requires type/s2k - * @requires crypto - * @requires enums - * @requires util - */ - -function SecretKey(date = new Date()) { - _public_key2.default.call(this, date); - /** - * Packet type - * @type {module:enums.packet} - */ - this.tag = _enums2.default.packet.secretKey; - /** - * Secret-key data - */ - this.keyMaterial = null; - /** - * Indicates whether secret-key data is encrypted. `this.isEncrypted === false` means data is available in decrypted form. - */ - this.isEncrypted = null; - /** - * S2K usage - * @type {Integer} - */ - this.s2k_usage = 0; - /** - * S2K object - * @type {type/s2k} - */ - this.s2k = null; - /** - * Symmetric algorithm - * @type {String} - */ - this.symmetric = 'aes256'; - /** - * AEAD algorithm - * @type {String} - */ - this.aead = 'eax'; -} - -SecretKey.prototype = new _public_key2.default(); -SecretKey.prototype.constructor = SecretKey; - -// Helper function - -function parse_cleartext_params(cleartext, algorithm) { - const algo = _enums2.default.write(_enums2.default.publicKey, algorithm); - const types = _crypto2.default.getPrivKeyParamTypes(algo); - const params = _crypto2.default.constructParams(types); - let p = 0; - - for (let i = 0; i < types.length && p < cleartext.length; i++) { - p += params[i].read(cleartext.subarray(p, cleartext.length)); - if (p > cleartext.length) { - throw new Error('Error reading param @:' + p); - } - } - - return params; -} - -function write_cleartext_params(params, algorithm) { - const arr = []; - const algo = _enums2.default.write(_enums2.default.publicKey, algorithm); - const numPublicParams = _crypto2.default.getPubKeyParamTypes(algo).length; - - for (let i = numPublicParams; i < params.length; i++) { - arr.push(params[i].write()); - } - - return _util2.default.concatUint8Array(arr); -} - -// 5.5.3. Secret-Key Packet Formats - -/** - * Internal parser for private keys as specified in - * {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.5.3|RFC4880bis-04 section 5.5.3} - * @param {String} bytes Input string to read the packet from - */ -SecretKey.prototype.read = function (bytes) { - // - A Public-Key or Public-Subkey packet, as described above. - let i = this.readPublicKey(bytes); - - // - One octet indicating string-to-key usage conventions. Zero - // indicates that the secret-key data is not encrypted. 255 or 254 - // indicates that a string-to-key specifier is being given. Any - // other value is a symmetric-key encryption algorithm identifier. - this.s2k_usage = bytes[i++]; - - // - Only for a version 5 packet, a one-octet scalar octet count of - // the next 4 optional fields. - if (this.version === 5) { - i++; - } - - // - [Optional] If string-to-key usage octet was 255, 254, or 253, a - // one-octet symmetric encryption algorithm. - if (this.s2k_usage === 255 || this.s2k_usage === 254 || this.s2k_usage === 253) { - this.symmetric = bytes[i++]; - this.symmetric = _enums2.default.read(_enums2.default.symmetric, this.symmetric); - - // - [Optional] If string-to-key usage octet was 253, a one-octet - // AEAD algorithm. - if (this.s2k_usage === 253) { - this.aead = bytes[i++]; - this.aead = _enums2.default.read(_enums2.default.aead, this.aead); - } - - // - [Optional] If string-to-key usage octet was 255, 254, or 253, a - // string-to-key specifier. The length of the string-to-key - // specifier is implied by its type, as described above. - this.s2k = new _s2k2.default(); - i += this.s2k.read(bytes.subarray(i, bytes.length)); - - if (this.s2k.type === 'gnu-dummy') { - return; - } - } else if (this.s2k_usage) { - this.symmetric = this.s2k_usage; - this.symmetric = _enums2.default.read(_enums2.default.symmetric, this.symmetric); - } - - // - [Optional] If secret data is encrypted (string-to-key usage octet - // not zero), an Initial Vector (IV) of the same length as the - // cipher's block size. - if (this.s2k_usage) { - this.iv = bytes.subarray(i, i + _crypto2.default.cipher[this.symmetric].blockSize); - - i += this.iv.length; - } - - // - Only for a version 5 packet, a four-octet scalar octet count for - // the following key material. - if (this.version === 5) { - i += 4; - } - - // - Plain or encrypted multiprecision integers comprising the secret - // key data. These algorithm-specific fields are as described - // below. - this.keyMaterial = bytes.subarray(i); - this.isEncrypted = !!this.s2k_usage; - - if (!this.isEncrypted) { - const cleartext = this.keyMaterial.subarray(0, -2); - if (!_util2.default.equalsUint8Array(_util2.default.write_checksum(cleartext), this.keyMaterial.subarray(-2))) { - throw new Error('Key checksum mismatch'); - } - const privParams = parse_cleartext_params(cleartext, this.algorithm); - this.params = this.params.concat(privParams); - } -}; - -/** - * Creates an OpenPGP key packet for the given key. - * @returns {String} A string of bytes containing the secret key OpenPGP packet - */ -SecretKey.prototype.write = function () { - const arr = [this.writePublicKey()]; - - arr.push(new Uint8Array([this.s2k_usage])); - - const optionalFieldsArr = []; - // - [Optional] If string-to-key usage octet was 255, 254, or 253, a - // one- octet symmetric encryption algorithm. - if (this.s2k_usage === 255 || this.s2k_usage === 254 || this.s2k_usage === 253) { - optionalFieldsArr.push(_enums2.default.write(_enums2.default.symmetric, this.symmetric)); - - // - [Optional] If string-to-key usage octet was 253, a one-octet - // AEAD algorithm. - if (this.s2k_usage === 253) { - optionalFieldsArr.push(_enums2.default.write(_enums2.default.aead, this.aead)); - } - - // - [Optional] If string-to-key usage octet was 255, 254, or 253, a - // string-to-key specifier. The length of the string-to-key - // specifier is implied by its type, as described above. - optionalFieldsArr.push(...this.s2k.write()); - } - - // - [Optional] If secret data is encrypted (string-to-key usage octet - // not zero), an Initial Vector (IV) of the same length as the - // cipher's block size. - if (this.s2k_usage && this.s2k.type !== 'gnu-dummy') { - optionalFieldsArr.push(...this.iv); - } - - if (this.version === 5) { - arr.push(new Uint8Array([optionalFieldsArr.length])); - } - arr.push(new Uint8Array(optionalFieldsArr)); - - if (!this.s2k || this.s2k.type !== 'gnu-dummy') { - if (!this.s2k_usage) { - const cleartextParams = write_cleartext_params(this.params, this.algorithm); - this.keyMaterial = _util2.default.concatUint8Array([cleartextParams, _util2.default.write_checksum(cleartextParams)]); - } - - if (this.version === 5) { - arr.push(_util2.default.writeNumber(this.keyMaterial.length, 4)); - } - arr.push(this.keyMaterial); - } - - return _util2.default.concatUint8Array(arr); -}; - -/** - * Check whether secret-key data is available in decrypted form. Returns null for public keys. - * @returns {Boolean|null} - */ -SecretKey.prototype.isDecrypted = function () { - return this.isEncrypted === false; -}; - -/** - * Encrypt the payload. By default, we use aes256 and iterated, salted string - * to key specifier. If the key is in a decrypted state (isEncrypted === false) - * and the passphrase is empty or undefined, the key will be set as not encrypted. - * This can be used to remove passphrase protection after calling decrypt(). - * @param {String} passphrase - * @returns {Promise} - * @async - */ -SecretKey.prototype.encrypt = async function (passphrase) { - if (this.s2k && this.s2k.type === 'gnu-dummy') { - return false; - } - - if (this.isDecrypted() && !passphrase) { - this.s2k_usage = 0; - return false; - } else if (!passphrase) { - throw new Error('The key must be decrypted before removing passphrase protection.'); - } - - this.s2k = new _s2k2.default(); - this.s2k.salt = await _crypto2.default.random.getRandomBytes(8); - const cleartext = write_cleartext_params(this.params, this.algorithm); - const key = await produceEncryptionKey(this.s2k, passphrase, this.symmetric); - const blockLen = _crypto2.default.cipher[this.symmetric].blockSize; - this.iv = await _crypto2.default.random.getRandomBytes(blockLen); - - if (this.version === 5) { - this.s2k_usage = 253; - const mode = _crypto2.default[this.aead]; - const modeInstance = await mode(this.symmetric, key); - this.keyMaterial = await modeInstance.encrypt(cleartext, this.iv.subarray(0, mode.ivLength), new Uint8Array()); - } else { - this.s2k_usage = 254; - this.keyMaterial = _crypto2.default.cfb.encrypt(this.symmetric, key, _util2.default.concatUint8Array([cleartext, await _crypto2.default.hash.sha1(cleartext)]), this.iv); - } - return true; -}; - -async function produceEncryptionKey(s2k, passphrase, algorithm) { - return s2k.produce_key(passphrase, _crypto2.default.cipher[algorithm].keySize); -} - -/** - * Decrypts the private key params which are needed to use the key. - * {@link module:packet.SecretKey.isDecrypted} should be false, as - * otherwise calls to this function will throw an error. - * @param {String} passphrase The passphrase for this private key as string - * @returns {Promise} - * @async - */ -SecretKey.prototype.decrypt = async function (passphrase) { - if (this.s2k.type === 'gnu-dummy') { - this.isEncrypted = false; - return false; - } - - if (this.isDecrypted()) { - throw new Error('Key packet is already decrypted.'); - } - - let key; - if (this.s2k_usage === 255 || this.s2k_usage === 254 || this.s2k_usage === 253) { - key = await produceEncryptionKey(this.s2k, passphrase, this.symmetric); - } else { - key = await _crypto2.default.hash.md5(passphrase); - } - - let cleartext; - if (this.s2k_usage === 253) { - const mode = _crypto2.default[this.aead]; - try { - const modeInstance = await mode(this.symmetric, key); - cleartext = await modeInstance.decrypt(this.keyMaterial, this.iv.subarray(0, mode.ivLength), new Uint8Array()); - } catch (err) { - if (err.message === 'Authentication tag mismatch') { - throw new Error('Incorrect key passphrase: ' + err.message); - } - throw err; - } - } else { - const cleartextWithHash = await _crypto2.default.cfb.decrypt(this.symmetric, key, this.keyMaterial, this.iv); - - let hash; - let hashlen; - if (this.s2k_usage === 255) { - hashlen = 2; - cleartext = cleartextWithHash.subarray(0, -hashlen); - hash = _util2.default.write_checksum(cleartext); - } else { - hashlen = 20; - cleartext = cleartextWithHash.subarray(0, -hashlen); - hash = await _crypto2.default.hash.sha1(cleartext); - } - - if (!_util2.default.equalsUint8Array(hash, cleartextWithHash.subarray(-hashlen))) { - throw new Error('Incorrect key passphrase'); - } - } - - const privParams = parse_cleartext_params(cleartext, this.algorithm); - this.params = this.params.concat(privParams); - this.isEncrypted = false; - this.keyMaterial = null; - this.s2k_usage = 0; - - return true; -}; - -SecretKey.prototype.generate = async function (bits, curve) { - const algo = _enums2.default.write(_enums2.default.publicKey, this.algorithm); - this.params = await _crypto2.default.generateParams(algo, bits, curve); - this.isEncrypted = false; -}; - -/** - * Clear private params, return to initial state - */ -SecretKey.prototype.clearPrivateParams = function () { - if (this.s2k && this.s2k.type === 'gnu-dummy') { - this.isEncrypted = true; - return; - } - - if (!this.keyMaterial) { - throw new Error('If secret key is not encrypted, clearing private params is irreversible.'); - } - const algo = _enums2.default.write(_enums2.default.publicKey, this.algorithm); - this.params = this.params.slice(0, _crypto2.default.getPubKeyParamTypes(algo).length); - this.isEncrypted = true; -}; - -/** - * Fix custom types after cloning - */ -SecretKey.prototype.postCloneTypeFix = function () { - const algo = _enums2.default.write(_enums2.default.publicKey, this.algorithm); - const types = [].concat(_crypto2.default.getPubKeyParamTypes(algo), _crypto2.default.getPrivKeyParamTypes(algo)); - for (let i = 0; i < this.params.length; i++) { - const param = this.params[i]; - this.params[i] = types[i].fromClone(param); - } - if (this.keyid) { - this.keyid = _keyid2.default.fromClone(this.keyid); - } -}; - -exports.default = SecretKey; - -},{"../crypto":94,"../enums":113,"../type/keyid.js":148,"../type/s2k":151,"../util":152,"./public_key":131}],135:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _secret_key = require('./secret_key'); - -var _secret_key2 = _interopRequireDefault(_secret_key); - -var _enums = require('../enums'); - -var _enums2 = _interopRequireDefault(_enums); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * A Secret-Subkey packet (tag 7) is the subkey analog of the Secret - * Key packet and has exactly the same format. - * @memberof module:packet - * @constructor - * @extends module:packet.SecretKey - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @requires packet/secret_key - * @requires enums - */ - -function SecretSubkey(date = new Date()) { - _secret_key2.default.call(this, date); - this.tag = _enums2.default.packet.secretSubkey; -} - -SecretSubkey.prototype = new _secret_key2.default(); -SecretSubkey.prototype.constructor = SecretSubkey; - -exports.default = SecretSubkey; - -},{"../enums":113,"./secret_key":134}],136:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _webStreamTools = require('web-stream-tools'); - -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); - -var _packet = require('./packet'); - -var _packet2 = _interopRequireDefault(_packet); - -var _keyid = require('../type/keyid.js'); - -var _keyid2 = _interopRequireDefault(_keyid); - -var _mpi = require('../type/mpi.js'); - -var _mpi2 = _interopRequireDefault(_mpi); - -var _crypto = require('../crypto'); - -var _crypto2 = _interopRequireDefault(_crypto); - -var _enums = require('../enums'); - -var _enums2 = _interopRequireDefault(_enums); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -var _config = require('../config'); - -var _config2 = _interopRequireDefault(_config); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Implementation of the Signature Packet (Tag 2) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.2|RFC4480 5.2}: - * A Signature packet describes a binding between some public key and - * some data. The most common signatures are a signature of a file or a - * block of text, and a signature that is a certification of a User ID. - * @memberof module:packet - * @constructor - * @param {Date} date the creation date of the signature - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @requires web-stream-tools - * @requires packet/packet - * @requires type/keyid - * @requires type/mpi - * @requires crypto - * @requires enums - * @requires util - */ - -function Signature(date = new Date()) { - this.tag = _enums2.default.packet.signature; - this.version = 4; // This is set to 5 below if we sign with a V5 key. - this.signatureType = null; - this.hashAlgorithm = null; - this.publicKeyAlgorithm = null; - - this.signatureData = null; - this.unhashedSubpackets = []; - this.signedHashValue = null; - - this.created = _util2.default.normalizeDate(date); - this.signatureExpirationTime = null; - this.signatureNeverExpires = true; - this.exportable = null; - this.trustLevel = null; - this.trustAmount = null; - this.regularExpression = null; - this.revocable = null; - this.keyExpirationTime = null; - this.keyNeverExpires = null; - this.preferredSymmetricAlgorithms = null; - this.revocationKeyClass = null; - this.revocationKeyAlgorithm = null; - this.revocationKeyFingerprint = null; - this.issuerKeyId = new _keyid2.default(); - this.notations = []; - this.preferredHashAlgorithms = null; - this.preferredCompressionAlgorithms = null; - this.keyServerPreferences = null; - this.preferredKeyServer = null; - this.isPrimaryUserID = null; - this.policyURI = null; - this.keyFlags = null; - this.signersUserId = null; - this.reasonForRevocationFlag = null; - this.reasonForRevocationString = null; - this.features = null; - this.signatureTargetPublicKeyAlgorithm = null; - this.signatureTargetHashAlgorithm = null; - this.signatureTargetHash = null; - this.embeddedSignature = null; - this.issuerKeyVersion = null; - this.issuerFingerprint = null; - this.preferredAeadAlgorithms = null; - - this.verified = null; - this.revoked = null; -} - -/** - * parsing function for a signature packet (tag 2). - * @param {String} bytes payload of a tag 2 packet - * @param {Integer} position position to start reading from the bytes string - * @param {Integer} len length of the packet or the remaining length of bytes at position - * @returns {module:packet.Signature} object representation - */ -Signature.prototype.read = function (bytes) { - let i = 0; - this.version = bytes[i++]; - - if (this.version !== 4 && this.version !== 5) { - throw new Error('Version ' + this.version + ' of the signature is unsupported.'); - } - - this.signatureType = bytes[i++]; - this.publicKeyAlgorithm = bytes[i++]; - this.hashAlgorithm = bytes[i++]; - - // hashed subpackets - i += this.read_sub_packets(bytes.subarray(i, bytes.length), true); - - // A V4 signature hashes the packet body - // starting from its first field, the version number, through the end - // of the hashed subpacket data. Thus, the fields hashed are the - // signature version, the signature type, the public-key algorithm, the - // hash algorithm, the hashed subpacket length, and the hashed - // subpacket body. - this.signatureData = bytes.subarray(0, i); - - // unhashed subpackets - i += this.read_sub_packets(bytes.subarray(i, bytes.length), false); - - // Two-octet field holding left 16 bits of signed hash value. - this.signedHashValue = bytes.subarray(i, i + 2); - i += 2; - - this.signature = bytes.subarray(i, bytes.length); -}; - -Signature.prototype.write = function () { - const arr = []; - arr.push(this.signatureData); - arr.push(this.write_unhashed_sub_packets()); - arr.push(this.signedHashValue); - arr.push(_webStreamTools2.default.clone(this.signature)); - return _util2.default.concat(arr); -}; - -/** - * Signs provided data. This needs to be done prior to serialization. - * @param {module:packet.SecretKey} key private key used to sign the message. - * @param {Object} data Contains packets to be signed. - * @param {Boolean} detached (optional) whether to create a detached signature - * @returns {Promise} - * @async - */ -Signature.prototype.sign = async function (key, data, detached = false) { - const signatureType = _enums2.default.write(_enums2.default.signature, this.signatureType); - const publicKeyAlgorithm = _enums2.default.write(_enums2.default.publicKey, this.publicKeyAlgorithm); - const hashAlgorithm = _enums2.default.write(_enums2.default.hash, this.hashAlgorithm); - - if (key.version === 5) { - this.version = 5; - } - const arr = [new Uint8Array([this.version, signatureType, publicKeyAlgorithm, hashAlgorithm])]; - - if (key.version === 5) { - // We could also generate this subpacket for version 4 keys, but for - // now we don't. - this.issuerKeyVersion = key.version; - this.issuerFingerprint = key.getFingerprintBytes(); - } - - this.issuerKeyId = key.getKeyId(); - - // Add hashed subpackets - arr.push(this.write_hashed_sub_packets()); - - this.signatureData = _util2.default.concat(arr); - - const toHash = this.toHash(signatureType, data, detached); - const hash = await this.hash(signatureType, data, toHash, detached); - - this.signedHashValue = _webStreamTools2.default.slice(_webStreamTools2.default.clone(hash), 0, 2); - - const params = key.params; - this.signature = _webStreamTools2.default.fromAsync(async () => _crypto2.default.signature.sign(publicKeyAlgorithm, hashAlgorithm, params, toHash, (await _webStreamTools2.default.readToEnd(hash)))); - - // Store the fact that this signature is valid, e.g. for when we call `await - // getLatestValidSignature(this.revocationSignatures, key, data)` later. Note - // that this only holds up if the key and data passed to verify are the same - // as the ones passed to sign. - this.verified = true; - return true; -}; - -/** - * Creates Uint8Array of bytes of all subpacket data except Issuer and Embedded Signature subpackets - * @returns {Uint8Array} subpacket data - */ -Signature.prototype.write_hashed_sub_packets = function () { - const sub = _enums2.default.signatureSubpacket; - const arr = []; - let bytes; - if (this.created !== null) { - arr.push(write_sub_packet(sub.signature_creation_time, _util2.default.writeDate(this.created))); - } - if (this.signatureExpirationTime !== null) { - arr.push(write_sub_packet(sub.signature_expiration_time, _util2.default.writeNumber(this.signatureExpirationTime, 4))); - } - if (this.exportable !== null) { - arr.push(write_sub_packet(sub.exportable_certification, new Uint8Array([this.exportable ? 1 : 0]))); - } - if (this.trustLevel !== null) { - bytes = new Uint8Array([this.trustLevel, this.trustAmount]); - arr.push(write_sub_packet(sub.trust_signature, bytes)); - } - if (this.regularExpression !== null) { - arr.push(write_sub_packet(sub.regular_expression, this.regularExpression)); - } - if (this.revocable !== null) { - arr.push(write_sub_packet(sub.revocable, new Uint8Array([this.revocable ? 1 : 0]))); - } - if (this.keyExpirationTime !== null) { - arr.push(write_sub_packet(sub.key_expiration_time, _util2.default.writeNumber(this.keyExpirationTime, 4))); - } - if (this.preferredSymmetricAlgorithms !== null) { - bytes = _util2.default.str_to_Uint8Array(_util2.default.Uint8Array_to_str(this.preferredSymmetricAlgorithms)); - arr.push(write_sub_packet(sub.preferred_symmetric_algorithms, bytes)); - } - if (this.revocationKeyClass !== null) { - bytes = new Uint8Array([this.revocationKeyClass, this.revocationKeyAlgorithm]); - bytes = _util2.default.concat([bytes, this.revocationKeyFingerprint]); - arr.push(write_sub_packet(sub.revocation_key, bytes)); - } - this.notations.forEach(([name, value]) => { - bytes = [new Uint8Array([0x80, 0, 0, 0])]; - // 2 octets of name length - bytes.push(_util2.default.writeNumber(name.length, 2)); - // 2 octets of value length - bytes.push(_util2.default.writeNumber(value.length, 2)); - bytes.push(_util2.default.str_to_Uint8Array(name + value)); - bytes = _util2.default.concat(bytes); - arr.push(write_sub_packet(sub.notation_data, bytes)); - }); - if (this.preferredHashAlgorithms !== null) { - bytes = _util2.default.str_to_Uint8Array(_util2.default.Uint8Array_to_str(this.preferredHashAlgorithms)); - arr.push(write_sub_packet(sub.preferred_hash_algorithms, bytes)); - } - if (this.preferredCompressionAlgorithms !== null) { - bytes = _util2.default.str_to_Uint8Array(_util2.default.Uint8Array_to_str(this.preferredCompressionAlgorithms)); - arr.push(write_sub_packet(sub.preferred_compression_algorithms, bytes)); - } - if (this.keyServerPreferences !== null) { - bytes = _util2.default.str_to_Uint8Array(_util2.default.Uint8Array_to_str(this.keyServerPreferences)); - arr.push(write_sub_packet(sub.key_server_preferences, bytes)); - } - if (this.preferredKeyServer !== null) { - arr.push(write_sub_packet(sub.preferred_key_server, _util2.default.str_to_Uint8Array(this.preferredKeyServer))); - } - if (this.isPrimaryUserID !== null) { - arr.push(write_sub_packet(sub.primary_user_id, new Uint8Array([this.isPrimaryUserID ? 1 : 0]))); - } - if (this.policyURI !== null) { - arr.push(write_sub_packet(sub.policy_uri, _util2.default.str_to_Uint8Array(this.policyURI))); - } - if (this.keyFlags !== null) { - bytes = _util2.default.str_to_Uint8Array(_util2.default.Uint8Array_to_str(this.keyFlags)); - arr.push(write_sub_packet(sub.key_flags, bytes)); - } - if (this.signersUserId !== null) { - arr.push(write_sub_packet(sub.signers_user_id, _util2.default.str_to_Uint8Array(this.signersUserId))); - } - if (this.reasonForRevocationFlag !== null) { - bytes = _util2.default.str_to_Uint8Array(String.fromCharCode(this.reasonForRevocationFlag) + this.reasonForRevocationString); - arr.push(write_sub_packet(sub.reason_for_revocation, bytes)); - } - if (this.features !== null) { - bytes = _util2.default.str_to_Uint8Array(_util2.default.Uint8Array_to_str(this.features)); - arr.push(write_sub_packet(sub.features, bytes)); - } - if (this.signatureTargetPublicKeyAlgorithm !== null) { - bytes = [new Uint8Array([this.signatureTargetPublicKeyAlgorithm, this.signatureTargetHashAlgorithm])]; - bytes.push(_util2.default.str_to_Uint8Array(this.signatureTargetHash)); - bytes = _util2.default.concat(bytes); - arr.push(write_sub_packet(sub.signature_target, bytes)); - } - if (this.preferredAeadAlgorithms !== null) { - bytes = _util2.default.str_to_Uint8Array(_util2.default.Uint8Array_to_str(this.preferredAeadAlgorithms)); - arr.push(write_sub_packet(sub.preferred_aead_algorithms, bytes)); - } - - const result = _util2.default.concat(arr); - const length = _util2.default.writeNumber(result.length, 2); - - return _util2.default.concat([length, result]); -}; - -/** - * Creates Uint8Array of bytes of Issuer and Embedded Signature subpackets - * @returns {Uint8Array} subpacket data - */ -Signature.prototype.write_unhashed_sub_packets = function () { - const sub = _enums2.default.signatureSubpacket; - const arr = []; - let bytes; - if (!this.issuerKeyId.isNull() && this.issuerKeyVersion !== 5) { - // If the version of [the] key is greater than 4, this subpacket - // MUST NOT be included in the signature. - arr.push(write_sub_packet(sub.issuer, this.issuerKeyId.write())); - } - if (this.embeddedSignature !== null) { - arr.push(write_sub_packet(sub.embedded_signature, this.embeddedSignature.write())); - } - if (this.issuerFingerprint !== null) { - bytes = [new Uint8Array([this.issuerKeyVersion]), this.issuerFingerprint]; - bytes = _util2.default.concat(bytes); - arr.push(write_sub_packet(sub.issuer_fingerprint, bytes)); - } - this.unhashedSubpackets.forEach(data => { - arr.push(_packet2.default.writeSimpleLength(data.length)); - arr.push(data); - }); - - const result = _util2.default.concat(arr); - const length = _util2.default.writeNumber(result.length, 2); - - return _util2.default.concat([length, result]); -}; - -/** - * Creates a string representation of a sub signature packet - * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.1|RFC4880 5.2.3.1} - * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.2|RFC4880 5.2.3.2} - * @param {Integer} type subpacket signature type. - * @param {String} data data to be included - * @returns {String} a string-representation of a sub signature packet - * @private - */ -function write_sub_packet(type, data) { - const arr = []; - arr.push(_packet2.default.writeSimpleLength(data.length + 1)); - arr.push(new Uint8Array([type])); - arr.push(data); - return _util2.default.concat(arr); -} - -// V4 signature sub packets - -Signature.prototype.read_sub_packet = function (bytes, trusted = true) { - let mypos = 0; - - const read_array = (prop, bytes) => { - this[prop] = []; - - for (let i = 0; i < bytes.length; i++) { - this[prop].push(bytes[i]); - } - }; - - // The leftmost bit denotes a "critical" packet - const critical = bytes[mypos] & 0x80; - const type = bytes[mypos] & 0x7F; - - // GPG puts the Issuer and Signature subpackets in the unhashed area. - // Tampering with those invalidates the signature, so we can trust them. - // Ignore all other unhashed subpackets. - if (!trusted && ![_enums2.default.signatureSubpacket.issuer, _enums2.default.signatureSubpacket.issuer_fingerprint, _enums2.default.signatureSubpacket.embedded_signature].includes(type)) { - this.unhashedSubpackets.push(bytes.subarray(mypos, bytes.length)); - return; - } - - mypos++; - - // subpacket type - switch (type) { - case 2: - // Signature Creation Time - this.created = _util2.default.readDate(bytes.subarray(mypos, bytes.length)); - break; - case 3: - { - // Signature Expiration Time in seconds - const seconds = _util2.default.readNumber(bytes.subarray(mypos, bytes.length)); - - this.signatureNeverExpires = seconds === 0; - this.signatureExpirationTime = seconds; - - break; - } - case 4: - // Exportable Certification - this.exportable = bytes[mypos++] === 1; - break; - case 5: - // Trust Signature - this.trustLevel = bytes[mypos++]; - this.trustAmount = bytes[mypos++]; - break; - case 6: - // Regular Expression - this.regularExpression = bytes[mypos]; - break; - case 7: - // Revocable - this.revocable = bytes[mypos++] === 1; - break; - case 9: - { - // Key Expiration Time in seconds - const seconds = _util2.default.readNumber(bytes.subarray(mypos, bytes.length)); - - this.keyExpirationTime = seconds; - this.keyNeverExpires = seconds === 0; - - break; - } - case 11: - // Preferred Symmetric Algorithms - read_array('preferredSymmetricAlgorithms', bytes.subarray(mypos, bytes.length)); - break; - case 12: - // Revocation Key - // (1 octet of class, 1 octet of public-key algorithm ID, 20 - // octets of - // fingerprint) - this.revocationKeyClass = bytes[mypos++]; - this.revocationKeyAlgorithm = bytes[mypos++]; - this.revocationKeyFingerprint = bytes.subarray(mypos, mypos + 20); - break; - - case 16: - // Issuer - this.issuerKeyId.read(bytes.subarray(mypos, bytes.length)); - break; - - case 20: - // Notation Data - // We don't know how to handle anything but a text flagged data. - if (bytes[mypos] === 0x80) { - // We extract key/value tuple from the byte stream. - mypos += 4; - const m = _util2.default.readNumber(bytes.subarray(mypos, mypos + 2)); - mypos += 2; - const n = _util2.default.readNumber(bytes.subarray(mypos, mypos + 2)); - mypos += 2; - - const name = _util2.default.Uint8Array_to_str(bytes.subarray(mypos, mypos + m)); - const value = _util2.default.Uint8Array_to_str(bytes.subarray(mypos + m, mypos + m + n)); - - this.notations.push([name, value]); - - if (critical && _config2.default.known_notations.indexOf(name) === -1) { - throw new Error("Unknown critical notation: " + name); - } - } else { - _util2.default.print_debug("Unsupported notation flag " + bytes[mypos]); - } - break; - case 21: - // Preferred Hash Algorithms - read_array('preferredHashAlgorithms', bytes.subarray(mypos, bytes.length)); - break; - case 22: - // Preferred Compression Algorithms - read_array('preferredCompressionAlgorithms', bytes.subarray(mypos, bytes.length)); - break; - case 23: - // Key Server Preferences - read_array('keyServerPreferences', bytes.subarray(mypos, bytes.length)); - break; - case 24: - // Preferred Key Server - this.preferredKeyServer = _util2.default.Uint8Array_to_str(bytes.subarray(mypos, bytes.length)); - break; - case 25: - // Primary User ID - this.isPrimaryUserID = bytes[mypos++] !== 0; - break; - case 26: - // Policy URI - this.policyURI = _util2.default.Uint8Array_to_str(bytes.subarray(mypos, bytes.length)); - break; - case 27: - // Key Flags - read_array('keyFlags', bytes.subarray(mypos, bytes.length)); - break; - case 28: - // Signer's User ID - this.signersUserId = _util2.default.Uint8Array_to_str(bytes.subarray(mypos, bytes.length)); - break; - case 29: - // Reason for Revocation - this.reasonForRevocationFlag = bytes[mypos++]; - this.reasonForRevocationString = _util2.default.Uint8Array_to_str(bytes.subarray(mypos, bytes.length)); - break; - case 30: - // Features - read_array('features', bytes.subarray(mypos, bytes.length)); - break; - case 31: - { - // Signature Target - // (1 octet public-key algorithm, 1 octet hash algorithm, N octets hash) - this.signatureTargetPublicKeyAlgorithm = bytes[mypos++]; - this.signatureTargetHashAlgorithm = bytes[mypos++]; - - const len = _crypto2.default.getHashByteLength(this.signatureTargetHashAlgorithm); - - this.signatureTargetHash = _util2.default.Uint8Array_to_str(bytes.subarray(mypos, mypos + len)); - break; - } - case 32: - // Embedded Signature - this.embeddedSignature = new Signature(); - this.embeddedSignature.read(bytes.subarray(mypos, bytes.length)); - break; - case 33: - // Issuer Fingerprint - this.issuerKeyVersion = bytes[mypos++]; - this.issuerFingerprint = bytes.subarray(mypos, bytes.length); - if (this.issuerKeyVersion === 5) { - this.issuerKeyId.read(this.issuerFingerprint); - } else { - this.issuerKeyId.read(this.issuerFingerprint.subarray(-8)); - } - break; - case 34: - // Preferred AEAD Algorithms - read_array.call(this, 'preferredAeadAlgorithms', bytes.subarray(mypos, bytes.length)); - break; - default: - { - const err = new Error("Unknown signature subpacket type " + type + " @:" + mypos); - if (critical) { - throw err; - } else { - _util2.default.print_debug(err); - } - } - } -}; - -Signature.prototype.read_sub_packets = function (bytes, trusted = true) { - // Two-octet scalar octet count for following subpacket data. - const subpacket_length = _util2.default.readNumber(bytes.subarray(0, 2)); - - let i = 2; - - // subpacket data set (zero or more subpackets) - while (i < 2 + subpacket_length) { - const len = _packet2.default.readSimpleLength(bytes.subarray(i, bytes.length)); - i += len.offset; - - this.read_sub_packet(bytes.subarray(i, i + len.len), trusted); - - i += len.len; - } - - return i; -}; - -// Produces data to produce signature on -Signature.prototype.toSign = function (type, data) { - const t = _enums2.default.signature; - - switch (type) { - case t.binary: - if (data.text !== null) { - return _util2.default.str_to_Uint8Array(data.getText(true)); - } - return data.getBytes(true); - - case t.text: - { - let text = data.getText(true); - // normalize EOL to \r\n - text = _util2.default.canonicalizeEOL(text); - // encode UTF8 - return _util2.default.encode_utf8(text); - } - case t.standalone: - return new Uint8Array(0); - - case t.cert_generic: - case t.cert_persona: - case t.cert_casual: - case t.cert_positive: - case t.cert_revocation: - { - let packet; - let tag; - - if (data.userId) { - tag = 0xB4; - packet = data.userId; - } else if (data.userAttribute) { - tag = 0xD1; - packet = data.userAttribute; - } else { - throw new Error('Either a userId or userAttribute packet needs to be ' + 'supplied for certification.'); - } - - const bytes = packet.write(); - - return _util2.default.concat([this.toSign(t.key, data), new Uint8Array([tag]), _util2.default.writeNumber(bytes.length, 4), bytes]); - } - case t.subkey_binding: - case t.subkey_revocation: - case t.key_binding: - return _util2.default.concat([this.toSign(t.key, data), this.toSign(t.key, { - key: data.bind - })]); - - case t.key: - if (data.key === undefined) { - throw new Error('Key packet is required for this signature.'); - } - return data.key.writeForHash(this.version); - - case t.key_revocation: - return this.toSign(t.key, data); - case t.timestamp: - return new Uint8Array(0); - case t.third_party: - throw new Error('Not implemented'); - default: - throw new Error('Unknown signature type.'); - } -}; - -Signature.prototype.calculateTrailer = function (data, detached) { - let length = 0; - return _webStreamTools2.default.transform(_webStreamTools2.default.clone(this.signatureData), value => { - length += value.length; - }, () => { - const arr = []; - if (this.version === 5 && (this.signatureType === _enums2.default.signature.binary || this.signatureType === _enums2.default.signature.text)) { - if (detached) { - arr.push(new Uint8Array(6)); - } else { - arr.push(data.writeHeader()); - } - } - arr.push(new Uint8Array([this.version, 0xFF])); - if (this.version === 5) { - arr.push(new Uint8Array(4)); - } - arr.push(_util2.default.writeNumber(length, 4)); - // For v5, this should really be writeNumber(length, 8) rather than the - // hardcoded 4 zero bytes above - return _util2.default.concat(arr); - }); -}; - -Signature.prototype.toHash = function (signatureType, data, detached = false) { - const bytes = this.toSign(signatureType, data); - - return _util2.default.concat([bytes, this.signatureData, this.calculateTrailer(data, detached)]); -}; - -Signature.prototype.hash = async function (signatureType, data, toHash, detached = false, streaming = true) { - const hashAlgorithm = _enums2.default.write(_enums2.default.hash, this.hashAlgorithm); - if (!toHash) toHash = this.toHash(signatureType, data, detached); - if (!streaming && _util2.default.isStream(toHash)) { - return _webStreamTools2.default.fromAsync(async () => this.hash(signatureType, data, (await _webStreamTools2.default.readToEnd(toHash)), detached)); - } - return _crypto2.default.hash.digest(hashAlgorithm, toHash); -}; - -/** - * verifys the signature packet. Note: not signature types are implemented - * @param {module:packet.PublicSubkey|module:packet.PublicKey| - * module:packet.SecretSubkey|module:packet.SecretKey} key the public key to verify the signature - * @param {module:enums.signature} signatureType expected signature type - * @param {String|Object} data data which on the signature applies - * @param {Boolean} detached (optional) whether to verify a detached signature - * @returns {Promise} True if message is verified, else false. - * @async - */ -Signature.prototype.verify = async function (key, signatureType, data, detached = false) { - const publicKeyAlgorithm = _enums2.default.write(_enums2.default.publicKey, this.publicKeyAlgorithm); - const hashAlgorithm = _enums2.default.write(_enums2.default.hash, this.hashAlgorithm); - - if (publicKeyAlgorithm !== _enums2.default.write(_enums2.default.publicKey, key.algorithm)) { - throw new Error('Public key algorithm used to sign signature does not match issuer key algorithm.'); - } - - let toHash; - let hash; - if (this.hashed) { - hash = this.hashed; - } else { - toHash = this.toHash(signatureType, data, detached); - hash = await this.hash(signatureType, data, toHash); - } - hash = await _webStreamTools2.default.readToEnd(hash); - - if (this.signedHashValue[0] !== hash[0] || this.signedHashValue[1] !== hash[1]) { - this.verified = false; - } else { - let mpicount = 0; - // Algorithm-Specific Fields for RSA signatures: - // - multiprecision number (MPI) of RSA signature value m**d mod n. - if (publicKeyAlgorithm > 0 && publicKeyAlgorithm < 4) { - mpicount = 1; - - // Algorithm-Specific Fields for DSA, ECDSA, and EdDSA signatures: - // - MPI of DSA value r. - // - MPI of DSA value s. - } else if (publicKeyAlgorithm === _enums2.default.publicKey.dsa || publicKeyAlgorithm === _enums2.default.publicKey.ecdsa || publicKeyAlgorithm === _enums2.default.publicKey.eddsa) { - mpicount = 2; - } - - // EdDSA signature parameters are encoded in little-endian format - // https://tools.ietf.org/html/rfc8032#section-5.1.2 - const endian = publicKeyAlgorithm === _enums2.default.publicKey.eddsa ? 'le' : 'be'; - const mpi = []; - let i = 0; - this.signature = await _webStreamTools2.default.readToEnd(this.signature); - for (let j = 0; j < mpicount; j++) { - mpi[j] = new _mpi2.default(); - i += mpi[j].read(this.signature.subarray(i, this.signature.length), endian); - } - - this.verified = await _crypto2.default.signature.verify(publicKeyAlgorithm, hashAlgorithm, mpi, key.params, toHash, hash); - } - return this.verified; -}; - -/** - * Verifies signature expiration date - * @param {Date} date (optional) use the given date for verification instead of the current time - * @returns {Boolean} true if expired - */ -Signature.prototype.isExpired = function (date = new Date()) { - const normDate = _util2.default.normalizeDate(date); - if (normDate !== null) { - const expirationTime = this.getExpirationTime(); - return !(this.created <= normDate && normDate <= expirationTime); - } - return false; -}; - -/** - * Returns the expiration time of the signature or Infinity if signature does not expire - * @returns {Date} expiration time - */ -Signature.prototype.getExpirationTime = function () { - return !this.signatureNeverExpires ? new Date(this.created.getTime() + this.signatureExpirationTime * 1000) : Infinity; -}; - -/** - * Fix custom types after cloning - */ -Signature.prototype.postCloneTypeFix = function () { - this.issuerKeyId = _keyid2.default.fromClone(this.issuerKeyId); -}; - -exports.default = Signature; - -},{"../config":79,"../crypto":94,"../enums":113,"../type/keyid.js":148,"../type/mpi.js":149,"../util":152,"./packet":129,"web-stream-tools":75}],137:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _webStreamTools = require('web-stream-tools'); - -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); - -var _config = require('../config'); - -var _config2 = _interopRequireDefault(_config); - -var _crypto = require('../crypto'); - -var _crypto2 = _interopRequireDefault(_crypto); - -var _enums = require('../enums'); - -var _enums2 = _interopRequireDefault(_enums); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const VERSION = 1; // A one-octet version number of the data packet. - -/** - * Implementation of the Symmetrically Encrypted Authenticated Encryption with - * Additional Data (AEAD) Protected Data Packet - * - * {@link https://tools.ietf.org/html/draft-ford-openpgp-format-00#section-2.1}: - * AEAD Protected Data Packet - * @memberof module:packet - * @constructor - */ -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2016 Tankred Hase -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @requires web-stream-tools - * @requires config - * @requires crypto - * @requires enums - * @requires util - */ - -function SymEncryptedAEADProtected() { - this.tag = _enums2.default.packet.symEncryptedAEADProtected; - this.version = VERSION; - this.cipherAlgo = null; - this.aeadAlgorithm = 'eax'; - this.aeadAlgo = null; - this.chunkSizeByte = null; - this.iv = null; - this.encrypted = null; - this.packets = null; -} - -exports.default = SymEncryptedAEADProtected; - -/** - * Parse an encrypted payload of bytes in the order: version, IV, ciphertext (see specification) - * @param {Uint8Array | ReadableStream} bytes - */ - -SymEncryptedAEADProtected.prototype.read = async function (bytes) { - await _webStreamTools2.default.parse(bytes, async reader => { - if ((await reader.readByte()) !== VERSION) { - // The only currently defined value is 1. - throw new Error('Invalid packet version.'); - } - this.cipherAlgo = await reader.readByte(); - this.aeadAlgo = await reader.readByte(); - this.chunkSizeByte = await reader.readByte(); - const mode = _crypto2.default[_enums2.default.read(_enums2.default.aead, this.aeadAlgo)]; - this.iv = await reader.readBytes(mode.ivLength); - this.encrypted = reader.remainder(); - }); -}; - -/** - * Write the encrypted payload of bytes in the order: version, IV, ciphertext (see specification) - * @returns {Uint8Array | ReadableStream} The encrypted payload - */ -SymEncryptedAEADProtected.prototype.write = function () { - return _util2.default.concat([new Uint8Array([this.version, this.cipherAlgo, this.aeadAlgo, this.chunkSizeByte]), this.iv, this.encrypted]); -}; - -/** - * Decrypt the encrypted payload. - * @param {String} sessionKeyAlgorithm The session key's cipher algorithm e.g. 'aes128' - * @param {Uint8Array} key The session key used to encrypt the payload - * @param {Boolean} streaming Whether the top-level function will return a stream - * @returns {Boolean} - * @async - */ -SymEncryptedAEADProtected.prototype.decrypt = async function (sessionKeyAlgorithm, key, streaming) { - await this.packets.read((await this.crypt('decrypt', key, _webStreamTools2.default.clone(this.encrypted), streaming)), streaming); - return true; -}; - -/** - * Encrypt the packet list payload. - * @param {String} sessionKeyAlgorithm The session key's cipher algorithm e.g. 'aes128' - * @param {Uint8Array} key The session key used to encrypt the payload - * @param {Boolean} streaming Whether the top-level function will return a stream - * @async - */ -SymEncryptedAEADProtected.prototype.encrypt = async function (sessionKeyAlgorithm, key, streaming) { - this.cipherAlgo = _enums2.default.write(_enums2.default.symmetric, sessionKeyAlgorithm); - this.aeadAlgo = _enums2.default.write(_enums2.default.aead, this.aeadAlgorithm); - const mode = _crypto2.default[_enums2.default.read(_enums2.default.aead, this.aeadAlgo)]; - this.iv = await _crypto2.default.random.getRandomBytes(mode.ivLength); // generate new random IV - this.chunkSizeByte = _config2.default.aead_chunk_size_byte; - const data = this.packets.write(); - this.encrypted = await this.crypt('encrypt', key, data, streaming); -}; - -/** - * En/decrypt the payload. - * @param {encrypt|decrypt} fn Whether to encrypt or decrypt - * @param {Uint8Array} key The session key used to en/decrypt the payload - * @param {Uint8Array | ReadableStream} data The data to en/decrypt - * @param {Boolean} streaming Whether the top-level function will return a stream - * @returns {Uint8Array | ReadableStream} - * @async - */ -SymEncryptedAEADProtected.prototype.crypt = async function (fn, key, data, streaming) { - const cipher = _enums2.default.read(_enums2.default.symmetric, this.cipherAlgo); - const mode = _crypto2.default[_enums2.default.read(_enums2.default.aead, this.aeadAlgo)]; - const modeInstance = await mode(cipher, key); - const tagLengthIfDecrypting = fn === 'decrypt' ? mode.tagLength : 0; - const chunkSize = 2 ** (this.chunkSizeByte + 6) + tagLengthIfDecrypting; // ((uint64_t)1 << (c + 6)) - const adataBuffer = new ArrayBuffer(21); - const adataArray = new Uint8Array(adataBuffer, 0, 13); - const adataTagArray = new Uint8Array(adataBuffer); - const adataView = new DataView(adataBuffer); - const chunkIndexArray = new Uint8Array(adataBuffer, 5, 8); - adataArray.set([0xC0 | this.tag, this.version, this.cipherAlgo, this.aeadAlgo, this.chunkSizeByte], 0); - let chunkIndex = 0; - let latestPromise = Promise.resolve(); - let cryptedBytes = 0; - let queuedBytes = 0; - const iv = this.iv; - return _webStreamTools2.default.transformPair(data, async (readable, writable) => { - const reader = _webStreamTools2.default.getReader(readable); - const buffer = new TransformStream({}, { - highWaterMark: streaming ? _util2.default.getHardwareConcurrency() * 2 ** (_config2.default.aead_chunk_size_byte + 6) : Infinity, - size: array => array.length - }); - _webStreamTools2.default.pipe(buffer.readable, writable); - const writer = _webStreamTools2.default.getWriter(buffer.writable); - try { - while (true) { - let chunk = (await reader.readBytes(chunkSize + tagLengthIfDecrypting)) || new Uint8Array(); - const finalChunk = chunk.subarray(chunk.length - tagLengthIfDecrypting); - chunk = chunk.subarray(0, chunk.length - tagLengthIfDecrypting); - let cryptedPromise; - let done; - if (!chunkIndex || chunk.length) { - reader.unshift(finalChunk); - cryptedPromise = modeInstance[fn](chunk, mode.getNonce(iv, chunkIndexArray), adataArray); - } else { - // After the last chunk, we either encrypt a final, empty - // data chunk to get the final authentication tag or - // validate that final authentication tag. - adataView.setInt32(13 + 4, cryptedBytes); // Should be setInt64(13, ...) - cryptedPromise = modeInstance[fn](finalChunk, mode.getNonce(iv, chunkIndexArray), adataTagArray); - done = true; - } - cryptedBytes += chunk.length - tagLengthIfDecrypting; - queuedBytes += chunk.length - tagLengthIfDecrypting; - // eslint-disable-next-line no-loop-func - latestPromise = latestPromise.then(() => cryptedPromise).then(async crypted => { - await writer.ready; - await writer.write(crypted); - queuedBytes -= chunk.length; - }).catch(err => writer.abort(err)); - if (done || queuedBytes > writer.desiredSize) { - await latestPromise; // Respect backpressure - } - if (!done) { - adataView.setInt32(5 + 4, ++chunkIndex); // Should be setInt64(5, ...) - } else { - await writer.close(); - break; - } - } - } catch (e) { - await writer.abort(e); - } - }); -}; - -},{"../config":79,"../crypto":94,"../enums":113,"../util":152,"web-stream-tools":75}],138:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _webStreamTools = require('web-stream-tools'); - -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); - -var _config = require('../config'); - -var _config2 = _interopRequireDefault(_config); - -var _crypto = require('../crypto'); - -var _crypto2 = _interopRequireDefault(_crypto); - -var _enums = require('../enums'); - -var _enums2 = _interopRequireDefault(_enums); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const VERSION = 1; // A one-octet version number of the data packet. - -/** - * Implementation of the Sym. Encrypted Integrity Protected Data Packet (Tag 18) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.13|RFC4880 5.13}: - * The Symmetrically Encrypted Integrity Protected Data packet is - * a variant of the Symmetrically Encrypted Data packet. It is a new feature - * created for OpenPGP that addresses the problem of detecting a modification to - * encrypted data. It is used in combination with a Modification Detection Code - * packet. - * @memberof module:packet - * @constructor - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @requires asmcrypto.js - * @requires web-stream-tools - * @requires config - * @requires crypto - * @requires enums - * @requires util - */ - -function SymEncryptedIntegrityProtected() { - this.tag = _enums2.default.packet.symEncryptedIntegrityProtected; - this.version = VERSION; - /** The encrypted payload. */ - this.encrypted = null; // string - /** - * If after decrypting the packet this is set to true, - * a modification has been detected and thus the contents - * should be discarded. - * @type {Boolean} - */ - this.modification = false; - this.packets = null; -} - -SymEncryptedIntegrityProtected.prototype.read = async function (bytes) { - await _webStreamTools2.default.parse(bytes, async reader => { - - // - A one-octet version number. The only currently defined value is 1. - if ((await reader.readByte()) !== VERSION) { - throw new Error('Invalid packet version.'); - } - - // - Encrypted data, the output of the selected symmetric-key cipher - // operating in Cipher Feedback mode with shift amount equal to the - // block size of the cipher (CFB-n where n is the block size). - this.encrypted = reader.remainder(); - }); -}; - -SymEncryptedIntegrityProtected.prototype.write = function () { - return _util2.default.concat([new Uint8Array([VERSION]), this.encrypted]); -}; - -/** - * Encrypt the payload in the packet. - * @param {String} sessionKeyAlgorithm The selected symmetric encryption algorithm to be used e.g. 'aes128' - * @param {Uint8Array} key The key of cipher blocksize length to be used - * @param {Boolean} streaming Whether to set this.encrypted to a stream - * @returns {Promise} - * @async - */ -SymEncryptedIntegrityProtected.prototype.encrypt = async function (sessionKeyAlgorithm, key, streaming) { - let bytes = this.packets.write(); - if (!streaming) bytes = await _webStreamTools2.default.readToEnd(bytes); - const prefix = await _crypto2.default.getPrefixRandom(sessionKeyAlgorithm); - const mdc = new Uint8Array([0xD3, 0x14]); // modification detection code packet - - const tohash = _util2.default.concat([prefix, bytes, mdc]); - const hash = await _crypto2.default.hash.sha1(_webStreamTools2.default.passiveClone(tohash)); - const plaintext = _util2.default.concat([tohash, hash]); - - this.encrypted = await _crypto2.default.cfb.encrypt(sessionKeyAlgorithm, key, plaintext, new Uint8Array(_crypto2.default.cipher[sessionKeyAlgorithm].blockSize)); - return true; -}; - -/** - * Decrypts the encrypted data contained in the packet. - * @param {String} sessionKeyAlgorithm The selected symmetric encryption algorithm to be used e.g. 'aes128' - * @param {Uint8Array} key The key of cipher blocksize length to be used - * @param {Boolean} streaming Whether to read this.encrypted as a stream - * @returns {Promise} - * @async - */ -SymEncryptedIntegrityProtected.prototype.decrypt = async function (sessionKeyAlgorithm, key, streaming) { - let encrypted = _webStreamTools2.default.clone(this.encrypted); - if (!streaming) encrypted = await _webStreamTools2.default.readToEnd(encrypted); - const decrypted = await _crypto2.default.cfb.decrypt(sessionKeyAlgorithm, key, encrypted, new Uint8Array(_crypto2.default.cipher[sessionKeyAlgorithm].blockSize)); - - // there must be a modification detection code packet as the - // last packet and everything gets hashed except the hash itself - const realHash = _webStreamTools2.default.slice(_webStreamTools2.default.passiveClone(decrypted), -20); - const tohash = _webStreamTools2.default.slice(decrypted, 0, -20); - const verifyHash = Promise.all([_webStreamTools2.default.readToEnd((await _crypto2.default.hash.sha1(_webStreamTools2.default.passiveClone(tohash)))), _webStreamTools2.default.readToEnd(realHash)]).then(([hash, mdc]) => { - if (!_util2.default.equalsUint8Array(hash, mdc)) { - throw new Error('Modification detected.'); - } - return new Uint8Array(); - }); - const bytes = _webStreamTools2.default.slice(tohash, _crypto2.default.cipher[sessionKeyAlgorithm].blockSize + 2); // Remove random prefix - let packetbytes = _webStreamTools2.default.slice(bytes, 0, -2); // Remove MDC packet - packetbytes = _webStreamTools2.default.concat([packetbytes, _webStreamTools2.default.fromAsync(() => verifyHash)]); - if (!_util2.default.isStream(encrypted) || !_config2.default.allow_unauthenticated_stream) { - packetbytes = await _webStreamTools2.default.readToEnd(packetbytes); - } - await this.packets.read(packetbytes, streaming); - return true; -}; - -exports.default = SymEncryptedIntegrityProtected; - -},{"../config":79,"../crypto":94,"../enums":113,"../util":152,"web-stream-tools":75}],139:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _s2k = require('../type/s2k'); - -var _s2k2 = _interopRequireDefault(_s2k); - -var _config = require('../config'); - -var _config2 = _interopRequireDefault(_config); - -var _crypto = require('../crypto'); - -var _crypto2 = _interopRequireDefault(_crypto); - -var _enums = require('../enums'); - -var _enums2 = _interopRequireDefault(_enums); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Public-Key Encrypted Session Key Packets (Tag 1) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.1|RFC4880 5.1}: - * A Public-Key Encrypted Session Key packet holds the session key - * used to encrypt a message. Zero or more Public-Key Encrypted Session Key - * packets and/or Symmetric-Key Encrypted Session Key packets may precede a - * Symmetrically Encrypted Data Packet, which holds an encrypted message. The - * message is encrypted with the session key, and the session key is itself - * encrypted and stored in the Encrypted Session Key packet(s). The - * Symmetrically Encrypted Data Packet is preceded by one Public-Key Encrypted - * Session Key packet for each OpenPGP key to which the message is encrypted. - * The recipient of the message finds a session key that is encrypted to their - * public key, decrypts the session key, and then uses the session key to - * decrypt the message. - * @memberof module:packet - * @constructor - */ -function SymEncryptedSessionKey() { - this.tag = _enums2.default.packet.symEncryptedSessionKey; - this.version = _config2.default.aead_protect ? 5 : 4; - this.sessionKey = null; - this.sessionKeyEncryptionAlgorithm = null; - this.sessionKeyAlgorithm = 'aes256'; - this.aeadAlgorithm = _enums2.default.read(_enums2.default.aead, _config2.default.aead_mode); - this.encrypted = null; - this.s2k = null; - this.iv = null; -} - -/** - * Parsing function for a symmetric encrypted session key packet (tag 3). - * - * @param {Uint8Array} input Payload of a tag 1 packet - * @param {Integer} position Position to start reading from the input string - * @param {Integer} len - * Length of the packet or the remaining length of - * input at position - * @returns {module:packet.SymEncryptedSessionKey} Object representation - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @requires type/s2k - * @requires config - * @requires crypto - * @requires enums - * @requires util - */ - -SymEncryptedSessionKey.prototype.read = function (bytes) { - let offset = 0; - - // A one-octet version number. The only currently defined version is 4. - this.version = bytes[offset++]; - - // A one-octet number describing the symmetric algorithm used. - const algo = _enums2.default.read(_enums2.default.symmetric, bytes[offset++]); - - if (this.version === 5) { - // A one-octet AEAD algorithm. - this.aeadAlgorithm = _enums2.default.read(_enums2.default.aead, bytes[offset++]); - } - - // A string-to-key (S2K) specifier, length as defined above. - this.s2k = new _s2k2.default(); - offset += this.s2k.read(bytes.subarray(offset, bytes.length)); - - if (this.version === 5) { - const mode = _crypto2.default[this.aeadAlgorithm]; - - // A starting initialization vector of size specified by the AEAD - // algorithm. - this.iv = bytes.subarray(offset, offset += mode.ivLength); - } - - // The encrypted session key itself, which is decrypted with the - // string-to-key object. This is optional in version 4. - if (this.version === 5 || offset < bytes.length) { - this.encrypted = bytes.subarray(offset, bytes.length); - this.sessionKeyEncryptionAlgorithm = algo; - } else { - this.sessionKeyAlgorithm = algo; - } -}; - -SymEncryptedSessionKey.prototype.write = function () { - const algo = this.encrypted === null ? this.sessionKeyAlgorithm : this.sessionKeyEncryptionAlgorithm; - - let bytes; - - if (this.version === 5) { - bytes = _util2.default.concatUint8Array([new Uint8Array([this.version, _enums2.default.write(_enums2.default.symmetric, algo), _enums2.default.write(_enums2.default.aead, this.aeadAlgorithm)]), this.s2k.write(), this.iv, this.encrypted]); - } else { - bytes = _util2.default.concatUint8Array([new Uint8Array([this.version, _enums2.default.write(_enums2.default.symmetric, algo)]), this.s2k.write()]); - - if (this.encrypted !== null) { - bytes = _util2.default.concatUint8Array([bytes, this.encrypted]); - } - } - - return bytes; -}; - -/** - * Decrypts the session key - * @param {String} passphrase The passphrase in string form - * @returns {Promise} - * @async - */ -SymEncryptedSessionKey.prototype.decrypt = async function (passphrase) { - const algo = this.sessionKeyEncryptionAlgorithm !== null ? this.sessionKeyEncryptionAlgorithm : this.sessionKeyAlgorithm; - - const length = _crypto2.default.cipher[algo].keySize; - const key = await this.s2k.produce_key(passphrase, length); - - if (this.version === 5) { - const mode = _crypto2.default[this.aeadAlgorithm]; - const adata = new Uint8Array([0xC0 | this.tag, this.version, _enums2.default.write(_enums2.default.symmetric, this.sessionKeyEncryptionAlgorithm), _enums2.default.write(_enums2.default.aead, this.aeadAlgorithm)]); - const modeInstance = await mode(algo, key); - this.sessionKey = await modeInstance.decrypt(this.encrypted, this.iv, adata); - } else if (this.encrypted !== null) { - const decrypted = await _crypto2.default.cfb.decrypt(algo, key, this.encrypted, new Uint8Array(_crypto2.default.cipher[algo].blockSize)); - - this.sessionKeyAlgorithm = _enums2.default.read(_enums2.default.symmetric, decrypted[0]); - this.sessionKey = decrypted.subarray(1, decrypted.length); - } else { - this.sessionKey = key; - } - - return true; -}; - -/** - * Encrypts the session key - * @param {String} passphrase The passphrase in string form - * @returns {Promise} - * @async - */ -SymEncryptedSessionKey.prototype.encrypt = async function (passphrase) { - const algo = this.sessionKeyEncryptionAlgorithm !== null ? this.sessionKeyEncryptionAlgorithm : this.sessionKeyAlgorithm; - - this.sessionKeyEncryptionAlgorithm = algo; - - this.s2k = new _s2k2.default(); - this.s2k.salt = await _crypto2.default.random.getRandomBytes(8); - - const length = _crypto2.default.cipher[algo].keySize; - const key = await this.s2k.produce_key(passphrase, length); - - if (this.sessionKey === null) { - this.sessionKey = await _crypto2.default.generateSessionKey(this.sessionKeyAlgorithm); - } - - if (this.version === 5) { - const mode = _crypto2.default[this.aeadAlgorithm]; - this.iv = await _crypto2.default.random.getRandomBytes(mode.ivLength); // generate new random IV - const adata = new Uint8Array([0xC0 | this.tag, this.version, _enums2.default.write(_enums2.default.symmetric, this.sessionKeyEncryptionAlgorithm), _enums2.default.write(_enums2.default.aead, this.aeadAlgorithm)]); - const modeInstance = await mode(algo, key); - this.encrypted = await modeInstance.encrypt(this.sessionKey, this.iv, adata); - } else { - const algo_enum = new Uint8Array([_enums2.default.write(_enums2.default.symmetric, this.sessionKeyAlgorithm)]); - const private_key = _util2.default.concatUint8Array([algo_enum, this.sessionKey]); - this.encrypted = await _crypto2.default.cfb.encrypt(algo, key, private_key, new Uint8Array(_crypto2.default.cipher[algo].blockSize)); - } - - return true; -}; - -/** - * Fix custom types after cloning - */ -SymEncryptedSessionKey.prototype.postCloneTypeFix = function () { - this.s2k = _s2k2.default.fromClone(this.s2k); -}; - -exports.default = SymEncryptedSessionKey; - -},{"../config":79,"../crypto":94,"../enums":113,"../type/s2k":151,"../util":152}],140:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _webStreamTools = require('web-stream-tools'); - -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); - -var _config = require('../config'); - -var _config2 = _interopRequireDefault(_config); - -var _crypto = require('../crypto'); - -var _crypto2 = _interopRequireDefault(_crypto); - -var _enums = require('../enums'); - -var _enums2 = _interopRequireDefault(_enums); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Implementation of the Symmetrically Encrypted Data Packet (Tag 9) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.7|RFC4880 5.7}: - * The Symmetrically Encrypted Data packet contains data encrypted with a - * symmetric-key algorithm. When it has been decrypted, it contains other - * packets (usually a literal data packet or compressed data packet, but in - * theory other Symmetrically Encrypted Data packets or sequences of packets - * that form whole OpenPGP messages). - * @memberof module:packet - * @constructor - */ -function SymmetricallyEncrypted() { - /** - * Packet type - * @type {module:enums.packet} - */ - this.tag = _enums2.default.packet.symmetricallyEncrypted; - /** - * Encrypted secret-key data - */ - this.encrypted = null; - /** - * Decrypted packets contained within. - * @type {module:packet.List} - */ - this.packets = null; - /** - * When true, decrypt fails if message is not integrity protected - * @see module:config.ignore_mdc_error - */ - this.ignore_mdc_error = _config2.default.ignore_mdc_error; -} // GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @requires web-stream-tools - * @requires config - * @requires crypto - * @requires enums - * @requires util - */ - -SymmetricallyEncrypted.prototype.read = function (bytes) { - this.encrypted = bytes; -}; - -SymmetricallyEncrypted.prototype.write = function () { - return this.encrypted; -}; - -/** - * Decrypt the symmetrically-encrypted packet data - * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. - * @param {module:enums.symmetric} sessionKeyAlgorithm Symmetric key algorithm to use - * @param {Uint8Array} key The key of cipher blocksize length to be used - * @returns {Promise} - * @async - */ -SymmetricallyEncrypted.prototype.decrypt = async function (sessionKeyAlgorithm, key) { - // If MDC errors are not being ignored, all missing MDC packets in symmetrically encrypted data should throw an error - if (!this.ignore_mdc_error) { - throw new Error('Decryption failed due to missing MDC.'); - } - - this.encrypted = await _webStreamTools2.default.readToEnd(this.encrypted); - const decrypted = await _crypto2.default.cfb.decrypt(sessionKeyAlgorithm, key, this.encrypted.subarray(_crypto2.default.cipher[sessionKeyAlgorithm].blockSize + 2), this.encrypted.subarray(2, _crypto2.default.cipher[sessionKeyAlgorithm].blockSize + 2)); - - await this.packets.read(decrypted); - - return true; -}; - -/** - * Encrypt the symmetrically-encrypted packet data - * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. - * @param {module:enums.symmetric} sessionKeyAlgorithm Symmetric key algorithm to use - * @param {Uint8Array} key The key of cipher blocksize length to be used - * @returns {Promise} - * @async - */ -SymmetricallyEncrypted.prototype.encrypt = async function (algo, key) { - const data = this.packets.write(); - - const prefix = await _crypto2.default.getPrefixRandom(algo); - const FRE = await _crypto2.default.cfb.encrypt(algo, key, prefix, new Uint8Array(_crypto2.default.cipher[algo].blockSize)); - const ciphertext = await _crypto2.default.cfb.encrypt(algo, key, data, FRE.subarray(2)); - this.encrypted = _util2.default.concat([FRE, ciphertext]); - - return true; -}; - -exports.default = SymmetricallyEncrypted; - -},{"../config":79,"../crypto":94,"../enums":113,"../util":152,"web-stream-tools":75}],141:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _enums = require('../enums'); - -var _enums2 = _interopRequireDefault(_enums); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Implementation of the Trust Packet (Tag 12) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.10|RFC4880 5.10}: - * The Trust packet is used only within keyrings and is not normally - * exported. Trust packets contain data that record the user's - * specifications of which key holders are trustworthy introducers, - * along with other information that implementing software uses for - * trust information. The format of Trust packets is defined by a given - * implementation. - * - * Trust packets SHOULD NOT be emitted to output streams that are - * transferred to other users, and they SHOULD be ignored on any input - * other than local keyring files. - * @memberof module:packet - * @constructor - */ -function Trust() { - this.tag = _enums2.default.packet.trust; -} - -/** - * Parsing function for a trust packet (tag 12). - * Currently not implemented as we ignore trust packets - * @param {String} byptes payload of a tag 12 packet - */ -/** - * @requires enums - */ - -Trust.prototype.read = function () {}; // TODO - -exports.default = Trust; - -},{"../enums":113}],142:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _packet = require('./packet'); - -var _packet2 = _interopRequireDefault(_packet); - -var _enums = require('../enums'); - -var _enums2 = _interopRequireDefault(_enums); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Implementation of the User Attribute Packet (Tag 17) - * - * The User Attribute packet is a variation of the User ID packet. It - * is capable of storing more types of data than the User ID packet, - * which is limited to text. Like the User ID packet, a User Attribute - * packet may be certified by the key owner ("self-signed") or any other - * key owner who cares to certify it. Except as noted, a User Attribute - * packet may be used anywhere that a User ID packet may be used. - * - * While User Attribute packets are not a required part of the OpenPGP - * standard, implementations SHOULD provide at least enough - * compatibility to properly handle a certification signature on the - * User Attribute packet. A simple way to do this is by treating the - * User Attribute packet as a User ID packet with opaque contents, but - * an implementation may use any method desired. - * @memberof module:packet - * @constructor - */ -function UserAttribute() { - this.tag = _enums2.default.packet.userAttribute; - this.attributes = []; -} - -/** - * parsing function for a user attribute packet (tag 17). - * @param {Uint8Array} input payload of a tag 17 packet - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @requires packet - * @requires enums - * @requires util - */ - -UserAttribute.prototype.read = function (bytes) { - let i = 0; - while (i < bytes.length) { - const len = _packet2.default.readSimpleLength(bytes.subarray(i, bytes.length)); - i += len.offset; - - this.attributes.push(_util2.default.Uint8Array_to_str(bytes.subarray(i, i + len.len))); - i += len.len; - } -}; - -/** - * Creates a binary representation of the user attribute packet - * @returns {Uint8Array} string representation - */ -UserAttribute.prototype.write = function () { - const arr = []; - for (let i = 0; i < this.attributes.length; i++) { - arr.push(_packet2.default.writeSimpleLength(this.attributes[i].length)); - arr.push(_util2.default.str_to_Uint8Array(this.attributes[i])); - } - return _util2.default.concatUint8Array(arr); -}; - -/** - * Compare for equality - * @param {module:packet.UserAttribute} usrAttr - * @returns {Boolean} true if equal - */ -UserAttribute.prototype.equals = function (usrAttr) { - if (!usrAttr || !(usrAttr instanceof UserAttribute)) { - return false; - } - return this.attributes.every(function (attr, index) { - return attr === usrAttr.attributes[index]; - }); -}; - -exports.default = UserAttribute; - -},{"../enums":113,"../util":152,"./packet":129}],143:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _enums = require('../enums'); - -var _enums2 = _interopRequireDefault(_enums); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Implementation of the User ID Packet (Tag 13) - * - * A User ID packet consists of UTF-8 text that is intended to represent - * the name and email address of the key holder. By convention, it - * includes an RFC 2822 [RFC2822] mail name-addr, but there are no - * restrictions on its content. The packet length in the header - * specifies the length of the User ID. - * @memberof module:packet - * @constructor - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @requires enums - * @requires util - */ - -function Userid() { - this.tag = _enums2.default.packet.userid; - /** A string containing the user id. Usually in the form - * John Doe - * @type {String} - */ - this.userid = ''; - - this.name = ''; - this.email = ''; - this.comment = ''; -} - -/** - * Parsing function for a user id packet (tag 13). - * @param {Uint8Array} input payload of a tag 13 packet - */ -Userid.prototype.read = function (bytes) { - this.parse(_util2.default.decode_utf8(bytes)); -}; - -/** - * Parse userid string, e.g. 'John Doe ' - */ -Userid.prototype.parse = function (userid) { - try { - Object.assign(this, _util2.default.parseUserId(userid)); - } catch (e) {} - this.userid = userid; -}; - -/** - * Creates a binary representation of the user id packet - * @returns {Uint8Array} binary representation - */ -Userid.prototype.write = function () { - return _util2.default.encode_utf8(this.userid); -}; - -/** - * Set userid string from object, e.g. { name:'Phil Zimmermann', email:'phil@openpgp.org' } - */ -Userid.prototype.format = function (userid) { - if (_util2.default.isString(userid)) { - userid = _util2.default.parseUserId(userid); - } - Object.assign(this, userid); - this.userid = _util2.default.formatUserId(userid); -}; - -exports.default = Userid; - -},{"../enums":113,"../util":152}],144:[function(require,module,exports){ -(function (global){ -'use strict'; - -var _util = require('./util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -if (typeof window !== 'undefined') { - /******************************************************************** - * NOTE: This list is duplicated in Gruntfile.js, * - * so that these polyfills are only included in the compat bundle. * - ********************************************************************/ - - try { - if (typeof window.fetch === 'undefined') { - require('whatwg-fetch'); - } - if (typeof Array.prototype.fill === 'undefined') { - require('core-js/fn/array/fill'); - } - if (typeof Array.prototype.find === 'undefined') { - require('core-js/fn/array/find'); - } - if (typeof Array.prototype.includes === 'undefined') { - require('core-js/fn/array/includes'); - } - if (typeof Array.from === 'undefined') { - require('core-js/fn/array/from'); - } - - // No if-statement on Promise because of IE11. Otherwise Promise is undefined in the service worker. - require('core-js/fn/promise'); - - if (typeof Uint8Array.from === 'undefined') { - require('core-js/fn/typed/uint8-array'); - } - if (typeof String.prototype.repeat === 'undefined') { - require('core-js/fn/string/repeat'); - } - if (typeof Symbol === 'undefined') { - require('core-js/fn/symbol'); - } - if (typeof Object.assign === 'undefined') { - require('core-js/fn/object/assign'); - } - } catch (e) {} -} /** - * @fileoverview Old browser polyfills - * All are listed as dev dependencies because Node does not need them - * and for browser babel will take care of it - * @requires util - * @module polyfills - */ - -if (typeof TransformStream === 'undefined') { - require('@mattiasbuelens/web-streams-polyfill/es6'); -} -if (typeof TextEncoder === 'undefined') { - const nodeUtil = _util2.default.nodeRequire('util') || {}; - global.TextEncoder = nodeUtil.TextEncoder; - global.TextDecoder = nodeUtil.TextDecoder; -} -if (typeof TextEncoder === 'undefined') { - const textEncoding = require('text-encoding-utf-8'); - global.TextEncoder = textEncoding.TextEncoder; - global.TextDecoder = textEncoding.TextDecoder; -} - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./util":152,"@mattiasbuelens/web-streams-polyfill/es6":1,"core-js/fn/array/fill":"core-js/fn/array/fill","core-js/fn/array/find":"core-js/fn/array/find","core-js/fn/array/from":"core-js/fn/array/from","core-js/fn/array/includes":"core-js/fn/array/includes","core-js/fn/object/assign":"core-js/fn/object/assign","core-js/fn/promise":"core-js/fn/promise","core-js/fn/string/repeat":"core-js/fn/string/repeat","core-js/fn/symbol":"core-js/fn/symbol","core-js/fn/typed/uint8-array":"core-js/fn/typed/uint8-array","text-encoding-utf-8":71,"whatwg-fetch":"whatwg-fetch"}],145:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.Signature = Signature; -exports.readArmored = readArmored; -exports.read = read; - -var _armor = require('./encoding/armor'); - -var _armor2 = _interopRequireDefault(_armor); - -var _packet = require('./packet'); - -var _packet2 = _interopRequireDefault(_packet); - -var _enums = require('./enums'); - -var _enums2 = _interopRequireDefault(_enums); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * @class - * @classdesc Class that represents an OpenPGP signature. - * @param {module:packet.List} packetlist The signature packets - */ -function Signature(packetlist) { - if (!(this instanceof Signature)) { - return new Signature(packetlist); - } - this.packets = packetlist || new _packet2.default.List(); -} - -/** - * Returns ASCII armored text of signature - * @returns {ReadableStream} ASCII armor - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @requires encoding/armor - * @requires packet - * @requires enums - * @module signature - */ - -Signature.prototype.armor = function () { - return _armor2.default.encode(_enums2.default.armor.signature, this.packets.write()); -}; - -/** - * reads an OpenPGP armored signature and returns a signature object - * @param {String | ReadableStream} armoredText text to be parsed - * @returns {Signature} new signature object - * @async - * @static - */ -async function readArmored(armoredText) { - const input = await _armor2.default.decode(armoredText); - return read(input.data); -} - -/** - * reads an OpenPGP signature as byte array and returns a signature object - * @param {Uint8Array | ReadableStream} input binary signature - * @returns {Signature} new signature object - * @async - * @static - */ -async function read(input) { - const packetlist = new _packet2.default.List(); - await packetlist.read(input); - return new Signature(packetlist); -} - -},{"./encoding/armor":111,"./enums":113,"./packet":125}],146:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * @constructor - */ -function ECDHSymmetricKey(data) { - if (typeof data === 'undefined') { - data = new Uint8Array([]); - } else if (_util2.default.isString(data)) { - data = _util2.default.str_to_Uint8Array(data); - } else { - data = new Uint8Array(data); - } - this.data = data; -} - -/** - * Read an ECDHSymmetricKey from an Uint8Array - * @param {Uint8Array} input Where to read the encoded symmetric key from - * @returns {Number} Number of read bytes - */ -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2015-2016 Decentral -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * Encoded symmetric key for ECDH - * - * @requires util - * @module type/ecdh_symkey - */ - -ECDHSymmetricKey.prototype.read = function (input) { - if (input.length >= 1) { - const length = input[0]; - if (input.length >= 1 + length) { - this.data = input.subarray(1, 1 + length); - return 1 + this.data.length; - } - } - throw new Error('Invalid symmetric key'); -}; - -/** - * Write an ECDHSymmetricKey as an Uint8Array - * @returns {Uint8Array} An array containing the value - */ -ECDHSymmetricKey.prototype.write = function () { - return _util2.default.concatUint8Array([new Uint8Array([this.data.length]), this.data]); -}; - -ECDHSymmetricKey.fromClone = function (clone) { - return new ECDHSymmetricKey(clone.data); -}; - -exports.default = ECDHSymmetricKey; - -},{"../util":152}],147:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _enums = require('../enums.js'); - -var _enums2 = _interopRequireDefault(_enums); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * @constructor - * @param {enums.hash} hash Hash algorithm - * @param {enums.symmetric} cipher Symmetric algorithm - */ -function KDFParams(data) { - if (data && data.length === 2) { - this.hash = data[0]; - this.cipher = data[1]; - } else { - this.hash = _enums2.default.hash.sha1; - this.cipher = _enums2.default.symmetric.aes128; - } -} - -/** - * Read KDFParams from an Uint8Array - * @param {Uint8Array} input Where to read the KDFParams from - * @returns {Number} Number of read bytes - */ -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2015-2016 Decentral -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * Implementation of type KDF parameters - * - * {@link https://tools.ietf.org/html/rfc6637#section-7|RFC 6637 7}: - * A key derivation function (KDF) is necessary to implement the EC - * encryption. The Concatenation Key Derivation Function (Approved - * Alternative 1) [NIST-SP800-56A] with the KDF hash function that is - * SHA2-256 [FIPS-180-3] or stronger is REQUIRED. - * @requires enums - * @module type/kdf_params - */ - -KDFParams.prototype.read = function (input) { - if (input.length < 4 || input[0] !== 3 || input[1] !== 1) { - throw new Error('Cannot read KDFParams'); - } - this.hash = input[2]; - this.cipher = input[3]; - return 4; -}; - -/** - * Write KDFParams to an Uint8Array - * @returns {Uint8Array} Array with the KDFParams value - */ -KDFParams.prototype.write = function () { - return new Uint8Array([3, 1, this.hash, this.cipher]); -}; - -KDFParams.fromClone = function (clone) { - return new KDFParams([clone.hash, clone.cipher]); -}; - -exports.default = KDFParams; - -},{"../enums.js":113}],148:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _util = require('../util.js'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * @constructor - */ -function Keyid() { - this.bytes = ''; -} - -/** - * Parsing method for a key id - * @param {Uint8Array} input Input to read the key id from - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * Implementation of type key id - * - * {@link https://tools.ietf.org/html/rfc4880#section-3.3|RFC4880 3.3}: - * A Key ID is an eight-octet scalar that identifies a key. - * Implementations SHOULD NOT assume that Key IDs are unique. The - * section "Enhanced Key Formats" below describes how Key IDs are - * formed. - * @requires util - * @module type/keyid - */ - -Keyid.prototype.read = function (bytes) { - this.bytes = _util2.default.Uint8Array_to_str(bytes.subarray(0, 8)); -}; - -Keyid.prototype.write = function () { - return _util2.default.str_to_Uint8Array(this.bytes); -}; - -Keyid.prototype.toHex = function () { - return _util2.default.str_to_hex(this.bytes); -}; - -/** - * Checks equality of Key ID's - * @param {Keyid} keyid - * @param {Boolean} matchWildcard Indicates whether to check if either keyid is a wildcard - */ -Keyid.prototype.equals = function (keyid, matchWildcard = false) { - return matchWildcard && (keyid.isWildcard() || this.isWildcard()) || this.bytes === keyid.bytes; -}; - -Keyid.prototype.isNull = function () { - return this.bytes === ''; -}; - -Keyid.prototype.isWildcard = function () { - return (/^0+$/.test(this.toHex()) - ); -}; - -Keyid.mapToHex = function (keyId) { - return keyId.toHex(); -}; - -Keyid.fromClone = function (clone) { - const keyid = new Keyid(); - keyid.bytes = clone.bytes; - return keyid; -}; - -Keyid.fromId = function (hex) { - const keyid = new Keyid(); - keyid.read(_util2.default.hex_to_Uint8Array(hex)); - return keyid; -}; - -Keyid.wildcard = function () { - const keyid = new Keyid(); - keyid.read(new Uint8Array(8)); - return keyid; -}; - -exports.default = Keyid; - -},{"../util.js":152}],149:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _bn = require('bn.js'); - -var _bn2 = _interopRequireDefault(_bn); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * @constructor - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -// Hint: We hold our MPIs as an array of octets in big endian format preceding a two -// octet scalar: MPI: [a,b,c,d,e,f] -// - MPI size: (a << 8) | b -// - MPI = c | d << 8 | e << ((MPI.length -2)*8) | f ((MPI.length -2)*8) - -/** - * Implementation of type MPI ({@link https://tools.ietf.org/html/rfc4880#section-3.2|RFC4880 3.2}) - * Multiprecision integers (also called MPIs) are unsigned integers used - * to hold large integers such as the ones used in cryptographic - * calculations. - * An MPI consists of two pieces: a two-octet scalar that is the length - * of the MPI in bits followed by a string of octets that contain the - * actual integer. - * @requires bn.js - * @requires util - * @module type/mpi - */ - -function MPI(data) { - /** An implementation dependent integer */ - if (data instanceof MPI) { - this.data = data.data; - } else if (_bn2.default.isBN(data)) { - this.fromBN(data); - } else if (_util2.default.isUint8Array(data)) { - this.fromUint8Array(data); - } else if (_util2.default.isString(data)) { - this.fromString(data); - } else { - this.data = null; - } -} - -/** - * Parsing function for a MPI ({@link https://tools.ietf.org/html/rfc4880#section-3.2|RFC 4880 3.2}). - * @param {Uint8Array} input Payload of MPI data - * @param {String} endian Endianness of the data; 'be' for big-endian or 'le' for little-endian - * @returns {Integer} Length of data read - */ -MPI.prototype.read = function (bytes, endian = 'be') { - if (_util2.default.isString(bytes)) { - bytes = _util2.default.str_to_Uint8Array(bytes); - } - - const bits = bytes[0] << 8 | bytes[1]; - const bytelen = bits + 7 >>> 3; - const payload = bytes.subarray(2, 2 + bytelen); - - this.fromUint8Array(payload, endian); - - return 2 + bytelen; -}; - -/** - * Converts the mpi object to a bytes as specified in - * {@link https://tools.ietf.org/html/rfc4880#section-3.2|RFC4880 3.2} - * @param {String} endian Endianness of the payload; 'be' for big-endian or 'le' for little-endian - * @param {Integer} length Length of the data part of the MPI - * @returns {Uint8Aray} mpi Byte representation - */ -MPI.prototype.write = function (endian, length) { - return _util2.default.Uint8Array_to_MPI(this.toUint8Array(endian, length)); -}; - -MPI.prototype.bitLength = function () { - return (this.data.length - 1) * 8 + _util2.default.nbits(this.data[0]); -}; - -MPI.prototype.byteLength = function () { - return this.data.length; -}; - -MPI.prototype.toUint8Array = function (endian, length) { - endian = endian || 'be'; - length = length || this.data.length; - - const payload = new Uint8Array(length); - const start = length - this.data.length; - if (start < 0) { - throw new Error('Payload is too large.'); - } - - payload.set(this.data, start); - if (endian === 'le') { - payload.reverse(); - } - - return payload; -}; - -MPI.prototype.fromUint8Array = function (bytes, endian = 'be') { - this.data = new Uint8Array(bytes.length); - this.data.set(bytes); - - if (endian === 'le') { - this.data.reverse(); - } -}; - -MPI.prototype.toString = function () { - return _util2.default.Uint8Array_to_str(this.toUint8Array()); -}; - -MPI.prototype.fromString = function (str, endian = 'be') { - this.fromUint8Array(_util2.default.str_to_Uint8Array(str), endian); -}; - -MPI.prototype.toBN = function () { - return new _bn2.default(this.toUint8Array()); -}; - -MPI.prototype.fromBN = function (bn) { - this.data = bn.toArrayLike(Uint8Array); -}; - -MPI.fromClone = function (clone) { - return new MPI(clone.data); -}; - -exports.default = MPI; - -},{"../util":152,"bn.js":16}],150:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _util = require('../util'); - -var _util2 = _interopRequireDefault(_util); - -var _enums = require('../enums'); - -var _enums2 = _interopRequireDefault(_enums); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * @constructor - */ -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2015-2016 Decentral -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * Wrapper to an OID value - * - * {@link https://tools.ietf.org/html/rfc6637#section-11|RFC6637, section 11}: - * The sequence of octets in the third column is the result of applying - * the Distinguished Encoding Rules (DER) to the ASN.1 Object Identifier - * with subsequent truncation. The truncation removes the two fields of - * encoded Object Identifier. The first omitted field is one octet - * representing the Object Identifier tag, and the second omitted field - * is the length of the Object Identifier body. For example, the - * complete ASN.1 DER encoding for the NIST P-256 curve OID is "06 08 2A - * 86 48 CE 3D 03 01 07", from which the first entry in the table above - * is constructed by omitting the first two octets. Only the truncated - * sequence of octets is the valid representation of a curve OID. - * @requires util - * @requires enums - * @module type/oid - */ - -function OID(oid) { - if (oid instanceof OID) { - this.oid = oid.oid; - } else if (_util2.default.isArray(oid) || _util2.default.isUint8Array(oid)) { - oid = new Uint8Array(oid); - if (oid[0] === 0x06) { - // DER encoded oid byte array - if (oid[1] !== oid.length - 2) { - throw new Error('Length mismatch in DER encoded oid'); - } - oid = oid.subarray(2); - } - this.oid = oid; - } else { - this.oid = ''; - } -} - -/** - * Method to read an OID object - * @param {Uint8Array} input Where to read the OID from - * @returns {Number} Number of read bytes - */ -OID.prototype.read = function (input) { - if (input.length >= 1) { - const length = input[0]; - if (input.length >= 1 + length) { - this.oid = input.subarray(1, 1 + length); - return 1 + this.oid.length; - } - } - throw new Error('Invalid oid'); -}; - -/** - * Serialize an OID object - * @returns {Uint8Array} Array with the serialized value the OID - */ -OID.prototype.write = function () { - return _util2.default.concatUint8Array([new Uint8Array([this.oid.length]), this.oid]); -}; - -/** - * Serialize an OID object as a hex string - * @returns {string} String with the hex value of the OID - */ -OID.prototype.toHex = function () { - return _util2.default.Uint8Array_to_hex(this.oid); -}; - -/** - * If a known curve object identifier, return the canonical name of the curve - * @returns {string} String with the canonical name of the curve - */ -OID.prototype.getName = function () { - const hex = this.toHex(); - if (_enums2.default.curve[hex]) { - return _enums2.default.write(_enums2.default.curve, hex); - } else { - throw new Error('Unknown curve object identifier.'); - } -}; - -OID.fromClone = function (clone) { - return new OID(clone.oid); -}; - -exports.default = OID; - -},{"../enums":113,"../util":152}],151:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _config = require('../config'); - -var _config2 = _interopRequireDefault(_config); - -var _crypto = require('../crypto'); - -var _crypto2 = _interopRequireDefault(_crypto); - -var _enums = require('../enums.js'); - -var _enums2 = _interopRequireDefault(_enums); - -var _util = require('../util.js'); - -var _util2 = _interopRequireDefault(_util); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * @constructor - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * Implementation of the String-to-key specifier - * - * {@link https://tools.ietf.org/html/rfc4880#section-3.7|RFC4880 3.7}: - * String-to-key (S2K) specifiers are used to convert passphrase strings - * into symmetric-key encryption/decryption keys. They are used in two - * places, currently: to encrypt the secret part of private keys in the - * private keyring, and to convert passphrases to encryption keys for - * symmetrically encrypted messages. - * @requires config - * @requires crypto - * @requires enums - * @requires util - * @module type/s2k - */ - -function S2K() { - /** @type {module:enums.hash} */ - this.algorithm = 'sha256'; - /** @type {module:enums.s2k} */ - this.type = 'iterated'; - /** @type {Integer} */ - this.c = _config2.default.s2k_iteration_count_byte; - /** Eight bytes of salt in a binary string. - * @type {String} - */ - this.salt = null; -} - -S2K.prototype.get_count = function () { - // Exponent bias, defined in RFC4880 - const expbias = 6; - - return 16 + (this.c & 15) << (this.c >> 4) + expbias; -}; - -/** - * Parsing function for a string-to-key specifier ({@link https://tools.ietf.org/html/rfc4880#section-3.7|RFC 4880 3.7}). - * @param {String} input Payload of string-to-key specifier - * @returns {Integer} Actual length of the object - */ -S2K.prototype.read = function (bytes) { - let i = 0; - this.type = _enums2.default.read(_enums2.default.s2k, bytes[i++]); - this.algorithm = bytes[i++]; - if (this.type !== 'gnu') { - this.algorithm = _enums2.default.read(_enums2.default.hash, this.algorithm); - } - - switch (this.type) { - case 'simple': - break; - - case 'salted': - this.salt = bytes.subarray(i, i + 8); - i += 8; - break; - - case 'iterated': - this.salt = bytes.subarray(i, i + 8); - i += 8; - - // Octet 10: count, a one-octet, coded value - this.c = bytes[i++]; - break; - - case 'gnu': - if (_util2.default.Uint8Array_to_str(bytes.subarray(i, i + 3)) === "GNU") { - i += 3; // GNU - const gnuExtType = 1000 + bytes[i++]; - if (gnuExtType === 1001) { - this.type = 'gnu-dummy'; - // GnuPG extension mode 1001 -- don't write secret key at all - } else { - throw new Error("Unknown s2k gnu protection mode."); - } - } else { - throw new Error("Unknown s2k type."); - } - break; - - default: - throw new Error("Unknown s2k type."); - } - - return i; -}; - -/** - * Serializes s2k information - * @returns {Uint8Array} binary representation of s2k - */ -S2K.prototype.write = function () { - if (this.type === 'gnu-dummy') { - return new Uint8Array([101, 0, ..._util2.default.str_to_Uint8Array('GNU'), 1]); - } - - const arr = [new Uint8Array([_enums2.default.write(_enums2.default.s2k, this.type), _enums2.default.write(_enums2.default.hash, this.algorithm)])]; - - switch (this.type) { - case 'simple': - break; - case 'salted': - arr.push(this.salt); - break; - case 'iterated': - arr.push(this.salt); - arr.push(new Uint8Array([this.c])); - break; - case 'gnu': - throw new Error("GNU s2k type not supported."); - default: - throw new Error("Unknown s2k type."); - } - - return _util2.default.concatUint8Array(arr); -}; - -/** - * Produces a key using the specified passphrase and the defined - * hashAlgorithm - * @param {String} passphrase Passphrase containing user input - * @returns {Uint8Array} Produced key with a length corresponding to - * hashAlgorithm hash length - */ -S2K.prototype.produce_key = async function (passphrase, numBytes) { - passphrase = _util2.default.encode_utf8(passphrase); - - async function round(prefix, s2k) { - const algorithm = _enums2.default.write(_enums2.default.hash, s2k.algorithm); - - switch (s2k.type) { - case 'simple': - return _crypto2.default.hash.digest(algorithm, _util2.default.concatUint8Array([prefix, passphrase])); - - case 'salted': - return _crypto2.default.hash.digest(algorithm, _util2.default.concatUint8Array([prefix, s2k.salt, passphrase])); - - case 'iterated': - { - const count = s2k.get_count(); - const data = _util2.default.concatUint8Array([s2k.salt, passphrase]); - const datalen = data.length; - const isp = new Uint8Array(prefix.length + count + datalen); - isp.set(prefix); - for (let pos = prefix.length; pos < count; pos += datalen) { - isp.set(data, pos); - } - return _crypto2.default.hash.digest(algorithm, isp.subarray(0, prefix.length + count)); - } - case 'gnu': - throw new Error("GNU s2k type not supported."); - - default: - throw new Error("Unknown s2k type."); - } - } - - const arr = []; - let rlength = 0; - const prefix = new Uint8Array(numBytes); - - for (let i = 0; i < numBytes; i++) { - prefix[i] = 0; - } - - let i = 0; - while (rlength < numBytes) { - const result = await round(prefix.subarray(0, i), this); - arr.push(result); - rlength += result.length; - i++; - } - - return _util2.default.concatUint8Array(arr).subarray(0, numBytes); -}; - -S2K.fromClone = function (clone) { - const s2k = new S2K(); - s2k.algorithm = clone.algorithm; - s2k.type = clone.type; - s2k.c = clone.c; - s2k.salt = clone.salt; - return s2k; -}; - -exports.default = S2K; - -},{"../config":79,"../crypto":94,"../enums.js":113,"../util.js":152}],152:[function(require,module,exports){ -(function (global){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _emailAddresses = require('email-addresses'); - -var _emailAddresses2 = _interopRequireDefault(_emailAddresses); - -var _webStreamTools = require('web-stream-tools'); - -var _webStreamTools2 = _interopRequireDefault(_webStreamTools); - -var _config = require('./config'); - -var _config2 = _interopRequireDefault(_config); - -var _util = require('./util'); - -var _util2 = _interopRequireDefault(_util); - -var _base = require('./encoding/base64'); - -var _base2 = _interopRequireDefault(_base); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -exports.default = { - isString: function isString(data) { - return typeof data === 'string' || String.prototype.isPrototypeOf(data); - }, - - isArray: function isArray(data) { - return Array.prototype.isPrototypeOf(data); - }, - - isUint8Array: _webStreamTools2.default.isUint8Array, - - isStream: _webStreamTools2.default.isStream, - - /** - * Get transferable objects to pass buffers with zero copy (similar to "pass by reference" in C++) - * See: https://developer.mozilla.org/en-US/docs/Web/API/Worker/postMessage - * Also, convert ReadableStreams to MessagePorts - * @param {Object} obj the options object to be passed to the web worker - * @returns {Array} an array of binary data to be passed - */ - getTransferables: function getTransferables(obj, zero_copy) { - const transferables = []; - _util2.default.collectTransferables(obj, transferables, zero_copy); - return transferables.length ? transferables : undefined; - }, - - collectTransferables: function collectTransferables(obj, collection, zero_copy) { - if (!obj) { - return; - } - - if (_util2.default.isUint8Array(obj)) { - if (zero_copy && collection.indexOf(obj.buffer) === -1 && !(navigator.userAgent.indexOf('Version/11.1') !== -1 || // Safari 11.1 - (navigator.userAgent.match(/Chrome\/(\d+)/) || [])[1] < 56 && navigator.userAgent.indexOf('Edge') === -1 // Chrome < 56 - )) { - collection.push(obj.buffer); - } - return; - } - if (Object.prototype.isPrototypeOf(obj)) { - Object.entries(obj).forEach(([key, value]) => { - // recursively search all children - if (_util2.default.isStream(value)) { - if (value.locked) { - obj[key] = null; - } else { - const transformed = _webStreamTools2.default.transformPair(value, async readable => { - const reader = _webStreamTools2.default.getReader(readable); - - var _ref = new MessageChannel(); - - const port1 = _ref.port1, - port2 = _ref.port2; - - port1.onmessage = async function ({ data: { action } }) { - if (action === 'read') { - try { - const result = await reader.read(); - port1.postMessage(result, _util2.default.getTransferables(result)); - } catch (e) { - port1.postMessage({ error: e.message }); - } - } else if (action === 'cancel') { - await transformed.cancel(); - port1.postMessage(); - } - }; - obj[key] = port2; - collection.push(port2); - }); - } - return; - } - if (Object.prototype.toString.call(value) === '[object MessagePort]') { - throw new Error("Can't transfer the same stream twice."); - } - _util2.default.collectTransferables(value, collection, zero_copy); - }); - } - }, - - /** - * Convert MessagePorts back to ReadableStreams - * @param {Object} obj - * @returns {Object} - */ - restoreStreams: function restoreStreams(obj) { - if (Object.prototype.isPrototypeOf(obj) && !Uint8Array.prototype.isPrototypeOf(obj)) { - Object.entries(obj).forEach(([key, value]) => { - // recursively search all children - if (Object.prototype.toString.call(value) === '[object MessagePort]') { - obj[key] = new ReadableStream({ - pull(controller) { - return new Promise(resolve => { - value.onmessage = evt => { - var _evt$data = evt.data; - const done = _evt$data.done, - value = _evt$data.value, - error = _evt$data.error; - - if (error) { - controller.error(new Error(error)); - } else if (!done) { - controller.enqueue(value); - } else { - controller.close(); - } - resolve(); - }; - value.postMessage({ action: 'read' }); - }); - }, - cancel() { - return new Promise(resolve => { - value.onmessage = resolve; - value.postMessage({ action: 'cancel' }); - }); - } - }, { highWaterMark: 0 }); - return; - } - _util2.default.restoreStreams(value); - }); - } - return obj; - }, - - readNumber: function readNumber(bytes) { - let n = 0; - for (let i = 0; i < bytes.length; i++) { - n += 256 ** i * bytes[bytes.length - 1 - i]; - } - return n; - }, - - writeNumber: function writeNumber(n, bytes) { - const b = new Uint8Array(bytes); - for (let i = 0; i < bytes; i++) { - b[i] = n >> 8 * (bytes - i - 1) & 0xFF; - } - - return b; - }, - - readDate: function readDate(bytes) { - const n = _util2.default.readNumber(bytes); - const d = new Date(n * 1000); - return d; - }, - - writeDate: function writeDate(time) { - const numeric = Math.floor(time.getTime() / 1000); - - return _util2.default.writeNumber(numeric, 4); - }, - - normalizeDate: function normalizeDate(time = Date.now()) { - return time === null || time === Infinity ? time : new Date(Math.floor(+time / 1000) * 1000); - }, - - /** - * Create hex string from a binary - * @param {String} str String to convert - * @returns {String} String containing the hexadecimal values - */ - str_to_hex: function str_to_hex(str) { - if (str === null) { - return ""; - } - const r = []; - const e = str.length; - let c = 0; - let h; - while (c < e) { - h = str.charCodeAt(c++).toString(16); - while (h.length < 2) { - h = "0" + h; - } - r.push("" + h); - } - return r.join(''); - }, - - /** - * Create binary string from a hex encoded string - * @param {String} str Hex string to convert - * @returns {String} - */ - hex_to_str: function hex_to_str(hex) { - let str = ''; - for (let i = 0; i < hex.length; i += 2) { - str += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); - } - return str; - }, - - /** - * Convert a Uint8Array to an MPI-formatted Uint8Array. - * Note: the output is **not** an MPI object. - * @see {@link module:type/mpi/MPI.fromUint8Array} - * @see {@link module:type/mpi/MPI.toUint8Array} - * @param {Uint8Array} bin An array of 8-bit integers to convert - * @returns {Uint8Array} MPI-formatted Uint8Array - */ - Uint8Array_to_MPI: function Uint8Array_to_MPI(bin) { - const size = (bin.length - 1) * 8 + _util2.default.nbits(bin[0]); - const prefix = Uint8Array.from([(size & 0xFF00) >> 8, size & 0xFF]); - return _util2.default.concatUint8Array([prefix, bin]); - }, - - /** - * Convert a Base-64 encoded string an array of 8-bit integer - * - * Note: accepts both Radix-64 and URL-safe strings - * @param {String} base64 Base-64 encoded string to convert - * @returns {Uint8Array} An array of 8-bit integers - */ - b64_to_Uint8Array: function b64_to_Uint8Array(base64) { - return _base2.default.decode(base64.replace(/-/g, '+').replace(/_/g, '/')); - }, - - /** - * Convert an array of 8-bit integer to a Base-64 encoded string - * @param {Uint8Array} bytes An array of 8-bit integers to convert - * @param {bool} url If true, output is URL-safe - * @returns {String} Base-64 encoded string - */ - Uint8Array_to_b64: function Uint8Array_to_b64(bytes, url) { - return _base2.default.encode(bytes, url).replace(/(\n)/g, ''); - }, - - /** - * Convert a hex string to an array of 8-bit integers - * @param {String} hex A hex string to convert - * @returns {Uint8Array} An array of 8-bit integers - */ - hex_to_Uint8Array: function hex_to_Uint8Array(hex) { - const result = new Uint8Array(hex.length >> 1); - for (let k = 0; k < hex.length >> 1; k++) { - result[k] = parseInt(hex.substr(k << 1, 2), 16); - } - return result; - }, - - /** - * Convert an array of 8-bit integers to a hex string - * @param {Uint8Array} bytes Array of 8-bit integers to convert - * @returns {String} Hexadecimal representation of the array - */ - Uint8Array_to_hex: function Uint8Array_to_hex(bytes) { - const r = []; - const e = bytes.length; - let c = 0; - let h; - while (c < e) { - h = bytes[c++].toString(16); - while (h.length < 2) { - h = "0" + h; - } - r.push("" + h); - } - return r.join(''); - }, - - /** - * Convert a string to an array of 8-bit integers - * @param {String} str String to convert - * @returns {Uint8Array} An array of 8-bit integers - */ - str_to_Uint8Array: function str_to_Uint8Array(str) { - return _webStreamTools2.default.transform(str, str => { - if (!_util2.default.isString(str)) { - throw new Error('str_to_Uint8Array: Data must be in the form of a string'); - } - - const result = new Uint8Array(str.length); - for (let i = 0; i < str.length; i++) { - result[i] = str.charCodeAt(i); - } - return result; - }); - }, - - /** - * Convert an array of 8-bit integers to a string - * @param {Uint8Array} bytes An array of 8-bit integers to convert - * @returns {String} String representation of the array - */ - Uint8Array_to_str: function Uint8Array_to_str(bytes) { - bytes = new Uint8Array(bytes); - const result = []; - const bs = 1 << 14; - const j = bytes.length; - - for (let i = 0; i < j; i += bs) { - result.push(String.fromCharCode.apply(String, bytes.subarray(i, i + bs < j ? i + bs : j))); - } - return result.join(''); - }, - - /** - * Convert a native javascript string to a Uint8Array of utf8 bytes - * @param {String|ReadableStream} str The string to convert - * @returns {Uint8Array|ReadableStream} A valid squence of utf8 bytes - */ - encode_utf8: function encode_utf8(str) { - const encoder = new TextEncoder('utf-8'); - // eslint-disable-next-line no-inner-declarations - function process(value, lastChunk = false) { - return encoder.encode(value, { stream: !lastChunk }); - } - return _webStreamTools2.default.transform(str, process, () => process('', true)); - }, - - /** - * Convert a Uint8Array of utf8 bytes to a native javascript string - * @param {Uint8Array|ReadableStream} utf8 A valid squence of utf8 bytes - * @returns {String|ReadableStream} A native javascript string - */ - decode_utf8: function decode_utf8(utf8) { - const decoder = new TextDecoder('utf-8'); - // eslint-disable-next-line no-inner-declarations - function process(value, lastChunk = false) { - return decoder.decode(value, { stream: !lastChunk }); - } - return _webStreamTools2.default.transform(utf8, process, () => process(new Uint8Array(), true)); - }, - - /** - * Concat a list of Uint8Arrays, Strings or Streams - * The caller must not mix Uint8Arrays with Strings, but may mix Streams with non-Streams. - * @param {Array} Array of Uint8Arrays/Strings/Streams to concatenate - * @returns {Uint8Array|String|ReadableStream} Concatenated array - */ - concat: _webStreamTools2.default.concat, - - /** - * Concat Uint8Arrays - * @param {Array} Array of Uint8Arrays to concatenate - * @returns {Uint8Array} Concatenated array - */ - concatUint8Array: _webStreamTools2.default.concatUint8Array, - - /** - * Check Uint8Array equality - * @param {Uint8Array} first array - * @param {Uint8Array} second array - * @returns {Boolean} equality - */ - equalsUint8Array: function equalsUint8Array(array1, array2) { - if (!_util2.default.isUint8Array(array1) || !_util2.default.isUint8Array(array2)) { - throw new Error('Data must be in the form of a Uint8Array'); - } - - if (array1.length !== array2.length) { - return false; - } - - for (let i = 0; i < array1.length; i++) { - if (array1[i] !== array2[i]) { - return false; - } - } - return true; - }, - - /** - * Calculates a 16bit sum of a Uint8Array by adding each character - * codes modulus 65535 - * @param {Uint8Array} Uint8Array to create a sum of - * @returns {Uint8Array} 2 bytes containing the sum of all charcodes % 65535 - */ - write_checksum: function write_checksum(text) { - let s = 0; - for (let i = 0; i < text.length; i++) { - s = s + text[i] & 0xFFFF; - } - return _util2.default.writeNumber(s, 2); - }, - - /** - * Helper function to print a debug message. Debug - * messages are only printed if - * @link module:config/config.debug is set to true. - * @param {String} str String of the debug message - */ - print_debug: function print_debug(str) { - if (_config2.default.debug) { - console.log(str); - } - }, - - /** - * Helper function to print a debug message. Debug - * messages are only printed if - * @link module:config/config.debug is set to true. - * Different than print_debug because will call Uint8Array_to_hex iff necessary. - * @param {String} str String of the debug message - */ - print_debug_hexarray_dump: function print_debug_hexarray_dump(str, arrToHex) { - if (_config2.default.debug) { - str += ': ' + _util2.default.Uint8Array_to_hex(arrToHex); - console.log(str); - } - }, - - /** - * Helper function to print a debug message. Debug - * messages are only printed if - * @link module:config/config.debug is set to true. - * Different than print_debug because will call str_to_hex iff necessary. - * @param {String} str String of the debug message - */ - print_debug_hexstr_dump: function print_debug_hexstr_dump(str, strToHex) { - if (_config2.default.debug) { - str += _util2.default.str_to_hex(strToHex); - console.log(str); - } - }, - - /** - * Helper function to print a debug error. Debug - * messages are only printed if - * @link module:config/config.debug is set to true. - * @param {String} str String of the debug message - */ - print_debug_error: function print_debug_error(error) { - if (_config2.default.debug) { - console.error(error); - } - }, - - /** - * Read a stream to the end and print it to the console when it's closed. - * @param {String} str String of the debug message - * @param {ReadableStream|Uint8array|String} input Stream to print - * @param {Function} concat Function to concatenate chunks of the stream (defaults to util.concat). - */ - print_entire_stream: function print_entire_stream(str, input, concat) { - _webStreamTools2.default.readToEnd(_webStreamTools2.default.clone(input), concat).then(result => { - console.log(str + ': ', result); - }); - }, - - // returns bit length of the integer x - nbits: function nbits(x) { - let r = 1; - let t = x >>> 16; - if (t !== 0) { - x = t; - r += 16; - } - t = x >> 8; - if (t !== 0) { - x = t; - r += 8; - } - t = x >> 4; - if (t !== 0) { - x = t; - r += 4; - } - t = x >> 2; - if (t !== 0) { - x = t; - r += 2; - } - t = x >> 1; - if (t !== 0) { - x = t; - r += 1; - } - return r; - }, - - /** - * If S[1] == 0, then double(S) == (S[2..128] || 0); - * otherwise, double(S) == (S[2..128] || 0) xor - * (zeros(120) || 10000111). - * - * Both OCB and EAX (through CMAC) require this function to be constant-time. - * - * @param {Uint8Array} data - */ - double: function double(data) { - const double_var = new Uint8Array(data.length); - const last = data.length - 1; - for (let i = 0; i < last; i++) { - double_var[i] = data[i] << 1 ^ data[i + 1] >> 7; - } - double_var[last] = data[last] << 1 ^ (data[0] >> 7) * 0x87; - return double_var; - }, - - /** - * Shift a Uint8Array to the right by n bits - * @param {Uint8Array} array The array to shift - * @param {Integer} bits Amount of bits to shift (MUST be smaller - * than 8) - * @returns {String} Resulting array. - */ - shiftRight: function shiftRight(array, bits) { - if (bits) { - for (let i = array.length - 1; i >= 0; i--) { - array[i] >>= bits; - if (i > 0) { - array[i] |= array[i - 1] << 8 - bits; - } - } - } - return array; - }, - - /** - * Get native Web Cryptography api, only the current version of the spec. - * The default configuration is to use the api when available. But it can - * be deactivated with config.use_native - * @returns {Object} The SubtleCrypto api or 'undefined' - */ - getWebCrypto: function getWebCrypto() { - if (!_config2.default.use_native) { - return; - } - - return typeof window !== 'undefined' && window.crypto && window.crypto.subtle; - }, - - /** - * Get native Web Cryptography api for all browsers, including legacy - * implementations of the spec e.g IE11 and Safari 8/9. The default - * configuration is to use the api when available. But it can be deactivated - * with config.use_native - * @returns {Object} The SubtleCrypto api or 'undefined' - */ - getWebCryptoAll: function getWebCryptoAll() { - if (!_config2.default.use_native) { - return; - } - - if (typeof window !== 'undefined') { - if (window.crypto) { - return window.crypto.subtle || window.crypto.webkitSubtle; - } - if (window.msCrypto) { - return window.msCrypto.subtle; - } - } - }, - - /** - * Detect Node.js runtime. - */ - detectNode: function detectNode() { - return typeof global.process === 'object' && typeof global.process.versions === 'object'; - }, - - /** - * Get native Node.js module - * @param {String} The module to require - * @returns {Object} The required module or 'undefined' - */ - nodeRequire: function nodeRequire(module) { - if (!_util2.default.detectNode()) { - return; - } - - // Requiring the module dynamically allows us to access the native node module. - // otherwise, it gets replaced with the browserified version - // eslint-disable-next-line import/no-dynamic-require - return require(module); - }, - - /** - * Get native Node.js crypto api. The default configuration is to use - * the api when available. But it can also be deactivated with config.use_native - * @returns {Object} The crypto module or 'undefined' - */ - getNodeCrypto: function getNodeCrypto() { - if (!_config2.default.use_native) { - return; - } - - return _util2.default.nodeRequire('crypto'); - }, - - getNodeZlib: function getNodeZlib() { - if (!_config2.default.use_native) { - return; - } - - return _util2.default.nodeRequire('zlib'); - }, - - /** - * Get native Node.js Buffer constructor. This should be used since - * Buffer is not available under browserify. - * @returns {Function} The Buffer constructor or 'undefined' - */ - getNodeBuffer: function getNodeBuffer() { - return (_util2.default.nodeRequire('buffer') || {}).Buffer; - }, - - getNodeStream: function getNodeStream() { - return (_util2.default.nodeRequire('stream') || {}).Readable; - }, - - getHardwareConcurrency: function getHardwareConcurrency() { - if (_util2.default.detectNode()) { - const os = _util2.default.nodeRequire('os'); - return os.cpus().length; - } - - return navigator.hardwareConcurrency || 1; - }, - - isEmailAddress: function isEmailAddress(data) { - if (!_util2.default.isString(data)) { - return false; - } - const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+([a-zA-Z]{2,}|xn--[a-zA-Z\-0-9]+)))$/; - return re.test(data); - }, - - /** - * Format user id for internal use. - */ - formatUserId: function formatUserId(id) { - // name, email address and comment can be empty but must be of the correct type - if (id.name && !_util2.default.isString(id.name) || id.email && !_util2.default.isEmailAddress(id.email) || id.comment && !_util2.default.isString(id.comment)) { - throw new Error('Invalid user id format'); - } - const components = []; - if (id.name) { - components.push(id.name); - } - if (id.comment) { - components.push(`(${id.comment})`); - } - if (id.email) { - components.push(`<${id.email}>`); - } - return components.join(' '); - }, - - /** - * Parse user id. - */ - parseUserId: function parseUserId(userid) { - if (userid.length > _config2.default.max_userid_length) { - throw new Error('User id string is too long'); - } - try { - var _emailAddresses$parse = _emailAddresses2.default.parseOneAddress(userid); - - const name = _emailAddresses$parse.name, - email = _emailAddresses$parse.address, - comments = _emailAddresses$parse.comments; - - return { name, email, comment: comments.replace(/^\(|\)$/g, '') }; - } catch (e) { - throw new Error('Invalid user id format'); - } - }, - - /** - * Normalize line endings to \r\n - */ - canonicalizeEOL: function canonicalizeEOL(text) { - return _webStreamTools2.default.transform(_util2.default.nativeEOL(text), value => value.replace(/\r/g, "\n").replace(/\n/g, "\r\n")); - }, - - /** - * Convert line endings from canonicalized \r\n to native \n - */ - nativeEOL: function nativeEOL(text) { - let lastChar = ''; - return _webStreamTools2.default.transform(text, value => { - value = lastChar + value; - if (value[value.length - 1] === '\r') { - lastChar = '\r'; - value = value.slice(0, -1); - } else { - lastChar = ''; - } - return value.replace(/\r\n/g, '\n'); - }, () => lastChar); - }, - - /** - * Remove trailing spaces and tabs from each line - */ - removeTrailingSpaces: function removeTrailingSpaces(text) { - return text.split('\n').map(line => { - let i = line.length - 1; - for (; i >= 0 && (line[i] === ' ' || line[i] === '\t'); i--); - return line.substr(0, i + 1); - }).join('\n'); - }, - - /** - * Encode input buffer using Z-Base32 encoding. - * See: https://tools.ietf.org/html/rfc6189#section-5.1.6 - * - * @param {Uint8Array} data The binary data to encode - * @returns {String} Binary data encoded using Z-Base32 - */ - encodeZBase32: function encodeZBase32(data) { - if (data.length === 0) { - return ""; - } - const ALPHABET = "ybndrfg8ejkmcpqxot1uwisza345h769"; - const SHIFT = 5; - const MASK = 31; - let buffer = data[0]; - let index = 1; - let bitsLeft = 8; - let result = ''; - while (bitsLeft > 0 || index < data.length) { - if (bitsLeft < SHIFT) { - if (index < data.length) { - buffer <<= 8; - buffer |= data[index++] & 0xff; - bitsLeft += 8; - } else { - const pad = SHIFT - bitsLeft; - buffer <<= pad; - bitsLeft += pad; - } - } - bitsLeft -= SHIFT; - result += ALPHABET[MASK & buffer >> bitsLeft]; - } - return result; - } -}; // re-import module to access util functions -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/* eslint-disable no-console */ - -/** - * This object contains utility functions - * @requires email-addresses - * @requires web-stream-tools - * @requires config - * @requires encoding/base64 - * @module util - */ - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./config":79,"./encoding/base64":112,"./util":152,"email-addresses":33,"web-stream-tools":75}],153:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); // OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2018 Wiktor Kwapisiewicz -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @fileoverview This class implements a client for the Web Key Directory (wkd) protocol - * in order to lookup keys on designated servers. - * See: https://datatracker.ietf.org/doc/draft-koch-openpgp-webkey-service/ - * @module wkd - */ - -var _util = require('./util'); - -var _util2 = _interopRequireDefault(_util); - -var _crypto = require('./crypto'); - -var _crypto2 = _interopRequireDefault(_crypto); - -var _key = require('./key'); - -var keyMod = _interopRequireWildcard(_key); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Initialize the WKD client - * @constructor - */ -function WKD() { - this._fetch = typeof window !== 'undefined' ? window.fetch : require('node-fetch'); -} - -/** - * Search for a public key using Web Key Directory protocol. - * @param {String} options.email User's email. - * @param {Boolean} options.rawBytes Returns Uint8Array instead of parsed key. - * @returns {Promise, - * err: (Array|null)}>} The public key. - * @async - */ -WKD.prototype.lookup = async function (options) { - const fetch = this._fetch; - - if (!options.email) { - throw new Error('You must provide an email parameter!'); - } - - if (!_util2.default.isEmailAddress(options.email)) { - throw new Error('Invalid e-mail address.'); - } - - var _$exec = /(.*)@(.*)/.exec(options.email), - _$exec2 = _slicedToArray(_$exec, 3); - - const localPart = _$exec2[1], - domain = _$exec2[2]; - - const localEncoded = _util2.default.encodeZBase32((await _crypto2.default.hash.sha1(_util2.default.str_to_Uint8Array(localPart.toLowerCase())))); - - const url = `https://${domain}/.well-known/openpgpkey/hu/${localEncoded}`; - - return fetch(url).then(function (response) { - if (response.status === 200) { - return response.arrayBuffer(); - } - }).then(function (publicKey) { - if (publicKey) { - const rawBytes = new Uint8Array(publicKey); - if (options.rawBytes) { - return rawBytes; - } - return keyMod.read(rawBytes); - } - }); -}; - -exports.default = WKD; - -},{"./crypto":94,"./key":116,"./util":152,"node-fetch":"node-fetch"}],154:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _util = require('../util.js'); - -var _util2 = _interopRequireDefault(_util); - -var _config = require('../config'); - -var _config2 = _interopRequireDefault(_config); - -var _crypto = require('../crypto'); - -var _crypto2 = _interopRequireDefault(_crypto); - -var _packet = require('../packet'); - -var _packet2 = _interopRequireDefault(_packet); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/** - * Initializes a new proxy and loads the web worker - * @param {String} path The path to the worker or 'openpgp.worker.js' by default - * @param {Number} n number of workers to initialize if path given - * @param {Object} config config The worker configuration - * @param {Array} worker alternative to path parameter: web worker initialized with 'openpgp.worker.js' - * @constructor - */ -// GPG4Browsers - An OpenPGP implementation in javascript -// Copyright (C) 2011 Recurity Labs GmbH -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * @fileoverview Provides functions for maintaining browser workers - * @see module:openpgp.initWorker - * @see module:openpgp.getWorker - * @see module:openpgp.destroyWorker - * @see module:worker/worker - * @requires util - * @requires config - * @requires crypto - * @requires packet - * @module worker/async_proxy - */ - -function AsyncProxy({ path = 'openpgp.worker.js', n = 1, workers = [], config } = {}) { - /** - * Message handling - */ - const handleMessage = workerId => event => { - const msg = event.data; - switch (msg.event) { - case 'loaded': - this.workers[workerId].loadedResolve(true); - break; - case 'method-return': - if (msg.err) { - // fail - const err = new Error(msg.err); - // add worker stack - err.workerStack = msg.stack; - this.tasks[msg.id].reject(err); - } else { - // success - this.tasks[msg.id].resolve(msg.data); - } - delete this.tasks[msg.id]; - this.workers[workerId].requests--; - break; - case 'request-seed': - this.seedRandom(workerId, msg.amount); - break; - default: - throw new Error('Unknown Worker Event.'); - } - }; - - if (workers.length) { - this.workers = workers; - } else { - this.workers = []; - while (this.workers.length < n) { - this.workers.push(new Worker(path)); - } - } - - let workerId = 0; - this.workers.forEach(worker => { - worker.loadedPromise = new Promise(resolve => { - worker.loadedResolve = resolve; - }); - worker.requests = 0; - worker.onmessage = handleMessage(workerId++); - worker.onerror = e => { - worker.loadedResolve(false); - console.error('Unhandled error in openpgp worker: ' + e.message + ' (' + e.filename + ':' + e.lineno + ')'); - return false; - }; - - if (config) { - worker.postMessage({ event: 'configure', config }); - } - }); - - // Cannot rely on task order being maintained, use object keyed by request ID to track tasks - this.tasks = {}; - this.currentID = 0; -} - -/** - * Returns a promise that resolves when all workers have finished loading - * @returns {Promise} Resolves to true if all workers have loaded succesfully; false otherwise -*/ -AsyncProxy.prototype.loaded = async function () { - const loaded = await Promise.all(this.workers.map(worker => worker.loadedPromise)); - return loaded.every(Boolean); -}; - -/** - * Get new request ID - * @returns {integer} New unique request ID -*/ -AsyncProxy.prototype.getID = function () { - return this.currentID++; -}; - -/** - * Send message to worker with random data - * @param {Integer} size Number of bytes to send - * @async - */ -AsyncProxy.prototype.seedRandom = async function (workerId, size) { - const buf = await _crypto2.default.random.getRandomBytes(size); - this.workers[workerId].postMessage({ event: 'seed-random', buf }, _util2.default.getTransferables(buf, true)); -}; - -/** - * Terminates the workers - */ -AsyncProxy.prototype.terminate = function () { - this.workers.forEach(worker => { - worker.terminate(); - }); -}; - -/** - * Generic proxy function that handles all commands from the public api. - * @param {String} method the public api function to be delegated to the worker thread - * @param {Object} options the api function's options - * @returns {Promise} see the corresponding public api functions for their return types - * @async - */ -AsyncProxy.prototype.delegate = function (method, options) { - - const id = this.getID(); - const requests = this.workers.map(worker => worker.requests); - const minRequests = Math.min(...requests); - let workerId = 0; - for (; workerId < this.workers.length; workerId++) { - if (this.workers[workerId].requests === minRequests) { - break; - } - } - - return new Promise((_resolve, reject) => { - // clone packets (for web worker structured cloning algorithm) - this.workers[workerId].postMessage({ id: id, event: method, options: _packet2.default.clone.clonePackets(options) }, _util2.default.getTransferables(options, _config2.default.zero_copy)); - this.workers[workerId].requests++; - - // remember to handle parsing cloned packets from worker - this.tasks[id] = { resolve: data => _resolve(_packet2.default.clone.parseClonedPackets(_util2.default.restoreStreams(data), method)), reject }; - }); -}; - -exports.default = AsyncProxy; - -},{"../config":79,"../crypto":94,"../packet":125,"../util.js":152}]},{},[115])(115) -}); diff --git a/Core/.save/openpgpv5/node/openpgp.js b/Core/source/lib/openpgpjs-v5/dist/node/openpgp.js similarity index 99% rename from Core/.save/openpgpv5/node/openpgp.js rename to Core/source/lib/openpgpjs-v5/dist/node/openpgp.js index bfa4b8c64..2cd0e6994 100644 --- a/Core/.save/openpgpv5/node/openpgp.js +++ b/Core/source/lib/openpgpjs-v5/dist/node/openpgp.js @@ -22800,7 +22800,7 @@ class UnsupportedError extends Error { // GPG4Browsers - An OpenPGP implementation in javascript // Symbol to store cryptographic validity of the signature, to avoid recomputing multiple times on verification. -const verified = Symbol('verified'); +// const verified = Symbol('verified'); // GPG puts the Issuer and Signature subpackets in the unhashed area. // Tampering with those invalidates the signature, so we still trust them and parse them. @@ -22874,7 +22874,7 @@ class SignaturePacket { this.preferredAEADAlgorithms = null; this.revoked = null; - this[verified] = null; + this.verified = null; } /** @@ -22982,7 +22982,7 @@ class SignaturePacket { // getLatestValidSignature(this.revocationSignatures, key, data)` later. // Note that this only holds up if the key and data passed to verify are the // same as the ones passed to sign. - this[verified] = true; + this.verified = true; } } @@ -23447,7 +23447,7 @@ class SignaturePacket { // Cryptographic validity is cached after one successful verification. // However, for message signatures, we always re-verify, since the passed `data` can change const skipVerify = this.verified && !isMessageSignature; - console.log(`verify signature OUID ${Object.__oid(this)} ${this[verified]} sigtype=${signatureType}...`); + // console.log(`verify signature OUID ${Object.__oid(this)} ${this.verified} sigtype=${signatureType}...`); if (!skipVerify) { let toHash; let hash; @@ -23469,7 +23469,7 @@ class SignaturePacket { this.publicKeyAlgorithm, this.hashAlgorithm, this.params, key.publicParams, toHash, hash ); - console.log(`verify signature OUID ${Object.__oid(this)} sigtype=${signatureType} result: ${this.verified}`); + // console.log(`verify signature OUID ${Object.__oid(this)} sigtype=${signatureType} result: ${this.verified}`); if (!this.verified) { throw new Error('Signature verification failed'); diff --git a/Core/.save/openpgpv5/openpgp.js b/Core/source/lib/openpgpjs-v5/dist/openpgp.js similarity index 99% rename from Core/.save/openpgpv5/openpgp.js rename to Core/source/lib/openpgpjs-v5/dist/openpgp.js index 965b44b2a..45c7f801e 100644 --- a/Core/.save/openpgpv5/openpgp.js +++ b/Core/source/lib/openpgpjs-v5/dist/openpgp.js @@ -22755,7 +22755,7 @@ var openpgp = (function (exports) { // GPG4Browsers - An OpenPGP implementation in javascript // Symbol to store cryptographic validity of the signature, to avoid recomputing multiple times on verification. - const verified = Symbol('verified'); + // const verified = Symbol('verified'); // GPG puts the Issuer and Signature subpackets in the unhashed area. // Tampering with those invalidates the signature, so we still trust them and parse them. @@ -22829,7 +22829,7 @@ var openpgp = (function (exports) { this.preferredAEADAlgorithms = null; this.revoked = null; - this[verified] = null; + this.verified = null; } /** @@ -22937,7 +22937,7 @@ var openpgp = (function (exports) { // getLatestValidSignature(this.revocationSignatures, key, data)` later. // Note that this only holds up if the key and data passed to verify are the // same as the ones passed to sign. - this[verified] = true; + this.verified = true; } } diff --git a/Core/source/lib/openpgpjs-v5/openpgp.d.ts b/Core/source/lib/openpgpjs-v5/openpgp.d.ts new file mode 100644 index 000000000..066818dba --- /dev/null +++ b/Core/source/lib/openpgpjs-v5/openpgp.d.ts @@ -0,0 +1,911 @@ +/** + * Type definitions for OpenPGP.js http://openpgpjs.org/ + * + * Contributors: + * - FlowCrypt a. s. + * - Guillaume Lacasa + * - Errietta Kostala + */ + +/* ############## v5 KEY #################### */ +// The Key and PublicKey types can be used interchangably since TS cannot detect the difference, as they have the same class properties. +// The declared readKey(s) return type is Key instead of a PublicKey since it seems more obvious that a Key can be cast to a PrivateKey. +export function readKey(options: { armoredKey: string, config?: PartialConfig }): Promise; +export function readKey(options: { binaryKey: Uint8Array, config?: PartialConfig }): Promise; +export function readKeys(options: { armoredKeys: string, config?: PartialConfig }): Promise; +export function readKeys(options: { binaryKeys: Uint8Array, config?: PartialConfig }): Promise; +export function readPrivateKey(options: { armoredKey: string, config?: PartialConfig }): Promise; +export function readPrivateKey(options: { binaryKey: Uint8Array, config?: PartialConfig }): Promise; +export function readPrivateKeys(options: { armoredKeys: string, config?: PartialConfig }): Promise; +export function readPrivateKeys(options: { binaryKeys: Uint8Array, config?: PartialConfig }): Promise; +export function generateKey(options: KeyOptions & { format?: 'armored' }): Promise & { revocationCertificate: string }>; +export function generateKey(options: KeyOptions & { format: 'binary' }): Promise & { revocationCertificate: string }>; +export function generateKey(options: KeyOptions & { format: 'object' }): Promise; +export function decryptKey(options: { privateKey: PrivateKey; passphrase?: MaybeArray; config?: PartialConfig }): Promise; +export function encryptKey(options: { privateKey: PrivateKey; passphrase?: MaybeArray; config?: PartialConfig }): Promise; +export function reformatKey(options: { privateKey: PrivateKey; userIDs?: MaybeArray; passphrase?: string; keyExpirationTime?: number; date?: Date, format?: 'armored', config?: PartialConfig }): Promise & { revocationCertificate: string }>; +export function reformatKey(options: { privateKey: PrivateKey; userIDs?: MaybeArray; passphrase?: string; keyExpirationTime?: number; date?: Date, format: 'binary', config?: PartialConfig }): Promise & { revocationCertificate: string }>; +export function reformatKey(options: { privateKey: PrivateKey; userIDs?: MaybeArray; passphrase?: string; keyExpirationTime?: number; date?: Date, format: 'object', config?: PartialConfig }): Promise; +export function revokeKey(options: { key: PrivateKey, reasonForRevocation?: ReasonForRevocation, date?: Date, format?: 'armored', config?: PartialConfig }): Promise>; +export function revokeKey(options: { key: PrivateKey, reasonForRevocation?: ReasonForRevocation, date?: Date, format: 'binary', config?: PartialConfig }): Promise>; +export function revokeKey(options: { key: PrivateKey, reasonForRevocation?: ReasonForRevocation, date?: Date, format: 'object', config?: PartialConfig }): Promise; +export function revokeKey(options: { key: PrivateKey, revocationCertificate: string, date?: Date, format?: 'armored', config?: PartialConfig }): Promise>; +export function revokeKey(options: { key: PrivateKey, revocationCertificate: string, date?: Date, format: 'binary', config?: PartialConfig }): Promise>; +export function revokeKey(options: { key: PrivateKey, revocationCertificate: string, date?: Date, format: 'object', config?: PartialConfig }): Promise; +export function revokeKey(options: { key: PublicKey, revocationCertificate: string, date?: Date, format?: 'armored', config?: PartialConfig }): Promise<{ publicKey: string, privateKey: null }>; +export function revokeKey(options: { key: PublicKey, revocationCertificate: string, date?: Date, format: 'binary', config?: PartialConfig }): Promise<{ publicKey: Uint8Array, privateKey: null }>; +export function revokeKey(options: { key: PublicKey, revocationCertificate: string, date?: Date, format: 'object', config?: PartialConfig }): Promise<{ publicKey: PublicKey, privateKey: null }>; + +export abstract class Key { + public readonly keyPacket: PublicKeyPacket | SecretKeyPacket; + public subkeys: Subkey[]; // do not add/replace users directly + public users: User[]; // do not add/replace subkeys directly + public revocationSignatures: SignaturePacket[]; + public write(): Uint8Array; + public armor(config?: Config): string; + public getExpirationTime(userID?: UserID, config?: Config): Promise; + public getKeyIDs(): KeyID[]; + public getPrimaryUser(date?: Date, userID?: UserID, config?: Config): Promise; // throws on error + public getUserIDs(): string[]; + public isPrivate(): this is PrivateKey; + public toPublic(): PublicKey; + // NB: the order of the `update` declarations matters, since PublicKey includes PrivateKey + public update(sourceKey: PrivateKey, date?: Date, config?: Config): Promise; + public update(sourceKey: PublicKey, date?: Date, config?: Config): Promise; + public signPrimaryUser(privateKeys: PrivateKey[], date?: Date, userID?: UserID, config?: Config): Promise + public signAllUsers(privateKeys: PrivateKey[], date?: Date, config?: Config): Promise + public verifyPrimaryKey(date?: Date, userID?: UserID, config?: Config): Promise; // throws on error + public verifyPrimaryUser(publicKeys: PublicKey[], date?: Date, userIDs?: UserID, config?: Config): Promise<{ keyID: KeyID, valid: boolean | null }[]>; + public verifyAllUsers(publicKeys: PublicKey[], date?: Date, config?: Config): Promise<{ userID: string, keyID: KeyID, valid: boolean | null }[]>; + // -----BEGIN MODIFIED BY FLOWCRYPT----- + // Make this permanent: https://github.com/openpgpjs/openpgpjs/pull/1486 + public isRevoked(signature?: SignaturePacket, key?: AnyKeyPacket, date?: Date, config?: Config): Promise; + // -----END MODIFIED BY FLOWCRYPT----- + public getRevocationCertificate(date?: Date, config?: Config): Promise | undefined>; + public getEncryptionKey(keyID?: KeyID, date?: Date | null, userID?: UserID, config?: Config): Promise; + public getSigningKey(keyID?: KeyID, date?: Date | null, userID?: UserID, config?: Config): Promise; + public getKeys(keyID?: KeyID): (this | Subkey)[]; + public getSubkeys(keyID?: KeyID): Subkey[]; + public getFingerprint(): string; + public getCreationTime(): Date; + public getAlgorithmInfo(): AlgorithmInfo; + public getKeyID(): KeyID; + public toPacketList(): PacketList; +} + +type AllowedKeyPackets = PublicKeyPacket | PublicSubkeyPacket | SecretKeyPacket | SecretSubkeyPacket | UserIDPacket | UserAttributePacket | SignaturePacket; +export class PublicKey extends Key { + constructor(packetlist: PacketList); +} + +export class PrivateKey extends PublicKey { + constructor(packetlist: PacketList); + public revoke(reason?: ReasonForRevocation, date?: Date, config?: Config): Promise; + public isDecrypted(): boolean; + public addSubkey(options: SubkeyOptions): Promise; + public getDecryptionKeys(keyID?: KeyID, date?: Date | null, userID?: UserID, config?: Config): Promise + public update(sourceKey: PublicKey, date?: Date, config?: Config): Promise; +} + +export class Subkey { + constructor(subkeyPacket: SecretSubkeyPacket | PublicSubkeyPacket, mainKey: PublicKey); + public readonly keyPacket: SecretSubkeyPacket | PublicSubkeyPacket; + public readonly mainKey: PublicKey; + public bindingSignatures: SignaturePacket[]; + public revocationSignatures: SignaturePacket[]; + public verify(date?: Date, config?: Config): Promise; + public isDecrypted(): boolean; + public getFingerprint(): string; + public getCreationTime(): Date; + public getAlgorithmInfo(): AlgorithmInfo; + public getKeyID(): KeyID; +} + +export interface User { + userID: UserIDPacket | null; + userAttribute: UserAttributePacket | null; + selfCertifications: SignaturePacket[]; + otherCertifications: SignaturePacket[]; + revocationSignatures: SignaturePacket[]; +} + +export interface PrimaryUser { + index: number; + user: User; +} + +type AlgorithmInfo = { + algorithm: enums.publicKeyNames; + bits?: number; + curve?: EllipticCurveName; +}; + +/* ############## v5 SIG #################### */ + +export function readSignature(options: { armoredSignature: string, config?: PartialConfig }): Promise; +export function readSignature(options: { binarySignature: Uint8Array, config?: PartialConfig }): Promise; + +export class Signature { + public readonly packets: PacketList; + constructor(packetlist: PacketList); + public write(): MaybeStream; + public armor(config?: Config): string; + public getSigningKeyIDs(): Array; +} + +interface VerificationResult { + keyID: KeyID; + verified: Promise; // throws on invalid signature + signature: Promise; +} + +/* ############## v5 CLEARTEXT #################### */ + +export function readCleartextMessage(options: { cleartextMessage: string, config?: PartialConfig }): Promise; + +export function createCleartextMessage(options: { text: string }): Promise; + +/** Class that represents an OpenPGP cleartext signed message. + */ +export class CleartextMessage { + /** Returns ASCII armored text of cleartext signed message + */ + armor(config?: Config): string; + + /** Returns the key IDs of the keys that signed the cleartext message + */ + getSigningKeyIDs(): KeyID[]; + + /** Get cleartext + */ + getText(): string; + + /** Sign the cleartext message + * + * @param privateKeys private keys with decrypted secret key data for signing + */ + sign(privateKeys: PrivateKey[], signature?: Signature, signingKeyIDs?: KeyID[], date?: Date, userIDs?: UserID[], config?: Config): void; + + /** Verify signatures of cleartext signed message + * @param keys array of keys to verify signatures + */ + verify(keys: PublicKey[], date?: Date, config?: Config): Promise; +} + +/* ############## v5 MSG #################### */ +export function generateSessionKey(options: { encryptionKeys: MaybeArray, date?: Date, encryptionUserIDs?: MaybeArray, config?: PartialConfig }): Promise; +export function encryptSessionKey(options: SessionKey & { + encryptionKeys?: MaybeArray, passwords?: MaybeArray, format?: 'armored', wildcard?: boolean, encryptionKeyIDs?: MaybeArray, date?: Date, encryptionUserIDs?: MaybeArray, config?: PartialConfig +}) : Promise; +export function encryptSessionKey(options: SessionKey & { + encryptionKeys?: MaybeArray, passwords?: MaybeArray, format: 'binary', wildcard?: boolean, encryptionKeyIDs?: MaybeArray, date?: Date, encryptionUserIDs?: MaybeArray, config?: PartialConfig +}) : Promise; +export function encryptSessionKey(options: SessionKey & { + encryptionKeys?: MaybeArray, passwords?: MaybeArray, format: 'object', wildcard?: boolean, encryptionKeyIDs?: MaybeArray, date?: Date, encryptionUserIDs?: MaybeArray, config?: PartialConfig +}) : Promise>; +export function decryptSessionKeys>(options: { message: Message, decryptionKeys?: MaybeArray, passwords?: MaybeArray, date?: Date, config?: PartialConfig }): Promise; + +export function readMessage>(options: { armoredMessage: T, config?: PartialConfig }): Promise>; +export function readMessage>(options: { binaryMessage: T, config?: PartialConfig }): Promise>; + +export function createMessage>(options: { text: T, filename?: string, date?: Date, format?: enums.literalFormatNames }): Promise>; +export function createMessage>(options: { binary: T, filename?: string, date?: Date, format?: enums.literalFormatNames }): Promise>; + +export function encrypt>(options: EncryptOptions & { message: Message, format?: 'armored' }): Promise< + T extends WebStream ? WebStream : + T extends NodeStream ? NodeStream : + string +>; +export function encrypt>(options: EncryptOptions & { message: Message, format: 'binary' }): Promise< + T extends WebStream ? WebStream : + T extends NodeStream ? NodeStream : + Uint8Array +>; +export function encrypt>(options: EncryptOptions & { message: Message, format: 'object' }): Promise>; + +export function sign>(options: SignOptions & { message: Message, format?: 'armored' }): Promise< + T extends WebStream ? WebStream : + T extends NodeStream ? NodeStream : + string +>; +export function sign>(options: SignOptions & { message: Message, format: 'binary' }): Promise< + T extends WebStream ? WebStream : + T extends NodeStream ? NodeStream : + Uint8Array +>; +export function sign>(options: SignOptions & { message: Message, format: 'object' }): Promise>; +export function sign(options: SignOptions & { message: CleartextMessage, format?: 'armored' }): Promise; +export function sign(options: SignOptions & { message: CleartextMessage, format: 'object' }): Promise; + +export function decrypt>(options: DecryptOptions & { message: Message, format: 'binary' }): Promise ? WebStream : + T extends NodeStream ? NodeStream : + Uint8Array +}>; +export function decrypt>(options: DecryptOptions & { message: Message }): Promise ? WebStream : + T extends NodeStream ? NodeStream : + string +}>; + +export function verify>(options: VerifyOptions & { message: Message, format: 'binary' }): Promise ? WebStream : + T extends NodeStream ? NodeStream : + Uint8Array +}>; +export function verify>(options: VerifyOptions & { message: Message }): Promise ? WebStream : + T extends NodeStream ? NodeStream : + string +}>; + +/** Class that represents an OpenPGP message. Can be an encrypted message, signed message, compressed message or literal message + */ +export class Message> { + + public readonly packets: PacketList; + constructor(packetlist: PacketList); + + /** Returns binary representation of message + */ + public write(): MaybeStream; + + /** Returns ASCII armored text of message + */ + public armor(config?: Config): string; + + /** Decrypt the message + @param decryptionKeys array of private keys with decrypted secret data + */ + public decrypt(decryptionKeys?: PrivateKey[], passwords?: string[], sessionKeys?: SessionKey[], date?: Date, config?: Config): Promise>>; + + /** Encrypt the message + @param encryptionKeys array of public keys, used to encrypt the message + */ + public encrypt(encryptionKeys?: PublicKey[], passwords?: string[], sessionKeys?: SessionKey[], wildcard?: boolean, encryptionKeyIDs?: KeyID[], date?: Date, userIDs?: UserID[], config?: Config): Promise>>; + + /** Returns the key IDs of the keys to which the session key is encrypted + */ + public getEncryptionKeyIDs(): KeyID[]; + + /** Get literal data that is the body of the message + */ + public getLiteralData(): MaybeStream | null; + + /** Returns the key IDs of the keys that signed the message + */ + public getSigningKeyIDs(): KeyID[]; + + /** Get literal data as text + */ + public getText(): MaybeStream | null; + + public getFilename(): string | null; + + /** Sign the message (the literal data packet of the message) + @param signingKeys private keys with decrypted secret key data for signing + */ + public sign(signingKeys: PrivateKey[], signature?: Signature, signingKeyIDs?: KeyID[], date?: Date, userIDs?: UserID[], config?: Config): Promise>; + + /** Unwrap compressed message + */ + public unwrapCompressed(): Message; + + /** Verify message signatures + @param verificationKeys array of public keys to verify signatures + */ + public verify(verificationKeys: PublicKey[], date?: Date, config?: Config): Promise; + + /** + * Append signature to unencrypted message object + * @param {String|Uint8Array} detachedSignature - The detached ASCII-armored or Uint8Array PGP signature + */ + public appendSignature(detachedSignature: string | Uint8Array, config?: Config): Promise; +} + + +/* ############## v5 CONFIG #################### */ + +interface Config { + preferredHashAlgorithm: enums.hash; + preferredSymmetricAlgorithm: enums.symmetric; + preferredCompressionAlgorithm: enums.compression; + showVersion: boolean; + showComment: boolean; + deflateLevel: number; + aeadProtect: boolean; + allowUnauthenticatedMessages: boolean; + allowUnauthenticatedStream: boolean; + checksumRequired: boolean; + minRSABits: number; + passwordCollisionCheck: boolean; + revocationsExpire: boolean; + ignoreUnsupportedPackets: boolean; + ignoreMalformedPackets: boolean; + versionString: string; + commentString: string; + allowInsecureDecryptionWithSigningKeys: boolean; + constantTimePKCS1Decryption: boolean; + constantTimePKCS1DecryptionSupportedSymmetricAlgorithms: Set; + v5Keys: boolean; + preferredAEADAlgorithm: enums.aead; + aeadChunkSizeByte: number; + s2kIterationCountByte: number; + minBytesForWebCrypto: number; + maxUserIDLength: number; + knownNotations: string[]; + useIndutnyElliptic: boolean; + rejectHashAlgorithms: Set; + rejectMessageHashAlgorithms: Set; + rejectPublicKeyAlgorithms: Set; + rejectCurves: Set; +} +export var config: Config; + +// PartialConfig has the same properties as Config, but declared as optional. +// This interface is relevant for top-level functions, which accept a subset of configuration options +interface PartialConfig extends Partial {} + +/* ############## v5 PACKET #################### */ + +export abstract class BasePacket { + static readonly tag: enums.packet; + public read(bytes: Uint8Array): void; + public write(): Uint8Array; +} + +/** + * The relationship between the KeyPacket classes is modeled by considering the following: + * - A Secret (Sub)Key Packet can always be used when a Public one is expected. + * - A Subkey Packet cannot always be used when a Primary Key Packet is expected (and vice versa). + */ +export abstract class BasePublicKeyPacket extends BasePacket { + public algorithm: enums.publicKey; + public created: Date; + public version: number; + public getAlgorithmInfo(): AlgorithmInfo; + public getFingerprint(): string; + public getFingerprintBytes(): Uint8Array | null; + public hasSameFingerprintAs(other: BasePublicKeyPacket): boolean; + public getCreationTime(): Date; + public getKeyID(): KeyID; + public isDecrypted(): boolean; + public publicParams: object; + // `isSubkey` is a dummy method to ensure that Subkey packets are not accepted as Key one, and vice versa. + // The key class hierarchy is already modelled to cover this, but the concrete key packet classes + // have compatible structure and TS can't detect the difference. + protected isSubkey(): boolean; +} + +export class PublicKeyPacket extends BasePublicKeyPacket { + static readonly tag: enums.packet.publicKey; + protected isSubkey(): false; +} + +export class PublicSubkeyPacket extends BasePublicKeyPacket { + static readonly tag: enums.packet.publicSubkey; + protected isSubkey(): true; +} + +export abstract class BaseSecretKeyPacket extends BasePublicKeyPacket { + public privateParams: object | null; + public encrypt(passphrase: string, config?: Config): Promise; // throws on error + public decrypt(passphrase: string): Promise; // throws on error + public validate(): Promise; // throws on error + public isDummy(): boolean; + public makeDummy(config?: Config): void; +} + +export class SecretKeyPacket extends BaseSecretKeyPacket { + static readonly tag: enums.packet.secretKey; + protected isSubkey(): false; +} + +export class SecretSubkeyPacket extends BaseSecretKeyPacket { + static readonly tag: enums.packet.secretSubkey; + protected isSubkey(): true; +} + +export class CompressedDataPacket extends BasePacket { + static readonly tag: enums.packet.compressedData; + private compress(): void; + private decompress(config?: Config): void; +} + +export class SymEncryptedIntegrityProtectedDataPacket extends BasePacket { + static readonly tag: enums.packet.symEncryptedIntegrityProtectedData; +} + +export class AEADEncryptedDataPacket extends BasePacket { + static readonly tag: enums.packet.aeadEncryptedData; + private decrypt(sessionKeyAlgorithm: enums.symmetric, sessionKey: Uint8Array, config?: Config): void; + private encrypt(sessionKeyAlgorithm: enums.symmetric, sessionKey: Uint8Array, config?: Config): void; + private crypt(fn: Function, sessionKey: Uint8Array, data: MaybeStream): MaybeStream +} + +export class PublicKeyEncryptedSessionKeyPacket extends BasePacket { + static readonly tag: enums.packet.publicKeyEncryptedSessionKey; + private decrypt(keyPacket: SecretKeyPacket): void; // throws on error + private encrypt(keyPacket: PublicKeyPacket): void; // throws on error +} + +export class SymEncryptedSessionKey extends BasePacket { + static readonly tag: enums.packet.symEncryptedSessionKey; + private decrypt(passphrase: string): Promise; + private encrypt(passphrase: string, config?: Config): Promise; +} + +export class LiteralDataPacket extends BasePacket { + static readonly tag: enums.packet.literalData; + private getText(clone?: boolean): MaybeStream; + private getBytes(clone?: boolean): MaybeStream; + private setText(text: MaybeStream, format?: enums.literal); + private setBytes(bytes: MaybeStream, format: enums.literal); + private setFilename(filename: string); + private getFilename(): string; + private writeHeader(): Uint8Array; +} + +export class SymmetricallyEncryptedDataPacket extends BasePacket { + static readonly tag: enums.packet.symmetricallyEncryptedData; + private decrypt(sessionKeyAlgorithm: enums.symmetric, sessionKey: Uint8Array, config?: Config): void; + private encrypt(sessionKeyAlgorithm: enums.symmetric, sessionKey: Uint8Array, config?: Config): void; +} + +export class MarkerPacket extends BasePacket { + static readonly tag: enums.packet.marker; +} + +export class UserAttributePacket extends BasePacket { + static readonly tag: enums.packet.userAttribute; + private equals(packet: UserAttributePacket): boolean; +} + +export class OnePassSignaturePacket extends BasePacket { + static readonly tag: enums.packet.onePassSignature; + public correspondingSig?: Promise; + private verify: SignaturePacket['verify']; +} + +export class UserIDPacket extends BasePacket { + static readonly tag: enums.packet.userID; + public readonly name: string; + public readonly comment: string; + public readonly email: string; + public readonly userID: string; + static fromObject(userID: UserID): UserIDPacket; +} + +export class SignaturePacket extends BasePacket { + static readonly tag: enums.packet.signature; + public version: number; + public signatureType: enums.signature | null; + public hashAlgorithm: enums.hash | null; + public publicKeyAlgorithm: enums.publicKey | null; + public signatureData: null | Uint8Array; + public unhashedSubpackets: null | Uint8Array; + public signedHashValue: null | Uint8Array; + public created: Date | null; + public signatureExpirationTime: null | number; + public signatureNeverExpires: boolean; + public exportable: null | boolean; + public trustLevel: null | number; + public trustAmount: null | number; + public regularExpression: null | number; + public revocable: null | boolean; + public keyExpirationTime: null | number; + public keyNeverExpires: null | boolean; + public preferredSymmetricAlgorithms: enums.symmetric[] | null; + public revocationKeyClass: null | number; + public revocationKeyAlgorithm: null | enums.publicKey; + public revocationKeyFingerprint: null | Uint8Array; + public issuerKeyID: KeyID; + public notation: null | { [name: string]: string }; + public preferredHashAlgorithms: enums.hash[] | null; + public preferredCompressionAlgorithms: enums.compression[] | null; + public keyServerPreferences: null | number[]; + public preferredKeyServer: null | string; + public isPrimaryUserID: null | boolean; + public policyURI: null | string; + public keyFlags: Uint8Array | null; + public signersUserID: null | string; + public reasonForRevocationFlag: null | enums.reasonForRevocation; + public reasonForRevocationString: null | string; + public features: Uint8Array | null; + public signatureTargetPublicKeyAlgorithm: enums.publicKey | null; + public signatureTargetHashAlgorithm: enums.hash | null; + public signatureTargetHash: null | string; + public embeddedSignature: null | SignaturePacket; + public issuerKeyVersion: null | number; + public issuerFingerprint: null | Uint8Array; + public preferredAEADAlgorithms: enums.aead[] | null; + public verified: null | boolean; + public revoked: null | boolean; + public sign(key: AnySecretKeyPacket, data: Uint8Array, date?: Date, detached?: boolean): Promise; + public verify(key: AnyKeyPacket, signatureType: enums.signature, data: Uint8Array, date?: Date, detached?: boolean, config?: Config): Promise; // throws on error + public isExpired(date?: Date): boolean; + public getExpirationTime(): Date | typeof Infinity; +} + +export class TrustPacket extends BasePacket { + static readonly tag: enums.packet.trust; +} + +export type AnyPacket = BasePacket; +export type AnySecretKeyPacket = SecretKeyPacket | SecretSubkeyPacket; +export type AnyKeyPacket = BasePublicKeyPacket; + +type AllowedPackets = Map; // mapping to Packet classes (i.e. typeof LiteralDataPacket etc.) +export class PacketList extends Array { + static fromBinary(bytes: MaybeStream, allowedPackets: AllowedPackets, config?: Config): PacketList; // the packet types depend on`allowedPackets` + public read(bytes: MaybeStream, allowedPackets: AllowedPackets, config?: Config): void; + public write(): Uint8Array; + public filterByTag(...args: enums.packet[]): PacketList; + public indexOfTag(...tags: enums.packet[]): number[]; + public findPacket(tag: enums.packet): T | undefined; +} + +/* ############## v5 STREAM #################### */ + +type Data = Uint8Array | string; +interface BaseStream extends AsyncIterable { } +interface WebStream extends BaseStream { // copied+simplified version of ReadableStream from lib.dom.d.ts + readonly locked: boolean; getReader: Function; pipeThrough: Function; pipeTo: Function; tee: Function; + cancel(reason?: any): Promise; +} +interface NodeStream extends BaseStream { // copied+simplified version of ReadableStream from @types/node/index.d.ts + readable: boolean; pipe: Function; unpipe: Function; wrap: Function; + read(size?: number): string | Uint8Array; setEncoding(encoding: string): this; pause(): this; resume(): this; + isPaused(): boolean; unshift(chunk: string | Uint8Array): void; +} +type Stream = WebStream | NodeStream; +type MaybeStream = T | Stream; + +/* ############## v5 GENERAL #################### */ +type MaybeArray = T | Array; + +export interface UserID { name?: string; email?: string; comment?: string; } +export interface SessionKey { + data: Uint8Array; + algorithm: enums.symmetricNames; + aeadAlgorithm?: enums.aeadNames; +} + +export interface ReasonForRevocation { flag?: enums.reasonForRevocation, string?: string } + +interface EncryptOptions { + /** message to be encrypted as created by createMessage */ + message: Message>; + /** (optional) array of keys or single key, used to encrypt the message */ + encryptionKeys?: MaybeArray; + /** (optional) private keys for signing. If omitted message will not be signed */ + signingKeys?: MaybeArray; + /** (optional) array of passwords or a single password to encrypt the message */ + passwords?: MaybeArray; + /** (optional) session key */ + sessionKey?: SessionKey; + /** if the return values should be ascii armored or the message/signature objects */ + format?: 'armored' | 'binary' | 'object'; + /** (optional) if the signature should be detached (if true, signature will be added to returned object) */ + signature?: Signature; + /** (optional) encrypt as of a certain date */ + date?: Date; + /** (optional) use a key ID of 0 instead of the public key IDs */ + wildcard?: boolean; + /** (optional) Array of key IDs to use for signing. Each `signingKeyIDs[i]` corresponds to `signingKeys[i]` */ + signingKeyIDs?: MaybeArray; + /** (optional) Array of key IDs to use for encryption. Each `encryptionKeyIDs[i]` corresponds to `encryptionKeys[i]`*/ + encryptionKeyIDs?: MaybeArray; + /** (optional) Array of user IDs to sign with, e.g. { name:'Steve Sender', email:'steve@openpgp.org' } */ + signingUserIDs?: MaybeArray; + /** (optional) array of user IDs to encrypt for, e.g. { name:'Robert Receiver', email:'robert@openpgp.org' } */ + encryptionUserIDs?: MaybeArray; + config?: PartialConfig; +} + +interface DecryptOptions { + /** the message object with the encrypted data */ + message: Message>; + /** (optional) private keys with decrypted secret key data or session key */ + decryptionKeys?: MaybeArray; + /** (optional) passwords to decrypt the message */ + passwords?: MaybeArray; + /** (optional) session keys in the form: { data:Uint8Array, algorithm:String } */ + sessionKeys?: MaybeArray; + /** (optional) array of public keys or single key, to verify signatures */ + verificationKeys?: MaybeArray; + /** (optional) whether data decryption should fail if the message is not signed with the provided publicKeys */ + expectSigned?: boolean; + /** (optional) whether to return data as a string(Stream) or Uint8Array(Stream). If 'utf8' (the default), also normalize newlines. */ + format?: 'utf8' | 'binary'; + /** (optional) detached signature for verification */ + signature?: Signature; + /** (optional) use the given date for verification instead of the current time */ + date?: Date; + config?: PartialConfig; +} + +interface SignOptions { + message: CleartextMessage | Message>; + signingKeys?: MaybeArray; + format?: 'armored' | 'binary' | 'object'; + detached?: boolean; + signingKeyIDs?: MaybeArray; + date?: Date; + signingUserIDs?: MaybeArray; + config?: PartialConfig; +} + +interface VerifyOptions { + /** (cleartext) message object with signatures */ + message: CleartextMessage | Message>; + /** array of publicKeys or single key, to verify signatures */ + verificationKeys: MaybeArray; + /** (optional) whether verification should throw if the message is not signed with the provided publicKeys */ + expectSigned?: boolean; + /** (optional) whether to return data as a string(Stream) or Uint8Array(Stream). If 'utf8' (the default), also normalize newlines. */ + format?: 'utf8' | 'binary'; + /** (optional) detached signature for verification */ + signature?: Signature; + /** (optional) use the given date for verification instead of the current time */ + date?: Date; + config?: PartialConfig; +} + + +interface SerializedKeyPair { + privateKey: T; + publicKey: T; +} +interface KeyPair { + privateKey: PrivateKey; + publicKey: PublicKey; +} + +export type EllipticCurveName = 'ed25519' | 'curve25519' | 'p256' | 'p384' | 'p521' | 'secp256k1' | 'brainpoolP256r1' | 'brainpoolP384r1' | 'brainpoolP512r1'; + +interface KeyOptions { + userIDs: MaybeArray; + passphrase?: string; + type?: 'ecc' | 'rsa'; + curve?: EllipticCurveName; + rsaBits?: number; + keyExpirationTime?: number; + date?: Date; + subkeys?: SubkeyOptions[]; + format?: 'armored' | 'object' | 'binary'; + config?: PartialConfig; +} + +interface SubkeyOptions { + type?: 'ecc' | 'rsa'; + curve?: EllipticCurveName; + rsaBits?: number; + keyExpirationTime?: number; + date?: Date; + sign?: boolean; + config?: PartialConfig; +} + +export class KeyID { + bytes: string; + equals(keyID: KeyID, matchWildcard?: boolean): boolean; + toHex(): string; + static fromID(hex: string): KeyID; +} + +interface DecryptMessageResult { + data: MaybeStream; + signatures: VerificationResult[]; + filename: string; +} + +interface VerifyMessageResult { + data: MaybeStream; + signatures: VerificationResult[]; +} + + +/** + * Armor an OpenPGP binary packet block + */ +export function armor(messagetype: enums.armor, body: object, partindex: number, parttotal: number, config?: Config): string; + +/** + * DeArmor an OpenPGP armored message; verify the checksum and return the encoded bytes + */ +export function unarmor(input: string, config?: Config): Promise<{ text: string, data: Stream, type: enums.armor }>; + +/* ############## v5 ENUMS #################### */ + +export namespace enums { + function read(type: typeof armor, e: armor): armorNames; + function read(type: typeof compression, e: compression): compressionNames; + function read(type: typeof hash, e: hash): hashNames; + function read(type: typeof packet, e: packet): packetNames; + function read(type: typeof publicKey, e: publicKey): publicKeyNames; + function read(type: typeof symmetric, e: symmetric): symmetricNames; + function read(type: typeof keyStatus, e: keyStatus): keyStatusNames; + function read(type: typeof keyFlags, e: keyFlags): keyFlagsNames; + + export type armorNames = 'multipartSection' | 'multipartLast' | 'signed' | 'message' | 'publicKey' | 'privateKey'; + enum armor { + multipartSection = 0, + multipartLast = 1, + signed = 2, + message = 3, + publicKey = 4, + privateKey = 5, + signature = 6, + } + + enum reasonForRevocation { + noReason = 0, // No reason specified (key revocations or cert revocations) + keySuperseded = 1, // Key is superseded (key revocations) + keyCompromised = 2, // Key material has been compromised (key revocations) + keyRetired = 3, // Key is retired and no longer used (key revocations) + userIDInvalid = 32, // User ID information is no longer valid (cert revocations) + } + + export type compressionNames = 'uncompressed' | 'zip' | 'zlib' | 'bzip2'; + enum compression { + uncompressed = 0, + zip = 1, + zlib = 2, + bzip2 = 3, + } + + export type hashNames = 'md5' | 'sha1' | 'ripemd' | 'sha256' | 'sha384' | 'sha512' | 'sha224'; + enum hash { + md5 = 1, + sha1 = 2, + ripemd = 3, + sha256 = 8, + sha384 = 9, + sha512 = 10, + sha224 = 11, + } + + export type packetNames = 'publicKeyEncryptedSessionKey' | 'signature' | 'symEncryptedSessionKey' | 'onePassSignature' | 'secretKey' | 'publicKey' + | 'secretSubkey' | 'compressed' | 'symmetricallyEncrypted' | 'marker' | 'literal' | 'trust' | 'userID' | 'publicSubkey' | 'userAttribute' + | 'symEncryptedIntegrityProtected' | 'modificationDetectionCode' | 'AEADEncryptedDataPacket'; + enum packet { + publicKeyEncryptedSessionKey = 1, + signature = 2, + symEncryptedSessionKey = 3, + onePassSignature = 4, + secretKey = 5, + publicKey = 6, + secretSubkey = 7, + compressedData = 8, + symmetricallyEncryptedData = 9, + marker = 10, + literalData = 11, + trust = 12, + userID = 13, + publicSubkey = 14, + userAttribute = 17, + symEncryptedIntegrityProtectedData = 18, + modificationDetectionCode = 19, + aeadEncryptedData = 20, + } + + export type publicKeyNames = 'rsaEncryptSign' | 'rsaEncrypt' | 'rsaSign' | 'elgamal' | 'dsa' | 'ecdh' | 'ecdsa' | 'eddsa' | 'aedh' | 'aedsa'; + enum publicKey { + rsaEncryptSign = 1, + rsaEncrypt = 2, + rsaSign = 3, + elgamal = 16, + dsa = 17, + ecdh = 18, + ecdsa = 19, + eddsa = 22, + aedh = 23, + aedsa = 24, + } + + enum curve { + p256 = 'p256', + p384 = 'p384', + p521 = 'p521', + ed25519 = 'ed25519', + curve25519 = 'curve25519', + secp256k1 = 'secp256k1', + brainpoolP256r1 = 'brainpoolP256r1', + brainpoolP384r1 = 'brainpoolP384r1', + brainpoolP512r1 = 'brainpoolP512r1' + } + + export type symmetricNames = 'plaintext' | 'idea' | 'tripledes' | 'cast5' | 'blowfish' | 'aes128' | 'aes192' | 'aes256' | 'twofish'; + enum symmetric { + plaintext = 0, + idea = 1, + tripledes = 2, + cast5 = 3, + blowfish = 4, + aes128 = 7, + aes192 = 8, + aes256 = 9, + twofish = 10, + } + + export type keyStatusNames = 'invalid' | 'expired' | 'revoked' | 'valid' | 'noSelfCert'; + enum keyStatus { + invalid = 0, + expired = 1, + revoked = 2, + valid = 3, + noSelfCert = 4, + } + + export type keyFlagsNames = 'certifyKeys' | 'signData' | 'encryptCommunication' | 'encryptStorage' | 'splitPrivateKey' | 'authentication' + | 'sharedPrivateKey'; + enum keyFlags { + certifyKeys = 1, + signData = 2, + encryptCommunication = 4, + encryptStorage = 8, + splitPrivateKey = 16, + authentication = 32, + sharedPrivateKey = 128, + } + + enum signature { + binary = 0, + text = 1, + standalone = 2, + certGeneric = 16, + certPersona = 17, + certCasual = 18, + certPositive = 19, + certRevocation = 48, + subkeyBinding = 24, + keyBinding = 25, + key = 31, + keyRevocation = 32, + subkeyRevocation = 40, + timestamp = 64, + thirdParty = 80 + } + + export type aeadNames = 'eax' | 'ocb' | 'gcm'; + enum aead { + eax = 1, + ocb = 2, + experimentalGCM = 100 // Private algorithm + } + + export type literalFormatNames = 'utf8' | 'binary' | 'text' | 'mime' + enum literal { + binary = 98, + text = 116, + utf8 = 117, + mime = 109 + } +} + +// -----BEGIN ADDED BY FLOWCRYPT----- + +export function readToEnd(input: MaybeStream, concat?: (list: T[]) => T): Promise; + +export namespace util { + // we can't copy this from openpgp.js into our sources (i.e. util.ts) because of LGPL + function uint8ArrayToString(bytes: Uint8Array): string; + function uint8ArrayToHex(bytes: Uint8Array): string; +} + +export class Hash { + public reset(): Hash; + public process(data: Uint8Array): Hash; + public finish(): Hash; + public result: Uint8Array; +} + +export class Sha1 extends Hash {} +export class Sha256 extends Hash {} + +// -----END ADDED BY FLOWCRYPT----- diff --git a/Core/tooling/build.sh b/Core/tooling/build.sh index 04e6d50f8..9cfa9af0d 100755 --- a/Core/tooling/build.sh +++ b/Core/tooling/build.sh @@ -3,87 +3,12 @@ set -euxo pipefail # fix openpgp in node_modules +echo "Patching openpgp.js v5..." for f in openpgp.min.js openpgp.min.js.map openpgp.min.mjs openpgp.min.mjs.map openpgp.mjs; do if [ -f node_modules/openpgp/dist/$f ]; then rm -f node_modules/openpgp/dist/$f ; fi if [ -f node_modules/openpgp/dist/node/$f ]; then rm -f node_modules/openpgp/dist/node/$f ; fi done - -# MacOS sed is old BSD sed w/o "-i" (see https://ss64.com/osx/sed.html) -sed 's/openpgp.min.js/openpgp.js/g' node_modules/openpgp/package.json >node_modules/openpgp/package.json.tmp -cp -f node_modules/openpgp/package.json.tmp node_modules/openpgp/package.json -sed 's/openpgp.min.mjs/openpgp.mjs/g' node_modules/openpgp/package.json >node_modules/openpgp/package.json.tmp -cp -f node_modules/openpgp/package.json.tmp node_modules/openpgp/package.json - -extra_exports=" -// -----BEGIN ADDED BY FLOWCRYPT---- -exports.Hash = Hash; -exports.Sha1 = Sha1; -exports.Sha256 = Sha256; -exports.readToEnd = readToEnd; -exports.util = util; -// -----END ADDED BY FLOWCRYPT----- -" - -dist_js=node_modules/openpgp/dist/openpgp.js -tmp_js=${dist_js}.tmp -set +e -fc_added=$(grep 'BEGIN ADDED BY FLOWCRYPT' ${dist_js} | wc -l) -set -e -if [ $fc_added = 0 ]; then - n=$(grep -n 'exports.verify' ${dist_js} | cut -f1 -d':') - head -$n ${dist_js} >${tmp_js} - echo "$extra_exports" >>${tmp_js} - tail -n +$((n+1)) ${dist_js} >>${tmp_js} - mv -f ${tmp_js} ${dist_js} -fi - -dist_js=node_modules/openpgp/dist/node/openpgp.js -tmp_js=${dist_js}.tmp -set +e -fc_added=$(grep 'BEGIN ADDED BY FLOWCRYPT' ${dist_js} | wc -l) -set -e -if [ $fc_added = 0 ]; then - cp -f ${dist_js} ${tmp_js} - echo "$extra_exports" >>${tmp_js} - mv -f ${tmp_js} ${dist_js} -fi - -extra_defs=" -// -----BEGIN ADDED BY FLOWCRYPT----- - -export function readToEnd(input: MaybeStream, concat?: (list: T[]) => T): Promise; - -export namespace util { - // we can't copy this from openpgp.js into our sources (i.e. util.ts) because of LGPL - function uint8ArrayToString(bytes: Uint8Array): string; - function uint8ArrayToHex(bytes: Uint8Array): string; -} - -export class Hash { - public reset(): Hash; - public process(data: Uint8Array): Hash; - public finish(): Hash; - public result: Uint8Array; -} - -export class Sha1 extends Hash {} -export class Sha256 extends Hash {} - -// -----END ADDED BY FLOWCRYPT----- -" - -dist_ts=node_modules/openpgp/openpgp.d.ts -tmp_ts=${dist_ts}.tmp -set +e -fc_added=$(grep 'BEGIN ADDED BY FLOWCRYPT' ${dist_ts} | wc -l) -set -e -if [ $fc_added = 0 ]; then - cp -f ${dist_ts} ${tmp_ts} - echo "${extra_defs}" >>${tmp_ts} - # MacOS sed MacOS sed is old BSD sed w/o "-i" (see https://ss64.com/osx/sed.html) - sed 's/public isRevoked(signature: SignaturePacket/public isRevoked(signature?: SignaturePacket/g' ${tmp_ts} >${tmp_ts}.tmp - mv -f ${tmp_ts}.tmp ${dist_ts} -fi +cp -Rfv source/lib/openpgpjs-v5/* node_modules/openpgp/ # clean up rm -rf build/ts build/bundles build/final/* From b457d5f171ba220ea32a14816978cc95dab0d782 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 10 Feb 2022 01:56:35 +0200 Subject: [PATCH 126/179] wip --- Core/tooling/build.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/Core/tooling/build.sh b/Core/tooling/build.sh index 9cfa9af0d..61eb82274 100755 --- a/Core/tooling/build.sh +++ b/Core/tooling/build.sh @@ -9,6 +9,7 @@ for f in openpgp.min.js openpgp.min.js.map openpgp.min.mjs openpgp.min.mjs.map o if [ -f node_modules/openpgp/dist/node/$f ]; then rm -f node_modules/openpgp/dist/node/$f ; fi done cp -Rfv source/lib/openpgpjs-v5/* node_modules/openpgp/ +echo "Patching openpgp.js v5 - DONE." # clean up rm -rf build/ts build/bundles build/final/* From 7052b3cc36dde196ae3c8a8b82f92d5effa6a062 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 10 Feb 2022 02:01:12 +0200 Subject: [PATCH 127/179] wip --- Core/tooling/build.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Core/tooling/build.sh b/Core/tooling/build.sh index 61eb82274..92b353a45 100755 --- a/Core/tooling/build.sh +++ b/Core/tooling/build.sh @@ -9,6 +9,11 @@ for f in openpgp.min.js openpgp.min.js.map openpgp.min.mjs openpgp.min.mjs.map o if [ -f node_modules/openpgp/dist/node/$f ]; then rm -f node_modules/openpgp/dist/node/$f ; fi done cp -Rfv source/lib/openpgpjs-v5/* node_modules/openpgp/ +# MacOS sed is old BSD sed w/o "-i" (see https://ss64.com/osx/sed.html) +sed 's/openpgp.min.js/openpgp.js/g' node_modules/openpgp/package.json >node_modules/openpgp/package.json.tmp +cp -f node_modules/openpgp/package.json.tmp node_modules/openpgp/package.json +sed 's/openpgp.min.mjs/openpgp.mjs/g' node_modules/openpgp/package.json >node_modules/openpgp/package.json.tmp +cp -f node_modules/openpgp/package.json.tmp node_modules/openpgp/package.json echo "Patching openpgp.js v5 - DONE." # clean up From 1db53b37416d990af77138f51059dea16d6552ed Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 10 Feb 2022 10:18:18 +0200 Subject: [PATCH 128/179] cleanup and formatting --- Core/failed_tests.txt | 7 - .../types/openpgp/web-stream-tools/README.txt | 3 - .../web-stream-tools/node-conversions.d.ts | 6 - .../openpgp/web-stream-tools/reader.d.ts | 75 --------- .../openpgp/web-stream-tools/streams.d.ts | 145 ------------------ .../types/openpgp/web-stream-tools/util.d.ts | 21 --- .../openpgp/web-stream-tools/writer.d.ts | 65 -------- Core/source/mobile-interface/endpoints.ts | 131 ++++++++++++---- .../source/mobile-interface/validate-input.ts | 4 +- Core/source/test.ts | 7 - Core/source/test/test-utils.ts | 12 -- Core/tsconfig.json | 3 - 12 files changed, 103 insertions(+), 376 deletions(-) delete mode 100644 Core/failed_tests.txt delete mode 100644 Core/source/core/types/openpgp/web-stream-tools/README.txt delete mode 100644 Core/source/core/types/openpgp/web-stream-tools/node-conversions.d.ts delete mode 100644 Core/source/core/types/openpgp/web-stream-tools/reader.d.ts delete mode 100644 Core/source/core/types/openpgp/web-stream-tools/streams.d.ts delete mode 100644 Core/source/core/types/openpgp/web-stream-tools/util.d.ts delete mode 100644 Core/source/core/types/openpgp/web-stream-tools/writer.d.ts diff --git a/Core/failed_tests.txt b/Core/failed_tests.txt deleted file mode 100644 index 61474662a..000000000 --- a/Core/failed_tests.txt +++ /dev/null @@ -1,7 +0,0 @@ -[+] [parseKeys] Rejected promise returned by test -[+] [parseKeys - expiration and date last updated] Rejected promise returned by test -[+] [parseKeys - revoked] Rejected promise returned by test -[+] [generateKey] Rejected promise returned by test -[+] [encryptKey] Rejected promise returned by test -[+] [parseDecryptMsg compat mime-email-plain-with-pubkey] Rejected promise returned by test -[>>>] [verify plain-text signed message that you edited after signing. This invalidates the signature. With correct key. (fail: signature mismatch)] Rejected promise returned by test diff --git a/Core/source/core/types/openpgp/web-stream-tools/README.txt b/Core/source/core/types/openpgp/web-stream-tools/README.txt deleted file mode 100644 index 73544f12d..000000000 --- a/Core/source/core/types/openpgp/web-stream-tools/README.txt +++ /dev/null @@ -1,3 +0,0 @@ -web-stream-tools don't provide Typescript definitions at the moment. -So I've had to generate them myself using its source code and these instructions: -https://www.typescriptlang.org/docs/handbook/declaration-files/dts-from-js.html diff --git a/Core/source/core/types/openpgp/web-stream-tools/node-conversions.d.ts b/Core/source/core/types/openpgp/web-stream-tools/node-conversions.d.ts deleted file mode 100644 index 2bbcb2da2..000000000 --- a/Core/source/core/types/openpgp/web-stream-tools/node-conversions.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -/** - * Web / node stream conversion functions - * From https://github.com/gwicke/node-web-streams - */ -export let nodeToWeb: any; -export let webToNode: any; diff --git a/Core/source/core/types/openpgp/web-stream-tools/reader.d.ts b/Core/source/core/types/openpgp/web-stream-tools/reader.d.ts deleted file mode 100644 index 318b344ce..000000000 --- a/Core/source/core/types/openpgp/web-stream-tools/reader.d.ts +++ /dev/null @@ -1,75 +0,0 @@ -/** - * A wrapper class over the native ReadableStreamDefaultReader. - * This additionally implements pushing back data on the stream, which - * lets us implement peeking and a host of convenience functions. - * It also lets you read data other than streams, such as a Uint8Array. - * @class - */ -export function Reader(input: any): void; -export class Reader { - /** - * A wrapper class over the native ReadableStreamDefaultReader. - * This additionally implements pushing back data on the stream, which - * lets us implement peeking and a host of convenience functions. - * It also lets you read data other than streams, such as a Uint8Array. - * @class - */ - constructor(input: any); - stream: any; - _read: any; - _releaseLock: () => void; - _cancel: any; - /** - * Read a chunk of data. - * @returns {Promise} Either { done: false, value: Uint8Array | String } or { done: true, value: undefined } - * @async - */ - read(): Promise; - /** - * Allow others to read the stream. - */ - releaseLock(): void; - /** - * Cancel the stream. - */ - cancel(reason: any): any; - /** - * Read up to and including the first \n character. - * @returns {Promise} - * @async - */ - readLine(): Promise; - /** - * Read a single byte/character. - * @returns {Promise} - * @async - */ - readByte(): Promise; - /** - * Read a specific amount of bytes/characters, unless the stream ends before that amount. - * @returns {Promise} - * @async - */ - readBytes(length: any): Promise; - /** - * Peek (look ahead) a specific amount of bytes/characters, unless the stream ends before that amount. - * @returns {Promise} - * @async - */ - peekBytes(length: any): Promise; - /** - * Push data to the front of the stream. - * Data must have been read in the last call to read*. - * @param {...(Uint8Array|String|Undefined)} values - */ - unshift(...values: (Uint8Array | string | undefined)[]): void; - /** - * Read the stream to the end and return its contents, concatenated by the join function (defaults to streams.concat). - * @param {Function} join - * @returns {Promise} the return value of join() - * @async - */ - readToEnd(join?: Function): Promise; - [externalBuffer]: any; -} -export const externalBuffer: unique symbol; diff --git a/Core/source/core/types/openpgp/web-stream-tools/streams.d.ts b/Core/source/core/types/openpgp/web-stream-tools/streams.d.ts deleted file mode 100644 index 0718da19e..000000000 --- a/Core/source/core/types/openpgp/web-stream-tools/streams.d.ts +++ /dev/null @@ -1,145 +0,0 @@ -export let ReadableStream: { - new (underlyingSource?: UnderlyingSource, strategy?: QueuingStrategy): ReadableStream; - prototype: ReadableStream; -}; -export let WritableStream: { - new (underlyingSink?: UnderlyingSink, strategy?: QueuingStrategy): WritableStream; - prototype: WritableStream; -}; -export let TransformStream: { - new (transformer?: Transformer, writableStrategy?: QueuingStrategy, readableStrategy?: QueuingStrategy): TransformStream; - prototype: TransformStream; -}; -import { ArrayStream } from "./writer"; -export function loadStreamsPonyfill(): Promise; -import { isStream } from "./util"; -import { isArrayStream } from "./util"; -import { isUint8Array } from "./util"; -/** - * Convert data to Stream - * @param {ReadableStream|Uint8array|String} input data to convert - * @returns {ReadableStream} Converted data - */ -export function toStream(input: ReadableStream | Uint8array | string): ReadableStream; -export let toPonyfillReadable: any; -export let toNativeReadable: any; -import { concatUint8Array } from "./util"; -/** - * Concat a list of Streams - * @param {Array} list Array of Uint8Arrays/Strings/Streams to concatenate - * @returns {ReadableStream} Concatenated list - */ -export function concatStream(list: Array): ReadableStream; -/** - * Concat a list of Uint8Arrays, Strings or Streams - * The caller should not mix Uint8Arrays with Strings, but may mix Streams with non-Streams. - * @param {Array} Array of Uint8Arrays/Strings/Streams to concatenate - * @returns {Uint8array|String|ReadableStream} Concatenated array - */ -export function concat(list: any): Uint8array | string | ReadableStream; -/** - * Get a Reader - * @param {ReadableStream|Uint8array|String} input - * @returns {Reader} - */ -export function getReader(input: ReadableStream | Uint8array | string): Reader; -/** - * Get a Writer - * @param {WritableStream} input - * @returns {Writer} - */ -export function getWriter(input: WritableStream): Writer; -/** - * Pipe a readable stream to a writable stream. Don't throw on input stream errors, but forward them to the output stream. - * @param {ReadableStream|Uint8array|String} input - * @param {WritableStream} target - * @param {Object} (optional) options - * @returns {Promise} Promise indicating when piping has finished (input stream closed or errored) - * @async - */ -export function pipe(input: ReadableStream | Uint8array | string, target: WritableStream, { preventClose, preventAbort, preventCancel }?: any): Promise; -/** - * Pipe a readable stream through a transform stream. - * @param {ReadableStream|Uint8array|String} input - * @param {Object} (optional) options - * @returns {ReadableStream} transformed stream - */ -export function transformRaw(input: ReadableStream | Uint8array | string, options: any): ReadableStream; -/** - * Transform a stream using helper functions which are called on each chunk, and on stream close, respectively. - * @param {ReadableStream|Uint8array|String} input - * @param {Function} process - * @param {Function} finish - * @returns {ReadableStream|Uint8array|String} - */ -export function transform(input: ReadableStream | Uint8array | string, process?: Function, finish?: Function): ReadableStream | Uint8array | string; -/** - * Transform a stream using a helper function which is passed a readable and a writable stream. - * This function also maintains the possibility to cancel the input stream, - * and does so on cancelation of the output stream, despite cancelation - * normally being impossible when the input stream is being read from. - * @param {ReadableStream|Uint8array|String} input - * @param {Function} fn - * @returns {ReadableStream} - */ -export function transformPair(input: ReadableStream | Uint8array | string, fn: Function): ReadableStream; -/** - * Parse a stream using a helper function which is passed a Reader. - * The reader additionally has a remainder() method which returns a - * stream pointing to the remainder of input, and is linked to input - * for cancelation. - * @param {ReadableStream|Uint8array|String} input - * @param {Function} fn - * @returns {Any} the return value of fn() - */ -export function parse(input: ReadableStream | Uint8array | string, fn: Function): Any; -/** - * Clone a Stream for reading it twice. The input stream can still be read after clone()ing. - * Reading from the clone will pull from the input stream. - * The input stream will only be canceled if both the clone and the input stream are canceled. - * @param {ReadableStream|Uint8array|String} input - * @returns {ReadableStream|Uint8array|String} cloned input - */ -export function clone(input: ReadableStream | Uint8array | string): ReadableStream | Uint8array | string; -/** - * Clone a Stream for reading it twice. Data will arrive at the same rate as the input stream is being read. - * Reading from the clone will NOT pull from the input stream. Data only arrives when reading the input stream. - * The input stream will NOT be canceled if the clone is canceled, only if the input stream are canceled. - * If the input stream is canceled, the clone will be errored. - * @param {ReadableStream|Uint8array|String} input - * @returns {ReadableStream|Uint8array|String} cloned input - */ -export function passiveClone(input: ReadableStream | Uint8array | string): ReadableStream | Uint8array | string; -/** - * Return a stream pointing to a part of the input stream. - * @param {ReadableStream|Uint8array|String} input - * @returns {ReadableStream|Uint8array|String} clone - */ -export function slice(input: ReadableStream | Uint8array | string, begin?: number, end?: number): ReadableStream | Uint8array | string; -/** - * Read a stream to the end and return its contents, concatenated by the join function (defaults to concat). - * @param {ReadableStream|Uint8array|String} input - * @param {Function} join - * @returns {Promise} the return value of join() - * @async - */ -export function readToEnd(input: ReadableStream | Uint8array | string, join?: Function): Promise; -/** - * Cancel a stream. - * @param {ReadableStream|Uint8array|String} input - * @param {Any} reason - * @returns {Promise} indicates when the stream has been canceled - * @async - */ -export function cancel(input: ReadableStream | Uint8array | string, reason: Any): Promise; -/** - * Convert an async function to an ArrayStream. When the function returns, its return value is written to the stream. - * @param {Function} fn - * @returns {ArrayStream} - */ -export function fromAsync(fn: Function): ArrayStream; -import { nodeToWeb } from "./node-conversions"; -import { webToNode } from "./node-conversions"; -import { Reader } from "./reader"; -import { Writer } from "./writer"; -export { ArrayStream, isStream, isArrayStream, isUint8Array, concatUint8Array, nodeToWeb, webToNode }; diff --git a/Core/source/core/types/openpgp/web-stream-tools/util.d.ts b/Core/source/core/types/openpgp/web-stream-tools/util.d.ts deleted file mode 100644 index dfcb8efcd..000000000 --- a/Core/source/core/types/openpgp/web-stream-tools/util.d.ts +++ /dev/null @@ -1,21 +0,0 @@ -export const isNode: boolean; -/** - * Check whether data is a Stream, and if so of which type - * @param {Any} input data to check - * @returns {'web'|'ponyfill'|'node'|'array'|'web-like'|false} - */ -export function isStream(input: Any): 'web' | 'ponyfill' | 'node' | 'array' | 'web-like' | false; -import { isArrayStream } from "./writer"; -/** - * Check whether data is a Uint8Array - * @param {Any} input data to check - * @returns {Boolean} - */ -export function isUint8Array(input: Any): boolean; -/** - * Concat Uint8Arrays - * @param {Array} Array of Uint8Arrays to concatenate - * @returns {Uint8array} Concatenated array - */ -export function concatUint8Array(arrays: any): Uint8array; -export { isArrayStream }; diff --git a/Core/source/core/types/openpgp/web-stream-tools/writer.d.ts b/Core/source/core/types/openpgp/web-stream-tools/writer.d.ts deleted file mode 100644 index ff81d1df2..000000000 --- a/Core/source/core/types/openpgp/web-stream-tools/writer.d.ts +++ /dev/null @@ -1,65 +0,0 @@ -export class ArrayStream extends Array { - constructor(); - getReader(): { - read: () => Promise<{ - value: any; - done: boolean; - }>; - }; - readToEnd(join: any): Promise; - clone(): ArrayStream; - [doneWritingPromise]: any; - [doneWritingResolve]: any; - [doneWritingReject]: any; - [readingIndex]: number; -} -/** - * Check whether data is an ArrayStream - * @param {Any} input data to check - * @returns {boolean} - */ -export function isArrayStream(input: Any): boolean; -/** - * A wrapper class over the native WritableStreamDefaultWriter. - * It also lets you "write data to" array streams instead of streams. - * @class - */ -export function Writer(input: any): any; -export class Writer { - /** - * A wrapper class over the native WritableStreamDefaultWriter. - * It also lets you "write data to" array streams instead of streams. - * @class - */ - constructor(input: any); - stream: any; - /** - * Write a chunk of data. - * @returns {Promise} - * @async - */ - write(chunk: any): Promise; - /** - * Close the stream. - * @returns {Promise} - * @async - */ - close(): Promise; - /** - * Error the stream. - * @returns {Promise} - * @async - */ - abort(reason: any): Promise; - /** - * Release the writer's lock. - * @returns {undefined} - * @async - */ - releaseLock(): undefined; -} -export const doneWritingPromise: unique symbol; -declare const doneWritingResolve: unique symbol; -declare const doneWritingReject: unique symbol; -declare const readingIndex: unique symbol; -export {}; diff --git a/Core/source/mobile-interface/endpoints.ts b/Core/source/mobile-interface/endpoints.ts index 75fec0ca5..f020b751c 100644 --- a/Core/source/mobile-interface/endpoints.ts +++ b/Core/source/mobile-interface/endpoints.ts @@ -32,7 +32,9 @@ export class Endpoints { Store.keyCacheWipe(); // generateKey may be used when changing major settings, wipe cache to prevent dated results const { passphrase, userIds, variant } = ValidateInput.generateKey(uncheckedReq); if (passphrase.length < 12) { - throw new Error('Pass phrase length seems way too low! Pass phrase strength should be properly checked before encrypting a key.'); + throw new Error( + 'Pass phrase length seems way too low! ' + + 'Pass phrase strength should be properly checked before encrypting a key.'); } let k = await PgpKey.create(userIds, variant, passphrase); return fmtRes({ key: await PgpKey.details(await PgpKey.read(k.private)) }); @@ -42,23 +44,40 @@ export class Endpoints { const req = ValidateInput.composeEmail(uncheckedReq); const mimeHeaders: RichHeaders = { to: req.to, from: req.from, subject: req.subject, cc: req.cc, bcc: req.bcc }; if (req.replyToMimeMsg) { - const previousMsg = await Mime.decode(Buf.fromUtfStr((req.replyToMimeMsg.substr(0, 10000).split('\n\n')[0] || '') + `\n\nno content`)); + const previousMsg = await Mime.decode(Buf.fromUtfStr((req.replyToMimeMsg.substr(0, 10000) + .split('\n\n')[0] || '') + `\n\nno content`)); const replyHeaders = Mime.replyHeaders(previousMsg); mimeHeaders['in-reply-to'] = replyHeaders['in-reply-to']; mimeHeaders['references'] = replyHeaders['references']; } if (req.format === 'plain') { - const atts = (req.atts || []).map(({ name, type, base64 }) => new Att({ name, type, data: Buf.fromBase64Str(base64) })); - return fmtRes({}, Buf.fromUtfStr(await Mime.encode({ 'text/plain': req.text, 'text/html': req.html }, mimeHeaders, atts))); + const atts = (req.atts || []).map(({ name, type, base64 }) => + new Att({ name, type, data: Buf.fromBase64Str(base64) })); + return fmtRes({}, Buf.fromUtfStr(await Mime.encode( + { 'text/plain': req.text, 'text/html': req.html }, mimeHeaders, atts))); } else if (req.format === 'encrypt-inline') { const encryptedAtts: Att[] = []; for (const att of req.atts || []) { - const encryptedAtt = await PgpMsg.encrypt({ pubkeys: req.pubKeys, data: Buf.fromBase64Str(att.base64), filename: att.name, armor: false }) as Uint8Array; - encryptedAtts.push(new Att({ name: `${att.name}.pgp`, type: 'application/pgp-encrypted', data: encryptedAtt })) + const encryptedAtt = await PgpMsg.encrypt({ + pubkeys: req.pubKeys, + data: Buf.fromBase64Str(att.base64), + filename: att.name, + armor: false + }) as Uint8Array; + encryptedAtts.push(new Att({ + name: `${att.name}.pgp`, + type: 'application/pgp-encrypted', + data: encryptedAtt + })) } const signingPrv = await getSigningPrv(req); - const encrypted = await PgpMsg.encrypt({ pubkeys: req.pubKeys, signingPrv, data: Buf.fromUtfStr(req.text), armor: true }) as string; + const encrypted = await PgpMsg.encrypt({ + pubkeys: req.pubKeys, + signingPrv, + data: Buf.fromUtfStr(req.text), + armor: true + }) as string; return fmtRes({}, Buf.fromUtfStr(await Mime.encode({ 'text/plain': encrypted }, mimeHeaders, encryptedAtts))); } else { throw new Error(`Unknown format: ${req.format}`); @@ -67,13 +86,15 @@ export class Endpoints { public encryptMsg = async (uncheckedReq: any, data: Buffers): Promise => { const req = ValidateInput.encryptMsg(uncheckedReq); - const encrypted = await PgpMsg.encrypt({ pubkeys: req.pubKeys, pwd: req.msgPwd, data: Buf.concat(data), armor: true }) as string; + const encrypted = await PgpMsg.encrypt( + { pubkeys: req.pubKeys, pwd: req.msgPwd, data: Buf.concat(data), armor: true }) as string; return fmtRes({}, Buf.fromUtfStr(encrypted)); } public encryptFile = async (uncheckedReq: any, data: Buffers): Promise => { const req = ValidateInput.encryptFile(uncheckedReq); - const encrypted = await PgpMsg.encrypt({ pubkeys: req.pubKeys, data: Buf.concat(data), filename: req.name, armor: false }) as Uint8Array; + const encrypted = await PgpMsg.encrypt( + { pubkeys: req.pubKeys, data: Buf.concat(data), filename: req.name, armor: false }) as Uint8Array; return fmtRes({}, encrypted); } @@ -93,38 +114,73 @@ export class Endpoints { const sequentialProcessedBlocks: MsgBlock[] = []; // contains decrypted or otherwise formatted data for (const rawBlock of rawBlocks) { if ((rawBlock.type === 'signedMsg' || rawBlock.type === 'signedHtml') && rawBlock.signature) { - const verify = await PgpMsg.verifyDetached({ sigText: Buf.fromUtfStr(rawBlock.signature), plaintext: Buf.with(rawSigned || rawBlock.content), verificationPubkeys: verificationPubkeys }); + const verify = await PgpMsg.verifyDetached({ + sigText: Buf.fromUtfStr(rawBlock.signature), + plaintext: Buf.with(rawSigned || rawBlock.content), + verificationPubkeys: verificationPubkeys + }); if (rawBlock.type === 'signedHtml') { - sequentialProcessedBlocks.push({ type: 'verifiedMsg', content: Xss.htmlSanitizeKeepBasicTags(rawBlock.content.toString()), verifyRes: verify, complete: true }); + sequentialProcessedBlocks.push({ + type: 'verifiedMsg', + content: Xss.htmlSanitizeKeepBasicTags(rawBlock.content.toString()), + verifyRes: verify, + complete: true + }); } else { // text - sequentialProcessedBlocks.push({ type: 'verifiedMsg', content: Str.asEscapedHtml(rawBlock.content.toString()), verifyRes: verify, complete: true }); + sequentialProcessedBlocks.push({ + type: 'verifiedMsg', + content: Str.asEscapedHtml(rawBlock.content.toString()), + verifyRes: verify, + complete: true + }); } } else if (rawBlock.type === 'encryptedMsg' || rawBlock.type === 'signedMsg') { - const decryptRes = await PgpMsg.decrypt({ kisWithPp, msgPwd, encryptedData: Buf.with(rawBlock.content), verificationPubkeys }); + const decryptRes = await PgpMsg.decrypt({ + kisWithPp, + msgPwd, + encryptedData: Buf.with(rawBlock.content), + verificationPubkeys + }); if (decryptRes.success) { if (decryptRes.isEncrypted) { - const formatted = await MsgBlockParser.fmtDecryptedAsSanitizedHtmlBlocks(decryptRes.content, decryptRes.signature); + const formatted = await MsgBlockParser.fmtDecryptedAsSanitizedHtmlBlocks( + decryptRes.content, decryptRes.signature); sequentialProcessedBlocks.push(...formatted.blocks); subject = formatted.subject || subject; } else { // treating as text, converting to html - what about plain signed html? This could produce html tags - // although hopefully, that would, typically, result in the `(rawBlock.type === 'signedMsg' || rawBlock.type === 'signedHtml')` block above - // the only time I can imagine it screwing up down here is if it was a signed-only message that was actually fully armored (text not visible) with a mime msg inside + // although hopefully, that would, typically, result in the + // `(rawBlock.type === 'signedMsg' || rawBlock.type === 'signedHtml')` block above + // the only time I can imagine it screwing up down here is if it was a signed-only message + // that was actually fully armored (text not visible) with a mime msg inside // ... -> in which case the user would I think see full mime content? - sequentialProcessedBlocks.push({ type: 'verifiedMsg', content: Str.asEscapedHtml(decryptRes.content.toUtfStr()), complete: true, verifyRes: decryptRes.signature }); + sequentialProcessedBlocks.push({ + type: 'verifiedMsg', + content: Str.asEscapedHtml(decryptRes.content.toUtfStr()), + complete: true, + verifyRes: decryptRes.signature + }); } } else { decryptRes.message = undefined; sequentialProcessedBlocks.push({ type: 'decryptErr', - content: decryptRes.error.type === DecryptErrTypes.noMdc ? decryptRes.content!.toUtfStr() : rawBlock.content.toString(), + content: decryptRes.error.type === DecryptErrTypes.noMdc + ? decryptRes.content!.toUtfStr() : rawBlock.content.toString(), decryptErr: decryptRes, complete: true }); } - } else if (rawBlock.type === 'encryptedAtt' && rawBlock.attMeta && /^(0x)?[A-Fa-f0-9]{16,40}\.asc\.pgp$/.test(rawBlock.attMeta.name || '')) { + } else if (rawBlock.type === 'encryptedAtt' + && rawBlock.attMeta + && /^(0x)?[A-Fa-f0-9]{16,40}\.asc\.pgp$/.test(rawBlock.attMeta.name || '')) { // encrypted pubkey attached - const decryptRes = await PgpMsg.decrypt({ kisWithPp, msgPwd, encryptedData: Buf.with(rawBlock.attMeta.data || ''), verificationPubkeys }); + const decryptRes = await PgpMsg.decrypt({ + kisWithPp, + msgPwd, + encryptedData: Buf.with(rawBlock.attMeta.data || ''), + verificationPubkeys + }); if (decryptRes.content) { sequentialProcessedBlocks.push({ type: 'publicKey', content: decryptRes.content.toString(), complete: true }); } else { @@ -161,7 +217,12 @@ export class Endpoints { const { keys } = await PgpKey.normalize(block.content); if (keys.length) { for (const pub of keys) { - blocks.push({ type: 'publicKey', content: pub.armor(), complete: true, keyDetails: await PgpKey.details(pub) }); + blocks.push({ + type: 'publicKey', + content: pub.armor(), + complete: true, + keyDetails: await PgpKey.details(pub) + }); } } else { blocks.push({ @@ -192,9 +253,14 @@ export class Endpoints { return fmtRes({ text, replyType, subject }, Buf.fromUtfStr(blocks.map(b => JSON.stringify(b)).join('\n'))); } - public decryptFile = async (uncheckedReq: any, data: Buffers, verificationPubkeys?: string[]): Promise => { + public decryptFile = async (uncheckedReq: any, data: Buffers, verificationPubkeys?: string[]): + Promise => { const { keys: kisWithPp, msgPwd } = ValidateInput.decryptFile(uncheckedReq); - const decryptRes = await PgpMsg.decrypt({ kisWithPp, encryptedData: Buf.concat(data), msgPwd, verificationPubkeys }); + const decryptRes = await PgpMsg.decrypt({ + kisWithPp, + encryptedData: Buf.concat(data), + msgPwd, verificationPubkeys + }); if (!decryptRes.success) { decryptRes.message = undefined; decryptRes.content = undefined; @@ -211,9 +277,11 @@ export class Endpoints { public zxcvbnStrengthBar = async (uncheckedReq: any): Promise => { const r = ValidateInput.zxcvbnStrengthBar(uncheckedReq); if (r.purpose === 'passphrase') { - if (typeof r.guesses === 'number') { // the host has a port of zxcvbn and already knows amount of guesses per password + if (typeof r.guesses === 'number') { + // the host has a port of zxcvbn and already knows amount of guesses per password return fmtRes(PgpPwd.estimateStrength(r.guesses)); - } else if (typeof r.value === 'string') { // host does not have zxcvbn, let's use zxcvbn-js to estimate guesses + } else if (typeof r.value === 'string') { + // host does not have zxcvbn, let's use zxcvbn-js to estimate guesses type FakeWindow = { zxcvbn: (password: string, weakWords: string[]) => { guesses: number } }; if (typeof (window as unknown as FakeWindow).zxcvbn !== 'function') { throw new Error("window.zxcvbn missing in js") @@ -263,9 +331,11 @@ export class Endpoints { } public decryptKey = async (uncheckedReq: any): Promise => { - Store.keyCacheWipe(); // decryptKey may be used when changing major settings, wipe cache to prevent dated results + // decryptKey may be used when changing major settings, wipe cache to prevent dated results + Store.keyCacheWipe(); const { armored, passphrases } = ValidateInput.decryptKey(uncheckedReq); - if (passphrases.length !== 1) { // todo - refactor endpoint decryptKey api to accept a single pp + if (passphrases.length !== 1) { + // todo - refactor endpoint decryptKey api to accept a single pp throw new Error(`decryptKey: Can only accept exactly 1 pass phrase for decrypt, received: ${passphrases.length}`); } const key = await readArmoredKeyOrThrow(armored); @@ -276,11 +346,14 @@ export class Endpoints { } public encryptKey = async (uncheckedReq: any): Promise => { - Store.keyCacheWipe(); // encryptKey may be used when changing major settings, wipe cache to prevent dated results + // encryptKey may be used when changing major settings, wipe cache to prevent dated results + Store.keyCacheWipe(); const { armored, passphrase } = ValidateInput.encryptKey(uncheckedReq); const privateKey = await readArmoredKeyOrThrow(armored) as PrivateKey; if (!passphrase || passphrase.length < 12) { // last resort check, this should never happen - throw new Error('Pass phrase length seems way too low! Pass phrase strength should be properly checked before encrypting a key.'); + throw new Error( + 'Pass phrase length seems way too low! ' + + 'Pass phrase strength should be properly checked before encrypting a key.'); } const encryptedKey = await encryptKey({privateKey, passphrase}); return fmtRes({ encryptedKey: encryptedKey.armor() }); diff --git a/Core/source/mobile-interface/validate-input.ts b/Core/source/mobile-interface/validate-input.ts index bfa3e0694..8fcd1e12e 100644 --- a/Core/source/mobile-interface/validate-input.ts +++ b/Core/source/mobile-interface/validate-input.ts @@ -179,8 +179,6 @@ const hasProp = (v: Obj, name: string, type: 'string[]' | 'string[]?' | 'object' export const readArmoredKeyOrThrow = async (armored: string) => { const key = await readKey({armoredKey: armored}); - if (!key) { - throw new Error('No key found'); - } + if (!key) throw new Error('No key found'); return key; } diff --git a/Core/source/test.ts b/Core/source/test.ts index b64e2786a..27e3343ab 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -404,13 +404,6 @@ ava.default('parseKeys - expiration and date last updated', async t => { } ] }; - //expect(json.keyDetails[0].ids[0]).to.deep.equal(expected.keyDetails[0].ids[0]); - //expect(json.keyDetails[0].ids[1]).to.deep.equal(expected.keyDetails[0].ids[1]); - //expect(json.keyDetails[0].algo).to.deep.equal(expected.keyDetails[0].algo); - //expect(json.keyDetails[0].created).to.equal(expected.keyDetails[0].created); - //expect(json.keyDetails[0].lastModified).to.equal(expected.keyDetails[0].lastModified); - //expect(json.keyDetails[0].public).to.equal(expected.keyDetails[0].public); - //expect(json.keyDetails[0]).to.deep.equal(expected.keyDetails[0]); expect(json).to.deep.equal(expected); expectNoData(data); t.pass(); diff --git a/Core/source/test/test-utils.ts b/Core/source/test/test-utils.ts index 33983a969..396329d01 100644 --- a/Core/source/test/test-utils.ts +++ b/Core/source/test/test-utils.ts @@ -86,18 +86,6 @@ export const expectData = (_data: Uint8Array, type?: 'armoredMsg' | 'msgBlocks' for (let i = 0; i < expectedBlocks.length; i++) { const a = blocks[i]; const b = expectedBlocks[i]; - //if (i == 1) { - // expect(a.type).to.be.equal(b.type); - // expect(a.content).to.be.equal(b.content); - // expect(a.complete).to.be.equal(b.complete); - // expect(a.keyDetails.public).to.be.equal(b.keyDetails.public); - // expect(a.keyDetails.algo).to.deep.equal(b.keyDetails.algo); - // expect(a.keyDetails.created).to.deep.equal(b.keyDetails.created); - // expect(a.keyDetails.lastModified).to.be.equal(b.keyDetails.lastModified); - // expect(a.keyDetails.revoked).to.deep.equal(b.keyDetails.revoked); - // expect(a.keyDetails.ids).to.deep.equal(b.keyDetails.ids); - // expect(a.keyDetails.users).to.deep.equal(b.keyDetails.users); - //} expect(a).to.deep.equal(b, `block ${i} failed cmp check`); } } else if (type === "binary") { diff --git a/Core/tsconfig.json b/Core/tsconfig.json index c02ecbc9a..e98014558 100644 --- a/Core/tsconfig.json +++ b/Core/tsconfig.json @@ -19,9 +19,6 @@ "checkJs": false, "outDir": "./build/ts", "baseUrl": "./", - "paths": { - "openpgp": ["source/lib"] - }, "traceResolution": false, "typeRoots": [ "./source/core/types/", From e133ec1b1bd4f5eb14374412c6e4b1638ec449eb Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 10 Feb 2022 12:48:22 +0200 Subject: [PATCH 129/179] comment about key.getExpirationTime() --- Core/source/core/pgp-key.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index 42ddf2bf3..69f5ede17 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -356,6 +356,8 @@ export class PgpKey { * This is used to figure out how recently was key updated, and if one key is newer than other. */ public static lastSig = async (key: Key): Promise => { + // no longer works, need some alternate solution + // discussion is in progress: https://github.com/openpgpjs/openpgpjs/discussions/1491 await key.getExpirationTime(); // will force all sigs to be verified const allSignatures: SignaturePacket[] = []; for (const user of key.users) { From 86e74d385c7582638d05602c4361a7fb27ffd6e1 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 10 Feb 2022 21:17:41 +0200 Subject: [PATCH 130/179] refactor (algoInfo as any) --- Core/source/core/pgp-key.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index 69f5ede17..a36d6193b 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -319,8 +319,12 @@ export class PgpKey { public static details = async (k: Key): Promise => { const keys = k.getKeys(); const algoInfo = k.keyPacket.getAlgorithmInfo(); - const algo = { algorithm: algoInfo.algorithm, bits: algoInfo.bits, curve: (algoInfo as any).curve, - algorithmId: enums.publicKey[algoInfo.algorithm] }; + const algo = { + algorithm: algoInfo.algorithm, + bits: algoInfo.bits, + curve: algoInfo.curve, + algorithmId: enums.publicKey[algoInfo.algorithm] + }; const created = k.keyPacket.created.getTime() / 1000; const exp = await k.getExpirationTime(); const expiration = exp === Infinity || !exp ? undefined : (exp as Date).getTime() / 1000; From 706e624efea6b20451557523b55fa7e9ebd59d5b Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 10 Feb 2022 21:22:55 +0200 Subject: [PATCH 131/179] remove unnecessary code --- Core/source/core/pgp-hash.ts | 33 ----------------------- Core/source/lib/openpgpjs-v5/openpgp.d.ts | 11 -------- 2 files changed, 44 deletions(-) delete mode 100644 Core/source/core/pgp-hash.ts diff --git a/Core/source/core/pgp-hash.ts b/Core/source/core/pgp-hash.ts deleted file mode 100644 index 933e3b265..000000000 --- a/Core/source/core/pgp-hash.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* © 2016-present FlowCrypt a. s. Limitations apply. Contact human@flowcrypt.com */ - -'use strict'; - -import { util, Sha1, Sha256 } from 'openpgp'; -import { Buf } from './buf'; - -export class PgpHash { - - public static sha1UtfStr = async (string: string): Promise => { - return util.uint8ArrayToHex((new Sha1()).process(Buf.fromUtfStr(string)).finish().result); - } - - public static sha256UtfStr = async (string: string) => { - return util.uint8ArrayToHex((new Sha256()).process(Buf.fromUtfStr(string)).finish().result); - } - - public static doubleSha1Upper = async (string: string) => { - return (await PgpHash.sha1UtfStr(await PgpHash.sha1UtfStr(string))).toUpperCase(); - } - - public static challengeAnswer = async (answer: string) => { - return await PgpHash.cryptoHashSha256Loop(answer); - } - - private static cryptoHashSha256Loop = async (string: string, times = 100000) => { - for (let i = 0; i < times; i++) { - string = await PgpHash.sha256UtfStr(string); - } - return string; - } - -} diff --git a/Core/source/lib/openpgpjs-v5/openpgp.d.ts b/Core/source/lib/openpgpjs-v5/openpgp.d.ts index 066818dba..4938ced40 100644 --- a/Core/source/lib/openpgpjs-v5/openpgp.d.ts +++ b/Core/source/lib/openpgpjs-v5/openpgp.d.ts @@ -895,17 +895,6 @@ export function readToEnd(input: MaybeStream, concat?: (list: export namespace util { // we can't copy this from openpgp.js into our sources (i.e. util.ts) because of LGPL function uint8ArrayToString(bytes: Uint8Array): string; - function uint8ArrayToHex(bytes: Uint8Array): string; } -export class Hash { - public reset(): Hash; - public process(data: Uint8Array): Hash; - public finish(): Hash; - public result: Uint8Array; -} - -export class Sha1 extends Hash {} -export class Sha256 extends Hash {} - // -----END ADDED BY FLOWCRYPT----- From 40239f48190a3116b2a88ff6a2200692509df11d Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 10 Feb 2022 21:27:38 +0200 Subject: [PATCH 132/179] fix encrypt --- Core/source/core/pgp-key.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index a36d6193b..7e72e01cd 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -9,7 +9,7 @@ import { PgpArmor } from './pgp-armor'; import { Store } from '../platform/store'; import { mnemonic } from './mnemonic'; import { str_to_hex } from '../platform/util'; -import { AnyKeyPacket, BaseSecretKeyPacket, enums, generateKey, Key, KeyID, PacketList, PrivateKey, PublicKey, readKey, readKeys, readMessage, readToEnd, revokeKey, SecretKeyPacket, SecretSubkeyPacket, SignaturePacket, UserID } from 'openpgp'; +import { AnyKeyPacket, encryptKey, enums, generateKey, Key, KeyID, PacketList, PrivateKey, PublicKey, readKey, readKeys, readMessage, readToEnd, revokeKey, SecretKeyPacket, SecretSubkeyPacket, SignaturePacket, UserID } from 'openpgp'; import { isFullyDecrypted, isFullyEncrypted } from './pgp'; export type Contact = { @@ -177,7 +177,7 @@ export class PgpKey { throw new Error(`Cannot encrypt a key that has ${encryptedPacketCount} of ` + `${secretPackets.length} private packets still encrypted`); } - await ((prv as unknown) as BaseSecretKeyPacket).encrypt(passphrase); + await encryptKey({privateKey: (prv as PrivateKey), passphrase}); } public static normalize = async (armored: string): Promise<{ normalized: string, keys: Key[] }> => { From f4ff14fef6a3cd419ea3d38e85fc60c08b98ec21 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 10 Feb 2022 21:32:01 +0200 Subject: [PATCH 133/179] wip --- Core/source/lib/openpgpjs-v5/dist/node/openpgp.js | 3 --- Core/source/lib/openpgpjs-v5/dist/openpgp.js | 3 --- 2 files changed, 6 deletions(-) diff --git a/Core/source/lib/openpgpjs-v5/dist/node/openpgp.js b/Core/source/lib/openpgpjs-v5/dist/node/openpgp.js index 2cd0e6994..83dbd60a6 100644 --- a/Core/source/lib/openpgpjs-v5/dist/node/openpgp.js +++ b/Core/source/lib/openpgpjs-v5/dist/node/openpgp.js @@ -43570,9 +43570,6 @@ exports.unarmor = unarmor; exports.verify = verify$5; // -----BEGIN ADDED BY FLOWCRYPT---- -exports.Hash = Hash; -exports.Sha1 = Sha1; -exports.Sha256 = Sha256; exports.readToEnd = readToEnd; exports.util = util; // -----END ADDED BY FLOWCRYPT----- diff --git a/Core/source/lib/openpgpjs-v5/dist/openpgp.js b/Core/source/lib/openpgpjs-v5/dist/openpgp.js index 45c7f801e..793eb3f83 100644 --- a/Core/source/lib/openpgpjs-v5/dist/openpgp.js +++ b/Core/source/lib/openpgpjs-v5/dist/openpgp.js @@ -43523,9 +43523,6 @@ var openpgp = (function (exports) { exports.verify = verify$5; // -----BEGIN ADDED BY FLOWCRYPT---- -exports.Hash = Hash; -exports.Sha1 = Sha1; -exports.Sha256 = Sha256; exports.readToEnd = readToEnd; exports.util = util; // -----END ADDED BY FLOWCRYPT----- From 477f504804fadfc42120ff9aac1dfbda7e6e5870 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 10 Feb 2022 21:33:23 +0200 Subject: [PATCH 134/179] wip --- Core/source/lib/openpgpjs-v5/dist/node/openpgp.js | 1 - Core/source/lib/openpgpjs-v5/dist/openpgp.js | 2 -- 2 files changed, 3 deletions(-) diff --git a/Core/source/lib/openpgpjs-v5/dist/node/openpgp.js b/Core/source/lib/openpgpjs-v5/dist/node/openpgp.js index 83dbd60a6..968758a60 100644 --- a/Core/source/lib/openpgpjs-v5/dist/node/openpgp.js +++ b/Core/source/lib/openpgpjs-v5/dist/node/openpgp.js @@ -43573,4 +43573,3 @@ exports.verify = verify$5; exports.readToEnd = readToEnd; exports.util = util; // -----END ADDED BY FLOWCRYPT----- - diff --git a/Core/source/lib/openpgpjs-v5/dist/openpgp.js b/Core/source/lib/openpgpjs-v5/dist/openpgp.js index 793eb3f83..507c8c2b5 100644 --- a/Core/source/lib/openpgpjs-v5/dist/openpgp.js +++ b/Core/source/lib/openpgpjs-v5/dist/openpgp.js @@ -43527,8 +43527,6 @@ exports.readToEnd = readToEnd; exports.util = util; // -----END ADDED BY FLOWCRYPT----- - - Object.defineProperty(exports, '__esModule', { value: true }); return exports; From 32a7ecd929a4f79511658216ea383d8c1b946009 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 10 Feb 2022 22:48:52 +0200 Subject: [PATCH 135/179] wip --- Core/source/lib/openpgpjs-v5/openpgp.d.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/Core/source/lib/openpgpjs-v5/openpgp.d.ts b/Core/source/lib/openpgpjs-v5/openpgp.d.ts index 4938ced40..a7e0674d5 100644 --- a/Core/source/lib/openpgpjs-v5/openpgp.d.ts +++ b/Core/source/lib/openpgpjs-v5/openpgp.d.ts @@ -523,7 +523,6 @@ export class SignaturePacket extends BasePacket { public issuerKeyVersion: null | number; public issuerFingerprint: null | Uint8Array; public preferredAEADAlgorithms: enums.aead[] | null; - public verified: null | boolean; public revoked: null | boolean; public sign(key: AnySecretKeyPacket, data: Uint8Array, date?: Date, detached?: boolean): Promise; public verify(key: AnyKeyPacket, signatureType: enums.signature, data: Uint8Array, date?: Date, detached?: boolean, config?: Config): Promise; // throws on error From 47b8dbd45f244ec0de032bb595c019597a7ffc9e Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 10 Feb 2022 22:58:18 +0200 Subject: [PATCH 136/179] wip --- Core/source/core/pgp-key.ts | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index 7e72e01cd..9403298d6 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -363,17 +363,28 @@ export class PgpKey { // no longer works, need some alternate solution // discussion is in progress: https://github.com/openpgpjs/openpgpjs/discussions/1491 await key.getExpirationTime(); // will force all sigs to be verified - const allSignatures: SignaturePacket[] = []; + const allSignatures: {sigPacket: SignaturePacket, verified: boolean}[] = []; for (const user of key.users) { - allSignatures.push(...user.selfCertifications); + for (const selfCertification of user.selfCertifications) { + // TODO: verify + const verified = false; + allSignatures.push({sigPacket: selfCertification, verified}); + } } for (const subKey of key.subkeys) { - allSignatures.push(...subKey.bindingSignatures); + for (const bindingSignature of subKey.bindingSignatures) { + // TODO: verify + const verified = false; + allSignatures.push({sigPacket: bindingSignature, verified}); + } } - allSignatures.sort((a, b) => (b.created ? b.created.getTime() : 0) - (a.created ? a.created.getTime() : 0)); + allSignatures.sort((a, b) => { + return (b.sigPacket.created ? b.sigPacket.created.getTime() : 0) - + (a.sigPacket.created ? a.sigPacket.created.getTime() : 0); + }); const newestSig = allSignatures.find(sig => sig.verified === true); if (newestSig) { - return newestSig.created ? newestSig.created.getTime() : 0; + return newestSig.sigPacket.created ? newestSig.sigPacket.created.getTime() : 0; } throw new Error('No valid signature found in key'); } From f7bc97928f3c999f017a448526ed5526a50dd036 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 10 Feb 2022 23:36:26 +0200 Subject: [PATCH 137/179] wip --- Core/source/core/pgp-key.ts | 34 +++++++++++------------ Core/source/lib/openpgpjs-v5/openpgp.d.ts | 2 +- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index 9403298d6..a3986b0cd 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -360,31 +360,29 @@ export class PgpKey { * This is used to figure out how recently was key updated, and if one key is newer than other. */ public static lastSig = async (key: Key): Promise => { - // no longer works, need some alternate solution + // "await key.getExpirationTime()" no longer works, need some alternate solution // discussion is in progress: https://github.com/openpgpjs/openpgpjs/discussions/1491 - await key.getExpirationTime(); // will force all sigs to be verified - const allSignatures: {sigPacket: SignaturePacket, verified: boolean}[] = []; + const allSignatures: SignaturePacket[] = []; for (const user of key.users) { + const data = { userID: user.userID, userAttribute: user.userAttribute, key: key }; for (const selfCertification of user.selfCertifications) { - // TODO: verify - const verified = false; - allSignatures.push({sigPacket: selfCertification, verified}); + try { + await selfCertification.verify(key.keyPacket, enums.signature.certGeneric, data); + allSignatures.push(selfCertification); + } catch (e) { + } } } for (const subKey of key.subkeys) { - for (const bindingSignature of subKey.bindingSignatures) { - // TODO: verify - const verified = false; - allSignatures.push({sigPacket: bindingSignature, verified}); - } + const latestValidSig = await subKey.verify(); + if (latestValidSig) allSignatures.push(latestValidSig); } - allSignatures.sort((a, b) => { - return (b.sigPacket.created ? b.sigPacket.created.getTime() : 0) - - (a.sigPacket.created ? a.sigPacket.created.getTime() : 0); - }); - const newestSig = allSignatures.find(sig => sig.verified === true); - if (newestSig) { - return newestSig.sigPacket.created ? newestSig.sigPacket.created.getTime() : 0; + if (allSignatures.length > 0) { + allSignatures.sort((a, b) => { + return (b.created ? b.created.getTime() : 0) - (a.created ? a.created.getTime() : 0); + }); + const newestSig = allSignatures[0]; + return newestSig.created ? newestSig.created.getTime() : 0; } throw new Error('No valid signature found in key'); } diff --git a/Core/source/lib/openpgpjs-v5/openpgp.d.ts b/Core/source/lib/openpgpjs-v5/openpgp.d.ts index a7e0674d5..03a2c57b7 100644 --- a/Core/source/lib/openpgpjs-v5/openpgp.d.ts +++ b/Core/source/lib/openpgpjs-v5/openpgp.d.ts @@ -525,7 +525,7 @@ export class SignaturePacket extends BasePacket { public preferredAEADAlgorithms: enums.aead[] | null; public revoked: null | boolean; public sign(key: AnySecretKeyPacket, data: Uint8Array, date?: Date, detached?: boolean): Promise; - public verify(key: AnyKeyPacket, signatureType: enums.signature, data: Uint8Array, date?: Date, detached?: boolean, config?: Config): Promise; // throws on error + public verify(key: AnyKeyPacket, signatureType: enums.signature, data: string | object, date?: Date, detached?: boolean, config?: Config): Promise; // throws on error public isExpired(date?: Date): boolean; public getExpirationTime(): Date | typeof Infinity; } From 6a7354c3ec6a207a38abfa2deea2ae2ffa0de357 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 10 Feb 2022 23:49:44 +0200 Subject: [PATCH 138/179] wip --- Core/source/core/pgp-key.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index a3986b0cd..f84c5158b 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -370,12 +370,17 @@ export class PgpKey { await selfCertification.verify(key.keyPacket, enums.signature.certGeneric, data); allSignatures.push(selfCertification); } catch (e) { + console.log(e); } } } for (const subKey of key.subkeys) { - const latestValidSig = await subKey.verify(); - if (latestValidSig) allSignatures.push(latestValidSig); + try { + const latestValidSig = await subKey.verify(); + if (latestValidSig) allSignatures.push(latestValidSig); + } catch (e) { + console.log(e); + } } if (allSignatures.length > 0) { allSignatures.sort((a, b) => { From a6c632b03177e15329949151f0092f9be1a38ab5 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 10 Feb 2022 23:56:26 +0200 Subject: [PATCH 139/179] wip --- .../openpgpjs-v5 => core/types}/openpgp.d.ts | 0 .../lib/openpgpjs-v5/dist/node/openpgp.js | 43575 ---------------- Core/source/lib/openpgpjs-v5/dist/openpgp.js | 43534 --------------- Core/tooling/build.sh | 25 +- 4 files changed, 23 insertions(+), 87111 deletions(-) rename Core/source/{lib/openpgpjs-v5 => core/types}/openpgp.d.ts (100%) delete mode 100644 Core/source/lib/openpgpjs-v5/dist/node/openpgp.js delete mode 100644 Core/source/lib/openpgpjs-v5/dist/openpgp.js diff --git a/Core/source/lib/openpgpjs-v5/openpgp.d.ts b/Core/source/core/types/openpgp.d.ts similarity index 100% rename from Core/source/lib/openpgpjs-v5/openpgp.d.ts rename to Core/source/core/types/openpgp.d.ts diff --git a/Core/source/lib/openpgpjs-v5/dist/node/openpgp.js b/Core/source/lib/openpgpjs-v5/dist/node/openpgp.js deleted file mode 100644 index 968758a60..000000000 --- a/Core/source/lib/openpgpjs-v5/dist/node/openpgp.js +++ /dev/null @@ -1,43575 +0,0 @@ -/*! OpenPGP.js v5.1.0 - 2022-01-24 - this is LGPL licensed code, see LICENSE/our website https://openpgpjs.org/ for more information. */ -'use strict'; - -const globalThis = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; - -Object.defineProperty(exports, '__esModule', { value: true }); - -var buffer = require('buffer'); -var stream$1 = require('stream'); -var crypto$3 = require('crypto'); -var zlib = require('zlib'); -var os = require('os'); -var util$1 = require('util'); -var asn1$2 = require('asn1.js'); - -function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } - -var buffer__default = /*#__PURE__*/_interopDefaultLegacy(buffer); -var stream__default = /*#__PURE__*/_interopDefaultLegacy(stream$1); -var crypto__default = /*#__PURE__*/_interopDefaultLegacy(crypto$3); -var zlib__default = /*#__PURE__*/_interopDefaultLegacy(zlib); -var os__default = /*#__PURE__*/_interopDefaultLegacy(os); -var util__default = /*#__PURE__*/_interopDefaultLegacy(util$1); -var asn1__default = /*#__PURE__*/_interopDefaultLegacy(asn1$2); - -const doneWritingPromise = Symbol('doneWritingPromise'); -const doneWritingResolve = Symbol('doneWritingResolve'); -const doneWritingReject = Symbol('doneWritingReject'); - -const readingIndex = Symbol('readingIndex'); - -// Based on https://stackoverflow.com/a/1997811/1540501 -// inject oids -(function() { - if ( typeof Object.__oid == "undefined" ) { - var id = 0; - - Object.__oid = function(o) { - if ( typeof o.__uniqueid == "undefined" ) { - Object.defineProperty(o, "__uniqueid", { - value: ++id, - enumerable: false, - // This could go either way, depending on your - // interpretation of what an "id" is - writable: false - }); - } - - return o.__uniqueid; - }; - } -})(); - -class ArrayStream extends Array { - constructor() { - super(); - this[doneWritingPromise] = new Promise((resolve, reject) => { - this[doneWritingResolve] = resolve; - this[doneWritingReject] = reject; - }); - this[doneWritingPromise].catch(() => {}); - } -} - -ArrayStream.prototype.getReader = function() { - if (this[readingIndex] === undefined) { - this[readingIndex] = 0; - } - return { - read: async () => { - await this[doneWritingPromise]; - if (this[readingIndex] === this.length) { - return { value: undefined, done: true }; - } - return { value: this[this[readingIndex]++], done: false }; - } - }; -}; - -ArrayStream.prototype.readToEnd = async function(join) { - await this[doneWritingPromise]; - const result = join(this.slice(this[readingIndex])); - this.length = 0; - return result; -}; - -ArrayStream.prototype.clone = function() { - const clone = new ArrayStream(); - clone[doneWritingPromise] = this[doneWritingPromise].then(() => { - clone.push(...this); - }); - return clone; -}; - -/** - * Check whether data is an ArrayStream - * @param {Any} input data to check - * @returns {boolean} - */ -function isArrayStream(input) { - return input && input.getReader && Array.isArray(input); -} - -/** - * A wrapper class over the native WritableStreamDefaultWriter. - * It also lets you "write data to" array streams instead of streams. - * @class - */ -function Writer(input) { - if (!isArrayStream(input)) { - const writer = input.getWriter(); - const releaseLock = writer.releaseLock; - writer.releaseLock = () => { - writer.closed.catch(function() {}); - releaseLock.call(writer); - }; - return writer; - } - this.stream = input; -} - -/** - * Write a chunk of data. - * @returns {Promise} - * @async - */ -Writer.prototype.write = async function(chunk) { - this.stream.push(chunk); -}; - -/** - * Close the stream. - * @returns {Promise} - * @async - */ -Writer.prototype.close = async function() { - this.stream[doneWritingResolve](); -}; - -/** - * Error the stream. - * @returns {Promise} - * @async - */ -Writer.prototype.abort = async function(reason) { - this.stream[doneWritingReject](reason); - return reason; -}; - -/** - * Release the writer's lock. - * @returns {undefined} - * @async - */ -Writer.prototype.releaseLock = function() {}; - -const isNode = typeof globalThis.process === 'object' && - typeof globalThis.process.versions === 'object'; - -const NodeReadableStream = isNode && stream__default['default'].Readable; - -/** - * Check whether data is a Stream, and if so of which type - * @param {Any} input data to check - * @returns {'web'|'ponyfill'|'node'|'array'|'web-like'|false} - */ -function isStream(input) { - if (isArrayStream(input)) { - return 'array'; - } - if (globalThis.ReadableStream && globalThis.ReadableStream.prototype.isPrototypeOf(input)) { - return 'web'; - } - if (ReadableStream && ReadableStream.prototype.isPrototypeOf(input)) { - return 'ponyfill'; - } - if (NodeReadableStream && NodeReadableStream.prototype.isPrototypeOf(input)) { - return 'node'; - } - if (input && input.getReader) { - return 'web-like'; - } - return false; -} - -/** - * Check whether data is a Uint8Array - * @param {Any} input data to check - * @returns {Boolean} - */ -function isUint8Array(input) { - return Uint8Array.prototype.isPrototypeOf(input); -} - -/** - * Concat Uint8Arrays - * @param {Array} Array of Uint8Arrays to concatenate - * @returns {Uint8array} Concatenated array - */ -function concatUint8Array(arrays) { - if (arrays.length === 1) return arrays[0]; - - let totalLength = 0; - for (let i = 0; i < arrays.length; i++) { - if (!isUint8Array(arrays[i])) { - throw new Error('concatUint8Array: Data must be in the form of a Uint8Array'); - } - - totalLength += arrays[i].length; - } - - const result = new Uint8Array(totalLength); - let pos = 0; - arrays.forEach(function (element) { - result.set(element, pos); - pos += element.length; - }); - - return result; -} - -const NodeBuffer = isNode && buffer__default['default'].Buffer; -const NodeReadableStream$1 = isNode && stream__default['default'].Readable; - -/** - * Web / node stream conversion functions - * From https://github.com/gwicke/node-web-streams - */ - -let nodeToWeb; -let webToNode; - -if (NodeReadableStream$1) { - - /** - * Convert a Node Readable Stream to a Web ReadableStream - * @param {Readable} nodeStream - * @returns {ReadableStream} - */ - nodeToWeb = function(nodeStream) { - let canceled = false; - return new ReadableStream({ - start(controller) { - nodeStream.pause(); - nodeStream.on('data', chunk => { - if (canceled) { - return; - } - if (NodeBuffer.isBuffer(chunk)) { - chunk = new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength); - } - controller.enqueue(chunk); - nodeStream.pause(); - }); - nodeStream.on('end', () => { - if (canceled) { - return; - } - controller.close(); - }); - nodeStream.on('error', e => controller.error(e)); - }, - pull() { - nodeStream.resume(); - }, - cancel(reason) { - canceled = true; - nodeStream.destroy(reason); - } - }); - }; - - - class NodeReadable extends NodeReadableStream$1 { - constructor(webStream, options) { - super(options); - this._reader = getReader(webStream); - } - - async _read(size) { - try { - while (true) { - const { done, value } = await this._reader.read(); - if (done) { - this.push(null); - break; - } - if (!this.push(value) || this._cancelling) { - this._reading = false; - break; - } - } - } catch(e) { - this.emit('error', e); - } - } - - _destroy(reason) { - this._reader.cancel(reason); - } - } - - /** - * Convert a Web ReadableStream to a Node Readable Stream - * @param {ReadableStream} webStream - * @param {Object} options - * @returns {Readable} - */ - webToNode = function(webStream, options) { - return new NodeReadable(webStream, options); - }; - -} - -const doneReadingSet = new WeakSet(); -const externalBuffer = Symbol('externalBuffer'); - -/** - * A wrapper class over the native ReadableStreamDefaultReader. - * This additionally implements pushing back data on the stream, which - * lets us implement peeking and a host of convenience functions. - * It also lets you read data other than streams, such as a Uint8Array. - * @class - */ -function Reader(input) { - this.stream = input; - if (input[externalBuffer]) { - this[externalBuffer] = input[externalBuffer].slice(); - } - if (isArrayStream(input)) { - const reader = input.getReader(); - this._read = reader.read.bind(reader); - this._releaseLock = () => {}; - this._cancel = () => {}; - return; - } - let streamType = isStream(input); - if (streamType === 'node') { - input = nodeToWeb(input); - } - if (streamType) { - const reader = input.getReader(); - this._read = reader.read.bind(reader); - this._releaseLock = () => { - reader.closed.catch(function() {}); - reader.releaseLock(); - }; - this._cancel = reader.cancel.bind(reader); - return; - } - let doneReading = false; - this._read = async () => { - if (doneReading || doneReadingSet.has(input)) { - return { value: undefined, done: true }; - } - doneReading = true; - return { value: input, done: false }; - }; - this._releaseLock = () => { - if (doneReading) { - try { - doneReadingSet.add(input); - } catch(e) {} - } - }; -} - -/** - * Read a chunk of data. - * @returns {Promise} Either { done: false, value: Uint8Array | String } or { done: true, value: undefined } - * @async - */ -Reader.prototype.read = async function() { - if (this[externalBuffer] && this[externalBuffer].length) { - const value = this[externalBuffer].shift(); - return { done: false, value }; - } - return this._read(); -}; - -/** - * Allow others to read the stream. - */ -Reader.prototype.releaseLock = function() { - if (this[externalBuffer]) { - this.stream[externalBuffer] = this[externalBuffer]; - } - this._releaseLock(); -}; - -/** - * Cancel the stream. - */ -Reader.prototype.cancel = function(reason) { - return this._cancel(reason); -}; - -/** - * Read up to and including the first \n character. - * @returns {Promise} - * @async - */ -Reader.prototype.readLine = async function() { - let buffer = []; - let returnVal; - while (!returnVal) { - let { done, value } = await this.read(); - value += ''; - if (done) { - if (buffer.length) return concat(buffer); - return; - } - const lineEndIndex = value.indexOf('\n') + 1; - if (lineEndIndex) { - returnVal = concat(buffer.concat(value.substr(0, lineEndIndex))); - buffer = []; - } - if (lineEndIndex !== value.length) { - buffer.push(value.substr(lineEndIndex)); - } - } - this.unshift(...buffer); - return returnVal; -}; - -/** - * Read a single byte/character. - * @returns {Promise} - * @async - */ -Reader.prototype.readByte = async function() { - const { done, value } = await this.read(); - if (done) return; - const byte = value[0]; - this.unshift(slice(value, 1)); - return byte; -}; - -/** - * Read a specific amount of bytes/characters, unless the stream ends before that amount. - * @returns {Promise} - * @async - */ -Reader.prototype.readBytes = async function(length) { - const buffer = []; - let bufferLength = 0; - while (true) { - const { done, value } = await this.read(); - if (done) { - if (buffer.length) return concat(buffer); - return; - } - buffer.push(value); - bufferLength += value.length; - if (bufferLength >= length) { - const bufferConcat = concat(buffer); - this.unshift(slice(bufferConcat, length)); - return slice(bufferConcat, 0, length); - } - } -}; - -/** - * Peek (look ahead) a specific amount of bytes/characters, unless the stream ends before that amount. - * @returns {Promise} - * @async - */ -Reader.prototype.peekBytes = async function(length) { - const bytes = await this.readBytes(length); - this.unshift(bytes); - return bytes; -}; - -/** - * Push data to the front of the stream. - * Data must have been read in the last call to read*. - * @param {...(Uint8Array|String|Undefined)} values - */ -Reader.prototype.unshift = function(...values) { - if (!this[externalBuffer]) { - this[externalBuffer] = []; - } - if ( - values.length === 1 && isUint8Array(values[0]) && - this[externalBuffer].length && values[0].length && - this[externalBuffer][0].byteOffset >= values[0].length - ) { - this[externalBuffer][0] = new Uint8Array( - this[externalBuffer][0].buffer, - this[externalBuffer][0].byteOffset - values[0].length, - this[externalBuffer][0].byteLength + values[0].length - ); - return; - } - this[externalBuffer].unshift(...values.filter(value => value && value.length)); -}; - -/** - * Read the stream to the end and return its contents, concatenated by the join function (defaults to streams.concat). - * @param {Function} join - * @returns {Promise} the return value of join() - * @async - */ -Reader.prototype.readToEnd = async function(join=concat) { - const result = []; - while (true) { - const { done, value } = await this.read(); - if (done) break; - result.push(value); - } - return join(result); -}; - -let { ReadableStream, WritableStream, TransformStream } = globalThis; - -let toPonyfillReadable, toNativeReadable; - -async function loadStreamsPonyfill() { - if (TransformStream) { - return; - } - - const [ponyfill, adapter] = await Promise.all([ - Promise.resolve().then(function () { return ponyfill_es6; }), - Promise.resolve().then(function () { return webStreamsAdapter; }) - ]); - - ({ ReadableStream, WritableStream, TransformStream } = ponyfill); - - const { createReadableStreamWrapper } = adapter; - - if (globalThis.ReadableStream && ReadableStream !== globalThis.ReadableStream) { - toPonyfillReadable = createReadableStreamWrapper(ReadableStream); - toNativeReadable = createReadableStreamWrapper(globalThis.ReadableStream); - } -} - -const NodeBuffer$1 = isNode && buffer__default['default'].Buffer; - -/** - * Convert data to Stream - * @param {ReadableStream|Uint8array|String} input data to convert - * @returns {ReadableStream} Converted data - */ -function toStream(input) { - let streamType = isStream(input); - if (streamType === 'node') { - return nodeToWeb(input); - } - if (streamType === 'web' && toPonyfillReadable) { - return toPonyfillReadable(input); - } - if (streamType) { - return input; - } - return new ReadableStream({ - start(controller) { - controller.enqueue(input); - controller.close(); - } - }); -} - -/** - * Convert data to ArrayStream - * @param {Object} input data to convert - * @returns {ArrayStream} Converted data - */ -function toArrayStream(input) { - if (isStream(input)) { - return input; - } - const stream = new ArrayStream(); - (async () => { - const writer = getWriter(stream); - await writer.write(input); - await writer.close(); - })(); - return stream; -} - -/** - * Concat a list of Uint8Arrays, Strings or Streams - * The caller should not mix Uint8Arrays with Strings, but may mix Streams with non-Streams. - * @param {Array} Array of Uint8Arrays/Strings/Streams to concatenate - * @returns {Uint8array|String|ReadableStream} Concatenated array - */ -function concat(list) { - if (list.some(stream => isStream(stream) && !isArrayStream(stream))) { - return concatStream(list); - } - if (list.some(stream => isArrayStream(stream))) { - return concatArrayStream(list); - } - if (typeof list[0] === 'string') { - return list.join(''); - } - if (NodeBuffer$1 && NodeBuffer$1.isBuffer(list[0])) { - return NodeBuffer$1.concat(list); - } - return concatUint8Array(list); -} - -/** - * Concat a list of Streams - * @param {Array} list Array of Uint8Arrays/Strings/Streams to concatenate - * @returns {ReadableStream} Concatenated list - */ -function concatStream(list) { - list = list.map(toStream); - const transform = transformWithCancel(async function(reason) { - await Promise.all(transforms.map(stream => cancel(stream, reason))); - }); - let prev = Promise.resolve(); - const transforms = list.map((stream, i) => transformPair(stream, (readable, writable) => { - prev = prev.then(() => pipe(readable, transform.writable, { - preventClose: i !== list.length - 1 - })); - return prev; - })); - return transform.readable; -} - -/** - * Concat a list of ArrayStreams - * @param {Array} list Array of Uint8Arrays/Strings/ArrayStreams to concatenate - * @returns {ArrayStream} Concatenated streams - */ -function concatArrayStream(list) { - const result = new ArrayStream(); - let prev = Promise.resolve(); - list.forEach((stream, i) => { - prev = prev.then(() => pipe(stream, result, { - preventClose: i !== list.length - 1 - })); - return prev; - }); - return result; -} - -/** - * Get a Reader - * @param {ReadableStream|Uint8array|String} input - * @returns {Reader} - */ -function getReader(input) { - return new Reader(input); -} - -/** - * Get a Writer - * @param {WritableStream} input - * @returns {Writer} - */ -function getWriter(input) { - return new Writer(input); -} - -/** - * Pipe a readable stream to a writable stream. Don't throw on input stream errors, but forward them to the output stream. - * @param {ReadableStream|Uint8array|String} input - * @param {WritableStream} target - * @param {Object} (optional) options - * @returns {Promise} Promise indicating when piping has finished (input stream closed or errored) - * @async - */ -async function pipe(input, target, { - preventClose = false, - preventAbort = false, - preventCancel = false -} = {}) { - if (isStream(input) && !isArrayStream(input)) { - input = toStream(input); - try { - if (input[externalBuffer]) { - const writer = getWriter(target); - for (let i = 0; i < input[externalBuffer].length; i++) { - await writer.ready; - await writer.write(input[externalBuffer][i]); - } - writer.releaseLock(); - } - await input.pipeTo(target, { - preventClose, - preventAbort, - preventCancel - }); - } catch(e) {} - return; - } - input = toArrayStream(input); - const reader = getReader(input); - const writer = getWriter(target); - try { - while (true) { - await writer.ready; - const { done, value } = await reader.read(); - if (done) { - if (!preventClose) await writer.close(); - break; - } - await writer.write(value); - } - } catch (e) { - if (!preventAbort) await writer.abort(e); - } finally { - reader.releaseLock(); - writer.releaseLock(); - } -} - -/** - * Pipe a readable stream through a transform stream. - * @param {ReadableStream|Uint8array|String} input - * @param {Object} (optional) options - * @returns {ReadableStream} transformed stream - */ -function transformRaw(input, options) { - const transformStream = new TransformStream(options); - pipe(input, transformStream.writable); - return transformStream.readable; -} - -/** - * Create a cancelable TransformStream. - * @param {Function} cancel - * @returns {TransformStream} - */ -function transformWithCancel(cancel) { - let pulled = false; - let backpressureChangePromiseResolve; - let outputController; - return { - readable: new ReadableStream({ - start(controller) { - outputController = controller; - }, - pull() { - if (backpressureChangePromiseResolve) { - backpressureChangePromiseResolve(); - } else { - pulled = true; - } - }, - cancel - }, {highWaterMark: 0}), - writable: new WritableStream({ - write: async function(chunk) { - outputController.enqueue(chunk); - if (!pulled) { - await new Promise(resolve => { - backpressureChangePromiseResolve = resolve; - }); - backpressureChangePromiseResolve = null; - } else { - pulled = false; - } - }, - close: outputController.close.bind(outputController), - abort: outputController.error.bind(outputController) - }) - }; -} - -/** - * Transform a stream using helper functions which are called on each chunk, and on stream close, respectively. - * @param {ReadableStream|Uint8array|String} input - * @param {Function} process - * @param {Function} finish - * @returns {ReadableStream|Uint8array|String} - */ -function transform(input, process = () => undefined, finish = () => undefined) { - if (isArrayStream(input)) { - const output = new ArrayStream(); - (async () => { - const data = await readToEnd(input); - const result1 = process(data); - const result2 = finish(); - let result; - if (result1 !== undefined && result2 !== undefined) result = concat([result1, result2]); - else result = result1 !== undefined ? result1 : result2; - const writer = getWriter(output); - await writer.write(result); - await writer.close(); - })(); - return output; - } - if (isStream(input)) { - return transformRaw(input, { - async transform(value, controller) { - try { - const result = await process(value); - if (result !== undefined) controller.enqueue(result); - } catch(e) { - controller.error(e); - } - }, - async flush(controller) { - try { - const result = await finish(); - if (result !== undefined) controller.enqueue(result); - } catch(e) { - controller.error(e); - } - } - }); - } - const result1 = process(input); - const result2 = finish(); - if (result1 !== undefined && result2 !== undefined) return concat([result1, result2]); - return result1 !== undefined ? result1 : result2; -} - -/** - * Transform a stream using a helper function which is passed a readable and a writable stream. - * This function also maintains the possibility to cancel the input stream, - * and does so on cancelation of the output stream, despite cancelation - * normally being impossible when the input stream is being read from. - * @param {ReadableStream|Uint8array|String} input - * @param {Function} fn - * @returns {ReadableStream} - */ -function transformPair(input, fn) { - if (isStream(input) && !isArrayStream(input)) { - let incomingTransformController; - const incoming = new TransformStream({ - start(controller) { - incomingTransformController = controller; - } - }); - - const pipeDonePromise = pipe(input, incoming.writable); - - const outgoing = transformWithCancel(async function() { - incomingTransformController.error(new Error('Readable side was canceled.')); - await pipeDonePromise; - await new Promise(setTimeout); - }); - fn(incoming.readable, outgoing.writable); - return outgoing.readable; - } - input = toArrayStream(input); - const output = new ArrayStream(); - fn(input, output); - return output; -} - -/** - * Parse a stream using a helper function which is passed a Reader. - * The reader additionally has a remainder() method which returns a - * stream pointing to the remainder of input, and is linked to input - * for cancelation. - * @param {ReadableStream|Uint8array|String} input - * @param {Function} fn - * @returns {Any} the return value of fn() - */ -function parse(input, fn) { - let returnValue; - const transformed = transformPair(input, (readable, writable) => { - const reader = getReader(readable); - reader.remainder = () => { - reader.releaseLock(); - pipe(readable, writable); - return transformed; - }; - returnValue = fn(reader); - }); - return returnValue; -} - -/** - * Tee a Stream for reading it twice. The input stream can no longer be read after tee()ing. - * Reading either of the two returned streams will pull from the input stream. - * The input stream will only be canceled if both of the returned streams are canceled. - * @param {ReadableStream|Uint8array|String} input - * @returns {Array} array containing two copies of input - */ -function tee(input) { - if (isArrayStream(input)) { - throw new Error('ArrayStream cannot be tee()d, use clone() instead'); - } - if (isStream(input)) { - const teed = toStream(input).tee(); - teed[0][externalBuffer] = teed[1][externalBuffer] = input[externalBuffer]; - return teed; - } - return [slice(input), slice(input)]; -} - -/** - * Clone a Stream for reading it twice. The input stream can still be read after clone()ing. - * Reading from the clone will pull from the input stream. - * The input stream will only be canceled if both the clone and the input stream are canceled. - * @param {ReadableStream|Uint8array|String} input - * @returns {ReadableStream|Uint8array|String} cloned input - */ -function clone(input) { - if (isArrayStream(input)) { - return input.clone(); - } - if (isStream(input)) { - const teed = tee(input); - overwrite(input, teed[0]); - return teed[1]; - } - return slice(input); -} - -/** - * Clone a Stream for reading it twice. Data will arrive at the same rate as the input stream is being read. - * Reading from the clone will NOT pull from the input stream. Data only arrives when reading the input stream. - * The input stream will NOT be canceled if the clone is canceled, only if the input stream are canceled. - * If the input stream is canceled, the clone will be errored. - * @param {ReadableStream|Uint8array|String} input - * @returns {ReadableStream|Uint8array|String} cloned input - */ -function passiveClone(input) { - if (isArrayStream(input)) { - return clone(input); - } - if (isStream(input)) { - return new ReadableStream({ - start(controller) { - const transformed = transformPair(input, async (readable, writable) => { - const reader = getReader(readable); - const writer = getWriter(writable); - try { - while (true) { - await writer.ready; - const { done, value } = await reader.read(); - if (done) { - try { controller.close(); } catch(e) {} - await writer.close(); - return; - } - try { controller.enqueue(value); } catch(e) {} - await writer.write(value); - } - } catch(e) { - controller.error(e); - await writer.abort(e); - } - }); - overwrite(input, transformed); - } - }); - } - return slice(input); -} - -/** - * Modify a stream object to point to a different stream object. - * This is used internally by clone() and passiveClone() to provide an abstraction over tee(). - * @param {ReadableStream} input - * @param {ReadableStream} clone - */ -function overwrite(input, clone) { - // Overwrite input.getReader, input.locked, etc to point to clone - Object.entries(Object.getOwnPropertyDescriptors(input.constructor.prototype)).forEach(([name, descriptor]) => { - if (name === 'constructor') { - return; - } - if (descriptor.value) { - descriptor.value = descriptor.value.bind(clone); - } else { - descriptor.get = descriptor.get.bind(clone); - } - Object.defineProperty(input, name, descriptor); - }); -} - -/** - * Return a stream pointing to a part of the input stream. - * @param {ReadableStream|Uint8array|String} input - * @returns {ReadableStream|Uint8array|String} clone - */ -function slice(input, begin=0, end=Infinity) { - if (isArrayStream(input)) { - throw new Error('Not implemented'); - } - if (isStream(input)) { - if (begin >= 0 && end >= 0) { - let bytesRead = 0; - return transformRaw(input, { - transform(value, controller) { - if (bytesRead < end) { - if (bytesRead + value.length >= begin) { - controller.enqueue(slice(value, Math.max(begin - bytesRead, 0), end - bytesRead)); - } - bytesRead += value.length; - } else { - controller.terminate(); - } - } - }); - } - if (begin < 0 && (end < 0 || end === Infinity)) { - let lastBytes = []; - return transform(input, value => { - if (value.length >= -begin) lastBytes = [value]; - else lastBytes.push(value); - }, () => slice(concat(lastBytes), begin, end)); - } - if (begin === 0 && end < 0) { - let lastBytes; - return transform(input, value => { - const returnValue = lastBytes ? concat([lastBytes, value]) : value; - if (returnValue.length >= -end) { - lastBytes = slice(returnValue, end); - return slice(returnValue, begin, end); - } else { - lastBytes = returnValue; - } - }); - } - console.warn(`stream.slice(input, ${begin}, ${end}) not implemented efficiently.`); - return fromAsync(async () => slice(await readToEnd(input), begin, end)); - } - if (input[externalBuffer]) { - input = concat(input[externalBuffer].concat([input])); - } - if (isUint8Array(input) && !(NodeBuffer$1 && NodeBuffer$1.isBuffer(input))) { - if (end === Infinity) end = input.length; - return input.subarray(begin, end); - } - return input.slice(begin, end); -} - -/** - * Read a stream to the end and return its contents, concatenated by the join function (defaults to concat). - * @param {ReadableStream|Uint8array|String} input - * @param {Function} join - * @returns {Promise} the return value of join() - * @async - */ -async function readToEnd(input, join=concat) { - if (isArrayStream(input)) { - return input.readToEnd(join); - } - if (isStream(input)) { - return getReader(input).readToEnd(join); - } - return input; -} - -/** - * Cancel a stream. - * @param {ReadableStream|Uint8array|String} input - * @param {Any} reason - * @returns {Promise} indicates when the stream has been canceled - * @async - */ -async function cancel(input, reason) { - if (isStream(input)) { - if (input.cancel) { - return input.cancel(reason); - } - if (input.destroy) { - input.destroy(reason); - await new Promise(setTimeout); - return reason; - } - } -} - -/** - * Convert an async function to an ArrayStream. When the function returns, its return value is written to the stream. - * @param {Function} fn - * @returns {ArrayStream} - */ -function fromAsync(fn) { - const arrayStream = new ArrayStream(); - (async () => { - const writer = getWriter(arrayStream); - try { - await writer.write(await fn()); - await writer.close(); - } catch (e) { - await writer.abort(e); - } - })(); - return arrayStream; -} - -/* eslint-disable new-cap */ - -/** - * @fileoverview - * BigInteger implementation of basic operations - * that wraps the native BigInt library. - * Operations are not constant time, - * but we try and limit timing leakage where we can - * @module biginteger/native - * @private - */ - -/** - * @private - */ -class BigInteger { - /** - * Get a BigInteger (input must be big endian for strings and arrays) - * @param {Number|String|Uint8Array} n - Value to convert - * @throws {Error} on null or undefined input - */ - constructor(n) { - if (n === undefined) { - throw new Error('Invalid BigInteger input'); - } - - if (n instanceof Uint8Array) { - const bytes = n; - const hex = new Array(bytes.length); - for (let i = 0; i < bytes.length; i++) { - const hexByte = bytes[i].toString(16); - hex[i] = (bytes[i] <= 0xF) ? ('0' + hexByte) : hexByte; - } - this.value = BigInt('0x0' + hex.join('')); - } else { - this.value = BigInt(n); - } - } - - clone() { - return new BigInteger(this.value); - } - - /** - * BigInteger increment in place - */ - iinc() { - this.value++; - return this; - } - - /** - * BigInteger increment - * @returns {BigInteger} this + 1. - */ - inc() { - return this.clone().iinc(); - } - - /** - * BigInteger decrement in place - */ - idec() { - this.value--; - return this; - } - - /** - * BigInteger decrement - * @returns {BigInteger} this - 1. - */ - dec() { - return this.clone().idec(); - } - - /** - * BigInteger addition in place - * @param {BigInteger} x - Value to add - */ - iadd(x) { - this.value += x.value; - return this; - } - - /** - * BigInteger addition - * @param {BigInteger} x - Value to add - * @returns {BigInteger} this + x. - */ - add(x) { - return this.clone().iadd(x); - } - - /** - * BigInteger subtraction in place - * @param {BigInteger} x - Value to subtract - */ - isub(x) { - this.value -= x.value; - return this; - } - - /** - * BigInteger subtraction - * @param {BigInteger} x - Value to subtract - * @returns {BigInteger} this - x. - */ - sub(x) { - return this.clone().isub(x); - } - - /** - * BigInteger multiplication in place - * @param {BigInteger} x - Value to multiply - */ - imul(x) { - this.value *= x.value; - return this; - } - - /** - * BigInteger multiplication - * @param {BigInteger} x - Value to multiply - * @returns {BigInteger} this * x. - */ - mul(x) { - return this.clone().imul(x); - } - - /** - * Compute value modulo m, in place - * @param {BigInteger} m - Modulo - */ - imod(m) { - this.value %= m.value; - if (this.isNegative()) { - this.iadd(m); - } - return this; - } - - /** - * Compute value modulo m - * @param {BigInteger} m - Modulo - * @returns {BigInteger} this mod m. - */ - mod(m) { - return this.clone().imod(m); - } - - /** - * Compute modular exponentiation using square and multiply - * @param {BigInteger} e - Exponent - * @param {BigInteger} n - Modulo - * @returns {BigInteger} this ** e mod n. - */ - modExp(e, n) { - if (n.isZero()) throw Error('Modulo cannot be zero'); - if (n.isOne()) return new BigInteger(0); - if (e.isNegative()) throw Error('Unsopported negative exponent'); - - let exp = e.value; - let x = this.value; - - x %= n.value; - let r = BigInt(1); - while (exp > BigInt(0)) { - const lsb = exp & BigInt(1); - exp >>= BigInt(1); // e / 2 - // Always compute multiplication step, to reduce timing leakage - const rx = (r * x) % n.value; - // Update r only if lsb is 1 (odd exponent) - r = lsb ? rx : r; - x = (x * x) % n.value; // Square - } - return new BigInteger(r); - } - - - /** - * Compute the inverse of this value modulo n - * Note: this and and n must be relatively prime - * @param {BigInteger} n - Modulo - * @returns {BigInteger} x such that this*x = 1 mod n - * @throws {Error} if the inverse does not exist - */ - modInv(n) { - const { gcd, x } = this._egcd(n); - if (!gcd.isOne()) { - throw new Error('Inverse does not exist'); - } - return x.add(n).mod(n); - } - - /** - * Extended Eucleadian algorithm (http://anh.cs.luc.edu/331/notes/xgcd.pdf) - * Given a = this and b, compute (x, y) such that ax + by = gdc(a, b) - * @param {BigInteger} b - Second operand - * @returns {{ gcd, x, y: BigInteger }} - */ - _egcd(b) { - let x = BigInt(0); - let y = BigInt(1); - let xPrev = BigInt(1); - let yPrev = BigInt(0); - - let a = this.value; - b = b.value; - - while (b !== BigInt(0)) { - const q = a / b; - let tmp = x; - x = xPrev - q * x; - xPrev = tmp; - - tmp = y; - y = yPrev - q * y; - yPrev = tmp; - - tmp = b; - b = a % b; - a = tmp; - } - - return { - x: new BigInteger(xPrev), - y: new BigInteger(yPrev), - gcd: new BigInteger(a) - }; - } - - /** - * Compute greatest common divisor between this and n - * @param {BigInteger} b - Operand - * @returns {BigInteger} gcd - */ - gcd(b) { - let a = this.value; - b = b.value; - while (b !== BigInt(0)) { - const tmp = b; - b = a % b; - a = tmp; - } - return new BigInteger(a); - } - - /** - * Shift this to the left by x, in place - * @param {BigInteger} x - Shift value - */ - ileftShift(x) { - this.value <<= x.value; - return this; - } - - /** - * Shift this to the left by x - * @param {BigInteger} x - Shift value - * @returns {BigInteger} this << x. - */ - leftShift(x) { - return this.clone().ileftShift(x); - } - - /** - * Shift this to the right by x, in place - * @param {BigInteger} x - Shift value - */ - irightShift(x) { - this.value >>= x.value; - return this; - } - - /** - * Shift this to the right by x - * @param {BigInteger} x - Shift value - * @returns {BigInteger} this >> x. - */ - rightShift(x) { - return this.clone().irightShift(x); - } - - /** - * Whether this value is equal to x - * @param {BigInteger} x - * @returns {Boolean} - */ - equal(x) { - return this.value === x.value; - } - - /** - * Whether this value is less than x - * @param {BigInteger} x - * @returns {Boolean} - */ - lt(x) { - return this.value < x.value; - } - - /** - * Whether this value is less than or equal to x - * @param {BigInteger} x - * @returns {Boolean} - */ - lte(x) { - return this.value <= x.value; - } - - /** - * Whether this value is greater than x - * @param {BigInteger} x - * @returns {Boolean} - */ - gt(x) { - return this.value > x.value; - } - - /** - * Whether this value is greater than or equal to x - * @param {BigInteger} x - * @returns {Boolean} - */ - gte(x) { - return this.value >= x.value; - } - - isZero() { - return this.value === BigInt(0); - } - - isOne() { - return this.value === BigInt(1); - } - - isNegative() { - return this.value < BigInt(0); - } - - isEven() { - return !(this.value & BigInt(1)); - } - - abs() { - const res = this.clone(); - if (this.isNegative()) { - res.value = -res.value; - } - return res; - } - - /** - * Get this value as a string - * @returns {String} this value. - */ - toString() { - return this.value.toString(); - } - - /** - * Get this value as an exact Number (max 53 bits) - * Fails if this value is too large - * @returns {Number} - */ - toNumber() { - const number = Number(this.value); - if (number > Number.MAX_SAFE_INTEGER) { - // We throw and error to conform with the bn.js implementation - throw new Error('Number can only safely store up to 53 bits'); - } - return number; - } - - /** - * Get value of i-th bit - * @param {Number} i - Bit index - * @returns {Number} Bit value. - */ - getBit(i) { - const bit = (this.value >> BigInt(i)) & BigInt(1); - return (bit === BigInt(0)) ? 0 : 1; - } - - /** - * Compute bit length - * @returns {Number} Bit length. - */ - bitLength() { - const zero = new BigInteger(0); - const one = new BigInteger(1); - const negOne = new BigInteger(-1); - - // -1n >> -1n is -1n - // 1n >> 1n is 0n - const target = this.isNegative() ? negOne : zero; - let bitlen = 1; - const tmp = this.clone(); - while (!tmp.irightShift(one).equal(target)) { - bitlen++; - } - return bitlen; - } - - /** - * Compute byte length - * @returns {Number} Byte length. - */ - byteLength() { - const zero = new BigInteger(0); - const negOne = new BigInteger(-1); - - const target = this.isNegative() ? negOne : zero; - const eight = new BigInteger(8); - let len = 1; - const tmp = this.clone(); - while (!tmp.irightShift(eight).equal(target)) { - len++; - } - return len; - } - - /** - * Get Uint8Array representation of this number - * @param {String} endian - Endianess of output array (defaults to 'be') - * @param {Number} length - Of output array - * @returns {Uint8Array} - */ - toUint8Array(endian = 'be', length) { - // we get and parse the hex string (https://coolaj86.com/articles/convert-js-bigints-to-typedarrays/) - // this is faster than shift+mod iterations - let hex = this.value.toString(16); - if (hex.length % 2 === 1) { - hex = '0' + hex; - } - - const rawLength = hex.length / 2; - const bytes = new Uint8Array(length || rawLength); - // parse hex - const offset = length ? (length - rawLength) : 0; - let i = 0; - while (i < rawLength) { - bytes[i + offset] = parseInt(hex.slice(2 * i, 2 * i + 2), 16); - i++; - } - - if (endian !== 'be') { - bytes.reverse(); - } - - return bytes; - } -} - -async function getBigInteger() { - if (util.detectBigInt()) { - return BigInteger; - } else { - const { default: BigInteger } = await Promise.resolve().then(function () { return bn_interface; }); - return BigInteger; - } -} - -const debugMode = (() => { - try { - return process.env.NODE_ENV === 'development'; // eslint-disable-line no-process-env - } catch (e) {} - return false; -})(); - -const util = { - isString: function(data) { - return typeof data === 'string' || String.prototype.isPrototypeOf(data); - }, - - isArray: function(data) { - return Array.prototype.isPrototypeOf(data); - }, - - isUint8Array: isUint8Array, - - isStream: isStream, - - readNumber: function (bytes) { - let n = 0; - for (let i = 0; i < bytes.length; i++) { - n += (256 ** i) * bytes[bytes.length - 1 - i]; - } - return n; - }, - - writeNumber: function (n, bytes) { - const b = new Uint8Array(bytes); - for (let i = 0; i < bytes; i++) { - b[i] = (n >> (8 * (bytes - i - 1))) & 0xFF; - } - - return b; - }, - - readDate: function (bytes) { - const n = util.readNumber(bytes); - const d = new Date(n * 1000); - return d; - }, - - writeDate: function (time) { - const numeric = Math.floor(time.getTime() / 1000); - - return util.writeNumber(numeric, 4); - }, - - normalizeDate: function (time = Date.now()) { - return time === null || time === Infinity ? time : new Date(Math.floor(+time / 1000) * 1000); - }, - - /** - * Read one MPI from bytes in input - * @param {Uint8Array} bytes - Input data to parse - * @returns {Uint8Array} Parsed MPI. - */ - readMPI: function (bytes) { - const bits = (bytes[0] << 8) | bytes[1]; - const bytelen = (bits + 7) >>> 3; - return bytes.subarray(2, 2 + bytelen); - }, - - /** - * Left-pad Uint8Array to length by adding 0x0 bytes - * @param {Uint8Array} bytes - Data to pad - * @param {Number} length - Padded length - * @returns {Uint8Array} Padded bytes. - */ - leftPad(bytes, length) { - const padded = new Uint8Array(length); - const offset = length - bytes.length; - padded.set(bytes, offset); - return padded; - }, - - /** - * Convert a Uint8Array to an MPI-formatted Uint8Array. - * @param {Uint8Array} bin - An array of 8-bit integers to convert - * @returns {Uint8Array} MPI-formatted Uint8Array. - */ - uint8ArrayToMPI: function (bin) { - const bitSize = util.uint8ArrayBitLength(bin); - if (bitSize === 0) { - throw new Error('Zero MPI'); - } - const stripped = bin.subarray(bin.length - Math.ceil(bitSize / 8)); - const prefix = new Uint8Array([(bitSize & 0xFF00) >> 8, bitSize & 0xFF]); - return util.concatUint8Array([prefix, stripped]); - }, - - /** - * Return bit length of the input data - * @param {Uint8Array} bin input data (big endian) - * @returns bit length - */ - uint8ArrayBitLength: function (bin) { - let i; // index of leading non-zero byte - for (i = 0; i < bin.length; i++) if (bin[i] !== 0) break; - if (i === bin.length) { - return 0; - } - const stripped = bin.subarray(i); - return (stripped.length - 1) * 8 + util.nbits(stripped[0]); - }, - - /** - * Convert a hex string to an array of 8-bit integers - * @param {String} hex - A hex string to convert - * @returns {Uint8Array} An array of 8-bit integers. - */ - hexToUint8Array: function (hex) { - const result = new Uint8Array(hex.length >> 1); - for (let k = 0; k < hex.length >> 1; k++) { - result[k] = parseInt(hex.substr(k << 1, 2), 16); - } - return result; - }, - - /** - * Convert an array of 8-bit integers to a hex string - * @param {Uint8Array} bytes - Array of 8-bit integers to convert - * @returns {String} Hexadecimal representation of the array. - */ - uint8ArrayToHex: function (bytes) { - const r = []; - const e = bytes.length; - let c = 0; - let h; - while (c < e) { - h = bytes[c++].toString(16); - while (h.length < 2) { - h = '0' + h; - } - r.push('' + h); - } - return r.join(''); - }, - - /** - * Convert a string to an array of 8-bit integers - * @param {String} str - String to convert - * @returns {Uint8Array} An array of 8-bit integers. - */ - stringToUint8Array: function (str) { - return transform(str, str => { - if (!util.isString(str)) { - throw new Error('stringToUint8Array: Data must be in the form of a string'); - } - - const result = new Uint8Array(str.length); - for (let i = 0; i < str.length; i++) { - result[i] = str.charCodeAt(i); - } - return result; - }); - }, - - /** - * Convert an array of 8-bit integers to a string - * @param {Uint8Array} bytes - An array of 8-bit integers to convert - * @returns {String} String representation of the array. - */ - uint8ArrayToString: function (bytes) { - bytes = new Uint8Array(bytes); - const result = []; - const bs = 1 << 14; - const j = bytes.length; - - for (let i = 0; i < j; i += bs) { - result.push(String.fromCharCode.apply(String, bytes.subarray(i, i + bs < j ? i + bs : j))); - } - return result.join(''); - }, - - /** - * Convert a native javascript string to a Uint8Array of utf8 bytes - * @param {String|ReadableStream} str - The string to convert - * @returns {Uint8Array|ReadableStream} A valid squence of utf8 bytes. - */ - encodeUTF8: function (str) { - const encoder = new TextEncoder('utf-8'); - // eslint-disable-next-line no-inner-declarations - function process(value, lastChunk = false) { - return encoder.encode(value, { stream: !lastChunk }); - } - return transform(str, process, () => process('', true)); - }, - - /** - * Convert a Uint8Array of utf8 bytes to a native javascript string - * @param {Uint8Array|ReadableStream} utf8 - A valid squence of utf8 bytes - * @returns {String|ReadableStream} A native javascript string. - */ - decodeUTF8: function (utf8) { - const decoder = new TextDecoder('utf-8'); - // eslint-disable-next-line no-inner-declarations - function process(value, lastChunk = false) { - return decoder.decode(value, { stream: !lastChunk }); - } - return transform(utf8, process, () => process(new Uint8Array(), true)); - }, - - /** - * Concat a list of Uint8Arrays, Strings or Streams - * The caller must not mix Uint8Arrays with Strings, but may mix Streams with non-Streams. - * @param {Array} Array - Of Uint8Arrays/Strings/Streams to concatenate - * @returns {Uint8Array|String|ReadableStream} Concatenated array. - */ - concat: concat, - - /** - * Concat Uint8Arrays - * @param {Array} Array - Of Uint8Arrays to concatenate - * @returns {Uint8Array} Concatenated array. - */ - concatUint8Array: concatUint8Array, - - /** - * Check Uint8Array equality - * @param {Uint8Array} array1 - First array - * @param {Uint8Array} array2 - Second array - * @returns {Boolean} Equality. - */ - equalsUint8Array: function (array1, array2) { - if (!util.isUint8Array(array1) || !util.isUint8Array(array2)) { - throw new Error('Data must be in the form of a Uint8Array'); - } - - if (array1.length !== array2.length) { - return false; - } - - for (let i = 0; i < array1.length; i++) { - if (array1[i] !== array2[i]) { - return false; - } - } - return true; - }, - - /** - * Calculates a 16bit sum of a Uint8Array by adding each character - * codes modulus 65535 - * @param {Uint8Array} Uint8Array - To create a sum of - * @returns {Uint8Array} 2 bytes containing the sum of all charcodes % 65535. - */ - writeChecksum: function (text) { - let s = 0; - for (let i = 0; i < text.length; i++) { - s = (s + text[i]) & 0xFFFF; - } - return util.writeNumber(s, 2); - }, - - /** - * Helper function to print a debug message. Debug - * messages are only printed if - * @param {String} str - String of the debug message - */ - printDebug: function (str) { - if (debugMode) { - console.log(str); - } - }, - - /** - * Helper function to print a debug error. Debug - * messages are only printed if - * @param {String} str - String of the debug message - */ - printDebugError: function (error) { - if (debugMode) { - console.error(error); - } - }, - - // returns bit length of the integer x - nbits: function (x) { - let r = 1; - let t = x >>> 16; - if (t !== 0) { - x = t; - r += 16; - } - t = x >> 8; - if (t !== 0) { - x = t; - r += 8; - } - t = x >> 4; - if (t !== 0) { - x = t; - r += 4; - } - t = x >> 2; - if (t !== 0) { - x = t; - r += 2; - } - t = x >> 1; - if (t !== 0) { - x = t; - r += 1; - } - return r; - }, - - /** - * If S[1] == 0, then double(S) == (S[2..128] || 0); - * otherwise, double(S) == (S[2..128] || 0) xor - * (zeros(120) || 10000111). - * - * Both OCB and EAX (through CMAC) require this function to be constant-time. - * - * @param {Uint8Array} data - */ - double: function(data) { - const doubleVar = new Uint8Array(data.length); - const last = data.length - 1; - for (let i = 0; i < last; i++) { - doubleVar[i] = (data[i] << 1) ^ (data[i + 1] >> 7); - } - doubleVar[last] = (data[last] << 1) ^ ((data[0] >> 7) * 0x87); - return doubleVar; - }, - - /** - * Shift a Uint8Array to the right by n bits - * @param {Uint8Array} array - The array to shift - * @param {Integer} bits - Amount of bits to shift (MUST be smaller - * than 8) - * @returns {String} Resulting array. - */ - shiftRight: function (array, bits) { - if (bits) { - for (let i = array.length - 1; i >= 0; i--) { - array[i] >>= bits; - if (i > 0) { - array[i] |= (array[i - 1] << (8 - bits)); - } - } - } - return array; - }, - - /** - * Get native Web Cryptography api, only the current version of the spec. - * @returns {Object} The SubtleCrypto api or 'undefined'. - */ - getWebCrypto: function() { - return typeof globalThis !== 'undefined' && globalThis.crypto && globalThis.crypto.subtle; - }, - - /** - * Detect Node.js runtime. - */ - detectNode: function() { - return typeof globalThis.process === 'object' && - typeof globalThis.process.versions === 'object'; - }, - - /** - * Detect native BigInt support - */ - detectBigInt: () => typeof BigInt !== 'undefined', - - /** - * Get BigInteger class - * It wraps the native BigInt type if it's available - * Otherwise it relies on bn.js - * @returns {BigInteger} - * @async - */ - getBigInteger, - - /** - * Get native Node.js crypto api. - * @returns {Object} The crypto module or 'undefined'. - */ - getNodeCrypto: function() { - return crypto__default['default']; - }, - - getNodeZlib: function() { - return zlib__default['default']; - }, - - /** - * Get native Node.js Buffer constructor. This should be used since - * Buffer is not available under browserify. - * @returns {Function} The Buffer constructor or 'undefined'. - */ - getNodeBuffer: function() { - return (buffer__default['default'] || {}).Buffer; - }, - - getHardwareConcurrency: function() { - if (util.detectNode()) { - const os = os__default['default']; - return os.cpus().length; - } - - return navigator.hardwareConcurrency || 1; - }, - - isEmailAddress: function(data) { - if (!util.isString(data)) { - return false; - } - const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+([a-zA-Z]{2,}|xn--[a-zA-Z\-0-9]+)))$/; - return re.test(data); - }, - - /** - * Normalize line endings to - * Support any encoding where CR=0x0D, LF=0x0A - */ - canonicalizeEOL: function(data) { - const CR = 13; - const LF = 10; - let carryOverCR = false; - - return transform(data, bytes => { - if (carryOverCR) { - bytes = util.concatUint8Array([new Uint8Array([CR]), bytes]); - } - - if (bytes[bytes.length - 1] === CR) { - carryOverCR = true; - bytes = bytes.subarray(0, -1); - } else { - carryOverCR = false; - } - - let index; - const indices = []; - for (let i = 0; ; i = index) { - index = bytes.indexOf(LF, i) + 1; - if (index) { - if (bytes[index - 2] !== CR) indices.push(index); - } else { - break; - } - } - if (!indices.length) { - return bytes; - } - - const normalized = new Uint8Array(bytes.length + indices.length); - let j = 0; - for (let i = 0; i < indices.length; i++) { - const sub = bytes.subarray(indices[i - 1] || 0, indices[i]); - normalized.set(sub, j); - j += sub.length; - normalized[j - 1] = CR; - normalized[j] = LF; - j++; - } - normalized.set(bytes.subarray(indices[indices.length - 1] || 0), j); - return normalized; - }, () => (carryOverCR ? new Uint8Array([CR]) : undefined)); - }, - - /** - * Convert line endings from canonicalized to native - * Support any encoding where CR=0x0D, LF=0x0A - */ - nativeEOL: function(data) { - const CR = 13; - const LF = 10; - let carryOverCR = false; - - return transform(data, bytes => { - if (carryOverCR && bytes[0] !== LF) { - bytes = util.concatUint8Array([new Uint8Array([CR]), bytes]); - } else { - bytes = new Uint8Array(bytes); // Don't mutate passed bytes - } - - if (bytes[bytes.length - 1] === CR) { - carryOverCR = true; - bytes = bytes.subarray(0, -1); - } else { - carryOverCR = false; - } - - let index; - let j = 0; - for (let i = 0; i !== bytes.length; i = index) { - index = bytes.indexOf(CR, i) + 1; - if (!index) index = bytes.length; - const last = index - (bytes[index] === LF ? 1 : 0); - if (i) bytes.copyWithin(j, i, last); - j += last - i; - } - return bytes.subarray(0, j); - }, () => (carryOverCR ? new Uint8Array([CR]) : undefined)); - }, - - /** - * Remove trailing spaces and tabs from each line - */ - removeTrailingSpaces: function(text) { - return text.split('\n').map(line => { - let i = line.length - 1; - for (; i >= 0 && (line[i] === ' ' || line[i] === '\t'); i--); - return line.substr(0, i + 1); - }).join('\n'); - }, - - wrapError: function(message, error) { - if (!error) { - return new Error(message); - } - - // update error message - try { - error.message = message + ': ' + error.message; - } catch (e) {} - - return error; - }, - - /** - * Map allowed packet tags to corresponding classes - * Meant to be used to format `allowedPacket` for Packetlist.read - * @param {Array} allowedClasses - * @returns {Object} map from enum.packet to corresponding *Packet class - */ - constructAllowedPackets: function(allowedClasses) { - const map = {}; - allowedClasses.forEach(PacketClass => { - if (!PacketClass.tag) { - throw new Error('Invalid input: expected a packet class'); - } - map[PacketClass.tag] = PacketClass; - }); - return map; - }, - - /** - * Return a Promise that will resolve as soon as one of the promises in input resolves - * or will reject if all input promises all rejected - * (similar to Promise.any, but with slightly different error handling) - * @param {Array} promises - * @return {Promise} Promise resolving to the result of the fastest fulfilled promise - * or rejected with the Error of the last resolved Promise (if all promises are rejected) - */ - anyPromise: function(promises) { - return new Promise(async (resolve, reject) => { - let exception; - await Promise.all(promises.map(async promise => { - try { - resolve(await promise); - } catch (e) { - exception = e; - } - })); - reject(exception); - }); - }, - - /** - * Return either `a` or `b` based on `cond`, in algorithmic constant time. - * @param {Boolean} cond - * @param {Uint8Array} a - * @param {Uint8Array} b - * @returns `a` if `cond` is true, `b` otherwise - */ - selectUint8Array: function(cond, a, b) { - const length = Math.max(a.length, b.length); - const result = new Uint8Array(length); - let end = 0; - for (let i = 0; i < result.length; i++) { - result[i] = (a[i] & (256 - cond)) | (b[i] & (255 + cond)); - end += (cond & i < a.length) | ((1 - cond) & i < b.length); - } - return result.subarray(0, end); - }, - /** - * Return either `a` or `b` based on `cond`, in algorithmic constant time. - * NB: it only supports `a, b` with values between 0-255. - * @param {Boolean} cond - * @param {Uint8} a - * @param {Uint8} b - * @returns `a` if `cond` is true, `b` otherwise - */ - selectUint8: function(cond, a, b) { - return (a & (256 - cond)) | (b & (255 + cond)); - } -}; - -/* OpenPGP radix-64/base64 string encoding/decoding - * Copyright 2005 Herbert Hanewinkel, www.haneWIN.de - * version 1.0, check www.haneWIN.de for the latest version - * - * This software is provided as-is, without express or implied warranty. - * Permission to use, copy, modify, distribute or sell this software, with or - * without fee, for any purpose and by any individual or organization, is hereby - * granted, provided that the above copyright notice and this paragraph appear - * in all copies. Distribution as a part of an application or binary must - * include the above copyright notice in the documentation and/or other materials - * provided with the application or distribution. - */ - -const Buffer = util.getNodeBuffer(); - -let encodeChunk; -let decodeChunk; -if (Buffer) { - encodeChunk = buf => Buffer.from(buf).toString('base64'); - decodeChunk = str => { - const b = Buffer.from(str, 'base64'); - return new Uint8Array(b.buffer, b.byteOffset, b.byteLength); - }; -} else { - encodeChunk = buf => btoa(util.uint8ArrayToString(buf)); - decodeChunk = str => util.stringToUint8Array(atob(str)); -} - -/** - * Convert binary array to radix-64 - * @param {Uint8Array | ReadableStream} data - Uint8Array to convert - * @returns {String | ReadableStream} Radix-64 version of input string. - * @static - */ -function encode(data) { - let buf = new Uint8Array(); - return transform(data, value => { - buf = util.concatUint8Array([buf, value]); - const r = []; - const bytesPerLine = 45; // 60 chars per line * (3 bytes / 4 chars of base64). - const lines = Math.floor(buf.length / bytesPerLine); - const bytes = lines * bytesPerLine; - const encoded = encodeChunk(buf.subarray(0, bytes)); - for (let i = 0; i < lines; i++) { - r.push(encoded.substr(i * 60, 60)); - r.push('\n'); - } - buf = buf.subarray(bytes); - return r.join(''); - }, () => (buf.length ? encodeChunk(buf) + '\n' : '')); -} - -/** - * Convert radix-64 to binary array - * @param {String | ReadableStream} data - Radix-64 string to convert - * @returns {Uint8Array | ReadableStream} Binary array version of input string. - * @static - */ -function decode(data) { - let buf = ''; - return transform(data, value => { - buf += value; - - // Count how many whitespace characters there are in buf - let spaces = 0; - const spacechars = [' ', '\t', '\r', '\n']; - for (let i = 0; i < spacechars.length; i++) { - const spacechar = spacechars[i]; - for (let pos = buf.indexOf(spacechar); pos !== -1; pos = buf.indexOf(spacechar, pos + 1)) { - spaces++; - } - } - - // Backtrack until we have 4n non-whitespace characters - // that we can safely base64-decode - let length = buf.length; - for (; length > 0 && (length - spaces) % 4 !== 0; length--) { - if (spacechars.includes(buf[length])) spaces--; - } - - const decoded = decodeChunk(buf.substr(0, length)); - buf = buf.substr(length); - return decoded; - }, () => decodeChunk(buf)); -} - -/** - * Convert a Base-64 encoded string an array of 8-bit integer - * - * Note: accepts both Radix-64 and URL-safe strings - * @param {String} base64 - Base-64 encoded string to convert - * @returns {Uint8Array} An array of 8-bit integers. - */ -function b64ToUint8Array(base64) { - return decode(base64.replace(/-/g, '+').replace(/_/g, '/')); -} - -/** - * Convert an array of 8-bit integer to a Base-64 encoded string - * @param {Uint8Array} bytes - An array of 8-bit integers to convert - * @param {bool} url - If true, output is URL-safe - * @returns {String} Base-64 encoded string. - */ -function uint8ArrayToB64(bytes, url) { - let encoded = encode(bytes).replace(/[\r\n]/g, ''); - if (url) { - encoded = encoded.replace(/[+]/g, '-').replace(/[/]/g, '_').replace(/[=]/g, ''); - } - return encoded; -} - -/** - * @module enums - */ - -const byValue = Symbol('byValue'); - -var enums = { - - /** Maps curve names under various standards to one - * @see {@link https://wiki.gnupg.org/ECC|ECC - GnuPG wiki} - * @enum {String} - * @readonly - */ - curve: { - /** NIST P-256 Curve */ - 'p256': 'p256', - 'P-256': 'p256', - 'secp256r1': 'p256', - 'prime256v1': 'p256', - '1.2.840.10045.3.1.7': 'p256', - '2a8648ce3d030107': 'p256', - '2A8648CE3D030107': 'p256', - - /** NIST P-384 Curve */ - 'p384': 'p384', - 'P-384': 'p384', - 'secp384r1': 'p384', - '1.3.132.0.34': 'p384', - '2b81040022': 'p384', - '2B81040022': 'p384', - - /** NIST P-521 Curve */ - 'p521': 'p521', - 'P-521': 'p521', - 'secp521r1': 'p521', - '1.3.132.0.35': 'p521', - '2b81040023': 'p521', - '2B81040023': 'p521', - - /** SECG SECP256k1 Curve */ - 'secp256k1': 'secp256k1', - '1.3.132.0.10': 'secp256k1', - '2b8104000a': 'secp256k1', - '2B8104000A': 'secp256k1', - - /** Ed25519 */ - 'ED25519': 'ed25519', - 'ed25519': 'ed25519', - 'Ed25519': 'ed25519', - '1.3.6.1.4.1.11591.15.1': 'ed25519', - '2b06010401da470f01': 'ed25519', - '2B06010401DA470F01': 'ed25519', - - /** Curve25519 */ - 'X25519': 'curve25519', - 'cv25519': 'curve25519', - 'curve25519': 'curve25519', - 'Curve25519': 'curve25519', - '1.3.6.1.4.1.3029.1.5.1': 'curve25519', - '2b060104019755010501': 'curve25519', - '2B060104019755010501': 'curve25519', - - /** BrainpoolP256r1 Curve */ - 'brainpoolP256r1': 'brainpoolP256r1', - '1.3.36.3.3.2.8.1.1.7': 'brainpoolP256r1', - '2b2403030208010107': 'brainpoolP256r1', - '2B2403030208010107': 'brainpoolP256r1', - - /** BrainpoolP384r1 Curve */ - 'brainpoolP384r1': 'brainpoolP384r1', - '1.3.36.3.3.2.8.1.1.11': 'brainpoolP384r1', - '2b240303020801010b': 'brainpoolP384r1', - '2B240303020801010B': 'brainpoolP384r1', - - /** BrainpoolP512r1 Curve */ - 'brainpoolP512r1': 'brainpoolP512r1', - '1.3.36.3.3.2.8.1.1.13': 'brainpoolP512r1', - '2b240303020801010d': 'brainpoolP512r1', - '2B240303020801010D': 'brainpoolP512r1' - }, - - /** A string to key specifier type - * @enum {Integer} - * @readonly - */ - s2k: { - simple: 0, - salted: 1, - iterated: 3, - gnu: 101 - }, - - /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-9.1|RFC4880bis-04, section 9.1} - * @enum {Integer} - * @readonly - */ - publicKey: { - /** RSA (Encrypt or Sign) [HAC] */ - rsaEncryptSign: 1, - /** RSA (Encrypt only) [HAC] */ - rsaEncrypt: 2, - /** RSA (Sign only) [HAC] */ - rsaSign: 3, - /** Elgamal (Encrypt only) [ELGAMAL] [HAC] */ - elgamal: 16, - /** DSA (Sign only) [FIPS186] [HAC] */ - dsa: 17, - /** ECDH (Encrypt only) [RFC6637] */ - ecdh: 18, - /** ECDSA (Sign only) [RFC6637] */ - ecdsa: 19, - /** EdDSA (Sign only) - * [{@link https://tools.ietf.org/html/draft-koch-eddsa-for-openpgp-04|Draft RFC}] */ - eddsa: 22, - /** Reserved for AEDH */ - aedh: 23, - /** Reserved for AEDSA */ - aedsa: 24 - }, - - /** {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC4880, section 9.2} - * @enum {Integer} - * @readonly - */ - symmetric: { - plaintext: 0, - /** Not implemented! */ - idea: 1, - tripledes: 2, - cast5: 3, - blowfish: 4, - aes128: 7, - aes192: 8, - aes256: 9, - twofish: 10 - }, - - /** {@link https://tools.ietf.org/html/rfc4880#section-9.3|RFC4880, section 9.3} - * @enum {Integer} - * @readonly - */ - compression: { - uncompressed: 0, - /** RFC1951 */ - zip: 1, - /** RFC1950 */ - zlib: 2, - bzip2: 3 - }, - - /** {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC4880, section 9.4} - * @enum {Integer} - * @readonly - */ - hash: { - md5: 1, - sha1: 2, - ripemd: 3, - sha256: 8, - sha384: 9, - sha512: 10, - sha224: 11 - }, - - /** A list of hash names as accepted by webCrypto functions. - * {@link https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest|Parameters, algo} - * @enum {String} - */ - webHash: { - 'SHA-1': 2, - 'SHA-256': 8, - 'SHA-384': 9, - 'SHA-512': 10 - }, - - /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-9.6|RFC4880bis-04, section 9.6} - * @enum {Integer} - * @readonly - */ - aead: { - eax: 1, - ocb: 2, - experimentalGCM: 100 // Private algorithm - }, - - /** A list of packet types and numeric tags associated with them. - * @enum {Integer} - * @readonly - */ - packet: { - publicKeyEncryptedSessionKey: 1, - signature: 2, - symEncryptedSessionKey: 3, - onePassSignature: 4, - secretKey: 5, - publicKey: 6, - secretSubkey: 7, - compressedData: 8, - symmetricallyEncryptedData: 9, - marker: 10, - literalData: 11, - trust: 12, - userID: 13, - publicSubkey: 14, - userAttribute: 17, - symEncryptedIntegrityProtectedData: 18, - modificationDetectionCode: 19, - aeadEncryptedData: 20 // see IETF draft: https://tools.ietf.org/html/draft-ford-openpgp-format-00#section-2.1 - }, - - /** Data types in the literal packet - * @enum {Integer} - * @readonly - */ - literal: { - /** Binary data 'b' */ - binary: 'b'.charCodeAt(), - /** Text data 't' */ - text: 't'.charCodeAt(), - /** Utf8 data 'u' */ - utf8: 'u'.charCodeAt(), - /** MIME message body part 'm' */ - mime: 'm'.charCodeAt() - }, - - - /** One pass signature packet type - * @enum {Integer} - * @readonly - */ - signature: { - /** 0x00: Signature of a binary document. */ - binary: 0, - /** 0x01: Signature of a canonical text document. - * - * Canonicalyzing the document by converting line endings. */ - text: 1, - /** 0x02: Standalone signature. - * - * This signature is a signature of only its own subpacket contents. - * It is calculated identically to a signature over a zero-lengh - * binary document. Note that it doesn't make sense to have a V3 - * standalone signature. */ - standalone: 2, - /** 0x10: Generic certification of a User ID and Public-Key packet. - * - * The issuer of this certification does not make any particular - * assertion as to how well the certifier has checked that the owner - * of the key is in fact the person described by the User ID. */ - certGeneric: 16, - /** 0x11: Persona certification of a User ID and Public-Key packet. - * - * The issuer of this certification has not done any verification of - * the claim that the owner of this key is the User ID specified. */ - certPersona: 17, - /** 0x12: Casual certification of a User ID and Public-Key packet. - * - * The issuer of this certification has done some casual - * verification of the claim of identity. */ - certCasual: 18, - /** 0x13: Positive certification of a User ID and Public-Key packet. - * - * The issuer of this certification has done substantial - * verification of the claim of identity. - * - * Most OpenPGP implementations make their "key signatures" as 0x10 - * certifications. Some implementations can issue 0x11-0x13 - * certifications, but few differentiate between the types. */ - certPositive: 19, - /** 0x30: Certification revocation signature - * - * This signature revokes an earlier User ID certification signature - * (signature class 0x10 through 0x13) or direct-key signature - * (0x1F). It should be issued by the same key that issued the - * revoked signature or an authorized revocation key. The signature - * is computed over the same data as the certificate that it - * revokes, and should have a later creation date than that - * certificate. */ - certRevocation: 48, - /** 0x18: Subkey Binding Signature - * - * This signature is a statement by the top-level signing key that - * indicates that it owns the subkey. This signature is calculated - * directly on the primary key and subkey, and not on any User ID or - * other packets. A signature that binds a signing subkey MUST have - * an Embedded Signature subpacket in this binding signature that - * contains a 0x19 signature made by the signing subkey on the - * primary key and subkey. */ - subkeyBinding: 24, - /** 0x19: Primary Key Binding Signature - * - * This signature is a statement by a signing subkey, indicating - * that it is owned by the primary key and subkey. This signature - * is calculated the same way as a 0x18 signature: directly on the - * primary key and subkey, and not on any User ID or other packets. - * - * When a signature is made over a key, the hash data starts with the - * octet 0x99, followed by a two-octet length of the key, and then body - * of the key packet. (Note that this is an old-style packet header for - * a key packet with two-octet length.) A subkey binding signature - * (type 0x18) or primary key binding signature (type 0x19) then hashes - * the subkey using the same format as the main key (also using 0x99 as - * the first octet). */ - keyBinding: 25, - /** 0x1F: Signature directly on a key - * - * This signature is calculated directly on a key. It binds the - * information in the Signature subpackets to the key, and is - * appropriate to be used for subpackets that provide information - * about the key, such as the Revocation Key subpacket. It is also - * appropriate for statements that non-self certifiers want to make - * about the key itself, rather than the binding between a key and a - * name. */ - key: 31, - /** 0x20: Key revocation signature - * - * The signature is calculated directly on the key being revoked. A - * revoked key is not to be used. Only revocation signatures by the - * key being revoked, or by an authorized revocation key, should be - * considered valid revocation signatures.a */ - keyRevocation: 32, - /** 0x28: Subkey revocation signature - * - * The signature is calculated directly on the subkey being revoked. - * A revoked subkey is not to be used. Only revocation signatures - * by the top-level signature key that is bound to this subkey, or - * by an authorized revocation key, should be considered valid - * revocation signatures. - * - * Key revocation signatures (types 0x20 and 0x28) - * hash only the key being revoked. */ - subkeyRevocation: 40, - /** 0x40: Timestamp signature. - * This signature is only meaningful for the timestamp contained in - * it. */ - timestamp: 64, - /** 0x50: Third-Party Confirmation signature. - * - * This signature is a signature over some other OpenPGP Signature - * packet(s). It is analogous to a notary seal on the signed data. - * A third-party signature SHOULD include Signature Target - * subpacket(s) to give easy identification. Note that we really do - * mean SHOULD. There are plausible uses for this (such as a blind - * party that only sees the signature, not the key or source - * document) that cannot include a target subpacket. */ - thirdParty: 80 - }, - - /** Signature subpacket type - * @enum {Integer} - * @readonly - */ - signatureSubpacket: { - signatureCreationTime: 2, - signatureExpirationTime: 3, - exportableCertification: 4, - trustSignature: 5, - regularExpression: 6, - revocable: 7, - keyExpirationTime: 9, - placeholderBackwardsCompatibility: 10, - preferredSymmetricAlgorithms: 11, - revocationKey: 12, - issuer: 16, - notationData: 20, - preferredHashAlgorithms: 21, - preferredCompressionAlgorithms: 22, - keyServerPreferences: 23, - preferredKeyServer: 24, - primaryUserID: 25, - policyURI: 26, - keyFlags: 27, - signersUserID: 28, - reasonForRevocation: 29, - features: 30, - signatureTarget: 31, - embeddedSignature: 32, - issuerFingerprint: 33, - preferredAEADAlgorithms: 34 - }, - - /** Key flags - * @enum {Integer} - * @readonly - */ - keyFlags: { - /** 0x01 - This key may be used to certify other keys. */ - certifyKeys: 1, - /** 0x02 - This key may be used to sign data. */ - signData: 2, - /** 0x04 - This key may be used to encrypt communications. */ - encryptCommunication: 4, - /** 0x08 - This key may be used to encrypt storage. */ - encryptStorage: 8, - /** 0x10 - The private component of this key may have been split - * by a secret-sharing mechanism. */ - splitPrivateKey: 16, - /** 0x20 - This key may be used for authentication. */ - authentication: 32, - /** 0x80 - The private component of this key may be in the - * possession of more than one person. */ - sharedPrivateKey: 128 - }, - - /** Armor type - * @enum {Integer} - * @readonly - */ - armor: { - multipartSection: 0, - multipartLast: 1, - signed: 2, - message: 3, - publicKey: 4, - privateKey: 5, - signature: 6 - }, - - /** {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.23|RFC4880, section 5.2.3.23} - * @enum {Integer} - * @readonly - */ - reasonForRevocation: { - /** No reason specified (key revocations or cert revocations) */ - noReason: 0, - /** Key is superseded (key revocations) */ - keySuperseded: 1, - /** Key material has been compromised (key revocations) */ - keyCompromised: 2, - /** Key is retired and no longer used (key revocations) */ - keyRetired: 3, - /** User ID information is no longer valid (cert revocations) */ - userIDInvalid: 32 - }, - - /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.2.3.25|RFC4880bis-04, section 5.2.3.25} - * @enum {Integer} - * @readonly - */ - features: { - /** 0x01 - Modification Detection (packets 18 and 19) */ - modificationDetection: 1, - /** 0x02 - AEAD Encrypted Data Packet (packet 20) and version 5 - * Symmetric-Key Encrypted Session Key Packets (packet 3) */ - aead: 2, - /** 0x04 - Version 5 Public-Key Packet format and corresponding new - * fingerprint format */ - v5Keys: 4 - }, - - /** - * Asserts validity of given value and converts from string/integer to integer. - * @param {Object} type target enum type - * @param {String|Integer} e value to check and/or convert - * @returns {Integer} enum value if it exists - * @throws {Error} if the value is invalid - */ - write: function(type, e) { - if (typeof e === 'number') { - e = this.read(type, e); - } - - if (type[e] !== undefined) { - return type[e]; - } - - throw new Error('Invalid enum value.'); - }, - - /** - * Converts enum integer value to the corresponding string, if it exists. - * @param {Object} type target enum type - * @param {Integer} e value to convert - * @returns {String} name of enum value if it exists - * @throws {Error} if the value is invalid - */ - read: function(type, e) { - if (!type[byValue]) { - type[byValue] = []; - Object.entries(type).forEach(([key, value]) => { - type[byValue][value] = key; - }); - } - - if (type[byValue][e] !== undefined) { - return type[byValue][e]; - } - - throw new Error('Invalid enum value.'); - } -}; - -// GPG4Browsers - An OpenPGP implementation in javascript - -var defaultConfig = { - /** - * @memberof module:config - * @property {Integer} preferredHashAlgorithm Default hash algorithm {@link module:enums.hash} - */ - preferredHashAlgorithm: enums.hash.sha256, - /** - * @memberof module:config - * @property {Integer} preferredSymmetricAlgorithm Default encryption cipher {@link module:enums.symmetric} - */ - preferredSymmetricAlgorithm: enums.symmetric.aes256, - /** - * @memberof module:config - * @property {Integer} compression Default compression algorithm {@link module:enums.compression} - */ - preferredCompressionAlgorithm: enums.compression.uncompressed, - /** - * @memberof module:config - * @property {Integer} deflateLevel Default zip/zlib compression level, between 1 and 9 - */ - deflateLevel: 6, - - /** - * Use Authenticated Encryption with Additional Data (AEAD) protection for symmetric encryption. - * Note: not all OpenPGP implementations are compatible with this option. - * **FUTURE OPENPGP.JS VERSIONS MAY BREAK COMPATIBILITY WHEN USING THIS OPTION** - * @see {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-07|RFC4880bis-07} - * @memberof module:config - * @property {Boolean} aeadProtect - */ - aeadProtect: false, - /** - * Default Authenticated Encryption with Additional Data (AEAD) encryption mode - * Only has an effect when aeadProtect is set to true. - * @memberof module:config - * @property {Integer} preferredAEADAlgorithm Default AEAD mode {@link module:enums.aead} - */ - preferredAEADAlgorithm: enums.aead.eax, - /** - * Chunk Size Byte for Authenticated Encryption with Additional Data (AEAD) mode - * Only has an effect when aeadProtect is set to true. - * Must be an integer value from 0 to 56. - * @memberof module:config - * @property {Integer} aeadChunkSizeByte - */ - aeadChunkSizeByte: 12, - /** - * Use V5 keys. - * Note: not all OpenPGP implementations are compatible with this option. - * **FUTURE OPENPGP.JS VERSIONS MAY BREAK COMPATIBILITY WHEN USING THIS OPTION** - * @memberof module:config - * @property {Boolean} v5Keys - */ - v5Keys: false, - /** - * {@link https://tools.ietf.org/html/rfc4880#section-3.7.1.3|RFC4880 3.7.1.3}: - * Iteration Count Byte for S2K (String to Key) - * @memberof module:config - * @property {Integer} s2kIterationCountByte - */ - s2kIterationCountByte: 224, - /** - * Allow decryption of messages without integrity protection. - * This is an **insecure** setting: - * - message modifications cannot be detected, thus processing the decrypted data is potentially unsafe. - * - it enables downgrade attacks against integrity-protected messages. - * @memberof module:config - * @property {Boolean} allowUnauthenticatedMessages - */ - allowUnauthenticatedMessages: false, - /** - * Allow streaming unauthenticated data before its integrity has been checked. - * This setting is **insecure** if the partially decrypted message is processed further or displayed to the user. - * @memberof module:config - * @property {Boolean} allowUnauthenticatedStream - */ - allowUnauthenticatedStream: false, - /** - * @memberof module:config - * @property {Boolean} checksumRequired Do not throw error when armor is missing a checksum - */ - checksumRequired: false, - /** - * Minimum RSA key size allowed for key generation and message signing, verification and encryption. - * The default is 2047 since due to a bug, previous versions of OpenPGP.js could generate 2047-bit keys instead of 2048-bit ones. - * @memberof module:config - * @property {Number} minRSABits - */ - minRSABits: 2047, - /** - * Work-around for rare GPG decryption bug when encrypting with multiple passwords. - * **Slower and slightly less secure** - * @memberof module:config - * @property {Boolean} passwordCollisionCheck - */ - passwordCollisionCheck: false, - /** - * @memberof module:config - * @property {Boolean} revocationsExpire If true, expired revocation signatures are ignored - */ - revocationsExpire: false, - /** - * Allow decryption using RSA keys without `encrypt` flag. - * This setting is potentially insecure, but it is needed to get around an old openpgpjs bug - * where key flags were ignored when selecting a key for encryption. - * @memberof module:config - * @property {Boolean} allowInsecureDecryptionWithSigningKeys - */ - allowInsecureDecryptionWithSigningKeys: false, - /** - * Allow verification of message signatures with keys whose validity at the time of signing cannot be determined. - * Instead, a verification key will also be consider valid as long as it is valid at the current time. - * This setting is potentially insecure, but it is needed to verify messages signed with keys that were later reformatted, - * and have self-signature's creation date that does not match the primary key creation date. - * @memberof module:config - * @property {Boolean} allowInsecureDecryptionWithSigningKeys - */ - allowInsecureVerificationWithReformattedKeys: false, - - /** - * Enable constant-time decryption of RSA- and ElGamal-encrypted session keys, to hinder Bleichenbacher-like attacks (https://link.springer.com/chapter/10.1007/BFb0055716). - * This setting has measurable performance impact and it is only helpful in application scenarios where both of the following conditions apply: - * - new/incoming messages are automatically decrypted (without user interaction); - * - an attacker can determine how long it takes to decrypt each message (e.g. due to decryption errors being logged remotely). - * See also `constantTimePKCS1DecryptionSupportedSymmetricAlgorithms`. - * @memberof module:config - * @property {Boolean} constantTimePKCS1Decryption - */ - constantTimePKCS1Decryption: false, - /** - * This setting is only meaningful if `constantTimePKCS1Decryption` is enabled. - * Decryption of RSA- and ElGamal-encrypted session keys of symmetric algorithms different from the ones specified here will fail. - * However, the more algorithms are added, the slower the decryption procedure becomes. - * @memberof module:config - * @property {Set} constantTimePKCS1DecryptionSupportedSymmetricAlgorithms {@link module:enums.symmetric} - */ - constantTimePKCS1DecryptionSupportedSymmetricAlgorithms: new Set([enums.symmetric.aes128, enums.symmetric.aes192, enums.symmetric.aes256]), - - /** - * @memberof module:config - * @property {Integer} minBytesForWebCrypto The minimum amount of bytes for which to use native WebCrypto APIs when available - */ - minBytesForWebCrypto: 1000, - /** - * @memberof module:config - * @property {Boolean} ignoreUnsupportedPackets Ignore unsupported/unrecognizable packets on parsing instead of throwing an error - */ - ignoreUnsupportedPackets: true, - /** - * @memberof module:config - * @property {Boolean} ignoreMalformedPackets Ignore malformed packets on parsing instead of throwing an error - */ - ignoreMalformedPackets: false, - /** - * @memberof module:config - * @property {Boolean} showVersion Whether to include {@link module:config/config.versionString} in armored messages - */ - showVersion: false, - /** - * @memberof module:config - * @property {Boolean} showComment Whether to include {@link module:config/config.commentString} in armored messages - */ - showComment: false, - /** - * @memberof module:config - * @property {String} versionString A version string to be included in armored messages - */ - versionString: 'OpenPGP.js 5.1.0', - /** - * @memberof module:config - * @property {String} commentString A comment string to be included in armored messages - */ - commentString: 'https://openpgpjs.org', - - /** - * Max userID string length (used for parsing) - * @memberof module:config - * @property {Integer} maxUserIDLength - */ - maxUserIDLength: 1024 * 5, - /** - * Contains notatations that are considered "known". Known notations do not trigger - * validation error when the notation is marked as critical. - * @memberof module:config - * @property {Array} knownNotations - */ - knownNotations: ['preferred-email-encoding@pgp.com', 'pka-address@gnupg.org'], - /** - * Whether to use the indutny/elliptic library for curves (other than Curve25519) that are not supported by the available native crypto API. - * When false, certain standard curves will not be supported (depending on the platform). - * Note: the indutny/elliptic curve library is not designed to be constant time. - * @memberof module:config - * @property {Boolean} useIndutnyElliptic - */ - useIndutnyElliptic: true, - /** - * Reject insecure hash algorithms - * @memberof module:config - * @property {Set} rejectHashAlgorithms {@link module:enums.hash} - */ - rejectHashAlgorithms: new Set([enums.hash.md5, enums.hash.ripemd]), - /** - * Reject insecure message hash algorithms - * @memberof module:config - * @property {Set} rejectMessageHashAlgorithms {@link module:enums.hash} - */ - rejectMessageHashAlgorithms: new Set([enums.hash.md5, enums.hash.ripemd, enums.hash.sha1]), - /** - * Reject insecure public key algorithms for key generation and message encryption, signing or verification - * @memberof module:config - * @property {Set} rejectPublicKeyAlgorithms {@link module:enums.publicKey} - */ - rejectPublicKeyAlgorithms: new Set([enums.publicKey.elgamal, enums.publicKey.dsa]), - /** - * Reject non-standard curves for key generation, message encryption, signing or verification - * @memberof module:config - * @property {Set} rejectCurves {@link module:enums.curve} - */ - rejectCurves: new Set([enums.curve.brainpoolP256r1, enums.curve.brainpoolP384r1, enums.curve.brainpoolP512r1, enums.curve.secp256k1]) -}; - -// GPG4Browsers - An OpenPGP implementation in javascript - -/** - * Finds out which Ascii Armoring type is used. Throws error if unknown type. - * @param {String} text - ascii armored text - * @returns {Integer} 0 = MESSAGE PART n of m. - * 1 = MESSAGE PART n - * 2 = SIGNED MESSAGE - * 3 = PGP MESSAGE - * 4 = PUBLIC KEY BLOCK - * 5 = PRIVATE KEY BLOCK - * 6 = SIGNATURE - * @private - */ -function getType(text) { - const reHeader = /^-----BEGIN PGP (MESSAGE, PART \d+\/\d+|MESSAGE, PART \d+|SIGNED MESSAGE|MESSAGE|PUBLIC KEY BLOCK|PRIVATE KEY BLOCK|SIGNATURE)-----$/m; - - const header = text.match(reHeader); - - if (!header) { - throw new Error('Unknown ASCII armor type'); - } - - // BEGIN PGP MESSAGE, PART X/Y - // Used for multi-part messages, where the armor is split amongst Y - // parts, and this is the Xth part out of Y. - if (/MESSAGE, PART \d+\/\d+/.test(header[1])) { - return enums.armor.multipartSection; - } else - // BEGIN PGP MESSAGE, PART X - // Used for multi-part messages, where this is the Xth part of an - // unspecified number of parts. Requires the MESSAGE-ID Armor - // Header to be used. - if (/MESSAGE, PART \d+/.test(header[1])) { - return enums.armor.multipartLast; - } else - // BEGIN PGP SIGNED MESSAGE - if (/SIGNED MESSAGE/.test(header[1])) { - return enums.armor.signed; - } else - // BEGIN PGP MESSAGE - // Used for signed, encrypted, or compressed files. - if (/MESSAGE/.test(header[1])) { - return enums.armor.message; - } else - // BEGIN PGP PUBLIC KEY BLOCK - // Used for armoring public keys. - if (/PUBLIC KEY BLOCK/.test(header[1])) { - return enums.armor.publicKey; - } else - // BEGIN PGP PRIVATE KEY BLOCK - // Used for armoring private keys. - if (/PRIVATE KEY BLOCK/.test(header[1])) { - return enums.armor.privateKey; - } else - // BEGIN PGP SIGNATURE - // Used for detached signatures, OpenPGP/MIME signatures, and - // cleartext signatures. Note that PGP 2.x uses BEGIN PGP MESSAGE - // for detached signatures. - if (/SIGNATURE/.test(header[1])) { - return enums.armor.signature; - } -} - -/** - * Add additional information to the armor version of an OpenPGP binary - * packet block. - * @author Alex - * @version 2011-12-16 - * @param {String} [customComment] - Additional comment to add to the armored string - * @returns {String} The header information. - * @private - */ -function addheader(customComment, config) { - let result = ''; - if (config.showVersion) { - result += 'Version: ' + config.versionString + '\n'; - } - if (config.showComment) { - result += 'Comment: ' + config.commentString + '\n'; - } - if (customComment) { - result += 'Comment: ' + customComment + '\n'; - } - result += '\n'; - return result; -} - - -/** - * Calculates a checksum over the given data and returns it base64 encoded - * @param {String | ReadableStream} data - Data to create a CRC-24 checksum for - * @returns {String | ReadableStream} Base64 encoded checksum. - * @private - */ -function getCheckSum(data) { - const crc = createcrc24(data); - return encode(crc); -} - -// https://create.stephan-brumme.com/crc32/#slicing-by-8-overview - -const crc_table = [ - new Array(0xFF), - new Array(0xFF), - new Array(0xFF), - new Array(0xFF) -]; - -for (let i = 0; i <= 0xFF; i++) { - let crc = i << 16; - for (let j = 0; j < 8; j++) { - crc = (crc << 1) ^ ((crc & 0x800000) !== 0 ? 0x864CFB : 0); - } - crc_table[0][i] = - ((crc & 0xFF0000) >> 16) | - (crc & 0x00FF00) | - ((crc & 0x0000FF) << 16); -} -for (let i = 0; i <= 0xFF; i++) { - crc_table[1][i] = (crc_table[0][i] >> 8) ^ crc_table[0][crc_table[0][i] & 0xFF]; -} -for (let i = 0; i <= 0xFF; i++) { - crc_table[2][i] = (crc_table[1][i] >> 8) ^ crc_table[0][crc_table[1][i] & 0xFF]; -} -for (let i = 0; i <= 0xFF; i++) { - crc_table[3][i] = (crc_table[2][i] >> 8) ^ crc_table[0][crc_table[2][i] & 0xFF]; -} - -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView#Endianness -const isLittleEndian = (function() { - const buffer = new ArrayBuffer(2); - new DataView(buffer).setInt16(0, 0xFF, true /* littleEndian */); - // Int16Array uses the platform's endianness. - return new Int16Array(buffer)[0] === 0xFF; -}()); - -/** - * Internal function to calculate a CRC-24 checksum over a given string (data) - * @param {String | ReadableStream} input - Data to create a CRC-24 checksum for - * @returns {Uint8Array | ReadableStream} The CRC-24 checksum. - * @private - */ -function createcrc24(input) { - let crc = 0xCE04B7; - return transform(input, value => { - const len32 = isLittleEndian ? Math.floor(value.length / 4) : 0; - const arr32 = new Uint32Array(value.buffer, value.byteOffset, len32); - for (let i = 0; i < len32; i++) { - crc ^= arr32[i]; - crc = - crc_table[0][(crc >> 24) & 0xFF] ^ - crc_table[1][(crc >> 16) & 0xFF] ^ - crc_table[2][(crc >> 8) & 0xFF] ^ - crc_table[3][(crc >> 0) & 0xFF]; - } - for (let i = len32 * 4; i < value.length; i++) { - crc = (crc >> 8) ^ crc_table[0][(crc & 0xFF) ^ value[i]]; - } - }, () => new Uint8Array([crc, crc >> 8, crc >> 16])); -} - -/** - * Verify armored headers. RFC4880, section 6.3: "OpenPGP should consider improperly formatted - * Armor Headers to be corruption of the ASCII Armor." - * @private - * @param {Array} headers - Armor headers - */ -function verifyHeaders(headers) { - for (let i = 0; i < headers.length; i++) { - if (!/^([^\s:]|[^\s:][^:]*[^\s:]): .+$/.test(headers[i])) { - throw new Error('Improperly formatted armor header: ' + headers[i]); - } - if (!/^(Version|Comment|MessageID|Hash|Charset): .+$/.test(headers[i])) { - util.printDebugError(new Error('Unknown header: ' + headers[i])); - } - } -} - -/** - * Splits a message into two parts, the body and the checksum. This is an internal function - * @param {String} text - OpenPGP armored message part - * @returns {Object} An object with attribute "body" containing the body. - * and an attribute "checksum" containing the checksum. - * @private - */ -function splitChecksum(text) { - let body = text; - let checksum = ''; - - const lastEquals = text.lastIndexOf('='); - - if (lastEquals >= 0 && lastEquals !== text.length - 1) { // '=' as the last char means no checksum - body = text.slice(0, lastEquals); - checksum = text.slice(lastEquals + 1).substr(0, 4); - } - - return { body: body, checksum: checksum }; -} - -/** - * Dearmor an OpenPGP armored message; verify the checksum and return - * the encoded bytes - * @param {String} input - OpenPGP armored message - * @returns {Promise} An object with attribute "text" containing the message text, - * an attribute "data" containing a stream of bytes and "type" for the ASCII armor type - * @async - * @static - */ -function unarmor(input, config = defaultConfig) { - return new Promise(async (resolve, reject) => { - try { - const reSplit = /^-----[^-]+-----$/m; - const reEmptyLine = /^[ \f\r\t\u00a0\u2000-\u200a\u202f\u205f\u3000]*$/; - - let type; - const headers = []; - let lastHeaders = headers; - let headersDone; - let text = []; - let textDone; - let checksum; - let data = decode(transformPair(input, async (readable, writable) => { - const reader = getReader(readable); - try { - while (true) { - let line = await reader.readLine(); - if (line === undefined) { - throw new Error('Misformed armored text'); - } - // remove trailing whitespace at end of lines - line = util.removeTrailingSpaces(line.replace(/[\r\n]/g, '')); - if (!type) { - if (reSplit.test(line)) { - type = getType(line); - } - } else if (!headersDone) { - if (reSplit.test(line)) { - reject(new Error('Mandatory blank line missing between armor headers and armor data')); - } - if (!reEmptyLine.test(line)) { - lastHeaders.push(line); - } else { - verifyHeaders(lastHeaders); - headersDone = true; - if (textDone || type !== 2) { - resolve({ text, data, headers, type }); - break; - } - } - } else if (!textDone && type === 2) { - if (!reSplit.test(line)) { - // Reverse dash-escaping for msg - text.push(line.replace(/^- /, '')); - } else { - text = text.join('\r\n'); - textDone = true; - verifyHeaders(lastHeaders); - lastHeaders = []; - headersDone = false; - } - } - } - } catch (e) { - reject(e); - return; - } - const writer = getWriter(writable); - try { - while (true) { - await writer.ready; - const { done, value } = await reader.read(); - if (done) { - throw new Error('Misformed armored text'); - } - const line = value + ''; - if (line.indexOf('=') === -1 && line.indexOf('-') === -1) { - await writer.write(line); - } else { - let remainder = await reader.readToEnd(); - if (!remainder.length) remainder = ''; - remainder = line + remainder; - remainder = util.removeTrailingSpaces(remainder.replace(/\r/g, '')); - const parts = remainder.split(reSplit); - if (parts.length === 1) { - throw new Error('Misformed armored text'); - } - const split = splitChecksum(parts[0].slice(0, -1)); - checksum = split.checksum; - await writer.write(split.body); - break; - } - } - await writer.ready; - await writer.close(); - } catch (e) { - await writer.abort(e); - } - })); - data = transformPair(data, async (readable, writable) => { - const checksumVerified = readToEnd(getCheckSum(passiveClone(readable))); - checksumVerified.catch(() => {}); - await pipe(readable, writable, { - preventClose: true - }); - const writer = getWriter(writable); - try { - const checksumVerifiedString = (await checksumVerified).replace('\n', ''); - if (checksum !== checksumVerifiedString && (checksum || config.checksumRequired)) { - throw new Error('Ascii armor integrity check failed'); - } - await writer.ready; - await writer.close(); - } catch (e) { - await writer.abort(e); - } - }); - } catch (e) { - reject(e); - } - }).then(async result => { - if (isArrayStream(result.data)) { - result.data = await readToEnd(result.data); - } - return result; - }); -} - - -/** - * Armor an OpenPGP binary packet block - * @param {module:enums.armor} messageType - Type of the message - * @param {Uint8Array | ReadableStream} body - The message body to armor - * @param {Integer} [partIndex] - * @param {Integer} [partTotal] - * @param {String} [customComment] - Additional comment to add to the armored string - * @returns {String | ReadableStream} Armored text. - * @static - */ -function armor(messageType, body, partIndex, partTotal, customComment, config = defaultConfig) { - let text; - let hash; - if (messageType === enums.armor.signed) { - text = body.text; - hash = body.hash; - body = body.data; - } - const bodyClone = passiveClone(body); - const result = []; - switch (messageType) { - case enums.armor.multipartSection: - result.push('-----BEGIN PGP MESSAGE, PART ' + partIndex + '/' + partTotal + '-----\n'); - result.push(addheader(customComment, config)); - result.push(encode(body)); - result.push('=', getCheckSum(bodyClone)); - result.push('-----END PGP MESSAGE, PART ' + partIndex + '/' + partTotal + '-----\n'); - break; - case enums.armor.multipartLast: - result.push('-----BEGIN PGP MESSAGE, PART ' + partIndex + '-----\n'); - result.push(addheader(customComment, config)); - result.push(encode(body)); - result.push('=', getCheckSum(bodyClone)); - result.push('-----END PGP MESSAGE, PART ' + partIndex + '-----\n'); - break; - case enums.armor.signed: - result.push('\n-----BEGIN PGP SIGNED MESSAGE-----\n'); - result.push('Hash: ' + hash + '\n\n'); - result.push(text.replace(/^-/mg, '- -')); - result.push('\n-----BEGIN PGP SIGNATURE-----\n'); - result.push(addheader(customComment, config)); - result.push(encode(body)); - result.push('=', getCheckSum(bodyClone)); - result.push('-----END PGP SIGNATURE-----\n'); - break; - case enums.armor.message: - result.push('-----BEGIN PGP MESSAGE-----\n'); - result.push(addheader(customComment, config)); - result.push(encode(body)); - result.push('=', getCheckSum(bodyClone)); - result.push('-----END PGP MESSAGE-----\n'); - break; - case enums.armor.publicKey: - result.push('-----BEGIN PGP PUBLIC KEY BLOCK-----\n'); - result.push(addheader(customComment, config)); - result.push(encode(body)); - result.push('=', getCheckSum(bodyClone)); - result.push('-----END PGP PUBLIC KEY BLOCK-----\n'); - break; - case enums.armor.privateKey: - result.push('-----BEGIN PGP PRIVATE KEY BLOCK-----\n'); - result.push(addheader(customComment, config)); - result.push(encode(body)); - result.push('=', getCheckSum(bodyClone)); - result.push('-----END PGP PRIVATE KEY BLOCK-----\n'); - break; - case enums.armor.signature: - result.push('-----BEGIN PGP SIGNATURE-----\n'); - result.push(addheader(customComment, config)); - result.push(encode(body)); - result.push('=', getCheckSum(bodyClone)); - result.push('-----END PGP SIGNATURE-----\n'); - break; - } - - return util.concat(result); -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -/** - * Implementation of type key id - * - * {@link https://tools.ietf.org/html/rfc4880#section-3.3|RFC4880 3.3}: - * A Key ID is an eight-octet scalar that identifies a key. - * Implementations SHOULD NOT assume that Key IDs are unique. The - * section "Enhanced Key Formats" below describes how Key IDs are - * formed. - */ -class KeyID { - constructor() { - this.bytes = ''; - } - - /** - * Parsing method for a key id - * @param {Uint8Array} bytes - Input to read the key id from - */ - read(bytes) { - this.bytes = util.uint8ArrayToString(bytes.subarray(0, 8)); - } - - /** - * Serializes the Key ID - * @returns {Uint8Array} Key ID as a Uint8Array. - */ - write() { - return util.stringToUint8Array(this.bytes); - } - - /** - * Returns the Key ID represented as a hexadecimal string - * @returns {String} Key ID as a hexadecimal string. - */ - toHex() { - return util.uint8ArrayToHex(util.stringToUint8Array(this.bytes)); - } - - /** - * Checks equality of Key ID's - * @param {KeyID} keyID - * @param {Boolean} matchWildcard - Indicates whether to check if either keyID is a wildcard - */ - equals(keyID, matchWildcard = false) { - return (matchWildcard && (keyID.isWildcard() || this.isWildcard())) || this.bytes === keyID.bytes; - } - - /** - * Checks to see if the Key ID is unset - * @returns {Boolean} True if the Key ID is null. - */ - isNull() { - return this.bytes === ''; - } - - /** - * Checks to see if the Key ID is a "wildcard" Key ID (all zeros) - * @returns {Boolean} True if this is a wildcard Key ID. - */ - isWildcard() { - return /^0+$/.test(this.toHex()); - } - - static mapToHex(keyID) { - return keyID.toHex(); - } - - static fromID(hex) { - const keyID = new KeyID(); - keyID.read(util.hexToUint8Array(hex)); - return keyID; - } - - static wildcard() { - const keyID = new KeyID(); - keyID.read(new Uint8Array(8)); - return keyID; - } -} - -/** - * @file {@link http://asmjs.org Asm.js} implementation of the {@link https://en.wikipedia.org/wiki/Advanced_Encryption_Standard Advanced Encryption Standard}. - * @author Artem S Vybornov - * @license MIT - */ -var AES_asm = function () { - - /** - * Galois Field stuff init flag - */ - var ginit_done = false; - - /** - * Galois Field exponentiation and logarithm tables for 3 (the generator) - */ - var gexp3, glog3; - - /** - * Init Galois Field tables - */ - function ginit() { - gexp3 = [], - glog3 = []; - - var a = 1, c, d; - for (c = 0; c < 255; c++) { - gexp3[c] = a; - - // Multiply by three - d = a & 0x80, a <<= 1, a &= 255; - if (d === 0x80) a ^= 0x1b; - a ^= gexp3[c]; - - // Set the log table value - glog3[gexp3[c]] = c; - } - gexp3[255] = gexp3[0]; - glog3[0] = 0; - - ginit_done = true; - } - - /** - * Galois Field multiplication - * @param {number} a - * @param {number} b - * @return {number} - */ - function gmul(a, b) { - var c = gexp3[(glog3[a] + glog3[b]) % 255]; - if (a === 0 || b === 0) c = 0; - return c; - } - - /** - * Galois Field reciprocal - * @param {number} a - * @return {number} - */ - function ginv(a) { - var i = gexp3[255 - glog3[a]]; - if (a === 0) i = 0; - return i; - } - - /** - * AES stuff init flag - */ - var aes_init_done = false; - - /** - * Encryption, Decryption, S-Box and KeyTransform tables - * - * @type {number[]} - */ - var aes_sbox; - - /** - * @type {number[]} - */ - var aes_sinv; - - /** - * @type {number[][]} - */ - var aes_enc; - - /** - * @type {number[][]} - */ - var aes_dec; - - /** - * Init AES tables - */ - function aes_init() { - if (!ginit_done) ginit(); - - // Calculates AES S-Box value - function _s(a) { - var c, s, x; - s = x = ginv(a); - for (c = 0; c < 4; c++) { - s = ((s << 1) | (s >>> 7)) & 255; - x ^= s; - } - x ^= 99; - return x; - } - - // Tables - aes_sbox = [], - aes_sinv = [], - aes_enc = [[], [], [], []], - aes_dec = [[], [], [], []]; - - for (var i = 0; i < 256; i++) { - var s = _s(i); - - // S-Box and its inverse - aes_sbox[i] = s; - aes_sinv[s] = i; - - // Ecryption and Decryption tables - aes_enc[0][i] = (gmul(2, s) << 24) | (s << 16) | (s << 8) | gmul(3, s); - aes_dec[0][s] = (gmul(14, i) << 24) | (gmul(9, i) << 16) | (gmul(13, i) << 8) | gmul(11, i); - // Rotate tables - for (var t = 1; t < 4; t++) { - aes_enc[t][i] = (aes_enc[t - 1][i] >>> 8) | (aes_enc[t - 1][i] << 24); - aes_dec[t][s] = (aes_dec[t - 1][s] >>> 8) | (aes_dec[t - 1][s] << 24); - } - } - - aes_init_done = true; - } - - /** - * Asm.js module constructor. - * - *

- * Heap buffer layout by offset: - *

-   * 0x0000   encryption key schedule
-   * 0x0400   decryption key schedule
-   * 0x0800   sbox
-   * 0x0c00   inv sbox
-   * 0x1000   encryption tables
-   * 0x2000   decryption tables
-   * 0x3000   reserved (future GCM multiplication lookup table)
-   * 0x4000   data
-   * 
- * Don't touch anything before 0x400. - *

- * - * @alias AES_asm - * @class - * @param foreign - ignored - * @param buffer - heap buffer to link with - */ - var wrapper = function (foreign, buffer) { - // Init AES stuff for the first time - if (!aes_init_done) aes_init(); - - // Fill up AES tables - var heap = new Uint32Array(buffer); - heap.set(aes_sbox, 0x0800 >> 2); - heap.set(aes_sinv, 0x0c00 >> 2); - for (var i = 0; i < 4; i++) { - heap.set(aes_enc[i], (0x1000 + 0x400 * i) >> 2); - heap.set(aes_dec[i], (0x2000 + 0x400 * i) >> 2); - } - - /** - * Calculate AES key schedules. - * @instance - * @memberof AES_asm - * @param {number} ks - key size, 4/6/8 (for 128/192/256-bit key correspondingly) - * @param {number} k0 - key vector components - * @param {number} k1 - key vector components - * @param {number} k2 - key vector components - * @param {number} k3 - key vector components - * @param {number} k4 - key vector components - * @param {number} k5 - key vector components - * @param {number} k6 - key vector components - * @param {number} k7 - key vector components - */ - function set_key(ks, k0, k1, k2, k3, k4, k5, k6, k7) { - var ekeys = heap.subarray(0x000, 60), - dkeys = heap.subarray(0x100, 0x100 + 60); - - // Encryption key schedule - ekeys.set([k0, k1, k2, k3, k4, k5, k6, k7]); - for (var i = ks, rcon = 1; i < 4 * ks + 28; i++) { - var k = ekeys[i - 1]; - if ((i % ks === 0) || (ks === 8 && i % ks === 4)) { - k = aes_sbox[k >>> 24] << 24 ^ aes_sbox[k >>> 16 & 255] << 16 ^ aes_sbox[k >>> 8 & 255] << 8 ^ aes_sbox[k & 255]; - } - if (i % ks === 0) { - k = (k << 8) ^ (k >>> 24) ^ (rcon << 24); - rcon = (rcon << 1) ^ ((rcon & 0x80) ? 0x1b : 0); - } - ekeys[i] = ekeys[i - ks] ^ k; - } - - // Decryption key schedule - for (var j = 0; j < i; j += 4) { - for (var jj = 0; jj < 4; jj++) { - var k = ekeys[i - (4 + j) + (4 - jj) % 4]; - if (j < 4 || j >= i - 4) { - dkeys[j + jj] = k; - } else { - dkeys[j + jj] = aes_dec[0][aes_sbox[k >>> 24]] - ^ aes_dec[1][aes_sbox[k >>> 16 & 255]] - ^ aes_dec[2][aes_sbox[k >>> 8 & 255]] - ^ aes_dec[3][aes_sbox[k & 255]]; - } - } - } - - // Set rounds number - asm.set_rounds(ks + 5); - } - - // create library object with necessary properties - var stdlib = {Uint8Array: Uint8Array, Uint32Array: Uint32Array}; - - var asm = function (stdlib, foreign, buffer) { - "use asm"; - - var S0 = 0, S1 = 0, S2 = 0, S3 = 0, - I0 = 0, I1 = 0, I2 = 0, I3 = 0, - N0 = 0, N1 = 0, N2 = 0, N3 = 0, - M0 = 0, M1 = 0, M2 = 0, M3 = 0, - H0 = 0, H1 = 0, H2 = 0, H3 = 0, - R = 0; - - var HEAP = new stdlib.Uint32Array(buffer), - DATA = new stdlib.Uint8Array(buffer); - - /** - * AES core - * @param {number} k - precomputed key schedule offset - * @param {number} s - precomputed sbox table offset - * @param {number} t - precomputed round table offset - * @param {number} r - number of inner rounds to perform - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _core(k, s, t, r, x0, x1, x2, x3) { - k = k | 0; - s = s | 0; - t = t | 0; - r = r | 0; - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - var t1 = 0, t2 = 0, t3 = 0, - y0 = 0, y1 = 0, y2 = 0, y3 = 0, - i = 0; - - t1 = t | 0x400, t2 = t | 0x800, t3 = t | 0xc00; - - // round 0 - x0 = x0 ^ HEAP[(k | 0) >> 2], - x1 = x1 ^ HEAP[(k | 4) >> 2], - x2 = x2 ^ HEAP[(k | 8) >> 2], - x3 = x3 ^ HEAP[(k | 12) >> 2]; - - // round 1..r - for (i = 16; (i | 0) <= (r << 4); i = (i + 16) | 0) { - y0 = HEAP[(t | x0 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x1 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x2 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x3 << 2 & 1020) >> 2] ^ HEAP[(k | i | 0) >> 2], - y1 = HEAP[(t | x1 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x2 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x3 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x0 << 2 & 1020) >> 2] ^ HEAP[(k | i | 4) >> 2], - y2 = HEAP[(t | x2 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x3 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x0 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x1 << 2 & 1020) >> 2] ^ HEAP[(k | i | 8) >> 2], - y3 = HEAP[(t | x3 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x0 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x1 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x2 << 2 & 1020) >> 2] ^ HEAP[(k | i | 12) >> 2]; - x0 = y0, x1 = y1, x2 = y2, x3 = y3; - } - - // final round - S0 = HEAP[(s | x0 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x1 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x2 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x3 << 2 & 1020) >> 2] ^ HEAP[(k | i | 0) >> 2], - S1 = HEAP[(s | x1 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x2 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x3 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x0 << 2 & 1020) >> 2] ^ HEAP[(k | i | 4) >> 2], - S2 = HEAP[(s | x2 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x3 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x0 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x1 << 2 & 1020) >> 2] ^ HEAP[(k | i | 8) >> 2], - S3 = HEAP[(s | x3 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x0 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x1 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x2 << 2 & 1020) >> 2] ^ HEAP[(k | i | 12) >> 2]; - } - - /** - * ECB mode encryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _ecb_enc(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core( - 0x0000, 0x0800, 0x1000, - R, - x0, - x1, - x2, - x3 - ); - } - - /** - * ECB mode decryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _ecb_dec(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - var t = 0; - - _core( - 0x0400, 0x0c00, 0x2000, - R, - x0, - x3, - x2, - x1 - ); - - t = S1, S1 = S3, S3 = t; - } - - - /** - * CBC mode encryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _cbc_enc(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core( - 0x0000, 0x0800, 0x1000, - R, - I0 ^ x0, - I1 ^ x1, - I2 ^ x2, - I3 ^ x3 - ); - - I0 = S0, - I1 = S1, - I2 = S2, - I3 = S3; - } - - /** - * CBC mode decryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _cbc_dec(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - var t = 0; - - _core( - 0x0400, 0x0c00, 0x2000, - R, - x0, - x3, - x2, - x1 - ); - - t = S1, S1 = S3, S3 = t; - - S0 = S0 ^ I0, - S1 = S1 ^ I1, - S2 = S2 ^ I2, - S3 = S3 ^ I3; - - I0 = x0, - I1 = x1, - I2 = x2, - I3 = x3; - } - - /** - * CFB mode encryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _cfb_enc(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core( - 0x0000, 0x0800, 0x1000, - R, - I0, - I1, - I2, - I3 - ); - - I0 = S0 = S0 ^ x0, - I1 = S1 = S1 ^ x1, - I2 = S2 = S2 ^ x2, - I3 = S3 = S3 ^ x3; - } - - - /** - * CFB mode decryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _cfb_dec(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core( - 0x0000, 0x0800, 0x1000, - R, - I0, - I1, - I2, - I3 - ); - - S0 = S0 ^ x0, - S1 = S1 ^ x1, - S2 = S2 ^ x2, - S3 = S3 ^ x3; - - I0 = x0, - I1 = x1, - I2 = x2, - I3 = x3; - } - - /** - * OFB mode encryption / decryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _ofb(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core( - 0x0000, 0x0800, 0x1000, - R, - I0, - I1, - I2, - I3 - ); - - I0 = S0, - I1 = S1, - I2 = S2, - I3 = S3; - - S0 = S0 ^ x0, - S1 = S1 ^ x1, - S2 = S2 ^ x2, - S3 = S3 ^ x3; - } - - /** - * CTR mode encryption / decryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _ctr(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core( - 0x0000, 0x0800, 0x1000, - R, - N0, - N1, - N2, - N3 - ); - - N3 = (~M3 & N3) | M3 & (N3 + 1); - N2 = (~M2 & N2) | M2 & (N2 + ((N3 | 0) == 0)); - N1 = (~M1 & N1) | M1 & (N1 + ((N2 | 0) == 0)); - N0 = (~M0 & N0) | M0 & (N0 + ((N1 | 0) == 0)); - - S0 = S0 ^ x0; - S1 = S1 ^ x1; - S2 = S2 ^ x2; - S3 = S3 ^ x3; - } - - /** - * GCM mode MAC calculation - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _gcm_mac(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - var y0 = 0, y1 = 0, y2 = 0, y3 = 0, - z0 = 0, z1 = 0, z2 = 0, z3 = 0, - i = 0, c = 0; - - x0 = x0 ^ I0, - x1 = x1 ^ I1, - x2 = x2 ^ I2, - x3 = x3 ^ I3; - - y0 = H0 | 0, - y1 = H1 | 0, - y2 = H2 | 0, - y3 = H3 | 0; - - for (; (i | 0) < 128; i = (i + 1) | 0) { - if (y0 >>> 31) { - z0 = z0 ^ x0, - z1 = z1 ^ x1, - z2 = z2 ^ x2, - z3 = z3 ^ x3; - } - - y0 = (y0 << 1) | (y1 >>> 31), - y1 = (y1 << 1) | (y2 >>> 31), - y2 = (y2 << 1) | (y3 >>> 31), - y3 = (y3 << 1); - - c = x3 & 1; - - x3 = (x3 >>> 1) | (x2 << 31), - x2 = (x2 >>> 1) | (x1 << 31), - x1 = (x1 >>> 1) | (x0 << 31), - x0 = (x0 >>> 1); - - if (c) x0 = x0 ^ 0xe1000000; - } - - I0 = z0, - I1 = z1, - I2 = z2, - I3 = z3; - } - - /** - * Set the internal rounds number. - * @instance - * @memberof AES_asm - * @param {number} r - number if inner AES rounds - */ - function set_rounds(r) { - r = r | 0; - R = r; - } - - /** - * Populate the internal state of the module. - * @instance - * @memberof AES_asm - * @param {number} s0 - state vector - * @param {number} s1 - state vector - * @param {number} s2 - state vector - * @param {number} s3 - state vector - */ - function set_state(s0, s1, s2, s3) { - s0 = s0 | 0; - s1 = s1 | 0; - s2 = s2 | 0; - s3 = s3 | 0; - - S0 = s0, - S1 = s1, - S2 = s2, - S3 = s3; - } - - /** - * Populate the internal iv of the module. - * @instance - * @memberof AES_asm - * @param {number} i0 - iv vector - * @param {number} i1 - iv vector - * @param {number} i2 - iv vector - * @param {number} i3 - iv vector - */ - function set_iv(i0, i1, i2, i3) { - i0 = i0 | 0; - i1 = i1 | 0; - i2 = i2 | 0; - i3 = i3 | 0; - - I0 = i0, - I1 = i1, - I2 = i2, - I3 = i3; - } - - /** - * Set nonce for CTR-family modes. - * @instance - * @memberof AES_asm - * @param {number} n0 - nonce vector - * @param {number} n1 - nonce vector - * @param {number} n2 - nonce vector - * @param {number} n3 - nonce vector - */ - function set_nonce(n0, n1, n2, n3) { - n0 = n0 | 0; - n1 = n1 | 0; - n2 = n2 | 0; - n3 = n3 | 0; - - N0 = n0, - N1 = n1, - N2 = n2, - N3 = n3; - } - - /** - * Set counter mask for CTR-family modes. - * @instance - * @memberof AES_asm - * @param {number} m0 - counter mask vector - * @param {number} m1 - counter mask vector - * @param {number} m2 - counter mask vector - * @param {number} m3 - counter mask vector - */ - function set_mask(m0, m1, m2, m3) { - m0 = m0 | 0; - m1 = m1 | 0; - m2 = m2 | 0; - m3 = m3 | 0; - - M0 = m0, - M1 = m1, - M2 = m2, - M3 = m3; - } - - /** - * Set counter for CTR-family modes. - * @instance - * @memberof AES_asm - * @param {number} c0 - counter vector - * @param {number} c1 - counter vector - * @param {number} c2 - counter vector - * @param {number} c3 - counter vector - */ - function set_counter(c0, c1, c2, c3) { - c0 = c0 | 0; - c1 = c1 | 0; - c2 = c2 | 0; - c3 = c3 | 0; - - N3 = (~M3 & N3) | M3 & c3, - N2 = (~M2 & N2) | M2 & c2, - N1 = (~M1 & N1) | M1 & c1, - N0 = (~M0 & N0) | M0 & c0; - } - - /** - * Store the internal state vector into the heap. - * @instance - * @memberof AES_asm - * @param {number} pos - offset where to put the data - * @return {number} The number of bytes have been written into the heap, always 16. - */ - function get_state(pos) { - pos = pos | 0; - - if (pos & 15) return -1; - - DATA[pos | 0] = S0 >>> 24, - DATA[pos | 1] = S0 >>> 16 & 255, - DATA[pos | 2] = S0 >>> 8 & 255, - DATA[pos | 3] = S0 & 255, - DATA[pos | 4] = S1 >>> 24, - DATA[pos | 5] = S1 >>> 16 & 255, - DATA[pos | 6] = S1 >>> 8 & 255, - DATA[pos | 7] = S1 & 255, - DATA[pos | 8] = S2 >>> 24, - DATA[pos | 9] = S2 >>> 16 & 255, - DATA[pos | 10] = S2 >>> 8 & 255, - DATA[pos | 11] = S2 & 255, - DATA[pos | 12] = S3 >>> 24, - DATA[pos | 13] = S3 >>> 16 & 255, - DATA[pos | 14] = S3 >>> 8 & 255, - DATA[pos | 15] = S3 & 255; - - return 16; - } - - /** - * Store the internal iv vector into the heap. - * @instance - * @memberof AES_asm - * @param {number} pos - offset where to put the data - * @return {number} The number of bytes have been written into the heap, always 16. - */ - function get_iv(pos) { - pos = pos | 0; - - if (pos & 15) return -1; - - DATA[pos | 0] = I0 >>> 24, - DATA[pos | 1] = I0 >>> 16 & 255, - DATA[pos | 2] = I0 >>> 8 & 255, - DATA[pos | 3] = I0 & 255, - DATA[pos | 4] = I1 >>> 24, - DATA[pos | 5] = I1 >>> 16 & 255, - DATA[pos | 6] = I1 >>> 8 & 255, - DATA[pos | 7] = I1 & 255, - DATA[pos | 8] = I2 >>> 24, - DATA[pos | 9] = I2 >>> 16 & 255, - DATA[pos | 10] = I2 >>> 8 & 255, - DATA[pos | 11] = I2 & 255, - DATA[pos | 12] = I3 >>> 24, - DATA[pos | 13] = I3 >>> 16 & 255, - DATA[pos | 14] = I3 >>> 8 & 255, - DATA[pos | 15] = I3 & 255; - - return 16; - } - - /** - * GCM initialization. - * @instance - * @memberof AES_asm - */ - function gcm_init() { - _ecb_enc(0, 0, 0, 0); - H0 = S0, - H1 = S1, - H2 = S2, - H3 = S3; - } - - /** - * Perform ciphering operation on the supplied data. - * @instance - * @memberof AES_asm - * @param {number} mode - block cipher mode (see {@link AES_asm} mode constants) - * @param {number} pos - offset of the data being processed - * @param {number} len - length of the data being processed - * @return {number} Actual amount of data have been processed. - */ - function cipher(mode, pos, len) { - mode = mode | 0; - pos = pos | 0; - len = len | 0; - - var ret = 0; - - if (pos & 15) return -1; - - while ((len | 0) >= 16) { - _cipher_modes[mode & 7]( - DATA[pos | 0] << 24 | DATA[pos | 1] << 16 | DATA[pos | 2] << 8 | DATA[pos | 3], - DATA[pos | 4] << 24 | DATA[pos | 5] << 16 | DATA[pos | 6] << 8 | DATA[pos | 7], - DATA[pos | 8] << 24 | DATA[pos | 9] << 16 | DATA[pos | 10] << 8 | DATA[pos | 11], - DATA[pos | 12] << 24 | DATA[pos | 13] << 16 | DATA[pos | 14] << 8 | DATA[pos | 15] - ); - - DATA[pos | 0] = S0 >>> 24, - DATA[pos | 1] = S0 >>> 16 & 255, - DATA[pos | 2] = S0 >>> 8 & 255, - DATA[pos | 3] = S0 & 255, - DATA[pos | 4] = S1 >>> 24, - DATA[pos | 5] = S1 >>> 16 & 255, - DATA[pos | 6] = S1 >>> 8 & 255, - DATA[pos | 7] = S1 & 255, - DATA[pos | 8] = S2 >>> 24, - DATA[pos | 9] = S2 >>> 16 & 255, - DATA[pos | 10] = S2 >>> 8 & 255, - DATA[pos | 11] = S2 & 255, - DATA[pos | 12] = S3 >>> 24, - DATA[pos | 13] = S3 >>> 16 & 255, - DATA[pos | 14] = S3 >>> 8 & 255, - DATA[pos | 15] = S3 & 255; - - ret = (ret + 16) | 0, - pos = (pos + 16) | 0, - len = (len - 16) | 0; - } - - return ret | 0; - } - - /** - * Calculates MAC of the supplied data. - * @instance - * @memberof AES_asm - * @param {number} mode - block cipher mode (see {@link AES_asm} mode constants) - * @param {number} pos - offset of the data being processed - * @param {number} len - length of the data being processed - * @return {number} Actual amount of data have been processed. - */ - function mac(mode, pos, len) { - mode = mode | 0; - pos = pos | 0; - len = len | 0; - - var ret = 0; - - if (pos & 15) return -1; - - while ((len | 0) >= 16) { - _mac_modes[mode & 1]( - DATA[pos | 0] << 24 | DATA[pos | 1] << 16 | DATA[pos | 2] << 8 | DATA[pos | 3], - DATA[pos | 4] << 24 | DATA[pos | 5] << 16 | DATA[pos | 6] << 8 | DATA[pos | 7], - DATA[pos | 8] << 24 | DATA[pos | 9] << 16 | DATA[pos | 10] << 8 | DATA[pos | 11], - DATA[pos | 12] << 24 | DATA[pos | 13] << 16 | DATA[pos | 14] << 8 | DATA[pos | 15] - ); - - ret = (ret + 16) | 0, - pos = (pos + 16) | 0, - len = (len - 16) | 0; - } - - return ret | 0; - } - - /** - * AES cipher modes table (virual methods) - */ - var _cipher_modes = [_ecb_enc, _ecb_dec, _cbc_enc, _cbc_dec, _cfb_enc, _cfb_dec, _ofb, _ctr]; - - /** - * AES MAC modes table (virual methods) - */ - var _mac_modes = [_cbc_enc, _gcm_mac]; - - /** - * Asm.js module exports - */ - return { - set_rounds: set_rounds, - set_state: set_state, - set_iv: set_iv, - set_nonce: set_nonce, - set_mask: set_mask, - set_counter: set_counter, - get_state: get_state, - get_iv: get_iv, - gcm_init: gcm_init, - cipher: cipher, - mac: mac, - }; - }(stdlib, foreign, buffer); - - asm.set_key = set_key; - - return asm; - }; - - /** - * AES enciphering mode constants - * @enum {number} - * @const - */ - wrapper.ENC = { - ECB: 0, - CBC: 2, - CFB: 4, - OFB: 6, - CTR: 7, - }, - - /** - * AES deciphering mode constants - * @enum {number} - * @const - */ - wrapper.DEC = { - ECB: 1, - CBC: 3, - CFB: 5, - OFB: 6, - CTR: 7, - }, - - /** - * AES MAC mode constants - * @enum {number} - * @const - */ - wrapper.MAC = { - CBC: 0, - GCM: 1, - }; - - /** - * Heap data offset - * @type {number} - * @const - */ - wrapper.HEAP_DATA = 0x4000; - - return wrapper; -}(); - -function is_bytes(a) { - return a instanceof Uint8Array; -} -function _heap_init(heap, heapSize) { - const size = heap ? heap.byteLength : heapSize || 65536; - if (size & 0xfff || size <= 0) - throw new Error('heap size must be a positive integer and a multiple of 4096'); - heap = heap || new Uint8Array(new ArrayBuffer(size)); - return heap; -} -function _heap_write(heap, hpos, data, dpos, dlen) { - const hlen = heap.length - hpos; - const wlen = hlen < dlen ? hlen : dlen; - heap.set(data.subarray(dpos, dpos + wlen), hpos); - return wlen; -} -function joinBytes(...arg) { - const totalLenght = arg.reduce((sum, curr) => sum + curr.length, 0); - const ret = new Uint8Array(totalLenght); - let cursor = 0; - for (let i = 0; i < arg.length; i++) { - ret.set(arg[i], cursor); - cursor += arg[i].length; - } - return ret; -} - -class IllegalStateError extends Error { - constructor(...args) { - super(...args); - } -} -class IllegalArgumentError extends Error { - constructor(...args) { - super(...args); - } -} -class SecurityError extends Error { - constructor(...args) { - super(...args); - } -} - -const heap_pool = []; -const asm_pool = []; -class AES { - constructor(key, iv, padding = true, mode, heap, asm) { - this.pos = 0; - this.len = 0; - this.mode = mode; - // The AES object state - this.pos = 0; - this.len = 0; - this.key = key; - this.iv = iv; - this.padding = padding; - // The AES "worker" - this.acquire_asm(heap, asm); - } - acquire_asm(heap, asm) { - if (this.heap === undefined || this.asm === undefined) { - this.heap = heap || heap_pool.pop() || _heap_init().subarray(AES_asm.HEAP_DATA); - this.asm = asm || asm_pool.pop() || new AES_asm(null, this.heap.buffer); - this.reset(this.key, this.iv); - } - return { heap: this.heap, asm: this.asm }; - } - release_asm() { - if (this.heap !== undefined && this.asm !== undefined) { - heap_pool.push(this.heap); - asm_pool.push(this.asm); - } - this.heap = undefined; - this.asm = undefined; - } - reset(key, iv) { - const { asm } = this.acquire_asm(); - // Key - const keylen = key.length; - if (keylen !== 16 && keylen !== 24 && keylen !== 32) - throw new IllegalArgumentError('illegal key size'); - const keyview = new DataView(key.buffer, key.byteOffset, key.byteLength); - asm.set_key(keylen >> 2, keyview.getUint32(0), keyview.getUint32(4), keyview.getUint32(8), keyview.getUint32(12), keylen > 16 ? keyview.getUint32(16) : 0, keylen > 16 ? keyview.getUint32(20) : 0, keylen > 24 ? keyview.getUint32(24) : 0, keylen > 24 ? keyview.getUint32(28) : 0); - // IV - if (iv !== undefined) { - if (iv.length !== 16) - throw new IllegalArgumentError('illegal iv size'); - let ivview = new DataView(iv.buffer, iv.byteOffset, iv.byteLength); - asm.set_iv(ivview.getUint32(0), ivview.getUint32(4), ivview.getUint32(8), ivview.getUint32(12)); - } - else { - asm.set_iv(0, 0, 0, 0); - } - } - AES_Encrypt_process(data) { - if (!is_bytes(data)) - throw new TypeError("data isn't of expected type"); - let { heap, asm } = this.acquire_asm(); - let amode = AES_asm.ENC[this.mode]; - let hpos = AES_asm.HEAP_DATA; - let pos = this.pos; - let len = this.len; - let dpos = 0; - let dlen = data.length || 0; - let rpos = 0; - let rlen = (len + dlen) & -16; - let wlen = 0; - let result = new Uint8Array(rlen); - while (dlen > 0) { - wlen = _heap_write(heap, pos + len, data, dpos, dlen); - len += wlen; - dpos += wlen; - dlen -= wlen; - wlen = asm.cipher(amode, hpos + pos, len); - if (wlen) - result.set(heap.subarray(pos, pos + wlen), rpos); - rpos += wlen; - if (wlen < len) { - pos += wlen; - len -= wlen; - } - else { - pos = 0; - len = 0; - } - } - this.pos = pos; - this.len = len; - return result; - } - AES_Encrypt_finish() { - let { heap, asm } = this.acquire_asm(); - let amode = AES_asm.ENC[this.mode]; - let hpos = AES_asm.HEAP_DATA; - let pos = this.pos; - let len = this.len; - let plen = 16 - (len % 16); - let rlen = len; - if (this.hasOwnProperty('padding')) { - if (this.padding) { - for (let p = 0; p < plen; ++p) { - heap[pos + len + p] = plen; - } - len += plen; - rlen = len; - } - else if (len % 16) { - throw new IllegalArgumentError('data length must be a multiple of the block size'); - } - } - else { - len += plen; - } - const result = new Uint8Array(rlen); - if (len) - asm.cipher(amode, hpos + pos, len); - if (rlen) - result.set(heap.subarray(pos, pos + rlen)); - this.pos = 0; - this.len = 0; - this.release_asm(); - return result; - } - AES_Decrypt_process(data) { - if (!is_bytes(data)) - throw new TypeError("data isn't of expected type"); - let { heap, asm } = this.acquire_asm(); - let amode = AES_asm.DEC[this.mode]; - let hpos = AES_asm.HEAP_DATA; - let pos = this.pos; - let len = this.len; - let dpos = 0; - let dlen = data.length || 0; - let rpos = 0; - let rlen = (len + dlen) & -16; - let plen = 0; - let wlen = 0; - if (this.padding) { - plen = len + dlen - rlen || 16; - rlen -= plen; - } - const result = new Uint8Array(rlen); - while (dlen > 0) { - wlen = _heap_write(heap, pos + len, data, dpos, dlen); - len += wlen; - dpos += wlen; - dlen -= wlen; - wlen = asm.cipher(amode, hpos + pos, len - (!dlen ? plen : 0)); - if (wlen) - result.set(heap.subarray(pos, pos + wlen), rpos); - rpos += wlen; - if (wlen < len) { - pos += wlen; - len -= wlen; - } - else { - pos = 0; - len = 0; - } - } - this.pos = pos; - this.len = len; - return result; - } - AES_Decrypt_finish() { - let { heap, asm } = this.acquire_asm(); - let amode = AES_asm.DEC[this.mode]; - let hpos = AES_asm.HEAP_DATA; - let pos = this.pos; - let len = this.len; - let rlen = len; - if (len > 0) { - if (len % 16) { - if (this.hasOwnProperty('padding')) { - throw new IllegalArgumentError('data length must be a multiple of the block size'); - } - else { - len += 16 - (len % 16); - } - } - asm.cipher(amode, hpos + pos, len); - if (this.hasOwnProperty('padding') && this.padding) { - let pad = heap[pos + rlen - 1]; - if (pad < 1 || pad > 16 || pad > rlen) - throw new SecurityError('bad padding'); - let pcheck = 0; - for (let i = pad; i > 1; i--) - pcheck |= pad ^ heap[pos + rlen - i]; - if (pcheck) - throw new SecurityError('bad padding'); - rlen -= pad; - } - } - const result = new Uint8Array(rlen); - if (rlen > 0) { - result.set(heap.subarray(pos, pos + rlen)); - } - this.pos = 0; - this.len = 0; - this.release_asm(); - return result; - } -} - -class AES_ECB { - static encrypt(data, key, padding = false) { - return new AES_ECB(key, padding).encrypt(data); - } - static decrypt(data, key, padding = false) { - return new AES_ECB(key, padding).decrypt(data); - } - constructor(key, padding = false, aes) { - this.aes = aes ? aes : new AES(key, undefined, padding, 'ECB'); - } - encrypt(data) { - const r1 = this.aes.AES_Encrypt_process(data); - const r2 = this.aes.AES_Encrypt_finish(); - return joinBytes(r1, r2); - } - decrypt(data) { - const r1 = this.aes.AES_Decrypt_process(data); - const r2 = this.aes.AES_Decrypt_finish(); - return joinBytes(r1, r2); - } -} - -/** - * Javascript AES implementation. - * This is used as fallback if the native Crypto APIs are not available. - */ -function aes(length) { - const C = function(key) { - const aesECB = new AES_ECB(key); - - this.encrypt = function(block) { - return aesECB.encrypt(block); - }; - - this.decrypt = function(block) { - return aesECB.decrypt(block); - }; - }; - - C.blockSize = C.prototype.blockSize = 16; - C.keySize = C.prototype.keySize = length / 8; - - return C; -} - -//Paul Tero, July 2001 -//http://www.tero.co.uk/des/ -// -//Optimised for performance with large blocks by Michael Hayworth, November 2001 -//http://www.netdealing.com -// -// Modified by Recurity Labs GmbH - -//THIS SOFTWARE IS PROVIDED "AS IS" AND -//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -//FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -//DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -//OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -//HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -//OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -//SUCH DAMAGE. - -//des -//this takes the key, the message, and whether to encrypt or decrypt - -function des(keys, message, encrypt, mode, iv, padding) { - //declaring this locally speeds things up a bit - const spfunction1 = [ - 0x1010400, 0, 0x10000, 0x1010404, 0x1010004, 0x10404, 0x4, 0x10000, 0x400, 0x1010400, - 0x1010404, 0x400, 0x1000404, 0x1010004, 0x1000000, 0x4, 0x404, 0x1000400, 0x1000400, 0x10400, 0x10400, 0x1010000, - 0x1010000, 0x1000404, 0x10004, 0x1000004, 0x1000004, 0x10004, 0, 0x404, 0x10404, 0x1000000, 0x10000, 0x1010404, 0x4, - 0x1010000, 0x1010400, 0x1000000, 0x1000000, 0x400, 0x1010004, 0x10000, 0x10400, 0x1000004, 0x400, 0x4, 0x1000404, - 0x10404, 0x1010404, 0x10004, 0x1010000, 0x1000404, 0x1000004, 0x404, 0x10404, 0x1010400, 0x404, 0x1000400, - 0x1000400, 0, 0x10004, 0x10400, 0, 0x1010004 - ]; - const spfunction2 = [ - -0x7fef7fe0, -0x7fff8000, 0x8000, 0x108020, 0x100000, 0x20, -0x7fefffe0, -0x7fff7fe0, - -0x7fffffe0, -0x7fef7fe0, -0x7fef8000, -0x80000000, -0x7fff8000, 0x100000, 0x20, -0x7fefffe0, 0x108000, 0x100020, - -0x7fff7fe0, 0, -0x80000000, 0x8000, 0x108020, -0x7ff00000, 0x100020, -0x7fffffe0, 0, 0x108000, 0x8020, -0x7fef8000, - -0x7ff00000, 0x8020, 0, 0x108020, -0x7fefffe0, 0x100000, -0x7fff7fe0, -0x7ff00000, -0x7fef8000, 0x8000, -0x7ff00000, - -0x7fff8000, 0x20, -0x7fef7fe0, 0x108020, 0x20, 0x8000, -0x80000000, 0x8020, -0x7fef8000, 0x100000, -0x7fffffe0, - 0x100020, -0x7fff7fe0, -0x7fffffe0, 0x100020, 0x108000, 0, -0x7fff8000, 0x8020, -0x80000000, -0x7fefffe0, - -0x7fef7fe0, 0x108000 - ]; - const spfunction3 = [ - 0x208, 0x8020200, 0, 0x8020008, 0x8000200, 0, 0x20208, 0x8000200, 0x20008, 0x8000008, - 0x8000008, 0x20000, 0x8020208, 0x20008, 0x8020000, 0x208, 0x8000000, 0x8, 0x8020200, 0x200, 0x20200, 0x8020000, - 0x8020008, 0x20208, 0x8000208, 0x20200, 0x20000, 0x8000208, 0x8, 0x8020208, 0x200, 0x8000000, 0x8020200, 0x8000000, - 0x20008, 0x208, 0x20000, 0x8020200, 0x8000200, 0, 0x200, 0x20008, 0x8020208, 0x8000200, 0x8000008, 0x200, 0, - 0x8020008, 0x8000208, 0x20000, 0x8000000, 0x8020208, 0x8, 0x20208, 0x20200, 0x8000008, 0x8020000, 0x8000208, 0x208, - 0x8020000, 0x20208, 0x8, 0x8020008, 0x20200 - ]; - const spfunction4 = [ - 0x802001, 0x2081, 0x2081, 0x80, 0x802080, 0x800081, 0x800001, 0x2001, 0, 0x802000, - 0x802000, 0x802081, 0x81, 0, 0x800080, 0x800001, 0x1, 0x2000, 0x800000, 0x802001, 0x80, 0x800000, 0x2001, 0x2080, - 0x800081, 0x1, 0x2080, 0x800080, 0x2000, 0x802080, 0x802081, 0x81, 0x800080, 0x800001, 0x802000, 0x802081, 0x81, 0, - 0, 0x802000, 0x2080, 0x800080, 0x800081, 0x1, 0x802001, 0x2081, 0x2081, 0x80, 0x802081, 0x81, 0x1, 0x2000, 0x800001, - 0x2001, 0x802080, 0x800081, 0x2001, 0x2080, 0x800000, 0x802001, 0x80, 0x800000, 0x2000, 0x802080 - ]; - const spfunction5 = [ - 0x100, 0x2080100, 0x2080000, 0x42000100, 0x80000, 0x100, 0x40000000, 0x2080000, - 0x40080100, 0x80000, 0x2000100, 0x40080100, 0x42000100, 0x42080000, 0x80100, 0x40000000, 0x2000000, 0x40080000, - 0x40080000, 0, 0x40000100, 0x42080100, 0x42080100, 0x2000100, 0x42080000, 0x40000100, 0, 0x42000000, 0x2080100, - 0x2000000, 0x42000000, 0x80100, 0x80000, 0x42000100, 0x100, 0x2000000, 0x40000000, 0x2080000, 0x42000100, - 0x40080100, 0x2000100, 0x40000000, 0x42080000, 0x2080100, 0x40080100, 0x100, 0x2000000, 0x42080000, 0x42080100, - 0x80100, 0x42000000, 0x42080100, 0x2080000, 0, 0x40080000, 0x42000000, 0x80100, 0x2000100, 0x40000100, 0x80000, 0, - 0x40080000, 0x2080100, 0x40000100 - ]; - const spfunction6 = [ - 0x20000010, 0x20400000, 0x4000, 0x20404010, 0x20400000, 0x10, 0x20404010, 0x400000, - 0x20004000, 0x404010, 0x400000, 0x20000010, 0x400010, 0x20004000, 0x20000000, 0x4010, 0, 0x400010, 0x20004010, - 0x4000, 0x404000, 0x20004010, 0x10, 0x20400010, 0x20400010, 0, 0x404010, 0x20404000, 0x4010, 0x404000, 0x20404000, - 0x20000000, 0x20004000, 0x10, 0x20400010, 0x404000, 0x20404010, 0x400000, 0x4010, 0x20000010, 0x400000, 0x20004000, - 0x20000000, 0x4010, 0x20000010, 0x20404010, 0x404000, 0x20400000, 0x404010, 0x20404000, 0, 0x20400010, 0x10, 0x4000, - 0x20400000, 0x404010, 0x4000, 0x400010, 0x20004010, 0, 0x20404000, 0x20000000, 0x400010, 0x20004010 - ]; - const spfunction7 = [ - 0x200000, 0x4200002, 0x4000802, 0, 0x800, 0x4000802, 0x200802, 0x4200800, 0x4200802, - 0x200000, 0, 0x4000002, 0x2, 0x4000000, 0x4200002, 0x802, 0x4000800, 0x200802, 0x200002, 0x4000800, 0x4000002, - 0x4200000, 0x4200800, 0x200002, 0x4200000, 0x800, 0x802, 0x4200802, 0x200800, 0x2, 0x4000000, 0x200800, 0x4000000, - 0x200800, 0x200000, 0x4000802, 0x4000802, 0x4200002, 0x4200002, 0x2, 0x200002, 0x4000000, 0x4000800, 0x200000, - 0x4200800, 0x802, 0x200802, 0x4200800, 0x802, 0x4000002, 0x4200802, 0x4200000, 0x200800, 0, 0x2, 0x4200802, 0, - 0x200802, 0x4200000, 0x800, 0x4000002, 0x4000800, 0x800, 0x200002 - ]; - const spfunction8 = [ - 0x10001040, 0x1000, 0x40000, 0x10041040, 0x10000000, 0x10001040, 0x40, 0x10000000, - 0x40040, 0x10040000, 0x10041040, 0x41000, 0x10041000, 0x41040, 0x1000, 0x40, 0x10040000, 0x10000040, 0x10001000, - 0x1040, 0x41000, 0x40040, 0x10040040, 0x10041000, 0x1040, 0, 0, 0x10040040, 0x10000040, 0x10001000, 0x41040, - 0x40000, 0x41040, 0x40000, 0x10041000, 0x1000, 0x40, 0x10040040, 0x1000, 0x41040, 0x10001000, 0x40, 0x10000040, - 0x10040000, 0x10040040, 0x10000000, 0x40000, 0x10001040, 0, 0x10041040, 0x40040, 0x10000040, 0x10040000, 0x10001000, - 0x10001040, 0, 0x10041040, 0x41000, 0x41000, 0x1040, 0x1040, 0x40040, 0x10000000, 0x10041000 - ]; - - //create the 16 or 48 subkeys we will need - let m = 0; - let i; - let j; - let temp; - let right1; - let right2; - let left; - let right; - let looping; - let cbcleft; - let cbcleft2; - let cbcright; - let cbcright2; - let endloop; - let loopinc; - let len = message.length; - - //set up the loops for single and triple des - const iterations = keys.length === 32 ? 3 : 9; //single or triple des - if (iterations === 3) { - looping = encrypt ? [0, 32, 2] : [30, -2, -2]; - } else { - looping = encrypt ? [0, 32, 2, 62, 30, -2, 64, 96, 2] : [94, 62, -2, 32, 64, 2, 30, -2, -2]; - } - - //pad the message depending on the padding parameter - //only add padding if encrypting - note that you need to use the same padding option for both encrypt and decrypt - if (encrypt) { - message = desAddPadding(message, padding); - len = message.length; - } - - //store the result here - let result = new Uint8Array(len); - let k = 0; - - if (mode === 1) { //CBC mode - cbcleft = (iv[m++] << 24) | (iv[m++] << 16) | (iv[m++] << 8) | iv[m++]; - cbcright = (iv[m++] << 24) | (iv[m++] << 16) | (iv[m++] << 8) | iv[m++]; - m = 0; - } - - //loop through each 64 bit chunk of the message - while (m < len) { - left = (message[m++] << 24) | (message[m++] << 16) | (message[m++] << 8) | message[m++]; - right = (message[m++] << 24) | (message[m++] << 16) | (message[m++] << 8) | message[m++]; - - //for Cipher Block Chaining mode, xor the message with the previous result - if (mode === 1) { - if (encrypt) { - left ^= cbcleft; - right ^= cbcright; - } else { - cbcleft2 = cbcleft; - cbcright2 = cbcright; - cbcleft = left; - cbcright = right; - } - } - - //first each 64 but chunk of the message must be permuted according to IP - temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; - right ^= temp; - left ^= (temp << 4); - temp = ((left >>> 16) ^ right) & 0x0000ffff; - right ^= temp; - left ^= (temp << 16); - temp = ((right >>> 2) ^ left) & 0x33333333; - left ^= temp; - right ^= (temp << 2); - temp = ((right >>> 8) ^ left) & 0x00ff00ff; - left ^= temp; - right ^= (temp << 8); - temp = ((left >>> 1) ^ right) & 0x55555555; - right ^= temp; - left ^= (temp << 1); - - left = ((left << 1) | (left >>> 31)); - right = ((right << 1) | (right >>> 31)); - - //do this either 1 or 3 times for each chunk of the message - for (j = 0; j < iterations; j += 3) { - endloop = looping[j + 1]; - loopinc = looping[j + 2]; - //now go through and perform the encryption or decryption - for (i = looping[j]; i !== endloop; i += loopinc) { //for efficiency - right1 = right ^ keys[i]; - right2 = ((right >>> 4) | (right << 28)) ^ keys[i + 1]; - //the result is attained by passing these bytes through the S selection functions - temp = left; - left = right; - right = temp ^ (spfunction2[(right1 >>> 24) & 0x3f] | spfunction4[(right1 >>> 16) & 0x3f] | spfunction6[(right1 >>> - 8) & 0x3f] | spfunction8[right1 & 0x3f] | spfunction1[(right2 >>> 24) & 0x3f] | spfunction3[(right2 >>> 16) & - 0x3f] | spfunction5[(right2 >>> 8) & 0x3f] | spfunction7[right2 & 0x3f]); - } - temp = left; - left = right; - right = temp; //unreverse left and right - } //for either 1 or 3 iterations - - //move then each one bit to the right - left = ((left >>> 1) | (left << 31)); - right = ((right >>> 1) | (right << 31)); - - //now perform IP-1, which is IP in the opposite direction - temp = ((left >>> 1) ^ right) & 0x55555555; - right ^= temp; - left ^= (temp << 1); - temp = ((right >>> 8) ^ left) & 0x00ff00ff; - left ^= temp; - right ^= (temp << 8); - temp = ((right >>> 2) ^ left) & 0x33333333; - left ^= temp; - right ^= (temp << 2); - temp = ((left >>> 16) ^ right) & 0x0000ffff; - right ^= temp; - left ^= (temp << 16); - temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; - right ^= temp; - left ^= (temp << 4); - - //for Cipher Block Chaining mode, xor the message with the previous result - if (mode === 1) { - if (encrypt) { - cbcleft = left; - cbcright = right; - } else { - left ^= cbcleft2; - right ^= cbcright2; - } - } - - result[k++] = (left >>> 24); - result[k++] = ((left >>> 16) & 0xff); - result[k++] = ((left >>> 8) & 0xff); - result[k++] = (left & 0xff); - result[k++] = (right >>> 24); - result[k++] = ((right >>> 16) & 0xff); - result[k++] = ((right >>> 8) & 0xff); - result[k++] = (right & 0xff); - } //for every 8 characters, or 64 bits in the message - - //only remove padding if decrypting - note that you need to use the same padding option for both encrypt and decrypt - if (!encrypt) { - result = desRemovePadding(result, padding); - } - - return result; -} //end of des - - -//desCreateKeys -//this takes as input a 64 bit key (even though only 56 bits are used) -//as an array of 2 integers, and returns 16 48 bit keys - -function desCreateKeys(key) { - //declaring this locally speeds things up a bit - const pc2bytes0 = [ - 0, 0x4, 0x20000000, 0x20000004, 0x10000, 0x10004, 0x20010000, 0x20010004, 0x200, 0x204, - 0x20000200, 0x20000204, 0x10200, 0x10204, 0x20010200, 0x20010204 - ]; - const pc2bytes1 = [ - 0, 0x1, 0x100000, 0x100001, 0x4000000, 0x4000001, 0x4100000, 0x4100001, 0x100, 0x101, 0x100100, - 0x100101, 0x4000100, 0x4000101, 0x4100100, 0x4100101 - ]; - const pc2bytes2 = [ - 0, 0x8, 0x800, 0x808, 0x1000000, 0x1000008, 0x1000800, 0x1000808, 0, 0x8, 0x800, 0x808, - 0x1000000, 0x1000008, 0x1000800, 0x1000808 - ]; - const pc2bytes3 = [ - 0, 0x200000, 0x8000000, 0x8200000, 0x2000, 0x202000, 0x8002000, 0x8202000, 0x20000, 0x220000, - 0x8020000, 0x8220000, 0x22000, 0x222000, 0x8022000, 0x8222000 - ]; - const pc2bytes4 = [ - 0, 0x40000, 0x10, 0x40010, 0, 0x40000, 0x10, 0x40010, 0x1000, 0x41000, 0x1010, 0x41010, 0x1000, - 0x41000, 0x1010, 0x41010 - ]; - const pc2bytes5 = [ - 0, 0x400, 0x20, 0x420, 0, 0x400, 0x20, 0x420, 0x2000000, 0x2000400, 0x2000020, 0x2000420, - 0x2000000, 0x2000400, 0x2000020, 0x2000420 - ]; - const pc2bytes6 = [ - 0, 0x10000000, 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002, 0, 0x10000000, - 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002 - ]; - const pc2bytes7 = [ - 0, 0x10000, 0x800, 0x10800, 0x20000000, 0x20010000, 0x20000800, 0x20010800, 0x20000, 0x30000, - 0x20800, 0x30800, 0x20020000, 0x20030000, 0x20020800, 0x20030800 - ]; - const pc2bytes8 = [ - 0, 0x40000, 0, 0x40000, 0x2, 0x40002, 0x2, 0x40002, 0x2000000, 0x2040000, 0x2000000, 0x2040000, - 0x2000002, 0x2040002, 0x2000002, 0x2040002 - ]; - const pc2bytes9 = [ - 0, 0x10000000, 0x8, 0x10000008, 0, 0x10000000, 0x8, 0x10000008, 0x400, 0x10000400, 0x408, - 0x10000408, 0x400, 0x10000400, 0x408, 0x10000408 - ]; - const pc2bytes10 = [ - 0, 0x20, 0, 0x20, 0x100000, 0x100020, 0x100000, 0x100020, 0x2000, 0x2020, 0x2000, 0x2020, - 0x102000, 0x102020, 0x102000, 0x102020 - ]; - const pc2bytes11 = [ - 0, 0x1000000, 0x200, 0x1000200, 0x200000, 0x1200000, 0x200200, 0x1200200, 0x4000000, 0x5000000, - 0x4000200, 0x5000200, 0x4200000, 0x5200000, 0x4200200, 0x5200200 - ]; - const pc2bytes12 = [ - 0, 0x1000, 0x8000000, 0x8001000, 0x80000, 0x81000, 0x8080000, 0x8081000, 0x10, 0x1010, - 0x8000010, 0x8001010, 0x80010, 0x81010, 0x8080010, 0x8081010 - ]; - const pc2bytes13 = [0, 0x4, 0x100, 0x104, 0, 0x4, 0x100, 0x104, 0x1, 0x5, 0x101, 0x105, 0x1, 0x5, 0x101, 0x105]; - - //how many iterations (1 for des, 3 for triple des) - const iterations = key.length > 8 ? 3 : 1; //changed by Paul 16/6/2007 to use Triple DES for 9+ byte keys - //stores the return keys - const keys = new Array(32 * iterations); - //now define the left shifts which need to be done - const shifts = [0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0]; - //other variables - let lefttemp; - let righttemp; - let m = 0; - let n = 0; - let temp; - - for (let j = 0; j < iterations; j++) { //either 1 or 3 iterations - let left = (key[m++] << 24) | (key[m++] << 16) | (key[m++] << 8) | key[m++]; - let right = (key[m++] << 24) | (key[m++] << 16) | (key[m++] << 8) | key[m++]; - - temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; - right ^= temp; - left ^= (temp << 4); - temp = ((right >>> -16) ^ left) & 0x0000ffff; - left ^= temp; - right ^= (temp << -16); - temp = ((left >>> 2) ^ right) & 0x33333333; - right ^= temp; - left ^= (temp << 2); - temp = ((right >>> -16) ^ left) & 0x0000ffff; - left ^= temp; - right ^= (temp << -16); - temp = ((left >>> 1) ^ right) & 0x55555555; - right ^= temp; - left ^= (temp << 1); - temp = ((right >>> 8) ^ left) & 0x00ff00ff; - left ^= temp; - right ^= (temp << 8); - temp = ((left >>> 1) ^ right) & 0x55555555; - right ^= temp; - left ^= (temp << 1); - - //the right side needs to be shifted and to get the last four bits of the left side - temp = (left << 8) | ((right >>> 20) & 0x000000f0); - //left needs to be put upside down - left = (right << 24) | ((right << 8) & 0xff0000) | ((right >>> 8) & 0xff00) | ((right >>> 24) & 0xf0); - right = temp; - - //now go through and perform these shifts on the left and right keys - for (let i = 0; i < shifts.length; i++) { - //shift the keys either one or two bits to the left - if (shifts[i]) { - left = (left << 2) | (left >>> 26); - right = (right << 2) | (right >>> 26); - } else { - left = (left << 1) | (left >>> 27); - right = (right << 1) | (right >>> 27); - } - left &= -0xf; - right &= -0xf; - - //now apply PC-2, in such a way that E is easier when encrypting or decrypting - //this conversion will look like PC-2 except only the last 6 bits of each byte are used - //rather than 48 consecutive bits and the order of lines will be according to - //how the S selection functions will be applied: S2, S4, S6, S8, S1, S3, S5, S7 - lefttemp = pc2bytes0[left >>> 28] | pc2bytes1[(left >>> 24) & 0xf] | pc2bytes2[(left >>> 20) & 0xf] | pc2bytes3[( - left >>> 16) & 0xf] | pc2bytes4[(left >>> 12) & 0xf] | pc2bytes5[(left >>> 8) & 0xf] | pc2bytes6[(left >>> 4) & - 0xf]; - righttemp = pc2bytes7[right >>> 28] | pc2bytes8[(right >>> 24) & 0xf] | pc2bytes9[(right >>> 20) & 0xf] | - pc2bytes10[(right >>> 16) & 0xf] | pc2bytes11[(right >>> 12) & 0xf] | pc2bytes12[(right >>> 8) & 0xf] | - pc2bytes13[(right >>> 4) & 0xf]; - temp = ((righttemp >>> 16) ^ lefttemp) & 0x0000ffff; - keys[n++] = lefttemp ^ temp; - keys[n++] = righttemp ^ (temp << 16); - } - } //for each iterations - //return the keys we've created - return keys; -} //end of desCreateKeys - - -function desAddPadding(message, padding) { - const padLength = 8 - (message.length % 8); - - let pad; - if (padding === 2 && (padLength < 8)) { //pad the message with spaces - pad = ' '.charCodeAt(0); - } else if (padding === 1) { //PKCS7 padding - pad = padLength; - } else if (!padding && (padLength < 8)) { //pad the message out with null bytes - pad = 0; - } else if (padLength === 8) { - return message; - } else { - throw new Error('des: invalid padding'); - } - - const paddedMessage = new Uint8Array(message.length + padLength); - for (let i = 0; i < message.length; i++) { - paddedMessage[i] = message[i]; - } - for (let j = 0; j < padLength; j++) { - paddedMessage[message.length + j] = pad; - } - - return paddedMessage; -} - -function desRemovePadding(message, padding) { - let padLength = null; - let pad; - if (padding === 2) { // space padded - pad = ' '.charCodeAt(0); - } else if (padding === 1) { // PKCS7 - padLength = message[message.length - 1]; - } else if (!padding) { // null padding - pad = 0; - } else { - throw new Error('des: invalid padding'); - } - - if (!padLength) { - padLength = 1; - while (message[message.length - padLength] === pad) { - padLength++; - } - padLength--; - } - - return message.subarray(0, message.length - padLength); -} - -// added by Recurity Labs - -function TripleDES(key) { - this.key = []; - - for (let i = 0; i < 3; i++) { - this.key.push(new Uint8Array(key.subarray(i * 8, (i * 8) + 8))); - } - - this.encrypt = function(block) { - return des( - desCreateKeys(this.key[2]), - des( - desCreateKeys(this.key[1]), - des( - desCreateKeys(this.key[0]), - block, true, 0, null, null - ), - false, 0, null, null - ), true, 0, null, null - ); - }; -} - -TripleDES.keySize = TripleDES.prototype.keySize = 24; -TripleDES.blockSize = TripleDES.prototype.blockSize = 8; - -// This is "original" DES - -function DES(key) { - this.key = key; - - this.encrypt = function(block, padding) { - const keys = desCreateKeys(this.key); - return des(keys, block, true, 0, null, padding); - }; - - this.decrypt = function(block, padding) { - const keys = desCreateKeys(this.key); - return des(keys, block, false, 0, null, padding); - }; -} - -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Copyright 2010 pjacobs@xeekr.com . All rights reserved. - -// Modified by Recurity Labs GmbH - -// fixed/modified by Herbert Hanewinkel, www.haneWIN.de -// check www.haneWIN.de for the latest version - -// cast5.js is a Javascript implementation of CAST-128, as defined in RFC 2144. -// CAST-128 is a common OpenPGP cipher. - - -// CAST5 constructor - -function OpenPGPSymEncCAST5() { - this.BlockSize = 8; - this.KeySize = 16; - - this.setKey = function(key) { - this.masking = new Array(16); - this.rotate = new Array(16); - - this.reset(); - - if (key.length === this.KeySize) { - this.keySchedule(key); - } else { - throw new Error('CAST-128: keys must be 16 bytes'); - } - return true; - }; - - this.reset = function() { - for (let i = 0; i < 16; i++) { - this.masking[i] = 0; - this.rotate[i] = 0; - } - }; - - this.getBlockSize = function() { - return this.BlockSize; - }; - - this.encrypt = function(src) { - const dst = new Array(src.length); - - for (let i = 0; i < src.length; i += 8) { - let l = (src[i] << 24) | (src[i + 1] << 16) | (src[i + 2] << 8) | src[i + 3]; - let r = (src[i + 4] << 24) | (src[i + 5] << 16) | (src[i + 6] << 8) | src[i + 7]; - let t; - - t = r; - r = l ^ f1(r, this.masking[0], this.rotate[0]); - l = t; - t = r; - r = l ^ f2(r, this.masking[1], this.rotate[1]); - l = t; - t = r; - r = l ^ f3(r, this.masking[2], this.rotate[2]); - l = t; - t = r; - r = l ^ f1(r, this.masking[3], this.rotate[3]); - l = t; - - t = r; - r = l ^ f2(r, this.masking[4], this.rotate[4]); - l = t; - t = r; - r = l ^ f3(r, this.masking[5], this.rotate[5]); - l = t; - t = r; - r = l ^ f1(r, this.masking[6], this.rotate[6]); - l = t; - t = r; - r = l ^ f2(r, this.masking[7], this.rotate[7]); - l = t; - - t = r; - r = l ^ f3(r, this.masking[8], this.rotate[8]); - l = t; - t = r; - r = l ^ f1(r, this.masking[9], this.rotate[9]); - l = t; - t = r; - r = l ^ f2(r, this.masking[10], this.rotate[10]); - l = t; - t = r; - r = l ^ f3(r, this.masking[11], this.rotate[11]); - l = t; - - t = r; - r = l ^ f1(r, this.masking[12], this.rotate[12]); - l = t; - t = r; - r = l ^ f2(r, this.masking[13], this.rotate[13]); - l = t; - t = r; - r = l ^ f3(r, this.masking[14], this.rotate[14]); - l = t; - t = r; - r = l ^ f1(r, this.masking[15], this.rotate[15]); - l = t; - - dst[i] = (r >>> 24) & 255; - dst[i + 1] = (r >>> 16) & 255; - dst[i + 2] = (r >>> 8) & 255; - dst[i + 3] = r & 255; - dst[i + 4] = (l >>> 24) & 255; - dst[i + 5] = (l >>> 16) & 255; - dst[i + 6] = (l >>> 8) & 255; - dst[i + 7] = l & 255; - } - - return dst; - }; - - this.decrypt = function(src) { - const dst = new Array(src.length); - - for (let i = 0; i < src.length; i += 8) { - let l = (src[i] << 24) | (src[i + 1] << 16) | (src[i + 2] << 8) | src[i + 3]; - let r = (src[i + 4] << 24) | (src[i + 5] << 16) | (src[i + 6] << 8) | src[i + 7]; - let t; - - t = r; - r = l ^ f1(r, this.masking[15], this.rotate[15]); - l = t; - t = r; - r = l ^ f3(r, this.masking[14], this.rotate[14]); - l = t; - t = r; - r = l ^ f2(r, this.masking[13], this.rotate[13]); - l = t; - t = r; - r = l ^ f1(r, this.masking[12], this.rotate[12]); - l = t; - - t = r; - r = l ^ f3(r, this.masking[11], this.rotate[11]); - l = t; - t = r; - r = l ^ f2(r, this.masking[10], this.rotate[10]); - l = t; - t = r; - r = l ^ f1(r, this.masking[9], this.rotate[9]); - l = t; - t = r; - r = l ^ f3(r, this.masking[8], this.rotate[8]); - l = t; - - t = r; - r = l ^ f2(r, this.masking[7], this.rotate[7]); - l = t; - t = r; - r = l ^ f1(r, this.masking[6], this.rotate[6]); - l = t; - t = r; - r = l ^ f3(r, this.masking[5], this.rotate[5]); - l = t; - t = r; - r = l ^ f2(r, this.masking[4], this.rotate[4]); - l = t; - - t = r; - r = l ^ f1(r, this.masking[3], this.rotate[3]); - l = t; - t = r; - r = l ^ f3(r, this.masking[2], this.rotate[2]); - l = t; - t = r; - r = l ^ f2(r, this.masking[1], this.rotate[1]); - l = t; - t = r; - r = l ^ f1(r, this.masking[0], this.rotate[0]); - l = t; - - dst[i] = (r >>> 24) & 255; - dst[i + 1] = (r >>> 16) & 255; - dst[i + 2] = (r >>> 8) & 255; - dst[i + 3] = r & 255; - dst[i + 4] = (l >>> 24) & 255; - dst[i + 5] = (l >> 16) & 255; - dst[i + 6] = (l >> 8) & 255; - dst[i + 7] = l & 255; - } - - return dst; - }; - const scheduleA = new Array(4); - - scheduleA[0] = new Array(4); - scheduleA[0][0] = [4, 0, 0xd, 0xf, 0xc, 0xe, 0x8]; - scheduleA[0][1] = [5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa]; - scheduleA[0][2] = [6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9]; - scheduleA[0][3] = [7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb]; - - scheduleA[1] = new Array(4); - scheduleA[1][0] = [0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0]; - scheduleA[1][1] = [1, 4, 0, 2, 1, 3, 16 + 2]; - scheduleA[1][2] = [2, 5, 7, 6, 5, 4, 16 + 1]; - scheduleA[1][3] = [3, 7, 0xa, 9, 0xb, 8, 16 + 3]; - - scheduleA[2] = new Array(4); - scheduleA[2][0] = [4, 0, 0xd, 0xf, 0xc, 0xe, 8]; - scheduleA[2][1] = [5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa]; - scheduleA[2][2] = [6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9]; - scheduleA[2][3] = [7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb]; - - - scheduleA[3] = new Array(4); - scheduleA[3][0] = [0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0]; - scheduleA[3][1] = [1, 4, 0, 2, 1, 3, 16 + 2]; - scheduleA[3][2] = [2, 5, 7, 6, 5, 4, 16 + 1]; - scheduleA[3][3] = [3, 7, 0xa, 9, 0xb, 8, 16 + 3]; - - const scheduleB = new Array(4); - - scheduleB[0] = new Array(4); - scheduleB[0][0] = [16 + 8, 16 + 9, 16 + 7, 16 + 6, 16 + 2]; - scheduleB[0][1] = [16 + 0xa, 16 + 0xb, 16 + 5, 16 + 4, 16 + 6]; - scheduleB[0][2] = [16 + 0xc, 16 + 0xd, 16 + 3, 16 + 2, 16 + 9]; - scheduleB[0][3] = [16 + 0xe, 16 + 0xf, 16 + 1, 16 + 0, 16 + 0xc]; - - scheduleB[1] = new Array(4); - scheduleB[1][0] = [3, 2, 0xc, 0xd, 8]; - scheduleB[1][1] = [1, 0, 0xe, 0xf, 0xd]; - scheduleB[1][2] = [7, 6, 8, 9, 3]; - scheduleB[1][3] = [5, 4, 0xa, 0xb, 7]; - - - scheduleB[2] = new Array(4); - scheduleB[2][0] = [16 + 3, 16 + 2, 16 + 0xc, 16 + 0xd, 16 + 9]; - scheduleB[2][1] = [16 + 1, 16 + 0, 16 + 0xe, 16 + 0xf, 16 + 0xc]; - scheduleB[2][2] = [16 + 7, 16 + 6, 16 + 8, 16 + 9, 16 + 2]; - scheduleB[2][3] = [16 + 5, 16 + 4, 16 + 0xa, 16 + 0xb, 16 + 6]; - - - scheduleB[3] = new Array(4); - scheduleB[3][0] = [8, 9, 7, 6, 3]; - scheduleB[3][1] = [0xa, 0xb, 5, 4, 7]; - scheduleB[3][2] = [0xc, 0xd, 3, 2, 8]; - scheduleB[3][3] = [0xe, 0xf, 1, 0, 0xd]; - - // changed 'in' to 'inn' (in javascript 'in' is a reserved word) - this.keySchedule = function(inn) { - const t = new Array(8); - const k = new Array(32); - - let j; - - for (let i = 0; i < 4; i++) { - j = i * 4; - t[i] = (inn[j] << 24) | (inn[j + 1] << 16) | (inn[j + 2] << 8) | inn[j + 3]; - } - - const x = [6, 7, 4, 5]; - let ki = 0; - let w; - - for (let half = 0; half < 2; half++) { - for (let round = 0; round < 4; round++) { - for (j = 0; j < 4; j++) { - const a = scheduleA[round][j]; - w = t[a[1]]; - - w ^= sBox[4][(t[a[2] >>> 2] >>> (24 - 8 * (a[2] & 3))) & 0xff]; - w ^= sBox[5][(t[a[3] >>> 2] >>> (24 - 8 * (a[3] & 3))) & 0xff]; - w ^= sBox[6][(t[a[4] >>> 2] >>> (24 - 8 * (a[4] & 3))) & 0xff]; - w ^= sBox[7][(t[a[5] >>> 2] >>> (24 - 8 * (a[5] & 3))) & 0xff]; - w ^= sBox[x[j]][(t[a[6] >>> 2] >>> (24 - 8 * (a[6] & 3))) & 0xff]; - t[a[0]] = w; - } - - for (j = 0; j < 4; j++) { - const b = scheduleB[round][j]; - w = sBox[4][(t[b[0] >>> 2] >>> (24 - 8 * (b[0] & 3))) & 0xff]; - - w ^= sBox[5][(t[b[1] >>> 2] >>> (24 - 8 * (b[1] & 3))) & 0xff]; - w ^= sBox[6][(t[b[2] >>> 2] >>> (24 - 8 * (b[2] & 3))) & 0xff]; - w ^= sBox[7][(t[b[3] >>> 2] >>> (24 - 8 * (b[3] & 3))) & 0xff]; - w ^= sBox[4 + j][(t[b[4] >>> 2] >>> (24 - 8 * (b[4] & 3))) & 0xff]; - k[ki] = w; - ki++; - } - } - } - - for (let i = 0; i < 16; i++) { - this.masking[i] = k[i]; - this.rotate[i] = k[16 + i] & 0x1f; - } - }; - - // These are the three 'f' functions. See RFC 2144, section 2.2. - - function f1(d, m, r) { - const t = m + d; - const I = (t << r) | (t >>> (32 - r)); - return ((sBox[0][I >>> 24] ^ sBox[1][(I >>> 16) & 255]) - sBox[2][(I >>> 8) & 255]) + sBox[3][I & 255]; - } - - function f2(d, m, r) { - const t = m ^ d; - const I = (t << r) | (t >>> (32 - r)); - return ((sBox[0][I >>> 24] - sBox[1][(I >>> 16) & 255]) + sBox[2][(I >>> 8) & 255]) ^ sBox[3][I & 255]; - } - - function f3(d, m, r) { - const t = m - d; - const I = (t << r) | (t >>> (32 - r)); - return ((sBox[0][I >>> 24] + sBox[1][(I >>> 16) & 255]) ^ sBox[2][(I >>> 8) & 255]) - sBox[3][I & 255]; - } - - const sBox = new Array(8); - sBox[0] = [ - 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949, - 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, - 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, - 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0, - 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, - 0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935, - 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d, - 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, - 0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe, - 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3, - 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, - 0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291, - 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779, - 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, - 0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, - 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d, - 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, - 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, - 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c, - 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, - 0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d, - 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96, - 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, - 0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, - 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, - 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, - 0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, - 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872, - 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, - 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, - 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9, - 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf - ]; - - sBox[1] = [ - 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651, - 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, - 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, - 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806, - 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, - 0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359, - 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b, - 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, - 0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34, - 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb, - 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, - 0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860, - 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b, - 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, - 0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, - 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, - 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, - 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, - 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f, - 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, - 0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6, - 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58, - 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, - 0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, - 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6, - 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, - 0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6, - 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f, - 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, - 0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, - 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9, - 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1 - ]; - - sBox[2] = [ - 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90, - 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, - 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, - 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240, - 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, - 0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, - 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71, - 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, - 0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, - 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15, - 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, - 0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176, - 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148, - 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, - 0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, - 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e, - 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, - 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, - 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a, - 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, - 0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, - 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5, - 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, - 0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536, - 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, - 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, - 0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69, - 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, - 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, - 0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, - 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a, - 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783 - ]; - - sBox[3] = [ - 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1, - 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, - 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, - 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121, - 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, - 0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, - 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb, - 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, - 0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d, - 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6, - 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, - 0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003, - 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, - 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, - 0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, - 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a, - 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, - 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, - 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26, - 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, - 0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7, - 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417, - 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, - 0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2, - 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, - 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, - 0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, - 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, - 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, - 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, - 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282, - 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2 - ]; - - sBox[4] = [ - 0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f, - 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, - 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, - 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02, - 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, - 0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7, - 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9, - 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, - 0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774, - 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655, - 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, - 0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910, - 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1, - 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, - 0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, - 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f, - 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, - 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, - 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3, - 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, - 0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4, - 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2, - 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, - 0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5, - 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, - 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, - 0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801, - 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, - 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, - 0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, - 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8, - 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4 - ]; - - sBox[5] = [ - 0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac, - 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, - 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, - 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98, - 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, - 0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3, - 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd, - 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, - 0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9, - 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54, - 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, - 0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc, - 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf, - 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, - 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, - 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289, - 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, - 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, - 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b, - 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, - 0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13, - 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976, - 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, - 0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891, - 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da, - 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, - 0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084, - 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25, - 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, - 0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, - 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd, - 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f - ]; - - sBox[6] = [ - 0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f, - 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, - 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, - 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19, - 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, - 0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516, - 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88, - 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, - 0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756, - 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, - 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, - 0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688, - 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28, - 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, - 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, - 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, - 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, - 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, - 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566, - 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, - 0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962, - 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e, - 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, - 0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c, - 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, - 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, - 0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be, - 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767, - 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, - 0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, - 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c, - 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3 - ]; - - sBox[7] = [ - 0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5, - 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, - 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, - 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d, - 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, - 0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862, - 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc, - 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, - 0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e, - 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039, - 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, - 0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42, - 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5, - 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, - 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, - 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c, - 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, - 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, - 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70, - 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, - 0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c, - 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3, - 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, - 0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101, - 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f, - 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, - 0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a, - 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c, - 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, - 0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, - 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82, - 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e - ]; -} - -function CAST5(key) { - this.cast5 = new OpenPGPSymEncCAST5(); - this.cast5.setKey(key); - - this.encrypt = function(block) { - return this.cast5.encrypt(block); - }; -} - -CAST5.blockSize = CAST5.prototype.blockSize = 8; -CAST5.keySize = CAST5.prototype.keySize = 16; - -/* eslint-disable no-mixed-operators, no-fallthrough */ - - -/* Modified by Recurity Labs GmbH - * - * Cipher.js - * A block-cipher algorithm implementation on JavaScript - * See Cipher.readme.txt for further information. - * - * Copyright(c) 2009 Atsushi Oka [ http://oka.nu/ ] - * This script file is distributed under the LGPL - * - * ACKNOWLEDGMENT - * - * The main subroutines are written by Michiel van Everdingen. - * - * Michiel van Everdingen - * http://home.versatel.nl/MAvanEverdingen/index.html - * - * All rights for these routines are reserved to Michiel van Everdingen. - * - */ - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//Math -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -const MAXINT = 0xFFFFFFFF; - -function rotw(w, n) { - return (w << n | w >>> (32 - n)) & MAXINT; -} - -function getW(a, i) { - return a[i] | a[i + 1] << 8 | a[i + 2] << 16 | a[i + 3] << 24; -} - -function setW(a, i, w) { - a.splice(i, 4, w & 0xFF, (w >>> 8) & 0xFF, (w >>> 16) & 0xFF, (w >>> 24) & 0xFF); -} - -function getB(x, n) { - return (x >>> (n * 8)) & 0xFF; -} - -// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Twofish -// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -function createTwofish() { - // - let keyBytes = null; - let dataBytes = null; - let dataOffset = -1; - // var dataLength = -1; - // var idx2 = -1; - // - - let tfsKey = []; - let tfsM = [ - [], - [], - [], - [] - ]; - - function tfsInit(key) { - keyBytes = key; - let i; - let a; - let b; - let c; - let d; - const meKey = []; - const moKey = []; - const inKey = []; - let kLen; - const sKey = []; - let f01; - let f5b; - let fef; - - const q0 = [ - [8, 1, 7, 13, 6, 15, 3, 2, 0, 11, 5, 9, 14, 12, 10, 4], - [2, 8, 11, 13, 15, 7, 6, 14, 3, 1, 9, 4, 0, 10, 12, 5] - ]; - const q1 = [ - [14, 12, 11, 8, 1, 2, 3, 5, 15, 4, 10, 6, 7, 0, 9, 13], - [1, 14, 2, 11, 4, 12, 3, 7, 6, 13, 10, 5, 15, 9, 0, 8] - ]; - const q2 = [ - [11, 10, 5, 14, 6, 13, 9, 0, 12, 8, 15, 3, 2, 4, 7, 1], - [4, 12, 7, 5, 1, 6, 9, 10, 0, 14, 13, 8, 2, 11, 3, 15] - ]; - const q3 = [ - [13, 7, 15, 4, 1, 2, 6, 14, 9, 11, 3, 0, 8, 5, 12, 10], - [11, 9, 5, 1, 12, 3, 13, 14, 6, 4, 7, 15, 2, 0, 8, 10] - ]; - const ror4 = [0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15]; - const ashx = [0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 5, 14, 7]; - const q = [ - [], - [] - ]; - const m = [ - [], - [], - [], - [] - ]; - - function ffm5b(x) { - return x ^ (x >> 2) ^ [0, 90, 180, 238][x & 3]; - } - - function ffmEf(x) { - return x ^ (x >> 1) ^ (x >> 2) ^ [0, 238, 180, 90][x & 3]; - } - - function mdsRem(p, q) { - let i; - let t; - let u; - for (i = 0; i < 8; i++) { - t = q >>> 24; - q = ((q << 8) & MAXINT) | p >>> 24; - p = (p << 8) & MAXINT; - u = t << 1; - if (t & 128) { - u ^= 333; - } - q ^= t ^ (u << 16); - u ^= t >>> 1; - if (t & 1) { - u ^= 166; - } - q ^= u << 24 | u << 8; - } - return q; - } - - function qp(n, x) { - const a = x >> 4; - const b = x & 15; - const c = q0[n][a ^ b]; - const d = q1[n][ror4[b] ^ ashx[a]]; - return q3[n][ror4[d] ^ ashx[c]] << 4 | q2[n][c ^ d]; - } - - function hFun(x, key) { - let a = getB(x, 0); - let b = getB(x, 1); - let c = getB(x, 2); - let d = getB(x, 3); - switch (kLen) { - case 4: - a = q[1][a] ^ getB(key[3], 0); - b = q[0][b] ^ getB(key[3], 1); - c = q[0][c] ^ getB(key[3], 2); - d = q[1][d] ^ getB(key[3], 3); - case 3: - a = q[1][a] ^ getB(key[2], 0); - b = q[1][b] ^ getB(key[2], 1); - c = q[0][c] ^ getB(key[2], 2); - d = q[0][d] ^ getB(key[2], 3); - case 2: - a = q[0][q[0][a] ^ getB(key[1], 0)] ^ getB(key[0], 0); - b = q[0][q[1][b] ^ getB(key[1], 1)] ^ getB(key[0], 1); - c = q[1][q[0][c] ^ getB(key[1], 2)] ^ getB(key[0], 2); - d = q[1][q[1][d] ^ getB(key[1], 3)] ^ getB(key[0], 3); - } - return m[0][a] ^ m[1][b] ^ m[2][c] ^ m[3][d]; - } - - keyBytes = keyBytes.slice(0, 32); - i = keyBytes.length; - while (i !== 16 && i !== 24 && i !== 32) { - keyBytes[i++] = 0; - } - - for (i = 0; i < keyBytes.length; i += 4) { - inKey[i >> 2] = getW(keyBytes, i); - } - for (i = 0; i < 256; i++) { - q[0][i] = qp(0, i); - q[1][i] = qp(1, i); - } - for (i = 0; i < 256; i++) { - f01 = q[1][i]; - f5b = ffm5b(f01); - fef = ffmEf(f01); - m[0][i] = f01 + (f5b << 8) + (fef << 16) + (fef << 24); - m[2][i] = f5b + (fef << 8) + (f01 << 16) + (fef << 24); - f01 = q[0][i]; - f5b = ffm5b(f01); - fef = ffmEf(f01); - m[1][i] = fef + (fef << 8) + (f5b << 16) + (f01 << 24); - m[3][i] = f5b + (f01 << 8) + (fef << 16) + (f5b << 24); - } - - kLen = inKey.length / 2; - for (i = 0; i < kLen; i++) { - a = inKey[i + i]; - meKey[i] = a; - b = inKey[i + i + 1]; - moKey[i] = b; - sKey[kLen - i - 1] = mdsRem(a, b); - } - for (i = 0; i < 40; i += 2) { - a = 0x1010101 * i; - b = a + 0x1010101; - a = hFun(a, meKey); - b = rotw(hFun(b, moKey), 8); - tfsKey[i] = (a + b) & MAXINT; - tfsKey[i + 1] = rotw(a + 2 * b, 9); - } - for (i = 0; i < 256; i++) { - a = b = c = d = i; - switch (kLen) { - case 4: - a = q[1][a] ^ getB(sKey[3], 0); - b = q[0][b] ^ getB(sKey[3], 1); - c = q[0][c] ^ getB(sKey[3], 2); - d = q[1][d] ^ getB(sKey[3], 3); - case 3: - a = q[1][a] ^ getB(sKey[2], 0); - b = q[1][b] ^ getB(sKey[2], 1); - c = q[0][c] ^ getB(sKey[2], 2); - d = q[0][d] ^ getB(sKey[2], 3); - case 2: - tfsM[0][i] = m[0][q[0][q[0][a] ^ getB(sKey[1], 0)] ^ getB(sKey[0], 0)]; - tfsM[1][i] = m[1][q[0][q[1][b] ^ getB(sKey[1], 1)] ^ getB(sKey[0], 1)]; - tfsM[2][i] = m[2][q[1][q[0][c] ^ getB(sKey[1], 2)] ^ getB(sKey[0], 2)]; - tfsM[3][i] = m[3][q[1][q[1][d] ^ getB(sKey[1], 3)] ^ getB(sKey[0], 3)]; - } - } - } - - function tfsG0(x) { - return tfsM[0][getB(x, 0)] ^ tfsM[1][getB(x, 1)] ^ tfsM[2][getB(x, 2)] ^ tfsM[3][getB(x, 3)]; - } - - function tfsG1(x) { - return tfsM[0][getB(x, 3)] ^ tfsM[1][getB(x, 0)] ^ tfsM[2][getB(x, 1)] ^ tfsM[3][getB(x, 2)]; - } - - function tfsFrnd(r, blk) { - let a = tfsG0(blk[0]); - let b = tfsG1(blk[1]); - blk[2] = rotw(blk[2] ^ (a + b + tfsKey[4 * r + 8]) & MAXINT, 31); - blk[3] = rotw(blk[3], 1) ^ (a + 2 * b + tfsKey[4 * r + 9]) & MAXINT; - a = tfsG0(blk[2]); - b = tfsG1(blk[3]); - blk[0] = rotw(blk[0] ^ (a + b + tfsKey[4 * r + 10]) & MAXINT, 31); - blk[1] = rotw(blk[1], 1) ^ (a + 2 * b + tfsKey[4 * r + 11]) & MAXINT; - } - - function tfsIrnd(i, blk) { - let a = tfsG0(blk[0]); - let b = tfsG1(blk[1]); - blk[2] = rotw(blk[2], 1) ^ (a + b + tfsKey[4 * i + 10]) & MAXINT; - blk[3] = rotw(blk[3] ^ (a + 2 * b + tfsKey[4 * i + 11]) & MAXINT, 31); - a = tfsG0(blk[2]); - b = tfsG1(blk[3]); - blk[0] = rotw(blk[0], 1) ^ (a + b + tfsKey[4 * i + 8]) & MAXINT; - blk[1] = rotw(blk[1] ^ (a + 2 * b + tfsKey[4 * i + 9]) & MAXINT, 31); - } - - function tfsClose() { - tfsKey = []; - tfsM = [ - [], - [], - [], - [] - ]; - } - - function tfsEncrypt(data, offset) { - dataBytes = data; - dataOffset = offset; - const blk = [getW(dataBytes, dataOffset) ^ tfsKey[0], - getW(dataBytes, dataOffset + 4) ^ tfsKey[1], - getW(dataBytes, dataOffset + 8) ^ tfsKey[2], - getW(dataBytes, dataOffset + 12) ^ tfsKey[3]]; - for (let j = 0; j < 8; j++) { - tfsFrnd(j, blk); - } - setW(dataBytes, dataOffset, blk[2] ^ tfsKey[4]); - setW(dataBytes, dataOffset + 4, blk[3] ^ tfsKey[5]); - setW(dataBytes, dataOffset + 8, blk[0] ^ tfsKey[6]); - setW(dataBytes, dataOffset + 12, blk[1] ^ tfsKey[7]); - dataOffset += 16; - return dataBytes; - } - - function tfsDecrypt(data, offset) { - dataBytes = data; - dataOffset = offset; - const blk = [getW(dataBytes, dataOffset) ^ tfsKey[4], - getW(dataBytes, dataOffset + 4) ^ tfsKey[5], - getW(dataBytes, dataOffset + 8) ^ tfsKey[6], - getW(dataBytes, dataOffset + 12) ^ tfsKey[7]]; - for (let j = 7; j >= 0; j--) { - tfsIrnd(j, blk); - } - setW(dataBytes, dataOffset, blk[2] ^ tfsKey[0]); - setW(dataBytes, dataOffset + 4, blk[3] ^ tfsKey[1]); - setW(dataBytes, dataOffset + 8, blk[0] ^ tfsKey[2]); - setW(dataBytes, dataOffset + 12, blk[1] ^ tfsKey[3]); - dataOffset += 16; - } - - // added by Recurity Labs - - function tfsFinal() { - return dataBytes; - } - - return { - name: 'twofish', - blocksize: 128 / 8, - open: tfsInit, - close: tfsClose, - encrypt: tfsEncrypt, - decrypt: tfsDecrypt, - // added by Recurity Labs - finalize: tfsFinal - }; -} - -// added by Recurity Labs - -function TF(key) { - this.tf = createTwofish(); - this.tf.open(Array.from(key), 0); - - this.encrypt = function(block) { - return this.tf.encrypt(Array.from(block), 0); - }; -} - -TF.keySize = TF.prototype.keySize = 32; -TF.blockSize = TF.prototype.blockSize = 16; - -/* Modified by Recurity Labs GmbH - * - * Originally written by nklein software (nklein.com) - */ - -/* - * Javascript implementation based on Bruce Schneier's reference implementation. - * - * - * The constructor doesn't do much of anything. It's just here - * so we can start defining properties and methods and such. - */ -function Blowfish() {} - -/* - * Declare the block size so that protocols know what size - * Initialization Vector (IV) they will need. - */ -Blowfish.prototype.BLOCKSIZE = 8; - -/* - * These are the default SBOXES. - */ -Blowfish.prototype.SBOXES = [ - [ - 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, - 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, - 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658, - 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, - 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, - 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, - 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6, - 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, - 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, - 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, - 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, - 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, - 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, - 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, - 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, - 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, - 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, - 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, - 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, - 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, - 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, - 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, - 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, - 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, - 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, - 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, - 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8, - 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, - 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, - 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, - 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, - 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, - 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, - 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, - 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, - 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, - 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, - 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, - 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, - 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, - 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, - 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, - 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a - ], - [ - 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, - 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, - 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, - 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, - 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, - 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, - 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, - 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, - 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, - 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, - 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, - 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, - 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, - 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, - 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, - 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, - 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, - 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, - 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, - 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, - 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, - 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, - 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, - 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, - 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, - 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, - 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, - 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, - 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, - 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, - 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, - 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, - 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, - 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, - 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, - 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, - 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, - 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, - 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, - 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, - 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, - 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, - 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7 - ], - [ - 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, - 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, - 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, - 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, - 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, - 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, - 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, - 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, - 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, - 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, - 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, - 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, - 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, - 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, - 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, - 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, - 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, - 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, - 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74, - 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, - 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, - 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, - 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, - 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, - 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, - 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, - 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, - 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, - 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, - 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, - 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, - 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, - 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, - 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, - 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, - 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, - 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, - 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, - 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, - 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, - 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, - 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, - 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0 - ], - [ - 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, - 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, - 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, - 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, - 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, - 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, - 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, - 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, - 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, - 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, - 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, - 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, - 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, - 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, - 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5, - 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, - 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, - 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, - 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd, - 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, - 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, - 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, - 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc, - 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, - 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, - 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, - 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, - 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, - 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, - 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, - 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, - 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, - 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, - 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, - 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623, - 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, - 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, - 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, - 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3, - 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, - 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, - 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, - 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 - ] -]; - -//* -//* This is the default PARRAY -//* -Blowfish.prototype.PARRAY = [ - 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, - 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, - 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b -]; - -//* -//* This is the number of rounds the cipher will go -//* -Blowfish.prototype.NN = 16; - -//* -//* This function is needed to get rid of problems -//* with the high-bit getting set. If we don't do -//* this, then sometimes ( aa & 0x00FFFFFFFF ) is not -//* equal to ( bb & 0x00FFFFFFFF ) even when they -//* agree bit-for-bit for the first 32 bits. -//* -Blowfish.prototype._clean = function(xx) { - if (xx < 0) { - const yy = xx & 0x7FFFFFFF; - xx = yy + 0x80000000; - } - return xx; -}; - -//* -//* This is the mixing function that uses the sboxes -//* -Blowfish.prototype._F = function(xx) { - let yy; - - const dd = xx & 0x00FF; - xx >>>= 8; - const cc = xx & 0x00FF; - xx >>>= 8; - const bb = xx & 0x00FF; - xx >>>= 8; - const aa = xx & 0x00FF; - - yy = this.sboxes[0][aa] + this.sboxes[1][bb]; - yy ^= this.sboxes[2][cc]; - yy += this.sboxes[3][dd]; - - return yy; -}; - -//* -//* This method takes an array with two values, left and right -//* and does NN rounds of Blowfish on them. -//* -Blowfish.prototype._encryptBlock = function(vals) { - let dataL = vals[0]; - let dataR = vals[1]; - - let ii; - - for (ii = 0; ii < this.NN; ++ii) { - dataL ^= this.parray[ii]; - dataR = this._F(dataL) ^ dataR; - - const tmp = dataL; - dataL = dataR; - dataR = tmp; - } - - dataL ^= this.parray[this.NN + 0]; - dataR ^= this.parray[this.NN + 1]; - - vals[0] = this._clean(dataR); - vals[1] = this._clean(dataL); -}; - -//* -//* This method takes a vector of numbers and turns them -//* into long words so that they can be processed by the -//* real algorithm. -//* -//* Maybe I should make the real algorithm above take a vector -//* instead. That will involve more looping, but it won't require -//* the F() method to deconstruct the vector. -//* -Blowfish.prototype.encryptBlock = function(vector) { - let ii; - const vals = [0, 0]; - const off = this.BLOCKSIZE / 2; - for (ii = 0; ii < this.BLOCKSIZE / 2; ++ii) { - vals[0] = (vals[0] << 8) | (vector[ii + 0] & 0x00FF); - vals[1] = (vals[1] << 8) | (vector[ii + off] & 0x00FF); - } - - this._encryptBlock(vals); - - const ret = []; - for (ii = 0; ii < this.BLOCKSIZE / 2; ++ii) { - ret[ii + 0] = ((vals[0] >>> (24 - 8 * (ii))) & 0x00FF); - ret[ii + off] = ((vals[1] >>> (24 - 8 * (ii))) & 0x00FF); - // vals[ 0 ] = ( vals[ 0 ] >>> 8 ); - // vals[ 1 ] = ( vals[ 1 ] >>> 8 ); - } - - return ret; -}; - -//* -//* This method takes an array with two values, left and right -//* and undoes NN rounds of Blowfish on them. -//* -Blowfish.prototype._decryptBlock = function(vals) { - let dataL = vals[0]; - let dataR = vals[1]; - - let ii; - - for (ii = this.NN + 1; ii > 1; --ii) { - dataL ^= this.parray[ii]; - dataR = this._F(dataL) ^ dataR; - - const tmp = dataL; - dataL = dataR; - dataR = tmp; - } - - dataL ^= this.parray[1]; - dataR ^= this.parray[0]; - - vals[0] = this._clean(dataR); - vals[1] = this._clean(dataL); -}; - -//* -//* This method takes a key array and initializes the -//* sboxes and parray for this encryption. -//* -Blowfish.prototype.init = function(key) { - let ii; - let jj = 0; - - this.parray = []; - for (ii = 0; ii < this.NN + 2; ++ii) { - let data = 0x00000000; - for (let kk = 0; kk < 4; ++kk) { - data = (data << 8) | (key[jj] & 0x00FF); - if (++jj >= key.length) { - jj = 0; - } - } - this.parray[ii] = this.PARRAY[ii] ^ data; - } - - this.sboxes = []; - for (ii = 0; ii < 4; ++ii) { - this.sboxes[ii] = []; - for (jj = 0; jj < 256; ++jj) { - this.sboxes[ii][jj] = this.SBOXES[ii][jj]; - } - } - - const vals = [0x00000000, 0x00000000]; - - for (ii = 0; ii < this.NN + 2; ii += 2) { - this._encryptBlock(vals); - this.parray[ii + 0] = vals[0]; - this.parray[ii + 1] = vals[1]; - } - - for (ii = 0; ii < 4; ++ii) { - for (jj = 0; jj < 256; jj += 2) { - this._encryptBlock(vals); - this.sboxes[ii][jj + 0] = vals[0]; - this.sboxes[ii][jj + 1] = vals[1]; - } - } -}; - -// added by Recurity Labs -function BF(key) { - this.bf = new Blowfish(); - this.bf.init(key); - - this.encrypt = function(block) { - return this.bf.encryptBlock(block); - }; -} - -BF.keySize = BF.prototype.keySize = 16; -BF.blockSize = BF.prototype.blockSize = 8; - -/** - * @fileoverview Symmetric cryptography functions - * @module crypto/cipher - * @private - */ - -/** - * AES-128 encryption and decryption (ID 7) - * @function - * @param {String} key - 128-bit key - * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} - * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} - * @returns {Object} - */ -const aes128 = aes(128); -/** - * AES-128 Block Cipher (ID 8) - * @function - * @param {String} key - 192-bit key - * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} - * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} - * @returns {Object} - */ -const aes192 = aes(192); -/** - * AES-128 Block Cipher (ID 9) - * @function - * @param {String} key - 256-bit key - * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} - * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} - * @returns {Object} - */ -const aes256 = aes(256); -// Not in OpenPGP specifications -const des$1 = DES; -/** - * Triple DES Block Cipher (ID 2) - * @function - * @param {String} key - 192-bit key - * @see {@link https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-67r2.pdf|NIST SP 800-67} - * @returns {Object} - */ -const tripledes = TripleDES; -/** - * CAST-128 Block Cipher (ID 3) - * @function - * @param {String} key - 128-bit key - * @see {@link https://tools.ietf.org/html/rfc2144|The CAST-128 Encryption Algorithm} - * @returns {Object} - */ -const cast5 = CAST5; -/** - * Twofish Block Cipher (ID 10) - * @function - * @param {String} key - 256-bit key - * @see {@link https://tools.ietf.org/html/rfc4880#ref-TWOFISH|TWOFISH} - * @returns {Object} - */ -const twofish = TF; -/** - * Blowfish Block Cipher (ID 4) - * @function - * @param {String} key - 128-bit key - * @see {@link https://tools.ietf.org/html/rfc4880#ref-BLOWFISH|BLOWFISH} - * @returns {Object} - */ -const blowfish = BF; -/** - * Not implemented - * @function - * @throws {Error} - */ -const idea = function() { - throw new Error('IDEA symmetric-key algorithm not implemented'); -}; - -var cipher = /*#__PURE__*/Object.freeze({ - __proto__: null, - aes128: aes128, - aes192: aes192, - aes256: aes256, - des: des$1, - tripledes: tripledes, - cast5: cast5, - twofish: twofish, - blowfish: blowfish, - idea: idea -}); - -var sha1_asm = function ( stdlib, foreign, buffer ) { - "use asm"; - - // SHA256 state - var H0 = 0, H1 = 0, H2 = 0, H3 = 0, H4 = 0, - TOTAL0 = 0, TOTAL1 = 0; - - // HMAC state - var I0 = 0, I1 = 0, I2 = 0, I3 = 0, I4 = 0, - O0 = 0, O1 = 0, O2 = 0, O3 = 0, O4 = 0; - - // I/O buffer - var HEAP = new stdlib.Uint8Array(buffer); - - function _core ( w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15 ) { - w0 = w0|0; - w1 = w1|0; - w2 = w2|0; - w3 = w3|0; - w4 = w4|0; - w5 = w5|0; - w6 = w6|0; - w7 = w7|0; - w8 = w8|0; - w9 = w9|0; - w10 = w10|0; - w11 = w11|0; - w12 = w12|0; - w13 = w13|0; - w14 = w14|0; - w15 = w15|0; - - var a = 0, b = 0, c = 0, d = 0, e = 0, n = 0, t = 0, - w16 = 0, w17 = 0, w18 = 0, w19 = 0, - w20 = 0, w21 = 0, w22 = 0, w23 = 0, w24 = 0, w25 = 0, w26 = 0, w27 = 0, w28 = 0, w29 = 0, - w30 = 0, w31 = 0, w32 = 0, w33 = 0, w34 = 0, w35 = 0, w36 = 0, w37 = 0, w38 = 0, w39 = 0, - w40 = 0, w41 = 0, w42 = 0, w43 = 0, w44 = 0, w45 = 0, w46 = 0, w47 = 0, w48 = 0, w49 = 0, - w50 = 0, w51 = 0, w52 = 0, w53 = 0, w54 = 0, w55 = 0, w56 = 0, w57 = 0, w58 = 0, w59 = 0, - w60 = 0, w61 = 0, w62 = 0, w63 = 0, w64 = 0, w65 = 0, w66 = 0, w67 = 0, w68 = 0, w69 = 0, - w70 = 0, w71 = 0, w72 = 0, w73 = 0, w74 = 0, w75 = 0, w76 = 0, w77 = 0, w78 = 0, w79 = 0; - - a = H0; - b = H1; - c = H2; - d = H3; - e = H4; - - // 0 - t = ( w0 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 1 - t = ( w1 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 2 - t = ( w2 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 3 - t = ( w3 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 4 - t = ( w4 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 5 - t = ( w5 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 6 - t = ( w6 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 7 - t = ( w7 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 8 - t = ( w8 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 9 - t = ( w9 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 10 - t = ( w10 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 11 - t = ( w11 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 12 - t = ( w12 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 13 - t = ( w13 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 14 - t = ( w14 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 15 - t = ( w15 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 16 - n = w13 ^ w8 ^ w2 ^ w0; - w16 = (n << 1) | (n >>> 31); - t = (w16 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 17 - n = w14 ^ w9 ^ w3 ^ w1; - w17 = (n << 1) | (n >>> 31); - t = (w17 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 18 - n = w15 ^ w10 ^ w4 ^ w2; - w18 = (n << 1) | (n >>> 31); - t = (w18 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 19 - n = w16 ^ w11 ^ w5 ^ w3; - w19 = (n << 1) | (n >>> 31); - t = (w19 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 20 - n = w17 ^ w12 ^ w6 ^ w4; - w20 = (n << 1) | (n >>> 31); - t = (w20 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 21 - n = w18 ^ w13 ^ w7 ^ w5; - w21 = (n << 1) | (n >>> 31); - t = (w21 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 22 - n = w19 ^ w14 ^ w8 ^ w6; - w22 = (n << 1) | (n >>> 31); - t = (w22 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 23 - n = w20 ^ w15 ^ w9 ^ w7; - w23 = (n << 1) | (n >>> 31); - t = (w23 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 24 - n = w21 ^ w16 ^ w10 ^ w8; - w24 = (n << 1) | (n >>> 31); - t = (w24 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 25 - n = w22 ^ w17 ^ w11 ^ w9; - w25 = (n << 1) | (n >>> 31); - t = (w25 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 26 - n = w23 ^ w18 ^ w12 ^ w10; - w26 = (n << 1) | (n >>> 31); - t = (w26 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 27 - n = w24 ^ w19 ^ w13 ^ w11; - w27 = (n << 1) | (n >>> 31); - t = (w27 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 28 - n = w25 ^ w20 ^ w14 ^ w12; - w28 = (n << 1) | (n >>> 31); - t = (w28 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 29 - n = w26 ^ w21 ^ w15 ^ w13; - w29 = (n << 1) | (n >>> 31); - t = (w29 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 30 - n = w27 ^ w22 ^ w16 ^ w14; - w30 = (n << 1) | (n >>> 31); - t = (w30 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 31 - n = w28 ^ w23 ^ w17 ^ w15; - w31 = (n << 1) | (n >>> 31); - t = (w31 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 32 - n = w29 ^ w24 ^ w18 ^ w16; - w32 = (n << 1) | (n >>> 31); - t = (w32 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 33 - n = w30 ^ w25 ^ w19 ^ w17; - w33 = (n << 1) | (n >>> 31); - t = (w33 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 34 - n = w31 ^ w26 ^ w20 ^ w18; - w34 = (n << 1) | (n >>> 31); - t = (w34 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 35 - n = w32 ^ w27 ^ w21 ^ w19; - w35 = (n << 1) | (n >>> 31); - t = (w35 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 36 - n = w33 ^ w28 ^ w22 ^ w20; - w36 = (n << 1) | (n >>> 31); - t = (w36 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 37 - n = w34 ^ w29 ^ w23 ^ w21; - w37 = (n << 1) | (n >>> 31); - t = (w37 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 38 - n = w35 ^ w30 ^ w24 ^ w22; - w38 = (n << 1) | (n >>> 31); - t = (w38 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 39 - n = w36 ^ w31 ^ w25 ^ w23; - w39 = (n << 1) | (n >>> 31); - t = (w39 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 40 - n = w37 ^ w32 ^ w26 ^ w24; - w40 = (n << 1) | (n >>> 31); - t = (w40 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 41 - n = w38 ^ w33 ^ w27 ^ w25; - w41 = (n << 1) | (n >>> 31); - t = (w41 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 42 - n = w39 ^ w34 ^ w28 ^ w26; - w42 = (n << 1) | (n >>> 31); - t = (w42 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 43 - n = w40 ^ w35 ^ w29 ^ w27; - w43 = (n << 1) | (n >>> 31); - t = (w43 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 44 - n = w41 ^ w36 ^ w30 ^ w28; - w44 = (n << 1) | (n >>> 31); - t = (w44 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 45 - n = w42 ^ w37 ^ w31 ^ w29; - w45 = (n << 1) | (n >>> 31); - t = (w45 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 46 - n = w43 ^ w38 ^ w32 ^ w30; - w46 = (n << 1) | (n >>> 31); - t = (w46 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 47 - n = w44 ^ w39 ^ w33 ^ w31; - w47 = (n << 1) | (n >>> 31); - t = (w47 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 48 - n = w45 ^ w40 ^ w34 ^ w32; - w48 = (n << 1) | (n >>> 31); - t = (w48 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 49 - n = w46 ^ w41 ^ w35 ^ w33; - w49 = (n << 1) | (n >>> 31); - t = (w49 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 50 - n = w47 ^ w42 ^ w36 ^ w34; - w50 = (n << 1) | (n >>> 31); - t = (w50 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 51 - n = w48 ^ w43 ^ w37 ^ w35; - w51 = (n << 1) | (n >>> 31); - t = (w51 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 52 - n = w49 ^ w44 ^ w38 ^ w36; - w52 = (n << 1) | (n >>> 31); - t = (w52 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 53 - n = w50 ^ w45 ^ w39 ^ w37; - w53 = (n << 1) | (n >>> 31); - t = (w53 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 54 - n = w51 ^ w46 ^ w40 ^ w38; - w54 = (n << 1) | (n >>> 31); - t = (w54 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 55 - n = w52 ^ w47 ^ w41 ^ w39; - w55 = (n << 1) | (n >>> 31); - t = (w55 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 56 - n = w53 ^ w48 ^ w42 ^ w40; - w56 = (n << 1) | (n >>> 31); - t = (w56 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 57 - n = w54 ^ w49 ^ w43 ^ w41; - w57 = (n << 1) | (n >>> 31); - t = (w57 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 58 - n = w55 ^ w50 ^ w44 ^ w42; - w58 = (n << 1) | (n >>> 31); - t = (w58 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 59 - n = w56 ^ w51 ^ w45 ^ w43; - w59 = (n << 1) | (n >>> 31); - t = (w59 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 60 - n = w57 ^ w52 ^ w46 ^ w44; - w60 = (n << 1) | (n >>> 31); - t = (w60 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 61 - n = w58 ^ w53 ^ w47 ^ w45; - w61 = (n << 1) | (n >>> 31); - t = (w61 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 62 - n = w59 ^ w54 ^ w48 ^ w46; - w62 = (n << 1) | (n >>> 31); - t = (w62 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 63 - n = w60 ^ w55 ^ w49 ^ w47; - w63 = (n << 1) | (n >>> 31); - t = (w63 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 64 - n = w61 ^ w56 ^ w50 ^ w48; - w64 = (n << 1) | (n >>> 31); - t = (w64 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 65 - n = w62 ^ w57 ^ w51 ^ w49; - w65 = (n << 1) | (n >>> 31); - t = (w65 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 66 - n = w63 ^ w58 ^ w52 ^ w50; - w66 = (n << 1) | (n >>> 31); - t = (w66 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 67 - n = w64 ^ w59 ^ w53 ^ w51; - w67 = (n << 1) | (n >>> 31); - t = (w67 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 68 - n = w65 ^ w60 ^ w54 ^ w52; - w68 = (n << 1) | (n >>> 31); - t = (w68 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 69 - n = w66 ^ w61 ^ w55 ^ w53; - w69 = (n << 1) | (n >>> 31); - t = (w69 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 70 - n = w67 ^ w62 ^ w56 ^ w54; - w70 = (n << 1) | (n >>> 31); - t = (w70 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 71 - n = w68 ^ w63 ^ w57 ^ w55; - w71 = (n << 1) | (n >>> 31); - t = (w71 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 72 - n = w69 ^ w64 ^ w58 ^ w56; - w72 = (n << 1) | (n >>> 31); - t = (w72 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 73 - n = w70 ^ w65 ^ w59 ^ w57; - w73 = (n << 1) | (n >>> 31); - t = (w73 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 74 - n = w71 ^ w66 ^ w60 ^ w58; - w74 = (n << 1) | (n >>> 31); - t = (w74 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 75 - n = w72 ^ w67 ^ w61 ^ w59; - w75 = (n << 1) | (n >>> 31); - t = (w75 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 76 - n = w73 ^ w68 ^ w62 ^ w60; - w76 = (n << 1) | (n >>> 31); - t = (w76 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 77 - n = w74 ^ w69 ^ w63 ^ w61; - w77 = (n << 1) | (n >>> 31); - t = (w77 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 78 - n = w75 ^ w70 ^ w64 ^ w62; - w78 = (n << 1) | (n >>> 31); - t = (w78 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 79 - n = w76 ^ w71 ^ w65 ^ w63; - w79 = (n << 1) | (n >>> 31); - t = (w79 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - H0 = ( H0 + a )|0; - H1 = ( H1 + b )|0; - H2 = ( H2 + c )|0; - H3 = ( H3 + d )|0; - H4 = ( H4 + e )|0; - - } - - function _core_heap ( offset ) { - offset = offset|0; - - _core( - HEAP[offset|0]<<24 | HEAP[offset|1]<<16 | HEAP[offset|2]<<8 | HEAP[offset|3], - HEAP[offset|4]<<24 | HEAP[offset|5]<<16 | HEAP[offset|6]<<8 | HEAP[offset|7], - HEAP[offset|8]<<24 | HEAP[offset|9]<<16 | HEAP[offset|10]<<8 | HEAP[offset|11], - HEAP[offset|12]<<24 | HEAP[offset|13]<<16 | HEAP[offset|14]<<8 | HEAP[offset|15], - HEAP[offset|16]<<24 | HEAP[offset|17]<<16 | HEAP[offset|18]<<8 | HEAP[offset|19], - HEAP[offset|20]<<24 | HEAP[offset|21]<<16 | HEAP[offset|22]<<8 | HEAP[offset|23], - HEAP[offset|24]<<24 | HEAP[offset|25]<<16 | HEAP[offset|26]<<8 | HEAP[offset|27], - HEAP[offset|28]<<24 | HEAP[offset|29]<<16 | HEAP[offset|30]<<8 | HEAP[offset|31], - HEAP[offset|32]<<24 | HEAP[offset|33]<<16 | HEAP[offset|34]<<8 | HEAP[offset|35], - HEAP[offset|36]<<24 | HEAP[offset|37]<<16 | HEAP[offset|38]<<8 | HEAP[offset|39], - HEAP[offset|40]<<24 | HEAP[offset|41]<<16 | HEAP[offset|42]<<8 | HEAP[offset|43], - HEAP[offset|44]<<24 | HEAP[offset|45]<<16 | HEAP[offset|46]<<8 | HEAP[offset|47], - HEAP[offset|48]<<24 | HEAP[offset|49]<<16 | HEAP[offset|50]<<8 | HEAP[offset|51], - HEAP[offset|52]<<24 | HEAP[offset|53]<<16 | HEAP[offset|54]<<8 | HEAP[offset|55], - HEAP[offset|56]<<24 | HEAP[offset|57]<<16 | HEAP[offset|58]<<8 | HEAP[offset|59], - HEAP[offset|60]<<24 | HEAP[offset|61]<<16 | HEAP[offset|62]<<8 | HEAP[offset|63] - ); - } - - // offset — multiple of 32 - function _state_to_heap ( output ) { - output = output|0; - - HEAP[output|0] = H0>>>24; - HEAP[output|1] = H0>>>16&255; - HEAP[output|2] = H0>>>8&255; - HEAP[output|3] = H0&255; - HEAP[output|4] = H1>>>24; - HEAP[output|5] = H1>>>16&255; - HEAP[output|6] = H1>>>8&255; - HEAP[output|7] = H1&255; - HEAP[output|8] = H2>>>24; - HEAP[output|9] = H2>>>16&255; - HEAP[output|10] = H2>>>8&255; - HEAP[output|11] = H2&255; - HEAP[output|12] = H3>>>24; - HEAP[output|13] = H3>>>16&255; - HEAP[output|14] = H3>>>8&255; - HEAP[output|15] = H3&255; - HEAP[output|16] = H4>>>24; - HEAP[output|17] = H4>>>16&255; - HEAP[output|18] = H4>>>8&255; - HEAP[output|19] = H4&255; - } - - function reset () { - H0 = 0x67452301; - H1 = 0xefcdab89; - H2 = 0x98badcfe; - H3 = 0x10325476; - H4 = 0xc3d2e1f0; - TOTAL0 = TOTAL1 = 0; - } - - function init ( h0, h1, h2, h3, h4, total0, total1 ) { - h0 = h0|0; - h1 = h1|0; - h2 = h2|0; - h3 = h3|0; - h4 = h4|0; - total0 = total0|0; - total1 = total1|0; - - H0 = h0; - H1 = h1; - H2 = h2; - H3 = h3; - H4 = h4; - TOTAL0 = total0; - TOTAL1 = total1; - } - - // offset — multiple of 64 - function process ( offset, length ) { - offset = offset|0; - length = length|0; - - var hashed = 0; - - if ( offset & 63 ) - return -1; - - while ( (length|0) >= 64 ) { - _core_heap(offset); - - offset = ( offset + 64 )|0; - length = ( length - 64 )|0; - - hashed = ( hashed + 64 )|0; - } - - TOTAL0 = ( TOTAL0 + hashed )|0; - if ( TOTAL0>>>0 < hashed>>>0 ) TOTAL1 = ( TOTAL1 + 1 )|0; - - return hashed|0; - } - - // offset — multiple of 64 - // output — multiple of 32 - function finish ( offset, length, output ) { - offset = offset|0; - length = length|0; - output = output|0; - - var hashed = 0, - i = 0; - - if ( offset & 63 ) - return -1; - - if ( ~output ) - if ( output & 31 ) - return -1; - - if ( (length|0) >= 64 ) { - hashed = process( offset, length )|0; - if ( (hashed|0) == -1 ) - return -1; - - offset = ( offset + hashed )|0; - length = ( length - hashed )|0; - } - - hashed = ( hashed + length )|0; - TOTAL0 = ( TOTAL0 + length )|0; - if ( TOTAL0>>>0 < length>>>0 ) TOTAL1 = (TOTAL1 + 1)|0; - - HEAP[offset|length] = 0x80; - - if ( (length|0) >= 56 ) { - for ( i = (length+1)|0; (i|0) < 64; i = (i+1)|0 ) - HEAP[offset|i] = 0x00; - _core_heap(offset); - - length = 0; - - HEAP[offset|0] = 0; - } - - for ( i = (length+1)|0; (i|0) < 59; i = (i+1)|0 ) - HEAP[offset|i] = 0; - - HEAP[offset|56] = TOTAL1>>>21&255; - HEAP[offset|57] = TOTAL1>>>13&255; - HEAP[offset|58] = TOTAL1>>>5&255; - HEAP[offset|59] = TOTAL1<<3&255 | TOTAL0>>>29; - HEAP[offset|60] = TOTAL0>>>21&255; - HEAP[offset|61] = TOTAL0>>>13&255; - HEAP[offset|62] = TOTAL0>>>5&255; - HEAP[offset|63] = TOTAL0<<3&255; - _core_heap(offset); - - if ( ~output ) - _state_to_heap(output); - - return hashed|0; - } - - function hmac_reset () { - H0 = I0; - H1 = I1; - H2 = I2; - H3 = I3; - H4 = I4; - TOTAL0 = 64; - TOTAL1 = 0; - } - - function _hmac_opad () { - H0 = O0; - H1 = O1; - H2 = O2; - H3 = O3; - H4 = O4; - TOTAL0 = 64; - TOTAL1 = 0; - } - - function hmac_init ( p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15 ) { - p0 = p0|0; - p1 = p1|0; - p2 = p2|0; - p3 = p3|0; - p4 = p4|0; - p5 = p5|0; - p6 = p6|0; - p7 = p7|0; - p8 = p8|0; - p9 = p9|0; - p10 = p10|0; - p11 = p11|0; - p12 = p12|0; - p13 = p13|0; - p14 = p14|0; - p15 = p15|0; - - // opad - reset(); - _core( - p0 ^ 0x5c5c5c5c, - p1 ^ 0x5c5c5c5c, - p2 ^ 0x5c5c5c5c, - p3 ^ 0x5c5c5c5c, - p4 ^ 0x5c5c5c5c, - p5 ^ 0x5c5c5c5c, - p6 ^ 0x5c5c5c5c, - p7 ^ 0x5c5c5c5c, - p8 ^ 0x5c5c5c5c, - p9 ^ 0x5c5c5c5c, - p10 ^ 0x5c5c5c5c, - p11 ^ 0x5c5c5c5c, - p12 ^ 0x5c5c5c5c, - p13 ^ 0x5c5c5c5c, - p14 ^ 0x5c5c5c5c, - p15 ^ 0x5c5c5c5c - ); - O0 = H0; - O1 = H1; - O2 = H2; - O3 = H3; - O4 = H4; - - // ipad - reset(); - _core( - p0 ^ 0x36363636, - p1 ^ 0x36363636, - p2 ^ 0x36363636, - p3 ^ 0x36363636, - p4 ^ 0x36363636, - p5 ^ 0x36363636, - p6 ^ 0x36363636, - p7 ^ 0x36363636, - p8 ^ 0x36363636, - p9 ^ 0x36363636, - p10 ^ 0x36363636, - p11 ^ 0x36363636, - p12 ^ 0x36363636, - p13 ^ 0x36363636, - p14 ^ 0x36363636, - p15 ^ 0x36363636 - ); - I0 = H0; - I1 = H1; - I2 = H2; - I3 = H3; - I4 = H4; - - TOTAL0 = 64; - TOTAL1 = 0; - } - - // offset — multiple of 64 - // output — multiple of 32 - function hmac_finish ( offset, length, output ) { - offset = offset|0; - length = length|0; - output = output|0; - - var t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, hashed = 0; - - if ( offset & 63 ) - return -1; - - if ( ~output ) - if ( output & 31 ) - return -1; - - hashed = finish( offset, length, -1 )|0; - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; - - _hmac_opad(); - _core( t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672 ); - - if ( ~output ) - _state_to_heap(output); - - return hashed|0; - } - - // salt is assumed to be already processed - // offset — multiple of 64 - // output — multiple of 32 - function pbkdf2_generate_block ( offset, length, block, count, output ) { - offset = offset|0; - length = length|0; - block = block|0; - count = count|0; - output = output|0; - - var h0 = 0, h1 = 0, h2 = 0, h3 = 0, h4 = 0, - t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0; - - if ( offset & 63 ) - return -1; - - if ( ~output ) - if ( output & 31 ) - return -1; - - // pad block number into heap - // FIXME probable OOB write - HEAP[(offset+length)|0] = block>>>24; - HEAP[(offset+length+1)|0] = block>>>16&255; - HEAP[(offset+length+2)|0] = block>>>8&255; - HEAP[(offset+length+3)|0] = block&255; - - // finish first iteration - hmac_finish( offset, (length+4)|0, -1 )|0; - h0 = t0 = H0, h1 = t1 = H1, h2 = t2 = H2, h3 = t3 = H3, h4 = t4 = H4; - count = (count-1)|0; - - // perform the rest iterations - while ( (count|0) > 0 ) { - hmac_reset(); - _core( t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672 ); - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; - - _hmac_opad(); - _core( t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672 ); - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; - - h0 = h0 ^ H0; - h1 = h1 ^ H1; - h2 = h2 ^ H2; - h3 = h3 ^ H3; - h4 = h4 ^ H4; - - count = (count-1)|0; - } - - H0 = h0; - H1 = h1; - H2 = h2; - H3 = h3; - H4 = h4; - - if ( ~output ) - _state_to_heap(output); - - return 0; - } - - return { - // SHA1 - reset: reset, - init: init, - process: process, - finish: finish, - - // HMAC-SHA1 - hmac_reset: hmac_reset, - hmac_init: hmac_init, - hmac_finish: hmac_finish, - - // PBKDF2-HMAC-SHA1 - pbkdf2_generate_block: pbkdf2_generate_block - } -}; - -class Hash { - constructor() { - this.pos = 0; - this.len = 0; - } - reset() { - const { asm } = this.acquire_asm(); - this.result = null; - this.pos = 0; - this.len = 0; - asm.reset(); - return this; - } - process(data) { - if (this.result !== null) - throw new IllegalStateError('state must be reset before processing new data'); - const { asm, heap } = this.acquire_asm(); - let hpos = this.pos; - let hlen = this.len; - let dpos = 0; - let dlen = data.length; - let wlen = 0; - while (dlen > 0) { - wlen = _heap_write(heap, hpos + hlen, data, dpos, dlen); - hlen += wlen; - dpos += wlen; - dlen -= wlen; - wlen = asm.process(hpos, hlen); - hpos += wlen; - hlen -= wlen; - if (!hlen) - hpos = 0; - } - this.pos = hpos; - this.len = hlen; - return this; - } - finish() { - if (this.result !== null) - throw new IllegalStateError('state must be reset before processing new data'); - const { asm, heap } = this.acquire_asm(); - asm.finish(this.pos, this.len, 0); - this.result = new Uint8Array(this.HASH_SIZE); - this.result.set(heap.subarray(0, this.HASH_SIZE)); - this.pos = 0; - this.len = 0; - this.release_asm(); - return this; - } -} - -const _sha1_block_size = 64; -const _sha1_hash_size = 20; -const heap_pool$1 = []; -const asm_pool$1 = []; -class Sha1 extends Hash { - constructor() { - super(); - this.NAME = 'sha1'; - this.BLOCK_SIZE = _sha1_block_size; - this.HASH_SIZE = _sha1_hash_size; - this.acquire_asm(); - } - acquire_asm() { - if (this.heap === undefined || this.asm === undefined) { - this.heap = heap_pool$1.pop() || _heap_init(); - this.asm = asm_pool$1.pop() || sha1_asm({ Uint8Array: Uint8Array }, null, this.heap.buffer); - this.reset(); - } - return { heap: this.heap, asm: this.asm }; - } - release_asm() { - if (this.heap !== undefined && this.asm !== undefined) { - heap_pool$1.push(this.heap); - asm_pool$1.push(this.asm); - } - this.heap = undefined; - this.asm = undefined; - } - static bytes(data) { - return new Sha1().process(data).finish().result; - } -} -Sha1.NAME = 'sha1'; -Sha1.heap_pool = []; -Sha1.asm_pool = []; -Sha1.asm_function = sha1_asm; - -var sha256_asm = function ( stdlib, foreign, buffer ) { - "use asm"; - - // SHA256 state - var H0 = 0, H1 = 0, H2 = 0, H3 = 0, H4 = 0, H5 = 0, H6 = 0, H7 = 0, - TOTAL0 = 0, TOTAL1 = 0; - - // HMAC state - var I0 = 0, I1 = 0, I2 = 0, I3 = 0, I4 = 0, I5 = 0, I6 = 0, I7 = 0, - O0 = 0, O1 = 0, O2 = 0, O3 = 0, O4 = 0, O5 = 0, O6 = 0, O7 = 0; - - // I/O buffer - var HEAP = new stdlib.Uint8Array(buffer); - - function _core ( w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15 ) { - w0 = w0|0; - w1 = w1|0; - w2 = w2|0; - w3 = w3|0; - w4 = w4|0; - w5 = w5|0; - w6 = w6|0; - w7 = w7|0; - w8 = w8|0; - w9 = w9|0; - w10 = w10|0; - w11 = w11|0; - w12 = w12|0; - w13 = w13|0; - w14 = w14|0; - w15 = w15|0; - - var a = 0, b = 0, c = 0, d = 0, e = 0, f = 0, g = 0, h = 0; - - a = H0; - b = H1; - c = H2; - d = H3; - e = H4; - f = H5; - g = H6; - h = H7; - - // 0 - h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x428a2f98 )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 1 - g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x71374491 )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 2 - f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0xb5c0fbcf )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 3 - e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0xe9b5dba5 )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 4 - d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x3956c25b )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 5 - c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x59f111f1 )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 6 - b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x923f82a4 )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 7 - a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0xab1c5ed5 )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - // 8 - h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0xd807aa98 )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 9 - g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x12835b01 )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 10 - f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x243185be )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 11 - e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x550c7dc3 )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 12 - d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x72be5d74 )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 13 - c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x80deb1fe )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 14 - b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x9bdc06a7 )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 15 - a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0xc19bf174 )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - // 16 - w0 = ( ( w1>>>7 ^ w1>>>18 ^ w1>>>3 ^ w1<<25 ^ w1<<14 ) + ( w14>>>17 ^ w14>>>19 ^ w14>>>10 ^ w14<<15 ^ w14<<13 ) + w0 + w9 )|0; - h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0xe49b69c1 )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 17 - w1 = ( ( w2>>>7 ^ w2>>>18 ^ w2>>>3 ^ w2<<25 ^ w2<<14 ) + ( w15>>>17 ^ w15>>>19 ^ w15>>>10 ^ w15<<15 ^ w15<<13 ) + w1 + w10 )|0; - g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0xefbe4786 )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 18 - w2 = ( ( w3>>>7 ^ w3>>>18 ^ w3>>>3 ^ w3<<25 ^ w3<<14 ) + ( w0>>>17 ^ w0>>>19 ^ w0>>>10 ^ w0<<15 ^ w0<<13 ) + w2 + w11 )|0; - f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x0fc19dc6 )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 19 - w3 = ( ( w4>>>7 ^ w4>>>18 ^ w4>>>3 ^ w4<<25 ^ w4<<14 ) + ( w1>>>17 ^ w1>>>19 ^ w1>>>10 ^ w1<<15 ^ w1<<13 ) + w3 + w12 )|0; - e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x240ca1cc )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 20 - w4 = ( ( w5>>>7 ^ w5>>>18 ^ w5>>>3 ^ w5<<25 ^ w5<<14 ) + ( w2>>>17 ^ w2>>>19 ^ w2>>>10 ^ w2<<15 ^ w2<<13 ) + w4 + w13 )|0; - d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x2de92c6f )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 21 - w5 = ( ( w6>>>7 ^ w6>>>18 ^ w6>>>3 ^ w6<<25 ^ w6<<14 ) + ( w3>>>17 ^ w3>>>19 ^ w3>>>10 ^ w3<<15 ^ w3<<13 ) + w5 + w14 )|0; - c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x4a7484aa )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 22 - w6 = ( ( w7>>>7 ^ w7>>>18 ^ w7>>>3 ^ w7<<25 ^ w7<<14 ) + ( w4>>>17 ^ w4>>>19 ^ w4>>>10 ^ w4<<15 ^ w4<<13 ) + w6 + w15 )|0; - b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x5cb0a9dc )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 23 - w7 = ( ( w8>>>7 ^ w8>>>18 ^ w8>>>3 ^ w8<<25 ^ w8<<14 ) + ( w5>>>17 ^ w5>>>19 ^ w5>>>10 ^ w5<<15 ^ w5<<13 ) + w7 + w0 )|0; - a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x76f988da )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - // 24 - w8 = ( ( w9>>>7 ^ w9>>>18 ^ w9>>>3 ^ w9<<25 ^ w9<<14 ) + ( w6>>>17 ^ w6>>>19 ^ w6>>>10 ^ w6<<15 ^ w6<<13 ) + w8 + w1 )|0; - h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x983e5152 )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 25 - w9 = ( ( w10>>>7 ^ w10>>>18 ^ w10>>>3 ^ w10<<25 ^ w10<<14 ) + ( w7>>>17 ^ w7>>>19 ^ w7>>>10 ^ w7<<15 ^ w7<<13 ) + w9 + w2 )|0; - g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0xa831c66d )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 26 - w10 = ( ( w11>>>7 ^ w11>>>18 ^ w11>>>3 ^ w11<<25 ^ w11<<14 ) + ( w8>>>17 ^ w8>>>19 ^ w8>>>10 ^ w8<<15 ^ w8<<13 ) + w10 + w3 )|0; - f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0xb00327c8 )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 27 - w11 = ( ( w12>>>7 ^ w12>>>18 ^ w12>>>3 ^ w12<<25 ^ w12<<14 ) + ( w9>>>17 ^ w9>>>19 ^ w9>>>10 ^ w9<<15 ^ w9<<13 ) + w11 + w4 )|0; - e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0xbf597fc7 )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 28 - w12 = ( ( w13>>>7 ^ w13>>>18 ^ w13>>>3 ^ w13<<25 ^ w13<<14 ) + ( w10>>>17 ^ w10>>>19 ^ w10>>>10 ^ w10<<15 ^ w10<<13 ) + w12 + w5 )|0; - d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0xc6e00bf3 )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 29 - w13 = ( ( w14>>>7 ^ w14>>>18 ^ w14>>>3 ^ w14<<25 ^ w14<<14 ) + ( w11>>>17 ^ w11>>>19 ^ w11>>>10 ^ w11<<15 ^ w11<<13 ) + w13 + w6 )|0; - c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0xd5a79147 )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 30 - w14 = ( ( w15>>>7 ^ w15>>>18 ^ w15>>>3 ^ w15<<25 ^ w15<<14 ) + ( w12>>>17 ^ w12>>>19 ^ w12>>>10 ^ w12<<15 ^ w12<<13 ) + w14 + w7 )|0; - b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x06ca6351 )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 31 - w15 = ( ( w0>>>7 ^ w0>>>18 ^ w0>>>3 ^ w0<<25 ^ w0<<14 ) + ( w13>>>17 ^ w13>>>19 ^ w13>>>10 ^ w13<<15 ^ w13<<13 ) + w15 + w8 )|0; - a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x14292967 )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - // 32 - w0 = ( ( w1>>>7 ^ w1>>>18 ^ w1>>>3 ^ w1<<25 ^ w1<<14 ) + ( w14>>>17 ^ w14>>>19 ^ w14>>>10 ^ w14<<15 ^ w14<<13 ) + w0 + w9 )|0; - h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x27b70a85 )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 33 - w1 = ( ( w2>>>7 ^ w2>>>18 ^ w2>>>3 ^ w2<<25 ^ w2<<14 ) + ( w15>>>17 ^ w15>>>19 ^ w15>>>10 ^ w15<<15 ^ w15<<13 ) + w1 + w10 )|0; - g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x2e1b2138 )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 34 - w2 = ( ( w3>>>7 ^ w3>>>18 ^ w3>>>3 ^ w3<<25 ^ w3<<14 ) + ( w0>>>17 ^ w0>>>19 ^ w0>>>10 ^ w0<<15 ^ w0<<13 ) + w2 + w11 )|0; - f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x4d2c6dfc )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 35 - w3 = ( ( w4>>>7 ^ w4>>>18 ^ w4>>>3 ^ w4<<25 ^ w4<<14 ) + ( w1>>>17 ^ w1>>>19 ^ w1>>>10 ^ w1<<15 ^ w1<<13 ) + w3 + w12 )|0; - e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x53380d13 )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 36 - w4 = ( ( w5>>>7 ^ w5>>>18 ^ w5>>>3 ^ w5<<25 ^ w5<<14 ) + ( w2>>>17 ^ w2>>>19 ^ w2>>>10 ^ w2<<15 ^ w2<<13 ) + w4 + w13 )|0; - d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x650a7354 )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 37 - w5 = ( ( w6>>>7 ^ w6>>>18 ^ w6>>>3 ^ w6<<25 ^ w6<<14 ) + ( w3>>>17 ^ w3>>>19 ^ w3>>>10 ^ w3<<15 ^ w3<<13 ) + w5 + w14 )|0; - c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x766a0abb )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 38 - w6 = ( ( w7>>>7 ^ w7>>>18 ^ w7>>>3 ^ w7<<25 ^ w7<<14 ) + ( w4>>>17 ^ w4>>>19 ^ w4>>>10 ^ w4<<15 ^ w4<<13 ) + w6 + w15 )|0; - b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x81c2c92e )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 39 - w7 = ( ( w8>>>7 ^ w8>>>18 ^ w8>>>3 ^ w8<<25 ^ w8<<14 ) + ( w5>>>17 ^ w5>>>19 ^ w5>>>10 ^ w5<<15 ^ w5<<13 ) + w7 + w0 )|0; - a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x92722c85 )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - // 40 - w8 = ( ( w9>>>7 ^ w9>>>18 ^ w9>>>3 ^ w9<<25 ^ w9<<14 ) + ( w6>>>17 ^ w6>>>19 ^ w6>>>10 ^ w6<<15 ^ w6<<13 ) + w8 + w1 )|0; - h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0xa2bfe8a1 )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 41 - w9 = ( ( w10>>>7 ^ w10>>>18 ^ w10>>>3 ^ w10<<25 ^ w10<<14 ) + ( w7>>>17 ^ w7>>>19 ^ w7>>>10 ^ w7<<15 ^ w7<<13 ) + w9 + w2 )|0; - g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0xa81a664b )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 42 - w10 = ( ( w11>>>7 ^ w11>>>18 ^ w11>>>3 ^ w11<<25 ^ w11<<14 ) + ( w8>>>17 ^ w8>>>19 ^ w8>>>10 ^ w8<<15 ^ w8<<13 ) + w10 + w3 )|0; - f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0xc24b8b70 )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 43 - w11 = ( ( w12>>>7 ^ w12>>>18 ^ w12>>>3 ^ w12<<25 ^ w12<<14 ) + ( w9>>>17 ^ w9>>>19 ^ w9>>>10 ^ w9<<15 ^ w9<<13 ) + w11 + w4 )|0; - e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0xc76c51a3 )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 44 - w12 = ( ( w13>>>7 ^ w13>>>18 ^ w13>>>3 ^ w13<<25 ^ w13<<14 ) + ( w10>>>17 ^ w10>>>19 ^ w10>>>10 ^ w10<<15 ^ w10<<13 ) + w12 + w5 )|0; - d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0xd192e819 )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 45 - w13 = ( ( w14>>>7 ^ w14>>>18 ^ w14>>>3 ^ w14<<25 ^ w14<<14 ) + ( w11>>>17 ^ w11>>>19 ^ w11>>>10 ^ w11<<15 ^ w11<<13 ) + w13 + w6 )|0; - c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0xd6990624 )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 46 - w14 = ( ( w15>>>7 ^ w15>>>18 ^ w15>>>3 ^ w15<<25 ^ w15<<14 ) + ( w12>>>17 ^ w12>>>19 ^ w12>>>10 ^ w12<<15 ^ w12<<13 ) + w14 + w7 )|0; - b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0xf40e3585 )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 47 - w15 = ( ( w0>>>7 ^ w0>>>18 ^ w0>>>3 ^ w0<<25 ^ w0<<14 ) + ( w13>>>17 ^ w13>>>19 ^ w13>>>10 ^ w13<<15 ^ w13<<13 ) + w15 + w8 )|0; - a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x106aa070 )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - // 48 - w0 = ( ( w1>>>7 ^ w1>>>18 ^ w1>>>3 ^ w1<<25 ^ w1<<14 ) + ( w14>>>17 ^ w14>>>19 ^ w14>>>10 ^ w14<<15 ^ w14<<13 ) + w0 + w9 )|0; - h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x19a4c116 )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 49 - w1 = ( ( w2>>>7 ^ w2>>>18 ^ w2>>>3 ^ w2<<25 ^ w2<<14 ) + ( w15>>>17 ^ w15>>>19 ^ w15>>>10 ^ w15<<15 ^ w15<<13 ) + w1 + w10 )|0; - g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x1e376c08 )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 50 - w2 = ( ( w3>>>7 ^ w3>>>18 ^ w3>>>3 ^ w3<<25 ^ w3<<14 ) + ( w0>>>17 ^ w0>>>19 ^ w0>>>10 ^ w0<<15 ^ w0<<13 ) + w2 + w11 )|0; - f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x2748774c )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 51 - w3 = ( ( w4>>>7 ^ w4>>>18 ^ w4>>>3 ^ w4<<25 ^ w4<<14 ) + ( w1>>>17 ^ w1>>>19 ^ w1>>>10 ^ w1<<15 ^ w1<<13 ) + w3 + w12 )|0; - e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x34b0bcb5 )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 52 - w4 = ( ( w5>>>7 ^ w5>>>18 ^ w5>>>3 ^ w5<<25 ^ w5<<14 ) + ( w2>>>17 ^ w2>>>19 ^ w2>>>10 ^ w2<<15 ^ w2<<13 ) + w4 + w13 )|0; - d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x391c0cb3 )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 53 - w5 = ( ( w6>>>7 ^ w6>>>18 ^ w6>>>3 ^ w6<<25 ^ w6<<14 ) + ( w3>>>17 ^ w3>>>19 ^ w3>>>10 ^ w3<<15 ^ w3<<13 ) + w5 + w14 )|0; - c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x4ed8aa4a )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 54 - w6 = ( ( w7>>>7 ^ w7>>>18 ^ w7>>>3 ^ w7<<25 ^ w7<<14 ) + ( w4>>>17 ^ w4>>>19 ^ w4>>>10 ^ w4<<15 ^ w4<<13 ) + w6 + w15 )|0; - b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x5b9cca4f )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 55 - w7 = ( ( w8>>>7 ^ w8>>>18 ^ w8>>>3 ^ w8<<25 ^ w8<<14 ) + ( w5>>>17 ^ w5>>>19 ^ w5>>>10 ^ w5<<15 ^ w5<<13 ) + w7 + w0 )|0; - a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x682e6ff3 )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - // 56 - w8 = ( ( w9>>>7 ^ w9>>>18 ^ w9>>>3 ^ w9<<25 ^ w9<<14 ) + ( w6>>>17 ^ w6>>>19 ^ w6>>>10 ^ w6<<15 ^ w6<<13 ) + w8 + w1 )|0; - h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x748f82ee )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 57 - w9 = ( ( w10>>>7 ^ w10>>>18 ^ w10>>>3 ^ w10<<25 ^ w10<<14 ) + ( w7>>>17 ^ w7>>>19 ^ w7>>>10 ^ w7<<15 ^ w7<<13 ) + w9 + w2 )|0; - g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x78a5636f )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 58 - w10 = ( ( w11>>>7 ^ w11>>>18 ^ w11>>>3 ^ w11<<25 ^ w11<<14 ) + ( w8>>>17 ^ w8>>>19 ^ w8>>>10 ^ w8<<15 ^ w8<<13 ) + w10 + w3 )|0; - f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x84c87814 )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 59 - w11 = ( ( w12>>>7 ^ w12>>>18 ^ w12>>>3 ^ w12<<25 ^ w12<<14 ) + ( w9>>>17 ^ w9>>>19 ^ w9>>>10 ^ w9<<15 ^ w9<<13 ) + w11 + w4 )|0; - e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x8cc70208 )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 60 - w12 = ( ( w13>>>7 ^ w13>>>18 ^ w13>>>3 ^ w13<<25 ^ w13<<14 ) + ( w10>>>17 ^ w10>>>19 ^ w10>>>10 ^ w10<<15 ^ w10<<13 ) + w12 + w5 )|0; - d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x90befffa )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 61 - w13 = ( ( w14>>>7 ^ w14>>>18 ^ w14>>>3 ^ w14<<25 ^ w14<<14 ) + ( w11>>>17 ^ w11>>>19 ^ w11>>>10 ^ w11<<15 ^ w11<<13 ) + w13 + w6 )|0; - c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0xa4506ceb )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 62 - w14 = ( ( w15>>>7 ^ w15>>>18 ^ w15>>>3 ^ w15<<25 ^ w15<<14 ) + ( w12>>>17 ^ w12>>>19 ^ w12>>>10 ^ w12<<15 ^ w12<<13 ) + w14 + w7 )|0; - b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0xbef9a3f7 )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 63 - w15 = ( ( w0>>>7 ^ w0>>>18 ^ w0>>>3 ^ w0<<25 ^ w0<<14 ) + ( w13>>>17 ^ w13>>>19 ^ w13>>>10 ^ w13<<15 ^ w13<<13 ) + w15 + w8 )|0; - a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0xc67178f2 )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - H0 = ( H0 + a )|0; - H1 = ( H1 + b )|0; - H2 = ( H2 + c )|0; - H3 = ( H3 + d )|0; - H4 = ( H4 + e )|0; - H5 = ( H5 + f )|0; - H6 = ( H6 + g )|0; - H7 = ( H7 + h )|0; - } - - function _core_heap ( offset ) { - offset = offset|0; - - _core( - HEAP[offset|0]<<24 | HEAP[offset|1]<<16 | HEAP[offset|2]<<8 | HEAP[offset|3], - HEAP[offset|4]<<24 | HEAP[offset|5]<<16 | HEAP[offset|6]<<8 | HEAP[offset|7], - HEAP[offset|8]<<24 | HEAP[offset|9]<<16 | HEAP[offset|10]<<8 | HEAP[offset|11], - HEAP[offset|12]<<24 | HEAP[offset|13]<<16 | HEAP[offset|14]<<8 | HEAP[offset|15], - HEAP[offset|16]<<24 | HEAP[offset|17]<<16 | HEAP[offset|18]<<8 | HEAP[offset|19], - HEAP[offset|20]<<24 | HEAP[offset|21]<<16 | HEAP[offset|22]<<8 | HEAP[offset|23], - HEAP[offset|24]<<24 | HEAP[offset|25]<<16 | HEAP[offset|26]<<8 | HEAP[offset|27], - HEAP[offset|28]<<24 | HEAP[offset|29]<<16 | HEAP[offset|30]<<8 | HEAP[offset|31], - HEAP[offset|32]<<24 | HEAP[offset|33]<<16 | HEAP[offset|34]<<8 | HEAP[offset|35], - HEAP[offset|36]<<24 | HEAP[offset|37]<<16 | HEAP[offset|38]<<8 | HEAP[offset|39], - HEAP[offset|40]<<24 | HEAP[offset|41]<<16 | HEAP[offset|42]<<8 | HEAP[offset|43], - HEAP[offset|44]<<24 | HEAP[offset|45]<<16 | HEAP[offset|46]<<8 | HEAP[offset|47], - HEAP[offset|48]<<24 | HEAP[offset|49]<<16 | HEAP[offset|50]<<8 | HEAP[offset|51], - HEAP[offset|52]<<24 | HEAP[offset|53]<<16 | HEAP[offset|54]<<8 | HEAP[offset|55], - HEAP[offset|56]<<24 | HEAP[offset|57]<<16 | HEAP[offset|58]<<8 | HEAP[offset|59], - HEAP[offset|60]<<24 | HEAP[offset|61]<<16 | HEAP[offset|62]<<8 | HEAP[offset|63] - ); - } - - // offset — multiple of 32 - function _state_to_heap ( output ) { - output = output|0; - - HEAP[output|0] = H0>>>24; - HEAP[output|1] = H0>>>16&255; - HEAP[output|2] = H0>>>8&255; - HEAP[output|3] = H0&255; - HEAP[output|4] = H1>>>24; - HEAP[output|5] = H1>>>16&255; - HEAP[output|6] = H1>>>8&255; - HEAP[output|7] = H1&255; - HEAP[output|8] = H2>>>24; - HEAP[output|9] = H2>>>16&255; - HEAP[output|10] = H2>>>8&255; - HEAP[output|11] = H2&255; - HEAP[output|12] = H3>>>24; - HEAP[output|13] = H3>>>16&255; - HEAP[output|14] = H3>>>8&255; - HEAP[output|15] = H3&255; - HEAP[output|16] = H4>>>24; - HEAP[output|17] = H4>>>16&255; - HEAP[output|18] = H4>>>8&255; - HEAP[output|19] = H4&255; - HEAP[output|20] = H5>>>24; - HEAP[output|21] = H5>>>16&255; - HEAP[output|22] = H5>>>8&255; - HEAP[output|23] = H5&255; - HEAP[output|24] = H6>>>24; - HEAP[output|25] = H6>>>16&255; - HEAP[output|26] = H6>>>8&255; - HEAP[output|27] = H6&255; - HEAP[output|28] = H7>>>24; - HEAP[output|29] = H7>>>16&255; - HEAP[output|30] = H7>>>8&255; - HEAP[output|31] = H7&255; - } - - function reset () { - H0 = 0x6a09e667; - H1 = 0xbb67ae85; - H2 = 0x3c6ef372; - H3 = 0xa54ff53a; - H4 = 0x510e527f; - H5 = 0x9b05688c; - H6 = 0x1f83d9ab; - H7 = 0x5be0cd19; - TOTAL0 = TOTAL1 = 0; - } - - function init ( h0, h1, h2, h3, h4, h5, h6, h7, total0, total1 ) { - h0 = h0|0; - h1 = h1|0; - h2 = h2|0; - h3 = h3|0; - h4 = h4|0; - h5 = h5|0; - h6 = h6|0; - h7 = h7|0; - total0 = total0|0; - total1 = total1|0; - - H0 = h0; - H1 = h1; - H2 = h2; - H3 = h3; - H4 = h4; - H5 = h5; - H6 = h6; - H7 = h7; - TOTAL0 = total0; - TOTAL1 = total1; - } - - // offset — multiple of 64 - function process ( offset, length ) { - offset = offset|0; - length = length|0; - - var hashed = 0; - - if ( offset & 63 ) - return -1; - - while ( (length|0) >= 64 ) { - _core_heap(offset); - - offset = ( offset + 64 )|0; - length = ( length - 64 )|0; - - hashed = ( hashed + 64 )|0; - } - - TOTAL0 = ( TOTAL0 + hashed )|0; - if ( TOTAL0>>>0 < hashed>>>0 ) TOTAL1 = ( TOTAL1 + 1 )|0; - - return hashed|0; - } - - // offset — multiple of 64 - // output — multiple of 32 - function finish ( offset, length, output ) { - offset = offset|0; - length = length|0; - output = output|0; - - var hashed = 0, - i = 0; - - if ( offset & 63 ) - return -1; - - if ( ~output ) - if ( output & 31 ) - return -1; - - if ( (length|0) >= 64 ) { - hashed = process( offset, length )|0; - if ( (hashed|0) == -1 ) - return -1; - - offset = ( offset + hashed )|0; - length = ( length - hashed )|0; - } - - hashed = ( hashed + length )|0; - TOTAL0 = ( TOTAL0 + length )|0; - if ( TOTAL0>>>0 < length>>>0 ) TOTAL1 = ( TOTAL1 + 1 )|0; - - HEAP[offset|length] = 0x80; - - if ( (length|0) >= 56 ) { - for ( i = (length+1)|0; (i|0) < 64; i = (i+1)|0 ) - HEAP[offset|i] = 0x00; - - _core_heap(offset); - - length = 0; - - HEAP[offset|0] = 0; - } - - for ( i = (length+1)|0; (i|0) < 59; i = (i+1)|0 ) - HEAP[offset|i] = 0; - - HEAP[offset|56] = TOTAL1>>>21&255; - HEAP[offset|57] = TOTAL1>>>13&255; - HEAP[offset|58] = TOTAL1>>>5&255; - HEAP[offset|59] = TOTAL1<<3&255 | TOTAL0>>>29; - HEAP[offset|60] = TOTAL0>>>21&255; - HEAP[offset|61] = TOTAL0>>>13&255; - HEAP[offset|62] = TOTAL0>>>5&255; - HEAP[offset|63] = TOTAL0<<3&255; - _core_heap(offset); - - if ( ~output ) - _state_to_heap(output); - - return hashed|0; - } - - function hmac_reset () { - H0 = I0; - H1 = I1; - H2 = I2; - H3 = I3; - H4 = I4; - H5 = I5; - H6 = I6; - H7 = I7; - TOTAL0 = 64; - TOTAL1 = 0; - } - - function _hmac_opad () { - H0 = O0; - H1 = O1; - H2 = O2; - H3 = O3; - H4 = O4; - H5 = O5; - H6 = O6; - H7 = O7; - TOTAL0 = 64; - TOTAL1 = 0; - } - - function hmac_init ( p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15 ) { - p0 = p0|0; - p1 = p1|0; - p2 = p2|0; - p3 = p3|0; - p4 = p4|0; - p5 = p5|0; - p6 = p6|0; - p7 = p7|0; - p8 = p8|0; - p9 = p9|0; - p10 = p10|0; - p11 = p11|0; - p12 = p12|0; - p13 = p13|0; - p14 = p14|0; - p15 = p15|0; - - // opad - reset(); - _core( - p0 ^ 0x5c5c5c5c, - p1 ^ 0x5c5c5c5c, - p2 ^ 0x5c5c5c5c, - p3 ^ 0x5c5c5c5c, - p4 ^ 0x5c5c5c5c, - p5 ^ 0x5c5c5c5c, - p6 ^ 0x5c5c5c5c, - p7 ^ 0x5c5c5c5c, - p8 ^ 0x5c5c5c5c, - p9 ^ 0x5c5c5c5c, - p10 ^ 0x5c5c5c5c, - p11 ^ 0x5c5c5c5c, - p12 ^ 0x5c5c5c5c, - p13 ^ 0x5c5c5c5c, - p14 ^ 0x5c5c5c5c, - p15 ^ 0x5c5c5c5c - ); - O0 = H0; - O1 = H1; - O2 = H2; - O3 = H3; - O4 = H4; - O5 = H5; - O6 = H6; - O7 = H7; - - // ipad - reset(); - _core( - p0 ^ 0x36363636, - p1 ^ 0x36363636, - p2 ^ 0x36363636, - p3 ^ 0x36363636, - p4 ^ 0x36363636, - p5 ^ 0x36363636, - p6 ^ 0x36363636, - p7 ^ 0x36363636, - p8 ^ 0x36363636, - p9 ^ 0x36363636, - p10 ^ 0x36363636, - p11 ^ 0x36363636, - p12 ^ 0x36363636, - p13 ^ 0x36363636, - p14 ^ 0x36363636, - p15 ^ 0x36363636 - ); - I0 = H0; - I1 = H1; - I2 = H2; - I3 = H3; - I4 = H4; - I5 = H5; - I6 = H6; - I7 = H7; - - TOTAL0 = 64; - TOTAL1 = 0; - } - - // offset — multiple of 64 - // output — multiple of 32 - function hmac_finish ( offset, length, output ) { - offset = offset|0; - length = length|0; - output = output|0; - - var t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0, - hashed = 0; - - if ( offset & 63 ) - return -1; - - if ( ~output ) - if ( output & 31 ) - return -1; - - hashed = finish( offset, length, -1 )|0; - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; - - _hmac_opad(); - _core( t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768 ); - - if ( ~output ) - _state_to_heap(output); - - return hashed|0; - } - - // salt is assumed to be already processed - // offset — multiple of 64 - // output — multiple of 32 - function pbkdf2_generate_block ( offset, length, block, count, output ) { - offset = offset|0; - length = length|0; - block = block|0; - count = count|0; - output = output|0; - - var h0 = 0, h1 = 0, h2 = 0, h3 = 0, h4 = 0, h5 = 0, h6 = 0, h7 = 0, - t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0; - - if ( offset & 63 ) - return -1; - - if ( ~output ) - if ( output & 31 ) - return -1; - - // pad block number into heap - // FIXME probable OOB write - HEAP[(offset+length)|0] = block>>>24; - HEAP[(offset+length+1)|0] = block>>>16&255; - HEAP[(offset+length+2)|0] = block>>>8&255; - HEAP[(offset+length+3)|0] = block&255; - - // finish first iteration - hmac_finish( offset, (length+4)|0, -1 )|0; - h0 = t0 = H0, h1 = t1 = H1, h2 = t2 = H2, h3 = t3 = H3, h4 = t4 = H4, h5 = t5 = H5, h6 = t6 = H6, h7 = t7 = H7; - count = (count-1)|0; - - // perform the rest iterations - while ( (count|0) > 0 ) { - hmac_reset(); - _core( t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768 ); - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; - - _hmac_opad(); - _core( t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768 ); - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; - - h0 = h0 ^ H0; - h1 = h1 ^ H1; - h2 = h2 ^ H2; - h3 = h3 ^ H3; - h4 = h4 ^ H4; - h5 = h5 ^ H5; - h6 = h6 ^ H6; - h7 = h7 ^ H7; - - count = (count-1)|0; - } - - H0 = h0; - H1 = h1; - H2 = h2; - H3 = h3; - H4 = h4; - H5 = h5; - H6 = h6; - H7 = h7; - - if ( ~output ) - _state_to_heap(output); - - return 0; - } - - return { - // SHA256 - reset: reset, - init: init, - process: process, - finish: finish, - - // HMAC-SHA256 - hmac_reset: hmac_reset, - hmac_init: hmac_init, - hmac_finish: hmac_finish, - - // PBKDF2-HMAC-SHA256 - pbkdf2_generate_block: pbkdf2_generate_block - } -}; - -const _sha256_block_size = 64; -const _sha256_hash_size = 32; -const heap_pool$2 = []; -const asm_pool$2 = []; -class Sha256 extends Hash { - constructor() { - super(); - this.NAME = 'sha256'; - this.BLOCK_SIZE = _sha256_block_size; - this.HASH_SIZE = _sha256_hash_size; - this.acquire_asm(); - } - acquire_asm() { - if (this.heap === undefined || this.asm === undefined) { - this.heap = heap_pool$2.pop() || _heap_init(); - this.asm = asm_pool$2.pop() || sha256_asm({ Uint8Array: Uint8Array }, null, this.heap.buffer); - this.reset(); - } - return { heap: this.heap, asm: this.asm }; - } - release_asm() { - if (this.heap !== undefined && this.asm !== undefined) { - heap_pool$2.push(this.heap); - asm_pool$2.push(this.asm); - } - this.heap = undefined; - this.asm = undefined; - } - static bytes(data) { - return new Sha256().process(data).finish().result; - } -} -Sha256.NAME = 'sha256'; - -var minimalisticAssert = assert; - -function assert(val, msg) { - if (!val) - throw new Error(msg || 'Assertion failed'); -} - -assert.equal = function assertEqual(l, r, msg) { - if (l != r) - throw new Error(msg || ('Assertion failed: ' + l + ' != ' + r)); -}; - -var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; - -function createCommonjsModule(fn, module) { - return module = { exports: {} }, fn(module, module.exports), module.exports; -} - -function commonjsRequire () { - throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs'); -} - -var inherits_browser = createCommonjsModule(function (module) { -if (typeof Object.create === 'function') { - // implementation from standard node.js 'util' module - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor; - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }); - }; -} else { - // old school shim for old browsers - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor; - var TempCtor = function () {}; - TempCtor.prototype = superCtor.prototype; - ctor.prototype = new TempCtor(); - ctor.prototype.constructor = ctor; - }; -} -}); - -var inherits = createCommonjsModule(function (module) { -try { - var util = util__default['default']; - if (typeof util.inherits !== 'function') throw ''; - module.exports = util.inherits; -} catch (e) { - module.exports = inherits_browser; -} -}); - -var inherits_1 = inherits; - -function toArray(msg, enc) { - if (Array.isArray(msg)) - return msg.slice(); - if (!msg) - return []; - var res = []; - if (typeof msg === 'string') { - if (!enc) { - for (var i = 0; i < msg.length; i++) { - var c = msg.charCodeAt(i); - var hi = c >> 8; - var lo = c & 0xff; - if (hi) - res.push(hi, lo); - else - res.push(lo); - } - } else if (enc === 'hex') { - msg = msg.replace(/[^a-z0-9]+/ig, ''); - if (msg.length % 2 !== 0) - msg = '0' + msg; - for (i = 0; i < msg.length; i += 2) - res.push(parseInt(msg[i] + msg[i + 1], 16)); - } - } else { - for (i = 0; i < msg.length; i++) - res[i] = msg[i] | 0; - } - return res; -} -var toArray_1 = toArray; - -function toHex(msg) { - var res = ''; - for (var i = 0; i < msg.length; i++) - res += zero2(msg[i].toString(16)); - return res; -} -var toHex_1 = toHex; - -function htonl(w) { - var res = (w >>> 24) | - ((w >>> 8) & 0xff00) | - ((w << 8) & 0xff0000) | - ((w & 0xff) << 24); - return res >>> 0; -} -var htonl_1 = htonl; - -function toHex32(msg, endian) { - var res = ''; - for (var i = 0; i < msg.length; i++) { - var w = msg[i]; - if (endian === 'little') - w = htonl(w); - res += zero8(w.toString(16)); - } - return res; -} -var toHex32_1 = toHex32; - -function zero2(word) { - if (word.length === 1) - return '0' + word; - else - return word; -} -var zero2_1 = zero2; - -function zero8(word) { - if (word.length === 7) - return '0' + word; - else if (word.length === 6) - return '00' + word; - else if (word.length === 5) - return '000' + word; - else if (word.length === 4) - return '0000' + word; - else if (word.length === 3) - return '00000' + word; - else if (word.length === 2) - return '000000' + word; - else if (word.length === 1) - return '0000000' + word; - else - return word; -} -var zero8_1 = zero8; - -function join32(msg, start, end, endian) { - var len = end - start; - minimalisticAssert(len % 4 === 0); - var res = new Array(len / 4); - for (var i = 0, k = start; i < res.length; i++, k += 4) { - var w; - if (endian === 'big') - w = (msg[k] << 24) | (msg[k + 1] << 16) | (msg[k + 2] << 8) | msg[k + 3]; - else - w = (msg[k + 3] << 24) | (msg[k + 2] << 16) | (msg[k + 1] << 8) | msg[k]; - res[i] = w >>> 0; - } - return res; -} -var join32_1 = join32; - -function split32(msg, endian) { - var res = new Array(msg.length * 4); - for (var i = 0, k = 0; i < msg.length; i++, k += 4) { - var m = msg[i]; - if (endian === 'big') { - res[k] = m >>> 24; - res[k + 1] = (m >>> 16) & 0xff; - res[k + 2] = (m >>> 8) & 0xff; - res[k + 3] = m & 0xff; - } else { - res[k + 3] = m >>> 24; - res[k + 2] = (m >>> 16) & 0xff; - res[k + 1] = (m >>> 8) & 0xff; - res[k] = m & 0xff; - } - } - return res; -} -var split32_1 = split32; - -function rotr32(w, b) { - return (w >>> b) | (w << (32 - b)); -} -var rotr32_1 = rotr32; - -function rotl32(w, b) { - return (w << b) | (w >>> (32 - b)); -} -var rotl32_1 = rotl32; - -function sum32(a, b) { - return (a + b) >>> 0; -} -var sum32_1 = sum32; - -function sum32_3(a, b, c) { - return (a + b + c) >>> 0; -} -var sum32_3_1 = sum32_3; - -function sum32_4(a, b, c, d) { - return (a + b + c + d) >>> 0; -} -var sum32_4_1 = sum32_4; - -function sum32_5(a, b, c, d, e) { - return (a + b + c + d + e) >>> 0; -} -var sum32_5_1 = sum32_5; - -function sum64(buf, pos, ah, al) { - var bh = buf[pos]; - var bl = buf[pos + 1]; - - var lo = (al + bl) >>> 0; - var hi = (lo < al ? 1 : 0) + ah + bh; - buf[pos] = hi >>> 0; - buf[pos + 1] = lo; -} -var sum64_1 = sum64; - -function sum64_hi(ah, al, bh, bl) { - var lo = (al + bl) >>> 0; - var hi = (lo < al ? 1 : 0) + ah + bh; - return hi >>> 0; -} -var sum64_hi_1 = sum64_hi; - -function sum64_lo(ah, al, bh, bl) { - var lo = al + bl; - return lo >>> 0; -} -var sum64_lo_1 = sum64_lo; - -function sum64_4_hi(ah, al, bh, bl, ch, cl, dh, dl) { - var carry = 0; - var lo = al; - lo = (lo + bl) >>> 0; - carry += lo < al ? 1 : 0; - lo = (lo + cl) >>> 0; - carry += lo < cl ? 1 : 0; - lo = (lo + dl) >>> 0; - carry += lo < dl ? 1 : 0; - - var hi = ah + bh + ch + dh + carry; - return hi >>> 0; -} -var sum64_4_hi_1 = sum64_4_hi; - -function sum64_4_lo(ah, al, bh, bl, ch, cl, dh, dl) { - var lo = al + bl + cl + dl; - return lo >>> 0; -} -var sum64_4_lo_1 = sum64_4_lo; - -function sum64_5_hi(ah, al, bh, bl, ch, cl, dh, dl, eh, el) { - var carry = 0; - var lo = al; - lo = (lo + bl) >>> 0; - carry += lo < al ? 1 : 0; - lo = (lo + cl) >>> 0; - carry += lo < cl ? 1 : 0; - lo = (lo + dl) >>> 0; - carry += lo < dl ? 1 : 0; - lo = (lo + el) >>> 0; - carry += lo < el ? 1 : 0; - - var hi = ah + bh + ch + dh + eh + carry; - return hi >>> 0; -} -var sum64_5_hi_1 = sum64_5_hi; - -function sum64_5_lo(ah, al, bh, bl, ch, cl, dh, dl, eh, el) { - var lo = al + bl + cl + dl + el; - - return lo >>> 0; -} -var sum64_5_lo_1 = sum64_5_lo; - -function rotr64_hi(ah, al, num) { - var r = (al << (32 - num)) | (ah >>> num); - return r >>> 0; -} -var rotr64_hi_1 = rotr64_hi; - -function rotr64_lo(ah, al, num) { - var r = (ah << (32 - num)) | (al >>> num); - return r >>> 0; -} -var rotr64_lo_1 = rotr64_lo; - -function shr64_hi(ah, al, num) { - return ah >>> num; -} -var shr64_hi_1 = shr64_hi; - -function shr64_lo(ah, al, num) { - var r = (ah << (32 - num)) | (al >>> num); - return r >>> 0; -} -var shr64_lo_1 = shr64_lo; - -var utils = { - inherits: inherits_1, - toArray: toArray_1, - toHex: toHex_1, - htonl: htonl_1, - toHex32: toHex32_1, - zero2: zero2_1, - zero8: zero8_1, - join32: join32_1, - split32: split32_1, - rotr32: rotr32_1, - rotl32: rotl32_1, - sum32: sum32_1, - sum32_3: sum32_3_1, - sum32_4: sum32_4_1, - sum32_5: sum32_5_1, - sum64: sum64_1, - sum64_hi: sum64_hi_1, - sum64_lo: sum64_lo_1, - sum64_4_hi: sum64_4_hi_1, - sum64_4_lo: sum64_4_lo_1, - sum64_5_hi: sum64_5_hi_1, - sum64_5_lo: sum64_5_lo_1, - rotr64_hi: rotr64_hi_1, - rotr64_lo: rotr64_lo_1, - shr64_hi: shr64_hi_1, - shr64_lo: shr64_lo_1 -}; - -function BlockHash() { - this.pending = null; - this.pendingTotal = 0; - this.blockSize = this.constructor.blockSize; - this.outSize = this.constructor.outSize; - this.hmacStrength = this.constructor.hmacStrength; - this.padLength = this.constructor.padLength / 8; - this.endian = 'big'; - - this._delta8 = this.blockSize / 8; - this._delta32 = this.blockSize / 32; -} -var BlockHash_1 = BlockHash; - -BlockHash.prototype.update = function update(msg, enc) { - // Convert message to array, pad it, and join into 32bit blocks - msg = utils.toArray(msg, enc); - if (!this.pending) - this.pending = msg; - else - this.pending = this.pending.concat(msg); - this.pendingTotal += msg.length; - - // Enough data, try updating - if (this.pending.length >= this._delta8) { - msg = this.pending; - - // Process pending data in blocks - var r = msg.length % this._delta8; - this.pending = msg.slice(msg.length - r, msg.length); - if (this.pending.length === 0) - this.pending = null; - - msg = utils.join32(msg, 0, msg.length - r, this.endian); - for (var i = 0; i < msg.length; i += this._delta32) - this._update(msg, i, i + this._delta32); - } - - return this; -}; - -BlockHash.prototype.digest = function digest(enc) { - this.update(this._pad()); - minimalisticAssert(this.pending === null); - - return this._digest(enc); -}; - -BlockHash.prototype._pad = function pad() { - var len = this.pendingTotal; - var bytes = this._delta8; - var k = bytes - ((len + this.padLength) % bytes); - var res = new Array(k + this.padLength); - res[0] = 0x80; - for (var i = 1; i < k; i++) - res[i] = 0; - - // Append length - len <<= 3; - if (this.endian === 'big') { - for (var t = 8; t < this.padLength; t++) - res[i++] = 0; - - res[i++] = 0; - res[i++] = 0; - res[i++] = 0; - res[i++] = 0; - res[i++] = (len >>> 24) & 0xff; - res[i++] = (len >>> 16) & 0xff; - res[i++] = (len >>> 8) & 0xff; - res[i++] = len & 0xff; - } else { - res[i++] = len & 0xff; - res[i++] = (len >>> 8) & 0xff; - res[i++] = (len >>> 16) & 0xff; - res[i++] = (len >>> 24) & 0xff; - res[i++] = 0; - res[i++] = 0; - res[i++] = 0; - res[i++] = 0; - - for (t = 8; t < this.padLength; t++) - res[i++] = 0; - } - - return res; -}; - -var common = { - BlockHash: BlockHash_1 -}; - -var rotr32$1 = utils.rotr32; - -function ft_1(s, x, y, z) { - if (s === 0) - return ch32(x, y, z); - if (s === 1 || s === 3) - return p32(x, y, z); - if (s === 2) - return maj32(x, y, z); -} -var ft_1_1 = ft_1; - -function ch32(x, y, z) { - return (x & y) ^ ((~x) & z); -} -var ch32_1 = ch32; - -function maj32(x, y, z) { - return (x & y) ^ (x & z) ^ (y & z); -} -var maj32_1 = maj32; - -function p32(x, y, z) { - return x ^ y ^ z; -} -var p32_1 = p32; - -function s0_256(x) { - return rotr32$1(x, 2) ^ rotr32$1(x, 13) ^ rotr32$1(x, 22); -} -var s0_256_1 = s0_256; - -function s1_256(x) { - return rotr32$1(x, 6) ^ rotr32$1(x, 11) ^ rotr32$1(x, 25); -} -var s1_256_1 = s1_256; - -function g0_256(x) { - return rotr32$1(x, 7) ^ rotr32$1(x, 18) ^ (x >>> 3); -} -var g0_256_1 = g0_256; - -function g1_256(x) { - return rotr32$1(x, 17) ^ rotr32$1(x, 19) ^ (x >>> 10); -} -var g1_256_1 = g1_256; - -var common$1 = { - ft_1: ft_1_1, - ch32: ch32_1, - maj32: maj32_1, - p32: p32_1, - s0_256: s0_256_1, - s1_256: s1_256_1, - g0_256: g0_256_1, - g1_256: g1_256_1 -}; - -var sum32$1 = utils.sum32; -var sum32_4$1 = utils.sum32_4; -var sum32_5$1 = utils.sum32_5; -var ch32$1 = common$1.ch32; -var maj32$1 = common$1.maj32; -var s0_256$1 = common$1.s0_256; -var s1_256$1 = common$1.s1_256; -var g0_256$1 = common$1.g0_256; -var g1_256$1 = common$1.g1_256; - -var BlockHash$1 = common.BlockHash; - -var sha256_K = [ - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -]; - -function SHA256() { - if (!(this instanceof SHA256)) - return new SHA256(); - - BlockHash$1.call(this); - this.h = [ - 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, - 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 - ]; - this.k = sha256_K; - this.W = new Array(64); -} -utils.inherits(SHA256, BlockHash$1); -var _256 = SHA256; - -SHA256.blockSize = 512; -SHA256.outSize = 256; -SHA256.hmacStrength = 192; -SHA256.padLength = 64; - -SHA256.prototype._update = function _update(msg, start) { - var W = this.W; - - for (var i = 0; i < 16; i++) - W[i] = msg[start + i]; - for (; i < W.length; i++) - W[i] = sum32_4$1(g1_256$1(W[i - 2]), W[i - 7], g0_256$1(W[i - 15]), W[i - 16]); - - var a = this.h[0]; - var b = this.h[1]; - var c = this.h[2]; - var d = this.h[3]; - var e = this.h[4]; - var f = this.h[5]; - var g = this.h[6]; - var h = this.h[7]; - - minimalisticAssert(this.k.length === W.length); - for (i = 0; i < W.length; i++) { - var T1 = sum32_5$1(h, s1_256$1(e), ch32$1(e, f, g), this.k[i], W[i]); - var T2 = sum32$1(s0_256$1(a), maj32$1(a, b, c)); - h = g; - g = f; - f = e; - e = sum32$1(d, T1); - d = c; - c = b; - b = a; - a = sum32$1(T1, T2); - } - - this.h[0] = sum32$1(this.h[0], a); - this.h[1] = sum32$1(this.h[1], b); - this.h[2] = sum32$1(this.h[2], c); - this.h[3] = sum32$1(this.h[3], d); - this.h[4] = sum32$1(this.h[4], e); - this.h[5] = sum32$1(this.h[5], f); - this.h[6] = sum32$1(this.h[6], g); - this.h[7] = sum32$1(this.h[7], h); -}; - -SHA256.prototype._digest = function digest(enc) { - if (enc === 'hex') - return utils.toHex32(this.h, 'big'); - else - return utils.split32(this.h, 'big'); -}; - -function SHA224() { - if (!(this instanceof SHA224)) - return new SHA224(); - - _256.call(this); - this.h = [ - 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, - 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 ]; -} -utils.inherits(SHA224, _256); -var _224 = SHA224; - -SHA224.blockSize = 512; -SHA224.outSize = 224; -SHA224.hmacStrength = 192; -SHA224.padLength = 64; - -SHA224.prototype._digest = function digest(enc) { - // Just truncate output - if (enc === 'hex') - return utils.toHex32(this.h.slice(0, 7), 'big'); - else - return utils.split32(this.h.slice(0, 7), 'big'); -}; - -var rotr64_hi$1 = utils.rotr64_hi; -var rotr64_lo$1 = utils.rotr64_lo; -var shr64_hi$1 = utils.shr64_hi; -var shr64_lo$1 = utils.shr64_lo; -var sum64$1 = utils.sum64; -var sum64_hi$1 = utils.sum64_hi; -var sum64_lo$1 = utils.sum64_lo; -var sum64_4_hi$1 = utils.sum64_4_hi; -var sum64_4_lo$1 = utils.sum64_4_lo; -var sum64_5_hi$1 = utils.sum64_5_hi; -var sum64_5_lo$1 = utils.sum64_5_lo; - -var BlockHash$2 = common.BlockHash; - -var sha512_K = [ - 0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd, - 0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc, - 0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019, - 0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118, - 0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe, - 0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2, - 0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1, - 0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694, - 0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3, - 0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65, - 0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483, - 0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5, - 0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210, - 0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4, - 0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725, - 0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70, - 0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926, - 0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df, - 0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8, - 0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b, - 0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001, - 0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30, - 0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910, - 0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8, - 0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53, - 0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8, - 0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb, - 0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3, - 0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60, - 0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec, - 0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9, - 0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b, - 0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207, - 0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178, - 0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6, - 0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b, - 0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493, - 0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c, - 0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a, - 0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817 -]; - -function SHA512() { - if (!(this instanceof SHA512)) - return new SHA512(); - - BlockHash$2.call(this); - this.h = [ - 0x6a09e667, 0xf3bcc908, - 0xbb67ae85, 0x84caa73b, - 0x3c6ef372, 0xfe94f82b, - 0xa54ff53a, 0x5f1d36f1, - 0x510e527f, 0xade682d1, - 0x9b05688c, 0x2b3e6c1f, - 0x1f83d9ab, 0xfb41bd6b, - 0x5be0cd19, 0x137e2179 ]; - this.k = sha512_K; - this.W = new Array(160); -} -utils.inherits(SHA512, BlockHash$2); -var _512 = SHA512; - -SHA512.blockSize = 1024; -SHA512.outSize = 512; -SHA512.hmacStrength = 192; -SHA512.padLength = 128; - -SHA512.prototype._prepareBlock = function _prepareBlock(msg, start) { - var W = this.W; - - // 32 x 32bit words - for (var i = 0; i < 32; i++) - W[i] = msg[start + i]; - for (; i < W.length; i += 2) { - var c0_hi = g1_512_hi(W[i - 4], W[i - 3]); // i - 2 - var c0_lo = g1_512_lo(W[i - 4], W[i - 3]); - var c1_hi = W[i - 14]; // i - 7 - var c1_lo = W[i - 13]; - var c2_hi = g0_512_hi(W[i - 30], W[i - 29]); // i - 15 - var c2_lo = g0_512_lo(W[i - 30], W[i - 29]); - var c3_hi = W[i - 32]; // i - 16 - var c3_lo = W[i - 31]; - - W[i] = sum64_4_hi$1( - c0_hi, c0_lo, - c1_hi, c1_lo, - c2_hi, c2_lo, - c3_hi, c3_lo); - W[i + 1] = sum64_4_lo$1( - c0_hi, c0_lo, - c1_hi, c1_lo, - c2_hi, c2_lo, - c3_hi, c3_lo); - } -}; - -SHA512.prototype._update = function _update(msg, start) { - this._prepareBlock(msg, start); - - var W = this.W; - - var ah = this.h[0]; - var al = this.h[1]; - var bh = this.h[2]; - var bl = this.h[3]; - var ch = this.h[4]; - var cl = this.h[5]; - var dh = this.h[6]; - var dl = this.h[7]; - var eh = this.h[8]; - var el = this.h[9]; - var fh = this.h[10]; - var fl = this.h[11]; - var gh = this.h[12]; - var gl = this.h[13]; - var hh = this.h[14]; - var hl = this.h[15]; - - minimalisticAssert(this.k.length === W.length); - for (var i = 0; i < W.length; i += 2) { - var c0_hi = hh; - var c0_lo = hl; - var c1_hi = s1_512_hi(eh, el); - var c1_lo = s1_512_lo(eh, el); - var c2_hi = ch64_hi(eh, el, fh, fl, gh); - var c2_lo = ch64_lo(eh, el, fh, fl, gh, gl); - var c3_hi = this.k[i]; - var c3_lo = this.k[i + 1]; - var c4_hi = W[i]; - var c4_lo = W[i + 1]; - - var T1_hi = sum64_5_hi$1( - c0_hi, c0_lo, - c1_hi, c1_lo, - c2_hi, c2_lo, - c3_hi, c3_lo, - c4_hi, c4_lo); - var T1_lo = sum64_5_lo$1( - c0_hi, c0_lo, - c1_hi, c1_lo, - c2_hi, c2_lo, - c3_hi, c3_lo, - c4_hi, c4_lo); - - c0_hi = s0_512_hi(ah, al); - c0_lo = s0_512_lo(ah, al); - c1_hi = maj64_hi(ah, al, bh, bl, ch); - c1_lo = maj64_lo(ah, al, bh, bl, ch, cl); - - var T2_hi = sum64_hi$1(c0_hi, c0_lo, c1_hi, c1_lo); - var T2_lo = sum64_lo$1(c0_hi, c0_lo, c1_hi, c1_lo); - - hh = gh; - hl = gl; - - gh = fh; - gl = fl; - - fh = eh; - fl = el; - - eh = sum64_hi$1(dh, dl, T1_hi, T1_lo); - el = sum64_lo$1(dl, dl, T1_hi, T1_lo); - - dh = ch; - dl = cl; - - ch = bh; - cl = bl; - - bh = ah; - bl = al; - - ah = sum64_hi$1(T1_hi, T1_lo, T2_hi, T2_lo); - al = sum64_lo$1(T1_hi, T1_lo, T2_hi, T2_lo); - } - - sum64$1(this.h, 0, ah, al); - sum64$1(this.h, 2, bh, bl); - sum64$1(this.h, 4, ch, cl); - sum64$1(this.h, 6, dh, dl); - sum64$1(this.h, 8, eh, el); - sum64$1(this.h, 10, fh, fl); - sum64$1(this.h, 12, gh, gl); - sum64$1(this.h, 14, hh, hl); -}; - -SHA512.prototype._digest = function digest(enc) { - if (enc === 'hex') - return utils.toHex32(this.h, 'big'); - else - return utils.split32(this.h, 'big'); -}; - -function ch64_hi(xh, xl, yh, yl, zh) { - var r = (xh & yh) ^ ((~xh) & zh); - if (r < 0) - r += 0x100000000; - return r; -} - -function ch64_lo(xh, xl, yh, yl, zh, zl) { - var r = (xl & yl) ^ ((~xl) & zl); - if (r < 0) - r += 0x100000000; - return r; -} - -function maj64_hi(xh, xl, yh, yl, zh) { - var r = (xh & yh) ^ (xh & zh) ^ (yh & zh); - if (r < 0) - r += 0x100000000; - return r; -} - -function maj64_lo(xh, xl, yh, yl, zh, zl) { - var r = (xl & yl) ^ (xl & zl) ^ (yl & zl); - if (r < 0) - r += 0x100000000; - return r; -} - -function s0_512_hi(xh, xl) { - var c0_hi = rotr64_hi$1(xh, xl, 28); - var c1_hi = rotr64_hi$1(xl, xh, 2); // 34 - var c2_hi = rotr64_hi$1(xl, xh, 7); // 39 - - var r = c0_hi ^ c1_hi ^ c2_hi; - if (r < 0) - r += 0x100000000; - return r; -} - -function s0_512_lo(xh, xl) { - var c0_lo = rotr64_lo$1(xh, xl, 28); - var c1_lo = rotr64_lo$1(xl, xh, 2); // 34 - var c2_lo = rotr64_lo$1(xl, xh, 7); // 39 - - var r = c0_lo ^ c1_lo ^ c2_lo; - if (r < 0) - r += 0x100000000; - return r; -} - -function s1_512_hi(xh, xl) { - var c0_hi = rotr64_hi$1(xh, xl, 14); - var c1_hi = rotr64_hi$1(xh, xl, 18); - var c2_hi = rotr64_hi$1(xl, xh, 9); // 41 - - var r = c0_hi ^ c1_hi ^ c2_hi; - if (r < 0) - r += 0x100000000; - return r; -} - -function s1_512_lo(xh, xl) { - var c0_lo = rotr64_lo$1(xh, xl, 14); - var c1_lo = rotr64_lo$1(xh, xl, 18); - var c2_lo = rotr64_lo$1(xl, xh, 9); // 41 - - var r = c0_lo ^ c1_lo ^ c2_lo; - if (r < 0) - r += 0x100000000; - return r; -} - -function g0_512_hi(xh, xl) { - var c0_hi = rotr64_hi$1(xh, xl, 1); - var c1_hi = rotr64_hi$1(xh, xl, 8); - var c2_hi = shr64_hi$1(xh, xl, 7); - - var r = c0_hi ^ c1_hi ^ c2_hi; - if (r < 0) - r += 0x100000000; - return r; -} - -function g0_512_lo(xh, xl) { - var c0_lo = rotr64_lo$1(xh, xl, 1); - var c1_lo = rotr64_lo$1(xh, xl, 8); - var c2_lo = shr64_lo$1(xh, xl, 7); - - var r = c0_lo ^ c1_lo ^ c2_lo; - if (r < 0) - r += 0x100000000; - return r; -} - -function g1_512_hi(xh, xl) { - var c0_hi = rotr64_hi$1(xh, xl, 19); - var c1_hi = rotr64_hi$1(xl, xh, 29); // 61 - var c2_hi = shr64_hi$1(xh, xl, 6); - - var r = c0_hi ^ c1_hi ^ c2_hi; - if (r < 0) - r += 0x100000000; - return r; -} - -function g1_512_lo(xh, xl) { - var c0_lo = rotr64_lo$1(xh, xl, 19); - var c1_lo = rotr64_lo$1(xl, xh, 29); // 61 - var c2_lo = shr64_lo$1(xh, xl, 6); - - var r = c0_lo ^ c1_lo ^ c2_lo; - if (r < 0) - r += 0x100000000; - return r; -} - -function SHA384() { - if (!(this instanceof SHA384)) - return new SHA384(); - - _512.call(this); - this.h = [ - 0xcbbb9d5d, 0xc1059ed8, - 0x629a292a, 0x367cd507, - 0x9159015a, 0x3070dd17, - 0x152fecd8, 0xf70e5939, - 0x67332667, 0xffc00b31, - 0x8eb44a87, 0x68581511, - 0xdb0c2e0d, 0x64f98fa7, - 0x47b5481d, 0xbefa4fa4 ]; -} -utils.inherits(SHA384, _512); -var _384 = SHA384; - -SHA384.blockSize = 1024; -SHA384.outSize = 384; -SHA384.hmacStrength = 192; -SHA384.padLength = 128; - -SHA384.prototype._digest = function digest(enc) { - if (enc === 'hex') - return utils.toHex32(this.h.slice(0, 12), 'big'); - else - return utils.split32(this.h.slice(0, 12), 'big'); -}; - -var rotl32$1 = utils.rotl32; -var sum32$2 = utils.sum32; -var sum32_3$1 = utils.sum32_3; -var sum32_4$2 = utils.sum32_4; -var BlockHash$3 = common.BlockHash; - -function RIPEMD160() { - if (!(this instanceof RIPEMD160)) - return new RIPEMD160(); - - BlockHash$3.call(this); - - this.h = [ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 ]; - this.endian = 'little'; -} -utils.inherits(RIPEMD160, BlockHash$3); -var ripemd160 = RIPEMD160; - -RIPEMD160.blockSize = 512; -RIPEMD160.outSize = 160; -RIPEMD160.hmacStrength = 192; -RIPEMD160.padLength = 64; - -RIPEMD160.prototype._update = function update(msg, start) { - var A = this.h[0]; - var B = this.h[1]; - var C = this.h[2]; - var D = this.h[3]; - var E = this.h[4]; - var Ah = A; - var Bh = B; - var Ch = C; - var Dh = D; - var Eh = E; - for (var j = 0; j < 80; j++) { - var T = sum32$2( - rotl32$1( - sum32_4$2(A, f(j, B, C, D), msg[r[j] + start], K(j)), - s[j]), - E); - A = E; - E = D; - D = rotl32$1(C, 10); - C = B; - B = T; - T = sum32$2( - rotl32$1( - sum32_4$2(Ah, f(79 - j, Bh, Ch, Dh), msg[rh[j] + start], Kh(j)), - sh[j]), - Eh); - Ah = Eh; - Eh = Dh; - Dh = rotl32$1(Ch, 10); - Ch = Bh; - Bh = T; - } - T = sum32_3$1(this.h[1], C, Dh); - this.h[1] = sum32_3$1(this.h[2], D, Eh); - this.h[2] = sum32_3$1(this.h[3], E, Ah); - this.h[3] = sum32_3$1(this.h[4], A, Bh); - this.h[4] = sum32_3$1(this.h[0], B, Ch); - this.h[0] = T; -}; - -RIPEMD160.prototype._digest = function digest(enc) { - if (enc === 'hex') - return utils.toHex32(this.h, 'little'); - else - return utils.split32(this.h, 'little'); -}; - -function f(j, x, y, z) { - if (j <= 15) - return x ^ y ^ z; - else if (j <= 31) - return (x & y) | ((~x) & z); - else if (j <= 47) - return (x | (~y)) ^ z; - else if (j <= 63) - return (x & z) | (y & (~z)); - else - return x ^ (y | (~z)); -} - -function K(j) { - if (j <= 15) - return 0x00000000; - else if (j <= 31) - return 0x5a827999; - else if (j <= 47) - return 0x6ed9eba1; - else if (j <= 63) - return 0x8f1bbcdc; - else - return 0xa953fd4e; -} - -function Kh(j) { - if (j <= 15) - return 0x50a28be6; - else if (j <= 31) - return 0x5c4dd124; - else if (j <= 47) - return 0x6d703ef3; - else if (j <= 63) - return 0x7a6d76e9; - else - return 0x00000000; -} - -var r = [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, - 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, - 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, - 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 -]; - -var rh = [ - 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, - 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, - 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, - 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, - 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 -]; - -var s = [ - 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, - 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, - 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, - 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, - 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 -]; - -var sh = [ - 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, - 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, - 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, - 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, - 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 -]; - -var ripemd = { - ripemd160: ripemd160 -}; - -/** - * A fast MD5 JavaScript implementation - * Copyright (c) 2012 Joseph Myers - * http://www.myersdaily.org/joseph/javascript/md5-text.html - * - * Permission to use, copy, modify, and distribute this software - * and its documentation for any purposes and without - * fee is hereby granted provided that this copyright notice - * appears in all copies. - * - * Of course, this soft is provided "as is" without express or implied - * warranty of any kind. - */ - -// MD5 Digest -async function md5(entree) { - const digest = md51(util.uint8ArrayToString(entree)); - return util.hexToUint8Array(hex(digest)); -} - -function md5cycle(x, k) { - let a = x[0]; - let b = x[1]; - let c = x[2]; - let d = x[3]; - - a = ff(a, b, c, d, k[0], 7, -680876936); - d = ff(d, a, b, c, k[1], 12, -389564586); - c = ff(c, d, a, b, k[2], 17, 606105819); - b = ff(b, c, d, a, k[3], 22, -1044525330); - a = ff(a, b, c, d, k[4], 7, -176418897); - d = ff(d, a, b, c, k[5], 12, 1200080426); - c = ff(c, d, a, b, k[6], 17, -1473231341); - b = ff(b, c, d, a, k[7], 22, -45705983); - a = ff(a, b, c, d, k[8], 7, 1770035416); - d = ff(d, a, b, c, k[9], 12, -1958414417); - c = ff(c, d, a, b, k[10], 17, -42063); - b = ff(b, c, d, a, k[11], 22, -1990404162); - a = ff(a, b, c, d, k[12], 7, 1804603682); - d = ff(d, a, b, c, k[13], 12, -40341101); - c = ff(c, d, a, b, k[14], 17, -1502002290); - b = ff(b, c, d, a, k[15], 22, 1236535329); - - a = gg(a, b, c, d, k[1], 5, -165796510); - d = gg(d, a, b, c, k[6], 9, -1069501632); - c = gg(c, d, a, b, k[11], 14, 643717713); - b = gg(b, c, d, a, k[0], 20, -373897302); - a = gg(a, b, c, d, k[5], 5, -701558691); - d = gg(d, a, b, c, k[10], 9, 38016083); - c = gg(c, d, a, b, k[15], 14, -660478335); - b = gg(b, c, d, a, k[4], 20, -405537848); - a = gg(a, b, c, d, k[9], 5, 568446438); - d = gg(d, a, b, c, k[14], 9, -1019803690); - c = gg(c, d, a, b, k[3], 14, -187363961); - b = gg(b, c, d, a, k[8], 20, 1163531501); - a = gg(a, b, c, d, k[13], 5, -1444681467); - d = gg(d, a, b, c, k[2], 9, -51403784); - c = gg(c, d, a, b, k[7], 14, 1735328473); - b = gg(b, c, d, a, k[12], 20, -1926607734); - - a = hh(a, b, c, d, k[5], 4, -378558); - d = hh(d, a, b, c, k[8], 11, -2022574463); - c = hh(c, d, a, b, k[11], 16, 1839030562); - b = hh(b, c, d, a, k[14], 23, -35309556); - a = hh(a, b, c, d, k[1], 4, -1530992060); - d = hh(d, a, b, c, k[4], 11, 1272893353); - c = hh(c, d, a, b, k[7], 16, -155497632); - b = hh(b, c, d, a, k[10], 23, -1094730640); - a = hh(a, b, c, d, k[13], 4, 681279174); - d = hh(d, a, b, c, k[0], 11, -358537222); - c = hh(c, d, a, b, k[3], 16, -722521979); - b = hh(b, c, d, a, k[6], 23, 76029189); - a = hh(a, b, c, d, k[9], 4, -640364487); - d = hh(d, a, b, c, k[12], 11, -421815835); - c = hh(c, d, a, b, k[15], 16, 530742520); - b = hh(b, c, d, a, k[2], 23, -995338651); - - a = ii(a, b, c, d, k[0], 6, -198630844); - d = ii(d, a, b, c, k[7], 10, 1126891415); - c = ii(c, d, a, b, k[14], 15, -1416354905); - b = ii(b, c, d, a, k[5], 21, -57434055); - a = ii(a, b, c, d, k[12], 6, 1700485571); - d = ii(d, a, b, c, k[3], 10, -1894986606); - c = ii(c, d, a, b, k[10], 15, -1051523); - b = ii(b, c, d, a, k[1], 21, -2054922799); - a = ii(a, b, c, d, k[8], 6, 1873313359); - d = ii(d, a, b, c, k[15], 10, -30611744); - c = ii(c, d, a, b, k[6], 15, -1560198380); - b = ii(b, c, d, a, k[13], 21, 1309151649); - a = ii(a, b, c, d, k[4], 6, -145523070); - d = ii(d, a, b, c, k[11], 10, -1120210379); - c = ii(c, d, a, b, k[2], 15, 718787259); - b = ii(b, c, d, a, k[9], 21, -343485551); - - x[0] = add32(a, x[0]); - x[1] = add32(b, x[1]); - x[2] = add32(c, x[2]); - x[3] = add32(d, x[3]); -} - -function cmn(q, a, b, x, s, t) { - a = add32(add32(a, q), add32(x, t)); - return add32((a << s) | (a >>> (32 - s)), b); -} - -function ff(a, b, c, d, x, s, t) { - return cmn((b & c) | ((~b) & d), a, b, x, s, t); -} - -function gg(a, b, c, d, x, s, t) { - return cmn((b & d) | (c & (~d)), a, b, x, s, t); -} - -function hh(a, b, c, d, x, s, t) { - return cmn(b ^ c ^ d, a, b, x, s, t); -} - -function ii(a, b, c, d, x, s, t) { - return cmn(c ^ (b | (~d)), a, b, x, s, t); -} - -function md51(s) { - const n = s.length; - const state = [1732584193, -271733879, -1732584194, 271733878]; - let i; - for (i = 64; i <= s.length; i += 64) { - md5cycle(state, md5blk(s.substring(i - 64, i))); - } - s = s.substring(i - 64); - const tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; - for (i = 0; i < s.length; i++) { - tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3); - } - tail[i >> 2] |= 0x80 << ((i % 4) << 3); - if (i > 55) { - md5cycle(state, tail); - for (i = 0; i < 16; i++) { - tail[i] = 0; - } - } - tail[14] = n * 8; - md5cycle(state, tail); - return state; -} - -/* there needs to be support for Unicode here, - * unless we pretend that we can redefine the MD-5 - * algorithm for multi-byte characters (perhaps - * by adding every four 16-bit characters and - * shortening the sum to 32 bits). Otherwise - * I suggest performing MD-5 as if every character - * was two bytes--e.g., 0040 0025 = @%--but then - * how will an ordinary MD-5 sum be matched? - * There is no way to standardize text to something - * like UTF-8 before transformation; speed cost is - * utterly prohibitive. The JavaScript standard - * itself needs to look at this: it should start - * providing access to strings as preformed UTF-8 - * 8-bit unsigned value arrays. - */ -function md5blk(s) { /* I figured global was faster. */ - const md5blks = []; - let i; /* Andy King said do it this way. */ - for (i = 0; i < 64; i += 4) { - md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << - 24); - } - return md5blks; -} - -const hex_chr = '0123456789abcdef'.split(''); - -function rhex(n) { - let s = ''; - let j = 0; - for (; j < 4; j++) { - s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F]; - } - return s; -} - -function hex(x) { - for (let i = 0; i < x.length; i++) { - x[i] = rhex(x[i]); - } - return x.join(''); -} - -/* this function is much faster, -so if possible we use it. Some IEs -are the only ones I know of that -need the idiotic second function, -generated by an if clause. */ - -function add32(a, b) { - return (a + b) & 0xFFFFFFFF; -} - -/** - * @fileoverview Provides an interface to hashing functions available in Node.js or external libraries. - * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} - * @see {@link https://github.com/indutny/hash.js|hash.js} - * @module crypto/hash - * @private - */ - -const webCrypto = util.getWebCrypto(); -const nodeCrypto = util.getNodeCrypto(); - -function nodeHash(type) { - return async function (data) { - const shasum = nodeCrypto.createHash(type); - return transform(data, value => { - shasum.update(value); - }, () => new Uint8Array(shasum.digest())); - }; -} - -function hashjsHash(hash, webCryptoHash) { - return async function(data, config = defaultConfig) { - if (isArrayStream(data)) { - data = await readToEnd(data); - } - if (!util.isStream(data) && webCrypto && webCryptoHash && data.length >= config.minBytesForWebCrypto) { - return new Uint8Array(await webCrypto.digest(webCryptoHash, data)); - } - const hashInstance = hash(); - return transform(data, value => { - hashInstance.update(value); - }, () => new Uint8Array(hashInstance.digest())); - }; -} - -function asmcryptoHash(hash, webCryptoHash) { - return async function(data, config = defaultConfig) { - if (isArrayStream(data)) { - data = await readToEnd(data); - } - if (util.isStream(data)) { - const hashInstance = new hash(); - return transform(data, value => { - hashInstance.process(value); - }, () => hashInstance.finish().result); - } else if (webCrypto && webCryptoHash && data.length >= config.minBytesForWebCrypto) { - return new Uint8Array(await webCrypto.digest(webCryptoHash, data)); - } else { - return hash.bytes(data); - } - }; -} - -let hashFunctions; -if (nodeCrypto) { // Use Node native crypto for all hash functions - hashFunctions = { - md5: nodeHash('md5'), - sha1: nodeHash('sha1'), - sha224: nodeHash('sha224'), - sha256: nodeHash('sha256'), - sha384: nodeHash('sha384'), - sha512: nodeHash('sha512'), - ripemd: nodeHash('ripemd160') - }; -} else { // Use JS fallbacks - hashFunctions = { - md5: md5, - sha1: asmcryptoHash(Sha1, (!navigator.userAgent || navigator.userAgent.indexOf('Edge') === -1) && 'SHA-1'), - sha224: hashjsHash(_224), - sha256: asmcryptoHash(Sha256, 'SHA-256'), - sha384: hashjsHash(_384, 'SHA-384'), - sha512: hashjsHash(_512, 'SHA-512'), // asmcrypto sha512 is huge. - ripemd: hashjsHash(ripemd160) - }; -} - -var hash = { - - /** @see module:md5 */ - md5: hashFunctions.md5, - /** @see asmCrypto */ - sha1: hashFunctions.sha1, - /** @see hash.js */ - sha224: hashFunctions.sha224, - /** @see asmCrypto */ - sha256: hashFunctions.sha256, - /** @see hash.js */ - sha384: hashFunctions.sha384, - /** @see asmCrypto */ - sha512: hashFunctions.sha512, - /** @see hash.js */ - ripemd: hashFunctions.ripemd, - - /** - * Create a hash on the specified data using the specified algorithm - * @param {module:enums.hash} algo - Hash algorithm type (see {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}) - * @param {Uint8Array} data - Data to be hashed - * @returns {Promise} Hash value. - */ - digest: function(algo, data) { - switch (algo) { - case enums.hash.md5: - return this.md5(data); - case enums.hash.sha1: - return this.sha1(data); - case enums.hash.ripemd: - return this.ripemd(data); - case enums.hash.sha256: - return this.sha256(data); - case enums.hash.sha384: - return this.sha384(data); - case enums.hash.sha512: - return this.sha512(data); - case enums.hash.sha224: - return this.sha224(data); - default: - throw new Error('Invalid hash function.'); - } - }, - - /** - * Returns the hash size in bytes of the specified hash algorithm type - * @param {module:enums.hash} algo - Hash algorithm type (See {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}) - * @returns {Integer} Size in bytes of the resulting hash. - */ - getHashByteLength: function(algo) { - switch (algo) { - case enums.hash.md5: - return 16; - case enums.hash.sha1: - case enums.hash.ripemd: - return 20; - case enums.hash.sha256: - return 32; - case enums.hash.sha384: - return 48; - case enums.hash.sha512: - return 64; - case enums.hash.sha224: - return 28; - default: - throw new Error('Invalid hash algorithm.'); - } - } -}; - -class AES_CFB { - static encrypt(data, key, iv) { - return new AES_CFB(key, iv).encrypt(data); - } - static decrypt(data, key, iv) { - return new AES_CFB(key, iv).decrypt(data); - } - constructor(key, iv, aes) { - this.aes = aes ? aes : new AES(key, iv, true, 'CFB'); - delete this.aes.padding; - } - encrypt(data) { - const r1 = this.aes.AES_Encrypt_process(data); - const r2 = this.aes.AES_Encrypt_finish(); - return joinBytes(r1, r2); - } - decrypt(data) { - const r1 = this.aes.AES_Decrypt_process(data); - const r2 = this.aes.AES_Decrypt_finish(); - return joinBytes(r1, r2); - } -} - -// Modified by ProtonTech AG - -const webCrypto$1 = util.getWebCrypto(); -const nodeCrypto$1 = util.getNodeCrypto(); - -const knownAlgos = nodeCrypto$1 ? nodeCrypto$1.getCiphers() : []; -const nodeAlgos = { - idea: knownAlgos.includes('idea-cfb') ? 'idea-cfb' : undefined, /* Unused, not implemented */ - tripledes: knownAlgos.includes('des-ede3-cfb') ? 'des-ede3-cfb' : undefined, - cast5: knownAlgos.includes('cast5-cfb') ? 'cast5-cfb' : undefined, - blowfish: knownAlgos.includes('bf-cfb') ? 'bf-cfb' : undefined, - aes128: knownAlgos.includes('aes-128-cfb') ? 'aes-128-cfb' : undefined, - aes192: knownAlgos.includes('aes-192-cfb') ? 'aes-192-cfb' : undefined, - aes256: knownAlgos.includes('aes-256-cfb') ? 'aes-256-cfb' : undefined - /* twofish is not implemented in OpenSSL */ -}; - -/** - * CFB encryption - * @param {enums.symmetric} algo - block cipher algorithm - * @param {Uint8Array} key - * @param {MaybeStream} plaintext - * @param {Uint8Array} iv - * @param {Object} config - full configuration, defaults to openpgp.config - * @returns MaybeStream - */ -async function encrypt(algo, key, plaintext, iv, config) { - const algoName = enums.read(enums.symmetric, algo); - if (util.getNodeCrypto() && nodeAlgos[algoName]) { // Node crypto library. - return nodeEncrypt(algo, key, plaintext, iv); - } - if (algoName.substr(0, 3) === 'aes') { - return aesEncrypt(algo, key, plaintext, iv, config); - } - - const cipherfn = new cipher[algoName](key); - const block_size = cipherfn.blockSize; - - const blockc = iv.slice(); - let pt = new Uint8Array(); - const process = chunk => { - if (chunk) { - pt = util.concatUint8Array([pt, chunk]); - } - const ciphertext = new Uint8Array(pt.length); - let i; - let j = 0; - while (chunk ? pt.length >= block_size : pt.length) { - const encblock = cipherfn.encrypt(blockc); - for (i = 0; i < block_size; i++) { - blockc[i] = pt[i] ^ encblock[i]; - ciphertext[j++] = blockc[i]; - } - pt = pt.subarray(block_size); - } - return ciphertext.subarray(0, j); - }; - return transform(plaintext, process, process); -} - -/** - * CFB decryption - * @param {enums.symmetric} algo - block cipher algorithm - * @param {Uint8Array} key - * @param {MaybeStream} ciphertext - * @param {Uint8Array} iv - * @returns MaybeStream - */ -async function decrypt(algo, key, ciphertext, iv) { - const algoName = enums.read(enums.symmetric, algo); - if (util.getNodeCrypto() && nodeAlgos[algoName]) { // Node crypto library. - return nodeDecrypt(algo, key, ciphertext, iv); - } - if (algoName.substr(0, 3) === 'aes') { - return aesDecrypt(algo, key, ciphertext, iv); - } - - const cipherfn = new cipher[algoName](key); - const block_size = cipherfn.blockSize; - - let blockp = iv; - let ct = new Uint8Array(); - const process = chunk => { - if (chunk) { - ct = util.concatUint8Array([ct, chunk]); - } - const plaintext = new Uint8Array(ct.length); - let i; - let j = 0; - while (chunk ? ct.length >= block_size : ct.length) { - const decblock = cipherfn.encrypt(blockp); - blockp = ct; - for (i = 0; i < block_size; i++) { - plaintext[j++] = blockp[i] ^ decblock[i]; - } - ct = ct.subarray(block_size); - } - return plaintext.subarray(0, j); - }; - return transform(ciphertext, process, process); -} - -function aesEncrypt(algo, key, pt, iv, config) { - if ( - util.getWebCrypto() && - key.length !== 24 && // Chrome doesn't support 192 bit keys, see https://www.chromium.org/blink/webcrypto#TOC-AES-support - !util.isStream(pt) && - pt.length >= 3000 * config.minBytesForWebCrypto // Default to a 3MB minimum. Chrome is pretty slow for small messages, see: https://bugs.chromium.org/p/chromium/issues/detail?id=701188#c2 - ) { // Web Crypto - return webEncrypt(algo, key, pt, iv); - } - // asm.js fallback - const cfb = new AES_CFB(key, iv); - return transform(pt, value => cfb.aes.AES_Encrypt_process(value), () => cfb.aes.AES_Encrypt_finish()); -} - -function aesDecrypt(algo, key, ct, iv) { - if (util.isStream(ct)) { - const cfb = new AES_CFB(key, iv); - return transform(ct, value => cfb.aes.AES_Decrypt_process(value), () => cfb.aes.AES_Decrypt_finish()); - } - return AES_CFB.decrypt(ct, key, iv); -} - -function xorMut(a, b) { - for (let i = 0; i < a.length; i++) { - a[i] = a[i] ^ b[i]; - } -} - -async function webEncrypt(algo, key, pt, iv) { - const ALGO = 'AES-CBC'; - const _key = await webCrypto$1.importKey('raw', key, { name: ALGO }, false, ['encrypt']); - const { blockSize } = crypto.getCipher(algo); - const cbc_pt = util.concatUint8Array([new Uint8Array(blockSize), pt]); - const ct = new Uint8Array(await webCrypto$1.encrypt({ name: ALGO, iv }, _key, cbc_pt)).subarray(0, pt.length); - xorMut(ct, pt); - return ct; -} - -function nodeEncrypt(algo, key, pt, iv) { - const algoName = enums.read(enums.symmetric, algo); - const cipherObj = new nodeCrypto$1.createCipheriv(nodeAlgos[algoName], key, iv); - return transform(pt, value => new Uint8Array(cipherObj.update(value))); -} - -function nodeDecrypt(algo, key, ct, iv) { - const algoName = enums.read(enums.symmetric, algo); - const decipherObj = new nodeCrypto$1.createDecipheriv(nodeAlgos[algoName], key, iv); - return transform(ct, value => new Uint8Array(decipherObj.update(value))); -} - -var cfb = /*#__PURE__*/Object.freeze({ - __proto__: null, - encrypt: encrypt, - decrypt: decrypt -}); - -class AES_CTR { - static encrypt(data, key, nonce) { - return new AES_CTR(key, nonce).encrypt(data); - } - static decrypt(data, key, nonce) { - return new AES_CTR(key, nonce).encrypt(data); - } - constructor(key, nonce, aes) { - this.aes = aes ? aes : new AES(key, undefined, false, 'CTR'); - delete this.aes.padding; - this.AES_CTR_set_options(nonce); - } - encrypt(data) { - const r1 = this.aes.AES_Encrypt_process(data); - const r2 = this.aes.AES_Encrypt_finish(); - return joinBytes(r1, r2); - } - decrypt(data) { - const r1 = this.aes.AES_Encrypt_process(data); - const r2 = this.aes.AES_Encrypt_finish(); - return joinBytes(r1, r2); - } - AES_CTR_set_options(nonce, counter, size) { - let { asm } = this.aes.acquire_asm(); - if (size !== undefined) { - if (size < 8 || size > 48) - throw new IllegalArgumentError('illegal counter size'); - let mask = Math.pow(2, size) - 1; - asm.set_mask(0, 0, (mask / 0x100000000) | 0, mask | 0); - } - else { - size = 48; - asm.set_mask(0, 0, 0xffff, 0xffffffff); - } - if (nonce !== undefined) { - let len = nonce.length; - if (!len || len > 16) - throw new IllegalArgumentError('illegal nonce size'); - let view = new DataView(new ArrayBuffer(16)); - new Uint8Array(view.buffer).set(nonce); - asm.set_nonce(view.getUint32(0), view.getUint32(4), view.getUint32(8), view.getUint32(12)); - } - else { - throw new Error('nonce is required'); - } - if (counter !== undefined) { - if (counter < 0 || counter >= Math.pow(2, size)) - throw new IllegalArgumentError('illegal counter value'); - asm.set_counter(0, 0, (counter / 0x100000000) | 0, counter | 0); - } - } -} - -class AES_CBC { - static encrypt(data, key, padding = true, iv) { - return new AES_CBC(key, iv, padding).encrypt(data); - } - static decrypt(data, key, padding = true, iv) { - return new AES_CBC(key, iv, padding).decrypt(data); - } - constructor(key, iv, padding = true, aes) { - this.aes = aes ? aes : new AES(key, iv, padding, 'CBC'); - } - encrypt(data) { - const r1 = this.aes.AES_Encrypt_process(data); - const r2 = this.aes.AES_Encrypt_finish(); - return joinBytes(r1, r2); - } - decrypt(data) { - const r1 = this.aes.AES_Decrypt_process(data); - const r2 = this.aes.AES_Decrypt_finish(); - return joinBytes(r1, r2); - } -} - -/** - * @fileoverview This module implements AES-CMAC on top of - * native AES-CBC using either the WebCrypto API or Node.js' crypto API. - * @module crypto/cmac - * @private - */ - -const webCrypto$2 = util.getWebCrypto(); -const nodeCrypto$2 = util.getNodeCrypto(); - - -/** - * This implementation of CMAC is based on the description of OMAC in - * http://web.cs.ucdavis.edu/~rogaway/papers/eax.pdf. As per that - * document: - * - * We have made a small modification to the OMAC algorithm as it was - * originally presented, changing one of its two constants. - * Specifically, the constant 4 at line 85 was the constant 1/2 (the - * multiplicative inverse of 2) in the original definition of OMAC [14]. - * The OMAC authors indicate that they will promulgate this modification - * [15], which slightly simplifies implementations. - */ - -const blockLength = 16; - - -/** - * xor `padding` into the end of `data`. This function implements "the - * operation xor→ [which] xors the shorter string into the end of longer - * one". Since data is always as least as long as padding, we can - * simplify the implementation. - * @param {Uint8Array} data - * @param {Uint8Array} padding - */ -function rightXORMut(data, padding) { - const offset = data.length - blockLength; - for (let i = 0; i < blockLength; i++) { - data[i + offset] ^= padding[i]; - } - return data; -} - -function pad(data, padding, padding2) { - // if |M| in {n, 2n, 3n, ...} - if (data.length && data.length % blockLength === 0) { - // then return M xor→ B, - return rightXORMut(data, padding); - } - // else return (M || 10^(n−1−(|M| mod n))) xor→ P - const padded = new Uint8Array(data.length + (blockLength - data.length % blockLength)); - padded.set(data); - padded[data.length] = 0b10000000; - return rightXORMut(padded, padding2); -} - -const zeroBlock = new Uint8Array(blockLength); - -async function CMAC(key) { - const cbc = await CBC(key); - - // L ← E_K(0^n); B ← 2L; P ← 4L - const padding = util.double(await cbc(zeroBlock)); - const padding2 = util.double(padding); - - return async function(data) { - // return CBC_K(pad(M; B, P)) - return (await cbc(pad(data, padding, padding2))).subarray(-blockLength); - }; -} - -async function CBC(key) { - if (util.getWebCrypto() && key.length !== 24) { // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support - key = await webCrypto$2.importKey('raw', key, { name: 'AES-CBC', length: key.length * 8 }, false, ['encrypt']); - return async function(pt) { - const ct = await webCrypto$2.encrypt({ name: 'AES-CBC', iv: zeroBlock, length: blockLength * 8 }, key, pt); - return new Uint8Array(ct).subarray(0, ct.byteLength - blockLength); - }; - } - if (util.getNodeCrypto()) { // Node crypto library - return async function(pt) { - const en = new nodeCrypto$2.createCipheriv('aes-' + (key.length * 8) + '-cbc', key, zeroBlock); - const ct = en.update(pt); - return new Uint8Array(ct); - }; - } - // asm.js fallback - return async function(pt) { - return AES_CBC.encrypt(pt, key, false, zeroBlock); - }; -} - -// OpenPGP.js - An OpenPGP implementation in javascript - -const webCrypto$3 = util.getWebCrypto(); -const nodeCrypto$3 = util.getNodeCrypto(); -const Buffer$1 = util.getNodeBuffer(); - - -const blockLength$1 = 16; -const ivLength = blockLength$1; -const tagLength = blockLength$1; - -const zero = new Uint8Array(blockLength$1); -const one = new Uint8Array(blockLength$1); one[blockLength$1 - 1] = 1; -const two = new Uint8Array(blockLength$1); two[blockLength$1 - 1] = 2; - -async function OMAC(key) { - const cmac = await CMAC(key); - return function(t, message) { - return cmac(util.concatUint8Array([t, message])); - }; -} - -async function CTR(key) { - if ( - util.getWebCrypto() && - key.length !== 24 && // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support - (!navigator.userAgent || navigator.userAgent.indexOf('Edge') === -1) - ) { - key = await webCrypto$3.importKey('raw', key, { name: 'AES-CTR', length: key.length * 8 }, false, ['encrypt']); - return async function(pt, iv) { - const ct = await webCrypto$3.encrypt({ name: 'AES-CTR', counter: iv, length: blockLength$1 * 8 }, key, pt); - return new Uint8Array(ct); - }; - } - if (util.getNodeCrypto()) { // Node crypto library - return async function(pt, iv) { - const en = new nodeCrypto$3.createCipheriv('aes-' + (key.length * 8) + '-ctr', key, iv); - const ct = Buffer$1.concat([en.update(pt), en.final()]); - return new Uint8Array(ct); - }; - } - // asm.js fallback - return async function(pt, iv) { - return AES_CTR.encrypt(pt, key, iv); - }; -} - - -/** - * Class to en/decrypt using EAX mode. - * @param {enums.symmetric} cipher - The symmetric cipher algorithm to use - * @param {Uint8Array} key - The encryption key - */ -async function EAX(cipher, key) { - if (cipher !== enums.symmetric.aes128 && - cipher !== enums.symmetric.aes192 && - cipher !== enums.symmetric.aes256) { - throw new Error('EAX mode supports only AES cipher'); - } - - const [ - omac, - ctr - ] = await Promise.all([ - OMAC(key), - CTR(key) - ]); - - return { - /** - * Encrypt plaintext input. - * @param {Uint8Array} plaintext - The cleartext input to be encrypted - * @param {Uint8Array} nonce - The nonce (16 bytes) - * @param {Uint8Array} adata - Associated data to sign - * @returns {Promise} The ciphertext output. - */ - encrypt: async function(plaintext, nonce, adata) { - const [ - omacNonce, - omacAdata - ] = await Promise.all([ - omac(zero, nonce), - omac(one, adata) - ]); - const ciphered = await ctr(plaintext, omacNonce); - const omacCiphered = await omac(two, ciphered); - const tag = omacCiphered; // Assumes that omac(*).length === tagLength. - for (let i = 0; i < tagLength; i++) { - tag[i] ^= omacAdata[i] ^ omacNonce[i]; - } - return util.concatUint8Array([ciphered, tag]); - }, - - /** - * Decrypt ciphertext input. - * @param {Uint8Array} ciphertext - The ciphertext input to be decrypted - * @param {Uint8Array} nonce - The nonce (16 bytes) - * @param {Uint8Array} adata - Associated data to verify - * @returns {Promise} The plaintext output. - */ - decrypt: async function(ciphertext, nonce, adata) { - if (ciphertext.length < tagLength) throw new Error('Invalid EAX ciphertext'); - const ciphered = ciphertext.subarray(0, -tagLength); - const ctTag = ciphertext.subarray(-tagLength); - const [ - omacNonce, - omacAdata, - omacCiphered - ] = await Promise.all([ - omac(zero, nonce), - omac(one, adata), - omac(two, ciphered) - ]); - const tag = omacCiphered; // Assumes that omac(*).length === tagLength. - for (let i = 0; i < tagLength; i++) { - tag[i] ^= omacAdata[i] ^ omacNonce[i]; - } - if (!util.equalsUint8Array(ctTag, tag)) throw new Error('Authentication tag mismatch'); - const plaintext = await ctr(ciphered, omacNonce); - return plaintext; - } - }; -} - - -/** - * Get EAX nonce as defined by {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.1|RFC4880bis-04, section 5.16.1}. - * @param {Uint8Array} iv - The initialization vector (16 bytes) - * @param {Uint8Array} chunkIndex - The chunk index (8 bytes) - */ -EAX.getNonce = function(iv, chunkIndex) { - const nonce = iv.slice(); - for (let i = 0; i < chunkIndex.length; i++) { - nonce[8 + i] ^= chunkIndex[i]; - } - return nonce; -}; - -EAX.blockLength = blockLength$1; -EAX.ivLength = ivLength; -EAX.tagLength = tagLength; - -// OpenPGP.js - An OpenPGP implementation in javascript - -const blockLength$2 = 16; -const ivLength$1 = 15; - -// https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.2: -// While OCB [RFC7253] allows the authentication tag length to be of any -// number up to 128 bits long, this document requires a fixed -// authentication tag length of 128 bits (16 octets) for simplicity. -const tagLength$1 = 16; - - -function ntz(n) { - let ntz = 0; - for (let i = 1; (n & i) === 0; i <<= 1) { - ntz++; - } - return ntz; -} - -function xorMut$1(S, T) { - for (let i = 0; i < S.length; i++) { - S[i] ^= T[i]; - } - return S; -} - -function xor(S, T) { - return xorMut$1(S.slice(), T); -} - -const zeroBlock$1 = new Uint8Array(blockLength$2); -const one$1 = new Uint8Array([1]); - -/** - * Class to en/decrypt using OCB mode. - * @param {enums.symmetric} cipher - The symmetric cipher algorithm to use - * @param {Uint8Array} key - The encryption key - */ -async function OCB(cipher$1, key) { - - let maxNtz = 0; - let encipher; - let decipher; - let mask; - - constructKeyVariables(cipher$1, key); - - function constructKeyVariables(cipher$1, key) { - const cipherName = enums.read(enums.symmetric, cipher$1); - const aes = new cipher[cipherName](key); - encipher = aes.encrypt.bind(aes); - decipher = aes.decrypt.bind(aes); - - const mask_x = encipher(zeroBlock$1); - const mask_$ = util.double(mask_x); - mask = []; - mask[0] = util.double(mask_$); - - - mask.x = mask_x; - mask.$ = mask_$; - } - - function extendKeyVariables(text, adata) { - const newMaxNtz = util.nbits(Math.max(text.length, adata.length) / blockLength$2 | 0) - 1; - for (let i = maxNtz + 1; i <= newMaxNtz; i++) { - mask[i] = util.double(mask[i - 1]); - } - maxNtz = newMaxNtz; - } - - function hash(adata) { - if (!adata.length) { - // Fast path - return zeroBlock$1; - } - - // - // Consider A as a sequence of 128-bit blocks - // - const m = adata.length / blockLength$2 | 0; - - const offset = new Uint8Array(blockLength$2); - const sum = new Uint8Array(blockLength$2); - for (let i = 0; i < m; i++) { - xorMut$1(offset, mask[ntz(i + 1)]); - xorMut$1(sum, encipher(xor(offset, adata))); - adata = adata.subarray(blockLength$2); - } - - // - // Process any final partial block; compute final hash value - // - if (adata.length) { - xorMut$1(offset, mask.x); - - const cipherInput = new Uint8Array(blockLength$2); - cipherInput.set(adata, 0); - cipherInput[adata.length] = 0b10000000; - xorMut$1(cipherInput, offset); - - xorMut$1(sum, encipher(cipherInput)); - } - - return sum; - } - - /** - * Encrypt/decrypt data. - * @param {encipher|decipher} fn - Encryption/decryption block cipher function - * @param {Uint8Array} text - The cleartext or ciphertext (without tag) input - * @param {Uint8Array} nonce - The nonce (15 bytes) - * @param {Uint8Array} adata - Associated data to sign - * @returns {Promise} The ciphertext or plaintext output, with tag appended in both cases. - */ - function crypt(fn, text, nonce, adata) { - // - // Consider P as a sequence of 128-bit blocks - // - const m = text.length / blockLength$2 | 0; - - // - // Key-dependent variables - // - extendKeyVariables(text, adata); - - // - // Nonce-dependent and per-encryption variables - // - // Nonce = num2str(TAGLEN mod 128,7) || zeros(120-bitlen(N)) || 1 || N - // Note: We assume here that tagLength mod 16 == 0. - const paddedNonce = util.concatUint8Array([zeroBlock$1.subarray(0, ivLength$1 - nonce.length), one$1, nonce]); - // bottom = str2num(Nonce[123..128]) - const bottom = paddedNonce[blockLength$2 - 1] & 0b111111; - // Ktop = ENCIPHER(K, Nonce[1..122] || zeros(6)) - paddedNonce[blockLength$2 - 1] &= 0b11000000; - const kTop = encipher(paddedNonce); - // Stretch = Ktop || (Ktop[1..64] xor Ktop[9..72]) - const stretched = util.concatUint8Array([kTop, xor(kTop.subarray(0, 8), kTop.subarray(1, 9))]); - // Offset_0 = Stretch[1+bottom..128+bottom] - const offset = util.shiftRight(stretched.subarray(0 + (bottom >> 3), 17 + (bottom >> 3)), 8 - (bottom & 7)).subarray(1); - // Checksum_0 = zeros(128) - const checksum = new Uint8Array(blockLength$2); - - const ct = new Uint8Array(text.length + tagLength$1); - - // - // Process any whole blocks - // - let i; - let pos = 0; - for (i = 0; i < m; i++) { - // Offset_i = Offset_{i-1} xor L_{ntz(i)} - xorMut$1(offset, mask[ntz(i + 1)]); - // C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) - // P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i) - ct.set(xorMut$1(fn(xor(offset, text)), offset), pos); - // Checksum_i = Checksum_{i-1} xor P_i - xorMut$1(checksum, fn === encipher ? text : ct.subarray(pos)); - - text = text.subarray(blockLength$2); - pos += blockLength$2; - } - - // - // Process any final partial block and compute raw tag - // - if (text.length) { - // Offset_* = Offset_m xor L_* - xorMut$1(offset, mask.x); - // Pad = ENCIPHER(K, Offset_*) - const padding = encipher(offset); - // C_* = P_* xor Pad[1..bitlen(P_*)] - ct.set(xor(text, padding), pos); - - // Checksum_* = Checksum_m xor (P_* || 1 || new Uint8Array(127-bitlen(P_*))) - const xorInput = new Uint8Array(blockLength$2); - xorInput.set(fn === encipher ? text : ct.subarray(pos, -tagLength$1), 0); - xorInput[text.length] = 0b10000000; - xorMut$1(checksum, xorInput); - pos += text.length; - } - // Tag = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) xor HASH(K,A) - const tag = xorMut$1(encipher(xorMut$1(xorMut$1(checksum, offset), mask.$)), hash(adata)); - - // - // Assemble ciphertext - // - // C = C_1 || C_2 || ... || C_m || C_* || Tag[1..TAGLEN] - ct.set(tag, pos); - return ct; - } - - - return { - /** - * Encrypt plaintext input. - * @param {Uint8Array} plaintext - The cleartext input to be encrypted - * @param {Uint8Array} nonce - The nonce (15 bytes) - * @param {Uint8Array} adata - Associated data to sign - * @returns {Promise} The ciphertext output. - */ - encrypt: async function(plaintext, nonce, adata) { - return crypt(encipher, plaintext, nonce, adata); - }, - - /** - * Decrypt ciphertext input. - * @param {Uint8Array} ciphertext - The ciphertext input to be decrypted - * @param {Uint8Array} nonce - The nonce (15 bytes) - * @param {Uint8Array} adata - Associated data to sign - * @returns {Promise} The ciphertext output. - */ - decrypt: async function(ciphertext, nonce, adata) { - if (ciphertext.length < tagLength$1) throw new Error('Invalid OCB ciphertext'); - - const tag = ciphertext.subarray(-tagLength$1); - ciphertext = ciphertext.subarray(0, -tagLength$1); - - const crypted = crypt(decipher, ciphertext, nonce, adata); - // if (Tag[1..TAGLEN] == T) - if (util.equalsUint8Array(tag, crypted.subarray(-tagLength$1))) { - return crypted.subarray(0, -tagLength$1); - } - throw new Error('Authentication tag mismatch'); - } - }; -} - - -/** - * Get OCB nonce as defined by {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.2|RFC4880bis-04, section 5.16.2}. - * @param {Uint8Array} iv - The initialization vector (15 bytes) - * @param {Uint8Array} chunkIndex - The chunk index (8 bytes) - */ -OCB.getNonce = function(iv, chunkIndex) { - const nonce = iv.slice(); - for (let i = 0; i < chunkIndex.length; i++) { - nonce[7 + i] ^= chunkIndex[i]; - } - return nonce; -}; - -OCB.blockLength = blockLength$2; -OCB.ivLength = ivLength$1; -OCB.tagLength = tagLength$1; - -const _AES_GCM_data_maxLength = 68719476704; // 2^36 - 2^5 -class AES_GCM { - constructor(key, nonce, adata, tagSize = 16, aes) { - this.tagSize = tagSize; - this.gamma0 = 0; - this.counter = 1; - this.aes = aes ? aes : new AES(key, undefined, false, 'CTR'); - let { asm, heap } = this.aes.acquire_asm(); - // Init GCM - asm.gcm_init(); - // Tag size - if (this.tagSize < 4 || this.tagSize > 16) - throw new IllegalArgumentError('illegal tagSize value'); - // Nonce - const noncelen = nonce.length || 0; - const noncebuf = new Uint8Array(16); - if (noncelen !== 12) { - this._gcm_mac_process(nonce); - heap[0] = 0; - heap[1] = 0; - heap[2] = 0; - heap[3] = 0; - heap[4] = 0; - heap[5] = 0; - heap[6] = 0; - heap[7] = 0; - heap[8] = 0; - heap[9] = 0; - heap[10] = 0; - heap[11] = noncelen >>> 29; - heap[12] = (noncelen >>> 21) & 255; - heap[13] = (noncelen >>> 13) & 255; - heap[14] = (noncelen >>> 5) & 255; - heap[15] = (noncelen << 3) & 255; - asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16); - asm.get_iv(AES_asm.HEAP_DATA); - asm.set_iv(0, 0, 0, 0); - noncebuf.set(heap.subarray(0, 16)); - } - else { - noncebuf.set(nonce); - noncebuf[15] = 1; - } - const nonceview = new DataView(noncebuf.buffer); - this.gamma0 = nonceview.getUint32(12); - asm.set_nonce(nonceview.getUint32(0), nonceview.getUint32(4), nonceview.getUint32(8), 0); - asm.set_mask(0, 0, 0, 0xffffffff); - // Associated data - if (adata !== undefined) { - if (adata.length > _AES_GCM_data_maxLength) - throw new IllegalArgumentError('illegal adata length'); - if (adata.length) { - this.adata = adata; - this._gcm_mac_process(adata); - } - else { - this.adata = undefined; - } - } - else { - this.adata = undefined; - } - // Counter - if (this.counter < 1 || this.counter > 0xffffffff) - throw new RangeError('counter must be a positive 32-bit integer'); - asm.set_counter(0, 0, 0, (this.gamma0 + this.counter) | 0); - } - static encrypt(cleartext, key, nonce, adata, tagsize) { - return new AES_GCM(key, nonce, adata, tagsize).encrypt(cleartext); - } - static decrypt(ciphertext, key, nonce, adata, tagsize) { - return new AES_GCM(key, nonce, adata, tagsize).decrypt(ciphertext); - } - encrypt(data) { - return this.AES_GCM_encrypt(data); - } - decrypt(data) { - return this.AES_GCM_decrypt(data); - } - AES_GCM_Encrypt_process(data) { - let dpos = 0; - let dlen = data.length || 0; - let { asm, heap } = this.aes.acquire_asm(); - let counter = this.counter; - let pos = this.aes.pos; - let len = this.aes.len; - let rpos = 0; - let rlen = (len + dlen) & -16; - let wlen = 0; - if (((counter - 1) << 4) + len + dlen > _AES_GCM_data_maxLength) - throw new RangeError('counter overflow'); - const result = new Uint8Array(rlen); - while (dlen > 0) { - wlen = _heap_write(heap, pos + len, data, dpos, dlen); - len += wlen; - dpos += wlen; - dlen -= wlen; - wlen = asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, len); - wlen = asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, wlen); - if (wlen) - result.set(heap.subarray(pos, pos + wlen), rpos); - counter += wlen >>> 4; - rpos += wlen; - if (wlen < len) { - pos += wlen; - len -= wlen; - } - else { - pos = 0; - len = 0; - } - } - this.counter = counter; - this.aes.pos = pos; - this.aes.len = len; - return result; - } - AES_GCM_Encrypt_finish() { - let { asm, heap } = this.aes.acquire_asm(); - let counter = this.counter; - let tagSize = this.tagSize; - let adata = this.adata; - let pos = this.aes.pos; - let len = this.aes.len; - const result = new Uint8Array(len + tagSize); - asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, (len + 15) & -16); - if (len) - result.set(heap.subarray(pos, pos + len)); - let i = len; - for (; i & 15; i++) - heap[pos + i] = 0; - asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, i); - const alen = adata !== undefined ? adata.length : 0; - const clen = ((counter - 1) << 4) + len; - heap[0] = 0; - heap[1] = 0; - heap[2] = 0; - heap[3] = alen >>> 29; - heap[4] = alen >>> 21; - heap[5] = (alen >>> 13) & 255; - heap[6] = (alen >>> 5) & 255; - heap[7] = (alen << 3) & 255; - heap[8] = heap[9] = heap[10] = 0; - heap[11] = clen >>> 29; - heap[12] = (clen >>> 21) & 255; - heap[13] = (clen >>> 13) & 255; - heap[14] = (clen >>> 5) & 255; - heap[15] = (clen << 3) & 255; - asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16); - asm.get_iv(AES_asm.HEAP_DATA); - asm.set_counter(0, 0, 0, this.gamma0); - asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16); - result.set(heap.subarray(0, tagSize), len); - this.counter = 1; - this.aes.pos = 0; - this.aes.len = 0; - return result; - } - AES_GCM_Decrypt_process(data) { - let dpos = 0; - let dlen = data.length || 0; - let { asm, heap } = this.aes.acquire_asm(); - let counter = this.counter; - let tagSize = this.tagSize; - let pos = this.aes.pos; - let len = this.aes.len; - let rpos = 0; - let rlen = len + dlen > tagSize ? (len + dlen - tagSize) & -16 : 0; - let tlen = len + dlen - rlen; - let wlen = 0; - if (((counter - 1) << 4) + len + dlen > _AES_GCM_data_maxLength) - throw new RangeError('counter overflow'); - const result = new Uint8Array(rlen); - while (dlen > tlen) { - wlen = _heap_write(heap, pos + len, data, dpos, dlen - tlen); - len += wlen; - dpos += wlen; - dlen -= wlen; - wlen = asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, wlen); - wlen = asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, wlen); - if (wlen) - result.set(heap.subarray(pos, pos + wlen), rpos); - counter += wlen >>> 4; - rpos += wlen; - pos = 0; - len = 0; - } - if (dlen > 0) { - len += _heap_write(heap, 0, data, dpos, dlen); - } - this.counter = counter; - this.aes.pos = pos; - this.aes.len = len; - return result; - } - AES_GCM_Decrypt_finish() { - let { asm, heap } = this.aes.acquire_asm(); - let tagSize = this.tagSize; - let adata = this.adata; - let counter = this.counter; - let pos = this.aes.pos; - let len = this.aes.len; - let rlen = len - tagSize; - if (len < tagSize) - throw new IllegalStateError('authentication tag not found'); - const result = new Uint8Array(rlen); - const atag = new Uint8Array(heap.subarray(pos + rlen, pos + len)); - let i = rlen; - for (; i & 15; i++) - heap[pos + i] = 0; - asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, i); - asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, i); - if (rlen) - result.set(heap.subarray(pos, pos + rlen)); - const alen = adata !== undefined ? adata.length : 0; - const clen = ((counter - 1) << 4) + len - tagSize; - heap[0] = 0; - heap[1] = 0; - heap[2] = 0; - heap[3] = alen >>> 29; - heap[4] = alen >>> 21; - heap[5] = (alen >>> 13) & 255; - heap[6] = (alen >>> 5) & 255; - heap[7] = (alen << 3) & 255; - heap[8] = heap[9] = heap[10] = 0; - heap[11] = clen >>> 29; - heap[12] = (clen >>> 21) & 255; - heap[13] = (clen >>> 13) & 255; - heap[14] = (clen >>> 5) & 255; - heap[15] = (clen << 3) & 255; - asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16); - asm.get_iv(AES_asm.HEAP_DATA); - asm.set_counter(0, 0, 0, this.gamma0); - asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16); - let acheck = 0; - for (let i = 0; i < tagSize; ++i) - acheck |= atag[i] ^ heap[i]; - if (acheck) - throw new SecurityError('data integrity check failed'); - this.counter = 1; - this.aes.pos = 0; - this.aes.len = 0; - return result; - } - AES_GCM_decrypt(data) { - const result1 = this.AES_GCM_Decrypt_process(data); - const result2 = this.AES_GCM_Decrypt_finish(); - const result = new Uint8Array(result1.length + result2.length); - if (result1.length) - result.set(result1); - if (result2.length) - result.set(result2, result1.length); - return result; - } - AES_GCM_encrypt(data) { - const result1 = this.AES_GCM_Encrypt_process(data); - const result2 = this.AES_GCM_Encrypt_finish(); - const result = new Uint8Array(result1.length + result2.length); - if (result1.length) - result.set(result1); - if (result2.length) - result.set(result2, result1.length); - return result; - } - _gcm_mac_process(data) { - let { asm, heap } = this.aes.acquire_asm(); - let dpos = 0; - let dlen = data.length || 0; - let wlen = 0; - while (dlen > 0) { - wlen = _heap_write(heap, 0, data, dpos, dlen); - dpos += wlen; - dlen -= wlen; - while (wlen & 15) - heap[wlen++] = 0; - asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, wlen); - } - } -} - -// OpenPGP.js - An OpenPGP implementation in javascript - -const webCrypto$4 = util.getWebCrypto(); -const nodeCrypto$4 = util.getNodeCrypto(); -const Buffer$2 = util.getNodeBuffer(); - -const blockLength$3 = 16; -const ivLength$2 = 12; // size of the IV in bytes -const tagLength$2 = 16; // size of the tag in bytes -const ALGO = 'AES-GCM'; - -/** - * Class to en/decrypt using GCM mode. - * @param {enums.symmetric} cipher - The symmetric cipher algorithm to use - * @param {Uint8Array} key - The encryption key - */ -async function GCM(cipher, key) { - if (cipher !== enums.symmetric.aes128 && - cipher !== enums.symmetric.aes192 && - cipher !== enums.symmetric.aes256) { - throw new Error('GCM mode supports only AES cipher'); - } - - if (util.getWebCrypto() && key.length !== 24) { // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support - const _key = await webCrypto$4.importKey('raw', key, { name: ALGO }, false, ['encrypt', 'decrypt']); - - return { - encrypt: async function(pt, iv, adata = new Uint8Array()) { - if ( - !pt.length || - // iOS does not support GCM-en/decrypting empty messages - // Also, synchronous en/decryption might be faster in this case. - (!adata.length && navigator.userAgent && navigator.userAgent.indexOf('Edge') !== -1) - // Edge does not support GCM-en/decrypting without ADATA - ) { - return AES_GCM.encrypt(pt, key, iv, adata); - } - const ct = await webCrypto$4.encrypt({ name: ALGO, iv, additionalData: adata, tagLength: tagLength$2 * 8 }, _key, pt); - return new Uint8Array(ct); - }, - - decrypt: async function(ct, iv, adata = new Uint8Array()) { - if ( - ct.length === tagLength$2 || - // iOS does not support GCM-en/decrypting empty messages - // Also, synchronous en/decryption might be faster in this case. - (!adata.length && navigator.userAgent && navigator.userAgent.indexOf('Edge') !== -1) - // Edge does not support GCM-en/decrypting without ADATA - ) { - return AES_GCM.decrypt(ct, key, iv, adata); - } - const pt = await webCrypto$4.decrypt({ name: ALGO, iv, additionalData: adata, tagLength: tagLength$2 * 8 }, _key, ct); - return new Uint8Array(pt); - } - }; - } - - if (util.getNodeCrypto()) { // Node crypto library - return { - encrypt: async function(pt, iv, adata = new Uint8Array()) { - const en = new nodeCrypto$4.createCipheriv('aes-' + (key.length * 8) + '-gcm', key, iv); - en.setAAD(adata); - const ct = Buffer$2.concat([en.update(pt), en.final(), en.getAuthTag()]); // append auth tag to ciphertext - return new Uint8Array(ct); - }, - - decrypt: async function(ct, iv, adata = new Uint8Array()) { - const de = new nodeCrypto$4.createDecipheriv('aes-' + (key.length * 8) + '-gcm', key, iv); - de.setAAD(adata); - de.setAuthTag(ct.slice(ct.length - tagLength$2, ct.length)); // read auth tag at end of ciphertext - const pt = Buffer$2.concat([de.update(ct.slice(0, ct.length - tagLength$2)), de.final()]); - return new Uint8Array(pt); - } - }; - } - - return { - encrypt: async function(pt, iv, adata) { - return AES_GCM.encrypt(pt, key, iv, adata); - }, - - decrypt: async function(ct, iv, adata) { - return AES_GCM.decrypt(ct, key, iv, adata); - } - }; -} - - -/** - * Get GCM nonce. Note: this operation is not defined by the standard. - * A future version of the standard may define GCM mode differently, - * hopefully under a different ID (we use Private/Experimental algorithm - * ID 100) so that we can maintain backwards compatibility. - * @param {Uint8Array} iv - The initialization vector (12 bytes) - * @param {Uint8Array} chunkIndex - The chunk index (8 bytes) - */ -GCM.getNonce = function(iv, chunkIndex) { - const nonce = iv.slice(); - for (let i = 0; i < chunkIndex.length; i++) { - nonce[4 + i] ^= chunkIndex[i]; - } - return nonce; -}; - -GCM.blockLength = blockLength$3; -GCM.ivLength = ivLength$2; -GCM.tagLength = tagLength$2; - -/** - * @fileoverview Cipher modes - * @module crypto/mode - * @private - */ - -var mode = { - /** @see module:crypto/mode/cfb */ - cfb: cfb, - /** @see module:crypto/mode/gcm */ - gcm: GCM, - experimentalGCM: GCM, - /** @see module:crypto/mode/eax */ - eax: EAX, - /** @see module:crypto/mode/ocb */ - ocb: OCB -}; - -var naclFastLight = createCommonjsModule(function (module) { -/*jshint bitwise: false*/ - -(function(nacl) { - -// Ported in 2014 by Dmitry Chestnykh and Devi Mandiri. -// Public domain. -// -// Implementation derived from TweetNaCl version 20140427. -// See for details: http://tweetnacl.cr.yp.to/ - -var gf = function(init) { - var i, r = new Float64Array(16); - if (init) for (i = 0; i < init.length; i++) r[i] = init[i]; - return r; -}; - -// Pluggable, initialized in high-level API below. -var randombytes = function(/* x, n */) { throw new Error('no PRNG'); }; - -var _9 = new Uint8Array(32); _9[0] = 9; - -var gf0 = gf(), - gf1 = gf([1]), - _121665 = gf([0xdb41, 1]), - D = gf([0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203]), - D2 = gf([0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406]), - X = gf([0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169]), - Y = gf([0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666]), - I = gf([0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83]); - -function vn(x, xi, y, yi, n) { - var i,d = 0; - for (i = 0; i < n; i++) d |= x[xi+i]^y[yi+i]; - return (1 & ((d - 1) >>> 8)) - 1; -} - -function crypto_verify_32(x, xi, y, yi) { - return vn(x,xi,y,yi,32); -} - -function set25519(r, a) { - var i; - for (i = 0; i < 16; i++) r[i] = a[i]|0; -} - -function car25519(o) { - var i, v, c = 1; - for (i = 0; i < 16; i++) { - v = o[i] + c + 65535; - c = Math.floor(v / 65536); - o[i] = v - c * 65536; - } - o[0] += c-1 + 37 * (c-1); -} - -function sel25519(p, q, b) { - var t, c = ~(b-1); - for (var i = 0; i < 16; i++) { - t = c & (p[i] ^ q[i]); - p[i] ^= t; - q[i] ^= t; - } -} - -function pack25519(o, n) { - var i, j, b; - var m = gf(), t = gf(); - for (i = 0; i < 16; i++) t[i] = n[i]; - car25519(t); - car25519(t); - car25519(t); - for (j = 0; j < 2; j++) { - m[0] = t[0] - 0xffed; - for (i = 1; i < 15; i++) { - m[i] = t[i] - 0xffff - ((m[i-1]>>16) & 1); - m[i-1] &= 0xffff; - } - m[15] = t[15] - 0x7fff - ((m[14]>>16) & 1); - b = (m[15]>>16) & 1; - m[14] &= 0xffff; - sel25519(t, m, 1-b); - } - for (i = 0; i < 16; i++) { - o[2*i] = t[i] & 0xff; - o[2*i+1] = t[i]>>8; - } -} - -function neq25519(a, b) { - var c = new Uint8Array(32), d = new Uint8Array(32); - pack25519(c, a); - pack25519(d, b); - return crypto_verify_32(c, 0, d, 0); -} - -function par25519(a) { - var d = new Uint8Array(32); - pack25519(d, a); - return d[0] & 1; -} - -function unpack25519(o, n) { - var i; - for (i = 0; i < 16; i++) o[i] = n[2*i] + (n[2*i+1] << 8); - o[15] &= 0x7fff; -} - -function A(o, a, b) { - for (var i = 0; i < 16; i++) o[i] = a[i] + b[i]; -} - -function Z(o, a, b) { - for (var i = 0; i < 16; i++) o[i] = a[i] - b[i]; -} - -function M(o, a, b) { - var v, c, - t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0, - t8 = 0, t9 = 0, t10 = 0, t11 = 0, t12 = 0, t13 = 0, t14 = 0, t15 = 0, - t16 = 0, t17 = 0, t18 = 0, t19 = 0, t20 = 0, t21 = 0, t22 = 0, t23 = 0, - t24 = 0, t25 = 0, t26 = 0, t27 = 0, t28 = 0, t29 = 0, t30 = 0, - b0 = b[0], - b1 = b[1], - b2 = b[2], - b3 = b[3], - b4 = b[4], - b5 = b[5], - b6 = b[6], - b7 = b[7], - b8 = b[8], - b9 = b[9], - b10 = b[10], - b11 = b[11], - b12 = b[12], - b13 = b[13], - b14 = b[14], - b15 = b[15]; - - v = a[0]; - t0 += v * b0; - t1 += v * b1; - t2 += v * b2; - t3 += v * b3; - t4 += v * b4; - t5 += v * b5; - t6 += v * b6; - t7 += v * b7; - t8 += v * b8; - t9 += v * b9; - t10 += v * b10; - t11 += v * b11; - t12 += v * b12; - t13 += v * b13; - t14 += v * b14; - t15 += v * b15; - v = a[1]; - t1 += v * b0; - t2 += v * b1; - t3 += v * b2; - t4 += v * b3; - t5 += v * b4; - t6 += v * b5; - t7 += v * b6; - t8 += v * b7; - t9 += v * b8; - t10 += v * b9; - t11 += v * b10; - t12 += v * b11; - t13 += v * b12; - t14 += v * b13; - t15 += v * b14; - t16 += v * b15; - v = a[2]; - t2 += v * b0; - t3 += v * b1; - t4 += v * b2; - t5 += v * b3; - t6 += v * b4; - t7 += v * b5; - t8 += v * b6; - t9 += v * b7; - t10 += v * b8; - t11 += v * b9; - t12 += v * b10; - t13 += v * b11; - t14 += v * b12; - t15 += v * b13; - t16 += v * b14; - t17 += v * b15; - v = a[3]; - t3 += v * b0; - t4 += v * b1; - t5 += v * b2; - t6 += v * b3; - t7 += v * b4; - t8 += v * b5; - t9 += v * b6; - t10 += v * b7; - t11 += v * b8; - t12 += v * b9; - t13 += v * b10; - t14 += v * b11; - t15 += v * b12; - t16 += v * b13; - t17 += v * b14; - t18 += v * b15; - v = a[4]; - t4 += v * b0; - t5 += v * b1; - t6 += v * b2; - t7 += v * b3; - t8 += v * b4; - t9 += v * b5; - t10 += v * b6; - t11 += v * b7; - t12 += v * b8; - t13 += v * b9; - t14 += v * b10; - t15 += v * b11; - t16 += v * b12; - t17 += v * b13; - t18 += v * b14; - t19 += v * b15; - v = a[5]; - t5 += v * b0; - t6 += v * b1; - t7 += v * b2; - t8 += v * b3; - t9 += v * b4; - t10 += v * b5; - t11 += v * b6; - t12 += v * b7; - t13 += v * b8; - t14 += v * b9; - t15 += v * b10; - t16 += v * b11; - t17 += v * b12; - t18 += v * b13; - t19 += v * b14; - t20 += v * b15; - v = a[6]; - t6 += v * b0; - t7 += v * b1; - t8 += v * b2; - t9 += v * b3; - t10 += v * b4; - t11 += v * b5; - t12 += v * b6; - t13 += v * b7; - t14 += v * b8; - t15 += v * b9; - t16 += v * b10; - t17 += v * b11; - t18 += v * b12; - t19 += v * b13; - t20 += v * b14; - t21 += v * b15; - v = a[7]; - t7 += v * b0; - t8 += v * b1; - t9 += v * b2; - t10 += v * b3; - t11 += v * b4; - t12 += v * b5; - t13 += v * b6; - t14 += v * b7; - t15 += v * b8; - t16 += v * b9; - t17 += v * b10; - t18 += v * b11; - t19 += v * b12; - t20 += v * b13; - t21 += v * b14; - t22 += v * b15; - v = a[8]; - t8 += v * b0; - t9 += v * b1; - t10 += v * b2; - t11 += v * b3; - t12 += v * b4; - t13 += v * b5; - t14 += v * b6; - t15 += v * b7; - t16 += v * b8; - t17 += v * b9; - t18 += v * b10; - t19 += v * b11; - t20 += v * b12; - t21 += v * b13; - t22 += v * b14; - t23 += v * b15; - v = a[9]; - t9 += v * b0; - t10 += v * b1; - t11 += v * b2; - t12 += v * b3; - t13 += v * b4; - t14 += v * b5; - t15 += v * b6; - t16 += v * b7; - t17 += v * b8; - t18 += v * b9; - t19 += v * b10; - t20 += v * b11; - t21 += v * b12; - t22 += v * b13; - t23 += v * b14; - t24 += v * b15; - v = a[10]; - t10 += v * b0; - t11 += v * b1; - t12 += v * b2; - t13 += v * b3; - t14 += v * b4; - t15 += v * b5; - t16 += v * b6; - t17 += v * b7; - t18 += v * b8; - t19 += v * b9; - t20 += v * b10; - t21 += v * b11; - t22 += v * b12; - t23 += v * b13; - t24 += v * b14; - t25 += v * b15; - v = a[11]; - t11 += v * b0; - t12 += v * b1; - t13 += v * b2; - t14 += v * b3; - t15 += v * b4; - t16 += v * b5; - t17 += v * b6; - t18 += v * b7; - t19 += v * b8; - t20 += v * b9; - t21 += v * b10; - t22 += v * b11; - t23 += v * b12; - t24 += v * b13; - t25 += v * b14; - t26 += v * b15; - v = a[12]; - t12 += v * b0; - t13 += v * b1; - t14 += v * b2; - t15 += v * b3; - t16 += v * b4; - t17 += v * b5; - t18 += v * b6; - t19 += v * b7; - t20 += v * b8; - t21 += v * b9; - t22 += v * b10; - t23 += v * b11; - t24 += v * b12; - t25 += v * b13; - t26 += v * b14; - t27 += v * b15; - v = a[13]; - t13 += v * b0; - t14 += v * b1; - t15 += v * b2; - t16 += v * b3; - t17 += v * b4; - t18 += v * b5; - t19 += v * b6; - t20 += v * b7; - t21 += v * b8; - t22 += v * b9; - t23 += v * b10; - t24 += v * b11; - t25 += v * b12; - t26 += v * b13; - t27 += v * b14; - t28 += v * b15; - v = a[14]; - t14 += v * b0; - t15 += v * b1; - t16 += v * b2; - t17 += v * b3; - t18 += v * b4; - t19 += v * b5; - t20 += v * b6; - t21 += v * b7; - t22 += v * b8; - t23 += v * b9; - t24 += v * b10; - t25 += v * b11; - t26 += v * b12; - t27 += v * b13; - t28 += v * b14; - t29 += v * b15; - v = a[15]; - t15 += v * b0; - t16 += v * b1; - t17 += v * b2; - t18 += v * b3; - t19 += v * b4; - t20 += v * b5; - t21 += v * b6; - t22 += v * b7; - t23 += v * b8; - t24 += v * b9; - t25 += v * b10; - t26 += v * b11; - t27 += v * b12; - t28 += v * b13; - t29 += v * b14; - t30 += v * b15; - - t0 += 38 * t16; - t1 += 38 * t17; - t2 += 38 * t18; - t3 += 38 * t19; - t4 += 38 * t20; - t5 += 38 * t21; - t6 += 38 * t22; - t7 += 38 * t23; - t8 += 38 * t24; - t9 += 38 * t25; - t10 += 38 * t26; - t11 += 38 * t27; - t12 += 38 * t28; - t13 += 38 * t29; - t14 += 38 * t30; - // t15 left as is - - // first car - c = 1; - v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536; - v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536; - v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536; - v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536; - v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536; - v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536; - v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536; - v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536; - v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536; - v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536; - v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536; - v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536; - v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536; - v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536; - v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536; - v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536; - t0 += c-1 + 37 * (c-1); - - // second car - c = 1; - v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536; - v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536; - v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536; - v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536; - v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536; - v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536; - v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536; - v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536; - v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536; - v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536; - v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536; - v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536; - v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536; - v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536; - v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536; - v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536; - t0 += c-1 + 37 * (c-1); - - o[ 0] = t0; - o[ 1] = t1; - o[ 2] = t2; - o[ 3] = t3; - o[ 4] = t4; - o[ 5] = t5; - o[ 6] = t6; - o[ 7] = t7; - o[ 8] = t8; - o[ 9] = t9; - o[10] = t10; - o[11] = t11; - o[12] = t12; - o[13] = t13; - o[14] = t14; - o[15] = t15; -} - -function S(o, a) { - M(o, a, a); -} - -function inv25519(o, i) { - var c = gf(); - var a; - for (a = 0; a < 16; a++) c[a] = i[a]; - for (a = 253; a >= 0; a--) { - S(c, c); - if(a !== 2 && a !== 4) M(c, c, i); - } - for (a = 0; a < 16; a++) o[a] = c[a]; -} - -function pow2523(o, i) { - var c = gf(); - var a; - for (a = 0; a < 16; a++) c[a] = i[a]; - for (a = 250; a >= 0; a--) { - S(c, c); - if(a !== 1) M(c, c, i); - } - for (a = 0; a < 16; a++) o[a] = c[a]; -} - -function crypto_scalarmult(q, n, p) { - var z = new Uint8Array(32); - var x = new Float64Array(80), r, i; - var a = gf(), b = gf(), c = gf(), - d = gf(), e = gf(), f = gf(); - for (i = 0; i < 31; i++) z[i] = n[i]; - z[31]=(n[31]&127)|64; - z[0]&=248; - unpack25519(x,p); - for (i = 0; i < 16; i++) { - b[i]=x[i]; - d[i]=a[i]=c[i]=0; - } - a[0]=d[0]=1; - for (i=254; i>=0; --i) { - r=(z[i>>>3]>>>(i&7))&1; - sel25519(a,b,r); - sel25519(c,d,r); - A(e,a,c); - Z(a,a,c); - A(c,b,d); - Z(b,b,d); - S(d,e); - S(f,a); - M(a,c,a); - M(c,b,e); - A(e,a,c); - Z(a,a,c); - S(b,a); - Z(c,d,f); - M(a,c,_121665); - A(a,a,d); - M(c,c,a); - M(a,d,f); - M(d,b,x); - S(b,e); - sel25519(a,b,r); - sel25519(c,d,r); - } - for (i = 0; i < 16; i++) { - x[i+16]=a[i]; - x[i+32]=c[i]; - x[i+48]=b[i]; - x[i+64]=d[i]; - } - var x32 = x.subarray(32); - var x16 = x.subarray(16); - inv25519(x32,x32); - M(x16,x16,x32); - pack25519(q,x16); - return 0; -} - -function crypto_scalarmult_base(q, n) { - return crypto_scalarmult(q, n, _9); -} - -function crypto_box_keypair(y, x) { - randombytes(x, 32); - return crypto_scalarmult_base(y, x); -} - -function add(p, q) { - var a = gf(), b = gf(), c = gf(), - d = gf(), e = gf(), f = gf(), - g = gf(), h = gf(), t = gf(); - - Z(a, p[1], p[0]); - Z(t, q[1], q[0]); - M(a, a, t); - A(b, p[0], p[1]); - A(t, q[0], q[1]); - M(b, b, t); - M(c, p[3], q[3]); - M(c, c, D2); - M(d, p[2], q[2]); - A(d, d, d); - Z(e, b, a); - Z(f, d, c); - A(g, d, c); - A(h, b, a); - - M(p[0], e, f); - M(p[1], h, g); - M(p[2], g, f); - M(p[3], e, h); -} - -function cswap(p, q, b) { - var i; - for (i = 0; i < 4; i++) { - sel25519(p[i], q[i], b); - } -} - -function pack(r, p) { - var tx = gf(), ty = gf(), zi = gf(); - inv25519(zi, p[2]); - M(tx, p[0], zi); - M(ty, p[1], zi); - pack25519(r, ty); - r[31] ^= par25519(tx) << 7; -} - -function scalarmult(p, q, s) { - var b, i; - set25519(p[0], gf0); - set25519(p[1], gf1); - set25519(p[2], gf1); - set25519(p[3], gf0); - for (i = 255; i >= 0; --i) { - b = (s[(i/8)|0] >> (i&7)) & 1; - cswap(p, q, b); - add(q, p); - add(p, p); - cswap(p, q, b); - } -} - -function scalarbase(p, s) { - var q = [gf(), gf(), gf(), gf()]; - set25519(q[0], X); - set25519(q[1], Y); - set25519(q[2], gf1); - M(q[3], X, Y); - scalarmult(p, q, s); -} - -function crypto_sign_keypair(pk, sk, seeded) { - var d; - var p = [gf(), gf(), gf(), gf()]; - var i; - - if (!seeded) randombytes(sk, 32); - d = nacl.hash(sk.subarray(0, 32)); - d[0] &= 248; - d[31] &= 127; - d[31] |= 64; - - scalarbase(p, d); - pack(pk, p); - - for (i = 0; i < 32; i++) sk[i+32] = pk[i]; - return 0; -} - -var L = new Float64Array([0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10]); - -function modL(r, x) { - var carry, i, j, k; - for (i = 63; i >= 32; --i) { - carry = 0; - for (j = i - 32, k = i - 12; j < k; ++j) { - x[j] += carry - 16 * x[i] * L[j - (i - 32)]; - carry = Math.floor((x[j] + 128) / 256); - x[j] -= carry * 256; - } - x[j] += carry; - x[i] = 0; - } - carry = 0; - for (j = 0; j < 32; j++) { - x[j] += carry - (x[31] >> 4) * L[j]; - carry = x[j] >> 8; - x[j] &= 255; - } - for (j = 0; j < 32; j++) x[j] -= carry * L[j]; - for (i = 0; i < 32; i++) { - x[i+1] += x[i] >> 8; - r[i] = x[i] & 255; - } -} - -function reduce(r) { - var x = new Float64Array(64), i; - for (i = 0; i < 64; i++) x[i] = r[i]; - for (i = 0; i < 64; i++) r[i] = 0; - modL(r, x); -} - -// Note: difference from C - smlen returned, not passed as argument. -function crypto_sign(sm, m, n, sk) { - var d, h, r; - var i, j, x = new Float64Array(64); - var p = [gf(), gf(), gf(), gf()]; - - d = nacl.hash(sk.subarray(0, 32)); - d[0] &= 248; - d[31] &= 127; - d[31] |= 64; - - var smlen = n + 64; - for (i = 0; i < n; i++) sm[64 + i] = m[i]; - for (i = 0; i < 32; i++) sm[32 + i] = d[32 + i]; - - r = nacl.hash(sm.subarray(32, smlen)); - reduce(r); - scalarbase(p, r); - pack(sm, p); - - for (i = 32; i < 64; i++) sm[i] = sk[i]; - h = nacl.hash(sm.subarray(0, smlen)); - reduce(h); - - for (i = 0; i < 64; i++) x[i] = 0; - for (i = 0; i < 32; i++) x[i] = r[i]; - for (i = 0; i < 32; i++) { - for (j = 0; j < 32; j++) { - x[i+j] += h[i] * d[j]; - } - } - - modL(sm.subarray(32), x); - return smlen; -} - -function unpackneg(r, p) { - var t = gf(), chk = gf(), num = gf(), - den = gf(), den2 = gf(), den4 = gf(), - den6 = gf(); - - set25519(r[2], gf1); - unpack25519(r[1], p); - S(num, r[1]); - M(den, num, D); - Z(num, num, r[2]); - A(den, r[2], den); - - S(den2, den); - S(den4, den2); - M(den6, den4, den2); - M(t, den6, num); - M(t, t, den); - - pow2523(t, t); - M(t, t, num); - M(t, t, den); - M(t, t, den); - M(r[0], t, den); - - S(chk, r[0]); - M(chk, chk, den); - if (neq25519(chk, num)) M(r[0], r[0], I); - - S(chk, r[0]); - M(chk, chk, den); - if (neq25519(chk, num)) return -1; - - if (par25519(r[0]) === (p[31]>>7)) Z(r[0], gf0, r[0]); - - M(r[3], r[0], r[1]); - return 0; -} - -function crypto_sign_open(m, sm, n, pk) { - var i; - var t = new Uint8Array(32), h; - var p = [gf(), gf(), gf(), gf()], - q = [gf(), gf(), gf(), gf()]; - - if (n < 64) return -1; - - if (unpackneg(q, pk)) return -1; - - for (i = 0; i < n; i++) m[i] = sm[i]; - for (i = 0; i < 32; i++) m[i+32] = pk[i]; - h = nacl.hash(m.subarray(0, n)); - reduce(h); - scalarmult(p, q, h); - - scalarbase(q, sm.subarray(32)); - add(p, q); - pack(t, p); - - n -= 64; - if (crypto_verify_32(sm, 0, t, 0)) { - for (i = 0; i < n; i++) m[i] = 0; - return -1; - } - - for (i = 0; i < n; i++) m[i] = sm[i + 64]; - return n; -} - -var crypto_scalarmult_BYTES = 32, - crypto_scalarmult_SCALARBYTES = 32, - crypto_box_PUBLICKEYBYTES = 32, - crypto_box_SECRETKEYBYTES = 32, - crypto_sign_BYTES = 64, - crypto_sign_PUBLICKEYBYTES = 32, - crypto_sign_SECRETKEYBYTES = 64, - crypto_sign_SEEDBYTES = 32; - -function checkArrayTypes() { - for (var i = 0; i < arguments.length; i++) { - if (!(arguments[i] instanceof Uint8Array)) - throw new TypeError('unexpected type, use Uint8Array'); - } -} - -function cleanup(arr) { - for (var i = 0; i < arr.length; i++) arr[i] = 0; -} - -nacl.scalarMult = function(n, p) { - checkArrayTypes(n, p); - if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error('bad n size'); - if (p.length !== crypto_scalarmult_BYTES) throw new Error('bad p size'); - var q = new Uint8Array(crypto_scalarmult_BYTES); - crypto_scalarmult(q, n, p); - return q; -}; - -nacl.box = {}; - -nacl.box.keyPair = function() { - var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); - var sk = new Uint8Array(crypto_box_SECRETKEYBYTES); - crypto_box_keypair(pk, sk); - return {publicKey: pk, secretKey: sk}; -}; - -nacl.box.keyPair.fromSecretKey = function(secretKey) { - checkArrayTypes(secretKey); - if (secretKey.length !== crypto_box_SECRETKEYBYTES) - throw new Error('bad secret key size'); - var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); - crypto_scalarmult_base(pk, secretKey); - return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; -}; - -nacl.sign = function(msg, secretKey) { - checkArrayTypes(msg, secretKey); - if (secretKey.length !== crypto_sign_SECRETKEYBYTES) - throw new Error('bad secret key size'); - var signedMsg = new Uint8Array(crypto_sign_BYTES+msg.length); - crypto_sign(signedMsg, msg, msg.length, secretKey); - return signedMsg; -}; - -nacl.sign.detached = function(msg, secretKey) { - var signedMsg = nacl.sign(msg, secretKey); - var sig = new Uint8Array(crypto_sign_BYTES); - for (var i = 0; i < sig.length; i++) sig[i] = signedMsg[i]; - return sig; -}; - -nacl.sign.detached.verify = function(msg, sig, publicKey) { - checkArrayTypes(msg, sig, publicKey); - if (sig.length !== crypto_sign_BYTES) - throw new Error('bad signature size'); - if (publicKey.length !== crypto_sign_PUBLICKEYBYTES) - throw new Error('bad public key size'); - var sm = new Uint8Array(crypto_sign_BYTES + msg.length); - var m = new Uint8Array(crypto_sign_BYTES + msg.length); - var i; - for (i = 0; i < crypto_sign_BYTES; i++) sm[i] = sig[i]; - for (i = 0; i < msg.length; i++) sm[i+crypto_sign_BYTES] = msg[i]; - return (crypto_sign_open(m, sm, sm.length, publicKey) >= 0); -}; - -nacl.sign.keyPair = function() { - var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); - var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); - crypto_sign_keypair(pk, sk); - return {publicKey: pk, secretKey: sk}; -}; - -nacl.sign.keyPair.fromSecretKey = function(secretKey) { - checkArrayTypes(secretKey); - if (secretKey.length !== crypto_sign_SECRETKEYBYTES) - throw new Error('bad secret key size'); - var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); - for (var i = 0; i < pk.length; i++) pk[i] = secretKey[32+i]; - return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; -}; - -nacl.sign.keyPair.fromSeed = function(seed) { - checkArrayTypes(seed); - if (seed.length !== crypto_sign_SEEDBYTES) - throw new Error('bad seed size'); - var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); - var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); - for (var i = 0; i < 32; i++) sk[i] = seed[i]; - crypto_sign_keypair(pk, sk, true); - return {publicKey: pk, secretKey: sk}; -}; - -nacl.setPRNG = function(fn) { - randombytes = fn; -}; - -(function() { - // Initialize PRNG if environment provides CSPRNG. - // If not, methods calling randombytes will throw. - var crypto = typeof self !== 'undefined' ? (self.crypto || self.msCrypto) : null; - if (crypto && crypto.getRandomValues) { - // Browsers. - var QUOTA = 65536; - nacl.setPRNG(function(x, n) { - var i, v = new Uint8Array(n); - for (i = 0; i < n; i += QUOTA) { - crypto.getRandomValues(v.subarray(i, i + Math.min(n - i, QUOTA))); - } - for (i = 0; i < n; i++) x[i] = v[i]; - cleanup(v); - }); - } else if (typeof commonjsRequire !== 'undefined') { - // Node.js. - crypto = crypto__default['default']; - if (crypto && crypto.randomBytes) { - nacl.setPRNG(function(x, n) { - var i, v = crypto.randomBytes(n); - for (i = 0; i < n; i++) x[i] = v[i]; - cleanup(v); - }); - } - } -})(); - -})(module.exports ? module.exports : (self.nacl = self.nacl || {})); -}); - -// GPG4Browsers - An OpenPGP implementation in javascript - -const nodeCrypto$5 = util.getNodeCrypto(); - -/** - * Buffer for secure random numbers - */ -class RandomBuffer { - constructor() { - this.buffer = null; - this.size = null; - this.callback = null; - } - - /** - * Initialize buffer - * @param {Integer} size - size of buffer - */ - init(size, callback) { - this.buffer = new Uint8Array(size); - this.size = 0; - this.callback = callback; - } - - /** - * Concat array of secure random numbers to buffer - * @param {Uint8Array} buf - */ - set(buf) { - if (!this.buffer) { - throw new Error('RandomBuffer is not initialized'); - } - if (!(buf instanceof Uint8Array)) { - throw new Error('Invalid type: buf not an Uint8Array'); - } - const freeSpace = this.buffer.length - this.size; - if (buf.length > freeSpace) { - buf = buf.subarray(0, freeSpace); - } - // set buf with offset old size of buffer - this.buffer.set(buf, this.size); - this.size += buf.length; - } - - /** - * Take numbers out of buffer and copy to array - * @param {Uint8Array} buf - The destination array - */ - async get(buf) { - if (!this.buffer) { - throw new Error('RandomBuffer is not initialized'); - } - if (!(buf instanceof Uint8Array)) { - throw new Error('Invalid type: buf not an Uint8Array'); - } - if (this.size < buf.length) { - if (!this.callback) { - throw new Error('Random number buffer depleted'); - } - // Wait for random bytes from main context, then try again - await this.callback(); - return this.get(buf); - } - for (let i = 0; i < buf.length; i++) { - buf[i] = this.buffer[--this.size]; - // clear buffer value - this.buffer[this.size] = 0; - } - } -} - -/** - * Retrieve secure random byte array of the specified length - * @param {Integer} length - Length in bytes to generate - * @returns {Promise} Random byte array. - * @async - */ -async function getRandomBytes(length) { - const buf = new Uint8Array(length); - if (typeof crypto !== 'undefined' && crypto.getRandomValues) { - crypto.getRandomValues(buf); - } else if (nodeCrypto$5) { - const bytes = nodeCrypto$5.randomBytes(buf.length); - buf.set(bytes); - } else if (randomBuffer.buffer) { - await randomBuffer.get(buf); - } else { - throw new Error('No secure random number generator available.'); - } - return buf; -} - -/** - * Create a secure random BigInteger that is greater than or equal to min and less than max. - * @param {module:BigInteger} min - Lower bound, included - * @param {module:BigInteger} max - Upper bound, excluded - * @returns {Promise} Random BigInteger. - * @async - */ -async function getRandomBigInteger(min, max) { - const BigInteger = await util.getBigInteger(); - - if (max.lt(min)) { - throw new Error('Illegal parameter value: max <= min'); - } - - const modulus = max.sub(min); - const bytes = modulus.byteLength(); - - // Using a while loop is necessary to avoid bias introduced by the mod operation. - // However, we request 64 extra random bits so that the bias is negligible. - // Section B.1.1 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - const r = new BigInteger(await getRandomBytes(bytes + 8)); - return r.mod(modulus).add(min); -} - -const randomBuffer = new RandomBuffer(); - -var random = /*#__PURE__*/Object.freeze({ - __proto__: null, - getRandomBytes: getRandomBytes, - getRandomBigInteger: getRandomBigInteger, - randomBuffer: randomBuffer -}); - -// OpenPGP.js - An OpenPGP implementation in javascript - -/** - * Generate a probably prime random number - * @param {Integer} bits - Bit length of the prime - * @param {BigInteger} e - Optional RSA exponent to check against the prime - * @param {Integer} k - Optional number of iterations of Miller-Rabin test - * @returns BigInteger - * @async - */ -async function randomProbablePrime(bits, e, k) { - const BigInteger = await util.getBigInteger(); - const one = new BigInteger(1); - const min = one.leftShift(new BigInteger(bits - 1)); - const thirty = new BigInteger(30); - /* - * We can avoid any multiples of 3 and 5 by looking at n mod 30 - * n mod 30 = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 - * the next possible prime is mod 30: - * 1 7 7 7 7 7 7 11 11 11 11 13 13 17 17 17 17 19 19 23 23 23 23 29 29 29 29 29 29 1 - */ - const adds = [1, 6, 5, 4, 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, 3, 2, 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1, 2]; - - const n = await getRandomBigInteger(min, min.leftShift(one)); - let i = n.mod(thirty).toNumber(); - - do { - n.iadd(new BigInteger(adds[i])); - i = (i + adds[i]) % adds.length; - // If reached the maximum, go back to the minimum. - if (n.bitLength() > bits) { - n.imod(min.leftShift(one)).iadd(min); - i = n.mod(thirty).toNumber(); - } - } while (!await isProbablePrime(n, e, k)); - return n; -} - -/** - * Probabilistic primality testing - * @param {BigInteger} n - Number to test - * @param {BigInteger} e - Optional RSA exponent to check against the prime - * @param {Integer} k - Optional number of iterations of Miller-Rabin test - * @returns {boolean} - * @async - */ -async function isProbablePrime(n, e, k) { - if (e && !n.dec().gcd(e).isOne()) { - return false; - } - if (!await divisionTest(n)) { - return false; - } - if (!await fermat(n)) { - return false; - } - if (!await millerRabin(n, k)) { - return false; - } - // TODO implement the Lucas test - // See Section C.3.3 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - return true; -} - -/** - * Tests whether n is probably prime or not using Fermat's test with b = 2. - * Fails if b^(n-1) mod n != 1. - * @param {BigInteger} n - Number to test - * @param {BigInteger} b - Optional Fermat test base - * @returns {boolean} - */ -async function fermat(n, b) { - const BigInteger = await util.getBigInteger(); - b = b || new BigInteger(2); - return b.modExp(n.dec(), n).isOne(); -} - -async function divisionTest(n) { - const BigInteger = await util.getBigInteger(); - return smallPrimes.every(m => { - return n.mod(new BigInteger(m)) !== 0; - }); -} - -// https://github.com/gpg/libgcrypt/blob/master/cipher/primegen.c -const smallPrimes = [ - 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, - 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, - 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, - 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, - 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, - 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, - 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, - 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, - 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, - 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, - 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, - 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, - 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, - 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, - 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, - 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, - 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, - 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, - 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, - 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, - 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, - 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, - 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, - 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, - 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, - 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, - 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, - 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, - 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, - 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, - 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, - 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, - 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, - 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, - 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, - 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, - 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, - 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, - 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, - 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, - 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, - 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, - 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, - 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, - 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, - 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, - 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, - 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, - 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, - 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, - 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, - 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, - 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, - 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, - 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, - 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, - 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, - 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, - 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, - 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, - 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, - 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, - 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, - 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, - 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, - 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, - 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, - 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, - 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, - 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, - 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457, - 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, - 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, - 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, - 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, - 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, - 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, - 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, - 4957, 4967, 4969, 4973, 4987, 4993, 4999 -]; - - -// Miller-Rabin - Miller Rabin algorithm for primality test -// Copyright Fedor Indutny, 2014. -// -// This software is licensed under the MIT License. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -// Adapted on Jan 2018 from version 4.0.1 at https://github.com/indutny/miller-rabin - -// Sample syntax for Fixed-Base Miller-Rabin: -// millerRabin(n, k, () => new BN(small_primes[Math.random() * small_primes.length | 0])) - -/** - * Tests whether n is probably prime or not using the Miller-Rabin test. - * See HAC Remark 4.28. - * @param {BigInteger} n - Number to test - * @param {Integer} k - Optional number of iterations of Miller-Rabin test - * @param {Function} rand - Optional function to generate potential witnesses - * @returns {boolean} - * @async - */ -async function millerRabin(n, k, rand) { - const BigInteger = await util.getBigInteger(); - const len = n.bitLength(); - - if (!k) { - k = Math.max(1, (len / 48) | 0); - } - - const n1 = n.dec(); // n - 1 - - // Find d and s, (n - 1) = (2 ^ s) * d; - let s = 0; - while (!n1.getBit(s)) { s++; } - const d = n.rightShift(new BigInteger(s)); - - for (; k > 0; k--) { - const a = rand ? rand() : await getRandomBigInteger(new BigInteger(2), n1); - - let x = a.modExp(d, n); - if (x.isOne() || x.equal(n1)) { - continue; - } - - let i; - for (i = 1; i < s; i++) { - x = x.mul(x).mod(n); - - if (x.isOne()) { - return false; - } - if (x.equal(n1)) { - break; - } - } - - if (i === s) { - return false; - } - } - - return true; -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -/** - * ASN1 object identifiers for hashes - * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.2} - */ -const hash_headers = []; -hash_headers[1] = [0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, - 0x10]; -hash_headers[2] = [0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14]; -hash_headers[3] = [0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14]; -hash_headers[8] = [0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, - 0x04, 0x20]; -hash_headers[9] = [0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, - 0x04, 0x30]; -hash_headers[10] = [0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, - 0x00, 0x04, 0x40]; -hash_headers[11] = [0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, - 0x00, 0x04, 0x1C]; - -/** - * Create padding with secure random data - * @private - * @param {Integer} length - Length of the padding in bytes - * @returns {Promise} Random padding. - * @async - */ -async function getPKCS1Padding(length) { - const result = new Uint8Array(length); - let count = 0; - while (count < length) { - const randomBytes = await getRandomBytes(length - count); - for (let i = 0; i < randomBytes.length; i++) { - if (randomBytes[i] !== 0) { - result[count++] = randomBytes[i]; - } - } - } - return result; -} - -/** - * Create a EME-PKCS1-v1_5 padded message - * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.1|RFC 4880 13.1.1} - * @param {Uint8Array} message - Message to be encoded - * @param {Integer} keyLength - The length in octets of the key modulus - * @returns {Promise} EME-PKCS1 padded message. - * @async - */ -async function emeEncode(message, keyLength) { - const mLength = message.length; - // length checking - if (mLength > keyLength - 11) { - throw new Error('Message too long'); - } - // Generate an octet string PS of length k - mLen - 3 consisting of - // pseudo-randomly generated nonzero octets - const PS = await getPKCS1Padding(keyLength - mLength - 3); - // Concatenate PS, the message M, and other padding to form an - // encoded message EM of length k octets as EM = 0x00 || 0x02 || PS || 0x00 || M. - const encoded = new Uint8Array(keyLength); - // 0x00 byte - encoded[1] = 2; - encoded.set(PS, 2); - // 0x00 bytes - encoded.set(message, keyLength - mLength); - return encoded; -} - -/** - * Decode a EME-PKCS1-v1_5 padded message - * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.2|RFC 4880 13.1.2} - * @param {Uint8Array} encoded - Encoded message bytes - * @param {Uint8Array} randomPayload - Data to return in case of decoding error (needed for constant-time processing) - * @returns {Uint8Array} decoded data or `randomPayload` (on error, if given) - * @throws {Error} on decoding failure, unless `randomPayload` is provided - */ -function emeDecode(encoded, randomPayload) { - // encoded format: 0x00 0x02 0x00 - let offset = 2; - let separatorNotFound = 1; - for (let j = offset; j < encoded.length; j++) { - separatorNotFound &= encoded[j] !== 0; - offset += separatorNotFound; - } - - const psLen = offset - 2; - const payload = encoded.subarray(offset + 1); // discard the 0x00 separator - const isValidPadding = encoded[0] === 0 & encoded[1] === 2 & psLen >= 8 & !separatorNotFound; - - if (randomPayload) { - return util.selectUint8Array(isValidPadding, payload, randomPayload); - } - - if (isValidPadding) { - return payload; - } - - throw new Error('Decryption error'); -} - -/** - * Create a EMSA-PKCS1-v1_5 padded message - * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.3|RFC 4880 13.1.3} - * @param {Integer} algo - Hash algorithm type used - * @param {Uint8Array} hashed - Message to be encoded - * @param {Integer} emLen - Intended length in octets of the encoded message - * @returns {Uint8Array} Encoded message. - */ -async function emsaEncode(algo, hashed, emLen) { - let i; - if (hashed.length !== hash.getHashByteLength(algo)) { - throw new Error('Invalid hash length'); - } - // produce an ASN.1 DER value for the hash function used. - // Let T be the full hash prefix - const hashPrefix = new Uint8Array(hash_headers[algo].length); - for (i = 0; i < hash_headers[algo].length; i++) { - hashPrefix[i] = hash_headers[algo][i]; - } - // and let tLen be the length in octets prefix and hashed data - const tLen = hashPrefix.length + hashed.length; - if (emLen < tLen + 11) { - throw new Error('Intended encoded message length too short'); - } - // an octet string PS consisting of emLen - tLen - 3 octets with hexadecimal value 0xFF - // The length of PS will be at least 8 octets - const PS = new Uint8Array(emLen - tLen - 3).fill(0xff); - - // Concatenate PS, the hash prefix, hashed data, and other padding to form the - // encoded message EM as EM = 0x00 || 0x01 || PS || 0x00 || prefix || hashed - const EM = new Uint8Array(emLen); - EM[1] = 0x01; - EM.set(PS, 2); - EM.set(hashPrefix, emLen - tLen); - EM.set(hashed, emLen - hashed.length); - return EM; -} - -var pkcs1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - emeEncode: emeEncode, - emeDecode: emeDecode, - emsaEncode: emsaEncode -}); - -const webCrypto$5 = util.getWebCrypto(); -const nodeCrypto$6 = util.getNodeCrypto(); -const asn1 = nodeCrypto$6 ? asn1__default['default'] : undefined; - -/* eslint-disable no-invalid-this */ -const RSAPrivateKey = util.detectNode() ? asn1.define('RSAPrivateKey', function () { - this.seq().obj( // used for native NodeJS crypto - this.key('version').int(), // 0 - this.key('modulus').int(), // n - this.key('publicExponent').int(), // e - this.key('privateExponent').int(), // d - this.key('prime1').int(), // p - this.key('prime2').int(), // q - this.key('exponent1').int(), // dp - this.key('exponent2').int(), // dq - this.key('coefficient').int() // u - ); -}) : undefined; - -const RSAPublicKey = util.detectNode() ? asn1.define('RSAPubliceKey', function () { - this.seq().obj( // used for native NodeJS crypto - this.key('modulus').int(), // n - this.key('publicExponent').int(), // e - ); -}) : undefined; -/* eslint-enable no-invalid-this */ - -/** Create signature - * @param {module:enums.hash} hashAlgo - Hash algorithm - * @param {Uint8Array} data - Message - * @param {Uint8Array} n - RSA public modulus - * @param {Uint8Array} e - RSA public exponent - * @param {Uint8Array} d - RSA private exponent - * @param {Uint8Array} p - RSA private prime p - * @param {Uint8Array} q - RSA private prime q - * @param {Uint8Array} u - RSA private coefficient - * @param {Uint8Array} hashed - Hashed message - * @returns {Promise} RSA Signature. - * @async - */ -async function sign(hashAlgo, data, n, e, d, p, q, u, hashed) { - if (data && !util.isStream(data)) { - if (util.getWebCrypto()) { - try { - return await webSign(enums.read(enums.webHash, hashAlgo), data, n, e, d, p, q, u); - } catch (err) { - util.printDebugError(err); - } - } else if (util.getNodeCrypto()) { - return nodeSign(hashAlgo, data, n, e, d, p, q, u); - } - } - return bnSign(hashAlgo, n, d, hashed); -} - -/** - * Verify signature - * @param {module:enums.hash} hashAlgo - Hash algorithm - * @param {Uint8Array} data - Message - * @param {Uint8Array} s - Signature - * @param {Uint8Array} n - RSA public modulus - * @param {Uint8Array} e - RSA public exponent - * @param {Uint8Array} hashed - Hashed message - * @returns {Boolean} - * @async - */ -async function verify(hashAlgo, data, s, n, e, hashed) { - if (data && !util.isStream(data)) { - if (util.getWebCrypto()) { - try { - return await webVerify(enums.read(enums.webHash, hashAlgo), data, s, n, e); - } catch (err) { - util.printDebugError(err); - } - } else if (util.getNodeCrypto()) { - return nodeVerify(hashAlgo, data, s, n, e); - } - } - return bnVerify(hashAlgo, s, n, e, hashed); -} - -/** - * Encrypt message - * @param {Uint8Array} data - Message - * @param {Uint8Array} n - RSA public modulus - * @param {Uint8Array} e - RSA public exponent - * @returns {Promise} RSA Ciphertext. - * @async - */ -async function encrypt$1(data, n, e) { - if (util.getNodeCrypto()) { - return nodeEncrypt$1(data, n, e); - } - return bnEncrypt(data, n, e); -} - -/** - * Decrypt RSA message - * @param {Uint8Array} m - Message - * @param {Uint8Array} n - RSA public modulus - * @param {Uint8Array} e - RSA public exponent - * @param {Uint8Array} d - RSA private exponent - * @param {Uint8Array} p - RSA private prime p - * @param {Uint8Array} q - RSA private prime q - * @param {Uint8Array} u - RSA private coefficient - * @param {Uint8Array} randomPayload - Data to return on decryption error, instead of throwing - * (needed for constant-time processing) - * @returns {Promise} RSA Plaintext. - * @throws {Error} on decryption error, unless `randomPayload` is given - * @async - */ -async function decrypt$1(data, n, e, d, p, q, u, randomPayload) { - if (util.getNodeCrypto()) { - return nodeDecrypt$1(data, n, e, d, p, q, u, randomPayload); - } - return bnDecrypt(data, n, e, d, p, q, u, randomPayload); -} - -/** - * Generate a new random private key B bits long with public exponent E. - * - * When possible, webCrypto or nodeCrypto is used. Otherwise, primes are generated using - * 40 rounds of the Miller-Rabin probabilistic random prime generation algorithm. - * @see module:crypto/public_key/prime - * @param {Integer} bits - RSA bit length - * @param {Integer} e - RSA public exponent - * @returns {{n, e, d, - * p, q ,u: Uint8Array}} RSA public modulus, RSA public exponent, RSA private exponent, - * RSA private prime p, RSA private prime q, u = p ** -1 mod q - * @async - */ -async function generate(bits, e) { - const BigInteger = await util.getBigInteger(); - - e = new BigInteger(e); - - // Native RSA keygen using Web Crypto - if (util.getWebCrypto()) { - const keyGenOpt = { - name: 'RSASSA-PKCS1-v1_5', - modulusLength: bits, // the specified keysize in bits - publicExponent: e.toUint8Array(), // take three bytes (max 65537) for exponent - hash: { - name: 'SHA-1' // not required for actual RSA keys, but for crypto api 'sign' and 'verify' - } - }; - const keyPair = await webCrypto$5.generateKey(keyGenOpt, true, ['sign', 'verify']); - - // export the generated keys as JsonWebKey (JWK) - // https://tools.ietf.org/html/draft-ietf-jose-json-web-key-33 - const jwk = await webCrypto$5.exportKey('jwk', keyPair.privateKey); - // map JWK parameters to corresponding OpenPGP names - return { - n: b64ToUint8Array(jwk.n), - e: e.toUint8Array(), - d: b64ToUint8Array(jwk.d), - // switch p and q - p: b64ToUint8Array(jwk.q), - q: b64ToUint8Array(jwk.p), - // Since p and q are switched in places, u is the inverse of jwk.q - u: b64ToUint8Array(jwk.qi) - }; - } else if (util.getNodeCrypto() && nodeCrypto$6.generateKeyPair && RSAPrivateKey) { - const opts = { - modulusLength: bits, - publicExponent: e.toNumber(), - publicKeyEncoding: { type: 'pkcs1', format: 'der' }, - privateKeyEncoding: { type: 'pkcs1', format: 'der' } - }; - const prv = await new Promise((resolve, reject) => nodeCrypto$6.generateKeyPair('rsa', opts, (err, _, der) => { - if (err) { - reject(err); - } else { - resolve(RSAPrivateKey.decode(der, 'der')); - } - })); - /** - * OpenPGP spec differs from DER spec, DER: `u = (inverse of q) mod p`, OpenPGP: `u = (inverse of p) mod q`. - * @link https://tools.ietf.org/html/rfc3447#section-3.2 - * @link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-08#section-5.6.1 - */ - return { - n: prv.modulus.toArrayLike(Uint8Array), - e: prv.publicExponent.toArrayLike(Uint8Array), - d: prv.privateExponent.toArrayLike(Uint8Array), - // switch p and q - p: prv.prime2.toArrayLike(Uint8Array), - q: prv.prime1.toArrayLike(Uint8Array), - // Since p and q are switched in places, we can keep u as defined by DER - u: prv.coefficient.toArrayLike(Uint8Array) - }; - } - - // RSA keygen fallback using 40 iterations of the Miller-Rabin test - // See https://stackoverflow.com/a/6330138 for justification - // Also see section C.3 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST - let p; - let q; - let n; - do { - q = await randomProbablePrime(bits - (bits >> 1), e, 40); - p = await randomProbablePrime(bits >> 1, e, 40); - n = p.mul(q); - } while (n.bitLength() !== bits); - - const phi = p.dec().imul(q.dec()); - - if (q.lt(p)) { - [p, q] = [q, p]; - } - - return { - n: n.toUint8Array(), - e: e.toUint8Array(), - d: e.modInv(phi).toUint8Array(), - p: p.toUint8Array(), - q: q.toUint8Array(), - // dp: d.mod(p.subn(1)), - // dq: d.mod(q.subn(1)), - u: p.modInv(q).toUint8Array() - }; -} - -/** - * Validate RSA parameters - * @param {Uint8Array} n - RSA public modulus - * @param {Uint8Array} e - RSA public exponent - * @param {Uint8Array} d - RSA private exponent - * @param {Uint8Array} p - RSA private prime p - * @param {Uint8Array} q - RSA private prime q - * @param {Uint8Array} u - RSA inverse of p w.r.t. q - * @returns {Promise} Whether params are valid. - * @async - */ -async function validateParams(n, e, d, p, q, u) { - const BigInteger = await util.getBigInteger(); - n = new BigInteger(n); - p = new BigInteger(p); - q = new BigInteger(q); - - // expect pq = n - if (!p.mul(q).equal(n)) { - return false; - } - - const two = new BigInteger(2); - // expect p*u = 1 mod q - u = new BigInteger(u); - if (!p.mul(u).mod(q).isOne()) { - return false; - } - - e = new BigInteger(e); - d = new BigInteger(d); - /** - * In RSA pkcs#1 the exponents (d, e) are inverses modulo lcm(p-1, q-1) - * We check that [de = 1 mod (p-1)] and [de = 1 mod (q-1)] - * By CRT on coprime factors of (p-1, q-1) it follows that [de = 1 mod lcm(p-1, q-1)] - * - * We blind the multiplication with r, and check that rde = r mod lcm(p-1, q-1) - */ - const nSizeOver3 = new BigInteger(Math.floor(n.bitLength() / 3)); - const r = await getRandomBigInteger(two, two.leftShift(nSizeOver3)); // r in [ 2, 2^{|n|/3} ) < p and q - const rde = r.mul(d).mul(e); - - const areInverses = rde.mod(p.dec()).equal(r) && rde.mod(q.dec()).equal(r); - if (!areInverses) { - return false; - } - - return true; -} - -async function bnSign(hashAlgo, n, d, hashed) { - const BigInteger = await util.getBigInteger(); - n = new BigInteger(n); - const m = new BigInteger(await emsaEncode(hashAlgo, hashed, n.byteLength())); - d = new BigInteger(d); - if (m.gte(n)) { - throw new Error('Message size cannot exceed modulus size'); - } - return m.modExp(d, n).toUint8Array('be', n.byteLength()); -} - -async function webSign(hashName, data, n, e, d, p, q, u) { - /** OpenPGP keys require that p < q, and Safari Web Crypto requires that p > q. - * We swap them in privateToJWK, so it usually works out, but nevertheless, - * not all OpenPGP keys are compatible with this requirement. - * OpenPGP.js used to generate RSA keys the wrong way around (p > q), and still - * does if the underlying Web Crypto does so (e.g. old MS Edge 50% of the time). - */ - const jwk = await privateToJWK(n, e, d, p, q, u); - const algo = { - name: 'RSASSA-PKCS1-v1_5', - hash: { name: hashName } - }; - const key = await webCrypto$5.importKey('jwk', jwk, algo, false, ['sign']); - // add hash field for ms edge support - return new Uint8Array(await webCrypto$5.sign({ 'name': 'RSASSA-PKCS1-v1_5', 'hash': hashName }, key, data)); -} - -async function nodeSign(hashAlgo, data, n, e, d, p, q, u) { - const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); - const pBNum = new BN(p); - const qBNum = new BN(q); - const dBNum = new BN(d); - const dq = dBNum.mod(qBNum.subn(1)); // d mod (q-1) - const dp = dBNum.mod(pBNum.subn(1)); // d mod (p-1) - const sign = nodeCrypto$6.createSign(enums.read(enums.hash, hashAlgo)); - sign.write(data); - sign.end(); - const keyObject = { - version: 0, - modulus: new BN(n), - publicExponent: new BN(e), - privateExponent: new BN(d), - // switch p and q - prime1: new BN(q), - prime2: new BN(p), - // switch dp and dq - exponent1: dq, - exponent2: dp, - coefficient: new BN(u) - }; - if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { //from version 11.6.0 Node supports der encoded key objects - const der = RSAPrivateKey.encode(keyObject, 'der'); - return new Uint8Array(sign.sign({ key: der, format: 'der', type: 'pkcs1' })); - } - const pem = RSAPrivateKey.encode(keyObject, 'pem', { - label: 'RSA PRIVATE KEY' - }); - return new Uint8Array(sign.sign(pem)); -} - -async function bnVerify(hashAlgo, s, n, e, hashed) { - const BigInteger = await util.getBigInteger(); - n = new BigInteger(n); - s = new BigInteger(s); - e = new BigInteger(e); - if (s.gte(n)) { - throw new Error('Signature size cannot exceed modulus size'); - } - const EM1 = s.modExp(e, n).toUint8Array('be', n.byteLength()); - const EM2 = await emsaEncode(hashAlgo, hashed, n.byteLength()); - return util.equalsUint8Array(EM1, EM2); -} - -async function webVerify(hashName, data, s, n, e) { - const jwk = publicToJWK(n, e); - const key = await webCrypto$5.importKey('jwk', jwk, { - name: 'RSASSA-PKCS1-v1_5', - hash: { name: hashName } - }, false, ['verify']); - // add hash field for ms edge support - return webCrypto$5.verify({ 'name': 'RSASSA-PKCS1-v1_5', 'hash': hashName }, key, s, data); -} - -async function nodeVerify(hashAlgo, data, s, n, e) { - const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); - - const verify = nodeCrypto$6.createVerify(enums.read(enums.hash, hashAlgo)); - verify.write(data); - verify.end(); - const keyObject = { - modulus: new BN(n), - publicExponent: new BN(e) - }; - let key; - if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { //from version 11.6.0 Node supports der encoded key objects - const der = RSAPublicKey.encode(keyObject, 'der'); - key = { key: der, format: 'der', type: 'pkcs1' }; - } else { - key = RSAPublicKey.encode(keyObject, 'pem', { - label: 'RSA PUBLIC KEY' - }); - } - try { - return await verify.verify(key, s); - } catch (err) { - return false; - } -} - -async function nodeEncrypt$1(data, n, e) { - const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); - - const keyObject = { - modulus: new BN(n), - publicExponent: new BN(e) - }; - let key; - if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { - const der = RSAPublicKey.encode(keyObject, 'der'); - key = { key: der, format: 'der', type: 'pkcs1', padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; - } else { - const pem = RSAPublicKey.encode(keyObject, 'pem', { - label: 'RSA PUBLIC KEY' - }); - key = { key: pem, padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; - } - return new Uint8Array(nodeCrypto$6.publicEncrypt(key, data)); -} - -async function bnEncrypt(data, n, e) { - const BigInteger = await util.getBigInteger(); - n = new BigInteger(n); - data = new BigInteger(await emeEncode(data, n.byteLength())); - e = new BigInteger(e); - if (data.gte(n)) { - throw new Error('Message size cannot exceed modulus size'); - } - return data.modExp(e, n).toUint8Array('be', n.byteLength()); -} - -async function nodeDecrypt$1(data, n, e, d, p, q, u, randomPayload) { - const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); - - const pBNum = new BN(p); - const qBNum = new BN(q); - const dBNum = new BN(d); - const dq = dBNum.mod(qBNum.subn(1)); // d mod (q-1) - const dp = dBNum.mod(pBNum.subn(1)); // d mod (p-1) - const keyObject = { - version: 0, - modulus: new BN(n), - publicExponent: new BN(e), - privateExponent: new BN(d), - // switch p and q - prime1: new BN(q), - prime2: new BN(p), - // switch dp and dq - exponent1: dq, - exponent2: dp, - coefficient: new BN(u) - }; - let key; - if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { - const der = RSAPrivateKey.encode(keyObject, 'der'); - key = { key: der, format: 'der' , type: 'pkcs1', padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; - } else { - const pem = RSAPrivateKey.encode(keyObject, 'pem', { - label: 'RSA PRIVATE KEY' - }); - key = { key: pem, padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; - } - try { - return new Uint8Array(nodeCrypto$6.privateDecrypt(key, data)); - } catch (err) { - if (randomPayload) { - return randomPayload; - } - throw new Error('Decryption error'); - } -} - -async function bnDecrypt(data, n, e, d, p, q, u, randomPayload) { - const BigInteger = await util.getBigInteger(); - data = new BigInteger(data); - n = new BigInteger(n); - e = new BigInteger(e); - d = new BigInteger(d); - p = new BigInteger(p); - q = new BigInteger(q); - u = new BigInteger(u); - if (data.gte(n)) { - throw new Error('Data too large.'); - } - const dq = d.mod(q.dec()); // d mod (q-1) - const dp = d.mod(p.dec()); // d mod (p-1) - - const unblinder = (await getRandomBigInteger(new BigInteger(2), n)).mod(n); - const blinder = unblinder.modInv(n).modExp(e, n); - data = data.mul(blinder).mod(n); - - - const mp = data.modExp(dp, p); // data**{d mod (q-1)} mod p - const mq = data.modExp(dq, q); // data**{d mod (p-1)} mod q - const h = u.mul(mq.sub(mp)).mod(q); // u * (mq-mp) mod q (operands already < q) - - let result = h.mul(p).add(mp); // result < n due to relations above - - result = result.mul(unblinder).mod(n); - - - return emeDecode(result.toUint8Array('be', n.byteLength()), randomPayload); -} - -/** Convert Openpgp private key params to jwk key according to - * @link https://tools.ietf.org/html/rfc7517 - * @param {String} hashAlgo - * @param {Uint8Array} n - * @param {Uint8Array} e - * @param {Uint8Array} d - * @param {Uint8Array} p - * @param {Uint8Array} q - * @param {Uint8Array} u - */ -async function privateToJWK(n, e, d, p, q, u) { - const BigInteger = await util.getBigInteger(); - const pNum = new BigInteger(p); - const qNum = new BigInteger(q); - const dNum = new BigInteger(d); - - let dq = dNum.mod(qNum.dec()); // d mod (q-1) - let dp = dNum.mod(pNum.dec()); // d mod (p-1) - dp = dp.toUint8Array(); - dq = dq.toUint8Array(); - return { - kty: 'RSA', - n: uint8ArrayToB64(n, true), - e: uint8ArrayToB64(e, true), - d: uint8ArrayToB64(d, true), - // switch p and q - p: uint8ArrayToB64(q, true), - q: uint8ArrayToB64(p, true), - // switch dp and dq - dp: uint8ArrayToB64(dq, true), - dq: uint8ArrayToB64(dp, true), - qi: uint8ArrayToB64(u, true), - ext: true - }; -} - -/** Convert Openpgp key public params to jwk key according to - * @link https://tools.ietf.org/html/rfc7517 - * @param {String} hashAlgo - * @param {Uint8Array} n - * @param {Uint8Array} e - */ -function publicToJWK(n, e) { - return { - kty: 'RSA', - n: uint8ArrayToB64(n, true), - e: uint8ArrayToB64(e, true), - ext: true - }; -} - -var rsa = /*#__PURE__*/Object.freeze({ - __proto__: null, - sign: sign, - verify: verify, - encrypt: encrypt$1, - decrypt: decrypt$1, - generate: generate, - validateParams: validateParams -}); - -// GPG4Browsers - An OpenPGP implementation in javascript - -/** - * ElGamal Encryption function - * Note that in OpenPGP, the message needs to be padded with PKCS#1 (same as RSA) - * @param {Uint8Array} data - To be padded and encrypted - * @param {Uint8Array} p - * @param {Uint8Array} g - * @param {Uint8Array} y - * @returns {Promise<{ c1: Uint8Array, c2: Uint8Array }>} - * @async - */ -async function encrypt$2(data, p, g, y) { - const BigInteger = await util.getBigInteger(); - p = new BigInteger(p); - g = new BigInteger(g); - y = new BigInteger(y); - - const padded = await emeEncode(data, p.byteLength()); - const m = new BigInteger(padded); - - // OpenPGP uses a "special" version of ElGamal where g is generator of the full group Z/pZ* - // hence g has order p-1, and to avoid that k = 0 mod p-1, we need to pick k in [1, p-2] - const k = await getRandomBigInteger(new BigInteger(1), p.dec()); - return { - c1: g.modExp(k, p).toUint8Array(), - c2: y.modExp(k, p).imul(m).imod(p).toUint8Array() - }; -} - -/** - * ElGamal Encryption function - * @param {Uint8Array} c1 - * @param {Uint8Array} c2 - * @param {Uint8Array} p - * @param {Uint8Array} x - * @param {Uint8Array} randomPayload - Data to return on unpadding error, instead of throwing - * (needed for constant-time processing) - * @returns {Promise} Unpadded message. - * @throws {Error} on decryption error, unless `randomPayload` is given - * @async - */ -async function decrypt$2(c1, c2, p, x, randomPayload) { - const BigInteger = await util.getBigInteger(); - c1 = new BigInteger(c1); - c2 = new BigInteger(c2); - p = new BigInteger(p); - x = new BigInteger(x); - - const padded = c1.modExp(x, p).modInv(p).imul(c2).imod(p); - return emeDecode(padded.toUint8Array('be', p.byteLength()), randomPayload); -} - -/** - * Validate ElGamal parameters - * @param {Uint8Array} p - ElGamal prime - * @param {Uint8Array} g - ElGamal group generator - * @param {Uint8Array} y - ElGamal public key - * @param {Uint8Array} x - ElGamal private exponent - * @returns {Promise} Whether params are valid. - * @async - */ -async function validateParams$1(p, g, y, x) { - const BigInteger = await util.getBigInteger(); - p = new BigInteger(p); - g = new BigInteger(g); - y = new BigInteger(y); - - const one = new BigInteger(1); - // Check that 1 < g < p - if (g.lte(one) || g.gte(p)) { - return false; - } - - // Expect p-1 to be large - const pSize = new BigInteger(p.bitLength()); - const n1023 = new BigInteger(1023); - if (pSize.lt(n1023)) { - return false; - } - - /** - * g should have order p-1 - * Check that g ** (p-1) = 1 mod p - */ - if (!g.modExp(p.dec(), p).isOne()) { - return false; - } - - /** - * Since p-1 is not prime, g might have a smaller order that divides p-1 - * We want to make sure that the order is large enough to hinder a small subgroup attack - * - * We just check g**i != 1 for all i up to a threshold - */ - let res = g; - const i = new BigInteger(1); - const threshold = new BigInteger(2).leftShift(new BigInteger(17)); // we want order > threshold - while (i.lt(threshold)) { - res = res.mul(g).imod(p); - if (res.isOne()) { - return false; - } - i.iinc(); - } - - /** - * Re-derive public key y' = g ** x mod p - * Expect y == y' - * - * Blinded exponentiation computes g**{r(p-1) + x} to compare to y - */ - x = new BigInteger(x); - const two = new BigInteger(2); - const r = await getRandomBigInteger(two.leftShift(pSize.dec()), two.leftShift(pSize)); // draw r of same size as p-1 - const rqx = p.dec().imul(r).iadd(x); - if (!y.equal(g.modExp(rqx, p))) { - return false; - } - - return true; -} - -var elgamal = /*#__PURE__*/Object.freeze({ - __proto__: null, - encrypt: encrypt$2, - decrypt: decrypt$2, - validateParams: validateParams$1 -}); - -// OpenPGP.js - An OpenPGP implementation in javascript - -class OID { - constructor(oid) { - if (oid instanceof OID) { - this.oid = oid.oid; - } else if (util.isArray(oid) || - util.isUint8Array(oid)) { - oid = new Uint8Array(oid); - if (oid[0] === 0x06) { // DER encoded oid byte array - if (oid[1] !== oid.length - 2) { - throw new Error('Length mismatch in DER encoded oid'); - } - oid = oid.subarray(2); - } - this.oid = oid; - } else { - this.oid = ''; - } - } - - /** - * Method to read an OID object - * @param {Uint8Array} input - Where to read the OID from - * @returns {Number} Number of read bytes. - */ - read(input) { - if (input.length >= 1) { - const length = input[0]; - if (input.length >= 1 + length) { - this.oid = input.subarray(1, 1 + length); - return 1 + this.oid.length; - } - } - throw new Error('Invalid oid'); - } - - /** - * Serialize an OID object - * @returns {Uint8Array} Array with the serialized value the OID. - */ - write() { - return util.concatUint8Array([new Uint8Array([this.oid.length]), this.oid]); - } - - /** - * Serialize an OID object as a hex string - * @returns {string} String with the hex value of the OID. - */ - toHex() { - return util.uint8ArrayToHex(this.oid); - } - - /** - * If a known curve object identifier, return the canonical name of the curve - * @returns {string} String with the canonical name of the curve. - */ - getName() { - const hex = this.toHex(); - if (enums.curve[hex]) { - return enums.write(enums.curve, hex); - } else { - throw new Error('Unknown curve object identifier.'); - } - } -} - -// OpenPGP.js - An OpenPGP implementation in javascript - -function keyFromPrivate(indutnyCurve, priv) { - const keyPair = indutnyCurve.keyPair({ priv: priv }); - return keyPair; -} - -function keyFromPublic(indutnyCurve, pub) { - const keyPair = indutnyCurve.keyPair({ pub: pub }); - if (keyPair.validate().result !== true) { - throw new Error('Invalid elliptic public key'); - } - return keyPair; -} - -async function getIndutnyCurve(name) { - if (!defaultConfig.useIndutnyElliptic) { - throw new Error('This curve is only supported in the full build of OpenPGP.js'); - } - const { default: elliptic } = await Promise.resolve().then(function () { return elliptic$1; }); - return new elliptic.ec(name); -} - -// OpenPGP.js - An OpenPGP implementation in javascript - -const webCrypto$6 = util.getWebCrypto(); -const nodeCrypto$7 = util.getNodeCrypto(); - -const webCurves = { - 'p256': 'P-256', - 'p384': 'P-384', - 'p521': 'P-521' -}; -const knownCurves = nodeCrypto$7 ? nodeCrypto$7.getCurves() : []; -const nodeCurves = nodeCrypto$7 ? { - secp256k1: knownCurves.includes('secp256k1') ? 'secp256k1' : undefined, - p256: knownCurves.includes('prime256v1') ? 'prime256v1' : undefined, - p384: knownCurves.includes('secp384r1') ? 'secp384r1' : undefined, - p521: knownCurves.includes('secp521r1') ? 'secp521r1' : undefined, - ed25519: knownCurves.includes('ED25519') ? 'ED25519' : undefined, - curve25519: knownCurves.includes('X25519') ? 'X25519' : undefined, - brainpoolP256r1: knownCurves.includes('brainpoolP256r1') ? 'brainpoolP256r1' : undefined, - brainpoolP384r1: knownCurves.includes('brainpoolP384r1') ? 'brainpoolP384r1' : undefined, - brainpoolP512r1: knownCurves.includes('brainpoolP512r1') ? 'brainpoolP512r1' : undefined -} : {}; - -const curves = { - p256: { - oid: [0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07], - keyType: enums.publicKey.ecdsa, - hash: enums.hash.sha256, - cipher: enums.symmetric.aes128, - node: nodeCurves.p256, - web: webCurves.p256, - payloadSize: 32, - sharedSize: 256 - }, - p384: { - oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22], - keyType: enums.publicKey.ecdsa, - hash: enums.hash.sha384, - cipher: enums.symmetric.aes192, - node: nodeCurves.p384, - web: webCurves.p384, - payloadSize: 48, - sharedSize: 384 - }, - p521: { - oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23], - keyType: enums.publicKey.ecdsa, - hash: enums.hash.sha512, - cipher: enums.symmetric.aes256, - node: nodeCurves.p521, - web: webCurves.p521, - payloadSize: 66, - sharedSize: 528 - }, - secp256k1: { - oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x0A], - keyType: enums.publicKey.ecdsa, - hash: enums.hash.sha256, - cipher: enums.symmetric.aes128, - node: nodeCurves.secp256k1, - payloadSize: 32 - }, - ed25519: { - oid: [0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01], - keyType: enums.publicKey.eddsa, - hash: enums.hash.sha512, - node: false, // nodeCurves.ed25519 TODO - payloadSize: 32 - }, - curve25519: { - oid: [0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01], - keyType: enums.publicKey.ecdh, - hash: enums.hash.sha256, - cipher: enums.symmetric.aes128, - node: false, // nodeCurves.curve25519 TODO - payloadSize: 32 - }, - brainpoolP256r1: { - oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07], - keyType: enums.publicKey.ecdsa, - hash: enums.hash.sha256, - cipher: enums.symmetric.aes128, - node: nodeCurves.brainpoolP256r1, - payloadSize: 32 - }, - brainpoolP384r1: { - oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B], - keyType: enums.publicKey.ecdsa, - hash: enums.hash.sha384, - cipher: enums.symmetric.aes192, - node: nodeCurves.brainpoolP384r1, - payloadSize: 48 - }, - brainpoolP512r1: { - oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D], - keyType: enums.publicKey.ecdsa, - hash: enums.hash.sha512, - cipher: enums.symmetric.aes256, - node: nodeCurves.brainpoolP512r1, - payloadSize: 64 - } -}; - -class Curve { - constructor(oidOrName, params) { - try { - if (util.isArray(oidOrName) || - util.isUint8Array(oidOrName)) { - // by oid byte array - oidOrName = new OID(oidOrName); - } - if (oidOrName instanceof OID) { - // by curve OID - oidOrName = oidOrName.getName(); - } - // by curve name or oid string - this.name = enums.write(enums.curve, oidOrName); - } catch (err) { - throw new Error('Not valid curve'); - } - params = params || curves[this.name]; - - this.keyType = params.keyType; - - this.oid = params.oid; - this.hash = params.hash; - this.cipher = params.cipher; - this.node = params.node && curves[this.name]; - this.web = params.web && curves[this.name]; - this.payloadSize = params.payloadSize; - if (this.web && util.getWebCrypto()) { - this.type = 'web'; - } else if (this.node && util.getNodeCrypto()) { - this.type = 'node'; - } else if (this.name === 'curve25519') { - this.type = 'curve25519'; - } else if (this.name === 'ed25519') { - this.type = 'ed25519'; - } - } - - async genKeyPair() { - let keyPair; - switch (this.type) { - case 'web': - try { - return await webGenKeyPair(this.name); - } catch (err) { - util.printDebugError('Browser did not support generating ec key ' + err.message); - break; - } - case 'node': - return nodeGenKeyPair(this.name); - case 'curve25519': { - const privateKey = await getRandomBytes(32); - privateKey[0] = (privateKey[0] & 127) | 64; - privateKey[31] &= 248; - const secretKey = privateKey.slice().reverse(); - keyPair = naclFastLight.box.keyPair.fromSecretKey(secretKey); - const publicKey = util.concatUint8Array([new Uint8Array([0x40]), keyPair.publicKey]); - return { publicKey, privateKey }; - } - case 'ed25519': { - const privateKey = await getRandomBytes(32); - const keyPair = naclFastLight.sign.keyPair.fromSeed(privateKey); - const publicKey = util.concatUint8Array([new Uint8Array([0x40]), keyPair.publicKey]); - return { publicKey, privateKey }; - } - } - const indutnyCurve = await getIndutnyCurve(this.name); - keyPair = await indutnyCurve.genKeyPair({ - entropy: util.uint8ArrayToString(await getRandomBytes(32)) - }); - return { publicKey: new Uint8Array(keyPair.getPublic('array', false)), privateKey: keyPair.getPrivate().toArrayLike(Uint8Array) }; - } -} - -async function generate$1(curve) { - const BigInteger = await util.getBigInteger(); - - curve = new Curve(curve); - const keyPair = await curve.genKeyPair(); - const Q = new BigInteger(keyPair.publicKey).toUint8Array(); - const secret = new BigInteger(keyPair.privateKey).toUint8Array('be', curve.payloadSize); - return { - oid: curve.oid, - Q, - secret, - hash: curve.hash, - cipher: curve.cipher - }; -} - -/** - * Get preferred hash algo to use with the given curve - * @param {module:type/oid} oid - curve oid - * @returns {enums.hash} hash algorithm - */ -function getPreferredHashAlgo(oid) { - return curves[enums.write(enums.curve, oid.toHex())].hash; -} - -/** - * Validate ECDH and ECDSA parameters - * Not suitable for EdDSA (different secret key format) - * @param {module:enums.publicKey} algo - EC algorithm, to filter supported curves - * @param {module:type/oid} oid - EC object identifier - * @param {Uint8Array} Q - EC public point - * @param {Uint8Array} d - EC secret scalar - * @returns {Promise} Whether params are valid. - * @async - */ -async function validateStandardParams(algo, oid, Q, d) { - const supportedCurves = { - p256: true, - p384: true, - p521: true, - secp256k1: true, - curve25519: algo === enums.publicKey.ecdh, - brainpoolP256r1: true, - brainpoolP384r1: true, - brainpoolP512r1: true - }; - - // Check whether the given curve is supported - const curveName = oid.getName(); - if (!supportedCurves[curveName]) { - return false; - } - - if (curveName === 'curve25519') { - d = d.slice().reverse(); - // Re-derive public point Q' - const { publicKey } = naclFastLight.box.keyPair.fromSecretKey(d); - - Q = new Uint8Array(Q); - const dG = new Uint8Array([0x40, ...publicKey]); // Add public key prefix - if (!util.equalsUint8Array(dG, Q)) { - return false; - } - - return true; - } - - const curve = await getIndutnyCurve(curveName); - try { - // Parse Q and check that it is on the curve but not at infinity - Q = keyFromPublic(curve, Q).getPublic(); - } catch (validationErrors) { - return false; - } - - /** - * Re-derive public point Q' = dG from private key - * Expect Q == Q' - */ - const dG = keyFromPrivate(curve, d).getPublic(); - if (!dG.eq(Q)) { - return false; - } - - return true; -} - -////////////////////////// -// // -// Helper functions // -// // -////////////////////////// - - -async function webGenKeyPair(name) { - // Note: keys generated with ECDSA and ECDH are structurally equivalent - const webCryptoKey = await webCrypto$6.generateKey({ name: 'ECDSA', namedCurve: webCurves[name] }, true, ['sign', 'verify']); - - const privateKey = await webCrypto$6.exportKey('jwk', webCryptoKey.privateKey); - const publicKey = await webCrypto$6.exportKey('jwk', webCryptoKey.publicKey); - - return { - publicKey: jwkToRawPublic(publicKey), - privateKey: b64ToUint8Array(privateKey.d) - }; -} - -async function nodeGenKeyPair(name) { - // Note: ECDSA and ECDH key generation is structurally equivalent - const ecdh = nodeCrypto$7.createECDH(nodeCurves[name]); - await ecdh.generateKeys(); - return { - publicKey: new Uint8Array(ecdh.getPublicKey()), - privateKey: new Uint8Array(ecdh.getPrivateKey()) - }; -} - -////////////////////////// -// // -// Helper functions // -// // -////////////////////////// - -/** - * @param {JsonWebKey} jwk - key for conversion - * - * @returns {Uint8Array} Raw public key. - */ -function jwkToRawPublic(jwk) { - const bufX = b64ToUint8Array(jwk.x); - const bufY = b64ToUint8Array(jwk.y); - const publicKey = new Uint8Array(bufX.length + bufY.length + 1); - publicKey[0] = 0x04; - publicKey.set(bufX, 1); - publicKey.set(bufY, bufX.length + 1); - return publicKey; -} - -/** - * @param {Integer} payloadSize - ec payload size - * @param {String} name - curve name - * @param {Uint8Array} publicKey - public key - * - * @returns {JsonWebKey} Public key in jwk format. - */ -function rawPublicToJWK(payloadSize, name, publicKey) { - const len = payloadSize; - const bufX = publicKey.slice(1, len + 1); - const bufY = publicKey.slice(len + 1, len * 2 + 1); - // https://www.rfc-editor.org/rfc/rfc7518.txt - const jwk = { - kty: 'EC', - crv: name, - x: uint8ArrayToB64(bufX, true), - y: uint8ArrayToB64(bufY, true), - ext: true - }; - return jwk; -} - -/** - * @param {Integer} payloadSize - ec payload size - * @param {String} name - curve name - * @param {Uint8Array} publicKey - public key - * @param {Uint8Array} privateKey - private key - * - * @returns {JsonWebKey} Private key in jwk format. - */ -function privateToJWK$1(payloadSize, name, publicKey, privateKey) { - const jwk = rawPublicToJWK(payloadSize, name, publicKey); - jwk.d = uint8ArrayToB64(privateKey, true); - return jwk; -} - -const webCrypto$7 = util.getWebCrypto(); -const nodeCrypto$8 = util.getNodeCrypto(); - -/** - * Sign a message using the provided key - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {module:enums.hash} hashAlgo - Hash algorithm used to sign - * @param {Uint8Array} message - Message to sign - * @param {Uint8Array} publicKey - Public key - * @param {Uint8Array} privateKey - Private key used to sign the message - * @param {Uint8Array} hashed - The hashed message - * @returns {Promise<{ - * r: Uint8Array, - * s: Uint8Array - * }>} Signature of the message - * @async - */ -async function sign$1(oid, hashAlgo, message, publicKey, privateKey, hashed) { - const curve = new Curve(oid); - if (message && !util.isStream(message)) { - const keyPair = { publicKey, privateKey }; - switch (curve.type) { - case 'web': { - // If browser doesn't support a curve, we'll catch it - try { - // Need to await to make sure browser succeeds - return await webSign$1(curve, hashAlgo, message, keyPair); - } catch (err) { - // We do not fallback if the error is related to key integrity - // Unfortunaley Safari does not support p521 and throws a DataError when using it - // So we need to always fallback for that curve - if (curve.name !== 'p521' && (err.name === 'DataError' || err.name === 'OperationError')) { - throw err; - } - util.printDebugError('Browser did not support signing: ' + err.message); - } - break; - } - case 'node': { - const signature = await nodeSign$1(curve, hashAlgo, message, keyPair); - return { - r: signature.r.toArrayLike(Uint8Array), - s: signature.s.toArrayLike(Uint8Array) - }; - } - } - } - return ellipticSign(curve, hashed, privateKey); -} - -/** - * Verifies if a signature is valid for a message - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {module:enums.hash} hashAlgo - Hash algorithm used in the signature - * @param {{r: Uint8Array, - s: Uint8Array}} signature Signature to verify - * @param {Uint8Array} message - Message to verify - * @param {Uint8Array} publicKey - Public key used to verify the message - * @param {Uint8Array} hashed - The hashed message - * @returns {Boolean} - * @async - */ -async function verify$1(oid, hashAlgo, signature, message, publicKey, hashed) { - const curve = new Curve(oid); - if (message && !util.isStream(message)) { - switch (curve.type) { - case 'web': - try { - // Need to await to make sure browser succeeds - return await webVerify$1(curve, hashAlgo, signature, message, publicKey); - } catch (err) { - // We do not fallback if the error is related to key integrity - // Unfortunately Safari does not support p521 and throws a DataError when using it - // So we need to always fallback for that curve - if (curve.name !== 'p521' && (err.name === 'DataError' || err.name === 'OperationError')) { - throw err; - } - util.printDebugError('Browser did not support verifying: ' + err.message); - } - break; - case 'node': - return nodeVerify$1(curve, hashAlgo, signature, message, publicKey); - } - } - const digest = (typeof hashAlgo === 'undefined') ? message : hashed; - return ellipticVerify(curve, signature, digest, publicKey); -} - -/** - * Validate ECDSA parameters - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {Uint8Array} Q - ECDSA public point - * @param {Uint8Array} d - ECDSA secret scalar - * @returns {Promise} Whether params are valid. - * @async - */ -async function validateParams$2(oid, Q, d) { - const curve = new Curve(oid); - // Reject curves x25519 and ed25519 - if (curve.keyType !== enums.publicKey.ecdsa) { - return false; - } - - // To speed up the validation, we try to use node- or webcrypto when available - // and sign + verify a random message - switch (curve.type) { - case 'web': - case 'node': { - const message = await getRandomBytes(8); - const hashAlgo = enums.hash.sha256; - const hashed = await hash.digest(hashAlgo, message); - try { - const signature = await sign$1(oid, hashAlgo, message, Q, d, hashed); - return await verify$1(oid, hashAlgo, signature, message, Q, hashed); - } catch (err) { - return false; - } - } - default: - return validateStandardParams(enums.publicKey.ecdsa, oid, Q, d); - } -} - - -////////////////////////// -// // -// Helper functions // -// // -////////////////////////// - -async function ellipticSign(curve, hashed, privateKey) { - const indutnyCurve = await getIndutnyCurve(curve.name); - const key = keyFromPrivate(indutnyCurve, privateKey); - const signature = key.sign(hashed); - return { - r: signature.r.toArrayLike(Uint8Array), - s: signature.s.toArrayLike(Uint8Array) - }; -} - -async function ellipticVerify(curve, signature, digest, publicKey) { - const indutnyCurve = await getIndutnyCurve(curve.name); - const key = keyFromPublic(indutnyCurve, publicKey); - return key.verify(digest, signature); -} - -async function webSign$1(curve, hashAlgo, message, keyPair) { - const len = curve.payloadSize; - const jwk = privateToJWK$1(curve.payloadSize, webCurves[curve.name], keyPair.publicKey, keyPair.privateKey); - const key = await webCrypto$7.importKey( - 'jwk', - jwk, - { - 'name': 'ECDSA', - 'namedCurve': webCurves[curve.name], - 'hash': { name: enums.read(enums.webHash, curve.hash) } - }, - false, - ['sign'] - ); - - const signature = new Uint8Array(await webCrypto$7.sign( - { - 'name': 'ECDSA', - 'namedCurve': webCurves[curve.name], - 'hash': { name: enums.read(enums.webHash, hashAlgo) } - }, - key, - message - )); - - return { - r: signature.slice(0, len), - s: signature.slice(len, len << 1) - }; -} - -async function webVerify$1(curve, hashAlgo, { r, s }, message, publicKey) { - const jwk = rawPublicToJWK(curve.payloadSize, webCurves[curve.name], publicKey); - const key = await webCrypto$7.importKey( - 'jwk', - jwk, - { - 'name': 'ECDSA', - 'namedCurve': webCurves[curve.name], - 'hash': { name: enums.read(enums.webHash, curve.hash) } - }, - false, - ['verify'] - ); - - const signature = util.concatUint8Array([r, s]).buffer; - - return webCrypto$7.verify( - { - 'name': 'ECDSA', - 'namedCurve': webCurves[curve.name], - 'hash': { name: enums.read(enums.webHash, hashAlgo) } - }, - key, - signature, - message - ); -} - -async function nodeSign$1(curve, hashAlgo, message, keyPair) { - const sign = nodeCrypto$8.createSign(enums.read(enums.hash, hashAlgo)); - sign.write(message); - sign.end(); - const key = ECPrivateKey.encode({ - version: 1, - parameters: curve.oid, - privateKey: Array.from(keyPair.privateKey), - publicKey: { unused: 0, data: Array.from(keyPair.publicKey) } - }, 'pem', { - label: 'EC PRIVATE KEY' - }); - - return ECDSASignature.decode(sign.sign(key), 'der'); -} - -async function nodeVerify$1(curve, hashAlgo, { r, s }, message, publicKey) { - const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); - - const verify = nodeCrypto$8.createVerify(enums.read(enums.hash, hashAlgo)); - verify.write(message); - verify.end(); - const key = SubjectPublicKeyInfo.encode({ - algorithm: { - algorithm: [1, 2, 840, 10045, 2, 1], - parameters: curve.oid - }, - subjectPublicKey: { unused: 0, data: Array.from(publicKey) } - }, 'pem', { - label: 'PUBLIC KEY' - }); - const signature = ECDSASignature.encode({ - r: new BN(r), s: new BN(s) - }, 'der'); - - try { - return verify.verify(key, signature); - } catch (err) { - return false; - } -} - -// Originally written by Owen Smith https://github.com/omsmith -// Adapted on Feb 2018 from https://github.com/Brightspace/node-jwk-to-pem/ - -/* eslint-disable no-invalid-this */ - -const asn1$1 = nodeCrypto$8 ? asn1__default['default'] : undefined; - -const ECDSASignature = nodeCrypto$8 ? - asn1$1.define('ECDSASignature', function() { - this.seq().obj( - this.key('r').int(), - this.key('s').int() - ); - }) : undefined; - -const ECPrivateKey = nodeCrypto$8 ? - asn1$1.define('ECPrivateKey', function() { - this.seq().obj( - this.key('version').int(), - this.key('privateKey').octstr(), - this.key('parameters').explicit(0).optional().any(), - this.key('publicKey').explicit(1).optional().bitstr() - ); - }) : undefined; - -const AlgorithmIdentifier = nodeCrypto$8 ? - asn1$1.define('AlgorithmIdentifier', function() { - this.seq().obj( - this.key('algorithm').objid(), - this.key('parameters').optional().any() - ); - }) : undefined; - -const SubjectPublicKeyInfo = nodeCrypto$8 ? - asn1$1.define('SubjectPublicKeyInfo', function() { - this.seq().obj( - this.key('algorithm').use(AlgorithmIdentifier), - this.key('subjectPublicKey').bitstr() - ); - }) : undefined; - -var ecdsa = /*#__PURE__*/Object.freeze({ - __proto__: null, - sign: sign$1, - verify: verify$1, - validateParams: validateParams$2 -}); - -// OpenPGP.js - An OpenPGP implementation in javascript - -naclFastLight.hash = bytes => new Uint8Array(_512().update(bytes).digest()); - -/** - * Sign a message using the provided key - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {module:enums.hash} hashAlgo - Hash algorithm used to sign (must be sha256 or stronger) - * @param {Uint8Array} message - Message to sign - * @param {Uint8Array} publicKey - Public key - * @param {Uint8Array} privateKey - Private key used to sign the message - * @param {Uint8Array} hashed - The hashed message - * @returns {Promise<{ - * r: Uint8Array, - * s: Uint8Array - * }>} Signature of the message - * @async - */ -async function sign$2(oid, hashAlgo, message, publicKey, privateKey, hashed) { - if (hash.getHashByteLength(hashAlgo) < hash.getHashByteLength(enums.hash.sha256)) { - // see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2 - throw new Error('Hash algorithm too weak: sha256 or stronger is required for EdDSA.'); - } - const secretKey = util.concatUint8Array([privateKey, publicKey.subarray(1)]); - const signature = naclFastLight.sign.detached(hashed, secretKey); - // EdDSA signature params are returned in little-endian format - return { - r: signature.subarray(0, 32), - s: signature.subarray(32) - }; -} - -/** - * Verifies if a signature is valid for a message - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {module:enums.hash} hashAlgo - Hash algorithm used in the signature - * @param {{r: Uint8Array, - s: Uint8Array}} signature Signature to verify the message - * @param {Uint8Array} m - Message to verify - * @param {Uint8Array} publicKey - Public key used to verify the message - * @param {Uint8Array} hashed - The hashed message - * @returns {Boolean} - * @async - */ -async function verify$2(oid, hashAlgo, { r, s }, m, publicKey, hashed) { - const signature = util.concatUint8Array([r, s]); - return naclFastLight.sign.detached.verify(hashed, signature, publicKey.subarray(1)); -} -/** - * Validate EdDSA parameters - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {Uint8Array} Q - EdDSA public point - * @param {Uint8Array} k - EdDSA secret seed - * @returns {Promise} Whether params are valid. - * @async - */ -async function validateParams$3(oid, Q, k) { - // Check whether the given curve is supported - if (oid.getName() !== 'ed25519') { - return false; - } - - /** - * Derive public point Q' = dG from private key - * and expect Q == Q' - */ - const { publicKey } = naclFastLight.sign.keyPair.fromSeed(k); - const dG = new Uint8Array([0x40, ...publicKey]); // Add public key prefix - return util.equalsUint8Array(Q, dG); -} - -var eddsa = /*#__PURE__*/Object.freeze({ - __proto__: null, - sign: sign$2, - verify: verify$2, - validateParams: validateParams$3 -}); - -// OpenPGP.js - An OpenPGP implementation in javascript - -/** - * AES key wrap - * @function - * @param {Uint8Array} key - * @param {Uint8Array} data - * @returns {Uint8Array} - */ -function wrap(key, data) { - const aes = new cipher['aes' + (key.length * 8)](key); - const IV = new Uint32Array([0xA6A6A6A6, 0xA6A6A6A6]); - const P = unpack(data); - let A = IV; - const R = P; - const n = P.length / 2; - const t = new Uint32Array([0, 0]); - let B = new Uint32Array(4); - for (let j = 0; j <= 5; ++j) { - for (let i = 0; i < n; ++i) { - t[1] = n * j + (1 + i); - // B = A - B[0] = A[0]; - B[1] = A[1]; - // B = A || R[i] - B[2] = R[2 * i]; - B[3] = R[2 * i + 1]; - // B = AES(K, B) - B = unpack(aes.encrypt(pack(B))); - // A = MSB(64, B) ^ t - A = B.subarray(0, 2); - A[0] ^= t[0]; - A[1] ^= t[1]; - // R[i] = LSB(64, B) - R[2 * i] = B[2]; - R[2 * i + 1] = B[3]; - } - } - return pack(A, R); -} - -/** - * AES key unwrap - * @function - * @param {String} key - * @param {String} data - * @returns {Uint8Array} - * @throws {Error} - */ -function unwrap(key, data) { - const aes = new cipher['aes' + (key.length * 8)](key); - const IV = new Uint32Array([0xA6A6A6A6, 0xA6A6A6A6]); - const C = unpack(data); - let A = C.subarray(0, 2); - const R = C.subarray(2); - const n = C.length / 2 - 1; - const t = new Uint32Array([0, 0]); - let B = new Uint32Array(4); - for (let j = 5; j >= 0; --j) { - for (let i = n - 1; i >= 0; --i) { - t[1] = n * j + (i + 1); - // B = A ^ t - B[0] = A[0] ^ t[0]; - B[1] = A[1] ^ t[1]; - // B = (A ^ t) || R[i] - B[2] = R[2 * i]; - B[3] = R[2 * i + 1]; - // B = AES-1(B) - B = unpack(aes.decrypt(pack(B))); - // A = MSB(64, B) - A = B.subarray(0, 2); - // R[i] = LSB(64, B) - R[2 * i] = B[2]; - R[2 * i + 1] = B[3]; - } - } - if (A[0] === IV[0] && A[1] === IV[1]) { - return pack(R); - } - throw new Error('Key Data Integrity failed'); -} - -function createArrayBuffer(data) { - if (util.isString(data)) { - const { length } = data; - const buffer = new ArrayBuffer(length); - const view = new Uint8Array(buffer); - for (let j = 0; j < length; ++j) { - view[j] = data.charCodeAt(j); - } - return buffer; - } - return new Uint8Array(data).buffer; -} - -function unpack(data) { - const { length } = data; - const buffer = createArrayBuffer(data); - const view = new DataView(buffer); - const arr = new Uint32Array(length / 4); - for (let i = 0; i < length / 4; ++i) { - arr[i] = view.getUint32(4 * i); - } - return arr; -} - -function pack() { - let length = 0; - for (let k = 0; k < arguments.length; ++k) { - length += 4 * arguments[k].length; - } - const buffer = new ArrayBuffer(length); - const view = new DataView(buffer); - let offset = 0; - for (let i = 0; i < arguments.length; ++i) { - for (let j = 0; j < arguments[i].length; ++j) { - view.setUint32(offset + 4 * j, arguments[i][j]); - } - offset += 4 * arguments[i].length; - } - return new Uint8Array(buffer); -} - -var aesKW = /*#__PURE__*/Object.freeze({ - __proto__: null, - wrap: wrap, - unwrap: unwrap -}); - -// OpenPGP.js - An OpenPGP implementation in javascript - -/** - * @fileoverview Functions to add and remove PKCS5 padding - * @see PublicKeyEncryptedSessionKeyPacket - * @module crypto/pkcs5 - * @private - */ - -/** - * Add pkcs5 padding to a message - * @param {Uint8Array} message - message to pad - * @returns {Uint8Array} Padded message. - */ -function encode$1(message) { - const c = 8 - (message.length % 8); - const padded = new Uint8Array(message.length + c).fill(c); - padded.set(message); - return padded; -} - -/** - * Remove pkcs5 padding from a message - * @param {Uint8Array} message - message to remove padding from - * @returns {Uint8Array} Message without padding. - */ -function decode$1(message) { - const len = message.length; - if (len > 0) { - const c = message[len - 1]; - if (c >= 1) { - const provided = message.subarray(len - c); - const computed = new Uint8Array(c).fill(c); - if (util.equalsUint8Array(provided, computed)) { - return message.subarray(0, len - c); - } - } - } - throw new Error('Invalid padding'); -} - -var pkcs5 = /*#__PURE__*/Object.freeze({ - __proto__: null, - encode: encode$1, - decode: decode$1 -}); - -// OpenPGP.js - An OpenPGP implementation in javascript - -class ECDHSymmetricKey { - constructor(data) { - if (typeof data === 'undefined') { - data = new Uint8Array([]); - } else if (util.isString(data)) { - data = util.stringToUint8Array(data); - } else { - data = new Uint8Array(data); - } - this.data = data; - } - - /** - * Read an ECDHSymmetricKey from an Uint8Array - * @param {Uint8Array} input - Where to read the encoded symmetric key from - * @returns {Number} Number of read bytes. - */ - read(input) { - if (input.length >= 1) { - const length = input[0]; - if (input.length >= 1 + length) { - this.data = input.subarray(1, 1 + length); - return 1 + this.data.length; - } - } - throw new Error('Invalid symmetric key'); - } - - /** - * Write an ECDHSymmetricKey as an Uint8Array - * @returns {Uint8Array} An array containing the value - */ - write() { - return util.concatUint8Array([new Uint8Array([this.data.length]), this.data]); - } -} - -// OpenPGP.js - An OpenPGP implementation in javascript -// Copyright (C) 2015-2016 Decentral -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3.0 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -/** - * Implementation of type KDF parameters - * - * {@link https://tools.ietf.org/html/rfc6637#section-7|RFC 6637 7}: - * A key derivation function (KDF) is necessary to implement the EC - * encryption. The Concatenation Key Derivation Function (Approved - * Alternative 1) [NIST-SP800-56A] with the KDF hash function that is - * SHA2-256 [FIPS-180-3] or stronger is REQUIRED. - * @module type/kdf_params - * @private - */ - -class KDFParams { - /** - * @param {enums.hash} hash - Hash algorithm - * @param {enums.symmetric} cipher - Symmetric algorithm - */ - constructor(data) { - if (data) { - const { hash, cipher } = data; - this.hash = hash; - this.cipher = cipher; - } else { - this.hash = null; - this.cipher = null; - } - } - - /** - * Read KDFParams from an Uint8Array - * @param {Uint8Array} input - Where to read the KDFParams from - * @returns {Number} Number of read bytes. - */ - read(input) { - if (input.length < 4 || input[0] !== 3 || input[1] !== 1) { - throw new Error('Cannot read KDFParams'); - } - this.hash = input[2]; - this.cipher = input[3]; - return 4; - } - - /** - * Write KDFParams to an Uint8Array - * @returns {Uint8Array} Array with the KDFParams value - */ - write() { - return new Uint8Array([3, 1, this.hash, this.cipher]); - } -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -/** - * Encrypts data using specified algorithm and public key parameters. - * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} for public key algorithms. - * @param {module:enums.publicKey} algo - Public key algorithm - * @param {Object} publicParams - Algorithm-specific public key parameters - * @param {Uint8Array} data - Data to be encrypted - * @param {Uint8Array} fingerprint - Recipient fingerprint - * @returns {Promise} Encrypted session key parameters. - * @async - */ -async function publicKeyEncrypt(algo, publicParams, data, fingerprint) { - switch (algo) { - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaEncryptSign: { - const { n, e } = publicParams; - const c = await publicKey.rsa.encrypt(data, n, e); - return { c }; - } - case enums.publicKey.elgamal: { - const { p, g, y } = publicParams; - return publicKey.elgamal.encrypt(data, p, g, y); - } - case enums.publicKey.ecdh: { - const { oid, Q, kdfParams } = publicParams; - const { publicKey: V, wrappedKey: C } = await publicKey.elliptic.ecdh.encrypt( - oid, kdfParams, data, Q, fingerprint); - return { V, C: new ECDHSymmetricKey(C) }; - } - default: - return []; - } -} - -/** - * Decrypts data using specified algorithm and private key parameters. - * See {@link https://tools.ietf.org/html/rfc4880#section-5.5.3|RFC 4880 5.5.3} - * @param {module:enums.publicKey} algo - Public key algorithm - * @param {Object} publicKeyParams - Algorithm-specific public key parameters - * @param {Object} privateKeyParams - Algorithm-specific private key parameters - * @param {Object} sessionKeyParams - Encrypted session key parameters - * @param {Uint8Array} fingerprint - Recipient fingerprint - * @param {Uint8Array} [randomPayload] - Data to return on decryption error, instead of throwing - * (needed for constant-time processing in RSA and ElGamal) - * @returns {Promise} Decrypted data. - * @throws {Error} on sensitive decryption error, unless `randomPayload` is given - * @async - */ -async function publicKeyDecrypt(algo, publicKeyParams, privateKeyParams, sessionKeyParams, fingerprint, randomPayload) { - switch (algo) { - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaEncrypt: { - const { c } = sessionKeyParams; - const { n, e } = publicKeyParams; - const { d, p, q, u } = privateKeyParams; - return publicKey.rsa.decrypt(c, n, e, d, p, q, u, randomPayload); - } - case enums.publicKey.elgamal: { - const { c1, c2 } = sessionKeyParams; - const p = publicKeyParams.p; - const x = privateKeyParams.x; - return publicKey.elgamal.decrypt(c1, c2, p, x, randomPayload); - } - case enums.publicKey.ecdh: { - const { oid, Q, kdfParams } = publicKeyParams; - const { d } = privateKeyParams; - const { V, C } = sessionKeyParams; - return publicKey.elliptic.ecdh.decrypt( - oid, kdfParams, V, C.data, Q, d, fingerprint); - } - default: - throw new Error('Invalid public key encryption algorithm.'); - } -} - -/** - * Parse public key material in binary form to get the key parameters - * @param {module:enums.publicKey} algo - The key algorithm - * @param {Uint8Array} bytes - The key material to parse - * @returns {{ read: Number, publicParams: Object }} Number of read bytes plus key parameters referenced by name. - */ -function parsePublicKeyParams(algo, bytes) { - let read = 0; - switch (algo) { - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaSign: { - const n = util.readMPI(bytes.subarray(read)); read += n.length + 2; - const e = util.readMPI(bytes.subarray(read)); read += e.length + 2; - return { read, publicParams: { n, e } }; - } - case enums.publicKey.dsa: { - const p = util.readMPI(bytes.subarray(read)); read += p.length + 2; - const q = util.readMPI(bytes.subarray(read)); read += q.length + 2; - const g = util.readMPI(bytes.subarray(read)); read += g.length + 2; - const y = util.readMPI(bytes.subarray(read)); read += y.length + 2; - return { read, publicParams: { p, q, g, y } }; - } - case enums.publicKey.elgamal: { - const p = util.readMPI(bytes.subarray(read)); read += p.length + 2; - const g = util.readMPI(bytes.subarray(read)); read += g.length + 2; - const y = util.readMPI(bytes.subarray(read)); read += y.length + 2; - return { read, publicParams: { p, g, y } }; - } - case enums.publicKey.ecdsa: { - const oid = new OID(); read += oid.read(bytes); - const Q = util.readMPI(bytes.subarray(read)); read += Q.length + 2; - return { read: read, publicParams: { oid, Q } }; - } - case enums.publicKey.eddsa: { - const oid = new OID(); read += oid.read(bytes); - let Q = util.readMPI(bytes.subarray(read)); read += Q.length + 2; - Q = util.leftPad(Q, 33); - return { read: read, publicParams: { oid, Q } }; - } - case enums.publicKey.ecdh: { - const oid = new OID(); read += oid.read(bytes); - const Q = util.readMPI(bytes.subarray(read)); read += Q.length + 2; - const kdfParams = new KDFParams(); read += kdfParams.read(bytes.subarray(read)); - return { read: read, publicParams: { oid, Q, kdfParams } }; - } - default: - throw new Error('Invalid public key encryption algorithm.'); - } -} - -/** - * Parse private key material in binary form to get the key parameters - * @param {module:enums.publicKey} algo - The key algorithm - * @param {Uint8Array} bytes - The key material to parse - * @param {Object} publicParams - (ECC only) public params, needed to format some private params - * @returns {{ read: Number, privateParams: Object }} Number of read bytes plus the key parameters referenced by name. - */ -function parsePrivateKeyParams(algo, bytes, publicParams) { - let read = 0; - switch (algo) { - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaSign: { - const d = util.readMPI(bytes.subarray(read)); read += d.length + 2; - const p = util.readMPI(bytes.subarray(read)); read += p.length + 2; - const q = util.readMPI(bytes.subarray(read)); read += q.length + 2; - const u = util.readMPI(bytes.subarray(read)); read += u.length + 2; - return { read, privateParams: { d, p, q, u } }; - } - case enums.publicKey.dsa: - case enums.publicKey.elgamal: { - const x = util.readMPI(bytes.subarray(read)); read += x.length + 2; - return { read, privateParams: { x } }; - } - case enums.publicKey.ecdsa: - case enums.publicKey.ecdh: { - const curve = new Curve(publicParams.oid); - let d = util.readMPI(bytes.subarray(read)); read += d.length + 2; - d = util.leftPad(d, curve.payloadSize); - return { read, privateParams: { d } }; - } - case enums.publicKey.eddsa: { - let seed = util.readMPI(bytes.subarray(read)); read += seed.length + 2; - seed = util.leftPad(seed, 32); - return { read, privateParams: { seed } }; - } - default: - throw new Error('Invalid public key encryption algorithm.'); - } -} - -/** Returns the types comprising the encrypted session key of an algorithm - * @param {module:enums.publicKey} algo - The key algorithm - * @param {Uint8Array} bytes - The key material to parse - * @returns {Object} The session key parameters referenced by name. - */ -function parseEncSessionKeyParams(algo, bytes) { - let read = 0; - switch (algo) { - // Algorithm-Specific Fields for RSA encrypted session keys: - // - MPI of RSA encrypted value m**e mod n. - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaEncryptSign: { - const c = util.readMPI(bytes.subarray(read)); - return { c }; - } - - // Algorithm-Specific Fields for Elgamal encrypted session keys: - // - MPI of Elgamal value g**k mod p - // - MPI of Elgamal value m * y**k mod p - case enums.publicKey.elgamal: { - const c1 = util.readMPI(bytes.subarray(read)); read += c1.length + 2; - const c2 = util.readMPI(bytes.subarray(read)); - return { c1, c2 }; - } - // Algorithm-Specific Fields for ECDH encrypted session keys: - // - MPI containing the ephemeral key used to establish the shared secret - // - ECDH Symmetric Key - case enums.publicKey.ecdh: { - const V = util.readMPI(bytes.subarray(read)); read += V.length + 2; - const C = new ECDHSymmetricKey(); C.read(bytes.subarray(read)); - return { V, C }; - } - default: - throw new Error('Invalid public key encryption algorithm.'); - } -} - -/** - * Convert params to MPI and serializes them in the proper order - * @param {module:enums.publicKey} algo - The public key algorithm - * @param {Object} params - The key parameters indexed by name - * @returns {Uint8Array} The array containing the MPIs. - */ -function serializeParams(algo, params) { - const orderedParams = Object.keys(params).map(name => { - const param = params[name]; - return util.isUint8Array(param) ? util.uint8ArrayToMPI(param) : param.write(); - }); - return util.concatUint8Array(orderedParams); -} - -/** - * Generate algorithm-specific key parameters - * @param {module:enums.publicKey} algo - The public key algorithm - * @param {Integer} bits - Bit length for RSA keys - * @param {module:type/oid} oid - Object identifier for ECC keys - * @returns {Promise<{ publicParams: {Object}, privateParams: {Object} }>} The parameters referenced by name. - * @async - */ -function generateParams(algo, bits, oid) { - switch (algo) { - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaSign: { - return publicKey.rsa.generate(bits, 65537).then(({ n, e, d, p, q, u }) => ({ - privateParams: { d, p, q, u }, - publicParams: { n, e } - })); - } - case enums.publicKey.ecdsa: - return publicKey.elliptic.generate(oid).then(({ oid, Q, secret }) => ({ - privateParams: { d: secret }, - publicParams: { oid: new OID(oid), Q } - })); - case enums.publicKey.eddsa: - return publicKey.elliptic.generate(oid).then(({ oid, Q, secret }) => ({ - privateParams: { seed: secret }, - publicParams: { oid: new OID(oid), Q } - })); - case enums.publicKey.ecdh: - return publicKey.elliptic.generate(oid).then(({ oid, Q, secret, hash, cipher }) => ({ - privateParams: { d: secret }, - publicParams: { - oid: new OID(oid), - Q, - kdfParams: new KDFParams({ hash, cipher }) - } - })); - case enums.publicKey.dsa: - case enums.publicKey.elgamal: - throw new Error('Unsupported algorithm for key generation.'); - default: - throw new Error('Invalid public key algorithm.'); - } -} - -/** - * Validate algorithm-specific key parameters - * @param {module:enums.publicKey} algo - The public key algorithm - * @param {Object} publicParams - Algorithm-specific public key parameters - * @param {Object} privateParams - Algorithm-specific private key parameters - * @returns {Promise} Whether the parameters are valid. - * @async - */ -async function validateParams$4(algo, publicParams, privateParams) { - if (!publicParams || !privateParams) { - throw new Error('Missing key parameters'); - } - switch (algo) { - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaSign: { - const { n, e } = publicParams; - const { d, p, q, u } = privateParams; - return publicKey.rsa.validateParams(n, e, d, p, q, u); - } - case enums.publicKey.dsa: { - const { p, q, g, y } = publicParams; - const { x } = privateParams; - return publicKey.dsa.validateParams(p, q, g, y, x); - } - case enums.publicKey.elgamal: { - const { p, g, y } = publicParams; - const { x } = privateParams; - return publicKey.elgamal.validateParams(p, g, y, x); - } - case enums.publicKey.ecdsa: - case enums.publicKey.ecdh: { - const algoModule = publicKey.elliptic[enums.read(enums.publicKey, algo)]; - const { oid, Q } = publicParams; - const { d } = privateParams; - return algoModule.validateParams(oid, Q, d); - } - case enums.publicKey.eddsa: { - const { oid, Q } = publicParams; - const { seed } = privateParams; - return publicKey.elliptic.eddsa.validateParams(oid, Q, seed); - } - default: - throw new Error('Invalid public key algorithm.'); - } -} - -/** - * Generates a random byte prefix for the specified algorithm - * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. - * @param {module:enums.symmetric} algo - Symmetric encryption algorithm - * @returns {Promise} Random bytes with length equal to the block size of the cipher, plus the last two bytes repeated. - * @async - */ -async function getPrefixRandom(algo) { - const { blockSize } = getCipher(algo); - const prefixrandom = await getRandomBytes(blockSize); - const repeat = new Uint8Array([prefixrandom[prefixrandom.length - 2], prefixrandom[prefixrandom.length - 1]]); - return util.concat([prefixrandom, repeat]); -} - -/** - * Generating a session key for the specified symmetric algorithm - * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. - * @param {module:enums.symmetric} algo - Symmetric encryption algorithm - * @returns {Promise} Random bytes as a string to be used as a key. - * @async - */ -function generateSessionKey(algo) { - const { keySize } = getCipher(algo); - return getRandomBytes(keySize); -} - -/** - * Get implementation of the given AEAD mode - * @param {enums.aead} algo - * @returns {Object} - * @throws {Error} on invalid algo - */ -function getAEADMode(algo) { - const algoName = enums.read(enums.aead, algo); - return mode[algoName]; -} - -/** - * Get implementation of the given cipher - * @param {enums.symmetric} algo - * @returns {Object} - * @throws {Error} on invalid algo - */ -function getCipher(algo) { - const algoName = enums.read(enums.symmetric, algo); - return cipher[algoName]; -} - -var crypto$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - publicKeyEncrypt: publicKeyEncrypt, - publicKeyDecrypt: publicKeyDecrypt, - parsePublicKeyParams: parsePublicKeyParams, - parsePrivateKeyParams: parsePrivateKeyParams, - parseEncSessionKeyParams: parseEncSessionKeyParams, - serializeParams: serializeParams, - generateParams: generateParams, - validateParams: validateParams$4, - getPrefixRandom: getPrefixRandom, - generateSessionKey: generateSessionKey, - getAEADMode: getAEADMode, - getCipher: getCipher -}); - -// OpenPGP.js - An OpenPGP implementation in javascript - -const webCrypto$8 = util.getWebCrypto(); -const nodeCrypto$9 = util.getNodeCrypto(); - -/** - * Validate ECDH parameters - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {Uint8Array} Q - ECDH public point - * @param {Uint8Array} d - ECDH secret scalar - * @returns {Promise} Whether params are valid. - * @async - */ -async function validateParams$5(oid, Q, d) { - return validateStandardParams(enums.publicKey.ecdh, oid, Q, d); -} - -// Build Param for ECDH algorithm (RFC 6637) -function buildEcdhParam(public_algo, oid, kdfParams, fingerprint) { - return util.concatUint8Array([ - oid.write(), - new Uint8Array([public_algo]), - kdfParams.write(), - util.stringToUint8Array('Anonymous Sender '), - fingerprint.subarray(0, 20) - ]); -} - -// Key Derivation Function (RFC 6637) -async function kdf(hashAlgo, X, length, param, stripLeading = false, stripTrailing = false) { - // Note: X is little endian for Curve25519, big-endian for all others. - // This is not ideal, but the RFC's are unclear - // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B - let i; - if (stripLeading) { - // Work around old go crypto bug - for (i = 0; i < X.length && X[i] === 0; i++); - X = X.subarray(i); - } - if (stripTrailing) { - // Work around old OpenPGP.js bug - for (i = X.length - 1; i >= 0 && X[i] === 0; i--); - X = X.subarray(0, i + 1); - } - const digest = await hash.digest(hashAlgo, util.concatUint8Array([ - new Uint8Array([0, 0, 0, 1]), - X, - param - ])); - return digest.subarray(0, length); -} - -/** - * Generate ECDHE ephemeral key and secret from public key - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} Q - Recipient public key - * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ -async function genPublicEphemeralKey(curve, Q) { - switch (curve.type) { - case 'curve25519': { - const d = await getRandomBytes(32); - const { secretKey, sharedKey } = await genPrivateEphemeralKey(curve, Q, null, d); - let { publicKey } = naclFastLight.box.keyPair.fromSecretKey(secretKey); - publicKey = util.concatUint8Array([new Uint8Array([0x40]), publicKey]); - return { publicKey, sharedKey }; // Note: sharedKey is little-endian here, unlike below - } - case 'web': - if (curve.web && util.getWebCrypto()) { - try { - return await webPublicEphemeralKey(curve, Q); - } catch (err) { - util.printDebugError(err); - } - } - break; - case 'node': - return nodePublicEphemeralKey(curve, Q); - } - return ellipticPublicEphemeralKey(curve, Q); -} - -/** - * Encrypt and wrap a session key - * - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {module:type/kdf_params} kdfParams - KDF params including cipher and algorithm to use - * @param {Uint8Array} data - Unpadded session key data - * @param {Uint8Array} Q - Recipient public key - * @param {Uint8Array} fingerprint - Recipient fingerprint - * @returns {Promise<{publicKey: Uint8Array, wrappedKey: Uint8Array}>} - * @async - */ -async function encrypt$3(oid, kdfParams, data, Q, fingerprint) { - const m = encode$1(data); - - const curve = new Curve(oid); - const { publicKey, sharedKey } = await genPublicEphemeralKey(curve, Q); - const param = buildEcdhParam(enums.publicKey.ecdh, oid, kdfParams, fingerprint); - const { keySize } = getCipher(kdfParams.cipher); - const Z = await kdf(kdfParams.hash, sharedKey, keySize, param); - const wrappedKey = wrap(Z, m); - return { publicKey, wrappedKey }; -} - -/** - * Generate ECDHE secret from private key and public part of ephemeral key - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} V - Public part of ephemeral key - * @param {Uint8Array} Q - Recipient public key - * @param {Uint8Array} d - Recipient private key - * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ -async function genPrivateEphemeralKey(curve, V, Q, d) { - if (d.length !== curve.payloadSize) { - const privateKey = new Uint8Array(curve.payloadSize); - privateKey.set(d, curve.payloadSize - d.length); - d = privateKey; - } - switch (curve.type) { - case 'curve25519': { - const secretKey = d.slice().reverse(); - const sharedKey = naclFastLight.scalarMult(secretKey, V.subarray(1)); - return { secretKey, sharedKey }; // Note: sharedKey is little-endian here, unlike below - } - case 'web': - if (curve.web && util.getWebCrypto()) { - try { - return await webPrivateEphemeralKey(curve, V, Q, d); - } catch (err) { - util.printDebugError(err); - } - } - break; - case 'node': - return nodePrivateEphemeralKey(curve, V, d); - } - return ellipticPrivateEphemeralKey(curve, V, d); -} - -/** - * Decrypt and unwrap the value derived from session key - * - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {module:type/kdf_params} kdfParams - KDF params including cipher and algorithm to use - * @param {Uint8Array} V - Public part of ephemeral key - * @param {Uint8Array} C - Encrypted and wrapped value derived from session key - * @param {Uint8Array} Q - Recipient public key - * @param {Uint8Array} d - Recipient private key - * @param {Uint8Array} fingerprint - Recipient fingerprint - * @returns {Promise} Value derived from session key. - * @async - */ -async function decrypt$3(oid, kdfParams, V, C, Q, d, fingerprint) { - const curve = new Curve(oid); - const { sharedKey } = await genPrivateEphemeralKey(curve, V, Q, d); - const param = buildEcdhParam(enums.publicKey.ecdh, oid, kdfParams, fingerprint); - const { keySize } = getCipher(kdfParams.cipher); - let err; - for (let i = 0; i < 3; i++) { - try { - // Work around old go crypto bug and old OpenPGP.js bug, respectively. - const Z = await kdf(kdfParams.hash, sharedKey, keySize, param, i === 1, i === 2); - return decode$1(unwrap(Z, C)); - } catch (e) { - err = e; - } - } - throw err; -} - -/** - * Generate ECDHE secret from private key and public part of ephemeral key using webCrypto - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} V - Public part of ephemeral key - * @param {Uint8Array} Q - Recipient public key - * @param {Uint8Array} d - Recipient private key - * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ -async function webPrivateEphemeralKey(curve, V, Q, d) { - const recipient = privateToJWK$1(curve.payloadSize, curve.web.web, Q, d); - let privateKey = webCrypto$8.importKey( - 'jwk', - recipient, - { - name: 'ECDH', - namedCurve: curve.web.web - }, - true, - ['deriveKey', 'deriveBits'] - ); - const jwk = rawPublicToJWK(curve.payloadSize, curve.web.web, V); - let sender = webCrypto$8.importKey( - 'jwk', - jwk, - { - name: 'ECDH', - namedCurve: curve.web.web - }, - true, - [] - ); - [privateKey, sender] = await Promise.all([privateKey, sender]); - let S = webCrypto$8.deriveBits( - { - name: 'ECDH', - namedCurve: curve.web.web, - public: sender - }, - privateKey, - curve.web.sharedSize - ); - let secret = webCrypto$8.exportKey( - 'jwk', - privateKey - ); - [S, secret] = await Promise.all([S, secret]); - const sharedKey = new Uint8Array(S); - const secretKey = b64ToUint8Array(secret.d); - return { secretKey, sharedKey }; -} - -/** - * Generate ECDHE ephemeral key and secret from public key using webCrypto - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} Q - Recipient public key - * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ -async function webPublicEphemeralKey(curve, Q) { - const jwk = rawPublicToJWK(curve.payloadSize, curve.web.web, Q); - let keyPair = webCrypto$8.generateKey( - { - name: 'ECDH', - namedCurve: curve.web.web - }, - true, - ['deriveKey', 'deriveBits'] - ); - let recipient = webCrypto$8.importKey( - 'jwk', - jwk, - { - name: 'ECDH', - namedCurve: curve.web.web - }, - false, - [] - ); - [keyPair, recipient] = await Promise.all([keyPair, recipient]); - let s = webCrypto$8.deriveBits( - { - name: 'ECDH', - namedCurve: curve.web.web, - public: recipient - }, - keyPair.privateKey, - curve.web.sharedSize - ); - let p = webCrypto$8.exportKey( - 'jwk', - keyPair.publicKey - ); - [s, p] = await Promise.all([s, p]); - const sharedKey = new Uint8Array(s); - const publicKey = new Uint8Array(jwkToRawPublic(p)); - return { publicKey, sharedKey }; -} - -/** - * Generate ECDHE secret from private key and public part of ephemeral key using indutny/elliptic - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} V - Public part of ephemeral key - * @param {Uint8Array} d - Recipient private key - * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ -async function ellipticPrivateEphemeralKey(curve, V, d) { - const indutnyCurve = await getIndutnyCurve(curve.name); - V = keyFromPublic(indutnyCurve, V); - d = keyFromPrivate(indutnyCurve, d); - const secretKey = new Uint8Array(d.getPrivate()); - const S = d.derive(V.getPublic()); - const len = indutnyCurve.curve.p.byteLength(); - const sharedKey = S.toArrayLike(Uint8Array, 'be', len); - return { secretKey, sharedKey }; -} - -/** - * Generate ECDHE ephemeral key and secret from public key using indutny/elliptic - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} Q - Recipient public key - * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ -async function ellipticPublicEphemeralKey(curve, Q) { - const indutnyCurve = await getIndutnyCurve(curve.name); - const v = await curve.genKeyPair(); - Q = keyFromPublic(indutnyCurve, Q); - const V = keyFromPrivate(indutnyCurve, v.privateKey); - const publicKey = v.publicKey; - const S = V.derive(Q.getPublic()); - const len = indutnyCurve.curve.p.byteLength(); - const sharedKey = S.toArrayLike(Uint8Array, 'be', len); - return { publicKey, sharedKey }; -} - -/** - * Generate ECDHE secret from private key and public part of ephemeral key using nodeCrypto - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} V - Public part of ephemeral key - * @param {Uint8Array} d - Recipient private key - * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ -async function nodePrivateEphemeralKey(curve, V, d) { - const recipient = nodeCrypto$9.createECDH(curve.node.node); - recipient.setPrivateKey(d); - const sharedKey = new Uint8Array(recipient.computeSecret(V)); - const secretKey = new Uint8Array(recipient.getPrivateKey()); - return { secretKey, sharedKey }; -} - -/** - * Generate ECDHE ephemeral key and secret from public key using nodeCrypto - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} Q - Recipient public key - * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ -async function nodePublicEphemeralKey(curve, Q) { - const sender = nodeCrypto$9.createECDH(curve.node.node); - sender.generateKeys(); - const sharedKey = new Uint8Array(sender.computeSecret(Q)); - const publicKey = new Uint8Array(sender.getPublicKey()); - return { publicKey, sharedKey }; -} - -var ecdh = /*#__PURE__*/Object.freeze({ - __proto__: null, - validateParams: validateParams$5, - encrypt: encrypt$3, - decrypt: decrypt$3 -}); - -// OpenPGP.js - An OpenPGP implementation in javascript - -var elliptic = /*#__PURE__*/Object.freeze({ - __proto__: null, - Curve: Curve, - ecdh: ecdh, - ecdsa: ecdsa, - eddsa: eddsa, - generate: generate$1, - getPreferredHashAlgo: getPreferredHashAlgo -}); - -// GPG4Browsers - An OpenPGP implementation in javascript - -/* - TODO regarding the hash function, read: - https://tools.ietf.org/html/rfc4880#section-13.6 - https://tools.ietf.org/html/rfc4880#section-14 -*/ - -/** - * DSA Sign function - * @param {Integer} hashAlgo - * @param {Uint8Array} hashed - * @param {Uint8Array} g - * @param {Uint8Array} p - * @param {Uint8Array} q - * @param {Uint8Array} x - * @returns {Promise<{ r: Uint8Array, s: Uint8Array }>} - * @async - */ -async function sign$3(hashAlgo, hashed, g, p, q, x) { - const BigInteger = await util.getBigInteger(); - const one = new BigInteger(1); - p = new BigInteger(p); - q = new BigInteger(q); - g = new BigInteger(g); - x = new BigInteger(x); - - let k; - let r; - let s; - let t; - g = g.mod(p); - x = x.mod(q); - // If the output size of the chosen hash is larger than the number of - // bits of q, the hash result is truncated to fit by taking the number - // of leftmost bits equal to the number of bits of q. This (possibly - // truncated) hash function result is treated as a number and used - // directly in the DSA signature algorithm. - const h = new BigInteger(hashed.subarray(0, q.byteLength())).mod(q); - // FIPS-186-4, section 4.6: - // The values of r and s shall be checked to determine if r = 0 or s = 0. - // If either r = 0 or s = 0, a new value of k shall be generated, and the - // signature shall be recalculated. It is extremely unlikely that r = 0 - // or s = 0 if signatures are generated properly. - while (true) { - // See Appendix B here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - k = await getRandomBigInteger(one, q); // returns in [1, q-1] - r = g.modExp(k, p).imod(q); // (g**k mod p) mod q - if (r.isZero()) { - continue; - } - const xr = x.mul(r).imod(q); - t = h.add(xr).imod(q); // H(m) + x*r mod q - s = k.modInv(q).imul(t).imod(q); // k**-1 * (H(m) + x*r) mod q - if (s.isZero()) { - continue; - } - break; - } - return { - r: r.toUint8Array('be', q.byteLength()), - s: s.toUint8Array('be', q.byteLength()) - }; -} - -/** - * DSA Verify function - * @param {Integer} hashAlgo - * @param {Uint8Array} r - * @param {Uint8Array} s - * @param {Uint8Array} hashed - * @param {Uint8Array} g - * @param {Uint8Array} p - * @param {Uint8Array} q - * @param {Uint8Array} y - * @returns {boolean} - * @async - */ -async function verify$3(hashAlgo, r, s, hashed, g, p, q, y) { - const BigInteger = await util.getBigInteger(); - const zero = new BigInteger(0); - r = new BigInteger(r); - s = new BigInteger(s); - - p = new BigInteger(p); - q = new BigInteger(q); - g = new BigInteger(g); - y = new BigInteger(y); - - if (r.lte(zero) || r.gte(q) || - s.lte(zero) || s.gte(q)) { - util.printDebug('invalid DSA Signature'); - return false; - } - const h = new BigInteger(hashed.subarray(0, q.byteLength())).imod(q); - const w = s.modInv(q); // s**-1 mod q - if (w.isZero()) { - util.printDebug('invalid DSA Signature'); - return false; - } - - g = g.mod(p); - y = y.mod(p); - const u1 = h.mul(w).imod(q); // H(m) * w mod q - const u2 = r.mul(w).imod(q); // r * w mod q - const t1 = g.modExp(u1, p); // g**u1 mod p - const t2 = y.modExp(u2, p); // y**u2 mod p - const v = t1.mul(t2).imod(p).imod(q); // (g**u1 * y**u2 mod p) mod q - return v.equal(r); -} - -/** - * Validate DSA parameters - * @param {Uint8Array} p - DSA prime - * @param {Uint8Array} q - DSA group order - * @param {Uint8Array} g - DSA sub-group generator - * @param {Uint8Array} y - DSA public key - * @param {Uint8Array} x - DSA private key - * @returns {Promise} Whether params are valid. - * @async - */ -async function validateParams$6(p, q, g, y, x) { - const BigInteger = await util.getBigInteger(); - p = new BigInteger(p); - q = new BigInteger(q); - g = new BigInteger(g); - y = new BigInteger(y); - const one = new BigInteger(1); - // Check that 1 < g < p - if (g.lte(one) || g.gte(p)) { - return false; - } - - /** - * Check that subgroup order q divides p-1 - */ - if (!p.dec().mod(q).isZero()) { - return false; - } - - /** - * g has order q - * Check that g ** q = 1 mod p - */ - if (!g.modExp(q, p).isOne()) { - return false; - } - - /** - * Check q is large and probably prime (we mainly want to avoid small factors) - */ - const qSize = new BigInteger(q.bitLength()); - const n150 = new BigInteger(150); - if (qSize.lt(n150) || !(await isProbablePrime(q, null, 32))) { - return false; - } - - /** - * Re-derive public key y' = g ** x mod p - * Expect y == y' - * - * Blinded exponentiation computes g**{rq + x} to compare to y - */ - x = new BigInteger(x); - const two = new BigInteger(2); - const r = await getRandomBigInteger(two.leftShift(qSize.dec()), two.leftShift(qSize)); // draw r of same size as q - const rqx = q.mul(r).add(x); - if (!y.equal(g.modExp(rqx, p))) { - return false; - } - - return true; -} - -var dsa = /*#__PURE__*/Object.freeze({ - __proto__: null, - sign: sign$3, - verify: verify$3, - validateParams: validateParams$6 -}); - -/** - * @fileoverview Asymmetric cryptography functions - * @module crypto/public_key - * @private - */ - -var publicKey = { - /** @see module:crypto/public_key/rsa */ - rsa: rsa, - /** @see module:crypto/public_key/elgamal */ - elgamal: elgamal, - /** @see module:crypto/public_key/elliptic */ - elliptic: elliptic, - /** @see module:crypto/public_key/dsa */ - dsa: dsa, - /** @see tweetnacl */ - nacl: naclFastLight -}; - -/** - * @fileoverview Provides functions for asymmetric signing and signature verification - * @module crypto/signature - * @private - */ - -/** - * Parse signature in binary form to get the parameters. - * The returned values are only padded for EdDSA, since in the other cases their expected length - * depends on the key params, hence we delegate the padding to the signature verification function. - * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} - * See {@link https://tools.ietf.org/html/rfc4880#section-5.2.2|RFC 4880 5.2.2.} - * @param {module:enums.publicKey} algo - Public key algorithm - * @param {Uint8Array} signature - Data for which the signature was created - * @returns {Promise} True if signature is valid. - * @async - */ -function parseSignatureParams(algo, signature) { - let read = 0; - switch (algo) { - // Algorithm-Specific Fields for RSA signatures: - // - MPI of RSA signature value m**d mod n. - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaSign: { - const s = util.readMPI(signature.subarray(read)); - // The signature needs to be the same length as the public key modulo n. - // We pad s on signature verification, where we have access to n. - return { s }; - } - // Algorithm-Specific Fields for DSA or ECDSA signatures: - // - MPI of DSA or ECDSA value r. - // - MPI of DSA or ECDSA value s. - case enums.publicKey.dsa: - case enums.publicKey.ecdsa: - { - const r = util.readMPI(signature.subarray(read)); read += r.length + 2; - const s = util.readMPI(signature.subarray(read)); - return { r, s }; - } - // Algorithm-Specific Fields for EdDSA signatures: - // - MPI of an EC point r. - // - EdDSA value s, in MPI, in the little endian representation - case enums.publicKey.eddsa: { - // When parsing little-endian MPI data, we always need to left-pad it, as done with big-endian values: - // https://www.ietf.org/archive/id/draft-ietf-openpgp-rfc4880bis-10.html#section-3.2-9 - let r = util.readMPI(signature.subarray(read)); read += r.length + 2; - r = util.leftPad(r, 32); - let s = util.readMPI(signature.subarray(read)); - s = util.leftPad(s, 32); - return { r, s }; - } - default: - throw new Error('Invalid signature algorithm.'); - } -} - -/** - * Verifies the signature provided for data using specified algorithms and public key parameters. - * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} - * and {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4} - * for public key and hash algorithms. - * @param {module:enums.publicKey} algo - Public key algorithm - * @param {module:enums.hash} hashAlgo - Hash algorithm - * @param {Object} signature - Named algorithm-specific signature parameters - * @param {Object} publicParams - Algorithm-specific public key parameters - * @param {Uint8Array} data - Data for which the signature was created - * @param {Uint8Array} hashed - The hashed data - * @returns {Promise} True if signature is valid. - * @async - */ -async function verify$4(algo, hashAlgo, signature, publicParams, data, hashed) { - switch (algo) { - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaSign: { - const { n, e } = publicParams; - const s = util.leftPad(signature.s, n.length); // padding needed for webcrypto and node crypto - return publicKey.rsa.verify(hashAlgo, data, s, n, e, hashed); - } - case enums.publicKey.dsa: { - const { g, p, q, y } = publicParams; - const { r, s } = signature; // no need to pad, since we always handle them as BigIntegers - return publicKey.dsa.verify(hashAlgo, r, s, hashed, g, p, q, y); - } - case enums.publicKey.ecdsa: { - const { oid, Q } = publicParams; - const curveSize = new publicKey.elliptic.Curve(oid).payloadSize; - // padding needed for webcrypto - const r = util.leftPad(signature.r, curveSize); - const s = util.leftPad(signature.s, curveSize); - return publicKey.elliptic.ecdsa.verify(oid, hashAlgo, { r, s }, data, Q, hashed); - } - case enums.publicKey.eddsa: { - const { oid, Q } = publicParams; - // signature already padded on parsing - return publicKey.elliptic.eddsa.verify(oid, hashAlgo, signature, data, Q, hashed); - } - default: - throw new Error('Invalid signature algorithm.'); - } -} - -/** - * Creates a signature on data using specified algorithms and private key parameters. - * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} - * and {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4} - * for public key and hash algorithms. - * @param {module:enums.publicKey} algo - Public key algorithm - * @param {module:enums.hash} hashAlgo - Hash algorithm - * @param {Object} publicKeyParams - Algorithm-specific public and private key parameters - * @param {Object} privateKeyParams - Algorithm-specific public and private key parameters - * @param {Uint8Array} data - Data to be signed - * @param {Uint8Array} hashed - The hashed data - * @returns {Promise} Signature Object containing named signature parameters. - * @async - */ -async function sign$4(algo, hashAlgo, publicKeyParams, privateKeyParams, data, hashed) { - if (!publicKeyParams || !privateKeyParams) { - throw new Error('Missing key parameters'); - } - switch (algo) { - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaSign: { - const { n, e } = publicKeyParams; - const { d, p, q, u } = privateKeyParams; - const s = await publicKey.rsa.sign(hashAlgo, data, n, e, d, p, q, u, hashed); - return { s }; - } - case enums.publicKey.dsa: { - const { g, p, q } = publicKeyParams; - const { x } = privateKeyParams; - return publicKey.dsa.sign(hashAlgo, hashed, g, p, q, x); - } - case enums.publicKey.elgamal: { - throw new Error('Signing with Elgamal is not defined in the OpenPGP standard.'); - } - case enums.publicKey.ecdsa: { - const { oid, Q } = publicKeyParams; - const { d } = privateKeyParams; - return publicKey.elliptic.ecdsa.sign(oid, hashAlgo, data, Q, d, hashed); - } - case enums.publicKey.eddsa: { - const { oid, Q } = publicKeyParams; - const { seed } = privateKeyParams; - return publicKey.elliptic.eddsa.sign(oid, hashAlgo, data, Q, seed, hashed); - } - default: - throw new Error('Invalid signature algorithm.'); - } -} - -var signature = /*#__PURE__*/Object.freeze({ - __proto__: null, - parseSignatureParams: parseSignatureParams, - verify: verify$4, - sign: sign$4 -}); - -/** - * @fileoverview Provides access to all cryptographic primitives used in OpenPGP.js - * @see module:crypto/crypto - * @see module:crypto/signature - * @see module:crypto/public_key - * @see module:crypto/cipher - * @see module:crypto/random - * @see module:crypto/hash - * @module crypto - * @private - */ - -// TODO move cfb and gcm to cipher -const mod = { - /** @see module:crypto/cipher */ - cipher: cipher, - /** @see module:crypto/hash */ - hash: hash, - /** @see module:crypto/mode */ - mode: mode, - /** @see module:crypto/public_key */ - publicKey: publicKey, - /** @see module:crypto/signature */ - signature: signature, - /** @see module:crypto/random */ - random: random, - /** @see module:crypto/pkcs1 */ - pkcs1: pkcs1, - /** @see module:crypto/pkcs5 */ - pkcs5: pkcs5, - /** @see module:crypto/aes_kw */ - aesKW: aesKW -}; - -Object.assign(mod, crypto$1); - -var TYPED_OK = typeof Uint8Array !== "undefined" && - typeof Uint16Array !== "undefined" && - typeof Int32Array !== "undefined"; - - -// reduce buffer size, avoiding mem copy -function shrinkBuf(buf, size) { - if (buf.length === size) { - return buf; - } - if (buf.subarray) { - return buf.subarray(0, size); - } - buf.length = size; - return buf; -} - - -const fnTyped = { - arraySet: function (dest, src, src_offs, len, dest_offs) { - if (src.subarray && dest.subarray) { - dest.set(src.subarray(src_offs, src_offs + len), dest_offs); - return; - } - // Fallback to ordinary array - for (let i = 0; i < len; i++) { - dest[dest_offs + i] = src[src_offs + i]; - } - }, - // Join array of chunks to single array. - flattenChunks: function (chunks) { - let i, l, len, pos, chunk; - - // calculate data length - len = 0; - for (i = 0, l = chunks.length; i < l; i++) { - len += chunks[i].length; - } - - // join chunks - const result = new Uint8Array(len); - pos = 0; - for (i = 0, l = chunks.length; i < l; i++) { - chunk = chunks[i]; - result.set(chunk, pos); - pos += chunk.length; - } - - return result; - } -}; - -const fnUntyped = { - arraySet: function (dest, src, src_offs, len, dest_offs) { - for (let i = 0; i < len; i++) { - dest[dest_offs + i] = src[src_offs + i]; - } - }, - // Join array of chunks to single array. - flattenChunks: function (chunks) { - return [].concat.apply([], chunks); - } -}; - - -// Enable/Disable typed arrays use, for testing -// - -let Buf8 = TYPED_OK ? Uint8Array : Array; -let Buf16 = TYPED_OK ? Uint16Array : Array; -let Buf32 = TYPED_OK ? Int32Array : Array; -let flattenChunks = TYPED_OK ? fnTyped.flattenChunks : fnUntyped.flattenChunks; -let arraySet = TYPED_OK ? fnTyped.arraySet : fnUntyped.arraySet; - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -/* Allowed flush values; see deflate() and inflate() below for details */ -const Z_NO_FLUSH = 0; -const Z_PARTIAL_FLUSH = 1; -const Z_SYNC_FLUSH = 2; -const Z_FULL_FLUSH = 3; -const Z_FINISH = 4; -const Z_BLOCK = 5; -const Z_TREES = 6; - -/* Return codes for the compression/decompression functions. Negative values - * are errors, positive values are used for special but normal events. - */ -const Z_OK = 0; -const Z_STREAM_END = 1; -const Z_NEED_DICT = 2; -const Z_STREAM_ERROR = -2; -const Z_DATA_ERROR = -3; -//export const Z_MEM_ERROR = -4; -const Z_BUF_ERROR = -5; -const Z_DEFAULT_COMPRESSION = -1; - - -const Z_FILTERED = 1; -const Z_HUFFMAN_ONLY = 2; -const Z_RLE = 3; -const Z_FIXED = 4; -const Z_DEFAULT_STRATEGY = 0; - -/* Possible values of the data_type field (though see inflate()) */ -const Z_BINARY = 0; -const Z_TEXT = 1; -//export const Z_ASCII = 1; // = Z_TEXT (deprecated) -const Z_UNKNOWN = 2; - -/* The deflate compression method */ -const Z_DEFLATED = 8; -//export const Z_NULL = null // Use -1 or null inline, depending on var type - -/*============================================================================*/ - - -function zero$1(buf) { - let len = buf.length; while (--len >= 0) { - buf[len] = 0; - } -} - -// From zutil.h - -const STORED_BLOCK = 0; -const STATIC_TREES = 1; -const DYN_TREES = 2; -/* The three kinds of block type */ - -const MIN_MATCH = 3; -const MAX_MATCH = 258; -/* The minimum and maximum match lengths */ - -// From deflate.h -/* =========================================================================== - * Internal compression state. - */ - -const LENGTH_CODES = 29; -/* number of length codes, not counting the special END_BLOCK code */ - -const LITERALS = 256; -/* number of literal bytes 0..255 */ - -const L_CODES = LITERALS + 1 + LENGTH_CODES; -/* number of Literal or Length codes, including the END_BLOCK code */ - -const D_CODES = 30; -/* number of distance codes */ - -const BL_CODES = 19; -/* number of codes used to transfer the bit lengths */ - -const HEAP_SIZE = 2 * L_CODES + 1; -/* maximum heap size */ - -const MAX_BITS = 15; -/* All codes must not exceed MAX_BITS bits */ - -const Buf_size = 16; -/* size of bit buffer in bi_buf */ - - -/* =========================================================================== - * Constants - */ - -const MAX_BL_BITS = 7; -/* Bit length codes must not exceed MAX_BL_BITS bits */ - -const END_BLOCK = 256; -/* end of block literal code */ - -const REP_3_6 = 16; -/* repeat previous bit length 3-6 times (2 bits of repeat count) */ - -const REPZ_3_10 = 17; -/* repeat a zero length 3-10 times (3 bits of repeat count) */ - -const REPZ_11_138 = 18; -/* repeat a zero length 11-138 times (7 bits of repeat count) */ - -/* eslint-disable comma-spacing,array-bracket-spacing */ -const extra_lbits = /* extra bits for each length code */ - [0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0]; - -const extra_dbits = /* extra bits for each distance code */ - [0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13]; - -const extra_blbits = /* extra bits for each bit length code */ - [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7]; - -const bl_order = - [16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]; -/* eslint-enable comma-spacing,array-bracket-spacing */ - -/* The lengths of the bit length codes are sent in order of decreasing - * probability, to avoid transmitting the lengths for unused bit length codes. - */ - -/* =========================================================================== - * Local data. These are initialized only once. - */ - -// We pre-fill arrays with 0 to avoid uninitialized gaps - -const DIST_CODE_LEN = 512; /* see definition of array dist_code below */ - -// !!!! Use flat array instead of structure, Freq = i*2, Len = i*2+1 -const static_ltree = new Array((L_CODES + 2) * 2); -zero$1(static_ltree); -/* The static literal tree. Since the bit lengths are imposed, there is no - * need for the L_CODES extra codes used during heap construction. However - * The codes 286 and 287 are needed to build a canonical tree (see _tr_init - * below). - */ - -const static_dtree = new Array(D_CODES * 2); -zero$1(static_dtree); -/* The static distance tree. (Actually a trivial tree since all codes use - * 5 bits.) - */ - -const _dist_code = new Array(DIST_CODE_LEN); -zero$1(_dist_code); -/* Distance codes. The first 256 values correspond to the distances - * 3 .. 258, the last 256 values correspond to the top 8 bits of - * the 15 bit distances. - */ - -const _length_code = new Array(MAX_MATCH - MIN_MATCH + 1); -zero$1(_length_code); -/* length code for each normalized match length (0 == MIN_MATCH) */ - -const base_length = new Array(LENGTH_CODES); -zero$1(base_length); -/* First normalized length for each code (0 = MIN_MATCH) */ - -const base_dist = new Array(D_CODES); -zero$1(base_dist); -/* First normalized distance for each code (0 = distance of 1) */ - - -function StaticTreeDesc(static_tree, extra_bits, extra_base, elems, max_length) { - - this.static_tree = static_tree; /* static tree or NULL */ - this.extra_bits = extra_bits; /* extra bits for each code or NULL */ - this.extra_base = extra_base; /* base index for extra_bits */ - this.elems = elems; /* max number of elements in the tree */ - this.max_length = max_length; /* max bit length for the codes */ - - // show if `static_tree` has data or dummy - needed for monomorphic objects - this.has_stree = static_tree && static_tree.length; -} - - -let static_l_desc; -let static_d_desc; -let static_bl_desc; - - -function TreeDesc(dyn_tree, stat_desc) { - this.dyn_tree = dyn_tree; /* the dynamic tree */ - this.max_code = 0; /* largest code with non zero frequency */ - this.stat_desc = stat_desc; /* the corresponding static tree */ -} - - - -function d_code(dist) { - return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)]; -} - - -/* =========================================================================== - * Output a short LSB first on the stream. - * IN assertion: there is enough room in pendingBuf. - */ -function put_short(s, w) { -// put_byte(s, (uch)((w) & 0xff)); -// put_byte(s, (uch)((ush)(w) >> 8)); - s.pending_buf[s.pending++] = w & 0xff; - s.pending_buf[s.pending++] = w >>> 8 & 0xff; -} - - -/* =========================================================================== - * Send a value on a given number of bits. - * IN assertion: length <= 16 and value fits in length bits. - */ -function send_bits(s, value, length) { - if (s.bi_valid > Buf_size - length) { - s.bi_buf |= value << s.bi_valid & 0xffff; - put_short(s, s.bi_buf); - s.bi_buf = value >> Buf_size - s.bi_valid; - s.bi_valid += length - Buf_size; - } else { - s.bi_buf |= value << s.bi_valid & 0xffff; - s.bi_valid += length; - } -} - - -function send_code(s, c, tree) { - send_bits(s, tree[c * 2]/*.Code*/, tree[c * 2 + 1]/*.Len*/); -} - - -/* =========================================================================== - * Reverse the first len bits of a code, using straightforward code (a faster - * method would use a table) - * IN assertion: 1 <= len <= 15 - */ -function bi_reverse(code, len) { - let res = 0; - do { - res |= code & 1; - code >>>= 1; - res <<= 1; - } while (--len > 0); - return res >>> 1; -} - - -/* =========================================================================== - * Flush the bit buffer, keeping at most 7 bits in it. - */ -function bi_flush(s) { - if (s.bi_valid === 16) { - put_short(s, s.bi_buf); - s.bi_buf = 0; - s.bi_valid = 0; - - } else if (s.bi_valid >= 8) { - s.pending_buf[s.pending++] = s.bi_buf & 0xff; - s.bi_buf >>= 8; - s.bi_valid -= 8; - } -} - - -/* =========================================================================== - * Compute the optimal bit lengths for a tree and update the total bit length - * for the current block. - * IN assertion: the fields freq and dad are set, heap[heap_max] and - * above are the tree nodes sorted by increasing frequency. - * OUT assertions: the field len is set to the optimal bit length, the - * array bl_count contains the frequencies for each bit length. - * The length opt_len is updated; static_len is also updated if stree is - * not null. - */ -function gen_bitlen(s, desc) -// deflate_state *s; -// tree_desc *desc; /* the tree descriptor */ -{ - const tree = desc.dyn_tree; - const max_code = desc.max_code; - const stree = desc.stat_desc.static_tree; - const has_stree = desc.stat_desc.has_stree; - const extra = desc.stat_desc.extra_bits; - const base = desc.stat_desc.extra_base; - const max_length = desc.stat_desc.max_length; - let h; /* heap index */ - let n, m; /* iterate over the tree elements */ - let bits; /* bit length */ - let xbits; /* extra bits */ - let f; /* frequency */ - let overflow = 0; /* number of elements with bit length too large */ - - for (bits = 0; bits <= MAX_BITS; bits++) { - s.bl_count[bits] = 0; - } - - /* In a first pass, compute the optimal bit lengths (which may - * overflow in the case of the bit length tree). - */ - tree[s.heap[s.heap_max] * 2 + 1]/*.Len*/ = 0; /* root of the heap */ - - for (h = s.heap_max + 1; h < HEAP_SIZE; h++) { - n = s.heap[h]; - bits = tree[tree[n * 2 + 1]/*.Dad*/ * 2 + 1]/*.Len*/ + 1; - if (bits > max_length) { - bits = max_length; - overflow++; - } - tree[n * 2 + 1]/*.Len*/ = bits; - /* We overwrite tree[n].Dad which is no longer needed */ - - if (n > max_code) { - continue; - } /* not a leaf node */ - - s.bl_count[bits]++; - xbits = 0; - if (n >= base) { - xbits = extra[n - base]; - } - f = tree[n * 2]/*.Freq*/; - s.opt_len += f * (bits + xbits); - if (has_stree) { - s.static_len += f * (stree[n * 2 + 1]/*.Len*/ + xbits); - } - } - if (overflow === 0) { - return; - } - - // Trace((stderr,"\nbit length overflow\n")); - /* This happens for example on obj2 and pic of the Calgary corpus */ - - /* Find the first bit length which could increase: */ - do { - bits = max_length - 1; - while (s.bl_count[bits] === 0) { - bits--; - } - s.bl_count[bits]--; /* move one leaf down the tree */ - s.bl_count[bits + 1] += 2; /* move one overflow item as its brother */ - s.bl_count[max_length]--; - /* The brother of the overflow item also moves one step up, - * but this does not affect bl_count[max_length] - */ - overflow -= 2; - } while (overflow > 0); - - /* Now recompute all bit lengths, scanning in increasing frequency. - * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all - * lengths instead of fixing only the wrong ones. This idea is taken - * from 'ar' written by Haruhiko Okumura.) - */ - for (bits = max_length; bits !== 0; bits--) { - n = s.bl_count[bits]; - while (n !== 0) { - m = s.heap[--h]; - if (m > max_code) { - continue; - } - if (tree[m * 2 + 1]/*.Len*/ !== bits) { - // Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); - s.opt_len += (bits - tree[m * 2 + 1]/*.Len*/) * tree[m * 2]/*.Freq*/; - tree[m * 2 + 1]/*.Len*/ = bits; - } - n--; - } - } -} - - -/* =========================================================================== - * Generate the codes for a given tree and bit counts (which need not be - * optimal). - * IN assertion: the array bl_count contains the bit length statistics for - * the given tree and the field len is set for all tree elements. - * OUT assertion: the field code is set for all tree elements of non - * zero code length. - */ -function gen_codes(tree, max_code, bl_count) -// ct_data *tree; /* the tree to decorate */ -// int max_code; /* largest code with non zero frequency */ -// ushf *bl_count; /* number of codes at each bit length */ -{ - const next_code = new Array(MAX_BITS + 1); /* next code value for each bit length */ - let code = 0; /* running code value */ - let bits; /* bit index */ - let n; /* code index */ - - /* The distribution counts are first used to generate the code values - * without bit reversal. - */ - for (bits = 1; bits <= MAX_BITS; bits++) { - next_code[bits] = code = code + bl_count[bits - 1] << 1; - } - /* Check that the bit counts in bl_count are consistent. The last code - * must be all ones. - */ - //Assert (code + bl_count[MAX_BITS]-1 == (1< length code (0..28) */ - length = 0; - for (code = 0; code < LENGTH_CODES - 1; code++) { - base_length[code] = length; - for (n = 0; n < 1 << extra_lbits[code]; n++) { - _length_code[length++] = code; - } - } - //Assert (length == 256, "tr_static_init: length != 256"); - /* Note that the length 255 (match length 258) can be represented - * in two different ways: code 284 + 5 bits or code 285, so we - * overwrite length_code[255] to use the best encoding: - */ - _length_code[length - 1] = code; - - /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ - dist = 0; - for (code = 0; code < 16; code++) { - base_dist[code] = dist; - for (n = 0; n < 1 << extra_dbits[code]; n++) { - _dist_code[dist++] = code; - } - } - //Assert (dist == 256, "tr_static_init: dist != 256"); - dist >>= 7; /* from now on, all distances are divided by 128 */ - for (; code < D_CODES; code++) { - base_dist[code] = dist << 7; - for (n = 0; n < 1 << extra_dbits[code] - 7; n++) { - _dist_code[256 + dist++] = code; - } - } - //Assert (dist == 256, "tr_static_init: 256+dist != 512"); - - /* Construct the codes of the static literal tree */ - for (bits = 0; bits <= MAX_BITS; bits++) { - bl_count[bits] = 0; - } - - n = 0; - while (n <= 143) { - static_ltree[n * 2 + 1]/*.Len*/ = 8; - n++; - bl_count[8]++; - } - while (n <= 255) { - static_ltree[n * 2 + 1]/*.Len*/ = 9; - n++; - bl_count[9]++; - } - while (n <= 279) { - static_ltree[n * 2 + 1]/*.Len*/ = 7; - n++; - bl_count[7]++; - } - while (n <= 287) { - static_ltree[n * 2 + 1]/*.Len*/ = 8; - n++; - bl_count[8]++; - } - /* Codes 286 and 287 do not exist, but we must include them in the - * tree construction to get a canonical Huffman tree (longest code - * all ones) - */ - gen_codes(static_ltree, L_CODES + 1, bl_count); - - /* The static distance tree is trivial: */ - for (n = 0; n < D_CODES; n++) { - static_dtree[n * 2 + 1]/*.Len*/ = 5; - static_dtree[n * 2]/*.Code*/ = bi_reverse(n, 5); - } - - // Now data ready and we can init static trees - static_l_desc = new StaticTreeDesc(static_ltree, extra_lbits, LITERALS + 1, L_CODES, MAX_BITS); - static_d_desc = new StaticTreeDesc(static_dtree, extra_dbits, 0, D_CODES, MAX_BITS); - static_bl_desc = new StaticTreeDesc(new Array(0), extra_blbits, 0, BL_CODES, MAX_BL_BITS); - - //static_init_done = true; -} - - -/* =========================================================================== - * Initialize a new block. - */ -function init_block(s) { - let n; /* iterates over tree elements */ - - /* Initialize the trees. */ - for (n = 0; n < L_CODES; n++) { - s.dyn_ltree[n * 2]/*.Freq*/ = 0; - } - for (n = 0; n < D_CODES; n++) { - s.dyn_dtree[n * 2]/*.Freq*/ = 0; - } - for (n = 0; n < BL_CODES; n++) { - s.bl_tree[n * 2]/*.Freq*/ = 0; - } - - s.dyn_ltree[END_BLOCK * 2]/*.Freq*/ = 1; - s.opt_len = s.static_len = 0; - s.last_lit = s.matches = 0; -} - - -/* =========================================================================== - * Flush the bit buffer and align the output on a byte boundary - */ -function bi_windup(s) { - if (s.bi_valid > 8) { - put_short(s, s.bi_buf); - } else if (s.bi_valid > 0) { - //put_byte(s, (Byte)s->bi_buf); - s.pending_buf[s.pending++] = s.bi_buf; - } - s.bi_buf = 0; - s.bi_valid = 0; -} - -/* =========================================================================== - * Copy a stored block, storing first the length and its - * one's complement if requested. - */ -function copy_block(s, buf, len, header) -//DeflateState *s; -//charf *buf; /* the input data */ -//unsigned len; /* its length */ -//int header; /* true if block header must be written */ -{ - bi_windup(s); /* align on byte boundary */ - - if (header) { - put_short(s, len); - put_short(s, ~len); - } - // while (len--) { - // put_byte(s, *buf++); - // } - arraySet(s.pending_buf, s.window, buf, len, s.pending); - s.pending += len; -} - -/* =========================================================================== - * Compares to subtrees, using the tree depth as tie breaker when - * the subtrees have equal frequency. This minimizes the worst case length. - */ -function smaller(tree, n, m, depth) { - const _n2 = n * 2; - const _m2 = m * 2; - return tree[_n2]/*.Freq*/ < tree[_m2]/*.Freq*/ || - tree[_n2]/*.Freq*/ === tree[_m2]/*.Freq*/ && depth[n] <= depth[m]; -} - -/* =========================================================================== - * Restore the heap property by moving down the tree starting at node k, - * exchanging a node with the smallest of its two sons if necessary, stopping - * when the heap property is re-established (each father smaller than its - * two sons). - */ -function pqdownheap(s, tree, k) -// deflate_state *s; -// ct_data *tree; /* the tree to restore */ -// int k; /* node to move down */ -{ - const v = s.heap[k]; - let j = k << 1; /* left son of k */ - while (j <= s.heap_len) { - /* Set j to the smallest of the two sons: */ - if (j < s.heap_len && - smaller(tree, s.heap[j + 1], s.heap[j], s.depth)) { - j++; - } - /* Exit if v is smaller than both sons */ - if (smaller(tree, v, s.heap[j], s.depth)) { - break; - } - - /* Exchange v with the smallest son */ - s.heap[k] = s.heap[j]; - k = j; - - /* And continue down the tree, setting j to the left son of k */ - j <<= 1; - } - s.heap[k] = v; -} - - -// inlined manually -// var SMALLEST = 1; - -/* =========================================================================== - * Send the block data compressed using the given Huffman trees - */ -function compress_block(s, ltree, dtree) -// deflate_state *s; -// const ct_data *ltree; /* literal tree */ -// const ct_data *dtree; /* distance tree */ -{ - let dist; /* distance of matched string */ - let lc; /* match length or unmatched char (if dist == 0) */ - let lx = 0; /* running index in l_buf */ - let code; /* the code to send */ - let extra; /* number of extra bits to send */ - - if (s.last_lit !== 0) { - do { - dist = s.pending_buf[s.d_buf + lx * 2] << 8 | s.pending_buf[s.d_buf + lx * 2 + 1]; - lc = s.pending_buf[s.l_buf + lx]; - lx++; - - if (dist === 0) { - send_code(s, lc, ltree); /* send a literal byte */ - //Tracecv(isgraph(lc), (stderr," '%c' ", lc)); - } else { - /* Here, lc is the match length - MIN_MATCH */ - code = _length_code[lc]; - send_code(s, code + LITERALS + 1, ltree); /* send the length code */ - extra = extra_lbits[code]; - if (extra !== 0) { - lc -= base_length[code]; - send_bits(s, lc, extra); /* send the extra length bits */ - } - dist--; /* dist is now the match distance - 1 */ - code = d_code(dist); - //Assert (code < D_CODES, "bad d_code"); - - send_code(s, code, dtree); /* send the distance code */ - extra = extra_dbits[code]; - if (extra !== 0) { - dist -= base_dist[code]; - send_bits(s, dist, extra); /* send the extra distance bits */ - } - } /* literal or match pair ? */ - - /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ - //Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, - // "pendingBuf overflow"); - - } while (lx < s.last_lit); - } - - send_code(s, END_BLOCK, ltree); -} - - -/* =========================================================================== - * Construct one Huffman tree and assigns the code bit strings and lengths. - * Update the total bit length for the current block. - * IN assertion: the field freq is set for all tree elements. - * OUT assertions: the fields len and code are set to the optimal bit length - * and corresponding code. The length opt_len is updated; static_len is - * also updated if stree is not null. The field max_code is set. - */ -function build_tree(s, desc) -// deflate_state *s; -// tree_desc *desc; /* the tree descriptor */ -{ - const tree = desc.dyn_tree; - const stree = desc.stat_desc.static_tree; - const has_stree = desc.stat_desc.has_stree; - const elems = desc.stat_desc.elems; - let n, m; /* iterate over heap elements */ - let max_code = -1; /* largest code with non zero frequency */ - let node; /* new node being created */ - - /* Construct the initial heap, with least frequent element in - * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. - * heap[0] is not used. - */ - s.heap_len = 0; - s.heap_max = HEAP_SIZE; - - for (n = 0; n < elems; n++) { - if (tree[n * 2]/*.Freq*/ !== 0) { - s.heap[++s.heap_len] = max_code = n; - s.depth[n] = 0; - - } else { - tree[n * 2 + 1]/*.Len*/ = 0; - } - } - - /* The pkzip format requires that at least one distance code exists, - * and that at least one bit should be sent even if there is only one - * possible code. So to avoid special checks later on we force at least - * two codes of non zero frequency. - */ - while (s.heap_len < 2) { - node = s.heap[++s.heap_len] = max_code < 2 ? ++max_code : 0; - tree[node * 2]/*.Freq*/ = 1; - s.depth[node] = 0; - s.opt_len--; - - if (has_stree) { - s.static_len -= stree[node * 2 + 1]/*.Len*/; - } - /* node is 0 or 1 so it does not have extra bits */ - } - desc.max_code = max_code; - - /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, - * establish sub-heaps of increasing lengths: - */ - for (n = s.heap_len >> 1/*int /2*/; n >= 1; n--) { - pqdownheap(s, tree, n); - } - - /* Construct the Huffman tree by repeatedly combining the least two - * frequent nodes. - */ - node = elems; /* next internal node of the tree */ - do { - //pqremove(s, tree, n); /* n = node of least frequency */ - /*** pqremove ***/ - n = s.heap[1/*SMALLEST*/]; - s.heap[1/*SMALLEST*/] = s.heap[s.heap_len--]; - pqdownheap(s, tree, 1/*SMALLEST*/); - /***/ - - m = s.heap[1/*SMALLEST*/]; /* m = node of next least frequency */ - - s.heap[--s.heap_max] = n; /* keep the nodes sorted by frequency */ - s.heap[--s.heap_max] = m; - - /* Create a new node father of n and m */ - tree[node * 2]/*.Freq*/ = tree[n * 2]/*.Freq*/ + tree[m * 2]/*.Freq*/; - s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1; - tree[n * 2 + 1]/*.Dad*/ = tree[m * 2 + 1]/*.Dad*/ = node; - - /* and insert the new node in the heap */ - s.heap[1/*SMALLEST*/] = node++; - pqdownheap(s, tree, 1/*SMALLEST*/); - - } while (s.heap_len >= 2); - - s.heap[--s.heap_max] = s.heap[1/*SMALLEST*/]; - - /* At this point, the fields freq and dad are set. We can now - * generate the bit lengths. - */ - gen_bitlen(s, desc); - - /* The field len is now set, we can generate the bit codes */ - gen_codes(tree, max_code, s.bl_count); -} - - -/* =========================================================================== - * Scan a literal or distance tree to determine the frequencies of the codes - * in the bit length tree. - */ -function scan_tree(s, tree, max_code) -// deflate_state *s; -// ct_data *tree; /* the tree to be scanned */ -// int max_code; /* and its largest code of non zero frequency */ -{ - let n; /* iterates over all tree elements */ - let prevlen = -1; /* last emitted length */ - let curlen; /* length of current code */ - - let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */ - - let count = 0; /* repeat count of the current code */ - let max_count = 7; /* max repeat count */ - let min_count = 4; /* min repeat count */ - - if (nextlen === 0) { - max_count = 138; - min_count = 3; - } - tree[(max_code + 1) * 2 + 1]/*.Len*/ = 0xffff; /* guard */ - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; - nextlen = tree[(n + 1) * 2 + 1]/*.Len*/; - - if (++count < max_count && curlen === nextlen) { - continue; - - } else if (count < min_count) { - s.bl_tree[curlen * 2]/*.Freq*/ += count; - - } else if (curlen !== 0) { - - if (curlen !== prevlen) { - s.bl_tree[curlen * 2]/*.Freq*/++; - } - s.bl_tree[REP_3_6 * 2]/*.Freq*/++; - - } else if (count <= 10) { - s.bl_tree[REPZ_3_10 * 2]/*.Freq*/++; - - } else { - s.bl_tree[REPZ_11_138 * 2]/*.Freq*/++; - } - - count = 0; - prevlen = curlen; - - if (nextlen === 0) { - max_count = 138; - min_count = 3; - - } else if (curlen === nextlen) { - max_count = 6; - min_count = 3; - - } else { - max_count = 7; - min_count = 4; - } - } -} - - -/* =========================================================================== - * Send a literal or distance tree in compressed form, using the codes in - * bl_tree. - */ -function send_tree(s, tree, max_code) -// deflate_state *s; -// ct_data *tree; /* the tree to be scanned */ -// int max_code; /* and its largest code of non zero frequency */ -{ - let n; /* iterates over all tree elements */ - let prevlen = -1; /* last emitted length */ - let curlen; /* length of current code */ - - let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */ - - let count = 0; /* repeat count of the current code */ - let max_count = 7; /* max repeat count */ - let min_count = 4; /* min repeat count */ - - /* tree[max_code+1].Len = -1; */ /* guard already set */ - if (nextlen === 0) { - max_count = 138; - min_count = 3; - } - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; - nextlen = tree[(n + 1) * 2 + 1]/*.Len*/; - - if (++count < max_count && curlen === nextlen) { - continue; - - } else if (count < min_count) { - do { - send_code(s, curlen, s.bl_tree); - } while (--count !== 0); - - } else if (curlen !== 0) { - if (curlen !== prevlen) { - send_code(s, curlen, s.bl_tree); - count--; - } - //Assert(count >= 3 && count <= 6, " 3_6?"); - send_code(s, REP_3_6, s.bl_tree); - send_bits(s, count - 3, 2); - - } else if (count <= 10) { - send_code(s, REPZ_3_10, s.bl_tree); - send_bits(s, count - 3, 3); - - } else { - send_code(s, REPZ_11_138, s.bl_tree); - send_bits(s, count - 11, 7); - } - - count = 0; - prevlen = curlen; - if (nextlen === 0) { - max_count = 138; - min_count = 3; - - } else if (curlen === nextlen) { - max_count = 6; - min_count = 3; - - } else { - max_count = 7; - min_count = 4; - } - } -} - - -/* =========================================================================== - * Construct the Huffman tree for the bit lengths and return the index in - * bl_order of the last bit length code to send. - */ -function build_bl_tree(s) { - let max_blindex; /* index of last bit length code of non zero freq */ - - /* Determine the bit length frequencies for literal and distance trees */ - scan_tree(s, s.dyn_ltree, s.l_desc.max_code); - scan_tree(s, s.dyn_dtree, s.d_desc.max_code); - - /* Build the bit length tree: */ - build_tree(s, s.bl_desc); - /* opt_len now includes the length of the tree representations, except - * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. - */ - - /* Determine the number of bit length codes to send. The pkzip format - * requires that at least 4 bit length codes be sent. (appnote.txt says - * 3 but the actual value used is 4.) - */ - for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) { - if (s.bl_tree[bl_order[max_blindex] * 2 + 1]/*.Len*/ !== 0) { - break; - } - } - /* Update opt_len to include the bit length tree and counts */ - s.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4; - //Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", - // s->opt_len, s->static_len)); - - return max_blindex; -} - - -/* =========================================================================== - * Send the header for a block using dynamic Huffman trees: the counts, the - * lengths of the bit length codes, the literal tree and the distance tree. - * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. - */ -function send_all_trees(s, lcodes, dcodes, blcodes) -// deflate_state *s; -// int lcodes, dcodes, blcodes; /* number of codes for each tree */ -{ - let rank; /* index in bl_order */ - - //Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); - //Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, - // "too many codes"); - //Tracev((stderr, "\nbl counts: ")); - send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */ - send_bits(s, dcodes - 1, 5); - send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */ - for (rank = 0; rank < blcodes; rank++) { - //Tracev((stderr, "\nbl code %2d ", bl_order[rank])); - send_bits(s, s.bl_tree[bl_order[rank] * 2 + 1]/*.Len*/, 3); - } - //Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); - - send_tree(s, s.dyn_ltree, lcodes - 1); /* literal tree */ - //Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); - - send_tree(s, s.dyn_dtree, dcodes - 1); /* distance tree */ - //Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); -} - - -/* =========================================================================== - * Check if the data type is TEXT or BINARY, using the following algorithm: - * - TEXT if the two conditions below are satisfied: - * a) There are no non-portable control characters belonging to the - * "black list" (0..6, 14..25, 28..31). - * b) There is at least one printable character belonging to the - * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). - * - BINARY otherwise. - * - The following partially-portable control characters form a - * "gray list" that is ignored in this detection algorithm: - * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). - * IN assertion: the fields Freq of dyn_ltree are set. - */ -function detect_data_type(s) { - /* black_mask is the bit mask of black-listed bytes - * set bits 0..6, 14..25, and 28..31 - * 0xf3ffc07f = binary 11110011111111111100000001111111 - */ - let black_mask = 0xf3ffc07f; - let n; - - /* Check for non-textual ("black-listed") bytes. */ - for (n = 0; n <= 31; n++, black_mask >>>= 1) { - if (black_mask & 1 && s.dyn_ltree[n * 2]/*.Freq*/ !== 0) { - return Z_BINARY; - } - } - - /* Check for textual ("white-listed") bytes. */ - if (s.dyn_ltree[9 * 2]/*.Freq*/ !== 0 || s.dyn_ltree[10 * 2]/*.Freq*/ !== 0 || - s.dyn_ltree[13 * 2]/*.Freq*/ !== 0) { - return Z_TEXT; - } - for (n = 32; n < LITERALS; n++) { - if (s.dyn_ltree[n * 2]/*.Freq*/ !== 0) { - return Z_TEXT; - } - } - - /* There are no "black-listed" or "white-listed" bytes: - * this stream either is empty or has tolerated ("gray-listed") bytes only. - */ - return Z_BINARY; -} - - -let static_init_done = false; - -/* =========================================================================== - * Initialize the tree data structures for a new zlib stream. - */ -function _tr_init(s) { - - if (!static_init_done) { - tr_static_init(); - static_init_done = true; - } - - s.l_desc = new TreeDesc(s.dyn_ltree, static_l_desc); - s.d_desc = new TreeDesc(s.dyn_dtree, static_d_desc); - s.bl_desc = new TreeDesc(s.bl_tree, static_bl_desc); - - s.bi_buf = 0; - s.bi_valid = 0; - - /* Initialize the first block of the first file: */ - init_block(s); -} - - -/* =========================================================================== - * Send a stored block - */ -function _tr_stored_block(s, buf, stored_len, last) -//DeflateState *s; -//charf *buf; /* input block */ -//ulg stored_len; /* length of input block */ -//int last; /* one if this is the last block for a file */ -{ - send_bits(s, (STORED_BLOCK << 1) + (last ? 1 : 0), 3); /* send block type */ - copy_block(s, buf, stored_len, true); /* with header */ -} - - -/* =========================================================================== - * Send one empty static block to give enough lookahead for inflate. - * This takes 10 bits, of which 7 may remain in the bit buffer. - */ -function _tr_align(s) { - send_bits(s, STATIC_TREES << 1, 3); - send_code(s, END_BLOCK, static_ltree); - bi_flush(s); -} - - -/* =========================================================================== - * Determine the best encoding for the current block: dynamic trees, static - * trees or store, and output the encoded block to the zip file. - */ -function _tr_flush_block(s, buf, stored_len, last) -//DeflateState *s; -//charf *buf; /* input block, or NULL if too old */ -//ulg stored_len; /* length of input block */ -//int last; /* one if this is the last block for a file */ -{ - let opt_lenb, static_lenb; /* opt_len and static_len in bytes */ - let max_blindex = 0; /* index of last bit length code of non zero freq */ - - /* Build the Huffman trees unless a stored block is forced */ - if (s.level > 0) { - - /* Check if the file is binary or text */ - if (s.strm.data_type === Z_UNKNOWN) { - s.strm.data_type = detect_data_type(s); - } - - /* Construct the literal and distance trees */ - build_tree(s, s.l_desc); - // Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, - // s->static_len)); - - build_tree(s, s.d_desc); - // Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, - // s->static_len)); - /* At this point, opt_len and static_len are the total bit lengths of - * the compressed block data, excluding the tree representations. - */ - - /* Build the bit length tree for the above two trees, and get the index - * in bl_order of the last bit length code to send. - */ - max_blindex = build_bl_tree(s); - - /* Determine the best encoding. Compute the block lengths in bytes. */ - opt_lenb = s.opt_len + 3 + 7 >>> 3; - static_lenb = s.static_len + 3 + 7 >>> 3; - - // Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", - // opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, - // s->last_lit)); - - if (static_lenb <= opt_lenb) { - opt_lenb = static_lenb; - } - - } else { - // Assert(buf != (char*)0, "lost buf"); - opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ - } - - if (stored_len + 4 <= opt_lenb && buf !== -1) { - /* 4: two words for the lengths */ - - /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. - * Otherwise we can't have processed more than WSIZE input bytes since - * the last block flush, because compression would have been - * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to - * transform a block into a stored block. - */ - _tr_stored_block(s, buf, stored_len, last); - - } else if (s.strategy === Z_FIXED || static_lenb === opt_lenb) { - - send_bits(s, (STATIC_TREES << 1) + (last ? 1 : 0), 3); - compress_block(s, static_ltree, static_dtree); - - } else { - send_bits(s, (DYN_TREES << 1) + (last ? 1 : 0), 3); - send_all_trees(s, s.l_desc.max_code + 1, s.d_desc.max_code + 1, max_blindex + 1); - compress_block(s, s.dyn_ltree, s.dyn_dtree); - } - // Assert (s->compressed_len == s->bits_sent, "bad compressed size"); - /* The above check is made mod 2^32, for files larger than 512 MB - * and uLong implemented on 32 bits. - */ - init_block(s); - - if (last) { - bi_windup(s); - } - // Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, - // s->compressed_len-7*last)); -} - -/* =========================================================================== - * Save the match info and tally the frequency counts. Return true if - * the current block must be flushed. - */ -function _tr_tally(s, dist, lc) -// deflate_state *s; -// unsigned dist; /* distance of matched string */ -// unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ -{ - //var out_length, in_length, dcode; - - s.pending_buf[s.d_buf + s.last_lit * 2] = dist >>> 8 & 0xff; - s.pending_buf[s.d_buf + s.last_lit * 2 + 1] = dist & 0xff; - - s.pending_buf[s.l_buf + s.last_lit] = lc & 0xff; - s.last_lit++; - - if (dist === 0) { - /* lc is the unmatched char */ - s.dyn_ltree[lc * 2]/*.Freq*/++; - } else { - s.matches++; - /* Here, lc is the match length - MIN_MATCH */ - dist--; /* dist = match distance - 1 */ - //Assert((ush)dist < (ush)MAX_DIST(s) && - // (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && - // (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); - - s.dyn_ltree[(_length_code[lc] + LITERALS + 1) * 2]/*.Freq*/++; - s.dyn_dtree[d_code(dist) * 2]/*.Freq*/++; - } - - // (!) This block is disabled in zlib defaults, - // don't enable it for binary compatibility - - //#ifdef TRUNCATE_BLOCK - // /* Try to guess if it is profitable to stop the current block here */ - // if ((s.last_lit & 0x1fff) === 0 && s.level > 2) { - // /* Compute an upper bound for the compressed length */ - // out_length = s.last_lit*8; - // in_length = s.strstart - s.block_start; - // - // for (dcode = 0; dcode < D_CODES; dcode++) { - // out_length += s.dyn_dtree[dcode*2]/*.Freq*/ * (5 + extra_dbits[dcode]); - // } - // out_length >>>= 3; - // //Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", - // // s->last_lit, in_length, out_length, - // // 100L - out_length*100L/in_length)); - // if (s.matches < (s.last_lit>>1)/*int /2*/ && out_length < (in_length>>1)/*int /2*/) { - // return true; - // } - // } - //#endif - - return s.last_lit === s.lit_bufsize - 1; - /* We avoid equality with lit_bufsize because of wraparound at 64K - * on 16 bit machines and because stored blocks are restricted to - * 64K-1 bytes. - */ -} - -// Note: adler32 takes 12% for level 0 and 2% for level 6. -// It isn't worth it to make additional optimizations as in original. -// Small size is preferable. - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -function adler32(adler, buf, len, pos) { - let s1 = adler & 0xffff |0, - s2 = adler >>> 16 & 0xffff |0, - n = 0; - - while (len !== 0) { - // Set limit ~ twice less than 5552, to keep - // s2 in 31-bits, because we force signed ints. - // in other case %= will fail. - n = len > 2000 ? 2000 : len; - len -= n; - - do { - s1 = s1 + buf[pos++] |0; - s2 = s2 + s1 |0; - } while (--n); - - s1 %= 65521; - s2 %= 65521; - } - - return s1 | s2 << 16 |0; -} - -// Note: we can't get significant speed boost here. -// So write code to minimize size - no pregenerated tables -// and array tools dependencies. - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -// Use ordinary array, since untyped makes no boost here -function makeTable() { - let c; - const table = []; - - for (let n = 0; n < 256; n++) { - c = n; - for (let k = 0; k < 8; k++) { - c = c & 1 ? 0xEDB88320 ^ c >>> 1 : c >>> 1; - } - table[n] = c; - } - - return table; -} - -// Create table on load. Just 255 signed longs. Not a problem. -const crcTable = makeTable(); - - -function crc32(crc, buf, len, pos) { - const t = crcTable, - end = pos + len; - - crc ^= -1; - - for (let i = pos; i < end; i++) { - crc = crc >>> 8 ^ t[(crc ^ buf[i]) & 0xFF]; - } - - return crc ^ -1; // >>> 0; -} - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -var msg = { - 2: "need dictionary", /* Z_NEED_DICT 2 */ - 1: "stream end", /* Z_STREAM_END 1 */ - 0: "", /* Z_OK 0 */ - "-1": "file error", /* Z_ERRNO (-1) */ - "-2": "stream error", /* Z_STREAM_ERROR (-2) */ - "-3": "data error", /* Z_DATA_ERROR (-3) */ - "-4": "insufficient memory", /* Z_MEM_ERROR (-4) */ - "-5": "buffer error", /* Z_BUF_ERROR (-5) */ - "-6": "incompatible version" /* Z_VERSION_ERROR (-6) */ -}; - -/*============================================================================*/ - - -const MAX_MEM_LEVEL = 9; - - -const LENGTH_CODES$1 = 29; -/* number of length codes, not counting the special END_BLOCK code */ -const LITERALS$1 = 256; -/* number of literal bytes 0..255 */ -const L_CODES$1 = LITERALS$1 + 1 + LENGTH_CODES$1; -/* number of Literal or Length codes, including the END_BLOCK code */ -const D_CODES$1 = 30; -/* number of distance codes */ -const BL_CODES$1 = 19; -/* number of codes used to transfer the bit lengths */ -const HEAP_SIZE$1 = 2 * L_CODES$1 + 1; -/* maximum heap size */ -const MAX_BITS$1 = 15; -/* All codes must not exceed MAX_BITS bits */ - -const MIN_MATCH$1 = 3; -const MAX_MATCH$1 = 258; -const MIN_LOOKAHEAD = (MAX_MATCH$1 + MIN_MATCH$1 + 1); - -const PRESET_DICT = 0x20; - -const INIT_STATE = 42; -const EXTRA_STATE = 69; -const NAME_STATE = 73; -const COMMENT_STATE = 91; -const HCRC_STATE = 103; -const BUSY_STATE = 113; -const FINISH_STATE = 666; - -const BS_NEED_MORE = 1; /* block not completed, need more input or more output */ -const BS_BLOCK_DONE = 2; /* block flush performed */ -const BS_FINISH_STARTED = 3; /* finish started, need only more output at next deflate */ -const BS_FINISH_DONE = 4; /* finish done, accept no more input or output */ - -const OS_CODE = 0x03; // Unix :) . Don't detect, use this default. - -function err(strm, errorCode) { - strm.msg = msg[errorCode]; - return errorCode; -} - -function rank(f) { - return ((f) << 1) - ((f) > 4 ? 9 : 0); -} - -function zero$2(buf) { let len = buf.length; while (--len >= 0) { buf[len] = 0; } } - - -/* ========================================================================= - * Flush as much pending output as possible. All deflate() output goes - * through this function so some applications may wish to modify it - * to avoid allocating a large strm->output buffer and copying into it. - * (See also read_buf()). - */ -function flush_pending(strm) { - const s = strm.state; - - //_tr_flush_bits(s); - let len = s.pending; - if (len > strm.avail_out) { - len = strm.avail_out; - } - if (len === 0) { return; } - - arraySet(strm.output, s.pending_buf, s.pending_out, len, strm.next_out); - strm.next_out += len; - s.pending_out += len; - strm.total_out += len; - strm.avail_out -= len; - s.pending -= len; - if (s.pending === 0) { - s.pending_out = 0; - } -} - - -function flush_block_only(s, last) { - _tr_flush_block(s, (s.block_start >= 0 ? s.block_start : -1), s.strstart - s.block_start, last); - s.block_start = s.strstart; - flush_pending(s.strm); -} - - -function put_byte(s, b) { - s.pending_buf[s.pending++] = b; -} - - -/* ========================================================================= - * Put a short in the pending buffer. The 16-bit value is put in MSB order. - * IN assertion: the stream state is correct and there is enough room in - * pending_buf. - */ -function putShortMSB(s, b) { - // put_byte(s, (Byte)(b >> 8)); - // put_byte(s, (Byte)(b & 0xff)); - s.pending_buf[s.pending++] = (b >>> 8) & 0xff; - s.pending_buf[s.pending++] = b & 0xff; -} - - -/* =========================================================================== - * Read a new buffer from the current input stream, update the adler32 - * and total number of bytes read. All deflate() input goes through - * this function so some applications may wish to modify it to avoid - * allocating a large strm->input buffer and copying from it. - * (See also flush_pending()). - */ -function read_buf(strm, buf, start, size) { - let len = strm.avail_in; - - if (len > size) { len = size; } - if (len === 0) { return 0; } - - strm.avail_in -= len; - - // zmemcpy(buf, strm->next_in, len); - arraySet(buf, strm.input, strm.next_in, len, start); - if (strm.state.wrap === 1) { - strm.adler = adler32(strm.adler, buf, len, start); - } - - else if (strm.state.wrap === 2) { - strm.adler = crc32(strm.adler, buf, len, start); - } - - strm.next_in += len; - strm.total_in += len; - - return len; -} - - -/* =========================================================================== - * Set match_start to the longest match starting at the given string and - * return its length. Matches shorter or equal to prev_length are discarded, - * in which case the result is equal to prev_length and match_start is - * garbage. - * IN assertions: cur_match is the head of the hash chain for the current - * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 - * OUT assertion: the match length is not greater than s->lookahead. - */ -function longest_match(s, cur_match) { - let chain_length = s.max_chain_length; /* max hash chain length */ - let scan = s.strstart; /* current string */ - let match; /* matched string */ - let len; /* length of current match */ - let best_len = s.prev_length; /* best match length so far */ - let nice_match = s.nice_match; /* stop if match long enough */ - const limit = (s.strstart > (s.w_size - MIN_LOOKAHEAD)) ? - s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0/*NIL*/; - - const _win = s.window; // shortcut - - const wmask = s.w_mask; - const prev = s.prev; - - /* Stop when cur_match becomes <= limit. To simplify the code, - * we prevent matches with the string of window index 0. - */ - - const strend = s.strstart + MAX_MATCH$1; - let scan_end1 = _win[scan + best_len - 1]; - let scan_end = _win[scan + best_len]; - - /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - * It is easy to get rid of this optimization if necessary. - */ - // Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - - /* Do not waste too much time if we already have a good match: */ - if (s.prev_length >= s.good_match) { - chain_length >>= 2; - } - /* Do not look for matches beyond the end of the input. This is necessary - * to make deflate deterministic. - */ - if (nice_match > s.lookahead) { nice_match = s.lookahead; } - - // Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); - - do { - // Assert(cur_match < s->strstart, "no future"); - match = cur_match; - - /* Skip to next match if the match length cannot increase - * or if the match length is less than 2. Note that the checks below - * for insufficient lookahead only occur occasionally for performance - * reasons. Therefore uninitialized memory will be accessed, and - * conditional jumps will be made that depend on those values. - * However the length of the match is limited to the lookahead, so - * the output of deflate is not affected by the uninitialized values. - */ - - if (_win[match + best_len] !== scan_end || - _win[match + best_len - 1] !== scan_end1 || - _win[match] !== _win[scan] || - _win[++match] !== _win[scan + 1]) { - continue; - } - - /* The check at best_len-1 can be removed because it will be made - * again later. (This heuristic is not always a win.) - * It is not necessary to compare scan[2] and match[2] since they - * are always equal when the other bytes match, given that - * the hash keys are equal and that HASH_BITS >= 8. - */ - scan += 2; - match++; - // Assert(*scan == *match, "match[2]?"); - - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. - */ - do { - /*jshint noempty:false*/ - } while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - scan < strend); - - // Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - - len = MAX_MATCH$1 - (strend - scan); - scan = strend - MAX_MATCH$1; - - if (len > best_len) { - s.match_start = cur_match; - best_len = len; - if (len >= nice_match) { - break; - } - scan_end1 = _win[scan + best_len - 1]; - scan_end = _win[scan + best_len]; - } - } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0); - - if (best_len <= s.lookahead) { - return best_len; - } - return s.lookahead; -} - - -/* =========================================================================== - * Fill the window when the lookahead becomes insufficient. - * Updates strstart and lookahead. - * - * IN assertion: lookahead < MIN_LOOKAHEAD - * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD - * At least one byte has been read, or avail_in == 0; reads are - * performed for at least two bytes (required for the zip translate_eol - * option -- not supported here). - */ -function fill_window(s) { - const _w_size = s.w_size; - let p, n, m, more, str; - - //Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); - - do { - more = s.window_size - s.lookahead - s.strstart; - - // JS ints have 32 bit, block below not needed - /* Deal with !@#$% 64K limit: */ - //if (sizeof(int) <= 2) { - // if (more == 0 && s->strstart == 0 && s->lookahead == 0) { - // more = wsize; - // - // } else if (more == (unsigned)(-1)) { - // /* Very unlikely, but possible on 16 bit machine if - // * strstart == 0 && lookahead == 1 (input done a byte at time) - // */ - // more--; - // } - //} - - - /* If the window is almost full and there is insufficient lookahead, - * move the upper half to the lower one to make room in the upper half. - */ - if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) { - - arraySet(s.window, s.window, _w_size, _w_size, 0); - s.match_start -= _w_size; - s.strstart -= _w_size; - /* we now have strstart >= MAX_DIST */ - s.block_start -= _w_size; - - /* Slide the hash table (could be avoided with 32 bit values - at the expense of memory usage). We slide even when level == 0 - to keep the hash table consistent if we switch back to level > 0 - later. (Using level 0 permanently is not an optimal usage of - zlib, so we don't care about this pathological case.) - */ - - n = s.hash_size; - p = n; - do { - m = s.head[--p]; - s.head[p] = (m >= _w_size ? m - _w_size : 0); - } while (--n); - - n = _w_size; - p = n; - do { - m = s.prev[--p]; - s.prev[p] = (m >= _w_size ? m - _w_size : 0); - /* If n is not on any hash chain, prev[n] is garbage but - * its value will never be used. - */ - } while (--n); - - more += _w_size; - } - if (s.strm.avail_in === 0) { - break; - } - - /* If there was no sliding: - * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && - * more == window_size - lookahead - strstart - * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) - * => more >= window_size - 2*WSIZE + 2 - * In the BIG_MEM or MMAP case (not yet supported), - * window_size == input_size + MIN_LOOKAHEAD && - * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. - * Otherwise, window_size == 2*WSIZE so more >= 2. - * If there was sliding, more >= WSIZE. So in all cases, more >= 2. - */ - //Assert(more >= 2, "more < 2"); - n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more); - s.lookahead += n; - - /* Initialize the hash value now that we have some input: */ - if (s.lookahead + s.insert >= MIN_MATCH$1) { - str = s.strstart - s.insert; - s.ins_h = s.window[str]; - - /* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + 1]) & s.hash_mask; - //#if MIN_MATCH != 3 - // Call update_hash() MIN_MATCH-3 more times - //#endif - while (s.insert) { - /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH$1 - 1]) & s.hash_mask; - - s.prev[str & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = str; - str++; - s.insert--; - if (s.lookahead + s.insert < MIN_MATCH$1) { - break; - } - } - } - /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, - * but this is not important since only literal bytes will be emitted. - */ - - } while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0); - - /* If the WIN_INIT bytes after the end of the current data have never been - * written, then zero those bytes in order to avoid memory check reports of - * the use of uninitialized (or uninitialised as Julian writes) bytes by - * the longest match routines. Update the high water mark for the next - * time through here. WIN_INIT is set to MAX_MATCH since the longest match - * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. - */ - // if (s.high_water < s.window_size) { - // var curr = s.strstart + s.lookahead; - // var init = 0; - // - // if (s.high_water < curr) { - // /* Previous high water mark below current data -- zero WIN_INIT - // * bytes or up to end of window, whichever is less. - // */ - // init = s.window_size - curr; - // if (init > WIN_INIT) - // init = WIN_INIT; - // zmemzero(s->window + curr, (unsigned)init); - // s->high_water = curr + init; - // } - // else if (s->high_water < (ulg)curr + WIN_INIT) { - // /* High water mark at or above current data, but below current data - // * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up - // * to end of window, whichever is less. - // */ - // init = (ulg)curr + WIN_INIT - s->high_water; - // if (init > s->window_size - s->high_water) - // init = s->window_size - s->high_water; - // zmemzero(s->window + s->high_water, (unsigned)init); - // s->high_water += init; - // } - // } - // - // Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, - // "not enough room for search"); -} - -/* =========================================================================== - * Copy without compression as much as possible from the input stream, return - * the current block state. - * This function does not insert new strings in the dictionary since - * uncompressible data is probably not useful. This function is used - * only for the level=0 compression option. - * NOTE: this function should be optimized to avoid extra copying from - * window to pending_buf. - */ -function deflate_stored(s, flush) { - /* Stored blocks are limited to 0xffff bytes, pending_buf is limited - * to pending_buf_size, and each stored block has a 5 byte header: - */ - let max_block_size = 0xffff; - - if (max_block_size > s.pending_buf_size - 5) { - max_block_size = s.pending_buf_size - 5; - } - - /* Copy as much as possible from input to output: */ - for (; ;) { - /* Fill the window as much as possible: */ - if (s.lookahead <= 1) { - - //Assert(s->strstart < s->w_size+MAX_DIST(s) || - // s->block_start >= (long)s->w_size, "slide too late"); - // if (!(s.strstart < s.w_size + (s.w_size - MIN_LOOKAHEAD) || - // s.block_start >= s.w_size)) { - // throw new Error("slide too late"); - // } - - fill_window(s); - if (s.lookahead === 0 && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - - if (s.lookahead === 0) { - break; - } - /* flush the current block */ - } - //Assert(s->block_start >= 0L, "block gone"); - // if (s.block_start < 0) throw new Error("block gone"); - - s.strstart += s.lookahead; - s.lookahead = 0; - - /* Emit a stored block if pending_buf will be full: */ - const max_start = s.block_start + max_block_size; - - if (s.strstart === 0 || s.strstart >= max_start) { - /* strstart == 0 is possible when wraparound on 16-bit machine */ - s.lookahead = s.strstart - max_start; - s.strstart = max_start; - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - - - } - /* Flush if we may have to slide, otherwise block_start may become - * negative and the data will be gone: - */ - if (s.strstart - s.block_start >= (s.w_size - MIN_LOOKAHEAD)) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } - - s.insert = 0; - - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - - if (s.strstart > s.block_start) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - - return BS_NEED_MORE; -} - -/* =========================================================================== - * Compress as much as possible from the input stream, return the current - * block state. - * This function does not perform lazy evaluation of matches and inserts - * new strings in the dictionary only for unmatched strings or for short - * matches. It is used only for the fast compression options. - */ -function deflate_fast(s, flush) { - let hash_head; /* head of the hash chain */ - let bflush; /* set if current block must be flushed */ - - for (; ;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s.lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - if (s.lookahead === 0) { - break; /* flush the current block */ - } - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - hash_head = 0/*NIL*/; - if (s.lookahead >= MIN_MATCH$1) { - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - } - - /* Find the longest match, discarding those <= prev_length. - * At this point we have always match_length < MIN_MATCH - */ - if (hash_head !== 0/*NIL*/ && ((s.strstart - hash_head) <= (s.w_size - MIN_LOOKAHEAD))) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - s.match_length = longest_match(s, hash_head); - /* longest_match() sets match_start */ - } - if (s.match_length >= MIN_MATCH$1) { - // check_match(s, s.strstart, s.match_start, s.match_length); // for debug only - - /*** _tr_tally_dist(s, s.strstart - s.match_start, - s.match_length - MIN_MATCH, bflush); ***/ - bflush = _tr_tally(s, s.strstart - s.match_start, s.match_length - MIN_MATCH$1); - - s.lookahead -= s.match_length; - - /* Insert new strings in the hash table only if the match length - * is not too large. This saves time but degrades compression. - */ - if (s.match_length <= s.max_lazy_match/*max_insert_length*/ && s.lookahead >= MIN_MATCH$1) { - s.match_length--; /* string at strstart already in table */ - do { - s.strstart++; - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - /* strstart never exceeds WSIZE-MAX_MATCH, so there are - * always MIN_MATCH bytes ahead. - */ - } while (--s.match_length !== 0); - s.strstart++; - } else { - s.strstart += s.match_length; - s.match_length = 0; - s.ins_h = s.window[s.strstart]; - /* UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]); */ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + 1]) & s.hash_mask; - - //#if MIN_MATCH != 3 - // Call UPDATE_HASH() MIN_MATCH-3 more times - //#endif - /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not - * matter since it will be recomputed at next deflate call. - */ - } - } else { - /* No match, output a literal byte */ - //Tracevv((stderr,"%c", s.window[s.strstart])); - /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ - bflush = _tr_tally(s, 0, s.window[s.strstart]); - - s.lookahead--; - s.strstart++; - } - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } - s.insert = ((s.strstart < (MIN_MATCH$1 - 1)) ? s.strstart : MIN_MATCH$1 - 1); - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - return BS_BLOCK_DONE; -} - -/* =========================================================================== - * Same as above, but achieves better compression. We use a lazy - * evaluation for matches: a match is finally adopted only if there is - * no better match at the next window position. - */ -function deflate_slow(s, flush) { - let hash_head; /* head of hash chain */ - let bflush; /* set if current block must be flushed */ - - let max_insert; - - /* Process the input block. */ - for (; ;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s.lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - if (s.lookahead === 0) { break; } /* flush the current block */ - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - hash_head = 0/*NIL*/; - if (s.lookahead >= MIN_MATCH$1) { - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - } - - /* Find the longest match, discarding those <= prev_length. - */ - s.prev_length = s.match_length; - s.prev_match = s.match_start; - s.match_length = MIN_MATCH$1 - 1; - - if (hash_head !== 0/*NIL*/ && s.prev_length < s.max_lazy_match && - s.strstart - hash_head <= (s.w_size - MIN_LOOKAHEAD)/*MAX_DIST(s)*/) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - s.match_length = longest_match(s, hash_head); - /* longest_match() sets match_start */ - - if (s.match_length <= 5 && - (s.strategy === Z_FILTERED || (s.match_length === MIN_MATCH$1 && s.strstart - s.match_start > 4096/*TOO_FAR*/))) { - - /* If prev_match is also MIN_MATCH, match_start is garbage - * but we will ignore the current match anyway. - */ - s.match_length = MIN_MATCH$1 - 1; - } - } - /* If there was a match at the previous step and the current - * match is not better, output the previous match: - */ - if (s.prev_length >= MIN_MATCH$1 && s.match_length <= s.prev_length) { - max_insert = s.strstart + s.lookahead - MIN_MATCH$1; - /* Do not insert strings in hash table beyond this. */ - - //check_match(s, s.strstart-1, s.prev_match, s.prev_length); - - /***_tr_tally_dist(s, s.strstart - 1 - s.prev_match, - s.prev_length - MIN_MATCH, bflush);***/ - bflush = _tr_tally(s, s.strstart - 1 - s.prev_match, s.prev_length - MIN_MATCH$1); - /* Insert in hash table all strings up to the end of the match. - * strstart-1 and strstart are already inserted. If there is not - * enough lookahead, the last two strings are not inserted in - * the hash table. - */ - s.lookahead -= s.prev_length - 1; - s.prev_length -= 2; - do { - if (++s.strstart <= max_insert) { - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - } - } while (--s.prev_length !== 0); - s.match_available = 0; - s.match_length = MIN_MATCH$1 - 1; - s.strstart++; - - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - - } else if (s.match_available) { - /* If there was no match at the previous position, output a - * single literal. If there was a match but the current match - * is longer, truncate the previous match to a single literal. - */ - //Tracevv((stderr,"%c", s->window[s->strstart-1])); - /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ - bflush = _tr_tally(s, 0, s.window[s.strstart - 1]); - - if (bflush) { - /*** FLUSH_BLOCK_ONLY(s, 0) ***/ - flush_block_only(s, false); - /***/ - } - s.strstart++; - s.lookahead--; - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - } else { - /* There is no previous match to compare with, wait for - * the next step to decide. - */ - s.match_available = 1; - s.strstart++; - s.lookahead--; - } - } - //Assert (flush != Z_NO_FLUSH, "no flush?"); - if (s.match_available) { - //Tracevv((stderr,"%c", s->window[s->strstart-1])); - /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ - bflush = _tr_tally(s, 0, s.window[s.strstart - 1]); - - s.match_available = 0; - } - s.insert = s.strstart < MIN_MATCH$1 - 1 ? s.strstart : MIN_MATCH$1 - 1; - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - - return BS_BLOCK_DONE; -} - - -/* =========================================================================== - * For Z_RLE, simply look for runs of bytes, generate matches only of distance - * one. Do not maintain a hash table. (It will be regenerated if this run of - * deflate switches away from Z_RLE.) - */ -function deflate_rle(s, flush) { - let bflush; /* set if current block must be flushed */ - let prev; /* byte at distance one to match */ - let scan, strend; /* scan goes up to strend for length of run */ - - const _win = s.window; - - for (; ;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the longest run, plus one for the unrolled loop. - */ - if (s.lookahead <= MAX_MATCH$1) { - fill_window(s); - if (s.lookahead <= MAX_MATCH$1 && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - if (s.lookahead === 0) { break; } /* flush the current block */ - } - - /* See how many times the previous byte repeats */ - s.match_length = 0; - if (s.lookahead >= MIN_MATCH$1 && s.strstart > 0) { - scan = s.strstart - 1; - prev = _win[scan]; - if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) { - strend = s.strstart + MAX_MATCH$1; - do { - /*jshint noempty:false*/ - } while (prev === _win[++scan] && prev === _win[++scan] && - prev === _win[++scan] && prev === _win[++scan] && - prev === _win[++scan] && prev === _win[++scan] && - prev === _win[++scan] && prev === _win[++scan] && - scan < strend); - s.match_length = MAX_MATCH$1 - (strend - scan); - if (s.match_length > s.lookahead) { - s.match_length = s.lookahead; - } - } - //Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); - } - - /* Emit match if have run of MIN_MATCH or longer, else emit literal */ - if (s.match_length >= MIN_MATCH$1) { - //check_match(s, s.strstart, s.strstart - 1, s.match_length); - - /*** _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ***/ - bflush = _tr_tally(s, 1, s.match_length - MIN_MATCH$1); - - s.lookahead -= s.match_length; - s.strstart += s.match_length; - s.match_length = 0; - } else { - /* No match, output a literal byte */ - //Tracevv((stderr,"%c", s->window[s->strstart])); - /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ - bflush = _tr_tally(s, 0, s.window[s.strstart]); - - s.lookahead--; - s.strstart++; - } - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } - s.insert = 0; - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - return BS_BLOCK_DONE; -} - -/* =========================================================================== - * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. - * (It will be regenerated if this run of deflate switches away from Huffman.) - */ -function deflate_huff(s, flush) { - let bflush; /* set if current block must be flushed */ - - for (; ;) { - /* Make sure that we have a literal to write. */ - if (s.lookahead === 0) { - fill_window(s); - if (s.lookahead === 0) { - if (flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - break; /* flush the current block */ - } - } - - /* Output a literal byte */ - s.match_length = 0; - //Tracevv((stderr,"%c", s->window[s->strstart])); - /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ - bflush = _tr_tally(s, 0, s.window[s.strstart]); - s.lookahead--; - s.strstart++; - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } - s.insert = 0; - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - return BS_BLOCK_DONE; -} - -/* Values for max_lazy_match, good_match and max_chain_length, depending on - * the desired pack level (0..9). The values given below have been tuned to - * exclude worst case performance for pathological files. Better values may be - * found for specific files. - */ -class Config { - constructor(good_length, max_lazy, nice_length, max_chain, func) { - this.good_length = good_length; - this.max_lazy = max_lazy; - this.nice_length = nice_length; - this.max_chain = max_chain; - this.func = func; - } -} -const configuration_table = [ - /* good lazy nice chain */ - new Config(0, 0, 0, 0, deflate_stored), /* 0 store only */ - new Config(4, 4, 8, 4, deflate_fast), /* 1 max speed, no lazy matches */ - new Config(4, 5, 16, 8, deflate_fast), /* 2 */ - new Config(4, 6, 32, 32, deflate_fast), /* 3 */ - - new Config(4, 4, 16, 16, deflate_slow), /* 4 lazy matches */ - new Config(8, 16, 32, 32, deflate_slow), /* 5 */ - new Config(8, 16, 128, 128, deflate_slow), /* 6 */ - new Config(8, 32, 128, 256, deflate_slow), /* 7 */ - new Config(32, 128, 258, 1024, deflate_slow), /* 8 */ - new Config(32, 258, 258, 4096, deflate_slow) /* 9 max compression */ -]; - - -/* =========================================================================== - * Initialize the "longest match" routines for a new zlib stream - */ -function lm_init(s) { - s.window_size = 2 * s.w_size; - - /*** CLEAR_HASH(s); ***/ - zero$2(s.head); // Fill with NIL (= 0); - - /* Set the default configuration parameters: - */ - s.max_lazy_match = configuration_table[s.level].max_lazy; - s.good_match = configuration_table[s.level].good_length; - s.nice_match = configuration_table[s.level].nice_length; - s.max_chain_length = configuration_table[s.level].max_chain; - - s.strstart = 0; - s.block_start = 0; - s.lookahead = 0; - s.insert = 0; - s.match_length = s.prev_length = MIN_MATCH$1 - 1; - s.match_available = 0; - s.ins_h = 0; -} - -class DeflateState { - constructor() { - this.strm = null; /* pointer back to this zlib stream */ - this.status = 0; /* as the name implies */ - this.pending_buf = null; /* output still pending */ - this.pending_buf_size = 0; /* size of pending_buf */ - this.pending_out = 0; /* next pending byte to output to the stream */ - this.pending = 0; /* nb of bytes in the pending buffer */ - this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ - this.gzhead = null; /* gzip header information to write */ - this.gzindex = 0; /* where in extra, name, or comment */ - this.method = Z_DEFLATED; /* can only be DEFLATED */ - this.last_flush = -1; /* value of flush param for previous deflate call */ - - this.w_size = 0; /* LZ77 window size (32K by default) */ - this.w_bits = 0; /* log2(w_size) (8..16) */ - this.w_mask = 0; /* w_size - 1 */ - - this.window = null; - /* Sliding window. Input bytes are read into the second half of the window, - * and move to the first half later to keep a dictionary of at least wSize - * bytes. With this organization, matches are limited to a distance of - * wSize-MAX_MATCH bytes, but this ensures that IO is always - * performed with a length multiple of the block size. - */ - - this.window_size = 0; - /* Actual size of window: 2*wSize, except when the user input buffer - * is directly used as sliding window. - */ - - this.prev = null; - /* Link to older string with same hash index. To limit the size of this - * array to 64K, this link is maintained only for the last 32K strings. - * An index in this array is thus a window index modulo 32K. - */ - - this.head = null; /* Heads of the hash chains or NIL. */ - - this.ins_h = 0; /* hash index of string to be inserted */ - this.hash_size = 0; /* number of elements in hash table */ - this.hash_bits = 0; /* log2(hash_size) */ - this.hash_mask = 0; /* hash_size-1 */ - - this.hash_shift = 0; - /* Number of bits by which ins_h must be shifted at each input - * step. It must be such that after MIN_MATCH steps, the oldest - * byte no longer takes part in the hash key, that is: - * hash_shift * MIN_MATCH >= hash_bits - */ - - this.block_start = 0; - /* Window position at the beginning of the current output block. Gets - * negative when the window is moved backwards. - */ - - this.match_length = 0; /* length of best match */ - this.prev_match = 0; /* previous match */ - this.match_available = 0; /* set if previous match exists */ - this.strstart = 0; /* start of string to insert */ - this.match_start = 0; /* start of matching string */ - this.lookahead = 0; /* number of valid bytes ahead in window */ - - this.prev_length = 0; - /* Length of the best match at previous step. Matches not greater than this - * are discarded. This is used in the lazy match evaluation. - */ - - this.max_chain_length = 0; - /* To speed up deflation, hash chains are never searched beyond this - * length. A higher limit improves compression ratio but degrades the - * speed. - */ - - this.max_lazy_match = 0; - /* Attempt to find a better match only when the current match is strictly - * smaller than this value. This mechanism is used only for compression - * levels >= 4. - */ - // That's alias to max_lazy_match, don't use directly - //this.max_insert_length = 0; - /* Insert new strings in the hash table only if the match length is not - * greater than this length. This saves time but degrades compression. - * max_insert_length is used only for compression levels <= 3. - */ - - this.level = 0; /* compression level (1..9) */ - this.strategy = 0; /* favor or force Huffman coding*/ - - this.good_match = 0; - /* Use a faster search when the previous match is longer than this */ - - this.nice_match = 0; /* Stop searching when current match exceeds this */ - - /* used by trees.c: */ - - /* Didn't use ct_data typedef below to suppress compiler warning */ - - // struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ - // struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ - // struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ - - // Use flat array of DOUBLE size, with interleaved fata, - // because JS does not support effective - this.dyn_ltree = new Buf16(HEAP_SIZE$1 * 2); - this.dyn_dtree = new Buf16((2 * D_CODES$1 + 1) * 2); - this.bl_tree = new Buf16((2 * BL_CODES$1 + 1) * 2); - zero$2(this.dyn_ltree); - zero$2(this.dyn_dtree); - zero$2(this.bl_tree); - - this.l_desc = null; /* desc. for literal tree */ - this.d_desc = null; /* desc. for distance tree */ - this.bl_desc = null; /* desc. for bit length tree */ - - //ush bl_count[MAX_BITS+1]; - this.bl_count = new Buf16(MAX_BITS$1 + 1); - /* number of codes at each bit length for an optimal tree */ - - //int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ - this.heap = new Buf16(2 * L_CODES$1 + 1); /* heap used to build the Huffman trees */ - zero$2(this.heap); - - this.heap_len = 0; /* number of elements in the heap */ - this.heap_max = 0; /* element of largest frequency */ - /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. - * The same heap array is used to build all trees. - */ - - this.depth = new Buf16(2 * L_CODES$1 + 1); //uch depth[2*L_CODES+1]; - zero$2(this.depth); - /* Depth of each subtree used as tie breaker for trees of equal frequency - */ - - this.l_buf = 0; /* buffer index for literals or lengths */ - - this.lit_bufsize = 0; - /* Size of match buffer for literals/lengths. There are 4 reasons for - * limiting lit_bufsize to 64K: - * - frequencies can be kept in 16 bit counters - * - if compression is not successful for the first block, all input - * data is still in the window so we can still emit a stored block even - * when input comes from standard input. (This can also be done for - * all blocks if lit_bufsize is not greater than 32K.) - * - if compression is not successful for a file smaller than 64K, we can - * even emit a stored file instead of a stored block (saving 5 bytes). - * This is applicable only for zip (not gzip or zlib). - * - creating new Huffman trees less frequently may not provide fast - * adaptation to changes in the input data statistics. (Take for - * example a binary file with poorly compressible code followed by - * a highly compressible string table.) Smaller buffer sizes give - * fast adaptation but have of course the overhead of transmitting - * trees more frequently. - * - I can't count above 4 - */ - - this.last_lit = 0; /* running index in l_buf */ - - this.d_buf = 0; - /* Buffer index for distances. To simplify the code, d_buf and l_buf have - * the same number of elements. To use different lengths, an extra flag - * array would be necessary. - */ - - this.opt_len = 0; /* bit length of current block with optimal trees */ - this.static_len = 0; /* bit length of current block with static trees */ - this.matches = 0; /* number of string matches in current block */ - this.insert = 0; /* bytes at end of window left to insert */ - - - this.bi_buf = 0; - /* Output buffer. bits are inserted starting at the bottom (least - * significant bits). - */ - this.bi_valid = 0; - /* Number of valid bits in bi_buf. All bits above the last valid bit - * are always zero. - */ - - // Used for window memory init. We safely ignore it for JS. That makes - // sense only for pointers and memory check tools. - //this.high_water = 0; - /* High water mark offset in window for initialized bytes -- bytes above - * this are set to zero in order to avoid memory check warnings when - * longest match routines access bytes past the input. This is then - * updated to the new high water mark. - */ - } -} - -function deflateResetKeep(strm) { - let s; - - if (!strm || !strm.state) { - return err(strm, Z_STREAM_ERROR); - } - - strm.total_in = strm.total_out = 0; - strm.data_type = Z_UNKNOWN; - - s = strm.state; - s.pending = 0; - s.pending_out = 0; - - if (s.wrap < 0) { - s.wrap = -s.wrap; - /* was made negative by deflate(..., Z_FINISH); */ - } - s.status = (s.wrap ? INIT_STATE : BUSY_STATE); - strm.adler = (s.wrap === 2) ? - 0 // crc32(0, Z_NULL, 0) - : - 1; // adler32(0, Z_NULL, 0) - s.last_flush = Z_NO_FLUSH; - _tr_init(s); - return Z_OK; -} - - -function deflateReset(strm) { - const ret = deflateResetKeep(strm); - if (ret === Z_OK) { - lm_init(strm.state); - } - return ret; -} - - -function deflateSetHeader(strm, head) { - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - if (strm.state.wrap !== 2) { return Z_STREAM_ERROR; } - strm.state.gzhead = head; - return Z_OK; -} - - -function deflateInit2(strm, level, method, windowBits, memLevel, strategy) { - if (!strm) { // === Z_NULL - return Z_STREAM_ERROR; - } - let wrap = 1; - - if (level === Z_DEFAULT_COMPRESSION) { - level = 6; - } - - if (windowBits < 0) { /* suppress zlib wrapper */ - wrap = 0; - windowBits = -windowBits; - } - - else if (windowBits > 15) { - wrap = 2; /* write gzip wrapper instead */ - windowBits -= 16; - } - - - if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method !== Z_DEFLATED || - windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || - strategy < 0 || strategy > Z_FIXED) { - return err(strm, Z_STREAM_ERROR); - } - - - if (windowBits === 8) { - windowBits = 9; - } - /* until 256-byte window bug fixed */ - - const s = new DeflateState(); - - strm.state = s; - s.strm = strm; - - s.wrap = wrap; - s.gzhead = null; - s.w_bits = windowBits; - s.w_size = 1 << s.w_bits; - s.w_mask = s.w_size - 1; - - s.hash_bits = memLevel + 7; - s.hash_size = 1 << s.hash_bits; - s.hash_mask = s.hash_size - 1; - s.hash_shift = ~~((s.hash_bits + MIN_MATCH$1 - 1) / MIN_MATCH$1); - s.window = new Buf8(s.w_size * 2); - s.head = new Buf16(s.hash_size); - s.prev = new Buf16(s.w_size); - - // Don't need mem init magic for JS. - //s.high_water = 0; /* nothing written to s->window yet */ - - s.lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ - - s.pending_buf_size = s.lit_bufsize * 4; - - //overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); - //s->pending_buf = (uchf *) overlay; - s.pending_buf = new Buf8(s.pending_buf_size); - - // It is offset from `s.pending_buf` (size is `s.lit_bufsize * 2`) - //s->d_buf = overlay + s->lit_bufsize/sizeof(ush); - s.d_buf = 1 * s.lit_bufsize; - - //s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; - s.l_buf = (1 + 2) * s.lit_bufsize; - - s.level = level; - s.strategy = strategy; - s.method = method; - - return deflateReset(strm); -} - - -function deflate(strm, flush) { - let old_flush, s; - let beg, val; // for gzip header write only - - if (!strm || !strm.state || - flush > Z_BLOCK || flush < 0) { - return strm ? err(strm, Z_STREAM_ERROR) : Z_STREAM_ERROR; - } - - s = strm.state; - - if (!strm.output || - (!strm.input && strm.avail_in !== 0) || - (s.status === FINISH_STATE && flush !== Z_FINISH)) { - return err(strm, (strm.avail_out === 0) ? Z_BUF_ERROR : Z_STREAM_ERROR); - } - - s.strm = strm; /* just in case */ - old_flush = s.last_flush; - s.last_flush = flush; - - /* Write the header */ - if (s.status === INIT_STATE) { - - if (s.wrap === 2) { // GZIP header - strm.adler = 0; //crc32(0L, Z_NULL, 0); - put_byte(s, 31); - put_byte(s, 139); - put_byte(s, 8); - if (!s.gzhead) { // s->gzhead == Z_NULL - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, s.level === 9 ? 2 : - (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? - 4 : 0)); - put_byte(s, OS_CODE); - s.status = BUSY_STATE; - } - else { - put_byte(s, (s.gzhead.text ? 1 : 0) + - (s.gzhead.hcrc ? 2 : 0) + - (!s.gzhead.extra ? 0 : 4) + - (!s.gzhead.name ? 0 : 8) + - (!s.gzhead.comment ? 0 : 16) - ); - put_byte(s, s.gzhead.time & 0xff); - put_byte(s, (s.gzhead.time >> 8) & 0xff); - put_byte(s, (s.gzhead.time >> 16) & 0xff); - put_byte(s, (s.gzhead.time >> 24) & 0xff); - put_byte(s, s.level === 9 ? 2 : - (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? - 4 : 0)); - put_byte(s, s.gzhead.os & 0xff); - if (s.gzhead.extra && s.gzhead.extra.length) { - put_byte(s, s.gzhead.extra.length & 0xff); - put_byte(s, (s.gzhead.extra.length >> 8) & 0xff); - } - if (s.gzhead.hcrc) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending, 0); - } - s.gzindex = 0; - s.status = EXTRA_STATE; - } - } - else // DEFLATE header - { - let header = (Z_DEFLATED + ((s.w_bits - 8) << 4)) << 8; - let level_flags = -1; - - if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) { - level_flags = 0; - } else if (s.level < 6) { - level_flags = 1; - } else if (s.level === 6) { - level_flags = 2; - } else { - level_flags = 3; - } - header |= (level_flags << 6); - if (s.strstart !== 0) { header |= PRESET_DICT; } - header += 31 - (header % 31); - - s.status = BUSY_STATE; - putShortMSB(s, header); - - /* Save the adler32 of the preset dictionary: */ - if (s.strstart !== 0) { - putShortMSB(s, strm.adler >>> 16); - putShortMSB(s, strm.adler & 0xffff); - } - strm.adler = 1; // adler32(0L, Z_NULL, 0); - } - } - - //#ifdef GZIP - if (s.status === EXTRA_STATE) { - if (s.gzhead.extra/* != Z_NULL*/) { - beg = s.pending; /* start of bytes to update crc */ - - while (s.gzindex < (s.gzhead.extra.length & 0xffff)) { - if (s.pending === s.pending_buf_size) { - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - flush_pending(strm); - beg = s.pending; - if (s.pending === s.pending_buf_size) { - break; - } - } - put_byte(s, s.gzhead.extra[s.gzindex] & 0xff); - s.gzindex++; - } - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - if (s.gzindex === s.gzhead.extra.length) { - s.gzindex = 0; - s.status = NAME_STATE; - } - } - else { - s.status = NAME_STATE; - } - } - if (s.status === NAME_STATE) { - if (s.gzhead.name/* != Z_NULL*/) { - beg = s.pending; /* start of bytes to update crc */ - //int val; - - do { - if (s.pending === s.pending_buf_size) { - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - flush_pending(strm); - beg = s.pending; - if (s.pending === s.pending_buf_size) { - val = 1; - break; - } - } - // JS specific: little magic to add zero terminator to end of string - if (s.gzindex < s.gzhead.name.length) { - val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff; - } else { - val = 0; - } - put_byte(s, val); - } while (val !== 0); - - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - if (val === 0) { - s.gzindex = 0; - s.status = COMMENT_STATE; - } - } - else { - s.status = COMMENT_STATE; - } - } - if (s.status === COMMENT_STATE) { - if (s.gzhead.comment/* != Z_NULL*/) { - beg = s.pending; /* start of bytes to update crc */ - //int val; - - do { - if (s.pending === s.pending_buf_size) { - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - flush_pending(strm); - beg = s.pending; - if (s.pending === s.pending_buf_size) { - val = 1; - break; - } - } - // JS specific: little magic to add zero terminator to end of string - if (s.gzindex < s.gzhead.comment.length) { - val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff; - } else { - val = 0; - } - put_byte(s, val); - } while (val !== 0); - - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - if (val === 0) { - s.status = HCRC_STATE; - } - } - else { - s.status = HCRC_STATE; - } - } - if (s.status === HCRC_STATE) { - if (s.gzhead.hcrc) { - if (s.pending + 2 > s.pending_buf_size) { - flush_pending(strm); - } - if (s.pending + 2 <= s.pending_buf_size) { - put_byte(s, strm.adler & 0xff); - put_byte(s, (strm.adler >> 8) & 0xff); - strm.adler = 0; //crc32(0L, Z_NULL, 0); - s.status = BUSY_STATE; - } - } - else { - s.status = BUSY_STATE; - } - } - //#endif - - /* Flush as much pending output as possible */ - if (s.pending !== 0) { - flush_pending(strm); - if (strm.avail_out === 0) { - /* Since avail_out is 0, deflate will be called again with - * more output space, but possibly with both pending and - * avail_in equal to zero. There won't be anything to do, - * but this is not an error situation so make sure we - * return OK instead of BUF_ERROR at next call of deflate: - */ - s.last_flush = -1; - return Z_OK; - } - - /* Make sure there is something to do and avoid duplicate consecutive - * flushes. For repeated and useless calls with Z_FINISH, we keep - * returning Z_STREAM_END instead of Z_BUF_ERROR. - */ - } else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) && - flush !== Z_FINISH) { - return err(strm, Z_BUF_ERROR); - } - - /* User must not provide more input after the first FINISH: */ - if (s.status === FINISH_STATE && strm.avail_in !== 0) { - return err(strm, Z_BUF_ERROR); - } - - /* Start a new block or continue the current one. - */ - if (strm.avail_in !== 0 || s.lookahead !== 0 || - (flush !== Z_NO_FLUSH && s.status !== FINISH_STATE)) { - var bstate = (s.strategy === Z_HUFFMAN_ONLY) ? deflate_huff(s, flush) : - (s.strategy === Z_RLE ? deflate_rle(s, flush) : - configuration_table[s.level].func(s, flush)); - - if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) { - s.status = FINISH_STATE; - } - if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) { - if (strm.avail_out === 0) { - s.last_flush = -1; - /* avoid BUF_ERROR next call, see above */ - } - return Z_OK; - /* If flush != Z_NO_FLUSH && avail_out == 0, the next call - * of deflate should use the same flush parameter to make sure - * that the flush is complete. So we don't have to output an - * empty block here, this will be done at next call. This also - * ensures that for a very small output buffer, we emit at most - * one empty block. - */ - } - if (bstate === BS_BLOCK_DONE) { - if (flush === Z_PARTIAL_FLUSH) { - _tr_align(s); - } - else if (flush !== Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ - - _tr_stored_block(s, 0, 0, false); - /* For a full flush, this empty block will be recognized - * as a special marker by inflate_sync(). - */ - if (flush === Z_FULL_FLUSH) { - /*** CLEAR_HASH(s); ***/ /* forget history */ - zero$2(s.head); // Fill with NIL (= 0); - - if (s.lookahead === 0) { - s.strstart = 0; - s.block_start = 0; - s.insert = 0; - } - } - } - flush_pending(strm); - if (strm.avail_out === 0) { - s.last_flush = -1; /* avoid BUF_ERROR at next call, see above */ - return Z_OK; - } - } - } - //Assert(strm->avail_out > 0, "bug2"); - //if (strm.avail_out <= 0) { throw new Error("bug2");} - - if (flush !== Z_FINISH) { return Z_OK; } - if (s.wrap <= 0) { return Z_STREAM_END; } - - /* Write the trailer */ - if (s.wrap === 2) { - put_byte(s, strm.adler & 0xff); - put_byte(s, (strm.adler >> 8) & 0xff); - put_byte(s, (strm.adler >> 16) & 0xff); - put_byte(s, (strm.adler >> 24) & 0xff); - put_byte(s, strm.total_in & 0xff); - put_byte(s, (strm.total_in >> 8) & 0xff); - put_byte(s, (strm.total_in >> 16) & 0xff); - put_byte(s, (strm.total_in >> 24) & 0xff); - } - else { - putShortMSB(s, strm.adler >>> 16); - putShortMSB(s, strm.adler & 0xffff); - } - - flush_pending(strm); - /* If avail_out is zero, the application will call deflate again - * to flush the rest. - */ - if (s.wrap > 0) { s.wrap = -s.wrap; } - /* write the trailer only once! */ - return s.pending !== 0 ? Z_OK : Z_STREAM_END; -} - -function deflateEnd(strm) { - let status; - - if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) { - return Z_STREAM_ERROR; - } - - status = strm.state.status; - if (status !== INIT_STATE && - status !== EXTRA_STATE && - status !== NAME_STATE && - status !== COMMENT_STATE && - status !== HCRC_STATE && - status !== BUSY_STATE && - status !== FINISH_STATE - ) { - return err(strm, Z_STREAM_ERROR); - } - - strm.state = null; - - return status === BUSY_STATE ? err(strm, Z_DATA_ERROR) : Z_OK; -} - - -/* ========================================================================= - * Initializes the compression dictionary from the given byte - * sequence without producing any compressed output. - */ -function deflateSetDictionary(strm, dictionary) { - let dictLength = dictionary.length; - - let s; - let str, n; - let wrap; - let avail; - let next; - let input; - let tmpDict; - - if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) { - return Z_STREAM_ERROR; - } - - s = strm.state; - wrap = s.wrap; - - if (wrap === 2 || (wrap === 1 && s.status !== INIT_STATE) || s.lookahead) { - return Z_STREAM_ERROR; - } - - /* when using zlib wrappers, compute Adler-32 for provided dictionary */ - if (wrap === 1) { - /* adler32(strm->adler, dictionary, dictLength); */ - strm.adler = adler32(strm.adler, dictionary, dictLength, 0); - } - - s.wrap = 0; /* avoid computing Adler-32 in read_buf */ - - /* if dictionary would fill window, just replace the history */ - if (dictLength >= s.w_size) { - if (wrap === 0) { /* already empty otherwise */ - /*** CLEAR_HASH(s); ***/ - zero$2(s.head); // Fill with NIL (= 0); - s.strstart = 0; - s.block_start = 0; - s.insert = 0; - } - /* use the tail */ - // dictionary = dictionary.slice(dictLength - s.w_size); - tmpDict = new Buf8(s.w_size); - arraySet(tmpDict, dictionary, dictLength - s.w_size, s.w_size, 0); - dictionary = tmpDict; - dictLength = s.w_size; - } - /* insert dictionary into window and hash */ - avail = strm.avail_in; - next = strm.next_in; - input = strm.input; - strm.avail_in = dictLength; - strm.next_in = 0; - strm.input = dictionary; - fill_window(s); - while (s.lookahead >= MIN_MATCH$1) { - str = s.strstart; - n = s.lookahead - (MIN_MATCH$1 - 1); - do { - /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH$1 - 1]) & s.hash_mask; - - s.prev[str & s.w_mask] = s.head[s.ins_h]; - - s.head[s.ins_h] = str; - str++; - } while (--n); - s.strstart = str; - s.lookahead = MIN_MATCH$1 - 1; - fill_window(s); - } - s.strstart += s.lookahead; - s.block_start = s.strstart; - s.insert = s.lookahead; - s.lookahead = 0; - s.match_length = s.prev_length = MIN_MATCH$1 - 1; - s.match_available = 0; - strm.next_in = next; - strm.input = input; - strm.avail_in = avail; - s.wrap = wrap; - return Z_OK; -} - -/* Not implemented -exports.deflateBound = deflateBound; -exports.deflateCopy = deflateCopy; -exports.deflateParams = deflateParams; -exports.deflatePending = deflatePending; -exports.deflatePrime = deflatePrime; -exports.deflateTune = deflateTune; -*/ - -// String encode/decode helpers - -try { - String.fromCharCode.apply(null, [ 0 ]); -} catch (__) { -} -try { - String.fromCharCode.apply(null, new Uint8Array(1)); -} catch (__) { -} - - -// Table with utf8 lengths (calculated by first byte of sequence) -// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS, -// because max possible codepoint is 0x10ffff -const _utf8len = new Buf8(256); -for (let q = 0; q < 256; q++) { - _utf8len[q] = q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1; -} -_utf8len[254] = _utf8len[254] = 1; // Invalid sequence start - - -// convert string to array (typed, when possible) -function string2buf (str) { - let c, c2, m_pos, i, buf_len = 0; - const str_len = str.length; - - // count binary size - for (m_pos = 0; m_pos < str_len; m_pos++) { - c = str.charCodeAt(m_pos); - if ((c & 0xfc00) === 0xd800 && m_pos + 1 < str_len) { - c2 = str.charCodeAt(m_pos + 1); - if ((c2 & 0xfc00) === 0xdc00) { - c = 0x10000 + (c - 0xd800 << 10) + (c2 - 0xdc00); - m_pos++; - } - } - buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4; - } - - // allocate buffer - const buf = new Buf8(buf_len); - - // convert - for (i = 0, m_pos = 0; i < buf_len; m_pos++) { - c = str.charCodeAt(m_pos); - if ((c & 0xfc00) === 0xd800 && m_pos + 1 < str_len) { - c2 = str.charCodeAt(m_pos + 1); - if ((c2 & 0xfc00) === 0xdc00) { - c = 0x10000 + (c - 0xd800 << 10) + (c2 - 0xdc00); - m_pos++; - } - } - if (c < 0x80) { - /* one byte */ - buf[i++] = c; - } else if (c < 0x800) { - /* two bytes */ - buf[i++] = 0xC0 | c >>> 6; - buf[i++] = 0x80 | c & 0x3f; - } else if (c < 0x10000) { - /* three bytes */ - buf[i++] = 0xE0 | c >>> 12; - buf[i++] = 0x80 | c >>> 6 & 0x3f; - buf[i++] = 0x80 | c & 0x3f; - } else { - /* four bytes */ - buf[i++] = 0xf0 | c >>> 18; - buf[i++] = 0x80 | c >>> 12 & 0x3f; - buf[i++] = 0x80 | c >>> 6 & 0x3f; - buf[i++] = 0x80 | c & 0x3f; - } - } - - return buf; -} - - -// Convert binary string (typed, when possible) -function binstring2buf (str) { - const buf = new Buf8(str.length); - for (let i = 0, len = buf.length; i < len; i++) { - buf[i] = str.charCodeAt(i); - } - return buf; -} - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -class ZStream { - constructor() { - /* next input byte */ - this.input = null; // JS specific, because we have no pointers - this.next_in = 0; - /* number of bytes available at input */ - this.avail_in = 0; - /* total number of input bytes read so far */ - this.total_in = 0; - /* next output byte should be put there */ - this.output = null; // JS specific, because we have no pointers - this.next_out = 0; - /* remaining free space at output */ - this.avail_out = 0; - /* total number of bytes output so far */ - this.total_out = 0; - /* last error message, NULL if no error */ - this.msg = ''/*Z_NULL*/; - /* not visible by applications */ - this.state = null; - /* best guess about the data type: binary or text */ - this.data_type = 2/*Z_UNKNOWN*/; - /* adler32 value of the uncompressed data */ - this.adler = 0; - } -} - -/* ===========================================================================*/ - - -/** - * class Deflate - * - * Generic JS-style wrapper for zlib calls. If you don't need - * streaming behaviour - use more simple functions: [[deflate]], - * [[deflateRaw]] and [[gzip]]. - **/ - -/* internal - * Deflate.chunks -> Array - * - * Chunks of output data, if [[Deflate#onData]] not overridden. - **/ - -/** - * Deflate.result -> Uint8Array|Array - * - * Compressed result, generated by default [[Deflate#onData]] - * and [[Deflate#onEnd]] handlers. Filled after you push last chunk - * (call [[Deflate#push]] with `Z_FINISH` / `true` param) or if you - * push a chunk with explicit flush (call [[Deflate#push]] with - * `Z_SYNC_FLUSH` param). - **/ - -/** - * Deflate.err -> Number - * - * Error code after deflate finished. 0 (Z_OK) on success. - * You will not need it in real life, because deflate errors - * are possible only on wrong options or bad `onData` / `onEnd` - * custom handlers. - **/ - -/** - * Deflate.msg -> String - * - * Error message, if [[Deflate.err]] != 0 - **/ - - -/** - * new Deflate(options) - * - options (Object): zlib deflate options. - * - * Creates new deflator instance with specified params. Throws exception - * on bad params. Supported options: - * - * - `level` - * - `windowBits` - * - `memLevel` - * - `strategy` - * - `dictionary` - * - * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) - * for more information on these. - * - * Additional options, for internal needs: - * - * - `chunkSize` - size of generated data chunks (16K by default) - * - `raw` (Boolean) - do raw deflate - * - `gzip` (Boolean) - create gzip wrapper - * - `to` (String) - if equal to 'string', then result will be "binary string" - * (each char code [0..255]) - * - `header` (Object) - custom header for gzip - * - `text` (Boolean) - true if compressed data believed to be text - * - `time` (Number) - modification time, unix timestamp - * - `os` (Number) - operation system code - * - `extra` (Array) - array of bytes with extra data (max 65536) - * - `name` (String) - file name (binary string) - * - `comment` (String) - comment (binary string) - * - `hcrc` (Boolean) - true if header crc should be added - * - * ##### Example: - * - * ```javascript - * var pako = require('pako') - * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9]) - * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]); - * - * var deflate = new pako.Deflate({ level: 3}); - * - * deflate.push(chunk1, false); - * deflate.push(chunk2, true); // true -> last chunk - * - * if (deflate.err) { throw new Error(deflate.err); } - * - * console.log(deflate.result); - * ``` - **/ - -class Deflate { - constructor(options) { - this.options = { - level: Z_DEFAULT_COMPRESSION, - method: Z_DEFLATED, - chunkSize: 16384, - windowBits: 15, - memLevel: 8, - strategy: Z_DEFAULT_STRATEGY, - ...(options || {}) - }; - - const opt = this.options; - - if (opt.raw && (opt.windowBits > 0)) { - opt.windowBits = -opt.windowBits; - } - - else if (opt.gzip && (opt.windowBits > 0) && (opt.windowBits < 16)) { - opt.windowBits += 16; - } - - this.err = 0; // error code, if happens (0 = Z_OK) - this.msg = ''; // error message - this.ended = false; // used to avoid multiple onEnd() calls - this.chunks = []; // chunks of compressed data - - this.strm = new ZStream(); - this.strm.avail_out = 0; - - var status = deflateInit2( - this.strm, - opt.level, - opt.method, - opt.windowBits, - opt.memLevel, - opt.strategy - ); - - if (status !== Z_OK) { - throw new Error(msg[status]); - } - - if (opt.header) { - deflateSetHeader(this.strm, opt.header); - } - - if (opt.dictionary) { - let dict; - // Convert data if needed - if (typeof opt.dictionary === 'string') { - // If we need to compress text, change encoding to utf8. - dict = string2buf(opt.dictionary); - } else if (opt.dictionary instanceof ArrayBuffer) { - dict = new Uint8Array(opt.dictionary); - } else { - dict = opt.dictionary; - } - - status = deflateSetDictionary(this.strm, dict); - - if (status !== Z_OK) { - throw new Error(msg[status]); - } - - this._dict_set = true; - } - } - - /** - * Deflate#push(data[, mode]) -> Boolean - * - data (Uint8Array|Array|ArrayBuffer|String): input data. Strings will be - * converted to utf8 byte sequence. - * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. - * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH. - * - * Sends input data to deflate pipe, generating [[Deflate#onData]] calls with - * new compressed chunks. Returns `true` on success. The last data block must have - * mode Z_FINISH (or `true`). That will flush internal pending buffers and call - * [[Deflate#onEnd]]. For interim explicit flushes (without ending the stream) you - * can use mode Z_SYNC_FLUSH, keeping the compression context. - * - * On fail call [[Deflate#onEnd]] with error code and return false. - * - * We strongly recommend to use `Uint8Array` on input for best speed (output - * array format is detected automatically). Also, don't skip last param and always - * use the same type in your code (boolean or number). That will improve JS speed. - * - * For regular `Array`-s make sure all elements are [0..255]. - * - * ##### Example - * - * ```javascript - * push(chunk, false); // push one of data chunks - * ... - * push(chunk, true); // push last chunk - * ``` - **/ - push(data, mode) { - const { strm, options: { chunkSize } } = this; - var status, _mode; - - if (this.ended) { return false; } - - _mode = (mode === ~~mode) ? mode : ((mode === true) ? Z_FINISH : Z_NO_FLUSH); - - // Convert data if needed - if (typeof data === 'string') { - // If we need to compress text, change encoding to utf8. - strm.input = string2buf(data); - } else if (data instanceof ArrayBuffer) { - strm.input = new Uint8Array(data); - } else { - strm.input = data; - } - - strm.next_in = 0; - strm.avail_in = strm.input.length; - - do { - if (strm.avail_out === 0) { - strm.output = new Buf8(chunkSize); - strm.next_out = 0; - strm.avail_out = chunkSize; - } - status = deflate(strm, _mode); /* no bad return value */ - - if (status !== Z_STREAM_END && status !== Z_OK) { - this.onEnd(status); - this.ended = true; - return false; - } - if (strm.avail_out === 0 || (strm.avail_in === 0 && (_mode === Z_FINISH || _mode === Z_SYNC_FLUSH))) { - this.onData(shrinkBuf(strm.output, strm.next_out)); - } - } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== Z_STREAM_END); - - // Finalize on the last chunk. - if (_mode === Z_FINISH) { - status = deflateEnd(this.strm); - this.onEnd(status); - this.ended = true; - return status === Z_OK; - } - - // callback interim results if Z_SYNC_FLUSH. - if (_mode === Z_SYNC_FLUSH) { - this.onEnd(Z_OK); - strm.avail_out = 0; - return true; - } - - return true; - }; - /** - * Deflate#onData(chunk) -> Void - * - chunk (Uint8Array|Array|String): output data. Type of array depends - * on js engine support. When string output requested, each chunk - * will be string. - * - * By default, stores data blocks in `chunks[]` property and glue - * those in `onEnd`. Override this handler, if you need another behaviour. - **/ - onData(chunk) { - this.chunks.push(chunk); - }; - - /** - * Deflate#onEnd(status) -> Void - * - status (Number): deflate status. 0 (Z_OK) on success, - * other if not. - * - * Called once after you tell deflate that the input stream is - * complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH) - * or if an error happened. By default - join collected chunks, - * free memory and fill `results` / `err` properties. - **/ - onEnd(status) { - // On success - join - if (status === Z_OK) { - this.result = flattenChunks(this.chunks); - } - this.chunks = []; - this.err = status; - this.msg = this.strm.msg; - }; -} - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -// See state defs from inflate.js -const BAD = 30; /* got a data error -- remain here until reset */ -const TYPE = 12; /* i: waiting for type bits, including last-flag bit */ - -/* - Decode literal, length, and distance codes and write out the resulting - literal and match bytes until either not enough input or output is - available, an end-of-block is encountered, or a data error is encountered. - When large enough input and output buffers are supplied to inflate(), for - example, a 16K input buffer and a 64K output buffer, more than 95% of the - inflate execution time is spent in this routine. - - Entry assumptions: - - state.mode === LEN - strm.avail_in >= 6 - strm.avail_out >= 258 - start >= strm.avail_out - state.bits < 8 - - On return, state.mode is one of: - - LEN -- ran out of enough output space or enough available input - TYPE -- reached end of block code, inflate() to interpret next block - BAD -- error in block data - - Notes: - - - The maximum input bits used by a length/distance pair is 15 bits for the - length code, 5 bits for the length extra, 15 bits for the distance code, - and 13 bits for the distance extra. This totals 48 bits, or six bytes. - Therefore if strm.avail_in >= 6, then there is enough input to avoid - checking for available input while decoding. - - - The maximum bytes that a single length/distance pair can output is 258 - bytes, which is the maximum length that can be coded. inflate_fast() - requires strm.avail_out >= 258 for each loop to avoid checking for - output space. - */ -function inflate_fast(strm, start) { - let _in; /* local strm.input */ - let _out; /* local strm.output */ - // Use `s_window` instead `window`, avoid conflict with instrumentation tools - let hold; /* local strm.hold */ - let bits; /* local strm.bits */ - let here; /* retrieved table entry */ - let op; /* code bits, operation, extra bits, or */ - /* window position, window bytes to copy */ - let len; /* match length, unused bytes */ - let dist; /* match distance */ - let from; /* where to copy match from */ - let from_source; - - - - /* copy state to local variables */ - const state = strm.state; - //here = state.here; - _in = strm.next_in; - const input = strm.input; - const last = _in + (strm.avail_in - 5); - _out = strm.next_out; - const output = strm.output; - const beg = _out - (start - strm.avail_out); - const end = _out + (strm.avail_out - 257); - //#ifdef INFLATE_STRICT - const dmax = state.dmax; - //#endif - const wsize = state.wsize; - const whave = state.whave; - const wnext = state.wnext; - const s_window = state.window; - hold = state.hold; - bits = state.bits; - const lcode = state.lencode; - const dcode = state.distcode; - const lmask = (1 << state.lenbits) - 1; - const dmask = (1 << state.distbits) - 1; - - - /* decode literals and length/distances until end-of-block or not enough - input data or output space */ - - top: - do { - if (bits < 15) { - hold += input[_in++] << bits; - bits += 8; - hold += input[_in++] << bits; - bits += 8; - } - - here = lcode[hold & lmask]; - - dolen: - for (;;) { // Goto emulation - op = here >>> 24/*here.bits*/; - hold >>>= op; - bits -= op; - op = here >>> 16 & 0xff/*here.op*/; - if (op === 0) { /* literal */ - //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - // "inflate: literal '%c'\n" : - // "inflate: literal 0x%02x\n", here.val)); - output[_out++] = here & 0xffff/*here.val*/; - } else if (op & 16) { /* length base */ - len = here & 0xffff/*here.val*/; - op &= 15; /* number of extra bits */ - if (op) { - if (bits < op) { - hold += input[_in++] << bits; - bits += 8; - } - len += hold & (1 << op) - 1; - hold >>>= op; - bits -= op; - } - //Tracevv((stderr, "inflate: length %u\n", len)); - if (bits < 15) { - hold += input[_in++] << bits; - bits += 8; - hold += input[_in++] << bits; - bits += 8; - } - here = dcode[hold & dmask]; - - dodist: - for (;;) { // goto emulation - op = here >>> 24/*here.bits*/; - hold >>>= op; - bits -= op; - op = here >>> 16 & 0xff/*here.op*/; - - if (op & 16) { /* distance base */ - dist = here & 0xffff/*here.val*/; - op &= 15; /* number of extra bits */ - if (bits < op) { - hold += input[_in++] << bits; - bits += 8; - if (bits < op) { - hold += input[_in++] << bits; - bits += 8; - } - } - dist += hold & (1 << op) - 1; - //#ifdef INFLATE_STRICT - if (dist > dmax) { - strm.msg = "invalid distance too far back"; - state.mode = BAD; - break top; - } - //#endif - hold >>>= op; - bits -= op; - //Tracevv((stderr, "inflate: distance %u\n", dist)); - op = _out - beg; /* max distance in output */ - if (dist > op) { /* see if copy from window */ - op = dist - op; /* distance back in window */ - if (op > whave) { - if (state.sane) { - strm.msg = "invalid distance too far back"; - state.mode = BAD; - break top; - } - - // (!) This block is disabled in zlib defaults, - // don't enable it for binary compatibility - //#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR - // if (len <= op - whave) { - // do { - // output[_out++] = 0; - // } while (--len); - // continue top; - // } - // len -= op - whave; - // do { - // output[_out++] = 0; - // } while (--op > whave); - // if (op === 0) { - // from = _out - dist; - // do { - // output[_out++] = output[from++]; - // } while (--len); - // continue top; - // } - //#endif - } - from = 0; // window index - from_source = s_window; - if (wnext === 0) { /* very common case */ - from += wsize - op; - if (op < len) { /* some from window */ - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = _out - dist; /* rest from output */ - from_source = output; - } - } else if (wnext < op) { /* wrap around window */ - from += wsize + wnext - op; - op -= wnext; - if (op < len) { /* some from end of window */ - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = 0; - if (wnext < len) { /* some from start of window */ - op = wnext; - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = _out - dist; /* rest from output */ - from_source = output; - } - } - } else { /* contiguous in window */ - from += wnext - op; - if (op < len) { /* some from window */ - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = _out - dist; /* rest from output */ - from_source = output; - } - } - while (len > 2) { - output[_out++] = from_source[from++]; - output[_out++] = from_source[from++]; - output[_out++] = from_source[from++]; - len -= 3; - } - if (len) { - output[_out++] = from_source[from++]; - if (len > 1) { - output[_out++] = from_source[from++]; - } - } - } else { - from = _out - dist; /* copy direct from output */ - do { /* minimum length is three */ - output[_out++] = output[from++]; - output[_out++] = output[from++]; - output[_out++] = output[from++]; - len -= 3; - } while (len > 2); - if (len) { - output[_out++] = output[from++]; - if (len > 1) { - output[_out++] = output[from++]; - } - } - } - } else if ((op & 64) === 0) { /* 2nd level distance code */ - here = dcode[(here & 0xffff)/*here.val*/ + (hold & (1 << op) - 1)]; - continue dodist; - } else { - strm.msg = "invalid distance code"; - state.mode = BAD; - break top; - } - - break; // need to emulate goto via "continue" - } - } else if ((op & 64) === 0) { /* 2nd level length code */ - here = lcode[(here & 0xffff)/*here.val*/ + (hold & (1 << op) - 1)]; - continue dolen; - } else if (op & 32) { /* end-of-block */ - //Tracevv((stderr, "inflate: end of block\n")); - state.mode = TYPE; - break top; - } else { - strm.msg = "invalid literal/length code"; - state.mode = BAD; - break top; - } - - break; // need to emulate goto via "continue" - } - } while (_in < last && _out < end); - - /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ - len = bits >> 3; - _in -= len; - bits -= len << 3; - hold &= (1 << bits) - 1; - - /* update state and return */ - strm.next_in = _in; - strm.next_out = _out; - strm.avail_in = _in < last ? 5 + (last - _in) : 5 - (_in - last); - strm.avail_out = _out < end ? 257 + (end - _out) : 257 - (_out - end); - state.hold = hold; - state.bits = bits; - return; -} - -const MAXBITS = 15; -const ENOUGH_LENS = 852; -const ENOUGH_DISTS = 592; -//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); - -const CODES = 0; -const LENS = 1; -const DISTS = 2; - -const lbase = [ /* Length codes 257..285 base */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 -]; - -const lext = [ /* Length codes 257..285 extra */ - 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78 -]; - -const dbase = [ /* Distance codes 0..29 base */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577, 0, 0 -]; - -const dext = [ /* Distance codes 0..29 extra */ - 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, - 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, - 28, 28, 29, 29, 64, 64 -]; - -function inflate_table(type, lens, lens_index, codes, table, table_index, work, opts) { - const bits = opts.bits; - //here = opts.here; /* table entry for duplication */ - - let len = 0; /* a code's length in bits */ - let sym = 0; /* index of code symbols */ - let min = 0, max = 0; /* minimum and maximum code lengths */ - let root = 0; /* number of index bits for root table */ - let curr = 0; /* number of index bits for current table */ - let drop = 0; /* code bits to drop for sub-table */ - let left = 0; /* number of prefix codes available */ - let used = 0; /* code entries in table used */ - let huff = 0; /* Huffman code */ - let incr; /* for incrementing code, index */ - let fill; /* index for replicating entries */ - let low; /* low bits for current root entry */ - let next; /* next available space in table */ - let base = null; /* base value table to use */ - let base_index = 0; - // var shoextra; /* extra bits table to use */ - let end; /* use base and extra for symbol > end */ - const count = new Buf16(MAXBITS + 1); //[MAXBITS+1]; /* number of codes of each length */ - const offs = new Buf16(MAXBITS + 1); //[MAXBITS+1]; /* offsets in table for each length */ - let extra = null; - let extra_index = 0; - - let here_bits, here_op, here_val; - - /* - Process a set of code lengths to create a canonical Huffman code. The - code lengths are lens[0..codes-1]. Each length corresponds to the - symbols 0..codes-1. The Huffman code is generated by first sorting the - symbols by length from short to long, and retaining the symbol order - for codes with equal lengths. Then the code starts with all zero bits - for the first code of the shortest length, and the codes are integer - increments for the same length, and zeros are appended as the length - increases. For the deflate format, these bits are stored backwards - from their more natural integer increment ordering, and so when the - decoding tables are built in the large loop below, the integer codes - are incremented backwards. - - This routine assumes, but does not check, that all of the entries in - lens[] are in the range 0..MAXBITS. The caller must assure this. - 1..MAXBITS is interpreted as that code length. zero means that that - symbol does not occur in this code. - - The codes are sorted by computing a count of codes for each length, - creating from that a table of starting indices for each length in the - sorted table, and then entering the symbols in order in the sorted - table. The sorted table is work[], with that space being provided by - the caller. - - The length counts are used for other purposes as well, i.e. finding - the minimum and maximum length codes, determining if there are any - codes at all, checking for a valid set of lengths, and looking ahead - at length counts to determine sub-table sizes when building the - decoding tables. - */ - - /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ - for (len = 0; len <= MAXBITS; len++) { - count[len] = 0; - } - for (sym = 0; sym < codes; sym++) { - count[lens[lens_index + sym]]++; - } - - /* bound code lengths, force root to be within code lengths */ - root = bits; - for (max = MAXBITS; max >= 1; max--) { - if (count[max] !== 0) { - break; - } - } - if (root > max) { - root = max; - } - if (max === 0) { /* no symbols to code at all */ - //table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */ - //table.bits[opts.table_index] = 1; //here.bits = (var char)1; - //table.val[opts.table_index++] = 0; //here.val = (var short)0; - table[table_index++] = 1 << 24 | 64 << 16 | 0; - - - //table.op[opts.table_index] = 64; - //table.bits[opts.table_index] = 1; - //table.val[opts.table_index++] = 0; - table[table_index++] = 1 << 24 | 64 << 16 | 0; - - opts.bits = 1; - return 0; /* no symbols, but wait for decoding to report error */ - } - for (min = 1; min < max; min++) { - if (count[min] !== 0) { - break; - } - } - if (root < min) { - root = min; - } - - /* check for an over-subscribed or incomplete set of lengths */ - left = 1; - for (len = 1; len <= MAXBITS; len++) { - left <<= 1; - left -= count[len]; - if (left < 0) { - return -1; - } /* over-subscribed */ - } - if (left > 0 && (type === CODES || max !== 1)) { - return -1; /* incomplete set */ - } - - /* generate offsets into symbol table for each length for sorting */ - offs[1] = 0; - for (len = 1; len < MAXBITS; len++) { - offs[len + 1] = offs[len] + count[len]; - } - - /* sort symbols by length, by symbol order within each length */ - for (sym = 0; sym < codes; sym++) { - if (lens[lens_index + sym] !== 0) { - work[offs[lens[lens_index + sym]]++] = sym; - } - } - - /* - Create and fill in decoding tables. In this loop, the table being - filled is at next and has curr index bits. The code being used is huff - with length len. That code is converted to an index by dropping drop - bits off of the bottom. For codes where len is less than drop + curr, - those top drop + curr - len bits are incremented through all values to - fill the table with replicated entries. - - root is the number of index bits for the root table. When len exceeds - root, sub-tables are created pointed to by the root entry with an index - of the low root bits of huff. This is saved in low to check for when a - new sub-table should be started. drop is zero when the root table is - being filled, and drop is root when sub-tables are being filled. - - When a new sub-table is needed, it is necessary to look ahead in the - code lengths to determine what size sub-table is needed. The length - counts are used for this, and so count[] is decremented as codes are - entered in the tables. - - used keeps track of how many table entries have been allocated from the - provided *table space. It is checked for LENS and DIST tables against - the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in - the initial root table size constants. See the comments in inftrees.h - for more information. - - sym increments through all symbols, and the loop terminates when - all codes of length max, i.e. all codes, have been processed. This - routine permits incomplete codes, so another loop after this one fills - in the rest of the decoding tables with invalid code markers. - */ - - /* set up for code type */ - // poor man optimization - use if-else instead of switch, - // to avoid deopts in old v8 - if (type === CODES) { - base = extra = work; /* dummy value--not used */ - end = 19; - - } else if (type === LENS) { - base = lbase; - base_index -= 257; - extra = lext; - extra_index -= 257; - end = 256; - - } else { /* DISTS */ - base = dbase; - extra = dext; - end = -1; - } - - /* initialize opts for loop */ - huff = 0; /* starting code */ - sym = 0; /* starting code symbol */ - len = min; /* starting code length */ - next = table_index; /* current table to fill in */ - curr = root; /* current table index bits */ - drop = 0; /* current bits to drop from code for index */ - low = -1; /* trigger new sub-table when len > root */ - used = 1 << root; /* use root table entries */ - const mask = used - 1; /* mask for comparing low */ - - /* check available table space */ - if (type === LENS && used > ENOUGH_LENS || - type === DISTS && used > ENOUGH_DISTS) { - return 1; - } - - /* process all codes and make table entries */ - for (;;) { - /* create table entry */ - here_bits = len - drop; - if (work[sym] < end) { - here_op = 0; - here_val = work[sym]; - } else if (work[sym] > end) { - here_op = extra[extra_index + work[sym]]; - here_val = base[base_index + work[sym]]; - } else { - here_op = 32 + 64; /* end of block */ - here_val = 0; - } - - /* replicate for those indices with low len bits equal to huff */ - incr = 1 << len - drop; - fill = 1 << curr; - min = fill; /* save offset to next table */ - do { - fill -= incr; - table[next + (huff >> drop) + fill] = here_bits << 24 | here_op << 16 | here_val |0; - } while (fill !== 0); - - /* backwards increment the len-bit code huff */ - incr = 1 << len - 1; - while (huff & incr) { - incr >>= 1; - } - if (incr !== 0) { - huff &= incr - 1; - huff += incr; - } else { - huff = 0; - } - - /* go to next symbol, update count, len */ - sym++; - if (--count[len] === 0) { - if (len === max) { - break; - } - len = lens[lens_index + work[sym]]; - } - - /* create new sub-table if needed */ - if (len > root && (huff & mask) !== low) { - /* if first time, transition to sub-tables */ - if (drop === 0) { - drop = root; - } - - /* increment past last table */ - next += min; /* here min is 1 << curr */ - - /* determine length of next table */ - curr = len - drop; - left = 1 << curr; - while (curr + drop < max) { - left -= count[curr + drop]; - if (left <= 0) { - break; - } - curr++; - left <<= 1; - } - - /* check for enough space */ - used += 1 << curr; - if (type === LENS && used > ENOUGH_LENS || - type === DISTS && used > ENOUGH_DISTS) { - return 1; - } - - /* point entry in root table to sub-table */ - low = huff & mask; - /*table.op[low] = curr; - table.bits[low] = root; - table.val[low] = next - opts.table_index;*/ - table[low] = root << 24 | curr << 16 | next - table_index |0; - } - } - - /* fill in remaining table entry if code is incomplete (guaranteed to have - at most one remaining entry, since if the code is incomplete, the - maximum code length that was allowed to get this far is one bit) */ - if (huff !== 0) { - //table.op[next + huff] = 64; /* invalid code marker */ - //table.bits[next + huff] = len - drop; - //table.val[next + huff] = 0; - table[next + huff] = len - drop << 24 | 64 << 16 |0; - } - - /* set return parameters */ - //opts.table_index += used; - opts.bits = root; - return 0; -} - -const CODES$1 = 0; -const LENS$1 = 1; -const DISTS$1 = 2; - -/* STATES ====================================================================*/ -/* ===========================================================================*/ - - -const HEAD = 1; /* i: waiting for magic header */ -const FLAGS = 2; /* i: waiting for method and flags (gzip) */ -const TIME = 3; /* i: waiting for modification time (gzip) */ -const OS = 4; /* i: waiting for extra flags and operating system (gzip) */ -const EXLEN = 5; /* i: waiting for extra length (gzip) */ -const EXTRA = 6; /* i: waiting for extra bytes (gzip) */ -const NAME = 7; /* i: waiting for end of file name (gzip) */ -const COMMENT = 8; /* i: waiting for end of comment (gzip) */ -const HCRC = 9; /* i: waiting for header crc (gzip) */ -const DICTID = 10; /* i: waiting for dictionary check value */ -const DICT = 11; /* waiting for inflateSetDictionary() call */ -const TYPE$1 = 12; /* i: waiting for type bits, including last-flag bit */ -const TYPEDO = 13; /* i: same, but skip check to exit inflate on new block */ -const STORED = 14; /* i: waiting for stored size (length and complement) */ -const COPY_ = 15; /* i/o: same as COPY below, but only first time in */ -const COPY = 16; /* i/o: waiting for input or output to copy stored block */ -const TABLE = 17; /* i: waiting for dynamic block table lengths */ -const LENLENS = 18; /* i: waiting for code length code lengths */ -const CODELENS = 19; /* i: waiting for length/lit and distance code lengths */ -const LEN_ = 20; /* i: same as LEN below, but only first time in */ -const LEN = 21; /* i: waiting for length/lit/eob code */ -const LENEXT = 22; /* i: waiting for length extra bits */ -const DIST = 23; /* i: waiting for distance code */ -const DISTEXT = 24; /* i: waiting for distance extra bits */ -const MATCH = 25; /* o: waiting for output space to copy string */ -const LIT = 26; /* o: waiting for output space to write literal */ -const CHECK = 27; /* i: waiting for 32-bit check value */ -const LENGTH = 28; /* i: waiting for 32-bit length (gzip) */ -const DONE = 29; /* finished check, done -- remain here until reset */ -const BAD$1 = 30; /* got a data error -- remain here until reset */ -//const MEM = 31; /* got an inflate() memory error -- remain here until reset */ -const SYNC = 32; /* looking for synchronization bytes to restart inflate() */ - -/* ===========================================================================*/ - - - -const ENOUGH_LENS$1 = 852; -const ENOUGH_DISTS$1 = 592; - - -function zswap32(q) { - return (((q >>> 24) & 0xff) + - ((q >>> 8) & 0xff00) + - ((q & 0xff00) << 8) + - ((q & 0xff) << 24)); -} - - -class InflateState { - constructor() { - this.mode = 0; /* current inflate mode */ - this.last = false; /* true if processing last block */ - this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ - this.havedict = false; /* true if dictionary provided */ - this.flags = 0; /* gzip header method and flags (0 if zlib) */ - this.dmax = 0; /* zlib header max distance (INFLATE_STRICT) */ - this.check = 0; /* protected copy of check value */ - this.total = 0; /* protected copy of output count */ - // TODO: may be {} - this.head = null; /* where to save gzip header information */ - - /* sliding window */ - this.wbits = 0; /* log base 2 of requested window size */ - this.wsize = 0; /* window size or zero if not using window */ - this.whave = 0; /* valid bytes in the window */ - this.wnext = 0; /* window write index */ - this.window = null; /* allocated sliding window, if needed */ - - /* bit accumulator */ - this.hold = 0; /* input bit accumulator */ - this.bits = 0; /* number of bits in "in" */ - - /* for string and stored block copying */ - this.length = 0; /* literal or length of data to copy */ - this.offset = 0; /* distance back to copy string from */ - - /* for table and code decoding */ - this.extra = 0; /* extra bits needed */ - - /* fixed and dynamic code tables */ - this.lencode = null; /* starting table for length/literal codes */ - this.distcode = null; /* starting table for distance codes */ - this.lenbits = 0; /* index bits for lencode */ - this.distbits = 0; /* index bits for distcode */ - - /* dynamic table building */ - this.ncode = 0; /* number of code length code lengths */ - this.nlen = 0; /* number of length code lengths */ - this.ndist = 0; /* number of distance code lengths */ - this.have = 0; /* number of code lengths in lens[] */ - this.next = null; /* next available space in codes[] */ - - this.lens = new Buf16(320); /* temporary storage for code lengths */ - this.work = new Buf16(288); /* work area for code table building */ - - /* - because we don't have pointers in js, we use lencode and distcode directly - as buffers so we don't need codes - */ - //this.codes = new utils.Buf32(ENOUGH); /* space for code tables */ - this.lendyn = null; /* dynamic table for length/literal codes (JS specific) */ - this.distdyn = null; /* dynamic table for distance codes (JS specific) */ - this.sane = 0; /* if false, allow invalid distance too far */ - this.back = 0; /* bits back of last unprocessed length/lit */ - this.was = 0; /* initial length of match */ - } -} - -function inflateResetKeep(strm) { - let state; - - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - strm.total_in = strm.total_out = state.total = 0; - strm.msg = ''; /*Z_NULL*/ - if (state.wrap) { /* to support ill-conceived Java test suite */ - strm.adler = state.wrap & 1; - } - state.mode = HEAD; - state.last = 0; - state.havedict = 0; - state.dmax = 32768; - state.head = null/*Z_NULL*/; - state.hold = 0; - state.bits = 0; - //state.lencode = state.distcode = state.next = state.codes; - state.lencode = state.lendyn = new Buf32(ENOUGH_LENS$1); - state.distcode = state.distdyn = new Buf32(ENOUGH_DISTS$1); - - state.sane = 1; - state.back = -1; - //Tracev((stderr, "inflate: reset\n")); - return Z_OK; -} - -function inflateReset(strm) { - let state; - - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - state.wsize = 0; - state.whave = 0; - state.wnext = 0; - return inflateResetKeep(strm); - -} - -function inflateReset2(strm, windowBits) { - let wrap; - let state; - - /* get the state */ - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - - /* extract wrap request from windowBits parameter */ - if (windowBits < 0) { - wrap = 0; - windowBits = -windowBits; - } - else { - wrap = (windowBits >> 4) + 1; - if (windowBits < 48) { - windowBits &= 15; - } - } - - /* set number of window bits, free window if different */ - if (windowBits && (windowBits < 8 || windowBits > 15)) { - return Z_STREAM_ERROR; - } - if (state.window !== null && state.wbits !== windowBits) { - state.window = null; - } - - /* update state and reset the rest of it */ - state.wrap = wrap; - state.wbits = windowBits; - return inflateReset(strm); -} - -function inflateInit2(strm, windowBits) { - let ret; - let state; - - if (!strm) { return Z_STREAM_ERROR; } - //strm.msg = Z_NULL; /* in case we return an error */ - - state = new InflateState(); - - //if (state === Z_NULL) return Z_MEM_ERROR; - //Tracev((stderr, "inflate: allocated\n")); - strm.state = state; - state.window = null/*Z_NULL*/; - ret = inflateReset2(strm, windowBits); - if (ret !== Z_OK) { - strm.state = null/*Z_NULL*/; - } - return ret; -} - - -/* - Return state with length and distance decoding tables and index sizes set to - fixed code decoding. Normally this returns fixed tables from inffixed.h. - If BUILDFIXED is defined, then instead this routine builds the tables the - first time it's called, and returns those tables the first time and - thereafter. This reduces the size of the code by about 2K bytes, in - exchange for a little execution time. However, BUILDFIXED should not be - used for threaded applications, since the rewriting of the tables and virgin - may not be thread-safe. - */ -let virgin = true; - -let lenfix, distfix; // We have no pointers in JS, so keep tables separate - -function fixedtables(state) { - /* build fixed huffman tables if first call (may not be thread safe) */ - if (virgin) { - let sym; - - lenfix = new Buf32(512); - distfix = new Buf32(32); - - /* literal/length table */ - sym = 0; - while (sym < 144) { state.lens[sym++] = 8; } - while (sym < 256) { state.lens[sym++] = 9; } - while (sym < 280) { state.lens[sym++] = 7; } - while (sym < 288) { state.lens[sym++] = 8; } - - inflate_table(LENS$1, state.lens, 0, 288, lenfix, 0, state.work, { bits: 9 }); - - /* distance table */ - sym = 0; - while (sym < 32) { state.lens[sym++] = 5; } - - inflate_table(DISTS$1, state.lens, 0, 32, distfix, 0, state.work, { bits: 5 }); - - /* do this just once */ - virgin = false; - } - - state.lencode = lenfix; - state.lenbits = 9; - state.distcode = distfix; - state.distbits = 5; -} - - -/* - Update the window with the last wsize (normally 32K) bytes written before - returning. If window does not exist yet, create it. This is only called - when a window is already in use, or when output has been written during this - inflate call, but the end of the deflate stream has not been reached yet. - It is also called to create a window for dictionary data when a dictionary - is loaded. - - Providing output buffers larger than 32K to inflate() should provide a speed - advantage, since only the last 32K of output is copied to the sliding window - upon return from inflate(), and since all distances after the first 32K of - output will fall in the output data, making match copies simpler and faster. - The advantage may be dependent on the size of the processor's data caches. - */ -function updatewindow(strm, src, end, copy) { - let dist; - const state = strm.state; - - /* if it hasn't been done already, allocate space for the window */ - if (state.window === null) { - state.wsize = 1 << state.wbits; - state.wnext = 0; - state.whave = 0; - - state.window = new Buf8(state.wsize); - } - - /* copy state->wsize or less output bytes into the circular window */ - if (copy >= state.wsize) { - arraySet(state.window, src, end - state.wsize, state.wsize, 0); - state.wnext = 0; - state.whave = state.wsize; - } - else { - dist = state.wsize - state.wnext; - if (dist > copy) { - dist = copy; - } - //zmemcpy(state->window + state->wnext, end - copy, dist); - arraySet(state.window, src, end - copy, dist, state.wnext); - copy -= dist; - if (copy) { - //zmemcpy(state->window, end - copy, copy); - arraySet(state.window, src, end - copy, copy, 0); - state.wnext = copy; - state.whave = state.wsize; - } - else { - state.wnext += dist; - if (state.wnext === state.wsize) { state.wnext = 0; } - if (state.whave < state.wsize) { state.whave += dist; } - } - } - return 0; -} - -function inflate(strm, flush) { - let state; - let input, output; // input/output buffers - let next; /* next input INDEX */ - let put; /* next output INDEX */ - let have, left; /* available input and output */ - let hold; /* bit buffer */ - let bits; /* bits in bit buffer */ - let _in, _out; /* save starting available input and output */ - let copy; /* number of stored or match bytes to copy */ - let from; /* where to copy match bytes from */ - let from_source; - let here = 0; /* current decoding table entry */ - let here_bits, here_op, here_val; // paked "here" denormalized (JS specific) - //var last; /* parent table entry */ - let last_bits, last_op, last_val; // paked "last" denormalized (JS specific) - let len; /* length to copy for repeats, bits to drop */ - let ret; /* return code */ - let hbuf = new Buf8(4); /* buffer for gzip header crc calculation */ - let opts; - - let n; // temporary var for NEED_BITS - - const order = /* permutation of code lengths */ - [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ]; - - - if (!strm || !strm.state || !strm.output || - (!strm.input && strm.avail_in !== 0)) { - return Z_STREAM_ERROR; - } - - state = strm.state; - if (state.mode === TYPE$1) { state.mode = TYPEDO; } /* skip check */ - - - //--- LOAD() --- - put = strm.next_out; - output = strm.output; - left = strm.avail_out; - next = strm.next_in; - input = strm.input; - have = strm.avail_in; - hold = state.hold; - bits = state.bits; - //--- - - _in = have; - _out = left; - ret = Z_OK; - - inf_leave: // goto emulation - for (;;) { - switch (state.mode) { - case HEAD: - if (state.wrap === 0) { - state.mode = TYPEDO; - break; - } - //=== NEEDBITS(16); - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if ((state.wrap & 2) && hold === 0x8b1f) { /* gzip header */ - state.check = 0/*crc32(0L, Z_NULL, 0)*/; - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = FLAGS; - break; - } - state.flags = 0; /* expect zlib header */ - if (state.head) { - state.head.done = false; - } - if (!(state.wrap & 1) || /* check if zlib header allowed */ - (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) { - strm.msg = 'incorrect header check'; - state.mode = BAD$1; - break; - } - if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) { - strm.msg = 'unknown compression method'; - state.mode = BAD$1; - break; - } - //--- DROPBITS(4) ---// - hold >>>= 4; - bits -= 4; - //---// - len = (hold & 0x0f)/*BITS(4)*/ + 8; - if (state.wbits === 0) { - state.wbits = len; - } - else if (len > state.wbits) { - strm.msg = 'invalid window size'; - state.mode = BAD$1; - break; - } - state.dmax = 1 << len; - //Tracev((stderr, "inflate: zlib header ok\n")); - strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; - state.mode = hold & 0x200 ? DICTID : TYPE$1; - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - break; - case FLAGS: - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.flags = hold; - if ((state.flags & 0xff) !== Z_DEFLATED) { - strm.msg = 'unknown compression method'; - state.mode = BAD$1; - break; - } - if (state.flags & 0xe000) { - strm.msg = 'unknown header flags set'; - state.mode = BAD$1; - break; - } - if (state.head) { - state.head.text = ((hold >> 8) & 1); - } - if (state.flags & 0x0200) { - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = TIME; - /* falls through */ - case TIME: - //=== NEEDBITS(32); */ - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (state.head) { - state.head.time = hold; - } - if (state.flags & 0x0200) { - //=== CRC4(state.check, hold) - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - hbuf[2] = (hold >>> 16) & 0xff; - hbuf[3] = (hold >>> 24) & 0xff; - state.check = crc32(state.check, hbuf, 4, 0); - //=== - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = OS; - /* falls through */ - case OS: - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (state.head) { - state.head.xflags = (hold & 0xff); - state.head.os = (hold >> 8); - } - if (state.flags & 0x0200) { - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = EXLEN; - /* falls through */ - case EXLEN: - if (state.flags & 0x0400) { - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.length = hold; - if (state.head) { - state.head.extra_len = hold; - } - if (state.flags & 0x0200) { - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - } - else if (state.head) { - state.head.extra = null/*Z_NULL*/; - } - state.mode = EXTRA; - /* falls through */ - case EXTRA: - if (state.flags & 0x0400) { - copy = state.length; - if (copy > have) { copy = have; } - if (copy) { - if (state.head) { - len = state.head.extra_len - state.length; - if (!state.head.extra) { - // Use untyped array for more convenient processing later - state.head.extra = new Array(state.head.extra_len); - } - arraySet( - state.head.extra, - input, - next, - // extra field is limited to 65536 bytes - // - no need for additional size check - copy, - /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/ - len - ); - //zmemcpy(state.head.extra + len, next, - // len + copy > state.head.extra_max ? - // state.head.extra_max - len : copy); - } - if (state.flags & 0x0200) { - state.check = crc32(state.check, input, copy, next); - } - have -= copy; - next += copy; - state.length -= copy; - } - if (state.length) { break inf_leave; } - } - state.length = 0; - state.mode = NAME; - /* falls through */ - case NAME: - if (state.flags & 0x0800) { - if (have === 0) { break inf_leave; } - copy = 0; - do { - // TODO: 2 or 1 bytes? - len = input[next + copy++]; - /* use constant limit because in js we should not preallocate memory */ - if (state.head && len && - (state.length < 65536 /*state.head.name_max*/)) { - state.head.name += String.fromCharCode(len); - } - } while (len && copy < have); - - if (state.flags & 0x0200) { - state.check = crc32(state.check, input, copy, next); - } - have -= copy; - next += copy; - if (len) { break inf_leave; } - } - else if (state.head) { - state.head.name = null; - } - state.length = 0; - state.mode = COMMENT; - /* falls through */ - case COMMENT: - if (state.flags & 0x1000) { - if (have === 0) { break inf_leave; } - copy = 0; - do { - len = input[next + copy++]; - /* use constant limit because in js we should not preallocate memory */ - if (state.head && len && - (state.length < 65536 /*state.head.comm_max*/)) { - state.head.comment += String.fromCharCode(len); - } - } while (len && copy < have); - if (state.flags & 0x0200) { - state.check = crc32(state.check, input, copy, next); - } - have -= copy; - next += copy; - if (len) { break inf_leave; } - } - else if (state.head) { - state.head.comment = null; - } - state.mode = HCRC; - /* falls through */ - case HCRC: - if (state.flags & 0x0200) { - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (hold !== (state.check & 0xffff)) { - strm.msg = 'header crc mismatch'; - state.mode = BAD$1; - break; - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - } - if (state.head) { - state.head.hcrc = ((state.flags >> 9) & 1); - state.head.done = true; - } - strm.adler = state.check = 0; - state.mode = TYPE$1; - break; - case DICTID: - //=== NEEDBITS(32); */ - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - strm.adler = state.check = zswap32(hold); - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = DICT; - /* falls through */ - case DICT: - if (state.havedict === 0) { - //--- RESTORE() --- - strm.next_out = put; - strm.avail_out = left; - strm.next_in = next; - strm.avail_in = have; - state.hold = hold; - state.bits = bits; - //--- - return Z_NEED_DICT; - } - strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; - state.mode = TYPE$1; - /* falls through */ - case TYPE$1: - if (flush === Z_BLOCK || flush === Z_TREES) { break inf_leave; } - /* falls through */ - case TYPEDO: - if (state.last) { - //--- BYTEBITS() ---// - hold >>>= bits & 7; - bits -= bits & 7; - //---// - state.mode = CHECK; - break; - } - //=== NEEDBITS(3); */ - while (bits < 3) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.last = (hold & 0x01)/*BITS(1)*/; - //--- DROPBITS(1) ---// - hold >>>= 1; - bits -= 1; - //---// - - switch ((hold & 0x03)/*BITS(2)*/) { - case 0: /* stored block */ - //Tracev((stderr, "inflate: stored block%s\n", - // state.last ? " (last)" : "")); - state.mode = STORED; - break; - case 1: /* fixed block */ - fixedtables(state); - //Tracev((stderr, "inflate: fixed codes block%s\n", - // state.last ? " (last)" : "")); - state.mode = LEN_; /* decode codes */ - if (flush === Z_TREES) { - //--- DROPBITS(2) ---// - hold >>>= 2; - bits -= 2; - //---// - break inf_leave; - } - break; - case 2: /* dynamic block */ - //Tracev((stderr, "inflate: dynamic codes block%s\n", - // state.last ? " (last)" : "")); - state.mode = TABLE; - break; - case 3: - strm.msg = 'invalid block type'; - state.mode = BAD$1; - } - //--- DROPBITS(2) ---// - hold >>>= 2; - bits -= 2; - //---// - break; - case STORED: - //--- BYTEBITS() ---// /* go to byte boundary */ - hold >>>= bits & 7; - bits -= bits & 7; - //---// - //=== NEEDBITS(32); */ - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) { - strm.msg = 'invalid stored block lengths'; - state.mode = BAD$1; - break; - } - state.length = hold & 0xffff; - //Tracev((stderr, "inflate: stored length %u\n", - // state.length)); - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = COPY_; - if (flush === Z_TREES) { break inf_leave; } - /* falls through */ - case COPY_: - state.mode = COPY; - /* falls through */ - case COPY: - copy = state.length; - if (copy) { - if (copy > have) { copy = have; } - if (copy > left) { copy = left; } - if (copy === 0) { break inf_leave; } - //--- zmemcpy(put, next, copy); --- - arraySet(output, input, next, copy, put); - //---// - have -= copy; - next += copy; - left -= copy; - put += copy; - state.length -= copy; - break; - } - //Tracev((stderr, "inflate: stored end\n")); - state.mode = TYPE$1; - break; - case TABLE: - //=== NEEDBITS(14); */ - while (bits < 14) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257; - //--- DROPBITS(5) ---// - hold >>>= 5; - bits -= 5; - //---// - state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1; - //--- DROPBITS(5) ---// - hold >>>= 5; - bits -= 5; - //---// - state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4; - //--- DROPBITS(4) ---// - hold >>>= 4; - bits -= 4; - //---// -//#ifndef PKZIP_BUG_WORKAROUND - if (state.nlen > 286 || state.ndist > 30) { - strm.msg = 'too many length or distance symbols'; - state.mode = BAD$1; - break; - } -//#endif - //Tracev((stderr, "inflate: table sizes ok\n")); - state.have = 0; - state.mode = LENLENS; - /* falls through */ - case LENLENS: - while (state.have < state.ncode) { - //=== NEEDBITS(3); - while (bits < 3) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.lens[order[state.have++]] = (hold & 0x07);//BITS(3); - //--- DROPBITS(3) ---// - hold >>>= 3; - bits -= 3; - //---// - } - while (state.have < 19) { - state.lens[order[state.have++]] = 0; - } - // We have separate tables & no pointers. 2 commented lines below not needed. - //state.next = state.codes; - //state.lencode = state.next; - // Switch to use dynamic table - state.lencode = state.lendyn; - state.lenbits = 7; - - opts = { bits: state.lenbits }; - ret = inflate_table(CODES$1, state.lens, 0, 19, state.lencode, 0, state.work, opts); - state.lenbits = opts.bits; - - if (ret) { - strm.msg = 'invalid code lengths set'; - state.mode = BAD$1; - break; - } - //Tracev((stderr, "inflate: code lengths ok\n")); - state.have = 0; - state.mode = CODELENS; - /* falls through */ - case CODELENS: - while (state.have < state.nlen + state.ndist) { - for (;;) { - here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/ - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - if (here_val < 16) { - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - state.lens[state.have++] = here_val; - } - else { - if (here_val === 16) { - //=== NEEDBITS(here.bits + 2); - n = here_bits + 2; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - if (state.have === 0) { - strm.msg = 'invalid bit length repeat'; - state.mode = BAD$1; - break; - } - len = state.lens[state.have - 1]; - copy = 3 + (hold & 0x03);//BITS(2); - //--- DROPBITS(2) ---// - hold >>>= 2; - bits -= 2; - //---// - } - else if (here_val === 17) { - //=== NEEDBITS(here.bits + 3); - n = here_bits + 3; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - len = 0; - copy = 3 + (hold & 0x07);//BITS(3); - //--- DROPBITS(3) ---// - hold >>>= 3; - bits -= 3; - //---// - } - else { - //=== NEEDBITS(here.bits + 7); - n = here_bits + 7; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - len = 0; - copy = 11 + (hold & 0x7f);//BITS(7); - //--- DROPBITS(7) ---// - hold >>>= 7; - bits -= 7; - //---// - } - if (state.have + copy > state.nlen + state.ndist) { - strm.msg = 'invalid bit length repeat'; - state.mode = BAD$1; - break; - } - while (copy--) { - state.lens[state.have++] = len; - } - } - } - - /* handle error breaks in while */ - if (state.mode === BAD$1) { break; } - - /* check for end-of-block code (better have one) */ - if (state.lens[256] === 0) { - strm.msg = 'invalid code -- missing end-of-block'; - state.mode = BAD$1; - break; - } - - /* build code tables -- note: do not change the lenbits or distbits - values here (9 and 6) without reading the comments in inftrees.h - concerning the ENOUGH constants, which depend on those values */ - state.lenbits = 9; - - opts = { bits: state.lenbits }; - ret = inflate_table(LENS$1, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts); - // We have separate tables & no pointers. 2 commented lines below not needed. - // state.next_index = opts.table_index; - state.lenbits = opts.bits; - // state.lencode = state.next; - - if (ret) { - strm.msg = 'invalid literal/lengths set'; - state.mode = BAD$1; - break; - } - - state.distbits = 6; - //state.distcode.copy(state.codes); - // Switch to use dynamic table - state.distcode = state.distdyn; - opts = { bits: state.distbits }; - ret = inflate_table(DISTS$1, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts); - // We have separate tables & no pointers. 2 commented lines below not needed. - // state.next_index = opts.table_index; - state.distbits = opts.bits; - // state.distcode = state.next; - - if (ret) { - strm.msg = 'invalid distances set'; - state.mode = BAD$1; - break; - } - //Tracev((stderr, 'inflate: codes ok\n')); - state.mode = LEN_; - if (flush === Z_TREES) { break inf_leave; } - /* falls through */ - case LEN_: - state.mode = LEN; - /* falls through */ - case LEN: - if (have >= 6 && left >= 258) { - //--- RESTORE() --- - strm.next_out = put; - strm.avail_out = left; - strm.next_in = next; - strm.avail_in = have; - state.hold = hold; - state.bits = bits; - //--- - inflate_fast(strm, _out); - //--- LOAD() --- - put = strm.next_out; - output = strm.output; - left = strm.avail_out; - next = strm.next_in; - input = strm.input; - have = strm.avail_in; - hold = state.hold; - bits = state.bits; - //--- - - if (state.mode === TYPE$1) { - state.back = -1; - } - break; - } - state.back = 0; - for (;;) { - here = state.lencode[hold & ((1 << state.lenbits) - 1)]; /*BITS(state.lenbits)*/ - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if (here_bits <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - if (here_op && (here_op & 0xf0) === 0) { - last_bits = here_bits; - last_op = here_op; - last_val = here_val; - for (;;) { - here = state.lencode[last_val + - ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((last_bits + here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - //--- DROPBITS(last.bits) ---// - hold >>>= last_bits; - bits -= last_bits; - //---// - state.back += last_bits; - } - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - state.back += here_bits; - state.length = here_val; - if (here_op === 0) { - //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - // "inflate: literal '%c'\n" : - // "inflate: literal 0x%02x\n", here.val)); - state.mode = LIT; - break; - } - if (here_op & 32) { - //Tracevv((stderr, "inflate: end of block\n")); - state.back = -1; - state.mode = TYPE$1; - break; - } - if (here_op & 64) { - strm.msg = 'invalid literal/length code'; - state.mode = BAD$1; - break; - } - state.extra = here_op & 15; - state.mode = LENEXT; - /* falls through */ - case LENEXT: - if (state.extra) { - //=== NEEDBITS(state.extra); - n = state.extra; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.length += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; - //--- DROPBITS(state.extra) ---// - hold >>>= state.extra; - bits -= state.extra; - //---// - state.back += state.extra; - } - //Tracevv((stderr, "inflate: length %u\n", state.length)); - state.was = state.length; - state.mode = DIST; - /* falls through */ - case DIST: - for (;;) { - here = state.distcode[hold & ((1 << state.distbits) - 1)];/*BITS(state.distbits)*/ - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - if ((here_op & 0xf0) === 0) { - last_bits = here_bits; - last_op = here_op; - last_val = here_val; - for (;;) { - here = state.distcode[last_val + - ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((last_bits + here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - //--- DROPBITS(last.bits) ---// - hold >>>= last_bits; - bits -= last_bits; - //---// - state.back += last_bits; - } - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - state.back += here_bits; - if (here_op & 64) { - strm.msg = 'invalid distance code'; - state.mode = BAD$1; - break; - } - state.offset = here_val; - state.extra = (here_op) & 15; - state.mode = DISTEXT; - /* falls through */ - case DISTEXT: - if (state.extra) { - //=== NEEDBITS(state.extra); - n = state.extra; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.offset += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; - //--- DROPBITS(state.extra) ---// - hold >>>= state.extra; - bits -= state.extra; - //---// - state.back += state.extra; - } -//#ifdef INFLATE_STRICT - if (state.offset > state.dmax) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD$1; - break; - } -//#endif - //Tracevv((stderr, "inflate: distance %u\n", state.offset)); - state.mode = MATCH; - /* falls through */ - case MATCH: - if (left === 0) { break inf_leave; } - copy = _out - left; - if (state.offset > copy) { /* copy from window */ - copy = state.offset - copy; - if (copy > state.whave) { - if (state.sane) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD$1; - break; - } -// (!) This block is disabled in zlib defaults, -// don't enable it for binary compatibility -//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR -// Trace((stderr, "inflate.c too far\n")); -// copy -= state.whave; -// if (copy > state.length) { copy = state.length; } -// if (copy > left) { copy = left; } -// left -= copy; -// state.length -= copy; -// do { -// output[put++] = 0; -// } while (--copy); -// if (state.length === 0) { state.mode = LEN; } -// break; -//#endif - } - if (copy > state.wnext) { - copy -= state.wnext; - from = state.wsize - copy; - } - else { - from = state.wnext - copy; - } - if (copy > state.length) { copy = state.length; } - from_source = state.window; - } - else { /* copy from output */ - from_source = output; - from = put - state.offset; - copy = state.length; - } - if (copy > left) { copy = left; } - left -= copy; - state.length -= copy; - do { - output[put++] = from_source[from++]; - } while (--copy); - if (state.length === 0) { state.mode = LEN; } - break; - case LIT: - if (left === 0) { break inf_leave; } - output[put++] = state.length; - left--; - state.mode = LEN; - break; - case CHECK: - if (state.wrap) { - //=== NEEDBITS(32); - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - // Use '|' instead of '+' to make sure that result is signed - hold |= input[next++] << bits; - bits += 8; - } - //===// - _out -= left; - strm.total_out += _out; - state.total += _out; - if (_out) { - strm.adler = state.check = - /*UPDATE(state.check, put - _out, _out);*/ - (state.flags ? crc32(state.check, output, _out, put - _out) : adler32(state.check, output, _out, put - _out)); - - } - _out = left; - // NB: crc32 stored as signed 32-bit int, zswap32 returns signed too - if ((state.flags ? hold : zswap32(hold)) !== state.check) { - strm.msg = 'incorrect data check'; - state.mode = BAD$1; - break; - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - //Tracev((stderr, "inflate: check matches trailer\n")); - } - state.mode = LENGTH; - /* falls through */ - case LENGTH: - if (state.wrap && state.flags) { - //=== NEEDBITS(32); - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (hold !== (state.total & 0xffffffff)) { - strm.msg = 'incorrect length check'; - state.mode = BAD$1; - break; - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - //Tracev((stderr, "inflate: length matches trailer\n")); - } - state.mode = DONE; - /* falls through */ - case DONE: - ret = Z_STREAM_END; - break inf_leave; - case BAD$1: - ret = Z_DATA_ERROR; - break inf_leave; - // case MEM: - // return Z_MEM_ERROR; - case SYNC: - /* falls through */ - default: - return Z_STREAM_ERROR; - } - } - - // inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave" - - /* - Return from inflate(), updating the total counts and the check value. - If there was no progress during the inflate() call, return a buffer - error. Call updatewindow() to create and/or update the window state. - Note: a memory error from inflate() is non-recoverable. - */ - - //--- RESTORE() --- - strm.next_out = put; - strm.avail_out = left; - strm.next_in = next; - strm.avail_in = have; - state.hold = hold; - state.bits = bits; - //--- - - if (state.wsize || (_out !== strm.avail_out && state.mode < BAD$1 && - (state.mode < CHECK || flush !== Z_FINISH))) { - if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) ; - } - _in -= strm.avail_in; - _out -= strm.avail_out; - strm.total_in += _in; - strm.total_out += _out; - state.total += _out; - if (state.wrap && _out) { - strm.adler = state.check = /*UPDATE(state.check, strm.next_out - _out, _out);*/ - (state.flags ? crc32(state.check, output, _out, strm.next_out - _out) : adler32(state.check, output, _out, strm.next_out - _out)); - } - strm.data_type = state.bits + (state.last ? 64 : 0) + - (state.mode === TYPE$1 ? 128 : 0) + - (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0); - if (((_in === 0 && _out === 0) || flush === Z_FINISH) && ret === Z_OK) { - ret = Z_BUF_ERROR; - } - return ret; -} - -function inflateEnd(strm) { - - if (!strm || !strm.state /*|| strm->zfree == (free_func)0*/) { - return Z_STREAM_ERROR; - } - - const state = strm.state; - if (state.window) { - state.window = null; - } - strm.state = null; - return Z_OK; -} - -function inflateGetHeader(strm, head) { - let state; - - /* check state */ - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR; } - - /* save header structure */ - state.head = head; - head.done = false; - return Z_OK; -} - -function inflateSetDictionary(strm, dictionary) { - const dictLength = dictionary.length; - - let state; - let dictid; - - /* check state */ - if (!strm /* == Z_NULL */ || !strm.state /* == Z_NULL */) { return Z_STREAM_ERROR; } - state = strm.state; - - if (state.wrap !== 0 && state.mode !== DICT) { - return Z_STREAM_ERROR; - } - - /* check for correct dictionary identifier */ - if (state.mode === DICT) { - dictid = 1; /* adler32(0, null, 0)*/ - /* dictid = adler32(dictid, dictionary, dictLength); */ - dictid = adler32(dictid, dictionary, dictLength, 0); - if (dictid !== state.check) { - return Z_DATA_ERROR; - } - } - /* copy dictionary to window using updatewindow(), which will amend the - existing dictionary if appropriate */ - updatewindow(strm, dictionary, dictLength, dictLength); - // if (ret) { - // state.mode = MEM; - // return Z_MEM_ERROR; - // } - state.havedict = 1; - // Tracev((stderr, "inflate: dictionary set\n")); - return Z_OK; -} - -/* Not implemented -exports.inflateCopy = inflateCopy; -exports.inflateGetDictionary = inflateGetDictionary; -exports.inflateMark = inflateMark; -exports.inflatePrime = inflatePrime; -exports.inflateSync = inflateSync; -exports.inflateSyncPoint = inflateSyncPoint; -exports.inflateUndermine = inflateUndermine; -*/ - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -class GZheader { - constructor() { - /* true if compressed data believed to be text */ - this.text = 0; - /* modification time */ - this.time = 0; - /* extra flags (not used when writing a gzip file) */ - this.xflags = 0; - /* operating system */ - this.os = 0; - /* pointer to extra field or Z_NULL if none */ - this.extra = null; - /* extra field length (valid if extra != Z_NULL) */ - this.extra_len = 0; // Actually, we don't need it in JS, - // but leave for few code modifications - - // - // Setup limits is not necessary because in js we should not preallocate memory - // for inflate use constant limit in 65536 bytes - // - - /* space at extra (only when reading header) */ - // this.extra_max = 0; - /* pointer to zero-terminated file name or Z_NULL */ - this.name = ''; - /* space at name (only when reading header) */ - // this.name_max = 0; - /* pointer to zero-terminated comment or Z_NULL */ - this.comment = ''; - /* space at comment (only when reading header) */ - // this.comm_max = 0; - /* true if there was or will be a header crc */ - this.hcrc = 0; - /* true when done reading gzip header (not used when writing a gzip file) */ - this.done = false; - } -} - -/** - * class Inflate - * - * Generic JS-style wrapper for zlib calls. If you don't need - * streaming behaviour - use more simple functions: [[inflate]] - * and [[inflateRaw]]. - **/ - -/* internal - * inflate.chunks -> Array - * - * Chunks of output data, if [[Inflate#onData]] not overridden. - **/ - -/** - * Inflate.result -> Uint8Array|Array|String - * - * Uncompressed result, generated by default [[Inflate#onData]] - * and [[Inflate#onEnd]] handlers. Filled after you push last chunk - * (call [[Inflate#push]] with `Z_FINISH` / `true` param) or if you - * push a chunk with explicit flush (call [[Inflate#push]] with - * `Z_SYNC_FLUSH` param). - **/ - -/** - * Inflate.err -> Number - * - * Error code after inflate finished. 0 (Z_OK) on success. - * Should be checked if broken data possible. - **/ - -/** - * Inflate.msg -> String - * - * Error message, if [[Inflate.err]] != 0 - **/ - - -/** - * new Inflate(options) - * - options (Object): zlib inflate options. - * - * Creates new inflator instance with specified params. Throws exception - * on bad params. Supported options: - * - * - `windowBits` - * - `dictionary` - * - * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) - * for more information on these. - * - * Additional options, for internal needs: - * - * - `chunkSize` - size of generated data chunks (16K by default) - * - `raw` (Boolean) - do raw inflate - * - `to` (String) - if equal to 'string', then result will be converted - * from utf8 to utf16 (javascript) string. When string output requested, - * chunk length can differ from `chunkSize`, depending on content. - * - * By default, when no options set, autodetect deflate/gzip data format via - * wrapper header. - * - * ##### Example: - * - * ```javascript - * var pako = require('pako') - * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9]) - * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]); - * - * var inflate = new pako.Inflate({ level: 3}); - * - * inflate.push(chunk1, false); - * inflate.push(chunk2, true); // true -> last chunk - * - * if (inflate.err) { throw new Error(inflate.err); } - * - * console.log(inflate.result); - * ``` - **/ -class Inflate { - constructor(options) { - this.options = { - chunkSize: 16384, - windowBits: 0, - ...(options || {}) - }; - - const opt = this.options; - - // Force window size for `raw` data, if not set directly, - // because we have no header for autodetect. - if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) { - opt.windowBits = -opt.windowBits; - if (opt.windowBits === 0) { opt.windowBits = -15; } - } - - // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate - if ((opt.windowBits >= 0) && (opt.windowBits < 16) && - !(options && options.windowBits)) { - opt.windowBits += 32; - } - - // Gzip header has no info about windows size, we can do autodetect only - // for deflate. So, if window size not set, force it to max when gzip possible - if ((opt.windowBits > 15) && (opt.windowBits < 48)) { - // bit 3 (16) -> gzipped data - // bit 4 (32) -> autodetect gzip/deflate - if ((opt.windowBits & 15) === 0) { - opt.windowBits |= 15; - } - } - - this.err = 0; // error code, if happens (0 = Z_OK) - this.msg = ''; // error message - this.ended = false; // used to avoid multiple onEnd() calls - this.chunks = []; // chunks of compressed data - - this.strm = new ZStream(); - this.strm.avail_out = 0; - - let status = inflateInit2( - this.strm, - opt.windowBits - ); - - if (status !== Z_OK) { - throw new Error(msg[status]); - } - - this.header = new GZheader(); - - inflateGetHeader(this.strm, this.header); - - // Setup dictionary - if (opt.dictionary) { - // Convert data if needed - if (typeof opt.dictionary === 'string') { - opt.dictionary = string2buf(opt.dictionary); - } else if (opt.dictionary instanceof ArrayBuffer) { - opt.dictionary = new Uint8Array(opt.dictionary); - } - if (opt.raw) { //In raw mode we need to set the dictionary early - status = inflateSetDictionary(this.strm, opt.dictionary); - if (status !== Z_OK) { - throw new Error(msg[status]); - } - } - } - } - /** - * Inflate#push(data[, mode]) -> Boolean - * - data (Uint8Array|Array|ArrayBuffer|String): input data - * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. - * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH. - * - * Sends input data to inflate pipe, generating [[Inflate#onData]] calls with - * new output chunks. Returns `true` on success. The last data block must have - * mode Z_FINISH (or `true`). That will flush internal pending buffers and call - * [[Inflate#onEnd]]. For interim explicit flushes (without ending the stream) you - * can use mode Z_SYNC_FLUSH, keeping the decompression context. - * - * On fail call [[Inflate#onEnd]] with error code and return false. - * - * We strongly recommend to use `Uint8Array` on input for best speed (output - * format is detected automatically). Also, don't skip last param and always - * use the same type in your code (boolean or number). That will improve JS speed. - * - * For regular `Array`-s make sure all elements are [0..255]. - * - * ##### Example - * - * ```javascript - * push(chunk, false); // push one of data chunks - * ... - * push(chunk, true); // push last chunk - * ``` - **/ - push(data, mode) { - const { strm, options: { chunkSize, dictionary } } = this; - let status, _mode; - - // Flag to properly process Z_BUF_ERROR on testing inflate call - // when we check that all output data was flushed. - let allowBufError = false; - - if (this.ended) { return false; } - _mode = (mode === ~~mode) ? mode : ((mode === true) ? Z_FINISH : Z_NO_FLUSH); - - // Convert data if needed - if (typeof data === 'string') { - // Only binary strings can be decompressed on practice - strm.input = binstring2buf(data); - } else if (data instanceof ArrayBuffer) { - strm.input = new Uint8Array(data); - } else { - strm.input = data; - } - - strm.next_in = 0; - strm.avail_in = strm.input.length; - - do { - if (strm.avail_out === 0) { - strm.output = new Buf8(chunkSize); - strm.next_out = 0; - strm.avail_out = chunkSize; - } - - status = inflate(strm, Z_NO_FLUSH); /* no bad return value */ - - if (status === Z_NEED_DICT && dictionary) { - status = inflateSetDictionary(this.strm, dictionary); - } - - if (status === Z_BUF_ERROR && allowBufError === true) { - status = Z_OK; - allowBufError = false; - } - - if (status !== Z_STREAM_END && status !== Z_OK) { - this.onEnd(status); - this.ended = true; - return false; - } - - if (strm.next_out) { - if (strm.avail_out === 0 || status === Z_STREAM_END || (strm.avail_in === 0 && (_mode === Z_FINISH || _mode === Z_SYNC_FLUSH))) { - this.onData(shrinkBuf(strm.output, strm.next_out)); - } - } - - // When no more input data, we should check that internal inflate buffers - // are flushed. The only way to do it when avail_out = 0 - run one more - // inflate pass. But if output data not exists, inflate return Z_BUF_ERROR. - // Here we set flag to process this error properly. - // - // NOTE. Deflate does not return error in this case and does not needs such - // logic. - if (strm.avail_in === 0 && strm.avail_out === 0) { - allowBufError = true; - } - - } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== Z_STREAM_END); - - if (status === Z_STREAM_END) { - _mode = Z_FINISH; - } - - // Finalize on the last chunk. - if (_mode === Z_FINISH) { - status = inflateEnd(this.strm); - this.onEnd(status); - this.ended = true; - return status === Z_OK; - } - - // callback interim results if Z_SYNC_FLUSH. - if (_mode === Z_SYNC_FLUSH) { - this.onEnd(Z_OK); - strm.avail_out = 0; - return true; - } - - return true; - }; - - /** - * Inflate#onData(chunk) -> Void - * - chunk (Uint8Array|Array|String): output data. Type of array depends - * on js engine support. When string output requested, each chunk - * will be string. - * - * By default, stores data blocks in `chunks[]` property and glue - * those in `onEnd`. Override this handler, if you need another behaviour. - **/ - onData(chunk) { - this.chunks.push(chunk); - }; - - - - /** - * Inflate#onEnd(status) -> Void - * - status (Number): inflate status. 0 (Z_OK) on success, - * other if not. - * - * Called either after you tell inflate that the input stream is - * complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH) - * or if an error happened. By default - join collected chunks, - * free memory and fill `results` / `err` properties. - **/ - onEnd(status) { - // On success - join - if (status === Z_OK) { - this.result = flattenChunks(this.chunks); - } - this.chunks = []; - this.err = status; - this.msg = this.strm.msg; - }; -} - -/* -node-bzip - a pure-javascript Node.JS module for decoding bzip2 data - -Copyright (C) 2012 Eli Skeggs - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, see -http://www.gnu.org/licenses/lgpl-2.1.html - -Adapted from bzip2.js, copyright 2011 antimatter15 (antimatter15@gmail.com). - -Based on micro-bunzip by Rob Landley (rob@landley.net). - -Based on bzip2 decompression code by Julian R Seward (jseward@acm.org), -which also acknowledges contributions by Mike Burrows, David Wheeler, -Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten, -Robert Sedgewick, and Jon L. Bentley. -*/ - -var BITMASK = [0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF]; - -// offset in bytes -var BitReader = function(stream) { - this.stream = stream; - this.bitOffset = 0; - this.curByte = 0; - this.hasByte = false; -}; - -BitReader.prototype._ensureByte = function() { - if (!this.hasByte) { - this.curByte = this.stream.readByte(); - this.hasByte = true; - } -}; - -// reads bits from the buffer -BitReader.prototype.read = function(bits) { - var result = 0; - while (bits > 0) { - this._ensureByte(); - var remaining = 8 - this.bitOffset; - // if we're in a byte - if (bits >= remaining) { - result <<= remaining; - result |= BITMASK[remaining] & this.curByte; - this.hasByte = false; - this.bitOffset = 0; - bits -= remaining; - } else { - result <<= bits; - var shift = remaining - bits; - result |= (this.curByte & (BITMASK[bits] << shift)) >> shift; - this.bitOffset += bits; - bits = 0; - } - } - return result; -}; - -// seek to an arbitrary point in the buffer (expressed in bits) -BitReader.prototype.seek = function(pos) { - var n_bit = pos % 8; - var n_byte = (pos - n_bit) / 8; - this.bitOffset = n_bit; - this.stream.seek(n_byte); - this.hasByte = false; -}; - -// reads 6 bytes worth of data using the read method -BitReader.prototype.pi = function() { - var buf = new Uint8Array(6), i; - for (i = 0; i < buf.length; i++) { - buf[i] = this.read(8); - } - return bufToHex(buf); -}; - -function bufToHex(buf) { - return Array.prototype.map.call(buf, x => ('00' + x.toString(16)).slice(-2)).join(''); -} - -var bitreader = BitReader; - -/* very simple input/output stream interface */ -var Stream = function() { -}; - -// input streams ////////////// -/** Returns the next byte, or -1 for EOF. */ -Stream.prototype.readByte = function() { - throw new Error("abstract method readByte() not implemented"); -}; -/** Attempts to fill the buffer; returns number of bytes read, or - * -1 for EOF. */ -Stream.prototype.read = function(buffer, bufOffset, length) { - var bytesRead = 0; - while (bytesRead < length) { - var c = this.readByte(); - if (c < 0) { // EOF - return (bytesRead===0) ? -1 : bytesRead; - } - buffer[bufOffset++] = c; - bytesRead++; - } - return bytesRead; -}; -Stream.prototype.seek = function(new_pos) { - throw new Error("abstract method seek() not implemented"); -}; - -// output streams /////////// -Stream.prototype.writeByte = function(_byte) { - throw new Error("abstract method readByte() not implemented"); -}; -Stream.prototype.write = function(buffer, bufOffset, length) { - var i; - for (i=0; i>> 0; // return an unsigned value - }; - - /** - * Update the CRC with a single byte - * @param value The value to update the CRC with - */ - this.updateCRC = function(value) { - crc = (crc << 8) ^ crc32Lookup[((crc >>> 24) ^ value) & 0xff]; - }; - - /** - * Update the CRC with a sequence of identical bytes - * @param value The value to update the CRC with - * @param count The number of bytes - */ - this.updateCRCRun = function(value, count) { - while (count-- > 0) { - crc = (crc << 8) ^ crc32Lookup[((crc >>> 24) ^ value) & 0xff]; - } - }; - }; - return CRC32; -})(); - -/* -seek-bzip - a pure-javascript module for seeking within bzip2 data - -Copyright (C) 2013 C. Scott Ananian -Copyright (C) 2012 Eli Skeggs -Copyright (C) 2011 Kevin Kwok - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, see -http://www.gnu.org/licenses/lgpl-2.1.html - -Adapted from node-bzip, copyright 2012 Eli Skeggs. -Adapted from bzip2.js, copyright 2011 Kevin Kwok (antimatter15@gmail.com). - -Based on micro-bunzip by Rob Landley (rob@landley.net). - -Based on bzip2 decompression code by Julian R Seward (jseward@acm.org), -which also acknowledges contributions by Mike Burrows, David Wheeler, -Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten, -Robert Sedgewick, and Jon L. Bentley. -*/ - - - - - -var MAX_HUFCODE_BITS = 20; -var MAX_SYMBOLS = 258; -var SYMBOL_RUNA = 0; -var SYMBOL_RUNB = 1; -var MIN_GROUPS = 2; -var MAX_GROUPS = 6; -var GROUP_SIZE = 50; - -var WHOLEPI = "314159265359"; -var SQRTPI = "177245385090"; - -var mtf = function(array, index) { - var src = array[index], i; - for (i = index; i > 0; i--) { - array[i] = array[i-1]; - } - array[0] = src; - return src; -}; - -var Err = { - OK: 0, - LAST_BLOCK: -1, - NOT_BZIP_DATA: -2, - UNEXPECTED_INPUT_EOF: -3, - UNEXPECTED_OUTPUT_EOF: -4, - DATA_ERROR: -5, - OUT_OF_MEMORY: -6, - OBSOLETE_INPUT: -7, - END_OF_BLOCK: -8 -}; -var ErrorMessages = {}; -ErrorMessages[Err.LAST_BLOCK] = "Bad file checksum"; -ErrorMessages[Err.NOT_BZIP_DATA] = "Not bzip data"; -ErrorMessages[Err.UNEXPECTED_INPUT_EOF] = "Unexpected input EOF"; -ErrorMessages[Err.UNEXPECTED_OUTPUT_EOF] = "Unexpected output EOF"; -ErrorMessages[Err.DATA_ERROR] = "Data error"; -ErrorMessages[Err.OUT_OF_MEMORY] = "Out of memory"; -ErrorMessages[Err.OBSOLETE_INPUT] = "Obsolete (pre 0.9.5) bzip format not supported."; - -var _throw = function(status, optDetail) { - var msg = ErrorMessages[status] || 'unknown error'; - if (optDetail) { msg += ': '+optDetail; } - var e = new TypeError(msg); - e.errorCode = status; - throw e; -}; - -var Bunzip = function(inputStream, outputStream) { - this.writePos = this.writeCurrent = this.writeCount = 0; - - this._start_bunzip(inputStream, outputStream); -}; -Bunzip.prototype._init_block = function() { - var moreBlocks = this._get_next_block(); - if ( !moreBlocks ) { - this.writeCount = -1; - return false; /* no more blocks */ - } - this.blockCRC = new crc32$1(); - return true; -}; -/* XXX micro-bunzip uses (inputStream, inputBuffer, len) as arguments */ -Bunzip.prototype._start_bunzip = function(inputStream, outputStream) { - /* Ensure that file starts with "BZh['1'-'9']." */ - var buf = new Uint8Array(4); - if (inputStream.read(buf, 0, 4) !== 4 || - String.fromCharCode(buf[0], buf[1], buf[2]) !== 'BZh') - _throw(Err.NOT_BZIP_DATA, 'bad magic'); - - var level = buf[3] - 0x30; - if (level < 1 || level > 9) - _throw(Err.NOT_BZIP_DATA, 'level out of range'); - - this.reader = new bitreader(inputStream); - - /* Fourth byte (ascii '1'-'9'), indicates block size in units of 100k of - uncompressed data. Allocate intermediate buffer for block. */ - this.dbufSize = 100000 * level; - this.nextoutput = 0; - this.outputStream = outputStream; - this.streamCRC = 0; -}; -Bunzip.prototype._get_next_block = function() { - var i, j, k; - var reader = this.reader; - // this is get_next_block() function from micro-bunzip: - /* Read in header signature and CRC, then validate signature. - (last block signature means CRC is for whole file, return now) */ - var h = reader.pi(); - if (h === SQRTPI) { // last block - return false; /* no more blocks */ - } - if (h !== WHOLEPI) - _throw(Err.NOT_BZIP_DATA); - this.targetBlockCRC = reader.read(32) >>> 0; // (convert to unsigned) - this.streamCRC = (this.targetBlockCRC ^ - ((this.streamCRC << 1) | (this.streamCRC>>>31))) >>> 0; - /* We can add support for blockRandomised if anybody complains. There was - some code for this in busybox 1.0.0-pre3, but nobody ever noticed that - it didn't actually work. */ - if (reader.read(1)) - _throw(Err.OBSOLETE_INPUT); - var origPointer = reader.read(24); - if (origPointer > this.dbufSize) - _throw(Err.DATA_ERROR, 'initial position out of bounds'); - /* mapping table: if some byte values are never used (encoding things - like ascii text), the compression code removes the gaps to have fewer - symbols to deal with, and writes a sparse bitfield indicating which - values were present. We make a translation table to convert the symbols - back to the corresponding bytes. */ - var t = reader.read(16); - var symToByte = new Uint8Array(256), symTotal = 0; - for (i = 0; i < 16; i++) { - if (t & (1 << (0xF - i))) { - var o = i * 16; - k = reader.read(16); - for (j = 0; j < 16; j++) - if (k & (1 << (0xF - j))) - symToByte[symTotal++] = o + j; - } - } - - /* How many different huffman coding groups does this block use? */ - var groupCount = reader.read(3); - if (groupCount < MIN_GROUPS || groupCount > MAX_GROUPS) - _throw(Err.DATA_ERROR); - /* nSelectors: Every GROUP_SIZE many symbols we select a new huffman coding - group. Read in the group selector list, which is stored as MTF encoded - bit runs. (MTF=Move To Front, as each value is used it's moved to the - start of the list.) */ - var nSelectors = reader.read(15); - if (nSelectors === 0) - _throw(Err.DATA_ERROR); - - var mtfSymbol = new Uint8Array(256); - for (i = 0; i < groupCount; i++) - mtfSymbol[i] = i; - - var selectors = new Uint8Array(nSelectors); // was 32768... - - for (i = 0; i < nSelectors; i++) { - /* Get next value */ - for (j = 0; reader.read(1); j++) - if (j >= groupCount) _throw(Err.DATA_ERROR); - /* Decode MTF to get the next selector */ - selectors[i] = mtf(mtfSymbol, j); - } - - /* Read the huffman coding tables for each group, which code for symTotal - literal symbols, plus two run symbols (RUNA, RUNB) */ - var symCount = symTotal + 2; - var groups = [], hufGroup; - for (j = 0; j < groupCount; j++) { - var length = new Uint8Array(symCount), temp = new Uint16Array(MAX_HUFCODE_BITS + 1); - /* Read huffman code lengths for each symbol. They're stored in - a way similar to mtf; record a starting value for the first symbol, - and an offset from the previous value for everys symbol after that. */ - t = reader.read(5); // lengths - for (i = 0; i < symCount; i++) { - for (;;) { - if (t < 1 || t > MAX_HUFCODE_BITS) _throw(Err.DATA_ERROR); - /* If first bit is 0, stop. Else second bit indicates whether - to increment or decrement the value. */ - if(!reader.read(1)) - break; - if(!reader.read(1)) - t++; - else - t--; - } - length[i] = t; - } - - /* Find largest and smallest lengths in this group */ - var minLen, maxLen; - minLen = maxLen = length[0]; - for (i = 1; i < symCount; i++) { - if (length[i] > maxLen) - maxLen = length[i]; - else if (length[i] < minLen) - minLen = length[i]; - } - - /* Calculate permute[], base[], and limit[] tables from length[]. - * - * permute[] is the lookup table for converting huffman coded symbols - * into decoded symbols. base[] is the amount to subtract from the - * value of a huffman symbol of a given length when using permute[]. - * - * limit[] indicates the largest numerical value a symbol with a given - * number of bits can have. This is how the huffman codes can vary in - * length: each code with a value>limit[length] needs another bit. - */ - hufGroup = {}; - groups.push(hufGroup); - hufGroup.permute = new Uint16Array(MAX_SYMBOLS); - hufGroup.limit = new Uint32Array(MAX_HUFCODE_BITS + 2); - hufGroup.base = new Uint32Array(MAX_HUFCODE_BITS + 1); - hufGroup.minLen = minLen; - hufGroup.maxLen = maxLen; - /* Calculate permute[]. Concurently, initialize temp[] and limit[]. */ - var pp = 0; - for (i = minLen; i <= maxLen; i++) { - temp[i] = hufGroup.limit[i] = 0; - for (t = 0; t < symCount; t++) - if (length[t] === i) - hufGroup.permute[pp++] = t; - } - /* Count symbols coded for at each bit length */ - for (i = 0; i < symCount; i++) - temp[length[i]]++; - /* Calculate limit[] (the largest symbol-coding value at each bit - * length, which is (previous limit<<1)+symbols at this level), and - * base[] (number of symbols to ignore at each bit length, which is - * limit minus the cumulative count of symbols coded for already). */ - pp = t = 0; - for (i = minLen; i < maxLen; i++) { - pp += temp[i]; - /* We read the largest possible symbol size and then unget bits - after determining how many we need, and those extra bits could - be set to anything. (They're noise from future symbols.) At - each level we're really only interested in the first few bits, - so here we set all the trailing to-be-ignored bits to 1 so they - don't affect the value>limit[length] comparison. */ - hufGroup.limit[i] = pp - 1; - pp <<= 1; - t += temp[i]; - hufGroup.base[i + 1] = pp - t; - } - hufGroup.limit[maxLen + 1] = Number.MAX_VALUE; /* Sentinal value for reading next sym. */ - hufGroup.limit[maxLen] = pp + temp[maxLen] - 1; - hufGroup.base[minLen] = 0; - } - /* We've finished reading and digesting the block header. Now read this - block's huffman coded symbols from the file and undo the huffman coding - and run length encoding, saving the result into dbuf[dbufCount++]=uc */ - - /* Initialize symbol occurrence counters and symbol Move To Front table */ - var byteCount = new Uint32Array(256); - for (i = 0; i < 256; i++) - mtfSymbol[i] = i; - /* Loop through compressed symbols. */ - var runPos = 0, dbufCount = 0, selector = 0, uc; - var dbuf = this.dbuf = new Uint32Array(this.dbufSize); - symCount = 0; - for (;;) { - /* Determine which huffman coding group to use. */ - if (!(symCount--)) { - symCount = GROUP_SIZE - 1; - if (selector >= nSelectors) { _throw(Err.DATA_ERROR); } - hufGroup = groups[selectors[selector++]]; - } - /* Read next huffman-coded symbol. */ - i = hufGroup.minLen; - j = reader.read(i); - for (;;i++) { - if (i > hufGroup.maxLen) { _throw(Err.DATA_ERROR); } - if (j <= hufGroup.limit[i]) - break; - j = (j << 1) | reader.read(1); - } - /* Huffman decode value to get nextSym (with bounds checking) */ - j -= hufGroup.base[i]; - if (j < 0 || j >= MAX_SYMBOLS) { _throw(Err.DATA_ERROR); } - var nextSym = hufGroup.permute[j]; - /* We have now decoded the symbol, which indicates either a new literal - byte, or a repeated run of the most recent literal byte. First, - check if nextSym indicates a repeated run, and if so loop collecting - how many times to repeat the last literal. */ - if (nextSym === SYMBOL_RUNA || nextSym === SYMBOL_RUNB) { - /* If this is the start of a new run, zero out counter */ - if (!runPos){ - runPos = 1; - t = 0; - } - /* Neat trick that saves 1 symbol: instead of or-ing 0 or 1 at - each bit position, add 1 or 2 instead. For example, - 1011 is 1<<0 + 1<<1 + 2<<2. 1010 is 2<<0 + 2<<1 + 1<<2. - You can make any bit pattern that way using 1 less symbol than - the basic or 0/1 method (except all bits 0, which would use no - symbols, but a run of length 0 doesn't mean anything in this - context). Thus space is saved. */ - if (nextSym === SYMBOL_RUNA) - t += runPos; - else - t += 2 * runPos; - runPos <<= 1; - continue; - } - /* When we hit the first non-run symbol after a run, we now know - how many times to repeat the last literal, so append that many - copies to our buffer of decoded symbols (dbuf) now. (The last - literal used is the one at the head of the mtfSymbol array.) */ - if (runPos){ - runPos = 0; - if (dbufCount + t > this.dbufSize) { _throw(Err.DATA_ERROR); } - uc = symToByte[mtfSymbol[0]]; - byteCount[uc] += t; - while (t--) - dbuf[dbufCount++] = uc; - } - /* Is this the terminating symbol? */ - if (nextSym > symTotal) - break; - /* At this point, nextSym indicates a new literal character. Subtract - one to get the position in the MTF array at which this literal is - currently to be found. (Note that the result can't be -1 or 0, - because 0 and 1 are RUNA and RUNB. But another instance of the - first symbol in the mtf array, position 0, would have been handled - as part of a run above. Therefore 1 unused mtf position minus - 2 non-literal nextSym values equals -1.) */ - if (dbufCount >= this.dbufSize) { _throw(Err.DATA_ERROR); } - i = nextSym - 1; - uc = mtf(mtfSymbol, i); - uc = symToByte[uc]; - /* We have our literal byte. Save it into dbuf. */ - byteCount[uc]++; - dbuf[dbufCount++] = uc; - } - /* At this point, we've read all the huffman-coded symbols (and repeated - runs) for this block from the input stream, and decoded them into the - intermediate buffer. There are dbufCount many decoded bytes in dbuf[]. - Now undo the Burrows-Wheeler transform on dbuf. - See http://dogma.net/markn/articles/bwt/bwt.htm - */ - if (origPointer < 0 || origPointer >= dbufCount) { _throw(Err.DATA_ERROR); } - /* Turn byteCount into cumulative occurrence counts of 0 to n-1. */ - j = 0; - for (i = 0; i < 256; i++) { - k = j + byteCount[i]; - byteCount[i] = j; - j = k; - } - /* Figure out what order dbuf would be in if we sorted it. */ - for (i = 0; i < dbufCount; i++) { - uc = dbuf[i] & 0xff; - dbuf[byteCount[uc]] |= (i << 8); - byteCount[uc]++; - } - /* Decode first byte by hand to initialize "previous" byte. Note that it - doesn't get output, and if the first three characters are identical - it doesn't qualify as a run (hence writeRunCountdown=5). */ - var pos = 0, current = 0, run = 0; - if (dbufCount) { - pos = dbuf[origPointer]; - current = (pos & 0xff); - pos >>= 8; - run = -1; - } - this.writePos = pos; - this.writeCurrent = current; - this.writeCount = dbufCount; - this.writeRun = run; - - return true; /* more blocks to come */ -}; -/* Undo burrows-wheeler transform on intermediate buffer to produce output. - If start_bunzip was initialized with out_fd=-1, then up to len bytes of - data are written to outbuf. Return value is number of bytes written or - error (all errors are negative numbers). If out_fd!=-1, outbuf and len - are ignored, data is written to out_fd and return is RETVAL_OK or error. -*/ -Bunzip.prototype._read_bunzip = function(outputBuffer, len) { - var copies, previous, outbyte; - /* james@jamestaylor.org: writeCount goes to -1 when the buffer is fully - decoded, which results in this returning RETVAL_LAST_BLOCK, also - equal to -1... Confusing, I'm returning 0 here to indicate no - bytes written into the buffer */ - if (this.writeCount < 0) { return 0; } - var dbuf = this.dbuf, pos = this.writePos, current = this.writeCurrent; - var dbufCount = this.writeCount; this.outputsize; - var run = this.writeRun; - - while (dbufCount) { - dbufCount--; - previous = current; - pos = dbuf[pos]; - current = pos & 0xff; - pos >>= 8; - if (run++ === 3){ - copies = current; - outbyte = previous; - current = -1; - } else { - copies = 1; - outbyte = current; - } - this.blockCRC.updateCRCRun(outbyte, copies); - while (copies--) { - this.outputStream.writeByte(outbyte); - this.nextoutput++; - } - if (current != previous) - run = 0; - } - this.writeCount = dbufCount; - // check CRC - if (this.blockCRC.getCRC() !== this.targetBlockCRC) { - _throw(Err.DATA_ERROR, "Bad block CRC "+ - "(got "+this.blockCRC.getCRC().toString(16)+ - " expected "+this.targetBlockCRC.toString(16)+")"); - } - return this.nextoutput; -}; - -var coerceInputStream = function(input) { - if ('readByte' in input) { return input; } - var inputStream = new stream(); - inputStream.pos = 0; - inputStream.readByte = function() { return input[this.pos++]; }; - inputStream.seek = function(pos) { this.pos = pos; }; - inputStream.eof = function() { return this.pos >= input.length; }; - return inputStream; -}; -var coerceOutputStream = function(output) { - var outputStream = new stream(); - var resizeOk = true; - if (output) { - if (typeof(output)==='number') { - outputStream.buffer = new Uint8Array(output); - resizeOk = false; - } else if ('writeByte' in output) { - return output; - } else { - outputStream.buffer = output; - resizeOk = false; - } - } else { - outputStream.buffer = new Uint8Array(16384); - } - outputStream.pos = 0; - outputStream.writeByte = function(_byte) { - if (resizeOk && this.pos >= this.buffer.length) { - var newBuffer = new Uint8Array(this.buffer.length*2); - newBuffer.set(this.buffer); - this.buffer = newBuffer; - } - this.buffer[this.pos++] = _byte; - }; - outputStream.getBuffer = function() { - // trim buffer - if (this.pos !== this.buffer.length) { - if (!resizeOk) - throw new TypeError('outputsize does not match decoded input'); - var newBuffer = new Uint8Array(this.pos); - newBuffer.set(this.buffer.subarray(0, this.pos)); - this.buffer = newBuffer; - } - return this.buffer; - }; - outputStream._coerced = true; - return outputStream; -}; - -/* Static helper functions */ -// 'input' can be a stream or a buffer -// 'output' can be a stream or a buffer or a number (buffer size) -const decode$2 = function(input, output, multistream) { - // make a stream from a buffer, if necessary - var inputStream = coerceInputStream(input); - var outputStream = coerceOutputStream(output); - - var bz = new Bunzip(inputStream, outputStream); - while (true) { - if ('eof' in inputStream && inputStream.eof()) break; - if (bz._init_block()) { - bz._read_bunzip(); - } else { - var targetStreamCRC = bz.reader.read(32) >>> 0; // (convert to unsigned) - if (targetStreamCRC !== bz.streamCRC) { - _throw(Err.DATA_ERROR, "Bad stream CRC "+ - "(got "+bz.streamCRC.toString(16)+ - " expected "+targetStreamCRC.toString(16)+")"); - } - if (multistream && - 'eof' in inputStream && - !inputStream.eof()) { - // note that start_bunzip will also resync the bit reader to next byte - bz._start_bunzip(inputStream, outputStream); - } else break; - } - } - if ('getBuffer' in outputStream) - return outputStream.getBuffer(); -}; -const decodeBlock = function(input, pos, output) { - // make a stream from a buffer, if necessary - var inputStream = coerceInputStream(input); - var outputStream = coerceOutputStream(output); - var bz = new Bunzip(inputStream, outputStream); - bz.reader.seek(pos); - /* Fill the decode buffer for the block */ - var moreBlocks = bz._get_next_block(); - if (moreBlocks) { - /* Init the CRC for writing */ - bz.blockCRC = new crc32$1(); - - /* Zero this so the current byte from before the seek is not written */ - bz.writeCopies = 0; - - /* Decompress the block and write to stdout */ - bz._read_bunzip(); - // XXX keep writing? - } - if ('getBuffer' in outputStream) - return outputStream.getBuffer(); -}; -/* Reads bzip2 file from stream or buffer `input`, and invoke - * `callback(position, size)` once for each bzip2 block, - * where position gives the starting position (in *bits*) - * and size gives uncompressed size of the block (in *bytes*). */ -const table = function(input, callback, multistream) { - // make a stream from a buffer, if necessary - var inputStream = new stream(); - inputStream.delegate = coerceInputStream(input); - inputStream.pos = 0; - inputStream.readByte = function() { - this.pos++; - return this.delegate.readByte(); - }; - if (inputStream.delegate.eof) { - inputStream.eof = inputStream.delegate.eof.bind(inputStream.delegate); - } - var outputStream = new stream(); - outputStream.pos = 0; - outputStream.writeByte = function() { this.pos++; }; - - var bz = new Bunzip(inputStream, outputStream); - var blockSize = bz.dbufSize; - while (true) { - if ('eof' in inputStream && inputStream.eof()) break; - - var position = inputStream.pos*8 + bz.reader.bitOffset; - if (bz.reader.hasByte) { position -= 8; } - - if (bz._init_block()) { - var start = outputStream.pos; - bz._read_bunzip(); - callback(position, outputStream.pos - start); - } else { - bz.reader.read(32); // (but we ignore the crc) - if (multistream && - 'eof' in inputStream && - !inputStream.eof()) { - // note that start_bunzip will also resync the bit reader to next byte - bz._start_bunzip(inputStream, outputStream); - console.assert(bz.dbufSize === blockSize, - "shouldn't change block size within multistream file"); - } else break; - } - } -}; - -var lib = { - Bunzip, - Stream: stream, - Err, - decode: decode$2, - decodeBlock, - table -}; -var lib_4 = lib.decode; - -// GPG4Browsers - An OpenPGP implementation in javascript - -/** - * Implementation of the Literal Data Packet (Tag 11) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.9|RFC4880 5.9}: - * A Literal Data packet contains the body of a message; data that is not to be - * further interpreted. - */ -class LiteralDataPacket { - static get tag() { - return enums.packet.literalData; - } - - /** - * @param {Date} date - The creation date of the literal package - */ - constructor(date = new Date()) { - this.format = enums.literal.utf8; // default format for literal data packets - this.date = util.normalizeDate(date); - this.text = null; // textual data representation - this.data = null; // literal data representation - this.filename = ''; - } - - /** - * Set the packet data to a javascript native string, end of line - * will be normalized to \r\n and by default text is converted to UTF8 - * @param {String | ReadableStream} text - Any native javascript string - * @param {enums.literal} [format] - The format of the string of bytes - */ - setText(text, format = enums.literal.utf8) { - this.format = format; - this.text = text; - this.data = null; - } - - /** - * Returns literal data packets as native JavaScript string - * with normalized end of line to \n - * @param {Boolean} [clone] - Whether to return a clone so that getBytes/getText can be called again - * @returns {String | ReadableStream} Literal data as text. - */ - getText(clone = false) { - if (this.text === null || util.isStream(this.text)) { // Assume that this.text has been read - this.text = util.decodeUTF8(util.nativeEOL(this.getBytes(clone))); - } - return this.text; - } - - /** - * Set the packet data to value represented by the provided string of bytes. - * @param {Uint8Array | ReadableStream} bytes - The string of bytes - * @param {enums.literal} format - The format of the string of bytes - */ - setBytes(bytes, format) { - this.format = format; - this.data = bytes; - this.text = null; - } - - - /** - * Get the byte sequence representing the literal packet data - * @param {Boolean} [clone] - Whether to return a clone so that getBytes/getText can be called again - * @returns {Uint8Array | ReadableStream} A sequence of bytes. - */ - getBytes(clone = false) { - if (this.data === null) { - // encode UTF8 and normalize EOL to \r\n - this.data = util.canonicalizeEOL(util.encodeUTF8(this.text)); - } - if (clone) { - return passiveClone(this.data); - } - return this.data; - } - - - /** - * Sets the filename of the literal packet data - * @param {String} filename - Any native javascript string - */ - setFilename(filename) { - this.filename = filename; - } - - - /** - * Get the filename of the literal packet data - * @returns {String} Filename. - */ - getFilename() { - return this.filename; - } - - /** - * Parsing function for a literal data packet (tag 11). - * - * @param {Uint8Array | ReadableStream} input - Payload of a tag 11 packet - * @returns {Promise} Object representation. - * @async - */ - async read(bytes) { - await parse(bytes, async reader => { - // - A one-octet field that describes how the data is formatted. - const format = await reader.readByte(); // enums.literal - - const filename_len = await reader.readByte(); - this.filename = util.decodeUTF8(await reader.readBytes(filename_len)); - - this.date = util.readDate(await reader.readBytes(4)); - - let data = reader.remainder(); - if (isArrayStream(data)) data = await readToEnd(data); - this.setBytes(data, format); - }); - } - - /** - * Creates a Uint8Array representation of the packet, excluding the data - * - * @returns {Uint8Array} Uint8Array representation of the packet. - */ - writeHeader() { - const filename = util.encodeUTF8(this.filename); - const filename_length = new Uint8Array([filename.length]); - - const format = new Uint8Array([this.format]); - const date = util.writeDate(this.date); - - return util.concatUint8Array([format, filename_length, filename, date]); - } - - /** - * Creates a Uint8Array representation of the packet - * - * @returns {Uint8Array | ReadableStream} Uint8Array representation of the packet. - */ - write() { - const header = this.writeHeader(); - const data = this.getBytes(); - - return util.concat([header, data]); - } -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -function readSimpleLength(bytes) { - let len = 0; - let offset; - const type = bytes[0]; - - - if (type < 192) { - [len] = bytes; - offset = 1; - } else if (type < 255) { - len = ((bytes[0] - 192) << 8) + (bytes[1]) + 192; - offset = 2; - } else if (type === 255) { - len = util.readNumber(bytes.subarray(1, 1 + 4)); - offset = 5; - } - - return { - len: len, - offset: offset - }; -} - -/** - * Encodes a given integer of length to the openpgp length specifier to a - * string - * - * @param {Integer} length - The length to encode - * @returns {Uint8Array} String with openpgp length representation. - */ -function writeSimpleLength(length) { - if (length < 192) { - return new Uint8Array([length]); - } else if (length > 191 && length < 8384) { - /* - * let a = (total data packet length) - 192 let bc = two octet - * representation of a let d = b + 192 - */ - return new Uint8Array([((length - 192) >> 8) + 192, (length - 192) & 0xFF]); - } - return util.concatUint8Array([new Uint8Array([255]), util.writeNumber(length, 4)]); -} - -function writePartialLength(power) { - if (power < 0 || power > 30) { - throw new Error('Partial Length power must be between 1 and 30'); - } - return new Uint8Array([224 + power]); -} - -function writeTag(tag_type) { - /* we're only generating v4 packet headers here */ - return new Uint8Array([0xC0 | tag_type]); -} - -/** - * Writes a packet header version 4 with the given tag_type and length to a - * string - * - * @param {Integer} tag_type - Tag type - * @param {Integer} length - Length of the payload - * @returns {String} String of the header. - */ -function writeHeader(tag_type, length) { - /* we're only generating v4 packet headers here */ - return util.concatUint8Array([writeTag(tag_type), writeSimpleLength(length)]); -} - -/** - * Whether the packet type supports partial lengths per RFC4880 - * @param {Integer} tag - Tag type - * @returns {Boolean} String of the header. - */ -function supportsStreaming(tag) { - return [ - enums.packet.literalData, - enums.packet.compressedData, - enums.packet.symmetricallyEncryptedData, - enums.packet.symEncryptedIntegrityProtectedData, - enums.packet.aeadEncryptedData - ].includes(tag); -} - -/** - * Generic static Packet Parser function - * - * @param {Uint8Array | ReadableStream} input - Input stream as string - * @param {Function} callback - Function to call with the parsed packet - * @returns {Boolean} Returns false if the stream was empty and parsing is done, and true otherwise. - */ -async function readPackets(input, callback) { - const reader = getReader(input); - let writer; - let callbackReturned; - try { - const peekedBytes = await reader.peekBytes(2); - // some sanity checks - if (!peekedBytes || peekedBytes.length < 2 || (peekedBytes[0] & 0x80) === 0) { - throw new Error('Error during parsing. This message / key probably does not conform to a valid OpenPGP format.'); - } - const headerByte = await reader.readByte(); - let tag = -1; - let format = -1; - let packetLength; - - format = 0; // 0 = old format; 1 = new format - if ((headerByte & 0x40) !== 0) { - format = 1; - } - - let packetLengthType; - if (format) { - // new format header - tag = headerByte & 0x3F; // bit 5-0 - } else { - // old format header - tag = (headerByte & 0x3F) >> 2; // bit 5-2 - packetLengthType = headerByte & 0x03; // bit 1-0 - } - - const packetSupportsStreaming = supportsStreaming(tag); - let packet = null; - if (packetSupportsStreaming) { - if (util.isStream(input) === 'array') { - const arrayStream = new ArrayStream(); - writer = getWriter(arrayStream); - packet = arrayStream; - } else { - const transform = new TransformStream(); - writer = getWriter(transform.writable); - packet = transform.readable; - } - callbackReturned = callback({ tag, packet }); - } else { - packet = []; - } - - let wasPartialLength; - do { - if (!format) { - // 4.2.1. Old Format Packet Lengths - switch (packetLengthType) { - case 0: - // The packet has a one-octet length. The header is 2 octets - // long. - packetLength = await reader.readByte(); - break; - case 1: - // The packet has a two-octet length. The header is 3 octets - // long. - packetLength = (await reader.readByte() << 8) | await reader.readByte(); - break; - case 2: - // The packet has a four-octet length. The header is 5 - // octets long. - packetLength = (await reader.readByte() << 24) | (await reader.readByte() << 16) | (await reader.readByte() << - 8) | await reader.readByte(); - break; - default: - // 3 - The packet is of indeterminate length. The header is 1 - // octet long, and the implementation must determine how long - // the packet is. If the packet is in a file, this means that - // the packet extends until the end of the file. In general, - // an implementation SHOULD NOT use indeterminate-length - // packets except where the end of the data will be clear - // from the context, and even then it is better to use a - // definite length, or a new format header. The new format - // headers described below have a mechanism for precisely - // encoding data of indeterminate length. - packetLength = Infinity; - break; - } - } else { // 4.2.2. New Format Packet Lengths - // 4.2.2.1. One-Octet Lengths - const lengthByte = await reader.readByte(); - wasPartialLength = false; - if (lengthByte < 192) { - packetLength = lengthByte; - // 4.2.2.2. Two-Octet Lengths - } else if (lengthByte >= 192 && lengthByte < 224) { - packetLength = ((lengthByte - 192) << 8) + (await reader.readByte()) + 192; - // 4.2.2.4. Partial Body Lengths - } else if (lengthByte > 223 && lengthByte < 255) { - packetLength = 1 << (lengthByte & 0x1F); - wasPartialLength = true; - if (!packetSupportsStreaming) { - throw new TypeError('This packet type does not support partial lengths.'); - } - // 4.2.2.3. Five-Octet Lengths - } else { - packetLength = (await reader.readByte() << 24) | (await reader.readByte() << 16) | (await reader.readByte() << - 8) | await reader.readByte(); - } - } - if (packetLength > 0) { - let bytesRead = 0; - while (true) { - if (writer) await writer.ready; - const { done, value } = await reader.read(); - if (done) { - if (packetLength === Infinity) break; - throw new Error('Unexpected end of packet'); - } - const chunk = packetLength === Infinity ? value : value.subarray(0, packetLength - bytesRead); - if (writer) await writer.write(chunk); - else packet.push(chunk); - bytesRead += value.length; - if (bytesRead >= packetLength) { - reader.unshift(value.subarray(packetLength - bytesRead + value.length)); - break; - } - } - } - } while (wasPartialLength); - - // If this was not a packet that "supports streaming", we peek to check - // whether it is the last packet in the message. We peek 2 bytes instead - // of 1 because the beginning of this function also peeks 2 bytes, and we - // want to cut a `subarray` of the correct length into `web-stream-tools`' - // `externalBuffer` as a tiny optimization here. - // - // If it *was* a streaming packet (i.e. the data packets), we peek at the - // entire remainder of the stream, in order to forward errors in the - // remainder of the stream to the packet data. (Note that this means we - // read/peek at all signature packets before closing the literal data - // packet, for example.) This forwards MDC errors to the literal data - // stream, for example, so that they don't get lost / forgotten on - // decryptedMessage.packets.stream, which we never look at. - // - // An example of what we do when stream-parsing a message containing - // [ one-pass signature packet, literal data packet, signature packet ]: - // 1. Read the one-pass signature packet - // 2. Peek 2 bytes of the literal data packet - // 3. Parse the one-pass signature packet - // - // 4. Read the literal data packet, simultaneously stream-parsing it - // 5. Peek until the end of the message - // 6. Finish parsing the literal data packet - // - // 7. Read the signature packet again (we already peeked at it in step 5) - // 8. Peek at the end of the stream again (`peekBytes` returns undefined) - // 9. Parse the signature packet - // - // Note that this means that if there's an error in the very end of the - // stream, such as an MDC error, we throw in step 5 instead of in step 8 - // (or never), which is the point of this exercise. - const nextPacket = await reader.peekBytes(packetSupportsStreaming ? Infinity : 2); - if (writer) { - await writer.ready; - await writer.close(); - } else { - packet = util.concatUint8Array(packet); - await callback({ tag, packet }); - } - return !nextPacket || !nextPacket.length; - } catch (e) { - if (writer) { - await writer.abort(e); - return true; - } else { - throw e; - } - } finally { - if (writer) { - await callbackReturned; - } - reader.releaseLock(); - } -} - -class UnsupportedError extends Error { - constructor(...params) { - super(...params); - - if (Error.captureStackTrace) { - Error.captureStackTrace(this, UnsupportedError); - } - - this.name = 'UnsupportedError'; - } -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -// Symbol to store cryptographic validity of the signature, to avoid recomputing multiple times on verification. -// const verified = Symbol('verified'); - -// GPG puts the Issuer and Signature subpackets in the unhashed area. -// Tampering with those invalidates the signature, so we still trust them and parse them. -// All other unhashed subpackets are ignored. -const allowedUnhashedSubpackets = new Set([ - enums.signatureSubpacket.issuer, - enums.signatureSubpacket.issuerFingerprint, - enums.signatureSubpacket.embeddedSignature -]); - -/** - * Implementation of the Signature Packet (Tag 2) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.2|RFC4480 5.2}: - * A Signature packet describes a binding between some public key and - * some data. The most common signatures are a signature of a file or a - * block of text, and a signature that is a certification of a User ID. - */ -class SignaturePacket { - static get tag() { - return enums.packet.signature; - } - - constructor() { - this.version = null; - /** @type {enums.signature} */ - this.signatureType = null; - /** @type {enums.hash} */ - this.hashAlgorithm = null; - /** @type {enums.publicKey} */ - this.publicKeyAlgorithm = null; - - this.signatureData = null; - this.unhashedSubpackets = []; - this.signedHashValue = null; - - this.created = null; - this.signatureExpirationTime = null; - this.signatureNeverExpires = true; - this.exportable = null; - this.trustLevel = null; - this.trustAmount = null; - this.regularExpression = null; - this.revocable = null; - this.keyExpirationTime = null; - this.keyNeverExpires = null; - this.preferredSymmetricAlgorithms = null; - this.revocationKeyClass = null; - this.revocationKeyAlgorithm = null; - this.revocationKeyFingerprint = null; - this.issuerKeyID = new KeyID(); - this.rawNotations = []; - this.notations = {}; - this.preferredHashAlgorithms = null; - this.preferredCompressionAlgorithms = null; - this.keyServerPreferences = null; - this.preferredKeyServer = null; - this.isPrimaryUserID = null; - this.policyURI = null; - this.keyFlags = null; - this.signersUserID = null; - this.reasonForRevocationFlag = null; - this.reasonForRevocationString = null; - this.features = null; - this.signatureTargetPublicKeyAlgorithm = null; - this.signatureTargetHashAlgorithm = null; - this.signatureTargetHash = null; - this.embeddedSignature = null; - this.issuerKeyVersion = null; - this.issuerFingerprint = null; - this.preferredAEADAlgorithms = null; - - this.revoked = null; - this.verified = null; - } - - /** - * parsing function for a signature packet (tag 2). - * @param {String} bytes - Payload of a tag 2 packet - * @returns {SignaturePacket} Object representation. - */ - read(bytes) { - let i = 0; - this.version = bytes[i++]; - - if (this.version !== 4 && this.version !== 5) { - throw new UnsupportedError(`Version ${this.version} of the signature packet is unsupported.`); - } - - this.signatureType = bytes[i++]; - this.publicKeyAlgorithm = bytes[i++]; - this.hashAlgorithm = bytes[i++]; - - // hashed subpackets - i += this.readSubPackets(bytes.subarray(i, bytes.length), true); - if (!this.created) { - throw new Error('Missing signature creation time subpacket.'); - } - - // A V4 signature hashes the packet body - // starting from its first field, the version number, through the end - // of the hashed subpacket data. Thus, the fields hashed are the - // signature version, the signature type, the public-key algorithm, the - // hash algorithm, the hashed subpacket length, and the hashed - // subpacket body. - this.signatureData = bytes.subarray(0, i); - - // unhashed subpackets - i += this.readSubPackets(bytes.subarray(i, bytes.length), false); - - // Two-octet field holding left 16 bits of signed hash value. - this.signedHashValue = bytes.subarray(i, i + 2); - i += 2; - - this.params = mod.signature.parseSignatureParams(this.publicKeyAlgorithm, bytes.subarray(i, bytes.length)); - } - - /** - * @returns {Uint8Array | ReadableStream} - */ - writeParams() { - if (this.params instanceof Promise) { - return fromAsync( - async () => mod.serializeParams(this.publicKeyAlgorithm, await this.params) - ); - } - return mod.serializeParams(this.publicKeyAlgorithm, this.params); - } - - write() { - const arr = []; - arr.push(this.signatureData); - arr.push(this.writeUnhashedSubPackets()); - arr.push(this.signedHashValue); - arr.push(this.writeParams()); - return util.concat(arr); - } - - /** - * Signs provided data. This needs to be done prior to serialization. - * @param {SecretKeyPacket} key - Private key used to sign the message. - * @param {Object} data - Contains packets to be signed. - * @param {Date} [date] - The signature creation time. - * @param {Boolean} [detached] - Whether to create a detached signature - * @throws {Error} if signing failed - * @async - */ - async sign(key, data, date = new Date(), detached = false) { - if (key.version === 5) { - this.version = 5; - } else { - this.version = 4; - } - const arr = [new Uint8Array([this.version, this.signatureType, this.publicKeyAlgorithm, this.hashAlgorithm])]; - - this.created = util.normalizeDate(date); - this.issuerKeyVersion = key.version; - this.issuerFingerprint = key.getFingerprintBytes(); - this.issuerKeyID = key.getKeyID(); - - // Add hashed subpackets - arr.push(this.writeHashedSubPackets()); - - this.signatureData = util.concat(arr); - - const toHash = this.toHash(this.signatureType, data, detached); - const hash = await this.hash(this.signatureType, data, toHash, detached); - - this.signedHashValue = slice(clone(hash), 0, 2); - const signed = async () => mod.signature.sign( - this.publicKeyAlgorithm, this.hashAlgorithm, key.publicParams, key.privateParams, toHash, await readToEnd(hash) - ); - if (util.isStream(hash)) { - this.params = signed(); - } else { - this.params = await signed(); - - // Store the fact that this signature is valid, e.g. for when we call `await - // getLatestValidSignature(this.revocationSignatures, key, data)` later. - // Note that this only holds up if the key and data passed to verify are the - // same as the ones passed to sign. - this.verified = true; - } - } - - /** - * Creates Uint8Array of bytes of all subpacket data except Issuer and Embedded Signature subpackets - * @returns {Uint8Array} Subpacket data. - */ - writeHashedSubPackets() { - const sub = enums.signatureSubpacket; - const arr = []; - let bytes; - if (this.created === null) { - throw new Error('Missing signature creation time'); - } - arr.push(writeSubPacket(sub.signatureCreationTime, util.writeDate(this.created))); - if (this.signatureExpirationTime !== null) { - arr.push(writeSubPacket(sub.signatureExpirationTime, util.writeNumber(this.signatureExpirationTime, 4))); - } - if (this.exportable !== null) { - arr.push(writeSubPacket(sub.exportableCertification, new Uint8Array([this.exportable ? 1 : 0]))); - } - if (this.trustLevel !== null) { - bytes = new Uint8Array([this.trustLevel, this.trustAmount]); - arr.push(writeSubPacket(sub.trustSignature, bytes)); - } - if (this.regularExpression !== null) { - arr.push(writeSubPacket(sub.regularExpression, this.regularExpression)); - } - if (this.revocable !== null) { - arr.push(writeSubPacket(sub.revocable, new Uint8Array([this.revocable ? 1 : 0]))); - } - if (this.keyExpirationTime !== null) { - arr.push(writeSubPacket(sub.keyExpirationTime, util.writeNumber(this.keyExpirationTime, 4))); - } - if (this.preferredSymmetricAlgorithms !== null) { - bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredSymmetricAlgorithms)); - arr.push(writeSubPacket(sub.preferredSymmetricAlgorithms, bytes)); - } - if (this.revocationKeyClass !== null) { - bytes = new Uint8Array([this.revocationKeyClass, this.revocationKeyAlgorithm]); - bytes = util.concat([bytes, this.revocationKeyFingerprint]); - arr.push(writeSubPacket(sub.revocationKey, bytes)); - } - this.rawNotations.forEach(([{ name, value, humanReadable }]) => { - bytes = [new Uint8Array([humanReadable ? 0x80 : 0, 0, 0, 0])]; - // 2 octets of name length - bytes.push(util.writeNumber(name.length, 2)); - // 2 octets of value length - bytes.push(util.writeNumber(value.length, 2)); - bytes.push(util.stringToUint8Array(name)); - bytes.push(value); - bytes = util.concat(bytes); - arr.push(writeSubPacket(sub.notationData, bytes)); - }); - if (this.preferredHashAlgorithms !== null) { - bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredHashAlgorithms)); - arr.push(writeSubPacket(sub.preferredHashAlgorithms, bytes)); - } - if (this.preferredCompressionAlgorithms !== null) { - bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredCompressionAlgorithms)); - arr.push(writeSubPacket(sub.preferredCompressionAlgorithms, bytes)); - } - if (this.keyServerPreferences !== null) { - bytes = util.stringToUint8Array(util.uint8ArrayToString(this.keyServerPreferences)); - arr.push(writeSubPacket(sub.keyServerPreferences, bytes)); - } - if (this.preferredKeyServer !== null) { - arr.push(writeSubPacket(sub.preferredKeyServer, util.stringToUint8Array(this.preferredKeyServer))); - } - if (this.isPrimaryUserID !== null) { - arr.push(writeSubPacket(sub.primaryUserID, new Uint8Array([this.isPrimaryUserID ? 1 : 0]))); - } - if (this.policyURI !== null) { - arr.push(writeSubPacket(sub.policyURI, util.stringToUint8Array(this.policyURI))); - } - if (this.keyFlags !== null) { - bytes = util.stringToUint8Array(util.uint8ArrayToString(this.keyFlags)); - arr.push(writeSubPacket(sub.keyFlags, bytes)); - } - if (this.signersUserID !== null) { - arr.push(writeSubPacket(sub.signersUserID, util.stringToUint8Array(this.signersUserID))); - } - if (this.reasonForRevocationFlag !== null) { - bytes = util.stringToUint8Array(String.fromCharCode(this.reasonForRevocationFlag) + this.reasonForRevocationString); - arr.push(writeSubPacket(sub.reasonForRevocation, bytes)); - } - if (this.features !== null) { - bytes = util.stringToUint8Array(util.uint8ArrayToString(this.features)); - arr.push(writeSubPacket(sub.features, bytes)); - } - if (this.signatureTargetPublicKeyAlgorithm !== null) { - bytes = [new Uint8Array([this.signatureTargetPublicKeyAlgorithm, this.signatureTargetHashAlgorithm])]; - bytes.push(util.stringToUint8Array(this.signatureTargetHash)); - bytes = util.concat(bytes); - arr.push(writeSubPacket(sub.signatureTarget, bytes)); - } - if (this.preferredAEADAlgorithms !== null) { - bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredAEADAlgorithms)); - arr.push(writeSubPacket(sub.preferredAEADAlgorithms, bytes)); - } - - const result = util.concat(arr); - const length = util.writeNumber(result.length, 2); - - return util.concat([length, result]); - } - - /** - * Creates Uint8Array of bytes of Issuer and Embedded Signature subpackets - * @returns {Uint8Array} Subpacket data. - */ - writeUnhashedSubPackets() { - const sub = enums.signatureSubpacket; - const arr = []; - let bytes; - if (!this.issuerKeyID.isNull() && this.issuerKeyVersion !== 5) { - // If the version of [the] key is greater than 4, this subpacket - // MUST NOT be included in the signature. - arr.push(writeSubPacket(sub.issuer, this.issuerKeyID.write())); - } - if (this.embeddedSignature !== null) { - arr.push(writeSubPacket(sub.embeddedSignature, this.embeddedSignature.write())); - } - if (this.issuerFingerprint !== null) { - bytes = [new Uint8Array([this.issuerKeyVersion]), this.issuerFingerprint]; - bytes = util.concat(bytes); - arr.push(writeSubPacket(sub.issuerFingerprint, bytes)); - } - this.unhashedSubpackets.forEach(data => { - arr.push(writeSimpleLength(data.length)); - arr.push(data); - }); - - const result = util.concat(arr); - const length = util.writeNumber(result.length, 2); - - return util.concat([length, result]); - } - - // V4 signature sub packets - readSubPacket(bytes, hashed = true) { - let mypos = 0; - - // The leftmost bit denotes a "critical" packet - const critical = bytes[mypos] & 0x80; - const type = bytes[mypos] & 0x7F; - - if (!hashed && !allowedUnhashedSubpackets.has(type)) { - this.unhashedSubpackets.push(bytes.subarray(mypos, bytes.length)); - return; - } - - mypos++; - - // subpacket type - switch (type) { - case enums.signatureSubpacket.signatureCreationTime: - // Signature Creation Time - this.created = util.readDate(bytes.subarray(mypos, bytes.length)); - break; - case enums.signatureSubpacket.signatureExpirationTime: { - // Signature Expiration Time in seconds - const seconds = util.readNumber(bytes.subarray(mypos, bytes.length)); - - this.signatureNeverExpires = seconds === 0; - this.signatureExpirationTime = seconds; - - break; - } - case enums.signatureSubpacket.exportableCertification: - // Exportable Certification - this.exportable = bytes[mypos++] === 1; - break; - case enums.signatureSubpacket.trustSignature: - // Trust Signature - this.trustLevel = bytes[mypos++]; - this.trustAmount = bytes[mypos++]; - break; - case enums.signatureSubpacket.regularExpression: - // Regular Expression - this.regularExpression = bytes[mypos]; - break; - case enums.signatureSubpacket.revocable: - // Revocable - this.revocable = bytes[mypos++] === 1; - break; - case enums.signatureSubpacket.keyExpirationTime: { - // Key Expiration Time in seconds - const seconds = util.readNumber(bytes.subarray(mypos, bytes.length)); - - this.keyExpirationTime = seconds; - this.keyNeverExpires = seconds === 0; - - break; - } - case enums.signatureSubpacket.preferredSymmetricAlgorithms: - // Preferred Symmetric Algorithms - this.preferredSymmetricAlgorithms = [...bytes.subarray(mypos, bytes.length)]; - break; - case enums.signatureSubpacket.revocationKey: - // Revocation Key - // (1 octet of class, 1 octet of public-key algorithm ID, 20 - // octets of - // fingerprint) - this.revocationKeyClass = bytes[mypos++]; - this.revocationKeyAlgorithm = bytes[mypos++]; - this.revocationKeyFingerprint = bytes.subarray(mypos, mypos + 20); - break; - - case enums.signatureSubpacket.issuer: - // Issuer - this.issuerKeyID.read(bytes.subarray(mypos, bytes.length)); - break; - - case enums.signatureSubpacket.notationData: { - // Notation Data - const humanReadable = !!(bytes[mypos] & 0x80); - - // We extract key/value tuple from the byte stream. - mypos += 4; - const m = util.readNumber(bytes.subarray(mypos, mypos + 2)); - mypos += 2; - const n = util.readNumber(bytes.subarray(mypos, mypos + 2)); - mypos += 2; - - const name = util.uint8ArrayToString(bytes.subarray(mypos, mypos + m)); - const value = bytes.subarray(mypos + m, mypos + m + n); - - this.rawNotations.push({ name, humanReadable, value, critical }); - - if (humanReadable) { - this.notations[name] = util.uint8ArrayToString(value); - } - break; - } - case enums.signatureSubpacket.preferredHashAlgorithms: - // Preferred Hash Algorithms - this.preferredHashAlgorithms = [...bytes.subarray(mypos, bytes.length)]; - break; - case enums.signatureSubpacket.preferredCompressionAlgorithms: - // Preferred Compression Algorithms - this.preferredCompressionAlgorithms = [...bytes.subarray(mypos, bytes.length)]; - break; - case enums.signatureSubpacket.keyServerPreferences: - // Key Server Preferences - this.keyServerPreferences = [...bytes.subarray(mypos, bytes.length)]; - break; - case enums.signatureSubpacket.preferredKeyServer: - // Preferred Key Server - this.preferredKeyServer = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); - break; - case enums.signatureSubpacket.primaryUserID: - // Primary User ID - this.isPrimaryUserID = bytes[mypos++] !== 0; - break; - case enums.signatureSubpacket.policyURI: - // Policy URI - this.policyURI = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); - break; - case enums.signatureSubpacket.keyFlags: - // Key Flags - this.keyFlags = [...bytes.subarray(mypos, bytes.length)]; - break; - case enums.signatureSubpacket.signersUserID: - // Signer's User ID - this.signersUserID = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); - break; - case enums.signatureSubpacket.reasonForRevocation: - // Reason for Revocation - this.reasonForRevocationFlag = bytes[mypos++]; - this.reasonForRevocationString = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); - break; - case enums.signatureSubpacket.features: - // Features - this.features = [...bytes.subarray(mypos, bytes.length)]; - break; - case enums.signatureSubpacket.signatureTarget: { - // Signature Target - // (1 octet public-key algorithm, 1 octet hash algorithm, N octets hash) - this.signatureTargetPublicKeyAlgorithm = bytes[mypos++]; - this.signatureTargetHashAlgorithm = bytes[mypos++]; - - const len = mod.getHashByteLength(this.signatureTargetHashAlgorithm); - - this.signatureTargetHash = util.uint8ArrayToString(bytes.subarray(mypos, mypos + len)); - break; - } - case enums.signatureSubpacket.embeddedSignature: - // Embedded Signature - this.embeddedSignature = new SignaturePacket(); - this.embeddedSignature.read(bytes.subarray(mypos, bytes.length)); - break; - case enums.signatureSubpacket.issuerFingerprint: - // Issuer Fingerprint - this.issuerKeyVersion = bytes[mypos++]; - this.issuerFingerprint = bytes.subarray(mypos, bytes.length); - if (this.issuerKeyVersion === 5) { - this.issuerKeyID.read(this.issuerFingerprint); - } else { - this.issuerKeyID.read(this.issuerFingerprint.subarray(-8)); - } - break; - case enums.signatureSubpacket.preferredAEADAlgorithms: - // Preferred AEAD Algorithms - this.preferredAEADAlgorithms = [...bytes.subarray(mypos, bytes.length)]; - break; - default: { - const err = new Error(`Unknown signature subpacket type ${type}`); - if (critical) { - throw err; - } else { - util.printDebug(err); - } - } - } - } - - readSubPackets(bytes, trusted = true, config) { - // Two-octet scalar octet count for following subpacket data. - const subpacketLength = util.readNumber(bytes.subarray(0, 2)); - - let i = 2; - - // subpacket data set (zero or more subpackets) - while (i < 2 + subpacketLength) { - const len = readSimpleLength(bytes.subarray(i, bytes.length)); - i += len.offset; - - this.readSubPacket(bytes.subarray(i, i + len.len), trusted, config); - - i += len.len; - } - - return i; - } - - // Produces data to produce signature on - toSign(type, data) { - const t = enums.signature; - - switch (type) { - case t.binary: - if (data.text !== null) { - return util.encodeUTF8(data.getText(true)); - } - return data.getBytes(true); - - case t.text: { - const bytes = data.getBytes(true); - // normalize EOL to \r\n - return util.canonicalizeEOL(bytes); - } - case t.standalone: - return new Uint8Array(0); - - case t.certGeneric: - case t.certPersona: - case t.certCasual: - case t.certPositive: - case t.certRevocation: { - let packet; - let tag; - - if (data.userID) { - tag = 0xB4; - packet = data.userID; - } else if (data.userAttribute) { - tag = 0xD1; - packet = data.userAttribute; - } else { - throw new Error('Either a userID or userAttribute packet needs to be ' + - 'supplied for certification.'); - } - - const bytes = packet.write(); - - return util.concat([this.toSign(t.key, data), - new Uint8Array([tag]), - util.writeNumber(bytes.length, 4), - bytes]); - } - case t.subkeyBinding: - case t.subkeyRevocation: - case t.keyBinding: - return util.concat([this.toSign(t.key, data), this.toSign(t.key, { - key: data.bind - })]); - - case t.key: - if (data.key === undefined) { - throw new Error('Key packet is required for this signature.'); - } - return data.key.writeForHash(this.version); - - case t.keyRevocation: - return this.toSign(t.key, data); - case t.timestamp: - return new Uint8Array(0); - case t.thirdParty: - throw new Error('Not implemented'); - default: - throw new Error('Unknown signature type.'); - } - } - - calculateTrailer(data, detached) { - let length = 0; - return transform(clone(this.signatureData), value => { - length += value.length; - }, () => { - const arr = []; - if (this.version === 5 && (this.signatureType === enums.signature.binary || this.signatureType === enums.signature.text)) { - if (detached) { - arr.push(new Uint8Array(6)); - } else { - arr.push(data.writeHeader()); - } - } - arr.push(new Uint8Array([this.version, 0xFF])); - if (this.version === 5) { - arr.push(new Uint8Array(4)); - } - arr.push(util.writeNumber(length, 4)); - // For v5, this should really be writeNumber(length, 8) rather than the - // hardcoded 4 zero bytes above - return util.concat(arr); - }); - } - - toHash(signatureType, data, detached = false) { - const bytes = this.toSign(signatureType, data); - - return util.concat([bytes, this.signatureData, this.calculateTrailer(data, detached)]); - } - - async hash(signatureType, data, toHash, detached = false) { - if (!toHash) toHash = this.toHash(signatureType, data, detached); - return mod.hash.digest(this.hashAlgorithm, toHash); - } - - /** - * verifies the signature packet. Note: not all signature types are implemented - * @param {PublicSubkeyPacket|PublicKeyPacket| - * SecretSubkeyPacket|SecretKeyPacket} key - the public key to verify the signature - * @param {module:enums.signature} signatureType - Expected signature type - * @param {String|Object} data - Data which on the signature applies - * @param {Date} [date] - Use the given date instead of the current time to check for signature validity and expiration - * @param {Boolean} [detached] - Whether to verify a detached signature - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if signature validation failed - * @async - */ - async verify(key, signatureType, data, date = new Date(), detached = false, config = defaultConfig) { - if (!this.issuerKeyID.equals(key.getKeyID())) { - throw new Error('Signature was not issued by the given public key'); - } - if (this.publicKeyAlgorithm !== key.algorithm) { - throw new Error('Public key algorithm used to sign signature does not match issuer key algorithm.'); - } - - const isMessageSignature = signatureType === enums.signature.binary || signatureType === enums.signature.text; - // Cryptographic validity is cached after one successful verification. - // However, for message signatures, we always re-verify, since the passed `data` can change - const skipVerify = this.verified && !isMessageSignature; - // console.log(`verify signature OUID ${Object.__oid(this)} ${this.verified} sigtype=${signatureType}...`); - if (!skipVerify) { - let toHash; - let hash; - if (this.hashed) { - hash = await this.hashed; - } else { - toHash = this.toHash(signatureType, data, detached); - hash = await this.hash(signatureType, data, toHash); - } - hash = await readToEnd(hash); - if (this.signedHashValue[0] !== hash[0] || - this.signedHashValue[1] !== hash[1]) { - throw new Error('Signed digest did not match'); - } - - this.params = await this.params; - - this.verified = await mod.signature.verify( - this.publicKeyAlgorithm, this.hashAlgorithm, this.params, key.publicParams, - toHash, hash - ); - // console.log(`verify signature OUID ${Object.__oid(this)} sigtype=${signatureType} result: ${this.verified}`); - - if (!this.verified) { - throw new Error('Signature verification failed'); - } - } - - const normDate = util.normalizeDate(date); - if (normDate && this.created > normDate) { - throw new Error('Signature creation time is in the future'); - } - if (normDate && normDate >= this.getExpirationTime()) { - throw new Error('Signature is expired'); - } - if (config.rejectHashAlgorithms.has(this.hashAlgorithm)) { - throw new Error('Insecure hash algorithm: ' + enums.read(enums.hash, this.hashAlgorithm).toUpperCase()); - } - if (config.rejectMessageHashAlgorithms.has(this.hashAlgorithm) && - [enums.signature.binary, enums.signature.text].includes(this.signatureType)) { - throw new Error('Insecure message hash algorithm: ' + enums.read(enums.hash, this.hashAlgorithm).toUpperCase()); - } - this.rawNotations.forEach(({ name, critical }) => { - if (critical && (config.knownNotations.indexOf(name) < 0)) { - throw new Error(`Unknown critical notation: ${name}`); - } - }); - if (this.revocationKeyClass !== null) { - throw new Error('This key is intended to be revoked with an authorized key, which OpenPGP.js does not support.'); - } - } - - /** - * Verifies signature expiration date - * @param {Date} [date] - Use the given date for verification instead of the current time - * @returns {Boolean} True if expired. - */ - isExpired(date = new Date()) { - const normDate = util.normalizeDate(date); - if (normDate !== null) { - return !(this.created <= normDate && normDate < this.getExpirationTime()); - } - return false; - } - - /** - * Returns the expiration time of the signature or Infinity if signature does not expire - * @returns {Date | Infinity} Expiration time. - */ - getExpirationTime() { - return this.signatureNeverExpires ? Infinity : new Date(this.created.getTime() + this.signatureExpirationTime * 1000); - } -} - -/** - * Creates a string representation of a sub signature packet - * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.1|RFC4880 5.2.3.1} - * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.2|RFC4880 5.2.3.2} - * @param {Integer} type - Subpacket signature type. - * @param {String} data - Data to be included - * @returns {String} A string-representation of a sub signature packet. - * @private - */ -function writeSubPacket(type, data) { - const arr = []; - arr.push(writeSimpleLength(data.length + 1)); - arr.push(new Uint8Array([type])); - arr.push(data); - return util.concat(arr); -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -const VERSION = 3; - -/** - * Implementation of the One-Pass Signature Packets (Tag 4) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.4|RFC4880 5.4}: - * The One-Pass Signature packet precedes the signed data and contains - * enough information to allow the receiver to begin calculating any - * hashes needed to verify the signature. It allows the Signature - * packet to be placed at the end of the message, so that the signer - * can compute the entire signed message in one pass. - */ -class OnePassSignaturePacket { - static get tag() { - return enums.packet.onePassSignature; - } - - constructor() { - /** A one-octet version number. The current version is 3. */ - this.version = null; - /** - * A one-octet signature type. - * Signature types are described in - * {@link https://tools.ietf.org/html/rfc4880#section-5.2.1|RFC4880 Section 5.2.1}. - * @type {enums.signature} - - */ - this.signatureType = null; - /** - * A one-octet number describing the hash algorithm used. - * @see {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC4880 9.4} - * @type {enums.hash} - */ - this.hashAlgorithm = null; - /** - * A one-octet number describing the public-key algorithm used. - * @see {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC4880 9.1} - * @type {enums.publicKey} - */ - this.publicKeyAlgorithm = null; - /** An eight-octet number holding the Key ID of the signing key. */ - this.issuerKeyID = null; - /** - * A one-octet number holding a flag showing whether the signature is nested. - * A zero value indicates that the next packet is another One-Pass Signature packet - * that describes another signature to be applied to the same message data. - */ - this.flags = null; - } - - /** - * parsing function for a one-pass signature packet (tag 4). - * @param {Uint8Array} bytes - Payload of a tag 4 packet - * @returns {OnePassSignaturePacket} Object representation. - */ - read(bytes) { - let mypos = 0; - // A one-octet version number. The current version is 3. - this.version = bytes[mypos++]; - if (this.version !== VERSION) { - throw new UnsupportedError(`Version ${this.version} of the one-pass signature packet is unsupported.`); - } - - // A one-octet signature type. Signature types are described in - // Section 5.2.1. - this.signatureType = bytes[mypos++]; - - // A one-octet number describing the hash algorithm used. - this.hashAlgorithm = bytes[mypos++]; - - // A one-octet number describing the public-key algorithm used. - this.publicKeyAlgorithm = bytes[mypos++]; - - // An eight-octet number holding the Key ID of the signing key. - this.issuerKeyID = new KeyID(); - this.issuerKeyID.read(bytes.subarray(mypos, mypos + 8)); - mypos += 8; - - // A one-octet number holding a flag showing whether the signature - // is nested. A zero value indicates that the next packet is - // another One-Pass Signature packet that describes another - // signature to be applied to the same message data. - this.flags = bytes[mypos++]; - return this; - } - - /** - * creates a string representation of a one-pass signature packet - * @returns {Uint8Array} A Uint8Array representation of a one-pass signature packet. - */ - write() { - const start = new Uint8Array([VERSION, this.signatureType, this.hashAlgorithm, this.publicKeyAlgorithm]); - - const end = new Uint8Array([this.flags]); - - return util.concatUint8Array([start, this.issuerKeyID.write(), end]); - } - - calculateTrailer(...args) { - return fromAsync(async () => SignaturePacket.prototype.calculateTrailer.apply(await this.correspondingSig, args)); - } - - async verify() { - const correspondingSig = await this.correspondingSig; - if (!correspondingSig || correspondingSig.constructor.tag !== enums.packet.signature) { - throw new Error('Corresponding signature packet missing'); - } - if ( - correspondingSig.signatureType !== this.signatureType || - correspondingSig.hashAlgorithm !== this.hashAlgorithm || - correspondingSig.publicKeyAlgorithm !== this.publicKeyAlgorithm || - !correspondingSig.issuerKeyID.equals(this.issuerKeyID) - ) { - throw new Error('Corresponding signature packet does not match one-pass signature packet'); - } - correspondingSig.hashed = this.hashed; - return correspondingSig.verify.apply(correspondingSig, arguments); - } -} - -OnePassSignaturePacket.prototype.hash = SignaturePacket.prototype.hash; -OnePassSignaturePacket.prototype.toHash = SignaturePacket.prototype.toHash; -OnePassSignaturePacket.prototype.toSign = SignaturePacket.prototype.toSign; - -/** - * Instantiate a new packet given its tag - * @function newPacketFromTag - * @param {module:enums.packet} tag - Property value from {@link module:enums.packet} - * @param {Object} allowedPackets - mapping where keys are allowed packet tags, pointing to their Packet class - * @returns {Object} New packet object with type based on tag - * @throws {Error|UnsupportedError} for disallowed or unknown packets - */ -function newPacketFromTag(tag, allowedPackets) { - if (!allowedPackets[tag]) { - // distinguish between disallowed packets and unknown ones - let packetType; - try { - packetType = enums.read(enums.packet, tag); - } catch (e) { - throw new UnsupportedError(`Unknown packet type with tag: ${tag}`); - } - throw new Error(`Packet not allowed in this context: ${packetType}`); - } - return new allowedPackets[tag](); -} - -/** - * This class represents a list of openpgp packets. - * Take care when iterating over it - the packets themselves - * are stored as numerical indices. - * @extends Array - */ -class PacketList extends Array { - /** - * Parses the given binary data and returns a list of packets. - * Equivalent to calling `read` on an empty PacketList instance. - * @param {Uint8Array | ReadableStream} bytes - binary data to parse - * @param {Object} allowedPackets - mapping where keys are allowed packet tags, pointing to their Packet class - * @param {Object} [config] - full configuration, defaults to openpgp.config - * @returns {PacketList} parsed list of packets - * @throws on parsing errors - * @async - */ - static async fromBinary(bytes, allowedPackets, config = defaultConfig) { - const packets = new PacketList(); - await packets.read(bytes, allowedPackets, config); - return packets; - } - - /** - * Reads a stream of binary data and interprets it as a list of packets. - * @param {Uint8Array | ReadableStream} bytes - binary data to parse - * @param {Object} allowedPackets - mapping where keys are allowed packet tags, pointing to their Packet class - * @param {Object} [config] - full configuration, defaults to openpgp.config - * @throws on parsing errors - * @async - */ - async read(bytes, allowedPackets, config = defaultConfig) { - this.stream = transformPair(bytes, async (readable, writable) => { - const writer = getWriter(writable); - try { - while (true) { - await writer.ready; - const done = await readPackets(readable, async parsed => { - try { - if (parsed.tag === enums.packet.marker || parsed.tag === enums.packet.trust) { - // According to the spec, these packet types should be ignored and not cause parsing errors, even if not esplicitly allowed: - // - Marker packets MUST be ignored when received: https://github.com/openpgpjs/openpgpjs/issues/1145 - // - Trust packets SHOULD be ignored outside of keyrings (unsupported): https://datatracker.ietf.org/doc/html/rfc4880#section-5.10 - return; - } - const packet = newPacketFromTag(parsed.tag, allowedPackets); - packet.packets = new PacketList(); - packet.fromStream = util.isStream(parsed.packet); - await packet.read(parsed.packet, config); - await writer.write(packet); - } catch (e) { - const throwUnsupportedError = !config.ignoreUnsupportedPackets && e instanceof UnsupportedError; - const throwMalformedError = !config.ignoreMalformedPackets && !(e instanceof UnsupportedError); - if (throwUnsupportedError || throwMalformedError || supportsStreaming(parsed.tag)) { - // The packets that support streaming are the ones that contain message data. - // Those are also the ones we want to be more strict about and throw on parse errors - // (since we likely cannot process the message without these packets anyway). - await writer.abort(e); - } - util.printDebugError(e); - } - }); - if (done) { - await writer.ready; - await writer.close(); - return; - } - } - } catch (e) { - await writer.abort(e); - } - }); - - // Wait until first few packets have been read - const reader = getReader(this.stream); - while (true) { - const { done, value } = await reader.read(); - if (!done) { - this.push(value); - } else { - this.stream = null; - } - if (done || supportsStreaming(value.constructor.tag)) { - break; - } - } - reader.releaseLock(); - } - - /** - * Creates a binary representation of openpgp objects contained within the - * class instance. - * @returns {Uint8Array} A Uint8Array containing valid openpgp packets. - */ - write() { - const arr = []; - - for (let i = 0; i < this.length; i++) { - const packetbytes = this[i].write(); - if (util.isStream(packetbytes) && supportsStreaming(this[i].constructor.tag)) { - let buffer = []; - let bufferLength = 0; - const minLength = 512; - arr.push(writeTag(this[i].constructor.tag)); - arr.push(transform(packetbytes, value => { - buffer.push(value); - bufferLength += value.length; - if (bufferLength >= minLength) { - const powerOf2 = Math.min(Math.log(bufferLength) / Math.LN2 | 0, 30); - const chunkSize = 2 ** powerOf2; - const bufferConcat = util.concat([writePartialLength(powerOf2)].concat(buffer)); - buffer = [bufferConcat.subarray(1 + chunkSize)]; - bufferLength = buffer[0].length; - return bufferConcat.subarray(0, 1 + chunkSize); - } - }, () => util.concat([writeSimpleLength(bufferLength)].concat(buffer)))); - } else { - if (util.isStream(packetbytes)) { - let length = 0; - arr.push(transform(clone(packetbytes), value => { - length += value.length; - }, () => writeHeader(this[i].constructor.tag, length))); - } else { - arr.push(writeHeader(this[i].constructor.tag, packetbytes.length)); - } - arr.push(packetbytes); - } - } - - return util.concat(arr); - } - - /** - * Creates a new PacketList with all packets matching the given tag(s) - * @param {...module:enums.packet} tags - packet tags to look for - * @returns {PacketList} - */ - filterByTag(...tags) { - const filtered = new PacketList(); - - const handle = tag => packetType => tag === packetType; - - for (let i = 0; i < this.length; i++) { - if (tags.some(handle(this[i].constructor.tag))) { - filtered.push(this[i]); - } - } - - return filtered; - } - - /** - * Traverses packet list and returns first packet with matching tag - * @param {module:enums.packet} tag - The packet tag - * @returns {Packet|undefined} - */ - findPacket(tag) { - return this.find(packet => packet.constructor.tag === tag); - } - - /** - * Find indices of packets with the given tag(s) - * @param {...module:enums.packet} tags - packet tags to look for - * @returns {Integer[]} packet indices - */ - indexOfTag(...tags) { - const tagIndex = []; - const that = this; - - const handle = tag => packetType => tag === packetType; - - for (let i = 0; i < this.length; i++) { - if (tags.some(handle(that[i].constructor.tag))) { - tagIndex.push(i); - } - } - return tagIndex; - } -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -// A Compressed Data packet can contain the following packet types -const allowedPackets = /*#__PURE__*/ util.constructAllowedPackets([ - LiteralDataPacket, - OnePassSignaturePacket, - SignaturePacket -]); - -/** - * Implementation of the Compressed Data Packet (Tag 8) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.6|RFC4880 5.6}: - * The Compressed Data packet contains compressed data. Typically, - * this packet is found as the contents of an encrypted packet, or following - * a Signature or One-Pass Signature packet, and contains a literal data packet. - */ -class CompressedDataPacket { - static get tag() { - return enums.packet.compressedData; - } - - /** - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - constructor(config = defaultConfig) { - /** - * List of packets - * @type {PacketList} - */ - this.packets = null; - /** - * Compression algorithm - * @type {enums.compression} - */ - this.algorithm = config.preferredCompressionAlgorithm; - - /** - * Compressed packet data - * @type {Uint8Array | ReadableStream} - */ - this.compressed = null; - - /** - * zip/zlib compression level, between 1 and 9 - */ - this.deflateLevel = config.deflateLevel; - } - - /** - * Parsing function for the packet. - * @param {Uint8Array | ReadableStream} bytes - Payload of a tag 8 packet - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - async read(bytes, config = defaultConfig) { - await parse(bytes, async reader => { - - // One octet that gives the algorithm used to compress the packet. - this.algorithm = await reader.readByte(); - - // Compressed data, which makes up the remainder of the packet. - this.compressed = reader.remainder(); - - await this.decompress(config); - }); - } - - - /** - * Return the compressed packet. - * @returns {Uint8Array | ReadableStream} Binary compressed packet. - */ - write() { - if (this.compressed === null) { - this.compress(); - } - - return util.concat([new Uint8Array([this.algorithm]), this.compressed]); - } - - - /** - * Decompression method for decompressing the compressed data - * read by read_packet - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - async decompress(config = defaultConfig) { - const compressionName = enums.read(enums.compression, this.algorithm); - const decompressionFn = decompress_fns[compressionName]; - if (!decompressionFn) { - throw new Error(`${compressionName} decompression not supported`); - } - - this.packets = await PacketList.fromBinary(decompressionFn(this.compressed), allowedPackets, config); - } - - /** - * Compress the packet data (member decompressedData) - */ - compress() { - const compressionName = enums.read(enums.compression, this.algorithm); - const compressionFn = compress_fns[compressionName]; - if (!compressionFn) { - throw new Error(`${compressionName} compression not supported`); - } - - this.compressed = compressionFn(this.packets.write(), this.deflateLevel); - } -} - -////////////////////////// -// // -// Helper functions // -// // -////////////////////////// - - -const nodeZlib = util.getNodeZlib(); - -function uncompressed(data) { - return data; -} - -function node_zlib(func, create, options = {}) { - return function (data) { - if (!util.isStream(data) || isArrayStream(data)) { - return fromAsync(() => readToEnd(data).then(data => { - return new Promise((resolve, reject) => { - func(data, options, (err, result) => { - if (err) return reject(err); - resolve(result); - }); - }); - })); - } - return nodeToWeb(webToNode(data).pipe(create(options))); - }; -} - -function pako_zlib(constructor, options = {}) { - return function(data) { - const obj = new constructor(options); - return transform(data, value => { - if (value.length) { - obj.push(value, Z_SYNC_FLUSH); - return obj.result; - } - }, () => { - if (constructor === Deflate) { - obj.push([], Z_FINISH); - return obj.result; - } - }); - }; -} - -function bzip2(func) { - return function(data) { - return fromAsync(async () => func(await readToEnd(data))); - }; -} - -const compress_fns = nodeZlib ? { - zip: /*#__PURE__*/ (compressed, level) => node_zlib(nodeZlib.deflateRaw, nodeZlib.createDeflateRaw, { level })(compressed), - zlib: /*#__PURE__*/ (compressed, level) => node_zlib(nodeZlib.deflate, nodeZlib.createDeflate, { level })(compressed) -} : { - zip: /*#__PURE__*/ (compressed, level) => pako_zlib(Deflate, { raw: true, level })(compressed), - zlib: /*#__PURE__*/ (compressed, level) => pako_zlib(Deflate, { level })(compressed) -}; - -const decompress_fns = nodeZlib ? { - uncompressed: uncompressed, - zip: /*#__PURE__*/ node_zlib(nodeZlib.inflateRaw, nodeZlib.createInflateRaw), - zlib: /*#__PURE__*/ node_zlib(nodeZlib.inflate, nodeZlib.createInflate), - bzip2: /*#__PURE__*/ bzip2(lib_4) -} : { - uncompressed: uncompressed, - zip: /*#__PURE__*/ pako_zlib(Inflate, { raw: true }), - zlib: /*#__PURE__*/ pako_zlib(Inflate), - bzip2: /*#__PURE__*/ bzip2(lib_4) -}; - -// GPG4Browsers - An OpenPGP implementation in javascript - -// A SEIP packet can contain the following packet types -const allowedPackets$1 = /*#__PURE__*/ util.constructAllowedPackets([ - LiteralDataPacket, - CompressedDataPacket, - OnePassSignaturePacket, - SignaturePacket -]); - -const VERSION$1 = 1; // A one-octet version number of the data packet. - -/** - * Implementation of the Sym. Encrypted Integrity Protected Data Packet (Tag 18) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.13|RFC4880 5.13}: - * The Symmetrically Encrypted Integrity Protected Data packet is - * a variant of the Symmetrically Encrypted Data packet. It is a new feature - * created for OpenPGP that addresses the problem of detecting a modification to - * encrypted data. It is used in combination with a Modification Detection Code - * packet. - */ -class SymEncryptedIntegrityProtectedDataPacket { - static get tag() { - return enums.packet.symEncryptedIntegrityProtectedData; - } - - constructor() { - this.version = VERSION$1; - this.encrypted = null; - this.packets = null; - } - - async read(bytes) { - await parse(bytes, async reader => { - const version = await reader.readByte(); - // - A one-octet version number. The only currently defined value is 1. - if (version !== VERSION$1) { - throw new UnsupportedError(`Version ${version} of the SEIP packet is unsupported.`); - } - - // - Encrypted data, the output of the selected symmetric-key cipher - // operating in Cipher Feedback mode with shift amount equal to the - // block size of the cipher (CFB-n where n is the block size). - this.encrypted = reader.remainder(); - }); - } - - write() { - return util.concat([new Uint8Array([VERSION$1]), this.encrypted]); - } - - /** - * Encrypt the payload in the packet. - * @param {enums.symmetric} sessionKeyAlgorithm - The symmetric encryption algorithm to use - * @param {Uint8Array} key - The key of cipher blocksize length to be used - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} - * @throws {Error} on encryption failure - * @async - */ - async encrypt(sessionKeyAlgorithm, key, config = defaultConfig) { - const { blockSize } = mod.getCipher(sessionKeyAlgorithm); - - let bytes = this.packets.write(); - if (isArrayStream(bytes)) bytes = await readToEnd(bytes); - const prefix = await mod.getPrefixRandom(sessionKeyAlgorithm); - const mdc = new Uint8Array([0xD3, 0x14]); // modification detection code packet - - const tohash = util.concat([prefix, bytes, mdc]); - const hash = await mod.hash.sha1(passiveClone(tohash)); - const plaintext = util.concat([tohash, hash]); - - this.encrypted = await mod.mode.cfb.encrypt(sessionKeyAlgorithm, key, plaintext, new Uint8Array(blockSize), config); - return true; - } - - /** - * Decrypts the encrypted data contained in the packet. - * @param {enums.symmetric} sessionKeyAlgorithm - The selected symmetric encryption algorithm to be used - * @param {Uint8Array} key - The key of cipher blocksize length to be used - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} - * @throws {Error} on decryption failure - * @async - */ - async decrypt(sessionKeyAlgorithm, key, config = defaultConfig) { - const { blockSize } = mod.getCipher(sessionKeyAlgorithm); - let encrypted = clone(this.encrypted); - if (isArrayStream(encrypted)) encrypted = await readToEnd(encrypted); - const decrypted = await mod.mode.cfb.decrypt(sessionKeyAlgorithm, key, encrypted, new Uint8Array(blockSize)); - - // there must be a modification detection code packet as the - // last packet and everything gets hashed except the hash itself - const realHash = slice(passiveClone(decrypted), -20); - const tohash = slice(decrypted, 0, -20); - const verifyHash = Promise.all([ - readToEnd(await mod.hash.sha1(passiveClone(tohash))), - readToEnd(realHash) - ]).then(([hash, mdc]) => { - if (!util.equalsUint8Array(hash, mdc)) { - throw new Error('Modification detected.'); - } - return new Uint8Array(); - }); - const bytes = slice(tohash, blockSize + 2); // Remove random prefix - let packetbytes = slice(bytes, 0, -2); // Remove MDC packet - packetbytes = concat([packetbytes, fromAsync(() => verifyHash)]); - if (!util.isStream(encrypted) || !config.allowUnauthenticatedStream) { - packetbytes = await readToEnd(packetbytes); - } - this.packets = await PacketList.fromBinary(packetbytes, allowedPackets$1, config); - return true; - } -} - -// OpenPGP.js - An OpenPGP implementation in javascript - -// An AEAD-encrypted Data packet can contain the following packet types -const allowedPackets$2 = /*#__PURE__*/ util.constructAllowedPackets([ - LiteralDataPacket, - CompressedDataPacket, - OnePassSignaturePacket, - SignaturePacket -]); - -const VERSION$2 = 1; // A one-octet version number of the data packet. - -/** - * Implementation of the Symmetrically Encrypted Authenticated Encryption with - * Additional Data (AEAD) Protected Data Packet - * - * {@link https://tools.ietf.org/html/draft-ford-openpgp-format-00#section-2.1}: - * AEAD Protected Data Packet - */ -class AEADEncryptedDataPacket { - static get tag() { - return enums.packet.aeadEncryptedData; - } - - constructor() { - this.version = VERSION$2; - /** @type {enums.symmetric} */ - this.cipherAlgorithm = null; - /** @type {enums.aead} */ - this.aeadAlgorithm = enums.aead.eax; - this.chunkSizeByte = null; - this.iv = null; - this.encrypted = null; - this.packets = null; - } - - /** - * Parse an encrypted payload of bytes in the order: version, IV, ciphertext (see specification) - * @param {Uint8Array | ReadableStream} bytes - * @throws {Error} on parsing failure - */ - async read(bytes) { - await parse(bytes, async reader => { - const version = await reader.readByte(); - if (version !== VERSION$2) { // The only currently defined value is 1. - throw new UnsupportedError(`Version ${version} of the AEAD-encrypted data packet is not supported.`); - } - this.cipherAlgorithm = await reader.readByte(); - this.aeadAlgorithm = await reader.readByte(); - this.chunkSizeByte = await reader.readByte(); - - const mode = mod.getAEADMode(this.aeadAlgorithm); - this.iv = await reader.readBytes(mode.ivLength); - this.encrypted = reader.remainder(); - }); - } - - /** - * Write the encrypted payload of bytes in the order: version, IV, ciphertext (see specification) - * @returns {Uint8Array | ReadableStream} The encrypted payload. - */ - write() { - return util.concat([new Uint8Array([this.version, this.cipherAlgorithm, this.aeadAlgorithm, this.chunkSizeByte]), this.iv, this.encrypted]); - } - - /** - * Decrypt the encrypted payload. - * @param {enums.symmetric} sessionKeyAlgorithm - The session key's cipher algorithm - * @param {Uint8Array} key - The session key used to encrypt the payload - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if decryption was not successful - * @async - */ - async decrypt(sessionKeyAlgorithm, key, config = defaultConfig) { - this.packets = await PacketList.fromBinary( - await this.crypt('decrypt', key, clone(this.encrypted)), - allowedPackets$2, - config - ); - } - - /** - * Encrypt the packet payload. - * @param {enums.symmetric} sessionKeyAlgorithm - The session key's cipher algorithm - * @param {Uint8Array} key - The session key used to encrypt the payload - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if encryption was not successful - * @async - */ - async encrypt(sessionKeyAlgorithm, key, config = defaultConfig) { - this.cipherAlgorithm = sessionKeyAlgorithm; - - const { ivLength } = mod.getAEADMode(this.aeadAlgorithm); - this.iv = await mod.random.getRandomBytes(ivLength); // generate new random IV - this.chunkSizeByte = config.aeadChunkSizeByte; - const data = this.packets.write(); - this.encrypted = await this.crypt('encrypt', key, data); - } - - /** - * En/decrypt the payload. - * @param {encrypt|decrypt} fn - Whether to encrypt or decrypt - * @param {Uint8Array} key - The session key used to en/decrypt the payload - * @param {Uint8Array | ReadableStream} data - The data to en/decrypt - * @returns {Promise>} - * @async - */ - async crypt(fn, key, data) { - const mode = mod.getAEADMode(this.aeadAlgorithm); - const modeInstance = await mode(this.cipherAlgorithm, key); - const tagLengthIfDecrypting = fn === 'decrypt' ? mode.tagLength : 0; - const tagLengthIfEncrypting = fn === 'encrypt' ? mode.tagLength : 0; - const chunkSize = 2 ** (this.chunkSizeByte + 6) + tagLengthIfDecrypting; // ((uint64_t)1 << (c + 6)) - const adataBuffer = new ArrayBuffer(21); - const adataArray = new Uint8Array(adataBuffer, 0, 13); - const adataTagArray = new Uint8Array(adataBuffer); - const adataView = new DataView(adataBuffer); - const chunkIndexArray = new Uint8Array(adataBuffer, 5, 8); - adataArray.set([0xC0 | AEADEncryptedDataPacket.tag, this.version, this.cipherAlgorithm, this.aeadAlgorithm, this.chunkSizeByte], 0); - let chunkIndex = 0; - let latestPromise = Promise.resolve(); - let cryptedBytes = 0; - let queuedBytes = 0; - const iv = this.iv; - return transformPair(data, async (readable, writable) => { - if (util.isStream(readable) !== 'array') { - const buffer = new TransformStream({}, { - highWaterMark: util.getHardwareConcurrency() * 2 ** (this.chunkSizeByte + 6), - size: array => array.length - }); - pipe(buffer.readable, writable); - writable = buffer.writable; - } - const reader = getReader(readable); - const writer = getWriter(writable); - try { - while (true) { - let chunk = await reader.readBytes(chunkSize + tagLengthIfDecrypting) || new Uint8Array(); - const finalChunk = chunk.subarray(chunk.length - tagLengthIfDecrypting); - chunk = chunk.subarray(0, chunk.length - tagLengthIfDecrypting); - let cryptedPromise; - let done; - if (!chunkIndex || chunk.length) { - reader.unshift(finalChunk); - cryptedPromise = modeInstance[fn](chunk, mode.getNonce(iv, chunkIndexArray), adataArray); - queuedBytes += chunk.length - tagLengthIfDecrypting + tagLengthIfEncrypting; - } else { - // After the last chunk, we either encrypt a final, empty - // data chunk to get the final authentication tag or - // validate that final authentication tag. - adataView.setInt32(13 + 4, cryptedBytes); // Should be setInt64(13, ...) - cryptedPromise = modeInstance[fn](finalChunk, mode.getNonce(iv, chunkIndexArray), adataTagArray); - queuedBytes += tagLengthIfEncrypting; - done = true; - } - cryptedBytes += chunk.length - tagLengthIfDecrypting; - // eslint-disable-next-line no-loop-func - latestPromise = latestPromise.then(() => cryptedPromise).then(async crypted => { - await writer.ready; - await writer.write(crypted); - queuedBytes -= crypted.length; - }).catch(err => writer.abort(err)); - if (done || queuedBytes > writer.desiredSize) { - await latestPromise; // Respect backpressure - } - if (!done) { - adataView.setInt32(5 + 4, ++chunkIndex); // Should be setInt64(5, ...) - } else { - await writer.close(); - break; - } - } - } catch (e) { - await writer.abort(e); - } - }); - } -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -const VERSION$3 = 3; - -/** - * Public-Key Encrypted Session Key Packets (Tag 1) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.1|RFC4880 5.1}: - * A Public-Key Encrypted Session Key packet holds the session key - * used to encrypt a message. Zero or more Public-Key Encrypted Session Key - * packets and/or Symmetric-Key Encrypted Session Key packets may precede a - * Symmetrically Encrypted Data Packet, which holds an encrypted message. The - * message is encrypted with the session key, and the session key is itself - * encrypted and stored in the Encrypted Session Key packet(s). The - * Symmetrically Encrypted Data Packet is preceded by one Public-Key Encrypted - * Session Key packet for each OpenPGP key to which the message is encrypted. - * The recipient of the message finds a session key that is encrypted to their - * public key, decrypts the session key, and then uses the session key to - * decrypt the message. - */ -class PublicKeyEncryptedSessionKeyPacket { - static get tag() { - return enums.packet.publicKeyEncryptedSessionKey; - } - - constructor() { - this.version = 3; - - this.publicKeyID = new KeyID(); - this.publicKeyAlgorithm = null; - - this.sessionKey = null; - /** - * Algorithm to encrypt the message with - * @type {enums.symmetric} - */ - this.sessionKeyAlgorithm = null; - - /** @type {Object} */ - this.encrypted = {}; - } - - /** - * Parsing function for a publickey encrypted session key packet (tag 1). - * - * @param {Uint8Array} bytes - Payload of a tag 1 packet - */ - read(bytes) { - this.version = bytes[0]; - if (this.version !== VERSION$3) { - throw new UnsupportedError(`Version ${this.version} of the PKESK packet is unsupported.`); - } - this.publicKeyID.read(bytes.subarray(1, bytes.length)); - this.publicKeyAlgorithm = bytes[9]; - this.encrypted = mod.parseEncSessionKeyParams(this.publicKeyAlgorithm, bytes.subarray(10)); - } - - /** - * Create a binary representation of a tag 1 packet - * - * @returns {Uint8Array} The Uint8Array representation. - */ - write() { - const arr = [ - new Uint8Array([this.version]), - this.publicKeyID.write(), - new Uint8Array([this.publicKeyAlgorithm]), - mod.serializeParams(this.publicKeyAlgorithm, this.encrypted) - ]; - - return util.concatUint8Array(arr); - } - - /** - * Encrypt session key packet - * @param {PublicKeyPacket} key - Public key - * @throws {Error} if encryption failed - * @async - */ - async encrypt(key) { - const data = util.concatUint8Array([ - new Uint8Array([enums.write(enums.symmetric, this.sessionKeyAlgorithm)]), - this.sessionKey, - util.writeChecksum(this.sessionKey) - ]); - const algo = enums.write(enums.publicKey, this.publicKeyAlgorithm); - this.encrypted = await mod.publicKeyEncrypt( - algo, key.publicParams, data, key.getFingerprintBytes()); - } - - /** - * Decrypts the session key (only for public key encrypted session key packets (tag 1) - * @param {SecretKeyPacket} key - decrypted private key - * @param {Object} [randomSessionKey] - Bogus session key to use in case of sensitive decryption error, or if the decrypted session key is of a different type/size. - * This is needed for constant-time processing. Expected object of the form: { sessionKey: Uint8Array, sessionKeyAlgorithm: enums.symmetric } - * @throws {Error} if decryption failed, unless `randomSessionKey` is given - * @async - */ - async decrypt(key, randomSessionKey) { - // check that session key algo matches the secret key algo - if (this.publicKeyAlgorithm !== key.algorithm) { - throw new Error('Decryption error'); - } - - const randomPayload = randomSessionKey ? util.concatUint8Array([ - new Uint8Array([randomSessionKey.sessionKeyAlgorithm]), - randomSessionKey.sessionKey, - util.writeChecksum(randomSessionKey.sessionKey) - ]) : null; - const decoded = await mod.publicKeyDecrypt(this.publicKeyAlgorithm, key.publicParams, key.privateParams, this.encrypted, key.getFingerprintBytes(), randomPayload); - const symmetricAlgoByte = decoded[0]; - const sessionKey = decoded.subarray(1, decoded.length - 2); - const checksum = decoded.subarray(decoded.length - 2); - const computedChecksum = util.writeChecksum(sessionKey); - const isValidChecksum = computedChecksum[0] === checksum[0] & computedChecksum[1] === checksum[1]; - - if (randomSessionKey) { - // We must not leak info about the validity of the decrypted checksum or cipher algo. - // The decrypted session key must be of the same algo and size as the random session key, otherwise we discard it and use the random data. - const isValidPayload = isValidChecksum & symmetricAlgoByte === randomSessionKey.sessionKeyAlgorithm & sessionKey.length === randomSessionKey.sessionKey.length; - this.sessionKeyAlgorithm = util.selectUint8(isValidPayload, symmetricAlgoByte, randomSessionKey.sessionKeyAlgorithm); - this.sessionKey = util.selectUint8Array(isValidPayload, sessionKey, randomSessionKey.sessionKey); - - } else { - const isValidPayload = isValidChecksum && enums.read(enums.symmetric, symmetricAlgoByte); - if (isValidPayload) { - this.sessionKey = sessionKey; - this.sessionKeyAlgorithm = symmetricAlgoByte; - } else { - throw new Error('Decryption error'); - } - } - } -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -class S2K { - /** - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - constructor(config = defaultConfig) { - /** - * Hash function identifier, or 0 for gnu-dummy keys - * @type {module:enums.hash | 0} - */ - this.algorithm = enums.hash.sha256; - /** - * enums.s2k identifier or 'gnu-dummy' - * @type {String} - */ - this.type = 'iterated'; - /** @type {Integer} */ - this.c = config.s2kIterationCountByte; - /** Eight bytes of salt in a binary string. - * @type {Uint8Array} - */ - this.salt = null; - } - - getCount() { - // Exponent bias, defined in RFC4880 - const expbias = 6; - - return (16 + (this.c & 15)) << ((this.c >> 4) + expbias); - } - - /** - * Parsing function for a string-to-key specifier ({@link https://tools.ietf.org/html/rfc4880#section-3.7|RFC 4880 3.7}). - * @param {Uint8Array} bytes - Payload of string-to-key specifier - * @returns {Integer} Actual length of the object. - */ - read(bytes) { - let i = 0; - this.type = enums.read(enums.s2k, bytes[i++]); - this.algorithm = bytes[i++]; - - switch (this.type) { - case 'simple': - break; - - case 'salted': - this.salt = bytes.subarray(i, i + 8); - i += 8; - break; - - case 'iterated': - this.salt = bytes.subarray(i, i + 8); - i += 8; - - // Octet 10: count, a one-octet, coded value - this.c = bytes[i++]; - break; - - case 'gnu': - if (util.uint8ArrayToString(bytes.subarray(i, i + 3)) === 'GNU') { - i += 3; // GNU - const gnuExtType = 1000 + bytes[i++]; - if (gnuExtType === 1001) { - this.type = 'gnu-dummy'; - // GnuPG extension mode 1001 -- don't write secret key at all - } else { - throw new Error('Unknown s2k gnu protection mode.'); - } - } else { - throw new Error('Unknown s2k type.'); - } - break; - - default: - throw new Error('Unknown s2k type.'); - } - - return i; - } - - /** - * Serializes s2k information - * @returns {Uint8Array} Binary representation of s2k. - */ - write() { - if (this.type === 'gnu-dummy') { - return new Uint8Array([101, 0, ...util.stringToUint8Array('GNU'), 1]); - } - const arr = [new Uint8Array([enums.write(enums.s2k, this.type), this.algorithm])]; - - switch (this.type) { - case 'simple': - break; - case 'salted': - arr.push(this.salt); - break; - case 'iterated': - arr.push(this.salt); - arr.push(new Uint8Array([this.c])); - break; - case 'gnu': - throw new Error('GNU s2k type not supported.'); - default: - throw new Error('Unknown s2k type.'); - } - - return util.concatUint8Array(arr); - } - - /** - * Produces a key using the specified passphrase and the defined - * hashAlgorithm - * @param {String} passphrase - Passphrase containing user input - * @returns {Promise} Produced key with a length corresponding to. - * hashAlgorithm hash length - * @async - */ - async produceKey(passphrase, numBytes) { - passphrase = util.encodeUTF8(passphrase); - - const arr = []; - let rlength = 0; - - let prefixlen = 0; - while (rlength < numBytes) { - let toHash; - switch (this.type) { - case 'simple': - toHash = util.concatUint8Array([new Uint8Array(prefixlen), passphrase]); - break; - case 'salted': - toHash = util.concatUint8Array([new Uint8Array(prefixlen), this.salt, passphrase]); - break; - case 'iterated': { - const data = util.concatUint8Array([this.salt, passphrase]); - let datalen = data.length; - const count = Math.max(this.getCount(), datalen); - toHash = new Uint8Array(prefixlen + count); - toHash.set(data, prefixlen); - for (let pos = prefixlen + datalen; pos < count; pos += datalen, datalen *= 2) { - toHash.copyWithin(pos, prefixlen, pos); - } - break; - } - case 'gnu': - throw new Error('GNU s2k type not supported.'); - default: - throw new Error('Unknown s2k type.'); - } - const result = await mod.hash.digest(this.algorithm, toHash); - arr.push(result); - rlength += result.length; - prefixlen++; - } - - return util.concatUint8Array(arr).subarray(0, numBytes); - } -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -/** - * Symmetric-Key Encrypted Session Key Packets (Tag 3) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.3|RFC4880 5.3}: - * The Symmetric-Key Encrypted Session Key packet holds the - * symmetric-key encryption of a session key used to encrypt a message. - * Zero or more Public-Key Encrypted Session Key packets and/or - * Symmetric-Key Encrypted Session Key packets may precede a - * Symmetrically Encrypted Data packet that holds an encrypted message. - * The message is encrypted with a session key, and the session key is - * itself encrypted and stored in the Encrypted Session Key packet or - * the Symmetric-Key Encrypted Session Key packet. - */ -class SymEncryptedSessionKeyPacket { - static get tag() { - return enums.packet.symEncryptedSessionKey; - } - - /** - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - constructor(config = defaultConfig) { - this.version = config.aeadProtect ? 5 : 4; - this.sessionKey = null; - /** - * Algorithm to encrypt the session key with - * @type {enums.symmetric} - */ - this.sessionKeyEncryptionAlgorithm = null; - /** - * Algorithm to encrypt the message with - * @type {enums.symmetric} - */ - this.sessionKeyAlgorithm = enums.symmetric.aes256; - /** - * AEAD mode to encrypt the session key with (if AEAD protection is enabled) - * @type {enums.aead} - */ - this.aeadAlgorithm = enums.write(enums.aead, config.preferredAEADAlgorithm); - this.encrypted = null; - this.s2k = null; - this.iv = null; - } - - /** - * Parsing function for a symmetric encrypted session key packet (tag 3). - * - * @param {Uint8Array} bytes - Payload of a tag 3 packet - */ - read(bytes) { - let offset = 0; - - // A one-octet version number. The only currently defined version is 4. - this.version = bytes[offset++]; - if (this.version !== 4 && this.version !== 5) { - throw new UnsupportedError(`Version ${this.version} of the SKESK packet is unsupported.`); - } - - // A one-octet number describing the symmetric algorithm used. - const algo = bytes[offset++]; - - if (this.version === 5) { - // A one-octet AEAD algorithm. - this.aeadAlgorithm = bytes[offset++]; - } - - // A string-to-key (S2K) specifier, length as defined above. - this.s2k = new S2K(); - offset += this.s2k.read(bytes.subarray(offset, bytes.length)); - - if (this.version === 5) { - const mode = mod.getAEADMode(this.aeadAlgorithm); - - // A starting initialization vector of size specified by the AEAD - // algorithm. - this.iv = bytes.subarray(offset, offset += mode.ivLength); - } - - // The encrypted session key itself, which is decrypted with the - // string-to-key object. This is optional in version 4. - if (this.version === 5 || offset < bytes.length) { - this.encrypted = bytes.subarray(offset, bytes.length); - this.sessionKeyEncryptionAlgorithm = algo; - } else { - this.sessionKeyAlgorithm = algo; - } - } - - /** - * Create a binary representation of a tag 3 packet - * - * @returns {Uint8Array} The Uint8Array representation. - */ - write() { - const algo = this.encrypted === null ? - this.sessionKeyAlgorithm : - this.sessionKeyEncryptionAlgorithm; - - let bytes; - - if (this.version === 5) { - bytes = util.concatUint8Array([new Uint8Array([this.version, algo, this.aeadAlgorithm]), this.s2k.write(), this.iv, this.encrypted]); - } else { - bytes = util.concatUint8Array([new Uint8Array([this.version, algo]), this.s2k.write()]); - - if (this.encrypted !== null) { - bytes = util.concatUint8Array([bytes, this.encrypted]); - } - } - - return bytes; - } - - /** - * Decrypts the session key with the given passphrase - * @param {String} passphrase - The passphrase in string form - * @throws {Error} if decryption was not successful - * @async - */ - async decrypt(passphrase) { - const algo = this.sessionKeyEncryptionAlgorithm !== null ? - this.sessionKeyEncryptionAlgorithm : - this.sessionKeyAlgorithm; - - const { blockSize, keySize } = mod.getCipher(algo); - const key = await this.s2k.produceKey(passphrase, keySize); - - if (this.version === 5) { - const mode = mod.getAEADMode(this.aeadAlgorithm); - const adata = new Uint8Array([0xC0 | SymEncryptedSessionKeyPacket.tag, this.version, this.sessionKeyEncryptionAlgorithm, this.aeadAlgorithm]); - const modeInstance = await mode(algo, key); - this.sessionKey = await modeInstance.decrypt(this.encrypted, this.iv, adata); - } else if (this.encrypted !== null) { - const decrypted = await mod.mode.cfb.decrypt(algo, key, this.encrypted, new Uint8Array(blockSize)); - - this.sessionKeyAlgorithm = enums.write(enums.symmetric, decrypted[0]); - this.sessionKey = decrypted.subarray(1, decrypted.length); - } else { - this.sessionKey = key; - } - } - - /** - * Encrypts the session key with the given passphrase - * @param {String} passphrase - The passphrase in string form - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if encryption was not successful - * @async - */ - async encrypt(passphrase, config = defaultConfig) { - const algo = this.sessionKeyEncryptionAlgorithm !== null ? - this.sessionKeyEncryptionAlgorithm : - this.sessionKeyAlgorithm; - - this.sessionKeyEncryptionAlgorithm = algo; - - this.s2k = new S2K(config); - this.s2k.salt = await mod.random.getRandomBytes(8); - - const { blockSize, keySize } = mod.getCipher(algo); - const encryptionKey = await this.s2k.produceKey(passphrase, keySize); - - if (this.sessionKey === null) { - this.sessionKey = await mod.generateSessionKey(this.sessionKeyAlgorithm); - } - - if (this.version === 5) { - const mode = mod.getAEADMode(this.aeadAlgorithm); - this.iv = await mod.random.getRandomBytes(mode.ivLength); // generate new random IV - const associatedData = new Uint8Array([0xC0 | SymEncryptedSessionKeyPacket.tag, this.version, this.sessionKeyEncryptionAlgorithm, this.aeadAlgorithm]); - const modeInstance = await mode(algo, encryptionKey); - this.encrypted = await modeInstance.encrypt(this.sessionKey, this.iv, associatedData); - } else { - const toEncrypt = util.concatUint8Array([ - new Uint8Array([this.sessionKeyAlgorithm]), - this.sessionKey - ]); - this.encrypted = await mod.mode.cfb.encrypt(algo, encryptionKey, toEncrypt, new Uint8Array(blockSize), config); - } - } -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -/** - * Implementation of the Key Material Packet (Tag 5,6,7,14) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.5|RFC4480 5.5}: - * A key material packet contains all the information about a public or - * private key. There are four variants of this packet type, and two - * major versions. - * - * A Public-Key packet starts a series of packets that forms an OpenPGP - * key (sometimes called an OpenPGP certificate). - */ -class PublicKeyPacket { - static get tag() { - return enums.packet.publicKey; - } - - /** - * @param {Date} [date] - Creation date - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - constructor(date = new Date(), config = defaultConfig) { - /** - * Packet version - * @type {Integer} - */ - this.version = config.v5Keys ? 5 : 4; - /** - * Key creation date. - * @type {Date} - */ - this.created = util.normalizeDate(date); - /** - * Public key algorithm. - * @type {enums.publicKey} - */ - this.algorithm = null; - /** - * Algorithm specific public params - * @type {Object} - */ - this.publicParams = null; - /** - * Time until expiration in days (V3 only) - * @type {Integer} - */ - this.expirationTimeV3 = 0; - /** - * Fingerprint bytes - * @type {Uint8Array} - */ - this.fingerprint = null; - /** - * KeyID - * @type {module:type/keyid~KeyID} - */ - this.keyID = null; - } - - /** - * Create a PublicKeyPacket from a SecretKeyPacket - * @param {SecretKeyPacket} secretKeyPacket - key packet to convert - * @returns {PublicKeyPacket} public key packet - * @static - */ - static fromSecretKeyPacket(secretKeyPacket) { - const keyPacket = new PublicKeyPacket(); - const { version, created, algorithm, publicParams, keyID, fingerprint } = secretKeyPacket; - keyPacket.version = version; - keyPacket.created = created; - keyPacket.algorithm = algorithm; - keyPacket.publicParams = publicParams; - keyPacket.keyID = keyID; - keyPacket.fingerprint = fingerprint; - return keyPacket; - } - - /** - * Internal Parser for public keys as specified in {@link https://tools.ietf.org/html/rfc4880#section-5.5.2|RFC 4880 section 5.5.2 Public-Key Packet Formats} - * @param {Uint8Array} bytes - Input array to read the packet from - * @returns {Object} This object with attributes set by the parser - * @async - */ - async read(bytes) { - let pos = 0; - // A one-octet version number (3, 4 or 5). - this.version = bytes[pos++]; - - if (this.version === 4 || this.version === 5) { - // - A four-octet number denoting the time that the key was created. - this.created = util.readDate(bytes.subarray(pos, pos + 4)); - pos += 4; - - // - A one-octet number denoting the public-key algorithm of this key. - this.algorithm = bytes[pos++]; - - if (this.version === 5) { - // - A four-octet scalar octet count for the following key material. - pos += 4; - } - - // - A series of values comprising the key material. - try { - const { read, publicParams } = mod.parsePublicKeyParams(this.algorithm, bytes.subarray(pos)); - this.publicParams = publicParams; - pos += read; - } catch (err) { - throw new Error('Error reading MPIs'); - } - - // we set the fingerprint and keyID already to make it possible to put together the key packets directly in the Key constructor - await this.computeFingerprintAndKeyID(); - return pos; - } - throw new UnsupportedError(`Version ${this.version} of the key packet is unsupported.`); - } - - /** - * Creates an OpenPGP public key packet for the given key. - * @returns {Uint8Array} Bytes encoding the public key OpenPGP packet. - */ - write() { - const arr = []; - // Version - arr.push(new Uint8Array([this.version])); - arr.push(util.writeDate(this.created)); - // A one-octet number denoting the public-key algorithm of this key - arr.push(new Uint8Array([this.algorithm])); - - const params = mod.serializeParams(this.algorithm, this.publicParams); - if (this.version === 5) { - // A four-octet scalar octet count for the following key material - arr.push(util.writeNumber(params.length, 4)); - } - // Algorithm-specific params - arr.push(params); - return util.concatUint8Array(arr); - } - - /** - * Write packet in order to be hashed; either for a signature or a fingerprint - * @param {Integer} version - target version of signature or key - */ - writeForHash(version) { - const bytes = this.writePublicKey(); - - if (version === 5) { - return util.concatUint8Array([new Uint8Array([0x9A]), util.writeNumber(bytes.length, 4), bytes]); - } - return util.concatUint8Array([new Uint8Array([0x99]), util.writeNumber(bytes.length, 2), bytes]); - } - - /** - * Check whether secret-key data is available in decrypted form. Returns null for public keys. - * @returns {Boolean|null} - */ - isDecrypted() { - return null; - } - - /** - * Returns the creation time of the key - * @returns {Date} - */ - getCreationTime() { - return this.created; - } - - /** - * Return the key ID of the key - * @returns {module:type/keyid~KeyID} The 8-byte key ID - */ - getKeyID() { - return this.keyID; - } - - /** - * Computes and set the key ID and fingerprint of the key - * @async - */ - async computeFingerprintAndKeyID() { - await this.computeFingerprint(); - this.keyID = new KeyID(); - - if (this.version === 5) { - this.keyID.read(this.fingerprint.subarray(0, 8)); - } else if (this.version === 4) { - this.keyID.read(this.fingerprint.subarray(12, 20)); - } else { - throw new Error('Unsupported key version'); - } - } - - /** - * Computes and set the fingerprint of the key - */ - async computeFingerprint() { - const toHash = this.writeForHash(this.version); - - if (this.version === 5) { - this.fingerprint = await mod.hash.sha256(toHash); - } else if (this.version === 4) { - this.fingerprint = await mod.hash.sha1(toHash); - } else { - throw new Error('Unsupported key version'); - } - } - - /** - * Returns the fingerprint of the key, as an array of bytes - * @returns {Uint8Array} A Uint8Array containing the fingerprint - */ - getFingerprintBytes() { - return this.fingerprint; - } - - /** - * Calculates and returns the fingerprint of the key, as a string - * @returns {String} A string containing the fingerprint in lowercase hex - */ - getFingerprint() { - return util.uint8ArrayToHex(this.getFingerprintBytes()); - } - - /** - * Calculates whether two keys have the same fingerprint without actually calculating the fingerprint - * @returns {Boolean} Whether the two keys have the same version and public key data. - */ - hasSameFingerprintAs(other) { - return this.version === other.version && util.equalsUint8Array(this.writePublicKey(), other.writePublicKey()); - } - - /** - * Returns algorithm information - * @returns {Object} An object of the form {algorithm: String, bits:int, curve:String}. - */ - getAlgorithmInfo() { - const result = {}; - result.algorithm = enums.read(enums.publicKey, this.algorithm); - // RSA, DSA or ElGamal public modulo - const modulo = this.publicParams.n || this.publicParams.p; - if (modulo) { - result.bits = util.uint8ArrayBitLength(modulo); - } else { - result.curve = this.publicParams.oid.getName(); - } - return result; - } -} - -/** - * Alias of read() - * @see PublicKeyPacket#read - */ -PublicKeyPacket.prototype.readPublicKey = PublicKeyPacket.prototype.read; - -/** - * Alias of write() - * @see PublicKeyPacket#write - */ -PublicKeyPacket.prototype.writePublicKey = PublicKeyPacket.prototype.write; - -// GPG4Browsers - An OpenPGP implementation in javascript - -// A SE packet can contain the following packet types -const allowedPackets$3 = /*#__PURE__*/ util.constructAllowedPackets([ - LiteralDataPacket, - CompressedDataPacket, - OnePassSignaturePacket, - SignaturePacket -]); - -/** - * Implementation of the Symmetrically Encrypted Data Packet (Tag 9) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.7|RFC4880 5.7}: - * The Symmetrically Encrypted Data packet contains data encrypted with a - * symmetric-key algorithm. When it has been decrypted, it contains other - * packets (usually a literal data packet or compressed data packet, but in - * theory other Symmetrically Encrypted Data packets or sequences of packets - * that form whole OpenPGP messages). - */ -class SymmetricallyEncryptedDataPacket { - static get tag() { - return enums.packet.symmetricallyEncryptedData; - } - - constructor() { - /** - * Encrypted secret-key data - */ - this.encrypted = null; - /** - * Decrypted packets contained within. - * @type {PacketList} - */ - this.packets = null; - } - - read(bytes) { - this.encrypted = bytes; - } - - write() { - return this.encrypted; - } - - /** - * Decrypt the symmetrically-encrypted packet data - * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. - * @param {module:enums.symmetric} sessionKeyAlgorithm - Symmetric key algorithm to use - * @param {Uint8Array} key - The key of cipher blocksize length to be used - * @param {Object} [config] - Full configuration, defaults to openpgp.config - - * @throws {Error} if decryption was not successful - * @async - */ - async decrypt(sessionKeyAlgorithm, key, config = defaultConfig) { - // If MDC errors are not being ignored, all missing MDC packets in symmetrically encrypted data should throw an error - if (!config.allowUnauthenticatedMessages) { - throw new Error('Message is not authenticated.'); - } - - const { blockSize } = mod.getCipher(sessionKeyAlgorithm); - const encrypted = await readToEnd(clone(this.encrypted)); - const decrypted = await mod.mode.cfb.decrypt(sessionKeyAlgorithm, key, - encrypted.subarray(blockSize + 2), - encrypted.subarray(2, blockSize + 2) - ); - - this.packets = await PacketList.fromBinary(decrypted, allowedPackets$3, config); - } - - /** - * Encrypt the symmetrically-encrypted packet data - * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. - * @param {module:enums.symmetric} sessionKeyAlgorithm - Symmetric key algorithm to use - * @param {Uint8Array} key - The key of cipher blocksize length to be used - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if encryption was not successful - * @async - */ - async encrypt(sessionKeyAlgorithm, key, config = defaultConfig) { - const data = this.packets.write(); - const { blockSize } = mod.getCipher(sessionKeyAlgorithm); - - const prefix = await mod.getPrefixRandom(sessionKeyAlgorithm); - const FRE = await mod.mode.cfb.encrypt(sessionKeyAlgorithm, key, prefix, new Uint8Array(blockSize), config); - const ciphertext = await mod.mode.cfb.encrypt(sessionKeyAlgorithm, key, data, FRE.subarray(2), config); - this.encrypted = util.concat([FRE, ciphertext]); - } -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -/** - * Implementation of the strange "Marker packet" (Tag 10) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.8|RFC4880 5.8}: - * An experimental version of PGP used this packet as the Literal - * packet, but no released version of PGP generated Literal packets with this - * tag. With PGP 5.x, this packet has been reassigned and is reserved for use as - * the Marker packet. - * - * The body of this packet consists of: - * The three octets 0x50, 0x47, 0x50 (which spell "PGP" in UTF-8). - * - * Such a packet MUST be ignored when received. It may be placed at the - * beginning of a message that uses features not available in PGP - * version 2.6 in order to cause that version to report that newer - * software is necessary to process the message. - */ -class MarkerPacket { - static get tag() { - return enums.packet.marker; - } - - /** - * Parsing function for a marker data packet (tag 10). - * @param {Uint8Array} bytes - Payload of a tag 10 packet - * @returns {Boolean} whether the packet payload contains "PGP" - */ - read(bytes) { - if (bytes[0] === 0x50 && // P - bytes[1] === 0x47 && // G - bytes[2] === 0x50) { // P - return true; - } - return false; - } - - write() { - return new Uint8Array([0x50, 0x47, 0x50]); - } -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -/** - * A Public-Subkey packet (tag 14) has exactly the same format as a - * Public-Key packet, but denotes a subkey. One or more subkeys may be - * associated with a top-level key. By convention, the top-level key - * provides signature services, and the subkeys provide encryption - * services. - * @extends PublicKeyPacket - */ -class PublicSubkeyPacket extends PublicKeyPacket { - static get tag() { - return enums.packet.publicSubkey; - } - - /** - * @param {Date} [date] - Creation date - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - // eslint-disable-next-line no-useless-constructor - constructor(date, config) { - super(date, config); - } - - /** - * Create a PublicSubkeyPacket from a SecretSubkeyPacket - * @param {SecretSubkeyPacket} secretSubkeyPacket - subkey packet to convert - * @returns {SecretSubkeyPacket} public key packet - * @static - */ - static fromSecretSubkeyPacket(secretSubkeyPacket) { - const keyPacket = new PublicSubkeyPacket(); - const { version, created, algorithm, publicParams, keyID, fingerprint } = secretSubkeyPacket; - keyPacket.version = version; - keyPacket.created = created; - keyPacket.algorithm = algorithm; - keyPacket.publicParams = publicParams; - keyPacket.keyID = keyID; - keyPacket.fingerprint = fingerprint; - return keyPacket; - } -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -/** - * Implementation of the User Attribute Packet (Tag 17) - * - * The User Attribute packet is a variation of the User ID packet. It - * is capable of storing more types of data than the User ID packet, - * which is limited to text. Like the User ID packet, a User Attribute - * packet may be certified by the key owner ("self-signed") or any other - * key owner who cares to certify it. Except as noted, a User Attribute - * packet may be used anywhere that a User ID packet may be used. - * - * While User Attribute packets are not a required part of the OpenPGP - * standard, implementations SHOULD provide at least enough - * compatibility to properly handle a certification signature on the - * User Attribute packet. A simple way to do this is by treating the - * User Attribute packet as a User ID packet with opaque contents, but - * an implementation may use any method desired. - */ -class UserAttributePacket { - static get tag() { - return enums.packet.userAttribute; - } - - constructor() { - this.attributes = []; - } - - /** - * parsing function for a user attribute packet (tag 17). - * @param {Uint8Array} input - Payload of a tag 17 packet - */ - read(bytes) { - let i = 0; - while (i < bytes.length) { - const len = readSimpleLength(bytes.subarray(i, bytes.length)); - i += len.offset; - - this.attributes.push(util.uint8ArrayToString(bytes.subarray(i, i + len.len))); - i += len.len; - } - } - - /** - * Creates a binary representation of the user attribute packet - * @returns {Uint8Array} String representation. - */ - write() { - const arr = []; - for (let i = 0; i < this.attributes.length; i++) { - arr.push(writeSimpleLength(this.attributes[i].length)); - arr.push(util.stringToUint8Array(this.attributes[i])); - } - return util.concatUint8Array(arr); - } - - /** - * Compare for equality - * @param {UserAttributePacket} usrAttr - * @returns {Boolean} True if equal. - */ - equals(usrAttr) { - if (!usrAttr || !(usrAttr instanceof UserAttributePacket)) { - return false; - } - return this.attributes.every(function(attr, index) { - return attr === usrAttr.attributes[index]; - }); - } -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -/** - * A Secret-Key packet contains all the information that is found in a - * Public-Key packet, including the public-key material, but also - * includes the secret-key material after all the public-key fields. - * @extends PublicKeyPacket - */ -class SecretKeyPacket extends PublicKeyPacket { - static get tag() { - return enums.packet.secretKey; - } - - /** - * @param {Date} [date] - Creation date - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - constructor(date = new Date(), config = defaultConfig) { - super(date, config); - /** - * Secret-key data - */ - this.keyMaterial = null; - /** - * Indicates whether secret-key data is encrypted. `this.isEncrypted === false` means data is available in decrypted form. - */ - this.isEncrypted = null; - /** - * S2K usage - * @type {enums.symmetric} - */ - this.s2kUsage = 0; - /** - * S2K object - * @type {type/s2k} - */ - this.s2k = null; - /** - * Symmetric algorithm to encrypt the key with - * @type {enums.symmetric} - */ - this.symmetric = null; - /** - * AEAD algorithm to encrypt the key with (if AEAD protection is enabled) - * @type {enums.aead} - */ - this.aead = null; - /** - * Decrypted private parameters, referenced by name - * @type {Object} - */ - this.privateParams = null; - } - - // 5.5.3. Secret-Key Packet Formats - - /** - * Internal parser for private keys as specified in - * {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.5.3|RFC4880bis-04 section 5.5.3} - * @param {Uint8Array} bytes - Input string to read the packet from - * @async - */ - async read(bytes) { - // - A Public-Key or Public-Subkey packet, as described above. - let i = await this.readPublicKey(bytes); - - // - One octet indicating string-to-key usage conventions. Zero - // indicates that the secret-key data is not encrypted. 255 or 254 - // indicates that a string-to-key specifier is being given. Any - // other value is a symmetric-key encryption algorithm identifier. - this.s2kUsage = bytes[i++]; - - // - Only for a version 5 packet, a one-octet scalar octet count of - // the next 4 optional fields. - if (this.version === 5) { - i++; - } - - // - [Optional] If string-to-key usage octet was 255, 254, or 253, a - // one-octet symmetric encryption algorithm. - if (this.s2kUsage === 255 || this.s2kUsage === 254 || this.s2kUsage === 253) { - this.symmetric = bytes[i++]; - - // - [Optional] If string-to-key usage octet was 253, a one-octet - // AEAD algorithm. - if (this.s2kUsage === 253) { - this.aead = bytes[i++]; - } - - // - [Optional] If string-to-key usage octet was 255, 254, or 253, a - // string-to-key specifier. The length of the string-to-key - // specifier is implied by its type, as described above. - this.s2k = new S2K(); - i += this.s2k.read(bytes.subarray(i, bytes.length)); - - if (this.s2k.type === 'gnu-dummy') { - return; - } - } else if (this.s2kUsage) { - this.symmetric = this.s2kUsage; - } - - // - [Optional] If secret data is encrypted (string-to-key usage octet - // not zero), an Initial Vector (IV) of the same length as the - // cipher's block size. - if (this.s2kUsage) { - this.iv = bytes.subarray( - i, - i + mod.getCipher(this.symmetric).blockSize - ); - - i += this.iv.length; - } - - // - Only for a version 5 packet, a four-octet scalar octet count for - // the following key material. - if (this.version === 5) { - i += 4; - } - - // - Plain or encrypted multiprecision integers comprising the secret - // key data. These algorithm-specific fields are as described - // below. - this.keyMaterial = bytes.subarray(i); - this.isEncrypted = !!this.s2kUsage; - - if (!this.isEncrypted) { - const cleartext = this.keyMaterial.subarray(0, -2); - if (!util.equalsUint8Array(util.writeChecksum(cleartext), this.keyMaterial.subarray(-2))) { - throw new Error('Key checksum mismatch'); - } - try { - const { privateParams } = mod.parsePrivateKeyParams(this.algorithm, cleartext, this.publicParams); - this.privateParams = privateParams; - } catch (err) { - throw new Error('Error reading MPIs'); - } - } - } - - /** - * Creates an OpenPGP key packet for the given key. - * @returns {Uint8Array} A string of bytes containing the secret key OpenPGP packet. - */ - write() { - const arr = [this.writePublicKey()]; - - arr.push(new Uint8Array([this.s2kUsage])); - - const optionalFieldsArr = []; - // - [Optional] If string-to-key usage octet was 255, 254, or 253, a - // one- octet symmetric encryption algorithm. - if (this.s2kUsage === 255 || this.s2kUsage === 254 || this.s2kUsage === 253) { - optionalFieldsArr.push(this.symmetric); - - // - [Optional] If string-to-key usage octet was 253, a one-octet - // AEAD algorithm. - if (this.s2kUsage === 253) { - optionalFieldsArr.push(this.aead); - } - - // - [Optional] If string-to-key usage octet was 255, 254, or 253, a - // string-to-key specifier. The length of the string-to-key - // specifier is implied by its type, as described above. - optionalFieldsArr.push(...this.s2k.write()); - } - - // - [Optional] If secret data is encrypted (string-to-key usage octet - // not zero), an Initial Vector (IV) of the same length as the - // cipher's block size. - if (this.s2kUsage && this.s2k.type !== 'gnu-dummy') { - optionalFieldsArr.push(...this.iv); - } - - if (this.version === 5) { - arr.push(new Uint8Array([optionalFieldsArr.length])); - } - arr.push(new Uint8Array(optionalFieldsArr)); - - if (!this.isDummy()) { - if (!this.s2kUsage) { - this.keyMaterial = mod.serializeParams(this.algorithm, this.privateParams); - } - - if (this.version === 5) { - arr.push(util.writeNumber(this.keyMaterial.length, 4)); - } - arr.push(this.keyMaterial); - - if (!this.s2kUsage) { - arr.push(util.writeChecksum(this.keyMaterial)); - } - } - - return util.concatUint8Array(arr); - } - - /** - * Check whether secret-key data is available in decrypted form. - * Returns false for gnu-dummy keys and null for public keys. - * @returns {Boolean|null} - */ - isDecrypted() { - return this.isEncrypted === false; - } - - /** - * Check whether this is a gnu-dummy key - * @returns {Boolean} - */ - isDummy() { - return !!(this.s2k && this.s2k.type === 'gnu-dummy'); - } - - /** - * Remove private key material, converting the key to a dummy one. - * The resulting key cannot be used for signing/decrypting but can still verify signatures. - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - makeDummy(config = defaultConfig) { - if (this.isDummy()) { - return; - } - if (this.isDecrypted()) { - this.clearPrivateParams(); - } - this.isEncrypted = null; - this.keyMaterial = null; - this.s2k = new S2K(config); - this.s2k.algorithm = 0; - this.s2k.c = 0; - this.s2k.type = 'gnu-dummy'; - this.s2kUsage = 254; - this.symmetric = enums.symmetric.aes256; - } - - /** - * Encrypt the payload. By default, we use aes256 and iterated, salted string - * to key specifier. If the key is in a decrypted state (isEncrypted === false) - * and the passphrase is empty or undefined, the key will be set as not encrypted. - * This can be used to remove passphrase protection after calling decrypt(). - * @param {String} passphrase - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if encryption was not successful - * @async - */ - async encrypt(passphrase, config = defaultConfig) { - if (this.isDummy()) { - return; - } - - if (!this.isDecrypted()) { - throw new Error('Key packet is already encrypted'); - } - - if (this.isDecrypted() && !passphrase) { - this.s2kUsage = 0; - return; - } else if (!passphrase) { - throw new Error('The key must be decrypted before removing passphrase protection.'); - } - - this.s2k = new S2K(config); - this.s2k.salt = await mod.random.getRandomBytes(8); - const cleartext = mod.serializeParams(this.algorithm, this.privateParams); - this.symmetric = enums.symmetric.aes256; - const key = await produceEncryptionKey(this.s2k, passphrase, this.symmetric); - - const { blockSize } = mod.getCipher(this.symmetric); - this.iv = await mod.random.getRandomBytes(blockSize); - - if (config.aeadProtect) { - this.s2kUsage = 253; - this.aead = enums.aead.eax; - const mode = mod.getAEADMode(this.aead); - const modeInstance = await mode(this.symmetric, key); - this.keyMaterial = await modeInstance.encrypt(cleartext, this.iv.subarray(0, mode.ivLength), new Uint8Array()); - } else { - this.s2kUsage = 254; - this.keyMaterial = await mod.mode.cfb.encrypt(this.symmetric, key, util.concatUint8Array([ - cleartext, - await mod.hash.sha1(cleartext, config) - ]), this.iv, config); - } - } - - /** - * Decrypts the private key params which are needed to use the key. - * Successful decryption does not imply key integrity, call validate() to confirm that. - * {@link SecretKeyPacket.isDecrypted} should be false, as - * otherwise calls to this function will throw an error. - * @param {String} passphrase - The passphrase for this private key as string - * @throws {Error} if the key is already decrypted, or if decryption was not successful - * @async - */ - async decrypt(passphrase) { - if (this.isDummy()) { - return false; - } - - if (this.isDecrypted()) { - throw new Error('Key packet is already decrypted.'); - } - - let key; - if (this.s2kUsage === 254 || this.s2kUsage === 253) { - key = await produceEncryptionKey(this.s2k, passphrase, this.symmetric); - } else if (this.s2kUsage === 255) { - throw new Error('Encrypted private key is authenticated using an insecure two-byte hash'); - } else { - throw new Error('Private key is encrypted using an insecure S2K function: unsalted MD5'); - } - - let cleartext; - if (this.s2kUsage === 253) { - const mode = mod.getAEADMode(this.aead); - const modeInstance = await mode(this.symmetric, key); - try { - cleartext = await modeInstance.decrypt(this.keyMaterial, this.iv.subarray(0, mode.ivLength), new Uint8Array()); - } catch (err) { - if (err.message === 'Authentication tag mismatch') { - throw new Error('Incorrect key passphrase: ' + err.message); - } - throw err; - } - } else { - const cleartextWithHash = await mod.mode.cfb.decrypt(this.symmetric, key, this.keyMaterial, this.iv); - - cleartext = cleartextWithHash.subarray(0, -20); - const hash = await mod.hash.sha1(cleartext); - - if (!util.equalsUint8Array(hash, cleartextWithHash.subarray(-20))) { - throw new Error('Incorrect key passphrase'); - } - } - - try { - const { privateParams } = mod.parsePrivateKeyParams(this.algorithm, cleartext, this.publicParams); - this.privateParams = privateParams; - } catch (err) { - throw new Error('Error reading MPIs'); - } - this.isEncrypted = false; - this.keyMaterial = null; - this.s2kUsage = 0; - } - - /** - * Checks that the key parameters are consistent - * @throws {Error} if validation was not successful - * @async - */ - async validate() { - if (this.isDummy()) { - return; - } - - if (!this.isDecrypted()) { - throw new Error('Key is not decrypted'); - } - - let validParams; - try { - // this can throw if some parameters are undefined - validParams = await mod.validateParams(this.algorithm, this.publicParams, this.privateParams); - } catch (_) { - validParams = false; - } - if (!validParams) { - throw new Error('Key is invalid'); - } - } - - async generate(bits, curve) { - const { privateParams, publicParams } = await mod.generateParams(this.algorithm, bits, curve); - this.privateParams = privateParams; - this.publicParams = publicParams; - this.isEncrypted = false; - } - - /** - * Clear private key parameters - */ - clearPrivateParams() { - if (this.isDummy()) { - return; - } - - Object.keys(this.privateParams).forEach(name => { - const param = this.privateParams[name]; - param.fill(0); - delete this.privateParams[name]; - }); - this.privateParams = null; - this.isEncrypted = true; - } -} - -async function produceEncryptionKey(s2k, passphrase, algorithm) { - const { keySize } = mod.getCipher(algorithm); - return s2k.produceKey(passphrase, keySize); -} - -var emailAddresses = createCommonjsModule(function (module) { -// email-addresses.js - RFC 5322 email address parser -// v 3.1.0 -// -// http://tools.ietf.org/html/rfc5322 -// -// This library does not validate email addresses. -// emailAddresses attempts to parse addresses using the (fairly liberal) -// grammar specified in RFC 5322. -// -// email-addresses returns { -// ast: , -// addresses: [{ -// node: , -// name: , -// address: , -// local: , -// domain: -// }, ...] -// } -// -// emailAddresses.parseOneAddress and emailAddresses.parseAddressList -// work as you might expect. Try it out. -// -// Many thanks to Dominic Sayers and his documentation on the is_email function, -// http://code.google.com/p/isemail/ , which helped greatly in writing this parser. - -(function (global) { - -function parse5322(opts) { - - // tokenizing functions - - function inStr() { return pos < len; } - function curTok() { return parseString[pos]; } - function getPos() { return pos; } - function setPos(i) { pos = i; } - function nextTok() { pos += 1; } - function initialize() { - pos = 0; - len = parseString.length; - } - - // parser helper functions - - function o(name, value) { - return { - name: name, - tokens: value || "", - semantic: value || "", - children: [] - }; - } - - function wrap(name, ast) { - var n; - if (ast === null) { return null; } - n = o(name); - n.tokens = ast.tokens; - n.semantic = ast.semantic; - n.children.push(ast); - return n; - } - - function add(parent, child) { - if (child !== null) { - parent.tokens += child.tokens; - parent.semantic += child.semantic; - } - parent.children.push(child); - return parent; - } - - function compareToken(fxnCompare) { - var tok; - if (!inStr()) { return null; } - tok = curTok(); - if (fxnCompare(tok)) { - nextTok(); - return o('token', tok); - } - return null; - } - - function literal(lit) { - return function literalFunc() { - return wrap('literal', compareToken(function (tok) { - return tok === lit; - })); - }; - } - - function and() { - var args = arguments; - return function andFunc() { - var i, s, result, start; - start = getPos(); - s = o('and'); - for (i = 0; i < args.length; i += 1) { - result = args[i](); - if (result === null) { - setPos(start); - return null; - } - add(s, result); - } - return s; - }; - } - - function or() { - var args = arguments; - return function orFunc() { - var i, result, start; - start = getPos(); - for (i = 0; i < args.length; i += 1) { - result = args[i](); - if (result !== null) { - return result; - } - setPos(start); - } - return null; - }; - } - - function opt(prod) { - return function optFunc() { - var result, start; - start = getPos(); - result = prod(); - if (result !== null) { - return result; - } - else { - setPos(start); - return o('opt'); - } - }; - } - - function invis(prod) { - return function invisFunc() { - var result = prod(); - if (result !== null) { - result.semantic = ""; - } - return result; - }; - } - - function colwsp(prod) { - return function collapseSemanticWhitespace() { - var result = prod(); - if (result !== null && result.semantic.length > 0) { - result.semantic = " "; - } - return result; - }; - } - - function star(prod, minimum) { - return function starFunc() { - var s, result, count, start, min; - start = getPos(); - s = o('star'); - count = 0; - min = minimum === undefined ? 0 : minimum; - while ((result = prod()) !== null) { - count = count + 1; - add(s, result); - } - if (count >= min) { - return s; - } - else { - setPos(start); - return null; - } - }; - } - - // One expects names to get normalized like this: - // " First Last " -> "First Last" - // "First Last" -> "First Last" - // "First Last" -> "First Last" - function collapseWhitespace(s) { - return s.replace(/([ \t]|\r\n)+/g, ' ').replace(/^\s*/, '').replace(/\s*$/, ''); - } - - // UTF-8 pseudo-production (RFC 6532) - // RFC 6532 extends RFC 5322 productions to include UTF-8 - // using the following productions: - // UTF8-non-ascii = UTF8-2 / UTF8-3 / UTF8-4 - // UTF8-2 = - // UTF8-3 = - // UTF8-4 = - // - // For reference, the extended RFC 5322 productions are: - // VCHAR =/ UTF8-non-ascii - // ctext =/ UTF8-non-ascii - // atext =/ UTF8-non-ascii - // qtext =/ UTF8-non-ascii - // dtext =/ UTF8-non-ascii - function isUTF8NonAscii(tok) { - // In JavaScript, we just deal directly with Unicode code points, - // so we aren't checking individual bytes for UTF-8 encoding. - // Just check that the character is non-ascii. - return tok.charCodeAt(0) >= 128; - } - - - // common productions (RFC 5234) - // http://tools.ietf.org/html/rfc5234 - // B.1. Core Rules - - // CR = %x0D - // ; carriage return - function cr() { return wrap('cr', literal('\r')()); } - - // CRLF = CR LF - // ; Internet standard newline - function crlf() { return wrap('crlf', and(cr, lf)()); } - - // DQUOTE = %x22 - // ; " (Double Quote) - function dquote() { return wrap('dquote', literal('"')()); } - - // HTAB = %x09 - // ; horizontal tab - function htab() { return wrap('htab', literal('\t')()); } - - // LF = %x0A - // ; linefeed - function lf() { return wrap('lf', literal('\n')()); } - - // SP = %x20 - function sp() { return wrap('sp', literal(' ')()); } - - // VCHAR = %x21-7E - // ; visible (printing) characters - function vchar() { - return wrap('vchar', compareToken(function vcharFunc(tok) { - var code = tok.charCodeAt(0); - var accept = (0x21 <= code && code <= 0x7E); - if (opts.rfc6532) { - accept = accept || isUTF8NonAscii(tok); - } - return accept; - })); - } - - // WSP = SP / HTAB - // ; white space - function wsp() { return wrap('wsp', or(sp, htab)()); } - - - // email productions (RFC 5322) - // http://tools.ietf.org/html/rfc5322 - // 3.2.1. Quoted characters - - // quoted-pair = ("\" (VCHAR / WSP)) / obs-qp - function quotedPair() { - var qp = wrap('quoted-pair', - or( - and(literal('\\'), or(vchar, wsp)), - obsQP - )()); - if (qp === null) { return null; } - // a quoted pair will be two characters, and the "\" character - // should be semantically "invisible" (RFC 5322 3.2.1) - qp.semantic = qp.semantic[1]; - return qp; - } - - // 3.2.2. Folding White Space and Comments - - // FWS = ([*WSP CRLF] 1*WSP) / obs-FWS - function fws() { - return wrap('fws', or( - obsFws, - and( - opt(and( - star(wsp), - invis(crlf) - )), - star(wsp, 1) - ) - )()); - } - - // ctext = %d33-39 / ; Printable US-ASCII - // %d42-91 / ; characters not including - // %d93-126 / ; "(", ")", or "\" - // obs-ctext - function ctext() { - return wrap('ctext', or( - function ctextFunc1() { - return compareToken(function ctextFunc2(tok) { - var code = tok.charCodeAt(0); - var accept = - (33 <= code && code <= 39) || - (42 <= code && code <= 91) || - (93 <= code && code <= 126); - if (opts.rfc6532) { - accept = accept || isUTF8NonAscii(tok); - } - return accept; - }); - }, - obsCtext - )()); - } - - // ccontent = ctext / quoted-pair / comment - function ccontent() { - return wrap('ccontent', or(ctext, quotedPair, comment)()); - } - - // comment = "(" *([FWS] ccontent) [FWS] ")" - function comment() { - return wrap('comment', and( - literal('('), - star(and(opt(fws), ccontent)), - opt(fws), - literal(')') - )()); - } - - // CFWS = (1*([FWS] comment) [FWS]) / FWS - function cfws() { - return wrap('cfws', or( - and( - star( - and(opt(fws), comment), - 1 - ), - opt(fws) - ), - fws - )()); - } - - // 3.2.3. Atom - - //atext = ALPHA / DIGIT / ; Printable US-ASCII - // "!" / "#" / ; characters not including - // "$" / "%" / ; specials. Used for atoms. - // "&" / "'" / - // "*" / "+" / - // "-" / "/" / - // "=" / "?" / - // "^" / "_" / - // "`" / "{" / - // "|" / "}" / - // "~" - function atext() { - return wrap('atext', compareToken(function atextFunc(tok) { - var accept = - ('a' <= tok && tok <= 'z') || - ('A' <= tok && tok <= 'Z') || - ('0' <= tok && tok <= '9') || - (['!', '#', '$', '%', '&', '\'', '*', '+', '-', '/', - '=', '?', '^', '_', '`', '{', '|', '}', '~'].indexOf(tok) >= 0); - if (opts.rfc6532) { - accept = accept || isUTF8NonAscii(tok); - } - return accept; - })); - } - - // atom = [CFWS] 1*atext [CFWS] - function atom() { - return wrap('atom', and(colwsp(opt(cfws)), star(atext, 1), colwsp(opt(cfws)))()); - } - - // dot-atom-text = 1*atext *("." 1*atext) - function dotAtomText() { - var s, maybeText; - s = wrap('dot-atom-text', star(atext, 1)()); - if (s === null) { return s; } - maybeText = star(and(literal('.'), star(atext, 1)))(); - if (maybeText !== null) { - add(s, maybeText); - } - return s; - } - - // dot-atom = [CFWS] dot-atom-text [CFWS] - function dotAtom() { - return wrap('dot-atom', and(invis(opt(cfws)), dotAtomText, invis(opt(cfws)))()); - } - - // 3.2.4. Quoted Strings - - // qtext = %d33 / ; Printable US-ASCII - // %d35-91 / ; characters not including - // %d93-126 / ; "\" or the quote character - // obs-qtext - function qtext() { - return wrap('qtext', or( - function qtextFunc1() { - return compareToken(function qtextFunc2(tok) { - var code = tok.charCodeAt(0); - var accept = - (33 === code) || - (35 <= code && code <= 91) || - (93 <= code && code <= 126); - if (opts.rfc6532) { - accept = accept || isUTF8NonAscii(tok); - } - return accept; - }); - }, - obsQtext - )()); - } - - // qcontent = qtext / quoted-pair - function qcontent() { - return wrap('qcontent', or(qtext, quotedPair)()); - } - - // quoted-string = [CFWS] - // DQUOTE *([FWS] qcontent) [FWS] DQUOTE - // [CFWS] - function quotedString() { - return wrap('quoted-string', and( - invis(opt(cfws)), - invis(dquote), star(and(opt(colwsp(fws)), qcontent)), opt(invis(fws)), invis(dquote), - invis(opt(cfws)) - )()); - } - - // 3.2.5 Miscellaneous Tokens - - // word = atom / quoted-string - function word() { - return wrap('word', or(atom, quotedString)()); - } - - // phrase = 1*word / obs-phrase - function phrase() { - return wrap('phrase', or(obsPhrase, star(word, 1))()); - } - - // 3.4. Address Specification - // address = mailbox / group - function address() { - return wrap('address', or(mailbox, group)()); - } - - // mailbox = name-addr / addr-spec - function mailbox() { - return wrap('mailbox', or(nameAddr, addrSpec)()); - } - - // name-addr = [display-name] angle-addr - function nameAddr() { - return wrap('name-addr', and(opt(displayName), angleAddr)()); - } - - // angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / - // obs-angle-addr - function angleAddr() { - return wrap('angle-addr', or( - and( - invis(opt(cfws)), - literal('<'), - addrSpec, - literal('>'), - invis(opt(cfws)) - ), - obsAngleAddr - )()); - } - - // group = display-name ":" [group-list] ";" [CFWS] - function group() { - return wrap('group', and( - displayName, - literal(':'), - opt(groupList), - literal(';'), - invis(opt(cfws)) - )()); - } - - // display-name = phrase - function displayName() { - return wrap('display-name', function phraseFixedSemantic() { - var result = phrase(); - if (result !== null) { - result.semantic = collapseWhitespace(result.semantic); - } - return result; - }()); - } - - // mailbox-list = (mailbox *("," mailbox)) / obs-mbox-list - function mailboxList() { - return wrap('mailbox-list', or( - and( - mailbox, - star(and(literal(','), mailbox)) - ), - obsMboxList - )()); - } - - // address-list = (address *("," address)) / obs-addr-list - function addressList() { - return wrap('address-list', or( - and( - address, - star(and(literal(','), address)) - ), - obsAddrList - )()); - } - - // group-list = mailbox-list / CFWS / obs-group-list - function groupList() { - return wrap('group-list', or( - mailboxList, - invis(cfws), - obsGroupList - )()); - } - - // 3.4.1 Addr-Spec Specification - - // local-part = dot-atom / quoted-string / obs-local-part - function localPart() { - // note: quoted-string, dotAtom are proper subsets of obs-local-part - // so we really just have to look for obsLocalPart, if we don't care about the exact parse tree - return wrap('local-part', or(obsLocalPart, dotAtom, quotedString)()); - } - - // dtext = %d33-90 / ; Printable US-ASCII - // %d94-126 / ; characters not including - // obs-dtext ; "[", "]", or "\" - function dtext() { - return wrap('dtext', or( - function dtextFunc1() { - return compareToken(function dtextFunc2(tok) { - var code = tok.charCodeAt(0); - var accept = - (33 <= code && code <= 90) || - (94 <= code && code <= 126); - if (opts.rfc6532) { - accept = accept || isUTF8NonAscii(tok); - } - return accept; - }); - }, - obsDtext - )() - ); - } - - // domain-literal = [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS] - function domainLiteral() { - return wrap('domain-literal', and( - invis(opt(cfws)), - literal('['), - star(and(opt(fws), dtext)), - opt(fws), - literal(']'), - invis(opt(cfws)) - )()); - } - - // domain = dot-atom / domain-literal / obs-domain - function domain() { - return wrap('domain', function domainCheckTLD() { - var result = or(obsDomain, dotAtom, domainLiteral)(); - if (opts.rejectTLD) { - if (result && result.semantic && result.semantic.indexOf('.') < 0) { - return null; - } - } - // strip all whitespace from domains - if (result) { - result.semantic = result.semantic.replace(/\s+/g, ''); - } - return result; - }()); - } - - // addr-spec = local-part "@" domain - function addrSpec() { - return wrap('addr-spec', and( - localPart, literal('@'), domain - )()); - } - - // 3.6.2 Originator Fields - // Below we only parse the field body, not the name of the field - // like "From:", "Sender:", or "Reply-To:". Other libraries that - // parse email headers can parse those and defer to these productions - // for the "RFC 5322" part. - - // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields - // from = "From:" (mailbox-list / address-list) CRLF - function fromSpec() { - return wrap('from', or( - mailboxList, - addressList - )()); - } - - // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields - // sender = "Sender:" (mailbox / address) CRLF - function senderSpec() { - return wrap('sender', or( - mailbox, - address - )()); - } - - // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields - // reply-to = "Reply-To:" address-list CRLF - function replyToSpec() { - return wrap('reply-to', addressList()); - } - - // 4.1. Miscellaneous Obsolete Tokens - - // obs-NO-WS-CTL = %d1-8 / ; US-ASCII control - // %d11 / ; characters that do not - // %d12 / ; include the carriage - // %d14-31 / ; return, line feed, and - // %d127 ; white space characters - function obsNoWsCtl() { - return opts.strict ? null : wrap('obs-NO-WS-CTL', compareToken(function (tok) { - var code = tok.charCodeAt(0); - return ((1 <= code && code <= 8) || - (11 === code || 12 === code) || - (14 <= code && code <= 31) || - (127 === code)); - })); - } - - // obs-ctext = obs-NO-WS-CTL - function obsCtext() { return opts.strict ? null : wrap('obs-ctext', obsNoWsCtl()); } - - // obs-qtext = obs-NO-WS-CTL - function obsQtext() { return opts.strict ? null : wrap('obs-qtext', obsNoWsCtl()); } - - // obs-qp = "\" (%d0 / obs-NO-WS-CTL / LF / CR) - function obsQP() { - return opts.strict ? null : wrap('obs-qp', and( - literal('\\'), - or(literal('\0'), obsNoWsCtl, lf, cr) - )()); - } - - // obs-phrase = word *(word / "." / CFWS) - function obsPhrase() { - if (opts.strict ) return null; - return opts.atInDisplayName ? wrap('obs-phrase', and( - word, - star(or(word, literal('.'), literal('@'), colwsp(cfws))) - )()) : - wrap('obs-phrase', and( - word, - star(or(word, literal('.'), colwsp(cfws))) - )()); - } - - // 4.2. Obsolete Folding White Space - - // NOTE: read the errata http://www.rfc-editor.org/errata_search.php?rfc=5322&eid=1908 - // obs-FWS = 1*([CRLF] WSP) - function obsFws() { - return opts.strict ? null : wrap('obs-FWS', star( - and(invis(opt(crlf)), wsp), - 1 - )()); - } - - // 4.4. Obsolete Addressing - - // obs-angle-addr = [CFWS] "<" obs-route addr-spec ">" [CFWS] - function obsAngleAddr() { - return opts.strict ? null : wrap('obs-angle-addr', and( - invis(opt(cfws)), - literal('<'), - obsRoute, - addrSpec, - literal('>'), - invis(opt(cfws)) - )()); - } - - // obs-route = obs-domain-list ":" - function obsRoute() { - return opts.strict ? null : wrap('obs-route', and( - obsDomainList, - literal(':') - )()); - } - - // obs-domain-list = *(CFWS / ",") "@" domain - // *("," [CFWS] ["@" domain]) - function obsDomainList() { - return opts.strict ? null : wrap('obs-domain-list', and( - star(or(invis(cfws), literal(','))), - literal('@'), - domain, - star(and( - literal(','), - invis(opt(cfws)), - opt(and(literal('@'), domain)) - )) - )()); - } - - // obs-mbox-list = *([CFWS] ",") mailbox *("," [mailbox / CFWS]) - function obsMboxList() { - return opts.strict ? null : wrap('obs-mbox-list', and( - star(and( - invis(opt(cfws)), - literal(',') - )), - mailbox, - star(and( - literal(','), - opt(and( - mailbox, - invis(cfws) - )) - )) - )()); - } - - // obs-addr-list = *([CFWS] ",") address *("," [address / CFWS]) - function obsAddrList() { - return opts.strict ? null : wrap('obs-addr-list', and( - star(and( - invis(opt(cfws)), - literal(',') - )), - address, - star(and( - literal(','), - opt(and( - address, - invis(cfws) - )) - )) - )()); - } - - // obs-group-list = 1*([CFWS] ",") [CFWS] - function obsGroupList() { - return opts.strict ? null : wrap('obs-group-list', and( - star(and( - invis(opt(cfws)), - literal(',') - ), 1), - invis(opt(cfws)) - )()); - } - - // obs-local-part = word *("." word) - function obsLocalPart() { - return opts.strict ? null : wrap('obs-local-part', and(word, star(and(literal('.'), word)))()); - } - - // obs-domain = atom *("." atom) - function obsDomain() { - return opts.strict ? null : wrap('obs-domain', and(atom, star(and(literal('.'), atom)))()); - } - - // obs-dtext = obs-NO-WS-CTL / quoted-pair - function obsDtext() { - return opts.strict ? null : wrap('obs-dtext', or(obsNoWsCtl, quotedPair)()); - } - - ///////////////////////////////////////////////////// - - // ast analysis - - function findNode(name, root) { - var i, stack, node; - if (root === null || root === undefined) { return null; } - stack = [root]; - while (stack.length > 0) { - node = stack.pop(); - if (node.name === name) { - return node; - } - for (i = node.children.length - 1; i >= 0; i -= 1) { - stack.push(node.children[i]); - } - } - return null; - } - - function findAllNodes(name, root) { - var i, stack, node, result; - if (root === null || root === undefined) { return null; } - stack = [root]; - result = []; - while (stack.length > 0) { - node = stack.pop(); - if (node.name === name) { - result.push(node); - } - for (i = node.children.length - 1; i >= 0; i -= 1) { - stack.push(node.children[i]); - } - } - return result; - } - - function findAllNodesNoChildren(names, root) { - var i, stack, node, result, namesLookup; - if (root === null || root === undefined) { return null; } - stack = [root]; - result = []; - namesLookup = {}; - for (i = 0; i < names.length; i += 1) { - namesLookup[names[i]] = true; - } - - while (stack.length > 0) { - node = stack.pop(); - if (node.name in namesLookup) { - result.push(node); - // don't look at children (hence findAllNodesNoChildren) - } else { - for (i = node.children.length - 1; i >= 0; i -= 1) { - stack.push(node.children[i]); - } - } - } - return result; - } - - function giveResult(ast) { - var addresses, groupsAndMailboxes, i, groupOrMailbox, result; - if (ast === null) { - return null; - } - addresses = []; - - // An address is a 'group' (i.e. a list of mailboxes) or a 'mailbox'. - groupsAndMailboxes = findAllNodesNoChildren(['group', 'mailbox'], ast); - for (i = 0; i < groupsAndMailboxes.length; i += 1) { - groupOrMailbox = groupsAndMailboxes[i]; - if (groupOrMailbox.name === 'group') { - addresses.push(giveResultGroup(groupOrMailbox)); - } else if (groupOrMailbox.name === 'mailbox') { - addresses.push(giveResultMailbox(groupOrMailbox)); - } - } - - result = { - ast: ast, - addresses: addresses, - }; - if (opts.simple) { - result = simplifyResult(result); - } - if (opts.oneResult) { - return oneResult(result); - } - if (opts.simple) { - return result && result.addresses; - } else { - return result; - } - } - - function giveResultGroup(group) { - var i; - var groupName = findNode('display-name', group); - var groupResultMailboxes = []; - var mailboxes = findAllNodesNoChildren(['mailbox'], group); - for (i = 0; i < mailboxes.length; i += 1) { - groupResultMailboxes.push(giveResultMailbox(mailboxes[i])); - } - return { - node: group, - parts: { - name: groupName, - }, - type: group.name, // 'group' - name: grabSemantic(groupName), - addresses: groupResultMailboxes, - }; - } - - function giveResultMailbox(mailbox) { - var name = findNode('display-name', mailbox); - var aspec = findNode('addr-spec', mailbox); - var cfws = findAllNodes('cfws', mailbox); - var comments = findAllNodesNoChildren(['comment'], mailbox); - - - var local = findNode('local-part', aspec); - var domain = findNode('domain', aspec); - return { - node: mailbox, - parts: { - name: name, - address: aspec, - local: local, - domain: domain, - comments: cfws - }, - type: mailbox.name, // 'mailbox' - name: grabSemantic(name), - address: grabSemantic(aspec), - local: grabSemantic(local), - domain: grabSemantic(domain), - comments: concatComments(comments), - groupName: grabSemantic(mailbox.groupName), - }; - } - - function grabSemantic(n) { - return n !== null && n !== undefined ? n.semantic : null; - } - - function simplifyResult(result) { - var i; - if (result && result.addresses) { - for (i = 0; i < result.addresses.length; i += 1) { - delete result.addresses[i].node; - } - } - return result; - } - - function concatComments(comments) { - var result = ''; - if (comments) { - for (var i = 0; i < comments.length; i += 1) { - result += grabSemantic(comments[i]); - } - } - return result; - } - - function oneResult(result) { - if (!result) { return null; } - if (!opts.partial && result.addresses.length > 1) { return null; } - return result.addresses && result.addresses[0]; - } - - ///////////////////////////////////////////////////// - - var parseString, pos, len, parsed, startProduction; - - opts = handleOpts(opts, {}); - if (opts === null) { return null; } - - parseString = opts.input; - - startProduction = { - 'address': address, - 'address-list': addressList, - 'angle-addr': angleAddr, - 'from': fromSpec, - 'group': group, - 'mailbox': mailbox, - 'mailbox-list': mailboxList, - 'reply-to': replyToSpec, - 'sender': senderSpec, - }[opts.startAt] || addressList; - - if (!opts.strict) { - initialize(); - opts.strict = true; - parsed = startProduction(parseString); - if (opts.partial || !inStr()) { - return giveResult(parsed); - } - opts.strict = false; - } - - initialize(); - parsed = startProduction(parseString); - if (!opts.partial && inStr()) { return null; } - return giveResult(parsed); -} - -function parseOneAddressSimple(opts) { - return parse5322(handleOpts(opts, { - oneResult: true, - rfc6532: true, - simple: true, - startAt: 'address-list', - })); -} - -function parseAddressListSimple(opts) { - return parse5322(handleOpts(opts, { - rfc6532: true, - simple: true, - startAt: 'address-list', - })); -} - -function parseFromSimple(opts) { - return parse5322(handleOpts(opts, { - rfc6532: true, - simple: true, - startAt: 'from', - })); -} - -function parseSenderSimple(opts) { - return parse5322(handleOpts(opts, { - oneResult: true, - rfc6532: true, - simple: true, - startAt: 'sender', - })); -} - -function parseReplyToSimple(opts) { - return parse5322(handleOpts(opts, { - rfc6532: true, - simple: true, - startAt: 'reply-to', - })); -} - -function handleOpts(opts, defs) { - function isString(str) { - return Object.prototype.toString.call(str) === '[object String]'; - } - - function isObject(o) { - return o === Object(o); - } - - function isNullUndef(o) { - return o === null || o === undefined; - } - - var defaults, o; - - if (isString(opts)) { - opts = { input: opts }; - } else if (!isObject(opts)) { - return null; - } - - if (!isString(opts.input)) { return null; } - if (!defs) { return null; } - - defaults = { - oneResult: false, - partial: false, - rejectTLD: false, - rfc6532: false, - simple: false, - startAt: 'address-list', - strict: false, - atInDisplayName: false - }; - - for (o in defaults) { - if (isNullUndef(opts[o])) { - opts[o] = !isNullUndef(defs[o]) ? defs[o] : defaults[o]; - } - } - return opts; -} - -parse5322.parseOneAddress = parseOneAddressSimple; -parse5322.parseAddressList = parseAddressListSimple; -parse5322.parseFrom = parseFromSimple; -parse5322.parseSender = parseSenderSimple; -parse5322.parseReplyTo = parseReplyToSimple; - -{ - module.exports = parse5322; -} - -}()); -}); - -// GPG4Browsers - An OpenPGP implementation in javascript - -/** - * Implementation of the User ID Packet (Tag 13) - * - * A User ID packet consists of UTF-8 text that is intended to represent - * the name and email address of the key holder. By convention, it - * includes an RFC 2822 [RFC2822] mail name-addr, but there are no - * restrictions on its content. The packet length in the header - * specifies the length of the User ID. - */ -class UserIDPacket { - static get tag() { - return enums.packet.userID; - } - - constructor() { - /** A string containing the user id. Usually in the form - * John Doe - * @type {String} - */ - this.userID = ''; - - this.name = ''; - this.email = ''; - this.comment = ''; - } - - /** - * Create UserIDPacket instance from object - * @param {Object} userID - Object specifying userID name, email and comment - * @returns {UserIDPacket} - * @static - */ - static fromObject(userID) { - if (util.isString(userID) || - (userID.name && !util.isString(userID.name)) || - (userID.email && !util.isEmailAddress(userID.email)) || - (userID.comment && !util.isString(userID.comment))) { - throw new Error('Invalid user ID format'); - } - const packet = new UserIDPacket(); - Object.assign(packet, userID); - const components = []; - if (packet.name) components.push(packet.name); - if (packet.comment) components.push(`(${packet.comment})`); - if (packet.email) components.push(`<${packet.email}>`); - packet.userID = components.join(' '); - return packet; - } - - /** - * Parsing function for a user id packet (tag 13). - * @param {Uint8Array} input - Payload of a tag 13 packet - */ - read(bytes, config = defaultConfig) { - const userID = util.decodeUTF8(bytes); - if (userID.length > config.maxUserIDLength) { - throw new Error('User ID string is too long'); - } - try { - const { name, address: email, comments } = emailAddresses.parseOneAddress({ input: userID, atInDisplayName: true }); - this.comment = comments.replace(/^\(|\)$/g, ''); - this.name = name; - this.email = email; - } catch (e) {} - this.userID = userID; - } - - /** - * Creates a binary representation of the user id packet - * @returns {Uint8Array} Binary representation. - */ - write() { - return util.encodeUTF8(this.userID); - } - - equals(otherUserID) { - return otherUserID && otherUserID.userID === this.userID; - } -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -/** - * A Secret-Subkey packet (tag 7) is the subkey analog of the Secret - * Key packet and has exactly the same format. - * @extends SecretKeyPacket - */ -class SecretSubkeyPacket extends SecretKeyPacket { - static get tag() { - return enums.packet.secretSubkey; - } - - /** - * @param {Date} [date] - Creation date - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - constructor(date = new Date(), config = defaultConfig) { - super(date, config); - } -} - -/** - * Implementation of the Trust Packet (Tag 12) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.10|RFC4880 5.10}: - * The Trust packet is used only within keyrings and is not normally - * exported. Trust packets contain data that record the user's - * specifications of which key holders are trustworthy introducers, - * along with other information that implementing software uses for - * trust information. The format of Trust packets is defined by a given - * implementation. - * - * Trust packets SHOULD NOT be emitted to output streams that are - * transferred to other users, and they SHOULD be ignored on any input - * other than local keyring files. - */ -class TrustPacket { - static get tag() { - return enums.packet.trust; - } - - /** - * Parsing function for a trust packet (tag 12). - * Currently not implemented as we ignore trust packets - */ - read() { - throw new UnsupportedError('Trust packets are not supported'); - } - - write() { - throw new UnsupportedError('Trust packets are not supported'); - } -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -// A Signature can contain the following packets -const allowedPackets$4 = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); - -/** - * Class that represents an OpenPGP signature. - */ -class Signature { - /** - * @param {PacketList} packetlist - The signature packets - */ - constructor(packetlist) { - this.packets = packetlist || new PacketList(); - } - - /** - * Returns binary encoded signature - * @returns {ReadableStream} Binary signature. - */ - write() { - return this.packets.write(); - } - - /** - * Returns ASCII armored text of signature - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {ReadableStream} ASCII armor. - */ - armor(config = defaultConfig) { - return armor(enums.armor.signature, this.write(), undefined, undefined, undefined, config); - } - - /** - * Returns an array of KeyIDs of all of the issuers who created this signature - * @returns {Array} The Key IDs of the signing keys - */ - getSigningKeyIDs() { - return this.packets.map(packet => packet.issuerKeyID); - } -} - -/** - * reads an (optionally armored) OpenPGP signature and returns a signature object - * @param {Object} options - * @param {String} [options.armoredSignature] - Armored signature to be parsed - * @param {Uint8Array} [options.binarySignature] - Binary signature to be parsed - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} New signature object. - * @async - * @static - */ -async function readSignature({ armoredSignature, binarySignature, config, ...rest }) { - config = { ...defaultConfig, ...config }; - let input = armoredSignature || binarySignature; - if (!input) { - throw new Error('readSignature: must pass options object containing `armoredSignature` or `binarySignature`'); - } - if (armoredSignature && !util.isString(armoredSignature)) { - throw new Error('readSignature: options.armoredSignature must be a string'); - } - if (binarySignature && !util.isUint8Array(binarySignature)) { - throw new Error('readSignature: options.binarySignature must be a Uint8Array'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (armoredSignature) { - const { type, data } = await unarmor(input, config); - if (type !== enums.armor.signature) { - throw new Error('Armored text not of type signature'); - } - input = data; - } - const packetlist = await PacketList.fromBinary(input, allowedPackets$4, config); - return new Signature(packetlist); -} - -/** - * @fileoverview Provides helpers methods for key module - * @module key/helper - * @private - */ - -async function generateSecretSubkey(options, config) { - const secretSubkeyPacket = new SecretSubkeyPacket(options.date, config); - secretSubkeyPacket.packets = null; - secretSubkeyPacket.algorithm = enums.write(enums.publicKey, options.algorithm); - await secretSubkeyPacket.generate(options.rsaBits, options.curve); - await secretSubkeyPacket.computeFingerprintAndKeyID(); - return secretSubkeyPacket; -} - -async function generateSecretKey(options, config) { - const secretKeyPacket = new SecretKeyPacket(options.date, config); - secretKeyPacket.packets = null; - secretKeyPacket.algorithm = enums.write(enums.publicKey, options.algorithm); - await secretKeyPacket.generate(options.rsaBits, options.curve, options.config); - await secretKeyPacket.computeFingerprintAndKeyID(); - return secretKeyPacket; -} - -/** - * Returns the valid and non-expired signature that has the latest creation date, while ignoring signatures created in the future. - * @param {Array} signatures - List of signatures - * @param {PublicKeyPacket|PublicSubkeyPacket} publicKey - Public key packet to verify the signature - * @param {Date} date - Use the given date instead of the current time - * @param {Object} config - full configuration - * @returns {Promise} The latest valid signature. - * @async - */ -async function getLatestValidSignature(signatures, publicKey, signatureType, dataToVerify, date = new Date(), config) { - let latestValid; - let exception; - for (let i = signatures.length - 1; i >= 0; i--) { - try { - if ( - (!latestValid || signatures[i].created >= latestValid.created) - ) { - await signatures[i].verify(publicKey, signatureType, dataToVerify, date, undefined, config); - latestValid = signatures[i]; - } - } catch (e) { - exception = e; - } - } - if (!latestValid) { - throw util.wrapError( - `Could not find valid ${enums.read(enums.signature, signatureType)} signature in key ${publicKey.getKeyID().toHex()}` - .replace('certGeneric ', 'self-') - .replace(/([a-z])([A-Z])/g, (_, $1, $2) => $1 + ' ' + $2.toLowerCase()) - , exception); - } - return latestValid; -} - -function isDataExpired(keyPacket, signature, date = new Date()) { - const normDate = util.normalizeDate(date); - if (normDate !== null) { - const expirationTime = getKeyExpirationTime(keyPacket, signature); - return !(keyPacket.created <= normDate && normDate < expirationTime); - } - return false; -} - -/** - * Create Binding signature to the key according to the {@link https://tools.ietf.org/html/rfc4880#section-5.2.1} - * @param {SecretSubkeyPacket} subkey - Subkey key packet - * @param {SecretKeyPacket} primaryKey - Primary key packet - * @param {Object} options - * @param {Object} config - Full configuration - */ -async function createBindingSignature(subkey, primaryKey, options, config) { - const dataToSign = {}; - dataToSign.key = primaryKey; - dataToSign.bind = subkey; - const subkeySignaturePacket = new SignaturePacket(); - subkeySignaturePacket.signatureType = enums.signature.subkeyBinding; - subkeySignaturePacket.publicKeyAlgorithm = primaryKey.algorithm; - subkeySignaturePacket.hashAlgorithm = await getPreferredHashAlgo$1(null, subkey, undefined, undefined, config); - if (options.sign) { - subkeySignaturePacket.keyFlags = [enums.keyFlags.signData]; - subkeySignaturePacket.embeddedSignature = await createSignaturePacket(dataToSign, null, subkey, { - signatureType: enums.signature.keyBinding - }, options.date, undefined, undefined, config); - } else { - subkeySignaturePacket.keyFlags = [enums.keyFlags.encryptCommunication | enums.keyFlags.encryptStorage]; - } - if (options.keyExpirationTime > 0) { - subkeySignaturePacket.keyExpirationTime = options.keyExpirationTime; - subkeySignaturePacket.keyNeverExpires = false; - } - await subkeySignaturePacket.sign(primaryKey, dataToSign, options.date); - return subkeySignaturePacket; -} - -/** - * Returns the preferred signature hash algorithm of a key - * @param {Key} [key] - The key to get preferences from - * @param {SecretKeyPacket|SecretSubkeyPacket} keyPacket - key packet used for signing - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} [userID] - User ID - * @param {Object} config - full configuration - * @returns {Promise} - * @async - */ -async function getPreferredHashAlgo$1(key, keyPacket, date = new Date(), userID = {}, config) { - let hashAlgo = config.preferredHashAlgorithm; - let prefAlgo = hashAlgo; - if (key) { - const primaryUser = await key.getPrimaryUser(date, userID, config); - if (primaryUser.selfCertification.preferredHashAlgorithms) { - [prefAlgo] = primaryUser.selfCertification.preferredHashAlgorithms; - hashAlgo = mod.hash.getHashByteLength(hashAlgo) <= mod.hash.getHashByteLength(prefAlgo) ? - prefAlgo : hashAlgo; - } - } - switch (Object.getPrototypeOf(keyPacket)) { - case SecretKeyPacket.prototype: - case PublicKeyPacket.prototype: - case SecretSubkeyPacket.prototype: - case PublicSubkeyPacket.prototype: - switch (keyPacket.algorithm) { - case enums.publicKey.ecdh: - case enums.publicKey.ecdsa: - case enums.publicKey.eddsa: - prefAlgo = mod.publicKey.elliptic.getPreferredHashAlgo(keyPacket.publicParams.oid); - } - } - return mod.hash.getHashByteLength(hashAlgo) <= mod.hash.getHashByteLength(prefAlgo) ? - prefAlgo : hashAlgo; -} - -/** - * Returns the preferred symmetric/aead/compression algorithm for a set of keys - * @param {'symmetric'|'aead'|'compression'} type - Type of preference to return - * @param {Array} [keys] - Set of keys - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Array} [userIDs] - User IDs - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} Preferred algorithm - * @async - */ -async function getPreferredAlgo(type, keys = [], date = new Date(), userIDs = [], config = defaultConfig) { - const defaultAlgo = { // these are all must-implement in rfc4880bis - 'symmetric': enums.symmetric.aes128, - 'aead': enums.aead.eax, - 'compression': enums.compression.uncompressed - }[type]; - const preferredSenderAlgo = { - 'symmetric': config.preferredSymmetricAlgorithm, - 'aead': config.preferredAEADAlgorithm, - 'compression': config.preferredCompressionAlgorithm - }[type]; - const prefPropertyName = { - 'symmetric': 'preferredSymmetricAlgorithms', - 'aead': 'preferredAEADAlgorithms', - 'compression': 'preferredCompressionAlgorithms' - }[type]; - - // if preferredSenderAlgo appears in the prefs of all recipients, we pick it - // otherwise we use the default algo - // if no keys are available, preferredSenderAlgo is returned - const senderAlgoSupport = await Promise.all(keys.map(async function(key, i) { - const primaryUser = await key.getPrimaryUser(date, userIDs[i], config); - const recipientPrefs = primaryUser.selfCertification[prefPropertyName]; - return !!recipientPrefs && recipientPrefs.indexOf(preferredSenderAlgo) >= 0; - })); - return senderAlgoSupport.every(Boolean) ? preferredSenderAlgo : defaultAlgo; -} - -/** - * Create signature packet - * @param {Object} dataToSign - Contains packets to be signed - * @param {PrivateKey} privateKey - key to get preferences from - * @param {SecretKeyPacket| - * SecretSubkeyPacket} signingKeyPacket secret key packet for signing - * @param {Object} [signatureProperties] - Properties to write on the signature packet before signing - * @param {Date} [date] - Override the creationtime of the signature - * @param {Object} [userID] - User ID - * @param {Object} [detached] - Whether to create a detached signature packet - * @param {Object} config - full configuration - * @returns {Promise} Signature packet. - */ -async function createSignaturePacket(dataToSign, privateKey, signingKeyPacket, signatureProperties, date, userID, detached = false, config) { - if (signingKeyPacket.isDummy()) { - throw new Error('Cannot sign with a gnu-dummy key.'); - } - if (!signingKeyPacket.isDecrypted()) { - throw new Error('Signing key is not decrypted.'); - } - const signaturePacket = new SignaturePacket(); - Object.assign(signaturePacket, signatureProperties); - signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm; - signaturePacket.hashAlgorithm = await getPreferredHashAlgo$1(privateKey, signingKeyPacket, date, userID, config); - await signaturePacket.sign(signingKeyPacket, dataToSign, date, detached); - return signaturePacket; -} - -/** - * Merges signatures from source[attr] to dest[attr] - * @param {Object} source - * @param {Object} dest - * @param {String} attr - * @param {Date} [date] - date to use for signature expiration check, instead of the current time - * @param {Function} [checkFn] - signature only merged if true - */ -async function mergeSignatures(source, dest, attr, date = new Date(), checkFn) { - source = source[attr]; - if (source) { - if (!dest[attr].length) { - dest[attr] = source; - } else { - await Promise.all(source.map(async function(sourceSig) { - if (!sourceSig.isExpired(date) && (!checkFn || await checkFn(sourceSig)) && - !dest[attr].some(function(destSig) { - return util.equalsUint8Array(destSig.writeParams(), sourceSig.writeParams()); - })) { - dest[attr].push(sourceSig); - } - })); - } - } -} - -/** - * Checks if a given certificate or binding signature is revoked - * @param {SecretKeyPacket| - * PublicKeyPacket} primaryKey The primary key packet - * @param {Object} dataToVerify - The data to check - * @param {Array} revocations - The revocation signatures to check - * @param {SignaturePacket} signature - The certificate or signature to check - * @param {PublicSubkeyPacket| - * SecretSubkeyPacket| - * PublicKeyPacket| - * SecretKeyPacket} key, optional The key packet to verify the signature, instead of the primary key - * @param {Date} date - Use the given date instead of the current time - * @param {Object} config - Full configuration - * @returns {Promise} True if the signature revokes the data. - * @async - */ -async function isDataRevoked(primaryKey, signatureType, dataToVerify, revocations, signature, key, date = new Date(), config) { - key = key || primaryKey; - const revocationKeyIDs = []; - await Promise.all(revocations.map(async function(revocationSignature) { - try { - if ( - // Note: a third-party revocation signature could legitimately revoke a - // self-signature if the signature has an authorized revocation key. - // However, we don't support passing authorized revocation keys, nor - // verifying such revocation signatures. Instead, we indicate an error - // when parsing a key with an authorized revocation key, and ignore - // third-party revocation signatures here. (It could also be revoking a - // third-party key certification, which should only affect - // `verifyAllCertifications`.) - !signature || revocationSignature.issuerKeyID.equals(signature.issuerKeyID) - ) { - await revocationSignature.verify( - key, signatureType, dataToVerify, config.revocationsExpire ? date : null, false, config - ); - - // TODO get an identifier of the revoked object instead - revocationKeyIDs.push(revocationSignature.issuerKeyID); - } - } catch (e) {} - })); - // TODO further verify that this is the signature that should be revoked - if (signature) { - signature.revoked = revocationKeyIDs.some(keyID => keyID.equals(signature.issuerKeyID)) ? true : - signature.revoked || false; - return signature.revoked; - } - return revocationKeyIDs.length > 0; -} - -/** - * Returns key expiration time based on the given certification signature. - * The expiration time of the signature is ignored. - * @param {PublicSubkeyPacket|PublicKeyPacket} keyPacket - key to check - * @param {SignaturePacket} signature - signature to process - * @returns {Date|Infinity} expiration time or infinity if the key does not expire - */ -function getKeyExpirationTime(keyPacket, signature) { - let expirationTime; - // check V4 expiration time - if (signature.keyNeverExpires === false) { - expirationTime = keyPacket.created.getTime() + signature.keyExpirationTime * 1000; - } - return expirationTime ? new Date(expirationTime) : Infinity; -} - -/** - * Returns whether aead is supported by all keys in the set - * @param {Array} keys - Set of keys - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Array} [userIDs] - User IDs - * @param {Object} config - full configuration - * @returns {Promise} - * @async - */ -async function isAEADSupported(keys, date = new Date(), userIDs = [], config = defaultConfig) { - let supported = true; - // TODO replace when Promise.some or Promise.any are implemented - await Promise.all(keys.map(async function(key, i) { - const primaryUser = await key.getPrimaryUser(date, userIDs[i], config); - if (!primaryUser.selfCertification.features || - !(primaryUser.selfCertification.features[0] & enums.features.aead)) { - supported = false; - } - })); - return supported; -} - -function sanitizeKeyOptions(options, subkeyDefaults = {}) { - options.type = options.type || subkeyDefaults.type; - options.curve = options.curve || subkeyDefaults.curve; - options.rsaBits = options.rsaBits || subkeyDefaults.rsaBits; - options.keyExpirationTime = options.keyExpirationTime !== undefined ? options.keyExpirationTime : subkeyDefaults.keyExpirationTime; - options.passphrase = util.isString(options.passphrase) ? options.passphrase : subkeyDefaults.passphrase; - options.date = options.date || subkeyDefaults.date; - - options.sign = options.sign || false; - - switch (options.type) { - case 'ecc': - try { - options.curve = enums.write(enums.curve, options.curve); - } catch (e) { - throw new Error('Invalid curve'); - } - if (options.curve === enums.curve.ed25519 || options.curve === enums.curve.curve25519) { - options.curve = options.sign ? enums.curve.ed25519 : enums.curve.curve25519; - } - if (options.sign) { - options.algorithm = options.curve === enums.curve.ed25519 ? enums.publicKey.eddsa : enums.publicKey.ecdsa; - } else { - options.algorithm = enums.publicKey.ecdh; - } - break; - case 'rsa': - options.algorithm = enums.publicKey.rsaEncryptSign; - break; - default: - throw new Error(`Unsupported key type ${options.type}`); - } - return options; -} - -function isValidSigningKeyPacket(keyPacket, signature) { - const keyAlgo = keyPacket.algorithm; - return keyAlgo !== enums.publicKey.rsaEncrypt && - keyAlgo !== enums.publicKey.elgamal && - keyAlgo !== enums.publicKey.ecdh && - (!signature.keyFlags || - (signature.keyFlags[0] & enums.keyFlags.signData) !== 0); -} - -function isValidEncryptionKeyPacket(keyPacket, signature) { - const keyAlgo = keyPacket.algorithm; - return keyAlgo !== enums.publicKey.dsa && - keyAlgo !== enums.publicKey.rsaSign && - keyAlgo !== enums.publicKey.ecdsa && - keyAlgo !== enums.publicKey.eddsa && - (!signature.keyFlags || - (signature.keyFlags[0] & enums.keyFlags.encryptCommunication) !== 0 || - (signature.keyFlags[0] & enums.keyFlags.encryptStorage) !== 0); -} - -function isValidDecryptionKeyPacket(signature, config) { - if (config.allowInsecureDecryptionWithSigningKeys) { - // This is only relevant for RSA keys, all other signing algorithms cannot decrypt - return true; - } - - return !signature.keyFlags || - (signature.keyFlags[0] & enums.keyFlags.encryptCommunication) !== 0 || - (signature.keyFlags[0] & enums.keyFlags.encryptStorage) !== 0; -} - -/** - * Check key against blacklisted algorithms and minimum strength requirements. - * @param {SecretKeyPacket|PublicKeyPacket| - * SecretSubkeyPacket|PublicSubkeyPacket} keyPacket - * @param {Config} config - * @throws {Error} if the key packet does not meet the requirements - */ -function checkKeyRequirements(keyPacket, config) { - const keyAlgo = enums.write(enums.publicKey, keyPacket.algorithm); - const algoInfo = keyPacket.getAlgorithmInfo(); - if (config.rejectPublicKeyAlgorithms.has(keyAlgo)) { - throw new Error(`${algoInfo.algorithm} keys are considered too weak.`); - } - switch (keyAlgo) { - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaSign: - case enums.publicKey.rsaEncrypt: - if (algoInfo.bits < config.minRSABits) { - throw new Error(`RSA keys shorter than ${config.minRSABits} bits are considered too weak.`); - } - break; - case enums.publicKey.ecdsa: - case enums.publicKey.eddsa: - case enums.publicKey.ecdh: - if (config.rejectCurves.has(algoInfo.curve)) { - throw new Error(`Support for ${algoInfo.algorithm} keys using curve ${algoInfo.curve} is disabled.`); - } - break; - } -} - -/** - * @module key/User - * @private - */ - -/** - * Class that represents an user ID or attribute packet and the relevant signatures. - * @param {UserIDPacket|UserAttributePacket} userPacket - packet containing the user info - * @param {Key} mainKey - reference to main Key object containing the primary key and subkeys that the user is associated with - */ -class User { - constructor(userPacket, mainKey) { - this.userID = userPacket.constructor.tag === enums.packet.userID ? userPacket : null; - this.userAttribute = userPacket.constructor.tag === enums.packet.userAttribute ? userPacket : null; - this.selfCertifications = []; - this.otherCertifications = []; - this.revocationSignatures = []; - this.mainKey = mainKey; - } - - /** - * Transforms structured user data to packetlist - * @returns {PacketList} - */ - toPacketList() { - const packetlist = new PacketList(); - packetlist.push(this.userID || this.userAttribute); - packetlist.push(...this.revocationSignatures); - packetlist.push(...this.selfCertifications); - packetlist.push(...this.otherCertifications); - return packetlist; - } - - /** - * Shallow clone - * @returns {User} - */ - clone() { - const user = new User(this.userID || this.userAttribute, this.mainKey); - user.selfCertifications = [...this.selfCertifications]; - user.otherCertifications = [...this.otherCertifications]; - user.revocationSignatures = [...this.revocationSignatures]; - return user; - } - - /** - * Generate third-party certifications over this user and its primary key - * @param {Array} signingKeys - Decrypted private keys for signing - * @param {Date} [date] - Date to use as creation date of the certificate, instead of the current time - * @param {Object} config - Full configuration - * @returns {Promise} New user with new certifications. - * @async - */ - async certify(signingKeys, date, config) { - const primaryKey = this.mainKey.keyPacket; - const dataToSign = { - userID: this.userID, - userAttribute: this.userAttribute, - key: primaryKey - }; - const user = new User(dataToSign.userID || dataToSign.userAttribute, this.mainKey); - user.otherCertifications = await Promise.all(signingKeys.map(async function(privateKey) { - if (!privateKey.isPrivate()) { - throw new Error('Need private key for signing'); - } - if (privateKey.hasSameFingerprintAs(primaryKey)) { - throw new Error("The user's own key can only be used for self-certifications"); - } - const signingKey = await privateKey.getSigningKey(undefined, date, undefined, config); - return createSignaturePacket(dataToSign, privateKey, signingKey.keyPacket, { - // Most OpenPGP implementations use generic certification (0x10) - signatureType: enums.signature.certGeneric, - keyFlags: [enums.keyFlags.certifyKeys | enums.keyFlags.signData] - }, date, undefined, undefined, config); - })); - await user.update(this, date, config); - return user; - } - - /** - * Checks if a given certificate of the user is revoked - * @param {SignaturePacket} certificate - The certificate to verify - * @param {PublicSubkeyPacket| - * SecretSubkeyPacket| - * PublicKeyPacket| - * SecretKeyPacket} [keyPacket] The key packet to verify the signature, instead of the primary key - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} config - Full configuration - * @returns {Promise} True if the certificate is revoked. - * @async - */ - async isRevoked(certificate, keyPacket, date = new Date(), config) { - const primaryKey = this.mainKey.keyPacket; - return isDataRevoked(primaryKey, enums.signature.certRevocation, { - key: primaryKey, - userID: this.userID, - userAttribute: this.userAttribute - }, this.revocationSignatures, certificate, keyPacket, date, config); - } - - /** - * Verifies the user certificate. - * @param {SignaturePacket} certificate - A certificate of this user - * @param {Array} verificationKeys - Array of keys to verify certificate signatures - * @param {Date} [date] - Use the given date instead of the current time - * @param {Object} config - Full configuration - * @returns {Promise} true if the certificate could be verified, or null if the verification keys do not correspond to the certificate - * @throws if the user certificate is invalid. - * @async - */ - async verifyCertificate(certificate, verificationKeys, date = new Date(), config) { - const that = this; - const primaryKey = this.mainKey.keyPacket; - const dataToVerify = { - userID: this.userID, - userAttribute: this.userAttribute, - key: primaryKey - }; - const { issuerKeyID } = certificate; - const issuerKeys = verificationKeys.filter(key => key.getKeys(issuerKeyID).length > 0); - if (issuerKeys.length === 0) { - return null; - } - await Promise.all(issuerKeys.map(async key => { - const signingKey = await key.getSigningKey(issuerKeyID, certificate.created, undefined, config); - if (certificate.revoked || await that.isRevoked(certificate, signingKey.keyPacket, date, config)) { - throw new Error('User certificate is revoked'); - } - try { - await certificate.verify(signingKey.keyPacket, enums.signature.certGeneric, dataToVerify, date, undefined, config); - } catch (e) { - throw util.wrapError('User certificate is invalid', e); - } - })); - return true; - } - - /** - * Verifies all user certificates - * @param {Array} verificationKeys - Array of keys to verify certificate signatures - * @param {Date} [date] - Use the given date instead of the current time - * @param {Object} config - Full configuration - * @returns {Promise>} List of signer's keyID and validity of signature. - * Signature validity is null if the verification keys do not correspond to the certificate. - * @async - */ - async verifyAllCertifications(verificationKeys, date = new Date(), config) { - const that = this; - const certifications = this.selfCertifications.concat(this.otherCertifications); - return Promise.all(certifications.map(async certification => ({ - keyID: certification.issuerKeyID, - valid: await that.verifyCertificate(certification, verificationKeys, date, config).catch(() => false) - }))); - } - - /** - * Verify User. Checks for existence of self signatures, revocation signatures - * and validity of self signature. - * @param {Date} date - Use the given date instead of the current time - * @param {Object} config - Full configuration - * @returns {Promise} Status of user. - * @throws {Error} if there are no valid self signatures. - * @async - */ - async verify(date = new Date(), config) { - if (!this.selfCertifications.length) { - throw new Error('No self-certifications found'); - } - const that = this; - const primaryKey = this.mainKey.keyPacket; - const dataToVerify = { - userID: this.userID, - userAttribute: this.userAttribute, - key: primaryKey - }; - // TODO replace when Promise.some or Promise.any are implemented - let exception; - for (let i = this.selfCertifications.length - 1; i >= 0; i--) { - try { - const selfCertification = this.selfCertifications[i]; - if (selfCertification.revoked || await that.isRevoked(selfCertification, undefined, date, config)) { - throw new Error('Self-certification is revoked'); - } - try { - await selfCertification.verify(primaryKey, enums.signature.certGeneric, dataToVerify, date, undefined, config); - } catch (e) { - throw util.wrapError('Self-certification is invalid', e); - } - return true; - } catch (e) { - exception = e; - } - } - throw exception; - } - - /** - * Update user with new components from specified user - * @param {User} sourceUser - Source user to merge - * @param {Date} date - Date to verify the validity of signatures - * @param {Object} config - Full configuration - * @returns {Promise} - * @async - */ - async update(sourceUser, date, config) { - const primaryKey = this.mainKey.keyPacket; - const dataToVerify = { - userID: this.userID, - userAttribute: this.userAttribute, - key: primaryKey - }; - // self signatures - await mergeSignatures(sourceUser, this, 'selfCertifications', date, async function(srcSelfSig) { - try { - await srcSelfSig.verify(primaryKey, enums.signature.certGeneric, dataToVerify, date, false, config); - return true; - } catch (e) { - return false; - } - }); - // other signatures - await mergeSignatures(sourceUser, this, 'otherCertifications', date); - // revocation signatures - await mergeSignatures(sourceUser, this, 'revocationSignatures', date, function(srcRevSig) { - return isDataRevoked(primaryKey, enums.signature.certRevocation, dataToVerify, [srcRevSig], undefined, undefined, date, config); - }); - } -} - -/** - * @module key/Subkey - * @private - */ - -/** - * Class that represents a subkey packet and the relevant signatures. - * @borrows PublicSubkeyPacket#getKeyID as Subkey#getKeyID - * @borrows PublicSubkeyPacket#getFingerprint as Subkey#getFingerprint - * @borrows PublicSubkeyPacket#hasSameFingerprintAs as Subkey#hasSameFingerprintAs - * @borrows PublicSubkeyPacket#getAlgorithmInfo as Subkey#getAlgorithmInfo - * @borrows PublicSubkeyPacket#getCreationTime as Subkey#getCreationTime - * @borrows PublicSubkeyPacket#isDecrypted as Subkey#isDecrypted - */ -class Subkey { - /** - * @param {SecretSubkeyPacket|PublicSubkeyPacket} subkeyPacket - subkey packet to hold in the Subkey - * @param {Key} mainKey - reference to main Key object, containing the primary key packet corresponding to the subkey - */ - constructor(subkeyPacket, mainKey) { - this.keyPacket = subkeyPacket; - this.bindingSignatures = []; - this.revocationSignatures = []; - this.mainKey = mainKey; - } - - /** - * Transforms structured subkey data to packetlist - * @returns {PacketList} - */ - toPacketList() { - const packetlist = new PacketList(); - packetlist.push(this.keyPacket); - packetlist.push(...this.revocationSignatures); - packetlist.push(...this.bindingSignatures); - return packetlist; - } - - /** - * Shallow clone - * @return {Subkey} - */ - clone() { - const subkey = new Subkey(this.keyPacket, this.mainKey); - subkey.bindingSignatures = [...this.bindingSignatures]; - subkey.revocationSignatures = [...this.revocationSignatures]; - return subkey; - } - - /** - * Checks if a binding signature of a subkey is revoked - * @param {SignaturePacket} signature - The binding signature to verify - * @param {PublicSubkeyPacket| - * SecretSubkeyPacket| - * PublicKeyPacket| - * SecretKeyPacket} key, optional The key to verify the signature - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} True if the binding signature is revoked. - * @async - */ - async isRevoked(signature, key, date = new Date(), config = defaultConfig) { - const primaryKey = this.mainKey.keyPacket; - return isDataRevoked( - primaryKey, enums.signature.subkeyRevocation, { - key: primaryKey, - bind: this.keyPacket - }, this.revocationSignatures, signature, key, date, config - ); - } - - /** - * Verify subkey. Checks for revocation signatures, expiration time - * and valid binding signature. - * @param {Date} date - Use the given date instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} - * @throws {Error} if the subkey is invalid. - * @async - */ - async verify(date = new Date(), config = defaultConfig) { - const primaryKey = this.mainKey.keyPacket; - const dataToVerify = { key: primaryKey, bind: this.keyPacket }; - // check subkey binding signatures - const bindingSignature = await getLatestValidSignature(this.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); - // check binding signature is not revoked - if (bindingSignature.revoked || await this.isRevoked(bindingSignature, null, date, config)) { - throw new Error('Subkey is revoked'); - } - // check for expiration time - if (isDataExpired(this.keyPacket, bindingSignature, date)) { - throw new Error('Subkey is expired'); - } - return bindingSignature; - } - - /** - * Returns the expiration time of the subkey or Infinity if key does not expire. - * Returns null if the subkey is invalid. - * @param {Date} date - Use the given date instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} - * @async - */ - async getExpirationTime(date = new Date(), config = defaultConfig) { - const primaryKey = this.mainKey.keyPacket; - const dataToVerify = { key: primaryKey, bind: this.keyPacket }; - let bindingSignature; - try { - bindingSignature = await getLatestValidSignature(this.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); - } catch (e) { - return null; - } - const keyExpiry = getKeyExpirationTime(this.keyPacket, bindingSignature); - const sigExpiry = bindingSignature.getExpirationTime(); - return keyExpiry < sigExpiry ? keyExpiry : sigExpiry; - } - - /** - * Update subkey with new components from specified subkey - * @param {Subkey} subkey - Source subkey to merge - * @param {Date} [date] - Date to verify validity of signatures - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if update failed - * @async - */ - async update(subkey, date = new Date(), config = defaultConfig) { - const primaryKey = this.mainKey.keyPacket; - if (!this.hasSameFingerprintAs(subkey)) { - throw new Error('Subkey update method: fingerprints of subkeys not equal'); - } - // key packet - if (this.keyPacket.constructor.tag === enums.packet.publicSubkey && - subkey.keyPacket.constructor.tag === enums.packet.secretSubkey) { - this.keyPacket = subkey.keyPacket; - } - // update missing binding signatures - const that = this; - const dataToVerify = { key: primaryKey, bind: that.keyPacket }; - await mergeSignatures(subkey, this, 'bindingSignatures', date, async function(srcBindSig) { - for (let i = 0; i < that.bindingSignatures.length; i++) { - if (that.bindingSignatures[i].issuerKeyID.equals(srcBindSig.issuerKeyID)) { - if (srcBindSig.created > that.bindingSignatures[i].created) { - that.bindingSignatures[i] = srcBindSig; - } - return false; - } - } - try { - await srcBindSig.verify(primaryKey, enums.signature.subkeyBinding, dataToVerify, date, undefined, config); - return true; - } catch (e) { - return false; - } - }); - // revocation signatures - await mergeSignatures(subkey, this, 'revocationSignatures', date, function(srcRevSig) { - return isDataRevoked(primaryKey, enums.signature.subkeyRevocation, dataToVerify, [srcRevSig], undefined, undefined, date, config); - }); - } - - /** - * Revokes the subkey - * @param {SecretKeyPacket} primaryKey - decrypted private primary key for revocation - * @param {Object} reasonForRevocation - optional, object indicating the reason for revocation - * @param {module:enums.reasonForRevocation} reasonForRevocation.flag optional, flag indicating the reason for revocation - * @param {String} reasonForRevocation.string optional, string explaining the reason for revocation - * @param {Date} date - optional, override the creationtime of the revocation signature - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New subkey with revocation signature. - * @async - */ - async revoke( - primaryKey, - { - flag: reasonForRevocationFlag = enums.reasonForRevocation.noReason, - string: reasonForRevocationString = '' - } = {}, - date = new Date(), - config = defaultConfig - ) { - const dataToSign = { key: primaryKey, bind: this.keyPacket }; - const subkey = new Subkey(this.keyPacket, this.mainKey); - subkey.revocationSignatures.push(await createSignaturePacket(dataToSign, null, primaryKey, { - signatureType: enums.signature.subkeyRevocation, - reasonForRevocationFlag: enums.write(enums.reasonForRevocation, reasonForRevocationFlag), - reasonForRevocationString - }, date, undefined, false, config)); - await subkey.update(this); - return subkey; - } - - hasSameFingerprintAs(other) { - return this.keyPacket.hasSameFingerprintAs(other.keyPacket || other); - } -} - -['getKeyID', 'getFingerprint', 'getAlgorithmInfo', 'getCreationTime', 'isDecrypted'].forEach(name => { - Subkey.prototype[name] = - function() { - return this.keyPacket[name](); - }; -}); - -// GPG4Browsers - An OpenPGP implementation in javascript - -// A key revocation certificate can contain the following packets -const allowedRevocationPackets = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); - -/** - * Abstract class that represents an OpenPGP key. Must contain a primary key. - * Can contain additional subkeys, signatures, user ids, user attributes. - * @borrows PublicKeyPacket#getKeyID as Key#getKeyID - * @borrows PublicKeyPacket#getFingerprint as Key#getFingerprint - * @borrows PublicKeyPacket#hasSameFingerprintAs as Key#hasSameFingerprintAs - * @borrows PublicKeyPacket#getAlgorithmInfo as Key#getAlgorithmInfo - * @borrows PublicKeyPacket#getCreationTime as Key#getCreationTime - */ -class Key { - /** - * Transforms packetlist to structured key data - * @param {PacketList} packetlist - The packets that form a key - * @param {Set} disallowedPackets - disallowed packet tags - */ - packetListToStructure(packetlist, disallowedPackets = new Set()) { - let user; - let primaryKeyID; - let subkey; - for (const packet of packetlist) { - const tag = packet.constructor.tag; - if (disallowedPackets.has(tag)) { - throw new Error(`Unexpected packet type: ${tag}`); - } - switch (tag) { - case enums.packet.publicKey: - case enums.packet.secretKey: - if (this.keyPacket) { - throw new Error('Key block contains multiple keys'); - } - this.keyPacket = packet; - primaryKeyID = this.getKeyID(); - if (!primaryKeyID) { - throw new Error('Missing Key ID'); - } - break; - case enums.packet.userID: - case enums.packet.userAttribute: - user = new User(packet, this); - this.users.push(user); - break; - case enums.packet.publicSubkey: - case enums.packet.secretSubkey: - user = null; - subkey = new Subkey(packet, this); - this.subkeys.push(subkey); - break; - case enums.packet.signature: - switch (packet.signatureType) { - case enums.signature.certGeneric: - case enums.signature.certPersona: - case enums.signature.certCasual: - case enums.signature.certPositive: - if (!user) { - util.printDebug('Dropping certification signatures without preceding user packet'); - continue; - } - if (packet.issuerKeyID.equals(primaryKeyID)) { - user.selfCertifications.push(packet); - } else { - user.otherCertifications.push(packet); - } - break; - case enums.signature.certRevocation: - if (user) { - user.revocationSignatures.push(packet); - } else { - this.directSignatures.push(packet); - } - break; - case enums.signature.key: - this.directSignatures.push(packet); - break; - case enums.signature.subkeyBinding: - if (!subkey) { - util.printDebug('Dropping subkey binding signature without preceding subkey packet'); - continue; - } - subkey.bindingSignatures.push(packet); - break; - case enums.signature.keyRevocation: - this.revocationSignatures.push(packet); - break; - case enums.signature.subkeyRevocation: - if (!subkey) { - util.printDebug('Dropping subkey revocation signature without preceding subkey packet'); - continue; - } - subkey.revocationSignatures.push(packet); - break; - } - break; - } - } - } - - /** - * Transforms structured key data to packetlist - * @returns {PacketList} The packets that form a key. - */ - toPacketList() { - const packetlist = new PacketList(); - packetlist.push(this.keyPacket); - packetlist.push(...this.revocationSignatures); - packetlist.push(...this.directSignatures); - this.users.map(user => packetlist.push(...user.toPacketList())); - this.subkeys.map(subkey => packetlist.push(...subkey.toPacketList())); - return packetlist; - } - - /** - * Clones the key object - * @param {Boolean} [deep=false] Whether to return a deep clone - * @returns {Promise} Clone of the key. - */ - clone(deep = false) { - const key = new this.constructor(this.toPacketList()); - if (deep) { - key.getKeys().forEach(k => { - // shallow clone the key packets - k.keyPacket = Object.create( - Object.getPrototypeOf(k.keyPacket), - Object.getOwnPropertyDescriptors(k.keyPacket) - ); - if (!k.keyPacket.isDecrypted()) return; - // deep clone the private params, which are cleared during encryption - const privateParams = {}; - Object.keys(k.keyPacket.privateParams).forEach(name => { - privateParams[name] = new Uint8Array(k.keyPacket.privateParams[name]); - }); - k.keyPacket.privateParams = privateParams; - }); - } - return key; - } - - /** - * Returns an array containing all public or private subkeys matching keyID; - * If no keyID is given, returns all subkeys. - * @param {type/keyID} [keyID] - key ID to look for - * @returns {Array} array of subkeys - */ - getSubkeys(keyID = null) { - const subkeys = this.subkeys.filter(subkey => ( - !keyID || subkey.getKeyID().equals(keyID, true) - )); - return subkeys; - } - - /** - * Returns an array containing all public or private keys matching keyID. - * If no keyID is given, returns all keys, starting with the primary key. - * @param {type/keyid~KeyID} [keyID] - key ID to look for - * @returns {Array} array of keys - */ - getKeys(keyID = null) { - const keys = []; - if (!keyID || this.getKeyID().equals(keyID, true)) { - keys.push(this); - } - return keys.concat(this.getSubkeys(keyID)); - } - - /** - * Returns key IDs of all keys - * @returns {Array} - */ - getKeyIDs() { - return this.getKeys().map(key => key.getKeyID()); - } - - /** - * Returns userIDs - * @returns {Array} Array of userIDs. - */ - getUserIDs() { - return this.users.map(user => { - return user.userID ? user.userID.userID : null; - }).filter(userID => userID !== null); - } - - /** - * Returns binary encoded key - * @returns {Uint8Array} Binary key. - */ - write() { - return this.toPacketList().write(); - } - - /** - * Returns last created key or key by given keyID that is available for signing and verification - * @param {module:type/keyid~KeyID} [keyID] - key ID of a specific key to retrieve - * @param {Date} [date] - use the fiven date date to to check key validity instead of the current date - * @param {Object} [userID] - filter keys for the given user ID - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} signing key - * @throws if no valid signing key was found - * @async - */ - async getSigningKey(keyID = null, date = new Date(), userID = {}, config = defaultConfig) { - await this.verifyPrimaryKey(date, userID, config); - const primaryKey = this.keyPacket; - const subkeys = this.subkeys.slice().sort((a, b) => b.keyPacket.created - a.keyPacket.created); - let exception; - for (const subkey of subkeys) { - if (!keyID || subkey.getKeyID().equals(keyID)) { - try { - await subkey.verify(date, config); - const dataToVerify = { key: primaryKey, bind: subkey.keyPacket }; - const bindingSignature = await getLatestValidSignature( - subkey.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config - ); - if (!isValidSigningKeyPacket(subkey.keyPacket, bindingSignature)) { - continue; - } - if (!bindingSignature.embeddedSignature) { - throw new Error('Missing embedded signature'); - } - // verify embedded signature - await getLatestValidSignature( - [bindingSignature.embeddedSignature], subkey.keyPacket, enums.signature.keyBinding, dataToVerify, date, config - ); - checkKeyRequirements(subkey.keyPacket, config); - return subkey; - } catch (e) { - exception = e; - } - } - } - - try { - const primaryUser = await this.getPrimaryUser(date, userID, config); - if ((!keyID || primaryKey.getKeyID().equals(keyID)) && - isValidSigningKeyPacket(primaryKey, primaryUser.selfCertification, config)) { - checkKeyRequirements(primaryKey, config); - return this; - } - } catch (e) { - exception = e; - } - throw util.wrapError('Could not find valid signing key packet in key ' + this.getKeyID().toHex(), exception); - } - - /** - * Returns last created key or key by given keyID that is available for encryption or decryption - * @param {module:type/keyid~KeyID} [keyID] - key ID of a specific key to retrieve - * @param {Date} [date] - use the fiven date date to to check key validity instead of the current date - * @param {Object} [userID] - filter keys for the given user ID - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} encryption key - * @throws if no valid encryption key was found - * @async - */ - async getEncryptionKey(keyID, date = new Date(), userID = {}, config = defaultConfig) { - await this.verifyPrimaryKey(date, userID, config); - const primaryKey = this.keyPacket; - // V4: by convention subkeys are preferred for encryption service - const subkeys = this.subkeys.slice().sort((a, b) => b.keyPacket.created - a.keyPacket.created); - let exception; - for (const subkey of subkeys) { - if (!keyID || subkey.getKeyID().equals(keyID)) { - try { - await subkey.verify(date, config); - const dataToVerify = { key: primaryKey, bind: subkey.keyPacket }; - const bindingSignature = await getLatestValidSignature(subkey.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); - if (isValidEncryptionKeyPacket(subkey.keyPacket, bindingSignature)) { - checkKeyRequirements(subkey.keyPacket, config); - return subkey; - } - } catch (e) { - exception = e; - } - } - } - - try { - // if no valid subkey for encryption, evaluate primary key - const primaryUser = await this.getPrimaryUser(date, userID, config); - if ((!keyID || primaryKey.getKeyID().equals(keyID)) && - isValidEncryptionKeyPacket(primaryKey, primaryUser.selfCertification)) { - checkKeyRequirements(primaryKey, config); - return this; - } - } catch (e) { - exception = e; - } - throw util.wrapError('Could not find valid encryption key packet in key ' + this.getKeyID().toHex(), exception); - } - - /** - * Checks if a signature on a key is revoked - * @param {SignaturePacket} signature - The signature to verify - * @param {PublicSubkeyPacket| - * SecretSubkeyPacket| - * PublicKeyPacket| - * SecretKeyPacket} key, optional The key to verify the signature - * @param {Date} [date] - Use the given date for verification, instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} True if the certificate is revoked. - * @async - */ - async isRevoked(signature, key, date = new Date(), config = defaultConfig) { - return isDataRevoked( - this.keyPacket, enums.signature.keyRevocation, { key: this.keyPacket }, this.revocationSignatures, signature, key, date, config - ); - } - - /** - * Verify primary key. Checks for revocation signatures, expiration time - * and valid self signature. Throws if the primary key is invalid. - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} [userID] - User ID - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} If key verification failed - * @async - */ - async verifyPrimaryKey(date = new Date(), userID = {}, config = defaultConfig) { - const primaryKey = this.keyPacket; - // check for key revocation signatures - if (await this.isRevoked(null, null, date, config)) { - throw new Error('Primary key is revoked'); - } - // check for valid, unrevoked, unexpired self signature - const { selfCertification } = await this.getPrimaryUser(date, userID, config); - // check for expiration time in binding signatures - if (isDataExpired(primaryKey, selfCertification, date)) { - throw new Error('Primary key is expired'); - } - // check for expiration time in direct signatures - const directSignature = await getLatestValidSignature( - this.directSignatures, primaryKey, enums.signature.key, { key: primaryKey }, date, config - ).catch(() => {}); // invalid signatures are discarded, to avoid breaking the key - - if (directSignature && isDataExpired(primaryKey, directSignature, date)) { - throw new Error('Primary key is expired'); - } - } - - /** - * Returns the expiration date of the primary key, considering self-certifications and direct-key signatures. - * Returns `Infinity` if the key doesn't expire, or `null` if the key is revoked or invalid. - * @param {Object} [userID] - User ID to consider instead of the primary user - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} - * @async - */ - async getExpirationTime(userID, config = defaultConfig) { - let primaryKeyExpiry; - try { - const { selfCertification } = await this.getPrimaryUser(null, userID, config); - const selfSigKeyExpiry = getKeyExpirationTime(this.keyPacket, selfCertification); - const selfSigExpiry = selfCertification.getExpirationTime(); - const directSignature = await getLatestValidSignature( - this.directSignatures, this.keyPacket, enums.signature.key, { key: this.keyPacket }, null, config - ).catch(() => {}); - if (directSignature) { - const directSigKeyExpiry = getKeyExpirationTime(this.keyPacket, directSignature); - // We do not support the edge case where the direct signature expires, since it would invalidate the corresponding key expiration, - // causing a discountinous validy period for the key - primaryKeyExpiry = Math.min(selfSigKeyExpiry, selfSigExpiry, directSigKeyExpiry); - } else { - primaryKeyExpiry = selfSigKeyExpiry < selfSigExpiry ? selfSigKeyExpiry : selfSigExpiry; - } - } catch (e) { - primaryKeyExpiry = null; - } - - return util.normalizeDate(primaryKeyExpiry); - } - - - /** - * Returns primary user and most significant (latest valid) self signature - * - if multiple primary users exist, returns the one with the latest self signature - * - otherwise, returns the user with the latest self signature - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} [userID] - User ID to get instead of the primary user, if it exists - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise<{ - * user: User, - * selfCertification: SignaturePacket - * }>} The primary user and the self signature - * @async - */ - async getPrimaryUser(date = new Date(), userID = {}, config = defaultConfig) { - const primaryKey = this.keyPacket; - const users = []; - let exception; - for (let i = 0; i < this.users.length; i++) { - try { - const user = this.users[i]; - if (!user.userID) { - continue; - } - if ( - (userID.name !== undefined && user.userID.name !== userID.name) || - (userID.email !== undefined && user.userID.email !== userID.email) || - (userID.comment !== undefined && user.userID.comment !== userID.comment) - ) { - throw new Error('Could not find user that matches that user ID'); - } - const dataToVerify = { userID: user.userID, key: primaryKey }; - const selfCertification = await getLatestValidSignature(user.selfCertifications, primaryKey, enums.signature.certGeneric, dataToVerify, date, config); - users.push({ index: i, user, selfCertification }); - } catch (e) { - exception = e; - } - } - if (!users.length) { - throw exception || new Error('Could not find primary user'); - } - await Promise.all(users.map(async function (a) { - return a.user.revoked || a.user.isRevoked(a.selfCertification, null, date, config); - })); - // sort by primary user flag and signature creation time - const primaryUser = users.sort(function(a, b) { - const A = a.selfCertification; - const B = b.selfCertification; - return B.revoked - A.revoked || A.isPrimaryUserID - B.isPrimaryUserID || A.created - B.created; - }).pop(); - const { user, selfCertification: cert } = primaryUser; - if (cert.revoked || await user.isRevoked(cert, null, date, config)) { - throw new Error('Primary user is revoked'); - } - return primaryUser; - } - - /** - * Update key with new components from specified key with same key ID: - * users, subkeys, certificates are merged into the destination key, - * duplicates and expired signatures are ignored. - * - * If the source key is a private key and the destination key is public, - * a private key is returned. - * @param {Key} sourceKey - Source key to merge - * @param {Date} [date] - Date to verify validity of signatures and keys - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} updated key - * @async - */ - async update(sourceKey, date = new Date(), config = defaultConfig) { - if (!this.hasSameFingerprintAs(sourceKey)) { - throw new Error('Primary key fingerprints must be equal to update the key'); - } - if (!this.isPrivate() && sourceKey.isPrivate()) { - // check for equal subkey packets - const equal = (this.subkeys.length === sourceKey.subkeys.length) && - (this.subkeys.every(destSubkey => { - return sourceKey.subkeys.some(srcSubkey => { - return destSubkey.hasSameFingerprintAs(srcSubkey); - }); - })); - if (!equal) { - throw new Error('Cannot update public key with private key if subkeys mismatch'); - } - - return sourceKey.update(this, config); - } - // from here on, either: - // - destination key is private, source key is public - // - the keys are of the same type - // hence we don't need to convert the destination key type - const updatedKey = this.clone(); - // revocation signatures - await mergeSignatures(sourceKey, updatedKey, 'revocationSignatures', date, srcRevSig => { - return isDataRevoked(updatedKey.keyPacket, enums.signature.keyRevocation, updatedKey, [srcRevSig], null, sourceKey.keyPacket, date, config); - }); - // direct signatures - await mergeSignatures(sourceKey, updatedKey, 'directSignatures', date); - // update users - await Promise.all(sourceKey.users.map(async srcUser => { - // multiple users with the same ID/attribute are not explicitly disallowed by the spec - // hence we support them, just in case - const usersToUpdate = updatedKey.users.filter(dstUser => ( - (srcUser.userID && srcUser.userID.equals(dstUser.userID)) || - (srcUser.userAttribute && srcUser.userAttribute.equals(dstUser.userAttribute)) - )); - if (usersToUpdate.length > 0) { - await Promise.all( - usersToUpdate.map(userToUpdate => userToUpdate.update(srcUser, date, config)) - ); - } else { - const newUser = srcUser.clone(); - newUser.mainKey = updatedKey; - updatedKey.users.push(newUser); - } - })); - // update subkeys - await Promise.all(sourceKey.subkeys.map(async srcSubkey => { - // multiple subkeys with same fingerprint might be preset - const subkeysToUpdate = updatedKey.subkeys.filter(dstSubkey => ( - dstSubkey.hasSameFingerprintAs(srcSubkey) - )); - if (subkeysToUpdate.length > 0) { - await Promise.all( - subkeysToUpdate.map(subkeyToUpdate => subkeyToUpdate.update(srcSubkey, date, config)) - ); - } else { - const newSubkey = srcSubkey.clone(); - newSubkey.mainKey = updatedKey; - updatedKey.subkeys.push(newSubkey); - } - })); - - return updatedKey; - } - - /** - * Get revocation certificate from a revoked key. - * (To get a revocation certificate for an unrevoked key, call revoke() first.) - * @param {Date} date - Use the given date instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} Armored revocation certificate. - * @async - */ - async getRevocationCertificate(date = new Date(), config = defaultConfig) { - const dataToVerify = { key: this.keyPacket }; - const revocationSignature = await getLatestValidSignature(this.revocationSignatures, this.keyPacket, enums.signature.keyRevocation, dataToVerify, date, config); - const packetlist = new PacketList(); - packetlist.push(revocationSignature); - return armor(enums.armor.publicKey, packetlist.write(), null, null, 'This is a revocation certificate'); - } - - /** - * Applies a revocation certificate to a key - * This adds the first signature packet in the armored text to the key, - * if it is a valid revocation signature. - * @param {String} revocationCertificate - armored revocation certificate - * @param {Date} [date] - Date to verify the certificate - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} Revoked key. - * @async - */ - async applyRevocationCertificate(revocationCertificate, date = new Date(), config = defaultConfig) { - const input = await unarmor(revocationCertificate, config); - const packetlist = await PacketList.fromBinary(input.data, allowedRevocationPackets, config); - const revocationSignature = packetlist.findPacket(enums.packet.signature); - if (!revocationSignature || revocationSignature.signatureType !== enums.signature.keyRevocation) { - throw new Error('Could not find revocation signature packet'); - } - if (!revocationSignature.issuerKeyID.equals(this.getKeyID())) { - throw new Error('Revocation signature does not match key'); - } - try { - await revocationSignature.verify(this.keyPacket, enums.signature.keyRevocation, { key: this.keyPacket }, date, undefined, config); - } catch (e) { - throw util.wrapError('Could not verify revocation signature', e); - } - const key = this.clone(); - key.revocationSignatures.push(revocationSignature); - return key; - } - - /** - * Signs primary user of key - * @param {Array} privateKeys - decrypted private keys for signing - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} [userID] - User ID to get instead of the primary user, if it exists - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} Key with new certificate signature. - * @async - */ - async signPrimaryUser(privateKeys, date, userID, config = defaultConfig) { - const { index, user } = await this.getPrimaryUser(date, userID, config); - const userSign = await user.certify(privateKeys, date, config); - const key = this.clone(); - key.users[index] = userSign; - return key; - } - - /** - * Signs all users of key - * @param {Array} privateKeys - decrypted private keys for signing - * @param {Date} [date] - Use the given date for signing, instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} Key with new certificate signature. - * @async - */ - async signAllUsers(privateKeys, date = new Date(), config = defaultConfig) { - const key = this.clone(); - key.users = await Promise.all(this.users.map(function(user) { - return user.certify(privateKeys, date, config); - })); - return key; - } - - /** - * Verifies primary user of key - * - if no arguments are given, verifies the self certificates; - * - otherwise, verifies all certificates signed with given keys. - * @param {Array} [verificationKeys] - array of keys to verify certificate signatures, instead of the primary key - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} [userID] - User ID to get instead of the primary user, if it exists - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise>} List of signer's keyID and validity of signature. - * Signature validity is null if the verification keys do not correspond to the certificate. - * @async - */ - async verifyPrimaryUser(verificationKeys, date = new Date(), userID, config = defaultConfig) { - const primaryKey = this.keyPacket; - const { user } = await this.getPrimaryUser(date, userID, config); - const results = verificationKeys ? - await user.verifyAllCertifications(verificationKeys, date, config) : - [{ keyID: primaryKey.getKeyID(), valid: await user.verify(date, config).catch(() => false) }]; - return results; - } - - /** - * Verifies all users of key - * - if no arguments are given, verifies the self certificates; - * - otherwise, verifies all certificates signed with given keys. - * @param {Array} [verificationKeys] - array of keys to verify certificate signatures - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise>} List of userID, signer's keyID and validity of signature. - * Signature validity is null if the verification keys do not correspond to the certificate. - * @async - */ - async verifyAllUsers(verificationKeys, date = new Date(), config = defaultConfig) { - const primaryKey = this.keyPacket; - const results = []; - await Promise.all(this.users.map(async user => { - const signatures = verificationKeys ? - await user.verifyAllCertifications(verificationKeys, date, config) : - [{ keyID: primaryKey.getKeyID(), valid: await user.verify(date, config).catch(() => false) }]; - - results.push(...signatures.map( - signature => ({ - userID: user.userID.userID, - keyID: signature.keyID, - valid: signature.valid - })) - ); - })); - return results; - } -} - -['getKeyID', 'getFingerprint', 'getAlgorithmInfo', 'getCreationTime', 'hasSameFingerprintAs'].forEach(name => { - Key.prototype[name] = - Subkey.prototype[name]; -}); - -/** - * Creates a PublicKey or PrivateKey depending on the packetlist in input - * @param {PacketList} - packets to parse - * @return {Key} parsed key - * @throws if no key packet was found - */ -function createKey(packetlist) { - for (const packet of packetlist) { - switch (packet.constructor.tag) { - case enums.packet.secretKey: - return new PrivateKey(packetlist); - case enums.packet.publicKey: - return new PublicKey(packetlist); - } - } - throw new Error('No key packet found'); -} - -// This library is free software; you can redistribute it and/or - -/** - * Class that represents an OpenPGP Public Key - */ -class PublicKey extends Key { - /** - * @param {PacketList} packetlist - The packets that form this key - */ - constructor(packetlist) { - super(); - this.keyPacket = null; - this.revocationSignatures = []; - this.directSignatures = []; - this.users = []; - this.subkeys = []; - if (packetlist) { - this.packetListToStructure(packetlist, new Set([enums.packet.secretKey, enums.packet.secretSubkey])); - if (!this.keyPacket) { - throw new Error('Invalid key: missing public-key packet'); - } - } - } - - /** - * Returns true if this is a private key - * @returns {false} - */ - isPrivate() { - return false; - } - - /** - * Returns key as public key (shallow copy) - * @returns {PublicKey} New public Key - */ - toPublic() { - return this; - } - - /** - * Returns ASCII armored text of key - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {ReadableStream} ASCII armor. - */ - armor(config = defaultConfig) { - return armor(enums.armor.publicKey, this.toPacketList().write(), undefined, undefined, undefined, config); - } -} - -/** - * Class that represents an OpenPGP Private key - */ -class PrivateKey extends PublicKey { - /** - * @param {PacketList} packetlist - The packets that form this key - */ - constructor(packetlist) { - super(); - this.packetListToStructure(packetlist, new Set([enums.packet.publicKey, enums.packet.publicSubkey])); - if (!this.keyPacket) { - throw new Error('Invalid key: missing private-key packet'); - } - } - - /** - * Returns true if this is a private key - * @returns {Boolean} - */ - isPrivate() { - return true; - } - - /** - * Returns key as public key (shallow copy) - * @returns {PublicKey} New public Key - */ - toPublic() { - const packetlist = new PacketList(); - const keyPackets = this.toPacketList(); - for (const keyPacket of keyPackets) { - switch (keyPacket.constructor.tag) { - case enums.packet.secretKey: { - const pubKeyPacket = PublicKeyPacket.fromSecretKeyPacket(keyPacket); - packetlist.push(pubKeyPacket); - break; - } - case enums.packet.secretSubkey: { - const pubSubkeyPacket = PublicSubkeyPacket.fromSecretSubkeyPacket(keyPacket); - packetlist.push(pubSubkeyPacket); - break; - } - default: - packetlist.push(keyPacket); - } - } - return new PublicKey(packetlist); - } - - /** - * Returns ASCII armored text of key - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {ReadableStream} ASCII armor. - */ - armor(config = defaultConfig) { - return armor(enums.armor.privateKey, this.toPacketList().write(), undefined, undefined, undefined, config); - } - - /** - * Returns all keys that are available for decryption, matching the keyID when given - * This is useful to retrieve keys for session key decryption - * @param {module:type/keyid~KeyID} keyID, optional - * @param {Date} date, optional - * @param {String} userID, optional - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise>} Array of decryption keys. - * @async - */ - async getDecryptionKeys(keyID, date = new Date(), userID = {}, config = defaultConfig) { - const primaryKey = this.keyPacket; - const keys = []; - for (let i = 0; i < this.subkeys.length; i++) { - if (!keyID || this.subkeys[i].getKeyID().equals(keyID, true)) { - try { - const dataToVerify = { key: primaryKey, bind: this.subkeys[i].keyPacket }; - const bindingSignature = await getLatestValidSignature(this.subkeys[i].bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); - if (isValidDecryptionKeyPacket(bindingSignature, config)) { - keys.push(this.subkeys[i]); - } - } catch (e) {} - } - } - - // evaluate primary key - const primaryUser = await this.getPrimaryUser(date, userID, config); - if ((!keyID || primaryKey.getKeyID().equals(keyID, true)) && - isValidDecryptionKeyPacket(primaryUser.selfCertification, config)) { - keys.push(this); - } - - return keys; - } - - /** - * Returns true if the primary key or any subkey is decrypted. - * A dummy key is considered encrypted. - */ - isDecrypted() { - return this.getKeys().some(({ keyPacket }) => keyPacket.isDecrypted()); - } - - /** - * Check whether the private and public primary key parameters correspond - * Together with verification of binding signatures, this guarantees key integrity - * In case of gnu-dummy primary key, it is enough to validate any signing subkeys - * otherwise all encryption subkeys are validated - * If only gnu-dummy keys are found, we cannot properly validate so we throw an error - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if validation was not successful and the key cannot be trusted - * @async - */ - async validate(config = defaultConfig) { - if (!this.isPrivate()) { - throw new Error('Cannot validate a public key'); - } - - let signingKeyPacket; - if (!this.keyPacket.isDummy()) { - signingKeyPacket = this.keyPacket; - } else { - /** - * It is enough to validate any signing keys - * since its binding signatures are also checked - */ - const signingKey = await this.getSigningKey(null, null, undefined, { ...config, rejectPublicKeyAlgorithms: new Set(), minRSABits: 0 }); - // This could again be a dummy key - if (signingKey && !signingKey.keyPacket.isDummy()) { - signingKeyPacket = signingKey.keyPacket; - } - } - - if (signingKeyPacket) { - return signingKeyPacket.validate(); - } else { - const keys = this.getKeys(); - const allDummies = keys.map(key => key.keyPacket.isDummy()).every(Boolean); - if (allDummies) { - throw new Error('Cannot validate an all-gnu-dummy key'); - } - - return Promise.all(keys.map(async key => key.keyPacket.validate())); - } - } - - /** - * Clear private key parameters - */ - clearPrivateParams() { - this.getKeys().forEach(({ keyPacket }) => { - if (keyPacket.isDecrypted()) { - keyPacket.clearPrivateParams(); - } - }); - } - - /** - * Revokes the key - * @param {Object} reasonForRevocation - optional, object indicating the reason for revocation - * @param {module:enums.reasonForRevocation} reasonForRevocation.flag optional, flag indicating the reason for revocation - * @param {String} reasonForRevocation.string optional, string explaining the reason for revocation - * @param {Date} date - optional, override the creationtime of the revocation signature - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New key with revocation signature. - * @async - */ - async revoke( - { - flag: reasonForRevocationFlag = enums.reasonForRevocation.noReason, - string: reasonForRevocationString = '' - } = {}, - date = new Date(), - config = defaultConfig - ) { - if (!this.isPrivate()) { - throw new Error('Need private key for revoking'); - } - const dataToSign = { key: this.keyPacket }; - const key = this.clone(); - key.revocationSignatures.push(await createSignaturePacket(dataToSign, null, this.keyPacket, { - signatureType: enums.signature.keyRevocation, - reasonForRevocationFlag: enums.write(enums.reasonForRevocation, reasonForRevocationFlag), - reasonForRevocationString - }, date, undefined, undefined, config)); - return key; - } - - - /** - * Generates a new OpenPGP subkey, and returns a clone of the Key object with the new subkey added. - * Supports RSA and ECC keys. Defaults to the algorithm and bit size/curve of the primary key. DSA primary keys default to RSA subkeys. - * @param {ecc|rsa} options.type The subkey algorithm: ECC or RSA - * @param {String} options.curve (optional) Elliptic curve for ECC keys - * @param {Integer} options.rsaBits (optional) Number of bits for RSA subkeys - * @param {Number} options.keyExpirationTime (optional) Number of seconds from the key creation time after which the key expires - * @param {Date} options.date (optional) Override the creation date of the key and the key signatures - * @param {Boolean} options.sign (optional) Indicates whether the subkey should sign rather than encrypt. Defaults to false - * @param {Object} options.config (optional) custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} - * @async - */ - async addSubkey(options = {}) { - const config = { ...defaultConfig, ...options.config }; - if (options.passphrase) { - throw new Error('Subkey could not be encrypted here, please encrypt whole key'); - } - if (options.rsaBits < config.minRSABits) { - throw new Error(`rsaBits should be at least ${config.minRSABits}, got: ${options.rsaBits}`); - } - const secretKeyPacket = this.keyPacket; - if (secretKeyPacket.isDummy()) { - throw new Error('Cannot add subkey to gnu-dummy primary key'); - } - if (!secretKeyPacket.isDecrypted()) { - throw new Error('Key is not decrypted'); - } - const defaultOptions = secretKeyPacket.getAlgorithmInfo(); - defaultOptions.type = defaultOptions.curve ? 'ecc' : 'rsa'; // DSA keys default to RSA - defaultOptions.rsaBits = defaultOptions.bits || 4096; - defaultOptions.curve = defaultOptions.curve || 'curve25519'; - options = sanitizeKeyOptions(options, defaultOptions); - const keyPacket = await generateSecretSubkey(options); - checkKeyRequirements(keyPacket, config); - const bindingSignature = await createBindingSignature(keyPacket, secretKeyPacket, options, config); - const packetList = this.toPacketList(); - packetList.push(keyPacket, bindingSignature); - return new PrivateKey(packetList); - } -} - -// OpenPGP.js - An OpenPGP implementation in javascript - -// A Key can contain the following packets -const allowedKeyPackets = /*#__PURE__*/ util.constructAllowedPackets([ - PublicKeyPacket, - PublicSubkeyPacket, - SecretKeyPacket, - SecretSubkeyPacket, - UserIDPacket, - UserAttributePacket, - SignaturePacket -]); - -/** - * Generates a new OpenPGP key. Supports RSA and ECC keys. - * By default, primary and subkeys will be of same type. - * @param {ecc|rsa} options.type The primary key algorithm type: ECC or RSA - * @param {String} options.curve Elliptic curve for ECC keys - * @param {Integer} options.rsaBits Number of bits for RSA keys - * @param {Array} options.userIDs User IDs as strings or objects: 'Jo Doe ' or { name:'Jo Doe', email:'info@jo.com' } - * @param {String} options.passphrase Passphrase used to encrypt the resulting private key - * @param {Number} options.keyExpirationTime (optional) Number of seconds from the key creation time after which the key expires - * @param {Date} options.date Creation date of the key and the key signatures - * @param {Object} config - Full configuration - * @param {Array} options.subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}] - * sign parameter defaults to false, and indicates whether the subkey should sign rather than encrypt - * @returns {Promise<{{ key: PrivateKey, revocationCertificate: String }}>} - * @async - * @static - * @private - */ -async function generate$2(options, config) { - options.sign = true; // primary key is always a signing key - options = sanitizeKeyOptions(options); - options.subkeys = options.subkeys.map((subkey, index) => sanitizeKeyOptions(options.subkeys[index], options)); - let promises = [generateSecretKey(options, config)]; - promises = promises.concat(options.subkeys.map(options => generateSecretSubkey(options, config))); - const packets = await Promise.all(promises); - - const key = await wrapKeyObject(packets[0], packets.slice(1), options, config); - const revocationCertificate = await key.getRevocationCertificate(options.date, config); - key.revocationSignatures = []; - return { key, revocationCertificate }; -} - -/** - * Reformats and signs an OpenPGP key with a given User ID. Currently only supports RSA keys. - * @param {PrivateKey} options.privateKey The private key to reformat - * @param {Array} options.userIDs User IDs as strings or objects: 'Jo Doe ' or { name:'Jo Doe', email:'info@jo.com' } - * @param {String} options.passphrase Passphrase used to encrypt the resulting private key - * @param {Number} options.keyExpirationTime Number of seconds from the key creation time after which the key expires - * @param {Date} options.date Override the creation date of the key signatures - * @param {Array} options.subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}] - * @param {Object} config - Full configuration - * - * @returns {Promise<{{ key: PrivateKey, revocationCertificate: String }}>} - * @async - * @static - * @private - */ -async function reformat(options, config) { - options = sanitize(options); - const { privateKey } = options; - - if (!privateKey.isPrivate()) { - throw new Error('Cannot reformat a public key'); - } - - if (privateKey.keyPacket.isDummy()) { - throw new Error('Cannot reformat a gnu-dummy primary key'); - } - - const isDecrypted = privateKey.getKeys().every(({ keyPacket }) => keyPacket.isDecrypted()); - if (!isDecrypted) { - throw new Error('Key is not decrypted'); - } - - const secretKeyPacket = privateKey.keyPacket; - - if (!options.subkeys) { - options.subkeys = await Promise.all(privateKey.subkeys.map(async subkey => { - const secretSubkeyPacket = subkey.keyPacket; - const dataToVerify = { key: secretKeyPacket, bind: secretSubkeyPacket }; - const bindingSignature = await ( - getLatestValidSignature(subkey.bindingSignatures, secretKeyPacket, enums.signature.subkeyBinding, dataToVerify, null, config) - ).catch(() => ({})); - return { - sign: bindingSignature.keyFlags && (bindingSignature.keyFlags[0] & enums.keyFlags.signData) - }; - })); - } - - const secretSubkeyPackets = privateKey.subkeys.map(subkey => subkey.keyPacket); - if (options.subkeys.length !== secretSubkeyPackets.length) { - throw new Error('Number of subkey options does not match number of subkeys'); - } - - options.subkeys = options.subkeys.map(subkeyOptions => sanitize(subkeyOptions, options)); - - const key = await wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options, config); - const revocationCertificate = await key.getRevocationCertificate(options.date, config); - key.revocationSignatures = []; - return { key, revocationCertificate }; - - function sanitize(options, subkeyDefaults = {}) { - options.keyExpirationTime = options.keyExpirationTime || subkeyDefaults.keyExpirationTime; - options.passphrase = util.isString(options.passphrase) ? options.passphrase : subkeyDefaults.passphrase; - options.date = options.date || subkeyDefaults.date; - - return options; - } -} - -/** - * Construct PrivateKey object from the given key packets, add certification signatures and set passphrase protection - * The new key includes a revocation certificate that must be removed before returning the key, otherwise the key is considered revoked. - * @param {SecretKeyPacket} secretKeyPacket - * @param {SecretSubkeyPacket} secretSubkeyPackets - * @param {Object} options - * @param {Object} config - Full configuration - * @returns {PrivateKey} - */ -async function wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options, config) { - // set passphrase protection - if (options.passphrase) { - await secretKeyPacket.encrypt(options.passphrase, config); - } - - await Promise.all(secretSubkeyPackets.map(async function(secretSubkeyPacket, index) { - const subkeyPassphrase = options.subkeys[index].passphrase; - if (subkeyPassphrase) { - await secretSubkeyPacket.encrypt(subkeyPassphrase, config); - } - })); - - const packetlist = new PacketList(); - packetlist.push(secretKeyPacket); - - await Promise.all(options.userIDs.map(async function(userID, index) { - function createPreferredAlgos(algos, preferredAlgo) { - return [preferredAlgo, ...algos.filter(algo => algo !== preferredAlgo)]; - } - - const userIDPacket = UserIDPacket.fromObject(userID); - const dataToSign = {}; - dataToSign.userID = userIDPacket; - dataToSign.key = secretKeyPacket; - const signaturePacket = new SignaturePacket(); - signaturePacket.signatureType = enums.signature.certGeneric; - signaturePacket.publicKeyAlgorithm = secretKeyPacket.algorithm; - signaturePacket.hashAlgorithm = await getPreferredHashAlgo$1(null, secretKeyPacket, undefined, undefined, config); - signaturePacket.keyFlags = [enums.keyFlags.certifyKeys | enums.keyFlags.signData]; - signaturePacket.preferredSymmetricAlgorithms = createPreferredAlgos([ - // prefer aes256, aes128, then aes192 (no WebCrypto support: https://www.chromium.org/blink/webcrypto#TOC-AES-support) - enums.symmetric.aes256, - enums.symmetric.aes128, - enums.symmetric.aes192 - ], config.preferredSymmetricAlgorithm); - if (config.aeadProtect) { - signaturePacket.preferredAEADAlgorithms = createPreferredAlgos([ - enums.aead.eax, - enums.aead.ocb - ], config.preferredAEADAlgorithm); - } - signaturePacket.preferredHashAlgorithms = createPreferredAlgos([ - // prefer fast asm.js implementations (SHA-256) - enums.hash.sha256, - enums.hash.sha512 - ], config.preferredHashAlgorithm); - signaturePacket.preferredCompressionAlgorithms = createPreferredAlgos([ - enums.compression.zlib, - enums.compression.zip, - enums.compression.uncompressed - ], config.preferredCompressionAlgorithm); - if (index === 0) { - signaturePacket.isPrimaryUserID = true; - } - // integrity protection always enabled - signaturePacket.features = [0]; - signaturePacket.features[0] |= enums.features.modificationDetection; - if (config.aeadProtect) { - signaturePacket.features[0] |= enums.features.aead; - } - if (config.v5Keys) { - signaturePacket.features[0] |= enums.features.v5Keys; - } - if (options.keyExpirationTime > 0) { - signaturePacket.keyExpirationTime = options.keyExpirationTime; - signaturePacket.keyNeverExpires = false; - } - await signaturePacket.sign(secretKeyPacket, dataToSign, options.date); - - return { userIDPacket, signaturePacket }; - })).then(list => { - list.forEach(({ userIDPacket, signaturePacket }) => { - packetlist.push(userIDPacket); - packetlist.push(signaturePacket); - }); - }); - - await Promise.all(secretSubkeyPackets.map(async function(secretSubkeyPacket, index) { - const subkeyOptions = options.subkeys[index]; - const subkeySignaturePacket = await createBindingSignature(secretSubkeyPacket, secretKeyPacket, subkeyOptions, config); - return { secretSubkeyPacket, subkeySignaturePacket }; - })).then(packets => { - packets.forEach(({ secretSubkeyPacket, subkeySignaturePacket }) => { - packetlist.push(secretSubkeyPacket); - packetlist.push(subkeySignaturePacket); - }); - }); - - // Add revocation signature packet for creating a revocation certificate. - // This packet should be removed before returning the key. - const dataToSign = { key: secretKeyPacket }; - packetlist.push(await createSignaturePacket(dataToSign, null, secretKeyPacket, { - signatureType: enums.signature.keyRevocation, - reasonForRevocationFlag: enums.reasonForRevocation.noReason, - reasonForRevocationString: '' - }, options.date, undefined, undefined, config)); - - if (options.passphrase) { - secretKeyPacket.clearPrivateParams(); - } - - await Promise.all(secretSubkeyPackets.map(async function(secretSubkeyPacket, index) { - const subkeyPassphrase = options.subkeys[index].passphrase; - if (subkeyPassphrase) { - secretSubkeyPacket.clearPrivateParams(); - } - })); - - return new PrivateKey(packetlist); -} - -/** - * Reads an (optionally armored) OpenPGP key and returns a key object - * @param {Object} options - * @param {String} [options.armoredKey] - Armored key to be parsed - * @param {Uint8Array} [options.binaryKey] - Binary key to be parsed - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} Key object. - * @async - * @static - */ -async function readKey({ armoredKey, binaryKey, config, ...rest }) { - config = { ...defaultConfig, ...config }; - if (!armoredKey && !binaryKey) { - throw new Error('readKey: must pass options object containing `armoredKey` or `binaryKey`'); - } - if (armoredKey && !util.isString(armoredKey)) { - throw new Error('readKey: options.armoredKey must be a string'); - } - if (binaryKey && !util.isUint8Array(binaryKey)) { - throw new Error('readKey: options.binaryKey must be a Uint8Array'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - let input; - if (armoredKey) { - const { type, data } = await unarmor(armoredKey, config); - if (!(type === enums.armor.publicKey || type === enums.armor.privateKey)) { - throw new Error('Armored text not of type key'); - } - input = data; - } else { - input = binaryKey; - } - const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); - return createKey(packetlist); -} - -/** - * Reads an (optionally armored) OpenPGP private key and returns a PrivateKey object - * @param {Object} options - * @param {String} [options.armoredKey] - Armored key to be parsed - * @param {Uint8Array} [options.binaryKey] - Binary key to be parsed - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} Key object. - * @async - * @static - */ -async function readPrivateKey({ armoredKey, binaryKey, config, ...rest }) { - config = { ...defaultConfig, ...config }; - if (!armoredKey && !binaryKey) { - throw new Error('readPrivateKey: must pass options object containing `armoredKey` or `binaryKey`'); - } - if (armoredKey && !util.isString(armoredKey)) { - throw new Error('readPrivateKey: options.armoredKey must be a string'); - } - if (binaryKey && !util.isUint8Array(binaryKey)) { - throw new Error('readPrivateKey: options.binaryKey must be a Uint8Array'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - let input; - if (armoredKey) { - const { type, data } = await unarmor(armoredKey, config); - if (!(type === enums.armor.privateKey)) { - throw new Error('Armored text not of type private key'); - } - input = data; - } else { - input = binaryKey; - } - const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); - return new PrivateKey(packetlist); -} - -/** - * Reads an (optionally armored) OpenPGP key block and returns a list of key objects - * @param {Object} options - * @param {String} [options.armoredKeys] - Armored keys to be parsed - * @param {Uint8Array} [options.binaryKeys] - Binary keys to be parsed - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise>} Key objects. - * @async - * @static - */ -async function readKeys({ armoredKeys, binaryKeys, config, ...rest }) { - config = { ...defaultConfig, ...config }; - let input = armoredKeys || binaryKeys; - if (!input) { - throw new Error('readKeys: must pass options object containing `armoredKeys` or `binaryKeys`'); - } - if (armoredKeys && !util.isString(armoredKeys)) { - throw new Error('readKeys: options.armoredKeys must be a string'); - } - if (binaryKeys && !util.isUint8Array(binaryKeys)) { - throw new Error('readKeys: options.binaryKeys must be a Uint8Array'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (armoredKeys) { - const { type, data } = await unarmor(armoredKeys, config); - if (type !== enums.armor.publicKey && type !== enums.armor.privateKey) { - throw new Error('Armored text not of type key'); - } - input = data; - } - const keys = []; - const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); - const keyIndex = packetlist.indexOfTag(enums.packet.publicKey, enums.packet.secretKey); - if (keyIndex.length === 0) { - throw new Error('No key packet found'); - } - for (let i = 0; i < keyIndex.length; i++) { - const oneKeyList = packetlist.slice(keyIndex[i], keyIndex[i + 1]); - const newKey = createKey(oneKeyList); - keys.push(newKey); - } - return keys; -} - -/** - * Reads an (optionally armored) OpenPGP private key block and returns a list of PrivateKey objects - * @param {Object} options - * @param {String} [options.armoredKeys] - Armored keys to be parsed - * @param {Uint8Array} [options.binaryKeys] - Binary keys to be parsed - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise>} Key objects. - * @async - * @static - */ -async function readPrivateKeys({ armoredKeys, binaryKeys, config }) { - config = { ...defaultConfig, ...config }; - let input = armoredKeys || binaryKeys; - if (!input) { - throw new Error('readPrivateKeys: must pass options object containing `armoredKeys` or `binaryKeys`'); - } - if (armoredKeys && !util.isString(armoredKeys)) { - throw new Error('readPrivateKeys: options.armoredKeys must be a string'); - } - if (binaryKeys && !util.isUint8Array(binaryKeys)) { - throw new Error('readPrivateKeys: options.binaryKeys must be a Uint8Array'); - } - if (armoredKeys) { - const { type, data } = await unarmor(armoredKeys, config); - if (type !== enums.armor.privateKey) { - throw new Error('Armored text not of type private key'); - } - input = data; - } - const keys = []; - const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); - const keyIndex = packetlist.indexOfTag(enums.packet.secretKey); - if (keyIndex.length === 0) { - throw new Error('No secret key packet found'); - } - for (let i = 0; i < keyIndex.length; i++) { - const oneKeyList = packetlist.slice(keyIndex[i], keyIndex[i + 1]); - const newKey = new PrivateKey(oneKeyList); - keys.push(newKey); - } - return keys; -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -// A Message can contain the following packets -const allowedMessagePackets = /*#__PURE__*/ util.constructAllowedPackets([ - LiteralDataPacket, - CompressedDataPacket, - AEADEncryptedDataPacket, - SymEncryptedIntegrityProtectedDataPacket, - SymmetricallyEncryptedDataPacket, - PublicKeyEncryptedSessionKeyPacket, - SymEncryptedSessionKeyPacket, - OnePassSignaturePacket, - SignaturePacket -]); -// A SKESK packet can contain the following packets -const allowedSymSessionKeyPackets = /*#__PURE__*/ util.constructAllowedPackets([SymEncryptedSessionKeyPacket]); -// A detached signature can contain the following packets -const allowedDetachedSignaturePackets = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); - -/** - * Class that represents an OpenPGP message. - * Can be an encrypted message, signed message, compressed message or literal message - * See {@link https://tools.ietf.org/html/rfc4880#section-11.3} - */ -class Message { - /** - * @param {PacketList} packetlist - The packets that form this message - */ - constructor(packetlist) { - this.packets = packetlist || new PacketList(); - } - - /** - * Returns the key IDs of the keys to which the session key is encrypted - * @returns {Array} Array of keyID objects. - */ - getEncryptionKeyIDs() { - const keyIDs = []; - const pkESKeyPacketlist = this.packets.filterByTag(enums.packet.publicKeyEncryptedSessionKey); - pkESKeyPacketlist.forEach(function(packet) { - keyIDs.push(packet.publicKeyID); - }); - return keyIDs; - } - - /** - * Returns the key IDs of the keys that signed the message - * @returns {Array} Array of keyID objects. - */ - getSigningKeyIDs() { - const msg = this.unwrapCompressed(); - // search for one pass signatures - const onePassSigList = msg.packets.filterByTag(enums.packet.onePassSignature); - if (onePassSigList.length > 0) { - return onePassSigList.map(packet => packet.issuerKeyID); - } - // if nothing found look for signature packets - const signatureList = msg.packets.filterByTag(enums.packet.signature); - return signatureList.map(packet => packet.issuerKeyID); - } - - /** - * Decrypt the message. Either a private key, a session key, or a password must be specified. - * @param {Array} [decryptionKeys] - Private keys with decrypted secret data - * @param {Array} [passwords] - Passwords used to decrypt - * @param {Array} [sessionKeys] - Session keys in the form: { data:Uint8Array, algorithm:String, [aeadAlgorithm:String] } - * @param {Date} [date] - Use the given date for key verification instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New message with decrypted content. - * @async - */ - async decrypt(decryptionKeys, passwords, sessionKeys, date = new Date(), config = defaultConfig) { - const sessionKeyObjects = sessionKeys || await this.decryptSessionKeys(decryptionKeys, passwords, date, config); - - const symEncryptedPacketlist = this.packets.filterByTag( - enums.packet.symmetricallyEncryptedData, - enums.packet.symEncryptedIntegrityProtectedData, - enums.packet.aeadEncryptedData - ); - - if (symEncryptedPacketlist.length === 0) { - return this; - } - - const symEncryptedPacket = symEncryptedPacketlist[0]; - let exception = null; - const decryptedPromise = Promise.all(sessionKeyObjects.map(async ({ algorithm: algorithmName, data }) => { - if (!util.isUint8Array(data) || !util.isString(algorithmName)) { - throw new Error('Invalid session key for decryption.'); - } - - try { - const algo = enums.write(enums.symmetric, algorithmName); - await symEncryptedPacket.decrypt(algo, data, config); - } catch (e) { - util.printDebugError(e); - exception = e; - } - })); - // We don't await stream.cancel here because it only returns when the other copy is canceled too. - cancel(symEncryptedPacket.encrypted); // Don't keep copy of encrypted data in memory. - symEncryptedPacket.encrypted = null; - await decryptedPromise; - - if (!symEncryptedPacket.packets || !symEncryptedPacket.packets.length) { - throw exception || new Error('Decryption failed.'); - } - - const resultMsg = new Message(symEncryptedPacket.packets); - symEncryptedPacket.packets = new PacketList(); // remove packets after decryption - - return resultMsg; - } - - /** - * Decrypt encrypted session keys either with private keys or passwords. - * @param {Array} [decryptionKeys] - Private keys with decrypted secret data - * @param {Array} [passwords] - Passwords used to decrypt - * @param {Date} [date] - Use the given date for key verification, instead of current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise>} array of object with potential sessionKey, algorithm pairs - * @async - */ - async decryptSessionKeys(decryptionKeys, passwords, date = new Date(), config = defaultConfig) { - let decryptedSessionKeyPackets = []; - - let exception; - if (passwords) { - const skeskPackets = this.packets.filterByTag(enums.packet.symEncryptedSessionKey); - if (skeskPackets.length === 0) { - throw new Error('No symmetrically encrypted session key packet found.'); - } - await Promise.all(passwords.map(async function(password, i) { - let packets; - if (i) { - packets = await PacketList.fromBinary(skeskPackets.write(), allowedSymSessionKeyPackets, config); - } else { - packets = skeskPackets; - } - await Promise.all(packets.map(async function(skeskPacket) { - try { - await skeskPacket.decrypt(password); - decryptedSessionKeyPackets.push(skeskPacket); - } catch (err) { - util.printDebugError(err); - } - })); - })); - } else if (decryptionKeys) { - const pkeskPackets = this.packets.filterByTag(enums.packet.publicKeyEncryptedSessionKey); - if (pkeskPackets.length === 0) { - throw new Error('No public key encrypted session key packet found.'); - } - await Promise.all(pkeskPackets.map(async function(pkeskPacket) { - await Promise.all(decryptionKeys.map(async function(decryptionKey) { - let algos = [ - enums.symmetric.aes256, // Old OpenPGP.js default fallback - enums.symmetric.aes128, // RFC4880bis fallback - enums.symmetric.tripledes, // RFC4880 fallback - enums.symmetric.cast5 // Golang OpenPGP fallback - ]; - try { - const primaryUser = await decryptionKey.getPrimaryUser(date, undefined, config); // TODO: Pass userID from somewhere. - if (primaryUser.selfCertification.preferredSymmetricAlgorithms) { - algos = algos.concat(primaryUser.selfCertification.preferredSymmetricAlgorithms); - } - } catch (e) {} - - // do not check key expiration to allow decryption of old messages - const decryptionKeyPackets = (await decryptionKey.getDecryptionKeys(pkeskPacket.publicKeyID, null, undefined, config)).map(key => key.keyPacket); - await Promise.all(decryptionKeyPackets.map(async function(decryptionKeyPacket) { - if (!decryptionKeyPacket || decryptionKeyPacket.isDummy()) { - return; - } - if (!decryptionKeyPacket.isDecrypted()) { - throw new Error('Decryption key is not decrypted.'); - } - - // To hinder CCA attacks against PKCS1, we carry out a constant-time decryption flow if the `constantTimePKCS1Decryption` config option is set. - const doConstantTimeDecryption = config.constantTimePKCS1Decryption && ( - pkeskPacket.publicKeyAlgorithm === enums.publicKey.rsaEncrypt || - pkeskPacket.publicKeyAlgorithm === enums.publicKey.rsaEncryptSign || - pkeskPacket.publicKeyAlgorithm === enums.publicKey.rsaSign || - pkeskPacket.publicKeyAlgorithm === enums.publicKey.elgamal - ); - - if (doConstantTimeDecryption) { - // The goal is to not reveal whether PKESK decryption (specifically the PKCS1 decoding step) failed, hence, we always proceed to decrypt the message, - // either with the successfully decrypted session key, or with a randomly generated one. - // Since the SEIP/AEAD's symmetric algorithm and key size are stored in the encrypted portion of the PKESK, and the execution flow cannot depend on - // the decrypted payload, we always assume the message to be encrypted with one of the symmetric algorithms specified in `config.constantTimePKCS1DecryptionSupportedSymmetricAlgorithms`: - // - If the PKESK decryption succeeds, and the session key cipher is in the supported set, then we try to decrypt the data with the decrypted session key as well as with the - // randomly generated keys of the remaining key types. - // - If the PKESK decryptions fails, or if it succeeds but support for the cipher is not enabled, then we discard the session key and try to decrypt the data using only the randomly - // generated session keys. - // NB: as a result, if the data is encrypted with a non-suported cipher, decryption will always fail. - - const serialisedPKESK = pkeskPacket.write(); // make copies to be able to decrypt the PKESK packet multiple times - await Promise.all(Array.from(config.constantTimePKCS1DecryptionSupportedSymmetricAlgorithms).map(async sessionKeyAlgorithm => { - const pkeskPacketCopy = new PublicKeyEncryptedSessionKeyPacket(); - pkeskPacketCopy.read(serialisedPKESK); - const randomSessionKey = { - sessionKeyAlgorithm, - sessionKey: await mod.generateSessionKey(sessionKeyAlgorithm) - }; - try { - await pkeskPacketCopy.decrypt(decryptionKeyPacket, randomSessionKey); - decryptedSessionKeyPackets.push(pkeskPacketCopy); - } catch (err) { - // `decrypt` can still throw some non-security-sensitive errors - util.printDebugError(err); - exception = err; - } - })); - - } else { - try { - await pkeskPacket.decrypt(decryptionKeyPacket); - if (!algos.includes(enums.write(enums.symmetric, pkeskPacket.sessionKeyAlgorithm))) { - throw new Error('A non-preferred symmetric algorithm was used.'); - } - decryptedSessionKeyPackets.push(pkeskPacket); - } catch (err) { - util.printDebugError(err); - exception = err; - } - } - })); - })); - cancel(pkeskPacket.encrypted); // Don't keep copy of encrypted data in memory. - pkeskPacket.encrypted = null; - })); - } else { - throw new Error('No key or password specified.'); - } - - if (decryptedSessionKeyPackets.length > 0) { - // Return only unique session keys - if (decryptedSessionKeyPackets.length > 1) { - const seen = new Set(); - decryptedSessionKeyPackets = decryptedSessionKeyPackets.filter(item => { - const k = item.sessionKeyAlgorithm + util.uint8ArrayToString(item.sessionKey); - if (seen.has(k)) { - return false; - } - seen.add(k); - return true; - }); - } - - return decryptedSessionKeyPackets.map(packet => ({ - data: packet.sessionKey, - algorithm: enums.read(enums.symmetric, packet.sessionKeyAlgorithm) - })); - } - throw exception || new Error('Session key decryption failed.'); - } - - /** - * Get literal data that is the body of the message - * @returns {(Uint8Array|null)} Literal body of the message as Uint8Array. - */ - getLiteralData() { - const msg = this.unwrapCompressed(); - const literal = msg.packets.findPacket(enums.packet.literalData); - return (literal && literal.getBytes()) || null; - } - - /** - * Get filename from literal data packet - * @returns {(String|null)} Filename of literal data packet as string. - */ - getFilename() { - const msg = this.unwrapCompressed(); - const literal = msg.packets.findPacket(enums.packet.literalData); - return (literal && literal.getFilename()) || null; - } - - /** - * Get literal data as text - * @returns {(String|null)} Literal body of the message interpreted as text. - */ - getText() { - const msg = this.unwrapCompressed(); - const literal = msg.packets.findPacket(enums.packet.literalData); - if (literal) { - return literal.getText(); - } - return null; - } - - /** - * Generate a new session key object, taking the algorithm preferences of the passed encryption keys into account, if any. - * @param {Array} [encryptionKeys] - Public key(s) to select algorithm preferences for - * @param {Date} [date] - Date to select algorithm preferences at - * @param {Array} [userIDs] - User IDs to select algorithm preferences for - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise<{ data: Uint8Array, algorithm: String, aeadAlgorithm: undefined|String }>} Object with session key data and algorithms. - * @async - */ - static async generateSessionKey(encryptionKeys = [], date = new Date(), userIDs = [], config = defaultConfig) { - const algo = await getPreferredAlgo('symmetric', encryptionKeys, date, userIDs, config); - const algorithmName = enums.read(enums.symmetric, algo); - const aeadAlgorithmName = config.aeadProtect && await isAEADSupported(encryptionKeys, date, userIDs, config) ? - enums.read(enums.aead, await getPreferredAlgo('aead', encryptionKeys, date, userIDs, config)) : - undefined; - - const sessionKeyData = await mod.generateSessionKey(algo); - return { data: sessionKeyData, algorithm: algorithmName, aeadAlgorithm: aeadAlgorithmName }; - } - - /** - * Encrypt the message either with public keys, passwords, or both at once. - * @param {Array} [encryptionKeys] - Public key(s) for message encryption - * @param {Array} [passwords] - Password(s) for message encryption - * @param {Object} [sessionKey] - Session key in the form: { data:Uint8Array, algorithm:String, [aeadAlgorithm:String] } - * @param {Boolean} [wildcard] - Use a key ID of 0 instead of the public key IDs - * @param {Array} [encryptionKeyIDs] - Array of key IDs to use for encryption. Each encryptionKeyIDs[i] corresponds to keys[i] - * @param {Date} [date] - Override the creation date of the literal package - * @param {Array} [userIDs] - User IDs to encrypt for, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }] - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New message with encrypted content. - * @async - */ - async encrypt(encryptionKeys, passwords, sessionKey, wildcard = false, encryptionKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { - if (sessionKey) { - if (!util.isUint8Array(sessionKey.data) || !util.isString(sessionKey.algorithm)) { - throw new Error('Invalid session key for encryption.'); - } - } else if (encryptionKeys && encryptionKeys.length) { - sessionKey = await Message.generateSessionKey(encryptionKeys, date, userIDs, config); - } else if (passwords && passwords.length) { - sessionKey = await Message.generateSessionKey(undefined, undefined, undefined, config); - } else { - throw new Error('No keys, passwords, or session key provided.'); - } - - const { data: sessionKeyData, algorithm: algorithmName, aeadAlgorithm: aeadAlgorithmName } = sessionKey; - - const msg = await Message.encryptSessionKey(sessionKeyData, algorithmName, aeadAlgorithmName, encryptionKeys, passwords, wildcard, encryptionKeyIDs, date, userIDs, config); - - let symEncryptedPacket; - if (aeadAlgorithmName) { - symEncryptedPacket = new AEADEncryptedDataPacket(); - symEncryptedPacket.aeadAlgorithm = enums.write(enums.aead, aeadAlgorithmName); - } else { - symEncryptedPacket = new SymEncryptedIntegrityProtectedDataPacket(); - } - symEncryptedPacket.packets = this.packets; - - const algorithm = enums.write(enums.symmetric, algorithmName); - await symEncryptedPacket.encrypt(algorithm, sessionKeyData, config); - - msg.packets.push(symEncryptedPacket); - symEncryptedPacket.packets = new PacketList(); // remove packets after encryption - return msg; - } - - /** - * Encrypt a session key either with public keys, passwords, or both at once. - * @param {Uint8Array} sessionKey - session key for encryption - * @param {String} algorithmName - session key algorithm - * @param {String} [aeadAlgorithmName] - AEAD algorithm, e.g. 'eax' or 'ocb' - * @param {Array} [encryptionKeys] - Public key(s) for message encryption - * @param {Array} [passwords] - For message encryption - * @param {Boolean} [wildcard] - Use a key ID of 0 instead of the public key IDs - * @param {Array} [encryptionKeyIDs] - Array of key IDs to use for encryption. Each encryptionKeyIDs[i] corresponds to encryptionKeys[i] - * @param {Date} [date] - Override the date - * @param {Array} [userIDs] - User IDs to encrypt for, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }] - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New message with encrypted content. - * @async - */ - static async encryptSessionKey(sessionKey, algorithmName, aeadAlgorithmName, encryptionKeys, passwords, wildcard = false, encryptionKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { - const packetlist = new PacketList(); - const algorithm = enums.write(enums.symmetric, algorithmName); - const aeadAlgorithm = aeadAlgorithmName && enums.write(enums.aead, aeadAlgorithmName); - - if (encryptionKeys) { - const results = await Promise.all(encryptionKeys.map(async function(primaryKey, i) { - const encryptionKey = await primaryKey.getEncryptionKey(encryptionKeyIDs[i], date, userIDs, config); - const pkESKeyPacket = new PublicKeyEncryptedSessionKeyPacket(); - pkESKeyPacket.publicKeyID = wildcard ? KeyID.wildcard() : encryptionKey.getKeyID(); - pkESKeyPacket.publicKeyAlgorithm = encryptionKey.keyPacket.algorithm; - pkESKeyPacket.sessionKey = sessionKey; - pkESKeyPacket.sessionKeyAlgorithm = algorithm; - await pkESKeyPacket.encrypt(encryptionKey.keyPacket); - delete pkESKeyPacket.sessionKey; // delete plaintext session key after encryption - return pkESKeyPacket; - })); - packetlist.push(...results); - } - if (passwords) { - const testDecrypt = async function(keyPacket, password) { - try { - await keyPacket.decrypt(password); - return 1; - } catch (e) { - return 0; - } - }; - - const sum = (accumulator, currentValue) => accumulator + currentValue; - - const encryptPassword = async function(sessionKey, algorithm, aeadAlgorithm, password) { - const symEncryptedSessionKeyPacket = new SymEncryptedSessionKeyPacket(config); - symEncryptedSessionKeyPacket.sessionKey = sessionKey; - symEncryptedSessionKeyPacket.sessionKeyAlgorithm = algorithm; - if (aeadAlgorithm) { - symEncryptedSessionKeyPacket.aeadAlgorithm = aeadAlgorithm; - } - await symEncryptedSessionKeyPacket.encrypt(password, config); - - if (config.passwordCollisionCheck) { - const results = await Promise.all(passwords.map(pwd => testDecrypt(symEncryptedSessionKeyPacket, pwd))); - if (results.reduce(sum) !== 1) { - return encryptPassword(sessionKey, algorithm, password); - } - } - - delete symEncryptedSessionKeyPacket.sessionKey; // delete plaintext session key after encryption - return symEncryptedSessionKeyPacket; - }; - - const results = await Promise.all(passwords.map(pwd => encryptPassword(sessionKey, algorithm, aeadAlgorithm, pwd))); - packetlist.push(...results); - } - - return new Message(packetlist); - } - - /** - * Sign the message (the literal data packet of the message) - * @param {Array} signingKeys - private keys with decrypted secret key data for signing - * @param {Signature} [signature] - Any existing detached signature to add to the message - * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] - * @param {Date} [date] - Override the creation time of the signature - * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New message with signed content. - * @async - */ - async sign(signingKeys = [], signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { - const packetlist = new PacketList(); - - const literalDataPacket = this.packets.findPacket(enums.packet.literalData); - if (!literalDataPacket) { - throw new Error('No literal data packet to sign.'); - } - - let i; - let existingSigPacketlist; - // If data packet was created from Uint8Array, use binary, otherwise use text - const signatureType = literalDataPacket.text === null ? - enums.signature.binary : enums.signature.text; - - if (signature) { - existingSigPacketlist = signature.packets.filterByTag(enums.packet.signature); - for (i = existingSigPacketlist.length - 1; i >= 0; i--) { - const signaturePacket = existingSigPacketlist[i]; - const onePassSig = new OnePassSignaturePacket(); - onePassSig.signatureType = signaturePacket.signatureType; - onePassSig.hashAlgorithm = signaturePacket.hashAlgorithm; - onePassSig.publicKeyAlgorithm = signaturePacket.publicKeyAlgorithm; - onePassSig.issuerKeyID = signaturePacket.issuerKeyID; - if (!signingKeys.length && i === 0) { - onePassSig.flags = 1; - } - packetlist.push(onePassSig); - } - } - - await Promise.all(Array.from(signingKeys).reverse().map(async function (primaryKey, i) { - if (!primaryKey.isPrivate()) { - throw new Error('Need private key for signing'); - } - const signingKeyID = signingKeyIDs[signingKeys.length - 1 - i]; - const signingKey = await primaryKey.getSigningKey(signingKeyID, date, userIDs, config); - const onePassSig = new OnePassSignaturePacket(); - onePassSig.signatureType = signatureType; - onePassSig.hashAlgorithm = await getPreferredHashAlgo$1(primaryKey, signingKey.keyPacket, date, userIDs, config); - onePassSig.publicKeyAlgorithm = signingKey.keyPacket.algorithm; - onePassSig.issuerKeyID = signingKey.getKeyID(); - if (i === signingKeys.length - 1) { - onePassSig.flags = 1; - } - return onePassSig; - })).then(onePassSignatureList => { - onePassSignatureList.forEach(onePassSig => packetlist.push(onePassSig)); - }); - - packetlist.push(literalDataPacket); - packetlist.push(...(await createSignaturePackets(literalDataPacket, signingKeys, signature, signingKeyIDs, date, userIDs, false, config))); - - return new Message(packetlist); - } - - /** - * Compresses the message (the literal and -if signed- signature data packets of the message) - * @param {module:enums.compression} algo - compression algorithm - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Message} New message with compressed content. - */ - compress(algo, config = defaultConfig) { - if (algo === enums.compression.uncompressed) { - return this; - } - - const compressed = new CompressedDataPacket(config); - compressed.algorithm = algo; - compressed.packets = this.packets; - - const packetList = new PacketList(); - packetList.push(compressed); - - return new Message(packetList); - } - - /** - * Create a detached signature for the message (the literal data packet of the message) - * @param {Array} signingKeys - private keys with decrypted secret key data for signing - * @param {Signature} [signature] - Any existing detached signature - * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] - * @param {Date} [date] - Override the creation time of the signature - * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New detached signature of message content. - * @async - */ - async signDetached(signingKeys = [], signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { - const literalDataPacket = this.packets.findPacket(enums.packet.literalData); - if (!literalDataPacket) { - throw new Error('No literal data packet to sign.'); - } - return new Signature(await createSignaturePackets(literalDataPacket, signingKeys, signature, signingKeyIDs, date, userIDs, true, config)); - } - - /** - * Verify message signatures - * @param {Array} verificationKeys - Array of public keys to verify signatures - * @param {Date} [date] - Verify the signature against the given date, i.e. check signature creation time < date < expiration time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise, - * verified: Promise - * }>>} List of signer's keyID and validity of signatures. - * @async - */ - async verify(verificationKeys, date = new Date(), config = defaultConfig) { - const msg = this.unwrapCompressed(); - const literalDataList = msg.packets.filterByTag(enums.packet.literalData); - if (literalDataList.length !== 1) { - throw new Error('Can only verify message with one literal data packet.'); - } - if (isArrayStream(msg.packets.stream)) { - msg.packets.push(...await readToEnd(msg.packets.stream, _ => _ || [])); - } - const onePassSigList = msg.packets.filterByTag(enums.packet.onePassSignature).reverse(); - const signatureList = msg.packets.filterByTag(enums.packet.signature); - if (onePassSigList.length && !signatureList.length && util.isStream(msg.packets.stream) && !isArrayStream(msg.packets.stream)) { - await Promise.all(onePassSigList.map(async onePassSig => { - onePassSig.correspondingSig = new Promise((resolve, reject) => { - onePassSig.correspondingSigResolve = resolve; - onePassSig.correspondingSigReject = reject; - }); - onePassSig.signatureData = fromAsync(async () => (await onePassSig.correspondingSig).signatureData); - onePassSig.hashed = readToEnd(await onePassSig.hash(onePassSig.signatureType, literalDataList[0], undefined, false)); - onePassSig.hashed.catch(() => {}); - })); - msg.packets.stream = transformPair(msg.packets.stream, async (readable, writable) => { - const reader = getReader(readable); - const writer = getWriter(writable); - try { - for (let i = 0; i < onePassSigList.length; i++) { - const { value: signature } = await reader.read(); - onePassSigList[i].correspondingSigResolve(signature); - } - await reader.readToEnd(); - await writer.ready; - await writer.close(); - } catch (e) { - onePassSigList.forEach(onePassSig => { - onePassSig.correspondingSigReject(e); - }); - await writer.abort(e); - } - }); - return createVerificationObjects(onePassSigList, literalDataList, verificationKeys, date, false, config); - } - return createVerificationObjects(signatureList, literalDataList, verificationKeys, date, false, config); - } - - /** - * Verify detached message signature - * @param {Array} verificationKeys - Array of public keys to verify signatures - * @param {Signature} signature - * @param {Date} date - Verify the signature against the given date, i.e. check signature creation time < date < expiration time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise, - * verified: Promise - * }>>} List of signer's keyID and validity of signature. - * @async - */ - verifyDetached(signature, verificationKeys, date = new Date(), config = defaultConfig) { - const msg = this.unwrapCompressed(); - const literalDataList = msg.packets.filterByTag(enums.packet.literalData); - if (literalDataList.length !== 1) { - throw new Error('Can only verify message with one literal data packet.'); - } - const signatureList = signature.packets; - return createVerificationObjects(signatureList, literalDataList, verificationKeys, date, true, config); - } - - /** - * Unwrap compressed message - * @returns {Message} Message Content of compressed message. - */ - unwrapCompressed() { - const compressed = this.packets.filterByTag(enums.packet.compressedData); - if (compressed.length) { - return new Message(compressed[0].packets); - } - return this; - } - - /** - * Append signature to unencrypted message object - * @param {String|Uint8Array} detachedSignature - The detached ASCII-armored or Uint8Array PGP signature - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - async appendSignature(detachedSignature, config = defaultConfig) { - await this.packets.read( - util.isUint8Array(detachedSignature) ? detachedSignature : (await unarmor(detachedSignature)).data, - allowedDetachedSignaturePackets, - config - ); - } - - /** - * Returns binary encoded message - * @returns {ReadableStream} Binary message. - */ - write() { - return this.packets.write(); - } - - /** - * Returns ASCII armored text of message - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {ReadableStream} ASCII armor. - */ - armor(config = defaultConfig) { - return armor(enums.armor.message, this.write(), null, null, null, config); - } -} - -/** - * Create signature packets for the message - * @param {LiteralDataPacket} literalDataPacket - the literal data packet to sign - * @param {Array} [signingKeys] - private keys with decrypted secret key data for signing - * @param {Signature} [signature] - Any existing detached signature to append - * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] - * @param {Date} [date] - Override the creationtime of the signature - * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] - * @param {Boolean} [detached] - Whether to create detached signature packets - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} List of signature packets. - * @async - * @private - */ -async function createSignaturePackets(literalDataPacket, signingKeys, signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], detached = false, config = defaultConfig) { - const packetlist = new PacketList(); - - // If data packet was created from Uint8Array, use binary, otherwise use text - const signatureType = literalDataPacket.text === null ? - enums.signature.binary : enums.signature.text; - - await Promise.all(signingKeys.map(async (primaryKey, i) => { - const userID = userIDs[i]; - if (!primaryKey.isPrivate()) { - throw new Error('Need private key for signing'); - } - const signingKey = await primaryKey.getSigningKey(signingKeyIDs[i], date, userID, config); - return createSignaturePacket(literalDataPacket, primaryKey, signingKey.keyPacket, { signatureType }, date, userID, detached, config); - })).then(signatureList => { - packetlist.push(...signatureList); - }); - - if (signature) { - const existingSigPacketlist = signature.packets.filterByTag(enums.packet.signature); - packetlist.push(...existingSigPacketlist); - } - return packetlist; -} - -/** - * Create object containing signer's keyID and validity of signature - * @param {SignaturePacket} signature - Signature packet - * @param {Array} literalDataList - Array of literal data packets - * @param {Array} verificationKeys - Array of public keys to verify signatures - * @param {Date} [date] - Check signature validity with respect to the given date - * @param {Boolean} [detached] - Whether to verify detached signature packets - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise<{ - * keyID: module:type/keyid~KeyID, - * signature: Promise, - * verified: Promise - * }>} signer's keyID and validity of signature - * @async - * @private - */ -async function createVerificationObject(signature, literalDataList, verificationKeys, date = new Date(), detached = false, config = defaultConfig) { - let primaryKey; - let unverifiedSigningKey; - - for (const key of verificationKeys) { - const issuerKeys = key.getKeys(signature.issuerKeyID); - if (issuerKeys.length > 0) { - primaryKey = key; - unverifiedSigningKey = issuerKeys[0]; - break; - } - } - - const isOnePassSignature = signature instanceof OnePassSignaturePacket; - const signaturePacketPromise = isOnePassSignature ? signature.correspondingSig : signature; - - const verifiedSig = { - keyID: signature.issuerKeyID, - verified: (async () => { - if (!unverifiedSigningKey) { - throw new Error(`Could not find signing key with key ID ${signature.issuerKeyID.toHex()}`); - } - - await signature.verify(unverifiedSigningKey.keyPacket, signature.signatureType, literalDataList[0], date, detached, config); - const signaturePacket = await signaturePacketPromise; - if (unverifiedSigningKey.getCreationTime() > signaturePacket.created) { - throw new Error('Key is newer than the signature'); - } - // We pass the signature creation time to check whether the key was expired at the time of signing. - // We check this after signature verification because for streamed one-pass signatures, the creation time is not available before - try { - await primaryKey.getSigningKey(unverifiedSigningKey.getKeyID(), signaturePacket.created, undefined, config); - } catch (e) { - // If a key was reformatted then the self-signatures of the signing key might be in the future compared to the message signature, - // making the key invalid at the time of signing. - // However, if the key is valid at the given `date`, we still allow using it provided the relevant `config` setting is enabled. - // Note: we do not support the edge case of a key that was reformatted and it has expired. - if (config.allowInsecureVerificationWithReformattedKeys && e.message.match(/Signature creation time is in the future/)) { - await primaryKey.getSigningKey(unverifiedSigningKey.getKeyID(), date, undefined, config); - } else { - throw e; - } - } - return true; - })(), - signature: (async () => { - const signaturePacket = await signaturePacketPromise; - const packetlist = new PacketList(); - signaturePacket && packetlist.push(signaturePacket); - return new Signature(packetlist); - })() - }; - - // Mark potential promise rejections as "handled". This is needed because in - // some cases, we reject them before the user has a reasonable chance to - // handle them (e.g. `await readToEnd(result.data); await result.verified` and - // the data stream errors). - verifiedSig.signature.catch(() => {}); - verifiedSig.verified.catch(() => {}); - - return verifiedSig; -} - -/** - * Create list of objects containing signer's keyID and validity of signature - * @param {Array} signatureList - Array of signature packets - * @param {Array} literalDataList - Array of literal data packets - * @param {Array} verificationKeys - Array of public keys to verify signatures - * @param {Date} date - Verify the signature against the given date, - * i.e. check signature creation time < date < expiration time - * @param {Boolean} [detached] - Whether to verify detached signature packets - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise, - * verified: Promise - * }>>} list of signer's keyID and validity of signatures (one entry per signature packet in input) - * @async - * @private - */ -async function createVerificationObjects(signatureList, literalDataList, verificationKeys, date = new Date(), detached = false, config = defaultConfig) { - return Promise.all(signatureList.filter(function(signature) { - return ['text', 'binary'].includes(enums.read(enums.signature, signature.signatureType)); - }).map(async function(signature) { - return createVerificationObject(signature, literalDataList, verificationKeys, date, detached, config); - })); -} - -/** - * Reads an (optionally armored) OpenPGP message and returns a Message object - * @param {Object} options - * @param {String | ReadableStream} [options.armoredMessage] - Armored message to be parsed - * @param {Uint8Array | ReadableStream} [options.binaryMessage] - Binary to be parsed - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} New message object. - * @async - * @static - */ -async function readMessage({ armoredMessage, binaryMessage, config, ...rest }) { - config = { ...defaultConfig, ...config }; - let input = armoredMessage || binaryMessage; - if (!input) { - throw new Error('readMessage: must pass options object containing `armoredMessage` or `binaryMessage`'); - } - if (armoredMessage && !util.isString(armoredMessage) && !util.isStream(armoredMessage)) { - throw new Error('readMessage: options.armoredMessage must be a string or stream'); - } - if (binaryMessage && !util.isUint8Array(binaryMessage) && !util.isStream(binaryMessage)) { - throw new Error('readMessage: options.binaryMessage must be a Uint8Array or stream'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - const streamType = util.isStream(input); - if (streamType) { - await loadStreamsPonyfill(); - input = toStream(input); - } - if (armoredMessage) { - const { type, data } = await unarmor(input, config); - if (type !== enums.armor.message) { - throw new Error('Armored text not of type message'); - } - input = data; - } - const packetlist = await PacketList.fromBinary(input, allowedMessagePackets, config); - const message = new Message(packetlist); - message.fromStream = streamType; - return message; -} - -/** - * Creates new message object from text or binary data. - * @param {Object} options - * @param {String | ReadableStream} [options.text] - The text message contents - * @param {Uint8Array | ReadableStream} [options.binary] - The binary message contents - * @param {String} [options.filename=""] - Name of the file (if any) - * @param {Date} [options.date=current date] - Date of the message, or modification date of the file - * @param {'utf8'|'binary'|'text'|'mime'} [options.format='utf8' if text is passed, 'binary' otherwise] - Data packet type - * @returns {Promise} New message object. - * @async - * @static - */ -async function createMessage({ text, binary, filename, date = new Date(), format = text !== undefined ? 'utf8' : 'binary', ...rest }) { - let input = text !== undefined ? text : binary; - if (input === undefined) { - throw new Error('createMessage: must pass options object containing `text` or `binary`'); - } - if (text && !util.isString(text) && !util.isStream(text)) { - throw new Error('createMessage: options.text must be a string or stream'); - } - if (binary && !util.isUint8Array(binary) && !util.isStream(binary)) { - throw new Error('createMessage: options.binary must be a Uint8Array or stream'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - const streamType = util.isStream(input); - if (streamType) { - await loadStreamsPonyfill(); - input = toStream(input); - } - const literalDataPacket = new LiteralDataPacket(date); - if (text !== undefined) { - literalDataPacket.setText(input, enums.write(enums.literal, format)); - } else { - literalDataPacket.setBytes(input, enums.write(enums.literal, format)); - } - if (filename !== undefined) { - literalDataPacket.setFilename(filename); - } - const literalDataPacketlist = new PacketList(); - literalDataPacketlist.push(literalDataPacket); - const message = new Message(literalDataPacketlist); - message.fromStream = streamType; - return message; -} - -// GPG4Browsers - An OpenPGP implementation in javascript - -// A Cleartext message can contain the following packets -const allowedPackets$5 = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); - -/** - * Class that represents an OpenPGP cleartext signed message. - * See {@link https://tools.ietf.org/html/rfc4880#section-7} - */ -class CleartextMessage { - /** - * @param {String} text - The cleartext of the signed message - * @param {Signature} signature - The detached signature or an empty signature for unsigned messages - */ - constructor(text, signature) { - // normalize EOL to canonical form - this.text = util.removeTrailingSpaces(text).replace(/\r?\n/g, '\r\n'); - if (signature && !(signature instanceof Signature)) { - throw new Error('Invalid signature input'); - } - this.signature = signature || new Signature(new PacketList()); - } - - /** - * Returns the key IDs of the keys that signed the cleartext message - * @returns {Array} Array of keyID objects. - */ - getSigningKeyIDs() { - const keyIDs = []; - const signatureList = this.signature.packets; - signatureList.forEach(function(packet) { - keyIDs.push(packet.issuerKeyID); - }); - return keyIDs; - } - - /** - * Sign the cleartext message - * @param {Array} privateKeys - private keys with decrypted secret key data for signing - * @param {Signature} [signature] - Any existing detached signature - * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to privateKeys[i] - * @param {Date} [date] - The creation time of the signature that should be created - * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New cleartext message with signed content. - * @async - */ - async sign(privateKeys, signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { - const literalDataPacket = new LiteralDataPacket(); - literalDataPacket.setText(this.text); - const newSignature = new Signature(await createSignaturePackets(literalDataPacket, privateKeys, signature, signingKeyIDs, date, userIDs, true, config)); - return new CleartextMessage(this.text, newSignature); - } - - /** - * Verify signatures of cleartext signed message - * @param {Array} keys - Array of keys to verify signatures - * @param {Date} [date] - Verify the signature against the given date, i.e. check signature creation time < date < expiration time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise, - * verified: Promise - * }>>} List of signer's keyID and validity of signature. - * @async - */ - verify(keys, date = new Date(), config = defaultConfig) { - const signatureList = this.signature.packets; - const literalDataPacket = new LiteralDataPacket(); - // we assume that cleartext signature is generated based on UTF8 cleartext - literalDataPacket.setText(this.text); - return createVerificationObjects(signatureList, [literalDataPacket], keys, date, true, config); - } - - /** - * Get cleartext - * @returns {String} Cleartext of message. - */ - getText() { - // normalize end of line to \n - return this.text.replace(/\r\n/g, '\n'); - } - - /** - * Returns ASCII armored text of cleartext signed message - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {String | ReadableStream} ASCII armor. - */ - armor(config = defaultConfig) { - let hashes = this.signature.packets.map(function(packet) { - return enums.read(enums.hash, packet.hashAlgorithm).toUpperCase(); - }); - hashes = hashes.filter(function(item, i, ar) { return ar.indexOf(item) === i; }); - const body = { - hash: hashes.join(), - text: this.text, - data: this.signature.packets.write() - }; - return armor(enums.armor.signed, body, undefined, undefined, undefined, config); - } -} - -/** - * Reads an OpenPGP cleartext signed message and returns a CleartextMessage object - * @param {Object} options - * @param {String} options.cleartextMessage - Text to be parsed - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} New cleartext message object. - * @async - * @static - */ -async function readCleartextMessage({ cleartextMessage, config, ...rest }) { - config = { ...defaultConfig, ...config }; - if (!cleartextMessage) { - throw new Error('readCleartextMessage: must pass options object containing `cleartextMessage`'); - } - if (!util.isString(cleartextMessage)) { - throw new Error('readCleartextMessage: options.cleartextMessage must be a string'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - const input = await unarmor(cleartextMessage); - if (input.type !== enums.armor.signed) { - throw new Error('No cleartext signed message.'); - } - const packetlist = await PacketList.fromBinary(input.data, allowedPackets$5, config); - verifyHeaders$1(input.headers, packetlist); - const signature = new Signature(packetlist); - return new CleartextMessage(input.text, signature); -} - -/** - * Compare hash algorithm specified in the armor header with signatures - * @param {Array} headers - Armor headers - * @param {PacketList} packetlist - The packetlist with signature packets - * @private - */ -function verifyHeaders$1(headers, packetlist) { - const checkHashAlgos = function(hashAlgos) { - const check = packet => algo => packet.hashAlgorithm === algo; - - for (let i = 0; i < packetlist.length; i++) { - if (packetlist[i].constructor.tag === enums.packet.signature && !hashAlgos.some(check(packetlist[i]))) { - return false; - } - } - return true; - }; - - let oneHeader = null; - let hashAlgos = []; - headers.forEach(function(header) { - oneHeader = header.match(/Hash: (.+)/); // get header value - if (oneHeader) { - oneHeader = oneHeader[1].replace(/\s/g, ''); // remove whitespace - oneHeader = oneHeader.split(','); - oneHeader = oneHeader.map(function(hash) { - hash = hash.toLowerCase(); - try { - return enums.write(enums.hash, hash); - } catch (e) { - throw new Error('Unknown hash algorithm in armor header: ' + hash); - } - }); - hashAlgos = hashAlgos.concat(oneHeader); - } else { - throw new Error('Only "Hash" header allowed in cleartext signed message'); - } - }); - - if (!hashAlgos.length && !checkHashAlgos([enums.hash.md5])) { - throw new Error('If no "Hash" header in cleartext signed message, then only MD5 signatures allowed'); - } else if (hashAlgos.length && !checkHashAlgos(hashAlgos)) { - throw new Error('Hash algorithm mismatch in armor header and signature'); - } -} - -/** - * Creates a new CleartextMessage object from text - * @param {Object} options - * @param {String} options.text - * @static - * @async - */ -async function createCleartextMessage({ text, ...rest }) { - if (!text) { - throw new Error('createCleartextMessage: must pass options object containing `text`'); - } - if (!util.isString(text)) { - throw new Error('createCleartextMessage: options.text must be a string'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - return new CleartextMessage(text); -} - -// OpenPGP.js - An OpenPGP implementation in javascript - - -////////////////////// -// // -// Key handling // -// // -////////////////////// - - -/** - * Generates a new OpenPGP key pair. Supports RSA and ECC keys. By default, primary and subkeys will be of same type. - * The generated primary key will have signing capabilities. By default, one subkey with encryption capabilities is also generated. - * @param {Object} options - * @param {Object|Array} options.userIDs - User IDs as objects: `{ name: 'Jo Doe', email: 'info@jo.com' }` - * @param {'ecc'|'rsa'} [options.type='ecc'] - The primary key algorithm type: ECC (default) or RSA - * @param {String} [options.passphrase=(not protected)] - The passphrase used to encrypt the generated private key. If omitted, the key won't be encrypted. - * @param {Number} [options.rsaBits=4096] - Number of bits for RSA keys - * @param {String} [options.curve='curve25519'] - Elliptic curve for ECC keys: - * curve25519 (default), p256, p384, p521, secp256k1, - * brainpoolP256r1, brainpoolP384r1, or brainpoolP512r1 - * @param {Date} [options.date=current date] - Override the creation date of the key and the key signatures - * @param {Number} [options.keyExpirationTime=0 (never expires)] - Number of seconds from the key creation time after which the key expires - * @param {Array} [options.subkeys=a single encryption subkey] - Options for each subkey e.g. `[{sign: true, passphrase: '123'}]` - * default to main key options, except for `sign` parameter that defaults to false, and indicates whether the subkey should sign rather than encrypt - * @param {'armored'|'binary'|'object'} [options.format='armored'] - format of the output keys - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} The generated key object in the form: - * { privateKey:PrivateKey|Uint8Array|String, publicKey:PublicKey|Uint8Array|String, revocationCertificate:String } - * @async - * @static - */ -async function generateKey({ userIDs = [], passphrase = '', type = 'ecc', rsaBits = 4096, curve = 'curve25519', keyExpirationTime = 0, date = new Date(), subkeys = [{}], format = 'armored', config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - userIDs = toArray$1(userIDs); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (userIDs.length === 0) { - throw new Error('UserIDs are required for key generation'); - } - if (type === 'rsa' && rsaBits < config.minRSABits) { - throw new Error(`rsaBits should be at least ${config.minRSABits}, got: ${rsaBits}`); - } - - const options = { userIDs, passphrase, type, rsaBits, curve, keyExpirationTime, date, subkeys }; - - try { - const { key, revocationCertificate } = await generate$2(options, config); - key.getKeys().forEach(({ keyPacket }) => checkKeyRequirements(keyPacket, config)); - - return { - privateKey: formatObject(key, format, config), - publicKey: formatObject(key.toPublic(), format, config), - revocationCertificate - }; - } catch (err) { - throw util.wrapError('Error generating keypair', err); - } -} - -/** - * Reformats signature packets for a key and rewraps key object. - * @param {Object} options - * @param {PrivateKey} options.privateKey - Private key to reformat - * @param {Object|Array} options.userIDs - User IDs as objects: `{ name: 'Jo Doe', email: 'info@jo.com' }` - * @param {String} [options.passphrase=(not protected)] - The passphrase used to encrypt the reformatted private key. If omitted, the key won't be encrypted. - * @param {Number} [options.keyExpirationTime=0 (never expires)] - Number of seconds from the key creation time after which the key expires - * @param {Date} [options.date] - Override the creation date of the key signatures. If the key was previously used to sign messages, it is recommended - * to set the same date as the key creation time to ensure that old message signatures will still be verifiable using the reformatted key. - * @param {'armored'|'binary'|'object'} [options.format='armored'] - format of the output keys - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} The generated key object in the form: - * { privateKey:PrivateKey|Uint8Array|String, publicKey:PublicKey|Uint8Array|String, revocationCertificate:String } - * @async - * @static - */ -async function reformatKey({ privateKey, userIDs = [], passphrase = '', keyExpirationTime = 0, date, format = 'armored', config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - userIDs = toArray$1(userIDs); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (userIDs.length === 0) { - throw new Error('UserIDs are required for key reformat'); - } - const options = { privateKey, userIDs, passphrase, keyExpirationTime, date }; - - try { - const { key: reformattedKey, revocationCertificate } = await reformat(options, config); - - return { - privateKey: formatObject(reformattedKey, format, config), - publicKey: formatObject(reformattedKey.toPublic(), format, config), - revocationCertificate - }; - } catch (err) { - throw util.wrapError('Error reformatting keypair', err); - } -} - -/** - * Revokes a key. Requires either a private key or a revocation certificate. - * If a revocation certificate is passed, the reasonForRevocation parameter will be ignored. - * @param {Object} options - * @param {Key} options.key - Public or private key to revoke - * @param {String} [options.revocationCertificate] - Revocation certificate to revoke the key with - * @param {Object} [options.reasonForRevocation] - Object indicating the reason for revocation - * @param {module:enums.reasonForRevocation} [options.reasonForRevocation.flag=[noReason]{@link module:enums.reasonForRevocation}] - Flag indicating the reason for revocation - * @param {String} [options.reasonForRevocation.string=""] - String explaining the reason for revocation - * @param {Date} [options.date] - Use the given date instead of the current time to verify validity of revocation certificate (if provided), or as creation time of the revocation signature - * @param {'armored'|'binary'|'object'} [options.format='armored'] - format of the output key(s) - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} The revoked key in the form: - * { privateKey:PrivateKey|Uint8Array|String, publicKey:PublicKey|Uint8Array|String } if private key is passed, or - * { privateKey: null, publicKey:PublicKey|Uint8Array|String } otherwise - * @async - * @static - */ -async function revokeKey({ key, revocationCertificate, reasonForRevocation, date = new Date(), format = 'armored', config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - try { - const revokedKey = revocationCertificate ? - await key.applyRevocationCertificate(revocationCertificate, date, config) : - await key.revoke(reasonForRevocation, date, config); - - return revokedKey.isPrivate() ? { - privateKey: formatObject(revokedKey, format, config), - publicKey: formatObject(revokedKey.toPublic(), format, config) - } : { - privateKey: null, - publicKey: formatObject(revokedKey, format, config) - }; - } catch (err) { - throw util.wrapError('Error revoking key', err); - } -} - -/** - * Unlock a private key with the given passphrase. - * This method does not change the original key. - * @param {Object} options - * @param {PrivateKey} options.privateKey - The private key to decrypt - * @param {String|Array} options.passphrase - The user's passphrase(s) - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} The unlocked key object. - * @async - */ -async function decryptKey({ privateKey, passphrase, config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (!privateKey.isPrivate()) { - throw new Error('Cannot decrypt a public key'); - } - const clonedPrivateKey = privateKey.clone(true); - const passphrases = util.isArray(passphrase) ? passphrase : [passphrase]; - - try { - await Promise.all(clonedPrivateKey.getKeys().map(key => ( - // try to decrypt each key with any of the given passphrases - util.anyPromise(passphrases.map(passphrase => key.keyPacket.decrypt(passphrase))) - ))); - - await clonedPrivateKey.validate(config); - return clonedPrivateKey; - } catch (err) { - clonedPrivateKey.clearPrivateParams(); - throw util.wrapError('Error decrypting private key', err); - } -} - -/** - * Lock a private key with the given passphrase. - * This method does not change the original key. - * @param {Object} options - * @param {PrivateKey} options.privateKey - The private key to encrypt - * @param {String|Array} options.passphrase - If multiple passphrases, they should be in the same order as the packets each should encrypt - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} The locked key object. - * @async - */ -async function encryptKey({ privateKey, passphrase, config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (!privateKey.isPrivate()) { - throw new Error('Cannot encrypt a public key'); - } - const clonedPrivateKey = privateKey.clone(true); - - const keys = clonedPrivateKey.getKeys(); - const passphrases = util.isArray(passphrase) ? passphrase : new Array(keys.length).fill(passphrase); - if (passphrases.length !== keys.length) { - throw new Error('Invalid number of passphrases given for key encryption'); - } - - try { - await Promise.all(keys.map(async (key, i) => { - const { keyPacket } = key; - await keyPacket.encrypt(passphrases[i], config); - keyPacket.clearPrivateParams(); - })); - return clonedPrivateKey; - } catch (err) { - clonedPrivateKey.clearPrivateParams(); - throw util.wrapError('Error encrypting private key', err); - } -} - - -/////////////////////////////////////////// -// // -// Message encryption and decryption // -// // -/////////////////////////////////////////// - - -/** - * Encrypts a message using public keys, passwords or both at once. At least one of `encryptionKeys` or `passwords` - * must be specified. If signing keys are specified, those will be used to sign the message. - * @param {Object} options - * @param {Message} options.message - Message to be encrypted as created by {@link createMessage} - * @param {PublicKey|PublicKey[]} [options.encryptionKeys] - Array of keys or single key, used to encrypt the message - * @param {PrivateKey|PrivateKey[]} [options.signingKeys] - Private keys for signing. If omitted message will not be signed - * @param {String|String[]} [options.passwords] - Array of passwords or a single password to encrypt the message - * @param {Object} [options.sessionKey] - Session key in the form: `{ data:Uint8Array, algorithm:String }` - * @param {'armored'|'binary'|'object'} [options.format='armored'] - Format of the returned message - * @param {Signature} [options.signature] - A detached signature to add to the encrypted message - * @param {Boolean} [options.wildcard=false] - Use a key ID of 0 instead of the public key IDs - * @param {KeyID|KeyID[]} [options.signingKeyIDs=latest-created valid signing (sub)keys] - Array of key IDs to use for signing. Each `signingKeyIDs[i]` corresponds to `signingKeys[i]` - * @param {KeyID|KeyID[]} [options.encryptionKeyIDs=latest-created valid encryption (sub)keys] - Array of key IDs to use for encryption. Each `encryptionKeyIDs[i]` corresponds to `encryptionKeys[i]` - * @param {Date} [options.date=current date] - Override the creation date of the message signature - * @param {Object|Object[]} [options.signingUserIDs=primary user IDs] - Array of user IDs to sign with, one per key in `signingKeys`, e.g. `[{ name: 'Steve Sender', email: 'steve@openpgp.org' }]` - * @param {Object|Object[]} [options.encryptionUserIDs=primary user IDs] - Array of user IDs to encrypt for, one per key in `encryptionKeys`, e.g. `[{ name: 'Robert Receiver', email: 'robert@openpgp.org' }]` - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise|MaybeStream>} Encrypted message (string if `armor` was true, the default; Uint8Array if `armor` was false). - * @async - * @static - */ -async function encrypt$4({ message, encryptionKeys, signingKeys, passwords, sessionKey, format = 'armored', signature = null, wildcard = false, signingKeyIDs = [], encryptionKeyIDs = [], date = new Date(), signingUserIDs = [], encryptionUserIDs = [], config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - checkMessage(message); checkOutputMessageFormat(format); - encryptionKeys = toArray$1(encryptionKeys); signingKeys = toArray$1(signingKeys); passwords = toArray$1(passwords); - signingKeyIDs = toArray$1(signingKeyIDs); encryptionKeyIDs = toArray$1(encryptionKeyIDs); signingUserIDs = toArray$1(signingUserIDs); encryptionUserIDs = toArray$1(encryptionUserIDs); - if (rest.detached) { - throw new Error("The `detached` option has been removed from openpgp.encrypt, separately call openpgp.sign instead. Don't forget to remove the `privateKeys` option as well."); - } - if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.encrypt, pass `encryptionKeys` instead'); - if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.encrypt, pass `signingKeys` instead'); - if (rest.armor !== undefined) throw new Error('The `armor` option has been removed from openpgp.encrypt, pass `format` instead.'); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (!signingKeys) { - signingKeys = []; - } - const streaming = message.fromStream; - try { - if (signingKeys.length || signature) { // sign the message only if signing keys or signature is specified - message = await message.sign(signingKeys, signature, signingKeyIDs, date, signingUserIDs, config); - } - message = message.compress( - await getPreferredAlgo('compression', encryptionKeys, date, encryptionUserIDs, config), - config - ); - message = await message.encrypt(encryptionKeys, passwords, sessionKey, wildcard, encryptionKeyIDs, date, encryptionUserIDs, config); - if (format === 'object') return message; - // serialize data - const armor = format === 'armored'; - const data = armor ? message.armor(config) : message.write(); - return convertStream(data, streaming, armor ? 'utf8' : 'binary'); - } catch (err) { - throw util.wrapError('Error encrypting message', err); - } -} - -/** - * Decrypts a message with the user's private key, a session key or a password. - * One of `decryptionKeys`, `sessionkeys` or `passwords` must be specified (passing a combination of these options is not supported). - * @param {Object} options - * @param {Message} options.message - The message object with the encrypted data - * @param {PrivateKey|PrivateKey[]} [options.decryptionKeys] - Private keys with decrypted secret key data or session key - * @param {String|String[]} [options.passwords] - Passwords to decrypt the message - * @param {Object|Object[]} [options.sessionKeys] - Session keys in the form: { data:Uint8Array, algorithm:String } - * @param {PublicKey|PublicKey[]} [options.verificationKeys] - Array of public keys or single key, to verify signatures - * @param {Boolean} [options.expectSigned=false] - If true, data decryption fails if the message is not signed with the provided publicKeys - * @param {'utf8'|'binary'} [options.format='utf8'] - Whether to return data as a string(Stream) or Uint8Array(Stream). If 'utf8' (the default), also normalize newlines. - * @param {Signature} [options.signature] - Detached signature for verification - * @param {Date} [options.date=current date] - Use the given date for verification instead of the current time - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} Object containing decrypted and verified message in the form: - * - * { - * data: MaybeStream, (if format was 'utf8', the default) - * data: MaybeStream, (if format was 'binary') - * filename: String, - * signatures: [ - * { - * keyID: module:type/keyid~KeyID, - * verified: Promise, - * signature: Promise - * }, ... - * ] - * } - * - * where `signatures` contains a separate entry for each signature packet found in the input message. - * @async - * @static - */ -async function decrypt$4({ message, decryptionKeys, passwords, sessionKeys, verificationKeys, expectSigned = false, format = 'utf8', signature = null, date = new Date(), config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - checkMessage(message); verificationKeys = toArray$1(verificationKeys); decryptionKeys = toArray$1(decryptionKeys); passwords = toArray$1(passwords); sessionKeys = toArray$1(sessionKeys); - if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.decrypt, pass `decryptionKeys` instead'); - if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.decrypt, pass `verificationKeys` instead'); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - try { - const decrypted = await message.decrypt(decryptionKeys, passwords, sessionKeys, date, config); - if (!verificationKeys) { - verificationKeys = []; - } - - const result = {}; - result.signatures = signature ? await decrypted.verifyDetached(signature, verificationKeys, date, config) : await decrypted.verify(verificationKeys, date, config); - result.data = format === 'binary' ? decrypted.getLiteralData() : decrypted.getText(); - result.filename = decrypted.getFilename(); - linkStreams(result, message); - if (expectSigned) { - if (verificationKeys.length === 0) { - throw new Error('Verification keys are required to verify message signatures'); - } - if (result.signatures.length === 0) { - throw new Error('Message is not signed'); - } - result.data = concat([ - result.data, - fromAsync(async () => { - await util.anyPromise(result.signatures.map(sig => sig.verified)); - }) - ]); - } - result.data = await convertStream(result.data, message.fromStream, format); - return result; - } catch (err) { - throw util.wrapError('Error decrypting message', err); - } -} - - -////////////////////////////////////////// -// // -// Message signing and verification // -// // -////////////////////////////////////////// - - -/** - * Signs a message. - * @param {Object} options - * @param {CleartextMessage|Message} options.message - (cleartext) message to be signed - * @param {PrivateKey|PrivateKey[]} options.signingKeys - Array of keys or single key with decrypted secret key data to sign cleartext - * @param {'armored'|'binary'|'object'} [options.format='armored'] - Format of the returned message - * @param {Boolean} [options.detached=false] - If the return value should contain a detached signature - * @param {KeyID|KeyID[]} [options.signingKeyIDs=latest-created valid signing (sub)keys] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] - * @param {Date} [options.date=current date] - Override the creation date of the signature - * @param {Object|Object[]} [options.signingUserIDs=primary user IDs] - Array of user IDs to sign with, one per key in `signingKeys`, e.g. `[{ name: 'Steve Sender', email: 'steve@openpgp.org' }]` - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise>} Signed message (string if `armor` was true, the default; Uint8Array if `armor` was false). - * @async - * @static - */ -async function sign$5({ message, signingKeys, format = 'armored', detached = false, signingKeyIDs = [], date = new Date(), signingUserIDs = [], config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - checkCleartextOrMessage(message); checkOutputMessageFormat(format); - signingKeys = toArray$1(signingKeys); signingKeyIDs = toArray$1(signingKeyIDs); signingUserIDs = toArray$1(signingUserIDs); - - if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.sign, pass `signingKeys` instead'); - if (rest.armor !== undefined) throw new Error('The `armor` option has been removed from openpgp.sign, pass `format` instead.'); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (message instanceof CleartextMessage && format === 'binary') throw new Error('Cannot return signed cleartext message in binary format'); - if (message instanceof CleartextMessage && detached) throw new Error('Cannot detach-sign a cleartext message'); - - if (!signingKeys || signingKeys.length === 0) { - throw new Error('No signing keys provided'); - } - - try { - let signature; - if (detached) { - signature = await message.signDetached(signingKeys, undefined, signingKeyIDs, date, signingUserIDs, config); - } else { - signature = await message.sign(signingKeys, undefined, signingKeyIDs, date, signingUserIDs, config); - } - if (format === 'object') return signature; - - const armor = format === 'armored'; - signature = armor ? signature.armor(config) : signature.write(); - if (detached) { - signature = transformPair(message.packets.write(), async (readable, writable) => { - await Promise.all([ - pipe(signature, writable), - readToEnd(readable).catch(() => {}) - ]); - }); - } - return convertStream(signature, message.fromStream, armor ? 'utf8' : 'binary'); - } catch (err) { - throw util.wrapError('Error signing message', err); - } -} - -/** - * Verifies signatures of cleartext signed message - * @param {Object} options - * @param {CleartextMessage|Message} options.message - (cleartext) message object with signatures - * @param {PublicKey|PublicKey[]} options.verificationKeys - Array of publicKeys or single key, to verify signatures - * @param {Boolean} [options.expectSigned=false] - If true, verification throws if the message is not signed with the provided publicKeys - * @param {'utf8'|'binary'} [options.format='utf8'] - Whether to return data as a string(Stream) or Uint8Array(Stream). If 'utf8' (the default), also normalize newlines. - * @param {Signature} [options.signature] - Detached signature for verification - * @param {Date} [options.date=current date] - Use the given date for verification instead of the current time - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} Object containing verified message in the form: - * - * { - * data: MaybeStream, (if `message` was a CleartextMessage) - * data: MaybeStream, (if `message` was a Message) - * signatures: [ - * { - * keyID: module:type/keyid~KeyID, - * verified: Promise, - * signature: Promise - * }, ... - * ] - * } - * - * where `signatures` contains a separate entry for each signature packet found in the input message. - * @async - * @static - */ -async function verify$5({ message, verificationKeys, expectSigned = false, format = 'utf8', signature = null, date = new Date(), config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - checkCleartextOrMessage(message); verificationKeys = toArray$1(verificationKeys); - if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.verify, pass `verificationKeys` instead'); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (message instanceof CleartextMessage && format === 'binary') throw new Error("Can't return cleartext message data as binary"); - if (message instanceof CleartextMessage && signature) throw new Error("Can't verify detached cleartext signature"); - - try { - const result = {}; - if (signature) { - result.signatures = await message.verifyDetached(signature, verificationKeys, date, config); - } else { - result.signatures = await message.verify(verificationKeys, date, config); - } - result.data = format === 'binary' ? message.getLiteralData() : message.getText(); - if (message.fromStream) linkStreams(result, message); - if (expectSigned) { - if (result.signatures.length === 0) { - throw new Error('Message is not signed'); - } - result.data = concat([ - result.data, - fromAsync(async () => { - await util.anyPromise(result.signatures.map(sig => sig.verified)); - }) - ]); - } - result.data = await convertStream(result.data, message.fromStream, format); - return result; - } catch (err) { - throw util.wrapError('Error verifying signed message', err); - } -} - - -/////////////////////////////////////////////// -// // -// Session key encryption and decryption // -// // -/////////////////////////////////////////////// - -/** - * Generate a new session key object, taking the algorithm preferences of the passed public keys into account. - * @param {Object} options - * @param {PublicKey|PublicKey[]} options.encryptionKeys - Array of public keys or single key used to select algorithm preferences for - * @param {Date} [options.date=current date] - Date to select algorithm preferences at - * @param {Object|Object[]} [options.encryptionUserIDs=primary user IDs] - User IDs to select algorithm preferences for - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise<{ data: Uint8Array, algorithm: String }>} Object with session key data and algorithm. - * @async - * @static - */ -async function generateSessionKey$1({ encryptionKeys, date = new Date(), encryptionUserIDs = [], config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - encryptionKeys = toArray$1(encryptionKeys); encryptionUserIDs = toArray$1(encryptionUserIDs); - if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.generateSessionKey, pass `encryptionKeys` instead'); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - try { - const sessionKeys = await Message.generateSessionKey(encryptionKeys, date, encryptionUserIDs, config); - return sessionKeys; - } catch (err) { - throw util.wrapError('Error generating session key', err); - } -} - -/** - * Encrypt a symmetric session key with public keys, passwords, or both at once. - * At least one of `encryptionKeys` or `passwords` must be specified. - * @param {Object} options - * @param {Uint8Array} options.data - The session key to be encrypted e.g. 16 random bytes (for aes128) - * @param {String} options.algorithm - Algorithm of the symmetric session key e.g. 'aes128' or 'aes256' - * @param {String} [options.aeadAlgorithm] - AEAD algorithm, e.g. 'eax' or 'ocb' - * @param {PublicKey|PublicKey[]} [options.encryptionKeys] - Array of public keys or single key, used to encrypt the key - * @param {String|String[]} [options.passwords] - Passwords for the message - * @param {'armored'|'binary'} [options.format='armored'] - Format of the returned value - * @param {Boolean} [options.wildcard=false] - Use a key ID of 0 instead of the public key IDs - * @param {KeyID|KeyID[]} [options.encryptionKeyIDs=latest-created valid encryption (sub)keys] - Array of key IDs to use for encryption. Each encryptionKeyIDs[i] corresponds to encryptionKeys[i] - * @param {Date} [options.date=current date] - Override the date - * @param {Object|Object[]} [options.encryptionUserIDs=primary user IDs] - Array of user IDs to encrypt for, one per key in `encryptionKeys`, e.g. `[{ name: 'Phil Zimmermann', email: 'phil@openpgp.org' }]` - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} Encrypted session keys (string if `armor` was true, the default; Uint8Array if `armor` was false). - * @async - * @static - */ -async function encryptSessionKey({ data, algorithm, aeadAlgorithm, encryptionKeys, passwords, format = 'armored', wildcard = false, encryptionKeyIDs = [], date = new Date(), encryptionUserIDs = [], config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - checkBinary(data); checkString(algorithm, 'algorithm'); checkOutputMessageFormat(format); - encryptionKeys = toArray$1(encryptionKeys); passwords = toArray$1(passwords); encryptionKeyIDs = toArray$1(encryptionKeyIDs); encryptionUserIDs = toArray$1(encryptionUserIDs); - if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.encryptSessionKey, pass `encryptionKeys` instead'); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - try { - const message = await Message.encryptSessionKey(data, algorithm, aeadAlgorithm, encryptionKeys, passwords, wildcard, encryptionKeyIDs, date, encryptionUserIDs, config); - return formatObject(message, format, config); - } catch (err) { - throw util.wrapError('Error encrypting session key', err); - } -} - -/** - * Decrypt symmetric session keys using private keys or passwords (not both). - * One of `decryptionKeys` or `passwords` must be specified. - * @param {Object} options - * @param {Message} options.message - A message object containing the encrypted session key packets - * @param {PrivateKey|PrivateKey[]} [options.decryptionKeys] - Private keys with decrypted secret key data - * @param {String|String[]} [options.passwords] - Passwords to decrypt the session key - * @param {Date} [options.date] - Date to use for key verification instead of the current time - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} Array of decrypted session key, algorithm pairs in the form: - * { data:Uint8Array, algorithm:String } - * @throws if no session key could be found or decrypted - * @async - * @static - */ -async function decryptSessionKeys({ message, decryptionKeys, passwords, date = new Date(), config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - checkMessage(message); decryptionKeys = toArray$1(decryptionKeys); passwords = toArray$1(passwords); - if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.decryptSessionKeys, pass `decryptionKeys` instead'); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - try { - const sessionKeys = await message.decryptSessionKeys(decryptionKeys, passwords, date, config); - return sessionKeys; - } catch (err) { - throw util.wrapError('Error decrypting session keys', err); - } -} - - -////////////////////////// -// // -// Helper functions // -// // -////////////////////////// - - -/** - * Input validation - * @private - */ -function checkString(data, name) { - if (!util.isString(data)) { - throw new Error('Parameter [' + (name || 'data') + '] must be of type String'); - } -} -function checkBinary(data, name) { - if (!util.isUint8Array(data)) { - throw new Error('Parameter [' + (name || 'data') + '] must be of type Uint8Array'); - } -} -function checkMessage(message) { - if (!(message instanceof Message)) { - throw new Error('Parameter [message] needs to be of type Message'); - } -} -function checkCleartextOrMessage(message) { - if (!(message instanceof CleartextMessage) && !(message instanceof Message)) { - throw new Error('Parameter [message] needs to be of type Message or CleartextMessage'); - } -} -function checkOutputMessageFormat(format) { - if (format !== 'armored' && format !== 'binary' && format !== 'object') { - throw new Error(`Unsupported format ${format}`); - } -} -const defaultConfigPropsCount = Object.keys(defaultConfig).length; -function checkConfig(config) { - const inputConfigProps = Object.keys(config); - if (inputConfigProps.length !== defaultConfigPropsCount) { - for (const inputProp of inputConfigProps) { - if (defaultConfig[inputProp] === undefined) { - throw new Error(`Unknown config property: ${inputProp}`); - } - } - } -} - -/** - * Normalize parameter to an array if it is not undefined. - * @param {Object} param - the parameter to be normalized - * @returns {Array|undefined} The resulting array or undefined. - * @private - */ -function toArray$1(param) { - if (param && !util.isArray(param)) { - param = [param]; - } - return param; -} - -/** - * Convert data to or from Stream - * @param {Object} data - the data to convert - * @param {'web'|'ponyfill'|'node'|false} streaming - Whether to return a ReadableStream, and of what type - * @param {'utf8'|'binary'} [encoding] - How to return data in Node Readable streams - * @returns {Promise} The data in the respective format. - * @async - * @private - */ -async function convertStream(data, streaming, encoding = 'utf8') { - const streamType = util.isStream(data); - if (streamType === 'array') { - return readToEnd(data); - } - if (streaming === 'node') { - data = webToNode(data); - if (encoding !== 'binary') data.setEncoding(encoding); - return data; - } - if (streaming === 'web' && streamType === 'ponyfill') { - return toNativeReadable(data); - } - return data; -} - -/** - * Link result.data to the message stream for cancellation. - * Also, forward errors in the message to result.data. - * @param {Object} result - the data to convert - * @param {Message} message - message object - * @returns {Object} - * @private - */ -function linkStreams(result, message) { - result.data = transformPair(message.packets.stream, async (readable, writable) => { - await pipe(result.data, writable, { - preventClose: true - }); - const writer = getWriter(writable); - try { - // Forward errors in the message stream to result.data. - await readToEnd(readable, _ => _); - await writer.close(); - } catch (e) { - await writer.abort(e); - } - }); -} - -/** - * Convert the object to the given format - * @param {Key|Message} object - * @param {'armored'|'binary'|'object'} format - * @param {Object} config - Full configuration - * @returns {String|Uint8Array|Object} - */ -function formatObject(object, format, config) { - switch (format) { - case 'object': - return object; - case 'armored': - return object.armor(config); - case 'binary': - return object.write(); - default: - throw new Error(`Unsupported format ${format}`); - } -} - -/** - * web-streams-polyfill v3.0.3 - */ -/// -const SymbolPolyfill = typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol' ? - Symbol : - description => `Symbol(${description})`; - -/// -function noop() { - return undefined; -} -function getGlobals() { - if (typeof self !== 'undefined') { - return self; - } - else if (typeof window !== 'undefined') { - return window; - } - else if (typeof global !== 'undefined') { - return global; - } - return undefined; -} -const globals = getGlobals(); - -function typeIsObject(x) { - return (typeof x === 'object' && x !== null) || typeof x === 'function'; -} -const rethrowAssertionErrorRejection = noop; - -const originalPromise = Promise; -const originalPromiseThen = Promise.prototype.then; -const originalPromiseResolve = Promise.resolve.bind(originalPromise); -const originalPromiseReject = Promise.reject.bind(originalPromise); -function newPromise(executor) { - return new originalPromise(executor); -} -function promiseResolvedWith(value) { - return originalPromiseResolve(value); -} -function promiseRejectedWith(reason) { - return originalPromiseReject(reason); -} -function PerformPromiseThen(promise, onFulfilled, onRejected) { - // There doesn't appear to be any way to correctly emulate the behaviour from JavaScript, so this is just an - // approximation. - return originalPromiseThen.call(promise, onFulfilled, onRejected); -} -function uponPromise(promise, onFulfilled, onRejected) { - PerformPromiseThen(PerformPromiseThen(promise, onFulfilled, onRejected), undefined, rethrowAssertionErrorRejection); -} -function uponFulfillment(promise, onFulfilled) { - uponPromise(promise, onFulfilled); -} -function uponRejection(promise, onRejected) { - uponPromise(promise, undefined, onRejected); -} -function transformPromiseWith(promise, fulfillmentHandler, rejectionHandler) { - return PerformPromiseThen(promise, fulfillmentHandler, rejectionHandler); -} -function setPromiseIsHandledToTrue(promise) { - PerformPromiseThen(promise, undefined, rethrowAssertionErrorRejection); -} -const queueMicrotask = (() => { - const globalQueueMicrotask = globals && globals.queueMicrotask; - if (typeof globalQueueMicrotask === 'function') { - return globalQueueMicrotask; - } - const resolvedPromise = promiseResolvedWith(undefined); - return (fn) => PerformPromiseThen(resolvedPromise, fn); -})(); -function reflectCall(F, V, args) { - if (typeof F !== 'function') { - throw new TypeError('Argument is not a function'); - } - return Function.prototype.apply.call(F, V, args); -} -function promiseCall(F, V, args) { - try { - return promiseResolvedWith(reflectCall(F, V, args)); - } - catch (value) { - return promiseRejectedWith(value); - } -} - -// Original from Chromium -// https://chromium.googlesource.com/chromium/src/+/0aee4434a4dba42a42abaea9bfbc0cd196a63bc1/third_party/blink/renderer/core/streams/SimpleQueue.js -const QUEUE_MAX_ARRAY_SIZE = 16384; -/** - * Simple queue structure. - * - * Avoids scalability issues with using a packed array directly by using - * multiple arrays in a linked list and keeping the array size bounded. - */ -class SimpleQueue { - constructor() { - this._cursor = 0; - this._size = 0; - // _front and _back are always defined. - this._front = { - _elements: [], - _next: undefined - }; - this._back = this._front; - // The cursor is used to avoid calling Array.shift(). - // It contains the index of the front element of the array inside the - // front-most node. It is always in the range [0, QUEUE_MAX_ARRAY_SIZE). - this._cursor = 0; - // When there is only one node, size === elements.length - cursor. - this._size = 0; - } - get length() { - return this._size; - } - // For exception safety, this method is structured in order: - // 1. Read state - // 2. Calculate required state mutations - // 3. Perform state mutations - push(element) { - const oldBack = this._back; - let newBack = oldBack; - if (oldBack._elements.length === QUEUE_MAX_ARRAY_SIZE - 1) { - newBack = { - _elements: [], - _next: undefined - }; - } - // push() is the mutation most likely to throw an exception, so it - // goes first. - oldBack._elements.push(element); - if (newBack !== oldBack) { - this._back = newBack; - oldBack._next = newBack; - } - ++this._size; - } - // Like push(), shift() follows the read -> calculate -> mutate pattern for - // exception safety. - shift() { // must not be called on an empty queue - const oldFront = this._front; - let newFront = oldFront; - const oldCursor = this._cursor; - let newCursor = oldCursor + 1; - const elements = oldFront._elements; - const element = elements[oldCursor]; - if (newCursor === QUEUE_MAX_ARRAY_SIZE) { - newFront = oldFront._next; - newCursor = 0; - } - // No mutations before this point. - --this._size; - this._cursor = newCursor; - if (oldFront !== newFront) { - this._front = newFront; - } - // Permit shifted element to be garbage collected. - elements[oldCursor] = undefined; - return element; - } - // The tricky thing about forEach() is that it can be called - // re-entrantly. The queue may be mutated inside the callback. It is easy to - // see that push() within the callback has no negative effects since the end - // of the queue is checked for on every iteration. If shift() is called - // repeatedly within the callback then the next iteration may return an - // element that has been removed. In this case the callback will be called - // with undefined values until we either "catch up" with elements that still - // exist or reach the back of the queue. - forEach(callback) { - let i = this._cursor; - let node = this._front; - let elements = node._elements; - while (i !== elements.length || node._next !== undefined) { - if (i === elements.length) { - node = node._next; - elements = node._elements; - i = 0; - if (elements.length === 0) { - break; - } - } - callback(elements[i]); - ++i; - } - } - // Return the element that would be returned if shift() was called now, - // without modifying the queue. - peek() { // must not be called on an empty queue - const front = this._front; - const cursor = this._cursor; - return front._elements[cursor]; - } -} - -function ReadableStreamReaderGenericInitialize(reader, stream) { - reader._ownerReadableStream = stream; - stream._reader = reader; - if (stream._state === 'readable') { - defaultReaderClosedPromiseInitialize(reader); - } - else if (stream._state === 'closed') { - defaultReaderClosedPromiseInitializeAsResolved(reader); - } - else { - defaultReaderClosedPromiseInitializeAsRejected(reader, stream._storedError); - } -} -// A client of ReadableStreamDefaultReader and ReadableStreamBYOBReader may use these functions directly to bypass state -// check. -function ReadableStreamReaderGenericCancel(reader, reason) { - const stream = reader._ownerReadableStream; - return ReadableStreamCancel(stream, reason); -} -function ReadableStreamReaderGenericRelease(reader) { - if (reader._ownerReadableStream._state === 'readable') { - defaultReaderClosedPromiseReject(reader, new TypeError(`Reader was released and can no longer be used to monitor the stream's closedness`)); - } - else { - defaultReaderClosedPromiseResetToRejected(reader, new TypeError(`Reader was released and can no longer be used to monitor the stream's closedness`)); - } - reader._ownerReadableStream._reader = undefined; - reader._ownerReadableStream = undefined; -} -// Helper functions for the readers. -function readerLockException(name) { - return new TypeError('Cannot ' + name + ' a stream using a released reader'); -} -// Helper functions for the ReadableStreamDefaultReader. -function defaultReaderClosedPromiseInitialize(reader) { - reader._closedPromise = newPromise((resolve, reject) => { - reader._closedPromise_resolve = resolve; - reader._closedPromise_reject = reject; - }); -} -function defaultReaderClosedPromiseInitializeAsRejected(reader, reason) { - defaultReaderClosedPromiseInitialize(reader); - defaultReaderClosedPromiseReject(reader, reason); -} -function defaultReaderClosedPromiseInitializeAsResolved(reader) { - defaultReaderClosedPromiseInitialize(reader); - defaultReaderClosedPromiseResolve(reader); -} -function defaultReaderClosedPromiseReject(reader, reason) { - if (reader._closedPromise_reject === undefined) { - return; - } - setPromiseIsHandledToTrue(reader._closedPromise); - reader._closedPromise_reject(reason); - reader._closedPromise_resolve = undefined; - reader._closedPromise_reject = undefined; -} -function defaultReaderClosedPromiseResetToRejected(reader, reason) { - defaultReaderClosedPromiseInitializeAsRejected(reader, reason); -} -function defaultReaderClosedPromiseResolve(reader) { - if (reader._closedPromise_resolve === undefined) { - return; - } - reader._closedPromise_resolve(undefined); - reader._closedPromise_resolve = undefined; - reader._closedPromise_reject = undefined; -} - -const AbortSteps = SymbolPolyfill('[[AbortSteps]]'); -const ErrorSteps = SymbolPolyfill('[[ErrorSteps]]'); -const CancelSteps = SymbolPolyfill('[[CancelSteps]]'); -const PullSteps = SymbolPolyfill('[[PullSteps]]'); - -/// -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isFinite#Polyfill -const NumberIsFinite = Number.isFinite || function (x) { - return typeof x === 'number' && isFinite(x); -}; - -/// -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc#Polyfill -const MathTrunc = Math.trunc || function (v) { - return v < 0 ? Math.ceil(v) : Math.floor(v); -}; - -// https://heycam.github.io/webidl/#idl-dictionaries -function isDictionary(x) { - return typeof x === 'object' || typeof x === 'function'; -} -function assertDictionary(obj, context) { - if (obj !== undefined && !isDictionary(obj)) { - throw new TypeError(`${context} is not an object.`); - } -} -// https://heycam.github.io/webidl/#idl-callback-functions -function assertFunction(x, context) { - if (typeof x !== 'function') { - throw new TypeError(`${context} is not a function.`); - } -} -// https://heycam.github.io/webidl/#idl-object -function isObject(x) { - return (typeof x === 'object' && x !== null) || typeof x === 'function'; -} -function assertObject(x, context) { - if (!isObject(x)) { - throw new TypeError(`${context} is not an object.`); - } -} -function assertRequiredArgument(x, position, context) { - if (x === undefined) { - throw new TypeError(`Parameter ${position} is required in '${context}'.`); - } -} -function assertRequiredField(x, field, context) { - if (x === undefined) { - throw new TypeError(`${field} is required in '${context}'.`); - } -} -// https://heycam.github.io/webidl/#idl-unrestricted-double -function convertUnrestrictedDouble(value) { - return Number(value); -} -function censorNegativeZero(x) { - return x === 0 ? 0 : x; -} -function integerPart(x) { - return censorNegativeZero(MathTrunc(x)); -} -// https://heycam.github.io/webidl/#idl-unsigned-long-long -function convertUnsignedLongLongWithEnforceRange(value, context) { - const lowerBound = 0; - const upperBound = Number.MAX_SAFE_INTEGER; - let x = Number(value); - x = censorNegativeZero(x); - if (!NumberIsFinite(x)) { - throw new TypeError(`${context} is not a finite number`); - } - x = integerPart(x); - if (x < lowerBound || x > upperBound) { - throw new TypeError(`${context} is outside the accepted range of ${lowerBound} to ${upperBound}, inclusive`); - } - if (!NumberIsFinite(x) || x === 0) { - return 0; - } - // TODO Use BigInt if supported? - // let xBigInt = BigInt(integerPart(x)); - // xBigInt = BigInt.asUintN(64, xBigInt); - // return Number(xBigInt); - return x; -} - -function assertReadableStream(x, context) { - if (!IsReadableStream(x)) { - throw new TypeError(`${context} is not a ReadableStream.`); - } -} - -// Abstract operations for the ReadableStream. -function AcquireReadableStreamDefaultReader(stream) { - return new ReadableStreamDefaultReader(stream); -} -// ReadableStream API exposed for controllers. -function ReadableStreamAddReadRequest(stream, readRequest) { - stream._reader._readRequests.push(readRequest); -} -function ReadableStreamFulfillReadRequest(stream, chunk, done) { - const reader = stream._reader; - const readRequest = reader._readRequests.shift(); - if (done) { - readRequest._closeSteps(); - } - else { - readRequest._chunkSteps(chunk); - } -} -function ReadableStreamGetNumReadRequests(stream) { - return stream._reader._readRequests.length; -} -function ReadableStreamHasDefaultReader(stream) { - const reader = stream._reader; - if (reader === undefined) { - return false; - } - if (!IsReadableStreamDefaultReader(reader)) { - return false; - } - return true; -} -/** - * A default reader vended by a {@link ReadableStream}. - * - * @public - */ -class ReadableStreamDefaultReader { - constructor(stream) { - assertRequiredArgument(stream, 1, 'ReadableStreamDefaultReader'); - assertReadableStream(stream, 'First parameter'); - if (IsReadableStreamLocked(stream)) { - throw new TypeError('This stream has already been locked for exclusive reading by another reader'); - } - ReadableStreamReaderGenericInitialize(this, stream); - this._readRequests = new SimpleQueue(); - } - /** - * Returns a promise that will be fulfilled when the stream becomes closed, - * or rejected if the stream ever errors or the reader's lock is released before the stream finishes closing. - */ - get closed() { - if (!IsReadableStreamDefaultReader(this)) { - return promiseRejectedWith(defaultReaderBrandCheckException('closed')); - } - return this._closedPromise; - } - /** - * If the reader is active, behaves the same as {@link ReadableStream.cancel | stream.cancel(reason)}. - */ - cancel(reason = undefined) { - if (!IsReadableStreamDefaultReader(this)) { - return promiseRejectedWith(defaultReaderBrandCheckException('cancel')); - } - if (this._ownerReadableStream === undefined) { - return promiseRejectedWith(readerLockException('cancel')); - } - return ReadableStreamReaderGenericCancel(this, reason); - } - /** - * Returns a promise that allows access to the next chunk from the stream's internal queue, if available. - * - * If reading a chunk causes the queue to become empty, more data will be pulled from the underlying source. - */ - read() { - if (!IsReadableStreamDefaultReader(this)) { - return promiseRejectedWith(defaultReaderBrandCheckException('read')); - } - if (this._ownerReadableStream === undefined) { - return promiseRejectedWith(readerLockException('read from')); - } - let resolvePromise; - let rejectPromise; - const promise = newPromise((resolve, reject) => { - resolvePromise = resolve; - rejectPromise = reject; - }); - const readRequest = { - _chunkSteps: chunk => resolvePromise({ value: chunk, done: false }), - _closeSteps: () => resolvePromise({ value: undefined, done: true }), - _errorSteps: e => rejectPromise(e) - }; - ReadableStreamDefaultReaderRead(this, readRequest); - return promise; - } - /** - * Releases the reader's lock on the corresponding stream. After the lock is released, the reader is no longer active. - * If the associated stream is errored when the lock is released, the reader will appear errored in the same way - * from now on; otherwise, the reader will appear closed. - * - * A reader's lock cannot be released while it still has a pending read request, i.e., if a promise returned by - * the reader's {@link ReadableStreamDefaultReader.read | read()} method has not yet been settled. Attempting to - * do so will throw a `TypeError` and leave the reader locked to the stream. - */ - releaseLock() { - if (!IsReadableStreamDefaultReader(this)) { - throw defaultReaderBrandCheckException('releaseLock'); - } - if (this._ownerReadableStream === undefined) { - return; - } - if (this._readRequests.length > 0) { - throw new TypeError('Tried to release a reader lock when that reader has pending read() calls un-settled'); - } - ReadableStreamReaderGenericRelease(this); - } -} -Object.defineProperties(ReadableStreamDefaultReader.prototype, { - cancel: { enumerable: true }, - read: { enumerable: true }, - releaseLock: { enumerable: true }, - closed: { enumerable: true } -}); -if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(ReadableStreamDefaultReader.prototype, SymbolPolyfill.toStringTag, { - value: 'ReadableStreamDefaultReader', - configurable: true - }); -} -// Abstract operations for the readers. -function IsReadableStreamDefaultReader(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_readRequests')) { - return false; - } - return true; -} -function ReadableStreamDefaultReaderRead(reader, readRequest) { - const stream = reader._ownerReadableStream; - stream._disturbed = true; - if (stream._state === 'closed') { - readRequest._closeSteps(); - } - else if (stream._state === 'errored') { - readRequest._errorSteps(stream._storedError); - } - else { - stream._readableStreamController[PullSteps](readRequest); - } -} -// Helper functions for the ReadableStreamDefaultReader. -function defaultReaderBrandCheckException(name) { - return new TypeError(`ReadableStreamDefaultReader.prototype.${name} can only be used on a ReadableStreamDefaultReader`); -} - -/// -let AsyncIteratorPrototype; -if (typeof SymbolPolyfill.asyncIterator === 'symbol') { - // We're running inside a ES2018+ environment, but we're compiling to an older syntax. - // We cannot access %AsyncIteratorPrototype% without non-ES2018 syntax, but we can re-create it. - AsyncIteratorPrototype = { - // 25.1.3.1 %AsyncIteratorPrototype% [ @@asyncIterator ] ( ) - // https://tc39.github.io/ecma262/#sec-asynciteratorprototype-asynciterator - [SymbolPolyfill.asyncIterator]() { - return this; - } - }; - Object.defineProperty(AsyncIteratorPrototype, SymbolPolyfill.asyncIterator, { enumerable: false }); -} - -/// -class ReadableStreamAsyncIteratorImpl { - constructor(reader, preventCancel) { - this._ongoingPromise = undefined; - this._isFinished = false; - this._reader = reader; - this._preventCancel = preventCancel; - } - next() { - const nextSteps = () => this._nextSteps(); - this._ongoingPromise = this._ongoingPromise ? - transformPromiseWith(this._ongoingPromise, nextSteps, nextSteps) : - nextSteps(); - return this._ongoingPromise; - } - return(value) { - const returnSteps = () => this._returnSteps(value); - return this._ongoingPromise ? - transformPromiseWith(this._ongoingPromise, returnSteps, returnSteps) : - returnSteps(); - } - _nextSteps() { - if (this._isFinished) { - return Promise.resolve({ value: undefined, done: true }); - } - const reader = this._reader; - if (reader._ownerReadableStream === undefined) { - return promiseRejectedWith(readerLockException('iterate')); - } - let resolvePromise; - let rejectPromise; - const promise = newPromise((resolve, reject) => { - resolvePromise = resolve; - rejectPromise = reject; - }); - const readRequest = { - _chunkSteps: chunk => { - this._ongoingPromise = undefined; - // This needs to be delayed by one microtask, otherwise we stop pulling too early which breaks a test. - // FIXME Is this a bug in the specification, or in the test? - queueMicrotask(() => resolvePromise({ value: chunk, done: false })); - }, - _closeSteps: () => { - this._ongoingPromise = undefined; - this._isFinished = true; - ReadableStreamReaderGenericRelease(reader); - resolvePromise({ value: undefined, done: true }); - }, - _errorSteps: reason => { - this._ongoingPromise = undefined; - this._isFinished = true; - ReadableStreamReaderGenericRelease(reader); - rejectPromise(reason); - } - }; - ReadableStreamDefaultReaderRead(reader, readRequest); - return promise; - } - _returnSteps(value) { - if (this._isFinished) { - return Promise.resolve({ value, done: true }); - } - this._isFinished = true; - const reader = this._reader; - if (reader._ownerReadableStream === undefined) { - return promiseRejectedWith(readerLockException('finish iterating')); - } - if (!this._preventCancel) { - const result = ReadableStreamReaderGenericCancel(reader, value); - ReadableStreamReaderGenericRelease(reader); - return transformPromiseWith(result, () => ({ value, done: true })); - } - ReadableStreamReaderGenericRelease(reader); - return promiseResolvedWith({ value, done: true }); - } -} -const ReadableStreamAsyncIteratorPrototype = { - next() { - if (!IsReadableStreamAsyncIterator(this)) { - return promiseRejectedWith(streamAsyncIteratorBrandCheckException('next')); - } - return this._asyncIteratorImpl.next(); - }, - return(value) { - if (!IsReadableStreamAsyncIterator(this)) { - return promiseRejectedWith(streamAsyncIteratorBrandCheckException('return')); - } - return this._asyncIteratorImpl.return(value); - } -}; -if (AsyncIteratorPrototype !== undefined) { - Object.setPrototypeOf(ReadableStreamAsyncIteratorPrototype, AsyncIteratorPrototype); -} -// Abstract operations for the ReadableStream. -function AcquireReadableStreamAsyncIterator(stream, preventCancel) { - const reader = AcquireReadableStreamDefaultReader(stream); - const impl = new ReadableStreamAsyncIteratorImpl(reader, preventCancel); - const iterator = Object.create(ReadableStreamAsyncIteratorPrototype); - iterator._asyncIteratorImpl = impl; - return iterator; -} -function IsReadableStreamAsyncIterator(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_asyncIteratorImpl')) { - return false; - } - return true; -} -// Helper functions for the ReadableStream. -function streamAsyncIteratorBrandCheckException(name) { - return new TypeError(`ReadableStreamAsyncIterator.${name} can only be used on a ReadableSteamAsyncIterator`); -} - -/// -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN#Polyfill -const NumberIsNaN = Number.isNaN || function (x) { - // eslint-disable-next-line no-self-compare - return x !== x; -}; - -function IsFiniteNonNegativeNumber(v) { - if (!IsNonNegativeNumber(v)) { - return false; - } - if (v === Infinity) { - return false; - } - return true; -} -function IsNonNegativeNumber(v) { - if (typeof v !== 'number') { - return false; - } - if (NumberIsNaN(v)) { - return false; - } - if (v < 0) { - return false; - } - return true; -} - -function DequeueValue(container) { - const pair = container._queue.shift(); - container._queueTotalSize -= pair.size; - if (container._queueTotalSize < 0) { - container._queueTotalSize = 0; - } - return pair.value; -} -function EnqueueValueWithSize(container, value, size) { - size = Number(size); - if (!IsFiniteNonNegativeNumber(size)) { - throw new RangeError('Size must be a finite, non-NaN, non-negative number.'); - } - container._queue.push({ value, size }); - container._queueTotalSize += size; -} -function PeekQueueValue(container) { - const pair = container._queue.peek(); - return pair.value; -} -function ResetQueue(container) { - container._queue = new SimpleQueue(); - container._queueTotalSize = 0; -} - -function CreateArrayFromList(elements) { - // We use arrays to represent lists, so this is basically a no-op. - // Do a slice though just in case we happen to depend on the unique-ness. - return elements.slice(); -} -function CopyDataBlockBytes(dest, destOffset, src, srcOffset, n) { - new Uint8Array(dest).set(new Uint8Array(src, srcOffset, n), destOffset); -} -// Not implemented correctly -function TransferArrayBuffer(O) { - return O; -} -// Not implemented correctly -function IsDetachedBuffer(O) { - return false; -} - -/** - * A pull-into request in a {@link ReadableByteStreamController}. - * - * @public - */ -class ReadableStreamBYOBRequest { - constructor() { - throw new TypeError('Illegal constructor'); - } - /** - * Returns the view for writing in to, or `null` if the BYOB request has already been responded to. - */ - get view() { - if (!IsReadableStreamBYOBRequest(this)) { - throw byobRequestBrandCheckException('view'); - } - return this._view; - } - respond(bytesWritten) { - if (!IsReadableStreamBYOBRequest(this)) { - throw byobRequestBrandCheckException('respond'); - } - assertRequiredArgument(bytesWritten, 1, 'respond'); - bytesWritten = convertUnsignedLongLongWithEnforceRange(bytesWritten, 'First parameter'); - if (this._associatedReadableByteStreamController === undefined) { - throw new TypeError('This BYOB request has been invalidated'); - } - if (IsDetachedBuffer(this._view.buffer)) ; - ReadableByteStreamControllerRespond(this._associatedReadableByteStreamController, bytesWritten); - } - respondWithNewView(view) { - if (!IsReadableStreamBYOBRequest(this)) { - throw byobRequestBrandCheckException('respondWithNewView'); - } - assertRequiredArgument(view, 1, 'respondWithNewView'); - if (!ArrayBuffer.isView(view)) { - throw new TypeError('You can only respond with array buffer views'); - } - if (view.byteLength === 0) { - throw new TypeError('chunk must have non-zero byteLength'); - } - if (view.buffer.byteLength === 0) { - throw new TypeError(`chunk's buffer must have non-zero byteLength`); - } - if (this._associatedReadableByteStreamController === undefined) { - throw new TypeError('This BYOB request has been invalidated'); - } - ReadableByteStreamControllerRespondWithNewView(this._associatedReadableByteStreamController, view); - } -} -Object.defineProperties(ReadableStreamBYOBRequest.prototype, { - respond: { enumerable: true }, - respondWithNewView: { enumerable: true }, - view: { enumerable: true } -}); -if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(ReadableStreamBYOBRequest.prototype, SymbolPolyfill.toStringTag, { - value: 'ReadableStreamBYOBRequest', - configurable: true - }); -} -/** - * Allows control of a {@link ReadableStream | readable byte stream}'s state and internal queue. - * - * @public - */ -class ReadableByteStreamController { - constructor() { - throw new TypeError('Illegal constructor'); - } - /** - * Returns the current BYOB pull request, or `null` if there isn't one. - */ - get byobRequest() { - if (!IsReadableByteStreamController(this)) { - throw byteStreamControllerBrandCheckException('byobRequest'); - } - if (this._byobRequest === null && this._pendingPullIntos.length > 0) { - const firstDescriptor = this._pendingPullIntos.peek(); - const view = new Uint8Array(firstDescriptor.buffer, firstDescriptor.byteOffset + firstDescriptor.bytesFilled, firstDescriptor.byteLength - firstDescriptor.bytesFilled); - const byobRequest = Object.create(ReadableStreamBYOBRequest.prototype); - SetUpReadableStreamBYOBRequest(byobRequest, this, view); - this._byobRequest = byobRequest; - } - return this._byobRequest; - } - /** - * Returns the desired size to fill the controlled stream's internal queue. It can be negative, if the queue is - * over-full. An underlying byte source ought to use this information to determine when and how to apply backpressure. - */ - get desiredSize() { - if (!IsReadableByteStreamController(this)) { - throw byteStreamControllerBrandCheckException('desiredSize'); - } - return ReadableByteStreamControllerGetDesiredSize(this); - } - /** - * Closes the controlled readable stream. Consumers will still be able to read any previously-enqueued chunks from - * the stream, but once those are read, the stream will become closed. - */ - close() { - if (!IsReadableByteStreamController(this)) { - throw byteStreamControllerBrandCheckException('close'); - } - if (this._closeRequested) { - throw new TypeError('The stream has already been closed; do not close it again!'); - } - const state = this._controlledReadableByteStream._state; - if (state !== 'readable') { - throw new TypeError(`The stream (in ${state} state) is not in the readable state and cannot be closed`); - } - ReadableByteStreamControllerClose(this); - } - enqueue(chunk) { - if (!IsReadableByteStreamController(this)) { - throw byteStreamControllerBrandCheckException('enqueue'); - } - assertRequiredArgument(chunk, 1, 'enqueue'); - if (!ArrayBuffer.isView(chunk)) { - throw new TypeError('chunk must be an array buffer view'); - } - if (chunk.byteLength === 0) { - throw new TypeError('chunk must have non-zero byteLength'); - } - if (chunk.buffer.byteLength === 0) { - throw new TypeError(`chunk's buffer must have non-zero byteLength`); - } - if (this._closeRequested) { - throw new TypeError('stream is closed or draining'); - } - const state = this._controlledReadableByteStream._state; - if (state !== 'readable') { - throw new TypeError(`The stream (in ${state} state) is not in the readable state and cannot be enqueued to`); - } - ReadableByteStreamControllerEnqueue(this, chunk); - } - /** - * Errors the controlled readable stream, making all future interactions with it fail with the given error `e`. - */ - error(e = undefined) { - if (!IsReadableByteStreamController(this)) { - throw byteStreamControllerBrandCheckException('error'); - } - ReadableByteStreamControllerError(this, e); - } - /** @internal */ - [CancelSteps](reason) { - if (this._pendingPullIntos.length > 0) { - const firstDescriptor = this._pendingPullIntos.peek(); - firstDescriptor.bytesFilled = 0; - } - ResetQueue(this); - const result = this._cancelAlgorithm(reason); - ReadableByteStreamControllerClearAlgorithms(this); - return result; - } - /** @internal */ - [PullSteps](readRequest) { - const stream = this._controlledReadableByteStream; - if (this._queueTotalSize > 0) { - const entry = this._queue.shift(); - this._queueTotalSize -= entry.byteLength; - ReadableByteStreamControllerHandleQueueDrain(this); - const view = new Uint8Array(entry.buffer, entry.byteOffset, entry.byteLength); - readRequest._chunkSteps(view); - return; - } - const autoAllocateChunkSize = this._autoAllocateChunkSize; - if (autoAllocateChunkSize !== undefined) { - let buffer; - try { - buffer = new ArrayBuffer(autoAllocateChunkSize); - } - catch (bufferE) { - readRequest._errorSteps(bufferE); - return; - } - const pullIntoDescriptor = { - buffer, - byteOffset: 0, - byteLength: autoAllocateChunkSize, - bytesFilled: 0, - elementSize: 1, - viewConstructor: Uint8Array, - readerType: 'default' - }; - this._pendingPullIntos.push(pullIntoDescriptor); - } - ReadableStreamAddReadRequest(stream, readRequest); - ReadableByteStreamControllerCallPullIfNeeded(this); - } -} -Object.defineProperties(ReadableByteStreamController.prototype, { - close: { enumerable: true }, - enqueue: { enumerable: true }, - error: { enumerable: true }, - byobRequest: { enumerable: true }, - desiredSize: { enumerable: true } -}); -if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(ReadableByteStreamController.prototype, SymbolPolyfill.toStringTag, { - value: 'ReadableByteStreamController', - configurable: true - }); -} -// Abstract operations for the ReadableByteStreamController. -function IsReadableByteStreamController(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_controlledReadableByteStream')) { - return false; - } - return true; -} -function IsReadableStreamBYOBRequest(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_associatedReadableByteStreamController')) { - return false; - } - return true; -} -function ReadableByteStreamControllerCallPullIfNeeded(controller) { - const shouldPull = ReadableByteStreamControllerShouldCallPull(controller); - if (!shouldPull) { - return; - } - if (controller._pulling) { - controller._pullAgain = true; - return; - } - controller._pulling = true; - // TODO: Test controller argument - const pullPromise = controller._pullAlgorithm(); - uponPromise(pullPromise, () => { - controller._pulling = false; - if (controller._pullAgain) { - controller._pullAgain = false; - ReadableByteStreamControllerCallPullIfNeeded(controller); - } - }, e => { - ReadableByteStreamControllerError(controller, e); - }); -} -function ReadableByteStreamControllerClearPendingPullIntos(controller) { - ReadableByteStreamControllerInvalidateBYOBRequest(controller); - controller._pendingPullIntos = new SimpleQueue(); -} -function ReadableByteStreamControllerCommitPullIntoDescriptor(stream, pullIntoDescriptor) { - let done = false; - if (stream._state === 'closed') { - done = true; - } - const filledView = ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor); - if (pullIntoDescriptor.readerType === 'default') { - ReadableStreamFulfillReadRequest(stream, filledView, done); - } - else { - ReadableStreamFulfillReadIntoRequest(stream, filledView, done); - } -} -function ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor) { - const bytesFilled = pullIntoDescriptor.bytesFilled; - const elementSize = pullIntoDescriptor.elementSize; - return new pullIntoDescriptor.viewConstructor(pullIntoDescriptor.buffer, pullIntoDescriptor.byteOffset, bytesFilled / elementSize); -} -function ReadableByteStreamControllerEnqueueChunkToQueue(controller, buffer, byteOffset, byteLength) { - controller._queue.push({ buffer, byteOffset, byteLength }); - controller._queueTotalSize += byteLength; -} -function ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor) { - const elementSize = pullIntoDescriptor.elementSize; - const currentAlignedBytes = pullIntoDescriptor.bytesFilled - pullIntoDescriptor.bytesFilled % elementSize; - const maxBytesToCopy = Math.min(controller._queueTotalSize, pullIntoDescriptor.byteLength - pullIntoDescriptor.bytesFilled); - const maxBytesFilled = pullIntoDescriptor.bytesFilled + maxBytesToCopy; - const maxAlignedBytes = maxBytesFilled - maxBytesFilled % elementSize; - let totalBytesToCopyRemaining = maxBytesToCopy; - let ready = false; - if (maxAlignedBytes > currentAlignedBytes) { - totalBytesToCopyRemaining = maxAlignedBytes - pullIntoDescriptor.bytesFilled; - ready = true; - } - const queue = controller._queue; - while (totalBytesToCopyRemaining > 0) { - const headOfQueue = queue.peek(); - const bytesToCopy = Math.min(totalBytesToCopyRemaining, headOfQueue.byteLength); - const destStart = pullIntoDescriptor.byteOffset + pullIntoDescriptor.bytesFilled; - CopyDataBlockBytes(pullIntoDescriptor.buffer, destStart, headOfQueue.buffer, headOfQueue.byteOffset, bytesToCopy); - if (headOfQueue.byteLength === bytesToCopy) { - queue.shift(); - } - else { - headOfQueue.byteOffset += bytesToCopy; - headOfQueue.byteLength -= bytesToCopy; - } - controller._queueTotalSize -= bytesToCopy; - ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, bytesToCopy, pullIntoDescriptor); - totalBytesToCopyRemaining -= bytesToCopy; - } - return ready; -} -function ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, size, pullIntoDescriptor) { - ReadableByteStreamControllerInvalidateBYOBRequest(controller); - pullIntoDescriptor.bytesFilled += size; -} -function ReadableByteStreamControllerHandleQueueDrain(controller) { - if (controller._queueTotalSize === 0 && controller._closeRequested) { - ReadableByteStreamControllerClearAlgorithms(controller); - ReadableStreamClose(controller._controlledReadableByteStream); - } - else { - ReadableByteStreamControllerCallPullIfNeeded(controller); - } -} -function ReadableByteStreamControllerInvalidateBYOBRequest(controller) { - if (controller._byobRequest === null) { - return; - } - controller._byobRequest._associatedReadableByteStreamController = undefined; - controller._byobRequest._view = null; - controller._byobRequest = null; -} -function ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller) { - while (controller._pendingPullIntos.length > 0) { - if (controller._queueTotalSize === 0) { - return; - } - const pullIntoDescriptor = controller._pendingPullIntos.peek(); - if (ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor)) { - ReadableByteStreamControllerShiftPendingPullInto(controller); - ReadableByteStreamControllerCommitPullIntoDescriptor(controller._controlledReadableByteStream, pullIntoDescriptor); - } - } -} -function ReadableByteStreamControllerPullInto(controller, view, readIntoRequest) { - const stream = controller._controlledReadableByteStream; - let elementSize = 1; - if (view.constructor !== DataView) { - elementSize = view.constructor.BYTES_PER_ELEMENT; - } - const ctor = view.constructor; - const buffer = TransferArrayBuffer(view.buffer); - const pullIntoDescriptor = { - buffer, - byteOffset: view.byteOffset, - byteLength: view.byteLength, - bytesFilled: 0, - elementSize, - viewConstructor: ctor, - readerType: 'byob' - }; - if (controller._pendingPullIntos.length > 0) { - controller._pendingPullIntos.push(pullIntoDescriptor); - // No ReadableByteStreamControllerCallPullIfNeeded() call since: - // - No change happens on desiredSize - // - The source has already been notified of that there's at least 1 pending read(view) - ReadableStreamAddReadIntoRequest(stream, readIntoRequest); - return; - } - if (stream._state === 'closed') { - const emptyView = new ctor(pullIntoDescriptor.buffer, pullIntoDescriptor.byteOffset, 0); - readIntoRequest._closeSteps(emptyView); - return; - } - if (controller._queueTotalSize > 0) { - if (ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor)) { - const filledView = ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor); - ReadableByteStreamControllerHandleQueueDrain(controller); - readIntoRequest._chunkSteps(filledView); - return; - } - if (controller._closeRequested) { - const e = new TypeError('Insufficient bytes to fill elements in the given buffer'); - ReadableByteStreamControllerError(controller, e); - readIntoRequest._errorSteps(e); - return; - } - } - controller._pendingPullIntos.push(pullIntoDescriptor); - ReadableStreamAddReadIntoRequest(stream, readIntoRequest); - ReadableByteStreamControllerCallPullIfNeeded(controller); -} -function ReadableByteStreamControllerRespondInClosedState(controller, firstDescriptor) { - firstDescriptor.buffer = TransferArrayBuffer(firstDescriptor.buffer); - const stream = controller._controlledReadableByteStream; - if (ReadableStreamHasBYOBReader(stream)) { - while (ReadableStreamGetNumReadIntoRequests(stream) > 0) { - const pullIntoDescriptor = ReadableByteStreamControllerShiftPendingPullInto(controller); - ReadableByteStreamControllerCommitPullIntoDescriptor(stream, pullIntoDescriptor); - } - } -} -function ReadableByteStreamControllerRespondInReadableState(controller, bytesWritten, pullIntoDescriptor) { - if (pullIntoDescriptor.bytesFilled + bytesWritten > pullIntoDescriptor.byteLength) { - throw new RangeError('bytesWritten out of range'); - } - ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, bytesWritten, pullIntoDescriptor); - if (pullIntoDescriptor.bytesFilled < pullIntoDescriptor.elementSize) { - // TODO: Figure out whether we should detach the buffer or not here. - return; - } - ReadableByteStreamControllerShiftPendingPullInto(controller); - const remainderSize = pullIntoDescriptor.bytesFilled % pullIntoDescriptor.elementSize; - if (remainderSize > 0) { - const end = pullIntoDescriptor.byteOffset + pullIntoDescriptor.bytesFilled; - const remainder = pullIntoDescriptor.buffer.slice(end - remainderSize, end); - ReadableByteStreamControllerEnqueueChunkToQueue(controller, remainder, 0, remainder.byteLength); - } - pullIntoDescriptor.buffer = TransferArrayBuffer(pullIntoDescriptor.buffer); - pullIntoDescriptor.bytesFilled -= remainderSize; - ReadableByteStreamControllerCommitPullIntoDescriptor(controller._controlledReadableByteStream, pullIntoDescriptor); - ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller); -} -function ReadableByteStreamControllerRespondInternal(controller, bytesWritten) { - const firstDescriptor = controller._pendingPullIntos.peek(); - const state = controller._controlledReadableByteStream._state; - if (state === 'closed') { - if (bytesWritten !== 0) { - throw new TypeError('bytesWritten must be 0 when calling respond() on a closed stream'); - } - ReadableByteStreamControllerRespondInClosedState(controller, firstDescriptor); - } - else { - ReadableByteStreamControllerRespondInReadableState(controller, bytesWritten, firstDescriptor); - } - ReadableByteStreamControllerCallPullIfNeeded(controller); -} -function ReadableByteStreamControllerShiftPendingPullInto(controller) { - const descriptor = controller._pendingPullIntos.shift(); - ReadableByteStreamControllerInvalidateBYOBRequest(controller); - return descriptor; -} -function ReadableByteStreamControllerShouldCallPull(controller) { - const stream = controller._controlledReadableByteStream; - if (stream._state !== 'readable') { - return false; - } - if (controller._closeRequested) { - return false; - } - if (!controller._started) { - return false; - } - if (ReadableStreamHasDefaultReader(stream) && ReadableStreamGetNumReadRequests(stream) > 0) { - return true; - } - if (ReadableStreamHasBYOBReader(stream) && ReadableStreamGetNumReadIntoRequests(stream) > 0) { - return true; - } - const desiredSize = ReadableByteStreamControllerGetDesiredSize(controller); - if (desiredSize > 0) { - return true; - } - return false; -} -function ReadableByteStreamControllerClearAlgorithms(controller) { - controller._pullAlgorithm = undefined; - controller._cancelAlgorithm = undefined; -} -// A client of ReadableByteStreamController may use these functions directly to bypass state check. -function ReadableByteStreamControllerClose(controller) { - const stream = controller._controlledReadableByteStream; - if (controller._closeRequested || stream._state !== 'readable') { - return; - } - if (controller._queueTotalSize > 0) { - controller._closeRequested = true; - return; - } - if (controller._pendingPullIntos.length > 0) { - const firstPendingPullInto = controller._pendingPullIntos.peek(); - if (firstPendingPullInto.bytesFilled > 0) { - const e = new TypeError('Insufficient bytes to fill elements in the given buffer'); - ReadableByteStreamControllerError(controller, e); - throw e; - } - } - ReadableByteStreamControllerClearAlgorithms(controller); - ReadableStreamClose(stream); -} -function ReadableByteStreamControllerEnqueue(controller, chunk) { - const stream = controller._controlledReadableByteStream; - if (controller._closeRequested || stream._state !== 'readable') { - return; - } - const buffer = chunk.buffer; - const byteOffset = chunk.byteOffset; - const byteLength = chunk.byteLength; - const transferredBuffer = TransferArrayBuffer(buffer); - if (ReadableStreamHasDefaultReader(stream)) { - if (ReadableStreamGetNumReadRequests(stream) === 0) { - ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength); - } - else { - const transferredView = new Uint8Array(transferredBuffer, byteOffset, byteLength); - ReadableStreamFulfillReadRequest(stream, transferredView, false); - } - } - else if (ReadableStreamHasBYOBReader(stream)) { - // TODO: Ideally in this branch detaching should happen only if the buffer is not consumed fully. - ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength); - ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller); - } - else { - ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength); - } - ReadableByteStreamControllerCallPullIfNeeded(controller); -} -function ReadableByteStreamControllerError(controller, e) { - const stream = controller._controlledReadableByteStream; - if (stream._state !== 'readable') { - return; - } - ReadableByteStreamControllerClearPendingPullIntos(controller); - ResetQueue(controller); - ReadableByteStreamControllerClearAlgorithms(controller); - ReadableStreamError(stream, e); -} -function ReadableByteStreamControllerGetDesiredSize(controller) { - const state = controller._controlledReadableByteStream._state; - if (state === 'errored') { - return null; - } - if (state === 'closed') { - return 0; - } - return controller._strategyHWM - controller._queueTotalSize; -} -function ReadableByteStreamControllerRespond(controller, bytesWritten) { - bytesWritten = Number(bytesWritten); - if (!IsFiniteNonNegativeNumber(bytesWritten)) { - throw new RangeError('bytesWritten must be a finite'); - } - ReadableByteStreamControllerRespondInternal(controller, bytesWritten); -} -function ReadableByteStreamControllerRespondWithNewView(controller, view) { - const firstDescriptor = controller._pendingPullIntos.peek(); - if (firstDescriptor.byteOffset + firstDescriptor.bytesFilled !== view.byteOffset) { - throw new RangeError('The region specified by view does not match byobRequest'); - } - if (firstDescriptor.byteLength !== view.byteLength) { - throw new RangeError('The buffer of view has different capacity than byobRequest'); - } - firstDescriptor.buffer = view.buffer; - ReadableByteStreamControllerRespondInternal(controller, view.byteLength); -} -function SetUpReadableByteStreamController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, autoAllocateChunkSize) { - controller._controlledReadableByteStream = stream; - controller._pullAgain = false; - controller._pulling = false; - controller._byobRequest = null; - // Need to set the slots so that the assert doesn't fire. In the spec the slots already exist implicitly. - controller._queue = controller._queueTotalSize = undefined; - ResetQueue(controller); - controller._closeRequested = false; - controller._started = false; - controller._strategyHWM = highWaterMark; - controller._pullAlgorithm = pullAlgorithm; - controller._cancelAlgorithm = cancelAlgorithm; - controller._autoAllocateChunkSize = autoAllocateChunkSize; - controller._pendingPullIntos = new SimpleQueue(); - stream._readableStreamController = controller; - const startResult = startAlgorithm(); - uponPromise(promiseResolvedWith(startResult), () => { - controller._started = true; - ReadableByteStreamControllerCallPullIfNeeded(controller); - }, r => { - ReadableByteStreamControllerError(controller, r); - }); -} -function SetUpReadableByteStreamControllerFromUnderlyingSource(stream, underlyingByteSource, highWaterMark) { - const controller = Object.create(ReadableByteStreamController.prototype); - let startAlgorithm = () => undefined; - let pullAlgorithm = () => promiseResolvedWith(undefined); - let cancelAlgorithm = () => promiseResolvedWith(undefined); - if (underlyingByteSource.start !== undefined) { - startAlgorithm = () => underlyingByteSource.start(controller); - } - if (underlyingByteSource.pull !== undefined) { - pullAlgorithm = () => underlyingByteSource.pull(controller); - } - if (underlyingByteSource.cancel !== undefined) { - cancelAlgorithm = reason => underlyingByteSource.cancel(reason); - } - const autoAllocateChunkSize = underlyingByteSource.autoAllocateChunkSize; - if (autoAllocateChunkSize === 0) { - throw new TypeError('autoAllocateChunkSize must be greater than 0'); - } - SetUpReadableByteStreamController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, autoAllocateChunkSize); -} -function SetUpReadableStreamBYOBRequest(request, controller, view) { - request._associatedReadableByteStreamController = controller; - request._view = view; -} -// Helper functions for the ReadableStreamBYOBRequest. -function byobRequestBrandCheckException(name) { - return new TypeError(`ReadableStreamBYOBRequest.prototype.${name} can only be used on a ReadableStreamBYOBRequest`); -} -// Helper functions for the ReadableByteStreamController. -function byteStreamControllerBrandCheckException(name) { - return new TypeError(`ReadableByteStreamController.prototype.${name} can only be used on a ReadableByteStreamController`); -} - -// Abstract operations for the ReadableStream. -function AcquireReadableStreamBYOBReader(stream) { - return new ReadableStreamBYOBReader(stream); -} -// ReadableStream API exposed for controllers. -function ReadableStreamAddReadIntoRequest(stream, readIntoRequest) { - stream._reader._readIntoRequests.push(readIntoRequest); -} -function ReadableStreamFulfillReadIntoRequest(stream, chunk, done) { - const reader = stream._reader; - const readIntoRequest = reader._readIntoRequests.shift(); - if (done) { - readIntoRequest._closeSteps(chunk); - } - else { - readIntoRequest._chunkSteps(chunk); - } -} -function ReadableStreamGetNumReadIntoRequests(stream) { - return stream._reader._readIntoRequests.length; -} -function ReadableStreamHasBYOBReader(stream) { - const reader = stream._reader; - if (reader === undefined) { - return false; - } - if (!IsReadableStreamBYOBReader(reader)) { - return false; - } - return true; -} -/** - * A BYOB reader vended by a {@link ReadableStream}. - * - * @public - */ -class ReadableStreamBYOBReader { - constructor(stream) { - assertRequiredArgument(stream, 1, 'ReadableStreamBYOBReader'); - assertReadableStream(stream, 'First parameter'); - if (IsReadableStreamLocked(stream)) { - throw new TypeError('This stream has already been locked for exclusive reading by another reader'); - } - if (!IsReadableByteStreamController(stream._readableStreamController)) { - throw new TypeError('Cannot construct a ReadableStreamBYOBReader for a stream not constructed with a byte ' + - 'source'); - } - ReadableStreamReaderGenericInitialize(this, stream); - this._readIntoRequests = new SimpleQueue(); - } - /** - * Returns a promise that will be fulfilled when the stream becomes closed, or rejected if the stream ever errors or - * the reader's lock is released before the stream finishes closing. - */ - get closed() { - if (!IsReadableStreamBYOBReader(this)) { - return promiseRejectedWith(byobReaderBrandCheckException('closed')); - } - return this._closedPromise; - } - /** - * If the reader is active, behaves the same as {@link ReadableStream.cancel | stream.cancel(reason)}. - */ - cancel(reason = undefined) { - if (!IsReadableStreamBYOBReader(this)) { - return promiseRejectedWith(byobReaderBrandCheckException('cancel')); - } - if (this._ownerReadableStream === undefined) { - return promiseRejectedWith(readerLockException('cancel')); - } - return ReadableStreamReaderGenericCancel(this, reason); - } - /** - * Attempts to reads bytes into view, and returns a promise resolved with the result. - * - * If reading a chunk causes the queue to become empty, more data will be pulled from the underlying source. - */ - read(view) { - if (!IsReadableStreamBYOBReader(this)) { - return promiseRejectedWith(byobReaderBrandCheckException('read')); - } - if (!ArrayBuffer.isView(view)) { - return promiseRejectedWith(new TypeError('view must be an array buffer view')); - } - if (view.byteLength === 0) { - return promiseRejectedWith(new TypeError('view must have non-zero byteLength')); - } - if (view.buffer.byteLength === 0) { - return promiseRejectedWith(new TypeError(`view's buffer must have non-zero byteLength`)); - } - if (this._ownerReadableStream === undefined) { - return promiseRejectedWith(readerLockException('read from')); - } - let resolvePromise; - let rejectPromise; - const promise = newPromise((resolve, reject) => { - resolvePromise = resolve; - rejectPromise = reject; - }); - const readIntoRequest = { - _chunkSteps: chunk => resolvePromise({ value: chunk, done: false }), - _closeSteps: chunk => resolvePromise({ value: chunk, done: true }), - _errorSteps: e => rejectPromise(e) - }; - ReadableStreamBYOBReaderRead(this, view, readIntoRequest); - return promise; - } - /** - * Releases the reader's lock on the corresponding stream. After the lock is released, the reader is no longer active. - * If the associated stream is errored when the lock is released, the reader will appear errored in the same way - * from now on; otherwise, the reader will appear closed. - * - * A reader's lock cannot be released while it still has a pending read request, i.e., if a promise returned by - * the reader's {@link ReadableStreamBYOBReader.read | read()} method has not yet been settled. Attempting to - * do so will throw a `TypeError` and leave the reader locked to the stream. - */ - releaseLock() { - if (!IsReadableStreamBYOBReader(this)) { - throw byobReaderBrandCheckException('releaseLock'); - } - if (this._ownerReadableStream === undefined) { - return; - } - if (this._readIntoRequests.length > 0) { - throw new TypeError('Tried to release a reader lock when that reader has pending read() calls un-settled'); - } - ReadableStreamReaderGenericRelease(this); - } -} -Object.defineProperties(ReadableStreamBYOBReader.prototype, { - cancel: { enumerable: true }, - read: { enumerable: true }, - releaseLock: { enumerable: true }, - closed: { enumerable: true } -}); -if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(ReadableStreamBYOBReader.prototype, SymbolPolyfill.toStringTag, { - value: 'ReadableStreamBYOBReader', - configurable: true - }); -} -// Abstract operations for the readers. -function IsReadableStreamBYOBReader(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_readIntoRequests')) { - return false; - } - return true; -} -function ReadableStreamBYOBReaderRead(reader, view, readIntoRequest) { - const stream = reader._ownerReadableStream; - stream._disturbed = true; - if (stream._state === 'errored') { - readIntoRequest._errorSteps(stream._storedError); - } - else { - ReadableByteStreamControllerPullInto(stream._readableStreamController, view, readIntoRequest); - } -} -// Helper functions for the ReadableStreamBYOBReader. -function byobReaderBrandCheckException(name) { - return new TypeError(`ReadableStreamBYOBReader.prototype.${name} can only be used on a ReadableStreamBYOBReader`); -} - -function ExtractHighWaterMark(strategy, defaultHWM) { - const { highWaterMark } = strategy; - if (highWaterMark === undefined) { - return defaultHWM; - } - if (NumberIsNaN(highWaterMark) || highWaterMark < 0) { - throw new RangeError('Invalid highWaterMark'); - } - return highWaterMark; -} -function ExtractSizeAlgorithm(strategy) { - const { size } = strategy; - if (!size) { - return () => 1; - } - return size; -} - -function convertQueuingStrategy(init, context) { - assertDictionary(init, context); - const highWaterMark = init === null || init === void 0 ? void 0 : init.highWaterMark; - const size = init === null || init === void 0 ? void 0 : init.size; - return { - highWaterMark: highWaterMark === undefined ? undefined : convertUnrestrictedDouble(highWaterMark), - size: size === undefined ? undefined : convertQueuingStrategySize(size, `${context} has member 'size' that`) - }; -} -function convertQueuingStrategySize(fn, context) { - assertFunction(fn, context); - return chunk => convertUnrestrictedDouble(fn(chunk)); -} - -function convertUnderlyingSink(original, context) { - assertDictionary(original, context); - const abort = original === null || original === void 0 ? void 0 : original.abort; - const close = original === null || original === void 0 ? void 0 : original.close; - const start = original === null || original === void 0 ? void 0 : original.start; - const type = original === null || original === void 0 ? void 0 : original.type; - const write = original === null || original === void 0 ? void 0 : original.write; - return { - abort: abort === undefined ? - undefined : - convertUnderlyingSinkAbortCallback(abort, original, `${context} has member 'abort' that`), - close: close === undefined ? - undefined : - convertUnderlyingSinkCloseCallback(close, original, `${context} has member 'close' that`), - start: start === undefined ? - undefined : - convertUnderlyingSinkStartCallback(start, original, `${context} has member 'start' that`), - write: write === undefined ? - undefined : - convertUnderlyingSinkWriteCallback(write, original, `${context} has member 'write' that`), - type - }; -} -function convertUnderlyingSinkAbortCallback(fn, original, context) { - assertFunction(fn, context); - return (reason) => promiseCall(fn, original, [reason]); -} -function convertUnderlyingSinkCloseCallback(fn, original, context) { - assertFunction(fn, context); - return () => promiseCall(fn, original, []); -} -function convertUnderlyingSinkStartCallback(fn, original, context) { - assertFunction(fn, context); - return (controller) => reflectCall(fn, original, [controller]); -} -function convertUnderlyingSinkWriteCallback(fn, original, context) { - assertFunction(fn, context); - return (chunk, controller) => promiseCall(fn, original, [chunk, controller]); -} - -function assertWritableStream(x, context) { - if (!IsWritableStream(x)) { - throw new TypeError(`${context} is not a WritableStream.`); - } -} - -/** - * A writable stream represents a destination for data, into which you can write. - * - * @public - */ -class WritableStream$1 { - constructor(rawUnderlyingSink = {}, rawStrategy = {}) { - if (rawUnderlyingSink === undefined) { - rawUnderlyingSink = null; - } - else { - assertObject(rawUnderlyingSink, 'First parameter'); - } - const strategy = convertQueuingStrategy(rawStrategy, 'Second parameter'); - const underlyingSink = convertUnderlyingSink(rawUnderlyingSink, 'First parameter'); - InitializeWritableStream(this); - const type = underlyingSink.type; - if (type !== undefined) { - throw new RangeError('Invalid type is specified'); - } - const sizeAlgorithm = ExtractSizeAlgorithm(strategy); - const highWaterMark = ExtractHighWaterMark(strategy, 1); - SetUpWritableStreamDefaultControllerFromUnderlyingSink(this, underlyingSink, highWaterMark, sizeAlgorithm); - } - /** - * Returns whether or not the writable stream is locked to a writer. - */ - get locked() { - if (!IsWritableStream(this)) { - throw streamBrandCheckException$2('locked'); - } - return IsWritableStreamLocked(this); - } - /** - * Aborts the stream, signaling that the producer can no longer successfully write to the stream and it is to be - * immediately moved to an errored state, with any queued-up writes discarded. This will also execute any abort - * mechanism of the underlying sink. - * - * The returned promise will fulfill if the stream shuts down successfully, or reject if the underlying sink signaled - * that there was an error doing so. Additionally, it will reject with a `TypeError` (without attempting to cancel - * the stream) if the stream is currently locked. - */ - abort(reason = undefined) { - if (!IsWritableStream(this)) { - return promiseRejectedWith(streamBrandCheckException$2('abort')); - } - if (IsWritableStreamLocked(this)) { - return promiseRejectedWith(new TypeError('Cannot abort a stream that already has a writer')); - } - return WritableStreamAbort(this, reason); - } - /** - * Closes the stream. The underlying sink will finish processing any previously-written chunks, before invoking its - * close behavior. During this time any further attempts to write will fail (without erroring the stream). - * - * The method returns a promise that will fulfill if all remaining chunks are successfully written and the stream - * successfully closes, or rejects if an error is encountered during this process. Additionally, it will reject with - * a `TypeError` (without attempting to cancel the stream) if the stream is currently locked. - */ - close() { - if (!IsWritableStream(this)) { - return promiseRejectedWith(streamBrandCheckException$2('close')); - } - if (IsWritableStreamLocked(this)) { - return promiseRejectedWith(new TypeError('Cannot close a stream that already has a writer')); - } - if (WritableStreamCloseQueuedOrInFlight(this)) { - return promiseRejectedWith(new TypeError('Cannot close an already-closing stream')); - } - return WritableStreamClose(this); - } - /** - * Creates a {@link WritableStreamDefaultWriter | writer} and locks the stream to the new writer. While the stream - * is locked, no other writer can be acquired until this one is released. - * - * This functionality is especially useful for creating abstractions that desire the ability to write to a stream - * without interruption or interleaving. By getting a writer for the stream, you can ensure nobody else can write at - * the same time, which would cause the resulting written data to be unpredictable and probably useless. - */ - getWriter() { - if (!IsWritableStream(this)) { - throw streamBrandCheckException$2('getWriter'); - } - return AcquireWritableStreamDefaultWriter(this); - } -} -Object.defineProperties(WritableStream$1.prototype, { - abort: { enumerable: true }, - close: { enumerable: true }, - getWriter: { enumerable: true }, - locked: { enumerable: true } -}); -if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(WritableStream$1.prototype, SymbolPolyfill.toStringTag, { - value: 'WritableStream', - configurable: true - }); -} -// Abstract operations for the WritableStream. -function AcquireWritableStreamDefaultWriter(stream) { - return new WritableStreamDefaultWriter(stream); -} -// Throws if and only if startAlgorithm throws. -function CreateWritableStream(startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark = 1, sizeAlgorithm = () => 1) { - const stream = Object.create(WritableStream$1.prototype); - InitializeWritableStream(stream); - const controller = Object.create(WritableStreamDefaultController.prototype); - SetUpWritableStreamDefaultController(stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark, sizeAlgorithm); - return stream; -} -function InitializeWritableStream(stream) { - stream._state = 'writable'; - // The error that will be reported by new method calls once the state becomes errored. Only set when [[state]] is - // 'erroring' or 'errored'. May be set to an undefined value. - stream._storedError = undefined; - stream._writer = undefined; - // Initialize to undefined first because the constructor of the controller checks this - // variable to validate the caller. - stream._writableStreamController = undefined; - // This queue is placed here instead of the writer class in order to allow for passing a writer to the next data - // producer without waiting for the queued writes to finish. - stream._writeRequests = new SimpleQueue(); - // Write requests are removed from _writeRequests when write() is called on the underlying sink. This prevents - // them from being erroneously rejected on error. If a write() call is in-flight, the request is stored here. - stream._inFlightWriteRequest = undefined; - // The promise that was returned from writer.close(). Stored here because it may be fulfilled after the writer - // has been detached. - stream._closeRequest = undefined; - // Close request is removed from _closeRequest when close() is called on the underlying sink. This prevents it - // from being erroneously rejected on error. If a close() call is in-flight, the request is stored here. - stream._inFlightCloseRequest = undefined; - // The promise that was returned from writer.abort(). This may also be fulfilled after the writer has detached. - stream._pendingAbortRequest = undefined; - // The backpressure signal set by the controller. - stream._backpressure = false; -} -function IsWritableStream(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_writableStreamController')) { - return false; - } - return true; -} -function IsWritableStreamLocked(stream) { - if (stream._writer === undefined) { - return false; - } - return true; -} -function WritableStreamAbort(stream, reason) { - const state = stream._state; - if (state === 'closed' || state === 'errored') { - return promiseResolvedWith(undefined); - } - if (stream._pendingAbortRequest !== undefined) { - return stream._pendingAbortRequest._promise; - } - let wasAlreadyErroring = false; - if (state === 'erroring') { - wasAlreadyErroring = true; - // reason will not be used, so don't keep a reference to it. - reason = undefined; - } - const promise = newPromise((resolve, reject) => { - stream._pendingAbortRequest = { - _promise: undefined, - _resolve: resolve, - _reject: reject, - _reason: reason, - _wasAlreadyErroring: wasAlreadyErroring - }; - }); - stream._pendingAbortRequest._promise = promise; - if (!wasAlreadyErroring) { - WritableStreamStartErroring(stream, reason); - } - return promise; -} -function WritableStreamClose(stream) { - const state = stream._state; - if (state === 'closed' || state === 'errored') { - return promiseRejectedWith(new TypeError(`The stream (in ${state} state) is not in the writable state and cannot be closed`)); - } - const promise = newPromise((resolve, reject) => { - const closeRequest = { - _resolve: resolve, - _reject: reject - }; - stream._closeRequest = closeRequest; - }); - const writer = stream._writer; - if (writer !== undefined && stream._backpressure && state === 'writable') { - defaultWriterReadyPromiseResolve(writer); - } - WritableStreamDefaultControllerClose(stream._writableStreamController); - return promise; -} -// WritableStream API exposed for controllers. -function WritableStreamAddWriteRequest(stream) { - const promise = newPromise((resolve, reject) => { - const writeRequest = { - _resolve: resolve, - _reject: reject - }; - stream._writeRequests.push(writeRequest); - }); - return promise; -} -function WritableStreamDealWithRejection(stream, error) { - const state = stream._state; - if (state === 'writable') { - WritableStreamStartErroring(stream, error); - return; - } - WritableStreamFinishErroring(stream); -} -function WritableStreamStartErroring(stream, reason) { - const controller = stream._writableStreamController; - stream._state = 'erroring'; - stream._storedError = reason; - const writer = stream._writer; - if (writer !== undefined) { - WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, reason); - } - if (!WritableStreamHasOperationMarkedInFlight(stream) && controller._started) { - WritableStreamFinishErroring(stream); - } -} -function WritableStreamFinishErroring(stream) { - stream._state = 'errored'; - stream._writableStreamController[ErrorSteps](); - const storedError = stream._storedError; - stream._writeRequests.forEach(writeRequest => { - writeRequest._reject(storedError); - }); - stream._writeRequests = new SimpleQueue(); - if (stream._pendingAbortRequest === undefined) { - WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); - return; - } - const abortRequest = stream._pendingAbortRequest; - stream._pendingAbortRequest = undefined; - if (abortRequest._wasAlreadyErroring) { - abortRequest._reject(storedError); - WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); - return; - } - const promise = stream._writableStreamController[AbortSteps](abortRequest._reason); - uponPromise(promise, () => { - abortRequest._resolve(); - WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); - }, (reason) => { - abortRequest._reject(reason); - WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); - }); -} -function WritableStreamFinishInFlightWrite(stream) { - stream._inFlightWriteRequest._resolve(undefined); - stream._inFlightWriteRequest = undefined; -} -function WritableStreamFinishInFlightWriteWithError(stream, error) { - stream._inFlightWriteRequest._reject(error); - stream._inFlightWriteRequest = undefined; - WritableStreamDealWithRejection(stream, error); -} -function WritableStreamFinishInFlightClose(stream) { - stream._inFlightCloseRequest._resolve(undefined); - stream._inFlightCloseRequest = undefined; - const state = stream._state; - if (state === 'erroring') { - // The error was too late to do anything, so it is ignored. - stream._storedError = undefined; - if (stream._pendingAbortRequest !== undefined) { - stream._pendingAbortRequest._resolve(); - stream._pendingAbortRequest = undefined; - } - } - stream._state = 'closed'; - const writer = stream._writer; - if (writer !== undefined) { - defaultWriterClosedPromiseResolve(writer); - } -} -function WritableStreamFinishInFlightCloseWithError(stream, error) { - stream._inFlightCloseRequest._reject(error); - stream._inFlightCloseRequest = undefined; - // Never execute sink abort() after sink close(). - if (stream._pendingAbortRequest !== undefined) { - stream._pendingAbortRequest._reject(error); - stream._pendingAbortRequest = undefined; - } - WritableStreamDealWithRejection(stream, error); -} -// TODO(ricea): Fix alphabetical order. -function WritableStreamCloseQueuedOrInFlight(stream) { - if (stream._closeRequest === undefined && stream._inFlightCloseRequest === undefined) { - return false; - } - return true; -} -function WritableStreamHasOperationMarkedInFlight(stream) { - if (stream._inFlightWriteRequest === undefined && stream._inFlightCloseRequest === undefined) { - return false; - } - return true; -} -function WritableStreamMarkCloseRequestInFlight(stream) { - stream._inFlightCloseRequest = stream._closeRequest; - stream._closeRequest = undefined; -} -function WritableStreamMarkFirstWriteRequestInFlight(stream) { - stream._inFlightWriteRequest = stream._writeRequests.shift(); -} -function WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream) { - if (stream._closeRequest !== undefined) { - stream._closeRequest._reject(stream._storedError); - stream._closeRequest = undefined; - } - const writer = stream._writer; - if (writer !== undefined) { - defaultWriterClosedPromiseReject(writer, stream._storedError); - } -} -function WritableStreamUpdateBackpressure(stream, backpressure) { - const writer = stream._writer; - if (writer !== undefined && backpressure !== stream._backpressure) { - if (backpressure) { - defaultWriterReadyPromiseReset(writer); - } - else { - defaultWriterReadyPromiseResolve(writer); - } - } - stream._backpressure = backpressure; -} -/** - * A default writer vended by a {@link WritableStream}. - * - * @public - */ -class WritableStreamDefaultWriter { - constructor(stream) { - assertRequiredArgument(stream, 1, 'WritableStreamDefaultWriter'); - assertWritableStream(stream, 'First parameter'); - if (IsWritableStreamLocked(stream)) { - throw new TypeError('This stream has already been locked for exclusive writing by another writer'); - } - this._ownerWritableStream = stream; - stream._writer = this; - const state = stream._state; - if (state === 'writable') { - if (!WritableStreamCloseQueuedOrInFlight(stream) && stream._backpressure) { - defaultWriterReadyPromiseInitialize(this); - } - else { - defaultWriterReadyPromiseInitializeAsResolved(this); - } - defaultWriterClosedPromiseInitialize(this); - } - else if (state === 'erroring') { - defaultWriterReadyPromiseInitializeAsRejected(this, stream._storedError); - defaultWriterClosedPromiseInitialize(this); - } - else if (state === 'closed') { - defaultWriterReadyPromiseInitializeAsResolved(this); - defaultWriterClosedPromiseInitializeAsResolved(this); - } - else { - const storedError = stream._storedError; - defaultWriterReadyPromiseInitializeAsRejected(this, storedError); - defaultWriterClosedPromiseInitializeAsRejected(this, storedError); - } - } - /** - * Returns a promise that will be fulfilled when the stream becomes closed, or rejected if the stream ever errors or - * the writer’s lock is released before the stream finishes closing. - */ - get closed() { - if (!IsWritableStreamDefaultWriter(this)) { - return promiseRejectedWith(defaultWriterBrandCheckException('closed')); - } - return this._closedPromise; - } - /** - * Returns the desired size to fill the stream’s internal queue. It can be negative, if the queue is over-full. - * A producer can use this information to determine the right amount of data to write. - * - * It will be `null` if the stream cannot be successfully written to (due to either being errored, or having an abort - * queued up). It will return zero if the stream is closed. And the getter will throw an exception if invoked when - * the writer’s lock is released. - */ - get desiredSize() { - if (!IsWritableStreamDefaultWriter(this)) { - throw defaultWriterBrandCheckException('desiredSize'); - } - if (this._ownerWritableStream === undefined) { - throw defaultWriterLockException('desiredSize'); - } - return WritableStreamDefaultWriterGetDesiredSize(this); - } - /** - * Returns a promise that will be fulfilled when the desired size to fill the stream’s internal queue transitions - * from non-positive to positive, signaling that it is no longer applying backpressure. Once the desired size dips - * back to zero or below, the getter will return a new promise that stays pending until the next transition. - * - * If the stream becomes errored or aborted, or the writer’s lock is released, the returned promise will become - * rejected. - */ - get ready() { - if (!IsWritableStreamDefaultWriter(this)) { - return promiseRejectedWith(defaultWriterBrandCheckException('ready')); - } - return this._readyPromise; - } - /** - * If the reader is active, behaves the same as {@link WritableStream.abort | stream.abort(reason)}. - */ - abort(reason = undefined) { - if (!IsWritableStreamDefaultWriter(this)) { - return promiseRejectedWith(defaultWriterBrandCheckException('abort')); - } - if (this._ownerWritableStream === undefined) { - return promiseRejectedWith(defaultWriterLockException('abort')); - } - return WritableStreamDefaultWriterAbort(this, reason); - } - /** - * If the reader is active, behaves the same as {@link WritableStream.close | stream.close()}. - */ - close() { - if (!IsWritableStreamDefaultWriter(this)) { - return promiseRejectedWith(defaultWriterBrandCheckException('close')); - } - const stream = this._ownerWritableStream; - if (stream === undefined) { - return promiseRejectedWith(defaultWriterLockException('close')); - } - if (WritableStreamCloseQueuedOrInFlight(stream)) { - return promiseRejectedWith(new TypeError('Cannot close an already-closing stream')); - } - return WritableStreamDefaultWriterClose(this); - } - /** - * Releases the writer’s lock on the corresponding stream. After the lock is released, the writer is no longer active. - * If the associated stream is errored when the lock is released, the writer will appear errored in the same way from - * now on; otherwise, the writer will appear closed. - * - * Note that the lock can still be released even if some ongoing writes have not yet finished (i.e. even if the - * promises returned from previous calls to {@link WritableStreamDefaultWriter.write | write()} have not yet settled). - * It’s not necessary to hold the lock on the writer for the duration of the write; the lock instead simply prevents - * other producers from writing in an interleaved manner. - */ - releaseLock() { - if (!IsWritableStreamDefaultWriter(this)) { - throw defaultWriterBrandCheckException('releaseLock'); - } - const stream = this._ownerWritableStream; - if (stream === undefined) { - return; - } - WritableStreamDefaultWriterRelease(this); - } - write(chunk = undefined) { - if (!IsWritableStreamDefaultWriter(this)) { - return promiseRejectedWith(defaultWriterBrandCheckException('write')); - } - if (this._ownerWritableStream === undefined) { - return promiseRejectedWith(defaultWriterLockException('write to')); - } - return WritableStreamDefaultWriterWrite(this, chunk); - } -} -Object.defineProperties(WritableStreamDefaultWriter.prototype, { - abort: { enumerable: true }, - close: { enumerable: true }, - releaseLock: { enumerable: true }, - write: { enumerable: true }, - closed: { enumerable: true }, - desiredSize: { enumerable: true }, - ready: { enumerable: true } -}); -if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(WritableStreamDefaultWriter.prototype, SymbolPolyfill.toStringTag, { - value: 'WritableStreamDefaultWriter', - configurable: true - }); -} -// Abstract operations for the WritableStreamDefaultWriter. -function IsWritableStreamDefaultWriter(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_ownerWritableStream')) { - return false; - } - return true; -} -// A client of WritableStreamDefaultWriter may use these functions directly to bypass state check. -function WritableStreamDefaultWriterAbort(writer, reason) { - const stream = writer._ownerWritableStream; - return WritableStreamAbort(stream, reason); -} -function WritableStreamDefaultWriterClose(writer) { - const stream = writer._ownerWritableStream; - return WritableStreamClose(stream); -} -function WritableStreamDefaultWriterCloseWithErrorPropagation(writer) { - const stream = writer._ownerWritableStream; - const state = stream._state; - if (WritableStreamCloseQueuedOrInFlight(stream) || state === 'closed') { - return promiseResolvedWith(undefined); - } - if (state === 'errored') { - return promiseRejectedWith(stream._storedError); - } - return WritableStreamDefaultWriterClose(writer); -} -function WritableStreamDefaultWriterEnsureClosedPromiseRejected(writer, error) { - if (writer._closedPromiseState === 'pending') { - defaultWriterClosedPromiseReject(writer, error); - } - else { - defaultWriterClosedPromiseResetToRejected(writer, error); - } -} -function WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, error) { - if (writer._readyPromiseState === 'pending') { - defaultWriterReadyPromiseReject(writer, error); - } - else { - defaultWriterReadyPromiseResetToRejected(writer, error); - } -} -function WritableStreamDefaultWriterGetDesiredSize(writer) { - const stream = writer._ownerWritableStream; - const state = stream._state; - if (state === 'errored' || state === 'erroring') { - return null; - } - if (state === 'closed') { - return 0; - } - return WritableStreamDefaultControllerGetDesiredSize(stream._writableStreamController); -} -function WritableStreamDefaultWriterRelease(writer) { - const stream = writer._ownerWritableStream; - const releasedError = new TypeError(`Writer was released and can no longer be used to monitor the stream's closedness`); - WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, releasedError); - // The state transitions to "errored" before the sink abort() method runs, but the writer.closed promise is not - // rejected until afterwards. This means that simply testing state will not work. - WritableStreamDefaultWriterEnsureClosedPromiseRejected(writer, releasedError); - stream._writer = undefined; - writer._ownerWritableStream = undefined; -} -function WritableStreamDefaultWriterWrite(writer, chunk) { - const stream = writer._ownerWritableStream; - const controller = stream._writableStreamController; - const chunkSize = WritableStreamDefaultControllerGetChunkSize(controller, chunk); - if (stream !== writer._ownerWritableStream) { - return promiseRejectedWith(defaultWriterLockException('write to')); - } - const state = stream._state; - if (state === 'errored') { - return promiseRejectedWith(stream._storedError); - } - if (WritableStreamCloseQueuedOrInFlight(stream) || state === 'closed') { - return promiseRejectedWith(new TypeError('The stream is closing or closed and cannot be written to')); - } - if (state === 'erroring') { - return promiseRejectedWith(stream._storedError); - } - const promise = WritableStreamAddWriteRequest(stream); - WritableStreamDefaultControllerWrite(controller, chunk, chunkSize); - return promise; -} -const closeSentinel = {}; -/** - * Allows control of a {@link WritableStream | writable stream}'s state and internal queue. - * - * @public - */ -class WritableStreamDefaultController { - constructor() { - throw new TypeError('Illegal constructor'); - } - /** - * Closes the controlled writable stream, making all future interactions with it fail with the given error `e`. - * - * This method is rarely used, since usually it suffices to return a rejected promise from one of the underlying - * sink's methods. However, it can be useful for suddenly shutting down a stream in response to an event outside the - * normal lifecycle of interactions with the underlying sink. - */ - error(e = undefined) { - if (!IsWritableStreamDefaultController(this)) { - throw new TypeError('WritableStreamDefaultController.prototype.error can only be used on a WritableStreamDefaultController'); - } - const state = this._controlledWritableStream._state; - if (state !== 'writable') { - // The stream is closed, errored or will be soon. The sink can't do anything useful if it gets an error here, so - // just treat it as a no-op. - return; - } - WritableStreamDefaultControllerError(this, e); - } - /** @internal */ - [AbortSteps](reason) { - const result = this._abortAlgorithm(reason); - WritableStreamDefaultControllerClearAlgorithms(this); - return result; - } - /** @internal */ - [ErrorSteps]() { - ResetQueue(this); - } -} -Object.defineProperties(WritableStreamDefaultController.prototype, { - error: { enumerable: true } -}); -if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(WritableStreamDefaultController.prototype, SymbolPolyfill.toStringTag, { - value: 'WritableStreamDefaultController', - configurable: true - }); -} -// Abstract operations implementing interface required by the WritableStream. -function IsWritableStreamDefaultController(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_controlledWritableStream')) { - return false; - } - return true; -} -function SetUpWritableStreamDefaultController(stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark, sizeAlgorithm) { - controller._controlledWritableStream = stream; - stream._writableStreamController = controller; - // Need to set the slots so that the assert doesn't fire. In the spec the slots already exist implicitly. - controller._queue = undefined; - controller._queueTotalSize = undefined; - ResetQueue(controller); - controller._started = false; - controller._strategySizeAlgorithm = sizeAlgorithm; - controller._strategyHWM = highWaterMark; - controller._writeAlgorithm = writeAlgorithm; - controller._closeAlgorithm = closeAlgorithm; - controller._abortAlgorithm = abortAlgorithm; - const backpressure = WritableStreamDefaultControllerGetBackpressure(controller); - WritableStreamUpdateBackpressure(stream, backpressure); - const startResult = startAlgorithm(); - const startPromise = promiseResolvedWith(startResult); - uponPromise(startPromise, () => { - controller._started = true; - WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); - }, r => { - controller._started = true; - WritableStreamDealWithRejection(stream, r); - }); -} -function SetUpWritableStreamDefaultControllerFromUnderlyingSink(stream, underlyingSink, highWaterMark, sizeAlgorithm) { - const controller = Object.create(WritableStreamDefaultController.prototype); - let startAlgorithm = () => undefined; - let writeAlgorithm = () => promiseResolvedWith(undefined); - let closeAlgorithm = () => promiseResolvedWith(undefined); - let abortAlgorithm = () => promiseResolvedWith(undefined); - if (underlyingSink.start !== undefined) { - startAlgorithm = () => underlyingSink.start(controller); - } - if (underlyingSink.write !== undefined) { - writeAlgorithm = chunk => underlyingSink.write(chunk, controller); - } - if (underlyingSink.close !== undefined) { - closeAlgorithm = () => underlyingSink.close(); - } - if (underlyingSink.abort !== undefined) { - abortAlgorithm = reason => underlyingSink.abort(reason); - } - SetUpWritableStreamDefaultController(stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark, sizeAlgorithm); -} -// ClearAlgorithms may be called twice. Erroring the same stream in multiple ways will often result in redundant calls. -function WritableStreamDefaultControllerClearAlgorithms(controller) { - controller._writeAlgorithm = undefined; - controller._closeAlgorithm = undefined; - controller._abortAlgorithm = undefined; - controller._strategySizeAlgorithm = undefined; -} -function WritableStreamDefaultControllerClose(controller) { - EnqueueValueWithSize(controller, closeSentinel, 0); - WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); -} -function WritableStreamDefaultControllerGetChunkSize(controller, chunk) { - try { - return controller._strategySizeAlgorithm(chunk); - } - catch (chunkSizeE) { - WritableStreamDefaultControllerErrorIfNeeded(controller, chunkSizeE); - return 1; - } -} -function WritableStreamDefaultControllerGetDesiredSize(controller) { - return controller._strategyHWM - controller._queueTotalSize; -} -function WritableStreamDefaultControllerWrite(controller, chunk, chunkSize) { - try { - EnqueueValueWithSize(controller, chunk, chunkSize); - } - catch (enqueueE) { - WritableStreamDefaultControllerErrorIfNeeded(controller, enqueueE); - return; - } - const stream = controller._controlledWritableStream; - if (!WritableStreamCloseQueuedOrInFlight(stream) && stream._state === 'writable') { - const backpressure = WritableStreamDefaultControllerGetBackpressure(controller); - WritableStreamUpdateBackpressure(stream, backpressure); - } - WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); -} -// Abstract operations for the WritableStreamDefaultController. -function WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller) { - const stream = controller._controlledWritableStream; - if (!controller._started) { - return; - } - if (stream._inFlightWriteRequest !== undefined) { - return; - } - const state = stream._state; - if (state === 'erroring') { - WritableStreamFinishErroring(stream); - return; - } - if (controller._queue.length === 0) { - return; - } - const value = PeekQueueValue(controller); - if (value === closeSentinel) { - WritableStreamDefaultControllerProcessClose(controller); - } - else { - WritableStreamDefaultControllerProcessWrite(controller, value); - } -} -function WritableStreamDefaultControllerErrorIfNeeded(controller, error) { - if (controller._controlledWritableStream._state === 'writable') { - WritableStreamDefaultControllerError(controller, error); - } -} -function WritableStreamDefaultControllerProcessClose(controller) { - const stream = controller._controlledWritableStream; - WritableStreamMarkCloseRequestInFlight(stream); - DequeueValue(controller); - const sinkClosePromise = controller._closeAlgorithm(); - WritableStreamDefaultControllerClearAlgorithms(controller); - uponPromise(sinkClosePromise, () => { - WritableStreamFinishInFlightClose(stream); - }, reason => { - WritableStreamFinishInFlightCloseWithError(stream, reason); - }); -} -function WritableStreamDefaultControllerProcessWrite(controller, chunk) { - const stream = controller._controlledWritableStream; - WritableStreamMarkFirstWriteRequestInFlight(stream); - const sinkWritePromise = controller._writeAlgorithm(chunk); - uponPromise(sinkWritePromise, () => { - WritableStreamFinishInFlightWrite(stream); - const state = stream._state; - DequeueValue(controller); - if (!WritableStreamCloseQueuedOrInFlight(stream) && state === 'writable') { - const backpressure = WritableStreamDefaultControllerGetBackpressure(controller); - WritableStreamUpdateBackpressure(stream, backpressure); - } - WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); - }, reason => { - if (stream._state === 'writable') { - WritableStreamDefaultControllerClearAlgorithms(controller); - } - WritableStreamFinishInFlightWriteWithError(stream, reason); - }); -} -function WritableStreamDefaultControllerGetBackpressure(controller) { - const desiredSize = WritableStreamDefaultControllerGetDesiredSize(controller); - return desiredSize <= 0; -} -// A client of WritableStreamDefaultController may use these functions directly to bypass state check. -function WritableStreamDefaultControllerError(controller, error) { - const stream = controller._controlledWritableStream; - WritableStreamDefaultControllerClearAlgorithms(controller); - WritableStreamStartErroring(stream, error); -} -// Helper functions for the WritableStream. -function streamBrandCheckException$2(name) { - return new TypeError(`WritableStream.prototype.${name} can only be used on a WritableStream`); -} -// Helper functions for the WritableStreamDefaultWriter. -function defaultWriterBrandCheckException(name) { - return new TypeError(`WritableStreamDefaultWriter.prototype.${name} can only be used on a WritableStreamDefaultWriter`); -} -function defaultWriterLockException(name) { - return new TypeError('Cannot ' + name + ' a stream using a released writer'); -} -function defaultWriterClosedPromiseInitialize(writer) { - writer._closedPromise = newPromise((resolve, reject) => { - writer._closedPromise_resolve = resolve; - writer._closedPromise_reject = reject; - writer._closedPromiseState = 'pending'; - }); -} -function defaultWriterClosedPromiseInitializeAsRejected(writer, reason) { - defaultWriterClosedPromiseInitialize(writer); - defaultWriterClosedPromiseReject(writer, reason); -} -function defaultWriterClosedPromiseInitializeAsResolved(writer) { - defaultWriterClosedPromiseInitialize(writer); - defaultWriterClosedPromiseResolve(writer); -} -function defaultWriterClosedPromiseReject(writer, reason) { - if (writer._closedPromise_reject === undefined) { - return; - } - setPromiseIsHandledToTrue(writer._closedPromise); - writer._closedPromise_reject(reason); - writer._closedPromise_resolve = undefined; - writer._closedPromise_reject = undefined; - writer._closedPromiseState = 'rejected'; -} -function defaultWriterClosedPromiseResetToRejected(writer, reason) { - defaultWriterClosedPromiseInitializeAsRejected(writer, reason); -} -function defaultWriterClosedPromiseResolve(writer) { - if (writer._closedPromise_resolve === undefined) { - return; - } - writer._closedPromise_resolve(undefined); - writer._closedPromise_resolve = undefined; - writer._closedPromise_reject = undefined; - writer._closedPromiseState = 'resolved'; -} -function defaultWriterReadyPromiseInitialize(writer) { - writer._readyPromise = newPromise((resolve, reject) => { - writer._readyPromise_resolve = resolve; - writer._readyPromise_reject = reject; - }); - writer._readyPromiseState = 'pending'; -} -function defaultWriterReadyPromiseInitializeAsRejected(writer, reason) { - defaultWriterReadyPromiseInitialize(writer); - defaultWriterReadyPromiseReject(writer, reason); -} -function defaultWriterReadyPromiseInitializeAsResolved(writer) { - defaultWriterReadyPromiseInitialize(writer); - defaultWriterReadyPromiseResolve(writer); -} -function defaultWriterReadyPromiseReject(writer, reason) { - if (writer._readyPromise_reject === undefined) { - return; - } - setPromiseIsHandledToTrue(writer._readyPromise); - writer._readyPromise_reject(reason); - writer._readyPromise_resolve = undefined; - writer._readyPromise_reject = undefined; - writer._readyPromiseState = 'rejected'; -} -function defaultWriterReadyPromiseReset(writer) { - defaultWriterReadyPromiseInitialize(writer); -} -function defaultWriterReadyPromiseResetToRejected(writer, reason) { - defaultWriterReadyPromiseInitializeAsRejected(writer, reason); -} -function defaultWriterReadyPromiseResolve(writer) { - if (writer._readyPromise_resolve === undefined) { - return; - } - writer._readyPromise_resolve(undefined); - writer._readyPromise_resolve = undefined; - writer._readyPromise_reject = undefined; - writer._readyPromiseState = 'fulfilled'; -} - -function isAbortSignal(value) { - if (typeof value !== 'object' || value === null) { - return false; - } - try { - return typeof value.aborted === 'boolean'; - } - catch (_a) { - // AbortSignal.prototype.aborted throws if its brand check fails - return false; - } -} - -/// -const NativeDOMException = typeof DOMException !== 'undefined' ? DOMException : undefined; - -/// -function isDOMExceptionConstructor(ctor) { - if (!(typeof ctor === 'function' || typeof ctor === 'object')) { - return false; - } - try { - new ctor(); - return true; - } - catch (_a) { - return false; - } -} -function createDOMExceptionPolyfill() { - // eslint-disable-next-line no-shadow - const ctor = function DOMException(message, name) { - this.message = message || ''; - this.name = name || 'Error'; - if (Error.captureStackTrace) { - Error.captureStackTrace(this, this.constructor); - } - }; - ctor.prototype = Object.create(Error.prototype); - Object.defineProperty(ctor.prototype, 'constructor', { value: ctor, writable: true, configurable: true }); - return ctor; -} -// eslint-disable-next-line no-redeclare -const DOMException$1 = isDOMExceptionConstructor(NativeDOMException) ? NativeDOMException : createDOMExceptionPolyfill(); - -function ReadableStreamPipeTo(source, dest, preventClose, preventAbort, preventCancel, signal) { - const reader = AcquireReadableStreamDefaultReader(source); - const writer = AcquireWritableStreamDefaultWriter(dest); - source._disturbed = true; - let shuttingDown = false; - // This is used to keep track of the spec's requirement that we wait for ongoing writes during shutdown. - let currentWrite = promiseResolvedWith(undefined); - return newPromise((resolve, reject) => { - let abortAlgorithm; - if (signal !== undefined) { - abortAlgorithm = () => { - const error = new DOMException$1('Aborted', 'AbortError'); - const actions = []; - if (!preventAbort) { - actions.push(() => { - if (dest._state === 'writable') { - return WritableStreamAbort(dest, error); - } - return promiseResolvedWith(undefined); - }); - } - if (!preventCancel) { - actions.push(() => { - if (source._state === 'readable') { - return ReadableStreamCancel(source, error); - } - return promiseResolvedWith(undefined); - }); - } - shutdownWithAction(() => Promise.all(actions.map(action => action())), true, error); - }; - if (signal.aborted) { - abortAlgorithm(); - return; - } - signal.addEventListener('abort', abortAlgorithm); - } - // Using reader and writer, read all chunks from this and write them to dest - // - Backpressure must be enforced - // - Shutdown must stop all activity - function pipeLoop() { - return newPromise((resolveLoop, rejectLoop) => { - function next(done) { - if (done) { - resolveLoop(); - } - else { - // Use `PerformPromiseThen` instead of `uponPromise` to avoid - // adding unnecessary `.catch(rethrowAssertionErrorRejection)` handlers - PerformPromiseThen(pipeStep(), next, rejectLoop); - } - } - next(false); - }); - } - function pipeStep() { - if (shuttingDown) { - return promiseResolvedWith(true); - } - return PerformPromiseThen(writer._readyPromise, () => { - return newPromise((resolveRead, rejectRead) => { - ReadableStreamDefaultReaderRead(reader, { - _chunkSteps: chunk => { - currentWrite = PerformPromiseThen(WritableStreamDefaultWriterWrite(writer, chunk), undefined, noop); - resolveRead(false); - }, - _closeSteps: () => resolveRead(true), - _errorSteps: rejectRead - }); - }); - }); - } - // Errors must be propagated forward - isOrBecomesErrored(source, reader._closedPromise, storedError => { - if (!preventAbort) { - shutdownWithAction(() => WritableStreamAbort(dest, storedError), true, storedError); - } - else { - shutdown(true, storedError); - } - }); - // Errors must be propagated backward - isOrBecomesErrored(dest, writer._closedPromise, storedError => { - if (!preventCancel) { - shutdownWithAction(() => ReadableStreamCancel(source, storedError), true, storedError); - } - else { - shutdown(true, storedError); - } - }); - // Closing must be propagated forward - isOrBecomesClosed(source, reader._closedPromise, () => { - if (!preventClose) { - shutdownWithAction(() => WritableStreamDefaultWriterCloseWithErrorPropagation(writer)); - } - else { - shutdown(); - } - }); - // Closing must be propagated backward - if (WritableStreamCloseQueuedOrInFlight(dest) || dest._state === 'closed') { - const destClosed = new TypeError('the destination writable stream closed before all data could be piped to it'); - if (!preventCancel) { - shutdownWithAction(() => ReadableStreamCancel(source, destClosed), true, destClosed); - } - else { - shutdown(true, destClosed); - } - } - setPromiseIsHandledToTrue(pipeLoop()); - function waitForWritesToFinish() { - // Another write may have started while we were waiting on this currentWrite, so we have to be sure to wait - // for that too. - const oldCurrentWrite = currentWrite; - return PerformPromiseThen(currentWrite, () => oldCurrentWrite !== currentWrite ? waitForWritesToFinish() : undefined); - } - function isOrBecomesErrored(stream, promise, action) { - if (stream._state === 'errored') { - action(stream._storedError); - } - else { - uponRejection(promise, action); - } - } - function isOrBecomesClosed(stream, promise, action) { - if (stream._state === 'closed') { - action(); - } - else { - uponFulfillment(promise, action); - } - } - function shutdownWithAction(action, originalIsError, originalError) { - if (shuttingDown) { - return; - } - shuttingDown = true; - if (dest._state === 'writable' && !WritableStreamCloseQueuedOrInFlight(dest)) { - uponFulfillment(waitForWritesToFinish(), doTheRest); - } - else { - doTheRest(); - } - function doTheRest() { - uponPromise(action(), () => finalize(originalIsError, originalError), newError => finalize(true, newError)); - } - } - function shutdown(isError, error) { - if (shuttingDown) { - return; - } - shuttingDown = true; - if (dest._state === 'writable' && !WritableStreamCloseQueuedOrInFlight(dest)) { - uponFulfillment(waitForWritesToFinish(), () => finalize(isError, error)); - } - else { - finalize(isError, error); - } - } - function finalize(isError, error) { - WritableStreamDefaultWriterRelease(writer); - ReadableStreamReaderGenericRelease(reader); - if (signal !== undefined) { - signal.removeEventListener('abort', abortAlgorithm); - } - if (isError) { - reject(error); - } - else { - resolve(undefined); - } - } - }); -} - -/** - * Allows control of a {@link ReadableStream | readable stream}'s state and internal queue. - * - * @public - */ -class ReadableStreamDefaultController { - constructor() { - throw new TypeError('Illegal constructor'); - } - /** - * Returns the desired size to fill the controlled stream's internal queue. It can be negative, if the queue is - * over-full. An underlying source ought to use this information to determine when and how to apply backpressure. - */ - get desiredSize() { - if (!IsReadableStreamDefaultController(this)) { - throw defaultControllerBrandCheckException$1('desiredSize'); - } - return ReadableStreamDefaultControllerGetDesiredSize(this); - } - /** - * Closes the controlled readable stream. Consumers will still be able to read any previously-enqueued chunks from - * the stream, but once those are read, the stream will become closed. - */ - close() { - if (!IsReadableStreamDefaultController(this)) { - throw defaultControllerBrandCheckException$1('close'); - } - if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(this)) { - throw new TypeError('The stream is not in a state that permits close'); - } - ReadableStreamDefaultControllerClose(this); - } - enqueue(chunk = undefined) { - if (!IsReadableStreamDefaultController(this)) { - throw defaultControllerBrandCheckException$1('enqueue'); - } - if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(this)) { - throw new TypeError('The stream is not in a state that permits enqueue'); - } - return ReadableStreamDefaultControllerEnqueue(this, chunk); - } - /** - * Errors the controlled readable stream, making all future interactions with it fail with the given error `e`. - */ - error(e = undefined) { - if (!IsReadableStreamDefaultController(this)) { - throw defaultControllerBrandCheckException$1('error'); - } - ReadableStreamDefaultControllerError(this, e); - } - /** @internal */ - [CancelSteps](reason) { - ResetQueue(this); - const result = this._cancelAlgorithm(reason); - ReadableStreamDefaultControllerClearAlgorithms(this); - return result; - } - /** @internal */ - [PullSteps](readRequest) { - const stream = this._controlledReadableStream; - if (this._queue.length > 0) { - const chunk = DequeueValue(this); - if (this._closeRequested && this._queue.length === 0) { - ReadableStreamDefaultControllerClearAlgorithms(this); - ReadableStreamClose(stream); - } - else { - ReadableStreamDefaultControllerCallPullIfNeeded(this); - } - readRequest._chunkSteps(chunk); - } - else { - ReadableStreamAddReadRequest(stream, readRequest); - ReadableStreamDefaultControllerCallPullIfNeeded(this); - } - } -} -Object.defineProperties(ReadableStreamDefaultController.prototype, { - close: { enumerable: true }, - enqueue: { enumerable: true }, - error: { enumerable: true }, - desiredSize: { enumerable: true } -}); -if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(ReadableStreamDefaultController.prototype, SymbolPolyfill.toStringTag, { - value: 'ReadableStreamDefaultController', - configurable: true - }); -} -// Abstract operations for the ReadableStreamDefaultController. -function IsReadableStreamDefaultController(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_controlledReadableStream')) { - return false; - } - return true; -} -function ReadableStreamDefaultControllerCallPullIfNeeded(controller) { - const shouldPull = ReadableStreamDefaultControllerShouldCallPull(controller); - if (!shouldPull) { - return; - } - if (controller._pulling) { - controller._pullAgain = true; - return; - } - controller._pulling = true; - const pullPromise = controller._pullAlgorithm(); - uponPromise(pullPromise, () => { - controller._pulling = false; - if (controller._pullAgain) { - controller._pullAgain = false; - ReadableStreamDefaultControllerCallPullIfNeeded(controller); - } - }, e => { - ReadableStreamDefaultControllerError(controller, e); - }); -} -function ReadableStreamDefaultControllerShouldCallPull(controller) { - const stream = controller._controlledReadableStream; - if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(controller)) { - return false; - } - if (!controller._started) { - return false; - } - if (IsReadableStreamLocked(stream) && ReadableStreamGetNumReadRequests(stream) > 0) { - return true; - } - const desiredSize = ReadableStreamDefaultControllerGetDesiredSize(controller); - if (desiredSize > 0) { - return true; - } - return false; -} -function ReadableStreamDefaultControllerClearAlgorithms(controller) { - controller._pullAlgorithm = undefined; - controller._cancelAlgorithm = undefined; - controller._strategySizeAlgorithm = undefined; -} -// A client of ReadableStreamDefaultController may use these functions directly to bypass state check. -function ReadableStreamDefaultControllerClose(controller) { - if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(controller)) { - return; - } - const stream = controller._controlledReadableStream; - controller._closeRequested = true; - if (controller._queue.length === 0) { - ReadableStreamDefaultControllerClearAlgorithms(controller); - ReadableStreamClose(stream); - } -} -function ReadableStreamDefaultControllerEnqueue(controller, chunk) { - if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(controller)) { - return; - } - const stream = controller._controlledReadableStream; - if (IsReadableStreamLocked(stream) && ReadableStreamGetNumReadRequests(stream) > 0) { - ReadableStreamFulfillReadRequest(stream, chunk, false); - } - else { - let chunkSize; - try { - chunkSize = controller._strategySizeAlgorithm(chunk); - } - catch (chunkSizeE) { - ReadableStreamDefaultControllerError(controller, chunkSizeE); - throw chunkSizeE; - } - try { - EnqueueValueWithSize(controller, chunk, chunkSize); - } - catch (enqueueE) { - ReadableStreamDefaultControllerError(controller, enqueueE); - throw enqueueE; - } - } - ReadableStreamDefaultControllerCallPullIfNeeded(controller); -} -function ReadableStreamDefaultControllerError(controller, e) { - const stream = controller._controlledReadableStream; - if (stream._state !== 'readable') { - return; - } - ResetQueue(controller); - ReadableStreamDefaultControllerClearAlgorithms(controller); - ReadableStreamError(stream, e); -} -function ReadableStreamDefaultControllerGetDesiredSize(controller) { - const state = controller._controlledReadableStream._state; - if (state === 'errored') { - return null; - } - if (state === 'closed') { - return 0; - } - return controller._strategyHWM - controller._queueTotalSize; -} -// This is used in the implementation of TransformStream. -function ReadableStreamDefaultControllerHasBackpressure(controller) { - if (ReadableStreamDefaultControllerShouldCallPull(controller)) { - return false; - } - return true; -} -function ReadableStreamDefaultControllerCanCloseOrEnqueue(controller) { - const state = controller._controlledReadableStream._state; - if (!controller._closeRequested && state === 'readable') { - return true; - } - return false; -} -function SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm) { - controller._controlledReadableStream = stream; - controller._queue = undefined; - controller._queueTotalSize = undefined; - ResetQueue(controller); - controller._started = false; - controller._closeRequested = false; - controller._pullAgain = false; - controller._pulling = false; - controller._strategySizeAlgorithm = sizeAlgorithm; - controller._strategyHWM = highWaterMark; - controller._pullAlgorithm = pullAlgorithm; - controller._cancelAlgorithm = cancelAlgorithm; - stream._readableStreamController = controller; - const startResult = startAlgorithm(); - uponPromise(promiseResolvedWith(startResult), () => { - controller._started = true; - ReadableStreamDefaultControllerCallPullIfNeeded(controller); - }, r => { - ReadableStreamDefaultControllerError(controller, r); - }); -} -function SetUpReadableStreamDefaultControllerFromUnderlyingSource(stream, underlyingSource, highWaterMark, sizeAlgorithm) { - const controller = Object.create(ReadableStreamDefaultController.prototype); - let startAlgorithm = () => undefined; - let pullAlgorithm = () => promiseResolvedWith(undefined); - let cancelAlgorithm = () => promiseResolvedWith(undefined); - if (underlyingSource.start !== undefined) { - startAlgorithm = () => underlyingSource.start(controller); - } - if (underlyingSource.pull !== undefined) { - pullAlgorithm = () => underlyingSource.pull(controller); - } - if (underlyingSource.cancel !== undefined) { - cancelAlgorithm = reason => underlyingSource.cancel(reason); - } - SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm); -} -// Helper functions for the ReadableStreamDefaultController. -function defaultControllerBrandCheckException$1(name) { - return new TypeError(`ReadableStreamDefaultController.prototype.${name} can only be used on a ReadableStreamDefaultController`); -} - -function ReadableStreamTee(stream, cloneForBranch2) { - const reader = AcquireReadableStreamDefaultReader(stream); - let reading = false; - let canceled1 = false; - let canceled2 = false; - let reason1; - let reason2; - let branch1; - let branch2; - let resolveCancelPromise; - const cancelPromise = newPromise(resolve => { - resolveCancelPromise = resolve; - }); - function pullAlgorithm() { - if (reading) { - return promiseResolvedWith(undefined); - } - reading = true; - const readRequest = { - _chunkSteps: value => { - // This needs to be delayed a microtask because it takes at least a microtask to detect errors (using - // reader._closedPromise below), and we want errors in stream to error both branches immediately. We cannot let - // successful synchronously-available reads get ahead of asynchronously-available errors. - queueMicrotask(() => { - reading = false; - const value1 = value; - const value2 = value; - // There is no way to access the cloning code right now in the reference implementation. - // If we add one then we'll need an implementation for serializable objects. - // if (!canceled2 && cloneForBranch2) { - // value2 = StructuredDeserialize(StructuredSerialize(value2)); - // } - if (!canceled1) { - ReadableStreamDefaultControllerEnqueue(branch1._readableStreamController, value1); - } - if (!canceled2) { - ReadableStreamDefaultControllerEnqueue(branch2._readableStreamController, value2); - } - }); - }, - _closeSteps: () => { - reading = false; - if (!canceled1) { - ReadableStreamDefaultControllerClose(branch1._readableStreamController); - } - if (!canceled2) { - ReadableStreamDefaultControllerClose(branch2._readableStreamController); - } - if (!canceled1 || !canceled2) { - resolveCancelPromise(undefined); - } - }, - _errorSteps: () => { - reading = false; - } - }; - ReadableStreamDefaultReaderRead(reader, readRequest); - return promiseResolvedWith(undefined); - } - function cancel1Algorithm(reason) { - canceled1 = true; - reason1 = reason; - if (canceled2) { - const compositeReason = CreateArrayFromList([reason1, reason2]); - const cancelResult = ReadableStreamCancel(stream, compositeReason); - resolveCancelPromise(cancelResult); - } - return cancelPromise; - } - function cancel2Algorithm(reason) { - canceled2 = true; - reason2 = reason; - if (canceled1) { - const compositeReason = CreateArrayFromList([reason1, reason2]); - const cancelResult = ReadableStreamCancel(stream, compositeReason); - resolveCancelPromise(cancelResult); - } - return cancelPromise; - } - function startAlgorithm() { - // do nothing - } - branch1 = CreateReadableStream(startAlgorithm, pullAlgorithm, cancel1Algorithm); - branch2 = CreateReadableStream(startAlgorithm, pullAlgorithm, cancel2Algorithm); - uponRejection(reader._closedPromise, (r) => { - ReadableStreamDefaultControllerError(branch1._readableStreamController, r); - ReadableStreamDefaultControllerError(branch2._readableStreamController, r); - if (!canceled1 || !canceled2) { - resolveCancelPromise(undefined); - } - }); - return [branch1, branch2]; -} - -function convertUnderlyingDefaultOrByteSource(source, context) { - assertDictionary(source, context); - const original = source; - const autoAllocateChunkSize = original === null || original === void 0 ? void 0 : original.autoAllocateChunkSize; - const cancel = original === null || original === void 0 ? void 0 : original.cancel; - const pull = original === null || original === void 0 ? void 0 : original.pull; - const start = original === null || original === void 0 ? void 0 : original.start; - const type = original === null || original === void 0 ? void 0 : original.type; - return { - autoAllocateChunkSize: autoAllocateChunkSize === undefined ? - undefined : - convertUnsignedLongLongWithEnforceRange(autoAllocateChunkSize, `${context} has member 'autoAllocateChunkSize' that`), - cancel: cancel === undefined ? - undefined : - convertUnderlyingSourceCancelCallback(cancel, original, `${context} has member 'cancel' that`), - pull: pull === undefined ? - undefined : - convertUnderlyingSourcePullCallback(pull, original, `${context} has member 'pull' that`), - start: start === undefined ? - undefined : - convertUnderlyingSourceStartCallback(start, original, `${context} has member 'start' that`), - type: type === undefined ? undefined : convertReadableStreamType(type, `${context} has member 'type' that`) - }; -} -function convertUnderlyingSourceCancelCallback(fn, original, context) { - assertFunction(fn, context); - return (reason) => promiseCall(fn, original, [reason]); -} -function convertUnderlyingSourcePullCallback(fn, original, context) { - assertFunction(fn, context); - return (controller) => promiseCall(fn, original, [controller]); -} -function convertUnderlyingSourceStartCallback(fn, original, context) { - assertFunction(fn, context); - return (controller) => reflectCall(fn, original, [controller]); -} -function convertReadableStreamType(type, context) { - type = `${type}`; - if (type !== 'bytes') { - throw new TypeError(`${context} '${type}' is not a valid enumeration value for ReadableStreamType`); - } - return type; -} - -function convertReaderOptions(options, context) { - assertDictionary(options, context); - const mode = options === null || options === void 0 ? void 0 : options.mode; - return { - mode: mode === undefined ? undefined : convertReadableStreamReaderMode(mode, `${context} has member 'mode' that`) - }; -} -function convertReadableStreamReaderMode(mode, context) { - mode = `${mode}`; - if (mode !== 'byob') { - throw new TypeError(`${context} '${mode}' is not a valid enumeration value for ReadableStreamReaderMode`); - } - return mode; -} - -function convertIteratorOptions(options, context) { - assertDictionary(options, context); - const preventCancel = options === null || options === void 0 ? void 0 : options.preventCancel; - return { preventCancel: Boolean(preventCancel) }; -} - -function convertPipeOptions(options, context) { - assertDictionary(options, context); - const preventAbort = options === null || options === void 0 ? void 0 : options.preventAbort; - const preventCancel = options === null || options === void 0 ? void 0 : options.preventCancel; - const preventClose = options === null || options === void 0 ? void 0 : options.preventClose; - const signal = options === null || options === void 0 ? void 0 : options.signal; - if (signal !== undefined) { - assertAbortSignal(signal, `${context} has member 'signal' that`); - } - return { - preventAbort: Boolean(preventAbort), - preventCancel: Boolean(preventCancel), - preventClose: Boolean(preventClose), - signal - }; -} -function assertAbortSignal(signal, context) { - if (!isAbortSignal(signal)) { - throw new TypeError(`${context} is not an AbortSignal.`); - } -} - -function convertReadableWritablePair(pair, context) { - assertDictionary(pair, context); - const readable = pair === null || pair === void 0 ? void 0 : pair.readable; - assertRequiredField(readable, 'readable', 'ReadableWritablePair'); - assertReadableStream(readable, `${context} has member 'readable' that`); - const writable = pair === null || pair === void 0 ? void 0 : pair.writable; - assertRequiredField(writable, 'writable', 'ReadableWritablePair'); - assertWritableStream(writable, `${context} has member 'writable' that`); - return { readable, writable }; -} - -/** - * A readable stream represents a source of data, from which you can read. - * - * @public - */ -class ReadableStream$1 { - constructor(rawUnderlyingSource = {}, rawStrategy = {}) { - if (rawUnderlyingSource === undefined) { - rawUnderlyingSource = null; - } - else { - assertObject(rawUnderlyingSource, 'First parameter'); - } - const strategy = convertQueuingStrategy(rawStrategy, 'Second parameter'); - const underlyingSource = convertUnderlyingDefaultOrByteSource(rawUnderlyingSource, 'First parameter'); - InitializeReadableStream(this); - if (underlyingSource.type === 'bytes') { - if (strategy.size !== undefined) { - throw new RangeError('The strategy for a byte stream cannot have a size function'); - } - const highWaterMark = ExtractHighWaterMark(strategy, 0); - SetUpReadableByteStreamControllerFromUnderlyingSource(this, underlyingSource, highWaterMark); - } - else { - const sizeAlgorithm = ExtractSizeAlgorithm(strategy); - const highWaterMark = ExtractHighWaterMark(strategy, 1); - SetUpReadableStreamDefaultControllerFromUnderlyingSource(this, underlyingSource, highWaterMark, sizeAlgorithm); - } - } - /** - * Whether or not the readable stream is locked to a {@link ReadableStreamDefaultReader | reader}. - */ - get locked() { - if (!IsReadableStream(this)) { - throw streamBrandCheckException$1('locked'); - } - return IsReadableStreamLocked(this); - } - /** - * Cancels the stream, signaling a loss of interest in the stream by a consumer. - * - * The supplied `reason` argument will be given to the underlying source's {@link UnderlyingSource.cancel | cancel()} - * method, which might or might not use it. - */ - cancel(reason = undefined) { - if (!IsReadableStream(this)) { - return promiseRejectedWith(streamBrandCheckException$1('cancel')); - } - if (IsReadableStreamLocked(this)) { - return promiseRejectedWith(new TypeError('Cannot cancel a stream that already has a reader')); - } - return ReadableStreamCancel(this, reason); - } - getReader(rawOptions = undefined) { - if (!IsReadableStream(this)) { - throw streamBrandCheckException$1('getReader'); - } - const options = convertReaderOptions(rawOptions, 'First parameter'); - if (options.mode === undefined) { - return AcquireReadableStreamDefaultReader(this); - } - return AcquireReadableStreamBYOBReader(this); - } - pipeThrough(rawTransform, rawOptions = {}) { - if (!IsReadableStream(this)) { - throw streamBrandCheckException$1('pipeThrough'); - } - assertRequiredArgument(rawTransform, 1, 'pipeThrough'); - const transform = convertReadableWritablePair(rawTransform, 'First parameter'); - const options = convertPipeOptions(rawOptions, 'Second parameter'); - if (IsReadableStreamLocked(this)) { - throw new TypeError('ReadableStream.prototype.pipeThrough cannot be used on a locked ReadableStream'); - } - if (IsWritableStreamLocked(transform.writable)) { - throw new TypeError('ReadableStream.prototype.pipeThrough cannot be used on a locked WritableStream'); - } - const promise = ReadableStreamPipeTo(this, transform.writable, options.preventClose, options.preventAbort, options.preventCancel, options.signal); - setPromiseIsHandledToTrue(promise); - return transform.readable; - } - pipeTo(destination, rawOptions = {}) { - if (!IsReadableStream(this)) { - return promiseRejectedWith(streamBrandCheckException$1('pipeTo')); - } - if (destination === undefined) { - return promiseRejectedWith(`Parameter 1 is required in 'pipeTo'.`); - } - if (!IsWritableStream(destination)) { - return promiseRejectedWith(new TypeError(`ReadableStream.prototype.pipeTo's first argument must be a WritableStream`)); - } - let options; - try { - options = convertPipeOptions(rawOptions, 'Second parameter'); - } - catch (e) { - return promiseRejectedWith(e); - } - if (IsReadableStreamLocked(this)) { - return promiseRejectedWith(new TypeError('ReadableStream.prototype.pipeTo cannot be used on a locked ReadableStream')); - } - if (IsWritableStreamLocked(destination)) { - return promiseRejectedWith(new TypeError('ReadableStream.prototype.pipeTo cannot be used on a locked WritableStream')); - } - return ReadableStreamPipeTo(this, destination, options.preventClose, options.preventAbort, options.preventCancel, options.signal); - } - /** - * Tees this readable stream, returning a two-element array containing the two resulting branches as - * new {@link ReadableStream} instances. - * - * Teeing a stream will lock it, preventing any other consumer from acquiring a reader. - * To cancel the stream, cancel both of the resulting branches; a composite cancellation reason will then be - * propagated to the stream's underlying source. - * - * Note that the chunks seen in each branch will be the same object. If the chunks are not immutable, - * this could allow interference between the two branches. - */ - tee() { - if (!IsReadableStream(this)) { - throw streamBrandCheckException$1('tee'); - } - const branches = ReadableStreamTee(this); - return CreateArrayFromList(branches); - } - values(rawOptions = undefined) { - if (!IsReadableStream(this)) { - throw streamBrandCheckException$1('values'); - } - const options = convertIteratorOptions(rawOptions, 'First parameter'); - return AcquireReadableStreamAsyncIterator(this, options.preventCancel); - } -} -Object.defineProperties(ReadableStream$1.prototype, { - cancel: { enumerable: true }, - getReader: { enumerable: true }, - pipeThrough: { enumerable: true }, - pipeTo: { enumerable: true }, - tee: { enumerable: true }, - values: { enumerable: true }, - locked: { enumerable: true } -}); -if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(ReadableStream$1.prototype, SymbolPolyfill.toStringTag, { - value: 'ReadableStream', - configurable: true - }); -} -if (typeof SymbolPolyfill.asyncIterator === 'symbol') { - Object.defineProperty(ReadableStream$1.prototype, SymbolPolyfill.asyncIterator, { - value: ReadableStream$1.prototype.values, - writable: true, - configurable: true - }); -} -// Abstract operations for the ReadableStream. -// Throws if and only if startAlgorithm throws. -function CreateReadableStream(startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark = 1, sizeAlgorithm = () => 1) { - const stream = Object.create(ReadableStream$1.prototype); - InitializeReadableStream(stream); - const controller = Object.create(ReadableStreamDefaultController.prototype); - SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm); - return stream; -} -function InitializeReadableStream(stream) { - stream._state = 'readable'; - stream._reader = undefined; - stream._storedError = undefined; - stream._disturbed = false; -} -function IsReadableStream(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_readableStreamController')) { - return false; - } - return true; -} -function IsReadableStreamLocked(stream) { - if (stream._reader === undefined) { - return false; - } - return true; -} -// ReadableStream API exposed for controllers. -function ReadableStreamCancel(stream, reason) { - stream._disturbed = true; - if (stream._state === 'closed') { - return promiseResolvedWith(undefined); - } - if (stream._state === 'errored') { - return promiseRejectedWith(stream._storedError); - } - ReadableStreamClose(stream); - const sourceCancelPromise = stream._readableStreamController[CancelSteps](reason); - return transformPromiseWith(sourceCancelPromise, noop); -} -function ReadableStreamClose(stream) { - stream._state = 'closed'; - const reader = stream._reader; - if (reader === undefined) { - return; - } - defaultReaderClosedPromiseResolve(reader); - if (IsReadableStreamDefaultReader(reader)) { - reader._readRequests.forEach(readRequest => { - readRequest._closeSteps(); - }); - reader._readRequests = new SimpleQueue(); - } -} -function ReadableStreamError(stream, e) { - stream._state = 'errored'; - stream._storedError = e; - const reader = stream._reader; - if (reader === undefined) { - return; - } - defaultReaderClosedPromiseReject(reader, e); - if (IsReadableStreamDefaultReader(reader)) { - reader._readRequests.forEach(readRequest => { - readRequest._errorSteps(e); - }); - reader._readRequests = new SimpleQueue(); - } - else { - reader._readIntoRequests.forEach(readIntoRequest => { - readIntoRequest._errorSteps(e); - }); - reader._readIntoRequests = new SimpleQueue(); - } -} -// Helper functions for the ReadableStream. -function streamBrandCheckException$1(name) { - return new TypeError(`ReadableStream.prototype.${name} can only be used on a ReadableStream`); -} - -function convertQueuingStrategyInit(init, context) { - assertDictionary(init, context); - const highWaterMark = init === null || init === void 0 ? void 0 : init.highWaterMark; - assertRequiredField(highWaterMark, 'highWaterMark', 'QueuingStrategyInit'); - return { - highWaterMark: convertUnrestrictedDouble(highWaterMark) - }; -} - -const byteLengthSizeFunction = function size(chunk) { - return chunk.byteLength; -}; -/** - * A queuing strategy that counts the number of bytes in each chunk. - * - * @public - */ -class ByteLengthQueuingStrategy { - constructor(options) { - assertRequiredArgument(options, 1, 'ByteLengthQueuingStrategy'); - options = convertQueuingStrategyInit(options, 'First parameter'); - this._byteLengthQueuingStrategyHighWaterMark = options.highWaterMark; - } - /** - * Returns the high water mark provided to the constructor. - */ - get highWaterMark() { - if (!IsByteLengthQueuingStrategy(this)) { - throw byteLengthBrandCheckException('highWaterMark'); - } - return this._byteLengthQueuingStrategyHighWaterMark; - } - /** - * Measures the size of `chunk` by returning the value of its `byteLength` property. - */ - get size() { - if (!IsByteLengthQueuingStrategy(this)) { - throw byteLengthBrandCheckException('size'); - } - return byteLengthSizeFunction; - } -} -Object.defineProperties(ByteLengthQueuingStrategy.prototype, { - highWaterMark: { enumerable: true }, - size: { enumerable: true } -}); -if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(ByteLengthQueuingStrategy.prototype, SymbolPolyfill.toStringTag, { - value: 'ByteLengthQueuingStrategy', - configurable: true - }); -} -// Helper functions for the ByteLengthQueuingStrategy. -function byteLengthBrandCheckException(name) { - return new TypeError(`ByteLengthQueuingStrategy.prototype.${name} can only be used on a ByteLengthQueuingStrategy`); -} -function IsByteLengthQueuingStrategy(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_byteLengthQueuingStrategyHighWaterMark')) { - return false; - } - return true; -} - -const countSizeFunction = function size() { - return 1; -}; -/** - * A queuing strategy that counts the number of chunks. - * - * @public - */ -class CountQueuingStrategy { - constructor(options) { - assertRequiredArgument(options, 1, 'CountQueuingStrategy'); - options = convertQueuingStrategyInit(options, 'First parameter'); - this._countQueuingStrategyHighWaterMark = options.highWaterMark; - } - /** - * Returns the high water mark provided to the constructor. - */ - get highWaterMark() { - if (!IsCountQueuingStrategy(this)) { - throw countBrandCheckException('highWaterMark'); - } - return this._countQueuingStrategyHighWaterMark; - } - /** - * Measures the size of `chunk` by always returning 1. - * This ensures that the total queue size is a count of the number of chunks in the queue. - */ - get size() { - if (!IsCountQueuingStrategy(this)) { - throw countBrandCheckException('size'); - } - return countSizeFunction; - } -} -Object.defineProperties(CountQueuingStrategy.prototype, { - highWaterMark: { enumerable: true }, - size: { enumerable: true } -}); -if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(CountQueuingStrategy.prototype, SymbolPolyfill.toStringTag, { - value: 'CountQueuingStrategy', - configurable: true - }); -} -// Helper functions for the CountQueuingStrategy. -function countBrandCheckException(name) { - return new TypeError(`CountQueuingStrategy.prototype.${name} can only be used on a CountQueuingStrategy`); -} -function IsCountQueuingStrategy(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_countQueuingStrategyHighWaterMark')) { - return false; - } - return true; -} - -function convertTransformer(original, context) { - assertDictionary(original, context); - const flush = original === null || original === void 0 ? void 0 : original.flush; - const readableType = original === null || original === void 0 ? void 0 : original.readableType; - const start = original === null || original === void 0 ? void 0 : original.start; - const transform = original === null || original === void 0 ? void 0 : original.transform; - const writableType = original === null || original === void 0 ? void 0 : original.writableType; - return { - flush: flush === undefined ? - undefined : - convertTransformerFlushCallback(flush, original, `${context} has member 'flush' that`), - readableType, - start: start === undefined ? - undefined : - convertTransformerStartCallback(start, original, `${context} has member 'start' that`), - transform: transform === undefined ? - undefined : - convertTransformerTransformCallback(transform, original, `${context} has member 'transform' that`), - writableType - }; -} -function convertTransformerFlushCallback(fn, original, context) { - assertFunction(fn, context); - return (controller) => promiseCall(fn, original, [controller]); -} -function convertTransformerStartCallback(fn, original, context) { - assertFunction(fn, context); - return (controller) => reflectCall(fn, original, [controller]); -} -function convertTransformerTransformCallback(fn, original, context) { - assertFunction(fn, context); - return (chunk, controller) => promiseCall(fn, original, [chunk, controller]); -} - -// Class TransformStream -/** - * A transform stream consists of a pair of streams: a {@link WritableStream | writable stream}, - * known as its writable side, and a {@link ReadableStream | readable stream}, known as its readable side. - * In a manner specific to the transform stream in question, writes to the writable side result in new data being - * made available for reading from the readable side. - * - * @public - */ -class TransformStream$1 { - constructor(rawTransformer = {}, rawWritableStrategy = {}, rawReadableStrategy = {}) { - if (rawTransformer === undefined) { - rawTransformer = null; - } - const writableStrategy = convertQueuingStrategy(rawWritableStrategy, 'Second parameter'); - const readableStrategy = convertQueuingStrategy(rawReadableStrategy, 'Third parameter'); - const transformer = convertTransformer(rawTransformer, 'First parameter'); - if (transformer.readableType !== undefined) { - throw new RangeError('Invalid readableType specified'); - } - if (transformer.writableType !== undefined) { - throw new RangeError('Invalid writableType specified'); - } - const readableHighWaterMark = ExtractHighWaterMark(readableStrategy, 0); - const readableSizeAlgorithm = ExtractSizeAlgorithm(readableStrategy); - const writableHighWaterMark = ExtractHighWaterMark(writableStrategy, 1); - const writableSizeAlgorithm = ExtractSizeAlgorithm(writableStrategy); - let startPromise_resolve; - const startPromise = newPromise(resolve => { - startPromise_resolve = resolve; - }); - InitializeTransformStream(this, startPromise, writableHighWaterMark, writableSizeAlgorithm, readableHighWaterMark, readableSizeAlgorithm); - SetUpTransformStreamDefaultControllerFromTransformer(this, transformer); - if (transformer.start !== undefined) { - startPromise_resolve(transformer.start(this._transformStreamController)); - } - else { - startPromise_resolve(undefined); - } - } - /** - * The readable side of the transform stream. - */ - get readable() { - if (!IsTransformStream(this)) { - throw streamBrandCheckException('readable'); - } - return this._readable; - } - /** - * The writable side of the transform stream. - */ - get writable() { - if (!IsTransformStream(this)) { - throw streamBrandCheckException('writable'); - } - return this._writable; - } -} -Object.defineProperties(TransformStream$1.prototype, { - readable: { enumerable: true }, - writable: { enumerable: true } -}); -if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(TransformStream$1.prototype, SymbolPolyfill.toStringTag, { - value: 'TransformStream', - configurable: true - }); -} -function InitializeTransformStream(stream, startPromise, writableHighWaterMark, writableSizeAlgorithm, readableHighWaterMark, readableSizeAlgorithm) { - function startAlgorithm() { - return startPromise; - } - function writeAlgorithm(chunk) { - return TransformStreamDefaultSinkWriteAlgorithm(stream, chunk); - } - function abortAlgorithm(reason) { - return TransformStreamDefaultSinkAbortAlgorithm(stream, reason); - } - function closeAlgorithm() { - return TransformStreamDefaultSinkCloseAlgorithm(stream); - } - stream._writable = CreateWritableStream(startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, writableHighWaterMark, writableSizeAlgorithm); - function pullAlgorithm() { - return TransformStreamDefaultSourcePullAlgorithm(stream); - } - function cancelAlgorithm(reason) { - TransformStreamErrorWritableAndUnblockWrite(stream, reason); - return promiseResolvedWith(undefined); - } - stream._readable = CreateReadableStream(startAlgorithm, pullAlgorithm, cancelAlgorithm, readableHighWaterMark, readableSizeAlgorithm); - // The [[backpressure]] slot is set to undefined so that it can be initialised by TransformStreamSetBackpressure. - stream._backpressure = undefined; - stream._backpressureChangePromise = undefined; - stream._backpressureChangePromise_resolve = undefined; - TransformStreamSetBackpressure(stream, true); - stream._transformStreamController = undefined; -} -function IsTransformStream(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_transformStreamController')) { - return false; - } - return true; -} -// This is a no-op if both sides are already errored. -function TransformStreamError(stream, e) { - ReadableStreamDefaultControllerError(stream._readable._readableStreamController, e); - TransformStreamErrorWritableAndUnblockWrite(stream, e); -} -function TransformStreamErrorWritableAndUnblockWrite(stream, e) { - TransformStreamDefaultControllerClearAlgorithms(stream._transformStreamController); - WritableStreamDefaultControllerErrorIfNeeded(stream._writable._writableStreamController, e); - if (stream._backpressure) { - // Pretend that pull() was called to permit any pending write() calls to complete. TransformStreamSetBackpressure() - // cannot be called from enqueue() or pull() once the ReadableStream is errored, so this will will be the final time - // _backpressure is set. - TransformStreamSetBackpressure(stream, false); - } -} -function TransformStreamSetBackpressure(stream, backpressure) { - // Passes also when called during construction. - if (stream._backpressureChangePromise !== undefined) { - stream._backpressureChangePromise_resolve(); - } - stream._backpressureChangePromise = newPromise(resolve => { - stream._backpressureChangePromise_resolve = resolve; - }); - stream._backpressure = backpressure; -} -// Class TransformStreamDefaultController -/** - * Allows control of the {@link ReadableStream} and {@link WritableStream} of the associated {@link TransformStream}. - * - * @public - */ -class TransformStreamDefaultController { - constructor() { - throw new TypeError('Illegal constructor'); - } - /** - * Returns the desired size to fill the readable side’s internal queue. It can be negative, if the queue is over-full. - */ - get desiredSize() { - if (!IsTransformStreamDefaultController(this)) { - throw defaultControllerBrandCheckException('desiredSize'); - } - const readableController = this._controlledTransformStream._readable._readableStreamController; - return ReadableStreamDefaultControllerGetDesiredSize(readableController); - } - enqueue(chunk = undefined) { - if (!IsTransformStreamDefaultController(this)) { - throw defaultControllerBrandCheckException('enqueue'); - } - TransformStreamDefaultControllerEnqueue(this, chunk); - } - /** - * Errors both the readable side and the writable side of the controlled transform stream, making all future - * interactions with it fail with the given error `e`. Any chunks queued for transformation will be discarded. - */ - error(reason = undefined) { - if (!IsTransformStreamDefaultController(this)) { - throw defaultControllerBrandCheckException('error'); - } - TransformStreamDefaultControllerError(this, reason); - } - /** - * Closes the readable side and errors the writable side of the controlled transform stream. This is useful when the - * transformer only needs to consume a portion of the chunks written to the writable side. - */ - terminate() { - if (!IsTransformStreamDefaultController(this)) { - throw defaultControllerBrandCheckException('terminate'); - } - TransformStreamDefaultControllerTerminate(this); - } -} -Object.defineProperties(TransformStreamDefaultController.prototype, { - enqueue: { enumerable: true }, - error: { enumerable: true }, - terminate: { enumerable: true }, - desiredSize: { enumerable: true } -}); -if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(TransformStreamDefaultController.prototype, SymbolPolyfill.toStringTag, { - value: 'TransformStreamDefaultController', - configurable: true - }); -} -// Transform Stream Default Controller Abstract Operations -function IsTransformStreamDefaultController(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_controlledTransformStream')) { - return false; - } - return true; -} -function SetUpTransformStreamDefaultController(stream, controller, transformAlgorithm, flushAlgorithm) { - controller._controlledTransformStream = stream; - stream._transformStreamController = controller; - controller._transformAlgorithm = transformAlgorithm; - controller._flushAlgorithm = flushAlgorithm; -} -function SetUpTransformStreamDefaultControllerFromTransformer(stream, transformer) { - const controller = Object.create(TransformStreamDefaultController.prototype); - let transformAlgorithm = (chunk) => { - try { - TransformStreamDefaultControllerEnqueue(controller, chunk); - return promiseResolvedWith(undefined); - } - catch (transformResultE) { - return promiseRejectedWith(transformResultE); - } - }; - let flushAlgorithm = () => promiseResolvedWith(undefined); - if (transformer.transform !== undefined) { - transformAlgorithm = chunk => transformer.transform(chunk, controller); - } - if (transformer.flush !== undefined) { - flushAlgorithm = () => transformer.flush(controller); - } - SetUpTransformStreamDefaultController(stream, controller, transformAlgorithm, flushAlgorithm); -} -function TransformStreamDefaultControllerClearAlgorithms(controller) { - controller._transformAlgorithm = undefined; - controller._flushAlgorithm = undefined; -} -function TransformStreamDefaultControllerEnqueue(controller, chunk) { - const stream = controller._controlledTransformStream; - const readableController = stream._readable._readableStreamController; - if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(readableController)) { - throw new TypeError('Readable side is not in a state that permits enqueue'); - } - // We throttle transform invocations based on the backpressure of the ReadableStream, but we still - // accept TransformStreamDefaultControllerEnqueue() calls. - try { - ReadableStreamDefaultControllerEnqueue(readableController, chunk); - } - catch (e) { - // This happens when readableStrategy.size() throws. - TransformStreamErrorWritableAndUnblockWrite(stream, e); - throw stream._readable._storedError; - } - const backpressure = ReadableStreamDefaultControllerHasBackpressure(readableController); - if (backpressure !== stream._backpressure) { - TransformStreamSetBackpressure(stream, true); - } -} -function TransformStreamDefaultControllerError(controller, e) { - TransformStreamError(controller._controlledTransformStream, e); -} -function TransformStreamDefaultControllerPerformTransform(controller, chunk) { - const transformPromise = controller._transformAlgorithm(chunk); - return transformPromiseWith(transformPromise, undefined, r => { - TransformStreamError(controller._controlledTransformStream, r); - throw r; - }); -} -function TransformStreamDefaultControllerTerminate(controller) { - const stream = controller._controlledTransformStream; - const readableController = stream._readable._readableStreamController; - ReadableStreamDefaultControllerClose(readableController); - const error = new TypeError('TransformStream terminated'); - TransformStreamErrorWritableAndUnblockWrite(stream, error); -} -// TransformStreamDefaultSink Algorithms -function TransformStreamDefaultSinkWriteAlgorithm(stream, chunk) { - const controller = stream._transformStreamController; - if (stream._backpressure) { - const backpressureChangePromise = stream._backpressureChangePromise; - return transformPromiseWith(backpressureChangePromise, () => { - const writable = stream._writable; - const state = writable._state; - if (state === 'erroring') { - throw writable._storedError; - } - return TransformStreamDefaultControllerPerformTransform(controller, chunk); - }); - } - return TransformStreamDefaultControllerPerformTransform(controller, chunk); -} -function TransformStreamDefaultSinkAbortAlgorithm(stream, reason) { - // abort() is not called synchronously, so it is possible for abort() to be called when the stream is already - // errored. - TransformStreamError(stream, reason); - return promiseResolvedWith(undefined); -} -function TransformStreamDefaultSinkCloseAlgorithm(stream) { - // stream._readable cannot change after construction, so caching it across a call to user code is safe. - const readable = stream._readable; - const controller = stream._transformStreamController; - const flushPromise = controller._flushAlgorithm(); - TransformStreamDefaultControllerClearAlgorithms(controller); - // Return a promise that is fulfilled with undefined on success. - return transformPromiseWith(flushPromise, () => { - if (readable._state === 'errored') { - throw readable._storedError; - } - ReadableStreamDefaultControllerClose(readable._readableStreamController); - }, r => { - TransformStreamError(stream, r); - throw readable._storedError; - }); -} -// TransformStreamDefaultSource Algorithms -function TransformStreamDefaultSourcePullAlgorithm(stream) { - // Invariant. Enforced by the promises returned by start() and pull(). - TransformStreamSetBackpressure(stream, false); - // Prevent the next pull() call until there is backpressure. - return stream._backpressureChangePromise; -} -// Helper functions for the TransformStreamDefaultController. -function defaultControllerBrandCheckException(name) { - return new TypeError(`TransformStreamDefaultController.prototype.${name} can only be used on a TransformStreamDefaultController`); -} -// Helper functions for the TransformStream. -function streamBrandCheckException(name) { - return new TypeError(`TransformStream.prototype.${name} can only be used on a TransformStream`); -} - -var ponyfill_es6 = /*#__PURE__*/Object.freeze({ - __proto__: null, - ByteLengthQueuingStrategy: ByteLengthQueuingStrategy, - CountQueuingStrategy: CountQueuingStrategy, - ReadableByteStreamController: ReadableByteStreamController, - ReadableStream: ReadableStream$1, - ReadableStreamBYOBReader: ReadableStreamBYOBReader, - ReadableStreamBYOBRequest: ReadableStreamBYOBRequest, - ReadableStreamDefaultController: ReadableStreamDefaultController, - ReadableStreamDefaultReader: ReadableStreamDefaultReader, - TransformStream: TransformStream$1, - TransformStreamDefaultController: TransformStreamDefaultController, - WritableStream: WritableStream$1, - WritableStreamDefaultController: WritableStreamDefaultController, - WritableStreamDefaultWriter: WritableStreamDefaultWriter -}); - -/*! ***************************************************************************** -Copyright (c) Microsoft Corporation. - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. -***************************************************************************** */ -/* global Reflect, Promise */ - -var extendStatics = function(d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); -}; - -function __extends(d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); -} - -function assert$1(test) { - if (!test) { - throw new TypeError('Assertion failed'); - } -} - -function noop$1() { - return; -} -function typeIsObject$1(x) { - return (typeof x === 'object' && x !== null) || typeof x === 'function'; -} - -function isStreamConstructor(ctor) { - if (typeof ctor !== 'function') { - return false; - } - var startCalled = false; - try { - new ctor({ - start: function () { - startCalled = true; - } - }); - } - catch (e) { - // ignore - } - return startCalled; -} -function isReadableStream(readable) { - if (!typeIsObject$1(readable)) { - return false; - } - if (typeof readable.getReader !== 'function') { - return false; - } - return true; -} -function isReadableStreamConstructor(ctor) { - if (!isStreamConstructor(ctor)) { - return false; - } - if (!isReadableStream(new ctor())) { - return false; - } - return true; -} -function isWritableStream(writable) { - if (!typeIsObject$1(writable)) { - return false; - } - if (typeof writable.getWriter !== 'function') { - return false; - } - return true; -} -function isWritableStreamConstructor(ctor) { - if (!isStreamConstructor(ctor)) { - return false; - } - if (!isWritableStream(new ctor())) { - return false; - } - return true; -} -function isTransformStream(transform) { - if (!typeIsObject$1(transform)) { - return false; - } - if (!isReadableStream(transform.readable)) { - return false; - } - if (!isWritableStream(transform.writable)) { - return false; - } - return true; -} -function isTransformStreamConstructor(ctor) { - if (!isStreamConstructor(ctor)) { - return false; - } - if (!isTransformStream(new ctor())) { - return false; - } - return true; -} -function supportsByobReader(readable) { - try { - var reader = readable.getReader({ mode: 'byob' }); - reader.releaseLock(); - return true; - } - catch (_a) { - return false; - } -} -function supportsByteSource(ctor) { - try { - new ctor({ type: 'bytes' }); - return true; - } - catch (_a) { - return false; - } -} - -function createReadableStreamWrapper(ctor) { - assert$1(isReadableStreamConstructor(ctor)); - var byteSourceSupported = supportsByteSource(ctor); - return function (readable, _a) { - var _b = _a === void 0 ? {} : _a, type = _b.type; - type = parseReadableType(type); - if (type === 'bytes' && !byteSourceSupported) { - type = undefined; - } - if (readable.constructor === ctor) { - if (type !== 'bytes' || supportsByobReader(readable)) { - return readable; - } - } - if (type === 'bytes') { - var source = createWrappingReadableSource(readable, { type: type }); - return new ctor(source); - } - else { - var source = createWrappingReadableSource(readable); - return new ctor(source); - } - }; -} -function createWrappingReadableSource(readable, _a) { - var _b = _a === void 0 ? {} : _a, type = _b.type; - assert$1(isReadableStream(readable)); - assert$1(readable.locked === false); - type = parseReadableType(type); - var source; - if (type === 'bytes') { - source = new WrappingReadableByteStreamSource(readable); - } - else { - source = new WrappingReadableStreamDefaultSource(readable); - } - return source; -} -function parseReadableType(type) { - var typeString = String(type); - if (typeString === 'bytes') { - return typeString; - } - else if (type === undefined) { - return type; - } - else { - throw new RangeError('Invalid type is specified'); - } -} -var AbstractWrappingReadableStreamSource = /** @class */ (function () { - function AbstractWrappingReadableStreamSource(underlyingStream) { - this._underlyingReader = undefined; - this._readerMode = undefined; - this._readableStreamController = undefined; - this._pendingRead = undefined; - this._underlyingStream = underlyingStream; - // always keep a reader attached to detect close/error - this._attachDefaultReader(); - } - AbstractWrappingReadableStreamSource.prototype.start = function (controller) { - this._readableStreamController = controller; - }; - AbstractWrappingReadableStreamSource.prototype.cancel = function (reason) { - assert$1(this._underlyingReader !== undefined); - return this._underlyingReader.cancel(reason); - }; - AbstractWrappingReadableStreamSource.prototype._attachDefaultReader = function () { - if (this._readerMode === "default" /* DEFAULT */) { - return; - } - this._detachReader(); - var reader = this._underlyingStream.getReader(); - this._readerMode = "default" /* DEFAULT */; - this._attachReader(reader); - }; - AbstractWrappingReadableStreamSource.prototype._attachReader = function (reader) { - var _this = this; - assert$1(this._underlyingReader === undefined); - this._underlyingReader = reader; - var closed = this._underlyingReader.closed; - if (!closed) { - return; - } - closed - .then(function () { return _this._finishPendingRead(); }) - .then(function () { - if (reader === _this._underlyingReader) { - _this._readableStreamController.close(); - } - }, function (reason) { - if (reader === _this._underlyingReader) { - _this._readableStreamController.error(reason); - } - }) - .catch(noop$1); - }; - AbstractWrappingReadableStreamSource.prototype._detachReader = function () { - if (this._underlyingReader === undefined) { - return; - } - this._underlyingReader.releaseLock(); - this._underlyingReader = undefined; - this._readerMode = undefined; - }; - AbstractWrappingReadableStreamSource.prototype._pullWithDefaultReader = function () { - var _this = this; - this._attachDefaultReader(); - // TODO Backpressure? - var read = this._underlyingReader.read() - .then(function (result) { - var controller = _this._readableStreamController; - if (result.done) { - _this._tryClose(); - } - else { - controller.enqueue(result.value); - } - }); - this._setPendingRead(read); - return read; - }; - AbstractWrappingReadableStreamSource.prototype._tryClose = function () { - try { - this._readableStreamController.close(); - } - catch (_a) { - // already errored or closed - } - }; - AbstractWrappingReadableStreamSource.prototype._setPendingRead = function (readPromise) { - var _this = this; - var pendingRead; - var finishRead = function () { - if (_this._pendingRead === pendingRead) { - _this._pendingRead = undefined; - } - }; - this._pendingRead = pendingRead = readPromise.then(finishRead, finishRead); - }; - AbstractWrappingReadableStreamSource.prototype._finishPendingRead = function () { - var _this = this; - if (!this._pendingRead) { - return undefined; - } - var afterRead = function () { return _this._finishPendingRead(); }; - return this._pendingRead.then(afterRead, afterRead); - }; - return AbstractWrappingReadableStreamSource; -}()); -var WrappingReadableStreamDefaultSource = /** @class */ (function (_super) { - __extends(WrappingReadableStreamDefaultSource, _super); - function WrappingReadableStreamDefaultSource() { - return _super !== null && _super.apply(this, arguments) || this; - } - WrappingReadableStreamDefaultSource.prototype.pull = function () { - return this._pullWithDefaultReader(); - }; - return WrappingReadableStreamDefaultSource; -}(AbstractWrappingReadableStreamSource)); -function toUint8Array(view) { - return new Uint8Array(view.buffer, view.byteOffset, view.byteLength); -} -function copyArrayBufferView(from, to) { - var fromArray = toUint8Array(from); - var toArray = toUint8Array(to); - toArray.set(fromArray, 0); -} -var WrappingReadableByteStreamSource = /** @class */ (function (_super) { - __extends(WrappingReadableByteStreamSource, _super); - function WrappingReadableByteStreamSource(underlyingStream) { - var _this = this; - var supportsByob = supportsByobReader(underlyingStream); - _this = _super.call(this, underlyingStream) || this; - _this._supportsByob = supportsByob; - return _this; - } - Object.defineProperty(WrappingReadableByteStreamSource.prototype, "type", { - get: function () { - return 'bytes'; - }, - enumerable: false, - configurable: true - }); - WrappingReadableByteStreamSource.prototype._attachByobReader = function () { - if (this._readerMode === "byob" /* BYOB */) { - return; - } - assert$1(this._supportsByob); - this._detachReader(); - var reader = this._underlyingStream.getReader({ mode: 'byob' }); - this._readerMode = "byob" /* BYOB */; - this._attachReader(reader); - }; - WrappingReadableByteStreamSource.prototype.pull = function () { - if (this._supportsByob) { - var byobRequest = this._readableStreamController.byobRequest; - if (byobRequest) { - return this._pullWithByobRequest(byobRequest); - } - } - return this._pullWithDefaultReader(); - }; - WrappingReadableByteStreamSource.prototype._pullWithByobRequest = function (byobRequest) { - var _this = this; - this._attachByobReader(); - // reader.read(view) detaches the input view, therefore we cannot pass byobRequest.view directly - // create a separate buffer to read into, then copy that to byobRequest.view - var buffer = new Uint8Array(byobRequest.view.byteLength); - // TODO Backpressure? - var read = this._underlyingReader.read(buffer) - .then(function (result) { - _this._readableStreamController; - if (result.done) { - _this._tryClose(); - byobRequest.respond(0); - } - else { - copyArrayBufferView(result.value, byobRequest.view); - byobRequest.respond(result.value.byteLength); - } - }); - this._setPendingRead(read); - return read; - }; - return WrappingReadableByteStreamSource; -}(AbstractWrappingReadableStreamSource)); - -function createWritableStreamWrapper(ctor) { - assert$1(isWritableStreamConstructor(ctor)); - return function (writable) { - if (writable.constructor === ctor) { - return writable; - } - var sink = createWrappingWritableSink(writable); - return new ctor(sink); - }; -} -function createWrappingWritableSink(writable) { - assert$1(isWritableStream(writable)); - assert$1(writable.locked === false); - var writer = writable.getWriter(); - return new WrappingWritableStreamSink(writer); -} -var WrappingWritableStreamSink = /** @class */ (function () { - function WrappingWritableStreamSink(underlyingWriter) { - var _this = this; - this._writableStreamController = undefined; - this._pendingWrite = undefined; - this._state = "writable" /* WRITABLE */; - this._storedError = undefined; - this._underlyingWriter = underlyingWriter; - this._errorPromise = new Promise(function (resolve, reject) { - _this._errorPromiseReject = reject; - }); - this._errorPromise.catch(noop$1); - } - WrappingWritableStreamSink.prototype.start = function (controller) { - var _this = this; - this._writableStreamController = controller; - this._underlyingWriter.closed - .then(function () { - _this._state = "closed" /* CLOSED */; - }) - .catch(function (reason) { return _this._finishErroring(reason); }); - }; - WrappingWritableStreamSink.prototype.write = function (chunk) { - var _this = this; - var writer = this._underlyingWriter; - // Detect past errors - if (writer.desiredSize === null) { - return writer.ready; - } - var writeRequest = writer.write(chunk); - // Detect future errors - writeRequest.catch(function (reason) { return _this._finishErroring(reason); }); - writer.ready.catch(function (reason) { return _this._startErroring(reason); }); - // Reject write when errored - var write = Promise.race([writeRequest, this._errorPromise]); - this._setPendingWrite(write); - return write; - }; - WrappingWritableStreamSink.prototype.close = function () { - var _this = this; - if (this._pendingWrite === undefined) { - return this._underlyingWriter.close(); - } - return this._finishPendingWrite().then(function () { return _this.close(); }); - }; - WrappingWritableStreamSink.prototype.abort = function (reason) { - if (this._state === "errored" /* ERRORED */) { - return undefined; - } - var writer = this._underlyingWriter; - return writer.abort(reason); - }; - WrappingWritableStreamSink.prototype._setPendingWrite = function (writePromise) { - var _this = this; - var pendingWrite; - var finishWrite = function () { - if (_this._pendingWrite === pendingWrite) { - _this._pendingWrite = undefined; - } - }; - this._pendingWrite = pendingWrite = writePromise.then(finishWrite, finishWrite); - }; - WrappingWritableStreamSink.prototype._finishPendingWrite = function () { - var _this = this; - if (this._pendingWrite === undefined) { - return Promise.resolve(); - } - var afterWrite = function () { return _this._finishPendingWrite(); }; - return this._pendingWrite.then(afterWrite, afterWrite); - }; - WrappingWritableStreamSink.prototype._startErroring = function (reason) { - var _this = this; - if (this._state === "writable" /* WRITABLE */) { - this._state = "erroring" /* ERRORING */; - this._storedError = reason; - var afterWrite = function () { return _this._finishErroring(reason); }; - if (this._pendingWrite === undefined) { - afterWrite(); - } - else { - this._finishPendingWrite().then(afterWrite, afterWrite); - } - this._writableStreamController.error(reason); - } - }; - WrappingWritableStreamSink.prototype._finishErroring = function (reason) { - if (this._state === "writable" /* WRITABLE */) { - this._startErroring(reason); - } - if (this._state === "erroring" /* ERRORING */) { - this._state = "errored" /* ERRORED */; - this._errorPromiseReject(this._storedError); - } - }; - return WrappingWritableStreamSink; -}()); - -function createTransformStreamWrapper(ctor) { - assert$1(isTransformStreamConstructor(ctor)); - return function (transform) { - if (transform.constructor === ctor) { - return transform; - } - var transformer = createWrappingTransformer(transform); - return new ctor(transformer); - }; -} -function createWrappingTransformer(transform) { - assert$1(isTransformStream(transform)); - var readable = transform.readable, writable = transform.writable; - assert$1(readable.locked === false); - assert$1(writable.locked === false); - var reader = readable.getReader(); - var writer; - try { - writer = writable.getWriter(); - } - catch (e) { - reader.releaseLock(); // do not leak reader - throw e; - } - return new WrappingTransformStreamTransformer(reader, writer); -} -var WrappingTransformStreamTransformer = /** @class */ (function () { - function WrappingTransformStreamTransformer(reader, writer) { - var _this = this; - this._transformStreamController = undefined; - this._onRead = function (result) { - if (result.done) { - return; - } - _this._transformStreamController.enqueue(result.value); - return _this._reader.read().then(_this._onRead); - }; - this._onError = function (reason) { - _this._flushReject(reason); - _this._transformStreamController.error(reason); - _this._reader.cancel(reason).catch(noop$1); - _this._writer.abort(reason).catch(noop$1); - }; - this._onTerminate = function () { - _this._flushResolve(); - _this._transformStreamController.terminate(); - var error = new TypeError('TransformStream terminated'); - _this._writer.abort(error).catch(noop$1); - }; - this._reader = reader; - this._writer = writer; - this._flushPromise = new Promise(function (resolve, reject) { - _this._flushResolve = resolve; - _this._flushReject = reject; - }); - } - WrappingTransformStreamTransformer.prototype.start = function (controller) { - this._transformStreamController = controller; - this._reader.read() - .then(this._onRead) - .then(this._onTerminate, this._onError); - var readerClosed = this._reader.closed; - if (readerClosed) { - readerClosed - .then(this._onTerminate, this._onError); - } - }; - WrappingTransformStreamTransformer.prototype.transform = function (chunk) { - return this._writer.write(chunk); - }; - WrappingTransformStreamTransformer.prototype.flush = function () { - var _this = this; - return this._writer.close() - .then(function () { return _this._flushPromise; }); - }; - return WrappingTransformStreamTransformer; -}()); - -var webStreamsAdapter = /*#__PURE__*/Object.freeze({ - __proto__: null, - createReadableStreamWrapper: createReadableStreamWrapper, - createTransformStreamWrapper: createTransformStreamWrapper, - createWrappingReadableSource: createWrappingReadableSource, - createWrappingTransformer: createWrappingTransformer, - createWrappingWritableSink: createWrappingWritableSink, - createWritableStreamWrapper: createWritableStreamWrapper -}); - -var bn = createCommonjsModule(function (module) { -(function (module, exports) { - - // Utils - function assert (val, msg) { - if (!val) throw new Error(msg || 'Assertion failed'); - } - - // Could use `inherits` module, but don't want to move from single file - // architecture yet. - function inherits (ctor, superCtor) { - ctor.super_ = superCtor; - var TempCtor = function () {}; - TempCtor.prototype = superCtor.prototype; - ctor.prototype = new TempCtor(); - ctor.prototype.constructor = ctor; - } - - // BN - - function BN (number, base, endian) { - if (BN.isBN(number)) { - return number; - } - - this.negative = 0; - this.words = null; - this.length = 0; - - // Reduction context - this.red = null; - - if (number !== null) { - if (base === 'le' || base === 'be') { - endian = base; - base = 10; - } - - this._init(number || 0, base || 10, endian || 'be'); - } - } - if (typeof module === 'object') { - module.exports = BN; - } else { - exports.BN = BN; - } - - BN.BN = BN; - BN.wordSize = 26; - - var Buffer; - try { - Buffer = buffer__default['default'].Buffer; - } catch (e) { - } - - BN.isBN = function isBN (num) { - if (num instanceof BN) { - return true; - } - - return num !== null && typeof num === 'object' && - num.constructor.wordSize === BN.wordSize && Array.isArray(num.words); - }; - - BN.max = function max (left, right) { - if (left.cmp(right) > 0) return left; - return right; - }; - - BN.min = function min (left, right) { - if (left.cmp(right) < 0) return left; - return right; - }; - - BN.prototype._init = function init (number, base, endian) { - if (typeof number === 'number') { - return this._initNumber(number, base, endian); - } - - if (typeof number === 'object') { - return this._initArray(number, base, endian); - } - - if (base === 'hex') { - base = 16; - } - assert(base === (base | 0) && base >= 2 && base <= 36); - - number = number.toString().replace(/\s+/g, ''); - var start = 0; - if (number[0] === '-') { - start++; - } - - if (base === 16) { - this._parseHex(number, start); - } else { - this._parseBase(number, base, start); - } - - if (number[0] === '-') { - this.negative = 1; - } - - this.strip(); - - if (endian !== 'le') return; - - this._initArray(this.toArray(), base, endian); - }; - - BN.prototype._initNumber = function _initNumber (number, base, endian) { - if (number < 0) { - this.negative = 1; - number = -number; - } - if (number < 0x4000000) { - this.words = [ number & 0x3ffffff ]; - this.length = 1; - } else if (number < 0x10000000000000) { - this.words = [ - number & 0x3ffffff, - (number / 0x4000000) & 0x3ffffff - ]; - this.length = 2; - } else { - assert(number < 0x20000000000000); // 2 ^ 53 (unsafe) - this.words = [ - number & 0x3ffffff, - (number / 0x4000000) & 0x3ffffff, - 1 - ]; - this.length = 3; - } - - if (endian !== 'le') return; - - // Reverse the bytes - this._initArray(this.toArray(), base, endian); - }; - - BN.prototype._initArray = function _initArray (number, base, endian) { - // Perhaps a Uint8Array - assert(typeof number.length === 'number'); - if (number.length <= 0) { - this.words = [ 0 ]; - this.length = 1; - return this; - } - - this.length = Math.ceil(number.length / 3); - this.words = new Array(this.length); - for (var i = 0; i < this.length; i++) { - this.words[i] = 0; - } - - var j, w; - var off = 0; - if (endian === 'be') { - for (i = number.length - 1, j = 0; i >= 0; i -= 3) { - w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16); - this.words[j] |= (w << off) & 0x3ffffff; - this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; - off += 24; - if (off >= 26) { - off -= 26; - j++; - } - } - } else if (endian === 'le') { - for (i = 0, j = 0; i < number.length; i += 3) { - w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16); - this.words[j] |= (w << off) & 0x3ffffff; - this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; - off += 24; - if (off >= 26) { - off -= 26; - j++; - } - } - } - return this.strip(); - }; - - function parseHex (str, start, end) { - var r = 0; - var len = Math.min(str.length, end); - for (var i = start; i < len; i++) { - var c = str.charCodeAt(i) - 48; - - r <<= 4; - - // 'a' - 'f' - if (c >= 49 && c <= 54) { - r |= c - 49 + 0xa; - - // 'A' - 'F' - } else if (c >= 17 && c <= 22) { - r |= c - 17 + 0xa; - - // '0' - '9' - } else { - r |= c & 0xf; - } - } - return r; - } - - BN.prototype._parseHex = function _parseHex (number, start) { - // Create possibly bigger array to ensure that it fits the number - this.length = Math.ceil((number.length - start) / 6); - this.words = new Array(this.length); - for (var i = 0; i < this.length; i++) { - this.words[i] = 0; - } - - var j, w; - // Scan 24-bit chunks and add them to the number - var off = 0; - for (i = number.length - 6, j = 0; i >= start; i -= 6) { - w = parseHex(number, i, i + 6); - this.words[j] |= (w << off) & 0x3ffffff; - // NOTE: `0x3fffff` is intentional here, 26bits max shift + 24bit hex limb - this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; - off += 24; - if (off >= 26) { - off -= 26; - j++; - } - } - if (i + 6 !== start) { - w = parseHex(number, start, i + 6); - this.words[j] |= (w << off) & 0x3ffffff; - this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; - } - this.strip(); - }; - - function parseBase (str, start, end, mul) { - var r = 0; - var len = Math.min(str.length, end); - for (var i = start; i < len; i++) { - var c = str.charCodeAt(i) - 48; - - r *= mul; - - // 'a' - if (c >= 49) { - r += c - 49 + 0xa; - - // 'A' - } else if (c >= 17) { - r += c - 17 + 0xa; - - // '0' - '9' - } else { - r += c; - } - } - return r; - } - - BN.prototype._parseBase = function _parseBase (number, base, start) { - // Initialize as zero - this.words = [ 0 ]; - this.length = 1; - - // Find length of limb in base - for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) { - limbLen++; - } - limbLen--; - limbPow = (limbPow / base) | 0; - - var total = number.length - start; - var mod = total % limbLen; - var end = Math.min(total, total - mod) + start; - - var word = 0; - for (var i = start; i < end; i += limbLen) { - word = parseBase(number, i, i + limbLen, base); - - this.imuln(limbPow); - if (this.words[0] + word < 0x4000000) { - this.words[0] += word; - } else { - this._iaddn(word); - } - } - - if (mod !== 0) { - var pow = 1; - word = parseBase(number, i, number.length, base); - - for (i = 0; i < mod; i++) { - pow *= base; - } - - this.imuln(pow); - if (this.words[0] + word < 0x4000000) { - this.words[0] += word; - } else { - this._iaddn(word); - } - } - }; - - BN.prototype.copy = function copy (dest) { - dest.words = new Array(this.length); - for (var i = 0; i < this.length; i++) { - dest.words[i] = this.words[i]; - } - dest.length = this.length; - dest.negative = this.negative; - dest.red = this.red; - }; - - BN.prototype.clone = function clone () { - var r = new BN(null); - this.copy(r); - return r; - }; - - BN.prototype._expand = function _expand (size) { - while (this.length < size) { - this.words[this.length++] = 0; - } - return this; - }; - - // Remove leading `0` from `this` - BN.prototype.strip = function strip () { - while (this.length > 1 && this.words[this.length - 1] === 0) { - this.length--; - } - return this._normSign(); - }; - - BN.prototype._normSign = function _normSign () { - // -0 = 0 - if (this.length === 1 && this.words[0] === 0) { - this.negative = 0; - } - return this; - }; - - BN.prototype.inspect = function inspect () { - return (this.red ? ''; - }; - - /* - - var zeros = []; - var groupSizes = []; - var groupBases = []; - - var s = ''; - var i = -1; - while (++i < BN.wordSize) { - zeros[i] = s; - s += '0'; - } - groupSizes[0] = 0; - groupSizes[1] = 0; - groupBases[0] = 0; - groupBases[1] = 0; - var base = 2 - 1; - while (++base < 36 + 1) { - var groupSize = 0; - var groupBase = 1; - while (groupBase < (1 << BN.wordSize) / base) { - groupBase *= base; - groupSize += 1; - } - groupSizes[base] = groupSize; - groupBases[base] = groupBase; - } - - */ - - var zeros = [ - '', - '0', - '00', - '000', - '0000', - '00000', - '000000', - '0000000', - '00000000', - '000000000', - '0000000000', - '00000000000', - '000000000000', - '0000000000000', - '00000000000000', - '000000000000000', - '0000000000000000', - '00000000000000000', - '000000000000000000', - '0000000000000000000', - '00000000000000000000', - '000000000000000000000', - '0000000000000000000000', - '00000000000000000000000', - '000000000000000000000000', - '0000000000000000000000000' - ]; - - var groupSizes = [ - 0, 0, - 25, 16, 12, 11, 10, 9, 8, - 8, 7, 7, 7, 7, 6, 6, - 6, 6, 6, 6, 6, 5, 5, - 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5 - ]; - - var groupBases = [ - 0, 0, - 33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216, - 43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625, - 16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632, - 6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149, - 24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176 - ]; - - BN.prototype.toString = function toString (base, padding) { - base = base || 10; - padding = padding | 0 || 1; - - var out; - if (base === 16 || base === 'hex') { - out = ''; - var off = 0; - var carry = 0; - for (var i = 0; i < this.length; i++) { - var w = this.words[i]; - var word = (((w << off) | carry) & 0xffffff).toString(16); - carry = (w >>> (24 - off)) & 0xffffff; - if (carry !== 0 || i !== this.length - 1) { - out = zeros[6 - word.length] + word + out; - } else { - out = word + out; - } - off += 2; - if (off >= 26) { - off -= 26; - i--; - } - } - if (carry !== 0) { - out = carry.toString(16) + out; - } - while (out.length % padding !== 0) { - out = '0' + out; - } - if (this.negative !== 0) { - out = '-' + out; - } - return out; - } - - if (base === (base | 0) && base >= 2 && base <= 36) { - // var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base)); - var groupSize = groupSizes[base]; - // var groupBase = Math.pow(base, groupSize); - var groupBase = groupBases[base]; - out = ''; - var c = this.clone(); - c.negative = 0; - while (!c.isZero()) { - var r = c.modn(groupBase).toString(base); - c = c.idivn(groupBase); - - if (!c.isZero()) { - out = zeros[groupSize - r.length] + r + out; - } else { - out = r + out; - } - } - if (this.isZero()) { - out = '0' + out; - } - while (out.length % padding !== 0) { - out = '0' + out; - } - if (this.negative !== 0) { - out = '-' + out; - } - return out; - } - - assert(false, 'Base should be between 2 and 36'); - }; - - BN.prototype.toNumber = function toNumber () { - var ret = this.words[0]; - if (this.length === 2) { - ret += this.words[1] * 0x4000000; - } else if (this.length === 3 && this.words[2] === 0x01) { - // NOTE: at this stage it is known that the top bit is set - ret += 0x10000000000000 + (this.words[1] * 0x4000000); - } else if (this.length > 2) { - assert(false, 'Number can only safely store up to 53 bits'); - } - return (this.negative !== 0) ? -ret : ret; - }; - - BN.prototype.toJSON = function toJSON () { - return this.toString(16); - }; - - BN.prototype.toBuffer = function toBuffer (endian, length) { - assert(typeof Buffer !== 'undefined'); - return this.toArrayLike(Buffer, endian, length); - }; - - BN.prototype.toArray = function toArray (endian, length) { - return this.toArrayLike(Array, endian, length); - }; - - BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) { - var byteLength = this.byteLength(); - var reqLength = length || Math.max(1, byteLength); - assert(byteLength <= reqLength, 'byte array longer than desired length'); - assert(reqLength > 0, 'Requested array length <= 0'); - - this.strip(); - var littleEndian = endian === 'le'; - var res = new ArrayType(reqLength); - - var b, i; - var q = this.clone(); - if (!littleEndian) { - // Assume big-endian - for (i = 0; i < reqLength - byteLength; i++) { - res[i] = 0; - } - - for (i = 0; !q.isZero(); i++) { - b = q.andln(0xff); - q.iushrn(8); - - res[reqLength - i - 1] = b; - } - } else { - for (i = 0; !q.isZero(); i++) { - b = q.andln(0xff); - q.iushrn(8); - - res[i] = b; - } - - for (; i < reqLength; i++) { - res[i] = 0; - } - } - - return res; - }; - - if (Math.clz32) { - BN.prototype._countBits = function _countBits (w) { - return 32 - Math.clz32(w); - }; - } else { - BN.prototype._countBits = function _countBits (w) { - var t = w; - var r = 0; - if (t >= 0x1000) { - r += 13; - t >>>= 13; - } - if (t >= 0x40) { - r += 7; - t >>>= 7; - } - if (t >= 0x8) { - r += 4; - t >>>= 4; - } - if (t >= 0x02) { - r += 2; - t >>>= 2; - } - return r + t; - }; - } - - BN.prototype._zeroBits = function _zeroBits (w) { - // Short-cut - if (w === 0) return 26; - - var t = w; - var r = 0; - if ((t & 0x1fff) === 0) { - r += 13; - t >>>= 13; - } - if ((t & 0x7f) === 0) { - r += 7; - t >>>= 7; - } - if ((t & 0xf) === 0) { - r += 4; - t >>>= 4; - } - if ((t & 0x3) === 0) { - r += 2; - t >>>= 2; - } - if ((t & 0x1) === 0) { - r++; - } - return r; - }; - - // Return number of used bits in a BN - BN.prototype.bitLength = function bitLength () { - var w = this.words[this.length - 1]; - var hi = this._countBits(w); - return (this.length - 1) * 26 + hi; - }; - - function toBitArray (num) { - var w = new Array(num.bitLength()); - - for (var bit = 0; bit < w.length; bit++) { - var off = (bit / 26) | 0; - var wbit = bit % 26; - - w[bit] = (num.words[off] & (1 << wbit)) >>> wbit; - } - - return w; - } - - // Number of trailing zero bits - BN.prototype.zeroBits = function zeroBits () { - if (this.isZero()) return 0; - - var r = 0; - for (var i = 0; i < this.length; i++) { - var b = this._zeroBits(this.words[i]); - r += b; - if (b !== 26) break; - } - return r; - }; - - BN.prototype.byteLength = function byteLength () { - return Math.ceil(this.bitLength() / 8); - }; - - BN.prototype.toTwos = function toTwos (width) { - if (this.negative !== 0) { - return this.abs().inotn(width).iaddn(1); - } - return this.clone(); - }; - - BN.prototype.fromTwos = function fromTwos (width) { - if (this.testn(width - 1)) { - return this.notn(width).iaddn(1).ineg(); - } - return this.clone(); - }; - - BN.prototype.isNeg = function isNeg () { - return this.negative !== 0; - }; - - // Return negative clone of `this` - BN.prototype.neg = function neg () { - return this.clone().ineg(); - }; - - BN.prototype.ineg = function ineg () { - if (!this.isZero()) { - this.negative ^= 1; - } - - return this; - }; - - // Or `num` with `this` in-place - BN.prototype.iuor = function iuor (num) { - while (this.length < num.length) { - this.words[this.length++] = 0; - } - - for (var i = 0; i < num.length; i++) { - this.words[i] = this.words[i] | num.words[i]; - } - - return this.strip(); - }; - - BN.prototype.ior = function ior (num) { - assert((this.negative | num.negative) === 0); - return this.iuor(num); - }; - - // Or `num` with `this` - BN.prototype.or = function or (num) { - if (this.length > num.length) return this.clone().ior(num); - return num.clone().ior(this); - }; - - BN.prototype.uor = function uor (num) { - if (this.length > num.length) return this.clone().iuor(num); - return num.clone().iuor(this); - }; - - // And `num` with `this` in-place - BN.prototype.iuand = function iuand (num) { - // b = min-length(num, this) - var b; - if (this.length > num.length) { - b = num; - } else { - b = this; - } - - for (var i = 0; i < b.length; i++) { - this.words[i] = this.words[i] & num.words[i]; - } - - this.length = b.length; - - return this.strip(); - }; - - BN.prototype.iand = function iand (num) { - assert((this.negative | num.negative) === 0); - return this.iuand(num); - }; - - // And `num` with `this` - BN.prototype.and = function and (num) { - if (this.length > num.length) return this.clone().iand(num); - return num.clone().iand(this); - }; - - BN.prototype.uand = function uand (num) { - if (this.length > num.length) return this.clone().iuand(num); - return num.clone().iuand(this); - }; - - // Xor `num` with `this` in-place - BN.prototype.iuxor = function iuxor (num) { - // a.length > b.length - var a; - var b; - if (this.length > num.length) { - a = this; - b = num; - } else { - a = num; - b = this; - } - - for (var i = 0; i < b.length; i++) { - this.words[i] = a.words[i] ^ b.words[i]; - } - - if (this !== a) { - for (; i < a.length; i++) { - this.words[i] = a.words[i]; - } - } - - this.length = a.length; - - return this.strip(); - }; - - BN.prototype.ixor = function ixor (num) { - assert((this.negative | num.negative) === 0); - return this.iuxor(num); - }; - - // Xor `num` with `this` - BN.prototype.xor = function xor (num) { - if (this.length > num.length) return this.clone().ixor(num); - return num.clone().ixor(this); - }; - - BN.prototype.uxor = function uxor (num) { - if (this.length > num.length) return this.clone().iuxor(num); - return num.clone().iuxor(this); - }; - - // Not ``this`` with ``width`` bitwidth - BN.prototype.inotn = function inotn (width) { - assert(typeof width === 'number' && width >= 0); - - var bytesNeeded = Math.ceil(width / 26) | 0; - var bitsLeft = width % 26; - - // Extend the buffer with leading zeroes - this._expand(bytesNeeded); - - if (bitsLeft > 0) { - bytesNeeded--; - } - - // Handle complete words - for (var i = 0; i < bytesNeeded; i++) { - this.words[i] = ~this.words[i] & 0x3ffffff; - } - - // Handle the residue - if (bitsLeft > 0) { - this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft)); - } - - // And remove leading zeroes - return this.strip(); - }; - - BN.prototype.notn = function notn (width) { - return this.clone().inotn(width); - }; - - // Set `bit` of `this` - BN.prototype.setn = function setn (bit, val) { - assert(typeof bit === 'number' && bit >= 0); - - var off = (bit / 26) | 0; - var wbit = bit % 26; - - this._expand(off + 1); - - if (val) { - this.words[off] = this.words[off] | (1 << wbit); - } else { - this.words[off] = this.words[off] & ~(1 << wbit); - } - - return this.strip(); - }; - - // Add `num` to `this` in-place - BN.prototype.iadd = function iadd (num) { - var r; - - // negative + positive - if (this.negative !== 0 && num.negative === 0) { - this.negative = 0; - r = this.isub(num); - this.negative ^= 1; - return this._normSign(); - - // positive + negative - } else if (this.negative === 0 && num.negative !== 0) { - num.negative = 0; - r = this.isub(num); - num.negative = 1; - return r._normSign(); - } - - // a.length > b.length - var a, b; - if (this.length > num.length) { - a = this; - b = num; - } else { - a = num; - b = this; - } - - var carry = 0; - for (var i = 0; i < b.length; i++) { - r = (a.words[i] | 0) + (b.words[i] | 0) + carry; - this.words[i] = r & 0x3ffffff; - carry = r >>> 26; - } - for (; carry !== 0 && i < a.length; i++) { - r = (a.words[i] | 0) + carry; - this.words[i] = r & 0x3ffffff; - carry = r >>> 26; - } - - this.length = a.length; - if (carry !== 0) { - this.words[this.length] = carry; - this.length++; - // Copy the rest of the words - } else if (a !== this) { - for (; i < a.length; i++) { - this.words[i] = a.words[i]; - } - } - - return this; - }; - - // Add `num` to `this` - BN.prototype.add = function add (num) { - var res; - if (num.negative !== 0 && this.negative === 0) { - num.negative = 0; - res = this.sub(num); - num.negative ^= 1; - return res; - } else if (num.negative === 0 && this.negative !== 0) { - this.negative = 0; - res = num.sub(this); - this.negative = 1; - return res; - } - - if (this.length > num.length) return this.clone().iadd(num); - - return num.clone().iadd(this); - }; - - // Subtract `num` from `this` in-place - BN.prototype.isub = function isub (num) { - // this - (-num) = this + num - if (num.negative !== 0) { - num.negative = 0; - var r = this.iadd(num); - num.negative = 1; - return r._normSign(); - - // -this - num = -(this + num) - } else if (this.negative !== 0) { - this.negative = 0; - this.iadd(num); - this.negative = 1; - return this._normSign(); - } - - // At this point both numbers are positive - var cmp = this.cmp(num); - - // Optimization - zeroify - if (cmp === 0) { - this.negative = 0; - this.length = 1; - this.words[0] = 0; - return this; - } - - // a > b - var a, b; - if (cmp > 0) { - a = this; - b = num; - } else { - a = num; - b = this; - } - - var carry = 0; - for (var i = 0; i < b.length; i++) { - r = (a.words[i] | 0) - (b.words[i] | 0) + carry; - carry = r >> 26; - this.words[i] = r & 0x3ffffff; - } - for (; carry !== 0 && i < a.length; i++) { - r = (a.words[i] | 0) + carry; - carry = r >> 26; - this.words[i] = r & 0x3ffffff; - } - - // Copy rest of the words - if (carry === 0 && i < a.length && a !== this) { - for (; i < a.length; i++) { - this.words[i] = a.words[i]; - } - } - - this.length = Math.max(this.length, i); - - if (a !== this) { - this.negative = 1; - } - - return this.strip(); - }; - - // Subtract `num` from `this` - BN.prototype.sub = function sub (num) { - return this.clone().isub(num); - }; - - function smallMulTo (self, num, out) { - out.negative = num.negative ^ self.negative; - var len = (self.length + num.length) | 0; - out.length = len; - len = (len - 1) | 0; - - // Peel one iteration (compiler can't do it, because of code complexity) - var a = self.words[0] | 0; - var b = num.words[0] | 0; - var r = a * b; - - var lo = r & 0x3ffffff; - var carry = (r / 0x4000000) | 0; - out.words[0] = lo; - - for (var k = 1; k < len; k++) { - // Sum all words with the same `i + j = k` and accumulate `ncarry`, - // note that ncarry could be >= 0x3ffffff - var ncarry = carry >>> 26; - var rword = carry & 0x3ffffff; - var maxJ = Math.min(k, num.length - 1); - for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { - var i = (k - j) | 0; - a = self.words[i] | 0; - b = num.words[j] | 0; - r = a * b + rword; - ncarry += (r / 0x4000000) | 0; - rword = r & 0x3ffffff; - } - out.words[k] = rword | 0; - carry = ncarry | 0; - } - if (carry !== 0) { - out.words[k] = carry | 0; - } else { - out.length--; - } - - return out.strip(); - } - - // TODO(indutny): it may be reasonable to omit it for users who don't need - // to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit - // multiplication (like elliptic secp256k1). - var comb10MulTo = function comb10MulTo (self, num, out) { - var a = self.words; - var b = num.words; - var o = out.words; - var c = 0; - var lo; - var mid; - var hi; - var a0 = a[0] | 0; - var al0 = a0 & 0x1fff; - var ah0 = a0 >>> 13; - var a1 = a[1] | 0; - var al1 = a1 & 0x1fff; - var ah1 = a1 >>> 13; - var a2 = a[2] | 0; - var al2 = a2 & 0x1fff; - var ah2 = a2 >>> 13; - var a3 = a[3] | 0; - var al3 = a3 & 0x1fff; - var ah3 = a3 >>> 13; - var a4 = a[4] | 0; - var al4 = a4 & 0x1fff; - var ah4 = a4 >>> 13; - var a5 = a[5] | 0; - var al5 = a5 & 0x1fff; - var ah5 = a5 >>> 13; - var a6 = a[6] | 0; - var al6 = a6 & 0x1fff; - var ah6 = a6 >>> 13; - var a7 = a[7] | 0; - var al7 = a7 & 0x1fff; - var ah7 = a7 >>> 13; - var a8 = a[8] | 0; - var al8 = a8 & 0x1fff; - var ah8 = a8 >>> 13; - var a9 = a[9] | 0; - var al9 = a9 & 0x1fff; - var ah9 = a9 >>> 13; - var b0 = b[0] | 0; - var bl0 = b0 & 0x1fff; - var bh0 = b0 >>> 13; - var b1 = b[1] | 0; - var bl1 = b1 & 0x1fff; - var bh1 = b1 >>> 13; - var b2 = b[2] | 0; - var bl2 = b2 & 0x1fff; - var bh2 = b2 >>> 13; - var b3 = b[3] | 0; - var bl3 = b3 & 0x1fff; - var bh3 = b3 >>> 13; - var b4 = b[4] | 0; - var bl4 = b4 & 0x1fff; - var bh4 = b4 >>> 13; - var b5 = b[5] | 0; - var bl5 = b5 & 0x1fff; - var bh5 = b5 >>> 13; - var b6 = b[6] | 0; - var bl6 = b6 & 0x1fff; - var bh6 = b6 >>> 13; - var b7 = b[7] | 0; - var bl7 = b7 & 0x1fff; - var bh7 = b7 >>> 13; - var b8 = b[8] | 0; - var bl8 = b8 & 0x1fff; - var bh8 = b8 >>> 13; - var b9 = b[9] | 0; - var bl9 = b9 & 0x1fff; - var bh9 = b9 >>> 13; - - out.negative = self.negative ^ num.negative; - out.length = 19; - /* k = 0 */ - lo = Math.imul(al0, bl0); - mid = Math.imul(al0, bh0); - mid = (mid + Math.imul(ah0, bl0)) | 0; - hi = Math.imul(ah0, bh0); - var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0; - w0 &= 0x3ffffff; - /* k = 1 */ - lo = Math.imul(al1, bl0); - mid = Math.imul(al1, bh0); - mid = (mid + Math.imul(ah1, bl0)) | 0; - hi = Math.imul(ah1, bh0); - lo = (lo + Math.imul(al0, bl1)) | 0; - mid = (mid + Math.imul(al0, bh1)) | 0; - mid = (mid + Math.imul(ah0, bl1)) | 0; - hi = (hi + Math.imul(ah0, bh1)) | 0; - var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0; - w1 &= 0x3ffffff; - /* k = 2 */ - lo = Math.imul(al2, bl0); - mid = Math.imul(al2, bh0); - mid = (mid + Math.imul(ah2, bl0)) | 0; - hi = Math.imul(ah2, bh0); - lo = (lo + Math.imul(al1, bl1)) | 0; - mid = (mid + Math.imul(al1, bh1)) | 0; - mid = (mid + Math.imul(ah1, bl1)) | 0; - hi = (hi + Math.imul(ah1, bh1)) | 0; - lo = (lo + Math.imul(al0, bl2)) | 0; - mid = (mid + Math.imul(al0, bh2)) | 0; - mid = (mid + Math.imul(ah0, bl2)) | 0; - hi = (hi + Math.imul(ah0, bh2)) | 0; - var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0; - w2 &= 0x3ffffff; - /* k = 3 */ - lo = Math.imul(al3, bl0); - mid = Math.imul(al3, bh0); - mid = (mid + Math.imul(ah3, bl0)) | 0; - hi = Math.imul(ah3, bh0); - lo = (lo + Math.imul(al2, bl1)) | 0; - mid = (mid + Math.imul(al2, bh1)) | 0; - mid = (mid + Math.imul(ah2, bl1)) | 0; - hi = (hi + Math.imul(ah2, bh1)) | 0; - lo = (lo + Math.imul(al1, bl2)) | 0; - mid = (mid + Math.imul(al1, bh2)) | 0; - mid = (mid + Math.imul(ah1, bl2)) | 0; - hi = (hi + Math.imul(ah1, bh2)) | 0; - lo = (lo + Math.imul(al0, bl3)) | 0; - mid = (mid + Math.imul(al0, bh3)) | 0; - mid = (mid + Math.imul(ah0, bl3)) | 0; - hi = (hi + Math.imul(ah0, bh3)) | 0; - var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0; - w3 &= 0x3ffffff; - /* k = 4 */ - lo = Math.imul(al4, bl0); - mid = Math.imul(al4, bh0); - mid = (mid + Math.imul(ah4, bl0)) | 0; - hi = Math.imul(ah4, bh0); - lo = (lo + Math.imul(al3, bl1)) | 0; - mid = (mid + Math.imul(al3, bh1)) | 0; - mid = (mid + Math.imul(ah3, bl1)) | 0; - hi = (hi + Math.imul(ah3, bh1)) | 0; - lo = (lo + Math.imul(al2, bl2)) | 0; - mid = (mid + Math.imul(al2, bh2)) | 0; - mid = (mid + Math.imul(ah2, bl2)) | 0; - hi = (hi + Math.imul(ah2, bh2)) | 0; - lo = (lo + Math.imul(al1, bl3)) | 0; - mid = (mid + Math.imul(al1, bh3)) | 0; - mid = (mid + Math.imul(ah1, bl3)) | 0; - hi = (hi + Math.imul(ah1, bh3)) | 0; - lo = (lo + Math.imul(al0, bl4)) | 0; - mid = (mid + Math.imul(al0, bh4)) | 0; - mid = (mid + Math.imul(ah0, bl4)) | 0; - hi = (hi + Math.imul(ah0, bh4)) | 0; - var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0; - w4 &= 0x3ffffff; - /* k = 5 */ - lo = Math.imul(al5, bl0); - mid = Math.imul(al5, bh0); - mid = (mid + Math.imul(ah5, bl0)) | 0; - hi = Math.imul(ah5, bh0); - lo = (lo + Math.imul(al4, bl1)) | 0; - mid = (mid + Math.imul(al4, bh1)) | 0; - mid = (mid + Math.imul(ah4, bl1)) | 0; - hi = (hi + Math.imul(ah4, bh1)) | 0; - lo = (lo + Math.imul(al3, bl2)) | 0; - mid = (mid + Math.imul(al3, bh2)) | 0; - mid = (mid + Math.imul(ah3, bl2)) | 0; - hi = (hi + Math.imul(ah3, bh2)) | 0; - lo = (lo + Math.imul(al2, bl3)) | 0; - mid = (mid + Math.imul(al2, bh3)) | 0; - mid = (mid + Math.imul(ah2, bl3)) | 0; - hi = (hi + Math.imul(ah2, bh3)) | 0; - lo = (lo + Math.imul(al1, bl4)) | 0; - mid = (mid + Math.imul(al1, bh4)) | 0; - mid = (mid + Math.imul(ah1, bl4)) | 0; - hi = (hi + Math.imul(ah1, bh4)) | 0; - lo = (lo + Math.imul(al0, bl5)) | 0; - mid = (mid + Math.imul(al0, bh5)) | 0; - mid = (mid + Math.imul(ah0, bl5)) | 0; - hi = (hi + Math.imul(ah0, bh5)) | 0; - var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0; - w5 &= 0x3ffffff; - /* k = 6 */ - lo = Math.imul(al6, bl0); - mid = Math.imul(al6, bh0); - mid = (mid + Math.imul(ah6, bl0)) | 0; - hi = Math.imul(ah6, bh0); - lo = (lo + Math.imul(al5, bl1)) | 0; - mid = (mid + Math.imul(al5, bh1)) | 0; - mid = (mid + Math.imul(ah5, bl1)) | 0; - hi = (hi + Math.imul(ah5, bh1)) | 0; - lo = (lo + Math.imul(al4, bl2)) | 0; - mid = (mid + Math.imul(al4, bh2)) | 0; - mid = (mid + Math.imul(ah4, bl2)) | 0; - hi = (hi + Math.imul(ah4, bh2)) | 0; - lo = (lo + Math.imul(al3, bl3)) | 0; - mid = (mid + Math.imul(al3, bh3)) | 0; - mid = (mid + Math.imul(ah3, bl3)) | 0; - hi = (hi + Math.imul(ah3, bh3)) | 0; - lo = (lo + Math.imul(al2, bl4)) | 0; - mid = (mid + Math.imul(al2, bh4)) | 0; - mid = (mid + Math.imul(ah2, bl4)) | 0; - hi = (hi + Math.imul(ah2, bh4)) | 0; - lo = (lo + Math.imul(al1, bl5)) | 0; - mid = (mid + Math.imul(al1, bh5)) | 0; - mid = (mid + Math.imul(ah1, bl5)) | 0; - hi = (hi + Math.imul(ah1, bh5)) | 0; - lo = (lo + Math.imul(al0, bl6)) | 0; - mid = (mid + Math.imul(al0, bh6)) | 0; - mid = (mid + Math.imul(ah0, bl6)) | 0; - hi = (hi + Math.imul(ah0, bh6)) | 0; - var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0; - w6 &= 0x3ffffff; - /* k = 7 */ - lo = Math.imul(al7, bl0); - mid = Math.imul(al7, bh0); - mid = (mid + Math.imul(ah7, bl0)) | 0; - hi = Math.imul(ah7, bh0); - lo = (lo + Math.imul(al6, bl1)) | 0; - mid = (mid + Math.imul(al6, bh1)) | 0; - mid = (mid + Math.imul(ah6, bl1)) | 0; - hi = (hi + Math.imul(ah6, bh1)) | 0; - lo = (lo + Math.imul(al5, bl2)) | 0; - mid = (mid + Math.imul(al5, bh2)) | 0; - mid = (mid + Math.imul(ah5, bl2)) | 0; - hi = (hi + Math.imul(ah5, bh2)) | 0; - lo = (lo + Math.imul(al4, bl3)) | 0; - mid = (mid + Math.imul(al4, bh3)) | 0; - mid = (mid + Math.imul(ah4, bl3)) | 0; - hi = (hi + Math.imul(ah4, bh3)) | 0; - lo = (lo + Math.imul(al3, bl4)) | 0; - mid = (mid + Math.imul(al3, bh4)) | 0; - mid = (mid + Math.imul(ah3, bl4)) | 0; - hi = (hi + Math.imul(ah3, bh4)) | 0; - lo = (lo + Math.imul(al2, bl5)) | 0; - mid = (mid + Math.imul(al2, bh5)) | 0; - mid = (mid + Math.imul(ah2, bl5)) | 0; - hi = (hi + Math.imul(ah2, bh5)) | 0; - lo = (lo + Math.imul(al1, bl6)) | 0; - mid = (mid + Math.imul(al1, bh6)) | 0; - mid = (mid + Math.imul(ah1, bl6)) | 0; - hi = (hi + Math.imul(ah1, bh6)) | 0; - lo = (lo + Math.imul(al0, bl7)) | 0; - mid = (mid + Math.imul(al0, bh7)) | 0; - mid = (mid + Math.imul(ah0, bl7)) | 0; - hi = (hi + Math.imul(ah0, bh7)) | 0; - var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0; - w7 &= 0x3ffffff; - /* k = 8 */ - lo = Math.imul(al8, bl0); - mid = Math.imul(al8, bh0); - mid = (mid + Math.imul(ah8, bl0)) | 0; - hi = Math.imul(ah8, bh0); - lo = (lo + Math.imul(al7, bl1)) | 0; - mid = (mid + Math.imul(al7, bh1)) | 0; - mid = (mid + Math.imul(ah7, bl1)) | 0; - hi = (hi + Math.imul(ah7, bh1)) | 0; - lo = (lo + Math.imul(al6, bl2)) | 0; - mid = (mid + Math.imul(al6, bh2)) | 0; - mid = (mid + Math.imul(ah6, bl2)) | 0; - hi = (hi + Math.imul(ah6, bh2)) | 0; - lo = (lo + Math.imul(al5, bl3)) | 0; - mid = (mid + Math.imul(al5, bh3)) | 0; - mid = (mid + Math.imul(ah5, bl3)) | 0; - hi = (hi + Math.imul(ah5, bh3)) | 0; - lo = (lo + Math.imul(al4, bl4)) | 0; - mid = (mid + Math.imul(al4, bh4)) | 0; - mid = (mid + Math.imul(ah4, bl4)) | 0; - hi = (hi + Math.imul(ah4, bh4)) | 0; - lo = (lo + Math.imul(al3, bl5)) | 0; - mid = (mid + Math.imul(al3, bh5)) | 0; - mid = (mid + Math.imul(ah3, bl5)) | 0; - hi = (hi + Math.imul(ah3, bh5)) | 0; - lo = (lo + Math.imul(al2, bl6)) | 0; - mid = (mid + Math.imul(al2, bh6)) | 0; - mid = (mid + Math.imul(ah2, bl6)) | 0; - hi = (hi + Math.imul(ah2, bh6)) | 0; - lo = (lo + Math.imul(al1, bl7)) | 0; - mid = (mid + Math.imul(al1, bh7)) | 0; - mid = (mid + Math.imul(ah1, bl7)) | 0; - hi = (hi + Math.imul(ah1, bh7)) | 0; - lo = (lo + Math.imul(al0, bl8)) | 0; - mid = (mid + Math.imul(al0, bh8)) | 0; - mid = (mid + Math.imul(ah0, bl8)) | 0; - hi = (hi + Math.imul(ah0, bh8)) | 0; - var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0; - w8 &= 0x3ffffff; - /* k = 9 */ - lo = Math.imul(al9, bl0); - mid = Math.imul(al9, bh0); - mid = (mid + Math.imul(ah9, bl0)) | 0; - hi = Math.imul(ah9, bh0); - lo = (lo + Math.imul(al8, bl1)) | 0; - mid = (mid + Math.imul(al8, bh1)) | 0; - mid = (mid + Math.imul(ah8, bl1)) | 0; - hi = (hi + Math.imul(ah8, bh1)) | 0; - lo = (lo + Math.imul(al7, bl2)) | 0; - mid = (mid + Math.imul(al7, bh2)) | 0; - mid = (mid + Math.imul(ah7, bl2)) | 0; - hi = (hi + Math.imul(ah7, bh2)) | 0; - lo = (lo + Math.imul(al6, bl3)) | 0; - mid = (mid + Math.imul(al6, bh3)) | 0; - mid = (mid + Math.imul(ah6, bl3)) | 0; - hi = (hi + Math.imul(ah6, bh3)) | 0; - lo = (lo + Math.imul(al5, bl4)) | 0; - mid = (mid + Math.imul(al5, bh4)) | 0; - mid = (mid + Math.imul(ah5, bl4)) | 0; - hi = (hi + Math.imul(ah5, bh4)) | 0; - lo = (lo + Math.imul(al4, bl5)) | 0; - mid = (mid + Math.imul(al4, bh5)) | 0; - mid = (mid + Math.imul(ah4, bl5)) | 0; - hi = (hi + Math.imul(ah4, bh5)) | 0; - lo = (lo + Math.imul(al3, bl6)) | 0; - mid = (mid + Math.imul(al3, bh6)) | 0; - mid = (mid + Math.imul(ah3, bl6)) | 0; - hi = (hi + Math.imul(ah3, bh6)) | 0; - lo = (lo + Math.imul(al2, bl7)) | 0; - mid = (mid + Math.imul(al2, bh7)) | 0; - mid = (mid + Math.imul(ah2, bl7)) | 0; - hi = (hi + Math.imul(ah2, bh7)) | 0; - lo = (lo + Math.imul(al1, bl8)) | 0; - mid = (mid + Math.imul(al1, bh8)) | 0; - mid = (mid + Math.imul(ah1, bl8)) | 0; - hi = (hi + Math.imul(ah1, bh8)) | 0; - lo = (lo + Math.imul(al0, bl9)) | 0; - mid = (mid + Math.imul(al0, bh9)) | 0; - mid = (mid + Math.imul(ah0, bl9)) | 0; - hi = (hi + Math.imul(ah0, bh9)) | 0; - var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0; - w9 &= 0x3ffffff; - /* k = 10 */ - lo = Math.imul(al9, bl1); - mid = Math.imul(al9, bh1); - mid = (mid + Math.imul(ah9, bl1)) | 0; - hi = Math.imul(ah9, bh1); - lo = (lo + Math.imul(al8, bl2)) | 0; - mid = (mid + Math.imul(al8, bh2)) | 0; - mid = (mid + Math.imul(ah8, bl2)) | 0; - hi = (hi + Math.imul(ah8, bh2)) | 0; - lo = (lo + Math.imul(al7, bl3)) | 0; - mid = (mid + Math.imul(al7, bh3)) | 0; - mid = (mid + Math.imul(ah7, bl3)) | 0; - hi = (hi + Math.imul(ah7, bh3)) | 0; - lo = (lo + Math.imul(al6, bl4)) | 0; - mid = (mid + Math.imul(al6, bh4)) | 0; - mid = (mid + Math.imul(ah6, bl4)) | 0; - hi = (hi + Math.imul(ah6, bh4)) | 0; - lo = (lo + Math.imul(al5, bl5)) | 0; - mid = (mid + Math.imul(al5, bh5)) | 0; - mid = (mid + Math.imul(ah5, bl5)) | 0; - hi = (hi + Math.imul(ah5, bh5)) | 0; - lo = (lo + Math.imul(al4, bl6)) | 0; - mid = (mid + Math.imul(al4, bh6)) | 0; - mid = (mid + Math.imul(ah4, bl6)) | 0; - hi = (hi + Math.imul(ah4, bh6)) | 0; - lo = (lo + Math.imul(al3, bl7)) | 0; - mid = (mid + Math.imul(al3, bh7)) | 0; - mid = (mid + Math.imul(ah3, bl7)) | 0; - hi = (hi + Math.imul(ah3, bh7)) | 0; - lo = (lo + Math.imul(al2, bl8)) | 0; - mid = (mid + Math.imul(al2, bh8)) | 0; - mid = (mid + Math.imul(ah2, bl8)) | 0; - hi = (hi + Math.imul(ah2, bh8)) | 0; - lo = (lo + Math.imul(al1, bl9)) | 0; - mid = (mid + Math.imul(al1, bh9)) | 0; - mid = (mid + Math.imul(ah1, bl9)) | 0; - hi = (hi + Math.imul(ah1, bh9)) | 0; - var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0; - w10 &= 0x3ffffff; - /* k = 11 */ - lo = Math.imul(al9, bl2); - mid = Math.imul(al9, bh2); - mid = (mid + Math.imul(ah9, bl2)) | 0; - hi = Math.imul(ah9, bh2); - lo = (lo + Math.imul(al8, bl3)) | 0; - mid = (mid + Math.imul(al8, bh3)) | 0; - mid = (mid + Math.imul(ah8, bl3)) | 0; - hi = (hi + Math.imul(ah8, bh3)) | 0; - lo = (lo + Math.imul(al7, bl4)) | 0; - mid = (mid + Math.imul(al7, bh4)) | 0; - mid = (mid + Math.imul(ah7, bl4)) | 0; - hi = (hi + Math.imul(ah7, bh4)) | 0; - lo = (lo + Math.imul(al6, bl5)) | 0; - mid = (mid + Math.imul(al6, bh5)) | 0; - mid = (mid + Math.imul(ah6, bl5)) | 0; - hi = (hi + Math.imul(ah6, bh5)) | 0; - lo = (lo + Math.imul(al5, bl6)) | 0; - mid = (mid + Math.imul(al5, bh6)) | 0; - mid = (mid + Math.imul(ah5, bl6)) | 0; - hi = (hi + Math.imul(ah5, bh6)) | 0; - lo = (lo + Math.imul(al4, bl7)) | 0; - mid = (mid + Math.imul(al4, bh7)) | 0; - mid = (mid + Math.imul(ah4, bl7)) | 0; - hi = (hi + Math.imul(ah4, bh7)) | 0; - lo = (lo + Math.imul(al3, bl8)) | 0; - mid = (mid + Math.imul(al3, bh8)) | 0; - mid = (mid + Math.imul(ah3, bl8)) | 0; - hi = (hi + Math.imul(ah3, bh8)) | 0; - lo = (lo + Math.imul(al2, bl9)) | 0; - mid = (mid + Math.imul(al2, bh9)) | 0; - mid = (mid + Math.imul(ah2, bl9)) | 0; - hi = (hi + Math.imul(ah2, bh9)) | 0; - var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0; - w11 &= 0x3ffffff; - /* k = 12 */ - lo = Math.imul(al9, bl3); - mid = Math.imul(al9, bh3); - mid = (mid + Math.imul(ah9, bl3)) | 0; - hi = Math.imul(ah9, bh3); - lo = (lo + Math.imul(al8, bl4)) | 0; - mid = (mid + Math.imul(al8, bh4)) | 0; - mid = (mid + Math.imul(ah8, bl4)) | 0; - hi = (hi + Math.imul(ah8, bh4)) | 0; - lo = (lo + Math.imul(al7, bl5)) | 0; - mid = (mid + Math.imul(al7, bh5)) | 0; - mid = (mid + Math.imul(ah7, bl5)) | 0; - hi = (hi + Math.imul(ah7, bh5)) | 0; - lo = (lo + Math.imul(al6, bl6)) | 0; - mid = (mid + Math.imul(al6, bh6)) | 0; - mid = (mid + Math.imul(ah6, bl6)) | 0; - hi = (hi + Math.imul(ah6, bh6)) | 0; - lo = (lo + Math.imul(al5, bl7)) | 0; - mid = (mid + Math.imul(al5, bh7)) | 0; - mid = (mid + Math.imul(ah5, bl7)) | 0; - hi = (hi + Math.imul(ah5, bh7)) | 0; - lo = (lo + Math.imul(al4, bl8)) | 0; - mid = (mid + Math.imul(al4, bh8)) | 0; - mid = (mid + Math.imul(ah4, bl8)) | 0; - hi = (hi + Math.imul(ah4, bh8)) | 0; - lo = (lo + Math.imul(al3, bl9)) | 0; - mid = (mid + Math.imul(al3, bh9)) | 0; - mid = (mid + Math.imul(ah3, bl9)) | 0; - hi = (hi + Math.imul(ah3, bh9)) | 0; - var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0; - w12 &= 0x3ffffff; - /* k = 13 */ - lo = Math.imul(al9, bl4); - mid = Math.imul(al9, bh4); - mid = (mid + Math.imul(ah9, bl4)) | 0; - hi = Math.imul(ah9, bh4); - lo = (lo + Math.imul(al8, bl5)) | 0; - mid = (mid + Math.imul(al8, bh5)) | 0; - mid = (mid + Math.imul(ah8, bl5)) | 0; - hi = (hi + Math.imul(ah8, bh5)) | 0; - lo = (lo + Math.imul(al7, bl6)) | 0; - mid = (mid + Math.imul(al7, bh6)) | 0; - mid = (mid + Math.imul(ah7, bl6)) | 0; - hi = (hi + Math.imul(ah7, bh6)) | 0; - lo = (lo + Math.imul(al6, bl7)) | 0; - mid = (mid + Math.imul(al6, bh7)) | 0; - mid = (mid + Math.imul(ah6, bl7)) | 0; - hi = (hi + Math.imul(ah6, bh7)) | 0; - lo = (lo + Math.imul(al5, bl8)) | 0; - mid = (mid + Math.imul(al5, bh8)) | 0; - mid = (mid + Math.imul(ah5, bl8)) | 0; - hi = (hi + Math.imul(ah5, bh8)) | 0; - lo = (lo + Math.imul(al4, bl9)) | 0; - mid = (mid + Math.imul(al4, bh9)) | 0; - mid = (mid + Math.imul(ah4, bl9)) | 0; - hi = (hi + Math.imul(ah4, bh9)) | 0; - var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0; - w13 &= 0x3ffffff; - /* k = 14 */ - lo = Math.imul(al9, bl5); - mid = Math.imul(al9, bh5); - mid = (mid + Math.imul(ah9, bl5)) | 0; - hi = Math.imul(ah9, bh5); - lo = (lo + Math.imul(al8, bl6)) | 0; - mid = (mid + Math.imul(al8, bh6)) | 0; - mid = (mid + Math.imul(ah8, bl6)) | 0; - hi = (hi + Math.imul(ah8, bh6)) | 0; - lo = (lo + Math.imul(al7, bl7)) | 0; - mid = (mid + Math.imul(al7, bh7)) | 0; - mid = (mid + Math.imul(ah7, bl7)) | 0; - hi = (hi + Math.imul(ah7, bh7)) | 0; - lo = (lo + Math.imul(al6, bl8)) | 0; - mid = (mid + Math.imul(al6, bh8)) | 0; - mid = (mid + Math.imul(ah6, bl8)) | 0; - hi = (hi + Math.imul(ah6, bh8)) | 0; - lo = (lo + Math.imul(al5, bl9)) | 0; - mid = (mid + Math.imul(al5, bh9)) | 0; - mid = (mid + Math.imul(ah5, bl9)) | 0; - hi = (hi + Math.imul(ah5, bh9)) | 0; - var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0; - w14 &= 0x3ffffff; - /* k = 15 */ - lo = Math.imul(al9, bl6); - mid = Math.imul(al9, bh6); - mid = (mid + Math.imul(ah9, bl6)) | 0; - hi = Math.imul(ah9, bh6); - lo = (lo + Math.imul(al8, bl7)) | 0; - mid = (mid + Math.imul(al8, bh7)) | 0; - mid = (mid + Math.imul(ah8, bl7)) | 0; - hi = (hi + Math.imul(ah8, bh7)) | 0; - lo = (lo + Math.imul(al7, bl8)) | 0; - mid = (mid + Math.imul(al7, bh8)) | 0; - mid = (mid + Math.imul(ah7, bl8)) | 0; - hi = (hi + Math.imul(ah7, bh8)) | 0; - lo = (lo + Math.imul(al6, bl9)) | 0; - mid = (mid + Math.imul(al6, bh9)) | 0; - mid = (mid + Math.imul(ah6, bl9)) | 0; - hi = (hi + Math.imul(ah6, bh9)) | 0; - var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0; - w15 &= 0x3ffffff; - /* k = 16 */ - lo = Math.imul(al9, bl7); - mid = Math.imul(al9, bh7); - mid = (mid + Math.imul(ah9, bl7)) | 0; - hi = Math.imul(ah9, bh7); - lo = (lo + Math.imul(al8, bl8)) | 0; - mid = (mid + Math.imul(al8, bh8)) | 0; - mid = (mid + Math.imul(ah8, bl8)) | 0; - hi = (hi + Math.imul(ah8, bh8)) | 0; - lo = (lo + Math.imul(al7, bl9)) | 0; - mid = (mid + Math.imul(al7, bh9)) | 0; - mid = (mid + Math.imul(ah7, bl9)) | 0; - hi = (hi + Math.imul(ah7, bh9)) | 0; - var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0; - w16 &= 0x3ffffff; - /* k = 17 */ - lo = Math.imul(al9, bl8); - mid = Math.imul(al9, bh8); - mid = (mid + Math.imul(ah9, bl8)) | 0; - hi = Math.imul(ah9, bh8); - lo = (lo + Math.imul(al8, bl9)) | 0; - mid = (mid + Math.imul(al8, bh9)) | 0; - mid = (mid + Math.imul(ah8, bl9)) | 0; - hi = (hi + Math.imul(ah8, bh9)) | 0; - var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0; - w17 &= 0x3ffffff; - /* k = 18 */ - lo = Math.imul(al9, bl9); - mid = Math.imul(al9, bh9); - mid = (mid + Math.imul(ah9, bl9)) | 0; - hi = Math.imul(ah9, bh9); - var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0; - w18 &= 0x3ffffff; - o[0] = w0; - o[1] = w1; - o[2] = w2; - o[3] = w3; - o[4] = w4; - o[5] = w5; - o[6] = w6; - o[7] = w7; - o[8] = w8; - o[9] = w9; - o[10] = w10; - o[11] = w11; - o[12] = w12; - o[13] = w13; - o[14] = w14; - o[15] = w15; - o[16] = w16; - o[17] = w17; - o[18] = w18; - if (c !== 0) { - o[19] = c; - out.length++; - } - return out; - }; - - // Polyfill comb - if (!Math.imul) { - comb10MulTo = smallMulTo; - } - - function bigMulTo (self, num, out) { - out.negative = num.negative ^ self.negative; - out.length = self.length + num.length; - - var carry = 0; - var hncarry = 0; - for (var k = 0; k < out.length - 1; k++) { - // Sum all words with the same `i + j = k` and accumulate `ncarry`, - // note that ncarry could be >= 0x3ffffff - var ncarry = hncarry; - hncarry = 0; - var rword = carry & 0x3ffffff; - var maxJ = Math.min(k, num.length - 1); - for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { - var i = k - j; - var a = self.words[i] | 0; - var b = num.words[j] | 0; - var r = a * b; - - var lo = r & 0x3ffffff; - ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0; - lo = (lo + rword) | 0; - rword = lo & 0x3ffffff; - ncarry = (ncarry + (lo >>> 26)) | 0; - - hncarry += ncarry >>> 26; - ncarry &= 0x3ffffff; - } - out.words[k] = rword; - carry = ncarry; - ncarry = hncarry; - } - if (carry !== 0) { - out.words[k] = carry; - } else { - out.length--; - } - - return out.strip(); - } - - function jumboMulTo (self, num, out) { - var fftm = new FFTM(); - return fftm.mulp(self, num, out); - } - - BN.prototype.mulTo = function mulTo (num, out) { - var res; - var len = this.length + num.length; - if (this.length === 10 && num.length === 10) { - res = comb10MulTo(this, num, out); - } else if (len < 63) { - res = smallMulTo(this, num, out); - } else if (len < 1024) { - res = bigMulTo(this, num, out); - } else { - res = jumboMulTo(this, num, out); - } - - return res; - }; - - // Cooley-Tukey algorithm for FFT - // slightly revisited to rely on looping instead of recursion - - function FFTM (x, y) { - this.x = x; - this.y = y; - } - - FFTM.prototype.makeRBT = function makeRBT (N) { - var t = new Array(N); - var l = BN.prototype._countBits(N) - 1; - for (var i = 0; i < N; i++) { - t[i] = this.revBin(i, l, N); - } - - return t; - }; - - // Returns binary-reversed representation of `x` - FFTM.prototype.revBin = function revBin (x, l, N) { - if (x === 0 || x === N - 1) return x; - - var rb = 0; - for (var i = 0; i < l; i++) { - rb |= (x & 1) << (l - i - 1); - x >>= 1; - } - - return rb; - }; - - // Performs "tweedling" phase, therefore 'emulating' - // behaviour of the recursive algorithm - FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) { - for (var i = 0; i < N; i++) { - rtws[i] = rws[rbt[i]]; - itws[i] = iws[rbt[i]]; - } - }; - - FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) { - this.permute(rbt, rws, iws, rtws, itws, N); - - for (var s = 1; s < N; s <<= 1) { - var l = s << 1; - - var rtwdf = Math.cos(2 * Math.PI / l); - var itwdf = Math.sin(2 * Math.PI / l); - - for (var p = 0; p < N; p += l) { - var rtwdf_ = rtwdf; - var itwdf_ = itwdf; - - for (var j = 0; j < s; j++) { - var re = rtws[p + j]; - var ie = itws[p + j]; - - var ro = rtws[p + j + s]; - var io = itws[p + j + s]; - - var rx = rtwdf_ * ro - itwdf_ * io; - - io = rtwdf_ * io + itwdf_ * ro; - ro = rx; - - rtws[p + j] = re + ro; - itws[p + j] = ie + io; - - rtws[p + j + s] = re - ro; - itws[p + j + s] = ie - io; - - /* jshint maxdepth : false */ - if (j !== l) { - rx = rtwdf * rtwdf_ - itwdf * itwdf_; - - itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_; - rtwdf_ = rx; - } - } - } - } - }; - - FFTM.prototype.guessLen13b = function guessLen13b (n, m) { - var N = Math.max(m, n) | 1; - var odd = N & 1; - var i = 0; - for (N = N / 2 | 0; N; N = N >>> 1) { - i++; - } - - return 1 << i + 1 + odd; - }; - - FFTM.prototype.conjugate = function conjugate (rws, iws, N) { - if (N <= 1) return; - - for (var i = 0; i < N / 2; i++) { - var t = rws[i]; - - rws[i] = rws[N - i - 1]; - rws[N - i - 1] = t; - - t = iws[i]; - - iws[i] = -iws[N - i - 1]; - iws[N - i - 1] = -t; - } - }; - - FFTM.prototype.normalize13b = function normalize13b (ws, N) { - var carry = 0; - for (var i = 0; i < N / 2; i++) { - var w = Math.round(ws[2 * i + 1] / N) * 0x2000 + - Math.round(ws[2 * i] / N) + - carry; - - ws[i] = w & 0x3ffffff; - - if (w < 0x4000000) { - carry = 0; - } else { - carry = w / 0x4000000 | 0; - } - } - - return ws; - }; - - FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) { - var carry = 0; - for (var i = 0; i < len; i++) { - carry = carry + (ws[i] | 0); - - rws[2 * i] = carry & 0x1fff; carry = carry >>> 13; - rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13; - } - - // Pad with zeroes - for (i = 2 * len; i < N; ++i) { - rws[i] = 0; - } - - assert(carry === 0); - assert((carry & ~0x1fff) === 0); - }; - - FFTM.prototype.stub = function stub (N) { - var ph = new Array(N); - for (var i = 0; i < N; i++) { - ph[i] = 0; - } - - return ph; - }; - - FFTM.prototype.mulp = function mulp (x, y, out) { - var N = 2 * this.guessLen13b(x.length, y.length); - - var rbt = this.makeRBT(N); - - var _ = this.stub(N); - - var rws = new Array(N); - var rwst = new Array(N); - var iwst = new Array(N); - - var nrws = new Array(N); - var nrwst = new Array(N); - var niwst = new Array(N); - - var rmws = out.words; - rmws.length = N; - - this.convert13b(x.words, x.length, rws, N); - this.convert13b(y.words, y.length, nrws, N); - - this.transform(rws, _, rwst, iwst, N, rbt); - this.transform(nrws, _, nrwst, niwst, N, rbt); - - for (var i = 0; i < N; i++) { - var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i]; - iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i]; - rwst[i] = rx; - } - - this.conjugate(rwst, iwst, N); - this.transform(rwst, iwst, rmws, _, N, rbt); - this.conjugate(rmws, _, N); - this.normalize13b(rmws, N); - - out.negative = x.negative ^ y.negative; - out.length = x.length + y.length; - return out.strip(); - }; - - // Multiply `this` by `num` - BN.prototype.mul = function mul (num) { - var out = new BN(null); - out.words = new Array(this.length + num.length); - return this.mulTo(num, out); - }; - - // Multiply employing FFT - BN.prototype.mulf = function mulf (num) { - var out = new BN(null); - out.words = new Array(this.length + num.length); - return jumboMulTo(this, num, out); - }; - - // In-place Multiplication - BN.prototype.imul = function imul (num) { - return this.clone().mulTo(num, this); - }; - - BN.prototype.imuln = function imuln (num) { - assert(typeof num === 'number'); - assert(num < 0x4000000); - - // Carry - var carry = 0; - for (var i = 0; i < this.length; i++) { - var w = (this.words[i] | 0) * num; - var lo = (w & 0x3ffffff) + (carry & 0x3ffffff); - carry >>= 26; - carry += (w / 0x4000000) | 0; - // NOTE: lo is 27bit maximum - carry += lo >>> 26; - this.words[i] = lo & 0x3ffffff; - } - - if (carry !== 0) { - this.words[i] = carry; - this.length++; - } - - return this; - }; - - BN.prototype.muln = function muln (num) { - return this.clone().imuln(num); - }; - - // `this` * `this` - BN.prototype.sqr = function sqr () { - return this.mul(this); - }; - - // `this` * `this` in-place - BN.prototype.isqr = function isqr () { - return this.imul(this.clone()); - }; - - // Math.pow(`this`, `num`) - BN.prototype.pow = function pow (num) { - var w = toBitArray(num); - if (w.length === 0) return new BN(1); - - // Skip leading zeroes - var res = this; - for (var i = 0; i < w.length; i++, res = res.sqr()) { - if (w[i] !== 0) break; - } - - if (++i < w.length) { - for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) { - if (w[i] === 0) continue; - - res = res.mul(q); - } - } - - return res; - }; - - // Shift-left in-place - BN.prototype.iushln = function iushln (bits) { - assert(typeof bits === 'number' && bits >= 0); - var r = bits % 26; - var s = (bits - r) / 26; - var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r); - var i; - - if (r !== 0) { - var carry = 0; - - for (i = 0; i < this.length; i++) { - var newCarry = this.words[i] & carryMask; - var c = ((this.words[i] | 0) - newCarry) << r; - this.words[i] = c | carry; - carry = newCarry >>> (26 - r); - } - - if (carry) { - this.words[i] = carry; - this.length++; - } - } - - if (s !== 0) { - for (i = this.length - 1; i >= 0; i--) { - this.words[i + s] = this.words[i]; - } - - for (i = 0; i < s; i++) { - this.words[i] = 0; - } - - this.length += s; - } - - return this.strip(); - }; - - BN.prototype.ishln = function ishln (bits) { - // TODO(indutny): implement me - assert(this.negative === 0); - return this.iushln(bits); - }; - - // Shift-right in-place - // NOTE: `hint` is a lowest bit before trailing zeroes - // NOTE: if `extended` is present - it will be filled with destroyed bits - BN.prototype.iushrn = function iushrn (bits, hint, extended) { - assert(typeof bits === 'number' && bits >= 0); - var h; - if (hint) { - h = (hint - (hint % 26)) / 26; - } else { - h = 0; - } - - var r = bits % 26; - var s = Math.min((bits - r) / 26, this.length); - var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); - var maskedWords = extended; - - h -= s; - h = Math.max(0, h); - - // Extended mode, copy masked part - if (maskedWords) { - for (var i = 0; i < s; i++) { - maskedWords.words[i] = this.words[i]; - } - maskedWords.length = s; - } - - if (s === 0) ; else if (this.length > s) { - this.length -= s; - for (i = 0; i < this.length; i++) { - this.words[i] = this.words[i + s]; - } - } else { - this.words[0] = 0; - this.length = 1; - } - - var carry = 0; - for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) { - var word = this.words[i] | 0; - this.words[i] = (carry << (26 - r)) | (word >>> r); - carry = word & mask; - } - - // Push carried bits as a mask - if (maskedWords && carry !== 0) { - maskedWords.words[maskedWords.length++] = carry; - } - - if (this.length === 0) { - this.words[0] = 0; - this.length = 1; - } - - return this.strip(); - }; - - BN.prototype.ishrn = function ishrn (bits, hint, extended) { - // TODO(indutny): implement me - assert(this.negative === 0); - return this.iushrn(bits, hint, extended); - }; - - // Shift-left - BN.prototype.shln = function shln (bits) { - return this.clone().ishln(bits); - }; - - BN.prototype.ushln = function ushln (bits) { - return this.clone().iushln(bits); - }; - - // Shift-right - BN.prototype.shrn = function shrn (bits) { - return this.clone().ishrn(bits); - }; - - BN.prototype.ushrn = function ushrn (bits) { - return this.clone().iushrn(bits); - }; - - // Test if n bit is set - BN.prototype.testn = function testn (bit) { - assert(typeof bit === 'number' && bit >= 0); - var r = bit % 26; - var s = (bit - r) / 26; - var q = 1 << r; - - // Fast case: bit is much higher than all existing words - if (this.length <= s) return false; - - // Check bit and return - var w = this.words[s]; - - return !!(w & q); - }; - - // Return only lowers bits of number (in-place) - BN.prototype.imaskn = function imaskn (bits) { - assert(typeof bits === 'number' && bits >= 0); - var r = bits % 26; - var s = (bits - r) / 26; - - assert(this.negative === 0, 'imaskn works only with positive numbers'); - - if (this.length <= s) { - return this; - } - - if (r !== 0) { - s++; - } - this.length = Math.min(s, this.length); - - if (r !== 0) { - var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); - this.words[this.length - 1] &= mask; - } - - return this.strip(); - }; - - // Return only lowers bits of number - BN.prototype.maskn = function maskn (bits) { - return this.clone().imaskn(bits); - }; - - // Add plain number `num` to `this` - BN.prototype.iaddn = function iaddn (num) { - assert(typeof num === 'number'); - assert(num < 0x4000000); - if (num < 0) return this.isubn(-num); - - // Possible sign change - if (this.negative !== 0) { - if (this.length === 1 && (this.words[0] | 0) < num) { - this.words[0] = num - (this.words[0] | 0); - this.negative = 0; - return this; - } - - this.negative = 0; - this.isubn(num); - this.negative = 1; - return this; - } - - // Add without checks - return this._iaddn(num); - }; - - BN.prototype._iaddn = function _iaddn (num) { - this.words[0] += num; - - // Carry - for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) { - this.words[i] -= 0x4000000; - if (i === this.length - 1) { - this.words[i + 1] = 1; - } else { - this.words[i + 1]++; - } - } - this.length = Math.max(this.length, i + 1); - - return this; - }; - - // Subtract plain number `num` from `this` - BN.prototype.isubn = function isubn (num) { - assert(typeof num === 'number'); - assert(num < 0x4000000); - if (num < 0) return this.iaddn(-num); - - if (this.negative !== 0) { - this.negative = 0; - this.iaddn(num); - this.negative = 1; - return this; - } - - this.words[0] -= num; - - if (this.length === 1 && this.words[0] < 0) { - this.words[0] = -this.words[0]; - this.negative = 1; - } else { - // Carry - for (var i = 0; i < this.length && this.words[i] < 0; i++) { - this.words[i] += 0x4000000; - this.words[i + 1] -= 1; - } - } - - return this.strip(); - }; - - BN.prototype.addn = function addn (num) { - return this.clone().iaddn(num); - }; - - BN.prototype.subn = function subn (num) { - return this.clone().isubn(num); - }; - - BN.prototype.iabs = function iabs () { - this.negative = 0; - - return this; - }; - - BN.prototype.abs = function abs () { - return this.clone().iabs(); - }; - - BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) { - var len = num.length + shift; - var i; - - this._expand(len); - - var w; - var carry = 0; - for (i = 0; i < num.length; i++) { - w = (this.words[i + shift] | 0) + carry; - var right = (num.words[i] | 0) * mul; - w -= right & 0x3ffffff; - carry = (w >> 26) - ((right / 0x4000000) | 0); - this.words[i + shift] = w & 0x3ffffff; - } - for (; i < this.length - shift; i++) { - w = (this.words[i + shift] | 0) + carry; - carry = w >> 26; - this.words[i + shift] = w & 0x3ffffff; - } - - if (carry === 0) return this.strip(); - - // Subtraction overflow - assert(carry === -1); - carry = 0; - for (i = 0; i < this.length; i++) { - w = -(this.words[i] | 0) + carry; - carry = w >> 26; - this.words[i] = w & 0x3ffffff; - } - this.negative = 1; - - return this.strip(); - }; - - BN.prototype._wordDiv = function _wordDiv (num, mode) { - var shift = this.length - num.length; - - var a = this.clone(); - var b = num; - - // Normalize - var bhi = b.words[b.length - 1] | 0; - var bhiBits = this._countBits(bhi); - shift = 26 - bhiBits; - if (shift !== 0) { - b = b.ushln(shift); - a.iushln(shift); - bhi = b.words[b.length - 1] | 0; - } - - // Initialize quotient - var m = a.length - b.length; - var q; - - if (mode !== 'mod') { - q = new BN(null); - q.length = m + 1; - q.words = new Array(q.length); - for (var i = 0; i < q.length; i++) { - q.words[i] = 0; - } - } - - var diff = a.clone()._ishlnsubmul(b, 1, m); - if (diff.negative === 0) { - a = diff; - if (q) { - q.words[m] = 1; - } - } - - for (var j = m - 1; j >= 0; j--) { - var qj = (a.words[b.length + j] | 0) * 0x4000000 + - (a.words[b.length + j - 1] | 0); - - // NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max - // (0x7ffffff) - qj = Math.min((qj / bhi) | 0, 0x3ffffff); - - a._ishlnsubmul(b, qj, j); - while (a.negative !== 0) { - qj--; - a.negative = 0; - a._ishlnsubmul(b, 1, j); - if (!a.isZero()) { - a.negative ^= 1; - } - } - if (q) { - q.words[j] = qj; - } - } - if (q) { - q.strip(); - } - a.strip(); - - // Denormalize - if (mode !== 'div' && shift !== 0) { - a.iushrn(shift); - } - - return { - div: q || null, - mod: a - }; - }; - - // NOTE: 1) `mode` can be set to `mod` to request mod only, - // to `div` to request div only, or be absent to - // request both div & mod - // 2) `positive` is true if unsigned mod is requested - BN.prototype.divmod = function divmod (num, mode, positive) { - assert(!num.isZero()); - - if (this.isZero()) { - return { - div: new BN(0), - mod: new BN(0) - }; - } - - var div, mod, res; - if (this.negative !== 0 && num.negative === 0) { - res = this.neg().divmod(num, mode); - - if (mode !== 'mod') { - div = res.div.neg(); - } - - if (mode !== 'div') { - mod = res.mod.neg(); - if (positive && mod.negative !== 0) { - mod.iadd(num); - } - } - - return { - div: div, - mod: mod - }; - } - - if (this.negative === 0 && num.negative !== 0) { - res = this.divmod(num.neg(), mode); - - if (mode !== 'mod') { - div = res.div.neg(); - } - - return { - div: div, - mod: res.mod - }; - } - - if ((this.negative & num.negative) !== 0) { - res = this.neg().divmod(num.neg(), mode); - - if (mode !== 'div') { - mod = res.mod.neg(); - if (positive && mod.negative !== 0) { - mod.isub(num); - } - } - - return { - div: res.div, - mod: mod - }; - } - - // Both numbers are positive at this point - - // Strip both numbers to approximate shift value - if (num.length > this.length || this.cmp(num) < 0) { - return { - div: new BN(0), - mod: this - }; - } - - // Very short reduction - if (num.length === 1) { - if (mode === 'div') { - return { - div: this.divn(num.words[0]), - mod: null - }; - } - - if (mode === 'mod') { - return { - div: null, - mod: new BN(this.modn(num.words[0])) - }; - } - - return { - div: this.divn(num.words[0]), - mod: new BN(this.modn(num.words[0])) - }; - } - - return this._wordDiv(num, mode); - }; - - // Find `this` / `num` - BN.prototype.div = function div (num) { - return this.divmod(num, 'div', false).div; - }; - - // Find `this` % `num` - BN.prototype.mod = function mod (num) { - return this.divmod(num, 'mod', false).mod; - }; - - BN.prototype.umod = function umod (num) { - return this.divmod(num, 'mod', true).mod; - }; - - // Find Round(`this` / `num`) - BN.prototype.divRound = function divRound (num) { - var dm = this.divmod(num); - - // Fast case - exact division - if (dm.mod.isZero()) return dm.div; - - var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod; - - var half = num.ushrn(1); - var r2 = num.andln(1); - var cmp = mod.cmp(half); - - // Round down - if (cmp < 0 || r2 === 1 && cmp === 0) return dm.div; - - // Round up - return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1); - }; - - BN.prototype.modn = function modn (num) { - assert(num <= 0x3ffffff); - var p = (1 << 26) % num; - - var acc = 0; - for (var i = this.length - 1; i >= 0; i--) { - acc = (p * acc + (this.words[i] | 0)) % num; - } - - return acc; - }; - - // In-place division by number - BN.prototype.idivn = function idivn (num) { - assert(num <= 0x3ffffff); - - var carry = 0; - for (var i = this.length - 1; i >= 0; i--) { - var w = (this.words[i] | 0) + carry * 0x4000000; - this.words[i] = (w / num) | 0; - carry = w % num; - } - - return this.strip(); - }; - - BN.prototype.divn = function divn (num) { - return this.clone().idivn(num); - }; - - BN.prototype.egcd = function egcd (p) { - assert(p.negative === 0); - assert(!p.isZero()); - - var x = this; - var y = p.clone(); - - if (x.negative !== 0) { - x = x.umod(p); - } else { - x = x.clone(); - } - - // A * x + B * y = x - var A = new BN(1); - var B = new BN(0); - - // C * x + D * y = y - var C = new BN(0); - var D = new BN(1); - - var g = 0; - - while (x.isEven() && y.isEven()) { - x.iushrn(1); - y.iushrn(1); - ++g; - } - - var yp = y.clone(); - var xp = x.clone(); - - while (!x.isZero()) { - for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1); - if (i > 0) { - x.iushrn(i); - while (i-- > 0) { - if (A.isOdd() || B.isOdd()) { - A.iadd(yp); - B.isub(xp); - } - - A.iushrn(1); - B.iushrn(1); - } - } - - for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); - if (j > 0) { - y.iushrn(j); - while (j-- > 0) { - if (C.isOdd() || D.isOdd()) { - C.iadd(yp); - D.isub(xp); - } - - C.iushrn(1); - D.iushrn(1); - } - } - - if (x.cmp(y) >= 0) { - x.isub(y); - A.isub(C); - B.isub(D); - } else { - y.isub(x); - C.isub(A); - D.isub(B); - } - } - - return { - a: C, - b: D, - gcd: y.iushln(g) - }; - }; - - // This is reduced incarnation of the binary EEA - // above, designated to invert members of the - // _prime_ fields F(p) at a maximal speed - BN.prototype._invmp = function _invmp (p) { - assert(p.negative === 0); - assert(!p.isZero()); - - var a = this; - var b = p.clone(); - - if (a.negative !== 0) { - a = a.umod(p); - } else { - a = a.clone(); - } - - var x1 = new BN(1); - var x2 = new BN(0); - - var delta = b.clone(); - - while (a.cmpn(1) > 0 && b.cmpn(1) > 0) { - for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1); - if (i > 0) { - a.iushrn(i); - while (i-- > 0) { - if (x1.isOdd()) { - x1.iadd(delta); - } - - x1.iushrn(1); - } - } - - for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); - if (j > 0) { - b.iushrn(j); - while (j-- > 0) { - if (x2.isOdd()) { - x2.iadd(delta); - } - - x2.iushrn(1); - } - } - - if (a.cmp(b) >= 0) { - a.isub(b); - x1.isub(x2); - } else { - b.isub(a); - x2.isub(x1); - } - } - - var res; - if (a.cmpn(1) === 0) { - res = x1; - } else { - res = x2; - } - - if (res.cmpn(0) < 0) { - res.iadd(p); - } - - return res; - }; - - BN.prototype.gcd = function gcd (num) { - if (this.isZero()) return num.abs(); - if (num.isZero()) return this.abs(); - - var a = this.clone(); - var b = num.clone(); - a.negative = 0; - b.negative = 0; - - // Remove common factor of two - for (var shift = 0; a.isEven() && b.isEven(); shift++) { - a.iushrn(1); - b.iushrn(1); - } - - do { - while (a.isEven()) { - a.iushrn(1); - } - while (b.isEven()) { - b.iushrn(1); - } - - var r = a.cmp(b); - if (r < 0) { - // Swap `a` and `b` to make `a` always bigger than `b` - var t = a; - a = b; - b = t; - } else if (r === 0 || b.cmpn(1) === 0) { - break; - } - - a.isub(b); - } while (true); - - return b.iushln(shift); - }; - - // Invert number in the field F(num) - BN.prototype.invm = function invm (num) { - return this.egcd(num).a.umod(num); - }; - - BN.prototype.isEven = function isEven () { - return (this.words[0] & 1) === 0; - }; - - BN.prototype.isOdd = function isOdd () { - return (this.words[0] & 1) === 1; - }; - - // And first word and num - BN.prototype.andln = function andln (num) { - return this.words[0] & num; - }; - - // Increment at the bit position in-line - BN.prototype.bincn = function bincn (bit) { - assert(typeof bit === 'number'); - var r = bit % 26; - var s = (bit - r) / 26; - var q = 1 << r; - - // Fast case: bit is much higher than all existing words - if (this.length <= s) { - this._expand(s + 1); - this.words[s] |= q; - return this; - } - - // Add bit and propagate, if needed - var carry = q; - for (var i = s; carry !== 0 && i < this.length; i++) { - var w = this.words[i] | 0; - w += carry; - carry = w >>> 26; - w &= 0x3ffffff; - this.words[i] = w; - } - if (carry !== 0) { - this.words[i] = carry; - this.length++; - } - return this; - }; - - BN.prototype.isZero = function isZero () { - return this.length === 1 && this.words[0] === 0; - }; - - BN.prototype.cmpn = function cmpn (num) { - var negative = num < 0; - - if (this.negative !== 0 && !negative) return -1; - if (this.negative === 0 && negative) return 1; - - this.strip(); - - var res; - if (this.length > 1) { - res = 1; - } else { - if (negative) { - num = -num; - } - - assert(num <= 0x3ffffff, 'Number is too big'); - - var w = this.words[0] | 0; - res = w === num ? 0 : w < num ? -1 : 1; - } - if (this.negative !== 0) return -res | 0; - return res; - }; - - // Compare two numbers and return: - // 1 - if `this` > `num` - // 0 - if `this` == `num` - // -1 - if `this` < `num` - BN.prototype.cmp = function cmp (num) { - if (this.negative !== 0 && num.negative === 0) return -1; - if (this.negative === 0 && num.negative !== 0) return 1; - - var res = this.ucmp(num); - if (this.negative !== 0) return -res | 0; - return res; - }; - - // Unsigned comparison - BN.prototype.ucmp = function ucmp (num) { - // At this point both numbers have the same sign - if (this.length > num.length) return 1; - if (this.length < num.length) return -1; - - var res = 0; - for (var i = this.length - 1; i >= 0; i--) { - var a = this.words[i] | 0; - var b = num.words[i] | 0; - - if (a === b) continue; - if (a < b) { - res = -1; - } else if (a > b) { - res = 1; - } - break; - } - return res; - }; - - BN.prototype.gtn = function gtn (num) { - return this.cmpn(num) === 1; - }; - - BN.prototype.gt = function gt (num) { - return this.cmp(num) === 1; - }; - - BN.prototype.gten = function gten (num) { - return this.cmpn(num) >= 0; - }; - - BN.prototype.gte = function gte (num) { - return this.cmp(num) >= 0; - }; - - BN.prototype.ltn = function ltn (num) { - return this.cmpn(num) === -1; - }; - - BN.prototype.lt = function lt (num) { - return this.cmp(num) === -1; - }; - - BN.prototype.lten = function lten (num) { - return this.cmpn(num) <= 0; - }; - - BN.prototype.lte = function lte (num) { - return this.cmp(num) <= 0; - }; - - BN.prototype.eqn = function eqn (num) { - return this.cmpn(num) === 0; - }; - - BN.prototype.eq = function eq (num) { - return this.cmp(num) === 0; - }; - - // - // A reduce context, could be using montgomery or something better, depending - // on the `m` itself. - // - BN.red = function red (num) { - return new Red(num); - }; - - BN.prototype.toRed = function toRed (ctx) { - assert(!this.red, 'Already a number in reduction context'); - assert(this.negative === 0, 'red works only with positives'); - return ctx.convertTo(this)._forceRed(ctx); - }; - - BN.prototype.fromRed = function fromRed () { - assert(this.red, 'fromRed works only with numbers in reduction context'); - return this.red.convertFrom(this); - }; - - BN.prototype._forceRed = function _forceRed (ctx) { - this.red = ctx; - return this; - }; - - BN.prototype.forceRed = function forceRed (ctx) { - assert(!this.red, 'Already a number in reduction context'); - return this._forceRed(ctx); - }; - - BN.prototype.redAdd = function redAdd (num) { - assert(this.red, 'redAdd works only with red numbers'); - return this.red.add(this, num); - }; - - BN.prototype.redIAdd = function redIAdd (num) { - assert(this.red, 'redIAdd works only with red numbers'); - return this.red.iadd(this, num); - }; - - BN.prototype.redSub = function redSub (num) { - assert(this.red, 'redSub works only with red numbers'); - return this.red.sub(this, num); - }; - - BN.prototype.redISub = function redISub (num) { - assert(this.red, 'redISub works only with red numbers'); - return this.red.isub(this, num); - }; - - BN.prototype.redShl = function redShl (num) { - assert(this.red, 'redShl works only with red numbers'); - return this.red.shl(this, num); - }; - - BN.prototype.redMul = function redMul (num) { - assert(this.red, 'redMul works only with red numbers'); - this.red._verify2(this, num); - return this.red.mul(this, num); - }; - - BN.prototype.redIMul = function redIMul (num) { - assert(this.red, 'redMul works only with red numbers'); - this.red._verify2(this, num); - return this.red.imul(this, num); - }; - - BN.prototype.redSqr = function redSqr () { - assert(this.red, 'redSqr works only with red numbers'); - this.red._verify1(this); - return this.red.sqr(this); - }; - - BN.prototype.redISqr = function redISqr () { - assert(this.red, 'redISqr works only with red numbers'); - this.red._verify1(this); - return this.red.isqr(this); - }; - - // Square root over p - BN.prototype.redSqrt = function redSqrt () { - assert(this.red, 'redSqrt works only with red numbers'); - this.red._verify1(this); - return this.red.sqrt(this); - }; - - BN.prototype.redInvm = function redInvm () { - assert(this.red, 'redInvm works only with red numbers'); - this.red._verify1(this); - return this.red.invm(this); - }; - - // Return negative clone of `this` % `red modulo` - BN.prototype.redNeg = function redNeg () { - assert(this.red, 'redNeg works only with red numbers'); - this.red._verify1(this); - return this.red.neg(this); - }; - - BN.prototype.redPow = function redPow (num) { - assert(this.red && !num.red, 'redPow(normalNum)'); - this.red._verify1(this); - return this.red.pow(this, num); - }; - - // Prime numbers with efficient reduction - var primes = { - k256: null, - p224: null, - p192: null, - p25519: null - }; - - // Pseudo-Mersenne prime - function MPrime (name, p) { - // P = 2 ^ N - K - this.name = name; - this.p = new BN(p, 16); - this.n = this.p.bitLength(); - this.k = new BN(1).iushln(this.n).isub(this.p); - - this.tmp = this._tmp(); - } - - MPrime.prototype._tmp = function _tmp () { - var tmp = new BN(null); - tmp.words = new Array(Math.ceil(this.n / 13)); - return tmp; - }; - - MPrime.prototype.ireduce = function ireduce (num) { - // Assumes that `num` is less than `P^2` - // num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P) - var r = num; - var rlen; - - do { - this.split(r, this.tmp); - r = this.imulK(r); - r = r.iadd(this.tmp); - rlen = r.bitLength(); - } while (rlen > this.n); - - var cmp = rlen < this.n ? -1 : r.ucmp(this.p); - if (cmp === 0) { - r.words[0] = 0; - r.length = 1; - } else if (cmp > 0) { - r.isub(this.p); - } else { - r.strip(); - } - - return r; - }; - - MPrime.prototype.split = function split (input, out) { - input.iushrn(this.n, 0, out); - }; - - MPrime.prototype.imulK = function imulK (num) { - return num.imul(this.k); - }; - - function K256 () { - MPrime.call( - this, - 'k256', - 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f'); - } - inherits(K256, MPrime); - - K256.prototype.split = function split (input, output) { - // 256 = 9 * 26 + 22 - var mask = 0x3fffff; - - var outLen = Math.min(input.length, 9); - for (var i = 0; i < outLen; i++) { - output.words[i] = input.words[i]; - } - output.length = outLen; - - if (input.length <= 9) { - input.words[0] = 0; - input.length = 1; - return; - } - - // Shift by 9 limbs - var prev = input.words[9]; - output.words[output.length++] = prev & mask; - - for (i = 10; i < input.length; i++) { - var next = input.words[i] | 0; - input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22); - prev = next; - } - prev >>>= 22; - input.words[i - 10] = prev; - if (prev === 0 && input.length > 10) { - input.length -= 10; - } else { - input.length -= 9; - } - }; - - K256.prototype.imulK = function imulK (num) { - // K = 0x1000003d1 = [ 0x40, 0x3d1 ] - num.words[num.length] = 0; - num.words[num.length + 1] = 0; - num.length += 2; - - // bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390 - var lo = 0; - for (var i = 0; i < num.length; i++) { - var w = num.words[i] | 0; - lo += w * 0x3d1; - num.words[i] = lo & 0x3ffffff; - lo = w * 0x40 + ((lo / 0x4000000) | 0); - } - - // Fast length reduction - if (num.words[num.length - 1] === 0) { - num.length--; - if (num.words[num.length - 1] === 0) { - num.length--; - } - } - return num; - }; - - function P224 () { - MPrime.call( - this, - 'p224', - 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001'); - } - inherits(P224, MPrime); - - function P192 () { - MPrime.call( - this, - 'p192', - 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff'); - } - inherits(P192, MPrime); - - function P25519 () { - // 2 ^ 255 - 19 - MPrime.call( - this, - '25519', - '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed'); - } - inherits(P25519, MPrime); - - P25519.prototype.imulK = function imulK (num) { - // K = 0x13 - var carry = 0; - for (var i = 0; i < num.length; i++) { - var hi = (num.words[i] | 0) * 0x13 + carry; - var lo = hi & 0x3ffffff; - hi >>>= 26; - - num.words[i] = lo; - carry = hi; - } - if (carry !== 0) { - num.words[num.length++] = carry; - } - return num; - }; - - // Exported mostly for testing purposes, use plain name instead - BN._prime = function prime (name) { - // Cached version of prime - if (primes[name]) return primes[name]; - - var prime; - if (name === 'k256') { - prime = new K256(); - } else if (name === 'p224') { - prime = new P224(); - } else if (name === 'p192') { - prime = new P192(); - } else if (name === 'p25519') { - prime = new P25519(); - } else { - throw new Error('Unknown prime ' + name); - } - primes[name] = prime; - - return prime; - }; - - // - // Base reduction engine - // - function Red (m) { - if (typeof m === 'string') { - var prime = BN._prime(m); - this.m = prime.p; - this.prime = prime; - } else { - assert(m.gtn(1), 'modulus must be greater than 1'); - this.m = m; - this.prime = null; - } - } - - Red.prototype._verify1 = function _verify1 (a) { - assert(a.negative === 0, 'red works only with positives'); - assert(a.red, 'red works only with red numbers'); - }; - - Red.prototype._verify2 = function _verify2 (a, b) { - assert((a.negative | b.negative) === 0, 'red works only with positives'); - assert(a.red && a.red === b.red, - 'red works only with red numbers'); - }; - - Red.prototype.imod = function imod (a) { - if (this.prime) return this.prime.ireduce(a)._forceRed(this); - return a.umod(this.m)._forceRed(this); - }; - - Red.prototype.neg = function neg (a) { - if (a.isZero()) { - return a.clone(); - } - - return this.m.sub(a)._forceRed(this); - }; - - Red.prototype.add = function add (a, b) { - this._verify2(a, b); - - var res = a.add(b); - if (res.cmp(this.m) >= 0) { - res.isub(this.m); - } - return res._forceRed(this); - }; - - Red.prototype.iadd = function iadd (a, b) { - this._verify2(a, b); - - var res = a.iadd(b); - if (res.cmp(this.m) >= 0) { - res.isub(this.m); - } - return res; - }; - - Red.prototype.sub = function sub (a, b) { - this._verify2(a, b); - - var res = a.sub(b); - if (res.cmpn(0) < 0) { - res.iadd(this.m); - } - return res._forceRed(this); - }; - - Red.prototype.isub = function isub (a, b) { - this._verify2(a, b); - - var res = a.isub(b); - if (res.cmpn(0) < 0) { - res.iadd(this.m); - } - return res; - }; - - Red.prototype.shl = function shl (a, num) { - this._verify1(a); - return this.imod(a.ushln(num)); - }; - - Red.prototype.imul = function imul (a, b) { - this._verify2(a, b); - return this.imod(a.imul(b)); - }; - - Red.prototype.mul = function mul (a, b) { - this._verify2(a, b); - return this.imod(a.mul(b)); - }; - - Red.prototype.isqr = function isqr (a) { - return this.imul(a, a.clone()); - }; - - Red.prototype.sqr = function sqr (a) { - return this.mul(a, a); - }; - - Red.prototype.sqrt = function sqrt (a) { - if (a.isZero()) return a.clone(); - - var mod3 = this.m.andln(3); - assert(mod3 % 2 === 1); - - // Fast case - if (mod3 === 3) { - var pow = this.m.add(new BN(1)).iushrn(2); - return this.pow(a, pow); - } - - // Tonelli-Shanks algorithm (Totally unoptimized and slow) - // - // Find Q and S, that Q * 2 ^ S = (P - 1) - var q = this.m.subn(1); - var s = 0; - while (!q.isZero() && q.andln(1) === 0) { - s++; - q.iushrn(1); - } - assert(!q.isZero()); - - var one = new BN(1).toRed(this); - var nOne = one.redNeg(); - - // Find quadratic non-residue - // NOTE: Max is such because of generalized Riemann hypothesis. - var lpow = this.m.subn(1).iushrn(1); - var z = this.m.bitLength(); - z = new BN(2 * z * z).toRed(this); - - while (this.pow(z, lpow).cmp(nOne) !== 0) { - z.redIAdd(nOne); - } - - var c = this.pow(z, q); - var r = this.pow(a, q.addn(1).iushrn(1)); - var t = this.pow(a, q); - var m = s; - while (t.cmp(one) !== 0) { - var tmp = t; - for (var i = 0; tmp.cmp(one) !== 0; i++) { - tmp = tmp.redSqr(); - } - assert(i < m); - var b = this.pow(c, new BN(1).iushln(m - i - 1)); - - r = r.redMul(b); - c = b.redSqr(); - t = t.redMul(c); - m = i; - } - - return r; - }; - - Red.prototype.invm = function invm (a) { - var inv = a._invmp(this.m); - if (inv.negative !== 0) { - inv.negative = 0; - return this.imod(inv).redNeg(); - } else { - return this.imod(inv); - } - }; - - Red.prototype.pow = function pow (a, num) { - if (num.isZero()) return new BN(1).toRed(this); - if (num.cmpn(1) === 0) return a.clone(); - - var windowSize = 4; - var wnd = new Array(1 << windowSize); - wnd[0] = new BN(1).toRed(this); - wnd[1] = a; - for (var i = 2; i < wnd.length; i++) { - wnd[i] = this.mul(wnd[i - 1], a); - } - - var res = wnd[0]; - var current = 0; - var currentLen = 0; - var start = num.bitLength() % 26; - if (start === 0) { - start = 26; - } - - for (i = num.length - 1; i >= 0; i--) { - var word = num.words[i]; - for (var j = start - 1; j >= 0; j--) { - var bit = (word >> j) & 1; - if (res !== wnd[0]) { - res = this.sqr(res); - } - - if (bit === 0 && current === 0) { - currentLen = 0; - continue; - } - - current <<= 1; - current |= bit; - currentLen++; - if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue; - - res = this.mul(res, wnd[current]); - currentLen = 0; - current = 0; - } - start = 26; - } - - return res; - }; - - Red.prototype.convertTo = function convertTo (num) { - var r = num.umod(this.m); - - return r === num ? r.clone() : r; - }; - - Red.prototype.convertFrom = function convertFrom (num) { - var res = num.clone(); - res.red = null; - return res; - }; - - // - // Montgomery method engine - // - - BN.mont = function mont (num) { - return new Mont(num); - }; - - function Mont (m) { - Red.call(this, m); - - this.shift = this.m.bitLength(); - if (this.shift % 26 !== 0) { - this.shift += 26 - (this.shift % 26); - } - - this.r = new BN(1).iushln(this.shift); - this.r2 = this.imod(this.r.sqr()); - this.rinv = this.r._invmp(this.m); - - this.minv = this.rinv.mul(this.r).isubn(1).div(this.m); - this.minv = this.minv.umod(this.r); - this.minv = this.r.sub(this.minv); - } - inherits(Mont, Red); - - Mont.prototype.convertTo = function convertTo (num) { - return this.imod(num.ushln(this.shift)); - }; - - Mont.prototype.convertFrom = function convertFrom (num) { - var r = this.imod(num.mul(this.rinv)); - r.red = null; - return r; - }; - - Mont.prototype.imul = function imul (a, b) { - if (a.isZero() || b.isZero()) { - a.words[0] = 0; - a.length = 1; - return a; - } - - var t = a.imul(b); - var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); - var u = t.isub(c).iushrn(this.shift); - var res = u; - - if (u.cmp(this.m) >= 0) { - res = u.isub(this.m); - } else if (u.cmpn(0) < 0) { - res = u.iadd(this.m); - } - - return res._forceRed(this); - }; - - Mont.prototype.mul = function mul (a, b) { - if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this); - - var t = a.mul(b); - var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); - var u = t.isub(c).iushrn(this.shift); - var res = u; - if (u.cmp(this.m) >= 0) { - res = u.isub(this.m); - } else if (u.cmpn(0) < 0) { - res = u.iadd(this.m); - } - - return res._forceRed(this); - }; - - Mont.prototype.invm = function invm (a) { - // (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R - var res = this.imod(a._invmp(this.m).mul(this.r2)); - return res._forceRed(this); - }; -})(module, commonjsGlobal); -}); - -var bn$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - 'default': bn, - __moduleExports: bn -}); - -/** - * @fileoverview - * BigInteger implementation of basic operations - * Wrapper of bn.js library (wwww.github.com/indutny/bn.js) - * @module biginteger/bn - * @private - */ - -/** - * @private - */ -class BigInteger$1 { - /** - * Get a BigInteger (input must be big endian for strings and arrays) - * @param {Number|String|Uint8Array} n - Value to convert - * @throws {Error} on undefined input - */ - constructor(n) { - if (n === undefined) { - throw new Error('Invalid BigInteger input'); - } - - this.value = new bn(n); - } - - clone() { - const clone = new BigInteger$1(null); - this.value.copy(clone.value); - return clone; - } - - /** - * BigInteger increment in place - */ - iinc() { - this.value.iadd(new bn(1)); - return this; - } - - /** - * BigInteger increment - * @returns {BigInteger} this + 1. - */ - inc() { - return this.clone().iinc(); - } - - /** - * BigInteger decrement in place - */ - idec() { - this.value.isub(new bn(1)); - return this; - } - - /** - * BigInteger decrement - * @returns {BigInteger} this - 1. - */ - dec() { - return this.clone().idec(); - } - - - /** - * BigInteger addition in place - * @param {BigInteger} x - Value to add - */ - iadd(x) { - this.value.iadd(x.value); - return this; - } - - /** - * BigInteger addition - * @param {BigInteger} x - Value to add - * @returns {BigInteger} this + x. - */ - add(x) { - return this.clone().iadd(x); - } - - /** - * BigInteger subtraction in place - * @param {BigInteger} x - Value to subtract - */ - isub(x) { - this.value.isub(x.value); - return this; - } - - /** - * BigInteger subtraction - * @param {BigInteger} x - Value to subtract - * @returns {BigInteger} this - x. - */ - sub(x) { - return this.clone().isub(x); - } - - /** - * BigInteger multiplication in place - * @param {BigInteger} x - Value to multiply - */ - imul(x) { - this.value.imul(x.value); - return this; - } - - /** - * BigInteger multiplication - * @param {BigInteger} x - Value to multiply - * @returns {BigInteger} this * x. - */ - mul(x) { - return this.clone().imul(x); - } - - /** - * Compute value modulo m, in place - * @param {BigInteger} m - Modulo - */ - imod(m) { - this.value = this.value.umod(m.value); - return this; - } - - /** - * Compute value modulo m - * @param {BigInteger} m - Modulo - * @returns {BigInteger} this mod m. - */ - mod(m) { - return this.clone().imod(m); - } - - /** - * Compute modular exponentiation - * Much faster than this.exp(e).mod(n) - * @param {BigInteger} e - Exponent - * @param {BigInteger} n - Modulo - * @returns {BigInteger} this ** e mod n. - */ - modExp(e, n) { - // We use either Montgomery or normal reduction context - // Montgomery requires coprime n and R (montogmery multiplier) - // bn.js picks R as power of 2, so n must be odd - const nred = n.isEven() ? bn.red(n.value) : bn.mont(n.value); - const x = this.clone(); - x.value = x.value.toRed(nred).redPow(e.value).fromRed(); - return x; - } - - /** - * Compute the inverse of this value modulo n - * Note: this and and n must be relatively prime - * @param {BigInteger} n - Modulo - * @returns {BigInteger} x such that this*x = 1 mod n - * @throws {Error} if the inverse does not exist - */ - modInv(n) { - // invm returns a wrong result if the inverse does not exist - if (!this.gcd(n).isOne()) { - throw new Error('Inverse does not exist'); - } - return new BigInteger$1(this.value.invm(n.value)); - } - - /** - * Compute greatest common divisor between this and n - * @param {BigInteger} n - Operand - * @returns {BigInteger} gcd - */ - gcd(n) { - return new BigInteger$1(this.value.gcd(n.value)); - } - - /** - * Shift this to the left by x, in place - * @param {BigInteger} x - Shift value - */ - ileftShift(x) { - this.value.ishln(x.value.toNumber()); - return this; - } - - /** - * Shift this to the left by x - * @param {BigInteger} x - Shift value - * @returns {BigInteger} this << x. - */ - leftShift(x) { - return this.clone().ileftShift(x); - } - - /** - * Shift this to the right by x, in place - * @param {BigInteger} x - Shift value - */ - irightShift(x) { - this.value.ishrn(x.value.toNumber()); - return this; - } - - /** - * Shift this to the right by x - * @param {BigInteger} x - Shift value - * @returns {BigInteger} this >> x. - */ - rightShift(x) { - return this.clone().irightShift(x); - } - - /** - * Whether this value is equal to x - * @param {BigInteger} x - * @returns {Boolean} - */ - equal(x) { - return this.value.eq(x.value); - } - - /** - * Whether this value is less than x - * @param {BigInteger} x - * @returns {Boolean} - */ - lt(x) { - return this.value.lt(x.value); - } - - /** - * Whether this value is less than or equal to x - * @param {BigInteger} x - * @returns {Boolean} - */ - lte(x) { - return this.value.lte(x.value); - } - - /** - * Whether this value is greater than x - * @param {BigInteger} x - * @returns {Boolean} - */ - gt(x) { - return this.value.gt(x.value); - } - - /** - * Whether this value is greater than or equal to x - * @param {BigInteger} x - * @returns {Boolean} - */ - gte(x) { - return this.value.gte(x.value); - } - - isZero() { - return this.value.isZero(); - } - - isOne() { - return this.value.eq(new bn(1)); - } - - isNegative() { - return this.value.isNeg(); - } - - isEven() { - return this.value.isEven(); - } - - abs() { - const res = this.clone(); - res.value = res.value.abs(); - return res; - } - - /** - * Get this value as a string - * @returns {String} this value. - */ - toString() { - return this.value.toString(); - } - - /** - * Get this value as an exact Number (max 53 bits) - * Fails if this value is too large - * @returns {Number} - */ - toNumber() { - return this.value.toNumber(); - } - - /** - * Get value of i-th bit - * @param {Number} i - Bit index - * @returns {Number} Bit value. - */ - getBit(i) { - return this.value.testn(i) ? 1 : 0; - } - - /** - * Compute bit length - * @returns {Number} Bit length. - */ - bitLength() { - return this.value.bitLength(); - } - - /** - * Compute byte length - * @returns {Number} Byte length. - */ - byteLength() { - return this.value.byteLength(); - } - - /** - * Get Uint8Array representation of this number - * @param {String} endian - Endianess of output array (defaults to 'be') - * @param {Number} length - Of output array - * @returns {Uint8Array} - */ - toUint8Array(endian = 'be', length) { - return this.value.toArrayLike(Uint8Array, endian, length); - } -} - -var bn_interface = /*#__PURE__*/Object.freeze({ - __proto__: null, - 'default': BigInteger$1 -}); - -var utils_1 = createCommonjsModule(function (module, exports) { - -var utils = exports; - -function toArray(msg, enc) { - if (Array.isArray(msg)) - return msg.slice(); - if (!msg) - return []; - var res = []; - if (typeof msg !== 'string') { - for (var i = 0; i < msg.length; i++) - res[i] = msg[i] | 0; - return res; - } - if (enc === 'hex') { - msg = msg.replace(/[^a-z0-9]+/ig, ''); - if (msg.length % 2 !== 0) - msg = '0' + msg; - for (var i = 0; i < msg.length; i += 2) - res.push(parseInt(msg[i] + msg[i + 1], 16)); - } else { - for (var i = 0; i < msg.length; i++) { - var c = msg.charCodeAt(i); - var hi = c >> 8; - var lo = c & 0xff; - if (hi) - res.push(hi, lo); - else - res.push(lo); - } - } - return res; -} -utils.toArray = toArray; - -function zero2(word) { - if (word.length === 1) - return '0' + word; - else - return word; -} -utils.zero2 = zero2; - -function toHex(msg) { - var res = ''; - for (var i = 0; i < msg.length; i++) - res += zero2(msg[i].toString(16)); - return res; -} -utils.toHex = toHex; - -utils.encode = function encode(arr, enc) { - if (enc === 'hex') - return toHex(arr); - else - return arr; -}; -}); - -var utils_1$1 = createCommonjsModule(function (module, exports) { - -var utils = exports; - - - - -utils.assert = minimalisticAssert; -utils.toArray = utils_1.toArray; -utils.zero2 = utils_1.zero2; -utils.toHex = utils_1.toHex; -utils.encode = utils_1.encode; - -// Represent num in a w-NAF form -function getNAF(num, w) { - var naf = []; - var ws = 1 << (w + 1); - var k = num.clone(); - while (k.cmpn(1) >= 0) { - var z; - if (k.isOdd()) { - var mod = k.andln(ws - 1); - if (mod > (ws >> 1) - 1) - z = (ws >> 1) - mod; - else - z = mod; - k.isubn(z); - } else { - z = 0; - } - naf.push(z); - - // Optimization, shift by word if possible - var shift = (k.cmpn(0) !== 0 && k.andln(ws - 1) === 0) ? (w + 1) : 1; - for (var i = 1; i < shift; i++) - naf.push(0); - k.iushrn(shift); - } - - return naf; -} -utils.getNAF = getNAF; - -// Represent k1, k2 in a Joint Sparse Form -function getJSF(k1, k2) { - var jsf = [ - [], - [] - ]; - - k1 = k1.clone(); - k2 = k2.clone(); - var d1 = 0; - var d2 = 0; - while (k1.cmpn(-d1) > 0 || k2.cmpn(-d2) > 0) { - - // First phase - var m14 = (k1.andln(3) + d1) & 3; - var m24 = (k2.andln(3) + d2) & 3; - if (m14 === 3) - m14 = -1; - if (m24 === 3) - m24 = -1; - var u1; - if ((m14 & 1) === 0) { - u1 = 0; - } else { - var m8 = (k1.andln(7) + d1) & 7; - if ((m8 === 3 || m8 === 5) && m24 === 2) - u1 = -m14; - else - u1 = m14; - } - jsf[0].push(u1); - - var u2; - if ((m24 & 1) === 0) { - u2 = 0; - } else { - var m8 = (k2.andln(7) + d2) & 7; - if ((m8 === 3 || m8 === 5) && m14 === 2) - u2 = -m24; - else - u2 = m24; - } - jsf[1].push(u2); - - // Second phase - if (2 * d1 === u1 + 1) - d1 = 1 - d1; - if (2 * d2 === u2 + 1) - d2 = 1 - d2; - k1.iushrn(1); - k2.iushrn(1); - } - - return jsf; -} -utils.getJSF = getJSF; - -function cachedProperty(obj, name, computer) { - var key = '_' + name; - obj.prototype[name] = function cachedProperty() { - return this[key] !== undefined ? this[key] : - this[key] = computer.call(this); - }; -} -utils.cachedProperty = cachedProperty; - -function parseBytes(bytes) { - return typeof bytes === 'string' ? utils.toArray(bytes, 'hex') : - bytes; -} -utils.parseBytes = parseBytes; - -function intFromLE(bytes) { - return new bn(bytes, 'hex', 'le'); -} -utils.intFromLE = intFromLE; -}); - -var r$1; - -var brorand = function rand(len) { - if (!r$1) - r$1 = new Rand(null); - - return r$1.generate(len); -}; - -function Rand(rand) { - this.rand = rand; -} -var Rand_1 = Rand; - -Rand.prototype.generate = function generate(len) { - return this._rand(len); -}; - -// Emulate crypto API using randy -Rand.prototype._rand = function _rand(n) { - if (this.rand.getBytes) - return this.rand.getBytes(n); - - var res = new Uint8Array(n); - for (var i = 0; i < res.length; i++) - res[i] = this.rand.getByte(); - return res; -}; - -if (typeof self === 'object') { - if (self.crypto && self.crypto.getRandomValues) { - // Modern browsers - Rand.prototype._rand = function _rand(n) { - var arr = new Uint8Array(n); - self.crypto.getRandomValues(arr); - return arr; - }; - } else if (self.msCrypto && self.msCrypto.getRandomValues) { - // IE - Rand.prototype._rand = function _rand(n) { - var arr = new Uint8Array(n); - self.msCrypto.getRandomValues(arr); - return arr; - }; - - // Safari's WebWorkers do not have `crypto` - } else if (typeof window === 'object') { - // Old junk - Rand.prototype._rand = function() { - throw new Error('Not implemented yet'); - }; - } -} else { - // Node.js or Web worker with no crypto support - try { - var crypto$2 = crypto__default['default']; - if (typeof crypto$2.randomBytes !== 'function') - throw new Error('Not supported'); - - Rand.prototype._rand = function _rand(n) { - return crypto$2.randomBytes(n); - }; - } catch (e) { - } -} -brorand.Rand = Rand_1; - -var getNAF = utils_1$1.getNAF; -var getJSF = utils_1$1.getJSF; -var assert$2 = utils_1$1.assert; - -function BaseCurve(type, conf) { - this.type = type; - this.p = new bn(conf.p, 16); - - // Use Montgomery, when there is no fast reduction for the prime - this.red = conf.prime ? bn.red(conf.prime) : bn.mont(this.p); - - // Useful for many curves - this.zero = new bn(0).toRed(this.red); - this.one = new bn(1).toRed(this.red); - this.two = new bn(2).toRed(this.red); - - // Curve configuration, optional - this.n = conf.n && new bn(conf.n, 16); - this.g = conf.g && this.pointFromJSON(conf.g, conf.gRed); - - // Temporary arrays - this._wnafT1 = new Array(4); - this._wnafT2 = new Array(4); - this._wnafT3 = new Array(4); - this._wnafT4 = new Array(4); - - // Generalized Greg Maxwell's trick - var adjustCount = this.n && this.p.div(this.n); - if (!adjustCount || adjustCount.cmpn(100) > 0) { - this.redN = null; - } else { - this._maxwellTrick = true; - this.redN = this.n.toRed(this.red); - } -} -var base = BaseCurve; - -BaseCurve.prototype.point = function point() { - throw new Error('Not implemented'); -}; - -BaseCurve.prototype.validate = function validate() { - throw new Error('Not implemented'); -}; - -BaseCurve.prototype._fixedNafMul = function _fixedNafMul(p, k) { - assert$2(p.precomputed); - var doubles = p._getDoubles(); - - var naf = getNAF(k, 1); - var I = (1 << (doubles.step + 1)) - (doubles.step % 2 === 0 ? 2 : 1); - I /= 3; - - // Translate into more windowed form - var repr = []; - for (var j = 0; j < naf.length; j += doubles.step) { - var nafW = 0; - for (var k = j + doubles.step - 1; k >= j; k--) - nafW = (nafW << 1) + naf[k]; - repr.push(nafW); - } - - var a = this.jpoint(null, null, null); - var b = this.jpoint(null, null, null); - for (var i = I; i > 0; i--) { - for (var j = 0; j < repr.length; j++) { - var nafW = repr[j]; - if (nafW === i) - b = b.mixedAdd(doubles.points[j]); - else if (nafW === -i) - b = b.mixedAdd(doubles.points[j].neg()); - } - a = a.add(b); - } - return a.toP(); -}; - -BaseCurve.prototype._wnafMul = function _wnafMul(p, k) { - var w = 4; - - // Precompute window - var nafPoints = p._getNAFPoints(w); - w = nafPoints.wnd; - var wnd = nafPoints.points; - - // Get NAF form - var naf = getNAF(k, w); - - // Add `this`*(N+1) for every w-NAF index - var acc = this.jpoint(null, null, null); - for (var i = naf.length - 1; i >= 0; i--) { - // Count zeroes - for (var k = 0; i >= 0 && naf[i] === 0; i--) - k++; - if (i >= 0) - k++; - acc = acc.dblp(k); - - if (i < 0) - break; - var z = naf[i]; - assert$2(z !== 0); - if (p.type === 'affine') { - // J +- P - if (z > 0) - acc = acc.mixedAdd(wnd[(z - 1) >> 1]); - else - acc = acc.mixedAdd(wnd[(-z - 1) >> 1].neg()); - } else { - // J +- J - if (z > 0) - acc = acc.add(wnd[(z - 1) >> 1]); - else - acc = acc.add(wnd[(-z - 1) >> 1].neg()); - } - } - return p.type === 'affine' ? acc.toP() : acc; -}; - -BaseCurve.prototype._wnafMulAdd = function _wnafMulAdd(defW, - points, - coeffs, - len, - jacobianResult) { - var wndWidth = this._wnafT1; - var wnd = this._wnafT2; - var naf = this._wnafT3; - - // Fill all arrays - var max = 0; - for (var i = 0; i < len; i++) { - var p = points[i]; - var nafPoints = p._getNAFPoints(defW); - wndWidth[i] = nafPoints.wnd; - wnd[i] = nafPoints.points; - } - - // Comb small window NAFs - for (var i = len - 1; i >= 1; i -= 2) { - var a = i - 1; - var b = i; - if (wndWidth[a] !== 1 || wndWidth[b] !== 1) { - naf[a] = getNAF(coeffs[a], wndWidth[a]); - naf[b] = getNAF(coeffs[b], wndWidth[b]); - max = Math.max(naf[a].length, max); - max = Math.max(naf[b].length, max); - continue; - } - - var comb = [ - points[a], /* 1 */ - null, /* 3 */ - null, /* 5 */ - points[b] /* 7 */ - ]; - - // Try to avoid Projective points, if possible - if (points[a].y.cmp(points[b].y) === 0) { - comb[1] = points[a].add(points[b]); - comb[2] = points[a].toJ().mixedAdd(points[b].neg()); - } else if (points[a].y.cmp(points[b].y.redNeg()) === 0) { - comb[1] = points[a].toJ().mixedAdd(points[b]); - comb[2] = points[a].add(points[b].neg()); - } else { - comb[1] = points[a].toJ().mixedAdd(points[b]); - comb[2] = points[a].toJ().mixedAdd(points[b].neg()); - } - - var index = [ - -3, /* -1 -1 */ - -1, /* -1 0 */ - -5, /* -1 1 */ - -7, /* 0 -1 */ - 0, /* 0 0 */ - 7, /* 0 1 */ - 5, /* 1 -1 */ - 1, /* 1 0 */ - 3 /* 1 1 */ - ]; - - var jsf = getJSF(coeffs[a], coeffs[b]); - max = Math.max(jsf[0].length, max); - naf[a] = new Array(max); - naf[b] = new Array(max); - for (var j = 0; j < max; j++) { - var ja = jsf[0][j] | 0; - var jb = jsf[1][j] | 0; - - naf[a][j] = index[(ja + 1) * 3 + (jb + 1)]; - naf[b][j] = 0; - wnd[a] = comb; - } - } - - var acc = this.jpoint(null, null, null); - var tmp = this._wnafT4; - for (var i = max; i >= 0; i--) { - var k = 0; - - while (i >= 0) { - var zero = true; - for (var j = 0; j < len; j++) { - tmp[j] = naf[j][i] | 0; - if (tmp[j] !== 0) - zero = false; - } - if (!zero) - break; - k++; - i--; - } - if (i >= 0) - k++; - acc = acc.dblp(k); - if (i < 0) - break; - - for (var j = 0; j < len; j++) { - var z = tmp[j]; - var p; - if (z === 0) - continue; - else if (z > 0) - p = wnd[j][(z - 1) >> 1]; - else if (z < 0) - p = wnd[j][(-z - 1) >> 1].neg(); - - if (p.type === 'affine') - acc = acc.mixedAdd(p); - else - acc = acc.add(p); - } - } - // Zeroify references - for (var i = 0; i < len; i++) - wnd[i] = null; - - if (jacobianResult) - return acc; - else - return acc.toP(); -}; - -function BasePoint(curve, type) { - this.curve = curve; - this.type = type; - this.precomputed = null; -} -BaseCurve.BasePoint = BasePoint; - -BasePoint.prototype.eq = function eq(/*other*/) { - throw new Error('Not implemented'); -}; - -BasePoint.prototype.validate = function validate() { - return this.curve.validate(this); -}; - -BaseCurve.prototype.decodePoint = function decodePoint(bytes, enc) { - bytes = utils_1$1.toArray(bytes, enc); - - var len = this.p.byteLength(); - - // uncompressed, hybrid-odd, hybrid-even - if ((bytes[0] === 0x04 || bytes[0] === 0x06 || bytes[0] === 0x07) && - bytes.length - 1 === 2 * len) { - if (bytes[0] === 0x06) - assert$2(bytes[bytes.length - 1] % 2 === 0); - else if (bytes[0] === 0x07) - assert$2(bytes[bytes.length - 1] % 2 === 1); - - var res = this.point(bytes.slice(1, 1 + len), - bytes.slice(1 + len, 1 + 2 * len)); - - return res; - } else if ((bytes[0] === 0x02 || bytes[0] === 0x03) && - bytes.length - 1 === len) { - return this.pointFromX(bytes.slice(1, 1 + len), bytes[0] === 0x03); - } - throw new Error('Unknown point format'); -}; - -BasePoint.prototype.encodeCompressed = function encodeCompressed(enc) { - return this.encode(enc, true); -}; - -BasePoint.prototype._encode = function _encode(compact) { - var len = this.curve.p.byteLength(); - var x = this.getX().toArray('be', len); - - if (compact) - return [ this.getY().isEven() ? 0x02 : 0x03 ].concat(x); - - return [ 0x04 ].concat(x, this.getY().toArray('be', len)) ; -}; - -BasePoint.prototype.encode = function encode(enc, compact) { - return utils_1$1.encode(this._encode(compact), enc); -}; - -BasePoint.prototype.precompute = function precompute(power) { - if (this.precomputed) - return this; - - var precomputed = { - doubles: null, - naf: null, - beta: null - }; - precomputed.naf = this._getNAFPoints(8); - precomputed.doubles = this._getDoubles(4, power); - precomputed.beta = this._getBeta(); - this.precomputed = precomputed; - - return this; -}; - -BasePoint.prototype._hasDoubles = function _hasDoubles(k) { - if (!this.precomputed) - return false; - - var doubles = this.precomputed.doubles; - if (!doubles) - return false; - - return doubles.points.length >= Math.ceil((k.bitLength() + 1) / doubles.step); -}; - -BasePoint.prototype._getDoubles = function _getDoubles(step, power) { - if (this.precomputed && this.precomputed.doubles) - return this.precomputed.doubles; - - var doubles = [ this ]; - var acc = this; - for (var i = 0; i < power; i += step) { - for (var j = 0; j < step; j++) - acc = acc.dbl(); - doubles.push(acc); - } - return { - step: step, - points: doubles - }; -}; - -BasePoint.prototype._getNAFPoints = function _getNAFPoints(wnd) { - if (this.precomputed && this.precomputed.naf) - return this.precomputed.naf; - - var res = [ this ]; - var max = (1 << wnd) - 1; - var dbl = max === 1 ? null : this.dbl(); - for (var i = 1; i < max; i++) - res[i] = res[i - 1].add(dbl); - return { - wnd: wnd, - points: res - }; -}; - -BasePoint.prototype._getBeta = function _getBeta() { - return null; -}; - -BasePoint.prototype.dblp = function dblp(k) { - var r = this; - for (var i = 0; i < k; i++) - r = r.dbl(); - return r; -}; - -var assert$3 = utils_1$1.assert; - -function ShortCurve(conf) { - base.call(this, 'short', conf); - - this.a = new bn(conf.a, 16).toRed(this.red); - this.b = new bn(conf.b, 16).toRed(this.red); - this.tinv = this.two.redInvm(); - - this.zeroA = this.a.fromRed().cmpn(0) === 0; - this.threeA = this.a.fromRed().sub(this.p).cmpn(-3) === 0; - - // If the curve is endomorphic, precalculate beta and lambda - this.endo = this._getEndomorphism(conf); - this._endoWnafT1 = new Array(4); - this._endoWnafT2 = new Array(4); -} -inherits(ShortCurve, base); -var short_1 = ShortCurve; - -ShortCurve.prototype._getEndomorphism = function _getEndomorphism(conf) { - // No efficient endomorphism - if (!this.zeroA || !this.g || !this.n || this.p.modn(3) !== 1) - return; - - // Compute beta and lambda, that lambda * P = (beta * Px; Py) - var beta; - var lambda; - if (conf.beta) { - beta = new bn(conf.beta, 16).toRed(this.red); - } else { - var betas = this._getEndoRoots(this.p); - // Choose the smallest beta - beta = betas[0].cmp(betas[1]) < 0 ? betas[0] : betas[1]; - beta = beta.toRed(this.red); - } - if (conf.lambda) { - lambda = new bn(conf.lambda, 16); - } else { - // Choose the lambda that is matching selected beta - var lambdas = this._getEndoRoots(this.n); - if (this.g.mul(lambdas[0]).x.cmp(this.g.x.redMul(beta)) === 0) { - lambda = lambdas[0]; - } else { - lambda = lambdas[1]; - assert$3(this.g.mul(lambda).x.cmp(this.g.x.redMul(beta)) === 0); - } - } - - // Get basis vectors, used for balanced length-two representation - var basis; - if (conf.basis) { - basis = conf.basis.map(function(vec) { - return { - a: new bn(vec.a, 16), - b: new bn(vec.b, 16) - }; - }); - } else { - basis = this._getEndoBasis(lambda); - } - - return { - beta: beta, - lambda: lambda, - basis: basis - }; -}; - -ShortCurve.prototype._getEndoRoots = function _getEndoRoots(num) { - // Find roots of for x^2 + x + 1 in F - // Root = (-1 +- Sqrt(-3)) / 2 - // - var red = num === this.p ? this.red : bn.mont(num); - var tinv = new bn(2).toRed(red).redInvm(); - var ntinv = tinv.redNeg(); - - var s = new bn(3).toRed(red).redNeg().redSqrt().redMul(tinv); - - var l1 = ntinv.redAdd(s).fromRed(); - var l2 = ntinv.redSub(s).fromRed(); - return [ l1, l2 ]; -}; - -ShortCurve.prototype._getEndoBasis = function _getEndoBasis(lambda) { - // aprxSqrt >= sqrt(this.n) - var aprxSqrt = this.n.ushrn(Math.floor(this.n.bitLength() / 2)); - - // 3.74 - // Run EGCD, until r(L + 1) < aprxSqrt - var u = lambda; - var v = this.n.clone(); - var x1 = new bn(1); - var y1 = new bn(0); - var x2 = new bn(0); - var y2 = new bn(1); - - // NOTE: all vectors are roots of: a + b * lambda = 0 (mod n) - var a0; - var b0; - // First vector - var a1; - var b1; - // Second vector - var a2; - var b2; - - var prevR; - var i = 0; - var r; - var x; - while (u.cmpn(0) !== 0) { - var q = v.div(u); - r = v.sub(q.mul(u)); - x = x2.sub(q.mul(x1)); - var y = y2.sub(q.mul(y1)); - - if (!a1 && r.cmp(aprxSqrt) < 0) { - a0 = prevR.neg(); - b0 = x1; - a1 = r.neg(); - b1 = x; - } else if (a1 && ++i === 2) { - break; - } - prevR = r; - - v = u; - u = r; - x2 = x1; - x1 = x; - y2 = y1; - y1 = y; - } - a2 = r.neg(); - b2 = x; - - var len1 = a1.sqr().add(b1.sqr()); - var len2 = a2.sqr().add(b2.sqr()); - if (len2.cmp(len1) >= 0) { - a2 = a0; - b2 = b0; - } - - // Normalize signs - if (a1.negative) { - a1 = a1.neg(); - b1 = b1.neg(); - } - if (a2.negative) { - a2 = a2.neg(); - b2 = b2.neg(); - } - - return [ - { a: a1, b: b1 }, - { a: a2, b: b2 } - ]; -}; - -ShortCurve.prototype._endoSplit = function _endoSplit(k) { - var basis = this.endo.basis; - var v1 = basis[0]; - var v2 = basis[1]; - - var c1 = v2.b.mul(k).divRound(this.n); - var c2 = v1.b.neg().mul(k).divRound(this.n); - - var p1 = c1.mul(v1.a); - var p2 = c2.mul(v2.a); - var q1 = c1.mul(v1.b); - var q2 = c2.mul(v2.b); - - // Calculate answer - var k1 = k.sub(p1).sub(p2); - var k2 = q1.add(q2).neg(); - return { k1: k1, k2: k2 }; -}; - -ShortCurve.prototype.pointFromX = function pointFromX(x, odd) { - x = new bn(x, 16); - if (!x.red) - x = x.toRed(this.red); - - var y2 = x.redSqr().redMul(x).redIAdd(x.redMul(this.a)).redIAdd(this.b); - var y = y2.redSqrt(); - if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) - throw new Error('invalid point'); - - // XXX Is there any way to tell if the number is odd without converting it - // to non-red form? - var isOdd = y.fromRed().isOdd(); - if (odd && !isOdd || !odd && isOdd) - y = y.redNeg(); - - return this.point(x, y); -}; - -ShortCurve.prototype.validate = function validate(point) { - if (point.inf) - return true; - - var x = point.x; - var y = point.y; - - var ax = this.a.redMul(x); - var rhs = x.redSqr().redMul(x).redIAdd(ax).redIAdd(this.b); - return y.redSqr().redISub(rhs).cmpn(0) === 0; -}; - -ShortCurve.prototype._endoWnafMulAdd = - function _endoWnafMulAdd(points, coeffs, jacobianResult) { - var npoints = this._endoWnafT1; - var ncoeffs = this._endoWnafT2; - for (var i = 0; i < points.length; i++) { - var split = this._endoSplit(coeffs[i]); - var p = points[i]; - var beta = p._getBeta(); - - if (split.k1.negative) { - split.k1.ineg(); - p = p.neg(true); - } - if (split.k2.negative) { - split.k2.ineg(); - beta = beta.neg(true); - } - - npoints[i * 2] = p; - npoints[i * 2 + 1] = beta; - ncoeffs[i * 2] = split.k1; - ncoeffs[i * 2 + 1] = split.k2; - } - var res = this._wnafMulAdd(1, npoints, ncoeffs, i * 2, jacobianResult); - - // Clean-up references to points and coefficients - for (var j = 0; j < i * 2; j++) { - npoints[j] = null; - ncoeffs[j] = null; - } - return res; -}; - -function Point(curve, x, y, isRed) { - base.BasePoint.call(this, curve, 'affine'); - if (x === null && y === null) { - this.x = null; - this.y = null; - this.inf = true; - } else { - this.x = new bn(x, 16); - this.y = new bn(y, 16); - // Force redgomery representation when loading from JSON - if (isRed) { - this.x.forceRed(this.curve.red); - this.y.forceRed(this.curve.red); - } - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.y.red) - this.y = this.y.toRed(this.curve.red); - this.inf = false; - } -} -inherits(Point, base.BasePoint); - -ShortCurve.prototype.point = function point(x, y, isRed) { - return new Point(this, x, y, isRed); -}; - -ShortCurve.prototype.pointFromJSON = function pointFromJSON(obj, red) { - return Point.fromJSON(this, obj, red); -}; - -Point.prototype._getBeta = function _getBeta() { - if (!this.curve.endo) - return; - - var pre = this.precomputed; - if (pre && pre.beta) - return pre.beta; - - var beta = this.curve.point(this.x.redMul(this.curve.endo.beta), this.y); - if (pre) { - var curve = this.curve; - var endoMul = function(p) { - return curve.point(p.x.redMul(curve.endo.beta), p.y); - }; - pre.beta = beta; - beta.precomputed = { - beta: null, - naf: pre.naf && { - wnd: pre.naf.wnd, - points: pre.naf.points.map(endoMul) - }, - doubles: pre.doubles && { - step: pre.doubles.step, - points: pre.doubles.points.map(endoMul) - } - }; - } - return beta; -}; - -Point.prototype.toJSON = function toJSON() { - if (!this.precomputed) - return [ this.x, this.y ]; - - return [ this.x, this.y, this.precomputed && { - doubles: this.precomputed.doubles && { - step: this.precomputed.doubles.step, - points: this.precomputed.doubles.points.slice(1) - }, - naf: this.precomputed.naf && { - wnd: this.precomputed.naf.wnd, - points: this.precomputed.naf.points.slice(1) - } - } ]; -}; - -Point.fromJSON = function fromJSON(curve, obj, red) { - if (typeof obj === 'string') - obj = JSON.parse(obj); - var res = curve.point(obj[0], obj[1], red); - if (!obj[2]) - return res; - - function obj2point(obj) { - return curve.point(obj[0], obj[1], red); - } - - var pre = obj[2]; - res.precomputed = { - beta: null, - doubles: pre.doubles && { - step: pre.doubles.step, - points: [ res ].concat(pre.doubles.points.map(obj2point)) - }, - naf: pre.naf && { - wnd: pre.naf.wnd, - points: [ res ].concat(pre.naf.points.map(obj2point)) - } - }; - return res; -}; - -Point.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; -}; - -Point.prototype.isInfinity = function isInfinity() { - return this.inf; -}; - -Point.prototype.add = function add(p) { - // O + P = P - if (this.inf) - return p; - - // P + O = P - if (p.inf) - return this; - - // P + P = 2P - if (this.eq(p)) - return this.dbl(); - - // P + (-P) = O - if (this.neg().eq(p)) - return this.curve.point(null, null); - - // P + Q = O - if (this.x.cmp(p.x) === 0) - return this.curve.point(null, null); - - var c = this.y.redSub(p.y); - if (c.cmpn(0) !== 0) - c = c.redMul(this.x.redSub(p.x).redInvm()); - var nx = c.redSqr().redISub(this.x).redISub(p.x); - var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); - return this.curve.point(nx, ny); -}; - -Point.prototype.dbl = function dbl() { - if (this.inf) - return this; - - // 2P = O - var ys1 = this.y.redAdd(this.y); - if (ys1.cmpn(0) === 0) - return this.curve.point(null, null); - - var a = this.curve.a; - - var x2 = this.x.redSqr(); - var dyinv = ys1.redInvm(); - var c = x2.redAdd(x2).redIAdd(x2).redIAdd(a).redMul(dyinv); - - var nx = c.redSqr().redISub(this.x.redAdd(this.x)); - var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); - return this.curve.point(nx, ny); -}; - -Point.prototype.getX = function getX() { - return this.x.fromRed(); -}; - -Point.prototype.getY = function getY() { - return this.y.fromRed(); -}; - -Point.prototype.mul = function mul(k) { - k = new bn(k, 16); - if (this.isInfinity()) - return this; - else if (this._hasDoubles(k)) - return this.curve._fixedNafMul(this, k); - else if (this.curve.endo) - return this.curve._endoWnafMulAdd([ this ], [ k ]); - else - return this.curve._wnafMul(this, k); -}; - -Point.prototype.mulAdd = function mulAdd(k1, p2, k2) { - var points = [ this, p2 ]; - var coeffs = [ k1, k2 ]; - if (this.curve.endo) - return this.curve._endoWnafMulAdd(points, coeffs); - else - return this.curve._wnafMulAdd(1, points, coeffs, 2); -}; - -Point.prototype.jmulAdd = function jmulAdd(k1, p2, k2) { - var points = [ this, p2 ]; - var coeffs = [ k1, k2 ]; - if (this.curve.endo) - return this.curve._endoWnafMulAdd(points, coeffs, true); - else - return this.curve._wnafMulAdd(1, points, coeffs, 2, true); -}; - -Point.prototype.eq = function eq(p) { - return this === p || - this.inf === p.inf && - (this.inf || this.x.cmp(p.x) === 0 && this.y.cmp(p.y) === 0); -}; - -Point.prototype.neg = function neg(_precompute) { - if (this.inf) - return this; - - var res = this.curve.point(this.x, this.y.redNeg()); - if (_precompute && this.precomputed) { - var pre = this.precomputed; - var negate = function(p) { - return p.neg(); - }; - res.precomputed = { - naf: pre.naf && { - wnd: pre.naf.wnd, - points: pre.naf.points.map(negate) - }, - doubles: pre.doubles && { - step: pre.doubles.step, - points: pre.doubles.points.map(negate) - } - }; - } - return res; -}; - -Point.prototype.toJ = function toJ() { - if (this.inf) - return this.curve.jpoint(null, null, null); - - var res = this.curve.jpoint(this.x, this.y, this.curve.one); - return res; -}; - -function JPoint(curve, x, y, z) { - base.BasePoint.call(this, curve, 'jacobian'); - if (x === null && y === null && z === null) { - this.x = this.curve.one; - this.y = this.curve.one; - this.z = new bn(0); - } else { - this.x = new bn(x, 16); - this.y = new bn(y, 16); - this.z = new bn(z, 16); - } - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.y.red) - this.y = this.y.toRed(this.curve.red); - if (!this.z.red) - this.z = this.z.toRed(this.curve.red); - - this.zOne = this.z === this.curve.one; -} -inherits(JPoint, base.BasePoint); - -ShortCurve.prototype.jpoint = function jpoint(x, y, z) { - return new JPoint(this, x, y, z); -}; - -JPoint.prototype.toP = function toP() { - if (this.isInfinity()) - return this.curve.point(null, null); - - var zinv = this.z.redInvm(); - var zinv2 = zinv.redSqr(); - var ax = this.x.redMul(zinv2); - var ay = this.y.redMul(zinv2).redMul(zinv); - - return this.curve.point(ax, ay); -}; - -JPoint.prototype.neg = function neg() { - return this.curve.jpoint(this.x, this.y.redNeg(), this.z); -}; - -JPoint.prototype.add = function add(p) { - // O + P = P - if (this.isInfinity()) - return p; - - // P + O = P - if (p.isInfinity()) - return this; - - // 12M + 4S + 7A - var pz2 = p.z.redSqr(); - var z2 = this.z.redSqr(); - var u1 = this.x.redMul(pz2); - var u2 = p.x.redMul(z2); - var s1 = this.y.redMul(pz2.redMul(p.z)); - var s2 = p.y.redMul(z2.redMul(this.z)); - - var h = u1.redSub(u2); - var r = s1.redSub(s2); - if (h.cmpn(0) === 0) { - if (r.cmpn(0) !== 0) - return this.curve.jpoint(null, null, null); - else - return this.dbl(); - } - - var h2 = h.redSqr(); - var h3 = h2.redMul(h); - var v = u1.redMul(h2); - - var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); - var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); - var nz = this.z.redMul(p.z).redMul(h); - - return this.curve.jpoint(nx, ny, nz); -}; - -JPoint.prototype.mixedAdd = function mixedAdd(p) { - // O + P = P - if (this.isInfinity()) - return p.toJ(); - - // P + O = P - if (p.isInfinity()) - return this; - - // 8M + 3S + 7A - var z2 = this.z.redSqr(); - var u1 = this.x; - var u2 = p.x.redMul(z2); - var s1 = this.y; - var s2 = p.y.redMul(z2).redMul(this.z); - - var h = u1.redSub(u2); - var r = s1.redSub(s2); - if (h.cmpn(0) === 0) { - if (r.cmpn(0) !== 0) - return this.curve.jpoint(null, null, null); - else - return this.dbl(); - } - - var h2 = h.redSqr(); - var h3 = h2.redMul(h); - var v = u1.redMul(h2); - - var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); - var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); - var nz = this.z.redMul(h); - - return this.curve.jpoint(nx, ny, nz); -}; - -JPoint.prototype.dblp = function dblp(pow) { - if (pow === 0) - return this; - if (this.isInfinity()) - return this; - if (!pow) - return this.dbl(); - - if (this.curve.zeroA || this.curve.threeA) { - var r = this; - for (var i = 0; i < pow; i++) - r = r.dbl(); - return r; - } - - // 1M + 2S + 1A + N * (4S + 5M + 8A) - // N = 1 => 6M + 6S + 9A - var a = this.curve.a; - var tinv = this.curve.tinv; - - var jx = this.x; - var jy = this.y; - var jz = this.z; - var jz4 = jz.redSqr().redSqr(); - - // Reuse results - var jyd = jy.redAdd(jy); - for (var i = 0; i < pow; i++) { - var jx2 = jx.redSqr(); - var jyd2 = jyd.redSqr(); - var jyd4 = jyd2.redSqr(); - var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); - - var t1 = jx.redMul(jyd2); - var nx = c.redSqr().redISub(t1.redAdd(t1)); - var t2 = t1.redISub(nx); - var dny = c.redMul(t2); - dny = dny.redIAdd(dny).redISub(jyd4); - var nz = jyd.redMul(jz); - if (i + 1 < pow) - jz4 = jz4.redMul(jyd4); - - jx = nx; - jz = nz; - jyd = dny; - } - - return this.curve.jpoint(jx, jyd.redMul(tinv), jz); -}; - -JPoint.prototype.dbl = function dbl() { - if (this.isInfinity()) - return this; - - if (this.curve.zeroA) - return this._zeroDbl(); - else if (this.curve.threeA) - return this._threeDbl(); - else - return this._dbl(); -}; - -JPoint.prototype._zeroDbl = function _zeroDbl() { - var nx; - var ny; - var nz; - // Z = 1 - if (this.zOne) { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html - // #doubling-mdbl-2007-bl - // 1M + 5S + 14A - - // XX = X1^2 - var xx = this.x.redSqr(); - // YY = Y1^2 - var yy = this.y.redSqr(); - // YYYY = YY^2 - var yyyy = yy.redSqr(); - // S = 2 * ((X1 + YY)^2 - XX - YYYY) - var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); - s = s.redIAdd(s); - // M = 3 * XX + a; a = 0 - var m = xx.redAdd(xx).redIAdd(xx); - // T = M ^ 2 - 2*S - var t = m.redSqr().redISub(s).redISub(s); - - // 8 * YYYY - var yyyy8 = yyyy.redIAdd(yyyy); - yyyy8 = yyyy8.redIAdd(yyyy8); - yyyy8 = yyyy8.redIAdd(yyyy8); - - // X3 = T - nx = t; - // Y3 = M * (S - T) - 8 * YYYY - ny = m.redMul(s.redISub(t)).redISub(yyyy8); - // Z3 = 2*Y1 - nz = this.y.redAdd(this.y); - } else { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html - // #doubling-dbl-2009-l - // 2M + 5S + 13A - - // A = X1^2 - var a = this.x.redSqr(); - // B = Y1^2 - var b = this.y.redSqr(); - // C = B^2 - var c = b.redSqr(); - // D = 2 * ((X1 + B)^2 - A - C) - var d = this.x.redAdd(b).redSqr().redISub(a).redISub(c); - d = d.redIAdd(d); - // E = 3 * A - var e = a.redAdd(a).redIAdd(a); - // F = E^2 - var f = e.redSqr(); - - // 8 * C - var c8 = c.redIAdd(c); - c8 = c8.redIAdd(c8); - c8 = c8.redIAdd(c8); - - // X3 = F - 2 * D - nx = f.redISub(d).redISub(d); - // Y3 = E * (D - X3) - 8 * C - ny = e.redMul(d.redISub(nx)).redISub(c8); - // Z3 = 2 * Y1 * Z1 - nz = this.y.redMul(this.z); - nz = nz.redIAdd(nz); - } - - return this.curve.jpoint(nx, ny, nz); -}; - -JPoint.prototype._threeDbl = function _threeDbl() { - var nx; - var ny; - var nz; - // Z = 1 - if (this.zOne) { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html - // #doubling-mdbl-2007-bl - // 1M + 5S + 15A - - // XX = X1^2 - var xx = this.x.redSqr(); - // YY = Y1^2 - var yy = this.y.redSqr(); - // YYYY = YY^2 - var yyyy = yy.redSqr(); - // S = 2 * ((X1 + YY)^2 - XX - YYYY) - var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); - s = s.redIAdd(s); - // M = 3 * XX + a - var m = xx.redAdd(xx).redIAdd(xx).redIAdd(this.curve.a); - // T = M^2 - 2 * S - var t = m.redSqr().redISub(s).redISub(s); - // X3 = T - nx = t; - // Y3 = M * (S - T) - 8 * YYYY - var yyyy8 = yyyy.redIAdd(yyyy); - yyyy8 = yyyy8.redIAdd(yyyy8); - yyyy8 = yyyy8.redIAdd(yyyy8); - ny = m.redMul(s.redISub(t)).redISub(yyyy8); - // Z3 = 2 * Y1 - nz = this.y.redAdd(this.y); - } else { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b - // 3M + 5S - - // delta = Z1^2 - var delta = this.z.redSqr(); - // gamma = Y1^2 - var gamma = this.y.redSqr(); - // beta = X1 * gamma - var beta = this.x.redMul(gamma); - // alpha = 3 * (X1 - delta) * (X1 + delta) - var alpha = this.x.redSub(delta).redMul(this.x.redAdd(delta)); - alpha = alpha.redAdd(alpha).redIAdd(alpha); - // X3 = alpha^2 - 8 * beta - var beta4 = beta.redIAdd(beta); - beta4 = beta4.redIAdd(beta4); - var beta8 = beta4.redAdd(beta4); - nx = alpha.redSqr().redISub(beta8); - // Z3 = (Y1 + Z1)^2 - gamma - delta - nz = this.y.redAdd(this.z).redSqr().redISub(gamma).redISub(delta); - // Y3 = alpha * (4 * beta - X3) - 8 * gamma^2 - var ggamma8 = gamma.redSqr(); - ggamma8 = ggamma8.redIAdd(ggamma8); - ggamma8 = ggamma8.redIAdd(ggamma8); - ggamma8 = ggamma8.redIAdd(ggamma8); - ny = alpha.redMul(beta4.redISub(nx)).redISub(ggamma8); - } - - return this.curve.jpoint(nx, ny, nz); -}; - -JPoint.prototype._dbl = function _dbl() { - var a = this.curve.a; - - // 4M + 6S + 10A - var jx = this.x; - var jy = this.y; - var jz = this.z; - var jz4 = jz.redSqr().redSqr(); - - var jx2 = jx.redSqr(); - var jy2 = jy.redSqr(); - - var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); - - var jxd4 = jx.redAdd(jx); - jxd4 = jxd4.redIAdd(jxd4); - var t1 = jxd4.redMul(jy2); - var nx = c.redSqr().redISub(t1.redAdd(t1)); - var t2 = t1.redISub(nx); - - var jyd8 = jy2.redSqr(); - jyd8 = jyd8.redIAdd(jyd8); - jyd8 = jyd8.redIAdd(jyd8); - jyd8 = jyd8.redIAdd(jyd8); - var ny = c.redMul(t2).redISub(jyd8); - var nz = jy.redAdd(jy).redMul(jz); - - return this.curve.jpoint(nx, ny, nz); -}; - -JPoint.prototype.trpl = function trpl() { - if (!this.curve.zeroA) - return this.dbl().add(this); - - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#tripling-tpl-2007-bl - // 5M + 10S + ... - - // XX = X1^2 - var xx = this.x.redSqr(); - // YY = Y1^2 - var yy = this.y.redSqr(); - // ZZ = Z1^2 - var zz = this.z.redSqr(); - // YYYY = YY^2 - var yyyy = yy.redSqr(); - // M = 3 * XX + a * ZZ2; a = 0 - var m = xx.redAdd(xx).redIAdd(xx); - // MM = M^2 - var mm = m.redSqr(); - // E = 6 * ((X1 + YY)^2 - XX - YYYY) - MM - var e = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); - e = e.redIAdd(e); - e = e.redAdd(e).redIAdd(e); - e = e.redISub(mm); - // EE = E^2 - var ee = e.redSqr(); - // T = 16*YYYY - var t = yyyy.redIAdd(yyyy); - t = t.redIAdd(t); - t = t.redIAdd(t); - t = t.redIAdd(t); - // U = (M + E)^2 - MM - EE - T - var u = m.redIAdd(e).redSqr().redISub(mm).redISub(ee).redISub(t); - // X3 = 4 * (X1 * EE - 4 * YY * U) - var yyu4 = yy.redMul(u); - yyu4 = yyu4.redIAdd(yyu4); - yyu4 = yyu4.redIAdd(yyu4); - var nx = this.x.redMul(ee).redISub(yyu4); - nx = nx.redIAdd(nx); - nx = nx.redIAdd(nx); - // Y3 = 8 * Y1 * (U * (T - U) - E * EE) - var ny = this.y.redMul(u.redMul(t.redISub(u)).redISub(e.redMul(ee))); - ny = ny.redIAdd(ny); - ny = ny.redIAdd(ny); - ny = ny.redIAdd(ny); - // Z3 = (Z1 + E)^2 - ZZ - EE - var nz = this.z.redAdd(e).redSqr().redISub(zz).redISub(ee); - - return this.curve.jpoint(nx, ny, nz); -}; - -JPoint.prototype.mul = function mul(k, kbase) { - k = new bn(k, kbase); - - return this.curve._wnafMul(this, k); -}; - -JPoint.prototype.eq = function eq(p) { - if (p.type === 'affine') - return this.eq(p.toJ()); - - if (this === p) - return true; - - // x1 * z2^2 == x2 * z1^2 - var z2 = this.z.redSqr(); - var pz2 = p.z.redSqr(); - if (this.x.redMul(pz2).redISub(p.x.redMul(z2)).cmpn(0) !== 0) - return false; - - // y1 * z2^3 == y2 * z1^3 - var z3 = z2.redMul(this.z); - var pz3 = pz2.redMul(p.z); - return this.y.redMul(pz3).redISub(p.y.redMul(z3)).cmpn(0) === 0; -}; - -JPoint.prototype.eqXToP = function eqXToP(x) { - var zs = this.z.redSqr(); - var rx = x.toRed(this.curve.red).redMul(zs); - if (this.x.cmp(rx) === 0) - return true; - - var xc = x.clone(); - var t = this.curve.redN.redMul(zs); - for (;;) { - xc.iadd(this.curve.n); - if (xc.cmp(this.curve.p) >= 0) - return false; - - rx.redIAdd(t); - if (this.x.cmp(rx) === 0) - return true; - } -}; - -JPoint.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; -}; - -JPoint.prototype.isInfinity = function isInfinity() { - // XXX This code assumes that zero is always zero in red - return this.z.cmpn(0) === 0; -}; - -function MontCurve(conf) { - base.call(this, 'mont', conf); - - this.a = new bn(conf.a, 16).toRed(this.red); - this.b = new bn(conf.b, 16).toRed(this.red); - this.i4 = new bn(4).toRed(this.red).redInvm(); - this.two = new bn(2).toRed(this.red); - // Note: this implementation is according to the original paper - // by P. Montgomery, NOT the one by D. J. Bernstein. - this.a24 = this.i4.redMul(this.a.redAdd(this.two)); -} -inherits(MontCurve, base); -var mont = MontCurve; - -MontCurve.prototype.validate = function validate(point) { - var x = point.normalize().x; - var x2 = x.redSqr(); - var rhs = x2.redMul(x).redAdd(x2.redMul(this.a)).redAdd(x); - var y = rhs.redSqrt(); - - return y.redSqr().cmp(rhs) === 0; -}; - -function Point$1(curve, x, z) { - base.BasePoint.call(this, curve, 'projective'); - if (x === null && z === null) { - this.x = this.curve.one; - this.z = this.curve.zero; - } else { - this.x = new bn(x, 16); - this.z = new bn(z, 16); - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.z.red) - this.z = this.z.toRed(this.curve.red); - } -} -inherits(Point$1, base.BasePoint); - -MontCurve.prototype.decodePoint = function decodePoint(bytes, enc) { - var bytes = utils_1$1.toArray(bytes, enc); - - // TODO Curve448 - // Montgomery curve points must be represented in the compressed format - // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B - if (bytes.length === 33 && bytes[0] === 0x40) - bytes = bytes.slice(1, 33).reverse(); // point must be little-endian - if (bytes.length !== 32) - throw new Error('Unknown point compression format'); - return this.point(bytes, 1); -}; - -MontCurve.prototype.point = function point(x, z) { - return new Point$1(this, x, z); -}; - -MontCurve.prototype.pointFromJSON = function pointFromJSON(obj) { - return Point$1.fromJSON(this, obj); -}; - -Point$1.prototype.precompute = function precompute() { - // No-op -}; - -Point$1.prototype._encode = function _encode(compact) { - var len = this.curve.p.byteLength(); - - // Note: the output should always be little-endian - // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B - if (compact) { - return [ 0x40 ].concat(this.getX().toArray('le', len)); - } else { - return this.getX().toArray('be', len); - } -}; - -Point$1.fromJSON = function fromJSON(curve, obj) { - return new Point$1(curve, obj[0], obj[1] || curve.one); -}; - -Point$1.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; -}; - -Point$1.prototype.isInfinity = function isInfinity() { - // XXX This code assumes that zero is always zero in red - return this.z.cmpn(0) === 0; -}; - -Point$1.prototype.dbl = function dbl() { - // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#doubling-dbl-1987-m-3 - // 2M + 2S + 4A - - // A = X1 + Z1 - var a = this.x.redAdd(this.z); - // AA = A^2 - var aa = a.redSqr(); - // B = X1 - Z1 - var b = this.x.redSub(this.z); - // BB = B^2 - var bb = b.redSqr(); - // C = AA - BB - var c = aa.redSub(bb); - // X3 = AA * BB - var nx = aa.redMul(bb); - // Z3 = C * (BB + A24 * C) - var nz = c.redMul(bb.redAdd(this.curve.a24.redMul(c))); - return this.curve.point(nx, nz); -}; - -Point$1.prototype.add = function add() { - throw new Error('Not supported on Montgomery curve'); -}; - -Point$1.prototype.diffAdd = function diffAdd(p, diff) { - // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#diffadd-dadd-1987-m-3 - // 4M + 2S + 6A - - // A = X2 + Z2 - var a = this.x.redAdd(this.z); - // B = X2 - Z2 - var b = this.x.redSub(this.z); - // C = X3 + Z3 - var c = p.x.redAdd(p.z); - // D = X3 - Z3 - var d = p.x.redSub(p.z); - // DA = D * A - var da = d.redMul(a); - // CB = C * B - var cb = c.redMul(b); - // X5 = Z1 * (DA + CB)^2 - var nx = diff.z.redMul(da.redAdd(cb).redSqr()); - // Z5 = X1 * (DA - CB)^2 - var nz = diff.x.redMul(da.redISub(cb).redSqr()); - return this.curve.point(nx, nz); -}; - -Point$1.prototype.mul = function mul(k) { - k = new bn(k, 16); - - var t = k.clone(); - var a = this; // (N / 2) * Q + Q - var b = this.curve.point(null, null); // (N / 2) * Q - var c = this; // Q - - for (var bits = []; t.cmpn(0) !== 0; t.iushrn(1)) - bits.push(t.andln(1)); - - for (var i = bits.length - 1; i >= 0; i--) { - if (bits[i] === 0) { - // N * Q + Q = ((N / 2) * Q + Q)) + (N / 2) * Q - a = a.diffAdd(b, c); - // N * Q = 2 * ((N / 2) * Q + Q)) - b = b.dbl(); - } else { - // N * Q = ((N / 2) * Q + Q) + ((N / 2) * Q) - b = a.diffAdd(b, c); - // N * Q + Q = 2 * ((N / 2) * Q + Q) - a = a.dbl(); - } - } - return b; -}; - -Point$1.prototype.mulAdd = function mulAdd() { - throw new Error('Not supported on Montgomery curve'); -}; - -Point$1.prototype.jumlAdd = function jumlAdd() { - throw new Error('Not supported on Montgomery curve'); -}; - -Point$1.prototype.eq = function eq(other) { - return this.getX().cmp(other.getX()) === 0; -}; - -Point$1.prototype.normalize = function normalize() { - this.x = this.x.redMul(this.z.redInvm()); - this.z = this.curve.one; - return this; -}; - -Point$1.prototype.getX = function getX() { - // Normalize coordinates - this.normalize(); - - return this.x.fromRed(); -}; - -var assert$4 = utils_1$1.assert; - -function EdwardsCurve(conf) { - // NOTE: Important as we are creating point in Base.call() - this.twisted = (conf.a | 0) !== 1; - this.mOneA = this.twisted && (conf.a | 0) === -1; - this.extended = this.mOneA; - - base.call(this, 'edwards', conf); - - this.a = new bn(conf.a, 16).umod(this.red.m); - this.a = this.a.toRed(this.red); - this.c = new bn(conf.c, 16).toRed(this.red); - this.c2 = this.c.redSqr(); - this.d = new bn(conf.d, 16).toRed(this.red); - this.dd = this.d.redAdd(this.d); - - assert$4(!this.twisted || this.c.fromRed().cmpn(1) === 0); - this.oneC = (conf.c | 0) === 1; -} -inherits(EdwardsCurve, base); -var edwards = EdwardsCurve; - -EdwardsCurve.prototype._mulA = function _mulA(num) { - if (this.mOneA) - return num.redNeg(); - else - return this.a.redMul(num); -}; - -EdwardsCurve.prototype._mulC = function _mulC(num) { - if (this.oneC) - return num; - else - return this.c.redMul(num); -}; - -// Just for compatibility with Short curve -EdwardsCurve.prototype.jpoint = function jpoint(x, y, z, t) { - return this.point(x, y, z, t); -}; - -EdwardsCurve.prototype.pointFromX = function pointFromX(x, odd) { - x = new bn(x, 16); - if (!x.red) - x = x.toRed(this.red); - - var x2 = x.redSqr(); - var rhs = this.c2.redSub(this.a.redMul(x2)); - var lhs = this.one.redSub(this.c2.redMul(this.d).redMul(x2)); - - var y2 = rhs.redMul(lhs.redInvm()); - var y = y2.redSqrt(); - if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) - throw new Error('invalid point'); - - var isOdd = y.fromRed().isOdd(); - if (odd && !isOdd || !odd && isOdd) - y = y.redNeg(); - - return this.point(x, y); -}; - -EdwardsCurve.prototype.pointFromY = function pointFromY(y, odd) { - y = new bn(y, 16); - if (!y.red) - y = y.toRed(this.red); - - // x^2 = (y^2 - c^2) / (c^2 d y^2 - a) - var y2 = y.redSqr(); - var lhs = y2.redSub(this.c2); - var rhs = y2.redMul(this.d).redMul(this.c2).redSub(this.a); - var x2 = lhs.redMul(rhs.redInvm()); - - if (x2.cmp(this.zero) === 0) { - if (odd) - throw new Error('invalid point'); - else - return this.point(this.zero, y); - } - - var x = x2.redSqrt(); - if (x.redSqr().redSub(x2).cmp(this.zero) !== 0) - throw new Error('invalid point'); - - if (x.fromRed().isOdd() !== odd) - x = x.redNeg(); - - return this.point(x, y); -}; - -EdwardsCurve.prototype.validate = function validate(point) { - if (point.isInfinity()) - return true; - - // Curve: A * X^2 + Y^2 = C^2 * (1 + D * X^2 * Y^2) - point.normalize(); - - var x2 = point.x.redSqr(); - var y2 = point.y.redSqr(); - var lhs = x2.redMul(this.a).redAdd(y2); - var rhs = this.c2.redMul(this.one.redAdd(this.d.redMul(x2).redMul(y2))); - - return lhs.cmp(rhs) === 0; -}; - -function Point$2(curve, x, y, z, t) { - base.BasePoint.call(this, curve, 'projective'); - if (x === null && y === null && z === null) { - this.x = this.curve.zero; - this.y = this.curve.one; - this.z = this.curve.one; - this.t = this.curve.zero; - this.zOne = true; - } else { - this.x = new bn(x, 16); - this.y = new bn(y, 16); - this.z = z ? new bn(z, 16) : this.curve.one; - this.t = t && new bn(t, 16); - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.y.red) - this.y = this.y.toRed(this.curve.red); - if (!this.z.red) - this.z = this.z.toRed(this.curve.red); - if (this.t && !this.t.red) - this.t = this.t.toRed(this.curve.red); - this.zOne = this.z === this.curve.one; - - // Use extended coordinates - if (this.curve.extended && !this.t) { - this.t = this.x.redMul(this.y); - if (!this.zOne) - this.t = this.t.redMul(this.z.redInvm()); - } - } -} -inherits(Point$2, base.BasePoint); - -EdwardsCurve.prototype.pointFromJSON = function pointFromJSON(obj) { - return Point$2.fromJSON(this, obj); -}; - -EdwardsCurve.prototype.point = function point(x, y, z, t) { - return new Point$2(this, x, y, z, t); -}; - -Point$2.fromJSON = function fromJSON(curve, obj) { - return new Point$2(curve, obj[0], obj[1], obj[2]); -}; - -Point$2.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; -}; - -Point$2.prototype.isInfinity = function isInfinity() { - // XXX This code assumes that zero is always zero in red - return this.x.cmpn(0) === 0 && - (this.y.cmp(this.z) === 0 || - (this.zOne && this.y.cmp(this.curve.c) === 0)); -}; - -Point$2.prototype._extDbl = function _extDbl() { - // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html - // #doubling-dbl-2008-hwcd - // 4M + 4S - - // A = X1^2 - var a = this.x.redSqr(); - // B = Y1^2 - var b = this.y.redSqr(); - // C = 2 * Z1^2 - var c = this.z.redSqr(); - c = c.redIAdd(c); - // D = a * A - var d = this.curve._mulA(a); - // E = (X1 + Y1)^2 - A - B - var e = this.x.redAdd(this.y).redSqr().redISub(a).redISub(b); - // G = D + B - var g = d.redAdd(b); - // F = G - C - var f = g.redSub(c); - // H = D - B - var h = d.redSub(b); - // X3 = E * F - var nx = e.redMul(f); - // Y3 = G * H - var ny = g.redMul(h); - // T3 = E * H - var nt = e.redMul(h); - // Z3 = F * G - var nz = f.redMul(g); - return this.curve.point(nx, ny, nz, nt); -}; - -Point$2.prototype._projDbl = function _projDbl() { - // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html - // #doubling-dbl-2008-bbjlp - // #doubling-dbl-2007-bl - // and others - // Generally 3M + 4S or 2M + 4S - - // B = (X1 + Y1)^2 - var b = this.x.redAdd(this.y).redSqr(); - // C = X1^2 - var c = this.x.redSqr(); - // D = Y1^2 - var d = this.y.redSqr(); - - var nx; - var ny; - var nz; - if (this.curve.twisted) { - // E = a * C - var e = this.curve._mulA(c); - // F = E + D - var f = e.redAdd(d); - if (this.zOne) { - // X3 = (B - C - D) * (F - 2) - nx = b.redSub(c).redSub(d).redMul(f.redSub(this.curve.two)); - // Y3 = F * (E - D) - ny = f.redMul(e.redSub(d)); - // Z3 = F^2 - 2 * F - nz = f.redSqr().redSub(f).redSub(f); - } else { - // H = Z1^2 - var h = this.z.redSqr(); - // J = F - 2 * H - var j = f.redSub(h).redISub(h); - // X3 = (B-C-D)*J - nx = b.redSub(c).redISub(d).redMul(j); - // Y3 = F * (E - D) - ny = f.redMul(e.redSub(d)); - // Z3 = F * J - nz = f.redMul(j); - } - } else { - // E = C + D - var e = c.redAdd(d); - // H = (c * Z1)^2 - var h = this.curve._mulC(this.z).redSqr(); - // J = E - 2 * H - var j = e.redSub(h).redSub(h); - // X3 = c * (B - E) * J - nx = this.curve._mulC(b.redISub(e)).redMul(j); - // Y3 = c * E * (C - D) - ny = this.curve._mulC(e).redMul(c.redISub(d)); - // Z3 = E * J - nz = e.redMul(j); - } - return this.curve.point(nx, ny, nz); -}; - -Point$2.prototype.dbl = function dbl() { - if (this.isInfinity()) - return this; - - // Double in extended coordinates - if (this.curve.extended) - return this._extDbl(); - else - return this._projDbl(); -}; - -Point$2.prototype._extAdd = function _extAdd(p) { - // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html - // #addition-add-2008-hwcd-3 - // 8M - - // A = (Y1 - X1) * (Y2 - X2) - var a = this.y.redSub(this.x).redMul(p.y.redSub(p.x)); - // B = (Y1 + X1) * (Y2 + X2) - var b = this.y.redAdd(this.x).redMul(p.y.redAdd(p.x)); - // C = T1 * k * T2 - var c = this.t.redMul(this.curve.dd).redMul(p.t); - // D = Z1 * 2 * Z2 - var d = this.z.redMul(p.z.redAdd(p.z)); - // E = B - A - var e = b.redSub(a); - // F = D - C - var f = d.redSub(c); - // G = D + C - var g = d.redAdd(c); - // H = B + A - var h = b.redAdd(a); - // X3 = E * F - var nx = e.redMul(f); - // Y3 = G * H - var ny = g.redMul(h); - // T3 = E * H - var nt = e.redMul(h); - // Z3 = F * G - var nz = f.redMul(g); - return this.curve.point(nx, ny, nz, nt); -}; - -Point$2.prototype._projAdd = function _projAdd(p) { - // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html - // #addition-add-2008-bbjlp - // #addition-add-2007-bl - // 10M + 1S - - // A = Z1 * Z2 - var a = this.z.redMul(p.z); - // B = A^2 - var b = a.redSqr(); - // C = X1 * X2 - var c = this.x.redMul(p.x); - // D = Y1 * Y2 - var d = this.y.redMul(p.y); - // E = d * C * D - var e = this.curve.d.redMul(c).redMul(d); - // F = B - E - var f = b.redSub(e); - // G = B + E - var g = b.redAdd(e); - // X3 = A * F * ((X1 + Y1) * (X2 + Y2) - C - D) - var tmp = this.x.redAdd(this.y).redMul(p.x.redAdd(p.y)).redISub(c).redISub(d); - var nx = a.redMul(f).redMul(tmp); - var ny; - var nz; - if (this.curve.twisted) { - // Y3 = A * G * (D - a * C) - ny = a.redMul(g).redMul(d.redSub(this.curve._mulA(c))); - // Z3 = F * G - nz = f.redMul(g); - } else { - // Y3 = A * G * (D - C) - ny = a.redMul(g).redMul(d.redSub(c)); - // Z3 = c * F * G - nz = this.curve._mulC(f).redMul(g); - } - return this.curve.point(nx, ny, nz); -}; - -Point$2.prototype.add = function add(p) { - if (this.isInfinity()) - return p; - if (p.isInfinity()) - return this; - - if (this.curve.extended) - return this._extAdd(p); - else - return this._projAdd(p); -}; - -Point$2.prototype.mul = function mul(k) { - if (this._hasDoubles(k)) - return this.curve._fixedNafMul(this, k); - else - return this.curve._wnafMul(this, k); -}; - -Point$2.prototype.mulAdd = function mulAdd(k1, p, k2) { - return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, false); -}; - -Point$2.prototype.jmulAdd = function jmulAdd(k1, p, k2) { - return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, true); -}; - -Point$2.prototype.normalize = function normalize() { - if (this.zOne) - return this; - - // Normalize coordinates - var zi = this.z.redInvm(); - this.x = this.x.redMul(zi); - this.y = this.y.redMul(zi); - if (this.t) - this.t = this.t.redMul(zi); - this.z = this.curve.one; - this.zOne = true; - return this; -}; - -Point$2.prototype.neg = function neg() { - return this.curve.point(this.x.redNeg(), - this.y, - this.z, - this.t && this.t.redNeg()); -}; - -Point$2.prototype.getX = function getX() { - this.normalize(); - return this.x.fromRed(); -}; - -Point$2.prototype.getY = function getY() { - this.normalize(); - return this.y.fromRed(); -}; - -Point$2.prototype.eq = function eq(other) { - return this === other || - this.getX().cmp(other.getX()) === 0 && - this.getY().cmp(other.getY()) === 0; -}; - -Point$2.prototype.eqXToP = function eqXToP(x) { - var rx = x.toRed(this.curve.red).redMul(this.z); - if (this.x.cmp(rx) === 0) - return true; - - var xc = x.clone(); - var t = this.curve.redN.redMul(this.z); - for (;;) { - xc.iadd(this.curve.n); - if (xc.cmp(this.curve.p) >= 0) - return false; - - rx.redIAdd(t); - if (this.x.cmp(rx) === 0) - return true; - } -}; - -// Compatibility with BaseCurve -Point$2.prototype.toP = Point$2.prototype.normalize; -Point$2.prototype.mixedAdd = Point$2.prototype.add; - -var curve_1 = createCommonjsModule(function (module, exports) { - -var curve = exports; - -curve.base = base; -curve.short = short_1; -curve.mont = mont; -curve.edwards = edwards; -}); - -var rotl32$2 = utils.rotl32; -var sum32$3 = utils.sum32; -var sum32_5$2 = utils.sum32_5; -var ft_1$1 = common$1.ft_1; -var BlockHash$4 = common.BlockHash; - -var sha1_K = [ - 0x5A827999, 0x6ED9EBA1, - 0x8F1BBCDC, 0xCA62C1D6 -]; - -function SHA1() { - if (!(this instanceof SHA1)) - return new SHA1(); - - BlockHash$4.call(this); - this.h = [ - 0x67452301, 0xefcdab89, 0x98badcfe, - 0x10325476, 0xc3d2e1f0 ]; - this.W = new Array(80); -} - -utils.inherits(SHA1, BlockHash$4); -var _1 = SHA1; - -SHA1.blockSize = 512; -SHA1.outSize = 160; -SHA1.hmacStrength = 80; -SHA1.padLength = 64; - -SHA1.prototype._update = function _update(msg, start) { - var W = this.W; - - for (var i = 0; i < 16; i++) - W[i] = msg[start + i]; - - for(; i < W.length; i++) - W[i] = rotl32$2(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1); - - var a = this.h[0]; - var b = this.h[1]; - var c = this.h[2]; - var d = this.h[3]; - var e = this.h[4]; - - for (i = 0; i < W.length; i++) { - var s = ~~(i / 20); - var t = sum32_5$2(rotl32$2(a, 5), ft_1$1(s, b, c, d), e, W[i], sha1_K[s]); - e = d; - d = c; - c = rotl32$2(b, 30); - b = a; - a = t; - } - - this.h[0] = sum32$3(this.h[0], a); - this.h[1] = sum32$3(this.h[1], b); - this.h[2] = sum32$3(this.h[2], c); - this.h[3] = sum32$3(this.h[3], d); - this.h[4] = sum32$3(this.h[4], e); -}; - -SHA1.prototype._digest = function digest(enc) { - if (enc === 'hex') - return utils.toHex32(this.h, 'big'); - else - return utils.split32(this.h, 'big'); -}; - -var sha1 = _1; -var sha224 = _224; -var sha256 = _256; -var sha384 = _384; -var sha512 = _512; - -var sha = { - sha1: sha1, - sha224: sha224, - sha256: sha256, - sha384: sha384, - sha512: sha512 -}; - -function Hmac(hash, key, enc) { - if (!(this instanceof Hmac)) - return new Hmac(hash, key, enc); - this.Hash = hash; - this.blockSize = hash.blockSize / 8; - this.outSize = hash.outSize / 8; - this.inner = null; - this.outer = null; - - this._init(utils.toArray(key, enc)); -} -var hmac = Hmac; - -Hmac.prototype._init = function init(key) { - // Shorten key, if needed - if (key.length > this.blockSize) - key = new this.Hash().update(key).digest(); - minimalisticAssert(key.length <= this.blockSize); - - // Add padding to key - for (var i = key.length; i < this.blockSize; i++) - key.push(0); - - for (i = 0; i < key.length; i++) - key[i] ^= 0x36; - this.inner = new this.Hash().update(key); - - // 0x36 ^ 0x5c = 0x6a - for (i = 0; i < key.length; i++) - key[i] ^= 0x6a; - this.outer = new this.Hash().update(key); -}; - -Hmac.prototype.update = function update(msg, enc) { - this.inner.update(msg, enc); - return this; -}; - -Hmac.prototype.digest = function digest(enc) { - this.outer.update(this.inner.digest()); - return this.outer.digest(enc); -}; - -var hash_1 = createCommonjsModule(function (module, exports) { -var hash = exports; - -hash.utils = utils; -hash.common = common; -hash.sha = sha; -hash.ripemd = ripemd; -hash.hmac = hmac; - -// Proxy hash functions to the main object -hash.sha1 = hash.sha.sha1; -hash.sha256 = hash.sha.sha256; -hash.sha224 = hash.sha.sha224; -hash.sha384 = hash.sha.sha384; -hash.sha512 = hash.sha.sha512; -hash.ripemd160 = hash.ripemd.ripemd160; -}); - -var secp256k1 = { - doubles: { - step: 4, - points: [ - [ - 'e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a', - 'f7e3507399e595929db99f34f57937101296891e44d23f0be1f32cce69616821' - ], - [ - '8282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508', - '11f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf' - ], - [ - '175e159f728b865a72f99cc6c6fc846de0b93833fd2222ed73fce5b551e5b739', - 'd3506e0d9e3c79eba4ef97a51ff71f5eacb5955add24345c6efa6ffee9fed695' - ], - [ - '363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640', - '4e273adfc732221953b445397f3363145b9a89008199ecb62003c7f3bee9de9' - ], - [ - '8b4b5f165df3c2be8c6244b5b745638843e4a781a15bcd1b69f79a55dffdf80c', - '4aad0a6f68d308b4b3fbd7813ab0da04f9e336546162ee56b3eff0c65fd4fd36' - ], - [ - '723cbaa6e5db996d6bf771c00bd548c7b700dbffa6c0e77bcb6115925232fcda', - '96e867b5595cc498a921137488824d6e2660a0653779494801dc069d9eb39f5f' - ], - [ - 'eebfa4d493bebf98ba5feec812c2d3b50947961237a919839a533eca0e7dd7fa', - '5d9a8ca3970ef0f269ee7edaf178089d9ae4cdc3a711f712ddfd4fdae1de8999' - ], - [ - '100f44da696e71672791d0a09b7bde459f1215a29b3c03bfefd7835b39a48db0', - 'cdd9e13192a00b772ec8f3300c090666b7ff4a18ff5195ac0fbd5cd62bc65a09' - ], - [ - 'e1031be262c7ed1b1dc9227a4a04c017a77f8d4464f3b3852c8acde6e534fd2d', - '9d7061928940405e6bb6a4176597535af292dd419e1ced79a44f18f29456a00d' - ], - [ - 'feea6cae46d55b530ac2839f143bd7ec5cf8b266a41d6af52d5e688d9094696d', - 'e57c6b6c97dce1bab06e4e12bf3ecd5c981c8957cc41442d3155debf18090088' - ], - [ - 'da67a91d91049cdcb367be4be6ffca3cfeed657d808583de33fa978bc1ec6cb1', - '9bacaa35481642bc41f463f7ec9780e5dec7adc508f740a17e9ea8e27a68be1d' - ], - [ - '53904faa0b334cdda6e000935ef22151ec08d0f7bb11069f57545ccc1a37b7c0', - '5bc087d0bc80106d88c9eccac20d3c1c13999981e14434699dcb096b022771c8' - ], - [ - '8e7bcd0bd35983a7719cca7764ca906779b53a043a9b8bcaeff959f43ad86047', - '10b7770b2a3da4b3940310420ca9514579e88e2e47fd68b3ea10047e8460372a' - ], - [ - '385eed34c1cdff21e6d0818689b81bde71a7f4f18397e6690a841e1599c43862', - '283bebc3e8ea23f56701de19e9ebf4576b304eec2086dc8cc0458fe5542e5453' - ], - [ - '6f9d9b803ecf191637c73a4413dfa180fddf84a5947fbc9c606ed86c3fac3a7', - '7c80c68e603059ba69b8e2a30e45c4d47ea4dd2f5c281002d86890603a842160' - ], - [ - '3322d401243c4e2582a2147c104d6ecbf774d163db0f5e5313b7e0e742d0e6bd', - '56e70797e9664ef5bfb019bc4ddaf9b72805f63ea2873af624f3a2e96c28b2a0' - ], - [ - '85672c7d2de0b7da2bd1770d89665868741b3f9af7643397721d74d28134ab83', - '7c481b9b5b43b2eb6374049bfa62c2e5e77f17fcc5298f44c8e3094f790313a6' - ], - [ - '948bf809b1988a46b06c9f1919413b10f9226c60f668832ffd959af60c82a0a', - '53a562856dcb6646dc6b74c5d1c3418c6d4dff08c97cd2bed4cb7f88d8c8e589' - ], - [ - '6260ce7f461801c34f067ce0f02873a8f1b0e44dfc69752accecd819f38fd8e8', - 'bc2da82b6fa5b571a7f09049776a1ef7ecd292238051c198c1a84e95b2b4ae17' - ], - [ - 'e5037de0afc1d8d43d8348414bbf4103043ec8f575bfdc432953cc8d2037fa2d', - '4571534baa94d3b5f9f98d09fb990bddbd5f5b03ec481f10e0e5dc841d755bda' - ], - [ - 'e06372b0f4a207adf5ea905e8f1771b4e7e8dbd1c6a6c5b725866a0ae4fce725', - '7a908974bce18cfe12a27bb2ad5a488cd7484a7787104870b27034f94eee31dd' - ], - [ - '213c7a715cd5d45358d0bbf9dc0ce02204b10bdde2a3f58540ad6908d0559754', - '4b6dad0b5ae462507013ad06245ba190bb4850f5f36a7eeddff2c27534b458f2' - ], - [ - '4e7c272a7af4b34e8dbb9352a5419a87e2838c70adc62cddf0cc3a3b08fbd53c', - '17749c766c9d0b18e16fd09f6def681b530b9614bff7dd33e0b3941817dcaae6' - ], - [ - 'fea74e3dbe778b1b10f238ad61686aa5c76e3db2be43057632427e2840fb27b6', - '6e0568db9b0b13297cf674deccb6af93126b596b973f7b77701d3db7f23cb96f' - ], - [ - '76e64113f677cf0e10a2570d599968d31544e179b760432952c02a4417bdde39', - 'c90ddf8dee4e95cf577066d70681f0d35e2a33d2b56d2032b4b1752d1901ac01' - ], - [ - 'c738c56b03b2abe1e8281baa743f8f9a8f7cc643df26cbee3ab150242bcbb891', - '893fb578951ad2537f718f2eacbfbbbb82314eef7880cfe917e735d9699a84c3' - ], - [ - 'd895626548b65b81e264c7637c972877d1d72e5f3a925014372e9f6588f6c14b', - 'febfaa38f2bc7eae728ec60818c340eb03428d632bb067e179363ed75d7d991f' - ], - [ - 'b8da94032a957518eb0f6433571e8761ceffc73693e84edd49150a564f676e03', - '2804dfa44805a1e4d7c99cc9762808b092cc584d95ff3b511488e4e74efdf6e7' - ], - [ - 'e80fea14441fb33a7d8adab9475d7fab2019effb5156a792f1a11778e3c0df5d', - 'eed1de7f638e00771e89768ca3ca94472d155e80af322ea9fcb4291b6ac9ec78' - ], - [ - 'a301697bdfcd704313ba48e51d567543f2a182031efd6915ddc07bbcc4e16070', - '7370f91cfb67e4f5081809fa25d40f9b1735dbf7c0a11a130c0d1a041e177ea1' - ], - [ - '90ad85b389d6b936463f9d0512678de208cc330b11307fffab7ac63e3fb04ed4', - 'e507a3620a38261affdcbd9427222b839aefabe1582894d991d4d48cb6ef150' - ], - [ - '8f68b9d2f63b5f339239c1ad981f162ee88c5678723ea3351b7b444c9ec4c0da', - '662a9f2dba063986de1d90c2b6be215dbbea2cfe95510bfdf23cbf79501fff82' - ], - [ - 'e4f3fb0176af85d65ff99ff9198c36091f48e86503681e3e6686fd5053231e11', - '1e63633ad0ef4f1c1661a6d0ea02b7286cc7e74ec951d1c9822c38576feb73bc' - ], - [ - '8c00fa9b18ebf331eb961537a45a4266c7034f2f0d4e1d0716fb6eae20eae29e', - 'efa47267fea521a1a9dc343a3736c974c2fadafa81e36c54e7d2a4c66702414b' - ], - [ - 'e7a26ce69dd4829f3e10cec0a9e98ed3143d084f308b92c0997fddfc60cb3e41', - '2a758e300fa7984b471b006a1aafbb18d0a6b2c0420e83e20e8a9421cf2cfd51' - ], - [ - 'b6459e0ee3662ec8d23540c223bcbdc571cbcb967d79424f3cf29eb3de6b80ef', - '67c876d06f3e06de1dadf16e5661db3c4b3ae6d48e35b2ff30bf0b61a71ba45' - ], - [ - 'd68a80c8280bb840793234aa118f06231d6f1fc67e73c5a5deda0f5b496943e8', - 'db8ba9fff4b586d00c4b1f9177b0e28b5b0e7b8f7845295a294c84266b133120' - ], - [ - '324aed7df65c804252dc0270907a30b09612aeb973449cea4095980fc28d3d5d', - '648a365774b61f2ff130c0c35aec1f4f19213b0c7e332843967224af96ab7c84' - ], - [ - '4df9c14919cde61f6d51dfdbe5fee5dceec4143ba8d1ca888e8bd373fd054c96', - '35ec51092d8728050974c23a1d85d4b5d506cdc288490192ebac06cad10d5d' - ], - [ - '9c3919a84a474870faed8a9c1cc66021523489054d7f0308cbfc99c8ac1f98cd', - 'ddb84f0f4a4ddd57584f044bf260e641905326f76c64c8e6be7e5e03d4fc599d' - ], - [ - '6057170b1dd12fdf8de05f281d8e06bb91e1493a8b91d4cc5a21382120a959e5', - '9a1af0b26a6a4807add9a2daf71df262465152bc3ee24c65e899be932385a2a8' - ], - [ - 'a576df8e23a08411421439a4518da31880cef0fba7d4df12b1a6973eecb94266', - '40a6bf20e76640b2c92b97afe58cd82c432e10a7f514d9f3ee8be11ae1b28ec8' - ], - [ - '7778a78c28dec3e30a05fe9629de8c38bb30d1f5cf9a3a208f763889be58ad71', - '34626d9ab5a5b22ff7098e12f2ff580087b38411ff24ac563b513fc1fd9f43ac' - ], - [ - '928955ee637a84463729fd30e7afd2ed5f96274e5ad7e5cb09eda9c06d903ac', - 'c25621003d3f42a827b78a13093a95eeac3d26efa8a8d83fc5180e935bcd091f' - ], - [ - '85d0fef3ec6db109399064f3a0e3b2855645b4a907ad354527aae75163d82751', - '1f03648413a38c0be29d496e582cf5663e8751e96877331582c237a24eb1f962' - ], - [ - 'ff2b0dce97eece97c1c9b6041798b85dfdfb6d8882da20308f5404824526087e', - '493d13fef524ba188af4c4dc54d07936c7b7ed6fb90e2ceb2c951e01f0c29907' - ], - [ - '827fbbe4b1e880ea9ed2b2e6301b212b57f1ee148cd6dd28780e5e2cf856e241', - 'c60f9c923c727b0b71bef2c67d1d12687ff7a63186903166d605b68baec293ec' - ], - [ - 'eaa649f21f51bdbae7be4ae34ce6e5217a58fdce7f47f9aa7f3b58fa2120e2b3', - 'be3279ed5bbbb03ac69a80f89879aa5a01a6b965f13f7e59d47a5305ba5ad93d' - ], - [ - 'e4a42d43c5cf169d9391df6decf42ee541b6d8f0c9a137401e23632dda34d24f', - '4d9f92e716d1c73526fc99ccfb8ad34ce886eedfa8d8e4f13a7f7131deba9414' - ], - [ - '1ec80fef360cbdd954160fadab352b6b92b53576a88fea4947173b9d4300bf19', - 'aeefe93756b5340d2f3a4958a7abbf5e0146e77f6295a07b671cdc1cc107cefd' - ], - [ - '146a778c04670c2f91b00af4680dfa8bce3490717d58ba889ddb5928366642be', - 'b318e0ec3354028add669827f9d4b2870aaa971d2f7e5ed1d0b297483d83efd0' - ], - [ - 'fa50c0f61d22e5f07e3acebb1aa07b128d0012209a28b9776d76a8793180eef9', - '6b84c6922397eba9b72cd2872281a68a5e683293a57a213b38cd8d7d3f4f2811' - ], - [ - 'da1d61d0ca721a11b1a5bf6b7d88e8421a288ab5d5bba5220e53d32b5f067ec2', - '8157f55a7c99306c79c0766161c91e2966a73899d279b48a655fba0f1ad836f1' - ], - [ - 'a8e282ff0c9706907215ff98e8fd416615311de0446f1e062a73b0610d064e13', - '7f97355b8db81c09abfb7f3c5b2515888b679a3e50dd6bd6cef7c73111f4cc0c' - ], - [ - '174a53b9c9a285872d39e56e6913cab15d59b1fa512508c022f382de8319497c', - 'ccc9dc37abfc9c1657b4155f2c47f9e6646b3a1d8cb9854383da13ac079afa73' - ], - [ - '959396981943785c3d3e57edf5018cdbe039e730e4918b3d884fdff09475b7ba', - '2e7e552888c331dd8ba0386a4b9cd6849c653f64c8709385e9b8abf87524f2fd' - ], - [ - 'd2a63a50ae401e56d645a1153b109a8fcca0a43d561fba2dbb51340c9d82b151', - 'e82d86fb6443fcb7565aee58b2948220a70f750af484ca52d4142174dcf89405' - ], - [ - '64587e2335471eb890ee7896d7cfdc866bacbdbd3839317b3436f9b45617e073', - 'd99fcdd5bf6902e2ae96dd6447c299a185b90a39133aeab358299e5e9faf6589' - ], - [ - '8481bde0e4e4d885b3a546d3e549de042f0aa6cea250e7fd358d6c86dd45e458', - '38ee7b8cba5404dd84a25bf39cecb2ca900a79c42b262e556d64b1b59779057e' - ], - [ - '13464a57a78102aa62b6979ae817f4637ffcfed3c4b1ce30bcd6303f6caf666b', - '69be159004614580ef7e433453ccb0ca48f300a81d0942e13f495a907f6ecc27' - ], - [ - 'bc4a9df5b713fe2e9aef430bcc1dc97a0cd9ccede2f28588cada3a0d2d83f366', - 'd3a81ca6e785c06383937adf4b798caa6e8a9fbfa547b16d758d666581f33c1' - ], - [ - '8c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa', - '40a30463a3305193378fedf31f7cc0eb7ae784f0451cb9459e71dc73cbef9482' - ], - [ - '8ea9666139527a8c1dd94ce4f071fd23c8b350c5a4bb33748c4ba111faccae0', - '620efabbc8ee2782e24e7c0cfb95c5d735b783be9cf0f8e955af34a30e62b945' - ], - [ - 'dd3625faef5ba06074669716bbd3788d89bdde815959968092f76cc4eb9a9787', - '7a188fa3520e30d461da2501045731ca941461982883395937f68d00c644a573' - ], - [ - 'f710d79d9eb962297e4f6232b40e8f7feb2bc63814614d692c12de752408221e', - 'ea98e67232d3b3295d3b535532115ccac8612c721851617526ae47a9c77bfc82' - ] - ] - }, - naf: { - wnd: 7, - points: [ - [ - 'f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9', - '388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672' - ], - [ - '2f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4', - 'd8ac222636e5e3d6d4dba9dda6c9c426f788271bab0d6840dca87d3aa6ac62d6' - ], - [ - '5cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc', - '6aebca40ba255960a3178d6d861a54dba813d0b813fde7b5a5082628087264da' - ], - [ - 'acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe', - 'cc338921b0a7d9fd64380971763b61e9add888a4375f8e0f05cc262ac64f9c37' - ], - [ - '774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb', - 'd984a032eb6b5e190243dd56d7b7b365372db1e2dff9d6a8301d74c9c953c61b' - ], - [ - 'f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8', - 'ab0902e8d880a89758212eb65cdaf473a1a06da521fa91f29b5cb52db03ed81' - ], - [ - 'd7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e', - '581e2872a86c72a683842ec228cc6defea40af2bd896d3a5c504dc9ff6a26b58' - ], - [ - 'defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34', - '4211ab0694635168e997b0ead2a93daeced1f4a04a95c0f6cfb199f69e56eb77' - ], - [ - '2b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c', - '85e89bc037945d93b343083b5a1c86131a01f60c50269763b570c854e5c09b7a' - ], - [ - '352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5', - '321eb4075348f534d59c18259dda3e1f4a1b3b2e71b1039c67bd3d8bcf81998c' - ], - [ - '2fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f', - '2de1068295dd865b64569335bd5dd80181d70ecfc882648423ba76b532b7d67' - ], - [ - '9248279b09b4d68dab21a9b066edda83263c3d84e09572e269ca0cd7f5453714', - '73016f7bf234aade5d1aa71bdea2b1ff3fc0de2a887912ffe54a32ce97cb3402' - ], - [ - 'daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729', - 'a69dce4a7d6c98e8d4a1aca87ef8d7003f83c230f3afa726ab40e52290be1c55' - ], - [ - 'c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db', - '2119a460ce326cdc76c45926c982fdac0e106e861edf61c5a039063f0e0e6482' - ], - [ - '6a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4', - 'e022cf42c2bd4a708b3f5126f16a24ad8b33ba48d0423b6efd5e6348100d8a82' - ], - [ - '1697ffa6fd9de627c077e3d2fe541084ce13300b0bec1146f95ae57f0d0bd6a5', - 'b9c398f186806f5d27561506e4557433a2cf15009e498ae7adee9d63d01b2396' - ], - [ - '605bdb019981718b986d0f07e834cb0d9deb8360ffb7f61df982345ef27a7479', - '2972d2de4f8d20681a78d93ec96fe23c26bfae84fb14db43b01e1e9056b8c49' - ], - [ - '62d14dab4150bf497402fdc45a215e10dcb01c354959b10cfe31c7e9d87ff33d', - '80fc06bd8cc5b01098088a1950eed0db01aa132967ab472235f5642483b25eaf' - ], - [ - '80c60ad0040f27dade5b4b06c408e56b2c50e9f56b9b8b425e555c2f86308b6f', - '1c38303f1cc5c30f26e66bad7fe72f70a65eed4cbe7024eb1aa01f56430bd57a' - ], - [ - '7a9375ad6167ad54aa74c6348cc54d344cc5dc9487d847049d5eabb0fa03c8fb', - 'd0e3fa9eca8726909559e0d79269046bdc59ea10c70ce2b02d499ec224dc7f7' - ], - [ - 'd528ecd9b696b54c907a9ed045447a79bb408ec39b68df504bb51f459bc3ffc9', - 'eecf41253136e5f99966f21881fd656ebc4345405c520dbc063465b521409933' - ], - [ - '49370a4b5f43412ea25f514e8ecdad05266115e4a7ecb1387231808f8b45963', - '758f3f41afd6ed428b3081b0512fd62a54c3f3afbb5b6764b653052a12949c9a' - ], - [ - '77f230936ee88cbbd73df930d64702ef881d811e0e1498e2f1c13eb1fc345d74', - '958ef42a7886b6400a08266e9ba1b37896c95330d97077cbbe8eb3c7671c60d6' - ], - [ - 'f2dac991cc4ce4b9ea44887e5c7c0bce58c80074ab9d4dbaeb28531b7739f530', - 'e0dedc9b3b2f8dad4da1f32dec2531df9eb5fbeb0598e4fd1a117dba703a3c37' - ], - [ - '463b3d9f662621fb1b4be8fbbe2520125a216cdfc9dae3debcba4850c690d45b', - '5ed430d78c296c3543114306dd8622d7c622e27c970a1de31cb377b01af7307e' - ], - [ - 'f16f804244e46e2a09232d4aff3b59976b98fac14328a2d1a32496b49998f247', - 'cedabd9b82203f7e13d206fcdf4e33d92a6c53c26e5cce26d6579962c4e31df6' - ], - [ - 'caf754272dc84563b0352b7a14311af55d245315ace27c65369e15f7151d41d1', - 'cb474660ef35f5f2a41b643fa5e460575f4fa9b7962232a5c32f908318a04476' - ], - [ - '2600ca4b282cb986f85d0f1709979d8b44a09c07cb86d7c124497bc86f082120', - '4119b88753c15bd6a693b03fcddbb45d5ac6be74ab5f0ef44b0be9475a7e4b40' - ], - [ - '7635ca72d7e8432c338ec53cd12220bc01c48685e24f7dc8c602a7746998e435', - '91b649609489d613d1d5e590f78e6d74ecfc061d57048bad9e76f302c5b9c61' - ], - [ - '754e3239f325570cdbbf4a87deee8a66b7f2b33479d468fbc1a50743bf56cc18', - '673fb86e5bda30fb3cd0ed304ea49a023ee33d0197a695d0c5d98093c536683' - ], - [ - 'e3e6bd1071a1e96aff57859c82d570f0330800661d1c952f9fe2694691d9b9e8', - '59c9e0bba394e76f40c0aa58379a3cb6a5a2283993e90c4167002af4920e37f5' - ], - [ - '186b483d056a033826ae73d88f732985c4ccb1f32ba35f4b4cc47fdcf04aa6eb', - '3b952d32c67cf77e2e17446e204180ab21fb8090895138b4a4a797f86e80888b' - ], - [ - 'df9d70a6b9876ce544c98561f4be4f725442e6d2b737d9c91a8321724ce0963f', - '55eb2dafd84d6ccd5f862b785dc39d4ab157222720ef9da217b8c45cf2ba2417' - ], - [ - '5edd5cc23c51e87a497ca815d5dce0f8ab52554f849ed8995de64c5f34ce7143', - 'efae9c8dbc14130661e8cec030c89ad0c13c66c0d17a2905cdc706ab7399a868' - ], - [ - '290798c2b6476830da12fe02287e9e777aa3fba1c355b17a722d362f84614fba', - 'e38da76dcd440621988d00bcf79af25d5b29c094db2a23146d003afd41943e7a' - ], - [ - 'af3c423a95d9f5b3054754efa150ac39cd29552fe360257362dfdecef4053b45', - 'f98a3fd831eb2b749a93b0e6f35cfb40c8cd5aa667a15581bc2feded498fd9c6' - ], - [ - '766dbb24d134e745cccaa28c99bf274906bb66b26dcf98df8d2fed50d884249a', - '744b1152eacbe5e38dcc887980da38b897584a65fa06cedd2c924f97cbac5996' - ], - [ - '59dbf46f8c94759ba21277c33784f41645f7b44f6c596a58ce92e666191abe3e', - 'c534ad44175fbc300f4ea6ce648309a042ce739a7919798cd85e216c4a307f6e' - ], - [ - 'f13ada95103c4537305e691e74e9a4a8dd647e711a95e73cb62dc6018cfd87b8', - 'e13817b44ee14de663bf4bc808341f326949e21a6a75c2570778419bdaf5733d' - ], - [ - '7754b4fa0e8aced06d4167a2c59cca4cda1869c06ebadfb6488550015a88522c', - '30e93e864e669d82224b967c3020b8fa8d1e4e350b6cbcc537a48b57841163a2' - ], - [ - '948dcadf5990e048aa3874d46abef9d701858f95de8041d2a6828c99e2262519', - 'e491a42537f6e597d5d28a3224b1bc25df9154efbd2ef1d2cbba2cae5347d57e' - ], - [ - '7962414450c76c1689c7b48f8202ec37fb224cf5ac0bfa1570328a8a3d7c77ab', - '100b610ec4ffb4760d5c1fc133ef6f6b12507a051f04ac5760afa5b29db83437' - ], - [ - '3514087834964b54b15b160644d915485a16977225b8847bb0dd085137ec47ca', - 'ef0afbb2056205448e1652c48e8127fc6039e77c15c2378b7e7d15a0de293311' - ], - [ - 'd3cc30ad6b483e4bc79ce2c9dd8bc54993e947eb8df787b442943d3f7b527eaf', - '8b378a22d827278d89c5e9be8f9508ae3c2ad46290358630afb34db04eede0a4' - ], - [ - '1624d84780732860ce1c78fcbfefe08b2b29823db913f6493975ba0ff4847610', - '68651cf9b6da903e0914448c6cd9d4ca896878f5282be4c8cc06e2a404078575' - ], - [ - '733ce80da955a8a26902c95633e62a985192474b5af207da6df7b4fd5fc61cd4', - 'f5435a2bd2badf7d485a4d8b8db9fcce3e1ef8e0201e4578c54673bc1dc5ea1d' - ], - [ - '15d9441254945064cf1a1c33bbd3b49f8966c5092171e699ef258dfab81c045c', - 'd56eb30b69463e7234f5137b73b84177434800bacebfc685fc37bbe9efe4070d' - ], - [ - 'a1d0fcf2ec9de675b612136e5ce70d271c21417c9d2b8aaaac138599d0717940', - 'edd77f50bcb5a3cab2e90737309667f2641462a54070f3d519212d39c197a629' - ], - [ - 'e22fbe15c0af8ccc5780c0735f84dbe9a790badee8245c06c7ca37331cb36980', - 'a855babad5cd60c88b430a69f53a1a7a38289154964799be43d06d77d31da06' - ], - [ - '311091dd9860e8e20ee13473c1155f5f69635e394704eaa74009452246cfa9b3', - '66db656f87d1f04fffd1f04788c06830871ec5a64feee685bd80f0b1286d8374' - ], - [ - '34c1fd04d301be89b31c0442d3e6ac24883928b45a9340781867d4232ec2dbdf', - '9414685e97b1b5954bd46f730174136d57f1ceeb487443dc5321857ba73abee' - ], - [ - 'f219ea5d6b54701c1c14de5b557eb42a8d13f3abbcd08affcc2a5e6b049b8d63', - '4cb95957e83d40b0f73af4544cccf6b1f4b08d3c07b27fb8d8c2962a400766d1' - ], - [ - 'd7b8740f74a8fbaab1f683db8f45de26543a5490bca627087236912469a0b448', - 'fa77968128d9c92ee1010f337ad4717eff15db5ed3c049b3411e0315eaa4593b' - ], - [ - '32d31c222f8f6f0ef86f7c98d3a3335ead5bcd32abdd94289fe4d3091aa824bf', - '5f3032f5892156e39ccd3d7915b9e1da2e6dac9e6f26e961118d14b8462e1661' - ], - [ - '7461f371914ab32671045a155d9831ea8793d77cd59592c4340f86cbc18347b5', - '8ec0ba238b96bec0cbdddcae0aa442542eee1ff50c986ea6b39847b3cc092ff6' - ], - [ - 'ee079adb1df1860074356a25aa38206a6d716b2c3e67453d287698bad7b2b2d6', - '8dc2412aafe3be5c4c5f37e0ecc5f9f6a446989af04c4e25ebaac479ec1c8c1e' - ], - [ - '16ec93e447ec83f0467b18302ee620f7e65de331874c9dc72bfd8616ba9da6b5', - '5e4631150e62fb40d0e8c2a7ca5804a39d58186a50e497139626778e25b0674d' - ], - [ - 'eaa5f980c245f6f038978290afa70b6bd8855897f98b6aa485b96065d537bd99', - 'f65f5d3e292c2e0819a528391c994624d784869d7e6ea67fb18041024edc07dc' - ], - [ - '78c9407544ac132692ee1910a02439958ae04877151342ea96c4b6b35a49f51', - 'f3e0319169eb9b85d5404795539a5e68fa1fbd583c064d2462b675f194a3ddb4' - ], - [ - '494f4be219a1a77016dcd838431aea0001cdc8ae7a6fc688726578d9702857a5', - '42242a969283a5f339ba7f075e36ba2af925ce30d767ed6e55f4b031880d562c' - ], - [ - 'a598a8030da6d86c6bc7f2f5144ea549d28211ea58faa70ebf4c1e665c1fe9b5', - '204b5d6f84822c307e4b4a7140737aec23fc63b65b35f86a10026dbd2d864e6b' - ], - [ - 'c41916365abb2b5d09192f5f2dbeafec208f020f12570a184dbadc3e58595997', - '4f14351d0087efa49d245b328984989d5caf9450f34bfc0ed16e96b58fa9913' - ], - [ - '841d6063a586fa475a724604da03bc5b92a2e0d2e0a36acfe4c73a5514742881', - '73867f59c0659e81904f9a1c7543698e62562d6744c169ce7a36de01a8d6154' - ], - [ - '5e95bb399a6971d376026947f89bde2f282b33810928be4ded112ac4d70e20d5', - '39f23f366809085beebfc71181313775a99c9aed7d8ba38b161384c746012865' - ], - [ - '36e4641a53948fd476c39f8a99fd974e5ec07564b5315d8bf99471bca0ef2f66', - 'd2424b1b1abe4eb8164227b085c9aa9456ea13493fd563e06fd51cf5694c78fc' - ], - [ - '336581ea7bfbbb290c191a2f507a41cf5643842170e914faeab27c2c579f726', - 'ead12168595fe1be99252129b6e56b3391f7ab1410cd1e0ef3dcdcabd2fda224' - ], - [ - '8ab89816dadfd6b6a1f2634fcf00ec8403781025ed6890c4849742706bd43ede', - '6fdcef09f2f6d0a044e654aef624136f503d459c3e89845858a47a9129cdd24e' - ], - [ - '1e33f1a746c9c5778133344d9299fcaa20b0938e8acff2544bb40284b8c5fb94', - '60660257dd11b3aa9c8ed618d24edff2306d320f1d03010e33a7d2057f3b3b6' - ], - [ - '85b7c1dcb3cec1b7ee7f30ded79dd20a0ed1f4cc18cbcfcfa410361fd8f08f31', - '3d98a9cdd026dd43f39048f25a8847f4fcafad1895d7a633c6fed3c35e999511' - ], - [ - '29df9fbd8d9e46509275f4b125d6d45d7fbe9a3b878a7af872a2800661ac5f51', - 'b4c4fe99c775a606e2d8862179139ffda61dc861c019e55cd2876eb2a27d84b' - ], - [ - 'a0b1cae06b0a847a3fea6e671aaf8adfdfe58ca2f768105c8082b2e449fce252', - 'ae434102edde0958ec4b19d917a6a28e6b72da1834aff0e650f049503a296cf2' - ], - [ - '4e8ceafb9b3e9a136dc7ff67e840295b499dfb3b2133e4ba113f2e4c0e121e5', - 'cf2174118c8b6d7a4b48f6d534ce5c79422c086a63460502b827ce62a326683c' - ], - [ - 'd24a44e047e19b6f5afb81c7ca2f69080a5076689a010919f42725c2b789a33b', - '6fb8d5591b466f8fc63db50f1c0f1c69013f996887b8244d2cdec417afea8fa3' - ], - [ - 'ea01606a7a6c9cdd249fdfcfacb99584001edd28abbab77b5104e98e8e3b35d4', - '322af4908c7312b0cfbfe369f7a7b3cdb7d4494bc2823700cfd652188a3ea98d' - ], - [ - 'af8addbf2b661c8a6c6328655eb96651252007d8c5ea31be4ad196de8ce2131f', - '6749e67c029b85f52a034eafd096836b2520818680e26ac8f3dfbcdb71749700' - ], - [ - 'e3ae1974566ca06cc516d47e0fb165a674a3dabcfca15e722f0e3450f45889', - '2aeabe7e4531510116217f07bf4d07300de97e4874f81f533420a72eeb0bd6a4' - ], - [ - '591ee355313d99721cf6993ffed1e3e301993ff3ed258802075ea8ced397e246', - 'b0ea558a113c30bea60fc4775460c7901ff0b053d25ca2bdeee98f1a4be5d196' - ], - [ - '11396d55fda54c49f19aa97318d8da61fa8584e47b084945077cf03255b52984', - '998c74a8cd45ac01289d5833a7beb4744ff536b01b257be4c5767bea93ea57a4' - ], - [ - '3c5d2a1ba39c5a1790000738c9e0c40b8dcdfd5468754b6405540157e017aa7a', - 'b2284279995a34e2f9d4de7396fc18b80f9b8b9fdd270f6661f79ca4c81bd257' - ], - [ - 'cc8704b8a60a0defa3a99a7299f2e9c3fbc395afb04ac078425ef8a1793cc030', - 'bdd46039feed17881d1e0862db347f8cf395b74fc4bcdc4e940b74e3ac1f1b13' - ], - [ - 'c533e4f7ea8555aacd9777ac5cad29b97dd4defccc53ee7ea204119b2889b197', - '6f0a256bc5efdf429a2fb6242f1a43a2d9b925bb4a4b3a26bb8e0f45eb596096' - ], - [ - 'c14f8f2ccb27d6f109f6d08d03cc96a69ba8c34eec07bbcf566d48e33da6593', - 'c359d6923bb398f7fd4473e16fe1c28475b740dd098075e6c0e8649113dc3a38' - ], - [ - 'a6cbc3046bc6a450bac24789fa17115a4c9739ed75f8f21ce441f72e0b90e6ef', - '21ae7f4680e889bb130619e2c0f95a360ceb573c70603139862afd617fa9b9f' - ], - [ - '347d6d9a02c48927ebfb86c1359b1caf130a3c0267d11ce6344b39f99d43cc38', - '60ea7f61a353524d1c987f6ecec92f086d565ab687870cb12689ff1e31c74448' - ], - [ - 'da6545d2181db8d983f7dcb375ef5866d47c67b1bf31c8cf855ef7437b72656a', - '49b96715ab6878a79e78f07ce5680c5d6673051b4935bd897fea824b77dc208a' - ], - [ - 'c40747cc9d012cb1a13b8148309c6de7ec25d6945d657146b9d5994b8feb1111', - '5ca560753be2a12fc6de6caf2cb489565db936156b9514e1bb5e83037e0fa2d4' - ], - [ - '4e42c8ec82c99798ccf3a610be870e78338c7f713348bd34c8203ef4037f3502', - '7571d74ee5e0fb92a7a8b33a07783341a5492144cc54bcc40a94473693606437' - ], - [ - '3775ab7089bc6af823aba2e1af70b236d251cadb0c86743287522a1b3b0dedea', - 'be52d107bcfa09d8bcb9736a828cfa7fac8db17bf7a76a2c42ad961409018cf7' - ], - [ - 'cee31cbf7e34ec379d94fb814d3d775ad954595d1314ba8846959e3e82f74e26', - '8fd64a14c06b589c26b947ae2bcf6bfa0149ef0be14ed4d80f448a01c43b1c6d' - ], - [ - 'b4f9eaea09b6917619f6ea6a4eb5464efddb58fd45b1ebefcdc1a01d08b47986', - '39e5c9925b5a54b07433a4f18c61726f8bb131c012ca542eb24a8ac07200682a' - ], - [ - 'd4263dfc3d2df923a0179a48966d30ce84e2515afc3dccc1b77907792ebcc60e', - '62dfaf07a0f78feb30e30d6295853ce189e127760ad6cf7fae164e122a208d54' - ], - [ - '48457524820fa65a4f8d35eb6930857c0032acc0a4a2de422233eeda897612c4', - '25a748ab367979d98733c38a1fa1c2e7dc6cc07db2d60a9ae7a76aaa49bd0f77' - ], - [ - 'dfeeef1881101f2cb11644f3a2afdfc2045e19919152923f367a1767c11cceda', - 'ecfb7056cf1de042f9420bab396793c0c390bde74b4bbdff16a83ae09a9a7517' - ], - [ - '6d7ef6b17543f8373c573f44e1f389835d89bcbc6062ced36c82df83b8fae859', - 'cd450ec335438986dfefa10c57fea9bcc521a0959b2d80bbf74b190dca712d10' - ], - [ - 'e75605d59102a5a2684500d3b991f2e3f3c88b93225547035af25af66e04541f', - 'f5c54754a8f71ee540b9b48728473e314f729ac5308b06938360990e2bfad125' - ], - [ - 'eb98660f4c4dfaa06a2be453d5020bc99a0c2e60abe388457dd43fefb1ed620c', - '6cb9a8876d9cb8520609af3add26cd20a0a7cd8a9411131ce85f44100099223e' - ], - [ - '13e87b027d8514d35939f2e6892b19922154596941888336dc3563e3b8dba942', - 'fef5a3c68059a6dec5d624114bf1e91aac2b9da568d6abeb2570d55646b8adf1' - ], - [ - 'ee163026e9fd6fe017c38f06a5be6fc125424b371ce2708e7bf4491691e5764a', - '1acb250f255dd61c43d94ccc670d0f58f49ae3fa15b96623e5430da0ad6c62b2' - ], - [ - 'b268f5ef9ad51e4d78de3a750c2dc89b1e626d43505867999932e5db33af3d80', - '5f310d4b3c99b9ebb19f77d41c1dee018cf0d34fd4191614003e945a1216e423' - ], - [ - 'ff07f3118a9df035e9fad85eb6c7bfe42b02f01ca99ceea3bf7ffdba93c4750d', - '438136d603e858a3a5c440c38eccbaddc1d2942114e2eddd4740d098ced1f0d8' - ], - [ - '8d8b9855c7c052a34146fd20ffb658bea4b9f69e0d825ebec16e8c3ce2b526a1', - 'cdb559eedc2d79f926baf44fb84ea4d44bcf50fee51d7ceb30e2e7f463036758' - ], - [ - '52db0b5384dfbf05bfa9d472d7ae26dfe4b851ceca91b1eba54263180da32b63', - 'c3b997d050ee5d423ebaf66a6db9f57b3180c902875679de924b69d84a7b375' - ], - [ - 'e62f9490d3d51da6395efd24e80919cc7d0f29c3f3fa48c6fff543becbd43352', - '6d89ad7ba4876b0b22c2ca280c682862f342c8591f1daf5170e07bfd9ccafa7d' - ], - [ - '7f30ea2476b399b4957509c88f77d0191afa2ff5cb7b14fd6d8e7d65aaab1193', - 'ca5ef7d4b231c94c3b15389a5f6311e9daff7bb67b103e9880ef4bff637acaec' - ], - [ - '5098ff1e1d9f14fb46a210fada6c903fef0fb7b4a1dd1d9ac60a0361800b7a00', - '9731141d81fc8f8084d37c6e7542006b3ee1b40d60dfe5362a5b132fd17ddc0' - ], - [ - '32b78c7de9ee512a72895be6b9cbefa6e2f3c4ccce445c96b9f2c81e2778ad58', - 'ee1849f513df71e32efc3896ee28260c73bb80547ae2275ba497237794c8753c' - ], - [ - 'e2cb74fddc8e9fbcd076eef2a7c72b0ce37d50f08269dfc074b581550547a4f7', - 'd3aa2ed71c9dd2247a62df062736eb0baddea9e36122d2be8641abcb005cc4a4' - ], - [ - '8438447566d4d7bedadc299496ab357426009a35f235cb141be0d99cd10ae3a8', - 'c4e1020916980a4da5d01ac5e6ad330734ef0d7906631c4f2390426b2edd791f' - ], - [ - '4162d488b89402039b584c6fc6c308870587d9c46f660b878ab65c82c711d67e', - '67163e903236289f776f22c25fb8a3afc1732f2b84b4e95dbda47ae5a0852649' - ], - [ - '3fad3fa84caf0f34f0f89bfd2dcf54fc175d767aec3e50684f3ba4a4bf5f683d', - 'cd1bc7cb6cc407bb2f0ca647c718a730cf71872e7d0d2a53fa20efcdfe61826' - ], - [ - '674f2600a3007a00568c1a7ce05d0816c1fb84bf1370798f1c69532faeb1a86b', - '299d21f9413f33b3edf43b257004580b70db57da0b182259e09eecc69e0d38a5' - ], - [ - 'd32f4da54ade74abb81b815ad1fb3b263d82d6c692714bcff87d29bd5ee9f08f', - 'f9429e738b8e53b968e99016c059707782e14f4535359d582fc416910b3eea87' - ], - [ - '30e4e670435385556e593657135845d36fbb6931f72b08cb1ed954f1e3ce3ff6', - '462f9bce619898638499350113bbc9b10a878d35da70740dc695a559eb88db7b' - ], - [ - 'be2062003c51cc3004682904330e4dee7f3dcd10b01e580bf1971b04d4cad297', - '62188bc49d61e5428573d48a74e1c655b1c61090905682a0d5558ed72dccb9bc' - ], - [ - '93144423ace3451ed29e0fb9ac2af211cb6e84a601df5993c419859fff5df04a', - '7c10dfb164c3425f5c71a3f9d7992038f1065224f72bb9d1d902a6d13037b47c' - ], - [ - 'b015f8044f5fcbdcf21ca26d6c34fb8197829205c7b7d2a7cb66418c157b112c', - 'ab8c1e086d04e813744a655b2df8d5f83b3cdc6faa3088c1d3aea1454e3a1d5f' - ], - [ - 'd5e9e1da649d97d89e4868117a465a3a4f8a18de57a140d36b3f2af341a21b52', - '4cb04437f391ed73111a13cc1d4dd0db1693465c2240480d8955e8592f27447a' - ], - [ - 'd3ae41047dd7ca065dbf8ed77b992439983005cd72e16d6f996a5316d36966bb', - 'bd1aeb21ad22ebb22a10f0303417c6d964f8cdd7df0aca614b10dc14d125ac46' - ], - [ - '463e2763d885f958fc66cdd22800f0a487197d0a82e377b49f80af87c897b065', - 'bfefacdb0e5d0fd7df3a311a94de062b26b80c61fbc97508b79992671ef7ca7f' - ], - [ - '7985fdfd127c0567c6f53ec1bb63ec3158e597c40bfe747c83cddfc910641917', - '603c12daf3d9862ef2b25fe1de289aed24ed291e0ec6708703a5bd567f32ed03' - ], - [ - '74a1ad6b5f76e39db2dd249410eac7f99e74c59cb83d2d0ed5ff1543da7703e9', - 'cc6157ef18c9c63cd6193d83631bbea0093e0968942e8c33d5737fd790e0db08' - ], - [ - '30682a50703375f602d416664ba19b7fc9bab42c72747463a71d0896b22f6da3', - '553e04f6b018b4fa6c8f39e7f311d3176290d0e0f19ca73f17714d9977a22ff8' - ], - [ - '9e2158f0d7c0d5f26c3791efefa79597654e7a2b2464f52b1ee6c1347769ef57', - '712fcdd1b9053f09003a3481fa7762e9ffd7c8ef35a38509e2fbf2629008373' - ], - [ - '176e26989a43c9cfeba4029c202538c28172e566e3c4fce7322857f3be327d66', - 'ed8cc9d04b29eb877d270b4878dc43c19aefd31f4eee09ee7b47834c1fa4b1c3' - ], - [ - '75d46efea3771e6e68abb89a13ad747ecf1892393dfc4f1b7004788c50374da8', - '9852390a99507679fd0b86fd2b39a868d7efc22151346e1a3ca4726586a6bed8' - ], - [ - '809a20c67d64900ffb698c4c825f6d5f2310fb0451c869345b7319f645605721', - '9e994980d9917e22b76b061927fa04143d096ccc54963e6a5ebfa5f3f8e286c1' - ], - [ - '1b38903a43f7f114ed4500b4eac7083fdefece1cf29c63528d563446f972c180', - '4036edc931a60ae889353f77fd53de4a2708b26b6f5da72ad3394119daf408f9' - ] - ] - } -}; - -var curves_1 = createCommonjsModule(function (module, exports) { - -var curves = exports; - - - - - -var assert = utils_1$1.assert; - -function PresetCurve(options) { - if (options.type === 'short') - this.curve = new curve_1.short(options); - else if (options.type === 'edwards') - this.curve = new curve_1.edwards(options); - else if (options.type === 'mont') - this.curve = new curve_1.mont(options); - else throw new Error('Unknown curve type.'); - this.g = this.curve.g; - this.n = this.curve.n; - this.hash = options.hash; - - assert(this.g.validate(), 'Invalid curve'); - assert(this.g.mul(this.n).isInfinity(), 'Invalid curve, n*G != O'); -} -curves.PresetCurve = PresetCurve; - -function defineCurve(name, options) { - Object.defineProperty(curves, name, { - configurable: true, - enumerable: true, - get: function() { - var curve = new PresetCurve(options); - Object.defineProperty(curves, name, { - configurable: true, - enumerable: true, - value: curve - }); - return curve; - } - }); -} - -defineCurve('p192', { - type: 'short', - prime: 'p192', - p: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff', - a: 'ffffffff ffffffff ffffffff fffffffe ffffffff fffffffc', - b: '64210519 e59c80e7 0fa7e9ab 72243049 feb8deec c146b9b1', - n: 'ffffffff ffffffff ffffffff 99def836 146bc9b1 b4d22831', - hash: hash_1.sha256, - gRed: false, - g: [ - '188da80e b03090f6 7cbf20eb 43a18800 f4ff0afd 82ff1012', - '07192b95 ffc8da78 631011ed 6b24cdd5 73f977a1 1e794811' - ] -}); - -defineCurve('p224', { - type: 'short', - prime: 'p224', - p: 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001', - a: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff fffffffe', - b: 'b4050a85 0c04b3ab f5413256 5044b0b7 d7bfd8ba 270b3943 2355ffb4', - n: 'ffffffff ffffffff ffffffff ffff16a2 e0b8f03e 13dd2945 5c5c2a3d', - hash: hash_1.sha256, - gRed: false, - g: [ - 'b70e0cbd 6bb4bf7f 321390b9 4a03c1d3 56c21122 343280d6 115c1d21', - 'bd376388 b5f723fb 4c22dfe6 cd4375a0 5a074764 44d58199 85007e34' - ] -}); - -defineCurve('p256', { - type: 'short', - prime: null, - p: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff', - a: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff fffffffc', - b: '5ac635d8 aa3a93e7 b3ebbd55 769886bc 651d06b0 cc53b0f6 3bce3c3e 27d2604b', - n: 'ffffffff 00000000 ffffffff ffffffff bce6faad a7179e84 f3b9cac2 fc632551', - hash: hash_1.sha256, - gRed: false, - g: [ - '6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296', - '4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5' - ] -}); - -defineCurve('p384', { - type: 'short', - prime: null, - p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'fffffffe ffffffff 00000000 00000000 ffffffff', - a: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'fffffffe ffffffff 00000000 00000000 fffffffc', - b: 'b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112 0314088f ' + - '5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef', - n: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff c7634d81 ' + - 'f4372ddf 581a0db2 48b0a77a ecec196a ccc52973', - hash: hash_1.sha384, - gRed: false, - g: [ - 'aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98 59f741e0 82542a38 ' + - '5502f25d bf55296c 3a545e38 72760ab7', - '3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c e9da3113 b5f0b8c0 ' + - '0a60b1ce 1d7e819d 7a431d7c 90ea0e5f' - ] -}); - -defineCurve('p521', { - type: 'short', - prime: null, - p: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff ffffffff', - a: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff fffffffc', - b: '00000051 953eb961 8e1c9a1f 929a21a0 b68540ee a2da725b ' + - '99b315f3 b8b48991 8ef109e1 56193951 ec7e937b 1652c0bd ' + - '3bb1bf07 3573df88 3d2c34f1 ef451fd4 6b503f00', - n: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff fffffffa 51868783 bf2f966b 7fcc0148 ' + - 'f709a5d0 3bb5c9b8 899c47ae bb6fb71e 91386409', - hash: hash_1.sha512, - gRed: false, - g: [ - '000000c6 858e06b7 0404e9cd 9e3ecb66 2395b442 9c648139 ' + - '053fb521 f828af60 6b4d3dba a14b5e77 efe75928 fe1dc127 ' + - 'a2ffa8de 3348b3c1 856a429b f97e7e31 c2e5bd66', - '00000118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd9 98f54449 ' + - '579b4468 17afbd17 273e662c 97ee7299 5ef42640 c550b901 ' + - '3fad0761 353c7086 a272c240 88be9476 9fd16650' - ] -}); - -// https://tools.ietf.org/html/rfc7748#section-4.1 -defineCurve('curve25519', { - type: 'mont', - prime: 'p25519', - p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', - a: '76d06', - b: '1', - n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', - cofactor: '8', - hash: hash_1.sha256, - gRed: false, - g: [ - '9' - ] -}); - -defineCurve('ed25519', { - type: 'edwards', - prime: 'p25519', - p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', - a: '-1', - c: '1', - // -121665 * (121666^(-1)) (mod P) - d: '52036cee2b6ffe73 8cc740797779e898 00700a4d4141d8ab 75eb4dca135978a3', - n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', - cofactor: '8', - hash: hash_1.sha256, - gRed: false, - g: [ - '216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a', - // 4/5 - '6666666666666666666666666666666666666666666666666666666666666658' - ] -}); - -// https://tools.ietf.org/html/rfc5639#section-3.4 -defineCurve('brainpoolP256r1', { - type: 'short', - prime: null, - p: 'A9FB57DB A1EEA9BC 3E660A90 9D838D72 6E3BF623 D5262028 2013481D 1F6E5377', - a: '7D5A0975 FC2C3057 EEF67530 417AFFE7 FB8055C1 26DC5C6C E94A4B44 F330B5D9', - b: '26DC5C6C E94A4B44 F330B5D9 BBD77CBF 95841629 5CF7E1CE 6BCCDC18 FF8C07B6', - n: 'A9FB57DB A1EEA9BC 3E660A90 9D838D71 8C397AA3 B561A6F7 901E0E82 974856A7', - hash: hash_1.sha256, // or 384, or 512 - gRed: false, - g: [ - '8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262', - '547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997' - ] -}); - -// https://tools.ietf.org/html/rfc5639#section-3.6 -defineCurve('brainpoolP384r1', { - type: 'short', - prime: null, - p: '8CB91E82 A3386D28 0F5D6F7E 50E641DF 152F7109 ED5456B4 12B1DA19 7FB71123' + - 'ACD3A729 901D1A71 87470013 3107EC53', - a: '7BC382C6 3D8C150C 3C72080A CE05AFA0 C2BEA28E 4FB22787 139165EF BA91F90F' + - '8AA5814A 503AD4EB 04A8C7DD 22CE2826', - b: '04A8C7DD 22CE2826 8B39B554 16F0447C 2FB77DE1 07DCD2A6 2E880EA5 3EEB62D5' + - '7CB43902 95DBC994 3AB78696 FA504C11', - n: '8CB91E82 A3386D28 0F5D6F7E 50E641DF 152F7109 ED5456B3 1F166E6C AC0425A7' + - 'CF3AB6AF 6B7FC310 3B883202 E9046565', - hash: hash_1.sha384, // or 512 - gRed: false, - g: [ - '1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10' + - 'E8E826E03436D646AAEF87B2E247D4AF1E', - '8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129' + - '280E4646217791811142820341263C5315' - ] -}); - -// https://tools.ietf.org/html/rfc5639#section-3.7 -defineCurve('brainpoolP512r1', { - type: 'short', - prime: null, - p: 'AADD9DB8 DBE9C48B 3FD4E6AE 33C9FC07 CB308DB3 B3C9D20E D6639CCA 70330871' + - '7D4D9B00 9BC66842 AECDA12A E6A380E6 2881FF2F 2D82C685 28AA6056 583A48F3', - a: '7830A331 8B603B89 E2327145 AC234CC5 94CBDD8D 3DF91610 A83441CA EA9863BC' + - '2DED5D5A A8253AA1 0A2EF1C9 8B9AC8B5 7F1117A7 2BF2C7B9 E7C1AC4D 77FC94CA', - b: '3DF91610 A83441CA EA9863BC 2DED5D5A A8253AA1 0A2EF1C9 8B9AC8B5 7F1117A7' + - '2BF2C7B9 E7C1AC4D 77FC94CA DC083E67 984050B7 5EBAE5DD 2809BD63 8016F723', - n: 'AADD9DB8 DBE9C48B 3FD4E6AE 33C9FC07 CB308DB3 B3C9D20E D6639CCA 70330870' + - '553E5C41 4CA92619 41866119 7FAC1047 1DB1D381 085DDADD B5879682 9CA90069', - hash: hash_1.sha512, - gRed: false, - g: [ - '81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D009' + - '8EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822', - '7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F81' + - '11B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892' - ] -}); - -// https://en.bitcoin.it/wiki/Secp256k1 -var pre; -try { - pre = secp256k1; -} catch (e) { - pre = undefined; -} - -defineCurve('secp256k1', { - type: 'short', - prime: 'k256', - p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f', - a: '0', - b: '7', - n: 'ffffffff ffffffff ffffffff fffffffe baaedce6 af48a03b bfd25e8c d0364141', - h: '1', - hash: hash_1.sha256, - - // Precomputed endomorphism - beta: '7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee', - lambda: '5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72', - basis: [ - { - a: '3086d221a7d46bcde86c90e49284eb15', - b: '-e4437ed6010e88286f547fa90abfe4c3' - }, - { - a: '114ca50f7a8e2f3f657c1108d9d44cfd8', - b: '3086d221a7d46bcde86c90e49284eb15' - } - ], - - gRed: false, - g: [ - '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', - '483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', - pre - ] -}); -}); - -function HmacDRBG(options) { - if (!(this instanceof HmacDRBG)) - return new HmacDRBG(options); - this.hash = options.hash; - this.predResist = !!options.predResist; - - this.outLen = this.hash.outSize; - this.minEntropy = options.minEntropy || this.hash.hmacStrength; - - this._reseed = null; - this.reseedInterval = null; - this.K = null; - this.V = null; - - var entropy = utils_1.toArray(options.entropy, options.entropyEnc || 'hex'); - var nonce = utils_1.toArray(options.nonce, options.nonceEnc || 'hex'); - var pers = utils_1.toArray(options.pers, options.persEnc || 'hex'); - minimalisticAssert(entropy.length >= (this.minEntropy / 8), - 'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits'); - this._init(entropy, nonce, pers); -} -var hmacDrbg = HmacDRBG; - -HmacDRBG.prototype._init = function init(entropy, nonce, pers) { - var seed = entropy.concat(nonce).concat(pers); - - this.K = new Array(this.outLen / 8); - this.V = new Array(this.outLen / 8); - for (var i = 0; i < this.V.length; i++) { - this.K[i] = 0x00; - this.V[i] = 0x01; - } - - this._update(seed); - this._reseed = 1; - this.reseedInterval = 0x1000000000000; // 2^48 -}; - -HmacDRBG.prototype._hmac = function hmac() { - return new hash_1.hmac(this.hash, this.K); -}; - -HmacDRBG.prototype._update = function update(seed) { - var kmac = this._hmac() - .update(this.V) - .update([ 0x00 ]); - if (seed) - kmac = kmac.update(seed); - this.K = kmac.digest(); - this.V = this._hmac().update(this.V).digest(); - if (!seed) - return; - - this.K = this._hmac() - .update(this.V) - .update([ 0x01 ]) - .update(seed) - .digest(); - this.V = this._hmac().update(this.V).digest(); -}; - -HmacDRBG.prototype.reseed = function reseed(entropy, entropyEnc, add, addEnc) { - // Optional entropy enc - if (typeof entropyEnc !== 'string') { - addEnc = add; - add = entropyEnc; - entropyEnc = null; - } - - entropy = utils_1.toArray(entropy, entropyEnc); - add = utils_1.toArray(add, addEnc); - - minimalisticAssert(entropy.length >= (this.minEntropy / 8), - 'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits'); - - this._update(entropy.concat(add || [])); - this._reseed = 1; -}; - -HmacDRBG.prototype.generate = function generate(len, enc, add, addEnc) { - if (this._reseed > this.reseedInterval) - throw new Error('Reseed is required'); - - // Optional encoding - if (typeof enc !== 'string') { - addEnc = add; - add = enc; - enc = null; - } - - // Optional additional data - if (add) { - add = utils_1.toArray(add, addEnc || 'hex'); - this._update(add); - } - - var temp = []; - while (temp.length < len) { - this.V = this._hmac().update(this.V).digest(); - temp = temp.concat(this.V); - } - - var res = temp.slice(0, len); - this._update(add); - this._reseed++; - return utils_1.encode(res, enc); -}; - -var assert$5 = utils_1$1.assert; - -function KeyPair(ec, options) { - this.ec = ec; - this.priv = null; - this.pub = null; - - // KeyPair(ec, { priv: ..., pub: ... }) - if (options.priv) - this._importPrivate(options.priv, options.privEnc); - if (options.pub) - this._importPublic(options.pub, options.pubEnc); -} -var key = KeyPair; - -KeyPair.fromPublic = function fromPublic(ec, pub, enc) { - if (pub instanceof KeyPair) - return pub; - - return new KeyPair(ec, { - pub: pub, - pubEnc: enc - }); -}; - -KeyPair.fromPrivate = function fromPrivate(ec, priv, enc) { - if (priv instanceof KeyPair) - return priv; - - return new KeyPair(ec, { - priv: priv, - privEnc: enc - }); -}; - -// TODO: should not validate for X25519 -KeyPair.prototype.validate = function validate() { - var pub = this.getPublic(); - - if (pub.isInfinity()) - return { result: false, reason: 'Invalid public key' }; - if (!pub.validate()) - return { result: false, reason: 'Public key is not a point' }; - if (!pub.mul(this.ec.curve.n).isInfinity()) - return { result: false, reason: 'Public key * N != O' }; - - return { result: true, reason: null }; -}; - -KeyPair.prototype.getPublic = function getPublic(enc, compact) { - if (!this.pub) - this.pub = this.ec.g.mul(this.priv); - - if (!enc) - return this.pub; - - return this.pub.encode(enc, compact); -}; - -KeyPair.prototype.getPrivate = function getPrivate(enc) { - if (enc === 'hex') - return this.priv.toString(16, 2); - else - return this.priv; -}; - -KeyPair.prototype._importPrivate = function _importPrivate(key, enc) { - this.priv = new bn(key, enc || 16); - - // For Curve25519/Curve448 we have a specific procedure. - // TODO Curve448 - if (this.ec.curve.type === 'mont') { - var one = this.ec.curve.one; - var mask = one.ushln(255 - 3).sub(one).ushln(3); - this.priv = this.priv.or(one.ushln(255 - 1)); - this.priv = this.priv.and(mask); - } else - // Ensure that the priv won't be bigger than n, otherwise we may fail - // in fixed multiplication method - this.priv = this.priv.umod(this.ec.curve.n); -}; - -KeyPair.prototype._importPublic = function _importPublic(key, enc) { - if (key.x || key.y) { - // Montgomery points only have an `x` coordinate. - // Weierstrass/Edwards points on the other hand have both `x` and - // `y` coordinates. - if (this.ec.curve.type === 'mont') { - assert$5(key.x, 'Need x coordinate'); - } else if (this.ec.curve.type === 'short' || - this.ec.curve.type === 'edwards') { - assert$5(key.x && key.y, 'Need both x and y coordinate'); - } - this.pub = this.ec.curve.point(key.x, key.y); - return; - } - this.pub = this.ec.curve.decodePoint(key, enc); -}; - -// ECDH -KeyPair.prototype.derive = function derive(pub) { - return pub.mul(this.priv).getX(); -}; - -// ECDSA -KeyPair.prototype.sign = function sign(msg, enc, options) { - return this.ec.sign(msg, this, enc, options); -}; - -KeyPair.prototype.verify = function verify(msg, signature) { - return this.ec.verify(msg, signature, this); -}; - -KeyPair.prototype.inspect = function inspect() { - return ''; -}; - -var assert$6 = utils_1$1.assert; - -function Signature$1(options, enc) { - if (options instanceof Signature$1) - return options; - - if (this._importDER(options, enc)) - return; - - assert$6(options.r && options.s, 'Signature without r or s'); - this.r = new bn(options.r, 16); - this.s = new bn(options.s, 16); - if (options.recoveryParam === undefined) - this.recoveryParam = null; - else - this.recoveryParam = options.recoveryParam; -} -var signature$1 = Signature$1; - -function Position() { - this.place = 0; -} - -function getLength(buf, p) { - var initial = buf[p.place++]; - if (!(initial & 0x80)) { - return initial; - } - var octetLen = initial & 0xf; - var val = 0; - for (var i = 0, off = p.place; i < octetLen; i++, off++) { - val <<= 8; - val |= buf[off]; - } - p.place = off; - return val; -} - -function rmPadding(buf) { - var i = 0; - var len = buf.length - 1; - while (!buf[i] && !(buf[i + 1] & 0x80) && i < len) { - i++; - } - if (i === 0) { - return buf; - } - return buf.slice(i); -} - -Signature$1.prototype._importDER = function _importDER(data, enc) { - data = utils_1$1.toArray(data, enc); - var p = new Position(); - if (data[p.place++] !== 0x30) { - return false; - } - var len = getLength(data, p); - if ((len + p.place) !== data.length) { - return false; - } - if (data[p.place++] !== 0x02) { - return false; - } - var rlen = getLength(data, p); - var r = data.slice(p.place, rlen + p.place); - p.place += rlen; - if (data[p.place++] !== 0x02) { - return false; - } - var slen = getLength(data, p); - if (data.length !== slen + p.place) { - return false; - } - var s = data.slice(p.place, slen + p.place); - if (r[0] === 0 && (r[1] & 0x80)) { - r = r.slice(1); - } - if (s[0] === 0 && (s[1] & 0x80)) { - s = s.slice(1); - } - - this.r = new bn(r); - this.s = new bn(s); - this.recoveryParam = null; - - return true; -}; - -function constructLength(arr, len) { - if (len < 0x80) { - arr.push(len); - return; - } - var octets = 1 + (Math.log(len) / Math.LN2 >>> 3); - arr.push(octets | 0x80); - while (--octets) { - arr.push((len >>> (octets << 3)) & 0xff); - } - arr.push(len); -} - -Signature$1.prototype.toDER = function toDER(enc) { - var r = this.r.toArray(); - var s = this.s.toArray(); - - // Pad values - if (r[0] & 0x80) - r = [ 0 ].concat(r); - // Pad values - if (s[0] & 0x80) - s = [ 0 ].concat(s); - - r = rmPadding(r); - s = rmPadding(s); - - while (!s[0] && !(s[1] & 0x80)) { - s = s.slice(1); - } - var arr = [ 0x02 ]; - constructLength(arr, r.length); - arr = arr.concat(r); - arr.push(0x02); - constructLength(arr, s.length); - var backHalf = arr.concat(s); - var res = [ 0x30 ]; - constructLength(res, backHalf.length); - res = res.concat(backHalf); - return utils_1$1.encode(res, enc); -}; - -var assert$7 = utils_1$1.assert; - - - - -function EC(options) { - if (!(this instanceof EC)) - return new EC(options); - - // Shortcut `elliptic.ec(curve-name)` - if (typeof options === 'string') { - assert$7(curves_1.hasOwnProperty(options), 'Unknown curve ' + options); - - options = curves_1[options]; - } - - // Shortcut for `elliptic.ec(elliptic.curves.curveName)` - if (options instanceof curves_1.PresetCurve) - options = { curve: options }; - - this.curve = options.curve.curve; - this.n = this.curve.n; - this.nh = this.n.ushrn(1); - this.g = this.curve.g; - - // Point on curve - this.g = options.curve.g; - this.g.precompute(options.curve.n.bitLength() + 1); - - // Hash function for DRBG - this.hash = options.hash || options.curve.hash; -} -var ec = EC; - -EC.prototype.keyPair = function keyPair(options) { - return new key(this, options); -}; - -EC.prototype.keyFromPrivate = function keyFromPrivate(priv, enc) { - return key.fromPrivate(this, priv, enc); -}; - -EC.prototype.keyFromPublic = function keyFromPublic(pub, enc) { - return key.fromPublic(this, pub, enc); -}; - -EC.prototype.genKeyPair = function genKeyPair(options) { - if (!options) - options = {}; - - // Instantiate Hmac_DRBG - var drbg = new hmacDrbg({ - hash: this.hash, - pers: options.pers, - persEnc: options.persEnc || 'utf8', - entropy: options.entropy || brorand(this.hash.hmacStrength), - entropyEnc: options.entropy && options.entropyEnc || 'utf8', - nonce: this.n.toArray() - }); - - // Key generation for curve25519 is simpler - if (this.curve.type === 'mont') { - var priv = new bn(drbg.generate(32)); - return this.keyFromPrivate(priv); - } - - var bytes = this.n.byteLength(); - var ns2 = this.n.sub(new bn(2)); - do { - var priv = new bn(drbg.generate(bytes)); - if (priv.cmp(ns2) > 0) - continue; - - priv.iaddn(1); - return this.keyFromPrivate(priv); - } while (true); -}; - -EC.prototype._truncateToN = function truncateToN(msg, truncOnly, bitSize) { - bitSize = bitSize || msg.byteLength() * 8; - var delta = bitSize - this.n.bitLength(); - if (delta > 0) - msg = msg.ushrn(delta); - if (!truncOnly && msg.cmp(this.n) >= 0) - return msg.sub(this.n); - else - return msg; -}; - -EC.prototype.truncateMsg = function truncateMSG(msg) { - // Bit size is only determined correctly for Uint8Arrays and hex strings - var bitSize; - if (msg instanceof Uint8Array) { - bitSize = msg.byteLength * 8; - msg = this._truncateToN(new bn(msg, 16), false, bitSize); - } else if (typeof msg === 'string') { - bitSize = msg.length * 4; - msg = this._truncateToN(new bn(msg, 16), false, bitSize); - } else { - msg = this._truncateToN(new bn(msg, 16)); - } - return msg; -}; - -EC.prototype.sign = function sign(msg, key, enc, options) { - if (typeof enc === 'object') { - options = enc; - enc = null; - } - if (!options) - options = {}; - - key = this.keyFromPrivate(key, enc); - msg = this.truncateMsg(msg); - - // Zero-extend key to provide enough entropy - var bytes = this.n.byteLength(); - var bkey = key.getPrivate().toArray('be', bytes); - - // Zero-extend nonce to have the same byte size as N - var nonce = msg.toArray('be', bytes); - - // Instantiate Hmac_DRBG - var drbg = new hmacDrbg({ - hash: this.hash, - entropy: bkey, - nonce: nonce, - pers: options.pers, - persEnc: options.persEnc || 'utf8' - }); - - // Number of bytes to generate - var ns1 = this.n.sub(new bn(1)); - - for (var iter = 0; true; iter++) { - var k = options.k ? - options.k(iter) : - new bn(drbg.generate(this.n.byteLength())); - k = this._truncateToN(k, true); - if (k.cmpn(1) <= 0 || k.cmp(ns1) >= 0) - continue; - - var kp = this.g.mul(k); - if (kp.isInfinity()) - continue; - - var kpX = kp.getX(); - var r = kpX.umod(this.n); - if (r.cmpn(0) === 0) - continue; - - var s = k.invm(this.n).mul(r.mul(key.getPrivate()).iadd(msg)); - s = s.umod(this.n); - if (s.cmpn(0) === 0) - continue; - - var recoveryParam = (kp.getY().isOdd() ? 1 : 0) | - (kpX.cmp(r) !== 0 ? 2 : 0); - - // Use complement of `s`, if it is > `n / 2` - if (options.canonical && s.cmp(this.nh) > 0) { - s = this.n.sub(s); - recoveryParam ^= 1; - } - - return new signature$1({ r: r, s: s, recoveryParam: recoveryParam }); - } -}; - -EC.prototype.verify = function verify(msg, signature, key, enc) { - key = this.keyFromPublic(key, enc); - signature = new signature$1(signature, 'hex'); - // Fallback to the old code - var ret = this._verify(this.truncateMsg(msg), signature, key) || - this._verify(this._truncateToN(new bn(msg, 16)), signature, key); - return ret; -}; - -EC.prototype._verify = function _verify(msg, signature, key) { - // Perform primitive values validation - var r = signature.r; - var s = signature.s; - if (r.cmpn(1) < 0 || r.cmp(this.n) >= 0) - return false; - if (s.cmpn(1) < 0 || s.cmp(this.n) >= 0) - return false; - - // Validate signature - var sinv = s.invm(this.n); - var u1 = sinv.mul(msg).umod(this.n); - var u2 = sinv.mul(r).umod(this.n); - - if (!this.curve._maxwellTrick) { - var p = this.g.mulAdd(u1, key.getPublic(), u2); - if (p.isInfinity()) - return false; - - return p.getX().umod(this.n).cmp(r) === 0; - } - - // NOTE: Greg Maxwell's trick, inspired by: - // https://git.io/vad3K - - var p = this.g.jmulAdd(u1, key.getPublic(), u2); - if (p.isInfinity()) - return false; - - // Compare `p.x` of Jacobian point with `r`, - // this will do `p.x == r * p.z^2` instead of multiplying `p.x` by the - // inverse of `p.z^2` - return p.eqXToP(r); -}; - -EC.prototype.recoverPubKey = function(msg, signature, j, enc) { - assert$7((3 & j) === j, 'The recovery param is more than two bits'); - signature = new signature$1(signature, enc); - - var n = this.n; - var e = new bn(msg); - var r = signature.r; - var s = signature.s; - - // A set LSB signifies that the y-coordinate is odd - var isYOdd = j & 1; - var isSecondKey = j >> 1; - if (r.cmp(this.curve.p.umod(this.curve.n)) >= 0 && isSecondKey) - throw new Error('Unable to find sencond key candinate'); - - // 1.1. Let x = r + jn. - if (isSecondKey) - r = this.curve.pointFromX(r.add(this.curve.n), isYOdd); - else - r = this.curve.pointFromX(r, isYOdd); - - var rInv = signature.r.invm(n); - var s1 = n.sub(e).mul(rInv).umod(n); - var s2 = s.mul(rInv).umod(n); - - // 1.6.1 Compute Q = r^-1 (sR - eG) - // Q = r^-1 (sR + -eG) - return this.g.mulAdd(s1, r, s2); -}; - -EC.prototype.getKeyRecoveryParam = function(e, signature, Q, enc) { - signature = new signature$1(signature, enc); - if (signature.recoveryParam !== null) - return signature.recoveryParam; - - for (var i = 0; i < 4; i++) { - var Qprime; - try { - Qprime = this.recoverPubKey(e, signature, i); - } catch (e) { - continue; - } - - if (Qprime.eq(Q)) - return i; - } - throw new Error('Unable to find valid recovery factor'); -}; - -var assert$8 = utils_1$1.assert; -var parseBytes = utils_1$1.parseBytes; -var cachedProperty = utils_1$1.cachedProperty; - -/** -* @param {EDDSA} eddsa - instance -* @param {Object} params - public/private key parameters -* -* @param {Array} [params.secret] - secret seed bytes -* @param {Point} [params.pub] - public key point (aka `A` in eddsa terms) -* @param {Array} [params.pub] - public key point encoded as bytes -* -*/ -function KeyPair$1(eddsa, params) { - this.eddsa = eddsa; - if (params.hasOwnProperty('secret')) - this._secret = parseBytes(params.secret); - if (eddsa.isPoint(params.pub)) - this._pub = params.pub; - else { - this._pubBytes = parseBytes(params.pub); - if (this._pubBytes && this._pubBytes.length === 33 && - this._pubBytes[0] === 0x40) - this._pubBytes = this._pubBytes.slice(1, 33); - if (this._pubBytes && this._pubBytes.length !== 32) - throw new Error('Unknown point compression format'); - } -} - -KeyPair$1.fromPublic = function fromPublic(eddsa, pub) { - if (pub instanceof KeyPair$1) - return pub; - return new KeyPair$1(eddsa, { pub: pub }); -}; - -KeyPair$1.fromSecret = function fromSecret(eddsa, secret) { - if (secret instanceof KeyPair$1) - return secret; - return new KeyPair$1(eddsa, { secret: secret }); -}; - -KeyPair$1.prototype.secret = function secret() { - return this._secret; -}; - -cachedProperty(KeyPair$1, 'pubBytes', function pubBytes() { - return this.eddsa.encodePoint(this.pub()); -}); - -cachedProperty(KeyPair$1, 'pub', function pub() { - if (this._pubBytes) - return this.eddsa.decodePoint(this._pubBytes); - return this.eddsa.g.mul(this.priv()); -}); - -cachedProperty(KeyPair$1, 'privBytes', function privBytes() { - var eddsa = this.eddsa; - var hash = this.hash(); - var lastIx = eddsa.encodingLength - 1; - - // https://tools.ietf.org/html/rfc8032#section-5.1.5 - var a = hash.slice(0, eddsa.encodingLength); - a[0] &= 248; - a[lastIx] &= 127; - a[lastIx] |= 64; - - return a; -}); - -cachedProperty(KeyPair$1, 'priv', function priv() { - return this.eddsa.decodeInt(this.privBytes()); -}); - -cachedProperty(KeyPair$1, 'hash', function hash() { - return this.eddsa.hash().update(this.secret()).digest(); -}); - -cachedProperty(KeyPair$1, 'messagePrefix', function messagePrefix() { - return this.hash().slice(this.eddsa.encodingLength); -}); - -KeyPair$1.prototype.sign = function sign(message) { - assert$8(this._secret, 'KeyPair can only verify'); - return this.eddsa.sign(message, this); -}; - -KeyPair$1.prototype.verify = function verify(message, sig) { - return this.eddsa.verify(message, sig, this); -}; - -KeyPair$1.prototype.getSecret = function getSecret(enc) { - assert$8(this._secret, 'KeyPair is public only'); - return utils_1$1.encode(this.secret(), enc); -}; - -KeyPair$1.prototype.getPublic = function getPublic(enc, compact) { - return utils_1$1.encode((compact ? [ 0x40 ] : []).concat(this.pubBytes()), enc); -}; - -var key$1 = KeyPair$1; - -var assert$9 = utils_1$1.assert; -var cachedProperty$1 = utils_1$1.cachedProperty; -var parseBytes$1 = utils_1$1.parseBytes; - -/** -* @param {EDDSA} eddsa - eddsa instance -* @param {Array|Object} sig - -* @param {Array|Point} [sig.R] - R point as Point or bytes -* @param {Array|bn} [sig.S] - S scalar as bn or bytes -* @param {Array} [sig.Rencoded] - R point encoded -* @param {Array} [sig.Sencoded] - S scalar encoded -*/ -function Signature$2(eddsa, sig) { - this.eddsa = eddsa; - - if (typeof sig !== 'object') - sig = parseBytes$1(sig); - - if (Array.isArray(sig)) { - sig = { - R: sig.slice(0, eddsa.encodingLength), - S: sig.slice(eddsa.encodingLength) - }; - } - - assert$9(sig.R && sig.S, 'Signature without R or S'); - - if (eddsa.isPoint(sig.R)) - this._R = sig.R; - if (sig.S instanceof bn) - this._S = sig.S; - - this._Rencoded = Array.isArray(sig.R) ? sig.R : sig.Rencoded; - this._Sencoded = Array.isArray(sig.S) ? sig.S : sig.Sencoded; -} - -cachedProperty$1(Signature$2, 'S', function S() { - return this.eddsa.decodeInt(this.Sencoded()); -}); - -cachedProperty$1(Signature$2, 'R', function R() { - return this.eddsa.decodePoint(this.Rencoded()); -}); - -cachedProperty$1(Signature$2, 'Rencoded', function Rencoded() { - return this.eddsa.encodePoint(this.R()); -}); - -cachedProperty$1(Signature$2, 'Sencoded', function Sencoded() { - return this.eddsa.encodeInt(this.S()); -}); - -Signature$2.prototype.toBytes = function toBytes() { - return this.Rencoded().concat(this.Sencoded()); -}; - -Signature$2.prototype.toHex = function toHex() { - return utils_1$1.encode(this.toBytes(), 'hex').toUpperCase(); -}; - -var signature$2 = Signature$2; - -var assert$a = utils_1$1.assert; -var parseBytes$2 = utils_1$1.parseBytes; - - - -function EDDSA(curve) { - assert$a(curve === 'ed25519', 'only tested with ed25519 so far'); - - if (!(this instanceof EDDSA)) - return new EDDSA(curve); - - var curve = curves_1[curve].curve; - this.curve = curve; - this.g = curve.g; - this.g.precompute(curve.n.bitLength() + 1); - - this.pointClass = curve.point().constructor; - this.encodingLength = Math.ceil(curve.n.bitLength() / 8); - this.hash = hash_1.sha512; -} - -var eddsa$1 = EDDSA; - -/** -* @param {Array|String} message - message bytes -* @param {Array|String|KeyPair} secret - secret bytes or a keypair -* @returns {Signature} - signature -*/ -EDDSA.prototype.sign = function sign(message, secret) { - message = parseBytes$2(message); - var key = this.keyFromSecret(secret); - var r = this.hashInt(key.messagePrefix(), message); - var R = this.g.mul(r); - var Rencoded = this.encodePoint(R); - var s_ = this.hashInt(Rencoded, key.pubBytes(), message) - .mul(key.priv()); - var S = r.add(s_).umod(this.curve.n); - return this.makeSignature({ R: R, S: S, Rencoded: Rencoded }); -}; - -/** -* @param {Array} message - message bytes -* @param {Array|String|Signature} sig - sig bytes -* @param {Array|String|Point|KeyPair} pub - public key -* @returns {Boolean} - true if public key matches sig of message -*/ -EDDSA.prototype.verify = function verify(message, sig, pub) { - message = parseBytes$2(message); - sig = this.makeSignature(sig); - var key = this.keyFromPublic(pub); - var h = this.hashInt(sig.Rencoded(), key.pubBytes(), message); - var SG = this.g.mul(sig.S()); - var RplusAh = sig.R().add(key.pub().mul(h)); - return RplusAh.eq(SG); -}; - -EDDSA.prototype.hashInt = function hashInt() { - var hash = this.hash(); - for (var i = 0; i < arguments.length; i++) - hash.update(arguments[i]); - return utils_1$1.intFromLE(hash.digest()).umod(this.curve.n); -}; - -EDDSA.prototype.keyPair = function keyPair(options) { - return new key$1(this, options); -}; - -EDDSA.prototype.keyFromPublic = function keyFromPublic(pub) { - return key$1.fromPublic(this, pub); -}; - -EDDSA.prototype.keyFromSecret = function keyFromSecret(secret) { - return key$1.fromSecret(this, secret); -}; - -EDDSA.prototype.genKeyPair = function genKeyPair(options) { - if (!options) - options = {}; - - // Instantiate Hmac_DRBG - var drbg = new hmacDrbg({ - hash: this.hash, - pers: options.pers, - persEnc: options.persEnc || 'utf8', - entropy: options.entropy || brorand(this.hash.hmacStrength), - entropyEnc: options.entropy && options.entropyEnc || 'utf8', - nonce: this.curve.n.toArray() - }); - - return this.keyFromSecret(drbg.generate(32)); -}; - -EDDSA.prototype.makeSignature = function makeSignature(sig) { - if (sig instanceof signature$2) - return sig; - return new signature$2(this, sig); -}; - -/** -* * https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03#section-5.2 -* -* EDDSA defines methods for encoding and decoding points and integers. These are -* helper convenience methods, that pass along to utility functions implied -* parameters. -* -*/ -EDDSA.prototype.encodePoint = function encodePoint(point) { - var enc = point.getY().toArray('le', this.encodingLength); - enc[this.encodingLength - 1] |= point.getX().isOdd() ? 0x80 : 0; - return enc; -}; - -EDDSA.prototype.decodePoint = function decodePoint(bytes) { - bytes = utils_1$1.parseBytes(bytes); - - var lastIx = bytes.length - 1; - var normed = bytes.slice(0, lastIx).concat(bytes[lastIx] & ~0x80); - var xIsOdd = (bytes[lastIx] & 0x80) !== 0; - - var y = utils_1$1.intFromLE(normed); - return this.curve.pointFromY(y, xIsOdd); -}; - -EDDSA.prototype.encodeInt = function encodeInt(num) { - return num.toArray('le', this.encodingLength); -}; - -EDDSA.prototype.decodeInt = function decodeInt(bytes) { - return utils_1$1.intFromLE(bytes); -}; - -EDDSA.prototype.isPoint = function isPoint(val) { - return val instanceof this.pointClass; -}; - -var elliptic_1 = createCommonjsModule(function (module, exports) { - -var elliptic = exports; - -elliptic.utils = utils_1$1; -elliptic.rand = brorand; -elliptic.curve = curve_1; -elliptic.curves = curves_1; - -// Protocols -elliptic.ec = ec; -elliptic.eddsa = eddsa$1; -}); - -var elliptic$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - 'default': elliptic_1, - __moduleExports: elliptic_1 -}); - -exports.AEADEncryptedDataPacket = AEADEncryptedDataPacket; -exports.CleartextMessage = CleartextMessage; -exports.CompressedDataPacket = CompressedDataPacket; -exports.LiteralDataPacket = LiteralDataPacket; -exports.MarkerPacket = MarkerPacket; -exports.Message = Message; -exports.OnePassSignaturePacket = OnePassSignaturePacket; -exports.PacketList = PacketList; -exports.PrivateKey = PrivateKey; -exports.PublicKey = PublicKey; -exports.PublicKeyEncryptedSessionKeyPacket = PublicKeyEncryptedSessionKeyPacket; -exports.PublicKeyPacket = PublicKeyPacket; -exports.PublicSubkeyPacket = PublicSubkeyPacket; -exports.SecretKeyPacket = SecretKeyPacket; -exports.SecretSubkeyPacket = SecretSubkeyPacket; -exports.Signature = Signature; -exports.SignaturePacket = SignaturePacket; -exports.Subkey = Subkey; -exports.SymEncryptedIntegrityProtectedDataPacket = SymEncryptedIntegrityProtectedDataPacket; -exports.SymEncryptedSessionKeyPacket = SymEncryptedSessionKeyPacket; -exports.SymmetricallyEncryptedDataPacket = SymmetricallyEncryptedDataPacket; -exports.TrustPacket = TrustPacket; -exports.UserAttributePacket = UserAttributePacket; -exports.UserIDPacket = UserIDPacket; -exports.armor = armor; -exports.config = defaultConfig; -exports.createCleartextMessage = createCleartextMessage; -exports.createMessage = createMessage; -exports.decrypt = decrypt$4; -exports.decryptKey = decryptKey; -exports.decryptSessionKeys = decryptSessionKeys; -exports.encrypt = encrypt$4; -exports.encryptKey = encryptKey; -exports.encryptSessionKey = encryptSessionKey; -exports.enums = enums; -exports.generateKey = generateKey; -exports.generateSessionKey = generateSessionKey$1; -exports.readCleartextMessage = readCleartextMessage; -exports.readKey = readKey; -exports.readKeys = readKeys; -exports.readMessage = readMessage; -exports.readPrivateKey = readPrivateKey; -exports.readPrivateKeys = readPrivateKeys; -exports.readSignature = readSignature; -exports.reformatKey = reformatKey; -exports.revokeKey = revokeKey; -exports.sign = sign$5; -exports.unarmor = unarmor; -exports.verify = verify$5; - -// -----BEGIN ADDED BY FLOWCRYPT---- -exports.readToEnd = readToEnd; -exports.util = util; -// -----END ADDED BY FLOWCRYPT----- diff --git a/Core/source/lib/openpgpjs-v5/dist/openpgp.js b/Core/source/lib/openpgpjs-v5/dist/openpgp.js deleted file mode 100644 index 507c8c2b5..000000000 --- a/Core/source/lib/openpgpjs-v5/dist/openpgp.js +++ /dev/null @@ -1,43534 +0,0 @@ -/*! OpenPGP.js v5.1.0 - 2022-01-24 - this is LGPL licensed code, see LICENSE/our website https://openpgpjs.org/ for more information. */ -var openpgp = (function (exports) { - 'use strict'; - - const globalThis = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; - - const doneWritingPromise = Symbol('doneWritingPromise'); - const doneWritingResolve = Symbol('doneWritingResolve'); - const doneWritingReject = Symbol('doneWritingReject'); - - const readingIndex = Symbol('readingIndex'); - - class ArrayStream extends Array { - constructor() { - super(); - this[doneWritingPromise] = new Promise((resolve, reject) => { - this[doneWritingResolve] = resolve; - this[doneWritingReject] = reject; - }); - this[doneWritingPromise].catch(() => {}); - } - } - - ArrayStream.prototype.getReader = function() { - if (this[readingIndex] === undefined) { - this[readingIndex] = 0; - } - return { - read: async () => { - await this[doneWritingPromise]; - if (this[readingIndex] === this.length) { - return { value: undefined, done: true }; - } - return { value: this[this[readingIndex]++], done: false }; - } - }; - }; - - ArrayStream.prototype.readToEnd = async function(join) { - await this[doneWritingPromise]; - const result = join(this.slice(this[readingIndex])); - this.length = 0; - return result; - }; - - ArrayStream.prototype.clone = function() { - const clone = new ArrayStream(); - clone[doneWritingPromise] = this[doneWritingPromise].then(() => { - clone.push(...this); - }); - return clone; - }; - - /** - * Check whether data is an ArrayStream - * @param {Any} input data to check - * @returns {boolean} - */ - function isArrayStream(input) { - return input && input.getReader && Array.isArray(input); - } - - /** - * A wrapper class over the native WritableStreamDefaultWriter. - * It also lets you "write data to" array streams instead of streams. - * @class - */ - function Writer(input) { - if (!isArrayStream(input)) { - const writer = input.getWriter(); - const releaseLock = writer.releaseLock; - writer.releaseLock = () => { - writer.closed.catch(function() {}); - releaseLock.call(writer); - }; - return writer; - } - this.stream = input; - } - - /** - * Write a chunk of data. - * @returns {Promise} - * @async - */ - Writer.prototype.write = async function(chunk) { - this.stream.push(chunk); - }; - - /** - * Close the stream. - * @returns {Promise} - * @async - */ - Writer.prototype.close = async function() { - this.stream[doneWritingResolve](); - }; - - /** - * Error the stream. - * @returns {Promise} - * @async - */ - Writer.prototype.abort = async function(reason) { - this.stream[doneWritingReject](reason); - return reason; - }; - - /** - * Release the writer's lock. - * @returns {undefined} - * @async - */ - Writer.prototype.releaseLock = function() {}; - - const isNode = typeof globalThis.process === 'object' && - typeof globalThis.process.versions === 'object'; - - const NodeReadableStream = isNode && void('stream').Readable; - - /** - * Check whether data is a Stream, and if so of which type - * @param {Any} input data to check - * @returns {'web'|'ponyfill'|'node'|'array'|'web-like'|false} - */ - function isStream(input) { - if (isArrayStream(input)) { - return 'array'; - } - if (globalThis.ReadableStream && globalThis.ReadableStream.prototype.isPrototypeOf(input)) { - return 'web'; - } - if (ReadableStream && ReadableStream.prototype.isPrototypeOf(input)) { - return 'ponyfill'; - } - if (NodeReadableStream && NodeReadableStream.prototype.isPrototypeOf(input)) { - return 'node'; - } - if (input && input.getReader) { - return 'web-like'; - } - return false; - } - - /** - * Check whether data is a Uint8Array - * @param {Any} input data to check - * @returns {Boolean} - */ - function isUint8Array(input) { - return Uint8Array.prototype.isPrototypeOf(input); - } - - /** - * Concat Uint8Arrays - * @param {Array} Array of Uint8Arrays to concatenate - * @returns {Uint8array} Concatenated array - */ - function concatUint8Array(arrays) { - if (arrays.length === 1) return arrays[0]; - - let totalLength = 0; - for (let i = 0; i < arrays.length; i++) { - if (!isUint8Array(arrays[i])) { - throw new Error('concatUint8Array: Data must be in the form of a Uint8Array'); - } - - totalLength += arrays[i].length; - } - - const result = new Uint8Array(totalLength); - let pos = 0; - arrays.forEach(function (element) { - result.set(element, pos); - pos += element.length; - }); - - return result; - } - - const NodeBuffer = isNode && void('buffer').Buffer; - const NodeReadableStream$1 = isNode && void('stream').Readable; - - /** - * Web / node stream conversion functions - * From https://github.com/gwicke/node-web-streams - */ - - let nodeToWeb; - let webToNode; - - if (NodeReadableStream$1) { - - /** - * Convert a Node Readable Stream to a Web ReadableStream - * @param {Readable} nodeStream - * @returns {ReadableStream} - */ - nodeToWeb = function(nodeStream) { - let canceled = false; - return new ReadableStream({ - start(controller) { - nodeStream.pause(); - nodeStream.on('data', chunk => { - if (canceled) { - return; - } - if (NodeBuffer.isBuffer(chunk)) { - chunk = new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength); - } - controller.enqueue(chunk); - nodeStream.pause(); - }); - nodeStream.on('end', () => { - if (canceled) { - return; - } - controller.close(); - }); - nodeStream.on('error', e => controller.error(e)); - }, - pull() { - nodeStream.resume(); - }, - cancel(reason) { - canceled = true; - nodeStream.destroy(reason); - } - }); - }; - - - class NodeReadable extends NodeReadableStream$1 { - constructor(webStream, options) { - super(options); - this._reader = getReader(webStream); - } - - async _read(size) { - try { - while (true) { - const { done, value } = await this._reader.read(); - if (done) { - this.push(null); - break; - } - if (!this.push(value) || this._cancelling) { - this._reading = false; - break; - } - } - } catch(e) { - this.emit('error', e); - } - } - - _destroy(reason) { - this._reader.cancel(reason); - } - } - - /** - * Convert a Web ReadableStream to a Node Readable Stream - * @param {ReadableStream} webStream - * @param {Object} options - * @returns {Readable} - */ - webToNode = function(webStream, options) { - return new NodeReadable(webStream, options); - }; - - } - - const doneReadingSet = new WeakSet(); - const externalBuffer = Symbol('externalBuffer'); - - /** - * A wrapper class over the native ReadableStreamDefaultReader. - * This additionally implements pushing back data on the stream, which - * lets us implement peeking and a host of convenience functions. - * It also lets you read data other than streams, such as a Uint8Array. - * @class - */ - function Reader(input) { - this.stream = input; - if (input[externalBuffer]) { - this[externalBuffer] = input[externalBuffer].slice(); - } - if (isArrayStream(input)) { - const reader = input.getReader(); - this._read = reader.read.bind(reader); - this._releaseLock = () => {}; - this._cancel = () => {}; - return; - } - let streamType = isStream(input); - if (streamType === 'node') { - input = nodeToWeb(input); - } - if (streamType) { - const reader = input.getReader(); - this._read = reader.read.bind(reader); - this._releaseLock = () => { - reader.closed.catch(function() {}); - reader.releaseLock(); - }; - this._cancel = reader.cancel.bind(reader); - return; - } - let doneReading = false; - this._read = async () => { - if (doneReading || doneReadingSet.has(input)) { - return { value: undefined, done: true }; - } - doneReading = true; - return { value: input, done: false }; - }; - this._releaseLock = () => { - if (doneReading) { - try { - doneReadingSet.add(input); - } catch(e) {} - } - }; - } - - /** - * Read a chunk of data. - * @returns {Promise} Either { done: false, value: Uint8Array | String } or { done: true, value: undefined } - * @async - */ - Reader.prototype.read = async function() { - if (this[externalBuffer] && this[externalBuffer].length) { - const value = this[externalBuffer].shift(); - return { done: false, value }; - } - return this._read(); - }; - - /** - * Allow others to read the stream. - */ - Reader.prototype.releaseLock = function() { - if (this[externalBuffer]) { - this.stream[externalBuffer] = this[externalBuffer]; - } - this._releaseLock(); - }; - - /** - * Cancel the stream. - */ - Reader.prototype.cancel = function(reason) { - return this._cancel(reason); - }; - - /** - * Read up to and including the first \n character. - * @returns {Promise} - * @async - */ - Reader.prototype.readLine = async function() { - let buffer = []; - let returnVal; - while (!returnVal) { - let { done, value } = await this.read(); - value += ''; - if (done) { - if (buffer.length) return concat(buffer); - return; - } - const lineEndIndex = value.indexOf('\n') + 1; - if (lineEndIndex) { - returnVal = concat(buffer.concat(value.substr(0, lineEndIndex))); - buffer = []; - } - if (lineEndIndex !== value.length) { - buffer.push(value.substr(lineEndIndex)); - } - } - this.unshift(...buffer); - return returnVal; - }; - - /** - * Read a single byte/character. - * @returns {Promise} - * @async - */ - Reader.prototype.readByte = async function() { - const { done, value } = await this.read(); - if (done) return; - const byte = value[0]; - this.unshift(slice(value, 1)); - return byte; - }; - - /** - * Read a specific amount of bytes/characters, unless the stream ends before that amount. - * @returns {Promise} - * @async - */ - Reader.prototype.readBytes = async function(length) { - const buffer = []; - let bufferLength = 0; - while (true) { - const { done, value } = await this.read(); - if (done) { - if (buffer.length) return concat(buffer); - return; - } - buffer.push(value); - bufferLength += value.length; - if (bufferLength >= length) { - const bufferConcat = concat(buffer); - this.unshift(slice(bufferConcat, length)); - return slice(bufferConcat, 0, length); - } - } - }; - - /** - * Peek (look ahead) a specific amount of bytes/characters, unless the stream ends before that amount. - * @returns {Promise} - * @async - */ - Reader.prototype.peekBytes = async function(length) { - const bytes = await this.readBytes(length); - this.unshift(bytes); - return bytes; - }; - - /** - * Push data to the front of the stream. - * Data must have been read in the last call to read*. - * @param {...(Uint8Array|String|Undefined)} values - */ - Reader.prototype.unshift = function(...values) { - if (!this[externalBuffer]) { - this[externalBuffer] = []; - } - if ( - values.length === 1 && isUint8Array(values[0]) && - this[externalBuffer].length && values[0].length && - this[externalBuffer][0].byteOffset >= values[0].length - ) { - this[externalBuffer][0] = new Uint8Array( - this[externalBuffer][0].buffer, - this[externalBuffer][0].byteOffset - values[0].length, - this[externalBuffer][0].byteLength + values[0].length - ); - return; - } - this[externalBuffer].unshift(...values.filter(value => value && value.length)); - }; - - /** - * Read the stream to the end and return its contents, concatenated by the join function (defaults to streams.concat). - * @param {Function} join - * @returns {Promise} the return value of join() - * @async - */ - Reader.prototype.readToEnd = async function(join=concat) { - const result = []; - while (true) { - const { done, value } = await this.read(); - if (done) break; - result.push(value); - } - return join(result); - }; - - let { ReadableStream, WritableStream, TransformStream } = globalThis; - - let toPonyfillReadable, toNativeReadable; - - async function loadStreamsPonyfill() { - if (TransformStream) { - return; - } - - const [ponyfill, adapter] = await Promise.all([ - Promise.resolve().then(function () { return ponyfill_es6; }), - Promise.resolve().then(function () { return webStreamsAdapter; }) - ]); - - ({ ReadableStream, WritableStream, TransformStream } = ponyfill); - - const { createReadableStreamWrapper } = adapter; - - if (globalThis.ReadableStream && ReadableStream !== globalThis.ReadableStream) { - toPonyfillReadable = createReadableStreamWrapper(ReadableStream); - toNativeReadable = createReadableStreamWrapper(globalThis.ReadableStream); - } - } - - const NodeBuffer$1 = isNode && void('buffer').Buffer; - - /** - * Convert data to Stream - * @param {ReadableStream|Uint8array|String} input data to convert - * @returns {ReadableStream} Converted data - */ - function toStream(input) { - let streamType = isStream(input); - if (streamType === 'node') { - return nodeToWeb(input); - } - if (streamType === 'web' && toPonyfillReadable) { - return toPonyfillReadable(input); - } - if (streamType) { - return input; - } - return new ReadableStream({ - start(controller) { - controller.enqueue(input); - controller.close(); - } - }); - } - - /** - * Convert data to ArrayStream - * @param {Object} input data to convert - * @returns {ArrayStream} Converted data - */ - function toArrayStream(input) { - if (isStream(input)) { - return input; - } - const stream = new ArrayStream(); - (async () => { - const writer = getWriter(stream); - await writer.write(input); - await writer.close(); - })(); - return stream; - } - - /** - * Concat a list of Uint8Arrays, Strings or Streams - * The caller should not mix Uint8Arrays with Strings, but may mix Streams with non-Streams. - * @param {Array} Array of Uint8Arrays/Strings/Streams to concatenate - * @returns {Uint8array|String|ReadableStream} Concatenated array - */ - function concat(list) { - if (list.some(stream => isStream(stream) && !isArrayStream(stream))) { - return concatStream(list); - } - if (list.some(stream => isArrayStream(stream))) { - return concatArrayStream(list); - } - if (typeof list[0] === 'string') { - return list.join(''); - } - if (NodeBuffer$1 && NodeBuffer$1.isBuffer(list[0])) { - return NodeBuffer$1.concat(list); - } - return concatUint8Array(list); - } - - /** - * Concat a list of Streams - * @param {Array} list Array of Uint8Arrays/Strings/Streams to concatenate - * @returns {ReadableStream} Concatenated list - */ - function concatStream(list) { - list = list.map(toStream); - const transform = transformWithCancel(async function(reason) { - await Promise.all(transforms.map(stream => cancel(stream, reason))); - }); - let prev = Promise.resolve(); - const transforms = list.map((stream, i) => transformPair(stream, (readable, writable) => { - prev = prev.then(() => pipe(readable, transform.writable, { - preventClose: i !== list.length - 1 - })); - return prev; - })); - return transform.readable; - } - - /** - * Concat a list of ArrayStreams - * @param {Array} list Array of Uint8Arrays/Strings/ArrayStreams to concatenate - * @returns {ArrayStream} Concatenated streams - */ - function concatArrayStream(list) { - const result = new ArrayStream(); - let prev = Promise.resolve(); - list.forEach((stream, i) => { - prev = prev.then(() => pipe(stream, result, { - preventClose: i !== list.length - 1 - })); - return prev; - }); - return result; - } - - /** - * Get a Reader - * @param {ReadableStream|Uint8array|String} input - * @returns {Reader} - */ - function getReader(input) { - return new Reader(input); - } - - /** - * Get a Writer - * @param {WritableStream} input - * @returns {Writer} - */ - function getWriter(input) { - return new Writer(input); - } - - /** - * Pipe a readable stream to a writable stream. Don't throw on input stream errors, but forward them to the output stream. - * @param {ReadableStream|Uint8array|String} input - * @param {WritableStream} target - * @param {Object} (optional) options - * @returns {Promise} Promise indicating when piping has finished (input stream closed or errored) - * @async - */ - async function pipe(input, target, { - preventClose = false, - preventAbort = false, - preventCancel = false - } = {}) { - if (isStream(input) && !isArrayStream(input)) { - input = toStream(input); - try { - if (input[externalBuffer]) { - const writer = getWriter(target); - for (let i = 0; i < input[externalBuffer].length; i++) { - await writer.ready; - await writer.write(input[externalBuffer][i]); - } - writer.releaseLock(); - } - await input.pipeTo(target, { - preventClose, - preventAbort, - preventCancel - }); - } catch(e) {} - return; - } - input = toArrayStream(input); - const reader = getReader(input); - const writer = getWriter(target); - try { - while (true) { - await writer.ready; - const { done, value } = await reader.read(); - if (done) { - if (!preventClose) await writer.close(); - break; - } - await writer.write(value); - } - } catch (e) { - if (!preventAbort) await writer.abort(e); - } finally { - reader.releaseLock(); - writer.releaseLock(); - } - } - - /** - * Pipe a readable stream through a transform stream. - * @param {ReadableStream|Uint8array|String} input - * @param {Object} (optional) options - * @returns {ReadableStream} transformed stream - */ - function transformRaw(input, options) { - const transformStream = new TransformStream(options); - pipe(input, transformStream.writable); - return transformStream.readable; - } - - /** - * Create a cancelable TransformStream. - * @param {Function} cancel - * @returns {TransformStream} - */ - function transformWithCancel(cancel) { - let pulled = false; - let backpressureChangePromiseResolve; - let outputController; - return { - readable: new ReadableStream({ - start(controller) { - outputController = controller; - }, - pull() { - if (backpressureChangePromiseResolve) { - backpressureChangePromiseResolve(); - } else { - pulled = true; - } - }, - cancel - }, {highWaterMark: 0}), - writable: new WritableStream({ - write: async function(chunk) { - outputController.enqueue(chunk); - if (!pulled) { - await new Promise(resolve => { - backpressureChangePromiseResolve = resolve; - }); - backpressureChangePromiseResolve = null; - } else { - pulled = false; - } - }, - close: outputController.close.bind(outputController), - abort: outputController.error.bind(outputController) - }) - }; - } - - /** - * Transform a stream using helper functions which are called on each chunk, and on stream close, respectively. - * @param {ReadableStream|Uint8array|String} input - * @param {Function} process - * @param {Function} finish - * @returns {ReadableStream|Uint8array|String} - */ - function transform(input, process = () => undefined, finish = () => undefined) { - if (isArrayStream(input)) { - const output = new ArrayStream(); - (async () => { - const data = await readToEnd(input); - const result1 = process(data); - const result2 = finish(); - let result; - if (result1 !== undefined && result2 !== undefined) result = concat([result1, result2]); - else result = result1 !== undefined ? result1 : result2; - const writer = getWriter(output); - await writer.write(result); - await writer.close(); - })(); - return output; - } - if (isStream(input)) { - return transformRaw(input, { - async transform(value, controller) { - try { - const result = await process(value); - if (result !== undefined) controller.enqueue(result); - } catch(e) { - controller.error(e); - } - }, - async flush(controller) { - try { - const result = await finish(); - if (result !== undefined) controller.enqueue(result); - } catch(e) { - controller.error(e); - } - } - }); - } - const result1 = process(input); - const result2 = finish(); - if (result1 !== undefined && result2 !== undefined) return concat([result1, result2]); - return result1 !== undefined ? result1 : result2; - } - - /** - * Transform a stream using a helper function which is passed a readable and a writable stream. - * This function also maintains the possibility to cancel the input stream, - * and does so on cancelation of the output stream, despite cancelation - * normally being impossible when the input stream is being read from. - * @param {ReadableStream|Uint8array|String} input - * @param {Function} fn - * @returns {ReadableStream} - */ - function transformPair(input, fn) { - if (isStream(input) && !isArrayStream(input)) { - let incomingTransformController; - const incoming = new TransformStream({ - start(controller) { - incomingTransformController = controller; - } - }); - - const pipeDonePromise = pipe(input, incoming.writable); - - const outgoing = transformWithCancel(async function() { - incomingTransformController.error(new Error('Readable side was canceled.')); - await pipeDonePromise; - await new Promise(setTimeout); - }); - fn(incoming.readable, outgoing.writable); - return outgoing.readable; - } - input = toArrayStream(input); - const output = new ArrayStream(); - fn(input, output); - return output; - } - - /** - * Parse a stream using a helper function which is passed a Reader. - * The reader additionally has a remainder() method which returns a - * stream pointing to the remainder of input, and is linked to input - * for cancelation. - * @param {ReadableStream|Uint8array|String} input - * @param {Function} fn - * @returns {Any} the return value of fn() - */ - function parse(input, fn) { - let returnValue; - const transformed = transformPair(input, (readable, writable) => { - const reader = getReader(readable); - reader.remainder = () => { - reader.releaseLock(); - pipe(readable, writable); - return transformed; - }; - returnValue = fn(reader); - }); - return returnValue; - } - - /** - * Tee a Stream for reading it twice. The input stream can no longer be read after tee()ing. - * Reading either of the two returned streams will pull from the input stream. - * The input stream will only be canceled if both of the returned streams are canceled. - * @param {ReadableStream|Uint8array|String} input - * @returns {Array} array containing two copies of input - */ - function tee(input) { - if (isArrayStream(input)) { - throw new Error('ArrayStream cannot be tee()d, use clone() instead'); - } - if (isStream(input)) { - const teed = toStream(input).tee(); - teed[0][externalBuffer] = teed[1][externalBuffer] = input[externalBuffer]; - return teed; - } - return [slice(input), slice(input)]; - } - - /** - * Clone a Stream for reading it twice. The input stream can still be read after clone()ing. - * Reading from the clone will pull from the input stream. - * The input stream will only be canceled if both the clone and the input stream are canceled. - * @param {ReadableStream|Uint8array|String} input - * @returns {ReadableStream|Uint8array|String} cloned input - */ - function clone(input) { - if (isArrayStream(input)) { - return input.clone(); - } - if (isStream(input)) { - const teed = tee(input); - overwrite(input, teed[0]); - return teed[1]; - } - return slice(input); - } - - /** - * Clone a Stream for reading it twice. Data will arrive at the same rate as the input stream is being read. - * Reading from the clone will NOT pull from the input stream. Data only arrives when reading the input stream. - * The input stream will NOT be canceled if the clone is canceled, only if the input stream are canceled. - * If the input stream is canceled, the clone will be errored. - * @param {ReadableStream|Uint8array|String} input - * @returns {ReadableStream|Uint8array|String} cloned input - */ - function passiveClone(input) { - if (isArrayStream(input)) { - return clone(input); - } - if (isStream(input)) { - return new ReadableStream({ - start(controller) { - const transformed = transformPair(input, async (readable, writable) => { - const reader = getReader(readable); - const writer = getWriter(writable); - try { - while (true) { - await writer.ready; - const { done, value } = await reader.read(); - if (done) { - try { controller.close(); } catch(e) {} - await writer.close(); - return; - } - try { controller.enqueue(value); } catch(e) {} - await writer.write(value); - } - } catch(e) { - controller.error(e); - await writer.abort(e); - } - }); - overwrite(input, transformed); - } - }); - } - return slice(input); - } - - /** - * Modify a stream object to point to a different stream object. - * This is used internally by clone() and passiveClone() to provide an abstraction over tee(). - * @param {ReadableStream} input - * @param {ReadableStream} clone - */ - function overwrite(input, clone) { - // Overwrite input.getReader, input.locked, etc to point to clone - Object.entries(Object.getOwnPropertyDescriptors(input.constructor.prototype)).forEach(([name, descriptor]) => { - if (name === 'constructor') { - return; - } - if (descriptor.value) { - descriptor.value = descriptor.value.bind(clone); - } else { - descriptor.get = descriptor.get.bind(clone); - } - Object.defineProperty(input, name, descriptor); - }); - } - - /** - * Return a stream pointing to a part of the input stream. - * @param {ReadableStream|Uint8array|String} input - * @returns {ReadableStream|Uint8array|String} clone - */ - function slice(input, begin=0, end=Infinity) { - if (isArrayStream(input)) { - throw new Error('Not implemented'); - } - if (isStream(input)) { - if (begin >= 0 && end >= 0) { - let bytesRead = 0; - return transformRaw(input, { - transform(value, controller) { - if (bytesRead < end) { - if (bytesRead + value.length >= begin) { - controller.enqueue(slice(value, Math.max(begin - bytesRead, 0), end - bytesRead)); - } - bytesRead += value.length; - } else { - controller.terminate(); - } - } - }); - } - if (begin < 0 && (end < 0 || end === Infinity)) { - let lastBytes = []; - return transform(input, value => { - if (value.length >= -begin) lastBytes = [value]; - else lastBytes.push(value); - }, () => slice(concat(lastBytes), begin, end)); - } - if (begin === 0 && end < 0) { - let lastBytes; - return transform(input, value => { - const returnValue = lastBytes ? concat([lastBytes, value]) : value; - if (returnValue.length >= -end) { - lastBytes = slice(returnValue, end); - return slice(returnValue, begin, end); - } else { - lastBytes = returnValue; - } - }); - } - console.warn(`stream.slice(input, ${begin}, ${end}) not implemented efficiently.`); - return fromAsync(async () => slice(await readToEnd(input), begin, end)); - } - if (input[externalBuffer]) { - input = concat(input[externalBuffer].concat([input])); - } - if (isUint8Array(input) && !(NodeBuffer$1 && NodeBuffer$1.isBuffer(input))) { - if (end === Infinity) end = input.length; - return input.subarray(begin, end); - } - return input.slice(begin, end); - } - - /** - * Read a stream to the end and return its contents, concatenated by the join function (defaults to concat). - * @param {ReadableStream|Uint8array|String} input - * @param {Function} join - * @returns {Promise} the return value of join() - * @async - */ - async function readToEnd(input, join=concat) { - if (isArrayStream(input)) { - return input.readToEnd(join); - } - if (isStream(input)) { - return getReader(input).readToEnd(join); - } - return input; - } - - /** - * Cancel a stream. - * @param {ReadableStream|Uint8array|String} input - * @param {Any} reason - * @returns {Promise} indicates when the stream has been canceled - * @async - */ - async function cancel(input, reason) { - if (isStream(input)) { - if (input.cancel) { - return input.cancel(reason); - } - if (input.destroy) { - input.destroy(reason); - await new Promise(setTimeout); - return reason; - } - } - } - - /** - * Convert an async function to an ArrayStream. When the function returns, its return value is written to the stream. - * @param {Function} fn - * @returns {ArrayStream} - */ - function fromAsync(fn) { - const arrayStream = new ArrayStream(); - (async () => { - const writer = getWriter(arrayStream); - try { - await writer.write(await fn()); - await writer.close(); - } catch (e) { - await writer.abort(e); - } - })(); - return arrayStream; - } - - /* eslint-disable new-cap */ - - /** - * @fileoverview - * BigInteger implementation of basic operations - * that wraps the native BigInt library. - * Operations are not constant time, - * but we try and limit timing leakage where we can - * @module biginteger/native - * @private - */ - - /** - * @private - */ - class BigInteger { - /** - * Get a BigInteger (input must be big endian for strings and arrays) - * @param {Number|String|Uint8Array} n - Value to convert - * @throws {Error} on null or undefined input - */ - constructor(n) { - if (n === undefined) { - throw new Error('Invalid BigInteger input'); - } - - if (n instanceof Uint8Array) { - const bytes = n; - const hex = new Array(bytes.length); - for (let i = 0; i < bytes.length; i++) { - const hexByte = bytes[i].toString(16); - hex[i] = (bytes[i] <= 0xF) ? ('0' + hexByte) : hexByte; - } - this.value = BigInt('0x0' + hex.join('')); - } else { - this.value = BigInt(n); - } - } - - clone() { - return new BigInteger(this.value); - } - - /** - * BigInteger increment in place - */ - iinc() { - this.value++; - return this; - } - - /** - * BigInteger increment - * @returns {BigInteger} this + 1. - */ - inc() { - return this.clone().iinc(); - } - - /** - * BigInteger decrement in place - */ - idec() { - this.value--; - return this; - } - - /** - * BigInteger decrement - * @returns {BigInteger} this - 1. - */ - dec() { - return this.clone().idec(); - } - - /** - * BigInteger addition in place - * @param {BigInteger} x - Value to add - */ - iadd(x) { - this.value += x.value; - return this; - } - - /** - * BigInteger addition - * @param {BigInteger} x - Value to add - * @returns {BigInteger} this + x. - */ - add(x) { - return this.clone().iadd(x); - } - - /** - * BigInteger subtraction in place - * @param {BigInteger} x - Value to subtract - */ - isub(x) { - this.value -= x.value; - return this; - } - - /** - * BigInteger subtraction - * @param {BigInteger} x - Value to subtract - * @returns {BigInteger} this - x. - */ - sub(x) { - return this.clone().isub(x); - } - - /** - * BigInteger multiplication in place - * @param {BigInteger} x - Value to multiply - */ - imul(x) { - this.value *= x.value; - return this; - } - - /** - * BigInteger multiplication - * @param {BigInteger} x - Value to multiply - * @returns {BigInteger} this * x. - */ - mul(x) { - return this.clone().imul(x); - } - - /** - * Compute value modulo m, in place - * @param {BigInteger} m - Modulo - */ - imod(m) { - this.value %= m.value; - if (this.isNegative()) { - this.iadd(m); - } - return this; - } - - /** - * Compute value modulo m - * @param {BigInteger} m - Modulo - * @returns {BigInteger} this mod m. - */ - mod(m) { - return this.clone().imod(m); - } - - /** - * Compute modular exponentiation using square and multiply - * @param {BigInteger} e - Exponent - * @param {BigInteger} n - Modulo - * @returns {BigInteger} this ** e mod n. - */ - modExp(e, n) { - if (n.isZero()) throw Error('Modulo cannot be zero'); - if (n.isOne()) return new BigInteger(0); - if (e.isNegative()) throw Error('Unsopported negative exponent'); - - let exp = e.value; - let x = this.value; - - x %= n.value; - let r = BigInt(1); - while (exp > BigInt(0)) { - const lsb = exp & BigInt(1); - exp >>= BigInt(1); // e / 2 - // Always compute multiplication step, to reduce timing leakage - const rx = (r * x) % n.value; - // Update r only if lsb is 1 (odd exponent) - r = lsb ? rx : r; - x = (x * x) % n.value; // Square - } - return new BigInteger(r); - } - - - /** - * Compute the inverse of this value modulo n - * Note: this and and n must be relatively prime - * @param {BigInteger} n - Modulo - * @returns {BigInteger} x such that this*x = 1 mod n - * @throws {Error} if the inverse does not exist - */ - modInv(n) { - const { gcd, x } = this._egcd(n); - if (!gcd.isOne()) { - throw new Error('Inverse does not exist'); - } - return x.add(n).mod(n); - } - - /** - * Extended Eucleadian algorithm (http://anh.cs.luc.edu/331/notes/xgcd.pdf) - * Given a = this and b, compute (x, y) such that ax + by = gdc(a, b) - * @param {BigInteger} b - Second operand - * @returns {{ gcd, x, y: BigInteger }} - */ - _egcd(b) { - let x = BigInt(0); - let y = BigInt(1); - let xPrev = BigInt(1); - let yPrev = BigInt(0); - - let a = this.value; - b = b.value; - - while (b !== BigInt(0)) { - const q = a / b; - let tmp = x; - x = xPrev - q * x; - xPrev = tmp; - - tmp = y; - y = yPrev - q * y; - yPrev = tmp; - - tmp = b; - b = a % b; - a = tmp; - } - - return { - x: new BigInteger(xPrev), - y: new BigInteger(yPrev), - gcd: new BigInteger(a) - }; - } - - /** - * Compute greatest common divisor between this and n - * @param {BigInteger} b - Operand - * @returns {BigInteger} gcd - */ - gcd(b) { - let a = this.value; - b = b.value; - while (b !== BigInt(0)) { - const tmp = b; - b = a % b; - a = tmp; - } - return new BigInteger(a); - } - - /** - * Shift this to the left by x, in place - * @param {BigInteger} x - Shift value - */ - ileftShift(x) { - this.value <<= x.value; - return this; - } - - /** - * Shift this to the left by x - * @param {BigInteger} x - Shift value - * @returns {BigInteger} this << x. - */ - leftShift(x) { - return this.clone().ileftShift(x); - } - - /** - * Shift this to the right by x, in place - * @param {BigInteger} x - Shift value - */ - irightShift(x) { - this.value >>= x.value; - return this; - } - - /** - * Shift this to the right by x - * @param {BigInteger} x - Shift value - * @returns {BigInteger} this >> x. - */ - rightShift(x) { - return this.clone().irightShift(x); - } - - /** - * Whether this value is equal to x - * @param {BigInteger} x - * @returns {Boolean} - */ - equal(x) { - return this.value === x.value; - } - - /** - * Whether this value is less than x - * @param {BigInteger} x - * @returns {Boolean} - */ - lt(x) { - return this.value < x.value; - } - - /** - * Whether this value is less than or equal to x - * @param {BigInteger} x - * @returns {Boolean} - */ - lte(x) { - return this.value <= x.value; - } - - /** - * Whether this value is greater than x - * @param {BigInteger} x - * @returns {Boolean} - */ - gt(x) { - return this.value > x.value; - } - - /** - * Whether this value is greater than or equal to x - * @param {BigInteger} x - * @returns {Boolean} - */ - gte(x) { - return this.value >= x.value; - } - - isZero() { - return this.value === BigInt(0); - } - - isOne() { - return this.value === BigInt(1); - } - - isNegative() { - return this.value < BigInt(0); - } - - isEven() { - return !(this.value & BigInt(1)); - } - - abs() { - const res = this.clone(); - if (this.isNegative()) { - res.value = -res.value; - } - return res; - } - - /** - * Get this value as a string - * @returns {String} this value. - */ - toString() { - return this.value.toString(); - } - - /** - * Get this value as an exact Number (max 53 bits) - * Fails if this value is too large - * @returns {Number} - */ - toNumber() { - const number = Number(this.value); - if (number > Number.MAX_SAFE_INTEGER) { - // We throw and error to conform with the bn.js implementation - throw new Error('Number can only safely store up to 53 bits'); - } - return number; - } - - /** - * Get value of i-th bit - * @param {Number} i - Bit index - * @returns {Number} Bit value. - */ - getBit(i) { - const bit = (this.value >> BigInt(i)) & BigInt(1); - return (bit === BigInt(0)) ? 0 : 1; - } - - /** - * Compute bit length - * @returns {Number} Bit length. - */ - bitLength() { - const zero = new BigInteger(0); - const one = new BigInteger(1); - const negOne = new BigInteger(-1); - - // -1n >> -1n is -1n - // 1n >> 1n is 0n - const target = this.isNegative() ? negOne : zero; - let bitlen = 1; - const tmp = this.clone(); - while (!tmp.irightShift(one).equal(target)) { - bitlen++; - } - return bitlen; - } - - /** - * Compute byte length - * @returns {Number} Byte length. - */ - byteLength() { - const zero = new BigInteger(0); - const negOne = new BigInteger(-1); - - const target = this.isNegative() ? negOne : zero; - const eight = new BigInteger(8); - let len = 1; - const tmp = this.clone(); - while (!tmp.irightShift(eight).equal(target)) { - len++; - } - return len; - } - - /** - * Get Uint8Array representation of this number - * @param {String} endian - Endianess of output array (defaults to 'be') - * @param {Number} length - Of output array - * @returns {Uint8Array} - */ - toUint8Array(endian = 'be', length) { - // we get and parse the hex string (https://coolaj86.com/articles/convert-js-bigints-to-typedarrays/) - // this is faster than shift+mod iterations - let hex = this.value.toString(16); - if (hex.length % 2 === 1) { - hex = '0' + hex; - } - - const rawLength = hex.length / 2; - const bytes = new Uint8Array(length || rawLength); - // parse hex - const offset = length ? (length - rawLength) : 0; - let i = 0; - while (i < rawLength) { - bytes[i + offset] = parseInt(hex.slice(2 * i, 2 * i + 2), 16); - i++; - } - - if (endian !== 'be') { - bytes.reverse(); - } - - return bytes; - } - } - - async function getBigInteger() { - if (util.detectBigInt()) { - return BigInteger; - } else { - const { default: BigInteger } = await Promise.resolve().then(function () { return bn_interface; }); - return BigInteger; - } - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - const debugMode = (() => { - try { - return process.env.NODE_ENV === 'development'; // eslint-disable-line no-process-env - } catch (e) {} - return false; - })(); - - const util = { - isString: function(data) { - return typeof data === 'string' || String.prototype.isPrototypeOf(data); - }, - - isArray: function(data) { - return Array.prototype.isPrototypeOf(data); - }, - - isUint8Array: isUint8Array, - - isStream: isStream, - - readNumber: function (bytes) { - let n = 0; - for (let i = 0; i < bytes.length; i++) { - n += (256 ** i) * bytes[bytes.length - 1 - i]; - } - return n; - }, - - writeNumber: function (n, bytes) { - const b = new Uint8Array(bytes); - for (let i = 0; i < bytes; i++) { - b[i] = (n >> (8 * (bytes - i - 1))) & 0xFF; - } - - return b; - }, - - readDate: function (bytes) { - const n = util.readNumber(bytes); - const d = new Date(n * 1000); - return d; - }, - - writeDate: function (time) { - const numeric = Math.floor(time.getTime() / 1000); - - return util.writeNumber(numeric, 4); - }, - - normalizeDate: function (time = Date.now()) { - return time === null || time === Infinity ? time : new Date(Math.floor(+time / 1000) * 1000); - }, - - /** - * Read one MPI from bytes in input - * @param {Uint8Array} bytes - Input data to parse - * @returns {Uint8Array} Parsed MPI. - */ - readMPI: function (bytes) { - const bits = (bytes[0] << 8) | bytes[1]; - const bytelen = (bits + 7) >>> 3; - return bytes.subarray(2, 2 + bytelen); - }, - - /** - * Left-pad Uint8Array to length by adding 0x0 bytes - * @param {Uint8Array} bytes - Data to pad - * @param {Number} length - Padded length - * @returns {Uint8Array} Padded bytes. - */ - leftPad(bytes, length) { - const padded = new Uint8Array(length); - const offset = length - bytes.length; - padded.set(bytes, offset); - return padded; - }, - - /** - * Convert a Uint8Array to an MPI-formatted Uint8Array. - * @param {Uint8Array} bin - An array of 8-bit integers to convert - * @returns {Uint8Array} MPI-formatted Uint8Array. - */ - uint8ArrayToMPI: function (bin) { - const bitSize = util.uint8ArrayBitLength(bin); - if (bitSize === 0) { - throw new Error('Zero MPI'); - } - const stripped = bin.subarray(bin.length - Math.ceil(bitSize / 8)); - const prefix = new Uint8Array([(bitSize & 0xFF00) >> 8, bitSize & 0xFF]); - return util.concatUint8Array([prefix, stripped]); - }, - - /** - * Return bit length of the input data - * @param {Uint8Array} bin input data (big endian) - * @returns bit length - */ - uint8ArrayBitLength: function (bin) { - let i; // index of leading non-zero byte - for (i = 0; i < bin.length; i++) if (bin[i] !== 0) break; - if (i === bin.length) { - return 0; - } - const stripped = bin.subarray(i); - return (stripped.length - 1) * 8 + util.nbits(stripped[0]); - }, - - /** - * Convert a hex string to an array of 8-bit integers - * @param {String} hex - A hex string to convert - * @returns {Uint8Array} An array of 8-bit integers. - */ - hexToUint8Array: function (hex) { - const result = new Uint8Array(hex.length >> 1); - for (let k = 0; k < hex.length >> 1; k++) { - result[k] = parseInt(hex.substr(k << 1, 2), 16); - } - return result; - }, - - /** - * Convert an array of 8-bit integers to a hex string - * @param {Uint8Array} bytes - Array of 8-bit integers to convert - * @returns {String} Hexadecimal representation of the array. - */ - uint8ArrayToHex: function (bytes) { - const r = []; - const e = bytes.length; - let c = 0; - let h; - while (c < e) { - h = bytes[c++].toString(16); - while (h.length < 2) { - h = '0' + h; - } - r.push('' + h); - } - return r.join(''); - }, - - /** - * Convert a string to an array of 8-bit integers - * @param {String} str - String to convert - * @returns {Uint8Array} An array of 8-bit integers. - */ - stringToUint8Array: function (str) { - return transform(str, str => { - if (!util.isString(str)) { - throw new Error('stringToUint8Array: Data must be in the form of a string'); - } - - const result = new Uint8Array(str.length); - for (let i = 0; i < str.length; i++) { - result[i] = str.charCodeAt(i); - } - return result; - }); - }, - - /** - * Convert an array of 8-bit integers to a string - * @param {Uint8Array} bytes - An array of 8-bit integers to convert - * @returns {String} String representation of the array. - */ - uint8ArrayToString: function (bytes) { - bytes = new Uint8Array(bytes); - const result = []; - const bs = 1 << 14; - const j = bytes.length; - - for (let i = 0; i < j; i += bs) { - result.push(String.fromCharCode.apply(String, bytes.subarray(i, i + bs < j ? i + bs : j))); - } - return result.join(''); - }, - - /** - * Convert a native javascript string to a Uint8Array of utf8 bytes - * @param {String|ReadableStream} str - The string to convert - * @returns {Uint8Array|ReadableStream} A valid squence of utf8 bytes. - */ - encodeUTF8: function (str) { - const encoder = new TextEncoder('utf-8'); - // eslint-disable-next-line no-inner-declarations - function process(value, lastChunk = false) { - return encoder.encode(value, { stream: !lastChunk }); - } - return transform(str, process, () => process('', true)); - }, - - /** - * Convert a Uint8Array of utf8 bytes to a native javascript string - * @param {Uint8Array|ReadableStream} utf8 - A valid squence of utf8 bytes - * @returns {String|ReadableStream} A native javascript string. - */ - decodeUTF8: function (utf8) { - const decoder = new TextDecoder('utf-8'); - // eslint-disable-next-line no-inner-declarations - function process(value, lastChunk = false) { - return decoder.decode(value, { stream: !lastChunk }); - } - return transform(utf8, process, () => process(new Uint8Array(), true)); - }, - - /** - * Concat a list of Uint8Arrays, Strings or Streams - * The caller must not mix Uint8Arrays with Strings, but may mix Streams with non-Streams. - * @param {Array} Array - Of Uint8Arrays/Strings/Streams to concatenate - * @returns {Uint8Array|String|ReadableStream} Concatenated array. - */ - concat: concat, - - /** - * Concat Uint8Arrays - * @param {Array} Array - Of Uint8Arrays to concatenate - * @returns {Uint8Array} Concatenated array. - */ - concatUint8Array: concatUint8Array, - - /** - * Check Uint8Array equality - * @param {Uint8Array} array1 - First array - * @param {Uint8Array} array2 - Second array - * @returns {Boolean} Equality. - */ - equalsUint8Array: function (array1, array2) { - if (!util.isUint8Array(array1) || !util.isUint8Array(array2)) { - throw new Error('Data must be in the form of a Uint8Array'); - } - - if (array1.length !== array2.length) { - return false; - } - - for (let i = 0; i < array1.length; i++) { - if (array1[i] !== array2[i]) { - return false; - } - } - return true; - }, - - /** - * Calculates a 16bit sum of a Uint8Array by adding each character - * codes modulus 65535 - * @param {Uint8Array} Uint8Array - To create a sum of - * @returns {Uint8Array} 2 bytes containing the sum of all charcodes % 65535. - */ - writeChecksum: function (text) { - let s = 0; - for (let i = 0; i < text.length; i++) { - s = (s + text[i]) & 0xFFFF; - } - return util.writeNumber(s, 2); - }, - - /** - * Helper function to print a debug message. Debug - * messages are only printed if - * @param {String} str - String of the debug message - */ - printDebug: function (str) { - if (debugMode) { - console.log(str); - } - }, - - /** - * Helper function to print a debug error. Debug - * messages are only printed if - * @param {String} str - String of the debug message - */ - printDebugError: function (error) { - if (debugMode) { - console.error(error); - } - }, - - // returns bit length of the integer x - nbits: function (x) { - let r = 1; - let t = x >>> 16; - if (t !== 0) { - x = t; - r += 16; - } - t = x >> 8; - if (t !== 0) { - x = t; - r += 8; - } - t = x >> 4; - if (t !== 0) { - x = t; - r += 4; - } - t = x >> 2; - if (t !== 0) { - x = t; - r += 2; - } - t = x >> 1; - if (t !== 0) { - x = t; - r += 1; - } - return r; - }, - - /** - * If S[1] == 0, then double(S) == (S[2..128] || 0); - * otherwise, double(S) == (S[2..128] || 0) xor - * (zeros(120) || 10000111). - * - * Both OCB and EAX (through CMAC) require this function to be constant-time. - * - * @param {Uint8Array} data - */ - double: function(data) { - const doubleVar = new Uint8Array(data.length); - const last = data.length - 1; - for (let i = 0; i < last; i++) { - doubleVar[i] = (data[i] << 1) ^ (data[i + 1] >> 7); - } - doubleVar[last] = (data[last] << 1) ^ ((data[0] >> 7) * 0x87); - return doubleVar; - }, - - /** - * Shift a Uint8Array to the right by n bits - * @param {Uint8Array} array - The array to shift - * @param {Integer} bits - Amount of bits to shift (MUST be smaller - * than 8) - * @returns {String} Resulting array. - */ - shiftRight: function (array, bits) { - if (bits) { - for (let i = array.length - 1; i >= 0; i--) { - array[i] >>= bits; - if (i > 0) { - array[i] |= (array[i - 1] << (8 - bits)); - } - } - } - return array; - }, - - /** - * Get native Web Cryptography api, only the current version of the spec. - * @returns {Object} The SubtleCrypto api or 'undefined'. - */ - getWebCrypto: function() { - return typeof globalThis !== 'undefined' && globalThis.crypto && globalThis.crypto.subtle; - }, - - /** - * Detect Node.js runtime. - */ - detectNode: function() { - return typeof globalThis.process === 'object' && - typeof globalThis.process.versions === 'object'; - }, - - /** - * Detect native BigInt support - */ - detectBigInt: () => typeof BigInt !== 'undefined', - - /** - * Get BigInteger class - * It wraps the native BigInt type if it's available - * Otherwise it relies on bn.js - * @returns {BigInteger} - * @async - */ - getBigInteger, - - /** - * Get native Node.js crypto api. - * @returns {Object} The crypto module or 'undefined'. - */ - getNodeCrypto: function() { - return void('crypto'); - }, - - getNodeZlib: function() { - return void('zlib'); - }, - - /** - * Get native Node.js Buffer constructor. This should be used since - * Buffer is not available under browserify. - * @returns {Function} The Buffer constructor or 'undefined'. - */ - getNodeBuffer: function() { - return ({}).Buffer; - }, - - getHardwareConcurrency: function() { - if (util.detectNode()) { - const os = void('os'); - return os.cpus().length; - } - - return navigator.hardwareConcurrency || 1; - }, - - isEmailAddress: function(data) { - if (!util.isString(data)) { - return false; - } - const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+([a-zA-Z]{2,}|xn--[a-zA-Z\-0-9]+)))$/; - return re.test(data); - }, - - /** - * Normalize line endings to - * Support any encoding where CR=0x0D, LF=0x0A - */ - canonicalizeEOL: function(data) { - const CR = 13; - const LF = 10; - let carryOverCR = false; - - return transform(data, bytes => { - if (carryOverCR) { - bytes = util.concatUint8Array([new Uint8Array([CR]), bytes]); - } - - if (bytes[bytes.length - 1] === CR) { - carryOverCR = true; - bytes = bytes.subarray(0, -1); - } else { - carryOverCR = false; - } - - let index; - const indices = []; - for (let i = 0; ; i = index) { - index = bytes.indexOf(LF, i) + 1; - if (index) { - if (bytes[index - 2] !== CR) indices.push(index); - } else { - break; - } - } - if (!indices.length) { - return bytes; - } - - const normalized = new Uint8Array(bytes.length + indices.length); - let j = 0; - for (let i = 0; i < indices.length; i++) { - const sub = bytes.subarray(indices[i - 1] || 0, indices[i]); - normalized.set(sub, j); - j += sub.length; - normalized[j - 1] = CR; - normalized[j] = LF; - j++; - } - normalized.set(bytes.subarray(indices[indices.length - 1] || 0), j); - return normalized; - }, () => (carryOverCR ? new Uint8Array([CR]) : undefined)); - }, - - /** - * Convert line endings from canonicalized to native - * Support any encoding where CR=0x0D, LF=0x0A - */ - nativeEOL: function(data) { - const CR = 13; - const LF = 10; - let carryOverCR = false; - - return transform(data, bytes => { - if (carryOverCR && bytes[0] !== LF) { - bytes = util.concatUint8Array([new Uint8Array([CR]), bytes]); - } else { - bytes = new Uint8Array(bytes); // Don't mutate passed bytes - } - - if (bytes[bytes.length - 1] === CR) { - carryOverCR = true; - bytes = bytes.subarray(0, -1); - } else { - carryOverCR = false; - } - - let index; - let j = 0; - for (let i = 0; i !== bytes.length; i = index) { - index = bytes.indexOf(CR, i) + 1; - if (!index) index = bytes.length; - const last = index - (bytes[index] === LF ? 1 : 0); - if (i) bytes.copyWithin(j, i, last); - j += last - i; - } - return bytes.subarray(0, j); - }, () => (carryOverCR ? new Uint8Array([CR]) : undefined)); - }, - - /** - * Remove trailing spaces and tabs from each line - */ - removeTrailingSpaces: function(text) { - return text.split('\n').map(line => { - let i = line.length - 1; - for (; i >= 0 && (line[i] === ' ' || line[i] === '\t'); i--); - return line.substr(0, i + 1); - }).join('\n'); - }, - - wrapError: function(message, error) { - if (!error) { - return new Error(message); - } - - // update error message - try { - error.message = message + ': ' + error.message; - } catch (e) {} - - return error; - }, - - /** - * Map allowed packet tags to corresponding classes - * Meant to be used to format `allowedPacket` for Packetlist.read - * @param {Array} allowedClasses - * @returns {Object} map from enum.packet to corresponding *Packet class - */ - constructAllowedPackets: function(allowedClasses) { - const map = {}; - allowedClasses.forEach(PacketClass => { - if (!PacketClass.tag) { - throw new Error('Invalid input: expected a packet class'); - } - map[PacketClass.tag] = PacketClass; - }); - return map; - }, - - /** - * Return a Promise that will resolve as soon as one of the promises in input resolves - * or will reject if all input promises all rejected - * (similar to Promise.any, but with slightly different error handling) - * @param {Array} promises - * @return {Promise} Promise resolving to the result of the fastest fulfilled promise - * or rejected with the Error of the last resolved Promise (if all promises are rejected) - */ - anyPromise: function(promises) { - return new Promise(async (resolve, reject) => { - let exception; - await Promise.all(promises.map(async promise => { - try { - resolve(await promise); - } catch (e) { - exception = e; - } - })); - reject(exception); - }); - }, - - /** - * Return either `a` or `b` based on `cond`, in algorithmic constant time. - * @param {Boolean} cond - * @param {Uint8Array} a - * @param {Uint8Array} b - * @returns `a` if `cond` is true, `b` otherwise - */ - selectUint8Array: function(cond, a, b) { - const length = Math.max(a.length, b.length); - const result = new Uint8Array(length); - let end = 0; - for (let i = 0; i < result.length; i++) { - result[i] = (a[i] & (256 - cond)) | (b[i] & (255 + cond)); - end += (cond & i < a.length) | ((1 - cond) & i < b.length); - } - return result.subarray(0, end); - }, - /** - * Return either `a` or `b` based on `cond`, in algorithmic constant time. - * NB: it only supports `a, b` with values between 0-255. - * @param {Boolean} cond - * @param {Uint8} a - * @param {Uint8} b - * @returns `a` if `cond` is true, `b` otherwise - */ - selectUint8: function(cond, a, b) { - return (a & (256 - cond)) | (b & (255 + cond)); - } - }; - - /* OpenPGP radix-64/base64 string encoding/decoding - * Copyright 2005 Herbert Hanewinkel, www.haneWIN.de - * version 1.0, check www.haneWIN.de for the latest version - * - * This software is provided as-is, without express or implied warranty. - * Permission to use, copy, modify, distribute or sell this software, with or - * without fee, for any purpose and by any individual or organization, is hereby - * granted, provided that the above copyright notice and this paragraph appear - * in all copies. Distribution as a part of an application or binary must - * include the above copyright notice in the documentation and/or other materials - * provided with the application or distribution. - */ - - const Buffer = util.getNodeBuffer(); - - let encodeChunk; - let decodeChunk; - if (Buffer) { - encodeChunk = buf => Buffer.from(buf).toString('base64'); - decodeChunk = str => { - const b = Buffer.from(str, 'base64'); - return new Uint8Array(b.buffer, b.byteOffset, b.byteLength); - }; - } else { - encodeChunk = buf => btoa(util.uint8ArrayToString(buf)); - decodeChunk = str => util.stringToUint8Array(atob(str)); - } - - /** - * Convert binary array to radix-64 - * @param {Uint8Array | ReadableStream} data - Uint8Array to convert - * @returns {String | ReadableStream} Radix-64 version of input string. - * @static - */ - function encode(data) { - let buf = new Uint8Array(); - return transform(data, value => { - buf = util.concatUint8Array([buf, value]); - const r = []; - const bytesPerLine = 45; // 60 chars per line * (3 bytes / 4 chars of base64). - const lines = Math.floor(buf.length / bytesPerLine); - const bytes = lines * bytesPerLine; - const encoded = encodeChunk(buf.subarray(0, bytes)); - for (let i = 0; i < lines; i++) { - r.push(encoded.substr(i * 60, 60)); - r.push('\n'); - } - buf = buf.subarray(bytes); - return r.join(''); - }, () => (buf.length ? encodeChunk(buf) + '\n' : '')); - } - - /** - * Convert radix-64 to binary array - * @param {String | ReadableStream} data - Radix-64 string to convert - * @returns {Uint8Array | ReadableStream} Binary array version of input string. - * @static - */ - function decode(data) { - let buf = ''; - return transform(data, value => { - buf += value; - - // Count how many whitespace characters there are in buf - let spaces = 0; - const spacechars = [' ', '\t', '\r', '\n']; - for (let i = 0; i < spacechars.length; i++) { - const spacechar = spacechars[i]; - for (let pos = buf.indexOf(spacechar); pos !== -1; pos = buf.indexOf(spacechar, pos + 1)) { - spaces++; - } - } - - // Backtrack until we have 4n non-whitespace characters - // that we can safely base64-decode - let length = buf.length; - for (; length > 0 && (length - spaces) % 4 !== 0; length--) { - if (spacechars.includes(buf[length])) spaces--; - } - - const decoded = decodeChunk(buf.substr(0, length)); - buf = buf.substr(length); - return decoded; - }, () => decodeChunk(buf)); - } - - /** - * Convert a Base-64 encoded string an array of 8-bit integer - * - * Note: accepts both Radix-64 and URL-safe strings - * @param {String} base64 - Base-64 encoded string to convert - * @returns {Uint8Array} An array of 8-bit integers. - */ - function b64ToUint8Array(base64) { - return decode(base64.replace(/-/g, '+').replace(/_/g, '/')); - } - - /** - * Convert an array of 8-bit integer to a Base-64 encoded string - * @param {Uint8Array} bytes - An array of 8-bit integers to convert - * @param {bool} url - If true, output is URL-safe - * @returns {String} Base-64 encoded string. - */ - function uint8ArrayToB64(bytes, url) { - let encoded = encode(bytes).replace(/[\r\n]/g, ''); - if (url) { - encoded = encoded.replace(/[+]/g, '-').replace(/[/]/g, '_').replace(/[=]/g, ''); - } - return encoded; - } - - /** - * @module enums - */ - - const byValue = Symbol('byValue'); - - var enums = { - - /** Maps curve names under various standards to one - * @see {@link https://wiki.gnupg.org/ECC|ECC - GnuPG wiki} - * @enum {String} - * @readonly - */ - curve: { - /** NIST P-256 Curve */ - 'p256': 'p256', - 'P-256': 'p256', - 'secp256r1': 'p256', - 'prime256v1': 'p256', - '1.2.840.10045.3.1.7': 'p256', - '2a8648ce3d030107': 'p256', - '2A8648CE3D030107': 'p256', - - /** NIST P-384 Curve */ - 'p384': 'p384', - 'P-384': 'p384', - 'secp384r1': 'p384', - '1.3.132.0.34': 'p384', - '2b81040022': 'p384', - '2B81040022': 'p384', - - /** NIST P-521 Curve */ - 'p521': 'p521', - 'P-521': 'p521', - 'secp521r1': 'p521', - '1.3.132.0.35': 'p521', - '2b81040023': 'p521', - '2B81040023': 'p521', - - /** SECG SECP256k1 Curve */ - 'secp256k1': 'secp256k1', - '1.3.132.0.10': 'secp256k1', - '2b8104000a': 'secp256k1', - '2B8104000A': 'secp256k1', - - /** Ed25519 */ - 'ED25519': 'ed25519', - 'ed25519': 'ed25519', - 'Ed25519': 'ed25519', - '1.3.6.1.4.1.11591.15.1': 'ed25519', - '2b06010401da470f01': 'ed25519', - '2B06010401DA470F01': 'ed25519', - - /** Curve25519 */ - 'X25519': 'curve25519', - 'cv25519': 'curve25519', - 'curve25519': 'curve25519', - 'Curve25519': 'curve25519', - '1.3.6.1.4.1.3029.1.5.1': 'curve25519', - '2b060104019755010501': 'curve25519', - '2B060104019755010501': 'curve25519', - - /** BrainpoolP256r1 Curve */ - 'brainpoolP256r1': 'brainpoolP256r1', - '1.3.36.3.3.2.8.1.1.7': 'brainpoolP256r1', - '2b2403030208010107': 'brainpoolP256r1', - '2B2403030208010107': 'brainpoolP256r1', - - /** BrainpoolP384r1 Curve */ - 'brainpoolP384r1': 'brainpoolP384r1', - '1.3.36.3.3.2.8.1.1.11': 'brainpoolP384r1', - '2b240303020801010b': 'brainpoolP384r1', - '2B240303020801010B': 'brainpoolP384r1', - - /** BrainpoolP512r1 Curve */ - 'brainpoolP512r1': 'brainpoolP512r1', - '1.3.36.3.3.2.8.1.1.13': 'brainpoolP512r1', - '2b240303020801010d': 'brainpoolP512r1', - '2B240303020801010D': 'brainpoolP512r1' - }, - - /** A string to key specifier type - * @enum {Integer} - * @readonly - */ - s2k: { - simple: 0, - salted: 1, - iterated: 3, - gnu: 101 - }, - - /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-9.1|RFC4880bis-04, section 9.1} - * @enum {Integer} - * @readonly - */ - publicKey: { - /** RSA (Encrypt or Sign) [HAC] */ - rsaEncryptSign: 1, - /** RSA (Encrypt only) [HAC] */ - rsaEncrypt: 2, - /** RSA (Sign only) [HAC] */ - rsaSign: 3, - /** Elgamal (Encrypt only) [ELGAMAL] [HAC] */ - elgamal: 16, - /** DSA (Sign only) [FIPS186] [HAC] */ - dsa: 17, - /** ECDH (Encrypt only) [RFC6637] */ - ecdh: 18, - /** ECDSA (Sign only) [RFC6637] */ - ecdsa: 19, - /** EdDSA (Sign only) - * [{@link https://tools.ietf.org/html/draft-koch-eddsa-for-openpgp-04|Draft RFC}] */ - eddsa: 22, - /** Reserved for AEDH */ - aedh: 23, - /** Reserved for AEDSA */ - aedsa: 24 - }, - - /** {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC4880, section 9.2} - * @enum {Integer} - * @readonly - */ - symmetric: { - plaintext: 0, - /** Not implemented! */ - idea: 1, - tripledes: 2, - cast5: 3, - blowfish: 4, - aes128: 7, - aes192: 8, - aes256: 9, - twofish: 10 - }, - - /** {@link https://tools.ietf.org/html/rfc4880#section-9.3|RFC4880, section 9.3} - * @enum {Integer} - * @readonly - */ - compression: { - uncompressed: 0, - /** RFC1951 */ - zip: 1, - /** RFC1950 */ - zlib: 2, - bzip2: 3 - }, - - /** {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC4880, section 9.4} - * @enum {Integer} - * @readonly - */ - hash: { - md5: 1, - sha1: 2, - ripemd: 3, - sha256: 8, - sha384: 9, - sha512: 10, - sha224: 11 - }, - - /** A list of hash names as accepted by webCrypto functions. - * {@link https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest|Parameters, algo} - * @enum {String} - */ - webHash: { - 'SHA-1': 2, - 'SHA-256': 8, - 'SHA-384': 9, - 'SHA-512': 10 - }, - - /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-9.6|RFC4880bis-04, section 9.6} - * @enum {Integer} - * @readonly - */ - aead: { - eax: 1, - ocb: 2, - experimentalGCM: 100 // Private algorithm - }, - - /** A list of packet types and numeric tags associated with them. - * @enum {Integer} - * @readonly - */ - packet: { - publicKeyEncryptedSessionKey: 1, - signature: 2, - symEncryptedSessionKey: 3, - onePassSignature: 4, - secretKey: 5, - publicKey: 6, - secretSubkey: 7, - compressedData: 8, - symmetricallyEncryptedData: 9, - marker: 10, - literalData: 11, - trust: 12, - userID: 13, - publicSubkey: 14, - userAttribute: 17, - symEncryptedIntegrityProtectedData: 18, - modificationDetectionCode: 19, - aeadEncryptedData: 20 // see IETF draft: https://tools.ietf.org/html/draft-ford-openpgp-format-00#section-2.1 - }, - - /** Data types in the literal packet - * @enum {Integer} - * @readonly - */ - literal: { - /** Binary data 'b' */ - binary: 'b'.charCodeAt(), - /** Text data 't' */ - text: 't'.charCodeAt(), - /** Utf8 data 'u' */ - utf8: 'u'.charCodeAt(), - /** MIME message body part 'm' */ - mime: 'm'.charCodeAt() - }, - - - /** One pass signature packet type - * @enum {Integer} - * @readonly - */ - signature: { - /** 0x00: Signature of a binary document. */ - binary: 0, - /** 0x01: Signature of a canonical text document. - * - * Canonicalyzing the document by converting line endings. */ - text: 1, - /** 0x02: Standalone signature. - * - * This signature is a signature of only its own subpacket contents. - * It is calculated identically to a signature over a zero-lengh - * binary document. Note that it doesn't make sense to have a V3 - * standalone signature. */ - standalone: 2, - /** 0x10: Generic certification of a User ID and Public-Key packet. - * - * The issuer of this certification does not make any particular - * assertion as to how well the certifier has checked that the owner - * of the key is in fact the person described by the User ID. */ - certGeneric: 16, - /** 0x11: Persona certification of a User ID and Public-Key packet. - * - * The issuer of this certification has not done any verification of - * the claim that the owner of this key is the User ID specified. */ - certPersona: 17, - /** 0x12: Casual certification of a User ID and Public-Key packet. - * - * The issuer of this certification has done some casual - * verification of the claim of identity. */ - certCasual: 18, - /** 0x13: Positive certification of a User ID and Public-Key packet. - * - * The issuer of this certification has done substantial - * verification of the claim of identity. - * - * Most OpenPGP implementations make their "key signatures" as 0x10 - * certifications. Some implementations can issue 0x11-0x13 - * certifications, but few differentiate between the types. */ - certPositive: 19, - /** 0x30: Certification revocation signature - * - * This signature revokes an earlier User ID certification signature - * (signature class 0x10 through 0x13) or direct-key signature - * (0x1F). It should be issued by the same key that issued the - * revoked signature or an authorized revocation key. The signature - * is computed over the same data as the certificate that it - * revokes, and should have a later creation date than that - * certificate. */ - certRevocation: 48, - /** 0x18: Subkey Binding Signature - * - * This signature is a statement by the top-level signing key that - * indicates that it owns the subkey. This signature is calculated - * directly on the primary key and subkey, and not on any User ID or - * other packets. A signature that binds a signing subkey MUST have - * an Embedded Signature subpacket in this binding signature that - * contains a 0x19 signature made by the signing subkey on the - * primary key and subkey. */ - subkeyBinding: 24, - /** 0x19: Primary Key Binding Signature - * - * This signature is a statement by a signing subkey, indicating - * that it is owned by the primary key and subkey. This signature - * is calculated the same way as a 0x18 signature: directly on the - * primary key and subkey, and not on any User ID or other packets. - * - * When a signature is made over a key, the hash data starts with the - * octet 0x99, followed by a two-octet length of the key, and then body - * of the key packet. (Note that this is an old-style packet header for - * a key packet with two-octet length.) A subkey binding signature - * (type 0x18) or primary key binding signature (type 0x19) then hashes - * the subkey using the same format as the main key (also using 0x99 as - * the first octet). */ - keyBinding: 25, - /** 0x1F: Signature directly on a key - * - * This signature is calculated directly on a key. It binds the - * information in the Signature subpackets to the key, and is - * appropriate to be used for subpackets that provide information - * about the key, such as the Revocation Key subpacket. It is also - * appropriate for statements that non-self certifiers want to make - * about the key itself, rather than the binding between a key and a - * name. */ - key: 31, - /** 0x20: Key revocation signature - * - * The signature is calculated directly on the key being revoked. A - * revoked key is not to be used. Only revocation signatures by the - * key being revoked, or by an authorized revocation key, should be - * considered valid revocation signatures.a */ - keyRevocation: 32, - /** 0x28: Subkey revocation signature - * - * The signature is calculated directly on the subkey being revoked. - * A revoked subkey is not to be used. Only revocation signatures - * by the top-level signature key that is bound to this subkey, or - * by an authorized revocation key, should be considered valid - * revocation signatures. - * - * Key revocation signatures (types 0x20 and 0x28) - * hash only the key being revoked. */ - subkeyRevocation: 40, - /** 0x40: Timestamp signature. - * This signature is only meaningful for the timestamp contained in - * it. */ - timestamp: 64, - /** 0x50: Third-Party Confirmation signature. - * - * This signature is a signature over some other OpenPGP Signature - * packet(s). It is analogous to a notary seal on the signed data. - * A third-party signature SHOULD include Signature Target - * subpacket(s) to give easy identification. Note that we really do - * mean SHOULD. There are plausible uses for this (such as a blind - * party that only sees the signature, not the key or source - * document) that cannot include a target subpacket. */ - thirdParty: 80 - }, - - /** Signature subpacket type - * @enum {Integer} - * @readonly - */ - signatureSubpacket: { - signatureCreationTime: 2, - signatureExpirationTime: 3, - exportableCertification: 4, - trustSignature: 5, - regularExpression: 6, - revocable: 7, - keyExpirationTime: 9, - placeholderBackwardsCompatibility: 10, - preferredSymmetricAlgorithms: 11, - revocationKey: 12, - issuer: 16, - notationData: 20, - preferredHashAlgorithms: 21, - preferredCompressionAlgorithms: 22, - keyServerPreferences: 23, - preferredKeyServer: 24, - primaryUserID: 25, - policyURI: 26, - keyFlags: 27, - signersUserID: 28, - reasonForRevocation: 29, - features: 30, - signatureTarget: 31, - embeddedSignature: 32, - issuerFingerprint: 33, - preferredAEADAlgorithms: 34 - }, - - /** Key flags - * @enum {Integer} - * @readonly - */ - keyFlags: { - /** 0x01 - This key may be used to certify other keys. */ - certifyKeys: 1, - /** 0x02 - This key may be used to sign data. */ - signData: 2, - /** 0x04 - This key may be used to encrypt communications. */ - encryptCommunication: 4, - /** 0x08 - This key may be used to encrypt storage. */ - encryptStorage: 8, - /** 0x10 - The private component of this key may have been split - * by a secret-sharing mechanism. */ - splitPrivateKey: 16, - /** 0x20 - This key may be used for authentication. */ - authentication: 32, - /** 0x80 - The private component of this key may be in the - * possession of more than one person. */ - sharedPrivateKey: 128 - }, - - /** Armor type - * @enum {Integer} - * @readonly - */ - armor: { - multipartSection: 0, - multipartLast: 1, - signed: 2, - message: 3, - publicKey: 4, - privateKey: 5, - signature: 6 - }, - - /** {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.23|RFC4880, section 5.2.3.23} - * @enum {Integer} - * @readonly - */ - reasonForRevocation: { - /** No reason specified (key revocations or cert revocations) */ - noReason: 0, - /** Key is superseded (key revocations) */ - keySuperseded: 1, - /** Key material has been compromised (key revocations) */ - keyCompromised: 2, - /** Key is retired and no longer used (key revocations) */ - keyRetired: 3, - /** User ID information is no longer valid (cert revocations) */ - userIDInvalid: 32 - }, - - /** {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.2.3.25|RFC4880bis-04, section 5.2.3.25} - * @enum {Integer} - * @readonly - */ - features: { - /** 0x01 - Modification Detection (packets 18 and 19) */ - modificationDetection: 1, - /** 0x02 - AEAD Encrypted Data Packet (packet 20) and version 5 - * Symmetric-Key Encrypted Session Key Packets (packet 3) */ - aead: 2, - /** 0x04 - Version 5 Public-Key Packet format and corresponding new - * fingerprint format */ - v5Keys: 4 - }, - - /** - * Asserts validity of given value and converts from string/integer to integer. - * @param {Object} type target enum type - * @param {String|Integer} e value to check and/or convert - * @returns {Integer} enum value if it exists - * @throws {Error} if the value is invalid - */ - write: function(type, e) { - if (typeof e === 'number') { - e = this.read(type, e); - } - - if (type[e] !== undefined) { - return type[e]; - } - - throw new Error('Invalid enum value.'); - }, - - /** - * Converts enum integer value to the corresponding string, if it exists. - * @param {Object} type target enum type - * @param {Integer} e value to convert - * @returns {String} name of enum value if it exists - * @throws {Error} if the value is invalid - */ - read: function(type, e) { - if (!type[byValue]) { - type[byValue] = []; - Object.entries(type).forEach(([key, value]) => { - type[byValue][value] = key; - }); - } - - if (type[byValue][e] !== undefined) { - return type[byValue][e]; - } - - throw new Error('Invalid enum value.'); - } - }; - - // GPG4Browsers - An OpenPGP implementation in javascript - - var defaultConfig = { - /** - * @memberof module:config - * @property {Integer} preferredHashAlgorithm Default hash algorithm {@link module:enums.hash} - */ - preferredHashAlgorithm: enums.hash.sha256, - /** - * @memberof module:config - * @property {Integer} preferredSymmetricAlgorithm Default encryption cipher {@link module:enums.symmetric} - */ - preferredSymmetricAlgorithm: enums.symmetric.aes256, - /** - * @memberof module:config - * @property {Integer} compression Default compression algorithm {@link module:enums.compression} - */ - preferredCompressionAlgorithm: enums.compression.uncompressed, - /** - * @memberof module:config - * @property {Integer} deflateLevel Default zip/zlib compression level, between 1 and 9 - */ - deflateLevel: 6, - - /** - * Use Authenticated Encryption with Additional Data (AEAD) protection for symmetric encryption. - * Note: not all OpenPGP implementations are compatible with this option. - * **FUTURE OPENPGP.JS VERSIONS MAY BREAK COMPATIBILITY WHEN USING THIS OPTION** - * @see {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-07|RFC4880bis-07} - * @memberof module:config - * @property {Boolean} aeadProtect - */ - aeadProtect: false, - /** - * Default Authenticated Encryption with Additional Data (AEAD) encryption mode - * Only has an effect when aeadProtect is set to true. - * @memberof module:config - * @property {Integer} preferredAEADAlgorithm Default AEAD mode {@link module:enums.aead} - */ - preferredAEADAlgorithm: enums.aead.eax, - /** - * Chunk Size Byte for Authenticated Encryption with Additional Data (AEAD) mode - * Only has an effect when aeadProtect is set to true. - * Must be an integer value from 0 to 56. - * @memberof module:config - * @property {Integer} aeadChunkSizeByte - */ - aeadChunkSizeByte: 12, - /** - * Use V5 keys. - * Note: not all OpenPGP implementations are compatible with this option. - * **FUTURE OPENPGP.JS VERSIONS MAY BREAK COMPATIBILITY WHEN USING THIS OPTION** - * @memberof module:config - * @property {Boolean} v5Keys - */ - v5Keys: false, - /** - * {@link https://tools.ietf.org/html/rfc4880#section-3.7.1.3|RFC4880 3.7.1.3}: - * Iteration Count Byte for S2K (String to Key) - * @memberof module:config - * @property {Integer} s2kIterationCountByte - */ - s2kIterationCountByte: 224, - /** - * Allow decryption of messages without integrity protection. - * This is an **insecure** setting: - * - message modifications cannot be detected, thus processing the decrypted data is potentially unsafe. - * - it enables downgrade attacks against integrity-protected messages. - * @memberof module:config - * @property {Boolean} allowUnauthenticatedMessages - */ - allowUnauthenticatedMessages: false, - /** - * Allow streaming unauthenticated data before its integrity has been checked. - * This setting is **insecure** if the partially decrypted message is processed further or displayed to the user. - * @memberof module:config - * @property {Boolean} allowUnauthenticatedStream - */ - allowUnauthenticatedStream: false, - /** - * @memberof module:config - * @property {Boolean} checksumRequired Do not throw error when armor is missing a checksum - */ - checksumRequired: false, - /** - * Minimum RSA key size allowed for key generation and message signing, verification and encryption. - * The default is 2047 since due to a bug, previous versions of OpenPGP.js could generate 2047-bit keys instead of 2048-bit ones. - * @memberof module:config - * @property {Number} minRSABits - */ - minRSABits: 2047, - /** - * Work-around for rare GPG decryption bug when encrypting with multiple passwords. - * **Slower and slightly less secure** - * @memberof module:config - * @property {Boolean} passwordCollisionCheck - */ - passwordCollisionCheck: false, - /** - * @memberof module:config - * @property {Boolean} revocationsExpire If true, expired revocation signatures are ignored - */ - revocationsExpire: false, - /** - * Allow decryption using RSA keys without `encrypt` flag. - * This setting is potentially insecure, but it is needed to get around an old openpgpjs bug - * where key flags were ignored when selecting a key for encryption. - * @memberof module:config - * @property {Boolean} allowInsecureDecryptionWithSigningKeys - */ - allowInsecureDecryptionWithSigningKeys: false, - /** - * Allow verification of message signatures with keys whose validity at the time of signing cannot be determined. - * Instead, a verification key will also be consider valid as long as it is valid at the current time. - * This setting is potentially insecure, but it is needed to verify messages signed with keys that were later reformatted, - * and have self-signature's creation date that does not match the primary key creation date. - * @memberof module:config - * @property {Boolean} allowInsecureDecryptionWithSigningKeys - */ - allowInsecureVerificationWithReformattedKeys: false, - - /** - * Enable constant-time decryption of RSA- and ElGamal-encrypted session keys, to hinder Bleichenbacher-like attacks (https://link.springer.com/chapter/10.1007/BFb0055716). - * This setting has measurable performance impact and it is only helpful in application scenarios where both of the following conditions apply: - * - new/incoming messages are automatically decrypted (without user interaction); - * - an attacker can determine how long it takes to decrypt each message (e.g. due to decryption errors being logged remotely). - * See also `constantTimePKCS1DecryptionSupportedSymmetricAlgorithms`. - * @memberof module:config - * @property {Boolean} constantTimePKCS1Decryption - */ - constantTimePKCS1Decryption: false, - /** - * This setting is only meaningful if `constantTimePKCS1Decryption` is enabled. - * Decryption of RSA- and ElGamal-encrypted session keys of symmetric algorithms different from the ones specified here will fail. - * However, the more algorithms are added, the slower the decryption procedure becomes. - * @memberof module:config - * @property {Set} constantTimePKCS1DecryptionSupportedSymmetricAlgorithms {@link module:enums.symmetric} - */ - constantTimePKCS1DecryptionSupportedSymmetricAlgorithms: new Set([enums.symmetric.aes128, enums.symmetric.aes192, enums.symmetric.aes256]), - - /** - * @memberof module:config - * @property {Integer} minBytesForWebCrypto The minimum amount of bytes for which to use native WebCrypto APIs when available - */ - minBytesForWebCrypto: 1000, - /** - * @memberof module:config - * @property {Boolean} ignoreUnsupportedPackets Ignore unsupported/unrecognizable packets on parsing instead of throwing an error - */ - ignoreUnsupportedPackets: true, - /** - * @memberof module:config - * @property {Boolean} ignoreMalformedPackets Ignore malformed packets on parsing instead of throwing an error - */ - ignoreMalformedPackets: false, - /** - * @memberof module:config - * @property {Boolean} showVersion Whether to include {@link module:config/config.versionString} in armored messages - */ - showVersion: false, - /** - * @memberof module:config - * @property {Boolean} showComment Whether to include {@link module:config/config.commentString} in armored messages - */ - showComment: false, - /** - * @memberof module:config - * @property {String} versionString A version string to be included in armored messages - */ - versionString: 'OpenPGP.js 5.1.0', - /** - * @memberof module:config - * @property {String} commentString A comment string to be included in armored messages - */ - commentString: 'https://openpgpjs.org', - - /** - * Max userID string length (used for parsing) - * @memberof module:config - * @property {Integer} maxUserIDLength - */ - maxUserIDLength: 1024 * 5, - /** - * Contains notatations that are considered "known". Known notations do not trigger - * validation error when the notation is marked as critical. - * @memberof module:config - * @property {Array} knownNotations - */ - knownNotations: ['preferred-email-encoding@pgp.com', 'pka-address@gnupg.org'], - /** - * Whether to use the indutny/elliptic library for curves (other than Curve25519) that are not supported by the available native crypto API. - * When false, certain standard curves will not be supported (depending on the platform). - * Note: the indutny/elliptic curve library is not designed to be constant time. - * @memberof module:config - * @property {Boolean} useIndutnyElliptic - */ - useIndutnyElliptic: true, - /** - * Reject insecure hash algorithms - * @memberof module:config - * @property {Set} rejectHashAlgorithms {@link module:enums.hash} - */ - rejectHashAlgorithms: new Set([enums.hash.md5, enums.hash.ripemd]), - /** - * Reject insecure message hash algorithms - * @memberof module:config - * @property {Set} rejectMessageHashAlgorithms {@link module:enums.hash} - */ - rejectMessageHashAlgorithms: new Set([enums.hash.md5, enums.hash.ripemd, enums.hash.sha1]), - /** - * Reject insecure public key algorithms for key generation and message encryption, signing or verification - * @memberof module:config - * @property {Set} rejectPublicKeyAlgorithms {@link module:enums.publicKey} - */ - rejectPublicKeyAlgorithms: new Set([enums.publicKey.elgamal, enums.publicKey.dsa]), - /** - * Reject non-standard curves for key generation, message encryption, signing or verification - * @memberof module:config - * @property {Set} rejectCurves {@link module:enums.curve} - */ - rejectCurves: new Set([enums.curve.brainpoolP256r1, enums.curve.brainpoolP384r1, enums.curve.brainpoolP512r1, enums.curve.secp256k1]) - }; - - // GPG4Browsers - An OpenPGP implementation in javascript - - /** - * Finds out which Ascii Armoring type is used. Throws error if unknown type. - * @param {String} text - ascii armored text - * @returns {Integer} 0 = MESSAGE PART n of m. - * 1 = MESSAGE PART n - * 2 = SIGNED MESSAGE - * 3 = PGP MESSAGE - * 4 = PUBLIC KEY BLOCK - * 5 = PRIVATE KEY BLOCK - * 6 = SIGNATURE - * @private - */ - function getType(text) { - const reHeader = /^-----BEGIN PGP (MESSAGE, PART \d+\/\d+|MESSAGE, PART \d+|SIGNED MESSAGE|MESSAGE|PUBLIC KEY BLOCK|PRIVATE KEY BLOCK|SIGNATURE)-----$/m; - - const header = text.match(reHeader); - - if (!header) { - throw new Error('Unknown ASCII armor type'); - } - - // BEGIN PGP MESSAGE, PART X/Y - // Used for multi-part messages, where the armor is split amongst Y - // parts, and this is the Xth part out of Y. - if (/MESSAGE, PART \d+\/\d+/.test(header[1])) { - return enums.armor.multipartSection; - } else - // BEGIN PGP MESSAGE, PART X - // Used for multi-part messages, where this is the Xth part of an - // unspecified number of parts. Requires the MESSAGE-ID Armor - // Header to be used. - if (/MESSAGE, PART \d+/.test(header[1])) { - return enums.armor.multipartLast; - } else - // BEGIN PGP SIGNED MESSAGE - if (/SIGNED MESSAGE/.test(header[1])) { - return enums.armor.signed; - } else - // BEGIN PGP MESSAGE - // Used for signed, encrypted, or compressed files. - if (/MESSAGE/.test(header[1])) { - return enums.armor.message; - } else - // BEGIN PGP PUBLIC KEY BLOCK - // Used for armoring public keys. - if (/PUBLIC KEY BLOCK/.test(header[1])) { - return enums.armor.publicKey; - } else - // BEGIN PGP PRIVATE KEY BLOCK - // Used for armoring private keys. - if (/PRIVATE KEY BLOCK/.test(header[1])) { - return enums.armor.privateKey; - } else - // BEGIN PGP SIGNATURE - // Used for detached signatures, OpenPGP/MIME signatures, and - // cleartext signatures. Note that PGP 2.x uses BEGIN PGP MESSAGE - // for detached signatures. - if (/SIGNATURE/.test(header[1])) { - return enums.armor.signature; - } - } - - /** - * Add additional information to the armor version of an OpenPGP binary - * packet block. - * @author Alex - * @version 2011-12-16 - * @param {String} [customComment] - Additional comment to add to the armored string - * @returns {String} The header information. - * @private - */ - function addheader(customComment, config) { - let result = ''; - if (config.showVersion) { - result += 'Version: ' + config.versionString + '\n'; - } - if (config.showComment) { - result += 'Comment: ' + config.commentString + '\n'; - } - if (customComment) { - result += 'Comment: ' + customComment + '\n'; - } - result += '\n'; - return result; - } - - - /** - * Calculates a checksum over the given data and returns it base64 encoded - * @param {String | ReadableStream} data - Data to create a CRC-24 checksum for - * @returns {String | ReadableStream} Base64 encoded checksum. - * @private - */ - function getCheckSum(data) { - const crc = createcrc24(data); - return encode(crc); - } - - // https://create.stephan-brumme.com/crc32/#slicing-by-8-overview - - const crc_table = [ - new Array(0xFF), - new Array(0xFF), - new Array(0xFF), - new Array(0xFF) - ]; - - for (let i = 0; i <= 0xFF; i++) { - let crc = i << 16; - for (let j = 0; j < 8; j++) { - crc = (crc << 1) ^ ((crc & 0x800000) !== 0 ? 0x864CFB : 0); - } - crc_table[0][i] = - ((crc & 0xFF0000) >> 16) | - (crc & 0x00FF00) | - ((crc & 0x0000FF) << 16); - } - for (let i = 0; i <= 0xFF; i++) { - crc_table[1][i] = (crc_table[0][i] >> 8) ^ crc_table[0][crc_table[0][i] & 0xFF]; - } - for (let i = 0; i <= 0xFF; i++) { - crc_table[2][i] = (crc_table[1][i] >> 8) ^ crc_table[0][crc_table[1][i] & 0xFF]; - } - for (let i = 0; i <= 0xFF; i++) { - crc_table[3][i] = (crc_table[2][i] >> 8) ^ crc_table[0][crc_table[2][i] & 0xFF]; - } - - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView#Endianness - const isLittleEndian = (function() { - const buffer = new ArrayBuffer(2); - new DataView(buffer).setInt16(0, 0xFF, true /* littleEndian */); - // Int16Array uses the platform's endianness. - return new Int16Array(buffer)[0] === 0xFF; - }()); - - /** - * Internal function to calculate a CRC-24 checksum over a given string (data) - * @param {String | ReadableStream} input - Data to create a CRC-24 checksum for - * @returns {Uint8Array | ReadableStream} The CRC-24 checksum. - * @private - */ - function createcrc24(input) { - let crc = 0xCE04B7; - return transform(input, value => { - const len32 = isLittleEndian ? Math.floor(value.length / 4) : 0; - const arr32 = new Uint32Array(value.buffer, value.byteOffset, len32); - for (let i = 0; i < len32; i++) { - crc ^= arr32[i]; - crc = - crc_table[0][(crc >> 24) & 0xFF] ^ - crc_table[1][(crc >> 16) & 0xFF] ^ - crc_table[2][(crc >> 8) & 0xFF] ^ - crc_table[3][(crc >> 0) & 0xFF]; - } - for (let i = len32 * 4; i < value.length; i++) { - crc = (crc >> 8) ^ crc_table[0][(crc & 0xFF) ^ value[i]]; - } - }, () => new Uint8Array([crc, crc >> 8, crc >> 16])); - } - - /** - * Verify armored headers. RFC4880, section 6.3: "OpenPGP should consider improperly formatted - * Armor Headers to be corruption of the ASCII Armor." - * @private - * @param {Array} headers - Armor headers - */ - function verifyHeaders(headers) { - for (let i = 0; i < headers.length; i++) { - if (!/^([^\s:]|[^\s:][^:]*[^\s:]): .+$/.test(headers[i])) { - throw new Error('Improperly formatted armor header: ' + headers[i]); - } - if (!/^(Version|Comment|MessageID|Hash|Charset): .+$/.test(headers[i])) { - util.printDebugError(new Error('Unknown header: ' + headers[i])); - } - } - } - - /** - * Splits a message into two parts, the body and the checksum. This is an internal function - * @param {String} text - OpenPGP armored message part - * @returns {Object} An object with attribute "body" containing the body. - * and an attribute "checksum" containing the checksum. - * @private - */ - function splitChecksum(text) { - let body = text; - let checksum = ''; - - const lastEquals = text.lastIndexOf('='); - - if (lastEquals >= 0 && lastEquals !== text.length - 1) { // '=' as the last char means no checksum - body = text.slice(0, lastEquals); - checksum = text.slice(lastEquals + 1).substr(0, 4); - } - - return { body: body, checksum: checksum }; - } - - /** - * Dearmor an OpenPGP armored message; verify the checksum and return - * the encoded bytes - * @param {String} input - OpenPGP armored message - * @returns {Promise} An object with attribute "text" containing the message text, - * an attribute "data" containing a stream of bytes and "type" for the ASCII armor type - * @async - * @static - */ - function unarmor(input, config = defaultConfig) { - return new Promise(async (resolve, reject) => { - try { - const reSplit = /^-----[^-]+-----$/m; - const reEmptyLine = /^[ \f\r\t\u00a0\u2000-\u200a\u202f\u205f\u3000]*$/; - - let type; - const headers = []; - let lastHeaders = headers; - let headersDone; - let text = []; - let textDone; - let checksum; - let data = decode(transformPair(input, async (readable, writable) => { - const reader = getReader(readable); - try { - while (true) { - let line = await reader.readLine(); - if (line === undefined) { - throw new Error('Misformed armored text'); - } - // remove trailing whitespace at end of lines - line = util.removeTrailingSpaces(line.replace(/[\r\n]/g, '')); - if (!type) { - if (reSplit.test(line)) { - type = getType(line); - } - } else if (!headersDone) { - if (reSplit.test(line)) { - reject(new Error('Mandatory blank line missing between armor headers and armor data')); - } - if (!reEmptyLine.test(line)) { - lastHeaders.push(line); - } else { - verifyHeaders(lastHeaders); - headersDone = true; - if (textDone || type !== 2) { - resolve({ text, data, headers, type }); - break; - } - } - } else if (!textDone && type === 2) { - if (!reSplit.test(line)) { - // Reverse dash-escaping for msg - text.push(line.replace(/^- /, '')); - } else { - text = text.join('\r\n'); - textDone = true; - verifyHeaders(lastHeaders); - lastHeaders = []; - headersDone = false; - } - } - } - } catch (e) { - reject(e); - return; - } - const writer = getWriter(writable); - try { - while (true) { - await writer.ready; - const { done, value } = await reader.read(); - if (done) { - throw new Error('Misformed armored text'); - } - const line = value + ''; - if (line.indexOf('=') === -1 && line.indexOf('-') === -1) { - await writer.write(line); - } else { - let remainder = await reader.readToEnd(); - if (!remainder.length) remainder = ''; - remainder = line + remainder; - remainder = util.removeTrailingSpaces(remainder.replace(/\r/g, '')); - const parts = remainder.split(reSplit); - if (parts.length === 1) { - throw new Error('Misformed armored text'); - } - const split = splitChecksum(parts[0].slice(0, -1)); - checksum = split.checksum; - await writer.write(split.body); - break; - } - } - await writer.ready; - await writer.close(); - } catch (e) { - await writer.abort(e); - } - })); - data = transformPair(data, async (readable, writable) => { - const checksumVerified = readToEnd(getCheckSum(passiveClone(readable))); - checksumVerified.catch(() => {}); - await pipe(readable, writable, { - preventClose: true - }); - const writer = getWriter(writable); - try { - const checksumVerifiedString = (await checksumVerified).replace('\n', ''); - if (checksum !== checksumVerifiedString && (checksum || config.checksumRequired)) { - throw new Error('Ascii armor integrity check failed'); - } - await writer.ready; - await writer.close(); - } catch (e) { - await writer.abort(e); - } - }); - } catch (e) { - reject(e); - } - }).then(async result => { - if (isArrayStream(result.data)) { - result.data = await readToEnd(result.data); - } - return result; - }); - } - - - /** - * Armor an OpenPGP binary packet block - * @param {module:enums.armor} messageType - Type of the message - * @param {Uint8Array | ReadableStream} body - The message body to armor - * @param {Integer} [partIndex] - * @param {Integer} [partTotal] - * @param {String} [customComment] - Additional comment to add to the armored string - * @returns {String | ReadableStream} Armored text. - * @static - */ - function armor(messageType, body, partIndex, partTotal, customComment, config = defaultConfig) { - let text; - let hash; - if (messageType === enums.armor.signed) { - text = body.text; - hash = body.hash; - body = body.data; - } - const bodyClone = passiveClone(body); - const result = []; - switch (messageType) { - case enums.armor.multipartSection: - result.push('-----BEGIN PGP MESSAGE, PART ' + partIndex + '/' + partTotal + '-----\n'); - result.push(addheader(customComment, config)); - result.push(encode(body)); - result.push('=', getCheckSum(bodyClone)); - result.push('-----END PGP MESSAGE, PART ' + partIndex + '/' + partTotal + '-----\n'); - break; - case enums.armor.multipartLast: - result.push('-----BEGIN PGP MESSAGE, PART ' + partIndex + '-----\n'); - result.push(addheader(customComment, config)); - result.push(encode(body)); - result.push('=', getCheckSum(bodyClone)); - result.push('-----END PGP MESSAGE, PART ' + partIndex + '-----\n'); - break; - case enums.armor.signed: - result.push('\n-----BEGIN PGP SIGNED MESSAGE-----\n'); - result.push('Hash: ' + hash + '\n\n'); - result.push(text.replace(/^-/mg, '- -')); - result.push('\n-----BEGIN PGP SIGNATURE-----\n'); - result.push(addheader(customComment, config)); - result.push(encode(body)); - result.push('=', getCheckSum(bodyClone)); - result.push('-----END PGP SIGNATURE-----\n'); - break; - case enums.armor.message: - result.push('-----BEGIN PGP MESSAGE-----\n'); - result.push(addheader(customComment, config)); - result.push(encode(body)); - result.push('=', getCheckSum(bodyClone)); - result.push('-----END PGP MESSAGE-----\n'); - break; - case enums.armor.publicKey: - result.push('-----BEGIN PGP PUBLIC KEY BLOCK-----\n'); - result.push(addheader(customComment, config)); - result.push(encode(body)); - result.push('=', getCheckSum(bodyClone)); - result.push('-----END PGP PUBLIC KEY BLOCK-----\n'); - break; - case enums.armor.privateKey: - result.push('-----BEGIN PGP PRIVATE KEY BLOCK-----\n'); - result.push(addheader(customComment, config)); - result.push(encode(body)); - result.push('=', getCheckSum(bodyClone)); - result.push('-----END PGP PRIVATE KEY BLOCK-----\n'); - break; - case enums.armor.signature: - result.push('-----BEGIN PGP SIGNATURE-----\n'); - result.push(addheader(customComment, config)); - result.push(encode(body)); - result.push('=', getCheckSum(bodyClone)); - result.push('-----END PGP SIGNATURE-----\n'); - break; - } - - return util.concat(result); - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - /** - * Implementation of type key id - * - * {@link https://tools.ietf.org/html/rfc4880#section-3.3|RFC4880 3.3}: - * A Key ID is an eight-octet scalar that identifies a key. - * Implementations SHOULD NOT assume that Key IDs are unique. The - * section "Enhanced Key Formats" below describes how Key IDs are - * formed. - */ - class KeyID { - constructor() { - this.bytes = ''; - } - - /** - * Parsing method for a key id - * @param {Uint8Array} bytes - Input to read the key id from - */ - read(bytes) { - this.bytes = util.uint8ArrayToString(bytes.subarray(0, 8)); - } - - /** - * Serializes the Key ID - * @returns {Uint8Array} Key ID as a Uint8Array. - */ - write() { - return util.stringToUint8Array(this.bytes); - } - - /** - * Returns the Key ID represented as a hexadecimal string - * @returns {String} Key ID as a hexadecimal string. - */ - toHex() { - return util.uint8ArrayToHex(util.stringToUint8Array(this.bytes)); - } - - /** - * Checks equality of Key ID's - * @param {KeyID} keyID - * @param {Boolean} matchWildcard - Indicates whether to check if either keyID is a wildcard - */ - equals(keyID, matchWildcard = false) { - return (matchWildcard && (keyID.isWildcard() || this.isWildcard())) || this.bytes === keyID.bytes; - } - - /** - * Checks to see if the Key ID is unset - * @returns {Boolean} True if the Key ID is null. - */ - isNull() { - return this.bytes === ''; - } - - /** - * Checks to see if the Key ID is a "wildcard" Key ID (all zeros) - * @returns {Boolean} True if this is a wildcard Key ID. - */ - isWildcard() { - return /^0+$/.test(this.toHex()); - } - - static mapToHex(keyID) { - return keyID.toHex(); - } - - static fromID(hex) { - const keyID = new KeyID(); - keyID.read(util.hexToUint8Array(hex)); - return keyID; - } - - static wildcard() { - const keyID = new KeyID(); - keyID.read(new Uint8Array(8)); - return keyID; - } - } - - /** - * @file {@link http://asmjs.org Asm.js} implementation of the {@link https://en.wikipedia.org/wiki/Advanced_Encryption_Standard Advanced Encryption Standard}. - * @author Artem S Vybornov - * @license MIT - */ - var AES_asm = function () { - - /** - * Galois Field stuff init flag - */ - var ginit_done = false; - - /** - * Galois Field exponentiation and logarithm tables for 3 (the generator) - */ - var gexp3, glog3; - - /** - * Init Galois Field tables - */ - function ginit() { - gexp3 = [], - glog3 = []; - - var a = 1, c, d; - for (c = 0; c < 255; c++) { - gexp3[c] = a; - - // Multiply by three - d = a & 0x80, a <<= 1, a &= 255; - if (d === 0x80) a ^= 0x1b; - a ^= gexp3[c]; - - // Set the log table value - glog3[gexp3[c]] = c; - } - gexp3[255] = gexp3[0]; - glog3[0] = 0; - - ginit_done = true; - } - - /** - * Galois Field multiplication - * @param {number} a - * @param {number} b - * @return {number} - */ - function gmul(a, b) { - var c = gexp3[(glog3[a] + glog3[b]) % 255]; - if (a === 0 || b === 0) c = 0; - return c; - } - - /** - * Galois Field reciprocal - * @param {number} a - * @return {number} - */ - function ginv(a) { - var i = gexp3[255 - glog3[a]]; - if (a === 0) i = 0; - return i; - } - - /** - * AES stuff init flag - */ - var aes_init_done = false; - - /** - * Encryption, Decryption, S-Box and KeyTransform tables - * - * @type {number[]} - */ - var aes_sbox; - - /** - * @type {number[]} - */ - var aes_sinv; - - /** - * @type {number[][]} - */ - var aes_enc; - - /** - * @type {number[][]} - */ - var aes_dec; - - /** - * Init AES tables - */ - function aes_init() { - if (!ginit_done) ginit(); - - // Calculates AES S-Box value - function _s(a) { - var c, s, x; - s = x = ginv(a); - for (c = 0; c < 4; c++) { - s = ((s << 1) | (s >>> 7)) & 255; - x ^= s; - } - x ^= 99; - return x; - } - - // Tables - aes_sbox = [], - aes_sinv = [], - aes_enc = [[], [], [], []], - aes_dec = [[], [], [], []]; - - for (var i = 0; i < 256; i++) { - var s = _s(i); - - // S-Box and its inverse - aes_sbox[i] = s; - aes_sinv[s] = i; - - // Ecryption and Decryption tables - aes_enc[0][i] = (gmul(2, s) << 24) | (s << 16) | (s << 8) | gmul(3, s); - aes_dec[0][s] = (gmul(14, i) << 24) | (gmul(9, i) << 16) | (gmul(13, i) << 8) | gmul(11, i); - // Rotate tables - for (var t = 1; t < 4; t++) { - aes_enc[t][i] = (aes_enc[t - 1][i] >>> 8) | (aes_enc[t - 1][i] << 24); - aes_dec[t][s] = (aes_dec[t - 1][s] >>> 8) | (aes_dec[t - 1][s] << 24); - } - } - - aes_init_done = true; - } - - /** - * Asm.js module constructor. - * - *

- * Heap buffer layout by offset: - *

-     * 0x0000   encryption key schedule
-     * 0x0400   decryption key schedule
-     * 0x0800   sbox
-     * 0x0c00   inv sbox
-     * 0x1000   encryption tables
-     * 0x2000   decryption tables
-     * 0x3000   reserved (future GCM multiplication lookup table)
-     * 0x4000   data
-     * 
- * Don't touch anything before 0x400. - *

- * - * @alias AES_asm - * @class - * @param foreign - ignored - * @param buffer - heap buffer to link with - */ - var wrapper = function (foreign, buffer) { - // Init AES stuff for the first time - if (!aes_init_done) aes_init(); - - // Fill up AES tables - var heap = new Uint32Array(buffer); - heap.set(aes_sbox, 0x0800 >> 2); - heap.set(aes_sinv, 0x0c00 >> 2); - for (var i = 0; i < 4; i++) { - heap.set(aes_enc[i], (0x1000 + 0x400 * i) >> 2); - heap.set(aes_dec[i], (0x2000 + 0x400 * i) >> 2); - } - - /** - * Calculate AES key schedules. - * @instance - * @memberof AES_asm - * @param {number} ks - key size, 4/6/8 (for 128/192/256-bit key correspondingly) - * @param {number} k0 - key vector components - * @param {number} k1 - key vector components - * @param {number} k2 - key vector components - * @param {number} k3 - key vector components - * @param {number} k4 - key vector components - * @param {number} k5 - key vector components - * @param {number} k6 - key vector components - * @param {number} k7 - key vector components - */ - function set_key(ks, k0, k1, k2, k3, k4, k5, k6, k7) { - var ekeys = heap.subarray(0x000, 60), - dkeys = heap.subarray(0x100, 0x100 + 60); - - // Encryption key schedule - ekeys.set([k0, k1, k2, k3, k4, k5, k6, k7]); - for (var i = ks, rcon = 1; i < 4 * ks + 28; i++) { - var k = ekeys[i - 1]; - if ((i % ks === 0) || (ks === 8 && i % ks === 4)) { - k = aes_sbox[k >>> 24] << 24 ^ aes_sbox[k >>> 16 & 255] << 16 ^ aes_sbox[k >>> 8 & 255] << 8 ^ aes_sbox[k & 255]; - } - if (i % ks === 0) { - k = (k << 8) ^ (k >>> 24) ^ (rcon << 24); - rcon = (rcon << 1) ^ ((rcon & 0x80) ? 0x1b : 0); - } - ekeys[i] = ekeys[i - ks] ^ k; - } - - // Decryption key schedule - for (var j = 0; j < i; j += 4) { - for (var jj = 0; jj < 4; jj++) { - var k = ekeys[i - (4 + j) + (4 - jj) % 4]; - if (j < 4 || j >= i - 4) { - dkeys[j + jj] = k; - } else { - dkeys[j + jj] = aes_dec[0][aes_sbox[k >>> 24]] - ^ aes_dec[1][aes_sbox[k >>> 16 & 255]] - ^ aes_dec[2][aes_sbox[k >>> 8 & 255]] - ^ aes_dec[3][aes_sbox[k & 255]]; - } - } - } - - // Set rounds number - asm.set_rounds(ks + 5); - } - - // create library object with necessary properties - var stdlib = {Uint8Array: Uint8Array, Uint32Array: Uint32Array}; - - var asm = function (stdlib, foreign, buffer) { - "use asm"; - - var S0 = 0, S1 = 0, S2 = 0, S3 = 0, - I0 = 0, I1 = 0, I2 = 0, I3 = 0, - N0 = 0, N1 = 0, N2 = 0, N3 = 0, - M0 = 0, M1 = 0, M2 = 0, M3 = 0, - H0 = 0, H1 = 0, H2 = 0, H3 = 0, - R = 0; - - var HEAP = new stdlib.Uint32Array(buffer), - DATA = new stdlib.Uint8Array(buffer); - - /** - * AES core - * @param {number} k - precomputed key schedule offset - * @param {number} s - precomputed sbox table offset - * @param {number} t - precomputed round table offset - * @param {number} r - number of inner rounds to perform - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _core(k, s, t, r, x0, x1, x2, x3) { - k = k | 0; - s = s | 0; - t = t | 0; - r = r | 0; - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - var t1 = 0, t2 = 0, t3 = 0, - y0 = 0, y1 = 0, y2 = 0, y3 = 0, - i = 0; - - t1 = t | 0x400, t2 = t | 0x800, t3 = t | 0xc00; - - // round 0 - x0 = x0 ^ HEAP[(k | 0) >> 2], - x1 = x1 ^ HEAP[(k | 4) >> 2], - x2 = x2 ^ HEAP[(k | 8) >> 2], - x3 = x3 ^ HEAP[(k | 12) >> 2]; - - // round 1..r - for (i = 16; (i | 0) <= (r << 4); i = (i + 16) | 0) { - y0 = HEAP[(t | x0 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x1 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x2 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x3 << 2 & 1020) >> 2] ^ HEAP[(k | i | 0) >> 2], - y1 = HEAP[(t | x1 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x2 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x3 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x0 << 2 & 1020) >> 2] ^ HEAP[(k | i | 4) >> 2], - y2 = HEAP[(t | x2 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x3 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x0 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x1 << 2 & 1020) >> 2] ^ HEAP[(k | i | 8) >> 2], - y3 = HEAP[(t | x3 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x0 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x1 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x2 << 2 & 1020) >> 2] ^ HEAP[(k | i | 12) >> 2]; - x0 = y0, x1 = y1, x2 = y2, x3 = y3; - } - - // final round - S0 = HEAP[(s | x0 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x1 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x2 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x3 << 2 & 1020) >> 2] ^ HEAP[(k | i | 0) >> 2], - S1 = HEAP[(s | x1 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x2 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x3 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x0 << 2 & 1020) >> 2] ^ HEAP[(k | i | 4) >> 2], - S2 = HEAP[(s | x2 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x3 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x0 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x1 << 2 & 1020) >> 2] ^ HEAP[(k | i | 8) >> 2], - S3 = HEAP[(s | x3 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x0 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x1 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x2 << 2 & 1020) >> 2] ^ HEAP[(k | i | 12) >> 2]; - } - - /** - * ECB mode encryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _ecb_enc(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core( - 0x0000, 0x0800, 0x1000, - R, - x0, - x1, - x2, - x3 - ); - } - - /** - * ECB mode decryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _ecb_dec(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - var t = 0; - - _core( - 0x0400, 0x0c00, 0x2000, - R, - x0, - x3, - x2, - x1 - ); - - t = S1, S1 = S3, S3 = t; - } - - - /** - * CBC mode encryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _cbc_enc(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core( - 0x0000, 0x0800, 0x1000, - R, - I0 ^ x0, - I1 ^ x1, - I2 ^ x2, - I3 ^ x3 - ); - - I0 = S0, - I1 = S1, - I2 = S2, - I3 = S3; - } - - /** - * CBC mode decryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _cbc_dec(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - var t = 0; - - _core( - 0x0400, 0x0c00, 0x2000, - R, - x0, - x3, - x2, - x1 - ); - - t = S1, S1 = S3, S3 = t; - - S0 = S0 ^ I0, - S1 = S1 ^ I1, - S2 = S2 ^ I2, - S3 = S3 ^ I3; - - I0 = x0, - I1 = x1, - I2 = x2, - I3 = x3; - } - - /** - * CFB mode encryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _cfb_enc(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core( - 0x0000, 0x0800, 0x1000, - R, - I0, - I1, - I2, - I3 - ); - - I0 = S0 = S0 ^ x0, - I1 = S1 = S1 ^ x1, - I2 = S2 = S2 ^ x2, - I3 = S3 = S3 ^ x3; - } - - - /** - * CFB mode decryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _cfb_dec(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core( - 0x0000, 0x0800, 0x1000, - R, - I0, - I1, - I2, - I3 - ); - - S0 = S0 ^ x0, - S1 = S1 ^ x1, - S2 = S2 ^ x2, - S3 = S3 ^ x3; - - I0 = x0, - I1 = x1, - I2 = x2, - I3 = x3; - } - - /** - * OFB mode encryption / decryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _ofb(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core( - 0x0000, 0x0800, 0x1000, - R, - I0, - I1, - I2, - I3 - ); - - I0 = S0, - I1 = S1, - I2 = S2, - I3 = S3; - - S0 = S0 ^ x0, - S1 = S1 ^ x1, - S2 = S2 ^ x2, - S3 = S3 ^ x3; - } - - /** - * CTR mode encryption / decryption - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _ctr(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - _core( - 0x0000, 0x0800, 0x1000, - R, - N0, - N1, - N2, - N3 - ); - - N3 = (~M3 & N3) | M3 & (N3 + 1); - N2 = (~M2 & N2) | M2 & (N2 + ((N3 | 0) == 0)); - N1 = (~M1 & N1) | M1 & (N1 + ((N2 | 0) == 0)); - N0 = (~M0 & N0) | M0 & (N0 + ((N1 | 0) == 0)); - - S0 = S0 ^ x0; - S1 = S1 ^ x1; - S2 = S2 ^ x2; - S3 = S3 ^ x3; - } - - /** - * GCM mode MAC calculation - * @param {number} x0 - 128-bit input block vector - * @param {number} x1 - 128-bit input block vector - * @param {number} x2 - 128-bit input block vector - * @param {number} x3 - 128-bit input block vector - */ - function _gcm_mac(x0, x1, x2, x3) { - x0 = x0 | 0; - x1 = x1 | 0; - x2 = x2 | 0; - x3 = x3 | 0; - - var y0 = 0, y1 = 0, y2 = 0, y3 = 0, - z0 = 0, z1 = 0, z2 = 0, z3 = 0, - i = 0, c = 0; - - x0 = x0 ^ I0, - x1 = x1 ^ I1, - x2 = x2 ^ I2, - x3 = x3 ^ I3; - - y0 = H0 | 0, - y1 = H1 | 0, - y2 = H2 | 0, - y3 = H3 | 0; - - for (; (i | 0) < 128; i = (i + 1) | 0) { - if (y0 >>> 31) { - z0 = z0 ^ x0, - z1 = z1 ^ x1, - z2 = z2 ^ x2, - z3 = z3 ^ x3; - } - - y0 = (y0 << 1) | (y1 >>> 31), - y1 = (y1 << 1) | (y2 >>> 31), - y2 = (y2 << 1) | (y3 >>> 31), - y3 = (y3 << 1); - - c = x3 & 1; - - x3 = (x3 >>> 1) | (x2 << 31), - x2 = (x2 >>> 1) | (x1 << 31), - x1 = (x1 >>> 1) | (x0 << 31), - x0 = (x0 >>> 1); - - if (c) x0 = x0 ^ 0xe1000000; - } - - I0 = z0, - I1 = z1, - I2 = z2, - I3 = z3; - } - - /** - * Set the internal rounds number. - * @instance - * @memberof AES_asm - * @param {number} r - number if inner AES rounds - */ - function set_rounds(r) { - r = r | 0; - R = r; - } - - /** - * Populate the internal state of the module. - * @instance - * @memberof AES_asm - * @param {number} s0 - state vector - * @param {number} s1 - state vector - * @param {number} s2 - state vector - * @param {number} s3 - state vector - */ - function set_state(s0, s1, s2, s3) { - s0 = s0 | 0; - s1 = s1 | 0; - s2 = s2 | 0; - s3 = s3 | 0; - - S0 = s0, - S1 = s1, - S2 = s2, - S3 = s3; - } - - /** - * Populate the internal iv of the module. - * @instance - * @memberof AES_asm - * @param {number} i0 - iv vector - * @param {number} i1 - iv vector - * @param {number} i2 - iv vector - * @param {number} i3 - iv vector - */ - function set_iv(i0, i1, i2, i3) { - i0 = i0 | 0; - i1 = i1 | 0; - i2 = i2 | 0; - i3 = i3 | 0; - - I0 = i0, - I1 = i1, - I2 = i2, - I3 = i3; - } - - /** - * Set nonce for CTR-family modes. - * @instance - * @memberof AES_asm - * @param {number} n0 - nonce vector - * @param {number} n1 - nonce vector - * @param {number} n2 - nonce vector - * @param {number} n3 - nonce vector - */ - function set_nonce(n0, n1, n2, n3) { - n0 = n0 | 0; - n1 = n1 | 0; - n2 = n2 | 0; - n3 = n3 | 0; - - N0 = n0, - N1 = n1, - N2 = n2, - N3 = n3; - } - - /** - * Set counter mask for CTR-family modes. - * @instance - * @memberof AES_asm - * @param {number} m0 - counter mask vector - * @param {number} m1 - counter mask vector - * @param {number} m2 - counter mask vector - * @param {number} m3 - counter mask vector - */ - function set_mask(m0, m1, m2, m3) { - m0 = m0 | 0; - m1 = m1 | 0; - m2 = m2 | 0; - m3 = m3 | 0; - - M0 = m0, - M1 = m1, - M2 = m2, - M3 = m3; - } - - /** - * Set counter for CTR-family modes. - * @instance - * @memberof AES_asm - * @param {number} c0 - counter vector - * @param {number} c1 - counter vector - * @param {number} c2 - counter vector - * @param {number} c3 - counter vector - */ - function set_counter(c0, c1, c2, c3) { - c0 = c0 | 0; - c1 = c1 | 0; - c2 = c2 | 0; - c3 = c3 | 0; - - N3 = (~M3 & N3) | M3 & c3, - N2 = (~M2 & N2) | M2 & c2, - N1 = (~M1 & N1) | M1 & c1, - N0 = (~M0 & N0) | M0 & c0; - } - - /** - * Store the internal state vector into the heap. - * @instance - * @memberof AES_asm - * @param {number} pos - offset where to put the data - * @return {number} The number of bytes have been written into the heap, always 16. - */ - function get_state(pos) { - pos = pos | 0; - - if (pos & 15) return -1; - - DATA[pos | 0] = S0 >>> 24, - DATA[pos | 1] = S0 >>> 16 & 255, - DATA[pos | 2] = S0 >>> 8 & 255, - DATA[pos | 3] = S0 & 255, - DATA[pos | 4] = S1 >>> 24, - DATA[pos | 5] = S1 >>> 16 & 255, - DATA[pos | 6] = S1 >>> 8 & 255, - DATA[pos | 7] = S1 & 255, - DATA[pos | 8] = S2 >>> 24, - DATA[pos | 9] = S2 >>> 16 & 255, - DATA[pos | 10] = S2 >>> 8 & 255, - DATA[pos | 11] = S2 & 255, - DATA[pos | 12] = S3 >>> 24, - DATA[pos | 13] = S3 >>> 16 & 255, - DATA[pos | 14] = S3 >>> 8 & 255, - DATA[pos | 15] = S3 & 255; - - return 16; - } - - /** - * Store the internal iv vector into the heap. - * @instance - * @memberof AES_asm - * @param {number} pos - offset where to put the data - * @return {number} The number of bytes have been written into the heap, always 16. - */ - function get_iv(pos) { - pos = pos | 0; - - if (pos & 15) return -1; - - DATA[pos | 0] = I0 >>> 24, - DATA[pos | 1] = I0 >>> 16 & 255, - DATA[pos | 2] = I0 >>> 8 & 255, - DATA[pos | 3] = I0 & 255, - DATA[pos | 4] = I1 >>> 24, - DATA[pos | 5] = I1 >>> 16 & 255, - DATA[pos | 6] = I1 >>> 8 & 255, - DATA[pos | 7] = I1 & 255, - DATA[pos | 8] = I2 >>> 24, - DATA[pos | 9] = I2 >>> 16 & 255, - DATA[pos | 10] = I2 >>> 8 & 255, - DATA[pos | 11] = I2 & 255, - DATA[pos | 12] = I3 >>> 24, - DATA[pos | 13] = I3 >>> 16 & 255, - DATA[pos | 14] = I3 >>> 8 & 255, - DATA[pos | 15] = I3 & 255; - - return 16; - } - - /** - * GCM initialization. - * @instance - * @memberof AES_asm - */ - function gcm_init() { - _ecb_enc(0, 0, 0, 0); - H0 = S0, - H1 = S1, - H2 = S2, - H3 = S3; - } - - /** - * Perform ciphering operation on the supplied data. - * @instance - * @memberof AES_asm - * @param {number} mode - block cipher mode (see {@link AES_asm} mode constants) - * @param {number} pos - offset of the data being processed - * @param {number} len - length of the data being processed - * @return {number} Actual amount of data have been processed. - */ - function cipher(mode, pos, len) { - mode = mode | 0; - pos = pos | 0; - len = len | 0; - - var ret = 0; - - if (pos & 15) return -1; - - while ((len | 0) >= 16) { - _cipher_modes[mode & 7]( - DATA[pos | 0] << 24 | DATA[pos | 1] << 16 | DATA[pos | 2] << 8 | DATA[pos | 3], - DATA[pos | 4] << 24 | DATA[pos | 5] << 16 | DATA[pos | 6] << 8 | DATA[pos | 7], - DATA[pos | 8] << 24 | DATA[pos | 9] << 16 | DATA[pos | 10] << 8 | DATA[pos | 11], - DATA[pos | 12] << 24 | DATA[pos | 13] << 16 | DATA[pos | 14] << 8 | DATA[pos | 15] - ); - - DATA[pos | 0] = S0 >>> 24, - DATA[pos | 1] = S0 >>> 16 & 255, - DATA[pos | 2] = S0 >>> 8 & 255, - DATA[pos | 3] = S0 & 255, - DATA[pos | 4] = S1 >>> 24, - DATA[pos | 5] = S1 >>> 16 & 255, - DATA[pos | 6] = S1 >>> 8 & 255, - DATA[pos | 7] = S1 & 255, - DATA[pos | 8] = S2 >>> 24, - DATA[pos | 9] = S2 >>> 16 & 255, - DATA[pos | 10] = S2 >>> 8 & 255, - DATA[pos | 11] = S2 & 255, - DATA[pos | 12] = S3 >>> 24, - DATA[pos | 13] = S3 >>> 16 & 255, - DATA[pos | 14] = S3 >>> 8 & 255, - DATA[pos | 15] = S3 & 255; - - ret = (ret + 16) | 0, - pos = (pos + 16) | 0, - len = (len - 16) | 0; - } - - return ret | 0; - } - - /** - * Calculates MAC of the supplied data. - * @instance - * @memberof AES_asm - * @param {number} mode - block cipher mode (see {@link AES_asm} mode constants) - * @param {number} pos - offset of the data being processed - * @param {number} len - length of the data being processed - * @return {number} Actual amount of data have been processed. - */ - function mac(mode, pos, len) { - mode = mode | 0; - pos = pos | 0; - len = len | 0; - - var ret = 0; - - if (pos & 15) return -1; - - while ((len | 0) >= 16) { - _mac_modes[mode & 1]( - DATA[pos | 0] << 24 | DATA[pos | 1] << 16 | DATA[pos | 2] << 8 | DATA[pos | 3], - DATA[pos | 4] << 24 | DATA[pos | 5] << 16 | DATA[pos | 6] << 8 | DATA[pos | 7], - DATA[pos | 8] << 24 | DATA[pos | 9] << 16 | DATA[pos | 10] << 8 | DATA[pos | 11], - DATA[pos | 12] << 24 | DATA[pos | 13] << 16 | DATA[pos | 14] << 8 | DATA[pos | 15] - ); - - ret = (ret + 16) | 0, - pos = (pos + 16) | 0, - len = (len - 16) | 0; - } - - return ret | 0; - } - - /** - * AES cipher modes table (virual methods) - */ - var _cipher_modes = [_ecb_enc, _ecb_dec, _cbc_enc, _cbc_dec, _cfb_enc, _cfb_dec, _ofb, _ctr]; - - /** - * AES MAC modes table (virual methods) - */ - var _mac_modes = [_cbc_enc, _gcm_mac]; - - /** - * Asm.js module exports - */ - return { - set_rounds: set_rounds, - set_state: set_state, - set_iv: set_iv, - set_nonce: set_nonce, - set_mask: set_mask, - set_counter: set_counter, - get_state: get_state, - get_iv: get_iv, - gcm_init: gcm_init, - cipher: cipher, - mac: mac, - }; - }(stdlib, foreign, buffer); - - asm.set_key = set_key; - - return asm; - }; - - /** - * AES enciphering mode constants - * @enum {number} - * @const - */ - wrapper.ENC = { - ECB: 0, - CBC: 2, - CFB: 4, - OFB: 6, - CTR: 7, - }, - - /** - * AES deciphering mode constants - * @enum {number} - * @const - */ - wrapper.DEC = { - ECB: 1, - CBC: 3, - CFB: 5, - OFB: 6, - CTR: 7, - }, - - /** - * AES MAC mode constants - * @enum {number} - * @const - */ - wrapper.MAC = { - CBC: 0, - GCM: 1, - }; - - /** - * Heap data offset - * @type {number} - * @const - */ - wrapper.HEAP_DATA = 0x4000; - - return wrapper; - }(); - - function is_bytes(a) { - return a instanceof Uint8Array; - } - function _heap_init(heap, heapSize) { - const size = heap ? heap.byteLength : heapSize || 65536; - if (size & 0xfff || size <= 0) - throw new Error('heap size must be a positive integer and a multiple of 4096'); - heap = heap || new Uint8Array(new ArrayBuffer(size)); - return heap; - } - function _heap_write(heap, hpos, data, dpos, dlen) { - const hlen = heap.length - hpos; - const wlen = hlen < dlen ? hlen : dlen; - heap.set(data.subarray(dpos, dpos + wlen), hpos); - return wlen; - } - function joinBytes(...arg) { - const totalLenght = arg.reduce((sum, curr) => sum + curr.length, 0); - const ret = new Uint8Array(totalLenght); - let cursor = 0; - for (let i = 0; i < arg.length; i++) { - ret.set(arg[i], cursor); - cursor += arg[i].length; - } - return ret; - } - - class IllegalStateError extends Error { - constructor(...args) { - super(...args); - } - } - class IllegalArgumentError extends Error { - constructor(...args) { - super(...args); - } - } - class SecurityError extends Error { - constructor(...args) { - super(...args); - } - } - - const heap_pool = []; - const asm_pool = []; - class AES { - constructor(key, iv, padding = true, mode, heap, asm) { - this.pos = 0; - this.len = 0; - this.mode = mode; - // The AES object state - this.pos = 0; - this.len = 0; - this.key = key; - this.iv = iv; - this.padding = padding; - // The AES "worker" - this.acquire_asm(heap, asm); - } - acquire_asm(heap, asm) { - if (this.heap === undefined || this.asm === undefined) { - this.heap = heap || heap_pool.pop() || _heap_init().subarray(AES_asm.HEAP_DATA); - this.asm = asm || asm_pool.pop() || new AES_asm(null, this.heap.buffer); - this.reset(this.key, this.iv); - } - return { heap: this.heap, asm: this.asm }; - } - release_asm() { - if (this.heap !== undefined && this.asm !== undefined) { - heap_pool.push(this.heap); - asm_pool.push(this.asm); - } - this.heap = undefined; - this.asm = undefined; - } - reset(key, iv) { - const { asm } = this.acquire_asm(); - // Key - const keylen = key.length; - if (keylen !== 16 && keylen !== 24 && keylen !== 32) - throw new IllegalArgumentError('illegal key size'); - const keyview = new DataView(key.buffer, key.byteOffset, key.byteLength); - asm.set_key(keylen >> 2, keyview.getUint32(0), keyview.getUint32(4), keyview.getUint32(8), keyview.getUint32(12), keylen > 16 ? keyview.getUint32(16) : 0, keylen > 16 ? keyview.getUint32(20) : 0, keylen > 24 ? keyview.getUint32(24) : 0, keylen > 24 ? keyview.getUint32(28) : 0); - // IV - if (iv !== undefined) { - if (iv.length !== 16) - throw new IllegalArgumentError('illegal iv size'); - let ivview = new DataView(iv.buffer, iv.byteOffset, iv.byteLength); - asm.set_iv(ivview.getUint32(0), ivview.getUint32(4), ivview.getUint32(8), ivview.getUint32(12)); - } - else { - asm.set_iv(0, 0, 0, 0); - } - } - AES_Encrypt_process(data) { - if (!is_bytes(data)) - throw new TypeError("data isn't of expected type"); - let { heap, asm } = this.acquire_asm(); - let amode = AES_asm.ENC[this.mode]; - let hpos = AES_asm.HEAP_DATA; - let pos = this.pos; - let len = this.len; - let dpos = 0; - let dlen = data.length || 0; - let rpos = 0; - let rlen = (len + dlen) & -16; - let wlen = 0; - let result = new Uint8Array(rlen); - while (dlen > 0) { - wlen = _heap_write(heap, pos + len, data, dpos, dlen); - len += wlen; - dpos += wlen; - dlen -= wlen; - wlen = asm.cipher(amode, hpos + pos, len); - if (wlen) - result.set(heap.subarray(pos, pos + wlen), rpos); - rpos += wlen; - if (wlen < len) { - pos += wlen; - len -= wlen; - } - else { - pos = 0; - len = 0; - } - } - this.pos = pos; - this.len = len; - return result; - } - AES_Encrypt_finish() { - let { heap, asm } = this.acquire_asm(); - let amode = AES_asm.ENC[this.mode]; - let hpos = AES_asm.HEAP_DATA; - let pos = this.pos; - let len = this.len; - let plen = 16 - (len % 16); - let rlen = len; - if (this.hasOwnProperty('padding')) { - if (this.padding) { - for (let p = 0; p < plen; ++p) { - heap[pos + len + p] = plen; - } - len += plen; - rlen = len; - } - else if (len % 16) { - throw new IllegalArgumentError('data length must be a multiple of the block size'); - } - } - else { - len += plen; - } - const result = new Uint8Array(rlen); - if (len) - asm.cipher(amode, hpos + pos, len); - if (rlen) - result.set(heap.subarray(pos, pos + rlen)); - this.pos = 0; - this.len = 0; - this.release_asm(); - return result; - } - AES_Decrypt_process(data) { - if (!is_bytes(data)) - throw new TypeError("data isn't of expected type"); - let { heap, asm } = this.acquire_asm(); - let amode = AES_asm.DEC[this.mode]; - let hpos = AES_asm.HEAP_DATA; - let pos = this.pos; - let len = this.len; - let dpos = 0; - let dlen = data.length || 0; - let rpos = 0; - let rlen = (len + dlen) & -16; - let plen = 0; - let wlen = 0; - if (this.padding) { - plen = len + dlen - rlen || 16; - rlen -= plen; - } - const result = new Uint8Array(rlen); - while (dlen > 0) { - wlen = _heap_write(heap, pos + len, data, dpos, dlen); - len += wlen; - dpos += wlen; - dlen -= wlen; - wlen = asm.cipher(amode, hpos + pos, len - (!dlen ? plen : 0)); - if (wlen) - result.set(heap.subarray(pos, pos + wlen), rpos); - rpos += wlen; - if (wlen < len) { - pos += wlen; - len -= wlen; - } - else { - pos = 0; - len = 0; - } - } - this.pos = pos; - this.len = len; - return result; - } - AES_Decrypt_finish() { - let { heap, asm } = this.acquire_asm(); - let amode = AES_asm.DEC[this.mode]; - let hpos = AES_asm.HEAP_DATA; - let pos = this.pos; - let len = this.len; - let rlen = len; - if (len > 0) { - if (len % 16) { - if (this.hasOwnProperty('padding')) { - throw new IllegalArgumentError('data length must be a multiple of the block size'); - } - else { - len += 16 - (len % 16); - } - } - asm.cipher(amode, hpos + pos, len); - if (this.hasOwnProperty('padding') && this.padding) { - let pad = heap[pos + rlen - 1]; - if (pad < 1 || pad > 16 || pad > rlen) - throw new SecurityError('bad padding'); - let pcheck = 0; - for (let i = pad; i > 1; i--) - pcheck |= pad ^ heap[pos + rlen - i]; - if (pcheck) - throw new SecurityError('bad padding'); - rlen -= pad; - } - } - const result = new Uint8Array(rlen); - if (rlen > 0) { - result.set(heap.subarray(pos, pos + rlen)); - } - this.pos = 0; - this.len = 0; - this.release_asm(); - return result; - } - } - - class AES_ECB { - static encrypt(data, key, padding = false) { - return new AES_ECB(key, padding).encrypt(data); - } - static decrypt(data, key, padding = false) { - return new AES_ECB(key, padding).decrypt(data); - } - constructor(key, padding = false, aes) { - this.aes = aes ? aes : new AES(key, undefined, padding, 'ECB'); - } - encrypt(data) { - const r1 = this.aes.AES_Encrypt_process(data); - const r2 = this.aes.AES_Encrypt_finish(); - return joinBytes(r1, r2); - } - decrypt(data) { - const r1 = this.aes.AES_Decrypt_process(data); - const r2 = this.aes.AES_Decrypt_finish(); - return joinBytes(r1, r2); - } - } - - /** - * Javascript AES implementation. - * This is used as fallback if the native Crypto APIs are not available. - */ - function aes(length) { - const C = function(key) { - const aesECB = new AES_ECB(key); - - this.encrypt = function(block) { - return aesECB.encrypt(block); - }; - - this.decrypt = function(block) { - return aesECB.decrypt(block); - }; - }; - - C.blockSize = C.prototype.blockSize = 16; - C.keySize = C.prototype.keySize = length / 8; - - return C; - } - - //Paul Tero, July 2001 - //http://www.tero.co.uk/des/ - // - //Optimised for performance with large blocks by Michael Hayworth, November 2001 - //http://www.netdealing.com - // - // Modified by Recurity Labs GmbH - - //THIS SOFTWARE IS PROVIDED "AS IS" AND - //ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - //IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - //ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - //FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - //DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - //OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - //HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - //LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - //OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - //SUCH DAMAGE. - - //des - //this takes the key, the message, and whether to encrypt or decrypt - - function des(keys, message, encrypt, mode, iv, padding) { - //declaring this locally speeds things up a bit - const spfunction1 = [ - 0x1010400, 0, 0x10000, 0x1010404, 0x1010004, 0x10404, 0x4, 0x10000, 0x400, 0x1010400, - 0x1010404, 0x400, 0x1000404, 0x1010004, 0x1000000, 0x4, 0x404, 0x1000400, 0x1000400, 0x10400, 0x10400, 0x1010000, - 0x1010000, 0x1000404, 0x10004, 0x1000004, 0x1000004, 0x10004, 0, 0x404, 0x10404, 0x1000000, 0x10000, 0x1010404, 0x4, - 0x1010000, 0x1010400, 0x1000000, 0x1000000, 0x400, 0x1010004, 0x10000, 0x10400, 0x1000004, 0x400, 0x4, 0x1000404, - 0x10404, 0x1010404, 0x10004, 0x1010000, 0x1000404, 0x1000004, 0x404, 0x10404, 0x1010400, 0x404, 0x1000400, - 0x1000400, 0, 0x10004, 0x10400, 0, 0x1010004 - ]; - const spfunction2 = [ - -0x7fef7fe0, -0x7fff8000, 0x8000, 0x108020, 0x100000, 0x20, -0x7fefffe0, -0x7fff7fe0, - -0x7fffffe0, -0x7fef7fe0, -0x7fef8000, -0x80000000, -0x7fff8000, 0x100000, 0x20, -0x7fefffe0, 0x108000, 0x100020, - -0x7fff7fe0, 0, -0x80000000, 0x8000, 0x108020, -0x7ff00000, 0x100020, -0x7fffffe0, 0, 0x108000, 0x8020, -0x7fef8000, - -0x7ff00000, 0x8020, 0, 0x108020, -0x7fefffe0, 0x100000, -0x7fff7fe0, -0x7ff00000, -0x7fef8000, 0x8000, -0x7ff00000, - -0x7fff8000, 0x20, -0x7fef7fe0, 0x108020, 0x20, 0x8000, -0x80000000, 0x8020, -0x7fef8000, 0x100000, -0x7fffffe0, - 0x100020, -0x7fff7fe0, -0x7fffffe0, 0x100020, 0x108000, 0, -0x7fff8000, 0x8020, -0x80000000, -0x7fefffe0, - -0x7fef7fe0, 0x108000 - ]; - const spfunction3 = [ - 0x208, 0x8020200, 0, 0x8020008, 0x8000200, 0, 0x20208, 0x8000200, 0x20008, 0x8000008, - 0x8000008, 0x20000, 0x8020208, 0x20008, 0x8020000, 0x208, 0x8000000, 0x8, 0x8020200, 0x200, 0x20200, 0x8020000, - 0x8020008, 0x20208, 0x8000208, 0x20200, 0x20000, 0x8000208, 0x8, 0x8020208, 0x200, 0x8000000, 0x8020200, 0x8000000, - 0x20008, 0x208, 0x20000, 0x8020200, 0x8000200, 0, 0x200, 0x20008, 0x8020208, 0x8000200, 0x8000008, 0x200, 0, - 0x8020008, 0x8000208, 0x20000, 0x8000000, 0x8020208, 0x8, 0x20208, 0x20200, 0x8000008, 0x8020000, 0x8000208, 0x208, - 0x8020000, 0x20208, 0x8, 0x8020008, 0x20200 - ]; - const spfunction4 = [ - 0x802001, 0x2081, 0x2081, 0x80, 0x802080, 0x800081, 0x800001, 0x2001, 0, 0x802000, - 0x802000, 0x802081, 0x81, 0, 0x800080, 0x800001, 0x1, 0x2000, 0x800000, 0x802001, 0x80, 0x800000, 0x2001, 0x2080, - 0x800081, 0x1, 0x2080, 0x800080, 0x2000, 0x802080, 0x802081, 0x81, 0x800080, 0x800001, 0x802000, 0x802081, 0x81, 0, - 0, 0x802000, 0x2080, 0x800080, 0x800081, 0x1, 0x802001, 0x2081, 0x2081, 0x80, 0x802081, 0x81, 0x1, 0x2000, 0x800001, - 0x2001, 0x802080, 0x800081, 0x2001, 0x2080, 0x800000, 0x802001, 0x80, 0x800000, 0x2000, 0x802080 - ]; - const spfunction5 = [ - 0x100, 0x2080100, 0x2080000, 0x42000100, 0x80000, 0x100, 0x40000000, 0x2080000, - 0x40080100, 0x80000, 0x2000100, 0x40080100, 0x42000100, 0x42080000, 0x80100, 0x40000000, 0x2000000, 0x40080000, - 0x40080000, 0, 0x40000100, 0x42080100, 0x42080100, 0x2000100, 0x42080000, 0x40000100, 0, 0x42000000, 0x2080100, - 0x2000000, 0x42000000, 0x80100, 0x80000, 0x42000100, 0x100, 0x2000000, 0x40000000, 0x2080000, 0x42000100, - 0x40080100, 0x2000100, 0x40000000, 0x42080000, 0x2080100, 0x40080100, 0x100, 0x2000000, 0x42080000, 0x42080100, - 0x80100, 0x42000000, 0x42080100, 0x2080000, 0, 0x40080000, 0x42000000, 0x80100, 0x2000100, 0x40000100, 0x80000, 0, - 0x40080000, 0x2080100, 0x40000100 - ]; - const spfunction6 = [ - 0x20000010, 0x20400000, 0x4000, 0x20404010, 0x20400000, 0x10, 0x20404010, 0x400000, - 0x20004000, 0x404010, 0x400000, 0x20000010, 0x400010, 0x20004000, 0x20000000, 0x4010, 0, 0x400010, 0x20004010, - 0x4000, 0x404000, 0x20004010, 0x10, 0x20400010, 0x20400010, 0, 0x404010, 0x20404000, 0x4010, 0x404000, 0x20404000, - 0x20000000, 0x20004000, 0x10, 0x20400010, 0x404000, 0x20404010, 0x400000, 0x4010, 0x20000010, 0x400000, 0x20004000, - 0x20000000, 0x4010, 0x20000010, 0x20404010, 0x404000, 0x20400000, 0x404010, 0x20404000, 0, 0x20400010, 0x10, 0x4000, - 0x20400000, 0x404010, 0x4000, 0x400010, 0x20004010, 0, 0x20404000, 0x20000000, 0x400010, 0x20004010 - ]; - const spfunction7 = [ - 0x200000, 0x4200002, 0x4000802, 0, 0x800, 0x4000802, 0x200802, 0x4200800, 0x4200802, - 0x200000, 0, 0x4000002, 0x2, 0x4000000, 0x4200002, 0x802, 0x4000800, 0x200802, 0x200002, 0x4000800, 0x4000002, - 0x4200000, 0x4200800, 0x200002, 0x4200000, 0x800, 0x802, 0x4200802, 0x200800, 0x2, 0x4000000, 0x200800, 0x4000000, - 0x200800, 0x200000, 0x4000802, 0x4000802, 0x4200002, 0x4200002, 0x2, 0x200002, 0x4000000, 0x4000800, 0x200000, - 0x4200800, 0x802, 0x200802, 0x4200800, 0x802, 0x4000002, 0x4200802, 0x4200000, 0x200800, 0, 0x2, 0x4200802, 0, - 0x200802, 0x4200000, 0x800, 0x4000002, 0x4000800, 0x800, 0x200002 - ]; - const spfunction8 = [ - 0x10001040, 0x1000, 0x40000, 0x10041040, 0x10000000, 0x10001040, 0x40, 0x10000000, - 0x40040, 0x10040000, 0x10041040, 0x41000, 0x10041000, 0x41040, 0x1000, 0x40, 0x10040000, 0x10000040, 0x10001000, - 0x1040, 0x41000, 0x40040, 0x10040040, 0x10041000, 0x1040, 0, 0, 0x10040040, 0x10000040, 0x10001000, 0x41040, - 0x40000, 0x41040, 0x40000, 0x10041000, 0x1000, 0x40, 0x10040040, 0x1000, 0x41040, 0x10001000, 0x40, 0x10000040, - 0x10040000, 0x10040040, 0x10000000, 0x40000, 0x10001040, 0, 0x10041040, 0x40040, 0x10000040, 0x10040000, 0x10001000, - 0x10001040, 0, 0x10041040, 0x41000, 0x41000, 0x1040, 0x1040, 0x40040, 0x10000000, 0x10041000 - ]; - - //create the 16 or 48 subkeys we will need - let m = 0; - let i; - let j; - let temp; - let right1; - let right2; - let left; - let right; - let looping; - let cbcleft; - let cbcleft2; - let cbcright; - let cbcright2; - let endloop; - let loopinc; - let len = message.length; - - //set up the loops for single and triple des - const iterations = keys.length === 32 ? 3 : 9; //single or triple des - if (iterations === 3) { - looping = encrypt ? [0, 32, 2] : [30, -2, -2]; - } else { - looping = encrypt ? [0, 32, 2, 62, 30, -2, 64, 96, 2] : [94, 62, -2, 32, 64, 2, 30, -2, -2]; - } - - //pad the message depending on the padding parameter - //only add padding if encrypting - note that you need to use the same padding option for both encrypt and decrypt - if (encrypt) { - message = desAddPadding(message, padding); - len = message.length; - } - - //store the result here - let result = new Uint8Array(len); - let k = 0; - - if (mode === 1) { //CBC mode - cbcleft = (iv[m++] << 24) | (iv[m++] << 16) | (iv[m++] << 8) | iv[m++]; - cbcright = (iv[m++] << 24) | (iv[m++] << 16) | (iv[m++] << 8) | iv[m++]; - m = 0; - } - - //loop through each 64 bit chunk of the message - while (m < len) { - left = (message[m++] << 24) | (message[m++] << 16) | (message[m++] << 8) | message[m++]; - right = (message[m++] << 24) | (message[m++] << 16) | (message[m++] << 8) | message[m++]; - - //for Cipher Block Chaining mode, xor the message with the previous result - if (mode === 1) { - if (encrypt) { - left ^= cbcleft; - right ^= cbcright; - } else { - cbcleft2 = cbcleft; - cbcright2 = cbcright; - cbcleft = left; - cbcright = right; - } - } - - //first each 64 but chunk of the message must be permuted according to IP - temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; - right ^= temp; - left ^= (temp << 4); - temp = ((left >>> 16) ^ right) & 0x0000ffff; - right ^= temp; - left ^= (temp << 16); - temp = ((right >>> 2) ^ left) & 0x33333333; - left ^= temp; - right ^= (temp << 2); - temp = ((right >>> 8) ^ left) & 0x00ff00ff; - left ^= temp; - right ^= (temp << 8); - temp = ((left >>> 1) ^ right) & 0x55555555; - right ^= temp; - left ^= (temp << 1); - - left = ((left << 1) | (left >>> 31)); - right = ((right << 1) | (right >>> 31)); - - //do this either 1 or 3 times for each chunk of the message - for (j = 0; j < iterations; j += 3) { - endloop = looping[j + 1]; - loopinc = looping[j + 2]; - //now go through and perform the encryption or decryption - for (i = looping[j]; i !== endloop; i += loopinc) { //for efficiency - right1 = right ^ keys[i]; - right2 = ((right >>> 4) | (right << 28)) ^ keys[i + 1]; - //the result is attained by passing these bytes through the S selection functions - temp = left; - left = right; - right = temp ^ (spfunction2[(right1 >>> 24) & 0x3f] | spfunction4[(right1 >>> 16) & 0x3f] | spfunction6[(right1 >>> - 8) & 0x3f] | spfunction8[right1 & 0x3f] | spfunction1[(right2 >>> 24) & 0x3f] | spfunction3[(right2 >>> 16) & - 0x3f] | spfunction5[(right2 >>> 8) & 0x3f] | spfunction7[right2 & 0x3f]); - } - temp = left; - left = right; - right = temp; //unreverse left and right - } //for either 1 or 3 iterations - - //move then each one bit to the right - left = ((left >>> 1) | (left << 31)); - right = ((right >>> 1) | (right << 31)); - - //now perform IP-1, which is IP in the opposite direction - temp = ((left >>> 1) ^ right) & 0x55555555; - right ^= temp; - left ^= (temp << 1); - temp = ((right >>> 8) ^ left) & 0x00ff00ff; - left ^= temp; - right ^= (temp << 8); - temp = ((right >>> 2) ^ left) & 0x33333333; - left ^= temp; - right ^= (temp << 2); - temp = ((left >>> 16) ^ right) & 0x0000ffff; - right ^= temp; - left ^= (temp << 16); - temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; - right ^= temp; - left ^= (temp << 4); - - //for Cipher Block Chaining mode, xor the message with the previous result - if (mode === 1) { - if (encrypt) { - cbcleft = left; - cbcright = right; - } else { - left ^= cbcleft2; - right ^= cbcright2; - } - } - - result[k++] = (left >>> 24); - result[k++] = ((left >>> 16) & 0xff); - result[k++] = ((left >>> 8) & 0xff); - result[k++] = (left & 0xff); - result[k++] = (right >>> 24); - result[k++] = ((right >>> 16) & 0xff); - result[k++] = ((right >>> 8) & 0xff); - result[k++] = (right & 0xff); - } //for every 8 characters, or 64 bits in the message - - //only remove padding if decrypting - note that you need to use the same padding option for both encrypt and decrypt - if (!encrypt) { - result = desRemovePadding(result, padding); - } - - return result; - } //end of des - - - //desCreateKeys - //this takes as input a 64 bit key (even though only 56 bits are used) - //as an array of 2 integers, and returns 16 48 bit keys - - function desCreateKeys(key) { - //declaring this locally speeds things up a bit - const pc2bytes0 = [ - 0, 0x4, 0x20000000, 0x20000004, 0x10000, 0x10004, 0x20010000, 0x20010004, 0x200, 0x204, - 0x20000200, 0x20000204, 0x10200, 0x10204, 0x20010200, 0x20010204 - ]; - const pc2bytes1 = [ - 0, 0x1, 0x100000, 0x100001, 0x4000000, 0x4000001, 0x4100000, 0x4100001, 0x100, 0x101, 0x100100, - 0x100101, 0x4000100, 0x4000101, 0x4100100, 0x4100101 - ]; - const pc2bytes2 = [ - 0, 0x8, 0x800, 0x808, 0x1000000, 0x1000008, 0x1000800, 0x1000808, 0, 0x8, 0x800, 0x808, - 0x1000000, 0x1000008, 0x1000800, 0x1000808 - ]; - const pc2bytes3 = [ - 0, 0x200000, 0x8000000, 0x8200000, 0x2000, 0x202000, 0x8002000, 0x8202000, 0x20000, 0x220000, - 0x8020000, 0x8220000, 0x22000, 0x222000, 0x8022000, 0x8222000 - ]; - const pc2bytes4 = [ - 0, 0x40000, 0x10, 0x40010, 0, 0x40000, 0x10, 0x40010, 0x1000, 0x41000, 0x1010, 0x41010, 0x1000, - 0x41000, 0x1010, 0x41010 - ]; - const pc2bytes5 = [ - 0, 0x400, 0x20, 0x420, 0, 0x400, 0x20, 0x420, 0x2000000, 0x2000400, 0x2000020, 0x2000420, - 0x2000000, 0x2000400, 0x2000020, 0x2000420 - ]; - const pc2bytes6 = [ - 0, 0x10000000, 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002, 0, 0x10000000, - 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002 - ]; - const pc2bytes7 = [ - 0, 0x10000, 0x800, 0x10800, 0x20000000, 0x20010000, 0x20000800, 0x20010800, 0x20000, 0x30000, - 0x20800, 0x30800, 0x20020000, 0x20030000, 0x20020800, 0x20030800 - ]; - const pc2bytes8 = [ - 0, 0x40000, 0, 0x40000, 0x2, 0x40002, 0x2, 0x40002, 0x2000000, 0x2040000, 0x2000000, 0x2040000, - 0x2000002, 0x2040002, 0x2000002, 0x2040002 - ]; - const pc2bytes9 = [ - 0, 0x10000000, 0x8, 0x10000008, 0, 0x10000000, 0x8, 0x10000008, 0x400, 0x10000400, 0x408, - 0x10000408, 0x400, 0x10000400, 0x408, 0x10000408 - ]; - const pc2bytes10 = [ - 0, 0x20, 0, 0x20, 0x100000, 0x100020, 0x100000, 0x100020, 0x2000, 0x2020, 0x2000, 0x2020, - 0x102000, 0x102020, 0x102000, 0x102020 - ]; - const pc2bytes11 = [ - 0, 0x1000000, 0x200, 0x1000200, 0x200000, 0x1200000, 0x200200, 0x1200200, 0x4000000, 0x5000000, - 0x4000200, 0x5000200, 0x4200000, 0x5200000, 0x4200200, 0x5200200 - ]; - const pc2bytes12 = [ - 0, 0x1000, 0x8000000, 0x8001000, 0x80000, 0x81000, 0x8080000, 0x8081000, 0x10, 0x1010, - 0x8000010, 0x8001010, 0x80010, 0x81010, 0x8080010, 0x8081010 - ]; - const pc2bytes13 = [0, 0x4, 0x100, 0x104, 0, 0x4, 0x100, 0x104, 0x1, 0x5, 0x101, 0x105, 0x1, 0x5, 0x101, 0x105]; - - //how many iterations (1 for des, 3 for triple des) - const iterations = key.length > 8 ? 3 : 1; //changed by Paul 16/6/2007 to use Triple DES for 9+ byte keys - //stores the return keys - const keys = new Array(32 * iterations); - //now define the left shifts which need to be done - const shifts = [0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0]; - //other variables - let lefttemp; - let righttemp; - let m = 0; - let n = 0; - let temp; - - for (let j = 0; j < iterations; j++) { //either 1 or 3 iterations - let left = (key[m++] << 24) | (key[m++] << 16) | (key[m++] << 8) | key[m++]; - let right = (key[m++] << 24) | (key[m++] << 16) | (key[m++] << 8) | key[m++]; - - temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; - right ^= temp; - left ^= (temp << 4); - temp = ((right >>> -16) ^ left) & 0x0000ffff; - left ^= temp; - right ^= (temp << -16); - temp = ((left >>> 2) ^ right) & 0x33333333; - right ^= temp; - left ^= (temp << 2); - temp = ((right >>> -16) ^ left) & 0x0000ffff; - left ^= temp; - right ^= (temp << -16); - temp = ((left >>> 1) ^ right) & 0x55555555; - right ^= temp; - left ^= (temp << 1); - temp = ((right >>> 8) ^ left) & 0x00ff00ff; - left ^= temp; - right ^= (temp << 8); - temp = ((left >>> 1) ^ right) & 0x55555555; - right ^= temp; - left ^= (temp << 1); - - //the right side needs to be shifted and to get the last four bits of the left side - temp = (left << 8) | ((right >>> 20) & 0x000000f0); - //left needs to be put upside down - left = (right << 24) | ((right << 8) & 0xff0000) | ((right >>> 8) & 0xff00) | ((right >>> 24) & 0xf0); - right = temp; - - //now go through and perform these shifts on the left and right keys - for (let i = 0; i < shifts.length; i++) { - //shift the keys either one or two bits to the left - if (shifts[i]) { - left = (left << 2) | (left >>> 26); - right = (right << 2) | (right >>> 26); - } else { - left = (left << 1) | (left >>> 27); - right = (right << 1) | (right >>> 27); - } - left &= -0xf; - right &= -0xf; - - //now apply PC-2, in such a way that E is easier when encrypting or decrypting - //this conversion will look like PC-2 except only the last 6 bits of each byte are used - //rather than 48 consecutive bits and the order of lines will be according to - //how the S selection functions will be applied: S2, S4, S6, S8, S1, S3, S5, S7 - lefttemp = pc2bytes0[left >>> 28] | pc2bytes1[(left >>> 24) & 0xf] | pc2bytes2[(left >>> 20) & 0xf] | pc2bytes3[( - left >>> 16) & 0xf] | pc2bytes4[(left >>> 12) & 0xf] | pc2bytes5[(left >>> 8) & 0xf] | pc2bytes6[(left >>> 4) & - 0xf]; - righttemp = pc2bytes7[right >>> 28] | pc2bytes8[(right >>> 24) & 0xf] | pc2bytes9[(right >>> 20) & 0xf] | - pc2bytes10[(right >>> 16) & 0xf] | pc2bytes11[(right >>> 12) & 0xf] | pc2bytes12[(right >>> 8) & 0xf] | - pc2bytes13[(right >>> 4) & 0xf]; - temp = ((righttemp >>> 16) ^ lefttemp) & 0x0000ffff; - keys[n++] = lefttemp ^ temp; - keys[n++] = righttemp ^ (temp << 16); - } - } //for each iterations - //return the keys we've created - return keys; - } //end of desCreateKeys - - - function desAddPadding(message, padding) { - const padLength = 8 - (message.length % 8); - - let pad; - if (padding === 2 && (padLength < 8)) { //pad the message with spaces - pad = ' '.charCodeAt(0); - } else if (padding === 1) { //PKCS7 padding - pad = padLength; - } else if (!padding && (padLength < 8)) { //pad the message out with null bytes - pad = 0; - } else if (padLength === 8) { - return message; - } else { - throw new Error('des: invalid padding'); - } - - const paddedMessage = new Uint8Array(message.length + padLength); - for (let i = 0; i < message.length; i++) { - paddedMessage[i] = message[i]; - } - for (let j = 0; j < padLength; j++) { - paddedMessage[message.length + j] = pad; - } - - return paddedMessage; - } - - function desRemovePadding(message, padding) { - let padLength = null; - let pad; - if (padding === 2) { // space padded - pad = ' '.charCodeAt(0); - } else if (padding === 1) { // PKCS7 - padLength = message[message.length - 1]; - } else if (!padding) { // null padding - pad = 0; - } else { - throw new Error('des: invalid padding'); - } - - if (!padLength) { - padLength = 1; - while (message[message.length - padLength] === pad) { - padLength++; - } - padLength--; - } - - return message.subarray(0, message.length - padLength); - } - - // added by Recurity Labs - - function TripleDES(key) { - this.key = []; - - for (let i = 0; i < 3; i++) { - this.key.push(new Uint8Array(key.subarray(i * 8, (i * 8) + 8))); - } - - this.encrypt = function(block) { - return des( - desCreateKeys(this.key[2]), - des( - desCreateKeys(this.key[1]), - des( - desCreateKeys(this.key[0]), - block, true, 0, null, null - ), - false, 0, null, null - ), true, 0, null, null - ); - }; - } - - TripleDES.keySize = TripleDES.prototype.keySize = 24; - TripleDES.blockSize = TripleDES.prototype.blockSize = 8; - - // This is "original" DES - - function DES(key) { - this.key = key; - - this.encrypt = function(block, padding) { - const keys = desCreateKeys(this.key); - return des(keys, block, true, 0, null, padding); - }; - - this.decrypt = function(block, padding) { - const keys = desCreateKeys(this.key); - return des(keys, block, false, 0, null, padding); - }; - } - - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - - // Copyright 2010 pjacobs@xeekr.com . All rights reserved. - - // Modified by Recurity Labs GmbH - - // fixed/modified by Herbert Hanewinkel, www.haneWIN.de - // check www.haneWIN.de for the latest version - - // cast5.js is a Javascript implementation of CAST-128, as defined in RFC 2144. - // CAST-128 is a common OpenPGP cipher. - - - // CAST5 constructor - - function OpenPGPSymEncCAST5() { - this.BlockSize = 8; - this.KeySize = 16; - - this.setKey = function(key) { - this.masking = new Array(16); - this.rotate = new Array(16); - - this.reset(); - - if (key.length === this.KeySize) { - this.keySchedule(key); - } else { - throw new Error('CAST-128: keys must be 16 bytes'); - } - return true; - }; - - this.reset = function() { - for (let i = 0; i < 16; i++) { - this.masking[i] = 0; - this.rotate[i] = 0; - } - }; - - this.getBlockSize = function() { - return this.BlockSize; - }; - - this.encrypt = function(src) { - const dst = new Array(src.length); - - for (let i = 0; i < src.length; i += 8) { - let l = (src[i] << 24) | (src[i + 1] << 16) | (src[i + 2] << 8) | src[i + 3]; - let r = (src[i + 4] << 24) | (src[i + 5] << 16) | (src[i + 6] << 8) | src[i + 7]; - let t; - - t = r; - r = l ^ f1(r, this.masking[0], this.rotate[0]); - l = t; - t = r; - r = l ^ f2(r, this.masking[1], this.rotate[1]); - l = t; - t = r; - r = l ^ f3(r, this.masking[2], this.rotate[2]); - l = t; - t = r; - r = l ^ f1(r, this.masking[3], this.rotate[3]); - l = t; - - t = r; - r = l ^ f2(r, this.masking[4], this.rotate[4]); - l = t; - t = r; - r = l ^ f3(r, this.masking[5], this.rotate[5]); - l = t; - t = r; - r = l ^ f1(r, this.masking[6], this.rotate[6]); - l = t; - t = r; - r = l ^ f2(r, this.masking[7], this.rotate[7]); - l = t; - - t = r; - r = l ^ f3(r, this.masking[8], this.rotate[8]); - l = t; - t = r; - r = l ^ f1(r, this.masking[9], this.rotate[9]); - l = t; - t = r; - r = l ^ f2(r, this.masking[10], this.rotate[10]); - l = t; - t = r; - r = l ^ f3(r, this.masking[11], this.rotate[11]); - l = t; - - t = r; - r = l ^ f1(r, this.masking[12], this.rotate[12]); - l = t; - t = r; - r = l ^ f2(r, this.masking[13], this.rotate[13]); - l = t; - t = r; - r = l ^ f3(r, this.masking[14], this.rotate[14]); - l = t; - t = r; - r = l ^ f1(r, this.masking[15], this.rotate[15]); - l = t; - - dst[i] = (r >>> 24) & 255; - dst[i + 1] = (r >>> 16) & 255; - dst[i + 2] = (r >>> 8) & 255; - dst[i + 3] = r & 255; - dst[i + 4] = (l >>> 24) & 255; - dst[i + 5] = (l >>> 16) & 255; - dst[i + 6] = (l >>> 8) & 255; - dst[i + 7] = l & 255; - } - - return dst; - }; - - this.decrypt = function(src) { - const dst = new Array(src.length); - - for (let i = 0; i < src.length; i += 8) { - let l = (src[i] << 24) | (src[i + 1] << 16) | (src[i + 2] << 8) | src[i + 3]; - let r = (src[i + 4] << 24) | (src[i + 5] << 16) | (src[i + 6] << 8) | src[i + 7]; - let t; - - t = r; - r = l ^ f1(r, this.masking[15], this.rotate[15]); - l = t; - t = r; - r = l ^ f3(r, this.masking[14], this.rotate[14]); - l = t; - t = r; - r = l ^ f2(r, this.masking[13], this.rotate[13]); - l = t; - t = r; - r = l ^ f1(r, this.masking[12], this.rotate[12]); - l = t; - - t = r; - r = l ^ f3(r, this.masking[11], this.rotate[11]); - l = t; - t = r; - r = l ^ f2(r, this.masking[10], this.rotate[10]); - l = t; - t = r; - r = l ^ f1(r, this.masking[9], this.rotate[9]); - l = t; - t = r; - r = l ^ f3(r, this.masking[8], this.rotate[8]); - l = t; - - t = r; - r = l ^ f2(r, this.masking[7], this.rotate[7]); - l = t; - t = r; - r = l ^ f1(r, this.masking[6], this.rotate[6]); - l = t; - t = r; - r = l ^ f3(r, this.masking[5], this.rotate[5]); - l = t; - t = r; - r = l ^ f2(r, this.masking[4], this.rotate[4]); - l = t; - - t = r; - r = l ^ f1(r, this.masking[3], this.rotate[3]); - l = t; - t = r; - r = l ^ f3(r, this.masking[2], this.rotate[2]); - l = t; - t = r; - r = l ^ f2(r, this.masking[1], this.rotate[1]); - l = t; - t = r; - r = l ^ f1(r, this.masking[0], this.rotate[0]); - l = t; - - dst[i] = (r >>> 24) & 255; - dst[i + 1] = (r >>> 16) & 255; - dst[i + 2] = (r >>> 8) & 255; - dst[i + 3] = r & 255; - dst[i + 4] = (l >>> 24) & 255; - dst[i + 5] = (l >> 16) & 255; - dst[i + 6] = (l >> 8) & 255; - dst[i + 7] = l & 255; - } - - return dst; - }; - const scheduleA = new Array(4); - - scheduleA[0] = new Array(4); - scheduleA[0][0] = [4, 0, 0xd, 0xf, 0xc, 0xe, 0x8]; - scheduleA[0][1] = [5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa]; - scheduleA[0][2] = [6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9]; - scheduleA[0][3] = [7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb]; - - scheduleA[1] = new Array(4); - scheduleA[1][0] = [0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0]; - scheduleA[1][1] = [1, 4, 0, 2, 1, 3, 16 + 2]; - scheduleA[1][2] = [2, 5, 7, 6, 5, 4, 16 + 1]; - scheduleA[1][3] = [3, 7, 0xa, 9, 0xb, 8, 16 + 3]; - - scheduleA[2] = new Array(4); - scheduleA[2][0] = [4, 0, 0xd, 0xf, 0xc, 0xe, 8]; - scheduleA[2][1] = [5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa]; - scheduleA[2][2] = [6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9]; - scheduleA[2][3] = [7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb]; - - - scheduleA[3] = new Array(4); - scheduleA[3][0] = [0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0]; - scheduleA[3][1] = [1, 4, 0, 2, 1, 3, 16 + 2]; - scheduleA[3][2] = [2, 5, 7, 6, 5, 4, 16 + 1]; - scheduleA[3][3] = [3, 7, 0xa, 9, 0xb, 8, 16 + 3]; - - const scheduleB = new Array(4); - - scheduleB[0] = new Array(4); - scheduleB[0][0] = [16 + 8, 16 + 9, 16 + 7, 16 + 6, 16 + 2]; - scheduleB[0][1] = [16 + 0xa, 16 + 0xb, 16 + 5, 16 + 4, 16 + 6]; - scheduleB[0][2] = [16 + 0xc, 16 + 0xd, 16 + 3, 16 + 2, 16 + 9]; - scheduleB[0][3] = [16 + 0xe, 16 + 0xf, 16 + 1, 16 + 0, 16 + 0xc]; - - scheduleB[1] = new Array(4); - scheduleB[1][0] = [3, 2, 0xc, 0xd, 8]; - scheduleB[1][1] = [1, 0, 0xe, 0xf, 0xd]; - scheduleB[1][2] = [7, 6, 8, 9, 3]; - scheduleB[1][3] = [5, 4, 0xa, 0xb, 7]; - - - scheduleB[2] = new Array(4); - scheduleB[2][0] = [16 + 3, 16 + 2, 16 + 0xc, 16 + 0xd, 16 + 9]; - scheduleB[2][1] = [16 + 1, 16 + 0, 16 + 0xe, 16 + 0xf, 16 + 0xc]; - scheduleB[2][2] = [16 + 7, 16 + 6, 16 + 8, 16 + 9, 16 + 2]; - scheduleB[2][3] = [16 + 5, 16 + 4, 16 + 0xa, 16 + 0xb, 16 + 6]; - - - scheduleB[3] = new Array(4); - scheduleB[3][0] = [8, 9, 7, 6, 3]; - scheduleB[3][1] = [0xa, 0xb, 5, 4, 7]; - scheduleB[3][2] = [0xc, 0xd, 3, 2, 8]; - scheduleB[3][3] = [0xe, 0xf, 1, 0, 0xd]; - - // changed 'in' to 'inn' (in javascript 'in' is a reserved word) - this.keySchedule = function(inn) { - const t = new Array(8); - const k = new Array(32); - - let j; - - for (let i = 0; i < 4; i++) { - j = i * 4; - t[i] = (inn[j] << 24) | (inn[j + 1] << 16) | (inn[j + 2] << 8) | inn[j + 3]; - } - - const x = [6, 7, 4, 5]; - let ki = 0; - let w; - - for (let half = 0; half < 2; half++) { - for (let round = 0; round < 4; round++) { - for (j = 0; j < 4; j++) { - const a = scheduleA[round][j]; - w = t[a[1]]; - - w ^= sBox[4][(t[a[2] >>> 2] >>> (24 - 8 * (a[2] & 3))) & 0xff]; - w ^= sBox[5][(t[a[3] >>> 2] >>> (24 - 8 * (a[3] & 3))) & 0xff]; - w ^= sBox[6][(t[a[4] >>> 2] >>> (24 - 8 * (a[4] & 3))) & 0xff]; - w ^= sBox[7][(t[a[5] >>> 2] >>> (24 - 8 * (a[5] & 3))) & 0xff]; - w ^= sBox[x[j]][(t[a[6] >>> 2] >>> (24 - 8 * (a[6] & 3))) & 0xff]; - t[a[0]] = w; - } - - for (j = 0; j < 4; j++) { - const b = scheduleB[round][j]; - w = sBox[4][(t[b[0] >>> 2] >>> (24 - 8 * (b[0] & 3))) & 0xff]; - - w ^= sBox[5][(t[b[1] >>> 2] >>> (24 - 8 * (b[1] & 3))) & 0xff]; - w ^= sBox[6][(t[b[2] >>> 2] >>> (24 - 8 * (b[2] & 3))) & 0xff]; - w ^= sBox[7][(t[b[3] >>> 2] >>> (24 - 8 * (b[3] & 3))) & 0xff]; - w ^= sBox[4 + j][(t[b[4] >>> 2] >>> (24 - 8 * (b[4] & 3))) & 0xff]; - k[ki] = w; - ki++; - } - } - } - - for (let i = 0; i < 16; i++) { - this.masking[i] = k[i]; - this.rotate[i] = k[16 + i] & 0x1f; - } - }; - - // These are the three 'f' functions. See RFC 2144, section 2.2. - - function f1(d, m, r) { - const t = m + d; - const I = (t << r) | (t >>> (32 - r)); - return ((sBox[0][I >>> 24] ^ sBox[1][(I >>> 16) & 255]) - sBox[2][(I >>> 8) & 255]) + sBox[3][I & 255]; - } - - function f2(d, m, r) { - const t = m ^ d; - const I = (t << r) | (t >>> (32 - r)); - return ((sBox[0][I >>> 24] - sBox[1][(I >>> 16) & 255]) + sBox[2][(I >>> 8) & 255]) ^ sBox[3][I & 255]; - } - - function f3(d, m, r) { - const t = m - d; - const I = (t << r) | (t >>> (32 - r)); - return ((sBox[0][I >>> 24] + sBox[1][(I >>> 16) & 255]) ^ sBox[2][(I >>> 8) & 255]) - sBox[3][I & 255]; - } - - const sBox = new Array(8); - sBox[0] = [ - 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949, - 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, - 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, - 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0, - 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, - 0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935, - 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d, - 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, - 0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe, - 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3, - 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, - 0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291, - 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779, - 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, - 0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, - 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d, - 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, - 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, - 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c, - 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, - 0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d, - 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96, - 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, - 0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, - 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, - 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, - 0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, - 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872, - 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, - 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, - 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9, - 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf - ]; - - sBox[1] = [ - 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651, - 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, - 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, - 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806, - 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, - 0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359, - 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b, - 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, - 0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34, - 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb, - 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, - 0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860, - 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b, - 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, - 0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, - 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, - 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, - 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, - 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f, - 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, - 0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6, - 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58, - 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, - 0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, - 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6, - 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, - 0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6, - 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f, - 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, - 0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, - 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9, - 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1 - ]; - - sBox[2] = [ - 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90, - 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, - 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, - 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240, - 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, - 0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, - 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71, - 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, - 0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, - 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15, - 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, - 0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176, - 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148, - 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, - 0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, - 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e, - 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, - 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, - 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a, - 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, - 0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, - 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5, - 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, - 0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536, - 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, - 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, - 0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69, - 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, - 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, - 0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, - 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a, - 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783 - ]; - - sBox[3] = [ - 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1, - 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, - 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, - 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121, - 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, - 0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, - 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb, - 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, - 0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d, - 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6, - 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, - 0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003, - 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, - 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, - 0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, - 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a, - 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, - 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, - 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26, - 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, - 0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7, - 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417, - 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, - 0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2, - 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, - 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, - 0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, - 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, - 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, - 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, - 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282, - 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2 - ]; - - sBox[4] = [ - 0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f, - 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, - 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, - 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02, - 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, - 0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7, - 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9, - 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, - 0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774, - 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655, - 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, - 0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910, - 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1, - 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, - 0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, - 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f, - 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, - 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, - 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3, - 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, - 0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4, - 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2, - 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, - 0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5, - 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, - 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, - 0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801, - 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, - 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, - 0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, - 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8, - 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4 - ]; - - sBox[5] = [ - 0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac, - 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, - 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, - 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98, - 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, - 0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3, - 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd, - 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, - 0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9, - 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54, - 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, - 0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc, - 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf, - 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, - 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, - 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289, - 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, - 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, - 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b, - 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, - 0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13, - 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976, - 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, - 0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891, - 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da, - 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, - 0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084, - 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25, - 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, - 0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, - 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd, - 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f - ]; - - sBox[6] = [ - 0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f, - 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, - 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, - 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19, - 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, - 0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516, - 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88, - 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, - 0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756, - 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, - 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, - 0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688, - 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28, - 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, - 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, - 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, - 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, - 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, - 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566, - 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, - 0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962, - 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e, - 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, - 0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c, - 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, - 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, - 0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be, - 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767, - 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, - 0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, - 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c, - 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3 - ]; - - sBox[7] = [ - 0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5, - 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, - 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, - 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d, - 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, - 0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862, - 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc, - 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, - 0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e, - 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039, - 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, - 0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42, - 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5, - 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, - 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, - 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c, - 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, - 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, - 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70, - 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, - 0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c, - 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3, - 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, - 0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101, - 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f, - 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, - 0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a, - 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c, - 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, - 0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, - 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82, - 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e - ]; - } - - function CAST5(key) { - this.cast5 = new OpenPGPSymEncCAST5(); - this.cast5.setKey(key); - - this.encrypt = function(block) { - return this.cast5.encrypt(block); - }; - } - - CAST5.blockSize = CAST5.prototype.blockSize = 8; - CAST5.keySize = CAST5.prototype.keySize = 16; - - /* eslint-disable no-mixed-operators, no-fallthrough */ - - - /* Modified by Recurity Labs GmbH - * - * Cipher.js - * A block-cipher algorithm implementation on JavaScript - * See Cipher.readme.txt for further information. - * - * Copyright(c) 2009 Atsushi Oka [ http://oka.nu/ ] - * This script file is distributed under the LGPL - * - * ACKNOWLEDGMENT - * - * The main subroutines are written by Michiel van Everdingen. - * - * Michiel van Everdingen - * http://home.versatel.nl/MAvanEverdingen/index.html - * - * All rights for these routines are reserved to Michiel van Everdingen. - * - */ - - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - //Math - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - const MAXINT = 0xFFFFFFFF; - - function rotw(w, n) { - return (w << n | w >>> (32 - n)) & MAXINT; - } - - function getW(a, i) { - return a[i] | a[i + 1] << 8 | a[i + 2] << 16 | a[i + 3] << 24; - } - - function setW(a, i, w) { - a.splice(i, 4, w & 0xFF, (w >>> 8) & 0xFF, (w >>> 16) & 0xFF, (w >>> 24) & 0xFF); - } - - function getB(x, n) { - return (x >>> (n * 8)) & 0xFF; - } - - // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Twofish - // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - function createTwofish() { - // - let keyBytes = null; - let dataBytes = null; - let dataOffset = -1; - // var dataLength = -1; - // var idx2 = -1; - // - - let tfsKey = []; - let tfsM = [ - [], - [], - [], - [] - ]; - - function tfsInit(key) { - keyBytes = key; - let i; - let a; - let b; - let c; - let d; - const meKey = []; - const moKey = []; - const inKey = []; - let kLen; - const sKey = []; - let f01; - let f5b; - let fef; - - const q0 = [ - [8, 1, 7, 13, 6, 15, 3, 2, 0, 11, 5, 9, 14, 12, 10, 4], - [2, 8, 11, 13, 15, 7, 6, 14, 3, 1, 9, 4, 0, 10, 12, 5] - ]; - const q1 = [ - [14, 12, 11, 8, 1, 2, 3, 5, 15, 4, 10, 6, 7, 0, 9, 13], - [1, 14, 2, 11, 4, 12, 3, 7, 6, 13, 10, 5, 15, 9, 0, 8] - ]; - const q2 = [ - [11, 10, 5, 14, 6, 13, 9, 0, 12, 8, 15, 3, 2, 4, 7, 1], - [4, 12, 7, 5, 1, 6, 9, 10, 0, 14, 13, 8, 2, 11, 3, 15] - ]; - const q3 = [ - [13, 7, 15, 4, 1, 2, 6, 14, 9, 11, 3, 0, 8, 5, 12, 10], - [11, 9, 5, 1, 12, 3, 13, 14, 6, 4, 7, 15, 2, 0, 8, 10] - ]; - const ror4 = [0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15]; - const ashx = [0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 5, 14, 7]; - const q = [ - [], - [] - ]; - const m = [ - [], - [], - [], - [] - ]; - - function ffm5b(x) { - return x ^ (x >> 2) ^ [0, 90, 180, 238][x & 3]; - } - - function ffmEf(x) { - return x ^ (x >> 1) ^ (x >> 2) ^ [0, 238, 180, 90][x & 3]; - } - - function mdsRem(p, q) { - let i; - let t; - let u; - for (i = 0; i < 8; i++) { - t = q >>> 24; - q = ((q << 8) & MAXINT) | p >>> 24; - p = (p << 8) & MAXINT; - u = t << 1; - if (t & 128) { - u ^= 333; - } - q ^= t ^ (u << 16); - u ^= t >>> 1; - if (t & 1) { - u ^= 166; - } - q ^= u << 24 | u << 8; - } - return q; - } - - function qp(n, x) { - const a = x >> 4; - const b = x & 15; - const c = q0[n][a ^ b]; - const d = q1[n][ror4[b] ^ ashx[a]]; - return q3[n][ror4[d] ^ ashx[c]] << 4 | q2[n][c ^ d]; - } - - function hFun(x, key) { - let a = getB(x, 0); - let b = getB(x, 1); - let c = getB(x, 2); - let d = getB(x, 3); - switch (kLen) { - case 4: - a = q[1][a] ^ getB(key[3], 0); - b = q[0][b] ^ getB(key[3], 1); - c = q[0][c] ^ getB(key[3], 2); - d = q[1][d] ^ getB(key[3], 3); - case 3: - a = q[1][a] ^ getB(key[2], 0); - b = q[1][b] ^ getB(key[2], 1); - c = q[0][c] ^ getB(key[2], 2); - d = q[0][d] ^ getB(key[2], 3); - case 2: - a = q[0][q[0][a] ^ getB(key[1], 0)] ^ getB(key[0], 0); - b = q[0][q[1][b] ^ getB(key[1], 1)] ^ getB(key[0], 1); - c = q[1][q[0][c] ^ getB(key[1], 2)] ^ getB(key[0], 2); - d = q[1][q[1][d] ^ getB(key[1], 3)] ^ getB(key[0], 3); - } - return m[0][a] ^ m[1][b] ^ m[2][c] ^ m[3][d]; - } - - keyBytes = keyBytes.slice(0, 32); - i = keyBytes.length; - while (i !== 16 && i !== 24 && i !== 32) { - keyBytes[i++] = 0; - } - - for (i = 0; i < keyBytes.length; i += 4) { - inKey[i >> 2] = getW(keyBytes, i); - } - for (i = 0; i < 256; i++) { - q[0][i] = qp(0, i); - q[1][i] = qp(1, i); - } - for (i = 0; i < 256; i++) { - f01 = q[1][i]; - f5b = ffm5b(f01); - fef = ffmEf(f01); - m[0][i] = f01 + (f5b << 8) + (fef << 16) + (fef << 24); - m[2][i] = f5b + (fef << 8) + (f01 << 16) + (fef << 24); - f01 = q[0][i]; - f5b = ffm5b(f01); - fef = ffmEf(f01); - m[1][i] = fef + (fef << 8) + (f5b << 16) + (f01 << 24); - m[3][i] = f5b + (f01 << 8) + (fef << 16) + (f5b << 24); - } - - kLen = inKey.length / 2; - for (i = 0; i < kLen; i++) { - a = inKey[i + i]; - meKey[i] = a; - b = inKey[i + i + 1]; - moKey[i] = b; - sKey[kLen - i - 1] = mdsRem(a, b); - } - for (i = 0; i < 40; i += 2) { - a = 0x1010101 * i; - b = a + 0x1010101; - a = hFun(a, meKey); - b = rotw(hFun(b, moKey), 8); - tfsKey[i] = (a + b) & MAXINT; - tfsKey[i + 1] = rotw(a + 2 * b, 9); - } - for (i = 0; i < 256; i++) { - a = b = c = d = i; - switch (kLen) { - case 4: - a = q[1][a] ^ getB(sKey[3], 0); - b = q[0][b] ^ getB(sKey[3], 1); - c = q[0][c] ^ getB(sKey[3], 2); - d = q[1][d] ^ getB(sKey[3], 3); - case 3: - a = q[1][a] ^ getB(sKey[2], 0); - b = q[1][b] ^ getB(sKey[2], 1); - c = q[0][c] ^ getB(sKey[2], 2); - d = q[0][d] ^ getB(sKey[2], 3); - case 2: - tfsM[0][i] = m[0][q[0][q[0][a] ^ getB(sKey[1], 0)] ^ getB(sKey[0], 0)]; - tfsM[1][i] = m[1][q[0][q[1][b] ^ getB(sKey[1], 1)] ^ getB(sKey[0], 1)]; - tfsM[2][i] = m[2][q[1][q[0][c] ^ getB(sKey[1], 2)] ^ getB(sKey[0], 2)]; - tfsM[3][i] = m[3][q[1][q[1][d] ^ getB(sKey[1], 3)] ^ getB(sKey[0], 3)]; - } - } - } - - function tfsG0(x) { - return tfsM[0][getB(x, 0)] ^ tfsM[1][getB(x, 1)] ^ tfsM[2][getB(x, 2)] ^ tfsM[3][getB(x, 3)]; - } - - function tfsG1(x) { - return tfsM[0][getB(x, 3)] ^ tfsM[1][getB(x, 0)] ^ tfsM[2][getB(x, 1)] ^ tfsM[3][getB(x, 2)]; - } - - function tfsFrnd(r, blk) { - let a = tfsG0(blk[0]); - let b = tfsG1(blk[1]); - blk[2] = rotw(blk[2] ^ (a + b + tfsKey[4 * r + 8]) & MAXINT, 31); - blk[3] = rotw(blk[3], 1) ^ (a + 2 * b + tfsKey[4 * r + 9]) & MAXINT; - a = tfsG0(blk[2]); - b = tfsG1(blk[3]); - blk[0] = rotw(blk[0] ^ (a + b + tfsKey[4 * r + 10]) & MAXINT, 31); - blk[1] = rotw(blk[1], 1) ^ (a + 2 * b + tfsKey[4 * r + 11]) & MAXINT; - } - - function tfsIrnd(i, blk) { - let a = tfsG0(blk[0]); - let b = tfsG1(blk[1]); - blk[2] = rotw(blk[2], 1) ^ (a + b + tfsKey[4 * i + 10]) & MAXINT; - blk[3] = rotw(blk[3] ^ (a + 2 * b + tfsKey[4 * i + 11]) & MAXINT, 31); - a = tfsG0(blk[2]); - b = tfsG1(blk[3]); - blk[0] = rotw(blk[0], 1) ^ (a + b + tfsKey[4 * i + 8]) & MAXINT; - blk[1] = rotw(blk[1] ^ (a + 2 * b + tfsKey[4 * i + 9]) & MAXINT, 31); - } - - function tfsClose() { - tfsKey = []; - tfsM = [ - [], - [], - [], - [] - ]; - } - - function tfsEncrypt(data, offset) { - dataBytes = data; - dataOffset = offset; - const blk = [getW(dataBytes, dataOffset) ^ tfsKey[0], - getW(dataBytes, dataOffset + 4) ^ tfsKey[1], - getW(dataBytes, dataOffset + 8) ^ tfsKey[2], - getW(dataBytes, dataOffset + 12) ^ tfsKey[3]]; - for (let j = 0; j < 8; j++) { - tfsFrnd(j, blk); - } - setW(dataBytes, dataOffset, blk[2] ^ tfsKey[4]); - setW(dataBytes, dataOffset + 4, blk[3] ^ tfsKey[5]); - setW(dataBytes, dataOffset + 8, blk[0] ^ tfsKey[6]); - setW(dataBytes, dataOffset + 12, blk[1] ^ tfsKey[7]); - dataOffset += 16; - return dataBytes; - } - - function tfsDecrypt(data, offset) { - dataBytes = data; - dataOffset = offset; - const blk = [getW(dataBytes, dataOffset) ^ tfsKey[4], - getW(dataBytes, dataOffset + 4) ^ tfsKey[5], - getW(dataBytes, dataOffset + 8) ^ tfsKey[6], - getW(dataBytes, dataOffset + 12) ^ tfsKey[7]]; - for (let j = 7; j >= 0; j--) { - tfsIrnd(j, blk); - } - setW(dataBytes, dataOffset, blk[2] ^ tfsKey[0]); - setW(dataBytes, dataOffset + 4, blk[3] ^ tfsKey[1]); - setW(dataBytes, dataOffset + 8, blk[0] ^ tfsKey[2]); - setW(dataBytes, dataOffset + 12, blk[1] ^ tfsKey[3]); - dataOffset += 16; - } - - // added by Recurity Labs - - function tfsFinal() { - return dataBytes; - } - - return { - name: 'twofish', - blocksize: 128 / 8, - open: tfsInit, - close: tfsClose, - encrypt: tfsEncrypt, - decrypt: tfsDecrypt, - // added by Recurity Labs - finalize: tfsFinal - }; - } - - // added by Recurity Labs - - function TF(key) { - this.tf = createTwofish(); - this.tf.open(Array.from(key), 0); - - this.encrypt = function(block) { - return this.tf.encrypt(Array.from(block), 0); - }; - } - - TF.keySize = TF.prototype.keySize = 32; - TF.blockSize = TF.prototype.blockSize = 16; - - /* Modified by Recurity Labs GmbH - * - * Originally written by nklein software (nklein.com) - */ - - /* - * Javascript implementation based on Bruce Schneier's reference implementation. - * - * - * The constructor doesn't do much of anything. It's just here - * so we can start defining properties and methods and such. - */ - function Blowfish() {} - - /* - * Declare the block size so that protocols know what size - * Initialization Vector (IV) they will need. - */ - Blowfish.prototype.BLOCKSIZE = 8; - - /* - * These are the default SBOXES. - */ - Blowfish.prototype.SBOXES = [ - [ - 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, - 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, - 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658, - 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, - 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, - 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, - 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6, - 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, - 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, - 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, - 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, - 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, - 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, - 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, - 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, - 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, - 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, - 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, - 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, - 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, - 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, - 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, - 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, - 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, - 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, - 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, - 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8, - 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, - 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, - 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, - 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, - 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, - 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, - 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, - 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, - 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, - 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, - 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, - 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, - 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, - 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, - 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, - 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a - ], - [ - 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, - 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, - 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, - 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, - 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, - 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, - 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, - 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, - 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, - 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, - 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, - 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, - 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, - 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, - 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, - 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, - 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, - 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, - 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, - 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, - 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, - 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, - 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, - 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, - 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, - 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, - 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, - 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, - 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, - 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, - 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, - 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, - 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, - 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, - 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, - 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, - 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, - 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, - 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, - 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, - 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, - 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, - 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7 - ], - [ - 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, - 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, - 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, - 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, - 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, - 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, - 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, - 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, - 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, - 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, - 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, - 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, - 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, - 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, - 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, - 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, - 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, - 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, - 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74, - 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, - 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, - 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, - 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, - 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, - 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, - 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, - 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, - 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, - 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, - 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, - 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, - 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, - 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, - 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, - 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, - 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, - 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, - 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, - 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, - 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, - 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, - 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, - 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0 - ], - [ - 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, - 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, - 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, - 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, - 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, - 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, - 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, - 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, - 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, - 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, - 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, - 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, - 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, - 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, - 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5, - 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, - 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, - 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, - 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd, - 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, - 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, - 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, - 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc, - 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, - 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, - 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, - 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, - 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, - 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, - 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, - 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, - 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, - 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, - 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, - 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623, - 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, - 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, - 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, - 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3, - 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, - 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, - 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, - 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 - ] - ]; - - //* - //* This is the default PARRAY - //* - Blowfish.prototype.PARRAY = [ - 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, - 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, - 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b - ]; - - //* - //* This is the number of rounds the cipher will go - //* - Blowfish.prototype.NN = 16; - - //* - //* This function is needed to get rid of problems - //* with the high-bit getting set. If we don't do - //* this, then sometimes ( aa & 0x00FFFFFFFF ) is not - //* equal to ( bb & 0x00FFFFFFFF ) even when they - //* agree bit-for-bit for the first 32 bits. - //* - Blowfish.prototype._clean = function(xx) { - if (xx < 0) { - const yy = xx & 0x7FFFFFFF; - xx = yy + 0x80000000; - } - return xx; - }; - - //* - //* This is the mixing function that uses the sboxes - //* - Blowfish.prototype._F = function(xx) { - let yy; - - const dd = xx & 0x00FF; - xx >>>= 8; - const cc = xx & 0x00FF; - xx >>>= 8; - const bb = xx & 0x00FF; - xx >>>= 8; - const aa = xx & 0x00FF; - - yy = this.sboxes[0][aa] + this.sboxes[1][bb]; - yy ^= this.sboxes[2][cc]; - yy += this.sboxes[3][dd]; - - return yy; - }; - - //* - //* This method takes an array with two values, left and right - //* and does NN rounds of Blowfish on them. - //* - Blowfish.prototype._encryptBlock = function(vals) { - let dataL = vals[0]; - let dataR = vals[1]; - - let ii; - - for (ii = 0; ii < this.NN; ++ii) { - dataL ^= this.parray[ii]; - dataR = this._F(dataL) ^ dataR; - - const tmp = dataL; - dataL = dataR; - dataR = tmp; - } - - dataL ^= this.parray[this.NN + 0]; - dataR ^= this.parray[this.NN + 1]; - - vals[0] = this._clean(dataR); - vals[1] = this._clean(dataL); - }; - - //* - //* This method takes a vector of numbers and turns them - //* into long words so that they can be processed by the - //* real algorithm. - //* - //* Maybe I should make the real algorithm above take a vector - //* instead. That will involve more looping, but it won't require - //* the F() method to deconstruct the vector. - //* - Blowfish.prototype.encryptBlock = function(vector) { - let ii; - const vals = [0, 0]; - const off = this.BLOCKSIZE / 2; - for (ii = 0; ii < this.BLOCKSIZE / 2; ++ii) { - vals[0] = (vals[0] << 8) | (vector[ii + 0] & 0x00FF); - vals[1] = (vals[1] << 8) | (vector[ii + off] & 0x00FF); - } - - this._encryptBlock(vals); - - const ret = []; - for (ii = 0; ii < this.BLOCKSIZE / 2; ++ii) { - ret[ii + 0] = ((vals[0] >>> (24 - 8 * (ii))) & 0x00FF); - ret[ii + off] = ((vals[1] >>> (24 - 8 * (ii))) & 0x00FF); - // vals[ 0 ] = ( vals[ 0 ] >>> 8 ); - // vals[ 1 ] = ( vals[ 1 ] >>> 8 ); - } - - return ret; - }; - - //* - //* This method takes an array with two values, left and right - //* and undoes NN rounds of Blowfish on them. - //* - Blowfish.prototype._decryptBlock = function(vals) { - let dataL = vals[0]; - let dataR = vals[1]; - - let ii; - - for (ii = this.NN + 1; ii > 1; --ii) { - dataL ^= this.parray[ii]; - dataR = this._F(dataL) ^ dataR; - - const tmp = dataL; - dataL = dataR; - dataR = tmp; - } - - dataL ^= this.parray[1]; - dataR ^= this.parray[0]; - - vals[0] = this._clean(dataR); - vals[1] = this._clean(dataL); - }; - - //* - //* This method takes a key array and initializes the - //* sboxes and parray for this encryption. - //* - Blowfish.prototype.init = function(key) { - let ii; - let jj = 0; - - this.parray = []; - for (ii = 0; ii < this.NN + 2; ++ii) { - let data = 0x00000000; - for (let kk = 0; kk < 4; ++kk) { - data = (data << 8) | (key[jj] & 0x00FF); - if (++jj >= key.length) { - jj = 0; - } - } - this.parray[ii] = this.PARRAY[ii] ^ data; - } - - this.sboxes = []; - for (ii = 0; ii < 4; ++ii) { - this.sboxes[ii] = []; - for (jj = 0; jj < 256; ++jj) { - this.sboxes[ii][jj] = this.SBOXES[ii][jj]; - } - } - - const vals = [0x00000000, 0x00000000]; - - for (ii = 0; ii < this.NN + 2; ii += 2) { - this._encryptBlock(vals); - this.parray[ii + 0] = vals[0]; - this.parray[ii + 1] = vals[1]; - } - - for (ii = 0; ii < 4; ++ii) { - for (jj = 0; jj < 256; jj += 2) { - this._encryptBlock(vals); - this.sboxes[ii][jj + 0] = vals[0]; - this.sboxes[ii][jj + 1] = vals[1]; - } - } - }; - - // added by Recurity Labs - function BF(key) { - this.bf = new Blowfish(); - this.bf.init(key); - - this.encrypt = function(block) { - return this.bf.encryptBlock(block); - }; - } - - BF.keySize = BF.prototype.keySize = 16; - BF.blockSize = BF.prototype.blockSize = 8; - - /** - * @fileoverview Symmetric cryptography functions - * @module crypto/cipher - * @private - */ - - /** - * AES-128 encryption and decryption (ID 7) - * @function - * @param {String} key - 128-bit key - * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} - * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} - * @returns {Object} - */ - const aes128 = aes(128); - /** - * AES-128 Block Cipher (ID 8) - * @function - * @param {String} key - 192-bit key - * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} - * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} - * @returns {Object} - */ - const aes192 = aes(192); - /** - * AES-128 Block Cipher (ID 9) - * @function - * @param {String} key - 256-bit key - * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} - * @see {@link https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf|NIST FIPS-197} - * @returns {Object} - */ - const aes256 = aes(256); - // Not in OpenPGP specifications - const des$1 = DES; - /** - * Triple DES Block Cipher (ID 2) - * @function - * @param {String} key - 192-bit key - * @see {@link https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-67r2.pdf|NIST SP 800-67} - * @returns {Object} - */ - const tripledes = TripleDES; - /** - * CAST-128 Block Cipher (ID 3) - * @function - * @param {String} key - 128-bit key - * @see {@link https://tools.ietf.org/html/rfc2144|The CAST-128 Encryption Algorithm} - * @returns {Object} - */ - const cast5 = CAST5; - /** - * Twofish Block Cipher (ID 10) - * @function - * @param {String} key - 256-bit key - * @see {@link https://tools.ietf.org/html/rfc4880#ref-TWOFISH|TWOFISH} - * @returns {Object} - */ - const twofish = TF; - /** - * Blowfish Block Cipher (ID 4) - * @function - * @param {String} key - 128-bit key - * @see {@link https://tools.ietf.org/html/rfc4880#ref-BLOWFISH|BLOWFISH} - * @returns {Object} - */ - const blowfish = BF; - /** - * Not implemented - * @function - * @throws {Error} - */ - const idea = function() { - throw new Error('IDEA symmetric-key algorithm not implemented'); - }; - - var cipher = /*#__PURE__*/Object.freeze({ - __proto__: null, - aes128: aes128, - aes192: aes192, - aes256: aes256, - des: des$1, - tripledes: tripledes, - cast5: cast5, - twofish: twofish, - blowfish: blowfish, - idea: idea - }); - - var sha1_asm = function ( stdlib, foreign, buffer ) { - "use asm"; - - // SHA256 state - var H0 = 0, H1 = 0, H2 = 0, H3 = 0, H4 = 0, - TOTAL0 = 0, TOTAL1 = 0; - - // HMAC state - var I0 = 0, I1 = 0, I2 = 0, I3 = 0, I4 = 0, - O0 = 0, O1 = 0, O2 = 0, O3 = 0, O4 = 0; - - // I/O buffer - var HEAP = new stdlib.Uint8Array(buffer); - - function _core ( w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15 ) { - w0 = w0|0; - w1 = w1|0; - w2 = w2|0; - w3 = w3|0; - w4 = w4|0; - w5 = w5|0; - w6 = w6|0; - w7 = w7|0; - w8 = w8|0; - w9 = w9|0; - w10 = w10|0; - w11 = w11|0; - w12 = w12|0; - w13 = w13|0; - w14 = w14|0; - w15 = w15|0; - - var a = 0, b = 0, c = 0, d = 0, e = 0, n = 0, t = 0, - w16 = 0, w17 = 0, w18 = 0, w19 = 0, - w20 = 0, w21 = 0, w22 = 0, w23 = 0, w24 = 0, w25 = 0, w26 = 0, w27 = 0, w28 = 0, w29 = 0, - w30 = 0, w31 = 0, w32 = 0, w33 = 0, w34 = 0, w35 = 0, w36 = 0, w37 = 0, w38 = 0, w39 = 0, - w40 = 0, w41 = 0, w42 = 0, w43 = 0, w44 = 0, w45 = 0, w46 = 0, w47 = 0, w48 = 0, w49 = 0, - w50 = 0, w51 = 0, w52 = 0, w53 = 0, w54 = 0, w55 = 0, w56 = 0, w57 = 0, w58 = 0, w59 = 0, - w60 = 0, w61 = 0, w62 = 0, w63 = 0, w64 = 0, w65 = 0, w66 = 0, w67 = 0, w68 = 0, w69 = 0, - w70 = 0, w71 = 0, w72 = 0, w73 = 0, w74 = 0, w75 = 0, w76 = 0, w77 = 0, w78 = 0, w79 = 0; - - a = H0; - b = H1; - c = H2; - d = H3; - e = H4; - - // 0 - t = ( w0 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 1 - t = ( w1 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 2 - t = ( w2 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 3 - t = ( w3 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 4 - t = ( w4 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 5 - t = ( w5 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 6 - t = ( w6 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 7 - t = ( w7 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 8 - t = ( w8 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 9 - t = ( w9 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 10 - t = ( w10 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 11 - t = ( w11 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 12 - t = ( w12 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 13 - t = ( w13 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 14 - t = ( w14 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 15 - t = ( w15 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 16 - n = w13 ^ w8 ^ w2 ^ w0; - w16 = (n << 1) | (n >>> 31); - t = (w16 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 17 - n = w14 ^ w9 ^ w3 ^ w1; - w17 = (n << 1) | (n >>> 31); - t = (w17 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 18 - n = w15 ^ w10 ^ w4 ^ w2; - w18 = (n << 1) | (n >>> 31); - t = (w18 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 19 - n = w16 ^ w11 ^ w5 ^ w3; - w19 = (n << 1) | (n >>> 31); - t = (w19 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 20 - n = w17 ^ w12 ^ w6 ^ w4; - w20 = (n << 1) | (n >>> 31); - t = (w20 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 21 - n = w18 ^ w13 ^ w7 ^ w5; - w21 = (n << 1) | (n >>> 31); - t = (w21 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 22 - n = w19 ^ w14 ^ w8 ^ w6; - w22 = (n << 1) | (n >>> 31); - t = (w22 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 23 - n = w20 ^ w15 ^ w9 ^ w7; - w23 = (n << 1) | (n >>> 31); - t = (w23 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 24 - n = w21 ^ w16 ^ w10 ^ w8; - w24 = (n << 1) | (n >>> 31); - t = (w24 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 25 - n = w22 ^ w17 ^ w11 ^ w9; - w25 = (n << 1) | (n >>> 31); - t = (w25 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 26 - n = w23 ^ w18 ^ w12 ^ w10; - w26 = (n << 1) | (n >>> 31); - t = (w26 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 27 - n = w24 ^ w19 ^ w13 ^ w11; - w27 = (n << 1) | (n >>> 31); - t = (w27 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 28 - n = w25 ^ w20 ^ w14 ^ w12; - w28 = (n << 1) | (n >>> 31); - t = (w28 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 29 - n = w26 ^ w21 ^ w15 ^ w13; - w29 = (n << 1) | (n >>> 31); - t = (w29 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 30 - n = w27 ^ w22 ^ w16 ^ w14; - w30 = (n << 1) | (n >>> 31); - t = (w30 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 31 - n = w28 ^ w23 ^ w17 ^ w15; - w31 = (n << 1) | (n >>> 31); - t = (w31 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 32 - n = w29 ^ w24 ^ w18 ^ w16; - w32 = (n << 1) | (n >>> 31); - t = (w32 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 33 - n = w30 ^ w25 ^ w19 ^ w17; - w33 = (n << 1) | (n >>> 31); - t = (w33 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 34 - n = w31 ^ w26 ^ w20 ^ w18; - w34 = (n << 1) | (n >>> 31); - t = (w34 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 35 - n = w32 ^ w27 ^ w21 ^ w19; - w35 = (n << 1) | (n >>> 31); - t = (w35 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 36 - n = w33 ^ w28 ^ w22 ^ w20; - w36 = (n << 1) | (n >>> 31); - t = (w36 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 37 - n = w34 ^ w29 ^ w23 ^ w21; - w37 = (n << 1) | (n >>> 31); - t = (w37 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 38 - n = w35 ^ w30 ^ w24 ^ w22; - w38 = (n << 1) | (n >>> 31); - t = (w38 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 39 - n = w36 ^ w31 ^ w25 ^ w23; - w39 = (n << 1) | (n >>> 31); - t = (w39 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 40 - n = w37 ^ w32 ^ w26 ^ w24; - w40 = (n << 1) | (n >>> 31); - t = (w40 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 41 - n = w38 ^ w33 ^ w27 ^ w25; - w41 = (n << 1) | (n >>> 31); - t = (w41 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 42 - n = w39 ^ w34 ^ w28 ^ w26; - w42 = (n << 1) | (n >>> 31); - t = (w42 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 43 - n = w40 ^ w35 ^ w29 ^ w27; - w43 = (n << 1) | (n >>> 31); - t = (w43 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 44 - n = w41 ^ w36 ^ w30 ^ w28; - w44 = (n << 1) | (n >>> 31); - t = (w44 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 45 - n = w42 ^ w37 ^ w31 ^ w29; - w45 = (n << 1) | (n >>> 31); - t = (w45 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 46 - n = w43 ^ w38 ^ w32 ^ w30; - w46 = (n << 1) | (n >>> 31); - t = (w46 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 47 - n = w44 ^ w39 ^ w33 ^ w31; - w47 = (n << 1) | (n >>> 31); - t = (w47 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 48 - n = w45 ^ w40 ^ w34 ^ w32; - w48 = (n << 1) | (n >>> 31); - t = (w48 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 49 - n = w46 ^ w41 ^ w35 ^ w33; - w49 = (n << 1) | (n >>> 31); - t = (w49 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 50 - n = w47 ^ w42 ^ w36 ^ w34; - w50 = (n << 1) | (n >>> 31); - t = (w50 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 51 - n = w48 ^ w43 ^ w37 ^ w35; - w51 = (n << 1) | (n >>> 31); - t = (w51 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 52 - n = w49 ^ w44 ^ w38 ^ w36; - w52 = (n << 1) | (n >>> 31); - t = (w52 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 53 - n = w50 ^ w45 ^ w39 ^ w37; - w53 = (n << 1) | (n >>> 31); - t = (w53 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 54 - n = w51 ^ w46 ^ w40 ^ w38; - w54 = (n << 1) | (n >>> 31); - t = (w54 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 55 - n = w52 ^ w47 ^ w41 ^ w39; - w55 = (n << 1) | (n >>> 31); - t = (w55 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 56 - n = w53 ^ w48 ^ w42 ^ w40; - w56 = (n << 1) | (n >>> 31); - t = (w56 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 57 - n = w54 ^ w49 ^ w43 ^ w41; - w57 = (n << 1) | (n >>> 31); - t = (w57 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 58 - n = w55 ^ w50 ^ w44 ^ w42; - w58 = (n << 1) | (n >>> 31); - t = (w58 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 59 - n = w56 ^ w51 ^ w45 ^ w43; - w59 = (n << 1) | (n >>> 31); - t = (w59 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 60 - n = w57 ^ w52 ^ w46 ^ w44; - w60 = (n << 1) | (n >>> 31); - t = (w60 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 61 - n = w58 ^ w53 ^ w47 ^ w45; - w61 = (n << 1) | (n >>> 31); - t = (w61 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 62 - n = w59 ^ w54 ^ w48 ^ w46; - w62 = (n << 1) | (n >>> 31); - t = (w62 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 63 - n = w60 ^ w55 ^ w49 ^ w47; - w63 = (n << 1) | (n >>> 31); - t = (w63 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 64 - n = w61 ^ w56 ^ w50 ^ w48; - w64 = (n << 1) | (n >>> 31); - t = (w64 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 65 - n = w62 ^ w57 ^ w51 ^ w49; - w65 = (n << 1) | (n >>> 31); - t = (w65 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 66 - n = w63 ^ w58 ^ w52 ^ w50; - w66 = (n << 1) | (n >>> 31); - t = (w66 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 67 - n = w64 ^ w59 ^ w53 ^ w51; - w67 = (n << 1) | (n >>> 31); - t = (w67 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 68 - n = w65 ^ w60 ^ w54 ^ w52; - w68 = (n << 1) | (n >>> 31); - t = (w68 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 69 - n = w66 ^ w61 ^ w55 ^ w53; - w69 = (n << 1) | (n >>> 31); - t = (w69 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 70 - n = w67 ^ w62 ^ w56 ^ w54; - w70 = (n << 1) | (n >>> 31); - t = (w70 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 71 - n = w68 ^ w63 ^ w57 ^ w55; - w71 = (n << 1) | (n >>> 31); - t = (w71 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 72 - n = w69 ^ w64 ^ w58 ^ w56; - w72 = (n << 1) | (n >>> 31); - t = (w72 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 73 - n = w70 ^ w65 ^ w59 ^ w57; - w73 = (n << 1) | (n >>> 31); - t = (w73 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 74 - n = w71 ^ w66 ^ w60 ^ w58; - w74 = (n << 1) | (n >>> 31); - t = (w74 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 75 - n = w72 ^ w67 ^ w61 ^ w59; - w75 = (n << 1) | (n >>> 31); - t = (w75 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 76 - n = w73 ^ w68 ^ w62 ^ w60; - w76 = (n << 1) | (n >>> 31); - t = (w76 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 77 - n = w74 ^ w69 ^ w63 ^ w61; - w77 = (n << 1) | (n >>> 31); - t = (w77 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 78 - n = w75 ^ w70 ^ w64 ^ w62; - w78 = (n << 1) | (n >>> 31); - t = (w78 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - // 79 - n = w76 ^ w71 ^ w65 ^ w63; - w79 = (n << 1) | (n >>> 31); - t = (w79 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) - 0x359d3e2a )|0; - e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t; - - H0 = ( H0 + a )|0; - H1 = ( H1 + b )|0; - H2 = ( H2 + c )|0; - H3 = ( H3 + d )|0; - H4 = ( H4 + e )|0; - - } - - function _core_heap ( offset ) { - offset = offset|0; - - _core( - HEAP[offset|0]<<24 | HEAP[offset|1]<<16 | HEAP[offset|2]<<8 | HEAP[offset|3], - HEAP[offset|4]<<24 | HEAP[offset|5]<<16 | HEAP[offset|6]<<8 | HEAP[offset|7], - HEAP[offset|8]<<24 | HEAP[offset|9]<<16 | HEAP[offset|10]<<8 | HEAP[offset|11], - HEAP[offset|12]<<24 | HEAP[offset|13]<<16 | HEAP[offset|14]<<8 | HEAP[offset|15], - HEAP[offset|16]<<24 | HEAP[offset|17]<<16 | HEAP[offset|18]<<8 | HEAP[offset|19], - HEAP[offset|20]<<24 | HEAP[offset|21]<<16 | HEAP[offset|22]<<8 | HEAP[offset|23], - HEAP[offset|24]<<24 | HEAP[offset|25]<<16 | HEAP[offset|26]<<8 | HEAP[offset|27], - HEAP[offset|28]<<24 | HEAP[offset|29]<<16 | HEAP[offset|30]<<8 | HEAP[offset|31], - HEAP[offset|32]<<24 | HEAP[offset|33]<<16 | HEAP[offset|34]<<8 | HEAP[offset|35], - HEAP[offset|36]<<24 | HEAP[offset|37]<<16 | HEAP[offset|38]<<8 | HEAP[offset|39], - HEAP[offset|40]<<24 | HEAP[offset|41]<<16 | HEAP[offset|42]<<8 | HEAP[offset|43], - HEAP[offset|44]<<24 | HEAP[offset|45]<<16 | HEAP[offset|46]<<8 | HEAP[offset|47], - HEAP[offset|48]<<24 | HEAP[offset|49]<<16 | HEAP[offset|50]<<8 | HEAP[offset|51], - HEAP[offset|52]<<24 | HEAP[offset|53]<<16 | HEAP[offset|54]<<8 | HEAP[offset|55], - HEAP[offset|56]<<24 | HEAP[offset|57]<<16 | HEAP[offset|58]<<8 | HEAP[offset|59], - HEAP[offset|60]<<24 | HEAP[offset|61]<<16 | HEAP[offset|62]<<8 | HEAP[offset|63] - ); - } - - // offset — multiple of 32 - function _state_to_heap ( output ) { - output = output|0; - - HEAP[output|0] = H0>>>24; - HEAP[output|1] = H0>>>16&255; - HEAP[output|2] = H0>>>8&255; - HEAP[output|3] = H0&255; - HEAP[output|4] = H1>>>24; - HEAP[output|5] = H1>>>16&255; - HEAP[output|6] = H1>>>8&255; - HEAP[output|7] = H1&255; - HEAP[output|8] = H2>>>24; - HEAP[output|9] = H2>>>16&255; - HEAP[output|10] = H2>>>8&255; - HEAP[output|11] = H2&255; - HEAP[output|12] = H3>>>24; - HEAP[output|13] = H3>>>16&255; - HEAP[output|14] = H3>>>8&255; - HEAP[output|15] = H3&255; - HEAP[output|16] = H4>>>24; - HEAP[output|17] = H4>>>16&255; - HEAP[output|18] = H4>>>8&255; - HEAP[output|19] = H4&255; - } - - function reset () { - H0 = 0x67452301; - H1 = 0xefcdab89; - H2 = 0x98badcfe; - H3 = 0x10325476; - H4 = 0xc3d2e1f0; - TOTAL0 = TOTAL1 = 0; - } - - function init ( h0, h1, h2, h3, h4, total0, total1 ) { - h0 = h0|0; - h1 = h1|0; - h2 = h2|0; - h3 = h3|0; - h4 = h4|0; - total0 = total0|0; - total1 = total1|0; - - H0 = h0; - H1 = h1; - H2 = h2; - H3 = h3; - H4 = h4; - TOTAL0 = total0; - TOTAL1 = total1; - } - - // offset — multiple of 64 - function process ( offset, length ) { - offset = offset|0; - length = length|0; - - var hashed = 0; - - if ( offset & 63 ) - return -1; - - while ( (length|0) >= 64 ) { - _core_heap(offset); - - offset = ( offset + 64 )|0; - length = ( length - 64 )|0; - - hashed = ( hashed + 64 )|0; - } - - TOTAL0 = ( TOTAL0 + hashed )|0; - if ( TOTAL0>>>0 < hashed>>>0 ) TOTAL1 = ( TOTAL1 + 1 )|0; - - return hashed|0; - } - - // offset — multiple of 64 - // output — multiple of 32 - function finish ( offset, length, output ) { - offset = offset|0; - length = length|0; - output = output|0; - - var hashed = 0, - i = 0; - - if ( offset & 63 ) - return -1; - - if ( ~output ) - if ( output & 31 ) - return -1; - - if ( (length|0) >= 64 ) { - hashed = process( offset, length )|0; - if ( (hashed|0) == -1 ) - return -1; - - offset = ( offset + hashed )|0; - length = ( length - hashed )|0; - } - - hashed = ( hashed + length )|0; - TOTAL0 = ( TOTAL0 + length )|0; - if ( TOTAL0>>>0 < length>>>0 ) TOTAL1 = (TOTAL1 + 1)|0; - - HEAP[offset|length] = 0x80; - - if ( (length|0) >= 56 ) { - for ( i = (length+1)|0; (i|0) < 64; i = (i+1)|0 ) - HEAP[offset|i] = 0x00; - _core_heap(offset); - - length = 0; - - HEAP[offset|0] = 0; - } - - for ( i = (length+1)|0; (i|0) < 59; i = (i+1)|0 ) - HEAP[offset|i] = 0; - - HEAP[offset|56] = TOTAL1>>>21&255; - HEAP[offset|57] = TOTAL1>>>13&255; - HEAP[offset|58] = TOTAL1>>>5&255; - HEAP[offset|59] = TOTAL1<<3&255 | TOTAL0>>>29; - HEAP[offset|60] = TOTAL0>>>21&255; - HEAP[offset|61] = TOTAL0>>>13&255; - HEAP[offset|62] = TOTAL0>>>5&255; - HEAP[offset|63] = TOTAL0<<3&255; - _core_heap(offset); - - if ( ~output ) - _state_to_heap(output); - - return hashed|0; - } - - function hmac_reset () { - H0 = I0; - H1 = I1; - H2 = I2; - H3 = I3; - H4 = I4; - TOTAL0 = 64; - TOTAL1 = 0; - } - - function _hmac_opad () { - H0 = O0; - H1 = O1; - H2 = O2; - H3 = O3; - H4 = O4; - TOTAL0 = 64; - TOTAL1 = 0; - } - - function hmac_init ( p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15 ) { - p0 = p0|0; - p1 = p1|0; - p2 = p2|0; - p3 = p3|0; - p4 = p4|0; - p5 = p5|0; - p6 = p6|0; - p7 = p7|0; - p8 = p8|0; - p9 = p9|0; - p10 = p10|0; - p11 = p11|0; - p12 = p12|0; - p13 = p13|0; - p14 = p14|0; - p15 = p15|0; - - // opad - reset(); - _core( - p0 ^ 0x5c5c5c5c, - p1 ^ 0x5c5c5c5c, - p2 ^ 0x5c5c5c5c, - p3 ^ 0x5c5c5c5c, - p4 ^ 0x5c5c5c5c, - p5 ^ 0x5c5c5c5c, - p6 ^ 0x5c5c5c5c, - p7 ^ 0x5c5c5c5c, - p8 ^ 0x5c5c5c5c, - p9 ^ 0x5c5c5c5c, - p10 ^ 0x5c5c5c5c, - p11 ^ 0x5c5c5c5c, - p12 ^ 0x5c5c5c5c, - p13 ^ 0x5c5c5c5c, - p14 ^ 0x5c5c5c5c, - p15 ^ 0x5c5c5c5c - ); - O0 = H0; - O1 = H1; - O2 = H2; - O3 = H3; - O4 = H4; - - // ipad - reset(); - _core( - p0 ^ 0x36363636, - p1 ^ 0x36363636, - p2 ^ 0x36363636, - p3 ^ 0x36363636, - p4 ^ 0x36363636, - p5 ^ 0x36363636, - p6 ^ 0x36363636, - p7 ^ 0x36363636, - p8 ^ 0x36363636, - p9 ^ 0x36363636, - p10 ^ 0x36363636, - p11 ^ 0x36363636, - p12 ^ 0x36363636, - p13 ^ 0x36363636, - p14 ^ 0x36363636, - p15 ^ 0x36363636 - ); - I0 = H0; - I1 = H1; - I2 = H2; - I3 = H3; - I4 = H4; - - TOTAL0 = 64; - TOTAL1 = 0; - } - - // offset — multiple of 64 - // output — multiple of 32 - function hmac_finish ( offset, length, output ) { - offset = offset|0; - length = length|0; - output = output|0; - - var t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, hashed = 0; - - if ( offset & 63 ) - return -1; - - if ( ~output ) - if ( output & 31 ) - return -1; - - hashed = finish( offset, length, -1 )|0; - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; - - _hmac_opad(); - _core( t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672 ); - - if ( ~output ) - _state_to_heap(output); - - return hashed|0; - } - - // salt is assumed to be already processed - // offset — multiple of 64 - // output — multiple of 32 - function pbkdf2_generate_block ( offset, length, block, count, output ) { - offset = offset|0; - length = length|0; - block = block|0; - count = count|0; - output = output|0; - - var h0 = 0, h1 = 0, h2 = 0, h3 = 0, h4 = 0, - t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0; - - if ( offset & 63 ) - return -1; - - if ( ~output ) - if ( output & 31 ) - return -1; - - // pad block number into heap - // FIXME probable OOB write - HEAP[(offset+length)|0] = block>>>24; - HEAP[(offset+length+1)|0] = block>>>16&255; - HEAP[(offset+length+2)|0] = block>>>8&255; - HEAP[(offset+length+3)|0] = block&255; - - // finish first iteration - hmac_finish( offset, (length+4)|0, -1 )|0; - h0 = t0 = H0, h1 = t1 = H1, h2 = t2 = H2, h3 = t3 = H3, h4 = t4 = H4; - count = (count-1)|0; - - // perform the rest iterations - while ( (count|0) > 0 ) { - hmac_reset(); - _core( t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672 ); - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; - - _hmac_opad(); - _core( t0, t1, t2, t3, t4, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672 ); - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4; - - h0 = h0 ^ H0; - h1 = h1 ^ H1; - h2 = h2 ^ H2; - h3 = h3 ^ H3; - h4 = h4 ^ H4; - - count = (count-1)|0; - } - - H0 = h0; - H1 = h1; - H2 = h2; - H3 = h3; - H4 = h4; - - if ( ~output ) - _state_to_heap(output); - - return 0; - } - - return { - // SHA1 - reset: reset, - init: init, - process: process, - finish: finish, - - // HMAC-SHA1 - hmac_reset: hmac_reset, - hmac_init: hmac_init, - hmac_finish: hmac_finish, - - // PBKDF2-HMAC-SHA1 - pbkdf2_generate_block: pbkdf2_generate_block - } - }; - - class Hash { - constructor() { - this.pos = 0; - this.len = 0; - } - reset() { - const { asm } = this.acquire_asm(); - this.result = null; - this.pos = 0; - this.len = 0; - asm.reset(); - return this; - } - process(data) { - if (this.result !== null) - throw new IllegalStateError('state must be reset before processing new data'); - const { asm, heap } = this.acquire_asm(); - let hpos = this.pos; - let hlen = this.len; - let dpos = 0; - let dlen = data.length; - let wlen = 0; - while (dlen > 0) { - wlen = _heap_write(heap, hpos + hlen, data, dpos, dlen); - hlen += wlen; - dpos += wlen; - dlen -= wlen; - wlen = asm.process(hpos, hlen); - hpos += wlen; - hlen -= wlen; - if (!hlen) - hpos = 0; - } - this.pos = hpos; - this.len = hlen; - return this; - } - finish() { - if (this.result !== null) - throw new IllegalStateError('state must be reset before processing new data'); - const { asm, heap } = this.acquire_asm(); - asm.finish(this.pos, this.len, 0); - this.result = new Uint8Array(this.HASH_SIZE); - this.result.set(heap.subarray(0, this.HASH_SIZE)); - this.pos = 0; - this.len = 0; - this.release_asm(); - return this; - } - } - - const _sha1_block_size = 64; - const _sha1_hash_size = 20; - const heap_pool$1 = []; - const asm_pool$1 = []; - class Sha1 extends Hash { - constructor() { - super(); - this.NAME = 'sha1'; - this.BLOCK_SIZE = _sha1_block_size; - this.HASH_SIZE = _sha1_hash_size; - this.acquire_asm(); - } - acquire_asm() { - if (this.heap === undefined || this.asm === undefined) { - this.heap = heap_pool$1.pop() || _heap_init(); - this.asm = asm_pool$1.pop() || sha1_asm({ Uint8Array: Uint8Array }, null, this.heap.buffer); - this.reset(); - } - return { heap: this.heap, asm: this.asm }; - } - release_asm() { - if (this.heap !== undefined && this.asm !== undefined) { - heap_pool$1.push(this.heap); - asm_pool$1.push(this.asm); - } - this.heap = undefined; - this.asm = undefined; - } - static bytes(data) { - return new Sha1().process(data).finish().result; - } - } - Sha1.NAME = 'sha1'; - Sha1.heap_pool = []; - Sha1.asm_pool = []; - Sha1.asm_function = sha1_asm; - - var sha256_asm = function ( stdlib, foreign, buffer ) { - "use asm"; - - // SHA256 state - var H0 = 0, H1 = 0, H2 = 0, H3 = 0, H4 = 0, H5 = 0, H6 = 0, H7 = 0, - TOTAL0 = 0, TOTAL1 = 0; - - // HMAC state - var I0 = 0, I1 = 0, I2 = 0, I3 = 0, I4 = 0, I5 = 0, I6 = 0, I7 = 0, - O0 = 0, O1 = 0, O2 = 0, O3 = 0, O4 = 0, O5 = 0, O6 = 0, O7 = 0; - - // I/O buffer - var HEAP = new stdlib.Uint8Array(buffer); - - function _core ( w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15 ) { - w0 = w0|0; - w1 = w1|0; - w2 = w2|0; - w3 = w3|0; - w4 = w4|0; - w5 = w5|0; - w6 = w6|0; - w7 = w7|0; - w8 = w8|0; - w9 = w9|0; - w10 = w10|0; - w11 = w11|0; - w12 = w12|0; - w13 = w13|0; - w14 = w14|0; - w15 = w15|0; - - var a = 0, b = 0, c = 0, d = 0, e = 0, f = 0, g = 0, h = 0; - - a = H0; - b = H1; - c = H2; - d = H3; - e = H4; - f = H5; - g = H6; - h = H7; - - // 0 - h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x428a2f98 )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 1 - g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x71374491 )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 2 - f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0xb5c0fbcf )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 3 - e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0xe9b5dba5 )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 4 - d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x3956c25b )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 5 - c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x59f111f1 )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 6 - b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x923f82a4 )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 7 - a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0xab1c5ed5 )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - // 8 - h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0xd807aa98 )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 9 - g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x12835b01 )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 10 - f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x243185be )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 11 - e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x550c7dc3 )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 12 - d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x72be5d74 )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 13 - c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x80deb1fe )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 14 - b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x9bdc06a7 )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 15 - a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0xc19bf174 )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - // 16 - w0 = ( ( w1>>>7 ^ w1>>>18 ^ w1>>>3 ^ w1<<25 ^ w1<<14 ) + ( w14>>>17 ^ w14>>>19 ^ w14>>>10 ^ w14<<15 ^ w14<<13 ) + w0 + w9 )|0; - h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0xe49b69c1 )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 17 - w1 = ( ( w2>>>7 ^ w2>>>18 ^ w2>>>3 ^ w2<<25 ^ w2<<14 ) + ( w15>>>17 ^ w15>>>19 ^ w15>>>10 ^ w15<<15 ^ w15<<13 ) + w1 + w10 )|0; - g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0xefbe4786 )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 18 - w2 = ( ( w3>>>7 ^ w3>>>18 ^ w3>>>3 ^ w3<<25 ^ w3<<14 ) + ( w0>>>17 ^ w0>>>19 ^ w0>>>10 ^ w0<<15 ^ w0<<13 ) + w2 + w11 )|0; - f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x0fc19dc6 )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 19 - w3 = ( ( w4>>>7 ^ w4>>>18 ^ w4>>>3 ^ w4<<25 ^ w4<<14 ) + ( w1>>>17 ^ w1>>>19 ^ w1>>>10 ^ w1<<15 ^ w1<<13 ) + w3 + w12 )|0; - e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x240ca1cc )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 20 - w4 = ( ( w5>>>7 ^ w5>>>18 ^ w5>>>3 ^ w5<<25 ^ w5<<14 ) + ( w2>>>17 ^ w2>>>19 ^ w2>>>10 ^ w2<<15 ^ w2<<13 ) + w4 + w13 )|0; - d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x2de92c6f )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 21 - w5 = ( ( w6>>>7 ^ w6>>>18 ^ w6>>>3 ^ w6<<25 ^ w6<<14 ) + ( w3>>>17 ^ w3>>>19 ^ w3>>>10 ^ w3<<15 ^ w3<<13 ) + w5 + w14 )|0; - c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x4a7484aa )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 22 - w6 = ( ( w7>>>7 ^ w7>>>18 ^ w7>>>3 ^ w7<<25 ^ w7<<14 ) + ( w4>>>17 ^ w4>>>19 ^ w4>>>10 ^ w4<<15 ^ w4<<13 ) + w6 + w15 )|0; - b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x5cb0a9dc )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 23 - w7 = ( ( w8>>>7 ^ w8>>>18 ^ w8>>>3 ^ w8<<25 ^ w8<<14 ) + ( w5>>>17 ^ w5>>>19 ^ w5>>>10 ^ w5<<15 ^ w5<<13 ) + w7 + w0 )|0; - a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x76f988da )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - // 24 - w8 = ( ( w9>>>7 ^ w9>>>18 ^ w9>>>3 ^ w9<<25 ^ w9<<14 ) + ( w6>>>17 ^ w6>>>19 ^ w6>>>10 ^ w6<<15 ^ w6<<13 ) + w8 + w1 )|0; - h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x983e5152 )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 25 - w9 = ( ( w10>>>7 ^ w10>>>18 ^ w10>>>3 ^ w10<<25 ^ w10<<14 ) + ( w7>>>17 ^ w7>>>19 ^ w7>>>10 ^ w7<<15 ^ w7<<13 ) + w9 + w2 )|0; - g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0xa831c66d )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 26 - w10 = ( ( w11>>>7 ^ w11>>>18 ^ w11>>>3 ^ w11<<25 ^ w11<<14 ) + ( w8>>>17 ^ w8>>>19 ^ w8>>>10 ^ w8<<15 ^ w8<<13 ) + w10 + w3 )|0; - f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0xb00327c8 )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 27 - w11 = ( ( w12>>>7 ^ w12>>>18 ^ w12>>>3 ^ w12<<25 ^ w12<<14 ) + ( w9>>>17 ^ w9>>>19 ^ w9>>>10 ^ w9<<15 ^ w9<<13 ) + w11 + w4 )|0; - e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0xbf597fc7 )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 28 - w12 = ( ( w13>>>7 ^ w13>>>18 ^ w13>>>3 ^ w13<<25 ^ w13<<14 ) + ( w10>>>17 ^ w10>>>19 ^ w10>>>10 ^ w10<<15 ^ w10<<13 ) + w12 + w5 )|0; - d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0xc6e00bf3 )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 29 - w13 = ( ( w14>>>7 ^ w14>>>18 ^ w14>>>3 ^ w14<<25 ^ w14<<14 ) + ( w11>>>17 ^ w11>>>19 ^ w11>>>10 ^ w11<<15 ^ w11<<13 ) + w13 + w6 )|0; - c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0xd5a79147 )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 30 - w14 = ( ( w15>>>7 ^ w15>>>18 ^ w15>>>3 ^ w15<<25 ^ w15<<14 ) + ( w12>>>17 ^ w12>>>19 ^ w12>>>10 ^ w12<<15 ^ w12<<13 ) + w14 + w7 )|0; - b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x06ca6351 )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 31 - w15 = ( ( w0>>>7 ^ w0>>>18 ^ w0>>>3 ^ w0<<25 ^ w0<<14 ) + ( w13>>>17 ^ w13>>>19 ^ w13>>>10 ^ w13<<15 ^ w13<<13 ) + w15 + w8 )|0; - a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x14292967 )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - // 32 - w0 = ( ( w1>>>7 ^ w1>>>18 ^ w1>>>3 ^ w1<<25 ^ w1<<14 ) + ( w14>>>17 ^ w14>>>19 ^ w14>>>10 ^ w14<<15 ^ w14<<13 ) + w0 + w9 )|0; - h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x27b70a85 )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 33 - w1 = ( ( w2>>>7 ^ w2>>>18 ^ w2>>>3 ^ w2<<25 ^ w2<<14 ) + ( w15>>>17 ^ w15>>>19 ^ w15>>>10 ^ w15<<15 ^ w15<<13 ) + w1 + w10 )|0; - g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x2e1b2138 )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 34 - w2 = ( ( w3>>>7 ^ w3>>>18 ^ w3>>>3 ^ w3<<25 ^ w3<<14 ) + ( w0>>>17 ^ w0>>>19 ^ w0>>>10 ^ w0<<15 ^ w0<<13 ) + w2 + w11 )|0; - f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x4d2c6dfc )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 35 - w3 = ( ( w4>>>7 ^ w4>>>18 ^ w4>>>3 ^ w4<<25 ^ w4<<14 ) + ( w1>>>17 ^ w1>>>19 ^ w1>>>10 ^ w1<<15 ^ w1<<13 ) + w3 + w12 )|0; - e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x53380d13 )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 36 - w4 = ( ( w5>>>7 ^ w5>>>18 ^ w5>>>3 ^ w5<<25 ^ w5<<14 ) + ( w2>>>17 ^ w2>>>19 ^ w2>>>10 ^ w2<<15 ^ w2<<13 ) + w4 + w13 )|0; - d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x650a7354 )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 37 - w5 = ( ( w6>>>7 ^ w6>>>18 ^ w6>>>3 ^ w6<<25 ^ w6<<14 ) + ( w3>>>17 ^ w3>>>19 ^ w3>>>10 ^ w3<<15 ^ w3<<13 ) + w5 + w14 )|0; - c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x766a0abb )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 38 - w6 = ( ( w7>>>7 ^ w7>>>18 ^ w7>>>3 ^ w7<<25 ^ w7<<14 ) + ( w4>>>17 ^ w4>>>19 ^ w4>>>10 ^ w4<<15 ^ w4<<13 ) + w6 + w15 )|0; - b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x81c2c92e )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 39 - w7 = ( ( w8>>>7 ^ w8>>>18 ^ w8>>>3 ^ w8<<25 ^ w8<<14 ) + ( w5>>>17 ^ w5>>>19 ^ w5>>>10 ^ w5<<15 ^ w5<<13 ) + w7 + w0 )|0; - a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x92722c85 )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - // 40 - w8 = ( ( w9>>>7 ^ w9>>>18 ^ w9>>>3 ^ w9<<25 ^ w9<<14 ) + ( w6>>>17 ^ w6>>>19 ^ w6>>>10 ^ w6<<15 ^ w6<<13 ) + w8 + w1 )|0; - h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0xa2bfe8a1 )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 41 - w9 = ( ( w10>>>7 ^ w10>>>18 ^ w10>>>3 ^ w10<<25 ^ w10<<14 ) + ( w7>>>17 ^ w7>>>19 ^ w7>>>10 ^ w7<<15 ^ w7<<13 ) + w9 + w2 )|0; - g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0xa81a664b )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 42 - w10 = ( ( w11>>>7 ^ w11>>>18 ^ w11>>>3 ^ w11<<25 ^ w11<<14 ) + ( w8>>>17 ^ w8>>>19 ^ w8>>>10 ^ w8<<15 ^ w8<<13 ) + w10 + w3 )|0; - f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0xc24b8b70 )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 43 - w11 = ( ( w12>>>7 ^ w12>>>18 ^ w12>>>3 ^ w12<<25 ^ w12<<14 ) + ( w9>>>17 ^ w9>>>19 ^ w9>>>10 ^ w9<<15 ^ w9<<13 ) + w11 + w4 )|0; - e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0xc76c51a3 )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 44 - w12 = ( ( w13>>>7 ^ w13>>>18 ^ w13>>>3 ^ w13<<25 ^ w13<<14 ) + ( w10>>>17 ^ w10>>>19 ^ w10>>>10 ^ w10<<15 ^ w10<<13 ) + w12 + w5 )|0; - d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0xd192e819 )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 45 - w13 = ( ( w14>>>7 ^ w14>>>18 ^ w14>>>3 ^ w14<<25 ^ w14<<14 ) + ( w11>>>17 ^ w11>>>19 ^ w11>>>10 ^ w11<<15 ^ w11<<13 ) + w13 + w6 )|0; - c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0xd6990624 )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 46 - w14 = ( ( w15>>>7 ^ w15>>>18 ^ w15>>>3 ^ w15<<25 ^ w15<<14 ) + ( w12>>>17 ^ w12>>>19 ^ w12>>>10 ^ w12<<15 ^ w12<<13 ) + w14 + w7 )|0; - b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0xf40e3585 )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 47 - w15 = ( ( w0>>>7 ^ w0>>>18 ^ w0>>>3 ^ w0<<25 ^ w0<<14 ) + ( w13>>>17 ^ w13>>>19 ^ w13>>>10 ^ w13<<15 ^ w13<<13 ) + w15 + w8 )|0; - a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x106aa070 )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - // 48 - w0 = ( ( w1>>>7 ^ w1>>>18 ^ w1>>>3 ^ w1<<25 ^ w1<<14 ) + ( w14>>>17 ^ w14>>>19 ^ w14>>>10 ^ w14<<15 ^ w14<<13 ) + w0 + w9 )|0; - h = ( w0 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x19a4c116 )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 49 - w1 = ( ( w2>>>7 ^ w2>>>18 ^ w2>>>3 ^ w2<<25 ^ w2<<14 ) + ( w15>>>17 ^ w15>>>19 ^ w15>>>10 ^ w15<<15 ^ w15<<13 ) + w1 + w10 )|0; - g = ( w1 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x1e376c08 )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 50 - w2 = ( ( w3>>>7 ^ w3>>>18 ^ w3>>>3 ^ w3<<25 ^ w3<<14 ) + ( w0>>>17 ^ w0>>>19 ^ w0>>>10 ^ w0<<15 ^ w0<<13 ) + w2 + w11 )|0; - f = ( w2 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x2748774c )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 51 - w3 = ( ( w4>>>7 ^ w4>>>18 ^ w4>>>3 ^ w4<<25 ^ w4<<14 ) + ( w1>>>17 ^ w1>>>19 ^ w1>>>10 ^ w1<<15 ^ w1<<13 ) + w3 + w12 )|0; - e = ( w3 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x34b0bcb5 )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 52 - w4 = ( ( w5>>>7 ^ w5>>>18 ^ w5>>>3 ^ w5<<25 ^ w5<<14 ) + ( w2>>>17 ^ w2>>>19 ^ w2>>>10 ^ w2<<15 ^ w2<<13 ) + w4 + w13 )|0; - d = ( w4 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x391c0cb3 )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 53 - w5 = ( ( w6>>>7 ^ w6>>>18 ^ w6>>>3 ^ w6<<25 ^ w6<<14 ) + ( w3>>>17 ^ w3>>>19 ^ w3>>>10 ^ w3<<15 ^ w3<<13 ) + w5 + w14 )|0; - c = ( w5 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0x4ed8aa4a )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 54 - w6 = ( ( w7>>>7 ^ w7>>>18 ^ w7>>>3 ^ w7<<25 ^ w7<<14 ) + ( w4>>>17 ^ w4>>>19 ^ w4>>>10 ^ w4<<15 ^ w4<<13 ) + w6 + w15 )|0; - b = ( w6 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0x5b9cca4f )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 55 - w7 = ( ( w8>>>7 ^ w8>>>18 ^ w8>>>3 ^ w8<<25 ^ w8<<14 ) + ( w5>>>17 ^ w5>>>19 ^ w5>>>10 ^ w5<<15 ^ w5<<13 ) + w7 + w0 )|0; - a = ( w7 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0x682e6ff3 )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - // 56 - w8 = ( ( w9>>>7 ^ w9>>>18 ^ w9>>>3 ^ w9<<25 ^ w9<<14 ) + ( w6>>>17 ^ w6>>>19 ^ w6>>>10 ^ w6<<15 ^ w6<<13 ) + w8 + w1 )|0; - h = ( w8 + h + ( e>>>6 ^ e>>>11 ^ e>>>25 ^ e<<26 ^ e<<21 ^ e<<7 ) + ( g ^ e & (f^g) ) + 0x748f82ee )|0; - d = ( d + h )|0; - h = ( h + ( (a & b) ^ ( c & (a ^ b) ) ) + ( a>>>2 ^ a>>>13 ^ a>>>22 ^ a<<30 ^ a<<19 ^ a<<10 ) )|0; - - // 57 - w9 = ( ( w10>>>7 ^ w10>>>18 ^ w10>>>3 ^ w10<<25 ^ w10<<14 ) + ( w7>>>17 ^ w7>>>19 ^ w7>>>10 ^ w7<<15 ^ w7<<13 ) + w9 + w2 )|0; - g = ( w9 + g + ( d>>>6 ^ d>>>11 ^ d>>>25 ^ d<<26 ^ d<<21 ^ d<<7 ) + ( f ^ d & (e^f) ) + 0x78a5636f )|0; - c = ( c + g )|0; - g = ( g + ( (h & a) ^ ( b & (h ^ a) ) ) + ( h>>>2 ^ h>>>13 ^ h>>>22 ^ h<<30 ^ h<<19 ^ h<<10 ) )|0; - - // 58 - w10 = ( ( w11>>>7 ^ w11>>>18 ^ w11>>>3 ^ w11<<25 ^ w11<<14 ) + ( w8>>>17 ^ w8>>>19 ^ w8>>>10 ^ w8<<15 ^ w8<<13 ) + w10 + w3 )|0; - f = ( w10 + f + ( c>>>6 ^ c>>>11 ^ c>>>25 ^ c<<26 ^ c<<21 ^ c<<7 ) + ( e ^ c & (d^e) ) + 0x84c87814 )|0; - b = ( b + f )|0; - f = ( f + ( (g & h) ^ ( a & (g ^ h) ) ) + ( g>>>2 ^ g>>>13 ^ g>>>22 ^ g<<30 ^ g<<19 ^ g<<10 ) )|0; - - // 59 - w11 = ( ( w12>>>7 ^ w12>>>18 ^ w12>>>3 ^ w12<<25 ^ w12<<14 ) + ( w9>>>17 ^ w9>>>19 ^ w9>>>10 ^ w9<<15 ^ w9<<13 ) + w11 + w4 )|0; - e = ( w11 + e + ( b>>>6 ^ b>>>11 ^ b>>>25 ^ b<<26 ^ b<<21 ^ b<<7 ) + ( d ^ b & (c^d) ) + 0x8cc70208 )|0; - a = ( a + e )|0; - e = ( e + ( (f & g) ^ ( h & (f ^ g) ) ) + ( f>>>2 ^ f>>>13 ^ f>>>22 ^ f<<30 ^ f<<19 ^ f<<10 ) )|0; - - // 60 - w12 = ( ( w13>>>7 ^ w13>>>18 ^ w13>>>3 ^ w13<<25 ^ w13<<14 ) + ( w10>>>17 ^ w10>>>19 ^ w10>>>10 ^ w10<<15 ^ w10<<13 ) + w12 + w5 )|0; - d = ( w12 + d + ( a>>>6 ^ a>>>11 ^ a>>>25 ^ a<<26 ^ a<<21 ^ a<<7 ) + ( c ^ a & (b^c) ) + 0x90befffa )|0; - h = ( h + d )|0; - d = ( d + ( (e & f) ^ ( g & (e ^ f) ) ) + ( e>>>2 ^ e>>>13 ^ e>>>22 ^ e<<30 ^ e<<19 ^ e<<10 ) )|0; - - // 61 - w13 = ( ( w14>>>7 ^ w14>>>18 ^ w14>>>3 ^ w14<<25 ^ w14<<14 ) + ( w11>>>17 ^ w11>>>19 ^ w11>>>10 ^ w11<<15 ^ w11<<13 ) + w13 + w6 )|0; - c = ( w13 + c + ( h>>>6 ^ h>>>11 ^ h>>>25 ^ h<<26 ^ h<<21 ^ h<<7 ) + ( b ^ h & (a^b) ) + 0xa4506ceb )|0; - g = ( g + c )|0; - c = ( c + ( (d & e) ^ ( f & (d ^ e) ) ) + ( d>>>2 ^ d>>>13 ^ d>>>22 ^ d<<30 ^ d<<19 ^ d<<10 ) )|0; - - // 62 - w14 = ( ( w15>>>7 ^ w15>>>18 ^ w15>>>3 ^ w15<<25 ^ w15<<14 ) + ( w12>>>17 ^ w12>>>19 ^ w12>>>10 ^ w12<<15 ^ w12<<13 ) + w14 + w7 )|0; - b = ( w14 + b + ( g>>>6 ^ g>>>11 ^ g>>>25 ^ g<<26 ^ g<<21 ^ g<<7 ) + ( a ^ g & (h^a) ) + 0xbef9a3f7 )|0; - f = ( f + b )|0; - b = ( b + ( (c & d) ^ ( e & (c ^ d) ) ) + ( c>>>2 ^ c>>>13 ^ c>>>22 ^ c<<30 ^ c<<19 ^ c<<10 ) )|0; - - // 63 - w15 = ( ( w0>>>7 ^ w0>>>18 ^ w0>>>3 ^ w0<<25 ^ w0<<14 ) + ( w13>>>17 ^ w13>>>19 ^ w13>>>10 ^ w13<<15 ^ w13<<13 ) + w15 + w8 )|0; - a = ( w15 + a + ( f>>>6 ^ f>>>11 ^ f>>>25 ^ f<<26 ^ f<<21 ^ f<<7 ) + ( h ^ f & (g^h) ) + 0xc67178f2 )|0; - e = ( e + a )|0; - a = ( a + ( (b & c) ^ ( d & (b ^ c) ) ) + ( b>>>2 ^ b>>>13 ^ b>>>22 ^ b<<30 ^ b<<19 ^ b<<10 ) )|0; - - H0 = ( H0 + a )|0; - H1 = ( H1 + b )|0; - H2 = ( H2 + c )|0; - H3 = ( H3 + d )|0; - H4 = ( H4 + e )|0; - H5 = ( H5 + f )|0; - H6 = ( H6 + g )|0; - H7 = ( H7 + h )|0; - } - - function _core_heap ( offset ) { - offset = offset|0; - - _core( - HEAP[offset|0]<<24 | HEAP[offset|1]<<16 | HEAP[offset|2]<<8 | HEAP[offset|3], - HEAP[offset|4]<<24 | HEAP[offset|5]<<16 | HEAP[offset|6]<<8 | HEAP[offset|7], - HEAP[offset|8]<<24 | HEAP[offset|9]<<16 | HEAP[offset|10]<<8 | HEAP[offset|11], - HEAP[offset|12]<<24 | HEAP[offset|13]<<16 | HEAP[offset|14]<<8 | HEAP[offset|15], - HEAP[offset|16]<<24 | HEAP[offset|17]<<16 | HEAP[offset|18]<<8 | HEAP[offset|19], - HEAP[offset|20]<<24 | HEAP[offset|21]<<16 | HEAP[offset|22]<<8 | HEAP[offset|23], - HEAP[offset|24]<<24 | HEAP[offset|25]<<16 | HEAP[offset|26]<<8 | HEAP[offset|27], - HEAP[offset|28]<<24 | HEAP[offset|29]<<16 | HEAP[offset|30]<<8 | HEAP[offset|31], - HEAP[offset|32]<<24 | HEAP[offset|33]<<16 | HEAP[offset|34]<<8 | HEAP[offset|35], - HEAP[offset|36]<<24 | HEAP[offset|37]<<16 | HEAP[offset|38]<<8 | HEAP[offset|39], - HEAP[offset|40]<<24 | HEAP[offset|41]<<16 | HEAP[offset|42]<<8 | HEAP[offset|43], - HEAP[offset|44]<<24 | HEAP[offset|45]<<16 | HEAP[offset|46]<<8 | HEAP[offset|47], - HEAP[offset|48]<<24 | HEAP[offset|49]<<16 | HEAP[offset|50]<<8 | HEAP[offset|51], - HEAP[offset|52]<<24 | HEAP[offset|53]<<16 | HEAP[offset|54]<<8 | HEAP[offset|55], - HEAP[offset|56]<<24 | HEAP[offset|57]<<16 | HEAP[offset|58]<<8 | HEAP[offset|59], - HEAP[offset|60]<<24 | HEAP[offset|61]<<16 | HEAP[offset|62]<<8 | HEAP[offset|63] - ); - } - - // offset — multiple of 32 - function _state_to_heap ( output ) { - output = output|0; - - HEAP[output|0] = H0>>>24; - HEAP[output|1] = H0>>>16&255; - HEAP[output|2] = H0>>>8&255; - HEAP[output|3] = H0&255; - HEAP[output|4] = H1>>>24; - HEAP[output|5] = H1>>>16&255; - HEAP[output|6] = H1>>>8&255; - HEAP[output|7] = H1&255; - HEAP[output|8] = H2>>>24; - HEAP[output|9] = H2>>>16&255; - HEAP[output|10] = H2>>>8&255; - HEAP[output|11] = H2&255; - HEAP[output|12] = H3>>>24; - HEAP[output|13] = H3>>>16&255; - HEAP[output|14] = H3>>>8&255; - HEAP[output|15] = H3&255; - HEAP[output|16] = H4>>>24; - HEAP[output|17] = H4>>>16&255; - HEAP[output|18] = H4>>>8&255; - HEAP[output|19] = H4&255; - HEAP[output|20] = H5>>>24; - HEAP[output|21] = H5>>>16&255; - HEAP[output|22] = H5>>>8&255; - HEAP[output|23] = H5&255; - HEAP[output|24] = H6>>>24; - HEAP[output|25] = H6>>>16&255; - HEAP[output|26] = H6>>>8&255; - HEAP[output|27] = H6&255; - HEAP[output|28] = H7>>>24; - HEAP[output|29] = H7>>>16&255; - HEAP[output|30] = H7>>>8&255; - HEAP[output|31] = H7&255; - } - - function reset () { - H0 = 0x6a09e667; - H1 = 0xbb67ae85; - H2 = 0x3c6ef372; - H3 = 0xa54ff53a; - H4 = 0x510e527f; - H5 = 0x9b05688c; - H6 = 0x1f83d9ab; - H7 = 0x5be0cd19; - TOTAL0 = TOTAL1 = 0; - } - - function init ( h0, h1, h2, h3, h4, h5, h6, h7, total0, total1 ) { - h0 = h0|0; - h1 = h1|0; - h2 = h2|0; - h3 = h3|0; - h4 = h4|0; - h5 = h5|0; - h6 = h6|0; - h7 = h7|0; - total0 = total0|0; - total1 = total1|0; - - H0 = h0; - H1 = h1; - H2 = h2; - H3 = h3; - H4 = h4; - H5 = h5; - H6 = h6; - H7 = h7; - TOTAL0 = total0; - TOTAL1 = total1; - } - - // offset — multiple of 64 - function process ( offset, length ) { - offset = offset|0; - length = length|0; - - var hashed = 0; - - if ( offset & 63 ) - return -1; - - while ( (length|0) >= 64 ) { - _core_heap(offset); - - offset = ( offset + 64 )|0; - length = ( length - 64 )|0; - - hashed = ( hashed + 64 )|0; - } - - TOTAL0 = ( TOTAL0 + hashed )|0; - if ( TOTAL0>>>0 < hashed>>>0 ) TOTAL1 = ( TOTAL1 + 1 )|0; - - return hashed|0; - } - - // offset — multiple of 64 - // output — multiple of 32 - function finish ( offset, length, output ) { - offset = offset|0; - length = length|0; - output = output|0; - - var hashed = 0, - i = 0; - - if ( offset & 63 ) - return -1; - - if ( ~output ) - if ( output & 31 ) - return -1; - - if ( (length|0) >= 64 ) { - hashed = process( offset, length )|0; - if ( (hashed|0) == -1 ) - return -1; - - offset = ( offset + hashed )|0; - length = ( length - hashed )|0; - } - - hashed = ( hashed + length )|0; - TOTAL0 = ( TOTAL0 + length )|0; - if ( TOTAL0>>>0 < length>>>0 ) TOTAL1 = ( TOTAL1 + 1 )|0; - - HEAP[offset|length] = 0x80; - - if ( (length|0) >= 56 ) { - for ( i = (length+1)|0; (i|0) < 64; i = (i+1)|0 ) - HEAP[offset|i] = 0x00; - - _core_heap(offset); - - length = 0; - - HEAP[offset|0] = 0; - } - - for ( i = (length+1)|0; (i|0) < 59; i = (i+1)|0 ) - HEAP[offset|i] = 0; - - HEAP[offset|56] = TOTAL1>>>21&255; - HEAP[offset|57] = TOTAL1>>>13&255; - HEAP[offset|58] = TOTAL1>>>5&255; - HEAP[offset|59] = TOTAL1<<3&255 | TOTAL0>>>29; - HEAP[offset|60] = TOTAL0>>>21&255; - HEAP[offset|61] = TOTAL0>>>13&255; - HEAP[offset|62] = TOTAL0>>>5&255; - HEAP[offset|63] = TOTAL0<<3&255; - _core_heap(offset); - - if ( ~output ) - _state_to_heap(output); - - return hashed|0; - } - - function hmac_reset () { - H0 = I0; - H1 = I1; - H2 = I2; - H3 = I3; - H4 = I4; - H5 = I5; - H6 = I6; - H7 = I7; - TOTAL0 = 64; - TOTAL1 = 0; - } - - function _hmac_opad () { - H0 = O0; - H1 = O1; - H2 = O2; - H3 = O3; - H4 = O4; - H5 = O5; - H6 = O6; - H7 = O7; - TOTAL0 = 64; - TOTAL1 = 0; - } - - function hmac_init ( p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15 ) { - p0 = p0|0; - p1 = p1|0; - p2 = p2|0; - p3 = p3|0; - p4 = p4|0; - p5 = p5|0; - p6 = p6|0; - p7 = p7|0; - p8 = p8|0; - p9 = p9|0; - p10 = p10|0; - p11 = p11|0; - p12 = p12|0; - p13 = p13|0; - p14 = p14|0; - p15 = p15|0; - - // opad - reset(); - _core( - p0 ^ 0x5c5c5c5c, - p1 ^ 0x5c5c5c5c, - p2 ^ 0x5c5c5c5c, - p3 ^ 0x5c5c5c5c, - p4 ^ 0x5c5c5c5c, - p5 ^ 0x5c5c5c5c, - p6 ^ 0x5c5c5c5c, - p7 ^ 0x5c5c5c5c, - p8 ^ 0x5c5c5c5c, - p9 ^ 0x5c5c5c5c, - p10 ^ 0x5c5c5c5c, - p11 ^ 0x5c5c5c5c, - p12 ^ 0x5c5c5c5c, - p13 ^ 0x5c5c5c5c, - p14 ^ 0x5c5c5c5c, - p15 ^ 0x5c5c5c5c - ); - O0 = H0; - O1 = H1; - O2 = H2; - O3 = H3; - O4 = H4; - O5 = H5; - O6 = H6; - O7 = H7; - - // ipad - reset(); - _core( - p0 ^ 0x36363636, - p1 ^ 0x36363636, - p2 ^ 0x36363636, - p3 ^ 0x36363636, - p4 ^ 0x36363636, - p5 ^ 0x36363636, - p6 ^ 0x36363636, - p7 ^ 0x36363636, - p8 ^ 0x36363636, - p9 ^ 0x36363636, - p10 ^ 0x36363636, - p11 ^ 0x36363636, - p12 ^ 0x36363636, - p13 ^ 0x36363636, - p14 ^ 0x36363636, - p15 ^ 0x36363636 - ); - I0 = H0; - I1 = H1; - I2 = H2; - I3 = H3; - I4 = H4; - I5 = H5; - I6 = H6; - I7 = H7; - - TOTAL0 = 64; - TOTAL1 = 0; - } - - // offset — multiple of 64 - // output — multiple of 32 - function hmac_finish ( offset, length, output ) { - offset = offset|0; - length = length|0; - output = output|0; - - var t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0, - hashed = 0; - - if ( offset & 63 ) - return -1; - - if ( ~output ) - if ( output & 31 ) - return -1; - - hashed = finish( offset, length, -1 )|0; - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; - - _hmac_opad(); - _core( t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768 ); - - if ( ~output ) - _state_to_heap(output); - - return hashed|0; - } - - // salt is assumed to be already processed - // offset — multiple of 64 - // output — multiple of 32 - function pbkdf2_generate_block ( offset, length, block, count, output ) { - offset = offset|0; - length = length|0; - block = block|0; - count = count|0; - output = output|0; - - var h0 = 0, h1 = 0, h2 = 0, h3 = 0, h4 = 0, h5 = 0, h6 = 0, h7 = 0, - t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0; - - if ( offset & 63 ) - return -1; - - if ( ~output ) - if ( output & 31 ) - return -1; - - // pad block number into heap - // FIXME probable OOB write - HEAP[(offset+length)|0] = block>>>24; - HEAP[(offset+length+1)|0] = block>>>16&255; - HEAP[(offset+length+2)|0] = block>>>8&255; - HEAP[(offset+length+3)|0] = block&255; - - // finish first iteration - hmac_finish( offset, (length+4)|0, -1 )|0; - h0 = t0 = H0, h1 = t1 = H1, h2 = t2 = H2, h3 = t3 = H3, h4 = t4 = H4, h5 = t5 = H5, h6 = t6 = H6, h7 = t7 = H7; - count = (count-1)|0; - - // perform the rest iterations - while ( (count|0) > 0 ) { - hmac_reset(); - _core( t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768 ); - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; - - _hmac_opad(); - _core( t0, t1, t2, t3, t4, t5, t6, t7, 0x80000000, 0, 0, 0, 0, 0, 0, 768 ); - t0 = H0, t1 = H1, t2 = H2, t3 = H3, t4 = H4, t5 = H5, t6 = H6, t7 = H7; - - h0 = h0 ^ H0; - h1 = h1 ^ H1; - h2 = h2 ^ H2; - h3 = h3 ^ H3; - h4 = h4 ^ H4; - h5 = h5 ^ H5; - h6 = h6 ^ H6; - h7 = h7 ^ H7; - - count = (count-1)|0; - } - - H0 = h0; - H1 = h1; - H2 = h2; - H3 = h3; - H4 = h4; - H5 = h5; - H6 = h6; - H7 = h7; - - if ( ~output ) - _state_to_heap(output); - - return 0; - } - - return { - // SHA256 - reset: reset, - init: init, - process: process, - finish: finish, - - // HMAC-SHA256 - hmac_reset: hmac_reset, - hmac_init: hmac_init, - hmac_finish: hmac_finish, - - // PBKDF2-HMAC-SHA256 - pbkdf2_generate_block: pbkdf2_generate_block - } - }; - - const _sha256_block_size = 64; - const _sha256_hash_size = 32; - const heap_pool$2 = []; - const asm_pool$2 = []; - class Sha256 extends Hash { - constructor() { - super(); - this.NAME = 'sha256'; - this.BLOCK_SIZE = _sha256_block_size; - this.HASH_SIZE = _sha256_hash_size; - this.acquire_asm(); - } - acquire_asm() { - if (this.heap === undefined || this.asm === undefined) { - this.heap = heap_pool$2.pop() || _heap_init(); - this.asm = asm_pool$2.pop() || sha256_asm({ Uint8Array: Uint8Array }, null, this.heap.buffer); - this.reset(); - } - return { heap: this.heap, asm: this.asm }; - } - release_asm() { - if (this.heap !== undefined && this.asm !== undefined) { - heap_pool$2.push(this.heap); - asm_pool$2.push(this.asm); - } - this.heap = undefined; - this.asm = undefined; - } - static bytes(data) { - return new Sha256().process(data).finish().result; - } - } - Sha256.NAME = 'sha256'; - - var minimalisticAssert = assert; - - function assert(val, msg) { - if (!val) - throw new Error(msg || 'Assertion failed'); - } - - assert.equal = function assertEqual(l, r, msg) { - if (l != r) - throw new Error(msg || ('Assertion failed: ' + l + ' != ' + r)); - }; - - var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; - - function createCommonjsModule(fn, module) { - return module = { exports: {} }, fn(module, module.exports), module.exports; - } - - function commonjsRequire () { - throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs'); - } - - var inherits_browser = createCommonjsModule(function (module) { - if (typeof Object.create === 'function') { - // implementation from standard node.js 'util' module - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor; - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }); - }; - } else { - // old school shim for old browsers - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor; - var TempCtor = function () {}; - TempCtor.prototype = superCtor.prototype; - ctor.prototype = new TempCtor(); - ctor.prototype.constructor = ctor; - }; - } - }); - - var inherits_1 = inherits_browser; - - function toArray(msg, enc) { - if (Array.isArray(msg)) - return msg.slice(); - if (!msg) - return []; - var res = []; - if (typeof msg === 'string') { - if (!enc) { - for (var i = 0; i < msg.length; i++) { - var c = msg.charCodeAt(i); - var hi = c >> 8; - var lo = c & 0xff; - if (hi) - res.push(hi, lo); - else - res.push(lo); - } - } else if (enc === 'hex') { - msg = msg.replace(/[^a-z0-9]+/ig, ''); - if (msg.length % 2 !== 0) - msg = '0' + msg; - for (i = 0; i < msg.length; i += 2) - res.push(parseInt(msg[i] + msg[i + 1], 16)); - } - } else { - for (i = 0; i < msg.length; i++) - res[i] = msg[i] | 0; - } - return res; - } - var toArray_1 = toArray; - - function toHex(msg) { - var res = ''; - for (var i = 0; i < msg.length; i++) - res += zero2(msg[i].toString(16)); - return res; - } - var toHex_1 = toHex; - - function htonl(w) { - var res = (w >>> 24) | - ((w >>> 8) & 0xff00) | - ((w << 8) & 0xff0000) | - ((w & 0xff) << 24); - return res >>> 0; - } - var htonl_1 = htonl; - - function toHex32(msg, endian) { - var res = ''; - for (var i = 0; i < msg.length; i++) { - var w = msg[i]; - if (endian === 'little') - w = htonl(w); - res += zero8(w.toString(16)); - } - return res; - } - var toHex32_1 = toHex32; - - function zero2(word) { - if (word.length === 1) - return '0' + word; - else - return word; - } - var zero2_1 = zero2; - - function zero8(word) { - if (word.length === 7) - return '0' + word; - else if (word.length === 6) - return '00' + word; - else if (word.length === 5) - return '000' + word; - else if (word.length === 4) - return '0000' + word; - else if (word.length === 3) - return '00000' + word; - else if (word.length === 2) - return '000000' + word; - else if (word.length === 1) - return '0000000' + word; - else - return word; - } - var zero8_1 = zero8; - - function join32(msg, start, end, endian) { - var len = end - start; - minimalisticAssert(len % 4 === 0); - var res = new Array(len / 4); - for (var i = 0, k = start; i < res.length; i++, k += 4) { - var w; - if (endian === 'big') - w = (msg[k] << 24) | (msg[k + 1] << 16) | (msg[k + 2] << 8) | msg[k + 3]; - else - w = (msg[k + 3] << 24) | (msg[k + 2] << 16) | (msg[k + 1] << 8) | msg[k]; - res[i] = w >>> 0; - } - return res; - } - var join32_1 = join32; - - function split32(msg, endian) { - var res = new Array(msg.length * 4); - for (var i = 0, k = 0; i < msg.length; i++, k += 4) { - var m = msg[i]; - if (endian === 'big') { - res[k] = m >>> 24; - res[k + 1] = (m >>> 16) & 0xff; - res[k + 2] = (m >>> 8) & 0xff; - res[k + 3] = m & 0xff; - } else { - res[k + 3] = m >>> 24; - res[k + 2] = (m >>> 16) & 0xff; - res[k + 1] = (m >>> 8) & 0xff; - res[k] = m & 0xff; - } - } - return res; - } - var split32_1 = split32; - - function rotr32(w, b) { - return (w >>> b) | (w << (32 - b)); - } - var rotr32_1 = rotr32; - - function rotl32(w, b) { - return (w << b) | (w >>> (32 - b)); - } - var rotl32_1 = rotl32; - - function sum32(a, b) { - return (a + b) >>> 0; - } - var sum32_1 = sum32; - - function sum32_3(a, b, c) { - return (a + b + c) >>> 0; - } - var sum32_3_1 = sum32_3; - - function sum32_4(a, b, c, d) { - return (a + b + c + d) >>> 0; - } - var sum32_4_1 = sum32_4; - - function sum32_5(a, b, c, d, e) { - return (a + b + c + d + e) >>> 0; - } - var sum32_5_1 = sum32_5; - - function sum64(buf, pos, ah, al) { - var bh = buf[pos]; - var bl = buf[pos + 1]; - - var lo = (al + bl) >>> 0; - var hi = (lo < al ? 1 : 0) + ah + bh; - buf[pos] = hi >>> 0; - buf[pos + 1] = lo; - } - var sum64_1 = sum64; - - function sum64_hi(ah, al, bh, bl) { - var lo = (al + bl) >>> 0; - var hi = (lo < al ? 1 : 0) + ah + bh; - return hi >>> 0; - } - var sum64_hi_1 = sum64_hi; - - function sum64_lo(ah, al, bh, bl) { - var lo = al + bl; - return lo >>> 0; - } - var sum64_lo_1 = sum64_lo; - - function sum64_4_hi(ah, al, bh, bl, ch, cl, dh, dl) { - var carry = 0; - var lo = al; - lo = (lo + bl) >>> 0; - carry += lo < al ? 1 : 0; - lo = (lo + cl) >>> 0; - carry += lo < cl ? 1 : 0; - lo = (lo + dl) >>> 0; - carry += lo < dl ? 1 : 0; - - var hi = ah + bh + ch + dh + carry; - return hi >>> 0; - } - var sum64_4_hi_1 = sum64_4_hi; - - function sum64_4_lo(ah, al, bh, bl, ch, cl, dh, dl) { - var lo = al + bl + cl + dl; - return lo >>> 0; - } - var sum64_4_lo_1 = sum64_4_lo; - - function sum64_5_hi(ah, al, bh, bl, ch, cl, dh, dl, eh, el) { - var carry = 0; - var lo = al; - lo = (lo + bl) >>> 0; - carry += lo < al ? 1 : 0; - lo = (lo + cl) >>> 0; - carry += lo < cl ? 1 : 0; - lo = (lo + dl) >>> 0; - carry += lo < dl ? 1 : 0; - lo = (lo + el) >>> 0; - carry += lo < el ? 1 : 0; - - var hi = ah + bh + ch + dh + eh + carry; - return hi >>> 0; - } - var sum64_5_hi_1 = sum64_5_hi; - - function sum64_5_lo(ah, al, bh, bl, ch, cl, dh, dl, eh, el) { - var lo = al + bl + cl + dl + el; - - return lo >>> 0; - } - var sum64_5_lo_1 = sum64_5_lo; - - function rotr64_hi(ah, al, num) { - var r = (al << (32 - num)) | (ah >>> num); - return r >>> 0; - } - var rotr64_hi_1 = rotr64_hi; - - function rotr64_lo(ah, al, num) { - var r = (ah << (32 - num)) | (al >>> num); - return r >>> 0; - } - var rotr64_lo_1 = rotr64_lo; - - function shr64_hi(ah, al, num) { - return ah >>> num; - } - var shr64_hi_1 = shr64_hi; - - function shr64_lo(ah, al, num) { - var r = (ah << (32 - num)) | (al >>> num); - return r >>> 0; - } - var shr64_lo_1 = shr64_lo; - - var utils = { - inherits: inherits_1, - toArray: toArray_1, - toHex: toHex_1, - htonl: htonl_1, - toHex32: toHex32_1, - zero2: zero2_1, - zero8: zero8_1, - join32: join32_1, - split32: split32_1, - rotr32: rotr32_1, - rotl32: rotl32_1, - sum32: sum32_1, - sum32_3: sum32_3_1, - sum32_4: sum32_4_1, - sum32_5: sum32_5_1, - sum64: sum64_1, - sum64_hi: sum64_hi_1, - sum64_lo: sum64_lo_1, - sum64_4_hi: sum64_4_hi_1, - sum64_4_lo: sum64_4_lo_1, - sum64_5_hi: sum64_5_hi_1, - sum64_5_lo: sum64_5_lo_1, - rotr64_hi: rotr64_hi_1, - rotr64_lo: rotr64_lo_1, - shr64_hi: shr64_hi_1, - shr64_lo: shr64_lo_1 - }; - - function BlockHash() { - this.pending = null; - this.pendingTotal = 0; - this.blockSize = this.constructor.blockSize; - this.outSize = this.constructor.outSize; - this.hmacStrength = this.constructor.hmacStrength; - this.padLength = this.constructor.padLength / 8; - this.endian = 'big'; - - this._delta8 = this.blockSize / 8; - this._delta32 = this.blockSize / 32; - } - var BlockHash_1 = BlockHash; - - BlockHash.prototype.update = function update(msg, enc) { - // Convert message to array, pad it, and join into 32bit blocks - msg = utils.toArray(msg, enc); - if (!this.pending) - this.pending = msg; - else - this.pending = this.pending.concat(msg); - this.pendingTotal += msg.length; - - // Enough data, try updating - if (this.pending.length >= this._delta8) { - msg = this.pending; - - // Process pending data in blocks - var r = msg.length % this._delta8; - this.pending = msg.slice(msg.length - r, msg.length); - if (this.pending.length === 0) - this.pending = null; - - msg = utils.join32(msg, 0, msg.length - r, this.endian); - for (var i = 0; i < msg.length; i += this._delta32) - this._update(msg, i, i + this._delta32); - } - - return this; - }; - - BlockHash.prototype.digest = function digest(enc) { - this.update(this._pad()); - minimalisticAssert(this.pending === null); - - return this._digest(enc); - }; - - BlockHash.prototype._pad = function pad() { - var len = this.pendingTotal; - var bytes = this._delta8; - var k = bytes - ((len + this.padLength) % bytes); - var res = new Array(k + this.padLength); - res[0] = 0x80; - for (var i = 1; i < k; i++) - res[i] = 0; - - // Append length - len <<= 3; - if (this.endian === 'big') { - for (var t = 8; t < this.padLength; t++) - res[i++] = 0; - - res[i++] = 0; - res[i++] = 0; - res[i++] = 0; - res[i++] = 0; - res[i++] = (len >>> 24) & 0xff; - res[i++] = (len >>> 16) & 0xff; - res[i++] = (len >>> 8) & 0xff; - res[i++] = len & 0xff; - } else { - res[i++] = len & 0xff; - res[i++] = (len >>> 8) & 0xff; - res[i++] = (len >>> 16) & 0xff; - res[i++] = (len >>> 24) & 0xff; - res[i++] = 0; - res[i++] = 0; - res[i++] = 0; - res[i++] = 0; - - for (t = 8; t < this.padLength; t++) - res[i++] = 0; - } - - return res; - }; - - var common = { - BlockHash: BlockHash_1 - }; - - var rotr32$1 = utils.rotr32; - - function ft_1(s, x, y, z) { - if (s === 0) - return ch32(x, y, z); - if (s === 1 || s === 3) - return p32(x, y, z); - if (s === 2) - return maj32(x, y, z); - } - var ft_1_1 = ft_1; - - function ch32(x, y, z) { - return (x & y) ^ ((~x) & z); - } - var ch32_1 = ch32; - - function maj32(x, y, z) { - return (x & y) ^ (x & z) ^ (y & z); - } - var maj32_1 = maj32; - - function p32(x, y, z) { - return x ^ y ^ z; - } - var p32_1 = p32; - - function s0_256(x) { - return rotr32$1(x, 2) ^ rotr32$1(x, 13) ^ rotr32$1(x, 22); - } - var s0_256_1 = s0_256; - - function s1_256(x) { - return rotr32$1(x, 6) ^ rotr32$1(x, 11) ^ rotr32$1(x, 25); - } - var s1_256_1 = s1_256; - - function g0_256(x) { - return rotr32$1(x, 7) ^ rotr32$1(x, 18) ^ (x >>> 3); - } - var g0_256_1 = g0_256; - - function g1_256(x) { - return rotr32$1(x, 17) ^ rotr32$1(x, 19) ^ (x >>> 10); - } - var g1_256_1 = g1_256; - - var common$1 = { - ft_1: ft_1_1, - ch32: ch32_1, - maj32: maj32_1, - p32: p32_1, - s0_256: s0_256_1, - s1_256: s1_256_1, - g0_256: g0_256_1, - g1_256: g1_256_1 - }; - - var sum32$1 = utils.sum32; - var sum32_4$1 = utils.sum32_4; - var sum32_5$1 = utils.sum32_5; - var ch32$1 = common$1.ch32; - var maj32$1 = common$1.maj32; - var s0_256$1 = common$1.s0_256; - var s1_256$1 = common$1.s1_256; - var g0_256$1 = common$1.g0_256; - var g1_256$1 = common$1.g1_256; - - var BlockHash$1 = common.BlockHash; - - var sha256_K = [ - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 - ]; - - function SHA256() { - if (!(this instanceof SHA256)) - return new SHA256(); - - BlockHash$1.call(this); - this.h = [ - 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, - 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 - ]; - this.k = sha256_K; - this.W = new Array(64); - } - utils.inherits(SHA256, BlockHash$1); - var _256 = SHA256; - - SHA256.blockSize = 512; - SHA256.outSize = 256; - SHA256.hmacStrength = 192; - SHA256.padLength = 64; - - SHA256.prototype._update = function _update(msg, start) { - var W = this.W; - - for (var i = 0; i < 16; i++) - W[i] = msg[start + i]; - for (; i < W.length; i++) - W[i] = sum32_4$1(g1_256$1(W[i - 2]), W[i - 7], g0_256$1(W[i - 15]), W[i - 16]); - - var a = this.h[0]; - var b = this.h[1]; - var c = this.h[2]; - var d = this.h[3]; - var e = this.h[4]; - var f = this.h[5]; - var g = this.h[6]; - var h = this.h[7]; - - minimalisticAssert(this.k.length === W.length); - for (i = 0; i < W.length; i++) { - var T1 = sum32_5$1(h, s1_256$1(e), ch32$1(e, f, g), this.k[i], W[i]); - var T2 = sum32$1(s0_256$1(a), maj32$1(a, b, c)); - h = g; - g = f; - f = e; - e = sum32$1(d, T1); - d = c; - c = b; - b = a; - a = sum32$1(T1, T2); - } - - this.h[0] = sum32$1(this.h[0], a); - this.h[1] = sum32$1(this.h[1], b); - this.h[2] = sum32$1(this.h[2], c); - this.h[3] = sum32$1(this.h[3], d); - this.h[4] = sum32$1(this.h[4], e); - this.h[5] = sum32$1(this.h[5], f); - this.h[6] = sum32$1(this.h[6], g); - this.h[7] = sum32$1(this.h[7], h); - }; - - SHA256.prototype._digest = function digest(enc) { - if (enc === 'hex') - return utils.toHex32(this.h, 'big'); - else - return utils.split32(this.h, 'big'); - }; - - function SHA224() { - if (!(this instanceof SHA224)) - return new SHA224(); - - _256.call(this); - this.h = [ - 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, - 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 ]; - } - utils.inherits(SHA224, _256); - var _224 = SHA224; - - SHA224.blockSize = 512; - SHA224.outSize = 224; - SHA224.hmacStrength = 192; - SHA224.padLength = 64; - - SHA224.prototype._digest = function digest(enc) { - // Just truncate output - if (enc === 'hex') - return utils.toHex32(this.h.slice(0, 7), 'big'); - else - return utils.split32(this.h.slice(0, 7), 'big'); - }; - - var rotr64_hi$1 = utils.rotr64_hi; - var rotr64_lo$1 = utils.rotr64_lo; - var shr64_hi$1 = utils.shr64_hi; - var shr64_lo$1 = utils.shr64_lo; - var sum64$1 = utils.sum64; - var sum64_hi$1 = utils.sum64_hi; - var sum64_lo$1 = utils.sum64_lo; - var sum64_4_hi$1 = utils.sum64_4_hi; - var sum64_4_lo$1 = utils.sum64_4_lo; - var sum64_5_hi$1 = utils.sum64_5_hi; - var sum64_5_lo$1 = utils.sum64_5_lo; - - var BlockHash$2 = common.BlockHash; - - var sha512_K = [ - 0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd, - 0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc, - 0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019, - 0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118, - 0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe, - 0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2, - 0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1, - 0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694, - 0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3, - 0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65, - 0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483, - 0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5, - 0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210, - 0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4, - 0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725, - 0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70, - 0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926, - 0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df, - 0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8, - 0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b, - 0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001, - 0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30, - 0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910, - 0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8, - 0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53, - 0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8, - 0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb, - 0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3, - 0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60, - 0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec, - 0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9, - 0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b, - 0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207, - 0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178, - 0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6, - 0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b, - 0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493, - 0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c, - 0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a, - 0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817 - ]; - - function SHA512() { - if (!(this instanceof SHA512)) - return new SHA512(); - - BlockHash$2.call(this); - this.h = [ - 0x6a09e667, 0xf3bcc908, - 0xbb67ae85, 0x84caa73b, - 0x3c6ef372, 0xfe94f82b, - 0xa54ff53a, 0x5f1d36f1, - 0x510e527f, 0xade682d1, - 0x9b05688c, 0x2b3e6c1f, - 0x1f83d9ab, 0xfb41bd6b, - 0x5be0cd19, 0x137e2179 ]; - this.k = sha512_K; - this.W = new Array(160); - } - utils.inherits(SHA512, BlockHash$2); - var _512 = SHA512; - - SHA512.blockSize = 1024; - SHA512.outSize = 512; - SHA512.hmacStrength = 192; - SHA512.padLength = 128; - - SHA512.prototype._prepareBlock = function _prepareBlock(msg, start) { - var W = this.W; - - // 32 x 32bit words - for (var i = 0; i < 32; i++) - W[i] = msg[start + i]; - for (; i < W.length; i += 2) { - var c0_hi = g1_512_hi(W[i - 4], W[i - 3]); // i - 2 - var c0_lo = g1_512_lo(W[i - 4], W[i - 3]); - var c1_hi = W[i - 14]; // i - 7 - var c1_lo = W[i - 13]; - var c2_hi = g0_512_hi(W[i - 30], W[i - 29]); // i - 15 - var c2_lo = g0_512_lo(W[i - 30], W[i - 29]); - var c3_hi = W[i - 32]; // i - 16 - var c3_lo = W[i - 31]; - - W[i] = sum64_4_hi$1( - c0_hi, c0_lo, - c1_hi, c1_lo, - c2_hi, c2_lo, - c3_hi, c3_lo); - W[i + 1] = sum64_4_lo$1( - c0_hi, c0_lo, - c1_hi, c1_lo, - c2_hi, c2_lo, - c3_hi, c3_lo); - } - }; - - SHA512.prototype._update = function _update(msg, start) { - this._prepareBlock(msg, start); - - var W = this.W; - - var ah = this.h[0]; - var al = this.h[1]; - var bh = this.h[2]; - var bl = this.h[3]; - var ch = this.h[4]; - var cl = this.h[5]; - var dh = this.h[6]; - var dl = this.h[7]; - var eh = this.h[8]; - var el = this.h[9]; - var fh = this.h[10]; - var fl = this.h[11]; - var gh = this.h[12]; - var gl = this.h[13]; - var hh = this.h[14]; - var hl = this.h[15]; - - minimalisticAssert(this.k.length === W.length); - for (var i = 0; i < W.length; i += 2) { - var c0_hi = hh; - var c0_lo = hl; - var c1_hi = s1_512_hi(eh, el); - var c1_lo = s1_512_lo(eh, el); - var c2_hi = ch64_hi(eh, el, fh, fl, gh); - var c2_lo = ch64_lo(eh, el, fh, fl, gh, gl); - var c3_hi = this.k[i]; - var c3_lo = this.k[i + 1]; - var c4_hi = W[i]; - var c4_lo = W[i + 1]; - - var T1_hi = sum64_5_hi$1( - c0_hi, c0_lo, - c1_hi, c1_lo, - c2_hi, c2_lo, - c3_hi, c3_lo, - c4_hi, c4_lo); - var T1_lo = sum64_5_lo$1( - c0_hi, c0_lo, - c1_hi, c1_lo, - c2_hi, c2_lo, - c3_hi, c3_lo, - c4_hi, c4_lo); - - c0_hi = s0_512_hi(ah, al); - c0_lo = s0_512_lo(ah, al); - c1_hi = maj64_hi(ah, al, bh, bl, ch); - c1_lo = maj64_lo(ah, al, bh, bl, ch, cl); - - var T2_hi = sum64_hi$1(c0_hi, c0_lo, c1_hi, c1_lo); - var T2_lo = sum64_lo$1(c0_hi, c0_lo, c1_hi, c1_lo); - - hh = gh; - hl = gl; - - gh = fh; - gl = fl; - - fh = eh; - fl = el; - - eh = sum64_hi$1(dh, dl, T1_hi, T1_lo); - el = sum64_lo$1(dl, dl, T1_hi, T1_lo); - - dh = ch; - dl = cl; - - ch = bh; - cl = bl; - - bh = ah; - bl = al; - - ah = sum64_hi$1(T1_hi, T1_lo, T2_hi, T2_lo); - al = sum64_lo$1(T1_hi, T1_lo, T2_hi, T2_lo); - } - - sum64$1(this.h, 0, ah, al); - sum64$1(this.h, 2, bh, bl); - sum64$1(this.h, 4, ch, cl); - sum64$1(this.h, 6, dh, dl); - sum64$1(this.h, 8, eh, el); - sum64$1(this.h, 10, fh, fl); - sum64$1(this.h, 12, gh, gl); - sum64$1(this.h, 14, hh, hl); - }; - - SHA512.prototype._digest = function digest(enc) { - if (enc === 'hex') - return utils.toHex32(this.h, 'big'); - else - return utils.split32(this.h, 'big'); - }; - - function ch64_hi(xh, xl, yh, yl, zh) { - var r = (xh & yh) ^ ((~xh) & zh); - if (r < 0) - r += 0x100000000; - return r; - } - - function ch64_lo(xh, xl, yh, yl, zh, zl) { - var r = (xl & yl) ^ ((~xl) & zl); - if (r < 0) - r += 0x100000000; - return r; - } - - function maj64_hi(xh, xl, yh, yl, zh) { - var r = (xh & yh) ^ (xh & zh) ^ (yh & zh); - if (r < 0) - r += 0x100000000; - return r; - } - - function maj64_lo(xh, xl, yh, yl, zh, zl) { - var r = (xl & yl) ^ (xl & zl) ^ (yl & zl); - if (r < 0) - r += 0x100000000; - return r; - } - - function s0_512_hi(xh, xl) { - var c0_hi = rotr64_hi$1(xh, xl, 28); - var c1_hi = rotr64_hi$1(xl, xh, 2); // 34 - var c2_hi = rotr64_hi$1(xl, xh, 7); // 39 - - var r = c0_hi ^ c1_hi ^ c2_hi; - if (r < 0) - r += 0x100000000; - return r; - } - - function s0_512_lo(xh, xl) { - var c0_lo = rotr64_lo$1(xh, xl, 28); - var c1_lo = rotr64_lo$1(xl, xh, 2); // 34 - var c2_lo = rotr64_lo$1(xl, xh, 7); // 39 - - var r = c0_lo ^ c1_lo ^ c2_lo; - if (r < 0) - r += 0x100000000; - return r; - } - - function s1_512_hi(xh, xl) { - var c0_hi = rotr64_hi$1(xh, xl, 14); - var c1_hi = rotr64_hi$1(xh, xl, 18); - var c2_hi = rotr64_hi$1(xl, xh, 9); // 41 - - var r = c0_hi ^ c1_hi ^ c2_hi; - if (r < 0) - r += 0x100000000; - return r; - } - - function s1_512_lo(xh, xl) { - var c0_lo = rotr64_lo$1(xh, xl, 14); - var c1_lo = rotr64_lo$1(xh, xl, 18); - var c2_lo = rotr64_lo$1(xl, xh, 9); // 41 - - var r = c0_lo ^ c1_lo ^ c2_lo; - if (r < 0) - r += 0x100000000; - return r; - } - - function g0_512_hi(xh, xl) { - var c0_hi = rotr64_hi$1(xh, xl, 1); - var c1_hi = rotr64_hi$1(xh, xl, 8); - var c2_hi = shr64_hi$1(xh, xl, 7); - - var r = c0_hi ^ c1_hi ^ c2_hi; - if (r < 0) - r += 0x100000000; - return r; - } - - function g0_512_lo(xh, xl) { - var c0_lo = rotr64_lo$1(xh, xl, 1); - var c1_lo = rotr64_lo$1(xh, xl, 8); - var c2_lo = shr64_lo$1(xh, xl, 7); - - var r = c0_lo ^ c1_lo ^ c2_lo; - if (r < 0) - r += 0x100000000; - return r; - } - - function g1_512_hi(xh, xl) { - var c0_hi = rotr64_hi$1(xh, xl, 19); - var c1_hi = rotr64_hi$1(xl, xh, 29); // 61 - var c2_hi = shr64_hi$1(xh, xl, 6); - - var r = c0_hi ^ c1_hi ^ c2_hi; - if (r < 0) - r += 0x100000000; - return r; - } - - function g1_512_lo(xh, xl) { - var c0_lo = rotr64_lo$1(xh, xl, 19); - var c1_lo = rotr64_lo$1(xl, xh, 29); // 61 - var c2_lo = shr64_lo$1(xh, xl, 6); - - var r = c0_lo ^ c1_lo ^ c2_lo; - if (r < 0) - r += 0x100000000; - return r; - } - - function SHA384() { - if (!(this instanceof SHA384)) - return new SHA384(); - - _512.call(this); - this.h = [ - 0xcbbb9d5d, 0xc1059ed8, - 0x629a292a, 0x367cd507, - 0x9159015a, 0x3070dd17, - 0x152fecd8, 0xf70e5939, - 0x67332667, 0xffc00b31, - 0x8eb44a87, 0x68581511, - 0xdb0c2e0d, 0x64f98fa7, - 0x47b5481d, 0xbefa4fa4 ]; - } - utils.inherits(SHA384, _512); - var _384 = SHA384; - - SHA384.blockSize = 1024; - SHA384.outSize = 384; - SHA384.hmacStrength = 192; - SHA384.padLength = 128; - - SHA384.prototype._digest = function digest(enc) { - if (enc === 'hex') - return utils.toHex32(this.h.slice(0, 12), 'big'); - else - return utils.split32(this.h.slice(0, 12), 'big'); - }; - - var rotl32$1 = utils.rotl32; - var sum32$2 = utils.sum32; - var sum32_3$1 = utils.sum32_3; - var sum32_4$2 = utils.sum32_4; - var BlockHash$3 = common.BlockHash; - - function RIPEMD160() { - if (!(this instanceof RIPEMD160)) - return new RIPEMD160(); - - BlockHash$3.call(this); - - this.h = [ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 ]; - this.endian = 'little'; - } - utils.inherits(RIPEMD160, BlockHash$3); - var ripemd160 = RIPEMD160; - - RIPEMD160.blockSize = 512; - RIPEMD160.outSize = 160; - RIPEMD160.hmacStrength = 192; - RIPEMD160.padLength = 64; - - RIPEMD160.prototype._update = function update(msg, start) { - var A = this.h[0]; - var B = this.h[1]; - var C = this.h[2]; - var D = this.h[3]; - var E = this.h[4]; - var Ah = A; - var Bh = B; - var Ch = C; - var Dh = D; - var Eh = E; - for (var j = 0; j < 80; j++) { - var T = sum32$2( - rotl32$1( - sum32_4$2(A, f(j, B, C, D), msg[r[j] + start], K(j)), - s[j]), - E); - A = E; - E = D; - D = rotl32$1(C, 10); - C = B; - B = T; - T = sum32$2( - rotl32$1( - sum32_4$2(Ah, f(79 - j, Bh, Ch, Dh), msg[rh[j] + start], Kh(j)), - sh[j]), - Eh); - Ah = Eh; - Eh = Dh; - Dh = rotl32$1(Ch, 10); - Ch = Bh; - Bh = T; - } - T = sum32_3$1(this.h[1], C, Dh); - this.h[1] = sum32_3$1(this.h[2], D, Eh); - this.h[2] = sum32_3$1(this.h[3], E, Ah); - this.h[3] = sum32_3$1(this.h[4], A, Bh); - this.h[4] = sum32_3$1(this.h[0], B, Ch); - this.h[0] = T; - }; - - RIPEMD160.prototype._digest = function digest(enc) { - if (enc === 'hex') - return utils.toHex32(this.h, 'little'); - else - return utils.split32(this.h, 'little'); - }; - - function f(j, x, y, z) { - if (j <= 15) - return x ^ y ^ z; - else if (j <= 31) - return (x & y) | ((~x) & z); - else if (j <= 47) - return (x | (~y)) ^ z; - else if (j <= 63) - return (x & z) | (y & (~z)); - else - return x ^ (y | (~z)); - } - - function K(j) { - if (j <= 15) - return 0x00000000; - else if (j <= 31) - return 0x5a827999; - else if (j <= 47) - return 0x6ed9eba1; - else if (j <= 63) - return 0x8f1bbcdc; - else - return 0xa953fd4e; - } - - function Kh(j) { - if (j <= 15) - return 0x50a28be6; - else if (j <= 31) - return 0x5c4dd124; - else if (j <= 47) - return 0x6d703ef3; - else if (j <= 63) - return 0x7a6d76e9; - else - return 0x00000000; - } - - var r = [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, - 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, - 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, - 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 - ]; - - var rh = [ - 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, - 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, - 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, - 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, - 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 - ]; - - var s = [ - 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, - 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, - 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, - 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, - 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 - ]; - - var sh = [ - 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, - 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, - 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, - 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, - 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 - ]; - - var ripemd = { - ripemd160: ripemd160 - }; - - /** - * A fast MD5 JavaScript implementation - * Copyright (c) 2012 Joseph Myers - * http://www.myersdaily.org/joseph/javascript/md5-text.html - * - * Permission to use, copy, modify, and distribute this software - * and its documentation for any purposes and without - * fee is hereby granted provided that this copyright notice - * appears in all copies. - * - * Of course, this soft is provided "as is" without express or implied - * warranty of any kind. - */ - - // MD5 Digest - async function md5(entree) { - const digest = md51(util.uint8ArrayToString(entree)); - return util.hexToUint8Array(hex(digest)); - } - - function md5cycle(x, k) { - let a = x[0]; - let b = x[1]; - let c = x[2]; - let d = x[3]; - - a = ff(a, b, c, d, k[0], 7, -680876936); - d = ff(d, a, b, c, k[1], 12, -389564586); - c = ff(c, d, a, b, k[2], 17, 606105819); - b = ff(b, c, d, a, k[3], 22, -1044525330); - a = ff(a, b, c, d, k[4], 7, -176418897); - d = ff(d, a, b, c, k[5], 12, 1200080426); - c = ff(c, d, a, b, k[6], 17, -1473231341); - b = ff(b, c, d, a, k[7], 22, -45705983); - a = ff(a, b, c, d, k[8], 7, 1770035416); - d = ff(d, a, b, c, k[9], 12, -1958414417); - c = ff(c, d, a, b, k[10], 17, -42063); - b = ff(b, c, d, a, k[11], 22, -1990404162); - a = ff(a, b, c, d, k[12], 7, 1804603682); - d = ff(d, a, b, c, k[13], 12, -40341101); - c = ff(c, d, a, b, k[14], 17, -1502002290); - b = ff(b, c, d, a, k[15], 22, 1236535329); - - a = gg(a, b, c, d, k[1], 5, -165796510); - d = gg(d, a, b, c, k[6], 9, -1069501632); - c = gg(c, d, a, b, k[11], 14, 643717713); - b = gg(b, c, d, a, k[0], 20, -373897302); - a = gg(a, b, c, d, k[5], 5, -701558691); - d = gg(d, a, b, c, k[10], 9, 38016083); - c = gg(c, d, a, b, k[15], 14, -660478335); - b = gg(b, c, d, a, k[4], 20, -405537848); - a = gg(a, b, c, d, k[9], 5, 568446438); - d = gg(d, a, b, c, k[14], 9, -1019803690); - c = gg(c, d, a, b, k[3], 14, -187363961); - b = gg(b, c, d, a, k[8], 20, 1163531501); - a = gg(a, b, c, d, k[13], 5, -1444681467); - d = gg(d, a, b, c, k[2], 9, -51403784); - c = gg(c, d, a, b, k[7], 14, 1735328473); - b = gg(b, c, d, a, k[12], 20, -1926607734); - - a = hh(a, b, c, d, k[5], 4, -378558); - d = hh(d, a, b, c, k[8], 11, -2022574463); - c = hh(c, d, a, b, k[11], 16, 1839030562); - b = hh(b, c, d, a, k[14], 23, -35309556); - a = hh(a, b, c, d, k[1], 4, -1530992060); - d = hh(d, a, b, c, k[4], 11, 1272893353); - c = hh(c, d, a, b, k[7], 16, -155497632); - b = hh(b, c, d, a, k[10], 23, -1094730640); - a = hh(a, b, c, d, k[13], 4, 681279174); - d = hh(d, a, b, c, k[0], 11, -358537222); - c = hh(c, d, a, b, k[3], 16, -722521979); - b = hh(b, c, d, a, k[6], 23, 76029189); - a = hh(a, b, c, d, k[9], 4, -640364487); - d = hh(d, a, b, c, k[12], 11, -421815835); - c = hh(c, d, a, b, k[15], 16, 530742520); - b = hh(b, c, d, a, k[2], 23, -995338651); - - a = ii(a, b, c, d, k[0], 6, -198630844); - d = ii(d, a, b, c, k[7], 10, 1126891415); - c = ii(c, d, a, b, k[14], 15, -1416354905); - b = ii(b, c, d, a, k[5], 21, -57434055); - a = ii(a, b, c, d, k[12], 6, 1700485571); - d = ii(d, a, b, c, k[3], 10, -1894986606); - c = ii(c, d, a, b, k[10], 15, -1051523); - b = ii(b, c, d, a, k[1], 21, -2054922799); - a = ii(a, b, c, d, k[8], 6, 1873313359); - d = ii(d, a, b, c, k[15], 10, -30611744); - c = ii(c, d, a, b, k[6], 15, -1560198380); - b = ii(b, c, d, a, k[13], 21, 1309151649); - a = ii(a, b, c, d, k[4], 6, -145523070); - d = ii(d, a, b, c, k[11], 10, -1120210379); - c = ii(c, d, a, b, k[2], 15, 718787259); - b = ii(b, c, d, a, k[9], 21, -343485551); - - x[0] = add32(a, x[0]); - x[1] = add32(b, x[1]); - x[2] = add32(c, x[2]); - x[3] = add32(d, x[3]); - } - - function cmn(q, a, b, x, s, t) { - a = add32(add32(a, q), add32(x, t)); - return add32((a << s) | (a >>> (32 - s)), b); - } - - function ff(a, b, c, d, x, s, t) { - return cmn((b & c) | ((~b) & d), a, b, x, s, t); - } - - function gg(a, b, c, d, x, s, t) { - return cmn((b & d) | (c & (~d)), a, b, x, s, t); - } - - function hh(a, b, c, d, x, s, t) { - return cmn(b ^ c ^ d, a, b, x, s, t); - } - - function ii(a, b, c, d, x, s, t) { - return cmn(c ^ (b | (~d)), a, b, x, s, t); - } - - function md51(s) { - const n = s.length; - const state = [1732584193, -271733879, -1732584194, 271733878]; - let i; - for (i = 64; i <= s.length; i += 64) { - md5cycle(state, md5blk(s.substring(i - 64, i))); - } - s = s.substring(i - 64); - const tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; - for (i = 0; i < s.length; i++) { - tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3); - } - tail[i >> 2] |= 0x80 << ((i % 4) << 3); - if (i > 55) { - md5cycle(state, tail); - for (i = 0; i < 16; i++) { - tail[i] = 0; - } - } - tail[14] = n * 8; - md5cycle(state, tail); - return state; - } - - /* there needs to be support for Unicode here, - * unless we pretend that we can redefine the MD-5 - * algorithm for multi-byte characters (perhaps - * by adding every four 16-bit characters and - * shortening the sum to 32 bits). Otherwise - * I suggest performing MD-5 as if every character - * was two bytes--e.g., 0040 0025 = @%--but then - * how will an ordinary MD-5 sum be matched? - * There is no way to standardize text to something - * like UTF-8 before transformation; speed cost is - * utterly prohibitive. The JavaScript standard - * itself needs to look at this: it should start - * providing access to strings as preformed UTF-8 - * 8-bit unsigned value arrays. - */ - function md5blk(s) { /* I figured global was faster. */ - const md5blks = []; - let i; /* Andy King said do it this way. */ - for (i = 0; i < 64; i += 4) { - md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << - 24); - } - return md5blks; - } - - const hex_chr = '0123456789abcdef'.split(''); - - function rhex(n) { - let s = ''; - let j = 0; - for (; j < 4; j++) { - s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F]; - } - return s; - } - - function hex(x) { - for (let i = 0; i < x.length; i++) { - x[i] = rhex(x[i]); - } - return x.join(''); - } - - /* this function is much faster, - so if possible we use it. Some IEs - are the only ones I know of that - need the idiotic second function, - generated by an if clause. */ - - function add32(a, b) { - return (a + b) & 0xFFFFFFFF; - } - - /** - * @fileoverview Provides an interface to hashing functions available in Node.js or external libraries. - * @see {@link https://github.com/asmcrypto/asmcrypto.js|asmCrypto} - * @see {@link https://github.com/indutny/hash.js|hash.js} - * @module crypto/hash - * @private - */ - - const webCrypto = util.getWebCrypto(); - const nodeCrypto = util.getNodeCrypto(); - - function nodeHash(type) { - return async function (data) { - const shasum = nodeCrypto.createHash(type); - return transform(data, value => { - shasum.update(value); - }, () => new Uint8Array(shasum.digest())); - }; - } - - function hashjsHash(hash, webCryptoHash) { - return async function(data, config = defaultConfig) { - if (isArrayStream(data)) { - data = await readToEnd(data); - } - if (!util.isStream(data) && webCrypto && webCryptoHash && data.length >= config.minBytesForWebCrypto) { - return new Uint8Array(await webCrypto.digest(webCryptoHash, data)); - } - const hashInstance = hash(); - return transform(data, value => { - hashInstance.update(value); - }, () => new Uint8Array(hashInstance.digest())); - }; - } - - function asmcryptoHash(hash, webCryptoHash) { - return async function(data, config = defaultConfig) { - if (isArrayStream(data)) { - data = await readToEnd(data); - } - if (util.isStream(data)) { - const hashInstance = new hash(); - return transform(data, value => { - hashInstance.process(value); - }, () => hashInstance.finish().result); - } else if (webCrypto && webCryptoHash && data.length >= config.minBytesForWebCrypto) { - return new Uint8Array(await webCrypto.digest(webCryptoHash, data)); - } else { - return hash.bytes(data); - } - }; - } - - let hashFunctions; - if (nodeCrypto) { // Use Node native crypto for all hash functions - hashFunctions = { - md5: nodeHash('md5'), - sha1: nodeHash('sha1'), - sha224: nodeHash('sha224'), - sha256: nodeHash('sha256'), - sha384: nodeHash('sha384'), - sha512: nodeHash('sha512'), - ripemd: nodeHash('ripemd160') - }; - } else { // Use JS fallbacks - hashFunctions = { - md5: md5, - sha1: asmcryptoHash(Sha1, (!navigator.userAgent || navigator.userAgent.indexOf('Edge') === -1) && 'SHA-1'), - sha224: hashjsHash(_224), - sha256: asmcryptoHash(Sha256, 'SHA-256'), - sha384: hashjsHash(_384, 'SHA-384'), - sha512: hashjsHash(_512, 'SHA-512'), // asmcrypto sha512 is huge. - ripemd: hashjsHash(ripemd160) - }; - } - - var hash = { - - /** @see module:md5 */ - md5: hashFunctions.md5, - /** @see asmCrypto */ - sha1: hashFunctions.sha1, - /** @see hash.js */ - sha224: hashFunctions.sha224, - /** @see asmCrypto */ - sha256: hashFunctions.sha256, - /** @see hash.js */ - sha384: hashFunctions.sha384, - /** @see asmCrypto */ - sha512: hashFunctions.sha512, - /** @see hash.js */ - ripemd: hashFunctions.ripemd, - - /** - * Create a hash on the specified data using the specified algorithm - * @param {module:enums.hash} algo - Hash algorithm type (see {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}) - * @param {Uint8Array} data - Data to be hashed - * @returns {Promise} Hash value. - */ - digest: function(algo, data) { - switch (algo) { - case enums.hash.md5: - return this.md5(data); - case enums.hash.sha1: - return this.sha1(data); - case enums.hash.ripemd: - return this.ripemd(data); - case enums.hash.sha256: - return this.sha256(data); - case enums.hash.sha384: - return this.sha384(data); - case enums.hash.sha512: - return this.sha512(data); - case enums.hash.sha224: - return this.sha224(data); - default: - throw new Error('Invalid hash function.'); - } - }, - - /** - * Returns the hash size in bytes of the specified hash algorithm type - * @param {module:enums.hash} algo - Hash algorithm type (See {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4}) - * @returns {Integer} Size in bytes of the resulting hash. - */ - getHashByteLength: function(algo) { - switch (algo) { - case enums.hash.md5: - return 16; - case enums.hash.sha1: - case enums.hash.ripemd: - return 20; - case enums.hash.sha256: - return 32; - case enums.hash.sha384: - return 48; - case enums.hash.sha512: - return 64; - case enums.hash.sha224: - return 28; - default: - throw new Error('Invalid hash algorithm.'); - } - } - }; - - class AES_CFB { - static encrypt(data, key, iv) { - return new AES_CFB(key, iv).encrypt(data); - } - static decrypt(data, key, iv) { - return new AES_CFB(key, iv).decrypt(data); - } - constructor(key, iv, aes) { - this.aes = aes ? aes : new AES(key, iv, true, 'CFB'); - delete this.aes.padding; - } - encrypt(data) { - const r1 = this.aes.AES_Encrypt_process(data); - const r2 = this.aes.AES_Encrypt_finish(); - return joinBytes(r1, r2); - } - decrypt(data) { - const r1 = this.aes.AES_Decrypt_process(data); - const r2 = this.aes.AES_Decrypt_finish(); - return joinBytes(r1, r2); - } - } - - // Modified by ProtonTech AG - - const webCrypto$1 = util.getWebCrypto(); - const nodeCrypto$1 = util.getNodeCrypto(); - - const knownAlgos = nodeCrypto$1 ? nodeCrypto$1.getCiphers() : []; - const nodeAlgos = { - idea: knownAlgos.includes('idea-cfb') ? 'idea-cfb' : undefined, /* Unused, not implemented */ - tripledes: knownAlgos.includes('des-ede3-cfb') ? 'des-ede3-cfb' : undefined, - cast5: knownAlgos.includes('cast5-cfb') ? 'cast5-cfb' : undefined, - blowfish: knownAlgos.includes('bf-cfb') ? 'bf-cfb' : undefined, - aes128: knownAlgos.includes('aes-128-cfb') ? 'aes-128-cfb' : undefined, - aes192: knownAlgos.includes('aes-192-cfb') ? 'aes-192-cfb' : undefined, - aes256: knownAlgos.includes('aes-256-cfb') ? 'aes-256-cfb' : undefined - /* twofish is not implemented in OpenSSL */ - }; - - /** - * CFB encryption - * @param {enums.symmetric} algo - block cipher algorithm - * @param {Uint8Array} key - * @param {MaybeStream} plaintext - * @param {Uint8Array} iv - * @param {Object} config - full configuration, defaults to openpgp.config - * @returns MaybeStream - */ - async function encrypt(algo, key, plaintext, iv, config) { - const algoName = enums.read(enums.symmetric, algo); - if (util.getNodeCrypto() && nodeAlgos[algoName]) { // Node crypto library. - return nodeEncrypt(algo, key, plaintext, iv); - } - if (algoName.substr(0, 3) === 'aes') { - return aesEncrypt(algo, key, plaintext, iv, config); - } - - const cipherfn = new cipher[algoName](key); - const block_size = cipherfn.blockSize; - - const blockc = iv.slice(); - let pt = new Uint8Array(); - const process = chunk => { - if (chunk) { - pt = util.concatUint8Array([pt, chunk]); - } - const ciphertext = new Uint8Array(pt.length); - let i; - let j = 0; - while (chunk ? pt.length >= block_size : pt.length) { - const encblock = cipherfn.encrypt(blockc); - for (i = 0; i < block_size; i++) { - blockc[i] = pt[i] ^ encblock[i]; - ciphertext[j++] = blockc[i]; - } - pt = pt.subarray(block_size); - } - return ciphertext.subarray(0, j); - }; - return transform(plaintext, process, process); - } - - /** - * CFB decryption - * @param {enums.symmetric} algo - block cipher algorithm - * @param {Uint8Array} key - * @param {MaybeStream} ciphertext - * @param {Uint8Array} iv - * @returns MaybeStream - */ - async function decrypt(algo, key, ciphertext, iv) { - const algoName = enums.read(enums.symmetric, algo); - if (util.getNodeCrypto() && nodeAlgos[algoName]) { // Node crypto library. - return nodeDecrypt(algo, key, ciphertext, iv); - } - if (algoName.substr(0, 3) === 'aes') { - return aesDecrypt(algo, key, ciphertext, iv); - } - - const cipherfn = new cipher[algoName](key); - const block_size = cipherfn.blockSize; - - let blockp = iv; - let ct = new Uint8Array(); - const process = chunk => { - if (chunk) { - ct = util.concatUint8Array([ct, chunk]); - } - const plaintext = new Uint8Array(ct.length); - let i; - let j = 0; - while (chunk ? ct.length >= block_size : ct.length) { - const decblock = cipherfn.encrypt(blockp); - blockp = ct; - for (i = 0; i < block_size; i++) { - plaintext[j++] = blockp[i] ^ decblock[i]; - } - ct = ct.subarray(block_size); - } - return plaintext.subarray(0, j); - }; - return transform(ciphertext, process, process); - } - - function aesEncrypt(algo, key, pt, iv, config) { - if ( - util.getWebCrypto() && - key.length !== 24 && // Chrome doesn't support 192 bit keys, see https://www.chromium.org/blink/webcrypto#TOC-AES-support - !util.isStream(pt) && - pt.length >= 3000 * config.minBytesForWebCrypto // Default to a 3MB minimum. Chrome is pretty slow for small messages, see: https://bugs.chromium.org/p/chromium/issues/detail?id=701188#c2 - ) { // Web Crypto - return webEncrypt(algo, key, pt, iv); - } - // asm.js fallback - const cfb = new AES_CFB(key, iv); - return transform(pt, value => cfb.aes.AES_Encrypt_process(value), () => cfb.aes.AES_Encrypt_finish()); - } - - function aesDecrypt(algo, key, ct, iv) { - if (util.isStream(ct)) { - const cfb = new AES_CFB(key, iv); - return transform(ct, value => cfb.aes.AES_Decrypt_process(value), () => cfb.aes.AES_Decrypt_finish()); - } - return AES_CFB.decrypt(ct, key, iv); - } - - function xorMut(a, b) { - for (let i = 0; i < a.length; i++) { - a[i] = a[i] ^ b[i]; - } - } - - async function webEncrypt(algo, key, pt, iv) { - const ALGO = 'AES-CBC'; - const _key = await webCrypto$1.importKey('raw', key, { name: ALGO }, false, ['encrypt']); - const { blockSize } = crypto.getCipher(algo); - const cbc_pt = util.concatUint8Array([new Uint8Array(blockSize), pt]); - const ct = new Uint8Array(await webCrypto$1.encrypt({ name: ALGO, iv }, _key, cbc_pt)).subarray(0, pt.length); - xorMut(ct, pt); - return ct; - } - - function nodeEncrypt(algo, key, pt, iv) { - const algoName = enums.read(enums.symmetric, algo); - const cipherObj = new nodeCrypto$1.createCipheriv(nodeAlgos[algoName], key, iv); - return transform(pt, value => new Uint8Array(cipherObj.update(value))); - } - - function nodeDecrypt(algo, key, ct, iv) { - const algoName = enums.read(enums.symmetric, algo); - const decipherObj = new nodeCrypto$1.createDecipheriv(nodeAlgos[algoName], key, iv); - return transform(ct, value => new Uint8Array(decipherObj.update(value))); - } - - var cfb = /*#__PURE__*/Object.freeze({ - __proto__: null, - encrypt: encrypt, - decrypt: decrypt - }); - - class AES_CTR { - static encrypt(data, key, nonce) { - return new AES_CTR(key, nonce).encrypt(data); - } - static decrypt(data, key, nonce) { - return new AES_CTR(key, nonce).encrypt(data); - } - constructor(key, nonce, aes) { - this.aes = aes ? aes : new AES(key, undefined, false, 'CTR'); - delete this.aes.padding; - this.AES_CTR_set_options(nonce); - } - encrypt(data) { - const r1 = this.aes.AES_Encrypt_process(data); - const r2 = this.aes.AES_Encrypt_finish(); - return joinBytes(r1, r2); - } - decrypt(data) { - const r1 = this.aes.AES_Encrypt_process(data); - const r2 = this.aes.AES_Encrypt_finish(); - return joinBytes(r1, r2); - } - AES_CTR_set_options(nonce, counter, size) { - let { asm } = this.aes.acquire_asm(); - if (size !== undefined) { - if (size < 8 || size > 48) - throw new IllegalArgumentError('illegal counter size'); - let mask = Math.pow(2, size) - 1; - asm.set_mask(0, 0, (mask / 0x100000000) | 0, mask | 0); - } - else { - size = 48; - asm.set_mask(0, 0, 0xffff, 0xffffffff); - } - if (nonce !== undefined) { - let len = nonce.length; - if (!len || len > 16) - throw new IllegalArgumentError('illegal nonce size'); - let view = new DataView(new ArrayBuffer(16)); - new Uint8Array(view.buffer).set(nonce); - asm.set_nonce(view.getUint32(0), view.getUint32(4), view.getUint32(8), view.getUint32(12)); - } - else { - throw new Error('nonce is required'); - } - if (counter !== undefined) { - if (counter < 0 || counter >= Math.pow(2, size)) - throw new IllegalArgumentError('illegal counter value'); - asm.set_counter(0, 0, (counter / 0x100000000) | 0, counter | 0); - } - } - } - - class AES_CBC { - static encrypt(data, key, padding = true, iv) { - return new AES_CBC(key, iv, padding).encrypt(data); - } - static decrypt(data, key, padding = true, iv) { - return new AES_CBC(key, iv, padding).decrypt(data); - } - constructor(key, iv, padding = true, aes) { - this.aes = aes ? aes : new AES(key, iv, padding, 'CBC'); - } - encrypt(data) { - const r1 = this.aes.AES_Encrypt_process(data); - const r2 = this.aes.AES_Encrypt_finish(); - return joinBytes(r1, r2); - } - decrypt(data) { - const r1 = this.aes.AES_Decrypt_process(data); - const r2 = this.aes.AES_Decrypt_finish(); - return joinBytes(r1, r2); - } - } - - /** - * @fileoverview This module implements AES-CMAC on top of - * native AES-CBC using either the WebCrypto API or Node.js' crypto API. - * @module crypto/cmac - * @private - */ - - const webCrypto$2 = util.getWebCrypto(); - const nodeCrypto$2 = util.getNodeCrypto(); - - - /** - * This implementation of CMAC is based on the description of OMAC in - * http://web.cs.ucdavis.edu/~rogaway/papers/eax.pdf. As per that - * document: - * - * We have made a small modification to the OMAC algorithm as it was - * originally presented, changing one of its two constants. - * Specifically, the constant 4 at line 85 was the constant 1/2 (the - * multiplicative inverse of 2) in the original definition of OMAC [14]. - * The OMAC authors indicate that they will promulgate this modification - * [15], which slightly simplifies implementations. - */ - - const blockLength = 16; - - - /** - * xor `padding` into the end of `data`. This function implements "the - * operation xor→ [which] xors the shorter string into the end of longer - * one". Since data is always as least as long as padding, we can - * simplify the implementation. - * @param {Uint8Array} data - * @param {Uint8Array} padding - */ - function rightXORMut(data, padding) { - const offset = data.length - blockLength; - for (let i = 0; i < blockLength; i++) { - data[i + offset] ^= padding[i]; - } - return data; - } - - function pad(data, padding, padding2) { - // if |M| in {n, 2n, 3n, ...} - if (data.length && data.length % blockLength === 0) { - // then return M xor→ B, - return rightXORMut(data, padding); - } - // else return (M || 10^(n−1−(|M| mod n))) xor→ P - const padded = new Uint8Array(data.length + (blockLength - data.length % blockLength)); - padded.set(data); - padded[data.length] = 0b10000000; - return rightXORMut(padded, padding2); - } - - const zeroBlock = new Uint8Array(blockLength); - - async function CMAC(key) { - const cbc = await CBC(key); - - // L ← E_K(0^n); B ← 2L; P ← 4L - const padding = util.double(await cbc(zeroBlock)); - const padding2 = util.double(padding); - - return async function(data) { - // return CBC_K(pad(M; B, P)) - return (await cbc(pad(data, padding, padding2))).subarray(-blockLength); - }; - } - - async function CBC(key) { - if (util.getWebCrypto() && key.length !== 24) { // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support - key = await webCrypto$2.importKey('raw', key, { name: 'AES-CBC', length: key.length * 8 }, false, ['encrypt']); - return async function(pt) { - const ct = await webCrypto$2.encrypt({ name: 'AES-CBC', iv: zeroBlock, length: blockLength * 8 }, key, pt); - return new Uint8Array(ct).subarray(0, ct.byteLength - blockLength); - }; - } - if (util.getNodeCrypto()) { // Node crypto library - return async function(pt) { - const en = new nodeCrypto$2.createCipheriv('aes-' + (key.length * 8) + '-cbc', key, zeroBlock); - const ct = en.update(pt); - return new Uint8Array(ct); - }; - } - // asm.js fallback - return async function(pt) { - return AES_CBC.encrypt(pt, key, false, zeroBlock); - }; - } - - // OpenPGP.js - An OpenPGP implementation in javascript - - const webCrypto$3 = util.getWebCrypto(); - const nodeCrypto$3 = util.getNodeCrypto(); - const Buffer$1 = util.getNodeBuffer(); - - - const blockLength$1 = 16; - const ivLength = blockLength$1; - const tagLength = blockLength$1; - - const zero = new Uint8Array(blockLength$1); - const one = new Uint8Array(blockLength$1); one[blockLength$1 - 1] = 1; - const two = new Uint8Array(blockLength$1); two[blockLength$1 - 1] = 2; - - async function OMAC(key) { - const cmac = await CMAC(key); - return function(t, message) { - return cmac(util.concatUint8Array([t, message])); - }; - } - - async function CTR(key) { - if ( - util.getWebCrypto() && - key.length !== 24 && // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support - (!navigator.userAgent || navigator.userAgent.indexOf('Edge') === -1) - ) { - key = await webCrypto$3.importKey('raw', key, { name: 'AES-CTR', length: key.length * 8 }, false, ['encrypt']); - return async function(pt, iv) { - const ct = await webCrypto$3.encrypt({ name: 'AES-CTR', counter: iv, length: blockLength$1 * 8 }, key, pt); - return new Uint8Array(ct); - }; - } - if (util.getNodeCrypto()) { // Node crypto library - return async function(pt, iv) { - const en = new nodeCrypto$3.createCipheriv('aes-' + (key.length * 8) + '-ctr', key, iv); - const ct = Buffer$1.concat([en.update(pt), en.final()]); - return new Uint8Array(ct); - }; - } - // asm.js fallback - return async function(pt, iv) { - return AES_CTR.encrypt(pt, key, iv); - }; - } - - - /** - * Class to en/decrypt using EAX mode. - * @param {enums.symmetric} cipher - The symmetric cipher algorithm to use - * @param {Uint8Array} key - The encryption key - */ - async function EAX(cipher, key) { - if (cipher !== enums.symmetric.aes128 && - cipher !== enums.symmetric.aes192 && - cipher !== enums.symmetric.aes256) { - throw new Error('EAX mode supports only AES cipher'); - } - - const [ - omac, - ctr - ] = await Promise.all([ - OMAC(key), - CTR(key) - ]); - - return { - /** - * Encrypt plaintext input. - * @param {Uint8Array} plaintext - The cleartext input to be encrypted - * @param {Uint8Array} nonce - The nonce (16 bytes) - * @param {Uint8Array} adata - Associated data to sign - * @returns {Promise} The ciphertext output. - */ - encrypt: async function(plaintext, nonce, adata) { - const [ - omacNonce, - omacAdata - ] = await Promise.all([ - omac(zero, nonce), - omac(one, adata) - ]); - const ciphered = await ctr(plaintext, omacNonce); - const omacCiphered = await omac(two, ciphered); - const tag = omacCiphered; // Assumes that omac(*).length === tagLength. - for (let i = 0; i < tagLength; i++) { - tag[i] ^= omacAdata[i] ^ omacNonce[i]; - } - return util.concatUint8Array([ciphered, tag]); - }, - - /** - * Decrypt ciphertext input. - * @param {Uint8Array} ciphertext - The ciphertext input to be decrypted - * @param {Uint8Array} nonce - The nonce (16 bytes) - * @param {Uint8Array} adata - Associated data to verify - * @returns {Promise} The plaintext output. - */ - decrypt: async function(ciphertext, nonce, adata) { - if (ciphertext.length < tagLength) throw new Error('Invalid EAX ciphertext'); - const ciphered = ciphertext.subarray(0, -tagLength); - const ctTag = ciphertext.subarray(-tagLength); - const [ - omacNonce, - omacAdata, - omacCiphered - ] = await Promise.all([ - omac(zero, nonce), - omac(one, adata), - omac(two, ciphered) - ]); - const tag = omacCiphered; // Assumes that omac(*).length === tagLength. - for (let i = 0; i < tagLength; i++) { - tag[i] ^= omacAdata[i] ^ omacNonce[i]; - } - if (!util.equalsUint8Array(ctTag, tag)) throw new Error('Authentication tag mismatch'); - const plaintext = await ctr(ciphered, omacNonce); - return plaintext; - } - }; - } - - - /** - * Get EAX nonce as defined by {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.1|RFC4880bis-04, section 5.16.1}. - * @param {Uint8Array} iv - The initialization vector (16 bytes) - * @param {Uint8Array} chunkIndex - The chunk index (8 bytes) - */ - EAX.getNonce = function(iv, chunkIndex) { - const nonce = iv.slice(); - for (let i = 0; i < chunkIndex.length; i++) { - nonce[8 + i] ^= chunkIndex[i]; - } - return nonce; - }; - - EAX.blockLength = blockLength$1; - EAX.ivLength = ivLength; - EAX.tagLength = tagLength; - - // OpenPGP.js - An OpenPGP implementation in javascript - - const blockLength$2 = 16; - const ivLength$1 = 15; - - // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.2: - // While OCB [RFC7253] allows the authentication tag length to be of any - // number up to 128 bits long, this document requires a fixed - // authentication tag length of 128 bits (16 octets) for simplicity. - const tagLength$1 = 16; - - - function ntz(n) { - let ntz = 0; - for (let i = 1; (n & i) === 0; i <<= 1) { - ntz++; - } - return ntz; - } - - function xorMut$1(S, T) { - for (let i = 0; i < S.length; i++) { - S[i] ^= T[i]; - } - return S; - } - - function xor(S, T) { - return xorMut$1(S.slice(), T); - } - - const zeroBlock$1 = new Uint8Array(blockLength$2); - const one$1 = new Uint8Array([1]); - - /** - * Class to en/decrypt using OCB mode. - * @param {enums.symmetric} cipher - The symmetric cipher algorithm to use - * @param {Uint8Array} key - The encryption key - */ - async function OCB(cipher$1, key) { - - let maxNtz = 0; - let encipher; - let decipher; - let mask; - - constructKeyVariables(cipher$1, key); - - function constructKeyVariables(cipher$1, key) { - const cipherName = enums.read(enums.symmetric, cipher$1); - const aes = new cipher[cipherName](key); - encipher = aes.encrypt.bind(aes); - decipher = aes.decrypt.bind(aes); - - const mask_x = encipher(zeroBlock$1); - const mask_$ = util.double(mask_x); - mask = []; - mask[0] = util.double(mask_$); - - - mask.x = mask_x; - mask.$ = mask_$; - } - - function extendKeyVariables(text, adata) { - const newMaxNtz = util.nbits(Math.max(text.length, adata.length) / blockLength$2 | 0) - 1; - for (let i = maxNtz + 1; i <= newMaxNtz; i++) { - mask[i] = util.double(mask[i - 1]); - } - maxNtz = newMaxNtz; - } - - function hash(adata) { - if (!adata.length) { - // Fast path - return zeroBlock$1; - } - - // - // Consider A as a sequence of 128-bit blocks - // - const m = adata.length / blockLength$2 | 0; - - const offset = new Uint8Array(blockLength$2); - const sum = new Uint8Array(blockLength$2); - for (let i = 0; i < m; i++) { - xorMut$1(offset, mask[ntz(i + 1)]); - xorMut$1(sum, encipher(xor(offset, adata))); - adata = adata.subarray(blockLength$2); - } - - // - // Process any final partial block; compute final hash value - // - if (adata.length) { - xorMut$1(offset, mask.x); - - const cipherInput = new Uint8Array(blockLength$2); - cipherInput.set(adata, 0); - cipherInput[adata.length] = 0b10000000; - xorMut$1(cipherInput, offset); - - xorMut$1(sum, encipher(cipherInput)); - } - - return sum; - } - - /** - * Encrypt/decrypt data. - * @param {encipher|decipher} fn - Encryption/decryption block cipher function - * @param {Uint8Array} text - The cleartext or ciphertext (without tag) input - * @param {Uint8Array} nonce - The nonce (15 bytes) - * @param {Uint8Array} adata - Associated data to sign - * @returns {Promise} The ciphertext or plaintext output, with tag appended in both cases. - */ - function crypt(fn, text, nonce, adata) { - // - // Consider P as a sequence of 128-bit blocks - // - const m = text.length / blockLength$2 | 0; - - // - // Key-dependent variables - // - extendKeyVariables(text, adata); - - // - // Nonce-dependent and per-encryption variables - // - // Nonce = num2str(TAGLEN mod 128,7) || zeros(120-bitlen(N)) || 1 || N - // Note: We assume here that tagLength mod 16 == 0. - const paddedNonce = util.concatUint8Array([zeroBlock$1.subarray(0, ivLength$1 - nonce.length), one$1, nonce]); - // bottom = str2num(Nonce[123..128]) - const bottom = paddedNonce[blockLength$2 - 1] & 0b111111; - // Ktop = ENCIPHER(K, Nonce[1..122] || zeros(6)) - paddedNonce[blockLength$2 - 1] &= 0b11000000; - const kTop = encipher(paddedNonce); - // Stretch = Ktop || (Ktop[1..64] xor Ktop[9..72]) - const stretched = util.concatUint8Array([kTop, xor(kTop.subarray(0, 8), kTop.subarray(1, 9))]); - // Offset_0 = Stretch[1+bottom..128+bottom] - const offset = util.shiftRight(stretched.subarray(0 + (bottom >> 3), 17 + (bottom >> 3)), 8 - (bottom & 7)).subarray(1); - // Checksum_0 = zeros(128) - const checksum = new Uint8Array(blockLength$2); - - const ct = new Uint8Array(text.length + tagLength$1); - - // - // Process any whole blocks - // - let i; - let pos = 0; - for (i = 0; i < m; i++) { - // Offset_i = Offset_{i-1} xor L_{ntz(i)} - xorMut$1(offset, mask[ntz(i + 1)]); - // C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) - // P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i) - ct.set(xorMut$1(fn(xor(offset, text)), offset), pos); - // Checksum_i = Checksum_{i-1} xor P_i - xorMut$1(checksum, fn === encipher ? text : ct.subarray(pos)); - - text = text.subarray(blockLength$2); - pos += blockLength$2; - } - - // - // Process any final partial block and compute raw tag - // - if (text.length) { - // Offset_* = Offset_m xor L_* - xorMut$1(offset, mask.x); - // Pad = ENCIPHER(K, Offset_*) - const padding = encipher(offset); - // C_* = P_* xor Pad[1..bitlen(P_*)] - ct.set(xor(text, padding), pos); - - // Checksum_* = Checksum_m xor (P_* || 1 || new Uint8Array(127-bitlen(P_*))) - const xorInput = new Uint8Array(blockLength$2); - xorInput.set(fn === encipher ? text : ct.subarray(pos, -tagLength$1), 0); - xorInput[text.length] = 0b10000000; - xorMut$1(checksum, xorInput); - pos += text.length; - } - // Tag = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) xor HASH(K,A) - const tag = xorMut$1(encipher(xorMut$1(xorMut$1(checksum, offset), mask.$)), hash(adata)); - - // - // Assemble ciphertext - // - // C = C_1 || C_2 || ... || C_m || C_* || Tag[1..TAGLEN] - ct.set(tag, pos); - return ct; - } - - - return { - /** - * Encrypt plaintext input. - * @param {Uint8Array} plaintext - The cleartext input to be encrypted - * @param {Uint8Array} nonce - The nonce (15 bytes) - * @param {Uint8Array} adata - Associated data to sign - * @returns {Promise} The ciphertext output. - */ - encrypt: async function(plaintext, nonce, adata) { - return crypt(encipher, plaintext, nonce, adata); - }, - - /** - * Decrypt ciphertext input. - * @param {Uint8Array} ciphertext - The ciphertext input to be decrypted - * @param {Uint8Array} nonce - The nonce (15 bytes) - * @param {Uint8Array} adata - Associated data to sign - * @returns {Promise} The ciphertext output. - */ - decrypt: async function(ciphertext, nonce, adata) { - if (ciphertext.length < tagLength$1) throw new Error('Invalid OCB ciphertext'); - - const tag = ciphertext.subarray(-tagLength$1); - ciphertext = ciphertext.subarray(0, -tagLength$1); - - const crypted = crypt(decipher, ciphertext, nonce, adata); - // if (Tag[1..TAGLEN] == T) - if (util.equalsUint8Array(tag, crypted.subarray(-tagLength$1))) { - return crypted.subarray(0, -tagLength$1); - } - throw new Error('Authentication tag mismatch'); - } - }; - } - - - /** - * Get OCB nonce as defined by {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.16.2|RFC4880bis-04, section 5.16.2}. - * @param {Uint8Array} iv - The initialization vector (15 bytes) - * @param {Uint8Array} chunkIndex - The chunk index (8 bytes) - */ - OCB.getNonce = function(iv, chunkIndex) { - const nonce = iv.slice(); - for (let i = 0; i < chunkIndex.length; i++) { - nonce[7 + i] ^= chunkIndex[i]; - } - return nonce; - }; - - OCB.blockLength = blockLength$2; - OCB.ivLength = ivLength$1; - OCB.tagLength = tagLength$1; - - const _AES_GCM_data_maxLength = 68719476704; // 2^36 - 2^5 - class AES_GCM { - constructor(key, nonce, adata, tagSize = 16, aes) { - this.tagSize = tagSize; - this.gamma0 = 0; - this.counter = 1; - this.aes = aes ? aes : new AES(key, undefined, false, 'CTR'); - let { asm, heap } = this.aes.acquire_asm(); - // Init GCM - asm.gcm_init(); - // Tag size - if (this.tagSize < 4 || this.tagSize > 16) - throw new IllegalArgumentError('illegal tagSize value'); - // Nonce - const noncelen = nonce.length || 0; - const noncebuf = new Uint8Array(16); - if (noncelen !== 12) { - this._gcm_mac_process(nonce); - heap[0] = 0; - heap[1] = 0; - heap[2] = 0; - heap[3] = 0; - heap[4] = 0; - heap[5] = 0; - heap[6] = 0; - heap[7] = 0; - heap[8] = 0; - heap[9] = 0; - heap[10] = 0; - heap[11] = noncelen >>> 29; - heap[12] = (noncelen >>> 21) & 255; - heap[13] = (noncelen >>> 13) & 255; - heap[14] = (noncelen >>> 5) & 255; - heap[15] = (noncelen << 3) & 255; - asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16); - asm.get_iv(AES_asm.HEAP_DATA); - asm.set_iv(0, 0, 0, 0); - noncebuf.set(heap.subarray(0, 16)); - } - else { - noncebuf.set(nonce); - noncebuf[15] = 1; - } - const nonceview = new DataView(noncebuf.buffer); - this.gamma0 = nonceview.getUint32(12); - asm.set_nonce(nonceview.getUint32(0), nonceview.getUint32(4), nonceview.getUint32(8), 0); - asm.set_mask(0, 0, 0, 0xffffffff); - // Associated data - if (adata !== undefined) { - if (adata.length > _AES_GCM_data_maxLength) - throw new IllegalArgumentError('illegal adata length'); - if (adata.length) { - this.adata = adata; - this._gcm_mac_process(adata); - } - else { - this.adata = undefined; - } - } - else { - this.adata = undefined; - } - // Counter - if (this.counter < 1 || this.counter > 0xffffffff) - throw new RangeError('counter must be a positive 32-bit integer'); - asm.set_counter(0, 0, 0, (this.gamma0 + this.counter) | 0); - } - static encrypt(cleartext, key, nonce, adata, tagsize) { - return new AES_GCM(key, nonce, adata, tagsize).encrypt(cleartext); - } - static decrypt(ciphertext, key, nonce, adata, tagsize) { - return new AES_GCM(key, nonce, adata, tagsize).decrypt(ciphertext); - } - encrypt(data) { - return this.AES_GCM_encrypt(data); - } - decrypt(data) { - return this.AES_GCM_decrypt(data); - } - AES_GCM_Encrypt_process(data) { - let dpos = 0; - let dlen = data.length || 0; - let { asm, heap } = this.aes.acquire_asm(); - let counter = this.counter; - let pos = this.aes.pos; - let len = this.aes.len; - let rpos = 0; - let rlen = (len + dlen) & -16; - let wlen = 0; - if (((counter - 1) << 4) + len + dlen > _AES_GCM_data_maxLength) - throw new RangeError('counter overflow'); - const result = new Uint8Array(rlen); - while (dlen > 0) { - wlen = _heap_write(heap, pos + len, data, dpos, dlen); - len += wlen; - dpos += wlen; - dlen -= wlen; - wlen = asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, len); - wlen = asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, wlen); - if (wlen) - result.set(heap.subarray(pos, pos + wlen), rpos); - counter += wlen >>> 4; - rpos += wlen; - if (wlen < len) { - pos += wlen; - len -= wlen; - } - else { - pos = 0; - len = 0; - } - } - this.counter = counter; - this.aes.pos = pos; - this.aes.len = len; - return result; - } - AES_GCM_Encrypt_finish() { - let { asm, heap } = this.aes.acquire_asm(); - let counter = this.counter; - let tagSize = this.tagSize; - let adata = this.adata; - let pos = this.aes.pos; - let len = this.aes.len; - const result = new Uint8Array(len + tagSize); - asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, (len + 15) & -16); - if (len) - result.set(heap.subarray(pos, pos + len)); - let i = len; - for (; i & 15; i++) - heap[pos + i] = 0; - asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, i); - const alen = adata !== undefined ? adata.length : 0; - const clen = ((counter - 1) << 4) + len; - heap[0] = 0; - heap[1] = 0; - heap[2] = 0; - heap[3] = alen >>> 29; - heap[4] = alen >>> 21; - heap[5] = (alen >>> 13) & 255; - heap[6] = (alen >>> 5) & 255; - heap[7] = (alen << 3) & 255; - heap[8] = heap[9] = heap[10] = 0; - heap[11] = clen >>> 29; - heap[12] = (clen >>> 21) & 255; - heap[13] = (clen >>> 13) & 255; - heap[14] = (clen >>> 5) & 255; - heap[15] = (clen << 3) & 255; - asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16); - asm.get_iv(AES_asm.HEAP_DATA); - asm.set_counter(0, 0, 0, this.gamma0); - asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16); - result.set(heap.subarray(0, tagSize), len); - this.counter = 1; - this.aes.pos = 0; - this.aes.len = 0; - return result; - } - AES_GCM_Decrypt_process(data) { - let dpos = 0; - let dlen = data.length || 0; - let { asm, heap } = this.aes.acquire_asm(); - let counter = this.counter; - let tagSize = this.tagSize; - let pos = this.aes.pos; - let len = this.aes.len; - let rpos = 0; - let rlen = len + dlen > tagSize ? (len + dlen - tagSize) & -16 : 0; - let tlen = len + dlen - rlen; - let wlen = 0; - if (((counter - 1) << 4) + len + dlen > _AES_GCM_data_maxLength) - throw new RangeError('counter overflow'); - const result = new Uint8Array(rlen); - while (dlen > tlen) { - wlen = _heap_write(heap, pos + len, data, dpos, dlen - tlen); - len += wlen; - dpos += wlen; - dlen -= wlen; - wlen = asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, wlen); - wlen = asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, wlen); - if (wlen) - result.set(heap.subarray(pos, pos + wlen), rpos); - counter += wlen >>> 4; - rpos += wlen; - pos = 0; - len = 0; - } - if (dlen > 0) { - len += _heap_write(heap, 0, data, dpos, dlen); - } - this.counter = counter; - this.aes.pos = pos; - this.aes.len = len; - return result; - } - AES_GCM_Decrypt_finish() { - let { asm, heap } = this.aes.acquire_asm(); - let tagSize = this.tagSize; - let adata = this.adata; - let counter = this.counter; - let pos = this.aes.pos; - let len = this.aes.len; - let rlen = len - tagSize; - if (len < tagSize) - throw new IllegalStateError('authentication tag not found'); - const result = new Uint8Array(rlen); - const atag = new Uint8Array(heap.subarray(pos + rlen, pos + len)); - let i = rlen; - for (; i & 15; i++) - heap[pos + i] = 0; - asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, i); - asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, i); - if (rlen) - result.set(heap.subarray(pos, pos + rlen)); - const alen = adata !== undefined ? adata.length : 0; - const clen = ((counter - 1) << 4) + len - tagSize; - heap[0] = 0; - heap[1] = 0; - heap[2] = 0; - heap[3] = alen >>> 29; - heap[4] = alen >>> 21; - heap[5] = (alen >>> 13) & 255; - heap[6] = (alen >>> 5) & 255; - heap[7] = (alen << 3) & 255; - heap[8] = heap[9] = heap[10] = 0; - heap[11] = clen >>> 29; - heap[12] = (clen >>> 21) & 255; - heap[13] = (clen >>> 13) & 255; - heap[14] = (clen >>> 5) & 255; - heap[15] = (clen << 3) & 255; - asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16); - asm.get_iv(AES_asm.HEAP_DATA); - asm.set_counter(0, 0, 0, this.gamma0); - asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16); - let acheck = 0; - for (let i = 0; i < tagSize; ++i) - acheck |= atag[i] ^ heap[i]; - if (acheck) - throw new SecurityError('data integrity check failed'); - this.counter = 1; - this.aes.pos = 0; - this.aes.len = 0; - return result; - } - AES_GCM_decrypt(data) { - const result1 = this.AES_GCM_Decrypt_process(data); - const result2 = this.AES_GCM_Decrypt_finish(); - const result = new Uint8Array(result1.length + result2.length); - if (result1.length) - result.set(result1); - if (result2.length) - result.set(result2, result1.length); - return result; - } - AES_GCM_encrypt(data) { - const result1 = this.AES_GCM_Encrypt_process(data); - const result2 = this.AES_GCM_Encrypt_finish(); - const result = new Uint8Array(result1.length + result2.length); - if (result1.length) - result.set(result1); - if (result2.length) - result.set(result2, result1.length); - return result; - } - _gcm_mac_process(data) { - let { asm, heap } = this.aes.acquire_asm(); - let dpos = 0; - let dlen = data.length || 0; - let wlen = 0; - while (dlen > 0) { - wlen = _heap_write(heap, 0, data, dpos, dlen); - dpos += wlen; - dlen -= wlen; - while (wlen & 15) - heap[wlen++] = 0; - asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, wlen); - } - } - } - - // OpenPGP.js - An OpenPGP implementation in javascript - - const webCrypto$4 = util.getWebCrypto(); - const nodeCrypto$4 = util.getNodeCrypto(); - const Buffer$2 = util.getNodeBuffer(); - - const blockLength$3 = 16; - const ivLength$2 = 12; // size of the IV in bytes - const tagLength$2 = 16; // size of the tag in bytes - const ALGO = 'AES-GCM'; - - /** - * Class to en/decrypt using GCM mode. - * @param {enums.symmetric} cipher - The symmetric cipher algorithm to use - * @param {Uint8Array} key - The encryption key - */ - async function GCM(cipher, key) { - if (cipher !== enums.symmetric.aes128 && - cipher !== enums.symmetric.aes192 && - cipher !== enums.symmetric.aes256) { - throw new Error('GCM mode supports only AES cipher'); - } - - if (util.getWebCrypto() && key.length !== 24) { // WebCrypto (no 192 bit support) see: https://www.chromium.org/blink/webcrypto#TOC-AES-support - const _key = await webCrypto$4.importKey('raw', key, { name: ALGO }, false, ['encrypt', 'decrypt']); - - return { - encrypt: async function(pt, iv, adata = new Uint8Array()) { - if ( - !pt.length || - // iOS does not support GCM-en/decrypting empty messages - // Also, synchronous en/decryption might be faster in this case. - (!adata.length && navigator.userAgent && navigator.userAgent.indexOf('Edge') !== -1) - // Edge does not support GCM-en/decrypting without ADATA - ) { - return AES_GCM.encrypt(pt, key, iv, adata); - } - const ct = await webCrypto$4.encrypt({ name: ALGO, iv, additionalData: adata, tagLength: tagLength$2 * 8 }, _key, pt); - return new Uint8Array(ct); - }, - - decrypt: async function(ct, iv, adata = new Uint8Array()) { - if ( - ct.length === tagLength$2 || - // iOS does not support GCM-en/decrypting empty messages - // Also, synchronous en/decryption might be faster in this case. - (!adata.length && navigator.userAgent && navigator.userAgent.indexOf('Edge') !== -1) - // Edge does not support GCM-en/decrypting without ADATA - ) { - return AES_GCM.decrypt(ct, key, iv, adata); - } - const pt = await webCrypto$4.decrypt({ name: ALGO, iv, additionalData: adata, tagLength: tagLength$2 * 8 }, _key, ct); - return new Uint8Array(pt); - } - }; - } - - if (util.getNodeCrypto()) { // Node crypto library - return { - encrypt: async function(pt, iv, adata = new Uint8Array()) { - const en = new nodeCrypto$4.createCipheriv('aes-' + (key.length * 8) + '-gcm', key, iv); - en.setAAD(adata); - const ct = Buffer$2.concat([en.update(pt), en.final(), en.getAuthTag()]); // append auth tag to ciphertext - return new Uint8Array(ct); - }, - - decrypt: async function(ct, iv, adata = new Uint8Array()) { - const de = new nodeCrypto$4.createDecipheriv('aes-' + (key.length * 8) + '-gcm', key, iv); - de.setAAD(adata); - de.setAuthTag(ct.slice(ct.length - tagLength$2, ct.length)); // read auth tag at end of ciphertext - const pt = Buffer$2.concat([de.update(ct.slice(0, ct.length - tagLength$2)), de.final()]); - return new Uint8Array(pt); - } - }; - } - - return { - encrypt: async function(pt, iv, adata) { - return AES_GCM.encrypt(pt, key, iv, adata); - }, - - decrypt: async function(ct, iv, adata) { - return AES_GCM.decrypt(ct, key, iv, adata); - } - }; - } - - - /** - * Get GCM nonce. Note: this operation is not defined by the standard. - * A future version of the standard may define GCM mode differently, - * hopefully under a different ID (we use Private/Experimental algorithm - * ID 100) so that we can maintain backwards compatibility. - * @param {Uint8Array} iv - The initialization vector (12 bytes) - * @param {Uint8Array} chunkIndex - The chunk index (8 bytes) - */ - GCM.getNonce = function(iv, chunkIndex) { - const nonce = iv.slice(); - for (let i = 0; i < chunkIndex.length; i++) { - nonce[4 + i] ^= chunkIndex[i]; - } - return nonce; - }; - - GCM.blockLength = blockLength$3; - GCM.ivLength = ivLength$2; - GCM.tagLength = tagLength$2; - - /** - * @fileoverview Cipher modes - * @module crypto/mode - * @private - */ - - var mode = { - /** @see module:crypto/mode/cfb */ - cfb: cfb, - /** @see module:crypto/mode/gcm */ - gcm: GCM, - experimentalGCM: GCM, - /** @see module:crypto/mode/eax */ - eax: EAX, - /** @see module:crypto/mode/ocb */ - ocb: OCB - }; - - var naclFastLight = createCommonjsModule(function (module) { - /*jshint bitwise: false*/ - - (function(nacl) { - - // Ported in 2014 by Dmitry Chestnykh and Devi Mandiri. - // Public domain. - // - // Implementation derived from TweetNaCl version 20140427. - // See for details: http://tweetnacl.cr.yp.to/ - - var gf = function(init) { - var i, r = new Float64Array(16); - if (init) for (i = 0; i < init.length; i++) r[i] = init[i]; - return r; - }; - - // Pluggable, initialized in high-level API below. - var randombytes = function(/* x, n */) { throw new Error('no PRNG'); }; - - var _9 = new Uint8Array(32); _9[0] = 9; - - var gf0 = gf(), - gf1 = gf([1]), - _121665 = gf([0xdb41, 1]), - D = gf([0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203]), - D2 = gf([0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406]), - X = gf([0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169]), - Y = gf([0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666]), - I = gf([0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83]); - - function vn(x, xi, y, yi, n) { - var i,d = 0; - for (i = 0; i < n; i++) d |= x[xi+i]^y[yi+i]; - return (1 & ((d - 1) >>> 8)) - 1; - } - - function crypto_verify_32(x, xi, y, yi) { - return vn(x,xi,y,yi,32); - } - - function set25519(r, a) { - var i; - for (i = 0; i < 16; i++) r[i] = a[i]|0; - } - - function car25519(o) { - var i, v, c = 1; - for (i = 0; i < 16; i++) { - v = o[i] + c + 65535; - c = Math.floor(v / 65536); - o[i] = v - c * 65536; - } - o[0] += c-1 + 37 * (c-1); - } - - function sel25519(p, q, b) { - var t, c = ~(b-1); - for (var i = 0; i < 16; i++) { - t = c & (p[i] ^ q[i]); - p[i] ^= t; - q[i] ^= t; - } - } - - function pack25519(o, n) { - var i, j, b; - var m = gf(), t = gf(); - for (i = 0; i < 16; i++) t[i] = n[i]; - car25519(t); - car25519(t); - car25519(t); - for (j = 0; j < 2; j++) { - m[0] = t[0] - 0xffed; - for (i = 1; i < 15; i++) { - m[i] = t[i] - 0xffff - ((m[i-1]>>16) & 1); - m[i-1] &= 0xffff; - } - m[15] = t[15] - 0x7fff - ((m[14]>>16) & 1); - b = (m[15]>>16) & 1; - m[14] &= 0xffff; - sel25519(t, m, 1-b); - } - for (i = 0; i < 16; i++) { - o[2*i] = t[i] & 0xff; - o[2*i+1] = t[i]>>8; - } - } - - function neq25519(a, b) { - var c = new Uint8Array(32), d = new Uint8Array(32); - pack25519(c, a); - pack25519(d, b); - return crypto_verify_32(c, 0, d, 0); - } - - function par25519(a) { - var d = new Uint8Array(32); - pack25519(d, a); - return d[0] & 1; - } - - function unpack25519(o, n) { - var i; - for (i = 0; i < 16; i++) o[i] = n[2*i] + (n[2*i+1] << 8); - o[15] &= 0x7fff; - } - - function A(o, a, b) { - for (var i = 0; i < 16; i++) o[i] = a[i] + b[i]; - } - - function Z(o, a, b) { - for (var i = 0; i < 16; i++) o[i] = a[i] - b[i]; - } - - function M(o, a, b) { - var v, c, - t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0, - t8 = 0, t9 = 0, t10 = 0, t11 = 0, t12 = 0, t13 = 0, t14 = 0, t15 = 0, - t16 = 0, t17 = 0, t18 = 0, t19 = 0, t20 = 0, t21 = 0, t22 = 0, t23 = 0, - t24 = 0, t25 = 0, t26 = 0, t27 = 0, t28 = 0, t29 = 0, t30 = 0, - b0 = b[0], - b1 = b[1], - b2 = b[2], - b3 = b[3], - b4 = b[4], - b5 = b[5], - b6 = b[6], - b7 = b[7], - b8 = b[8], - b9 = b[9], - b10 = b[10], - b11 = b[11], - b12 = b[12], - b13 = b[13], - b14 = b[14], - b15 = b[15]; - - v = a[0]; - t0 += v * b0; - t1 += v * b1; - t2 += v * b2; - t3 += v * b3; - t4 += v * b4; - t5 += v * b5; - t6 += v * b6; - t7 += v * b7; - t8 += v * b8; - t9 += v * b9; - t10 += v * b10; - t11 += v * b11; - t12 += v * b12; - t13 += v * b13; - t14 += v * b14; - t15 += v * b15; - v = a[1]; - t1 += v * b0; - t2 += v * b1; - t3 += v * b2; - t4 += v * b3; - t5 += v * b4; - t6 += v * b5; - t7 += v * b6; - t8 += v * b7; - t9 += v * b8; - t10 += v * b9; - t11 += v * b10; - t12 += v * b11; - t13 += v * b12; - t14 += v * b13; - t15 += v * b14; - t16 += v * b15; - v = a[2]; - t2 += v * b0; - t3 += v * b1; - t4 += v * b2; - t5 += v * b3; - t6 += v * b4; - t7 += v * b5; - t8 += v * b6; - t9 += v * b7; - t10 += v * b8; - t11 += v * b9; - t12 += v * b10; - t13 += v * b11; - t14 += v * b12; - t15 += v * b13; - t16 += v * b14; - t17 += v * b15; - v = a[3]; - t3 += v * b0; - t4 += v * b1; - t5 += v * b2; - t6 += v * b3; - t7 += v * b4; - t8 += v * b5; - t9 += v * b6; - t10 += v * b7; - t11 += v * b8; - t12 += v * b9; - t13 += v * b10; - t14 += v * b11; - t15 += v * b12; - t16 += v * b13; - t17 += v * b14; - t18 += v * b15; - v = a[4]; - t4 += v * b0; - t5 += v * b1; - t6 += v * b2; - t7 += v * b3; - t8 += v * b4; - t9 += v * b5; - t10 += v * b6; - t11 += v * b7; - t12 += v * b8; - t13 += v * b9; - t14 += v * b10; - t15 += v * b11; - t16 += v * b12; - t17 += v * b13; - t18 += v * b14; - t19 += v * b15; - v = a[5]; - t5 += v * b0; - t6 += v * b1; - t7 += v * b2; - t8 += v * b3; - t9 += v * b4; - t10 += v * b5; - t11 += v * b6; - t12 += v * b7; - t13 += v * b8; - t14 += v * b9; - t15 += v * b10; - t16 += v * b11; - t17 += v * b12; - t18 += v * b13; - t19 += v * b14; - t20 += v * b15; - v = a[6]; - t6 += v * b0; - t7 += v * b1; - t8 += v * b2; - t9 += v * b3; - t10 += v * b4; - t11 += v * b5; - t12 += v * b6; - t13 += v * b7; - t14 += v * b8; - t15 += v * b9; - t16 += v * b10; - t17 += v * b11; - t18 += v * b12; - t19 += v * b13; - t20 += v * b14; - t21 += v * b15; - v = a[7]; - t7 += v * b0; - t8 += v * b1; - t9 += v * b2; - t10 += v * b3; - t11 += v * b4; - t12 += v * b5; - t13 += v * b6; - t14 += v * b7; - t15 += v * b8; - t16 += v * b9; - t17 += v * b10; - t18 += v * b11; - t19 += v * b12; - t20 += v * b13; - t21 += v * b14; - t22 += v * b15; - v = a[8]; - t8 += v * b0; - t9 += v * b1; - t10 += v * b2; - t11 += v * b3; - t12 += v * b4; - t13 += v * b5; - t14 += v * b6; - t15 += v * b7; - t16 += v * b8; - t17 += v * b9; - t18 += v * b10; - t19 += v * b11; - t20 += v * b12; - t21 += v * b13; - t22 += v * b14; - t23 += v * b15; - v = a[9]; - t9 += v * b0; - t10 += v * b1; - t11 += v * b2; - t12 += v * b3; - t13 += v * b4; - t14 += v * b5; - t15 += v * b6; - t16 += v * b7; - t17 += v * b8; - t18 += v * b9; - t19 += v * b10; - t20 += v * b11; - t21 += v * b12; - t22 += v * b13; - t23 += v * b14; - t24 += v * b15; - v = a[10]; - t10 += v * b0; - t11 += v * b1; - t12 += v * b2; - t13 += v * b3; - t14 += v * b4; - t15 += v * b5; - t16 += v * b6; - t17 += v * b7; - t18 += v * b8; - t19 += v * b9; - t20 += v * b10; - t21 += v * b11; - t22 += v * b12; - t23 += v * b13; - t24 += v * b14; - t25 += v * b15; - v = a[11]; - t11 += v * b0; - t12 += v * b1; - t13 += v * b2; - t14 += v * b3; - t15 += v * b4; - t16 += v * b5; - t17 += v * b6; - t18 += v * b7; - t19 += v * b8; - t20 += v * b9; - t21 += v * b10; - t22 += v * b11; - t23 += v * b12; - t24 += v * b13; - t25 += v * b14; - t26 += v * b15; - v = a[12]; - t12 += v * b0; - t13 += v * b1; - t14 += v * b2; - t15 += v * b3; - t16 += v * b4; - t17 += v * b5; - t18 += v * b6; - t19 += v * b7; - t20 += v * b8; - t21 += v * b9; - t22 += v * b10; - t23 += v * b11; - t24 += v * b12; - t25 += v * b13; - t26 += v * b14; - t27 += v * b15; - v = a[13]; - t13 += v * b0; - t14 += v * b1; - t15 += v * b2; - t16 += v * b3; - t17 += v * b4; - t18 += v * b5; - t19 += v * b6; - t20 += v * b7; - t21 += v * b8; - t22 += v * b9; - t23 += v * b10; - t24 += v * b11; - t25 += v * b12; - t26 += v * b13; - t27 += v * b14; - t28 += v * b15; - v = a[14]; - t14 += v * b0; - t15 += v * b1; - t16 += v * b2; - t17 += v * b3; - t18 += v * b4; - t19 += v * b5; - t20 += v * b6; - t21 += v * b7; - t22 += v * b8; - t23 += v * b9; - t24 += v * b10; - t25 += v * b11; - t26 += v * b12; - t27 += v * b13; - t28 += v * b14; - t29 += v * b15; - v = a[15]; - t15 += v * b0; - t16 += v * b1; - t17 += v * b2; - t18 += v * b3; - t19 += v * b4; - t20 += v * b5; - t21 += v * b6; - t22 += v * b7; - t23 += v * b8; - t24 += v * b9; - t25 += v * b10; - t26 += v * b11; - t27 += v * b12; - t28 += v * b13; - t29 += v * b14; - t30 += v * b15; - - t0 += 38 * t16; - t1 += 38 * t17; - t2 += 38 * t18; - t3 += 38 * t19; - t4 += 38 * t20; - t5 += 38 * t21; - t6 += 38 * t22; - t7 += 38 * t23; - t8 += 38 * t24; - t9 += 38 * t25; - t10 += 38 * t26; - t11 += 38 * t27; - t12 += 38 * t28; - t13 += 38 * t29; - t14 += 38 * t30; - // t15 left as is - - // first car - c = 1; - v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536; - v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536; - v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536; - v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536; - v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536; - v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536; - v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536; - v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536; - v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536; - v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536; - v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536; - v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536; - v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536; - v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536; - v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536; - v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536; - t0 += c-1 + 37 * (c-1); - - // second car - c = 1; - v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536; - v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536; - v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536; - v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536; - v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536; - v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536; - v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536; - v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536; - v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536; - v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536; - v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536; - v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536; - v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536; - v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536; - v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536; - v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536; - t0 += c-1 + 37 * (c-1); - - o[ 0] = t0; - o[ 1] = t1; - o[ 2] = t2; - o[ 3] = t3; - o[ 4] = t4; - o[ 5] = t5; - o[ 6] = t6; - o[ 7] = t7; - o[ 8] = t8; - o[ 9] = t9; - o[10] = t10; - o[11] = t11; - o[12] = t12; - o[13] = t13; - o[14] = t14; - o[15] = t15; - } - - function S(o, a) { - M(o, a, a); - } - - function inv25519(o, i) { - var c = gf(); - var a; - for (a = 0; a < 16; a++) c[a] = i[a]; - for (a = 253; a >= 0; a--) { - S(c, c); - if(a !== 2 && a !== 4) M(c, c, i); - } - for (a = 0; a < 16; a++) o[a] = c[a]; - } - - function pow2523(o, i) { - var c = gf(); - var a; - for (a = 0; a < 16; a++) c[a] = i[a]; - for (a = 250; a >= 0; a--) { - S(c, c); - if(a !== 1) M(c, c, i); - } - for (a = 0; a < 16; a++) o[a] = c[a]; - } - - function crypto_scalarmult(q, n, p) { - var z = new Uint8Array(32); - var x = new Float64Array(80), r, i; - var a = gf(), b = gf(), c = gf(), - d = gf(), e = gf(), f = gf(); - for (i = 0; i < 31; i++) z[i] = n[i]; - z[31]=(n[31]&127)|64; - z[0]&=248; - unpack25519(x,p); - for (i = 0; i < 16; i++) { - b[i]=x[i]; - d[i]=a[i]=c[i]=0; - } - a[0]=d[0]=1; - for (i=254; i>=0; --i) { - r=(z[i>>>3]>>>(i&7))&1; - sel25519(a,b,r); - sel25519(c,d,r); - A(e,a,c); - Z(a,a,c); - A(c,b,d); - Z(b,b,d); - S(d,e); - S(f,a); - M(a,c,a); - M(c,b,e); - A(e,a,c); - Z(a,a,c); - S(b,a); - Z(c,d,f); - M(a,c,_121665); - A(a,a,d); - M(c,c,a); - M(a,d,f); - M(d,b,x); - S(b,e); - sel25519(a,b,r); - sel25519(c,d,r); - } - for (i = 0; i < 16; i++) { - x[i+16]=a[i]; - x[i+32]=c[i]; - x[i+48]=b[i]; - x[i+64]=d[i]; - } - var x32 = x.subarray(32); - var x16 = x.subarray(16); - inv25519(x32,x32); - M(x16,x16,x32); - pack25519(q,x16); - return 0; - } - - function crypto_scalarmult_base(q, n) { - return crypto_scalarmult(q, n, _9); - } - - function crypto_box_keypair(y, x) { - randombytes(x, 32); - return crypto_scalarmult_base(y, x); - } - - function add(p, q) { - var a = gf(), b = gf(), c = gf(), - d = gf(), e = gf(), f = gf(), - g = gf(), h = gf(), t = gf(); - - Z(a, p[1], p[0]); - Z(t, q[1], q[0]); - M(a, a, t); - A(b, p[0], p[1]); - A(t, q[0], q[1]); - M(b, b, t); - M(c, p[3], q[3]); - M(c, c, D2); - M(d, p[2], q[2]); - A(d, d, d); - Z(e, b, a); - Z(f, d, c); - A(g, d, c); - A(h, b, a); - - M(p[0], e, f); - M(p[1], h, g); - M(p[2], g, f); - M(p[3], e, h); - } - - function cswap(p, q, b) { - var i; - for (i = 0; i < 4; i++) { - sel25519(p[i], q[i], b); - } - } - - function pack(r, p) { - var tx = gf(), ty = gf(), zi = gf(); - inv25519(zi, p[2]); - M(tx, p[0], zi); - M(ty, p[1], zi); - pack25519(r, ty); - r[31] ^= par25519(tx) << 7; - } - - function scalarmult(p, q, s) { - var b, i; - set25519(p[0], gf0); - set25519(p[1], gf1); - set25519(p[2], gf1); - set25519(p[3], gf0); - for (i = 255; i >= 0; --i) { - b = (s[(i/8)|0] >> (i&7)) & 1; - cswap(p, q, b); - add(q, p); - add(p, p); - cswap(p, q, b); - } - } - - function scalarbase(p, s) { - var q = [gf(), gf(), gf(), gf()]; - set25519(q[0], X); - set25519(q[1], Y); - set25519(q[2], gf1); - M(q[3], X, Y); - scalarmult(p, q, s); - } - - function crypto_sign_keypair(pk, sk, seeded) { - var d; - var p = [gf(), gf(), gf(), gf()]; - var i; - - if (!seeded) randombytes(sk, 32); - d = nacl.hash(sk.subarray(0, 32)); - d[0] &= 248; - d[31] &= 127; - d[31] |= 64; - - scalarbase(p, d); - pack(pk, p); - - for (i = 0; i < 32; i++) sk[i+32] = pk[i]; - return 0; - } - - var L = new Float64Array([0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10]); - - function modL(r, x) { - var carry, i, j, k; - for (i = 63; i >= 32; --i) { - carry = 0; - for (j = i - 32, k = i - 12; j < k; ++j) { - x[j] += carry - 16 * x[i] * L[j - (i - 32)]; - carry = Math.floor((x[j] + 128) / 256); - x[j] -= carry * 256; - } - x[j] += carry; - x[i] = 0; - } - carry = 0; - for (j = 0; j < 32; j++) { - x[j] += carry - (x[31] >> 4) * L[j]; - carry = x[j] >> 8; - x[j] &= 255; - } - for (j = 0; j < 32; j++) x[j] -= carry * L[j]; - for (i = 0; i < 32; i++) { - x[i+1] += x[i] >> 8; - r[i] = x[i] & 255; - } - } - - function reduce(r) { - var x = new Float64Array(64), i; - for (i = 0; i < 64; i++) x[i] = r[i]; - for (i = 0; i < 64; i++) r[i] = 0; - modL(r, x); - } - - // Note: difference from C - smlen returned, not passed as argument. - function crypto_sign(sm, m, n, sk) { - var d, h, r; - var i, j, x = new Float64Array(64); - var p = [gf(), gf(), gf(), gf()]; - - d = nacl.hash(sk.subarray(0, 32)); - d[0] &= 248; - d[31] &= 127; - d[31] |= 64; - - var smlen = n + 64; - for (i = 0; i < n; i++) sm[64 + i] = m[i]; - for (i = 0; i < 32; i++) sm[32 + i] = d[32 + i]; - - r = nacl.hash(sm.subarray(32, smlen)); - reduce(r); - scalarbase(p, r); - pack(sm, p); - - for (i = 32; i < 64; i++) sm[i] = sk[i]; - h = nacl.hash(sm.subarray(0, smlen)); - reduce(h); - - for (i = 0; i < 64; i++) x[i] = 0; - for (i = 0; i < 32; i++) x[i] = r[i]; - for (i = 0; i < 32; i++) { - for (j = 0; j < 32; j++) { - x[i+j] += h[i] * d[j]; - } - } - - modL(sm.subarray(32), x); - return smlen; - } - - function unpackneg(r, p) { - var t = gf(), chk = gf(), num = gf(), - den = gf(), den2 = gf(), den4 = gf(), - den6 = gf(); - - set25519(r[2], gf1); - unpack25519(r[1], p); - S(num, r[1]); - M(den, num, D); - Z(num, num, r[2]); - A(den, r[2], den); - - S(den2, den); - S(den4, den2); - M(den6, den4, den2); - M(t, den6, num); - M(t, t, den); - - pow2523(t, t); - M(t, t, num); - M(t, t, den); - M(t, t, den); - M(r[0], t, den); - - S(chk, r[0]); - M(chk, chk, den); - if (neq25519(chk, num)) M(r[0], r[0], I); - - S(chk, r[0]); - M(chk, chk, den); - if (neq25519(chk, num)) return -1; - - if (par25519(r[0]) === (p[31]>>7)) Z(r[0], gf0, r[0]); - - M(r[3], r[0], r[1]); - return 0; - } - - function crypto_sign_open(m, sm, n, pk) { - var i; - var t = new Uint8Array(32), h; - var p = [gf(), gf(), gf(), gf()], - q = [gf(), gf(), gf(), gf()]; - - if (n < 64) return -1; - - if (unpackneg(q, pk)) return -1; - - for (i = 0; i < n; i++) m[i] = sm[i]; - for (i = 0; i < 32; i++) m[i+32] = pk[i]; - h = nacl.hash(m.subarray(0, n)); - reduce(h); - scalarmult(p, q, h); - - scalarbase(q, sm.subarray(32)); - add(p, q); - pack(t, p); - - n -= 64; - if (crypto_verify_32(sm, 0, t, 0)) { - for (i = 0; i < n; i++) m[i] = 0; - return -1; - } - - for (i = 0; i < n; i++) m[i] = sm[i + 64]; - return n; - } - - var crypto_scalarmult_BYTES = 32, - crypto_scalarmult_SCALARBYTES = 32, - crypto_box_PUBLICKEYBYTES = 32, - crypto_box_SECRETKEYBYTES = 32, - crypto_sign_BYTES = 64, - crypto_sign_PUBLICKEYBYTES = 32, - crypto_sign_SECRETKEYBYTES = 64, - crypto_sign_SEEDBYTES = 32; - - function checkArrayTypes() { - for (var i = 0; i < arguments.length; i++) { - if (!(arguments[i] instanceof Uint8Array)) - throw new TypeError('unexpected type, use Uint8Array'); - } - } - - function cleanup(arr) { - for (var i = 0; i < arr.length; i++) arr[i] = 0; - } - - nacl.scalarMult = function(n, p) { - checkArrayTypes(n, p); - if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error('bad n size'); - if (p.length !== crypto_scalarmult_BYTES) throw new Error('bad p size'); - var q = new Uint8Array(crypto_scalarmult_BYTES); - crypto_scalarmult(q, n, p); - return q; - }; - - nacl.box = {}; - - nacl.box.keyPair = function() { - var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); - var sk = new Uint8Array(crypto_box_SECRETKEYBYTES); - crypto_box_keypair(pk, sk); - return {publicKey: pk, secretKey: sk}; - }; - - nacl.box.keyPair.fromSecretKey = function(secretKey) { - checkArrayTypes(secretKey); - if (secretKey.length !== crypto_box_SECRETKEYBYTES) - throw new Error('bad secret key size'); - var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); - crypto_scalarmult_base(pk, secretKey); - return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; - }; - - nacl.sign = function(msg, secretKey) { - checkArrayTypes(msg, secretKey); - if (secretKey.length !== crypto_sign_SECRETKEYBYTES) - throw new Error('bad secret key size'); - var signedMsg = new Uint8Array(crypto_sign_BYTES+msg.length); - crypto_sign(signedMsg, msg, msg.length, secretKey); - return signedMsg; - }; - - nacl.sign.detached = function(msg, secretKey) { - var signedMsg = nacl.sign(msg, secretKey); - var sig = new Uint8Array(crypto_sign_BYTES); - for (var i = 0; i < sig.length; i++) sig[i] = signedMsg[i]; - return sig; - }; - - nacl.sign.detached.verify = function(msg, sig, publicKey) { - checkArrayTypes(msg, sig, publicKey); - if (sig.length !== crypto_sign_BYTES) - throw new Error('bad signature size'); - if (publicKey.length !== crypto_sign_PUBLICKEYBYTES) - throw new Error('bad public key size'); - var sm = new Uint8Array(crypto_sign_BYTES + msg.length); - var m = new Uint8Array(crypto_sign_BYTES + msg.length); - var i; - for (i = 0; i < crypto_sign_BYTES; i++) sm[i] = sig[i]; - for (i = 0; i < msg.length; i++) sm[i+crypto_sign_BYTES] = msg[i]; - return (crypto_sign_open(m, sm, sm.length, publicKey) >= 0); - }; - - nacl.sign.keyPair = function() { - var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); - var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); - crypto_sign_keypair(pk, sk); - return {publicKey: pk, secretKey: sk}; - }; - - nacl.sign.keyPair.fromSecretKey = function(secretKey) { - checkArrayTypes(secretKey); - if (secretKey.length !== crypto_sign_SECRETKEYBYTES) - throw new Error('bad secret key size'); - var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); - for (var i = 0; i < pk.length; i++) pk[i] = secretKey[32+i]; - return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; - }; - - nacl.sign.keyPair.fromSeed = function(seed) { - checkArrayTypes(seed); - if (seed.length !== crypto_sign_SEEDBYTES) - throw new Error('bad seed size'); - var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); - var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); - for (var i = 0; i < 32; i++) sk[i] = seed[i]; - crypto_sign_keypair(pk, sk, true); - return {publicKey: pk, secretKey: sk}; - }; - - nacl.setPRNG = function(fn) { - randombytes = fn; - }; - - (function() { - // Initialize PRNG if environment provides CSPRNG. - // If not, methods calling randombytes will throw. - var crypto = typeof self !== 'undefined' ? (self.crypto || self.msCrypto) : null; - if (crypto && crypto.getRandomValues) { - // Browsers. - var QUOTA = 65536; - nacl.setPRNG(function(x, n) { - var i, v = new Uint8Array(n); - for (i = 0; i < n; i += QUOTA) { - crypto.getRandomValues(v.subarray(i, i + Math.min(n - i, QUOTA))); - } - for (i = 0; i < n; i++) x[i] = v[i]; - cleanup(v); - }); - } else if (typeof commonjsRequire !== 'undefined') { - // Node.js. - crypto = void('crypto'); - if (crypto && crypto.randomBytes) { - nacl.setPRNG(function(x, n) { - var i, v = crypto.randomBytes(n); - for (i = 0; i < n; i++) x[i] = v[i]; - cleanup(v); - }); - } - } - })(); - - })(module.exports ? module.exports : (self.nacl = self.nacl || {})); - }); - - // GPG4Browsers - An OpenPGP implementation in javascript - - const nodeCrypto$5 = util.getNodeCrypto(); - - /** - * Buffer for secure random numbers - */ - class RandomBuffer { - constructor() { - this.buffer = null; - this.size = null; - this.callback = null; - } - - /** - * Initialize buffer - * @param {Integer} size - size of buffer - */ - init(size, callback) { - this.buffer = new Uint8Array(size); - this.size = 0; - this.callback = callback; - } - - /** - * Concat array of secure random numbers to buffer - * @param {Uint8Array} buf - */ - set(buf) { - if (!this.buffer) { - throw new Error('RandomBuffer is not initialized'); - } - if (!(buf instanceof Uint8Array)) { - throw new Error('Invalid type: buf not an Uint8Array'); - } - const freeSpace = this.buffer.length - this.size; - if (buf.length > freeSpace) { - buf = buf.subarray(0, freeSpace); - } - // set buf with offset old size of buffer - this.buffer.set(buf, this.size); - this.size += buf.length; - } - - /** - * Take numbers out of buffer and copy to array - * @param {Uint8Array} buf - The destination array - */ - async get(buf) { - if (!this.buffer) { - throw new Error('RandomBuffer is not initialized'); - } - if (!(buf instanceof Uint8Array)) { - throw new Error('Invalid type: buf not an Uint8Array'); - } - if (this.size < buf.length) { - if (!this.callback) { - throw new Error('Random number buffer depleted'); - } - // Wait for random bytes from main context, then try again - await this.callback(); - return this.get(buf); - } - for (let i = 0; i < buf.length; i++) { - buf[i] = this.buffer[--this.size]; - // clear buffer value - this.buffer[this.size] = 0; - } - } - } - - /** - * Retrieve secure random byte array of the specified length - * @param {Integer} length - Length in bytes to generate - * @returns {Promise} Random byte array. - * @async - */ - async function getRandomBytes(length) { - const buf = new Uint8Array(length); - if (typeof crypto !== 'undefined' && crypto.getRandomValues) { - crypto.getRandomValues(buf); - } else if (nodeCrypto$5) { - const bytes = nodeCrypto$5.randomBytes(buf.length); - buf.set(bytes); - } else if (randomBuffer.buffer) { - await randomBuffer.get(buf); - } else { - throw new Error('No secure random number generator available.'); - } - return buf; - } - - /** - * Create a secure random BigInteger that is greater than or equal to min and less than max. - * @param {module:BigInteger} min - Lower bound, included - * @param {module:BigInteger} max - Upper bound, excluded - * @returns {Promise} Random BigInteger. - * @async - */ - async function getRandomBigInteger(min, max) { - const BigInteger = await util.getBigInteger(); - - if (max.lt(min)) { - throw new Error('Illegal parameter value: max <= min'); - } - - const modulus = max.sub(min); - const bytes = modulus.byteLength(); - - // Using a while loop is necessary to avoid bias introduced by the mod operation. - // However, we request 64 extra random bits so that the bias is negligible. - // Section B.1.1 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - const r = new BigInteger(await getRandomBytes(bytes + 8)); - return r.mod(modulus).add(min); - } - - const randomBuffer = new RandomBuffer(); - - var random = /*#__PURE__*/Object.freeze({ - __proto__: null, - getRandomBytes: getRandomBytes, - getRandomBigInteger: getRandomBigInteger, - randomBuffer: randomBuffer - }); - - // OpenPGP.js - An OpenPGP implementation in javascript - - /** - * Generate a probably prime random number - * @param {Integer} bits - Bit length of the prime - * @param {BigInteger} e - Optional RSA exponent to check against the prime - * @param {Integer} k - Optional number of iterations of Miller-Rabin test - * @returns BigInteger - * @async - */ - async function randomProbablePrime(bits, e, k) { - const BigInteger = await util.getBigInteger(); - const one = new BigInteger(1); - const min = one.leftShift(new BigInteger(bits - 1)); - const thirty = new BigInteger(30); - /* - * We can avoid any multiples of 3 and 5 by looking at n mod 30 - * n mod 30 = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 - * the next possible prime is mod 30: - * 1 7 7 7 7 7 7 11 11 11 11 13 13 17 17 17 17 19 19 23 23 23 23 29 29 29 29 29 29 1 - */ - const adds = [1, 6, 5, 4, 3, 2, 1, 4, 3, 2, 1, 2, 1, 4, 3, 2, 1, 2, 1, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1, 2]; - - const n = await getRandomBigInteger(min, min.leftShift(one)); - let i = n.mod(thirty).toNumber(); - - do { - n.iadd(new BigInteger(adds[i])); - i = (i + adds[i]) % adds.length; - // If reached the maximum, go back to the minimum. - if (n.bitLength() > bits) { - n.imod(min.leftShift(one)).iadd(min); - i = n.mod(thirty).toNumber(); - } - } while (!await isProbablePrime(n, e, k)); - return n; - } - - /** - * Probabilistic primality testing - * @param {BigInteger} n - Number to test - * @param {BigInteger} e - Optional RSA exponent to check against the prime - * @param {Integer} k - Optional number of iterations of Miller-Rabin test - * @returns {boolean} - * @async - */ - async function isProbablePrime(n, e, k) { - if (e && !n.dec().gcd(e).isOne()) { - return false; - } - if (!await divisionTest(n)) { - return false; - } - if (!await fermat(n)) { - return false; - } - if (!await millerRabin(n, k)) { - return false; - } - // TODO implement the Lucas test - // See Section C.3.3 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - return true; - } - - /** - * Tests whether n is probably prime or not using Fermat's test with b = 2. - * Fails if b^(n-1) mod n != 1. - * @param {BigInteger} n - Number to test - * @param {BigInteger} b - Optional Fermat test base - * @returns {boolean} - */ - async function fermat(n, b) { - const BigInteger = await util.getBigInteger(); - b = b || new BigInteger(2); - return b.modExp(n.dec(), n).isOne(); - } - - async function divisionTest(n) { - const BigInteger = await util.getBigInteger(); - return smallPrimes.every(m => { - return n.mod(new BigInteger(m)) !== 0; - }); - } - - // https://github.com/gpg/libgcrypt/blob/master/cipher/primegen.c - const smallPrimes = [ - 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, - 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, - 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, - 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, - 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, - 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, - 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, - 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, - 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, - 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, - 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, - 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, - 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, - 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, - 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, - 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, - 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, - 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, - 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, - 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, - 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, - 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, - 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, - 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, - 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, - 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, - 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, - 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, - 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, - 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, - 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, - 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, - 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, - 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, - 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, - 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, - 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, - 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, - 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, - 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, - 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, - 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, - 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, - 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, - 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, - 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, - 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, - 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, - 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, - 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, - 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, - 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, - 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, - 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, - 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, - 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, - 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, - 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, - 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, - 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, - 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, - 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, - 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, - 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, - 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, - 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, - 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, - 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, - 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, - 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, - 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457, - 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, - 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, - 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, - 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, - 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, - 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, - 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, - 4957, 4967, 4969, 4973, 4987, 4993, 4999 - ]; - - - // Miller-Rabin - Miller Rabin algorithm for primality test - // Copyright Fedor Indutny, 2014. - // - // This software is licensed under the MIT License. - // - // Permission is hereby granted, free of charge, to any person obtaining a - // copy of this software and associated documentation files (the - // "Software"), to deal in the Software without restriction, including - // without limitation the rights to use, copy, modify, merge, publish, - // distribute, sublicense, and/or sell copies of the Software, and to permit - // persons to whom the Software is furnished to do so, subject to the - // following conditions: - // - // The above copyright notice and this permission notice shall be included - // in all copies or substantial portions of the Software. - // - // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - // USE OR OTHER DEALINGS IN THE SOFTWARE. - - // Adapted on Jan 2018 from version 4.0.1 at https://github.com/indutny/miller-rabin - - // Sample syntax for Fixed-Base Miller-Rabin: - // millerRabin(n, k, () => new BN(small_primes[Math.random() * small_primes.length | 0])) - - /** - * Tests whether n is probably prime or not using the Miller-Rabin test. - * See HAC Remark 4.28. - * @param {BigInteger} n - Number to test - * @param {Integer} k - Optional number of iterations of Miller-Rabin test - * @param {Function} rand - Optional function to generate potential witnesses - * @returns {boolean} - * @async - */ - async function millerRabin(n, k, rand) { - const BigInteger = await util.getBigInteger(); - const len = n.bitLength(); - - if (!k) { - k = Math.max(1, (len / 48) | 0); - } - - const n1 = n.dec(); // n - 1 - - // Find d and s, (n - 1) = (2 ^ s) * d; - let s = 0; - while (!n1.getBit(s)) { s++; } - const d = n.rightShift(new BigInteger(s)); - - for (; k > 0; k--) { - const a = rand ? rand() : await getRandomBigInteger(new BigInteger(2), n1); - - let x = a.modExp(d, n); - if (x.isOne() || x.equal(n1)) { - continue; - } - - let i; - for (i = 1; i < s; i++) { - x = x.mul(x).mod(n); - - if (x.isOne()) { - return false; - } - if (x.equal(n1)) { - break; - } - } - - if (i === s) { - return false; - } - } - - return true; - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - /** - * ASN1 object identifiers for hashes - * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.2} - */ - const hash_headers = []; - hash_headers[1] = [0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, - 0x10]; - hash_headers[2] = [0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14]; - hash_headers[3] = [0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14]; - hash_headers[8] = [0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, - 0x04, 0x20]; - hash_headers[9] = [0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, - 0x04, 0x30]; - hash_headers[10] = [0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, - 0x00, 0x04, 0x40]; - hash_headers[11] = [0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, - 0x00, 0x04, 0x1C]; - - /** - * Create padding with secure random data - * @private - * @param {Integer} length - Length of the padding in bytes - * @returns {Promise} Random padding. - * @async - */ - async function getPKCS1Padding(length) { - const result = new Uint8Array(length); - let count = 0; - while (count < length) { - const randomBytes = await getRandomBytes(length - count); - for (let i = 0; i < randomBytes.length; i++) { - if (randomBytes[i] !== 0) { - result[count++] = randomBytes[i]; - } - } - } - return result; - } - - /** - * Create a EME-PKCS1-v1_5 padded message - * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.1|RFC 4880 13.1.1} - * @param {Uint8Array} message - Message to be encoded - * @param {Integer} keyLength - The length in octets of the key modulus - * @returns {Promise} EME-PKCS1 padded message. - * @async - */ - async function emeEncode(message, keyLength) { - const mLength = message.length; - // length checking - if (mLength > keyLength - 11) { - throw new Error('Message too long'); - } - // Generate an octet string PS of length k - mLen - 3 consisting of - // pseudo-randomly generated nonzero octets - const PS = await getPKCS1Padding(keyLength - mLength - 3); - // Concatenate PS, the message M, and other padding to form an - // encoded message EM of length k octets as EM = 0x00 || 0x02 || PS || 0x00 || M. - const encoded = new Uint8Array(keyLength); - // 0x00 byte - encoded[1] = 2; - encoded.set(PS, 2); - // 0x00 bytes - encoded.set(message, keyLength - mLength); - return encoded; - } - - /** - * Decode a EME-PKCS1-v1_5 padded message - * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.2|RFC 4880 13.1.2} - * @param {Uint8Array} encoded - Encoded message bytes - * @param {Uint8Array} randomPayload - Data to return in case of decoding error (needed for constant-time processing) - * @returns {Uint8Array} decoded data or `randomPayload` (on error, if given) - * @throws {Error} on decoding failure, unless `randomPayload` is provided - */ - function emeDecode(encoded, randomPayload) { - // encoded format: 0x00 0x02 0x00 - let offset = 2; - let separatorNotFound = 1; - for (let j = offset; j < encoded.length; j++) { - separatorNotFound &= encoded[j] !== 0; - offset += separatorNotFound; - } - - const psLen = offset - 2; - const payload = encoded.subarray(offset + 1); // discard the 0x00 separator - const isValidPadding = encoded[0] === 0 & encoded[1] === 2 & psLen >= 8 & !separatorNotFound; - - if (randomPayload) { - return util.selectUint8Array(isValidPadding, payload, randomPayload); - } - - if (isValidPadding) { - return payload; - } - - throw new Error('Decryption error'); - } - - /** - * Create a EMSA-PKCS1-v1_5 padded message - * @see {@link https://tools.ietf.org/html/rfc4880#section-13.1.3|RFC 4880 13.1.3} - * @param {Integer} algo - Hash algorithm type used - * @param {Uint8Array} hashed - Message to be encoded - * @param {Integer} emLen - Intended length in octets of the encoded message - * @returns {Uint8Array} Encoded message. - */ - async function emsaEncode(algo, hashed, emLen) { - let i; - if (hashed.length !== hash.getHashByteLength(algo)) { - throw new Error('Invalid hash length'); - } - // produce an ASN.1 DER value for the hash function used. - // Let T be the full hash prefix - const hashPrefix = new Uint8Array(hash_headers[algo].length); - for (i = 0; i < hash_headers[algo].length; i++) { - hashPrefix[i] = hash_headers[algo][i]; - } - // and let tLen be the length in octets prefix and hashed data - const tLen = hashPrefix.length + hashed.length; - if (emLen < tLen + 11) { - throw new Error('Intended encoded message length too short'); - } - // an octet string PS consisting of emLen - tLen - 3 octets with hexadecimal value 0xFF - // The length of PS will be at least 8 octets - const PS = new Uint8Array(emLen - tLen - 3).fill(0xff); - - // Concatenate PS, the hash prefix, hashed data, and other padding to form the - // encoded message EM as EM = 0x00 || 0x01 || PS || 0x00 || prefix || hashed - const EM = new Uint8Array(emLen); - EM[1] = 0x01; - EM.set(PS, 2); - EM.set(hashPrefix, emLen - tLen); - EM.set(hashed, emLen - hashed.length); - return EM; - } - - var pkcs1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - emeEncode: emeEncode, - emeDecode: emeDecode, - emsaEncode: emsaEncode - }); - - // GPG4Browsers - An OpenPGP implementation in javascript - - const webCrypto$5 = util.getWebCrypto(); - const nodeCrypto$6 = util.getNodeCrypto(); - const asn1 = nodeCrypto$6 ? void('asn1.js') : undefined; - - /* eslint-disable no-invalid-this */ - const RSAPrivateKey = util.detectNode() ? asn1.define('RSAPrivateKey', function () { - this.seq().obj( // used for native NodeJS crypto - this.key('version').int(), // 0 - this.key('modulus').int(), // n - this.key('publicExponent').int(), // e - this.key('privateExponent').int(), // d - this.key('prime1').int(), // p - this.key('prime2').int(), // q - this.key('exponent1').int(), // dp - this.key('exponent2').int(), // dq - this.key('coefficient').int() // u - ); - }) : undefined; - - const RSAPublicKey = util.detectNode() ? asn1.define('RSAPubliceKey', function () { - this.seq().obj( // used for native NodeJS crypto - this.key('modulus').int(), // n - this.key('publicExponent').int(), // e - ); - }) : undefined; - /* eslint-enable no-invalid-this */ - - /** Create signature - * @param {module:enums.hash} hashAlgo - Hash algorithm - * @param {Uint8Array} data - Message - * @param {Uint8Array} n - RSA public modulus - * @param {Uint8Array} e - RSA public exponent - * @param {Uint8Array} d - RSA private exponent - * @param {Uint8Array} p - RSA private prime p - * @param {Uint8Array} q - RSA private prime q - * @param {Uint8Array} u - RSA private coefficient - * @param {Uint8Array} hashed - Hashed message - * @returns {Promise} RSA Signature. - * @async - */ - async function sign(hashAlgo, data, n, e, d, p, q, u, hashed) { - if (data && !util.isStream(data)) { - if (util.getWebCrypto()) { - try { - return await webSign(enums.read(enums.webHash, hashAlgo), data, n, e, d, p, q, u); - } catch (err) { - util.printDebugError(err); - } - } else if (util.getNodeCrypto()) { - return nodeSign(hashAlgo, data, n, e, d, p, q, u); - } - } - return bnSign(hashAlgo, n, d, hashed); - } - - /** - * Verify signature - * @param {module:enums.hash} hashAlgo - Hash algorithm - * @param {Uint8Array} data - Message - * @param {Uint8Array} s - Signature - * @param {Uint8Array} n - RSA public modulus - * @param {Uint8Array} e - RSA public exponent - * @param {Uint8Array} hashed - Hashed message - * @returns {Boolean} - * @async - */ - async function verify(hashAlgo, data, s, n, e, hashed) { - if (data && !util.isStream(data)) { - if (util.getWebCrypto()) { - try { - return await webVerify(enums.read(enums.webHash, hashAlgo), data, s, n, e); - } catch (err) { - util.printDebugError(err); - } - } else if (util.getNodeCrypto()) { - return nodeVerify(hashAlgo, data, s, n, e); - } - } - return bnVerify(hashAlgo, s, n, e, hashed); - } - - /** - * Encrypt message - * @param {Uint8Array} data - Message - * @param {Uint8Array} n - RSA public modulus - * @param {Uint8Array} e - RSA public exponent - * @returns {Promise} RSA Ciphertext. - * @async - */ - async function encrypt$1(data, n, e) { - if (util.getNodeCrypto()) { - return nodeEncrypt$1(data, n, e); - } - return bnEncrypt(data, n, e); - } - - /** - * Decrypt RSA message - * @param {Uint8Array} m - Message - * @param {Uint8Array} n - RSA public modulus - * @param {Uint8Array} e - RSA public exponent - * @param {Uint8Array} d - RSA private exponent - * @param {Uint8Array} p - RSA private prime p - * @param {Uint8Array} q - RSA private prime q - * @param {Uint8Array} u - RSA private coefficient - * @param {Uint8Array} randomPayload - Data to return on decryption error, instead of throwing - * (needed for constant-time processing) - * @returns {Promise} RSA Plaintext. - * @throws {Error} on decryption error, unless `randomPayload` is given - * @async - */ - async function decrypt$1(data, n, e, d, p, q, u, randomPayload) { - if (util.getNodeCrypto()) { - return nodeDecrypt$1(data, n, e, d, p, q, u, randomPayload); - } - return bnDecrypt(data, n, e, d, p, q, u, randomPayload); - } - - /** - * Generate a new random private key B bits long with public exponent E. - * - * When possible, webCrypto or nodeCrypto is used. Otherwise, primes are generated using - * 40 rounds of the Miller-Rabin probabilistic random prime generation algorithm. - * @see module:crypto/public_key/prime - * @param {Integer} bits - RSA bit length - * @param {Integer} e - RSA public exponent - * @returns {{n, e, d, - * p, q ,u: Uint8Array}} RSA public modulus, RSA public exponent, RSA private exponent, - * RSA private prime p, RSA private prime q, u = p ** -1 mod q - * @async - */ - async function generate(bits, e) { - const BigInteger = await util.getBigInteger(); - - e = new BigInteger(e); - - // Native RSA keygen using Web Crypto - if (util.getWebCrypto()) { - const keyGenOpt = { - name: 'RSASSA-PKCS1-v1_5', - modulusLength: bits, // the specified keysize in bits - publicExponent: e.toUint8Array(), // take three bytes (max 65537) for exponent - hash: { - name: 'SHA-1' // not required for actual RSA keys, but for crypto api 'sign' and 'verify' - } - }; - const keyPair = await webCrypto$5.generateKey(keyGenOpt, true, ['sign', 'verify']); - - // export the generated keys as JsonWebKey (JWK) - // https://tools.ietf.org/html/draft-ietf-jose-json-web-key-33 - const jwk = await webCrypto$5.exportKey('jwk', keyPair.privateKey); - // map JWK parameters to corresponding OpenPGP names - return { - n: b64ToUint8Array(jwk.n), - e: e.toUint8Array(), - d: b64ToUint8Array(jwk.d), - // switch p and q - p: b64ToUint8Array(jwk.q), - q: b64ToUint8Array(jwk.p), - // Since p and q are switched in places, u is the inverse of jwk.q - u: b64ToUint8Array(jwk.qi) - }; - } else if (util.getNodeCrypto() && nodeCrypto$6.generateKeyPair && RSAPrivateKey) { - const opts = { - modulusLength: bits, - publicExponent: e.toNumber(), - publicKeyEncoding: { type: 'pkcs1', format: 'der' }, - privateKeyEncoding: { type: 'pkcs1', format: 'der' } - }; - const prv = await new Promise((resolve, reject) => nodeCrypto$6.generateKeyPair('rsa', opts, (err, _, der) => { - if (err) { - reject(err); - } else { - resolve(RSAPrivateKey.decode(der, 'der')); - } - })); - /** - * OpenPGP spec differs from DER spec, DER: `u = (inverse of q) mod p`, OpenPGP: `u = (inverse of p) mod q`. - * @link https://tools.ietf.org/html/rfc3447#section-3.2 - * @link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-08#section-5.6.1 - */ - return { - n: prv.modulus.toArrayLike(Uint8Array), - e: prv.publicExponent.toArrayLike(Uint8Array), - d: prv.privateExponent.toArrayLike(Uint8Array), - // switch p and q - p: prv.prime2.toArrayLike(Uint8Array), - q: prv.prime1.toArrayLike(Uint8Array), - // Since p and q are switched in places, we can keep u as defined by DER - u: prv.coefficient.toArrayLike(Uint8Array) - }; - } - - // RSA keygen fallback using 40 iterations of the Miller-Rabin test - // See https://stackoverflow.com/a/6330138 for justification - // Also see section C.3 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST - let p; - let q; - let n; - do { - q = await randomProbablePrime(bits - (bits >> 1), e, 40); - p = await randomProbablePrime(bits >> 1, e, 40); - n = p.mul(q); - } while (n.bitLength() !== bits); - - const phi = p.dec().imul(q.dec()); - - if (q.lt(p)) { - [p, q] = [q, p]; - } - - return { - n: n.toUint8Array(), - e: e.toUint8Array(), - d: e.modInv(phi).toUint8Array(), - p: p.toUint8Array(), - q: q.toUint8Array(), - // dp: d.mod(p.subn(1)), - // dq: d.mod(q.subn(1)), - u: p.modInv(q).toUint8Array() - }; - } - - /** - * Validate RSA parameters - * @param {Uint8Array} n - RSA public modulus - * @param {Uint8Array} e - RSA public exponent - * @param {Uint8Array} d - RSA private exponent - * @param {Uint8Array} p - RSA private prime p - * @param {Uint8Array} q - RSA private prime q - * @param {Uint8Array} u - RSA inverse of p w.r.t. q - * @returns {Promise} Whether params are valid. - * @async - */ - async function validateParams(n, e, d, p, q, u) { - const BigInteger = await util.getBigInteger(); - n = new BigInteger(n); - p = new BigInteger(p); - q = new BigInteger(q); - - // expect pq = n - if (!p.mul(q).equal(n)) { - return false; - } - - const two = new BigInteger(2); - // expect p*u = 1 mod q - u = new BigInteger(u); - if (!p.mul(u).mod(q).isOne()) { - return false; - } - - e = new BigInteger(e); - d = new BigInteger(d); - /** - * In RSA pkcs#1 the exponents (d, e) are inverses modulo lcm(p-1, q-1) - * We check that [de = 1 mod (p-1)] and [de = 1 mod (q-1)] - * By CRT on coprime factors of (p-1, q-1) it follows that [de = 1 mod lcm(p-1, q-1)] - * - * We blind the multiplication with r, and check that rde = r mod lcm(p-1, q-1) - */ - const nSizeOver3 = new BigInteger(Math.floor(n.bitLength() / 3)); - const r = await getRandomBigInteger(two, two.leftShift(nSizeOver3)); // r in [ 2, 2^{|n|/3} ) < p and q - const rde = r.mul(d).mul(e); - - const areInverses = rde.mod(p.dec()).equal(r) && rde.mod(q.dec()).equal(r); - if (!areInverses) { - return false; - } - - return true; - } - - async function bnSign(hashAlgo, n, d, hashed) { - const BigInteger = await util.getBigInteger(); - n = new BigInteger(n); - const m = new BigInteger(await emsaEncode(hashAlgo, hashed, n.byteLength())); - d = new BigInteger(d); - if (m.gte(n)) { - throw new Error('Message size cannot exceed modulus size'); - } - return m.modExp(d, n).toUint8Array('be', n.byteLength()); - } - - async function webSign(hashName, data, n, e, d, p, q, u) { - /** OpenPGP keys require that p < q, and Safari Web Crypto requires that p > q. - * We swap them in privateToJWK, so it usually works out, but nevertheless, - * not all OpenPGP keys are compatible with this requirement. - * OpenPGP.js used to generate RSA keys the wrong way around (p > q), and still - * does if the underlying Web Crypto does so (e.g. old MS Edge 50% of the time). - */ - const jwk = await privateToJWK(n, e, d, p, q, u); - const algo = { - name: 'RSASSA-PKCS1-v1_5', - hash: { name: hashName } - }; - const key = await webCrypto$5.importKey('jwk', jwk, algo, false, ['sign']); - // add hash field for ms edge support - return new Uint8Array(await webCrypto$5.sign({ 'name': 'RSASSA-PKCS1-v1_5', 'hash': hashName }, key, data)); - } - - async function nodeSign(hashAlgo, data, n, e, d, p, q, u) { - const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); - const pBNum = new BN(p); - const qBNum = new BN(q); - const dBNum = new BN(d); - const dq = dBNum.mod(qBNum.subn(1)); // d mod (q-1) - const dp = dBNum.mod(pBNum.subn(1)); // d mod (p-1) - const sign = nodeCrypto$6.createSign(enums.read(enums.hash, hashAlgo)); - sign.write(data); - sign.end(); - const keyObject = { - version: 0, - modulus: new BN(n), - publicExponent: new BN(e), - privateExponent: new BN(d), - // switch p and q - prime1: new BN(q), - prime2: new BN(p), - // switch dp and dq - exponent1: dq, - exponent2: dp, - coefficient: new BN(u) - }; - if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { //from version 11.6.0 Node supports der encoded key objects - const der = RSAPrivateKey.encode(keyObject, 'der'); - return new Uint8Array(sign.sign({ key: der, format: 'der', type: 'pkcs1' })); - } - const pem = RSAPrivateKey.encode(keyObject, 'pem', { - label: 'RSA PRIVATE KEY' - }); - return new Uint8Array(sign.sign(pem)); - } - - async function bnVerify(hashAlgo, s, n, e, hashed) { - const BigInteger = await util.getBigInteger(); - n = new BigInteger(n); - s = new BigInteger(s); - e = new BigInteger(e); - if (s.gte(n)) { - throw new Error('Signature size cannot exceed modulus size'); - } - const EM1 = s.modExp(e, n).toUint8Array('be', n.byteLength()); - const EM2 = await emsaEncode(hashAlgo, hashed, n.byteLength()); - return util.equalsUint8Array(EM1, EM2); - } - - async function webVerify(hashName, data, s, n, e) { - const jwk = publicToJWK(n, e); - const key = await webCrypto$5.importKey('jwk', jwk, { - name: 'RSASSA-PKCS1-v1_5', - hash: { name: hashName } - }, false, ['verify']); - // add hash field for ms edge support - return webCrypto$5.verify({ 'name': 'RSASSA-PKCS1-v1_5', 'hash': hashName }, key, s, data); - } - - async function nodeVerify(hashAlgo, data, s, n, e) { - const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); - - const verify = nodeCrypto$6.createVerify(enums.read(enums.hash, hashAlgo)); - verify.write(data); - verify.end(); - const keyObject = { - modulus: new BN(n), - publicExponent: new BN(e) - }; - let key; - if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { //from version 11.6.0 Node supports der encoded key objects - const der = RSAPublicKey.encode(keyObject, 'der'); - key = { key: der, format: 'der', type: 'pkcs1' }; - } else { - key = RSAPublicKey.encode(keyObject, 'pem', { - label: 'RSA PUBLIC KEY' - }); - } - try { - return await verify.verify(key, s); - } catch (err) { - return false; - } - } - - async function nodeEncrypt$1(data, n, e) { - const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); - - const keyObject = { - modulus: new BN(n), - publicExponent: new BN(e) - }; - let key; - if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { - const der = RSAPublicKey.encode(keyObject, 'der'); - key = { key: der, format: 'der', type: 'pkcs1', padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; - } else { - const pem = RSAPublicKey.encode(keyObject, 'pem', { - label: 'RSA PUBLIC KEY' - }); - key = { key: pem, padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; - } - return new Uint8Array(nodeCrypto$6.publicEncrypt(key, data)); - } - - async function bnEncrypt(data, n, e) { - const BigInteger = await util.getBigInteger(); - n = new BigInteger(n); - data = new BigInteger(await emeEncode(data, n.byteLength())); - e = new BigInteger(e); - if (data.gte(n)) { - throw new Error('Message size cannot exceed modulus size'); - } - return data.modExp(e, n).toUint8Array('be', n.byteLength()); - } - - async function nodeDecrypt$1(data, n, e, d, p, q, u, randomPayload) { - const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); - - const pBNum = new BN(p); - const qBNum = new BN(q); - const dBNum = new BN(d); - const dq = dBNum.mod(qBNum.subn(1)); // d mod (q-1) - const dp = dBNum.mod(pBNum.subn(1)); // d mod (p-1) - const keyObject = { - version: 0, - modulus: new BN(n), - publicExponent: new BN(e), - privateExponent: new BN(d), - // switch p and q - prime1: new BN(q), - prime2: new BN(p), - // switch dp and dq - exponent1: dq, - exponent2: dp, - coefficient: new BN(u) - }; - let key; - if (typeof nodeCrypto$6.createPrivateKey !== 'undefined') { - const der = RSAPrivateKey.encode(keyObject, 'der'); - key = { key: der, format: 'der' , type: 'pkcs1', padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; - } else { - const pem = RSAPrivateKey.encode(keyObject, 'pem', { - label: 'RSA PRIVATE KEY' - }); - key = { key: pem, padding: nodeCrypto$6.constants.RSA_PKCS1_PADDING }; - } - try { - return new Uint8Array(nodeCrypto$6.privateDecrypt(key, data)); - } catch (err) { - if (randomPayload) { - return randomPayload; - } - throw new Error('Decryption error'); - } - } - - async function bnDecrypt(data, n, e, d, p, q, u, randomPayload) { - const BigInteger = await util.getBigInteger(); - data = new BigInteger(data); - n = new BigInteger(n); - e = new BigInteger(e); - d = new BigInteger(d); - p = new BigInteger(p); - q = new BigInteger(q); - u = new BigInteger(u); - if (data.gte(n)) { - throw new Error('Data too large.'); - } - const dq = d.mod(q.dec()); // d mod (q-1) - const dp = d.mod(p.dec()); // d mod (p-1) - - const unblinder = (await getRandomBigInteger(new BigInteger(2), n)).mod(n); - const blinder = unblinder.modInv(n).modExp(e, n); - data = data.mul(blinder).mod(n); - - - const mp = data.modExp(dp, p); // data**{d mod (q-1)} mod p - const mq = data.modExp(dq, q); // data**{d mod (p-1)} mod q - const h = u.mul(mq.sub(mp)).mod(q); // u * (mq-mp) mod q (operands already < q) - - let result = h.mul(p).add(mp); // result < n due to relations above - - result = result.mul(unblinder).mod(n); - - - return emeDecode(result.toUint8Array('be', n.byteLength()), randomPayload); - } - - /** Convert Openpgp private key params to jwk key according to - * @link https://tools.ietf.org/html/rfc7517 - * @param {String} hashAlgo - * @param {Uint8Array} n - * @param {Uint8Array} e - * @param {Uint8Array} d - * @param {Uint8Array} p - * @param {Uint8Array} q - * @param {Uint8Array} u - */ - async function privateToJWK(n, e, d, p, q, u) { - const BigInteger = await util.getBigInteger(); - const pNum = new BigInteger(p); - const qNum = new BigInteger(q); - const dNum = new BigInteger(d); - - let dq = dNum.mod(qNum.dec()); // d mod (q-1) - let dp = dNum.mod(pNum.dec()); // d mod (p-1) - dp = dp.toUint8Array(); - dq = dq.toUint8Array(); - return { - kty: 'RSA', - n: uint8ArrayToB64(n, true), - e: uint8ArrayToB64(e, true), - d: uint8ArrayToB64(d, true), - // switch p and q - p: uint8ArrayToB64(q, true), - q: uint8ArrayToB64(p, true), - // switch dp and dq - dp: uint8ArrayToB64(dq, true), - dq: uint8ArrayToB64(dp, true), - qi: uint8ArrayToB64(u, true), - ext: true - }; - } - - /** Convert Openpgp key public params to jwk key according to - * @link https://tools.ietf.org/html/rfc7517 - * @param {String} hashAlgo - * @param {Uint8Array} n - * @param {Uint8Array} e - */ - function publicToJWK(n, e) { - return { - kty: 'RSA', - n: uint8ArrayToB64(n, true), - e: uint8ArrayToB64(e, true), - ext: true - }; - } - - var rsa = /*#__PURE__*/Object.freeze({ - __proto__: null, - sign: sign, - verify: verify, - encrypt: encrypt$1, - decrypt: decrypt$1, - generate: generate, - validateParams: validateParams - }); - - // GPG4Browsers - An OpenPGP implementation in javascript - - /** - * ElGamal Encryption function - * Note that in OpenPGP, the message needs to be padded with PKCS#1 (same as RSA) - * @param {Uint8Array} data - To be padded and encrypted - * @param {Uint8Array} p - * @param {Uint8Array} g - * @param {Uint8Array} y - * @returns {Promise<{ c1: Uint8Array, c2: Uint8Array }>} - * @async - */ - async function encrypt$2(data, p, g, y) { - const BigInteger = await util.getBigInteger(); - p = new BigInteger(p); - g = new BigInteger(g); - y = new BigInteger(y); - - const padded = await emeEncode(data, p.byteLength()); - const m = new BigInteger(padded); - - // OpenPGP uses a "special" version of ElGamal where g is generator of the full group Z/pZ* - // hence g has order p-1, and to avoid that k = 0 mod p-1, we need to pick k in [1, p-2] - const k = await getRandomBigInteger(new BigInteger(1), p.dec()); - return { - c1: g.modExp(k, p).toUint8Array(), - c2: y.modExp(k, p).imul(m).imod(p).toUint8Array() - }; - } - - /** - * ElGamal Encryption function - * @param {Uint8Array} c1 - * @param {Uint8Array} c2 - * @param {Uint8Array} p - * @param {Uint8Array} x - * @param {Uint8Array} randomPayload - Data to return on unpadding error, instead of throwing - * (needed for constant-time processing) - * @returns {Promise} Unpadded message. - * @throws {Error} on decryption error, unless `randomPayload` is given - * @async - */ - async function decrypt$2(c1, c2, p, x, randomPayload) { - const BigInteger = await util.getBigInteger(); - c1 = new BigInteger(c1); - c2 = new BigInteger(c2); - p = new BigInteger(p); - x = new BigInteger(x); - - const padded = c1.modExp(x, p).modInv(p).imul(c2).imod(p); - return emeDecode(padded.toUint8Array('be', p.byteLength()), randomPayload); - } - - /** - * Validate ElGamal parameters - * @param {Uint8Array} p - ElGamal prime - * @param {Uint8Array} g - ElGamal group generator - * @param {Uint8Array} y - ElGamal public key - * @param {Uint8Array} x - ElGamal private exponent - * @returns {Promise} Whether params are valid. - * @async - */ - async function validateParams$1(p, g, y, x) { - const BigInteger = await util.getBigInteger(); - p = new BigInteger(p); - g = new BigInteger(g); - y = new BigInteger(y); - - const one = new BigInteger(1); - // Check that 1 < g < p - if (g.lte(one) || g.gte(p)) { - return false; - } - - // Expect p-1 to be large - const pSize = new BigInteger(p.bitLength()); - const n1023 = new BigInteger(1023); - if (pSize.lt(n1023)) { - return false; - } - - /** - * g should have order p-1 - * Check that g ** (p-1) = 1 mod p - */ - if (!g.modExp(p.dec(), p).isOne()) { - return false; - } - - /** - * Since p-1 is not prime, g might have a smaller order that divides p-1 - * We want to make sure that the order is large enough to hinder a small subgroup attack - * - * We just check g**i != 1 for all i up to a threshold - */ - let res = g; - const i = new BigInteger(1); - const threshold = new BigInteger(2).leftShift(new BigInteger(17)); // we want order > threshold - while (i.lt(threshold)) { - res = res.mul(g).imod(p); - if (res.isOne()) { - return false; - } - i.iinc(); - } - - /** - * Re-derive public key y' = g ** x mod p - * Expect y == y' - * - * Blinded exponentiation computes g**{r(p-1) + x} to compare to y - */ - x = new BigInteger(x); - const two = new BigInteger(2); - const r = await getRandomBigInteger(two.leftShift(pSize.dec()), two.leftShift(pSize)); // draw r of same size as p-1 - const rqx = p.dec().imul(r).iadd(x); - if (!y.equal(g.modExp(rqx, p))) { - return false; - } - - return true; - } - - var elgamal = /*#__PURE__*/Object.freeze({ - __proto__: null, - encrypt: encrypt$2, - decrypt: decrypt$2, - validateParams: validateParams$1 - }); - - // OpenPGP.js - An OpenPGP implementation in javascript - - class OID { - constructor(oid) { - if (oid instanceof OID) { - this.oid = oid.oid; - } else if (util.isArray(oid) || - util.isUint8Array(oid)) { - oid = new Uint8Array(oid); - if (oid[0] === 0x06) { // DER encoded oid byte array - if (oid[1] !== oid.length - 2) { - throw new Error('Length mismatch in DER encoded oid'); - } - oid = oid.subarray(2); - } - this.oid = oid; - } else { - this.oid = ''; - } - } - - /** - * Method to read an OID object - * @param {Uint8Array} input - Where to read the OID from - * @returns {Number} Number of read bytes. - */ - read(input) { - if (input.length >= 1) { - const length = input[0]; - if (input.length >= 1 + length) { - this.oid = input.subarray(1, 1 + length); - return 1 + this.oid.length; - } - } - throw new Error('Invalid oid'); - } - - /** - * Serialize an OID object - * @returns {Uint8Array} Array with the serialized value the OID. - */ - write() { - return util.concatUint8Array([new Uint8Array([this.oid.length]), this.oid]); - } - - /** - * Serialize an OID object as a hex string - * @returns {string} String with the hex value of the OID. - */ - toHex() { - return util.uint8ArrayToHex(this.oid); - } - - /** - * If a known curve object identifier, return the canonical name of the curve - * @returns {string} String with the canonical name of the curve. - */ - getName() { - const hex = this.toHex(); - if (enums.curve[hex]) { - return enums.write(enums.curve, hex); - } else { - throw new Error('Unknown curve object identifier.'); - } - } - } - - // OpenPGP.js - An OpenPGP implementation in javascript - - function keyFromPrivate(indutnyCurve, priv) { - const keyPair = indutnyCurve.keyPair({ priv: priv }); - return keyPair; - } - - function keyFromPublic(indutnyCurve, pub) { - const keyPair = indutnyCurve.keyPair({ pub: pub }); - if (keyPair.validate().result !== true) { - throw new Error('Invalid elliptic public key'); - } - return keyPair; - } - - async function getIndutnyCurve(name) { - if (!defaultConfig.useIndutnyElliptic) { - throw new Error('This curve is only supported in the full build of OpenPGP.js'); - } - const { default: elliptic } = await Promise.resolve().then(function () { return elliptic$1; }); - return new elliptic.ec(name); - } - - // OpenPGP.js - An OpenPGP implementation in javascript - - const webCrypto$6 = util.getWebCrypto(); - const nodeCrypto$7 = util.getNodeCrypto(); - - const webCurves = { - 'p256': 'P-256', - 'p384': 'P-384', - 'p521': 'P-521' - }; - const knownCurves = nodeCrypto$7 ? nodeCrypto$7.getCurves() : []; - const nodeCurves = nodeCrypto$7 ? { - secp256k1: knownCurves.includes('secp256k1') ? 'secp256k1' : undefined, - p256: knownCurves.includes('prime256v1') ? 'prime256v1' : undefined, - p384: knownCurves.includes('secp384r1') ? 'secp384r1' : undefined, - p521: knownCurves.includes('secp521r1') ? 'secp521r1' : undefined, - ed25519: knownCurves.includes('ED25519') ? 'ED25519' : undefined, - curve25519: knownCurves.includes('X25519') ? 'X25519' : undefined, - brainpoolP256r1: knownCurves.includes('brainpoolP256r1') ? 'brainpoolP256r1' : undefined, - brainpoolP384r1: knownCurves.includes('brainpoolP384r1') ? 'brainpoolP384r1' : undefined, - brainpoolP512r1: knownCurves.includes('brainpoolP512r1') ? 'brainpoolP512r1' : undefined - } : {}; - - const curves = { - p256: { - oid: [0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07], - keyType: enums.publicKey.ecdsa, - hash: enums.hash.sha256, - cipher: enums.symmetric.aes128, - node: nodeCurves.p256, - web: webCurves.p256, - payloadSize: 32, - sharedSize: 256 - }, - p384: { - oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22], - keyType: enums.publicKey.ecdsa, - hash: enums.hash.sha384, - cipher: enums.symmetric.aes192, - node: nodeCurves.p384, - web: webCurves.p384, - payloadSize: 48, - sharedSize: 384 - }, - p521: { - oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23], - keyType: enums.publicKey.ecdsa, - hash: enums.hash.sha512, - cipher: enums.symmetric.aes256, - node: nodeCurves.p521, - web: webCurves.p521, - payloadSize: 66, - sharedSize: 528 - }, - secp256k1: { - oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x0A], - keyType: enums.publicKey.ecdsa, - hash: enums.hash.sha256, - cipher: enums.symmetric.aes128, - node: nodeCurves.secp256k1, - payloadSize: 32 - }, - ed25519: { - oid: [0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01], - keyType: enums.publicKey.eddsa, - hash: enums.hash.sha512, - node: false, // nodeCurves.ed25519 TODO - payloadSize: 32 - }, - curve25519: { - oid: [0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01], - keyType: enums.publicKey.ecdh, - hash: enums.hash.sha256, - cipher: enums.symmetric.aes128, - node: false, // nodeCurves.curve25519 TODO - payloadSize: 32 - }, - brainpoolP256r1: { - oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07], - keyType: enums.publicKey.ecdsa, - hash: enums.hash.sha256, - cipher: enums.symmetric.aes128, - node: nodeCurves.brainpoolP256r1, - payloadSize: 32 - }, - brainpoolP384r1: { - oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B], - keyType: enums.publicKey.ecdsa, - hash: enums.hash.sha384, - cipher: enums.symmetric.aes192, - node: nodeCurves.brainpoolP384r1, - payloadSize: 48 - }, - brainpoolP512r1: { - oid: [0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D], - keyType: enums.publicKey.ecdsa, - hash: enums.hash.sha512, - cipher: enums.symmetric.aes256, - node: nodeCurves.brainpoolP512r1, - payloadSize: 64 - } - }; - - class Curve { - constructor(oidOrName, params) { - try { - if (util.isArray(oidOrName) || - util.isUint8Array(oidOrName)) { - // by oid byte array - oidOrName = new OID(oidOrName); - } - if (oidOrName instanceof OID) { - // by curve OID - oidOrName = oidOrName.getName(); - } - // by curve name or oid string - this.name = enums.write(enums.curve, oidOrName); - } catch (err) { - throw new Error('Not valid curve'); - } - params = params || curves[this.name]; - - this.keyType = params.keyType; - - this.oid = params.oid; - this.hash = params.hash; - this.cipher = params.cipher; - this.node = params.node && curves[this.name]; - this.web = params.web && curves[this.name]; - this.payloadSize = params.payloadSize; - if (this.web && util.getWebCrypto()) { - this.type = 'web'; - } else if (this.node && util.getNodeCrypto()) { - this.type = 'node'; - } else if (this.name === 'curve25519') { - this.type = 'curve25519'; - } else if (this.name === 'ed25519') { - this.type = 'ed25519'; - } - } - - async genKeyPair() { - let keyPair; - switch (this.type) { - case 'web': - try { - return await webGenKeyPair(this.name); - } catch (err) { - util.printDebugError('Browser did not support generating ec key ' + err.message); - break; - } - case 'node': - return nodeGenKeyPair(this.name); - case 'curve25519': { - const privateKey = await getRandomBytes(32); - privateKey[0] = (privateKey[0] & 127) | 64; - privateKey[31] &= 248; - const secretKey = privateKey.slice().reverse(); - keyPair = naclFastLight.box.keyPair.fromSecretKey(secretKey); - const publicKey = util.concatUint8Array([new Uint8Array([0x40]), keyPair.publicKey]); - return { publicKey, privateKey }; - } - case 'ed25519': { - const privateKey = await getRandomBytes(32); - const keyPair = naclFastLight.sign.keyPair.fromSeed(privateKey); - const publicKey = util.concatUint8Array([new Uint8Array([0x40]), keyPair.publicKey]); - return { publicKey, privateKey }; - } - } - const indutnyCurve = await getIndutnyCurve(this.name); - keyPair = await indutnyCurve.genKeyPair({ - entropy: util.uint8ArrayToString(await getRandomBytes(32)) - }); - return { publicKey: new Uint8Array(keyPair.getPublic('array', false)), privateKey: keyPair.getPrivate().toArrayLike(Uint8Array) }; - } - } - - async function generate$1(curve) { - const BigInteger = await util.getBigInteger(); - - curve = new Curve(curve); - const keyPair = await curve.genKeyPair(); - const Q = new BigInteger(keyPair.publicKey).toUint8Array(); - const secret = new BigInteger(keyPair.privateKey).toUint8Array('be', curve.payloadSize); - return { - oid: curve.oid, - Q, - secret, - hash: curve.hash, - cipher: curve.cipher - }; - } - - /** - * Get preferred hash algo to use with the given curve - * @param {module:type/oid} oid - curve oid - * @returns {enums.hash} hash algorithm - */ - function getPreferredHashAlgo(oid) { - return curves[enums.write(enums.curve, oid.toHex())].hash; - } - - /** - * Validate ECDH and ECDSA parameters - * Not suitable for EdDSA (different secret key format) - * @param {module:enums.publicKey} algo - EC algorithm, to filter supported curves - * @param {module:type/oid} oid - EC object identifier - * @param {Uint8Array} Q - EC public point - * @param {Uint8Array} d - EC secret scalar - * @returns {Promise} Whether params are valid. - * @async - */ - async function validateStandardParams(algo, oid, Q, d) { - const supportedCurves = { - p256: true, - p384: true, - p521: true, - secp256k1: true, - curve25519: algo === enums.publicKey.ecdh, - brainpoolP256r1: true, - brainpoolP384r1: true, - brainpoolP512r1: true - }; - - // Check whether the given curve is supported - const curveName = oid.getName(); - if (!supportedCurves[curveName]) { - return false; - } - - if (curveName === 'curve25519') { - d = d.slice().reverse(); - // Re-derive public point Q' - const { publicKey } = naclFastLight.box.keyPair.fromSecretKey(d); - - Q = new Uint8Array(Q); - const dG = new Uint8Array([0x40, ...publicKey]); // Add public key prefix - if (!util.equalsUint8Array(dG, Q)) { - return false; - } - - return true; - } - - const curve = await getIndutnyCurve(curveName); - try { - // Parse Q and check that it is on the curve but not at infinity - Q = keyFromPublic(curve, Q).getPublic(); - } catch (validationErrors) { - return false; - } - - /** - * Re-derive public point Q' = dG from private key - * Expect Q == Q' - */ - const dG = keyFromPrivate(curve, d).getPublic(); - if (!dG.eq(Q)) { - return false; - } - - return true; - } - - ////////////////////////// - // // - // Helper functions // - // // - ////////////////////////// - - - async function webGenKeyPair(name) { - // Note: keys generated with ECDSA and ECDH are structurally equivalent - const webCryptoKey = await webCrypto$6.generateKey({ name: 'ECDSA', namedCurve: webCurves[name] }, true, ['sign', 'verify']); - - const privateKey = await webCrypto$6.exportKey('jwk', webCryptoKey.privateKey); - const publicKey = await webCrypto$6.exportKey('jwk', webCryptoKey.publicKey); - - return { - publicKey: jwkToRawPublic(publicKey), - privateKey: b64ToUint8Array(privateKey.d) - }; - } - - async function nodeGenKeyPair(name) { - // Note: ECDSA and ECDH key generation is structurally equivalent - const ecdh = nodeCrypto$7.createECDH(nodeCurves[name]); - await ecdh.generateKeys(); - return { - publicKey: new Uint8Array(ecdh.getPublicKey()), - privateKey: new Uint8Array(ecdh.getPrivateKey()) - }; - } - - ////////////////////////// - // // - // Helper functions // - // // - ////////////////////////// - - /** - * @param {JsonWebKey} jwk - key for conversion - * - * @returns {Uint8Array} Raw public key. - */ - function jwkToRawPublic(jwk) { - const bufX = b64ToUint8Array(jwk.x); - const bufY = b64ToUint8Array(jwk.y); - const publicKey = new Uint8Array(bufX.length + bufY.length + 1); - publicKey[0] = 0x04; - publicKey.set(bufX, 1); - publicKey.set(bufY, bufX.length + 1); - return publicKey; - } - - /** - * @param {Integer} payloadSize - ec payload size - * @param {String} name - curve name - * @param {Uint8Array} publicKey - public key - * - * @returns {JsonWebKey} Public key in jwk format. - */ - function rawPublicToJWK(payloadSize, name, publicKey) { - const len = payloadSize; - const bufX = publicKey.slice(1, len + 1); - const bufY = publicKey.slice(len + 1, len * 2 + 1); - // https://www.rfc-editor.org/rfc/rfc7518.txt - const jwk = { - kty: 'EC', - crv: name, - x: uint8ArrayToB64(bufX, true), - y: uint8ArrayToB64(bufY, true), - ext: true - }; - return jwk; - } - - /** - * @param {Integer} payloadSize - ec payload size - * @param {String} name - curve name - * @param {Uint8Array} publicKey - public key - * @param {Uint8Array} privateKey - private key - * - * @returns {JsonWebKey} Private key in jwk format. - */ - function privateToJWK$1(payloadSize, name, publicKey, privateKey) { - const jwk = rawPublicToJWK(payloadSize, name, publicKey); - jwk.d = uint8ArrayToB64(privateKey, true); - return jwk; - } - - // OpenPGP.js - An OpenPGP implementation in javascript - - const webCrypto$7 = util.getWebCrypto(); - const nodeCrypto$8 = util.getNodeCrypto(); - - /** - * Sign a message using the provided key - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {module:enums.hash} hashAlgo - Hash algorithm used to sign - * @param {Uint8Array} message - Message to sign - * @param {Uint8Array} publicKey - Public key - * @param {Uint8Array} privateKey - Private key used to sign the message - * @param {Uint8Array} hashed - The hashed message - * @returns {Promise<{ - * r: Uint8Array, - * s: Uint8Array - * }>} Signature of the message - * @async - */ - async function sign$1(oid, hashAlgo, message, publicKey, privateKey, hashed) { - const curve = new Curve(oid); - if (message && !util.isStream(message)) { - const keyPair = { publicKey, privateKey }; - switch (curve.type) { - case 'web': { - // If browser doesn't support a curve, we'll catch it - try { - // Need to await to make sure browser succeeds - return await webSign$1(curve, hashAlgo, message, keyPair); - } catch (err) { - // We do not fallback if the error is related to key integrity - // Unfortunaley Safari does not support p521 and throws a DataError when using it - // So we need to always fallback for that curve - if (curve.name !== 'p521' && (err.name === 'DataError' || err.name === 'OperationError')) { - throw err; - } - util.printDebugError('Browser did not support signing: ' + err.message); - } - break; - } - case 'node': { - const signature = await nodeSign$1(curve, hashAlgo, message, keyPair); - return { - r: signature.r.toArrayLike(Uint8Array), - s: signature.s.toArrayLike(Uint8Array) - }; - } - } - } - return ellipticSign(curve, hashed, privateKey); - } - - /** - * Verifies if a signature is valid for a message - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {module:enums.hash} hashAlgo - Hash algorithm used in the signature - * @param {{r: Uint8Array, - s: Uint8Array}} signature Signature to verify - * @param {Uint8Array} message - Message to verify - * @param {Uint8Array} publicKey - Public key used to verify the message - * @param {Uint8Array} hashed - The hashed message - * @returns {Boolean} - * @async - */ - async function verify$1(oid, hashAlgo, signature, message, publicKey, hashed) { - const curve = new Curve(oid); - if (message && !util.isStream(message)) { - switch (curve.type) { - case 'web': - try { - // Need to await to make sure browser succeeds - return await webVerify$1(curve, hashAlgo, signature, message, publicKey); - } catch (err) { - // We do not fallback if the error is related to key integrity - // Unfortunately Safari does not support p521 and throws a DataError when using it - // So we need to always fallback for that curve - if (curve.name !== 'p521' && (err.name === 'DataError' || err.name === 'OperationError')) { - throw err; - } - util.printDebugError('Browser did not support verifying: ' + err.message); - } - break; - case 'node': - return nodeVerify$1(curve, hashAlgo, signature, message, publicKey); - } - } - const digest = (typeof hashAlgo === 'undefined') ? message : hashed; - return ellipticVerify(curve, signature, digest, publicKey); - } - - /** - * Validate ECDSA parameters - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {Uint8Array} Q - ECDSA public point - * @param {Uint8Array} d - ECDSA secret scalar - * @returns {Promise} Whether params are valid. - * @async - */ - async function validateParams$2(oid, Q, d) { - const curve = new Curve(oid); - // Reject curves x25519 and ed25519 - if (curve.keyType !== enums.publicKey.ecdsa) { - return false; - } - - // To speed up the validation, we try to use node- or webcrypto when available - // and sign + verify a random message - switch (curve.type) { - case 'web': - case 'node': { - const message = await getRandomBytes(8); - const hashAlgo = enums.hash.sha256; - const hashed = await hash.digest(hashAlgo, message); - try { - const signature = await sign$1(oid, hashAlgo, message, Q, d, hashed); - return await verify$1(oid, hashAlgo, signature, message, Q, hashed); - } catch (err) { - return false; - } - } - default: - return validateStandardParams(enums.publicKey.ecdsa, oid, Q, d); - } - } - - - ////////////////////////// - // // - // Helper functions // - // // - ////////////////////////// - - async function ellipticSign(curve, hashed, privateKey) { - const indutnyCurve = await getIndutnyCurve(curve.name); - const key = keyFromPrivate(indutnyCurve, privateKey); - const signature = key.sign(hashed); - return { - r: signature.r.toArrayLike(Uint8Array), - s: signature.s.toArrayLike(Uint8Array) - }; - } - - async function ellipticVerify(curve, signature, digest, publicKey) { - const indutnyCurve = await getIndutnyCurve(curve.name); - const key = keyFromPublic(indutnyCurve, publicKey); - return key.verify(digest, signature); - } - - async function webSign$1(curve, hashAlgo, message, keyPair) { - const len = curve.payloadSize; - const jwk = privateToJWK$1(curve.payloadSize, webCurves[curve.name], keyPair.publicKey, keyPair.privateKey); - const key = await webCrypto$7.importKey( - 'jwk', - jwk, - { - 'name': 'ECDSA', - 'namedCurve': webCurves[curve.name], - 'hash': { name: enums.read(enums.webHash, curve.hash) } - }, - false, - ['sign'] - ); - - const signature = new Uint8Array(await webCrypto$7.sign( - { - 'name': 'ECDSA', - 'namedCurve': webCurves[curve.name], - 'hash': { name: enums.read(enums.webHash, hashAlgo) } - }, - key, - message - )); - - return { - r: signature.slice(0, len), - s: signature.slice(len, len << 1) - }; - } - - async function webVerify$1(curve, hashAlgo, { r, s }, message, publicKey) { - const jwk = rawPublicToJWK(curve.payloadSize, webCurves[curve.name], publicKey); - const key = await webCrypto$7.importKey( - 'jwk', - jwk, - { - 'name': 'ECDSA', - 'namedCurve': webCurves[curve.name], - 'hash': { name: enums.read(enums.webHash, curve.hash) } - }, - false, - ['verify'] - ); - - const signature = util.concatUint8Array([r, s]).buffer; - - return webCrypto$7.verify( - { - 'name': 'ECDSA', - 'namedCurve': webCurves[curve.name], - 'hash': { name: enums.read(enums.webHash, hashAlgo) } - }, - key, - signature, - message - ); - } - - async function nodeSign$1(curve, hashAlgo, message, keyPair) { - const sign = nodeCrypto$8.createSign(enums.read(enums.hash, hashAlgo)); - sign.write(message); - sign.end(); - const key = ECPrivateKey.encode({ - version: 1, - parameters: curve.oid, - privateKey: Array.from(keyPair.privateKey), - publicKey: { unused: 0, data: Array.from(keyPair.publicKey) } - }, 'pem', { - label: 'EC PRIVATE KEY' - }); - - return ECDSASignature.decode(sign.sign(key), 'der'); - } - - async function nodeVerify$1(curve, hashAlgo, { r, s }, message, publicKey) { - const { default: BN } = await Promise.resolve().then(function () { return bn$1; }); - - const verify = nodeCrypto$8.createVerify(enums.read(enums.hash, hashAlgo)); - verify.write(message); - verify.end(); - const key = SubjectPublicKeyInfo.encode({ - algorithm: { - algorithm: [1, 2, 840, 10045, 2, 1], - parameters: curve.oid - }, - subjectPublicKey: { unused: 0, data: Array.from(publicKey) } - }, 'pem', { - label: 'PUBLIC KEY' - }); - const signature = ECDSASignature.encode({ - r: new BN(r), s: new BN(s) - }, 'der'); - - try { - return verify.verify(key, signature); - } catch (err) { - return false; - } - } - - // Originally written by Owen Smith https://github.com/omsmith - // Adapted on Feb 2018 from https://github.com/Brightspace/node-jwk-to-pem/ - - /* eslint-disable no-invalid-this */ - - const asn1$1 = nodeCrypto$8 ? void('asn1.js') : undefined; - - const ECDSASignature = nodeCrypto$8 ? - asn1$1.define('ECDSASignature', function() { - this.seq().obj( - this.key('r').int(), - this.key('s').int() - ); - }) : undefined; - - const ECPrivateKey = nodeCrypto$8 ? - asn1$1.define('ECPrivateKey', function() { - this.seq().obj( - this.key('version').int(), - this.key('privateKey').octstr(), - this.key('parameters').explicit(0).optional().any(), - this.key('publicKey').explicit(1).optional().bitstr() - ); - }) : undefined; - - const AlgorithmIdentifier = nodeCrypto$8 ? - asn1$1.define('AlgorithmIdentifier', function() { - this.seq().obj( - this.key('algorithm').objid(), - this.key('parameters').optional().any() - ); - }) : undefined; - - const SubjectPublicKeyInfo = nodeCrypto$8 ? - asn1$1.define('SubjectPublicKeyInfo', function() { - this.seq().obj( - this.key('algorithm').use(AlgorithmIdentifier), - this.key('subjectPublicKey').bitstr() - ); - }) : undefined; - - var ecdsa = /*#__PURE__*/Object.freeze({ - __proto__: null, - sign: sign$1, - verify: verify$1, - validateParams: validateParams$2 - }); - - // OpenPGP.js - An OpenPGP implementation in javascript - - naclFastLight.hash = bytes => new Uint8Array(_512().update(bytes).digest()); - - /** - * Sign a message using the provided key - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {module:enums.hash} hashAlgo - Hash algorithm used to sign (must be sha256 or stronger) - * @param {Uint8Array} message - Message to sign - * @param {Uint8Array} publicKey - Public key - * @param {Uint8Array} privateKey - Private key used to sign the message - * @param {Uint8Array} hashed - The hashed message - * @returns {Promise<{ - * r: Uint8Array, - * s: Uint8Array - * }>} Signature of the message - * @async - */ - async function sign$2(oid, hashAlgo, message, publicKey, privateKey, hashed) { - if (hash.getHashByteLength(hashAlgo) < hash.getHashByteLength(enums.hash.sha256)) { - // see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2 - throw new Error('Hash algorithm too weak: sha256 or stronger is required for EdDSA.'); - } - const secretKey = util.concatUint8Array([privateKey, publicKey.subarray(1)]); - const signature = naclFastLight.sign.detached(hashed, secretKey); - // EdDSA signature params are returned in little-endian format - return { - r: signature.subarray(0, 32), - s: signature.subarray(32) - }; - } - - /** - * Verifies if a signature is valid for a message - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {module:enums.hash} hashAlgo - Hash algorithm used in the signature - * @param {{r: Uint8Array, - s: Uint8Array}} signature Signature to verify the message - * @param {Uint8Array} m - Message to verify - * @param {Uint8Array} publicKey - Public key used to verify the message - * @param {Uint8Array} hashed - The hashed message - * @returns {Boolean} - * @async - */ - async function verify$2(oid, hashAlgo, { r, s }, m, publicKey, hashed) { - const signature = util.concatUint8Array([r, s]); - return naclFastLight.sign.detached.verify(hashed, signature, publicKey.subarray(1)); - } - /** - * Validate EdDSA parameters - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {Uint8Array} Q - EdDSA public point - * @param {Uint8Array} k - EdDSA secret seed - * @returns {Promise} Whether params are valid. - * @async - */ - async function validateParams$3(oid, Q, k) { - // Check whether the given curve is supported - if (oid.getName() !== 'ed25519') { - return false; - } - - /** - * Derive public point Q' = dG from private key - * and expect Q == Q' - */ - const { publicKey } = naclFastLight.sign.keyPair.fromSeed(k); - const dG = new Uint8Array([0x40, ...publicKey]); // Add public key prefix - return util.equalsUint8Array(Q, dG); - } - - var eddsa = /*#__PURE__*/Object.freeze({ - __proto__: null, - sign: sign$2, - verify: verify$2, - validateParams: validateParams$3 - }); - - // OpenPGP.js - An OpenPGP implementation in javascript - - /** - * AES key wrap - * @function - * @param {Uint8Array} key - * @param {Uint8Array} data - * @returns {Uint8Array} - */ - function wrap(key, data) { - const aes = new cipher['aes' + (key.length * 8)](key); - const IV = new Uint32Array([0xA6A6A6A6, 0xA6A6A6A6]); - const P = unpack(data); - let A = IV; - const R = P; - const n = P.length / 2; - const t = new Uint32Array([0, 0]); - let B = new Uint32Array(4); - for (let j = 0; j <= 5; ++j) { - for (let i = 0; i < n; ++i) { - t[1] = n * j + (1 + i); - // B = A - B[0] = A[0]; - B[1] = A[1]; - // B = A || R[i] - B[2] = R[2 * i]; - B[3] = R[2 * i + 1]; - // B = AES(K, B) - B = unpack(aes.encrypt(pack(B))); - // A = MSB(64, B) ^ t - A = B.subarray(0, 2); - A[0] ^= t[0]; - A[1] ^= t[1]; - // R[i] = LSB(64, B) - R[2 * i] = B[2]; - R[2 * i + 1] = B[3]; - } - } - return pack(A, R); - } - - /** - * AES key unwrap - * @function - * @param {String} key - * @param {String} data - * @returns {Uint8Array} - * @throws {Error} - */ - function unwrap(key, data) { - const aes = new cipher['aes' + (key.length * 8)](key); - const IV = new Uint32Array([0xA6A6A6A6, 0xA6A6A6A6]); - const C = unpack(data); - let A = C.subarray(0, 2); - const R = C.subarray(2); - const n = C.length / 2 - 1; - const t = new Uint32Array([0, 0]); - let B = new Uint32Array(4); - for (let j = 5; j >= 0; --j) { - for (let i = n - 1; i >= 0; --i) { - t[1] = n * j + (i + 1); - // B = A ^ t - B[0] = A[0] ^ t[0]; - B[1] = A[1] ^ t[1]; - // B = (A ^ t) || R[i] - B[2] = R[2 * i]; - B[3] = R[2 * i + 1]; - // B = AES-1(B) - B = unpack(aes.decrypt(pack(B))); - // A = MSB(64, B) - A = B.subarray(0, 2); - // R[i] = LSB(64, B) - R[2 * i] = B[2]; - R[2 * i + 1] = B[3]; - } - } - if (A[0] === IV[0] && A[1] === IV[1]) { - return pack(R); - } - throw new Error('Key Data Integrity failed'); - } - - function createArrayBuffer(data) { - if (util.isString(data)) { - const { length } = data; - const buffer = new ArrayBuffer(length); - const view = new Uint8Array(buffer); - for (let j = 0; j < length; ++j) { - view[j] = data.charCodeAt(j); - } - return buffer; - } - return new Uint8Array(data).buffer; - } - - function unpack(data) { - const { length } = data; - const buffer = createArrayBuffer(data); - const view = new DataView(buffer); - const arr = new Uint32Array(length / 4); - for (let i = 0; i < length / 4; ++i) { - arr[i] = view.getUint32(4 * i); - } - return arr; - } - - function pack() { - let length = 0; - for (let k = 0; k < arguments.length; ++k) { - length += 4 * arguments[k].length; - } - const buffer = new ArrayBuffer(length); - const view = new DataView(buffer); - let offset = 0; - for (let i = 0; i < arguments.length; ++i) { - for (let j = 0; j < arguments[i].length; ++j) { - view.setUint32(offset + 4 * j, arguments[i][j]); - } - offset += 4 * arguments[i].length; - } - return new Uint8Array(buffer); - } - - var aesKW = /*#__PURE__*/Object.freeze({ - __proto__: null, - wrap: wrap, - unwrap: unwrap - }); - - // OpenPGP.js - An OpenPGP implementation in javascript - - /** - * @fileoverview Functions to add and remove PKCS5 padding - * @see PublicKeyEncryptedSessionKeyPacket - * @module crypto/pkcs5 - * @private - */ - - /** - * Add pkcs5 padding to a message - * @param {Uint8Array} message - message to pad - * @returns {Uint8Array} Padded message. - */ - function encode$1(message) { - const c = 8 - (message.length % 8); - const padded = new Uint8Array(message.length + c).fill(c); - padded.set(message); - return padded; - } - - /** - * Remove pkcs5 padding from a message - * @param {Uint8Array} message - message to remove padding from - * @returns {Uint8Array} Message without padding. - */ - function decode$1(message) { - const len = message.length; - if (len > 0) { - const c = message[len - 1]; - if (c >= 1) { - const provided = message.subarray(len - c); - const computed = new Uint8Array(c).fill(c); - if (util.equalsUint8Array(provided, computed)) { - return message.subarray(0, len - c); - } - } - } - throw new Error('Invalid padding'); - } - - var pkcs5 = /*#__PURE__*/Object.freeze({ - __proto__: null, - encode: encode$1, - decode: decode$1 - }); - - // OpenPGP.js - An OpenPGP implementation in javascript - - class ECDHSymmetricKey { - constructor(data) { - if (typeof data === 'undefined') { - data = new Uint8Array([]); - } else if (util.isString(data)) { - data = util.stringToUint8Array(data); - } else { - data = new Uint8Array(data); - } - this.data = data; - } - - /** - * Read an ECDHSymmetricKey from an Uint8Array - * @param {Uint8Array} input - Where to read the encoded symmetric key from - * @returns {Number} Number of read bytes. - */ - read(input) { - if (input.length >= 1) { - const length = input[0]; - if (input.length >= 1 + length) { - this.data = input.subarray(1, 1 + length); - return 1 + this.data.length; - } - } - throw new Error('Invalid symmetric key'); - } - - /** - * Write an ECDHSymmetricKey as an Uint8Array - * @returns {Uint8Array} An array containing the value - */ - write() { - return util.concatUint8Array([new Uint8Array([this.data.length]), this.data]); - } - } - - // OpenPGP.js - An OpenPGP implementation in javascript - // Copyright (C) 2015-2016 Decentral - // - // This library is free software; you can redistribute it and/or - // modify it under the terms of the GNU Lesser General Public - // License as published by the Free Software Foundation; either - // version 3.0 of the License, or (at your option) any later version. - // - // This library is distributed in the hope that it will be useful, - // but WITHOUT ANY WARRANTY; without even the implied warranty of - // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - // Lesser General Public License for more details. - // - // You should have received a copy of the GNU Lesser General Public - // License along with this library; if not, write to the Free Software - // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - - /** - * Implementation of type KDF parameters - * - * {@link https://tools.ietf.org/html/rfc6637#section-7|RFC 6637 7}: - * A key derivation function (KDF) is necessary to implement the EC - * encryption. The Concatenation Key Derivation Function (Approved - * Alternative 1) [NIST-SP800-56A] with the KDF hash function that is - * SHA2-256 [FIPS-180-3] or stronger is REQUIRED. - * @module type/kdf_params - * @private - */ - - class KDFParams { - /** - * @param {enums.hash} hash - Hash algorithm - * @param {enums.symmetric} cipher - Symmetric algorithm - */ - constructor(data) { - if (data) { - const { hash, cipher } = data; - this.hash = hash; - this.cipher = cipher; - } else { - this.hash = null; - this.cipher = null; - } - } - - /** - * Read KDFParams from an Uint8Array - * @param {Uint8Array} input - Where to read the KDFParams from - * @returns {Number} Number of read bytes. - */ - read(input) { - if (input.length < 4 || input[0] !== 3 || input[1] !== 1) { - throw new Error('Cannot read KDFParams'); - } - this.hash = input[2]; - this.cipher = input[3]; - return 4; - } - - /** - * Write KDFParams to an Uint8Array - * @returns {Uint8Array} Array with the KDFParams value - */ - write() { - return new Uint8Array([3, 1, this.hash, this.cipher]); - } - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - /** - * Encrypts data using specified algorithm and public key parameters. - * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} for public key algorithms. - * @param {module:enums.publicKey} algo - Public key algorithm - * @param {Object} publicParams - Algorithm-specific public key parameters - * @param {Uint8Array} data - Data to be encrypted - * @param {Uint8Array} fingerprint - Recipient fingerprint - * @returns {Promise} Encrypted session key parameters. - * @async - */ - async function publicKeyEncrypt(algo, publicParams, data, fingerprint) { - switch (algo) { - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaEncryptSign: { - const { n, e } = publicParams; - const c = await publicKey.rsa.encrypt(data, n, e); - return { c }; - } - case enums.publicKey.elgamal: { - const { p, g, y } = publicParams; - return publicKey.elgamal.encrypt(data, p, g, y); - } - case enums.publicKey.ecdh: { - const { oid, Q, kdfParams } = publicParams; - const { publicKey: V, wrappedKey: C } = await publicKey.elliptic.ecdh.encrypt( - oid, kdfParams, data, Q, fingerprint); - return { V, C: new ECDHSymmetricKey(C) }; - } - default: - return []; - } - } - - /** - * Decrypts data using specified algorithm and private key parameters. - * See {@link https://tools.ietf.org/html/rfc4880#section-5.5.3|RFC 4880 5.5.3} - * @param {module:enums.publicKey} algo - Public key algorithm - * @param {Object} publicKeyParams - Algorithm-specific public key parameters - * @param {Object} privateKeyParams - Algorithm-specific private key parameters - * @param {Object} sessionKeyParams - Encrypted session key parameters - * @param {Uint8Array} fingerprint - Recipient fingerprint - * @param {Uint8Array} [randomPayload] - Data to return on decryption error, instead of throwing - * (needed for constant-time processing in RSA and ElGamal) - * @returns {Promise} Decrypted data. - * @throws {Error} on sensitive decryption error, unless `randomPayload` is given - * @async - */ - async function publicKeyDecrypt(algo, publicKeyParams, privateKeyParams, sessionKeyParams, fingerprint, randomPayload) { - switch (algo) { - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaEncrypt: { - const { c } = sessionKeyParams; - const { n, e } = publicKeyParams; - const { d, p, q, u } = privateKeyParams; - return publicKey.rsa.decrypt(c, n, e, d, p, q, u, randomPayload); - } - case enums.publicKey.elgamal: { - const { c1, c2 } = sessionKeyParams; - const p = publicKeyParams.p; - const x = privateKeyParams.x; - return publicKey.elgamal.decrypt(c1, c2, p, x, randomPayload); - } - case enums.publicKey.ecdh: { - const { oid, Q, kdfParams } = publicKeyParams; - const { d } = privateKeyParams; - const { V, C } = sessionKeyParams; - return publicKey.elliptic.ecdh.decrypt( - oid, kdfParams, V, C.data, Q, d, fingerprint); - } - default: - throw new Error('Invalid public key encryption algorithm.'); - } - } - - /** - * Parse public key material in binary form to get the key parameters - * @param {module:enums.publicKey} algo - The key algorithm - * @param {Uint8Array} bytes - The key material to parse - * @returns {{ read: Number, publicParams: Object }} Number of read bytes plus key parameters referenced by name. - */ - function parsePublicKeyParams(algo, bytes) { - let read = 0; - switch (algo) { - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaSign: { - const n = util.readMPI(bytes.subarray(read)); read += n.length + 2; - const e = util.readMPI(bytes.subarray(read)); read += e.length + 2; - return { read, publicParams: { n, e } }; - } - case enums.publicKey.dsa: { - const p = util.readMPI(bytes.subarray(read)); read += p.length + 2; - const q = util.readMPI(bytes.subarray(read)); read += q.length + 2; - const g = util.readMPI(bytes.subarray(read)); read += g.length + 2; - const y = util.readMPI(bytes.subarray(read)); read += y.length + 2; - return { read, publicParams: { p, q, g, y } }; - } - case enums.publicKey.elgamal: { - const p = util.readMPI(bytes.subarray(read)); read += p.length + 2; - const g = util.readMPI(bytes.subarray(read)); read += g.length + 2; - const y = util.readMPI(bytes.subarray(read)); read += y.length + 2; - return { read, publicParams: { p, g, y } }; - } - case enums.publicKey.ecdsa: { - const oid = new OID(); read += oid.read(bytes); - const Q = util.readMPI(bytes.subarray(read)); read += Q.length + 2; - return { read: read, publicParams: { oid, Q } }; - } - case enums.publicKey.eddsa: { - const oid = new OID(); read += oid.read(bytes); - let Q = util.readMPI(bytes.subarray(read)); read += Q.length + 2; - Q = util.leftPad(Q, 33); - return { read: read, publicParams: { oid, Q } }; - } - case enums.publicKey.ecdh: { - const oid = new OID(); read += oid.read(bytes); - const Q = util.readMPI(bytes.subarray(read)); read += Q.length + 2; - const kdfParams = new KDFParams(); read += kdfParams.read(bytes.subarray(read)); - return { read: read, publicParams: { oid, Q, kdfParams } }; - } - default: - throw new Error('Invalid public key encryption algorithm.'); - } - } - - /** - * Parse private key material in binary form to get the key parameters - * @param {module:enums.publicKey} algo - The key algorithm - * @param {Uint8Array} bytes - The key material to parse - * @param {Object} publicParams - (ECC only) public params, needed to format some private params - * @returns {{ read: Number, privateParams: Object }} Number of read bytes plus the key parameters referenced by name. - */ - function parsePrivateKeyParams(algo, bytes, publicParams) { - let read = 0; - switch (algo) { - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaSign: { - const d = util.readMPI(bytes.subarray(read)); read += d.length + 2; - const p = util.readMPI(bytes.subarray(read)); read += p.length + 2; - const q = util.readMPI(bytes.subarray(read)); read += q.length + 2; - const u = util.readMPI(bytes.subarray(read)); read += u.length + 2; - return { read, privateParams: { d, p, q, u } }; - } - case enums.publicKey.dsa: - case enums.publicKey.elgamal: { - const x = util.readMPI(bytes.subarray(read)); read += x.length + 2; - return { read, privateParams: { x } }; - } - case enums.publicKey.ecdsa: - case enums.publicKey.ecdh: { - const curve = new Curve(publicParams.oid); - let d = util.readMPI(bytes.subarray(read)); read += d.length + 2; - d = util.leftPad(d, curve.payloadSize); - return { read, privateParams: { d } }; - } - case enums.publicKey.eddsa: { - let seed = util.readMPI(bytes.subarray(read)); read += seed.length + 2; - seed = util.leftPad(seed, 32); - return { read, privateParams: { seed } }; - } - default: - throw new Error('Invalid public key encryption algorithm.'); - } - } - - /** Returns the types comprising the encrypted session key of an algorithm - * @param {module:enums.publicKey} algo - The key algorithm - * @param {Uint8Array} bytes - The key material to parse - * @returns {Object} The session key parameters referenced by name. - */ - function parseEncSessionKeyParams(algo, bytes) { - let read = 0; - switch (algo) { - // Algorithm-Specific Fields for RSA encrypted session keys: - // - MPI of RSA encrypted value m**e mod n. - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaEncryptSign: { - const c = util.readMPI(bytes.subarray(read)); - return { c }; - } - - // Algorithm-Specific Fields for Elgamal encrypted session keys: - // - MPI of Elgamal value g**k mod p - // - MPI of Elgamal value m * y**k mod p - case enums.publicKey.elgamal: { - const c1 = util.readMPI(bytes.subarray(read)); read += c1.length + 2; - const c2 = util.readMPI(bytes.subarray(read)); - return { c1, c2 }; - } - // Algorithm-Specific Fields for ECDH encrypted session keys: - // - MPI containing the ephemeral key used to establish the shared secret - // - ECDH Symmetric Key - case enums.publicKey.ecdh: { - const V = util.readMPI(bytes.subarray(read)); read += V.length + 2; - const C = new ECDHSymmetricKey(); C.read(bytes.subarray(read)); - return { V, C }; - } - default: - throw new Error('Invalid public key encryption algorithm.'); - } - } - - /** - * Convert params to MPI and serializes them in the proper order - * @param {module:enums.publicKey} algo - The public key algorithm - * @param {Object} params - The key parameters indexed by name - * @returns {Uint8Array} The array containing the MPIs. - */ - function serializeParams(algo, params) { - const orderedParams = Object.keys(params).map(name => { - const param = params[name]; - return util.isUint8Array(param) ? util.uint8ArrayToMPI(param) : param.write(); - }); - return util.concatUint8Array(orderedParams); - } - - /** - * Generate algorithm-specific key parameters - * @param {module:enums.publicKey} algo - The public key algorithm - * @param {Integer} bits - Bit length for RSA keys - * @param {module:type/oid} oid - Object identifier for ECC keys - * @returns {Promise<{ publicParams: {Object}, privateParams: {Object} }>} The parameters referenced by name. - * @async - */ - function generateParams(algo, bits, oid) { - switch (algo) { - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaSign: { - return publicKey.rsa.generate(bits, 65537).then(({ n, e, d, p, q, u }) => ({ - privateParams: { d, p, q, u }, - publicParams: { n, e } - })); - } - case enums.publicKey.ecdsa: - return publicKey.elliptic.generate(oid).then(({ oid, Q, secret }) => ({ - privateParams: { d: secret }, - publicParams: { oid: new OID(oid), Q } - })); - case enums.publicKey.eddsa: - return publicKey.elliptic.generate(oid).then(({ oid, Q, secret }) => ({ - privateParams: { seed: secret }, - publicParams: { oid: new OID(oid), Q } - })); - case enums.publicKey.ecdh: - return publicKey.elliptic.generate(oid).then(({ oid, Q, secret, hash, cipher }) => ({ - privateParams: { d: secret }, - publicParams: { - oid: new OID(oid), - Q, - kdfParams: new KDFParams({ hash, cipher }) - } - })); - case enums.publicKey.dsa: - case enums.publicKey.elgamal: - throw new Error('Unsupported algorithm for key generation.'); - default: - throw new Error('Invalid public key algorithm.'); - } - } - - /** - * Validate algorithm-specific key parameters - * @param {module:enums.publicKey} algo - The public key algorithm - * @param {Object} publicParams - Algorithm-specific public key parameters - * @param {Object} privateParams - Algorithm-specific private key parameters - * @returns {Promise} Whether the parameters are valid. - * @async - */ - async function validateParams$4(algo, publicParams, privateParams) { - if (!publicParams || !privateParams) { - throw new Error('Missing key parameters'); - } - switch (algo) { - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaSign: { - const { n, e } = publicParams; - const { d, p, q, u } = privateParams; - return publicKey.rsa.validateParams(n, e, d, p, q, u); - } - case enums.publicKey.dsa: { - const { p, q, g, y } = publicParams; - const { x } = privateParams; - return publicKey.dsa.validateParams(p, q, g, y, x); - } - case enums.publicKey.elgamal: { - const { p, g, y } = publicParams; - const { x } = privateParams; - return publicKey.elgamal.validateParams(p, g, y, x); - } - case enums.publicKey.ecdsa: - case enums.publicKey.ecdh: { - const algoModule = publicKey.elliptic[enums.read(enums.publicKey, algo)]; - const { oid, Q } = publicParams; - const { d } = privateParams; - return algoModule.validateParams(oid, Q, d); - } - case enums.publicKey.eddsa: { - const { oid, Q } = publicParams; - const { seed } = privateParams; - return publicKey.elliptic.eddsa.validateParams(oid, Q, seed); - } - default: - throw new Error('Invalid public key algorithm.'); - } - } - - /** - * Generates a random byte prefix for the specified algorithm - * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. - * @param {module:enums.symmetric} algo - Symmetric encryption algorithm - * @returns {Promise} Random bytes with length equal to the block size of the cipher, plus the last two bytes repeated. - * @async - */ - async function getPrefixRandom(algo) { - const { blockSize } = getCipher(algo); - const prefixrandom = await getRandomBytes(blockSize); - const repeat = new Uint8Array([prefixrandom[prefixrandom.length - 2], prefixrandom[prefixrandom.length - 1]]); - return util.concat([prefixrandom, repeat]); - } - - /** - * Generating a session key for the specified symmetric algorithm - * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. - * @param {module:enums.symmetric} algo - Symmetric encryption algorithm - * @returns {Promise} Random bytes as a string to be used as a key. - * @async - */ - function generateSessionKey(algo) { - const { keySize } = getCipher(algo); - return getRandomBytes(keySize); - } - - /** - * Get implementation of the given AEAD mode - * @param {enums.aead} algo - * @returns {Object} - * @throws {Error} on invalid algo - */ - function getAEADMode(algo) { - const algoName = enums.read(enums.aead, algo); - return mode[algoName]; - } - - /** - * Get implementation of the given cipher - * @param {enums.symmetric} algo - * @returns {Object} - * @throws {Error} on invalid algo - */ - function getCipher(algo) { - const algoName = enums.read(enums.symmetric, algo); - return cipher[algoName]; - } - - var crypto$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - publicKeyEncrypt: publicKeyEncrypt, - publicKeyDecrypt: publicKeyDecrypt, - parsePublicKeyParams: parsePublicKeyParams, - parsePrivateKeyParams: parsePrivateKeyParams, - parseEncSessionKeyParams: parseEncSessionKeyParams, - serializeParams: serializeParams, - generateParams: generateParams, - validateParams: validateParams$4, - getPrefixRandom: getPrefixRandom, - generateSessionKey: generateSessionKey, - getAEADMode: getAEADMode, - getCipher: getCipher - }); - - // OpenPGP.js - An OpenPGP implementation in javascript - - const webCrypto$8 = util.getWebCrypto(); - const nodeCrypto$9 = util.getNodeCrypto(); - - /** - * Validate ECDH parameters - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {Uint8Array} Q - ECDH public point - * @param {Uint8Array} d - ECDH secret scalar - * @returns {Promise} Whether params are valid. - * @async - */ - async function validateParams$5(oid, Q, d) { - return validateStandardParams(enums.publicKey.ecdh, oid, Q, d); - } - - // Build Param for ECDH algorithm (RFC 6637) - function buildEcdhParam(public_algo, oid, kdfParams, fingerprint) { - return util.concatUint8Array([ - oid.write(), - new Uint8Array([public_algo]), - kdfParams.write(), - util.stringToUint8Array('Anonymous Sender '), - fingerprint.subarray(0, 20) - ]); - } - - // Key Derivation Function (RFC 6637) - async function kdf(hashAlgo, X, length, param, stripLeading = false, stripTrailing = false) { - // Note: X is little endian for Curve25519, big-endian for all others. - // This is not ideal, but the RFC's are unclear - // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B - let i; - if (stripLeading) { - // Work around old go crypto bug - for (i = 0; i < X.length && X[i] === 0; i++); - X = X.subarray(i); - } - if (stripTrailing) { - // Work around old OpenPGP.js bug - for (i = X.length - 1; i >= 0 && X[i] === 0; i--); - X = X.subarray(0, i + 1); - } - const digest = await hash.digest(hashAlgo, util.concatUint8Array([ - new Uint8Array([0, 0, 0, 1]), - X, - param - ])); - return digest.subarray(0, length); - } - - /** - * Generate ECDHE ephemeral key and secret from public key - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} Q - Recipient public key - * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ - async function genPublicEphemeralKey(curve, Q) { - switch (curve.type) { - case 'curve25519': { - const d = await getRandomBytes(32); - const { secretKey, sharedKey } = await genPrivateEphemeralKey(curve, Q, null, d); - let { publicKey } = naclFastLight.box.keyPair.fromSecretKey(secretKey); - publicKey = util.concatUint8Array([new Uint8Array([0x40]), publicKey]); - return { publicKey, sharedKey }; // Note: sharedKey is little-endian here, unlike below - } - case 'web': - if (curve.web && util.getWebCrypto()) { - try { - return await webPublicEphemeralKey(curve, Q); - } catch (err) { - util.printDebugError(err); - } - } - break; - case 'node': - return nodePublicEphemeralKey(curve, Q); - } - return ellipticPublicEphemeralKey(curve, Q); - } - - /** - * Encrypt and wrap a session key - * - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {module:type/kdf_params} kdfParams - KDF params including cipher and algorithm to use - * @param {Uint8Array} data - Unpadded session key data - * @param {Uint8Array} Q - Recipient public key - * @param {Uint8Array} fingerprint - Recipient fingerprint - * @returns {Promise<{publicKey: Uint8Array, wrappedKey: Uint8Array}>} - * @async - */ - async function encrypt$3(oid, kdfParams, data, Q, fingerprint) { - const m = encode$1(data); - - const curve = new Curve(oid); - const { publicKey, sharedKey } = await genPublicEphemeralKey(curve, Q); - const param = buildEcdhParam(enums.publicKey.ecdh, oid, kdfParams, fingerprint); - const { keySize } = getCipher(kdfParams.cipher); - const Z = await kdf(kdfParams.hash, sharedKey, keySize, param); - const wrappedKey = wrap(Z, m); - return { publicKey, wrappedKey }; - } - - /** - * Generate ECDHE secret from private key and public part of ephemeral key - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} V - Public part of ephemeral key - * @param {Uint8Array} Q - Recipient public key - * @param {Uint8Array} d - Recipient private key - * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ - async function genPrivateEphemeralKey(curve, V, Q, d) { - if (d.length !== curve.payloadSize) { - const privateKey = new Uint8Array(curve.payloadSize); - privateKey.set(d, curve.payloadSize - d.length); - d = privateKey; - } - switch (curve.type) { - case 'curve25519': { - const secretKey = d.slice().reverse(); - const sharedKey = naclFastLight.scalarMult(secretKey, V.subarray(1)); - return { secretKey, sharedKey }; // Note: sharedKey is little-endian here, unlike below - } - case 'web': - if (curve.web && util.getWebCrypto()) { - try { - return await webPrivateEphemeralKey(curve, V, Q, d); - } catch (err) { - util.printDebugError(err); - } - } - break; - case 'node': - return nodePrivateEphemeralKey(curve, V, d); - } - return ellipticPrivateEphemeralKey(curve, V, d); - } - - /** - * Decrypt and unwrap the value derived from session key - * - * @param {module:type/oid} oid - Elliptic curve object identifier - * @param {module:type/kdf_params} kdfParams - KDF params including cipher and algorithm to use - * @param {Uint8Array} V - Public part of ephemeral key - * @param {Uint8Array} C - Encrypted and wrapped value derived from session key - * @param {Uint8Array} Q - Recipient public key - * @param {Uint8Array} d - Recipient private key - * @param {Uint8Array} fingerprint - Recipient fingerprint - * @returns {Promise} Value derived from session key. - * @async - */ - async function decrypt$3(oid, kdfParams, V, C, Q, d, fingerprint) { - const curve = new Curve(oid); - const { sharedKey } = await genPrivateEphemeralKey(curve, V, Q, d); - const param = buildEcdhParam(enums.publicKey.ecdh, oid, kdfParams, fingerprint); - const { keySize } = getCipher(kdfParams.cipher); - let err; - for (let i = 0; i < 3; i++) { - try { - // Work around old go crypto bug and old OpenPGP.js bug, respectively. - const Z = await kdf(kdfParams.hash, sharedKey, keySize, param, i === 1, i === 2); - return decode$1(unwrap(Z, C)); - } catch (e) { - err = e; - } - } - throw err; - } - - /** - * Generate ECDHE secret from private key and public part of ephemeral key using webCrypto - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} V - Public part of ephemeral key - * @param {Uint8Array} Q - Recipient public key - * @param {Uint8Array} d - Recipient private key - * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ - async function webPrivateEphemeralKey(curve, V, Q, d) { - const recipient = privateToJWK$1(curve.payloadSize, curve.web.web, Q, d); - let privateKey = webCrypto$8.importKey( - 'jwk', - recipient, - { - name: 'ECDH', - namedCurve: curve.web.web - }, - true, - ['deriveKey', 'deriveBits'] - ); - const jwk = rawPublicToJWK(curve.payloadSize, curve.web.web, V); - let sender = webCrypto$8.importKey( - 'jwk', - jwk, - { - name: 'ECDH', - namedCurve: curve.web.web - }, - true, - [] - ); - [privateKey, sender] = await Promise.all([privateKey, sender]); - let S = webCrypto$8.deriveBits( - { - name: 'ECDH', - namedCurve: curve.web.web, - public: sender - }, - privateKey, - curve.web.sharedSize - ); - let secret = webCrypto$8.exportKey( - 'jwk', - privateKey - ); - [S, secret] = await Promise.all([S, secret]); - const sharedKey = new Uint8Array(S); - const secretKey = b64ToUint8Array(secret.d); - return { secretKey, sharedKey }; - } - - /** - * Generate ECDHE ephemeral key and secret from public key using webCrypto - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} Q - Recipient public key - * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ - async function webPublicEphemeralKey(curve, Q) { - const jwk = rawPublicToJWK(curve.payloadSize, curve.web.web, Q); - let keyPair = webCrypto$8.generateKey( - { - name: 'ECDH', - namedCurve: curve.web.web - }, - true, - ['deriveKey', 'deriveBits'] - ); - let recipient = webCrypto$8.importKey( - 'jwk', - jwk, - { - name: 'ECDH', - namedCurve: curve.web.web - }, - false, - [] - ); - [keyPair, recipient] = await Promise.all([keyPair, recipient]); - let s = webCrypto$8.deriveBits( - { - name: 'ECDH', - namedCurve: curve.web.web, - public: recipient - }, - keyPair.privateKey, - curve.web.sharedSize - ); - let p = webCrypto$8.exportKey( - 'jwk', - keyPair.publicKey - ); - [s, p] = await Promise.all([s, p]); - const sharedKey = new Uint8Array(s); - const publicKey = new Uint8Array(jwkToRawPublic(p)); - return { publicKey, sharedKey }; - } - - /** - * Generate ECDHE secret from private key and public part of ephemeral key using indutny/elliptic - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} V - Public part of ephemeral key - * @param {Uint8Array} d - Recipient private key - * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ - async function ellipticPrivateEphemeralKey(curve, V, d) { - const indutnyCurve = await getIndutnyCurve(curve.name); - V = keyFromPublic(indutnyCurve, V); - d = keyFromPrivate(indutnyCurve, d); - const secretKey = new Uint8Array(d.getPrivate()); - const S = d.derive(V.getPublic()); - const len = indutnyCurve.curve.p.byteLength(); - const sharedKey = S.toArrayLike(Uint8Array, 'be', len); - return { secretKey, sharedKey }; - } - - /** - * Generate ECDHE ephemeral key and secret from public key using indutny/elliptic - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} Q - Recipient public key - * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ - async function ellipticPublicEphemeralKey(curve, Q) { - const indutnyCurve = await getIndutnyCurve(curve.name); - const v = await curve.genKeyPair(); - Q = keyFromPublic(indutnyCurve, Q); - const V = keyFromPrivate(indutnyCurve, v.privateKey); - const publicKey = v.publicKey; - const S = V.derive(Q.getPublic()); - const len = indutnyCurve.curve.p.byteLength(); - const sharedKey = S.toArrayLike(Uint8Array, 'be', len); - return { publicKey, sharedKey }; - } - - /** - * Generate ECDHE secret from private key and public part of ephemeral key using nodeCrypto - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} V - Public part of ephemeral key - * @param {Uint8Array} d - Recipient private key - * @returns {Promise<{secretKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ - async function nodePrivateEphemeralKey(curve, V, d) { - const recipient = nodeCrypto$9.createECDH(curve.node.node); - recipient.setPrivateKey(d); - const sharedKey = new Uint8Array(recipient.computeSecret(V)); - const secretKey = new Uint8Array(recipient.getPrivateKey()); - return { secretKey, sharedKey }; - } - - /** - * Generate ECDHE ephemeral key and secret from public key using nodeCrypto - * - * @param {Curve} curve - Elliptic curve object - * @param {Uint8Array} Q - Recipient public key - * @returns {Promise<{publicKey: Uint8Array, sharedKey: Uint8Array}>} - * @async - */ - async function nodePublicEphemeralKey(curve, Q) { - const sender = nodeCrypto$9.createECDH(curve.node.node); - sender.generateKeys(); - const sharedKey = new Uint8Array(sender.computeSecret(Q)); - const publicKey = new Uint8Array(sender.getPublicKey()); - return { publicKey, sharedKey }; - } - - var ecdh = /*#__PURE__*/Object.freeze({ - __proto__: null, - validateParams: validateParams$5, - encrypt: encrypt$3, - decrypt: decrypt$3 - }); - - // OpenPGP.js - An OpenPGP implementation in javascript - - var elliptic = /*#__PURE__*/Object.freeze({ - __proto__: null, - Curve: Curve, - ecdh: ecdh, - ecdsa: ecdsa, - eddsa: eddsa, - generate: generate$1, - getPreferredHashAlgo: getPreferredHashAlgo - }); - - // GPG4Browsers - An OpenPGP implementation in javascript - - /* - TODO regarding the hash function, read: - https://tools.ietf.org/html/rfc4880#section-13.6 - https://tools.ietf.org/html/rfc4880#section-14 - */ - - /** - * DSA Sign function - * @param {Integer} hashAlgo - * @param {Uint8Array} hashed - * @param {Uint8Array} g - * @param {Uint8Array} p - * @param {Uint8Array} q - * @param {Uint8Array} x - * @returns {Promise<{ r: Uint8Array, s: Uint8Array }>} - * @async - */ - async function sign$3(hashAlgo, hashed, g, p, q, x) { - const BigInteger = await util.getBigInteger(); - const one = new BigInteger(1); - p = new BigInteger(p); - q = new BigInteger(q); - g = new BigInteger(g); - x = new BigInteger(x); - - let k; - let r; - let s; - let t; - g = g.mod(p); - x = x.mod(q); - // If the output size of the chosen hash is larger than the number of - // bits of q, the hash result is truncated to fit by taking the number - // of leftmost bits equal to the number of bits of q. This (possibly - // truncated) hash function result is treated as a number and used - // directly in the DSA signature algorithm. - const h = new BigInteger(hashed.subarray(0, q.byteLength())).mod(q); - // FIPS-186-4, section 4.6: - // The values of r and s shall be checked to determine if r = 0 or s = 0. - // If either r = 0 or s = 0, a new value of k shall be generated, and the - // signature shall be recalculated. It is extremely unlikely that r = 0 - // or s = 0 if signatures are generated properly. - while (true) { - // See Appendix B here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf - k = await getRandomBigInteger(one, q); // returns in [1, q-1] - r = g.modExp(k, p).imod(q); // (g**k mod p) mod q - if (r.isZero()) { - continue; - } - const xr = x.mul(r).imod(q); - t = h.add(xr).imod(q); // H(m) + x*r mod q - s = k.modInv(q).imul(t).imod(q); // k**-1 * (H(m) + x*r) mod q - if (s.isZero()) { - continue; - } - break; - } - return { - r: r.toUint8Array('be', q.byteLength()), - s: s.toUint8Array('be', q.byteLength()) - }; - } - - /** - * DSA Verify function - * @param {Integer} hashAlgo - * @param {Uint8Array} r - * @param {Uint8Array} s - * @param {Uint8Array} hashed - * @param {Uint8Array} g - * @param {Uint8Array} p - * @param {Uint8Array} q - * @param {Uint8Array} y - * @returns {boolean} - * @async - */ - async function verify$3(hashAlgo, r, s, hashed, g, p, q, y) { - const BigInteger = await util.getBigInteger(); - const zero = new BigInteger(0); - r = new BigInteger(r); - s = new BigInteger(s); - - p = new BigInteger(p); - q = new BigInteger(q); - g = new BigInteger(g); - y = new BigInteger(y); - - if (r.lte(zero) || r.gte(q) || - s.lte(zero) || s.gte(q)) { - util.printDebug('invalid DSA Signature'); - return false; - } - const h = new BigInteger(hashed.subarray(0, q.byteLength())).imod(q); - const w = s.modInv(q); // s**-1 mod q - if (w.isZero()) { - util.printDebug('invalid DSA Signature'); - return false; - } - - g = g.mod(p); - y = y.mod(p); - const u1 = h.mul(w).imod(q); // H(m) * w mod q - const u2 = r.mul(w).imod(q); // r * w mod q - const t1 = g.modExp(u1, p); // g**u1 mod p - const t2 = y.modExp(u2, p); // y**u2 mod p - const v = t1.mul(t2).imod(p).imod(q); // (g**u1 * y**u2 mod p) mod q - return v.equal(r); - } - - /** - * Validate DSA parameters - * @param {Uint8Array} p - DSA prime - * @param {Uint8Array} q - DSA group order - * @param {Uint8Array} g - DSA sub-group generator - * @param {Uint8Array} y - DSA public key - * @param {Uint8Array} x - DSA private key - * @returns {Promise} Whether params are valid. - * @async - */ - async function validateParams$6(p, q, g, y, x) { - const BigInteger = await util.getBigInteger(); - p = new BigInteger(p); - q = new BigInteger(q); - g = new BigInteger(g); - y = new BigInteger(y); - const one = new BigInteger(1); - // Check that 1 < g < p - if (g.lte(one) || g.gte(p)) { - return false; - } - - /** - * Check that subgroup order q divides p-1 - */ - if (!p.dec().mod(q).isZero()) { - return false; - } - - /** - * g has order q - * Check that g ** q = 1 mod p - */ - if (!g.modExp(q, p).isOne()) { - return false; - } - - /** - * Check q is large and probably prime (we mainly want to avoid small factors) - */ - const qSize = new BigInteger(q.bitLength()); - const n150 = new BigInteger(150); - if (qSize.lt(n150) || !(await isProbablePrime(q, null, 32))) { - return false; - } - - /** - * Re-derive public key y' = g ** x mod p - * Expect y == y' - * - * Blinded exponentiation computes g**{rq + x} to compare to y - */ - x = new BigInteger(x); - const two = new BigInteger(2); - const r = await getRandomBigInteger(two.leftShift(qSize.dec()), two.leftShift(qSize)); // draw r of same size as q - const rqx = q.mul(r).add(x); - if (!y.equal(g.modExp(rqx, p))) { - return false; - } - - return true; - } - - var dsa = /*#__PURE__*/Object.freeze({ - __proto__: null, - sign: sign$3, - verify: verify$3, - validateParams: validateParams$6 - }); - - /** - * @fileoverview Asymmetric cryptography functions - * @module crypto/public_key - * @private - */ - - var publicKey = { - /** @see module:crypto/public_key/rsa */ - rsa: rsa, - /** @see module:crypto/public_key/elgamal */ - elgamal: elgamal, - /** @see module:crypto/public_key/elliptic */ - elliptic: elliptic, - /** @see module:crypto/public_key/dsa */ - dsa: dsa, - /** @see tweetnacl */ - nacl: naclFastLight - }; - - /** - * @fileoverview Provides functions for asymmetric signing and signature verification - * @module crypto/signature - * @private - */ - - /** - * Parse signature in binary form to get the parameters. - * The returned values are only padded for EdDSA, since in the other cases their expected length - * depends on the key params, hence we delegate the padding to the signature verification function. - * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} - * See {@link https://tools.ietf.org/html/rfc4880#section-5.2.2|RFC 4880 5.2.2.} - * @param {module:enums.publicKey} algo - Public key algorithm - * @param {Uint8Array} signature - Data for which the signature was created - * @returns {Promise} True if signature is valid. - * @async - */ - function parseSignatureParams(algo, signature) { - let read = 0; - switch (algo) { - // Algorithm-Specific Fields for RSA signatures: - // - MPI of RSA signature value m**d mod n. - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaSign: { - const s = util.readMPI(signature.subarray(read)); - // The signature needs to be the same length as the public key modulo n. - // We pad s on signature verification, where we have access to n. - return { s }; - } - // Algorithm-Specific Fields for DSA or ECDSA signatures: - // - MPI of DSA or ECDSA value r. - // - MPI of DSA or ECDSA value s. - case enums.publicKey.dsa: - case enums.publicKey.ecdsa: - { - const r = util.readMPI(signature.subarray(read)); read += r.length + 2; - const s = util.readMPI(signature.subarray(read)); - return { r, s }; - } - // Algorithm-Specific Fields for EdDSA signatures: - // - MPI of an EC point r. - // - EdDSA value s, in MPI, in the little endian representation - case enums.publicKey.eddsa: { - // When parsing little-endian MPI data, we always need to left-pad it, as done with big-endian values: - // https://www.ietf.org/archive/id/draft-ietf-openpgp-rfc4880bis-10.html#section-3.2-9 - let r = util.readMPI(signature.subarray(read)); read += r.length + 2; - r = util.leftPad(r, 32); - let s = util.readMPI(signature.subarray(read)); - s = util.leftPad(s, 32); - return { r, s }; - } - default: - throw new Error('Invalid signature algorithm.'); - } - } - - /** - * Verifies the signature provided for data using specified algorithms and public key parameters. - * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} - * and {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4} - * for public key and hash algorithms. - * @param {module:enums.publicKey} algo - Public key algorithm - * @param {module:enums.hash} hashAlgo - Hash algorithm - * @param {Object} signature - Named algorithm-specific signature parameters - * @param {Object} publicParams - Algorithm-specific public key parameters - * @param {Uint8Array} data - Data for which the signature was created - * @param {Uint8Array} hashed - The hashed data - * @returns {Promise} True if signature is valid. - * @async - */ - async function verify$4(algo, hashAlgo, signature, publicParams, data, hashed) { - switch (algo) { - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaSign: { - const { n, e } = publicParams; - const s = util.leftPad(signature.s, n.length); // padding needed for webcrypto and node crypto - return publicKey.rsa.verify(hashAlgo, data, s, n, e, hashed); - } - case enums.publicKey.dsa: { - const { g, p, q, y } = publicParams; - const { r, s } = signature; // no need to pad, since we always handle them as BigIntegers - return publicKey.dsa.verify(hashAlgo, r, s, hashed, g, p, q, y); - } - case enums.publicKey.ecdsa: { - const { oid, Q } = publicParams; - const curveSize = new publicKey.elliptic.Curve(oid).payloadSize; - // padding needed for webcrypto - const r = util.leftPad(signature.r, curveSize); - const s = util.leftPad(signature.s, curveSize); - return publicKey.elliptic.ecdsa.verify(oid, hashAlgo, { r, s }, data, Q, hashed); - } - case enums.publicKey.eddsa: { - const { oid, Q } = publicParams; - // signature already padded on parsing - return publicKey.elliptic.eddsa.verify(oid, hashAlgo, signature, data, Q, hashed); - } - default: - throw new Error('Invalid signature algorithm.'); - } - } - - /** - * Creates a signature on data using specified algorithms and private key parameters. - * See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} - * and {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4} - * for public key and hash algorithms. - * @param {module:enums.publicKey} algo - Public key algorithm - * @param {module:enums.hash} hashAlgo - Hash algorithm - * @param {Object} publicKeyParams - Algorithm-specific public and private key parameters - * @param {Object} privateKeyParams - Algorithm-specific public and private key parameters - * @param {Uint8Array} data - Data to be signed - * @param {Uint8Array} hashed - The hashed data - * @returns {Promise} Signature Object containing named signature parameters. - * @async - */ - async function sign$4(algo, hashAlgo, publicKeyParams, privateKeyParams, data, hashed) { - if (!publicKeyParams || !privateKeyParams) { - throw new Error('Missing key parameters'); - } - switch (algo) { - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaEncrypt: - case enums.publicKey.rsaSign: { - const { n, e } = publicKeyParams; - const { d, p, q, u } = privateKeyParams; - const s = await publicKey.rsa.sign(hashAlgo, data, n, e, d, p, q, u, hashed); - return { s }; - } - case enums.publicKey.dsa: { - const { g, p, q } = publicKeyParams; - const { x } = privateKeyParams; - return publicKey.dsa.sign(hashAlgo, hashed, g, p, q, x); - } - case enums.publicKey.elgamal: { - throw new Error('Signing with Elgamal is not defined in the OpenPGP standard.'); - } - case enums.publicKey.ecdsa: { - const { oid, Q } = publicKeyParams; - const { d } = privateKeyParams; - return publicKey.elliptic.ecdsa.sign(oid, hashAlgo, data, Q, d, hashed); - } - case enums.publicKey.eddsa: { - const { oid, Q } = publicKeyParams; - const { seed } = privateKeyParams; - return publicKey.elliptic.eddsa.sign(oid, hashAlgo, data, Q, seed, hashed); - } - default: - throw new Error('Invalid signature algorithm.'); - } - } - - var signature = /*#__PURE__*/Object.freeze({ - __proto__: null, - parseSignatureParams: parseSignatureParams, - verify: verify$4, - sign: sign$4 - }); - - /** - * @fileoverview Provides access to all cryptographic primitives used in OpenPGP.js - * @see module:crypto/crypto - * @see module:crypto/signature - * @see module:crypto/public_key - * @see module:crypto/cipher - * @see module:crypto/random - * @see module:crypto/hash - * @module crypto - * @private - */ - - // TODO move cfb and gcm to cipher - const mod = { - /** @see module:crypto/cipher */ - cipher: cipher, - /** @see module:crypto/hash */ - hash: hash, - /** @see module:crypto/mode */ - mode: mode, - /** @see module:crypto/public_key */ - publicKey: publicKey, - /** @see module:crypto/signature */ - signature: signature, - /** @see module:crypto/random */ - random: random, - /** @see module:crypto/pkcs1 */ - pkcs1: pkcs1, - /** @see module:crypto/pkcs5 */ - pkcs5: pkcs5, - /** @see module:crypto/aes_kw */ - aesKW: aesKW - }; - - Object.assign(mod, crypto$1); - - var TYPED_OK = typeof Uint8Array !== "undefined" && - typeof Uint16Array !== "undefined" && - typeof Int32Array !== "undefined"; - - - // reduce buffer size, avoiding mem copy - function shrinkBuf(buf, size) { - if (buf.length === size) { - return buf; - } - if (buf.subarray) { - return buf.subarray(0, size); - } - buf.length = size; - return buf; - } - - - const fnTyped = { - arraySet: function (dest, src, src_offs, len, dest_offs) { - if (src.subarray && dest.subarray) { - dest.set(src.subarray(src_offs, src_offs + len), dest_offs); - return; - } - // Fallback to ordinary array - for (let i = 0; i < len; i++) { - dest[dest_offs + i] = src[src_offs + i]; - } - }, - // Join array of chunks to single array. - flattenChunks: function (chunks) { - let i, l, len, pos, chunk; - - // calculate data length - len = 0; - for (i = 0, l = chunks.length; i < l; i++) { - len += chunks[i].length; - } - - // join chunks - const result = new Uint8Array(len); - pos = 0; - for (i = 0, l = chunks.length; i < l; i++) { - chunk = chunks[i]; - result.set(chunk, pos); - pos += chunk.length; - } - - return result; - } - }; - - const fnUntyped = { - arraySet: function (dest, src, src_offs, len, dest_offs) { - for (let i = 0; i < len; i++) { - dest[dest_offs + i] = src[src_offs + i]; - } - }, - // Join array of chunks to single array. - flattenChunks: function (chunks) { - return [].concat.apply([], chunks); - } - }; - - - // Enable/Disable typed arrays use, for testing - // - - let Buf8 = TYPED_OK ? Uint8Array : Array; - let Buf16 = TYPED_OK ? Uint16Array : Array; - let Buf32 = TYPED_OK ? Int32Array : Array; - let flattenChunks = TYPED_OK ? fnTyped.flattenChunks : fnUntyped.flattenChunks; - let arraySet = TYPED_OK ? fnTyped.arraySet : fnUntyped.arraySet; - - // (C) 1995-2013 Jean-loup Gailly and Mark Adler - // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin - // - // This software is provided 'as-is', without any express or implied - // warranty. In no event will the authors be held liable for any damages - // arising from the use of this software. - // - // Permission is granted to anyone to use this software for any purpose, - // including commercial applications, and to alter it and redistribute it - // freely, subject to the following restrictions: - // - // 1. The origin of this software must not be misrepresented; you must not - // claim that you wrote the original software. If you use this software - // in a product, an acknowledgment in the product documentation would be - // appreciated but is not required. - // 2. Altered source versions must be plainly marked as such, and must not be - // misrepresented as being the original software. - // 3. This notice may not be removed or altered from any source distribution. - - /* Allowed flush values; see deflate() and inflate() below for details */ - const Z_NO_FLUSH = 0; - const Z_PARTIAL_FLUSH = 1; - const Z_SYNC_FLUSH = 2; - const Z_FULL_FLUSH = 3; - const Z_FINISH = 4; - const Z_BLOCK = 5; - const Z_TREES = 6; - - /* Return codes for the compression/decompression functions. Negative values - * are errors, positive values are used for special but normal events. - */ - const Z_OK = 0; - const Z_STREAM_END = 1; - const Z_NEED_DICT = 2; - const Z_STREAM_ERROR = -2; - const Z_DATA_ERROR = -3; - //export const Z_MEM_ERROR = -4; - const Z_BUF_ERROR = -5; - const Z_DEFAULT_COMPRESSION = -1; - - - const Z_FILTERED = 1; - const Z_HUFFMAN_ONLY = 2; - const Z_RLE = 3; - const Z_FIXED = 4; - const Z_DEFAULT_STRATEGY = 0; - - /* Possible values of the data_type field (though see inflate()) */ - const Z_BINARY = 0; - const Z_TEXT = 1; - //export const Z_ASCII = 1; // = Z_TEXT (deprecated) - const Z_UNKNOWN = 2; - - /* The deflate compression method */ - const Z_DEFLATED = 8; - //export const Z_NULL = null // Use -1 or null inline, depending on var type - - /*============================================================================*/ - - - function zero$1(buf) { - let len = buf.length; while (--len >= 0) { - buf[len] = 0; - } - } - - // From zutil.h - - const STORED_BLOCK = 0; - const STATIC_TREES = 1; - const DYN_TREES = 2; - /* The three kinds of block type */ - - const MIN_MATCH = 3; - const MAX_MATCH = 258; - /* The minimum and maximum match lengths */ - - // From deflate.h - /* =========================================================================== - * Internal compression state. - */ - - const LENGTH_CODES = 29; - /* number of length codes, not counting the special END_BLOCK code */ - - const LITERALS = 256; - /* number of literal bytes 0..255 */ - - const L_CODES = LITERALS + 1 + LENGTH_CODES; - /* number of Literal or Length codes, including the END_BLOCK code */ - - const D_CODES = 30; - /* number of distance codes */ - - const BL_CODES = 19; - /* number of codes used to transfer the bit lengths */ - - const HEAP_SIZE = 2 * L_CODES + 1; - /* maximum heap size */ - - const MAX_BITS = 15; - /* All codes must not exceed MAX_BITS bits */ - - const Buf_size = 16; - /* size of bit buffer in bi_buf */ - - - /* =========================================================================== - * Constants - */ - - const MAX_BL_BITS = 7; - /* Bit length codes must not exceed MAX_BL_BITS bits */ - - const END_BLOCK = 256; - /* end of block literal code */ - - const REP_3_6 = 16; - /* repeat previous bit length 3-6 times (2 bits of repeat count) */ - - const REPZ_3_10 = 17; - /* repeat a zero length 3-10 times (3 bits of repeat count) */ - - const REPZ_11_138 = 18; - /* repeat a zero length 11-138 times (7 bits of repeat count) */ - - /* eslint-disable comma-spacing,array-bracket-spacing */ - const extra_lbits = /* extra bits for each length code */ - [0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0]; - - const extra_dbits = /* extra bits for each distance code */ - [0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13]; - - const extra_blbits = /* extra bits for each bit length code */ - [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7]; - - const bl_order = - [16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]; - /* eslint-enable comma-spacing,array-bracket-spacing */ - - /* The lengths of the bit length codes are sent in order of decreasing - * probability, to avoid transmitting the lengths for unused bit length codes. - */ - - /* =========================================================================== - * Local data. These are initialized only once. - */ - - // We pre-fill arrays with 0 to avoid uninitialized gaps - - const DIST_CODE_LEN = 512; /* see definition of array dist_code below */ - - // !!!! Use flat array instead of structure, Freq = i*2, Len = i*2+1 - const static_ltree = new Array((L_CODES + 2) * 2); - zero$1(static_ltree); - /* The static literal tree. Since the bit lengths are imposed, there is no - * need for the L_CODES extra codes used during heap construction. However - * The codes 286 and 287 are needed to build a canonical tree (see _tr_init - * below). - */ - - const static_dtree = new Array(D_CODES * 2); - zero$1(static_dtree); - /* The static distance tree. (Actually a trivial tree since all codes use - * 5 bits.) - */ - - const _dist_code = new Array(DIST_CODE_LEN); - zero$1(_dist_code); - /* Distance codes. The first 256 values correspond to the distances - * 3 .. 258, the last 256 values correspond to the top 8 bits of - * the 15 bit distances. - */ - - const _length_code = new Array(MAX_MATCH - MIN_MATCH + 1); - zero$1(_length_code); - /* length code for each normalized match length (0 == MIN_MATCH) */ - - const base_length = new Array(LENGTH_CODES); - zero$1(base_length); - /* First normalized length for each code (0 = MIN_MATCH) */ - - const base_dist = new Array(D_CODES); - zero$1(base_dist); - /* First normalized distance for each code (0 = distance of 1) */ - - - function StaticTreeDesc(static_tree, extra_bits, extra_base, elems, max_length) { - - this.static_tree = static_tree; /* static tree or NULL */ - this.extra_bits = extra_bits; /* extra bits for each code or NULL */ - this.extra_base = extra_base; /* base index for extra_bits */ - this.elems = elems; /* max number of elements in the tree */ - this.max_length = max_length; /* max bit length for the codes */ - - // show if `static_tree` has data or dummy - needed for monomorphic objects - this.has_stree = static_tree && static_tree.length; - } - - - let static_l_desc; - let static_d_desc; - let static_bl_desc; - - - function TreeDesc(dyn_tree, stat_desc) { - this.dyn_tree = dyn_tree; /* the dynamic tree */ - this.max_code = 0; /* largest code with non zero frequency */ - this.stat_desc = stat_desc; /* the corresponding static tree */ - } - - - - function d_code(dist) { - return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)]; - } - - - /* =========================================================================== - * Output a short LSB first on the stream. - * IN assertion: there is enough room in pendingBuf. - */ - function put_short(s, w) { - // put_byte(s, (uch)((w) & 0xff)); - // put_byte(s, (uch)((ush)(w) >> 8)); - s.pending_buf[s.pending++] = w & 0xff; - s.pending_buf[s.pending++] = w >>> 8 & 0xff; - } - - - /* =========================================================================== - * Send a value on a given number of bits. - * IN assertion: length <= 16 and value fits in length bits. - */ - function send_bits(s, value, length) { - if (s.bi_valid > Buf_size - length) { - s.bi_buf |= value << s.bi_valid & 0xffff; - put_short(s, s.bi_buf); - s.bi_buf = value >> Buf_size - s.bi_valid; - s.bi_valid += length - Buf_size; - } else { - s.bi_buf |= value << s.bi_valid & 0xffff; - s.bi_valid += length; - } - } - - - function send_code(s, c, tree) { - send_bits(s, tree[c * 2]/*.Code*/, tree[c * 2 + 1]/*.Len*/); - } - - - /* =========================================================================== - * Reverse the first len bits of a code, using straightforward code (a faster - * method would use a table) - * IN assertion: 1 <= len <= 15 - */ - function bi_reverse(code, len) { - let res = 0; - do { - res |= code & 1; - code >>>= 1; - res <<= 1; - } while (--len > 0); - return res >>> 1; - } - - - /* =========================================================================== - * Flush the bit buffer, keeping at most 7 bits in it. - */ - function bi_flush(s) { - if (s.bi_valid === 16) { - put_short(s, s.bi_buf); - s.bi_buf = 0; - s.bi_valid = 0; - - } else if (s.bi_valid >= 8) { - s.pending_buf[s.pending++] = s.bi_buf & 0xff; - s.bi_buf >>= 8; - s.bi_valid -= 8; - } - } - - - /* =========================================================================== - * Compute the optimal bit lengths for a tree and update the total bit length - * for the current block. - * IN assertion: the fields freq and dad are set, heap[heap_max] and - * above are the tree nodes sorted by increasing frequency. - * OUT assertions: the field len is set to the optimal bit length, the - * array bl_count contains the frequencies for each bit length. - * The length opt_len is updated; static_len is also updated if stree is - * not null. - */ - function gen_bitlen(s, desc) - // deflate_state *s; - // tree_desc *desc; /* the tree descriptor */ - { - const tree = desc.dyn_tree; - const max_code = desc.max_code; - const stree = desc.stat_desc.static_tree; - const has_stree = desc.stat_desc.has_stree; - const extra = desc.stat_desc.extra_bits; - const base = desc.stat_desc.extra_base; - const max_length = desc.stat_desc.max_length; - let h; /* heap index */ - let n, m; /* iterate over the tree elements */ - let bits; /* bit length */ - let xbits; /* extra bits */ - let f; /* frequency */ - let overflow = 0; /* number of elements with bit length too large */ - - for (bits = 0; bits <= MAX_BITS; bits++) { - s.bl_count[bits] = 0; - } - - /* In a first pass, compute the optimal bit lengths (which may - * overflow in the case of the bit length tree). - */ - tree[s.heap[s.heap_max] * 2 + 1]/*.Len*/ = 0; /* root of the heap */ - - for (h = s.heap_max + 1; h < HEAP_SIZE; h++) { - n = s.heap[h]; - bits = tree[tree[n * 2 + 1]/*.Dad*/ * 2 + 1]/*.Len*/ + 1; - if (bits > max_length) { - bits = max_length; - overflow++; - } - tree[n * 2 + 1]/*.Len*/ = bits; - /* We overwrite tree[n].Dad which is no longer needed */ - - if (n > max_code) { - continue; - } /* not a leaf node */ - - s.bl_count[bits]++; - xbits = 0; - if (n >= base) { - xbits = extra[n - base]; - } - f = tree[n * 2]/*.Freq*/; - s.opt_len += f * (bits + xbits); - if (has_stree) { - s.static_len += f * (stree[n * 2 + 1]/*.Len*/ + xbits); - } - } - if (overflow === 0) { - return; - } - - // Trace((stderr,"\nbit length overflow\n")); - /* This happens for example on obj2 and pic of the Calgary corpus */ - - /* Find the first bit length which could increase: */ - do { - bits = max_length - 1; - while (s.bl_count[bits] === 0) { - bits--; - } - s.bl_count[bits]--; /* move one leaf down the tree */ - s.bl_count[bits + 1] += 2; /* move one overflow item as its brother */ - s.bl_count[max_length]--; - /* The brother of the overflow item also moves one step up, - * but this does not affect bl_count[max_length] - */ - overflow -= 2; - } while (overflow > 0); - - /* Now recompute all bit lengths, scanning in increasing frequency. - * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all - * lengths instead of fixing only the wrong ones. This idea is taken - * from 'ar' written by Haruhiko Okumura.) - */ - for (bits = max_length; bits !== 0; bits--) { - n = s.bl_count[bits]; - while (n !== 0) { - m = s.heap[--h]; - if (m > max_code) { - continue; - } - if (tree[m * 2 + 1]/*.Len*/ !== bits) { - // Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); - s.opt_len += (bits - tree[m * 2 + 1]/*.Len*/) * tree[m * 2]/*.Freq*/; - tree[m * 2 + 1]/*.Len*/ = bits; - } - n--; - } - } - } - - - /* =========================================================================== - * Generate the codes for a given tree and bit counts (which need not be - * optimal). - * IN assertion: the array bl_count contains the bit length statistics for - * the given tree and the field len is set for all tree elements. - * OUT assertion: the field code is set for all tree elements of non - * zero code length. - */ - function gen_codes(tree, max_code, bl_count) - // ct_data *tree; /* the tree to decorate */ - // int max_code; /* largest code with non zero frequency */ - // ushf *bl_count; /* number of codes at each bit length */ - { - const next_code = new Array(MAX_BITS + 1); /* next code value for each bit length */ - let code = 0; /* running code value */ - let bits; /* bit index */ - let n; /* code index */ - - /* The distribution counts are first used to generate the code values - * without bit reversal. - */ - for (bits = 1; bits <= MAX_BITS; bits++) { - next_code[bits] = code = code + bl_count[bits - 1] << 1; - } - /* Check that the bit counts in bl_count are consistent. The last code - * must be all ones. - */ - //Assert (code + bl_count[MAX_BITS]-1 == (1< length code (0..28) */ - length = 0; - for (code = 0; code < LENGTH_CODES - 1; code++) { - base_length[code] = length; - for (n = 0; n < 1 << extra_lbits[code]; n++) { - _length_code[length++] = code; - } - } - //Assert (length == 256, "tr_static_init: length != 256"); - /* Note that the length 255 (match length 258) can be represented - * in two different ways: code 284 + 5 bits or code 285, so we - * overwrite length_code[255] to use the best encoding: - */ - _length_code[length - 1] = code; - - /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ - dist = 0; - for (code = 0; code < 16; code++) { - base_dist[code] = dist; - for (n = 0; n < 1 << extra_dbits[code]; n++) { - _dist_code[dist++] = code; - } - } - //Assert (dist == 256, "tr_static_init: dist != 256"); - dist >>= 7; /* from now on, all distances are divided by 128 */ - for (; code < D_CODES; code++) { - base_dist[code] = dist << 7; - for (n = 0; n < 1 << extra_dbits[code] - 7; n++) { - _dist_code[256 + dist++] = code; - } - } - //Assert (dist == 256, "tr_static_init: 256+dist != 512"); - - /* Construct the codes of the static literal tree */ - for (bits = 0; bits <= MAX_BITS; bits++) { - bl_count[bits] = 0; - } - - n = 0; - while (n <= 143) { - static_ltree[n * 2 + 1]/*.Len*/ = 8; - n++; - bl_count[8]++; - } - while (n <= 255) { - static_ltree[n * 2 + 1]/*.Len*/ = 9; - n++; - bl_count[9]++; - } - while (n <= 279) { - static_ltree[n * 2 + 1]/*.Len*/ = 7; - n++; - bl_count[7]++; - } - while (n <= 287) { - static_ltree[n * 2 + 1]/*.Len*/ = 8; - n++; - bl_count[8]++; - } - /* Codes 286 and 287 do not exist, but we must include them in the - * tree construction to get a canonical Huffman tree (longest code - * all ones) - */ - gen_codes(static_ltree, L_CODES + 1, bl_count); - - /* The static distance tree is trivial: */ - for (n = 0; n < D_CODES; n++) { - static_dtree[n * 2 + 1]/*.Len*/ = 5; - static_dtree[n * 2]/*.Code*/ = bi_reverse(n, 5); - } - - // Now data ready and we can init static trees - static_l_desc = new StaticTreeDesc(static_ltree, extra_lbits, LITERALS + 1, L_CODES, MAX_BITS); - static_d_desc = new StaticTreeDesc(static_dtree, extra_dbits, 0, D_CODES, MAX_BITS); - static_bl_desc = new StaticTreeDesc(new Array(0), extra_blbits, 0, BL_CODES, MAX_BL_BITS); - - //static_init_done = true; - } - - - /* =========================================================================== - * Initialize a new block. - */ - function init_block(s) { - let n; /* iterates over tree elements */ - - /* Initialize the trees. */ - for (n = 0; n < L_CODES; n++) { - s.dyn_ltree[n * 2]/*.Freq*/ = 0; - } - for (n = 0; n < D_CODES; n++) { - s.dyn_dtree[n * 2]/*.Freq*/ = 0; - } - for (n = 0; n < BL_CODES; n++) { - s.bl_tree[n * 2]/*.Freq*/ = 0; - } - - s.dyn_ltree[END_BLOCK * 2]/*.Freq*/ = 1; - s.opt_len = s.static_len = 0; - s.last_lit = s.matches = 0; - } - - - /* =========================================================================== - * Flush the bit buffer and align the output on a byte boundary - */ - function bi_windup(s) { - if (s.bi_valid > 8) { - put_short(s, s.bi_buf); - } else if (s.bi_valid > 0) { - //put_byte(s, (Byte)s->bi_buf); - s.pending_buf[s.pending++] = s.bi_buf; - } - s.bi_buf = 0; - s.bi_valid = 0; - } - - /* =========================================================================== - * Copy a stored block, storing first the length and its - * one's complement if requested. - */ - function copy_block(s, buf, len, header) - //DeflateState *s; - //charf *buf; /* the input data */ - //unsigned len; /* its length */ - //int header; /* true if block header must be written */ - { - bi_windup(s); /* align on byte boundary */ - - if (header) { - put_short(s, len); - put_short(s, ~len); - } - // while (len--) { - // put_byte(s, *buf++); - // } - arraySet(s.pending_buf, s.window, buf, len, s.pending); - s.pending += len; - } - - /* =========================================================================== - * Compares to subtrees, using the tree depth as tie breaker when - * the subtrees have equal frequency. This minimizes the worst case length. - */ - function smaller(tree, n, m, depth) { - const _n2 = n * 2; - const _m2 = m * 2; - return tree[_n2]/*.Freq*/ < tree[_m2]/*.Freq*/ || - tree[_n2]/*.Freq*/ === tree[_m2]/*.Freq*/ && depth[n] <= depth[m]; - } - - /* =========================================================================== - * Restore the heap property by moving down the tree starting at node k, - * exchanging a node with the smallest of its two sons if necessary, stopping - * when the heap property is re-established (each father smaller than its - * two sons). - */ - function pqdownheap(s, tree, k) - // deflate_state *s; - // ct_data *tree; /* the tree to restore */ - // int k; /* node to move down */ - { - const v = s.heap[k]; - let j = k << 1; /* left son of k */ - while (j <= s.heap_len) { - /* Set j to the smallest of the two sons: */ - if (j < s.heap_len && - smaller(tree, s.heap[j + 1], s.heap[j], s.depth)) { - j++; - } - /* Exit if v is smaller than both sons */ - if (smaller(tree, v, s.heap[j], s.depth)) { - break; - } - - /* Exchange v with the smallest son */ - s.heap[k] = s.heap[j]; - k = j; - - /* And continue down the tree, setting j to the left son of k */ - j <<= 1; - } - s.heap[k] = v; - } - - - // inlined manually - // var SMALLEST = 1; - - /* =========================================================================== - * Send the block data compressed using the given Huffman trees - */ - function compress_block(s, ltree, dtree) - // deflate_state *s; - // const ct_data *ltree; /* literal tree */ - // const ct_data *dtree; /* distance tree */ - { - let dist; /* distance of matched string */ - let lc; /* match length or unmatched char (if dist == 0) */ - let lx = 0; /* running index in l_buf */ - let code; /* the code to send */ - let extra; /* number of extra bits to send */ - - if (s.last_lit !== 0) { - do { - dist = s.pending_buf[s.d_buf + lx * 2] << 8 | s.pending_buf[s.d_buf + lx * 2 + 1]; - lc = s.pending_buf[s.l_buf + lx]; - lx++; - - if (dist === 0) { - send_code(s, lc, ltree); /* send a literal byte */ - //Tracecv(isgraph(lc), (stderr," '%c' ", lc)); - } else { - /* Here, lc is the match length - MIN_MATCH */ - code = _length_code[lc]; - send_code(s, code + LITERALS + 1, ltree); /* send the length code */ - extra = extra_lbits[code]; - if (extra !== 0) { - lc -= base_length[code]; - send_bits(s, lc, extra); /* send the extra length bits */ - } - dist--; /* dist is now the match distance - 1 */ - code = d_code(dist); - //Assert (code < D_CODES, "bad d_code"); - - send_code(s, code, dtree); /* send the distance code */ - extra = extra_dbits[code]; - if (extra !== 0) { - dist -= base_dist[code]; - send_bits(s, dist, extra); /* send the extra distance bits */ - } - } /* literal or match pair ? */ - - /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ - //Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, - // "pendingBuf overflow"); - - } while (lx < s.last_lit); - } - - send_code(s, END_BLOCK, ltree); - } - - - /* =========================================================================== - * Construct one Huffman tree and assigns the code bit strings and lengths. - * Update the total bit length for the current block. - * IN assertion: the field freq is set for all tree elements. - * OUT assertions: the fields len and code are set to the optimal bit length - * and corresponding code. The length opt_len is updated; static_len is - * also updated if stree is not null. The field max_code is set. - */ - function build_tree(s, desc) - // deflate_state *s; - // tree_desc *desc; /* the tree descriptor */ - { - const tree = desc.dyn_tree; - const stree = desc.stat_desc.static_tree; - const has_stree = desc.stat_desc.has_stree; - const elems = desc.stat_desc.elems; - let n, m; /* iterate over heap elements */ - let max_code = -1; /* largest code with non zero frequency */ - let node; /* new node being created */ - - /* Construct the initial heap, with least frequent element in - * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. - * heap[0] is not used. - */ - s.heap_len = 0; - s.heap_max = HEAP_SIZE; - - for (n = 0; n < elems; n++) { - if (tree[n * 2]/*.Freq*/ !== 0) { - s.heap[++s.heap_len] = max_code = n; - s.depth[n] = 0; - - } else { - tree[n * 2 + 1]/*.Len*/ = 0; - } - } - - /* The pkzip format requires that at least one distance code exists, - * and that at least one bit should be sent even if there is only one - * possible code. So to avoid special checks later on we force at least - * two codes of non zero frequency. - */ - while (s.heap_len < 2) { - node = s.heap[++s.heap_len] = max_code < 2 ? ++max_code : 0; - tree[node * 2]/*.Freq*/ = 1; - s.depth[node] = 0; - s.opt_len--; - - if (has_stree) { - s.static_len -= stree[node * 2 + 1]/*.Len*/; - } - /* node is 0 or 1 so it does not have extra bits */ - } - desc.max_code = max_code; - - /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, - * establish sub-heaps of increasing lengths: - */ - for (n = s.heap_len >> 1/*int /2*/; n >= 1; n--) { - pqdownheap(s, tree, n); - } - - /* Construct the Huffman tree by repeatedly combining the least two - * frequent nodes. - */ - node = elems; /* next internal node of the tree */ - do { - //pqremove(s, tree, n); /* n = node of least frequency */ - /*** pqremove ***/ - n = s.heap[1/*SMALLEST*/]; - s.heap[1/*SMALLEST*/] = s.heap[s.heap_len--]; - pqdownheap(s, tree, 1/*SMALLEST*/); - /***/ - - m = s.heap[1/*SMALLEST*/]; /* m = node of next least frequency */ - - s.heap[--s.heap_max] = n; /* keep the nodes sorted by frequency */ - s.heap[--s.heap_max] = m; - - /* Create a new node father of n and m */ - tree[node * 2]/*.Freq*/ = tree[n * 2]/*.Freq*/ + tree[m * 2]/*.Freq*/; - s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1; - tree[n * 2 + 1]/*.Dad*/ = tree[m * 2 + 1]/*.Dad*/ = node; - - /* and insert the new node in the heap */ - s.heap[1/*SMALLEST*/] = node++; - pqdownheap(s, tree, 1/*SMALLEST*/); - - } while (s.heap_len >= 2); - - s.heap[--s.heap_max] = s.heap[1/*SMALLEST*/]; - - /* At this point, the fields freq and dad are set. We can now - * generate the bit lengths. - */ - gen_bitlen(s, desc); - - /* The field len is now set, we can generate the bit codes */ - gen_codes(tree, max_code, s.bl_count); - } - - - /* =========================================================================== - * Scan a literal or distance tree to determine the frequencies of the codes - * in the bit length tree. - */ - function scan_tree(s, tree, max_code) - // deflate_state *s; - // ct_data *tree; /* the tree to be scanned */ - // int max_code; /* and its largest code of non zero frequency */ - { - let n; /* iterates over all tree elements */ - let prevlen = -1; /* last emitted length */ - let curlen; /* length of current code */ - - let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */ - - let count = 0; /* repeat count of the current code */ - let max_count = 7; /* max repeat count */ - let min_count = 4; /* min repeat count */ - - if (nextlen === 0) { - max_count = 138; - min_count = 3; - } - tree[(max_code + 1) * 2 + 1]/*.Len*/ = 0xffff; /* guard */ - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; - nextlen = tree[(n + 1) * 2 + 1]/*.Len*/; - - if (++count < max_count && curlen === nextlen) { - continue; - - } else if (count < min_count) { - s.bl_tree[curlen * 2]/*.Freq*/ += count; - - } else if (curlen !== 0) { - - if (curlen !== prevlen) { - s.bl_tree[curlen * 2]/*.Freq*/++; - } - s.bl_tree[REP_3_6 * 2]/*.Freq*/++; - - } else if (count <= 10) { - s.bl_tree[REPZ_3_10 * 2]/*.Freq*/++; - - } else { - s.bl_tree[REPZ_11_138 * 2]/*.Freq*/++; - } - - count = 0; - prevlen = curlen; - - if (nextlen === 0) { - max_count = 138; - min_count = 3; - - } else if (curlen === nextlen) { - max_count = 6; - min_count = 3; - - } else { - max_count = 7; - min_count = 4; - } - } - } - - - /* =========================================================================== - * Send a literal or distance tree in compressed form, using the codes in - * bl_tree. - */ - function send_tree(s, tree, max_code) - // deflate_state *s; - // ct_data *tree; /* the tree to be scanned */ - // int max_code; /* and its largest code of non zero frequency */ - { - let n; /* iterates over all tree elements */ - let prevlen = -1; /* last emitted length */ - let curlen; /* length of current code */ - - let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */ - - let count = 0; /* repeat count of the current code */ - let max_count = 7; /* max repeat count */ - let min_count = 4; /* min repeat count */ - - /* tree[max_code+1].Len = -1; */ /* guard already set */ - if (nextlen === 0) { - max_count = 138; - min_count = 3; - } - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; - nextlen = tree[(n + 1) * 2 + 1]/*.Len*/; - - if (++count < max_count && curlen === nextlen) { - continue; - - } else if (count < min_count) { - do { - send_code(s, curlen, s.bl_tree); - } while (--count !== 0); - - } else if (curlen !== 0) { - if (curlen !== prevlen) { - send_code(s, curlen, s.bl_tree); - count--; - } - //Assert(count >= 3 && count <= 6, " 3_6?"); - send_code(s, REP_3_6, s.bl_tree); - send_bits(s, count - 3, 2); - - } else if (count <= 10) { - send_code(s, REPZ_3_10, s.bl_tree); - send_bits(s, count - 3, 3); - - } else { - send_code(s, REPZ_11_138, s.bl_tree); - send_bits(s, count - 11, 7); - } - - count = 0; - prevlen = curlen; - if (nextlen === 0) { - max_count = 138; - min_count = 3; - - } else if (curlen === nextlen) { - max_count = 6; - min_count = 3; - - } else { - max_count = 7; - min_count = 4; - } - } - } - - - /* =========================================================================== - * Construct the Huffman tree for the bit lengths and return the index in - * bl_order of the last bit length code to send. - */ - function build_bl_tree(s) { - let max_blindex; /* index of last bit length code of non zero freq */ - - /* Determine the bit length frequencies for literal and distance trees */ - scan_tree(s, s.dyn_ltree, s.l_desc.max_code); - scan_tree(s, s.dyn_dtree, s.d_desc.max_code); - - /* Build the bit length tree: */ - build_tree(s, s.bl_desc); - /* opt_len now includes the length of the tree representations, except - * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. - */ - - /* Determine the number of bit length codes to send. The pkzip format - * requires that at least 4 bit length codes be sent. (appnote.txt says - * 3 but the actual value used is 4.) - */ - for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) { - if (s.bl_tree[bl_order[max_blindex] * 2 + 1]/*.Len*/ !== 0) { - break; - } - } - /* Update opt_len to include the bit length tree and counts */ - s.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4; - //Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", - // s->opt_len, s->static_len)); - - return max_blindex; - } - - - /* =========================================================================== - * Send the header for a block using dynamic Huffman trees: the counts, the - * lengths of the bit length codes, the literal tree and the distance tree. - * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. - */ - function send_all_trees(s, lcodes, dcodes, blcodes) - // deflate_state *s; - // int lcodes, dcodes, blcodes; /* number of codes for each tree */ - { - let rank; /* index in bl_order */ - - //Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); - //Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, - // "too many codes"); - //Tracev((stderr, "\nbl counts: ")); - send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */ - send_bits(s, dcodes - 1, 5); - send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */ - for (rank = 0; rank < blcodes; rank++) { - //Tracev((stderr, "\nbl code %2d ", bl_order[rank])); - send_bits(s, s.bl_tree[bl_order[rank] * 2 + 1]/*.Len*/, 3); - } - //Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); - - send_tree(s, s.dyn_ltree, lcodes - 1); /* literal tree */ - //Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); - - send_tree(s, s.dyn_dtree, dcodes - 1); /* distance tree */ - //Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); - } - - - /* =========================================================================== - * Check if the data type is TEXT or BINARY, using the following algorithm: - * - TEXT if the two conditions below are satisfied: - * a) There are no non-portable control characters belonging to the - * "black list" (0..6, 14..25, 28..31). - * b) There is at least one printable character belonging to the - * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). - * - BINARY otherwise. - * - The following partially-portable control characters form a - * "gray list" that is ignored in this detection algorithm: - * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). - * IN assertion: the fields Freq of dyn_ltree are set. - */ - function detect_data_type(s) { - /* black_mask is the bit mask of black-listed bytes - * set bits 0..6, 14..25, and 28..31 - * 0xf3ffc07f = binary 11110011111111111100000001111111 - */ - let black_mask = 0xf3ffc07f; - let n; - - /* Check for non-textual ("black-listed") bytes. */ - for (n = 0; n <= 31; n++, black_mask >>>= 1) { - if (black_mask & 1 && s.dyn_ltree[n * 2]/*.Freq*/ !== 0) { - return Z_BINARY; - } - } - - /* Check for textual ("white-listed") bytes. */ - if (s.dyn_ltree[9 * 2]/*.Freq*/ !== 0 || s.dyn_ltree[10 * 2]/*.Freq*/ !== 0 || - s.dyn_ltree[13 * 2]/*.Freq*/ !== 0) { - return Z_TEXT; - } - for (n = 32; n < LITERALS; n++) { - if (s.dyn_ltree[n * 2]/*.Freq*/ !== 0) { - return Z_TEXT; - } - } - - /* There are no "black-listed" or "white-listed" bytes: - * this stream either is empty or has tolerated ("gray-listed") bytes only. - */ - return Z_BINARY; - } - - - let static_init_done = false; - - /* =========================================================================== - * Initialize the tree data structures for a new zlib stream. - */ - function _tr_init(s) { - - if (!static_init_done) { - tr_static_init(); - static_init_done = true; - } - - s.l_desc = new TreeDesc(s.dyn_ltree, static_l_desc); - s.d_desc = new TreeDesc(s.dyn_dtree, static_d_desc); - s.bl_desc = new TreeDesc(s.bl_tree, static_bl_desc); - - s.bi_buf = 0; - s.bi_valid = 0; - - /* Initialize the first block of the first file: */ - init_block(s); - } - - - /* =========================================================================== - * Send a stored block - */ - function _tr_stored_block(s, buf, stored_len, last) - //DeflateState *s; - //charf *buf; /* input block */ - //ulg stored_len; /* length of input block */ - //int last; /* one if this is the last block for a file */ - { - send_bits(s, (STORED_BLOCK << 1) + (last ? 1 : 0), 3); /* send block type */ - copy_block(s, buf, stored_len, true); /* with header */ - } - - - /* =========================================================================== - * Send one empty static block to give enough lookahead for inflate. - * This takes 10 bits, of which 7 may remain in the bit buffer. - */ - function _tr_align(s) { - send_bits(s, STATIC_TREES << 1, 3); - send_code(s, END_BLOCK, static_ltree); - bi_flush(s); - } - - - /* =========================================================================== - * Determine the best encoding for the current block: dynamic trees, static - * trees or store, and output the encoded block to the zip file. - */ - function _tr_flush_block(s, buf, stored_len, last) - //DeflateState *s; - //charf *buf; /* input block, or NULL if too old */ - //ulg stored_len; /* length of input block */ - //int last; /* one if this is the last block for a file */ - { - let opt_lenb, static_lenb; /* opt_len and static_len in bytes */ - let max_blindex = 0; /* index of last bit length code of non zero freq */ - - /* Build the Huffman trees unless a stored block is forced */ - if (s.level > 0) { - - /* Check if the file is binary or text */ - if (s.strm.data_type === Z_UNKNOWN) { - s.strm.data_type = detect_data_type(s); - } - - /* Construct the literal and distance trees */ - build_tree(s, s.l_desc); - // Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, - // s->static_len)); - - build_tree(s, s.d_desc); - // Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, - // s->static_len)); - /* At this point, opt_len and static_len are the total bit lengths of - * the compressed block data, excluding the tree representations. - */ - - /* Build the bit length tree for the above two trees, and get the index - * in bl_order of the last bit length code to send. - */ - max_blindex = build_bl_tree(s); - - /* Determine the best encoding. Compute the block lengths in bytes. */ - opt_lenb = s.opt_len + 3 + 7 >>> 3; - static_lenb = s.static_len + 3 + 7 >>> 3; - - // Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", - // opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, - // s->last_lit)); - - if (static_lenb <= opt_lenb) { - opt_lenb = static_lenb; - } - - } else { - // Assert(buf != (char*)0, "lost buf"); - opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ - } - - if (stored_len + 4 <= opt_lenb && buf !== -1) { - /* 4: two words for the lengths */ - - /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. - * Otherwise we can't have processed more than WSIZE input bytes since - * the last block flush, because compression would have been - * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to - * transform a block into a stored block. - */ - _tr_stored_block(s, buf, stored_len, last); - - } else if (s.strategy === Z_FIXED || static_lenb === opt_lenb) { - - send_bits(s, (STATIC_TREES << 1) + (last ? 1 : 0), 3); - compress_block(s, static_ltree, static_dtree); - - } else { - send_bits(s, (DYN_TREES << 1) + (last ? 1 : 0), 3); - send_all_trees(s, s.l_desc.max_code + 1, s.d_desc.max_code + 1, max_blindex + 1); - compress_block(s, s.dyn_ltree, s.dyn_dtree); - } - // Assert (s->compressed_len == s->bits_sent, "bad compressed size"); - /* The above check is made mod 2^32, for files larger than 512 MB - * and uLong implemented on 32 bits. - */ - init_block(s); - - if (last) { - bi_windup(s); - } - // Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, - // s->compressed_len-7*last)); - } - - /* =========================================================================== - * Save the match info and tally the frequency counts. Return true if - * the current block must be flushed. - */ - function _tr_tally(s, dist, lc) - // deflate_state *s; - // unsigned dist; /* distance of matched string */ - // unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ - { - //var out_length, in_length, dcode; - - s.pending_buf[s.d_buf + s.last_lit * 2] = dist >>> 8 & 0xff; - s.pending_buf[s.d_buf + s.last_lit * 2 + 1] = dist & 0xff; - - s.pending_buf[s.l_buf + s.last_lit] = lc & 0xff; - s.last_lit++; - - if (dist === 0) { - /* lc is the unmatched char */ - s.dyn_ltree[lc * 2]/*.Freq*/++; - } else { - s.matches++; - /* Here, lc is the match length - MIN_MATCH */ - dist--; /* dist = match distance - 1 */ - //Assert((ush)dist < (ush)MAX_DIST(s) && - // (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && - // (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); - - s.dyn_ltree[(_length_code[lc] + LITERALS + 1) * 2]/*.Freq*/++; - s.dyn_dtree[d_code(dist) * 2]/*.Freq*/++; - } - - // (!) This block is disabled in zlib defaults, - // don't enable it for binary compatibility - - //#ifdef TRUNCATE_BLOCK - // /* Try to guess if it is profitable to stop the current block here */ - // if ((s.last_lit & 0x1fff) === 0 && s.level > 2) { - // /* Compute an upper bound for the compressed length */ - // out_length = s.last_lit*8; - // in_length = s.strstart - s.block_start; - // - // for (dcode = 0; dcode < D_CODES; dcode++) { - // out_length += s.dyn_dtree[dcode*2]/*.Freq*/ * (5 + extra_dbits[dcode]); - // } - // out_length >>>= 3; - // //Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", - // // s->last_lit, in_length, out_length, - // // 100L - out_length*100L/in_length)); - // if (s.matches < (s.last_lit>>1)/*int /2*/ && out_length < (in_length>>1)/*int /2*/) { - // return true; - // } - // } - //#endif - - return s.last_lit === s.lit_bufsize - 1; - /* We avoid equality with lit_bufsize because of wraparound at 64K - * on 16 bit machines and because stored blocks are restricted to - * 64K-1 bytes. - */ - } - - // Note: adler32 takes 12% for level 0 and 2% for level 6. - // It isn't worth it to make additional optimizations as in original. - // Small size is preferable. - - // (C) 1995-2013 Jean-loup Gailly and Mark Adler - // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin - // - // This software is provided 'as-is', without any express or implied - // warranty. In no event will the authors be held liable for any damages - // arising from the use of this software. - // - // Permission is granted to anyone to use this software for any purpose, - // including commercial applications, and to alter it and redistribute it - // freely, subject to the following restrictions: - // - // 1. The origin of this software must not be misrepresented; you must not - // claim that you wrote the original software. If you use this software - // in a product, an acknowledgment in the product documentation would be - // appreciated but is not required. - // 2. Altered source versions must be plainly marked as such, and must not be - // misrepresented as being the original software. - // 3. This notice may not be removed or altered from any source distribution. - - function adler32(adler, buf, len, pos) { - let s1 = adler & 0xffff |0, - s2 = adler >>> 16 & 0xffff |0, - n = 0; - - while (len !== 0) { - // Set limit ~ twice less than 5552, to keep - // s2 in 31-bits, because we force signed ints. - // in other case %= will fail. - n = len > 2000 ? 2000 : len; - len -= n; - - do { - s1 = s1 + buf[pos++] |0; - s2 = s2 + s1 |0; - } while (--n); - - s1 %= 65521; - s2 %= 65521; - } - - return s1 | s2 << 16 |0; - } - - // Note: we can't get significant speed boost here. - // So write code to minimize size - no pregenerated tables - // and array tools dependencies. - - // (C) 1995-2013 Jean-loup Gailly and Mark Adler - // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin - // - // This software is provided 'as-is', without any express or implied - // warranty. In no event will the authors be held liable for any damages - // arising from the use of this software. - // - // Permission is granted to anyone to use this software for any purpose, - // including commercial applications, and to alter it and redistribute it - // freely, subject to the following restrictions: - // - // 1. The origin of this software must not be misrepresented; you must not - // claim that you wrote the original software. If you use this software - // in a product, an acknowledgment in the product documentation would be - // appreciated but is not required. - // 2. Altered source versions must be plainly marked as such, and must not be - // misrepresented as being the original software. - // 3. This notice may not be removed or altered from any source distribution. - - // Use ordinary array, since untyped makes no boost here - function makeTable() { - let c; - const table = []; - - for (let n = 0; n < 256; n++) { - c = n; - for (let k = 0; k < 8; k++) { - c = c & 1 ? 0xEDB88320 ^ c >>> 1 : c >>> 1; - } - table[n] = c; - } - - return table; - } - - // Create table on load. Just 255 signed longs. Not a problem. - const crcTable = makeTable(); - - - function crc32(crc, buf, len, pos) { - const t = crcTable, - end = pos + len; - - crc ^= -1; - - for (let i = pos; i < end; i++) { - crc = crc >>> 8 ^ t[(crc ^ buf[i]) & 0xFF]; - } - - return crc ^ -1; // >>> 0; - } - - // (C) 1995-2013 Jean-loup Gailly and Mark Adler - // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin - // - // This software is provided 'as-is', without any express or implied - // warranty. In no event will the authors be held liable for any damages - // arising from the use of this software. - // - // Permission is granted to anyone to use this software for any purpose, - // including commercial applications, and to alter it and redistribute it - // freely, subject to the following restrictions: - // - // 1. The origin of this software must not be misrepresented; you must not - // claim that you wrote the original software. If you use this software - // in a product, an acknowledgment in the product documentation would be - // appreciated but is not required. - // 2. Altered source versions must be plainly marked as such, and must not be - // misrepresented as being the original software. - // 3. This notice may not be removed or altered from any source distribution. - - var msg = { - 2: "need dictionary", /* Z_NEED_DICT 2 */ - 1: "stream end", /* Z_STREAM_END 1 */ - 0: "", /* Z_OK 0 */ - "-1": "file error", /* Z_ERRNO (-1) */ - "-2": "stream error", /* Z_STREAM_ERROR (-2) */ - "-3": "data error", /* Z_DATA_ERROR (-3) */ - "-4": "insufficient memory", /* Z_MEM_ERROR (-4) */ - "-5": "buffer error", /* Z_BUF_ERROR (-5) */ - "-6": "incompatible version" /* Z_VERSION_ERROR (-6) */ - }; - - /*============================================================================*/ - - - const MAX_MEM_LEVEL = 9; - - - const LENGTH_CODES$1 = 29; - /* number of length codes, not counting the special END_BLOCK code */ - const LITERALS$1 = 256; - /* number of literal bytes 0..255 */ - const L_CODES$1 = LITERALS$1 + 1 + LENGTH_CODES$1; - /* number of Literal or Length codes, including the END_BLOCK code */ - const D_CODES$1 = 30; - /* number of distance codes */ - const BL_CODES$1 = 19; - /* number of codes used to transfer the bit lengths */ - const HEAP_SIZE$1 = 2 * L_CODES$1 + 1; - /* maximum heap size */ - const MAX_BITS$1 = 15; - /* All codes must not exceed MAX_BITS bits */ - - const MIN_MATCH$1 = 3; - const MAX_MATCH$1 = 258; - const MIN_LOOKAHEAD = (MAX_MATCH$1 + MIN_MATCH$1 + 1); - - const PRESET_DICT = 0x20; - - const INIT_STATE = 42; - const EXTRA_STATE = 69; - const NAME_STATE = 73; - const COMMENT_STATE = 91; - const HCRC_STATE = 103; - const BUSY_STATE = 113; - const FINISH_STATE = 666; - - const BS_NEED_MORE = 1; /* block not completed, need more input or more output */ - const BS_BLOCK_DONE = 2; /* block flush performed */ - const BS_FINISH_STARTED = 3; /* finish started, need only more output at next deflate */ - const BS_FINISH_DONE = 4; /* finish done, accept no more input or output */ - - const OS_CODE = 0x03; // Unix :) . Don't detect, use this default. - - function err(strm, errorCode) { - strm.msg = msg[errorCode]; - return errorCode; - } - - function rank(f) { - return ((f) << 1) - ((f) > 4 ? 9 : 0); - } - - function zero$2(buf) { let len = buf.length; while (--len >= 0) { buf[len] = 0; } } - - - /* ========================================================================= - * Flush as much pending output as possible. All deflate() output goes - * through this function so some applications may wish to modify it - * to avoid allocating a large strm->output buffer and copying into it. - * (See also read_buf()). - */ - function flush_pending(strm) { - const s = strm.state; - - //_tr_flush_bits(s); - let len = s.pending; - if (len > strm.avail_out) { - len = strm.avail_out; - } - if (len === 0) { return; } - - arraySet(strm.output, s.pending_buf, s.pending_out, len, strm.next_out); - strm.next_out += len; - s.pending_out += len; - strm.total_out += len; - strm.avail_out -= len; - s.pending -= len; - if (s.pending === 0) { - s.pending_out = 0; - } - } - - - function flush_block_only(s, last) { - _tr_flush_block(s, (s.block_start >= 0 ? s.block_start : -1), s.strstart - s.block_start, last); - s.block_start = s.strstart; - flush_pending(s.strm); - } - - - function put_byte(s, b) { - s.pending_buf[s.pending++] = b; - } - - - /* ========================================================================= - * Put a short in the pending buffer. The 16-bit value is put in MSB order. - * IN assertion: the stream state is correct and there is enough room in - * pending_buf. - */ - function putShortMSB(s, b) { - // put_byte(s, (Byte)(b >> 8)); - // put_byte(s, (Byte)(b & 0xff)); - s.pending_buf[s.pending++] = (b >>> 8) & 0xff; - s.pending_buf[s.pending++] = b & 0xff; - } - - - /* =========================================================================== - * Read a new buffer from the current input stream, update the adler32 - * and total number of bytes read. All deflate() input goes through - * this function so some applications may wish to modify it to avoid - * allocating a large strm->input buffer and copying from it. - * (See also flush_pending()). - */ - function read_buf(strm, buf, start, size) { - let len = strm.avail_in; - - if (len > size) { len = size; } - if (len === 0) { return 0; } - - strm.avail_in -= len; - - // zmemcpy(buf, strm->next_in, len); - arraySet(buf, strm.input, strm.next_in, len, start); - if (strm.state.wrap === 1) { - strm.adler = adler32(strm.adler, buf, len, start); - } - - else if (strm.state.wrap === 2) { - strm.adler = crc32(strm.adler, buf, len, start); - } - - strm.next_in += len; - strm.total_in += len; - - return len; - } - - - /* =========================================================================== - * Set match_start to the longest match starting at the given string and - * return its length. Matches shorter or equal to prev_length are discarded, - * in which case the result is equal to prev_length and match_start is - * garbage. - * IN assertions: cur_match is the head of the hash chain for the current - * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 - * OUT assertion: the match length is not greater than s->lookahead. - */ - function longest_match(s, cur_match) { - let chain_length = s.max_chain_length; /* max hash chain length */ - let scan = s.strstart; /* current string */ - let match; /* matched string */ - let len; /* length of current match */ - let best_len = s.prev_length; /* best match length so far */ - let nice_match = s.nice_match; /* stop if match long enough */ - const limit = (s.strstart > (s.w_size - MIN_LOOKAHEAD)) ? - s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0/*NIL*/; - - const _win = s.window; // shortcut - - const wmask = s.w_mask; - const prev = s.prev; - - /* Stop when cur_match becomes <= limit. To simplify the code, - * we prevent matches with the string of window index 0. - */ - - const strend = s.strstart + MAX_MATCH$1; - let scan_end1 = _win[scan + best_len - 1]; - let scan_end = _win[scan + best_len]; - - /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - * It is easy to get rid of this optimization if necessary. - */ - // Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - - /* Do not waste too much time if we already have a good match: */ - if (s.prev_length >= s.good_match) { - chain_length >>= 2; - } - /* Do not look for matches beyond the end of the input. This is necessary - * to make deflate deterministic. - */ - if (nice_match > s.lookahead) { nice_match = s.lookahead; } - - // Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); - - do { - // Assert(cur_match < s->strstart, "no future"); - match = cur_match; - - /* Skip to next match if the match length cannot increase - * or if the match length is less than 2. Note that the checks below - * for insufficient lookahead only occur occasionally for performance - * reasons. Therefore uninitialized memory will be accessed, and - * conditional jumps will be made that depend on those values. - * However the length of the match is limited to the lookahead, so - * the output of deflate is not affected by the uninitialized values. - */ - - if (_win[match + best_len] !== scan_end || - _win[match + best_len - 1] !== scan_end1 || - _win[match] !== _win[scan] || - _win[++match] !== _win[scan + 1]) { - continue; - } - - /* The check at best_len-1 can be removed because it will be made - * again later. (This heuristic is not always a win.) - * It is not necessary to compare scan[2] and match[2] since they - * are always equal when the other bytes match, given that - * the hash keys are equal and that HASH_BITS >= 8. - */ - scan += 2; - match++; - // Assert(*scan == *match, "match[2]?"); - - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. - */ - do { - /*jshint noempty:false*/ - } while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - scan < strend); - - // Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - - len = MAX_MATCH$1 - (strend - scan); - scan = strend - MAX_MATCH$1; - - if (len > best_len) { - s.match_start = cur_match; - best_len = len; - if (len >= nice_match) { - break; - } - scan_end1 = _win[scan + best_len - 1]; - scan_end = _win[scan + best_len]; - } - } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0); - - if (best_len <= s.lookahead) { - return best_len; - } - return s.lookahead; - } - - - /* =========================================================================== - * Fill the window when the lookahead becomes insufficient. - * Updates strstart and lookahead. - * - * IN assertion: lookahead < MIN_LOOKAHEAD - * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD - * At least one byte has been read, or avail_in == 0; reads are - * performed for at least two bytes (required for the zip translate_eol - * option -- not supported here). - */ - function fill_window(s) { - const _w_size = s.w_size; - let p, n, m, more, str; - - //Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); - - do { - more = s.window_size - s.lookahead - s.strstart; - - // JS ints have 32 bit, block below not needed - /* Deal with !@#$% 64K limit: */ - //if (sizeof(int) <= 2) { - // if (more == 0 && s->strstart == 0 && s->lookahead == 0) { - // more = wsize; - // - // } else if (more == (unsigned)(-1)) { - // /* Very unlikely, but possible on 16 bit machine if - // * strstart == 0 && lookahead == 1 (input done a byte at time) - // */ - // more--; - // } - //} - - - /* If the window is almost full and there is insufficient lookahead, - * move the upper half to the lower one to make room in the upper half. - */ - if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) { - - arraySet(s.window, s.window, _w_size, _w_size, 0); - s.match_start -= _w_size; - s.strstart -= _w_size; - /* we now have strstart >= MAX_DIST */ - s.block_start -= _w_size; - - /* Slide the hash table (could be avoided with 32 bit values - at the expense of memory usage). We slide even when level == 0 - to keep the hash table consistent if we switch back to level > 0 - later. (Using level 0 permanently is not an optimal usage of - zlib, so we don't care about this pathological case.) - */ - - n = s.hash_size; - p = n; - do { - m = s.head[--p]; - s.head[p] = (m >= _w_size ? m - _w_size : 0); - } while (--n); - - n = _w_size; - p = n; - do { - m = s.prev[--p]; - s.prev[p] = (m >= _w_size ? m - _w_size : 0); - /* If n is not on any hash chain, prev[n] is garbage but - * its value will never be used. - */ - } while (--n); - - more += _w_size; - } - if (s.strm.avail_in === 0) { - break; - } - - /* If there was no sliding: - * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && - * more == window_size - lookahead - strstart - * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) - * => more >= window_size - 2*WSIZE + 2 - * In the BIG_MEM or MMAP case (not yet supported), - * window_size == input_size + MIN_LOOKAHEAD && - * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. - * Otherwise, window_size == 2*WSIZE so more >= 2. - * If there was sliding, more >= WSIZE. So in all cases, more >= 2. - */ - //Assert(more >= 2, "more < 2"); - n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more); - s.lookahead += n; - - /* Initialize the hash value now that we have some input: */ - if (s.lookahead + s.insert >= MIN_MATCH$1) { - str = s.strstart - s.insert; - s.ins_h = s.window[str]; - - /* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + 1]) & s.hash_mask; - //#if MIN_MATCH != 3 - // Call update_hash() MIN_MATCH-3 more times - //#endif - while (s.insert) { - /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH$1 - 1]) & s.hash_mask; - - s.prev[str & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = str; - str++; - s.insert--; - if (s.lookahead + s.insert < MIN_MATCH$1) { - break; - } - } - } - /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, - * but this is not important since only literal bytes will be emitted. - */ - - } while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0); - - /* If the WIN_INIT bytes after the end of the current data have never been - * written, then zero those bytes in order to avoid memory check reports of - * the use of uninitialized (or uninitialised as Julian writes) bytes by - * the longest match routines. Update the high water mark for the next - * time through here. WIN_INIT is set to MAX_MATCH since the longest match - * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. - */ - // if (s.high_water < s.window_size) { - // var curr = s.strstart + s.lookahead; - // var init = 0; - // - // if (s.high_water < curr) { - // /* Previous high water mark below current data -- zero WIN_INIT - // * bytes or up to end of window, whichever is less. - // */ - // init = s.window_size - curr; - // if (init > WIN_INIT) - // init = WIN_INIT; - // zmemzero(s->window + curr, (unsigned)init); - // s->high_water = curr + init; - // } - // else if (s->high_water < (ulg)curr + WIN_INIT) { - // /* High water mark at or above current data, but below current data - // * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up - // * to end of window, whichever is less. - // */ - // init = (ulg)curr + WIN_INIT - s->high_water; - // if (init > s->window_size - s->high_water) - // init = s->window_size - s->high_water; - // zmemzero(s->window + s->high_water, (unsigned)init); - // s->high_water += init; - // } - // } - // - // Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, - // "not enough room for search"); - } - - /* =========================================================================== - * Copy without compression as much as possible from the input stream, return - * the current block state. - * This function does not insert new strings in the dictionary since - * uncompressible data is probably not useful. This function is used - * only for the level=0 compression option. - * NOTE: this function should be optimized to avoid extra copying from - * window to pending_buf. - */ - function deflate_stored(s, flush) { - /* Stored blocks are limited to 0xffff bytes, pending_buf is limited - * to pending_buf_size, and each stored block has a 5 byte header: - */ - let max_block_size = 0xffff; - - if (max_block_size > s.pending_buf_size - 5) { - max_block_size = s.pending_buf_size - 5; - } - - /* Copy as much as possible from input to output: */ - for (; ;) { - /* Fill the window as much as possible: */ - if (s.lookahead <= 1) { - - //Assert(s->strstart < s->w_size+MAX_DIST(s) || - // s->block_start >= (long)s->w_size, "slide too late"); - // if (!(s.strstart < s.w_size + (s.w_size - MIN_LOOKAHEAD) || - // s.block_start >= s.w_size)) { - // throw new Error("slide too late"); - // } - - fill_window(s); - if (s.lookahead === 0 && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - - if (s.lookahead === 0) { - break; - } - /* flush the current block */ - } - //Assert(s->block_start >= 0L, "block gone"); - // if (s.block_start < 0) throw new Error("block gone"); - - s.strstart += s.lookahead; - s.lookahead = 0; - - /* Emit a stored block if pending_buf will be full: */ - const max_start = s.block_start + max_block_size; - - if (s.strstart === 0 || s.strstart >= max_start) { - /* strstart == 0 is possible when wraparound on 16-bit machine */ - s.lookahead = s.strstart - max_start; - s.strstart = max_start; - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - - - } - /* Flush if we may have to slide, otherwise block_start may become - * negative and the data will be gone: - */ - if (s.strstart - s.block_start >= (s.w_size - MIN_LOOKAHEAD)) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } - - s.insert = 0; - - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - - if (s.strstart > s.block_start) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - - return BS_NEED_MORE; - } - - /* =========================================================================== - * Compress as much as possible from the input stream, return the current - * block state. - * This function does not perform lazy evaluation of matches and inserts - * new strings in the dictionary only for unmatched strings or for short - * matches. It is used only for the fast compression options. - */ - function deflate_fast(s, flush) { - let hash_head; /* head of the hash chain */ - let bflush; /* set if current block must be flushed */ - - for (; ;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s.lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - if (s.lookahead === 0) { - break; /* flush the current block */ - } - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - hash_head = 0/*NIL*/; - if (s.lookahead >= MIN_MATCH$1) { - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - } - - /* Find the longest match, discarding those <= prev_length. - * At this point we have always match_length < MIN_MATCH - */ - if (hash_head !== 0/*NIL*/ && ((s.strstart - hash_head) <= (s.w_size - MIN_LOOKAHEAD))) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - s.match_length = longest_match(s, hash_head); - /* longest_match() sets match_start */ - } - if (s.match_length >= MIN_MATCH$1) { - // check_match(s, s.strstart, s.match_start, s.match_length); // for debug only - - /*** _tr_tally_dist(s, s.strstart - s.match_start, - s.match_length - MIN_MATCH, bflush); ***/ - bflush = _tr_tally(s, s.strstart - s.match_start, s.match_length - MIN_MATCH$1); - - s.lookahead -= s.match_length; - - /* Insert new strings in the hash table only if the match length - * is not too large. This saves time but degrades compression. - */ - if (s.match_length <= s.max_lazy_match/*max_insert_length*/ && s.lookahead >= MIN_MATCH$1) { - s.match_length--; /* string at strstart already in table */ - do { - s.strstart++; - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - /* strstart never exceeds WSIZE-MAX_MATCH, so there are - * always MIN_MATCH bytes ahead. - */ - } while (--s.match_length !== 0); - s.strstart++; - } else { - s.strstart += s.match_length; - s.match_length = 0; - s.ins_h = s.window[s.strstart]; - /* UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]); */ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + 1]) & s.hash_mask; - - //#if MIN_MATCH != 3 - // Call UPDATE_HASH() MIN_MATCH-3 more times - //#endif - /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not - * matter since it will be recomputed at next deflate call. - */ - } - } else { - /* No match, output a literal byte */ - //Tracevv((stderr,"%c", s.window[s.strstart])); - /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ - bflush = _tr_tally(s, 0, s.window[s.strstart]); - - s.lookahead--; - s.strstart++; - } - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } - s.insert = ((s.strstart < (MIN_MATCH$1 - 1)) ? s.strstart : MIN_MATCH$1 - 1); - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - return BS_BLOCK_DONE; - } - - /* =========================================================================== - * Same as above, but achieves better compression. We use a lazy - * evaluation for matches: a match is finally adopted only if there is - * no better match at the next window position. - */ - function deflate_slow(s, flush) { - let hash_head; /* head of hash chain */ - let bflush; /* set if current block must be flushed */ - - let max_insert; - - /* Process the input block. */ - for (; ;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s.lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - if (s.lookahead === 0) { break; } /* flush the current block */ - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - hash_head = 0/*NIL*/; - if (s.lookahead >= MIN_MATCH$1) { - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - } - - /* Find the longest match, discarding those <= prev_length. - */ - s.prev_length = s.match_length; - s.prev_match = s.match_start; - s.match_length = MIN_MATCH$1 - 1; - - if (hash_head !== 0/*NIL*/ && s.prev_length < s.max_lazy_match && - s.strstart - hash_head <= (s.w_size - MIN_LOOKAHEAD)/*MAX_DIST(s)*/) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - s.match_length = longest_match(s, hash_head); - /* longest_match() sets match_start */ - - if (s.match_length <= 5 && - (s.strategy === Z_FILTERED || (s.match_length === MIN_MATCH$1 && s.strstart - s.match_start > 4096/*TOO_FAR*/))) { - - /* If prev_match is also MIN_MATCH, match_start is garbage - * but we will ignore the current match anyway. - */ - s.match_length = MIN_MATCH$1 - 1; - } - } - /* If there was a match at the previous step and the current - * match is not better, output the previous match: - */ - if (s.prev_length >= MIN_MATCH$1 && s.match_length <= s.prev_length) { - max_insert = s.strstart + s.lookahead - MIN_MATCH$1; - /* Do not insert strings in hash table beyond this. */ - - //check_match(s, s.strstart-1, s.prev_match, s.prev_length); - - /***_tr_tally_dist(s, s.strstart - 1 - s.prev_match, - s.prev_length - MIN_MATCH, bflush);***/ - bflush = _tr_tally(s, s.strstart - 1 - s.prev_match, s.prev_length - MIN_MATCH$1); - /* Insert in hash table all strings up to the end of the match. - * strstart-1 and strstart are already inserted. If there is not - * enough lookahead, the last two strings are not inserted in - * the hash table. - */ - s.lookahead -= s.prev_length - 1; - s.prev_length -= 2; - do { - if (++s.strstart <= max_insert) { - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH$1 - 1]) & s.hash_mask; - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - } - } while (--s.prev_length !== 0); - s.match_available = 0; - s.match_length = MIN_MATCH$1 - 1; - s.strstart++; - - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - - } else if (s.match_available) { - /* If there was no match at the previous position, output a - * single literal. If there was a match but the current match - * is longer, truncate the previous match to a single literal. - */ - //Tracevv((stderr,"%c", s->window[s->strstart-1])); - /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ - bflush = _tr_tally(s, 0, s.window[s.strstart - 1]); - - if (bflush) { - /*** FLUSH_BLOCK_ONLY(s, 0) ***/ - flush_block_only(s, false); - /***/ - } - s.strstart++; - s.lookahead--; - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - } else { - /* There is no previous match to compare with, wait for - * the next step to decide. - */ - s.match_available = 1; - s.strstart++; - s.lookahead--; - } - } - //Assert (flush != Z_NO_FLUSH, "no flush?"); - if (s.match_available) { - //Tracevv((stderr,"%c", s->window[s->strstart-1])); - /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ - bflush = _tr_tally(s, 0, s.window[s.strstart - 1]); - - s.match_available = 0; - } - s.insert = s.strstart < MIN_MATCH$1 - 1 ? s.strstart : MIN_MATCH$1 - 1; - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - - return BS_BLOCK_DONE; - } - - - /* =========================================================================== - * For Z_RLE, simply look for runs of bytes, generate matches only of distance - * one. Do not maintain a hash table. (It will be regenerated if this run of - * deflate switches away from Z_RLE.) - */ - function deflate_rle(s, flush) { - let bflush; /* set if current block must be flushed */ - let prev; /* byte at distance one to match */ - let scan, strend; /* scan goes up to strend for length of run */ - - const _win = s.window; - - for (; ;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the longest run, plus one for the unrolled loop. - */ - if (s.lookahead <= MAX_MATCH$1) { - fill_window(s); - if (s.lookahead <= MAX_MATCH$1 && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - if (s.lookahead === 0) { break; } /* flush the current block */ - } - - /* See how many times the previous byte repeats */ - s.match_length = 0; - if (s.lookahead >= MIN_MATCH$1 && s.strstart > 0) { - scan = s.strstart - 1; - prev = _win[scan]; - if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) { - strend = s.strstart + MAX_MATCH$1; - do { - /*jshint noempty:false*/ - } while (prev === _win[++scan] && prev === _win[++scan] && - prev === _win[++scan] && prev === _win[++scan] && - prev === _win[++scan] && prev === _win[++scan] && - prev === _win[++scan] && prev === _win[++scan] && - scan < strend); - s.match_length = MAX_MATCH$1 - (strend - scan); - if (s.match_length > s.lookahead) { - s.match_length = s.lookahead; - } - } - //Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); - } - - /* Emit match if have run of MIN_MATCH or longer, else emit literal */ - if (s.match_length >= MIN_MATCH$1) { - //check_match(s, s.strstart, s.strstart - 1, s.match_length); - - /*** _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ***/ - bflush = _tr_tally(s, 1, s.match_length - MIN_MATCH$1); - - s.lookahead -= s.match_length; - s.strstart += s.match_length; - s.match_length = 0; - } else { - /* No match, output a literal byte */ - //Tracevv((stderr,"%c", s->window[s->strstart])); - /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ - bflush = _tr_tally(s, 0, s.window[s.strstart]); - - s.lookahead--; - s.strstart++; - } - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } - s.insert = 0; - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - return BS_BLOCK_DONE; - } - - /* =========================================================================== - * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. - * (It will be regenerated if this run of deflate switches away from Huffman.) - */ - function deflate_huff(s, flush) { - let bflush; /* set if current block must be flushed */ - - for (; ;) { - /* Make sure that we have a literal to write. */ - if (s.lookahead === 0) { - fill_window(s); - if (s.lookahead === 0) { - if (flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - break; /* flush the current block */ - } - } - - /* Output a literal byte */ - s.match_length = 0; - //Tracevv((stderr,"%c", s->window[s->strstart])); - /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ - bflush = _tr_tally(s, 0, s.window[s.strstart]); - s.lookahead--; - s.strstart++; - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } - s.insert = 0; - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - return BS_BLOCK_DONE; - } - - /* Values for max_lazy_match, good_match and max_chain_length, depending on - * the desired pack level (0..9). The values given below have been tuned to - * exclude worst case performance for pathological files. Better values may be - * found for specific files. - */ - class Config { - constructor(good_length, max_lazy, nice_length, max_chain, func) { - this.good_length = good_length; - this.max_lazy = max_lazy; - this.nice_length = nice_length; - this.max_chain = max_chain; - this.func = func; - } - } - const configuration_table = [ - /* good lazy nice chain */ - new Config(0, 0, 0, 0, deflate_stored), /* 0 store only */ - new Config(4, 4, 8, 4, deflate_fast), /* 1 max speed, no lazy matches */ - new Config(4, 5, 16, 8, deflate_fast), /* 2 */ - new Config(4, 6, 32, 32, deflate_fast), /* 3 */ - - new Config(4, 4, 16, 16, deflate_slow), /* 4 lazy matches */ - new Config(8, 16, 32, 32, deflate_slow), /* 5 */ - new Config(8, 16, 128, 128, deflate_slow), /* 6 */ - new Config(8, 32, 128, 256, deflate_slow), /* 7 */ - new Config(32, 128, 258, 1024, deflate_slow), /* 8 */ - new Config(32, 258, 258, 4096, deflate_slow) /* 9 max compression */ - ]; - - - /* =========================================================================== - * Initialize the "longest match" routines for a new zlib stream - */ - function lm_init(s) { - s.window_size = 2 * s.w_size; - - /*** CLEAR_HASH(s); ***/ - zero$2(s.head); // Fill with NIL (= 0); - - /* Set the default configuration parameters: - */ - s.max_lazy_match = configuration_table[s.level].max_lazy; - s.good_match = configuration_table[s.level].good_length; - s.nice_match = configuration_table[s.level].nice_length; - s.max_chain_length = configuration_table[s.level].max_chain; - - s.strstart = 0; - s.block_start = 0; - s.lookahead = 0; - s.insert = 0; - s.match_length = s.prev_length = MIN_MATCH$1 - 1; - s.match_available = 0; - s.ins_h = 0; - } - - class DeflateState { - constructor() { - this.strm = null; /* pointer back to this zlib stream */ - this.status = 0; /* as the name implies */ - this.pending_buf = null; /* output still pending */ - this.pending_buf_size = 0; /* size of pending_buf */ - this.pending_out = 0; /* next pending byte to output to the stream */ - this.pending = 0; /* nb of bytes in the pending buffer */ - this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ - this.gzhead = null; /* gzip header information to write */ - this.gzindex = 0; /* where in extra, name, or comment */ - this.method = Z_DEFLATED; /* can only be DEFLATED */ - this.last_flush = -1; /* value of flush param for previous deflate call */ - - this.w_size = 0; /* LZ77 window size (32K by default) */ - this.w_bits = 0; /* log2(w_size) (8..16) */ - this.w_mask = 0; /* w_size - 1 */ - - this.window = null; - /* Sliding window. Input bytes are read into the second half of the window, - * and move to the first half later to keep a dictionary of at least wSize - * bytes. With this organization, matches are limited to a distance of - * wSize-MAX_MATCH bytes, but this ensures that IO is always - * performed with a length multiple of the block size. - */ - - this.window_size = 0; - /* Actual size of window: 2*wSize, except when the user input buffer - * is directly used as sliding window. - */ - - this.prev = null; - /* Link to older string with same hash index. To limit the size of this - * array to 64K, this link is maintained only for the last 32K strings. - * An index in this array is thus a window index modulo 32K. - */ - - this.head = null; /* Heads of the hash chains or NIL. */ - - this.ins_h = 0; /* hash index of string to be inserted */ - this.hash_size = 0; /* number of elements in hash table */ - this.hash_bits = 0; /* log2(hash_size) */ - this.hash_mask = 0; /* hash_size-1 */ - - this.hash_shift = 0; - /* Number of bits by which ins_h must be shifted at each input - * step. It must be such that after MIN_MATCH steps, the oldest - * byte no longer takes part in the hash key, that is: - * hash_shift * MIN_MATCH >= hash_bits - */ - - this.block_start = 0; - /* Window position at the beginning of the current output block. Gets - * negative when the window is moved backwards. - */ - - this.match_length = 0; /* length of best match */ - this.prev_match = 0; /* previous match */ - this.match_available = 0; /* set if previous match exists */ - this.strstart = 0; /* start of string to insert */ - this.match_start = 0; /* start of matching string */ - this.lookahead = 0; /* number of valid bytes ahead in window */ - - this.prev_length = 0; - /* Length of the best match at previous step. Matches not greater than this - * are discarded. This is used in the lazy match evaluation. - */ - - this.max_chain_length = 0; - /* To speed up deflation, hash chains are never searched beyond this - * length. A higher limit improves compression ratio but degrades the - * speed. - */ - - this.max_lazy_match = 0; - /* Attempt to find a better match only when the current match is strictly - * smaller than this value. This mechanism is used only for compression - * levels >= 4. - */ - // That's alias to max_lazy_match, don't use directly - //this.max_insert_length = 0; - /* Insert new strings in the hash table only if the match length is not - * greater than this length. This saves time but degrades compression. - * max_insert_length is used only for compression levels <= 3. - */ - - this.level = 0; /* compression level (1..9) */ - this.strategy = 0; /* favor or force Huffman coding*/ - - this.good_match = 0; - /* Use a faster search when the previous match is longer than this */ - - this.nice_match = 0; /* Stop searching when current match exceeds this */ - - /* used by trees.c: */ - - /* Didn't use ct_data typedef below to suppress compiler warning */ - - // struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ - // struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ - // struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ - - // Use flat array of DOUBLE size, with interleaved fata, - // because JS does not support effective - this.dyn_ltree = new Buf16(HEAP_SIZE$1 * 2); - this.dyn_dtree = new Buf16((2 * D_CODES$1 + 1) * 2); - this.bl_tree = new Buf16((2 * BL_CODES$1 + 1) * 2); - zero$2(this.dyn_ltree); - zero$2(this.dyn_dtree); - zero$2(this.bl_tree); - - this.l_desc = null; /* desc. for literal tree */ - this.d_desc = null; /* desc. for distance tree */ - this.bl_desc = null; /* desc. for bit length tree */ - - //ush bl_count[MAX_BITS+1]; - this.bl_count = new Buf16(MAX_BITS$1 + 1); - /* number of codes at each bit length for an optimal tree */ - - //int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ - this.heap = new Buf16(2 * L_CODES$1 + 1); /* heap used to build the Huffman trees */ - zero$2(this.heap); - - this.heap_len = 0; /* number of elements in the heap */ - this.heap_max = 0; /* element of largest frequency */ - /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. - * The same heap array is used to build all trees. - */ - - this.depth = new Buf16(2 * L_CODES$1 + 1); //uch depth[2*L_CODES+1]; - zero$2(this.depth); - /* Depth of each subtree used as tie breaker for trees of equal frequency - */ - - this.l_buf = 0; /* buffer index for literals or lengths */ - - this.lit_bufsize = 0; - /* Size of match buffer for literals/lengths. There are 4 reasons for - * limiting lit_bufsize to 64K: - * - frequencies can be kept in 16 bit counters - * - if compression is not successful for the first block, all input - * data is still in the window so we can still emit a stored block even - * when input comes from standard input. (This can also be done for - * all blocks if lit_bufsize is not greater than 32K.) - * - if compression is not successful for a file smaller than 64K, we can - * even emit a stored file instead of a stored block (saving 5 bytes). - * This is applicable only for zip (not gzip or zlib). - * - creating new Huffman trees less frequently may not provide fast - * adaptation to changes in the input data statistics. (Take for - * example a binary file with poorly compressible code followed by - * a highly compressible string table.) Smaller buffer sizes give - * fast adaptation but have of course the overhead of transmitting - * trees more frequently. - * - I can't count above 4 - */ - - this.last_lit = 0; /* running index in l_buf */ - - this.d_buf = 0; - /* Buffer index for distances. To simplify the code, d_buf and l_buf have - * the same number of elements. To use different lengths, an extra flag - * array would be necessary. - */ - - this.opt_len = 0; /* bit length of current block with optimal trees */ - this.static_len = 0; /* bit length of current block with static trees */ - this.matches = 0; /* number of string matches in current block */ - this.insert = 0; /* bytes at end of window left to insert */ - - - this.bi_buf = 0; - /* Output buffer. bits are inserted starting at the bottom (least - * significant bits). - */ - this.bi_valid = 0; - /* Number of valid bits in bi_buf. All bits above the last valid bit - * are always zero. - */ - - // Used for window memory init. We safely ignore it for JS. That makes - // sense only for pointers and memory check tools. - //this.high_water = 0; - /* High water mark offset in window for initialized bytes -- bytes above - * this are set to zero in order to avoid memory check warnings when - * longest match routines access bytes past the input. This is then - * updated to the new high water mark. - */ - } - } - - function deflateResetKeep(strm) { - let s; - - if (!strm || !strm.state) { - return err(strm, Z_STREAM_ERROR); - } - - strm.total_in = strm.total_out = 0; - strm.data_type = Z_UNKNOWN; - - s = strm.state; - s.pending = 0; - s.pending_out = 0; - - if (s.wrap < 0) { - s.wrap = -s.wrap; - /* was made negative by deflate(..., Z_FINISH); */ - } - s.status = (s.wrap ? INIT_STATE : BUSY_STATE); - strm.adler = (s.wrap === 2) ? - 0 // crc32(0, Z_NULL, 0) - : - 1; // adler32(0, Z_NULL, 0) - s.last_flush = Z_NO_FLUSH; - _tr_init(s); - return Z_OK; - } - - - function deflateReset(strm) { - const ret = deflateResetKeep(strm); - if (ret === Z_OK) { - lm_init(strm.state); - } - return ret; - } - - - function deflateSetHeader(strm, head) { - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - if (strm.state.wrap !== 2) { return Z_STREAM_ERROR; } - strm.state.gzhead = head; - return Z_OK; - } - - - function deflateInit2(strm, level, method, windowBits, memLevel, strategy) { - if (!strm) { // === Z_NULL - return Z_STREAM_ERROR; - } - let wrap = 1; - - if (level === Z_DEFAULT_COMPRESSION) { - level = 6; - } - - if (windowBits < 0) { /* suppress zlib wrapper */ - wrap = 0; - windowBits = -windowBits; - } - - else if (windowBits > 15) { - wrap = 2; /* write gzip wrapper instead */ - windowBits -= 16; - } - - - if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method !== Z_DEFLATED || - windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || - strategy < 0 || strategy > Z_FIXED) { - return err(strm, Z_STREAM_ERROR); - } - - - if (windowBits === 8) { - windowBits = 9; - } - /* until 256-byte window bug fixed */ - - const s = new DeflateState(); - - strm.state = s; - s.strm = strm; - - s.wrap = wrap; - s.gzhead = null; - s.w_bits = windowBits; - s.w_size = 1 << s.w_bits; - s.w_mask = s.w_size - 1; - - s.hash_bits = memLevel + 7; - s.hash_size = 1 << s.hash_bits; - s.hash_mask = s.hash_size - 1; - s.hash_shift = ~~((s.hash_bits + MIN_MATCH$1 - 1) / MIN_MATCH$1); - s.window = new Buf8(s.w_size * 2); - s.head = new Buf16(s.hash_size); - s.prev = new Buf16(s.w_size); - - // Don't need mem init magic for JS. - //s.high_water = 0; /* nothing written to s->window yet */ - - s.lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ - - s.pending_buf_size = s.lit_bufsize * 4; - - //overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); - //s->pending_buf = (uchf *) overlay; - s.pending_buf = new Buf8(s.pending_buf_size); - - // It is offset from `s.pending_buf` (size is `s.lit_bufsize * 2`) - //s->d_buf = overlay + s->lit_bufsize/sizeof(ush); - s.d_buf = 1 * s.lit_bufsize; - - //s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; - s.l_buf = (1 + 2) * s.lit_bufsize; - - s.level = level; - s.strategy = strategy; - s.method = method; - - return deflateReset(strm); - } - - - function deflate(strm, flush) { - let old_flush, s; - let beg, val; // for gzip header write only - - if (!strm || !strm.state || - flush > Z_BLOCK || flush < 0) { - return strm ? err(strm, Z_STREAM_ERROR) : Z_STREAM_ERROR; - } - - s = strm.state; - - if (!strm.output || - (!strm.input && strm.avail_in !== 0) || - (s.status === FINISH_STATE && flush !== Z_FINISH)) { - return err(strm, (strm.avail_out === 0) ? Z_BUF_ERROR : Z_STREAM_ERROR); - } - - s.strm = strm; /* just in case */ - old_flush = s.last_flush; - s.last_flush = flush; - - /* Write the header */ - if (s.status === INIT_STATE) { - - if (s.wrap === 2) { // GZIP header - strm.adler = 0; //crc32(0L, Z_NULL, 0); - put_byte(s, 31); - put_byte(s, 139); - put_byte(s, 8); - if (!s.gzhead) { // s->gzhead == Z_NULL - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, s.level === 9 ? 2 : - (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? - 4 : 0)); - put_byte(s, OS_CODE); - s.status = BUSY_STATE; - } - else { - put_byte(s, (s.gzhead.text ? 1 : 0) + - (s.gzhead.hcrc ? 2 : 0) + - (!s.gzhead.extra ? 0 : 4) + - (!s.gzhead.name ? 0 : 8) + - (!s.gzhead.comment ? 0 : 16) - ); - put_byte(s, s.gzhead.time & 0xff); - put_byte(s, (s.gzhead.time >> 8) & 0xff); - put_byte(s, (s.gzhead.time >> 16) & 0xff); - put_byte(s, (s.gzhead.time >> 24) & 0xff); - put_byte(s, s.level === 9 ? 2 : - (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? - 4 : 0)); - put_byte(s, s.gzhead.os & 0xff); - if (s.gzhead.extra && s.gzhead.extra.length) { - put_byte(s, s.gzhead.extra.length & 0xff); - put_byte(s, (s.gzhead.extra.length >> 8) & 0xff); - } - if (s.gzhead.hcrc) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending, 0); - } - s.gzindex = 0; - s.status = EXTRA_STATE; - } - } - else // DEFLATE header - { - let header = (Z_DEFLATED + ((s.w_bits - 8) << 4)) << 8; - let level_flags = -1; - - if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) { - level_flags = 0; - } else if (s.level < 6) { - level_flags = 1; - } else if (s.level === 6) { - level_flags = 2; - } else { - level_flags = 3; - } - header |= (level_flags << 6); - if (s.strstart !== 0) { header |= PRESET_DICT; } - header += 31 - (header % 31); - - s.status = BUSY_STATE; - putShortMSB(s, header); - - /* Save the adler32 of the preset dictionary: */ - if (s.strstart !== 0) { - putShortMSB(s, strm.adler >>> 16); - putShortMSB(s, strm.adler & 0xffff); - } - strm.adler = 1; // adler32(0L, Z_NULL, 0); - } - } - - //#ifdef GZIP - if (s.status === EXTRA_STATE) { - if (s.gzhead.extra/* != Z_NULL*/) { - beg = s.pending; /* start of bytes to update crc */ - - while (s.gzindex < (s.gzhead.extra.length & 0xffff)) { - if (s.pending === s.pending_buf_size) { - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - flush_pending(strm); - beg = s.pending; - if (s.pending === s.pending_buf_size) { - break; - } - } - put_byte(s, s.gzhead.extra[s.gzindex] & 0xff); - s.gzindex++; - } - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - if (s.gzindex === s.gzhead.extra.length) { - s.gzindex = 0; - s.status = NAME_STATE; - } - } - else { - s.status = NAME_STATE; - } - } - if (s.status === NAME_STATE) { - if (s.gzhead.name/* != Z_NULL*/) { - beg = s.pending; /* start of bytes to update crc */ - //int val; - - do { - if (s.pending === s.pending_buf_size) { - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - flush_pending(strm); - beg = s.pending; - if (s.pending === s.pending_buf_size) { - val = 1; - break; - } - } - // JS specific: little magic to add zero terminator to end of string - if (s.gzindex < s.gzhead.name.length) { - val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff; - } else { - val = 0; - } - put_byte(s, val); - } while (val !== 0); - - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - if (val === 0) { - s.gzindex = 0; - s.status = COMMENT_STATE; - } - } - else { - s.status = COMMENT_STATE; - } - } - if (s.status === COMMENT_STATE) { - if (s.gzhead.comment/* != Z_NULL*/) { - beg = s.pending; /* start of bytes to update crc */ - //int val; - - do { - if (s.pending === s.pending_buf_size) { - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - flush_pending(strm); - beg = s.pending; - if (s.pending === s.pending_buf_size) { - val = 1; - break; - } - } - // JS specific: little magic to add zero terminator to end of string - if (s.gzindex < s.gzhead.comment.length) { - val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff; - } else { - val = 0; - } - put_byte(s, val); - } while (val !== 0); - - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - if (val === 0) { - s.status = HCRC_STATE; - } - } - else { - s.status = HCRC_STATE; - } - } - if (s.status === HCRC_STATE) { - if (s.gzhead.hcrc) { - if (s.pending + 2 > s.pending_buf_size) { - flush_pending(strm); - } - if (s.pending + 2 <= s.pending_buf_size) { - put_byte(s, strm.adler & 0xff); - put_byte(s, (strm.adler >> 8) & 0xff); - strm.adler = 0; //crc32(0L, Z_NULL, 0); - s.status = BUSY_STATE; - } - } - else { - s.status = BUSY_STATE; - } - } - //#endif - - /* Flush as much pending output as possible */ - if (s.pending !== 0) { - flush_pending(strm); - if (strm.avail_out === 0) { - /* Since avail_out is 0, deflate will be called again with - * more output space, but possibly with both pending and - * avail_in equal to zero. There won't be anything to do, - * but this is not an error situation so make sure we - * return OK instead of BUF_ERROR at next call of deflate: - */ - s.last_flush = -1; - return Z_OK; - } - - /* Make sure there is something to do and avoid duplicate consecutive - * flushes. For repeated and useless calls with Z_FINISH, we keep - * returning Z_STREAM_END instead of Z_BUF_ERROR. - */ - } else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) && - flush !== Z_FINISH) { - return err(strm, Z_BUF_ERROR); - } - - /* User must not provide more input after the first FINISH: */ - if (s.status === FINISH_STATE && strm.avail_in !== 0) { - return err(strm, Z_BUF_ERROR); - } - - /* Start a new block or continue the current one. - */ - if (strm.avail_in !== 0 || s.lookahead !== 0 || - (flush !== Z_NO_FLUSH && s.status !== FINISH_STATE)) { - var bstate = (s.strategy === Z_HUFFMAN_ONLY) ? deflate_huff(s, flush) : - (s.strategy === Z_RLE ? deflate_rle(s, flush) : - configuration_table[s.level].func(s, flush)); - - if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) { - s.status = FINISH_STATE; - } - if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) { - if (strm.avail_out === 0) { - s.last_flush = -1; - /* avoid BUF_ERROR next call, see above */ - } - return Z_OK; - /* If flush != Z_NO_FLUSH && avail_out == 0, the next call - * of deflate should use the same flush parameter to make sure - * that the flush is complete. So we don't have to output an - * empty block here, this will be done at next call. This also - * ensures that for a very small output buffer, we emit at most - * one empty block. - */ - } - if (bstate === BS_BLOCK_DONE) { - if (flush === Z_PARTIAL_FLUSH) { - _tr_align(s); - } - else if (flush !== Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ - - _tr_stored_block(s, 0, 0, false); - /* For a full flush, this empty block will be recognized - * as a special marker by inflate_sync(). - */ - if (flush === Z_FULL_FLUSH) { - /*** CLEAR_HASH(s); ***/ /* forget history */ - zero$2(s.head); // Fill with NIL (= 0); - - if (s.lookahead === 0) { - s.strstart = 0; - s.block_start = 0; - s.insert = 0; - } - } - } - flush_pending(strm); - if (strm.avail_out === 0) { - s.last_flush = -1; /* avoid BUF_ERROR at next call, see above */ - return Z_OK; - } - } - } - //Assert(strm->avail_out > 0, "bug2"); - //if (strm.avail_out <= 0) { throw new Error("bug2");} - - if (flush !== Z_FINISH) { return Z_OK; } - if (s.wrap <= 0) { return Z_STREAM_END; } - - /* Write the trailer */ - if (s.wrap === 2) { - put_byte(s, strm.adler & 0xff); - put_byte(s, (strm.adler >> 8) & 0xff); - put_byte(s, (strm.adler >> 16) & 0xff); - put_byte(s, (strm.adler >> 24) & 0xff); - put_byte(s, strm.total_in & 0xff); - put_byte(s, (strm.total_in >> 8) & 0xff); - put_byte(s, (strm.total_in >> 16) & 0xff); - put_byte(s, (strm.total_in >> 24) & 0xff); - } - else { - putShortMSB(s, strm.adler >>> 16); - putShortMSB(s, strm.adler & 0xffff); - } - - flush_pending(strm); - /* If avail_out is zero, the application will call deflate again - * to flush the rest. - */ - if (s.wrap > 0) { s.wrap = -s.wrap; } - /* write the trailer only once! */ - return s.pending !== 0 ? Z_OK : Z_STREAM_END; - } - - function deflateEnd(strm) { - let status; - - if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) { - return Z_STREAM_ERROR; - } - - status = strm.state.status; - if (status !== INIT_STATE && - status !== EXTRA_STATE && - status !== NAME_STATE && - status !== COMMENT_STATE && - status !== HCRC_STATE && - status !== BUSY_STATE && - status !== FINISH_STATE - ) { - return err(strm, Z_STREAM_ERROR); - } - - strm.state = null; - - return status === BUSY_STATE ? err(strm, Z_DATA_ERROR) : Z_OK; - } - - - /* ========================================================================= - * Initializes the compression dictionary from the given byte - * sequence without producing any compressed output. - */ - function deflateSetDictionary(strm, dictionary) { - let dictLength = dictionary.length; - - let s; - let str, n; - let wrap; - let avail; - let next; - let input; - let tmpDict; - - if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) { - return Z_STREAM_ERROR; - } - - s = strm.state; - wrap = s.wrap; - - if (wrap === 2 || (wrap === 1 && s.status !== INIT_STATE) || s.lookahead) { - return Z_STREAM_ERROR; - } - - /* when using zlib wrappers, compute Adler-32 for provided dictionary */ - if (wrap === 1) { - /* adler32(strm->adler, dictionary, dictLength); */ - strm.adler = adler32(strm.adler, dictionary, dictLength, 0); - } - - s.wrap = 0; /* avoid computing Adler-32 in read_buf */ - - /* if dictionary would fill window, just replace the history */ - if (dictLength >= s.w_size) { - if (wrap === 0) { /* already empty otherwise */ - /*** CLEAR_HASH(s); ***/ - zero$2(s.head); // Fill with NIL (= 0); - s.strstart = 0; - s.block_start = 0; - s.insert = 0; - } - /* use the tail */ - // dictionary = dictionary.slice(dictLength - s.w_size); - tmpDict = new Buf8(s.w_size); - arraySet(tmpDict, dictionary, dictLength - s.w_size, s.w_size, 0); - dictionary = tmpDict; - dictLength = s.w_size; - } - /* insert dictionary into window and hash */ - avail = strm.avail_in; - next = strm.next_in; - input = strm.input; - strm.avail_in = dictLength; - strm.next_in = 0; - strm.input = dictionary; - fill_window(s); - while (s.lookahead >= MIN_MATCH$1) { - str = s.strstart; - n = s.lookahead - (MIN_MATCH$1 - 1); - do { - /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH$1 - 1]) & s.hash_mask; - - s.prev[str & s.w_mask] = s.head[s.ins_h]; - - s.head[s.ins_h] = str; - str++; - } while (--n); - s.strstart = str; - s.lookahead = MIN_MATCH$1 - 1; - fill_window(s); - } - s.strstart += s.lookahead; - s.block_start = s.strstart; - s.insert = s.lookahead; - s.lookahead = 0; - s.match_length = s.prev_length = MIN_MATCH$1 - 1; - s.match_available = 0; - strm.next_in = next; - strm.input = input; - strm.avail_in = avail; - s.wrap = wrap; - return Z_OK; - } - - /* Not implemented - exports.deflateBound = deflateBound; - exports.deflateCopy = deflateCopy; - exports.deflateParams = deflateParams; - exports.deflatePending = deflatePending; - exports.deflatePrime = deflatePrime; - exports.deflateTune = deflateTune; - */ - - // String encode/decode helpers - - try { - String.fromCharCode.apply(null, [ 0 ]); - } catch (__) { - } - try { - String.fromCharCode.apply(null, new Uint8Array(1)); - } catch (__) { - } - - - // Table with utf8 lengths (calculated by first byte of sequence) - // Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS, - // because max possible codepoint is 0x10ffff - const _utf8len = new Buf8(256); - for (let q = 0; q < 256; q++) { - _utf8len[q] = q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1; - } - _utf8len[254] = _utf8len[254] = 1; // Invalid sequence start - - - // convert string to array (typed, when possible) - function string2buf (str) { - let c, c2, m_pos, i, buf_len = 0; - const str_len = str.length; - - // count binary size - for (m_pos = 0; m_pos < str_len; m_pos++) { - c = str.charCodeAt(m_pos); - if ((c & 0xfc00) === 0xd800 && m_pos + 1 < str_len) { - c2 = str.charCodeAt(m_pos + 1); - if ((c2 & 0xfc00) === 0xdc00) { - c = 0x10000 + (c - 0xd800 << 10) + (c2 - 0xdc00); - m_pos++; - } - } - buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4; - } - - // allocate buffer - const buf = new Buf8(buf_len); - - // convert - for (i = 0, m_pos = 0; i < buf_len; m_pos++) { - c = str.charCodeAt(m_pos); - if ((c & 0xfc00) === 0xd800 && m_pos + 1 < str_len) { - c2 = str.charCodeAt(m_pos + 1); - if ((c2 & 0xfc00) === 0xdc00) { - c = 0x10000 + (c - 0xd800 << 10) + (c2 - 0xdc00); - m_pos++; - } - } - if (c < 0x80) { - /* one byte */ - buf[i++] = c; - } else if (c < 0x800) { - /* two bytes */ - buf[i++] = 0xC0 | c >>> 6; - buf[i++] = 0x80 | c & 0x3f; - } else if (c < 0x10000) { - /* three bytes */ - buf[i++] = 0xE0 | c >>> 12; - buf[i++] = 0x80 | c >>> 6 & 0x3f; - buf[i++] = 0x80 | c & 0x3f; - } else { - /* four bytes */ - buf[i++] = 0xf0 | c >>> 18; - buf[i++] = 0x80 | c >>> 12 & 0x3f; - buf[i++] = 0x80 | c >>> 6 & 0x3f; - buf[i++] = 0x80 | c & 0x3f; - } - } - - return buf; - } - - - // Convert binary string (typed, when possible) - function binstring2buf (str) { - const buf = new Buf8(str.length); - for (let i = 0, len = buf.length; i < len; i++) { - buf[i] = str.charCodeAt(i); - } - return buf; - } - - // (C) 1995-2013 Jean-loup Gailly and Mark Adler - // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin - // - // This software is provided 'as-is', without any express or implied - // warranty. In no event will the authors be held liable for any damages - // arising from the use of this software. - // - // Permission is granted to anyone to use this software for any purpose, - // including commercial applications, and to alter it and redistribute it - // freely, subject to the following restrictions: - // - // 1. The origin of this software must not be misrepresented; you must not - // claim that you wrote the original software. If you use this software - // in a product, an acknowledgment in the product documentation would be - // appreciated but is not required. - // 2. Altered source versions must be plainly marked as such, and must not be - // misrepresented as being the original software. - // 3. This notice may not be removed or altered from any source distribution. - - class ZStream { - constructor() { - /* next input byte */ - this.input = null; // JS specific, because we have no pointers - this.next_in = 0; - /* number of bytes available at input */ - this.avail_in = 0; - /* total number of input bytes read so far */ - this.total_in = 0; - /* next output byte should be put there */ - this.output = null; // JS specific, because we have no pointers - this.next_out = 0; - /* remaining free space at output */ - this.avail_out = 0; - /* total number of bytes output so far */ - this.total_out = 0; - /* last error message, NULL if no error */ - this.msg = ''/*Z_NULL*/; - /* not visible by applications */ - this.state = null; - /* best guess about the data type: binary or text */ - this.data_type = 2/*Z_UNKNOWN*/; - /* adler32 value of the uncompressed data */ - this.adler = 0; - } - } - - /* ===========================================================================*/ - - - /** - * class Deflate - * - * Generic JS-style wrapper for zlib calls. If you don't need - * streaming behaviour - use more simple functions: [[deflate]], - * [[deflateRaw]] and [[gzip]]. - **/ - - /* internal - * Deflate.chunks -> Array - * - * Chunks of output data, if [[Deflate#onData]] not overridden. - **/ - - /** - * Deflate.result -> Uint8Array|Array - * - * Compressed result, generated by default [[Deflate#onData]] - * and [[Deflate#onEnd]] handlers. Filled after you push last chunk - * (call [[Deflate#push]] with `Z_FINISH` / `true` param) or if you - * push a chunk with explicit flush (call [[Deflate#push]] with - * `Z_SYNC_FLUSH` param). - **/ - - /** - * Deflate.err -> Number - * - * Error code after deflate finished. 0 (Z_OK) on success. - * You will not need it in real life, because deflate errors - * are possible only on wrong options or bad `onData` / `onEnd` - * custom handlers. - **/ - - /** - * Deflate.msg -> String - * - * Error message, if [[Deflate.err]] != 0 - **/ - - - /** - * new Deflate(options) - * - options (Object): zlib deflate options. - * - * Creates new deflator instance with specified params. Throws exception - * on bad params. Supported options: - * - * - `level` - * - `windowBits` - * - `memLevel` - * - `strategy` - * - `dictionary` - * - * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) - * for more information on these. - * - * Additional options, for internal needs: - * - * - `chunkSize` - size of generated data chunks (16K by default) - * - `raw` (Boolean) - do raw deflate - * - `gzip` (Boolean) - create gzip wrapper - * - `to` (String) - if equal to 'string', then result will be "binary string" - * (each char code [0..255]) - * - `header` (Object) - custom header for gzip - * - `text` (Boolean) - true if compressed data believed to be text - * - `time` (Number) - modification time, unix timestamp - * - `os` (Number) - operation system code - * - `extra` (Array) - array of bytes with extra data (max 65536) - * - `name` (String) - file name (binary string) - * - `comment` (String) - comment (binary string) - * - `hcrc` (Boolean) - true if header crc should be added - * - * ##### Example: - * - * ```javascript - * var pako = void('pako') - * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9]) - * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]); - * - * var deflate = new pako.Deflate({ level: 3}); - * - * deflate.push(chunk1, false); - * deflate.push(chunk2, true); // true -> last chunk - * - * if (deflate.err) { throw new Error(deflate.err); } - * - * console.log(deflate.result); - * ``` - **/ - - class Deflate { - constructor(options) { - this.options = { - level: Z_DEFAULT_COMPRESSION, - method: Z_DEFLATED, - chunkSize: 16384, - windowBits: 15, - memLevel: 8, - strategy: Z_DEFAULT_STRATEGY, - ...(options || {}) - }; - - const opt = this.options; - - if (opt.raw && (opt.windowBits > 0)) { - opt.windowBits = -opt.windowBits; - } - - else if (opt.gzip && (opt.windowBits > 0) && (opt.windowBits < 16)) { - opt.windowBits += 16; - } - - this.err = 0; // error code, if happens (0 = Z_OK) - this.msg = ''; // error message - this.ended = false; // used to avoid multiple onEnd() calls - this.chunks = []; // chunks of compressed data - - this.strm = new ZStream(); - this.strm.avail_out = 0; - - var status = deflateInit2( - this.strm, - opt.level, - opt.method, - opt.windowBits, - opt.memLevel, - opt.strategy - ); - - if (status !== Z_OK) { - throw new Error(msg[status]); - } - - if (opt.header) { - deflateSetHeader(this.strm, opt.header); - } - - if (opt.dictionary) { - let dict; - // Convert data if needed - if (typeof opt.dictionary === 'string') { - // If we need to compress text, change encoding to utf8. - dict = string2buf(opt.dictionary); - } else if (opt.dictionary instanceof ArrayBuffer) { - dict = new Uint8Array(opt.dictionary); - } else { - dict = opt.dictionary; - } - - status = deflateSetDictionary(this.strm, dict); - - if (status !== Z_OK) { - throw new Error(msg[status]); - } - - this._dict_set = true; - } - } - - /** - * Deflate#push(data[, mode]) -> Boolean - * - data (Uint8Array|Array|ArrayBuffer|String): input data. Strings will be - * converted to utf8 byte sequence. - * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. - * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH. - * - * Sends input data to deflate pipe, generating [[Deflate#onData]] calls with - * new compressed chunks. Returns `true` on success. The last data block must have - * mode Z_FINISH (or `true`). That will flush internal pending buffers and call - * [[Deflate#onEnd]]. For interim explicit flushes (without ending the stream) you - * can use mode Z_SYNC_FLUSH, keeping the compression context. - * - * On fail call [[Deflate#onEnd]] with error code and return false. - * - * We strongly recommend to use `Uint8Array` on input for best speed (output - * array format is detected automatically). Also, don't skip last param and always - * use the same type in your code (boolean or number). That will improve JS speed. - * - * For regular `Array`-s make sure all elements are [0..255]. - * - * ##### Example - * - * ```javascript - * push(chunk, false); // push one of data chunks - * ... - * push(chunk, true); // push last chunk - * ``` - **/ - push(data, mode) { - const { strm, options: { chunkSize } } = this; - var status, _mode; - - if (this.ended) { return false; } - - _mode = (mode === ~~mode) ? mode : ((mode === true) ? Z_FINISH : Z_NO_FLUSH); - - // Convert data if needed - if (typeof data === 'string') { - // If we need to compress text, change encoding to utf8. - strm.input = string2buf(data); - } else if (data instanceof ArrayBuffer) { - strm.input = new Uint8Array(data); - } else { - strm.input = data; - } - - strm.next_in = 0; - strm.avail_in = strm.input.length; - - do { - if (strm.avail_out === 0) { - strm.output = new Buf8(chunkSize); - strm.next_out = 0; - strm.avail_out = chunkSize; - } - status = deflate(strm, _mode); /* no bad return value */ - - if (status !== Z_STREAM_END && status !== Z_OK) { - this.onEnd(status); - this.ended = true; - return false; - } - if (strm.avail_out === 0 || (strm.avail_in === 0 && (_mode === Z_FINISH || _mode === Z_SYNC_FLUSH))) { - this.onData(shrinkBuf(strm.output, strm.next_out)); - } - } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== Z_STREAM_END); - - // Finalize on the last chunk. - if (_mode === Z_FINISH) { - status = deflateEnd(this.strm); - this.onEnd(status); - this.ended = true; - return status === Z_OK; - } - - // callback interim results if Z_SYNC_FLUSH. - if (_mode === Z_SYNC_FLUSH) { - this.onEnd(Z_OK); - strm.avail_out = 0; - return true; - } - - return true; - }; - /** - * Deflate#onData(chunk) -> Void - * - chunk (Uint8Array|Array|String): output data. Type of array depends - * on js engine support. When string output requested, each chunk - * will be string. - * - * By default, stores data blocks in `chunks[]` property and glue - * those in `onEnd`. Override this handler, if you need another behaviour. - **/ - onData(chunk) { - this.chunks.push(chunk); - }; - - /** - * Deflate#onEnd(status) -> Void - * - status (Number): deflate status. 0 (Z_OK) on success, - * other if not. - * - * Called once after you tell deflate that the input stream is - * complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH) - * or if an error happened. By default - join collected chunks, - * free memory and fill `results` / `err` properties. - **/ - onEnd(status) { - // On success - join - if (status === Z_OK) { - this.result = flattenChunks(this.chunks); - } - this.chunks = []; - this.err = status; - this.msg = this.strm.msg; - }; - } - - // (C) 1995-2013 Jean-loup Gailly and Mark Adler - // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin - // - // This software is provided 'as-is', without any express or implied - // warranty. In no event will the authors be held liable for any damages - // arising from the use of this software. - // - // Permission is granted to anyone to use this software for any purpose, - // including commercial applications, and to alter it and redistribute it - // freely, subject to the following restrictions: - // - // 1. The origin of this software must not be misrepresented; you must not - // claim that you wrote the original software. If you use this software - // in a product, an acknowledgment in the product documentation would be - // appreciated but is not required. - // 2. Altered source versions must be plainly marked as such, and must not be - // misrepresented as being the original software. - // 3. This notice may not be removed or altered from any source distribution. - - // See state defs from inflate.js - const BAD = 30; /* got a data error -- remain here until reset */ - const TYPE = 12; /* i: waiting for type bits, including last-flag bit */ - - /* - Decode literal, length, and distance codes and write out the resulting - literal and match bytes until either not enough input or output is - available, an end-of-block is encountered, or a data error is encountered. - When large enough input and output buffers are supplied to inflate(), for - example, a 16K input buffer and a 64K output buffer, more than 95% of the - inflate execution time is spent in this routine. - - Entry assumptions: - - state.mode === LEN - strm.avail_in >= 6 - strm.avail_out >= 258 - start >= strm.avail_out - state.bits < 8 - - On return, state.mode is one of: - - LEN -- ran out of enough output space or enough available input - TYPE -- reached end of block code, inflate() to interpret next block - BAD -- error in block data - - Notes: - - - The maximum input bits used by a length/distance pair is 15 bits for the - length code, 5 bits for the length extra, 15 bits for the distance code, - and 13 bits for the distance extra. This totals 48 bits, or six bytes. - Therefore if strm.avail_in >= 6, then there is enough input to avoid - checking for available input while decoding. - - - The maximum bytes that a single length/distance pair can output is 258 - bytes, which is the maximum length that can be coded. inflate_fast() - requires strm.avail_out >= 258 for each loop to avoid checking for - output space. - */ - function inflate_fast(strm, start) { - let _in; /* local strm.input */ - let _out; /* local strm.output */ - // Use `s_window` instead `window`, avoid conflict with instrumentation tools - let hold; /* local strm.hold */ - let bits; /* local strm.bits */ - let here; /* retrieved table entry */ - let op; /* code bits, operation, extra bits, or */ - /* window position, window bytes to copy */ - let len; /* match length, unused bytes */ - let dist; /* match distance */ - let from; /* where to copy match from */ - let from_source; - - - - /* copy state to local variables */ - const state = strm.state; - //here = state.here; - _in = strm.next_in; - const input = strm.input; - const last = _in + (strm.avail_in - 5); - _out = strm.next_out; - const output = strm.output; - const beg = _out - (start - strm.avail_out); - const end = _out + (strm.avail_out - 257); - //#ifdef INFLATE_STRICT - const dmax = state.dmax; - //#endif - const wsize = state.wsize; - const whave = state.whave; - const wnext = state.wnext; - const s_window = state.window; - hold = state.hold; - bits = state.bits; - const lcode = state.lencode; - const dcode = state.distcode; - const lmask = (1 << state.lenbits) - 1; - const dmask = (1 << state.distbits) - 1; - - - /* decode literals and length/distances until end-of-block or not enough - input data or output space */ - - top: - do { - if (bits < 15) { - hold += input[_in++] << bits; - bits += 8; - hold += input[_in++] << bits; - bits += 8; - } - - here = lcode[hold & lmask]; - - dolen: - for (;;) { // Goto emulation - op = here >>> 24/*here.bits*/; - hold >>>= op; - bits -= op; - op = here >>> 16 & 0xff/*here.op*/; - if (op === 0) { /* literal */ - //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - // "inflate: literal '%c'\n" : - // "inflate: literal 0x%02x\n", here.val)); - output[_out++] = here & 0xffff/*here.val*/; - } else if (op & 16) { /* length base */ - len = here & 0xffff/*here.val*/; - op &= 15; /* number of extra bits */ - if (op) { - if (bits < op) { - hold += input[_in++] << bits; - bits += 8; - } - len += hold & (1 << op) - 1; - hold >>>= op; - bits -= op; - } - //Tracevv((stderr, "inflate: length %u\n", len)); - if (bits < 15) { - hold += input[_in++] << bits; - bits += 8; - hold += input[_in++] << bits; - bits += 8; - } - here = dcode[hold & dmask]; - - dodist: - for (;;) { // goto emulation - op = here >>> 24/*here.bits*/; - hold >>>= op; - bits -= op; - op = here >>> 16 & 0xff/*here.op*/; - - if (op & 16) { /* distance base */ - dist = here & 0xffff/*here.val*/; - op &= 15; /* number of extra bits */ - if (bits < op) { - hold += input[_in++] << bits; - bits += 8; - if (bits < op) { - hold += input[_in++] << bits; - bits += 8; - } - } - dist += hold & (1 << op) - 1; - //#ifdef INFLATE_STRICT - if (dist > dmax) { - strm.msg = "invalid distance too far back"; - state.mode = BAD; - break top; - } - //#endif - hold >>>= op; - bits -= op; - //Tracevv((stderr, "inflate: distance %u\n", dist)); - op = _out - beg; /* max distance in output */ - if (dist > op) { /* see if copy from window */ - op = dist - op; /* distance back in window */ - if (op > whave) { - if (state.sane) { - strm.msg = "invalid distance too far back"; - state.mode = BAD; - break top; - } - - // (!) This block is disabled in zlib defaults, - // don't enable it for binary compatibility - //#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR - // if (len <= op - whave) { - // do { - // output[_out++] = 0; - // } while (--len); - // continue top; - // } - // len -= op - whave; - // do { - // output[_out++] = 0; - // } while (--op > whave); - // if (op === 0) { - // from = _out - dist; - // do { - // output[_out++] = output[from++]; - // } while (--len); - // continue top; - // } - //#endif - } - from = 0; // window index - from_source = s_window; - if (wnext === 0) { /* very common case */ - from += wsize - op; - if (op < len) { /* some from window */ - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = _out - dist; /* rest from output */ - from_source = output; - } - } else if (wnext < op) { /* wrap around window */ - from += wsize + wnext - op; - op -= wnext; - if (op < len) { /* some from end of window */ - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = 0; - if (wnext < len) { /* some from start of window */ - op = wnext; - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = _out - dist; /* rest from output */ - from_source = output; - } - } - } else { /* contiguous in window */ - from += wnext - op; - if (op < len) { /* some from window */ - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = _out - dist; /* rest from output */ - from_source = output; - } - } - while (len > 2) { - output[_out++] = from_source[from++]; - output[_out++] = from_source[from++]; - output[_out++] = from_source[from++]; - len -= 3; - } - if (len) { - output[_out++] = from_source[from++]; - if (len > 1) { - output[_out++] = from_source[from++]; - } - } - } else { - from = _out - dist; /* copy direct from output */ - do { /* minimum length is three */ - output[_out++] = output[from++]; - output[_out++] = output[from++]; - output[_out++] = output[from++]; - len -= 3; - } while (len > 2); - if (len) { - output[_out++] = output[from++]; - if (len > 1) { - output[_out++] = output[from++]; - } - } - } - } else if ((op & 64) === 0) { /* 2nd level distance code */ - here = dcode[(here & 0xffff)/*here.val*/ + (hold & (1 << op) - 1)]; - continue dodist; - } else { - strm.msg = "invalid distance code"; - state.mode = BAD; - break top; - } - - break; // need to emulate goto via "continue" - } - } else if ((op & 64) === 0) { /* 2nd level length code */ - here = lcode[(here & 0xffff)/*here.val*/ + (hold & (1 << op) - 1)]; - continue dolen; - } else if (op & 32) { /* end-of-block */ - //Tracevv((stderr, "inflate: end of block\n")); - state.mode = TYPE; - break top; - } else { - strm.msg = "invalid literal/length code"; - state.mode = BAD; - break top; - } - - break; // need to emulate goto via "continue" - } - } while (_in < last && _out < end); - - /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ - len = bits >> 3; - _in -= len; - bits -= len << 3; - hold &= (1 << bits) - 1; - - /* update state and return */ - strm.next_in = _in; - strm.next_out = _out; - strm.avail_in = _in < last ? 5 + (last - _in) : 5 - (_in - last); - strm.avail_out = _out < end ? 257 + (end - _out) : 257 - (_out - end); - state.hold = hold; - state.bits = bits; - return; - } - - const MAXBITS = 15; - const ENOUGH_LENS = 852; - const ENOUGH_DISTS = 592; - //var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); - - const CODES = 0; - const LENS = 1; - const DISTS = 2; - - const lbase = [ /* Length codes 257..285 base */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 - ]; - - const lext = [ /* Length codes 257..285 extra */ - 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78 - ]; - - const dbase = [ /* Distance codes 0..29 base */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577, 0, 0 - ]; - - const dext = [ /* Distance codes 0..29 extra */ - 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, - 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, - 28, 28, 29, 29, 64, 64 - ]; - - function inflate_table(type, lens, lens_index, codes, table, table_index, work, opts) { - const bits = opts.bits; - //here = opts.here; /* table entry for duplication */ - - let len = 0; /* a code's length in bits */ - let sym = 0; /* index of code symbols */ - let min = 0, max = 0; /* minimum and maximum code lengths */ - let root = 0; /* number of index bits for root table */ - let curr = 0; /* number of index bits for current table */ - let drop = 0; /* code bits to drop for sub-table */ - let left = 0; /* number of prefix codes available */ - let used = 0; /* code entries in table used */ - let huff = 0; /* Huffman code */ - let incr; /* for incrementing code, index */ - let fill; /* index for replicating entries */ - let low; /* low bits for current root entry */ - let next; /* next available space in table */ - let base = null; /* base value table to use */ - let base_index = 0; - // var shoextra; /* extra bits table to use */ - let end; /* use base and extra for symbol > end */ - const count = new Buf16(MAXBITS + 1); //[MAXBITS+1]; /* number of codes of each length */ - const offs = new Buf16(MAXBITS + 1); //[MAXBITS+1]; /* offsets in table for each length */ - let extra = null; - let extra_index = 0; - - let here_bits, here_op, here_val; - - /* - Process a set of code lengths to create a canonical Huffman code. The - code lengths are lens[0..codes-1]. Each length corresponds to the - symbols 0..codes-1. The Huffman code is generated by first sorting the - symbols by length from short to long, and retaining the symbol order - for codes with equal lengths. Then the code starts with all zero bits - for the first code of the shortest length, and the codes are integer - increments for the same length, and zeros are appended as the length - increases. For the deflate format, these bits are stored backwards - from their more natural integer increment ordering, and so when the - decoding tables are built in the large loop below, the integer codes - are incremented backwards. - - This routine assumes, but does not check, that all of the entries in - lens[] are in the range 0..MAXBITS. The caller must assure this. - 1..MAXBITS is interpreted as that code length. zero means that that - symbol does not occur in this code. - - The codes are sorted by computing a count of codes for each length, - creating from that a table of starting indices for each length in the - sorted table, and then entering the symbols in order in the sorted - table. The sorted table is work[], with that space being provided by - the caller. - - The length counts are used for other purposes as well, i.e. finding - the minimum and maximum length codes, determining if there are any - codes at all, checking for a valid set of lengths, and looking ahead - at length counts to determine sub-table sizes when building the - decoding tables. - */ - - /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ - for (len = 0; len <= MAXBITS; len++) { - count[len] = 0; - } - for (sym = 0; sym < codes; sym++) { - count[lens[lens_index + sym]]++; - } - - /* bound code lengths, force root to be within code lengths */ - root = bits; - for (max = MAXBITS; max >= 1; max--) { - if (count[max] !== 0) { - break; - } - } - if (root > max) { - root = max; - } - if (max === 0) { /* no symbols to code at all */ - //table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */ - //table.bits[opts.table_index] = 1; //here.bits = (var char)1; - //table.val[opts.table_index++] = 0; //here.val = (var short)0; - table[table_index++] = 1 << 24 | 64 << 16 | 0; - - - //table.op[opts.table_index] = 64; - //table.bits[opts.table_index] = 1; - //table.val[opts.table_index++] = 0; - table[table_index++] = 1 << 24 | 64 << 16 | 0; - - opts.bits = 1; - return 0; /* no symbols, but wait for decoding to report error */ - } - for (min = 1; min < max; min++) { - if (count[min] !== 0) { - break; - } - } - if (root < min) { - root = min; - } - - /* check for an over-subscribed or incomplete set of lengths */ - left = 1; - for (len = 1; len <= MAXBITS; len++) { - left <<= 1; - left -= count[len]; - if (left < 0) { - return -1; - } /* over-subscribed */ - } - if (left > 0 && (type === CODES || max !== 1)) { - return -1; /* incomplete set */ - } - - /* generate offsets into symbol table for each length for sorting */ - offs[1] = 0; - for (len = 1; len < MAXBITS; len++) { - offs[len + 1] = offs[len] + count[len]; - } - - /* sort symbols by length, by symbol order within each length */ - for (sym = 0; sym < codes; sym++) { - if (lens[lens_index + sym] !== 0) { - work[offs[lens[lens_index + sym]]++] = sym; - } - } - - /* - Create and fill in decoding tables. In this loop, the table being - filled is at next and has curr index bits. The code being used is huff - with length len. That code is converted to an index by dropping drop - bits off of the bottom. For codes where len is less than drop + curr, - those top drop + curr - len bits are incremented through all values to - fill the table with replicated entries. - - root is the number of index bits for the root table. When len exceeds - root, sub-tables are created pointed to by the root entry with an index - of the low root bits of huff. This is saved in low to check for when a - new sub-table should be started. drop is zero when the root table is - being filled, and drop is root when sub-tables are being filled. - - When a new sub-table is needed, it is necessary to look ahead in the - code lengths to determine what size sub-table is needed. The length - counts are used for this, and so count[] is decremented as codes are - entered in the tables. - - used keeps track of how many table entries have been allocated from the - provided *table space. It is checked for LENS and DIST tables against - the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in - the initial root table size constants. See the comments in inftrees.h - for more information. - - sym increments through all symbols, and the loop terminates when - all codes of length max, i.e. all codes, have been processed. This - routine permits incomplete codes, so another loop after this one fills - in the rest of the decoding tables with invalid code markers. - */ - - /* set up for code type */ - // poor man optimization - use if-else instead of switch, - // to avoid deopts in old v8 - if (type === CODES) { - base = extra = work; /* dummy value--not used */ - end = 19; - - } else if (type === LENS) { - base = lbase; - base_index -= 257; - extra = lext; - extra_index -= 257; - end = 256; - - } else { /* DISTS */ - base = dbase; - extra = dext; - end = -1; - } - - /* initialize opts for loop */ - huff = 0; /* starting code */ - sym = 0; /* starting code symbol */ - len = min; /* starting code length */ - next = table_index; /* current table to fill in */ - curr = root; /* current table index bits */ - drop = 0; /* current bits to drop from code for index */ - low = -1; /* trigger new sub-table when len > root */ - used = 1 << root; /* use root table entries */ - const mask = used - 1; /* mask for comparing low */ - - /* check available table space */ - if (type === LENS && used > ENOUGH_LENS || - type === DISTS && used > ENOUGH_DISTS) { - return 1; - } - - /* process all codes and make table entries */ - for (;;) { - /* create table entry */ - here_bits = len - drop; - if (work[sym] < end) { - here_op = 0; - here_val = work[sym]; - } else if (work[sym] > end) { - here_op = extra[extra_index + work[sym]]; - here_val = base[base_index + work[sym]]; - } else { - here_op = 32 + 64; /* end of block */ - here_val = 0; - } - - /* replicate for those indices with low len bits equal to huff */ - incr = 1 << len - drop; - fill = 1 << curr; - min = fill; /* save offset to next table */ - do { - fill -= incr; - table[next + (huff >> drop) + fill] = here_bits << 24 | here_op << 16 | here_val |0; - } while (fill !== 0); - - /* backwards increment the len-bit code huff */ - incr = 1 << len - 1; - while (huff & incr) { - incr >>= 1; - } - if (incr !== 0) { - huff &= incr - 1; - huff += incr; - } else { - huff = 0; - } - - /* go to next symbol, update count, len */ - sym++; - if (--count[len] === 0) { - if (len === max) { - break; - } - len = lens[lens_index + work[sym]]; - } - - /* create new sub-table if needed */ - if (len > root && (huff & mask) !== low) { - /* if first time, transition to sub-tables */ - if (drop === 0) { - drop = root; - } - - /* increment past last table */ - next += min; /* here min is 1 << curr */ - - /* determine length of next table */ - curr = len - drop; - left = 1 << curr; - while (curr + drop < max) { - left -= count[curr + drop]; - if (left <= 0) { - break; - } - curr++; - left <<= 1; - } - - /* check for enough space */ - used += 1 << curr; - if (type === LENS && used > ENOUGH_LENS || - type === DISTS && used > ENOUGH_DISTS) { - return 1; - } - - /* point entry in root table to sub-table */ - low = huff & mask; - /*table.op[low] = curr; - table.bits[low] = root; - table.val[low] = next - opts.table_index;*/ - table[low] = root << 24 | curr << 16 | next - table_index |0; - } - } - - /* fill in remaining table entry if code is incomplete (guaranteed to have - at most one remaining entry, since if the code is incomplete, the - maximum code length that was allowed to get this far is one bit) */ - if (huff !== 0) { - //table.op[next + huff] = 64; /* invalid code marker */ - //table.bits[next + huff] = len - drop; - //table.val[next + huff] = 0; - table[next + huff] = len - drop << 24 | 64 << 16 |0; - } - - /* set return parameters */ - //opts.table_index += used; - opts.bits = root; - return 0; - } - - const CODES$1 = 0; - const LENS$1 = 1; - const DISTS$1 = 2; - - /* STATES ====================================================================*/ - /* ===========================================================================*/ - - - const HEAD = 1; /* i: waiting for magic header */ - const FLAGS = 2; /* i: waiting for method and flags (gzip) */ - const TIME = 3; /* i: waiting for modification time (gzip) */ - const OS = 4; /* i: waiting for extra flags and operating system (gzip) */ - const EXLEN = 5; /* i: waiting for extra length (gzip) */ - const EXTRA = 6; /* i: waiting for extra bytes (gzip) */ - const NAME = 7; /* i: waiting for end of file name (gzip) */ - const COMMENT = 8; /* i: waiting for end of comment (gzip) */ - const HCRC = 9; /* i: waiting for header crc (gzip) */ - const DICTID = 10; /* i: waiting for dictionary check value */ - const DICT = 11; /* waiting for inflateSetDictionary() call */ - const TYPE$1 = 12; /* i: waiting for type bits, including last-flag bit */ - const TYPEDO = 13; /* i: same, but skip check to exit inflate on new block */ - const STORED = 14; /* i: waiting for stored size (length and complement) */ - const COPY_ = 15; /* i/o: same as COPY below, but only first time in */ - const COPY = 16; /* i/o: waiting for input or output to copy stored block */ - const TABLE = 17; /* i: waiting for dynamic block table lengths */ - const LENLENS = 18; /* i: waiting for code length code lengths */ - const CODELENS = 19; /* i: waiting for length/lit and distance code lengths */ - const LEN_ = 20; /* i: same as LEN below, but only first time in */ - const LEN = 21; /* i: waiting for length/lit/eob code */ - const LENEXT = 22; /* i: waiting for length extra bits */ - const DIST = 23; /* i: waiting for distance code */ - const DISTEXT = 24; /* i: waiting for distance extra bits */ - const MATCH = 25; /* o: waiting for output space to copy string */ - const LIT = 26; /* o: waiting for output space to write literal */ - const CHECK = 27; /* i: waiting for 32-bit check value */ - const LENGTH = 28; /* i: waiting for 32-bit length (gzip) */ - const DONE = 29; /* finished check, done -- remain here until reset */ - const BAD$1 = 30; /* got a data error -- remain here until reset */ - //const MEM = 31; /* got an inflate() memory error -- remain here until reset */ - const SYNC = 32; /* looking for synchronization bytes to restart inflate() */ - - /* ===========================================================================*/ - - - - const ENOUGH_LENS$1 = 852; - const ENOUGH_DISTS$1 = 592; - - - function zswap32(q) { - return (((q >>> 24) & 0xff) + - ((q >>> 8) & 0xff00) + - ((q & 0xff00) << 8) + - ((q & 0xff) << 24)); - } - - - class InflateState { - constructor() { - this.mode = 0; /* current inflate mode */ - this.last = false; /* true if processing last block */ - this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ - this.havedict = false; /* true if dictionary provided */ - this.flags = 0; /* gzip header method and flags (0 if zlib) */ - this.dmax = 0; /* zlib header max distance (INFLATE_STRICT) */ - this.check = 0; /* protected copy of check value */ - this.total = 0; /* protected copy of output count */ - // TODO: may be {} - this.head = null; /* where to save gzip header information */ - - /* sliding window */ - this.wbits = 0; /* log base 2 of requested window size */ - this.wsize = 0; /* window size or zero if not using window */ - this.whave = 0; /* valid bytes in the window */ - this.wnext = 0; /* window write index */ - this.window = null; /* allocated sliding window, if needed */ - - /* bit accumulator */ - this.hold = 0; /* input bit accumulator */ - this.bits = 0; /* number of bits in "in" */ - - /* for string and stored block copying */ - this.length = 0; /* literal or length of data to copy */ - this.offset = 0; /* distance back to copy string from */ - - /* for table and code decoding */ - this.extra = 0; /* extra bits needed */ - - /* fixed and dynamic code tables */ - this.lencode = null; /* starting table for length/literal codes */ - this.distcode = null; /* starting table for distance codes */ - this.lenbits = 0; /* index bits for lencode */ - this.distbits = 0; /* index bits for distcode */ - - /* dynamic table building */ - this.ncode = 0; /* number of code length code lengths */ - this.nlen = 0; /* number of length code lengths */ - this.ndist = 0; /* number of distance code lengths */ - this.have = 0; /* number of code lengths in lens[] */ - this.next = null; /* next available space in codes[] */ - - this.lens = new Buf16(320); /* temporary storage for code lengths */ - this.work = new Buf16(288); /* work area for code table building */ - - /* - because we don't have pointers in js, we use lencode and distcode directly - as buffers so we don't need codes - */ - //this.codes = new utils.Buf32(ENOUGH); /* space for code tables */ - this.lendyn = null; /* dynamic table for length/literal codes (JS specific) */ - this.distdyn = null; /* dynamic table for distance codes (JS specific) */ - this.sane = 0; /* if false, allow invalid distance too far */ - this.back = 0; /* bits back of last unprocessed length/lit */ - this.was = 0; /* initial length of match */ - } - } - - function inflateResetKeep(strm) { - let state; - - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - strm.total_in = strm.total_out = state.total = 0; - strm.msg = ''; /*Z_NULL*/ - if (state.wrap) { /* to support ill-conceived Java test suite */ - strm.adler = state.wrap & 1; - } - state.mode = HEAD; - state.last = 0; - state.havedict = 0; - state.dmax = 32768; - state.head = null/*Z_NULL*/; - state.hold = 0; - state.bits = 0; - //state.lencode = state.distcode = state.next = state.codes; - state.lencode = state.lendyn = new Buf32(ENOUGH_LENS$1); - state.distcode = state.distdyn = new Buf32(ENOUGH_DISTS$1); - - state.sane = 1; - state.back = -1; - //Tracev((stderr, "inflate: reset\n")); - return Z_OK; - } - - function inflateReset(strm) { - let state; - - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - state.wsize = 0; - state.whave = 0; - state.wnext = 0; - return inflateResetKeep(strm); - - } - - function inflateReset2(strm, windowBits) { - let wrap; - let state; - - /* get the state */ - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - - /* extract wrap request from windowBits parameter */ - if (windowBits < 0) { - wrap = 0; - windowBits = -windowBits; - } - else { - wrap = (windowBits >> 4) + 1; - if (windowBits < 48) { - windowBits &= 15; - } - } - - /* set number of window bits, free window if different */ - if (windowBits && (windowBits < 8 || windowBits > 15)) { - return Z_STREAM_ERROR; - } - if (state.window !== null && state.wbits !== windowBits) { - state.window = null; - } - - /* update state and reset the rest of it */ - state.wrap = wrap; - state.wbits = windowBits; - return inflateReset(strm); - } - - function inflateInit2(strm, windowBits) { - let ret; - let state; - - if (!strm) { return Z_STREAM_ERROR; } - //strm.msg = Z_NULL; /* in case we return an error */ - - state = new InflateState(); - - //if (state === Z_NULL) return Z_MEM_ERROR; - //Tracev((stderr, "inflate: allocated\n")); - strm.state = state; - state.window = null/*Z_NULL*/; - ret = inflateReset2(strm, windowBits); - if (ret !== Z_OK) { - strm.state = null/*Z_NULL*/; - } - return ret; - } - - - /* - Return state with length and distance decoding tables and index sizes set to - fixed code decoding. Normally this returns fixed tables from inffixed.h. - If BUILDFIXED is defined, then instead this routine builds the tables the - first time it's called, and returns those tables the first time and - thereafter. This reduces the size of the code by about 2K bytes, in - exchange for a little execution time. However, BUILDFIXED should not be - used for threaded applications, since the rewriting of the tables and virgin - may not be thread-safe. - */ - let virgin = true; - - let lenfix, distfix; // We have no pointers in JS, so keep tables separate - - function fixedtables(state) { - /* build fixed huffman tables if first call (may not be thread safe) */ - if (virgin) { - let sym; - - lenfix = new Buf32(512); - distfix = new Buf32(32); - - /* literal/length table */ - sym = 0; - while (sym < 144) { state.lens[sym++] = 8; } - while (sym < 256) { state.lens[sym++] = 9; } - while (sym < 280) { state.lens[sym++] = 7; } - while (sym < 288) { state.lens[sym++] = 8; } - - inflate_table(LENS$1, state.lens, 0, 288, lenfix, 0, state.work, { bits: 9 }); - - /* distance table */ - sym = 0; - while (sym < 32) { state.lens[sym++] = 5; } - - inflate_table(DISTS$1, state.lens, 0, 32, distfix, 0, state.work, { bits: 5 }); - - /* do this just once */ - virgin = false; - } - - state.lencode = lenfix; - state.lenbits = 9; - state.distcode = distfix; - state.distbits = 5; - } - - - /* - Update the window with the last wsize (normally 32K) bytes written before - returning. If window does not exist yet, create it. This is only called - when a window is already in use, or when output has been written during this - inflate call, but the end of the deflate stream has not been reached yet. - It is also called to create a window for dictionary data when a dictionary - is loaded. - - Providing output buffers larger than 32K to inflate() should provide a speed - advantage, since only the last 32K of output is copied to the sliding window - upon return from inflate(), and since all distances after the first 32K of - output will fall in the output data, making match copies simpler and faster. - The advantage may be dependent on the size of the processor's data caches. - */ - function updatewindow(strm, src, end, copy) { - let dist; - const state = strm.state; - - /* if it hasn't been done already, allocate space for the window */ - if (state.window === null) { - state.wsize = 1 << state.wbits; - state.wnext = 0; - state.whave = 0; - - state.window = new Buf8(state.wsize); - } - - /* copy state->wsize or less output bytes into the circular window */ - if (copy >= state.wsize) { - arraySet(state.window, src, end - state.wsize, state.wsize, 0); - state.wnext = 0; - state.whave = state.wsize; - } - else { - dist = state.wsize - state.wnext; - if (dist > copy) { - dist = copy; - } - //zmemcpy(state->window + state->wnext, end - copy, dist); - arraySet(state.window, src, end - copy, dist, state.wnext); - copy -= dist; - if (copy) { - //zmemcpy(state->window, end - copy, copy); - arraySet(state.window, src, end - copy, copy, 0); - state.wnext = copy; - state.whave = state.wsize; - } - else { - state.wnext += dist; - if (state.wnext === state.wsize) { state.wnext = 0; } - if (state.whave < state.wsize) { state.whave += dist; } - } - } - return 0; - } - - function inflate(strm, flush) { - let state; - let input, output; // input/output buffers - let next; /* next input INDEX */ - let put; /* next output INDEX */ - let have, left; /* available input and output */ - let hold; /* bit buffer */ - let bits; /* bits in bit buffer */ - let _in, _out; /* save starting available input and output */ - let copy; /* number of stored or match bytes to copy */ - let from; /* where to copy match bytes from */ - let from_source; - let here = 0; /* current decoding table entry */ - let here_bits, here_op, here_val; // paked "here" denormalized (JS specific) - //var last; /* parent table entry */ - let last_bits, last_op, last_val; // paked "last" denormalized (JS specific) - let len; /* length to copy for repeats, bits to drop */ - let ret; /* return code */ - let hbuf = new Buf8(4); /* buffer for gzip header crc calculation */ - let opts; - - let n; // temporary var for NEED_BITS - - const order = /* permutation of code lengths */ - [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ]; - - - if (!strm || !strm.state || !strm.output || - (!strm.input && strm.avail_in !== 0)) { - return Z_STREAM_ERROR; - } - - state = strm.state; - if (state.mode === TYPE$1) { state.mode = TYPEDO; } /* skip check */ - - - //--- LOAD() --- - put = strm.next_out; - output = strm.output; - left = strm.avail_out; - next = strm.next_in; - input = strm.input; - have = strm.avail_in; - hold = state.hold; - bits = state.bits; - //--- - - _in = have; - _out = left; - ret = Z_OK; - - inf_leave: // goto emulation - for (;;) { - switch (state.mode) { - case HEAD: - if (state.wrap === 0) { - state.mode = TYPEDO; - break; - } - //=== NEEDBITS(16); - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if ((state.wrap & 2) && hold === 0x8b1f) { /* gzip header */ - state.check = 0/*crc32(0L, Z_NULL, 0)*/; - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = FLAGS; - break; - } - state.flags = 0; /* expect zlib header */ - if (state.head) { - state.head.done = false; - } - if (!(state.wrap & 1) || /* check if zlib header allowed */ - (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) { - strm.msg = 'incorrect header check'; - state.mode = BAD$1; - break; - } - if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) { - strm.msg = 'unknown compression method'; - state.mode = BAD$1; - break; - } - //--- DROPBITS(4) ---// - hold >>>= 4; - bits -= 4; - //---// - len = (hold & 0x0f)/*BITS(4)*/ + 8; - if (state.wbits === 0) { - state.wbits = len; - } - else if (len > state.wbits) { - strm.msg = 'invalid window size'; - state.mode = BAD$1; - break; - } - state.dmax = 1 << len; - //Tracev((stderr, "inflate: zlib header ok\n")); - strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; - state.mode = hold & 0x200 ? DICTID : TYPE$1; - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - break; - case FLAGS: - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.flags = hold; - if ((state.flags & 0xff) !== Z_DEFLATED) { - strm.msg = 'unknown compression method'; - state.mode = BAD$1; - break; - } - if (state.flags & 0xe000) { - strm.msg = 'unknown header flags set'; - state.mode = BAD$1; - break; - } - if (state.head) { - state.head.text = ((hold >> 8) & 1); - } - if (state.flags & 0x0200) { - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = TIME; - /* falls through */ - case TIME: - //=== NEEDBITS(32); */ - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (state.head) { - state.head.time = hold; - } - if (state.flags & 0x0200) { - //=== CRC4(state.check, hold) - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - hbuf[2] = (hold >>> 16) & 0xff; - hbuf[3] = (hold >>> 24) & 0xff; - state.check = crc32(state.check, hbuf, 4, 0); - //=== - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = OS; - /* falls through */ - case OS: - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (state.head) { - state.head.xflags = (hold & 0xff); - state.head.os = (hold >> 8); - } - if (state.flags & 0x0200) { - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = EXLEN; - /* falls through */ - case EXLEN: - if (state.flags & 0x0400) { - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.length = hold; - if (state.head) { - state.head.extra_len = hold; - } - if (state.flags & 0x0200) { - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - } - else if (state.head) { - state.head.extra = null/*Z_NULL*/; - } - state.mode = EXTRA; - /* falls through */ - case EXTRA: - if (state.flags & 0x0400) { - copy = state.length; - if (copy > have) { copy = have; } - if (copy) { - if (state.head) { - len = state.head.extra_len - state.length; - if (!state.head.extra) { - // Use untyped array for more convenient processing later - state.head.extra = new Array(state.head.extra_len); - } - arraySet( - state.head.extra, - input, - next, - // extra field is limited to 65536 bytes - // - no need for additional size check - copy, - /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/ - len - ); - //zmemcpy(state.head.extra + len, next, - // len + copy > state.head.extra_max ? - // state.head.extra_max - len : copy); - } - if (state.flags & 0x0200) { - state.check = crc32(state.check, input, copy, next); - } - have -= copy; - next += copy; - state.length -= copy; - } - if (state.length) { break inf_leave; } - } - state.length = 0; - state.mode = NAME; - /* falls through */ - case NAME: - if (state.flags & 0x0800) { - if (have === 0) { break inf_leave; } - copy = 0; - do { - // TODO: 2 or 1 bytes? - len = input[next + copy++]; - /* use constant limit because in js we should not preallocate memory */ - if (state.head && len && - (state.length < 65536 /*state.head.name_max*/)) { - state.head.name += String.fromCharCode(len); - } - } while (len && copy < have); - - if (state.flags & 0x0200) { - state.check = crc32(state.check, input, copy, next); - } - have -= copy; - next += copy; - if (len) { break inf_leave; } - } - else if (state.head) { - state.head.name = null; - } - state.length = 0; - state.mode = COMMENT; - /* falls through */ - case COMMENT: - if (state.flags & 0x1000) { - if (have === 0) { break inf_leave; } - copy = 0; - do { - len = input[next + copy++]; - /* use constant limit because in js we should not preallocate memory */ - if (state.head && len && - (state.length < 65536 /*state.head.comm_max*/)) { - state.head.comment += String.fromCharCode(len); - } - } while (len && copy < have); - if (state.flags & 0x0200) { - state.check = crc32(state.check, input, copy, next); - } - have -= copy; - next += copy; - if (len) { break inf_leave; } - } - else if (state.head) { - state.head.comment = null; - } - state.mode = HCRC; - /* falls through */ - case HCRC: - if (state.flags & 0x0200) { - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (hold !== (state.check & 0xffff)) { - strm.msg = 'header crc mismatch'; - state.mode = BAD$1; - break; - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - } - if (state.head) { - state.head.hcrc = ((state.flags >> 9) & 1); - state.head.done = true; - } - strm.adler = state.check = 0; - state.mode = TYPE$1; - break; - case DICTID: - //=== NEEDBITS(32); */ - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - strm.adler = state.check = zswap32(hold); - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = DICT; - /* falls through */ - case DICT: - if (state.havedict === 0) { - //--- RESTORE() --- - strm.next_out = put; - strm.avail_out = left; - strm.next_in = next; - strm.avail_in = have; - state.hold = hold; - state.bits = bits; - //--- - return Z_NEED_DICT; - } - strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; - state.mode = TYPE$1; - /* falls through */ - case TYPE$1: - if (flush === Z_BLOCK || flush === Z_TREES) { break inf_leave; } - /* falls through */ - case TYPEDO: - if (state.last) { - //--- BYTEBITS() ---// - hold >>>= bits & 7; - bits -= bits & 7; - //---// - state.mode = CHECK; - break; - } - //=== NEEDBITS(3); */ - while (bits < 3) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.last = (hold & 0x01)/*BITS(1)*/; - //--- DROPBITS(1) ---// - hold >>>= 1; - bits -= 1; - //---// - - switch ((hold & 0x03)/*BITS(2)*/) { - case 0: /* stored block */ - //Tracev((stderr, "inflate: stored block%s\n", - // state.last ? " (last)" : "")); - state.mode = STORED; - break; - case 1: /* fixed block */ - fixedtables(state); - //Tracev((stderr, "inflate: fixed codes block%s\n", - // state.last ? " (last)" : "")); - state.mode = LEN_; /* decode codes */ - if (flush === Z_TREES) { - //--- DROPBITS(2) ---// - hold >>>= 2; - bits -= 2; - //---// - break inf_leave; - } - break; - case 2: /* dynamic block */ - //Tracev((stderr, "inflate: dynamic codes block%s\n", - // state.last ? " (last)" : "")); - state.mode = TABLE; - break; - case 3: - strm.msg = 'invalid block type'; - state.mode = BAD$1; - } - //--- DROPBITS(2) ---// - hold >>>= 2; - bits -= 2; - //---// - break; - case STORED: - //--- BYTEBITS() ---// /* go to byte boundary */ - hold >>>= bits & 7; - bits -= bits & 7; - //---// - //=== NEEDBITS(32); */ - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) { - strm.msg = 'invalid stored block lengths'; - state.mode = BAD$1; - break; - } - state.length = hold & 0xffff; - //Tracev((stderr, "inflate: stored length %u\n", - // state.length)); - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = COPY_; - if (flush === Z_TREES) { break inf_leave; } - /* falls through */ - case COPY_: - state.mode = COPY; - /* falls through */ - case COPY: - copy = state.length; - if (copy) { - if (copy > have) { copy = have; } - if (copy > left) { copy = left; } - if (copy === 0) { break inf_leave; } - //--- zmemcpy(put, next, copy); --- - arraySet(output, input, next, copy, put); - //---// - have -= copy; - next += copy; - left -= copy; - put += copy; - state.length -= copy; - break; - } - //Tracev((stderr, "inflate: stored end\n")); - state.mode = TYPE$1; - break; - case TABLE: - //=== NEEDBITS(14); */ - while (bits < 14) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257; - //--- DROPBITS(5) ---// - hold >>>= 5; - bits -= 5; - //---// - state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1; - //--- DROPBITS(5) ---// - hold >>>= 5; - bits -= 5; - //---// - state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4; - //--- DROPBITS(4) ---// - hold >>>= 4; - bits -= 4; - //---// - //#ifndef PKZIP_BUG_WORKAROUND - if (state.nlen > 286 || state.ndist > 30) { - strm.msg = 'too many length or distance symbols'; - state.mode = BAD$1; - break; - } - //#endif - //Tracev((stderr, "inflate: table sizes ok\n")); - state.have = 0; - state.mode = LENLENS; - /* falls through */ - case LENLENS: - while (state.have < state.ncode) { - //=== NEEDBITS(3); - while (bits < 3) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.lens[order[state.have++]] = (hold & 0x07);//BITS(3); - //--- DROPBITS(3) ---// - hold >>>= 3; - bits -= 3; - //---// - } - while (state.have < 19) { - state.lens[order[state.have++]] = 0; - } - // We have separate tables & no pointers. 2 commented lines below not needed. - //state.next = state.codes; - //state.lencode = state.next; - // Switch to use dynamic table - state.lencode = state.lendyn; - state.lenbits = 7; - - opts = { bits: state.lenbits }; - ret = inflate_table(CODES$1, state.lens, 0, 19, state.lencode, 0, state.work, opts); - state.lenbits = opts.bits; - - if (ret) { - strm.msg = 'invalid code lengths set'; - state.mode = BAD$1; - break; - } - //Tracev((stderr, "inflate: code lengths ok\n")); - state.have = 0; - state.mode = CODELENS; - /* falls through */ - case CODELENS: - while (state.have < state.nlen + state.ndist) { - for (;;) { - here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/ - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - if (here_val < 16) { - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - state.lens[state.have++] = here_val; - } - else { - if (here_val === 16) { - //=== NEEDBITS(here.bits + 2); - n = here_bits + 2; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - if (state.have === 0) { - strm.msg = 'invalid bit length repeat'; - state.mode = BAD$1; - break; - } - len = state.lens[state.have - 1]; - copy = 3 + (hold & 0x03);//BITS(2); - //--- DROPBITS(2) ---// - hold >>>= 2; - bits -= 2; - //---// - } - else if (here_val === 17) { - //=== NEEDBITS(here.bits + 3); - n = here_bits + 3; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - len = 0; - copy = 3 + (hold & 0x07);//BITS(3); - //--- DROPBITS(3) ---// - hold >>>= 3; - bits -= 3; - //---// - } - else { - //=== NEEDBITS(here.bits + 7); - n = here_bits + 7; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - len = 0; - copy = 11 + (hold & 0x7f);//BITS(7); - //--- DROPBITS(7) ---// - hold >>>= 7; - bits -= 7; - //---// - } - if (state.have + copy > state.nlen + state.ndist) { - strm.msg = 'invalid bit length repeat'; - state.mode = BAD$1; - break; - } - while (copy--) { - state.lens[state.have++] = len; - } - } - } - - /* handle error breaks in while */ - if (state.mode === BAD$1) { break; } - - /* check for end-of-block code (better have one) */ - if (state.lens[256] === 0) { - strm.msg = 'invalid code -- missing end-of-block'; - state.mode = BAD$1; - break; - } - - /* build code tables -- note: do not change the lenbits or distbits - values here (9 and 6) without reading the comments in inftrees.h - concerning the ENOUGH constants, which depend on those values */ - state.lenbits = 9; - - opts = { bits: state.lenbits }; - ret = inflate_table(LENS$1, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts); - // We have separate tables & no pointers. 2 commented lines below not needed. - // state.next_index = opts.table_index; - state.lenbits = opts.bits; - // state.lencode = state.next; - - if (ret) { - strm.msg = 'invalid literal/lengths set'; - state.mode = BAD$1; - break; - } - - state.distbits = 6; - //state.distcode.copy(state.codes); - // Switch to use dynamic table - state.distcode = state.distdyn; - opts = { bits: state.distbits }; - ret = inflate_table(DISTS$1, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts); - // We have separate tables & no pointers. 2 commented lines below not needed. - // state.next_index = opts.table_index; - state.distbits = opts.bits; - // state.distcode = state.next; - - if (ret) { - strm.msg = 'invalid distances set'; - state.mode = BAD$1; - break; - } - //Tracev((stderr, 'inflate: codes ok\n')); - state.mode = LEN_; - if (flush === Z_TREES) { break inf_leave; } - /* falls through */ - case LEN_: - state.mode = LEN; - /* falls through */ - case LEN: - if (have >= 6 && left >= 258) { - //--- RESTORE() --- - strm.next_out = put; - strm.avail_out = left; - strm.next_in = next; - strm.avail_in = have; - state.hold = hold; - state.bits = bits; - //--- - inflate_fast(strm, _out); - //--- LOAD() --- - put = strm.next_out; - output = strm.output; - left = strm.avail_out; - next = strm.next_in; - input = strm.input; - have = strm.avail_in; - hold = state.hold; - bits = state.bits; - //--- - - if (state.mode === TYPE$1) { - state.back = -1; - } - break; - } - state.back = 0; - for (;;) { - here = state.lencode[hold & ((1 << state.lenbits) - 1)]; /*BITS(state.lenbits)*/ - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if (here_bits <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - if (here_op && (here_op & 0xf0) === 0) { - last_bits = here_bits; - last_op = here_op; - last_val = here_val; - for (;;) { - here = state.lencode[last_val + - ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((last_bits + here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - //--- DROPBITS(last.bits) ---// - hold >>>= last_bits; - bits -= last_bits; - //---// - state.back += last_bits; - } - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - state.back += here_bits; - state.length = here_val; - if (here_op === 0) { - //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - // "inflate: literal '%c'\n" : - // "inflate: literal 0x%02x\n", here.val)); - state.mode = LIT; - break; - } - if (here_op & 32) { - //Tracevv((stderr, "inflate: end of block\n")); - state.back = -1; - state.mode = TYPE$1; - break; - } - if (here_op & 64) { - strm.msg = 'invalid literal/length code'; - state.mode = BAD$1; - break; - } - state.extra = here_op & 15; - state.mode = LENEXT; - /* falls through */ - case LENEXT: - if (state.extra) { - //=== NEEDBITS(state.extra); - n = state.extra; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.length += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; - //--- DROPBITS(state.extra) ---// - hold >>>= state.extra; - bits -= state.extra; - //---// - state.back += state.extra; - } - //Tracevv((stderr, "inflate: length %u\n", state.length)); - state.was = state.length; - state.mode = DIST; - /* falls through */ - case DIST: - for (;;) { - here = state.distcode[hold & ((1 << state.distbits) - 1)];/*BITS(state.distbits)*/ - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - if ((here_op & 0xf0) === 0) { - last_bits = here_bits; - last_op = here_op; - last_val = here_val; - for (;;) { - here = state.distcode[last_val + - ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((last_bits + here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - //--- DROPBITS(last.bits) ---// - hold >>>= last_bits; - bits -= last_bits; - //---// - state.back += last_bits; - } - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - state.back += here_bits; - if (here_op & 64) { - strm.msg = 'invalid distance code'; - state.mode = BAD$1; - break; - } - state.offset = here_val; - state.extra = (here_op) & 15; - state.mode = DISTEXT; - /* falls through */ - case DISTEXT: - if (state.extra) { - //=== NEEDBITS(state.extra); - n = state.extra; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.offset += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; - //--- DROPBITS(state.extra) ---// - hold >>>= state.extra; - bits -= state.extra; - //---// - state.back += state.extra; - } - //#ifdef INFLATE_STRICT - if (state.offset > state.dmax) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD$1; - break; - } - //#endif - //Tracevv((stderr, "inflate: distance %u\n", state.offset)); - state.mode = MATCH; - /* falls through */ - case MATCH: - if (left === 0) { break inf_leave; } - copy = _out - left; - if (state.offset > copy) { /* copy from window */ - copy = state.offset - copy; - if (copy > state.whave) { - if (state.sane) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD$1; - break; - } - // (!) This block is disabled in zlib defaults, - // don't enable it for binary compatibility - //#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR - // Trace((stderr, "inflate.c too far\n")); - // copy -= state.whave; - // if (copy > state.length) { copy = state.length; } - // if (copy > left) { copy = left; } - // left -= copy; - // state.length -= copy; - // do { - // output[put++] = 0; - // } while (--copy); - // if (state.length === 0) { state.mode = LEN; } - // break; - //#endif - } - if (copy > state.wnext) { - copy -= state.wnext; - from = state.wsize - copy; - } - else { - from = state.wnext - copy; - } - if (copy > state.length) { copy = state.length; } - from_source = state.window; - } - else { /* copy from output */ - from_source = output; - from = put - state.offset; - copy = state.length; - } - if (copy > left) { copy = left; } - left -= copy; - state.length -= copy; - do { - output[put++] = from_source[from++]; - } while (--copy); - if (state.length === 0) { state.mode = LEN; } - break; - case LIT: - if (left === 0) { break inf_leave; } - output[put++] = state.length; - left--; - state.mode = LEN; - break; - case CHECK: - if (state.wrap) { - //=== NEEDBITS(32); - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - // Use '|' instead of '+' to make sure that result is signed - hold |= input[next++] << bits; - bits += 8; - } - //===// - _out -= left; - strm.total_out += _out; - state.total += _out; - if (_out) { - strm.adler = state.check = - /*UPDATE(state.check, put - _out, _out);*/ - (state.flags ? crc32(state.check, output, _out, put - _out) : adler32(state.check, output, _out, put - _out)); - - } - _out = left; - // NB: crc32 stored as signed 32-bit int, zswap32 returns signed too - if ((state.flags ? hold : zswap32(hold)) !== state.check) { - strm.msg = 'incorrect data check'; - state.mode = BAD$1; - break; - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - //Tracev((stderr, "inflate: check matches trailer\n")); - } - state.mode = LENGTH; - /* falls through */ - case LENGTH: - if (state.wrap && state.flags) { - //=== NEEDBITS(32); - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (hold !== (state.total & 0xffffffff)) { - strm.msg = 'incorrect length check'; - state.mode = BAD$1; - break; - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - //Tracev((stderr, "inflate: length matches trailer\n")); - } - state.mode = DONE; - /* falls through */ - case DONE: - ret = Z_STREAM_END; - break inf_leave; - case BAD$1: - ret = Z_DATA_ERROR; - break inf_leave; - // case MEM: - // return Z_MEM_ERROR; - case SYNC: - /* falls through */ - default: - return Z_STREAM_ERROR; - } - } - - // inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave" - - /* - Return from inflate(), updating the total counts and the check value. - If there was no progress during the inflate() call, return a buffer - error. Call updatewindow() to create and/or update the window state. - Note: a memory error from inflate() is non-recoverable. - */ - - //--- RESTORE() --- - strm.next_out = put; - strm.avail_out = left; - strm.next_in = next; - strm.avail_in = have; - state.hold = hold; - state.bits = bits; - //--- - - if (state.wsize || (_out !== strm.avail_out && state.mode < BAD$1 && - (state.mode < CHECK || flush !== Z_FINISH))) { - if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) ; - } - _in -= strm.avail_in; - _out -= strm.avail_out; - strm.total_in += _in; - strm.total_out += _out; - state.total += _out; - if (state.wrap && _out) { - strm.adler = state.check = /*UPDATE(state.check, strm.next_out - _out, _out);*/ - (state.flags ? crc32(state.check, output, _out, strm.next_out - _out) : adler32(state.check, output, _out, strm.next_out - _out)); - } - strm.data_type = state.bits + (state.last ? 64 : 0) + - (state.mode === TYPE$1 ? 128 : 0) + - (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0); - if (((_in === 0 && _out === 0) || flush === Z_FINISH) && ret === Z_OK) { - ret = Z_BUF_ERROR; - } - return ret; - } - - function inflateEnd(strm) { - - if (!strm || !strm.state /*|| strm->zfree == (free_func)0*/) { - return Z_STREAM_ERROR; - } - - const state = strm.state; - if (state.window) { - state.window = null; - } - strm.state = null; - return Z_OK; - } - - function inflateGetHeader(strm, head) { - let state; - - /* check state */ - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR; } - - /* save header structure */ - state.head = head; - head.done = false; - return Z_OK; - } - - function inflateSetDictionary(strm, dictionary) { - const dictLength = dictionary.length; - - let state; - let dictid; - - /* check state */ - if (!strm /* == Z_NULL */ || !strm.state /* == Z_NULL */) { return Z_STREAM_ERROR; } - state = strm.state; - - if (state.wrap !== 0 && state.mode !== DICT) { - return Z_STREAM_ERROR; - } - - /* check for correct dictionary identifier */ - if (state.mode === DICT) { - dictid = 1; /* adler32(0, null, 0)*/ - /* dictid = adler32(dictid, dictionary, dictLength); */ - dictid = adler32(dictid, dictionary, dictLength, 0); - if (dictid !== state.check) { - return Z_DATA_ERROR; - } - } - /* copy dictionary to window using updatewindow(), which will amend the - existing dictionary if appropriate */ - updatewindow(strm, dictionary, dictLength, dictLength); - // if (ret) { - // state.mode = MEM; - // return Z_MEM_ERROR; - // } - state.havedict = 1; - // Tracev((stderr, "inflate: dictionary set\n")); - return Z_OK; - } - - /* Not implemented - exports.inflateCopy = inflateCopy; - exports.inflateGetDictionary = inflateGetDictionary; - exports.inflateMark = inflateMark; - exports.inflatePrime = inflatePrime; - exports.inflateSync = inflateSync; - exports.inflateSyncPoint = inflateSyncPoint; - exports.inflateUndermine = inflateUndermine; - */ - - // (C) 1995-2013 Jean-loup Gailly and Mark Adler - // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin - // - // This software is provided 'as-is', without any express or implied - // warranty. In no event will the authors be held liable for any damages - // arising from the use of this software. - // - // Permission is granted to anyone to use this software for any purpose, - // including commercial applications, and to alter it and redistribute it - // freely, subject to the following restrictions: - // - // 1. The origin of this software must not be misrepresented; you must not - // claim that you wrote the original software. If you use this software - // in a product, an acknowledgment in the product documentation would be - // appreciated but is not required. - // 2. Altered source versions must be plainly marked as such, and must not be - // misrepresented as being the original software. - // 3. This notice may not be removed or altered from any source distribution. - - class GZheader { - constructor() { - /* true if compressed data believed to be text */ - this.text = 0; - /* modification time */ - this.time = 0; - /* extra flags (not used when writing a gzip file) */ - this.xflags = 0; - /* operating system */ - this.os = 0; - /* pointer to extra field or Z_NULL if none */ - this.extra = null; - /* extra field length (valid if extra != Z_NULL) */ - this.extra_len = 0; // Actually, we don't need it in JS, - // but leave for few code modifications - - // - // Setup limits is not necessary because in js we should not preallocate memory - // for inflate use constant limit in 65536 bytes - // - - /* space at extra (only when reading header) */ - // this.extra_max = 0; - /* pointer to zero-terminated file name or Z_NULL */ - this.name = ''; - /* space at name (only when reading header) */ - // this.name_max = 0; - /* pointer to zero-terminated comment or Z_NULL */ - this.comment = ''; - /* space at comment (only when reading header) */ - // this.comm_max = 0; - /* true if there was or will be a header crc */ - this.hcrc = 0; - /* true when done reading gzip header (not used when writing a gzip file) */ - this.done = false; - } - } - - /** - * class Inflate - * - * Generic JS-style wrapper for zlib calls. If you don't need - * streaming behaviour - use more simple functions: [[inflate]] - * and [[inflateRaw]]. - **/ - - /* internal - * inflate.chunks -> Array - * - * Chunks of output data, if [[Inflate#onData]] not overridden. - **/ - - /** - * Inflate.result -> Uint8Array|Array|String - * - * Uncompressed result, generated by default [[Inflate#onData]] - * and [[Inflate#onEnd]] handlers. Filled after you push last chunk - * (call [[Inflate#push]] with `Z_FINISH` / `true` param) or if you - * push a chunk with explicit flush (call [[Inflate#push]] with - * `Z_SYNC_FLUSH` param). - **/ - - /** - * Inflate.err -> Number - * - * Error code after inflate finished. 0 (Z_OK) on success. - * Should be checked if broken data possible. - **/ - - /** - * Inflate.msg -> String - * - * Error message, if [[Inflate.err]] != 0 - **/ - - - /** - * new Inflate(options) - * - options (Object): zlib inflate options. - * - * Creates new inflator instance with specified params. Throws exception - * on bad params. Supported options: - * - * - `windowBits` - * - `dictionary` - * - * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) - * for more information on these. - * - * Additional options, for internal needs: - * - * - `chunkSize` - size of generated data chunks (16K by default) - * - `raw` (Boolean) - do raw inflate - * - `to` (String) - if equal to 'string', then result will be converted - * from utf8 to utf16 (javascript) string. When string output requested, - * chunk length can differ from `chunkSize`, depending on content. - * - * By default, when no options set, autodetect deflate/gzip data format via - * wrapper header. - * - * ##### Example: - * - * ```javascript - * var pako = void('pako') - * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9]) - * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]); - * - * var inflate = new pako.Inflate({ level: 3}); - * - * inflate.push(chunk1, false); - * inflate.push(chunk2, true); // true -> last chunk - * - * if (inflate.err) { throw new Error(inflate.err); } - * - * console.log(inflate.result); - * ``` - **/ - class Inflate { - constructor(options) { - this.options = { - chunkSize: 16384, - windowBits: 0, - ...(options || {}) - }; - - const opt = this.options; - - // Force window size for `raw` data, if not set directly, - // because we have no header for autodetect. - if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) { - opt.windowBits = -opt.windowBits; - if (opt.windowBits === 0) { opt.windowBits = -15; } - } - - // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate - if ((opt.windowBits >= 0) && (opt.windowBits < 16) && - !(options && options.windowBits)) { - opt.windowBits += 32; - } - - // Gzip header has no info about windows size, we can do autodetect only - // for deflate. So, if window size not set, force it to max when gzip possible - if ((opt.windowBits > 15) && (opt.windowBits < 48)) { - // bit 3 (16) -> gzipped data - // bit 4 (32) -> autodetect gzip/deflate - if ((opt.windowBits & 15) === 0) { - opt.windowBits |= 15; - } - } - - this.err = 0; // error code, if happens (0 = Z_OK) - this.msg = ''; // error message - this.ended = false; // used to avoid multiple onEnd() calls - this.chunks = []; // chunks of compressed data - - this.strm = new ZStream(); - this.strm.avail_out = 0; - - let status = inflateInit2( - this.strm, - opt.windowBits - ); - - if (status !== Z_OK) { - throw new Error(msg[status]); - } - - this.header = new GZheader(); - - inflateGetHeader(this.strm, this.header); - - // Setup dictionary - if (opt.dictionary) { - // Convert data if needed - if (typeof opt.dictionary === 'string') { - opt.dictionary = string2buf(opt.dictionary); - } else if (opt.dictionary instanceof ArrayBuffer) { - opt.dictionary = new Uint8Array(opt.dictionary); - } - if (opt.raw) { //In raw mode we need to set the dictionary early - status = inflateSetDictionary(this.strm, opt.dictionary); - if (status !== Z_OK) { - throw new Error(msg[status]); - } - } - } - } - /** - * Inflate#push(data[, mode]) -> Boolean - * - data (Uint8Array|Array|ArrayBuffer|String): input data - * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. - * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH. - * - * Sends input data to inflate pipe, generating [[Inflate#onData]] calls with - * new output chunks. Returns `true` on success. The last data block must have - * mode Z_FINISH (or `true`). That will flush internal pending buffers and call - * [[Inflate#onEnd]]. For interim explicit flushes (without ending the stream) you - * can use mode Z_SYNC_FLUSH, keeping the decompression context. - * - * On fail call [[Inflate#onEnd]] with error code and return false. - * - * We strongly recommend to use `Uint8Array` on input for best speed (output - * format is detected automatically). Also, don't skip last param and always - * use the same type in your code (boolean or number). That will improve JS speed. - * - * For regular `Array`-s make sure all elements are [0..255]. - * - * ##### Example - * - * ```javascript - * push(chunk, false); // push one of data chunks - * ... - * push(chunk, true); // push last chunk - * ``` - **/ - push(data, mode) { - const { strm, options: { chunkSize, dictionary } } = this; - let status, _mode; - - // Flag to properly process Z_BUF_ERROR on testing inflate call - // when we check that all output data was flushed. - let allowBufError = false; - - if (this.ended) { return false; } - _mode = (mode === ~~mode) ? mode : ((mode === true) ? Z_FINISH : Z_NO_FLUSH); - - // Convert data if needed - if (typeof data === 'string') { - // Only binary strings can be decompressed on practice - strm.input = binstring2buf(data); - } else if (data instanceof ArrayBuffer) { - strm.input = new Uint8Array(data); - } else { - strm.input = data; - } - - strm.next_in = 0; - strm.avail_in = strm.input.length; - - do { - if (strm.avail_out === 0) { - strm.output = new Buf8(chunkSize); - strm.next_out = 0; - strm.avail_out = chunkSize; - } - - status = inflate(strm, Z_NO_FLUSH); /* no bad return value */ - - if (status === Z_NEED_DICT && dictionary) { - status = inflateSetDictionary(this.strm, dictionary); - } - - if (status === Z_BUF_ERROR && allowBufError === true) { - status = Z_OK; - allowBufError = false; - } - - if (status !== Z_STREAM_END && status !== Z_OK) { - this.onEnd(status); - this.ended = true; - return false; - } - - if (strm.next_out) { - if (strm.avail_out === 0 || status === Z_STREAM_END || (strm.avail_in === 0 && (_mode === Z_FINISH || _mode === Z_SYNC_FLUSH))) { - this.onData(shrinkBuf(strm.output, strm.next_out)); - } - } - - // When no more input data, we should check that internal inflate buffers - // are flushed. The only way to do it when avail_out = 0 - run one more - // inflate pass. But if output data not exists, inflate return Z_BUF_ERROR. - // Here we set flag to process this error properly. - // - // NOTE. Deflate does not return error in this case and does not needs such - // logic. - if (strm.avail_in === 0 && strm.avail_out === 0) { - allowBufError = true; - } - - } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== Z_STREAM_END); - - if (status === Z_STREAM_END) { - _mode = Z_FINISH; - } - - // Finalize on the last chunk. - if (_mode === Z_FINISH) { - status = inflateEnd(this.strm); - this.onEnd(status); - this.ended = true; - return status === Z_OK; - } - - // callback interim results if Z_SYNC_FLUSH. - if (_mode === Z_SYNC_FLUSH) { - this.onEnd(Z_OK); - strm.avail_out = 0; - return true; - } - - return true; - }; - - /** - * Inflate#onData(chunk) -> Void - * - chunk (Uint8Array|Array|String): output data. Type of array depends - * on js engine support. When string output requested, each chunk - * will be string. - * - * By default, stores data blocks in `chunks[]` property and glue - * those in `onEnd`. Override this handler, if you need another behaviour. - **/ - onData(chunk) { - this.chunks.push(chunk); - }; - - - - /** - * Inflate#onEnd(status) -> Void - * - status (Number): inflate status. 0 (Z_OK) on success, - * other if not. - * - * Called either after you tell inflate that the input stream is - * complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH) - * or if an error happened. By default - join collected chunks, - * free memory and fill `results` / `err` properties. - **/ - onEnd(status) { - // On success - join - if (status === Z_OK) { - this.result = flattenChunks(this.chunks); - } - this.chunks = []; - this.err = status; - this.msg = this.strm.msg; - }; - } - - /* - node-bzip - a pure-javascript Node.JS module for decoding bzip2 data - - Copyright (C) 2012 Eli Skeggs - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see - http://www.gnu.org/licenses/lgpl-2.1.html - - Adapted from bzip2.js, copyright 2011 antimatter15 (antimatter15@gmail.com). - - Based on micro-bunzip by Rob Landley (rob@landley.net). - - Based on bzip2 decompression code by Julian R Seward (jseward@acm.org), - which also acknowledges contributions by Mike Burrows, David Wheeler, - Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten, - Robert Sedgewick, and Jon L. Bentley. - */ - - var BITMASK = [0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF]; - - // offset in bytes - var BitReader = function(stream) { - this.stream = stream; - this.bitOffset = 0; - this.curByte = 0; - this.hasByte = false; - }; - - BitReader.prototype._ensureByte = function() { - if (!this.hasByte) { - this.curByte = this.stream.readByte(); - this.hasByte = true; - } - }; - - // reads bits from the buffer - BitReader.prototype.read = function(bits) { - var result = 0; - while (bits > 0) { - this._ensureByte(); - var remaining = 8 - this.bitOffset; - // if we're in a byte - if (bits >= remaining) { - result <<= remaining; - result |= BITMASK[remaining] & this.curByte; - this.hasByte = false; - this.bitOffset = 0; - bits -= remaining; - } else { - result <<= bits; - var shift = remaining - bits; - result |= (this.curByte & (BITMASK[bits] << shift)) >> shift; - this.bitOffset += bits; - bits = 0; - } - } - return result; - }; - - // seek to an arbitrary point in the buffer (expressed in bits) - BitReader.prototype.seek = function(pos) { - var n_bit = pos % 8; - var n_byte = (pos - n_bit) / 8; - this.bitOffset = n_bit; - this.stream.seek(n_byte); - this.hasByte = false; - }; - - // reads 6 bytes worth of data using the read method - BitReader.prototype.pi = function() { - var buf = new Uint8Array(6), i; - for (i = 0; i < buf.length; i++) { - buf[i] = this.read(8); - } - return bufToHex(buf); - }; - - function bufToHex(buf) { - return Array.prototype.map.call(buf, x => ('00' + x.toString(16)).slice(-2)).join(''); - } - - var bitreader = BitReader; - - /* very simple input/output stream interface */ - var Stream = function() { - }; - - // input streams ////////////// - /** Returns the next byte, or -1 for EOF. */ - Stream.prototype.readByte = function() { - throw new Error("abstract method readByte() not implemented"); - }; - /** Attempts to fill the buffer; returns number of bytes read, or - * -1 for EOF. */ - Stream.prototype.read = function(buffer, bufOffset, length) { - var bytesRead = 0; - while (bytesRead < length) { - var c = this.readByte(); - if (c < 0) { // EOF - return (bytesRead===0) ? -1 : bytesRead; - } - buffer[bufOffset++] = c; - bytesRead++; - } - return bytesRead; - }; - Stream.prototype.seek = function(new_pos) { - throw new Error("abstract method seek() not implemented"); - }; - - // output streams /////////// - Stream.prototype.writeByte = function(_byte) { - throw new Error("abstract method readByte() not implemented"); - }; - Stream.prototype.write = function(buffer, bufOffset, length) { - var i; - for (i=0; i>> 0; // return an unsigned value - }; - - /** - * Update the CRC with a single byte - * @param value The value to update the CRC with - */ - this.updateCRC = function(value) { - crc = (crc << 8) ^ crc32Lookup[((crc >>> 24) ^ value) & 0xff]; - }; - - /** - * Update the CRC with a sequence of identical bytes - * @param value The value to update the CRC with - * @param count The number of bytes - */ - this.updateCRCRun = function(value, count) { - while (count-- > 0) { - crc = (crc << 8) ^ crc32Lookup[((crc >>> 24) ^ value) & 0xff]; - } - }; - }; - return CRC32; - })(); - - /* - seek-bzip - a pure-javascript module for seeking within bzip2 data - - Copyright (C) 2013 C. Scott Ananian - Copyright (C) 2012 Eli Skeggs - Copyright (C) 2011 Kevin Kwok - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see - http://www.gnu.org/licenses/lgpl-2.1.html - - Adapted from node-bzip, copyright 2012 Eli Skeggs. - Adapted from bzip2.js, copyright 2011 Kevin Kwok (antimatter15@gmail.com). - - Based on micro-bunzip by Rob Landley (rob@landley.net). - - Based on bzip2 decompression code by Julian R Seward (jseward@acm.org), - which also acknowledges contributions by Mike Burrows, David Wheeler, - Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten, - Robert Sedgewick, and Jon L. Bentley. - */ - - - - - - var MAX_HUFCODE_BITS = 20; - var MAX_SYMBOLS = 258; - var SYMBOL_RUNA = 0; - var SYMBOL_RUNB = 1; - var MIN_GROUPS = 2; - var MAX_GROUPS = 6; - var GROUP_SIZE = 50; - - var WHOLEPI = "314159265359"; - var SQRTPI = "177245385090"; - - var mtf = function(array, index) { - var src = array[index], i; - for (i = index; i > 0; i--) { - array[i] = array[i-1]; - } - array[0] = src; - return src; - }; - - var Err = { - OK: 0, - LAST_BLOCK: -1, - NOT_BZIP_DATA: -2, - UNEXPECTED_INPUT_EOF: -3, - UNEXPECTED_OUTPUT_EOF: -4, - DATA_ERROR: -5, - OUT_OF_MEMORY: -6, - OBSOLETE_INPUT: -7, - END_OF_BLOCK: -8 - }; - var ErrorMessages = {}; - ErrorMessages[Err.LAST_BLOCK] = "Bad file checksum"; - ErrorMessages[Err.NOT_BZIP_DATA] = "Not bzip data"; - ErrorMessages[Err.UNEXPECTED_INPUT_EOF] = "Unexpected input EOF"; - ErrorMessages[Err.UNEXPECTED_OUTPUT_EOF] = "Unexpected output EOF"; - ErrorMessages[Err.DATA_ERROR] = "Data error"; - ErrorMessages[Err.OUT_OF_MEMORY] = "Out of memory"; - ErrorMessages[Err.OBSOLETE_INPUT] = "Obsolete (pre 0.9.5) bzip format not supported."; - - var _throw = function(status, optDetail) { - var msg = ErrorMessages[status] || 'unknown error'; - if (optDetail) { msg += ': '+optDetail; } - var e = new TypeError(msg); - e.errorCode = status; - throw e; - }; - - var Bunzip = function(inputStream, outputStream) { - this.writePos = this.writeCurrent = this.writeCount = 0; - - this._start_bunzip(inputStream, outputStream); - }; - Bunzip.prototype._init_block = function() { - var moreBlocks = this._get_next_block(); - if ( !moreBlocks ) { - this.writeCount = -1; - return false; /* no more blocks */ - } - this.blockCRC = new crc32$1(); - return true; - }; - /* XXX micro-bunzip uses (inputStream, inputBuffer, len) as arguments */ - Bunzip.prototype._start_bunzip = function(inputStream, outputStream) { - /* Ensure that file starts with "BZh['1'-'9']." */ - var buf = new Uint8Array(4); - if (inputStream.read(buf, 0, 4) !== 4 || - String.fromCharCode(buf[0], buf[1], buf[2]) !== 'BZh') - _throw(Err.NOT_BZIP_DATA, 'bad magic'); - - var level = buf[3] - 0x30; - if (level < 1 || level > 9) - _throw(Err.NOT_BZIP_DATA, 'level out of range'); - - this.reader = new bitreader(inputStream); - - /* Fourth byte (ascii '1'-'9'), indicates block size in units of 100k of - uncompressed data. Allocate intermediate buffer for block. */ - this.dbufSize = 100000 * level; - this.nextoutput = 0; - this.outputStream = outputStream; - this.streamCRC = 0; - }; - Bunzip.prototype._get_next_block = function() { - var i, j, k; - var reader = this.reader; - // this is get_next_block() function from micro-bunzip: - /* Read in header signature and CRC, then validate signature. - (last block signature means CRC is for whole file, return now) */ - var h = reader.pi(); - if (h === SQRTPI) { // last block - return false; /* no more blocks */ - } - if (h !== WHOLEPI) - _throw(Err.NOT_BZIP_DATA); - this.targetBlockCRC = reader.read(32) >>> 0; // (convert to unsigned) - this.streamCRC = (this.targetBlockCRC ^ - ((this.streamCRC << 1) | (this.streamCRC>>>31))) >>> 0; - /* We can add support for blockRandomised if anybody complains. There was - some code for this in busybox 1.0.0-pre3, but nobody ever noticed that - it didn't actually work. */ - if (reader.read(1)) - _throw(Err.OBSOLETE_INPUT); - var origPointer = reader.read(24); - if (origPointer > this.dbufSize) - _throw(Err.DATA_ERROR, 'initial position out of bounds'); - /* mapping table: if some byte values are never used (encoding things - like ascii text), the compression code removes the gaps to have fewer - symbols to deal with, and writes a sparse bitfield indicating which - values were present. We make a translation table to convert the symbols - back to the corresponding bytes. */ - var t = reader.read(16); - var symToByte = new Uint8Array(256), symTotal = 0; - for (i = 0; i < 16; i++) { - if (t & (1 << (0xF - i))) { - var o = i * 16; - k = reader.read(16); - for (j = 0; j < 16; j++) - if (k & (1 << (0xF - j))) - symToByte[symTotal++] = o + j; - } - } - - /* How many different huffman coding groups does this block use? */ - var groupCount = reader.read(3); - if (groupCount < MIN_GROUPS || groupCount > MAX_GROUPS) - _throw(Err.DATA_ERROR); - /* nSelectors: Every GROUP_SIZE many symbols we select a new huffman coding - group. Read in the group selector list, which is stored as MTF encoded - bit runs. (MTF=Move To Front, as each value is used it's moved to the - start of the list.) */ - var nSelectors = reader.read(15); - if (nSelectors === 0) - _throw(Err.DATA_ERROR); - - var mtfSymbol = new Uint8Array(256); - for (i = 0; i < groupCount; i++) - mtfSymbol[i] = i; - - var selectors = new Uint8Array(nSelectors); // was 32768... - - for (i = 0; i < nSelectors; i++) { - /* Get next value */ - for (j = 0; reader.read(1); j++) - if (j >= groupCount) _throw(Err.DATA_ERROR); - /* Decode MTF to get the next selector */ - selectors[i] = mtf(mtfSymbol, j); - } - - /* Read the huffman coding tables for each group, which code for symTotal - literal symbols, plus two run symbols (RUNA, RUNB) */ - var symCount = symTotal + 2; - var groups = [], hufGroup; - for (j = 0; j < groupCount; j++) { - var length = new Uint8Array(symCount), temp = new Uint16Array(MAX_HUFCODE_BITS + 1); - /* Read huffman code lengths for each symbol. They're stored in - a way similar to mtf; record a starting value for the first symbol, - and an offset from the previous value for everys symbol after that. */ - t = reader.read(5); // lengths - for (i = 0; i < symCount; i++) { - for (;;) { - if (t < 1 || t > MAX_HUFCODE_BITS) _throw(Err.DATA_ERROR); - /* If first bit is 0, stop. Else second bit indicates whether - to increment or decrement the value. */ - if(!reader.read(1)) - break; - if(!reader.read(1)) - t++; - else - t--; - } - length[i] = t; - } - - /* Find largest and smallest lengths in this group */ - var minLen, maxLen; - minLen = maxLen = length[0]; - for (i = 1; i < symCount; i++) { - if (length[i] > maxLen) - maxLen = length[i]; - else if (length[i] < minLen) - minLen = length[i]; - } - - /* Calculate permute[], base[], and limit[] tables from length[]. - * - * permute[] is the lookup table for converting huffman coded symbols - * into decoded symbols. base[] is the amount to subtract from the - * value of a huffman symbol of a given length when using permute[]. - * - * limit[] indicates the largest numerical value a symbol with a given - * number of bits can have. This is how the huffman codes can vary in - * length: each code with a value>limit[length] needs another bit. - */ - hufGroup = {}; - groups.push(hufGroup); - hufGroup.permute = new Uint16Array(MAX_SYMBOLS); - hufGroup.limit = new Uint32Array(MAX_HUFCODE_BITS + 2); - hufGroup.base = new Uint32Array(MAX_HUFCODE_BITS + 1); - hufGroup.minLen = minLen; - hufGroup.maxLen = maxLen; - /* Calculate permute[]. Concurently, initialize temp[] and limit[]. */ - var pp = 0; - for (i = minLen; i <= maxLen; i++) { - temp[i] = hufGroup.limit[i] = 0; - for (t = 0; t < symCount; t++) - if (length[t] === i) - hufGroup.permute[pp++] = t; - } - /* Count symbols coded for at each bit length */ - for (i = 0; i < symCount; i++) - temp[length[i]]++; - /* Calculate limit[] (the largest symbol-coding value at each bit - * length, which is (previous limit<<1)+symbols at this level), and - * base[] (number of symbols to ignore at each bit length, which is - * limit minus the cumulative count of symbols coded for already). */ - pp = t = 0; - for (i = minLen; i < maxLen; i++) { - pp += temp[i]; - /* We read the largest possible symbol size and then unget bits - after determining how many we need, and those extra bits could - be set to anything. (They're noise from future symbols.) At - each level we're really only interested in the first few bits, - so here we set all the trailing to-be-ignored bits to 1 so they - don't affect the value>limit[length] comparison. */ - hufGroup.limit[i] = pp - 1; - pp <<= 1; - t += temp[i]; - hufGroup.base[i + 1] = pp - t; - } - hufGroup.limit[maxLen + 1] = Number.MAX_VALUE; /* Sentinal value for reading next sym. */ - hufGroup.limit[maxLen] = pp + temp[maxLen] - 1; - hufGroup.base[minLen] = 0; - } - /* We've finished reading and digesting the block header. Now read this - block's huffman coded symbols from the file and undo the huffman coding - and run length encoding, saving the result into dbuf[dbufCount++]=uc */ - - /* Initialize symbol occurrence counters and symbol Move To Front table */ - var byteCount = new Uint32Array(256); - for (i = 0; i < 256; i++) - mtfSymbol[i] = i; - /* Loop through compressed symbols. */ - var runPos = 0, dbufCount = 0, selector = 0, uc; - var dbuf = this.dbuf = new Uint32Array(this.dbufSize); - symCount = 0; - for (;;) { - /* Determine which huffman coding group to use. */ - if (!(symCount--)) { - symCount = GROUP_SIZE - 1; - if (selector >= nSelectors) { _throw(Err.DATA_ERROR); } - hufGroup = groups[selectors[selector++]]; - } - /* Read next huffman-coded symbol. */ - i = hufGroup.minLen; - j = reader.read(i); - for (;;i++) { - if (i > hufGroup.maxLen) { _throw(Err.DATA_ERROR); } - if (j <= hufGroup.limit[i]) - break; - j = (j << 1) | reader.read(1); - } - /* Huffman decode value to get nextSym (with bounds checking) */ - j -= hufGroup.base[i]; - if (j < 0 || j >= MAX_SYMBOLS) { _throw(Err.DATA_ERROR); } - var nextSym = hufGroup.permute[j]; - /* We have now decoded the symbol, which indicates either a new literal - byte, or a repeated run of the most recent literal byte. First, - check if nextSym indicates a repeated run, and if so loop collecting - how many times to repeat the last literal. */ - if (nextSym === SYMBOL_RUNA || nextSym === SYMBOL_RUNB) { - /* If this is the start of a new run, zero out counter */ - if (!runPos){ - runPos = 1; - t = 0; - } - /* Neat trick that saves 1 symbol: instead of or-ing 0 or 1 at - each bit position, add 1 or 2 instead. For example, - 1011 is 1<<0 + 1<<1 + 2<<2. 1010 is 2<<0 + 2<<1 + 1<<2. - You can make any bit pattern that way using 1 less symbol than - the basic or 0/1 method (except all bits 0, which would use no - symbols, but a run of length 0 doesn't mean anything in this - context). Thus space is saved. */ - if (nextSym === SYMBOL_RUNA) - t += runPos; - else - t += 2 * runPos; - runPos <<= 1; - continue; - } - /* When we hit the first non-run symbol after a run, we now know - how many times to repeat the last literal, so append that many - copies to our buffer of decoded symbols (dbuf) now. (The last - literal used is the one at the head of the mtfSymbol array.) */ - if (runPos){ - runPos = 0; - if (dbufCount + t > this.dbufSize) { _throw(Err.DATA_ERROR); } - uc = symToByte[mtfSymbol[0]]; - byteCount[uc] += t; - while (t--) - dbuf[dbufCount++] = uc; - } - /* Is this the terminating symbol? */ - if (nextSym > symTotal) - break; - /* At this point, nextSym indicates a new literal character. Subtract - one to get the position in the MTF array at which this literal is - currently to be found. (Note that the result can't be -1 or 0, - because 0 and 1 are RUNA and RUNB. But another instance of the - first symbol in the mtf array, position 0, would have been handled - as part of a run above. Therefore 1 unused mtf position minus - 2 non-literal nextSym values equals -1.) */ - if (dbufCount >= this.dbufSize) { _throw(Err.DATA_ERROR); } - i = nextSym - 1; - uc = mtf(mtfSymbol, i); - uc = symToByte[uc]; - /* We have our literal byte. Save it into dbuf. */ - byteCount[uc]++; - dbuf[dbufCount++] = uc; - } - /* At this point, we've read all the huffman-coded symbols (and repeated - runs) for this block from the input stream, and decoded them into the - intermediate buffer. There are dbufCount many decoded bytes in dbuf[]. - Now undo the Burrows-Wheeler transform on dbuf. - See http://dogma.net/markn/articles/bwt/bwt.htm - */ - if (origPointer < 0 || origPointer >= dbufCount) { _throw(Err.DATA_ERROR); } - /* Turn byteCount into cumulative occurrence counts of 0 to n-1. */ - j = 0; - for (i = 0; i < 256; i++) { - k = j + byteCount[i]; - byteCount[i] = j; - j = k; - } - /* Figure out what order dbuf would be in if we sorted it. */ - for (i = 0; i < dbufCount; i++) { - uc = dbuf[i] & 0xff; - dbuf[byteCount[uc]] |= (i << 8); - byteCount[uc]++; - } - /* Decode first byte by hand to initialize "previous" byte. Note that it - doesn't get output, and if the first three characters are identical - it doesn't qualify as a run (hence writeRunCountdown=5). */ - var pos = 0, current = 0, run = 0; - if (dbufCount) { - pos = dbuf[origPointer]; - current = (pos & 0xff); - pos >>= 8; - run = -1; - } - this.writePos = pos; - this.writeCurrent = current; - this.writeCount = dbufCount; - this.writeRun = run; - - return true; /* more blocks to come */ - }; - /* Undo burrows-wheeler transform on intermediate buffer to produce output. - If start_bunzip was initialized with out_fd=-1, then up to len bytes of - data are written to outbuf. Return value is number of bytes written or - error (all errors are negative numbers). If out_fd!=-1, outbuf and len - are ignored, data is written to out_fd and return is RETVAL_OK or error. - */ - Bunzip.prototype._read_bunzip = function(outputBuffer, len) { - var copies, previous, outbyte; - /* james@jamestaylor.org: writeCount goes to -1 when the buffer is fully - decoded, which results in this returning RETVAL_LAST_BLOCK, also - equal to -1... Confusing, I'm returning 0 here to indicate no - bytes written into the buffer */ - if (this.writeCount < 0) { return 0; } - var dbuf = this.dbuf, pos = this.writePos, current = this.writeCurrent; - var dbufCount = this.writeCount; this.outputsize; - var run = this.writeRun; - - while (dbufCount) { - dbufCount--; - previous = current; - pos = dbuf[pos]; - current = pos & 0xff; - pos >>= 8; - if (run++ === 3){ - copies = current; - outbyte = previous; - current = -1; - } else { - copies = 1; - outbyte = current; - } - this.blockCRC.updateCRCRun(outbyte, copies); - while (copies--) { - this.outputStream.writeByte(outbyte); - this.nextoutput++; - } - if (current != previous) - run = 0; - } - this.writeCount = dbufCount; - // check CRC - if (this.blockCRC.getCRC() !== this.targetBlockCRC) { - _throw(Err.DATA_ERROR, "Bad block CRC "+ - "(got "+this.blockCRC.getCRC().toString(16)+ - " expected "+this.targetBlockCRC.toString(16)+")"); - } - return this.nextoutput; - }; - - var coerceInputStream = function(input) { - if ('readByte' in input) { return input; } - var inputStream = new stream(); - inputStream.pos = 0; - inputStream.readByte = function() { return input[this.pos++]; }; - inputStream.seek = function(pos) { this.pos = pos; }; - inputStream.eof = function() { return this.pos >= input.length; }; - return inputStream; - }; - var coerceOutputStream = function(output) { - var outputStream = new stream(); - var resizeOk = true; - if (output) { - if (typeof(output)==='number') { - outputStream.buffer = new Uint8Array(output); - resizeOk = false; - } else if ('writeByte' in output) { - return output; - } else { - outputStream.buffer = output; - resizeOk = false; - } - } else { - outputStream.buffer = new Uint8Array(16384); - } - outputStream.pos = 0; - outputStream.writeByte = function(_byte) { - if (resizeOk && this.pos >= this.buffer.length) { - var newBuffer = new Uint8Array(this.buffer.length*2); - newBuffer.set(this.buffer); - this.buffer = newBuffer; - } - this.buffer[this.pos++] = _byte; - }; - outputStream.getBuffer = function() { - // trim buffer - if (this.pos !== this.buffer.length) { - if (!resizeOk) - throw new TypeError('outputsize does not match decoded input'); - var newBuffer = new Uint8Array(this.pos); - newBuffer.set(this.buffer.subarray(0, this.pos)); - this.buffer = newBuffer; - } - return this.buffer; - }; - outputStream._coerced = true; - return outputStream; - }; - - /* Static helper functions */ - // 'input' can be a stream or a buffer - // 'output' can be a stream or a buffer or a number (buffer size) - const decode$2 = function(input, output, multistream) { - // make a stream from a buffer, if necessary - var inputStream = coerceInputStream(input); - var outputStream = coerceOutputStream(output); - - var bz = new Bunzip(inputStream, outputStream); - while (true) { - if ('eof' in inputStream && inputStream.eof()) break; - if (bz._init_block()) { - bz._read_bunzip(); - } else { - var targetStreamCRC = bz.reader.read(32) >>> 0; // (convert to unsigned) - if (targetStreamCRC !== bz.streamCRC) { - _throw(Err.DATA_ERROR, "Bad stream CRC "+ - "(got "+bz.streamCRC.toString(16)+ - " expected "+targetStreamCRC.toString(16)+")"); - } - if (multistream && - 'eof' in inputStream && - !inputStream.eof()) { - // note that start_bunzip will also resync the bit reader to next byte - bz._start_bunzip(inputStream, outputStream); - } else break; - } - } - if ('getBuffer' in outputStream) - return outputStream.getBuffer(); - }; - const decodeBlock = function(input, pos, output) { - // make a stream from a buffer, if necessary - var inputStream = coerceInputStream(input); - var outputStream = coerceOutputStream(output); - var bz = new Bunzip(inputStream, outputStream); - bz.reader.seek(pos); - /* Fill the decode buffer for the block */ - var moreBlocks = bz._get_next_block(); - if (moreBlocks) { - /* Init the CRC for writing */ - bz.blockCRC = new crc32$1(); - - /* Zero this so the current byte from before the seek is not written */ - bz.writeCopies = 0; - - /* Decompress the block and write to stdout */ - bz._read_bunzip(); - // XXX keep writing? - } - if ('getBuffer' in outputStream) - return outputStream.getBuffer(); - }; - /* Reads bzip2 file from stream or buffer `input`, and invoke - * `callback(position, size)` once for each bzip2 block, - * where position gives the starting position (in *bits*) - * and size gives uncompressed size of the block (in *bytes*). */ - const table = function(input, callback, multistream) { - // make a stream from a buffer, if necessary - var inputStream = new stream(); - inputStream.delegate = coerceInputStream(input); - inputStream.pos = 0; - inputStream.readByte = function() { - this.pos++; - return this.delegate.readByte(); - }; - if (inputStream.delegate.eof) { - inputStream.eof = inputStream.delegate.eof.bind(inputStream.delegate); - } - var outputStream = new stream(); - outputStream.pos = 0; - outputStream.writeByte = function() { this.pos++; }; - - var bz = new Bunzip(inputStream, outputStream); - var blockSize = bz.dbufSize; - while (true) { - if ('eof' in inputStream && inputStream.eof()) break; - - var position = inputStream.pos*8 + bz.reader.bitOffset; - if (bz.reader.hasByte) { position -= 8; } - - if (bz._init_block()) { - var start = outputStream.pos; - bz._read_bunzip(); - callback(position, outputStream.pos - start); - } else { - bz.reader.read(32); // (but we ignore the crc) - if (multistream && - 'eof' in inputStream && - !inputStream.eof()) { - // note that start_bunzip will also resync the bit reader to next byte - bz._start_bunzip(inputStream, outputStream); - console.assert(bz.dbufSize === blockSize, - "shouldn't change block size within multistream file"); - } else break; - } - } - }; - - var lib = { - Bunzip, - Stream: stream, - Err, - decode: decode$2, - decodeBlock, - table - }; - var lib_4 = lib.decode; - - // GPG4Browsers - An OpenPGP implementation in javascript - - /** - * Implementation of the Literal Data Packet (Tag 11) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.9|RFC4880 5.9}: - * A Literal Data packet contains the body of a message; data that is not to be - * further interpreted. - */ - class LiteralDataPacket { - static get tag() { - return enums.packet.literalData; - } - - /** - * @param {Date} date - The creation date of the literal package - */ - constructor(date = new Date()) { - this.format = enums.literal.utf8; // default format for literal data packets - this.date = util.normalizeDate(date); - this.text = null; // textual data representation - this.data = null; // literal data representation - this.filename = ''; - } - - /** - * Set the packet data to a javascript native string, end of line - * will be normalized to \r\n and by default text is converted to UTF8 - * @param {String | ReadableStream} text - Any native javascript string - * @param {enums.literal} [format] - The format of the string of bytes - */ - setText(text, format = enums.literal.utf8) { - this.format = format; - this.text = text; - this.data = null; - } - - /** - * Returns literal data packets as native JavaScript string - * with normalized end of line to \n - * @param {Boolean} [clone] - Whether to return a clone so that getBytes/getText can be called again - * @returns {String | ReadableStream} Literal data as text. - */ - getText(clone = false) { - if (this.text === null || util.isStream(this.text)) { // Assume that this.text has been read - this.text = util.decodeUTF8(util.nativeEOL(this.getBytes(clone))); - } - return this.text; - } - - /** - * Set the packet data to value represented by the provided string of bytes. - * @param {Uint8Array | ReadableStream} bytes - The string of bytes - * @param {enums.literal} format - The format of the string of bytes - */ - setBytes(bytes, format) { - this.format = format; - this.data = bytes; - this.text = null; - } - - - /** - * Get the byte sequence representing the literal packet data - * @param {Boolean} [clone] - Whether to return a clone so that getBytes/getText can be called again - * @returns {Uint8Array | ReadableStream} A sequence of bytes. - */ - getBytes(clone = false) { - if (this.data === null) { - // encode UTF8 and normalize EOL to \r\n - this.data = util.canonicalizeEOL(util.encodeUTF8(this.text)); - } - if (clone) { - return passiveClone(this.data); - } - return this.data; - } - - - /** - * Sets the filename of the literal packet data - * @param {String} filename - Any native javascript string - */ - setFilename(filename) { - this.filename = filename; - } - - - /** - * Get the filename of the literal packet data - * @returns {String} Filename. - */ - getFilename() { - return this.filename; - } - - /** - * Parsing function for a literal data packet (tag 11). - * - * @param {Uint8Array | ReadableStream} input - Payload of a tag 11 packet - * @returns {Promise} Object representation. - * @async - */ - async read(bytes) { - await parse(bytes, async reader => { - // - A one-octet field that describes how the data is formatted. - const format = await reader.readByte(); // enums.literal - - const filename_len = await reader.readByte(); - this.filename = util.decodeUTF8(await reader.readBytes(filename_len)); - - this.date = util.readDate(await reader.readBytes(4)); - - let data = reader.remainder(); - if (isArrayStream(data)) data = await readToEnd(data); - this.setBytes(data, format); - }); - } - - /** - * Creates a Uint8Array representation of the packet, excluding the data - * - * @returns {Uint8Array} Uint8Array representation of the packet. - */ - writeHeader() { - const filename = util.encodeUTF8(this.filename); - const filename_length = new Uint8Array([filename.length]); - - const format = new Uint8Array([this.format]); - const date = util.writeDate(this.date); - - return util.concatUint8Array([format, filename_length, filename, date]); - } - - /** - * Creates a Uint8Array representation of the packet - * - * @returns {Uint8Array | ReadableStream} Uint8Array representation of the packet. - */ - write() { - const header = this.writeHeader(); - const data = this.getBytes(); - - return util.concat([header, data]); - } - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - function readSimpleLength(bytes) { - let len = 0; - let offset; - const type = bytes[0]; - - - if (type < 192) { - [len] = bytes; - offset = 1; - } else if (type < 255) { - len = ((bytes[0] - 192) << 8) + (bytes[1]) + 192; - offset = 2; - } else if (type === 255) { - len = util.readNumber(bytes.subarray(1, 1 + 4)); - offset = 5; - } - - return { - len: len, - offset: offset - }; - } - - /** - * Encodes a given integer of length to the openpgp length specifier to a - * string - * - * @param {Integer} length - The length to encode - * @returns {Uint8Array} String with openpgp length representation. - */ - function writeSimpleLength(length) { - if (length < 192) { - return new Uint8Array([length]); - } else if (length > 191 && length < 8384) { - /* - * let a = (total data packet length) - 192 let bc = two octet - * representation of a let d = b + 192 - */ - return new Uint8Array([((length - 192) >> 8) + 192, (length - 192) & 0xFF]); - } - return util.concatUint8Array([new Uint8Array([255]), util.writeNumber(length, 4)]); - } - - function writePartialLength(power) { - if (power < 0 || power > 30) { - throw new Error('Partial Length power must be between 1 and 30'); - } - return new Uint8Array([224 + power]); - } - - function writeTag(tag_type) { - /* we're only generating v4 packet headers here */ - return new Uint8Array([0xC0 | tag_type]); - } - - /** - * Writes a packet header version 4 with the given tag_type and length to a - * string - * - * @param {Integer} tag_type - Tag type - * @param {Integer} length - Length of the payload - * @returns {String} String of the header. - */ - function writeHeader(tag_type, length) { - /* we're only generating v4 packet headers here */ - return util.concatUint8Array([writeTag(tag_type), writeSimpleLength(length)]); - } - - /** - * Whether the packet type supports partial lengths per RFC4880 - * @param {Integer} tag - Tag type - * @returns {Boolean} String of the header. - */ - function supportsStreaming(tag) { - return [ - enums.packet.literalData, - enums.packet.compressedData, - enums.packet.symmetricallyEncryptedData, - enums.packet.symEncryptedIntegrityProtectedData, - enums.packet.aeadEncryptedData - ].includes(tag); - } - - /** - * Generic static Packet Parser function - * - * @param {Uint8Array | ReadableStream} input - Input stream as string - * @param {Function} callback - Function to call with the parsed packet - * @returns {Boolean} Returns false if the stream was empty and parsing is done, and true otherwise. - */ - async function readPackets(input, callback) { - const reader = getReader(input); - let writer; - let callbackReturned; - try { - const peekedBytes = await reader.peekBytes(2); - // some sanity checks - if (!peekedBytes || peekedBytes.length < 2 || (peekedBytes[0] & 0x80) === 0) { - throw new Error('Error during parsing. This message / key probably does not conform to a valid OpenPGP format.'); - } - const headerByte = await reader.readByte(); - let tag = -1; - let format = -1; - let packetLength; - - format = 0; // 0 = old format; 1 = new format - if ((headerByte & 0x40) !== 0) { - format = 1; - } - - let packetLengthType; - if (format) { - // new format header - tag = headerByte & 0x3F; // bit 5-0 - } else { - // old format header - tag = (headerByte & 0x3F) >> 2; // bit 5-2 - packetLengthType = headerByte & 0x03; // bit 1-0 - } - - const packetSupportsStreaming = supportsStreaming(tag); - let packet = null; - if (packetSupportsStreaming) { - if (util.isStream(input) === 'array') { - const arrayStream = new ArrayStream(); - writer = getWriter(arrayStream); - packet = arrayStream; - } else { - const transform = new TransformStream(); - writer = getWriter(transform.writable); - packet = transform.readable; - } - callbackReturned = callback({ tag, packet }); - } else { - packet = []; - } - - let wasPartialLength; - do { - if (!format) { - // 4.2.1. Old Format Packet Lengths - switch (packetLengthType) { - case 0: - // The packet has a one-octet length. The header is 2 octets - // long. - packetLength = await reader.readByte(); - break; - case 1: - // The packet has a two-octet length. The header is 3 octets - // long. - packetLength = (await reader.readByte() << 8) | await reader.readByte(); - break; - case 2: - // The packet has a four-octet length. The header is 5 - // octets long. - packetLength = (await reader.readByte() << 24) | (await reader.readByte() << 16) | (await reader.readByte() << - 8) | await reader.readByte(); - break; - default: - // 3 - The packet is of indeterminate length. The header is 1 - // octet long, and the implementation must determine how long - // the packet is. If the packet is in a file, this means that - // the packet extends until the end of the file. In general, - // an implementation SHOULD NOT use indeterminate-length - // packets except where the end of the data will be clear - // from the context, and even then it is better to use a - // definite length, or a new format header. The new format - // headers described below have a mechanism for precisely - // encoding data of indeterminate length. - packetLength = Infinity; - break; - } - } else { // 4.2.2. New Format Packet Lengths - // 4.2.2.1. One-Octet Lengths - const lengthByte = await reader.readByte(); - wasPartialLength = false; - if (lengthByte < 192) { - packetLength = lengthByte; - // 4.2.2.2. Two-Octet Lengths - } else if (lengthByte >= 192 && lengthByte < 224) { - packetLength = ((lengthByte - 192) << 8) + (await reader.readByte()) + 192; - // 4.2.2.4. Partial Body Lengths - } else if (lengthByte > 223 && lengthByte < 255) { - packetLength = 1 << (lengthByte & 0x1F); - wasPartialLength = true; - if (!packetSupportsStreaming) { - throw new TypeError('This packet type does not support partial lengths.'); - } - // 4.2.2.3. Five-Octet Lengths - } else { - packetLength = (await reader.readByte() << 24) | (await reader.readByte() << 16) | (await reader.readByte() << - 8) | await reader.readByte(); - } - } - if (packetLength > 0) { - let bytesRead = 0; - while (true) { - if (writer) await writer.ready; - const { done, value } = await reader.read(); - if (done) { - if (packetLength === Infinity) break; - throw new Error('Unexpected end of packet'); - } - const chunk = packetLength === Infinity ? value : value.subarray(0, packetLength - bytesRead); - if (writer) await writer.write(chunk); - else packet.push(chunk); - bytesRead += value.length; - if (bytesRead >= packetLength) { - reader.unshift(value.subarray(packetLength - bytesRead + value.length)); - break; - } - } - } - } while (wasPartialLength); - - // If this was not a packet that "supports streaming", we peek to check - // whether it is the last packet in the message. We peek 2 bytes instead - // of 1 because the beginning of this function also peeks 2 bytes, and we - // want to cut a `subarray` of the correct length into `web-stream-tools`' - // `externalBuffer` as a tiny optimization here. - // - // If it *was* a streaming packet (i.e. the data packets), we peek at the - // entire remainder of the stream, in order to forward errors in the - // remainder of the stream to the packet data. (Note that this means we - // read/peek at all signature packets before closing the literal data - // packet, for example.) This forwards MDC errors to the literal data - // stream, for example, so that they don't get lost / forgotten on - // decryptedMessage.packets.stream, which we never look at. - // - // An example of what we do when stream-parsing a message containing - // [ one-pass signature packet, literal data packet, signature packet ]: - // 1. Read the one-pass signature packet - // 2. Peek 2 bytes of the literal data packet - // 3. Parse the one-pass signature packet - // - // 4. Read the literal data packet, simultaneously stream-parsing it - // 5. Peek until the end of the message - // 6. Finish parsing the literal data packet - // - // 7. Read the signature packet again (we already peeked at it in step 5) - // 8. Peek at the end of the stream again (`peekBytes` returns undefined) - // 9. Parse the signature packet - // - // Note that this means that if there's an error in the very end of the - // stream, such as an MDC error, we throw in step 5 instead of in step 8 - // (or never), which is the point of this exercise. - const nextPacket = await reader.peekBytes(packetSupportsStreaming ? Infinity : 2); - if (writer) { - await writer.ready; - await writer.close(); - } else { - packet = util.concatUint8Array(packet); - await callback({ tag, packet }); - } - return !nextPacket || !nextPacket.length; - } catch (e) { - if (writer) { - await writer.abort(e); - return true; - } else { - throw e; - } - } finally { - if (writer) { - await callbackReturned; - } - reader.releaseLock(); - } - } - - class UnsupportedError extends Error { - constructor(...params) { - super(...params); - - if (Error.captureStackTrace) { - Error.captureStackTrace(this, UnsupportedError); - } - - this.name = 'UnsupportedError'; - } - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - // Symbol to store cryptographic validity of the signature, to avoid recomputing multiple times on verification. - // const verified = Symbol('verified'); - - // GPG puts the Issuer and Signature subpackets in the unhashed area. - // Tampering with those invalidates the signature, so we still trust them and parse them. - // All other unhashed subpackets are ignored. - const allowedUnhashedSubpackets = new Set([ - enums.signatureSubpacket.issuer, - enums.signatureSubpacket.issuerFingerprint, - enums.signatureSubpacket.embeddedSignature - ]); - - /** - * Implementation of the Signature Packet (Tag 2) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.2|RFC4480 5.2}: - * A Signature packet describes a binding between some public key and - * some data. The most common signatures are a signature of a file or a - * block of text, and a signature that is a certification of a User ID. - */ - class SignaturePacket { - static get tag() { - return enums.packet.signature; - } - - constructor() { - this.version = null; - /** @type {enums.signature} */ - this.signatureType = null; - /** @type {enums.hash} */ - this.hashAlgorithm = null; - /** @type {enums.publicKey} */ - this.publicKeyAlgorithm = null; - - this.signatureData = null; - this.unhashedSubpackets = []; - this.signedHashValue = null; - - this.created = null; - this.signatureExpirationTime = null; - this.signatureNeverExpires = true; - this.exportable = null; - this.trustLevel = null; - this.trustAmount = null; - this.regularExpression = null; - this.revocable = null; - this.keyExpirationTime = null; - this.keyNeverExpires = null; - this.preferredSymmetricAlgorithms = null; - this.revocationKeyClass = null; - this.revocationKeyAlgorithm = null; - this.revocationKeyFingerprint = null; - this.issuerKeyID = new KeyID(); - this.rawNotations = []; - this.notations = {}; - this.preferredHashAlgorithms = null; - this.preferredCompressionAlgorithms = null; - this.keyServerPreferences = null; - this.preferredKeyServer = null; - this.isPrimaryUserID = null; - this.policyURI = null; - this.keyFlags = null; - this.signersUserID = null; - this.reasonForRevocationFlag = null; - this.reasonForRevocationString = null; - this.features = null; - this.signatureTargetPublicKeyAlgorithm = null; - this.signatureTargetHashAlgorithm = null; - this.signatureTargetHash = null; - this.embeddedSignature = null; - this.issuerKeyVersion = null; - this.issuerFingerprint = null; - this.preferredAEADAlgorithms = null; - - this.revoked = null; - this.verified = null; - } - - /** - * parsing function for a signature packet (tag 2). - * @param {String} bytes - Payload of a tag 2 packet - * @returns {SignaturePacket} Object representation. - */ - read(bytes) { - let i = 0; - this.version = bytes[i++]; - - if (this.version !== 4 && this.version !== 5) { - throw new UnsupportedError(`Version ${this.version} of the signature packet is unsupported.`); - } - - this.signatureType = bytes[i++]; - this.publicKeyAlgorithm = bytes[i++]; - this.hashAlgorithm = bytes[i++]; - - // hashed subpackets - i += this.readSubPackets(bytes.subarray(i, bytes.length), true); - if (!this.created) { - throw new Error('Missing signature creation time subpacket.'); - } - - // A V4 signature hashes the packet body - // starting from its first field, the version number, through the end - // of the hashed subpacket data. Thus, the fields hashed are the - // signature version, the signature type, the public-key algorithm, the - // hash algorithm, the hashed subpacket length, and the hashed - // subpacket body. - this.signatureData = bytes.subarray(0, i); - - // unhashed subpackets - i += this.readSubPackets(bytes.subarray(i, bytes.length), false); - - // Two-octet field holding left 16 bits of signed hash value. - this.signedHashValue = bytes.subarray(i, i + 2); - i += 2; - - this.params = mod.signature.parseSignatureParams(this.publicKeyAlgorithm, bytes.subarray(i, bytes.length)); - } - - /** - * @returns {Uint8Array | ReadableStream} - */ - writeParams() { - if (this.params instanceof Promise) { - return fromAsync( - async () => mod.serializeParams(this.publicKeyAlgorithm, await this.params) - ); - } - return mod.serializeParams(this.publicKeyAlgorithm, this.params); - } - - write() { - const arr = []; - arr.push(this.signatureData); - arr.push(this.writeUnhashedSubPackets()); - arr.push(this.signedHashValue); - arr.push(this.writeParams()); - return util.concat(arr); - } - - /** - * Signs provided data. This needs to be done prior to serialization. - * @param {SecretKeyPacket} key - Private key used to sign the message. - * @param {Object} data - Contains packets to be signed. - * @param {Date} [date] - The signature creation time. - * @param {Boolean} [detached] - Whether to create a detached signature - * @throws {Error} if signing failed - * @async - */ - async sign(key, data, date = new Date(), detached = false) { - if (key.version === 5) { - this.version = 5; - } else { - this.version = 4; - } - const arr = [new Uint8Array([this.version, this.signatureType, this.publicKeyAlgorithm, this.hashAlgorithm])]; - - this.created = util.normalizeDate(date); - this.issuerKeyVersion = key.version; - this.issuerFingerprint = key.getFingerprintBytes(); - this.issuerKeyID = key.getKeyID(); - - // Add hashed subpackets - arr.push(this.writeHashedSubPackets()); - - this.signatureData = util.concat(arr); - - const toHash = this.toHash(this.signatureType, data, detached); - const hash = await this.hash(this.signatureType, data, toHash, detached); - - this.signedHashValue = slice(clone(hash), 0, 2); - const signed = async () => mod.signature.sign( - this.publicKeyAlgorithm, this.hashAlgorithm, key.publicParams, key.privateParams, toHash, await readToEnd(hash) - ); - if (util.isStream(hash)) { - this.params = signed(); - } else { - this.params = await signed(); - - // Store the fact that this signature is valid, e.g. for when we call `await - // getLatestValidSignature(this.revocationSignatures, key, data)` later. - // Note that this only holds up if the key and data passed to verify are the - // same as the ones passed to sign. - this.verified = true; - } - } - - /** - * Creates Uint8Array of bytes of all subpacket data except Issuer and Embedded Signature subpackets - * @returns {Uint8Array} Subpacket data. - */ - writeHashedSubPackets() { - const sub = enums.signatureSubpacket; - const arr = []; - let bytes; - if (this.created === null) { - throw new Error('Missing signature creation time'); - } - arr.push(writeSubPacket(sub.signatureCreationTime, util.writeDate(this.created))); - if (this.signatureExpirationTime !== null) { - arr.push(writeSubPacket(sub.signatureExpirationTime, util.writeNumber(this.signatureExpirationTime, 4))); - } - if (this.exportable !== null) { - arr.push(writeSubPacket(sub.exportableCertification, new Uint8Array([this.exportable ? 1 : 0]))); - } - if (this.trustLevel !== null) { - bytes = new Uint8Array([this.trustLevel, this.trustAmount]); - arr.push(writeSubPacket(sub.trustSignature, bytes)); - } - if (this.regularExpression !== null) { - arr.push(writeSubPacket(sub.regularExpression, this.regularExpression)); - } - if (this.revocable !== null) { - arr.push(writeSubPacket(sub.revocable, new Uint8Array([this.revocable ? 1 : 0]))); - } - if (this.keyExpirationTime !== null) { - arr.push(writeSubPacket(sub.keyExpirationTime, util.writeNumber(this.keyExpirationTime, 4))); - } - if (this.preferredSymmetricAlgorithms !== null) { - bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredSymmetricAlgorithms)); - arr.push(writeSubPacket(sub.preferredSymmetricAlgorithms, bytes)); - } - if (this.revocationKeyClass !== null) { - bytes = new Uint8Array([this.revocationKeyClass, this.revocationKeyAlgorithm]); - bytes = util.concat([bytes, this.revocationKeyFingerprint]); - arr.push(writeSubPacket(sub.revocationKey, bytes)); - } - this.rawNotations.forEach(([{ name, value, humanReadable }]) => { - bytes = [new Uint8Array([humanReadable ? 0x80 : 0, 0, 0, 0])]; - // 2 octets of name length - bytes.push(util.writeNumber(name.length, 2)); - // 2 octets of value length - bytes.push(util.writeNumber(value.length, 2)); - bytes.push(util.stringToUint8Array(name)); - bytes.push(value); - bytes = util.concat(bytes); - arr.push(writeSubPacket(sub.notationData, bytes)); - }); - if (this.preferredHashAlgorithms !== null) { - bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredHashAlgorithms)); - arr.push(writeSubPacket(sub.preferredHashAlgorithms, bytes)); - } - if (this.preferredCompressionAlgorithms !== null) { - bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredCompressionAlgorithms)); - arr.push(writeSubPacket(sub.preferredCompressionAlgorithms, bytes)); - } - if (this.keyServerPreferences !== null) { - bytes = util.stringToUint8Array(util.uint8ArrayToString(this.keyServerPreferences)); - arr.push(writeSubPacket(sub.keyServerPreferences, bytes)); - } - if (this.preferredKeyServer !== null) { - arr.push(writeSubPacket(sub.preferredKeyServer, util.stringToUint8Array(this.preferredKeyServer))); - } - if (this.isPrimaryUserID !== null) { - arr.push(writeSubPacket(sub.primaryUserID, new Uint8Array([this.isPrimaryUserID ? 1 : 0]))); - } - if (this.policyURI !== null) { - arr.push(writeSubPacket(sub.policyURI, util.stringToUint8Array(this.policyURI))); - } - if (this.keyFlags !== null) { - bytes = util.stringToUint8Array(util.uint8ArrayToString(this.keyFlags)); - arr.push(writeSubPacket(sub.keyFlags, bytes)); - } - if (this.signersUserID !== null) { - arr.push(writeSubPacket(sub.signersUserID, util.stringToUint8Array(this.signersUserID))); - } - if (this.reasonForRevocationFlag !== null) { - bytes = util.stringToUint8Array(String.fromCharCode(this.reasonForRevocationFlag) + this.reasonForRevocationString); - arr.push(writeSubPacket(sub.reasonForRevocation, bytes)); - } - if (this.features !== null) { - bytes = util.stringToUint8Array(util.uint8ArrayToString(this.features)); - arr.push(writeSubPacket(sub.features, bytes)); - } - if (this.signatureTargetPublicKeyAlgorithm !== null) { - bytes = [new Uint8Array([this.signatureTargetPublicKeyAlgorithm, this.signatureTargetHashAlgorithm])]; - bytes.push(util.stringToUint8Array(this.signatureTargetHash)); - bytes = util.concat(bytes); - arr.push(writeSubPacket(sub.signatureTarget, bytes)); - } - if (this.preferredAEADAlgorithms !== null) { - bytes = util.stringToUint8Array(util.uint8ArrayToString(this.preferredAEADAlgorithms)); - arr.push(writeSubPacket(sub.preferredAEADAlgorithms, bytes)); - } - - const result = util.concat(arr); - const length = util.writeNumber(result.length, 2); - - return util.concat([length, result]); - } - - /** - * Creates Uint8Array of bytes of Issuer and Embedded Signature subpackets - * @returns {Uint8Array} Subpacket data. - */ - writeUnhashedSubPackets() { - const sub = enums.signatureSubpacket; - const arr = []; - let bytes; - if (!this.issuerKeyID.isNull() && this.issuerKeyVersion !== 5) { - // If the version of [the] key is greater than 4, this subpacket - // MUST NOT be included in the signature. - arr.push(writeSubPacket(sub.issuer, this.issuerKeyID.write())); - } - if (this.embeddedSignature !== null) { - arr.push(writeSubPacket(sub.embeddedSignature, this.embeddedSignature.write())); - } - if (this.issuerFingerprint !== null) { - bytes = [new Uint8Array([this.issuerKeyVersion]), this.issuerFingerprint]; - bytes = util.concat(bytes); - arr.push(writeSubPacket(sub.issuerFingerprint, bytes)); - } - this.unhashedSubpackets.forEach(data => { - arr.push(writeSimpleLength(data.length)); - arr.push(data); - }); - - const result = util.concat(arr); - const length = util.writeNumber(result.length, 2); - - return util.concat([length, result]); - } - - // V4 signature sub packets - readSubPacket(bytes, hashed = true) { - let mypos = 0; - - // The leftmost bit denotes a "critical" packet - const critical = bytes[mypos] & 0x80; - const type = bytes[mypos] & 0x7F; - - if (!hashed && !allowedUnhashedSubpackets.has(type)) { - this.unhashedSubpackets.push(bytes.subarray(mypos, bytes.length)); - return; - } - - mypos++; - - // subpacket type - switch (type) { - case enums.signatureSubpacket.signatureCreationTime: - // Signature Creation Time - this.created = util.readDate(bytes.subarray(mypos, bytes.length)); - break; - case enums.signatureSubpacket.signatureExpirationTime: { - // Signature Expiration Time in seconds - const seconds = util.readNumber(bytes.subarray(mypos, bytes.length)); - - this.signatureNeverExpires = seconds === 0; - this.signatureExpirationTime = seconds; - - break; - } - case enums.signatureSubpacket.exportableCertification: - // Exportable Certification - this.exportable = bytes[mypos++] === 1; - break; - case enums.signatureSubpacket.trustSignature: - // Trust Signature - this.trustLevel = bytes[mypos++]; - this.trustAmount = bytes[mypos++]; - break; - case enums.signatureSubpacket.regularExpression: - // Regular Expression - this.regularExpression = bytes[mypos]; - break; - case enums.signatureSubpacket.revocable: - // Revocable - this.revocable = bytes[mypos++] === 1; - break; - case enums.signatureSubpacket.keyExpirationTime: { - // Key Expiration Time in seconds - const seconds = util.readNumber(bytes.subarray(mypos, bytes.length)); - - this.keyExpirationTime = seconds; - this.keyNeverExpires = seconds === 0; - - break; - } - case enums.signatureSubpacket.preferredSymmetricAlgorithms: - // Preferred Symmetric Algorithms - this.preferredSymmetricAlgorithms = [...bytes.subarray(mypos, bytes.length)]; - break; - case enums.signatureSubpacket.revocationKey: - // Revocation Key - // (1 octet of class, 1 octet of public-key algorithm ID, 20 - // octets of - // fingerprint) - this.revocationKeyClass = bytes[mypos++]; - this.revocationKeyAlgorithm = bytes[mypos++]; - this.revocationKeyFingerprint = bytes.subarray(mypos, mypos + 20); - break; - - case enums.signatureSubpacket.issuer: - // Issuer - this.issuerKeyID.read(bytes.subarray(mypos, bytes.length)); - break; - - case enums.signatureSubpacket.notationData: { - // Notation Data - const humanReadable = !!(bytes[mypos] & 0x80); - - // We extract key/value tuple from the byte stream. - mypos += 4; - const m = util.readNumber(bytes.subarray(mypos, mypos + 2)); - mypos += 2; - const n = util.readNumber(bytes.subarray(mypos, mypos + 2)); - mypos += 2; - - const name = util.uint8ArrayToString(bytes.subarray(mypos, mypos + m)); - const value = bytes.subarray(mypos + m, mypos + m + n); - - this.rawNotations.push({ name, humanReadable, value, critical }); - - if (humanReadable) { - this.notations[name] = util.uint8ArrayToString(value); - } - break; - } - case enums.signatureSubpacket.preferredHashAlgorithms: - // Preferred Hash Algorithms - this.preferredHashAlgorithms = [...bytes.subarray(mypos, bytes.length)]; - break; - case enums.signatureSubpacket.preferredCompressionAlgorithms: - // Preferred Compression Algorithms - this.preferredCompressionAlgorithms = [...bytes.subarray(mypos, bytes.length)]; - break; - case enums.signatureSubpacket.keyServerPreferences: - // Key Server Preferences - this.keyServerPreferences = [...bytes.subarray(mypos, bytes.length)]; - break; - case enums.signatureSubpacket.preferredKeyServer: - // Preferred Key Server - this.preferredKeyServer = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); - break; - case enums.signatureSubpacket.primaryUserID: - // Primary User ID - this.isPrimaryUserID = bytes[mypos++] !== 0; - break; - case enums.signatureSubpacket.policyURI: - // Policy URI - this.policyURI = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); - break; - case enums.signatureSubpacket.keyFlags: - // Key Flags - this.keyFlags = [...bytes.subarray(mypos, bytes.length)]; - break; - case enums.signatureSubpacket.signersUserID: - // Signer's User ID - this.signersUserID = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); - break; - case enums.signatureSubpacket.reasonForRevocation: - // Reason for Revocation - this.reasonForRevocationFlag = bytes[mypos++]; - this.reasonForRevocationString = util.uint8ArrayToString(bytes.subarray(mypos, bytes.length)); - break; - case enums.signatureSubpacket.features: - // Features - this.features = [...bytes.subarray(mypos, bytes.length)]; - break; - case enums.signatureSubpacket.signatureTarget: { - // Signature Target - // (1 octet public-key algorithm, 1 octet hash algorithm, N octets hash) - this.signatureTargetPublicKeyAlgorithm = bytes[mypos++]; - this.signatureTargetHashAlgorithm = bytes[mypos++]; - - const len = mod.getHashByteLength(this.signatureTargetHashAlgorithm); - - this.signatureTargetHash = util.uint8ArrayToString(bytes.subarray(mypos, mypos + len)); - break; - } - case enums.signatureSubpacket.embeddedSignature: - // Embedded Signature - this.embeddedSignature = new SignaturePacket(); - this.embeddedSignature.read(bytes.subarray(mypos, bytes.length)); - break; - case enums.signatureSubpacket.issuerFingerprint: - // Issuer Fingerprint - this.issuerKeyVersion = bytes[mypos++]; - this.issuerFingerprint = bytes.subarray(mypos, bytes.length); - if (this.issuerKeyVersion === 5) { - this.issuerKeyID.read(this.issuerFingerprint); - } else { - this.issuerKeyID.read(this.issuerFingerprint.subarray(-8)); - } - break; - case enums.signatureSubpacket.preferredAEADAlgorithms: - // Preferred AEAD Algorithms - this.preferredAEADAlgorithms = [...bytes.subarray(mypos, bytes.length)]; - break; - default: { - const err = new Error(`Unknown signature subpacket type ${type}`); - if (critical) { - throw err; - } else { - util.printDebug(err); - } - } - } - } - - readSubPackets(bytes, trusted = true, config) { - // Two-octet scalar octet count for following subpacket data. - const subpacketLength = util.readNumber(bytes.subarray(0, 2)); - - let i = 2; - - // subpacket data set (zero or more subpackets) - while (i < 2 + subpacketLength) { - const len = readSimpleLength(bytes.subarray(i, bytes.length)); - i += len.offset; - - this.readSubPacket(bytes.subarray(i, i + len.len), trusted, config); - - i += len.len; - } - - return i; - } - - // Produces data to produce signature on - toSign(type, data) { - const t = enums.signature; - - switch (type) { - case t.binary: - if (data.text !== null) { - return util.encodeUTF8(data.getText(true)); - } - return data.getBytes(true); - - case t.text: { - const bytes = data.getBytes(true); - // normalize EOL to \r\n - return util.canonicalizeEOL(bytes); - } - case t.standalone: - return new Uint8Array(0); - - case t.certGeneric: - case t.certPersona: - case t.certCasual: - case t.certPositive: - case t.certRevocation: { - let packet; - let tag; - - if (data.userID) { - tag = 0xB4; - packet = data.userID; - } else if (data.userAttribute) { - tag = 0xD1; - packet = data.userAttribute; - } else { - throw new Error('Either a userID or userAttribute packet needs to be ' + - 'supplied for certification.'); - } - - const bytes = packet.write(); - - return util.concat([this.toSign(t.key, data), - new Uint8Array([tag]), - util.writeNumber(bytes.length, 4), - bytes]); - } - case t.subkeyBinding: - case t.subkeyRevocation: - case t.keyBinding: - return util.concat([this.toSign(t.key, data), this.toSign(t.key, { - key: data.bind - })]); - - case t.key: - if (data.key === undefined) { - throw new Error('Key packet is required for this signature.'); - } - return data.key.writeForHash(this.version); - - case t.keyRevocation: - return this.toSign(t.key, data); - case t.timestamp: - return new Uint8Array(0); - case t.thirdParty: - throw new Error('Not implemented'); - default: - throw new Error('Unknown signature type.'); - } - } - - calculateTrailer(data, detached) { - let length = 0; - return transform(clone(this.signatureData), value => { - length += value.length; - }, () => { - const arr = []; - if (this.version === 5 && (this.signatureType === enums.signature.binary || this.signatureType === enums.signature.text)) { - if (detached) { - arr.push(new Uint8Array(6)); - } else { - arr.push(data.writeHeader()); - } - } - arr.push(new Uint8Array([this.version, 0xFF])); - if (this.version === 5) { - arr.push(new Uint8Array(4)); - } - arr.push(util.writeNumber(length, 4)); - // For v5, this should really be writeNumber(length, 8) rather than the - // hardcoded 4 zero bytes above - return util.concat(arr); - }); - } - - toHash(signatureType, data, detached = false) { - const bytes = this.toSign(signatureType, data); - - return util.concat([bytes, this.signatureData, this.calculateTrailer(data, detached)]); - } - - async hash(signatureType, data, toHash, detached = false) { - if (!toHash) toHash = this.toHash(signatureType, data, detached); - return mod.hash.digest(this.hashAlgorithm, toHash); - } - - /** - * verifies the signature packet. Note: not all signature types are implemented - * @param {PublicSubkeyPacket|PublicKeyPacket| - * SecretSubkeyPacket|SecretKeyPacket} key - the public key to verify the signature - * @param {module:enums.signature} signatureType - Expected signature type - * @param {String|Object} data - Data which on the signature applies - * @param {Date} [date] - Use the given date instead of the current time to check for signature validity and expiration - * @param {Boolean} [detached] - Whether to verify a detached signature - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if signature validation failed - * @async - */ - async verify(key, signatureType, data, date = new Date(), detached = false, config = defaultConfig) { - if (!this.issuerKeyID.equals(key.getKeyID())) { - throw new Error('Signature was not issued by the given public key'); - } - if (this.publicKeyAlgorithm !== key.algorithm) { - throw new Error('Public key algorithm used to sign signature does not match issuer key algorithm.'); - } - - const isMessageSignature = signatureType === enums.signature.binary || signatureType === enums.signature.text; - // Cryptographic validity is cached after one successful verification. - // However, for message signatures, we always re-verify, since the passed `data` can change - const skipVerify = this.verified && !isMessageSignature; - if (!skipVerify) { - let toHash; - let hash; - if (this.hashed) { - hash = await this.hashed; - } else { - toHash = this.toHash(signatureType, data, detached); - hash = await this.hash(signatureType, data, toHash); - } - hash = await readToEnd(hash); - if (this.signedHashValue[0] !== hash[0] || - this.signedHashValue[1] !== hash[1]) { - throw new Error('Signed digest did not match'); - } - - this.params = await this.params; - - this.verified = await mod.signature.verify( - this.publicKeyAlgorithm, this.hashAlgorithm, this.params, key.publicParams, - toHash, hash - ); - - if (!this.verified) { - throw new Error('Signature verification failed'); - } - } - - const normDate = util.normalizeDate(date); - if (normDate && this.created > normDate) { - throw new Error('Signature creation time is in the future'); - } - if (normDate && normDate >= this.getExpirationTime()) { - throw new Error('Signature is expired'); - } - if (config.rejectHashAlgorithms.has(this.hashAlgorithm)) { - throw new Error('Insecure hash algorithm: ' + enums.read(enums.hash, this.hashAlgorithm).toUpperCase()); - } - if (config.rejectMessageHashAlgorithms.has(this.hashAlgorithm) && - [enums.signature.binary, enums.signature.text].includes(this.signatureType)) { - throw new Error('Insecure message hash algorithm: ' + enums.read(enums.hash, this.hashAlgorithm).toUpperCase()); - } - this.rawNotations.forEach(({ name, critical }) => { - if (critical && (config.knownNotations.indexOf(name) < 0)) { - throw new Error(`Unknown critical notation: ${name}`); - } - }); - if (this.revocationKeyClass !== null) { - throw new Error('This key is intended to be revoked with an authorized key, which OpenPGP.js does not support.'); - } - } - - /** - * Verifies signature expiration date - * @param {Date} [date] - Use the given date for verification instead of the current time - * @returns {Boolean} True if expired. - */ - isExpired(date = new Date()) { - const normDate = util.normalizeDate(date); - if (normDate !== null) { - return !(this.created <= normDate && normDate < this.getExpirationTime()); - } - return false; - } - - /** - * Returns the expiration time of the signature or Infinity if signature does not expire - * @returns {Date | Infinity} Expiration time. - */ - getExpirationTime() { - return this.signatureNeverExpires ? Infinity : new Date(this.created.getTime() + this.signatureExpirationTime * 1000); - } - } - - /** - * Creates a string representation of a sub signature packet - * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.1|RFC4880 5.2.3.1} - * @see {@link https://tools.ietf.org/html/rfc4880#section-5.2.3.2|RFC4880 5.2.3.2} - * @param {Integer} type - Subpacket signature type. - * @param {String} data - Data to be included - * @returns {String} A string-representation of a sub signature packet. - * @private - */ - function writeSubPacket(type, data) { - const arr = []; - arr.push(writeSimpleLength(data.length + 1)); - arr.push(new Uint8Array([type])); - arr.push(data); - return util.concat(arr); - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - const VERSION = 3; - - /** - * Implementation of the One-Pass Signature Packets (Tag 4) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.4|RFC4880 5.4}: - * The One-Pass Signature packet precedes the signed data and contains - * enough information to allow the receiver to begin calculating any - * hashes needed to verify the signature. It allows the Signature - * packet to be placed at the end of the message, so that the signer - * can compute the entire signed message in one pass. - */ - class OnePassSignaturePacket { - static get tag() { - return enums.packet.onePassSignature; - } - - constructor() { - /** A one-octet version number. The current version is 3. */ - this.version = null; - /** - * A one-octet signature type. - * Signature types are described in - * {@link https://tools.ietf.org/html/rfc4880#section-5.2.1|RFC4880 Section 5.2.1}. - * @type {enums.signature} - - */ - this.signatureType = null; - /** - * A one-octet number describing the hash algorithm used. - * @see {@link https://tools.ietf.org/html/rfc4880#section-9.4|RFC4880 9.4} - * @type {enums.hash} - */ - this.hashAlgorithm = null; - /** - * A one-octet number describing the public-key algorithm used. - * @see {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC4880 9.1} - * @type {enums.publicKey} - */ - this.publicKeyAlgorithm = null; - /** An eight-octet number holding the Key ID of the signing key. */ - this.issuerKeyID = null; - /** - * A one-octet number holding a flag showing whether the signature is nested. - * A zero value indicates that the next packet is another One-Pass Signature packet - * that describes another signature to be applied to the same message data. - */ - this.flags = null; - } - - /** - * parsing function for a one-pass signature packet (tag 4). - * @param {Uint8Array} bytes - Payload of a tag 4 packet - * @returns {OnePassSignaturePacket} Object representation. - */ - read(bytes) { - let mypos = 0; - // A one-octet version number. The current version is 3. - this.version = bytes[mypos++]; - if (this.version !== VERSION) { - throw new UnsupportedError(`Version ${this.version} of the one-pass signature packet is unsupported.`); - } - - // A one-octet signature type. Signature types are described in - // Section 5.2.1. - this.signatureType = bytes[mypos++]; - - // A one-octet number describing the hash algorithm used. - this.hashAlgorithm = bytes[mypos++]; - - // A one-octet number describing the public-key algorithm used. - this.publicKeyAlgorithm = bytes[mypos++]; - - // An eight-octet number holding the Key ID of the signing key. - this.issuerKeyID = new KeyID(); - this.issuerKeyID.read(bytes.subarray(mypos, mypos + 8)); - mypos += 8; - - // A one-octet number holding a flag showing whether the signature - // is nested. A zero value indicates that the next packet is - // another One-Pass Signature packet that describes another - // signature to be applied to the same message data. - this.flags = bytes[mypos++]; - return this; - } - - /** - * creates a string representation of a one-pass signature packet - * @returns {Uint8Array} A Uint8Array representation of a one-pass signature packet. - */ - write() { - const start = new Uint8Array([VERSION, this.signatureType, this.hashAlgorithm, this.publicKeyAlgorithm]); - - const end = new Uint8Array([this.flags]); - - return util.concatUint8Array([start, this.issuerKeyID.write(), end]); - } - - calculateTrailer(...args) { - return fromAsync(async () => SignaturePacket.prototype.calculateTrailer.apply(await this.correspondingSig, args)); - } - - async verify() { - const correspondingSig = await this.correspondingSig; - if (!correspondingSig || correspondingSig.constructor.tag !== enums.packet.signature) { - throw new Error('Corresponding signature packet missing'); - } - if ( - correspondingSig.signatureType !== this.signatureType || - correspondingSig.hashAlgorithm !== this.hashAlgorithm || - correspondingSig.publicKeyAlgorithm !== this.publicKeyAlgorithm || - !correspondingSig.issuerKeyID.equals(this.issuerKeyID) - ) { - throw new Error('Corresponding signature packet does not match one-pass signature packet'); - } - correspondingSig.hashed = this.hashed; - return correspondingSig.verify.apply(correspondingSig, arguments); - } - } - - OnePassSignaturePacket.prototype.hash = SignaturePacket.prototype.hash; - OnePassSignaturePacket.prototype.toHash = SignaturePacket.prototype.toHash; - OnePassSignaturePacket.prototype.toSign = SignaturePacket.prototype.toSign; - - /** - * Instantiate a new packet given its tag - * @function newPacketFromTag - * @param {module:enums.packet} tag - Property value from {@link module:enums.packet} - * @param {Object} allowedPackets - mapping where keys are allowed packet tags, pointing to their Packet class - * @returns {Object} New packet object with type based on tag - * @throws {Error|UnsupportedError} for disallowed or unknown packets - */ - function newPacketFromTag(tag, allowedPackets) { - if (!allowedPackets[tag]) { - // distinguish between disallowed packets and unknown ones - let packetType; - try { - packetType = enums.read(enums.packet, tag); - } catch (e) { - throw new UnsupportedError(`Unknown packet type with tag: ${tag}`); - } - throw new Error(`Packet not allowed in this context: ${packetType}`); - } - return new allowedPackets[tag](); - } - - /** - * This class represents a list of openpgp packets. - * Take care when iterating over it - the packets themselves - * are stored as numerical indices. - * @extends Array - */ - class PacketList extends Array { - /** - * Parses the given binary data and returns a list of packets. - * Equivalent to calling `read` on an empty PacketList instance. - * @param {Uint8Array | ReadableStream} bytes - binary data to parse - * @param {Object} allowedPackets - mapping where keys are allowed packet tags, pointing to their Packet class - * @param {Object} [config] - full configuration, defaults to openpgp.config - * @returns {PacketList} parsed list of packets - * @throws on parsing errors - * @async - */ - static async fromBinary(bytes, allowedPackets, config = defaultConfig) { - const packets = new PacketList(); - await packets.read(bytes, allowedPackets, config); - return packets; - } - - /** - * Reads a stream of binary data and interprets it as a list of packets. - * @param {Uint8Array | ReadableStream} bytes - binary data to parse - * @param {Object} allowedPackets - mapping where keys are allowed packet tags, pointing to their Packet class - * @param {Object} [config] - full configuration, defaults to openpgp.config - * @throws on parsing errors - * @async - */ - async read(bytes, allowedPackets, config = defaultConfig) { - this.stream = transformPair(bytes, async (readable, writable) => { - const writer = getWriter(writable); - try { - while (true) { - await writer.ready; - const done = await readPackets(readable, async parsed => { - try { - if (parsed.tag === enums.packet.marker || parsed.tag === enums.packet.trust) { - // According to the spec, these packet types should be ignored and not cause parsing errors, even if not esplicitly allowed: - // - Marker packets MUST be ignored when received: https://github.com/openpgpjs/openpgpjs/issues/1145 - // - Trust packets SHOULD be ignored outside of keyrings (unsupported): https://datatracker.ietf.org/doc/html/rfc4880#section-5.10 - return; - } - const packet = newPacketFromTag(parsed.tag, allowedPackets); - packet.packets = new PacketList(); - packet.fromStream = util.isStream(parsed.packet); - await packet.read(parsed.packet, config); - await writer.write(packet); - } catch (e) { - const throwUnsupportedError = !config.ignoreUnsupportedPackets && e instanceof UnsupportedError; - const throwMalformedError = !config.ignoreMalformedPackets && !(e instanceof UnsupportedError); - if (throwUnsupportedError || throwMalformedError || supportsStreaming(parsed.tag)) { - // The packets that support streaming are the ones that contain message data. - // Those are also the ones we want to be more strict about and throw on parse errors - // (since we likely cannot process the message without these packets anyway). - await writer.abort(e); - } - util.printDebugError(e); - } - }); - if (done) { - await writer.ready; - await writer.close(); - return; - } - } - } catch (e) { - await writer.abort(e); - } - }); - - // Wait until first few packets have been read - const reader = getReader(this.stream); - while (true) { - const { done, value } = await reader.read(); - if (!done) { - this.push(value); - } else { - this.stream = null; - } - if (done || supportsStreaming(value.constructor.tag)) { - break; - } - } - reader.releaseLock(); - } - - /** - * Creates a binary representation of openpgp objects contained within the - * class instance. - * @returns {Uint8Array} A Uint8Array containing valid openpgp packets. - */ - write() { - const arr = []; - - for (let i = 0; i < this.length; i++) { - const packetbytes = this[i].write(); - if (util.isStream(packetbytes) && supportsStreaming(this[i].constructor.tag)) { - let buffer = []; - let bufferLength = 0; - const minLength = 512; - arr.push(writeTag(this[i].constructor.tag)); - arr.push(transform(packetbytes, value => { - buffer.push(value); - bufferLength += value.length; - if (bufferLength >= minLength) { - const powerOf2 = Math.min(Math.log(bufferLength) / Math.LN2 | 0, 30); - const chunkSize = 2 ** powerOf2; - const bufferConcat = util.concat([writePartialLength(powerOf2)].concat(buffer)); - buffer = [bufferConcat.subarray(1 + chunkSize)]; - bufferLength = buffer[0].length; - return bufferConcat.subarray(0, 1 + chunkSize); - } - }, () => util.concat([writeSimpleLength(bufferLength)].concat(buffer)))); - } else { - if (util.isStream(packetbytes)) { - let length = 0; - arr.push(transform(clone(packetbytes), value => { - length += value.length; - }, () => writeHeader(this[i].constructor.tag, length))); - } else { - arr.push(writeHeader(this[i].constructor.tag, packetbytes.length)); - } - arr.push(packetbytes); - } - } - - return util.concat(arr); - } - - /** - * Creates a new PacketList with all packets matching the given tag(s) - * @param {...module:enums.packet} tags - packet tags to look for - * @returns {PacketList} - */ - filterByTag(...tags) { - const filtered = new PacketList(); - - const handle = tag => packetType => tag === packetType; - - for (let i = 0; i < this.length; i++) { - if (tags.some(handle(this[i].constructor.tag))) { - filtered.push(this[i]); - } - } - - return filtered; - } - - /** - * Traverses packet list and returns first packet with matching tag - * @param {module:enums.packet} tag - The packet tag - * @returns {Packet|undefined} - */ - findPacket(tag) { - return this.find(packet => packet.constructor.tag === tag); - } - - /** - * Find indices of packets with the given tag(s) - * @param {...module:enums.packet} tags - packet tags to look for - * @returns {Integer[]} packet indices - */ - indexOfTag(...tags) { - const tagIndex = []; - const that = this; - - const handle = tag => packetType => tag === packetType; - - for (let i = 0; i < this.length; i++) { - if (tags.some(handle(that[i].constructor.tag))) { - tagIndex.push(i); - } - } - return tagIndex; - } - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - // A Compressed Data packet can contain the following packet types - const allowedPackets = /*#__PURE__*/ util.constructAllowedPackets([ - LiteralDataPacket, - OnePassSignaturePacket, - SignaturePacket - ]); - - /** - * Implementation of the Compressed Data Packet (Tag 8) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.6|RFC4880 5.6}: - * The Compressed Data packet contains compressed data. Typically, - * this packet is found as the contents of an encrypted packet, or following - * a Signature or One-Pass Signature packet, and contains a literal data packet. - */ - class CompressedDataPacket { - static get tag() { - return enums.packet.compressedData; - } - - /** - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - constructor(config = defaultConfig) { - /** - * List of packets - * @type {PacketList} - */ - this.packets = null; - /** - * Compression algorithm - * @type {enums.compression} - */ - this.algorithm = config.preferredCompressionAlgorithm; - - /** - * Compressed packet data - * @type {Uint8Array | ReadableStream} - */ - this.compressed = null; - - /** - * zip/zlib compression level, between 1 and 9 - */ - this.deflateLevel = config.deflateLevel; - } - - /** - * Parsing function for the packet. - * @param {Uint8Array | ReadableStream} bytes - Payload of a tag 8 packet - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - async read(bytes, config = defaultConfig) { - await parse(bytes, async reader => { - - // One octet that gives the algorithm used to compress the packet. - this.algorithm = await reader.readByte(); - - // Compressed data, which makes up the remainder of the packet. - this.compressed = reader.remainder(); - - await this.decompress(config); - }); - } - - - /** - * Return the compressed packet. - * @returns {Uint8Array | ReadableStream} Binary compressed packet. - */ - write() { - if (this.compressed === null) { - this.compress(); - } - - return util.concat([new Uint8Array([this.algorithm]), this.compressed]); - } - - - /** - * Decompression method for decompressing the compressed data - * read by read_packet - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - async decompress(config = defaultConfig) { - const compressionName = enums.read(enums.compression, this.algorithm); - const decompressionFn = decompress_fns[compressionName]; - if (!decompressionFn) { - throw new Error(`${compressionName} decompression not supported`); - } - - this.packets = await PacketList.fromBinary(decompressionFn(this.compressed), allowedPackets, config); - } - - /** - * Compress the packet data (member decompressedData) - */ - compress() { - const compressionName = enums.read(enums.compression, this.algorithm); - const compressionFn = compress_fns[compressionName]; - if (!compressionFn) { - throw new Error(`${compressionName} compression not supported`); - } - - this.compressed = compressionFn(this.packets.write(), this.deflateLevel); - } - } - - ////////////////////////// - // // - // Helper functions // - // // - ////////////////////////// - - - const nodeZlib = util.getNodeZlib(); - - function uncompressed(data) { - return data; - } - - function node_zlib(func, create, options = {}) { - return function (data) { - if (!util.isStream(data) || isArrayStream(data)) { - return fromAsync(() => readToEnd(data).then(data => { - return new Promise((resolve, reject) => { - func(data, options, (err, result) => { - if (err) return reject(err); - resolve(result); - }); - }); - })); - } - return nodeToWeb(webToNode(data).pipe(create(options))); - }; - } - - function pako_zlib(constructor, options = {}) { - return function(data) { - const obj = new constructor(options); - return transform(data, value => { - if (value.length) { - obj.push(value, Z_SYNC_FLUSH); - return obj.result; - } - }, () => { - if (constructor === Deflate) { - obj.push([], Z_FINISH); - return obj.result; - } - }); - }; - } - - function bzip2(func) { - return function(data) { - return fromAsync(async () => func(await readToEnd(data))); - }; - } - - const compress_fns = nodeZlib ? { - zip: /*#__PURE__*/ (compressed, level) => node_zlib(nodeZlib.deflateRaw, nodeZlib.createDeflateRaw, { level })(compressed), - zlib: /*#__PURE__*/ (compressed, level) => node_zlib(nodeZlib.deflate, nodeZlib.createDeflate, { level })(compressed) - } : { - zip: /*#__PURE__*/ (compressed, level) => pako_zlib(Deflate, { raw: true, level })(compressed), - zlib: /*#__PURE__*/ (compressed, level) => pako_zlib(Deflate, { level })(compressed) - }; - - const decompress_fns = nodeZlib ? { - uncompressed: uncompressed, - zip: /*#__PURE__*/ node_zlib(nodeZlib.inflateRaw, nodeZlib.createInflateRaw), - zlib: /*#__PURE__*/ node_zlib(nodeZlib.inflate, nodeZlib.createInflate), - bzip2: /*#__PURE__*/ bzip2(lib_4) - } : { - uncompressed: uncompressed, - zip: /*#__PURE__*/ pako_zlib(Inflate, { raw: true }), - zlib: /*#__PURE__*/ pako_zlib(Inflate), - bzip2: /*#__PURE__*/ bzip2(lib_4) - }; - - // GPG4Browsers - An OpenPGP implementation in javascript - - // A SEIP packet can contain the following packet types - const allowedPackets$1 = /*#__PURE__*/ util.constructAllowedPackets([ - LiteralDataPacket, - CompressedDataPacket, - OnePassSignaturePacket, - SignaturePacket - ]); - - const VERSION$1 = 1; // A one-octet version number of the data packet. - - /** - * Implementation of the Sym. Encrypted Integrity Protected Data Packet (Tag 18) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.13|RFC4880 5.13}: - * The Symmetrically Encrypted Integrity Protected Data packet is - * a variant of the Symmetrically Encrypted Data packet. It is a new feature - * created for OpenPGP that addresses the problem of detecting a modification to - * encrypted data. It is used in combination with a Modification Detection Code - * packet. - */ - class SymEncryptedIntegrityProtectedDataPacket { - static get tag() { - return enums.packet.symEncryptedIntegrityProtectedData; - } - - constructor() { - this.version = VERSION$1; - this.encrypted = null; - this.packets = null; - } - - async read(bytes) { - await parse(bytes, async reader => { - const version = await reader.readByte(); - // - A one-octet version number. The only currently defined value is 1. - if (version !== VERSION$1) { - throw new UnsupportedError(`Version ${version} of the SEIP packet is unsupported.`); - } - - // - Encrypted data, the output of the selected symmetric-key cipher - // operating in Cipher Feedback mode with shift amount equal to the - // block size of the cipher (CFB-n where n is the block size). - this.encrypted = reader.remainder(); - }); - } - - write() { - return util.concat([new Uint8Array([VERSION$1]), this.encrypted]); - } - - /** - * Encrypt the payload in the packet. - * @param {enums.symmetric} sessionKeyAlgorithm - The symmetric encryption algorithm to use - * @param {Uint8Array} key - The key of cipher blocksize length to be used - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} - * @throws {Error} on encryption failure - * @async - */ - async encrypt(sessionKeyAlgorithm, key, config = defaultConfig) { - const { blockSize } = mod.getCipher(sessionKeyAlgorithm); - - let bytes = this.packets.write(); - if (isArrayStream(bytes)) bytes = await readToEnd(bytes); - const prefix = await mod.getPrefixRandom(sessionKeyAlgorithm); - const mdc = new Uint8Array([0xD3, 0x14]); // modification detection code packet - - const tohash = util.concat([prefix, bytes, mdc]); - const hash = await mod.hash.sha1(passiveClone(tohash)); - const plaintext = util.concat([tohash, hash]); - - this.encrypted = await mod.mode.cfb.encrypt(sessionKeyAlgorithm, key, plaintext, new Uint8Array(blockSize), config); - return true; - } - - /** - * Decrypts the encrypted data contained in the packet. - * @param {enums.symmetric} sessionKeyAlgorithm - The selected symmetric encryption algorithm to be used - * @param {Uint8Array} key - The key of cipher blocksize length to be used - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} - * @throws {Error} on decryption failure - * @async - */ - async decrypt(sessionKeyAlgorithm, key, config = defaultConfig) { - const { blockSize } = mod.getCipher(sessionKeyAlgorithm); - let encrypted = clone(this.encrypted); - if (isArrayStream(encrypted)) encrypted = await readToEnd(encrypted); - const decrypted = await mod.mode.cfb.decrypt(sessionKeyAlgorithm, key, encrypted, new Uint8Array(blockSize)); - - // there must be a modification detection code packet as the - // last packet and everything gets hashed except the hash itself - const realHash = slice(passiveClone(decrypted), -20); - const tohash = slice(decrypted, 0, -20); - const verifyHash = Promise.all([ - readToEnd(await mod.hash.sha1(passiveClone(tohash))), - readToEnd(realHash) - ]).then(([hash, mdc]) => { - if (!util.equalsUint8Array(hash, mdc)) { - throw new Error('Modification detected.'); - } - return new Uint8Array(); - }); - const bytes = slice(tohash, blockSize + 2); // Remove random prefix - let packetbytes = slice(bytes, 0, -2); // Remove MDC packet - packetbytes = concat([packetbytes, fromAsync(() => verifyHash)]); - if (!util.isStream(encrypted) || !config.allowUnauthenticatedStream) { - packetbytes = await readToEnd(packetbytes); - } - this.packets = await PacketList.fromBinary(packetbytes, allowedPackets$1, config); - return true; - } - } - - // OpenPGP.js - An OpenPGP implementation in javascript - - // An AEAD-encrypted Data packet can contain the following packet types - const allowedPackets$2 = /*#__PURE__*/ util.constructAllowedPackets([ - LiteralDataPacket, - CompressedDataPacket, - OnePassSignaturePacket, - SignaturePacket - ]); - - const VERSION$2 = 1; // A one-octet version number of the data packet. - - /** - * Implementation of the Symmetrically Encrypted Authenticated Encryption with - * Additional Data (AEAD) Protected Data Packet - * - * {@link https://tools.ietf.org/html/draft-ford-openpgp-format-00#section-2.1}: - * AEAD Protected Data Packet - */ - class AEADEncryptedDataPacket { - static get tag() { - return enums.packet.aeadEncryptedData; - } - - constructor() { - this.version = VERSION$2; - /** @type {enums.symmetric} */ - this.cipherAlgorithm = null; - /** @type {enums.aead} */ - this.aeadAlgorithm = enums.aead.eax; - this.chunkSizeByte = null; - this.iv = null; - this.encrypted = null; - this.packets = null; - } - - /** - * Parse an encrypted payload of bytes in the order: version, IV, ciphertext (see specification) - * @param {Uint8Array | ReadableStream} bytes - * @throws {Error} on parsing failure - */ - async read(bytes) { - await parse(bytes, async reader => { - const version = await reader.readByte(); - if (version !== VERSION$2) { // The only currently defined value is 1. - throw new UnsupportedError(`Version ${version} of the AEAD-encrypted data packet is not supported.`); - } - this.cipherAlgorithm = await reader.readByte(); - this.aeadAlgorithm = await reader.readByte(); - this.chunkSizeByte = await reader.readByte(); - - const mode = mod.getAEADMode(this.aeadAlgorithm); - this.iv = await reader.readBytes(mode.ivLength); - this.encrypted = reader.remainder(); - }); - } - - /** - * Write the encrypted payload of bytes in the order: version, IV, ciphertext (see specification) - * @returns {Uint8Array | ReadableStream} The encrypted payload. - */ - write() { - return util.concat([new Uint8Array([this.version, this.cipherAlgorithm, this.aeadAlgorithm, this.chunkSizeByte]), this.iv, this.encrypted]); - } - - /** - * Decrypt the encrypted payload. - * @param {enums.symmetric} sessionKeyAlgorithm - The session key's cipher algorithm - * @param {Uint8Array} key - The session key used to encrypt the payload - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if decryption was not successful - * @async - */ - async decrypt(sessionKeyAlgorithm, key, config = defaultConfig) { - this.packets = await PacketList.fromBinary( - await this.crypt('decrypt', key, clone(this.encrypted)), - allowedPackets$2, - config - ); - } - - /** - * Encrypt the packet payload. - * @param {enums.symmetric} sessionKeyAlgorithm - The session key's cipher algorithm - * @param {Uint8Array} key - The session key used to encrypt the payload - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if encryption was not successful - * @async - */ - async encrypt(sessionKeyAlgorithm, key, config = defaultConfig) { - this.cipherAlgorithm = sessionKeyAlgorithm; - - const { ivLength } = mod.getAEADMode(this.aeadAlgorithm); - this.iv = await mod.random.getRandomBytes(ivLength); // generate new random IV - this.chunkSizeByte = config.aeadChunkSizeByte; - const data = this.packets.write(); - this.encrypted = await this.crypt('encrypt', key, data); - } - - /** - * En/decrypt the payload. - * @param {encrypt|decrypt} fn - Whether to encrypt or decrypt - * @param {Uint8Array} key - The session key used to en/decrypt the payload - * @param {Uint8Array | ReadableStream} data - The data to en/decrypt - * @returns {Promise>} - * @async - */ - async crypt(fn, key, data) { - const mode = mod.getAEADMode(this.aeadAlgorithm); - const modeInstance = await mode(this.cipherAlgorithm, key); - const tagLengthIfDecrypting = fn === 'decrypt' ? mode.tagLength : 0; - const tagLengthIfEncrypting = fn === 'encrypt' ? mode.tagLength : 0; - const chunkSize = 2 ** (this.chunkSizeByte + 6) + tagLengthIfDecrypting; // ((uint64_t)1 << (c + 6)) - const adataBuffer = new ArrayBuffer(21); - const adataArray = new Uint8Array(adataBuffer, 0, 13); - const adataTagArray = new Uint8Array(adataBuffer); - const adataView = new DataView(adataBuffer); - const chunkIndexArray = new Uint8Array(adataBuffer, 5, 8); - adataArray.set([0xC0 | AEADEncryptedDataPacket.tag, this.version, this.cipherAlgorithm, this.aeadAlgorithm, this.chunkSizeByte], 0); - let chunkIndex = 0; - let latestPromise = Promise.resolve(); - let cryptedBytes = 0; - let queuedBytes = 0; - const iv = this.iv; - return transformPair(data, async (readable, writable) => { - if (util.isStream(readable) !== 'array') { - const buffer = new TransformStream({}, { - highWaterMark: util.getHardwareConcurrency() * 2 ** (this.chunkSizeByte + 6), - size: array => array.length - }); - pipe(buffer.readable, writable); - writable = buffer.writable; - } - const reader = getReader(readable); - const writer = getWriter(writable); - try { - while (true) { - let chunk = await reader.readBytes(chunkSize + tagLengthIfDecrypting) || new Uint8Array(); - const finalChunk = chunk.subarray(chunk.length - tagLengthIfDecrypting); - chunk = chunk.subarray(0, chunk.length - tagLengthIfDecrypting); - let cryptedPromise; - let done; - if (!chunkIndex || chunk.length) { - reader.unshift(finalChunk); - cryptedPromise = modeInstance[fn](chunk, mode.getNonce(iv, chunkIndexArray), adataArray); - queuedBytes += chunk.length - tagLengthIfDecrypting + tagLengthIfEncrypting; - } else { - // After the last chunk, we either encrypt a final, empty - // data chunk to get the final authentication tag or - // validate that final authentication tag. - adataView.setInt32(13 + 4, cryptedBytes); // Should be setInt64(13, ...) - cryptedPromise = modeInstance[fn](finalChunk, mode.getNonce(iv, chunkIndexArray), adataTagArray); - queuedBytes += tagLengthIfEncrypting; - done = true; - } - cryptedBytes += chunk.length - tagLengthIfDecrypting; - // eslint-disable-next-line no-loop-func - latestPromise = latestPromise.then(() => cryptedPromise).then(async crypted => { - await writer.ready; - await writer.write(crypted); - queuedBytes -= crypted.length; - }).catch(err => writer.abort(err)); - if (done || queuedBytes > writer.desiredSize) { - await latestPromise; // Respect backpressure - } - if (!done) { - adataView.setInt32(5 + 4, ++chunkIndex); // Should be setInt64(5, ...) - } else { - await writer.close(); - break; - } - } - } catch (e) { - await writer.abort(e); - } - }); - } - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - const VERSION$3 = 3; - - /** - * Public-Key Encrypted Session Key Packets (Tag 1) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.1|RFC4880 5.1}: - * A Public-Key Encrypted Session Key packet holds the session key - * used to encrypt a message. Zero or more Public-Key Encrypted Session Key - * packets and/or Symmetric-Key Encrypted Session Key packets may precede a - * Symmetrically Encrypted Data Packet, which holds an encrypted message. The - * message is encrypted with the session key, and the session key is itself - * encrypted and stored in the Encrypted Session Key packet(s). The - * Symmetrically Encrypted Data Packet is preceded by one Public-Key Encrypted - * Session Key packet for each OpenPGP key to which the message is encrypted. - * The recipient of the message finds a session key that is encrypted to their - * public key, decrypts the session key, and then uses the session key to - * decrypt the message. - */ - class PublicKeyEncryptedSessionKeyPacket { - static get tag() { - return enums.packet.publicKeyEncryptedSessionKey; - } - - constructor() { - this.version = 3; - - this.publicKeyID = new KeyID(); - this.publicKeyAlgorithm = null; - - this.sessionKey = null; - /** - * Algorithm to encrypt the message with - * @type {enums.symmetric} - */ - this.sessionKeyAlgorithm = null; - - /** @type {Object} */ - this.encrypted = {}; - } - - /** - * Parsing function for a publickey encrypted session key packet (tag 1). - * - * @param {Uint8Array} bytes - Payload of a tag 1 packet - */ - read(bytes) { - this.version = bytes[0]; - if (this.version !== VERSION$3) { - throw new UnsupportedError(`Version ${this.version} of the PKESK packet is unsupported.`); - } - this.publicKeyID.read(bytes.subarray(1, bytes.length)); - this.publicKeyAlgorithm = bytes[9]; - this.encrypted = mod.parseEncSessionKeyParams(this.publicKeyAlgorithm, bytes.subarray(10)); - } - - /** - * Create a binary representation of a tag 1 packet - * - * @returns {Uint8Array} The Uint8Array representation. - */ - write() { - const arr = [ - new Uint8Array([this.version]), - this.publicKeyID.write(), - new Uint8Array([this.publicKeyAlgorithm]), - mod.serializeParams(this.publicKeyAlgorithm, this.encrypted) - ]; - - return util.concatUint8Array(arr); - } - - /** - * Encrypt session key packet - * @param {PublicKeyPacket} key - Public key - * @throws {Error} if encryption failed - * @async - */ - async encrypt(key) { - const data = util.concatUint8Array([ - new Uint8Array([enums.write(enums.symmetric, this.sessionKeyAlgorithm)]), - this.sessionKey, - util.writeChecksum(this.sessionKey) - ]); - const algo = enums.write(enums.publicKey, this.publicKeyAlgorithm); - this.encrypted = await mod.publicKeyEncrypt( - algo, key.publicParams, data, key.getFingerprintBytes()); - } - - /** - * Decrypts the session key (only for public key encrypted session key packets (tag 1) - * @param {SecretKeyPacket} key - decrypted private key - * @param {Object} [randomSessionKey] - Bogus session key to use in case of sensitive decryption error, or if the decrypted session key is of a different type/size. - * This is needed for constant-time processing. Expected object of the form: { sessionKey: Uint8Array, sessionKeyAlgorithm: enums.symmetric } - * @throws {Error} if decryption failed, unless `randomSessionKey` is given - * @async - */ - async decrypt(key, randomSessionKey) { - // check that session key algo matches the secret key algo - if (this.publicKeyAlgorithm !== key.algorithm) { - throw new Error('Decryption error'); - } - - const randomPayload = randomSessionKey ? util.concatUint8Array([ - new Uint8Array([randomSessionKey.sessionKeyAlgorithm]), - randomSessionKey.sessionKey, - util.writeChecksum(randomSessionKey.sessionKey) - ]) : null; - const decoded = await mod.publicKeyDecrypt(this.publicKeyAlgorithm, key.publicParams, key.privateParams, this.encrypted, key.getFingerprintBytes(), randomPayload); - const symmetricAlgoByte = decoded[0]; - const sessionKey = decoded.subarray(1, decoded.length - 2); - const checksum = decoded.subarray(decoded.length - 2); - const computedChecksum = util.writeChecksum(sessionKey); - const isValidChecksum = computedChecksum[0] === checksum[0] & computedChecksum[1] === checksum[1]; - - if (randomSessionKey) { - // We must not leak info about the validity of the decrypted checksum or cipher algo. - // The decrypted session key must be of the same algo and size as the random session key, otherwise we discard it and use the random data. - const isValidPayload = isValidChecksum & symmetricAlgoByte === randomSessionKey.sessionKeyAlgorithm & sessionKey.length === randomSessionKey.sessionKey.length; - this.sessionKeyAlgorithm = util.selectUint8(isValidPayload, symmetricAlgoByte, randomSessionKey.sessionKeyAlgorithm); - this.sessionKey = util.selectUint8Array(isValidPayload, sessionKey, randomSessionKey.sessionKey); - - } else { - const isValidPayload = isValidChecksum && enums.read(enums.symmetric, symmetricAlgoByte); - if (isValidPayload) { - this.sessionKey = sessionKey; - this.sessionKeyAlgorithm = symmetricAlgoByte; - } else { - throw new Error('Decryption error'); - } - } - } - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - class S2K { - /** - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - constructor(config = defaultConfig) { - /** - * Hash function identifier, or 0 for gnu-dummy keys - * @type {module:enums.hash | 0} - */ - this.algorithm = enums.hash.sha256; - /** - * enums.s2k identifier or 'gnu-dummy' - * @type {String} - */ - this.type = 'iterated'; - /** @type {Integer} */ - this.c = config.s2kIterationCountByte; - /** Eight bytes of salt in a binary string. - * @type {Uint8Array} - */ - this.salt = null; - } - - getCount() { - // Exponent bias, defined in RFC4880 - const expbias = 6; - - return (16 + (this.c & 15)) << ((this.c >> 4) + expbias); - } - - /** - * Parsing function for a string-to-key specifier ({@link https://tools.ietf.org/html/rfc4880#section-3.7|RFC 4880 3.7}). - * @param {Uint8Array} bytes - Payload of string-to-key specifier - * @returns {Integer} Actual length of the object. - */ - read(bytes) { - let i = 0; - this.type = enums.read(enums.s2k, bytes[i++]); - this.algorithm = bytes[i++]; - - switch (this.type) { - case 'simple': - break; - - case 'salted': - this.salt = bytes.subarray(i, i + 8); - i += 8; - break; - - case 'iterated': - this.salt = bytes.subarray(i, i + 8); - i += 8; - - // Octet 10: count, a one-octet, coded value - this.c = bytes[i++]; - break; - - case 'gnu': - if (util.uint8ArrayToString(bytes.subarray(i, i + 3)) === 'GNU') { - i += 3; // GNU - const gnuExtType = 1000 + bytes[i++]; - if (gnuExtType === 1001) { - this.type = 'gnu-dummy'; - // GnuPG extension mode 1001 -- don't write secret key at all - } else { - throw new Error('Unknown s2k gnu protection mode.'); - } - } else { - throw new Error('Unknown s2k type.'); - } - break; - - default: - throw new Error('Unknown s2k type.'); - } - - return i; - } - - /** - * Serializes s2k information - * @returns {Uint8Array} Binary representation of s2k. - */ - write() { - if (this.type === 'gnu-dummy') { - return new Uint8Array([101, 0, ...util.stringToUint8Array('GNU'), 1]); - } - const arr = [new Uint8Array([enums.write(enums.s2k, this.type), this.algorithm])]; - - switch (this.type) { - case 'simple': - break; - case 'salted': - arr.push(this.salt); - break; - case 'iterated': - arr.push(this.salt); - arr.push(new Uint8Array([this.c])); - break; - case 'gnu': - throw new Error('GNU s2k type not supported.'); - default: - throw new Error('Unknown s2k type.'); - } - - return util.concatUint8Array(arr); - } - - /** - * Produces a key using the specified passphrase and the defined - * hashAlgorithm - * @param {String} passphrase - Passphrase containing user input - * @returns {Promise} Produced key with a length corresponding to. - * hashAlgorithm hash length - * @async - */ - async produceKey(passphrase, numBytes) { - passphrase = util.encodeUTF8(passphrase); - - const arr = []; - let rlength = 0; - - let prefixlen = 0; - while (rlength < numBytes) { - let toHash; - switch (this.type) { - case 'simple': - toHash = util.concatUint8Array([new Uint8Array(prefixlen), passphrase]); - break; - case 'salted': - toHash = util.concatUint8Array([new Uint8Array(prefixlen), this.salt, passphrase]); - break; - case 'iterated': { - const data = util.concatUint8Array([this.salt, passphrase]); - let datalen = data.length; - const count = Math.max(this.getCount(), datalen); - toHash = new Uint8Array(prefixlen + count); - toHash.set(data, prefixlen); - for (let pos = prefixlen + datalen; pos < count; pos += datalen, datalen *= 2) { - toHash.copyWithin(pos, prefixlen, pos); - } - break; - } - case 'gnu': - throw new Error('GNU s2k type not supported.'); - default: - throw new Error('Unknown s2k type.'); - } - const result = await mod.hash.digest(this.algorithm, toHash); - arr.push(result); - rlength += result.length; - prefixlen++; - } - - return util.concatUint8Array(arr).subarray(0, numBytes); - } - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - /** - * Symmetric-Key Encrypted Session Key Packets (Tag 3) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.3|RFC4880 5.3}: - * The Symmetric-Key Encrypted Session Key packet holds the - * symmetric-key encryption of a session key used to encrypt a message. - * Zero or more Public-Key Encrypted Session Key packets and/or - * Symmetric-Key Encrypted Session Key packets may precede a - * Symmetrically Encrypted Data packet that holds an encrypted message. - * The message is encrypted with a session key, and the session key is - * itself encrypted and stored in the Encrypted Session Key packet or - * the Symmetric-Key Encrypted Session Key packet. - */ - class SymEncryptedSessionKeyPacket { - static get tag() { - return enums.packet.symEncryptedSessionKey; - } - - /** - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - constructor(config = defaultConfig) { - this.version = config.aeadProtect ? 5 : 4; - this.sessionKey = null; - /** - * Algorithm to encrypt the session key with - * @type {enums.symmetric} - */ - this.sessionKeyEncryptionAlgorithm = null; - /** - * Algorithm to encrypt the message with - * @type {enums.symmetric} - */ - this.sessionKeyAlgorithm = enums.symmetric.aes256; - /** - * AEAD mode to encrypt the session key with (if AEAD protection is enabled) - * @type {enums.aead} - */ - this.aeadAlgorithm = enums.write(enums.aead, config.preferredAEADAlgorithm); - this.encrypted = null; - this.s2k = null; - this.iv = null; - } - - /** - * Parsing function for a symmetric encrypted session key packet (tag 3). - * - * @param {Uint8Array} bytes - Payload of a tag 3 packet - */ - read(bytes) { - let offset = 0; - - // A one-octet version number. The only currently defined version is 4. - this.version = bytes[offset++]; - if (this.version !== 4 && this.version !== 5) { - throw new UnsupportedError(`Version ${this.version} of the SKESK packet is unsupported.`); - } - - // A one-octet number describing the symmetric algorithm used. - const algo = bytes[offset++]; - - if (this.version === 5) { - // A one-octet AEAD algorithm. - this.aeadAlgorithm = bytes[offset++]; - } - - // A string-to-key (S2K) specifier, length as defined above. - this.s2k = new S2K(); - offset += this.s2k.read(bytes.subarray(offset, bytes.length)); - - if (this.version === 5) { - const mode = mod.getAEADMode(this.aeadAlgorithm); - - // A starting initialization vector of size specified by the AEAD - // algorithm. - this.iv = bytes.subarray(offset, offset += mode.ivLength); - } - - // The encrypted session key itself, which is decrypted with the - // string-to-key object. This is optional in version 4. - if (this.version === 5 || offset < bytes.length) { - this.encrypted = bytes.subarray(offset, bytes.length); - this.sessionKeyEncryptionAlgorithm = algo; - } else { - this.sessionKeyAlgorithm = algo; - } - } - - /** - * Create a binary representation of a tag 3 packet - * - * @returns {Uint8Array} The Uint8Array representation. - */ - write() { - const algo = this.encrypted === null ? - this.sessionKeyAlgorithm : - this.sessionKeyEncryptionAlgorithm; - - let bytes; - - if (this.version === 5) { - bytes = util.concatUint8Array([new Uint8Array([this.version, algo, this.aeadAlgorithm]), this.s2k.write(), this.iv, this.encrypted]); - } else { - bytes = util.concatUint8Array([new Uint8Array([this.version, algo]), this.s2k.write()]); - - if (this.encrypted !== null) { - bytes = util.concatUint8Array([bytes, this.encrypted]); - } - } - - return bytes; - } - - /** - * Decrypts the session key with the given passphrase - * @param {String} passphrase - The passphrase in string form - * @throws {Error} if decryption was not successful - * @async - */ - async decrypt(passphrase) { - const algo = this.sessionKeyEncryptionAlgorithm !== null ? - this.sessionKeyEncryptionAlgorithm : - this.sessionKeyAlgorithm; - - const { blockSize, keySize } = mod.getCipher(algo); - const key = await this.s2k.produceKey(passphrase, keySize); - - if (this.version === 5) { - const mode = mod.getAEADMode(this.aeadAlgorithm); - const adata = new Uint8Array([0xC0 | SymEncryptedSessionKeyPacket.tag, this.version, this.sessionKeyEncryptionAlgorithm, this.aeadAlgorithm]); - const modeInstance = await mode(algo, key); - this.sessionKey = await modeInstance.decrypt(this.encrypted, this.iv, adata); - } else if (this.encrypted !== null) { - const decrypted = await mod.mode.cfb.decrypt(algo, key, this.encrypted, new Uint8Array(blockSize)); - - this.sessionKeyAlgorithm = enums.write(enums.symmetric, decrypted[0]); - this.sessionKey = decrypted.subarray(1, decrypted.length); - } else { - this.sessionKey = key; - } - } - - /** - * Encrypts the session key with the given passphrase - * @param {String} passphrase - The passphrase in string form - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if encryption was not successful - * @async - */ - async encrypt(passphrase, config = defaultConfig) { - const algo = this.sessionKeyEncryptionAlgorithm !== null ? - this.sessionKeyEncryptionAlgorithm : - this.sessionKeyAlgorithm; - - this.sessionKeyEncryptionAlgorithm = algo; - - this.s2k = new S2K(config); - this.s2k.salt = await mod.random.getRandomBytes(8); - - const { blockSize, keySize } = mod.getCipher(algo); - const encryptionKey = await this.s2k.produceKey(passphrase, keySize); - - if (this.sessionKey === null) { - this.sessionKey = await mod.generateSessionKey(this.sessionKeyAlgorithm); - } - - if (this.version === 5) { - const mode = mod.getAEADMode(this.aeadAlgorithm); - this.iv = await mod.random.getRandomBytes(mode.ivLength); // generate new random IV - const associatedData = new Uint8Array([0xC0 | SymEncryptedSessionKeyPacket.tag, this.version, this.sessionKeyEncryptionAlgorithm, this.aeadAlgorithm]); - const modeInstance = await mode(algo, encryptionKey); - this.encrypted = await modeInstance.encrypt(this.sessionKey, this.iv, associatedData); - } else { - const toEncrypt = util.concatUint8Array([ - new Uint8Array([this.sessionKeyAlgorithm]), - this.sessionKey - ]); - this.encrypted = await mod.mode.cfb.encrypt(algo, encryptionKey, toEncrypt, new Uint8Array(blockSize), config); - } - } - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - /** - * Implementation of the Key Material Packet (Tag 5,6,7,14) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.5|RFC4480 5.5}: - * A key material packet contains all the information about a public or - * private key. There are four variants of this packet type, and two - * major versions. - * - * A Public-Key packet starts a series of packets that forms an OpenPGP - * key (sometimes called an OpenPGP certificate). - */ - class PublicKeyPacket { - static get tag() { - return enums.packet.publicKey; - } - - /** - * @param {Date} [date] - Creation date - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - constructor(date = new Date(), config = defaultConfig) { - /** - * Packet version - * @type {Integer} - */ - this.version = config.v5Keys ? 5 : 4; - /** - * Key creation date. - * @type {Date} - */ - this.created = util.normalizeDate(date); - /** - * Public key algorithm. - * @type {enums.publicKey} - */ - this.algorithm = null; - /** - * Algorithm specific public params - * @type {Object} - */ - this.publicParams = null; - /** - * Time until expiration in days (V3 only) - * @type {Integer} - */ - this.expirationTimeV3 = 0; - /** - * Fingerprint bytes - * @type {Uint8Array} - */ - this.fingerprint = null; - /** - * KeyID - * @type {module:type/keyid~KeyID} - */ - this.keyID = null; - } - - /** - * Create a PublicKeyPacket from a SecretKeyPacket - * @param {SecretKeyPacket} secretKeyPacket - key packet to convert - * @returns {PublicKeyPacket} public key packet - * @static - */ - static fromSecretKeyPacket(secretKeyPacket) { - const keyPacket = new PublicKeyPacket(); - const { version, created, algorithm, publicParams, keyID, fingerprint } = secretKeyPacket; - keyPacket.version = version; - keyPacket.created = created; - keyPacket.algorithm = algorithm; - keyPacket.publicParams = publicParams; - keyPacket.keyID = keyID; - keyPacket.fingerprint = fingerprint; - return keyPacket; - } - - /** - * Internal Parser for public keys as specified in {@link https://tools.ietf.org/html/rfc4880#section-5.5.2|RFC 4880 section 5.5.2 Public-Key Packet Formats} - * @param {Uint8Array} bytes - Input array to read the packet from - * @returns {Object} This object with attributes set by the parser - * @async - */ - async read(bytes) { - let pos = 0; - // A one-octet version number (3, 4 or 5). - this.version = bytes[pos++]; - - if (this.version === 4 || this.version === 5) { - // - A four-octet number denoting the time that the key was created. - this.created = util.readDate(bytes.subarray(pos, pos + 4)); - pos += 4; - - // - A one-octet number denoting the public-key algorithm of this key. - this.algorithm = bytes[pos++]; - - if (this.version === 5) { - // - A four-octet scalar octet count for the following key material. - pos += 4; - } - - // - A series of values comprising the key material. - try { - const { read, publicParams } = mod.parsePublicKeyParams(this.algorithm, bytes.subarray(pos)); - this.publicParams = publicParams; - pos += read; - } catch (err) { - throw new Error('Error reading MPIs'); - } - - // we set the fingerprint and keyID already to make it possible to put together the key packets directly in the Key constructor - await this.computeFingerprintAndKeyID(); - return pos; - } - throw new UnsupportedError(`Version ${this.version} of the key packet is unsupported.`); - } - - /** - * Creates an OpenPGP public key packet for the given key. - * @returns {Uint8Array} Bytes encoding the public key OpenPGP packet. - */ - write() { - const arr = []; - // Version - arr.push(new Uint8Array([this.version])); - arr.push(util.writeDate(this.created)); - // A one-octet number denoting the public-key algorithm of this key - arr.push(new Uint8Array([this.algorithm])); - - const params = mod.serializeParams(this.algorithm, this.publicParams); - if (this.version === 5) { - // A four-octet scalar octet count for the following key material - arr.push(util.writeNumber(params.length, 4)); - } - // Algorithm-specific params - arr.push(params); - return util.concatUint8Array(arr); - } - - /** - * Write packet in order to be hashed; either for a signature or a fingerprint - * @param {Integer} version - target version of signature or key - */ - writeForHash(version) { - const bytes = this.writePublicKey(); - - if (version === 5) { - return util.concatUint8Array([new Uint8Array([0x9A]), util.writeNumber(bytes.length, 4), bytes]); - } - return util.concatUint8Array([new Uint8Array([0x99]), util.writeNumber(bytes.length, 2), bytes]); - } - - /** - * Check whether secret-key data is available in decrypted form. Returns null for public keys. - * @returns {Boolean|null} - */ - isDecrypted() { - return null; - } - - /** - * Returns the creation time of the key - * @returns {Date} - */ - getCreationTime() { - return this.created; - } - - /** - * Return the key ID of the key - * @returns {module:type/keyid~KeyID} The 8-byte key ID - */ - getKeyID() { - return this.keyID; - } - - /** - * Computes and set the key ID and fingerprint of the key - * @async - */ - async computeFingerprintAndKeyID() { - await this.computeFingerprint(); - this.keyID = new KeyID(); - - if (this.version === 5) { - this.keyID.read(this.fingerprint.subarray(0, 8)); - } else if (this.version === 4) { - this.keyID.read(this.fingerprint.subarray(12, 20)); - } else { - throw new Error('Unsupported key version'); - } - } - - /** - * Computes and set the fingerprint of the key - */ - async computeFingerprint() { - const toHash = this.writeForHash(this.version); - - if (this.version === 5) { - this.fingerprint = await mod.hash.sha256(toHash); - } else if (this.version === 4) { - this.fingerprint = await mod.hash.sha1(toHash); - } else { - throw new Error('Unsupported key version'); - } - } - - /** - * Returns the fingerprint of the key, as an array of bytes - * @returns {Uint8Array} A Uint8Array containing the fingerprint - */ - getFingerprintBytes() { - return this.fingerprint; - } - - /** - * Calculates and returns the fingerprint of the key, as a string - * @returns {String} A string containing the fingerprint in lowercase hex - */ - getFingerprint() { - return util.uint8ArrayToHex(this.getFingerprintBytes()); - } - - /** - * Calculates whether two keys have the same fingerprint without actually calculating the fingerprint - * @returns {Boolean} Whether the two keys have the same version and public key data. - */ - hasSameFingerprintAs(other) { - return this.version === other.version && util.equalsUint8Array(this.writePublicKey(), other.writePublicKey()); - } - - /** - * Returns algorithm information - * @returns {Object} An object of the form {algorithm: String, bits:int, curve:String}. - */ - getAlgorithmInfo() { - const result = {}; - result.algorithm = enums.read(enums.publicKey, this.algorithm); - // RSA, DSA or ElGamal public modulo - const modulo = this.publicParams.n || this.publicParams.p; - if (modulo) { - result.bits = util.uint8ArrayBitLength(modulo); - } else { - result.curve = this.publicParams.oid.getName(); - } - return result; - } - } - - /** - * Alias of read() - * @see PublicKeyPacket#read - */ - PublicKeyPacket.prototype.readPublicKey = PublicKeyPacket.prototype.read; - - /** - * Alias of write() - * @see PublicKeyPacket#write - */ - PublicKeyPacket.prototype.writePublicKey = PublicKeyPacket.prototype.write; - - // GPG4Browsers - An OpenPGP implementation in javascript - - // A SE packet can contain the following packet types - const allowedPackets$3 = /*#__PURE__*/ util.constructAllowedPackets([ - LiteralDataPacket, - CompressedDataPacket, - OnePassSignaturePacket, - SignaturePacket - ]); - - /** - * Implementation of the Symmetrically Encrypted Data Packet (Tag 9) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.7|RFC4880 5.7}: - * The Symmetrically Encrypted Data packet contains data encrypted with a - * symmetric-key algorithm. When it has been decrypted, it contains other - * packets (usually a literal data packet or compressed data packet, but in - * theory other Symmetrically Encrypted Data packets or sequences of packets - * that form whole OpenPGP messages). - */ - class SymmetricallyEncryptedDataPacket { - static get tag() { - return enums.packet.symmetricallyEncryptedData; - } - - constructor() { - /** - * Encrypted secret-key data - */ - this.encrypted = null; - /** - * Decrypted packets contained within. - * @type {PacketList} - */ - this.packets = null; - } - - read(bytes) { - this.encrypted = bytes; - } - - write() { - return this.encrypted; - } - - /** - * Decrypt the symmetrically-encrypted packet data - * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. - * @param {module:enums.symmetric} sessionKeyAlgorithm - Symmetric key algorithm to use - * @param {Uint8Array} key - The key of cipher blocksize length to be used - * @param {Object} [config] - Full configuration, defaults to openpgp.config - - * @throws {Error} if decryption was not successful - * @async - */ - async decrypt(sessionKeyAlgorithm, key, config = defaultConfig) { - // If MDC errors are not being ignored, all missing MDC packets in symmetrically encrypted data should throw an error - if (!config.allowUnauthenticatedMessages) { - throw new Error('Message is not authenticated.'); - } - - const { blockSize } = mod.getCipher(sessionKeyAlgorithm); - const encrypted = await readToEnd(clone(this.encrypted)); - const decrypted = await mod.mode.cfb.decrypt(sessionKeyAlgorithm, key, - encrypted.subarray(blockSize + 2), - encrypted.subarray(2, blockSize + 2) - ); - - this.packets = await PacketList.fromBinary(decrypted, allowedPackets$3, config); - } - - /** - * Encrypt the symmetrically-encrypted packet data - * See {@link https://tools.ietf.org/html/rfc4880#section-9.2|RFC 4880 9.2} for algorithms. - * @param {module:enums.symmetric} sessionKeyAlgorithm - Symmetric key algorithm to use - * @param {Uint8Array} key - The key of cipher blocksize length to be used - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if encryption was not successful - * @async - */ - async encrypt(sessionKeyAlgorithm, key, config = defaultConfig) { - const data = this.packets.write(); - const { blockSize } = mod.getCipher(sessionKeyAlgorithm); - - const prefix = await mod.getPrefixRandom(sessionKeyAlgorithm); - const FRE = await mod.mode.cfb.encrypt(sessionKeyAlgorithm, key, prefix, new Uint8Array(blockSize), config); - const ciphertext = await mod.mode.cfb.encrypt(sessionKeyAlgorithm, key, data, FRE.subarray(2), config); - this.encrypted = util.concat([FRE, ciphertext]); - } - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - /** - * Implementation of the strange "Marker packet" (Tag 10) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.8|RFC4880 5.8}: - * An experimental version of PGP used this packet as the Literal - * packet, but no released version of PGP generated Literal packets with this - * tag. With PGP 5.x, this packet has been reassigned and is reserved for use as - * the Marker packet. - * - * The body of this packet consists of: - * The three octets 0x50, 0x47, 0x50 (which spell "PGP" in UTF-8). - * - * Such a packet MUST be ignored when received. It may be placed at the - * beginning of a message that uses features not available in PGP - * version 2.6 in order to cause that version to report that newer - * software is necessary to process the message. - */ - class MarkerPacket { - static get tag() { - return enums.packet.marker; - } - - /** - * Parsing function for a marker data packet (tag 10). - * @param {Uint8Array} bytes - Payload of a tag 10 packet - * @returns {Boolean} whether the packet payload contains "PGP" - */ - read(bytes) { - if (bytes[0] === 0x50 && // P - bytes[1] === 0x47 && // G - bytes[2] === 0x50) { // P - return true; - } - return false; - } - - write() { - return new Uint8Array([0x50, 0x47, 0x50]); - } - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - /** - * A Public-Subkey packet (tag 14) has exactly the same format as a - * Public-Key packet, but denotes a subkey. One or more subkeys may be - * associated with a top-level key. By convention, the top-level key - * provides signature services, and the subkeys provide encryption - * services. - * @extends PublicKeyPacket - */ - class PublicSubkeyPacket extends PublicKeyPacket { - static get tag() { - return enums.packet.publicSubkey; - } - - /** - * @param {Date} [date] - Creation date - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - // eslint-disable-next-line no-useless-constructor - constructor(date, config) { - super(date, config); - } - - /** - * Create a PublicSubkeyPacket from a SecretSubkeyPacket - * @param {SecretSubkeyPacket} secretSubkeyPacket - subkey packet to convert - * @returns {SecretSubkeyPacket} public key packet - * @static - */ - static fromSecretSubkeyPacket(secretSubkeyPacket) { - const keyPacket = new PublicSubkeyPacket(); - const { version, created, algorithm, publicParams, keyID, fingerprint } = secretSubkeyPacket; - keyPacket.version = version; - keyPacket.created = created; - keyPacket.algorithm = algorithm; - keyPacket.publicParams = publicParams; - keyPacket.keyID = keyID; - keyPacket.fingerprint = fingerprint; - return keyPacket; - } - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - /** - * Implementation of the User Attribute Packet (Tag 17) - * - * The User Attribute packet is a variation of the User ID packet. It - * is capable of storing more types of data than the User ID packet, - * which is limited to text. Like the User ID packet, a User Attribute - * packet may be certified by the key owner ("self-signed") or any other - * key owner who cares to certify it. Except as noted, a User Attribute - * packet may be used anywhere that a User ID packet may be used. - * - * While User Attribute packets are not a required part of the OpenPGP - * standard, implementations SHOULD provide at least enough - * compatibility to properly handle a certification signature on the - * User Attribute packet. A simple way to do this is by treating the - * User Attribute packet as a User ID packet with opaque contents, but - * an implementation may use any method desired. - */ - class UserAttributePacket { - static get tag() { - return enums.packet.userAttribute; - } - - constructor() { - this.attributes = []; - } - - /** - * parsing function for a user attribute packet (tag 17). - * @param {Uint8Array} input - Payload of a tag 17 packet - */ - read(bytes) { - let i = 0; - while (i < bytes.length) { - const len = readSimpleLength(bytes.subarray(i, bytes.length)); - i += len.offset; - - this.attributes.push(util.uint8ArrayToString(bytes.subarray(i, i + len.len))); - i += len.len; - } - } - - /** - * Creates a binary representation of the user attribute packet - * @returns {Uint8Array} String representation. - */ - write() { - const arr = []; - for (let i = 0; i < this.attributes.length; i++) { - arr.push(writeSimpleLength(this.attributes[i].length)); - arr.push(util.stringToUint8Array(this.attributes[i])); - } - return util.concatUint8Array(arr); - } - - /** - * Compare for equality - * @param {UserAttributePacket} usrAttr - * @returns {Boolean} True if equal. - */ - equals(usrAttr) { - if (!usrAttr || !(usrAttr instanceof UserAttributePacket)) { - return false; - } - return this.attributes.every(function(attr, index) { - return attr === usrAttr.attributes[index]; - }); - } - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - /** - * A Secret-Key packet contains all the information that is found in a - * Public-Key packet, including the public-key material, but also - * includes the secret-key material after all the public-key fields. - * @extends PublicKeyPacket - */ - class SecretKeyPacket extends PublicKeyPacket { - static get tag() { - return enums.packet.secretKey; - } - - /** - * @param {Date} [date] - Creation date - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - constructor(date = new Date(), config = defaultConfig) { - super(date, config); - /** - * Secret-key data - */ - this.keyMaterial = null; - /** - * Indicates whether secret-key data is encrypted. `this.isEncrypted === false` means data is available in decrypted form. - */ - this.isEncrypted = null; - /** - * S2K usage - * @type {enums.symmetric} - */ - this.s2kUsage = 0; - /** - * S2K object - * @type {type/s2k} - */ - this.s2k = null; - /** - * Symmetric algorithm to encrypt the key with - * @type {enums.symmetric} - */ - this.symmetric = null; - /** - * AEAD algorithm to encrypt the key with (if AEAD protection is enabled) - * @type {enums.aead} - */ - this.aead = null; - /** - * Decrypted private parameters, referenced by name - * @type {Object} - */ - this.privateParams = null; - } - - // 5.5.3. Secret-Key Packet Formats - - /** - * Internal parser for private keys as specified in - * {@link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-04#section-5.5.3|RFC4880bis-04 section 5.5.3} - * @param {Uint8Array} bytes - Input string to read the packet from - * @async - */ - async read(bytes) { - // - A Public-Key or Public-Subkey packet, as described above. - let i = await this.readPublicKey(bytes); - - // - One octet indicating string-to-key usage conventions. Zero - // indicates that the secret-key data is not encrypted. 255 or 254 - // indicates that a string-to-key specifier is being given. Any - // other value is a symmetric-key encryption algorithm identifier. - this.s2kUsage = bytes[i++]; - - // - Only for a version 5 packet, a one-octet scalar octet count of - // the next 4 optional fields. - if (this.version === 5) { - i++; - } - - // - [Optional] If string-to-key usage octet was 255, 254, or 253, a - // one-octet symmetric encryption algorithm. - if (this.s2kUsage === 255 || this.s2kUsage === 254 || this.s2kUsage === 253) { - this.symmetric = bytes[i++]; - - // - [Optional] If string-to-key usage octet was 253, a one-octet - // AEAD algorithm. - if (this.s2kUsage === 253) { - this.aead = bytes[i++]; - } - - // - [Optional] If string-to-key usage octet was 255, 254, or 253, a - // string-to-key specifier. The length of the string-to-key - // specifier is implied by its type, as described above. - this.s2k = new S2K(); - i += this.s2k.read(bytes.subarray(i, bytes.length)); - - if (this.s2k.type === 'gnu-dummy') { - return; - } - } else if (this.s2kUsage) { - this.symmetric = this.s2kUsage; - } - - // - [Optional] If secret data is encrypted (string-to-key usage octet - // not zero), an Initial Vector (IV) of the same length as the - // cipher's block size. - if (this.s2kUsage) { - this.iv = bytes.subarray( - i, - i + mod.getCipher(this.symmetric).blockSize - ); - - i += this.iv.length; - } - - // - Only for a version 5 packet, a four-octet scalar octet count for - // the following key material. - if (this.version === 5) { - i += 4; - } - - // - Plain or encrypted multiprecision integers comprising the secret - // key data. These algorithm-specific fields are as described - // below. - this.keyMaterial = bytes.subarray(i); - this.isEncrypted = !!this.s2kUsage; - - if (!this.isEncrypted) { - const cleartext = this.keyMaterial.subarray(0, -2); - if (!util.equalsUint8Array(util.writeChecksum(cleartext), this.keyMaterial.subarray(-2))) { - throw new Error('Key checksum mismatch'); - } - try { - const { privateParams } = mod.parsePrivateKeyParams(this.algorithm, cleartext, this.publicParams); - this.privateParams = privateParams; - } catch (err) { - throw new Error('Error reading MPIs'); - } - } - } - - /** - * Creates an OpenPGP key packet for the given key. - * @returns {Uint8Array} A string of bytes containing the secret key OpenPGP packet. - */ - write() { - const arr = [this.writePublicKey()]; - - arr.push(new Uint8Array([this.s2kUsage])); - - const optionalFieldsArr = []; - // - [Optional] If string-to-key usage octet was 255, 254, or 253, a - // one- octet symmetric encryption algorithm. - if (this.s2kUsage === 255 || this.s2kUsage === 254 || this.s2kUsage === 253) { - optionalFieldsArr.push(this.symmetric); - - // - [Optional] If string-to-key usage octet was 253, a one-octet - // AEAD algorithm. - if (this.s2kUsage === 253) { - optionalFieldsArr.push(this.aead); - } - - // - [Optional] If string-to-key usage octet was 255, 254, or 253, a - // string-to-key specifier. The length of the string-to-key - // specifier is implied by its type, as described above. - optionalFieldsArr.push(...this.s2k.write()); - } - - // - [Optional] If secret data is encrypted (string-to-key usage octet - // not zero), an Initial Vector (IV) of the same length as the - // cipher's block size. - if (this.s2kUsage && this.s2k.type !== 'gnu-dummy') { - optionalFieldsArr.push(...this.iv); - } - - if (this.version === 5) { - arr.push(new Uint8Array([optionalFieldsArr.length])); - } - arr.push(new Uint8Array(optionalFieldsArr)); - - if (!this.isDummy()) { - if (!this.s2kUsage) { - this.keyMaterial = mod.serializeParams(this.algorithm, this.privateParams); - } - - if (this.version === 5) { - arr.push(util.writeNumber(this.keyMaterial.length, 4)); - } - arr.push(this.keyMaterial); - - if (!this.s2kUsage) { - arr.push(util.writeChecksum(this.keyMaterial)); - } - } - - return util.concatUint8Array(arr); - } - - /** - * Check whether secret-key data is available in decrypted form. - * Returns false for gnu-dummy keys and null for public keys. - * @returns {Boolean|null} - */ - isDecrypted() { - return this.isEncrypted === false; - } - - /** - * Check whether this is a gnu-dummy key - * @returns {Boolean} - */ - isDummy() { - return !!(this.s2k && this.s2k.type === 'gnu-dummy'); - } - - /** - * Remove private key material, converting the key to a dummy one. - * The resulting key cannot be used for signing/decrypting but can still verify signatures. - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - makeDummy(config = defaultConfig) { - if (this.isDummy()) { - return; - } - if (this.isDecrypted()) { - this.clearPrivateParams(); - } - this.isEncrypted = null; - this.keyMaterial = null; - this.s2k = new S2K(config); - this.s2k.algorithm = 0; - this.s2k.c = 0; - this.s2k.type = 'gnu-dummy'; - this.s2kUsage = 254; - this.symmetric = enums.symmetric.aes256; - } - - /** - * Encrypt the payload. By default, we use aes256 and iterated, salted string - * to key specifier. If the key is in a decrypted state (isEncrypted === false) - * and the passphrase is empty or undefined, the key will be set as not encrypted. - * This can be used to remove passphrase protection after calling decrypt(). - * @param {String} passphrase - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if encryption was not successful - * @async - */ - async encrypt(passphrase, config = defaultConfig) { - if (this.isDummy()) { - return; - } - - if (!this.isDecrypted()) { - throw new Error('Key packet is already encrypted'); - } - - if (this.isDecrypted() && !passphrase) { - this.s2kUsage = 0; - return; - } else if (!passphrase) { - throw new Error('The key must be decrypted before removing passphrase protection.'); - } - - this.s2k = new S2K(config); - this.s2k.salt = await mod.random.getRandomBytes(8); - const cleartext = mod.serializeParams(this.algorithm, this.privateParams); - this.symmetric = enums.symmetric.aes256; - const key = await produceEncryptionKey(this.s2k, passphrase, this.symmetric); - - const { blockSize } = mod.getCipher(this.symmetric); - this.iv = await mod.random.getRandomBytes(blockSize); - - if (config.aeadProtect) { - this.s2kUsage = 253; - this.aead = enums.aead.eax; - const mode = mod.getAEADMode(this.aead); - const modeInstance = await mode(this.symmetric, key); - this.keyMaterial = await modeInstance.encrypt(cleartext, this.iv.subarray(0, mode.ivLength), new Uint8Array()); - } else { - this.s2kUsage = 254; - this.keyMaterial = await mod.mode.cfb.encrypt(this.symmetric, key, util.concatUint8Array([ - cleartext, - await mod.hash.sha1(cleartext, config) - ]), this.iv, config); - } - } - - /** - * Decrypts the private key params which are needed to use the key. - * Successful decryption does not imply key integrity, call validate() to confirm that. - * {@link SecretKeyPacket.isDecrypted} should be false, as - * otherwise calls to this function will throw an error. - * @param {String} passphrase - The passphrase for this private key as string - * @throws {Error} if the key is already decrypted, or if decryption was not successful - * @async - */ - async decrypt(passphrase) { - if (this.isDummy()) { - return false; - } - - if (this.isDecrypted()) { - throw new Error('Key packet is already decrypted.'); - } - - let key; - if (this.s2kUsage === 254 || this.s2kUsage === 253) { - key = await produceEncryptionKey(this.s2k, passphrase, this.symmetric); - } else if (this.s2kUsage === 255) { - throw new Error('Encrypted private key is authenticated using an insecure two-byte hash'); - } else { - throw new Error('Private key is encrypted using an insecure S2K function: unsalted MD5'); - } - - let cleartext; - if (this.s2kUsage === 253) { - const mode = mod.getAEADMode(this.aead); - const modeInstance = await mode(this.symmetric, key); - try { - cleartext = await modeInstance.decrypt(this.keyMaterial, this.iv.subarray(0, mode.ivLength), new Uint8Array()); - } catch (err) { - if (err.message === 'Authentication tag mismatch') { - throw new Error('Incorrect key passphrase: ' + err.message); - } - throw err; - } - } else { - const cleartextWithHash = await mod.mode.cfb.decrypt(this.symmetric, key, this.keyMaterial, this.iv); - - cleartext = cleartextWithHash.subarray(0, -20); - const hash = await mod.hash.sha1(cleartext); - - if (!util.equalsUint8Array(hash, cleartextWithHash.subarray(-20))) { - throw new Error('Incorrect key passphrase'); - } - } - - try { - const { privateParams } = mod.parsePrivateKeyParams(this.algorithm, cleartext, this.publicParams); - this.privateParams = privateParams; - } catch (err) { - throw new Error('Error reading MPIs'); - } - this.isEncrypted = false; - this.keyMaterial = null; - this.s2kUsage = 0; - } - - /** - * Checks that the key parameters are consistent - * @throws {Error} if validation was not successful - * @async - */ - async validate() { - if (this.isDummy()) { - return; - } - - if (!this.isDecrypted()) { - throw new Error('Key is not decrypted'); - } - - let validParams; - try { - // this can throw if some parameters are undefined - validParams = await mod.validateParams(this.algorithm, this.publicParams, this.privateParams); - } catch (_) { - validParams = false; - } - if (!validParams) { - throw new Error('Key is invalid'); - } - } - - async generate(bits, curve) { - const { privateParams, publicParams } = await mod.generateParams(this.algorithm, bits, curve); - this.privateParams = privateParams; - this.publicParams = publicParams; - this.isEncrypted = false; - } - - /** - * Clear private key parameters - */ - clearPrivateParams() { - if (this.isDummy()) { - return; - } - - Object.keys(this.privateParams).forEach(name => { - const param = this.privateParams[name]; - param.fill(0); - delete this.privateParams[name]; - }); - this.privateParams = null; - this.isEncrypted = true; - } - } - - async function produceEncryptionKey(s2k, passphrase, algorithm) { - const { keySize } = mod.getCipher(algorithm); - return s2k.produceKey(passphrase, keySize); - } - - var emailAddresses = createCommonjsModule(function (module) { - // email-addresses.js - RFC 5322 email address parser - // v 3.1.0 - // - // http://tools.ietf.org/html/rfc5322 - // - // This library does not validate email addresses. - // emailAddresses attempts to parse addresses using the (fairly liberal) - // grammar specified in RFC 5322. - // - // email-addresses returns { - // ast: , - // addresses: [{ - // node: , - // name: , - // address: , - // local: , - // domain: - // }, ...] - // } - // - // emailAddresses.parseOneAddress and emailAddresses.parseAddressList - // work as you might expect. Try it out. - // - // Many thanks to Dominic Sayers and his documentation on the is_email function, - // http://code.google.com/p/isemail/ , which helped greatly in writing this parser. - - (function (global) { - - function parse5322(opts) { - - // tokenizing functions - - function inStr() { return pos < len; } - function curTok() { return parseString[pos]; } - function getPos() { return pos; } - function setPos(i) { pos = i; } - function nextTok() { pos += 1; } - function initialize() { - pos = 0; - len = parseString.length; - } - - // parser helper functions - - function o(name, value) { - return { - name: name, - tokens: value || "", - semantic: value || "", - children: [] - }; - } - - function wrap(name, ast) { - var n; - if (ast === null) { return null; } - n = o(name); - n.tokens = ast.tokens; - n.semantic = ast.semantic; - n.children.push(ast); - return n; - } - - function add(parent, child) { - if (child !== null) { - parent.tokens += child.tokens; - parent.semantic += child.semantic; - } - parent.children.push(child); - return parent; - } - - function compareToken(fxnCompare) { - var tok; - if (!inStr()) { return null; } - tok = curTok(); - if (fxnCompare(tok)) { - nextTok(); - return o('token', tok); - } - return null; - } - - function literal(lit) { - return function literalFunc() { - return wrap('literal', compareToken(function (tok) { - return tok === lit; - })); - }; - } - - function and() { - var args = arguments; - return function andFunc() { - var i, s, result, start; - start = getPos(); - s = o('and'); - for (i = 0; i < args.length; i += 1) { - result = args[i](); - if (result === null) { - setPos(start); - return null; - } - add(s, result); - } - return s; - }; - } - - function or() { - var args = arguments; - return function orFunc() { - var i, result, start; - start = getPos(); - for (i = 0; i < args.length; i += 1) { - result = args[i](); - if (result !== null) { - return result; - } - setPos(start); - } - return null; - }; - } - - function opt(prod) { - return function optFunc() { - var result, start; - start = getPos(); - result = prod(); - if (result !== null) { - return result; - } - else { - setPos(start); - return o('opt'); - } - }; - } - - function invis(prod) { - return function invisFunc() { - var result = prod(); - if (result !== null) { - result.semantic = ""; - } - return result; - }; - } - - function colwsp(prod) { - return function collapseSemanticWhitespace() { - var result = prod(); - if (result !== null && result.semantic.length > 0) { - result.semantic = " "; - } - return result; - }; - } - - function star(prod, minimum) { - return function starFunc() { - var s, result, count, start, min; - start = getPos(); - s = o('star'); - count = 0; - min = minimum === undefined ? 0 : minimum; - while ((result = prod()) !== null) { - count = count + 1; - add(s, result); - } - if (count >= min) { - return s; - } - else { - setPos(start); - return null; - } - }; - } - - // One expects names to get normalized like this: - // " First Last " -> "First Last" - // "First Last" -> "First Last" - // "First Last" -> "First Last" - function collapseWhitespace(s) { - return s.replace(/([ \t]|\r\n)+/g, ' ').replace(/^\s*/, '').replace(/\s*$/, ''); - } - - // UTF-8 pseudo-production (RFC 6532) - // RFC 6532 extends RFC 5322 productions to include UTF-8 - // using the following productions: - // UTF8-non-ascii = UTF8-2 / UTF8-3 / UTF8-4 - // UTF8-2 = - // UTF8-3 = - // UTF8-4 = - // - // For reference, the extended RFC 5322 productions are: - // VCHAR =/ UTF8-non-ascii - // ctext =/ UTF8-non-ascii - // atext =/ UTF8-non-ascii - // qtext =/ UTF8-non-ascii - // dtext =/ UTF8-non-ascii - function isUTF8NonAscii(tok) { - // In JavaScript, we just deal directly with Unicode code points, - // so we aren't checking individual bytes for UTF-8 encoding. - // Just check that the character is non-ascii. - return tok.charCodeAt(0) >= 128; - } - - - // common productions (RFC 5234) - // http://tools.ietf.org/html/rfc5234 - // B.1. Core Rules - - // CR = %x0D - // ; carriage return - function cr() { return wrap('cr', literal('\r')()); } - - // CRLF = CR LF - // ; Internet standard newline - function crlf() { return wrap('crlf', and(cr, lf)()); } - - // DQUOTE = %x22 - // ; " (Double Quote) - function dquote() { return wrap('dquote', literal('"')()); } - - // HTAB = %x09 - // ; horizontal tab - function htab() { return wrap('htab', literal('\t')()); } - - // LF = %x0A - // ; linefeed - function lf() { return wrap('lf', literal('\n')()); } - - // SP = %x20 - function sp() { return wrap('sp', literal(' ')()); } - - // VCHAR = %x21-7E - // ; visible (printing) characters - function vchar() { - return wrap('vchar', compareToken(function vcharFunc(tok) { - var code = tok.charCodeAt(0); - var accept = (0x21 <= code && code <= 0x7E); - if (opts.rfc6532) { - accept = accept || isUTF8NonAscii(tok); - } - return accept; - })); - } - - // WSP = SP / HTAB - // ; white space - function wsp() { return wrap('wsp', or(sp, htab)()); } - - - // email productions (RFC 5322) - // http://tools.ietf.org/html/rfc5322 - // 3.2.1. Quoted characters - - // quoted-pair = ("\" (VCHAR / WSP)) / obs-qp - function quotedPair() { - var qp = wrap('quoted-pair', - or( - and(literal('\\'), or(vchar, wsp)), - obsQP - )()); - if (qp === null) { return null; } - // a quoted pair will be two characters, and the "\" character - // should be semantically "invisible" (RFC 5322 3.2.1) - qp.semantic = qp.semantic[1]; - return qp; - } - - // 3.2.2. Folding White Space and Comments - - // FWS = ([*WSP CRLF] 1*WSP) / obs-FWS - function fws() { - return wrap('fws', or( - obsFws, - and( - opt(and( - star(wsp), - invis(crlf) - )), - star(wsp, 1) - ) - )()); - } - - // ctext = %d33-39 / ; Printable US-ASCII - // %d42-91 / ; characters not including - // %d93-126 / ; "(", ")", or "\" - // obs-ctext - function ctext() { - return wrap('ctext', or( - function ctextFunc1() { - return compareToken(function ctextFunc2(tok) { - var code = tok.charCodeAt(0); - var accept = - (33 <= code && code <= 39) || - (42 <= code && code <= 91) || - (93 <= code && code <= 126); - if (opts.rfc6532) { - accept = accept || isUTF8NonAscii(tok); - } - return accept; - }); - }, - obsCtext - )()); - } - - // ccontent = ctext / quoted-pair / comment - function ccontent() { - return wrap('ccontent', or(ctext, quotedPair, comment)()); - } - - // comment = "(" *([FWS] ccontent) [FWS] ")" - function comment() { - return wrap('comment', and( - literal('('), - star(and(opt(fws), ccontent)), - opt(fws), - literal(')') - )()); - } - - // CFWS = (1*([FWS] comment) [FWS]) / FWS - function cfws() { - return wrap('cfws', or( - and( - star( - and(opt(fws), comment), - 1 - ), - opt(fws) - ), - fws - )()); - } - - // 3.2.3. Atom - - //atext = ALPHA / DIGIT / ; Printable US-ASCII - // "!" / "#" / ; characters not including - // "$" / "%" / ; specials. Used for atoms. - // "&" / "'" / - // "*" / "+" / - // "-" / "/" / - // "=" / "?" / - // "^" / "_" / - // "`" / "{" / - // "|" / "}" / - // "~" - function atext() { - return wrap('atext', compareToken(function atextFunc(tok) { - var accept = - ('a' <= tok && tok <= 'z') || - ('A' <= tok && tok <= 'Z') || - ('0' <= tok && tok <= '9') || - (['!', '#', '$', '%', '&', '\'', '*', '+', '-', '/', - '=', '?', '^', '_', '`', '{', '|', '}', '~'].indexOf(tok) >= 0); - if (opts.rfc6532) { - accept = accept || isUTF8NonAscii(tok); - } - return accept; - })); - } - - // atom = [CFWS] 1*atext [CFWS] - function atom() { - return wrap('atom', and(colwsp(opt(cfws)), star(atext, 1), colwsp(opt(cfws)))()); - } - - // dot-atom-text = 1*atext *("." 1*atext) - function dotAtomText() { - var s, maybeText; - s = wrap('dot-atom-text', star(atext, 1)()); - if (s === null) { return s; } - maybeText = star(and(literal('.'), star(atext, 1)))(); - if (maybeText !== null) { - add(s, maybeText); - } - return s; - } - - // dot-atom = [CFWS] dot-atom-text [CFWS] - function dotAtom() { - return wrap('dot-atom', and(invis(opt(cfws)), dotAtomText, invis(opt(cfws)))()); - } - - // 3.2.4. Quoted Strings - - // qtext = %d33 / ; Printable US-ASCII - // %d35-91 / ; characters not including - // %d93-126 / ; "\" or the quote character - // obs-qtext - function qtext() { - return wrap('qtext', or( - function qtextFunc1() { - return compareToken(function qtextFunc2(tok) { - var code = tok.charCodeAt(0); - var accept = - (33 === code) || - (35 <= code && code <= 91) || - (93 <= code && code <= 126); - if (opts.rfc6532) { - accept = accept || isUTF8NonAscii(tok); - } - return accept; - }); - }, - obsQtext - )()); - } - - // qcontent = qtext / quoted-pair - function qcontent() { - return wrap('qcontent', or(qtext, quotedPair)()); - } - - // quoted-string = [CFWS] - // DQUOTE *([FWS] qcontent) [FWS] DQUOTE - // [CFWS] - function quotedString() { - return wrap('quoted-string', and( - invis(opt(cfws)), - invis(dquote), star(and(opt(colwsp(fws)), qcontent)), opt(invis(fws)), invis(dquote), - invis(opt(cfws)) - )()); - } - - // 3.2.5 Miscellaneous Tokens - - // word = atom / quoted-string - function word() { - return wrap('word', or(atom, quotedString)()); - } - - // phrase = 1*word / obs-phrase - function phrase() { - return wrap('phrase', or(obsPhrase, star(word, 1))()); - } - - // 3.4. Address Specification - // address = mailbox / group - function address() { - return wrap('address', or(mailbox, group)()); - } - - // mailbox = name-addr / addr-spec - function mailbox() { - return wrap('mailbox', or(nameAddr, addrSpec)()); - } - - // name-addr = [display-name] angle-addr - function nameAddr() { - return wrap('name-addr', and(opt(displayName), angleAddr)()); - } - - // angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / - // obs-angle-addr - function angleAddr() { - return wrap('angle-addr', or( - and( - invis(opt(cfws)), - literal('<'), - addrSpec, - literal('>'), - invis(opt(cfws)) - ), - obsAngleAddr - )()); - } - - // group = display-name ":" [group-list] ";" [CFWS] - function group() { - return wrap('group', and( - displayName, - literal(':'), - opt(groupList), - literal(';'), - invis(opt(cfws)) - )()); - } - - // display-name = phrase - function displayName() { - return wrap('display-name', function phraseFixedSemantic() { - var result = phrase(); - if (result !== null) { - result.semantic = collapseWhitespace(result.semantic); - } - return result; - }()); - } - - // mailbox-list = (mailbox *("," mailbox)) / obs-mbox-list - function mailboxList() { - return wrap('mailbox-list', or( - and( - mailbox, - star(and(literal(','), mailbox)) - ), - obsMboxList - )()); - } - - // address-list = (address *("," address)) / obs-addr-list - function addressList() { - return wrap('address-list', or( - and( - address, - star(and(literal(','), address)) - ), - obsAddrList - )()); - } - - // group-list = mailbox-list / CFWS / obs-group-list - function groupList() { - return wrap('group-list', or( - mailboxList, - invis(cfws), - obsGroupList - )()); - } - - // 3.4.1 Addr-Spec Specification - - // local-part = dot-atom / quoted-string / obs-local-part - function localPart() { - // note: quoted-string, dotAtom are proper subsets of obs-local-part - // so we really just have to look for obsLocalPart, if we don't care about the exact parse tree - return wrap('local-part', or(obsLocalPart, dotAtom, quotedString)()); - } - - // dtext = %d33-90 / ; Printable US-ASCII - // %d94-126 / ; characters not including - // obs-dtext ; "[", "]", or "\" - function dtext() { - return wrap('dtext', or( - function dtextFunc1() { - return compareToken(function dtextFunc2(tok) { - var code = tok.charCodeAt(0); - var accept = - (33 <= code && code <= 90) || - (94 <= code && code <= 126); - if (opts.rfc6532) { - accept = accept || isUTF8NonAscii(tok); - } - return accept; - }); - }, - obsDtext - )() - ); - } - - // domain-literal = [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS] - function domainLiteral() { - return wrap('domain-literal', and( - invis(opt(cfws)), - literal('['), - star(and(opt(fws), dtext)), - opt(fws), - literal(']'), - invis(opt(cfws)) - )()); - } - - // domain = dot-atom / domain-literal / obs-domain - function domain() { - return wrap('domain', function domainCheckTLD() { - var result = or(obsDomain, dotAtom, domainLiteral)(); - if (opts.rejectTLD) { - if (result && result.semantic && result.semantic.indexOf('.') < 0) { - return null; - } - } - // strip all whitespace from domains - if (result) { - result.semantic = result.semantic.replace(/\s+/g, ''); - } - return result; - }()); - } - - // addr-spec = local-part "@" domain - function addrSpec() { - return wrap('addr-spec', and( - localPart, literal('@'), domain - )()); - } - - // 3.6.2 Originator Fields - // Below we only parse the field body, not the name of the field - // like "From:", "Sender:", or "Reply-To:". Other libraries that - // parse email headers can parse those and defer to these productions - // for the "RFC 5322" part. - - // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields - // from = "From:" (mailbox-list / address-list) CRLF - function fromSpec() { - return wrap('from', or( - mailboxList, - addressList - )()); - } - - // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields - // sender = "Sender:" (mailbox / address) CRLF - function senderSpec() { - return wrap('sender', or( - mailbox, - address - )()); - } - - // RFC 6854 2.1. Replacement of RFC 5322, Section 3.6.2. Originator Fields - // reply-to = "Reply-To:" address-list CRLF - function replyToSpec() { - return wrap('reply-to', addressList()); - } - - // 4.1. Miscellaneous Obsolete Tokens - - // obs-NO-WS-CTL = %d1-8 / ; US-ASCII control - // %d11 / ; characters that do not - // %d12 / ; include the carriage - // %d14-31 / ; return, line feed, and - // %d127 ; white space characters - function obsNoWsCtl() { - return opts.strict ? null : wrap('obs-NO-WS-CTL', compareToken(function (tok) { - var code = tok.charCodeAt(0); - return ((1 <= code && code <= 8) || - (11 === code || 12 === code) || - (14 <= code && code <= 31) || - (127 === code)); - })); - } - - // obs-ctext = obs-NO-WS-CTL - function obsCtext() { return opts.strict ? null : wrap('obs-ctext', obsNoWsCtl()); } - - // obs-qtext = obs-NO-WS-CTL - function obsQtext() { return opts.strict ? null : wrap('obs-qtext', obsNoWsCtl()); } - - // obs-qp = "\" (%d0 / obs-NO-WS-CTL / LF / CR) - function obsQP() { - return opts.strict ? null : wrap('obs-qp', and( - literal('\\'), - or(literal('\0'), obsNoWsCtl, lf, cr) - )()); - } - - // obs-phrase = word *(word / "." / CFWS) - function obsPhrase() { - if (opts.strict ) return null; - return opts.atInDisplayName ? wrap('obs-phrase', and( - word, - star(or(word, literal('.'), literal('@'), colwsp(cfws))) - )()) : - wrap('obs-phrase', and( - word, - star(or(word, literal('.'), colwsp(cfws))) - )()); - } - - // 4.2. Obsolete Folding White Space - - // NOTE: read the errata http://www.rfc-editor.org/errata_search.php?rfc=5322&eid=1908 - // obs-FWS = 1*([CRLF] WSP) - function obsFws() { - return opts.strict ? null : wrap('obs-FWS', star( - and(invis(opt(crlf)), wsp), - 1 - )()); - } - - // 4.4. Obsolete Addressing - - // obs-angle-addr = [CFWS] "<" obs-route addr-spec ">" [CFWS] - function obsAngleAddr() { - return opts.strict ? null : wrap('obs-angle-addr', and( - invis(opt(cfws)), - literal('<'), - obsRoute, - addrSpec, - literal('>'), - invis(opt(cfws)) - )()); - } - - // obs-route = obs-domain-list ":" - function obsRoute() { - return opts.strict ? null : wrap('obs-route', and( - obsDomainList, - literal(':') - )()); - } - - // obs-domain-list = *(CFWS / ",") "@" domain - // *("," [CFWS] ["@" domain]) - function obsDomainList() { - return opts.strict ? null : wrap('obs-domain-list', and( - star(or(invis(cfws), literal(','))), - literal('@'), - domain, - star(and( - literal(','), - invis(opt(cfws)), - opt(and(literal('@'), domain)) - )) - )()); - } - - // obs-mbox-list = *([CFWS] ",") mailbox *("," [mailbox / CFWS]) - function obsMboxList() { - return opts.strict ? null : wrap('obs-mbox-list', and( - star(and( - invis(opt(cfws)), - literal(',') - )), - mailbox, - star(and( - literal(','), - opt(and( - mailbox, - invis(cfws) - )) - )) - )()); - } - - // obs-addr-list = *([CFWS] ",") address *("," [address / CFWS]) - function obsAddrList() { - return opts.strict ? null : wrap('obs-addr-list', and( - star(and( - invis(opt(cfws)), - literal(',') - )), - address, - star(and( - literal(','), - opt(and( - address, - invis(cfws) - )) - )) - )()); - } - - // obs-group-list = 1*([CFWS] ",") [CFWS] - function obsGroupList() { - return opts.strict ? null : wrap('obs-group-list', and( - star(and( - invis(opt(cfws)), - literal(',') - ), 1), - invis(opt(cfws)) - )()); - } - - // obs-local-part = word *("." word) - function obsLocalPart() { - return opts.strict ? null : wrap('obs-local-part', and(word, star(and(literal('.'), word)))()); - } - - // obs-domain = atom *("." atom) - function obsDomain() { - return opts.strict ? null : wrap('obs-domain', and(atom, star(and(literal('.'), atom)))()); - } - - // obs-dtext = obs-NO-WS-CTL / quoted-pair - function obsDtext() { - return opts.strict ? null : wrap('obs-dtext', or(obsNoWsCtl, quotedPair)()); - } - - ///////////////////////////////////////////////////// - - // ast analysis - - function findNode(name, root) { - var i, stack, node; - if (root === null || root === undefined) { return null; } - stack = [root]; - while (stack.length > 0) { - node = stack.pop(); - if (node.name === name) { - return node; - } - for (i = node.children.length - 1; i >= 0; i -= 1) { - stack.push(node.children[i]); - } - } - return null; - } - - function findAllNodes(name, root) { - var i, stack, node, result; - if (root === null || root === undefined) { return null; } - stack = [root]; - result = []; - while (stack.length > 0) { - node = stack.pop(); - if (node.name === name) { - result.push(node); - } - for (i = node.children.length - 1; i >= 0; i -= 1) { - stack.push(node.children[i]); - } - } - return result; - } - - function findAllNodesNoChildren(names, root) { - var i, stack, node, result, namesLookup; - if (root === null || root === undefined) { return null; } - stack = [root]; - result = []; - namesLookup = {}; - for (i = 0; i < names.length; i += 1) { - namesLookup[names[i]] = true; - } - - while (stack.length > 0) { - node = stack.pop(); - if (node.name in namesLookup) { - result.push(node); - // don't look at children (hence findAllNodesNoChildren) - } else { - for (i = node.children.length - 1; i >= 0; i -= 1) { - stack.push(node.children[i]); - } - } - } - return result; - } - - function giveResult(ast) { - var addresses, groupsAndMailboxes, i, groupOrMailbox, result; - if (ast === null) { - return null; - } - addresses = []; - - // An address is a 'group' (i.e. a list of mailboxes) or a 'mailbox'. - groupsAndMailboxes = findAllNodesNoChildren(['group', 'mailbox'], ast); - for (i = 0; i < groupsAndMailboxes.length; i += 1) { - groupOrMailbox = groupsAndMailboxes[i]; - if (groupOrMailbox.name === 'group') { - addresses.push(giveResultGroup(groupOrMailbox)); - } else if (groupOrMailbox.name === 'mailbox') { - addresses.push(giveResultMailbox(groupOrMailbox)); - } - } - - result = { - ast: ast, - addresses: addresses, - }; - if (opts.simple) { - result = simplifyResult(result); - } - if (opts.oneResult) { - return oneResult(result); - } - if (opts.simple) { - return result && result.addresses; - } else { - return result; - } - } - - function giveResultGroup(group) { - var i; - var groupName = findNode('display-name', group); - var groupResultMailboxes = []; - var mailboxes = findAllNodesNoChildren(['mailbox'], group); - for (i = 0; i < mailboxes.length; i += 1) { - groupResultMailboxes.push(giveResultMailbox(mailboxes[i])); - } - return { - node: group, - parts: { - name: groupName, - }, - type: group.name, // 'group' - name: grabSemantic(groupName), - addresses: groupResultMailboxes, - }; - } - - function giveResultMailbox(mailbox) { - var name = findNode('display-name', mailbox); - var aspec = findNode('addr-spec', mailbox); - var cfws = findAllNodes('cfws', mailbox); - var comments = findAllNodesNoChildren(['comment'], mailbox); - - - var local = findNode('local-part', aspec); - var domain = findNode('domain', aspec); - return { - node: mailbox, - parts: { - name: name, - address: aspec, - local: local, - domain: domain, - comments: cfws - }, - type: mailbox.name, // 'mailbox' - name: grabSemantic(name), - address: grabSemantic(aspec), - local: grabSemantic(local), - domain: grabSemantic(domain), - comments: concatComments(comments), - groupName: grabSemantic(mailbox.groupName), - }; - } - - function grabSemantic(n) { - return n !== null && n !== undefined ? n.semantic : null; - } - - function simplifyResult(result) { - var i; - if (result && result.addresses) { - for (i = 0; i < result.addresses.length; i += 1) { - delete result.addresses[i].node; - } - } - return result; - } - - function concatComments(comments) { - var result = ''; - if (comments) { - for (var i = 0; i < comments.length; i += 1) { - result += grabSemantic(comments[i]); - } - } - return result; - } - - function oneResult(result) { - if (!result) { return null; } - if (!opts.partial && result.addresses.length > 1) { return null; } - return result.addresses && result.addresses[0]; - } - - ///////////////////////////////////////////////////// - - var parseString, pos, len, parsed, startProduction; - - opts = handleOpts(opts, {}); - if (opts === null) { return null; } - - parseString = opts.input; - - startProduction = { - 'address': address, - 'address-list': addressList, - 'angle-addr': angleAddr, - 'from': fromSpec, - 'group': group, - 'mailbox': mailbox, - 'mailbox-list': mailboxList, - 'reply-to': replyToSpec, - 'sender': senderSpec, - }[opts.startAt] || addressList; - - if (!opts.strict) { - initialize(); - opts.strict = true; - parsed = startProduction(parseString); - if (opts.partial || !inStr()) { - return giveResult(parsed); - } - opts.strict = false; - } - - initialize(); - parsed = startProduction(parseString); - if (!opts.partial && inStr()) { return null; } - return giveResult(parsed); - } - - function parseOneAddressSimple(opts) { - return parse5322(handleOpts(opts, { - oneResult: true, - rfc6532: true, - simple: true, - startAt: 'address-list', - })); - } - - function parseAddressListSimple(opts) { - return parse5322(handleOpts(opts, { - rfc6532: true, - simple: true, - startAt: 'address-list', - })); - } - - function parseFromSimple(opts) { - return parse5322(handleOpts(opts, { - rfc6532: true, - simple: true, - startAt: 'from', - })); - } - - function parseSenderSimple(opts) { - return parse5322(handleOpts(opts, { - oneResult: true, - rfc6532: true, - simple: true, - startAt: 'sender', - })); - } - - function parseReplyToSimple(opts) { - return parse5322(handleOpts(opts, { - rfc6532: true, - simple: true, - startAt: 'reply-to', - })); - } - - function handleOpts(opts, defs) { - function isString(str) { - return Object.prototype.toString.call(str) === '[object String]'; - } - - function isObject(o) { - return o === Object(o); - } - - function isNullUndef(o) { - return o === null || o === undefined; - } - - var defaults, o; - - if (isString(opts)) { - opts = { input: opts }; - } else if (!isObject(opts)) { - return null; - } - - if (!isString(opts.input)) { return null; } - if (!defs) { return null; } - - defaults = { - oneResult: false, - partial: false, - rejectTLD: false, - rfc6532: false, - simple: false, - startAt: 'address-list', - strict: false, - atInDisplayName: false - }; - - for (o in defaults) { - if (isNullUndef(opts[o])) { - opts[o] = !isNullUndef(defs[o]) ? defs[o] : defaults[o]; - } - } - return opts; - } - - parse5322.parseOneAddress = parseOneAddressSimple; - parse5322.parseAddressList = parseAddressListSimple; - parse5322.parseFrom = parseFromSimple; - parse5322.parseSender = parseSenderSimple; - parse5322.parseReplyTo = parseReplyToSimple; - - { - module.exports = parse5322; - } - - }()); - }); - - // GPG4Browsers - An OpenPGP implementation in javascript - - /** - * Implementation of the User ID Packet (Tag 13) - * - * A User ID packet consists of UTF-8 text that is intended to represent - * the name and email address of the key holder. By convention, it - * includes an RFC 2822 [RFC2822] mail name-addr, but there are no - * restrictions on its content. The packet length in the header - * specifies the length of the User ID. - */ - class UserIDPacket { - static get tag() { - return enums.packet.userID; - } - - constructor() { - /** A string containing the user id. Usually in the form - * John Doe - * @type {String} - */ - this.userID = ''; - - this.name = ''; - this.email = ''; - this.comment = ''; - } - - /** - * Create UserIDPacket instance from object - * @param {Object} userID - Object specifying userID name, email and comment - * @returns {UserIDPacket} - * @static - */ - static fromObject(userID) { - if (util.isString(userID) || - (userID.name && !util.isString(userID.name)) || - (userID.email && !util.isEmailAddress(userID.email)) || - (userID.comment && !util.isString(userID.comment))) { - throw new Error('Invalid user ID format'); - } - const packet = new UserIDPacket(); - Object.assign(packet, userID); - const components = []; - if (packet.name) components.push(packet.name); - if (packet.comment) components.push(`(${packet.comment})`); - if (packet.email) components.push(`<${packet.email}>`); - packet.userID = components.join(' '); - return packet; - } - - /** - * Parsing function for a user id packet (tag 13). - * @param {Uint8Array} input - Payload of a tag 13 packet - */ - read(bytes, config = defaultConfig) { - const userID = util.decodeUTF8(bytes); - if (userID.length > config.maxUserIDLength) { - throw new Error('User ID string is too long'); - } - try { - const { name, address: email, comments } = emailAddresses.parseOneAddress({ input: userID, atInDisplayName: true }); - this.comment = comments.replace(/^\(|\)$/g, ''); - this.name = name; - this.email = email; - } catch (e) {} - this.userID = userID; - } - - /** - * Creates a binary representation of the user id packet - * @returns {Uint8Array} Binary representation. - */ - write() { - return util.encodeUTF8(this.userID); - } - - equals(otherUserID) { - return otherUserID && otherUserID.userID === this.userID; - } - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - /** - * A Secret-Subkey packet (tag 7) is the subkey analog of the Secret - * Key packet and has exactly the same format. - * @extends SecretKeyPacket - */ - class SecretSubkeyPacket extends SecretKeyPacket { - static get tag() { - return enums.packet.secretSubkey; - } - - /** - * @param {Date} [date] - Creation date - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - constructor(date = new Date(), config = defaultConfig) { - super(date, config); - } - } - - /** - * Implementation of the Trust Packet (Tag 12) - * - * {@link https://tools.ietf.org/html/rfc4880#section-5.10|RFC4880 5.10}: - * The Trust packet is used only within keyrings and is not normally - * exported. Trust packets contain data that record the user's - * specifications of which key holders are trustworthy introducers, - * along with other information that implementing software uses for - * trust information. The format of Trust packets is defined by a given - * implementation. - * - * Trust packets SHOULD NOT be emitted to output streams that are - * transferred to other users, and they SHOULD be ignored on any input - * other than local keyring files. - */ - class TrustPacket { - static get tag() { - return enums.packet.trust; - } - - /** - * Parsing function for a trust packet (tag 12). - * Currently not implemented as we ignore trust packets - */ - read() { - throw new UnsupportedError('Trust packets are not supported'); - } - - write() { - throw new UnsupportedError('Trust packets are not supported'); - } - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - // A Signature can contain the following packets - const allowedPackets$4 = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); - - /** - * Class that represents an OpenPGP signature. - */ - class Signature { - /** - * @param {PacketList} packetlist - The signature packets - */ - constructor(packetlist) { - this.packets = packetlist || new PacketList(); - } - - /** - * Returns binary encoded signature - * @returns {ReadableStream} Binary signature. - */ - write() { - return this.packets.write(); - } - - /** - * Returns ASCII armored text of signature - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {ReadableStream} ASCII armor. - */ - armor(config = defaultConfig) { - return armor(enums.armor.signature, this.write(), undefined, undefined, undefined, config); - } - - /** - * Returns an array of KeyIDs of all of the issuers who created this signature - * @returns {Array} The Key IDs of the signing keys - */ - getSigningKeyIDs() { - return this.packets.map(packet => packet.issuerKeyID); - } - } - - /** - * reads an (optionally armored) OpenPGP signature and returns a signature object - * @param {Object} options - * @param {String} [options.armoredSignature] - Armored signature to be parsed - * @param {Uint8Array} [options.binarySignature] - Binary signature to be parsed - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} New signature object. - * @async - * @static - */ - async function readSignature({ armoredSignature, binarySignature, config, ...rest }) { - config = { ...defaultConfig, ...config }; - let input = armoredSignature || binarySignature; - if (!input) { - throw new Error('readSignature: must pass options object containing `armoredSignature` or `binarySignature`'); - } - if (armoredSignature && !util.isString(armoredSignature)) { - throw new Error('readSignature: options.armoredSignature must be a string'); - } - if (binarySignature && !util.isUint8Array(binarySignature)) { - throw new Error('readSignature: options.binarySignature must be a Uint8Array'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (armoredSignature) { - const { type, data } = await unarmor(input, config); - if (type !== enums.armor.signature) { - throw new Error('Armored text not of type signature'); - } - input = data; - } - const packetlist = await PacketList.fromBinary(input, allowedPackets$4, config); - return new Signature(packetlist); - } - - /** - * @fileoverview Provides helpers methods for key module - * @module key/helper - * @private - */ - - async function generateSecretSubkey(options, config) { - const secretSubkeyPacket = new SecretSubkeyPacket(options.date, config); - secretSubkeyPacket.packets = null; - secretSubkeyPacket.algorithm = enums.write(enums.publicKey, options.algorithm); - await secretSubkeyPacket.generate(options.rsaBits, options.curve); - await secretSubkeyPacket.computeFingerprintAndKeyID(); - return secretSubkeyPacket; - } - - async function generateSecretKey(options, config) { - const secretKeyPacket = new SecretKeyPacket(options.date, config); - secretKeyPacket.packets = null; - secretKeyPacket.algorithm = enums.write(enums.publicKey, options.algorithm); - await secretKeyPacket.generate(options.rsaBits, options.curve, options.config); - await secretKeyPacket.computeFingerprintAndKeyID(); - return secretKeyPacket; - } - - /** - * Returns the valid and non-expired signature that has the latest creation date, while ignoring signatures created in the future. - * @param {Array} signatures - List of signatures - * @param {PublicKeyPacket|PublicSubkeyPacket} publicKey - Public key packet to verify the signature - * @param {Date} date - Use the given date instead of the current time - * @param {Object} config - full configuration - * @returns {Promise} The latest valid signature. - * @async - */ - async function getLatestValidSignature(signatures, publicKey, signatureType, dataToVerify, date = new Date(), config) { - let latestValid; - let exception; - for (let i = signatures.length - 1; i >= 0; i--) { - try { - if ( - (!latestValid || signatures[i].created >= latestValid.created) - ) { - await signatures[i].verify(publicKey, signatureType, dataToVerify, date, undefined, config); - latestValid = signatures[i]; - } - } catch (e) { - exception = e; - } - } - if (!latestValid) { - throw util.wrapError( - `Could not find valid ${enums.read(enums.signature, signatureType)} signature in key ${publicKey.getKeyID().toHex()}` - .replace('certGeneric ', 'self-') - .replace(/([a-z])([A-Z])/g, (_, $1, $2) => $1 + ' ' + $2.toLowerCase()) - , exception); - } - return latestValid; - } - - function isDataExpired(keyPacket, signature, date = new Date()) { - const normDate = util.normalizeDate(date); - if (normDate !== null) { - const expirationTime = getKeyExpirationTime(keyPacket, signature); - return !(keyPacket.created <= normDate && normDate < expirationTime); - } - return false; - } - - /** - * Create Binding signature to the key according to the {@link https://tools.ietf.org/html/rfc4880#section-5.2.1} - * @param {SecretSubkeyPacket} subkey - Subkey key packet - * @param {SecretKeyPacket} primaryKey - Primary key packet - * @param {Object} options - * @param {Object} config - Full configuration - */ - async function createBindingSignature(subkey, primaryKey, options, config) { - const dataToSign = {}; - dataToSign.key = primaryKey; - dataToSign.bind = subkey; - const subkeySignaturePacket = new SignaturePacket(); - subkeySignaturePacket.signatureType = enums.signature.subkeyBinding; - subkeySignaturePacket.publicKeyAlgorithm = primaryKey.algorithm; - subkeySignaturePacket.hashAlgorithm = await getPreferredHashAlgo$1(null, subkey, undefined, undefined, config); - if (options.sign) { - subkeySignaturePacket.keyFlags = [enums.keyFlags.signData]; - subkeySignaturePacket.embeddedSignature = await createSignaturePacket(dataToSign, null, subkey, { - signatureType: enums.signature.keyBinding - }, options.date, undefined, undefined, config); - } else { - subkeySignaturePacket.keyFlags = [enums.keyFlags.encryptCommunication | enums.keyFlags.encryptStorage]; - } - if (options.keyExpirationTime > 0) { - subkeySignaturePacket.keyExpirationTime = options.keyExpirationTime; - subkeySignaturePacket.keyNeverExpires = false; - } - await subkeySignaturePacket.sign(primaryKey, dataToSign, options.date); - return subkeySignaturePacket; - } - - /** - * Returns the preferred signature hash algorithm of a key - * @param {Key} [key] - The key to get preferences from - * @param {SecretKeyPacket|SecretSubkeyPacket} keyPacket - key packet used for signing - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} [userID] - User ID - * @param {Object} config - full configuration - * @returns {Promise} - * @async - */ - async function getPreferredHashAlgo$1(key, keyPacket, date = new Date(), userID = {}, config) { - let hashAlgo = config.preferredHashAlgorithm; - let prefAlgo = hashAlgo; - if (key) { - const primaryUser = await key.getPrimaryUser(date, userID, config); - if (primaryUser.selfCertification.preferredHashAlgorithms) { - [prefAlgo] = primaryUser.selfCertification.preferredHashAlgorithms; - hashAlgo = mod.hash.getHashByteLength(hashAlgo) <= mod.hash.getHashByteLength(prefAlgo) ? - prefAlgo : hashAlgo; - } - } - switch (Object.getPrototypeOf(keyPacket)) { - case SecretKeyPacket.prototype: - case PublicKeyPacket.prototype: - case SecretSubkeyPacket.prototype: - case PublicSubkeyPacket.prototype: - switch (keyPacket.algorithm) { - case enums.publicKey.ecdh: - case enums.publicKey.ecdsa: - case enums.publicKey.eddsa: - prefAlgo = mod.publicKey.elliptic.getPreferredHashAlgo(keyPacket.publicParams.oid); - } - } - return mod.hash.getHashByteLength(hashAlgo) <= mod.hash.getHashByteLength(prefAlgo) ? - prefAlgo : hashAlgo; - } - - /** - * Returns the preferred symmetric/aead/compression algorithm for a set of keys - * @param {'symmetric'|'aead'|'compression'} type - Type of preference to return - * @param {Array} [keys] - Set of keys - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Array} [userIDs] - User IDs - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} Preferred algorithm - * @async - */ - async function getPreferredAlgo(type, keys = [], date = new Date(), userIDs = [], config = defaultConfig) { - const defaultAlgo = { // these are all must-implement in rfc4880bis - 'symmetric': enums.symmetric.aes128, - 'aead': enums.aead.eax, - 'compression': enums.compression.uncompressed - }[type]; - const preferredSenderAlgo = { - 'symmetric': config.preferredSymmetricAlgorithm, - 'aead': config.preferredAEADAlgorithm, - 'compression': config.preferredCompressionAlgorithm - }[type]; - const prefPropertyName = { - 'symmetric': 'preferredSymmetricAlgorithms', - 'aead': 'preferredAEADAlgorithms', - 'compression': 'preferredCompressionAlgorithms' - }[type]; - - // if preferredSenderAlgo appears in the prefs of all recipients, we pick it - // otherwise we use the default algo - // if no keys are available, preferredSenderAlgo is returned - const senderAlgoSupport = await Promise.all(keys.map(async function(key, i) { - const primaryUser = await key.getPrimaryUser(date, userIDs[i], config); - const recipientPrefs = primaryUser.selfCertification[prefPropertyName]; - return !!recipientPrefs && recipientPrefs.indexOf(preferredSenderAlgo) >= 0; - })); - return senderAlgoSupport.every(Boolean) ? preferredSenderAlgo : defaultAlgo; - } - - /** - * Create signature packet - * @param {Object} dataToSign - Contains packets to be signed - * @param {PrivateKey} privateKey - key to get preferences from - * @param {SecretKeyPacket| - * SecretSubkeyPacket} signingKeyPacket secret key packet for signing - * @param {Object} [signatureProperties] - Properties to write on the signature packet before signing - * @param {Date} [date] - Override the creationtime of the signature - * @param {Object} [userID] - User ID - * @param {Object} [detached] - Whether to create a detached signature packet - * @param {Object} config - full configuration - * @returns {Promise} Signature packet. - */ - async function createSignaturePacket(dataToSign, privateKey, signingKeyPacket, signatureProperties, date, userID, detached = false, config) { - if (signingKeyPacket.isDummy()) { - throw new Error('Cannot sign with a gnu-dummy key.'); - } - if (!signingKeyPacket.isDecrypted()) { - throw new Error('Signing key is not decrypted.'); - } - const signaturePacket = new SignaturePacket(); - Object.assign(signaturePacket, signatureProperties); - signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm; - signaturePacket.hashAlgorithm = await getPreferredHashAlgo$1(privateKey, signingKeyPacket, date, userID, config); - await signaturePacket.sign(signingKeyPacket, dataToSign, date, detached); - return signaturePacket; - } - - /** - * Merges signatures from source[attr] to dest[attr] - * @param {Object} source - * @param {Object} dest - * @param {String} attr - * @param {Date} [date] - date to use for signature expiration check, instead of the current time - * @param {Function} [checkFn] - signature only merged if true - */ - async function mergeSignatures(source, dest, attr, date = new Date(), checkFn) { - source = source[attr]; - if (source) { - if (!dest[attr].length) { - dest[attr] = source; - } else { - await Promise.all(source.map(async function(sourceSig) { - if (!sourceSig.isExpired(date) && (!checkFn || await checkFn(sourceSig)) && - !dest[attr].some(function(destSig) { - return util.equalsUint8Array(destSig.writeParams(), sourceSig.writeParams()); - })) { - dest[attr].push(sourceSig); - } - })); - } - } - } - - /** - * Checks if a given certificate or binding signature is revoked - * @param {SecretKeyPacket| - * PublicKeyPacket} primaryKey The primary key packet - * @param {Object} dataToVerify - The data to check - * @param {Array} revocations - The revocation signatures to check - * @param {SignaturePacket} signature - The certificate or signature to check - * @param {PublicSubkeyPacket| - * SecretSubkeyPacket| - * PublicKeyPacket| - * SecretKeyPacket} key, optional The key packet to verify the signature, instead of the primary key - * @param {Date} date - Use the given date instead of the current time - * @param {Object} config - Full configuration - * @returns {Promise} True if the signature revokes the data. - * @async - */ - async function isDataRevoked(primaryKey, signatureType, dataToVerify, revocations, signature, key, date = new Date(), config) { - key = key || primaryKey; - const revocationKeyIDs = []; - await Promise.all(revocations.map(async function(revocationSignature) { - try { - if ( - // Note: a third-party revocation signature could legitimately revoke a - // self-signature if the signature has an authorized revocation key. - // However, we don't support passing authorized revocation keys, nor - // verifying such revocation signatures. Instead, we indicate an error - // when parsing a key with an authorized revocation key, and ignore - // third-party revocation signatures here. (It could also be revoking a - // third-party key certification, which should only affect - // `verifyAllCertifications`.) - !signature || revocationSignature.issuerKeyID.equals(signature.issuerKeyID) - ) { - await revocationSignature.verify( - key, signatureType, dataToVerify, config.revocationsExpire ? date : null, false, config - ); - - // TODO get an identifier of the revoked object instead - revocationKeyIDs.push(revocationSignature.issuerKeyID); - } - } catch (e) {} - })); - // TODO further verify that this is the signature that should be revoked - if (signature) { - signature.revoked = revocationKeyIDs.some(keyID => keyID.equals(signature.issuerKeyID)) ? true : - signature.revoked || false; - return signature.revoked; - } - return revocationKeyIDs.length > 0; - } - - /** - * Returns key expiration time based on the given certification signature. - * The expiration time of the signature is ignored. - * @param {PublicSubkeyPacket|PublicKeyPacket} keyPacket - key to check - * @param {SignaturePacket} signature - signature to process - * @returns {Date|Infinity} expiration time or infinity if the key does not expire - */ - function getKeyExpirationTime(keyPacket, signature) { - let expirationTime; - // check V4 expiration time - if (signature.keyNeverExpires === false) { - expirationTime = keyPacket.created.getTime() + signature.keyExpirationTime * 1000; - } - return expirationTime ? new Date(expirationTime) : Infinity; - } - - /** - * Returns whether aead is supported by all keys in the set - * @param {Array} keys - Set of keys - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Array} [userIDs] - User IDs - * @param {Object} config - full configuration - * @returns {Promise} - * @async - */ - async function isAEADSupported(keys, date = new Date(), userIDs = [], config = defaultConfig) { - let supported = true; - // TODO replace when Promise.some or Promise.any are implemented - await Promise.all(keys.map(async function(key, i) { - const primaryUser = await key.getPrimaryUser(date, userIDs[i], config); - if (!primaryUser.selfCertification.features || - !(primaryUser.selfCertification.features[0] & enums.features.aead)) { - supported = false; - } - })); - return supported; - } - - function sanitizeKeyOptions(options, subkeyDefaults = {}) { - options.type = options.type || subkeyDefaults.type; - options.curve = options.curve || subkeyDefaults.curve; - options.rsaBits = options.rsaBits || subkeyDefaults.rsaBits; - options.keyExpirationTime = options.keyExpirationTime !== undefined ? options.keyExpirationTime : subkeyDefaults.keyExpirationTime; - options.passphrase = util.isString(options.passphrase) ? options.passphrase : subkeyDefaults.passphrase; - options.date = options.date || subkeyDefaults.date; - - options.sign = options.sign || false; - - switch (options.type) { - case 'ecc': - try { - options.curve = enums.write(enums.curve, options.curve); - } catch (e) { - throw new Error('Invalid curve'); - } - if (options.curve === enums.curve.ed25519 || options.curve === enums.curve.curve25519) { - options.curve = options.sign ? enums.curve.ed25519 : enums.curve.curve25519; - } - if (options.sign) { - options.algorithm = options.curve === enums.curve.ed25519 ? enums.publicKey.eddsa : enums.publicKey.ecdsa; - } else { - options.algorithm = enums.publicKey.ecdh; - } - break; - case 'rsa': - options.algorithm = enums.publicKey.rsaEncryptSign; - break; - default: - throw new Error(`Unsupported key type ${options.type}`); - } - return options; - } - - function isValidSigningKeyPacket(keyPacket, signature) { - const keyAlgo = keyPacket.algorithm; - return keyAlgo !== enums.publicKey.rsaEncrypt && - keyAlgo !== enums.publicKey.elgamal && - keyAlgo !== enums.publicKey.ecdh && - (!signature.keyFlags || - (signature.keyFlags[0] & enums.keyFlags.signData) !== 0); - } - - function isValidEncryptionKeyPacket(keyPacket, signature) { - const keyAlgo = keyPacket.algorithm; - return keyAlgo !== enums.publicKey.dsa && - keyAlgo !== enums.publicKey.rsaSign && - keyAlgo !== enums.publicKey.ecdsa && - keyAlgo !== enums.publicKey.eddsa && - (!signature.keyFlags || - (signature.keyFlags[0] & enums.keyFlags.encryptCommunication) !== 0 || - (signature.keyFlags[0] & enums.keyFlags.encryptStorage) !== 0); - } - - function isValidDecryptionKeyPacket(signature, config) { - if (config.allowInsecureDecryptionWithSigningKeys) { - // This is only relevant for RSA keys, all other signing algorithms cannot decrypt - return true; - } - - return !signature.keyFlags || - (signature.keyFlags[0] & enums.keyFlags.encryptCommunication) !== 0 || - (signature.keyFlags[0] & enums.keyFlags.encryptStorage) !== 0; - } - - /** - * Check key against blacklisted algorithms and minimum strength requirements. - * @param {SecretKeyPacket|PublicKeyPacket| - * SecretSubkeyPacket|PublicSubkeyPacket} keyPacket - * @param {Config} config - * @throws {Error} if the key packet does not meet the requirements - */ - function checkKeyRequirements(keyPacket, config) { - const keyAlgo = enums.write(enums.publicKey, keyPacket.algorithm); - const algoInfo = keyPacket.getAlgorithmInfo(); - if (config.rejectPublicKeyAlgorithms.has(keyAlgo)) { - throw new Error(`${algoInfo.algorithm} keys are considered too weak.`); - } - switch (keyAlgo) { - case enums.publicKey.rsaEncryptSign: - case enums.publicKey.rsaSign: - case enums.publicKey.rsaEncrypt: - if (algoInfo.bits < config.minRSABits) { - throw new Error(`RSA keys shorter than ${config.minRSABits} bits are considered too weak.`); - } - break; - case enums.publicKey.ecdsa: - case enums.publicKey.eddsa: - case enums.publicKey.ecdh: - if (config.rejectCurves.has(algoInfo.curve)) { - throw new Error(`Support for ${algoInfo.algorithm} keys using curve ${algoInfo.curve} is disabled.`); - } - break; - } - } - - /** - * @module key/User - * @private - */ - - /** - * Class that represents an user ID or attribute packet and the relevant signatures. - * @param {UserIDPacket|UserAttributePacket} userPacket - packet containing the user info - * @param {Key} mainKey - reference to main Key object containing the primary key and subkeys that the user is associated with - */ - class User { - constructor(userPacket, mainKey) { - this.userID = userPacket.constructor.tag === enums.packet.userID ? userPacket : null; - this.userAttribute = userPacket.constructor.tag === enums.packet.userAttribute ? userPacket : null; - this.selfCertifications = []; - this.otherCertifications = []; - this.revocationSignatures = []; - this.mainKey = mainKey; - } - - /** - * Transforms structured user data to packetlist - * @returns {PacketList} - */ - toPacketList() { - const packetlist = new PacketList(); - packetlist.push(this.userID || this.userAttribute); - packetlist.push(...this.revocationSignatures); - packetlist.push(...this.selfCertifications); - packetlist.push(...this.otherCertifications); - return packetlist; - } - - /** - * Shallow clone - * @returns {User} - */ - clone() { - const user = new User(this.userID || this.userAttribute, this.mainKey); - user.selfCertifications = [...this.selfCertifications]; - user.otherCertifications = [...this.otherCertifications]; - user.revocationSignatures = [...this.revocationSignatures]; - return user; - } - - /** - * Generate third-party certifications over this user and its primary key - * @param {Array} signingKeys - Decrypted private keys for signing - * @param {Date} [date] - Date to use as creation date of the certificate, instead of the current time - * @param {Object} config - Full configuration - * @returns {Promise} New user with new certifications. - * @async - */ - async certify(signingKeys, date, config) { - const primaryKey = this.mainKey.keyPacket; - const dataToSign = { - userID: this.userID, - userAttribute: this.userAttribute, - key: primaryKey - }; - const user = new User(dataToSign.userID || dataToSign.userAttribute, this.mainKey); - user.otherCertifications = await Promise.all(signingKeys.map(async function(privateKey) { - if (!privateKey.isPrivate()) { - throw new Error('Need private key for signing'); - } - if (privateKey.hasSameFingerprintAs(primaryKey)) { - throw new Error("The user's own key can only be used for self-certifications"); - } - const signingKey = await privateKey.getSigningKey(undefined, date, undefined, config); - return createSignaturePacket(dataToSign, privateKey, signingKey.keyPacket, { - // Most OpenPGP implementations use generic certification (0x10) - signatureType: enums.signature.certGeneric, - keyFlags: [enums.keyFlags.certifyKeys | enums.keyFlags.signData] - }, date, undefined, undefined, config); - })); - await user.update(this, date, config); - return user; - } - - /** - * Checks if a given certificate of the user is revoked - * @param {SignaturePacket} certificate - The certificate to verify - * @param {PublicSubkeyPacket| - * SecretSubkeyPacket| - * PublicKeyPacket| - * SecretKeyPacket} [keyPacket] The key packet to verify the signature, instead of the primary key - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} config - Full configuration - * @returns {Promise} True if the certificate is revoked. - * @async - */ - async isRevoked(certificate, keyPacket, date = new Date(), config) { - const primaryKey = this.mainKey.keyPacket; - return isDataRevoked(primaryKey, enums.signature.certRevocation, { - key: primaryKey, - userID: this.userID, - userAttribute: this.userAttribute - }, this.revocationSignatures, certificate, keyPacket, date, config); - } - - /** - * Verifies the user certificate. - * @param {SignaturePacket} certificate - A certificate of this user - * @param {Array} verificationKeys - Array of keys to verify certificate signatures - * @param {Date} [date] - Use the given date instead of the current time - * @param {Object} config - Full configuration - * @returns {Promise} true if the certificate could be verified, or null if the verification keys do not correspond to the certificate - * @throws if the user certificate is invalid. - * @async - */ - async verifyCertificate(certificate, verificationKeys, date = new Date(), config) { - const that = this; - const primaryKey = this.mainKey.keyPacket; - const dataToVerify = { - userID: this.userID, - userAttribute: this.userAttribute, - key: primaryKey - }; - const { issuerKeyID } = certificate; - const issuerKeys = verificationKeys.filter(key => key.getKeys(issuerKeyID).length > 0); - if (issuerKeys.length === 0) { - return null; - } - await Promise.all(issuerKeys.map(async key => { - const signingKey = await key.getSigningKey(issuerKeyID, certificate.created, undefined, config); - if (certificate.revoked || await that.isRevoked(certificate, signingKey.keyPacket, date, config)) { - throw new Error('User certificate is revoked'); - } - try { - await certificate.verify(signingKey.keyPacket, enums.signature.certGeneric, dataToVerify, date, undefined, config); - } catch (e) { - throw util.wrapError('User certificate is invalid', e); - } - })); - return true; - } - - /** - * Verifies all user certificates - * @param {Array} verificationKeys - Array of keys to verify certificate signatures - * @param {Date} [date] - Use the given date instead of the current time - * @param {Object} config - Full configuration - * @returns {Promise>} List of signer's keyID and validity of signature. - * Signature validity is null if the verification keys do not correspond to the certificate. - * @async - */ - async verifyAllCertifications(verificationKeys, date = new Date(), config) { - const that = this; - const certifications = this.selfCertifications.concat(this.otherCertifications); - return Promise.all(certifications.map(async certification => ({ - keyID: certification.issuerKeyID, - valid: await that.verifyCertificate(certification, verificationKeys, date, config).catch(() => false) - }))); - } - - /** - * Verify User. Checks for existence of self signatures, revocation signatures - * and validity of self signature. - * @param {Date} date - Use the given date instead of the current time - * @param {Object} config - Full configuration - * @returns {Promise} Status of user. - * @throws {Error} if there are no valid self signatures. - * @async - */ - async verify(date = new Date(), config) { - if (!this.selfCertifications.length) { - throw new Error('No self-certifications found'); - } - const that = this; - const primaryKey = this.mainKey.keyPacket; - const dataToVerify = { - userID: this.userID, - userAttribute: this.userAttribute, - key: primaryKey - }; - // TODO replace when Promise.some or Promise.any are implemented - let exception; - for (let i = this.selfCertifications.length - 1; i >= 0; i--) { - try { - const selfCertification = this.selfCertifications[i]; - if (selfCertification.revoked || await that.isRevoked(selfCertification, undefined, date, config)) { - throw new Error('Self-certification is revoked'); - } - try { - await selfCertification.verify(primaryKey, enums.signature.certGeneric, dataToVerify, date, undefined, config); - } catch (e) { - throw util.wrapError('Self-certification is invalid', e); - } - return true; - } catch (e) { - exception = e; - } - } - throw exception; - } - - /** - * Update user with new components from specified user - * @param {User} sourceUser - Source user to merge - * @param {Date} date - Date to verify the validity of signatures - * @param {Object} config - Full configuration - * @returns {Promise} - * @async - */ - async update(sourceUser, date, config) { - const primaryKey = this.mainKey.keyPacket; - const dataToVerify = { - userID: this.userID, - userAttribute: this.userAttribute, - key: primaryKey - }; - // self signatures - await mergeSignatures(sourceUser, this, 'selfCertifications', date, async function(srcSelfSig) { - try { - await srcSelfSig.verify(primaryKey, enums.signature.certGeneric, dataToVerify, date, false, config); - return true; - } catch (e) { - return false; - } - }); - // other signatures - await mergeSignatures(sourceUser, this, 'otherCertifications', date); - // revocation signatures - await mergeSignatures(sourceUser, this, 'revocationSignatures', date, function(srcRevSig) { - return isDataRevoked(primaryKey, enums.signature.certRevocation, dataToVerify, [srcRevSig], undefined, undefined, date, config); - }); - } - } - - /** - * @module key/Subkey - * @private - */ - - /** - * Class that represents a subkey packet and the relevant signatures. - * @borrows PublicSubkeyPacket#getKeyID as Subkey#getKeyID - * @borrows PublicSubkeyPacket#getFingerprint as Subkey#getFingerprint - * @borrows PublicSubkeyPacket#hasSameFingerprintAs as Subkey#hasSameFingerprintAs - * @borrows PublicSubkeyPacket#getAlgorithmInfo as Subkey#getAlgorithmInfo - * @borrows PublicSubkeyPacket#getCreationTime as Subkey#getCreationTime - * @borrows PublicSubkeyPacket#isDecrypted as Subkey#isDecrypted - */ - class Subkey { - /** - * @param {SecretSubkeyPacket|PublicSubkeyPacket} subkeyPacket - subkey packet to hold in the Subkey - * @param {Key} mainKey - reference to main Key object, containing the primary key packet corresponding to the subkey - */ - constructor(subkeyPacket, mainKey) { - this.keyPacket = subkeyPacket; - this.bindingSignatures = []; - this.revocationSignatures = []; - this.mainKey = mainKey; - } - - /** - * Transforms structured subkey data to packetlist - * @returns {PacketList} - */ - toPacketList() { - const packetlist = new PacketList(); - packetlist.push(this.keyPacket); - packetlist.push(...this.revocationSignatures); - packetlist.push(...this.bindingSignatures); - return packetlist; - } - - /** - * Shallow clone - * @return {Subkey} - */ - clone() { - const subkey = new Subkey(this.keyPacket, this.mainKey); - subkey.bindingSignatures = [...this.bindingSignatures]; - subkey.revocationSignatures = [...this.revocationSignatures]; - return subkey; - } - - /** - * Checks if a binding signature of a subkey is revoked - * @param {SignaturePacket} signature - The binding signature to verify - * @param {PublicSubkeyPacket| - * SecretSubkeyPacket| - * PublicKeyPacket| - * SecretKeyPacket} key, optional The key to verify the signature - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} True if the binding signature is revoked. - * @async - */ - async isRevoked(signature, key, date = new Date(), config = defaultConfig) { - const primaryKey = this.mainKey.keyPacket; - return isDataRevoked( - primaryKey, enums.signature.subkeyRevocation, { - key: primaryKey, - bind: this.keyPacket - }, this.revocationSignatures, signature, key, date, config - ); - } - - /** - * Verify subkey. Checks for revocation signatures, expiration time - * and valid binding signature. - * @param {Date} date - Use the given date instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} - * @throws {Error} if the subkey is invalid. - * @async - */ - async verify(date = new Date(), config = defaultConfig) { - const primaryKey = this.mainKey.keyPacket; - const dataToVerify = { key: primaryKey, bind: this.keyPacket }; - // check subkey binding signatures - const bindingSignature = await getLatestValidSignature(this.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); - // check binding signature is not revoked - if (bindingSignature.revoked || await this.isRevoked(bindingSignature, null, date, config)) { - throw new Error('Subkey is revoked'); - } - // check for expiration time - if (isDataExpired(this.keyPacket, bindingSignature, date)) { - throw new Error('Subkey is expired'); - } - return bindingSignature; - } - - /** - * Returns the expiration time of the subkey or Infinity if key does not expire. - * Returns null if the subkey is invalid. - * @param {Date} date - Use the given date instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} - * @async - */ - async getExpirationTime(date = new Date(), config = defaultConfig) { - const primaryKey = this.mainKey.keyPacket; - const dataToVerify = { key: primaryKey, bind: this.keyPacket }; - let bindingSignature; - try { - bindingSignature = await getLatestValidSignature(this.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); - } catch (e) { - return null; - } - const keyExpiry = getKeyExpirationTime(this.keyPacket, bindingSignature); - const sigExpiry = bindingSignature.getExpirationTime(); - return keyExpiry < sigExpiry ? keyExpiry : sigExpiry; - } - - /** - * Update subkey with new components from specified subkey - * @param {Subkey} subkey - Source subkey to merge - * @param {Date} [date] - Date to verify validity of signatures - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if update failed - * @async - */ - async update(subkey, date = new Date(), config = defaultConfig) { - const primaryKey = this.mainKey.keyPacket; - if (!this.hasSameFingerprintAs(subkey)) { - throw new Error('Subkey update method: fingerprints of subkeys not equal'); - } - // key packet - if (this.keyPacket.constructor.tag === enums.packet.publicSubkey && - subkey.keyPacket.constructor.tag === enums.packet.secretSubkey) { - this.keyPacket = subkey.keyPacket; - } - // update missing binding signatures - const that = this; - const dataToVerify = { key: primaryKey, bind: that.keyPacket }; - await mergeSignatures(subkey, this, 'bindingSignatures', date, async function(srcBindSig) { - for (let i = 0; i < that.bindingSignatures.length; i++) { - if (that.bindingSignatures[i].issuerKeyID.equals(srcBindSig.issuerKeyID)) { - if (srcBindSig.created > that.bindingSignatures[i].created) { - that.bindingSignatures[i] = srcBindSig; - } - return false; - } - } - try { - await srcBindSig.verify(primaryKey, enums.signature.subkeyBinding, dataToVerify, date, undefined, config); - return true; - } catch (e) { - return false; - } - }); - // revocation signatures - await mergeSignatures(subkey, this, 'revocationSignatures', date, function(srcRevSig) { - return isDataRevoked(primaryKey, enums.signature.subkeyRevocation, dataToVerify, [srcRevSig], undefined, undefined, date, config); - }); - } - - /** - * Revokes the subkey - * @param {SecretKeyPacket} primaryKey - decrypted private primary key for revocation - * @param {Object} reasonForRevocation - optional, object indicating the reason for revocation - * @param {module:enums.reasonForRevocation} reasonForRevocation.flag optional, flag indicating the reason for revocation - * @param {String} reasonForRevocation.string optional, string explaining the reason for revocation - * @param {Date} date - optional, override the creationtime of the revocation signature - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New subkey with revocation signature. - * @async - */ - async revoke( - primaryKey, - { - flag: reasonForRevocationFlag = enums.reasonForRevocation.noReason, - string: reasonForRevocationString = '' - } = {}, - date = new Date(), - config = defaultConfig - ) { - const dataToSign = { key: primaryKey, bind: this.keyPacket }; - const subkey = new Subkey(this.keyPacket, this.mainKey); - subkey.revocationSignatures.push(await createSignaturePacket(dataToSign, null, primaryKey, { - signatureType: enums.signature.subkeyRevocation, - reasonForRevocationFlag: enums.write(enums.reasonForRevocation, reasonForRevocationFlag), - reasonForRevocationString - }, date, undefined, false, config)); - await subkey.update(this); - return subkey; - } - - hasSameFingerprintAs(other) { - return this.keyPacket.hasSameFingerprintAs(other.keyPacket || other); - } - } - - ['getKeyID', 'getFingerprint', 'getAlgorithmInfo', 'getCreationTime', 'isDecrypted'].forEach(name => { - Subkey.prototype[name] = - function() { - return this.keyPacket[name](); - }; - }); - - // GPG4Browsers - An OpenPGP implementation in javascript - - // A key revocation certificate can contain the following packets - const allowedRevocationPackets = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); - - /** - * Abstract class that represents an OpenPGP key. Must contain a primary key. - * Can contain additional subkeys, signatures, user ids, user attributes. - * @borrows PublicKeyPacket#getKeyID as Key#getKeyID - * @borrows PublicKeyPacket#getFingerprint as Key#getFingerprint - * @borrows PublicKeyPacket#hasSameFingerprintAs as Key#hasSameFingerprintAs - * @borrows PublicKeyPacket#getAlgorithmInfo as Key#getAlgorithmInfo - * @borrows PublicKeyPacket#getCreationTime as Key#getCreationTime - */ - class Key { - /** - * Transforms packetlist to structured key data - * @param {PacketList} packetlist - The packets that form a key - * @param {Set} disallowedPackets - disallowed packet tags - */ - packetListToStructure(packetlist, disallowedPackets = new Set()) { - let user; - let primaryKeyID; - let subkey; - for (const packet of packetlist) { - const tag = packet.constructor.tag; - if (disallowedPackets.has(tag)) { - throw new Error(`Unexpected packet type: ${tag}`); - } - switch (tag) { - case enums.packet.publicKey: - case enums.packet.secretKey: - if (this.keyPacket) { - throw new Error('Key block contains multiple keys'); - } - this.keyPacket = packet; - primaryKeyID = this.getKeyID(); - if (!primaryKeyID) { - throw new Error('Missing Key ID'); - } - break; - case enums.packet.userID: - case enums.packet.userAttribute: - user = new User(packet, this); - this.users.push(user); - break; - case enums.packet.publicSubkey: - case enums.packet.secretSubkey: - user = null; - subkey = new Subkey(packet, this); - this.subkeys.push(subkey); - break; - case enums.packet.signature: - switch (packet.signatureType) { - case enums.signature.certGeneric: - case enums.signature.certPersona: - case enums.signature.certCasual: - case enums.signature.certPositive: - if (!user) { - util.printDebug('Dropping certification signatures without preceding user packet'); - continue; - } - if (packet.issuerKeyID.equals(primaryKeyID)) { - user.selfCertifications.push(packet); - } else { - user.otherCertifications.push(packet); - } - break; - case enums.signature.certRevocation: - if (user) { - user.revocationSignatures.push(packet); - } else { - this.directSignatures.push(packet); - } - break; - case enums.signature.key: - this.directSignatures.push(packet); - break; - case enums.signature.subkeyBinding: - if (!subkey) { - util.printDebug('Dropping subkey binding signature without preceding subkey packet'); - continue; - } - subkey.bindingSignatures.push(packet); - break; - case enums.signature.keyRevocation: - this.revocationSignatures.push(packet); - break; - case enums.signature.subkeyRevocation: - if (!subkey) { - util.printDebug('Dropping subkey revocation signature without preceding subkey packet'); - continue; - } - subkey.revocationSignatures.push(packet); - break; - } - break; - } - } - } - - /** - * Transforms structured key data to packetlist - * @returns {PacketList} The packets that form a key. - */ - toPacketList() { - const packetlist = new PacketList(); - packetlist.push(this.keyPacket); - packetlist.push(...this.revocationSignatures); - packetlist.push(...this.directSignatures); - this.users.map(user => packetlist.push(...user.toPacketList())); - this.subkeys.map(subkey => packetlist.push(...subkey.toPacketList())); - return packetlist; - } - - /** - * Clones the key object - * @param {Boolean} [deep=false] Whether to return a deep clone - * @returns {Promise} Clone of the key. - */ - clone(deep = false) { - const key = new this.constructor(this.toPacketList()); - if (deep) { - key.getKeys().forEach(k => { - // shallow clone the key packets - k.keyPacket = Object.create( - Object.getPrototypeOf(k.keyPacket), - Object.getOwnPropertyDescriptors(k.keyPacket) - ); - if (!k.keyPacket.isDecrypted()) return; - // deep clone the private params, which are cleared during encryption - const privateParams = {}; - Object.keys(k.keyPacket.privateParams).forEach(name => { - privateParams[name] = new Uint8Array(k.keyPacket.privateParams[name]); - }); - k.keyPacket.privateParams = privateParams; - }); - } - return key; - } - - /** - * Returns an array containing all public or private subkeys matching keyID; - * If no keyID is given, returns all subkeys. - * @param {type/keyID} [keyID] - key ID to look for - * @returns {Array} array of subkeys - */ - getSubkeys(keyID = null) { - const subkeys = this.subkeys.filter(subkey => ( - !keyID || subkey.getKeyID().equals(keyID, true) - )); - return subkeys; - } - - /** - * Returns an array containing all public or private keys matching keyID. - * If no keyID is given, returns all keys, starting with the primary key. - * @param {type/keyid~KeyID} [keyID] - key ID to look for - * @returns {Array} array of keys - */ - getKeys(keyID = null) { - const keys = []; - if (!keyID || this.getKeyID().equals(keyID, true)) { - keys.push(this); - } - return keys.concat(this.getSubkeys(keyID)); - } - - /** - * Returns key IDs of all keys - * @returns {Array} - */ - getKeyIDs() { - return this.getKeys().map(key => key.getKeyID()); - } - - /** - * Returns userIDs - * @returns {Array} Array of userIDs. - */ - getUserIDs() { - return this.users.map(user => { - return user.userID ? user.userID.userID : null; - }).filter(userID => userID !== null); - } - - /** - * Returns binary encoded key - * @returns {Uint8Array} Binary key. - */ - write() { - return this.toPacketList().write(); - } - - /** - * Returns last created key or key by given keyID that is available for signing and verification - * @param {module:type/keyid~KeyID} [keyID] - key ID of a specific key to retrieve - * @param {Date} [date] - use the fiven date date to to check key validity instead of the current date - * @param {Object} [userID] - filter keys for the given user ID - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} signing key - * @throws if no valid signing key was found - * @async - */ - async getSigningKey(keyID = null, date = new Date(), userID = {}, config = defaultConfig) { - await this.verifyPrimaryKey(date, userID, config); - const primaryKey = this.keyPacket; - const subkeys = this.subkeys.slice().sort((a, b) => b.keyPacket.created - a.keyPacket.created); - let exception; - for (const subkey of subkeys) { - if (!keyID || subkey.getKeyID().equals(keyID)) { - try { - await subkey.verify(date, config); - const dataToVerify = { key: primaryKey, bind: subkey.keyPacket }; - const bindingSignature = await getLatestValidSignature( - subkey.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config - ); - if (!isValidSigningKeyPacket(subkey.keyPacket, bindingSignature)) { - continue; - } - if (!bindingSignature.embeddedSignature) { - throw new Error('Missing embedded signature'); - } - // verify embedded signature - await getLatestValidSignature( - [bindingSignature.embeddedSignature], subkey.keyPacket, enums.signature.keyBinding, dataToVerify, date, config - ); - checkKeyRequirements(subkey.keyPacket, config); - return subkey; - } catch (e) { - exception = e; - } - } - } - - try { - const primaryUser = await this.getPrimaryUser(date, userID, config); - if ((!keyID || primaryKey.getKeyID().equals(keyID)) && - isValidSigningKeyPacket(primaryKey, primaryUser.selfCertification, config)) { - checkKeyRequirements(primaryKey, config); - return this; - } - } catch (e) { - exception = e; - } - throw util.wrapError('Could not find valid signing key packet in key ' + this.getKeyID().toHex(), exception); - } - - /** - * Returns last created key or key by given keyID that is available for encryption or decryption - * @param {module:type/keyid~KeyID} [keyID] - key ID of a specific key to retrieve - * @param {Date} [date] - use the fiven date date to to check key validity instead of the current date - * @param {Object} [userID] - filter keys for the given user ID - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} encryption key - * @throws if no valid encryption key was found - * @async - */ - async getEncryptionKey(keyID, date = new Date(), userID = {}, config = defaultConfig) { - await this.verifyPrimaryKey(date, userID, config); - const primaryKey = this.keyPacket; - // V4: by convention subkeys are preferred for encryption service - const subkeys = this.subkeys.slice().sort((a, b) => b.keyPacket.created - a.keyPacket.created); - let exception; - for (const subkey of subkeys) { - if (!keyID || subkey.getKeyID().equals(keyID)) { - try { - await subkey.verify(date, config); - const dataToVerify = { key: primaryKey, bind: subkey.keyPacket }; - const bindingSignature = await getLatestValidSignature(subkey.bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); - if (isValidEncryptionKeyPacket(subkey.keyPacket, bindingSignature)) { - checkKeyRequirements(subkey.keyPacket, config); - return subkey; - } - } catch (e) { - exception = e; - } - } - } - - try { - // if no valid subkey for encryption, evaluate primary key - const primaryUser = await this.getPrimaryUser(date, userID, config); - if ((!keyID || primaryKey.getKeyID().equals(keyID)) && - isValidEncryptionKeyPacket(primaryKey, primaryUser.selfCertification)) { - checkKeyRequirements(primaryKey, config); - return this; - } - } catch (e) { - exception = e; - } - throw util.wrapError('Could not find valid encryption key packet in key ' + this.getKeyID().toHex(), exception); - } - - /** - * Checks if a signature on a key is revoked - * @param {SignaturePacket} signature - The signature to verify - * @param {PublicSubkeyPacket| - * SecretSubkeyPacket| - * PublicKeyPacket| - * SecretKeyPacket} key, optional The key to verify the signature - * @param {Date} [date] - Use the given date for verification, instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} True if the certificate is revoked. - * @async - */ - async isRevoked(signature, key, date = new Date(), config = defaultConfig) { - return isDataRevoked( - this.keyPacket, enums.signature.keyRevocation, { key: this.keyPacket }, this.revocationSignatures, signature, key, date, config - ); - } - - /** - * Verify primary key. Checks for revocation signatures, expiration time - * and valid self signature. Throws if the primary key is invalid. - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} [userID] - User ID - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} If key verification failed - * @async - */ - async verifyPrimaryKey(date = new Date(), userID = {}, config = defaultConfig) { - const primaryKey = this.keyPacket; - // check for key revocation signatures - if (await this.isRevoked(null, null, date, config)) { - throw new Error('Primary key is revoked'); - } - // check for valid, unrevoked, unexpired self signature - const { selfCertification } = await this.getPrimaryUser(date, userID, config); - // check for expiration time in binding signatures - if (isDataExpired(primaryKey, selfCertification, date)) { - throw new Error('Primary key is expired'); - } - // check for expiration time in direct signatures - const directSignature = await getLatestValidSignature( - this.directSignatures, primaryKey, enums.signature.key, { key: primaryKey }, date, config - ).catch(() => {}); // invalid signatures are discarded, to avoid breaking the key - - if (directSignature && isDataExpired(primaryKey, directSignature, date)) { - throw new Error('Primary key is expired'); - } - } - - /** - * Returns the expiration date of the primary key, considering self-certifications and direct-key signatures. - * Returns `Infinity` if the key doesn't expire, or `null` if the key is revoked or invalid. - * @param {Object} [userID] - User ID to consider instead of the primary user - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} - * @async - */ - async getExpirationTime(userID, config = defaultConfig) { - let primaryKeyExpiry; - try { - const { selfCertification } = await this.getPrimaryUser(null, userID, config); - const selfSigKeyExpiry = getKeyExpirationTime(this.keyPacket, selfCertification); - const selfSigExpiry = selfCertification.getExpirationTime(); - const directSignature = await getLatestValidSignature( - this.directSignatures, this.keyPacket, enums.signature.key, { key: this.keyPacket }, null, config - ).catch(() => {}); - if (directSignature) { - const directSigKeyExpiry = getKeyExpirationTime(this.keyPacket, directSignature); - // We do not support the edge case where the direct signature expires, since it would invalidate the corresponding key expiration, - // causing a discountinous validy period for the key - primaryKeyExpiry = Math.min(selfSigKeyExpiry, selfSigExpiry, directSigKeyExpiry); - } else { - primaryKeyExpiry = selfSigKeyExpiry < selfSigExpiry ? selfSigKeyExpiry : selfSigExpiry; - } - } catch (e) { - primaryKeyExpiry = null; - } - - return util.normalizeDate(primaryKeyExpiry); - } - - - /** - * Returns primary user and most significant (latest valid) self signature - * - if multiple primary users exist, returns the one with the latest self signature - * - otherwise, returns the user with the latest self signature - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} [userID] - User ID to get instead of the primary user, if it exists - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise<{ - * user: User, - * selfCertification: SignaturePacket - * }>} The primary user and the self signature - * @async - */ - async getPrimaryUser(date = new Date(), userID = {}, config = defaultConfig) { - const primaryKey = this.keyPacket; - const users = []; - let exception; - for (let i = 0; i < this.users.length; i++) { - try { - const user = this.users[i]; - if (!user.userID) { - continue; - } - if ( - (userID.name !== undefined && user.userID.name !== userID.name) || - (userID.email !== undefined && user.userID.email !== userID.email) || - (userID.comment !== undefined && user.userID.comment !== userID.comment) - ) { - throw new Error('Could not find user that matches that user ID'); - } - const dataToVerify = { userID: user.userID, key: primaryKey }; - const selfCertification = await getLatestValidSignature(user.selfCertifications, primaryKey, enums.signature.certGeneric, dataToVerify, date, config); - users.push({ index: i, user, selfCertification }); - } catch (e) { - exception = e; - } - } - if (!users.length) { - throw exception || new Error('Could not find primary user'); - } - await Promise.all(users.map(async function (a) { - return a.user.revoked || a.user.isRevoked(a.selfCertification, null, date, config); - })); - // sort by primary user flag and signature creation time - const primaryUser = users.sort(function(a, b) { - const A = a.selfCertification; - const B = b.selfCertification; - return B.revoked - A.revoked || A.isPrimaryUserID - B.isPrimaryUserID || A.created - B.created; - }).pop(); - const { user, selfCertification: cert } = primaryUser; - if (cert.revoked || await user.isRevoked(cert, null, date, config)) { - throw new Error('Primary user is revoked'); - } - return primaryUser; - } - - /** - * Update key with new components from specified key with same key ID: - * users, subkeys, certificates are merged into the destination key, - * duplicates and expired signatures are ignored. - * - * If the source key is a private key and the destination key is public, - * a private key is returned. - * @param {Key} sourceKey - Source key to merge - * @param {Date} [date] - Date to verify validity of signatures and keys - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} updated key - * @async - */ - async update(sourceKey, date = new Date(), config = defaultConfig) { - if (!this.hasSameFingerprintAs(sourceKey)) { - throw new Error('Primary key fingerprints must be equal to update the key'); - } - if (!this.isPrivate() && sourceKey.isPrivate()) { - // check for equal subkey packets - const equal = (this.subkeys.length === sourceKey.subkeys.length) && - (this.subkeys.every(destSubkey => { - return sourceKey.subkeys.some(srcSubkey => { - return destSubkey.hasSameFingerprintAs(srcSubkey); - }); - })); - if (!equal) { - throw new Error('Cannot update public key with private key if subkeys mismatch'); - } - - return sourceKey.update(this, config); - } - // from here on, either: - // - destination key is private, source key is public - // - the keys are of the same type - // hence we don't need to convert the destination key type - const updatedKey = this.clone(); - // revocation signatures - await mergeSignatures(sourceKey, updatedKey, 'revocationSignatures', date, srcRevSig => { - return isDataRevoked(updatedKey.keyPacket, enums.signature.keyRevocation, updatedKey, [srcRevSig], null, sourceKey.keyPacket, date, config); - }); - // direct signatures - await mergeSignatures(sourceKey, updatedKey, 'directSignatures', date); - // update users - await Promise.all(sourceKey.users.map(async srcUser => { - // multiple users with the same ID/attribute are not explicitly disallowed by the spec - // hence we support them, just in case - const usersToUpdate = updatedKey.users.filter(dstUser => ( - (srcUser.userID && srcUser.userID.equals(dstUser.userID)) || - (srcUser.userAttribute && srcUser.userAttribute.equals(dstUser.userAttribute)) - )); - if (usersToUpdate.length > 0) { - await Promise.all( - usersToUpdate.map(userToUpdate => userToUpdate.update(srcUser, date, config)) - ); - } else { - const newUser = srcUser.clone(); - newUser.mainKey = updatedKey; - updatedKey.users.push(newUser); - } - })); - // update subkeys - await Promise.all(sourceKey.subkeys.map(async srcSubkey => { - // multiple subkeys with same fingerprint might be preset - const subkeysToUpdate = updatedKey.subkeys.filter(dstSubkey => ( - dstSubkey.hasSameFingerprintAs(srcSubkey) - )); - if (subkeysToUpdate.length > 0) { - await Promise.all( - subkeysToUpdate.map(subkeyToUpdate => subkeyToUpdate.update(srcSubkey, date, config)) - ); - } else { - const newSubkey = srcSubkey.clone(); - newSubkey.mainKey = updatedKey; - updatedKey.subkeys.push(newSubkey); - } - })); - - return updatedKey; - } - - /** - * Get revocation certificate from a revoked key. - * (To get a revocation certificate for an unrevoked key, call revoke() first.) - * @param {Date} date - Use the given date instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} Armored revocation certificate. - * @async - */ - async getRevocationCertificate(date = new Date(), config = defaultConfig) { - const dataToVerify = { key: this.keyPacket }; - const revocationSignature = await getLatestValidSignature(this.revocationSignatures, this.keyPacket, enums.signature.keyRevocation, dataToVerify, date, config); - const packetlist = new PacketList(); - packetlist.push(revocationSignature); - return armor(enums.armor.publicKey, packetlist.write(), null, null, 'This is a revocation certificate'); - } - - /** - * Applies a revocation certificate to a key - * This adds the first signature packet in the armored text to the key, - * if it is a valid revocation signature. - * @param {String} revocationCertificate - armored revocation certificate - * @param {Date} [date] - Date to verify the certificate - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} Revoked key. - * @async - */ - async applyRevocationCertificate(revocationCertificate, date = new Date(), config = defaultConfig) { - const input = await unarmor(revocationCertificate, config); - const packetlist = await PacketList.fromBinary(input.data, allowedRevocationPackets, config); - const revocationSignature = packetlist.findPacket(enums.packet.signature); - if (!revocationSignature || revocationSignature.signatureType !== enums.signature.keyRevocation) { - throw new Error('Could not find revocation signature packet'); - } - if (!revocationSignature.issuerKeyID.equals(this.getKeyID())) { - throw new Error('Revocation signature does not match key'); - } - try { - await revocationSignature.verify(this.keyPacket, enums.signature.keyRevocation, { key: this.keyPacket }, date, undefined, config); - } catch (e) { - throw util.wrapError('Could not verify revocation signature', e); - } - const key = this.clone(); - key.revocationSignatures.push(revocationSignature); - return key; - } - - /** - * Signs primary user of key - * @param {Array} privateKeys - decrypted private keys for signing - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} [userID] - User ID to get instead of the primary user, if it exists - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} Key with new certificate signature. - * @async - */ - async signPrimaryUser(privateKeys, date, userID, config = defaultConfig) { - const { index, user } = await this.getPrimaryUser(date, userID, config); - const userSign = await user.certify(privateKeys, date, config); - const key = this.clone(); - key.users[index] = userSign; - return key; - } - - /** - * Signs all users of key - * @param {Array} privateKeys - decrypted private keys for signing - * @param {Date} [date] - Use the given date for signing, instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} Key with new certificate signature. - * @async - */ - async signAllUsers(privateKeys, date = new Date(), config = defaultConfig) { - const key = this.clone(); - key.users = await Promise.all(this.users.map(function(user) { - return user.certify(privateKeys, date, config); - })); - return key; - } - - /** - * Verifies primary user of key - * - if no arguments are given, verifies the self certificates; - * - otherwise, verifies all certificates signed with given keys. - * @param {Array} [verificationKeys] - array of keys to verify certificate signatures, instead of the primary key - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} [userID] - User ID to get instead of the primary user, if it exists - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise>} List of signer's keyID and validity of signature. - * Signature validity is null if the verification keys do not correspond to the certificate. - * @async - */ - async verifyPrimaryUser(verificationKeys, date = new Date(), userID, config = defaultConfig) { - const primaryKey = this.keyPacket; - const { user } = await this.getPrimaryUser(date, userID, config); - const results = verificationKeys ? - await user.verifyAllCertifications(verificationKeys, date, config) : - [{ keyID: primaryKey.getKeyID(), valid: await user.verify(date, config).catch(() => false) }]; - return results; - } - - /** - * Verifies all users of key - * - if no arguments are given, verifies the self certificates; - * - otherwise, verifies all certificates signed with given keys. - * @param {Array} [verificationKeys] - array of keys to verify certificate signatures - * @param {Date} [date] - Use the given date for verification instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise>} List of userID, signer's keyID and validity of signature. - * Signature validity is null if the verification keys do not correspond to the certificate. - * @async - */ - async verifyAllUsers(verificationKeys, date = new Date(), config = defaultConfig) { - const primaryKey = this.keyPacket; - const results = []; - await Promise.all(this.users.map(async user => { - const signatures = verificationKeys ? - await user.verifyAllCertifications(verificationKeys, date, config) : - [{ keyID: primaryKey.getKeyID(), valid: await user.verify(date, config).catch(() => false) }]; - - results.push(...signatures.map( - signature => ({ - userID: user.userID.userID, - keyID: signature.keyID, - valid: signature.valid - })) - ); - })); - return results; - } - } - - ['getKeyID', 'getFingerprint', 'getAlgorithmInfo', 'getCreationTime', 'hasSameFingerprintAs'].forEach(name => { - Key.prototype[name] = - Subkey.prototype[name]; - }); - - /** - * Creates a PublicKey or PrivateKey depending on the packetlist in input - * @param {PacketList} - packets to parse - * @return {Key} parsed key - * @throws if no key packet was found - */ - function createKey(packetlist) { - for (const packet of packetlist) { - switch (packet.constructor.tag) { - case enums.packet.secretKey: - return new PrivateKey(packetlist); - case enums.packet.publicKey: - return new PublicKey(packetlist); - } - } - throw new Error('No key packet found'); - } - - // This library is free software; you can redistribute it and/or - - /** - * Class that represents an OpenPGP Public Key - */ - class PublicKey extends Key { - /** - * @param {PacketList} packetlist - The packets that form this key - */ - constructor(packetlist) { - super(); - this.keyPacket = null; - this.revocationSignatures = []; - this.directSignatures = []; - this.users = []; - this.subkeys = []; - if (packetlist) { - this.packetListToStructure(packetlist, new Set([enums.packet.secretKey, enums.packet.secretSubkey])); - if (!this.keyPacket) { - throw new Error('Invalid key: missing public-key packet'); - } - } - } - - /** - * Returns true if this is a private key - * @returns {false} - */ - isPrivate() { - return false; - } - - /** - * Returns key as public key (shallow copy) - * @returns {PublicKey} New public Key - */ - toPublic() { - return this; - } - - /** - * Returns ASCII armored text of key - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {ReadableStream} ASCII armor. - */ - armor(config = defaultConfig) { - return armor(enums.armor.publicKey, this.toPacketList().write(), undefined, undefined, undefined, config); - } - } - - /** - * Class that represents an OpenPGP Private key - */ - class PrivateKey extends PublicKey { - /** - * @param {PacketList} packetlist - The packets that form this key - */ - constructor(packetlist) { - super(); - this.packetListToStructure(packetlist, new Set([enums.packet.publicKey, enums.packet.publicSubkey])); - if (!this.keyPacket) { - throw new Error('Invalid key: missing private-key packet'); - } - } - - /** - * Returns true if this is a private key - * @returns {Boolean} - */ - isPrivate() { - return true; - } - - /** - * Returns key as public key (shallow copy) - * @returns {PublicKey} New public Key - */ - toPublic() { - const packetlist = new PacketList(); - const keyPackets = this.toPacketList(); - for (const keyPacket of keyPackets) { - switch (keyPacket.constructor.tag) { - case enums.packet.secretKey: { - const pubKeyPacket = PublicKeyPacket.fromSecretKeyPacket(keyPacket); - packetlist.push(pubKeyPacket); - break; - } - case enums.packet.secretSubkey: { - const pubSubkeyPacket = PublicSubkeyPacket.fromSecretSubkeyPacket(keyPacket); - packetlist.push(pubSubkeyPacket); - break; - } - default: - packetlist.push(keyPacket); - } - } - return new PublicKey(packetlist); - } - - /** - * Returns ASCII armored text of key - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {ReadableStream} ASCII armor. - */ - armor(config = defaultConfig) { - return armor(enums.armor.privateKey, this.toPacketList().write(), undefined, undefined, undefined, config); - } - - /** - * Returns all keys that are available for decryption, matching the keyID when given - * This is useful to retrieve keys for session key decryption - * @param {module:type/keyid~KeyID} keyID, optional - * @param {Date} date, optional - * @param {String} userID, optional - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise>} Array of decryption keys. - * @async - */ - async getDecryptionKeys(keyID, date = new Date(), userID = {}, config = defaultConfig) { - const primaryKey = this.keyPacket; - const keys = []; - for (let i = 0; i < this.subkeys.length; i++) { - if (!keyID || this.subkeys[i].getKeyID().equals(keyID, true)) { - try { - const dataToVerify = { key: primaryKey, bind: this.subkeys[i].keyPacket }; - const bindingSignature = await getLatestValidSignature(this.subkeys[i].bindingSignatures, primaryKey, enums.signature.subkeyBinding, dataToVerify, date, config); - if (isValidDecryptionKeyPacket(bindingSignature, config)) { - keys.push(this.subkeys[i]); - } - } catch (e) {} - } - } - - // evaluate primary key - const primaryUser = await this.getPrimaryUser(date, userID, config); - if ((!keyID || primaryKey.getKeyID().equals(keyID, true)) && - isValidDecryptionKeyPacket(primaryUser.selfCertification, config)) { - keys.push(this); - } - - return keys; - } - - /** - * Returns true if the primary key or any subkey is decrypted. - * A dummy key is considered encrypted. - */ - isDecrypted() { - return this.getKeys().some(({ keyPacket }) => keyPacket.isDecrypted()); - } - - /** - * Check whether the private and public primary key parameters correspond - * Together with verification of binding signatures, this guarantees key integrity - * In case of gnu-dummy primary key, it is enough to validate any signing subkeys - * otherwise all encryption subkeys are validated - * If only gnu-dummy keys are found, we cannot properly validate so we throw an error - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @throws {Error} if validation was not successful and the key cannot be trusted - * @async - */ - async validate(config = defaultConfig) { - if (!this.isPrivate()) { - throw new Error('Cannot validate a public key'); - } - - let signingKeyPacket; - if (!this.keyPacket.isDummy()) { - signingKeyPacket = this.keyPacket; - } else { - /** - * It is enough to validate any signing keys - * since its binding signatures are also checked - */ - const signingKey = await this.getSigningKey(null, null, undefined, { ...config, rejectPublicKeyAlgorithms: new Set(), minRSABits: 0 }); - // This could again be a dummy key - if (signingKey && !signingKey.keyPacket.isDummy()) { - signingKeyPacket = signingKey.keyPacket; - } - } - - if (signingKeyPacket) { - return signingKeyPacket.validate(); - } else { - const keys = this.getKeys(); - const allDummies = keys.map(key => key.keyPacket.isDummy()).every(Boolean); - if (allDummies) { - throw new Error('Cannot validate an all-gnu-dummy key'); - } - - return Promise.all(keys.map(async key => key.keyPacket.validate())); - } - } - - /** - * Clear private key parameters - */ - clearPrivateParams() { - this.getKeys().forEach(({ keyPacket }) => { - if (keyPacket.isDecrypted()) { - keyPacket.clearPrivateParams(); - } - }); - } - - /** - * Revokes the key - * @param {Object} reasonForRevocation - optional, object indicating the reason for revocation - * @param {module:enums.reasonForRevocation} reasonForRevocation.flag optional, flag indicating the reason for revocation - * @param {String} reasonForRevocation.string optional, string explaining the reason for revocation - * @param {Date} date - optional, override the creationtime of the revocation signature - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New key with revocation signature. - * @async - */ - async revoke( - { - flag: reasonForRevocationFlag = enums.reasonForRevocation.noReason, - string: reasonForRevocationString = '' - } = {}, - date = new Date(), - config = defaultConfig - ) { - if (!this.isPrivate()) { - throw new Error('Need private key for revoking'); - } - const dataToSign = { key: this.keyPacket }; - const key = this.clone(); - key.revocationSignatures.push(await createSignaturePacket(dataToSign, null, this.keyPacket, { - signatureType: enums.signature.keyRevocation, - reasonForRevocationFlag: enums.write(enums.reasonForRevocation, reasonForRevocationFlag), - reasonForRevocationString - }, date, undefined, undefined, config)); - return key; - } - - - /** - * Generates a new OpenPGP subkey, and returns a clone of the Key object with the new subkey added. - * Supports RSA and ECC keys. Defaults to the algorithm and bit size/curve of the primary key. DSA primary keys default to RSA subkeys. - * @param {ecc|rsa} options.type The subkey algorithm: ECC or RSA - * @param {String} options.curve (optional) Elliptic curve for ECC keys - * @param {Integer} options.rsaBits (optional) Number of bits for RSA subkeys - * @param {Number} options.keyExpirationTime (optional) Number of seconds from the key creation time after which the key expires - * @param {Date} options.date (optional) Override the creation date of the key and the key signatures - * @param {Boolean} options.sign (optional) Indicates whether the subkey should sign rather than encrypt. Defaults to false - * @param {Object} options.config (optional) custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} - * @async - */ - async addSubkey(options = {}) { - const config = { ...defaultConfig, ...options.config }; - if (options.passphrase) { - throw new Error('Subkey could not be encrypted here, please encrypt whole key'); - } - if (options.rsaBits < config.minRSABits) { - throw new Error(`rsaBits should be at least ${config.minRSABits}, got: ${options.rsaBits}`); - } - const secretKeyPacket = this.keyPacket; - if (secretKeyPacket.isDummy()) { - throw new Error('Cannot add subkey to gnu-dummy primary key'); - } - if (!secretKeyPacket.isDecrypted()) { - throw new Error('Key is not decrypted'); - } - const defaultOptions = secretKeyPacket.getAlgorithmInfo(); - defaultOptions.type = defaultOptions.curve ? 'ecc' : 'rsa'; // DSA keys default to RSA - defaultOptions.rsaBits = defaultOptions.bits || 4096; - defaultOptions.curve = defaultOptions.curve || 'curve25519'; - options = sanitizeKeyOptions(options, defaultOptions); - const keyPacket = await generateSecretSubkey(options); - checkKeyRequirements(keyPacket, config); - const bindingSignature = await createBindingSignature(keyPacket, secretKeyPacket, options, config); - const packetList = this.toPacketList(); - packetList.push(keyPacket, bindingSignature); - return new PrivateKey(packetList); - } - } - - // OpenPGP.js - An OpenPGP implementation in javascript - - // A Key can contain the following packets - const allowedKeyPackets = /*#__PURE__*/ util.constructAllowedPackets([ - PublicKeyPacket, - PublicSubkeyPacket, - SecretKeyPacket, - SecretSubkeyPacket, - UserIDPacket, - UserAttributePacket, - SignaturePacket - ]); - - /** - * Generates a new OpenPGP key. Supports RSA and ECC keys. - * By default, primary and subkeys will be of same type. - * @param {ecc|rsa} options.type The primary key algorithm type: ECC or RSA - * @param {String} options.curve Elliptic curve for ECC keys - * @param {Integer} options.rsaBits Number of bits for RSA keys - * @param {Array} options.userIDs User IDs as strings or objects: 'Jo Doe ' or { name:'Jo Doe', email:'info@jo.com' } - * @param {String} options.passphrase Passphrase used to encrypt the resulting private key - * @param {Number} options.keyExpirationTime (optional) Number of seconds from the key creation time after which the key expires - * @param {Date} options.date Creation date of the key and the key signatures - * @param {Object} config - Full configuration - * @param {Array} options.subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}] - * sign parameter defaults to false, and indicates whether the subkey should sign rather than encrypt - * @returns {Promise<{{ key: PrivateKey, revocationCertificate: String }}>} - * @async - * @static - * @private - */ - async function generate$2(options, config) { - options.sign = true; // primary key is always a signing key - options = sanitizeKeyOptions(options); - options.subkeys = options.subkeys.map((subkey, index) => sanitizeKeyOptions(options.subkeys[index], options)); - let promises = [generateSecretKey(options, config)]; - promises = promises.concat(options.subkeys.map(options => generateSecretSubkey(options, config))); - const packets = await Promise.all(promises); - - const key = await wrapKeyObject(packets[0], packets.slice(1), options, config); - const revocationCertificate = await key.getRevocationCertificate(options.date, config); - key.revocationSignatures = []; - return { key, revocationCertificate }; - } - - /** - * Reformats and signs an OpenPGP key with a given User ID. Currently only supports RSA keys. - * @param {PrivateKey} options.privateKey The private key to reformat - * @param {Array} options.userIDs User IDs as strings or objects: 'Jo Doe ' or { name:'Jo Doe', email:'info@jo.com' } - * @param {String} options.passphrase Passphrase used to encrypt the resulting private key - * @param {Number} options.keyExpirationTime Number of seconds from the key creation time after which the key expires - * @param {Date} options.date Override the creation date of the key signatures - * @param {Array} options.subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}] - * @param {Object} config - Full configuration - * - * @returns {Promise<{{ key: PrivateKey, revocationCertificate: String }}>} - * @async - * @static - * @private - */ - async function reformat(options, config) { - options = sanitize(options); - const { privateKey } = options; - - if (!privateKey.isPrivate()) { - throw new Error('Cannot reformat a public key'); - } - - if (privateKey.keyPacket.isDummy()) { - throw new Error('Cannot reformat a gnu-dummy primary key'); - } - - const isDecrypted = privateKey.getKeys().every(({ keyPacket }) => keyPacket.isDecrypted()); - if (!isDecrypted) { - throw new Error('Key is not decrypted'); - } - - const secretKeyPacket = privateKey.keyPacket; - - if (!options.subkeys) { - options.subkeys = await Promise.all(privateKey.subkeys.map(async subkey => { - const secretSubkeyPacket = subkey.keyPacket; - const dataToVerify = { key: secretKeyPacket, bind: secretSubkeyPacket }; - const bindingSignature = await ( - getLatestValidSignature(subkey.bindingSignatures, secretKeyPacket, enums.signature.subkeyBinding, dataToVerify, null, config) - ).catch(() => ({})); - return { - sign: bindingSignature.keyFlags && (bindingSignature.keyFlags[0] & enums.keyFlags.signData) - }; - })); - } - - const secretSubkeyPackets = privateKey.subkeys.map(subkey => subkey.keyPacket); - if (options.subkeys.length !== secretSubkeyPackets.length) { - throw new Error('Number of subkey options does not match number of subkeys'); - } - - options.subkeys = options.subkeys.map(subkeyOptions => sanitize(subkeyOptions, options)); - - const key = await wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options, config); - const revocationCertificate = await key.getRevocationCertificate(options.date, config); - key.revocationSignatures = []; - return { key, revocationCertificate }; - - function sanitize(options, subkeyDefaults = {}) { - options.keyExpirationTime = options.keyExpirationTime || subkeyDefaults.keyExpirationTime; - options.passphrase = util.isString(options.passphrase) ? options.passphrase : subkeyDefaults.passphrase; - options.date = options.date || subkeyDefaults.date; - - return options; - } - } - - /** - * Construct PrivateKey object from the given key packets, add certification signatures and set passphrase protection - * The new key includes a revocation certificate that must be removed before returning the key, otherwise the key is considered revoked. - * @param {SecretKeyPacket} secretKeyPacket - * @param {SecretSubkeyPacket} secretSubkeyPackets - * @param {Object} options - * @param {Object} config - Full configuration - * @returns {PrivateKey} - */ - async function wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options, config) { - // set passphrase protection - if (options.passphrase) { - await secretKeyPacket.encrypt(options.passphrase, config); - } - - await Promise.all(secretSubkeyPackets.map(async function(secretSubkeyPacket, index) { - const subkeyPassphrase = options.subkeys[index].passphrase; - if (subkeyPassphrase) { - await secretSubkeyPacket.encrypt(subkeyPassphrase, config); - } - })); - - const packetlist = new PacketList(); - packetlist.push(secretKeyPacket); - - await Promise.all(options.userIDs.map(async function(userID, index) { - function createPreferredAlgos(algos, preferredAlgo) { - return [preferredAlgo, ...algos.filter(algo => algo !== preferredAlgo)]; - } - - const userIDPacket = UserIDPacket.fromObject(userID); - const dataToSign = {}; - dataToSign.userID = userIDPacket; - dataToSign.key = secretKeyPacket; - const signaturePacket = new SignaturePacket(); - signaturePacket.signatureType = enums.signature.certGeneric; - signaturePacket.publicKeyAlgorithm = secretKeyPacket.algorithm; - signaturePacket.hashAlgorithm = await getPreferredHashAlgo$1(null, secretKeyPacket, undefined, undefined, config); - signaturePacket.keyFlags = [enums.keyFlags.certifyKeys | enums.keyFlags.signData]; - signaturePacket.preferredSymmetricAlgorithms = createPreferredAlgos([ - // prefer aes256, aes128, then aes192 (no WebCrypto support: https://www.chromium.org/blink/webcrypto#TOC-AES-support) - enums.symmetric.aes256, - enums.symmetric.aes128, - enums.symmetric.aes192 - ], config.preferredSymmetricAlgorithm); - if (config.aeadProtect) { - signaturePacket.preferredAEADAlgorithms = createPreferredAlgos([ - enums.aead.eax, - enums.aead.ocb - ], config.preferredAEADAlgorithm); - } - signaturePacket.preferredHashAlgorithms = createPreferredAlgos([ - // prefer fast asm.js implementations (SHA-256) - enums.hash.sha256, - enums.hash.sha512 - ], config.preferredHashAlgorithm); - signaturePacket.preferredCompressionAlgorithms = createPreferredAlgos([ - enums.compression.zlib, - enums.compression.zip, - enums.compression.uncompressed - ], config.preferredCompressionAlgorithm); - if (index === 0) { - signaturePacket.isPrimaryUserID = true; - } - // integrity protection always enabled - signaturePacket.features = [0]; - signaturePacket.features[0] |= enums.features.modificationDetection; - if (config.aeadProtect) { - signaturePacket.features[0] |= enums.features.aead; - } - if (config.v5Keys) { - signaturePacket.features[0] |= enums.features.v5Keys; - } - if (options.keyExpirationTime > 0) { - signaturePacket.keyExpirationTime = options.keyExpirationTime; - signaturePacket.keyNeverExpires = false; - } - await signaturePacket.sign(secretKeyPacket, dataToSign, options.date); - - return { userIDPacket, signaturePacket }; - })).then(list => { - list.forEach(({ userIDPacket, signaturePacket }) => { - packetlist.push(userIDPacket); - packetlist.push(signaturePacket); - }); - }); - - await Promise.all(secretSubkeyPackets.map(async function(secretSubkeyPacket, index) { - const subkeyOptions = options.subkeys[index]; - const subkeySignaturePacket = await createBindingSignature(secretSubkeyPacket, secretKeyPacket, subkeyOptions, config); - return { secretSubkeyPacket, subkeySignaturePacket }; - })).then(packets => { - packets.forEach(({ secretSubkeyPacket, subkeySignaturePacket }) => { - packetlist.push(secretSubkeyPacket); - packetlist.push(subkeySignaturePacket); - }); - }); - - // Add revocation signature packet for creating a revocation certificate. - // This packet should be removed before returning the key. - const dataToSign = { key: secretKeyPacket }; - packetlist.push(await createSignaturePacket(dataToSign, null, secretKeyPacket, { - signatureType: enums.signature.keyRevocation, - reasonForRevocationFlag: enums.reasonForRevocation.noReason, - reasonForRevocationString: '' - }, options.date, undefined, undefined, config)); - - if (options.passphrase) { - secretKeyPacket.clearPrivateParams(); - } - - await Promise.all(secretSubkeyPackets.map(async function(secretSubkeyPacket, index) { - const subkeyPassphrase = options.subkeys[index].passphrase; - if (subkeyPassphrase) { - secretSubkeyPacket.clearPrivateParams(); - } - })); - - return new PrivateKey(packetlist); - } - - /** - * Reads an (optionally armored) OpenPGP key and returns a key object - * @param {Object} options - * @param {String} [options.armoredKey] - Armored key to be parsed - * @param {Uint8Array} [options.binaryKey] - Binary key to be parsed - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} Key object. - * @async - * @static - */ - async function readKey({ armoredKey, binaryKey, config, ...rest }) { - config = { ...defaultConfig, ...config }; - if (!armoredKey && !binaryKey) { - throw new Error('readKey: must pass options object containing `armoredKey` or `binaryKey`'); - } - if (armoredKey && !util.isString(armoredKey)) { - throw new Error('readKey: options.armoredKey must be a string'); - } - if (binaryKey && !util.isUint8Array(binaryKey)) { - throw new Error('readKey: options.binaryKey must be a Uint8Array'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - let input; - if (armoredKey) { - const { type, data } = await unarmor(armoredKey, config); - if (!(type === enums.armor.publicKey || type === enums.armor.privateKey)) { - throw new Error('Armored text not of type key'); - } - input = data; - } else { - input = binaryKey; - } - const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); - return createKey(packetlist); - } - - /** - * Reads an (optionally armored) OpenPGP private key and returns a PrivateKey object - * @param {Object} options - * @param {String} [options.armoredKey] - Armored key to be parsed - * @param {Uint8Array} [options.binaryKey] - Binary key to be parsed - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} Key object. - * @async - * @static - */ - async function readPrivateKey({ armoredKey, binaryKey, config, ...rest }) { - config = { ...defaultConfig, ...config }; - if (!armoredKey && !binaryKey) { - throw new Error('readPrivateKey: must pass options object containing `armoredKey` or `binaryKey`'); - } - if (armoredKey && !util.isString(armoredKey)) { - throw new Error('readPrivateKey: options.armoredKey must be a string'); - } - if (binaryKey && !util.isUint8Array(binaryKey)) { - throw new Error('readPrivateKey: options.binaryKey must be a Uint8Array'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - let input; - if (armoredKey) { - const { type, data } = await unarmor(armoredKey, config); - if (!(type === enums.armor.privateKey)) { - throw new Error('Armored text not of type private key'); - } - input = data; - } else { - input = binaryKey; - } - const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); - return new PrivateKey(packetlist); - } - - /** - * Reads an (optionally armored) OpenPGP key block and returns a list of key objects - * @param {Object} options - * @param {String} [options.armoredKeys] - Armored keys to be parsed - * @param {Uint8Array} [options.binaryKeys] - Binary keys to be parsed - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise>} Key objects. - * @async - * @static - */ - async function readKeys({ armoredKeys, binaryKeys, config, ...rest }) { - config = { ...defaultConfig, ...config }; - let input = armoredKeys || binaryKeys; - if (!input) { - throw new Error('readKeys: must pass options object containing `armoredKeys` or `binaryKeys`'); - } - if (armoredKeys && !util.isString(armoredKeys)) { - throw new Error('readKeys: options.armoredKeys must be a string'); - } - if (binaryKeys && !util.isUint8Array(binaryKeys)) { - throw new Error('readKeys: options.binaryKeys must be a Uint8Array'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (armoredKeys) { - const { type, data } = await unarmor(armoredKeys, config); - if (type !== enums.armor.publicKey && type !== enums.armor.privateKey) { - throw new Error('Armored text not of type key'); - } - input = data; - } - const keys = []; - const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); - const keyIndex = packetlist.indexOfTag(enums.packet.publicKey, enums.packet.secretKey); - if (keyIndex.length === 0) { - throw new Error('No key packet found'); - } - for (let i = 0; i < keyIndex.length; i++) { - const oneKeyList = packetlist.slice(keyIndex[i], keyIndex[i + 1]); - const newKey = createKey(oneKeyList); - keys.push(newKey); - } - return keys; - } - - /** - * Reads an (optionally armored) OpenPGP private key block and returns a list of PrivateKey objects - * @param {Object} options - * @param {String} [options.armoredKeys] - Armored keys to be parsed - * @param {Uint8Array} [options.binaryKeys] - Binary keys to be parsed - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise>} Key objects. - * @async - * @static - */ - async function readPrivateKeys({ armoredKeys, binaryKeys, config }) { - config = { ...defaultConfig, ...config }; - let input = armoredKeys || binaryKeys; - if (!input) { - throw new Error('readPrivateKeys: must pass options object containing `armoredKeys` or `binaryKeys`'); - } - if (armoredKeys && !util.isString(armoredKeys)) { - throw new Error('readPrivateKeys: options.armoredKeys must be a string'); - } - if (binaryKeys && !util.isUint8Array(binaryKeys)) { - throw new Error('readPrivateKeys: options.binaryKeys must be a Uint8Array'); - } - if (armoredKeys) { - const { type, data } = await unarmor(armoredKeys, config); - if (type !== enums.armor.privateKey) { - throw new Error('Armored text not of type private key'); - } - input = data; - } - const keys = []; - const packetlist = await PacketList.fromBinary(input, allowedKeyPackets, config); - const keyIndex = packetlist.indexOfTag(enums.packet.secretKey); - if (keyIndex.length === 0) { - throw new Error('No secret key packet found'); - } - for (let i = 0; i < keyIndex.length; i++) { - const oneKeyList = packetlist.slice(keyIndex[i], keyIndex[i + 1]); - const newKey = new PrivateKey(oneKeyList); - keys.push(newKey); - } - return keys; - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - // A Message can contain the following packets - const allowedMessagePackets = /*#__PURE__*/ util.constructAllowedPackets([ - LiteralDataPacket, - CompressedDataPacket, - AEADEncryptedDataPacket, - SymEncryptedIntegrityProtectedDataPacket, - SymmetricallyEncryptedDataPacket, - PublicKeyEncryptedSessionKeyPacket, - SymEncryptedSessionKeyPacket, - OnePassSignaturePacket, - SignaturePacket - ]); - // A SKESK packet can contain the following packets - const allowedSymSessionKeyPackets = /*#__PURE__*/ util.constructAllowedPackets([SymEncryptedSessionKeyPacket]); - // A detached signature can contain the following packets - const allowedDetachedSignaturePackets = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); - - /** - * Class that represents an OpenPGP message. - * Can be an encrypted message, signed message, compressed message or literal message - * See {@link https://tools.ietf.org/html/rfc4880#section-11.3} - */ - class Message { - /** - * @param {PacketList} packetlist - The packets that form this message - */ - constructor(packetlist) { - this.packets = packetlist || new PacketList(); - } - - /** - * Returns the key IDs of the keys to which the session key is encrypted - * @returns {Array} Array of keyID objects. - */ - getEncryptionKeyIDs() { - const keyIDs = []; - const pkESKeyPacketlist = this.packets.filterByTag(enums.packet.publicKeyEncryptedSessionKey); - pkESKeyPacketlist.forEach(function(packet) { - keyIDs.push(packet.publicKeyID); - }); - return keyIDs; - } - - /** - * Returns the key IDs of the keys that signed the message - * @returns {Array} Array of keyID objects. - */ - getSigningKeyIDs() { - const msg = this.unwrapCompressed(); - // search for one pass signatures - const onePassSigList = msg.packets.filterByTag(enums.packet.onePassSignature); - if (onePassSigList.length > 0) { - return onePassSigList.map(packet => packet.issuerKeyID); - } - // if nothing found look for signature packets - const signatureList = msg.packets.filterByTag(enums.packet.signature); - return signatureList.map(packet => packet.issuerKeyID); - } - - /** - * Decrypt the message. Either a private key, a session key, or a password must be specified. - * @param {Array} [decryptionKeys] - Private keys with decrypted secret data - * @param {Array} [passwords] - Passwords used to decrypt - * @param {Array} [sessionKeys] - Session keys in the form: { data:Uint8Array, algorithm:String, [aeadAlgorithm:String] } - * @param {Date} [date] - Use the given date for key verification instead of the current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New message with decrypted content. - * @async - */ - async decrypt(decryptionKeys, passwords, sessionKeys, date = new Date(), config = defaultConfig) { - const sessionKeyObjects = sessionKeys || await this.decryptSessionKeys(decryptionKeys, passwords, date, config); - - const symEncryptedPacketlist = this.packets.filterByTag( - enums.packet.symmetricallyEncryptedData, - enums.packet.symEncryptedIntegrityProtectedData, - enums.packet.aeadEncryptedData - ); - - if (symEncryptedPacketlist.length === 0) { - return this; - } - - const symEncryptedPacket = symEncryptedPacketlist[0]; - let exception = null; - const decryptedPromise = Promise.all(sessionKeyObjects.map(async ({ algorithm: algorithmName, data }) => { - if (!util.isUint8Array(data) || !util.isString(algorithmName)) { - throw new Error('Invalid session key for decryption.'); - } - - try { - const algo = enums.write(enums.symmetric, algorithmName); - await symEncryptedPacket.decrypt(algo, data, config); - } catch (e) { - util.printDebugError(e); - exception = e; - } - })); - // We don't await stream.cancel here because it only returns when the other copy is canceled too. - cancel(symEncryptedPacket.encrypted); // Don't keep copy of encrypted data in memory. - symEncryptedPacket.encrypted = null; - await decryptedPromise; - - if (!symEncryptedPacket.packets || !symEncryptedPacket.packets.length) { - throw exception || new Error('Decryption failed.'); - } - - const resultMsg = new Message(symEncryptedPacket.packets); - symEncryptedPacket.packets = new PacketList(); // remove packets after decryption - - return resultMsg; - } - - /** - * Decrypt encrypted session keys either with private keys or passwords. - * @param {Array} [decryptionKeys] - Private keys with decrypted secret data - * @param {Array} [passwords] - Passwords used to decrypt - * @param {Date} [date] - Use the given date for key verification, instead of current time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise>} array of object with potential sessionKey, algorithm pairs - * @async - */ - async decryptSessionKeys(decryptionKeys, passwords, date = new Date(), config = defaultConfig) { - let decryptedSessionKeyPackets = []; - - let exception; - if (passwords) { - const skeskPackets = this.packets.filterByTag(enums.packet.symEncryptedSessionKey); - if (skeskPackets.length === 0) { - throw new Error('No symmetrically encrypted session key packet found.'); - } - await Promise.all(passwords.map(async function(password, i) { - let packets; - if (i) { - packets = await PacketList.fromBinary(skeskPackets.write(), allowedSymSessionKeyPackets, config); - } else { - packets = skeskPackets; - } - await Promise.all(packets.map(async function(skeskPacket) { - try { - await skeskPacket.decrypt(password); - decryptedSessionKeyPackets.push(skeskPacket); - } catch (err) { - util.printDebugError(err); - } - })); - })); - } else if (decryptionKeys) { - const pkeskPackets = this.packets.filterByTag(enums.packet.publicKeyEncryptedSessionKey); - if (pkeskPackets.length === 0) { - throw new Error('No public key encrypted session key packet found.'); - } - await Promise.all(pkeskPackets.map(async function(pkeskPacket) { - await Promise.all(decryptionKeys.map(async function(decryptionKey) { - let algos = [ - enums.symmetric.aes256, // Old OpenPGP.js default fallback - enums.symmetric.aes128, // RFC4880bis fallback - enums.symmetric.tripledes, // RFC4880 fallback - enums.symmetric.cast5 // Golang OpenPGP fallback - ]; - try { - const primaryUser = await decryptionKey.getPrimaryUser(date, undefined, config); // TODO: Pass userID from somewhere. - if (primaryUser.selfCertification.preferredSymmetricAlgorithms) { - algos = algos.concat(primaryUser.selfCertification.preferredSymmetricAlgorithms); - } - } catch (e) {} - - // do not check key expiration to allow decryption of old messages - const decryptionKeyPackets = (await decryptionKey.getDecryptionKeys(pkeskPacket.publicKeyID, null, undefined, config)).map(key => key.keyPacket); - await Promise.all(decryptionKeyPackets.map(async function(decryptionKeyPacket) { - if (!decryptionKeyPacket || decryptionKeyPacket.isDummy()) { - return; - } - if (!decryptionKeyPacket.isDecrypted()) { - throw new Error('Decryption key is not decrypted.'); - } - - // To hinder CCA attacks against PKCS1, we carry out a constant-time decryption flow if the `constantTimePKCS1Decryption` config option is set. - const doConstantTimeDecryption = config.constantTimePKCS1Decryption && ( - pkeskPacket.publicKeyAlgorithm === enums.publicKey.rsaEncrypt || - pkeskPacket.publicKeyAlgorithm === enums.publicKey.rsaEncryptSign || - pkeskPacket.publicKeyAlgorithm === enums.publicKey.rsaSign || - pkeskPacket.publicKeyAlgorithm === enums.publicKey.elgamal - ); - - if (doConstantTimeDecryption) { - // The goal is to not reveal whether PKESK decryption (specifically the PKCS1 decoding step) failed, hence, we always proceed to decrypt the message, - // either with the successfully decrypted session key, or with a randomly generated one. - // Since the SEIP/AEAD's symmetric algorithm and key size are stored in the encrypted portion of the PKESK, and the execution flow cannot depend on - // the decrypted payload, we always assume the message to be encrypted with one of the symmetric algorithms specified in `config.constantTimePKCS1DecryptionSupportedSymmetricAlgorithms`: - // - If the PKESK decryption succeeds, and the session key cipher is in the supported set, then we try to decrypt the data with the decrypted session key as well as with the - // randomly generated keys of the remaining key types. - // - If the PKESK decryptions fails, or if it succeeds but support for the cipher is not enabled, then we discard the session key and try to decrypt the data using only the randomly - // generated session keys. - // NB: as a result, if the data is encrypted with a non-suported cipher, decryption will always fail. - - const serialisedPKESK = pkeskPacket.write(); // make copies to be able to decrypt the PKESK packet multiple times - await Promise.all(Array.from(config.constantTimePKCS1DecryptionSupportedSymmetricAlgorithms).map(async sessionKeyAlgorithm => { - const pkeskPacketCopy = new PublicKeyEncryptedSessionKeyPacket(); - pkeskPacketCopy.read(serialisedPKESK); - const randomSessionKey = { - sessionKeyAlgorithm, - sessionKey: await mod.generateSessionKey(sessionKeyAlgorithm) - }; - try { - await pkeskPacketCopy.decrypt(decryptionKeyPacket, randomSessionKey); - decryptedSessionKeyPackets.push(pkeskPacketCopy); - } catch (err) { - // `decrypt` can still throw some non-security-sensitive errors - util.printDebugError(err); - exception = err; - } - })); - - } else { - try { - await pkeskPacket.decrypt(decryptionKeyPacket); - if (!algos.includes(enums.write(enums.symmetric, pkeskPacket.sessionKeyAlgorithm))) { - throw new Error('A non-preferred symmetric algorithm was used.'); - } - decryptedSessionKeyPackets.push(pkeskPacket); - } catch (err) { - util.printDebugError(err); - exception = err; - } - } - })); - })); - cancel(pkeskPacket.encrypted); // Don't keep copy of encrypted data in memory. - pkeskPacket.encrypted = null; - })); - } else { - throw new Error('No key or password specified.'); - } - - if (decryptedSessionKeyPackets.length > 0) { - // Return only unique session keys - if (decryptedSessionKeyPackets.length > 1) { - const seen = new Set(); - decryptedSessionKeyPackets = decryptedSessionKeyPackets.filter(item => { - const k = item.sessionKeyAlgorithm + util.uint8ArrayToString(item.sessionKey); - if (seen.has(k)) { - return false; - } - seen.add(k); - return true; - }); - } - - return decryptedSessionKeyPackets.map(packet => ({ - data: packet.sessionKey, - algorithm: enums.read(enums.symmetric, packet.sessionKeyAlgorithm) - })); - } - throw exception || new Error('Session key decryption failed.'); - } - - /** - * Get literal data that is the body of the message - * @returns {(Uint8Array|null)} Literal body of the message as Uint8Array. - */ - getLiteralData() { - const msg = this.unwrapCompressed(); - const literal = msg.packets.findPacket(enums.packet.literalData); - return (literal && literal.getBytes()) || null; - } - - /** - * Get filename from literal data packet - * @returns {(String|null)} Filename of literal data packet as string. - */ - getFilename() { - const msg = this.unwrapCompressed(); - const literal = msg.packets.findPacket(enums.packet.literalData); - return (literal && literal.getFilename()) || null; - } - - /** - * Get literal data as text - * @returns {(String|null)} Literal body of the message interpreted as text. - */ - getText() { - const msg = this.unwrapCompressed(); - const literal = msg.packets.findPacket(enums.packet.literalData); - if (literal) { - return literal.getText(); - } - return null; - } - - /** - * Generate a new session key object, taking the algorithm preferences of the passed encryption keys into account, if any. - * @param {Array} [encryptionKeys] - Public key(s) to select algorithm preferences for - * @param {Date} [date] - Date to select algorithm preferences at - * @param {Array} [userIDs] - User IDs to select algorithm preferences for - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise<{ data: Uint8Array, algorithm: String, aeadAlgorithm: undefined|String }>} Object with session key data and algorithms. - * @async - */ - static async generateSessionKey(encryptionKeys = [], date = new Date(), userIDs = [], config = defaultConfig) { - const algo = await getPreferredAlgo('symmetric', encryptionKeys, date, userIDs, config); - const algorithmName = enums.read(enums.symmetric, algo); - const aeadAlgorithmName = config.aeadProtect && await isAEADSupported(encryptionKeys, date, userIDs, config) ? - enums.read(enums.aead, await getPreferredAlgo('aead', encryptionKeys, date, userIDs, config)) : - undefined; - - const sessionKeyData = await mod.generateSessionKey(algo); - return { data: sessionKeyData, algorithm: algorithmName, aeadAlgorithm: aeadAlgorithmName }; - } - - /** - * Encrypt the message either with public keys, passwords, or both at once. - * @param {Array} [encryptionKeys] - Public key(s) for message encryption - * @param {Array} [passwords] - Password(s) for message encryption - * @param {Object} [sessionKey] - Session key in the form: { data:Uint8Array, algorithm:String, [aeadAlgorithm:String] } - * @param {Boolean} [wildcard] - Use a key ID of 0 instead of the public key IDs - * @param {Array} [encryptionKeyIDs] - Array of key IDs to use for encryption. Each encryptionKeyIDs[i] corresponds to keys[i] - * @param {Date} [date] - Override the creation date of the literal package - * @param {Array} [userIDs] - User IDs to encrypt for, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }] - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New message with encrypted content. - * @async - */ - async encrypt(encryptionKeys, passwords, sessionKey, wildcard = false, encryptionKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { - if (sessionKey) { - if (!util.isUint8Array(sessionKey.data) || !util.isString(sessionKey.algorithm)) { - throw new Error('Invalid session key for encryption.'); - } - } else if (encryptionKeys && encryptionKeys.length) { - sessionKey = await Message.generateSessionKey(encryptionKeys, date, userIDs, config); - } else if (passwords && passwords.length) { - sessionKey = await Message.generateSessionKey(undefined, undefined, undefined, config); - } else { - throw new Error('No keys, passwords, or session key provided.'); - } - - const { data: sessionKeyData, algorithm: algorithmName, aeadAlgorithm: aeadAlgorithmName } = sessionKey; - - const msg = await Message.encryptSessionKey(sessionKeyData, algorithmName, aeadAlgorithmName, encryptionKeys, passwords, wildcard, encryptionKeyIDs, date, userIDs, config); - - let symEncryptedPacket; - if (aeadAlgorithmName) { - symEncryptedPacket = new AEADEncryptedDataPacket(); - symEncryptedPacket.aeadAlgorithm = enums.write(enums.aead, aeadAlgorithmName); - } else { - symEncryptedPacket = new SymEncryptedIntegrityProtectedDataPacket(); - } - symEncryptedPacket.packets = this.packets; - - const algorithm = enums.write(enums.symmetric, algorithmName); - await symEncryptedPacket.encrypt(algorithm, sessionKeyData, config); - - msg.packets.push(symEncryptedPacket); - symEncryptedPacket.packets = new PacketList(); // remove packets after encryption - return msg; - } - - /** - * Encrypt a session key either with public keys, passwords, or both at once. - * @param {Uint8Array} sessionKey - session key for encryption - * @param {String} algorithmName - session key algorithm - * @param {String} [aeadAlgorithmName] - AEAD algorithm, e.g. 'eax' or 'ocb' - * @param {Array} [encryptionKeys] - Public key(s) for message encryption - * @param {Array} [passwords] - For message encryption - * @param {Boolean} [wildcard] - Use a key ID of 0 instead of the public key IDs - * @param {Array} [encryptionKeyIDs] - Array of key IDs to use for encryption. Each encryptionKeyIDs[i] corresponds to encryptionKeys[i] - * @param {Date} [date] - Override the date - * @param {Array} [userIDs] - User IDs to encrypt for, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }] - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New message with encrypted content. - * @async - */ - static async encryptSessionKey(sessionKey, algorithmName, aeadAlgorithmName, encryptionKeys, passwords, wildcard = false, encryptionKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { - const packetlist = new PacketList(); - const algorithm = enums.write(enums.symmetric, algorithmName); - const aeadAlgorithm = aeadAlgorithmName && enums.write(enums.aead, aeadAlgorithmName); - - if (encryptionKeys) { - const results = await Promise.all(encryptionKeys.map(async function(primaryKey, i) { - const encryptionKey = await primaryKey.getEncryptionKey(encryptionKeyIDs[i], date, userIDs, config); - const pkESKeyPacket = new PublicKeyEncryptedSessionKeyPacket(); - pkESKeyPacket.publicKeyID = wildcard ? KeyID.wildcard() : encryptionKey.getKeyID(); - pkESKeyPacket.publicKeyAlgorithm = encryptionKey.keyPacket.algorithm; - pkESKeyPacket.sessionKey = sessionKey; - pkESKeyPacket.sessionKeyAlgorithm = algorithm; - await pkESKeyPacket.encrypt(encryptionKey.keyPacket); - delete pkESKeyPacket.sessionKey; // delete plaintext session key after encryption - return pkESKeyPacket; - })); - packetlist.push(...results); - } - if (passwords) { - const testDecrypt = async function(keyPacket, password) { - try { - await keyPacket.decrypt(password); - return 1; - } catch (e) { - return 0; - } - }; - - const sum = (accumulator, currentValue) => accumulator + currentValue; - - const encryptPassword = async function(sessionKey, algorithm, aeadAlgorithm, password) { - const symEncryptedSessionKeyPacket = new SymEncryptedSessionKeyPacket(config); - symEncryptedSessionKeyPacket.sessionKey = sessionKey; - symEncryptedSessionKeyPacket.sessionKeyAlgorithm = algorithm; - if (aeadAlgorithm) { - symEncryptedSessionKeyPacket.aeadAlgorithm = aeadAlgorithm; - } - await symEncryptedSessionKeyPacket.encrypt(password, config); - - if (config.passwordCollisionCheck) { - const results = await Promise.all(passwords.map(pwd => testDecrypt(symEncryptedSessionKeyPacket, pwd))); - if (results.reduce(sum) !== 1) { - return encryptPassword(sessionKey, algorithm, password); - } - } - - delete symEncryptedSessionKeyPacket.sessionKey; // delete plaintext session key after encryption - return symEncryptedSessionKeyPacket; - }; - - const results = await Promise.all(passwords.map(pwd => encryptPassword(sessionKey, algorithm, aeadAlgorithm, pwd))); - packetlist.push(...results); - } - - return new Message(packetlist); - } - - /** - * Sign the message (the literal data packet of the message) - * @param {Array} signingKeys - private keys with decrypted secret key data for signing - * @param {Signature} [signature] - Any existing detached signature to add to the message - * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] - * @param {Date} [date] - Override the creation time of the signature - * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New message with signed content. - * @async - */ - async sign(signingKeys = [], signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { - const packetlist = new PacketList(); - - const literalDataPacket = this.packets.findPacket(enums.packet.literalData); - if (!literalDataPacket) { - throw new Error('No literal data packet to sign.'); - } - - let i; - let existingSigPacketlist; - // If data packet was created from Uint8Array, use binary, otherwise use text - const signatureType = literalDataPacket.text === null ? - enums.signature.binary : enums.signature.text; - - if (signature) { - existingSigPacketlist = signature.packets.filterByTag(enums.packet.signature); - for (i = existingSigPacketlist.length - 1; i >= 0; i--) { - const signaturePacket = existingSigPacketlist[i]; - const onePassSig = new OnePassSignaturePacket(); - onePassSig.signatureType = signaturePacket.signatureType; - onePassSig.hashAlgorithm = signaturePacket.hashAlgorithm; - onePassSig.publicKeyAlgorithm = signaturePacket.publicKeyAlgorithm; - onePassSig.issuerKeyID = signaturePacket.issuerKeyID; - if (!signingKeys.length && i === 0) { - onePassSig.flags = 1; - } - packetlist.push(onePassSig); - } - } - - await Promise.all(Array.from(signingKeys).reverse().map(async function (primaryKey, i) { - if (!primaryKey.isPrivate()) { - throw new Error('Need private key for signing'); - } - const signingKeyID = signingKeyIDs[signingKeys.length - 1 - i]; - const signingKey = await primaryKey.getSigningKey(signingKeyID, date, userIDs, config); - const onePassSig = new OnePassSignaturePacket(); - onePassSig.signatureType = signatureType; - onePassSig.hashAlgorithm = await getPreferredHashAlgo$1(primaryKey, signingKey.keyPacket, date, userIDs, config); - onePassSig.publicKeyAlgorithm = signingKey.keyPacket.algorithm; - onePassSig.issuerKeyID = signingKey.getKeyID(); - if (i === signingKeys.length - 1) { - onePassSig.flags = 1; - } - return onePassSig; - })).then(onePassSignatureList => { - onePassSignatureList.forEach(onePassSig => packetlist.push(onePassSig)); - }); - - packetlist.push(literalDataPacket); - packetlist.push(...(await createSignaturePackets(literalDataPacket, signingKeys, signature, signingKeyIDs, date, userIDs, false, config))); - - return new Message(packetlist); - } - - /** - * Compresses the message (the literal and -if signed- signature data packets of the message) - * @param {module:enums.compression} algo - compression algorithm - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Message} New message with compressed content. - */ - compress(algo, config = defaultConfig) { - if (algo === enums.compression.uncompressed) { - return this; - } - - const compressed = new CompressedDataPacket(config); - compressed.algorithm = algo; - compressed.packets = this.packets; - - const packetList = new PacketList(); - packetList.push(compressed); - - return new Message(packetList); - } - - /** - * Create a detached signature for the message (the literal data packet of the message) - * @param {Array} signingKeys - private keys with decrypted secret key data for signing - * @param {Signature} [signature] - Any existing detached signature - * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] - * @param {Date} [date] - Override the creation time of the signature - * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New detached signature of message content. - * @async - */ - async signDetached(signingKeys = [], signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { - const literalDataPacket = this.packets.findPacket(enums.packet.literalData); - if (!literalDataPacket) { - throw new Error('No literal data packet to sign.'); - } - return new Signature(await createSignaturePackets(literalDataPacket, signingKeys, signature, signingKeyIDs, date, userIDs, true, config)); - } - - /** - * Verify message signatures - * @param {Array} verificationKeys - Array of public keys to verify signatures - * @param {Date} [date] - Verify the signature against the given date, i.e. check signature creation time < date < expiration time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise, - * verified: Promise - * }>>} List of signer's keyID and validity of signatures. - * @async - */ - async verify(verificationKeys, date = new Date(), config = defaultConfig) { - const msg = this.unwrapCompressed(); - const literalDataList = msg.packets.filterByTag(enums.packet.literalData); - if (literalDataList.length !== 1) { - throw new Error('Can only verify message with one literal data packet.'); - } - if (isArrayStream(msg.packets.stream)) { - msg.packets.push(...await readToEnd(msg.packets.stream, _ => _ || [])); - } - const onePassSigList = msg.packets.filterByTag(enums.packet.onePassSignature).reverse(); - const signatureList = msg.packets.filterByTag(enums.packet.signature); - if (onePassSigList.length && !signatureList.length && util.isStream(msg.packets.stream) && !isArrayStream(msg.packets.stream)) { - await Promise.all(onePassSigList.map(async onePassSig => { - onePassSig.correspondingSig = new Promise((resolve, reject) => { - onePassSig.correspondingSigResolve = resolve; - onePassSig.correspondingSigReject = reject; - }); - onePassSig.signatureData = fromAsync(async () => (await onePassSig.correspondingSig).signatureData); - onePassSig.hashed = readToEnd(await onePassSig.hash(onePassSig.signatureType, literalDataList[0], undefined, false)); - onePassSig.hashed.catch(() => {}); - })); - msg.packets.stream = transformPair(msg.packets.stream, async (readable, writable) => { - const reader = getReader(readable); - const writer = getWriter(writable); - try { - for (let i = 0; i < onePassSigList.length; i++) { - const { value: signature } = await reader.read(); - onePassSigList[i].correspondingSigResolve(signature); - } - await reader.readToEnd(); - await writer.ready; - await writer.close(); - } catch (e) { - onePassSigList.forEach(onePassSig => { - onePassSig.correspondingSigReject(e); - }); - await writer.abort(e); - } - }); - return createVerificationObjects(onePassSigList, literalDataList, verificationKeys, date, false, config); - } - return createVerificationObjects(signatureList, literalDataList, verificationKeys, date, false, config); - } - - /** - * Verify detached message signature - * @param {Array} verificationKeys - Array of public keys to verify signatures - * @param {Signature} signature - * @param {Date} date - Verify the signature against the given date, i.e. check signature creation time < date < expiration time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise, - * verified: Promise - * }>>} List of signer's keyID and validity of signature. - * @async - */ - verifyDetached(signature, verificationKeys, date = new Date(), config = defaultConfig) { - const msg = this.unwrapCompressed(); - const literalDataList = msg.packets.filterByTag(enums.packet.literalData); - if (literalDataList.length !== 1) { - throw new Error('Can only verify message with one literal data packet.'); - } - const signatureList = signature.packets; - return createVerificationObjects(signatureList, literalDataList, verificationKeys, date, true, config); - } - - /** - * Unwrap compressed message - * @returns {Message} Message Content of compressed message. - */ - unwrapCompressed() { - const compressed = this.packets.filterByTag(enums.packet.compressedData); - if (compressed.length) { - return new Message(compressed[0].packets); - } - return this; - } - - /** - * Append signature to unencrypted message object - * @param {String|Uint8Array} detachedSignature - The detached ASCII-armored or Uint8Array PGP signature - * @param {Object} [config] - Full configuration, defaults to openpgp.config - */ - async appendSignature(detachedSignature, config = defaultConfig) { - await this.packets.read( - util.isUint8Array(detachedSignature) ? detachedSignature : (await unarmor(detachedSignature)).data, - allowedDetachedSignaturePackets, - config - ); - } - - /** - * Returns binary encoded message - * @returns {ReadableStream} Binary message. - */ - write() { - return this.packets.write(); - } - - /** - * Returns ASCII armored text of message - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {ReadableStream} ASCII armor. - */ - armor(config = defaultConfig) { - return armor(enums.armor.message, this.write(), null, null, null, config); - } - } - - /** - * Create signature packets for the message - * @param {LiteralDataPacket} literalDataPacket - the literal data packet to sign - * @param {Array} [signingKeys] - private keys with decrypted secret key data for signing - * @param {Signature} [signature] - Any existing detached signature to append - * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] - * @param {Date} [date] - Override the creationtime of the signature - * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] - * @param {Boolean} [detached] - Whether to create detached signature packets - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} List of signature packets. - * @async - * @private - */ - async function createSignaturePackets(literalDataPacket, signingKeys, signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], detached = false, config = defaultConfig) { - const packetlist = new PacketList(); - - // If data packet was created from Uint8Array, use binary, otherwise use text - const signatureType = literalDataPacket.text === null ? - enums.signature.binary : enums.signature.text; - - await Promise.all(signingKeys.map(async (primaryKey, i) => { - const userID = userIDs[i]; - if (!primaryKey.isPrivate()) { - throw new Error('Need private key for signing'); - } - const signingKey = await primaryKey.getSigningKey(signingKeyIDs[i], date, userID, config); - return createSignaturePacket(literalDataPacket, primaryKey, signingKey.keyPacket, { signatureType }, date, userID, detached, config); - })).then(signatureList => { - packetlist.push(...signatureList); - }); - - if (signature) { - const existingSigPacketlist = signature.packets.filterByTag(enums.packet.signature); - packetlist.push(...existingSigPacketlist); - } - return packetlist; - } - - /** - * Create object containing signer's keyID and validity of signature - * @param {SignaturePacket} signature - Signature packet - * @param {Array} literalDataList - Array of literal data packets - * @param {Array} verificationKeys - Array of public keys to verify signatures - * @param {Date} [date] - Check signature validity with respect to the given date - * @param {Boolean} [detached] - Whether to verify detached signature packets - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise<{ - * keyID: module:type/keyid~KeyID, - * signature: Promise, - * verified: Promise - * }>} signer's keyID and validity of signature - * @async - * @private - */ - async function createVerificationObject(signature, literalDataList, verificationKeys, date = new Date(), detached = false, config = defaultConfig) { - let primaryKey; - let unverifiedSigningKey; - - for (const key of verificationKeys) { - const issuerKeys = key.getKeys(signature.issuerKeyID); - if (issuerKeys.length > 0) { - primaryKey = key; - unverifiedSigningKey = issuerKeys[0]; - break; - } - } - - const isOnePassSignature = signature instanceof OnePassSignaturePacket; - const signaturePacketPromise = isOnePassSignature ? signature.correspondingSig : signature; - - const verifiedSig = { - keyID: signature.issuerKeyID, - verified: (async () => { - if (!unverifiedSigningKey) { - throw new Error(`Could not find signing key with key ID ${signature.issuerKeyID.toHex()}`); - } - - await signature.verify(unverifiedSigningKey.keyPacket, signature.signatureType, literalDataList[0], date, detached, config); - const signaturePacket = await signaturePacketPromise; - if (unverifiedSigningKey.getCreationTime() > signaturePacket.created) { - throw new Error('Key is newer than the signature'); - } - // We pass the signature creation time to check whether the key was expired at the time of signing. - // We check this after signature verification because for streamed one-pass signatures, the creation time is not available before - try { - await primaryKey.getSigningKey(unverifiedSigningKey.getKeyID(), signaturePacket.created, undefined, config); - } catch (e) { - // If a key was reformatted then the self-signatures of the signing key might be in the future compared to the message signature, - // making the key invalid at the time of signing. - // However, if the key is valid at the given `date`, we still allow using it provided the relevant `config` setting is enabled. - // Note: we do not support the edge case of a key that was reformatted and it has expired. - if (config.allowInsecureVerificationWithReformattedKeys && e.message.match(/Signature creation time is in the future/)) { - await primaryKey.getSigningKey(unverifiedSigningKey.getKeyID(), date, undefined, config); - } else { - throw e; - } - } - return true; - })(), - signature: (async () => { - const signaturePacket = await signaturePacketPromise; - const packetlist = new PacketList(); - signaturePacket && packetlist.push(signaturePacket); - return new Signature(packetlist); - })() - }; - - // Mark potential promise rejections as "handled". This is needed because in - // some cases, we reject them before the user has a reasonable chance to - // handle them (e.g. `await readToEnd(result.data); await result.verified` and - // the data stream errors). - verifiedSig.signature.catch(() => {}); - verifiedSig.verified.catch(() => {}); - - return verifiedSig; - } - - /** - * Create list of objects containing signer's keyID and validity of signature - * @param {Array} signatureList - Array of signature packets - * @param {Array} literalDataList - Array of literal data packets - * @param {Array} verificationKeys - Array of public keys to verify signatures - * @param {Date} date - Verify the signature against the given date, - * i.e. check signature creation time < date < expiration time - * @param {Boolean} [detached] - Whether to verify detached signature packets - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise, - * verified: Promise - * }>>} list of signer's keyID and validity of signatures (one entry per signature packet in input) - * @async - * @private - */ - async function createVerificationObjects(signatureList, literalDataList, verificationKeys, date = new Date(), detached = false, config = defaultConfig) { - return Promise.all(signatureList.filter(function(signature) { - return ['text', 'binary'].includes(enums.read(enums.signature, signature.signatureType)); - }).map(async function(signature) { - return createVerificationObject(signature, literalDataList, verificationKeys, date, detached, config); - })); - } - - /** - * Reads an (optionally armored) OpenPGP message and returns a Message object - * @param {Object} options - * @param {String | ReadableStream} [options.armoredMessage] - Armored message to be parsed - * @param {Uint8Array | ReadableStream} [options.binaryMessage] - Binary to be parsed - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} New message object. - * @async - * @static - */ - async function readMessage({ armoredMessage, binaryMessage, config, ...rest }) { - config = { ...defaultConfig, ...config }; - let input = armoredMessage || binaryMessage; - if (!input) { - throw new Error('readMessage: must pass options object containing `armoredMessage` or `binaryMessage`'); - } - if (armoredMessage && !util.isString(armoredMessage) && !util.isStream(armoredMessage)) { - throw new Error('readMessage: options.armoredMessage must be a string or stream'); - } - if (binaryMessage && !util.isUint8Array(binaryMessage) && !util.isStream(binaryMessage)) { - throw new Error('readMessage: options.binaryMessage must be a Uint8Array or stream'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - const streamType = util.isStream(input); - if (streamType) { - await loadStreamsPonyfill(); - input = toStream(input); - } - if (armoredMessage) { - const { type, data } = await unarmor(input, config); - if (type !== enums.armor.message) { - throw new Error('Armored text not of type message'); - } - input = data; - } - const packetlist = await PacketList.fromBinary(input, allowedMessagePackets, config); - const message = new Message(packetlist); - message.fromStream = streamType; - return message; - } - - /** - * Creates new message object from text or binary data. - * @param {Object} options - * @param {String | ReadableStream} [options.text] - The text message contents - * @param {Uint8Array | ReadableStream} [options.binary] - The binary message contents - * @param {String} [options.filename=""] - Name of the file (if any) - * @param {Date} [options.date=current date] - Date of the message, or modification date of the file - * @param {'utf8'|'binary'|'text'|'mime'} [options.format='utf8' if text is passed, 'binary' otherwise] - Data packet type - * @returns {Promise} New message object. - * @async - * @static - */ - async function createMessage({ text, binary, filename, date = new Date(), format = text !== undefined ? 'utf8' : 'binary', ...rest }) { - let input = text !== undefined ? text : binary; - if (input === undefined) { - throw new Error('createMessage: must pass options object containing `text` or `binary`'); - } - if (text && !util.isString(text) && !util.isStream(text)) { - throw new Error('createMessage: options.text must be a string or stream'); - } - if (binary && !util.isUint8Array(binary) && !util.isStream(binary)) { - throw new Error('createMessage: options.binary must be a Uint8Array or stream'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - const streamType = util.isStream(input); - if (streamType) { - await loadStreamsPonyfill(); - input = toStream(input); - } - const literalDataPacket = new LiteralDataPacket(date); - if (text !== undefined) { - literalDataPacket.setText(input, enums.write(enums.literal, format)); - } else { - literalDataPacket.setBytes(input, enums.write(enums.literal, format)); - } - if (filename !== undefined) { - literalDataPacket.setFilename(filename); - } - const literalDataPacketlist = new PacketList(); - literalDataPacketlist.push(literalDataPacket); - const message = new Message(literalDataPacketlist); - message.fromStream = streamType; - return message; - } - - // GPG4Browsers - An OpenPGP implementation in javascript - - // A Cleartext message can contain the following packets - const allowedPackets$5 = /*#__PURE__*/ util.constructAllowedPackets([SignaturePacket]); - - /** - * Class that represents an OpenPGP cleartext signed message. - * See {@link https://tools.ietf.org/html/rfc4880#section-7} - */ - class CleartextMessage { - /** - * @param {String} text - The cleartext of the signed message - * @param {Signature} signature - The detached signature or an empty signature for unsigned messages - */ - constructor(text, signature) { - // normalize EOL to canonical form - this.text = util.removeTrailingSpaces(text).replace(/\r?\n/g, '\r\n'); - if (signature && !(signature instanceof Signature)) { - throw new Error('Invalid signature input'); - } - this.signature = signature || new Signature(new PacketList()); - } - - /** - * Returns the key IDs of the keys that signed the cleartext message - * @returns {Array} Array of keyID objects. - */ - getSigningKeyIDs() { - const keyIDs = []; - const signatureList = this.signature.packets; - signatureList.forEach(function(packet) { - keyIDs.push(packet.issuerKeyID); - }); - return keyIDs; - } - - /** - * Sign the cleartext message - * @param {Array} privateKeys - private keys with decrypted secret key data for signing - * @param {Signature} [signature] - Any existing detached signature - * @param {Array} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to privateKeys[i] - * @param {Date} [date] - The creation time of the signature that should be created - * @param {Array} [userIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }] - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise} New cleartext message with signed content. - * @async - */ - async sign(privateKeys, signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], config = defaultConfig) { - const literalDataPacket = new LiteralDataPacket(); - literalDataPacket.setText(this.text); - const newSignature = new Signature(await createSignaturePackets(literalDataPacket, privateKeys, signature, signingKeyIDs, date, userIDs, true, config)); - return new CleartextMessage(this.text, newSignature); - } - - /** - * Verify signatures of cleartext signed message - * @param {Array} keys - Array of keys to verify signatures - * @param {Date} [date] - Verify the signature against the given date, i.e. check signature creation time < date < expiration time - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {Promise, - * verified: Promise - * }>>} List of signer's keyID and validity of signature. - * @async - */ - verify(keys, date = new Date(), config = defaultConfig) { - const signatureList = this.signature.packets; - const literalDataPacket = new LiteralDataPacket(); - // we assume that cleartext signature is generated based on UTF8 cleartext - literalDataPacket.setText(this.text); - return createVerificationObjects(signatureList, [literalDataPacket], keys, date, true, config); - } - - /** - * Get cleartext - * @returns {String} Cleartext of message. - */ - getText() { - // normalize end of line to \n - return this.text.replace(/\r\n/g, '\n'); - } - - /** - * Returns ASCII armored text of cleartext signed message - * @param {Object} [config] - Full configuration, defaults to openpgp.config - * @returns {String | ReadableStream} ASCII armor. - */ - armor(config = defaultConfig) { - let hashes = this.signature.packets.map(function(packet) { - return enums.read(enums.hash, packet.hashAlgorithm).toUpperCase(); - }); - hashes = hashes.filter(function(item, i, ar) { return ar.indexOf(item) === i; }); - const body = { - hash: hashes.join(), - text: this.text, - data: this.signature.packets.write() - }; - return armor(enums.armor.signed, body, undefined, undefined, undefined, config); - } - } - - /** - * Reads an OpenPGP cleartext signed message and returns a CleartextMessage object - * @param {Object} options - * @param {String} options.cleartextMessage - Text to be parsed - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} New cleartext message object. - * @async - * @static - */ - async function readCleartextMessage({ cleartextMessage, config, ...rest }) { - config = { ...defaultConfig, ...config }; - if (!cleartextMessage) { - throw new Error('readCleartextMessage: must pass options object containing `cleartextMessage`'); - } - if (!util.isString(cleartextMessage)) { - throw new Error('readCleartextMessage: options.cleartextMessage must be a string'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - const input = await unarmor(cleartextMessage); - if (input.type !== enums.armor.signed) { - throw new Error('No cleartext signed message.'); - } - const packetlist = await PacketList.fromBinary(input.data, allowedPackets$5, config); - verifyHeaders$1(input.headers, packetlist); - const signature = new Signature(packetlist); - return new CleartextMessage(input.text, signature); - } - - /** - * Compare hash algorithm specified in the armor header with signatures - * @param {Array} headers - Armor headers - * @param {PacketList} packetlist - The packetlist with signature packets - * @private - */ - function verifyHeaders$1(headers, packetlist) { - const checkHashAlgos = function(hashAlgos) { - const check = packet => algo => packet.hashAlgorithm === algo; - - for (let i = 0; i < packetlist.length; i++) { - if (packetlist[i].constructor.tag === enums.packet.signature && !hashAlgos.some(check(packetlist[i]))) { - return false; - } - } - return true; - }; - - let oneHeader = null; - let hashAlgos = []; - headers.forEach(function(header) { - oneHeader = header.match(/Hash: (.+)/); // get header value - if (oneHeader) { - oneHeader = oneHeader[1].replace(/\s/g, ''); // remove whitespace - oneHeader = oneHeader.split(','); - oneHeader = oneHeader.map(function(hash) { - hash = hash.toLowerCase(); - try { - return enums.write(enums.hash, hash); - } catch (e) { - throw new Error('Unknown hash algorithm in armor header: ' + hash); - } - }); - hashAlgos = hashAlgos.concat(oneHeader); - } else { - throw new Error('Only "Hash" header allowed in cleartext signed message'); - } - }); - - if (!hashAlgos.length && !checkHashAlgos([enums.hash.md5])) { - throw new Error('If no "Hash" header in cleartext signed message, then only MD5 signatures allowed'); - } else if (hashAlgos.length && !checkHashAlgos(hashAlgos)) { - throw new Error('Hash algorithm mismatch in armor header and signature'); - } - } - - /** - * Creates a new CleartextMessage object from text - * @param {Object} options - * @param {String} options.text - * @static - * @async - */ - async function createCleartextMessage({ text, ...rest }) { - if (!text) { - throw new Error('createCleartextMessage: must pass options object containing `text`'); - } - if (!util.isString(text)) { - throw new Error('createCleartextMessage: options.text must be a string'); - } - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - return new CleartextMessage(text); - } - - // OpenPGP.js - An OpenPGP implementation in javascript - - - ////////////////////// - // // - // Key handling // - // // - ////////////////////// - - - /** - * Generates a new OpenPGP key pair. Supports RSA and ECC keys. By default, primary and subkeys will be of same type. - * The generated primary key will have signing capabilities. By default, one subkey with encryption capabilities is also generated. - * @param {Object} options - * @param {Object|Array} options.userIDs - User IDs as objects: `{ name: 'Jo Doe', email: 'info@jo.com' }` - * @param {'ecc'|'rsa'} [options.type='ecc'] - The primary key algorithm type: ECC (default) or RSA - * @param {String} [options.passphrase=(not protected)] - The passphrase used to encrypt the generated private key. If omitted, the key won't be encrypted. - * @param {Number} [options.rsaBits=4096] - Number of bits for RSA keys - * @param {String} [options.curve='curve25519'] - Elliptic curve for ECC keys: - * curve25519 (default), p256, p384, p521, secp256k1, - * brainpoolP256r1, brainpoolP384r1, or brainpoolP512r1 - * @param {Date} [options.date=current date] - Override the creation date of the key and the key signatures - * @param {Number} [options.keyExpirationTime=0 (never expires)] - Number of seconds from the key creation time after which the key expires - * @param {Array} [options.subkeys=a single encryption subkey] - Options for each subkey e.g. `[{sign: true, passphrase: '123'}]` - * default to main key options, except for `sign` parameter that defaults to false, and indicates whether the subkey should sign rather than encrypt - * @param {'armored'|'binary'|'object'} [options.format='armored'] - format of the output keys - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} The generated key object in the form: - * { privateKey:PrivateKey|Uint8Array|String, publicKey:PublicKey|Uint8Array|String, revocationCertificate:String } - * @async - * @static - */ - async function generateKey({ userIDs = [], passphrase = '', type = 'ecc', rsaBits = 4096, curve = 'curve25519', keyExpirationTime = 0, date = new Date(), subkeys = [{}], format = 'armored', config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - userIDs = toArray$1(userIDs); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (userIDs.length === 0) { - throw new Error('UserIDs are required for key generation'); - } - if (type === 'rsa' && rsaBits < config.minRSABits) { - throw new Error(`rsaBits should be at least ${config.minRSABits}, got: ${rsaBits}`); - } - - const options = { userIDs, passphrase, type, rsaBits, curve, keyExpirationTime, date, subkeys }; - - try { - const { key, revocationCertificate } = await generate$2(options, config); - key.getKeys().forEach(({ keyPacket }) => checkKeyRequirements(keyPacket, config)); - - return { - privateKey: formatObject(key, format, config), - publicKey: formatObject(key.toPublic(), format, config), - revocationCertificate - }; - } catch (err) { - throw util.wrapError('Error generating keypair', err); - } - } - - /** - * Reformats signature packets for a key and rewraps key object. - * @param {Object} options - * @param {PrivateKey} options.privateKey - Private key to reformat - * @param {Object|Array} options.userIDs - User IDs as objects: `{ name: 'Jo Doe', email: 'info@jo.com' }` - * @param {String} [options.passphrase=(not protected)] - The passphrase used to encrypt the reformatted private key. If omitted, the key won't be encrypted. - * @param {Number} [options.keyExpirationTime=0 (never expires)] - Number of seconds from the key creation time after which the key expires - * @param {Date} [options.date] - Override the creation date of the key signatures. If the key was previously used to sign messages, it is recommended - * to set the same date as the key creation time to ensure that old message signatures will still be verifiable using the reformatted key. - * @param {'armored'|'binary'|'object'} [options.format='armored'] - format of the output keys - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} The generated key object in the form: - * { privateKey:PrivateKey|Uint8Array|String, publicKey:PublicKey|Uint8Array|String, revocationCertificate:String } - * @async - * @static - */ - async function reformatKey({ privateKey, userIDs = [], passphrase = '', keyExpirationTime = 0, date, format = 'armored', config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - userIDs = toArray$1(userIDs); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (userIDs.length === 0) { - throw new Error('UserIDs are required for key reformat'); - } - const options = { privateKey, userIDs, passphrase, keyExpirationTime, date }; - - try { - const { key: reformattedKey, revocationCertificate } = await reformat(options, config); - - return { - privateKey: formatObject(reformattedKey, format, config), - publicKey: formatObject(reformattedKey.toPublic(), format, config), - revocationCertificate - }; - } catch (err) { - throw util.wrapError('Error reformatting keypair', err); - } - } - - /** - * Revokes a key. Requires either a private key or a revocation certificate. - * If a revocation certificate is passed, the reasonForRevocation parameter will be ignored. - * @param {Object} options - * @param {Key} options.key - Public or private key to revoke - * @param {String} [options.revocationCertificate] - Revocation certificate to revoke the key with - * @param {Object} [options.reasonForRevocation] - Object indicating the reason for revocation - * @param {module:enums.reasonForRevocation} [options.reasonForRevocation.flag=[noReason]{@link module:enums.reasonForRevocation}] - Flag indicating the reason for revocation - * @param {String} [options.reasonForRevocation.string=""] - String explaining the reason for revocation - * @param {Date} [options.date] - Use the given date instead of the current time to verify validity of revocation certificate (if provided), or as creation time of the revocation signature - * @param {'armored'|'binary'|'object'} [options.format='armored'] - format of the output key(s) - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} The revoked key in the form: - * { privateKey:PrivateKey|Uint8Array|String, publicKey:PublicKey|Uint8Array|String } if private key is passed, or - * { privateKey: null, publicKey:PublicKey|Uint8Array|String } otherwise - * @async - * @static - */ - async function revokeKey({ key, revocationCertificate, reasonForRevocation, date = new Date(), format = 'armored', config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - try { - const revokedKey = revocationCertificate ? - await key.applyRevocationCertificate(revocationCertificate, date, config) : - await key.revoke(reasonForRevocation, date, config); - - return revokedKey.isPrivate() ? { - privateKey: formatObject(revokedKey, format, config), - publicKey: formatObject(revokedKey.toPublic(), format, config) - } : { - privateKey: null, - publicKey: formatObject(revokedKey, format, config) - }; - } catch (err) { - throw util.wrapError('Error revoking key', err); - } - } - - /** - * Unlock a private key with the given passphrase. - * This method does not change the original key. - * @param {Object} options - * @param {PrivateKey} options.privateKey - The private key to decrypt - * @param {String|Array} options.passphrase - The user's passphrase(s) - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} The unlocked key object. - * @async - */ - async function decryptKey({ privateKey, passphrase, config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (!privateKey.isPrivate()) { - throw new Error('Cannot decrypt a public key'); - } - const clonedPrivateKey = privateKey.clone(true); - const passphrases = util.isArray(passphrase) ? passphrase : [passphrase]; - - try { - await Promise.all(clonedPrivateKey.getKeys().map(key => ( - // try to decrypt each key with any of the given passphrases - util.anyPromise(passphrases.map(passphrase => key.keyPacket.decrypt(passphrase))) - ))); - - await clonedPrivateKey.validate(config); - return clonedPrivateKey; - } catch (err) { - clonedPrivateKey.clearPrivateParams(); - throw util.wrapError('Error decrypting private key', err); - } - } - - /** - * Lock a private key with the given passphrase. - * This method does not change the original key. - * @param {Object} options - * @param {PrivateKey} options.privateKey - The private key to encrypt - * @param {String|Array} options.passphrase - If multiple passphrases, they should be in the same order as the packets each should encrypt - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} The locked key object. - * @async - */ - async function encryptKey({ privateKey, passphrase, config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (!privateKey.isPrivate()) { - throw new Error('Cannot encrypt a public key'); - } - const clonedPrivateKey = privateKey.clone(true); - - const keys = clonedPrivateKey.getKeys(); - const passphrases = util.isArray(passphrase) ? passphrase : new Array(keys.length).fill(passphrase); - if (passphrases.length !== keys.length) { - throw new Error('Invalid number of passphrases given for key encryption'); - } - - try { - await Promise.all(keys.map(async (key, i) => { - const { keyPacket } = key; - await keyPacket.encrypt(passphrases[i], config); - keyPacket.clearPrivateParams(); - })); - return clonedPrivateKey; - } catch (err) { - clonedPrivateKey.clearPrivateParams(); - throw util.wrapError('Error encrypting private key', err); - } - } - - - /////////////////////////////////////////// - // // - // Message encryption and decryption // - // // - /////////////////////////////////////////// - - - /** - * Encrypts a message using public keys, passwords or both at once. At least one of `encryptionKeys` or `passwords` - * must be specified. If signing keys are specified, those will be used to sign the message. - * @param {Object} options - * @param {Message} options.message - Message to be encrypted as created by {@link createMessage} - * @param {PublicKey|PublicKey[]} [options.encryptionKeys] - Array of keys or single key, used to encrypt the message - * @param {PrivateKey|PrivateKey[]} [options.signingKeys] - Private keys for signing. If omitted message will not be signed - * @param {String|String[]} [options.passwords] - Array of passwords or a single password to encrypt the message - * @param {Object} [options.sessionKey] - Session key in the form: `{ data:Uint8Array, algorithm:String }` - * @param {'armored'|'binary'|'object'} [options.format='armored'] - Format of the returned message - * @param {Signature} [options.signature] - A detached signature to add to the encrypted message - * @param {Boolean} [options.wildcard=false] - Use a key ID of 0 instead of the public key IDs - * @param {KeyID|KeyID[]} [options.signingKeyIDs=latest-created valid signing (sub)keys] - Array of key IDs to use for signing. Each `signingKeyIDs[i]` corresponds to `signingKeys[i]` - * @param {KeyID|KeyID[]} [options.encryptionKeyIDs=latest-created valid encryption (sub)keys] - Array of key IDs to use for encryption. Each `encryptionKeyIDs[i]` corresponds to `encryptionKeys[i]` - * @param {Date} [options.date=current date] - Override the creation date of the message signature - * @param {Object|Object[]} [options.signingUserIDs=primary user IDs] - Array of user IDs to sign with, one per key in `signingKeys`, e.g. `[{ name: 'Steve Sender', email: 'steve@openpgp.org' }]` - * @param {Object|Object[]} [options.encryptionUserIDs=primary user IDs] - Array of user IDs to encrypt for, one per key in `encryptionKeys`, e.g. `[{ name: 'Robert Receiver', email: 'robert@openpgp.org' }]` - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise|MaybeStream>} Encrypted message (string if `armor` was true, the default; Uint8Array if `armor` was false). - * @async - * @static - */ - async function encrypt$4({ message, encryptionKeys, signingKeys, passwords, sessionKey, format = 'armored', signature = null, wildcard = false, signingKeyIDs = [], encryptionKeyIDs = [], date = new Date(), signingUserIDs = [], encryptionUserIDs = [], config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - checkMessage(message); checkOutputMessageFormat(format); - encryptionKeys = toArray$1(encryptionKeys); signingKeys = toArray$1(signingKeys); passwords = toArray$1(passwords); - signingKeyIDs = toArray$1(signingKeyIDs); encryptionKeyIDs = toArray$1(encryptionKeyIDs); signingUserIDs = toArray$1(signingUserIDs); encryptionUserIDs = toArray$1(encryptionUserIDs); - if (rest.detached) { - throw new Error("The `detached` option has been removed from openpgp.encrypt, separately call openpgp.sign instead. Don't forget to remove the `privateKeys` option as well."); - } - if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.encrypt, pass `encryptionKeys` instead'); - if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.encrypt, pass `signingKeys` instead'); - if (rest.armor !== undefined) throw new Error('The `armor` option has been removed from openpgp.encrypt, pass `format` instead.'); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (!signingKeys) { - signingKeys = []; - } - const streaming = message.fromStream; - try { - if (signingKeys.length || signature) { // sign the message only if signing keys or signature is specified - message = await message.sign(signingKeys, signature, signingKeyIDs, date, signingUserIDs, config); - } - message = message.compress( - await getPreferredAlgo('compression', encryptionKeys, date, encryptionUserIDs, config), - config - ); - message = await message.encrypt(encryptionKeys, passwords, sessionKey, wildcard, encryptionKeyIDs, date, encryptionUserIDs, config); - if (format === 'object') return message; - // serialize data - const armor = format === 'armored'; - const data = armor ? message.armor(config) : message.write(); - return convertStream(data, streaming, armor ? 'utf8' : 'binary'); - } catch (err) { - throw util.wrapError('Error encrypting message', err); - } - } - - /** - * Decrypts a message with the user's private key, a session key or a password. - * One of `decryptionKeys`, `sessionkeys` or `passwords` must be specified (passing a combination of these options is not supported). - * @param {Object} options - * @param {Message} options.message - The message object with the encrypted data - * @param {PrivateKey|PrivateKey[]} [options.decryptionKeys] - Private keys with decrypted secret key data or session key - * @param {String|String[]} [options.passwords] - Passwords to decrypt the message - * @param {Object|Object[]} [options.sessionKeys] - Session keys in the form: { data:Uint8Array, algorithm:String } - * @param {PublicKey|PublicKey[]} [options.verificationKeys] - Array of public keys or single key, to verify signatures - * @param {Boolean} [options.expectSigned=false] - If true, data decryption fails if the message is not signed with the provided publicKeys - * @param {'utf8'|'binary'} [options.format='utf8'] - Whether to return data as a string(Stream) or Uint8Array(Stream). If 'utf8' (the default), also normalize newlines. - * @param {Signature} [options.signature] - Detached signature for verification - * @param {Date} [options.date=current date] - Use the given date for verification instead of the current time - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} Object containing decrypted and verified message in the form: - * - * { - * data: MaybeStream, (if format was 'utf8', the default) - * data: MaybeStream, (if format was 'binary') - * filename: String, - * signatures: [ - * { - * keyID: module:type/keyid~KeyID, - * verified: Promise, - * signature: Promise - * }, ... - * ] - * } - * - * where `signatures` contains a separate entry for each signature packet found in the input message. - * @async - * @static - */ - async function decrypt$4({ message, decryptionKeys, passwords, sessionKeys, verificationKeys, expectSigned = false, format = 'utf8', signature = null, date = new Date(), config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - checkMessage(message); verificationKeys = toArray$1(verificationKeys); decryptionKeys = toArray$1(decryptionKeys); passwords = toArray$1(passwords); sessionKeys = toArray$1(sessionKeys); - if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.decrypt, pass `decryptionKeys` instead'); - if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.decrypt, pass `verificationKeys` instead'); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - try { - const decrypted = await message.decrypt(decryptionKeys, passwords, sessionKeys, date, config); - if (!verificationKeys) { - verificationKeys = []; - } - - const result = {}; - result.signatures = signature ? await decrypted.verifyDetached(signature, verificationKeys, date, config) : await decrypted.verify(verificationKeys, date, config); - result.data = format === 'binary' ? decrypted.getLiteralData() : decrypted.getText(); - result.filename = decrypted.getFilename(); - linkStreams(result, message); - if (expectSigned) { - if (verificationKeys.length === 0) { - throw new Error('Verification keys are required to verify message signatures'); - } - if (result.signatures.length === 0) { - throw new Error('Message is not signed'); - } - result.data = concat([ - result.data, - fromAsync(async () => { - await util.anyPromise(result.signatures.map(sig => sig.verified)); - }) - ]); - } - result.data = await convertStream(result.data, message.fromStream, format); - return result; - } catch (err) { - throw util.wrapError('Error decrypting message', err); - } - } - - - ////////////////////////////////////////// - // // - // Message signing and verification // - // // - ////////////////////////////////////////// - - - /** - * Signs a message. - * @param {Object} options - * @param {CleartextMessage|Message} options.message - (cleartext) message to be signed - * @param {PrivateKey|PrivateKey[]} options.signingKeys - Array of keys or single key with decrypted secret key data to sign cleartext - * @param {'armored'|'binary'|'object'} [options.format='armored'] - Format of the returned message - * @param {Boolean} [options.detached=false] - If the return value should contain a detached signature - * @param {KeyID|KeyID[]} [options.signingKeyIDs=latest-created valid signing (sub)keys] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i] - * @param {Date} [options.date=current date] - Override the creation date of the signature - * @param {Object|Object[]} [options.signingUserIDs=primary user IDs] - Array of user IDs to sign with, one per key in `signingKeys`, e.g. `[{ name: 'Steve Sender', email: 'steve@openpgp.org' }]` - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise>} Signed message (string if `armor` was true, the default; Uint8Array if `armor` was false). - * @async - * @static - */ - async function sign$5({ message, signingKeys, format = 'armored', detached = false, signingKeyIDs = [], date = new Date(), signingUserIDs = [], config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - checkCleartextOrMessage(message); checkOutputMessageFormat(format); - signingKeys = toArray$1(signingKeys); signingKeyIDs = toArray$1(signingKeyIDs); signingUserIDs = toArray$1(signingUserIDs); - - if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.sign, pass `signingKeys` instead'); - if (rest.armor !== undefined) throw new Error('The `armor` option has been removed from openpgp.sign, pass `format` instead.'); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (message instanceof CleartextMessage && format === 'binary') throw new Error('Cannot return signed cleartext message in binary format'); - if (message instanceof CleartextMessage && detached) throw new Error('Cannot detach-sign a cleartext message'); - - if (!signingKeys || signingKeys.length === 0) { - throw new Error('No signing keys provided'); - } - - try { - let signature; - if (detached) { - signature = await message.signDetached(signingKeys, undefined, signingKeyIDs, date, signingUserIDs, config); - } else { - signature = await message.sign(signingKeys, undefined, signingKeyIDs, date, signingUserIDs, config); - } - if (format === 'object') return signature; - - const armor = format === 'armored'; - signature = armor ? signature.armor(config) : signature.write(); - if (detached) { - signature = transformPair(message.packets.write(), async (readable, writable) => { - await Promise.all([ - pipe(signature, writable), - readToEnd(readable).catch(() => {}) - ]); - }); - } - return convertStream(signature, message.fromStream, armor ? 'utf8' : 'binary'); - } catch (err) { - throw util.wrapError('Error signing message', err); - } - } - - /** - * Verifies signatures of cleartext signed message - * @param {Object} options - * @param {CleartextMessage|Message} options.message - (cleartext) message object with signatures - * @param {PublicKey|PublicKey[]} options.verificationKeys - Array of publicKeys or single key, to verify signatures - * @param {Boolean} [options.expectSigned=false] - If true, verification throws if the message is not signed with the provided publicKeys - * @param {'utf8'|'binary'} [options.format='utf8'] - Whether to return data as a string(Stream) or Uint8Array(Stream). If 'utf8' (the default), also normalize newlines. - * @param {Signature} [options.signature] - Detached signature for verification - * @param {Date} [options.date=current date] - Use the given date for verification instead of the current time - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} Object containing verified message in the form: - * - * { - * data: MaybeStream, (if `message` was a CleartextMessage) - * data: MaybeStream, (if `message` was a Message) - * signatures: [ - * { - * keyID: module:type/keyid~KeyID, - * verified: Promise, - * signature: Promise - * }, ... - * ] - * } - * - * where `signatures` contains a separate entry for each signature packet found in the input message. - * @async - * @static - */ - async function verify$5({ message, verificationKeys, expectSigned = false, format = 'utf8', signature = null, date = new Date(), config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - checkCleartextOrMessage(message); verificationKeys = toArray$1(verificationKeys); - if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.verify, pass `verificationKeys` instead'); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - if (message instanceof CleartextMessage && format === 'binary') throw new Error("Can't return cleartext message data as binary"); - if (message instanceof CleartextMessage && signature) throw new Error("Can't verify detached cleartext signature"); - - try { - const result = {}; - if (signature) { - result.signatures = await message.verifyDetached(signature, verificationKeys, date, config); - } else { - result.signatures = await message.verify(verificationKeys, date, config); - } - result.data = format === 'binary' ? message.getLiteralData() : message.getText(); - if (message.fromStream) linkStreams(result, message); - if (expectSigned) { - if (result.signatures.length === 0) { - throw new Error('Message is not signed'); - } - result.data = concat([ - result.data, - fromAsync(async () => { - await util.anyPromise(result.signatures.map(sig => sig.verified)); - }) - ]); - } - result.data = await convertStream(result.data, message.fromStream, format); - return result; - } catch (err) { - throw util.wrapError('Error verifying signed message', err); - } - } - - - /////////////////////////////////////////////// - // // - // Session key encryption and decryption // - // // - /////////////////////////////////////////////// - - /** - * Generate a new session key object, taking the algorithm preferences of the passed public keys into account. - * @param {Object} options - * @param {PublicKey|PublicKey[]} options.encryptionKeys - Array of public keys or single key used to select algorithm preferences for - * @param {Date} [options.date=current date] - Date to select algorithm preferences at - * @param {Object|Object[]} [options.encryptionUserIDs=primary user IDs] - User IDs to select algorithm preferences for - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise<{ data: Uint8Array, algorithm: String }>} Object with session key data and algorithm. - * @async - * @static - */ - async function generateSessionKey$1({ encryptionKeys, date = new Date(), encryptionUserIDs = [], config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - encryptionKeys = toArray$1(encryptionKeys); encryptionUserIDs = toArray$1(encryptionUserIDs); - if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.generateSessionKey, pass `encryptionKeys` instead'); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - try { - const sessionKeys = await Message.generateSessionKey(encryptionKeys, date, encryptionUserIDs, config); - return sessionKeys; - } catch (err) { - throw util.wrapError('Error generating session key', err); - } - } - - /** - * Encrypt a symmetric session key with public keys, passwords, or both at once. - * At least one of `encryptionKeys` or `passwords` must be specified. - * @param {Object} options - * @param {Uint8Array} options.data - The session key to be encrypted e.g. 16 random bytes (for aes128) - * @param {String} options.algorithm - Algorithm of the symmetric session key e.g. 'aes128' or 'aes256' - * @param {String} [options.aeadAlgorithm] - AEAD algorithm, e.g. 'eax' or 'ocb' - * @param {PublicKey|PublicKey[]} [options.encryptionKeys] - Array of public keys or single key, used to encrypt the key - * @param {String|String[]} [options.passwords] - Passwords for the message - * @param {'armored'|'binary'} [options.format='armored'] - Format of the returned value - * @param {Boolean} [options.wildcard=false] - Use a key ID of 0 instead of the public key IDs - * @param {KeyID|KeyID[]} [options.encryptionKeyIDs=latest-created valid encryption (sub)keys] - Array of key IDs to use for encryption. Each encryptionKeyIDs[i] corresponds to encryptionKeys[i] - * @param {Date} [options.date=current date] - Override the date - * @param {Object|Object[]} [options.encryptionUserIDs=primary user IDs] - Array of user IDs to encrypt for, one per key in `encryptionKeys`, e.g. `[{ name: 'Phil Zimmermann', email: 'phil@openpgp.org' }]` - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} Encrypted session keys (string if `armor` was true, the default; Uint8Array if `armor` was false). - * @async - * @static - */ - async function encryptSessionKey({ data, algorithm, aeadAlgorithm, encryptionKeys, passwords, format = 'armored', wildcard = false, encryptionKeyIDs = [], date = new Date(), encryptionUserIDs = [], config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - checkBinary(data); checkString(algorithm, 'algorithm'); checkOutputMessageFormat(format); - encryptionKeys = toArray$1(encryptionKeys); passwords = toArray$1(passwords); encryptionKeyIDs = toArray$1(encryptionKeyIDs); encryptionUserIDs = toArray$1(encryptionUserIDs); - if (rest.publicKeys) throw new Error('The `publicKeys` option has been removed from openpgp.encryptSessionKey, pass `encryptionKeys` instead'); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - try { - const message = await Message.encryptSessionKey(data, algorithm, aeadAlgorithm, encryptionKeys, passwords, wildcard, encryptionKeyIDs, date, encryptionUserIDs, config); - return formatObject(message, format, config); - } catch (err) { - throw util.wrapError('Error encrypting session key', err); - } - } - - /** - * Decrypt symmetric session keys using private keys or passwords (not both). - * One of `decryptionKeys` or `passwords` must be specified. - * @param {Object} options - * @param {Message} options.message - A message object containing the encrypted session key packets - * @param {PrivateKey|PrivateKey[]} [options.decryptionKeys] - Private keys with decrypted secret key data - * @param {String|String[]} [options.passwords] - Passwords to decrypt the session key - * @param {Date} [options.date] - Date to use for key verification instead of the current time - * @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config} - * @returns {Promise} Array of decrypted session key, algorithm pairs in the form: - * { data:Uint8Array, algorithm:String } - * @throws if no session key could be found or decrypted - * @async - * @static - */ - async function decryptSessionKeys({ message, decryptionKeys, passwords, date = new Date(), config, ...rest }) { - config = { ...defaultConfig, ...config }; checkConfig(config); - checkMessage(message); decryptionKeys = toArray$1(decryptionKeys); passwords = toArray$1(passwords); - if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.decryptSessionKeys, pass `decryptionKeys` instead'); - const unknownOptions = Object.keys(rest); if (unknownOptions.length > 0) throw new Error(`Unknown option: ${unknownOptions.join(', ')}`); - - try { - const sessionKeys = await message.decryptSessionKeys(decryptionKeys, passwords, date, config); - return sessionKeys; - } catch (err) { - throw util.wrapError('Error decrypting session keys', err); - } - } - - - ////////////////////////// - // // - // Helper functions // - // // - ////////////////////////// - - - /** - * Input validation - * @private - */ - function checkString(data, name) { - if (!util.isString(data)) { - throw new Error('Parameter [' + (name || 'data') + '] must be of type String'); - } - } - function checkBinary(data, name) { - if (!util.isUint8Array(data)) { - throw new Error('Parameter [' + (name || 'data') + '] must be of type Uint8Array'); - } - } - function checkMessage(message) { - if (!(message instanceof Message)) { - throw new Error('Parameter [message] needs to be of type Message'); - } - } - function checkCleartextOrMessage(message) { - if (!(message instanceof CleartextMessage) && !(message instanceof Message)) { - throw new Error('Parameter [message] needs to be of type Message or CleartextMessage'); - } - } - function checkOutputMessageFormat(format) { - if (format !== 'armored' && format !== 'binary' && format !== 'object') { - throw new Error(`Unsupported format ${format}`); - } - } - const defaultConfigPropsCount = Object.keys(defaultConfig).length; - function checkConfig(config) { - const inputConfigProps = Object.keys(config); - if (inputConfigProps.length !== defaultConfigPropsCount) { - for (const inputProp of inputConfigProps) { - if (defaultConfig[inputProp] === undefined) { - throw new Error(`Unknown config property: ${inputProp}`); - } - } - } - } - - /** - * Normalize parameter to an array if it is not undefined. - * @param {Object} param - the parameter to be normalized - * @returns {Array|undefined} The resulting array or undefined. - * @private - */ - function toArray$1(param) { - if (param && !util.isArray(param)) { - param = [param]; - } - return param; - } - - /** - * Convert data to or from Stream - * @param {Object} data - the data to convert - * @param {'web'|'ponyfill'|'node'|false} streaming - Whether to return a ReadableStream, and of what type - * @param {'utf8'|'binary'} [encoding] - How to return data in Node Readable streams - * @returns {Promise} The data in the respective format. - * @async - * @private - */ - async function convertStream(data, streaming, encoding = 'utf8') { - const streamType = util.isStream(data); - if (streamType === 'array') { - return readToEnd(data); - } - if (streaming === 'node') { - data = webToNode(data); - if (encoding !== 'binary') data.setEncoding(encoding); - return data; - } - if (streaming === 'web' && streamType === 'ponyfill') { - return toNativeReadable(data); - } - return data; - } - - /** - * Link result.data to the message stream for cancellation. - * Also, forward errors in the message to result.data. - * @param {Object} result - the data to convert - * @param {Message} message - message object - * @returns {Object} - * @private - */ - function linkStreams(result, message) { - result.data = transformPair(message.packets.stream, async (readable, writable) => { - await pipe(result.data, writable, { - preventClose: true - }); - const writer = getWriter(writable); - try { - // Forward errors in the message stream to result.data. - await readToEnd(readable, _ => _); - await writer.close(); - } catch (e) { - await writer.abort(e); - } - }); - } - - /** - * Convert the object to the given format - * @param {Key|Message} object - * @param {'armored'|'binary'|'object'} format - * @param {Object} config - Full configuration - * @returns {String|Uint8Array|Object} - */ - function formatObject(object, format, config) { - switch (format) { - case 'object': - return object; - case 'armored': - return object.armor(config); - case 'binary': - return object.write(); - default: - throw new Error(`Unsupported format ${format}`); - } - } - - /** - * web-streams-polyfill v3.0.3 - */ - /// - const SymbolPolyfill = typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol' ? - Symbol : - description => `Symbol(${description})`; - - /// - function noop() { - return undefined; - } - function getGlobals() { - if (typeof self !== 'undefined') { - return self; - } - else if (typeof window !== 'undefined') { - return window; - } - else if (typeof global !== 'undefined') { - return global; - } - return undefined; - } - const globals = getGlobals(); - - function typeIsObject(x) { - return (typeof x === 'object' && x !== null) || typeof x === 'function'; - } - const rethrowAssertionErrorRejection = noop; - - const originalPromise = Promise; - const originalPromiseThen = Promise.prototype.then; - const originalPromiseResolve = Promise.resolve.bind(originalPromise); - const originalPromiseReject = Promise.reject.bind(originalPromise); - function newPromise(executor) { - return new originalPromise(executor); - } - function promiseResolvedWith(value) { - return originalPromiseResolve(value); - } - function promiseRejectedWith(reason) { - return originalPromiseReject(reason); - } - function PerformPromiseThen(promise, onFulfilled, onRejected) { - // There doesn't appear to be any way to correctly emulate the behaviour from JavaScript, so this is just an - // approximation. - return originalPromiseThen.call(promise, onFulfilled, onRejected); - } - function uponPromise(promise, onFulfilled, onRejected) { - PerformPromiseThen(PerformPromiseThen(promise, onFulfilled, onRejected), undefined, rethrowAssertionErrorRejection); - } - function uponFulfillment(promise, onFulfilled) { - uponPromise(promise, onFulfilled); - } - function uponRejection(promise, onRejected) { - uponPromise(promise, undefined, onRejected); - } - function transformPromiseWith(promise, fulfillmentHandler, rejectionHandler) { - return PerformPromiseThen(promise, fulfillmentHandler, rejectionHandler); - } - function setPromiseIsHandledToTrue(promise) { - PerformPromiseThen(promise, undefined, rethrowAssertionErrorRejection); - } - const queueMicrotask = (() => { - const globalQueueMicrotask = globals && globals.queueMicrotask; - if (typeof globalQueueMicrotask === 'function') { - return globalQueueMicrotask; - } - const resolvedPromise = promiseResolvedWith(undefined); - return (fn) => PerformPromiseThen(resolvedPromise, fn); - })(); - function reflectCall(F, V, args) { - if (typeof F !== 'function') { - throw new TypeError('Argument is not a function'); - } - return Function.prototype.apply.call(F, V, args); - } - function promiseCall(F, V, args) { - try { - return promiseResolvedWith(reflectCall(F, V, args)); - } - catch (value) { - return promiseRejectedWith(value); - } - } - - // Original from Chromium - // https://chromium.googlesource.com/chromium/src/+/0aee4434a4dba42a42abaea9bfbc0cd196a63bc1/third_party/blink/renderer/core/streams/SimpleQueue.js - const QUEUE_MAX_ARRAY_SIZE = 16384; - /** - * Simple queue structure. - * - * Avoids scalability issues with using a packed array directly by using - * multiple arrays in a linked list and keeping the array size bounded. - */ - class SimpleQueue { - constructor() { - this._cursor = 0; - this._size = 0; - // _front and _back are always defined. - this._front = { - _elements: [], - _next: undefined - }; - this._back = this._front; - // The cursor is used to avoid calling Array.shift(). - // It contains the index of the front element of the array inside the - // front-most node. It is always in the range [0, QUEUE_MAX_ARRAY_SIZE). - this._cursor = 0; - // When there is only one node, size === elements.length - cursor. - this._size = 0; - } - get length() { - return this._size; - } - // For exception safety, this method is structured in order: - // 1. Read state - // 2. Calculate required state mutations - // 3. Perform state mutations - push(element) { - const oldBack = this._back; - let newBack = oldBack; - if (oldBack._elements.length === QUEUE_MAX_ARRAY_SIZE - 1) { - newBack = { - _elements: [], - _next: undefined - }; - } - // push() is the mutation most likely to throw an exception, so it - // goes first. - oldBack._elements.push(element); - if (newBack !== oldBack) { - this._back = newBack; - oldBack._next = newBack; - } - ++this._size; - } - // Like push(), shift() follows the read -> calculate -> mutate pattern for - // exception safety. - shift() { // must not be called on an empty queue - const oldFront = this._front; - let newFront = oldFront; - const oldCursor = this._cursor; - let newCursor = oldCursor + 1; - const elements = oldFront._elements; - const element = elements[oldCursor]; - if (newCursor === QUEUE_MAX_ARRAY_SIZE) { - newFront = oldFront._next; - newCursor = 0; - } - // No mutations before this point. - --this._size; - this._cursor = newCursor; - if (oldFront !== newFront) { - this._front = newFront; - } - // Permit shifted element to be garbage collected. - elements[oldCursor] = undefined; - return element; - } - // The tricky thing about forEach() is that it can be called - // re-entrantly. The queue may be mutated inside the callback. It is easy to - // see that push() within the callback has no negative effects since the end - // of the queue is checked for on every iteration. If shift() is called - // repeatedly within the callback then the next iteration may return an - // element that has been removed. In this case the callback will be called - // with undefined values until we either "catch up" with elements that still - // exist or reach the back of the queue. - forEach(callback) { - let i = this._cursor; - let node = this._front; - let elements = node._elements; - while (i !== elements.length || node._next !== undefined) { - if (i === elements.length) { - node = node._next; - elements = node._elements; - i = 0; - if (elements.length === 0) { - break; - } - } - callback(elements[i]); - ++i; - } - } - // Return the element that would be returned if shift() was called now, - // without modifying the queue. - peek() { // must not be called on an empty queue - const front = this._front; - const cursor = this._cursor; - return front._elements[cursor]; - } - } - - function ReadableStreamReaderGenericInitialize(reader, stream) { - reader._ownerReadableStream = stream; - stream._reader = reader; - if (stream._state === 'readable') { - defaultReaderClosedPromiseInitialize(reader); - } - else if (stream._state === 'closed') { - defaultReaderClosedPromiseInitializeAsResolved(reader); - } - else { - defaultReaderClosedPromiseInitializeAsRejected(reader, stream._storedError); - } - } - // A client of ReadableStreamDefaultReader and ReadableStreamBYOBReader may use these functions directly to bypass state - // check. - function ReadableStreamReaderGenericCancel(reader, reason) { - const stream = reader._ownerReadableStream; - return ReadableStreamCancel(stream, reason); - } - function ReadableStreamReaderGenericRelease(reader) { - if (reader._ownerReadableStream._state === 'readable') { - defaultReaderClosedPromiseReject(reader, new TypeError(`Reader was released and can no longer be used to monitor the stream's closedness`)); - } - else { - defaultReaderClosedPromiseResetToRejected(reader, new TypeError(`Reader was released and can no longer be used to monitor the stream's closedness`)); - } - reader._ownerReadableStream._reader = undefined; - reader._ownerReadableStream = undefined; - } - // Helper functions for the readers. - function readerLockException(name) { - return new TypeError('Cannot ' + name + ' a stream using a released reader'); - } - // Helper functions for the ReadableStreamDefaultReader. - function defaultReaderClosedPromiseInitialize(reader) { - reader._closedPromise = newPromise((resolve, reject) => { - reader._closedPromise_resolve = resolve; - reader._closedPromise_reject = reject; - }); - } - function defaultReaderClosedPromiseInitializeAsRejected(reader, reason) { - defaultReaderClosedPromiseInitialize(reader); - defaultReaderClosedPromiseReject(reader, reason); - } - function defaultReaderClosedPromiseInitializeAsResolved(reader) { - defaultReaderClosedPromiseInitialize(reader); - defaultReaderClosedPromiseResolve(reader); - } - function defaultReaderClosedPromiseReject(reader, reason) { - if (reader._closedPromise_reject === undefined) { - return; - } - setPromiseIsHandledToTrue(reader._closedPromise); - reader._closedPromise_reject(reason); - reader._closedPromise_resolve = undefined; - reader._closedPromise_reject = undefined; - } - function defaultReaderClosedPromiseResetToRejected(reader, reason) { - defaultReaderClosedPromiseInitializeAsRejected(reader, reason); - } - function defaultReaderClosedPromiseResolve(reader) { - if (reader._closedPromise_resolve === undefined) { - return; - } - reader._closedPromise_resolve(undefined); - reader._closedPromise_resolve = undefined; - reader._closedPromise_reject = undefined; - } - - const AbortSteps = SymbolPolyfill('[[AbortSteps]]'); - const ErrorSteps = SymbolPolyfill('[[ErrorSteps]]'); - const CancelSteps = SymbolPolyfill('[[CancelSteps]]'); - const PullSteps = SymbolPolyfill('[[PullSteps]]'); - - /// - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isFinite#Polyfill - const NumberIsFinite = Number.isFinite || function (x) { - return typeof x === 'number' && isFinite(x); - }; - - /// - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc#Polyfill - const MathTrunc = Math.trunc || function (v) { - return v < 0 ? Math.ceil(v) : Math.floor(v); - }; - - // https://heycam.github.io/webidl/#idl-dictionaries - function isDictionary(x) { - return typeof x === 'object' || typeof x === 'function'; - } - function assertDictionary(obj, context) { - if (obj !== undefined && !isDictionary(obj)) { - throw new TypeError(`${context} is not an object.`); - } - } - // https://heycam.github.io/webidl/#idl-callback-functions - function assertFunction(x, context) { - if (typeof x !== 'function') { - throw new TypeError(`${context} is not a function.`); - } - } - // https://heycam.github.io/webidl/#idl-object - function isObject(x) { - return (typeof x === 'object' && x !== null) || typeof x === 'function'; - } - function assertObject(x, context) { - if (!isObject(x)) { - throw new TypeError(`${context} is not an object.`); - } - } - function assertRequiredArgument(x, position, context) { - if (x === undefined) { - throw new TypeError(`Parameter ${position} is required in '${context}'.`); - } - } - function assertRequiredField(x, field, context) { - if (x === undefined) { - throw new TypeError(`${field} is required in '${context}'.`); - } - } - // https://heycam.github.io/webidl/#idl-unrestricted-double - function convertUnrestrictedDouble(value) { - return Number(value); - } - function censorNegativeZero(x) { - return x === 0 ? 0 : x; - } - function integerPart(x) { - return censorNegativeZero(MathTrunc(x)); - } - // https://heycam.github.io/webidl/#idl-unsigned-long-long - function convertUnsignedLongLongWithEnforceRange(value, context) { - const lowerBound = 0; - const upperBound = Number.MAX_SAFE_INTEGER; - let x = Number(value); - x = censorNegativeZero(x); - if (!NumberIsFinite(x)) { - throw new TypeError(`${context} is not a finite number`); - } - x = integerPart(x); - if (x < lowerBound || x > upperBound) { - throw new TypeError(`${context} is outside the accepted range of ${lowerBound} to ${upperBound}, inclusive`); - } - if (!NumberIsFinite(x) || x === 0) { - return 0; - } - // TODO Use BigInt if supported? - // let xBigInt = BigInt(integerPart(x)); - // xBigInt = BigInt.asUintN(64, xBigInt); - // return Number(xBigInt); - return x; - } - - function assertReadableStream(x, context) { - if (!IsReadableStream(x)) { - throw new TypeError(`${context} is not a ReadableStream.`); - } - } - - // Abstract operations for the ReadableStream. - function AcquireReadableStreamDefaultReader(stream) { - return new ReadableStreamDefaultReader(stream); - } - // ReadableStream API exposed for controllers. - function ReadableStreamAddReadRequest(stream, readRequest) { - stream._reader._readRequests.push(readRequest); - } - function ReadableStreamFulfillReadRequest(stream, chunk, done) { - const reader = stream._reader; - const readRequest = reader._readRequests.shift(); - if (done) { - readRequest._closeSteps(); - } - else { - readRequest._chunkSteps(chunk); - } - } - function ReadableStreamGetNumReadRequests(stream) { - return stream._reader._readRequests.length; - } - function ReadableStreamHasDefaultReader(stream) { - const reader = stream._reader; - if (reader === undefined) { - return false; - } - if (!IsReadableStreamDefaultReader(reader)) { - return false; - } - return true; - } - /** - * A default reader vended by a {@link ReadableStream}. - * - * @public - */ - class ReadableStreamDefaultReader { - constructor(stream) { - assertRequiredArgument(stream, 1, 'ReadableStreamDefaultReader'); - assertReadableStream(stream, 'First parameter'); - if (IsReadableStreamLocked(stream)) { - throw new TypeError('This stream has already been locked for exclusive reading by another reader'); - } - ReadableStreamReaderGenericInitialize(this, stream); - this._readRequests = new SimpleQueue(); - } - /** - * Returns a promise that will be fulfilled when the stream becomes closed, - * or rejected if the stream ever errors or the reader's lock is released before the stream finishes closing. - */ - get closed() { - if (!IsReadableStreamDefaultReader(this)) { - return promiseRejectedWith(defaultReaderBrandCheckException('closed')); - } - return this._closedPromise; - } - /** - * If the reader is active, behaves the same as {@link ReadableStream.cancel | stream.cancel(reason)}. - */ - cancel(reason = undefined) { - if (!IsReadableStreamDefaultReader(this)) { - return promiseRejectedWith(defaultReaderBrandCheckException('cancel')); - } - if (this._ownerReadableStream === undefined) { - return promiseRejectedWith(readerLockException('cancel')); - } - return ReadableStreamReaderGenericCancel(this, reason); - } - /** - * Returns a promise that allows access to the next chunk from the stream's internal queue, if available. - * - * If reading a chunk causes the queue to become empty, more data will be pulled from the underlying source. - */ - read() { - if (!IsReadableStreamDefaultReader(this)) { - return promiseRejectedWith(defaultReaderBrandCheckException('read')); - } - if (this._ownerReadableStream === undefined) { - return promiseRejectedWith(readerLockException('read from')); - } - let resolvePromise; - let rejectPromise; - const promise = newPromise((resolve, reject) => { - resolvePromise = resolve; - rejectPromise = reject; - }); - const readRequest = { - _chunkSteps: chunk => resolvePromise({ value: chunk, done: false }), - _closeSteps: () => resolvePromise({ value: undefined, done: true }), - _errorSteps: e => rejectPromise(e) - }; - ReadableStreamDefaultReaderRead(this, readRequest); - return promise; - } - /** - * Releases the reader's lock on the corresponding stream. After the lock is released, the reader is no longer active. - * If the associated stream is errored when the lock is released, the reader will appear errored in the same way - * from now on; otherwise, the reader will appear closed. - * - * A reader's lock cannot be released while it still has a pending read request, i.e., if a promise returned by - * the reader's {@link ReadableStreamDefaultReader.read | read()} method has not yet been settled. Attempting to - * do so will throw a `TypeError` and leave the reader locked to the stream. - */ - releaseLock() { - if (!IsReadableStreamDefaultReader(this)) { - throw defaultReaderBrandCheckException('releaseLock'); - } - if (this._ownerReadableStream === undefined) { - return; - } - if (this._readRequests.length > 0) { - throw new TypeError('Tried to release a reader lock when that reader has pending read() calls un-settled'); - } - ReadableStreamReaderGenericRelease(this); - } - } - Object.defineProperties(ReadableStreamDefaultReader.prototype, { - cancel: { enumerable: true }, - read: { enumerable: true }, - releaseLock: { enumerable: true }, - closed: { enumerable: true } - }); - if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(ReadableStreamDefaultReader.prototype, SymbolPolyfill.toStringTag, { - value: 'ReadableStreamDefaultReader', - configurable: true - }); - } - // Abstract operations for the readers. - function IsReadableStreamDefaultReader(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_readRequests')) { - return false; - } - return true; - } - function ReadableStreamDefaultReaderRead(reader, readRequest) { - const stream = reader._ownerReadableStream; - stream._disturbed = true; - if (stream._state === 'closed') { - readRequest._closeSteps(); - } - else if (stream._state === 'errored') { - readRequest._errorSteps(stream._storedError); - } - else { - stream._readableStreamController[PullSteps](readRequest); - } - } - // Helper functions for the ReadableStreamDefaultReader. - function defaultReaderBrandCheckException(name) { - return new TypeError(`ReadableStreamDefaultReader.prototype.${name} can only be used on a ReadableStreamDefaultReader`); - } - - /// - let AsyncIteratorPrototype; - if (typeof SymbolPolyfill.asyncIterator === 'symbol') { - // We're running inside a ES2018+ environment, but we're compiling to an older syntax. - // We cannot access %AsyncIteratorPrototype% without non-ES2018 syntax, but we can re-create it. - AsyncIteratorPrototype = { - // 25.1.3.1 %AsyncIteratorPrototype% [ @@asyncIterator ] ( ) - // https://tc39.github.io/ecma262/#sec-asynciteratorprototype-asynciterator - [SymbolPolyfill.asyncIterator]() { - return this; - } - }; - Object.defineProperty(AsyncIteratorPrototype, SymbolPolyfill.asyncIterator, { enumerable: false }); - } - - /// - class ReadableStreamAsyncIteratorImpl { - constructor(reader, preventCancel) { - this._ongoingPromise = undefined; - this._isFinished = false; - this._reader = reader; - this._preventCancel = preventCancel; - } - next() { - const nextSteps = () => this._nextSteps(); - this._ongoingPromise = this._ongoingPromise ? - transformPromiseWith(this._ongoingPromise, nextSteps, nextSteps) : - nextSteps(); - return this._ongoingPromise; - } - return(value) { - const returnSteps = () => this._returnSteps(value); - return this._ongoingPromise ? - transformPromiseWith(this._ongoingPromise, returnSteps, returnSteps) : - returnSteps(); - } - _nextSteps() { - if (this._isFinished) { - return Promise.resolve({ value: undefined, done: true }); - } - const reader = this._reader; - if (reader._ownerReadableStream === undefined) { - return promiseRejectedWith(readerLockException('iterate')); - } - let resolvePromise; - let rejectPromise; - const promise = newPromise((resolve, reject) => { - resolvePromise = resolve; - rejectPromise = reject; - }); - const readRequest = { - _chunkSteps: chunk => { - this._ongoingPromise = undefined; - // This needs to be delayed by one microtask, otherwise we stop pulling too early which breaks a test. - // FIXME Is this a bug in the specification, or in the test? - queueMicrotask(() => resolvePromise({ value: chunk, done: false })); - }, - _closeSteps: () => { - this._ongoingPromise = undefined; - this._isFinished = true; - ReadableStreamReaderGenericRelease(reader); - resolvePromise({ value: undefined, done: true }); - }, - _errorSteps: reason => { - this._ongoingPromise = undefined; - this._isFinished = true; - ReadableStreamReaderGenericRelease(reader); - rejectPromise(reason); - } - }; - ReadableStreamDefaultReaderRead(reader, readRequest); - return promise; - } - _returnSteps(value) { - if (this._isFinished) { - return Promise.resolve({ value, done: true }); - } - this._isFinished = true; - const reader = this._reader; - if (reader._ownerReadableStream === undefined) { - return promiseRejectedWith(readerLockException('finish iterating')); - } - if (!this._preventCancel) { - const result = ReadableStreamReaderGenericCancel(reader, value); - ReadableStreamReaderGenericRelease(reader); - return transformPromiseWith(result, () => ({ value, done: true })); - } - ReadableStreamReaderGenericRelease(reader); - return promiseResolvedWith({ value, done: true }); - } - } - const ReadableStreamAsyncIteratorPrototype = { - next() { - if (!IsReadableStreamAsyncIterator(this)) { - return promiseRejectedWith(streamAsyncIteratorBrandCheckException('next')); - } - return this._asyncIteratorImpl.next(); - }, - return(value) { - if (!IsReadableStreamAsyncIterator(this)) { - return promiseRejectedWith(streamAsyncIteratorBrandCheckException('return')); - } - return this._asyncIteratorImpl.return(value); - } - }; - if (AsyncIteratorPrototype !== undefined) { - Object.setPrototypeOf(ReadableStreamAsyncIteratorPrototype, AsyncIteratorPrototype); - } - // Abstract operations for the ReadableStream. - function AcquireReadableStreamAsyncIterator(stream, preventCancel) { - const reader = AcquireReadableStreamDefaultReader(stream); - const impl = new ReadableStreamAsyncIteratorImpl(reader, preventCancel); - const iterator = Object.create(ReadableStreamAsyncIteratorPrototype); - iterator._asyncIteratorImpl = impl; - return iterator; - } - function IsReadableStreamAsyncIterator(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_asyncIteratorImpl')) { - return false; - } - return true; - } - // Helper functions for the ReadableStream. - function streamAsyncIteratorBrandCheckException(name) { - return new TypeError(`ReadableStreamAsyncIterator.${name} can only be used on a ReadableSteamAsyncIterator`); - } - - /// - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN#Polyfill - const NumberIsNaN = Number.isNaN || function (x) { - // eslint-disable-next-line no-self-compare - return x !== x; - }; - - function IsFiniteNonNegativeNumber(v) { - if (!IsNonNegativeNumber(v)) { - return false; - } - if (v === Infinity) { - return false; - } - return true; - } - function IsNonNegativeNumber(v) { - if (typeof v !== 'number') { - return false; - } - if (NumberIsNaN(v)) { - return false; - } - if (v < 0) { - return false; - } - return true; - } - - function DequeueValue(container) { - const pair = container._queue.shift(); - container._queueTotalSize -= pair.size; - if (container._queueTotalSize < 0) { - container._queueTotalSize = 0; - } - return pair.value; - } - function EnqueueValueWithSize(container, value, size) { - size = Number(size); - if (!IsFiniteNonNegativeNumber(size)) { - throw new RangeError('Size must be a finite, non-NaN, non-negative number.'); - } - container._queue.push({ value, size }); - container._queueTotalSize += size; - } - function PeekQueueValue(container) { - const pair = container._queue.peek(); - return pair.value; - } - function ResetQueue(container) { - container._queue = new SimpleQueue(); - container._queueTotalSize = 0; - } - - function CreateArrayFromList(elements) { - // We use arrays to represent lists, so this is basically a no-op. - // Do a slice though just in case we happen to depend on the unique-ness. - return elements.slice(); - } - function CopyDataBlockBytes(dest, destOffset, src, srcOffset, n) { - new Uint8Array(dest).set(new Uint8Array(src, srcOffset, n), destOffset); - } - // Not implemented correctly - function TransferArrayBuffer(O) { - return O; - } - // Not implemented correctly - function IsDetachedBuffer(O) { - return false; - } - - /** - * A pull-into request in a {@link ReadableByteStreamController}. - * - * @public - */ - class ReadableStreamBYOBRequest { - constructor() { - throw new TypeError('Illegal constructor'); - } - /** - * Returns the view for writing in to, or `null` if the BYOB request has already been responded to. - */ - get view() { - if (!IsReadableStreamBYOBRequest(this)) { - throw byobRequestBrandCheckException('view'); - } - return this._view; - } - respond(bytesWritten) { - if (!IsReadableStreamBYOBRequest(this)) { - throw byobRequestBrandCheckException('respond'); - } - assertRequiredArgument(bytesWritten, 1, 'respond'); - bytesWritten = convertUnsignedLongLongWithEnforceRange(bytesWritten, 'First parameter'); - if (this._associatedReadableByteStreamController === undefined) { - throw new TypeError('This BYOB request has been invalidated'); - } - if (IsDetachedBuffer(this._view.buffer)) ; - ReadableByteStreamControllerRespond(this._associatedReadableByteStreamController, bytesWritten); - } - respondWithNewView(view) { - if (!IsReadableStreamBYOBRequest(this)) { - throw byobRequestBrandCheckException('respondWithNewView'); - } - assertRequiredArgument(view, 1, 'respondWithNewView'); - if (!ArrayBuffer.isView(view)) { - throw new TypeError('You can only respond with array buffer views'); - } - if (view.byteLength === 0) { - throw new TypeError('chunk must have non-zero byteLength'); - } - if (view.buffer.byteLength === 0) { - throw new TypeError(`chunk's buffer must have non-zero byteLength`); - } - if (this._associatedReadableByteStreamController === undefined) { - throw new TypeError('This BYOB request has been invalidated'); - } - ReadableByteStreamControllerRespondWithNewView(this._associatedReadableByteStreamController, view); - } - } - Object.defineProperties(ReadableStreamBYOBRequest.prototype, { - respond: { enumerable: true }, - respondWithNewView: { enumerable: true }, - view: { enumerable: true } - }); - if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(ReadableStreamBYOBRequest.prototype, SymbolPolyfill.toStringTag, { - value: 'ReadableStreamBYOBRequest', - configurable: true - }); - } - /** - * Allows control of a {@link ReadableStream | readable byte stream}'s state and internal queue. - * - * @public - */ - class ReadableByteStreamController { - constructor() { - throw new TypeError('Illegal constructor'); - } - /** - * Returns the current BYOB pull request, or `null` if there isn't one. - */ - get byobRequest() { - if (!IsReadableByteStreamController(this)) { - throw byteStreamControllerBrandCheckException('byobRequest'); - } - if (this._byobRequest === null && this._pendingPullIntos.length > 0) { - const firstDescriptor = this._pendingPullIntos.peek(); - const view = new Uint8Array(firstDescriptor.buffer, firstDescriptor.byteOffset + firstDescriptor.bytesFilled, firstDescriptor.byteLength - firstDescriptor.bytesFilled); - const byobRequest = Object.create(ReadableStreamBYOBRequest.prototype); - SetUpReadableStreamBYOBRequest(byobRequest, this, view); - this._byobRequest = byobRequest; - } - return this._byobRequest; - } - /** - * Returns the desired size to fill the controlled stream's internal queue. It can be negative, if the queue is - * over-full. An underlying byte source ought to use this information to determine when and how to apply backpressure. - */ - get desiredSize() { - if (!IsReadableByteStreamController(this)) { - throw byteStreamControllerBrandCheckException('desiredSize'); - } - return ReadableByteStreamControllerGetDesiredSize(this); - } - /** - * Closes the controlled readable stream. Consumers will still be able to read any previously-enqueued chunks from - * the stream, but once those are read, the stream will become closed. - */ - close() { - if (!IsReadableByteStreamController(this)) { - throw byteStreamControllerBrandCheckException('close'); - } - if (this._closeRequested) { - throw new TypeError('The stream has already been closed; do not close it again!'); - } - const state = this._controlledReadableByteStream._state; - if (state !== 'readable') { - throw new TypeError(`The stream (in ${state} state) is not in the readable state and cannot be closed`); - } - ReadableByteStreamControllerClose(this); - } - enqueue(chunk) { - if (!IsReadableByteStreamController(this)) { - throw byteStreamControllerBrandCheckException('enqueue'); - } - assertRequiredArgument(chunk, 1, 'enqueue'); - if (!ArrayBuffer.isView(chunk)) { - throw new TypeError('chunk must be an array buffer view'); - } - if (chunk.byteLength === 0) { - throw new TypeError('chunk must have non-zero byteLength'); - } - if (chunk.buffer.byteLength === 0) { - throw new TypeError(`chunk's buffer must have non-zero byteLength`); - } - if (this._closeRequested) { - throw new TypeError('stream is closed or draining'); - } - const state = this._controlledReadableByteStream._state; - if (state !== 'readable') { - throw new TypeError(`The stream (in ${state} state) is not in the readable state and cannot be enqueued to`); - } - ReadableByteStreamControllerEnqueue(this, chunk); - } - /** - * Errors the controlled readable stream, making all future interactions with it fail with the given error `e`. - */ - error(e = undefined) { - if (!IsReadableByteStreamController(this)) { - throw byteStreamControllerBrandCheckException('error'); - } - ReadableByteStreamControllerError(this, e); - } - /** @internal */ - [CancelSteps](reason) { - if (this._pendingPullIntos.length > 0) { - const firstDescriptor = this._pendingPullIntos.peek(); - firstDescriptor.bytesFilled = 0; - } - ResetQueue(this); - const result = this._cancelAlgorithm(reason); - ReadableByteStreamControllerClearAlgorithms(this); - return result; - } - /** @internal */ - [PullSteps](readRequest) { - const stream = this._controlledReadableByteStream; - if (this._queueTotalSize > 0) { - const entry = this._queue.shift(); - this._queueTotalSize -= entry.byteLength; - ReadableByteStreamControllerHandleQueueDrain(this); - const view = new Uint8Array(entry.buffer, entry.byteOffset, entry.byteLength); - readRequest._chunkSteps(view); - return; - } - const autoAllocateChunkSize = this._autoAllocateChunkSize; - if (autoAllocateChunkSize !== undefined) { - let buffer; - try { - buffer = new ArrayBuffer(autoAllocateChunkSize); - } - catch (bufferE) { - readRequest._errorSteps(bufferE); - return; - } - const pullIntoDescriptor = { - buffer, - byteOffset: 0, - byteLength: autoAllocateChunkSize, - bytesFilled: 0, - elementSize: 1, - viewConstructor: Uint8Array, - readerType: 'default' - }; - this._pendingPullIntos.push(pullIntoDescriptor); - } - ReadableStreamAddReadRequest(stream, readRequest); - ReadableByteStreamControllerCallPullIfNeeded(this); - } - } - Object.defineProperties(ReadableByteStreamController.prototype, { - close: { enumerable: true }, - enqueue: { enumerable: true }, - error: { enumerable: true }, - byobRequest: { enumerable: true }, - desiredSize: { enumerable: true } - }); - if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(ReadableByteStreamController.prototype, SymbolPolyfill.toStringTag, { - value: 'ReadableByteStreamController', - configurable: true - }); - } - // Abstract operations for the ReadableByteStreamController. - function IsReadableByteStreamController(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_controlledReadableByteStream')) { - return false; - } - return true; - } - function IsReadableStreamBYOBRequest(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_associatedReadableByteStreamController')) { - return false; - } - return true; - } - function ReadableByteStreamControllerCallPullIfNeeded(controller) { - const shouldPull = ReadableByteStreamControllerShouldCallPull(controller); - if (!shouldPull) { - return; - } - if (controller._pulling) { - controller._pullAgain = true; - return; - } - controller._pulling = true; - // TODO: Test controller argument - const pullPromise = controller._pullAlgorithm(); - uponPromise(pullPromise, () => { - controller._pulling = false; - if (controller._pullAgain) { - controller._pullAgain = false; - ReadableByteStreamControllerCallPullIfNeeded(controller); - } - }, e => { - ReadableByteStreamControllerError(controller, e); - }); - } - function ReadableByteStreamControllerClearPendingPullIntos(controller) { - ReadableByteStreamControllerInvalidateBYOBRequest(controller); - controller._pendingPullIntos = new SimpleQueue(); - } - function ReadableByteStreamControllerCommitPullIntoDescriptor(stream, pullIntoDescriptor) { - let done = false; - if (stream._state === 'closed') { - done = true; - } - const filledView = ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor); - if (pullIntoDescriptor.readerType === 'default') { - ReadableStreamFulfillReadRequest(stream, filledView, done); - } - else { - ReadableStreamFulfillReadIntoRequest(stream, filledView, done); - } - } - function ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor) { - const bytesFilled = pullIntoDescriptor.bytesFilled; - const elementSize = pullIntoDescriptor.elementSize; - return new pullIntoDescriptor.viewConstructor(pullIntoDescriptor.buffer, pullIntoDescriptor.byteOffset, bytesFilled / elementSize); - } - function ReadableByteStreamControllerEnqueueChunkToQueue(controller, buffer, byteOffset, byteLength) { - controller._queue.push({ buffer, byteOffset, byteLength }); - controller._queueTotalSize += byteLength; - } - function ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor) { - const elementSize = pullIntoDescriptor.elementSize; - const currentAlignedBytes = pullIntoDescriptor.bytesFilled - pullIntoDescriptor.bytesFilled % elementSize; - const maxBytesToCopy = Math.min(controller._queueTotalSize, pullIntoDescriptor.byteLength - pullIntoDescriptor.bytesFilled); - const maxBytesFilled = pullIntoDescriptor.bytesFilled + maxBytesToCopy; - const maxAlignedBytes = maxBytesFilled - maxBytesFilled % elementSize; - let totalBytesToCopyRemaining = maxBytesToCopy; - let ready = false; - if (maxAlignedBytes > currentAlignedBytes) { - totalBytesToCopyRemaining = maxAlignedBytes - pullIntoDescriptor.bytesFilled; - ready = true; - } - const queue = controller._queue; - while (totalBytesToCopyRemaining > 0) { - const headOfQueue = queue.peek(); - const bytesToCopy = Math.min(totalBytesToCopyRemaining, headOfQueue.byteLength); - const destStart = pullIntoDescriptor.byteOffset + pullIntoDescriptor.bytesFilled; - CopyDataBlockBytes(pullIntoDescriptor.buffer, destStart, headOfQueue.buffer, headOfQueue.byteOffset, bytesToCopy); - if (headOfQueue.byteLength === bytesToCopy) { - queue.shift(); - } - else { - headOfQueue.byteOffset += bytesToCopy; - headOfQueue.byteLength -= bytesToCopy; - } - controller._queueTotalSize -= bytesToCopy; - ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, bytesToCopy, pullIntoDescriptor); - totalBytesToCopyRemaining -= bytesToCopy; - } - return ready; - } - function ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, size, pullIntoDescriptor) { - ReadableByteStreamControllerInvalidateBYOBRequest(controller); - pullIntoDescriptor.bytesFilled += size; - } - function ReadableByteStreamControllerHandleQueueDrain(controller) { - if (controller._queueTotalSize === 0 && controller._closeRequested) { - ReadableByteStreamControllerClearAlgorithms(controller); - ReadableStreamClose(controller._controlledReadableByteStream); - } - else { - ReadableByteStreamControllerCallPullIfNeeded(controller); - } - } - function ReadableByteStreamControllerInvalidateBYOBRequest(controller) { - if (controller._byobRequest === null) { - return; - } - controller._byobRequest._associatedReadableByteStreamController = undefined; - controller._byobRequest._view = null; - controller._byobRequest = null; - } - function ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller) { - while (controller._pendingPullIntos.length > 0) { - if (controller._queueTotalSize === 0) { - return; - } - const pullIntoDescriptor = controller._pendingPullIntos.peek(); - if (ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor)) { - ReadableByteStreamControllerShiftPendingPullInto(controller); - ReadableByteStreamControllerCommitPullIntoDescriptor(controller._controlledReadableByteStream, pullIntoDescriptor); - } - } - } - function ReadableByteStreamControllerPullInto(controller, view, readIntoRequest) { - const stream = controller._controlledReadableByteStream; - let elementSize = 1; - if (view.constructor !== DataView) { - elementSize = view.constructor.BYTES_PER_ELEMENT; - } - const ctor = view.constructor; - const buffer = TransferArrayBuffer(view.buffer); - const pullIntoDescriptor = { - buffer, - byteOffset: view.byteOffset, - byteLength: view.byteLength, - bytesFilled: 0, - elementSize, - viewConstructor: ctor, - readerType: 'byob' - }; - if (controller._pendingPullIntos.length > 0) { - controller._pendingPullIntos.push(pullIntoDescriptor); - // No ReadableByteStreamControllerCallPullIfNeeded() call since: - // - No change happens on desiredSize - // - The source has already been notified of that there's at least 1 pending read(view) - ReadableStreamAddReadIntoRequest(stream, readIntoRequest); - return; - } - if (stream._state === 'closed') { - const emptyView = new ctor(pullIntoDescriptor.buffer, pullIntoDescriptor.byteOffset, 0); - readIntoRequest._closeSteps(emptyView); - return; - } - if (controller._queueTotalSize > 0) { - if (ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor)) { - const filledView = ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor); - ReadableByteStreamControllerHandleQueueDrain(controller); - readIntoRequest._chunkSteps(filledView); - return; - } - if (controller._closeRequested) { - const e = new TypeError('Insufficient bytes to fill elements in the given buffer'); - ReadableByteStreamControllerError(controller, e); - readIntoRequest._errorSteps(e); - return; - } - } - controller._pendingPullIntos.push(pullIntoDescriptor); - ReadableStreamAddReadIntoRequest(stream, readIntoRequest); - ReadableByteStreamControllerCallPullIfNeeded(controller); - } - function ReadableByteStreamControllerRespondInClosedState(controller, firstDescriptor) { - firstDescriptor.buffer = TransferArrayBuffer(firstDescriptor.buffer); - const stream = controller._controlledReadableByteStream; - if (ReadableStreamHasBYOBReader(stream)) { - while (ReadableStreamGetNumReadIntoRequests(stream) > 0) { - const pullIntoDescriptor = ReadableByteStreamControllerShiftPendingPullInto(controller); - ReadableByteStreamControllerCommitPullIntoDescriptor(stream, pullIntoDescriptor); - } - } - } - function ReadableByteStreamControllerRespondInReadableState(controller, bytesWritten, pullIntoDescriptor) { - if (pullIntoDescriptor.bytesFilled + bytesWritten > pullIntoDescriptor.byteLength) { - throw new RangeError('bytesWritten out of range'); - } - ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, bytesWritten, pullIntoDescriptor); - if (pullIntoDescriptor.bytesFilled < pullIntoDescriptor.elementSize) { - // TODO: Figure out whether we should detach the buffer or not here. - return; - } - ReadableByteStreamControllerShiftPendingPullInto(controller); - const remainderSize = pullIntoDescriptor.bytesFilled % pullIntoDescriptor.elementSize; - if (remainderSize > 0) { - const end = pullIntoDescriptor.byteOffset + pullIntoDescriptor.bytesFilled; - const remainder = pullIntoDescriptor.buffer.slice(end - remainderSize, end); - ReadableByteStreamControllerEnqueueChunkToQueue(controller, remainder, 0, remainder.byteLength); - } - pullIntoDescriptor.buffer = TransferArrayBuffer(pullIntoDescriptor.buffer); - pullIntoDescriptor.bytesFilled -= remainderSize; - ReadableByteStreamControllerCommitPullIntoDescriptor(controller._controlledReadableByteStream, pullIntoDescriptor); - ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller); - } - function ReadableByteStreamControllerRespondInternal(controller, bytesWritten) { - const firstDescriptor = controller._pendingPullIntos.peek(); - const state = controller._controlledReadableByteStream._state; - if (state === 'closed') { - if (bytesWritten !== 0) { - throw new TypeError('bytesWritten must be 0 when calling respond() on a closed stream'); - } - ReadableByteStreamControllerRespondInClosedState(controller, firstDescriptor); - } - else { - ReadableByteStreamControllerRespondInReadableState(controller, bytesWritten, firstDescriptor); - } - ReadableByteStreamControllerCallPullIfNeeded(controller); - } - function ReadableByteStreamControllerShiftPendingPullInto(controller) { - const descriptor = controller._pendingPullIntos.shift(); - ReadableByteStreamControllerInvalidateBYOBRequest(controller); - return descriptor; - } - function ReadableByteStreamControllerShouldCallPull(controller) { - const stream = controller._controlledReadableByteStream; - if (stream._state !== 'readable') { - return false; - } - if (controller._closeRequested) { - return false; - } - if (!controller._started) { - return false; - } - if (ReadableStreamHasDefaultReader(stream) && ReadableStreamGetNumReadRequests(stream) > 0) { - return true; - } - if (ReadableStreamHasBYOBReader(stream) && ReadableStreamGetNumReadIntoRequests(stream) > 0) { - return true; - } - const desiredSize = ReadableByteStreamControllerGetDesiredSize(controller); - if (desiredSize > 0) { - return true; - } - return false; - } - function ReadableByteStreamControllerClearAlgorithms(controller) { - controller._pullAlgorithm = undefined; - controller._cancelAlgorithm = undefined; - } - // A client of ReadableByteStreamController may use these functions directly to bypass state check. - function ReadableByteStreamControllerClose(controller) { - const stream = controller._controlledReadableByteStream; - if (controller._closeRequested || stream._state !== 'readable') { - return; - } - if (controller._queueTotalSize > 0) { - controller._closeRequested = true; - return; - } - if (controller._pendingPullIntos.length > 0) { - const firstPendingPullInto = controller._pendingPullIntos.peek(); - if (firstPendingPullInto.bytesFilled > 0) { - const e = new TypeError('Insufficient bytes to fill elements in the given buffer'); - ReadableByteStreamControllerError(controller, e); - throw e; - } - } - ReadableByteStreamControllerClearAlgorithms(controller); - ReadableStreamClose(stream); - } - function ReadableByteStreamControllerEnqueue(controller, chunk) { - const stream = controller._controlledReadableByteStream; - if (controller._closeRequested || stream._state !== 'readable') { - return; - } - const buffer = chunk.buffer; - const byteOffset = chunk.byteOffset; - const byteLength = chunk.byteLength; - const transferredBuffer = TransferArrayBuffer(buffer); - if (ReadableStreamHasDefaultReader(stream)) { - if (ReadableStreamGetNumReadRequests(stream) === 0) { - ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength); - } - else { - const transferredView = new Uint8Array(transferredBuffer, byteOffset, byteLength); - ReadableStreamFulfillReadRequest(stream, transferredView, false); - } - } - else if (ReadableStreamHasBYOBReader(stream)) { - // TODO: Ideally in this branch detaching should happen only if the buffer is not consumed fully. - ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength); - ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller); - } - else { - ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength); - } - ReadableByteStreamControllerCallPullIfNeeded(controller); - } - function ReadableByteStreamControllerError(controller, e) { - const stream = controller._controlledReadableByteStream; - if (stream._state !== 'readable') { - return; - } - ReadableByteStreamControllerClearPendingPullIntos(controller); - ResetQueue(controller); - ReadableByteStreamControllerClearAlgorithms(controller); - ReadableStreamError(stream, e); - } - function ReadableByteStreamControllerGetDesiredSize(controller) { - const state = controller._controlledReadableByteStream._state; - if (state === 'errored') { - return null; - } - if (state === 'closed') { - return 0; - } - return controller._strategyHWM - controller._queueTotalSize; - } - function ReadableByteStreamControllerRespond(controller, bytesWritten) { - bytesWritten = Number(bytesWritten); - if (!IsFiniteNonNegativeNumber(bytesWritten)) { - throw new RangeError('bytesWritten must be a finite'); - } - ReadableByteStreamControllerRespondInternal(controller, bytesWritten); - } - function ReadableByteStreamControllerRespondWithNewView(controller, view) { - const firstDescriptor = controller._pendingPullIntos.peek(); - if (firstDescriptor.byteOffset + firstDescriptor.bytesFilled !== view.byteOffset) { - throw new RangeError('The region specified by view does not match byobRequest'); - } - if (firstDescriptor.byteLength !== view.byteLength) { - throw new RangeError('The buffer of view has different capacity than byobRequest'); - } - firstDescriptor.buffer = view.buffer; - ReadableByteStreamControllerRespondInternal(controller, view.byteLength); - } - function SetUpReadableByteStreamController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, autoAllocateChunkSize) { - controller._controlledReadableByteStream = stream; - controller._pullAgain = false; - controller._pulling = false; - controller._byobRequest = null; - // Need to set the slots so that the assert doesn't fire. In the spec the slots already exist implicitly. - controller._queue = controller._queueTotalSize = undefined; - ResetQueue(controller); - controller._closeRequested = false; - controller._started = false; - controller._strategyHWM = highWaterMark; - controller._pullAlgorithm = pullAlgorithm; - controller._cancelAlgorithm = cancelAlgorithm; - controller._autoAllocateChunkSize = autoAllocateChunkSize; - controller._pendingPullIntos = new SimpleQueue(); - stream._readableStreamController = controller; - const startResult = startAlgorithm(); - uponPromise(promiseResolvedWith(startResult), () => { - controller._started = true; - ReadableByteStreamControllerCallPullIfNeeded(controller); - }, r => { - ReadableByteStreamControllerError(controller, r); - }); - } - function SetUpReadableByteStreamControllerFromUnderlyingSource(stream, underlyingByteSource, highWaterMark) { - const controller = Object.create(ReadableByteStreamController.prototype); - let startAlgorithm = () => undefined; - let pullAlgorithm = () => promiseResolvedWith(undefined); - let cancelAlgorithm = () => promiseResolvedWith(undefined); - if (underlyingByteSource.start !== undefined) { - startAlgorithm = () => underlyingByteSource.start(controller); - } - if (underlyingByteSource.pull !== undefined) { - pullAlgorithm = () => underlyingByteSource.pull(controller); - } - if (underlyingByteSource.cancel !== undefined) { - cancelAlgorithm = reason => underlyingByteSource.cancel(reason); - } - const autoAllocateChunkSize = underlyingByteSource.autoAllocateChunkSize; - if (autoAllocateChunkSize === 0) { - throw new TypeError('autoAllocateChunkSize must be greater than 0'); - } - SetUpReadableByteStreamController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, autoAllocateChunkSize); - } - function SetUpReadableStreamBYOBRequest(request, controller, view) { - request._associatedReadableByteStreamController = controller; - request._view = view; - } - // Helper functions for the ReadableStreamBYOBRequest. - function byobRequestBrandCheckException(name) { - return new TypeError(`ReadableStreamBYOBRequest.prototype.${name} can only be used on a ReadableStreamBYOBRequest`); - } - // Helper functions for the ReadableByteStreamController. - function byteStreamControllerBrandCheckException(name) { - return new TypeError(`ReadableByteStreamController.prototype.${name} can only be used on a ReadableByteStreamController`); - } - - // Abstract operations for the ReadableStream. - function AcquireReadableStreamBYOBReader(stream) { - return new ReadableStreamBYOBReader(stream); - } - // ReadableStream API exposed for controllers. - function ReadableStreamAddReadIntoRequest(stream, readIntoRequest) { - stream._reader._readIntoRequests.push(readIntoRequest); - } - function ReadableStreamFulfillReadIntoRequest(stream, chunk, done) { - const reader = stream._reader; - const readIntoRequest = reader._readIntoRequests.shift(); - if (done) { - readIntoRequest._closeSteps(chunk); - } - else { - readIntoRequest._chunkSteps(chunk); - } - } - function ReadableStreamGetNumReadIntoRequests(stream) { - return stream._reader._readIntoRequests.length; - } - function ReadableStreamHasBYOBReader(stream) { - const reader = stream._reader; - if (reader === undefined) { - return false; - } - if (!IsReadableStreamBYOBReader(reader)) { - return false; - } - return true; - } - /** - * A BYOB reader vended by a {@link ReadableStream}. - * - * @public - */ - class ReadableStreamBYOBReader { - constructor(stream) { - assertRequiredArgument(stream, 1, 'ReadableStreamBYOBReader'); - assertReadableStream(stream, 'First parameter'); - if (IsReadableStreamLocked(stream)) { - throw new TypeError('This stream has already been locked for exclusive reading by another reader'); - } - if (!IsReadableByteStreamController(stream._readableStreamController)) { - throw new TypeError('Cannot construct a ReadableStreamBYOBReader for a stream not constructed with a byte ' + - 'source'); - } - ReadableStreamReaderGenericInitialize(this, stream); - this._readIntoRequests = new SimpleQueue(); - } - /** - * Returns a promise that will be fulfilled when the stream becomes closed, or rejected if the stream ever errors or - * the reader's lock is released before the stream finishes closing. - */ - get closed() { - if (!IsReadableStreamBYOBReader(this)) { - return promiseRejectedWith(byobReaderBrandCheckException('closed')); - } - return this._closedPromise; - } - /** - * If the reader is active, behaves the same as {@link ReadableStream.cancel | stream.cancel(reason)}. - */ - cancel(reason = undefined) { - if (!IsReadableStreamBYOBReader(this)) { - return promiseRejectedWith(byobReaderBrandCheckException('cancel')); - } - if (this._ownerReadableStream === undefined) { - return promiseRejectedWith(readerLockException('cancel')); - } - return ReadableStreamReaderGenericCancel(this, reason); - } - /** - * Attempts to reads bytes into view, and returns a promise resolved with the result. - * - * If reading a chunk causes the queue to become empty, more data will be pulled from the underlying source. - */ - read(view) { - if (!IsReadableStreamBYOBReader(this)) { - return promiseRejectedWith(byobReaderBrandCheckException('read')); - } - if (!ArrayBuffer.isView(view)) { - return promiseRejectedWith(new TypeError('view must be an array buffer view')); - } - if (view.byteLength === 0) { - return promiseRejectedWith(new TypeError('view must have non-zero byteLength')); - } - if (view.buffer.byteLength === 0) { - return promiseRejectedWith(new TypeError(`view's buffer must have non-zero byteLength`)); - } - if (this._ownerReadableStream === undefined) { - return promiseRejectedWith(readerLockException('read from')); - } - let resolvePromise; - let rejectPromise; - const promise = newPromise((resolve, reject) => { - resolvePromise = resolve; - rejectPromise = reject; - }); - const readIntoRequest = { - _chunkSteps: chunk => resolvePromise({ value: chunk, done: false }), - _closeSteps: chunk => resolvePromise({ value: chunk, done: true }), - _errorSteps: e => rejectPromise(e) - }; - ReadableStreamBYOBReaderRead(this, view, readIntoRequest); - return promise; - } - /** - * Releases the reader's lock on the corresponding stream. After the lock is released, the reader is no longer active. - * If the associated stream is errored when the lock is released, the reader will appear errored in the same way - * from now on; otherwise, the reader will appear closed. - * - * A reader's lock cannot be released while it still has a pending read request, i.e., if a promise returned by - * the reader's {@link ReadableStreamBYOBReader.read | read()} method has not yet been settled. Attempting to - * do so will throw a `TypeError` and leave the reader locked to the stream. - */ - releaseLock() { - if (!IsReadableStreamBYOBReader(this)) { - throw byobReaderBrandCheckException('releaseLock'); - } - if (this._ownerReadableStream === undefined) { - return; - } - if (this._readIntoRequests.length > 0) { - throw new TypeError('Tried to release a reader lock when that reader has pending read() calls un-settled'); - } - ReadableStreamReaderGenericRelease(this); - } - } - Object.defineProperties(ReadableStreamBYOBReader.prototype, { - cancel: { enumerable: true }, - read: { enumerable: true }, - releaseLock: { enumerable: true }, - closed: { enumerable: true } - }); - if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(ReadableStreamBYOBReader.prototype, SymbolPolyfill.toStringTag, { - value: 'ReadableStreamBYOBReader', - configurable: true - }); - } - // Abstract operations for the readers. - function IsReadableStreamBYOBReader(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_readIntoRequests')) { - return false; - } - return true; - } - function ReadableStreamBYOBReaderRead(reader, view, readIntoRequest) { - const stream = reader._ownerReadableStream; - stream._disturbed = true; - if (stream._state === 'errored') { - readIntoRequest._errorSteps(stream._storedError); - } - else { - ReadableByteStreamControllerPullInto(stream._readableStreamController, view, readIntoRequest); - } - } - // Helper functions for the ReadableStreamBYOBReader. - function byobReaderBrandCheckException(name) { - return new TypeError(`ReadableStreamBYOBReader.prototype.${name} can only be used on a ReadableStreamBYOBReader`); - } - - function ExtractHighWaterMark(strategy, defaultHWM) { - const { highWaterMark } = strategy; - if (highWaterMark === undefined) { - return defaultHWM; - } - if (NumberIsNaN(highWaterMark) || highWaterMark < 0) { - throw new RangeError('Invalid highWaterMark'); - } - return highWaterMark; - } - function ExtractSizeAlgorithm(strategy) { - const { size } = strategy; - if (!size) { - return () => 1; - } - return size; - } - - function convertQueuingStrategy(init, context) { - assertDictionary(init, context); - const highWaterMark = init === null || init === void 0 ? void 0 : init.highWaterMark; - const size = init === null || init === void 0 ? void 0 : init.size; - return { - highWaterMark: highWaterMark === undefined ? undefined : convertUnrestrictedDouble(highWaterMark), - size: size === undefined ? undefined : convertQueuingStrategySize(size, `${context} has member 'size' that`) - }; - } - function convertQueuingStrategySize(fn, context) { - assertFunction(fn, context); - return chunk => convertUnrestrictedDouble(fn(chunk)); - } - - function convertUnderlyingSink(original, context) { - assertDictionary(original, context); - const abort = original === null || original === void 0 ? void 0 : original.abort; - const close = original === null || original === void 0 ? void 0 : original.close; - const start = original === null || original === void 0 ? void 0 : original.start; - const type = original === null || original === void 0 ? void 0 : original.type; - const write = original === null || original === void 0 ? void 0 : original.write; - return { - abort: abort === undefined ? - undefined : - convertUnderlyingSinkAbortCallback(abort, original, `${context} has member 'abort' that`), - close: close === undefined ? - undefined : - convertUnderlyingSinkCloseCallback(close, original, `${context} has member 'close' that`), - start: start === undefined ? - undefined : - convertUnderlyingSinkStartCallback(start, original, `${context} has member 'start' that`), - write: write === undefined ? - undefined : - convertUnderlyingSinkWriteCallback(write, original, `${context} has member 'write' that`), - type - }; - } - function convertUnderlyingSinkAbortCallback(fn, original, context) { - assertFunction(fn, context); - return (reason) => promiseCall(fn, original, [reason]); - } - function convertUnderlyingSinkCloseCallback(fn, original, context) { - assertFunction(fn, context); - return () => promiseCall(fn, original, []); - } - function convertUnderlyingSinkStartCallback(fn, original, context) { - assertFunction(fn, context); - return (controller) => reflectCall(fn, original, [controller]); - } - function convertUnderlyingSinkWriteCallback(fn, original, context) { - assertFunction(fn, context); - return (chunk, controller) => promiseCall(fn, original, [chunk, controller]); - } - - function assertWritableStream(x, context) { - if (!IsWritableStream(x)) { - throw new TypeError(`${context} is not a WritableStream.`); - } - } - - /** - * A writable stream represents a destination for data, into which you can write. - * - * @public - */ - class WritableStream$1 { - constructor(rawUnderlyingSink = {}, rawStrategy = {}) { - if (rawUnderlyingSink === undefined) { - rawUnderlyingSink = null; - } - else { - assertObject(rawUnderlyingSink, 'First parameter'); - } - const strategy = convertQueuingStrategy(rawStrategy, 'Second parameter'); - const underlyingSink = convertUnderlyingSink(rawUnderlyingSink, 'First parameter'); - InitializeWritableStream(this); - const type = underlyingSink.type; - if (type !== undefined) { - throw new RangeError('Invalid type is specified'); - } - const sizeAlgorithm = ExtractSizeAlgorithm(strategy); - const highWaterMark = ExtractHighWaterMark(strategy, 1); - SetUpWritableStreamDefaultControllerFromUnderlyingSink(this, underlyingSink, highWaterMark, sizeAlgorithm); - } - /** - * Returns whether or not the writable stream is locked to a writer. - */ - get locked() { - if (!IsWritableStream(this)) { - throw streamBrandCheckException$2('locked'); - } - return IsWritableStreamLocked(this); - } - /** - * Aborts the stream, signaling that the producer can no longer successfully write to the stream and it is to be - * immediately moved to an errored state, with any queued-up writes discarded. This will also execute any abort - * mechanism of the underlying sink. - * - * The returned promise will fulfill if the stream shuts down successfully, or reject if the underlying sink signaled - * that there was an error doing so. Additionally, it will reject with a `TypeError` (without attempting to cancel - * the stream) if the stream is currently locked. - */ - abort(reason = undefined) { - if (!IsWritableStream(this)) { - return promiseRejectedWith(streamBrandCheckException$2('abort')); - } - if (IsWritableStreamLocked(this)) { - return promiseRejectedWith(new TypeError('Cannot abort a stream that already has a writer')); - } - return WritableStreamAbort(this, reason); - } - /** - * Closes the stream. The underlying sink will finish processing any previously-written chunks, before invoking its - * close behavior. During this time any further attempts to write will fail (without erroring the stream). - * - * The method returns a promise that will fulfill if all remaining chunks are successfully written and the stream - * successfully closes, or rejects if an error is encountered during this process. Additionally, it will reject with - * a `TypeError` (without attempting to cancel the stream) if the stream is currently locked. - */ - close() { - if (!IsWritableStream(this)) { - return promiseRejectedWith(streamBrandCheckException$2('close')); - } - if (IsWritableStreamLocked(this)) { - return promiseRejectedWith(new TypeError('Cannot close a stream that already has a writer')); - } - if (WritableStreamCloseQueuedOrInFlight(this)) { - return promiseRejectedWith(new TypeError('Cannot close an already-closing stream')); - } - return WritableStreamClose(this); - } - /** - * Creates a {@link WritableStreamDefaultWriter | writer} and locks the stream to the new writer. While the stream - * is locked, no other writer can be acquired until this one is released. - * - * This functionality is especially useful for creating abstractions that desire the ability to write to a stream - * without interruption or interleaving. By getting a writer for the stream, you can ensure nobody else can write at - * the same time, which would cause the resulting written data to be unpredictable and probably useless. - */ - getWriter() { - if (!IsWritableStream(this)) { - throw streamBrandCheckException$2('getWriter'); - } - return AcquireWritableStreamDefaultWriter(this); - } - } - Object.defineProperties(WritableStream$1.prototype, { - abort: { enumerable: true }, - close: { enumerable: true }, - getWriter: { enumerable: true }, - locked: { enumerable: true } - }); - if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(WritableStream$1.prototype, SymbolPolyfill.toStringTag, { - value: 'WritableStream', - configurable: true - }); - } - // Abstract operations for the WritableStream. - function AcquireWritableStreamDefaultWriter(stream) { - return new WritableStreamDefaultWriter(stream); - } - // Throws if and only if startAlgorithm throws. - function CreateWritableStream(startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark = 1, sizeAlgorithm = () => 1) { - const stream = Object.create(WritableStream$1.prototype); - InitializeWritableStream(stream); - const controller = Object.create(WritableStreamDefaultController.prototype); - SetUpWritableStreamDefaultController(stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark, sizeAlgorithm); - return stream; - } - function InitializeWritableStream(stream) { - stream._state = 'writable'; - // The error that will be reported by new method calls once the state becomes errored. Only set when [[state]] is - // 'erroring' or 'errored'. May be set to an undefined value. - stream._storedError = undefined; - stream._writer = undefined; - // Initialize to undefined first because the constructor of the controller checks this - // variable to validate the caller. - stream._writableStreamController = undefined; - // This queue is placed here instead of the writer class in order to allow for passing a writer to the next data - // producer without waiting for the queued writes to finish. - stream._writeRequests = new SimpleQueue(); - // Write requests are removed from _writeRequests when write() is called on the underlying sink. This prevents - // them from being erroneously rejected on error. If a write() call is in-flight, the request is stored here. - stream._inFlightWriteRequest = undefined; - // The promise that was returned from writer.close(). Stored here because it may be fulfilled after the writer - // has been detached. - stream._closeRequest = undefined; - // Close request is removed from _closeRequest when close() is called on the underlying sink. This prevents it - // from being erroneously rejected on error. If a close() call is in-flight, the request is stored here. - stream._inFlightCloseRequest = undefined; - // The promise that was returned from writer.abort(). This may also be fulfilled after the writer has detached. - stream._pendingAbortRequest = undefined; - // The backpressure signal set by the controller. - stream._backpressure = false; - } - function IsWritableStream(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_writableStreamController')) { - return false; - } - return true; - } - function IsWritableStreamLocked(stream) { - if (stream._writer === undefined) { - return false; - } - return true; - } - function WritableStreamAbort(stream, reason) { - const state = stream._state; - if (state === 'closed' || state === 'errored') { - return promiseResolvedWith(undefined); - } - if (stream._pendingAbortRequest !== undefined) { - return stream._pendingAbortRequest._promise; - } - let wasAlreadyErroring = false; - if (state === 'erroring') { - wasAlreadyErroring = true; - // reason will not be used, so don't keep a reference to it. - reason = undefined; - } - const promise = newPromise((resolve, reject) => { - stream._pendingAbortRequest = { - _promise: undefined, - _resolve: resolve, - _reject: reject, - _reason: reason, - _wasAlreadyErroring: wasAlreadyErroring - }; - }); - stream._pendingAbortRequest._promise = promise; - if (!wasAlreadyErroring) { - WritableStreamStartErroring(stream, reason); - } - return promise; - } - function WritableStreamClose(stream) { - const state = stream._state; - if (state === 'closed' || state === 'errored') { - return promiseRejectedWith(new TypeError(`The stream (in ${state} state) is not in the writable state and cannot be closed`)); - } - const promise = newPromise((resolve, reject) => { - const closeRequest = { - _resolve: resolve, - _reject: reject - }; - stream._closeRequest = closeRequest; - }); - const writer = stream._writer; - if (writer !== undefined && stream._backpressure && state === 'writable') { - defaultWriterReadyPromiseResolve(writer); - } - WritableStreamDefaultControllerClose(stream._writableStreamController); - return promise; - } - // WritableStream API exposed for controllers. - function WritableStreamAddWriteRequest(stream) { - const promise = newPromise((resolve, reject) => { - const writeRequest = { - _resolve: resolve, - _reject: reject - }; - stream._writeRequests.push(writeRequest); - }); - return promise; - } - function WritableStreamDealWithRejection(stream, error) { - const state = stream._state; - if (state === 'writable') { - WritableStreamStartErroring(stream, error); - return; - } - WritableStreamFinishErroring(stream); - } - function WritableStreamStartErroring(stream, reason) { - const controller = stream._writableStreamController; - stream._state = 'erroring'; - stream._storedError = reason; - const writer = stream._writer; - if (writer !== undefined) { - WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, reason); - } - if (!WritableStreamHasOperationMarkedInFlight(stream) && controller._started) { - WritableStreamFinishErroring(stream); - } - } - function WritableStreamFinishErroring(stream) { - stream._state = 'errored'; - stream._writableStreamController[ErrorSteps](); - const storedError = stream._storedError; - stream._writeRequests.forEach(writeRequest => { - writeRequest._reject(storedError); - }); - stream._writeRequests = new SimpleQueue(); - if (stream._pendingAbortRequest === undefined) { - WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); - return; - } - const abortRequest = stream._pendingAbortRequest; - stream._pendingAbortRequest = undefined; - if (abortRequest._wasAlreadyErroring) { - abortRequest._reject(storedError); - WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); - return; - } - const promise = stream._writableStreamController[AbortSteps](abortRequest._reason); - uponPromise(promise, () => { - abortRequest._resolve(); - WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); - }, (reason) => { - abortRequest._reject(reason); - WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); - }); - } - function WritableStreamFinishInFlightWrite(stream) { - stream._inFlightWriteRequest._resolve(undefined); - stream._inFlightWriteRequest = undefined; - } - function WritableStreamFinishInFlightWriteWithError(stream, error) { - stream._inFlightWriteRequest._reject(error); - stream._inFlightWriteRequest = undefined; - WritableStreamDealWithRejection(stream, error); - } - function WritableStreamFinishInFlightClose(stream) { - stream._inFlightCloseRequest._resolve(undefined); - stream._inFlightCloseRequest = undefined; - const state = stream._state; - if (state === 'erroring') { - // The error was too late to do anything, so it is ignored. - stream._storedError = undefined; - if (stream._pendingAbortRequest !== undefined) { - stream._pendingAbortRequest._resolve(); - stream._pendingAbortRequest = undefined; - } - } - stream._state = 'closed'; - const writer = stream._writer; - if (writer !== undefined) { - defaultWriterClosedPromiseResolve(writer); - } - } - function WritableStreamFinishInFlightCloseWithError(stream, error) { - stream._inFlightCloseRequest._reject(error); - stream._inFlightCloseRequest = undefined; - // Never execute sink abort() after sink close(). - if (stream._pendingAbortRequest !== undefined) { - stream._pendingAbortRequest._reject(error); - stream._pendingAbortRequest = undefined; - } - WritableStreamDealWithRejection(stream, error); - } - // TODO(ricea): Fix alphabetical order. - function WritableStreamCloseQueuedOrInFlight(stream) { - if (stream._closeRequest === undefined && stream._inFlightCloseRequest === undefined) { - return false; - } - return true; - } - function WritableStreamHasOperationMarkedInFlight(stream) { - if (stream._inFlightWriteRequest === undefined && stream._inFlightCloseRequest === undefined) { - return false; - } - return true; - } - function WritableStreamMarkCloseRequestInFlight(stream) { - stream._inFlightCloseRequest = stream._closeRequest; - stream._closeRequest = undefined; - } - function WritableStreamMarkFirstWriteRequestInFlight(stream) { - stream._inFlightWriteRequest = stream._writeRequests.shift(); - } - function WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream) { - if (stream._closeRequest !== undefined) { - stream._closeRequest._reject(stream._storedError); - stream._closeRequest = undefined; - } - const writer = stream._writer; - if (writer !== undefined) { - defaultWriterClosedPromiseReject(writer, stream._storedError); - } - } - function WritableStreamUpdateBackpressure(stream, backpressure) { - const writer = stream._writer; - if (writer !== undefined && backpressure !== stream._backpressure) { - if (backpressure) { - defaultWriterReadyPromiseReset(writer); - } - else { - defaultWriterReadyPromiseResolve(writer); - } - } - stream._backpressure = backpressure; - } - /** - * A default writer vended by a {@link WritableStream}. - * - * @public - */ - class WritableStreamDefaultWriter { - constructor(stream) { - assertRequiredArgument(stream, 1, 'WritableStreamDefaultWriter'); - assertWritableStream(stream, 'First parameter'); - if (IsWritableStreamLocked(stream)) { - throw new TypeError('This stream has already been locked for exclusive writing by another writer'); - } - this._ownerWritableStream = stream; - stream._writer = this; - const state = stream._state; - if (state === 'writable') { - if (!WritableStreamCloseQueuedOrInFlight(stream) && stream._backpressure) { - defaultWriterReadyPromiseInitialize(this); - } - else { - defaultWriterReadyPromiseInitializeAsResolved(this); - } - defaultWriterClosedPromiseInitialize(this); - } - else if (state === 'erroring') { - defaultWriterReadyPromiseInitializeAsRejected(this, stream._storedError); - defaultWriterClosedPromiseInitialize(this); - } - else if (state === 'closed') { - defaultWriterReadyPromiseInitializeAsResolved(this); - defaultWriterClosedPromiseInitializeAsResolved(this); - } - else { - const storedError = stream._storedError; - defaultWriterReadyPromiseInitializeAsRejected(this, storedError); - defaultWriterClosedPromiseInitializeAsRejected(this, storedError); - } - } - /** - * Returns a promise that will be fulfilled when the stream becomes closed, or rejected if the stream ever errors or - * the writer’s lock is released before the stream finishes closing. - */ - get closed() { - if (!IsWritableStreamDefaultWriter(this)) { - return promiseRejectedWith(defaultWriterBrandCheckException('closed')); - } - return this._closedPromise; - } - /** - * Returns the desired size to fill the stream’s internal queue. It can be negative, if the queue is over-full. - * A producer can use this information to determine the right amount of data to write. - * - * It will be `null` if the stream cannot be successfully written to (due to either being errored, or having an abort - * queued up). It will return zero if the stream is closed. And the getter will throw an exception if invoked when - * the writer’s lock is released. - */ - get desiredSize() { - if (!IsWritableStreamDefaultWriter(this)) { - throw defaultWriterBrandCheckException('desiredSize'); - } - if (this._ownerWritableStream === undefined) { - throw defaultWriterLockException('desiredSize'); - } - return WritableStreamDefaultWriterGetDesiredSize(this); - } - /** - * Returns a promise that will be fulfilled when the desired size to fill the stream’s internal queue transitions - * from non-positive to positive, signaling that it is no longer applying backpressure. Once the desired size dips - * back to zero or below, the getter will return a new promise that stays pending until the next transition. - * - * If the stream becomes errored or aborted, or the writer’s lock is released, the returned promise will become - * rejected. - */ - get ready() { - if (!IsWritableStreamDefaultWriter(this)) { - return promiseRejectedWith(defaultWriterBrandCheckException('ready')); - } - return this._readyPromise; - } - /** - * If the reader is active, behaves the same as {@link WritableStream.abort | stream.abort(reason)}. - */ - abort(reason = undefined) { - if (!IsWritableStreamDefaultWriter(this)) { - return promiseRejectedWith(defaultWriterBrandCheckException('abort')); - } - if (this._ownerWritableStream === undefined) { - return promiseRejectedWith(defaultWriterLockException('abort')); - } - return WritableStreamDefaultWriterAbort(this, reason); - } - /** - * If the reader is active, behaves the same as {@link WritableStream.close | stream.close()}. - */ - close() { - if (!IsWritableStreamDefaultWriter(this)) { - return promiseRejectedWith(defaultWriterBrandCheckException('close')); - } - const stream = this._ownerWritableStream; - if (stream === undefined) { - return promiseRejectedWith(defaultWriterLockException('close')); - } - if (WritableStreamCloseQueuedOrInFlight(stream)) { - return promiseRejectedWith(new TypeError('Cannot close an already-closing stream')); - } - return WritableStreamDefaultWriterClose(this); - } - /** - * Releases the writer’s lock on the corresponding stream. After the lock is released, the writer is no longer active. - * If the associated stream is errored when the lock is released, the writer will appear errored in the same way from - * now on; otherwise, the writer will appear closed. - * - * Note that the lock can still be released even if some ongoing writes have not yet finished (i.e. even if the - * promises returned from previous calls to {@link WritableStreamDefaultWriter.write | write()} have not yet settled). - * It’s not necessary to hold the lock on the writer for the duration of the write; the lock instead simply prevents - * other producers from writing in an interleaved manner. - */ - releaseLock() { - if (!IsWritableStreamDefaultWriter(this)) { - throw defaultWriterBrandCheckException('releaseLock'); - } - const stream = this._ownerWritableStream; - if (stream === undefined) { - return; - } - WritableStreamDefaultWriterRelease(this); - } - write(chunk = undefined) { - if (!IsWritableStreamDefaultWriter(this)) { - return promiseRejectedWith(defaultWriterBrandCheckException('write')); - } - if (this._ownerWritableStream === undefined) { - return promiseRejectedWith(defaultWriterLockException('write to')); - } - return WritableStreamDefaultWriterWrite(this, chunk); - } - } - Object.defineProperties(WritableStreamDefaultWriter.prototype, { - abort: { enumerable: true }, - close: { enumerable: true }, - releaseLock: { enumerable: true }, - write: { enumerable: true }, - closed: { enumerable: true }, - desiredSize: { enumerable: true }, - ready: { enumerable: true } - }); - if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(WritableStreamDefaultWriter.prototype, SymbolPolyfill.toStringTag, { - value: 'WritableStreamDefaultWriter', - configurable: true - }); - } - // Abstract operations for the WritableStreamDefaultWriter. - function IsWritableStreamDefaultWriter(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_ownerWritableStream')) { - return false; - } - return true; - } - // A client of WritableStreamDefaultWriter may use these functions directly to bypass state check. - function WritableStreamDefaultWriterAbort(writer, reason) { - const stream = writer._ownerWritableStream; - return WritableStreamAbort(stream, reason); - } - function WritableStreamDefaultWriterClose(writer) { - const stream = writer._ownerWritableStream; - return WritableStreamClose(stream); - } - function WritableStreamDefaultWriterCloseWithErrorPropagation(writer) { - const stream = writer._ownerWritableStream; - const state = stream._state; - if (WritableStreamCloseQueuedOrInFlight(stream) || state === 'closed') { - return promiseResolvedWith(undefined); - } - if (state === 'errored') { - return promiseRejectedWith(stream._storedError); - } - return WritableStreamDefaultWriterClose(writer); - } - function WritableStreamDefaultWriterEnsureClosedPromiseRejected(writer, error) { - if (writer._closedPromiseState === 'pending') { - defaultWriterClosedPromiseReject(writer, error); - } - else { - defaultWriterClosedPromiseResetToRejected(writer, error); - } - } - function WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, error) { - if (writer._readyPromiseState === 'pending') { - defaultWriterReadyPromiseReject(writer, error); - } - else { - defaultWriterReadyPromiseResetToRejected(writer, error); - } - } - function WritableStreamDefaultWriterGetDesiredSize(writer) { - const stream = writer._ownerWritableStream; - const state = stream._state; - if (state === 'errored' || state === 'erroring') { - return null; - } - if (state === 'closed') { - return 0; - } - return WritableStreamDefaultControllerGetDesiredSize(stream._writableStreamController); - } - function WritableStreamDefaultWriterRelease(writer) { - const stream = writer._ownerWritableStream; - const releasedError = new TypeError(`Writer was released and can no longer be used to monitor the stream's closedness`); - WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, releasedError); - // The state transitions to "errored" before the sink abort() method runs, but the writer.closed promise is not - // rejected until afterwards. This means that simply testing state will not work. - WritableStreamDefaultWriterEnsureClosedPromiseRejected(writer, releasedError); - stream._writer = undefined; - writer._ownerWritableStream = undefined; - } - function WritableStreamDefaultWriterWrite(writer, chunk) { - const stream = writer._ownerWritableStream; - const controller = stream._writableStreamController; - const chunkSize = WritableStreamDefaultControllerGetChunkSize(controller, chunk); - if (stream !== writer._ownerWritableStream) { - return promiseRejectedWith(defaultWriterLockException('write to')); - } - const state = stream._state; - if (state === 'errored') { - return promiseRejectedWith(stream._storedError); - } - if (WritableStreamCloseQueuedOrInFlight(stream) || state === 'closed') { - return promiseRejectedWith(new TypeError('The stream is closing or closed and cannot be written to')); - } - if (state === 'erroring') { - return promiseRejectedWith(stream._storedError); - } - const promise = WritableStreamAddWriteRequest(stream); - WritableStreamDefaultControllerWrite(controller, chunk, chunkSize); - return promise; - } - const closeSentinel = {}; - /** - * Allows control of a {@link WritableStream | writable stream}'s state and internal queue. - * - * @public - */ - class WritableStreamDefaultController { - constructor() { - throw new TypeError('Illegal constructor'); - } - /** - * Closes the controlled writable stream, making all future interactions with it fail with the given error `e`. - * - * This method is rarely used, since usually it suffices to return a rejected promise from one of the underlying - * sink's methods. However, it can be useful for suddenly shutting down a stream in response to an event outside the - * normal lifecycle of interactions with the underlying sink. - */ - error(e = undefined) { - if (!IsWritableStreamDefaultController(this)) { - throw new TypeError('WritableStreamDefaultController.prototype.error can only be used on a WritableStreamDefaultController'); - } - const state = this._controlledWritableStream._state; - if (state !== 'writable') { - // The stream is closed, errored or will be soon. The sink can't do anything useful if it gets an error here, so - // just treat it as a no-op. - return; - } - WritableStreamDefaultControllerError(this, e); - } - /** @internal */ - [AbortSteps](reason) { - const result = this._abortAlgorithm(reason); - WritableStreamDefaultControllerClearAlgorithms(this); - return result; - } - /** @internal */ - [ErrorSteps]() { - ResetQueue(this); - } - } - Object.defineProperties(WritableStreamDefaultController.prototype, { - error: { enumerable: true } - }); - if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(WritableStreamDefaultController.prototype, SymbolPolyfill.toStringTag, { - value: 'WritableStreamDefaultController', - configurable: true - }); - } - // Abstract operations implementing interface required by the WritableStream. - function IsWritableStreamDefaultController(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_controlledWritableStream')) { - return false; - } - return true; - } - function SetUpWritableStreamDefaultController(stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark, sizeAlgorithm) { - controller._controlledWritableStream = stream; - stream._writableStreamController = controller; - // Need to set the slots so that the assert doesn't fire. In the spec the slots already exist implicitly. - controller._queue = undefined; - controller._queueTotalSize = undefined; - ResetQueue(controller); - controller._started = false; - controller._strategySizeAlgorithm = sizeAlgorithm; - controller._strategyHWM = highWaterMark; - controller._writeAlgorithm = writeAlgorithm; - controller._closeAlgorithm = closeAlgorithm; - controller._abortAlgorithm = abortAlgorithm; - const backpressure = WritableStreamDefaultControllerGetBackpressure(controller); - WritableStreamUpdateBackpressure(stream, backpressure); - const startResult = startAlgorithm(); - const startPromise = promiseResolvedWith(startResult); - uponPromise(startPromise, () => { - controller._started = true; - WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); - }, r => { - controller._started = true; - WritableStreamDealWithRejection(stream, r); - }); - } - function SetUpWritableStreamDefaultControllerFromUnderlyingSink(stream, underlyingSink, highWaterMark, sizeAlgorithm) { - const controller = Object.create(WritableStreamDefaultController.prototype); - let startAlgorithm = () => undefined; - let writeAlgorithm = () => promiseResolvedWith(undefined); - let closeAlgorithm = () => promiseResolvedWith(undefined); - let abortAlgorithm = () => promiseResolvedWith(undefined); - if (underlyingSink.start !== undefined) { - startAlgorithm = () => underlyingSink.start(controller); - } - if (underlyingSink.write !== undefined) { - writeAlgorithm = chunk => underlyingSink.write(chunk, controller); - } - if (underlyingSink.close !== undefined) { - closeAlgorithm = () => underlyingSink.close(); - } - if (underlyingSink.abort !== undefined) { - abortAlgorithm = reason => underlyingSink.abort(reason); - } - SetUpWritableStreamDefaultController(stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark, sizeAlgorithm); - } - // ClearAlgorithms may be called twice. Erroring the same stream in multiple ways will often result in redundant calls. - function WritableStreamDefaultControllerClearAlgorithms(controller) { - controller._writeAlgorithm = undefined; - controller._closeAlgorithm = undefined; - controller._abortAlgorithm = undefined; - controller._strategySizeAlgorithm = undefined; - } - function WritableStreamDefaultControllerClose(controller) { - EnqueueValueWithSize(controller, closeSentinel, 0); - WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); - } - function WritableStreamDefaultControllerGetChunkSize(controller, chunk) { - try { - return controller._strategySizeAlgorithm(chunk); - } - catch (chunkSizeE) { - WritableStreamDefaultControllerErrorIfNeeded(controller, chunkSizeE); - return 1; - } - } - function WritableStreamDefaultControllerGetDesiredSize(controller) { - return controller._strategyHWM - controller._queueTotalSize; - } - function WritableStreamDefaultControllerWrite(controller, chunk, chunkSize) { - try { - EnqueueValueWithSize(controller, chunk, chunkSize); - } - catch (enqueueE) { - WritableStreamDefaultControllerErrorIfNeeded(controller, enqueueE); - return; - } - const stream = controller._controlledWritableStream; - if (!WritableStreamCloseQueuedOrInFlight(stream) && stream._state === 'writable') { - const backpressure = WritableStreamDefaultControllerGetBackpressure(controller); - WritableStreamUpdateBackpressure(stream, backpressure); - } - WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); - } - // Abstract operations for the WritableStreamDefaultController. - function WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller) { - const stream = controller._controlledWritableStream; - if (!controller._started) { - return; - } - if (stream._inFlightWriteRequest !== undefined) { - return; - } - const state = stream._state; - if (state === 'erroring') { - WritableStreamFinishErroring(stream); - return; - } - if (controller._queue.length === 0) { - return; - } - const value = PeekQueueValue(controller); - if (value === closeSentinel) { - WritableStreamDefaultControllerProcessClose(controller); - } - else { - WritableStreamDefaultControllerProcessWrite(controller, value); - } - } - function WritableStreamDefaultControllerErrorIfNeeded(controller, error) { - if (controller._controlledWritableStream._state === 'writable') { - WritableStreamDefaultControllerError(controller, error); - } - } - function WritableStreamDefaultControllerProcessClose(controller) { - const stream = controller._controlledWritableStream; - WritableStreamMarkCloseRequestInFlight(stream); - DequeueValue(controller); - const sinkClosePromise = controller._closeAlgorithm(); - WritableStreamDefaultControllerClearAlgorithms(controller); - uponPromise(sinkClosePromise, () => { - WritableStreamFinishInFlightClose(stream); - }, reason => { - WritableStreamFinishInFlightCloseWithError(stream, reason); - }); - } - function WritableStreamDefaultControllerProcessWrite(controller, chunk) { - const stream = controller._controlledWritableStream; - WritableStreamMarkFirstWriteRequestInFlight(stream); - const sinkWritePromise = controller._writeAlgorithm(chunk); - uponPromise(sinkWritePromise, () => { - WritableStreamFinishInFlightWrite(stream); - const state = stream._state; - DequeueValue(controller); - if (!WritableStreamCloseQueuedOrInFlight(stream) && state === 'writable') { - const backpressure = WritableStreamDefaultControllerGetBackpressure(controller); - WritableStreamUpdateBackpressure(stream, backpressure); - } - WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); - }, reason => { - if (stream._state === 'writable') { - WritableStreamDefaultControllerClearAlgorithms(controller); - } - WritableStreamFinishInFlightWriteWithError(stream, reason); - }); - } - function WritableStreamDefaultControllerGetBackpressure(controller) { - const desiredSize = WritableStreamDefaultControllerGetDesiredSize(controller); - return desiredSize <= 0; - } - // A client of WritableStreamDefaultController may use these functions directly to bypass state check. - function WritableStreamDefaultControllerError(controller, error) { - const stream = controller._controlledWritableStream; - WritableStreamDefaultControllerClearAlgorithms(controller); - WritableStreamStartErroring(stream, error); - } - // Helper functions for the WritableStream. - function streamBrandCheckException$2(name) { - return new TypeError(`WritableStream.prototype.${name} can only be used on a WritableStream`); - } - // Helper functions for the WritableStreamDefaultWriter. - function defaultWriterBrandCheckException(name) { - return new TypeError(`WritableStreamDefaultWriter.prototype.${name} can only be used on a WritableStreamDefaultWriter`); - } - function defaultWriterLockException(name) { - return new TypeError('Cannot ' + name + ' a stream using a released writer'); - } - function defaultWriterClosedPromiseInitialize(writer) { - writer._closedPromise = newPromise((resolve, reject) => { - writer._closedPromise_resolve = resolve; - writer._closedPromise_reject = reject; - writer._closedPromiseState = 'pending'; - }); - } - function defaultWriterClosedPromiseInitializeAsRejected(writer, reason) { - defaultWriterClosedPromiseInitialize(writer); - defaultWriterClosedPromiseReject(writer, reason); - } - function defaultWriterClosedPromiseInitializeAsResolved(writer) { - defaultWriterClosedPromiseInitialize(writer); - defaultWriterClosedPromiseResolve(writer); - } - function defaultWriterClosedPromiseReject(writer, reason) { - if (writer._closedPromise_reject === undefined) { - return; - } - setPromiseIsHandledToTrue(writer._closedPromise); - writer._closedPromise_reject(reason); - writer._closedPromise_resolve = undefined; - writer._closedPromise_reject = undefined; - writer._closedPromiseState = 'rejected'; - } - function defaultWriterClosedPromiseResetToRejected(writer, reason) { - defaultWriterClosedPromiseInitializeAsRejected(writer, reason); - } - function defaultWriterClosedPromiseResolve(writer) { - if (writer._closedPromise_resolve === undefined) { - return; - } - writer._closedPromise_resolve(undefined); - writer._closedPromise_resolve = undefined; - writer._closedPromise_reject = undefined; - writer._closedPromiseState = 'resolved'; - } - function defaultWriterReadyPromiseInitialize(writer) { - writer._readyPromise = newPromise((resolve, reject) => { - writer._readyPromise_resolve = resolve; - writer._readyPromise_reject = reject; - }); - writer._readyPromiseState = 'pending'; - } - function defaultWriterReadyPromiseInitializeAsRejected(writer, reason) { - defaultWriterReadyPromiseInitialize(writer); - defaultWriterReadyPromiseReject(writer, reason); - } - function defaultWriterReadyPromiseInitializeAsResolved(writer) { - defaultWriterReadyPromiseInitialize(writer); - defaultWriterReadyPromiseResolve(writer); - } - function defaultWriterReadyPromiseReject(writer, reason) { - if (writer._readyPromise_reject === undefined) { - return; - } - setPromiseIsHandledToTrue(writer._readyPromise); - writer._readyPromise_reject(reason); - writer._readyPromise_resolve = undefined; - writer._readyPromise_reject = undefined; - writer._readyPromiseState = 'rejected'; - } - function defaultWriterReadyPromiseReset(writer) { - defaultWriterReadyPromiseInitialize(writer); - } - function defaultWriterReadyPromiseResetToRejected(writer, reason) { - defaultWriterReadyPromiseInitializeAsRejected(writer, reason); - } - function defaultWriterReadyPromiseResolve(writer) { - if (writer._readyPromise_resolve === undefined) { - return; - } - writer._readyPromise_resolve(undefined); - writer._readyPromise_resolve = undefined; - writer._readyPromise_reject = undefined; - writer._readyPromiseState = 'fulfilled'; - } - - function isAbortSignal(value) { - if (typeof value !== 'object' || value === null) { - return false; - } - try { - return typeof value.aborted === 'boolean'; - } - catch (_a) { - // AbortSignal.prototype.aborted throws if its brand check fails - return false; - } - } - - /// - const NativeDOMException = typeof DOMException !== 'undefined' ? DOMException : undefined; - - /// - function isDOMExceptionConstructor(ctor) { - if (!(typeof ctor === 'function' || typeof ctor === 'object')) { - return false; - } - try { - new ctor(); - return true; - } - catch (_a) { - return false; - } - } - function createDOMExceptionPolyfill() { - // eslint-disable-next-line no-shadow - const ctor = function DOMException(message, name) { - this.message = message || ''; - this.name = name || 'Error'; - if (Error.captureStackTrace) { - Error.captureStackTrace(this, this.constructor); - } - }; - ctor.prototype = Object.create(Error.prototype); - Object.defineProperty(ctor.prototype, 'constructor', { value: ctor, writable: true, configurable: true }); - return ctor; - } - // eslint-disable-next-line no-redeclare - const DOMException$1 = isDOMExceptionConstructor(NativeDOMException) ? NativeDOMException : createDOMExceptionPolyfill(); - - function ReadableStreamPipeTo(source, dest, preventClose, preventAbort, preventCancel, signal) { - const reader = AcquireReadableStreamDefaultReader(source); - const writer = AcquireWritableStreamDefaultWriter(dest); - source._disturbed = true; - let shuttingDown = false; - // This is used to keep track of the spec's requirement that we wait for ongoing writes during shutdown. - let currentWrite = promiseResolvedWith(undefined); - return newPromise((resolve, reject) => { - let abortAlgorithm; - if (signal !== undefined) { - abortAlgorithm = () => { - const error = new DOMException$1('Aborted', 'AbortError'); - const actions = []; - if (!preventAbort) { - actions.push(() => { - if (dest._state === 'writable') { - return WritableStreamAbort(dest, error); - } - return promiseResolvedWith(undefined); - }); - } - if (!preventCancel) { - actions.push(() => { - if (source._state === 'readable') { - return ReadableStreamCancel(source, error); - } - return promiseResolvedWith(undefined); - }); - } - shutdownWithAction(() => Promise.all(actions.map(action => action())), true, error); - }; - if (signal.aborted) { - abortAlgorithm(); - return; - } - signal.addEventListener('abort', abortAlgorithm); - } - // Using reader and writer, read all chunks from this and write them to dest - // - Backpressure must be enforced - // - Shutdown must stop all activity - function pipeLoop() { - return newPromise((resolveLoop, rejectLoop) => { - function next(done) { - if (done) { - resolveLoop(); - } - else { - // Use `PerformPromiseThen` instead of `uponPromise` to avoid - // adding unnecessary `.catch(rethrowAssertionErrorRejection)` handlers - PerformPromiseThen(pipeStep(), next, rejectLoop); - } - } - next(false); - }); - } - function pipeStep() { - if (shuttingDown) { - return promiseResolvedWith(true); - } - return PerformPromiseThen(writer._readyPromise, () => { - return newPromise((resolveRead, rejectRead) => { - ReadableStreamDefaultReaderRead(reader, { - _chunkSteps: chunk => { - currentWrite = PerformPromiseThen(WritableStreamDefaultWriterWrite(writer, chunk), undefined, noop); - resolveRead(false); - }, - _closeSteps: () => resolveRead(true), - _errorSteps: rejectRead - }); - }); - }); - } - // Errors must be propagated forward - isOrBecomesErrored(source, reader._closedPromise, storedError => { - if (!preventAbort) { - shutdownWithAction(() => WritableStreamAbort(dest, storedError), true, storedError); - } - else { - shutdown(true, storedError); - } - }); - // Errors must be propagated backward - isOrBecomesErrored(dest, writer._closedPromise, storedError => { - if (!preventCancel) { - shutdownWithAction(() => ReadableStreamCancel(source, storedError), true, storedError); - } - else { - shutdown(true, storedError); - } - }); - // Closing must be propagated forward - isOrBecomesClosed(source, reader._closedPromise, () => { - if (!preventClose) { - shutdownWithAction(() => WritableStreamDefaultWriterCloseWithErrorPropagation(writer)); - } - else { - shutdown(); - } - }); - // Closing must be propagated backward - if (WritableStreamCloseQueuedOrInFlight(dest) || dest._state === 'closed') { - const destClosed = new TypeError('the destination writable stream closed before all data could be piped to it'); - if (!preventCancel) { - shutdownWithAction(() => ReadableStreamCancel(source, destClosed), true, destClosed); - } - else { - shutdown(true, destClosed); - } - } - setPromiseIsHandledToTrue(pipeLoop()); - function waitForWritesToFinish() { - // Another write may have started while we were waiting on this currentWrite, so we have to be sure to wait - // for that too. - const oldCurrentWrite = currentWrite; - return PerformPromiseThen(currentWrite, () => oldCurrentWrite !== currentWrite ? waitForWritesToFinish() : undefined); - } - function isOrBecomesErrored(stream, promise, action) { - if (stream._state === 'errored') { - action(stream._storedError); - } - else { - uponRejection(promise, action); - } - } - function isOrBecomesClosed(stream, promise, action) { - if (stream._state === 'closed') { - action(); - } - else { - uponFulfillment(promise, action); - } - } - function shutdownWithAction(action, originalIsError, originalError) { - if (shuttingDown) { - return; - } - shuttingDown = true; - if (dest._state === 'writable' && !WritableStreamCloseQueuedOrInFlight(dest)) { - uponFulfillment(waitForWritesToFinish(), doTheRest); - } - else { - doTheRest(); - } - function doTheRest() { - uponPromise(action(), () => finalize(originalIsError, originalError), newError => finalize(true, newError)); - } - } - function shutdown(isError, error) { - if (shuttingDown) { - return; - } - shuttingDown = true; - if (dest._state === 'writable' && !WritableStreamCloseQueuedOrInFlight(dest)) { - uponFulfillment(waitForWritesToFinish(), () => finalize(isError, error)); - } - else { - finalize(isError, error); - } - } - function finalize(isError, error) { - WritableStreamDefaultWriterRelease(writer); - ReadableStreamReaderGenericRelease(reader); - if (signal !== undefined) { - signal.removeEventListener('abort', abortAlgorithm); - } - if (isError) { - reject(error); - } - else { - resolve(undefined); - } - } - }); - } - - /** - * Allows control of a {@link ReadableStream | readable stream}'s state and internal queue. - * - * @public - */ - class ReadableStreamDefaultController { - constructor() { - throw new TypeError('Illegal constructor'); - } - /** - * Returns the desired size to fill the controlled stream's internal queue. It can be negative, if the queue is - * over-full. An underlying source ought to use this information to determine when and how to apply backpressure. - */ - get desiredSize() { - if (!IsReadableStreamDefaultController(this)) { - throw defaultControllerBrandCheckException$1('desiredSize'); - } - return ReadableStreamDefaultControllerGetDesiredSize(this); - } - /** - * Closes the controlled readable stream. Consumers will still be able to read any previously-enqueued chunks from - * the stream, but once those are read, the stream will become closed. - */ - close() { - if (!IsReadableStreamDefaultController(this)) { - throw defaultControllerBrandCheckException$1('close'); - } - if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(this)) { - throw new TypeError('The stream is not in a state that permits close'); - } - ReadableStreamDefaultControllerClose(this); - } - enqueue(chunk = undefined) { - if (!IsReadableStreamDefaultController(this)) { - throw defaultControllerBrandCheckException$1('enqueue'); - } - if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(this)) { - throw new TypeError('The stream is not in a state that permits enqueue'); - } - return ReadableStreamDefaultControllerEnqueue(this, chunk); - } - /** - * Errors the controlled readable stream, making all future interactions with it fail with the given error `e`. - */ - error(e = undefined) { - if (!IsReadableStreamDefaultController(this)) { - throw defaultControllerBrandCheckException$1('error'); - } - ReadableStreamDefaultControllerError(this, e); - } - /** @internal */ - [CancelSteps](reason) { - ResetQueue(this); - const result = this._cancelAlgorithm(reason); - ReadableStreamDefaultControllerClearAlgorithms(this); - return result; - } - /** @internal */ - [PullSteps](readRequest) { - const stream = this._controlledReadableStream; - if (this._queue.length > 0) { - const chunk = DequeueValue(this); - if (this._closeRequested && this._queue.length === 0) { - ReadableStreamDefaultControllerClearAlgorithms(this); - ReadableStreamClose(stream); - } - else { - ReadableStreamDefaultControllerCallPullIfNeeded(this); - } - readRequest._chunkSteps(chunk); - } - else { - ReadableStreamAddReadRequest(stream, readRequest); - ReadableStreamDefaultControllerCallPullIfNeeded(this); - } - } - } - Object.defineProperties(ReadableStreamDefaultController.prototype, { - close: { enumerable: true }, - enqueue: { enumerable: true }, - error: { enumerable: true }, - desiredSize: { enumerable: true } - }); - if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(ReadableStreamDefaultController.prototype, SymbolPolyfill.toStringTag, { - value: 'ReadableStreamDefaultController', - configurable: true - }); - } - // Abstract operations for the ReadableStreamDefaultController. - function IsReadableStreamDefaultController(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_controlledReadableStream')) { - return false; - } - return true; - } - function ReadableStreamDefaultControllerCallPullIfNeeded(controller) { - const shouldPull = ReadableStreamDefaultControllerShouldCallPull(controller); - if (!shouldPull) { - return; - } - if (controller._pulling) { - controller._pullAgain = true; - return; - } - controller._pulling = true; - const pullPromise = controller._pullAlgorithm(); - uponPromise(pullPromise, () => { - controller._pulling = false; - if (controller._pullAgain) { - controller._pullAgain = false; - ReadableStreamDefaultControllerCallPullIfNeeded(controller); - } - }, e => { - ReadableStreamDefaultControllerError(controller, e); - }); - } - function ReadableStreamDefaultControllerShouldCallPull(controller) { - const stream = controller._controlledReadableStream; - if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(controller)) { - return false; - } - if (!controller._started) { - return false; - } - if (IsReadableStreamLocked(stream) && ReadableStreamGetNumReadRequests(stream) > 0) { - return true; - } - const desiredSize = ReadableStreamDefaultControllerGetDesiredSize(controller); - if (desiredSize > 0) { - return true; - } - return false; - } - function ReadableStreamDefaultControllerClearAlgorithms(controller) { - controller._pullAlgorithm = undefined; - controller._cancelAlgorithm = undefined; - controller._strategySizeAlgorithm = undefined; - } - // A client of ReadableStreamDefaultController may use these functions directly to bypass state check. - function ReadableStreamDefaultControllerClose(controller) { - if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(controller)) { - return; - } - const stream = controller._controlledReadableStream; - controller._closeRequested = true; - if (controller._queue.length === 0) { - ReadableStreamDefaultControllerClearAlgorithms(controller); - ReadableStreamClose(stream); - } - } - function ReadableStreamDefaultControllerEnqueue(controller, chunk) { - if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(controller)) { - return; - } - const stream = controller._controlledReadableStream; - if (IsReadableStreamLocked(stream) && ReadableStreamGetNumReadRequests(stream) > 0) { - ReadableStreamFulfillReadRequest(stream, chunk, false); - } - else { - let chunkSize; - try { - chunkSize = controller._strategySizeAlgorithm(chunk); - } - catch (chunkSizeE) { - ReadableStreamDefaultControllerError(controller, chunkSizeE); - throw chunkSizeE; - } - try { - EnqueueValueWithSize(controller, chunk, chunkSize); - } - catch (enqueueE) { - ReadableStreamDefaultControllerError(controller, enqueueE); - throw enqueueE; - } - } - ReadableStreamDefaultControllerCallPullIfNeeded(controller); - } - function ReadableStreamDefaultControllerError(controller, e) { - const stream = controller._controlledReadableStream; - if (stream._state !== 'readable') { - return; - } - ResetQueue(controller); - ReadableStreamDefaultControllerClearAlgorithms(controller); - ReadableStreamError(stream, e); - } - function ReadableStreamDefaultControllerGetDesiredSize(controller) { - const state = controller._controlledReadableStream._state; - if (state === 'errored') { - return null; - } - if (state === 'closed') { - return 0; - } - return controller._strategyHWM - controller._queueTotalSize; - } - // This is used in the implementation of TransformStream. - function ReadableStreamDefaultControllerHasBackpressure(controller) { - if (ReadableStreamDefaultControllerShouldCallPull(controller)) { - return false; - } - return true; - } - function ReadableStreamDefaultControllerCanCloseOrEnqueue(controller) { - const state = controller._controlledReadableStream._state; - if (!controller._closeRequested && state === 'readable') { - return true; - } - return false; - } - function SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm) { - controller._controlledReadableStream = stream; - controller._queue = undefined; - controller._queueTotalSize = undefined; - ResetQueue(controller); - controller._started = false; - controller._closeRequested = false; - controller._pullAgain = false; - controller._pulling = false; - controller._strategySizeAlgorithm = sizeAlgorithm; - controller._strategyHWM = highWaterMark; - controller._pullAlgorithm = pullAlgorithm; - controller._cancelAlgorithm = cancelAlgorithm; - stream._readableStreamController = controller; - const startResult = startAlgorithm(); - uponPromise(promiseResolvedWith(startResult), () => { - controller._started = true; - ReadableStreamDefaultControllerCallPullIfNeeded(controller); - }, r => { - ReadableStreamDefaultControllerError(controller, r); - }); - } - function SetUpReadableStreamDefaultControllerFromUnderlyingSource(stream, underlyingSource, highWaterMark, sizeAlgorithm) { - const controller = Object.create(ReadableStreamDefaultController.prototype); - let startAlgorithm = () => undefined; - let pullAlgorithm = () => promiseResolvedWith(undefined); - let cancelAlgorithm = () => promiseResolvedWith(undefined); - if (underlyingSource.start !== undefined) { - startAlgorithm = () => underlyingSource.start(controller); - } - if (underlyingSource.pull !== undefined) { - pullAlgorithm = () => underlyingSource.pull(controller); - } - if (underlyingSource.cancel !== undefined) { - cancelAlgorithm = reason => underlyingSource.cancel(reason); - } - SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm); - } - // Helper functions for the ReadableStreamDefaultController. - function defaultControllerBrandCheckException$1(name) { - return new TypeError(`ReadableStreamDefaultController.prototype.${name} can only be used on a ReadableStreamDefaultController`); - } - - function ReadableStreamTee(stream, cloneForBranch2) { - const reader = AcquireReadableStreamDefaultReader(stream); - let reading = false; - let canceled1 = false; - let canceled2 = false; - let reason1; - let reason2; - let branch1; - let branch2; - let resolveCancelPromise; - const cancelPromise = newPromise(resolve => { - resolveCancelPromise = resolve; - }); - function pullAlgorithm() { - if (reading) { - return promiseResolvedWith(undefined); - } - reading = true; - const readRequest = { - _chunkSteps: value => { - // This needs to be delayed a microtask because it takes at least a microtask to detect errors (using - // reader._closedPromise below), and we want errors in stream to error both branches immediately. We cannot let - // successful synchronously-available reads get ahead of asynchronously-available errors. - queueMicrotask(() => { - reading = false; - const value1 = value; - const value2 = value; - // There is no way to access the cloning code right now in the reference implementation. - // If we add one then we'll need an implementation for serializable objects. - // if (!canceled2 && cloneForBranch2) { - // value2 = StructuredDeserialize(StructuredSerialize(value2)); - // } - if (!canceled1) { - ReadableStreamDefaultControllerEnqueue(branch1._readableStreamController, value1); - } - if (!canceled2) { - ReadableStreamDefaultControllerEnqueue(branch2._readableStreamController, value2); - } - }); - }, - _closeSteps: () => { - reading = false; - if (!canceled1) { - ReadableStreamDefaultControllerClose(branch1._readableStreamController); - } - if (!canceled2) { - ReadableStreamDefaultControllerClose(branch2._readableStreamController); - } - if (!canceled1 || !canceled2) { - resolveCancelPromise(undefined); - } - }, - _errorSteps: () => { - reading = false; - } - }; - ReadableStreamDefaultReaderRead(reader, readRequest); - return promiseResolvedWith(undefined); - } - function cancel1Algorithm(reason) { - canceled1 = true; - reason1 = reason; - if (canceled2) { - const compositeReason = CreateArrayFromList([reason1, reason2]); - const cancelResult = ReadableStreamCancel(stream, compositeReason); - resolveCancelPromise(cancelResult); - } - return cancelPromise; - } - function cancel2Algorithm(reason) { - canceled2 = true; - reason2 = reason; - if (canceled1) { - const compositeReason = CreateArrayFromList([reason1, reason2]); - const cancelResult = ReadableStreamCancel(stream, compositeReason); - resolveCancelPromise(cancelResult); - } - return cancelPromise; - } - function startAlgorithm() { - // do nothing - } - branch1 = CreateReadableStream(startAlgorithm, pullAlgorithm, cancel1Algorithm); - branch2 = CreateReadableStream(startAlgorithm, pullAlgorithm, cancel2Algorithm); - uponRejection(reader._closedPromise, (r) => { - ReadableStreamDefaultControllerError(branch1._readableStreamController, r); - ReadableStreamDefaultControllerError(branch2._readableStreamController, r); - if (!canceled1 || !canceled2) { - resolveCancelPromise(undefined); - } - }); - return [branch1, branch2]; - } - - function convertUnderlyingDefaultOrByteSource(source, context) { - assertDictionary(source, context); - const original = source; - const autoAllocateChunkSize = original === null || original === void 0 ? void 0 : original.autoAllocateChunkSize; - const cancel = original === null || original === void 0 ? void 0 : original.cancel; - const pull = original === null || original === void 0 ? void 0 : original.pull; - const start = original === null || original === void 0 ? void 0 : original.start; - const type = original === null || original === void 0 ? void 0 : original.type; - return { - autoAllocateChunkSize: autoAllocateChunkSize === undefined ? - undefined : - convertUnsignedLongLongWithEnforceRange(autoAllocateChunkSize, `${context} has member 'autoAllocateChunkSize' that`), - cancel: cancel === undefined ? - undefined : - convertUnderlyingSourceCancelCallback(cancel, original, `${context} has member 'cancel' that`), - pull: pull === undefined ? - undefined : - convertUnderlyingSourcePullCallback(pull, original, `${context} has member 'pull' that`), - start: start === undefined ? - undefined : - convertUnderlyingSourceStartCallback(start, original, `${context} has member 'start' that`), - type: type === undefined ? undefined : convertReadableStreamType(type, `${context} has member 'type' that`) - }; - } - function convertUnderlyingSourceCancelCallback(fn, original, context) { - assertFunction(fn, context); - return (reason) => promiseCall(fn, original, [reason]); - } - function convertUnderlyingSourcePullCallback(fn, original, context) { - assertFunction(fn, context); - return (controller) => promiseCall(fn, original, [controller]); - } - function convertUnderlyingSourceStartCallback(fn, original, context) { - assertFunction(fn, context); - return (controller) => reflectCall(fn, original, [controller]); - } - function convertReadableStreamType(type, context) { - type = `${type}`; - if (type !== 'bytes') { - throw new TypeError(`${context} '${type}' is not a valid enumeration value for ReadableStreamType`); - } - return type; - } - - function convertReaderOptions(options, context) { - assertDictionary(options, context); - const mode = options === null || options === void 0 ? void 0 : options.mode; - return { - mode: mode === undefined ? undefined : convertReadableStreamReaderMode(mode, `${context} has member 'mode' that`) - }; - } - function convertReadableStreamReaderMode(mode, context) { - mode = `${mode}`; - if (mode !== 'byob') { - throw new TypeError(`${context} '${mode}' is not a valid enumeration value for ReadableStreamReaderMode`); - } - return mode; - } - - function convertIteratorOptions(options, context) { - assertDictionary(options, context); - const preventCancel = options === null || options === void 0 ? void 0 : options.preventCancel; - return { preventCancel: Boolean(preventCancel) }; - } - - function convertPipeOptions(options, context) { - assertDictionary(options, context); - const preventAbort = options === null || options === void 0 ? void 0 : options.preventAbort; - const preventCancel = options === null || options === void 0 ? void 0 : options.preventCancel; - const preventClose = options === null || options === void 0 ? void 0 : options.preventClose; - const signal = options === null || options === void 0 ? void 0 : options.signal; - if (signal !== undefined) { - assertAbortSignal(signal, `${context} has member 'signal' that`); - } - return { - preventAbort: Boolean(preventAbort), - preventCancel: Boolean(preventCancel), - preventClose: Boolean(preventClose), - signal - }; - } - function assertAbortSignal(signal, context) { - if (!isAbortSignal(signal)) { - throw new TypeError(`${context} is not an AbortSignal.`); - } - } - - function convertReadableWritablePair(pair, context) { - assertDictionary(pair, context); - const readable = pair === null || pair === void 0 ? void 0 : pair.readable; - assertRequiredField(readable, 'readable', 'ReadableWritablePair'); - assertReadableStream(readable, `${context} has member 'readable' that`); - const writable = pair === null || pair === void 0 ? void 0 : pair.writable; - assertRequiredField(writable, 'writable', 'ReadableWritablePair'); - assertWritableStream(writable, `${context} has member 'writable' that`); - return { readable, writable }; - } - - /** - * A readable stream represents a source of data, from which you can read. - * - * @public - */ - class ReadableStream$1 { - constructor(rawUnderlyingSource = {}, rawStrategy = {}) { - if (rawUnderlyingSource === undefined) { - rawUnderlyingSource = null; - } - else { - assertObject(rawUnderlyingSource, 'First parameter'); - } - const strategy = convertQueuingStrategy(rawStrategy, 'Second parameter'); - const underlyingSource = convertUnderlyingDefaultOrByteSource(rawUnderlyingSource, 'First parameter'); - InitializeReadableStream(this); - if (underlyingSource.type === 'bytes') { - if (strategy.size !== undefined) { - throw new RangeError('The strategy for a byte stream cannot have a size function'); - } - const highWaterMark = ExtractHighWaterMark(strategy, 0); - SetUpReadableByteStreamControllerFromUnderlyingSource(this, underlyingSource, highWaterMark); - } - else { - const sizeAlgorithm = ExtractSizeAlgorithm(strategy); - const highWaterMark = ExtractHighWaterMark(strategy, 1); - SetUpReadableStreamDefaultControllerFromUnderlyingSource(this, underlyingSource, highWaterMark, sizeAlgorithm); - } - } - /** - * Whether or not the readable stream is locked to a {@link ReadableStreamDefaultReader | reader}. - */ - get locked() { - if (!IsReadableStream(this)) { - throw streamBrandCheckException$1('locked'); - } - return IsReadableStreamLocked(this); - } - /** - * Cancels the stream, signaling a loss of interest in the stream by a consumer. - * - * The supplied `reason` argument will be given to the underlying source's {@link UnderlyingSource.cancel | cancel()} - * method, which might or might not use it. - */ - cancel(reason = undefined) { - if (!IsReadableStream(this)) { - return promiseRejectedWith(streamBrandCheckException$1('cancel')); - } - if (IsReadableStreamLocked(this)) { - return promiseRejectedWith(new TypeError('Cannot cancel a stream that already has a reader')); - } - return ReadableStreamCancel(this, reason); - } - getReader(rawOptions = undefined) { - if (!IsReadableStream(this)) { - throw streamBrandCheckException$1('getReader'); - } - const options = convertReaderOptions(rawOptions, 'First parameter'); - if (options.mode === undefined) { - return AcquireReadableStreamDefaultReader(this); - } - return AcquireReadableStreamBYOBReader(this); - } - pipeThrough(rawTransform, rawOptions = {}) { - if (!IsReadableStream(this)) { - throw streamBrandCheckException$1('pipeThrough'); - } - assertRequiredArgument(rawTransform, 1, 'pipeThrough'); - const transform = convertReadableWritablePair(rawTransform, 'First parameter'); - const options = convertPipeOptions(rawOptions, 'Second parameter'); - if (IsReadableStreamLocked(this)) { - throw new TypeError('ReadableStream.prototype.pipeThrough cannot be used on a locked ReadableStream'); - } - if (IsWritableStreamLocked(transform.writable)) { - throw new TypeError('ReadableStream.prototype.pipeThrough cannot be used on a locked WritableStream'); - } - const promise = ReadableStreamPipeTo(this, transform.writable, options.preventClose, options.preventAbort, options.preventCancel, options.signal); - setPromiseIsHandledToTrue(promise); - return transform.readable; - } - pipeTo(destination, rawOptions = {}) { - if (!IsReadableStream(this)) { - return promiseRejectedWith(streamBrandCheckException$1('pipeTo')); - } - if (destination === undefined) { - return promiseRejectedWith(`Parameter 1 is required in 'pipeTo'.`); - } - if (!IsWritableStream(destination)) { - return promiseRejectedWith(new TypeError(`ReadableStream.prototype.pipeTo's first argument must be a WritableStream`)); - } - let options; - try { - options = convertPipeOptions(rawOptions, 'Second parameter'); - } - catch (e) { - return promiseRejectedWith(e); - } - if (IsReadableStreamLocked(this)) { - return promiseRejectedWith(new TypeError('ReadableStream.prototype.pipeTo cannot be used on a locked ReadableStream')); - } - if (IsWritableStreamLocked(destination)) { - return promiseRejectedWith(new TypeError('ReadableStream.prototype.pipeTo cannot be used on a locked WritableStream')); - } - return ReadableStreamPipeTo(this, destination, options.preventClose, options.preventAbort, options.preventCancel, options.signal); - } - /** - * Tees this readable stream, returning a two-element array containing the two resulting branches as - * new {@link ReadableStream} instances. - * - * Teeing a stream will lock it, preventing any other consumer from acquiring a reader. - * To cancel the stream, cancel both of the resulting branches; a composite cancellation reason will then be - * propagated to the stream's underlying source. - * - * Note that the chunks seen in each branch will be the same object. If the chunks are not immutable, - * this could allow interference between the two branches. - */ - tee() { - if (!IsReadableStream(this)) { - throw streamBrandCheckException$1('tee'); - } - const branches = ReadableStreamTee(this); - return CreateArrayFromList(branches); - } - values(rawOptions = undefined) { - if (!IsReadableStream(this)) { - throw streamBrandCheckException$1('values'); - } - const options = convertIteratorOptions(rawOptions, 'First parameter'); - return AcquireReadableStreamAsyncIterator(this, options.preventCancel); - } - } - Object.defineProperties(ReadableStream$1.prototype, { - cancel: { enumerable: true }, - getReader: { enumerable: true }, - pipeThrough: { enumerable: true }, - pipeTo: { enumerable: true }, - tee: { enumerable: true }, - values: { enumerable: true }, - locked: { enumerable: true } - }); - if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(ReadableStream$1.prototype, SymbolPolyfill.toStringTag, { - value: 'ReadableStream', - configurable: true - }); - } - if (typeof SymbolPolyfill.asyncIterator === 'symbol') { - Object.defineProperty(ReadableStream$1.prototype, SymbolPolyfill.asyncIterator, { - value: ReadableStream$1.prototype.values, - writable: true, - configurable: true - }); - } - // Abstract operations for the ReadableStream. - // Throws if and only if startAlgorithm throws. - function CreateReadableStream(startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark = 1, sizeAlgorithm = () => 1) { - const stream = Object.create(ReadableStream$1.prototype); - InitializeReadableStream(stream); - const controller = Object.create(ReadableStreamDefaultController.prototype); - SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm); - return stream; - } - function InitializeReadableStream(stream) { - stream._state = 'readable'; - stream._reader = undefined; - stream._storedError = undefined; - stream._disturbed = false; - } - function IsReadableStream(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_readableStreamController')) { - return false; - } - return true; - } - function IsReadableStreamLocked(stream) { - if (stream._reader === undefined) { - return false; - } - return true; - } - // ReadableStream API exposed for controllers. - function ReadableStreamCancel(stream, reason) { - stream._disturbed = true; - if (stream._state === 'closed') { - return promiseResolvedWith(undefined); - } - if (stream._state === 'errored') { - return promiseRejectedWith(stream._storedError); - } - ReadableStreamClose(stream); - const sourceCancelPromise = stream._readableStreamController[CancelSteps](reason); - return transformPromiseWith(sourceCancelPromise, noop); - } - function ReadableStreamClose(stream) { - stream._state = 'closed'; - const reader = stream._reader; - if (reader === undefined) { - return; - } - defaultReaderClosedPromiseResolve(reader); - if (IsReadableStreamDefaultReader(reader)) { - reader._readRequests.forEach(readRequest => { - readRequest._closeSteps(); - }); - reader._readRequests = new SimpleQueue(); - } - } - function ReadableStreamError(stream, e) { - stream._state = 'errored'; - stream._storedError = e; - const reader = stream._reader; - if (reader === undefined) { - return; - } - defaultReaderClosedPromiseReject(reader, e); - if (IsReadableStreamDefaultReader(reader)) { - reader._readRequests.forEach(readRequest => { - readRequest._errorSteps(e); - }); - reader._readRequests = new SimpleQueue(); - } - else { - reader._readIntoRequests.forEach(readIntoRequest => { - readIntoRequest._errorSteps(e); - }); - reader._readIntoRequests = new SimpleQueue(); - } - } - // Helper functions for the ReadableStream. - function streamBrandCheckException$1(name) { - return new TypeError(`ReadableStream.prototype.${name} can only be used on a ReadableStream`); - } - - function convertQueuingStrategyInit(init, context) { - assertDictionary(init, context); - const highWaterMark = init === null || init === void 0 ? void 0 : init.highWaterMark; - assertRequiredField(highWaterMark, 'highWaterMark', 'QueuingStrategyInit'); - return { - highWaterMark: convertUnrestrictedDouble(highWaterMark) - }; - } - - const byteLengthSizeFunction = function size(chunk) { - return chunk.byteLength; - }; - /** - * A queuing strategy that counts the number of bytes in each chunk. - * - * @public - */ - class ByteLengthQueuingStrategy { - constructor(options) { - assertRequiredArgument(options, 1, 'ByteLengthQueuingStrategy'); - options = convertQueuingStrategyInit(options, 'First parameter'); - this._byteLengthQueuingStrategyHighWaterMark = options.highWaterMark; - } - /** - * Returns the high water mark provided to the constructor. - */ - get highWaterMark() { - if (!IsByteLengthQueuingStrategy(this)) { - throw byteLengthBrandCheckException('highWaterMark'); - } - return this._byteLengthQueuingStrategyHighWaterMark; - } - /** - * Measures the size of `chunk` by returning the value of its `byteLength` property. - */ - get size() { - if (!IsByteLengthQueuingStrategy(this)) { - throw byteLengthBrandCheckException('size'); - } - return byteLengthSizeFunction; - } - } - Object.defineProperties(ByteLengthQueuingStrategy.prototype, { - highWaterMark: { enumerable: true }, - size: { enumerable: true } - }); - if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(ByteLengthQueuingStrategy.prototype, SymbolPolyfill.toStringTag, { - value: 'ByteLengthQueuingStrategy', - configurable: true - }); - } - // Helper functions for the ByteLengthQueuingStrategy. - function byteLengthBrandCheckException(name) { - return new TypeError(`ByteLengthQueuingStrategy.prototype.${name} can only be used on a ByteLengthQueuingStrategy`); - } - function IsByteLengthQueuingStrategy(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_byteLengthQueuingStrategyHighWaterMark')) { - return false; - } - return true; - } - - const countSizeFunction = function size() { - return 1; - }; - /** - * A queuing strategy that counts the number of chunks. - * - * @public - */ - class CountQueuingStrategy { - constructor(options) { - assertRequiredArgument(options, 1, 'CountQueuingStrategy'); - options = convertQueuingStrategyInit(options, 'First parameter'); - this._countQueuingStrategyHighWaterMark = options.highWaterMark; - } - /** - * Returns the high water mark provided to the constructor. - */ - get highWaterMark() { - if (!IsCountQueuingStrategy(this)) { - throw countBrandCheckException('highWaterMark'); - } - return this._countQueuingStrategyHighWaterMark; - } - /** - * Measures the size of `chunk` by always returning 1. - * This ensures that the total queue size is a count of the number of chunks in the queue. - */ - get size() { - if (!IsCountQueuingStrategy(this)) { - throw countBrandCheckException('size'); - } - return countSizeFunction; - } - } - Object.defineProperties(CountQueuingStrategy.prototype, { - highWaterMark: { enumerable: true }, - size: { enumerable: true } - }); - if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(CountQueuingStrategy.prototype, SymbolPolyfill.toStringTag, { - value: 'CountQueuingStrategy', - configurable: true - }); - } - // Helper functions for the CountQueuingStrategy. - function countBrandCheckException(name) { - return new TypeError(`CountQueuingStrategy.prototype.${name} can only be used on a CountQueuingStrategy`); - } - function IsCountQueuingStrategy(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_countQueuingStrategyHighWaterMark')) { - return false; - } - return true; - } - - function convertTransformer(original, context) { - assertDictionary(original, context); - const flush = original === null || original === void 0 ? void 0 : original.flush; - const readableType = original === null || original === void 0 ? void 0 : original.readableType; - const start = original === null || original === void 0 ? void 0 : original.start; - const transform = original === null || original === void 0 ? void 0 : original.transform; - const writableType = original === null || original === void 0 ? void 0 : original.writableType; - return { - flush: flush === undefined ? - undefined : - convertTransformerFlushCallback(flush, original, `${context} has member 'flush' that`), - readableType, - start: start === undefined ? - undefined : - convertTransformerStartCallback(start, original, `${context} has member 'start' that`), - transform: transform === undefined ? - undefined : - convertTransformerTransformCallback(transform, original, `${context} has member 'transform' that`), - writableType - }; - } - function convertTransformerFlushCallback(fn, original, context) { - assertFunction(fn, context); - return (controller) => promiseCall(fn, original, [controller]); - } - function convertTransformerStartCallback(fn, original, context) { - assertFunction(fn, context); - return (controller) => reflectCall(fn, original, [controller]); - } - function convertTransformerTransformCallback(fn, original, context) { - assertFunction(fn, context); - return (chunk, controller) => promiseCall(fn, original, [chunk, controller]); - } - - // Class TransformStream - /** - * A transform stream consists of a pair of streams: a {@link WritableStream | writable stream}, - * known as its writable side, and a {@link ReadableStream | readable stream}, known as its readable side. - * In a manner specific to the transform stream in question, writes to the writable side result in new data being - * made available for reading from the readable side. - * - * @public - */ - class TransformStream$1 { - constructor(rawTransformer = {}, rawWritableStrategy = {}, rawReadableStrategy = {}) { - if (rawTransformer === undefined) { - rawTransformer = null; - } - const writableStrategy = convertQueuingStrategy(rawWritableStrategy, 'Second parameter'); - const readableStrategy = convertQueuingStrategy(rawReadableStrategy, 'Third parameter'); - const transformer = convertTransformer(rawTransformer, 'First parameter'); - if (transformer.readableType !== undefined) { - throw new RangeError('Invalid readableType specified'); - } - if (transformer.writableType !== undefined) { - throw new RangeError('Invalid writableType specified'); - } - const readableHighWaterMark = ExtractHighWaterMark(readableStrategy, 0); - const readableSizeAlgorithm = ExtractSizeAlgorithm(readableStrategy); - const writableHighWaterMark = ExtractHighWaterMark(writableStrategy, 1); - const writableSizeAlgorithm = ExtractSizeAlgorithm(writableStrategy); - let startPromise_resolve; - const startPromise = newPromise(resolve => { - startPromise_resolve = resolve; - }); - InitializeTransformStream(this, startPromise, writableHighWaterMark, writableSizeAlgorithm, readableHighWaterMark, readableSizeAlgorithm); - SetUpTransformStreamDefaultControllerFromTransformer(this, transformer); - if (transformer.start !== undefined) { - startPromise_resolve(transformer.start(this._transformStreamController)); - } - else { - startPromise_resolve(undefined); - } - } - /** - * The readable side of the transform stream. - */ - get readable() { - if (!IsTransformStream(this)) { - throw streamBrandCheckException('readable'); - } - return this._readable; - } - /** - * The writable side of the transform stream. - */ - get writable() { - if (!IsTransformStream(this)) { - throw streamBrandCheckException('writable'); - } - return this._writable; - } - } - Object.defineProperties(TransformStream$1.prototype, { - readable: { enumerable: true }, - writable: { enumerable: true } - }); - if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(TransformStream$1.prototype, SymbolPolyfill.toStringTag, { - value: 'TransformStream', - configurable: true - }); - } - function InitializeTransformStream(stream, startPromise, writableHighWaterMark, writableSizeAlgorithm, readableHighWaterMark, readableSizeAlgorithm) { - function startAlgorithm() { - return startPromise; - } - function writeAlgorithm(chunk) { - return TransformStreamDefaultSinkWriteAlgorithm(stream, chunk); - } - function abortAlgorithm(reason) { - return TransformStreamDefaultSinkAbortAlgorithm(stream, reason); - } - function closeAlgorithm() { - return TransformStreamDefaultSinkCloseAlgorithm(stream); - } - stream._writable = CreateWritableStream(startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, writableHighWaterMark, writableSizeAlgorithm); - function pullAlgorithm() { - return TransformStreamDefaultSourcePullAlgorithm(stream); - } - function cancelAlgorithm(reason) { - TransformStreamErrorWritableAndUnblockWrite(stream, reason); - return promiseResolvedWith(undefined); - } - stream._readable = CreateReadableStream(startAlgorithm, pullAlgorithm, cancelAlgorithm, readableHighWaterMark, readableSizeAlgorithm); - // The [[backpressure]] slot is set to undefined so that it can be initialised by TransformStreamSetBackpressure. - stream._backpressure = undefined; - stream._backpressureChangePromise = undefined; - stream._backpressureChangePromise_resolve = undefined; - TransformStreamSetBackpressure(stream, true); - stream._transformStreamController = undefined; - } - function IsTransformStream(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_transformStreamController')) { - return false; - } - return true; - } - // This is a no-op if both sides are already errored. - function TransformStreamError(stream, e) { - ReadableStreamDefaultControllerError(stream._readable._readableStreamController, e); - TransformStreamErrorWritableAndUnblockWrite(stream, e); - } - function TransformStreamErrorWritableAndUnblockWrite(stream, e) { - TransformStreamDefaultControllerClearAlgorithms(stream._transformStreamController); - WritableStreamDefaultControllerErrorIfNeeded(stream._writable._writableStreamController, e); - if (stream._backpressure) { - // Pretend that pull() was called to permit any pending write() calls to complete. TransformStreamSetBackpressure() - // cannot be called from enqueue() or pull() once the ReadableStream is errored, so this will will be the final time - // _backpressure is set. - TransformStreamSetBackpressure(stream, false); - } - } - function TransformStreamSetBackpressure(stream, backpressure) { - // Passes also when called during construction. - if (stream._backpressureChangePromise !== undefined) { - stream._backpressureChangePromise_resolve(); - } - stream._backpressureChangePromise = newPromise(resolve => { - stream._backpressureChangePromise_resolve = resolve; - }); - stream._backpressure = backpressure; - } - // Class TransformStreamDefaultController - /** - * Allows control of the {@link ReadableStream} and {@link WritableStream} of the associated {@link TransformStream}. - * - * @public - */ - class TransformStreamDefaultController { - constructor() { - throw new TypeError('Illegal constructor'); - } - /** - * Returns the desired size to fill the readable side’s internal queue. It can be negative, if the queue is over-full. - */ - get desiredSize() { - if (!IsTransformStreamDefaultController(this)) { - throw defaultControllerBrandCheckException('desiredSize'); - } - const readableController = this._controlledTransformStream._readable._readableStreamController; - return ReadableStreamDefaultControllerGetDesiredSize(readableController); - } - enqueue(chunk = undefined) { - if (!IsTransformStreamDefaultController(this)) { - throw defaultControllerBrandCheckException('enqueue'); - } - TransformStreamDefaultControllerEnqueue(this, chunk); - } - /** - * Errors both the readable side and the writable side of the controlled transform stream, making all future - * interactions with it fail with the given error `e`. Any chunks queued for transformation will be discarded. - */ - error(reason = undefined) { - if (!IsTransformStreamDefaultController(this)) { - throw defaultControllerBrandCheckException('error'); - } - TransformStreamDefaultControllerError(this, reason); - } - /** - * Closes the readable side and errors the writable side of the controlled transform stream. This is useful when the - * transformer only needs to consume a portion of the chunks written to the writable side. - */ - terminate() { - if (!IsTransformStreamDefaultController(this)) { - throw defaultControllerBrandCheckException('terminate'); - } - TransformStreamDefaultControllerTerminate(this); - } - } - Object.defineProperties(TransformStreamDefaultController.prototype, { - enqueue: { enumerable: true }, - error: { enumerable: true }, - terminate: { enumerable: true }, - desiredSize: { enumerable: true } - }); - if (typeof SymbolPolyfill.toStringTag === 'symbol') { - Object.defineProperty(TransformStreamDefaultController.prototype, SymbolPolyfill.toStringTag, { - value: 'TransformStreamDefaultController', - configurable: true - }); - } - // Transform Stream Default Controller Abstract Operations - function IsTransformStreamDefaultController(x) { - if (!typeIsObject(x)) { - return false; - } - if (!Object.prototype.hasOwnProperty.call(x, '_controlledTransformStream')) { - return false; - } - return true; - } - function SetUpTransformStreamDefaultController(stream, controller, transformAlgorithm, flushAlgorithm) { - controller._controlledTransformStream = stream; - stream._transformStreamController = controller; - controller._transformAlgorithm = transformAlgorithm; - controller._flushAlgorithm = flushAlgorithm; - } - function SetUpTransformStreamDefaultControllerFromTransformer(stream, transformer) { - const controller = Object.create(TransformStreamDefaultController.prototype); - let transformAlgorithm = (chunk) => { - try { - TransformStreamDefaultControllerEnqueue(controller, chunk); - return promiseResolvedWith(undefined); - } - catch (transformResultE) { - return promiseRejectedWith(transformResultE); - } - }; - let flushAlgorithm = () => promiseResolvedWith(undefined); - if (transformer.transform !== undefined) { - transformAlgorithm = chunk => transformer.transform(chunk, controller); - } - if (transformer.flush !== undefined) { - flushAlgorithm = () => transformer.flush(controller); - } - SetUpTransformStreamDefaultController(stream, controller, transformAlgorithm, flushAlgorithm); - } - function TransformStreamDefaultControllerClearAlgorithms(controller) { - controller._transformAlgorithm = undefined; - controller._flushAlgorithm = undefined; - } - function TransformStreamDefaultControllerEnqueue(controller, chunk) { - const stream = controller._controlledTransformStream; - const readableController = stream._readable._readableStreamController; - if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(readableController)) { - throw new TypeError('Readable side is not in a state that permits enqueue'); - } - // We throttle transform invocations based on the backpressure of the ReadableStream, but we still - // accept TransformStreamDefaultControllerEnqueue() calls. - try { - ReadableStreamDefaultControllerEnqueue(readableController, chunk); - } - catch (e) { - // This happens when readableStrategy.size() throws. - TransformStreamErrorWritableAndUnblockWrite(stream, e); - throw stream._readable._storedError; - } - const backpressure = ReadableStreamDefaultControllerHasBackpressure(readableController); - if (backpressure !== stream._backpressure) { - TransformStreamSetBackpressure(stream, true); - } - } - function TransformStreamDefaultControllerError(controller, e) { - TransformStreamError(controller._controlledTransformStream, e); - } - function TransformStreamDefaultControllerPerformTransform(controller, chunk) { - const transformPromise = controller._transformAlgorithm(chunk); - return transformPromiseWith(transformPromise, undefined, r => { - TransformStreamError(controller._controlledTransformStream, r); - throw r; - }); - } - function TransformStreamDefaultControllerTerminate(controller) { - const stream = controller._controlledTransformStream; - const readableController = stream._readable._readableStreamController; - ReadableStreamDefaultControllerClose(readableController); - const error = new TypeError('TransformStream terminated'); - TransformStreamErrorWritableAndUnblockWrite(stream, error); - } - // TransformStreamDefaultSink Algorithms - function TransformStreamDefaultSinkWriteAlgorithm(stream, chunk) { - const controller = stream._transformStreamController; - if (stream._backpressure) { - const backpressureChangePromise = stream._backpressureChangePromise; - return transformPromiseWith(backpressureChangePromise, () => { - const writable = stream._writable; - const state = writable._state; - if (state === 'erroring') { - throw writable._storedError; - } - return TransformStreamDefaultControllerPerformTransform(controller, chunk); - }); - } - return TransformStreamDefaultControllerPerformTransform(controller, chunk); - } - function TransformStreamDefaultSinkAbortAlgorithm(stream, reason) { - // abort() is not called synchronously, so it is possible for abort() to be called when the stream is already - // errored. - TransformStreamError(stream, reason); - return promiseResolvedWith(undefined); - } - function TransformStreamDefaultSinkCloseAlgorithm(stream) { - // stream._readable cannot change after construction, so caching it across a call to user code is safe. - const readable = stream._readable; - const controller = stream._transformStreamController; - const flushPromise = controller._flushAlgorithm(); - TransformStreamDefaultControllerClearAlgorithms(controller); - // Return a promise that is fulfilled with undefined on success. - return transformPromiseWith(flushPromise, () => { - if (readable._state === 'errored') { - throw readable._storedError; - } - ReadableStreamDefaultControllerClose(readable._readableStreamController); - }, r => { - TransformStreamError(stream, r); - throw readable._storedError; - }); - } - // TransformStreamDefaultSource Algorithms - function TransformStreamDefaultSourcePullAlgorithm(stream) { - // Invariant. Enforced by the promises returned by start() and pull(). - TransformStreamSetBackpressure(stream, false); - // Prevent the next pull() call until there is backpressure. - return stream._backpressureChangePromise; - } - // Helper functions for the TransformStreamDefaultController. - function defaultControllerBrandCheckException(name) { - return new TypeError(`TransformStreamDefaultController.prototype.${name} can only be used on a TransformStreamDefaultController`); - } - // Helper functions for the TransformStream. - function streamBrandCheckException(name) { - return new TypeError(`TransformStream.prototype.${name} can only be used on a TransformStream`); - } - - var ponyfill_es6 = /*#__PURE__*/Object.freeze({ - __proto__: null, - ByteLengthQueuingStrategy: ByteLengthQueuingStrategy, - CountQueuingStrategy: CountQueuingStrategy, - ReadableByteStreamController: ReadableByteStreamController, - ReadableStream: ReadableStream$1, - ReadableStreamBYOBReader: ReadableStreamBYOBReader, - ReadableStreamBYOBRequest: ReadableStreamBYOBRequest, - ReadableStreamDefaultController: ReadableStreamDefaultController, - ReadableStreamDefaultReader: ReadableStreamDefaultReader, - TransformStream: TransformStream$1, - TransformStreamDefaultController: TransformStreamDefaultController, - WritableStream: WritableStream$1, - WritableStreamDefaultController: WritableStreamDefaultController, - WritableStreamDefaultWriter: WritableStreamDefaultWriter - }); - - /*! ***************************************************************************** - Copyright (c) Microsoft Corporation. - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. - ***************************************************************************** */ - /* global Reflect, Promise */ - - var extendStatics = function(d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - - function __extends(d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - } - - function assert$1(test) { - if (!test) { - throw new TypeError('Assertion failed'); - } - } - - function noop$1() { - return; - } - function typeIsObject$1(x) { - return (typeof x === 'object' && x !== null) || typeof x === 'function'; - } - - function isStreamConstructor(ctor) { - if (typeof ctor !== 'function') { - return false; - } - var startCalled = false; - try { - new ctor({ - start: function () { - startCalled = true; - } - }); - } - catch (e) { - // ignore - } - return startCalled; - } - function isReadableStream(readable) { - if (!typeIsObject$1(readable)) { - return false; - } - if (typeof readable.getReader !== 'function') { - return false; - } - return true; - } - function isReadableStreamConstructor(ctor) { - if (!isStreamConstructor(ctor)) { - return false; - } - if (!isReadableStream(new ctor())) { - return false; - } - return true; - } - function isWritableStream(writable) { - if (!typeIsObject$1(writable)) { - return false; - } - if (typeof writable.getWriter !== 'function') { - return false; - } - return true; - } - function isWritableStreamConstructor(ctor) { - if (!isStreamConstructor(ctor)) { - return false; - } - if (!isWritableStream(new ctor())) { - return false; - } - return true; - } - function isTransformStream(transform) { - if (!typeIsObject$1(transform)) { - return false; - } - if (!isReadableStream(transform.readable)) { - return false; - } - if (!isWritableStream(transform.writable)) { - return false; - } - return true; - } - function isTransformStreamConstructor(ctor) { - if (!isStreamConstructor(ctor)) { - return false; - } - if (!isTransformStream(new ctor())) { - return false; - } - return true; - } - function supportsByobReader(readable) { - try { - var reader = readable.getReader({ mode: 'byob' }); - reader.releaseLock(); - return true; - } - catch (_a) { - return false; - } - } - function supportsByteSource(ctor) { - try { - new ctor({ type: 'bytes' }); - return true; - } - catch (_a) { - return false; - } - } - - function createReadableStreamWrapper(ctor) { - assert$1(isReadableStreamConstructor(ctor)); - var byteSourceSupported = supportsByteSource(ctor); - return function (readable, _a) { - var _b = _a === void 0 ? {} : _a, type = _b.type; - type = parseReadableType(type); - if (type === 'bytes' && !byteSourceSupported) { - type = undefined; - } - if (readable.constructor === ctor) { - if (type !== 'bytes' || supportsByobReader(readable)) { - return readable; - } - } - if (type === 'bytes') { - var source = createWrappingReadableSource(readable, { type: type }); - return new ctor(source); - } - else { - var source = createWrappingReadableSource(readable); - return new ctor(source); - } - }; - } - function createWrappingReadableSource(readable, _a) { - var _b = _a === void 0 ? {} : _a, type = _b.type; - assert$1(isReadableStream(readable)); - assert$1(readable.locked === false); - type = parseReadableType(type); - var source; - if (type === 'bytes') { - source = new WrappingReadableByteStreamSource(readable); - } - else { - source = new WrappingReadableStreamDefaultSource(readable); - } - return source; - } - function parseReadableType(type) { - var typeString = String(type); - if (typeString === 'bytes') { - return typeString; - } - else if (type === undefined) { - return type; - } - else { - throw new RangeError('Invalid type is specified'); - } - } - var AbstractWrappingReadableStreamSource = /** @class */ (function () { - function AbstractWrappingReadableStreamSource(underlyingStream) { - this._underlyingReader = undefined; - this._readerMode = undefined; - this._readableStreamController = undefined; - this._pendingRead = undefined; - this._underlyingStream = underlyingStream; - // always keep a reader attached to detect close/error - this._attachDefaultReader(); - } - AbstractWrappingReadableStreamSource.prototype.start = function (controller) { - this._readableStreamController = controller; - }; - AbstractWrappingReadableStreamSource.prototype.cancel = function (reason) { - assert$1(this._underlyingReader !== undefined); - return this._underlyingReader.cancel(reason); - }; - AbstractWrappingReadableStreamSource.prototype._attachDefaultReader = function () { - if (this._readerMode === "default" /* DEFAULT */) { - return; - } - this._detachReader(); - var reader = this._underlyingStream.getReader(); - this._readerMode = "default" /* DEFAULT */; - this._attachReader(reader); - }; - AbstractWrappingReadableStreamSource.prototype._attachReader = function (reader) { - var _this = this; - assert$1(this._underlyingReader === undefined); - this._underlyingReader = reader; - var closed = this._underlyingReader.closed; - if (!closed) { - return; - } - closed - .then(function () { return _this._finishPendingRead(); }) - .then(function () { - if (reader === _this._underlyingReader) { - _this._readableStreamController.close(); - } - }, function (reason) { - if (reader === _this._underlyingReader) { - _this._readableStreamController.error(reason); - } - }) - .catch(noop$1); - }; - AbstractWrappingReadableStreamSource.prototype._detachReader = function () { - if (this._underlyingReader === undefined) { - return; - } - this._underlyingReader.releaseLock(); - this._underlyingReader = undefined; - this._readerMode = undefined; - }; - AbstractWrappingReadableStreamSource.prototype._pullWithDefaultReader = function () { - var _this = this; - this._attachDefaultReader(); - // TODO Backpressure? - var read = this._underlyingReader.read() - .then(function (result) { - var controller = _this._readableStreamController; - if (result.done) { - _this._tryClose(); - } - else { - controller.enqueue(result.value); - } - }); - this._setPendingRead(read); - return read; - }; - AbstractWrappingReadableStreamSource.prototype._tryClose = function () { - try { - this._readableStreamController.close(); - } - catch (_a) { - // already errored or closed - } - }; - AbstractWrappingReadableStreamSource.prototype._setPendingRead = function (readPromise) { - var _this = this; - var pendingRead; - var finishRead = function () { - if (_this._pendingRead === pendingRead) { - _this._pendingRead = undefined; - } - }; - this._pendingRead = pendingRead = readPromise.then(finishRead, finishRead); - }; - AbstractWrappingReadableStreamSource.prototype._finishPendingRead = function () { - var _this = this; - if (!this._pendingRead) { - return undefined; - } - var afterRead = function () { return _this._finishPendingRead(); }; - return this._pendingRead.then(afterRead, afterRead); - }; - return AbstractWrappingReadableStreamSource; - }()); - var WrappingReadableStreamDefaultSource = /** @class */ (function (_super) { - __extends(WrappingReadableStreamDefaultSource, _super); - function WrappingReadableStreamDefaultSource() { - return _super !== null && _super.apply(this, arguments) || this; - } - WrappingReadableStreamDefaultSource.prototype.pull = function () { - return this._pullWithDefaultReader(); - }; - return WrappingReadableStreamDefaultSource; - }(AbstractWrappingReadableStreamSource)); - function toUint8Array(view) { - return new Uint8Array(view.buffer, view.byteOffset, view.byteLength); - } - function copyArrayBufferView(from, to) { - var fromArray = toUint8Array(from); - var toArray = toUint8Array(to); - toArray.set(fromArray, 0); - } - var WrappingReadableByteStreamSource = /** @class */ (function (_super) { - __extends(WrappingReadableByteStreamSource, _super); - function WrappingReadableByteStreamSource(underlyingStream) { - var _this = this; - var supportsByob = supportsByobReader(underlyingStream); - _this = _super.call(this, underlyingStream) || this; - _this._supportsByob = supportsByob; - return _this; - } - Object.defineProperty(WrappingReadableByteStreamSource.prototype, "type", { - get: function () { - return 'bytes'; - }, - enumerable: false, - configurable: true - }); - WrappingReadableByteStreamSource.prototype._attachByobReader = function () { - if (this._readerMode === "byob" /* BYOB */) { - return; - } - assert$1(this._supportsByob); - this._detachReader(); - var reader = this._underlyingStream.getReader({ mode: 'byob' }); - this._readerMode = "byob" /* BYOB */; - this._attachReader(reader); - }; - WrappingReadableByteStreamSource.prototype.pull = function () { - if (this._supportsByob) { - var byobRequest = this._readableStreamController.byobRequest; - if (byobRequest) { - return this._pullWithByobRequest(byobRequest); - } - } - return this._pullWithDefaultReader(); - }; - WrappingReadableByteStreamSource.prototype._pullWithByobRequest = function (byobRequest) { - var _this = this; - this._attachByobReader(); - // reader.read(view) detaches the input view, therefore we cannot pass byobRequest.view directly - // create a separate buffer to read into, then copy that to byobRequest.view - var buffer = new Uint8Array(byobRequest.view.byteLength); - // TODO Backpressure? - var read = this._underlyingReader.read(buffer) - .then(function (result) { - _this._readableStreamController; - if (result.done) { - _this._tryClose(); - byobRequest.respond(0); - } - else { - copyArrayBufferView(result.value, byobRequest.view); - byobRequest.respond(result.value.byteLength); - } - }); - this._setPendingRead(read); - return read; - }; - return WrappingReadableByteStreamSource; - }(AbstractWrappingReadableStreamSource)); - - function createWritableStreamWrapper(ctor) { - assert$1(isWritableStreamConstructor(ctor)); - return function (writable) { - if (writable.constructor === ctor) { - return writable; - } - var sink = createWrappingWritableSink(writable); - return new ctor(sink); - }; - } - function createWrappingWritableSink(writable) { - assert$1(isWritableStream(writable)); - assert$1(writable.locked === false); - var writer = writable.getWriter(); - return new WrappingWritableStreamSink(writer); - } - var WrappingWritableStreamSink = /** @class */ (function () { - function WrappingWritableStreamSink(underlyingWriter) { - var _this = this; - this._writableStreamController = undefined; - this._pendingWrite = undefined; - this._state = "writable" /* WRITABLE */; - this._storedError = undefined; - this._underlyingWriter = underlyingWriter; - this._errorPromise = new Promise(function (resolve, reject) { - _this._errorPromiseReject = reject; - }); - this._errorPromise.catch(noop$1); - } - WrappingWritableStreamSink.prototype.start = function (controller) { - var _this = this; - this._writableStreamController = controller; - this._underlyingWriter.closed - .then(function () { - _this._state = "closed" /* CLOSED */; - }) - .catch(function (reason) { return _this._finishErroring(reason); }); - }; - WrappingWritableStreamSink.prototype.write = function (chunk) { - var _this = this; - var writer = this._underlyingWriter; - // Detect past errors - if (writer.desiredSize === null) { - return writer.ready; - } - var writeRequest = writer.write(chunk); - // Detect future errors - writeRequest.catch(function (reason) { return _this._finishErroring(reason); }); - writer.ready.catch(function (reason) { return _this._startErroring(reason); }); - // Reject write when errored - var write = Promise.race([writeRequest, this._errorPromise]); - this._setPendingWrite(write); - return write; - }; - WrappingWritableStreamSink.prototype.close = function () { - var _this = this; - if (this._pendingWrite === undefined) { - return this._underlyingWriter.close(); - } - return this._finishPendingWrite().then(function () { return _this.close(); }); - }; - WrappingWritableStreamSink.prototype.abort = function (reason) { - if (this._state === "errored" /* ERRORED */) { - return undefined; - } - var writer = this._underlyingWriter; - return writer.abort(reason); - }; - WrappingWritableStreamSink.prototype._setPendingWrite = function (writePromise) { - var _this = this; - var pendingWrite; - var finishWrite = function () { - if (_this._pendingWrite === pendingWrite) { - _this._pendingWrite = undefined; - } - }; - this._pendingWrite = pendingWrite = writePromise.then(finishWrite, finishWrite); - }; - WrappingWritableStreamSink.prototype._finishPendingWrite = function () { - var _this = this; - if (this._pendingWrite === undefined) { - return Promise.resolve(); - } - var afterWrite = function () { return _this._finishPendingWrite(); }; - return this._pendingWrite.then(afterWrite, afterWrite); - }; - WrappingWritableStreamSink.prototype._startErroring = function (reason) { - var _this = this; - if (this._state === "writable" /* WRITABLE */) { - this._state = "erroring" /* ERRORING */; - this._storedError = reason; - var afterWrite = function () { return _this._finishErroring(reason); }; - if (this._pendingWrite === undefined) { - afterWrite(); - } - else { - this._finishPendingWrite().then(afterWrite, afterWrite); - } - this._writableStreamController.error(reason); - } - }; - WrappingWritableStreamSink.prototype._finishErroring = function (reason) { - if (this._state === "writable" /* WRITABLE */) { - this._startErroring(reason); - } - if (this._state === "erroring" /* ERRORING */) { - this._state = "errored" /* ERRORED */; - this._errorPromiseReject(this._storedError); - } - }; - return WrappingWritableStreamSink; - }()); - - function createTransformStreamWrapper(ctor) { - assert$1(isTransformStreamConstructor(ctor)); - return function (transform) { - if (transform.constructor === ctor) { - return transform; - } - var transformer = createWrappingTransformer(transform); - return new ctor(transformer); - }; - } - function createWrappingTransformer(transform) { - assert$1(isTransformStream(transform)); - var readable = transform.readable, writable = transform.writable; - assert$1(readable.locked === false); - assert$1(writable.locked === false); - var reader = readable.getReader(); - var writer; - try { - writer = writable.getWriter(); - } - catch (e) { - reader.releaseLock(); // do not leak reader - throw e; - } - return new WrappingTransformStreamTransformer(reader, writer); - } - var WrappingTransformStreamTransformer = /** @class */ (function () { - function WrappingTransformStreamTransformer(reader, writer) { - var _this = this; - this._transformStreamController = undefined; - this._onRead = function (result) { - if (result.done) { - return; - } - _this._transformStreamController.enqueue(result.value); - return _this._reader.read().then(_this._onRead); - }; - this._onError = function (reason) { - _this._flushReject(reason); - _this._transformStreamController.error(reason); - _this._reader.cancel(reason).catch(noop$1); - _this._writer.abort(reason).catch(noop$1); - }; - this._onTerminate = function () { - _this._flushResolve(); - _this._transformStreamController.terminate(); - var error = new TypeError('TransformStream terminated'); - _this._writer.abort(error).catch(noop$1); - }; - this._reader = reader; - this._writer = writer; - this._flushPromise = new Promise(function (resolve, reject) { - _this._flushResolve = resolve; - _this._flushReject = reject; - }); - } - WrappingTransformStreamTransformer.prototype.start = function (controller) { - this._transformStreamController = controller; - this._reader.read() - .then(this._onRead) - .then(this._onTerminate, this._onError); - var readerClosed = this._reader.closed; - if (readerClosed) { - readerClosed - .then(this._onTerminate, this._onError); - } - }; - WrappingTransformStreamTransformer.prototype.transform = function (chunk) { - return this._writer.write(chunk); - }; - WrappingTransformStreamTransformer.prototype.flush = function () { - var _this = this; - return this._writer.close() - .then(function () { return _this._flushPromise; }); - }; - return WrappingTransformStreamTransformer; - }()); - - var webStreamsAdapter = /*#__PURE__*/Object.freeze({ - __proto__: null, - createReadableStreamWrapper: createReadableStreamWrapper, - createTransformStreamWrapper: createTransformStreamWrapper, - createWrappingReadableSource: createWrappingReadableSource, - createWrappingTransformer: createWrappingTransformer, - createWrappingWritableSink: createWrappingWritableSink, - createWritableStreamWrapper: createWritableStreamWrapper - }); - - var bn = createCommonjsModule(function (module) { - (function (module, exports) { - - // Utils - function assert (val, msg) { - if (!val) throw new Error(msg || 'Assertion failed'); - } - - // Could use `inherits` module, but don't want to move from single file - // architecture yet. - function inherits (ctor, superCtor) { - ctor.super_ = superCtor; - var TempCtor = function () {}; - TempCtor.prototype = superCtor.prototype; - ctor.prototype = new TempCtor(); - ctor.prototype.constructor = ctor; - } - - // BN - - function BN (number, base, endian) { - if (BN.isBN(number)) { - return number; - } - - this.negative = 0; - this.words = null; - this.length = 0; - - // Reduction context - this.red = null; - - if (number !== null) { - if (base === 'le' || base === 'be') { - endian = base; - base = 10; - } - - this._init(number || 0, base || 10, endian || 'be'); - } - } - if (typeof module === 'object') { - module.exports = BN; - } else { - exports.BN = BN; - } - - BN.BN = BN; - BN.wordSize = 26; - - var Buffer; - try { - Buffer = void('buffer').Buffer; - } catch (e) { - } - - BN.isBN = function isBN (num) { - if (num instanceof BN) { - return true; - } - - return num !== null && typeof num === 'object' && - num.constructor.wordSize === BN.wordSize && Array.isArray(num.words); - }; - - BN.max = function max (left, right) { - if (left.cmp(right) > 0) return left; - return right; - }; - - BN.min = function min (left, right) { - if (left.cmp(right) < 0) return left; - return right; - }; - - BN.prototype._init = function init (number, base, endian) { - if (typeof number === 'number') { - return this._initNumber(number, base, endian); - } - - if (typeof number === 'object') { - return this._initArray(number, base, endian); - } - - if (base === 'hex') { - base = 16; - } - assert(base === (base | 0) && base >= 2 && base <= 36); - - number = number.toString().replace(/\s+/g, ''); - var start = 0; - if (number[0] === '-') { - start++; - } - - if (base === 16) { - this._parseHex(number, start); - } else { - this._parseBase(number, base, start); - } - - if (number[0] === '-') { - this.negative = 1; - } - - this.strip(); - - if (endian !== 'le') return; - - this._initArray(this.toArray(), base, endian); - }; - - BN.prototype._initNumber = function _initNumber (number, base, endian) { - if (number < 0) { - this.negative = 1; - number = -number; - } - if (number < 0x4000000) { - this.words = [ number & 0x3ffffff ]; - this.length = 1; - } else if (number < 0x10000000000000) { - this.words = [ - number & 0x3ffffff, - (number / 0x4000000) & 0x3ffffff - ]; - this.length = 2; - } else { - assert(number < 0x20000000000000); // 2 ^ 53 (unsafe) - this.words = [ - number & 0x3ffffff, - (number / 0x4000000) & 0x3ffffff, - 1 - ]; - this.length = 3; - } - - if (endian !== 'le') return; - - // Reverse the bytes - this._initArray(this.toArray(), base, endian); - }; - - BN.prototype._initArray = function _initArray (number, base, endian) { - // Perhaps a Uint8Array - assert(typeof number.length === 'number'); - if (number.length <= 0) { - this.words = [ 0 ]; - this.length = 1; - return this; - } - - this.length = Math.ceil(number.length / 3); - this.words = new Array(this.length); - for (var i = 0; i < this.length; i++) { - this.words[i] = 0; - } - - var j, w; - var off = 0; - if (endian === 'be') { - for (i = number.length - 1, j = 0; i >= 0; i -= 3) { - w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16); - this.words[j] |= (w << off) & 0x3ffffff; - this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; - off += 24; - if (off >= 26) { - off -= 26; - j++; - } - } - } else if (endian === 'le') { - for (i = 0, j = 0; i < number.length; i += 3) { - w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16); - this.words[j] |= (w << off) & 0x3ffffff; - this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; - off += 24; - if (off >= 26) { - off -= 26; - j++; - } - } - } - return this.strip(); - }; - - function parseHex (str, start, end) { - var r = 0; - var len = Math.min(str.length, end); - for (var i = start; i < len; i++) { - var c = str.charCodeAt(i) - 48; - - r <<= 4; - - // 'a' - 'f' - if (c >= 49 && c <= 54) { - r |= c - 49 + 0xa; - - // 'A' - 'F' - } else if (c >= 17 && c <= 22) { - r |= c - 17 + 0xa; - - // '0' - '9' - } else { - r |= c & 0xf; - } - } - return r; - } - - BN.prototype._parseHex = function _parseHex (number, start) { - // Create possibly bigger array to ensure that it fits the number - this.length = Math.ceil((number.length - start) / 6); - this.words = new Array(this.length); - for (var i = 0; i < this.length; i++) { - this.words[i] = 0; - } - - var j, w; - // Scan 24-bit chunks and add them to the number - var off = 0; - for (i = number.length - 6, j = 0; i >= start; i -= 6) { - w = parseHex(number, i, i + 6); - this.words[j] |= (w << off) & 0x3ffffff; - // NOTE: `0x3fffff` is intentional here, 26bits max shift + 24bit hex limb - this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; - off += 24; - if (off >= 26) { - off -= 26; - j++; - } - } - if (i + 6 !== start) { - w = parseHex(number, start, i + 6); - this.words[j] |= (w << off) & 0x3ffffff; - this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; - } - this.strip(); - }; - - function parseBase (str, start, end, mul) { - var r = 0; - var len = Math.min(str.length, end); - for (var i = start; i < len; i++) { - var c = str.charCodeAt(i) - 48; - - r *= mul; - - // 'a' - if (c >= 49) { - r += c - 49 + 0xa; - - // 'A' - } else if (c >= 17) { - r += c - 17 + 0xa; - - // '0' - '9' - } else { - r += c; - } - } - return r; - } - - BN.prototype._parseBase = function _parseBase (number, base, start) { - // Initialize as zero - this.words = [ 0 ]; - this.length = 1; - - // Find length of limb in base - for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) { - limbLen++; - } - limbLen--; - limbPow = (limbPow / base) | 0; - - var total = number.length - start; - var mod = total % limbLen; - var end = Math.min(total, total - mod) + start; - - var word = 0; - for (var i = start; i < end; i += limbLen) { - word = parseBase(number, i, i + limbLen, base); - - this.imuln(limbPow); - if (this.words[0] + word < 0x4000000) { - this.words[0] += word; - } else { - this._iaddn(word); - } - } - - if (mod !== 0) { - var pow = 1; - word = parseBase(number, i, number.length, base); - - for (i = 0; i < mod; i++) { - pow *= base; - } - - this.imuln(pow); - if (this.words[0] + word < 0x4000000) { - this.words[0] += word; - } else { - this._iaddn(word); - } - } - }; - - BN.prototype.copy = function copy (dest) { - dest.words = new Array(this.length); - for (var i = 0; i < this.length; i++) { - dest.words[i] = this.words[i]; - } - dest.length = this.length; - dest.negative = this.negative; - dest.red = this.red; - }; - - BN.prototype.clone = function clone () { - var r = new BN(null); - this.copy(r); - return r; - }; - - BN.prototype._expand = function _expand (size) { - while (this.length < size) { - this.words[this.length++] = 0; - } - return this; - }; - - // Remove leading `0` from `this` - BN.prototype.strip = function strip () { - while (this.length > 1 && this.words[this.length - 1] === 0) { - this.length--; - } - return this._normSign(); - }; - - BN.prototype._normSign = function _normSign () { - // -0 = 0 - if (this.length === 1 && this.words[0] === 0) { - this.negative = 0; - } - return this; - }; - - BN.prototype.inspect = function inspect () { - return (this.red ? ''; - }; - - /* - - var zeros = []; - var groupSizes = []; - var groupBases = []; - - var s = ''; - var i = -1; - while (++i < BN.wordSize) { - zeros[i] = s; - s += '0'; - } - groupSizes[0] = 0; - groupSizes[1] = 0; - groupBases[0] = 0; - groupBases[1] = 0; - var base = 2 - 1; - while (++base < 36 + 1) { - var groupSize = 0; - var groupBase = 1; - while (groupBase < (1 << BN.wordSize) / base) { - groupBase *= base; - groupSize += 1; - } - groupSizes[base] = groupSize; - groupBases[base] = groupBase; - } - - */ - - var zeros = [ - '', - '0', - '00', - '000', - '0000', - '00000', - '000000', - '0000000', - '00000000', - '000000000', - '0000000000', - '00000000000', - '000000000000', - '0000000000000', - '00000000000000', - '000000000000000', - '0000000000000000', - '00000000000000000', - '000000000000000000', - '0000000000000000000', - '00000000000000000000', - '000000000000000000000', - '0000000000000000000000', - '00000000000000000000000', - '000000000000000000000000', - '0000000000000000000000000' - ]; - - var groupSizes = [ - 0, 0, - 25, 16, 12, 11, 10, 9, 8, - 8, 7, 7, 7, 7, 6, 6, - 6, 6, 6, 6, 6, 5, 5, - 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5 - ]; - - var groupBases = [ - 0, 0, - 33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216, - 43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625, - 16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632, - 6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149, - 24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176 - ]; - - BN.prototype.toString = function toString (base, padding) { - base = base || 10; - padding = padding | 0 || 1; - - var out; - if (base === 16 || base === 'hex') { - out = ''; - var off = 0; - var carry = 0; - for (var i = 0; i < this.length; i++) { - var w = this.words[i]; - var word = (((w << off) | carry) & 0xffffff).toString(16); - carry = (w >>> (24 - off)) & 0xffffff; - if (carry !== 0 || i !== this.length - 1) { - out = zeros[6 - word.length] + word + out; - } else { - out = word + out; - } - off += 2; - if (off >= 26) { - off -= 26; - i--; - } - } - if (carry !== 0) { - out = carry.toString(16) + out; - } - while (out.length % padding !== 0) { - out = '0' + out; - } - if (this.negative !== 0) { - out = '-' + out; - } - return out; - } - - if (base === (base | 0) && base >= 2 && base <= 36) { - // var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base)); - var groupSize = groupSizes[base]; - // var groupBase = Math.pow(base, groupSize); - var groupBase = groupBases[base]; - out = ''; - var c = this.clone(); - c.negative = 0; - while (!c.isZero()) { - var r = c.modn(groupBase).toString(base); - c = c.idivn(groupBase); - - if (!c.isZero()) { - out = zeros[groupSize - r.length] + r + out; - } else { - out = r + out; - } - } - if (this.isZero()) { - out = '0' + out; - } - while (out.length % padding !== 0) { - out = '0' + out; - } - if (this.negative !== 0) { - out = '-' + out; - } - return out; - } - - assert(false, 'Base should be between 2 and 36'); - }; - - BN.prototype.toNumber = function toNumber () { - var ret = this.words[0]; - if (this.length === 2) { - ret += this.words[1] * 0x4000000; - } else if (this.length === 3 && this.words[2] === 0x01) { - // NOTE: at this stage it is known that the top bit is set - ret += 0x10000000000000 + (this.words[1] * 0x4000000); - } else if (this.length > 2) { - assert(false, 'Number can only safely store up to 53 bits'); - } - return (this.negative !== 0) ? -ret : ret; - }; - - BN.prototype.toJSON = function toJSON () { - return this.toString(16); - }; - - BN.prototype.toBuffer = function toBuffer (endian, length) { - assert(typeof Buffer !== 'undefined'); - return this.toArrayLike(Buffer, endian, length); - }; - - BN.prototype.toArray = function toArray (endian, length) { - return this.toArrayLike(Array, endian, length); - }; - - BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) { - var byteLength = this.byteLength(); - var reqLength = length || Math.max(1, byteLength); - assert(byteLength <= reqLength, 'byte array longer than desired length'); - assert(reqLength > 0, 'Requested array length <= 0'); - - this.strip(); - var littleEndian = endian === 'le'; - var res = new ArrayType(reqLength); - - var b, i; - var q = this.clone(); - if (!littleEndian) { - // Assume big-endian - for (i = 0; i < reqLength - byteLength; i++) { - res[i] = 0; - } - - for (i = 0; !q.isZero(); i++) { - b = q.andln(0xff); - q.iushrn(8); - - res[reqLength - i - 1] = b; - } - } else { - for (i = 0; !q.isZero(); i++) { - b = q.andln(0xff); - q.iushrn(8); - - res[i] = b; - } - - for (; i < reqLength; i++) { - res[i] = 0; - } - } - - return res; - }; - - if (Math.clz32) { - BN.prototype._countBits = function _countBits (w) { - return 32 - Math.clz32(w); - }; - } else { - BN.prototype._countBits = function _countBits (w) { - var t = w; - var r = 0; - if (t >= 0x1000) { - r += 13; - t >>>= 13; - } - if (t >= 0x40) { - r += 7; - t >>>= 7; - } - if (t >= 0x8) { - r += 4; - t >>>= 4; - } - if (t >= 0x02) { - r += 2; - t >>>= 2; - } - return r + t; - }; - } - - BN.prototype._zeroBits = function _zeroBits (w) { - // Short-cut - if (w === 0) return 26; - - var t = w; - var r = 0; - if ((t & 0x1fff) === 0) { - r += 13; - t >>>= 13; - } - if ((t & 0x7f) === 0) { - r += 7; - t >>>= 7; - } - if ((t & 0xf) === 0) { - r += 4; - t >>>= 4; - } - if ((t & 0x3) === 0) { - r += 2; - t >>>= 2; - } - if ((t & 0x1) === 0) { - r++; - } - return r; - }; - - // Return number of used bits in a BN - BN.prototype.bitLength = function bitLength () { - var w = this.words[this.length - 1]; - var hi = this._countBits(w); - return (this.length - 1) * 26 + hi; - }; - - function toBitArray (num) { - var w = new Array(num.bitLength()); - - for (var bit = 0; bit < w.length; bit++) { - var off = (bit / 26) | 0; - var wbit = bit % 26; - - w[bit] = (num.words[off] & (1 << wbit)) >>> wbit; - } - - return w; - } - - // Number of trailing zero bits - BN.prototype.zeroBits = function zeroBits () { - if (this.isZero()) return 0; - - var r = 0; - for (var i = 0; i < this.length; i++) { - var b = this._zeroBits(this.words[i]); - r += b; - if (b !== 26) break; - } - return r; - }; - - BN.prototype.byteLength = function byteLength () { - return Math.ceil(this.bitLength() / 8); - }; - - BN.prototype.toTwos = function toTwos (width) { - if (this.negative !== 0) { - return this.abs().inotn(width).iaddn(1); - } - return this.clone(); - }; - - BN.prototype.fromTwos = function fromTwos (width) { - if (this.testn(width - 1)) { - return this.notn(width).iaddn(1).ineg(); - } - return this.clone(); - }; - - BN.prototype.isNeg = function isNeg () { - return this.negative !== 0; - }; - - // Return negative clone of `this` - BN.prototype.neg = function neg () { - return this.clone().ineg(); - }; - - BN.prototype.ineg = function ineg () { - if (!this.isZero()) { - this.negative ^= 1; - } - - return this; - }; - - // Or `num` with `this` in-place - BN.prototype.iuor = function iuor (num) { - while (this.length < num.length) { - this.words[this.length++] = 0; - } - - for (var i = 0; i < num.length; i++) { - this.words[i] = this.words[i] | num.words[i]; - } - - return this.strip(); - }; - - BN.prototype.ior = function ior (num) { - assert((this.negative | num.negative) === 0); - return this.iuor(num); - }; - - // Or `num` with `this` - BN.prototype.or = function or (num) { - if (this.length > num.length) return this.clone().ior(num); - return num.clone().ior(this); - }; - - BN.prototype.uor = function uor (num) { - if (this.length > num.length) return this.clone().iuor(num); - return num.clone().iuor(this); - }; - - // And `num` with `this` in-place - BN.prototype.iuand = function iuand (num) { - // b = min-length(num, this) - var b; - if (this.length > num.length) { - b = num; - } else { - b = this; - } - - for (var i = 0; i < b.length; i++) { - this.words[i] = this.words[i] & num.words[i]; - } - - this.length = b.length; - - return this.strip(); - }; - - BN.prototype.iand = function iand (num) { - assert((this.negative | num.negative) === 0); - return this.iuand(num); - }; - - // And `num` with `this` - BN.prototype.and = function and (num) { - if (this.length > num.length) return this.clone().iand(num); - return num.clone().iand(this); - }; - - BN.prototype.uand = function uand (num) { - if (this.length > num.length) return this.clone().iuand(num); - return num.clone().iuand(this); - }; - - // Xor `num` with `this` in-place - BN.prototype.iuxor = function iuxor (num) { - // a.length > b.length - var a; - var b; - if (this.length > num.length) { - a = this; - b = num; - } else { - a = num; - b = this; - } - - for (var i = 0; i < b.length; i++) { - this.words[i] = a.words[i] ^ b.words[i]; - } - - if (this !== a) { - for (; i < a.length; i++) { - this.words[i] = a.words[i]; - } - } - - this.length = a.length; - - return this.strip(); - }; - - BN.prototype.ixor = function ixor (num) { - assert((this.negative | num.negative) === 0); - return this.iuxor(num); - }; - - // Xor `num` with `this` - BN.prototype.xor = function xor (num) { - if (this.length > num.length) return this.clone().ixor(num); - return num.clone().ixor(this); - }; - - BN.prototype.uxor = function uxor (num) { - if (this.length > num.length) return this.clone().iuxor(num); - return num.clone().iuxor(this); - }; - - // Not ``this`` with ``width`` bitwidth - BN.prototype.inotn = function inotn (width) { - assert(typeof width === 'number' && width >= 0); - - var bytesNeeded = Math.ceil(width / 26) | 0; - var bitsLeft = width % 26; - - // Extend the buffer with leading zeroes - this._expand(bytesNeeded); - - if (bitsLeft > 0) { - bytesNeeded--; - } - - // Handle complete words - for (var i = 0; i < bytesNeeded; i++) { - this.words[i] = ~this.words[i] & 0x3ffffff; - } - - // Handle the residue - if (bitsLeft > 0) { - this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft)); - } - - // And remove leading zeroes - return this.strip(); - }; - - BN.prototype.notn = function notn (width) { - return this.clone().inotn(width); - }; - - // Set `bit` of `this` - BN.prototype.setn = function setn (bit, val) { - assert(typeof bit === 'number' && bit >= 0); - - var off = (bit / 26) | 0; - var wbit = bit % 26; - - this._expand(off + 1); - - if (val) { - this.words[off] = this.words[off] | (1 << wbit); - } else { - this.words[off] = this.words[off] & ~(1 << wbit); - } - - return this.strip(); - }; - - // Add `num` to `this` in-place - BN.prototype.iadd = function iadd (num) { - var r; - - // negative + positive - if (this.negative !== 0 && num.negative === 0) { - this.negative = 0; - r = this.isub(num); - this.negative ^= 1; - return this._normSign(); - - // positive + negative - } else if (this.negative === 0 && num.negative !== 0) { - num.negative = 0; - r = this.isub(num); - num.negative = 1; - return r._normSign(); - } - - // a.length > b.length - var a, b; - if (this.length > num.length) { - a = this; - b = num; - } else { - a = num; - b = this; - } - - var carry = 0; - for (var i = 0; i < b.length; i++) { - r = (a.words[i] | 0) + (b.words[i] | 0) + carry; - this.words[i] = r & 0x3ffffff; - carry = r >>> 26; - } - for (; carry !== 0 && i < a.length; i++) { - r = (a.words[i] | 0) + carry; - this.words[i] = r & 0x3ffffff; - carry = r >>> 26; - } - - this.length = a.length; - if (carry !== 0) { - this.words[this.length] = carry; - this.length++; - // Copy the rest of the words - } else if (a !== this) { - for (; i < a.length; i++) { - this.words[i] = a.words[i]; - } - } - - return this; - }; - - // Add `num` to `this` - BN.prototype.add = function add (num) { - var res; - if (num.negative !== 0 && this.negative === 0) { - num.negative = 0; - res = this.sub(num); - num.negative ^= 1; - return res; - } else if (num.negative === 0 && this.negative !== 0) { - this.negative = 0; - res = num.sub(this); - this.negative = 1; - return res; - } - - if (this.length > num.length) return this.clone().iadd(num); - - return num.clone().iadd(this); - }; - - // Subtract `num` from `this` in-place - BN.prototype.isub = function isub (num) { - // this - (-num) = this + num - if (num.negative !== 0) { - num.negative = 0; - var r = this.iadd(num); - num.negative = 1; - return r._normSign(); - - // -this - num = -(this + num) - } else if (this.negative !== 0) { - this.negative = 0; - this.iadd(num); - this.negative = 1; - return this._normSign(); - } - - // At this point both numbers are positive - var cmp = this.cmp(num); - - // Optimization - zeroify - if (cmp === 0) { - this.negative = 0; - this.length = 1; - this.words[0] = 0; - return this; - } - - // a > b - var a, b; - if (cmp > 0) { - a = this; - b = num; - } else { - a = num; - b = this; - } - - var carry = 0; - for (var i = 0; i < b.length; i++) { - r = (a.words[i] | 0) - (b.words[i] | 0) + carry; - carry = r >> 26; - this.words[i] = r & 0x3ffffff; - } - for (; carry !== 0 && i < a.length; i++) { - r = (a.words[i] | 0) + carry; - carry = r >> 26; - this.words[i] = r & 0x3ffffff; - } - - // Copy rest of the words - if (carry === 0 && i < a.length && a !== this) { - for (; i < a.length; i++) { - this.words[i] = a.words[i]; - } - } - - this.length = Math.max(this.length, i); - - if (a !== this) { - this.negative = 1; - } - - return this.strip(); - }; - - // Subtract `num` from `this` - BN.prototype.sub = function sub (num) { - return this.clone().isub(num); - }; - - function smallMulTo (self, num, out) { - out.negative = num.negative ^ self.negative; - var len = (self.length + num.length) | 0; - out.length = len; - len = (len - 1) | 0; - - // Peel one iteration (compiler can't do it, because of code complexity) - var a = self.words[0] | 0; - var b = num.words[0] | 0; - var r = a * b; - - var lo = r & 0x3ffffff; - var carry = (r / 0x4000000) | 0; - out.words[0] = lo; - - for (var k = 1; k < len; k++) { - // Sum all words with the same `i + j = k` and accumulate `ncarry`, - // note that ncarry could be >= 0x3ffffff - var ncarry = carry >>> 26; - var rword = carry & 0x3ffffff; - var maxJ = Math.min(k, num.length - 1); - for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { - var i = (k - j) | 0; - a = self.words[i] | 0; - b = num.words[j] | 0; - r = a * b + rword; - ncarry += (r / 0x4000000) | 0; - rword = r & 0x3ffffff; - } - out.words[k] = rword | 0; - carry = ncarry | 0; - } - if (carry !== 0) { - out.words[k] = carry | 0; - } else { - out.length--; - } - - return out.strip(); - } - - // TODO(indutny): it may be reasonable to omit it for users who don't need - // to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit - // multiplication (like elliptic secp256k1). - var comb10MulTo = function comb10MulTo (self, num, out) { - var a = self.words; - var b = num.words; - var o = out.words; - var c = 0; - var lo; - var mid; - var hi; - var a0 = a[0] | 0; - var al0 = a0 & 0x1fff; - var ah0 = a0 >>> 13; - var a1 = a[1] | 0; - var al1 = a1 & 0x1fff; - var ah1 = a1 >>> 13; - var a2 = a[2] | 0; - var al2 = a2 & 0x1fff; - var ah2 = a2 >>> 13; - var a3 = a[3] | 0; - var al3 = a3 & 0x1fff; - var ah3 = a3 >>> 13; - var a4 = a[4] | 0; - var al4 = a4 & 0x1fff; - var ah4 = a4 >>> 13; - var a5 = a[5] | 0; - var al5 = a5 & 0x1fff; - var ah5 = a5 >>> 13; - var a6 = a[6] | 0; - var al6 = a6 & 0x1fff; - var ah6 = a6 >>> 13; - var a7 = a[7] | 0; - var al7 = a7 & 0x1fff; - var ah7 = a7 >>> 13; - var a8 = a[8] | 0; - var al8 = a8 & 0x1fff; - var ah8 = a8 >>> 13; - var a9 = a[9] | 0; - var al9 = a9 & 0x1fff; - var ah9 = a9 >>> 13; - var b0 = b[0] | 0; - var bl0 = b0 & 0x1fff; - var bh0 = b0 >>> 13; - var b1 = b[1] | 0; - var bl1 = b1 & 0x1fff; - var bh1 = b1 >>> 13; - var b2 = b[2] | 0; - var bl2 = b2 & 0x1fff; - var bh2 = b2 >>> 13; - var b3 = b[3] | 0; - var bl3 = b3 & 0x1fff; - var bh3 = b3 >>> 13; - var b4 = b[4] | 0; - var bl4 = b4 & 0x1fff; - var bh4 = b4 >>> 13; - var b5 = b[5] | 0; - var bl5 = b5 & 0x1fff; - var bh5 = b5 >>> 13; - var b6 = b[6] | 0; - var bl6 = b6 & 0x1fff; - var bh6 = b6 >>> 13; - var b7 = b[7] | 0; - var bl7 = b7 & 0x1fff; - var bh7 = b7 >>> 13; - var b8 = b[8] | 0; - var bl8 = b8 & 0x1fff; - var bh8 = b8 >>> 13; - var b9 = b[9] | 0; - var bl9 = b9 & 0x1fff; - var bh9 = b9 >>> 13; - - out.negative = self.negative ^ num.negative; - out.length = 19; - /* k = 0 */ - lo = Math.imul(al0, bl0); - mid = Math.imul(al0, bh0); - mid = (mid + Math.imul(ah0, bl0)) | 0; - hi = Math.imul(ah0, bh0); - var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0; - w0 &= 0x3ffffff; - /* k = 1 */ - lo = Math.imul(al1, bl0); - mid = Math.imul(al1, bh0); - mid = (mid + Math.imul(ah1, bl0)) | 0; - hi = Math.imul(ah1, bh0); - lo = (lo + Math.imul(al0, bl1)) | 0; - mid = (mid + Math.imul(al0, bh1)) | 0; - mid = (mid + Math.imul(ah0, bl1)) | 0; - hi = (hi + Math.imul(ah0, bh1)) | 0; - var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0; - w1 &= 0x3ffffff; - /* k = 2 */ - lo = Math.imul(al2, bl0); - mid = Math.imul(al2, bh0); - mid = (mid + Math.imul(ah2, bl0)) | 0; - hi = Math.imul(ah2, bh0); - lo = (lo + Math.imul(al1, bl1)) | 0; - mid = (mid + Math.imul(al1, bh1)) | 0; - mid = (mid + Math.imul(ah1, bl1)) | 0; - hi = (hi + Math.imul(ah1, bh1)) | 0; - lo = (lo + Math.imul(al0, bl2)) | 0; - mid = (mid + Math.imul(al0, bh2)) | 0; - mid = (mid + Math.imul(ah0, bl2)) | 0; - hi = (hi + Math.imul(ah0, bh2)) | 0; - var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0; - w2 &= 0x3ffffff; - /* k = 3 */ - lo = Math.imul(al3, bl0); - mid = Math.imul(al3, bh0); - mid = (mid + Math.imul(ah3, bl0)) | 0; - hi = Math.imul(ah3, bh0); - lo = (lo + Math.imul(al2, bl1)) | 0; - mid = (mid + Math.imul(al2, bh1)) | 0; - mid = (mid + Math.imul(ah2, bl1)) | 0; - hi = (hi + Math.imul(ah2, bh1)) | 0; - lo = (lo + Math.imul(al1, bl2)) | 0; - mid = (mid + Math.imul(al1, bh2)) | 0; - mid = (mid + Math.imul(ah1, bl2)) | 0; - hi = (hi + Math.imul(ah1, bh2)) | 0; - lo = (lo + Math.imul(al0, bl3)) | 0; - mid = (mid + Math.imul(al0, bh3)) | 0; - mid = (mid + Math.imul(ah0, bl3)) | 0; - hi = (hi + Math.imul(ah0, bh3)) | 0; - var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0; - w3 &= 0x3ffffff; - /* k = 4 */ - lo = Math.imul(al4, bl0); - mid = Math.imul(al4, bh0); - mid = (mid + Math.imul(ah4, bl0)) | 0; - hi = Math.imul(ah4, bh0); - lo = (lo + Math.imul(al3, bl1)) | 0; - mid = (mid + Math.imul(al3, bh1)) | 0; - mid = (mid + Math.imul(ah3, bl1)) | 0; - hi = (hi + Math.imul(ah3, bh1)) | 0; - lo = (lo + Math.imul(al2, bl2)) | 0; - mid = (mid + Math.imul(al2, bh2)) | 0; - mid = (mid + Math.imul(ah2, bl2)) | 0; - hi = (hi + Math.imul(ah2, bh2)) | 0; - lo = (lo + Math.imul(al1, bl3)) | 0; - mid = (mid + Math.imul(al1, bh3)) | 0; - mid = (mid + Math.imul(ah1, bl3)) | 0; - hi = (hi + Math.imul(ah1, bh3)) | 0; - lo = (lo + Math.imul(al0, bl4)) | 0; - mid = (mid + Math.imul(al0, bh4)) | 0; - mid = (mid + Math.imul(ah0, bl4)) | 0; - hi = (hi + Math.imul(ah0, bh4)) | 0; - var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0; - w4 &= 0x3ffffff; - /* k = 5 */ - lo = Math.imul(al5, bl0); - mid = Math.imul(al5, bh0); - mid = (mid + Math.imul(ah5, bl0)) | 0; - hi = Math.imul(ah5, bh0); - lo = (lo + Math.imul(al4, bl1)) | 0; - mid = (mid + Math.imul(al4, bh1)) | 0; - mid = (mid + Math.imul(ah4, bl1)) | 0; - hi = (hi + Math.imul(ah4, bh1)) | 0; - lo = (lo + Math.imul(al3, bl2)) | 0; - mid = (mid + Math.imul(al3, bh2)) | 0; - mid = (mid + Math.imul(ah3, bl2)) | 0; - hi = (hi + Math.imul(ah3, bh2)) | 0; - lo = (lo + Math.imul(al2, bl3)) | 0; - mid = (mid + Math.imul(al2, bh3)) | 0; - mid = (mid + Math.imul(ah2, bl3)) | 0; - hi = (hi + Math.imul(ah2, bh3)) | 0; - lo = (lo + Math.imul(al1, bl4)) | 0; - mid = (mid + Math.imul(al1, bh4)) | 0; - mid = (mid + Math.imul(ah1, bl4)) | 0; - hi = (hi + Math.imul(ah1, bh4)) | 0; - lo = (lo + Math.imul(al0, bl5)) | 0; - mid = (mid + Math.imul(al0, bh5)) | 0; - mid = (mid + Math.imul(ah0, bl5)) | 0; - hi = (hi + Math.imul(ah0, bh5)) | 0; - var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0; - w5 &= 0x3ffffff; - /* k = 6 */ - lo = Math.imul(al6, bl0); - mid = Math.imul(al6, bh0); - mid = (mid + Math.imul(ah6, bl0)) | 0; - hi = Math.imul(ah6, bh0); - lo = (lo + Math.imul(al5, bl1)) | 0; - mid = (mid + Math.imul(al5, bh1)) | 0; - mid = (mid + Math.imul(ah5, bl1)) | 0; - hi = (hi + Math.imul(ah5, bh1)) | 0; - lo = (lo + Math.imul(al4, bl2)) | 0; - mid = (mid + Math.imul(al4, bh2)) | 0; - mid = (mid + Math.imul(ah4, bl2)) | 0; - hi = (hi + Math.imul(ah4, bh2)) | 0; - lo = (lo + Math.imul(al3, bl3)) | 0; - mid = (mid + Math.imul(al3, bh3)) | 0; - mid = (mid + Math.imul(ah3, bl3)) | 0; - hi = (hi + Math.imul(ah3, bh3)) | 0; - lo = (lo + Math.imul(al2, bl4)) | 0; - mid = (mid + Math.imul(al2, bh4)) | 0; - mid = (mid + Math.imul(ah2, bl4)) | 0; - hi = (hi + Math.imul(ah2, bh4)) | 0; - lo = (lo + Math.imul(al1, bl5)) | 0; - mid = (mid + Math.imul(al1, bh5)) | 0; - mid = (mid + Math.imul(ah1, bl5)) | 0; - hi = (hi + Math.imul(ah1, bh5)) | 0; - lo = (lo + Math.imul(al0, bl6)) | 0; - mid = (mid + Math.imul(al0, bh6)) | 0; - mid = (mid + Math.imul(ah0, bl6)) | 0; - hi = (hi + Math.imul(ah0, bh6)) | 0; - var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0; - w6 &= 0x3ffffff; - /* k = 7 */ - lo = Math.imul(al7, bl0); - mid = Math.imul(al7, bh0); - mid = (mid + Math.imul(ah7, bl0)) | 0; - hi = Math.imul(ah7, bh0); - lo = (lo + Math.imul(al6, bl1)) | 0; - mid = (mid + Math.imul(al6, bh1)) | 0; - mid = (mid + Math.imul(ah6, bl1)) | 0; - hi = (hi + Math.imul(ah6, bh1)) | 0; - lo = (lo + Math.imul(al5, bl2)) | 0; - mid = (mid + Math.imul(al5, bh2)) | 0; - mid = (mid + Math.imul(ah5, bl2)) | 0; - hi = (hi + Math.imul(ah5, bh2)) | 0; - lo = (lo + Math.imul(al4, bl3)) | 0; - mid = (mid + Math.imul(al4, bh3)) | 0; - mid = (mid + Math.imul(ah4, bl3)) | 0; - hi = (hi + Math.imul(ah4, bh3)) | 0; - lo = (lo + Math.imul(al3, bl4)) | 0; - mid = (mid + Math.imul(al3, bh4)) | 0; - mid = (mid + Math.imul(ah3, bl4)) | 0; - hi = (hi + Math.imul(ah3, bh4)) | 0; - lo = (lo + Math.imul(al2, bl5)) | 0; - mid = (mid + Math.imul(al2, bh5)) | 0; - mid = (mid + Math.imul(ah2, bl5)) | 0; - hi = (hi + Math.imul(ah2, bh5)) | 0; - lo = (lo + Math.imul(al1, bl6)) | 0; - mid = (mid + Math.imul(al1, bh6)) | 0; - mid = (mid + Math.imul(ah1, bl6)) | 0; - hi = (hi + Math.imul(ah1, bh6)) | 0; - lo = (lo + Math.imul(al0, bl7)) | 0; - mid = (mid + Math.imul(al0, bh7)) | 0; - mid = (mid + Math.imul(ah0, bl7)) | 0; - hi = (hi + Math.imul(ah0, bh7)) | 0; - var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0; - w7 &= 0x3ffffff; - /* k = 8 */ - lo = Math.imul(al8, bl0); - mid = Math.imul(al8, bh0); - mid = (mid + Math.imul(ah8, bl0)) | 0; - hi = Math.imul(ah8, bh0); - lo = (lo + Math.imul(al7, bl1)) | 0; - mid = (mid + Math.imul(al7, bh1)) | 0; - mid = (mid + Math.imul(ah7, bl1)) | 0; - hi = (hi + Math.imul(ah7, bh1)) | 0; - lo = (lo + Math.imul(al6, bl2)) | 0; - mid = (mid + Math.imul(al6, bh2)) | 0; - mid = (mid + Math.imul(ah6, bl2)) | 0; - hi = (hi + Math.imul(ah6, bh2)) | 0; - lo = (lo + Math.imul(al5, bl3)) | 0; - mid = (mid + Math.imul(al5, bh3)) | 0; - mid = (mid + Math.imul(ah5, bl3)) | 0; - hi = (hi + Math.imul(ah5, bh3)) | 0; - lo = (lo + Math.imul(al4, bl4)) | 0; - mid = (mid + Math.imul(al4, bh4)) | 0; - mid = (mid + Math.imul(ah4, bl4)) | 0; - hi = (hi + Math.imul(ah4, bh4)) | 0; - lo = (lo + Math.imul(al3, bl5)) | 0; - mid = (mid + Math.imul(al3, bh5)) | 0; - mid = (mid + Math.imul(ah3, bl5)) | 0; - hi = (hi + Math.imul(ah3, bh5)) | 0; - lo = (lo + Math.imul(al2, bl6)) | 0; - mid = (mid + Math.imul(al2, bh6)) | 0; - mid = (mid + Math.imul(ah2, bl6)) | 0; - hi = (hi + Math.imul(ah2, bh6)) | 0; - lo = (lo + Math.imul(al1, bl7)) | 0; - mid = (mid + Math.imul(al1, bh7)) | 0; - mid = (mid + Math.imul(ah1, bl7)) | 0; - hi = (hi + Math.imul(ah1, bh7)) | 0; - lo = (lo + Math.imul(al0, bl8)) | 0; - mid = (mid + Math.imul(al0, bh8)) | 0; - mid = (mid + Math.imul(ah0, bl8)) | 0; - hi = (hi + Math.imul(ah0, bh8)) | 0; - var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0; - w8 &= 0x3ffffff; - /* k = 9 */ - lo = Math.imul(al9, bl0); - mid = Math.imul(al9, bh0); - mid = (mid + Math.imul(ah9, bl0)) | 0; - hi = Math.imul(ah9, bh0); - lo = (lo + Math.imul(al8, bl1)) | 0; - mid = (mid + Math.imul(al8, bh1)) | 0; - mid = (mid + Math.imul(ah8, bl1)) | 0; - hi = (hi + Math.imul(ah8, bh1)) | 0; - lo = (lo + Math.imul(al7, bl2)) | 0; - mid = (mid + Math.imul(al7, bh2)) | 0; - mid = (mid + Math.imul(ah7, bl2)) | 0; - hi = (hi + Math.imul(ah7, bh2)) | 0; - lo = (lo + Math.imul(al6, bl3)) | 0; - mid = (mid + Math.imul(al6, bh3)) | 0; - mid = (mid + Math.imul(ah6, bl3)) | 0; - hi = (hi + Math.imul(ah6, bh3)) | 0; - lo = (lo + Math.imul(al5, bl4)) | 0; - mid = (mid + Math.imul(al5, bh4)) | 0; - mid = (mid + Math.imul(ah5, bl4)) | 0; - hi = (hi + Math.imul(ah5, bh4)) | 0; - lo = (lo + Math.imul(al4, bl5)) | 0; - mid = (mid + Math.imul(al4, bh5)) | 0; - mid = (mid + Math.imul(ah4, bl5)) | 0; - hi = (hi + Math.imul(ah4, bh5)) | 0; - lo = (lo + Math.imul(al3, bl6)) | 0; - mid = (mid + Math.imul(al3, bh6)) | 0; - mid = (mid + Math.imul(ah3, bl6)) | 0; - hi = (hi + Math.imul(ah3, bh6)) | 0; - lo = (lo + Math.imul(al2, bl7)) | 0; - mid = (mid + Math.imul(al2, bh7)) | 0; - mid = (mid + Math.imul(ah2, bl7)) | 0; - hi = (hi + Math.imul(ah2, bh7)) | 0; - lo = (lo + Math.imul(al1, bl8)) | 0; - mid = (mid + Math.imul(al1, bh8)) | 0; - mid = (mid + Math.imul(ah1, bl8)) | 0; - hi = (hi + Math.imul(ah1, bh8)) | 0; - lo = (lo + Math.imul(al0, bl9)) | 0; - mid = (mid + Math.imul(al0, bh9)) | 0; - mid = (mid + Math.imul(ah0, bl9)) | 0; - hi = (hi + Math.imul(ah0, bh9)) | 0; - var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0; - w9 &= 0x3ffffff; - /* k = 10 */ - lo = Math.imul(al9, bl1); - mid = Math.imul(al9, bh1); - mid = (mid + Math.imul(ah9, bl1)) | 0; - hi = Math.imul(ah9, bh1); - lo = (lo + Math.imul(al8, bl2)) | 0; - mid = (mid + Math.imul(al8, bh2)) | 0; - mid = (mid + Math.imul(ah8, bl2)) | 0; - hi = (hi + Math.imul(ah8, bh2)) | 0; - lo = (lo + Math.imul(al7, bl3)) | 0; - mid = (mid + Math.imul(al7, bh3)) | 0; - mid = (mid + Math.imul(ah7, bl3)) | 0; - hi = (hi + Math.imul(ah7, bh3)) | 0; - lo = (lo + Math.imul(al6, bl4)) | 0; - mid = (mid + Math.imul(al6, bh4)) | 0; - mid = (mid + Math.imul(ah6, bl4)) | 0; - hi = (hi + Math.imul(ah6, bh4)) | 0; - lo = (lo + Math.imul(al5, bl5)) | 0; - mid = (mid + Math.imul(al5, bh5)) | 0; - mid = (mid + Math.imul(ah5, bl5)) | 0; - hi = (hi + Math.imul(ah5, bh5)) | 0; - lo = (lo + Math.imul(al4, bl6)) | 0; - mid = (mid + Math.imul(al4, bh6)) | 0; - mid = (mid + Math.imul(ah4, bl6)) | 0; - hi = (hi + Math.imul(ah4, bh6)) | 0; - lo = (lo + Math.imul(al3, bl7)) | 0; - mid = (mid + Math.imul(al3, bh7)) | 0; - mid = (mid + Math.imul(ah3, bl7)) | 0; - hi = (hi + Math.imul(ah3, bh7)) | 0; - lo = (lo + Math.imul(al2, bl8)) | 0; - mid = (mid + Math.imul(al2, bh8)) | 0; - mid = (mid + Math.imul(ah2, bl8)) | 0; - hi = (hi + Math.imul(ah2, bh8)) | 0; - lo = (lo + Math.imul(al1, bl9)) | 0; - mid = (mid + Math.imul(al1, bh9)) | 0; - mid = (mid + Math.imul(ah1, bl9)) | 0; - hi = (hi + Math.imul(ah1, bh9)) | 0; - var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0; - w10 &= 0x3ffffff; - /* k = 11 */ - lo = Math.imul(al9, bl2); - mid = Math.imul(al9, bh2); - mid = (mid + Math.imul(ah9, bl2)) | 0; - hi = Math.imul(ah9, bh2); - lo = (lo + Math.imul(al8, bl3)) | 0; - mid = (mid + Math.imul(al8, bh3)) | 0; - mid = (mid + Math.imul(ah8, bl3)) | 0; - hi = (hi + Math.imul(ah8, bh3)) | 0; - lo = (lo + Math.imul(al7, bl4)) | 0; - mid = (mid + Math.imul(al7, bh4)) | 0; - mid = (mid + Math.imul(ah7, bl4)) | 0; - hi = (hi + Math.imul(ah7, bh4)) | 0; - lo = (lo + Math.imul(al6, bl5)) | 0; - mid = (mid + Math.imul(al6, bh5)) | 0; - mid = (mid + Math.imul(ah6, bl5)) | 0; - hi = (hi + Math.imul(ah6, bh5)) | 0; - lo = (lo + Math.imul(al5, bl6)) | 0; - mid = (mid + Math.imul(al5, bh6)) | 0; - mid = (mid + Math.imul(ah5, bl6)) | 0; - hi = (hi + Math.imul(ah5, bh6)) | 0; - lo = (lo + Math.imul(al4, bl7)) | 0; - mid = (mid + Math.imul(al4, bh7)) | 0; - mid = (mid + Math.imul(ah4, bl7)) | 0; - hi = (hi + Math.imul(ah4, bh7)) | 0; - lo = (lo + Math.imul(al3, bl8)) | 0; - mid = (mid + Math.imul(al3, bh8)) | 0; - mid = (mid + Math.imul(ah3, bl8)) | 0; - hi = (hi + Math.imul(ah3, bh8)) | 0; - lo = (lo + Math.imul(al2, bl9)) | 0; - mid = (mid + Math.imul(al2, bh9)) | 0; - mid = (mid + Math.imul(ah2, bl9)) | 0; - hi = (hi + Math.imul(ah2, bh9)) | 0; - var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0; - w11 &= 0x3ffffff; - /* k = 12 */ - lo = Math.imul(al9, bl3); - mid = Math.imul(al9, bh3); - mid = (mid + Math.imul(ah9, bl3)) | 0; - hi = Math.imul(ah9, bh3); - lo = (lo + Math.imul(al8, bl4)) | 0; - mid = (mid + Math.imul(al8, bh4)) | 0; - mid = (mid + Math.imul(ah8, bl4)) | 0; - hi = (hi + Math.imul(ah8, bh4)) | 0; - lo = (lo + Math.imul(al7, bl5)) | 0; - mid = (mid + Math.imul(al7, bh5)) | 0; - mid = (mid + Math.imul(ah7, bl5)) | 0; - hi = (hi + Math.imul(ah7, bh5)) | 0; - lo = (lo + Math.imul(al6, bl6)) | 0; - mid = (mid + Math.imul(al6, bh6)) | 0; - mid = (mid + Math.imul(ah6, bl6)) | 0; - hi = (hi + Math.imul(ah6, bh6)) | 0; - lo = (lo + Math.imul(al5, bl7)) | 0; - mid = (mid + Math.imul(al5, bh7)) | 0; - mid = (mid + Math.imul(ah5, bl7)) | 0; - hi = (hi + Math.imul(ah5, bh7)) | 0; - lo = (lo + Math.imul(al4, bl8)) | 0; - mid = (mid + Math.imul(al4, bh8)) | 0; - mid = (mid + Math.imul(ah4, bl8)) | 0; - hi = (hi + Math.imul(ah4, bh8)) | 0; - lo = (lo + Math.imul(al3, bl9)) | 0; - mid = (mid + Math.imul(al3, bh9)) | 0; - mid = (mid + Math.imul(ah3, bl9)) | 0; - hi = (hi + Math.imul(ah3, bh9)) | 0; - var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0; - w12 &= 0x3ffffff; - /* k = 13 */ - lo = Math.imul(al9, bl4); - mid = Math.imul(al9, bh4); - mid = (mid + Math.imul(ah9, bl4)) | 0; - hi = Math.imul(ah9, bh4); - lo = (lo + Math.imul(al8, bl5)) | 0; - mid = (mid + Math.imul(al8, bh5)) | 0; - mid = (mid + Math.imul(ah8, bl5)) | 0; - hi = (hi + Math.imul(ah8, bh5)) | 0; - lo = (lo + Math.imul(al7, bl6)) | 0; - mid = (mid + Math.imul(al7, bh6)) | 0; - mid = (mid + Math.imul(ah7, bl6)) | 0; - hi = (hi + Math.imul(ah7, bh6)) | 0; - lo = (lo + Math.imul(al6, bl7)) | 0; - mid = (mid + Math.imul(al6, bh7)) | 0; - mid = (mid + Math.imul(ah6, bl7)) | 0; - hi = (hi + Math.imul(ah6, bh7)) | 0; - lo = (lo + Math.imul(al5, bl8)) | 0; - mid = (mid + Math.imul(al5, bh8)) | 0; - mid = (mid + Math.imul(ah5, bl8)) | 0; - hi = (hi + Math.imul(ah5, bh8)) | 0; - lo = (lo + Math.imul(al4, bl9)) | 0; - mid = (mid + Math.imul(al4, bh9)) | 0; - mid = (mid + Math.imul(ah4, bl9)) | 0; - hi = (hi + Math.imul(ah4, bh9)) | 0; - var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0; - w13 &= 0x3ffffff; - /* k = 14 */ - lo = Math.imul(al9, bl5); - mid = Math.imul(al9, bh5); - mid = (mid + Math.imul(ah9, bl5)) | 0; - hi = Math.imul(ah9, bh5); - lo = (lo + Math.imul(al8, bl6)) | 0; - mid = (mid + Math.imul(al8, bh6)) | 0; - mid = (mid + Math.imul(ah8, bl6)) | 0; - hi = (hi + Math.imul(ah8, bh6)) | 0; - lo = (lo + Math.imul(al7, bl7)) | 0; - mid = (mid + Math.imul(al7, bh7)) | 0; - mid = (mid + Math.imul(ah7, bl7)) | 0; - hi = (hi + Math.imul(ah7, bh7)) | 0; - lo = (lo + Math.imul(al6, bl8)) | 0; - mid = (mid + Math.imul(al6, bh8)) | 0; - mid = (mid + Math.imul(ah6, bl8)) | 0; - hi = (hi + Math.imul(ah6, bh8)) | 0; - lo = (lo + Math.imul(al5, bl9)) | 0; - mid = (mid + Math.imul(al5, bh9)) | 0; - mid = (mid + Math.imul(ah5, bl9)) | 0; - hi = (hi + Math.imul(ah5, bh9)) | 0; - var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0; - w14 &= 0x3ffffff; - /* k = 15 */ - lo = Math.imul(al9, bl6); - mid = Math.imul(al9, bh6); - mid = (mid + Math.imul(ah9, bl6)) | 0; - hi = Math.imul(ah9, bh6); - lo = (lo + Math.imul(al8, bl7)) | 0; - mid = (mid + Math.imul(al8, bh7)) | 0; - mid = (mid + Math.imul(ah8, bl7)) | 0; - hi = (hi + Math.imul(ah8, bh7)) | 0; - lo = (lo + Math.imul(al7, bl8)) | 0; - mid = (mid + Math.imul(al7, bh8)) | 0; - mid = (mid + Math.imul(ah7, bl8)) | 0; - hi = (hi + Math.imul(ah7, bh8)) | 0; - lo = (lo + Math.imul(al6, bl9)) | 0; - mid = (mid + Math.imul(al6, bh9)) | 0; - mid = (mid + Math.imul(ah6, bl9)) | 0; - hi = (hi + Math.imul(ah6, bh9)) | 0; - var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0; - w15 &= 0x3ffffff; - /* k = 16 */ - lo = Math.imul(al9, bl7); - mid = Math.imul(al9, bh7); - mid = (mid + Math.imul(ah9, bl7)) | 0; - hi = Math.imul(ah9, bh7); - lo = (lo + Math.imul(al8, bl8)) | 0; - mid = (mid + Math.imul(al8, bh8)) | 0; - mid = (mid + Math.imul(ah8, bl8)) | 0; - hi = (hi + Math.imul(ah8, bh8)) | 0; - lo = (lo + Math.imul(al7, bl9)) | 0; - mid = (mid + Math.imul(al7, bh9)) | 0; - mid = (mid + Math.imul(ah7, bl9)) | 0; - hi = (hi + Math.imul(ah7, bh9)) | 0; - var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0; - w16 &= 0x3ffffff; - /* k = 17 */ - lo = Math.imul(al9, bl8); - mid = Math.imul(al9, bh8); - mid = (mid + Math.imul(ah9, bl8)) | 0; - hi = Math.imul(ah9, bh8); - lo = (lo + Math.imul(al8, bl9)) | 0; - mid = (mid + Math.imul(al8, bh9)) | 0; - mid = (mid + Math.imul(ah8, bl9)) | 0; - hi = (hi + Math.imul(ah8, bh9)) | 0; - var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0; - w17 &= 0x3ffffff; - /* k = 18 */ - lo = Math.imul(al9, bl9); - mid = Math.imul(al9, bh9); - mid = (mid + Math.imul(ah9, bl9)) | 0; - hi = Math.imul(ah9, bh9); - var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0; - w18 &= 0x3ffffff; - o[0] = w0; - o[1] = w1; - o[2] = w2; - o[3] = w3; - o[4] = w4; - o[5] = w5; - o[6] = w6; - o[7] = w7; - o[8] = w8; - o[9] = w9; - o[10] = w10; - o[11] = w11; - o[12] = w12; - o[13] = w13; - o[14] = w14; - o[15] = w15; - o[16] = w16; - o[17] = w17; - o[18] = w18; - if (c !== 0) { - o[19] = c; - out.length++; - } - return out; - }; - - // Polyfill comb - if (!Math.imul) { - comb10MulTo = smallMulTo; - } - - function bigMulTo (self, num, out) { - out.negative = num.negative ^ self.negative; - out.length = self.length + num.length; - - var carry = 0; - var hncarry = 0; - for (var k = 0; k < out.length - 1; k++) { - // Sum all words with the same `i + j = k` and accumulate `ncarry`, - // note that ncarry could be >= 0x3ffffff - var ncarry = hncarry; - hncarry = 0; - var rword = carry & 0x3ffffff; - var maxJ = Math.min(k, num.length - 1); - for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { - var i = k - j; - var a = self.words[i] | 0; - var b = num.words[j] | 0; - var r = a * b; - - var lo = r & 0x3ffffff; - ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0; - lo = (lo + rword) | 0; - rword = lo & 0x3ffffff; - ncarry = (ncarry + (lo >>> 26)) | 0; - - hncarry += ncarry >>> 26; - ncarry &= 0x3ffffff; - } - out.words[k] = rword; - carry = ncarry; - ncarry = hncarry; - } - if (carry !== 0) { - out.words[k] = carry; - } else { - out.length--; - } - - return out.strip(); - } - - function jumboMulTo (self, num, out) { - var fftm = new FFTM(); - return fftm.mulp(self, num, out); - } - - BN.prototype.mulTo = function mulTo (num, out) { - var res; - var len = this.length + num.length; - if (this.length === 10 && num.length === 10) { - res = comb10MulTo(this, num, out); - } else if (len < 63) { - res = smallMulTo(this, num, out); - } else if (len < 1024) { - res = bigMulTo(this, num, out); - } else { - res = jumboMulTo(this, num, out); - } - - return res; - }; - - // Cooley-Tukey algorithm for FFT - // slightly revisited to rely on looping instead of recursion - - function FFTM (x, y) { - this.x = x; - this.y = y; - } - - FFTM.prototype.makeRBT = function makeRBT (N) { - var t = new Array(N); - var l = BN.prototype._countBits(N) - 1; - for (var i = 0; i < N; i++) { - t[i] = this.revBin(i, l, N); - } - - return t; - }; - - // Returns binary-reversed representation of `x` - FFTM.prototype.revBin = function revBin (x, l, N) { - if (x === 0 || x === N - 1) return x; - - var rb = 0; - for (var i = 0; i < l; i++) { - rb |= (x & 1) << (l - i - 1); - x >>= 1; - } - - return rb; - }; - - // Performs "tweedling" phase, therefore 'emulating' - // behaviour of the recursive algorithm - FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) { - for (var i = 0; i < N; i++) { - rtws[i] = rws[rbt[i]]; - itws[i] = iws[rbt[i]]; - } - }; - - FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) { - this.permute(rbt, rws, iws, rtws, itws, N); - - for (var s = 1; s < N; s <<= 1) { - var l = s << 1; - - var rtwdf = Math.cos(2 * Math.PI / l); - var itwdf = Math.sin(2 * Math.PI / l); - - for (var p = 0; p < N; p += l) { - var rtwdf_ = rtwdf; - var itwdf_ = itwdf; - - for (var j = 0; j < s; j++) { - var re = rtws[p + j]; - var ie = itws[p + j]; - - var ro = rtws[p + j + s]; - var io = itws[p + j + s]; - - var rx = rtwdf_ * ro - itwdf_ * io; - - io = rtwdf_ * io + itwdf_ * ro; - ro = rx; - - rtws[p + j] = re + ro; - itws[p + j] = ie + io; - - rtws[p + j + s] = re - ro; - itws[p + j + s] = ie - io; - - /* jshint maxdepth : false */ - if (j !== l) { - rx = rtwdf * rtwdf_ - itwdf * itwdf_; - - itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_; - rtwdf_ = rx; - } - } - } - } - }; - - FFTM.prototype.guessLen13b = function guessLen13b (n, m) { - var N = Math.max(m, n) | 1; - var odd = N & 1; - var i = 0; - for (N = N / 2 | 0; N; N = N >>> 1) { - i++; - } - - return 1 << i + 1 + odd; - }; - - FFTM.prototype.conjugate = function conjugate (rws, iws, N) { - if (N <= 1) return; - - for (var i = 0; i < N / 2; i++) { - var t = rws[i]; - - rws[i] = rws[N - i - 1]; - rws[N - i - 1] = t; - - t = iws[i]; - - iws[i] = -iws[N - i - 1]; - iws[N - i - 1] = -t; - } - }; - - FFTM.prototype.normalize13b = function normalize13b (ws, N) { - var carry = 0; - for (var i = 0; i < N / 2; i++) { - var w = Math.round(ws[2 * i + 1] / N) * 0x2000 + - Math.round(ws[2 * i] / N) + - carry; - - ws[i] = w & 0x3ffffff; - - if (w < 0x4000000) { - carry = 0; - } else { - carry = w / 0x4000000 | 0; - } - } - - return ws; - }; - - FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) { - var carry = 0; - for (var i = 0; i < len; i++) { - carry = carry + (ws[i] | 0); - - rws[2 * i] = carry & 0x1fff; carry = carry >>> 13; - rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13; - } - - // Pad with zeroes - for (i = 2 * len; i < N; ++i) { - rws[i] = 0; - } - - assert(carry === 0); - assert((carry & ~0x1fff) === 0); - }; - - FFTM.prototype.stub = function stub (N) { - var ph = new Array(N); - for (var i = 0; i < N; i++) { - ph[i] = 0; - } - - return ph; - }; - - FFTM.prototype.mulp = function mulp (x, y, out) { - var N = 2 * this.guessLen13b(x.length, y.length); - - var rbt = this.makeRBT(N); - - var _ = this.stub(N); - - var rws = new Array(N); - var rwst = new Array(N); - var iwst = new Array(N); - - var nrws = new Array(N); - var nrwst = new Array(N); - var niwst = new Array(N); - - var rmws = out.words; - rmws.length = N; - - this.convert13b(x.words, x.length, rws, N); - this.convert13b(y.words, y.length, nrws, N); - - this.transform(rws, _, rwst, iwst, N, rbt); - this.transform(nrws, _, nrwst, niwst, N, rbt); - - for (var i = 0; i < N; i++) { - var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i]; - iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i]; - rwst[i] = rx; - } - - this.conjugate(rwst, iwst, N); - this.transform(rwst, iwst, rmws, _, N, rbt); - this.conjugate(rmws, _, N); - this.normalize13b(rmws, N); - - out.negative = x.negative ^ y.negative; - out.length = x.length + y.length; - return out.strip(); - }; - - // Multiply `this` by `num` - BN.prototype.mul = function mul (num) { - var out = new BN(null); - out.words = new Array(this.length + num.length); - return this.mulTo(num, out); - }; - - // Multiply employing FFT - BN.prototype.mulf = function mulf (num) { - var out = new BN(null); - out.words = new Array(this.length + num.length); - return jumboMulTo(this, num, out); - }; - - // In-place Multiplication - BN.prototype.imul = function imul (num) { - return this.clone().mulTo(num, this); - }; - - BN.prototype.imuln = function imuln (num) { - assert(typeof num === 'number'); - assert(num < 0x4000000); - - // Carry - var carry = 0; - for (var i = 0; i < this.length; i++) { - var w = (this.words[i] | 0) * num; - var lo = (w & 0x3ffffff) + (carry & 0x3ffffff); - carry >>= 26; - carry += (w / 0x4000000) | 0; - // NOTE: lo is 27bit maximum - carry += lo >>> 26; - this.words[i] = lo & 0x3ffffff; - } - - if (carry !== 0) { - this.words[i] = carry; - this.length++; - } - - return this; - }; - - BN.prototype.muln = function muln (num) { - return this.clone().imuln(num); - }; - - // `this` * `this` - BN.prototype.sqr = function sqr () { - return this.mul(this); - }; - - // `this` * `this` in-place - BN.prototype.isqr = function isqr () { - return this.imul(this.clone()); - }; - - // Math.pow(`this`, `num`) - BN.prototype.pow = function pow (num) { - var w = toBitArray(num); - if (w.length === 0) return new BN(1); - - // Skip leading zeroes - var res = this; - for (var i = 0; i < w.length; i++, res = res.sqr()) { - if (w[i] !== 0) break; - } - - if (++i < w.length) { - for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) { - if (w[i] === 0) continue; - - res = res.mul(q); - } - } - - return res; - }; - - // Shift-left in-place - BN.prototype.iushln = function iushln (bits) { - assert(typeof bits === 'number' && bits >= 0); - var r = bits % 26; - var s = (bits - r) / 26; - var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r); - var i; - - if (r !== 0) { - var carry = 0; - - for (i = 0; i < this.length; i++) { - var newCarry = this.words[i] & carryMask; - var c = ((this.words[i] | 0) - newCarry) << r; - this.words[i] = c | carry; - carry = newCarry >>> (26 - r); - } - - if (carry) { - this.words[i] = carry; - this.length++; - } - } - - if (s !== 0) { - for (i = this.length - 1; i >= 0; i--) { - this.words[i + s] = this.words[i]; - } - - for (i = 0; i < s; i++) { - this.words[i] = 0; - } - - this.length += s; - } - - return this.strip(); - }; - - BN.prototype.ishln = function ishln (bits) { - // TODO(indutny): implement me - assert(this.negative === 0); - return this.iushln(bits); - }; - - // Shift-right in-place - // NOTE: `hint` is a lowest bit before trailing zeroes - // NOTE: if `extended` is present - it will be filled with destroyed bits - BN.prototype.iushrn = function iushrn (bits, hint, extended) { - assert(typeof bits === 'number' && bits >= 0); - var h; - if (hint) { - h = (hint - (hint % 26)) / 26; - } else { - h = 0; - } - - var r = bits % 26; - var s = Math.min((bits - r) / 26, this.length); - var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); - var maskedWords = extended; - - h -= s; - h = Math.max(0, h); - - // Extended mode, copy masked part - if (maskedWords) { - for (var i = 0; i < s; i++) { - maskedWords.words[i] = this.words[i]; - } - maskedWords.length = s; - } - - if (s === 0) ; else if (this.length > s) { - this.length -= s; - for (i = 0; i < this.length; i++) { - this.words[i] = this.words[i + s]; - } - } else { - this.words[0] = 0; - this.length = 1; - } - - var carry = 0; - for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) { - var word = this.words[i] | 0; - this.words[i] = (carry << (26 - r)) | (word >>> r); - carry = word & mask; - } - - // Push carried bits as a mask - if (maskedWords && carry !== 0) { - maskedWords.words[maskedWords.length++] = carry; - } - - if (this.length === 0) { - this.words[0] = 0; - this.length = 1; - } - - return this.strip(); - }; - - BN.prototype.ishrn = function ishrn (bits, hint, extended) { - // TODO(indutny): implement me - assert(this.negative === 0); - return this.iushrn(bits, hint, extended); - }; - - // Shift-left - BN.prototype.shln = function shln (bits) { - return this.clone().ishln(bits); - }; - - BN.prototype.ushln = function ushln (bits) { - return this.clone().iushln(bits); - }; - - // Shift-right - BN.prototype.shrn = function shrn (bits) { - return this.clone().ishrn(bits); - }; - - BN.prototype.ushrn = function ushrn (bits) { - return this.clone().iushrn(bits); - }; - - // Test if n bit is set - BN.prototype.testn = function testn (bit) { - assert(typeof bit === 'number' && bit >= 0); - var r = bit % 26; - var s = (bit - r) / 26; - var q = 1 << r; - - // Fast case: bit is much higher than all existing words - if (this.length <= s) return false; - - // Check bit and return - var w = this.words[s]; - - return !!(w & q); - }; - - // Return only lowers bits of number (in-place) - BN.prototype.imaskn = function imaskn (bits) { - assert(typeof bits === 'number' && bits >= 0); - var r = bits % 26; - var s = (bits - r) / 26; - - assert(this.negative === 0, 'imaskn works only with positive numbers'); - - if (this.length <= s) { - return this; - } - - if (r !== 0) { - s++; - } - this.length = Math.min(s, this.length); - - if (r !== 0) { - var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); - this.words[this.length - 1] &= mask; - } - - return this.strip(); - }; - - // Return only lowers bits of number - BN.prototype.maskn = function maskn (bits) { - return this.clone().imaskn(bits); - }; - - // Add plain number `num` to `this` - BN.prototype.iaddn = function iaddn (num) { - assert(typeof num === 'number'); - assert(num < 0x4000000); - if (num < 0) return this.isubn(-num); - - // Possible sign change - if (this.negative !== 0) { - if (this.length === 1 && (this.words[0] | 0) < num) { - this.words[0] = num - (this.words[0] | 0); - this.negative = 0; - return this; - } - - this.negative = 0; - this.isubn(num); - this.negative = 1; - return this; - } - - // Add without checks - return this._iaddn(num); - }; - - BN.prototype._iaddn = function _iaddn (num) { - this.words[0] += num; - - // Carry - for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) { - this.words[i] -= 0x4000000; - if (i === this.length - 1) { - this.words[i + 1] = 1; - } else { - this.words[i + 1]++; - } - } - this.length = Math.max(this.length, i + 1); - - return this; - }; - - // Subtract plain number `num` from `this` - BN.prototype.isubn = function isubn (num) { - assert(typeof num === 'number'); - assert(num < 0x4000000); - if (num < 0) return this.iaddn(-num); - - if (this.negative !== 0) { - this.negative = 0; - this.iaddn(num); - this.negative = 1; - return this; - } - - this.words[0] -= num; - - if (this.length === 1 && this.words[0] < 0) { - this.words[0] = -this.words[0]; - this.negative = 1; - } else { - // Carry - for (var i = 0; i < this.length && this.words[i] < 0; i++) { - this.words[i] += 0x4000000; - this.words[i + 1] -= 1; - } - } - - return this.strip(); - }; - - BN.prototype.addn = function addn (num) { - return this.clone().iaddn(num); - }; - - BN.prototype.subn = function subn (num) { - return this.clone().isubn(num); - }; - - BN.prototype.iabs = function iabs () { - this.negative = 0; - - return this; - }; - - BN.prototype.abs = function abs () { - return this.clone().iabs(); - }; - - BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) { - var len = num.length + shift; - var i; - - this._expand(len); - - var w; - var carry = 0; - for (i = 0; i < num.length; i++) { - w = (this.words[i + shift] | 0) + carry; - var right = (num.words[i] | 0) * mul; - w -= right & 0x3ffffff; - carry = (w >> 26) - ((right / 0x4000000) | 0); - this.words[i + shift] = w & 0x3ffffff; - } - for (; i < this.length - shift; i++) { - w = (this.words[i + shift] | 0) + carry; - carry = w >> 26; - this.words[i + shift] = w & 0x3ffffff; - } - - if (carry === 0) return this.strip(); - - // Subtraction overflow - assert(carry === -1); - carry = 0; - for (i = 0; i < this.length; i++) { - w = -(this.words[i] | 0) + carry; - carry = w >> 26; - this.words[i] = w & 0x3ffffff; - } - this.negative = 1; - - return this.strip(); - }; - - BN.prototype._wordDiv = function _wordDiv (num, mode) { - var shift = this.length - num.length; - - var a = this.clone(); - var b = num; - - // Normalize - var bhi = b.words[b.length - 1] | 0; - var bhiBits = this._countBits(bhi); - shift = 26 - bhiBits; - if (shift !== 0) { - b = b.ushln(shift); - a.iushln(shift); - bhi = b.words[b.length - 1] | 0; - } - - // Initialize quotient - var m = a.length - b.length; - var q; - - if (mode !== 'mod') { - q = new BN(null); - q.length = m + 1; - q.words = new Array(q.length); - for (var i = 0; i < q.length; i++) { - q.words[i] = 0; - } - } - - var diff = a.clone()._ishlnsubmul(b, 1, m); - if (diff.negative === 0) { - a = diff; - if (q) { - q.words[m] = 1; - } - } - - for (var j = m - 1; j >= 0; j--) { - var qj = (a.words[b.length + j] | 0) * 0x4000000 + - (a.words[b.length + j - 1] | 0); - - // NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max - // (0x7ffffff) - qj = Math.min((qj / bhi) | 0, 0x3ffffff); - - a._ishlnsubmul(b, qj, j); - while (a.negative !== 0) { - qj--; - a.negative = 0; - a._ishlnsubmul(b, 1, j); - if (!a.isZero()) { - a.negative ^= 1; - } - } - if (q) { - q.words[j] = qj; - } - } - if (q) { - q.strip(); - } - a.strip(); - - // Denormalize - if (mode !== 'div' && shift !== 0) { - a.iushrn(shift); - } - - return { - div: q || null, - mod: a - }; - }; - - // NOTE: 1) `mode` can be set to `mod` to request mod only, - // to `div` to request div only, or be absent to - // request both div & mod - // 2) `positive` is true if unsigned mod is requested - BN.prototype.divmod = function divmod (num, mode, positive) { - assert(!num.isZero()); - - if (this.isZero()) { - return { - div: new BN(0), - mod: new BN(0) - }; - } - - var div, mod, res; - if (this.negative !== 0 && num.negative === 0) { - res = this.neg().divmod(num, mode); - - if (mode !== 'mod') { - div = res.div.neg(); - } - - if (mode !== 'div') { - mod = res.mod.neg(); - if (positive && mod.negative !== 0) { - mod.iadd(num); - } - } - - return { - div: div, - mod: mod - }; - } - - if (this.negative === 0 && num.negative !== 0) { - res = this.divmod(num.neg(), mode); - - if (mode !== 'mod') { - div = res.div.neg(); - } - - return { - div: div, - mod: res.mod - }; - } - - if ((this.negative & num.negative) !== 0) { - res = this.neg().divmod(num.neg(), mode); - - if (mode !== 'div') { - mod = res.mod.neg(); - if (positive && mod.negative !== 0) { - mod.isub(num); - } - } - - return { - div: res.div, - mod: mod - }; - } - - // Both numbers are positive at this point - - // Strip both numbers to approximate shift value - if (num.length > this.length || this.cmp(num) < 0) { - return { - div: new BN(0), - mod: this - }; - } - - // Very short reduction - if (num.length === 1) { - if (mode === 'div') { - return { - div: this.divn(num.words[0]), - mod: null - }; - } - - if (mode === 'mod') { - return { - div: null, - mod: new BN(this.modn(num.words[0])) - }; - } - - return { - div: this.divn(num.words[0]), - mod: new BN(this.modn(num.words[0])) - }; - } - - return this._wordDiv(num, mode); - }; - - // Find `this` / `num` - BN.prototype.div = function div (num) { - return this.divmod(num, 'div', false).div; - }; - - // Find `this` % `num` - BN.prototype.mod = function mod (num) { - return this.divmod(num, 'mod', false).mod; - }; - - BN.prototype.umod = function umod (num) { - return this.divmod(num, 'mod', true).mod; - }; - - // Find Round(`this` / `num`) - BN.prototype.divRound = function divRound (num) { - var dm = this.divmod(num); - - // Fast case - exact division - if (dm.mod.isZero()) return dm.div; - - var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod; - - var half = num.ushrn(1); - var r2 = num.andln(1); - var cmp = mod.cmp(half); - - // Round down - if (cmp < 0 || r2 === 1 && cmp === 0) return dm.div; - - // Round up - return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1); - }; - - BN.prototype.modn = function modn (num) { - assert(num <= 0x3ffffff); - var p = (1 << 26) % num; - - var acc = 0; - for (var i = this.length - 1; i >= 0; i--) { - acc = (p * acc + (this.words[i] | 0)) % num; - } - - return acc; - }; - - // In-place division by number - BN.prototype.idivn = function idivn (num) { - assert(num <= 0x3ffffff); - - var carry = 0; - for (var i = this.length - 1; i >= 0; i--) { - var w = (this.words[i] | 0) + carry * 0x4000000; - this.words[i] = (w / num) | 0; - carry = w % num; - } - - return this.strip(); - }; - - BN.prototype.divn = function divn (num) { - return this.clone().idivn(num); - }; - - BN.prototype.egcd = function egcd (p) { - assert(p.negative === 0); - assert(!p.isZero()); - - var x = this; - var y = p.clone(); - - if (x.negative !== 0) { - x = x.umod(p); - } else { - x = x.clone(); - } - - // A * x + B * y = x - var A = new BN(1); - var B = new BN(0); - - // C * x + D * y = y - var C = new BN(0); - var D = new BN(1); - - var g = 0; - - while (x.isEven() && y.isEven()) { - x.iushrn(1); - y.iushrn(1); - ++g; - } - - var yp = y.clone(); - var xp = x.clone(); - - while (!x.isZero()) { - for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1); - if (i > 0) { - x.iushrn(i); - while (i-- > 0) { - if (A.isOdd() || B.isOdd()) { - A.iadd(yp); - B.isub(xp); - } - - A.iushrn(1); - B.iushrn(1); - } - } - - for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); - if (j > 0) { - y.iushrn(j); - while (j-- > 0) { - if (C.isOdd() || D.isOdd()) { - C.iadd(yp); - D.isub(xp); - } - - C.iushrn(1); - D.iushrn(1); - } - } - - if (x.cmp(y) >= 0) { - x.isub(y); - A.isub(C); - B.isub(D); - } else { - y.isub(x); - C.isub(A); - D.isub(B); - } - } - - return { - a: C, - b: D, - gcd: y.iushln(g) - }; - }; - - // This is reduced incarnation of the binary EEA - // above, designated to invert members of the - // _prime_ fields F(p) at a maximal speed - BN.prototype._invmp = function _invmp (p) { - assert(p.negative === 0); - assert(!p.isZero()); - - var a = this; - var b = p.clone(); - - if (a.negative !== 0) { - a = a.umod(p); - } else { - a = a.clone(); - } - - var x1 = new BN(1); - var x2 = new BN(0); - - var delta = b.clone(); - - while (a.cmpn(1) > 0 && b.cmpn(1) > 0) { - for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1); - if (i > 0) { - a.iushrn(i); - while (i-- > 0) { - if (x1.isOdd()) { - x1.iadd(delta); - } - - x1.iushrn(1); - } - } - - for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); - if (j > 0) { - b.iushrn(j); - while (j-- > 0) { - if (x2.isOdd()) { - x2.iadd(delta); - } - - x2.iushrn(1); - } - } - - if (a.cmp(b) >= 0) { - a.isub(b); - x1.isub(x2); - } else { - b.isub(a); - x2.isub(x1); - } - } - - var res; - if (a.cmpn(1) === 0) { - res = x1; - } else { - res = x2; - } - - if (res.cmpn(0) < 0) { - res.iadd(p); - } - - return res; - }; - - BN.prototype.gcd = function gcd (num) { - if (this.isZero()) return num.abs(); - if (num.isZero()) return this.abs(); - - var a = this.clone(); - var b = num.clone(); - a.negative = 0; - b.negative = 0; - - // Remove common factor of two - for (var shift = 0; a.isEven() && b.isEven(); shift++) { - a.iushrn(1); - b.iushrn(1); - } - - do { - while (a.isEven()) { - a.iushrn(1); - } - while (b.isEven()) { - b.iushrn(1); - } - - var r = a.cmp(b); - if (r < 0) { - // Swap `a` and `b` to make `a` always bigger than `b` - var t = a; - a = b; - b = t; - } else if (r === 0 || b.cmpn(1) === 0) { - break; - } - - a.isub(b); - } while (true); - - return b.iushln(shift); - }; - - // Invert number in the field F(num) - BN.prototype.invm = function invm (num) { - return this.egcd(num).a.umod(num); - }; - - BN.prototype.isEven = function isEven () { - return (this.words[0] & 1) === 0; - }; - - BN.prototype.isOdd = function isOdd () { - return (this.words[0] & 1) === 1; - }; - - // And first word and num - BN.prototype.andln = function andln (num) { - return this.words[0] & num; - }; - - // Increment at the bit position in-line - BN.prototype.bincn = function bincn (bit) { - assert(typeof bit === 'number'); - var r = bit % 26; - var s = (bit - r) / 26; - var q = 1 << r; - - // Fast case: bit is much higher than all existing words - if (this.length <= s) { - this._expand(s + 1); - this.words[s] |= q; - return this; - } - - // Add bit and propagate, if needed - var carry = q; - for (var i = s; carry !== 0 && i < this.length; i++) { - var w = this.words[i] | 0; - w += carry; - carry = w >>> 26; - w &= 0x3ffffff; - this.words[i] = w; - } - if (carry !== 0) { - this.words[i] = carry; - this.length++; - } - return this; - }; - - BN.prototype.isZero = function isZero () { - return this.length === 1 && this.words[0] === 0; - }; - - BN.prototype.cmpn = function cmpn (num) { - var negative = num < 0; - - if (this.negative !== 0 && !negative) return -1; - if (this.negative === 0 && negative) return 1; - - this.strip(); - - var res; - if (this.length > 1) { - res = 1; - } else { - if (negative) { - num = -num; - } - - assert(num <= 0x3ffffff, 'Number is too big'); - - var w = this.words[0] | 0; - res = w === num ? 0 : w < num ? -1 : 1; - } - if (this.negative !== 0) return -res | 0; - return res; - }; - - // Compare two numbers and return: - // 1 - if `this` > `num` - // 0 - if `this` == `num` - // -1 - if `this` < `num` - BN.prototype.cmp = function cmp (num) { - if (this.negative !== 0 && num.negative === 0) return -1; - if (this.negative === 0 && num.negative !== 0) return 1; - - var res = this.ucmp(num); - if (this.negative !== 0) return -res | 0; - return res; - }; - - // Unsigned comparison - BN.prototype.ucmp = function ucmp (num) { - // At this point both numbers have the same sign - if (this.length > num.length) return 1; - if (this.length < num.length) return -1; - - var res = 0; - for (var i = this.length - 1; i >= 0; i--) { - var a = this.words[i] | 0; - var b = num.words[i] | 0; - - if (a === b) continue; - if (a < b) { - res = -1; - } else if (a > b) { - res = 1; - } - break; - } - return res; - }; - - BN.prototype.gtn = function gtn (num) { - return this.cmpn(num) === 1; - }; - - BN.prototype.gt = function gt (num) { - return this.cmp(num) === 1; - }; - - BN.prototype.gten = function gten (num) { - return this.cmpn(num) >= 0; - }; - - BN.prototype.gte = function gte (num) { - return this.cmp(num) >= 0; - }; - - BN.prototype.ltn = function ltn (num) { - return this.cmpn(num) === -1; - }; - - BN.prototype.lt = function lt (num) { - return this.cmp(num) === -1; - }; - - BN.prototype.lten = function lten (num) { - return this.cmpn(num) <= 0; - }; - - BN.prototype.lte = function lte (num) { - return this.cmp(num) <= 0; - }; - - BN.prototype.eqn = function eqn (num) { - return this.cmpn(num) === 0; - }; - - BN.prototype.eq = function eq (num) { - return this.cmp(num) === 0; - }; - - // - // A reduce context, could be using montgomery or something better, depending - // on the `m` itself. - // - BN.red = function red (num) { - return new Red(num); - }; - - BN.prototype.toRed = function toRed (ctx) { - assert(!this.red, 'Already a number in reduction context'); - assert(this.negative === 0, 'red works only with positives'); - return ctx.convertTo(this)._forceRed(ctx); - }; - - BN.prototype.fromRed = function fromRed () { - assert(this.red, 'fromRed works only with numbers in reduction context'); - return this.red.convertFrom(this); - }; - - BN.prototype._forceRed = function _forceRed (ctx) { - this.red = ctx; - return this; - }; - - BN.prototype.forceRed = function forceRed (ctx) { - assert(!this.red, 'Already a number in reduction context'); - return this._forceRed(ctx); - }; - - BN.prototype.redAdd = function redAdd (num) { - assert(this.red, 'redAdd works only with red numbers'); - return this.red.add(this, num); - }; - - BN.prototype.redIAdd = function redIAdd (num) { - assert(this.red, 'redIAdd works only with red numbers'); - return this.red.iadd(this, num); - }; - - BN.prototype.redSub = function redSub (num) { - assert(this.red, 'redSub works only with red numbers'); - return this.red.sub(this, num); - }; - - BN.prototype.redISub = function redISub (num) { - assert(this.red, 'redISub works only with red numbers'); - return this.red.isub(this, num); - }; - - BN.prototype.redShl = function redShl (num) { - assert(this.red, 'redShl works only with red numbers'); - return this.red.shl(this, num); - }; - - BN.prototype.redMul = function redMul (num) { - assert(this.red, 'redMul works only with red numbers'); - this.red._verify2(this, num); - return this.red.mul(this, num); - }; - - BN.prototype.redIMul = function redIMul (num) { - assert(this.red, 'redMul works only with red numbers'); - this.red._verify2(this, num); - return this.red.imul(this, num); - }; - - BN.prototype.redSqr = function redSqr () { - assert(this.red, 'redSqr works only with red numbers'); - this.red._verify1(this); - return this.red.sqr(this); - }; - - BN.prototype.redISqr = function redISqr () { - assert(this.red, 'redISqr works only with red numbers'); - this.red._verify1(this); - return this.red.isqr(this); - }; - - // Square root over p - BN.prototype.redSqrt = function redSqrt () { - assert(this.red, 'redSqrt works only with red numbers'); - this.red._verify1(this); - return this.red.sqrt(this); - }; - - BN.prototype.redInvm = function redInvm () { - assert(this.red, 'redInvm works only with red numbers'); - this.red._verify1(this); - return this.red.invm(this); - }; - - // Return negative clone of `this` % `red modulo` - BN.prototype.redNeg = function redNeg () { - assert(this.red, 'redNeg works only with red numbers'); - this.red._verify1(this); - return this.red.neg(this); - }; - - BN.prototype.redPow = function redPow (num) { - assert(this.red && !num.red, 'redPow(normalNum)'); - this.red._verify1(this); - return this.red.pow(this, num); - }; - - // Prime numbers with efficient reduction - var primes = { - k256: null, - p224: null, - p192: null, - p25519: null - }; - - // Pseudo-Mersenne prime - function MPrime (name, p) { - // P = 2 ^ N - K - this.name = name; - this.p = new BN(p, 16); - this.n = this.p.bitLength(); - this.k = new BN(1).iushln(this.n).isub(this.p); - - this.tmp = this._tmp(); - } - - MPrime.prototype._tmp = function _tmp () { - var tmp = new BN(null); - tmp.words = new Array(Math.ceil(this.n / 13)); - return tmp; - }; - - MPrime.prototype.ireduce = function ireduce (num) { - // Assumes that `num` is less than `P^2` - // num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P) - var r = num; - var rlen; - - do { - this.split(r, this.tmp); - r = this.imulK(r); - r = r.iadd(this.tmp); - rlen = r.bitLength(); - } while (rlen > this.n); - - var cmp = rlen < this.n ? -1 : r.ucmp(this.p); - if (cmp === 0) { - r.words[0] = 0; - r.length = 1; - } else if (cmp > 0) { - r.isub(this.p); - } else { - r.strip(); - } - - return r; - }; - - MPrime.prototype.split = function split (input, out) { - input.iushrn(this.n, 0, out); - }; - - MPrime.prototype.imulK = function imulK (num) { - return num.imul(this.k); - }; - - function K256 () { - MPrime.call( - this, - 'k256', - 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f'); - } - inherits(K256, MPrime); - - K256.prototype.split = function split (input, output) { - // 256 = 9 * 26 + 22 - var mask = 0x3fffff; - - var outLen = Math.min(input.length, 9); - for (var i = 0; i < outLen; i++) { - output.words[i] = input.words[i]; - } - output.length = outLen; - - if (input.length <= 9) { - input.words[0] = 0; - input.length = 1; - return; - } - - // Shift by 9 limbs - var prev = input.words[9]; - output.words[output.length++] = prev & mask; - - for (i = 10; i < input.length; i++) { - var next = input.words[i] | 0; - input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22); - prev = next; - } - prev >>>= 22; - input.words[i - 10] = prev; - if (prev === 0 && input.length > 10) { - input.length -= 10; - } else { - input.length -= 9; - } - }; - - K256.prototype.imulK = function imulK (num) { - // K = 0x1000003d1 = [ 0x40, 0x3d1 ] - num.words[num.length] = 0; - num.words[num.length + 1] = 0; - num.length += 2; - - // bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390 - var lo = 0; - for (var i = 0; i < num.length; i++) { - var w = num.words[i] | 0; - lo += w * 0x3d1; - num.words[i] = lo & 0x3ffffff; - lo = w * 0x40 + ((lo / 0x4000000) | 0); - } - - // Fast length reduction - if (num.words[num.length - 1] === 0) { - num.length--; - if (num.words[num.length - 1] === 0) { - num.length--; - } - } - return num; - }; - - function P224 () { - MPrime.call( - this, - 'p224', - 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001'); - } - inherits(P224, MPrime); - - function P192 () { - MPrime.call( - this, - 'p192', - 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff'); - } - inherits(P192, MPrime); - - function P25519 () { - // 2 ^ 255 - 19 - MPrime.call( - this, - '25519', - '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed'); - } - inherits(P25519, MPrime); - - P25519.prototype.imulK = function imulK (num) { - // K = 0x13 - var carry = 0; - for (var i = 0; i < num.length; i++) { - var hi = (num.words[i] | 0) * 0x13 + carry; - var lo = hi & 0x3ffffff; - hi >>>= 26; - - num.words[i] = lo; - carry = hi; - } - if (carry !== 0) { - num.words[num.length++] = carry; - } - return num; - }; - - // Exported mostly for testing purposes, use plain name instead - BN._prime = function prime (name) { - // Cached version of prime - if (primes[name]) return primes[name]; - - var prime; - if (name === 'k256') { - prime = new K256(); - } else if (name === 'p224') { - prime = new P224(); - } else if (name === 'p192') { - prime = new P192(); - } else if (name === 'p25519') { - prime = new P25519(); - } else { - throw new Error('Unknown prime ' + name); - } - primes[name] = prime; - - return prime; - }; - - // - // Base reduction engine - // - function Red (m) { - if (typeof m === 'string') { - var prime = BN._prime(m); - this.m = prime.p; - this.prime = prime; - } else { - assert(m.gtn(1), 'modulus must be greater than 1'); - this.m = m; - this.prime = null; - } - } - - Red.prototype._verify1 = function _verify1 (a) { - assert(a.negative === 0, 'red works only with positives'); - assert(a.red, 'red works only with red numbers'); - }; - - Red.prototype._verify2 = function _verify2 (a, b) { - assert((a.negative | b.negative) === 0, 'red works only with positives'); - assert(a.red && a.red === b.red, - 'red works only with red numbers'); - }; - - Red.prototype.imod = function imod (a) { - if (this.prime) return this.prime.ireduce(a)._forceRed(this); - return a.umod(this.m)._forceRed(this); - }; - - Red.prototype.neg = function neg (a) { - if (a.isZero()) { - return a.clone(); - } - - return this.m.sub(a)._forceRed(this); - }; - - Red.prototype.add = function add (a, b) { - this._verify2(a, b); - - var res = a.add(b); - if (res.cmp(this.m) >= 0) { - res.isub(this.m); - } - return res._forceRed(this); - }; - - Red.prototype.iadd = function iadd (a, b) { - this._verify2(a, b); - - var res = a.iadd(b); - if (res.cmp(this.m) >= 0) { - res.isub(this.m); - } - return res; - }; - - Red.prototype.sub = function sub (a, b) { - this._verify2(a, b); - - var res = a.sub(b); - if (res.cmpn(0) < 0) { - res.iadd(this.m); - } - return res._forceRed(this); - }; - - Red.prototype.isub = function isub (a, b) { - this._verify2(a, b); - - var res = a.isub(b); - if (res.cmpn(0) < 0) { - res.iadd(this.m); - } - return res; - }; - - Red.prototype.shl = function shl (a, num) { - this._verify1(a); - return this.imod(a.ushln(num)); - }; - - Red.prototype.imul = function imul (a, b) { - this._verify2(a, b); - return this.imod(a.imul(b)); - }; - - Red.prototype.mul = function mul (a, b) { - this._verify2(a, b); - return this.imod(a.mul(b)); - }; - - Red.prototype.isqr = function isqr (a) { - return this.imul(a, a.clone()); - }; - - Red.prototype.sqr = function sqr (a) { - return this.mul(a, a); - }; - - Red.prototype.sqrt = function sqrt (a) { - if (a.isZero()) return a.clone(); - - var mod3 = this.m.andln(3); - assert(mod3 % 2 === 1); - - // Fast case - if (mod3 === 3) { - var pow = this.m.add(new BN(1)).iushrn(2); - return this.pow(a, pow); - } - - // Tonelli-Shanks algorithm (Totally unoptimized and slow) - // - // Find Q and S, that Q * 2 ^ S = (P - 1) - var q = this.m.subn(1); - var s = 0; - while (!q.isZero() && q.andln(1) === 0) { - s++; - q.iushrn(1); - } - assert(!q.isZero()); - - var one = new BN(1).toRed(this); - var nOne = one.redNeg(); - - // Find quadratic non-residue - // NOTE: Max is such because of generalized Riemann hypothesis. - var lpow = this.m.subn(1).iushrn(1); - var z = this.m.bitLength(); - z = new BN(2 * z * z).toRed(this); - - while (this.pow(z, lpow).cmp(nOne) !== 0) { - z.redIAdd(nOne); - } - - var c = this.pow(z, q); - var r = this.pow(a, q.addn(1).iushrn(1)); - var t = this.pow(a, q); - var m = s; - while (t.cmp(one) !== 0) { - var tmp = t; - for (var i = 0; tmp.cmp(one) !== 0; i++) { - tmp = tmp.redSqr(); - } - assert(i < m); - var b = this.pow(c, new BN(1).iushln(m - i - 1)); - - r = r.redMul(b); - c = b.redSqr(); - t = t.redMul(c); - m = i; - } - - return r; - }; - - Red.prototype.invm = function invm (a) { - var inv = a._invmp(this.m); - if (inv.negative !== 0) { - inv.negative = 0; - return this.imod(inv).redNeg(); - } else { - return this.imod(inv); - } - }; - - Red.prototype.pow = function pow (a, num) { - if (num.isZero()) return new BN(1).toRed(this); - if (num.cmpn(1) === 0) return a.clone(); - - var windowSize = 4; - var wnd = new Array(1 << windowSize); - wnd[0] = new BN(1).toRed(this); - wnd[1] = a; - for (var i = 2; i < wnd.length; i++) { - wnd[i] = this.mul(wnd[i - 1], a); - } - - var res = wnd[0]; - var current = 0; - var currentLen = 0; - var start = num.bitLength() % 26; - if (start === 0) { - start = 26; - } - - for (i = num.length - 1; i >= 0; i--) { - var word = num.words[i]; - for (var j = start - 1; j >= 0; j--) { - var bit = (word >> j) & 1; - if (res !== wnd[0]) { - res = this.sqr(res); - } - - if (bit === 0 && current === 0) { - currentLen = 0; - continue; - } - - current <<= 1; - current |= bit; - currentLen++; - if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue; - - res = this.mul(res, wnd[current]); - currentLen = 0; - current = 0; - } - start = 26; - } - - return res; - }; - - Red.prototype.convertTo = function convertTo (num) { - var r = num.umod(this.m); - - return r === num ? r.clone() : r; - }; - - Red.prototype.convertFrom = function convertFrom (num) { - var res = num.clone(); - res.red = null; - return res; - }; - - // - // Montgomery method engine - // - - BN.mont = function mont (num) { - return new Mont(num); - }; - - function Mont (m) { - Red.call(this, m); - - this.shift = this.m.bitLength(); - if (this.shift % 26 !== 0) { - this.shift += 26 - (this.shift % 26); - } - - this.r = new BN(1).iushln(this.shift); - this.r2 = this.imod(this.r.sqr()); - this.rinv = this.r._invmp(this.m); - - this.minv = this.rinv.mul(this.r).isubn(1).div(this.m); - this.minv = this.minv.umod(this.r); - this.minv = this.r.sub(this.minv); - } - inherits(Mont, Red); - - Mont.prototype.convertTo = function convertTo (num) { - return this.imod(num.ushln(this.shift)); - }; - - Mont.prototype.convertFrom = function convertFrom (num) { - var r = this.imod(num.mul(this.rinv)); - r.red = null; - return r; - }; - - Mont.prototype.imul = function imul (a, b) { - if (a.isZero() || b.isZero()) { - a.words[0] = 0; - a.length = 1; - return a; - } - - var t = a.imul(b); - var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); - var u = t.isub(c).iushrn(this.shift); - var res = u; - - if (u.cmp(this.m) >= 0) { - res = u.isub(this.m); - } else if (u.cmpn(0) < 0) { - res = u.iadd(this.m); - } - - return res._forceRed(this); - }; - - Mont.prototype.mul = function mul (a, b) { - if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this); - - var t = a.mul(b); - var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); - var u = t.isub(c).iushrn(this.shift); - var res = u; - if (u.cmp(this.m) >= 0) { - res = u.isub(this.m); - } else if (u.cmpn(0) < 0) { - res = u.iadd(this.m); - } - - return res._forceRed(this); - }; - - Mont.prototype.invm = function invm (a) { - // (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R - var res = this.imod(a._invmp(this.m).mul(this.r2)); - return res._forceRed(this); - }; - })(module, commonjsGlobal); - }); - - var bn$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - 'default': bn, - __moduleExports: bn - }); - - /** - * @fileoverview - * BigInteger implementation of basic operations - * Wrapper of bn.js library (wwww.github.com/indutny/bn.js) - * @module biginteger/bn - * @private - */ - - /** - * @private - */ - class BigInteger$1 { - /** - * Get a BigInteger (input must be big endian for strings and arrays) - * @param {Number|String|Uint8Array} n - Value to convert - * @throws {Error} on undefined input - */ - constructor(n) { - if (n === undefined) { - throw new Error('Invalid BigInteger input'); - } - - this.value = new bn(n); - } - - clone() { - const clone = new BigInteger$1(null); - this.value.copy(clone.value); - return clone; - } - - /** - * BigInteger increment in place - */ - iinc() { - this.value.iadd(new bn(1)); - return this; - } - - /** - * BigInteger increment - * @returns {BigInteger} this + 1. - */ - inc() { - return this.clone().iinc(); - } - - /** - * BigInteger decrement in place - */ - idec() { - this.value.isub(new bn(1)); - return this; - } - - /** - * BigInteger decrement - * @returns {BigInteger} this - 1. - */ - dec() { - return this.clone().idec(); - } - - - /** - * BigInteger addition in place - * @param {BigInteger} x - Value to add - */ - iadd(x) { - this.value.iadd(x.value); - return this; - } - - /** - * BigInteger addition - * @param {BigInteger} x - Value to add - * @returns {BigInteger} this + x. - */ - add(x) { - return this.clone().iadd(x); - } - - /** - * BigInteger subtraction in place - * @param {BigInteger} x - Value to subtract - */ - isub(x) { - this.value.isub(x.value); - return this; - } - - /** - * BigInteger subtraction - * @param {BigInteger} x - Value to subtract - * @returns {BigInteger} this - x. - */ - sub(x) { - return this.clone().isub(x); - } - - /** - * BigInteger multiplication in place - * @param {BigInteger} x - Value to multiply - */ - imul(x) { - this.value.imul(x.value); - return this; - } - - /** - * BigInteger multiplication - * @param {BigInteger} x - Value to multiply - * @returns {BigInteger} this * x. - */ - mul(x) { - return this.clone().imul(x); - } - - /** - * Compute value modulo m, in place - * @param {BigInteger} m - Modulo - */ - imod(m) { - this.value = this.value.umod(m.value); - return this; - } - - /** - * Compute value modulo m - * @param {BigInteger} m - Modulo - * @returns {BigInteger} this mod m. - */ - mod(m) { - return this.clone().imod(m); - } - - /** - * Compute modular exponentiation - * Much faster than this.exp(e).mod(n) - * @param {BigInteger} e - Exponent - * @param {BigInteger} n - Modulo - * @returns {BigInteger} this ** e mod n. - */ - modExp(e, n) { - // We use either Montgomery or normal reduction context - // Montgomery requires coprime n and R (montogmery multiplier) - // bn.js picks R as power of 2, so n must be odd - const nred = n.isEven() ? bn.red(n.value) : bn.mont(n.value); - const x = this.clone(); - x.value = x.value.toRed(nred).redPow(e.value).fromRed(); - return x; - } - - /** - * Compute the inverse of this value modulo n - * Note: this and and n must be relatively prime - * @param {BigInteger} n - Modulo - * @returns {BigInteger} x such that this*x = 1 mod n - * @throws {Error} if the inverse does not exist - */ - modInv(n) { - // invm returns a wrong result if the inverse does not exist - if (!this.gcd(n).isOne()) { - throw new Error('Inverse does not exist'); - } - return new BigInteger$1(this.value.invm(n.value)); - } - - /** - * Compute greatest common divisor between this and n - * @param {BigInteger} n - Operand - * @returns {BigInteger} gcd - */ - gcd(n) { - return new BigInteger$1(this.value.gcd(n.value)); - } - - /** - * Shift this to the left by x, in place - * @param {BigInteger} x - Shift value - */ - ileftShift(x) { - this.value.ishln(x.value.toNumber()); - return this; - } - - /** - * Shift this to the left by x - * @param {BigInteger} x - Shift value - * @returns {BigInteger} this << x. - */ - leftShift(x) { - return this.clone().ileftShift(x); - } - - /** - * Shift this to the right by x, in place - * @param {BigInteger} x - Shift value - */ - irightShift(x) { - this.value.ishrn(x.value.toNumber()); - return this; - } - - /** - * Shift this to the right by x - * @param {BigInteger} x - Shift value - * @returns {BigInteger} this >> x. - */ - rightShift(x) { - return this.clone().irightShift(x); - } - - /** - * Whether this value is equal to x - * @param {BigInteger} x - * @returns {Boolean} - */ - equal(x) { - return this.value.eq(x.value); - } - - /** - * Whether this value is less than x - * @param {BigInteger} x - * @returns {Boolean} - */ - lt(x) { - return this.value.lt(x.value); - } - - /** - * Whether this value is less than or equal to x - * @param {BigInteger} x - * @returns {Boolean} - */ - lte(x) { - return this.value.lte(x.value); - } - - /** - * Whether this value is greater than x - * @param {BigInteger} x - * @returns {Boolean} - */ - gt(x) { - return this.value.gt(x.value); - } - - /** - * Whether this value is greater than or equal to x - * @param {BigInteger} x - * @returns {Boolean} - */ - gte(x) { - return this.value.gte(x.value); - } - - isZero() { - return this.value.isZero(); - } - - isOne() { - return this.value.eq(new bn(1)); - } - - isNegative() { - return this.value.isNeg(); - } - - isEven() { - return this.value.isEven(); - } - - abs() { - const res = this.clone(); - res.value = res.value.abs(); - return res; - } - - /** - * Get this value as a string - * @returns {String} this value. - */ - toString() { - return this.value.toString(); - } - - /** - * Get this value as an exact Number (max 53 bits) - * Fails if this value is too large - * @returns {Number} - */ - toNumber() { - return this.value.toNumber(); - } - - /** - * Get value of i-th bit - * @param {Number} i - Bit index - * @returns {Number} Bit value. - */ - getBit(i) { - return this.value.testn(i) ? 1 : 0; - } - - /** - * Compute bit length - * @returns {Number} Bit length. - */ - bitLength() { - return this.value.bitLength(); - } - - /** - * Compute byte length - * @returns {Number} Byte length. - */ - byteLength() { - return this.value.byteLength(); - } - - /** - * Get Uint8Array representation of this number - * @param {String} endian - Endianess of output array (defaults to 'be') - * @param {Number} length - Of output array - * @returns {Uint8Array} - */ - toUint8Array(endian = 'be', length) { - return this.value.toArrayLike(Uint8Array, endian, length); - } - } - - var bn_interface = /*#__PURE__*/Object.freeze({ - __proto__: null, - 'default': BigInteger$1 - }); - - var utils_1 = createCommonjsModule(function (module, exports) { - - var utils = exports; - - function toArray(msg, enc) { - if (Array.isArray(msg)) - return msg.slice(); - if (!msg) - return []; - var res = []; - if (typeof msg !== 'string') { - for (var i = 0; i < msg.length; i++) - res[i] = msg[i] | 0; - return res; - } - if (enc === 'hex') { - msg = msg.replace(/[^a-z0-9]+/ig, ''); - if (msg.length % 2 !== 0) - msg = '0' + msg; - for (var i = 0; i < msg.length; i += 2) - res.push(parseInt(msg[i] + msg[i + 1], 16)); - } else { - for (var i = 0; i < msg.length; i++) { - var c = msg.charCodeAt(i); - var hi = c >> 8; - var lo = c & 0xff; - if (hi) - res.push(hi, lo); - else - res.push(lo); - } - } - return res; - } - utils.toArray = toArray; - - function zero2(word) { - if (word.length === 1) - return '0' + word; - else - return word; - } - utils.zero2 = zero2; - - function toHex(msg) { - var res = ''; - for (var i = 0; i < msg.length; i++) - res += zero2(msg[i].toString(16)); - return res; - } - utils.toHex = toHex; - - utils.encode = function encode(arr, enc) { - if (enc === 'hex') - return toHex(arr); - else - return arr; - }; - }); - - var utils_1$1 = createCommonjsModule(function (module, exports) { - - var utils = exports; - - - - - utils.assert = minimalisticAssert; - utils.toArray = utils_1.toArray; - utils.zero2 = utils_1.zero2; - utils.toHex = utils_1.toHex; - utils.encode = utils_1.encode; - - // Represent num in a w-NAF form - function getNAF(num, w) { - var naf = []; - var ws = 1 << (w + 1); - var k = num.clone(); - while (k.cmpn(1) >= 0) { - var z; - if (k.isOdd()) { - var mod = k.andln(ws - 1); - if (mod > (ws >> 1) - 1) - z = (ws >> 1) - mod; - else - z = mod; - k.isubn(z); - } else { - z = 0; - } - naf.push(z); - - // Optimization, shift by word if possible - var shift = (k.cmpn(0) !== 0 && k.andln(ws - 1) === 0) ? (w + 1) : 1; - for (var i = 1; i < shift; i++) - naf.push(0); - k.iushrn(shift); - } - - return naf; - } - utils.getNAF = getNAF; - - // Represent k1, k2 in a Joint Sparse Form - function getJSF(k1, k2) { - var jsf = [ - [], - [] - ]; - - k1 = k1.clone(); - k2 = k2.clone(); - var d1 = 0; - var d2 = 0; - while (k1.cmpn(-d1) > 0 || k2.cmpn(-d2) > 0) { - - // First phase - var m14 = (k1.andln(3) + d1) & 3; - var m24 = (k2.andln(3) + d2) & 3; - if (m14 === 3) - m14 = -1; - if (m24 === 3) - m24 = -1; - var u1; - if ((m14 & 1) === 0) { - u1 = 0; - } else { - var m8 = (k1.andln(7) + d1) & 7; - if ((m8 === 3 || m8 === 5) && m24 === 2) - u1 = -m14; - else - u1 = m14; - } - jsf[0].push(u1); - - var u2; - if ((m24 & 1) === 0) { - u2 = 0; - } else { - var m8 = (k2.andln(7) + d2) & 7; - if ((m8 === 3 || m8 === 5) && m14 === 2) - u2 = -m24; - else - u2 = m24; - } - jsf[1].push(u2); - - // Second phase - if (2 * d1 === u1 + 1) - d1 = 1 - d1; - if (2 * d2 === u2 + 1) - d2 = 1 - d2; - k1.iushrn(1); - k2.iushrn(1); - } - - return jsf; - } - utils.getJSF = getJSF; - - function cachedProperty(obj, name, computer) { - var key = '_' + name; - obj.prototype[name] = function cachedProperty() { - return this[key] !== undefined ? this[key] : - this[key] = computer.call(this); - }; - } - utils.cachedProperty = cachedProperty; - - function parseBytes(bytes) { - return typeof bytes === 'string' ? utils.toArray(bytes, 'hex') : - bytes; - } - utils.parseBytes = parseBytes; - - function intFromLE(bytes) { - return new bn(bytes, 'hex', 'le'); - } - utils.intFromLE = intFromLE; - }); - - var r$1; - - var brorand = function rand(len) { - if (!r$1) - r$1 = new Rand(null); - - return r$1.generate(len); - }; - - function Rand(rand) { - this.rand = rand; - } - var Rand_1 = Rand; - - Rand.prototype.generate = function generate(len) { - return this._rand(len); - }; - - // Emulate crypto API using randy - Rand.prototype._rand = function _rand(n) { - if (this.rand.getBytes) - return this.rand.getBytes(n); - - var res = new Uint8Array(n); - for (var i = 0; i < res.length; i++) - res[i] = this.rand.getByte(); - return res; - }; - - if (typeof self === 'object') { - if (self.crypto && self.crypto.getRandomValues) { - // Modern browsers - Rand.prototype._rand = function _rand(n) { - var arr = new Uint8Array(n); - self.crypto.getRandomValues(arr); - return arr; - }; - } else if (self.msCrypto && self.msCrypto.getRandomValues) { - // IE - Rand.prototype._rand = function _rand(n) { - var arr = new Uint8Array(n); - self.msCrypto.getRandomValues(arr); - return arr; - }; - - // Safari's WebWorkers do not have `crypto` - } else if (typeof window === 'object') { - // Old junk - Rand.prototype._rand = function() { - throw new Error('Not implemented yet'); - }; - } - } else { - // Node.js or Web worker with no crypto support - try { - var crypto$2 = void('crypto'); - if (typeof crypto$2.randomBytes !== 'function') - throw new Error('Not supported'); - - Rand.prototype._rand = function _rand(n) { - return crypto$2.randomBytes(n); - }; - } catch (e) { - } - } - brorand.Rand = Rand_1; - - var getNAF = utils_1$1.getNAF; - var getJSF = utils_1$1.getJSF; - var assert$2 = utils_1$1.assert; - - function BaseCurve(type, conf) { - this.type = type; - this.p = new bn(conf.p, 16); - - // Use Montgomery, when there is no fast reduction for the prime - this.red = conf.prime ? bn.red(conf.prime) : bn.mont(this.p); - - // Useful for many curves - this.zero = new bn(0).toRed(this.red); - this.one = new bn(1).toRed(this.red); - this.two = new bn(2).toRed(this.red); - - // Curve configuration, optional - this.n = conf.n && new bn(conf.n, 16); - this.g = conf.g && this.pointFromJSON(conf.g, conf.gRed); - - // Temporary arrays - this._wnafT1 = new Array(4); - this._wnafT2 = new Array(4); - this._wnafT3 = new Array(4); - this._wnafT4 = new Array(4); - - // Generalized Greg Maxwell's trick - var adjustCount = this.n && this.p.div(this.n); - if (!adjustCount || adjustCount.cmpn(100) > 0) { - this.redN = null; - } else { - this._maxwellTrick = true; - this.redN = this.n.toRed(this.red); - } - } - var base = BaseCurve; - - BaseCurve.prototype.point = function point() { - throw new Error('Not implemented'); - }; - - BaseCurve.prototype.validate = function validate() { - throw new Error('Not implemented'); - }; - - BaseCurve.prototype._fixedNafMul = function _fixedNafMul(p, k) { - assert$2(p.precomputed); - var doubles = p._getDoubles(); - - var naf = getNAF(k, 1); - var I = (1 << (doubles.step + 1)) - (doubles.step % 2 === 0 ? 2 : 1); - I /= 3; - - // Translate into more windowed form - var repr = []; - for (var j = 0; j < naf.length; j += doubles.step) { - var nafW = 0; - for (var k = j + doubles.step - 1; k >= j; k--) - nafW = (nafW << 1) + naf[k]; - repr.push(nafW); - } - - var a = this.jpoint(null, null, null); - var b = this.jpoint(null, null, null); - for (var i = I; i > 0; i--) { - for (var j = 0; j < repr.length; j++) { - var nafW = repr[j]; - if (nafW === i) - b = b.mixedAdd(doubles.points[j]); - else if (nafW === -i) - b = b.mixedAdd(doubles.points[j].neg()); - } - a = a.add(b); - } - return a.toP(); - }; - - BaseCurve.prototype._wnafMul = function _wnafMul(p, k) { - var w = 4; - - // Precompute window - var nafPoints = p._getNAFPoints(w); - w = nafPoints.wnd; - var wnd = nafPoints.points; - - // Get NAF form - var naf = getNAF(k, w); - - // Add `this`*(N+1) for every w-NAF index - var acc = this.jpoint(null, null, null); - for (var i = naf.length - 1; i >= 0; i--) { - // Count zeroes - for (var k = 0; i >= 0 && naf[i] === 0; i--) - k++; - if (i >= 0) - k++; - acc = acc.dblp(k); - - if (i < 0) - break; - var z = naf[i]; - assert$2(z !== 0); - if (p.type === 'affine') { - // J +- P - if (z > 0) - acc = acc.mixedAdd(wnd[(z - 1) >> 1]); - else - acc = acc.mixedAdd(wnd[(-z - 1) >> 1].neg()); - } else { - // J +- J - if (z > 0) - acc = acc.add(wnd[(z - 1) >> 1]); - else - acc = acc.add(wnd[(-z - 1) >> 1].neg()); - } - } - return p.type === 'affine' ? acc.toP() : acc; - }; - - BaseCurve.prototype._wnafMulAdd = function _wnafMulAdd(defW, - points, - coeffs, - len, - jacobianResult) { - var wndWidth = this._wnafT1; - var wnd = this._wnafT2; - var naf = this._wnafT3; - - // Fill all arrays - var max = 0; - for (var i = 0; i < len; i++) { - var p = points[i]; - var nafPoints = p._getNAFPoints(defW); - wndWidth[i] = nafPoints.wnd; - wnd[i] = nafPoints.points; - } - - // Comb small window NAFs - for (var i = len - 1; i >= 1; i -= 2) { - var a = i - 1; - var b = i; - if (wndWidth[a] !== 1 || wndWidth[b] !== 1) { - naf[a] = getNAF(coeffs[a], wndWidth[a]); - naf[b] = getNAF(coeffs[b], wndWidth[b]); - max = Math.max(naf[a].length, max); - max = Math.max(naf[b].length, max); - continue; - } - - var comb = [ - points[a], /* 1 */ - null, /* 3 */ - null, /* 5 */ - points[b] /* 7 */ - ]; - - // Try to avoid Projective points, if possible - if (points[a].y.cmp(points[b].y) === 0) { - comb[1] = points[a].add(points[b]); - comb[2] = points[a].toJ().mixedAdd(points[b].neg()); - } else if (points[a].y.cmp(points[b].y.redNeg()) === 0) { - comb[1] = points[a].toJ().mixedAdd(points[b]); - comb[2] = points[a].add(points[b].neg()); - } else { - comb[1] = points[a].toJ().mixedAdd(points[b]); - comb[2] = points[a].toJ().mixedAdd(points[b].neg()); - } - - var index = [ - -3, /* -1 -1 */ - -1, /* -1 0 */ - -5, /* -1 1 */ - -7, /* 0 -1 */ - 0, /* 0 0 */ - 7, /* 0 1 */ - 5, /* 1 -1 */ - 1, /* 1 0 */ - 3 /* 1 1 */ - ]; - - var jsf = getJSF(coeffs[a], coeffs[b]); - max = Math.max(jsf[0].length, max); - naf[a] = new Array(max); - naf[b] = new Array(max); - for (var j = 0; j < max; j++) { - var ja = jsf[0][j] | 0; - var jb = jsf[1][j] | 0; - - naf[a][j] = index[(ja + 1) * 3 + (jb + 1)]; - naf[b][j] = 0; - wnd[a] = comb; - } - } - - var acc = this.jpoint(null, null, null); - var tmp = this._wnafT4; - for (var i = max; i >= 0; i--) { - var k = 0; - - while (i >= 0) { - var zero = true; - for (var j = 0; j < len; j++) { - tmp[j] = naf[j][i] | 0; - if (tmp[j] !== 0) - zero = false; - } - if (!zero) - break; - k++; - i--; - } - if (i >= 0) - k++; - acc = acc.dblp(k); - if (i < 0) - break; - - for (var j = 0; j < len; j++) { - var z = tmp[j]; - var p; - if (z === 0) - continue; - else if (z > 0) - p = wnd[j][(z - 1) >> 1]; - else if (z < 0) - p = wnd[j][(-z - 1) >> 1].neg(); - - if (p.type === 'affine') - acc = acc.mixedAdd(p); - else - acc = acc.add(p); - } - } - // Zeroify references - for (var i = 0; i < len; i++) - wnd[i] = null; - - if (jacobianResult) - return acc; - else - return acc.toP(); - }; - - function BasePoint(curve, type) { - this.curve = curve; - this.type = type; - this.precomputed = null; - } - BaseCurve.BasePoint = BasePoint; - - BasePoint.prototype.eq = function eq(/*other*/) { - throw new Error('Not implemented'); - }; - - BasePoint.prototype.validate = function validate() { - return this.curve.validate(this); - }; - - BaseCurve.prototype.decodePoint = function decodePoint(bytes, enc) { - bytes = utils_1$1.toArray(bytes, enc); - - var len = this.p.byteLength(); - - // uncompressed, hybrid-odd, hybrid-even - if ((bytes[0] === 0x04 || bytes[0] === 0x06 || bytes[0] === 0x07) && - bytes.length - 1 === 2 * len) { - if (bytes[0] === 0x06) - assert$2(bytes[bytes.length - 1] % 2 === 0); - else if (bytes[0] === 0x07) - assert$2(bytes[bytes.length - 1] % 2 === 1); - - var res = this.point(bytes.slice(1, 1 + len), - bytes.slice(1 + len, 1 + 2 * len)); - - return res; - } else if ((bytes[0] === 0x02 || bytes[0] === 0x03) && - bytes.length - 1 === len) { - return this.pointFromX(bytes.slice(1, 1 + len), bytes[0] === 0x03); - } - throw new Error('Unknown point format'); - }; - - BasePoint.prototype.encodeCompressed = function encodeCompressed(enc) { - return this.encode(enc, true); - }; - - BasePoint.prototype._encode = function _encode(compact) { - var len = this.curve.p.byteLength(); - var x = this.getX().toArray('be', len); - - if (compact) - return [ this.getY().isEven() ? 0x02 : 0x03 ].concat(x); - - return [ 0x04 ].concat(x, this.getY().toArray('be', len)) ; - }; - - BasePoint.prototype.encode = function encode(enc, compact) { - return utils_1$1.encode(this._encode(compact), enc); - }; - - BasePoint.prototype.precompute = function precompute(power) { - if (this.precomputed) - return this; - - var precomputed = { - doubles: null, - naf: null, - beta: null - }; - precomputed.naf = this._getNAFPoints(8); - precomputed.doubles = this._getDoubles(4, power); - precomputed.beta = this._getBeta(); - this.precomputed = precomputed; - - return this; - }; - - BasePoint.prototype._hasDoubles = function _hasDoubles(k) { - if (!this.precomputed) - return false; - - var doubles = this.precomputed.doubles; - if (!doubles) - return false; - - return doubles.points.length >= Math.ceil((k.bitLength() + 1) / doubles.step); - }; - - BasePoint.prototype._getDoubles = function _getDoubles(step, power) { - if (this.precomputed && this.precomputed.doubles) - return this.precomputed.doubles; - - var doubles = [ this ]; - var acc = this; - for (var i = 0; i < power; i += step) { - for (var j = 0; j < step; j++) - acc = acc.dbl(); - doubles.push(acc); - } - return { - step: step, - points: doubles - }; - }; - - BasePoint.prototype._getNAFPoints = function _getNAFPoints(wnd) { - if (this.precomputed && this.precomputed.naf) - return this.precomputed.naf; - - var res = [ this ]; - var max = (1 << wnd) - 1; - var dbl = max === 1 ? null : this.dbl(); - for (var i = 1; i < max; i++) - res[i] = res[i - 1].add(dbl); - return { - wnd: wnd, - points: res - }; - }; - - BasePoint.prototype._getBeta = function _getBeta() { - return null; - }; - - BasePoint.prototype.dblp = function dblp(k) { - var r = this; - for (var i = 0; i < k; i++) - r = r.dbl(); - return r; - }; - - var assert$3 = utils_1$1.assert; - - function ShortCurve(conf) { - base.call(this, 'short', conf); - - this.a = new bn(conf.a, 16).toRed(this.red); - this.b = new bn(conf.b, 16).toRed(this.red); - this.tinv = this.two.redInvm(); - - this.zeroA = this.a.fromRed().cmpn(0) === 0; - this.threeA = this.a.fromRed().sub(this.p).cmpn(-3) === 0; - - // If the curve is endomorphic, precalculate beta and lambda - this.endo = this._getEndomorphism(conf); - this._endoWnafT1 = new Array(4); - this._endoWnafT2 = new Array(4); - } - inherits_browser(ShortCurve, base); - var short_1 = ShortCurve; - - ShortCurve.prototype._getEndomorphism = function _getEndomorphism(conf) { - // No efficient endomorphism - if (!this.zeroA || !this.g || !this.n || this.p.modn(3) !== 1) - return; - - // Compute beta and lambda, that lambda * P = (beta * Px; Py) - var beta; - var lambda; - if (conf.beta) { - beta = new bn(conf.beta, 16).toRed(this.red); - } else { - var betas = this._getEndoRoots(this.p); - // Choose the smallest beta - beta = betas[0].cmp(betas[1]) < 0 ? betas[0] : betas[1]; - beta = beta.toRed(this.red); - } - if (conf.lambda) { - lambda = new bn(conf.lambda, 16); - } else { - // Choose the lambda that is matching selected beta - var lambdas = this._getEndoRoots(this.n); - if (this.g.mul(lambdas[0]).x.cmp(this.g.x.redMul(beta)) === 0) { - lambda = lambdas[0]; - } else { - lambda = lambdas[1]; - assert$3(this.g.mul(lambda).x.cmp(this.g.x.redMul(beta)) === 0); - } - } - - // Get basis vectors, used for balanced length-two representation - var basis; - if (conf.basis) { - basis = conf.basis.map(function(vec) { - return { - a: new bn(vec.a, 16), - b: new bn(vec.b, 16) - }; - }); - } else { - basis = this._getEndoBasis(lambda); - } - - return { - beta: beta, - lambda: lambda, - basis: basis - }; - }; - - ShortCurve.prototype._getEndoRoots = function _getEndoRoots(num) { - // Find roots of for x^2 + x + 1 in F - // Root = (-1 +- Sqrt(-3)) / 2 - // - var red = num === this.p ? this.red : bn.mont(num); - var tinv = new bn(2).toRed(red).redInvm(); - var ntinv = tinv.redNeg(); - - var s = new bn(3).toRed(red).redNeg().redSqrt().redMul(tinv); - - var l1 = ntinv.redAdd(s).fromRed(); - var l2 = ntinv.redSub(s).fromRed(); - return [ l1, l2 ]; - }; - - ShortCurve.prototype._getEndoBasis = function _getEndoBasis(lambda) { - // aprxSqrt >= sqrt(this.n) - var aprxSqrt = this.n.ushrn(Math.floor(this.n.bitLength() / 2)); - - // 3.74 - // Run EGCD, until r(L + 1) < aprxSqrt - var u = lambda; - var v = this.n.clone(); - var x1 = new bn(1); - var y1 = new bn(0); - var x2 = new bn(0); - var y2 = new bn(1); - - // NOTE: all vectors are roots of: a + b * lambda = 0 (mod n) - var a0; - var b0; - // First vector - var a1; - var b1; - // Second vector - var a2; - var b2; - - var prevR; - var i = 0; - var r; - var x; - while (u.cmpn(0) !== 0) { - var q = v.div(u); - r = v.sub(q.mul(u)); - x = x2.sub(q.mul(x1)); - var y = y2.sub(q.mul(y1)); - - if (!a1 && r.cmp(aprxSqrt) < 0) { - a0 = prevR.neg(); - b0 = x1; - a1 = r.neg(); - b1 = x; - } else if (a1 && ++i === 2) { - break; - } - prevR = r; - - v = u; - u = r; - x2 = x1; - x1 = x; - y2 = y1; - y1 = y; - } - a2 = r.neg(); - b2 = x; - - var len1 = a1.sqr().add(b1.sqr()); - var len2 = a2.sqr().add(b2.sqr()); - if (len2.cmp(len1) >= 0) { - a2 = a0; - b2 = b0; - } - - // Normalize signs - if (a1.negative) { - a1 = a1.neg(); - b1 = b1.neg(); - } - if (a2.negative) { - a2 = a2.neg(); - b2 = b2.neg(); - } - - return [ - { a: a1, b: b1 }, - { a: a2, b: b2 } - ]; - }; - - ShortCurve.prototype._endoSplit = function _endoSplit(k) { - var basis = this.endo.basis; - var v1 = basis[0]; - var v2 = basis[1]; - - var c1 = v2.b.mul(k).divRound(this.n); - var c2 = v1.b.neg().mul(k).divRound(this.n); - - var p1 = c1.mul(v1.a); - var p2 = c2.mul(v2.a); - var q1 = c1.mul(v1.b); - var q2 = c2.mul(v2.b); - - // Calculate answer - var k1 = k.sub(p1).sub(p2); - var k2 = q1.add(q2).neg(); - return { k1: k1, k2: k2 }; - }; - - ShortCurve.prototype.pointFromX = function pointFromX(x, odd) { - x = new bn(x, 16); - if (!x.red) - x = x.toRed(this.red); - - var y2 = x.redSqr().redMul(x).redIAdd(x.redMul(this.a)).redIAdd(this.b); - var y = y2.redSqrt(); - if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) - throw new Error('invalid point'); - - // XXX Is there any way to tell if the number is odd without converting it - // to non-red form? - var isOdd = y.fromRed().isOdd(); - if (odd && !isOdd || !odd && isOdd) - y = y.redNeg(); - - return this.point(x, y); - }; - - ShortCurve.prototype.validate = function validate(point) { - if (point.inf) - return true; - - var x = point.x; - var y = point.y; - - var ax = this.a.redMul(x); - var rhs = x.redSqr().redMul(x).redIAdd(ax).redIAdd(this.b); - return y.redSqr().redISub(rhs).cmpn(0) === 0; - }; - - ShortCurve.prototype._endoWnafMulAdd = - function _endoWnafMulAdd(points, coeffs, jacobianResult) { - var npoints = this._endoWnafT1; - var ncoeffs = this._endoWnafT2; - for (var i = 0; i < points.length; i++) { - var split = this._endoSplit(coeffs[i]); - var p = points[i]; - var beta = p._getBeta(); - - if (split.k1.negative) { - split.k1.ineg(); - p = p.neg(true); - } - if (split.k2.negative) { - split.k2.ineg(); - beta = beta.neg(true); - } - - npoints[i * 2] = p; - npoints[i * 2 + 1] = beta; - ncoeffs[i * 2] = split.k1; - ncoeffs[i * 2 + 1] = split.k2; - } - var res = this._wnafMulAdd(1, npoints, ncoeffs, i * 2, jacobianResult); - - // Clean-up references to points and coefficients - for (var j = 0; j < i * 2; j++) { - npoints[j] = null; - ncoeffs[j] = null; - } - return res; - }; - - function Point(curve, x, y, isRed) { - base.BasePoint.call(this, curve, 'affine'); - if (x === null && y === null) { - this.x = null; - this.y = null; - this.inf = true; - } else { - this.x = new bn(x, 16); - this.y = new bn(y, 16); - // Force redgomery representation when loading from JSON - if (isRed) { - this.x.forceRed(this.curve.red); - this.y.forceRed(this.curve.red); - } - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.y.red) - this.y = this.y.toRed(this.curve.red); - this.inf = false; - } - } - inherits_browser(Point, base.BasePoint); - - ShortCurve.prototype.point = function point(x, y, isRed) { - return new Point(this, x, y, isRed); - }; - - ShortCurve.prototype.pointFromJSON = function pointFromJSON(obj, red) { - return Point.fromJSON(this, obj, red); - }; - - Point.prototype._getBeta = function _getBeta() { - if (!this.curve.endo) - return; - - var pre = this.precomputed; - if (pre && pre.beta) - return pre.beta; - - var beta = this.curve.point(this.x.redMul(this.curve.endo.beta), this.y); - if (pre) { - var curve = this.curve; - var endoMul = function(p) { - return curve.point(p.x.redMul(curve.endo.beta), p.y); - }; - pre.beta = beta; - beta.precomputed = { - beta: null, - naf: pre.naf && { - wnd: pre.naf.wnd, - points: pre.naf.points.map(endoMul) - }, - doubles: pre.doubles && { - step: pre.doubles.step, - points: pre.doubles.points.map(endoMul) - } - }; - } - return beta; - }; - - Point.prototype.toJSON = function toJSON() { - if (!this.precomputed) - return [ this.x, this.y ]; - - return [ this.x, this.y, this.precomputed && { - doubles: this.precomputed.doubles && { - step: this.precomputed.doubles.step, - points: this.precomputed.doubles.points.slice(1) - }, - naf: this.precomputed.naf && { - wnd: this.precomputed.naf.wnd, - points: this.precomputed.naf.points.slice(1) - } - } ]; - }; - - Point.fromJSON = function fromJSON(curve, obj, red) { - if (typeof obj === 'string') - obj = JSON.parse(obj); - var res = curve.point(obj[0], obj[1], red); - if (!obj[2]) - return res; - - function obj2point(obj) { - return curve.point(obj[0], obj[1], red); - } - - var pre = obj[2]; - res.precomputed = { - beta: null, - doubles: pre.doubles && { - step: pre.doubles.step, - points: [ res ].concat(pre.doubles.points.map(obj2point)) - }, - naf: pre.naf && { - wnd: pre.naf.wnd, - points: [ res ].concat(pre.naf.points.map(obj2point)) - } - }; - return res; - }; - - Point.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; - }; - - Point.prototype.isInfinity = function isInfinity() { - return this.inf; - }; - - Point.prototype.add = function add(p) { - // O + P = P - if (this.inf) - return p; - - // P + O = P - if (p.inf) - return this; - - // P + P = 2P - if (this.eq(p)) - return this.dbl(); - - // P + (-P) = O - if (this.neg().eq(p)) - return this.curve.point(null, null); - - // P + Q = O - if (this.x.cmp(p.x) === 0) - return this.curve.point(null, null); - - var c = this.y.redSub(p.y); - if (c.cmpn(0) !== 0) - c = c.redMul(this.x.redSub(p.x).redInvm()); - var nx = c.redSqr().redISub(this.x).redISub(p.x); - var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); - return this.curve.point(nx, ny); - }; - - Point.prototype.dbl = function dbl() { - if (this.inf) - return this; - - // 2P = O - var ys1 = this.y.redAdd(this.y); - if (ys1.cmpn(0) === 0) - return this.curve.point(null, null); - - var a = this.curve.a; - - var x2 = this.x.redSqr(); - var dyinv = ys1.redInvm(); - var c = x2.redAdd(x2).redIAdd(x2).redIAdd(a).redMul(dyinv); - - var nx = c.redSqr().redISub(this.x.redAdd(this.x)); - var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); - return this.curve.point(nx, ny); - }; - - Point.prototype.getX = function getX() { - return this.x.fromRed(); - }; - - Point.prototype.getY = function getY() { - return this.y.fromRed(); - }; - - Point.prototype.mul = function mul(k) { - k = new bn(k, 16); - if (this.isInfinity()) - return this; - else if (this._hasDoubles(k)) - return this.curve._fixedNafMul(this, k); - else if (this.curve.endo) - return this.curve._endoWnafMulAdd([ this ], [ k ]); - else - return this.curve._wnafMul(this, k); - }; - - Point.prototype.mulAdd = function mulAdd(k1, p2, k2) { - var points = [ this, p2 ]; - var coeffs = [ k1, k2 ]; - if (this.curve.endo) - return this.curve._endoWnafMulAdd(points, coeffs); - else - return this.curve._wnafMulAdd(1, points, coeffs, 2); - }; - - Point.prototype.jmulAdd = function jmulAdd(k1, p2, k2) { - var points = [ this, p2 ]; - var coeffs = [ k1, k2 ]; - if (this.curve.endo) - return this.curve._endoWnafMulAdd(points, coeffs, true); - else - return this.curve._wnafMulAdd(1, points, coeffs, 2, true); - }; - - Point.prototype.eq = function eq(p) { - return this === p || - this.inf === p.inf && - (this.inf || this.x.cmp(p.x) === 0 && this.y.cmp(p.y) === 0); - }; - - Point.prototype.neg = function neg(_precompute) { - if (this.inf) - return this; - - var res = this.curve.point(this.x, this.y.redNeg()); - if (_precompute && this.precomputed) { - var pre = this.precomputed; - var negate = function(p) { - return p.neg(); - }; - res.precomputed = { - naf: pre.naf && { - wnd: pre.naf.wnd, - points: pre.naf.points.map(negate) - }, - doubles: pre.doubles && { - step: pre.doubles.step, - points: pre.doubles.points.map(negate) - } - }; - } - return res; - }; - - Point.prototype.toJ = function toJ() { - if (this.inf) - return this.curve.jpoint(null, null, null); - - var res = this.curve.jpoint(this.x, this.y, this.curve.one); - return res; - }; - - function JPoint(curve, x, y, z) { - base.BasePoint.call(this, curve, 'jacobian'); - if (x === null && y === null && z === null) { - this.x = this.curve.one; - this.y = this.curve.one; - this.z = new bn(0); - } else { - this.x = new bn(x, 16); - this.y = new bn(y, 16); - this.z = new bn(z, 16); - } - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.y.red) - this.y = this.y.toRed(this.curve.red); - if (!this.z.red) - this.z = this.z.toRed(this.curve.red); - - this.zOne = this.z === this.curve.one; - } - inherits_browser(JPoint, base.BasePoint); - - ShortCurve.prototype.jpoint = function jpoint(x, y, z) { - return new JPoint(this, x, y, z); - }; - - JPoint.prototype.toP = function toP() { - if (this.isInfinity()) - return this.curve.point(null, null); - - var zinv = this.z.redInvm(); - var zinv2 = zinv.redSqr(); - var ax = this.x.redMul(zinv2); - var ay = this.y.redMul(zinv2).redMul(zinv); - - return this.curve.point(ax, ay); - }; - - JPoint.prototype.neg = function neg() { - return this.curve.jpoint(this.x, this.y.redNeg(), this.z); - }; - - JPoint.prototype.add = function add(p) { - // O + P = P - if (this.isInfinity()) - return p; - - // P + O = P - if (p.isInfinity()) - return this; - - // 12M + 4S + 7A - var pz2 = p.z.redSqr(); - var z2 = this.z.redSqr(); - var u1 = this.x.redMul(pz2); - var u2 = p.x.redMul(z2); - var s1 = this.y.redMul(pz2.redMul(p.z)); - var s2 = p.y.redMul(z2.redMul(this.z)); - - var h = u1.redSub(u2); - var r = s1.redSub(s2); - if (h.cmpn(0) === 0) { - if (r.cmpn(0) !== 0) - return this.curve.jpoint(null, null, null); - else - return this.dbl(); - } - - var h2 = h.redSqr(); - var h3 = h2.redMul(h); - var v = u1.redMul(h2); - - var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); - var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); - var nz = this.z.redMul(p.z).redMul(h); - - return this.curve.jpoint(nx, ny, nz); - }; - - JPoint.prototype.mixedAdd = function mixedAdd(p) { - // O + P = P - if (this.isInfinity()) - return p.toJ(); - - // P + O = P - if (p.isInfinity()) - return this; - - // 8M + 3S + 7A - var z2 = this.z.redSqr(); - var u1 = this.x; - var u2 = p.x.redMul(z2); - var s1 = this.y; - var s2 = p.y.redMul(z2).redMul(this.z); - - var h = u1.redSub(u2); - var r = s1.redSub(s2); - if (h.cmpn(0) === 0) { - if (r.cmpn(0) !== 0) - return this.curve.jpoint(null, null, null); - else - return this.dbl(); - } - - var h2 = h.redSqr(); - var h3 = h2.redMul(h); - var v = u1.redMul(h2); - - var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); - var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); - var nz = this.z.redMul(h); - - return this.curve.jpoint(nx, ny, nz); - }; - - JPoint.prototype.dblp = function dblp(pow) { - if (pow === 0) - return this; - if (this.isInfinity()) - return this; - if (!pow) - return this.dbl(); - - if (this.curve.zeroA || this.curve.threeA) { - var r = this; - for (var i = 0; i < pow; i++) - r = r.dbl(); - return r; - } - - // 1M + 2S + 1A + N * (4S + 5M + 8A) - // N = 1 => 6M + 6S + 9A - var a = this.curve.a; - var tinv = this.curve.tinv; - - var jx = this.x; - var jy = this.y; - var jz = this.z; - var jz4 = jz.redSqr().redSqr(); - - // Reuse results - var jyd = jy.redAdd(jy); - for (var i = 0; i < pow; i++) { - var jx2 = jx.redSqr(); - var jyd2 = jyd.redSqr(); - var jyd4 = jyd2.redSqr(); - var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); - - var t1 = jx.redMul(jyd2); - var nx = c.redSqr().redISub(t1.redAdd(t1)); - var t2 = t1.redISub(nx); - var dny = c.redMul(t2); - dny = dny.redIAdd(dny).redISub(jyd4); - var nz = jyd.redMul(jz); - if (i + 1 < pow) - jz4 = jz4.redMul(jyd4); - - jx = nx; - jz = nz; - jyd = dny; - } - - return this.curve.jpoint(jx, jyd.redMul(tinv), jz); - }; - - JPoint.prototype.dbl = function dbl() { - if (this.isInfinity()) - return this; - - if (this.curve.zeroA) - return this._zeroDbl(); - else if (this.curve.threeA) - return this._threeDbl(); - else - return this._dbl(); - }; - - JPoint.prototype._zeroDbl = function _zeroDbl() { - var nx; - var ny; - var nz; - // Z = 1 - if (this.zOne) { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html - // #doubling-mdbl-2007-bl - // 1M + 5S + 14A - - // XX = X1^2 - var xx = this.x.redSqr(); - // YY = Y1^2 - var yy = this.y.redSqr(); - // YYYY = YY^2 - var yyyy = yy.redSqr(); - // S = 2 * ((X1 + YY)^2 - XX - YYYY) - var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); - s = s.redIAdd(s); - // M = 3 * XX + a; a = 0 - var m = xx.redAdd(xx).redIAdd(xx); - // T = M ^ 2 - 2*S - var t = m.redSqr().redISub(s).redISub(s); - - // 8 * YYYY - var yyyy8 = yyyy.redIAdd(yyyy); - yyyy8 = yyyy8.redIAdd(yyyy8); - yyyy8 = yyyy8.redIAdd(yyyy8); - - // X3 = T - nx = t; - // Y3 = M * (S - T) - 8 * YYYY - ny = m.redMul(s.redISub(t)).redISub(yyyy8); - // Z3 = 2*Y1 - nz = this.y.redAdd(this.y); - } else { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html - // #doubling-dbl-2009-l - // 2M + 5S + 13A - - // A = X1^2 - var a = this.x.redSqr(); - // B = Y1^2 - var b = this.y.redSqr(); - // C = B^2 - var c = b.redSqr(); - // D = 2 * ((X1 + B)^2 - A - C) - var d = this.x.redAdd(b).redSqr().redISub(a).redISub(c); - d = d.redIAdd(d); - // E = 3 * A - var e = a.redAdd(a).redIAdd(a); - // F = E^2 - var f = e.redSqr(); - - // 8 * C - var c8 = c.redIAdd(c); - c8 = c8.redIAdd(c8); - c8 = c8.redIAdd(c8); - - // X3 = F - 2 * D - nx = f.redISub(d).redISub(d); - // Y3 = E * (D - X3) - 8 * C - ny = e.redMul(d.redISub(nx)).redISub(c8); - // Z3 = 2 * Y1 * Z1 - nz = this.y.redMul(this.z); - nz = nz.redIAdd(nz); - } - - return this.curve.jpoint(nx, ny, nz); - }; - - JPoint.prototype._threeDbl = function _threeDbl() { - var nx; - var ny; - var nz; - // Z = 1 - if (this.zOne) { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html - // #doubling-mdbl-2007-bl - // 1M + 5S + 15A - - // XX = X1^2 - var xx = this.x.redSqr(); - // YY = Y1^2 - var yy = this.y.redSqr(); - // YYYY = YY^2 - var yyyy = yy.redSqr(); - // S = 2 * ((X1 + YY)^2 - XX - YYYY) - var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); - s = s.redIAdd(s); - // M = 3 * XX + a - var m = xx.redAdd(xx).redIAdd(xx).redIAdd(this.curve.a); - // T = M^2 - 2 * S - var t = m.redSqr().redISub(s).redISub(s); - // X3 = T - nx = t; - // Y3 = M * (S - T) - 8 * YYYY - var yyyy8 = yyyy.redIAdd(yyyy); - yyyy8 = yyyy8.redIAdd(yyyy8); - yyyy8 = yyyy8.redIAdd(yyyy8); - ny = m.redMul(s.redISub(t)).redISub(yyyy8); - // Z3 = 2 * Y1 - nz = this.y.redAdd(this.y); - } else { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b - // 3M + 5S - - // delta = Z1^2 - var delta = this.z.redSqr(); - // gamma = Y1^2 - var gamma = this.y.redSqr(); - // beta = X1 * gamma - var beta = this.x.redMul(gamma); - // alpha = 3 * (X1 - delta) * (X1 + delta) - var alpha = this.x.redSub(delta).redMul(this.x.redAdd(delta)); - alpha = alpha.redAdd(alpha).redIAdd(alpha); - // X3 = alpha^2 - 8 * beta - var beta4 = beta.redIAdd(beta); - beta4 = beta4.redIAdd(beta4); - var beta8 = beta4.redAdd(beta4); - nx = alpha.redSqr().redISub(beta8); - // Z3 = (Y1 + Z1)^2 - gamma - delta - nz = this.y.redAdd(this.z).redSqr().redISub(gamma).redISub(delta); - // Y3 = alpha * (4 * beta - X3) - 8 * gamma^2 - var ggamma8 = gamma.redSqr(); - ggamma8 = ggamma8.redIAdd(ggamma8); - ggamma8 = ggamma8.redIAdd(ggamma8); - ggamma8 = ggamma8.redIAdd(ggamma8); - ny = alpha.redMul(beta4.redISub(nx)).redISub(ggamma8); - } - - return this.curve.jpoint(nx, ny, nz); - }; - - JPoint.prototype._dbl = function _dbl() { - var a = this.curve.a; - - // 4M + 6S + 10A - var jx = this.x; - var jy = this.y; - var jz = this.z; - var jz4 = jz.redSqr().redSqr(); - - var jx2 = jx.redSqr(); - var jy2 = jy.redSqr(); - - var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); - - var jxd4 = jx.redAdd(jx); - jxd4 = jxd4.redIAdd(jxd4); - var t1 = jxd4.redMul(jy2); - var nx = c.redSqr().redISub(t1.redAdd(t1)); - var t2 = t1.redISub(nx); - - var jyd8 = jy2.redSqr(); - jyd8 = jyd8.redIAdd(jyd8); - jyd8 = jyd8.redIAdd(jyd8); - jyd8 = jyd8.redIAdd(jyd8); - var ny = c.redMul(t2).redISub(jyd8); - var nz = jy.redAdd(jy).redMul(jz); - - return this.curve.jpoint(nx, ny, nz); - }; - - JPoint.prototype.trpl = function trpl() { - if (!this.curve.zeroA) - return this.dbl().add(this); - - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#tripling-tpl-2007-bl - // 5M + 10S + ... - - // XX = X1^2 - var xx = this.x.redSqr(); - // YY = Y1^2 - var yy = this.y.redSqr(); - // ZZ = Z1^2 - var zz = this.z.redSqr(); - // YYYY = YY^2 - var yyyy = yy.redSqr(); - // M = 3 * XX + a * ZZ2; a = 0 - var m = xx.redAdd(xx).redIAdd(xx); - // MM = M^2 - var mm = m.redSqr(); - // E = 6 * ((X1 + YY)^2 - XX - YYYY) - MM - var e = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); - e = e.redIAdd(e); - e = e.redAdd(e).redIAdd(e); - e = e.redISub(mm); - // EE = E^2 - var ee = e.redSqr(); - // T = 16*YYYY - var t = yyyy.redIAdd(yyyy); - t = t.redIAdd(t); - t = t.redIAdd(t); - t = t.redIAdd(t); - // U = (M + E)^2 - MM - EE - T - var u = m.redIAdd(e).redSqr().redISub(mm).redISub(ee).redISub(t); - // X3 = 4 * (X1 * EE - 4 * YY * U) - var yyu4 = yy.redMul(u); - yyu4 = yyu4.redIAdd(yyu4); - yyu4 = yyu4.redIAdd(yyu4); - var nx = this.x.redMul(ee).redISub(yyu4); - nx = nx.redIAdd(nx); - nx = nx.redIAdd(nx); - // Y3 = 8 * Y1 * (U * (T - U) - E * EE) - var ny = this.y.redMul(u.redMul(t.redISub(u)).redISub(e.redMul(ee))); - ny = ny.redIAdd(ny); - ny = ny.redIAdd(ny); - ny = ny.redIAdd(ny); - // Z3 = (Z1 + E)^2 - ZZ - EE - var nz = this.z.redAdd(e).redSqr().redISub(zz).redISub(ee); - - return this.curve.jpoint(nx, ny, nz); - }; - - JPoint.prototype.mul = function mul(k, kbase) { - k = new bn(k, kbase); - - return this.curve._wnafMul(this, k); - }; - - JPoint.prototype.eq = function eq(p) { - if (p.type === 'affine') - return this.eq(p.toJ()); - - if (this === p) - return true; - - // x1 * z2^2 == x2 * z1^2 - var z2 = this.z.redSqr(); - var pz2 = p.z.redSqr(); - if (this.x.redMul(pz2).redISub(p.x.redMul(z2)).cmpn(0) !== 0) - return false; - - // y1 * z2^3 == y2 * z1^3 - var z3 = z2.redMul(this.z); - var pz3 = pz2.redMul(p.z); - return this.y.redMul(pz3).redISub(p.y.redMul(z3)).cmpn(0) === 0; - }; - - JPoint.prototype.eqXToP = function eqXToP(x) { - var zs = this.z.redSqr(); - var rx = x.toRed(this.curve.red).redMul(zs); - if (this.x.cmp(rx) === 0) - return true; - - var xc = x.clone(); - var t = this.curve.redN.redMul(zs); - for (;;) { - xc.iadd(this.curve.n); - if (xc.cmp(this.curve.p) >= 0) - return false; - - rx.redIAdd(t); - if (this.x.cmp(rx) === 0) - return true; - } - }; - - JPoint.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; - }; - - JPoint.prototype.isInfinity = function isInfinity() { - // XXX This code assumes that zero is always zero in red - return this.z.cmpn(0) === 0; - }; - - function MontCurve(conf) { - base.call(this, 'mont', conf); - - this.a = new bn(conf.a, 16).toRed(this.red); - this.b = new bn(conf.b, 16).toRed(this.red); - this.i4 = new bn(4).toRed(this.red).redInvm(); - this.two = new bn(2).toRed(this.red); - // Note: this implementation is according to the original paper - // by P. Montgomery, NOT the one by D. J. Bernstein. - this.a24 = this.i4.redMul(this.a.redAdd(this.two)); - } - inherits_browser(MontCurve, base); - var mont = MontCurve; - - MontCurve.prototype.validate = function validate(point) { - var x = point.normalize().x; - var x2 = x.redSqr(); - var rhs = x2.redMul(x).redAdd(x2.redMul(this.a)).redAdd(x); - var y = rhs.redSqrt(); - - return y.redSqr().cmp(rhs) === 0; - }; - - function Point$1(curve, x, z) { - base.BasePoint.call(this, curve, 'projective'); - if (x === null && z === null) { - this.x = this.curve.one; - this.z = this.curve.zero; - } else { - this.x = new bn(x, 16); - this.z = new bn(z, 16); - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.z.red) - this.z = this.z.toRed(this.curve.red); - } - } - inherits_browser(Point$1, base.BasePoint); - - MontCurve.prototype.decodePoint = function decodePoint(bytes, enc) { - var bytes = utils_1$1.toArray(bytes, enc); - - // TODO Curve448 - // Montgomery curve points must be represented in the compressed format - // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B - if (bytes.length === 33 && bytes[0] === 0x40) - bytes = bytes.slice(1, 33).reverse(); // point must be little-endian - if (bytes.length !== 32) - throw new Error('Unknown point compression format'); - return this.point(bytes, 1); - }; - - MontCurve.prototype.point = function point(x, z) { - return new Point$1(this, x, z); - }; - - MontCurve.prototype.pointFromJSON = function pointFromJSON(obj) { - return Point$1.fromJSON(this, obj); - }; - - Point$1.prototype.precompute = function precompute() { - // No-op - }; - - Point$1.prototype._encode = function _encode(compact) { - var len = this.curve.p.byteLength(); - - // Note: the output should always be little-endian - // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-02#appendix-B - if (compact) { - return [ 0x40 ].concat(this.getX().toArray('le', len)); - } else { - return this.getX().toArray('be', len); - } - }; - - Point$1.fromJSON = function fromJSON(curve, obj) { - return new Point$1(curve, obj[0], obj[1] || curve.one); - }; - - Point$1.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; - }; - - Point$1.prototype.isInfinity = function isInfinity() { - // XXX This code assumes that zero is always zero in red - return this.z.cmpn(0) === 0; - }; - - Point$1.prototype.dbl = function dbl() { - // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#doubling-dbl-1987-m-3 - // 2M + 2S + 4A - - // A = X1 + Z1 - var a = this.x.redAdd(this.z); - // AA = A^2 - var aa = a.redSqr(); - // B = X1 - Z1 - var b = this.x.redSub(this.z); - // BB = B^2 - var bb = b.redSqr(); - // C = AA - BB - var c = aa.redSub(bb); - // X3 = AA * BB - var nx = aa.redMul(bb); - // Z3 = C * (BB + A24 * C) - var nz = c.redMul(bb.redAdd(this.curve.a24.redMul(c))); - return this.curve.point(nx, nz); - }; - - Point$1.prototype.add = function add() { - throw new Error('Not supported on Montgomery curve'); - }; - - Point$1.prototype.diffAdd = function diffAdd(p, diff) { - // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#diffadd-dadd-1987-m-3 - // 4M + 2S + 6A - - // A = X2 + Z2 - var a = this.x.redAdd(this.z); - // B = X2 - Z2 - var b = this.x.redSub(this.z); - // C = X3 + Z3 - var c = p.x.redAdd(p.z); - // D = X3 - Z3 - var d = p.x.redSub(p.z); - // DA = D * A - var da = d.redMul(a); - // CB = C * B - var cb = c.redMul(b); - // X5 = Z1 * (DA + CB)^2 - var nx = diff.z.redMul(da.redAdd(cb).redSqr()); - // Z5 = X1 * (DA - CB)^2 - var nz = diff.x.redMul(da.redISub(cb).redSqr()); - return this.curve.point(nx, nz); - }; - - Point$1.prototype.mul = function mul(k) { - k = new bn(k, 16); - - var t = k.clone(); - var a = this; // (N / 2) * Q + Q - var b = this.curve.point(null, null); // (N / 2) * Q - var c = this; // Q - - for (var bits = []; t.cmpn(0) !== 0; t.iushrn(1)) - bits.push(t.andln(1)); - - for (var i = bits.length - 1; i >= 0; i--) { - if (bits[i] === 0) { - // N * Q + Q = ((N / 2) * Q + Q)) + (N / 2) * Q - a = a.diffAdd(b, c); - // N * Q = 2 * ((N / 2) * Q + Q)) - b = b.dbl(); - } else { - // N * Q = ((N / 2) * Q + Q) + ((N / 2) * Q) - b = a.diffAdd(b, c); - // N * Q + Q = 2 * ((N / 2) * Q + Q) - a = a.dbl(); - } - } - return b; - }; - - Point$1.prototype.mulAdd = function mulAdd() { - throw new Error('Not supported on Montgomery curve'); - }; - - Point$1.prototype.jumlAdd = function jumlAdd() { - throw new Error('Not supported on Montgomery curve'); - }; - - Point$1.prototype.eq = function eq(other) { - return this.getX().cmp(other.getX()) === 0; - }; - - Point$1.prototype.normalize = function normalize() { - this.x = this.x.redMul(this.z.redInvm()); - this.z = this.curve.one; - return this; - }; - - Point$1.prototype.getX = function getX() { - // Normalize coordinates - this.normalize(); - - return this.x.fromRed(); - }; - - var assert$4 = utils_1$1.assert; - - function EdwardsCurve(conf) { - // NOTE: Important as we are creating point in Base.call() - this.twisted = (conf.a | 0) !== 1; - this.mOneA = this.twisted && (conf.a | 0) === -1; - this.extended = this.mOneA; - - base.call(this, 'edwards', conf); - - this.a = new bn(conf.a, 16).umod(this.red.m); - this.a = this.a.toRed(this.red); - this.c = new bn(conf.c, 16).toRed(this.red); - this.c2 = this.c.redSqr(); - this.d = new bn(conf.d, 16).toRed(this.red); - this.dd = this.d.redAdd(this.d); - - assert$4(!this.twisted || this.c.fromRed().cmpn(1) === 0); - this.oneC = (conf.c | 0) === 1; - } - inherits_browser(EdwardsCurve, base); - var edwards = EdwardsCurve; - - EdwardsCurve.prototype._mulA = function _mulA(num) { - if (this.mOneA) - return num.redNeg(); - else - return this.a.redMul(num); - }; - - EdwardsCurve.prototype._mulC = function _mulC(num) { - if (this.oneC) - return num; - else - return this.c.redMul(num); - }; - - // Just for compatibility with Short curve - EdwardsCurve.prototype.jpoint = function jpoint(x, y, z, t) { - return this.point(x, y, z, t); - }; - - EdwardsCurve.prototype.pointFromX = function pointFromX(x, odd) { - x = new bn(x, 16); - if (!x.red) - x = x.toRed(this.red); - - var x2 = x.redSqr(); - var rhs = this.c2.redSub(this.a.redMul(x2)); - var lhs = this.one.redSub(this.c2.redMul(this.d).redMul(x2)); - - var y2 = rhs.redMul(lhs.redInvm()); - var y = y2.redSqrt(); - if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) - throw new Error('invalid point'); - - var isOdd = y.fromRed().isOdd(); - if (odd && !isOdd || !odd && isOdd) - y = y.redNeg(); - - return this.point(x, y); - }; - - EdwardsCurve.prototype.pointFromY = function pointFromY(y, odd) { - y = new bn(y, 16); - if (!y.red) - y = y.toRed(this.red); - - // x^2 = (y^2 - c^2) / (c^2 d y^2 - a) - var y2 = y.redSqr(); - var lhs = y2.redSub(this.c2); - var rhs = y2.redMul(this.d).redMul(this.c2).redSub(this.a); - var x2 = lhs.redMul(rhs.redInvm()); - - if (x2.cmp(this.zero) === 0) { - if (odd) - throw new Error('invalid point'); - else - return this.point(this.zero, y); - } - - var x = x2.redSqrt(); - if (x.redSqr().redSub(x2).cmp(this.zero) !== 0) - throw new Error('invalid point'); - - if (x.fromRed().isOdd() !== odd) - x = x.redNeg(); - - return this.point(x, y); - }; - - EdwardsCurve.prototype.validate = function validate(point) { - if (point.isInfinity()) - return true; - - // Curve: A * X^2 + Y^2 = C^2 * (1 + D * X^2 * Y^2) - point.normalize(); - - var x2 = point.x.redSqr(); - var y2 = point.y.redSqr(); - var lhs = x2.redMul(this.a).redAdd(y2); - var rhs = this.c2.redMul(this.one.redAdd(this.d.redMul(x2).redMul(y2))); - - return lhs.cmp(rhs) === 0; - }; - - function Point$2(curve, x, y, z, t) { - base.BasePoint.call(this, curve, 'projective'); - if (x === null && y === null && z === null) { - this.x = this.curve.zero; - this.y = this.curve.one; - this.z = this.curve.one; - this.t = this.curve.zero; - this.zOne = true; - } else { - this.x = new bn(x, 16); - this.y = new bn(y, 16); - this.z = z ? new bn(z, 16) : this.curve.one; - this.t = t && new bn(t, 16); - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.y.red) - this.y = this.y.toRed(this.curve.red); - if (!this.z.red) - this.z = this.z.toRed(this.curve.red); - if (this.t && !this.t.red) - this.t = this.t.toRed(this.curve.red); - this.zOne = this.z === this.curve.one; - - // Use extended coordinates - if (this.curve.extended && !this.t) { - this.t = this.x.redMul(this.y); - if (!this.zOne) - this.t = this.t.redMul(this.z.redInvm()); - } - } - } - inherits_browser(Point$2, base.BasePoint); - - EdwardsCurve.prototype.pointFromJSON = function pointFromJSON(obj) { - return Point$2.fromJSON(this, obj); - }; - - EdwardsCurve.prototype.point = function point(x, y, z, t) { - return new Point$2(this, x, y, z, t); - }; - - Point$2.fromJSON = function fromJSON(curve, obj) { - return new Point$2(curve, obj[0], obj[1], obj[2]); - }; - - Point$2.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; - }; - - Point$2.prototype.isInfinity = function isInfinity() { - // XXX This code assumes that zero is always zero in red - return this.x.cmpn(0) === 0 && - (this.y.cmp(this.z) === 0 || - (this.zOne && this.y.cmp(this.curve.c) === 0)); - }; - - Point$2.prototype._extDbl = function _extDbl() { - // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html - // #doubling-dbl-2008-hwcd - // 4M + 4S - - // A = X1^2 - var a = this.x.redSqr(); - // B = Y1^2 - var b = this.y.redSqr(); - // C = 2 * Z1^2 - var c = this.z.redSqr(); - c = c.redIAdd(c); - // D = a * A - var d = this.curve._mulA(a); - // E = (X1 + Y1)^2 - A - B - var e = this.x.redAdd(this.y).redSqr().redISub(a).redISub(b); - // G = D + B - var g = d.redAdd(b); - // F = G - C - var f = g.redSub(c); - // H = D - B - var h = d.redSub(b); - // X3 = E * F - var nx = e.redMul(f); - // Y3 = G * H - var ny = g.redMul(h); - // T3 = E * H - var nt = e.redMul(h); - // Z3 = F * G - var nz = f.redMul(g); - return this.curve.point(nx, ny, nz, nt); - }; - - Point$2.prototype._projDbl = function _projDbl() { - // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html - // #doubling-dbl-2008-bbjlp - // #doubling-dbl-2007-bl - // and others - // Generally 3M + 4S or 2M + 4S - - // B = (X1 + Y1)^2 - var b = this.x.redAdd(this.y).redSqr(); - // C = X1^2 - var c = this.x.redSqr(); - // D = Y1^2 - var d = this.y.redSqr(); - - var nx; - var ny; - var nz; - if (this.curve.twisted) { - // E = a * C - var e = this.curve._mulA(c); - // F = E + D - var f = e.redAdd(d); - if (this.zOne) { - // X3 = (B - C - D) * (F - 2) - nx = b.redSub(c).redSub(d).redMul(f.redSub(this.curve.two)); - // Y3 = F * (E - D) - ny = f.redMul(e.redSub(d)); - // Z3 = F^2 - 2 * F - nz = f.redSqr().redSub(f).redSub(f); - } else { - // H = Z1^2 - var h = this.z.redSqr(); - // J = F - 2 * H - var j = f.redSub(h).redISub(h); - // X3 = (B-C-D)*J - nx = b.redSub(c).redISub(d).redMul(j); - // Y3 = F * (E - D) - ny = f.redMul(e.redSub(d)); - // Z3 = F * J - nz = f.redMul(j); - } - } else { - // E = C + D - var e = c.redAdd(d); - // H = (c * Z1)^2 - var h = this.curve._mulC(this.z).redSqr(); - // J = E - 2 * H - var j = e.redSub(h).redSub(h); - // X3 = c * (B - E) * J - nx = this.curve._mulC(b.redISub(e)).redMul(j); - // Y3 = c * E * (C - D) - ny = this.curve._mulC(e).redMul(c.redISub(d)); - // Z3 = E * J - nz = e.redMul(j); - } - return this.curve.point(nx, ny, nz); - }; - - Point$2.prototype.dbl = function dbl() { - if (this.isInfinity()) - return this; - - // Double in extended coordinates - if (this.curve.extended) - return this._extDbl(); - else - return this._projDbl(); - }; - - Point$2.prototype._extAdd = function _extAdd(p) { - // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html - // #addition-add-2008-hwcd-3 - // 8M - - // A = (Y1 - X1) * (Y2 - X2) - var a = this.y.redSub(this.x).redMul(p.y.redSub(p.x)); - // B = (Y1 + X1) * (Y2 + X2) - var b = this.y.redAdd(this.x).redMul(p.y.redAdd(p.x)); - // C = T1 * k * T2 - var c = this.t.redMul(this.curve.dd).redMul(p.t); - // D = Z1 * 2 * Z2 - var d = this.z.redMul(p.z.redAdd(p.z)); - // E = B - A - var e = b.redSub(a); - // F = D - C - var f = d.redSub(c); - // G = D + C - var g = d.redAdd(c); - // H = B + A - var h = b.redAdd(a); - // X3 = E * F - var nx = e.redMul(f); - // Y3 = G * H - var ny = g.redMul(h); - // T3 = E * H - var nt = e.redMul(h); - // Z3 = F * G - var nz = f.redMul(g); - return this.curve.point(nx, ny, nz, nt); - }; - - Point$2.prototype._projAdd = function _projAdd(p) { - // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html - // #addition-add-2008-bbjlp - // #addition-add-2007-bl - // 10M + 1S - - // A = Z1 * Z2 - var a = this.z.redMul(p.z); - // B = A^2 - var b = a.redSqr(); - // C = X1 * X2 - var c = this.x.redMul(p.x); - // D = Y1 * Y2 - var d = this.y.redMul(p.y); - // E = d * C * D - var e = this.curve.d.redMul(c).redMul(d); - // F = B - E - var f = b.redSub(e); - // G = B + E - var g = b.redAdd(e); - // X3 = A * F * ((X1 + Y1) * (X2 + Y2) - C - D) - var tmp = this.x.redAdd(this.y).redMul(p.x.redAdd(p.y)).redISub(c).redISub(d); - var nx = a.redMul(f).redMul(tmp); - var ny; - var nz; - if (this.curve.twisted) { - // Y3 = A * G * (D - a * C) - ny = a.redMul(g).redMul(d.redSub(this.curve._mulA(c))); - // Z3 = F * G - nz = f.redMul(g); - } else { - // Y3 = A * G * (D - C) - ny = a.redMul(g).redMul(d.redSub(c)); - // Z3 = c * F * G - nz = this.curve._mulC(f).redMul(g); - } - return this.curve.point(nx, ny, nz); - }; - - Point$2.prototype.add = function add(p) { - if (this.isInfinity()) - return p; - if (p.isInfinity()) - return this; - - if (this.curve.extended) - return this._extAdd(p); - else - return this._projAdd(p); - }; - - Point$2.prototype.mul = function mul(k) { - if (this._hasDoubles(k)) - return this.curve._fixedNafMul(this, k); - else - return this.curve._wnafMul(this, k); - }; - - Point$2.prototype.mulAdd = function mulAdd(k1, p, k2) { - return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, false); - }; - - Point$2.prototype.jmulAdd = function jmulAdd(k1, p, k2) { - return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, true); - }; - - Point$2.prototype.normalize = function normalize() { - if (this.zOne) - return this; - - // Normalize coordinates - var zi = this.z.redInvm(); - this.x = this.x.redMul(zi); - this.y = this.y.redMul(zi); - if (this.t) - this.t = this.t.redMul(zi); - this.z = this.curve.one; - this.zOne = true; - return this; - }; - - Point$2.prototype.neg = function neg() { - return this.curve.point(this.x.redNeg(), - this.y, - this.z, - this.t && this.t.redNeg()); - }; - - Point$2.prototype.getX = function getX() { - this.normalize(); - return this.x.fromRed(); - }; - - Point$2.prototype.getY = function getY() { - this.normalize(); - return this.y.fromRed(); - }; - - Point$2.prototype.eq = function eq(other) { - return this === other || - this.getX().cmp(other.getX()) === 0 && - this.getY().cmp(other.getY()) === 0; - }; - - Point$2.prototype.eqXToP = function eqXToP(x) { - var rx = x.toRed(this.curve.red).redMul(this.z); - if (this.x.cmp(rx) === 0) - return true; - - var xc = x.clone(); - var t = this.curve.redN.redMul(this.z); - for (;;) { - xc.iadd(this.curve.n); - if (xc.cmp(this.curve.p) >= 0) - return false; - - rx.redIAdd(t); - if (this.x.cmp(rx) === 0) - return true; - } - }; - - // Compatibility with BaseCurve - Point$2.prototype.toP = Point$2.prototype.normalize; - Point$2.prototype.mixedAdd = Point$2.prototype.add; - - var curve_1 = createCommonjsModule(function (module, exports) { - - var curve = exports; - - curve.base = base; - curve.short = short_1; - curve.mont = mont; - curve.edwards = edwards; - }); - - var rotl32$2 = utils.rotl32; - var sum32$3 = utils.sum32; - var sum32_5$2 = utils.sum32_5; - var ft_1$1 = common$1.ft_1; - var BlockHash$4 = common.BlockHash; - - var sha1_K = [ - 0x5A827999, 0x6ED9EBA1, - 0x8F1BBCDC, 0xCA62C1D6 - ]; - - function SHA1() { - if (!(this instanceof SHA1)) - return new SHA1(); - - BlockHash$4.call(this); - this.h = [ - 0x67452301, 0xefcdab89, 0x98badcfe, - 0x10325476, 0xc3d2e1f0 ]; - this.W = new Array(80); - } - - utils.inherits(SHA1, BlockHash$4); - var _1 = SHA1; - - SHA1.blockSize = 512; - SHA1.outSize = 160; - SHA1.hmacStrength = 80; - SHA1.padLength = 64; - - SHA1.prototype._update = function _update(msg, start) { - var W = this.W; - - for (var i = 0; i < 16; i++) - W[i] = msg[start + i]; - - for(; i < W.length; i++) - W[i] = rotl32$2(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1); - - var a = this.h[0]; - var b = this.h[1]; - var c = this.h[2]; - var d = this.h[3]; - var e = this.h[4]; - - for (i = 0; i < W.length; i++) { - var s = ~~(i / 20); - var t = sum32_5$2(rotl32$2(a, 5), ft_1$1(s, b, c, d), e, W[i], sha1_K[s]); - e = d; - d = c; - c = rotl32$2(b, 30); - b = a; - a = t; - } - - this.h[0] = sum32$3(this.h[0], a); - this.h[1] = sum32$3(this.h[1], b); - this.h[2] = sum32$3(this.h[2], c); - this.h[3] = sum32$3(this.h[3], d); - this.h[4] = sum32$3(this.h[4], e); - }; - - SHA1.prototype._digest = function digest(enc) { - if (enc === 'hex') - return utils.toHex32(this.h, 'big'); - else - return utils.split32(this.h, 'big'); - }; - - var sha1 = _1; - var sha224 = _224; - var sha256 = _256; - var sha384 = _384; - var sha512 = _512; - - var sha = { - sha1: sha1, - sha224: sha224, - sha256: sha256, - sha384: sha384, - sha512: sha512 - }; - - function Hmac(hash, key, enc) { - if (!(this instanceof Hmac)) - return new Hmac(hash, key, enc); - this.Hash = hash; - this.blockSize = hash.blockSize / 8; - this.outSize = hash.outSize / 8; - this.inner = null; - this.outer = null; - - this._init(utils.toArray(key, enc)); - } - var hmac = Hmac; - - Hmac.prototype._init = function init(key) { - // Shorten key, if needed - if (key.length > this.blockSize) - key = new this.Hash().update(key).digest(); - minimalisticAssert(key.length <= this.blockSize); - - // Add padding to key - for (var i = key.length; i < this.blockSize; i++) - key.push(0); - - for (i = 0; i < key.length; i++) - key[i] ^= 0x36; - this.inner = new this.Hash().update(key); - - // 0x36 ^ 0x5c = 0x6a - for (i = 0; i < key.length; i++) - key[i] ^= 0x6a; - this.outer = new this.Hash().update(key); - }; - - Hmac.prototype.update = function update(msg, enc) { - this.inner.update(msg, enc); - return this; - }; - - Hmac.prototype.digest = function digest(enc) { - this.outer.update(this.inner.digest()); - return this.outer.digest(enc); - }; - - var hash_1 = createCommonjsModule(function (module, exports) { - var hash = exports; - - hash.utils = utils; - hash.common = common; - hash.sha = sha; - hash.ripemd = ripemd; - hash.hmac = hmac; - - // Proxy hash functions to the main object - hash.sha1 = hash.sha.sha1; - hash.sha256 = hash.sha.sha256; - hash.sha224 = hash.sha.sha224; - hash.sha384 = hash.sha.sha384; - hash.sha512 = hash.sha.sha512; - hash.ripemd160 = hash.ripemd.ripemd160; - }); - - var secp256k1 = { - doubles: { - step: 4, - points: [ - [ - 'e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a', - 'f7e3507399e595929db99f34f57937101296891e44d23f0be1f32cce69616821' - ], - [ - '8282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508', - '11f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf' - ], - [ - '175e159f728b865a72f99cc6c6fc846de0b93833fd2222ed73fce5b551e5b739', - 'd3506e0d9e3c79eba4ef97a51ff71f5eacb5955add24345c6efa6ffee9fed695' - ], - [ - '363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640', - '4e273adfc732221953b445397f3363145b9a89008199ecb62003c7f3bee9de9' - ], - [ - '8b4b5f165df3c2be8c6244b5b745638843e4a781a15bcd1b69f79a55dffdf80c', - '4aad0a6f68d308b4b3fbd7813ab0da04f9e336546162ee56b3eff0c65fd4fd36' - ], - [ - '723cbaa6e5db996d6bf771c00bd548c7b700dbffa6c0e77bcb6115925232fcda', - '96e867b5595cc498a921137488824d6e2660a0653779494801dc069d9eb39f5f' - ], - [ - 'eebfa4d493bebf98ba5feec812c2d3b50947961237a919839a533eca0e7dd7fa', - '5d9a8ca3970ef0f269ee7edaf178089d9ae4cdc3a711f712ddfd4fdae1de8999' - ], - [ - '100f44da696e71672791d0a09b7bde459f1215a29b3c03bfefd7835b39a48db0', - 'cdd9e13192a00b772ec8f3300c090666b7ff4a18ff5195ac0fbd5cd62bc65a09' - ], - [ - 'e1031be262c7ed1b1dc9227a4a04c017a77f8d4464f3b3852c8acde6e534fd2d', - '9d7061928940405e6bb6a4176597535af292dd419e1ced79a44f18f29456a00d' - ], - [ - 'feea6cae46d55b530ac2839f143bd7ec5cf8b266a41d6af52d5e688d9094696d', - 'e57c6b6c97dce1bab06e4e12bf3ecd5c981c8957cc41442d3155debf18090088' - ], - [ - 'da67a91d91049cdcb367be4be6ffca3cfeed657d808583de33fa978bc1ec6cb1', - '9bacaa35481642bc41f463f7ec9780e5dec7adc508f740a17e9ea8e27a68be1d' - ], - [ - '53904faa0b334cdda6e000935ef22151ec08d0f7bb11069f57545ccc1a37b7c0', - '5bc087d0bc80106d88c9eccac20d3c1c13999981e14434699dcb096b022771c8' - ], - [ - '8e7bcd0bd35983a7719cca7764ca906779b53a043a9b8bcaeff959f43ad86047', - '10b7770b2a3da4b3940310420ca9514579e88e2e47fd68b3ea10047e8460372a' - ], - [ - '385eed34c1cdff21e6d0818689b81bde71a7f4f18397e6690a841e1599c43862', - '283bebc3e8ea23f56701de19e9ebf4576b304eec2086dc8cc0458fe5542e5453' - ], - [ - '6f9d9b803ecf191637c73a4413dfa180fddf84a5947fbc9c606ed86c3fac3a7', - '7c80c68e603059ba69b8e2a30e45c4d47ea4dd2f5c281002d86890603a842160' - ], - [ - '3322d401243c4e2582a2147c104d6ecbf774d163db0f5e5313b7e0e742d0e6bd', - '56e70797e9664ef5bfb019bc4ddaf9b72805f63ea2873af624f3a2e96c28b2a0' - ], - [ - '85672c7d2de0b7da2bd1770d89665868741b3f9af7643397721d74d28134ab83', - '7c481b9b5b43b2eb6374049bfa62c2e5e77f17fcc5298f44c8e3094f790313a6' - ], - [ - '948bf809b1988a46b06c9f1919413b10f9226c60f668832ffd959af60c82a0a', - '53a562856dcb6646dc6b74c5d1c3418c6d4dff08c97cd2bed4cb7f88d8c8e589' - ], - [ - '6260ce7f461801c34f067ce0f02873a8f1b0e44dfc69752accecd819f38fd8e8', - 'bc2da82b6fa5b571a7f09049776a1ef7ecd292238051c198c1a84e95b2b4ae17' - ], - [ - 'e5037de0afc1d8d43d8348414bbf4103043ec8f575bfdc432953cc8d2037fa2d', - '4571534baa94d3b5f9f98d09fb990bddbd5f5b03ec481f10e0e5dc841d755bda' - ], - [ - 'e06372b0f4a207adf5ea905e8f1771b4e7e8dbd1c6a6c5b725866a0ae4fce725', - '7a908974bce18cfe12a27bb2ad5a488cd7484a7787104870b27034f94eee31dd' - ], - [ - '213c7a715cd5d45358d0bbf9dc0ce02204b10bdde2a3f58540ad6908d0559754', - '4b6dad0b5ae462507013ad06245ba190bb4850f5f36a7eeddff2c27534b458f2' - ], - [ - '4e7c272a7af4b34e8dbb9352a5419a87e2838c70adc62cddf0cc3a3b08fbd53c', - '17749c766c9d0b18e16fd09f6def681b530b9614bff7dd33e0b3941817dcaae6' - ], - [ - 'fea74e3dbe778b1b10f238ad61686aa5c76e3db2be43057632427e2840fb27b6', - '6e0568db9b0b13297cf674deccb6af93126b596b973f7b77701d3db7f23cb96f' - ], - [ - '76e64113f677cf0e10a2570d599968d31544e179b760432952c02a4417bdde39', - 'c90ddf8dee4e95cf577066d70681f0d35e2a33d2b56d2032b4b1752d1901ac01' - ], - [ - 'c738c56b03b2abe1e8281baa743f8f9a8f7cc643df26cbee3ab150242bcbb891', - '893fb578951ad2537f718f2eacbfbbbb82314eef7880cfe917e735d9699a84c3' - ], - [ - 'd895626548b65b81e264c7637c972877d1d72e5f3a925014372e9f6588f6c14b', - 'febfaa38f2bc7eae728ec60818c340eb03428d632bb067e179363ed75d7d991f' - ], - [ - 'b8da94032a957518eb0f6433571e8761ceffc73693e84edd49150a564f676e03', - '2804dfa44805a1e4d7c99cc9762808b092cc584d95ff3b511488e4e74efdf6e7' - ], - [ - 'e80fea14441fb33a7d8adab9475d7fab2019effb5156a792f1a11778e3c0df5d', - 'eed1de7f638e00771e89768ca3ca94472d155e80af322ea9fcb4291b6ac9ec78' - ], - [ - 'a301697bdfcd704313ba48e51d567543f2a182031efd6915ddc07bbcc4e16070', - '7370f91cfb67e4f5081809fa25d40f9b1735dbf7c0a11a130c0d1a041e177ea1' - ], - [ - '90ad85b389d6b936463f9d0512678de208cc330b11307fffab7ac63e3fb04ed4', - 'e507a3620a38261affdcbd9427222b839aefabe1582894d991d4d48cb6ef150' - ], - [ - '8f68b9d2f63b5f339239c1ad981f162ee88c5678723ea3351b7b444c9ec4c0da', - '662a9f2dba063986de1d90c2b6be215dbbea2cfe95510bfdf23cbf79501fff82' - ], - [ - 'e4f3fb0176af85d65ff99ff9198c36091f48e86503681e3e6686fd5053231e11', - '1e63633ad0ef4f1c1661a6d0ea02b7286cc7e74ec951d1c9822c38576feb73bc' - ], - [ - '8c00fa9b18ebf331eb961537a45a4266c7034f2f0d4e1d0716fb6eae20eae29e', - 'efa47267fea521a1a9dc343a3736c974c2fadafa81e36c54e7d2a4c66702414b' - ], - [ - 'e7a26ce69dd4829f3e10cec0a9e98ed3143d084f308b92c0997fddfc60cb3e41', - '2a758e300fa7984b471b006a1aafbb18d0a6b2c0420e83e20e8a9421cf2cfd51' - ], - [ - 'b6459e0ee3662ec8d23540c223bcbdc571cbcb967d79424f3cf29eb3de6b80ef', - '67c876d06f3e06de1dadf16e5661db3c4b3ae6d48e35b2ff30bf0b61a71ba45' - ], - [ - 'd68a80c8280bb840793234aa118f06231d6f1fc67e73c5a5deda0f5b496943e8', - 'db8ba9fff4b586d00c4b1f9177b0e28b5b0e7b8f7845295a294c84266b133120' - ], - [ - '324aed7df65c804252dc0270907a30b09612aeb973449cea4095980fc28d3d5d', - '648a365774b61f2ff130c0c35aec1f4f19213b0c7e332843967224af96ab7c84' - ], - [ - '4df9c14919cde61f6d51dfdbe5fee5dceec4143ba8d1ca888e8bd373fd054c96', - '35ec51092d8728050974c23a1d85d4b5d506cdc288490192ebac06cad10d5d' - ], - [ - '9c3919a84a474870faed8a9c1cc66021523489054d7f0308cbfc99c8ac1f98cd', - 'ddb84f0f4a4ddd57584f044bf260e641905326f76c64c8e6be7e5e03d4fc599d' - ], - [ - '6057170b1dd12fdf8de05f281d8e06bb91e1493a8b91d4cc5a21382120a959e5', - '9a1af0b26a6a4807add9a2daf71df262465152bc3ee24c65e899be932385a2a8' - ], - [ - 'a576df8e23a08411421439a4518da31880cef0fba7d4df12b1a6973eecb94266', - '40a6bf20e76640b2c92b97afe58cd82c432e10a7f514d9f3ee8be11ae1b28ec8' - ], - [ - '7778a78c28dec3e30a05fe9629de8c38bb30d1f5cf9a3a208f763889be58ad71', - '34626d9ab5a5b22ff7098e12f2ff580087b38411ff24ac563b513fc1fd9f43ac' - ], - [ - '928955ee637a84463729fd30e7afd2ed5f96274e5ad7e5cb09eda9c06d903ac', - 'c25621003d3f42a827b78a13093a95eeac3d26efa8a8d83fc5180e935bcd091f' - ], - [ - '85d0fef3ec6db109399064f3a0e3b2855645b4a907ad354527aae75163d82751', - '1f03648413a38c0be29d496e582cf5663e8751e96877331582c237a24eb1f962' - ], - [ - 'ff2b0dce97eece97c1c9b6041798b85dfdfb6d8882da20308f5404824526087e', - '493d13fef524ba188af4c4dc54d07936c7b7ed6fb90e2ceb2c951e01f0c29907' - ], - [ - '827fbbe4b1e880ea9ed2b2e6301b212b57f1ee148cd6dd28780e5e2cf856e241', - 'c60f9c923c727b0b71bef2c67d1d12687ff7a63186903166d605b68baec293ec' - ], - [ - 'eaa649f21f51bdbae7be4ae34ce6e5217a58fdce7f47f9aa7f3b58fa2120e2b3', - 'be3279ed5bbbb03ac69a80f89879aa5a01a6b965f13f7e59d47a5305ba5ad93d' - ], - [ - 'e4a42d43c5cf169d9391df6decf42ee541b6d8f0c9a137401e23632dda34d24f', - '4d9f92e716d1c73526fc99ccfb8ad34ce886eedfa8d8e4f13a7f7131deba9414' - ], - [ - '1ec80fef360cbdd954160fadab352b6b92b53576a88fea4947173b9d4300bf19', - 'aeefe93756b5340d2f3a4958a7abbf5e0146e77f6295a07b671cdc1cc107cefd' - ], - [ - '146a778c04670c2f91b00af4680dfa8bce3490717d58ba889ddb5928366642be', - 'b318e0ec3354028add669827f9d4b2870aaa971d2f7e5ed1d0b297483d83efd0' - ], - [ - 'fa50c0f61d22e5f07e3acebb1aa07b128d0012209a28b9776d76a8793180eef9', - '6b84c6922397eba9b72cd2872281a68a5e683293a57a213b38cd8d7d3f4f2811' - ], - [ - 'da1d61d0ca721a11b1a5bf6b7d88e8421a288ab5d5bba5220e53d32b5f067ec2', - '8157f55a7c99306c79c0766161c91e2966a73899d279b48a655fba0f1ad836f1' - ], - [ - 'a8e282ff0c9706907215ff98e8fd416615311de0446f1e062a73b0610d064e13', - '7f97355b8db81c09abfb7f3c5b2515888b679a3e50dd6bd6cef7c73111f4cc0c' - ], - [ - '174a53b9c9a285872d39e56e6913cab15d59b1fa512508c022f382de8319497c', - 'ccc9dc37abfc9c1657b4155f2c47f9e6646b3a1d8cb9854383da13ac079afa73' - ], - [ - '959396981943785c3d3e57edf5018cdbe039e730e4918b3d884fdff09475b7ba', - '2e7e552888c331dd8ba0386a4b9cd6849c653f64c8709385e9b8abf87524f2fd' - ], - [ - 'd2a63a50ae401e56d645a1153b109a8fcca0a43d561fba2dbb51340c9d82b151', - 'e82d86fb6443fcb7565aee58b2948220a70f750af484ca52d4142174dcf89405' - ], - [ - '64587e2335471eb890ee7896d7cfdc866bacbdbd3839317b3436f9b45617e073', - 'd99fcdd5bf6902e2ae96dd6447c299a185b90a39133aeab358299e5e9faf6589' - ], - [ - '8481bde0e4e4d885b3a546d3e549de042f0aa6cea250e7fd358d6c86dd45e458', - '38ee7b8cba5404dd84a25bf39cecb2ca900a79c42b262e556d64b1b59779057e' - ], - [ - '13464a57a78102aa62b6979ae817f4637ffcfed3c4b1ce30bcd6303f6caf666b', - '69be159004614580ef7e433453ccb0ca48f300a81d0942e13f495a907f6ecc27' - ], - [ - 'bc4a9df5b713fe2e9aef430bcc1dc97a0cd9ccede2f28588cada3a0d2d83f366', - 'd3a81ca6e785c06383937adf4b798caa6e8a9fbfa547b16d758d666581f33c1' - ], - [ - '8c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa', - '40a30463a3305193378fedf31f7cc0eb7ae784f0451cb9459e71dc73cbef9482' - ], - [ - '8ea9666139527a8c1dd94ce4f071fd23c8b350c5a4bb33748c4ba111faccae0', - '620efabbc8ee2782e24e7c0cfb95c5d735b783be9cf0f8e955af34a30e62b945' - ], - [ - 'dd3625faef5ba06074669716bbd3788d89bdde815959968092f76cc4eb9a9787', - '7a188fa3520e30d461da2501045731ca941461982883395937f68d00c644a573' - ], - [ - 'f710d79d9eb962297e4f6232b40e8f7feb2bc63814614d692c12de752408221e', - 'ea98e67232d3b3295d3b535532115ccac8612c721851617526ae47a9c77bfc82' - ] - ] - }, - naf: { - wnd: 7, - points: [ - [ - 'f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9', - '388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672' - ], - [ - '2f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4', - 'd8ac222636e5e3d6d4dba9dda6c9c426f788271bab0d6840dca87d3aa6ac62d6' - ], - [ - '5cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc', - '6aebca40ba255960a3178d6d861a54dba813d0b813fde7b5a5082628087264da' - ], - [ - 'acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe', - 'cc338921b0a7d9fd64380971763b61e9add888a4375f8e0f05cc262ac64f9c37' - ], - [ - '774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb', - 'd984a032eb6b5e190243dd56d7b7b365372db1e2dff9d6a8301d74c9c953c61b' - ], - [ - 'f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8', - 'ab0902e8d880a89758212eb65cdaf473a1a06da521fa91f29b5cb52db03ed81' - ], - [ - 'd7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e', - '581e2872a86c72a683842ec228cc6defea40af2bd896d3a5c504dc9ff6a26b58' - ], - [ - 'defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34', - '4211ab0694635168e997b0ead2a93daeced1f4a04a95c0f6cfb199f69e56eb77' - ], - [ - '2b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c', - '85e89bc037945d93b343083b5a1c86131a01f60c50269763b570c854e5c09b7a' - ], - [ - '352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5', - '321eb4075348f534d59c18259dda3e1f4a1b3b2e71b1039c67bd3d8bcf81998c' - ], - [ - '2fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f', - '2de1068295dd865b64569335bd5dd80181d70ecfc882648423ba76b532b7d67' - ], - [ - '9248279b09b4d68dab21a9b066edda83263c3d84e09572e269ca0cd7f5453714', - '73016f7bf234aade5d1aa71bdea2b1ff3fc0de2a887912ffe54a32ce97cb3402' - ], - [ - 'daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729', - 'a69dce4a7d6c98e8d4a1aca87ef8d7003f83c230f3afa726ab40e52290be1c55' - ], - [ - 'c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db', - '2119a460ce326cdc76c45926c982fdac0e106e861edf61c5a039063f0e0e6482' - ], - [ - '6a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4', - 'e022cf42c2bd4a708b3f5126f16a24ad8b33ba48d0423b6efd5e6348100d8a82' - ], - [ - '1697ffa6fd9de627c077e3d2fe541084ce13300b0bec1146f95ae57f0d0bd6a5', - 'b9c398f186806f5d27561506e4557433a2cf15009e498ae7adee9d63d01b2396' - ], - [ - '605bdb019981718b986d0f07e834cb0d9deb8360ffb7f61df982345ef27a7479', - '2972d2de4f8d20681a78d93ec96fe23c26bfae84fb14db43b01e1e9056b8c49' - ], - [ - '62d14dab4150bf497402fdc45a215e10dcb01c354959b10cfe31c7e9d87ff33d', - '80fc06bd8cc5b01098088a1950eed0db01aa132967ab472235f5642483b25eaf' - ], - [ - '80c60ad0040f27dade5b4b06c408e56b2c50e9f56b9b8b425e555c2f86308b6f', - '1c38303f1cc5c30f26e66bad7fe72f70a65eed4cbe7024eb1aa01f56430bd57a' - ], - [ - '7a9375ad6167ad54aa74c6348cc54d344cc5dc9487d847049d5eabb0fa03c8fb', - 'd0e3fa9eca8726909559e0d79269046bdc59ea10c70ce2b02d499ec224dc7f7' - ], - [ - 'd528ecd9b696b54c907a9ed045447a79bb408ec39b68df504bb51f459bc3ffc9', - 'eecf41253136e5f99966f21881fd656ebc4345405c520dbc063465b521409933' - ], - [ - '49370a4b5f43412ea25f514e8ecdad05266115e4a7ecb1387231808f8b45963', - '758f3f41afd6ed428b3081b0512fd62a54c3f3afbb5b6764b653052a12949c9a' - ], - [ - '77f230936ee88cbbd73df930d64702ef881d811e0e1498e2f1c13eb1fc345d74', - '958ef42a7886b6400a08266e9ba1b37896c95330d97077cbbe8eb3c7671c60d6' - ], - [ - 'f2dac991cc4ce4b9ea44887e5c7c0bce58c80074ab9d4dbaeb28531b7739f530', - 'e0dedc9b3b2f8dad4da1f32dec2531df9eb5fbeb0598e4fd1a117dba703a3c37' - ], - [ - '463b3d9f662621fb1b4be8fbbe2520125a216cdfc9dae3debcba4850c690d45b', - '5ed430d78c296c3543114306dd8622d7c622e27c970a1de31cb377b01af7307e' - ], - [ - 'f16f804244e46e2a09232d4aff3b59976b98fac14328a2d1a32496b49998f247', - 'cedabd9b82203f7e13d206fcdf4e33d92a6c53c26e5cce26d6579962c4e31df6' - ], - [ - 'caf754272dc84563b0352b7a14311af55d245315ace27c65369e15f7151d41d1', - 'cb474660ef35f5f2a41b643fa5e460575f4fa9b7962232a5c32f908318a04476' - ], - [ - '2600ca4b282cb986f85d0f1709979d8b44a09c07cb86d7c124497bc86f082120', - '4119b88753c15bd6a693b03fcddbb45d5ac6be74ab5f0ef44b0be9475a7e4b40' - ], - [ - '7635ca72d7e8432c338ec53cd12220bc01c48685e24f7dc8c602a7746998e435', - '91b649609489d613d1d5e590f78e6d74ecfc061d57048bad9e76f302c5b9c61' - ], - [ - '754e3239f325570cdbbf4a87deee8a66b7f2b33479d468fbc1a50743bf56cc18', - '673fb86e5bda30fb3cd0ed304ea49a023ee33d0197a695d0c5d98093c536683' - ], - [ - 'e3e6bd1071a1e96aff57859c82d570f0330800661d1c952f9fe2694691d9b9e8', - '59c9e0bba394e76f40c0aa58379a3cb6a5a2283993e90c4167002af4920e37f5' - ], - [ - '186b483d056a033826ae73d88f732985c4ccb1f32ba35f4b4cc47fdcf04aa6eb', - '3b952d32c67cf77e2e17446e204180ab21fb8090895138b4a4a797f86e80888b' - ], - [ - 'df9d70a6b9876ce544c98561f4be4f725442e6d2b737d9c91a8321724ce0963f', - '55eb2dafd84d6ccd5f862b785dc39d4ab157222720ef9da217b8c45cf2ba2417' - ], - [ - '5edd5cc23c51e87a497ca815d5dce0f8ab52554f849ed8995de64c5f34ce7143', - 'efae9c8dbc14130661e8cec030c89ad0c13c66c0d17a2905cdc706ab7399a868' - ], - [ - '290798c2b6476830da12fe02287e9e777aa3fba1c355b17a722d362f84614fba', - 'e38da76dcd440621988d00bcf79af25d5b29c094db2a23146d003afd41943e7a' - ], - [ - 'af3c423a95d9f5b3054754efa150ac39cd29552fe360257362dfdecef4053b45', - 'f98a3fd831eb2b749a93b0e6f35cfb40c8cd5aa667a15581bc2feded498fd9c6' - ], - [ - '766dbb24d134e745cccaa28c99bf274906bb66b26dcf98df8d2fed50d884249a', - '744b1152eacbe5e38dcc887980da38b897584a65fa06cedd2c924f97cbac5996' - ], - [ - '59dbf46f8c94759ba21277c33784f41645f7b44f6c596a58ce92e666191abe3e', - 'c534ad44175fbc300f4ea6ce648309a042ce739a7919798cd85e216c4a307f6e' - ], - [ - 'f13ada95103c4537305e691e74e9a4a8dd647e711a95e73cb62dc6018cfd87b8', - 'e13817b44ee14de663bf4bc808341f326949e21a6a75c2570778419bdaf5733d' - ], - [ - '7754b4fa0e8aced06d4167a2c59cca4cda1869c06ebadfb6488550015a88522c', - '30e93e864e669d82224b967c3020b8fa8d1e4e350b6cbcc537a48b57841163a2' - ], - [ - '948dcadf5990e048aa3874d46abef9d701858f95de8041d2a6828c99e2262519', - 'e491a42537f6e597d5d28a3224b1bc25df9154efbd2ef1d2cbba2cae5347d57e' - ], - [ - '7962414450c76c1689c7b48f8202ec37fb224cf5ac0bfa1570328a8a3d7c77ab', - '100b610ec4ffb4760d5c1fc133ef6f6b12507a051f04ac5760afa5b29db83437' - ], - [ - '3514087834964b54b15b160644d915485a16977225b8847bb0dd085137ec47ca', - 'ef0afbb2056205448e1652c48e8127fc6039e77c15c2378b7e7d15a0de293311' - ], - [ - 'd3cc30ad6b483e4bc79ce2c9dd8bc54993e947eb8df787b442943d3f7b527eaf', - '8b378a22d827278d89c5e9be8f9508ae3c2ad46290358630afb34db04eede0a4' - ], - [ - '1624d84780732860ce1c78fcbfefe08b2b29823db913f6493975ba0ff4847610', - '68651cf9b6da903e0914448c6cd9d4ca896878f5282be4c8cc06e2a404078575' - ], - [ - '733ce80da955a8a26902c95633e62a985192474b5af207da6df7b4fd5fc61cd4', - 'f5435a2bd2badf7d485a4d8b8db9fcce3e1ef8e0201e4578c54673bc1dc5ea1d' - ], - [ - '15d9441254945064cf1a1c33bbd3b49f8966c5092171e699ef258dfab81c045c', - 'd56eb30b69463e7234f5137b73b84177434800bacebfc685fc37bbe9efe4070d' - ], - [ - 'a1d0fcf2ec9de675b612136e5ce70d271c21417c9d2b8aaaac138599d0717940', - 'edd77f50bcb5a3cab2e90737309667f2641462a54070f3d519212d39c197a629' - ], - [ - 'e22fbe15c0af8ccc5780c0735f84dbe9a790badee8245c06c7ca37331cb36980', - 'a855babad5cd60c88b430a69f53a1a7a38289154964799be43d06d77d31da06' - ], - [ - '311091dd9860e8e20ee13473c1155f5f69635e394704eaa74009452246cfa9b3', - '66db656f87d1f04fffd1f04788c06830871ec5a64feee685bd80f0b1286d8374' - ], - [ - '34c1fd04d301be89b31c0442d3e6ac24883928b45a9340781867d4232ec2dbdf', - '9414685e97b1b5954bd46f730174136d57f1ceeb487443dc5321857ba73abee' - ], - [ - 'f219ea5d6b54701c1c14de5b557eb42a8d13f3abbcd08affcc2a5e6b049b8d63', - '4cb95957e83d40b0f73af4544cccf6b1f4b08d3c07b27fb8d8c2962a400766d1' - ], - [ - 'd7b8740f74a8fbaab1f683db8f45de26543a5490bca627087236912469a0b448', - 'fa77968128d9c92ee1010f337ad4717eff15db5ed3c049b3411e0315eaa4593b' - ], - [ - '32d31c222f8f6f0ef86f7c98d3a3335ead5bcd32abdd94289fe4d3091aa824bf', - '5f3032f5892156e39ccd3d7915b9e1da2e6dac9e6f26e961118d14b8462e1661' - ], - [ - '7461f371914ab32671045a155d9831ea8793d77cd59592c4340f86cbc18347b5', - '8ec0ba238b96bec0cbdddcae0aa442542eee1ff50c986ea6b39847b3cc092ff6' - ], - [ - 'ee079adb1df1860074356a25aa38206a6d716b2c3e67453d287698bad7b2b2d6', - '8dc2412aafe3be5c4c5f37e0ecc5f9f6a446989af04c4e25ebaac479ec1c8c1e' - ], - [ - '16ec93e447ec83f0467b18302ee620f7e65de331874c9dc72bfd8616ba9da6b5', - '5e4631150e62fb40d0e8c2a7ca5804a39d58186a50e497139626778e25b0674d' - ], - [ - 'eaa5f980c245f6f038978290afa70b6bd8855897f98b6aa485b96065d537bd99', - 'f65f5d3e292c2e0819a528391c994624d784869d7e6ea67fb18041024edc07dc' - ], - [ - '78c9407544ac132692ee1910a02439958ae04877151342ea96c4b6b35a49f51', - 'f3e0319169eb9b85d5404795539a5e68fa1fbd583c064d2462b675f194a3ddb4' - ], - [ - '494f4be219a1a77016dcd838431aea0001cdc8ae7a6fc688726578d9702857a5', - '42242a969283a5f339ba7f075e36ba2af925ce30d767ed6e55f4b031880d562c' - ], - [ - 'a598a8030da6d86c6bc7f2f5144ea549d28211ea58faa70ebf4c1e665c1fe9b5', - '204b5d6f84822c307e4b4a7140737aec23fc63b65b35f86a10026dbd2d864e6b' - ], - [ - 'c41916365abb2b5d09192f5f2dbeafec208f020f12570a184dbadc3e58595997', - '4f14351d0087efa49d245b328984989d5caf9450f34bfc0ed16e96b58fa9913' - ], - [ - '841d6063a586fa475a724604da03bc5b92a2e0d2e0a36acfe4c73a5514742881', - '73867f59c0659e81904f9a1c7543698e62562d6744c169ce7a36de01a8d6154' - ], - [ - '5e95bb399a6971d376026947f89bde2f282b33810928be4ded112ac4d70e20d5', - '39f23f366809085beebfc71181313775a99c9aed7d8ba38b161384c746012865' - ], - [ - '36e4641a53948fd476c39f8a99fd974e5ec07564b5315d8bf99471bca0ef2f66', - 'd2424b1b1abe4eb8164227b085c9aa9456ea13493fd563e06fd51cf5694c78fc' - ], - [ - '336581ea7bfbbb290c191a2f507a41cf5643842170e914faeab27c2c579f726', - 'ead12168595fe1be99252129b6e56b3391f7ab1410cd1e0ef3dcdcabd2fda224' - ], - [ - '8ab89816dadfd6b6a1f2634fcf00ec8403781025ed6890c4849742706bd43ede', - '6fdcef09f2f6d0a044e654aef624136f503d459c3e89845858a47a9129cdd24e' - ], - [ - '1e33f1a746c9c5778133344d9299fcaa20b0938e8acff2544bb40284b8c5fb94', - '60660257dd11b3aa9c8ed618d24edff2306d320f1d03010e33a7d2057f3b3b6' - ], - [ - '85b7c1dcb3cec1b7ee7f30ded79dd20a0ed1f4cc18cbcfcfa410361fd8f08f31', - '3d98a9cdd026dd43f39048f25a8847f4fcafad1895d7a633c6fed3c35e999511' - ], - [ - '29df9fbd8d9e46509275f4b125d6d45d7fbe9a3b878a7af872a2800661ac5f51', - 'b4c4fe99c775a606e2d8862179139ffda61dc861c019e55cd2876eb2a27d84b' - ], - [ - 'a0b1cae06b0a847a3fea6e671aaf8adfdfe58ca2f768105c8082b2e449fce252', - 'ae434102edde0958ec4b19d917a6a28e6b72da1834aff0e650f049503a296cf2' - ], - [ - '4e8ceafb9b3e9a136dc7ff67e840295b499dfb3b2133e4ba113f2e4c0e121e5', - 'cf2174118c8b6d7a4b48f6d534ce5c79422c086a63460502b827ce62a326683c' - ], - [ - 'd24a44e047e19b6f5afb81c7ca2f69080a5076689a010919f42725c2b789a33b', - '6fb8d5591b466f8fc63db50f1c0f1c69013f996887b8244d2cdec417afea8fa3' - ], - [ - 'ea01606a7a6c9cdd249fdfcfacb99584001edd28abbab77b5104e98e8e3b35d4', - '322af4908c7312b0cfbfe369f7a7b3cdb7d4494bc2823700cfd652188a3ea98d' - ], - [ - 'af8addbf2b661c8a6c6328655eb96651252007d8c5ea31be4ad196de8ce2131f', - '6749e67c029b85f52a034eafd096836b2520818680e26ac8f3dfbcdb71749700' - ], - [ - 'e3ae1974566ca06cc516d47e0fb165a674a3dabcfca15e722f0e3450f45889', - '2aeabe7e4531510116217f07bf4d07300de97e4874f81f533420a72eeb0bd6a4' - ], - [ - '591ee355313d99721cf6993ffed1e3e301993ff3ed258802075ea8ced397e246', - 'b0ea558a113c30bea60fc4775460c7901ff0b053d25ca2bdeee98f1a4be5d196' - ], - [ - '11396d55fda54c49f19aa97318d8da61fa8584e47b084945077cf03255b52984', - '998c74a8cd45ac01289d5833a7beb4744ff536b01b257be4c5767bea93ea57a4' - ], - [ - '3c5d2a1ba39c5a1790000738c9e0c40b8dcdfd5468754b6405540157e017aa7a', - 'b2284279995a34e2f9d4de7396fc18b80f9b8b9fdd270f6661f79ca4c81bd257' - ], - [ - 'cc8704b8a60a0defa3a99a7299f2e9c3fbc395afb04ac078425ef8a1793cc030', - 'bdd46039feed17881d1e0862db347f8cf395b74fc4bcdc4e940b74e3ac1f1b13' - ], - [ - 'c533e4f7ea8555aacd9777ac5cad29b97dd4defccc53ee7ea204119b2889b197', - '6f0a256bc5efdf429a2fb6242f1a43a2d9b925bb4a4b3a26bb8e0f45eb596096' - ], - [ - 'c14f8f2ccb27d6f109f6d08d03cc96a69ba8c34eec07bbcf566d48e33da6593', - 'c359d6923bb398f7fd4473e16fe1c28475b740dd098075e6c0e8649113dc3a38' - ], - [ - 'a6cbc3046bc6a450bac24789fa17115a4c9739ed75f8f21ce441f72e0b90e6ef', - '21ae7f4680e889bb130619e2c0f95a360ceb573c70603139862afd617fa9b9f' - ], - [ - '347d6d9a02c48927ebfb86c1359b1caf130a3c0267d11ce6344b39f99d43cc38', - '60ea7f61a353524d1c987f6ecec92f086d565ab687870cb12689ff1e31c74448' - ], - [ - 'da6545d2181db8d983f7dcb375ef5866d47c67b1bf31c8cf855ef7437b72656a', - '49b96715ab6878a79e78f07ce5680c5d6673051b4935bd897fea824b77dc208a' - ], - [ - 'c40747cc9d012cb1a13b8148309c6de7ec25d6945d657146b9d5994b8feb1111', - '5ca560753be2a12fc6de6caf2cb489565db936156b9514e1bb5e83037e0fa2d4' - ], - [ - '4e42c8ec82c99798ccf3a610be870e78338c7f713348bd34c8203ef4037f3502', - '7571d74ee5e0fb92a7a8b33a07783341a5492144cc54bcc40a94473693606437' - ], - [ - '3775ab7089bc6af823aba2e1af70b236d251cadb0c86743287522a1b3b0dedea', - 'be52d107bcfa09d8bcb9736a828cfa7fac8db17bf7a76a2c42ad961409018cf7' - ], - [ - 'cee31cbf7e34ec379d94fb814d3d775ad954595d1314ba8846959e3e82f74e26', - '8fd64a14c06b589c26b947ae2bcf6bfa0149ef0be14ed4d80f448a01c43b1c6d' - ], - [ - 'b4f9eaea09b6917619f6ea6a4eb5464efddb58fd45b1ebefcdc1a01d08b47986', - '39e5c9925b5a54b07433a4f18c61726f8bb131c012ca542eb24a8ac07200682a' - ], - [ - 'd4263dfc3d2df923a0179a48966d30ce84e2515afc3dccc1b77907792ebcc60e', - '62dfaf07a0f78feb30e30d6295853ce189e127760ad6cf7fae164e122a208d54' - ], - [ - '48457524820fa65a4f8d35eb6930857c0032acc0a4a2de422233eeda897612c4', - '25a748ab367979d98733c38a1fa1c2e7dc6cc07db2d60a9ae7a76aaa49bd0f77' - ], - [ - 'dfeeef1881101f2cb11644f3a2afdfc2045e19919152923f367a1767c11cceda', - 'ecfb7056cf1de042f9420bab396793c0c390bde74b4bbdff16a83ae09a9a7517' - ], - [ - '6d7ef6b17543f8373c573f44e1f389835d89bcbc6062ced36c82df83b8fae859', - 'cd450ec335438986dfefa10c57fea9bcc521a0959b2d80bbf74b190dca712d10' - ], - [ - 'e75605d59102a5a2684500d3b991f2e3f3c88b93225547035af25af66e04541f', - 'f5c54754a8f71ee540b9b48728473e314f729ac5308b06938360990e2bfad125' - ], - [ - 'eb98660f4c4dfaa06a2be453d5020bc99a0c2e60abe388457dd43fefb1ed620c', - '6cb9a8876d9cb8520609af3add26cd20a0a7cd8a9411131ce85f44100099223e' - ], - [ - '13e87b027d8514d35939f2e6892b19922154596941888336dc3563e3b8dba942', - 'fef5a3c68059a6dec5d624114bf1e91aac2b9da568d6abeb2570d55646b8adf1' - ], - [ - 'ee163026e9fd6fe017c38f06a5be6fc125424b371ce2708e7bf4491691e5764a', - '1acb250f255dd61c43d94ccc670d0f58f49ae3fa15b96623e5430da0ad6c62b2' - ], - [ - 'b268f5ef9ad51e4d78de3a750c2dc89b1e626d43505867999932e5db33af3d80', - '5f310d4b3c99b9ebb19f77d41c1dee018cf0d34fd4191614003e945a1216e423' - ], - [ - 'ff07f3118a9df035e9fad85eb6c7bfe42b02f01ca99ceea3bf7ffdba93c4750d', - '438136d603e858a3a5c440c38eccbaddc1d2942114e2eddd4740d098ced1f0d8' - ], - [ - '8d8b9855c7c052a34146fd20ffb658bea4b9f69e0d825ebec16e8c3ce2b526a1', - 'cdb559eedc2d79f926baf44fb84ea4d44bcf50fee51d7ceb30e2e7f463036758' - ], - [ - '52db0b5384dfbf05bfa9d472d7ae26dfe4b851ceca91b1eba54263180da32b63', - 'c3b997d050ee5d423ebaf66a6db9f57b3180c902875679de924b69d84a7b375' - ], - [ - 'e62f9490d3d51da6395efd24e80919cc7d0f29c3f3fa48c6fff543becbd43352', - '6d89ad7ba4876b0b22c2ca280c682862f342c8591f1daf5170e07bfd9ccafa7d' - ], - [ - '7f30ea2476b399b4957509c88f77d0191afa2ff5cb7b14fd6d8e7d65aaab1193', - 'ca5ef7d4b231c94c3b15389a5f6311e9daff7bb67b103e9880ef4bff637acaec' - ], - [ - '5098ff1e1d9f14fb46a210fada6c903fef0fb7b4a1dd1d9ac60a0361800b7a00', - '9731141d81fc8f8084d37c6e7542006b3ee1b40d60dfe5362a5b132fd17ddc0' - ], - [ - '32b78c7de9ee512a72895be6b9cbefa6e2f3c4ccce445c96b9f2c81e2778ad58', - 'ee1849f513df71e32efc3896ee28260c73bb80547ae2275ba497237794c8753c' - ], - [ - 'e2cb74fddc8e9fbcd076eef2a7c72b0ce37d50f08269dfc074b581550547a4f7', - 'd3aa2ed71c9dd2247a62df062736eb0baddea9e36122d2be8641abcb005cc4a4' - ], - [ - '8438447566d4d7bedadc299496ab357426009a35f235cb141be0d99cd10ae3a8', - 'c4e1020916980a4da5d01ac5e6ad330734ef0d7906631c4f2390426b2edd791f' - ], - [ - '4162d488b89402039b584c6fc6c308870587d9c46f660b878ab65c82c711d67e', - '67163e903236289f776f22c25fb8a3afc1732f2b84b4e95dbda47ae5a0852649' - ], - [ - '3fad3fa84caf0f34f0f89bfd2dcf54fc175d767aec3e50684f3ba4a4bf5f683d', - 'cd1bc7cb6cc407bb2f0ca647c718a730cf71872e7d0d2a53fa20efcdfe61826' - ], - [ - '674f2600a3007a00568c1a7ce05d0816c1fb84bf1370798f1c69532faeb1a86b', - '299d21f9413f33b3edf43b257004580b70db57da0b182259e09eecc69e0d38a5' - ], - [ - 'd32f4da54ade74abb81b815ad1fb3b263d82d6c692714bcff87d29bd5ee9f08f', - 'f9429e738b8e53b968e99016c059707782e14f4535359d582fc416910b3eea87' - ], - [ - '30e4e670435385556e593657135845d36fbb6931f72b08cb1ed954f1e3ce3ff6', - '462f9bce619898638499350113bbc9b10a878d35da70740dc695a559eb88db7b' - ], - [ - 'be2062003c51cc3004682904330e4dee7f3dcd10b01e580bf1971b04d4cad297', - '62188bc49d61e5428573d48a74e1c655b1c61090905682a0d5558ed72dccb9bc' - ], - [ - '93144423ace3451ed29e0fb9ac2af211cb6e84a601df5993c419859fff5df04a', - '7c10dfb164c3425f5c71a3f9d7992038f1065224f72bb9d1d902a6d13037b47c' - ], - [ - 'b015f8044f5fcbdcf21ca26d6c34fb8197829205c7b7d2a7cb66418c157b112c', - 'ab8c1e086d04e813744a655b2df8d5f83b3cdc6faa3088c1d3aea1454e3a1d5f' - ], - [ - 'd5e9e1da649d97d89e4868117a465a3a4f8a18de57a140d36b3f2af341a21b52', - '4cb04437f391ed73111a13cc1d4dd0db1693465c2240480d8955e8592f27447a' - ], - [ - 'd3ae41047dd7ca065dbf8ed77b992439983005cd72e16d6f996a5316d36966bb', - 'bd1aeb21ad22ebb22a10f0303417c6d964f8cdd7df0aca614b10dc14d125ac46' - ], - [ - '463e2763d885f958fc66cdd22800f0a487197d0a82e377b49f80af87c897b065', - 'bfefacdb0e5d0fd7df3a311a94de062b26b80c61fbc97508b79992671ef7ca7f' - ], - [ - '7985fdfd127c0567c6f53ec1bb63ec3158e597c40bfe747c83cddfc910641917', - '603c12daf3d9862ef2b25fe1de289aed24ed291e0ec6708703a5bd567f32ed03' - ], - [ - '74a1ad6b5f76e39db2dd249410eac7f99e74c59cb83d2d0ed5ff1543da7703e9', - 'cc6157ef18c9c63cd6193d83631bbea0093e0968942e8c33d5737fd790e0db08' - ], - [ - '30682a50703375f602d416664ba19b7fc9bab42c72747463a71d0896b22f6da3', - '553e04f6b018b4fa6c8f39e7f311d3176290d0e0f19ca73f17714d9977a22ff8' - ], - [ - '9e2158f0d7c0d5f26c3791efefa79597654e7a2b2464f52b1ee6c1347769ef57', - '712fcdd1b9053f09003a3481fa7762e9ffd7c8ef35a38509e2fbf2629008373' - ], - [ - '176e26989a43c9cfeba4029c202538c28172e566e3c4fce7322857f3be327d66', - 'ed8cc9d04b29eb877d270b4878dc43c19aefd31f4eee09ee7b47834c1fa4b1c3' - ], - [ - '75d46efea3771e6e68abb89a13ad747ecf1892393dfc4f1b7004788c50374da8', - '9852390a99507679fd0b86fd2b39a868d7efc22151346e1a3ca4726586a6bed8' - ], - [ - '809a20c67d64900ffb698c4c825f6d5f2310fb0451c869345b7319f645605721', - '9e994980d9917e22b76b061927fa04143d096ccc54963e6a5ebfa5f3f8e286c1' - ], - [ - '1b38903a43f7f114ed4500b4eac7083fdefece1cf29c63528d563446f972c180', - '4036edc931a60ae889353f77fd53de4a2708b26b6f5da72ad3394119daf408f9' - ] - ] - } - }; - - var curves_1 = createCommonjsModule(function (module, exports) { - - var curves = exports; - - - - - - var assert = utils_1$1.assert; - - function PresetCurve(options) { - if (options.type === 'short') - this.curve = new curve_1.short(options); - else if (options.type === 'edwards') - this.curve = new curve_1.edwards(options); - else if (options.type === 'mont') - this.curve = new curve_1.mont(options); - else throw new Error('Unknown curve type.'); - this.g = this.curve.g; - this.n = this.curve.n; - this.hash = options.hash; - - assert(this.g.validate(), 'Invalid curve'); - assert(this.g.mul(this.n).isInfinity(), 'Invalid curve, n*G != O'); - } - curves.PresetCurve = PresetCurve; - - function defineCurve(name, options) { - Object.defineProperty(curves, name, { - configurable: true, - enumerable: true, - get: function() { - var curve = new PresetCurve(options); - Object.defineProperty(curves, name, { - configurable: true, - enumerable: true, - value: curve - }); - return curve; - } - }); - } - - defineCurve('p192', { - type: 'short', - prime: 'p192', - p: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff', - a: 'ffffffff ffffffff ffffffff fffffffe ffffffff fffffffc', - b: '64210519 e59c80e7 0fa7e9ab 72243049 feb8deec c146b9b1', - n: 'ffffffff ffffffff ffffffff 99def836 146bc9b1 b4d22831', - hash: hash_1.sha256, - gRed: false, - g: [ - '188da80e b03090f6 7cbf20eb 43a18800 f4ff0afd 82ff1012', - '07192b95 ffc8da78 631011ed 6b24cdd5 73f977a1 1e794811' - ] - }); - - defineCurve('p224', { - type: 'short', - prime: 'p224', - p: 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001', - a: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff fffffffe', - b: 'b4050a85 0c04b3ab f5413256 5044b0b7 d7bfd8ba 270b3943 2355ffb4', - n: 'ffffffff ffffffff ffffffff ffff16a2 e0b8f03e 13dd2945 5c5c2a3d', - hash: hash_1.sha256, - gRed: false, - g: [ - 'b70e0cbd 6bb4bf7f 321390b9 4a03c1d3 56c21122 343280d6 115c1d21', - 'bd376388 b5f723fb 4c22dfe6 cd4375a0 5a074764 44d58199 85007e34' - ] - }); - - defineCurve('p256', { - type: 'short', - prime: null, - p: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff', - a: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff fffffffc', - b: '5ac635d8 aa3a93e7 b3ebbd55 769886bc 651d06b0 cc53b0f6 3bce3c3e 27d2604b', - n: 'ffffffff 00000000 ffffffff ffffffff bce6faad a7179e84 f3b9cac2 fc632551', - hash: hash_1.sha256, - gRed: false, - g: [ - '6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296', - '4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5' - ] - }); - - defineCurve('p384', { - type: 'short', - prime: null, - p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'fffffffe ffffffff 00000000 00000000 ffffffff', - a: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'fffffffe ffffffff 00000000 00000000 fffffffc', - b: 'b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112 0314088f ' + - '5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef', - n: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff c7634d81 ' + - 'f4372ddf 581a0db2 48b0a77a ecec196a ccc52973', - hash: hash_1.sha384, - gRed: false, - g: [ - 'aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98 59f741e0 82542a38 ' + - '5502f25d bf55296c 3a545e38 72760ab7', - '3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c e9da3113 b5f0b8c0 ' + - '0a60b1ce 1d7e819d 7a431d7c 90ea0e5f' - ] - }); - - defineCurve('p521', { - type: 'short', - prime: null, - p: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff ffffffff', - a: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff fffffffc', - b: '00000051 953eb961 8e1c9a1f 929a21a0 b68540ee a2da725b ' + - '99b315f3 b8b48991 8ef109e1 56193951 ec7e937b 1652c0bd ' + - '3bb1bf07 3573df88 3d2c34f1 ef451fd4 6b503f00', - n: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff fffffffa 51868783 bf2f966b 7fcc0148 ' + - 'f709a5d0 3bb5c9b8 899c47ae bb6fb71e 91386409', - hash: hash_1.sha512, - gRed: false, - g: [ - '000000c6 858e06b7 0404e9cd 9e3ecb66 2395b442 9c648139 ' + - '053fb521 f828af60 6b4d3dba a14b5e77 efe75928 fe1dc127 ' + - 'a2ffa8de 3348b3c1 856a429b f97e7e31 c2e5bd66', - '00000118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd9 98f54449 ' + - '579b4468 17afbd17 273e662c 97ee7299 5ef42640 c550b901 ' + - '3fad0761 353c7086 a272c240 88be9476 9fd16650' - ] - }); - - // https://tools.ietf.org/html/rfc7748#section-4.1 - defineCurve('curve25519', { - type: 'mont', - prime: 'p25519', - p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', - a: '76d06', - b: '1', - n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', - cofactor: '8', - hash: hash_1.sha256, - gRed: false, - g: [ - '9' - ] - }); - - defineCurve('ed25519', { - type: 'edwards', - prime: 'p25519', - p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', - a: '-1', - c: '1', - // -121665 * (121666^(-1)) (mod P) - d: '52036cee2b6ffe73 8cc740797779e898 00700a4d4141d8ab 75eb4dca135978a3', - n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', - cofactor: '8', - hash: hash_1.sha256, - gRed: false, - g: [ - '216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a', - // 4/5 - '6666666666666666666666666666666666666666666666666666666666666658' - ] - }); - - // https://tools.ietf.org/html/rfc5639#section-3.4 - defineCurve('brainpoolP256r1', { - type: 'short', - prime: null, - p: 'A9FB57DB A1EEA9BC 3E660A90 9D838D72 6E3BF623 D5262028 2013481D 1F6E5377', - a: '7D5A0975 FC2C3057 EEF67530 417AFFE7 FB8055C1 26DC5C6C E94A4B44 F330B5D9', - b: '26DC5C6C E94A4B44 F330B5D9 BBD77CBF 95841629 5CF7E1CE 6BCCDC18 FF8C07B6', - n: 'A9FB57DB A1EEA9BC 3E660A90 9D838D71 8C397AA3 B561A6F7 901E0E82 974856A7', - hash: hash_1.sha256, // or 384, or 512 - gRed: false, - g: [ - '8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262', - '547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997' - ] - }); - - // https://tools.ietf.org/html/rfc5639#section-3.6 - defineCurve('brainpoolP384r1', { - type: 'short', - prime: null, - p: '8CB91E82 A3386D28 0F5D6F7E 50E641DF 152F7109 ED5456B4 12B1DA19 7FB71123' + - 'ACD3A729 901D1A71 87470013 3107EC53', - a: '7BC382C6 3D8C150C 3C72080A CE05AFA0 C2BEA28E 4FB22787 139165EF BA91F90F' + - '8AA5814A 503AD4EB 04A8C7DD 22CE2826', - b: '04A8C7DD 22CE2826 8B39B554 16F0447C 2FB77DE1 07DCD2A6 2E880EA5 3EEB62D5' + - '7CB43902 95DBC994 3AB78696 FA504C11', - n: '8CB91E82 A3386D28 0F5D6F7E 50E641DF 152F7109 ED5456B3 1F166E6C AC0425A7' + - 'CF3AB6AF 6B7FC310 3B883202 E9046565', - hash: hash_1.sha384, // or 512 - gRed: false, - g: [ - '1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10' + - 'E8E826E03436D646AAEF87B2E247D4AF1E', - '8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129' + - '280E4646217791811142820341263C5315' - ] - }); - - // https://tools.ietf.org/html/rfc5639#section-3.7 - defineCurve('brainpoolP512r1', { - type: 'short', - prime: null, - p: 'AADD9DB8 DBE9C48B 3FD4E6AE 33C9FC07 CB308DB3 B3C9D20E D6639CCA 70330871' + - '7D4D9B00 9BC66842 AECDA12A E6A380E6 2881FF2F 2D82C685 28AA6056 583A48F3', - a: '7830A331 8B603B89 E2327145 AC234CC5 94CBDD8D 3DF91610 A83441CA EA9863BC' + - '2DED5D5A A8253AA1 0A2EF1C9 8B9AC8B5 7F1117A7 2BF2C7B9 E7C1AC4D 77FC94CA', - b: '3DF91610 A83441CA EA9863BC 2DED5D5A A8253AA1 0A2EF1C9 8B9AC8B5 7F1117A7' + - '2BF2C7B9 E7C1AC4D 77FC94CA DC083E67 984050B7 5EBAE5DD 2809BD63 8016F723', - n: 'AADD9DB8 DBE9C48B 3FD4E6AE 33C9FC07 CB308DB3 B3C9D20E D6639CCA 70330870' + - '553E5C41 4CA92619 41866119 7FAC1047 1DB1D381 085DDADD B5879682 9CA90069', - hash: hash_1.sha512, - gRed: false, - g: [ - '81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D009' + - '8EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822', - '7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F81' + - '11B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892' - ] - }); - - // https://en.bitcoin.it/wiki/Secp256k1 - var pre; - try { - pre = secp256k1; - } catch (e) { - pre = undefined; - } - - defineCurve('secp256k1', { - type: 'short', - prime: 'k256', - p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f', - a: '0', - b: '7', - n: 'ffffffff ffffffff ffffffff fffffffe baaedce6 af48a03b bfd25e8c d0364141', - h: '1', - hash: hash_1.sha256, - - // Precomputed endomorphism - beta: '7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee', - lambda: '5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72', - basis: [ - { - a: '3086d221a7d46bcde86c90e49284eb15', - b: '-e4437ed6010e88286f547fa90abfe4c3' - }, - { - a: '114ca50f7a8e2f3f657c1108d9d44cfd8', - b: '3086d221a7d46bcde86c90e49284eb15' - } - ], - - gRed: false, - g: [ - '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', - '483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', - pre - ] - }); - }); - - function HmacDRBG(options) { - if (!(this instanceof HmacDRBG)) - return new HmacDRBG(options); - this.hash = options.hash; - this.predResist = !!options.predResist; - - this.outLen = this.hash.outSize; - this.minEntropy = options.minEntropy || this.hash.hmacStrength; - - this._reseed = null; - this.reseedInterval = null; - this.K = null; - this.V = null; - - var entropy = utils_1.toArray(options.entropy, options.entropyEnc || 'hex'); - var nonce = utils_1.toArray(options.nonce, options.nonceEnc || 'hex'); - var pers = utils_1.toArray(options.pers, options.persEnc || 'hex'); - minimalisticAssert(entropy.length >= (this.minEntropy / 8), - 'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits'); - this._init(entropy, nonce, pers); - } - var hmacDrbg = HmacDRBG; - - HmacDRBG.prototype._init = function init(entropy, nonce, pers) { - var seed = entropy.concat(nonce).concat(pers); - - this.K = new Array(this.outLen / 8); - this.V = new Array(this.outLen / 8); - for (var i = 0; i < this.V.length; i++) { - this.K[i] = 0x00; - this.V[i] = 0x01; - } - - this._update(seed); - this._reseed = 1; - this.reseedInterval = 0x1000000000000; // 2^48 - }; - - HmacDRBG.prototype._hmac = function hmac() { - return new hash_1.hmac(this.hash, this.K); - }; - - HmacDRBG.prototype._update = function update(seed) { - var kmac = this._hmac() - .update(this.V) - .update([ 0x00 ]); - if (seed) - kmac = kmac.update(seed); - this.K = kmac.digest(); - this.V = this._hmac().update(this.V).digest(); - if (!seed) - return; - - this.K = this._hmac() - .update(this.V) - .update([ 0x01 ]) - .update(seed) - .digest(); - this.V = this._hmac().update(this.V).digest(); - }; - - HmacDRBG.prototype.reseed = function reseed(entropy, entropyEnc, add, addEnc) { - // Optional entropy enc - if (typeof entropyEnc !== 'string') { - addEnc = add; - add = entropyEnc; - entropyEnc = null; - } - - entropy = utils_1.toArray(entropy, entropyEnc); - add = utils_1.toArray(add, addEnc); - - minimalisticAssert(entropy.length >= (this.minEntropy / 8), - 'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits'); - - this._update(entropy.concat(add || [])); - this._reseed = 1; - }; - - HmacDRBG.prototype.generate = function generate(len, enc, add, addEnc) { - if (this._reseed > this.reseedInterval) - throw new Error('Reseed is required'); - - // Optional encoding - if (typeof enc !== 'string') { - addEnc = add; - add = enc; - enc = null; - } - - // Optional additional data - if (add) { - add = utils_1.toArray(add, addEnc || 'hex'); - this._update(add); - } - - var temp = []; - while (temp.length < len) { - this.V = this._hmac().update(this.V).digest(); - temp = temp.concat(this.V); - } - - var res = temp.slice(0, len); - this._update(add); - this._reseed++; - return utils_1.encode(res, enc); - }; - - var assert$5 = utils_1$1.assert; - - function KeyPair(ec, options) { - this.ec = ec; - this.priv = null; - this.pub = null; - - // KeyPair(ec, { priv: ..., pub: ... }) - if (options.priv) - this._importPrivate(options.priv, options.privEnc); - if (options.pub) - this._importPublic(options.pub, options.pubEnc); - } - var key = KeyPair; - - KeyPair.fromPublic = function fromPublic(ec, pub, enc) { - if (pub instanceof KeyPair) - return pub; - - return new KeyPair(ec, { - pub: pub, - pubEnc: enc - }); - }; - - KeyPair.fromPrivate = function fromPrivate(ec, priv, enc) { - if (priv instanceof KeyPair) - return priv; - - return new KeyPair(ec, { - priv: priv, - privEnc: enc - }); - }; - - // TODO: should not validate for X25519 - KeyPair.prototype.validate = function validate() { - var pub = this.getPublic(); - - if (pub.isInfinity()) - return { result: false, reason: 'Invalid public key' }; - if (!pub.validate()) - return { result: false, reason: 'Public key is not a point' }; - if (!pub.mul(this.ec.curve.n).isInfinity()) - return { result: false, reason: 'Public key * N != O' }; - - return { result: true, reason: null }; - }; - - KeyPair.prototype.getPublic = function getPublic(enc, compact) { - if (!this.pub) - this.pub = this.ec.g.mul(this.priv); - - if (!enc) - return this.pub; - - return this.pub.encode(enc, compact); - }; - - KeyPair.prototype.getPrivate = function getPrivate(enc) { - if (enc === 'hex') - return this.priv.toString(16, 2); - else - return this.priv; - }; - - KeyPair.prototype._importPrivate = function _importPrivate(key, enc) { - this.priv = new bn(key, enc || 16); - - // For Curve25519/Curve448 we have a specific procedure. - // TODO Curve448 - if (this.ec.curve.type === 'mont') { - var one = this.ec.curve.one; - var mask = one.ushln(255 - 3).sub(one).ushln(3); - this.priv = this.priv.or(one.ushln(255 - 1)); - this.priv = this.priv.and(mask); - } else - // Ensure that the priv won't be bigger than n, otherwise we may fail - // in fixed multiplication method - this.priv = this.priv.umod(this.ec.curve.n); - }; - - KeyPair.prototype._importPublic = function _importPublic(key, enc) { - if (key.x || key.y) { - // Montgomery points only have an `x` coordinate. - // Weierstrass/Edwards points on the other hand have both `x` and - // `y` coordinates. - if (this.ec.curve.type === 'mont') { - assert$5(key.x, 'Need x coordinate'); - } else if (this.ec.curve.type === 'short' || - this.ec.curve.type === 'edwards') { - assert$5(key.x && key.y, 'Need both x and y coordinate'); - } - this.pub = this.ec.curve.point(key.x, key.y); - return; - } - this.pub = this.ec.curve.decodePoint(key, enc); - }; - - // ECDH - KeyPair.prototype.derive = function derive(pub) { - return pub.mul(this.priv).getX(); - }; - - // ECDSA - KeyPair.prototype.sign = function sign(msg, enc, options) { - return this.ec.sign(msg, this, enc, options); - }; - - KeyPair.prototype.verify = function verify(msg, signature) { - return this.ec.verify(msg, signature, this); - }; - - KeyPair.prototype.inspect = function inspect() { - return ''; - }; - - var assert$6 = utils_1$1.assert; - - function Signature$1(options, enc) { - if (options instanceof Signature$1) - return options; - - if (this._importDER(options, enc)) - return; - - assert$6(options.r && options.s, 'Signature without r or s'); - this.r = new bn(options.r, 16); - this.s = new bn(options.s, 16); - if (options.recoveryParam === undefined) - this.recoveryParam = null; - else - this.recoveryParam = options.recoveryParam; - } - var signature$1 = Signature$1; - - function Position() { - this.place = 0; - } - - function getLength(buf, p) { - var initial = buf[p.place++]; - if (!(initial & 0x80)) { - return initial; - } - var octetLen = initial & 0xf; - var val = 0; - for (var i = 0, off = p.place; i < octetLen; i++, off++) { - val <<= 8; - val |= buf[off]; - } - p.place = off; - return val; - } - - function rmPadding(buf) { - var i = 0; - var len = buf.length - 1; - while (!buf[i] && !(buf[i + 1] & 0x80) && i < len) { - i++; - } - if (i === 0) { - return buf; - } - return buf.slice(i); - } - - Signature$1.prototype._importDER = function _importDER(data, enc) { - data = utils_1$1.toArray(data, enc); - var p = new Position(); - if (data[p.place++] !== 0x30) { - return false; - } - var len = getLength(data, p); - if ((len + p.place) !== data.length) { - return false; - } - if (data[p.place++] !== 0x02) { - return false; - } - var rlen = getLength(data, p); - var r = data.slice(p.place, rlen + p.place); - p.place += rlen; - if (data[p.place++] !== 0x02) { - return false; - } - var slen = getLength(data, p); - if (data.length !== slen + p.place) { - return false; - } - var s = data.slice(p.place, slen + p.place); - if (r[0] === 0 && (r[1] & 0x80)) { - r = r.slice(1); - } - if (s[0] === 0 && (s[1] & 0x80)) { - s = s.slice(1); - } - - this.r = new bn(r); - this.s = new bn(s); - this.recoveryParam = null; - - return true; - }; - - function constructLength(arr, len) { - if (len < 0x80) { - arr.push(len); - return; - } - var octets = 1 + (Math.log(len) / Math.LN2 >>> 3); - arr.push(octets | 0x80); - while (--octets) { - arr.push((len >>> (octets << 3)) & 0xff); - } - arr.push(len); - } - - Signature$1.prototype.toDER = function toDER(enc) { - var r = this.r.toArray(); - var s = this.s.toArray(); - - // Pad values - if (r[0] & 0x80) - r = [ 0 ].concat(r); - // Pad values - if (s[0] & 0x80) - s = [ 0 ].concat(s); - - r = rmPadding(r); - s = rmPadding(s); - - while (!s[0] && !(s[1] & 0x80)) { - s = s.slice(1); - } - var arr = [ 0x02 ]; - constructLength(arr, r.length); - arr = arr.concat(r); - arr.push(0x02); - constructLength(arr, s.length); - var backHalf = arr.concat(s); - var res = [ 0x30 ]; - constructLength(res, backHalf.length); - res = res.concat(backHalf); - return utils_1$1.encode(res, enc); - }; - - var assert$7 = utils_1$1.assert; - - - - - function EC(options) { - if (!(this instanceof EC)) - return new EC(options); - - // Shortcut `elliptic.ec(curve-name)` - if (typeof options === 'string') { - assert$7(curves_1.hasOwnProperty(options), 'Unknown curve ' + options); - - options = curves_1[options]; - } - - // Shortcut for `elliptic.ec(elliptic.curves.curveName)` - if (options instanceof curves_1.PresetCurve) - options = { curve: options }; - - this.curve = options.curve.curve; - this.n = this.curve.n; - this.nh = this.n.ushrn(1); - this.g = this.curve.g; - - // Point on curve - this.g = options.curve.g; - this.g.precompute(options.curve.n.bitLength() + 1); - - // Hash function for DRBG - this.hash = options.hash || options.curve.hash; - } - var ec = EC; - - EC.prototype.keyPair = function keyPair(options) { - return new key(this, options); - }; - - EC.prototype.keyFromPrivate = function keyFromPrivate(priv, enc) { - return key.fromPrivate(this, priv, enc); - }; - - EC.prototype.keyFromPublic = function keyFromPublic(pub, enc) { - return key.fromPublic(this, pub, enc); - }; - - EC.prototype.genKeyPair = function genKeyPair(options) { - if (!options) - options = {}; - - // Instantiate Hmac_DRBG - var drbg = new hmacDrbg({ - hash: this.hash, - pers: options.pers, - persEnc: options.persEnc || 'utf8', - entropy: options.entropy || brorand(this.hash.hmacStrength), - entropyEnc: options.entropy && options.entropyEnc || 'utf8', - nonce: this.n.toArray() - }); - - // Key generation for curve25519 is simpler - if (this.curve.type === 'mont') { - var priv = new bn(drbg.generate(32)); - return this.keyFromPrivate(priv); - } - - var bytes = this.n.byteLength(); - var ns2 = this.n.sub(new bn(2)); - do { - var priv = new bn(drbg.generate(bytes)); - if (priv.cmp(ns2) > 0) - continue; - - priv.iaddn(1); - return this.keyFromPrivate(priv); - } while (true); - }; - - EC.prototype._truncateToN = function truncateToN(msg, truncOnly, bitSize) { - bitSize = bitSize || msg.byteLength() * 8; - var delta = bitSize - this.n.bitLength(); - if (delta > 0) - msg = msg.ushrn(delta); - if (!truncOnly && msg.cmp(this.n) >= 0) - return msg.sub(this.n); - else - return msg; - }; - - EC.prototype.truncateMsg = function truncateMSG(msg) { - // Bit size is only determined correctly for Uint8Arrays and hex strings - var bitSize; - if (msg instanceof Uint8Array) { - bitSize = msg.byteLength * 8; - msg = this._truncateToN(new bn(msg, 16), false, bitSize); - } else if (typeof msg === 'string') { - bitSize = msg.length * 4; - msg = this._truncateToN(new bn(msg, 16), false, bitSize); - } else { - msg = this._truncateToN(new bn(msg, 16)); - } - return msg; - }; - - EC.prototype.sign = function sign(msg, key, enc, options) { - if (typeof enc === 'object') { - options = enc; - enc = null; - } - if (!options) - options = {}; - - key = this.keyFromPrivate(key, enc); - msg = this.truncateMsg(msg); - - // Zero-extend key to provide enough entropy - var bytes = this.n.byteLength(); - var bkey = key.getPrivate().toArray('be', bytes); - - // Zero-extend nonce to have the same byte size as N - var nonce = msg.toArray('be', bytes); - - // Instantiate Hmac_DRBG - var drbg = new hmacDrbg({ - hash: this.hash, - entropy: bkey, - nonce: nonce, - pers: options.pers, - persEnc: options.persEnc || 'utf8' - }); - - // Number of bytes to generate - var ns1 = this.n.sub(new bn(1)); - - for (var iter = 0; true; iter++) { - var k = options.k ? - options.k(iter) : - new bn(drbg.generate(this.n.byteLength())); - k = this._truncateToN(k, true); - if (k.cmpn(1) <= 0 || k.cmp(ns1) >= 0) - continue; - - var kp = this.g.mul(k); - if (kp.isInfinity()) - continue; - - var kpX = kp.getX(); - var r = kpX.umod(this.n); - if (r.cmpn(0) === 0) - continue; - - var s = k.invm(this.n).mul(r.mul(key.getPrivate()).iadd(msg)); - s = s.umod(this.n); - if (s.cmpn(0) === 0) - continue; - - var recoveryParam = (kp.getY().isOdd() ? 1 : 0) | - (kpX.cmp(r) !== 0 ? 2 : 0); - - // Use complement of `s`, if it is > `n / 2` - if (options.canonical && s.cmp(this.nh) > 0) { - s = this.n.sub(s); - recoveryParam ^= 1; - } - - return new signature$1({ r: r, s: s, recoveryParam: recoveryParam }); - } - }; - - EC.prototype.verify = function verify(msg, signature, key, enc) { - key = this.keyFromPublic(key, enc); - signature = new signature$1(signature, 'hex'); - // Fallback to the old code - var ret = this._verify(this.truncateMsg(msg), signature, key) || - this._verify(this._truncateToN(new bn(msg, 16)), signature, key); - return ret; - }; - - EC.prototype._verify = function _verify(msg, signature, key) { - // Perform primitive values validation - var r = signature.r; - var s = signature.s; - if (r.cmpn(1) < 0 || r.cmp(this.n) >= 0) - return false; - if (s.cmpn(1) < 0 || s.cmp(this.n) >= 0) - return false; - - // Validate signature - var sinv = s.invm(this.n); - var u1 = sinv.mul(msg).umod(this.n); - var u2 = sinv.mul(r).umod(this.n); - - if (!this.curve._maxwellTrick) { - var p = this.g.mulAdd(u1, key.getPublic(), u2); - if (p.isInfinity()) - return false; - - return p.getX().umod(this.n).cmp(r) === 0; - } - - // NOTE: Greg Maxwell's trick, inspired by: - // https://git.io/vad3K - - var p = this.g.jmulAdd(u1, key.getPublic(), u2); - if (p.isInfinity()) - return false; - - // Compare `p.x` of Jacobian point with `r`, - // this will do `p.x == r * p.z^2` instead of multiplying `p.x` by the - // inverse of `p.z^2` - return p.eqXToP(r); - }; - - EC.prototype.recoverPubKey = function(msg, signature, j, enc) { - assert$7((3 & j) === j, 'The recovery param is more than two bits'); - signature = new signature$1(signature, enc); - - var n = this.n; - var e = new bn(msg); - var r = signature.r; - var s = signature.s; - - // A set LSB signifies that the y-coordinate is odd - var isYOdd = j & 1; - var isSecondKey = j >> 1; - if (r.cmp(this.curve.p.umod(this.curve.n)) >= 0 && isSecondKey) - throw new Error('Unable to find sencond key candinate'); - - // 1.1. Let x = r + jn. - if (isSecondKey) - r = this.curve.pointFromX(r.add(this.curve.n), isYOdd); - else - r = this.curve.pointFromX(r, isYOdd); - - var rInv = signature.r.invm(n); - var s1 = n.sub(e).mul(rInv).umod(n); - var s2 = s.mul(rInv).umod(n); - - // 1.6.1 Compute Q = r^-1 (sR - eG) - // Q = r^-1 (sR + -eG) - return this.g.mulAdd(s1, r, s2); - }; - - EC.prototype.getKeyRecoveryParam = function(e, signature, Q, enc) { - signature = new signature$1(signature, enc); - if (signature.recoveryParam !== null) - return signature.recoveryParam; - - for (var i = 0; i < 4; i++) { - var Qprime; - try { - Qprime = this.recoverPubKey(e, signature, i); - } catch (e) { - continue; - } - - if (Qprime.eq(Q)) - return i; - } - throw new Error('Unable to find valid recovery factor'); - }; - - var assert$8 = utils_1$1.assert; - var parseBytes = utils_1$1.parseBytes; - var cachedProperty = utils_1$1.cachedProperty; - - /** - * @param {EDDSA} eddsa - instance - * @param {Object} params - public/private key parameters - * - * @param {Array} [params.secret] - secret seed bytes - * @param {Point} [params.pub] - public key point (aka `A` in eddsa terms) - * @param {Array} [params.pub] - public key point encoded as bytes - * - */ - function KeyPair$1(eddsa, params) { - this.eddsa = eddsa; - if (params.hasOwnProperty('secret')) - this._secret = parseBytes(params.secret); - if (eddsa.isPoint(params.pub)) - this._pub = params.pub; - else { - this._pubBytes = parseBytes(params.pub); - if (this._pubBytes && this._pubBytes.length === 33 && - this._pubBytes[0] === 0x40) - this._pubBytes = this._pubBytes.slice(1, 33); - if (this._pubBytes && this._pubBytes.length !== 32) - throw new Error('Unknown point compression format'); - } - } - - KeyPair$1.fromPublic = function fromPublic(eddsa, pub) { - if (pub instanceof KeyPair$1) - return pub; - return new KeyPair$1(eddsa, { pub: pub }); - }; - - KeyPair$1.fromSecret = function fromSecret(eddsa, secret) { - if (secret instanceof KeyPair$1) - return secret; - return new KeyPair$1(eddsa, { secret: secret }); - }; - - KeyPair$1.prototype.secret = function secret() { - return this._secret; - }; - - cachedProperty(KeyPair$1, 'pubBytes', function pubBytes() { - return this.eddsa.encodePoint(this.pub()); - }); - - cachedProperty(KeyPair$1, 'pub', function pub() { - if (this._pubBytes) - return this.eddsa.decodePoint(this._pubBytes); - return this.eddsa.g.mul(this.priv()); - }); - - cachedProperty(KeyPair$1, 'privBytes', function privBytes() { - var eddsa = this.eddsa; - var hash = this.hash(); - var lastIx = eddsa.encodingLength - 1; - - // https://tools.ietf.org/html/rfc8032#section-5.1.5 - var a = hash.slice(0, eddsa.encodingLength); - a[0] &= 248; - a[lastIx] &= 127; - a[lastIx] |= 64; - - return a; - }); - - cachedProperty(KeyPair$1, 'priv', function priv() { - return this.eddsa.decodeInt(this.privBytes()); - }); - - cachedProperty(KeyPair$1, 'hash', function hash() { - return this.eddsa.hash().update(this.secret()).digest(); - }); - - cachedProperty(KeyPair$1, 'messagePrefix', function messagePrefix() { - return this.hash().slice(this.eddsa.encodingLength); - }); - - KeyPair$1.prototype.sign = function sign(message) { - assert$8(this._secret, 'KeyPair can only verify'); - return this.eddsa.sign(message, this); - }; - - KeyPair$1.prototype.verify = function verify(message, sig) { - return this.eddsa.verify(message, sig, this); - }; - - KeyPair$1.prototype.getSecret = function getSecret(enc) { - assert$8(this._secret, 'KeyPair is public only'); - return utils_1$1.encode(this.secret(), enc); - }; - - KeyPair$1.prototype.getPublic = function getPublic(enc, compact) { - return utils_1$1.encode((compact ? [ 0x40 ] : []).concat(this.pubBytes()), enc); - }; - - var key$1 = KeyPair$1; - - var assert$9 = utils_1$1.assert; - var cachedProperty$1 = utils_1$1.cachedProperty; - var parseBytes$1 = utils_1$1.parseBytes; - - /** - * @param {EDDSA} eddsa - eddsa instance - * @param {Array|Object} sig - - * @param {Array|Point} [sig.R] - R point as Point or bytes - * @param {Array|bn} [sig.S] - S scalar as bn or bytes - * @param {Array} [sig.Rencoded] - R point encoded - * @param {Array} [sig.Sencoded] - S scalar encoded - */ - function Signature$2(eddsa, sig) { - this.eddsa = eddsa; - - if (typeof sig !== 'object') - sig = parseBytes$1(sig); - - if (Array.isArray(sig)) { - sig = { - R: sig.slice(0, eddsa.encodingLength), - S: sig.slice(eddsa.encodingLength) - }; - } - - assert$9(sig.R && sig.S, 'Signature without R or S'); - - if (eddsa.isPoint(sig.R)) - this._R = sig.R; - if (sig.S instanceof bn) - this._S = sig.S; - - this._Rencoded = Array.isArray(sig.R) ? sig.R : sig.Rencoded; - this._Sencoded = Array.isArray(sig.S) ? sig.S : sig.Sencoded; - } - - cachedProperty$1(Signature$2, 'S', function S() { - return this.eddsa.decodeInt(this.Sencoded()); - }); - - cachedProperty$1(Signature$2, 'R', function R() { - return this.eddsa.decodePoint(this.Rencoded()); - }); - - cachedProperty$1(Signature$2, 'Rencoded', function Rencoded() { - return this.eddsa.encodePoint(this.R()); - }); - - cachedProperty$1(Signature$2, 'Sencoded', function Sencoded() { - return this.eddsa.encodeInt(this.S()); - }); - - Signature$2.prototype.toBytes = function toBytes() { - return this.Rencoded().concat(this.Sencoded()); - }; - - Signature$2.prototype.toHex = function toHex() { - return utils_1$1.encode(this.toBytes(), 'hex').toUpperCase(); - }; - - var signature$2 = Signature$2; - - var assert$a = utils_1$1.assert; - var parseBytes$2 = utils_1$1.parseBytes; - - - - function EDDSA(curve) { - assert$a(curve === 'ed25519', 'only tested with ed25519 so far'); - - if (!(this instanceof EDDSA)) - return new EDDSA(curve); - - var curve = curves_1[curve].curve; - this.curve = curve; - this.g = curve.g; - this.g.precompute(curve.n.bitLength() + 1); - - this.pointClass = curve.point().constructor; - this.encodingLength = Math.ceil(curve.n.bitLength() / 8); - this.hash = hash_1.sha512; - } - - var eddsa$1 = EDDSA; - - /** - * @param {Array|String} message - message bytes - * @param {Array|String|KeyPair} secret - secret bytes or a keypair - * @returns {Signature} - signature - */ - EDDSA.prototype.sign = function sign(message, secret) { - message = parseBytes$2(message); - var key = this.keyFromSecret(secret); - var r = this.hashInt(key.messagePrefix(), message); - var R = this.g.mul(r); - var Rencoded = this.encodePoint(R); - var s_ = this.hashInt(Rencoded, key.pubBytes(), message) - .mul(key.priv()); - var S = r.add(s_).umod(this.curve.n); - return this.makeSignature({ R: R, S: S, Rencoded: Rencoded }); - }; - - /** - * @param {Array} message - message bytes - * @param {Array|String|Signature} sig - sig bytes - * @param {Array|String|Point|KeyPair} pub - public key - * @returns {Boolean} - true if public key matches sig of message - */ - EDDSA.prototype.verify = function verify(message, sig, pub) { - message = parseBytes$2(message); - sig = this.makeSignature(sig); - var key = this.keyFromPublic(pub); - var h = this.hashInt(sig.Rencoded(), key.pubBytes(), message); - var SG = this.g.mul(sig.S()); - var RplusAh = sig.R().add(key.pub().mul(h)); - return RplusAh.eq(SG); - }; - - EDDSA.prototype.hashInt = function hashInt() { - var hash = this.hash(); - for (var i = 0; i < arguments.length; i++) - hash.update(arguments[i]); - return utils_1$1.intFromLE(hash.digest()).umod(this.curve.n); - }; - - EDDSA.prototype.keyPair = function keyPair(options) { - return new key$1(this, options); - }; - - EDDSA.prototype.keyFromPublic = function keyFromPublic(pub) { - return key$1.fromPublic(this, pub); - }; - - EDDSA.prototype.keyFromSecret = function keyFromSecret(secret) { - return key$1.fromSecret(this, secret); - }; - - EDDSA.prototype.genKeyPair = function genKeyPair(options) { - if (!options) - options = {}; - - // Instantiate Hmac_DRBG - var drbg = new hmacDrbg({ - hash: this.hash, - pers: options.pers, - persEnc: options.persEnc || 'utf8', - entropy: options.entropy || brorand(this.hash.hmacStrength), - entropyEnc: options.entropy && options.entropyEnc || 'utf8', - nonce: this.curve.n.toArray() - }); - - return this.keyFromSecret(drbg.generate(32)); - }; - - EDDSA.prototype.makeSignature = function makeSignature(sig) { - if (sig instanceof signature$2) - return sig; - return new signature$2(this, sig); - }; - - /** - * * https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03#section-5.2 - * - * EDDSA defines methods for encoding and decoding points and integers. These are - * helper convenience methods, that pass along to utility functions implied - * parameters. - * - */ - EDDSA.prototype.encodePoint = function encodePoint(point) { - var enc = point.getY().toArray('le', this.encodingLength); - enc[this.encodingLength - 1] |= point.getX().isOdd() ? 0x80 : 0; - return enc; - }; - - EDDSA.prototype.decodePoint = function decodePoint(bytes) { - bytes = utils_1$1.parseBytes(bytes); - - var lastIx = bytes.length - 1; - var normed = bytes.slice(0, lastIx).concat(bytes[lastIx] & ~0x80); - var xIsOdd = (bytes[lastIx] & 0x80) !== 0; - - var y = utils_1$1.intFromLE(normed); - return this.curve.pointFromY(y, xIsOdd); - }; - - EDDSA.prototype.encodeInt = function encodeInt(num) { - return num.toArray('le', this.encodingLength); - }; - - EDDSA.prototype.decodeInt = function decodeInt(bytes) { - return utils_1$1.intFromLE(bytes); - }; - - EDDSA.prototype.isPoint = function isPoint(val) { - return val instanceof this.pointClass; - }; - - var elliptic_1 = createCommonjsModule(function (module, exports) { - - var elliptic = exports; - - elliptic.utils = utils_1$1; - elliptic.rand = brorand; - elliptic.curve = curve_1; - elliptic.curves = curves_1; - - // Protocols - elliptic.ec = ec; - elliptic.eddsa = eddsa$1; - }); - - var elliptic$1 = /*#__PURE__*/Object.freeze({ - __proto__: null, - 'default': elliptic_1, - __moduleExports: elliptic_1 - }); - - exports.AEADEncryptedDataPacket = AEADEncryptedDataPacket; - exports.CleartextMessage = CleartextMessage; - exports.CompressedDataPacket = CompressedDataPacket; - exports.LiteralDataPacket = LiteralDataPacket; - exports.MarkerPacket = MarkerPacket; - exports.Message = Message; - exports.OnePassSignaturePacket = OnePassSignaturePacket; - exports.PacketList = PacketList; - exports.PrivateKey = PrivateKey; - exports.PublicKey = PublicKey; - exports.PublicKeyEncryptedSessionKeyPacket = PublicKeyEncryptedSessionKeyPacket; - exports.PublicKeyPacket = PublicKeyPacket; - exports.PublicSubkeyPacket = PublicSubkeyPacket; - exports.SecretKeyPacket = SecretKeyPacket; - exports.SecretSubkeyPacket = SecretSubkeyPacket; - exports.Signature = Signature; - exports.SignaturePacket = SignaturePacket; - exports.Subkey = Subkey; - exports.SymEncryptedIntegrityProtectedDataPacket = SymEncryptedIntegrityProtectedDataPacket; - exports.SymEncryptedSessionKeyPacket = SymEncryptedSessionKeyPacket; - exports.SymmetricallyEncryptedDataPacket = SymmetricallyEncryptedDataPacket; - exports.TrustPacket = TrustPacket; - exports.UserAttributePacket = UserAttributePacket; - exports.UserIDPacket = UserIDPacket; - exports.armor = armor; - exports.config = defaultConfig; - exports.createCleartextMessage = createCleartextMessage; - exports.createMessage = createMessage; - exports.decrypt = decrypt$4; - exports.decryptKey = decryptKey; - exports.decryptSessionKeys = decryptSessionKeys; - exports.encrypt = encrypt$4; - exports.encryptKey = encryptKey; - exports.encryptSessionKey = encryptSessionKey; - exports.enums = enums; - exports.generateKey = generateKey; - exports.generateSessionKey = generateSessionKey$1; - exports.readCleartextMessage = readCleartextMessage; - exports.readKey = readKey; - exports.readKeys = readKeys; - exports.readMessage = readMessage; - exports.readPrivateKey = readPrivateKey; - exports.readPrivateKeys = readPrivateKeys; - exports.readSignature = readSignature; - exports.reformatKey = reformatKey; - exports.revokeKey = revokeKey; - exports.sign = sign$5; - exports.unarmor = unarmor; - exports.verify = verify$5; - -// -----BEGIN ADDED BY FLOWCRYPT---- -exports.readToEnd = readToEnd; -exports.util = util; -// -----END ADDED BY FLOWCRYPT----- - - Object.defineProperty(exports, '__esModule', { value: true }); - - return exports; - -}({})); diff --git a/Core/tooling/build.sh b/Core/tooling/build.sh index 92b353a45..c87215cf8 100755 --- a/Core/tooling/build.sh +++ b/Core/tooling/build.sh @@ -4,11 +4,32 @@ set -euxo pipefail # fix openpgp in node_modules echo "Patching openpgp.js v5..." -for f in openpgp.min.js openpgp.min.js.map openpgp.min.mjs openpgp.min.mjs.map openpgp.mjs; do +for f in openpgp.min.js openpgp.min.js.map openpgp.min.mjs openpgp.min.mjs.map openpgp.mjs; +do if [ -f node_modules/openpgp/dist/$f ]; then rm -f node_modules/openpgp/dist/$f ; fi if [ -f node_modules/openpgp/dist/node/$f ]; then rm -f node_modules/openpgp/dist/node/$f ; fi done -cp -Rfv source/lib/openpgpjs-v5/* node_modules/openpgp/ +extra_exports=" +// -----BEGIN ADDED BY FLOWCRYPT---- +exports.readToEnd = readToEnd; +exports.util = util; +// -----END ADDED BY FLOWCRYPT----- +" +for dist_js in node_modules/openpgp/dist/openpgp.js node_modules/openpgp/dist/node/openpgp.js; +do + tmp_js=${dist_js}.tmp + set +e + fc_added=$(grep 'BEGIN ADDED BY FLOWCRYPT' ${dist_js} | wc -l) + set -e + if [ $fc_added = 0 ]; then + n=$(grep -n 'exports.verify' ${dist_js} | cut -f1 -d':') + head -$n ${dist_js} >${tmp_js} + echo "$extra_exports" >>${tmp_js} + tail -n +$((n+1)) ${dist_js} >>${tmp_js} + mv -f ${tmp_js} ${dist_js} + fi +done +cp -fv source/types/openpgp.d.ts node_modules/openpgp/ # MacOS sed is old BSD sed w/o "-i" (see https://ss64.com/osx/sed.html) sed 's/openpgp.min.js/openpgp.js/g' node_modules/openpgp/package.json >node_modules/openpgp/package.json.tmp cp -f node_modules/openpgp/package.json.tmp node_modules/openpgp/package.json From 2c07d459befd569bb482063150d8cfb9c1232f58 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Thu, 10 Feb 2022 23:56:47 +0200 Subject: [PATCH 140/179] wip --- Core/tooling/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/tooling/build.sh b/Core/tooling/build.sh index c87215cf8..cd660c6e5 100755 --- a/Core/tooling/build.sh +++ b/Core/tooling/build.sh @@ -29,7 +29,7 @@ do mv -f ${tmp_js} ${dist_js} fi done -cp -fv source/types/openpgp.d.ts node_modules/openpgp/ +cp -fv source/core/types/openpgp.d.ts node_modules/openpgp/ # MacOS sed is old BSD sed w/o "-i" (see https://ss64.com/osx/sed.html) sed 's/openpgp.min.js/openpgp.js/g' node_modules/openpgp/package.json >node_modules/openpgp/package.json.tmp cp -f node_modules/openpgp/package.json.tmp node_modules/openpgp/package.json From 50e3f9072fb8cd04402112a64b37e6ed9caf3962 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Fri, 11 Feb 2022 00:20:06 +0200 Subject: [PATCH 141/179] fix --- Core/source/core/pgp-key.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index f84c5158b..d51f7fba7 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -377,7 +377,7 @@ export class PgpKey { for (const subKey of key.subkeys) { try { const latestValidSig = await subKey.verify(); - if (latestValidSig) allSignatures.push(latestValidSig); + allSignatures.push(latestValidSig); } catch (e) { console.log(e); } From 982660e029ba990879fa13111a469f859c5fd937 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Fri, 11 Feb 2022 22:41:55 +0200 Subject: [PATCH 142/179] wip --- Core/source/platform/util.ts | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/Core/source/platform/util.ts b/Core/source/platform/util.ts index 08c2844b9..b39dd6e9c 100644 --- a/Core/source/platform/util.ts +++ b/Core/source/platform/util.ts @@ -5,6 +5,7 @@ import { Buf } from '../core/buf'; import { randomBytes } from 'crypto'; import { ConvertStringOptions } from 'encoding-japanese'; +import { Key, KeyID, UserID } from 'openpgp'; declare const dereq_encoding_japanese : { convert: (data: Uint8Array, options: ConvertStringOptions) => string; @@ -53,3 +54,32 @@ export const str_to_hex = (str: string): string => { } return r.join(''); } + +export const getExpirationTimeForCapability = async ( + key: Key, capabilities: string, keyId?: KeyID | undefined, userId?: UserID | undefined) + : Promise => { + const primaryUser = await key.getPrimaryUser(undefined, userId, undefined); + if (!primaryUser) throw new Error('Could not find primary user'); + const keyExpiry = await key.getExpirationTime(userId); + if (!keyExpiry) return Infinity; + let sigExpiry: Date | number | null = null; + for (const exp of primaryUser.user.selfCertifications.map(selfCert => selfCert.getExpirationTime())) { + if (sigExpiry == null || exp < sigExpiry!) sigExpiry = exp; + } + let expiry = sigExpiry == null || keyExpiry < sigExpiry! ? keyExpiry : sigExpiry; + if (capabilities === 'encrypt' || capabilities === 'encrypt_sign') { + const encryptKey = (await key.getEncryptionKey(keyId, new Date(expiry), userId)) + || (await key.getEncryptionKey(keyId, null, userId)); + if (!encryptKey) return null; + const encryptExpiry = await encryptKey.getExpirationTime(userId); + if (encryptExpiry < expiry) expiry = encryptExpiry; + } + if (capabilities === 'sign' || capabilities === 'encrypt_sign') { + const signKey = (await key.getSigningKey(keyId, new Date(expiry), userId)) + || (await key.getSigningKey(keyId, null, userId)); + if (!signKey) return null; + const signExpiry = await signKey.getExpirationTime(key.keyPacket); + if (signExpiry < expiry) expiry = signExpiry; + } + return expiry; +} From 48c193c6639df1a0ac5845e1b46e23086b15e30e Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Fri, 11 Feb 2022 22:56:12 +0200 Subject: [PATCH 143/179] wip --- Core/source/platform/util.ts | 38 ++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/Core/source/platform/util.ts b/Core/source/platform/util.ts index b39dd6e9c..5969fecc1 100644 --- a/Core/source/platform/util.ts +++ b/Core/source/platform/util.ts @@ -55,30 +55,42 @@ export const str_to_hex = (str: string): string => { return r.join(''); } +const maxDate = (dates: (Date | null)[]): Date | null => { + let res: Date | null = null; + for (const d of dates) { + if (res == null || (d != null && d > res)) res = d; + } + return res; +} + +// Trying to backport from openpgp.js v4 export const getExpirationTimeForCapability = async ( - key: Key, capabilities: string, keyId?: KeyID | undefined, userId?: UserID | undefined) - : Promise => { + key: Key, capabilities: string, keyId?: KeyID | undefined, userId?: UserID | undefined + ): Promise => { const primaryUser = await key.getPrimaryUser(undefined, userId, undefined); if (!primaryUser) throw new Error('Could not find primary user'); const keyExpiry = await key.getExpirationTime(userId); if (!keyExpiry) return Infinity; - let sigExpiry: Date | number | null = null; - for (const exp of primaryUser.user.selfCertifications.map(selfCert => selfCert.getExpirationTime())) { - if (sigExpiry == null || exp < sigExpiry!) sigExpiry = exp; - } - let expiry = sigExpiry == null || keyExpiry < sigExpiry! ? keyExpiry : sigExpiry; + const selfCertCreated = maxDate(primaryUser.user.selfCertifications.map(selfCert => selfCert.created)); + const selfCert = primaryUser.user.selfCertifications.filter(selfCert => selfCert.created === selfCertCreated)[0]; + const sigExpiry = selfCert.getExpirationTime(); + let expiry = keyExpiry < sigExpiry ? keyExpiry : sigExpiry; if (capabilities === 'encrypt' || capabilities === 'encrypt_sign') { - const encryptKey = (await key.getEncryptionKey(keyId, new Date(expiry), userId)) + const encryptionKey = (await key.getEncryptionKey(keyId, new Date(expiry), userId)) || (await key.getEncryptionKey(keyId, null, userId)); - if (!encryptKey) return null; - const encryptExpiry = await encryptKey.getExpirationTime(userId); + if (!encryptionKey) return null; + const encryptExpiry = encryptionKey instanceof Key + ? await encryptionKey.getExpirationTime(userId) + : ... ; if (encryptExpiry < expiry) expiry = encryptExpiry; } if (capabilities === 'sign' || capabilities === 'encrypt_sign') { - const signKey = (await key.getSigningKey(keyId, new Date(expiry), userId)) + const signatureKey = (await key.getSigningKey(keyId, new Date(expiry), userId)) || (await key.getSigningKey(keyId, null, userId)); - if (!signKey) return null; - const signExpiry = await signKey.getExpirationTime(key.keyPacket); + if (!signatureKey) return null; + const signExpiry = signatureKey instanceof Key + ? await signatureKey.getExpirationTime(userId) + : await signatureKey.getExpirationTime(key.keyPacket); if (signExpiry < expiry) expiry = signExpiry; } return expiry; From 1cc6651408bfeba31ac7dabbc98187197a446398 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Fri, 11 Feb 2022 23:11:34 +0200 Subject: [PATCH 144/179] wip --- Core/source/core/pgp-key.ts | 9 ++++++--- Core/source/platform/util.ts | 31 +++++++++++++++++++++---------- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index d51f7fba7..e7e1d8d2d 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -8,7 +8,7 @@ import { MsgBlockParser } from './msg-block-parser'; import { PgpArmor } from './pgp-armor'; import { Store } from '../platform/store'; import { mnemonic } from './mnemonic'; -import { str_to_hex } from '../platform/util'; +import { getKeyExpirationTimeForCapabilities, str_to_hex } from '../platform/util'; import { AnyKeyPacket, encryptKey, enums, generateKey, Key, KeyID, PacketList, PrivateKey, PublicKey, readKey, readKeys, readMessage, readToEnd, revokeKey, SecretKeyPacket, SecretSubkeyPacket, SignaturePacket, UserID } from 'openpgp'; import { isFullyDecrypted, isFullyEncrypted } from './pgp'; @@ -304,7 +304,9 @@ export class PgpKey { public static dateBeforeExpiration = async (key: Key | string): Promise => { const openPgpKey = typeof key === 'string' ? await PgpKey.read(key) : key; - const expires = await openPgpKey.getExpirationTime(); + // const expires = await openPgpKey.getExpirationTime(); + // meanhile use or backported fuinction + const expires = await getKeyExpirationTimeForCapabilities(openPgpKey, 'encrypt'); if (expires instanceof Date && expires.getTime() < Date.now()) { // expired return new Date(expires.getTime() - 1000); } @@ -326,7 +328,8 @@ export class PgpKey { algorithmId: enums.publicKey[algoInfo.algorithm] }; const created = k.keyPacket.created.getTime() / 1000; - const exp = await k.getExpirationTime(); + // meanwhile use our backported function + const exp = await getKeyExpirationTimeForCapabilities(k, 'encrypt'); const expiration = exp === Infinity || !exp ? undefined : (exp as Date).getTime() / 1000; const lastModified = await PgpKey.lastSig(k) / 1000; const ids: KeyDetails$ids[] = []; diff --git a/Core/source/platform/util.ts b/Core/source/platform/util.ts index 5969fecc1..b4df753fe 100644 --- a/Core/source/platform/util.ts +++ b/Core/source/platform/util.ts @@ -5,7 +5,7 @@ import { Buf } from '../core/buf'; import { randomBytes } from 'crypto'; import { ConvertStringOptions } from 'encoding-japanese'; -import { Key, KeyID, UserID } from 'openpgp'; +import { Key, KeyID, Subkey, UserID } from 'openpgp'; declare const dereq_encoding_japanese : { convert: (data: Uint8Array, options: ConvertStringOptions) => string; @@ -57,15 +57,26 @@ export const str_to_hex = (str: string): string => { const maxDate = (dates: (Date | null)[]): Date | null => { let res: Date | null = null; - for (const d of dates) { - if (res == null || (d != null && d > res)) res = d; + for (const date of dates) { + if (res == null || (date != null && date > res)) { + res = date; + } } return res; } -// Trying to backport from openpgp.js v4 -export const getExpirationTimeForCapability = async ( - key: Key, capabilities: string, keyId?: KeyID | undefined, userId?: UserID | undefined +const getSubkeyExpirationTime = (subkey: Subkey): number | Date => { + const bindingCreated = maxDate(subkey.bindingSignatures.map(b => b.created)); + const binding = subkey.bindingSignatures.filter(b => b.created === bindingCreated)[0]; + return binding.getExpirationTime(); +} + +// Attempt to backport from openpgp.js v4 +export const getKeyExpirationTimeForCapabilities = async ( + key: Key, + capabilities?: 'encrypt' | 'encrypt_sign' | 'sign' | null, + keyId?: KeyID | undefined, + userId?: UserID | undefined ): Promise => { const primaryUser = await key.getPrimaryUser(undefined, userId, undefined); if (!primaryUser) throw new Error('Could not find primary user'); @@ -80,8 +91,8 @@ export const getExpirationTimeForCapability = async ( || (await key.getEncryptionKey(keyId, null, userId)); if (!encryptionKey) return null; const encryptExpiry = encryptionKey instanceof Key - ? await encryptionKey.getExpirationTime(userId) - : ... ; + ? (await encryptionKey.getExpirationTime(userId))! + : getSubkeyExpirationTime(encryptionKey) ; if (encryptExpiry < expiry) expiry = encryptExpiry; } if (capabilities === 'sign' || capabilities === 'encrypt_sign') { @@ -89,8 +100,8 @@ export const getExpirationTimeForCapability = async ( || (await key.getSigningKey(keyId, null, userId)); if (!signatureKey) return null; const signExpiry = signatureKey instanceof Key - ? await signatureKey.getExpirationTime(userId) - : await signatureKey.getExpirationTime(key.keyPacket); + ? (await signatureKey.getExpirationTime(userId))! + : await getSubkeyExpirationTime(signatureKey); if (signExpiry < expiry) expiry = signExpiry; } return expiry; From e31a387db048d26013f63517c4dcee2313019284 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Fri, 11 Feb 2022 23:36:45 +0200 Subject: [PATCH 145/179] wip --- Core/source/core/pgp-key.ts | 1 + Core/source/platform/util.ts | 19 ++++++++++--------- Core/source/test.ts | 2 +- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index e7e1d8d2d..20e8ed1a9 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -330,6 +330,7 @@ export class PgpKey { const created = k.keyPacket.created.getTime() / 1000; // meanwhile use our backported function const exp = await getKeyExpirationTimeForCapabilities(k, 'encrypt'); + console.log(`\nexp=${exp}\n`); const expiration = exp === Infinity || !exp ? undefined : (exp as Date).getTime() / 1000; const lastModified = await PgpKey.lastSig(k) / 1000; const ids: KeyDetails$ids[] = []; diff --git a/Core/source/platform/util.ts b/Core/source/platform/util.ts index b4df753fe..c5a212721 100644 --- a/Core/source/platform/util.ts +++ b/Core/source/platform/util.ts @@ -81,28 +81,29 @@ export const getKeyExpirationTimeForCapabilities = async ( const primaryUser = await key.getPrimaryUser(undefined, userId, undefined); if (!primaryUser) throw new Error('Could not find primary user'); const keyExpiry = await key.getExpirationTime(userId); - if (!keyExpiry) return Infinity; + if (!keyExpiry) return null; const selfCertCreated = maxDate(primaryUser.user.selfCertifications.map(selfCert => selfCert.created)); const selfCert = primaryUser.user.selfCertifications.filter(selfCert => selfCert.created === selfCertCreated)[0]; const sigExpiry = selfCert.getExpirationTime(); let expiry = keyExpiry < sigExpiry ? keyExpiry : sigExpiry; if (capabilities === 'encrypt' || capabilities === 'encrypt_sign') { - const encryptionKey = (await key.getEncryptionKey(keyId, new Date(expiry), userId)) - || (await key.getEncryptionKey(keyId, null, userId)); + const encryptionKey = (await key.getEncryptionKey(keyId, new Date(expiry), userId).catch(() => {})) + || (await key.getEncryptionKey(keyId, null, userId).catch(() => {})); if (!encryptionKey) return null; - const encryptExpiry = encryptionKey instanceof Key + console.log(encryptionKey); + const encryptionKeyExpiry = encryptionKey instanceof Key ? (await encryptionKey.getExpirationTime(userId))! : getSubkeyExpirationTime(encryptionKey) ; - if (encryptExpiry < expiry) expiry = encryptExpiry; + if (encryptionKeyExpiry < expiry) expiry = encryptionKeyExpiry; } if (capabilities === 'sign' || capabilities === 'encrypt_sign') { - const signatureKey = (await key.getSigningKey(keyId, new Date(expiry), userId)) - || (await key.getSigningKey(keyId, null, userId)); + const signatureKey = (await key.getSigningKey(keyId, new Date(expiry), userId).catch(() => {})) + || (await key.getSigningKey(keyId, null, userId).catch(() => {})); if (!signatureKey) return null; - const signExpiry = signatureKey instanceof Key + const signatureKeyExpiry = signatureKey instanceof Key ? (await signatureKey.getExpirationTime(userId))! : await getSubkeyExpirationTime(signatureKey); - if (signExpiry < expiry) expiry = signExpiry; + if (signatureKeyExpiry < expiry) expiry = signatureKeyExpiry; } return expiry; } diff --git a/Core/source/test.ts b/Core/source/test.ts index 27e3343ab..0f9bf6529 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -335,7 +335,7 @@ ava.default('isEmailValid - false', async t => { t.pass(); }); -ava.default('parseKeys', async t => { +ava.default.only('parseKeys', async t => { const { pubKeys: [pubkey] } = getKeypairs('rsa1'); console.log(pubkey); const { data, json } = parseResponse(await endpoints.parseKeys({}, [Buffer.from(pubkey)])); From ca9062e6ce427f0dfa6c496b8130d67b51621e03 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Fri, 11 Feb 2022 23:37:04 +0200 Subject: [PATCH 146/179] wip --- Core/source/core/pgp-key.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index 20e8ed1a9..e7e1d8d2d 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -330,7 +330,6 @@ export class PgpKey { const created = k.keyPacket.created.getTime() / 1000; // meanwhile use our backported function const exp = await getKeyExpirationTimeForCapabilities(k, 'encrypt'); - console.log(`\nexp=${exp}\n`); const expiration = exp === Infinity || !exp ? undefined : (exp as Date).getTime() / 1000; const lastModified = await PgpKey.lastSig(k) / 1000; const ids: KeyDetails$ids[] = []; From ed54f01b730ceb5eb664496f9dd5daa28ab46c9a Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Fri, 11 Feb 2022 23:41:55 +0200 Subject: [PATCH 147/179] wip --- Core/source/platform/util.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Core/source/platform/util.ts b/Core/source/platform/util.ts index c5a212721..cdd7d23a1 100644 --- a/Core/source/platform/util.ts +++ b/Core/source/platform/util.ts @@ -91,18 +91,19 @@ export const getKeyExpirationTimeForCapabilities = async ( || (await key.getEncryptionKey(keyId, null, userId).catch(() => {})); if (!encryptionKey) return null; console.log(encryptionKey); - const encryptionKeyExpiry = encryptionKey instanceof Key - ? (await encryptionKey.getExpirationTime(userId))! - : getSubkeyExpirationTime(encryptionKey) ; + // for some reason, "instanceof Key" didn't work: 'Right-hand side of \'instanceof\' is not an object' + const encryptionKeyExpiry = 'bindingSignatures' in encryptionKey + ? getSubkeyExpirationTime(encryptionKey) + : (await encryptionKey.getExpirationTime(userId))!; if (encryptionKeyExpiry < expiry) expiry = encryptionKeyExpiry; } if (capabilities === 'sign' || capabilities === 'encrypt_sign') { const signatureKey = (await key.getSigningKey(keyId, new Date(expiry), userId).catch(() => {})) || (await key.getSigningKey(keyId, null, userId).catch(() => {})); if (!signatureKey) return null; - const signatureKeyExpiry = signatureKey instanceof Key - ? (await signatureKey.getExpirationTime(userId))! - : await getSubkeyExpirationTime(signatureKey); + const signatureKeyExpiry = 'bindingSignatures' in signatureKey + ? await getSubkeyExpirationTime(signatureKey) + : (await signatureKey.getExpirationTime(userId))!; if (signatureKeyExpiry < expiry) expiry = signatureKeyExpiry; } return expiry; From bd54221d3a680a886355dced22d34b0ff45ae9d8 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Fri, 11 Feb 2022 23:43:34 +0200 Subject: [PATCH 148/179] wip --- Core/source/platform/util.ts | 2 +- Core/source/test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/source/platform/util.ts b/Core/source/platform/util.ts index cdd7d23a1..f18138e0b 100644 --- a/Core/source/platform/util.ts +++ b/Core/source/platform/util.ts @@ -90,7 +90,6 @@ export const getKeyExpirationTimeForCapabilities = async ( const encryptionKey = (await key.getEncryptionKey(keyId, new Date(expiry), userId).catch(() => {})) || (await key.getEncryptionKey(keyId, null, userId).catch(() => {})); if (!encryptionKey) return null; - console.log(encryptionKey); // for some reason, "instanceof Key" didn't work: 'Right-hand side of \'instanceof\' is not an object' const encryptionKeyExpiry = 'bindingSignatures' in encryptionKey ? getSubkeyExpirationTime(encryptionKey) @@ -101,6 +100,7 @@ export const getKeyExpirationTimeForCapabilities = async ( const signatureKey = (await key.getSigningKey(keyId, new Date(expiry), userId).catch(() => {})) || (await key.getSigningKey(keyId, null, userId).catch(() => {})); if (!signatureKey) return null; + // could be the same as above, so checking for property instead of using "instanceof" const signatureKeyExpiry = 'bindingSignatures' in signatureKey ? await getSubkeyExpirationTime(signatureKey) : (await signatureKey.getExpirationTime(userId))!; diff --git a/Core/source/test.ts b/Core/source/test.ts index 0f9bf6529..27e3343ab 100644 --- a/Core/source/test.ts +++ b/Core/source/test.ts @@ -335,7 +335,7 @@ ava.default('isEmailValid - false', async t => { t.pass(); }); -ava.default.only('parseKeys', async t => { +ava.default('parseKeys', async t => { const { pubKeys: [pubkey] } = getKeypairs('rsa1'); console.log(pubkey); const { data, json } = parseResponse(await endpoints.parseKeys({}, [Buffer.from(pubkey)])); From 4d68bc2a95d02d71d9271ce389467d4da4c4bda7 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sat, 12 Feb 2022 22:19:45 +0200 Subject: [PATCH 149/179] clarify error messages in the lastSig() --- Core/source/core/pgp-key.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index e7e1d8d2d..09a9cec1f 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -373,7 +373,7 @@ export class PgpKey { await selfCertification.verify(key.keyPacket, enums.signature.certGeneric, data); allSignatures.push(selfCertification); } catch (e) { - console.log(e); + console.log(`PgpKey.lastSig: Skipping self-certification signature because it is invalid: ${String(e)}`); } } } @@ -382,7 +382,8 @@ export class PgpKey { const latestValidSig = await subKey.verify(); allSignatures.push(latestValidSig); } catch (e) { - console.log(e); + console.log(`PgpKey.lastSig: Skipping subkey ${subKey.getKeyID().toHex()} ` + + `because there is no valid binding signature: ${String(e)}`); } } if (allSignatures.length > 0) { From 074983948c529eb036c0643d887b6709602ac46a Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sat, 12 Feb 2022 22:25:32 +0200 Subject: [PATCH 150/179] deduplicate preparation of encryptionKeys --- Core/source/core/pgp-msg.ts | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index e1a72b932..33b6cfce0 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -270,19 +270,17 @@ export class PgpMsg { throw new Error('no-pubkeys-no-challenge'); } const message = await createMessage({binary: data, filename, date}); + const encryptionKeys = []; + for (const armoredPubkey of pubkeys) { + const publicKeys = await readKeys({armoredKeys: armoredPubkey}); + encryptionKeys.push(...publicKeys); + } if (armor) { return await encrypt({ format: 'armored', message, date, - encryptionKeys: await (async () => { - const encryptionKeys = []; - for (const armoredPubkey of pubkeys) { - const publicKeys = await readKeys({armoredKeys: armoredPubkey}); - encryptionKeys.push(...publicKeys); - } - return encryptionKeys; - })(), + encryptionKeys, passwords: pwd ? [pwd] : undefined, signingKeys: signingPrv && signingPrv.isPrivate() ? signingPrv : undefined }); @@ -291,14 +289,7 @@ export class PgpMsg { format: 'binary', message, date, - encryptionKeys: await (async () => { - const encryptionKeys = []; - for (const armoredPubkey of pubkeys) { - const publicKeys = await readKeys({armoredKeys: armoredPubkey}); - encryptionKeys.push(...publicKeys); - } - return encryptionKeys; - })(), + encryptionKeys, passwords: pwd ? [pwd] : undefined, signingKeys: signingPrv && signingPrv.isPrivate() ? signingPrv : undefined }); From 10cec19eff710dfb245be902edb88896a60a1b1e Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sat, 12 Feb 2022 22:30:24 +0200 Subject: [PATCH 151/179] add block --- Core/source/mobile-interface/validate-input.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Core/source/mobile-interface/validate-input.ts b/Core/source/mobile-interface/validate-input.ts index 8fcd1e12e..bfa3e0694 100644 --- a/Core/source/mobile-interface/validate-input.ts +++ b/Core/source/mobile-interface/validate-input.ts @@ -179,6 +179,8 @@ const hasProp = (v: Obj, name: string, type: 'string[]' | 'string[]?' | 'object' export const readArmoredKeyOrThrow = async (armored: string) => { const key = await readKey({armoredKey: armored}); - if (!key) throw new Error('No key found'); + if (!key) { + throw new Error('No key found'); + } return key; } From 7bb42721f344ce20d391f99866729dbe53490539 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sat, 12 Feb 2022 22:46:54 +0200 Subject: [PATCH 152/179] update build script --- Core/tooling/build.sh | 55 +++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/Core/tooling/build.sh b/Core/tooling/build.sh index cd660c6e5..14c208d6b 100755 --- a/Core/tooling/build.sh +++ b/Core/tooling/build.sh @@ -6,52 +6,51 @@ set -euxo pipefail echo "Patching openpgp.js v5..." for f in openpgp.min.js openpgp.min.js.map openpgp.min.mjs openpgp.min.mjs.map openpgp.mjs; do - if [ -f node_modules/openpgp/dist/$f ]; then rm -f node_modules/openpgp/dist/$f ; fi - if [ -f node_modules/openpgp/dist/node/$f ]; then rm -f node_modules/openpgp/dist/node/$f ; fi + if [ -f ./node_modules/openpgp/dist/$f ]; then rm -f ./node_modules/openpgp/dist/$f ; fi + if [ -f ./node_modules/openpgp/dist/node/$f ]; then rm -f ./node_modules/openpgp/dist/node/$f ; fi done +if [ -f ./node_modules/openpgp/dist/openpgp.js ]; then rm -f ./node_modules/openpgp/dist/openpgp.js ; fi extra_exports=" // -----BEGIN ADDED BY FLOWCRYPT---- exports.readToEnd = readToEnd; exports.util = util; // -----END ADDED BY FLOWCRYPT----- " -for dist_js in node_modules/openpgp/dist/openpgp.js node_modules/openpgp/dist/node/openpgp.js; -do - tmp_js=${dist_js}.tmp - set +e - fc_added=$(grep 'BEGIN ADDED BY FLOWCRYPT' ${dist_js} | wc -l) - set -e - if [ $fc_added = 0 ]; then - n=$(grep -n 'exports.verify' ${dist_js} | cut -f1 -d':') - head -$n ${dist_js} >${tmp_js} - echo "$extra_exports" >>${tmp_js} - tail -n +$((n+1)) ${dist_js} >>${tmp_js} - mv -f ${tmp_js} ${dist_js} - fi -done -cp -fv source/core/types/openpgp.d.ts node_modules/openpgp/ +dist_js=./node_modules/openpgp/dist/node/openpgp.js +tmp_js=${dist_js}.tmp +set +e +fc_added=$(grep 'BEGIN ADDED BY FLOWCRYPT' ${dist_js} | wc -l) +set -e +if [ $fc_added = 0 ]; then + n=$(grep -n 'exports.verify' ${dist_js} | cut -f1 -d':') + head -$n ${dist_js} >${tmp_js} + echo "$extra_exports" >>${tmp_js} + tail -n +$((n+1)) ${dist_js} >>${tmp_js} + mv -f ${tmp_js} ${dist_js} +fi +cp -fv ./source/core/types/openpgp.d.ts ./node_modules/openpgp/ # MacOS sed is old BSD sed w/o "-i" (see https://ss64.com/osx/sed.html) -sed 's/openpgp.min.js/openpgp.js/g' node_modules/openpgp/package.json >node_modules/openpgp/package.json.tmp -cp -f node_modules/openpgp/package.json.tmp node_modules/openpgp/package.json -sed 's/openpgp.min.mjs/openpgp.mjs/g' node_modules/openpgp/package.json >node_modules/openpgp/package.json.tmp -cp -f node_modules/openpgp/package.json.tmp node_modules/openpgp/package.json +sed 's/openpgp.min.js/openpgp.js/g' ./node_modules/openpgp/package.json >./node_modules/openpgp/package.json.tmp +cp -f ./node_modules/openpgp/package.json.tmp ./node_modules/openpgp/package.json +sed 's/openpgp.min.mjs/openpgp.mjs/g' ./node_modules/openpgp/package.json >./node_modules/openpgp/package.json.tmp +cp -f ./node_modules/openpgp/package.json.tmp ./node_modules/openpgp/package.json echo "Patching openpgp.js v5 - DONE." # clean up -rm -rf build/ts build/bundles build/final/* -mkdir -p build/final +rm -rf ./build/ts ./build/bundles ./build/final/* +mkdir -p ./build/final # build our source with typescript -node_modules/.bin/tsc --project tsconfig.json +./node_modules/.bin/tsc --project tsconfig.json # build raw/ with webpack -node_modules/.bin/webpack --config webpack.bare.config.js +./node_modules/.bin/webpack --config webpack.bare.config.js # move modified raw/ to bundles/ -node tooling/fix-bundles.js +node ./tooling/fix-bundles.js # concatenate external deps into one bundle -( cd build/bundles && cat bare-html-sanitize-bundle.js bare-emailjs-bundle.js bare-openpgp-bundle.js bare-zxcvbn-bundle.js bare-encoding-japanese.js > bare-deps-bundle.js ) # bare deps +( cd ./build/bundles && cat bare-html-sanitize-bundle.js bare-emailjs-bundle.js bare-openpgp-bundle.js bare-zxcvbn-bundle.js bare-encoding-japanese.js > bare-deps-bundle.js ) # bare deps # create final builds for dev, ios, android -node tooling/build-final.js +node ./tooling/build-final.js From fc2cff394af2154455bfd02bee17c817be34abac Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sat, 12 Feb 2022 22:48:20 +0200 Subject: [PATCH 153/179] remove test.sh --- Core/.gitignore | 1 + Core/test.sh | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) delete mode 100755 Core/test.sh diff --git a/Core/.gitignore b/Core/.gitignore index 40f7ce905..e73dbe2e4 100644 --- a/Core/.gitignore +++ b/Core/.gitignore @@ -2,3 +2,4 @@ build/* tmp/* node_modules +./test.sh diff --git a/Core/test.sh b/Core/test.sh deleted file mode 100755 index 6fab1674e..000000000 --- a/Core/test.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -clear -npm run test From d2eb325ec74aaf06c65c5e5e05b30e088116ba11 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sat, 12 Feb 2022 22:49:13 +0200 Subject: [PATCH 154/179] fix gitignore --- Core/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/.gitignore b/Core/.gitignore index e73dbe2e4..0ccb33748 100644 --- a/Core/.gitignore +++ b/Core/.gitignore @@ -2,4 +2,4 @@ build/* tmp/* node_modules -./test.sh +/test.sh From 67753da501c8c328faf08ca979c7c1636e50e95c Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sat, 12 Feb 2022 22:57:09 +0200 Subject: [PATCH 155/179] remove random() --- Core/source/core/pgp-password.ts | 8 -------- Core/tooling/build.sh | 1 - 2 files changed, 9 deletions(-) diff --git a/Core/source/core/pgp-password.ts b/Core/source/core/pgp-password.ts index 4fea534e5..94d49e02f 100644 --- a/Core/source/core/pgp-password.ts +++ b/Core/source/core/pgp-password.ts @@ -2,9 +2,6 @@ 'use strict'; -import { base64encode, secureRandomBytes } from '../platform/util'; -import { util } from 'openpgp'; - interface PwdStrengthResult { word: { match: string; @@ -68,11 +65,6 @@ export class PgpPwd { ]; } - public static random = () => { // eg TDW6-DU5M-TANI-LJXY - return base64encode(util.uint8ArrayToString(secureRandomBytes(128))) - .toUpperCase().replace(/[^A-Z0-9]|0|O|1/g, '').replace(/(.{4})/g, '$1-').substr(0, 19); - } - private static readableCrackTime = (totalSeconds: number) => { // See http://stackoverflow.com/questions/8211744/convert-time-interval-given-in-seconds-into-more-human-readable-form const numberWordEnding = (n: number) => (n > 1) ? 's' : ''; diff --git a/Core/tooling/build.sh b/Core/tooling/build.sh index 14c208d6b..58de250c9 100755 --- a/Core/tooling/build.sh +++ b/Core/tooling/build.sh @@ -13,7 +13,6 @@ if [ -f ./node_modules/openpgp/dist/openpgp.js ]; then rm -f ./node_modules/open extra_exports=" // -----BEGIN ADDED BY FLOWCRYPT---- exports.readToEnd = readToEnd; -exports.util = util; // -----END ADDED BY FLOWCRYPT----- " dist_js=./node_modules/openpgp/dist/node/openpgp.js From 7d3bc2ed82cc867c374f288432fe67b6dcce65cd Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sat, 12 Feb 2022 22:59:51 +0200 Subject: [PATCH 156/179] indicate origin of the str_to_hex() --- Core/source/platform/util.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Core/source/platform/util.ts b/Core/source/platform/util.ts index f18138e0b..ad7cd25bb 100644 --- a/Core/source/platform/util.ts +++ b/Core/source/platform/util.ts @@ -36,6 +36,8 @@ export const iso2022jpToUtf = (content: Buf) => { * Create hex string from a binary * @param {String} str String to convert * @returns {String} String containing the hexadecimal values + * Ported from openpgp v4.10.10, original source can be obtained here: + * https://github.com/openpgpjs/openpgpjs/releases/tag/v4.10.10 */ export const str_to_hex = (str: string): string => { if (str === null) { From dcc01425bf1c49d6d8a9252fc74adbf1dc5e7b75 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sat, 12 Feb 2022 23:11:44 +0200 Subject: [PATCH 157/179] wip --- Core/source/core/pgp-key.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index 09a9cec1f..c5e573f2b 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -368,10 +368,10 @@ export class PgpKey { const allSignatures: SignaturePacket[] = []; for (const user of key.users) { const data = { userID: user.userID, userAttribute: user.userAttribute, key: key }; - for (const selfCertification of user.selfCertifications) { + for (const selfCert of user.selfCertifications) { try { - await selfCertification.verify(key.keyPacket, enums.signature.certGeneric, data); - allSignatures.push(selfCertification); + await selfCert.verify(key.keyPacket, enums.signature.certGeneric, data); + allSignatures.push(selfCert); } catch (e) { console.log(`PgpKey.lastSig: Skipping self-certification signature because it is invalid: ${String(e)}`); } From f983021250406f9183e85c280c0271b91144bdd2 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 13 Feb 2022 00:28:25 +0200 Subject: [PATCH 158/179] latestValidKeyBindingSig --- Core/source/core/pgp-key.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index c5e573f2b..714095755 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -379,8 +379,8 @@ export class PgpKey { } for (const subKey of key.subkeys) { try { - const latestValidSig = await subKey.verify(); - allSignatures.push(latestValidSig); + const latestValidKeyBindingSig = await subKey.verify(); + allSignatures.push(latestValidKeyBindingSig); } catch (e) { console.log(`PgpKey.lastSig: Skipping subkey ${subKey.getKeyID().toHex()} ` + `because there is no valid binding signature: ${String(e)}`); From b4f492452e3359c9ffb9ed32d49795db3013c041 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 13 Feb 2022 00:28:51 +0200 Subject: [PATCH 159/179] str_to_hex LGPL --- Core/source/platform/util.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Core/source/platform/util.ts b/Core/source/platform/util.ts index ad7cd25bb..d4b194588 100644 --- a/Core/source/platform/util.ts +++ b/Core/source/platform/util.ts @@ -33,11 +33,11 @@ export const iso2022jpToUtf = (content: Buf) => { } /** - * Create hex string from a binary - * @param {String} str String to convert - * @returns {String} String containing the hexadecimal values - * Ported from openpgp v4.10.10, original source can be obtained here: - * https://github.com/openpgpjs/openpgpjs/releases/tag/v4.10.10 + * Create hex string from a binary. + * @param {String} str A string to convert. + * @returns {String} String containing the hexadecimal values. + * @note This method, brought from OpenPGP.js project is, unlike the rest of the codebase, + * licensed under LGPL. See original license file: https://github.com/openpgpjs/openpgpjs/blob/main/LICENSE */ export const str_to_hex = (str: string): string => { if (str === null) { From de8f3e39bf01d7a75e29d243e61aee73d4117029 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 13 Feb 2022 00:41:04 +0200 Subject: [PATCH 160/179] wip --- Core/source/core/pgp-msg.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index 33b6cfce0..b7ed7ebb6 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -275,6 +275,8 @@ export class PgpMsg { const publicKeys = await readKeys({armoredKeys: armoredPubkey}); encryptionKeys.push(...publicKeys); } + // Have to keep this "if" here because it doesn't compile if we use + // format: armor ? 'armored' : 'binary' if (armor) { return await encrypt({ format: 'armored', From f963686400b3305cfc3a64b928ceec9b9d74d76f Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 13 Feb 2022 00:45:13 +0200 Subject: [PATCH 161/179] Add web-stream-tools --- Core/package-lock.json | 47 +++++++++++++++++++++++++++++++++++++++++- Core/package.json | 3 ++- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/Core/package-lock.json b/Core/package-lock.json index c09ebd6a7..e6aee1a8a 100644 --- a/Core/package-lock.json +++ b/Core/package-lock.json @@ -9,8 +9,9 @@ "version": "0.0.1", "license": "SEE LICENSE IN ", "dependencies": { + "@openpgp/web-stream-tools": "^0.0.9", "encoding-japanese": "^1.0.30", - "openpgp": "5.1.0", + "openpgp": "^5.1.0", "sanitize-html": "2.6.1", "zxcvbn": "4.4.2" }, @@ -355,6 +356,14 @@ "node": ">=10.0.0" } }, + "node_modules/@mattiasbuelens/web-streams-adapter": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@mattiasbuelens/web-streams-adapter/-/web-streams-adapter-0.1.0.tgz", + "integrity": "sha512-oV4PyZfwJNtmFWhvlJLqYIX1Nn22ML8FZpS16ZUKv0hg7414xV1fjsGqxQzLT2dyK92TKxsJSwMOd7VNHAtPmA==", + "engines": { + "node": ">= 12" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -390,6 +399,15 @@ "node": ">= 8" } }, + "node_modules/@openpgp/web-stream-tools": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@openpgp/web-stream-tools/-/web-stream-tools-0.0.9.tgz", + "integrity": "sha512-GEKuXpQRshUqgKH4sMcwYbHolxaUSHIowcIMd02EsnLv4q5acP0z9pRUy3kjV0ZyRPgyD0vXAy60Rf0MPKoCMw==", + "dependencies": { + "@mattiasbuelens/web-streams-adapter": "~0.1.0", + "web-streams-polyfill": "~3.0.3" + } + }, "node_modules/@types/chai": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.0.tgz", @@ -7913,6 +7931,14 @@ "node": ">=8.0" } }, + "node_modules/web-streams-polyfill": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.0.3.tgz", + "integrity": "sha512-d2H/t0eqRNM4w2WvmTdoeIvzAUSpK7JmATB8Nr2lb7nQ9BTIJVjbQ/TRFVEh2gUH1HwclPdoPtfMoFfetXaZnA==", + "engines": { + "node": ">= 8" + } + }, "node_modules/webpack": { "version": "4.46.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", @@ -8751,6 +8777,11 @@ "integrity": "sha512-ws57AidsDvREKrZKYffXddNkyaF14iHNHm8VQnZH6t99E8gczjNN0GpvcGny0imC80yQ0tHz1xVUKk/KFQSUyA==", "dev": true }, + "@mattiasbuelens/web-streams-adapter": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@mattiasbuelens/web-streams-adapter/-/web-streams-adapter-0.1.0.tgz", + "integrity": "sha512-oV4PyZfwJNtmFWhvlJLqYIX1Nn22ML8FZpS16ZUKv0hg7414xV1fjsGqxQzLT2dyK92TKxsJSwMOd7VNHAtPmA==" + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -8777,6 +8808,15 @@ "fastq": "^1.6.0" } }, + "@openpgp/web-stream-tools": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@openpgp/web-stream-tools/-/web-stream-tools-0.0.9.tgz", + "integrity": "sha512-GEKuXpQRshUqgKH4sMcwYbHolxaUSHIowcIMd02EsnLv4q5acP0z9pRUy3kjV0ZyRPgyD0vXAy60Rf0MPKoCMw==", + "requires": { + "@mattiasbuelens/web-streams-adapter": "~0.1.0", + "web-streams-polyfill": "~3.0.3" + } + }, "@types/chai": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.0.tgz", @@ -14871,6 +14911,11 @@ "chokidar": "^2.1.8" } }, + "web-streams-polyfill": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.0.3.tgz", + "integrity": "sha512-d2H/t0eqRNM4w2WvmTdoeIvzAUSpK7JmATB8Nr2lb7nQ9BTIJVjbQ/TRFVEh2gUH1HwclPdoPtfMoFfetXaZnA==" + }, "webpack": { "version": "4.46.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", diff --git a/Core/package.json b/Core/package.json index feb601e8a..e1c8f1902 100644 --- a/Core/package.json +++ b/Core/package.json @@ -4,8 +4,9 @@ "description": "TypeScript core for FlowCrypt iOS internal use", "dependencies": { "encoding-japanese": "^1.0.30", - "openpgp": "5.1.0", + "openpgp": "^5.1.0", "sanitize-html": "2.6.1", + "@openpgp/web-stream-tools": "^0.0.9", "zxcvbn": "4.4.2" }, "devDependencies": { From 1cc254b90bd655fd5e0c6ca42b53a2527e2bbfe7 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 13 Feb 2022 00:50:43 +0200 Subject: [PATCH 162/179] wip --- Core/source/core/types/openpgp.d.ts | 11 ----------- Core/tooling/build.sh | 29 +---------------------------- 2 files changed, 1 insertion(+), 39 deletions(-) diff --git a/Core/source/core/types/openpgp.d.ts b/Core/source/core/types/openpgp.d.ts index 03a2c57b7..2d61e341a 100644 --- a/Core/source/core/types/openpgp.d.ts +++ b/Core/source/core/types/openpgp.d.ts @@ -886,14 +886,3 @@ export namespace enums { mime = 109 } } - -// -----BEGIN ADDED BY FLOWCRYPT----- - -export function readToEnd(input: MaybeStream, concat?: (list: T[]) => T): Promise; - -export namespace util { - // we can't copy this from openpgp.js into our sources (i.e. util.ts) because of LGPL - function uint8ArrayToString(bytes: Uint8Array): string; -} - -// -----END ADDED BY FLOWCRYPT----- diff --git a/Core/tooling/build.sh b/Core/tooling/build.sh index 58de250c9..b4ad3b6b3 100755 --- a/Core/tooling/build.sh +++ b/Core/tooling/build.sh @@ -4,35 +4,8 @@ set -euxo pipefail # fix openpgp in node_modules echo "Patching openpgp.js v5..." -for f in openpgp.min.js openpgp.min.js.map openpgp.min.mjs openpgp.min.mjs.map openpgp.mjs; -do - if [ -f ./node_modules/openpgp/dist/$f ]; then rm -f ./node_modules/openpgp/dist/$f ; fi - if [ -f ./node_modules/openpgp/dist/node/$f ]; then rm -f ./node_modules/openpgp/dist/node/$f ; fi -done -if [ -f ./node_modules/openpgp/dist/openpgp.js ]; then rm -f ./node_modules/openpgp/dist/openpgp.js ; fi -extra_exports=" -// -----BEGIN ADDED BY FLOWCRYPT---- -exports.readToEnd = readToEnd; -// -----END ADDED BY FLOWCRYPT----- -" -dist_js=./node_modules/openpgp/dist/node/openpgp.js -tmp_js=${dist_js}.tmp -set +e -fc_added=$(grep 'BEGIN ADDED BY FLOWCRYPT' ${dist_js} | wc -l) -set -e -if [ $fc_added = 0 ]; then - n=$(grep -n 'exports.verify' ${dist_js} | cut -f1 -d':') - head -$n ${dist_js} >${tmp_js} - echo "$extra_exports" >>${tmp_js} - tail -n +$((n+1)) ${dist_js} >>${tmp_js} - mv -f ${tmp_js} ${dist_js} -fi +# will remove this when openpgp.js will release all our fixes cp -fv ./source/core/types/openpgp.d.ts ./node_modules/openpgp/ -# MacOS sed is old BSD sed w/o "-i" (see https://ss64.com/osx/sed.html) -sed 's/openpgp.min.js/openpgp.js/g' ./node_modules/openpgp/package.json >./node_modules/openpgp/package.json.tmp -cp -f ./node_modules/openpgp/package.json.tmp ./node_modules/openpgp/package.json -sed 's/openpgp.min.mjs/openpgp.mjs/g' ./node_modules/openpgp/package.json >./node_modules/openpgp/package.json.tmp -cp -f ./node_modules/openpgp/package.json.tmp ./node_modules/openpgp/package.json echo "Patching openpgp.js v5 - DONE." # clean up From 240e84e21e11b520ed200682605acdb702ca71b7 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 13 Feb 2022 00:53:54 +0200 Subject: [PATCH 163/179] import readToEnd() from web-stream-tools --- Core/source/core/pgp-key.ts | 3 ++- Core/source/core/pgp-msg.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index 714095755..fcf36d50e 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -9,7 +9,8 @@ import { PgpArmor } from './pgp-armor'; import { Store } from '../platform/store'; import { mnemonic } from './mnemonic'; import { getKeyExpirationTimeForCapabilities, str_to_hex } from '../platform/util'; -import { AnyKeyPacket, encryptKey, enums, generateKey, Key, KeyID, PacketList, PrivateKey, PublicKey, readKey, readKeys, readMessage, readToEnd, revokeKey, SecretKeyPacket, SecretSubkeyPacket, SignaturePacket, UserID } from 'openpgp'; +import { AnyKeyPacket, encryptKey, enums, generateKey, Key, KeyID, PacketList, PrivateKey, PublicKey, readKey, readKeys, readMessage, revokeKey, SecretKeyPacket, SecretSubkeyPacket, SignaturePacket, UserID } from 'openpgp'; +import { readToEnd } from '@openpgp/web-stream-tools'; import { isFullyDecrypted, isFullyEncrypted } from './pgp'; export type Contact = { diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index b7ed7ebb6..9c7cbd6ef 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -14,7 +14,8 @@ import { FcAttLinkData } from './att'; import { MsgBlockParser } from './msg-block-parser'; import { PgpArmor } from './pgp-armor'; import { Store } from '../platform/store'; -import { CleartextMessage, createCleartextMessage, createMessage, Data, encrypt, enums, Key, KeyID, Message, PrivateKey, readKeys, readMessage, readToEnd, sign, VerificationResult } from 'openpgp'; +import { CleartextMessage, createCleartextMessage, createMessage, Data, encrypt, enums, Key, KeyID, Message, PrivateKey, readKeys, readMessage, sign, VerificationResult } from 'openpgp'; +import { readToEnd } from '@openpgp/web-stream-tools'; import { isFullyDecrypted, isFullyEncrypted, isPacketDecrypted } from './pgp'; export namespace PgpMsgMethod { From bdab05bdb3aa6c7dd164166046c6efc836794784 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 13 Feb 2022 01:12:29 +0200 Subject: [PATCH 164/179] added ambiets.d.ts --- Core/ambients.d.ts | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 Core/ambients.d.ts diff --git a/Core/ambients.d.ts b/Core/ambients.d.ts new file mode 100644 index 000000000..afb5fcb4d --- /dev/null +++ b/Core/ambients.d.ts @@ -0,0 +1,5 @@ +import { Data, MaybeStream } from "openpgp"; + +declare module "@openpgp/web-stream-tools" { + export function readToEnd(input: MaybeStream, concat?: (list: T[]) => T): Promise; +} From c30fdf0bb9a5cc8b68cb5e5f962c20beebd51808 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 13 Feb 2022 01:32:06 +0200 Subject: [PATCH 165/179] wip --- .../@openpgp/web-stream-tools/index.d.ts} | 0 .../@openpgp/web-stream-tools/package.json | 26 +++++++++++++++++++ 2 files changed, 26 insertions(+) rename Core/{ambients.d.ts => source/core/types/@openpgp/web-stream-tools/index.d.ts} (100%) create mode 100755 Core/source/core/types/@openpgp/web-stream-tools/package.json diff --git a/Core/ambients.d.ts b/Core/source/core/types/@openpgp/web-stream-tools/index.d.ts similarity index 100% rename from Core/ambients.d.ts rename to Core/source/core/types/@openpgp/web-stream-tools/index.d.ts diff --git a/Core/source/core/types/@openpgp/web-stream-tools/package.json b/Core/source/core/types/@openpgp/web-stream-tools/package.json new file mode 100755 index 000000000..b5bf3b2b4 --- /dev/null +++ b/Core/source/core/types/@openpgp/web-stream-tools/package.json @@ -0,0 +1,26 @@ +{ + "name": "@types/@openpgp/web-stream-tools", + "version": "0.0.9", + "description": "TypeScript definitions for @openpgp/web-stream-tools", + "homepage": "https://flowcrypt.com", + "license": "MIT", + "contributors": [ + { + "name": "Flowcrypt a.s.", + "url": "https://flowcrypt.com" + }, + ], + "main": "", + "types": "index.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git", + "directory": "types/@openpgp/web-stream-tools" + }, + "scripts": {}, + "dependencies": { + "openpgp": "*" + }, + "typesPublisherContentHash": "4003dec3031c1eaedfef9b35d82336844717759fbad199dabb4d8f7cad2e2e58", + "typeScriptVersion": "3.7" +} \ No newline at end of file From b1fba8b7eb7a5f3d05a0a3c110219f23b75249d8 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 13 Feb 2022 02:07:26 +0200 Subject: [PATCH 166/179] added web-stream-tools.d.ts --- .../@openpgp/web-stream-tools/package.json | 26 ------------------- .../index.d.ts => web-stream-tools.d.ts} | 0 2 files changed, 26 deletions(-) delete mode 100755 Core/source/core/types/@openpgp/web-stream-tools/package.json rename Core/source/core/types/{@openpgp/web-stream-tools/index.d.ts => web-stream-tools.d.ts} (100%) diff --git a/Core/source/core/types/@openpgp/web-stream-tools/package.json b/Core/source/core/types/@openpgp/web-stream-tools/package.json deleted file mode 100755 index b5bf3b2b4..000000000 --- a/Core/source/core/types/@openpgp/web-stream-tools/package.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "@types/@openpgp/web-stream-tools", - "version": "0.0.9", - "description": "TypeScript definitions for @openpgp/web-stream-tools", - "homepage": "https://flowcrypt.com", - "license": "MIT", - "contributors": [ - { - "name": "Flowcrypt a.s.", - "url": "https://flowcrypt.com" - }, - ], - "main": "", - "types": "index.d.ts", - "repository": { - "type": "git", - "url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git", - "directory": "types/@openpgp/web-stream-tools" - }, - "scripts": {}, - "dependencies": { - "openpgp": "*" - }, - "typesPublisherContentHash": "4003dec3031c1eaedfef9b35d82336844717759fbad199dabb4d8f7cad2e2e58", - "typeScriptVersion": "3.7" -} \ No newline at end of file diff --git a/Core/source/core/types/@openpgp/web-stream-tools/index.d.ts b/Core/source/core/types/web-stream-tools.d.ts similarity index 100% rename from Core/source/core/types/@openpgp/web-stream-tools/index.d.ts rename to Core/source/core/types/web-stream-tools.d.ts From 4896c9604d1598b0d8572ebfa63814d6a7dadcbe Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 13 Feb 2022 02:23:21 +0200 Subject: [PATCH 167/179] patch web-stream-tools --- Core/tooling/build.sh | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/Core/tooling/build.sh b/Core/tooling/build.sh index b4ad3b6b3..bec9a61be 100755 --- a/Core/tooling/build.sh +++ b/Core/tooling/build.sh @@ -2,12 +2,28 @@ set -euxo pipefail -# fix openpgp in node_modules -echo "Patching openpgp.js v5..." # will remove this when openpgp.js will release all our fixes +echo "Patching openpgp.js v5..." cp -fv ./source/core/types/openpgp.d.ts ./node_modules/openpgp/ echo "Patching openpgp.js v5 - DONE." +# will remove this when @openpgp/web-stream-tools would release their type definitions +echo "Patching @openpgp/web-stream-tools ..." +cp -fv ./source/core/types/web-stream-tools.d.ts ./node_modules/@openpgp/web-stream-tools/ +wst_pkg=./node_modules/@openpgp/web-stream-tools/package.json +set +e +wst_patched=$(grep -n '"types":' $wst_pkg | wc -l) +set -e +if [ $wst_patched = 0 ]; then + wst_pkg_tmp=${wst_pkg}.tmp + n=$(grep -n '"main":' $wst_pkg | cut -f1 -d':') + head -$n ${wst_pkg} >${wst_pkg_tmp} + echo ' "types": "web-stream-tools.d.ts",' >>${wst_pkg_tmp} + tail -n $((n+1)) ${wst_pkg} >>${wst_pkg_tmp} + mv -f ${wst_pkg_tmp} ${wst_pkg} +fi +echo "Patching @openpgp/web-stream-tools - DONE." + # clean up rm -rf ./build/ts ./build/bundles ./build/final/* mkdir -p ./build/final From e8b55848d74e80f9afb6addac51c6b223afe3663 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 13 Feb 2022 02:35:52 +0200 Subject: [PATCH 168/179] wip --- Core/source/core/types/web-stream-tools.d.ts | 21 ++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/Core/source/core/types/web-stream-tools.d.ts b/Core/source/core/types/web-stream-tools.d.ts index afb5fcb4d..61afc63d4 100644 --- a/Core/source/core/types/web-stream-tools.d.ts +++ b/Core/source/core/types/web-stream-tools.d.ts @@ -1,5 +1,22 @@ -import { Data, MaybeStream } from "openpgp"; - declare module "@openpgp/web-stream-tools" { + type Data = Uint8Array | string; + + interface BaseStream extends AsyncIterable { } + + interface WebStream extends BaseStream { // copied+simplified version of ReadableStream from lib.dom.d.ts + readonly locked: boolean; getReader: Function; pipeThrough: Function; pipeTo: Function; tee: Function; + cancel(reason?: any): Promise; + } + + interface NodeStream extends BaseStream { // copied+simplified version of ReadableStream from @types/node/index.d.ts + readable: boolean; pipe: Function; unpipe: Function; wrap: Function; + read(size?: number): string | Uint8Array; setEncoding(encoding: string): this; pause(): this; resume(): this; + isPaused(): boolean; unshift(chunk: string | Uint8Array): void; + } + + type Stream = WebStream | NodeStream; + + type MaybeStream = T | Stream; + export function readToEnd(input: MaybeStream, concat?: (list: T[]) => T): Promise; } From 1bdc1568cf5742ea7098f611f229a493c96b943d Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 13 Feb 2022 03:00:53 +0200 Subject: [PATCH 169/179] Change type of PrvKeyInfo.decrypted to PrivateKey --- Core/source/core/pgp-key.ts | 2 +- Core/source/core/pgp-msg.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index fcf36d50e..be3592079 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -35,7 +35,7 @@ export interface PrvKeyInfo { private: string; longid: string; passphrase?: string; - decrypted?: Key; // only for internal use in this file + decrypted?: PrivateKey; // only for internal use in this file parsed?: Key; // only for internal use in this file } diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index 9c7cbd6ef..1a30d5956 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -247,7 +247,7 @@ export class PgpMsg { }; } const passwords = msgPwd ? [msgPwd] : undefined; - const privateKeys = keys.prvForDecryptDecrypted.map(ki => ki.decrypted!) as PrivateKey[]; + const privateKeys = keys.prvForDecryptDecrypted.map(ki => ki.decrypted!); const decrypted = await (prepared.message as Message).decrypt(privateKeys, passwords); // we can only figure out who signed the msg once it's decrypted await PgpMsg.cryptoMsgGetSignedBy(decrypted, keys); @@ -428,11 +428,11 @@ export class PgpMsg { const matchingKeyids = PgpMsg.matchingKeyids(ki.parsed!, encryptedForKeyids); const cachedKey = Store.decryptedKeyCacheGet(ki.longid); if (cachedKey && PgpMsg.isKeyDecryptedFor(cachedKey, matchingKeyids)) { - ki.decrypted = cachedKey; + ki.decrypted = cachedKey as PrivateKey; keys.prvForDecryptDecrypted.push(ki); } else if (PgpMsg.isKeyDecryptedFor(ki.parsed!, matchingKeyids) || await PgpMsg.decryptKeyFor(ki.parsed!, ki.passphrase!, matchingKeyids) === true) { Store.decryptedKeyCacheSet(ki.parsed!); - ki.decrypted = ki.parsed!; + ki.decrypted = ki.parsed! as PrivateKey; keys.prvForDecryptDecrypted.push(ki); } else { keys.prvForDecryptWithoutPassphrases.push(ki); From 27dfeb2e190df1df96f14f9e390c6306d214ff0e Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 13 Feb 2022 12:30:04 +0200 Subject: [PATCH 170/179] revert to openpgp.js patch --- Core/source/core/pgp-key.ts | 3 +- Core/source/core/pgp-msg.ts | 3 +- Core/source/core/types/openpgp.d.ts | 4 ++ Core/tooling/build.sh | 45 ++++++++++++------- .../build.sh.with-web-stream-tools.save | 44 ++++++++++++++++++ 5 files changed, 80 insertions(+), 19 deletions(-) create mode 100755 Core/tooling/build.sh.with-web-stream-tools.save diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index be3592079..250973bea 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -10,7 +10,8 @@ import { Store } from '../platform/store'; import { mnemonic } from './mnemonic'; import { getKeyExpirationTimeForCapabilities, str_to_hex } from '../platform/util'; import { AnyKeyPacket, encryptKey, enums, generateKey, Key, KeyID, PacketList, PrivateKey, PublicKey, readKey, readKeys, readMessage, revokeKey, SecretKeyPacket, SecretSubkeyPacket, SignaturePacket, UserID } from 'openpgp'; -import { readToEnd } from '@openpgp/web-stream-tools'; +import { readToEnd } from 'openpgp'; +//import { readToEnd } from '@openpgp/web-stream-tools'; import { isFullyDecrypted, isFullyEncrypted } from './pgp'; export type Contact = { diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index 1a30d5956..a655ad976 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -15,7 +15,8 @@ import { MsgBlockParser } from './msg-block-parser'; import { PgpArmor } from './pgp-armor'; import { Store } from '../platform/store'; import { CleartextMessage, createCleartextMessage, createMessage, Data, encrypt, enums, Key, KeyID, Message, PrivateKey, readKeys, readMessage, sign, VerificationResult } from 'openpgp'; -import { readToEnd } from '@openpgp/web-stream-tools'; +import { readToEnd } from 'openpgp'; +//import { readToEnd } from '@openpgp/web-stream-tools'; import { isFullyDecrypted, isFullyEncrypted, isPacketDecrypted } from './pgp'; export namespace PgpMsgMethod { diff --git a/Core/source/core/types/openpgp.d.ts b/Core/source/core/types/openpgp.d.ts index 2d61e341a..93eb2b992 100644 --- a/Core/source/core/types/openpgp.d.ts +++ b/Core/source/core/types/openpgp.d.ts @@ -886,3 +886,7 @@ export namespace enums { mime = 109 } } + +// -----BEGIN ADDED BY FLOWCRYPT----- +export function readToEnd(input: MaybeStream, concat?: (list: T[]) => T): Promise; +// -----END ADDED BY FLOWCRYPT----- diff --git a/Core/tooling/build.sh b/Core/tooling/build.sh index bec9a61be..58de250c9 100755 --- a/Core/tooling/build.sh +++ b/Core/tooling/build.sh @@ -2,27 +2,38 @@ set -euxo pipefail -# will remove this when openpgp.js will release all our fixes +# fix openpgp in node_modules echo "Patching openpgp.js v5..." -cp -fv ./source/core/types/openpgp.d.ts ./node_modules/openpgp/ -echo "Patching openpgp.js v5 - DONE." - -# will remove this when @openpgp/web-stream-tools would release their type definitions -echo "Patching @openpgp/web-stream-tools ..." -cp -fv ./source/core/types/web-stream-tools.d.ts ./node_modules/@openpgp/web-stream-tools/ -wst_pkg=./node_modules/@openpgp/web-stream-tools/package.json +for f in openpgp.min.js openpgp.min.js.map openpgp.min.mjs openpgp.min.mjs.map openpgp.mjs; +do + if [ -f ./node_modules/openpgp/dist/$f ]; then rm -f ./node_modules/openpgp/dist/$f ; fi + if [ -f ./node_modules/openpgp/dist/node/$f ]; then rm -f ./node_modules/openpgp/dist/node/$f ; fi +done +if [ -f ./node_modules/openpgp/dist/openpgp.js ]; then rm -f ./node_modules/openpgp/dist/openpgp.js ; fi +extra_exports=" +// -----BEGIN ADDED BY FLOWCRYPT---- +exports.readToEnd = readToEnd; +// -----END ADDED BY FLOWCRYPT----- +" +dist_js=./node_modules/openpgp/dist/node/openpgp.js +tmp_js=${dist_js}.tmp set +e -wst_patched=$(grep -n '"types":' $wst_pkg | wc -l) +fc_added=$(grep 'BEGIN ADDED BY FLOWCRYPT' ${dist_js} | wc -l) set -e -if [ $wst_patched = 0 ]; then - wst_pkg_tmp=${wst_pkg}.tmp - n=$(grep -n '"main":' $wst_pkg | cut -f1 -d':') - head -$n ${wst_pkg} >${wst_pkg_tmp} - echo ' "types": "web-stream-tools.d.ts",' >>${wst_pkg_tmp} - tail -n $((n+1)) ${wst_pkg} >>${wst_pkg_tmp} - mv -f ${wst_pkg_tmp} ${wst_pkg} +if [ $fc_added = 0 ]; then + n=$(grep -n 'exports.verify' ${dist_js} | cut -f1 -d':') + head -$n ${dist_js} >${tmp_js} + echo "$extra_exports" >>${tmp_js} + tail -n +$((n+1)) ${dist_js} >>${tmp_js} + mv -f ${tmp_js} ${dist_js} fi -echo "Patching @openpgp/web-stream-tools - DONE." +cp -fv ./source/core/types/openpgp.d.ts ./node_modules/openpgp/ +# MacOS sed is old BSD sed w/o "-i" (see https://ss64.com/osx/sed.html) +sed 's/openpgp.min.js/openpgp.js/g' ./node_modules/openpgp/package.json >./node_modules/openpgp/package.json.tmp +cp -f ./node_modules/openpgp/package.json.tmp ./node_modules/openpgp/package.json +sed 's/openpgp.min.mjs/openpgp.mjs/g' ./node_modules/openpgp/package.json >./node_modules/openpgp/package.json.tmp +cp -f ./node_modules/openpgp/package.json.tmp ./node_modules/openpgp/package.json +echo "Patching openpgp.js v5 - DONE." # clean up rm -rf ./build/ts ./build/bundles ./build/final/* diff --git a/Core/tooling/build.sh.with-web-stream-tools.save b/Core/tooling/build.sh.with-web-stream-tools.save new file mode 100755 index 000000000..bec9a61be --- /dev/null +++ b/Core/tooling/build.sh.with-web-stream-tools.save @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +set -euxo pipefail + +# will remove this when openpgp.js will release all our fixes +echo "Patching openpgp.js v5..." +cp -fv ./source/core/types/openpgp.d.ts ./node_modules/openpgp/ +echo "Patching openpgp.js v5 - DONE." + +# will remove this when @openpgp/web-stream-tools would release their type definitions +echo "Patching @openpgp/web-stream-tools ..." +cp -fv ./source/core/types/web-stream-tools.d.ts ./node_modules/@openpgp/web-stream-tools/ +wst_pkg=./node_modules/@openpgp/web-stream-tools/package.json +set +e +wst_patched=$(grep -n '"types":' $wst_pkg | wc -l) +set -e +if [ $wst_patched = 0 ]; then + wst_pkg_tmp=${wst_pkg}.tmp + n=$(grep -n '"main":' $wst_pkg | cut -f1 -d':') + head -$n ${wst_pkg} >${wst_pkg_tmp} + echo ' "types": "web-stream-tools.d.ts",' >>${wst_pkg_tmp} + tail -n $((n+1)) ${wst_pkg} >>${wst_pkg_tmp} + mv -f ${wst_pkg_tmp} ${wst_pkg} +fi +echo "Patching @openpgp/web-stream-tools - DONE." + +# clean up +rm -rf ./build/ts ./build/bundles ./build/final/* +mkdir -p ./build/final + +# build our source with typescript +./node_modules/.bin/tsc --project tsconfig.json + +# build raw/ with webpack +./node_modules/.bin/webpack --config webpack.bare.config.js + +# move modified raw/ to bundles/ +node ./tooling/fix-bundles.js + +# concatenate external deps into one bundle +( cd ./build/bundles && cat bare-html-sanitize-bundle.js bare-emailjs-bundle.js bare-openpgp-bundle.js bare-zxcvbn-bundle.js bare-encoding-japanese.js > bare-deps-bundle.js ) # bare deps + +# create final builds for dev, ios, android +node ./tooling/build-final.js From c85856574a185ee0734fc96a8a967ad71fec3d56 Mon Sep 17 00:00:00 2001 From: tomholub Date: Sun, 13 Feb 2022 19:42:44 +0100 Subject: [PATCH 171/179] import web-stream-tools --- Core/source/core/pgp-msg.ts | 44 ++++++++++---------- Core/source/core/types/web-stream-tools.d.ts | 31 +++++++------- Core/tooling/build.sh | 2 +- Core/webpack.bare.config.js | 6 ++- 4 files changed, 45 insertions(+), 38 deletions(-) diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index a655ad976..ab8d883f6 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -1,8 +1,8 @@ /* © 2016-present FlowCrypt a. s. Limitations apply. Contact human@flowcrypt.com */ -'use strict'; +/// - -/// +'use strict'; import { KeyInfo, PgpKey, PrvKeyInfo } from './pgp-key'; import { MsgBlock, MsgBlockType } from './msg-block'; @@ -15,8 +15,10 @@ import { MsgBlockParser } from './msg-block-parser'; import { PgpArmor } from './pgp-armor'; import { Store } from '../platform/store'; import { CleartextMessage, createCleartextMessage, createMessage, Data, encrypt, enums, Key, KeyID, Message, PrivateKey, readKeys, readMessage, sign, VerificationResult } from 'openpgp'; -import { readToEnd } from 'openpgp'; -//import { readToEnd } from '@openpgp/web-stream-tools'; +// this will work for running tests in node with build/ts/test.js as entrypoint +// a different solution will have to be done for running in iOS +(global as any)['window'] = (global as any)['window'] || {}; // web-stream-tools needs this +const { readToEnd } = require('../../bundles/raw/web-stream-tools'); import { isFullyDecrypted, isFullyEncrypted, isPacketDecrypted } from './pgp'; export namespace PgpMsgMethod { @@ -140,7 +142,7 @@ export class PgpMsg { * Returns signature if detached=true, armored */ public static sign = async (signingPrv: Key, data: string, detached = false): Promise => { - const message = await createCleartextMessage({text: data}); + const message = await createCleartextMessage({ text: data }); const signRes = await sign({ message, signingKeys: (signingPrv as PrivateKey), @@ -153,7 +155,7 @@ export class PgpMsg { public static verify = async ( msgOrVerResults: OpenpgpMsgOrCleartext | VerificationResult[], pubs: Key[] - ): Promise => { + ): Promise => { const sig: VerifyRes = { match: null }; // tslint:disable-line:no-null-keyword try { // While this looks like bad method API design, it's here to ensure execution order when: @@ -186,12 +188,12 @@ export class PgpMsg { } public static verifyDetached: PgpMsgMethod.VerifyDetached = async ({ plaintext, sigText, verificationPubkeys }) => { - const message = await createMessage({text: Buf.fromUint8(plaintext).toUtfStr()}); + const message = await createMessage({ text: Buf.fromUint8(plaintext).toUtfStr() }); await message.appendSignature(Buf.fromUint8(sigText).toUtfStr()); const keys = await PgpMsg.getSortedKeys([], message); if (verificationPubkeys) { for (const verificationPubkey of verificationPubkeys) { - const k = await readKeys({armoredKeys: verificationPubkey}); + const k = await readKeys({ armoredKeys: verificationPubkey }); keys.forVerification.push(...k); } } @@ -271,10 +273,10 @@ export class PgpMsg { if (!pubkeys && !pwd) { throw new Error('no-pubkeys-no-challenge'); } - const message = await createMessage({binary: data, filename, date}); + const message = await createMessage({ binary: data, filename, date }); const encryptionKeys = []; for (const armoredPubkey of pubkeys) { - const publicKeys = await readKeys({armoredKeys: armoredPubkey}); + const publicKeys = await readKeys({ armoredKeys: armoredPubkey }); encryptionKeys.push(...publicKeys); } // Have to keep this "if" here because it doesn't compile if we use @@ -326,17 +328,17 @@ export class PgpMsg { if (decryptedContent.includes('class="cryptup_file"')) { decryptedContent = decryptedContent.replace( /[^<]+<\/a>\n?/gm, (_, url, fcData) => { - const a = Str.htmlAttrDecode(String(fcData)); - if (PgpMsg.isFcAttLinkData(a)) { - blocks.push(MsgBlock.fromAtt('encryptedAttLink', '', { - type: a.type, - name: a.name, - length: a.size, - url: String(url) - })); - } - return ''; - }); + const a = Str.htmlAttrDecode(String(fcData)); + if (PgpMsg.isFcAttLinkData(a)) { + blocks.push(MsgBlock.fromAtt('encryptedAttLink', '', { + type: a.type, + name: a.name, + length: a.size, + url: String(url) + })); + } + return ''; + }); } return decryptedContent; } diff --git a/Core/source/core/types/web-stream-tools.d.ts b/Core/source/core/types/web-stream-tools.d.ts index 61afc63d4..90c4e9e44 100644 --- a/Core/source/core/types/web-stream-tools.d.ts +++ b/Core/source/core/types/web-stream-tools.d.ts @@ -1,22 +1,25 @@ + +// declare module '@openpgp/web-stream-tools'; + declare module "@openpgp/web-stream-tools" { - type Data = Uint8Array | string; + type Data = Uint8Array | string; - interface BaseStream extends AsyncIterable { } + interface BaseStream extends AsyncIterable { } - interface WebStream extends BaseStream { // copied+simplified version of ReadableStream from lib.dom.d.ts - readonly locked: boolean; getReader: Function; pipeThrough: Function; pipeTo: Function; tee: Function; - cancel(reason?: any): Promise; - } + interface WebStream extends BaseStream { // copied+simplified version of ReadableStream from lib.dom.d.ts + readonly locked: boolean; getReader: Function; pipeThrough: Function; pipeTo: Function; tee: Function; + cancel(reason?: any): Promise; + } - interface NodeStream extends BaseStream { // copied+simplified version of ReadableStream from @types/node/index.d.ts - readable: boolean; pipe: Function; unpipe: Function; wrap: Function; - read(size?: number): string | Uint8Array; setEncoding(encoding: string): this; pause(): this; resume(): this; - isPaused(): boolean; unshift(chunk: string | Uint8Array): void; - } + interface NodeStream extends BaseStream { // copied+simplified version of ReadableStream from @types/node/index.d.ts + readable: boolean; pipe: Function; unpipe: Function; wrap: Function; + read(size?: number): string | Uint8Array; setEncoding(encoding: string): this; pause(): this; resume(): this; + isPaused(): boolean; unshift(chunk: string | Uint8Array): void; + } - type Stream = WebStream | NodeStream; + type Stream = WebStream | NodeStream; - type MaybeStream = T | Stream; + type MaybeStream = T | Stream; - export function readToEnd(input: MaybeStream, concat?: (list: T[]) => T): Promise; + export function readToEnd(input: MaybeStream, concat?: (list: T[]) => T): Promise; } diff --git a/Core/tooling/build.sh b/Core/tooling/build.sh index 58de250c9..07c5e72f7 100755 --- a/Core/tooling/build.sh +++ b/Core/tooling/build.sh @@ -51,5 +51,5 @@ node ./tooling/fix-bundles.js # concatenate external deps into one bundle ( cd ./build/bundles && cat bare-html-sanitize-bundle.js bare-emailjs-bundle.js bare-openpgp-bundle.js bare-zxcvbn-bundle.js bare-encoding-japanese.js > bare-deps-bundle.js ) # bare deps -# create final builds for dev, ios, android +# create final builds for ios node ./tooling/build-final.js diff --git a/Core/webpack.bare.config.js b/Core/webpack.bare.config.js index 6c8eeaef0..79897c270 100644 --- a/Core/webpack.bare.config.js +++ b/Core/webpack.bare.config.js @@ -6,7 +6,8 @@ module.exports = { 'entrypoint-bare': './build/ts/entrypoint-bare.js', 'bare-asn1': './node_modules/asn1.js/lib/asn1.js', 'bare-encoding-japanese': './node_modules/encoding-japanese/encoding.js', - 'sanitize-html': './node_modules/sanitize-html/index.js' + 'sanitize-html': './node_modules/sanitize-html/index.js', + 'web-stream-tools': './node_modules/@openpgp/web-stream-tools/lib/streams.js' }, output: { path: __dirname + '/build/bundles/raw', @@ -14,6 +15,7 @@ module.exports = { libraryTarget: 'commonjs2' }, externals: { - openpgp: 'openpgp' + openpgp: 'openpgp', + '../../bundles/raw/web-stream-tools': '../../bundles/raw/web-stream-tools' } } From e76703399850a3e06f37a9c167f74a2a79f5e92f Mon Sep 17 00:00:00 2001 From: tomholub Date: Sun, 13 Feb 2022 20:02:29 +0100 Subject: [PATCH 172/179] clean up --- Core/source/core/pgp-key.ts | 38 ++++++++++---------- Core/source/core/pgp-msg.ts | 7 ++-- Core/source/core/types/web-stream-tools.d.ts | 25 ------------- Core/source/platform/require.ts | 23 ++++++++++++ Core/tooling/build.sh | 33 ----------------- Core/webpack.bare.config.js | 2 +- 6 files changed, 46 insertions(+), 82 deletions(-) delete mode 100644 Core/source/core/types/web-stream-tools.d.ts diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index 250973bea..68b378748 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -10,9 +10,9 @@ import { Store } from '../platform/store'; import { mnemonic } from './mnemonic'; import { getKeyExpirationTimeForCapabilities, str_to_hex } from '../platform/util'; import { AnyKeyPacket, encryptKey, enums, generateKey, Key, KeyID, PacketList, PrivateKey, PublicKey, readKey, readKeys, readMessage, revokeKey, SecretKeyPacket, SecretSubkeyPacket, SignaturePacket, UserID } from 'openpgp'; -import { readToEnd } from 'openpgp'; -//import { readToEnd } from '@openpgp/web-stream-tools'; import { isFullyDecrypted, isFullyEncrypted } from './pgp'; +import { requireStreamReadToEnd } from '../platform/require'; +const readToEnd = requireStreamReadToEnd(); export type Contact = { email: string; @@ -95,7 +95,7 @@ export class PgpKey { if (fromCache) { return fromCache; } - const key = await readKey({armoredKey: armoredKey}); + const key = await readKey({ armoredKey: armoredKey }); if (key?.isPrivate()) { Store.armoredKeyCacheSet(armoredKey, key); } @@ -114,8 +114,8 @@ export class PgpKey { const pushKeysAndErrs = async (content: string | Buf, type: 'readArmored' | 'read') => { try { const keys = type === 'readArmored' - ? await readKeys({armoredKeys: content.toString()}) - : await readKeys({binaryKeys: (typeof content === 'string' ? Buf.fromUtfStr(content) : content)}); + ? await readKeys({ armoredKeys: content.toString() }) + : await readKeys({ binaryKeys: (typeof content === 'string' ? Buf.fromUtfStr(content) : content) }); allKeys.push(...keys); } catch (e) { allErrs.push(e instanceof Error ? e : new Error(String(e))); @@ -179,7 +179,7 @@ export class PgpKey { throw new Error(`Cannot encrypt a key that has ${encryptedPacketCount} of ` + `${secretPackets.length} private packets still encrypted`); } - await encryptKey({privateKey: (prv as PrivateKey), passphrase}); + await encryptKey({ privateKey: (prv as PrivateKey), passphrase }); } public static normalize = async (armored: string): Promise<{ normalized: string, keys: Key[] }> => { @@ -187,11 +187,11 @@ export class PgpKey { let keys: Key[] = []; armored = PgpArmor.normalize(armored, 'key'); if (RegExp(PgpArmor.headers('publicKey', 're').begin).test(armored)) { - keys = (await readKeys({armoredKeys: armored})); + keys = (await readKeys({ armoredKeys: armored })); } else if (RegExp(PgpArmor.headers('privateKey', 're').begin).test(armored)) { - keys = (await readKeys({armoredKeys: armored})); + keys = (await readKeys({ armoredKeys: armored })); } else if (RegExp(PgpArmor.headers('encryptedMsg', 're').begin).test(armored)) { - const msg = await readMessage({armoredMessage: armored}); + const msg = await readMessage({ armoredMessage: armored }); keys = [new PublicKey(msg.packets as PacketList)]; } for (const k of keys) { @@ -265,7 +265,7 @@ export class PgpKey { if (!PgpKey.fingerprint(armored)) { return false; } - const pubkey = await readKey({armoredKey: armored}); + const pubkey = await readKey({ armoredKey: armored }); if (!pubkey) { return false; } @@ -372,7 +372,8 @@ export class PgpKey { const data = { userID: user.userID, userAttribute: user.userAttribute, key: key }; for (const selfCert of user.selfCertifications) { try { - await selfCert.verify(key.keyPacket, enums.signature.certGeneric, data); + // todo - add proper type in openpgp.d.ts + await selfCert.verify(key.keyPacket, enums.signature.certGeneric, data as any); // quick hack allSignatures.push(selfCert); } catch (e) { console.log(`PgpKey.lastSig: Skipping self-certification signature because it is invalid: ${String(e)}`); @@ -389,19 +390,20 @@ export class PgpKey { } } if (allSignatures.length > 0) { - allSignatures.sort((a, b) => { - return (b.created ? b.created.getTime() : 0) - (a.created ? a.created.getTime() : 0); - }); - const newestSig = allSignatures[0]; - return newestSig.created ? newestSig.created.getTime() : 0; + allSignatures.sort((a, b) => { + return (b.created ? b.created.getTime() : 0) - (a.created ? a.created.getTime() : 0); + }); + const newestSig = allSignatures[0]; + return newestSig.created ? newestSig.created.getTime() : 0; } throw new Error('No valid signature found in key'); } public static revoke = async (key: Key): Promise => { - if (!key.isRevoked()) { + // todo - quick hack to pass tests + if (!key.isRevoked(undefined as any as SignaturePacket)) { if (!key.isPrivate()) throw Error('Revocation of public key not implemented'); - const keypair = await revokeKey({key: key as PrivateKey, format: 'object'}); + const keypair = await revokeKey({ key: key as PrivateKey, format: 'object' }); key = keypair.privateKey; } const certificate = await key.getRevocationCertificate(); diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index ab8d883f6..4056542a3 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -7,7 +7,6 @@ import { KeyInfo, PgpKey, PrvKeyInfo } from './pgp-key'; import { MsgBlock, MsgBlockType } from './msg-block'; import { Str, Value } from './common'; - import { Buf } from './buf'; import { Catch } from '../platform/catch'; import { FcAttLinkData } from './att'; @@ -15,11 +14,9 @@ import { MsgBlockParser } from './msg-block-parser'; import { PgpArmor } from './pgp-armor'; import { Store } from '../platform/store'; import { CleartextMessage, createCleartextMessage, createMessage, Data, encrypt, enums, Key, KeyID, Message, PrivateKey, readKeys, readMessage, sign, VerificationResult } from 'openpgp'; -// this will work for running tests in node with build/ts/test.js as entrypoint -// a different solution will have to be done for running in iOS -(global as any)['window'] = (global as any)['window'] || {}; // web-stream-tools needs this -const { readToEnd } = require('../../bundles/raw/web-stream-tools'); import { isFullyDecrypted, isFullyEncrypted, isPacketDecrypted } from './pgp'; +import { requireStreamReadToEnd } from '../platform/require'; +const readToEnd = requireStreamReadToEnd(); export namespace PgpMsgMethod { export namespace Arg { diff --git a/Core/source/core/types/web-stream-tools.d.ts b/Core/source/core/types/web-stream-tools.d.ts deleted file mode 100644 index 90c4e9e44..000000000 --- a/Core/source/core/types/web-stream-tools.d.ts +++ /dev/null @@ -1,25 +0,0 @@ - -// declare module '@openpgp/web-stream-tools'; - -declare module "@openpgp/web-stream-tools" { - type Data = Uint8Array | string; - - interface BaseStream extends AsyncIterable { } - - interface WebStream extends BaseStream { // copied+simplified version of ReadableStream from lib.dom.d.ts - readonly locked: boolean; getReader: Function; pipeThrough: Function; pipeTo: Function; tee: Function; - cancel(reason?: any): Promise; - } - - interface NodeStream extends BaseStream { // copied+simplified version of ReadableStream from @types/node/index.d.ts - readable: boolean; pipe: Function; unpipe: Function; wrap: Function; - read(size?: number): string | Uint8Array; setEncoding(encoding: string): this; pause(): this; resume(): this; - isPaused(): boolean; unshift(chunk: string | Uint8Array): void; - } - - type Stream = WebStream | NodeStream; - - type MaybeStream = T | Stream; - - export function readToEnd(input: MaybeStream, concat?: (list: T[]) => T): Promise; -} diff --git a/Core/source/platform/require.ts b/Core/source/platform/require.ts index a5eb54908..dd2edccdd 100644 --- a/Core/source/platform/require.ts +++ b/Core/source/platform/require.ts @@ -2,6 +2,29 @@ 'use strict'; +interface BaseStream extends AsyncIterable { } + +interface WebStream extends BaseStream { // copied+simplified version of ReadableStream from lib.dom.d.ts + readonly locked: boolean; getReader: Function; pipeThrough: Function; pipeTo: Function; tee: Function; + cancel(reason?: any): Promise; +} + +interface NodeStream extends BaseStream { // copied+simplified version of ReadableStream from @types/node/index.d.ts + readable: boolean; pipe: Function; unpipe: Function; wrap: Function; + read(size?: number): string | Uint8Array; setEncoding(encoding: string): this; pause(): this; resume(): this; + isPaused(): boolean; unshift(chunk: string | Uint8Array): void; +} + +type ReadToEndFn = (input: T | WebStream | NodeStream, concat?: (list: T[]) => T) => Promise; + +export const requireStreamReadToEnd = (): ReadToEndFn => { + // this will work for running tests in node with build/ts/test.js as entrypoint + // a different solution will have to be done for running in iOS + (global as any)['window'] = (global as any)['window'] || {}; // web-stream-tools needs this + const { readToEnd } = require('../../bundles/raw/web-stream-tools'); + return readToEnd as ReadToEndFn; +} + export const requireMimeParser = (): any => { // @ts-ignore; return global['emailjs-mime-parser']; diff --git a/Core/tooling/build.sh b/Core/tooling/build.sh index 07c5e72f7..3db3bd9c7 100755 --- a/Core/tooling/build.sh +++ b/Core/tooling/build.sh @@ -2,39 +2,6 @@ set -euxo pipefail -# fix openpgp in node_modules -echo "Patching openpgp.js v5..." -for f in openpgp.min.js openpgp.min.js.map openpgp.min.mjs openpgp.min.mjs.map openpgp.mjs; -do - if [ -f ./node_modules/openpgp/dist/$f ]; then rm -f ./node_modules/openpgp/dist/$f ; fi - if [ -f ./node_modules/openpgp/dist/node/$f ]; then rm -f ./node_modules/openpgp/dist/node/$f ; fi -done -if [ -f ./node_modules/openpgp/dist/openpgp.js ]; then rm -f ./node_modules/openpgp/dist/openpgp.js ; fi -extra_exports=" -// -----BEGIN ADDED BY FLOWCRYPT---- -exports.readToEnd = readToEnd; -// -----END ADDED BY FLOWCRYPT----- -" -dist_js=./node_modules/openpgp/dist/node/openpgp.js -tmp_js=${dist_js}.tmp -set +e -fc_added=$(grep 'BEGIN ADDED BY FLOWCRYPT' ${dist_js} | wc -l) -set -e -if [ $fc_added = 0 ]; then - n=$(grep -n 'exports.verify' ${dist_js} | cut -f1 -d':') - head -$n ${dist_js} >${tmp_js} - echo "$extra_exports" >>${tmp_js} - tail -n +$((n+1)) ${dist_js} >>${tmp_js} - mv -f ${tmp_js} ${dist_js} -fi -cp -fv ./source/core/types/openpgp.d.ts ./node_modules/openpgp/ -# MacOS sed is old BSD sed w/o "-i" (see https://ss64.com/osx/sed.html) -sed 's/openpgp.min.js/openpgp.js/g' ./node_modules/openpgp/package.json >./node_modules/openpgp/package.json.tmp -cp -f ./node_modules/openpgp/package.json.tmp ./node_modules/openpgp/package.json -sed 's/openpgp.min.mjs/openpgp.mjs/g' ./node_modules/openpgp/package.json >./node_modules/openpgp/package.json.tmp -cp -f ./node_modules/openpgp/package.json.tmp ./node_modules/openpgp/package.json -echo "Patching openpgp.js v5 - DONE." - # clean up rm -rf ./build/ts ./build/bundles ./build/final/* mkdir -p ./build/final diff --git a/Core/webpack.bare.config.js b/Core/webpack.bare.config.js index 79897c270..e40fff6f4 100644 --- a/Core/webpack.bare.config.js +++ b/Core/webpack.bare.config.js @@ -16,6 +16,6 @@ module.exports = { }, externals: { openpgp: 'openpgp', - '../../bundles/raw/web-stream-tools': '../../bundles/raw/web-stream-tools' + '../../bundles/raw/web-stream-tools': '../..bundles/raw/web-stream-tools' } } From b0a929ceb26d89e287538440a56f7f200ab0ed44 Mon Sep 17 00:00:00 2001 From: tomholub Date: Sun, 13 Feb 2022 20:05:26 +0100 Subject: [PATCH 173/179] cleanup --- .../build.sh.with-web-stream-tools.save | 44 ------------------- 1 file changed, 44 deletions(-) delete mode 100755 Core/tooling/build.sh.with-web-stream-tools.save diff --git a/Core/tooling/build.sh.with-web-stream-tools.save b/Core/tooling/build.sh.with-web-stream-tools.save deleted file mode 100755 index bec9a61be..000000000 --- a/Core/tooling/build.sh.with-web-stream-tools.save +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env bash - -set -euxo pipefail - -# will remove this when openpgp.js will release all our fixes -echo "Patching openpgp.js v5..." -cp -fv ./source/core/types/openpgp.d.ts ./node_modules/openpgp/ -echo "Patching openpgp.js v5 - DONE." - -# will remove this when @openpgp/web-stream-tools would release their type definitions -echo "Patching @openpgp/web-stream-tools ..." -cp -fv ./source/core/types/web-stream-tools.d.ts ./node_modules/@openpgp/web-stream-tools/ -wst_pkg=./node_modules/@openpgp/web-stream-tools/package.json -set +e -wst_patched=$(grep -n '"types":' $wst_pkg | wc -l) -set -e -if [ $wst_patched = 0 ]; then - wst_pkg_tmp=${wst_pkg}.tmp - n=$(grep -n '"main":' $wst_pkg | cut -f1 -d':') - head -$n ${wst_pkg} >${wst_pkg_tmp} - echo ' "types": "web-stream-tools.d.ts",' >>${wst_pkg_tmp} - tail -n $((n+1)) ${wst_pkg} >>${wst_pkg_tmp} - mv -f ${wst_pkg_tmp} ${wst_pkg} -fi -echo "Patching @openpgp/web-stream-tools - DONE." - -# clean up -rm -rf ./build/ts ./build/bundles ./build/final/* -mkdir -p ./build/final - -# build our source with typescript -./node_modules/.bin/tsc --project tsconfig.json - -# build raw/ with webpack -./node_modules/.bin/webpack --config webpack.bare.config.js - -# move modified raw/ to bundles/ -node ./tooling/fix-bundles.js - -# concatenate external deps into one bundle -( cd ./build/bundles && cat bare-html-sanitize-bundle.js bare-emailjs-bundle.js bare-openpgp-bundle.js bare-zxcvbn-bundle.js bare-encoding-japanese.js > bare-deps-bundle.js ) # bare deps - -# create final builds for dev, ios, android -node ./tooling/build-final.js From 2a8c6c26b44ba832d905c68464efe02368b04dfc Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 13 Feb 2022 21:54:42 +0200 Subject: [PATCH 174/179] remove openpgp.d.ts --- Core/source/core/types/openpgp.d.ts | 892 ---------------------------- 1 file changed, 892 deletions(-) delete mode 100644 Core/source/core/types/openpgp.d.ts diff --git a/Core/source/core/types/openpgp.d.ts b/Core/source/core/types/openpgp.d.ts deleted file mode 100644 index 93eb2b992..000000000 --- a/Core/source/core/types/openpgp.d.ts +++ /dev/null @@ -1,892 +0,0 @@ -/** - * Type definitions for OpenPGP.js http://openpgpjs.org/ - * - * Contributors: - * - FlowCrypt a. s. - * - Guillaume Lacasa - * - Errietta Kostala - */ - -/* ############## v5 KEY #################### */ -// The Key and PublicKey types can be used interchangably since TS cannot detect the difference, as they have the same class properties. -// The declared readKey(s) return type is Key instead of a PublicKey since it seems more obvious that a Key can be cast to a PrivateKey. -export function readKey(options: { armoredKey: string, config?: PartialConfig }): Promise; -export function readKey(options: { binaryKey: Uint8Array, config?: PartialConfig }): Promise; -export function readKeys(options: { armoredKeys: string, config?: PartialConfig }): Promise; -export function readKeys(options: { binaryKeys: Uint8Array, config?: PartialConfig }): Promise; -export function readPrivateKey(options: { armoredKey: string, config?: PartialConfig }): Promise; -export function readPrivateKey(options: { binaryKey: Uint8Array, config?: PartialConfig }): Promise; -export function readPrivateKeys(options: { armoredKeys: string, config?: PartialConfig }): Promise; -export function readPrivateKeys(options: { binaryKeys: Uint8Array, config?: PartialConfig }): Promise; -export function generateKey(options: KeyOptions & { format?: 'armored' }): Promise & { revocationCertificate: string }>; -export function generateKey(options: KeyOptions & { format: 'binary' }): Promise & { revocationCertificate: string }>; -export function generateKey(options: KeyOptions & { format: 'object' }): Promise; -export function decryptKey(options: { privateKey: PrivateKey; passphrase?: MaybeArray; config?: PartialConfig }): Promise; -export function encryptKey(options: { privateKey: PrivateKey; passphrase?: MaybeArray; config?: PartialConfig }): Promise; -export function reformatKey(options: { privateKey: PrivateKey; userIDs?: MaybeArray; passphrase?: string; keyExpirationTime?: number; date?: Date, format?: 'armored', config?: PartialConfig }): Promise & { revocationCertificate: string }>; -export function reformatKey(options: { privateKey: PrivateKey; userIDs?: MaybeArray; passphrase?: string; keyExpirationTime?: number; date?: Date, format: 'binary', config?: PartialConfig }): Promise & { revocationCertificate: string }>; -export function reformatKey(options: { privateKey: PrivateKey; userIDs?: MaybeArray; passphrase?: string; keyExpirationTime?: number; date?: Date, format: 'object', config?: PartialConfig }): Promise; -export function revokeKey(options: { key: PrivateKey, reasonForRevocation?: ReasonForRevocation, date?: Date, format?: 'armored', config?: PartialConfig }): Promise>; -export function revokeKey(options: { key: PrivateKey, reasonForRevocation?: ReasonForRevocation, date?: Date, format: 'binary', config?: PartialConfig }): Promise>; -export function revokeKey(options: { key: PrivateKey, reasonForRevocation?: ReasonForRevocation, date?: Date, format: 'object', config?: PartialConfig }): Promise; -export function revokeKey(options: { key: PrivateKey, revocationCertificate: string, date?: Date, format?: 'armored', config?: PartialConfig }): Promise>; -export function revokeKey(options: { key: PrivateKey, revocationCertificate: string, date?: Date, format: 'binary', config?: PartialConfig }): Promise>; -export function revokeKey(options: { key: PrivateKey, revocationCertificate: string, date?: Date, format: 'object', config?: PartialConfig }): Promise; -export function revokeKey(options: { key: PublicKey, revocationCertificate: string, date?: Date, format?: 'armored', config?: PartialConfig }): Promise<{ publicKey: string, privateKey: null }>; -export function revokeKey(options: { key: PublicKey, revocationCertificate: string, date?: Date, format: 'binary', config?: PartialConfig }): Promise<{ publicKey: Uint8Array, privateKey: null }>; -export function revokeKey(options: { key: PublicKey, revocationCertificate: string, date?: Date, format: 'object', config?: PartialConfig }): Promise<{ publicKey: PublicKey, privateKey: null }>; - -export abstract class Key { - public readonly keyPacket: PublicKeyPacket | SecretKeyPacket; - public subkeys: Subkey[]; // do not add/replace users directly - public users: User[]; // do not add/replace subkeys directly - public revocationSignatures: SignaturePacket[]; - public write(): Uint8Array; - public armor(config?: Config): string; - public getExpirationTime(userID?: UserID, config?: Config): Promise; - public getKeyIDs(): KeyID[]; - public getPrimaryUser(date?: Date, userID?: UserID, config?: Config): Promise; // throws on error - public getUserIDs(): string[]; - public isPrivate(): this is PrivateKey; - public toPublic(): PublicKey; - // NB: the order of the `update` declarations matters, since PublicKey includes PrivateKey - public update(sourceKey: PrivateKey, date?: Date, config?: Config): Promise; - public update(sourceKey: PublicKey, date?: Date, config?: Config): Promise; - public signPrimaryUser(privateKeys: PrivateKey[], date?: Date, userID?: UserID, config?: Config): Promise - public signAllUsers(privateKeys: PrivateKey[], date?: Date, config?: Config): Promise - public verifyPrimaryKey(date?: Date, userID?: UserID, config?: Config): Promise; // throws on error - public verifyPrimaryUser(publicKeys: PublicKey[], date?: Date, userIDs?: UserID, config?: Config): Promise<{ keyID: KeyID, valid: boolean | null }[]>; - public verifyAllUsers(publicKeys: PublicKey[], date?: Date, config?: Config): Promise<{ userID: string, keyID: KeyID, valid: boolean | null }[]>; - // -----BEGIN MODIFIED BY FLOWCRYPT----- - // Make this permanent: https://github.com/openpgpjs/openpgpjs/pull/1486 - public isRevoked(signature?: SignaturePacket, key?: AnyKeyPacket, date?: Date, config?: Config): Promise; - // -----END MODIFIED BY FLOWCRYPT----- - public getRevocationCertificate(date?: Date, config?: Config): Promise | undefined>; - public getEncryptionKey(keyID?: KeyID, date?: Date | null, userID?: UserID, config?: Config): Promise; - public getSigningKey(keyID?: KeyID, date?: Date | null, userID?: UserID, config?: Config): Promise; - public getKeys(keyID?: KeyID): (this | Subkey)[]; - public getSubkeys(keyID?: KeyID): Subkey[]; - public getFingerprint(): string; - public getCreationTime(): Date; - public getAlgorithmInfo(): AlgorithmInfo; - public getKeyID(): KeyID; - public toPacketList(): PacketList; -} - -type AllowedKeyPackets = PublicKeyPacket | PublicSubkeyPacket | SecretKeyPacket | SecretSubkeyPacket | UserIDPacket | UserAttributePacket | SignaturePacket; -export class PublicKey extends Key { - constructor(packetlist: PacketList); -} - -export class PrivateKey extends PublicKey { - constructor(packetlist: PacketList); - public revoke(reason?: ReasonForRevocation, date?: Date, config?: Config): Promise; - public isDecrypted(): boolean; - public addSubkey(options: SubkeyOptions): Promise; - public getDecryptionKeys(keyID?: KeyID, date?: Date | null, userID?: UserID, config?: Config): Promise - public update(sourceKey: PublicKey, date?: Date, config?: Config): Promise; -} - -export class Subkey { - constructor(subkeyPacket: SecretSubkeyPacket | PublicSubkeyPacket, mainKey: PublicKey); - public readonly keyPacket: SecretSubkeyPacket | PublicSubkeyPacket; - public readonly mainKey: PublicKey; - public bindingSignatures: SignaturePacket[]; - public revocationSignatures: SignaturePacket[]; - public verify(date?: Date, config?: Config): Promise; - public isDecrypted(): boolean; - public getFingerprint(): string; - public getCreationTime(): Date; - public getAlgorithmInfo(): AlgorithmInfo; - public getKeyID(): KeyID; -} - -export interface User { - userID: UserIDPacket | null; - userAttribute: UserAttributePacket | null; - selfCertifications: SignaturePacket[]; - otherCertifications: SignaturePacket[]; - revocationSignatures: SignaturePacket[]; -} - -export interface PrimaryUser { - index: number; - user: User; -} - -type AlgorithmInfo = { - algorithm: enums.publicKeyNames; - bits?: number; - curve?: EllipticCurveName; -}; - -/* ############## v5 SIG #################### */ - -export function readSignature(options: { armoredSignature: string, config?: PartialConfig }): Promise; -export function readSignature(options: { binarySignature: Uint8Array, config?: PartialConfig }): Promise; - -export class Signature { - public readonly packets: PacketList; - constructor(packetlist: PacketList); - public write(): MaybeStream; - public armor(config?: Config): string; - public getSigningKeyIDs(): Array; -} - -interface VerificationResult { - keyID: KeyID; - verified: Promise; // throws on invalid signature - signature: Promise; -} - -/* ############## v5 CLEARTEXT #################### */ - -export function readCleartextMessage(options: { cleartextMessage: string, config?: PartialConfig }): Promise; - -export function createCleartextMessage(options: { text: string }): Promise; - -/** Class that represents an OpenPGP cleartext signed message. - */ -export class CleartextMessage { - /** Returns ASCII armored text of cleartext signed message - */ - armor(config?: Config): string; - - /** Returns the key IDs of the keys that signed the cleartext message - */ - getSigningKeyIDs(): KeyID[]; - - /** Get cleartext - */ - getText(): string; - - /** Sign the cleartext message - * - * @param privateKeys private keys with decrypted secret key data for signing - */ - sign(privateKeys: PrivateKey[], signature?: Signature, signingKeyIDs?: KeyID[], date?: Date, userIDs?: UserID[], config?: Config): void; - - /** Verify signatures of cleartext signed message - * @param keys array of keys to verify signatures - */ - verify(keys: PublicKey[], date?: Date, config?: Config): Promise; -} - -/* ############## v5 MSG #################### */ -export function generateSessionKey(options: { encryptionKeys: MaybeArray, date?: Date, encryptionUserIDs?: MaybeArray, config?: PartialConfig }): Promise; -export function encryptSessionKey(options: SessionKey & { - encryptionKeys?: MaybeArray, passwords?: MaybeArray, format?: 'armored', wildcard?: boolean, encryptionKeyIDs?: MaybeArray, date?: Date, encryptionUserIDs?: MaybeArray, config?: PartialConfig -}) : Promise; -export function encryptSessionKey(options: SessionKey & { - encryptionKeys?: MaybeArray, passwords?: MaybeArray, format: 'binary', wildcard?: boolean, encryptionKeyIDs?: MaybeArray, date?: Date, encryptionUserIDs?: MaybeArray, config?: PartialConfig -}) : Promise; -export function encryptSessionKey(options: SessionKey & { - encryptionKeys?: MaybeArray, passwords?: MaybeArray, format: 'object', wildcard?: boolean, encryptionKeyIDs?: MaybeArray, date?: Date, encryptionUserIDs?: MaybeArray, config?: PartialConfig -}) : Promise>; -export function decryptSessionKeys>(options: { message: Message, decryptionKeys?: MaybeArray, passwords?: MaybeArray, date?: Date, config?: PartialConfig }): Promise; - -export function readMessage>(options: { armoredMessage: T, config?: PartialConfig }): Promise>; -export function readMessage>(options: { binaryMessage: T, config?: PartialConfig }): Promise>; - -export function createMessage>(options: { text: T, filename?: string, date?: Date, format?: enums.literalFormatNames }): Promise>; -export function createMessage>(options: { binary: T, filename?: string, date?: Date, format?: enums.literalFormatNames }): Promise>; - -export function encrypt>(options: EncryptOptions & { message: Message, format?: 'armored' }): Promise< - T extends WebStream ? WebStream : - T extends NodeStream ? NodeStream : - string ->; -export function encrypt>(options: EncryptOptions & { message: Message, format: 'binary' }): Promise< - T extends WebStream ? WebStream : - T extends NodeStream ? NodeStream : - Uint8Array ->; -export function encrypt>(options: EncryptOptions & { message: Message, format: 'object' }): Promise>; - -export function sign>(options: SignOptions & { message: Message, format?: 'armored' }): Promise< - T extends WebStream ? WebStream : - T extends NodeStream ? NodeStream : - string ->; -export function sign>(options: SignOptions & { message: Message, format: 'binary' }): Promise< - T extends WebStream ? WebStream : - T extends NodeStream ? NodeStream : - Uint8Array ->; -export function sign>(options: SignOptions & { message: Message, format: 'object' }): Promise>; -export function sign(options: SignOptions & { message: CleartextMessage, format?: 'armored' }): Promise; -export function sign(options: SignOptions & { message: CleartextMessage, format: 'object' }): Promise; - -export function decrypt>(options: DecryptOptions & { message: Message, format: 'binary' }): Promise ? WebStream : - T extends NodeStream ? NodeStream : - Uint8Array -}>; -export function decrypt>(options: DecryptOptions & { message: Message }): Promise ? WebStream : - T extends NodeStream ? NodeStream : - string -}>; - -export function verify>(options: VerifyOptions & { message: Message, format: 'binary' }): Promise ? WebStream : - T extends NodeStream ? NodeStream : - Uint8Array -}>; -export function verify>(options: VerifyOptions & { message: Message }): Promise ? WebStream : - T extends NodeStream ? NodeStream : - string -}>; - -/** Class that represents an OpenPGP message. Can be an encrypted message, signed message, compressed message or literal message - */ -export class Message> { - - public readonly packets: PacketList; - constructor(packetlist: PacketList); - - /** Returns binary representation of message - */ - public write(): MaybeStream; - - /** Returns ASCII armored text of message - */ - public armor(config?: Config): string; - - /** Decrypt the message - @param decryptionKeys array of private keys with decrypted secret data - */ - public decrypt(decryptionKeys?: PrivateKey[], passwords?: string[], sessionKeys?: SessionKey[], date?: Date, config?: Config): Promise>>; - - /** Encrypt the message - @param encryptionKeys array of public keys, used to encrypt the message - */ - public encrypt(encryptionKeys?: PublicKey[], passwords?: string[], sessionKeys?: SessionKey[], wildcard?: boolean, encryptionKeyIDs?: KeyID[], date?: Date, userIDs?: UserID[], config?: Config): Promise>>; - - /** Returns the key IDs of the keys to which the session key is encrypted - */ - public getEncryptionKeyIDs(): KeyID[]; - - /** Get literal data that is the body of the message - */ - public getLiteralData(): MaybeStream | null; - - /** Returns the key IDs of the keys that signed the message - */ - public getSigningKeyIDs(): KeyID[]; - - /** Get literal data as text - */ - public getText(): MaybeStream | null; - - public getFilename(): string | null; - - /** Sign the message (the literal data packet of the message) - @param signingKeys private keys with decrypted secret key data for signing - */ - public sign(signingKeys: PrivateKey[], signature?: Signature, signingKeyIDs?: KeyID[], date?: Date, userIDs?: UserID[], config?: Config): Promise>; - - /** Unwrap compressed message - */ - public unwrapCompressed(): Message; - - /** Verify message signatures - @param verificationKeys array of public keys to verify signatures - */ - public verify(verificationKeys: PublicKey[], date?: Date, config?: Config): Promise; - - /** - * Append signature to unencrypted message object - * @param {String|Uint8Array} detachedSignature - The detached ASCII-armored or Uint8Array PGP signature - */ - public appendSignature(detachedSignature: string | Uint8Array, config?: Config): Promise; -} - - -/* ############## v5 CONFIG #################### */ - -interface Config { - preferredHashAlgorithm: enums.hash; - preferredSymmetricAlgorithm: enums.symmetric; - preferredCompressionAlgorithm: enums.compression; - showVersion: boolean; - showComment: boolean; - deflateLevel: number; - aeadProtect: boolean; - allowUnauthenticatedMessages: boolean; - allowUnauthenticatedStream: boolean; - checksumRequired: boolean; - minRSABits: number; - passwordCollisionCheck: boolean; - revocationsExpire: boolean; - ignoreUnsupportedPackets: boolean; - ignoreMalformedPackets: boolean; - versionString: string; - commentString: string; - allowInsecureDecryptionWithSigningKeys: boolean; - constantTimePKCS1Decryption: boolean; - constantTimePKCS1DecryptionSupportedSymmetricAlgorithms: Set; - v5Keys: boolean; - preferredAEADAlgorithm: enums.aead; - aeadChunkSizeByte: number; - s2kIterationCountByte: number; - minBytesForWebCrypto: number; - maxUserIDLength: number; - knownNotations: string[]; - useIndutnyElliptic: boolean; - rejectHashAlgorithms: Set; - rejectMessageHashAlgorithms: Set; - rejectPublicKeyAlgorithms: Set; - rejectCurves: Set; -} -export var config: Config; - -// PartialConfig has the same properties as Config, but declared as optional. -// This interface is relevant for top-level functions, which accept a subset of configuration options -interface PartialConfig extends Partial {} - -/* ############## v5 PACKET #################### */ - -export abstract class BasePacket { - static readonly tag: enums.packet; - public read(bytes: Uint8Array): void; - public write(): Uint8Array; -} - -/** - * The relationship between the KeyPacket classes is modeled by considering the following: - * - A Secret (Sub)Key Packet can always be used when a Public one is expected. - * - A Subkey Packet cannot always be used when a Primary Key Packet is expected (and vice versa). - */ -export abstract class BasePublicKeyPacket extends BasePacket { - public algorithm: enums.publicKey; - public created: Date; - public version: number; - public getAlgorithmInfo(): AlgorithmInfo; - public getFingerprint(): string; - public getFingerprintBytes(): Uint8Array | null; - public hasSameFingerprintAs(other: BasePublicKeyPacket): boolean; - public getCreationTime(): Date; - public getKeyID(): KeyID; - public isDecrypted(): boolean; - public publicParams: object; - // `isSubkey` is a dummy method to ensure that Subkey packets are not accepted as Key one, and vice versa. - // The key class hierarchy is already modelled to cover this, but the concrete key packet classes - // have compatible structure and TS can't detect the difference. - protected isSubkey(): boolean; -} - -export class PublicKeyPacket extends BasePublicKeyPacket { - static readonly tag: enums.packet.publicKey; - protected isSubkey(): false; -} - -export class PublicSubkeyPacket extends BasePublicKeyPacket { - static readonly tag: enums.packet.publicSubkey; - protected isSubkey(): true; -} - -export abstract class BaseSecretKeyPacket extends BasePublicKeyPacket { - public privateParams: object | null; - public encrypt(passphrase: string, config?: Config): Promise; // throws on error - public decrypt(passphrase: string): Promise; // throws on error - public validate(): Promise; // throws on error - public isDummy(): boolean; - public makeDummy(config?: Config): void; -} - -export class SecretKeyPacket extends BaseSecretKeyPacket { - static readonly tag: enums.packet.secretKey; - protected isSubkey(): false; -} - -export class SecretSubkeyPacket extends BaseSecretKeyPacket { - static readonly tag: enums.packet.secretSubkey; - protected isSubkey(): true; -} - -export class CompressedDataPacket extends BasePacket { - static readonly tag: enums.packet.compressedData; - private compress(): void; - private decompress(config?: Config): void; -} - -export class SymEncryptedIntegrityProtectedDataPacket extends BasePacket { - static readonly tag: enums.packet.symEncryptedIntegrityProtectedData; -} - -export class AEADEncryptedDataPacket extends BasePacket { - static readonly tag: enums.packet.aeadEncryptedData; - private decrypt(sessionKeyAlgorithm: enums.symmetric, sessionKey: Uint8Array, config?: Config): void; - private encrypt(sessionKeyAlgorithm: enums.symmetric, sessionKey: Uint8Array, config?: Config): void; - private crypt(fn: Function, sessionKey: Uint8Array, data: MaybeStream): MaybeStream -} - -export class PublicKeyEncryptedSessionKeyPacket extends BasePacket { - static readonly tag: enums.packet.publicKeyEncryptedSessionKey; - private decrypt(keyPacket: SecretKeyPacket): void; // throws on error - private encrypt(keyPacket: PublicKeyPacket): void; // throws on error -} - -export class SymEncryptedSessionKey extends BasePacket { - static readonly tag: enums.packet.symEncryptedSessionKey; - private decrypt(passphrase: string): Promise; - private encrypt(passphrase: string, config?: Config): Promise; -} - -export class LiteralDataPacket extends BasePacket { - static readonly tag: enums.packet.literalData; - private getText(clone?: boolean): MaybeStream; - private getBytes(clone?: boolean): MaybeStream; - private setText(text: MaybeStream, format?: enums.literal); - private setBytes(bytes: MaybeStream, format: enums.literal); - private setFilename(filename: string); - private getFilename(): string; - private writeHeader(): Uint8Array; -} - -export class SymmetricallyEncryptedDataPacket extends BasePacket { - static readonly tag: enums.packet.symmetricallyEncryptedData; - private decrypt(sessionKeyAlgorithm: enums.symmetric, sessionKey: Uint8Array, config?: Config): void; - private encrypt(sessionKeyAlgorithm: enums.symmetric, sessionKey: Uint8Array, config?: Config): void; -} - -export class MarkerPacket extends BasePacket { - static readonly tag: enums.packet.marker; -} - -export class UserAttributePacket extends BasePacket { - static readonly tag: enums.packet.userAttribute; - private equals(packet: UserAttributePacket): boolean; -} - -export class OnePassSignaturePacket extends BasePacket { - static readonly tag: enums.packet.onePassSignature; - public correspondingSig?: Promise; - private verify: SignaturePacket['verify']; -} - -export class UserIDPacket extends BasePacket { - static readonly tag: enums.packet.userID; - public readonly name: string; - public readonly comment: string; - public readonly email: string; - public readonly userID: string; - static fromObject(userID: UserID): UserIDPacket; -} - -export class SignaturePacket extends BasePacket { - static readonly tag: enums.packet.signature; - public version: number; - public signatureType: enums.signature | null; - public hashAlgorithm: enums.hash | null; - public publicKeyAlgorithm: enums.publicKey | null; - public signatureData: null | Uint8Array; - public unhashedSubpackets: null | Uint8Array; - public signedHashValue: null | Uint8Array; - public created: Date | null; - public signatureExpirationTime: null | number; - public signatureNeverExpires: boolean; - public exportable: null | boolean; - public trustLevel: null | number; - public trustAmount: null | number; - public regularExpression: null | number; - public revocable: null | boolean; - public keyExpirationTime: null | number; - public keyNeverExpires: null | boolean; - public preferredSymmetricAlgorithms: enums.symmetric[] | null; - public revocationKeyClass: null | number; - public revocationKeyAlgorithm: null | enums.publicKey; - public revocationKeyFingerprint: null | Uint8Array; - public issuerKeyID: KeyID; - public notation: null | { [name: string]: string }; - public preferredHashAlgorithms: enums.hash[] | null; - public preferredCompressionAlgorithms: enums.compression[] | null; - public keyServerPreferences: null | number[]; - public preferredKeyServer: null | string; - public isPrimaryUserID: null | boolean; - public policyURI: null | string; - public keyFlags: Uint8Array | null; - public signersUserID: null | string; - public reasonForRevocationFlag: null | enums.reasonForRevocation; - public reasonForRevocationString: null | string; - public features: Uint8Array | null; - public signatureTargetPublicKeyAlgorithm: enums.publicKey | null; - public signatureTargetHashAlgorithm: enums.hash | null; - public signatureTargetHash: null | string; - public embeddedSignature: null | SignaturePacket; - public issuerKeyVersion: null | number; - public issuerFingerprint: null | Uint8Array; - public preferredAEADAlgorithms: enums.aead[] | null; - public revoked: null | boolean; - public sign(key: AnySecretKeyPacket, data: Uint8Array, date?: Date, detached?: boolean): Promise; - public verify(key: AnyKeyPacket, signatureType: enums.signature, data: string | object, date?: Date, detached?: boolean, config?: Config): Promise; // throws on error - public isExpired(date?: Date): boolean; - public getExpirationTime(): Date | typeof Infinity; -} - -export class TrustPacket extends BasePacket { - static readonly tag: enums.packet.trust; -} - -export type AnyPacket = BasePacket; -export type AnySecretKeyPacket = SecretKeyPacket | SecretSubkeyPacket; -export type AnyKeyPacket = BasePublicKeyPacket; - -type AllowedPackets = Map; // mapping to Packet classes (i.e. typeof LiteralDataPacket etc.) -export class PacketList extends Array { - static fromBinary(bytes: MaybeStream, allowedPackets: AllowedPackets, config?: Config): PacketList; // the packet types depend on`allowedPackets` - public read(bytes: MaybeStream, allowedPackets: AllowedPackets, config?: Config): void; - public write(): Uint8Array; - public filterByTag(...args: enums.packet[]): PacketList; - public indexOfTag(...tags: enums.packet[]): number[]; - public findPacket(tag: enums.packet): T | undefined; -} - -/* ############## v5 STREAM #################### */ - -type Data = Uint8Array | string; -interface BaseStream extends AsyncIterable { } -interface WebStream extends BaseStream { // copied+simplified version of ReadableStream from lib.dom.d.ts - readonly locked: boolean; getReader: Function; pipeThrough: Function; pipeTo: Function; tee: Function; - cancel(reason?: any): Promise; -} -interface NodeStream extends BaseStream { // copied+simplified version of ReadableStream from @types/node/index.d.ts - readable: boolean; pipe: Function; unpipe: Function; wrap: Function; - read(size?: number): string | Uint8Array; setEncoding(encoding: string): this; pause(): this; resume(): this; - isPaused(): boolean; unshift(chunk: string | Uint8Array): void; -} -type Stream = WebStream | NodeStream; -type MaybeStream = T | Stream; - -/* ############## v5 GENERAL #################### */ -type MaybeArray = T | Array; - -export interface UserID { name?: string; email?: string; comment?: string; } -export interface SessionKey { - data: Uint8Array; - algorithm: enums.symmetricNames; - aeadAlgorithm?: enums.aeadNames; -} - -export interface ReasonForRevocation { flag?: enums.reasonForRevocation, string?: string } - -interface EncryptOptions { - /** message to be encrypted as created by createMessage */ - message: Message>; - /** (optional) array of keys or single key, used to encrypt the message */ - encryptionKeys?: MaybeArray; - /** (optional) private keys for signing. If omitted message will not be signed */ - signingKeys?: MaybeArray; - /** (optional) array of passwords or a single password to encrypt the message */ - passwords?: MaybeArray; - /** (optional) session key */ - sessionKey?: SessionKey; - /** if the return values should be ascii armored or the message/signature objects */ - format?: 'armored' | 'binary' | 'object'; - /** (optional) if the signature should be detached (if true, signature will be added to returned object) */ - signature?: Signature; - /** (optional) encrypt as of a certain date */ - date?: Date; - /** (optional) use a key ID of 0 instead of the public key IDs */ - wildcard?: boolean; - /** (optional) Array of key IDs to use for signing. Each `signingKeyIDs[i]` corresponds to `signingKeys[i]` */ - signingKeyIDs?: MaybeArray; - /** (optional) Array of key IDs to use for encryption. Each `encryptionKeyIDs[i]` corresponds to `encryptionKeys[i]`*/ - encryptionKeyIDs?: MaybeArray; - /** (optional) Array of user IDs to sign with, e.g. { name:'Steve Sender', email:'steve@openpgp.org' } */ - signingUserIDs?: MaybeArray; - /** (optional) array of user IDs to encrypt for, e.g. { name:'Robert Receiver', email:'robert@openpgp.org' } */ - encryptionUserIDs?: MaybeArray; - config?: PartialConfig; -} - -interface DecryptOptions { - /** the message object with the encrypted data */ - message: Message>; - /** (optional) private keys with decrypted secret key data or session key */ - decryptionKeys?: MaybeArray; - /** (optional) passwords to decrypt the message */ - passwords?: MaybeArray; - /** (optional) session keys in the form: { data:Uint8Array, algorithm:String } */ - sessionKeys?: MaybeArray; - /** (optional) array of public keys or single key, to verify signatures */ - verificationKeys?: MaybeArray; - /** (optional) whether data decryption should fail if the message is not signed with the provided publicKeys */ - expectSigned?: boolean; - /** (optional) whether to return data as a string(Stream) or Uint8Array(Stream). If 'utf8' (the default), also normalize newlines. */ - format?: 'utf8' | 'binary'; - /** (optional) detached signature for verification */ - signature?: Signature; - /** (optional) use the given date for verification instead of the current time */ - date?: Date; - config?: PartialConfig; -} - -interface SignOptions { - message: CleartextMessage | Message>; - signingKeys?: MaybeArray; - format?: 'armored' | 'binary' | 'object'; - detached?: boolean; - signingKeyIDs?: MaybeArray; - date?: Date; - signingUserIDs?: MaybeArray; - config?: PartialConfig; -} - -interface VerifyOptions { - /** (cleartext) message object with signatures */ - message: CleartextMessage | Message>; - /** array of publicKeys or single key, to verify signatures */ - verificationKeys: MaybeArray; - /** (optional) whether verification should throw if the message is not signed with the provided publicKeys */ - expectSigned?: boolean; - /** (optional) whether to return data as a string(Stream) or Uint8Array(Stream). If 'utf8' (the default), also normalize newlines. */ - format?: 'utf8' | 'binary'; - /** (optional) detached signature for verification */ - signature?: Signature; - /** (optional) use the given date for verification instead of the current time */ - date?: Date; - config?: PartialConfig; -} - - -interface SerializedKeyPair { - privateKey: T; - publicKey: T; -} -interface KeyPair { - privateKey: PrivateKey; - publicKey: PublicKey; -} - -export type EllipticCurveName = 'ed25519' | 'curve25519' | 'p256' | 'p384' | 'p521' | 'secp256k1' | 'brainpoolP256r1' | 'brainpoolP384r1' | 'brainpoolP512r1'; - -interface KeyOptions { - userIDs: MaybeArray; - passphrase?: string; - type?: 'ecc' | 'rsa'; - curve?: EllipticCurveName; - rsaBits?: number; - keyExpirationTime?: number; - date?: Date; - subkeys?: SubkeyOptions[]; - format?: 'armored' | 'object' | 'binary'; - config?: PartialConfig; -} - -interface SubkeyOptions { - type?: 'ecc' | 'rsa'; - curve?: EllipticCurveName; - rsaBits?: number; - keyExpirationTime?: number; - date?: Date; - sign?: boolean; - config?: PartialConfig; -} - -export class KeyID { - bytes: string; - equals(keyID: KeyID, matchWildcard?: boolean): boolean; - toHex(): string; - static fromID(hex: string): KeyID; -} - -interface DecryptMessageResult { - data: MaybeStream; - signatures: VerificationResult[]; - filename: string; -} - -interface VerifyMessageResult { - data: MaybeStream; - signatures: VerificationResult[]; -} - - -/** - * Armor an OpenPGP binary packet block - */ -export function armor(messagetype: enums.armor, body: object, partindex: number, parttotal: number, config?: Config): string; - -/** - * DeArmor an OpenPGP armored message; verify the checksum and return the encoded bytes - */ -export function unarmor(input: string, config?: Config): Promise<{ text: string, data: Stream, type: enums.armor }>; - -/* ############## v5 ENUMS #################### */ - -export namespace enums { - function read(type: typeof armor, e: armor): armorNames; - function read(type: typeof compression, e: compression): compressionNames; - function read(type: typeof hash, e: hash): hashNames; - function read(type: typeof packet, e: packet): packetNames; - function read(type: typeof publicKey, e: publicKey): publicKeyNames; - function read(type: typeof symmetric, e: symmetric): symmetricNames; - function read(type: typeof keyStatus, e: keyStatus): keyStatusNames; - function read(type: typeof keyFlags, e: keyFlags): keyFlagsNames; - - export type armorNames = 'multipartSection' | 'multipartLast' | 'signed' | 'message' | 'publicKey' | 'privateKey'; - enum armor { - multipartSection = 0, - multipartLast = 1, - signed = 2, - message = 3, - publicKey = 4, - privateKey = 5, - signature = 6, - } - - enum reasonForRevocation { - noReason = 0, // No reason specified (key revocations or cert revocations) - keySuperseded = 1, // Key is superseded (key revocations) - keyCompromised = 2, // Key material has been compromised (key revocations) - keyRetired = 3, // Key is retired and no longer used (key revocations) - userIDInvalid = 32, // User ID information is no longer valid (cert revocations) - } - - export type compressionNames = 'uncompressed' | 'zip' | 'zlib' | 'bzip2'; - enum compression { - uncompressed = 0, - zip = 1, - zlib = 2, - bzip2 = 3, - } - - export type hashNames = 'md5' | 'sha1' | 'ripemd' | 'sha256' | 'sha384' | 'sha512' | 'sha224'; - enum hash { - md5 = 1, - sha1 = 2, - ripemd = 3, - sha256 = 8, - sha384 = 9, - sha512 = 10, - sha224 = 11, - } - - export type packetNames = 'publicKeyEncryptedSessionKey' | 'signature' | 'symEncryptedSessionKey' | 'onePassSignature' | 'secretKey' | 'publicKey' - | 'secretSubkey' | 'compressed' | 'symmetricallyEncrypted' | 'marker' | 'literal' | 'trust' | 'userID' | 'publicSubkey' | 'userAttribute' - | 'symEncryptedIntegrityProtected' | 'modificationDetectionCode' | 'AEADEncryptedDataPacket'; - enum packet { - publicKeyEncryptedSessionKey = 1, - signature = 2, - symEncryptedSessionKey = 3, - onePassSignature = 4, - secretKey = 5, - publicKey = 6, - secretSubkey = 7, - compressedData = 8, - symmetricallyEncryptedData = 9, - marker = 10, - literalData = 11, - trust = 12, - userID = 13, - publicSubkey = 14, - userAttribute = 17, - symEncryptedIntegrityProtectedData = 18, - modificationDetectionCode = 19, - aeadEncryptedData = 20, - } - - export type publicKeyNames = 'rsaEncryptSign' | 'rsaEncrypt' | 'rsaSign' | 'elgamal' | 'dsa' | 'ecdh' | 'ecdsa' | 'eddsa' | 'aedh' | 'aedsa'; - enum publicKey { - rsaEncryptSign = 1, - rsaEncrypt = 2, - rsaSign = 3, - elgamal = 16, - dsa = 17, - ecdh = 18, - ecdsa = 19, - eddsa = 22, - aedh = 23, - aedsa = 24, - } - - enum curve { - p256 = 'p256', - p384 = 'p384', - p521 = 'p521', - ed25519 = 'ed25519', - curve25519 = 'curve25519', - secp256k1 = 'secp256k1', - brainpoolP256r1 = 'brainpoolP256r1', - brainpoolP384r1 = 'brainpoolP384r1', - brainpoolP512r1 = 'brainpoolP512r1' - } - - export type symmetricNames = 'plaintext' | 'idea' | 'tripledes' | 'cast5' | 'blowfish' | 'aes128' | 'aes192' | 'aes256' | 'twofish'; - enum symmetric { - plaintext = 0, - idea = 1, - tripledes = 2, - cast5 = 3, - blowfish = 4, - aes128 = 7, - aes192 = 8, - aes256 = 9, - twofish = 10, - } - - export type keyStatusNames = 'invalid' | 'expired' | 'revoked' | 'valid' | 'noSelfCert'; - enum keyStatus { - invalid = 0, - expired = 1, - revoked = 2, - valid = 3, - noSelfCert = 4, - } - - export type keyFlagsNames = 'certifyKeys' | 'signData' | 'encryptCommunication' | 'encryptStorage' | 'splitPrivateKey' | 'authentication' - | 'sharedPrivateKey'; - enum keyFlags { - certifyKeys = 1, - signData = 2, - encryptCommunication = 4, - encryptStorage = 8, - splitPrivateKey = 16, - authentication = 32, - sharedPrivateKey = 128, - } - - enum signature { - binary = 0, - text = 1, - standalone = 2, - certGeneric = 16, - certPersona = 17, - certCasual = 18, - certPositive = 19, - certRevocation = 48, - subkeyBinding = 24, - keyBinding = 25, - key = 31, - keyRevocation = 32, - subkeyRevocation = 40, - timestamp = 64, - thirdParty = 80 - } - - export type aeadNames = 'eax' | 'ocb' | 'gcm'; - enum aead { - eax = 1, - ocb = 2, - experimentalGCM = 100 // Private algorithm - } - - export type literalFormatNames = 'utf8' | 'binary' | 'text' | 'mime' - enum literal { - binary = 98, - text = 116, - utf8 = 117, - mime = 109 - } -} - -// -----BEGIN ADDED BY FLOWCRYPT----- -export function readToEnd(input: MaybeStream, concat?: (list: T[]) => T): Promise; -// -----END ADDED BY FLOWCRYPT----- From bc2c18648bd20f63a331673699fb56048d1b4cd8 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 13 Feb 2022 22:04:10 +0200 Subject: [PATCH 175/179] fix path --- Core/webpack.bare.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/webpack.bare.config.js b/Core/webpack.bare.config.js index e40fff6f4..79897c270 100644 --- a/Core/webpack.bare.config.js +++ b/Core/webpack.bare.config.js @@ -16,6 +16,6 @@ module.exports = { }, externals: { openpgp: 'openpgp', - '../../bundles/raw/web-stream-tools': '../..bundles/raw/web-stream-tools' + '../../bundles/raw/web-stream-tools': '../../bundles/raw/web-stream-tools' } } From 18f006a5957a8e93b1ceed756f7fd077ef86996a Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Sun, 13 Feb 2022 22:04:35 +0200 Subject: [PATCH 176/179] remove reference to .d.ts --- Core/source/core/pgp-msg.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/Core/source/core/pgp-msg.ts b/Core/source/core/pgp-msg.ts index 4056542a3..c8ab73879 100644 --- a/Core/source/core/pgp-msg.ts +++ b/Core/source/core/pgp-msg.ts @@ -1,7 +1,5 @@ /* © 2016-present FlowCrypt a. s. Limitations apply. Contact human@flowcrypt.com */ -/// - - 'use strict'; import { KeyInfo, PgpKey, PrvKeyInfo } from './pgp-key'; From 8cb4f80fc357dc6eee46c93108cf056019dbe161 Mon Sep 17 00:00:00 2001 From: tomholub Date: Sun, 13 Feb 2022 22:38:26 +0100 Subject: [PATCH 177/179] added todos --- Core/source/core/pgp-key.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index 68b378748..aef23dd06 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -372,8 +372,7 @@ export class PgpKey { const data = { userID: user.userID, userAttribute: user.userAttribute, key: key }; for (const selfCert of user.selfCertifications) { try { - // todo - add proper type in openpgp.d.ts - await selfCert.verify(key.keyPacket, enums.signature.certGeneric, data as any); // quick hack + await selfCert.verify(key.keyPacket, enums.signature.certGeneric, data as any); // todo https://github.com/FlowCrypt/flowcrypt-ios/issues/1377 allSignatures.push(selfCert); } catch (e) { console.log(`PgpKey.lastSig: Skipping self-certification signature because it is invalid: ${String(e)}`); @@ -400,8 +399,7 @@ export class PgpKey { } public static revoke = async (key: Key): Promise => { - // todo - quick hack to pass tests - if (!key.isRevoked(undefined as any as SignaturePacket)) { + if (!key.isRevoked(undefined as any as SignaturePacket)) { // todo - https://github.com/FlowCrypt/flowcrypt-ios/issues/1377 if (!key.isPrivate()) throw Error('Revocation of public key not implemented'); const keypair = await revokeKey({ key: key as PrivateKey, format: 'object' }); key = keypair.privateKey; From bab071d83e03b8bd1d9b88bc1efac96e7dcbe533 Mon Sep 17 00:00:00 2001 From: Ivan Pizhenko Date: Tue, 15 Feb 2022 18:36:50 +0200 Subject: [PATCH 178/179] use Math.max() in the lastSig() --- Core/source/core/pgp-key.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Core/source/core/pgp-key.ts b/Core/source/core/pgp-key.ts index 68b378748..7e5b32f3e 100644 --- a/Core/source/core/pgp-key.ts +++ b/Core/source/core/pgp-key.ts @@ -390,11 +390,7 @@ export class PgpKey { } } if (allSignatures.length > 0) { - allSignatures.sort((a, b) => { - return (b.created ? b.created.getTime() : 0) - (a.created ? a.created.getTime() : 0); - }); - const newestSig = allSignatures[0]; - return newestSig.created ? newestSig.created.getTime() : 0; + return Math.max(...allSignatures.map(x => x.created ? x.created.getTime() : 0)); } throw new Error('No valid signature found in key'); } From d06f77d9cf4506a6d65edcf38fb4f2eb0443aa84 Mon Sep 17 00:00:00 2001 From: Roma Sosnovsky Date: Thu, 17 Feb 2022 23:38:15 +0200 Subject: [PATCH 179/179] disable test video reporter --- appium/config/wdio.shared.conf.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/appium/config/wdio.shared.conf.js b/appium/config/wdio.shared.conf.js index cc556a9cf..3612418e7 100644 --- a/appium/config/wdio.shared.conf.js +++ b/appium/config/wdio.shared.conf.js @@ -31,12 +31,12 @@ exports.config = { return `wdio-${options.cid}.xml` } }], - [video, { - saveAllVideos: false, // If true, also saves videos for successful test cases - videoSlowdownMultiplier: 3, // Higher to get slower videos, lower for faster videos [Value 1-100] - videoRenderTimeout: 10, // Max seconds to wait for a video to finish rendering - outputDir: './video', - }] + // [video, { + // saveAllVideos: false, // If true, also saves videos for successful test cases + // videoSlowdownMultiplier: 3, // Higher to get slower videos, lower for faster videos [Value 1-100] + // videoRenderTimeout: 10, // Max seconds to wait for a video to finish rendering + // outputDir: './video', + // }] ], services: [ ['appium', {